berkeley-abc-1.01+20161002hgeb6eca6+dfsg/000077500000000000000000000000001300674244400172455ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/CMakeLists.txt000066400000000000000000000071661300674244400220170ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.3.0) include(CMakeParseArguments) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) 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() # run make to extract compiler options, linker options and list of source files execute_process( COMMAND 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() add_executable(abc ${ABC_SRC}) abc_properties(abc PRIVATE) list(REMOVE_ITEM ABC_SRC src/base/main/main.c) add_library(libabc EXCLUDE_FROM_ALL ${ABC_SRC}) abc_properties(libabc PUBLIC) set_property(TARGET libabc PROPERTY OUTPUT_NAME abc) 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) berkeley-abc-1.01+20161002hgeb6eca6+dfsg/Makefile000066400000000000000000000133701300674244400207110ustar00rootroot00000000000000 CC := gcc CXX := g++ LD := $(CXX) MSG_PREFIX ?= $(info $(MSG_PREFIX)Using CC=$(CC)) $(info $(MSG_PREFIX)Using CXX=$(CXX)) $(info $(MSG_PREFIX)Using LD=$(LD)) PROG := abc 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/bac src/base/cba src/base/pla src/base/test \ src/map/mapper src/map/mio src/map/super src/map/if \ src/map/amap src/map/cov src/map/scl src/map/mpm \ src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \ 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/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/sfm \ src/sat/bsat src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc \ 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) arch_flags.c -o $(ARCHFLAGS_EXE) INCLUDES += -Isrc ARCHFLAGS ?= $(shell $(CC) arch_flags.c -o $(ARCHFLAGS_EXE) && $(ARCHFLAGS_EXE)) 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++ comipler and put everything in the namespace $(ABC_NAMESPACE) ifdef ABC_USE_NAMESPACE CFLAGS += -DABC_NAMESPACE=$(ABC_USE_NAMESPACE) -fpermissive 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) $(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),) $(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 endif endif # LIBS := -ldl -lrt LIBS += -ldl -lm ifneq ($(findstring Darwin, $(shell uname)), Darwin) LIBS += -lrt endif $(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS)) CXXFLAGS += $(CFLAGS) SRC := GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags .PHONY: all default tags clean docs cmake_info include $(patsubst %, %/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))) DEP := $(OBJ:.o=.d) # implicit rules %.o: %.c @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CC) -c $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< -o $@ %.o: %.cc @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ %.o: %.cpp @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ %.d: %.c @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)./depends.sh $(CC) `dirname $*.c` $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $*.c > $@ %.d: %.cc @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)./depends.sh $(CXX) `dirname $*.cc` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $*.cc > $@ %.d: %.cpp @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)./depends.sh $(CXX) `dirname $*.cpp` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $*.cpp > $@ 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 $(OBJ) $(GARBAGE) $(OBJ:.o=.d) tags: etags `find . -type f -regex '.*\.\(c\|h\)'` $(PROG): $(OBJ) @echo "$(MSG_PREFIX)\`\` Building binary:" $(notdir $@) $(VERBOSE)$(LD) -o $@ $^ $(LIBS) lib$(PROG).a: $(OBJ) @echo "$(MSG_PREFIX)\`\` Linking:" $(notdir $@) $(VERBOSE)ar rv $@ $? $(VERBOSE)ranlib $@ 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/abc.rc000066400000000000000000000114021300674244400203160ustar00rootroot00000000000000# 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 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" # 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" berkeley-abc-1.01+20161002hgeb6eca6+dfsg/abcexe.dsp000066400000000000000000000113241300674244400212050ustar00rootroot00000000000000# 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 # Begin Source File SOURCE=.\src\proof\ssw\sswSat.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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/abclib.dsp000066400000000000000000003070461300674244400212030ustar00rootroot00000000000000# 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\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\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\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\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\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\ioWriteEqn.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteGml.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\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\wlcBlast.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcCom.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcNtk.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\wlcSim.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcStdin.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\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 # 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\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\extraBddMisc.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\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\bmcBmci.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\bmcMaxi.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 # 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 "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\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\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 # 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\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\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\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\extraUtilMemory.c # End Source File # Begin Source File SOURCE=.\src\misc\extra\extraUtilMisc.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\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\utilFile.c # 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\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\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\giaCSatOld.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaCTas.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\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\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\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\giaMuxes.c # 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\giaPf.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaQbf.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaResub.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\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\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\giaSim.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSim2.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\giaStr.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSupMin.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\giaUtil.c # End Source File # End Group # Begin Group "miniaig" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\aig\miniaig\miniaig.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\kit_.c # 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\cecSeq.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecSolve.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\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\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\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\acecOrder.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\acecRe.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecUtil.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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/abcspace.dsw000066400000000000000000000014511300674244400215260ustar00rootroot00000000000000Microsoft 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> {{{ }}} ############################################################################### berkeley-abc-1.01+20161002hgeb6eca6+dfsg/arch_flags.c000066400000000000000000000005431300674244400215040ustar00rootroot00000000000000#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; } berkeley-abc-1.01+20161002hgeb6eca6+dfsg/copyright.txt000066400000000000000000000022001300674244400220100ustar00rootroot00000000000000ABC: 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. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/depends.sh000077500000000000000000000003311300674244400212230ustar00rootroot00000000000000#!/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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/i10.aig000066400000000000000000000345501300674244400203270ustar00rootroot00000000000000aig 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/lib/000077500000000000000000000000001300674244400200135ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/lib/pthread.h000066400000000000000000001243071300674244400216220ustar00rootroot00000000000000/* 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 */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/lib/sched.h000066400000000000000000000113541300674244400212560ustar00rootroot00000000000000/* * 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 */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/lib/semaphore.h000066400000000000000000000105151300674244400221510ustar00rootroot00000000000000/* * 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 */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/readme.md000066400000000000000000000117401300674244400210270ustar00rootroot00000000000000# ABC: System for Sequential Logic Synthesis and Formal Verification ABC is always changing but the current snapshot is believed to be stable. ## 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.cc and libabc.a to the working directory * Run `gcc -Wall -g -c demo.c -o demo.o` * Run `gcc -g -o demo demo.o libabc.a -lm -ldl -rdynamic -lreadline -ltermcap -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. ## Bug reporting: Please try to reproduce all the reported bugs and unexpected features using the latest version of ABC available from https://bitbucket.org/alanmi/abc/ If the bug still persists, please provide the following information: 1. ABC version (when it was downloaded from BitBucket) 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 This file was last modified on June 18, 2014 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/readmeaig000066400000000000000000000064531300674244400211160ustar00rootroot00000000000000Using 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. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/000077500000000000000000000000001300674244400200345ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/000077500000000000000000000000001300674244400205745ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/000077500000000000000000000000001300674244400213345ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aig.h000066400000000000000000001346711300674244400222610ustar00rootroot00000000000000/**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 (1 << (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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigCanon.c000066400000000000000000000504021300674244400232200ustar00rootroot00000000000000/**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), 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigCuts.c000066400000000000000000000456171300674244400231140ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigDfs.c000066400000000000000000001022601300674244400226760ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigDoms.c000066400000000000000000000767551300674244400231070ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigDup.c000066400000000000000000001265641300674244400227270ustar00rootroot00000000000000/**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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigFact.c000066400000000000000000000566211300674244400230500ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigFanout.c000066400000000000000000000137441300674244400234260ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigFrames.c000066400000000000000000000125721300674244400234050ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigInter.c000066400000000000000000000211751300674244400232500ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigJust.c000066400000000000000000000236241300674244400231150ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigMan.c000066400000000000000000000341301300674244400226750ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigMem.c000066400000000000000000000423351300674244400227060ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigMffc.c000066400000000000000000000237731300674244400230500ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigObj.c000066400000000000000000000415541300674244400227040ustar00rootroot00000000000000/**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; 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigOper.c000066400000000000000000000461311300674244400230730ustar00rootroot00000000000000/**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 && vNodes1->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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigOrder.c000066400000000000000000000117051300674244400232400ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigPack.c000066400000000000000000000255101300674244400230420ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigPart.c000066400000000000000000001450021300674244400230710ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigPartReg.c000066400000000000000000000475161300674244400235420ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigPartSat.c000066400000000000000000000501071300674244400235420ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigRepar.c000066400000000000000000000316031300674244400232350ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigRepr.c000066400000000000000000000401631300674244400230750ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigRet.c000066400000000000000000001027231300674244400227200ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigRetF.c000066400000000000000000000152251300674244400230260ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigScl.c000066400000000000000000000547121300674244400227130ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigShow.c000066400000000000000000000316141300674244400231060ustar00rootroot00000000000000/**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" 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 ); static int Counter = 0; char FileNameDot[200]; FILE * pFile; // create the file name // Aig_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 Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); // visualize the file Abc_ShowFile( FileNameDot ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigSplit.c000066400000000000000000000243371300674244400232650ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigTable.c000066400000000000000000000203651300674244400232160ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigTest.c000066400000000000000000000012511300674244400230770ustar00rootroot00000000000000 #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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigTiming.c000066400000000000000000000257161300674244400234230ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigTruth.c000066400000000000000000000070701300674244400232730ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigTsim.c000066400000000000000000000377231300674244400231110ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigUtil.c000066400000000000000000001374341300674244400231120ustar00rootroot00000000000000/**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[20]; // 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 ) { static unsigned int m_z = NUMBER1; static unsigned int m_w = NUMBER2; 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 ); // 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aigWin.c000066400000000000000000000137251300674244400227260ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/aig_.c000066400000000000000000000026331300674244400224030ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/aig/module.make000066400000000000000000000014251300674244400234620ustar00rootroot00000000000000SRC += 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.cberkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/000077500000000000000000000000001300674244400213345ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/gia.c000066400000000000000000000026401300674244400222420ustar00rootroot00000000000000/**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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/gia.h000066400000000000000000003350521300674244400222550ustar00rootroot00000000000000/**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_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) int * pHTable; // hash table int nHTable; // hash table size int fAddStrash; // performs additional structural hashing int fSweeper; // sweeper is running int fGiaSimple; // simple mode (no const-propagation and strashing) 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 * 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 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_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 iPatsPi; Vec_Wrd_t * vSims; Vec_Wrd_t * vSimsPi; Vec_Int_t * vClassOld; Vec_Int_t * vClassNew; // 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 }; 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; 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 fCnfObjIds; int fAddOrCla; int fPureAig; int fDoAverage; int fCutHashing; int fCutSimple; 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; float 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_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 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_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_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_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_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 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_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_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_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 void Gia_ObjSetTravIdCurrentId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); p->pTravIds[Id] = p->nTravIds; } static inline int Gia_ObjIsTravIdCurrentId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); return (p->pTravIds[Id] == p->nTravIds); } 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; } 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; } 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 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); pObj->fCompl0 = Abc_LitIsCompl(iLit0); pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); pObj->fCompl1 = Abc_LitIsCompl(iLit1); } else { pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); pObj->fCompl1 = Abc_LitIsCompl(iLit0); pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); pObj->fCompl0 = Abc_LitIsCompl(iLit1); } 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)); } return Gia_ObjId( p, pObj ) << 1; } 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_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 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); pObj->fCompl0 = Abc_LitIsCompl(iLit0); pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); pObj->fCompl1 = Abc_LitIsCompl(iLit1); } else { pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); pObj->fCompl1 = Abc_LitIsCompl(iLit0); pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); pObj->fCompl0 = Abc_LitIsCompl(iLit1); } 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( !p->pHTable || !Abc_LitIsCompl(iLit1) ); if ( Abc_Lit2Var(iLit0) < Abc_Lit2Var(iLit1) ) { pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); pObj->fCompl0 = Abc_LitIsCompl(iLit0); pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); pObj->fCompl1 = Abc_LitIsCompl(iLit1); p->pMuxes[Gia_ObjId(p, pObj)] = iLitC; } else { pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); pObj->fCompl1 = Abc_LitIsCompl(iLit0); pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); pObj->fCompl0 = Abc_LitIsCompl(iLit1); 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 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_ManForEachClassReverse( p, i ) \ for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsHead(p, i) ) {} else #define Gia_ClassForEachObj( p, i, iObj ) \ for ( assert(Gia_ObjIsHead(p, i)), iObj = i; iObj; iObj = Gia_ObjNext(p, iObj) ) #define Gia_ClassForEachObj1( p, i, iObj ) \ for ( assert(Gia_ObjIsHead(p, i)), iObj = Gia_ObjNext(p, i); iObj; 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++ ) 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_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_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++ ) //////////////////////////////////////////////////////////////////////// /// 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 ); 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 ============================================================*/ extern Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); /*=== 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 ); /*=== 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_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_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 ); 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_ManDupWithAttributes( Gia_Man_t * p ); 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_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_ManDupBlock( Gia_Man_t * p, int nBlock ); extern Gia_Man_t * Gia_ManDupExist( 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_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_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_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl ); extern Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int fGiaSimple, int fVerbose ); extern Gia_Man_t * Gia_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_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 ); /*=== 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 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 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 ); /*=== 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 ); /*=== 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 ); /*=== 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 ); /*=== 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 ); /*=== giaMini.c ===========================================================*/ extern Gia_Man_t * Gia_ManReadMiniAig( char * pFileName ); extern void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ); /*=== 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 ); /*=== 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 ); /*=== 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 ); /*=== 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 ); /*=== 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_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 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 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 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 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 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_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ); 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 ); /*=== 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 ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaAgi.c000066400000000000000000000237641300674244400226750ustar00rootroot00000000000000/**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_RO) == 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaAig.c000066400000000000000000000533101300674244400226630ustar00rootroot00000000000000/**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 "proof/fra/fra.h" #include "proof/dch/dch.h" #include "opt/dar/dar.h" 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 [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) ); 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 [] ***********************************************************************/ Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars ) { Gia_Man_t * pGia; Aig_Man_t * pNew; if ( p->pManTime && p->vLevels == NULL ) Gia_ManLevelWithBoxes( p ); pNew = Gia_ManToAig( p, 0 ); pNew = Dar_ManChoiceNew( pNew, (Dch_Pars_t *)pPars ); // pGia = Gia_ManFromAig( pNew ); pGia = Gia_ManFromAigChoices( pNew ); Aig_ManStop( pNew ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaAig.h000066400000000000000000000064051300674244400226730ustar00rootroot00000000000000/**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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaAiger.c000066400000000000000000001540011300674244400232110ustar00rootroot00000000000000/**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_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 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, 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, 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, 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, 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, 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, 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') ) { 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, 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, 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, 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, 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, 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; Vec_Int_t * vFlopMap, * vGateMap, * vObjMap; vFlopMap = pNew->vFlopClasses; pNew->vFlopClasses = NULL; vGateMap = pNew->vGateClasses; pNew->vGateClasses = NULL; vObjMap = pNew->vObjClasses; pNew->vObjClasses = NULL; pManTime = (Tim_Man_t *)pNew->pManTime; pNew->pManTime = NULL; 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->vFlopClasses = vFlopMap; pNew->vGateClasses = vGateMap; pNew->vObjClasses = vObjMap; pNew->pManTime = pManTime; } 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; pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 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 ); } 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_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact ) { 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->vNamesIn = pInit->vNamesIn; pInit->vNamesIn = NULL; p->vNamesOut = pInit->vNamesOut; pInit->vNamesOut = NULL; p->nConstrs = pInit->nConstrs; pInit->nConstrs = 0; } 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) ); } // write the comment // fprintf( pFile, "c\n" ); 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 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 fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() ); fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); fclose( pFile ); if ( p != pInit ) { pInit->pManTime = p->pManTime; p->pManTime = NULL; pInit->vNamesIn = p->vNamesIn; p->vNamesIn = NULL; pInit->vNamesOut = p->vNamesOut; p->vNamesOut = NULL; Gia_ManStop( p ); } } /**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 ); } /**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 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaAigerExt.c000066400000000000000000000250711300674244400236760ustar00rootroot00000000000000/**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" 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, 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), 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 ); } /**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaBalAig.c000066400000000000000000001166071300674244400233130ustar00rootroot00000000000000/**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) > 10000 ) { 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) > 10000 ) { 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 ); // 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 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); pNew1 = Gia_ManBalanceInt( pNew, fStrict ); if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); Gia_ManStop( pNew ); pNew2 = Gia_ManDupNoMuxes( 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; // 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) : p; if ( fVerbose ) Gia_ManPrintStats( pNew0, NULL ); // derive internal manager pNew = fSimpleAnd ? Gia_ManDup( pNew0 ) : Gia_ManDupMuxes( pNew0, 2 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); if ( pNew0 != p ) Gia_ManStop( pNew0 ); // perform the operation pNew1 = Dam_ManAreaBalanceInt( pNew, vCiLevels, nNewNodesMax, fVerbose, fVeryVerbose ); if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); Gia_ManStop( pNew ); Vec_IntFreeP( &vCiLevels ); // derive the final result pNew2 = Gia_ManDupNoMuxes( pNew1 ); if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew1 ); // normalize if needed if ( !Gia_ManIsNormalized(pNew2) ) { pNew2 = Gia_ManDupNormalize( pNew1 = pNew2, 0 ); Gia_ManStop( pNew1 ); } Gia_ManTransferTiming( pNew2, p ); return pNew2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaBalLut.c000066400000000000000000001031131300674244400233430ustar00rootroot00000000000000/**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 ); if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew1 ); return pNew2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaBalMap.c000066400000000000000000000246201300674244400233210ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaBidec.c000066400000000000000000000264221300674244400231750ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaCCof.c000066400000000000000000000255171300674244400230050ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaCSat.c000066400000000000000000001052411300674244400230160ustar00rootroot00000000000000/**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 } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cbs_Man_t * Cbs_ManAlloc() { 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 ); 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)) ); } /**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 ) { 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, * 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 [] 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; } /**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 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(); 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 = 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 ) { 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaCSatOld.c000066400000000000000000000604041300674244400234560ustar00rootroot00000000000000/**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, * 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaCTas.c000066400000000000000000001633211300674244400230210ustar00rootroot00000000000000/**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, * 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 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaCTas2.c000066400000000000000000000205411300674244400230770ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaCex.c000066400000000000000000000343701300674244400227070ustar00rootroot00000000000000/**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" 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 ); // 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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaClp.c000066400000000000000000000327451300674244400227120ustar00rootroot00000000000000/**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 [] ***********************************************************************/ Vec_Ptr_t * Gia_GetFakeNames( int nNames ) { Vec_Ptr_t * vNames; char Buffer[5]; int i; vNames = Vec_PtrAlloc( nNames ); for ( i = 0; i < nNames; i++ ) { if ( nNames < 26 ) { Buffer[0] = 'a' + i; Buffer[1] = 0; } else { Buffer[0] = 'a' + i%26; Buffer[1] = '0' + i/26; Buffer[2] = 0; } Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); } return vNames; } /**Function************************************************************* Synopsis [] 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) ); Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p) ); char ** ppNamesCi = (char **)Vec_PtrArray( vNamesCi ); char ** ppNamesCo = (char **)Vec_PtrArray( vNamesCo ); Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1 ); 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 ); } #else Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) { return NULL; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaCof.c000066400000000000000000001037151300674244400226770ustar00rootroot00000000000000/**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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaCone.c000066400000000000000000000434271300674244400230570ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaConstr.c000066400000000000000000000027271300674244400234410ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaDfs.c000066400000000000000000000401771300674244400227060ustar00rootroot00000000000000/**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 [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 [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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaDup.c000066400000000000000000004177211300674244400227250ustar00rootroot00000000000000/**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" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// 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_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 [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOrderDfsReverse( 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_ManForEachCoReverse( p, pObj, i ) Gia_ManDupOrderDfs_rec( pNew, p, pObj ); Gia_ManForEachCi( p, pObj, i ) if ( !~pObj->Value ) pObj->Value = Gia_ManAppendCi(pNew); assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); 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_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 ); 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_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_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachPo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy( Gia_ManRi(p, Vec_IntEntry(vPermInv, i)) ) ); Vec_IntFree( vPermInv ); 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 [] ***********************************************************************/ 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 ( pNew->pHTable == NULL ) 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 ( pNew->pHTable == NULL ) 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; } /**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(p); 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 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 ( pNew->pHTable ) 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; } /**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; } /**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 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 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; } /**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 [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 [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 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 ); 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; } /**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 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 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, 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 (*)(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 ) { 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 ) 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 (*)(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; } /**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_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 (*)(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_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, * pPerm, Count1 = 0; Vec_Int_t * vXors, * vSizes, * vPart[2], * vOrder; Gia_Obj_t * pFan[2], * pObj = Gia_ManCo(p, 0); assert( Gia_ManCoNum(p) == 1 ); vXors = Vec_IntAlloc( 100 ); if ( Gia_ObjFaninC0(pObj) ) Gia_ManCollectTopXors_rec( p, Gia_ObjFanin0(pObj), vXors ); else Vec_IntPush( vXors, Gia_ObjId(p, Gia_ObjFanin0(pObj)) ); // order by support size 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 ); 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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaEdge.c000066400000000000000000001055541300674244400230370ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaEmbed.c000066400000000000000000001720401300674244400232010ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaEnable.c000066400000000000000000000514641300674244400233610ustar00rootroot00000000000000/**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, * 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaEquiv.c000066400000000000000000002260461300674244400232640ustar00rootroot00000000000000/**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 ) 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 [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 || 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 [] 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 ); assert( Gia_ManEquivCheckLits( p, nLits ) ); if ( fVerbose ) { // int Ent; Abc_Print( 1, "Const0 = " ); 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 [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 ) { 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; } /* 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 [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))) ) { 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++ ) 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 ) 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 ); 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 ); // 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 ); // 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 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaEra.c000066400000000000000000000464431300674244400227030ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaEra2.c000066400000000000000000001743431300674244400227660ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaEsop.c000066400000000000000000000424111300674244400230710ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaFalse.c000066400000000000000000000507711300674244400232250ustar00rootroot00000000000000/**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 ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaFanout.c000066400000000000000000000252451300674244400234250ustar00rootroot00000000000000/**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_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) ) { 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 [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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaForce.c000066400000000000000000001073351300674244400232300ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaFrames.c000066400000000000000000001006721300674244400234040ustar00rootroot00000000000000/**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, 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaFront.c000066400000000000000000000220371300674244400232550ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaFx.c000066400000000000000000000436411300674244400225460ustar00rootroot00000000000000/**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 ); 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 ); int Status = Kit_TruthIsop( (unsigned *)pTruth, nVars, vCover, 1 ); 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 ) return Gia_ManDup(p); // 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaGiarf.c000066400000000000000000001035541300674244400232210ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaGig.c000066400000000000000000000421261300674244400226740ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaGlitch.c000066400000000000000000000624521300674244400234040ustar00rootroot00000000000000/**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 unsigned uTruth[2]; // 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( pNode->uTruth, 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( pNode->uTruth, Phase ); } /**Function************************************************************* Synopsis [Creates node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gli_ManCreateNode( Gli_Man_t * p, Vec_Int_t * vFanins, int nFanouts, unsigned * puTruth ) { Gli_Obj_t * pObj, * pFanin; int i; assert( Vec_IntSize(vFanins) <= 6 ); pObj = Gli_ObjAlloc( p, Vec_IntSize(vFanins), nFanouts ); Gli_ManForEachEntry( vFanins, p, pFanin, i ) Gli_ObjAddFanin( pObj, pFanin ); pObj->uTruth[0] = puTruth[0]; pObj->uTruth[1] = puTruth[Vec_IntSize(vFanins) == 6]; 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 <= 6 ); 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( pNode->uTruth, 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( "\nSimulated %d patterns. ", nPatterns ); ABC_PRMn( "Memory", 4*p->nObjData ); ABC_PRT( "Time", Abc_Clock() - clk ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaHash.c000066400000000000000000000653501300674244400230550ustar00rootroot00000000000000/**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 ) { Gia_Obj_t * pThis; int * pPlace = p->pHTable + Gia_ManHashOne( iLit0, iLit1, iLitC, p->nHTable ); assert( p->pMuxes || iLit0 < iLit1 ); assert( iLit0 < iLit1 || (!Abc_LitIsCompl(iLit0) && !Abc_LitIsCompl(iLit1)) ); assert( iLitC == -1 || !Abc_LitIsCompl(iLit1) ); for ( pThis = (*pPlace)? Gia_ManObj(p, Abc_Lit2Var(*pPlace)) : NULL; pThis; pPlace = (int *)&pThis->Value, pThis = (*pPlace)? Gia_ManObj(p, Abc_Lit2Var(*pPlace)) : NULL ) if ( Gia_ObjFaninLit0p(p, pThis) == iLit0 && Gia_ObjFaninLit1p(p, pThis) == 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 *Gia_ManHashFind( p, iLit0, iLit1, -1 ); } 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( p->pHTable == NULL ); p->nHTable = Abc_PrimeCudd( Gia_ManAndNum(p) ? Gia_ManAndNum(p) + 1000 : p->nObjsAlloc ); p->pHTable = ABC_CALLOC( int, p->nHTable ); } /**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_ManCleanValue( 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 = Abc_Var2Lit( i, 0 ); } } /**Function************************************************************* Synopsis [Stops the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManHashStop( Gia_Man_t * p ) { ABC_FREE( p->pHTable ); p->nHTable = 0; } /**Function************************************************************* Synopsis [Resizes the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManHashResize( Gia_Man_t * p ) { Gia_Obj_t * pThis; int * pHTableOld, * pPlace; int nHTableOld, iNext, Counter, Counter2, i; assert( p->pHTable != NULL ); // replace the table pHTableOld = p->pHTable; nHTableOld = p->nHTable; p->nHTable = Abc_PrimeCudd( 2 * Gia_ManAndNum(p) ); p->pHTable = ABC_CALLOC( int, p->nHTable ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < nHTableOld; i++ ) for ( pThis = (pHTableOld[i]? Gia_ManObj(p, Abc_Lit2Var(pHTableOld[i])) : NULL), iNext = (pThis? pThis->Value : 0); pThis; pThis = (iNext? Gia_ManObj(p, Abc_Lit2Var(iNext)) : NULL), iNext = (pThis? pThis->Value : 0) ) { pThis->Value = 0; pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0p(p, pThis), Gia_ObjFaninLit1p(p, pThis), Gia_ObjFaninLit2p(p, pThis) ); assert( *pPlace == 0 ); // should not be there *pPlace = Abc_Var2Lit( Gia_ObjId(p, pThis), 0 ); assert( *pPlace != 0 ); Counter++; } Counter2 = Gia_ManAndNum(p) - Gia_ManBufNum(p); assert( Counter == Counter2 ); ABC_FREE( pHTableOld ); // if ( p->fVerbose ) // printf( "Resizing GIA hash table: %d -> %d.\n", nHTableOld, p->nHTable ); } /**Function******************************************************************** Synopsis [Profiles the hash table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Gia_ManHashProfile( Gia_Man_t * p ) { Gia_Obj_t * pEntry; int i, Counter, Limit; printf( "Table size = %d. Entries = %d. ", p->nHTable, Gia_ManAndNum(p) ); printf( "Hits = %d. Misses = %d.\n", (int)p->nHashHit, (int)p->nHashMiss ); Limit = Abc_MinInt( 1000, p->nHTable ); for ( i = 0; i < Limit; i++ ) { Counter = 0; for ( pEntry = (p->pHTable[i]? Gia_ManObj(p, Abc_Lit2Var(p->pHTable[i])) : NULL); pEntry; pEntry = (pEntry->Value? Gia_ManObj(p, Abc_Lit2Var(pEntry->Value)) : NULL) ) 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 * p->nHTable < 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_LitNotCond( *pPlace, fCompl ); } p->nHashMiss++; if ( p->nObjs < p->nObjsAlloc ) *pPlace = Gia_ManAppendXorReal( p, iLit0, iLit1 ); else { int iNode = Gia_ManAppendXorReal( p, iLit0, iLit1 ); pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); assert( *pPlace == 0 ); *pPlace = iNode; } return Abc_LitNotCond( *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_LitNotCond( *pPlace, fCompl ); } p->nHashMiss++; if ( p->nObjs < p->nObjsAlloc ) *pPlace = 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 = iNode; } return Abc_LitNotCond( *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( p->nHTable == 0 ); return Gia_ManAppendAnd( p, iLit0, iLit1 ); } if ( (p->nObjs & 0xFF) == 0 && 2 * p->nHTable < 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 *pPlace; } p->nHashMiss++; if ( p->nObjs < p->nObjsAlloc ) return *pPlace = Gia_ManAppendAnd( p, iLit0, iLit1 ); else { int iNode = Gia_ManAppendAnd( p, iLit0, iLit1 ); pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); assert( *pPlace == 0 ); return *pPlace = iNode; } } } 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 *pPlace; 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); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaHcd.c000066400000000000000000000524441300674244400226700ustar00rootroot00000000000000/**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 ); } 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaIf.c000066400000000000000000002636561300674244400225410ustar00rootroot00000000000000/**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 ); //////////////////////////////////////////////////////////////////////// /// 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 ) { 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; Gia_ManForEachLut( p, i ) { int Level = 0; (*pnCurLuts)++; (*pnCurEdges) += Gia_ObjLutSize(p, i); Gia_LutForEachFanin( p, i, iFan, k ) if ( Level < pLevels[iFan] ) Level = pLevels[iFan]; pLevels[i] = Level + 1; } *pnCurLevels = 0; Gia_ManForEachCo( p, pObj, k ) if ( *pnCurLevels < pLevels[Gia_ObjFaninId0p(p, pObj)] ) *pnCurLevels = pLevels[Gia_ObjFaninId0p(p, pObj)]; 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 ) { 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) ) { 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", p->pName ); fprintf( pTable, "\n" ); fprintf( pTable, "%s ", p->pName ); // fprintf( pTable, "%d ", Gia_ManCiNum(p) ); // fprintf( pTable, "%d ", Gia_ManCoNum(p) ); // fprintf( pTable, "%d ", Gia_ManAndNum(p) ); // fprintf( pTable, "%d ", Gia_ManPiNum(p) - Gia_ManBoxCiNum(p) - Gia_ManRegBoxNum(p) ); // fprintf( pTable, "%d ", Gia_ManPoNum(p) - Gia_ManBoxCoNum(p) - Gia_ManRegBoxNum(p) ); // fprintf( pTable, "%d ", Gia_ManClockDomainNum(p) ); fprintf( pTable, " " ); fprintf( pTable, "%d ", p->MappedDelay ); fprintf( pTable, "%d ", p->MappedArea ); fprintf( pTable, "%d ", nFanins ); fprintf( pTable, "%d ", LevelMax ); fprintf( pTable, "%d ", nLuts ); // fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) ); // fprintf( pTable, "%d ", Gia_ManNonRegBoxNum(p) ); clk = Abc_Clock(); } else { printf( "This part of the code is currently not used.\n" ); assert( 0 ); fprintf( pTable, " " ); fprintf( pTable, "%d ", nLuts ); fprintf( pTable, "%d ", LevelMax ); 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 [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; 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 ); 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 ); } // 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_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 [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 fCompl ) { If_Obj_t * pIfObj; 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 ^ fCompl ) Abc_TtSetBit( pArray, nTtBitNum + nPermBitNum ); // update count Vec_IntAddToEntry( vConfigs, 0, 1 ); } 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 ) { 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; 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 ); } // 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 ) 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->fDeriveLuts && pIfMan->pPars->fTruth) || pIfMan->pPars->fUseDsd || pIfMan->pPars->fUseTtPerm ) { 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, Abc_LitIsCompl(pIfObj->iCopy) ); } 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)) ); } 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: CO 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; 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 ) { 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) ); Vec_IntPush( p->vMapping, Gia_ObjLutSize(pGia, i) ); Gia_LutForEachFanin( pGia, i, iFan, k ) 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 ( 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; } if ( pGia->vNamesIn || pGia->vNamesOut ) { p->vNamesIn = pGia->vNamesIn; pGia->vNamesIn = NULL; p->vNamesOut = pGia->vNamesOut; pGia->vNamesOut = NULL; } if ( pGia->vConfigs || pGia->pCellStr ) { p->vConfigs = pGia->vConfigs; pGia->vConfigs = NULL; p->pCellStr = pGia->pCellStr; pGia->pCellStr = NULL; } if ( pGia->pManTime == NULL || p == pGia ) 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 [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; assert( pPars->pTimesArr == NULL ); assert( pPars->pTimesReq == NULL ); 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->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 ( 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 ( !If_ManPerformMapping( pIfMan ) ) { If_ManStop( pIfMan ); return NULL; } // 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_ManStop( pIfMan ); // 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_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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaIff.c000066400000000000000000000367511300674244400227010ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaIso.c000066400000000000000000001321771300674244400227260ustar00rootroot00000000000000/**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 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 (*)(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 (*)(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 (*)(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 ); // 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaIso2.c000066400000000000000000000700671300674244400230070ustar00rootroot00000000000000/**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 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 (*)(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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaIso3.c000066400000000000000000000114351300674244400230020ustar00rootroot00000000000000/**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 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaJf.c000066400000000000000000002024731300674244400225300ustar00rootroot00000000000000/**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 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; return 0; } float Jf_CutCompareArea( Jf_Cut_t * pOld, Jf_Cut_t * pNew ) { // float Epsilon = (float)0.001; // if ( pOld->Flow > pNew->Flow + Epsilon ) return 1; // if ( pOld->Flow < pNew->Flow - Epsilon ) return -1; if ( pOld->Flow != pNew->Flow ) return pOld->Flow - pNew->Flow; 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 ", p->CutCount[0] ); printf( "Merge = %lu ", p->CutCount[1] ); printf( "Eval = %lu ", p->CutCount[2] ); printf( "Cut = %lu ", 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 || (AreaBest == Area && 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 ", p->pPars->Delay ); printf( "Area =%9lu ", p->pPars->Area ); printf( "Edge =%9lu ", p->pPars->Edge ); if ( p->pPars->fGenCnf ) printf( "Cnf =%9lu ", 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaKf.c000066400000000000000000001344651300674244400225360ustar00rootroot00000000000000/**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 ABC_USE_PTHREADS #ifdef _WIN32 #include "../lib/pthread.h" #else #include #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 ", p->pPars->Delay ); printf( "Area =%9lu ", p->pPars->Area ); printf( "Edge =%9lu ", 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 ", p->pSett->CutCount[0] ); printf( "Merge = %lu ", p->pSett->CutCount[1] ); printf( "Eval = %lu ", p->pSett->CutCount[2] ); printf( "Cut = %lu ", 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaLf.c000066400000000000000000002631521300674244400225330ustar00rootroot00000000000000/**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 12 #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) 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; return 1; } 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 ) return -1; if ( pCut0->Flow > pCut1->Flow ) 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 ) 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 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]; } 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; } 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->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) ) { 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 ) Lf_CutSetForEachCut( nCutWords, pCutSet1, pCut1, k, nCuts1 ) Lf_CutSetForEachCut( nCutWords, pCutSet2, pCut2, n, nCuts2 ) { 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 ); } } else { int fIsXor = Gia_ObjIsXor(pObj); p->CutCount[0] += nCuts0 * nCuts1; Lf_CutSetForEachCut( nCutWords, pCutSet0, pCut0, i, nCuts0 ) Lf_CutSetForEachCut( nCutWords, pCutSet1, pCut1, k, nCuts1 ) { 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 )//&& !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 ", p->pPars->Delay ); printf( "Area =%9lu ", p->pPars->Area ); printf( "Edge =%9lu ", p->pPars->Edge ); printf( "LUT =%9lu ", p->pPars->Area+p->nInverters ); if ( Vec_FltSize(&p->vSwitches) ) printf( "Swt =%8.1f ", p->Switches ); if ( p->pPars->fUseMux7 ) printf( "Mux7 =%7lu ", 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 ) 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; // 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaMan.c000066400000000000000000000613151300674244400227020ustar00rootroot00000000000000/**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 "gia.h" #include "misc/tim/tim.h" #include "proof/abs/abs.h" #include "opt/dar/dar.h" #ifdef WIN32 #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// 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_IntFreeP( &p->vSwitching ); Vec_IntFreeP( &p->vSuper ); Vec_IntFreeP( &p->vStore ); Vec_IntFreeP( &p->vClassNew ); Vec_IntFreeP( &p->vClassOld ); Vec_WrdFreeP( &p->vSims ); Vec_WrdFreeP( &p->vSimsPi ); 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_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 ); Gia_ManStopP( &p->pAigExtra ); Vec_IntFree( p->vCis ); Vec_IntFree( p->vCos ); 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->pHTable ); 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) * p->nHTable * (p->pHTable != NULL); 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 ); 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 ); Gia_ManStop( pTemp ); pTemp = Gia_ManDupFlopClass( p, 2 ); Gia_AigerWrite( pTemp, "dom2.aig", 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_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) { extern float Gia_ManLevelAve( Gia_Man_t * p ); if ( pPars && pPars->fMiter ) { Gia_ManPrintStatsMiter( p, 0 ); return; } #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) ); #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, " (%.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 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 ( 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 ); if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) && Gia_ManLutSizeMax(p) <= 4 ) 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 ); } } /**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; 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 ) { 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 = 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, "Class %3d : Count = %6d (%7.2f %%) %s\n", 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) ); ABC_FREE( pLutClass ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaMem.c000066400000000000000000000415051300674244400227040ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaMf.c000066400000000000000000001761561300674244400225430ustar00rootroot00000000000000/**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" 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 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 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); } // 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)); } // 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) ); //Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, iFunc), 3 ); fComplLast = Abc_LitIsCompl( Mf_CutFunc(pCut) ); 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 ); } } // 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; 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 && truthId == Vec_IntSize(&p->vCnfSizes) ) Vec_IntPush( &p->vCnfSizes, Abc_Tt6CnfSize(t, pCutR->nLeaves) ); // 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 && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) Vec_IntPush( &p->vCnfSizes, Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) ); 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 && truthId == Vec_IntSize(&p->vCnfSizes) ) Vec_IntPush( &p->vCnfSizes, Abc_Tt6CnfSize(t, pCutR->nLeaves) ); 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 && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) Vec_IntPush( &p->vCnfSizes, Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) ); 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)) ); 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 ) 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 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 ) 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->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 ) { 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 || 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->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->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 ", p->pPars->Delay ); printf( "Area =%9lu ", p->pPars->Area ); printf( "Edge =%9lu ", p->pPars->Edge ); if ( p->pPars->fGenCnf ) printf( "CNF =%9lu ", 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( "\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_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 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_CutAreaDerefed(p, pCut) : Mf_CutFlow(p, pCut, &Time); if ( pCutBest == NULL || FlowBest > Flow || (FlowBest == Flow && 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 [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->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 ); 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 ) // 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 [] ***********************************************************************/ Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, 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->fVerbose = fVerbose; pNew = Mf_ManPerformMapping( pGia, pPars ); Gia_ManStopP( &pNew ); // Cnf_DataPrint( (Cnf_Dat_t *)pGia->pData, 1 ); return (Cnf_Dat_t*)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 = Mf_ManGenerateCnf( p, nLutSize, fCnfObjIds, fAddOrCla, 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaMffc.c000066400000000000000000000236441300674244400230450ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaMfs.c000066400000000000000000000437601300674244400227200ustar00rootroot00000000000000/**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" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) { word uTruth, 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_Wrd_t * vTruths; // mfs data Vec_Int_t * vArray; Vec_Int_t * vLeaves; 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, j, k, curCi, curCo, nBoxIns, nBoxOuts; int Id, iFan, nMfsVars, nBbIns = 0, nBbOuts = 0, Counter = 0; 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 ); vTruths = Vec_WrdStart( nMfsVars ); // 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( 6 ); Gia_ObjComputeTruthTableStart( p, 6 ); 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) <= 6 ); assert( Vec_IntSize(vLeaves) == Gia_ObjLutSize(p, Id) ); uTruth = *Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, Id), vLeaves ); Vec_WrdWriteEntry( vTruths, Counter, uTruth ); 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 ); } 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 ) { int iBbIn = 0, iBbOut = 0; Gia_ObjComputeTruthTableStart( p->pAigExtra, 6 ); curCi = nRealPis; curCo = 0; for ( k = 0; k < nBoxes; k++ ) { nBoxIns = Tim_ManBoxInputNum( pManTime, k ); nBoxOuts = Tim_ManBoxOutputNum( pManTime, k ); // collect truth table leaves Vec_IntClear( vLeaves ); for ( i = 0; i < nBoxIns; i++ ) Vec_IntPush( vLeaves, Gia_ObjId(p->pAigExtra, Gia_ManCi(p->pAigExtra, i)) ); // iterate through box outputs if ( !Tim_ManBoxIsBlack(pManTime, k) ) { 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) ); // box output in the extra manager pObjExtra = Gia_ManCo( p->pAigExtra, curCi - nRealPis + j ); // compute truth table if ( Gia_ObjFaninId0p(p->pAigExtra, pObjExtra) == 0 ) uTruth = 0; else if ( Gia_ObjIsCi(Gia_ObjFanin0(pObjExtra)) ) uTruth = uTruths6[Gia_ObjCioId(Gia_ObjFanin0(pObjExtra))]; else uTruth = *Gia_ObjComputeTruthTableCut( p->pAigExtra, Gia_ObjFanin0(pObjExtra), vLeaves ); uTruth = Gia_ObjFaninC0(pObjExtra) ? ~uTruth : uTruth; Vec_WrdWriteEntry( vTruths, Counter, uTruth ); //Dau_DsdPrintFromTruth( &uTruth, Vec_IntSize(vLeaves) ); // 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 ); } } 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_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) vArray = Vec_WecEntry( vFanins, nMfsVars - nBbIns + iBbIn++ ); 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; Gia_ObjComputeTruthTableStop( p->pAigExtra ); // verify counts assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); assert( curCi - nRealPis == Gia_ManCoNum(p->pAigExtra) ); assert( iBbIn == nBbIns ); assert( iBbOut == nBbOuts ); } // finalize Vec_IntFree( vLeaves ); return Sfm_NtkConstruct( vFanins, nBbOuts + nRealPis, nRealPos + nBbIns, vFixed, vEmpty, vTruths ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk ) { 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; 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 ); vGroupMap = Vec_IntStartFull( nMfsNodes ); // 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 ); 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 ); 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) ); iLitNew = Gia_ManFromIfLogicCreateLut( pNew, pTruth, vLeaves, vCover, vMapping, vMapping2 ); } else if ( Abc_LitIsCompl(iGroup) ) // internal CI { //Dau_DsdPrintFromTruth( pTruth, Vec_IntSize(vLeaves) ); iLitNew = Gia_ManAppendCi( pNew ); } else // internal CO { iLitNew = Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vLeaves, 0), pTruth[0] == ~uTruthVar) ); //printf("Group = %d. po = %d\n", iGroup>>1, iMfsId ); } 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 ); 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 ); // cleanup Vec_WecFree( vGroups ); Vec_IntFree( vMfsTopo ); Vec_IntFree( vGroupMap ); Vec_IntFree( vMfs2Gia ); 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; assert( Gia_ManRegNum(p) == 0 ); assert( p->vMapping != NULL ); if ( p->pManTime != NULL && p->pAigExtra == NULL ) { Abc_Print( 1, "Timing manager is given but there is no GIA of boxes.\n" ); return NULL; } // count fanouts nFaninMax = Gia_ManLutSizeMax( p ); if ( nFaninMax > 6 ) { Abc_Print( 1, "Currently \"&mfs\" cannot process the network containing nodes with more than 6 fanins.\n" ); return NULL; } // collect information pNtk = Gia_ManExtractMfs( p ); // perform optimization nNodes = Sfm_NtkPerform( pNtk, pPars ); if ( nNodes == 0 ) { 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 { pNew = Gia_ManInsertMfs( p, pNtk ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaMini.c000066400000000000000000000137111300674244400230600ustar00rootroot00000000000000/**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 "base/main/main.h" #include "aig/miniaig/miniaig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// 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 ) { Gia_Man_t * pGia, * pTemp; Vec_Int_t * vCopies; int i, iGiaLit, 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 ); Vec_IntPush( vCopies, iGiaLit ); } Gia_ManHashStop( pGia ); assert( Vec_IntSize(vCopies) == nNodes ); Vec_IntFree( vCopies ); Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); pGia = Gia_ManCleanup( pTemp = pGia ); 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" ); pGia = Gia_ManFromMiniAig( (Mini_Aig_t *)p ); Abc_FrameUpdateGia( pAbc, 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 [] ***********************************************************************/ Gia_Man_t * Gia_ManReadMiniAig( char * pFileName ) { Mini_Aig_t * p = Mini_AigLoad( pFileName ); Gia_Man_t * pGia = Gia_ManFromMiniAig( p ); ABC_FREE( pGia->pName ); pGia->pName = Extra_FileNameGeneric( pFileName ); Mini_AigStop( p ); return pGia; } void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ) { Mini_Aig_t * p = Gia_ManToMiniAig( pGia ); Mini_AigDump( p, pFileName ); Mini_AigStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaMuxes.c000066400000000000000000000717551300674244400233010ustar00rootroot00000000000000/**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/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 >= 1 ); // 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 [Derives GIA without MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; assert( p->pMuxes != NULL ); // 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 = 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 ); Gia_ManPrintStats( p, NULL ); Gia_ManPrintStats( pNew, NULL ); Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew ); // Gia_ManStop( pNew2 ); return pNew2; } /**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 ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaNf.c000066400000000000000000002724421300674244400225370ustar00rootroot00000000000000/**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" 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 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 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 < 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 && Abc_TtBitCount8[Nf_Int2Cfg(Entry).Phase] == Abc_TtBitCount8[Mat.Phase] ) 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 ); 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->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 ); 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 ) 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 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; Gia_ManForEachAnd( 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 Nf_ObjMergeOrder( p, i ); } /**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] ); 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 ( 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 ) { 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 && 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 && 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" ); } */ } void Nf_ManComputeMapping( Nf_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachAnd( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Nf_ObjPrepareBuf( p, pObj ); else Nf_ManCutMatch( p, i ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Nf_Mat_t * Nf_ObjMatchBest( Nf_Man_t * p, int i, int c ) { Nf_Mat_t * pD = Nf_ObjMatchD(p, i, c); Nf_Mat_t * pA = Nf_ObjMatchA(p, i, c); assert( pD->fBest != pA->fBest ); //assert( Nf_ObjMapRefNum(p, i, c) > 0 ); if ( pA->fBest ) return pA; if ( pD->fBest ) return pD; return NULL; } void Nf_ManSetOutputRequireds( Nf_Man_t * p, int fPropCompl ) { Gia_Obj_t * pObj; 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_ManForEachCo( 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 Gia_ManForEachCo( 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 ); //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]; 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_ManForEachAndReverse( 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; } // 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_ManForEachCiId( 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 || (pRes->F == pMb->F && 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 || (pRes->F == pMb->F && 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 Gia_ManForEachAnd( 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; } // 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; int Required; Nf_ManSetOutputRequireds( p, 1 ); Nf_ManResetMatches( p, p->Iter - p->pPars->nRounds ); Gia_ManForEachAndReverse( 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 ); Nf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), Nf_ObjRequired(p, i, 0) ); 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_ManForEachCiId( 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_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Gia_Man_t * pNew = NULL, * pCls; Nf_Man_t * p; int i, Id; if ( Gia_ManHasChoices(pGia) ) pPars->fCoarsen = 0; pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; p = Nf_StoCreate( pCls, pPars ); // 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_ManForEachCiId( p->pGia, Id, i ) Nf_ObjPrepareCi( p, Id, Scl_ConGetInArr(i) ); } else { Gia_ManForEachCiId( 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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaOf.c000066400000000000000000002123131300674244400225270ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaPack.c000066400000000000000000000160661300674244400230500ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaPat.c000066400000000000000000000110021300674244400226770ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaPf.c000066400000000000000000001457071300674244400225440ustar00rootroot00000000000000/**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 ", 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaProp.c000066400000000000000000000120121300674244400230750ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaQbf.c000066400000000000000000000600751300674244400227010ustar00rootroot00000000000000/**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" 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 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 }; extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// 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 fVerbose ) { Gia_Obj_t * pObj; Gia_Man_t * pTemp, * pNew; int i, iMiter, 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)) ); 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 [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 = Mf_ManGenerateCnf( pGia, 8, 0, 1, 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 = Mf_ManGenerateCnf( pGia, 8, 0, 1, 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 ); } /**Function************************************************************* Synopsis [Generate one SAT assignment of the problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Qbf_Man_t * Gia_QbfAlloc( Gia_Man_t * pGia, int nPars, int fVerbose ) { Qbf_Man_t * p; Cnf_Dat_t * pCnf; Gia_ObjFlipFaninC0( Gia_ManPo(pGia, 0) ); pCnf = Mf_ManGenerateCnf( pGia, 8, 0, 1, 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->vValues = Vec_IntAlloc( Gia_ManPiNum(pGia) ); p->vParMap = Vec_IntStartFull( nPars ); p->vLits = Vec_IntAlloc( nPars ); sat_solver_setnvars( p->pSatSyn, nPars ); Cnf_DataFree( pCnf ); return p; } void Gia_QbfFree( Qbf_Man_t * p ) { sat_solver_delete( p->pSatVer ); sat_solver_delete( p->pSatSyn ); 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 = Mf_ManGenerateCnf( pCof, 8, 0, 1, 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 = Mf_ManGenerateCnf( pCof, 8, 0, 1, 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; } /**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, 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 = %6d ", sat_solver_nvars(p->pSatSyn) ); printf( "Cla = %6d ", sat_solver_nclauses(p->pSatSyn) ); printf( "Conf = %6d ", 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 fVerbose ) { Qbf_Man_t * p = Gia_QbfAlloc( pGia, nPars, 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 = Gia_QbfAddCofactor( p, pCof ); Gia_ManStop( pCof ); if ( status == 0 ) { RetValue = 1; break; } // synthesize next assignment clk = Abc_Clock(); 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 ( 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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaResub.c000066400000000000000000000243471300674244400232530ustar00rootroot00000000000000/**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" 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; } static inline 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 [Perform resubstitution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaRetime.c000066400000000000000000000240471300674244400234150ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaRex.c000066400000000000000000000457441300674244400227350ustar00rootroot00000000000000/**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 ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSat.c000066400000000000000000000274731300674244400227250ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSatEdge.c000066400000000000000000000461341300674244400235050ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSatLE.c000066400000000000000000001201641300674244400231350ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSatLut.c000066400000000000000000001341261300674244400234040ustar00rootroot00000000000000/**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 "sat/bsat/satStore.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" #include "misc/vec/vecHsh.h" 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 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSatMap.c000066400000000000000000000476021300674244400233570ustar00rootroot00000000000000/**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 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 ) { 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaScl.c000066400000000000000000000214561300674244400227120ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaScript.c000066400000000000000000000630231300674244400234310ustar00rootroot00000000000000/**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 ) return p; // 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 ) return Gia_ManDup(p); // 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 ) return Gia_ManDup(p); //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[100], Comm2[100], Comm3[100], Comm4[100]; sprintf( Comm1, "&synch2 -K %d -C 500; &if -m%s -K %d -C %d; %s &save", nLutSize, fMinAve?"t":"", nLutSize, nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); sprintf( Comm2, "&dch -C 500; &if -m%s -K %d -C %d; %s &save", fMinAve?"t":"", nLutSize, nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); sprintf( Comm3, "&synch2 -K %d -C 500; &lf -m%s -E 5 -K %d -C %d; %s &save", nLutSize, fMinAve?"t":"", nLutSize, nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); sprintf( Comm4, "&dch -C 500; &lf -m%sk -E 5 -K %d -C %d; %s &save", fMinAve?"t":"", nLutSize, nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); // 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" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaShow.c000066400000000000000000000574571300674244400231230ustar00rootroot00000000000000/**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" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* Vec_Int_t * Gia_WriteDotAigMarks( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds ) { int i; Vec_Int_t * vMarks = Vec_IntStart( Gia_ManObjNum(p) ); for ( i = 0; i < Vec_IntSize(vHadds)/2; i++ ) { Vec_IntWriteEntry( vMarks, Vec_IntEntry(vHadds, 2*i+0), Abc_Var2Lit(i+1, 0) ); Vec_IntWriteEntry( vMarks, Vec_IntEntry(vHadds, 2*i+1), Abc_Var2Lit(i+1, 0) ); } for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ ) { Vec_IntWriteEntry( vMarks, Vec_IntEntry(vFadds, 5*i+3), Abc_Var2Lit(i+1, 1) ); Vec_IntWriteEntry( vMarks, Vec_IntEntry(vFadds, 5*i+4), Abc_Var2Lit(i+1, 1) ); } return vMarks; } int Gia_WriteDotAigLevel_rec( Gia_Man_t * p, Vec_Int_t * vMarks, Vec_Int_t * vFadds, Vec_Int_t * vHadds, int Id, Vec_Int_t * vLevel ) { int Level = Vec_IntEntry(vLevel, Id), Mark = Vec_IntEntry(vMarks, Id); if ( Level || Mark == -1 ) return Level; if ( Mark == 0 ) { Gia_Obj_t * pObj = Gia_ManObj( p, Id ); int Level0 = Gia_WriteDotAigLevel_rec( p, vMarks, vFadds, vHadds, Gia_ObjFaninId0(pObj, Id), vLevel ); int Level1 = Gia_WriteDotAigLevel_rec( p, vMarks, vFadds, vHadds, Gia_ObjFaninId1(pObj, Id), vLevel ); Level = Abc_MaxInt(Level0, Level1) + 1; Vec_IntWriteEntry( vLevel, Id, Level ); Vec_IntWriteEntry( vMarks, Id, -1 ); } else if ( Abc_LitIsCompl(Mark) ) // FA { int i, * pFanins = Vec_IntEntryP( vFadds, 5*(Abc_Lit2Var(Mark)-1) ); assert( pFanins[3] == Id || pFanins[4] == Id ); for ( i = 0; i < 3; i++ ) Level = Abc_MaxInt( Level, Gia_WriteDotAigLevel_rec( p, vMarks, vFadds, vHadds, pFanins[i], vLevel ) ); Vec_IntWriteEntry( vLevel, pFanins[3], Level+1 ); Vec_IntWriteEntry( vLevel, pFanins[4], Level+1 ); } else // HA { int * pFanins = Vec_IntEntryP( vHadds, 2*(Abc_Lit2Var(Mark)-1) ); Gia_Obj_t * pObj = Gia_ManObj( p, pFanins[1] ); int Level0 = Gia_WriteDotAigLevel_rec( p, vMarks, vFadds, vHadds, Gia_ObjFaninId0(pObj, Id), vLevel ); int Level1 = Gia_WriteDotAigLevel_rec( p, vMarks, vFadds, vHadds, Gia_ObjFaninId1(pObj, Id), vLevel ); assert( pFanins[0] == Id || pFanins[1] == Id ); Level = Abc_MaxInt(Level0, Level1) + 1; Vec_IntWriteEntry( vLevel, pFanins[0], Level ); Vec_IntWriteEntry( vLevel, pFanins[1], Level ); } return Level; } int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds, Vec_Int_t ** pvMarks, Vec_Int_t ** pvLevel ) { Vec_Int_t * vMarks = Gia_WriteDotAigMarks( p, vFadds, vHadds ); Vec_Int_t * vLevel = Vec_IntStart( Gia_ManObjNum(p) ); int i, Id, Level = 0; Vec_IntWriteEntry( vMarks, 0, -1 ); Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( vMarks, Id, -1 ); Gia_ManForEachCoDriverId( p, Id, i ) Level = Abc_MaxInt( Level, Gia_WriteDotAigLevel_rec(p, vMarks, vFadds, vHadds, Id, vLevel) ); Gia_ManForEachCoId( p, Id, i ) Vec_IntWriteEntry( vMarks, Id, -1 ); *pvMarks = vMarks; *pvLevel = vLevel; return Level; } */ int Gia_WriteDotAigLevel( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vHadds, Vec_Int_t * vRecord, Vec_Int_t ** pvLevel, Vec_Int_t ** pvMarks, Vec_Int_t ** pvRemap, Vec_Int_t ** pvRemap2 ) { Vec_Int_t * vLevel = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vMarks = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vRemap = Vec_IntStartNatural( Gia_ManObjNum(p) ); Vec_Int_t * vRemap2 = Vec_IntStartNatural( Gia_ManObjNum(p) ); int i, k, Id, Entry, LevelMax = 0; Vec_IntWriteEntry( vMarks, 0, -1 ); Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( vMarks, Id, -1 ); Gia_ManForEachCoId( p, Id, i ) Vec_IntWriteEntry( vMarks, Id, -1 ); Vec_IntForEachEntry( vRecord, Entry, i ) { int Level = 0; int Node = Abc_Lit2Var2(Entry); int Attr = Abc_Lit2Att2(Entry); if ( Attr == 2 ) { int * pFanins = Vec_IntEntryP( vFadds, 5*Node ); for ( k = 0; k < 3; k++ ) Level = Abc_MaxInt( Level, Vec_IntEntry(vLevel, pFanins[k]) ); Vec_IntWriteEntry( vLevel, pFanins[3], Level+1 ); Vec_IntWriteEntry( vLevel, pFanins[4], Level+1 ); Vec_IntWriteEntry( vMarks, pFanins[4], Entry ); Vec_IntWriteEntry( vRemap, pFanins[3], pFanins[4] ); Vec_IntWriteEntry( vRemap2, pFanins[4], pFanins[3] ); //printf( "Making FA output %d.\n", pFanins[4] ); } else if ( Attr == 1 ) { int * pFanins = Vec_IntEntryP( vHadds, 2*Node ); Gia_Obj_t * pObj = Gia_ManObj( p, pFanins[1] ); int pFaninsIn[2] = { Gia_ObjFaninId0(pObj, pFanins[1]), Gia_ObjFaninId1(pObj, pFanins[1]) }; for ( k = 0; k < 2; k++ ) Level = Abc_MaxInt( Level, Vec_IntEntry(vLevel, pFaninsIn[k]) ); Vec_IntWriteEntry( vLevel, pFanins[0], Level+1 ); Vec_IntWriteEntry( vLevel, pFanins[1], Level+1 ); Vec_IntWriteEntry( vMarks, pFanins[1], Entry ); Vec_IntWriteEntry( vRemap, pFanins[0], pFanins[1] ); Vec_IntWriteEntry( vRemap2, pFanins[1], pFanins[0] ); //printf( "Making HA output %d %d.\n", pFanins[0], pFanins[1] ); } else // if ( Attr == 3 || Attr == 0 ) { Gia_Obj_t * pObj = Gia_ManObj( p, Node ); int pFaninsIn[2] = { Gia_ObjFaninId0(pObj, Node), Gia_ObjFaninId1(pObj, Node) }; for ( k = 0; k < 2; k++ ) Level = Abc_MaxInt( Level, Vec_IntEntry(vLevel, pFaninsIn[k]) ); Vec_IntWriteEntry( vLevel, Node, Level+1 ); Vec_IntWriteEntry( vMarks, Node, -1 ); //printf( "Making node %d.\n", Node ); } LevelMax = Abc_MaxInt( LevelMax, Level+1 ); } *pvLevel = vLevel; *pvMarks = vMarks; *pvRemap = vRemap; *pvRemap2 = vRemap2; return LevelMax; } /**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_WriteDotAig( Gia_Man_t * pMan, char * pFileName, Vec_Int_t * vBold, int fAdders ) { Vec_Int_t * vFadds = NULL, * vHadds = NULL, * vRecord = NULL, * vMarks = NULL, * vRemap = NULL, * vRemap2 = NULL; FILE * pFile; Gia_Obj_t * pNode;//, * pTemp, * pPrev; int LevelMax, Prev, Level, i; int fConstIsUsed = 0; if ( Gia_ManAndNum(pMan) > 1000 ) { fprintf( stdout, "Cannot visualize AIG with more than 1000 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 ) Gia_ManForEachObjVec( vBold, pMan, pNode, i ) pNode->fMark0 = 1; else if ( pMan->nXors || pMan->nMuxes ) Gia_ManForEachObj( pMan, pNode, i ) if ( Gia_ObjIsXor(pNode) || Gia_ObjIsMux(pMan, pNode) ) pNode->fMark0 = 1; // compute levels if ( fAdders ) { Vec_IntFreeP( &pMan->vLevels ); vFadds = Gia_ManDetectFullAdders( pMan, 0, NULL ); vHadds = Gia_ManDetectHalfAdders( pMan, 0 ); vRecord = Gia_PolynFindOrder( pMan, vFadds, vHadds, 0, 0 ); LevelMax = 1 + Gia_WriteDotAigLevel( pMan, vFadds, vHadds, vRecord, &pMan->vLevels, &vMarks, &vRemap, &vRemap2 ); } else LevelMax = 1 + Gia_ManLevelNum( pMan ); // set output levels Gia_ManForEachCo( pMan, pNode, i ) Vec_IntWriteEntry( pMan->vLevels, Gia_ObjId(pMan, pNode), 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.", Gia_ManAndNum(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 Gia_ManForEachCo( pMan, pNode, i ) { if ( Gia_ObjFaninId0p(pMan, 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(pMan, pNode), Gia_ObjId(pMan, 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( pMan, pNode, i ) { if ( vMarks && Vec_IntEntry(vMarks, i) == 0 ) continue; if ( (int)Gia_ObjLevel(pMan, 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)? "\'":"" ); */ if ( vMarks && Vec_IntEntry(vMarks, i) > 0 ) { fprintf( pFile, " Node%d [label = \"%d_%d\"", i, Vec_IntEntry(vRemap2, i), i ); if ( Abc_Lit2Att2(Vec_IntEntry(vMarks, i)) == 2 ) fprintf( pFile, ", shape = doubleoctagon" ); else fprintf( pFile, ", shape = octagon" ); } else if ( Gia_ObjIsXor(pNode) ) { fprintf( pFile, " Node%d [label = \"%d\"", i, i ); fprintf( pFile, ", shape = doublecircle" ); } else if ( Gia_ObjIsMux(pMan, pNode) ) { fprintf( pFile, " Node%d [label = \"%d\"", i, i ); fprintf( pFile, ", shape = trapezium" ); } else { fprintf( pFile, " Node%d [label = \"%d\"", i, i ); 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 || pMan->fGiaSimple ) { // 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( pMan, 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(pMan, pNode), Gia_ObjId(pMan, 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( pMan, pNode, i ) fprintf( pFile, "title2 -> Node%d [style = invis];\n", Gia_ObjId(pMan, pNode) ); // generate invisible edges among the COs Prev = -1; Gia_ManForEachCo( pMan, pNode, i ) { if ( i > 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(pMan, pNode) ); Prev = Gia_ObjId(pMan, pNode); } // generate edges Gia_ManForEachObj( pMan, pNode, i ) { if ( !Gia_ObjIsAnd(pNode) && !Gia_ObjIsCo(pNode) && !Gia_ObjIsBuf(pNode) ) continue; if ( vMarks && Vec_IntEntry(vMarks, i) == 0 ) continue; // consider half/full-adder if ( vMarks && Vec_IntEntry(vMarks, i) > 0 ) { int k, Mark = Vec_IntEntry(vMarks, i); if ( Abc_Lit2Att2(Mark) == 2 ) // FA { int * pFanins = Vec_IntEntryP( vFadds, 5*Abc_Lit2Var2(Mark) ); if ( pFanins[3] == i ) continue; assert( pFanins[4] == i ); // generate the edge from this node to the next for ( k = 0; k < 3; k++ ) { fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Vec_IntEntry(vRemap, pFanins[k]) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", "bold" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } } else // HA { int * pFanins = Vec_IntEntryP( vHadds, 2*Abc_Lit2Var2(Mark) ); int pFaninsIn[2] = { Vec_IntEntry(vRemap, Gia_ObjFaninId0(pNode, i)), Vec_IntEntry(vRemap, Gia_ObjFaninId1(pNode, i)) }; if ( pFanins[0] == i ) continue; assert( pFanins[1] == i ); for ( k = 0; k < 2; k++ ) { fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Vec_IntEntry(vRemap, pFaninsIn[k]) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", "bold" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } } continue; } // generate the edge from this node to the next fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", vRemap ? Vec_IntEntry(vRemap, Gia_ObjFaninId0(pNode, i)) : Gia_ObjFaninId0(pNode, i) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC0(pNode)? "dotted" : "bold" ); // if ( Gia_NtkIsSeq(pNode->pMan) && 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", vRemap ? Vec_IntEntry(vRemap, Gia_ObjFaninId1(pNode, i)) : Gia_ObjFaninId1(pNode, i) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC1(pNode)? "dotted" : "bold" ); // if ( Gia_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) // fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); if ( !Gia_ObjIsMux(pMan, pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", vRemap ? Vec_IntEntry(vRemap, Gia_ObjFaninId2(pMan, i)) : Gia_ObjFaninId2(pMan, i) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC2(pMan, pNode)? "dotted" : "bold" ); // if ( Gia_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 && 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" : "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]", Gia_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); fprintf( pFile, ";\n" ); } */ } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); fclose( pFile ); // unmark nodes if ( vBold ) Gia_ManForEachObjVec( vBold, pMan, pNode, i ) pNode->fMark0 = 0; else if ( pMan->nXors || pMan->nMuxes ) Gia_ManCleanMark0( pMan ); Vec_IntFreeP( &vFadds ); Vec_IntFreeP( &vHadds ); Vec_IntFreeP( &vRecord ); Vec_IntFreeP( &pMan->vLevels ); Vec_IntFreeP( &vMarks ); Vec_IntFreeP( &vRemap ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders ) { extern void Abc_ShowFile( char * FileNameDot ); static int Counter = 0; char FileNameDot[200]; FILE * pFile; // create the file name // Gia_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 Gia_WriteDotAig( pMan, FileNameDot, vBold, fAdders ); // visualize the file Abc_ShowFile( FileNameDot ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaShrink.c000066400000000000000000000124661300674244400234300ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaShrink6.c000066400000000000000000000424421300674244400235130ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaShrink7.c000066400000000000000000000315031300674244400235100ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSim.c000066400000000000000000000537021300674244400227200ustar00rootroot00000000000000/**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 /// //////////////////////////////////////////////////////////////////////// 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 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSim2.c000066400000000000000000000464221300674244400230030ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSort.c000066400000000000000000000166121300674244400231160ustar00rootroot00000000000000/**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, 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSpeedup.c000066400000000000000000000663731300674244400236050ustar00rootroot00000000000000/**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 ); // 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSplit.c000066400000000000000000000454651300674244400232720ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaStg.c000066400000000000000000000404611300674244400227230ustar00rootroot00000000000000/**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, '-', 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<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), 1 + Gia_ManCoNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManMuxNum(p) ); 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[256], int nLimit ) { int fVerbose = 0; int Levels[256]; int nSize = Vec_IntSize(vSuper); int Prev = nSize, nLevels = 1; int i, k, iLit, iFanin, nSizeNew; word Mask; assert( nSize > 2 ); if ( nSize > 64 ) { for ( i = 0; i < 64; i++ ) Matrix[i] = 0; return 0; } // 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 ); 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; } 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[256]; int Limit = 256; Vec_Int_t * vSuper = pNew->vSuper; Vec_Int_t * vCosts = pNew->vStore; int * pSuper = Vec_IntArray(vSuper); int * pCost = Vec_IntArray(vCosts); int k, iLit, MatrixSize = 0; assert( Limit <= Vec_IntCap(vSuper) ); assert( Limit <= Vec_IntCap(vCosts) ); // 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); return; } if ( Vec_IntSize(vSuper) == 2 ) { pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); 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, Limit ); // 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, Limit ); 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 ); /* // 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 ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSupMin.c000066400000000000000000000114121300674244400233730ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSweep.c000066400000000000000000000670011300674244400232500ustar00rootroot00000000000000/**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 ); 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 ); 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) ); } 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSweeper.c000066400000000000000000001220251300674244400235750ustar00rootroot00000000000000/**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( pGia->pHTable != NULL ); 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 ( pGia->pHTable == NULL ) 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 ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaSwitch.c000066400000000000000000000626561300674244400234410ustar00rootroot00000000000000/**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; 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; 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_ManSwiComputeProbOne( 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 * 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)]; } 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaTim.c000066400000000000000000001071231300674244400227160ustar00rootroot00000000000000/**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 "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 ); // 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 [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; 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++; } } 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 ); assert( Tim_ManPoNum(pManTime) == Gia_ManCoNum(pNew) - nBBouts ); assert( 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, 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 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 ); } // 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaTis.c000066400000000000000000000152751300674244400227320ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaTruth.c000066400000000000000000000514161300674244400232760ustar00rootroot00000000000000/**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_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_ObjIsAnd(pObj) ) return; Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId0p(p, pObj), vTemp ); Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId1p(p, pObj), vTemp ); uTruth0 = Vec_WrdEntry( vTemp, Gia_ObjFanin0(pObj)->Value ); uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0; uTruth1 = Vec_WrdEntry( vTemp, Gia_ObjFanin1(pObj)->Value ); 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_LutForEachFanin( p, iObj, Fanin, i ) 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.] 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 ); } 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 ) { 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; assert( p->vTtMemory != NULL ); assert( Vec_IntSize(vLeaves) <= p->nTtVars ); // 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaTsim.c000066400000000000000000000565601300674244400231110ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/giaUtil.c000066400000000000000000001700501300674244400231010ustar00rootroot00000000000000/**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 ) { static unsigned int m_z = NUMBER1; static unsigned int m_w = NUMBER2; 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 [] ***********************************************************************/ 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; } 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++; 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 ); Gia_ObjRefFanin1Inc( p, pObj ); if ( Gia_ObjIsMuxId(p, i) ) Gia_ObjRefFanin2Inc( p, pObj ); } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjRefFanin0Inc( p, pObj ); } } /**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 [] ***********************************************************************/ 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 ); 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; *ppFan0 = Gia_ObjChild0(p0); *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 ) { 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; } /**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 ); 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 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 >= 0 ); return ConeSize1; } /**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) ) { pLuts[iLut].Type = 3; Gia_LutForEachFanin( p, i, iFan, k ) pLuts[iLut].pFans[k] = Gia_ManObj(p, iFan)->Value; pLuts[iLut].nFans = k; *(word *)pLuts[iLut].pTruth = Gia_LutComputeTruth6(p, i, vTruths); 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 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/gia/module.make000066400000000000000000000040651300674244400234650ustar00rootroot00000000000000SRC += 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/giaCTas.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/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/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/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/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/giaPf.c \ src/aig/gia/giaQbf.c \ src/aig/gia/giaResub.c \ src/aig/gia/giaRetime.c \ src/aig/gia/giaRex.c \ src/aig/gia/giaSatEdge.c \ src/aig/gia/giaSatLE.c \ src/aig/gia/giaSatLut.c \ src/aig/gia/giaSatMap.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/giaSim.c \ src/aig/gia/giaSim2.c \ src/aig/gia/giaSort.c \ src/aig/gia/giaSpeedup.c \ src/aig/gia/giaSplit.c \ src/aig/gia/giaStg.c \ src/aig/gia/giaStr.c \ src/aig/gia/giaSupMin.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/giaTruth.c \ src/aig/gia/giaTsim.c \ src/aig/gia/giaUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/000077500000000000000000000000001300674244400213625ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/cudd2.c000066400000000000000000000240521300674244400225320ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/cudd2.h000066400000000000000000000067421300674244400225450ustar00rootroot00000000000000/**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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hop.h000066400000000000000000000521261300674244400223270ustar00rootroot00000000000000/**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 ); 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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopBalance.c000066400000000000000000000332351300674244400235700ustar00rootroot00000000000000/**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 (*)(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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopCheck.c000066400000000000000000000067241300674244400232630ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopDfs.c000066400000000000000000000425711300674244400227620ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopMan.c000066400000000000000000000114071300674244400227530ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopMem.c000066400000000000000000000070061300674244400227560ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopObj.c000066400000000000000000000172321300674244400227540ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopOper.c000066400000000000000000000262151300674244400231500ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopTable.c000066400000000000000000000157051300674244400232740ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopTruth.c000066400000000000000000000222711300674244400233470ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hopUtil.c000066400000000000000000000453641300674244400231660ustar00rootroot00000000000000/**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 ) { 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 ( 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 ); if ( i < Vec_PtrSize(vSuper) - 1 ) fprintf( pFile, " ^ " ); } fprintf( pFile, "%s", (Level==0? "" : ")") ); return; } // MUX case if ( Hop_ObjIsMuxType(pObj) ) { if ( Hop_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) { fprintf( pFile, "%s", (Level==0? "" : "(") ); Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 ); fprintf( pFile, " ^ " ); Hop_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); fprintf( pFile, "%s", (Level==0? "" : ")") ); } else { pFaninC = Hop_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Hop_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); fprintf( pFile, " ? " ); Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin1, fCompl), vLevels, Level+1 ); fprintf( pFile, " : " ); Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 ); 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 ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/hop_.c000066400000000000000000000026651300674244400224640ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/hop/module.make000066400000000000000000000004011300674244400235010ustar00rootroot00000000000000SRC += 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ioa/000077500000000000000000000000001300674244400213445ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ioa/ioa.h000066400000000000000000000062041300674244400222670ustar00rootroot00000000000000/**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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ioa/ioaReadAig.c000066400000000000000000000351261300674244400235040ustar00rootroot00000000000000/**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_ALLOC( char, nFileSize ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ioa/ioaUtil.c000066400000000000000000000074271300674244400231300ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ioa/ioaWriteAig.c000066400000000000000000000516451300674244400237270ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ioa/module.make000066400000000000000000000001311300674244400234630ustar00rootroot00000000000000SRC += src/aig/ioa/ioaReadAig.c \ src/aig/ioa/ioaWriteAig.c \ src/aig/ioa/ioaUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/000077500000000000000000000000001300674244400214035ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/attr.h000066400000000000000000000267771300674244400225510ustar00rootroot00000000000000/**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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivy.h000066400000000000000000001034341300674244400223700ustar00rootroot00000000000000/**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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyBalance.c000066400000000000000000000342031300674244400236260ustar00rootroot00000000000000/**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 (*)(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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyCanon.c000066400000000000000000000115461300674244400233440ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyCheck.c000066400000000000000000000225001300674244400233130ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyCut.c000066400000000000000000000717641300674244400230510ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyCutTrav.c000066400000000000000000000346061300674244400237000ustar00rootroot00000000000000/**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, 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 (*)(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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyDfs.c000066400000000000000000000372551300674244400230270ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyDsd.c000066400000000000000000000632641300674244400230240ustar00rootroot00000000000000/**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; int nSupp, Count0, Count1, Count2, nVars, RetValue, fCompl, 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyFanout.c000066400000000000000000000225651300674244400235450ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyFastMap.c000066400000000000000000001367221300674244400236450ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyFraig.c000066400000000000000000003033061300674244400233340ustar00rootroot00000000000000/**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, 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, 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyHaig.c000066400000000000000000000417741300674244400231640ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyMan.c000066400000000000000000000425161300674244400230220ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyMem.c000066400000000000000000000071011300674244400230140ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyMulti.c000066400000000000000000000232241300674244400233740ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyMulti8.c000066400000000000000000000327051300674244400234700ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyObj.c000066400000000000000000000370671300674244400230260ustar00rootroot00000000000000/**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; 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyOper.c000066400000000000000000000224011300674244400232030ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyResyn.c000066400000000000000000000137241300674244400234060ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyRwr.c000066400000000000000000000526511300674244400230620ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyRwrAlg.c000066400000000000000000000322621300674244400235020ustar00rootroot00000000000000/**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 (*)(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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivySeq.c000066400000000000000000001076601300674244400230410ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyShow.c000066400000000000000000000310011300674244400232120ustar00rootroot00000000000000/**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 ); 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 ); } /**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyTable.c000066400000000000000000000174741300674244400233430ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivyUtil.c000066400000000000000000000645241300674244400232270ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/ivy_.c000066400000000000000000000026501300674244400225200ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/ivy/module.make000066400000000000000000000010631300674244400235270ustar00rootroot00000000000000SRC += 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/miniaig/000077500000000000000000000000001300674244400222115ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/miniaig/abcapis.h000066400000000000000000000061311300674244400237650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcapis.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Include this file in the external code calling ABC.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 29, 2012.] Revision [$Id: abcapis.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef MINI_AIG__abc_apis_h #define MINI_AIG__abc_apis_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // procedures to start and stop the ABC framework extern void Abc_Start(); extern void Abc_Stop(); // procedures to get the ABC framework (pAbc) and execute commands in it extern void * Abc_FrameGetGlobalFrame(); extern int Cmd_CommandExecute( void * pAbc, char * pCommandLine ); // procedures to input/output 'mini AIG' extern void Abc_NtkInputMiniAig( void * pAbc, void * pMiniAig ); extern void * Abc_NtkOutputMiniAig( void * pAbc ); extern void Abc_NtkSetFlopNum( void * pAbc, int nFlops ); // procedures to set CI/CO arrival/required times extern void Abc_NtkSetCiArrivalTime( void * pAbc, int iCi, float Rise, float Fall ); extern void Abc_NtkSetCoRequiredTime( void * pAbc, int iCo, float Rise, float Fall ); // procedure to set AND-gate delay to tech-independent synthesis and mapping extern void Abc_NtkSetAndGateDelay( void * pAbc, float Delay ); // procedures to return the mapped network extern int * Abc_NtkOutputMiniMapping( void * pAbc ); extern void Abc_NtkPrintMiniMapping( int * pArray ); // procedures to access verifization status and a counter-example extern int Abc_FrameReadProbStatus( void * pAbc ); extern void * Abc_FrameReadCex( void * pAbc ); #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/miniaig/miniaig.h000066400000000000000000000237251300674244400240100ustar00rootroot00000000000000/**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 ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// 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 ) { 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 ); return p->pArray[2*Id]; } static int Mini_AigNodeFanin1( Mini_Aig_t * p, int Id ) { assert( Id >= 0 && 2*Id < p->nSize ); return p->pArray[2*Id+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 void Mini_AigStop( Mini_Aig_t * p ) { MINI_AIG_FREE( p->pArray ); MINI_AIG_FREE( p ); } static void Mini_AigPrintStats( Mini_Aig_t * p ) { int i, nPis, nPos, nNodes; nPis = 0; Mini_AigForEachPi( p, i ) nPis++; nPos = 0; Mini_AigForEachPo( p, i ) nPos++; nNodes = 0; Mini_AigForEachAnd( p, i ) nNodes++; printf( "PI = %d. PO = %d. Node = %d.\n", nPis, nPos, nNodes ); } // 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 = fwrite( &p->nSize, sizeof(int), 1, pFile ); RetValue = fwrite( &p->nRegs, sizeof(int), 1, pFile ); RetValue = 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 = 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 = fread( &p->nRegs, sizeof(int), 1, pFile ); RetValue = 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 ); Mini_AigPush( p, Lit0, Lit1 ); 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 ); } // 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; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/miniaig/module.make000066400000000000000000000000101300674244400243240ustar00rootroot00000000000000SRC += berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/000077500000000000000000000000001300674244400215175ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/module.make000066400000000000000000000013411300674244400236420ustar00rootroot00000000000000SRC += 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saig.h000066400000000000000000000320201300674244400226100ustar00rootroot00000000000000/**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 ); 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 ); 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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigCone.c000066400000000000000000000127661300674244400234270ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigConstr.c000066400000000000000000000366351300674244400240140ustar00rootroot00000000000000/**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 (*)(void))Saig_ManDupCompare ); Vec_PtrSort( vCons, (int (*)(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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigConstr2.c000066400000000000000000001057431300674244400240730ustar00rootroot00000000000000/**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 ) { 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 ); Aig_ManSeqCleanup( pAigNew ); return pAigNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #include "saigUnfold2.c" ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigDual.c000066400000000000000000000211261300674244400234160ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigDup.c000066400000000000000000000475341300674244400232740ustar00rootroot00000000000000/**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 ) { 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 Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pAigNew ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigGlaCba.c000066400000000000000000000655221300674244400236520ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigGlaPba.c000066400000000000000000000443051300674244400236630ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigGlaPba2.c000066400000000000000000000416001300674244400237400ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigInd.c000066400000000000000000000344711300674244400232520ustar00rootroot00000000000000/**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 interations and added %d uniqueness constraints.\n", f+1, nConstrs ); else printf( "Completed %d interations.\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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigIoa.c000066400000000000000000000327471300674244400232540ustar00rootroot00000000000000/**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[16]; if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) sprintf( Buffer, "n%0*d", Abc_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); else if ( Saig_ObjIsPi(p, pObj) ) sprintf( Buffer, "pi%0*d", Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjCioId(pObj) ); else if ( Saig_ObjIsPo(p, pObj) ) sprintf( Buffer, "po%0*d", Abc_Base10Log(Saig_ManPoNum(p)), Aig_ObjCioId(pObj) ); else if ( Saig_ObjIsLo(p, pObj) ) sprintf( Buffer, "lo%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPiNum(p) ); else if ( Saig_ObjIsLi(p, pObj) ) sprintf( Buffer, "li%0*d", 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigIso.c000066400000000000000000000470441300674244400232720ustar00rootroot00000000000000/**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 (*)(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 (*)(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( "Devided %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 ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigIsoFast.c000066400000000000000000000254601300674244400241060ustar00rootroot00000000000000/**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 = { 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 (*)(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( "Devided %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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigIsoSlow.c000066400000000000000000001476141300674244400241430ustar00rootroot00000000000000/**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 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 (*)(void))Iso_ObjCompare ); Vec_PtrSort( p->vClasses, (int (*)(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 (*)(void))Iso_ObjCompareByData ); Vec_PtrSort( p->vTemp2, (int (*)(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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigMiter.c000066400000000000000000001222371300674244400236160ustar00rootroot00000000000000/**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( "Ouput 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigOutDec.c000066400000000000000000000161271300674244400237210ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigPhase.c000066400000000000000000001077461300674244400236060ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigRefSat.c000066400000000000000000001023531300674244400237170ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigRetFwd.c000066400000000000000000000172431300674244400237310ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigRetMin.c000066400000000000000000000536221300674244400237350ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigRetStep.c000066400000000000000000000163461300674244400241270ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigScl.c000066400000000000000000000064211300674244400232530ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigSimFast.c000066400000000000000000000371501300674244400241030ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigSimMv.c000066400000000000000000000741411300674244400235710ustar00rootroot00000000000000/**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( "Begining to saturate simulation after %d frames\n", f ); // find all flops that have at least one X value in the past and set them to X forever p->vXFlops = Saig_MvManFindXFlops( p ); } if ( f == 2 * nFramesSatur ) { if ( fVerbose ) printf( "Agressively saturating simulation after %d frames\n", f ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigSimSeq.c000066400000000000000000000404641300674244400237400ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigStrSim.c000066400000000000000000000723721300674244400237630ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigSwitch.c000066400000000000000000000406301300674244400237730ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigSynch.c000066400000000000000000000501351300674244400236170ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigTempor.c000066400000000000000000000206501300674244400240000ustar00rootroot00000000000000/**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 ); 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigTrans.c000066400000000000000000000342451300674244400236260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigTrans.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Dynamic simplication 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigUnfold2.c000066400000000000000000000420571300674244400240500ustar00rootroot00000000000000 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; } berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saigWnd.c000066400000000000000000000635231300674244400232700ustar00rootroot00000000000000/**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 (*)(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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/aig/saig/saig_.c000066400000000000000000000026471300674244400227560ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/000077500000000000000000000000001300674244400207465ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/000077500000000000000000000000001300674244400214735ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abc.h000066400000000000000000002542771300674244400224120ustar00rootroot00000000000000/**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 }; 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 void 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 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 ); /*=== 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_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 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 ); 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_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_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 ); extern ABC_DLL void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, 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_NtkCreateWithNode( char * pSop ); extern ABC_DLL void Abc_NtkDelete( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches ); extern ABC_DLL void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pFlopPermFile ); extern ABC_DLL void Abc_NtkUnpermute( Abc_Ntk_t * pNtk ); /*=== 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 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 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 ); extern ABC_DLL void Abc_NodeMffcConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); extern ABC_DLL int Abc_NodeDeref_rec( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeRef_rec( Abc_Obj_t * pNode ); /*=== abcRefactor.c ==========================================================*/ extern ABC_DLL int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); /*=== 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 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 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 ); 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 ); /*=== 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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcAig.c000066400000000000000000001407211300674244400230120ustar00rootroot00000000000000/**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 [] ***********************************************************************/ void 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 ); Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel ); } if ( fUpdateLevel ) { Abc_AigUpdateLevel_int( pMan ); if ( pMan->pNtkAig->vLevelsR ) Abc_AigUpdateLevelR_int( pMan ); } } /**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) ) { 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcBarBuf.c000066400000000000000000000454031300674244400234540ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcBlifMv.c000066400000000000000000001143461300674244400234750ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcCheck.c000066400000000000000000000720401300674244400233250ustar00rootroot00000000000000/**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) ) Abc_AigCheck( (Abc_Aig_t *)pNtk->pManFunc ); 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 (*)())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 (*)())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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcDfs.c000066400000000000000000001657041300674244400230360ustar00rootroot00000000000000/**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_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes ); else 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; } /**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcFanOrder.c000066400000000000000000000521641300674244400240150ustar00rootroot00000000000000/**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, 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, 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, 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, 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 (*)())Abc_NodeCompareCubes2 ); else Vec_PtrSort( vCubes, (int (*)())Abc_NodeCompareCubes1 ); Vec_StrGrow( vStore, Vec_PtrSize(vCubes) * (nVars + 3) ); pPivot = Vec_StrArray( vStore ); Vec_PtrForEachEntry( char *, vCubes, pCube, i ) { assert( pCube[nVars] == 0 ); pCube[nVars] = ' '; memcpy( pPivot, pCube, nVars + 3 ); pPivot += nVars + 3; } memcpy( pSop, Vec_StrArray(vStore), 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 ( !fCont21 && !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, 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcFanio.c000066400000000000000000000274101300674244400233450ustar00rootroot00000000000000/**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 [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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcFunc.c000066400000000000000000001166051300674244400232110ustar00rootroot00000000000000/**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 100000 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 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**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 { // 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; assert( Abc_NtkHasSop(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 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, nCubes0, nCubes1, fPhase; 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 ) { 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 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 ) { 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 ) ); } Vec_PtrFree( vNodes ); // create primary outputs Abc_NtkForEachCo( p, pNode, i ) Gia_ManAppendCo( pNew, Abc_ObjFanin0(pNode)->iTemp ); Gia_ManSetRegNum( pNew, Abc_NtkLatchNum(p) ); // 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) { extern void * Abc_FrameReadLibGen(); Abc_Obj_t * pNode; char * pSop; int i; assert( Abc_NtkHasMapping(pNtk) ); // update the functionality manager assert( pNtk->pManFunc == Abc_FrameReadLibGen() ); 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 [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); } if ( Abc_NtkHasMapping(pNtk) ) return Abc_NtkMapToSop(pNtk); if ( Abc_NtkHasBdd(pNtk) ) return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit); if ( Abc_NtkHasAig(pNtk) ) { if ( !Abc_NtkAigToBdd(pNtk) ) return 0; return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit); } 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) ) return 0; return Abc_NtkSopToAig(pNtk); } if ( Abc_NtkHasSop(pNtk) ) return Abc_NtkSopToAig(pNtk); assert( 0 ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcHie.c000066400000000000000000000722731300674244400230250ustar00rootroot00000000000000/**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(*)())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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcHieCec.c000066400000000000000000000542671300674244400234430ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcHieGia.c000066400000000000000000000525071300674244400234440ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcHieNew.c000066400000000000000000001717371300674244400235040ustar00rootroot00000000000000/**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(*)())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(*)())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; 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcInt.h000066400000000000000000000037051300674244400230510ustar00rootroot00000000000000/**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 /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcLatch.c000066400000000000000000000620721300674244400233470ustar00rootroot00000000000000/**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, * pLatch, * 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 ) { // remember current fanins of the PI Abc_NodeCollectFanouts( pObj, vNodes ); // create the latches for ( pFanin = pObj, k = 0; k < nLatches; k++, pFanin = pLatch ) { pLatch = Abc_NtkCreateLatch( pNtk ); Abc_ObjAddFanin( pLatch, pFanin ); Abc_LatchSetInitDc( pLatch ); // create the name of the new latch Abc_ObjAssignName( pLatch, Abc_ObjNameDummy("LL", i*nLatches + k, nDigits), NULL ); } // patch the PI fanouts 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 reencode %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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcLib.c000066400000000000000000000265631300674244400230270ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcMinBase.c000066400000000000000000000676421300674244400236420ustar00rootroot00000000000000/**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( 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; } /**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 (*)())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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcNames.c000066400000000000000000000635451300674244400233650ustar00rootroot00000000000000/**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), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareNames ); qsort( (void *)Vec_PtrArray(pNtk->vPos), Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareNames ); // if the comparison if combinational (latches as PIs/POs), order them too if ( fComb ) qsort( (void *)Vec_PtrArray(pNtk->vBoxes), Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *), (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), Vec_PtrSize(pNtkNew->vPis), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); qsort( (void *)Vec_PtrArray(pNtkNew->vPos), Vec_PtrSize(pNtkNew->vPos), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); // order CI/CO qsort( (void *)Vec_PtrArray(pNtkNew->vCis), Vec_PtrSize(pNtkNew->vCis), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); qsort( (void *)Vec_PtrArray(pNtkNew->vCos), Vec_PtrSize(pNtkNew->vCos), sizeof(Abc_Obj_t *), (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 ); } /**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcNetlist.c000066400000000000000000000434361300674244400237410ustar00rootroot00000000000000/**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 ) { if ( pObj->pCopy->pCopy ) // the net of the new object is already created continue; // create the new net pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcNtk.c000066400000000000000000002213701300674244400230460ustar00rootroot00000000000000/**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 ); } // 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 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 [Deletes the Ntk.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; void * pAttrMan; int TotalMemory, i; // 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 ); } // 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 ); 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 [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 ); printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" ); } else { 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_NtkReadFlopPerm( char * pFileName, int nFlops ) { char Buffer[1000]; FILE * pFile; Vec_Int_t * vFlops; int iFlop = -1; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return NULL; } vFlops = Vec_IntAlloc( nFlops ); while ( fgets( Buffer, 1000, pFile ) != NULL ) { if ( Buffer[0] == ' ' || Buffer[0] == '\r' || Buffer[0] == '\n' ) continue; iFlop = atoi( Buffer ); if ( iFlop < 0 || iFlop >= nFlops ) { printf( "Flop ID (%d) is out of range.\n", iFlop ); fclose( pFile ); Vec_IntFree( vFlops ); return NULL; } Vec_IntPush( vFlops, iFlop ); } fclose( pFile ); if ( Vec_IntSize(vFlops) != nFlops ) { printf( "The number of flops read in from file (%d) is different from the number of flops in the circuit (%d).\n", iFlop, nFlops ); Vec_IntFree( vFlops ); return NULL; } return vFlops; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pFlopPermFile ) { Abc_Obj_t * pTemp; Vec_Int_t * vInputs, * vOutputs, * vFlops, * vTemp; int i, k, Entry; // start permutation arrays if ( pFlopPermFile ) { vFlops = Abc_NtkReadFlopPerm( pFlopPermFile, Abc_NtkLatchNum(pNtk) ); if ( vFlops == NULL ) return; fInputs = 0; fOutputs = 0; fFlops = 0; } else vFlops = Vec_IntStartNatural( Abc_NtkLatchNum(pNtk) ); vInputs = Vec_IntStartNatural( Abc_NtkPiNum(pNtk) ); vOutputs = Vec_IntStartNatural( Abc_NtkPoNum(pNtk) ); // permute inputs if ( fInputs ) for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) { 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++ ) { 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++ ) { 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 ); } // 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), 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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcObj.c000066400000000000000000001017461300674244400230300ustar00rootroot00000000000000/**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; // 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcRefs.c000066400000000000000000000321371300674244400232120ustar00rootroot00000000000000/**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 ) { 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 ); // collect the internal node // printf( "%d ", pNode->Id ); } /**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 ) { 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 ); // reference it back Count2 = Abc_NodeRef_rec( pNode ); assert( Count1 == Count2 ); return Count1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcShow.c000066400000000000000000000323001300674244400232230ustar00rootroot00000000000000/**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 ); 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 ); } /**Function************************************************************* Synopsis [Visualizes BDD of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) { FILE * pFile; Vec_Ptr_t * vNamesIn; char FileNameDot[200]; char * pNameOut; 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); Cudd_DumpDot( (DdManager *)pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); Abc_NodeFreeNames( vNamesIn ); Abc_NtkCleanCopy( pNode->pNtk ); fclose( pFile ); // visualize the file Abc_ShowFile( FileNameDot ); } #else void Abc_NodeShowBdd( Abc_Obj_t * pNode ) {} #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 ); // stop the cut computation manager Abc_NtkManCutStop( p ); // visualize the file Abc_ShowFile( FileNameDot ); } /**Function************************************************************* Synopsis [Visualizes AIG with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse ) { 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 ); pNtk->nBarBufs = nBarBufs; Vec_PtrFree( vNodes ); // visualize the file Abc_ShowFile( FileNameDot ); Abc_NtkDelete( pNtk ); } /**Function************************************************************* Synopsis [Shows the given DOT file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ShowFile( char * FileNameDot ) { 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 ); RetValue = system( CommandDot ); 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 _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]; unlink( FileNameDot ); sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); if ( system( CommandPs ) == -1 ) { 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 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcSop.c000066400000000000000000001040051300674244400230460ustar00rootroot00000000000000/**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" 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, '-', 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; // 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 [] ***********************************************************************/ 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 [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; } // 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; } /**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 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'; } /* // create TT representation { extern void Bdc_ManDecomposeTest( unsigned uTruth, int nVars ); unsigned uTruth = 0; int nVarsAll = 4; assert( nVarsAll == 4 ); assert( nVars <= nVarsAll ); Vec_IntForEachEntry( vMints, Mint, i ) uTruth |= (1 << Mint); // uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24); uTruth = uTruth | (uTruth << 16); Bdc_ManDecomposeTest( uTruth, nVarsAll ); } */ Vec_IntFree( vMints ); return pSopCover; } /**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abcUtil.c000066400000000000000000002553761300674244400232440ustar00rootroot00000000000000/**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" #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 ) { 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 ); 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 = 1; 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, 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) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/abc_.c000066400000000000000000000026471300674244400225340ustar00rootroot00000000000000/**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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abc/module.make000066400000000000000000000011531300674244400236170ustar00rootroot00000000000000SRC += 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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/000077500000000000000000000000001300674244400216445ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abc.c000066400000000000000000054047131300674244400225530ustar00rootroot00000000000000/**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/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 "bool/rpo/rpo.h" #include "map/mpm/mpm.h" #include "opt/fret/fretime.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 ); 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_CommandTrace ( 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_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_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDetect ( 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_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_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_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_CommandTopmost ( 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_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_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_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_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_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_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_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_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_CommandAbc9Get ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Put ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Save ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Load ( 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_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_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_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_CommandAbc9Sim3 ( 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_CommandAbc9Balance ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BalanceLut ( 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_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_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_CommandAbc9If ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Iff ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9If2 ( 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_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_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 ); #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_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_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_CommandAbc9Bmc ( 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_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_CommandAbc9Polyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ATree ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Acec ( 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_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_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_CommandAbc9Test ( 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 ); //////////////////////////////////////////////////////////////////////// /// 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; } /**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(): Tranformation 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; } // 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", "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", "print_fanio", Abc_CommandPrintFanio, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); 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", "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", "collapse", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "satclp", Abc_CommandSatClp, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 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", "trace", Abc_CommandTrace, 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", "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", "rr", Abc_CommandRr, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "detect", Abc_CommandDetect, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "exact", Abc_CommandExact, 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, "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", "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", "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", "topmost", Abc_CommandTopmost, 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", "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", "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", "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, "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", "permute", Abc_CommandPermute, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "unpermute", Abc_CommandUnpermute, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "cubeenum", Abc_CommandCubeEnum, 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", "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", "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, "ABC9", "&get", Abc_CommandAbc9Get, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&put", Abc_CommandAbc9Put, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&save", Abc_CommandAbc9Save, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&load", Abc_CommandAbc9Load, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&r", 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", "&wlut", Abc_CommandAbc9WriteLut, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&ps", Abc_CommandAbc9Ps, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&pfan", Abc_CommandAbc9PFan, 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", "&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", "&trim", Abc_CommandAbc9Trim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dfs", Abc_CommandAbc9Dfs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim", Abc_CommandAbc9Sim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim3", Abc_CommandAbc9Sim3, 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", "&b", Abc_CommandAbc9Balance, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&blut", Abc_CommandAbc9BalanceLut, 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", "&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", "&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", "&if", Abc_CommandAbc9If, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&iff", Abc_CommandAbc9Iff, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&if2", Abc_CommandAbc9If2, 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", "&pack", Abc_CommandAbc9Pack, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&edge", Abc_CommandAbc9Edge, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satlut", Abc_CommandAbc9SatLut, 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 ); #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", "&iso", Abc_CommandAbc9Iso, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&isonpn", Abc_CommandAbc9IsoNpn, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&isost", Abc_CommandAbc9IsoSt, 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", "&bmc", Abc_CommandAbc9Bmc, 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", "&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", "&polyn", Abc_CommandAbc9Polyn, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&atree", Abc_CommandAbc9ATree, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&acec", Abc_CommandAbc9Acec, 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", "&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_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", "&test", Abc_CommandAbc9Test, 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(); if ( Abc_FrameGetGlobalFrame()->pGia ) Gia_ManStop( Abc_FrameGetGlobalFrame()->pGia ); if ( Abc_FrameGetGlobalFrame()->pGia2 ) Gia_ManStop( Abc_FrameGetGlobalFrame()->pGia2 ); if ( Abc_FrameGetGlobalFrame()->pGiaBest ) Gia_ManStop( Abc_FrameGetGlobalFrame()->pGiaBest ); 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", fSaveBest? "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 ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; int c; 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 ( 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; } Abc_NodePrintFactor( stdout, pNode, fUseRealNames ); return 0; } // print the nodes Abc_NtkPrintFactor( stdout, pNtk, fUseRealNames ); return 0; usage: Abc_Print( -2, "usage: print_factor [-nh] \n" ); Abc_Print( -2, "\t prints the factored forms of nodes\n" ); Abc_Print( -2, "\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 fVerbose; // set defaults fListNodes = 0; fProfile = 1; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "npvh" ) ) != EOF ) { switch ( c ) { case 'n': fListNodes ^= 1; break; case 'p': fProfile ^= 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, fVerbose ); return 0; usage: Abc_Print( -2, "usage: print_level [-npvh] \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-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 [] ***********************************************************************/ 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_NtkPrintPoEquivs( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, fOutStatus = 0, fShort = 1; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "osh" ) ) != EOF ) { switch ( c ) { 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; } 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 ( 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 [-osh]\n" ); Abc_Print( -2, "\t prints verification status\n" ); Abc_Print( -2, "\t-o : toggle printing output status [default = %s]\n", fOutStatus? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using short print-out [default = %s]\n", fShort? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); 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; extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ); extern void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ); // set defaults fSeq = 0; fGateNames = 0; fUseReverse = 1; fFlopDep = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfh" ) ) != EOF ) { switch ( c ) { case 'r': fUseReverse ^= 1; break; case 's': fSeq ^= 1; break; case 'g': fGateNames ^= 1; break; case 'f': fFlopDep ^= 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 ); return 0; usage: Abc_Print( -2, "usage: show [-srgfh]\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-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; extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); // 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_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; } } Abc_NodeShowBdd( pNode ); return 0; usage: Abc_Print( -2, "usage: show_bdd [-h] \n" ); Abc_Print( -2, " visualizes the BDD of a node using DOT and GSVIEW\n" ); #ifdef WIN32 Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); Abc_Print( -2, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); #endif Abc_Print( -2, "\t: the node to consider [default = the driver of the first PO]\n"); Abc_Print( -2, "\t-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 c; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fVerbose = 0; fReorder = 1; fDualRail = 0; fBddSizeMax = ABC_INFINITY; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != 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 'd': fDualRail ^= 1; break; case 'v': fVerbose ^= 1; break; case 'r': fReorder ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" ); return 1; } // get the new network if ( Abc_NtkIsStrash(pNtk) ) pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); else { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); Abc_NtkDelete( pNtk ); } if ( pNtkRes == NULL ) { Abc_Print( -1, "Collapsing has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: collapse [-B ] [-rdvh]\n" ); Abc_Print( -2, "\t collapses the network by constructing global BDDs\n" ); Abc_Print( -2, "\t-B : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); Abc_Print( -2, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSatClp( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; int nCubeLim = 0; int nBTLimit = 1000000; int nCostMax = 20000000; int fCanon = 0; int fReverse = 0; int fCnfShared = 0; int fVerbose = 0; int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CLZcrsvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nCubeLim = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCubeLim < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBTLimit < 0 ) goto usage; break; case 'Z': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Z\" should be followed by an integer.\n" ); 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 dagling 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 ( !fCleanupPos && !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_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; } 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 > 8 ) 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, \"imfs\")\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 ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int nLutSize; int fVerbose; extern Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nLutSize = 4; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; 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, 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 ] [-vh]\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-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, "WFDMLCZNIdaeijvwh" ) ) != 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 '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 ] [-daeijvwh]\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-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_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_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-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 varibles\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-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_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUpdateLevel; int fPrecompute; int fUseZeros; int fVerbose; int fVeryVerbose; int fPlaceEnable; // external functions extern void Rwr_Precompute(); // set defaults fUpdateLevel = 1; fPrecompute = 0; fUseZeros = 0; fVerbose = 0; fVeryVerbose = 0; fPlaceEnable = 0; 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 if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) ) { Abc_Print( -1, "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); int c; int nNodeSizeMax; int nConeSizeMax; int fUpdateLevel; int fUseZeros; int fUseDcs; int fVerbose; extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); // set defaults nNodeSizeMax = 10; nConeSizeMax = 16; fUpdateLevel = 1; fUseZeros = 0; fUseDcs = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Nlzvh" ) ) != 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 '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 ( 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 if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) ) { Abc_Print( -1, "Refactoring has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: refactor [-N ] [-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-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 fUpdateLevel; int fUseZeros; int fVerbose; int fVeryVerbose; extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ); // set defaults nCutsMax = 8; nNodesMax = 1; nLevelsOdc = 0; fUpdateLevel = 1; fUseZeros = 0; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != 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 ^= 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 ( 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, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) { Abc_Print( -1, "Refactoring has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: resub [-KN ] [-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-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_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 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_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_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_CommandDetect( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose ); Abc_Ntk_t * pNtk; int c, fSeq = 0, fVerbose = 0; pNtk = Abc_FrameReadNtk(pAbc); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) { switch ( c ) { case 's': fSeq ^= 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 applicable to a logic network.\n" ); return 1; } Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose ); return 0; usage: Abc_Print( -2, "usage: detect [-svh]\n" ); Abc_Print( -2, "\t detects properties of internal nodes\n" ); Abc_Print( -2, "\t-s : toggle using sequential circuit information [default = %s]\n", fSeq? "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_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 = 100; 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 ); 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.\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.\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 = %s]\n", nStartGates ); 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-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_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 ) ) 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"); 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), * pNtkRes; 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 pNtkRes = Abc_NtkDup( pNtk ); if ( Abc_NtkPiNum(pNtkRes) == 0 ) { 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_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; 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_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 pNtkRes = Abc_NtkPutOnTop( pNtk, pNtk2 ); 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"); 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 ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, fMode = -1, nCubeLimit = 1000000; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Cdnh" ) ) != 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 '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 ( !Abc_NtkToSop(pNtk, fMode, nCubeLimit) ) { Abc_Print( -1, "Converting to SOP has failed.\n" ); return 0; } return 0; usage: Abc_Print( -2, "usage: sop [-C num] [-dnh]\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-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; 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_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 ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Converting to MUXes has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: muxes [-h]\n" ); Abc_Print( -2, "\t converts the current network into a network derived by\n" ); Abc_Print( -2, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); 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 Gia_Man_t * Abc_NtkClpGia( Abc_Ntk_t * pNtk ); 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 ); 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; } 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; } /**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; int c; int fUseAllCis; int fUseMffc; int fSeq; int Output; int nRange; extern Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtk, int Output, int nRange ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fUseAllCis = 0; fUseMffc = 0; fSeq = 0; Output = -1; nRange = -1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ORmash" ) ) != 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 'm': fUseMffc ^= 1; break; case 'a': fUseAllCis ^= 1; break; case 's': fSeq ^= 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 ( Output == -1 ) { Abc_Print( -1, "The node 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 outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) ); return 1; } pNodeCo = Abc_NtkCo( pNtk, Output ); if ( fSeq ) pNtkRes = Abc_NtkMakeOnePo( pNtk, Output, nRange ); else 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) && !fSeq ) { 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 [-OR num] [-amsh] \n" ); Abc_Print( -2, "\t replaces the current network by one logic cone\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-s : toggle comb or sequential cone (works with \"-O num\") [default = %s]\n", fSeq? "seq": "comb" ); 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, "\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_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 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; } 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_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; // 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; } Abc_NtkShortNames( pNtk ); return 0; usage: Abc_Print( -2, "usage: short_names [-h]\n" ); Abc_Print( -2, "\t replaces PI/PO/latch names by short char strings\n" ); 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 nLutSize = -1; // the size of LUTs int nLuts = -1; // the number of LUTs int fAdder; int fSorter; int fMesh; int fMulti; int fFpga; int fOneHot; int fRandom; 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_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 ); // set defaults nVars = 8; fAdder = 0; fSorter = 0; fMesh = 0; fMulti = 0; fFpga = 0; fOneHot = 0; fRandom = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NKLasemftrvh" ) ) != 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 '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 's': fSorter ^= 1; break; case 'e': fMesh ^= 1; break; case 'm': fMulti ^= 1; break; case 'f': fFpga ^= 1; break; case 't': fOneHot ^= 1; break; case 'r': fRandom ^= 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 ( 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 { 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 [-NKL num] [-asemftrvh] \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-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-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-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" ); Abc_Print( -2, "\t-t : generate one-hotness conditions [default = %s]\n", fOneHot? "yes": "no" ); Abc_Print( -2, "\t-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_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 ) ) 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_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 ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int nCutMax = 1; int nLeafMax = 4; int nDivMax = 2; int nDecMax = 70; int nNumOnes = 4; 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( nDecMax, nDivMax, fVerbose ); } /* 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(); extern void Sfm_TimTest( Abc_Ntk_t * pNtk ); Sfm_TimTest( pNtk ); } 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, "CNflzrvwh" ) ) != 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 '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 ( 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] [-N 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-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, "WCSsptgcfrvh" ) ) != 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 '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] [-sptgcfrvh]\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-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 = 0; 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; 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, "NCFGLIrfbvh" ) ) != 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 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" 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 '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 ); } return 0; usage: Abc_Print( -2, "usage: iprove [-NCFGLI num] [-rfbvh]\n" ); Abc_Print( -2, "\t performs CEC using a new method\n" ); Abc_Print( -2, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); Abc_Print( -2, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); Abc_Print( -2, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); Abc_Print( -2, "\t-G num : multiplicative coefficient for fraiging [default = %d]\n", (int)pParams->nFraigingLimitMulti ); Abc_Print( -2, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); Abc_Print( -2, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit ); 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"); 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_start2\".\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_start2\".\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 ); } 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 fVerbose; int c; extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fVerbose ); extern 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; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "DABFSGMarspfuvh" ) ) != 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 '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, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, 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, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, 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] [-arspfuvh]\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-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_CommandUnmap( 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_NtkHasMapping(pNtk) ) { Abc_Print( -1, "Cannot unmap the network that is not mapped.\n" ); return 1; } // get the new network if ( !Abc_NtkMapToSop( pNtk ) ) { Abc_Print( -1, "Unmapping has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: unmap [-h]\n" ); Abc_Print( -2, "\t replaces the library gates by the logic nodes represented using SOPs\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAttach( 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_NtkIsSopLogic(pNtk) ) { Abc_Print( -1, "Can only attach gates if the nodes have SOP representations.\n" ); return 1; } // get the new network if ( !Abc_NtkAttach( pNtk ) ) { Abc_Print( -1, "Attaching gates has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: attach [-h]\n" ); Abc_Print( -2, "\t replaces the SOP functions by the gates from the library\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; extern Abc_Ntk_t * Abc_NtkSuperChoice( 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, "Superchoicing works only for the AIG representation (run \"strash\").\n" ); return 1; } // get the new network pNtkRes = Abc_NtkSuperChoice( pNtk ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Superchoicing has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: superc [-h]\n" ); Abc_Print( -2, "\t performs superchoicing\n" ); Abc_Print( -2, "\t (accumulate: \"r file.blif; rsup; b; sc; f -ac; wb file_sc.blif\")\n" ); Abc_Print( -2, "\t (map without supergate library: \"r file_sc.blif; ft; map\")\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSuperChoiceLut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int nLutSize; int nCutSizeMax; int fVerbose; extern int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fVerbose = 1; nLutSize = 4; nCutSizeMax = 10; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KNh" ) ) != 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 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } nCutSizeMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutSizeMax < 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, "Superchoicing works only for the AIG representation (run \"strash\").\n" ); return 1; } // convert the network into the SOP network pNtkRes = Abc_NtkToLogic( pNtk ); // get the new network if ( !Abc_NtkSuperChoiceLut( pNtkRes, nLutSize, nCutSizeMax, fVerbose ) ) { Abc_NtkDelete( pNtkRes ); Abc_Print( -1, "Superchoicing has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: supercl [-K num] [-N num] [-vh]\n" ); Abc_Print( -2, "\t performs superchoicing for K-LUTs\n" ); Abc_Print( -2, "\t (accumulate: \"r file.blif; b; scl; f -ac; wb file_sc.blif\")\n" ); Abc_Print( -2, "\t (FPGA map: \"r file_sc.blif; ft; read_lut lutlibK; fpga\")\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-N num : the max size of the cut [default = %d]\n", nCutSizeMax ); 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_CommandTimeScale( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkTimeScale( Abc_Ntk_t * pNtk, float Scale ); Abc_Ntk_t * pNtk; float nTimeScale; int c, fVerbose; pNtk = Abc_FrameReadNtk(pAbc); // set defaults nTimeScale = (float)0.01; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Th" ) ) != EOF ) { switch ( c ) { case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); goto usage; } nTimeScale = atof(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeScale < 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 ( pNtk->pManTime == NULL ) { Abc_Print( -1, "Timing manager is not defined.\n" ); return 1; } Abc_NtkTimeScale( pNtk, nTimeScale ); return 0; usage: Abc_Print( -2, "usage: timescale [-T float] [-vh]\n" ); Abc_Print( -2, "\t scales timing information of the current network\n" ); Abc_Print( -2, "\t-T float : multiplicative factor [default = %f]\n", nTimeScale ); 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 [] ***********************************************************************/ #if 0 int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[100]; char LutSize[100]; Abc_Ntk_t * pNtk, * pNtkRes; int c; int fRecovery; int fSwitching; int fLatchPaths; int fVerbose; int nLutSize; float DelayTarget; extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fRecovery = 1; fSwitching = 0; fLatchPaths = 0; fVerbose = 0; DelayTarget =-1; nLutSize =-1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "aplvhDK" ) ) != EOF ) { switch ( c ) { case 'a': fRecovery ^= 1; break; case 'p': fSwitching ^= 1; break; case 'l': fLatchPaths ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; 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 '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; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // create the new LUT library if ( nLutSize >= 3 && nLutSize <= 10 ) Fpga_SetSimpleLutLib( nLutSize ); /* else { Abc_Print( -1, "Cannot perform FPGA mapping with LUT size %d.\n", nLutSize ); return 1; } */ if ( !Abc_NtkIsStrash(pNtk) ) { // strash and balance the network pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); if ( pNtk == NULL ) { Abc_Print( -1, "Strashing before FPGA 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 FPGA mapping has failed.\n" ); return 1; } Abc_Print( 1, "The network was strashed and balanced before FPGA mapping.\n" ); // get the new network pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); Abc_Print( -1, "FPGA mapping has failed.\n" ); return 1; } Abc_NtkDelete( pNtk ); } else { // get the new network pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "FPGA mapping has failed.\n" ); return 1; } } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: if ( DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%.2f", DelayTarget ); if ( nLutSize == -1 ) sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", nLutSize ); Abc_Print( -2, "usage: fpga [-D float] [-K num] [-aplvh]\n" ); Abc_Print( -2, "\t performs FPGA mapping of the current network\n" ); Abc_Print( -2, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); Abc_Print( -2, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" ); Abc_Print( -2, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", fLatchPaths? "yes": "no" ); Abc_Print( -2, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < 11) [default = %s]%s\n", LutSize, (nLutSize == -1 ? " (type \"print_lut\")" : "") ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFpgaFast( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[100]; Abc_Ntk_t * pNtk, * pNtkRes; int c; int fRecovery; int fVerbose; int nLutSize; float DelayTarget; extern Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fRecovery = 1; fVerbose = 0; DelayTarget =-1; nLutSize = 5; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "avhDK" ) ) != EOF ) { switch ( c ) { case 'a': fRecovery ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; 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 '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; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { // strash and balance the network pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); if ( pNtk == NULL ) { Abc_Print( -1, "Strashing before FPGA 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 FPGA mapping has failed.\n" ); return 1; } Abc_Print( 1, "The network was strashed and balanced before FPGA mapping.\n" ); // get the new network pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); Abc_Print( -1, "FPGA mapping has failed.\n" ); return 1; } Abc_NtkDelete( pNtk ); } else { // get the new network pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "FPGA mapping has failed.\n" ); return 1; } } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: if ( DelayTarget == -1 ) sprintf(Buffer, "not used" ); else sprintf(Buffer, "%.2f", DelayTarget ); Abc_Print( -2, "usage: ffpga [-K num] [-avh]\n" ); Abc_Print( -2, "\t performs fast FPGA mapping of the current network\n" ); Abc_Print( -2, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); // Abc_Print( -2, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < 32) [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } #endif /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); char Buffer[100], LutSize[100]; Abc_Ntk_t * pNtk, * pNtkRes; If_Par_t Pars, * pPars = &Pars; int c; pNtk = Abc_FrameReadNtk(pAbc); If_ManSetDefaultPars( pPars ); pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktncvh" ) ) != 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 0 ) goto usage; // if the LUT size is specified, disable library pPars->pLutLib = NULL; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nCutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->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; } pPars->nFlowIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->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; } pPars->nAreaIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAreaIters < 0 ) goto usage; break; case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer no less than 3.\n" ); goto usage; } pPars->nGateSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nGateSize < 2 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } pPars->nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRelaxRatio < 0 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer no less than 3.\n" ); goto usage; } pPars->nNonDecLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nNonDecLimit < 2 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer 0,1,or 2.\n" ); goto usage; } pPars->nStructType = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nStructType < 0 || pPars->nStructType > 2 ) goto usage; break; case 'X': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer 0,1,or 2.\n" ); goto usage; } pPars->nAndDelay = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAndArea < 0 ) goto usage; break; case 'Y': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Y\" should be followed by a positive integer 0,1,or 2.\n" ); goto usage; } pPars->nAndArea = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAndDelay < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } pPars->DelayTarget = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0.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->Epsilon = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a floating point number.\n" ); goto usage; } pPars->WireDelay = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->WireDelay < 0.0 ) goto usage; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); goto usage; } pPars->pLutStruct = argv[globalUtilOptind]; globalUtilOptind++; if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by a 2- or 3-char string (e.g. \"44\" or \"555\").\n" ); goto usage; } break; case 'q': pPars->fPreprocess ^= 1; break; case 'a': pPars->fArea ^= 1; break; case 'r': pPars->fExpRed ^= 1; break; case 'f': pPars->fFancy ^= 1; break; case 'l': pPars->fLatchPaths ^= 1; break; case 'e': pPars->fEdge ^= 1; break; case 'p': pPars->fPower ^= 1; break; case 'm': pPars->fCutMin ^= 1; break; case 's': pPars->fDelayOptLut ^= 1; break; case 'd': pPars->fBidec ^= 1; break; case 'b': pPars->fUseBat ^= 1; break; case 'g': pPars->fDelayOpt ^= 1; break; case 'x': pPars->fDsdBalance ^= 1; break; case 'y': pPars->fUserRecLib ^= 1; break; case 'u': pPars->fUserSesLib ^= 1; break; case 'o': pPars->fUseBuffs ^= 1; break; case 'j': pPars->fEnableCheck07 ^= 1; break; case 'i': pPars->fUseCofVars ^= 1; break; case 'k': pPars->fUseDsdTune ^= 1; break; case 't': pPars->fDoAverage ^= 1; break; case 'n': pPars->fUseDsd ^= 1; break; case 'c': pPars->fUseTtPerm ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( pPars->nLutSize == -1 ) { if ( pPars->pLutLib == NULL ) { Abc_Print( -1, "The LUT library is not given.\n" ); return 1; } pPars->nLutSize = pPars->pLutLib->LutMax; } if ( pPars->nLutSize < 2 || pPars->nLutSize > IF_MAX_LUTSIZE ) { Abc_Print( -1, "Incorrect LUT size (%d).\n", pPars->nLutSize ); return 1; } if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) ) { Abc_Print( -1, "Incorrect number of cuts.\n" ); return 1; } // enable truth table computation if choices are selected if ( (c = Abc_NtkGetChoiceNum( pNtk )) ) { // if ( !Abc_FrameReadFlag("silentmode") ) // Abc_Print( 0, "Performing LUT mapping with %d choices.\n", c ); pPars->fExpRed = 0; } if ( pPars->fUseBat ) { if ( pPars->nLutSize < 4 || pPars->nLutSize > 6 ) { Abc_Print( -1, "This feature only works for {4,5,6}-LUTs.\n" ); return 1; } pPars->fCutMin = 1; } if ( pPars->fEnableCheck07 + pPars->fUseCofVars + pPars->fUseDsdTune + (pPars->pLutStruct != NULL) > 1 ) { Abc_Print( -1, "Only one additional check can be performed at the same time.\n" ); return 1; } if ( pPars->fEnableCheck07 ) { if ( pPars->nLutSize < 6 || pPars->nLutSize > 7 ) { Abc_Print( -1, "This feature only works for {6,7}-LUTs.\n" ); return 1; } pPars->pFuncCell = If_CutPerformCheck07; pPars->fCutMin = 1; } if ( pPars->fUseCofVars ) { if ( !(pPars->nLutSize & 1) ) { Abc_Print( -1, "This feature only works for odd-sized LUTs.\n" ); return 1; } pPars->fCutMin = 1; } if ( pPars->fUseDsdTune ) { If_DsdMan_t * pDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd(); if ( pDsdMan == NULL ) { Abc_Print( -1, "DSD manager is not available.\n" ); return 1; } if ( pPars->nLutSize > If_DsdManVarNum(pDsdMan) ) { Abc_Print( -1, "LUT size (%d) is more than the number of variables in the DSD manager (%d).\n", pPars->nLutSize, If_DsdManVarNum(pDsdMan) ); return 1; } if ( pPars->fDeriveLuts && If_DsdManGetCellStr(pDsdMan) == NULL ) { Abc_Print( -1, "DSD manager is not matched with any particular cell.\n" ); return 1; } pPars->fCutMin = 1; pPars->fUseDsd = 1; If_DsdManSetNewAsUseless( pDsdMan ); } if ( pPars->pLutStruct ) { if ( pPars->fDsdBalance ) { Abc_Print( -1, "Incompatible options (-S and -x).\n" ); return 1; } if ( pPars->nLutSize < 6 || pPars->nLutSize > 16 ) { Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" ); return 1; } pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; pPars->fCutMin = 1; } // enable truth table computation if cut minimization is selected if ( pPars->fCutMin ) { pPars->fTruth = 1; pPars->fExpRed = 0; } // modify the subgraph recording if ( pPars->fUserRecLib || pPars->fUserSesLib ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; pPars->fUsePerm = 1; pPars->pLutLib = NULL; } // modify for delay optimization if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; pPars->fUseDsd = pPars->fDsdBalance || pPars->fDelayOptLut; pPars->pLutLib = NULL; } // modify for delay optimization if ( pPars->nGateSize > 0 ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; pPars->fUsePerm = 1; pPars->pLutLib = NULL; pPars->nLutSize = pPars->nGateSize; } if ( pPars->fUseDsd || pPars->fUseTtPerm ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; } if ( pPars->fUseDsd ) { int LutSize = (pPars->pLutStruct && pPars->pLutStruct[2] == 0)? pPars->pLutStruct[0] - '0' : 0; If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd(); if ( pPars->pLutStruct && pPars->pLutStruct[2] != 0 ) { printf( "DSD only works for LUT structures XY.\n" ); return 0; } if ( p && pPars->nLutSize > If_DsdManVarNum(p) ) { printf( "DSD manager has incompatible number of variables.\n" ); return 0; } if ( p && LutSize != If_DsdManLutSize(p) && !pPars->fDsdBalance ) { printf( "DSD manager has different LUT size.\n" ); return 0; } if ( p == NULL ) { if ( LutSize > DAU_MAX_VAR || pPars->nLutSize > DAU_MAX_VAR ) { printf( "Size of required DSD manager (%d) exceeds the precompiled limit (%d) (change parameter DAU_MAX_VAR).\n", LutSize, DAU_MAX_VAR ); return 0; } Abc_FrameSetManDsd( If_DsdManAlloc(pPars->nLutSize, LutSize) ); } } if ( pPars->fUserRecLib ) { if ( !Abc_NtkRecIsRunning3() ) { printf( "LMS manager is not running (use \"rec_start3\").\n" ); return 0; } if ( Abc_NtkRecInputNum3() != pPars->nLutSize ) { printf( "The number of library inputs (%d) is different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize ); return 0; } } if ( pPars->fUserSesLib ) { if ( !Abc_ExactIsRunning() ) { printf( "BMS manager is not running (use \"bms_start\").\n" ); return 0; } if ( Abc_ExactInputNum() < pPars->nLutSize ) { printf( "The number of library inputs (%d) is smaller than the K parameters (%d).\n", Abc_ExactInputNum(), pPars->nLutSize ); return 0; } } // complain if truth tables are requested but the cut size is too large if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE ) { Abc_Print( -1, "Truth tables cannot be computed for LUT larger than %d inputs.\n", IF_MAX_FUNC_LUTSIZE ); return 1; } // disable cut-expansion if edge-based heuristics are selected // if ( pPars->fEdge ) // pPars->fExpRed = 0; if ( !Abc_NtkIsStrash(pNtk) ) { // strash and balance the network pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); if ( pNtk == NULL ) { Abc_Print( -1, "Strashing before FPGA 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 FPGA mapping has failed.\n" ); return 1; } if ( !Abc_FrameReadFlag("silentmode") ) Abc_Print( 1, "The network was strashed and balanced before FPGA mapping.\n" ); // get the new network pNtkRes = Abc_NtkIf( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); Abc_Print( -1, "FPGA mapping has failed.\n" ); return 0; } Abc_NtkDelete( pNtk ); } else { // get the new network pNtkRes = Abc_NtkIf( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_Print( -1, "FPGA mapping has failed.\n" ); return 0; } } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%.2f", pPars->DelayTarget ); if ( pPars->nLutSize == -1 ) sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); Abc_Print( -2, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters ); Abc_Print( -2, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); Abc_Print( -2, "\t-G num : the max AND/OR gate size for mapping (0 = unused) [default = %d]\n", pPars->nGateSize ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio ); Abc_Print( -2, "\t-N num : the max size of non-decomposable nodes [default = unused]\n", pPars->nNonDecLimit ); Abc_Print( -2, "\t-T num : the type of LUT structures [default = any]\n" ); Abc_Print( -2, "\t-X num : delay of AND-gate in LUT library units [default = %d]\n", pPars->nAndDelay ); Abc_Print( -2, "\t-Y num : area of AND-gate in LUT library units [default = %d]\n", pPars->nAndArea ); Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); Abc_Print( -2, "\t-S str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); Abc_Print( -2, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); Abc_Print( -2, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); Abc_Print( -2, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" ); Abc_Print( -2, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); Abc_Print( -2, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-s : toggles delay-oriented mapping used with -S [default = %s]\n", pPars->fDelayOptLut? "yes": "no" ); Abc_Print( -2, "\t-d : toggles deriving local AIGs using bi-decomposition [default = %s]\n", pPars->fBidec? "yes": "no" ); Abc_Print( -2, "\t-b : toggles the use of one special feature [default = %s]\n", pPars->fUseBat? "yes": "no" ); Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" ); Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); Abc_Print( -2, "\t-u : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); Abc_Print( -2, "\t-i : toggles using cofactoring variables [default = %s]\n", pPars->fUseCofVars? "yes": "no" ); Abc_Print( -2, "\t-k : toggles matching based on precomputed DSD manager [default = %s]\n", pPars->fUseDsdTune? "yes": "no" ); Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-n : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandIfif( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkPerformIfif( Abc_Ntk_t * pNtk, Ifif_Par_t * pPars ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Ifif_Par_t Pars, * pPars = &Pars; int c, fError; pPars->nLutSize = -1; // the LUT size pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); // the LUT library pPars->DelayWire = (float)0.5; // wire delay pPars->nDegree = 0; // structure degree pPars->fCascade = 0; // cascade pPars->fVerbose = 0; // verbose pPars->fVeryVerbose = 0; // verbose Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "DNcvwh" ) ) != 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; } pPars->DelayWire = atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayWire < 0.0 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a floating point number.\n" ); goto usage; } pPars->nDegree = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nDegree < 0 ) goto usage; break; case 'c': pPars->fCascade ^= 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, "Need mapped network.\n" ); return 1; } if ( pPars->pLutLib == NULL ) { Abc_Print( -1, "LUT library is not given.\n" ); return 1; } pPars->nLutSize = Abc_NtkGetFaninMax( pNtk ); if ( pPars->nLutSize > pPars->pLutLib->LutMax ) { Abc_Print( -1, "The max node size (%d) exceeds the LUT size (%d).\n", pPars->nLutSize, pPars->pLutLib->LutMax ); return 1; } if ( pPars->nLutSize < pPars->pLutLib->LutMax ) Abc_Print( 0, "Node size (%d) is less than LUT size (%d).\n", pPars->nLutSize, pPars->pLutLib->LutMax ); // check delay information fError = 0; for ( c = 0; c < pPars->pLutLib->LutMax; c++ ) { pPars->pLutDelays[c] = ( pPars->pLutLib->fVarPinDelays ? pPars->pLutLib->pLutDelays[pPars->pLutLib->LutMax][c] : pPars->pLutLib->pLutDelays[pPars->pLutLib->LutMax][0] ); if ( pPars->DelayWire >= pPars->pLutDelays[c] ) { fError = 1; printf(" Wire delay (%.2f) exceeds pin+wire delay (%.2f) for pin %d in the LUT library.\n", pPars->DelayWire, pPars->pLutDelays[c], c ); } } if ( fError ) return 1; // call the mapper Abc_NtkPerformIfif( pNtk, pPars ); return 0; usage: Abc_Print( -2, "usage: ifif [-DNcvwh]\n" ); Abc_Print( -2, "\t technology mapper into N-node K-LUT structures\n" ); Abc_Print( -2, "\t (takes a LUT network and maps it into a delay-optimal network\n" ); Abc_Print( -2, "\t of N-node K-LUT structures using the current LUT library)\n" ); Abc_Print( -2, "\t-D float : wire delay (should be less than the LUT delay) [default = %.2f]\n", pPars->DelayWire ); Abc_Print( -2, "\t-N num : degree of the LUT structure [default = %d]\n", pPars->nDegree ); Abc_Print( -2, "\t-c : toggles using LUT cascade vs LUT cluster [default = %s]\n", pPars->fCascade? "cascade": "cluster" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDsdSave( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * FileName; char ** pArgvNew; int nArgcNew; int c, fSecond = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "bh" ) ) != EOF ) { switch ( c ) { case 'b': fSecond ^= 1; break; case 'h': goto usage; default: goto usage; } } 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 = (nArgcNew == 1) ? pArgvNew[0] : NULL; if ( fSecond ) { if ( !Abc_FrameReadManDsd2() ) { Abc_Print( -1, "The DSD manager is not started.\n" ); return 1; } If_DsdManSave( (If_DsdMan_t *)Abc_FrameReadManDsd2(), FileName ); } else { if ( !Abc_FrameReadManDsd() ) { Abc_Print( -1, "The DSD manager is not started.\n" ); return 1; } If_DsdManSave( (If_DsdMan_t *)Abc_FrameReadManDsd(), FileName ); } return 0; usage: Abc_Print( -2, "usage: dsd_save [-bh] \n" ); Abc_Print( -2, "\t saves DSD manager into a file\n"); Abc_Print( -2, "\t-b : toggles processing second manager [default = %s]\n", fSecond? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : (optional) file name to write\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDsdLoad( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * FileName, * pTemp; char ** pArgvNew; int c, nArgcNew, fSecond = 0; FILE * pFile; If_DsdMan_t * pDsdMan; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "bh" ) ) != EOF ) { switch ( c ) { case 'b': fSecond ^= 1; break; case 'h': goto usage; default: goto usage; } } 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]; // 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 ); if ( fSecond ) { Abc_FrameSetManDsd2( NULL ); pDsdMan = If_DsdManLoad(FileName); if ( pDsdMan == NULL ) return 1; Abc_FrameSetManDsd2( pDsdMan ); } else { Abc_FrameSetManDsd( NULL ); pDsdMan = If_DsdManLoad(FileName); if ( pDsdMan == NULL ) return 1; Abc_FrameSetManDsd( pDsdMan ); } return 0; usage: Abc_Print( -2, "usage: dsd_load [-bh] \n" ); Abc_Print( -2, "\t loads DSD manager from file\n"); Abc_Print( -2, "\t-b : toggles processing second manager [default = %s]\n", fSecond? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file name to read\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDsdFree( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, fSecond = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "bh" ) ) != EOF ) { switch ( c ) { case 'b': fSecond ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fSecond ) { if ( !Abc_FrameReadManDsd2() ) { Abc_Print( -1, "The DSD manager is not started.\n" ); return 0; } Abc_FrameSetManDsd2( NULL ); } else { if ( !Abc_FrameReadManDsd() ) { Abc_Print( -1, "The DSD manager is not started.\n" ); return 0; } Abc_FrameSetManDsd( NULL ); } return 0; usage: Abc_Print( -2, "usage: dsd_free [-bh]\n" ); Abc_Print( -2, "\t deletes DSD manager\n" ); Abc_Print( -2, "\t-b : toggles processing second manager [default = %s]\n", fSecond? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDsdPs( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, Number = 0, Support = 0, fOccurs = 0, fTtDump = 0, fSecond = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NSotbvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a floating point number.\n" ); goto usage; } Number = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Number < 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; } Support = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Support < 0 ) goto usage; break; case 'o': fOccurs ^= 1; break; case 't': fTtDump ^= 1; break; case 'b': fSecond ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fSecond ) { if ( !Abc_FrameReadManDsd2() ) { Abc_Print( -1, "The DSD manager is not started.\n" ); return 0; } If_DsdManPrint( (If_DsdMan_t *)Abc_FrameReadManDsd2(), NULL, Number, Support, fOccurs, fTtDump, fVerbose ); } else { if ( !Abc_FrameReadManDsd() ) { Abc_Print( -1, "The DSD manager is not started.\n" ); return 0; } If_DsdManPrint( (If_DsdMan_t *)Abc_FrameReadManDsd(), NULL, Number, Support, fOccurs, fTtDump, fVerbose ); } return 0; usage: Abc_Print( -2, "usage: dsd_ps [-NS num] [-obvh]\n" ); Abc_Print( -2, "\t prints statistics of the DSD manager\n" ); Abc_Print( -2, "\t-N num : show structures whose ID divides by N [default = %d]\n", Number ); Abc_Print( -2, "\t-S num : show structures whose support size is S [default = %d]\n", Support ); Abc_Print( -2, "\t-o : toggles printing occurence distribution [default = %s]\n", fOccurs? "yes": "no" ); Abc_Print( -2, "\t-t : toggles dumping truth tables [default = %s]\n", fTtDump? "yes": "no" ); Abc_Print( -2, "\t-b : toggles processing second manager [default = %s]\n", fSecond? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDsdMatch( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pStruct = NULL; int c, fVerbose = 0, fFast = 0, fAdd = 0, fSpec = 0, LutSize = 0, nConfls = 10000, nProcs = 1; If_DsdMan_t * pDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd(); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCPSfasvh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by a floating point number.\n" ); goto usage; } LutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( LutSize < 4 || LutSize > 6 ) 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; } nConfls = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by a floating point number.\n" ); goto usage; } nProcs = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); goto usage; } pStruct = argv[globalUtilOptind]; globalUtilOptind++; break; case 'f': fFast ^= 1; break; case 'a': fAdd ^= 1; break; case 's': fSpec ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( !Abc_FrameReadManDsd() ) { Abc_Print( -1, "The DSD manager is not started.\n" ); return 0; } if ( pStruct ) { char * pStructCur = If_DsdManGetCellStr( pDsdMan ); if ( pStructCur && strcmp(pStructCur, pStruct) ) { Abc_Print( -1, "DSD manager matched with cell %s should be cleaned by \"dsd_filter -m\" before matching with cell %s.\n", pStructCur, pStruct ); return 0; } Id_DsdManTuneStr( pDsdMan, pStruct, nConfls, nProcs, fVerbose ); } else If_DsdManTune( pDsdMan, LutSize, fFast, fAdd, fSpec, fVerbose ); return 0; usage: Abc_Print( -2, "usage: dsd_match [-KCP num] [-fasvh] [-S str]\n" ); Abc_Print( -2, "\t matches DSD structures with the given cell\n" ); Abc_Print( -2, "\t-K num : LUT size used for tuning [default = %d]\n", LutSize ); Abc_Print( -2, "\t-C num : the maximum number of conflicts [default = %d]\n", nConfls ); Abc_Print( -2, "\t-P num : the maximum number of processes [default = %d]\n", nProcs ); Abc_Print( -2, "\t-f : toggles using fast check [default = %s]\n", fFast? "yes": "no" ); Abc_Print( -2, "\t-a : toggles adding tuning to the current one [default = %s]\n", fAdd? "yes": "no" ); Abc_Print( -2, "\t-s : toggles using specialized check [default = %s]\n", fSpec? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-S str : string representing programmable cell [default = %s]\n", pStruct ? pStruct : "not used" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDsdMerge( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * FileName, * pTemp; char ** pArgvNew; int c, nArgcNew; FILE * pFile; If_DsdMan_t * pDsdMan; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( !Abc_FrameReadManDsd() ) { Abc_Print( -1, "The DSD manager is not 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.\n" ); return 1; } // get the input file name FileName = pArgvNew[0]; // fix the wrong symbol for ( pTemp = FileName; *pTemp; pTemp++ ) if ( *pTemp == '>' ) *pTemp = '\\'; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); pDsdMan = If_DsdManLoad(FileName); if ( pDsdMan == NULL ) return 1; If_DsdManMerge( (If_DsdMan_t *)Abc_FrameReadManDsd(), pDsdMan ); If_DsdManFree( pDsdMan, 0 ); return 0; usage: Abc_Print( -2, "usage: dsd_merge [-h] \n" ); Abc_Print( -2, "\t merges DSD manager from file with the current one\n"); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file name to read\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDsdFilter( Abc_Frame_t * pAbc, int argc, char ** argv ) { If_DsdMan_t * pDsd = (If_DsdMan_t *)Abc_FrameReadManDsd(); int c, nLimit = 0, nLutSize = -1, fCleanOccur = 0, fCleanMarks = 0, fInvMarks = 0, fUnate = 0, fThresh = 0, fThreshHeuristic = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "LKomiutsvh" ) ) != EOF ) { switch ( c ) { case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by a floating point number.\n" ); goto usage; } nLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by a floating point number.\n" ); goto usage; } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'o': fCleanOccur ^= 1; break; case 'm': fCleanMarks ^= 1; break; case 'i': fInvMarks ^= 1; break; case 'u': fUnate ^= 1; break; case 't': fThresh ^= 1; break; case 's': fThreshHeuristic ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pDsd == NULL ) { Abc_Print( -1, "The DSD manager is not started.\n" ); return 0; } if ( nLimit > 0 ) Abc_FrameSetManDsd( If_DsdManFilter(pDsd, nLimit) ); if ( nLutSize >= 0 ) If_DsdManSetLutSize( pDsd, nLutSize ); if ( fCleanOccur ) If_DsdManCleanOccur( pDsd, fVerbose ); if ( fCleanMarks ) If_DsdManCleanMarks( pDsd, fVerbose ); if ( fInvMarks ) If_DsdManInvertMarks( pDsd, fVerbose ); #ifdef ABC_USE_CUDD else Id_DsdManTuneThresh( pDsd, fUnate, fThresh, fThreshHeuristic, fVerbose ); #endif return 0; usage: Abc_Print( -2, "usage: dsd_filter [-LK num] [-omiutsvh]\n" ); Abc_Print( -2, "\t filtering structured and modifying parameters of DSD manager\n" ); Abc_Print( -2, "\t-L num : remove structures with fewer occurrences that this [default = %d]\n", nLimit ); Abc_Print( -2, "\t-K num : new LUT size to set for the DSD manager [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-o : toggles cleaning occurrence counters [default = %s]\n", fCleanOccur? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cleaning matching marks [default = %s]\n", fCleanMarks? "yes": "no" ); Abc_Print( -2, "\t-i : toggles inverting matching marks [default = %s]\n", fInvMarks? "yes": "no" ); Abc_Print( -2, "\t-u : toggles marking unate functions [default = %s]\n", fUnate? "yes": "no" ); Abc_Print( -2, "\t-t : toggles marking threshold functions [default = %s]\n", fThresh? "yes": "no" ); Abc_Print( -2, "\t-s : toggles marking threshold functions heuristically [default = %s]\n", fThreshHeuristic?"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"); Abc_Print( -2, "\t \n" ); Abc_Print( -2, "\t Option \"dsd_filter -s\" was contributed by Augusto Neutzling and Jody Matos from\n" ); Abc_Print( -2, "\t Federal University of Rio Grande do Sul, Brazil. The paper describing the method:\n" ); Abc_Print( -2, "\t A. Neutzling, J. M. Matos, A. Mishchenko, R. Ribas, and A. Reis,\n" ); Abc_Print( -2, "\t \"Threshold logic synthesis based on cut pruning\". Proc. ICCAD 2015.\n" ); // Abc_Print( -2, "\t http://www.eecs.berkeley.edu/~alanmi/publications/2015/iccad15_thresh.pdf\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pObj; char * pInitStr = NULL; int fZeros = 0; int fOnes = 0; int fRandom = 0; int fDontCare = 0; int fUseCexCs = 0; int fUseCexNs = 0; int c, i; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Szordcnh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by a file name.\n" ); goto usage; } pInitStr = argv[globalUtilOptind]; globalUtilOptind++; break; case 'z': fZeros ^= 1; break; case 'o': fOnes ^= 1; break; case 'r': fRandom ^= 1; break; case 'd': fDontCare ^= 1; break; case 'c': fUseCexCs ^= 1; break; case 'n': fUseCexNs ^= 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( 0, "The current network is combinational.\n" ); return 0; } if ( pInitStr != NULL ) { if ( (int)strlen(pInitStr) != Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The length of init string (%d) differs from the number of flops (%d).\n", strlen(pInitStr), Abc_NtkLatchNum(pNtk) ); return 1; } Abc_NtkForEachLatch( pNtk, pObj, i ) if ( pInitStr[i] == '0' ) Abc_LatchSetInit0( pObj ); else if ( pInitStr[i] == '1' ) Abc_LatchSetInit1( pObj ); else Abc_LatchSetInitDc( pObj ); return 0; } if ( fZeros ) { Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInit0( pObj ); } else if ( fOnes ) { Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInit1( pObj ); } else if ( fRandom ) { srand( time(NULL) ); Abc_NtkForEachLatch( pNtk, pObj, i ) if ( rand() & 1 ) Abc_LatchSetInit1( pObj ); else Abc_LatchSetInit0( pObj ); } else if ( fDontCare ) { Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj ); } else if ( fUseCexCs || fUseCexNs ) { extern Vec_Int_t * Saig_ManReturnFailingState( Aig_Man_t * pMan, Abc_Cex_t * p, int fNextOne ); Aig_Man_t * pMan; Vec_Int_t * vFailState; if ( fUseCexCs && fUseCexNs ) { Abc_Print( -1, "The two options (-c and -n) are incompatible.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The current network should be an AIG.\n" ); return 0; } if ( pAbc->pCex == NULL ) { Abc_Print( -1, "The current CEX is not available.\n" ); return 0; } pMan = Abc_NtkToDar( pNtk, 0, 1 ); vFailState = Saig_ManReturnFailingState( pMan, pAbc->pCex, fUseCexNs ); //Vec_IntPrint( vFailState ); Aig_ManStop( pMan ); Abc_NtkForEachLatch( pNtk, pObj, i ) if ( Vec_IntEntry( vFailState, i ) ) Abc_LatchSetInit1( pObj ); else Abc_LatchSetInit0( pObj ); Vec_IntFree( vFailState ); } else Abc_Print( -1, "The initial states remain unchanged.\n" ); return 0; usage: Abc_Print( -2, "usage: init [-zordcnh] [-S ]\n" ); Abc_Print( -2, "\t resets initial states of all latches\n" ); Abc_Print( -2, "\t-z : set zeros initial states [default = %s]\n", fZeros? "yes": "no" ); Abc_Print( -2, "\t-o : set ones initial states [default = %s]\n", fOnes? "yes": "no" ); Abc_Print( -2, "\t-d : set don't-care initial states [default = %s]\n", fDontCare? "yes": "no" ); Abc_Print( -2, "\t-r : set random initial states [default = %s]\n", fRandom? "yes": "no" ); Abc_Print( -2, "\t-c : set failure current state from the CEX (and run \"zero\") [default = %s]\n", fUseCexCs? "yes": "no" ); Abc_Print( -2, "\t-n : set next state after failure from the CEX (and run \"zero\") [default = %s]\n", fUseCexNs? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t-S str : (optional) initial state [default = unused]\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandZero( 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_NtkIsComb(pNtk) ) { Abc_Print( 0, "The current network is combinational.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for AIGs.\n" ); return 0; } // get the new network pNtkRes = Abc_NtkRestrashZero( pNtk, 0 ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Converting to sequential AIG has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: zero [-h]\n" ); Abc_Print( -2, "\t converts latches to have const-0 initial value\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandUndc( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, fUseCex = 0; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fUseCex ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( fUseCex ) { char * pInit; Abc_Cex_t * pTemp; int k, nFlopsX = 0; if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Current CEX is not available.\n" ); return 1; } pInit = Abc_NtkCollectLatchValuesStr( pAbc->pNtkCur ); // count the number of X-valued flops for ( k = 0; k < Abc_NtkLatchNum(pAbc->pNtkCur); k++ ) nFlopsX += (int)(pInit[k] == 'x'); // compare this value if ( Abc_NtkPiNum(pNtk) + nFlopsX != pAbc->pCex->nPis ) { Abc_Print( -1, "The number of PIs (%d) plus X-valued flops (%d) in the original network does not match the number of PIs in the current CEX (%d).\n", Abc_NtkPiNum(pNtk), Abc_NtkLatchNum(pNtk), pAbc->pCex->nPis ); return 1; } pAbc->pCex = Abc_CexTransformUndc( pTemp = pAbc->pCex, pInit ); assert( pAbc->pCex->nPis == Abc_NtkPiNum(pAbc->pNtkCur) ); assert( pAbc->pCex->nRegs == Abc_NtkLatchNum(pAbc->pNtkCur) ); Abc_CexFree( pTemp ); ABC_FREE( pInit ); return 0; } if ( Abc_NtkIsComb(pNtk) ) { Abc_Print( 0, "The current network is combinational.\n" ); return 0; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "This command works only for logic networks.\n" ); return 0; } // get the new network Abc_NtkConvertDcLatches( pNtk ); return 0; usage: Abc_Print( -2, "usage: undc [-ch]\n" ); Abc_Print( -2, "\t converts latches with DC init values into free PIs\n" ); Abc_Print( -2, "\t-c : toggles transforming CEX after \"logic;undc;st;zero\" [default = %s]\n", fUseCex? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandOneHot( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; extern Abc_Ntk_t * Abc_NtkConvertOnehot( 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_NtkIsComb(pNtk) ) { Abc_Print( 0, "The current network is combinational.\n" ); return 0; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "This command works only for logic networks.\n" ); return 0; } // get the new network pNtkRes = Abc_NtkConvertOnehot( pNtk ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Converting to one-hot encoding has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: onehot [-h]\n" ); Abc_Print( -2, "\t converts natural encoding into one-hot encoding\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nLatches; extern void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ); // set defaults nLatches = 5; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF ) { switch ( c ) { case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by a positive integer.\n" ); goto usage; } nLatches = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLatches < 0 ) goto usage; 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( 0, "The current network is combinational.\n" ); return 0; } // update the network Abc_NtkLatchPipe( pNtk, nLatches ); return 0; usage: Abc_Print( -2, "usage: pipe [-L num] [-h]\n" ); Abc_Print( -2, "\t inserts the given number of latches at each PI for pipelining\n" ); Abc_Print( -2, "\t-L num : the number of latches to insert [default = %d]\n", nLatches ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSeq( 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_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "The network has no latches.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Conversion to sequential AIG works only for combinational AIGs (run \"strash\").\n" ); return 1; } // get the new network // pNtkRes = Abc_NtkAigToSeq( pNtk ); pNtkRes = NULL; if ( pNtkRes == NULL ) { Abc_Print( -1, "Converting to sequential AIG has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: seq [-h]\n" ); Abc_Print( -2, "\t converts AIG into sequential AIG\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fShare; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fShare = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) { switch ( c ) { case 's': fShare ^= 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, "Conversion to combinational AIG works only for sequential AIG (run \"seq\").\n" ); return 1; } */ // share the latches on the fanout edges // if ( fShare ) // Seq_NtkShareFanouts(pNtk); // get the new network // pNtkRes = Abc_NtkSeqToLogicSop( pNtk ); pNtkRes = NULL; if ( pNtkRes == NULL ) { Abc_Print( -1, "Converting sequential AIG into an SOP logic network has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: unseq [-sh]\n" ); Abc_Print( -2, "\t converts sequential AIG into an SOP logic network\n" ); Abc_Print( -2, "\t-s : toggle sharing latches [default = %s]\n", fShare? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, nMaxIters; int fForward; int fBackward; int fOneStep; int fUseOldNames; int fVerbose; int Mode; int nDelayLim; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Mode = 5; nDelayLim = 0; fForward = 0; fBackward = 0; fOneStep = 0; fUseOldNames = 0; fVerbose = 0; nMaxIters = 15; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "MDfbsovh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" ); goto usage; } Mode = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Mode < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); goto usage; } nDelayLim = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDelayLim < 0 ) goto usage; break; case 'f': fForward ^= 1; break; case 'b': fBackward ^= 1; break; case 's': fOneStep ^= 1; break; case 'o': fUseOldNames ^= 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 ( fForward && fBackward ) { Abc_Print( -1, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" ); return 1; } if ( !Abc_NtkLatchNum(pNtk) ) { // Abc_Print( -1, "The network has no latches. Retiming is not performed.\n" ); return 0; } if ( Mode < 0 || Mode > 6 ) { Abc_Print( -1, "The mode (%d) is incorrect. Retiming is not performed.\n", Mode ); return 0; } if ( Abc_NtkIsStrash(pNtk) ) { if ( Abc_NtkGetChoiceNum(pNtk) ) { Abc_Print( -1, "Retiming with choice nodes is not implemented.\n" ); return 0; } // convert the network into an SOP network pNtkRes = Abc_NtkToLogic( pNtk ); // perform the retiming Abc_NtkRetime( pNtkRes, Mode, nDelayLim, fForward, fBackward, fOneStep, fUseOldNames, fVerbose ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; } // get the network in the SOP form if ( !Abc_NtkToSop(pNtk, -1, ABC_INFINITY) ) { Abc_Print( -1, "Converting to SOPs has failed.\n" ); return 0; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "The network is not a logic network. Retiming is not performed.\n" ); return 0; } // perform the retiming Abc_NtkRetime( pNtk, Mode, nDelayLim, fForward, fBackward, fOneStep, fUseOldNames, fVerbose ); return 0; usage: Abc_Print( -2, "usage: retime [-MD num] [-fbsovh]\n" ); Abc_Print( -2, "\t retimes the current network using one of the algorithms:\n" ); Abc_Print( -2, "\t 1: most forward retiming\n" ); Abc_Print( -2, "\t 2: most backward retiming\n" ); Abc_Print( -2, "\t 3: forward and backward min-area retiming\n" ); Abc_Print( -2, "\t 4: forward and backward min-delay retiming\n" ); Abc_Print( -2, "\t 5: mode 3 followed by mode 4\n" ); Abc_Print( -2, "\t 6: Pan's optimum-delay retiming using binary search\n" ); Abc_Print( -2, "\t-M num : the retiming algorithm to use [default = %d]\n", Mode ); Abc_Print( -2, "\t-D num : the minimum delay target (0=unused) [default = %d]\n", nDelayLim ); Abc_Print( -2, "\t-f : enables forward-only retiming in modes 3,4,5 [default = %s]\n", fForward? "yes": "no" ); Abc_Print( -2, "\t-b : enables backward-only retiming in modes 3,4,5 [default = %s]\n", fBackward? "yes": "no" ); Abc_Print( -2, "\t-s : enables retiming one step only in mode 4 [default = %s]\n", fOneStep? "yes": "no" ); Abc_Print( -2, "\t-o : enables usind old flop naming conventions [default = %s]\n", fUseOldNames? "yes": "no" ); Abc_Print( -2, "\t-v : enables verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; // Abc_Print( -2, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); // Abc_Print( -2, "\t-f : toggle forward retiming (for AIGs) [default = %s]\n", fForward? "yes": "no" ); // Abc_Print( -2, "\t-b : toggle backward retiming (for AIGs) [default = %s]\n", fBackward? "yes": "no" ); // Abc_Print( -2, "\t-i : toggle computation of initial state [default = %s]\n", fInitial? "yes": "no" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int fMinArea; int fForwardOnly; int fBackwardOnly; int fInitial; int nStepsMax; int fFastAlgo; int fVerbose; int c, nMaxIters; extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ); extern Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ); extern Abc_Ntk_t * Abc_NtkDarRetimeMinArea( Abc_Ntk_t * pNtk, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); extern Abc_Ntk_t * Abc_NtkDarRetimeMostFwd( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fMinArea = 1; fForwardOnly = 0; fBackwardOnly = 0; fInitial = 1; nStepsMax = 100000; fFastAlgo = 0; nMaxIters = 20; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NSmfbiavh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } nMaxIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nMaxIters < 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; } nStepsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nStepsMax < 0 ) goto usage; break; case 'm': fMinArea ^= 1; break; case 'f': fForwardOnly ^= 1; break; case 'b': fBackwardOnly ^= 1; break; case 'i': fInitial ^= 1; break; case 'a': fFastAlgo ^= 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) ) { // Abc_Print( -1, "The network has no latches. Retiming is not performed.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } // perform the retiming if ( fMinArea ) pNtkRes = Abc_NtkDarRetimeMinArea( pNtk, nMaxIters, fForwardOnly, fBackwardOnly, fInitial, fVerbose ); else if ( fFastAlgo ) pNtkRes = Abc_NtkDarRetime( pNtk, nStepsMax, fVerbose ); else // pNtkRes = Abc_NtkDarRetimeF( pNtk, nStepsMax, fVerbose ); pNtkRes = Abc_NtkDarRetimeMostFwd( pNtk, nMaxIters, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Retiming has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: dretime [-NS num] [-mfbiavh]\n" ); Abc_Print( -2, "\t new implementation of min-area (or most-forward) retiming\n" ); Abc_Print( -2, "\t-m : toggle min-area retiming and most-forward retiming [default = %s]\n", fMinArea? "min-area": "most-fwd" ); Abc_Print( -2, "\t-f : enables forward-only retiming [default = %s]\n", fForwardOnly? "yes": "no" ); Abc_Print( -2, "\t-b : enables backward-only retiming [default = %s]\n", fBackwardOnly? "yes": "no" ); Abc_Print( -2, "\t-i : enables init state computation [default = %s]\n", fInitial? "yes": "no" ); Abc_Print( -2, "\t-N num : the max number of one-frame iterations to perform [default = %d]\n", nMaxIters ); Abc_Print( -2, "\t-S num : the max number of forward retiming steps to perform [default = %d]\n", nStepsMax ); Abc_Print( -2, "\t-a : enables a fast most-forward algorithm [default = %s]\n", fFastAlgo? "yes": "no" ); Abc_Print( -2, "\t-v : enables 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_CommandFlowRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, nMaxIters; int fForward; int fBackward; int fVerbose; int fComputeInit, fGuaranteeInit, fBlockConst; int fFastButConservative; int maxDelay; extern Abc_Ntk_t* Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInit, int fGuaranteeInit, int fBlockConst, int fForward, int fBackward, int nMaxIters, int maxDelay, int fFastButConservative); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fForward = 0; fFastButConservative = 0; fBackward = 0; fComputeInit = 1; fGuaranteeInit = 0; fVerbose = 0; fBlockConst = 0; nMaxIters = 999; maxDelay = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "MDfcgbkivh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" ); goto usage; } nMaxIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nMaxIters < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); goto usage; } maxDelay = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( maxDelay < 0 ) goto usage; break; case 'f': fForward ^= 1; break; case 'c': fFastButConservative ^= 1; break; case 'i': fComputeInit ^= 1; break; case 'b': fBackward ^= 1; break; case 'g': fGuaranteeInit ^= 1; break; case 'k': fBlockConst ^= 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 ( fForward && fBackward ) { Abc_Print( -1, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" ); return 1; } if ( fGuaranteeInit && !fComputeInit ) { Abc_Print( -1, "Initial state guarantee (-g) requires initial state computation (-i).\n" ); return 1; } if ( !Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The network has no latches. Retiming is not performed.\n" ); return 0; } if ( Abc_NtkGetChoiceNum(pNtk) ) { Abc_Print( -1, "Retiming with choice nodes is not implemented.\n" ); return 0; } // perform the retiming pNtkRes = Abc_FlowRetime_MinReg( pNtk, fVerbose, fComputeInit, fGuaranteeInit, fBlockConst, fForward, fBackward, nMaxIters, maxDelay, fFastButConservative ); if (pNtkRes != pNtk) Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: fretime [-M num] [-D num] [-fbvih]\n" ); Abc_Print( -2, "\t retimes the current network using flow-based algorithm\n" ); Abc_Print( -2, "\t-M num : the maximum number of iterations [default = %d]\n", nMaxIters ); Abc_Print( -2, "\t-D num : the maximum delay [default = none]\n" ); Abc_Print( -2, "\t-i : enables init state computation [default = %s]\n", fComputeInit? "yes": "no" ); Abc_Print( -2, "\t-k : blocks retiming over const nodes [default = %s]\n", fBlockConst? "yes": "no" ); Abc_Print( -2, "\t-g : guarantees init state computation [default = %s]\n", fGuaranteeInit? "yes": "no" ); Abc_Print( -2, "\t-c : very fast (but conserv.) delay constraints [default = %s]\n", fFastButConservative? "yes": "no" ); Abc_Print( -2, "\t-f : enables forward-only retiming [default = %s]\n", fForward? "yes": "no" ); Abc_Print( -2, "\t-b : enables backward-only retiming [default = %s]\n", fBackward? "yes": "no" ); Abc_Print( -2, "\t-v : enables 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_CommandCRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fVerbose; extern Abc_Ntk_t * Abc_NtkCRetime( 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; } if ( Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Only works for logic networks.\n" ); return 1; } if ( !Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } // modify the current network pNtkRes = Abc_NtkCRetime( pNtk, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Sequential cleanup has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: cretime [-vh]\n" ); Abc_Print( -2, "\t performs most-forward retiming with equiv classes\n" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; int c, nMaxIters; int fVerbose; pNtk = Abc_FrameReadNtk(pAbc); // set defaults nMaxIters = 15; 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 a positive integer.\n" ); goto usage; } nMaxIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nMaxIters < 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_NtkHasAig(pNtk) ) { /* // quit if there are choice nodes if ( Abc_NtkGetChoiceNum(pNtk) ) { Abc_Print( -1, "Currently cannot map/retime networks with choice nodes.\n" ); return 0; } */ // if ( Abc_NtkIsStrash(pNtk) ) // pNtkNew = Abc_NtkAigToSeq(pNtk); // else // pNtkNew = Abc_NtkDup(pNtk); pNtkNew = NULL; } else { // strash and balance the network pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Strashing before FPGA mapping/retiming has failed.\n" ); return 1; } pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Balancing before FPGA mapping has failed.\n" ); return 1; } // convert into a sequential AIG // pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew ); pNtkNew = NULL; Abc_NtkDelete( pNtkRes ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Converting into a seq AIG before FPGA mapping/retiming has failed.\n" ); return 1; } Abc_Print( 1, "The network was strashed and balanced before FPGA mapping/retiming.\n" ); } // get the new network // pNtkRes = Seq_NtkFpgaMapRetime( pNtkNew, nMaxIters, fVerbose ); pNtkRes = NULL; if ( pNtkRes == NULL ) { // Abc_Print( -1, "Sequential FPGA mapping has failed.\n" ); Abc_NtkDelete( pNtkNew ); return 0; } Abc_NtkDelete( pNtkNew ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: sfpga [-I num] [-vh]\n" ); Abc_Print( -2, "\t performs integrated sequential FPGA mapping/retiming\n" ); Abc_Print( -2, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; int c, nMaxIters; int fVerbose; pNtk = Abc_FrameReadNtk(pAbc); // set defaults nMaxIters = 15; 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 a positive integer.\n" ); goto usage; } nMaxIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nMaxIters < 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_NtkHasAig(pNtk) ) { /* // quit if there are choice nodes if ( Abc_NtkGetChoiceNum(pNtk) ) { Abc_Print( -1, "Currently cannot map/retime networks with choice nodes.\n" ); return 0; } */ // if ( Abc_NtkIsStrash(pNtk) ) // pNtkNew = Abc_NtkAigToSeq(pNtk); // else // pNtkNew = Abc_NtkDup(pNtk); pNtkNew = NULL; } else { // strash and balance the network pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Strashing before SC mapping/retiming has failed.\n" ); return 1; } pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Balancing before SC mapping/retiming has failed.\n" ); return 1; } // convert into a sequential AIG // pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew ); pNtkNew = NULL; Abc_NtkDelete( pNtkRes ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Converting into a seq AIG before SC mapping/retiming has failed.\n" ); return 1; } Abc_Print( -1, "The network was strashed and balanced before SC mapping/retiming.\n" ); } // get the new network // pNtkRes = Seq_MapRetime( pNtkNew, nMaxIters, fVerbose ); pNtkRes = NULL; if ( pNtkRes == NULL ) { // Abc_Print( -1, "Sequential FPGA mapping has failed.\n" ); Abc_NtkDelete( pNtkNew ); return 0; } Abc_NtkDelete( pNtkNew ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: smap [-I num] [-vh]\n" ); Abc_Print( -2, "\t performs integrated sequential standard-cell mapping/retiming\n" ); Abc_Print( -2, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Fra_Ssw_t Pars, * pPars = &Pars; int c; extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, Fra_Ssw_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults pPars->nPartSize = 0; pPars->nOverSize = 0; pPars->nFramesP = 0; pPars->nFramesK = 1; pPars->nMaxImps = 5000; pPars->nMaxLevs = 0; pPars->fUseImps = 0; pPars->fRewrite = 0; pPars->fFraiging = 0; pPars->fLatchCorr = 0; pPars->fWriteImps = 0; pPars->fUse1Hot = 0; pPars->fVerbose = 0; pPars->TimeLimit = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PQNFILirfletvh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } pPars->nPartSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nPartSize < 2 ) 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->nOverSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nOverSize < 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->nFramesP = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesP < 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->nFramesK = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesK <= 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->nMaxImps = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxImps <= 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->nMaxLevs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxLevs <= 0 ) goto usage; break; case 'i': pPars->fUseImps ^= 1; break; case 'r': pPars->fRewrite ^= 1; break; case 'f': pPars->fFraiging ^= 1; break; case 'l': pPars->fLatchCorr ^= 1; break; case 'e': pPars->fWriteImps ^= 1; break; case 't': pPars->fUse1Hot ^= 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_NtkIsComb(pNtk) ) { Abc_Print( -1, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } if ( pPars->nFramesK > 1 && pPars->fUse1Hot ) { Abc_Print( -1, "Currrently can only use one-hotness for simple induction (K=1).\n" ); return 0; } if ( pPars->nFramesP && pPars->fUse1Hot ) { Abc_Print( -1, "Currrently can only use one-hotness without prefix.\n" ); return 0; } // get the new network pNtkRes = Abc_NtkDarSeqSweep( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Sequential sweeping has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: ssweep [-PQNFL ] [-lrfetvh]\n" ); Abc_Print( -2, "\t performs sequential sweep using K-step induction\n" ); Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); Abc_Print( -2, "\t-N num : number of time frames to use as the prefix [default = %d]\n", pPars->nFramesP ); Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", pPars->nFramesK ); Abc_Print( -2, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", pPars->nMaxLevs ); // Abc_Print( -2, "\t-I num : max number of implications to consider [default = %d]\n", pPars->nMaxImps ); // Abc_Print( -2, "\t-i : toggle using implications [default = %s]\n", pPars->fUseImps? "yes": "no" ); Abc_Print( -2, "\t-l : toggle latch correspondence only [default = %s]\n", pPars->fLatchCorr? "yes": "no" ); Abc_Print( -2, "\t-r : toggle AIG rewriting [default = %s]\n", pPars->fRewrite? "yes": "no" ); Abc_Print( -2, "\t-f : toggle fraiging (combinational SAT sweeping) [default = %s]\n", pPars->fFraiging? "yes": "no" ); Abc_Print( -2, "\t-e : toggle writing implications as assertions [default = %s]\n", pPars->fWriteImps? "yes": "no" ); Abc_Print( -2, "\t-t : toggle using one-hotness conditions [default = %s]\n", pPars->fUse1Hot? "yes": "no" ); Abc_Print( -2, "\t-v : toggle 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_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Ssw_Pars_t Pars, * pPars = &Pars; int nConstrs = 0; int c; extern Abc_Ntk_t * Abc_NtkDarSeqSweep2( Abc_Ntk_t * pNtk, Ssw_Pars_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults Ssw_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNcmplkofdseqvwh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } pPars->nPartSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nPartSize < 2 ) 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->nOverSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nOverSize < 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->nFramesK = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesK <= 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 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } pPars->nMaxLevs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxLevs <= 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->nFramesAddSim = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesAddSim < 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->nItersStop = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nItersStop < 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->nSatVarMax2 = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nSatVarMax2 < 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->nRecycleCalls2 = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRecycleCalls2 < 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; } nConstrs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConstrs < 0 ) goto usage; break; case 'c': pPars->fConstrs ^= 1; break; case 'm': pPars->fMergeFull ^= 1; break; case 'p': pPars->fPolarFlip ^= 1; break; case 'l': pPars->fLatchCorr ^= 1; break; case 'k': pPars->fConstCorr ^= 1; break; case 'o': pPars->fOutputCorr ^= 1; break; case 'f': pPars->fSemiFormal ^= 1; break; case 'd': pPars->fDynamic ^= 1; break; case 's': pPars->fLocalSim ^= 1; break; case 'e': pPars->fEquivDump ^= 1; break; case 'q': pPars->fStopWhenGone ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fFlopVerbose ^= 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( 0, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( 0, "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } if ( Abc_NtkPiNum(pNtk) == 0 ) { Abc_Print( 0, "This command works only for designs with primary inputs.\n" ); return 0; } // if constraints are to be used, network should have no constraints if ( nConstrs > 0 ) { if ( Abc_NtkConstrNum(pNtk) > 0 ) { Abc_Print( -1, "The network already has %d constraints.\n", Abc_NtkConstrNum(pNtk) ); return 0; } else { Abc_Print( 0, "Setting the number of constraints to be %d.\n", nConstrs ); pNtk->nConstrs = nConstrs; } } if ( pPars->fConstrs ) { if ( Abc_NtkConstrNum(pNtk) > 0 ) Abc_Print( 0, "Performing scorr with %d constraints.\n", Abc_NtkConstrNum(pNtk) ); else Abc_Print( 0, "Performing constraint-based scorr without constraints.\n" ); } // get the new network pNtkRes = Abc_NtkDarSeqSweep2( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Sequential sweeping has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: scorr [-PQFCLSIVMN ] [-cmplkodseqvwh]\n" ); Abc_Print( -2, "\t performs sequential sweep using K-step induction\n" ); Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", pPars->nFramesK ); Abc_Print( -2, "\t-C num : max number of conflicts at a node (0=inifinite) [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", pPars->nMaxLevs ); Abc_Print( -2, "\t-N num : number of last POs treated as constraints (0=none) [default = %d]\n", pPars->fConstrs ); Abc_Print( -2, "\t-S num : additional simulation frames for c-examples (0=none) [default = %d]\n", pPars->nFramesAddSim ); Abc_Print( -2, "\t-I num : iteration number to stop and output SR-model (-1=none) [default = %d]\n", pPars->nItersStop ); Abc_Print( -2, "\t-V num : min var num needed to recycle the SAT solver [default = %d]\n", pPars->nSatVarMax2 ); Abc_Print( -2, "\t-M num : min call num needed to recycle the SAT solver [default = %d]\n", pPars->nRecycleCalls2 ); Abc_Print( -2, "\t-N num : set last POs to be constraints (use with -c) [default = %d]\n", nConstrs ); Abc_Print( -2, "\t-c : toggle using explicit constraints [default = %s]\n", pPars->fConstrs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle full merge if constraints are present [default = %s]\n", pPars->fMergeFull? "yes": "no" ); Abc_Print( -2, "\t-p : toggle aligning polarity of SAT variables [default = %s]\n", pPars->fPolarFlip? "yes": "no" ); Abc_Print( -2, "\t-l : toggle doing latch correspondence [default = %s]\n", pPars->fLatchCorr? "yes": "no" ); Abc_Print( -2, "\t-k : toggle doing constant correspondence [default = %s]\n", pPars->fConstCorr? "yes": "no" ); Abc_Print( -2, "\t-o : toggle doing \'PO correspondence\' [default = %s]\n", pPars->fOutputCorr? "yes": "no" ); // Abc_Print( -2, "\t-f : toggle filtering using iterative BMC [default = %s]\n", pPars->fSemiFormal? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dynamic addition of constraints [default = %s]\n", pPars->fDynamic? "yes": "no" ); Abc_Print( -2, "\t-s : toggle local simulation in the cone of influence [default = %s]\n", pPars->fLocalSim? "yes": "no" ); Abc_Print( -2, "\t-e : toggle dumping disproved internal equivalences [default = %s]\n", pPars->fEquivDump? "yes": "no" ); Abc_Print( -2, "\t-q : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printout of flop equivalences [default = %s]\n", pPars->fFlopVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle 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_CommandTestSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileName; Fra_Ssw_t Pars, * pPars = &Pars; int c; // extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, Fra_Ssw_t * pPars ); extern int Fra_FraigInductionTest( char * pFileName, Fra_Ssw_t * pParams ); // set defaults pPars->nPartSize = 0; pPars->nOverSize = 0; pPars->nFramesP = 0; pPars->nFramesK = 1; pPars->nMaxImps = 5000; pPars->nMaxLevs = 0; pPars->fUseImps = 0; pPars->fRewrite = 0; pPars->fFraiging = 0; pPars->fLatchCorr = 0; pPars->fWriteImps = 0; pPars->fUse1Hot = 0; pPars->fVerbose = 0; pPars->TimeLimit = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PQNFILirfletvh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } pPars->nPartSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nPartSize < 2 ) 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->nOverSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nOverSize < 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->nFramesP = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesP < 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->nFramesK = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesK <= 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->nMaxImps = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxImps <= 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->nMaxLevs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxLevs <= 0 ) goto usage; break; case 'i': pPars->fUseImps ^= 1; break; case 'r': pPars->fRewrite ^= 1; break; case 'f': pPars->fFraiging ^= 1; break; case 'l': pPars->fLatchCorr ^= 1; break; case 'e': pPars->fWriteImps ^= 1; break; case 't': pPars->fUse1Hot ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } // get the input file name if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; else { Abc_Print( -1, "File name should be given on the command line.\n" ); return 1; } Fra_FraigInductionTest( pFileName, pPars ); return 0; usage: Abc_Print( -2, "usage: testssw [-PQNFL num] [-lrfetvh] \n" ); Abc_Print( -2, "\t performs sequential sweep using K-step induction\n" ); Abc_Print( -2, "\t (outputs a file with a set of pairs of equivalent nodes)\n" ); Abc_Print( -2, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); Abc_Print( -2, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); Abc_Print( -2, "\t-N num : number of time frames to use as the prefix [default = %d]\n", pPars->nFramesP ); Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", pPars->nFramesK ); Abc_Print( -2, "\t-L num : max number of levels to consider (0=all) [default = %d]\n", pPars->nMaxLevs ); // Abc_Print( -2, "\t-I num : max number of implications to consider [default = %d]\n", pPars->nMaxImps ); // Abc_Print( -2, "\t-i : toggle using implications [default = %s]\n", pPars->fUseImps? "yes": "no" ); Abc_Print( -2, "\t-l : toggle latch correspondence only [default = %s]\n", pPars->fLatchCorr? "yes": "no" ); Abc_Print( -2, "\t-r : toggle AIG rewriting [default = %s]\n", pPars->fRewrite? "yes": "no" ); Abc_Print( -2, "\t-f : toggle fraiging (combinational SAT sweeping) [default = %s]\n", pPars->fFraiging? "yes": "no" ); Abc_Print( -2, "\t-e : toggle writing implications as assertions [default = %s]\n", pPars->fWriteImps? "yes": "no" ); Abc_Print( -2, "\t-t : toggle using one-hotness conditions [default = %s]\n", pPars->fUse1Hot? "yes": "no" ); Abc_Print( -2, "\t-v : toggle 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_CommandTestScorr( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkTestScorr( char * pFileNameIn, char * pFileNameOut, int nStepsMax, int nBTLimit, int fNewAlgo, int fFlopOnly, int fFfNdOnly, int fVerbose ); Abc_Ntk_t * pNtkRes; int c; int nConfMax; int nStepsMax; int fNewAlgo; int fFlopOnly; int fFfNdOnly; int fVerbose; // set defaults nConfMax = 100; nStepsMax = -1; fNewAlgo = 0; fFlopOnly = 0; fFfNdOnly = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CSnfsvh" ) ) != 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 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } nStepsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nStepsMax < 0 ) goto usage; break; case 'n': fNewAlgo ^= 1; break; case 'f': fFlopOnly ^= 1; break; case 's': fFfNdOnly ^= 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; } if ( fFlopOnly && fFfNdOnly ) { Abc_Print( -1, "These two options (-f and -s) are incompatible.\n" ); goto usage; } // get the new network pNtkRes = Abc_NtkTestScorr( argv[globalUtilOptind], argv[globalUtilOptind+1], nStepsMax, nConfMax, fNewAlgo, fFlopOnly, fFfNdOnly, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Sequential sweeping has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: testscorr [-CS num] [-nfsvh] \n" ); Abc_Print( -2, "\t outputs the list of sequential equivalences into a file\n" ); Abc_Print( -2, "\t (if is in BENCH, init state file should be the same directory)\n" ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-S num : limit on refinement iterations (-1=no limit, 0=after BMC, etc) [default = %d]\n", nStepsMax ); Abc_Print( -2, "\t-n : toggle between \"scorr\" and \"&scorr\" [default = %s]\n", fNewAlgo? "&scorr": "scorr" ); Abc_Print( -2, "\t-f : toggle reporting only flop/flop equivs [default = %s]\n", fFlopOnly? "yes": "no" ); Abc_Print( -2, "\t-s : toggle reporting only flop/flop and flop/node equivs [default = %s]\n", fFfNdOnly? "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 for sequential equivalence computation\n"); Abc_Print( -2, "\t : output file with the list of pairs of equivalent signals\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int nFramesP; int nConfMax; int nVarsMax; int fNewAlgor; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ); extern Abc_Ntk_t * Abc_NtkDarLcorrNew( Abc_Ntk_t * pNtk, int nVarsMax, int nConfMax, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nFramesP = 0; nConfMax = 1000; nVarsMax = 1000; fNewAlgor = 1; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PCSnvh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nFramesP = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFramesP < 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; } nConfMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfMax < 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; } nVarsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVarsMax < 0 ) goto usage; break; case 'n': fNewAlgor ^= 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, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } // get the new network if ( fNewAlgor ) pNtkRes = Abc_NtkDarLcorrNew( pNtk, nVarsMax, nConfMax, fVerbose ); else pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Sequential sweeping has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: lcorr [-PCS num] [-nvh]\n" ); Abc_Print( -2, "\t computes latch correspondence using 1-step induction\n" ); Abc_Print( -2, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", nVarsMax ); Abc_Print( -2, "\t-n : toggle using new algorithm [default = %s]\n", fNewAlgor? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fLatchConst = 1; int fLatchEqual = 1; int fSaveNames = 1; int fUseMvSweep = 0; int nFramesSymb = 1; int nFramesSatur = 512; int fVerbose = 0; int fVeryVerbose = 0; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cenmFSvwh" ) ) != EOF ) { switch ( c ) { case 'c': fLatchConst ^= 1; break; case 'e': fLatchEqual ^= 1; break; case 'n': fSaveNames ^= 1; break; case 'm': fUseMvSweep ^= 1; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFramesSymb = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFramesSymb < 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; } nFramesSatur = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFramesSatur < 0 ) goto usage; 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 works for structrally hashed networks.\n" ); return 1; } if ( !Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } // modify the current network pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchConst, fLatchEqual, fSaveNames, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Sequential cleanup has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: scleanup [-cenmFSvwh]\n" ); Abc_Print( -2, "\t performs sequential cleanup of the current network\n" ); Abc_Print( -2, "\t by removing nodes and latches that do not feed into POs\n" ); Abc_Print( -2, "\t-c : sweep stuck-at latches detected by ternary simulation [default = %s]\n", fLatchConst? "yes": "no" ); Abc_Print( -2, "\t-e : merge equal latches (same data inputs and init states) [default = %s]\n", fLatchEqual? "yes": "no" ); Abc_Print( -2, "\t-n : toggle preserving latch names [default = %s]\n", fSaveNames? "yes": "no" ); Abc_Print( -2, "\t-m : toggle using hybrid ternary/symbolic simulation [default = %s]\n", fUseMvSweep? "yes": "no" ); Abc_Print( -2, "\t-F num : the number of first frames simulated symbolically [default = %d]\n", nFramesSymb ); Abc_Print( -2, "\t-S num : the number of frames when symbolic saturation begins [default = %d]\n", nFramesSatur ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle very verbose output [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_CommandCycle( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nFrames; int fUseXval; int fVerbose; extern void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fUseXval, int fVerbose ); extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); // set defaults nFrames = 100; fUseXval = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fxvh" ) ) != 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 'x': fUseXval ^= 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_NtkIsSopLogic(pNtk) ) { Abc_Print( -1, "Only works for strashed networks or logic SOP networks.\n" ); return 1; } if ( !Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( fUseXval && !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "X-valued simulation only works for AIGs. Run \"strash\".\n" ); return 0; } if ( fUseXval ) Abc_NtkCycleInitState( pNtk, nFrames, 1, fVerbose ); else if ( Abc_NtkIsStrash(pNtk) ) Abc_NtkCycleInitState( pNtk, nFrames, 0, fVerbose ); else Abc_NtkCycleInitStateSop( pNtk, nFrames, fVerbose ); return 0; usage: Abc_Print( -2, "usage: cycle [-F num] [-xvh]\n" ); Abc_Print( -2, "\t cycles sequential circuit for the given number of timeframes\n" ); Abc_Print( -2, "\t to derive a new initial state (which may be on the envelope)\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); Abc_Print( -2, "\t-x : use x-valued primary inputs [default = %s]\n", fUseXval? "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_CommandXsim( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nFrames; int fXInputs; int fXState; int fVerbose; extern void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose ); // set defaults nFrames = 10; fXInputs = 0; fXState = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fisvh" ) ) != 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': fXInputs ^= 1; break; case 's': fXState ^= 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; } if ( !Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } Abc_NtkXValueSimulate( pNtk, nFrames, fXInputs, fXState, fVerbose ); return 0; usage: Abc_Print( -2, "usage: xsim [-F num] [-isvh]\n" ); Abc_Print( -2, "\t performs X-valued simulation of the AIG\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); Abc_Print( -2, "\t-i : toggle X-valued representation of inputs [default = %s]\n", fXInputs? "yes": "no" ); Abc_Print( -2, "\t-s : toggle X-valued representation of state [default = %s]\n", fXState? "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_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fNew; int fComb; int nFrames; int nWords; int TimeOut; int fMiter; int fVerbose; char * pFileSim; extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fMiter, int fVerbose, char * pFileSim ); // set defaults fNew = 0; fComb = 0; nFrames = 32; nWords = 8; TimeOut = 30; fMiter = 1; fVerbose = 0; pFileSim = NULL; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FWTAnmvh" ) ) != 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 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nWords < 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } TimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( TimeOut < 0 ) goto usage; break; case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" ); goto usage; } pFileSim = argv[globalUtilOptind]; globalUtilOptind++; break; case 'n': fNew ^= 1; break; case 'm': fMiter ^= 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; } if ( pFileSim != NULL && Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "Currently simulation with user-specified patterns works only for comb miters.\n" ); return 1; } ABC_FREE( pNtk->pSeqModel ); pAbc->Status = Abc_NtkDarSeqSim( pNtk, nFrames, nWords, TimeOut, fNew, fMiter, fVerbose, pFileSim ); Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); return 0; usage: Abc_Print( -2, "usage: sim [-FWT num] [-A file] [-nmvh]\n" ); Abc_Print( -2, "\t performs random simulation of the sequential miter\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", TimeOut ); Abc_Print( -2, "\t-A file : text file name with user's patterns [default = random simulation]\n" ); Abc_Print( -2, "\t (patterns are listed, one per line, as sequences of 0s and 1s)\n" ); Abc_Print( -2, "\t-n : toggle new vs. old implementation [default = %s]\n", fNew? "new": "old" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", fMiter? "miter": "circuit" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSim3( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NtkDarSeqSim3( Abc_Ntk_t * pNtk, Ssw_RarPars_t * pPars ); Ssw_RarPars_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc); Vec_Ptr_t * vSeqModelVec; int c; Ssw_RarSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FWBRSNTGadivzh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 0 ) goto usage; break; case '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 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); goto usage; } pPars->nBinSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBinSize < 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->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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->nRestart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRestart < 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->nRandSeed = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRandSeed < 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->TimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOut < 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; } pPars->TimeOutGap = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOutGap < 0 ) goto usage; break; case 'a': pPars->fSolveAll ^= 1; break; case 'd': pPars->fDropSatOuts ^= 1; break; case 'i': pPars->fSetLastState ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'z': pPars->fNotVerbose ^= 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; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "Only works for sequential networks.\n" ); return 1; } ABC_FREE( pNtk->pSeqModel ); pAbc->Status = Abc_NtkDarSeqSim3( pNtk, pPars ); Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); vSeqModelVec = pNtk->vSeqModelVec; pNtk->vSeqModelVec = NULL; if ( pPars->fSetLastState && pAbc->pNtkCur->pData ) { Abc_Obj_t * pObj; Vec_Int_t * vInit = (Vec_Int_t *)pAbc->pNtkCur->pData; pAbc->pNtkCur->pData = NULL; Abc_NtkForEachLatch( pAbc->pNtkCur, pObj, c ) if ( Vec_IntEntry(vInit, c) ) Abc_LatchSetInit1( pObj ); Vec_IntFree( vInit ); pNtkRes = Abc_NtkRestrashZero( pAbc->pNtkCur, 0 ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Removing SAT outputs has failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); pNtk = Abc_FrameReadNtk(pAbc); } if ( pPars->fSolveAll && pPars->fDropSatOuts ) { if ( vSeqModelVec == NULL ) Abc_Print( 1,"The array of counter-examples is not available.\n" ); else if ( Vec_PtrSize(vSeqModelVec) != Abc_NtkPoNum(pNtk) ) Abc_Print( 1,"The array size does not match the number of outputs.\n" ); else { extern void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose ); Abc_NtkDropSatOutputs( pNtk, vSeqModelVec, pPars->fVerbose ); 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 ); } } if ( vSeqModelVec ) { Abc_FrameReplaceCexVec( pAbc, &vSeqModelVec ); pAbc->nFrames = -1; } return 0; usage: Abc_Print( -2, "usage: sim3 [-FWBRSNTG num] [-advzh]\n" ); Abc_Print( -2, "\t performs random simulation of the sequential miter\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-B num : the number of flops in one bin [default = %d]\n", pPars->nBinSize ); Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-S num : the number of rounds before a restart [default = %d]\n", pPars->nRestart ); Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n", pPars->nRandSeed ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeOut ); Abc_Print( -2, "\t-G num : approximate runtime gap in seconds since the last CEX [default = %d]\n", pPars->TimeOutGap ); Abc_Print( -2, "\t-a : toggle solving all outputs (do not stop when one is SAT) [default = %s]\n", pPars->fSolveAll? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dropping (replacing by 0) SAT outputs [default = %s]\n", pPars->fDropSatOuts? "yes": "no" ); Abc_Print( -2, "\t-i : toggle changing init state to a last rare state [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-z : toggle suppressing report about solved outputs [default = %s]\n", pPars->fNotVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDarPhase( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int nFrames, nPref; int fIgnore; int fPrint; int fUpdateCex; int c, fVerbose; extern Abc_Ntk_t * Abc_NtkPhaseAbstract( Abc_Ntk_t * pNtk, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nFrames = 0; nPref = 0; fIgnore = 0; fPrint = 0; fUpdateCex = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FPipcvh" ) ) != 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 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nPref = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPref < 0 ) goto usage; break; case 'i': fIgnore ^= 1; break; case 'p': fPrint ^= 1; break; case 'c': fUpdateCex ^= 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 structrally hashed networks.\n" ); return 1; } if ( fUpdateCex ) { Abc_Cex_t * pCexNew; if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Counter-example is not available.\n" ); return 1; } if ( pAbc->pCex->nPis % Abc_NtkPiNum(pNtk) != 0 ) { Abc_Print( -1, "PI count of the CEX is not a multiple of PI count of the current AIG.\n" ); return 1; } pCexNew = Abc_CexTransformPhase( pAbc->pCex, Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkLatchNum(pNtk) ); { Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); Gia_Man_t * pGia = Gia_ManFromAig( pAig ); int iPo = Gia_ManSetFailedPoCex( pGia, pCexNew ); Gia_ManStop( pGia ); Aig_ManStop( pAig ); if ( iPo == -1 ) { Abc_Print( -1, "The counter-example does not fail any of the outputs of the original AIG.\n" ); return 1; } } Abc_FrameReplaceCex( pAbc, &pCexNew ); return 0; } if ( !Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( fPrint ) { Abc_NtkPhaseAbstract( pNtk, 0, nPref, fIgnore, 1, fVerbose ); return 0; } // modify the current network pNtkRes = Abc_NtkPhaseAbstract( pNtk, nFrames, nPref, fIgnore, 0, fVerbose ); if ( pNtkRes == NULL ) { // Abc_Print( -1, "Phase abstraction has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: phase [-FP ] [-ipcvh]\n" ); Abc_Print( -2, "\t performs sequential cleanup of the current network\n" ); Abc_Print( -2, "\t by removing nodes and latches that do not feed into POs\n" ); Abc_Print( -2, "\t-F num : the number of frames to abstract [default = %d]\n", nFrames ); Abc_Print( -2, "\t-P num : the number of prefix frames to skip [default = %d]\n", nPref ); Abc_Print( -2, "\t-i : toggle ignoring the initial state [default = %s]\n", fIgnore? "yes": "no" ); Abc_Print( -2, "\t-p : toggle printing statistics about generators [default = %s]\n", fPrint? "yes": "no" ); Abc_Print( -2, "\t-c : update the current CEX derived for a new AIG after \"phase\"\n" ); Abc_Print( -2, "\t to match the current AIG (the one before \"phase\") [default = %s]\n", fUpdateCex? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSynch( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtkRes, * pNtk1, * pNtk2, * pNtk; char ** pArgvNew; int nArgcNew; int fDelete1, fDelete2; int c; int nWords; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarSynch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nWords, int fVerbose ); extern Abc_Ntk_t * Abc_NtkDarSynchOne( Abc_Ntk_t * pNtk, int nWords, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nWords = 32; fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Wvh" ) ) != EOF ) { switch ( c ) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nWords <= 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew == 0 ) { if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } pNtkRes = Abc_NtkDarSynchOne( pNtk, nWords, fVerbose ); } else { if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) { if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The network has no latches..\n" ); return 0; } // modify the current network pNtkRes = Abc_NtkDarSynch( pNtk1, pNtk2, nWords, fVerbose ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); } if ( pNtkRes == NULL ) { Abc_Print( -1, "Synchronization has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: synch [-W ] [-vh] \n" ); Abc_Print( -2, "\t derives and applies synchronization sequence\n" ); Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", nWords ); 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, "\tfile1 : (optional) the file with the first design\n"); Abc_Print( -2, "\tfile2 : (optional) the file with the second design\n\n"); Abc_Print( -2, "\t If no designs are given on the command line,\n" ); Abc_Print( -2, "\t assumes the current network has no initial state,\n" ); Abc_Print( -2, "\t derives synchronization sequence and applies it.\n\n" ); Abc_Print( -2, "\t If two designs are given on the command line\n" ); Abc_Print( -2, "\t assumes both of them have no initial state,\n" ); Abc_Print( -2, "\t derives sequences for both designs, synchorinizes\n" ); Abc_Print( -2, "\t them, and creates SEC miter comparing two designs.\n\n" ); Abc_Print( -2, "\t If only one design is given on the command line,\n" ); Abc_Print( -2, "\t considers the second design to be the current network,\n" ); Abc_Print( -2, "\t and derives SEC miter for them, as described above.\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandClockGate( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cgt_Par_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtkRes, * pNtk, * pNtkCare; int c; extern Abc_Ntk_t * Abc_NtkDarClockGate( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, Cgt_Par_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults Cgt_SetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "LNDCVKavwh" ) ) != EOF ) { switch ( c ) { case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } pPars->nLevelMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLevelMax <= 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->nCandMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCandMax <= 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->nOdcMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nOdcMax <= 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->nConfMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nConfMax <= 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->nVarsMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVarsMin <= 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->nFlopsMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFlopsMin <= 0 ) goto usage; break; case 'a': pPars->fAreaOnly ^= 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 ( argc == globalUtilOptind + 1 ) { pNtkCare = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1, 0 ); if ( pNtkCare == NULL ) { Abc_Print( -1, "Reading care network has failed.\n" ); return 1; } // modify the current network pNtkRes = Abc_NtkDarClockGate( pNtk, pNtkCare, pPars ); Abc_NtkDelete( pNtkCare ); } else if ( argc == globalUtilOptind ) { pNtkRes = Abc_NtkDarClockGate( pNtk, NULL, pPars ); } else { Abc_Print( -1, "Wrong number of arguments.\n" ); return 0; } if ( pNtkRes == NULL ) { Abc_Print( -1, "Clock gating has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: clockgate [-LNDCVK ] [-avwh] \n" ); Abc_Print( -2, "\t sequential clock gating with observability don't-cares\n" ); Abc_Print( -2, "\t-L num : max level number of a clock gate [default = %d]\n", pPars->nLevelMax ); Abc_Print( -2, "\t-N num : max number of candidates for a flop [default = %d]\n", pPars->nCandMax ); Abc_Print( -2, "\t-D num : max number of ODC levels to consider [default = %d]\n", pPars->nOdcMax ); Abc_Print( -2, "\t-C num : max number of conflicts at a node [default = %d]\n", pPars->nConfMax ); Abc_Print( -2, "\t-V num : min number of vars to recycle SAT solver [default = %d]\n", pPars->nVarsMin ); Abc_Print( -2, "\t-K num : min number of flops to recycle SAT solver [default = %d]\n", pPars->nFlopsMin ); Abc_Print( -2, "\t-a : toggle minimizing area-only [default = %s]\n", pPars->fAreaOnly? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle even more detailed output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tfile : (optional) constraints for primary inputs and register outputs\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandExtWin( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtkRes, * pNtk; int c; int nObjId; int nDist; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarExtWin( Abc_Ntk_t * pNtk, int nObjId, int nDist, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nObjId = -1; nDist = 5; 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; } nObjId = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nObjId <= 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; } nDist = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDist <= 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, "Only works for structrally hashed networks.\n" ); return 1; } if ( argc != globalUtilOptind ) { Abc_Print( -1, "Not enough command-line arguments.\n" ); return 1; } // modify the current network pNtkRes = Abc_NtkDarExtWin( pNtk, nObjId, nDist, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Extracting sequential window has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: extwin [-ND ] [-vh]\n" ); Abc_Print( -2, "\t extracts sequential window from the AIG\n" ); Abc_Print( -2, "\t-N num : the ID of the object to use as the center [default = %d]\n", nObjId ); Abc_Print( -2, "\t-D num : the \"radius\" of the window [default = %d]\n", nDist ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandInsWin( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtkRes, * pNtk, * pNtkCare; int c; int nObjId; int nDist; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarInsWin( Abc_Ntk_t * pNtk, Abc_Ntk_t * pWnd, int nObjId, int nDist, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nObjId = -1; nDist = 5; 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; } nObjId = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nObjId <= 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; } nDist = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDist <= 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, "Only works for structrally hashed networks.\n" ); return 1; } if ( argc != globalUtilOptind + 1 ) { Abc_Print( -1, "Not enough command-line arguments.\n" ); return 1; } pNtkCare = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1, 0 ); if ( pNtkCare == NULL ) { Abc_Print( -1, "Reading care network has failed.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtkCare) ) { Abc_Ntk_t * pNtkTemp; pNtkCare = Abc_NtkStrash( pNtkTemp = pNtkCare, 0, 1, 0 ); Abc_NtkDelete( pNtkTemp ); } // modify the current network pNtkRes = Abc_NtkDarInsWin( pNtk, pNtkCare, nObjId, nDist, fVerbose ); Abc_NtkDelete( pNtkCare ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Inserting sequential window has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: inswin [-ND ] [-vh] \n" ); Abc_Print( -2, "\t inserts sequential window into the AIG\n" ); Abc_Print( -2, "\t-N num : the ID of the object to use as the center [default = %d]\n", nObjId ); Abc_Print( -2, "\t-D num : the \"radius\" of the window [default = %d]\n", nDist ); 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 : file with the AIG to be inserted\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPermute( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkRestrashRandom( Abc_Ntk_t * pNtk ); extern void Abc_NtkPermutePiUsingFanout( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pNtk = pAbc->pNtkCur, * pNtkRes = NULL; char * pFlopPermFile = NULL; int fInputs = 1; int fOutputs = 1; int fFlops = 1; int fNodes = 1; int fFanout = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fiofnxh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); goto usage; } pFlopPermFile = argv[globalUtilOptind]; globalUtilOptind++; break; case 'i': fInputs ^= 1; break; case 'o': fOutputs ^= 1; break; case 'f': fFlops ^= 1; break; case 'n': fNodes ^= 1; break; case 'x': fFanout ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( fFanout ) { if ( Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "Currently \"permute -x\" works only for combinational networks.\n" ); return 1; } Abc_NtkPermutePiUsingFanout( pNtk ); return 0; } if ( fNodes && !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "To permute nodes, the network should be structurally hashed.\n" ); return 1; } if ( fNodes ) pNtkRes = Abc_NtkRestrashRandom( pNtk ); else pNtkRes = Abc_NtkDup( pNtk ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command \"permute\" has failed.\n" ); return 1; } Abc_NtkPermute( pNtkRes, fInputs, fOutputs, fFlops, pFlopPermFile ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: permute [-iofnxh] [-F filename]\n" ); Abc_Print( -2, "\t performs random permutation of inputs/outputs/flops\n" ); Abc_Print( -2, "\t-i : toggle permuting primary inputs [default = %s]\n", fInputs? "yes": "no" ); Abc_Print( -2, "\t-o : toggle permuting primary outputs [default = %s]\n", fOutputs? "yes": "no" ); Abc_Print( -2, "\t-f : toggle permuting flip-flops [default = %s]\n", fFlops? "yes": "no" ); Abc_Print( -2, "\t-n : toggle deriving new topological ordering of nodes [default = %s]\n", fNodes? "yes": "no" ); Abc_Print( -2, "\t-x : toggle permuting inputs based on their fanout count [default = %s]\n", fFanout? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t-F : (optional) file with the flop permutation\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandUnpermute( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = pAbc->pNtkCur, * pNtkRes = NULL; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } pNtkRes = Abc_NtkDup( pNtk ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command \"unpermute\" has failed.\n" ); return 1; } Abc_NtkUnpermute( pNtkRes ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: unpermute [-h]\n" ); Abc_Print( -2, "\t restores inputs/outputs/flops before the last permutation\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCubeEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_EnumerateCubeStates(); extern void Abc_EnumerateCubeStatesZdd(); int c, fZddAlgo = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "zvh" ) ) != EOF ) { switch ( c ) { case 'z': fZddAlgo ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( fZddAlgo ) Abc_EnumerateCubeStatesZdd(); else Abc_EnumerateCubeStates(); return 0; usage: Abc_Print( -2, "usage: cubeenum [-vh]\n" ); Abc_Print( -2, "\t enumerates reachable states of 2x2x2 cube\n" ); Abc_Print( -2, "\t (http://en.wikipedia.org/wiki/Pocket_Cube)\n" ); Abc_Print( -2, "\t-z : toggle using ZDD-based algorithm [default = %s]\n", fZddAlgo? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[16]; Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; int fDelete1, fDelete2; char ** pArgvNew; int nArgcNew; int c; int fSat; int fVerbose; int nSeconds; int nPartSize; int nConfLimit; int nInsLimit; int fPartition; int fIgnoreNames; extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ); extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fSat = 0; fVerbose = 0; nSeconds = 20; nPartSize = 0; nConfLimit = 10000; nInsLimit = 0; fPartition = 0; fIgnoreNames = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsnvh" ) ) != EOF ) { switch ( c ) { case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } nSeconds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSeconds < 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 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nInsLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nInsLimit < 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; } nPartSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPartSize < 0 ) goto usage; break; case 'p': fPartition ^= 1; break; case 's': fSat ^= 1; break; case 'n': fIgnoreNames ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } if ( pNtk && pNtk->vPhases != NULL ) { Abc_Print( -1, "Cannot compare networks with phases defined.\n" ); return 1; } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) 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 ); } // perform equivalence checking if ( fPartition ) Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose ); else if ( nPartSize ) Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose ); else if ( fSat ) Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit ); else Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 0; usage: if ( nPartSize == 0 ) strcpy( Buffer, "unused" ); else sprintf(Buffer, "%d", nPartSize ); Abc_Print( -2, "usage: cec [-T num] [-C num] [-I num] [-P num] [-psnvh] \n" ); Abc_Print( -2, "\t performs combinational equivalence checking\n" ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit ); Abc_Print( -2, "\t-P num : partition size for multi-output networks [default = %s]\n", Buffer ); Abc_Print( -2, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" ); Abc_Print( -2, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); Abc_Print( -2, "\t-n : toggle how CIs/COs are matched (by name or by order) [default = %s]\n", fIgnoreNames? "by order": "by name" ); 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, "\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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDCec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; int fDelete1, fDelete2; char ** pArgvNew; int nArgcNew; int c; int fSat; int fVerbose; int nSeconds; int nConfLimit; int nInsLimit; int fPartition; int fMiter; extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose ); extern int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int fPartition, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fSat = 0; fVerbose = 0; nSeconds = 20; nConfLimit = 10000; nInsLimit = 0; fPartition = 0; fMiter = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "TCIpmsvh" ) ) != EOF ) { switch ( c ) { case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } nSeconds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSeconds < 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 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nInsLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nInsLimit < 0 ) goto usage; break; case 'p': fPartition ^= 1; break; case 'm': fMiter ^= 1; break; case 's': fSat ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( fMiter ) { if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkIsStrash(pNtk) ) { pNtk1 = pNtk; fDelete1 = 0; } else { pNtk1 = Abc_NtkStrash( pNtk, 0, 1, 0 ); fDelete1 = 1; } pNtk2 = NULL; fDelete2 = 0; } else { if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; } if ( (pNtk1 && Abc_NtkLatchNum(pNtk1)) || (pNtk2 && Abc_NtkLatchNum(pNtk2)) ) { if ( pNtk1 && fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( pNtk2 && fDelete2 ) Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "Currently this command only works for networks without latches. Run \"comb\".\n" ); return 1; } // perform equivalence checking if ( fSat && fMiter ) Abc_NtkDSat( pNtk1, nConfLimit, nInsLimit, 0, 0, 0, 0, 0, 0, fVerbose ); else Abc_NtkDarCec( pNtk1, pNtk2, nConfLimit, fPartition, fVerbose ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 0; usage: Abc_Print( -2, "usage: dcec [-T num] [-C num] [-I num] [-mpsvh] \n" ); Abc_Print( -2, "\t performs combinational equivalence checking\n" ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit ); Abc_Print( -2, "\t-m : toggle working on two networks or a miter [default = %s]\n", fMiter? "miter": "two networks" ); Abc_Print( -2, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" ); Abc_Print( -2, "\t-s : toggle \"SAT only\" (miter) or \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Fra_Sec_t SecPar, * pSecPar = &SecPar; Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; int fDelete1, fDelete2; char ** pArgvNew; int nArgcNew; int c; int fIgnoreNames; extern int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * p ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults Fra_SecSetDefaultParams( pSecPar ); pSecPar->TimeLimit = 0; fIgnoreNames = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FTarmfnwvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pSecPar->nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nFramesMax < 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; } pSecPar->TimeLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->TimeLimit < 0 ) goto usage; break; case 'a': pSecPar->fPhaseAbstract ^= 1; break; case 'r': pSecPar->fRetimeFirst ^= 1; break; case 'm': pSecPar->fRetimeRegs ^= 1; break; case 'f': pSecPar->fFraiging ^= 1; break; case 'n': fIgnoreNames ^= 1; break; case 'w': pSecPar->fVeryVerbose ^= 1; break; case 'v': pSecPar->fVerbose ^= 1; break; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) { if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The network has no latches. Used combinational command \"cec\".\n" ); return 0; } 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 ); } // perform verification Abc_NtkDarSec( pNtk1, pNtk2, pSecPar ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 0; usage: Abc_Print( -2, "usage: dsec [-F num] [-T num] [-armfnwvh] \n" ); Abc_Print( -2, "\t performs inductive sequential equivalence checking\n" ); Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax ); Abc_Print( -2, "\t-T num : the approximate runtime limit (in seconds) [default = %d]\n", pSecPar->TimeLimit ); Abc_Print( -2, "\t-a : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" ); Abc_Print( -2, "\t-r : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" ); Abc_Print( -2, "\t-m : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" ); Abc_Print( -2, "\t-f : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" ); Abc_Print( -2, "\t-n : toggle how CIs/COs are matched (by name or by order) [default = %s]\n", fIgnoreNames? "by order": "by name" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) { Fra_Sec_t SecPar, * pSecPar = &SecPar; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; char * pLogFileName = NULL; int nBmcFramesMax = 20; int nBmcConfMax = 2000; extern void Fra_SecSetDefaultParams( Fra_Sec_t * p ); extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, Fra_Sec_t * pSecPar, int nBmcFramesMax, int nBmcConfMax ); // set defaults Fra_SecSetDefaultParams( pSecPar ); // pSecPar->TimeLimit = 300; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cbAEFCGDVBRTLarmfijkoupwvh" ) ) != EOF ) { switch ( c ) { case 'c': pSecPar->fTryComb ^= 1; break; case 'b': pSecPar->fTryBmc ^= 1; break; case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); goto usage; } nBmcFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBmcFramesMax < 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; } nBmcConfMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBmcConfMax < 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; } pSecPar->nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nFramesMax < 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; } pSecPar->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nBTLimit < 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; } pSecPar->nBTLimitGlobal = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nBTLimitGlobal < 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; } pSecPar->nBTLimitInter = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nBTLimitInter < 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; } pSecPar->nBddVarsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nBddVarsMax < 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; } pSecPar->nBddMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nBddMax < 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; } pSecPar->nBddIterMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nBddIterMax < 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; } pSecPar->nPdrTimeout = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pSecPar->nPdrTimeout < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); goto usage; } pLogFileName = argv[globalUtilOptind]; globalUtilOptind++; break; case 'a': pSecPar->fPhaseAbstract ^= 1; break; case 'r': pSecPar->fRetimeFirst ^= 1; break; case 'm': pSecPar->fRetimeRegs ^= 1; break; case 'f': pSecPar->fFraiging ^= 1; break; case 'i': pSecPar->fInduction ^= 1; break; case 'j': pSecPar->fInterpolation ^= 1; break; case 'k': pSecPar->fInterSeparate ^= 1; break; case 'o': pSecPar->fReorderImage ^= 1; break; case 'u': pSecPar->fReadUnsolved ^= 1; break; case 'p': pSecPar->fUsePdr ^= 1; break; case 'w': pSecPar->fVeryVerbose ^= 1; break; case 'v': pSecPar->fVerbose ^= 1; break; 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 structrally hashed networks. Run \"st\".\n" ); return 0; } // perform verification pAbc->Status = Abc_NtkDarProve( pNtk, pSecPar, nBmcFramesMax, nBmcConfMax ); Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "dprove" ); // read back the resulting unsolved reduced sequential miter if ( pSecPar->fReadUnsolved && pSecPar->nSMnumber >= 0 ) { char FileName[100]; sprintf(FileName, "sm%02d.aig", pSecPar->nSMnumber ); pNtk = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); if ( pNtk == NULL ) Abc_Print( -1, "Cannot read back unsolved reduced sequential miter \"%s\",\n", FileName ); else Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); } return 0; usage: Abc_Print( -2, "usage: dprove [-AEFCGDVBRT num] [-L file] [-cbarmfijoupvwh]\n" ); Abc_Print( -2, "\t performs SEC on the sequential miter\n" ); Abc_Print( -2, "\t-A num : the limit on the depth of BMC [default = %d]\n", nBmcFramesMax ); Abc_Print( -2, "\t-E num : the conflict limit during BMC [default = %d]\n", nBmcConfMax ); Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", pSecPar->nFramesMax ); Abc_Print( -2, "\t-C num : the conflict limit at a node during induction [default = %d]\n", pSecPar->nBTLimit ); Abc_Print( -2, "\t-G num : the global conflict limit during induction [default = %d]\n", pSecPar->nBTLimitGlobal ); Abc_Print( -2, "\t-D num : the conflict limit during interpolation [default = %d]\n", pSecPar->nBTLimitInter ); Abc_Print( -2, "\t-V num : the flop count limit for BDD-based reachablity [default = %d]\n", pSecPar->nBddVarsMax ); Abc_Print( -2, "\t-B num : the BDD size limit in BDD-based reachablity [default = %d]\n", pSecPar->nBddMax ); Abc_Print( -2, "\t-R num : the max number of reachability iterations [default = %d]\n", pSecPar->nBddIterMax ); Abc_Print( -2, "\t-T num : the timeout for property directed reachability [default = %d]\n", pSecPar->nPdrTimeout ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-c : toggles using CEC before attempting SEC [default = %s]\n", pSecPar->fTryComb? "yes": "no" ); Abc_Print( -2, "\t-b : toggles using BMC before attempting SEC [default = %s]\n", pSecPar->fTryBmc? "yes": "no" ); Abc_Print( -2, "\t-a : toggles the use of phase abstraction [default = %s]\n", pSecPar->fPhaseAbstract? "yes": "no" ); Abc_Print( -2, "\t-r : toggles forward retiming at the beginning [default = %s]\n", pSecPar->fRetimeFirst? "yes": "no" ); Abc_Print( -2, "\t-m : toggles min-register retiming [default = %s]\n", pSecPar->fRetimeRegs? "yes": "no" ); Abc_Print( -2, "\t-f : toggles the internal use of fraiging [default = %s]\n", pSecPar->fFraiging? "yes": "no" ); Abc_Print( -2, "\t-i : toggles the use of induction [default = %s]\n", pSecPar->fInduction? "yes": "no" ); Abc_Print( -2, "\t-j : toggles the use of interpolation [default = %s]\n", pSecPar->fInterpolation? "yes": "no" ); Abc_Print( -2, "\t-k : toggles applying interpolation to each output [default = %s]\n", pSecPar->fInterSeparate? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using BDD variable reordering during image computation [default = %s]\n", pSecPar->fReorderImage? "yes": "no" ); Abc_Print( -2, "\t-u : toggles reading back unsolved reduced sequential miter [default = %s]\n", pSecPar->fReadUnsolved? "yes": "no" ); Abc_Print( -2, "\t-p : toggles trying property directed reachability in the end [default = %s]\n", pSecPar->fUsePdr? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pSecPar->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles additional verbose output [default = %s]\n", pSecPar->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tCommand \"dprove\" can also be used for sequential synthesis (dprove -brjopu)\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbSec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; int fDelete1, fDelete2; char ** pArgvNew; int nArgcNew; int fMiter, nFrames, fVerbose, c; extern int Abc_NtkDarAbSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fMiter = 1; nFrames = 2; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fmvh" ) ) != 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 'm': fMiter ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } if ( fMiter ) { // pNtk = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1, 0 ); if ( argc == globalUtilOptind + 1 ) { Abc_Print( -1, "The miter cannot be given on the command line. Use \"read\".\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The miter should be structurally hashed. Use \"st\"\n" ); return 0; } if ( Abc_NtkDarAbSec( pNtk, NULL, nFrames, fVerbose ) == 1 ) pAbc->Status = 1; else pAbc->Status = -1; } else { pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) { if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The network has no latches. Used combinational command \"cec\".\n" ); return 0; } // perform verification if ( Abc_NtkDarAbSec( pNtk1, pNtk2, nFrames, fVerbose ) == 1 ) pAbc->Status = 1; else pAbc->Status = -1; if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); } return 0; usage: Abc_Print( -2, "usage: absec [-F num] [-mv] \n" ); Abc_Print( -2, "\t performs SEC by applying CEC to several timeframes\n" ); Abc_Print( -2, "\t-F num : the total number of timeframes to use [default = %d]\n", nFrames ); Abc_Print( -2, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); 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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSimSec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Ssw_Pars_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; int fDelete1, fDelete2; char ** pArgvNew; int nArgcNew, c; int fMiter; extern int Abc_NtkDarSimSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Ssw_Pars_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fMiter = 1; Ssw_ManSetDefaultParams( pPars ); pPars->fPartSigCorr = 1; pPars->fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FDcymvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFramesK = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesK < 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->nIsleDist = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIsleDist < 0 ) goto usage; break; case 'm': fMiter ^= 1; break; case 'c': pPars->fPartSigCorr ^= 1; break; case 'y': pPars->fDumpSRInit ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; default: goto usage; } } if ( fMiter ) { // Abc_Ntk_t * pNtkA, * pNtkB; if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } Abc_NtkDarSimSec( pNtk, NULL, pPars ); /* pNtkA = Abc_NtkDup( pNtk ); pNtkB = Abc_NtkDup( pNtk ); Abc_NtkDarSimSec( pNtkA, pNtkB, pPars ); Abc_NtkDelete( pNtkA ); Abc_NtkDelete( pNtkB ); */ } else { pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) { if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The network has no latches. Used combinational command \"cec\".\n" ); return 0; } // perform verification Abc_NtkDarSimSec( pNtk1, pNtk2, pPars ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); } return 0; usage: Abc_Print( -2, "usage: simsec [-FD num] [-mcyv] \n" ); Abc_Print( -2, "\t performs SEC using structural similarity\n" ); Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", pPars->nFramesK ); Abc_Print( -2, "\t-D num : the distance for extending islands [default = %d]\n", pPars->nIsleDist ); Abc_Print( -2, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" ); Abc_Print( -2, "\t-c : uses partial vs. full signal correspondence [default = %s]\n", pPars->fPartSigCorr? "partial": "full" ); Abc_Print( -2, "\t-y : dumps speculatively reduced miter of the classes [default = %s]\n", pPars->fDumpSRInit? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); 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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMatch( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes; int fDelete1, fDelete2; char ** pArgvNew; int nArgcNew, c; int fMiter; int nDist; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarMatch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nDist, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fMiter = 0; nDist = 0; fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Dmvh" ) ) != EOF ) { switch ( c ) { case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } nDist = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDist < 0 ) goto usage; break; case 'm': fMiter ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } if ( fMiter ) { // Abc_Ntk_t * pNtkA, * pNtkB; if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } pNtkRes = Abc_NtkDarMatch( pNtk, NULL, nDist, fVerbose ); /* pNtkA = Abc_NtkDup( pNtk ); pNtkB = Abc_NtkDup( pNtk ); Abc_NtkDarSimSec( pNtkA, pNtkB, pPars ); Abc_NtkDelete( pNtkA ); Abc_NtkDelete( pNtkB ); */ } else { pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) { if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The network has no latches. Used combinational command \"cec\".\n" ); return 0; } // perform verification pNtkRes = Abc_NtkDarMatch( pNtk1, pNtk2, nDist, fVerbose ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); } if ( pNtkRes == NULL ) { Abc_Print( -1, "Matching has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: match [-D num] [-mv] \n" ); Abc_Print( -2, "\t detects structural similarity using simulation\n" ); Abc_Print( -2, "\t replaces the current network by the miter of differences\n" ); Abc_Print( -2, "\t-D num : the distance for extending differences [default = %d]\n", nDist ); Abc_Print( -2, "\t-m : toggles miter vs. two networks [default = %s]\n", fMiter? "miter": "two networks" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); 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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int RetValue; int fVerbose; int nConfLimit; int nInsLimit; abctime clk; // set defaults fVerbose = 0; nConfLimit = 0; nInsLimit = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != 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 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nInsLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nInsLimit < 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_NtkLatchNum(pNtk) > 0 ) { Abc_Print( -1, "Currently can only solve the miter for combinational circuits.\n" ); return 0; } clk = Abc_Clock(); if ( Abc_NtkIsStrash(pNtk) ) { RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, fVerbose, NULL, NULL ); } else { assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkToBdd( pNtk ); RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, fVerbose, NULL, NULL ); } // verify that the pattern is correct if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) { //int i; //Abc_Obj_t * pObj; int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); if ( pSimInfo[0] != 1 ) Abc_Print( 1, "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); ABC_FREE( pSimInfo ); /* // print model Abc_NtkForEachPi( pNtk, pObj, i ) { Abc_Print( -1, "%d", (int)(pNtk->pModel[i] > 0) ); if ( i == 70 ) break; } Abc_Print( -1, "\n" ); */ } pAbc->Status = RetValue; if ( RetValue == -1 ) Abc_Print( 1, "UNDECIDED " ); else if ( RetValue == 0 ) Abc_Print( 1, "SATISFIABLE " ); else Abc_Print( 1, "UNSATISFIABLE " ); //Abc_Print( -1, "\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return 0; usage: Abc_Print( -2, "usage: sat [-C num] [-I num] [-vh]\n" ); Abc_Print( -2, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); Abc_Print( -2, "\t derives CNF from the current network and leave it unchanged\n" ); Abc_Print( -2, "\t (there is also a newer SAT solving command \"dsat\")\n" ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); 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_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int RetValue; int fAlignPol; int fAndOuts; int fNewSolver; int fSilent; int fShowPattern; int fVerbose; int nConfLimit; int nLearnedStart; int nLearnedDelta; int nLearnedPerce; int nInsLimit; abctime clk; extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose ); // set defaults fAlignPol = 0; fAndOuts = 0; fNewSolver = 0; fSilent = 0; fShowPattern = 0; fVerbose = 0; nConfLimit = 0; nInsLimit = 0; nLearnedStart = 0; nLearnedDelta = 0; nLearnedPerce = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CILDEpansvwh" ) ) != 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 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nInsLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nInsLimit < 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; } nLearnedStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLearnedStart < 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; } nLearnedDelta = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLearnedDelta < 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; } nLearnedPerce = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLearnedPerce < 0 ) goto usage; break; case 'p': fAlignPol ^= 1; break; case 'a': fAndOuts ^= 1; break; case 'n': fNewSolver ^= 1; break; case 's': fSilent ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fShowPattern ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc == globalUtilOptind + 1 ) { int * pModel = NULL; extern int Cnf_DataSolveFromFile( char * pFileName, int nConfLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fVerbose, int fShowPattern, int ** ppModel, int nPis ); // get the input file name char * pFileName = argv[globalUtilOptind]; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return 0; } fclose( pFile ); Cnf_DataSolveFromFile( pFileName, nConfLimit, nLearnedStart, nLearnedDelta, nLearnedPerce, fVerbose, fShowPattern, &pModel, pNtk ? Abc_NtkPiNum(pNtk) : 0 ); if ( pModel && pNtk ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pModel ); if ( pSimInfo[0] != 1 ) Abc_Print( 1, "ERROR in mapping PIs into SAT vars: Generated CEX is invalid.\n" ); ABC_FREE( pSimInfo ); pAbc->pCex = Abc_CexCreate( 0, Abc_NtkPiNum(pNtk), pModel, 0, 0, 0 ); } ABC_FREE( pModel ); return 0; } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkLatchNum(pNtk) > 0 ) { Abc_Print( -1, "Currently can only solve the miter 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } clk = Abc_Clock(); RetValue = Abc_NtkDSat( pNtk, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, nLearnedStart, nLearnedDelta, nLearnedPerce, fAlignPol, fAndOuts, fNewSolver, fVerbose ); // verify that the pattern is correct if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); if ( pSimInfo[0] != 1 ) Abc_Print( 1, "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); ABC_FREE( pSimInfo ); pAbc->pCex = Abc_CexCreate( 0, Abc_NtkPiNum(pNtk), pNtk->pModel, 0, 0, 0 ); } pAbc->Status = RetValue; if ( !fSilent ) { if ( RetValue == -1 ) Abc_Print( 1, "UNDECIDED " ); else if ( RetValue == 0 ) Abc_Print( 1, "SATISFIABLE " ); else Abc_Print( 1, "UNSATISFIABLE " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return 0; usage: Abc_Print( -2, "usage: dsat [-CILDE num] [-pansvh]\n" ); Abc_Print( -2, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); Abc_Print( -2, "\t derives CNF from the current network and leaves it unchanged\n" ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); Abc_Print( -2, "\t-L num : starting value for learned clause removal [default = %d]\n", nLearnedStart ); Abc_Print( -2, "\t-D num : delta value for learned clause removal [default = %d]\n", nLearnedDelta ); Abc_Print( -2, "\t-E num : ratio percentage for learned clause removal [default = %d]\n", nLearnedPerce ); Abc_Print( -2, "\t-p : align polarity of SAT variables [default = %s]\n", fAlignPol? "yes": "no" ); Abc_Print( -2, "\t-a : toggle ANDing/ORing of miter outputs [default = %s]\n", fAndOuts? "ANDing": "ORing" ); Abc_Print( -2, "\t-n : toggle using new solver [default = %s]\n", fNewSolver? "yes": "no" ); Abc_Print( -2, "\t-s : enable silent computation (no reporting) [default = %s]\n", fSilent? "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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPSat( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int RetValue; int c; int nAlgo; int nPartSize; int nConfPart; int nConfTotal; int fAlignPol; int fSynthesize; int fVerbose; abctime clk; extern int Abc_NtkPartitionedSat( Abc_Ntk_t * pNtk, int nAlgo, int nPartSize, int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose ); // set defaults nAlgo = 0; nPartSize = 10000; nConfPart = 0; nConfTotal = 1000000; fAlignPol = 1; fSynthesize = 0; fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "APCpsvh" ) ) != EOF ) { switch ( c ) { case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); goto usage; } nAlgo = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nAlgo < 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; } 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; } nConfTotal = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfTotal < 0 ) goto usage; break; case 'p': fAlignPol ^= 1; break; case 's': fSynthesize ^= 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 can only solve the miter for combinational circuits.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } clk = Abc_Clock(); RetValue = Abc_NtkPartitionedSat( pNtk, nAlgo, nPartSize, nConfPart, nConfTotal, fAlignPol, fSynthesize, fVerbose ); // verify that the pattern is correct if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) { //int i; //Abc_Obj_t * pObj; int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); if ( pSimInfo[0] != 1 ) Abc_Print( 1, "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); ABC_FREE( pSimInfo ); /* // print model Abc_NtkForEachPi( pNtk, pObj, i ) { Abc_Print( -1, "%d", (int)(pNtk->pModel[i] > 0) ); if ( i == 70 ) break; } Abc_Print( -1, "\n" ); */ } if ( RetValue == -1 ) Abc_Print( 1, "UNDECIDED " ); else if ( RetValue == 0 ) Abc_Print( 1, "SATISFIABLE " ); else Abc_Print( 1, "UNSATISFIABLE " ); //Abc_Print( -1, "\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return 0; usage: Abc_Print( -2, "usage: psat [-APC num] [-psvh]\n" ); Abc_Print( -2, "\t solves the combinational miter using partitioning\n" ); Abc_Print( -2, "\t (derives CNF from the current network and leave it unchanged)\n" ); Abc_Print( -2, "\t for multi-output miters, tries to prove that the AND of POs is always 0\n" ); Abc_Print( -2, "\t (if POs should be ORed instead of ANDed, use command \"orpos\")\n" ); Abc_Print( -2, "\t-A num : partitioning algorithm [default = %d]\n", nAlgo ); Abc_Print( -2, "\t 0 : no partitioning\n" ); Abc_Print( -2, "\t 1 : partitioning by level\n" ); Abc_Print( -2, "\t 2 : DFS post-order\n" ); Abc_Print( -2, "\t 3 : DFS pre-order\n" ); Abc_Print( -2, "\t 4 : bit-slicing\n" ); Abc_Print( -2, "\t partitions are ordered by level (high level first)\n" ); Abc_Print( -2, "\t-P num : limit on the partition size [default = %d]\n", nPartSize ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfTotal ); Abc_Print( -2, "\t-p : align polarity of SAT variables [default = %s]\n", fAlignPol? "yes": "no" ); Abc_Print( -2, "\t-s : apply logic synthesis to each partition [default = %s]\n", fSynthesize? "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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkTemp; Prove_Params_t Params, * pParams = &Params; int c, RetValue; abctime clk; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Prove_ParamsSetDefault( pParams ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGLIrfbvh" ) ) != 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 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" 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 '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, "Currently can only solve the miter for combinational circuits.\n" ); return 0; } if ( Abc_NtkCoNum(pNtk) != 1 ) { Abc_Print( -1, "Currently can only solve the miter with one output.\n" ); return 0; } clk = Abc_Clock(); if ( Abc_NtkIsStrash(pNtk) ) pNtkTemp = Abc_NtkDup( pNtk ); else pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); RetValue = Abc_NtkMiterProve( &pNtkTemp, pParams ); // verify that the pattern is correct if ( RetValue == 0 ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); if ( pSimInfo[0] != 1 ) 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 " ); else Abc_Print( 1, "UNSATISFIABLE " ); //Abc_Print( -1, "\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); return 0; usage: Abc_Print( -2, "usage: prove [-NCFGLI num] [-rfbvh]\n" ); Abc_Print( -2, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" ); Abc_Print( -2, "\t replaces the current network by the cone modified by rewriting\n" ); Abc_Print( -2, "\t (there is also newer CEC command \"iprove\")\n" ); Abc_Print( -2, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); Abc_Print( -2, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); Abc_Print( -2, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); Abc_Print( -2, "\t-G num : multiplicative coefficient for fraiging [default = %d]\n", (int)pParams->nFraigingLimitMulti ); Abc_Print( -2, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); Abc_Print( -2, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit ); 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_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; extern void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ); extern int Abc_NtkRetimeDebug( 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; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "This command is applicable to logic networks.\n" ); return 1; } Abc_NtkAutoDebug( pNtk, Abc_NtkRetimeDebug ); return 0; usage: Abc_Print( -2, "usage: debug [-h]\n" ); Abc_Print( -2, "\t performs automated debugging of the given procedure\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nFrames; int nSizeMax; int nBTLimit; int nBTLimitAll; int nNodeDelta; int fRewrite; int fNewAlgo; int nCofFanLit; int fVerbose; int iFrames; char * pLogFileName = NULL; extern int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nStart, int nFrames, int nSizeMax, int nNodeDelta, int nTimeOut, int nBTLimit, int nBTLimitAll, int fRewrite, int fNewAlgo, int fOrDecomp, int nCofFanLit, int fVerbose, int * piFrames ); // set defaults nFrames = 20; nSizeMax = 100000; nBTLimit = 0; nBTLimitAll = 0; nNodeDelta = 1000; fRewrite = 0; fNewAlgo = 1; nCofFanLit = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FNCGDLrvh" ) ) != 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 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nSizeMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSizeMax < 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 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); goto usage; } nBTLimitAll = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBTLimitAll < 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; } nNodeDelta = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nNodeDelta < 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; } nCofFanLit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCofFanLit < 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': fRewrite ^= 1; break; case 'a': fNewAlgo ^= 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, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "Does not work for combinational networks.\n" ); return 0; } pAbc->Status = Abc_NtkDarBmc( pNtk, 0, nFrames, nSizeMax, nNodeDelta, 0, nBTLimit, nBTLimitAll, fRewrite, fNewAlgo, 0, nCofFanLit, fVerbose, &iFrames ); pAbc->nFrames = iFrames; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "bmc" ); return 0; usage: Abc_Print( -2, "usage: bmc [-FNC num] [-L file] [-rcvh]\n" ); Abc_Print( -2, "\t performs bounded model checking with static unrolling\n" ); Abc_Print( -2, "\t-F num : the number of time frames [default = %d]\n", nFrames ); Abc_Print( -2, "\t-N num : the max number of nodes in the frames [default = %d]\n", nSizeMax ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit ); // Abc_Print( -2, "\t-L num : the limit on fanout count of resets/enables to cofactor [default = %d]\n", nCofFanLit ); 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", fRewrite? "yes": "no" ); // Abc_Print( -2, "\t-a : toggle SAT sweeping and SAT solving [default = %s]\n", fNewAlgo? "SAT solving": "SAT sweeping" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBmc2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nStart; int nFrames; int nSizeMax; int nBTLimit; int nBTLimitAll; int nNodeDelta; int nTimeOut; int fRewrite; int fNewAlgo; int fOrDecomp; int fVerbose; int iFrames; char * pLogFileName = NULL; extern int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nStart, int nFrames, int nSizeMax, int nNodeDelta, int nTimeOut, int nBTLimit, int nBTLimitAll, int fRewrite, int fNewAlgo, int fOrDecomp, int nCofFanLit, int fVerbose, int * piFrames ); // set defaults nStart = 0; nFrames = 0; nSizeMax = 200000; nBTLimit = 0; nBTLimitAll = 0; nNodeDelta = 2000; nTimeOut = 0; fRewrite = 0; fNewAlgo = 0; fOrDecomp = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "SFNTCGDLruvh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } nStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nStart < 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 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nSizeMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSizeMax < 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; } nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeOut < 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 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); goto usage; } nBTLimitAll = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBTLimitAll < 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; } nNodeDelta = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nNodeDelta < 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': fRewrite ^= 1; break; case 'a': fNewAlgo ^= 1; break; case 'u': fOrDecomp ^= 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, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "Does not work for combinational networks.\n" ); return 0; } pAbc->Status = Abc_NtkDarBmc( pNtk, nStart, nFrames, nSizeMax, nNodeDelta, nTimeOut, nBTLimit, nBTLimitAll, fRewrite, fNewAlgo, fOrDecomp, 0, fVerbose, &iFrames ); pAbc->nFrames = iFrames; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "bmc2" ); return 0; usage: Abc_Print( -2, "usage: bmc2 [-SFTCGD num] [-L file] [-uvh]\n" ); Abc_Print( -2, "\t performs bounded model checking with dynamic unrolling\n" ); Abc_Print( -2, "\t-S num : the starting time frame [default = %d]\n", nStart ); Abc_Print( -2, "\t-F num : the max number of time frames (0 = unused) [default = %d]\n", nFrames ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-G num : the max number of conflicts globally [default = %d]\n", nBTLimitAll ); Abc_Print( -2, "\t-D num : the delta in the number of nodes [default = %d]\n", nNodeDelta ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-u : toggle performing structural OR-decomposition [default = %s]\n", fOrDecomp? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBmc3( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NtkDarBmc3( Abc_Ntk_t * pNtk, Saig_ParBmc_t * pPars, int fOrDecomp ); Saig_ParBmc_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc); Vec_Ptr_t * vSeqModelVec = NULL; Vec_Int_t * vStatuses = NULL; char * pLogFileName = NULL; int fOrDecomp = 0; int c; Saig_ParBmcSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "SFTHGCDJIPQRLWaxdurvzh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } pPars->nStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nStart < 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->nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesMax < 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->nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOut < 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->nTimeOutOne = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOutOne < 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; } pPars->nTimeOutGap = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOutGap < 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->nConfLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nConfLimit < 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->nConfLimitJump = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nConfLimitJump < 0 ) goto usage; break; case 'J': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-J\" should be followed by an integer.\n" ); goto usage; } pPars->nFramesJump = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesJump < 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->nPisAbstract = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nPisAbstract < 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->nLearnedStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedStart < 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; } pPars->nLearnedDelta = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedDelta < 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->nLearnedPerce = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedPerce < 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 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a file name.\n" ); goto usage; } pPars->pLogFileName = argv[globalUtilOptind]; globalUtilOptind++; break; case 'a': pPars->fSolveAll ^= 1; break; case 'x': pPars->fStoreCex ^= 1; break; case 'd': pPars->fDropSatOuts ^= 1; break; case 'u': fOrDecomp ^= 1; break; case 'r': pPars->fNoRestarts ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'z': pPars->fNotVerbose ^= 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, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "Does not work for combinational networks.\n" ); return 0; } if ( Abc_NtkConstrNum(pNtk) > 0 ) { Abc_Print( -1, "Constraints have to be folded (use \"fold\").\n" ); return 0; } pPars->fUseBridge = pAbc->fBridgeMode; pAbc->Status = Abc_NtkDarBmc3( pNtk, pPars, fOrDecomp ); pAbc->nFrames = pNtk->vSeqModelVec ? -1 : pPars->iFrame; if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "bmc3" ); vSeqModelVec = pNtk->vSeqModelVec; pNtk->vSeqModelVec = NULL; if ( pPars->fSolveAll && pPars->fDropSatOuts ) { if ( vSeqModelVec == NULL ) Abc_Print( 1,"The array of counter-examples is not available.\n" ); else if ( Vec_PtrSize(vSeqModelVec) != Abc_NtkPoNum(pNtk) ) Abc_Print( 1,"The array size does not match the number of outputs.\n" ); else { extern void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose ); Abc_NtkDropSatOutputs( pNtk, vSeqModelVec, pPars->fVerbose ); 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 ); } } vStatuses = Abc_FrameDeriveStatusArray( vSeqModelVec ); Abc_FrameReplacePoStatuses( pAbc, &vStatuses ); if ( vSeqModelVec ) Abc_FrameReplaceCexVec( pAbc, &vSeqModelVec ); else Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); return 0; usage: Abc_Print( -2, "usage: bmc3 [-SFTHGCDJIPQR num] [-LW file] [-axdurvzh]\n" ); Abc_Print( -2, "\t performs bounded model checking with dynamic unrolling\n" ); Abc_Print( -2, "\t-S num : the starting time frame [default = %d]\n", pPars->nStart ); Abc_Print( -2, "\t-F num : the max number of time frames (0 = unused) [default = %d]\n", pPars->nFramesMax ); Abc_Print( -2, "\t-T num : runtime limit, in seconds [default = %d]\n", pPars->nTimeOut ); Abc_Print( -2, "\t-H num : runtime limit per output, in miliseconds (with \"-a\") [default = %d]\n", pPars->nTimeOutOne ); Abc_Print( -2, "\t-G num : runtime gap since the last CEX, in seconds [default = %d]\n", pPars->nTimeOutGap ); Abc_Print( -2, "\t-C num : max conflicts at an output [default = %d]\n", pPars->nConfLimit ); Abc_Print( -2, "\t-D num : max conflicts after jumping (0 = infinity) [default = %d]\n", pPars->nConfLimitJump ); Abc_Print( -2, "\t-J num : the number of timeframes to jump (0 = not used) [default = %d]\n", pPars->nFramesJump ); Abc_Print( -2, "\t-I num : the number of PIs to abstract [default = %d]\n", pPars->nPisAbstract ); Abc_Print( -2, "\t-P num : the max number of learned clauses to keep (0=unused) [default = %d]\n", pPars->nLearnedStart ); Abc_Print( -2, "\t-Q num : delta value for learned clause removal [default = %d]\n", pPars->nLearnedDelta ); Abc_Print( -2, "\t-R num : percentage to keep for learned clause removal [default = %d]\n", pPars->nLearnedPerce ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-W file: the log file name with per-output details [default = %s]\n", pPars->pLogFileName ? pPars->pLogFileName : "no logging" ); Abc_Print( -2, "\t-a : solve all outputs (do not stop when one is SAT) [default = %s]\n", pPars->fSolveAll? "yes": "no" ); Abc_Print( -2, "\t-x : toggle storing CEXes when solving all outputs [default = %s]\n", pPars->fStoreCex? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dropping (replacing by 0) SAT outputs [default = %s]\n", pPars->fDropSatOuts? "yes": "no" ); Abc_Print( -2, "\t-u : toggle performing structural OR-decomposition [default = %s]\n", fOrDecomp? "yes": "not" ); Abc_Print( -2, "\t-r : toggle disabling periodic restarts [default = %s]\n", pPars->fNoRestarts? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-z : toggle suppressing report about solved outputs [default = %s]\n", pPars->fNotVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBmcInter( Abc_Frame_t * pAbc, int argc, char ** argv ) { Inter_ManParams_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc); int c; char * pLogFileName = NULL; extern int Abc_NtkDarBmcInter( Abc_Ntk_t * pNtk, Inter_ManParams_t * pPars, Abc_Ntk_t ** ppNtkRes ); // set defaults Inter_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CFTKLIrtpomcgbqkdivh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBTLimit < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesMax < 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->nSecLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nSecLimit < 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->nFramesK = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesK < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); goto usage; } pLogFileName = argv[globalUtilOptind]; globalUtilOptind++; break; case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by a file name.\n" ); goto usage; } pPars->pFileName = argv[globalUtilOptind]; globalUtilOptind++; break; case 'r': pPars->fRewrite ^= 1; break; case 't': pPars->fTransLoop ^= 1; break; case 'p': pPars->fUsePudlak ^= 1; break; case 'o': pPars->fUseOther ^= 1; break; case 'm': pPars->fUseMiniSat ^= 1; break; case 'c': pPars->fCheckKstep ^= 1; break; case 'g': pPars->fUseBias ^= 1; break; case 'b': pPars->fUseBackward ^= 1; break; case 'q': pPars->fUseTwoFrames ^= 1; break; case 'k': pPars->fUseSeparate ^= 1; break; case 'd': pPars->fDropSatOuts ^= 1; break; case 'i': pPars->fDropInvar ^= 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, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "Does not work for combinational networks.\n" ); return 0; } if ( Abc_NtkConstrNum(pNtk) > 0 ) { Abc_Print( -1, "Cannot run interpolation with constraints. Use \"fold\".\n" ); return 0; } if ( Abc_NtkPoNum(pNtk)-Abc_NtkConstrNum(pNtk) != 1 ) { if ( Abc_NtkConstrNum(pNtk) > 0 ) { Abc_Print( 1,"Cannot solve multiple-output miter with constraints.\n" ); return 0; } if ( pPars->fUseSeparate ) { Abc_Print( 0, "Each of %d outputs will be solved separately.\n", Abc_NtkPoNum(pNtk) ); pAbc->Status = Abc_NtkDarBmcInter( pNtk, pPars, &pNtkRes ); Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Generating resulting network has failed.\n" ); return 0; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } else { Abc_Ntk_t * pNtkNew = Abc_NtkDup( pNtk ); Abc_Print( 0, "All %d outputs will be ORed together.\n", Abc_NtkPoNum(pNtk) ); if ( !Abc_NtkCombinePos( pNtkNew, 0, 0 ) ) { Abc_NtkDelete( pNtkNew ); Abc_Print( -1, "ORing outputs has failed.\n" ); return 0; } pAbc->Status = Abc_NtkDarBmcInter( pNtkNew, pPars, NULL ); if ( pAbc->Status == 0 ) { Aig_Man_t * pMan = Abc_NtkToDar( pNtk, 0, 1 ); pNtkNew->pSeqModel->iPo = Saig_ManFindFailedPoCex( pMan, pNtkNew->pSeqModel ); Aig_ManStop( pMan ); } Abc_FrameReplaceCex( pAbc, &pNtkNew->pSeqModel ); Abc_NtkDelete( pNtkNew ); } pAbc->nFrames = -1; } else { pAbc->Status = Abc_NtkDarBmcInter( pNtk, pPars, NULL ); pAbc->nFrames = pPars->iFrameMax; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); } if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "int" ); return 0; usage: Abc_Print( -2, "usage: int [-CFTK num] [-LI file] [-irtpomcgbqkdvh]\n" ); Abc_Print( -2, "\t uses interpolation to prove the property\n" ); Abc_Print( -2, "\t-C num : the limit on conflicts for one SAT run [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-F num : the limit on number of frames to unroll [default = %d]\n", pPars->nFramesMax ); Abc_Print( -2, "\t-T num : the limit on runtime per output in seconds [default = %d]\n", pPars->nSecLimit ); Abc_Print( -2, "\t-K num : the number of steps in inductive checking [default = %d]\n", pPars->nFramesK ); Abc_Print( -2, "\t (K = 1 works in all cases; K > 1 works without -t and -b)\n" ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-I file: the file name for dumping interpolant [default = \"%s\"]\n", pPars->pFileName ? pPars->pFileName : "invar.aig" ); Abc_Print( -2, "\t-i : toggle dumping interpolant/invariant into a file [default = %s]\n", pPars->fDropInvar? "yes": "no" ); Abc_Print( -2, "\t-r : toggle rewriting of the unrolled timeframes [default = %s]\n", pPars->fRewrite? "yes": "no" ); Abc_Print( -2, "\t-t : toggle adding transition into the initial state [default = %s]\n", pPars->fTransLoop? "yes": "no" ); Abc_Print( -2, "\t-p : toggle using original Pudlak's interpolation procedure [default = %s]\n", pPars->fUsePudlak? "yes": "no" ); Abc_Print( -2, "\t-o : toggle using optimized Pudlak's interpolation procedure [default = %s]\n", pPars->fUseOther? "yes": "no" ); Abc_Print( -2, "\t-m : toggle using MiniSat-1.14p (now, Windows-only) [default = %s]\n", pPars->fUseMiniSat? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using inductive containment check [default = %s]\n", pPars->fCheckKstep? "yes": "no" ); Abc_Print( -2, "\t-g : toggle using bias for global variables using SAT [default = %s]\n", pPars->fUseBias? "yes": "no" ); Abc_Print( -2, "\t-b : toggle using backward interpolation (works with -t) [default = %s]\n", pPars->fUseBackward? "yes": "no" ); Abc_Print( -2, "\t-q : toggle using property in two last timeframes [default = %s]\n", pPars->fUseTwoFrames? "yes": "no" ); Abc_Print( -2, "\t-k : toggle solving each output separately [default = %s]\n", pPars->fUseSeparate? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dropping (replacing by 0) SAT outputs (with -k is used) [default = %s]\n", pPars->fDropSatOuts? "yes": "no" ); Abc_Print( -2, "\t-v : toggle 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_CommandIndcut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int nFrames; int nPref; int nClauses; int nLutSize; int nLevels; int nCutsMax; int nBatches; int fStepUp; int fBmc; int fRegs; int fTarget; int fVerbose; int fVeryVerbose; int c; extern int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRegs, int fTarget, int fVerbose, int fVeryVerbose ); // set defaults nFrames = 1; nPref = 0; nClauses = 5000; nLutSize = 4; nLevels = 8; nCutsMax = 16; nBatches = 1; fStepUp = 0; fBmc = 1; fRegs = 1; fTarget = 1; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FPCMLNBsbrtvwh" ) ) != 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 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nPref = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPref < 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; } nClauses = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nClauses < 0 ) goto usage; break; case 'M': 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; } nLevels = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLevels < 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; } nCutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutsMax < 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; } nBatches = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBatches < 0 ) goto usage; break; case 's': fStepUp ^= 1; break; case 'b': fBmc ^= 1; break; case 'r': fRegs ^= 1; break; case 't': fTarget ^= 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_NtkIsComb(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( nLutSize > 12 ) { Abc_Print( -1, "The cut size should be not exceed 12.\n" ); return 0; } Abc_NtkDarClau( pNtk, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRegs, fTarget, fVerbose, fVeryVerbose ); return 0; usage: Abc_Print( -2, "usage: indcut [-FPCMLNB num] [-sbrtvh]\n" ); Abc_Print( -2, "\t K-step induction strengthened with cut properties\n" ); Abc_Print( -2, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFrames ); Abc_Print( -2, "\t-P num : number of time frames in the prefix (0=no prefix) [default = %d]\n", nPref ); Abc_Print( -2, "\t-C num : the max number of clauses to use for strengthening [default = %d]\n", nClauses ); Abc_Print( -2, "\t-M num : the cut size (2 <= M <= 12) [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-L num : the max number of levels for cut computation [default = %d]\n", nLevels ); Abc_Print( -2, "\t-N num : the max number of cuts to compute at a node [default = %d]\n", nCutsMax ); Abc_Print( -2, "\t-B num : the max number of invariant batches to try [default = %d]\n", nBatches ); Abc_Print( -2, "\t-s : toggle increment cut size in each batch [default = %s]\n", fStepUp? "yes": "no" ); Abc_Print( -2, "\t-b : toggle enabling BMC check [default = %s]\n", fBmc? "yes": "no" ); Abc_Print( -2, "\t-r : toggle enabling register clauses [default = %s]\n", fRegs? "yes": "no" ); Abc_Print( -2, "\t-t : toggle proving target / computing don't-cares [default = %s]\n", fTarget? "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_CommandEnlarge( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int nFrames; int fVerbose; int c; extern Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nFrames = 5; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != 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 < 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_NtkIsComb(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } // modify the current network pNtkRes = Abc_NtkDarEnlarge( pNtk, nFrames, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Target enlargement has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: enlarge [-F ] [-vh]\n" ); Abc_Print( -2, "\t performs structural K-step target enlargement\n" ); Abc_Print( -2, "\t-F : the number of timeframes to unroll ( > 0) [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_CommandTempor( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkDarTempor( Abc_Ntk_t * pNtk, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc); int nFrames = 0; int TimeOut = 300; int nConfMax = 100000; int fUseBmc = 1; int fUseTransSigs = 0; int fUpdateCex = 0; int fVerbose = 0; int fVeryVerbose = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FTCbscvwh" ) ) != 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 '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 '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 'b': fUseBmc ^= 1; break; case 's': fUseTransSigs ^= 1; break; case 'c': fUpdateCex ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -2, "There is no current network.\n"); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n"); return 0; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( 0, "The current network is combinational.\n"); return 0; } if ( Abc_NtkPiNum(pNtk) == 0 ) { Abc_Print( 0, "The current network does not have primary inputs. Use \"addpi\".\n"); return 0; } if ( fUpdateCex ) { Abc_Cex_t * pCexNew; if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Counter-example is not available.\n" ); return 1; } if ( pAbc->pCex->nPis % Abc_NtkPiNum(pNtk) != 0 ) { Abc_Print( -1, "PI count of the CEX is not a multiple of PI count of the current AIG.\n" ); return 1; } pCexNew = Abc_CexTransformTempor( pAbc->pCex, Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkLatchNum(pNtk) ); Abc_FrameReplaceCex( pAbc, &pCexNew ); return 0; } // modify the current network pNtkRes = Abc_NtkDarTempor( pNtk, nFrames, TimeOut, nConfMax, fUseBmc, fUseTransSigs, fVerbose, fVeryVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Temporal decomposition has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: tempor [-FTC ] [-bscvwh]\n" ); Abc_Print( -2, "\t performs temporal decomposition\n" ); Abc_Print( -2, "\t-F : init logic timeframe count (0 = use leading length) [default = %d]\n", nFrames ); Abc_Print( -2, "\t-T : runtime limit in seconds for BMC (0=unused) [default = %d]\n", TimeOut ); Abc_Print( -2, "\t-C : max number of SAT conflicts in BMC (0=unused) [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-b : toggle running BMC2 on the init frames [default = %s]\n", fUseBmc? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using transient signals [default = %s]\n", fUseTransSigs? "yes": "no" ); Abc_Print( -2, "\t-c : update the current CEX derived for a new AIG after \"tempor\"\n" ); Abc_Print( -2, "\t to match the current AIG (the one before \"tempor\") [default = %s]\n", fUpdateCex? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing ternary state space [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_CommandInduction( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int nTimeOut; int nFramesMax; int nConfMax; int fUnique; int fUniqueAll; int fGetCex; int fVerbose; int fVeryVerbose; int c; extern int Abc_NtkDarInduction( Abc_Ntk_t * pNtk, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose ); // set defaults nTimeOut = 0; nFramesMax = 0; nConfMax = 0; fUnique = 0; fUniqueAll = 0; fGetCex = 0; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCTuaxvwh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFramesMax < 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; } nConfMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfMax < 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; } nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeOut < 0 ) goto usage; break; case 'u': fUnique ^= 1; break; case 'a': fUniqueAll ^= 1; break; case 'x': fGetCex ^= 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_NtkIsComb(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkPoNum(pNtk) != 1 ) { Abc_Print( -1, "Currently this command works only for single-output miter.\n" ); return 0; } if ( fUnique && fUniqueAll ) { Abc_Print( -1, "Only one of the options, \"-u\" or \"-a\", should be selected.\n" ); return 0; } // modify the current network pAbc->Status = Abc_NtkDarInduction( pNtk, nTimeOut, nFramesMax, nConfMax, fUnique, fUniqueAll, fGetCex, fVerbose, fVeryVerbose ); if ( fGetCex ) { Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); Abc_Print( 1,"The current CEX in ABC is set to be the CEX to induction.\n" ); } return 0; usage: Abc_Print( -2, "usage: ind [-FCT num] [-uaxvwh]\n" ); Abc_Print( -2, "\t runs the inductive case of the K-step induction\n" ); Abc_Print( -2, "\t-F num : the max number of timeframes [default = %d]\n", nFramesMax ); Abc_Print( -2, "\t-C num : the max number of conflicts by SAT solver [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-T num : the limit on runtime per output in seconds [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-u : toggle adding uniqueness constraints on demand [default = %s]\n", fUnique? "yes": "no" ); Abc_Print( -2, "\t-a : toggle adding uniqueness constraints always [default = %s]\n", fUniqueAll? "yes": "no" ); Abc_Print( -2, "\t-x : toggle returning CEX to induction for the top frame [default = %s]\n", fGetCex? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing additional 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_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; int c; int nFrames; int nConfs; int nProps; int fRemove; int fStruct; int fInvert; int fOldAlgo; int fVerbose; int nConstrs; extern void Abc_NtkDarConstr( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nFrames = 1; nConfs = 1000; nProps = 1000; fRemove = 0; fStruct = 0; fInvert = 0; fOldAlgo = 0; fVerbose = 0; nConstrs = -1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCPNrsiavh" ) ) != 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 '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 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nProps = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nProps < 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; } nConstrs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConstrs < 0 ) goto usage; break; case 'r': fRemove ^= 1; break; case 's': fStruct ^= 1; break; case 'i': fInvert ^= 1; break; case 'a': fOldAlgo ^= 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, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( fRemove ) { if ( Abc_NtkConstrNum(pNtk) == 0 ) { Abc_Print( -1, "Constraints are not defined.\n" ); return 0; } Abc_Print( 1, "Constraints are converted to be primary outputs.\n" ); pNtk->nConstrs = 0; return 0; } // consider the case of manual constraint definition if ( nConstrs >= 0 ) { if ( Abc_NtkIsComb(pNtk) ) Abc_Print( 0, "The network is combinational.\n" ); if ( Abc_NtkConstrNum(pNtk) > 0 ) Abc_Print( 0, "The network currently has %d constraints.\n", Abc_NtkConstrNum(pNtk) ); if ( nConstrs >= Abc_NtkPoNum(pNtk) ) { Abc_Print( -1, "The number of constraints specified (%d) should be less than POs (%d).\n", nConstrs, Abc_NtkPoNum(pNtk) ); return 0; } Abc_Print( 1, "Setting the last %d POs as constraint outputs.\n", nConstrs ); pNtk->nConstrs = nConstrs; return 0; } // consider the case of already defined constraints if ( Abc_NtkConstrNum(pNtk) > 0 ) { extern void Abc_NtkDarConstrProfile( Abc_Ntk_t * pNtk, int fVerbose ); if ( fInvert ) { Abc_NtkInvertConstraints( pNtk ); if ( Abc_NtkConstrNum(pNtk) == 1 ) Abc_Print( 1, "The output of %d constraint is complemented.\n", Abc_NtkConstrNum(pNtk) ); else Abc_Print( 1, "The outputs of %d constraints are complemented.\n", Abc_NtkConstrNum(pNtk) ); } if ( fVerbose ) Abc_NtkDarConstrProfile( pNtk, fVerbose ); return 0; } if ( Abc_NtkIsComb(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } // detect constraints using functional/structural methods Abc_NtkDarConstr( pNtk, nFrames, nConfs, nProps, fStruct, fOldAlgo, fVerbose ); return 0; usage: Abc_Print( -2, "usage: constr [-FCPN num] [-risavh]\n" ); Abc_Print( -2, "\t a toolkit for constraint manipulation\n" ); Abc_Print( -2, "\t if constraints are absent, detect them functionally\n" ); Abc_Print( -2, "\t if constraints are present, profiles them using random simulation\n" ); Abc_Print( -2, "\t-F num : the max number of timeframes to consider [default = %d]\n", nFrames ); Abc_Print( -2, "\t-C num : the max number of conflicts in SAT solving [default = %d]\n", nConfs ); Abc_Print( -2, "\t-P num : the max number of propagations in SAT solving [default = %d]\n", nProps ); Abc_Print( -2, "\t-N num : manually set the last POs to be constraints [default = %d]\n", nConstrs ); Abc_Print( -2, "\t-r : manually remove the constraints [default = %s]\n", fRemove? "yes": "no" ); Abc_Print( -2, "\t-i : toggle inverting already defined constraints [default = %s]\n", fInvert? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using structural detection methods [default = %s]\n", fStruct? "yes": "no" ); Abc_Print( -2, "\t-a : toggle fast implication detection [default = %s]\n", !fOldAlgo? "yes": "no" ); 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_CommandUnfold( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int nFrames; int nConfs; int nProps; int fStruct; int fOldAlgo; int fVerbose; int c; extern Abc_Ntk_t * Abc_NtkDarUnfold( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nFrames = 1; nConfs = 1000; nProps = 1000; fStruct = 0; fOldAlgo = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCPsavh" ) ) != 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 '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 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nProps = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nProps < 0 ) goto usage; break; case 's': fStruct ^= 1; break; case 'a': fOldAlgo ^= 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_NtkPoNum(pNtk) > 1 ) { Abc_Print( -1, "Combinational miter has more than one PO.\n" ); return 0; } if ( Abc_NtkIsComb(pNtk) ) { extern Gia_Man_t * Gia_ManDupWithConstr( Gia_Man_t * p ); Gia_Man_t * pNew; Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 0 ); Gia_Man_t * pGia = Gia_ManFromAigSimple( pAig ); Aig_ManStop( pAig ); pNew = Gia_ManDupWithConstr( pGia ); Gia_ManStop( pGia ); if ( pNew == NULL ) { Abc_Print( -1, "Cannot extract constrains from the miter.\n" ); return 0; } pAig = Gia_ManToAigSimple( pNew ); Gia_ManStop( pNew ); pNtkRes = Abc_NtkFromAigPhase( pAig ); Aig_ManStop( pAig ); ABC_FREE( pNtkRes->pName ); pNtkRes->pName = Extra_UtilStrsav( pNtk->pName ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkConstrNum(pNtk) > 0 ) { Abc_Print( -1, "Constraints are already extracted.\n" ); return 0; } if ( Abc_NtkPoNum(pNtk) > 1 && !fStruct ) { Abc_Print( -1, "Functional constraint extraction works for single-output miters (use \"orpos\").\n" ); return 0; } // modify the current network pNtkRes = Abc_NtkDarUnfold( pNtk, nFrames, nConfs, nProps, fStruct, fOldAlgo, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( 1,"Transformation has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: unfold [-FCP num] [-savh]\n" ); Abc_Print( -2, "\t unfold hidden constraints as separate outputs\n" ); Abc_Print( -2, "\t-F num : the max number of timeframes to consider [default = %d]\n", nFrames ); Abc_Print( -2, "\t-C num : the max number of conflicts in SAT solving [default = %d]\n", nConfs ); Abc_Print( -2, "\t-P num : the max number of constraint propagations [default = %d]\n", nProps ); Abc_Print( -2, "\t-s : toggle detecting structural constraints [default = %s]\n", fStruct? "yes": "no" ); Abc_Print( -2, "\t-a : toggle fast implication detection [default = %s]\n", !fOldAlgo? "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_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int fCompl; int fVerbose; int c; extern Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fCompl = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF ) { switch ( c ) { case 'c': fCompl ^= 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, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkConstrNum(pNtk) == 0 ) { Abc_Print( 0, "The network has no constraints.\n" ); return 0; } if ( Abc_NtkIsComb(pNtk) ) Abc_Print( 0, "The network is combinational.\n" ); // modify the current network pNtkRes = Abc_NtkDarFold( pNtk, fCompl, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( 1,"Transformation has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: fold [-cvh]\n" ); Abc_Print( -2, "\t folds constraints represented as separate outputs\n" ); Abc_Print( -2, "\t-c : toggle complementing constraints while folding [default = %s]\n", fCompl? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBm( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t *pNtk, *pNtk1, *pNtk2; int fDelete1, fDelete2; char ** pArgvNew; int c, nArgcNew; int p_equivalence = FALSE; extern void bmGateWay( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int p_equivalence ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Ph" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; case 'P': p_equivalence = 1; break; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew , &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; if( (unsigned)Abc_NtkPiNum(pNtk1) != (unsigned)Abc_NtkPiNum(pNtk2) || (unsigned)Abc_NtkPoNum(pNtk1) != (unsigned)Abc_NtkPoNum(pNtk2) ) { Abc_Print( -2, "Mismatch in the number of inputs or outputs\n"); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 1; } bmGateWay( pNtk1, pNtk2, p_equivalence ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 0; usage: Abc_Print( -2, "usage: bm [-P] \n" ); Abc_Print( -2, "\t performs Boolean matching (P-equivalence & PP-equivalence)\n" ); Abc_Print( -2, "\t for equivalent circuits, I/O matches are printed in IOmatch.txt\n" ); Abc_Print( -2, "\t-P : performs P-equivalnce checking\n"); Abc_Print( -2, "\t default is PP-equivalence checking (when -P is not provided)\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tfile1 : the file with the first network\n"); Abc_Print( -2, "\tfile2 : the file with the second network\n"); Abc_Print( -2, "\t \n" ); Abc_Print( -2, "\t This command was contributed by Hadi Katebi from U Michigan.\n" ); Abc_Print( -2, "\t The paper describing the method: H. Katebi and I. L. Markov.\n" ); Abc_Print( -2, "\t \"Large-scale Boolean matching\". Proc. DATE 2010. \n" ); Abc_Print( -2, "\t http://www.eecs.umich.edu/~imarkov/pubs/conf/date10-match.pdf\n" ); // Abc_Print( -2, "\t \n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBm2( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t *pNtk, *pNtk1, *pNtk2; int fDelete1, fDelete2; Abc_Obj_t * pObj; char ** pArgvNew; int c, nArgcNew, i; extern void saucyGateWay( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodePo, FILE * gFile, int fBooleanMatching, int fLookForSwaps, int fFixOutputs, int fFixInputs, int fQuiet, int fPrintTree); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew , &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) return 1; if( (unsigned)Abc_NtkPiNum(pNtk1) != (unsigned)Abc_NtkPiNum(pNtk2) || (unsigned)Abc_NtkPoNum(pNtk1) != (unsigned)Abc_NtkPoNum(pNtk2) ) { Abc_Print( -2, "Mismatch in the number of inputs or outputs\n"); Abc_Print( -2, "*** Networks are NOT equivalent ***\n"); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 1; } Abc_NtkPermute(pNtk2, 1, 1, 0, NULL ); Abc_NtkShortNames(pNtk2); Abc_NtkForEachCi( pNtk1, pObj, i ) { char * newName = Abc_ObjNamePrefix( pObj, "N1:" ); Nm_ManDeleteIdName( pNtk1->pManName, pObj->Id); Abc_ObjAssignName( pObj, newName, NULL ); } Abc_NtkForEachCo( pNtk1, pObj, i ) { char * newName = Abc_ObjNamePrefix( pObj, "N1:" ); Nm_ManDeleteIdName( pNtk1->pManName, pObj->Id); Abc_ObjAssignName( pObj, newName, NULL ); } Abc_NtkForEachCi( pNtk2, pObj, i ) { char * newName = Abc_ObjNamePrefix( pObj, "N2:" ); Nm_ManDeleteIdName( pNtk2->pManName, pObj->Id); Abc_ObjAssignName( pObj, newName, NULL ); } Abc_NtkForEachCo( pNtk2, pObj, i ) { char * newName = Abc_ObjNamePrefix( pObj, "N2:" ); Nm_ManDeleteIdName( pNtk2->pManName, pObj->Id); Abc_ObjAssignName( pObj, newName, NULL ); } Abc_NtkAppend( pNtk1, pNtk2, 1 ); saucyGateWay( pNtk1, NULL, NULL, 1, 0, 0, 0, 0, 0); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); return 0; usage: Abc_Print( -2, "usage: bm2 \n" ); Abc_Print( -2, "\t performs Boolean matching (PP-equivalence)\n" ); Abc_Print( -2, "\t for equivalent circuits, permutation that maps one circuit\n" ); Abc_Print( -2, "\t to another is printed to standard output (PIs and POs of the\n" ); Abc_Print( -2, "\t first network have prefix \"N1:\", while PIs and POs of the\n" ); Abc_Print( -2, "\t second network have prefix \"N2:\")\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tfile1 : the file with the first network\n"); Abc_Print( -2, "\tfile2 : the file with the second network\n"); Abc_Print( -2, "\t \n" ); Abc_Print( -2, "\t This command was contributed by Hadi Katebi from U Michigan.\n" ); Abc_Print( -2, "\t The paper describing the method: H. Katebi, K. Sakallah and\n"); Abc_Print( -2, "\t I. L. Markov.\n" ); Abc_Print( -2, "\t \"Generalized Boolean Symmetries Through Nested Partition\n"); Abc_Print( -2, "\t Refinement\". Proc. ICCAD 2013. \n" ); //Abc_Print( -2, "\t http://www.eecs.umich.edu/~imarkov/pubs/conf/date10-match.pdf\n" ); // Abc_Print( -2, "\t \n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSaucy( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t *pNtk; char * outputName = NULL; FILE * gFile = NULL; int fOutputsOneAtTime = 0; int fFixOutputs = 0; int fFixInputs = 0; int fLookForSwaps = 0; int fQuiet = 0; int fPrintTree = 0; int c; extern void saucyGateWay( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodePo, FILE * gFile, int fBooleanMatching, int fLookForSwaps, int fFixOutputs, int fFixInputs, int fQuiet, int fPrintTree); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "OFiosqvh" ) ) != EOF ) { switch ( c ) { case 'O': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-O\" should be followed by an output name or the keyword all.\n" ); goto usage; } outputName = argv[globalUtilOptind]; if ( !strcmp(argv[globalUtilOptind], "all") ) fOutputsOneAtTime ^= 1; globalUtilOptind++; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); goto usage; } if ( (gFile = fopen( argv[globalUtilOptind], "w" )) == NULL ) { Abc_Print( -1, "Cannot create output file \"%s\". ", argv[globalUtilOptind] ); return 1; } globalUtilOptind++; break; case 'i': fFixOutputs ^= 1; break; case 'o': fFixInputs ^= 1; break; case 's': fLookForSwaps ^= 1; break; case 'q': fQuiet ^= 1; break; case 'v': fPrintTree ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } pNtk = Abc_FrameReadNtk(pAbc); 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; } pNtk = Abc_NtkDup( pNtk ); Abc_NtkOrderObjsByName( pNtk, 1 ); if (fOutputsOneAtTime) { int i; Abc_Obj_t * pNodePo; FILE * hadi = fopen("hadi.txt", "w"); Abc_NtkForEachPo( pNtk, pNodePo, i ) { printf("Ouput %s\n\n", Abc_ObjName(pNodePo)); saucyGateWay( pNtk, pNodePo, gFile, 0, fLookForSwaps, fFixOutputs, fFixInputs, fQuiet, fPrintTree ); printf("----------------------------------------\n"); } fclose(hadi); } else if (outputName != NULL) { int i; Abc_Obj_t * pNodePo; Abc_NtkForEachPo( pNtk, pNodePo, i ) { if (!strcmp(Abc_ObjName(pNodePo), outputName)) { saucyGateWay( pNtk, pNodePo, gFile, 0, fLookForSwaps, fFixOutputs, fFixInputs, fQuiet, fPrintTree ); Abc_NtkDelete( pNtk ); return 0; } } Abc_Print( -1, "Output not found\n" ); return 1; } else saucyGateWay( pNtk, NULL, gFile, 0, fLookForSwaps, fFixOutputs, fFixInputs, fQuiet, fPrintTree ); if (gFile != NULL) fclose(gFile); Abc_NtkDelete( pNtk ); return 0; usage: Abc_Print( -2, "usage: saucy3 [-O ] [-F ] [-iosqvh]\n\n" ); Abc_Print( -2, "\t computes functional symmetries of the netowrk\n" ); Abc_Print( -2, "\t prints symmetry generators to the standard output\n" ); Abc_Print( -2, "\t-O : (optional) compute symmetries only for output given by name\n"); Abc_Print( -2, "\t only inputs in the output cone are permuted\n"); Abc_Print( -2, "\t (special case) name=all, compute symmetries for each\n" ); Abc_Print( -2, "\t output, but only one output at a time\n" ); Abc_Print( -2, "\t [default = compute symmetries by permuting all I/Os]\n" ); Abc_Print( -2, "\t-F : print symmetry generators to file [default = stdout]\n"); Abc_Print( -2, "\t-i : permute just the inputs (fix the outputs) [default = no]\n"); Abc_Print( -2, "\t-o : permute just the outputs (fix the inputs) [default = no]\n"); Abc_Print( -2, "\t-s : only look for swaps of inputs [default = no]\n"); Abc_Print( -2, "\t-q : quiet (do not print symmetry generators) [default = no]\n"); Abc_Print( -2, "\t-v : verbose (print the search tree) [default = no]\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 Hadi Katebi from U Michigan.\n" ); Abc_Print( -2, "\t The paper describing the method: H. Katebi, K. Sakallah and\n"); Abc_Print( -2, "\t I. L. Markov.\n" ); Abc_Print( -2, "\t \"Generalized Boolean Symmetries Through Nested Partition\n"); Abc_Print( -2, "\t Refinement\". Proc. ICCAD 2013. \n" ); //Abc_Print( -2, "\t http://www.eecs.umich.edu/~imarkov/pubs/conf/date10-match.pdf\n" ); Abc_Print( -2, "\t Saucy webpage: http://vlsicad.eecs.umich.edu/BK/SAUCY/\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestCex( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; int c; int nOutputs = 0; int fCheckAnd = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Oah" ) ) != EOF ) { switch ( c ) { case 'O': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } nOutputs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nOutputs < 0 ) goto usage; break; case 'a': fCheckAnd ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( pAbc->pCex == NULL ) { Abc_Print( 1, "There is no current cex.\n"); return 0; } if ( !fCheckAnd ) { // check the main AIG pNtk = Abc_FrameReadNtk(pAbc); if ( pNtk == NULL ) Abc_Print( 1, "Main AIG: There is no current network.\n"); else if ( !Abc_NtkIsStrash(pNtk) ) Abc_Print( 1, "Main AIG: The current network is not an AIG.\n"); else if ( Abc_NtkPiNum(pNtk) != pAbc->pCex->nPis ) Abc_Print( 1, "Main AIG: The number of PIs (%d) is different from cex (%d).\n", Abc_NtkPiNum(pNtk), pAbc->pCex->nPis ); else { extern int Abc_NtkVerifyCex( Abc_Ntk_t * pNtk, Abc_Cex_t * p ); int iPoOld = pAbc->pCex->iPo; pAbc->pCex->iPo = Abc_NtkVerifyCex( pNtk, pAbc->pCex ); if ( pAbc->pCex->iPo == -1 ) Abc_Print( 1, "Main AIG: The cex does not fail any outputs.\n" ); else if ( iPoOld != pAbc->pCex->iPo ) Abc_Print( 1, "Main AIG: The cex refined PO %d instead of PO %d.\n", pAbc->pCex->iPo, iPoOld ); else Abc_Print( 1, "Main AIG: The cex is correct.\n" ); } } else { // check the AND AIG if ( pAbc->pGia == NULL ) Abc_Print( 1, "And AIG: There is no current network.\n"); else if ( Gia_ManPiNum(pAbc->pGia) != pAbc->pCex->nPis ) Abc_Print( 1, "And AIG: The number of PIs (%d) is different from cex (%d).\n", Gia_ManPiNum(pAbc->pGia), pAbc->pCex->nPis ); else { int iPoOld = pAbc->pCex->iPo; pAbc->pCex->iPo = Gia_ManFindFailedPoCex( pAbc->pGia, pAbc->pCex, nOutputs ); if ( pAbc->pCex->iPo == -1 ) Abc_Print( 1, "And AIG: The cex does not fail any outputs.\n" ); else if ( iPoOld != pAbc->pCex->iPo ) Abc_Print( 1, "And AIG: The cex refined PO %d instead of PO %d.\n", pAbc->pCex->iPo, iPoOld ); else Abc_Print( 1, "And AIG: The cex is correct.\n" ); } } return 0; usage: Abc_Print( -2, "usage: testcex [-O num] [-ah]\n" ); Abc_Print( -2, "\t tests the current cex against the current AIG or the &-AIG\n" ); Abc_Print( -2, "\t-O num : the number of real POs in the PO list [default = %d]\n", nOutputs ); Abc_Print( -2, "\t-a : toggle checking the current AIG or the &-AIG [default = %s]\n", fCheckAnd ? "&-AIG": "current AIG" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NtkDarPdr( Abc_Ntk_t * pNtk, Pdr_Par_t * pPars ); Pdr_Par_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; Pdr_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "MFCDRTHGaxrmsipdegovwzh" ) ) != 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->nRecycle = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRecycle < 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->nFrameMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrameMax < 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->nConfLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nConfLimit < 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->nConfGenLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nConfGenLimit < 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->nRestLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRestLimit < 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->nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOut < 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->nTimeOutOne = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOutOne < 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; } pPars->nTimeOutGap = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOutGap < 0 ) goto usage; break; case 'a': pPars->fSolveAll ^= 1; break; case 'x': pPars->fStoreCex ^= 1; break; case 'r': pPars->fTwoRounds ^= 1; break; case 'm': pPars->fMonoCnf ^= 1; break; case 's': pPars->fShortest ^= 1; break; case 'i': pPars->fShiftStart ^= 1; break; case 'p': pPars->fReuseProofOblig ^= 1; break; case 'd': pPars->fDumpInv ^= 1; break; case 'e': pPars->fUseSupp ^= 1; break; case 'g': pPars->fSkipGeneral ^= 1; break; case 'o': pPars->fUsePropOut ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'z': pPars->fNotVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -2, "There is no current network.\n"); return 0; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( 0, "The current network is combinational.\n"); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n"); return 0; } // run the procedure pPars->fUseBridge = pAbc->fBridgeMode; pAbc->Status = Abc_NtkDarPdr( pNtk, pPars ); pAbc->nFrames = pNtk->vSeqModelVec ? -1 : pPars->iFrame; Abc_FrameReplacePoStatuses( pAbc, &pPars->vOutMap ); if ( pNtk->vSeqModelVec ) Abc_FrameReplaceCexVec( pAbc, &pNtk->vSeqModelVec ); else Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); return 0; usage: Abc_Print( -2, "usage: pdr [-MFCDRTHG ] [-axrmsipdegovwzh]\n" ); Abc_Print( -2, "\t model checking using property directed reachability (aka IC3)\n" ); Abc_Print( -2, "\t pioneered by Aaron Bradley (http://ecee.colorado.edu/~bradleya/ic3/)\n" ); Abc_Print( -2, "\t with improvements by Niklas Een (http://een.se/niklas/)\n" ); Abc_Print( -2, "\t-M num : limit on unused vars to trigger SAT solver recycling [default = %d]\n", pPars->nRecycle ); Abc_Print( -2, "\t-F num : limit on timeframes explored to stop computation [default = %d]\n", pPars->nFrameMax ); Abc_Print( -2, "\t-C num : limit on conflicts in one SAT call (0 = no limit) [default = %d]\n", pPars->nConfLimit ); Abc_Print( -2, "\t-D num : limit on conflicts during ind-generalization (0 = no limit) [default = %d]\n",pPars->nConfGenLimit ); Abc_Print( -2, "\t-R num : limit on proof obligations before a restart (0 = no limit) [default = %d]\n", pPars->nRestLimit ); Abc_Print( -2, "\t-T num : runtime limit, in seconds (0 = no limit) [default = %d]\n", pPars->nTimeOut ); Abc_Print( -2, "\t-H num : runtime limit per output, in miliseconds (with \"-a\") [default = %d]\n", pPars->nTimeOutOne ); Abc_Print( -2, "\t-G num : runtime gap since the last CEX (0 = no limit) [default = %d]\n", pPars->nTimeOutGap ); Abc_Print( -2, "\t-a : toggle solving all outputs even if one of them is SAT [default = %s]\n", pPars->fSolveAll? "yes": "no" ); Abc_Print( -2, "\t-x : toggle storing CEXes when solving all outputs [default = %s]\n", pPars->fStoreCex? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using more effort in generalization [default = %s]\n", pPars->fTwoRounds? "yes": "no" ); Abc_Print( -2, "\t-m : toggle using monolythic CNF computation [default = %s]\n", pPars->fMonoCnf? "yes": "no" ); Abc_Print( -2, "\t-s : toggle creating only shortest counter-examples [default = %s]\n", pPars->fShortest? "yes": "no" ); Abc_Print( -2, "\t-i : toggle clause pushing from an intermediate timeframe [default = %s]\n", pPars->fShiftStart? "yes": "no" ); Abc_Print( -2, "\t-p : toggle reusing proof-obligations in the last timeframe [default = %s]\n", pPars->fReuseProofOblig? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dumping invariant (valid if init state is all-0) [default = %s]\n", pPars->fDumpInv? "yes": "no" ); Abc_Print( -2, "\t-e : toggle using only support variables in the invariant [default = %s]\n", pPars->fUseSupp? "yes": "no" ); Abc_Print( -2, "\t-g : toggle skipping expensive generalization step [default = %s]\n", pPars->fSkipGeneral? "yes": "no" ); Abc_Print( -2, "\t-o : toggle using property output as inductive hypothesis [default = %s]\n", pPars->fUsePropOut? "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 default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-z : toggle suppressing report about solved outputs [default = %s]\n", pPars->fNotVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandReconcile( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm ); Abc_Cex_t * pCex; Abc_Ntk_t * pNtk1 = NULL, * pNtk2 = NULL; Aig_Man_t * pAig1 = NULL, * pAig2 = NULL; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( argc != globalUtilOptind + 2 && argc != globalUtilOptind ) { Abc_Print( 1,"Does not seen to have two files names as arguments.\n" ); return 1; } if ( pAbc->pCex == NULL ) { Abc_Print( 1,"There is no current counter-example.\n" ); return 1; } if ( argc == globalUtilOptind + 2 ) { // derive networks pNtk1 = Io_Read( argv[globalUtilOptind], Io_ReadFileType(argv[globalUtilOptind]), 1, 0 ); if ( pNtk1 == NULL ) return 1; pNtk2 = Io_Read( argv[globalUtilOptind+1], Io_ReadFileType(argv[globalUtilOptind+1]), 1, 0 ); if ( pNtk2 == NULL ) { Abc_NtkDelete( pNtk1 ); return 1; } // create counter-examples pAig1 = Abc_NtkToDar( pNtk1, 0, 0 ); pAig2 = Abc_NtkToDar( pNtk2, 0, 0 ); } else if ( argc == globalUtilOptind ) { if ( pAbc->pNtkCur == NULL ) { Abc_Print( 1, "There is no AIG in the main-space.\n"); return 0; } if ( pAbc->pGia == NULL ) { Abc_Print( 1, "There is no AIG in the &-space.\n"); return 0; } // create counter-examples pAig1 = Abc_NtkToDar( pAbc->pNtkCur, 0, 0 ); pAig2 = Gia_ManToAigSimple( pAbc->pGia ); } else assert( 0 ); pCex = Llb4_Nonlin4NormalizeCex( pAig1, pAig2, pAbc->pCex ); Aig_ManStop( pAig1 ); Aig_ManStop( pAig2 ); if ( pNtk2 ) Abc_NtkDelete( pNtk2 ); if ( pCex == NULL ) { Abc_Print( 1,"Counter-example computation has failed.\n" ); if ( pNtk1 ) Abc_NtkDelete( pNtk1 ); return 1; } // replace the current network if ( pNtk1 ) Abc_FrameReplaceCurrentNetwork( pAbc, pNtk1 ); // update the counter-example pAbc->nFrames = pCex->iFrame; Abc_FrameReplaceCex( pAbc, &pCex ); return 0; usage: Abc_Print( -2, "usage: reconcile [-h] \n" ); Abc_Print( -2, "\t reconciles current CEX with \n" ); Abc_Print( -2, "\t More specifically:\n" ); Abc_Print( -2, "\t (i) assumes that is an AIG derived by input\n" ); Abc_Print( -2, "\t reparametrization of without seq synthesis;\n" ); Abc_Print( -2, "\t (ii) assumes that current CEX is valid for ;\n" ); Abc_Print( -2, "\t (iii) derives new CEX for and sets this CEX\n" ); Abc_Print( -2, "\t and to be current CEX and current network\n" ); Abc_Print( -2, "\t : file name with the original AIG\n"); Abc_Print( -2, "\t : file name with the reparametrized AIG\n"); Abc_Print( -2, "\t (if both file names are not given on the command line,\n"); Abc_Print( -2, "\t original/reparam AIG has to be in the main-space/&-space)\n"); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } #endif /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCexSave( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Current CEX is not available..\n" ); return 1; } ABC_FREE( pAbc->pCex2 ); pAbc->pCex2 = Abc_CexDup( pAbc->pCex, -1 ); return 0; usage: Abc_Print( -2, "usage: cexsave [-h]\n" ); Abc_Print( -2, "\t saves the current CEX into the internal storage\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCexLoad( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pCex2 == NULL ) { Abc_Print( -1, "Saved CEX is not available.\n" ); return 1; } ABC_FREE( pAbc->pCex ); pAbc->pCex = Abc_CexDup( pAbc->pCex2, -1 ); // update status pAbc->nFrames = pAbc->pCex2->iFrame; pAbc->Status = 0; return 0; usage: Abc_Print( -2, "usage: cexload [-h]\n" ); Abc_Print( -2, "\t loads the current CEX from the internal storage\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCexCut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtkNew; int c, iFrStart = 0; int iFrStop = ABC_INFINITY; int fCombOnly = 0; int fUseOne = 0; int fAllFrames = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FGcnmvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } iFrStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrStart < 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; } iFrStop = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrStop < 0 ) goto usage; break; case 'c': fCombOnly ^= 1; break; case 'n': fUseOne ^= 1; break; case 'm': fAllFrames ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( pAbc->pCex == NULL ) { Abc_Print( 1, "There is no current cex.\n"); return 0; } if ( pAbc->pNtkCur == NULL ) { Abc_Print( 1, "There is no AIG in the &-space.\n"); return 0; } if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) { Abc_Print( 1, "Current network is not an AIG.\n"); return 0; } if ( iFrStop == ABC_INFINITY ) iFrStop = pAbc->pCex->iFrame; { Aig_Man_t * pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 ); Aig_Man_t * pAigNew = Bmc_AigTargetStates( pAig, pAbc->pCex, iFrStart, iFrStop, fCombOnly, fUseOne, fAllFrames, fVerbose ); Aig_ManStop( pAig ); if ( pAigNew == NULL ) { Abc_Print( 1, "Command has failed.\n"); return 0; } pNtkNew = Abc_NtkFromAigPhase( pAigNew ); pNtkNew->pName = Extra_UtilStrsav( pAbc->pNtkCur->pName ); Aig_ManStop( pAigNew ); // update the network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); } /* pGiaNew = Bmc_GiaTargetStates( pAbc->pGia, pAbc->pCex, iFrStart, iFrStop, fCombOnly, fUseOne, fVerbose ); if ( pGiaNew == NULL ) { Abc_Print( 1, "Command has failed.\n"); return 0; } Abc_FrameUpdateGia( pAbc, pGiaNew ); */ return 0; usage: Abc_Print( -2, "usage: cexcut [-FG num] [-cnmvh]\n" ); Abc_Print( -2, "\t creates logic for bad states using the current CEX\n" ); Abc_Print( -2, "\t-F num : 0-based number of the starting frame [default = %d]\n", iFrStart ); Abc_Print( -2, "\t-G num : 0-based number of the ending frame [default = %d]\n", iFrStop ); Abc_Print( -2, "\t-c : toggle outputting unate combinational circuit [default = %s]\n", fCombOnly? "yes": "no" ); Abc_Print( -2, "\t-n : toggle generating only one bad state [default = %s]\n", fUseOne? "yes": "no" ); Abc_Print( -2, "\t-m : toggle generating bad states for all frames after G [default = %s]\n", fAllFrames? "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_CommandCexMerge( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Cex_t * pCexNew; int c; int iFrStart = 0; int iFrStop = ABC_INFINITY; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FGvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } iFrStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrStart < 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; } iFrStop = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrStop < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( pAbc->pCex == NULL ) { Abc_Print( 1, "There is no current cex.\n"); return 0; } if ( pAbc->pCex2 == NULL ) { Abc_Print( 1, "There is no saved cex.\n"); return 0; } if ( iFrStop - iFrStart + pAbc->pCex->iPo < pAbc->pCex->iFrame ) { Abc_Print( 1, "Current CEX does not allow to shorten the saved CEX.\n"); return 0; } pCexNew = Abc_CexMerge( pAbc->pCex2, pAbc->pCex, iFrStart, iFrStop ); if ( pCexNew == NULL ) { Abc_Print( 1, "Merging CEXes has failed.\n"); return 0; } // replace the saved CEX ABC_FREE( pAbc->pCex2 ); pAbc->pCex2 = pCexNew; return 0; usage: Abc_Print( -2, "usage: cexmerge [-FG num] [-vh]\n" ); Abc_Print( -2, "\t merges the current CEX into the saved one\n" ); Abc_Print( -2, "\t and sets the resulting CEX as the saved one\n" ); Abc_Print( -2, "\t-F num : 0-based number of the starting frame [default = %d]\n", iFrStart ); Abc_Print( -2, "\t-G num : 0-based number of the ending frame [default = %d]\n", iFrStop ); 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_CommandCexMin( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; Abc_Cex_t * vCexNew = NULL; int c; int nConfLimit = 1000; int nRounds = 1; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CRvh" ) ) != 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 '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 'v': fVerbose ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( pAbc->pCex == NULL ) { Abc_Print( 1, "There is no current cex.\n"); return 0; } // check the main AIG pNtk = Abc_FrameReadNtk(pAbc); if ( pNtk == NULL ) Abc_Print( 1, "Main AIG: There is no current network.\n"); else if ( !Abc_NtkIsStrash(pNtk) ) Abc_Print( 1, "Main AIG: The current network is not an AIG.\n"); else if ( Abc_NtkPiNum(pNtk) != pAbc->pCex->nPis ) Abc_Print( 1, "Main AIG: The number of PIs (%d) is different from cex (%d).\n", Abc_NtkPiNum(pNtk), pAbc->pCex->nPis ); // else if ( Abc_NtkLatchNum(pNtk) != pAbc->pCex->nRegs ) // Abc_Print( 1, "Main AIG: The number of registers (%d) is different from cex (%d).\n", Abc_NtkLatchNum(pNtk), pAbc->pCex->nRegs ); // else if ( Abc_NtkPoNum(pNtk) <= pAbc->pCex->iPo ) // Abc_Print( 1, "Main AIG: The number of POs (%d) is less than the PO index in cex (%d).\n", Abc_NtkPoNum(pNtk), pAbc->pCex->iPo ); else { Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); Gia_Man_t * pGia = Gia_ManFromAigSimple( pAig ); // if ( !Gia_ManVerifyCex( pGia, pAbc->pCex, 0 ) ) int iPoOld = pAbc->pCex->iPo; pAbc->pCex->iPo = Gia_ManFindFailedPoCex( pGia, pAbc->pCex, 0 ); Gia_ManStop( pGia ); if ( pAbc->pCex->iPo == -1 ) { pAbc->pCex->iPo = iPoOld; Abc_Print( -1, "Main AIG: The cex does not fail any outputs.\n" ); return 0; } else if ( iPoOld != pAbc->pCex->iPo ) Abc_Print( 0, "Main AIG: The cex refined PO %d instead of PO %d.\n", pAbc->pCex->iPo, iPoOld ); // perform minimization vCexNew = Saig_ManCexMinPerform( pAig, pAbc->pCex ); Aig_ManStop( pAig ); Abc_CexFree( vCexNew ); // Abc_FrameReplaceCex( pAbc, &vCexNew ); // Abc_Print( 1,"Implementation of this command is not finished.\n" ); } return 0; usage: Abc_Print( -2, "usage: cexmin [-CR num] [-vh]\n" ); Abc_Print( -2, "\t reduces the length of the counter-example\n" ); Abc_Print( -2, "\t-C num : the maximum number of conflicts [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-R num : the number of minimization rounds [default = %d]\n", nRounds ); 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_CommandDualRail( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Int_t * Abc_NtkFindDcLatches( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pNtk, * pNtkNew = NULL; Aig_Man_t * pAig, * pAigNew; Vec_Int_t * vDcFlops = NULL; int c; int nDualPis = 0; int fDualFfs = 0; int fDualDcFfs = 0; int fMiterFfs = 0; int fComplPo = 0; int fCheckZero = 0; int fCheckOne = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Itxfczovh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nDualPis = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDualPis < 0 ) goto usage; break; case 't': fDualFfs ^= 1; break; case 'x': fDualDcFfs ^= 1; break; case 'f': fMiterFfs ^= 1; break; case 'c': fComplPo ^= 1; break; case 'z': fCheckZero ^= 1; break; case 'o': fCheckOne ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } // check the main AIG pNtk = Abc_FrameReadNtk(pAbc); if ( pNtk == NULL ) { Abc_Print( 1, "Main AIG: There is no current network.\n"); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( 1, "Main AIG: The current network is not an AIG.\n"); return 0; } if ( fDualDcFfs ) vDcFlops = Abc_NtkFindDcLatches( pNtk ); // transform pAig = Abc_NtkToDar( pNtk, 0, 1 ); pAigNew = Saig_ManDupDual( pAig, vDcFlops, nDualPis, fDualFfs, fMiterFfs, fComplPo, fCheckZero, fCheckOne ); Aig_ManStop( pAig ); pNtkNew = Abc_NtkFromAigPhase( pAigNew ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); Aig_ManStop( pAigNew ); Vec_IntFreeP( &vDcFlops ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); return 0; usage: Abc_Print( -2, "usage: dualrail [-I num] [-txfczovh]\n" ); Abc_Print( -2, "\t transforms the current AIG into a dual-rail miter\n" ); Abc_Print( -2, "\t expressing the property \"at least one PO has ternary value\"\n" ); Abc_Print( -2, "\t (to compute an initialization sequence, use switches \"-tfc\")\n" ); Abc_Print( -2, "\t-I num : the number of first PIs interpreted as ternary [default = %d]\n", nDualPis ); Abc_Print( -2, "\t-t : toggle ternary flop init values for all flops [default = %s]\n", fDualFfs? "yes": "const0 init values" ); Abc_Print( -2, "\t-x : toggle ternary flop init values for DC-valued flops [default = %s]\n", fDualDcFfs? "yes": "const0 init values" ); Abc_Print( -2, "\t-f : toggle mitering flops instead of POs [default = %s]\n", fMiterFfs? "flops": "POs" ); Abc_Print( -2, "\t-c : toggle complementing the miter output [default = %s]\n", fComplPo? "yes": "no" ); Abc_Print( -2, "\t-z : toggle checking PO==0 instead of PO==X [default = %s]\n", fCheckZero? "yes": "no" ); Abc_Print( -2, "\t-o : toggle checking PO==1 instead of PO==X [default = %s]\n", fCheckOne? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBlockPo( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkNew = NULL; Aig_Man_t * pAig; int c; int nCycles = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nCycles = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCycles < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } // check the main AIG pNtk = Abc_FrameReadNtk(pAbc); if ( pNtk == NULL ) { Abc_Print( 1, "Main AIG: There is no current network.\n"); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( 1, "Main AIG: The current network is not an AIG.\n"); return 0; } if ( nCycles == 0 ) { Abc_Print( 1, "The number of time frame is 0. The circuit is left unchanged.\n" ); return 0; } // transform pAig = Abc_NtkToDar( pNtk, 0, 1 ); Saig_ManBlockPo( pAig, nCycles ); pNtkNew = Abc_NtkFromAigPhase( pAig ); Aig_ManStop( pAig ); // transfer the name pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); return 0; usage: Abc_Print( -2, "usage: blockpo [-F num] [-fvh]\n" ); Abc_Print( -2, "\t forces the miter outputs to be \"true\" in the first F frames\n" ); Abc_Print( -2, "\t-F num : the number of time frames [default = %d]\n", nCycles ); 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_CommandIso( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkNew = NULL; Aig_Man_t * pAig, * pTemp; Vec_Ptr_t * vPosEquivs = 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: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } // check the main AIG pNtk = Abc_FrameReadNtk(pAbc); if ( pNtk == NULL ) { Abc_Print( 1, "Main AIG: There is no current network.\n"); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( 1, "Main AIG: The current network is not an AIG.\n"); return 0; } if ( Abc_NtkPoNum(pNtk) == 1 ) { Abc_Print( 1, "Current AIG has only one PO. Transformation is not performed.\n"); return 0; } // transform pAig = Abc_NtkToDar( pNtk, 0, 1 ); pTemp = Saig_ManIsoReduce( pAig, &vPosEquivs, fVerbose ); pNtkNew = Abc_NtkFromAigPhase( pTemp ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); Aig_ManStop( pTemp ); Aig_ManStop( pAig ); // update the internal storage of PO equivalences Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); return 0; usage: Abc_Print( -2, "usage: iso [-vh]\n" ); Abc_Print( -2, "\t removes POs with isomorphic sequential COI\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_CommandTraceStart( 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command is applicable to AIGs.\n" ); return 1; } /* Abc_HManStart(); if ( !Abc_HManPopulate( pNtk ) ) { Abc_Print( -1, "Failed to start the tracing database.\n" ); return 1; } */ return 0; usage: Abc_Print( -2, "usage: trace_start [-h]\n" ); Abc_Print( -2, "\t starts verification tracing\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTraceCheck( 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command is applicable to AIGs.\n" ); return 1; } /* if ( !Abc_HManIsRunning(pNtk) ) { Abc_Print( -1, "The tracing database is not available.\n" ); return 1; } if ( !Abc_HManVerify( 1, pNtk->Id ) ) Abc_Print( -1, "Verification failed.\n" ); Abc_HManStop(); */ return 0; usage: Abc_Print( -2, "usage: trace_check [-h]\n" ); Abc_Print( -2, "\t checks the current network using verification trace\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc3_ReadShowHie( char * pFileName, int fFlat ); Gia_Man_t * pAig = NULL; FILE * pFile; char ** pArgvNew; char * FileName, * pTemp; int c, nArgcNew; int fUseMini = 0; int fVerbose = 0; int fGiaSimple = 0; int fSkipStrash = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "csmvh" ) ) != EOF ) { switch ( c ) { case 'c': fGiaSimple ^= 1; break; case 's': fSkipStrash ^= 1; break; case 'm': fUseMini ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "There is no file name.\n" ); return 1; } // get the input file name FileName = pArgvNew[0]; // fix the wrong symbol for ( pTemp = FileName; *pTemp; pTemp++ ) if ( *pTemp == '>' ) *pTemp = '\\'; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); if ( fUseMini ) pAig = Gia_ManReadMiniAig( FileName ); // else if ( Extra_FileIsType( FileName, ".v", NULL, NULL ) ) // Abc3_ReadShowHie( FileName, fSkipStrash ); else pAig = Gia_AigerRead( FileName, fGiaSimple, fSkipStrash, 0 ); if ( pAig ) Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: Abc_Print( -2, "usage: &r [-csmvh] \n" ); Abc_Print( -2, "\t reads the current AIG from the AIGER file\n" ); Abc_Print( -2, "\t-c : toggles reading simple AIG [default = %s]\n", fGiaSimple? "yes": "no" ); Abc_Print( -2, "\t-s : toggles structural hashing while reading [default = %s]\n", !fSkipStrash? "yes": "no" ); Abc_Print( -2, "\t-m : toggles reading MiniAIG rather than AIGER file [default = %s]\n", fUseMini? "yes": "no" ); Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9ReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose ); Gia_Man_t * pAig; FILE * pFile; char ** pArgvNew; char * FileName, * pTemp; int nArgcNew; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "There is no file name.\n" ); return 1; } // get the input file name FileName = pArgvNew[0]; // fix the wrong symbol for ( pTemp = FileName; *pTemp; pTemp++ ) if ( *pTemp == '>' ) *pTemp = '\\'; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".blif", NULL, NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); pAig = Abc_NtkHieCecTest( FileName, fVerbose ); Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: Abc_Print( -2, "usage: &read_blif [-vh] \n" ); Abc_Print( -2, "\t a specialized reader for hierarchical BLIF files\n" ); Abc_Print( -2, "\t (for general-purpose BLIFs, please use \"read_blif\")\n" ); Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9ReadCBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose ); Gia_Man_t * pAig; FILE * pFile; char ** pArgvNew; char * FileName, * pTemp; char * pModelName = NULL; int nArgcNew; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by a file name.\n" ); goto usage; } pModelName = argv[globalUtilOptind]; globalUtilOptind++; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "There is no file name.\n" ); return 1; } // get the input file name FileName = pArgvNew[0]; // fix the wrong symbol for ( pTemp = FileName; *pTemp; pTemp++ ) if ( *pTemp == '>' ) *pTemp = '\\'; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".cblif", NULL, NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); pAig = Abc_NtkHieCecTest2( FileName, pModelName, fVerbose ); Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: Abc_Print( -2, "usage: &read_cblif [-M name] [-vh] \n" ); Abc_Print( -2, "\t reads CBLIF file and collapse it into an AIG\n" ); Abc_Print( -2, "\t-M name: module name to collapse [default = ]\n" ); Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9ReadStg( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pAig; FILE * pFile; char * FileName, ** pArgvNew; int c, nArgcNew; int kHot = 1; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } kHot = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( kHot < 1 || kHot > 5 ) goto usage; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "There is no file name.\n" ); return 1; } // get the input file name FileName = pArgvNew[0]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); return 1; } fclose( pFile ); pAig = Gia_ManStgRead( FileName, kHot, fVerbose ); Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: Abc_Print( -2, "usage: &read_stg [-K ] [-vh] \n" ); Abc_Print( -2, "\t reads STG file and generates K-hot-encoded AIG\n" ); Abc_Print( -2, "\t-K num : the K parameter for hotness of the encoding (1 <= K <= 5) [default = %d]\n", kHot ); Abc_Print( -2, "\t-v : toggles printing state codes [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9ReadVer( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; Gia_Man_t * pAig; FILE * pFile; char ** pArgvNew; char * pFileName, * pTemp; int nArgcNew; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "There is no file name.\n" ); return 1; } // get the input file name pFileName = pArgvNew[0]; // fix the wrong symbol for ( pTemp = pFileName; *pTemp; pTemp++ ) if ( *pTemp == '>' ) *pTemp = '\\'; if ( (pFile = fopen( pFileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); // read hierarchical Verilog pNtk = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 0 ); if ( pNtk == NULL ) { Abc_Print( -1, "Reading hierarchical Verilog has failed.\n" ); return 1; } pAig = Abc_NtkFlattenHierarchyGia( pNtk, NULL, fVerbose ); Abc_NtkDelete( pNtk ); Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: Abc_Print( -2, "usage: &read_ver [-vh] \n" ); Abc_Print( -2, "\t a specialized reader for hierarchical Verilog files\n" ); Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Get( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Aig_Man_t * Abc_NtkToDarChoices( Abc_Ntk_t * pNtk ); extern Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk ); extern Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pStrash; Aig_Man_t * pAig; Gia_Man_t * pGia, * pTemp; char * pInits; int c, fGiaSimple = 0, fMapped = 0, fNames = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cmnvh" ) ) != EOF ) { switch ( c ) { case 'c': fGiaSimple ^= 1; break; case 'm': fMapped ^= 1; break; case 'n': fNames ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { Abc_Print( -1, "There is no current network\n" ); return 1; } if ( !Abc_NtkIsStrash( pAbc->pNtkCur ) ) { if ( fGiaSimple || fMapped ) { assert( Abc_NtkIsLogic(pAbc->pNtkCur) ); Abc_NtkToAig( pAbc->pNtkCur ); pGia = Abc_NtkAigToGia( pAbc->pNtkCur, fGiaSimple ); } else { // derive comb GIA pStrash = Abc_NtkStrash( pAbc->pNtkCur, 0, 1, 0 ); pAig = Abc_NtkToDar( pStrash, 0, 0 ); Abc_NtkDelete( pStrash ); pGia = Gia_ManFromAig( pAig ); Aig_ManStop( pAig ); // perform undc/zero pInits = Abc_NtkCollectLatchValuesStr( pAbc->pNtkCur ); pGia = Gia_ManDupZeroUndc( pTemp = pGia, pInits, 0, fVerbose ); Gia_ManStop( pTemp ); ABC_FREE( pInits ); } } else { if ( Abc_NtkGetChoiceNum(pAbc->pNtkCur) ) pAig = Abc_NtkToDarChoices( pAbc->pNtkCur ); else pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 ); pGia = Gia_ManFromAig( pAig ); Aig_ManStop( pAig ); } // copy names if ( fNames ) { pGia->vNamesIn = Abc_NtkCollectCiNames( pAbc->pNtkCur ); pGia->vNamesOut = Abc_NtkCollectCoNames( pAbc->pNtkCur ); } // copy user timing information if ( pAbc->pNtkCur->pManTime != NULL ) { Abc_Ntk_t * pNtk = pAbc->pNtkCur; Vec_FltFreeP( &pGia->vInArrs ); Vec_FltFreeP( &pGia->vOutReqs ); pGia->DefInArrs = Abc_NtkReadDefaultArrivalWorst(pNtk); pGia->DefOutReqs = Abc_NtkReadDefaultRequiredWorst(pNtk); pGia->vInArrs = Vec_FltAllocArray( Abc_NtkGetCiArrivalFloats(pNtk), Abc_NtkCiNum(pNtk) ); pGia->vOutReqs = Vec_FltAllocArray( Abc_NtkGetCoRequiredFloats(pNtk), Abc_NtkCoNum(pNtk) ); } Abc_FrameUpdateGia( pAbc, pGia ); return 0; usage: Abc_Print( -2, "usage: &get [-cmnvh] \n" ); Abc_Print( -2, "\t converts the current network into GIA and moves it to the &-space\n" ); Abc_Print( -2, "\t (if the network is a sequential logic network, normalizes the flops\n" ); Abc_Print( -2, "\t to have const-0 initial values, equivalent to \"undc; st; zero\")\n" ); Abc_Print( -2, "\t-c : toggles allowing simple GIA to be imported [default = %s]\n", fGiaSimple? "yes": "no" ); Abc_Print( -2, "\t-m : toggles preserving the current mapping [default = %s]\n", fMapped? "yes": "no" ); Abc_Print( -2, "\t-n : toggles saving CI/CO names of the AIG [default = %s]\n", fNames? "yes": "no" ); Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ); extern void Abc_NtkRedirectCiCo( Abc_Ntk_t * pNtk ); Aig_Man_t * pMan; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, fVerbose = 0; int fStatusClear = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) { switch ( c ) { case 's': fStatusClear ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Gia_ManHasCellMapping(pAbc->pGia) ) { extern Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p ); pNtk = Abc_NtkFromCellMappedGia( pAbc->pGia ); } else if ( Gia_ManHasMapping(pAbc->pGia) || pAbc->pGia->pMuxes ) { extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p ); pNtk = Abc_NtkFromMappedGia( pAbc->pGia ); } else if ( Gia_ManHasDangling(pAbc->pGia) == 0 ) { pMan = Gia_ManToAig( pAbc->pGia, 0 ); pNtk = Abc_NtkFromAigPhase( pMan ); pNtk->pName = Extra_UtilStrsav(pMan->pName); Aig_ManStop( pMan ); } else { Abc_Ntk_t * pNtkNoCh; // Abc_Print( -1, "Transforming AIG with %d choice nodes.\n", Gia_ManEquivCountClasses(pAbc->pGia) ); // create network without choices pMan = Gia_ManToAig( pAbc->pGia, 0 ); pNtkNoCh = Abc_NtkFromAigPhase( pMan ); pNtkNoCh->pName = Extra_UtilStrsav(pMan->pName); Aig_ManStop( pMan ); // derive network with choices pMan = Gia_ManToAig( pAbc->pGia, 1 ); pNtk = Abc_NtkFromDarChoices( pNtkNoCh, pMan ); Abc_NtkDelete( pNtkNoCh ); Aig_ManStop( pMan ); } // transfer PI names to pNtk if ( pAbc->pGia->vNamesIn ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachCi( pNtk, pObj, i ) { if (i < Vec_PtrSize(pAbc->pGia->vNamesIn)) { Nm_ManDeleteIdName(pNtk->pManName, pObj->Id); Abc_ObjAssignName( pObj, (char *)Vec_PtrEntry(pAbc->pGia->vNamesIn, i), NULL ); } } } // transfer PO names to pNtk if ( pAbc->pGia->vNamesOut ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachCo( pNtk, pObj, i ) { if (i < Vec_PtrSize(pAbc->pGia->vNamesOut)) { Nm_ManDeleteIdName(pNtk->pManName, pObj->Id); Abc_ObjAssignName( pObj, (char *)Vec_PtrEntry(pAbc->pGia->vNamesOut, i), NULL ); } } } // decouple CI/CO with the same name if ( pAbc->pGia->vNamesIn || pAbc->pGia->vNamesOut ) Abc_NtkRedirectCiCo( pNtk ); // transfer timing information if ( pAbc->pGia->vInArrs || pAbc->pGia->vOutReqs ) { Abc_Obj_t * pObj; int i; Abc_NtkTimeInitialize( pNtk, NULL ); Abc_NtkTimeSetDefaultArrival( pNtk, pAbc->pGia->DefInArrs, pAbc->pGia->DefInArrs ); Abc_NtkTimeSetDefaultRequired( pNtk, pAbc->pGia->DefOutReqs, pAbc->pGia->DefOutReqs ); if ( pAbc->pGia->vInArrs ) Abc_NtkForEachCi( pNtk, pObj, i ) Abc_NtkTimeSetArrival( pNtk, Abc_ObjId(pObj), Vec_FltEntry(pAbc->pGia->vInArrs, i), Vec_FltEntry(pAbc->pGia->vInArrs, i) ); if ( pAbc->pGia->vOutReqs ) Abc_NtkForEachCo( pNtk, pObj, i ) Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pObj), Vec_FltEntry(pAbc->pGia->vOutReqs, i), Vec_FltEntry(pAbc->pGia->vOutReqs, i) ); } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); if ( fStatusClear ) Abc_FrameClearVerifStatus( pAbc ); return 0; usage: Abc_Print( -2, "usage: &put [-svh]\n" ); Abc_Print( -2, "\t transfer the current network into the old ABC\n" ); Abc_Print( -2, "\t-s : toggle clearning verification status [default = %s]\n", fStatusClear? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [Compares to versions of the design and finds the best.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManCompareWithBest( Gia_Man_t * pBest, Gia_Man_t * p, int * pnBestLuts, int * pnBestEdges, int * pnBestLevels, int fArea ) { int nCurLuts, nCurEdges, nCurLevels; Gia_ManLutParams( p, &nCurLuts, &nCurEdges, &nCurLevels ); if ( pBest == NULL || Gia_ManPiNum(pBest) != Gia_ManPiNum(p) || Gia_ManPoNum(pBest) != Gia_ManPoNum(p) || Gia_ManRegNum(pBest) != Gia_ManRegNum(p) || strcmp(Gia_ManName(pBest), Gia_ManName(p)) || (!fArea && (*pnBestLevels > nCurLevels || (*pnBestLevels == nCurLevels && 2*(*pnBestLuts) + *pnBestEdges > 2*nCurLuts + nCurEdges))) || ( fArea && (*pnBestLuts > nCurLuts || (*pnBestLuts == nCurLuts && *pnBestLevels > nCurLevels))) ) { *pnBestLuts = nCurLuts; *pnBestEdges = nCurEdges; *pnBestLevels = nCurLevels; return 1; } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Save( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, fArea = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) { switch ( c ) { case 'a': fArea ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "GIA has no mapping.\n" ); return 1; } if ( !Gia_ManCompareWithBest( pAbc->pGiaBest, pAbc->pGia, &pAbc->nBestLuts, &pAbc->nBestEdges, &pAbc->nBestLevels, fArea ) ) return 0; // save the design as best Gia_ManStopP( &pAbc->pGiaBest ); pAbc->pGiaBest = Gia_ManDupWithAttributes( pAbc->pGia ); return 0; usage: Abc_Print( -2, "usage: &save [-ah]\n" ); Abc_Print( -2, "\t compares and possibly saves AIG with mapping\n" ); Abc_Print( -2, "\t-a : toggle using area as the primary metric [default = %s]\n", fArea? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Load( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } // restore from best if ( pAbc->pGiaBest == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Load(): There is no best design saved.\n" ); return 1; } Gia_ManStopP( &pAbc->pGia ); pAbc->pGia = Gia_ManDupWithAttributes( pAbc->pGiaBest ); return 0; usage: Abc_Print( -2, "usage: &load [-h]\n" ); Abc_Print( -2, "\t loads previously saved AIG with mapping" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9WriteVer( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileSpec = NULL; Abc_Ntk_t * pNtkSpec = NULL; char * pFileName; char ** pArgvNew; int c, nArgcNew; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Svh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by a file name.\n" ); goto usage; } pFileSpec = argv[globalUtilOptind]; globalUtilOptind++; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "Expecting output file name on the command line.\n" ); return 1; } pFileName = argv[globalUtilOptind]; if ( pAbc->pNtkCur == NULL ) { Abc_Print( -1, "There is no mapped file to write.\n" ); return 1; } if ( pFileSpec == NULL ) { Abc_Print( -1, "The specification file is not given.\n" ); return 1; } pNtkSpec = Io_ReadNetlist( pFileSpec, Io_ReadFileType(pFileSpec), 0 ); if ( pNtkSpec == NULL ) { Abc_Print( -1, "Reading hierarchical Verilog for the specification has failed.\n" ); return 1; } Abc_NtkInsertHierarchyGia( pNtkSpec, pAbc->pNtkCur, fVerbose ); Io_WriteVerilog( pNtkSpec, pFileName ); Abc_NtkDelete( pNtkSpec ); return 0; usage: Abc_Print( -2, "usage: &write_ver [-S ] [-vh] \n" ); Abc_Print( -2, "\t writes hierarchical Verilog after mapping\n" ); Abc_Print( -2, "\t-S file : file name for the original hierarchical design (required)\n" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileName; char ** pArgvNew; int c, nArgcNew; int fUnique = 0; int fMiniAig = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "umvh" ) ) != EOF ) { switch ( c ) { case 'u': fUnique ^= 1; break; case 'm': fMiniAig ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "There is no file name.\n" ); return 1; } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Write(): There is no AIG to write.\n" ); return 1; } pFileName = argv[globalUtilOptind]; if ( fUnique ) { Gia_Man_t * pGia = Gia_ManIsoCanonicize( pAbc->pGia, fVerbose ); Gia_AigerWriteSimple( pGia, pFileName ); Gia_ManStop( pGia ); } else if ( fMiniAig ) Gia_ManWriteMiniAig( pAbc->pGia, pFileName ); else Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0 ); return 0; usage: Abc_Print( -2, "usage: &w [-umvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9WriteLut( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_AigerWriteLut( Gia_Man_t * pGia, char * pFileName ); char * pFileName; char ** pArgvNew; int c, nArgcNew; int 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; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "There is no file name.\n" ); return 1; } pFileName = argv[globalUtilOptind]; if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9WriteLut(): There is no AIG to write.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9WriteLut(): AIG has no mapping.\n" ); return 1; } Gia_AigerWriteLut( pAbc->pGia, pFileName ); return 0; usage: Abc_Print( -2, "usage: &wlut [-umvh] \n" ); Abc_Print( -2, "\t writes the the current LUT mapping into a binary file\n" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gps_Par_t Pars, * pPars = &Pars; int c, fBest = 0; memset( pPars, 0, sizeof(Gps_Par_t) ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Dtpcnlmasbh" ) ) != EOF ) { switch ( c ) { case 't': pPars->fTents ^= 1; break; case 'p': pPars->fSwitch ^= 1; break; case 'c': pPars->fCut ^= 1; break; case 'n': pPars->fNpn ^= 1; break; case 'l': pPars->fLutProf ^= 1; break; case 'm': pPars->fMuxXor ^= 1; break; case 'a': pPars->fMiter ^= 1; break; case 's': pPars->fSkipMap ^= 1; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a file name.\n" ); goto usage; } pPars->pDumpFile = argv[globalUtilOptind]; globalUtilOptind++; break; case 'b': fBest ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fBest ) { if ( pAbc->pGiaBest == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Ps(): There is no AIG.\n" ); return 1; } Gia_ManPrintStats( pAbc->pGiaBest, pPars ); } else { if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Ps(): There is no AIG.\n" ); return 1; } Gia_ManPrintStats( pAbc->pGia, pPars ); } return 0; usage: Abc_Print( -2, "usage: &ps [-tpcnlmasbh] [-D file]\n" ); Abc_Print( -2, "\t prints stats of the current AIG\n" ); Abc_Print( -2, "\t-t : toggle printing BMC tents [default = %s]\n", pPars->fTents? "yes": "no" ); Abc_Print( -2, "\t-p : toggle printing switching activity [default = %s]\n", pPars->fSwitch? "yes": "no" ); Abc_Print( -2, "\t-c : toggle printing the size of frontier cut [default = %s]\n", pPars->fCut? "yes": "no" ); Abc_Print( -2, "\t-n : toggle printing NPN classes of functions [default = %s]\n", pPars->fNpn? "yes": "no" ); Abc_Print( -2, "\t-l : toggle printing LUT size profile [default = %s]\n", pPars->fLutProf? "yes": "no" ); Abc_Print( -2, "\t-m : toggle printing MUX/XOR statistics [default = %s]\n", pPars->fMuxXor? "yes": "no" ); Abc_Print( -2, "\t-a : toggle printing miter statistics [default = %s]\n", pPars->fMiter? "yes": "no" ); Abc_Print( -2, "\t-s : skip mapping statistics even if mapped [default = %s]\n", pPars->fSkipMap? "yes": "no" ); Abc_Print( -2, "\t-b : toggle printing saved AIG statistics [default = %s]\n", fBest? "yes": "no" ); Abc_Print( -2, "\t-D file : file name to dump statistics [default = none]\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9PFan( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; int nNodes = 0; 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; } nNodes = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nNodes < 0 ) goto usage; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9PFan(): There is no AIG.\n" ); return 1; } Gia_ManPrintFanio( pAbc->pGia, nNodes ); return 0; usage: Abc_Print( -2, "usage: &pfan [-N num] [-h]\n" ); Abc_Print( -2, "\t prints fanin/fanout statistics\n" ); Abc_Print( -2, "\t-N num : the number of high-fanout nodes to explore [default = %d]\n", nNodes ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9PSig( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; int fSetReset = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rh" ) ) != EOF ) { switch ( c ) { case 'r': fSetReset ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9PSigs(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9PSigs(): Works only for sequential circuits.\n" ); return 1; } Gia_ManDetectSeqSignals( pAbc->pGia, fSetReset, 1 ); return 0; usage: Abc_Print( -2, "usage: &psig [-rh]\n" ); Abc_Print( -2, "\t prints enable/set/reset statistics\n" ); Abc_Print( -2, "\t-r : toggle printing set/reset signals [default = %s]\n", fSetReset? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Status( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Status(): There is no AIG.\n" ); return 1; } Gia_ManPrintMiterStatus( pAbc->pGia ); return 0; usage: Abc_Print( -2, "usage: &status [-h]\n" ); Abc_Print( -2, "\t prints status of the miter\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9MuxProfile( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManMuxProfiling( Gia_Man_t * p ); extern void Gia_ManProfileStructures( Gia_Man_t * p, int nLimit, int fVerbose ); int c, fMuxes = 0, nLimit = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Nmvh" ) ) != 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++; if ( nLimit < 0 ) goto usage; break; case 'm': fMuxes ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9MuxProfile(): There is no AIG.\n" ); return 1; } if ( fMuxes ) Gia_ManMuxProfiling( pAbc->pGia ); else Gia_ManProfileStructures( pAbc->pGia, nLimit, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &profile [-N num] [-mvh]\n" ); Abc_Print( -2, "\t profile gate structures appearing in the AIG\n" ); Abc_Print( -2, "\t-N num : limit on class size to show [default = %d]\n", nLimit ); Abc_Print( -2, "\t-m : toggle profiling MUX structures [default = %s]\n", fMuxes? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Rex2Gia( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManRex2Gia( char * pStr, int fOrder, int fVerbose ); Gia_Man_t * pGia = NULL; char * pStr = NULL; char ** pArgvNew; int nArgcNew; int c, fOrder = 1, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "avh" ) ) != EOF ) { switch ( c ) { case 'a': fOrder ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "No regular expression is entered on the command line.\n" ); return 1; } pStr = pArgvNew[0]; pGia = Gia_ManRex2Gia( pStr, fOrder, fVerbose ); if ( pGia ) Abc_FrameUpdateGia( pAbc, pGia ); return 0; usage: Abc_Print( -2, "usage: &rex2gia [-avh] [string]\n" ); Abc_Print( -2, "\t converts a regular expression into a sequential AIG\n" ); Abc_Print( -2, "\t-a : toggle ordering input symbols alphabetically [default = %s]\n", fOrder? "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, "\tstring : representation of a regular expression\n"); Abc_Print( -2, "\t Special symbols: parentheses \'(\' and \')\', Kleene closure \'*\', union \'|'\n"); Abc_Print( -2, "\t All other characters are treated as symbols of the input alphabet.\n"); Abc_Print( -2, "\t For example, ((A*B|AC)D) is defined over the alphabet {A, B, C, D}\n"); Abc_Print( -2, "\t and generates the following language: {BD, ABD, AABD, AAABD, ..., ACD}\n"); Abc_Print( -2, "\t A known limitation: For the command to work correctly, each two-input union\n"); Abc_Print( -2, "\t should have a dedicated pair of parentheses: ((A|B)|C) rather than (A|B|C)\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9RexWalk( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManAutomWalk( Gia_Man_t * p, int nSteps, int nWalks, int fVerbose ); int c, nSteps = 50, nWalks = 5, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "SRvh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } nSteps = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSteps < 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; } nWalks = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nWalks < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Show(): There is no AIG.\n" ); return 1; } Gia_ManAutomWalk( pAbc->pGia, nSteps, nWalks, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &rexwalk [-SR] [-vh]\n" ); Abc_Print( -2, "\t performs simulation of an AIG representing a regular expression\n" ); Abc_Print( -2, "\t-S num : the number of steps to take [default = %d]\n", nSteps ); Abc_Print( -2, "\t-R num : the number of walks to make [default = %d]\n", nWalks ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Show( Abc_Frame_t * pAbc, int argc, char ** argv ) { Vec_Int_t * vBold = NULL; int c, fAdders = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) { switch ( c ) { case 'a': fAdders ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Show(): There is no AIG.\n" ); return 1; } if ( Gia_ManBufNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Show(): Cannot show GIA with barrier buffers.\n" ); return 1; } if ( !fAdders && Gia_ManHasMapping(pAbc->pGia) ) { vBold = Vec_IntAlloc( 100 ); Gia_ManForEachLut( pAbc->pGia, c ) Vec_IntPush( vBold, c ); } Gia_ManShow( pAbc->pGia, vBold, fAdders ); Vec_IntFreeP( &vBold ); return 0; usage: Abc_Print( -2, "usage: &show [-ah]\n" ); Abc_Print( -2, "\t shows the current GIA using GSView\n" ); Abc_Print( -2, "\t-a : toggle visualazing adders [default = %s]\n", fAdders? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9SetRegNum( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, nRegNum = 0; 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; } nRegNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRegNum < 0 ) goto usage; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SetRegNum(): There is no AIG.\n" ); return 1; } if ( nRegNum >= Gia_ManCiNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9SetRegNum(): The number of registers should be less than the number of CIs.\n" ); return 1; } if ( nRegNum >= Gia_ManCoNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9SetRegNum(): The number of registers should be less than the number of COs.\n" ); return 1; } pAbc->pGia->nRegs = nRegNum; return 0; usage: Abc_Print( -2, "usage: &setregnum [-N num] [-h]\n" ); Abc_Print( -2, "\t manually sets the number of registers to combine the last PI/PO pairs\n" ); Abc_Print( -2, "\t-N num : set the number of registers to be the given number [default = %d]\n", nRegNum ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, Limit = 2; int fAddStrash = 0; int fCollapse = 0; int fAddMuxes = 0; int fRehashMap = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Lacmrh" ) ) != EOF ) { switch ( c ) { case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } Limit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Limit < 0 ) goto usage; break; case 'a': fAddStrash ^= 1; break; case 'c': fCollapse ^= 1; break; case 'm': fAddMuxes ^= 1; break; case 'r': fRehashMap ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Strash(): There is no AIG.\n" ); return 1; } if ( Gia_ManHasMapping(pAbc->pGia) && fRehashMap ) { pTemp = Gia_ManDupHashMapping( pAbc->pGia ); Gia_ManTransferPacking( pTemp, pAbc->pGia ); Gia_ManTransferTiming( pTemp, pAbc->pGia ); } else if ( Gia_ManHasMapping(pAbc->pGia) && pAbc->pGia->vConfigs ) pTemp = (Gia_Man_t *)If_ManDeriveGiaFromCells( pAbc->pGia ); else if ( Gia_ManHasMapping(pAbc->pGia) ) pTemp = (Gia_Man_t *)Dsm_ManDeriveGia( pAbc->pGia, fAddMuxes ); // delay-oriented unmapping else if ( fAddMuxes ) { if ( pAbc->pGia->pMuxes ) { Abc_Print( -1, "Abc_CommandAbc9Strash(): The AIG already has MUXes.\n" ); return 1; } pTemp = Gia_ManDupMuxes( pAbc->pGia, Limit ); if ( !Abc_FrameReadFlag("silentmode") ) printf( "Generated AND/XOR/MUX graph.\n" ); } else if ( fCollapse && pAbc->pGia->pAigExtra ) { assert( !Gia_ManBufNum(pAbc->pGia) ); if ( Gia_ManIsSeqWithBoxes(pAbc->pGia) || Gia_ManRegBoxNum(pAbc->pGia) ) { Gia_Man_t * pUnshuffled = Gia_ManDupUnshuffleInputs( pAbc->pGia ); Gia_ManTransferTiming( pUnshuffled, pAbc->pGia ); pTemp = Gia_ManDupCollapse( pUnshuffled, pUnshuffled->pAigExtra, NULL, Gia_ManRegBoxNum(pUnshuffled) > 0 ); Gia_ManTransferTiming( pAbc->pGia, pUnshuffled ); Gia_ManStop( pUnshuffled ); } else pTemp = Gia_ManDupCollapse( pAbc->pGia, pAbc->pGia->pAigExtra, NULL, 0 ); if ( !Abc_FrameReadFlag("silentmode") ) printf( "Collapsed AIG with boxes and logic of the boxes.\n" ); } else if ( pAbc->pGia->pMuxes ) { pTemp = Gia_ManDupNoMuxes( pAbc->pGia ); if ( !Abc_FrameReadFlag("silentmode") ) printf( "Generated AIG from AND/XOR/MUX graph.\n" ); } else { pTemp = Gia_ManRehash( pAbc->pGia, fAddStrash ); // if ( !Abc_FrameReadFlag("silentmode") ) // printf( "Rehashed the current AIG.\n" ); } if ( !(fCollapse && pAbc->pGia->pAigExtra) ) { Gia_ManTransferTiming( pTemp, pAbc->pGia ); pAbc->pGia->vConfigs = pTemp->vConfigs; pTemp->vConfigs = NULL; pAbc->pGia->pCellStr = pTemp->pCellStr; pTemp->pCellStr = NULL; } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &st [-L num] [-acmrh]\n" ); Abc_Print( -2, "\t performs structural hashing\n" ); Abc_Print( -2, "\t-a : toggle additional hashing [default = %s]\n", fAddStrash? "yes": "no" ); Abc_Print( -2, "\t-c : toggle collapsing hierarchical AIG [default = %s]\n", fCollapse? "yes": "no" ); Abc_Print( -2, "\t-m : toggle converting to larger gates [default = %s]\n", fAddMuxes? "yes": "no" ); Abc_Print( -2, "\t-L num : create MUX when sum of refs does not exceed this limit [default = %d]\n", Limit ); Abc_Print( -2, "\t (use L = 1 to create AIG with XORs but without MUXes)\n" ); Abc_Print( -2, "\t-r : toggle rehashing AIG while preserving mapping [default = %s]\n", fRehashMap? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Topand( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Topand(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) > 0 ) { Abc_Print( -1, "Abc_CommandAbc9Topand(): Can only be applied to a combinational miter.\n" ); return 1; } pTemp = Gia_ManDupTopAnd( pAbc->pGia, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &topand [-vh]\n" ); Abc_Print( -2, "\t performs AND decomposition for combinational miter\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_CommandAbc9Add1Hot( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Add1Hot(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManDupOneHot( pAbc->pGia ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &add1hot [-vh]\n" ); Abc_Print( -2, "\t adds 1-hotness constraints as additional primary outputs\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_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fVerbose = 0; int iVar = 0, nLimFan = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "VLvh" ) ) != EOF ) { switch ( c ) { case 'V': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" ); goto usage; } iVar = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iVar < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } nLimFan = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLimFan < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Cof(): There is no AIG.\n" ); return 1; } if ( nLimFan ) { Abc_Print( -1, "Cofactoring all variables whose fanout count is higher than %d.\n", nLimFan ); pTemp = Gia_ManDupCofAll( pAbc->pGia, nLimFan, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); } else if ( iVar ) { Abc_Print( -1, "Cofactoring one variable with object ID %d.\n", iVar ); pTemp = Gia_ManDupCof( pAbc->pGia, iVar ); Abc_FrameUpdateGia( pAbc, pTemp ); } else { Abc_Print( -1, "One of the parameters, -V or -L , should be set on the command line.\n" ); goto usage; } return 0; usage: Abc_Print( -2, "usage: &cof [-VL num] [-vh]\n" ); Abc_Print( -2, "\t performs cofactoring w.r.t. variable(s)\n" ); Abc_Print( -2, "\t-V num : the zero-based ID of one variable to cofactor [default = %d]\n", iVar ); Abc_Print( -2, "\t-L num : cofactor vars with fanout count higher than this [default = %d]\n", nLimFan ); Abc_Print( -2, "\t-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_CommandAbc9Trim( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp, * pTemp2; int c; int OutValue = -1; int fTrimCis = 1; int fTrimCos = 1; int fDualOut = 0; int fPoFedByPi = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Viocdh" ) ) != EOF ) { switch ( c ) { case 'V': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" ); goto usage; } OutValue = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( OutValue < 0 ) goto usage; break; case 'i': fTrimCis ^= 1; break; case 'o': fTrimCos ^= 1; break; case 'c': fPoFedByPi ^= 1; break; case 'd': fDualOut ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Trim(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManDupTrimmed( pAbc->pGia, fTrimCis, fTrimCos, fDualOut, OutValue ); if ( fPoFedByPi ) { extern Gia_Man_t * Gia_ManDupTrimmed2( Gia_Man_t * p ); pTemp = Gia_ManDupTrimmed2( pTemp2 = pTemp ); Gia_ManStop( pTemp2 ); } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &trim [-V num] [-iocdh]\n" ); Abc_Print( -2, "\t removes PIs without fanout and PO driven by constants\n" ); Abc_Print( -2, "\t-V num : the value (0 or 1) of POs to remove [default = both]\n" ); Abc_Print( -2, "\t-i : toggle removing PIs [default = %s]\n", fTrimCis? "yes": "no" ); Abc_Print( -2, "\t-o : toggle removing POs [default = %s]\n", fTrimCos? "yes": "no" ); Abc_Print( -2, "\t-c : toggle additionally removing POs fed by PIs [default = %s]\n", fPoFedByPi? "yes": "no" ); Abc_Print( -2, "\t-d : toggle using dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Dfs( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c; int fNormal = 0; int fReverse = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "nrvh" ) ) != EOF ) { switch ( c ) { case 'n': fNormal ^= 1; break; case 'r': fReverse ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Dfs(): There is no AIG.\n" ); return 1; } if ( fNormal ) { pTemp = Gia_ManDupOrderAiger( pAbc->pGia ); if ( fVerbose ) Abc_Print( -1, "AIG objects are reordered as follows: CIs, ANDs, COs.\n" ); } else if ( fReverse ) { pTemp = Gia_ManDupOrderDfsReverse( pAbc->pGia ); if ( fVerbose ) Abc_Print( -1, "AIG objects are reordered in the reserve DFS order.\n" ); } else { pTemp = Gia_ManDupOrderDfs( pAbc->pGia ); if ( fVerbose ) Abc_Print( -1, "AIG objects are reordered in the DFS order.\n" ); } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &dfs [-nrvh]\n" ); Abc_Print( -2, "\t orders objects in the DFS order\n" ); Abc_Print( -2, "\t-n : toggle using normalized ordering [default = %s]\n", fNormal? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using reverse DFS ordering [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Sim( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_ParSim_t Pars, * pPars = &Pars; char * pFileName = NULL; int c; Gia_ManSimSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FWNTImvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIters < 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->nWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nWords < 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->RandSeed = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->RandSeed < 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } pPars->TimeLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeLimit < 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; } pFileName = argv[globalUtilOptind]; globalUtilOptind++; if ( pFileName == NULL ) goto usage; break; case 'm': pPars->fCheckMiter ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Sim(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( pFileName != NULL ) { extern void Gia_ManSimSimulatePattern( Gia_Man_t * p, char * pFileIn, char * pFileOut ); char pFileNameOut[1000]; char * pNameGeneric = Extra_FileNameGeneric(pFileName); assert( strlen(pNameGeneric) < 900 ); sprintf( pFileNameOut, "%s_out.%s", pNameGeneric, Extra_FileNameExtension(pFileName) ); ABC_FREE( pNameGeneric ); Gia_ManSimSimulatePattern( pAbc->pGia, pFileName, pFileNameOut ); return 1; } pAbc->nFrames = -1; if ( Gia_ManSimSimulate( pAbc->pGia, pPars ) ) pAbc->Status = 0; else pAbc->Status = -1; Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); // if ( pLogFileName ) // Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&sim" ); return 0; usage: Abc_Print( -2, "usage: &sim [-FWNT num] [-mvh] -I \n" ); Abc_Print( -2, "\t performs random simulation of the sequential miter\n" ); Abc_Print( -2, "\t (if candidate equivalences are defined, performs refinement)\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", pPars->nIters ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n", pPars->RandSeed ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t-I file: (optional) file with input patterns (one line per frame, as many as PIs)\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Sim3( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Ssw_RarSimulateGia( Gia_Man_t * p, Ssw_RarPars_t * pPars ); Ssw_RarPars_t Pars, * pPars = &Pars; int c; Ssw_RarSetDefaultParams( pPars ); // parse command line Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FWBRSNTGgvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 0 ) goto usage; break; case '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 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); goto usage; } pPars->nBinSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBinSize < 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->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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->nRestart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRestart < 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->nRandSeed = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRandSeed < 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->TimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOut < 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; } pPars->TimeOutGap = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOutGap < 0 ) goto usage; break; case 'g': pPars->fUseFfGrouping ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Sim3(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9Sim3(): This command works only for sequential AIGs.\n" ); return 0; } pAbc->Status = Ssw_RarSimulateGia( pAbc->pGia, pPars ); Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &sim3 [-FWBRNT num] [-gvh]\n" ); Abc_Print( -2, "\t performs random simulation of the sequential miter\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-B num : the number of flops in one bin [default = %d]\n", pPars->nBinSize ); Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-S num : the number of rounds before a restart [default = %d]\n", pPars->nRestart ); Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n", pPars->nRandSeed ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeOut ); Abc_Print( -2, "\t-g : toggle heuristic flop grouping [default = %s]\n", pPars->fUseFfGrouping? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Resim( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParSim_t Pars, * pPars = &Pars; int c, RetValue; Cec_ManSimSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fmvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 0 ) goto usage; break; case 'm': pPars->fCheckMiter ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Resim(): There is no AIG.\n" ); return 1; } RetValue = Cec_ManSeqResimulateCounter( pAbc->pGia, pPars, pAbc->pCex ); pAbc->Status = RetValue ? 0 : -1; pAbc->nFrames = pAbc->pCex->iFrame; // Abc_FrameReplaceCex( pAbc, &pAbc->pCex ); return 0; usage: Abc_Print( -2, "usage: &resim [-F num] [-mvh]\n" ); Abc_Print( -2, "\t resimulates equivalence classes using counter-example\n" ); Abc_Print( -2, "\t-F num : the number of additinal frames to simulate [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9SpecI( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Gia_CommandSpecI( Gia_Man_t * pGia, int nFrames, int nBTLimit, int fUseStart, int fCheckMiter, int fVerbose ); int nFrames = 100; int nBTLimit = 25000; int fUseStart = 1; int fCheckMiter = 1; int fVerbose = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCfmvh" ) ) != 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 '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 'f': fUseStart ^= 1; break; case 'm': fCheckMiter ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SpecI(): There is no AIG.\n" ); return 1; } Gia_CommandSpecI( pAbc->pGia, nFrames, nBTLimit, fUseStart, fCheckMiter, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &speci [-FC num] [-fmvh]\n" ); Abc_Print( -2, "\t refines equivalence classes using speculative reduction\n" ); Abc_Print( -2, "\t-F num : the max number of time frames [default = %d]\n", nFrames ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-f : toggle starting BMC from a later frame [default = %s]\n", fUseStart? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", fCheckMiter? "miter": "circuit" ); 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_CommandAbc9Equiv( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParSim_t Pars, * pPars = &Pars; int c; Cec_ManSimSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WFRSTsmdvh" ) ) != 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 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } pPars->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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->nNonRefines = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nNonRefines < 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } pPars->TimeLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeLimit < 0 ) goto usage; break; case 's': pPars->fSeqSimulate ^= 1; break; case 'm': pPars->fCheckMiter ^= 1; break; case 'd': pPars->fDualOut ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Equiv(): There is no AIG.\n" ); return 1; } Cec_ManSimulation( pAbc->pGia, pPars ); return 0; usage: Abc_Print( -2, "usage: &equiv [-WFRST num] [-smdvh]\n" ); Abc_Print( -2, "\t computes candidate equivalence classes\n" ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-R num : the max number of simulation rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-S num : the max number of rounds w/o refinement to stop [default = %d]\n", pPars->nNonRefines ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-s : toggle seq vs. comb simulation [default = %s]\n", pPars->fSeqSimulate? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-d : toggle using two POs intead of XOR [default = %s]\n", pPars->fDualOut? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [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_CommandAbc9Equiv2( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Ssw_SignalFilterGia( Gia_Man_t * p, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ); int nFramesMax = 20; int nConfMax = 500; int nRounds = 10; int TimeLimit = 0; int TimeLimit2 = 0; int fUseCex = 0; int fLatchOnly = 0; int fVerbose = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCRTSxlvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFramesMax < 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; } nConfMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfMax < 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 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } TimeLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( TimeLimit < 0 ) goto usage; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } TimeLimit2 = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( TimeLimit2 < 0 ) goto usage; break; case 'x': fUseCex ^= 1; break; case 'l': fLatchOnly ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Equiv2(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( 0, "Abc_CommandAbc9Equiv2(): There is no flops. Nothing is done.\n" ); return 0; } if ( fUseCex ) { if ( pAbc->pCex == NULL ) { Abc_Print( 0, "Abc_CommandAbc9Equiv2(): Counter-example is not available.\n" ); return 0; } if ( pAbc->pCex->nPis != Gia_ManPiNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Equiv2(): The number of PIs differs in cex (%d) and in AIG (%d).\n", pAbc->pCex->nPis, Gia_ManPiNum(pAbc->pGia) ); return 1; } } Ssw_SignalFilterGia( pAbc->pGia, nFramesMax, nConfMax, nRounds, TimeLimit, TimeLimit2, fUseCex? pAbc->pCex: NULL, fLatchOnly, fVerbose ); pAbc->Status = -1; // pAbc->nFrames = pAbc->pCex->iFrame; // Abc_FrameReplaceCex( pAbc, &pAbc->pCex ); return 0; usage: Abc_Print( -2, "usage: &equiv2 [-FCRTS num] [-xlvh]\n" ); Abc_Print( -2, "\t computes candidate equivalence classes\n" ); Abc_Print( -2, "\t-F num : the max number of frames for BMC [default = %d]\n", nFramesMax ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-R num : the max number of BMC rounds [default = %d]\n", nRounds ); Abc_Print( -2, "\t-T num : runtime limit in seconds for all rounds [default = %d]\n", TimeLimit ); Abc_Print( -2, "\t-S num : runtime limit in seconds for one round [default = %d]\n", TimeLimit2 ); Abc_Print( -2, "\t-x : toggle using the current cex to perform refinement [default = %s]\n", fUseCex? "yes": "no" ); Abc_Print( -2, "\t-l : toggle considering only latch output equivalences [default = %s]\n", fLatchOnly? "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_CommandAbc9Equiv3( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Ssw_RarSignalFilterGia( Gia_Man_t * p, Ssw_RarPars_t * pPars ); Ssw_RarPars_t Pars, * pPars = &Pars; int c; Ssw_RarSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FWBRSNTmxlvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 0 ) goto usage; break; case '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 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); goto usage; } pPars->nBinSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBinSize < 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->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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->nRestart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRestart < 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->nRandSeed = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRandSeed < 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->TimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOut < 0 ) goto usage; break; case 'm': pPars->fMiter ^= 1; break; case 'x': pPars->fUseCex ^= 1; break; case 'l': pPars->fLatchOnly ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Equiv3(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( 0, "Abc_CommandAbc9Equiv3(): There is no flops. Nothing is done.\n" ); return 0; } if ( pPars->fUseCex ) { if ( pPars->fMiter ) { Abc_Print( 0, "Abc_CommandAbc9Equiv3(): Considering the miter as a circuit because the CEX is given.\n" ); pPars->fMiter = 0; } if ( pAbc->pCex == NULL ) { Abc_Print( 0, "Abc_CommandAbc9Equiv3(): Counter-example is not available.\n" ); return 0; } if ( pAbc->pCex->nPis != Gia_ManPiNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Equiv3(): The number of PIs differs in cex (%d) and in AIG (%d).\n", pAbc->pCex->nPis, Gia_ManPiNum(pAbc->pGia) ); return 1; } pPars->pCex = pAbc->pCex; } pAbc->Status = Ssw_RarSignalFilterGia( pAbc->pGia, pPars ); // pAbc->nFrames = pAbc->pGia->pCexSeq->iFrame; Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &equiv3 [-FWRSNT num] [-mxlvh]\n" ); Abc_Print( -2, "\t computes candidate equivalence classes\n" ); Abc_Print( -2, "\t-F num : the max number of frames for BMC [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-R num : the max number of simulation rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-S num : the number of rounds before a restart [default = %d]\n", pPars->nRestart ); Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n", pPars->nRandSeed ); Abc_Print( -2, "\t-T num : runtime limit in seconds for all rounds [default = %d]\n", pPars->TimeOut ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fMiter? "miter": "circuit" ); Abc_Print( -2, "\t-x : toggle using the current CEX to perform refinement [default = %s]\n", pPars->fUseCex? "yes": "no" ); Abc_Print( -2, "\t-l : toggle considering only latch output equivalences [default = %s]\n", pPars->fLatchOnly? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Semi( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParSmf_t Pars, * pPars = &Pars; int c; Cec_ManSmfSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WRFSMCTmdvh" ) ) != 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 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } pPars->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 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->nNonRefines = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nNonRefines < 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->nMinOutputs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMinOutputs < 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 '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 'm': pPars->fCheckMiter ^= 1; break; case 'd': pPars->fDualOut ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Resim(): There is no AIG.\n" ); return 1; } Cec_ManSeqSemiformal( pAbc->pGia, pPars ); return 0; usage: Abc_Print( -2, "usage: &semi [-WRFSMCT num] [-mdvh]\n" ); Abc_Print( -2, "\t performs semiformal refinement of equivalence classes\n" ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-R num : the max number of rounds to simulate [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-F num : the max number of frames to unroll [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-S num : the max number of rounds w/o refinement to stop [default = %d]\n", pPars->nNonRefines ); Abc_Print( -2, "\t-M num : the min number of outputs of bounded SRM [default = %d]\n", pPars->nMinOutputs ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-d : toggle using two POs intead of XOR [default = %s]\n", pPars->fDualOut? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [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_CommandAbc9Times( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, nTimes = 2, 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 \"-T\" should be followed by an integer.\n" ); goto usage; } nTimes = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimes < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Times(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManDupTimes( pAbc->pGia, nTimes ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: × [-N ] [-vh]\n" ); Abc_Print( -2, "\t creates several \"parallel\" copies of the design\n" ); Abc_Print( -2, "\t-N num : number of copies to create [default = %d]\n", nTimes ); 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_CommandAbc9Frames( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManFrames2( Gia_Man_t * pAig, Gia_ParFra_t * pPars ); Gia_Man_t * pTemp; Gia_ParFra_t Pars, * pPars = &Pars; int c; int nCofFanLit = 0; int fNewAlgo = 0; int fInitSpecial = 0; Gia_ManFraSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FLsoibavh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } nCofFanLit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCofFanLit < 0 ) goto usage; break; case 's': pPars->fDisableSt ^= 1; break; case 'o': pPars->fOrPos ^= 1; break; case 'i': pPars->fInit ^= 1; break; case 'b': fInitSpecial ^= 1; break; case 'a': fNewAlgo ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Frames(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( fInitSpecial ) pTemp = Gia_ManFramesInitSpecial( pAbc->pGia, pPars->nFrames, pPars->fVerbose ); else if ( nCofFanLit ) pTemp = Gia_ManUnrollAndCofactor( pAbc->pGia, pPars->nFrames, nCofFanLit, pPars->fVerbose ); else if ( fNewAlgo ) pTemp = Gia_ManFrames2( pAbc->pGia, pPars ); else pTemp = Gia_ManFrames( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &frames [-FL ] [-soibavh]\n" ); Abc_Print( -2, "\t unrolls the design for several timeframes\n" ); Abc_Print( -2, "\t-F num : the number of frames to unroll [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-L num : the limit on fanout count of resets/enables to cofactor [default = %d]\n", nCofFanLit ); Abc_Print( -2, "\t-s : toggle disabling structural hashing [default = %s]\n", pPars->fDisableSt? "yes": "no" ); Abc_Print( -2, "\t-o : toggle ORing corresponding POs [default = %s]\n", pPars->fOrPos? "yes": "no" ); Abc_Print( -2, "\t-i : toggle initializing registers [default = %s]\n", pPars->fInit? "yes": "no" ); Abc_Print( -2, "\t-b : toggle computing special AIG for BMC [default = %s]\n", fInitSpecial? "yes": "no" ); Abc_Print( -2, "\t-a : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Retime( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c; int nMaxIters = 100; int 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; } nMaxIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nMaxIters < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Retime(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } pTemp = Gia_ManRetimeForward( pAbc->pGia, nMaxIters, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &retime [-N ] [-vh]\n" ); Abc_Print( -2, "\t performs most-forward retiming\n" ); Abc_Print( -2, "\t-N num : the number of incremental iterations [default = %d]\n", nMaxIters ); 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_CommandAbc9Enable( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c; int fRemove = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) { switch ( c ) { case 'r': fRemove ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Enable(): There is no AIG.\n" ); return 1; } if ( fRemove ) pTemp = Gia_ManRemoveEnables( pAbc->pGia ); else pTemp = Gia_ManDupSelf( pAbc->pGia ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &enable [-rvh]\n" ); Abc_Print( -2, "\t adds or removes flop enable signals\n" ); Abc_Print( -2, "\t-r : toggle adding vs. removing enables [default = %s]\n", fRemove? "remove": "add" ); 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_CommandAbc9Dc2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fVerbose = 0; int fUpdateLevel = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF ) { switch ( c ) { case 'l': fUpdateLevel ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Dc2(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManCompress2( pAbc->pGia, fUpdateLevel, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &dc2 [-lvh]\n" ); Abc_Print( -2, "\t performs heavy rewriting of the AIG\n" ); Abc_Print( -2, "\t-l : toggle level update during rewriting [default = %s]\n", fUpdateLevel? "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_CommandAbc9Dsd( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ); Gia_Man_t * pTemp; int c, fVerbose = 0; int fUpdateLevel = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF ) { switch ( c ) { case 'l': fUpdateLevel ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Dsd(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManCollapseTest( pAbc->pGia, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &dsd [-vh]\n" ); Abc_Print( -2, "\t performs DSD-based collapsing\n" ); // Abc_Print( -2, "\t-l : toggle level update during rewriting [default = %s]\n", fUpdateLevel? "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_CommandAbc9Bidec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fVerbose = 0; int fUpdateLevel = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF ) { switch ( c ) { case 'l': fUpdateLevel ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Bidec(): There is no AIG.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Bidec(): Mapping of the AIG is not defined.\n" ); return 1; } pTemp = Gia_ManPerformBidec( pAbc->pGia, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &bidec [-vh]\n" ); Abc_Print( -2, "\t performs heavy rewriting of the AIG\n" ); // Abc_Print( -2, "\t-l : toggle level update during rewriting [default = %s]\n", fUpdateLevel? "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_CommandAbc9Shrink( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp = NULL; int nLutSize; int c,fVerbose = 0; int fKeepLevel = 0; int nFanoutMax = 50; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Nlvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a char string.\n" ); goto usage; } nFanoutMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFanoutMax < 0 ) goto usage; break; case 'l': fKeepLevel ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Shrink(): There is no AIG.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Shrink(): Mapping of the AIG is not defined.\n" ); return 1; } nLutSize = Gia_ManLutSizeMax( pAbc->pGia ); if ( nLutSize <= 4 ) pTemp = Gia_ManMapShrink4( pAbc->pGia, fKeepLevel, fVerbose ); else if ( nLutSize <= 6 ) pTemp = Gia_ManMapShrink6( pAbc->pGia, nFanoutMax, fKeepLevel, fVerbose ); else Abc_Print( -1, "Abc_CommandAbc9Shrink(): Works only for 4-LUTs and 6-LUTs.\n" ); if ( pTemp ) Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &shrink [-N num] [-lvh]\n" ); Abc_Print( -2, "\t performs fast shrinking using current mapping\n" ); Abc_Print( -2, "\t-N num : the max fanout count to skip a divisor [default = %d]\n", nFanoutMax ); Abc_Print( -2, "\t-l : toggle level update during shrinking [default = %s]\n", fKeepLevel? "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_CommandAbc9Fx( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int nNewNodesMax = 1000000; int LitCountMax = 0; int fReverse = 0; int c, fVerbose = 0; int fVeryVerbose = 0; // set the defaults Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "NMrvwh")) != EOF ) { switch (c) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nNewNodesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nNewNodesMax < 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; } LitCountMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( LitCountMax < 0 ) goto usage; break; case 'r': fReverse ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Shrink(): There is no AIG.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Shrink(): Mapping of the AIG is not defined.\n" ); return 1; } pTemp = Gia_ManPerformFx( pAbc->pGia, nNewNodesMax, LitCountMax, fReverse, fVerbose, fVeryVerbose ); if ( pTemp != NULL ) Abc_FrameUpdateGia( pAbc, pTemp ); else Abc_Print( -1, "Abc_CommandAbc9Fx(): Command has failed.\n" ); return 0; usage: Abc_Print( -2, "usage: &fx [-NM ] [-vh]\n"); Abc_Print( -2, "\t extract shared logic using the classical \"fast_extract\" algorithm\n"); Abc_Print( -2, "\t-N : max number of divisors to extract during this run [default = %d]\n", nNewNodesMax ); Abc_Print( -2, "\t-M : upper bound on literal count of divisors to extract [default = %d]\n", LitCountMax ); Abc_Print( -2, "\t-r : reversing variable order during ISOP computation [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Balance( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp = NULL; int nNewNodesMax = ABC_INFINITY; int fDelayOnly = 0; int fSimpleAnd = 0; int fStrict = 0; int fKeepLevel = 0; int c, fVerbose = 0; int fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Ndaslvwh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a char string.\n" ); goto usage; } nNewNodesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nNewNodesMax < 0 ) goto usage; break; case 'd': fDelayOnly ^= 1; break; case 'a': fSimpleAnd ^= 1; break; case 's': fStrict ^= 1; break; case 'l': fKeepLevel ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Balance(): There is no AIG.\n" ); return 1; } if ( fDelayOnly ) pTemp = Gia_ManBalance( pAbc->pGia, fSimpleAnd, fStrict, fVerbose ); else pTemp = Gia_ManAreaBalance( pAbc->pGia, fSimpleAnd, nNewNodesMax, fVerbose, fVeryVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &b [-N num] [-dasvwh]\n" ); Abc_Print( -2, "\t performs AIG balancing to reduce delay and area\n" ); Abc_Print( -2, "\t-N num : the max fanout count to skip a divisor [default = %d]\n", nNewNodesMax ); Abc_Print( -2, "\t-d : toggle delay only balancing [default = %s]\n", fDelayOnly? "yes": "no" ); Abc_Print( -2, "\t-a : toggle using AND instead of AND/XOR/MUX [default = %s]\n", fSimpleAnd? "yes": "no" ); Abc_Print( -2, "\t-s : toggle strict control of area in delay-mode (\"&b -d\") [default = %s]\n", fStrict? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9BalanceLut( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManBalanceLut( Gia_Man_t * p, int nLutSize, int nCutNum, int fVerbose ); extern Gia_Man_t * Gia_ManLutBalance( Gia_Man_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ); Gia_Man_t * pTemp = NULL; int fUseOld = 0; int nLutSize = 6; int nCutNum = 8; int fUseMuxes = 1; int fRecursive = 1; int fOptArea = 1; int c, fVerbose = 0; int fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCnmravwh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by a char string.\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 a char string.\n" ); goto usage; } nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutNum < 0 ) goto usage; break; case 'n': fUseOld ^= 1; break; case 'm': fUseMuxes ^= 1; break; case 'r': fRecursive ^= 1; break; case 'a': fOptArea ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9BalanceLut(): There is no AIG.\n" ); return 1; } if ( fUseOld ) pTemp = Gia_ManBalanceLut( pAbc->pGia, nLutSize, nCutNum, fVerbose ); else pTemp = Gia_ManLutBalance( pAbc->pGia, nLutSize, fUseMuxes, fRecursive, fOptArea, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &blut [-KC num] [-mravh]\n" ); Abc_Print( -2, "\t performs AIG balancing for the given LUT size\n" ); Abc_Print( -2, "\t-K num : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", 6, nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", 8, nCutNum ); Abc_Print( -2, "\t-m : toggle performing MUX restructuring [default = %s]\n", fUseMuxes? "yes": "no" ); Abc_Print( -2, "\t-r : toggle performing recursive restructuring [default = %s]\n", fRecursive? "yes": "no" ); Abc_Print( -2, "\t-a : toggle performing area-oriented restructuring [default = %s]\n", fOptArea? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); // Abc_Print( -2, "\t-w : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Syn2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fVerbose = 0; int fOldAlgo = 0; int fCoarsen = 1; int fCutMin = 0; int nRelaxRatio = 20; int fDelayMin = 0; int fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Rakmdvwh" ) ) != EOF ) { switch ( c ) { case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRelaxRatio < 0 ) goto usage; break; case 'a': fOldAlgo ^= 1; break; case 'k': fCoarsen ^= 1; break; case 'm': fCutMin ^= 1; break; case 'd': fDelayMin ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Syn2(): There is no AIG.\n" ); return 1; } if ( fDelayMin ) { If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd(); if ( p && If_DsdManVarNum(p) < 6 ) { printf( "DSD manager has incompatible number of variables. Delay minimization is not performed.\n" ); fDelayMin = 0; } } pTemp = Gia_ManAigSyn2( pAbc->pGia, fOldAlgo, fCoarsen, fCutMin, nRelaxRatio, fDelayMin, fVerbose, fVeryVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &syn2 [-R num] [-akmdvh]\n" ); Abc_Print( -2, "\t performs AIG optimization\n" ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", nRelaxRatio ); Abc_Print( -2, "\t-a : toggles using the old algorithm [default = %s]\n", fOldAlgo? "yes": "no" ); Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cut minimization [default = %s]\n", fCutMin? "yes": "no" ); Abc_Print( -2, "\t-d : toggles additional delay optimization [default = %s]\n", fDelayMin? "yes": "no" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Synch2( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManAigSynch2( Gia_Man_t * p, void * pPars, int nLutSize, int nRelaxRatio ); Gia_Man_t * pTemp; Dch_Pars_t Pars, * pPars = &Pars; int c, nLutSize = 6; int nRelaxRatio = 20; // set defaults Dch_ManSetDefaultParams( pPars ); pPars->nBTLimit = 100; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WCSKRfvh" ) ) != 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 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by a char string.\n" ); goto usage; } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLutSize < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRelaxRatio < 0 ) goto usage; break; case 'f': pPars->fLightSynth ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Dch(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManAigSynch2( pAbc->pGia, pPars, nLutSize, nRelaxRatio ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &synch2 [-WCSKR num] [-fvh]\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-K num : the target LUT size for downstream mapping [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", nRelaxRatio ); Abc_Print( -2, "\t-f : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "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_CommandAbc9Syn3( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fVerbose = 0; int fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vwh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Syn3(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManAigSyn3( pAbc->pGia, fVerbose, fVeryVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &syn3 [-lvh]\n" ); Abc_Print( -2, "\t performs AIG optimization\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Syn4( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fVerbose = 0; int fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vwh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Syn4(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManAigSyn4( pAbc->pGia, fVerbose, fVeryVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &syn4 [-lvh]\n" ); Abc_Print( -2, "\t performs AIG optimization\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9False( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManCheckFalse( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose ); Gia_Man_t * pTemp; int nSlackMax = 0; int nTimeOut = 0; int c, fVerbose = 0; int fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "STvwh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by a char string.\n" ); goto usage; } nSlackMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSlackMax < 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by a char string.\n" ); goto usage; } nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeOut < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9False(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManCheckFalse( pAbc->pGia, nSlackMax, nTimeOut, fVerbose, fVeryVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &false [-ST num] [-vwh]\n" ); Abc_Print( -2, "\t detecting and elimintation false paths\n" ); Abc_Print( -2, "\t-S num : maximum slack to identify false paths [default = %d]\n", nSlackMax ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Gia_Man_t * pAux; Gia_Man_t * pSecond; char * FileName, * pTemp; char ** pArgvNew; int nArgcNew; int c; int nInsDup = 0; int fDualOut = 0; int fSeq = 0; int fTrans = 0; int fTransX = 0; int fConvert = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Idstxyvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by a char string.\n" ); goto usage; } nInsDup = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nInsDup < 0 ) goto usage; break; case 'd': fDualOut ^= 1; break; case 's': fSeq ^= 1; break; case 't': fTrans ^= 1; break; case 'x': fTransX ^= 1; break; case 'y': fConvert ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fTrans || fTransX || fConvert ) { if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Miter(): There is no AIG.\n" ); return 1; } if ( (Gia_ManPoNum(pAbc->pGia) & 1) == 1 ) { Abc_Print( -1, "Abc_CommandAbc9Miter(): The number of outputs should be even.\n" ); return 0; } if ( fTrans ) { pAux = Gia_ManTransformMiter( pAbc->pGia ); Abc_Print( 1, "The miter (current AIG) is transformed by XORing POs pair-wise.\n" ); } else if ( fTransX ) { pAux = Gia_ManTransformMiter2( pAbc->pGia ); Abc_Print( 1, "The miter (current AIG) is transformed by XORing POs of two word-level outputs.\n" ); } else { pAux = Gia_ManTransformTwoWord2DualOutput( pAbc->pGia ); Abc_Print( 1, "The miter (current AIG) is transformed from two-word to dual-output.\n" ); } Abc_FrameUpdateGia( pAbc, pAux ); 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; } // 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 ); pSecond = Gia_AigerRead( FileName, 0, 0, 0 ); if ( pSecond == NULL ) { Abc_Print( -1, "Reading AIGER has failed.\n" ); return 0; } // compute the miter pAux = Gia_ManMiter( pAbc->pGia, pSecond, nInsDup, fDualOut, fSeq, 0, fVerbose ); Gia_ManStop( pSecond ); Abc_FrameUpdateGia( pAbc, pAux ); return 0; usage: Abc_Print( -2, "usage: &miter [-I num] [-dstxyvh] \n" ); Abc_Print( -2, "\t creates miter of two designs (current AIG vs. )\n" ); Abc_Print( -2, "\t-I num : the number of last PIs to replicate [default = %d]\n", nInsDup ); Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-s : toggle creating sequential miter [default = %s]\n", fSeq? "yes": "no" ); Abc_Print( -2, "\t-t : toggle XORing POs of dual-output miter [default = %s]\n", fTrans? "yes": "no" ); Abc_Print( -2, "\t-x : toggle XORing POs of two-word miter [default = %s]\n", fTransX? "yes": "no" ); Abc_Print( -2, "\t-y : toggle convering two-word miter into dual-output miter [default = %s]\n", fConvert? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : AIGER file with the design to miter\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Miter2( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Gia_Man_t * pAux; char * FileName, * pTemp, * pInit; char ** pArgvNew; int nArgcNew; 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; } } 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]; // 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 ); // extract string pInit = Extra_FileReadContents( FileName ); Extra_StringClean( pInit, "01xX" ); if ( (int)strlen(pInit) != Gia_ManCiNum(pAbc->pGia) ) { Abc_Print( -1, "Init string length (%d) differs from PI and flop count (%d).\n", strlen(pInit), Gia_ManCiNum(pAbc->pGia) ); ABC_FREE( pInit ); return 1; } // compute the miter pAux = Gia_ManMiter2( pAbc->pGia, pInit, fVerbose ); ABC_FREE( pInit ); Abc_FrameUpdateGia( pAbc, pAux ); return 0; usage: Abc_Print( -2, "usage: &miter2 [-vh] \n" ); Abc_Print( -2, "\t creates miter of two copies of the design\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file name with flop initial values (0/1/x/X) [default = required]\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Append( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Gia_Man_t * pSecond; char * FileName, * pTemp; char ** pArgvNew; int nArgcNew; int c; int 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; } } 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]; // 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 ); pSecond = Gia_AigerRead( FileName, 0, 0, 0 ); if ( pSecond == NULL ) { Abc_Print( -1, "Reading AIGER has failed.\n" ); return 0; } // compute the miter Gia_ManDupAppend( pAbc->pGia, pSecond ); Gia_ManStop( pSecond ); return 0; usage: Abc_Print( -2, "usage: &append [-vh] \n" ); Abc_Print( -2, "\t appends to the current AIG using new PIs and POs\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : AIGER file with the design to miter\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Scl( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c; int fConst = 1; int fEquiv = 1; int fVerbose = 0; int fVerboseFlops = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cevwh" ) ) != EOF ) { switch ( c ) { case 'c': fConst ^= 1; break; case 'e': fEquiv ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVerboseFlops ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Scl(): There is no AIG.\n" ); return 1; } if ( Gia_ManBoxNum(pAbc->pGia) && Gia_ManRegBoxNum(pAbc->pGia) ) { if ( pAbc->pGia->pAigExtra == NULL ) { printf( "Timing manager is given but there is no GIA of boxes.\n" ); return 0; } pTemp = Gia_ManSweepWithBoxes( pAbc->pGia, NULL, NULL, fConst, fEquiv, fVerbose, fVerboseFlops ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } pTemp = Gia_ManSeqStructSweep( pAbc->pGia, fConst, fEquiv, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &scl [-cevwh]\n" ); Abc_Print( -2, "\t performs structural sequential cleanup\n" ); Abc_Print( -2, "\t-c : toggle removing stuck-at constant registers [default = %s]\n", fConst? "yes": "no" ); Abc_Print( -2, "\t-e : toggle removing equivalent-driver registers [default = %s]\n", fEquiv? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", fVerboseFlops? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Lcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParCor_t Pars, * pPars = &Pars; Gia_Man_t * pTemp; int c; Cec_ManCorSetDefaultParams( pPars ); pPars->fLatchCorr = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCPrcvwh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 0 ) goto usage; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBTLimit < 0 ) goto usage; break; case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } pPars->nPrefix = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nPrefix < 0 ) goto usage; break; case 'r': pPars->fUseRings ^= 1; break; case 'c': pPars->fUseCSat ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVerboseFlops ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Lcorr(): There is no AIG.\n" ); return 1; } if ( Gia_ManBoxNum(pAbc->pGia) && Gia_ManRegBoxNum(pAbc->pGia) ) { if ( pAbc->pGia->pAigExtra == NULL ) { printf( "Timing manager is given but there is no GIA of boxes.\n" ); return 0; } pTemp = Gia_ManSweepWithBoxes( pAbc->pGia, NULL, pPars, 0, 0, pPars->fVerbose, pPars->fVerboseFlops ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &lcorr [-FCP num] [-rcvwh]\n" ); Abc_Print( -2, "\t performs latch correpondence computation\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-F num : the number of timeframes in inductive case [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-P num : the number of timeframes in the prefix [default = %d]\n", pPars->nPrefix ); Abc_Print( -2, "\t-r : toggle using implication rings during refinement [default = %s]\n", pPars->fUseRings? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParCor_t Pars, * pPars = &Pars; Gia_Man_t * pTemp; int c; Cec_ManCorSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCPkrecqwvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFrames < 0 ) goto usage; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBTLimit < 0 ) goto usage; break; case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } pPars->nPrefix = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nPrefix < 0 ) goto usage; break; case 'k': pPars->fConstCorr ^= 1; break; case 'r': pPars->fUseRings ^= 1; break; case 'e': pPars->fMakeChoices ^= 1; break; case 'c': pPars->fUseCSat ^= 1; break; case 'q': pPars->fStopWhenGone ^= 1; break; case 'w': pPars->fVerboseFlops ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Scorr(): There is no AIG.\n" ); return 1; } if ( Gia_ManBoxNum(pAbc->pGia) && Gia_ManRegBoxNum(pAbc->pGia) ) { if ( pAbc->pGia->pAigExtra == NULL ) { printf( "Timing manager is given but there is no GIA of boxes.\n" ); return 0; } pTemp = Gia_ManSweepWithBoxes( pAbc->pGia, NULL, pPars, 0, 0, pPars->fVerbose, pPars->fVerboseFlops ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &scorr [-FCP num] [-krecqwvh]\n" ); Abc_Print( -2, "\t performs signal correpondence computation\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-F num : the number of timeframes in inductive case [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-P num : the number of timeframes in the prefix [default = %d]\n", pPars->nPrefix ); Abc_Print( -2, "\t-k : toggle using constant correspondence [default = %s]\n", pPars->fConstCorr? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using implication rings during refinement [default = %s]\n", pPars->fUseRings? "yes": "no" ); Abc_Print( -2, "\t-e : toggle using equivalences as choices [default = %s]\n", pPars->fMakeChoices? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-q : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Choice( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParChc_t Pars, * pPars = &Pars; Gia_Man_t * pTemp; int c; Cec_ManChcSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Ccvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBTLimit < 0 ) goto usage; break; case 'c': pPars->fUseCSat ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Choice(): There is no AIG.\n" ); return 1; } pTemp = Cec_ManChoiceComputation( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &choice [-C num] [-cvh]\n" ); Abc_Print( -2, "\t performs computation of structural choices\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParSat_t ParsSat, * pPars = &ParsSat; Gia_Man_t * pTemp; int c; int fCSat = 0; Cec_ManSatSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CSNnmtcvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBTLimit < 0 ) goto usage; break; case '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 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } pPars->nCallsRecycle = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCallsRecycle < 0 ) goto usage; break; case 'n': pPars->fNonChrono ^= 1; break; case 'm': pPars->fCheckMiter ^= 1; break; case 't': pPars->fLearnCls ^= 1; break; case 'c': fCSat ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Sat(): There is no AIG.\n" ); return 1; } if ( fCSat ) { Vec_Int_t * vCounters; Vec_Str_t * vStatus; if ( pPars->fLearnCls ) vCounters = Tas_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); else if ( pPars->fNonChrono ) vCounters = Cbs_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); else vCounters = Cbs_ManSolveMiter( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); Vec_IntFree( vCounters ); Vec_StrFree( vStatus ); } else { pTemp = Cec_ManSatSolving( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); } return 0; usage: Abc_Print( -2, "usage: &sat [-CSN ] [-nmctvh]\n" ); Abc_Print( -2, "\t performs SAT solving for the combinational outputs\n" ); 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 min number of variables to recycle the solver [default = %d]\n", pPars->nSatVarMax ); Abc_Print( -2, "\t-N num : the min number of calls to recycle the solver [default = %d]\n", pPars->nCallsRecycle ); Abc_Print( -2, "\t-n : toggle using non-chronological backtracking [default = %s]\n", pPars->fNonChrono? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", fCSat? "yes": "no" ); Abc_Print( -2, "\t-t : toggle using learning in curcuit-based solver [default = %s]\n", pPars->fLearnCls? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [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_CommandAbc9SatEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Gia_ManSatEnum( Gia_Man_t * p, int nConfLimit, int nTimeOut, int fVerbose ); int c, nConfLimit = 0, nTimeOut = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CTvh" ) ) != 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 '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 'v': fVerbose ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SatEnum(): There is no AIG.\n" ); return 1; } Gia_ManSatEnum( pAbc->pGia, nConfLimit, nTimeOut, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &satenum [-CT ] [-vh]\n" ); Abc_Print( -2, "\t enumerates solutions of the combinational miter\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-T num : global timeout [default = %d]\n", nTimeOut ); 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_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParFra_t ParsFra, * pPars = &ParsFra; Gia_Man_t * pTemp; int c; Cec_ManFraSetDefaultParams( pPars ); pPars->fSatSweeping = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WRILDCrmdcwvh" ) ) != 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 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } pPars->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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->nItersMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nItersMax < 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->nLevelMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLevelMax < 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 '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 'r': pPars->fRewriting ^= 1; break; case 'm': pPars->fCheckMiter ^= 1; break; case 'd': pPars->fDualOut ^= 1; break; case 'c': pPars->fRunCSat ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Fraig(): There is no AIG.\n" ); return 1; } pTemp = Cec_ManSatSweeping( pAbc->pGia, pPars, 0 ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &fraig [-WRILDC ] [-rmdcwvh]\n" ); Abc_Print( -2, "\t performs combinational SAT sweeping\n" ); Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-I num : the number of sweeping iterations [default = %d]\n", pPars->nItersMax ); Abc_Print( -2, "\t-L num : the max number of levels of nodes to consider [default = %d]\n", pPars->nLevelMax ); Abc_Print( -2, "\t-D num : the max number of steps of speculative reduction [default = %d]\n", pPars->nDepthMax ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-r : toggle the use of AIG rewriting [default = %s]\n", pPars->fRewriting? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-d : toggle using double output miters [default = %s]\n", pPars->fDualOut? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based solver [default = %s]\n", pPars->fRunCSat? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing even more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9CFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c; Ssc_Pars_t Pars, * pPars = &Pars; Ssc_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WCacvh" ) ) != 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 'a': pPars->fAppend ^= 1; break; case 'c': pPars->fVerify ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9CFraig(): There is no AIG.\n" ); return 1; } pTemp = Ssc_PerformSweepingConstr( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &cfraig [-WC ] [-acvh]\n" ); Abc_Print( -2, "\t performs combinational SAT sweeping under constraints\n" ); Abc_Print( -2, "\t which are present in the AIG or set manually using \"constr\"\n" ); Abc_Print( -2, "\t (constraints are listed as last POs and true when they are 0)\n" ); Abc_Print( -2, "\t-W num : the 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-a : toggle appending constraints to the result [default = %s]\n", pPars->fAppend? "yes": "no" ); Abc_Print( -2, "\t-c : toggle performing internal verification [default = %s]\n", pPars->fVerify? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileNameIn = NULL; char pFileName[10] = "gsrm.aig", pFileName2[10] = "gsyn.aig"; Gia_Man_t * pTemp, * pAux; int c, fVerbose = 0; int fSynthesis = 0; int fSpeculate = 1; int fSkipSome = 0; int fDualOut = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Adrsfvh" ) ) != EOF ) { switch ( c ) { case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" ); goto usage; } pFileNameIn = argv[globalUtilOptind]; globalUtilOptind++; break; case 'd': fDualOut ^= 1; break; case 'r': fSynthesis ^= 1; break; case 's': fSpeculate ^= 1; break; case 'f': fSkipSome ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Srm(): There is no AIG.\n" ); return 1; } sprintf(pFileName, "gsrm%s.aig", fSpeculate? "" : "s" ); sprintf(pFileName2, "gsyn%s.aig", fSpeculate? "" : "s" ); pTemp = Gia_ManSpecReduce( pAbc->pGia, fDualOut, fSynthesis, fSpeculate, fSkipSome, fVerbose ); if ( pTemp ) { if ( fSpeculate ) { pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); } Gia_AigerWrite( pTemp, pFileNameIn ? pFileNameIn : pFileName, 0, 0 ); Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); } if ( fSynthesis ) { pTemp = Gia_ManEquivReduce( pAbc->pGia, 1, fDualOut, 0, fVerbose ); if ( pTemp ) { pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); Gia_AigerWrite( pTemp, pFileName2, 0, 0 ); Abc_Print( 1, "Reduced original network was written into file \"%s\".\n", pFileName2 ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); } } return 0; usage: Abc_Print( -2, "usage: &srm [-A file] [-drsfvh]\n" ); Abc_Print( -2, "\t writes speculatively reduced model into file \"%s\"\n", pFileName ); Abc_Print( -2, "\t-A file : file name for dumping speculative-reduced model [default = \"gsrm.aig\"]\n" ); Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-r : toggle writing reduced network for synthesis [default = %s]\n", fSynthesis? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using speculation at the internal nodes [default = %s]\n", fSpeculate? "yes": "no" ); Abc_Print( -2, "\t-f : toggle filtering to remove redundant equivalences [default = %s]\n", fSkipSome? "yes": "no" ); Abc_Print( -2, "\t-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_CommandAbc9Srm2( Abc_Frame_t * pAbc, int argc, char ** argv ) { char pFileName[10], * pFileName1, * pFileName2; Gia_Man_t * pTemp, * pAux; int fLatchA = 0, fLatchB = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "abvh" ) ) != EOF ) { switch ( c ) { case 'a': fLatchA ^= 1; break; case 'b': fLatchB ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Srm2(): There is no AIG.\n" ); return 1; } if ( pAbc->pGia->pReprs == NULL || pAbc->pGia->pNexts == NULL ) { Abc_Print( -1, "Equivalences are not defined.\n" ); return 0; } if ( argc != globalUtilOptind + 2 ) { Abc_Print( -1, "Abc_CommandAbc9Srm2(): Expecting two file names on the command line.\n" ); return 1; } // get the input file name pFileName1 = argv[globalUtilOptind]; pFileName2 = argv[globalUtilOptind+1]; // create file name sprintf(pFileName, "gsrm.aig" ); pTemp = Gia_ManDup( pAbc->pGia ); // copy equivalences pTemp->pReprs = ABC_ALLOC( Gia_Rpr_t, Gia_ManObjNum(pTemp) ); memcpy( pTemp->pReprs, pAbc->pGia->pReprs, sizeof(Gia_Rpr_t) * Gia_ManObjNum(pTemp) ); pTemp->pNexts = ABC_ALLOC( int, Gia_ManObjNum(pTemp) ); memcpy( pTemp->pNexts, pAbc->pGia->pNexts, sizeof(int) * Gia_ManObjNum(pTemp) ); //Gia_ManPrintStats( pTemp, 0 ); // filter the classes if ( !Gia_ManFilterEquivsForSpeculation( pTemp, pFileName1, pFileName2, fLatchA, fLatchB ) ) { Gia_ManStop( pTemp ); Abc_Print( -1, "Filtering equivalences has failed.\n" ); return 1; } //Gia_ManPrintStats( pTemp, 0 ); pTemp = Gia_ManSpecReduce( pAux = pTemp, 0, 0, 1, 0, 0 ); Gia_ManStop( pAux ); if ( pTemp ) { pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); Gia_AigerWrite( pTemp, pFileName, 0, 0 ); Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); } return 0; usage: Abc_Print( -2, "usage: &srm2 [-abvh] \n" ); Abc_Print( -2, "\t writes speculatively reduced model into file \"%s\"\n", pFileName ); Abc_Print( -2, "\t only preserves equivalences across PartA and PartB\n" ); Abc_Print( -2, "\t-a : toggle using latches only in PartA [default = %s]\n", fLatchA? "yes": "no" ); Abc_Print( -2, "\t-b : toggle using latches only in PartB [default = %s]\n", fLatchB? "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_CommandAbc9Filter( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileName1 = NULL, * pFileName2 = NULL; int fFlopsOnly = 0, fFlopsWith = 0, fUseRiDrivers = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "fgivh" ) ) != EOF ) { switch ( c ) { case 'f': fFlopsOnly ^= 1; break; case 'g': fFlopsWith ^= 1; break; case 'i': fUseRiDrivers ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Srm2(): There is no AIG.\n" ); return 1; } if ( pAbc->pGia->pReprs == NULL || pAbc->pGia->pNexts == NULL ) { Abc_Print( -1, "Equivalences are not defined.\n" ); return 0; } if ( argc != globalUtilOptind && argc != globalUtilOptind + 2 ) { Abc_Print( -1, "Abc_CommandAbc9Srm2(): Expecting two file names on the command line.\n" ); return 1; } // filter using one of the choices if ( fFlopsOnly ^ fFlopsWith ) Gia_ManFilterEquivsUsingLatches( pAbc->pGia, fFlopsOnly, fFlopsWith, fUseRiDrivers ); // get the input file name if ( argc == globalUtilOptind + 2 ) { pFileName1 = argv[globalUtilOptind]; pFileName2 = argv[globalUtilOptind+1]; if ( !Gia_ManFilterEquivsUsingParts( pAbc->pGia, pFileName1, pFileName2 ) ) { Abc_Print( -1, "Filtering equivalences using PartA and PartB has failed.\n" ); return 1; } } return 0; usage: Abc_Print( -2, "usage: &filter [-fgivh] \n" ); Abc_Print( -2, "\t performs filtering of equivalence classes\n" ); Abc_Print( -2, "\t (if Parts A/B are given, removes classes composed of one part)\n" ); Abc_Print( -2, "\t-f : toggle removing all elements except flops [default = %s]\n", fFlopsOnly? "yes": "no" ); Abc_Print( -2, "\t-g : toggle removing classes without flops [default = %s]\n", fFlopsWith? "yes": "no" ); Abc_Print( -2, "\t-i : toggle using flop inputs instead of flop outputs [default = %s]\n", fUseRiDrivers? "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_CommandAbc9Reduce( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp, * pTemp2; int c, fVerbose = 0; int fUseAll = 0; int fDualOut = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "advh" ) ) != EOF ) { switch ( c ) { case 'a': fUseAll ^= 1; break; case 'd': fDualOut ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Reduce(): There is no AIG.\n" ); return 1; } if ( fUseAll ) { pTemp = Gia_ManEquivReduce( pAbc->pGia, fUseAll, fDualOut, 0, fVerbose ); pTemp = Gia_ManSeqStructSweep( pTemp2 = pTemp, 1, 1, 0 ); Gia_ManStop( pTemp2 ); } else pTemp = Gia_ManEquivReduceAndRemap( pAbc->pGia, 1, fDualOut ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &reduce [-advh]\n" ); Abc_Print( -2, "\t reduces the circuit using equivalence classes\n" ); Abc_Print( -2, "\t-a : toggle merging all equivalences [default = %s]\n", fUseAll? "yes": "no" ); Abc_Print( -2, "\t-d : toggle using dual-output merging [default = %s]\n", fDualOut? "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_CommandAbc9EquivMark( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManEquivMark( Gia_Man_t * p, char * pFileName, int fSkipSome, int fVerbose ); char * pFileName; int c, fVerbose = 0; int fSkipSome = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "fvh" ) ) != EOF ) { switch ( c ) { case 'f': fSkipSome ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9EquivMark(): There is no AIG.\n" ); return 1; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // mark equivalences Gia_ManEquivMark( pAbc->pGia, pFileName, fSkipSome, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &equiv_mark [-fvh] \n" ); Abc_Print( -2, "\t marks equivalences using an external miter\n" ); Abc_Print( -2, "\t-f : toggle the use of filtered equivalences [default = %s]\n", fSkipSome? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file with the external miter to read\n"); Abc_Print( -2, "\t \n" ); Abc_Print( -2, "\t The external miter should be generated by &srm -s\n" ); Abc_Print( -2, "\t and (partially) solved by any verification engine(s).\n" ); Abc_Print( -2, "\t The external miter should have as many POs as\n" ); Abc_Print( -2, "\t the number of POs in the current AIG plus\n" ); Abc_Print( -2, "\t the number of equivalences in the current AIG.\n" ); Abc_Print( -2, "\t If some POs are proved, the corresponding equivs\n" ); Abc_Print( -2, "\t are marked as proved, to be reduced by &reduce.\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9EquivFilter( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManEquivFilter( Gia_Man_t * p, Vec_Int_t * vPoIds, int fVerbose ); int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9EquivFilter(): There is no AIG.\n" ); return 1; } Gia_ManEquivFilter( pAbc->pGia, pAbc->vAbcObjIds, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &equiv_filter [-vh]\n" ); Abc_Print( -2, "\t filters equivalence candidates after disproving some SRM outputs\n" ); Abc_Print( -2, "\t (the array of disproved outputs should be given as pAbc->vAbcObjIds)\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_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cec_ParCec_t ParsCec, * pPars = &ParsCec; FILE * pFile; Gia_Man_t * pSecond, * pMiter; char * FileName, * pTemp; char ** pArgvNew; int c, nArgcNew, fMiter = 0, fDualOutput = 0, fDumpMiter = 0; Cec_ManCecSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CTnmdasvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBTLimit < 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } pPars->TimeLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeLimit < 0 ) goto usage; break; case 'n': pPars->fNaive ^= 1; break; case 'm': fMiter ^= 1; break; case 'd': fDualOutput ^= 1; break; case 'a': fDumpMiter ^= 1; break; case 's': pPars->fSilent ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Cec(): There is no AIG.\n" ); return 1; } if ( fMiter ) { if ( fDualOutput ) { if ( Gia_ManPoNum(pAbc->pGia) & 1 ) { Abc_Print( -1, "The dual-output miter should have an even number of outputs.\n" ); return 1; } if ( !pPars->fSilent ) Abc_Print( 1, "Assuming the current network is a double-output miter. (Conflict limit = %d.)\n", pPars->nBTLimit ); pAbc->Status = Cec_ManVerify( pAbc->pGia, pPars ); } else { Gia_Man_t * pTemp; if ( !pPars->fSilent ) Abc_Print( 1, "Assuming the current network is a single-output miter. (Conflict limit = %d.)\n", pPars->nBTLimit ); pTemp = Gia_ManDemiterToDual( pAbc->pGia ); pAbc->Status = Cec_ManVerify( pTemp, pPars ); ABC_SWAP( Abc_Cex_t *, pAbc->pGia->pCexComb, pTemp->pCexComb ); Gia_ManStop( pTemp ); } Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); return 0; } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { if ( pAbc->pGia->pSpec == NULL ) { Abc_Print( -1, "File name is not given on the command line.\n" ); return 1; } FileName = pAbc->pGia->pSpec; } else 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 ); pSecond = Gia_AigerRead( FileName, 0, 0, 0 ); if ( pSecond == NULL ) { Abc_Print( -1, "Reading AIGER has failed.\n" ); return 0; } // compute the miter pMiter = Gia_ManMiter( pAbc->pGia, pSecond, 0, 1, 0, 0, pPars->fVerbose ); if ( pMiter ) { if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 ); } pAbc->Status = Cec_ManVerify( pMiter, pPars ); Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); Gia_ManStop( pMiter ); } Gia_ManStop( pSecond ); return 0; usage: Abc_Print( -2, "usage: &cec [-CT num] [-nmdasvh]\n" ); Abc_Print( -2, "\t new combinational equivalence checker\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-n : toggle using naive SAT-based checking [default = %s]\n", pPars->fNaive? "yes":"no"); Abc_Print( -2, "\t-m : toggle miter vs. two circuits [default = %s]\n", fMiter? "miter":"two circuits"); Abc_Print( -2, "\t-d : toggle using dual output miter [default = %s]\n", fDualOutput? "yes":"no"); Abc_Print( -2, "\t-a : toggle writing dual-output miter [default = %s]\n", fDumpMiter? "yes":"no"); Abc_Print( -2, "\t-s : toggle silent operation [default = %s]\n", pPars->fSilent ? "yes":"no"); Abc_Print( -2, "\t-v : toggle 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_CommandAbc9Verify( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileSpec = NULL; int c, nBTLimit = 1000, nTimeLim = 0, fSeq = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CTsvh" ) ) != 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++; if ( nBTLimit < 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } nTimeLim = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeLim < 0 ) goto usage; break; case 's': fSeq ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc == globalUtilOptind + 1 ) { pFileSpec = argv[globalUtilOptind]; Extra_FileNameCorrectPath( pFileSpec ); printf( "Taking spec from file \"%s\".\n", pFileSpec ); } Gia_ManVerifyWithBoxes( pAbc->pGia, nBTLimit, nTimeLim, fSeq, fVerbose, pFileSpec ); return 0; usage: Abc_Print( -2, "usage: &verify [-CT num] [-svh] \n" ); Abc_Print( -2, "\t performs verification of combinational design\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nTimeLim ); Abc_Print( -2, "\t-s : toggle using sequential verification [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 : optional file name with the spec [default = not used]\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Sweep( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; Dch_Pars_t Pars, * pPars = &Pars; int c; Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WCStvh" ) ) != 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 't': pPars->fSimulateTfo ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Sweep(): There is no AIG.\n" ); return 1; } if ( Gia_ManBoxNum(pAbc->pGia) && pAbc->pGia->pAigExtra == NULL ) { printf( "Timing manager is given but there is no GIA of boxes.\n" ); return 0; } if ( Gia_ManBoxNum(pAbc->pGia) ) pTemp = Gia_ManSweepWithBoxes( pAbc->pGia, pPars, NULL, 0, 0, pPars->fVerbose, 0 ); else pTemp = Gia_ManFraigSweepSimple( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &sweep [-WCS num] [-tvh]\n" ); Abc_Print( -2, "\t performs SAT sweeping for AIG with boxes\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-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "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_CommandAbc9Force( Abc_Frame_t * pAbc, int argc, char ** argv ) { int nIters = 20; int fClustered = 1; int fVerbose = 1; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Icvh" ) ) != 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 'c': fClustered ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Force(): There is no AIG.\n" ); return 1; } For_ManExperiment( pAbc->pGia, nIters, fClustered, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &force [-I ] [-cvh]\n" ); Abc_Print( -2, "\t one-dimensional placement algorithm FORCE introduced by\n" ); Abc_Print( -2, "\t F. A. Aloul, I. L. Markov, and K. A. Sakallah (GLSVLSI�03).\n" ); Abc_Print( -2, "\t-I num : the number of refinement iterations [default = %d]\n", nIters ); Abc_Print( -2, "\t-c : toggle clustered representation [default = %s]\n", fClustered? "yes":"no"); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes":"no"); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Embed( Abc_Frame_t * pAbc, int argc, char ** argv ) { Emb_Par_t Pars, * pPars = &Pars; int c; pPars->nDims = 30; pPars->nIters = 10; pPars->nSols = 2; pPars->fRefine = 0; pPars->fCluster = 0; pPars->fDump = 0; pPars->fDumpLarge = 0; pPars->fShowImage = 0; pPars->fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "DIrcdlsvh" ) ) != EOF ) { switch ( c ) { case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } pPars->nDims = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nDims < 0 ) goto usage; break; case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } pPars->nIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIters < 0 ) goto usage; break; case 'r': pPars->fRefine ^= 1; break; case 'c': pPars->fCluster ^= 1; break; case 'd': pPars->fDump ^= 1; break; case 'l': pPars->fDumpLarge ^= 1; break; case 's': pPars->fShowImage ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Embed(): There is no AIG.\n" ); return 1; } Gia_ManSolveProblem( pAbc->pGia, pPars ); return 0; usage: Abc_Print( -2, "usage: &embed [-DI ] [-rdlscvh]\n" ); Abc_Print( -2, "\t fast placement based on high-dimensional embedding from\n" ); Abc_Print( -2, "\t D. Harel and Y. Koren, \"Graph drawing by high-dimensional\n" ); Abc_Print( -2, "\t embedding\", J. Graph Algs & Apps, 2004, Vol 8(2), pp. 195-217\n" ); Abc_Print( -2, "\t-D num : the number of dimensions for embedding [default = %d]\n", pPars->nDims ); Abc_Print( -2, "\t-I num : the number of refinement iterations [default = %d]\n", pPars->nIters ); Abc_Print( -2, "\t-r : toggle the use of refinement [default = %s]\n", pPars->fRefine? "yes":"no"); Abc_Print( -2, "\t-c : toggle clustered representation [default = %s]\n", pPars->fCluster? "yes":"no"); Abc_Print( -2, "\t-d : toggle dumping placement into a Gnuplot file [default = %s]\n", pPars->fDump? "yes":"no"); Abc_Print( -2, "\t-l : toggle dumping Gnuplot for large placement [default = %s]\n", pPars->fDumpLarge? "yes":"no"); Abc_Print( -2, "\t-s : toggle showing image if Gnuplot is installed [default = %s]\n", pPars->fShowImage? "yes":"no"); Abc_Print( -2, "\t-v : toggle 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_CommandAbc9Sopb( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int nLevelMax = 0; int nTimeWindow = 0; int nCutNum = 8; int nRelaxRatio = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "LWCRvh" ) ) != EOF ) { switch ( c ) { 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 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nTimeWindow = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeWindow < 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; } nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutNum < 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; } nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRelaxRatio < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Sopb(): There is no AIG.\n" ); return 1; } if ( nLevelMax || nTimeWindow ) pTemp = Gia_ManPerformSopBalanceWin( pAbc->pGia, nLevelMax, nTimeWindow, nCutNum, nRelaxRatio, fVerbose ); else pTemp = Gia_ManPerformSopBalance( pAbc->pGia, nCutNum, nRelaxRatio, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &sopb [-LWCR num] [-vh]\n" ); Abc_Print( -2, "\t performs SOP balancing\n" ); Abc_Print( -2, "\t-L num : optimize paths above this level [default = %d]\n", nLevelMax ); Abc_Print( -2, "\t-W num : optimize paths falling into this window [default = %d]\n", nTimeWindow ); Abc_Print( -2, "\t-C num : the number of cuts at a node [default = %d]\n", nCutNum ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", nRelaxRatio ); 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_CommandAbc9Dsdb( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int nLevelMax = 0; int nTimeWindow = 0; int nLutSize = 6; int nCutNum = 8; int nRelaxRatio = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "LWKCRvh" ) ) != EOF ) { switch ( c ) { 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 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nTimeWindow = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeWindow < 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 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutNum < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRelaxRatio < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Dsdb(): There is no AIG.\n" ); return 1; } if ( nLutSize > DAU_MAX_VAR ) { printf( "Abc_CommandAbc9Dsdb(): Size of the required DSD manager (%d) exceeds the precompiled limit (%d) (change parameter DAU_MAX_VAR).\n", nLutSize, DAU_MAX_VAR ); return 0; } if ( Abc_FrameReadManDsd2() && nLutSize > If_DsdManVarNum((If_DsdMan_t*)Abc_FrameReadManDsd2()) ) { printf( "Abc_CommandAbc9Dsdb(): Incompatible size of the DSD manager (run \"dsd_free -b\").\n" ); return 0; } if ( nLevelMax || nTimeWindow ) pTemp = Gia_ManPerformDsdBalanceWin( pAbc->pGia, nLevelMax, nTimeWindow, nLutSize, nCutNum, nRelaxRatio, fVerbose ); else pTemp = Gia_ManPerformDsdBalance( pAbc->pGia, nLutSize, nCutNum, nRelaxRatio, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &dsdb [-LWKCR num] [-vh]\n" ); Abc_Print( -2, "\t performs DSD balancing\n" ); Abc_Print( -2, "\t-L num : optimize paths above this level [default = %d]\n", nLevelMax ); Abc_Print( -2, "\t-W num : optimize paths falling into this window [default = %d]\n", nTimeWindow ); Abc_Print( -2, "\t-K num : the number of LUT inputs (LUT size) [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-C num : the number of cuts at a node [default = %d]\n", nCutNum ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", nRelaxRatio ); 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_CommandAbc9Flow( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManPerformFlow( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fMinAve, int fUseMfs, int fVerbose ); int nLutSize = 6; int nCutNum = 8; int fMinAve = 0; int fUseMfs = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCtmvh" ) ) != 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': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutNum < 0 ) goto usage; break; case 't': fMinAve ^= 1; break; case 'm': fUseMfs ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Flow(): There is no AIG.\n" ); return 1; } Gia_ManPerformFlow( Gia_ManHasMapping(pAbc->pGia), Gia_ManAndNum(pAbc->pGia), Gia_ManLevelNum(pAbc->pGia), nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &flow [-KC num] [-tmvh]\n" ); Abc_Print( -2, "\t integration optimization and mapping flow\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (LUT size) [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-C num : the number of cuts at a node [default = %d]\n", nCutNum ); Abc_Print( -2, "\t-t : toggle minimizing average rather than max delay [default = %s]\n", fMinAve? "yes": "no" ); Abc_Print( -2, "\t-m : toggle using \"mfs2\" in the script [default = %s]\n", fUseMfs? "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_CommandAbc9Flow2( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManPerformFlow2( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fBalance, int fMinAve, int fUseMfs, int fVerbose ); int nLutSize = 6; int nCutNum = 8; int fBalance = 0; int fMinAve = 0; int fUseMfs = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCbtmvh" ) ) != 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': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutNum < 0 ) goto usage; break; case 'b': fBalance ^= 1; break; case 't': fMinAve ^= 1; break; case 'm': fUseMfs ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Flow2(): There is no AIG.\n" ); return 1; } Gia_ManPerformFlow2( Gia_ManHasMapping(pAbc->pGia), Gia_ManAndNum(pAbc->pGia), Gia_ManLevelNum(pAbc->pGia), nLutSize, nCutNum, fBalance, fMinAve, fUseMfs, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &flow2 [-KC num] [-btmvh]\n" ); Abc_Print( -2, "\t integration optimization and mapping flow\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (LUT size) [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-C num : the number of cuts at a node [default = %d]\n", nCutNum ); Abc_Print( -2, "\t-b : toggle using SOP balancing during synthesis [default = %s]\n", fBalance? "yes": "no" ); Abc_Print( -2, "\t-t : toggle minimizing average (not maximum) level [default = %s]\n", fMinAve? "yes": "no" ); Abc_Print( -2, "\t-m : toggle using \"mfs2\" in the script [default = %s]\n", fUseMfs? "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_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[200]; char LutSize[200]; Gia_Man_t * pNew; If_Par_t Pars, * pPars = &Pars; int c; // set defaults Gia_ManSetIfParsDefault( pPars ); if ( pAbc->pLibLut == NULL ) { Abc_Print( -1, "LUT library is not given. Using default LUT library.\n" ); pAbc->pLibLut = If_LibLutSetSimple( 6 ); } pPars->pLutLib = (If_LibLut_t *)pAbc->pLibLut; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSTXYqalepmrsdbgxyofuijkztncvh" ) ) != 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 0 ) goto usage; // if the LUT size is specified, disable library pPars->pLutLib = NULL; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nCutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->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; } pPars->nFlowIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->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; } pPars->nAreaIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAreaIters < 0 ) goto usage; break; case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer no less than 3.\n" ); goto usage; } pPars->nGateSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nGateSize < 2 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } pPars->nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRelaxRatio < 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer 0,1,or 2.\n" ); goto usage; } pPars->nStructType = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nStructType < 0 || pPars->nStructType > 2 ) goto usage; break; case 'X': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer 0,1,or 2.\n" ); goto usage; } pPars->nAndDelay = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAndArea < 0 ) goto usage; break; case 'Y': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Y\" should be followed by a positive integer 0,1,or 2.\n" ); goto usage; } pPars->nAndArea = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAndDelay < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } pPars->DelayTarget = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0.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->Epsilon = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->Epsilon < 0.0 || pPars->Epsilon > 1.0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a floating point number.\n" ); goto usage; } pPars->WireDelay = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->WireDelay < 0.0 ) goto usage; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); goto usage; } pPars->pLutStruct = argv[globalUtilOptind]; globalUtilOptind++; if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by a 2- or 3-char string (e.g. \"44\" or \"555\").\n" ); goto usage; } break; case 'q': pPars->fPreprocess ^= 1; break; case 'a': pPars->fArea ^= 1; break; case 'r': pPars->fExpRed ^= 1; break; case 'l': pPars->fLatchPaths ^= 1; break; case 'e': pPars->fEdge ^= 1; break; case 'p': pPars->fPower ^= 1; break; case 'm': pPars->fCutMin ^= 1; break; case 's': pPars->fDelayOptLut ^= 1; break; case 'd': pPars->fUse34Spec ^= 1; break; case 'b': pPars->fUseBat ^= 1; break; case 'g': pPars->fDelayOpt ^= 1; break; case 'x': pPars->fDsdBalance ^= 1; break; case 'y': pPars->fUserRecLib ^= 1; break; case 'o': pPars->fUseBuffs ^= 1; break; case 'f': pPars->fEnableCheck75 ^= 1; break; case 'u': pPars->fEnableCheck75u ^= 1; break; case 'i': pPars->fUseCofVars ^= 1; break; // case 'j': // pPars->fEnableCheck07 ^= 1; // break; case 'j': pPars->fUseAndVars ^= 1; break; case 'k': pPars->fUseDsdTune ^= 1; break; case 'z': pPars->fDeriveLuts ^= 1; break; case 't': pPars->fDoAverage ^= 1; break; case 'n': pPars->fUseDsd ^= 1; break; case 'c': pPars->fUseTtPerm ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': pPars->fHashMapping ^= 1; break; default: goto usage; } } if ( pAbc->pGia == NULL ) { if ( !Abc_FrameReadFlag("silentmode") ) Abc_Print( -1, "Empty GIA network.\n" ); return 0; } if ( Gia_ManBufNum(pAbc->pGia) ) { Abc_Print( -1, "This command does not work with barrier buffers.\n" ); return 1; } if ( Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Current AIG has mapping. Run \"&st\".\n" ); return 1; } if ( pPars->nLutSize == -1 ) { if ( pPars->pLutLib == NULL ) { Abc_Print( -1, "The LUT library is not given.\n" ); return 1; } // get LUT size from the library pPars->nLutSize = pPars->pLutLib->LutMax; // if variable pin delay, force truth table computation // if ( pPars->pLutLib->fVarPinDelays ) // pPars->fTruth = 1; } if ( pPars->nLutSize < 2 || pPars->nLutSize > IF_MAX_LUTSIZE ) { Abc_Print( -1, "Incorrect LUT size (%d).\n", pPars->nLutSize ); return 1; } if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) ) { Abc_Print( -1, "Incorrect number of cuts.\n" ); return 1; } // enable truth table computation if choices are selected if ( Gia_ManHasChoices(pAbc->pGia) ) { // if ( !Abc_FrameReadFlag("silentmode") ) // Abc_Print( 0, "Performing LUT mapping with choices.\n" ); pPars->fExpRed = 0; } if ( pPars->fUseBat ) { if ( pPars->nLutSize < 4 || pPars->nLutSize > 6 ) { Abc_Print( -1, "This feature only works for {4,5,6}-LUTs.\n" ); return 1; } pPars->fCutMin = 1; } if ( pPars->fEnableCheck07 + pPars->fUseCofVars + pPars->fUseDsdTune + pPars->fEnableCheck75 + pPars->fEnableCheck75u + (pPars->pLutStruct != NULL) > 1 ) { Abc_Print( -1, "Only one additional check can be performed at the same time.\n" ); return 1; } if ( pPars->fEnableCheck07 ) { if ( pPars->nLutSize < 6 || pPars->nLutSize > 7 ) { Abc_Print( -1, "This feature only works for {6,7}-LUTs.\n" ); return 1; } pPars->pFuncCell = If_CutPerformCheck07; pPars->fCutMin = 1; } if ( pPars->fUseCofVars ) { if ( !(pPars->nLutSize & 1) ) { Abc_Print( -1, "This feature only works for odd-sized LUTs.\n" ); return 1; } pPars->fCutMin = 1; } if ( pPars->fUseAndVars ) pPars->fCutMin = 1; if ( pPars->fUseDsdTune ) { If_DsdMan_t * pDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd(); if ( pDsdMan == NULL ) { Abc_Print( -1, "DSD manager is not available.\n" ); return 1; } if ( pPars->nLutSize > If_DsdManVarNum(pDsdMan) ) { Abc_Print( -1, "LUT size (%d) is more than the number of variables in the DSD manager (%d).\n", pPars->nLutSize, If_DsdManVarNum(pDsdMan) ); return 1; } if ( pPars->fDeriveLuts && If_DsdManGetCellStr(pDsdMan) == NULL ) { Abc_Print( -1, "DSD manager is not matched with any particular cell.\n" ); return 1; } pPars->fCutMin = 1; pPars->fUseDsd = 1; If_DsdManSetNewAsUseless( pDsdMan ); } if ( pPars->fEnableCheck75 || pPars->fEnableCheck75u ) { if ( pPars->fEnableCheck75 && pPars->fEnableCheck75u ) { Abc_Print( -1, "Switches -f and -u are not compatible.\n" ); return 1; } if ( pPars->nLutSize < 5 || pPars->nLutSize > 8 ) { Abc_Print( -1, "This feature only works for {6,7,8}-LUTs.\n" ); return 1; } pPars->pFuncCell = If_CutPerformCheck75; pPars->fCutMin = 1; } if ( pPars->pLutStruct ) { if ( pPars->fDsdBalance ) { Abc_Print( -1, "Incompatible options (-S and -x).\n" ); return 1; } if ( pPars->nLutSize < 6 || pPars->nLutSize > 16 ) { Abc_Print( -1, "This feature only works for [6;16]-LUTs.\n" ); return 1; } pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck16; pPars->fCutMin = 1; } if ( pPars->fUse34Spec ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->nLutSize = 4; } // enable truth table computation if cut minimization is selected if ( pPars->fCutMin || pPars->fDeriveLuts ) { pPars->fTruth = 1; pPars->fExpRed = 0; if ( pPars->pLutStruct == NULL && !pPars->fUseDsdTune ) pPars->fDeriveLuts = 1; } // modify the subgraph recording if ( pPars->fUserRecLib ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; pPars->fUsePerm = 1; pPars->pLutLib = NULL; } // modify for delay optimization if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; pPars->fUseDsd = pPars->fDsdBalance || pPars->fDelayOptLut; pPars->pLutLib = NULL; } // modify for delay optimization if ( pPars->nGateSize > 0 ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; pPars->fUsePerm = 1; pPars->pLutLib = NULL; pPars->nLutSize = pPars->nGateSize; } if ( pPars->fUseDsd || pPars->fUseTtPerm ) { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fExpRed = 0; } if ( pPars->fUseDsd ) { int LutSize = (pPars->pLutStruct && pPars->pLutStruct[2] == 0)? pPars->pLutStruct[0] - '0' : 0; If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd(); if ( pPars->pLutStruct && pPars->pLutStruct[2] != 0 ) { printf( "DSD only works for LUT structures XY.\n" ); return 0; } if ( p && pPars->nLutSize > If_DsdManVarNum(p) ) { printf( "DSD manager has incompatible number of variables.\n" ); return 0; } if ( p && LutSize != If_DsdManLutSize(p) && !pPars->fDsdBalance ) { printf( "DSD manager has different LUT size.\n" ); return 0; } if ( p == NULL ) { if ( LutSize > DAU_MAX_VAR || pPars->nLutSize > DAU_MAX_VAR ) { printf( "Size of required DSD manager (%d) exceeds the precompiled limit (%d) (change parameter DAU_MAX_VAR).\n", LutSize, DAU_MAX_VAR ); return 0; } Abc_FrameSetManDsd( If_DsdManAlloc(pPars->nLutSize, LutSize) ); } } if ( pPars->fUserRecLib ) { if ( !Abc_NtkRecIsRunning3() ) { printf( "LMS manager is not running (use \"rec_start3\").\n" ); return 0; } if ( Abc_NtkRecInputNum3() != pPars->nLutSize ) { printf( "The number of library inputs (%d) different from the K parameters (%d).\n", Abc_NtkRecInputNum3(), pPars->nLutSize ); return 0; } } // complain if truth tables are requested but the cut size is too large if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE ) { Abc_Print( -1, "Truth tables cannot be computed for LUT larger than %d inputs.\n", IF_MAX_FUNC_LUTSIZE ); return 1; } if ( pAbc->pGia->pManTime && pAbc->pLibBox == NULL ) { Abc_Print( -1, "Design has boxes but box library is not entered.\n" ); return 1; } // perform mapping pNew = Gia_ManPerformMapping( pAbc->pGia, pPars ); if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9If(): Mapping of GIA has failed.\n" ); return 1; } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%.2f", pPars->DelayTarget ); if ( pPars->nLutSize == -1 ) sprintf(LutSize, "library" ); else sprintf(LutSize, "%d", pPars->nLutSize ); Abc_Print( -2, "usage: &if [-KCFAGRTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyofuijkztnchv]\n" ); Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); Abc_Print( -2, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters ); Abc_Print( -2, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); Abc_Print( -2, "\t-G num : the max AND/OR gate size for mapping (0 = unused) [default = %d]\n", pPars->nGateSize ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio ); Abc_Print( -2, "\t-T num : the type of LUT structures [default = any]\n", pPars->nStructType ); Abc_Print( -2, "\t-X num : delay of AND-gate in LUT library units [default = %d]\n", pPars->nAndDelay ); Abc_Print( -2, "\t-Y num : area of AND-gate in LUT library units [default = %d]\n", pPars->nAndArea ); Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon ); Abc_Print( -2, "\t-W float : sets wire delay between adjects LUTs [default = %f]\n", pPars->WireDelay ); Abc_Print( -2, "\t-S str : string representing the LUT structure [default = %s]\n", pPars->pLutStruct ? pPars->pLutStruct : "not used" ); Abc_Print( -2, "\t-q : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); Abc_Print( -2, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); Abc_Print( -2, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" ); Abc_Print( -2, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); Abc_Print( -2, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-s : toggles delay-oriented mapping used with -S [default = %s]\n", pPars->fDelayOptLut? "yes": "no" ); Abc_Print( -2, "\t-d : toggles deriving specialized matching step [default = %s]\n", pPars->fUse34Spec? "yes": "no" ); Abc_Print( -2, "\t-b : toggles the use of one special feature [default = %s]\n", pPars->fUseBat? "yes": "no" ); Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" ); Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" ); Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-f : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck75? "yes": "no" ); Abc_Print( -2, "\t-u : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck75u? "yes": "no" ); Abc_Print( -2, "\t-i : toggles using cofactoring variables [default = %s]\n", pPars->fUseCofVars? "yes": "no" ); // Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" ); Abc_Print( -2, "\t-j : toggles using AND bi-decomposition [default = %s]\n", pPars->fUseAndVars? "yes": "no" ); Abc_Print( -2, "\t-k : toggles matching based on precomputed DSD manager [default = %s]\n", pPars->fUseDsdTune? "yes": "no" ); Abc_Print( -2, "\t-z : toggles deriving LUTs when mapping into LUT structures [default = %s]\n", pPars->fDeriveLuts? "yes": "no" ); Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-n : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" ); Abc_Print( -2, "\t-h : toggles rehashing AIG after mapping [default = %s]\n", pPars->fHashMapping? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Iff( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose ); int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Iff(): There is no AIG to map.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Iff(): Mapping of the AIG is not defined.\n" ); return 1; } if ( pAbc->pLibLut == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Iff(): LUT library is not defined.\n" ); return 1; } Gia_ManIffTest( pAbc->pGia, (If_LibLut_t *)pAbc->pLibLut, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &iff [-vh]\n" ); Abc_Print( -2, "\t performs structural mapping into LUT structures\n" ); 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_CommandAbc9If2( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Mpm_ManCellMapping( Gia_Man_t * p, Mpm_Par_t * pPars, void * pMio ); extern Gia_Man_t * Mpm_ManLutMapping( Gia_Man_t * p, Mpm_Par_t * pPars ); char Buffer[200]; Abc_Ntk_t * pTemp; Gia_Man_t * pNew; Mpm_Par_t Pars, * pPars = &Pars; int c, nLutSize = 6; // set defaults Mpm_ManSetParsDefault( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCDtmzrcuxvwh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" ); goto usage; } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLutSize < 2 || nLutSize > 16 ) { Abc_Print( -1, "LUT size %d is not supported.\n", nLutSize ); goto usage; } break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nNumCuts = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nNumCuts < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } pPars->DelayTarget = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0.0 ) goto usage; break; case 't': pPars->fUseGates ^= 1; break; case 'm': pPars->fCutMin ^= 1; break; case 'z': pPars->fDeriveLuts ^= 1; break; case 'r': pPars->fOneRound ^= 1; break; case 'c': pPars->fMap4Cnf ^= 1; break; case 'u': pPars->fMap4Aig ^= 1; break; case 'x': pPars->fMap4Gates ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } if ( pPars->fMap4Cnf ) pPars->fUseDsd = 1; if ( pPars->fCutMin ) pPars->fUseDsd = 1; // pPars->fUseTruth = 1; if ( pPars->fMap4Gates ) { pPars->fUseDsd = 1; if ( pAbc->pLibScl == NULL ) { Abc_Print( -1, "There is no SCL library available.\n" ); return 1; } pPars->pScl = pAbc->pLibScl; } if ( pPars->fUseDsd || pPars->fUseTruth ) pPars->fDeriveLuts = 1; if ( pPars->fUseDsd && nLutSize != 6 ) { Abc_Print( -1, "Currently DSD can only be used with 6-input cuts.\n" ); return 1; } // perform mapping assert( pPars->pLib == NULL ); if ( pPars->fMap4Gates ) { if ( Abc_FrameReadLibGen() == NULL ) { Abc_Print( -1, "There is no GENLIB library available.\n" ); return 1; } pPars->pLib = Mpm_LibLutSetSimple( nLutSize ); pTemp = Mpm_ManCellMapping( pAbc->pGia, pPars, Abc_FrameReadLibGen() ); Mpm_LibLutFree( pPars->pLib ); if ( pTemp == NULL ) { Abc_Print( -1, "Abc_CommandAbc9If2(): Mapping into standard cells has failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pTemp ); } else { pPars->pLib = Mpm_LibLutSetSimple( nLutSize ); pNew = Mpm_ManLutMapping( pAbc->pGia, pPars ); Mpm_LibLutFree( pPars->pLib ); if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9If2(): Mapping into LUTs has failed.\n" ); return 1; } Abc_FrameUpdateGia( pAbc, pNew ); } return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%d", pPars->DelayTarget ); Abc_Print( -2, "usage: &if2 [-KCD num] [-tmzrcuxvwh]\n" ); Abc_Print( -2, "\t performs technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : sets the LUT size for the mapping [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nNumCuts ); Abc_Print( -2, "\t-D num : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-t : enables using AND/XOR/MUX nodes instead of simple AIG [default = %s]\n", pPars->fUseGates? "yes": "no" ); Abc_Print( -2, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-z : toggles deriving LUTs when mapping into LUT structures [default = %s]\n", pPars->fDeriveLuts? "yes": "no" ); Abc_Print( -2, "\t-r : toggles using one round of mapping [default = %s]\n", pPars->fOneRound? "yes": "no" ); Abc_Print( -2, "\t-c : toggles mapping for CNF computation [default = %s]\n", pPars->fMap4Cnf? "yes": "no" ); Abc_Print( -2, "\t-u : toggles mapping for AIG computation [default = %s]\n", pPars->fMap4Aig? "yes": "no" ); Abc_Print( -2, "\t-x : toggles mapping for standard cells [default = %s]\n", pPars->fMap4Gates? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Jf( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[200]; Jf_Par_t Pars, * pPars = &Pars; Gia_Man_t * pNew; int c; Jf_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCDWaekmdcgvwh" ) ) != 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax ) { Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize ); goto usage; } break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax ) { Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum ); goto usage; } break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } pPars->DelayTarget = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0.0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); goto usage; } pPars->nVerbLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVerbLimit < 0 ) goto usage; break; case 'a': pPars->fAreaOnly ^= 1; break; case 'e': pPars->fOptEdge ^= 1; break; case 'k': pPars->fCoarsen ^= 1; break; case 'm': pPars->fCutMin ^= 1; break; case 'd': pPars->fFuncDsd ^= 1; break; case 'c': pPars->fGenCnf ^= 1; break; case 'g': pPars->fPureAig ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } if ( Gia_ManBufNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Jf(): This command does not work with barrier buffers.\n" ); return 1; } if ( (pPars->fFuncDsd || pPars->fGenCnf) && pPars->nLutSize > 6 ) { Abc_Print( -1, "Abc_CommandAbc9Jf(): DSD computation works for LUT6 or less.\n" ); return 1; } if ( (pPars->fFuncDsd || pPars->fGenCnf) && !Sdm_ManCanRead() ) { Abc_Print( -1, "Abc_CommandAbc9Jf(): Cannot input DSD data from file.\n" ); return 1; } pNew = Jf_ManPerformMapping( pAbc->pGia, pPars ); if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Jf(): Mapping into LUTs has failed.\n" ); return 1; } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%d", pPars->DelayTarget ); Abc_Print( -2, "usage: &jf [-KCDW num] [-akmdcgvwh]\n" ); Abc_Print( -2, "\t performs technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum ); Abc_Print( -2, "\t-D num : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-W num : min frequency when printing functions with \"-w\" [default = %d]\n", pPars->nVerbLimit ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" ); Abc_Print( -2, "\t-e : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" ); Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-d : toggles using DSD to represent cut functions [default = %s]\n", pPars->fFuncDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles mapping for CNF generation [default = %s]\n", pPars->fGenCnf? "yes": "no" ); Abc_Print( -2, "\t-g : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Kf( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Kf_ManSetDefaultPars( Jf_Par_t * pPars ); extern Gia_Man_t * Kf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); char Buffer[200]; Jf_Par_t Pars, * pPars = &Pars; Gia_Man_t * pNew; int c; Kf_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCPDWaekmdcgtsvwh" ) ) != 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax ) { Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize ); goto usage; } break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax ) { Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum ); goto usage; } break; case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); goto usage; } pPars->nProcNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nProcNum < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } pPars->DelayTarget = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0.0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); goto usage; } pPars->nVerbLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVerbLimit < 0 ) goto usage; break; case 'a': pPars->fAreaOnly ^= 1; break; case 'e': pPars->fOptEdge ^= 1; break; case 'k': pPars->fCoarsen ^= 1; break; case 'm': pPars->fCutMin ^= 1; break; case 'd': pPars->fFuncDsd ^= 1; break; case 'c': pPars->fGenCnf ^= 1; break; case 'g': pPars->fPureAig ^= 1; break; case 't': pPars->fCutHashing ^= 1; break; case 's': pPars->fCutSimple ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } pNew = Kf_ManPerformMapping( pAbc->pGia, pPars ); if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Kf(): Mapping into LUTs has failed.\n" ); return 1; } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%d", pPars->DelayTarget ); Abc_Print( -2, "usage: &kf [-KCPDW num] [-akmdcgtsvwh]\n" ); Abc_Print( -2, "\t performs technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum ); Abc_Print( -2, "\t-P num : the number of cut computation processes (0 <= P <= %d) [default = %d]\n", pPars->nProcNumMax, pPars->nProcNum ); Abc_Print( -2, "\t-D num : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-W num : min frequency when printing functions with \"-w\" [default = %d]\n", pPars->nVerbLimit ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" ); Abc_Print( -2, "\t-e : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" ); Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-d : toggles using DSD to represent cut functions [default = %s]\n", pPars->fFuncDsd? "yes": "no" ); Abc_Print( -2, "\t-c : toggles mapping for CNF generation [default = %s]\n", pPars->fGenCnf? "yes": "no" ); Abc_Print( -2, "\t-g : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" ); Abc_Print( -2, "\t-t : toggles cut computation using hash table [default = %s]\n", pPars->fCutHashing? "yes": "no" ); Abc_Print( -2, "\t-s : toggles cut computation using a simple method [default = %s]\n", pPars->fCutSimple? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Lf( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[200]; Jf_Par_t Pars, * pPars = &Pars; Gia_Man_t * pNew; int c; Lf_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWMaekmupgtvwh" ) ) != 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax ) { Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize ); goto usage; } break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax ) { Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum ); 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; } pPars->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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; } pPars->nRoundsEla = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRoundsEla < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } pPars->nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRelaxRatio < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } pPars->nCoarseLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCoarseLimit < 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" ); return 0; } pPars->nAreaTuner = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAreaTuner < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } pPars->DelayTarget = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0.0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); goto usage; } pPars->nVerbLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVerbLimit < 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; } pPars->nLutSizeMux = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSizeMux < 2 || pPars->nLutSizeMux > pPars->nLutSizeMax ) { Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSizeMux ); goto usage; } break; case 'a': pPars->fAreaOnly ^= 1; break; case 'e': pPars->fOptEdge ^= 1; break; case 'k': pPars->fCoarsen ^= 1; break; case 'm': pPars->fCutMin ^= 1; break; case 'u': pPars->fUseMux7 ^= 1; break; case 'p': pPars->fPower ^= 1; break; case 'g': pPars->fPureAig ^= 1; break; case 't': pPars->fDoAverage ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } if ( Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Current AIG has mapping. Run \"&st\".\n" ); return 1; } if ( pPars->nLutSizeMux && pPars->fUseMux7 ) { Abc_Print( -1, "Flags \"-M\" and \"-u\" are incompatible.\n" ); return 1; } pNew = Lf_ManPerformMapping( pAbc->pGia, pPars ); if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Lf(): Mapping into LUTs has failed.\n" ); return 1; } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%d", pPars->DelayTarget ); Abc_Print( -2, "usage: &lf [-KCFARLEDM num] [-kmupgtvwh]\n" ); Abc_Print( -2, "\t performs technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum ); Abc_Print( -2, "\t-F num : the number of area flow rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-A num : the number of exact area rounds [default = %d]\n", pPars->nRoundsEla ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio ); Abc_Print( -2, "\t-L num : the fanout limit for coarsening XOR/MUX (num >= 2) [default = %d]\n", pPars->nCoarseLimit ); Abc_Print( -2, "\t-E num : the area/edge tradeoff parameter (0 <= num <= 100) [default = %d]\n", pPars->nAreaTuner ); Abc_Print( -2, "\t-D num : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-M num : LUT size when cofactoring is performed (0 <= num <= 100) [default = %d]\n", pPars->nLutSizeMux ); // Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" ); Abc_Print( -2, "\t-e : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" ); Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-u : toggles using additional MUXes [default = %s]\n", pPars->fUseMux7? "yes": "no" ); Abc_Print( -2, "\t-p : toggles power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); Abc_Print( -2, "\t-g : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" ); Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Mf( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[200]; Jf_Par_t Pars, * pPars = &Pars; Gia_Man_t * pNew; int c; Mf_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWaekmcgvwh" ) ) != 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax ) { Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize ); goto usage; } break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax ) { Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum ); 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; } pPars->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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; } pPars->nRoundsEla = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRoundsEla < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } pPars->nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRelaxRatio < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } pPars->nCoarseLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCoarseLimit < 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" ); return 0; } pPars->nAreaTuner = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAreaTuner < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } pPars->DelayTarget = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0.0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); goto usage; } pPars->nVerbLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVerbLimit < 0 ) goto usage; break; case 'a': pPars->fAreaOnly ^= 1; break; case 'e': pPars->fOptEdge ^= 1; break; case 'k': pPars->fCoarsen ^= 1; break; case 'm': pPars->fCutMin ^= 1; break; case 'c': pPars->fGenCnf ^= 1; break; case 'g': pPars->fPureAig ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } pNew = Mf_ManPerformMapping( pAbc->pGia, pPars ); if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Lf(): Mapping into LUTs has failed.\n" ); return 1; } if ( pPars->fGenCnf ) Cnf_DataFree( (Cnf_Dat_t*)pAbc->pGia->pData ), pAbc->pGia->pData = NULL; Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%d", pPars->DelayTarget ); Abc_Print( -2, "usage: &mf [-KCFARLED num] [-akmcgvwh]\n" ); Abc_Print( -2, "\t performs technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum ); Abc_Print( -2, "\t-F num : the number of area flow rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-A num : the number of exact area rounds [default = %d]\n", pPars->nRoundsEla ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio ); Abc_Print( -2, "\t-L num : the fanout limit for coarsening XOR/MUX (num >= 2) [default = %d]\n", pPars->nCoarseLimit ); Abc_Print( -2, "\t-E num : the area/edge tradeoff parameter (0 <= num <= 100) [default = %d]\n", pPars->nAreaTuner ); Abc_Print( -2, "\t-D num : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fAreaOnly? "yes": "no" ); Abc_Print( -2, "\t-e : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" ); Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-c : toggles mapping for CNF generation [default = %s]\n", pPars->fGenCnf? "yes": "no" ); Abc_Print( -2, "\t-g : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Nf( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Nf_ManSetDefaultPars( Jf_Par_t * pPars ); extern Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); extern Gia_Man_t * Pf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); char Buffer[200]; Jf_Par_t Pars, * pPars = &Pars; Gia_Man_t * pNew; int c; Nf_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDQWakpqfvwh" ) ) != 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax ) { Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize ); goto usage; } break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax ) { Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum ); 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; } pPars->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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; } pPars->nRoundsEla = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRoundsEla < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by an integer number.\n" ); return 0; } pPars->nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRelaxRatio < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by an integer number.\n" ); return 0; } pPars->nCoarseLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCoarseLimit < 0 ) goto usage; break; case 'E': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-E\" should be followed by an integer number.\n" ); return 0; } pPars->nAreaTuner = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAreaTuner < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer number.\n" ); goto usage; } pPars->DelayTarget = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0 ) goto usage; break; case 'Q': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer number.\n" ); goto usage; } pPars->nReqTimeFlex = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nReqTimeFlex < 0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); goto usage; } pPars->nVerbLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVerbLimit < 0 ) goto usage; break; case 'a': pPars->fAreaOnly ^= 1; break; case 'k': pPars->fCoarsen ^= 1; break; case 'p': pPars->fPinPerm ^= 1; break; case 'q': pPars->fPinQuick ^= 1; break; case 'f': pPars->fPinFilter ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } if ( Abc_FrameReadLibGen() == NULL ) { Abc_Print( -1, "Current library is not available.\n" ); return 1; } // if ( pPars->fAreaOnly ) // pNew = Pf_ManPerformMapping( pAbc->pGia, pPars ); // else pNew = Nf_ManPerformMapping( pAbc->pGia, pPars ); if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Nf(): Mapping into LUTs has failed.\n" ); return 1; } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%d", pPars->DelayTarget ); Abc_Print( -2, "usage: &nf [-KCFARLEDQ num] [-akpqfvwh]\n" ); Abc_Print( -2, "\t performs technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum ); Abc_Print( -2, "\t-F num : the number of area flow rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-A num : the number of exact area rounds (when \'-a\' is used) [default = %d]\n", pPars->nRoundsEla ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio ); Abc_Print( -2, "\t-L num : the fanout limit for coarsening XOR/MUX (num >= 2) [default = %d]\n", pPars->nCoarseLimit ); Abc_Print( -2, "\t-E num : the area/edge tradeoff parameter (0 <= num <= 100) [default = %d]\n", pPars->nAreaTuner ); Abc_Print( -2, "\t-D num : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-Q num : internal parameter impacting area of the mapping [default = %d]\n", pPars->nReqTimeFlex ); Abc_Print( -2, "\t-a : toggles SAT-based area-oriented mapping (experimental) [default = %s]\n", pPars->fAreaOnly? "yes": "no" ); Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-p : toggles pin permutation (more matches - better quality) [default = %s]\n", pPars->fPinPerm? "yes": "no" ); Abc_Print( -2, "\t-q : toggles quick mapping (fewer matches - worse quality) [default = %s]\n", pPars->fPinQuick? "yes": "no" ); Abc_Print( -2, "\t-f : toggles filtering matches (useful with unit delay model) [default = %s]\n", pPars->fPinFilter? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Of( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Of_ManSetDefaultPars( Jf_Par_t * pPars ); extern Gia_Man_t * Of_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); char Buffer[200]; Jf_Par_t Pars, * pPars = &Pars; Gia_Man_t * pNew; int c; Of_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDNMQekmpgtvwh" ) ) != 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 2 || pPars->nLutSize > pPars->nLutSizeMax ) { Abc_Print( -1, "LUT size %d is not supported.\n", pPars->nLutSize ); goto usage; } break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } pPars->nCutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCutNum < 1 || pPars->nCutNum > pPars->nCutNumMax ) { Abc_Print( -1, "This number of cuts (%d) is not supported.\n", pPars->nCutNum ); 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; } pPars->nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRounds < 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; } pPars->nRoundsEla = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRoundsEla < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } pPars->nRelaxRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRelaxRatio < 0 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( 1, "Command line switch \"-R\" should be followed by a floating point number.\n" ); return 0; } pPars->nCoarseLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCoarseLimit < 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" ); return 0; } pPars->nAreaTuner = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nAreaTuner < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } pPars->DelayTarget = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayTarget <= 0.0 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } pPars->nDelayLut1 = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nDelayLut1 < 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; } pPars->nDelayLut2 = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nDelayLut2 < 0 ) goto usage; break; case 'Q': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Q\" should be followed by a positive integer.\n" ); goto usage; } pPars->nFastEdges = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFastEdges < 0 ) goto usage; break; case 'e': pPars->fOptEdge ^= 1; break; case 'k': pPars->fCoarsen ^= 1; break; case 'm': pPars->fCutMin ^= 1; break; case 'p': pPars->fPower ^= 1; break; case 'g': pPars->fPureAig ^= 1; break; case 't': pPars->fDoAverage ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } if ( Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Current AIG has mapping. Run \"&st\".\n" ); return 1; } pNew = Of_ManPerformMapping( pAbc->pGia, pPars ); if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Of(): Mapping into LUTs has failed.\n" ); return 1; } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: if ( pPars->DelayTarget == -1 ) sprintf(Buffer, "best possible" ); else sprintf(Buffer, "%d", pPars->DelayTarget ); Abc_Print( -2, "usage: &of [-KCFARLEDNMQ num] [-kmpgtvwh]\n" ); Abc_Print( -2, "\t performs technology mapping of the network\n" ); Abc_Print( -2, "\t-K num : LUT size for the mapping (2 <= K <= %d) [default = %d]\n", pPars->nLutSizeMax, pPars->nLutSize ); Abc_Print( -2, "\t-C num : the max number of priority cuts (1 <= C <= %d) [default = %d]\n", pPars->nCutNumMax, pPars->nCutNum ); Abc_Print( -2, "\t-F num : the number of area flow rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-A num : the number of exact area rounds [default = %d]\n", pPars->nRoundsEla ); Abc_Print( -2, "\t-R num : the delay relaxation ratio (num >= 0) [default = %d]\n", pPars->nRelaxRatio ); Abc_Print( -2, "\t-L num : the fanout limit for coarsening XOR/MUX (num >= 2) [default = %d]\n", pPars->nCoarseLimit ); Abc_Print( -2, "\t-E num : the area/edge tradeoff parameter (0 <= num <= 100) [default = %d]\n", pPars->nAreaTuner ); Abc_Print( -2, "\t-D num : sets the delay constraint for the mapping [default = %s]\n", Buffer ); Abc_Print( -2, "\t-N num : delay of the first LUT [default = %d]\n", pPars->nDelayLut1 ); Abc_Print( -2, "\t-M num : delay of the second LUT [default = %d]\n", pPars->nDelayLut2 ); Abc_Print( -2, "\t-Q num : the number of fast non-routable edges [default = %d]\n", pPars->nFastEdges ); Abc_Print( -2, "\t-e : toggles edge vs node minimization [default = %s]\n", pPars->fOptEdge? "yes": "no" ); Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-p : toggles power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); Abc_Print( -2, "\t-g : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" ); Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Pack( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManLutPacking( Gia_Man_t * p, int nBlock, int DelayRoute, int DelayDir, int fVerbose ); int c, nBlock = 2, DelayRoute = 10, DelayDir = 2, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NRDvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } nBlock = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBlock < 2 ) { Abc_Print( -1, "LUT block size (%d) should be more than 1.\n", nBlock ); goto usage; } break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } DelayRoute = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( DelayRoute <= 0 ) { Abc_Print( -1, "Rounting delay (%d) should be more than 0.\n", DelayRoute); goto usage; } break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); goto usage; } DelayDir = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( DelayDir <= 0 ) { Abc_Print( -1, "Direct delay (%d) should be more than 0.\n", DelayRoute); goto usage; } break; case 'v': fVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" ); return 1; } if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 ) Abc_Print( 0, "Current AIG has mapping into %d-LUTs.\n", Gia_ManLutSizeMax(pAbc->pGia) ); else Gia_ManLutPacking( pAbc->pGia, nBlock, DelayRoute, DelayDir, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &pack [-NRD num] [-vh]\n" ); Abc_Print( -2, "\t performs packing for the LUT mapped network\n" ); Abc_Print( -2, "\t-N num : the number of LUTs in the block [default = %d]\n", nBlock ); Abc_Print( -2, "\t-R num : the routable delay of a LUT [default = %d]\n", DelayRoute ); Abc_Print( -2, "\t-D num : the direct (non-routable) delay of a LUT [default = %d]\n", DelayDir ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Edg_ManAssignEdgeNew( Gia_Man_t * p, int nEdges, int fVerbose ); extern void Seg_ManComputeDelay( Gia_Man_t * pGia, int Delay, int nFanouts, int fTwo, int fVerbose ); extern void Sle_ManExplore( Gia_Man_t * pGia, int nBTLimit, int DelayInit, int fDynamic, int fTwoEdges, int fVerbose ); int c, nBTLimit = 0, DelayMax = 0, nFanouts = 0, nEdges = 1, fReverse = 0, fUsePack = 0, fUseOld = 0, fMapping = 0, fDynamic = 1, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CDFErpomdvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); goto usage; } DelayMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" ); goto usage; } nFanouts = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'E': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-E\" should be followed by a positive integer.\n" ); goto usage; } nEdges = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nEdges != 1 && nEdges != 2 ) { Abc_Print( -1, "Edge limit (%d) should be 1 or 2.\n", nEdges ); goto usage; } break; case 'r': fReverse ^= 1; break; case 'p': fUsePack ^= 1; break; case 'o': fUseOld ^= 1; break; case 'm': fMapping ^= 1; break; case 'd': fDynamic ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } if ( fMapping ) { Sle_ManExplore( pAbc->pGia, nBTLimit, DelayMax, fDynamic, nEdges==2, fVerbose ); return 0; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" ); return 1; } if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 ) { Abc_Print( 0, "Current AIG has mapping into %d-LUTs.\n", Gia_ManLutSizeMax(pAbc->pGia) ); return 0; } if ( fUsePack ) { if ( pAbc->pGia->vPacking == NULL ) { Abc_Print( -1, "Packing information is not present.\n" ); return 0; } Gia_ManConvertPackingToEdges( pAbc->pGia ); return 0; } if ( !fUseOld ) { //Edg_ManAssignEdgeNew( pAbc->pGia, nEdges, fVerbose ); Seg_ManComputeDelay( pAbc->pGia, DelayMax, nFanouts, nEdges==2, fVerbose ); return 0; } if ( pAbc->pGia->pManTime && fReverse ) { Abc_Print( 0, "Reverse computation does not work when boxes are present.\n" ); return 0; } if ( fReverse ) DelayMax = Gia_ManComputeEdgeDelay2( pAbc->pGia ); else DelayMax = Gia_ManComputeEdgeDelay( pAbc->pGia, nEdges == 2 ); //printf( "The number of edges = %d. Delay = %d.\n", Gia_ManEvalEdgeCount(pAbc->pGia), DelayMax ); return 0; usage: Abc_Print( -2, "usage: &edge [-CDFE num] [-rpomdvh]\n" ); Abc_Print( -2, "\t find edge assignment of the LUT-mapped network\n" ); Abc_Print( -2, "\t-C num : the SAT solver conflict limit (0 = unused) [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-D num : the upper bound on delay [default = %d]\n", DelayMax ); Abc_Print( -2, "\t-F num : skip using edge if fanout higher than this [default = %d]\n", nFanouts ); Abc_Print( -2, "\t-E num : the limit on the number of edges (1 <= num <= 2) [default = %d]\n", nEdges ); Abc_Print( -2, "\t-r : toggles using reverse order [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-p : toggles deriving edges from packing [default = %s]\n", fUsePack? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using old algorithm [default = %s]\n", fUseOld? "yes": "no" ); Abc_Print( -2, "\t-m : toggles combining edge assignment with mapping [default = %s]\n", fMapping? "yes": "no" ); Abc_Print( -2, "\t-d : toggles dynamic addition of clauses [default = %s]\n", fDynamic? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9SatLut( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManLutSat( Gia_Man_t * p, int LutSize, int nNumber, int nImproves, int nBTLimit, int DelayMax, int nEdges, int fDelay, int fReverse, int fVerbose, int fVeryVerbose ); int c, LutSize = 0, nNumber = 32, nImproves = 0, nBTLimit = 100, DelayMax = 0, nEdges = 0; int fDelay = 0, fReverse = 0, fVeryVerbose = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NICDQdrwvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } nNumber = atoi(argv[globalUtilOptind]); if ( nNumber > 128 ) { Abc_Print( -1, "The number of AIG nodes should not exceed 128.\n" ); goto usage; } globalUtilOptind++; break; case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); goto usage; } nImproves = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); goto usage; } nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); goto usage; } DelayMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'Q': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Q\" should be followed by a positive integer.\n" ); goto usage; } nEdges = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'd': fDelay ^= 1; break; case 'r': fReverse ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" ); return 1; } LutSize = Gia_ManLutSizeMax(pAbc->pGia); if ( LutSize > 6 ) Abc_Print( 0, "Current AIG is mapped into %d-LUTs (only 6-LUT mapping is currently supported).\n", Gia_ManLutSizeMax(pAbc->pGia) ); else Gia_ManLutSat( pAbc->pGia, LutSize, nNumber, nImproves, nBTLimit, DelayMax, nEdges, fDelay, fReverse, fVerbose, fVeryVerbose ); return 0; usage: Abc_Print( -2, "usage: &satlut [-NICDQ num] [-drwvh]\n" ); Abc_Print( -2, "\t performs SAT-based remapping of the 4-LUT network\n" ); Abc_Print( -2, "\t-N num : the limit on AIG nodes in the window (num <= 128) [default = %d]\n", nNumber ); Abc_Print( -2, "\t-I num : the limit on the number of improved windows [default = %d]\n", nImproves ); Abc_Print( -2, "\t-C num : the limit on the number of conflicts [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-D num : the user-specified required times at the outputs [default = %d]\n", DelayMax ); Abc_Print( -2, "\t-Q num : the maximum number of edges [default = %d]\n", nEdges ); Abc_Print( -2, "\t-d : toggles delay optimization [default = %s]\n", fDelay? "yes": "no" ); Abc_Print( -2, "\t-r : toggles using reverse search [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Unmap( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManTestStruct( Gia_Man_t * p ); int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Struct(): There is no AIG to map.\n" ); return 1; } Vec_IntFreeP( &pAbc->pGia->vMapping ); Vec_IntFreeP( &pAbc->pGia->vPacking ); Vec_IntFreeP( &pAbc->pGia->vCellMapping ); Vec_IntFreeP( &pAbc->pGia->vEdge1 ); Vec_IntFreeP( &pAbc->pGia->vEdge2 ); return 0; usage: Abc_Print( -2, "usage: &unmap [-vh]\n" ); Abc_Print( -2, "\t removes mapping from the current network\n" ); 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_CommandAbc9Struct( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ManTestStruct( Gia_Man_t * p ); int c, 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 ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Struct(): There is no AIG to map.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Struct(): Mapping of the AIG is not defined.\n" ); return 1; } if ( Gia_ManLutSizeMax(pAbc->pGia) >= 8 ) { Abc_Print( -1, "Abc_CommandAbc9Struct(): Can only handle nodes with less than 8 inputs.\n" ); return 1; } Gia_ManTestStruct( pAbc->pGia ); return 0; usage: Abc_Print( -2, "usage: &struct [-vh]\n" ); Abc_Print( -2, "\t checks decomposition structures of the current mapping\n" ); 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_CommandAbc9Trace( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; 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 ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Speedup(): There is no AIG to map.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Speedup(): Mapping of the AIG is not defined.\n" ); return 1; } pAbc->pGia->pLutLib = fUseLutLib ? pAbc->pLibLut : NULL; Gia_ManDelayTraceLutPrint( pAbc->pGia, 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_CommandAbc9Speedup( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int fUseLutLib; int Percentage; int Degree; int fVerbose; int c, fVeryVerbose; // 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 ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Speedup(): There is no AIG to map.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Speedup(): Mapping of the AIG is not defined.\n" ); return 1; } pAbc->pGia->pLutLib = fUseLutLib ? pAbc->pLibLut : NULL; pTemp = Gia_ManSpeedup( pAbc->pGia, Percentage, Degree, fVerbose, fVeryVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &speedup [-P num] [-N num] [-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_CommandAbc9Era( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Gia_Man_t * pTemp = NULL; int c, fVerbose = 0; int fUseCubes = 1; int fDumpFile = 0; int fMiter = 0; int nStatesMax = 1000000000; extern int Gia_ManCollectReachable( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fDumpFile, int fVerbose ); extern int Gia_ManArePerform( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fVerbose ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Smcdvh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" ); goto usage; } nStatesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nStatesMax < 0 ) goto usage; break; case 'm': fMiter ^= 1; break; case 'c': fUseCubes ^= 1; break; case 'd': fDumpFile ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Era(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9Era(): The network is combinational.\n" ); return 1; } if ( !fUseCubes && Gia_ManPiNum(pAbc->pGia) > 12 ) { Abc_Print( -1, "Abc_CommandAbc9Era(): The number of PIs (%d) should be no more than 12 when cubes are not used.\n", Gia_ManPiNum(pAbc->pGia) ); return 1; } if ( fUseCubes && !fDumpFile ) pAbc->Status = Gia_ManArePerform( pAbc->pGia, nStatesMax, fMiter, fVerbose ); else pAbc->Status = Gia_ManCollectReachable( pAbc->pGia, nStatesMax, fMiter, fDumpFile, fVerbose ); Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &era [-S num] [-mcdvh]\n" ); Abc_Print( -2, "\t explicit reachability analysis for small sequential AIGs\n" ); Abc_Print( -2, "\t-S num : the max number of states (num > 0) [default = %d]\n", nStatesMax ); Abc_Print( -2, "\t-m : stop when the miter output is 1 [default = %s]\n", fMiter? "yes": "no" ); Abc_Print( -2, "\t-c : use state cubes instead of state minterms [default = %s]\n", fUseCubes? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dumping STG into a file [default = %s]\n", fDumpFile? "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_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; Dch_Pars_t Pars, * pPars = &Pars; int c; // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfrvh" ) ) != 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 'f': pPars->fLightSynth ^= 1; break; case 'r': pPars->fSkipRedSupp ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Dch(): There is no AIG.\n" ); return 1; } if ( Gia_ManBufNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Dch(): This command does not work with barrier buffers.\n" ); return 1; } pTemp = Gia_ManPerformDch( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &dch [-WCS num] [-sptfrvh]\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-f : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); Abc_Print( -2, "\t-r : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" ); Abc_Print( -2, "\t-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_CommandAbc9Rpm( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, nCutMax = 16; int fUseOldAlgo = 0; int fVerbose = 0; int fVeryVerbose = 0; 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; } nCutMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutMax < 0 ) goto usage; break; case 'a': fUseOldAlgo ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Rpm(): There is no AIG.\n" ); return 0; } if ( fUseOldAlgo ) pTemp = Abs_RpmPerformOld( pAbc->pGia, fVerbose ); else pTemp = Abs_RpmPerform( pAbc->pGia, nCutMax, fVerbose, fVeryVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &rpm [-C num] [-avwh]\n" ); Abc_Print( -2, "\t performs structural reparametrization\n" ); Abc_Print( -2, "\t-C num : max cut size for testing range equivalence [default = %d]\n", nCutMax ); Abc_Print( -2, "\t-a : toggle using old algorithm [default = %s]\n", fUseOldAlgo? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9BackReach( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManCofTest( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose ); Gia_Man_t * pTemp = NULL; int c, fVerbose = 0; int nFrameMax = 1000000; int nConfMax = 1000000; int nTimeMax = 10; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCTvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFrameMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFrameMax < 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; } nConfMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfMax < 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; } nTimeMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeMax < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9BackReach(): There is no AIG.\n" ); return 1; } if ( Gia_ManPoNum(pAbc->pGia) != 1 ) { Abc_Print( -1, "Abc_CommandAbc9BackReach(): The number of POs is different from 1.\n" ); return 1; } pTemp = Gia_ManCofTest( pAbc->pGia, nFrameMax, nConfMax, nTimeMax, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &back_reach [-FCT ] [-vh]\n" ); Abc_Print( -2, "\t performs backward reachability by circuit cofactoring\n" ); Abc_Print( -2, "\t-F num : the limit on the depth of induction [default = %d]\n", nFrameMax ); Abc_Print( -2, "\t-C num : the conflict limit at a node during induction [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-T num : the timeout for property directed reachability [default = %d]\n", nTimeMax ); 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_CommandAbc9Posplit( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose ); Aig_Man_t * pMan, * pAux; Gia_Man_t * pTemp = NULL; int c, nVars = 5, 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; } nVars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVars < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Posplit(): There is no AIG.\n" ); return 1; } pMan = Gia_ManToAigSimple( pAbc->pGia ); pMan = Aig_ManSplit( pAux = pMan, nVars, fVerbose ); Aig_ManStop( pAux ); if ( pMan != NULL ) { pTemp = Gia_ManFromAigSimple( pMan ); Aig_ManStop( pMan ); Abc_FrameUpdateGia( pAbc, pTemp ); } return 0; usage: Abc_Print( -2, "usage: &posplit [-N num] [-vh]\n" ); Abc_Print( -2, "\t cofactors the property output w.r.t. a support subset\n" ); Abc_Print( -2, "\t (the OR of new PO functions is equal to the original property)\n" ); Abc_Print( -2, "\t-N num : the number of random cofactoring variables [default = %d]\n", nVars ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9ReachM( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Gia_ParLlb_t Pars, * pPars = &Pars; char * pLogFileName = NULL; int c; extern int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ); // set defaults Llb_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "TBFCHSLripcsyzvwh" ) ) != 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 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nClusterMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nClusterMax < 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->nHintDepth = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nHintDepth < 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->HintFirst = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->HintFirst < 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': pPars->fReorder ^= 1; break; case 'i': pPars->fIndConstr ^= 1; break; case 'p': pPars->fUsePivots ^= 1; break; case 'c': pPars->fCluster ^= 1; break; case 's': pPars->fSchedule ^= 1; break; case 'y': pPars->fSkipOutCheck ^= 1; break; case 'z': pPars->fSkipReach ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9ReachM(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9ReachM(): The current AIG has no latches.\n" ); return 0; } if ( Gia_ManObjNum(pAbc->pGia) >= (1<<16) ) { Abc_Print( -1, "Abc_CommandAbc9ReachM(): Currently cannot handle AIGs with more than %d objects.\n", (1<<16) ); return 0; } pAbc->Status = Llb_ManModelCheckGia( pAbc->pGia, pPars ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&reachm" ); return 0; usage: Abc_Print( -2, "usage: &reachm [-TBFCHS num] [-L file] [-ripcsyzvwh]\n" ); Abc_Print( -2, "\t model checking via BDD-based reachability (dependence-matrix-based)\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-C num : max number of variables in a cluster [default = %d]\n", pPars->nClusterMax ); Abc_Print( -2, "\t-H num : max number of hints to use [default = %d]\n", pPars->nHintDepth ); Abc_Print( -2, "\t-S num : the number of the starting hint [default = %d]\n", pPars->HintFirst ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-r : enable dynamic BDD variable reordering [default = %s]\n", pPars->fReorder? "yes": "no" ); Abc_Print( -2, "\t-i : enable extraction of inductive constraints [default = %s]\n", pPars->fIndConstr? "yes": "no" ); Abc_Print( -2, "\t-p : enable partitions for internal cut-points [default = %s]\n", pPars->fUsePivots? "yes": "no" ); Abc_Print( -2, "\t-c : enable clustering of partitions [default = %s]\n", pPars->fCluster? "yes": "no" ); Abc_Print( -2, "\t-s : enable scheduling of clusters [default = %s]\n", pPars->fSchedule? "yes": "no" ); Abc_Print( -2, "\t-y : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" ); Abc_Print( -2, "\t-z : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : prints dependency matrix [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_CommandAbc9ReachP( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Gia_ParLlb_t Pars, * pPars = &Pars; Aig_Man_t * pMan; char * pLogFileName = NULL; int c; extern int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); // set defaults Llb_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NBFTLrbyzdvwh" ) ) != 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->nPartValue = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nPartValue < 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 '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 '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': pPars->fReorder ^= 1; break; case 'b': pPars->fBackward ^= 1; break; case 'y': pPars->fSkipOutCheck ^= 1; break; case 'z': pPars->fSkipReach ^= 1; break; case 'd': pPars->fDumpReached ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9ReachP(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9ReachP(): The current AIG has no latches.\n" ); return 0; } if ( Gia_ManObjNum(pAbc->pGia) >= (1<<16) ) { Abc_Print( -1, "Abc_CommandAbc9ReachP(): Currently cannot handle AIGs with more than %d objects.\n", (1<<16) ); return 0; } pMan = Gia_ManToAigSimple( pAbc->pGia ); pAbc->Status = Llb_ManReachMinCut( pMan, pPars ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pMan->pSeqModel ); if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&reachp" ); Aig_ManStop( pMan ); return 0; usage: Abc_Print( -2, "usage: &reachp [-NFT num] [-L file] [-rbyzdvwh]\n" ); Abc_Print( -2, "\t model checking via BDD-based reachability (partitioning-based)\n" ); Abc_Print( -2, "\t-N num : partitioning value (MinVol=nANDs/N/2; MaxVol=nANDs/N) [default = %d]\n", pPars->nPartValue ); // Abc_Print( -2, "\t-B num : the BDD node increase when hints kick in [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-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-r : enable additional BDD var reordering before image [default = %s]\n", pPars->fReorder? "yes": "no" ); Abc_Print( -2, "\t-b : perform backward reachability analysis [default = %s]\n", pPars->fBackward? "yes": "no" ); Abc_Print( -2, "\t-y : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" ); Abc_Print( -2, "\t-z : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" ); Abc_Print( -2, "\t-d : dump BDD of reached states into file \"reached.blif\" [default = %s]\n", pPars->fDumpReached? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : prints additional information [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_CommandAbc9ReachN( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Gia_ParLlb_t Pars, * pPars = &Pars; Aig_Man_t * pMan; char * pLogFileName = NULL; int c; extern int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); // set defaults Llb_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "BFTLryzvwh" ) ) != EOF ) { switch ( c ) { 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 '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 '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': pPars->fReorder ^= 1; break; case 'y': pPars->fSkipOutCheck ^= 1; break; case 'z': pPars->fSkipReach ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9ReachN(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9ReachN(): The current AIG has no latches.\n" ); return 0; } if ( Gia_ManObjNum(pAbc->pGia) >= (1<<16) ) { Abc_Print( -1, "Abc_CommandAbc9ReachN(): Currently cannot handle AIGs with more than %d objects.\n", (1<<16) ); return 0; } pMan = Gia_ManToAigSimple( pAbc->pGia ); pAbc->Status = Llb_NonlinCoreReach( pMan, pPars ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pMan->pSeqModel ); if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&reachn" ); Aig_ManStop( pMan ); return 0; usage: Abc_Print( -2, "usage: &reachn [-BFT num] [-L file] [-ryzvh]\n" ); Abc_Print( -2, "\t model checking via BDD-based reachability (non-linear-QS-based)\n" ); Abc_Print( -2, "\t-B num : the BDD node increase when hints kick in [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-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-r : enable additional BDD var reordering before image [default = %s]\n", pPars->fReorder? "yes": "no" ); Abc_Print( -2, "\t-y : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" ); Abc_Print( -2, "\t-z : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); // Abc_Print( -2, "\t-w : prints additional information [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_CommandAbc9ReachY( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Gia_ParLlb_t Pars, * pPars = &Pars; Aig_Man_t * pMan; char * pLogFileName = NULL; int c; // set defaults Llb_ManSetDefaultParams( pPars ); pPars->fCluster = 0; pPars->fReorder = 0; pPars->nBddMax = 100; pPars->nClusterMax = 500; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "BCFTLbcryzvwh" ) ) != EOF ) { switch ( c ) { 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 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nClusterMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nClusterMax < 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 '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 '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 'b': pPars->fBackward ^= 1; break; case 'c': pPars->fCluster ^= 1; break; case 'r': pPars->fReorder ^= 1; break; case 'y': pPars->fSkipOutCheck ^= 1; break; case 'z': pPars->fSkipReach ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9ReachN(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9ReachN(): The current AIG has no latches.\n" ); return 0; } /* if ( Gia_ManObjNum(pAbc->pGia) >= (1<<16) ) { Abc_Print( -1, "Abc_CommandAbc9ReachN(): Currently cannot handle AIGs with more than %d objects.\n", (1<<16) ); return 0; } */ pMan = Gia_ManToAigSimple( pAbc->pGia ); pAbc->Status = Llb_Nonlin4CoreReach( pMan, pPars ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pMan->pSeqModel ); if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "&reachy" ); Aig_ManStop( pMan ); return 0; usage: Abc_Print( -2, "usage: &reachy [-BCFT num] [-L file] [-bcryzvh]\n" ); Abc_Print( -2, "\t model checking via BDD-based reachability (non-linear-QS-based)\n" ); Abc_Print( -2, "\t-B num : the max BDD size to introduce cut points [default = %d]\n", pPars->nBddMax ); Abc_Print( -2, "\t-C num : the max BDD size to reparameterize/cluster [default = %d]\n", pPars->nClusterMax ); Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax ); Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-b : enable using backward enumeration [default = %s]\n", pPars->fBackward? "yes": "no" ); Abc_Print( -2, "\t-c : enable reparametrization clustering [default = %s]\n", pPars->fCluster? "yes": "no" ); Abc_Print( -2, "\t-r : enable additional BDD var reordering before image [default = %s]\n", pPars->fReorder? "yes": "no" ); Abc_Print( -2, "\t-y : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" ); Abc_Print( -2, "\t-z : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); // Abc_Print( -2, "\t-w : prints additional information [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_CommandAbc9Undo( 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->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Undo(): There is no design.\n" ); return 1; } if ( pAbc->pGia2 == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Undo(): There is no previously saved network.\n" ); return 1; } Gia_ManStop( pAbc->pGia ); pAbc->pGia = pAbc->pGia2; pAbc->pGia2 = NULL; return 0; usage: Abc_Print( -2, "usage: &undo [-h]\n" ); Abc_Print( -2, "\t reverses the previous AIG transformation\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Iso( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pAig; Vec_Ptr_t * vPosEquivs; // Vec_Ptr_t * vPiPerms; int c, fNewAlgo = 1, fEstimate = 0, fBetterQual = 0, fDualOut = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "neqdvwh" ) ) != EOF ) { switch ( c ) { case 'n': fNewAlgo ^= 1; break; case 'e': fEstimate ^= 1; break; case 'q': fBetterQual ^= 1; break; case 'd': fDualOut ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Iso(): There is no AIG.\n" ); return 1; } if ( Gia_ManPoNum(pAbc->pGia) == 1 ) { Abc_Print( -1, "Abc_CommandAbc9Iso(): The AIG has only one PO. Isomorphism detection is not performed.\n" ); return 1; } if ( fNewAlgo ) pAig = Gia_ManIsoReduce2( pAbc->pGia, &vPosEquivs, NULL, fEstimate, fBetterQual, fDualOut, fVerbose, fVeryVerbose ); else pAig = Gia_ManIsoReduce( pAbc->pGia, &vPosEquivs, NULL, fEstimate, fDualOut, fVerbose, fVeryVerbose ); // pAig = Gia_ManIsoReduce( pAbc->pGia, &vPosEquivs, &vPiPerms, 0, fDualOut, fVerbose, fVeryVerbose ); // Vec_VecFree( (Vec_Vec_t *)vPiPerms ); if ( pAig == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Iso(): Transformation has failed.\n" ); return 1; } // update the internal storage of PO equivalences Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs ); // update the AIG Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: Abc_Print( -2, "usage: &iso [-neqdvwh]\n" ); Abc_Print( -2, "\t removes POs with isomorphic sequential COI\n" ); Abc_Print( -2, "\t-n : toggle using new fast algorithm [default = %s]\n", fNewAlgo? "yes": "no" ); Abc_Print( -2, "\t-e : toggle computing lower bound on equivalence classes [default = %s]\n", fEstimate? "yes": "no" ); Abc_Print( -2, "\t-q : toggle improving quality at the expense of runtime [default = %s]\n", fBetterQual? "yes": "no" ); Abc_Print( -2, "\t-d : toggle treating the current AIG as a dual-output miter [default = %s]\n", fDualOut? "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_CommandAbc9IsoNpn( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManIsoNpnReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ); Gia_Man_t * pAig; Vec_Ptr_t * vPosEquivs; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9IsoNpn(): There is no AIG.\n" ); return 1; } if ( Gia_ManPoNum(pAbc->pGia) == 1 ) { Abc_Print( -1, "Abc_CommandAbc9IsoNpn(): The AIG has only one PO. Isomorphism detection is not performed.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9IsoNpn(): ISO-NPN does not work with sequential AIGs.\n" ); return 1; } pAig = Gia_ManIsoNpnReduce( pAbc->pGia, &vPosEquivs, fVerbose ); if ( pAig == NULL ) { Abc_Print( -1, "Abc_CommandAbc9IsoNpn(): Transformation has failed.\n" ); return 1; } // update the internal storage of PO equivalences Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs ); // update the AIG Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: Abc_Print( -2, "usage: &isonpn [-vh]\n" ); Abc_Print( -2, "\t removes POs with functionally isomorphic combinational COI\n" ); Abc_Print( -2, "\t (currently ignores POs whose structural support is more than 16)\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_CommandAbc9IsoSt( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManIsoStrashReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ); Gia_Man_t * pAig; Vec_Ptr_t * vPosEquivs; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9IsoSt(): There is no AIG.\n" ); return 1; } if ( Gia_ManPoNum(pAbc->pGia) == 1 ) { Abc_Print( -1, "Abc_CommandAbc9IsoSt(): The AIG has only one PO. Isomorphism detection is not performed.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9IsoSt(): ISO-ST does not work with sequential AIGs.\n" ); return 1; } pAig = Gia_ManIsoStrashReduce( pAbc->pGia, &vPosEquivs, fVerbose ); if ( pAig == NULL ) { Abc_Print( -1, "Abc_CommandAbc9IsoSt(): Transformation has failed.\n" ); return 1; } // update the internal storage of PO equivalences Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs ); // update the AIG Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: Abc_Print( -2, "usage: &isost [-vh]\n" ); Abc_Print( -2, "\t removes POs with functionally isomorphic combinational COI\n" ); Abc_Print( -2, "\t (this command relies exclusively on structural hashing)\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_CommandAbc9CexInfo( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ); int c, fDualOut = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF ) { switch ( c ) { case 'd': fDualOut ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9CexInfo(): There is no AIG.\n" ); return 1; } if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Abc_CommandAbc9CexInfo(): There is no CEX.\n" ); return 1; } Bmc_CexTest( pAbc->pGia, pAbc->pCex, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &cexinfo [-vh]\n" ); Abc_Print( -2, "\t prints information about the current counter-example\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_CommandAbc9Cycle( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, nFrames = 10, fUseCex = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fcvh" ) ) != 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 'c': fUseCex ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Cycle(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManDupCycled( pAbc->pGia, fUseCex ? pAbc->pCex : NULL, nFrames ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &cycle [-F num] [-cvh]\n" ); Abc_Print( -2, "\t cycles sequential circuit for the given number of timeframes\n" ); Abc_Print( -2, "\t to derive a new initial state (which may be on the envelope)\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); Abc_Print( -2, "\t-c : toggle using PI values from the current CEX [default = %s]\n", fUseCex? "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_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; Vec_Int_t * vPos; int c, iOutNum = -1, nOutRange = 1, iPartNum = -1, nLevelMax = 0, nTimeWindow = 0, fUseAllCis = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ORPLWavh" ) ) != EOF ) { switch ( c ) { case 'O': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } iOutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iOutNum < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } nOutRange = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nOutRange < 0 ) goto usage; break; case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } iPartNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iPartNum < 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 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nTimeWindow = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeWindow < 0 ) goto usage; break; case 'a': fUseAllCis ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Cone(): There is no AIG.\n" ); return 1; } if ( nLevelMax || nTimeWindow ) { if ( nLevelMax && nTimeWindow ) { Abc_Print( -1, "Abc_CommandAbc9Cone(): Parameters -L (max level) and -W (timing window) cannot be specified at the same time.\n" ); return 1; } else { pTemp = Gia_ManExtractWindow( pAbc->pGia, nLevelMax, nTimeWindow, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; } } if ( iPartNum >= 0 ) { Vec_Int_t * vClass; Vec_Vec_t * vClasses = (Vec_Vec_t *)pAbc->vPoEquivs; if ( vClasses == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Cone(): Partitions are not defined.\n" ); return 1; } if ( iPartNum >= Vec_VecSize(vClasses) ) { Abc_Print( -1, "Abc_CommandAbc9Cone(): Partition index exceed the array size.\n" ); return 1; } vClass = Vec_VecEntryInt( vClasses, iPartNum ); pTemp = Gia_ManDupCones( pAbc->pGia, Vec_IntArray(vClass), Vec_IntSize(vClass), !fUseAllCis ); if ( pTemp ) Abc_FrameUpdateGia( pAbc, pTemp ); return 0; } if ( iOutNum < 0 || iOutNum + nOutRange > Gia_ManPoNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Cone(): Range of outputs to extract is incorrect.\n" ); return 1; } vPos = Vec_IntStartRange( iOutNum, nOutRange ); pTemp = Gia_ManDupCones( pAbc->pGia, Vec_IntArray(vPos), nOutRange, !fUseAllCis ); Vec_IntFree( vPos ); if ( pTemp ) Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &cone [-ORPLW num] [-avh]\n" ); Abc_Print( -2, "\t extracting multi-output sequential logic cones\n" ); Abc_Print( -2, "\t-O num : the index of first PO to extract [default = %d]\n", iOutNum ); Abc_Print( -2, "\t-R num : (optional) the number of outputs to extract [default = %d]\n", nOutRange ); Abc_Print( -2, "\t-P num : (optional) the partition number to extract [default = %d]\n", iPartNum ); Abc_Print( -2, "\t-L num : (optional) extract cones with higher level [default = %d]\n", nLevelMax ); Abc_Print( -2, "\t-W num : (optional) extract cones falling into this window [default = %d]\n", nTimeWindow ); Abc_Print( -2, "\t-a : toggle keeping all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); Abc_Print( -2, "\t-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_CommandAbc9Slice( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, nSuppSize = 6, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Svh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } nSuppSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSuppSize < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Slice(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManDupSliced( pAbc->pGia, nSuppSize ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &slice [-S num] [-vh]\n" ); Abc_Print( -2, "\t cuts the lower part of the AIG with nodes using their support\n" ); Abc_Print( -2, "\t-S num : the largest support size to keep in the slide [default = %d]\n", nSuppSize ); 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_CommandAbc9PoPart( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManFindPoPartition( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ); Gia_Man_t * pTemp; Vec_Ptr_t * vPosEquivs = NULL; int c, SelectShift = 0, fOnlyCis = 0, fSetLargest = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Simvh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } SelectShift = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( SelectShift < 0 ) goto usage; break; case 'i': fOnlyCis ^= 1; break; case 'm': fSetLargest ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9PoPart(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManFindPoPartition( pAbc->pGia, SelectShift, fOnlyCis, fSetLargest, fVerbose, &vPosEquivs ); if ( pTemp ) Abc_FrameUpdateGia( pAbc, pTemp ); Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs ); return 0; usage: Abc_Print( -2, "usage: &popart [-S num] [-imvh]\n" ); Abc_Print( -2, "\t partitioning of POs into equivalence classes\n" ); Abc_Print( -2, "\t-S num : random seed to select the set of pivot nodes [default = %d]\n", SelectShift ); Abc_Print( -2, "\t : (if the seed is 0, the nodes with max fanout counts are used)\n" ); Abc_Print( -2, "\t-i : toggle allowing only CIs to be the pivots [default = %s]\n", fOnlyCis? "yes": "no" ); Abc_Print( -2, "\t-m : toggle using the largest part as the current network [default = %s]\n", fSetLargest? "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_CommandAbc9PoPart2( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern 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 ); Gia_Man_t * pTemp = NULL; Vec_Ptr_t * vPosEquivs = NULL; int c, iStartNum = 0, nDelta = 10, nOutsMin = 100, nOutsMax = 1000, fSetLargest = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "SDLUmvh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } iStartNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iStartNum < 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; } nDelta = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDelta < 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; } nOutsMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nOutsMin < 0 ) goto usage; break; case 'U': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-U\" should be followed by an integer.\n" ); goto usage; } nOutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nOutsMax < 0 ) goto usage; break; case 'm': fSetLargest ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9PoPart(): There is no AIG.\n" ); return 1; } pTemp = Gia_ManFindPoPartition2( pAbc->pGia, iStartNum, nDelta, nOutsMin, nOutsMax, fSetLargest, fVerbose, &vPosEquivs ); if ( pTemp ) Abc_FrameUpdateGia( pAbc, pTemp ); Abc_FrameReplacePoEquivs( pAbc, &vPosEquivs ); return 0; usage: Abc_Print( -2, "usage: &popart2 [-SDLU num] [-mvh]\n" ); Abc_Print( -2, "\t extracting multi-output sequential logic cones\n" ); Abc_Print( -2, "\t-S num : the index of the PO to start the cluster [default = %d]\n", iStartNum ); Abc_Print( -2, "\t-D num : the max increase in flop count after adding one PO [default = %d]\n", nDelta ); Abc_Print( -2, "\t-L num : the minimum number of POs in a cluster [default = %d]\n", nOutsMin ); Abc_Print( -2, "\t-U num : the maximum number of POs in a cluster [default = %d]\n", nOutsMax ); Abc_Print( -2, "\t-m : toggle selecting the largest cluster [default = %s]\n", fSetLargest? "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_CommandAbc9GroupProve( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Int_t * Gia_ManGroupProve( Gia_Man_t * p, char * pCommLine, int nGroupSize, int fVerbose ); Vec_Int_t * vStatus; char * pCommLine = NULL; int c, nGroupSize = 1, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "GSvh" ) ) != EOF ) { switch ( c ) { case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); goto usage; } nGroupSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nGroupSize <= 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; } pCommLine = argv[globalUtilOptind]; globalUtilOptind++; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9GroupProve(): There is no AIG.\n" ); return 1; } if ( pCommLine == NULL ) { Abc_Print( -1, "Abc_CommandAbc9GroupProve(): Command line is not given.\n" ); return 1; } vStatus = Gia_ManGroupProve( pAbc->pGia, pCommLine, nGroupSize, fVerbose ); Vec_IntFree( vStatus ); return 0; usage: Abc_Print( -2, "usage: &gprove [-GS num] [-vh]\n" ); Abc_Print( -2, "\t proves multi-output testcase by splitting outputs into groups\n" ); Abc_Print( -2, "\t (currently, group size more than one works only for \"bmc3\" and \"pdr\")\n" ); Abc_Print( -2, "\t-G num : the size of one group [default = %d]\n", nGroupSize ); Abc_Print( -2, "\t-S str : the command line to be executed for each group [default = %s]\n", pCommLine ? pCommLine : "none" ); 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_CommandAbc9MultiProve( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Gia_ManMultiProve( Gia_Man_t * p, Bmc_MulPar_t * pPars ); Vec_Int_t * vStatuses; int c; Bmc_MulPar_t Pars, * pPars = &Pars; memset( pPars, 0, sizeof(Bmc_MulPar_t) ); pPars->TimeOutGlo = 30; pPars->TimeOutLoc = 2; pPars->TimeOutInc = 100; pPars->TimeOutGap = 0; pPars->TimePerOut = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "TLMGHsdvwh" ) ) != 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->TimeOutGlo = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOutGlo < 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->TimeOutLoc = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOutLoc <= 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->TimeOutInc = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOutInc <= 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; } pPars->TimeOutGap = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOutGap <= 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->TimePerOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimePerOut <= 0 ) goto usage; break; case 's': pPars->fUseSyn ^= 1; break; case 'd': pPars->fDumpFinal ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9MultiProve(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9MultiProve(): The problem is combinational.\n" ); return 1; } pAbc->Status = Gia_ManMultiProve( pAbc->pGia, pPars ); vStatuses = Abc_FrameDeriveStatusArray( pAbc->pGia->vSeqModelVec ); Abc_FrameReplacePoStatuses( pAbc, &vStatuses ); Abc_FrameReplaceCexVec( pAbc, &pAbc->pGia->vSeqModelVec ); return 0; usage: Abc_Print( -2, "usage: &mprove [-TLMGH num] [-sdvwh]\n" ); Abc_Print( -2, "\t proves multi-output testcase by applying several engines\n" ); Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n", pPars->TimeOutGlo ); Abc_Print( -2, "\t-L num : approximate local runtime limit in seconds [default = %d]\n", pPars->TimeOutLoc ); Abc_Print( -2, "\t-M num : percentage of local runtime limit increase [default = %d]\n", pPars->TimeOutInc ); Abc_Print( -2, "\t-G num : approximate gap runtime limit in seconds [default = %d]\n", pPars->TimeOutGap ); Abc_Print( -2, "\t-H num : timeout per output in miliseconds [default = %d]\n", pPars->TimePerOut ); Abc_Print( -2, "\t-s : toggle using combinational synthesis [default = %s]\n", pPars->fUseSyn? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dumping invariant into a file [default = %s]\n", pPars->fDumpFinal? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing additional verbose information [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_CommandAbc9SplitProve( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Cec_GiaSplitTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose, int fSilent ); int c, nProcs = 1, nTimeOut = 10, nIterMax = 0, LookAhead = 1, fVerbose = 0, fVeryVerbose = 0, fSilent = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PTILsvwh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); goto usage; } nProcs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nProcs <= 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); goto usage; } nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeOut <= 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; } nIterMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nIterMax < 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; } LookAhead = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( LookAhead <= 0 || LookAhead > 100 ) { Abc_Print( -1, "Look-ahead value (\"-L \") should be between 1 and 100.\n", LookAhead ); goto usage; } break; case 's': fSilent ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SplitProve(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) > 0 ) { Abc_Print( -1, "Abc_CommandAbc9SplitProve(): The problem is sequential.\n" ); return 1; } pAbc->Status = Cec_GiaSplitTest( pAbc->pGia, nProcs, nTimeOut, nIterMax, LookAhead, fVerbose, fVeryVerbose, fSilent ); pAbc->pCex = pAbc->pGia->pCexComb; pAbc->pGia->pCexComb = NULL; return 0; usage: Abc_Print( -2, "usage: &splitprove [-PTIL num] [-svwh]\n" ); Abc_Print( -2, "\t proves CEC problem by case-splitting\n" ); Abc_Print( -2, "\t-P num : the number of concurrent processes [default = %d]\n", nProcs ); Abc_Print( -2, "\t-T num : runtime limit in seconds per subproblem [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-I num : the max number of iterations (0 = infinity) [default = %d]\n", nIterMax ); Abc_Print( -2, "\t-L num : maximum look-ahead during cofactoring [default = %d]\n", LookAhead ); Abc_Print( -2, "\t-s : enable silent computation (no reporting) [default = %s]\n", fSilent? "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_CommandAbc9Bmc( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; Bmc_AndPar_t Pars, * pPars = &Pars; memset( pPars, 0, sizeof(Bmc_AndPar_t) ); pPars->nStart = 0; // starting timeframe pPars->nFramesMax = 0; // maximum number of timeframes pPars->nFramesAdd = 50; // the number of additional frames pPars->nConfLimit = 0; // maximum number of conflicts at a node pPars->nTimeOut = 0; // timeout in seconds pPars->nLutSize = 6; // max LUT size for CNF computation pPars->fLoadCnf = 0; // dynamic CNF loading pPars->fDumpFrames = 0; // dump unrolled timeframes pPars->fUseSynth = 0; // use synthesis pPars->fUseOldCnf = 0; // use old CNF construction pPars->fVerbose = 0; // verbose pPars->fVeryVerbose = 0; // very verbose pPars->fNotVerbose = 0; // skip line-by-line print-out pPars->iFrame = 0; // explored up to this frame pPars->nFailOuts = 0; // the number of failed outputs pPars->nDropOuts = 0; // the number of dropped outputs Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "SFATKdscvwh" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } pPars->nStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nStart < 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->nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesMax < 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; } pPars->nFramesAdd = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesAdd < 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->nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOut < 0 ) goto usage; break; case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 0 ) goto usage; break; case 'd': pPars->fDumpFrames ^= 1; break; case 's': pPars->fUseSynth ^= 1; break; case 'c': pPars->fUseOldCnf ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Bmc(): There is no AIG.\n" ); return 0; } pAbc->Status = Gia_ManBmcPerform( pAbc->pGia, pPars ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &bmc [-SFATK num] [-dscvwh]\n" ); Abc_Print( -2, "\t performs bounded model checking\n" ); Abc_Print( -2, "\t-S num : the starting timeframe [default = %d]\n", pPars->nStart ); Abc_Print( -2, "\t-F num : the maximum number of timeframes [default = %d]\n", pPars->nFramesMax ); Abc_Print( -2, "\t-A num : the number of additional frames to unroll [default = %d]\n", pPars->nFramesAdd ); Abc_Print( -2, "\t-T num : approximate timeout in seconds [default = %d]\n", pPars->nTimeOut ); Abc_Print( -2, "\t-K num : the maximum cut size for CNF computation [default = %d]\n", pPars->nLutSize ); Abc_Print( -2, "\t-d : toggle dumping unfolded timeframes [default = %s]\n", pPars->fDumpFrames? "yes": "no" ); Abc_Print( -2, "\t-s : toggle synthesizing unrolled timeframes [default = %s]\n", pPars->fUseSynth? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using old CNF computation [default = %s]\n", pPars->fUseOldCnf? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing information about unfolding [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_CommandAbc9ChainBmc( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Bmc_ChainTest( Gia_Man_t * p, int nFrameMax, int nConfMax, int fVerbose, int fVeryVerbose, Vec_Ptr_t ** pvCexes ); Vec_Ptr_t * vCexes = NULL; int nFrameMax = 200; int nConfMax = 0; int fVerbose = 0; int fVeryVerbose = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FCvwh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFrameMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFrameMax < 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; } nConfMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfMax < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9ChainBmc(): There is no AIG.\n" ); return 0; } if ( !Gia_ManRegNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9ChainBmc(): The AIG is combinational.\n" ); return 0; } Bmc_ChainTest( pAbc->pGia, nFrameMax, nConfMax, fVerbose, fVeryVerbose, &vCexes ); if ( vCexes ) Vec_PtrFreeFree( vCexes ); //pAbc->Status = ...; //pAbc->nFrames = pPars->iFrame; //Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &chainbmc [-FC ] [-vwh]\n" ); Abc_Print( -2, "\t runs a specialized flavor of BMC\n" ); Abc_Print( -2, "\t-F : the max number of timeframes (0 = unused) [default = %d]\n", nFrameMax ); Abc_Print( -2, "\t-C : the max number of conflicts (0 = unused) [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing even more 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_CommandAbc9BCore( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; Bmc_BCorePar_t Pars, * pPars = &Pars; memset( pPars, 0, sizeof(Bmc_BCorePar_t) ); pPars->iFrame = 10; // timeframe pPars->iOutput = 0; // property output pPars->nTimeOut = 0; // timeout in seconds pPars->pFilePivots = NULL; // file name with AIG IDs of pivot objects pPars->pFileProof = NULL; // file name to write the resulting proof pPars->fVerbose = 0; // verbose output Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FOTVvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->iFrame = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->iFrame < 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->iOutput = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->iOutput < 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->nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOut < 0 ) goto usage; break; case 'V': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-V\" should be followed by a file name.\n" ); goto usage; } pPars->pFilePivots = argv[globalUtilOptind]; globalUtilOptind++; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9BCore(): There is no AIG.\n" ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9BCore(): AIG has no registers.\n" ); return 0; } // get the file name if ( pPars->pFilePivots != NULL ) { FILE * pFile; pFile = fopen( pPars->pFilePivots, "r" ); if ( pFile == NULL ) { Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" with pivot node IDs.\n", pPars->pFilePivots ); return 0; } fclose( pFile ); } // get the file name if ( argc == globalUtilOptind + 1 ) { FILE * pFile; pPars->pFileProof = argv[globalUtilOptind]; pFile = fopen( pPars->pFileProof, "wb" ); if ( pFile == NULL ) { Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" for writing the proof.\n", pPars->pFileProof ); return 0; } fclose( pFile ); } Bmc_ManBCorePerform( pAbc->pGia, pPars ); return 0; usage: Abc_Print( -2, "usage: &bcore [-FOTV num] [-vh] \n" ); Abc_Print( -2, "\t records UNSAT core of the BMC instance\n" ); Abc_Print( -2, "\t-F num : the zero-based index of a timeframe [default = %d]\n", pPars->iFrame ); Abc_Print( -2, "\t-O num : the zero-based index of a primary output [default = %d]\n", pPars->iOutput ); Abc_Print( -2, "\t-T num : approximate timeout in seconds [default = %d]\n", pPars->nTimeOut ); Abc_Print( -2, "\t-V file: file name with AIG IDs of pivot variables [default = no pivots]\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file name to write the resulting proof [default = stdout]\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9ICheck( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, nFramesMax = 1, nTimeOut = 0, fEmpty = 0, fSearch = 1, fReverse = 0, fBackTopo = 0, fDump = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "MTesrbdvh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFramesMax <= 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; } nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeOut < 0 ) goto usage; break; case 'e': fEmpty ^= 1; break; case 's': fSearch ^= 1; break; case 'r': fReverse ^= 1; break; case 'b': fBackTopo ^= 1; break; case 'd': fDump ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9ICheck(): There is no AIG.\n" ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9ICheck(): The AIG is combinational.\n" ); return 0; } Vec_IntFreeP( &pAbc->vIndFlops ); if ( fSearch ) pAbc->vIndFlops = Bmc_PerformISearch( pAbc->pGia, nFramesMax, nTimeOut, fReverse, fBackTopo, fDump, fVerbose ); else Bmc_PerformICheck( pAbc->pGia, nFramesMax, nTimeOut, fEmpty, fVerbose ); pAbc->nIndFrames = pAbc->vIndFlops ? nFramesMax : 0; return 0; usage: Abc_Print( -2, "usage: &icheck [-MT num] [-esrbdvh]\n" ); Abc_Print( -2, "\t performs specialized induction check\n" ); Abc_Print( -2, "\t-M num : the number of timeframes used for induction [default = %d]\n", nFramesMax ); Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-e : toggle using empty set of next-state functions [default = %s]\n", fEmpty? "yes": "no" ); Abc_Print( -2, "\t-s : toggle searching for a minimal subset [default = %s]\n", fSearch? "yes": "no" ); Abc_Print( -2, "\t-r : toggle searching in the reverse order [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-b : toggle searching in backward order from POs [default = %s]\n", fBackTopo? "yes": "no" ); Abc_Print( -2, "\t-d : toggle printing out the resulting set [default = %s]\n", fDump? "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_CommandAbc9SatTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Bmc_LoadTest( Gia_Man_t * pGia, int fLoadCnf, int fVerbose ); int c, fLoadCnf = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF ) { switch ( c ) { case 'c': fLoadCnf ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SatTest(): There is no AIG.\n" ); return 0; } Bmc_LoadTest( pAbc->pGia, fLoadCnf, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &sattest [-cvh]\n" ); Abc_Print( -2, "\t performs testing of dynamic CNF loading\n" ); Abc_Print( -2, "\t-c : toggle dynamic CNF loading [default = %s]\n", fLoadCnf? "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_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_ParFfSetDefault( Bmc_ParFf_t * p ); extern void Gia_ManFaultTest( Gia_Man_t * p, Gia_Man_t * pG, Bmc_ParFf_t * pPars ); Bmc_ParFf_t Pars, * pPars = &Pars; char * pFileName = NULL; Gia_Man_t * pGold = NULL; int c; Gia_ParFfSetDefault( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ATNKSGkbsfdeunvh" ) ) != EOF ) { switch ( c ) { case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); goto usage; } pPars->Algo = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->Algo < 0 || pPars->Algo > 4 ) 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->nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOut < 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->nIterCheck = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIterCheck < 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->nCardConstr = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCardConstr <= 0 ) goto usage; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); goto usage; } pPars->pFormStr = argv[globalUtilOptind]; globalUtilOptind++; break; case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by string.\n" ); goto usage; } pFileName = argv[globalUtilOptind]; globalUtilOptind++; break; case 'k': pPars->fNonStrict ^= 1; break; case 'b': pPars->fBasic ^= 1; break; case 's': pPars->fStartPats ^= 1; break; case 'f': pPars->fFfOnly ^= 1; break; case 'd': pPars->fDump ^= 1; break; case 'e': pPars->fDumpDelay ^= 1; break; case 'u': pPars->fDumpUntest ^= 1; break; case 'n': pPars->fDumpNewFaults ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pPars->Algo == 0 && pPars->pFormStr == NULL ) { Abc_Print( -1, "Formula string (-S ) should be selected when algorithm is 0 (-A 0).\n" ); return 0; } if ( pPars->Algo != 0 && pPars->pFormStr != NULL ) { Abc_Print( -1, "Algorithm should be 0 (-A 0) when formula string is selected (-S ).\n" ); return 0; } // get the file name if ( argc == globalUtilOptind + 1 ) { FILE * pFile; pPars->pFileName = argv[globalUtilOptind]; pFile = fopen( pPars->pFileName, "r" ); if ( pFile == NULL ) { Abc_Print( -1, "Cannot open file \"%s\" with the input test patterns.\n", pPars->pFileName ); return 0; } fclose( pFile ); } // check other conditions if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9FFTest(): There is no AIG.\n" ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 && pPars->Algo == 1 ) { Abc_Print( -1, "Abc_CommandAbc9FFTest(): For delay testing, AIG should be sequential.\n" ); return 0; } // check if the file is valid if ( pFileName ) { FILE * pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { Abc_Print( -1, "Abc_CommandAbc9FFTest(): File name \"%s\" with golden model is invalid.\n", pFileName ); return 0; } fclose( pFile ); pGold = Gia_AigerRead( pFileName, 0, 0, 0 ); if ( pGold == NULL ) { Abc_Print( -1, "Abc_CommandAbc9FFTest(): Cannot read file \"%s\" with golden model.\n", pFileName ); return 0; } if ( Gia_ManPiNum(pAbc->pGia) != Gia_ManPiNum(pGold) ) { Gia_ManStop( pGold ); Abc_Print( -1, "Abc_CommandAbc9FFTest(): Old model and gold model have different number of PIs.\n" ); return 0; } if ( Gia_ManPoNum(pAbc->pGia) != Gia_ManPoNum(pGold) ) { Gia_ManStop( pGold ); Abc_Print( -1, "Abc_CommandAbc9FFTest(): Old model and gold model have different number of POs.\n" ); return 0; } printf( "Entered spec AIG from file \"%s\".\n", pFileName ); } Gia_ManFaultTest( pAbc->pGia, pGold ? pGold : pAbc->pGia, pPars ); Gia_ManStopP( &pGold ); return 0; usage: Abc_Print( -2, "usage: &fftest [-ATNK num] [-kbsfdeunvh] [-G file] [-S str]\n" ); Abc_Print( -2, "\t performs functional fault test generation\n" ); Abc_Print( -2, "\t-A num : selects fault model for all gates [default = %d]\n", pPars->Algo ); Abc_Print( -2, "\t 0: fault model is not selected (use -S str)\n" ); Abc_Print( -2, "\t 1: delay fault testing for sequential circuits\n" ); Abc_Print( -2, "\t 2: traditional stuck-at fault: -S (((a&b)&~p)|q)\n" ); Abc_Print( -2, "\t 3: complement fault: -S ((a&b)^p)\n" ); Abc_Print( -2, "\t 4: functionally observable fault\n" ); Abc_Print( -2, "\t-T num : specifies approximate runtime limit in seconds [default = %d]\n", pPars->nTimeOut ); Abc_Print( -2, "\t-N num : specifies iteration to check for fixed parameters [default = %d]\n", pPars->nIterCheck ); Abc_Print( -2, "\t-K num : specifies cardinality constraint (num > 0) [default = unused]\n" ); Abc_Print( -2, "\t-k : toggles non-strict cardinality (n <= K, instead of n == K) [default = %s]\n",pPars->fNonStrict? "yes": "no" ); Abc_Print( -2, "\t-b : toggles testing for single faults (the same as \"-K 1\") [default = %s]\n", pPars->fBasic? "yes": "no" ); Abc_Print( -2, "\t-s : toggles starting with the all-0 and all-1 patterns [default = %s]\n", pPars->fStartPats? "yes": "no" ); Abc_Print( -2, "\t-f : toggles faults at flop inputs only with \"-A 1\" and \"-S str\" [default = %s]\n", pPars->fFfOnly? "yes": "no" ); Abc_Print( -2, "\t-d : toggles dumping test patterns into file \"tests.txt\" [default = %s]\n", pPars->fDump? "yes": "no" ); Abc_Print( -2, "\t-e : toggles dumping test pattern pairs (delay faults only) [default = %s]\n", pPars->fDumpDelay? "yes": "no" ); Abc_Print( -2, "\t-u : toggles dumping untestable faults into \"untest.txt\" [default = %s]\n", pPars->fDumpUntest? "yes": "no" ); Abc_Print( -2, "\t-n : toggles dumping faults not detected by a given test set [default = %s]\n", pPars->fDumpNewFaults? "yes": "no" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : (optional) file name with input test patterns\n\n"); Abc_Print( -2, "\t-G file : (optional) file name with the golden model\n\n"); Abc_Print( -2, "\t-S str : (optional) string representing the fault model\n"); Abc_Print( -2, "\t The following notations are used:\n"); Abc_Print( -2, "\t Functional variables: {a,b} (both a and b are always present)\n"); Abc_Print( -2, "\t Parameter variables: {p,q,r,s,t,u,v,w} (any number from 1 to 8)\n"); Abc_Print( -2, "\t Boolean operators: AND(&), OR(|), XOR(^), MUX(?:), NOT(~)\n"); Abc_Print( -2, "\t Parentheses should be used around each operator. Spaces not allowed.\n"); Abc_Print( -2, "\t Complement (~) is only allowed before variables (use DeMorgan law).\n"); Abc_Print( -2, "\t Examples:\n"); Abc_Print( -2, "\t (((a&b)&~p)|q) stuck-at-0/1 at the output\n"); Abc_Print( -2, "\t (((a&~p)|q)&b) stuck-at-0/1 at input a\n"); Abc_Print( -2, "\t (((a|p)&(b|q))&~r) stuck-at-1 at the inputs and stuck-at-0 at the output\n"); Abc_Print( -2, "\t (((a&~p)&(b&~q))|r) stuck-at-0 at the inputs and stuck-at-1 at the output\n"); Abc_Print( -2, "\t ((a&b)^p) complement at the output\n"); Abc_Print( -2, "\t (((a^p)&(b^q))^r) complement at the inputs and at the output\n"); Abc_Print( -2, "\t (a?(b?~s:r):(b?q:p)) functionally observable fault at the output\n"); Abc_Print( -2, "\t (p?(a|b):(a&b)) replace AND by OR\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_QbfDumpFile( Gia_Man_t * pGia, int nPars ); extern int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, int nTimeOut, int fVerbose ); int c, nPars = -1; int nIterLimit = 0; int nConfLimit = 0; int nTimeOut = 0; int fDumpCnf = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PICTdvh" ) ) != 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; } nIterLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nIterLimit < 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 '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 'd': fDumpCnf ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "There is no current GIA.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) ) { Abc_Print( -1, "Works only for combinational networks.\n" ); return 1; } if ( Gia_ManPoNum(pAbc->pGia) != 1 ) { Abc_Print( -1, "The miter should have one primary output.\n" ); return 1; } if ( !(nPars > 0 && nPars < Gia_ManPiNum(pAbc->pGia)) ) { Abc_Print( -1, "The number of parameter variables is invalid (should be > 0 and < PI num).\n" ); return 1; } if ( fDumpCnf ) Gia_QbfDumpFile( pAbc->pGia, nPars ); else Gia_QbfSolve( pAbc->pGia, nPars, nIterLimit, nConfLimit, nTimeOut, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &qbf [-PICT 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", nIterLimit ); Abc_Print( -2, "\t-C num : conflict limit per problem [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-T num : global timeout [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-d : toggle dumping QDIMACS file instead of solving [default = %s]\n", fDumpCnf? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9QVar( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_QbfQuantifyAll( Gia_Man_t * p, int nPars, int fAndAll, int fOrAll ); Gia_Man_t * pTemp; int c, nPars = -1; int fQuantU = 0; int fQuantE = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Puevh" ) ) != 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 'u': fQuantU ^= 1; break; case 'e': fQuantE ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "There is no current GIA.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) ) { Abc_Print( -1, "Works only for combinational networks.\n" ); return 1; } if ( !(nPars > 0 && nPars < Gia_ManPiNum(pAbc->pGia)) ) { Abc_Print( -1, "The number of parameter variables is invalid (should be > 0 and < PI num).\n" ); return 1; } pTemp = Gia_QbfQuantifyAll( pAbc->pGia, nPars, fQuantU, fQuantE ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &qvar [-P num] [-uevh]\n" ); Abc_Print( -2, "\t derives cofactors w.r.t. the last NumPi- variables\n" ); Abc_Print( -2, "\t-P num : number of parameters p (should be the first PIs) [default = %d]\n", nPars ); Abc_Print( -2, "\t-u : toggle ANDing cofactors (universal quantification) [default = %s]\n", fQuantU? "yes": "no" ); Abc_Print( -2, "\t-e : toggle ORing cofactors (existential quantification) [default = %s]\n", fQuantE? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9GenQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * pGia, int nFrames, int nLutNum, int nLutSize, char * pStr, int fVerbose ); int nFrames = 1; int nLutNum = 1; int nLutSize = 6; char * pStr = NULL; int fVerbose = 0; int c; Gia_Man_t * pTemp; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FKNSvh" ) ) != 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 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLutSize < 0 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nLutNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLutNum < 0 ) goto usage; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } pStr = Abc_UtilStrsav(argv[globalUtilOptind]); globalUtilOptind++; if ( pStr == NULL ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "There is no current GIA.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Works only for sequential networks.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) < nLutSize * nLutNum ) { Abc_Print( -1, "The number of flops (%d) is less than required (%d).\n", Gia_ManRegNum(pAbc->pGia), nLutSize * nLutNum ); return 1; } if ( nFrames != 1 || nLutNum != 1 ) { Abc_Print( -1, "Currently this commands works for one frame and one LUT.\n" ); return 1; } pTemp = Gia_GenQbfMiter( pAbc->pGia, nFrames, nLutNum, nLutSize, pStr, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); ABC_FREE( pStr ); return 0; usage: Abc_Print( -2, "usage: &genqbf [-FKN num] [-vh]\n" ); Abc_Print( -2, "\t generates QBF miter for computing an inductive invariant\n" ); Abc_Print( -2, "\t-F num : the number of time frames for induction [default = %d]\n", nFrames ); Abc_Print( -2, "\t-K num : the LUT size [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-N num : the number of LUTs [default = %d]\n", nLutNum ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9SatFx( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Bmc_FxCompute( Gia_Man_t * p ); extern int Bmc_FxComputeOne( Gia_Man_t * p, int nIterMax, int nDiv2Add ); int nIterMax = 5; int nDiv2Add = 10; int c, fDec = 1; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IDdvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nIterMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nIterMax < 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; } nDiv2Add = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDiv2Add < 0 ) goto usage; break; case 'd': fDec ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SatFx(): There is no AIG.\n" ); return 0; } if ( fDec ) Bmc_FxComputeOne( pAbc->pGia, nIterMax, nDiv2Add ); else Bmc_FxCompute( pAbc->pGia ); return 0; usage: Abc_Print( -2, "usage: &satfx [-ID num] [-dvh]\n" ); Abc_Print( -2, "\t performs SAT based shared logic extraction\n" ); Abc_Print( -2, "\t-I num : the number of iterations of divisor extraction [default = %d]\n", nIterMax ); Abc_Print( -2, "\t-D num : the number of divisors to extract in each iteration [default = %d]\n", nDiv2Add ); Abc_Print( -2, "\t-d : toggles decomposing the first output [default = %s]\n", fDec? "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_CommandAbc9SatClp( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Str_t * Bmc_CollapseOne( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ); int nCubeLim = 1000; int nBTLimit = 1000000; int fCanon = 0; int fVerbose = 0; int c; Vec_Str_t * vSop; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CLcvh" ) ) != 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 'c': fCanon ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9SatClp(): There is no AIG.\n" ); return 0; } vSop = Bmc_CollapseOne( pAbc->pGia, nCubeLim, nBTLimit, fCanon, 0, fVerbose ); Vec_StrFree( vSop ); return 0; usage: Abc_Print( -2, "usage: &satclp [-CL num] [-cvh]\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-c : toggles using canonical ISOP computation [default = %s]\n", fCanon? "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_CommandAbc9Inse( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Int_t * Gia_ManInseTest( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose ); int c, nFrames = 10, nWords = 1000, nTimeOut = 0, fSim = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FWTsvh" ) ) != 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 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nWords < 0 ) goto usage; break; case 'T': 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 's': fSim ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Inse(): There is no AIG.\n" ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9Inse(): AIG is combinational.\n" ); return 0; } if ( pAbc->pGia->vInitClasses != NULL ) { Abc_Print( 1, "Abc_CommandAbc9Inse(): All-0 initial state is assumed.\n" ); Vec_IntFreeP( &pAbc->pGia->vInitClasses ); } pAbc->pGia->vInitClasses = Gia_ManInseTest( pAbc->pGia, NULL, nFrames, nWords, nTimeOut, fSim, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &inse [-FWT num] [-svh]\n" ); Abc_Print( -2, "\t experimental procedure\n" ); Abc_Print( -2, "\t-F num : the number of timeframes [default = %d]\n", nFrames ); Abc_Print( -2, "\t-W num : the number of machine words [default = %d]\n", nWords ); Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-s : toggles using ternary simulation [default = %s]\n", fSim? "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_CommandAbc9Maxi( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Int_t * Gia_ManMaxiTest( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose ); Vec_Int_t * vTemp; int c, nFrames = 5, nWords = 1000, nTimeOut = 0, fSim = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FWTsvh" ) ) != 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 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nWords < 0 ) goto usage; break; case 'T': 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 's': fSim ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Maxi(): There is no AIG.\n" ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9Maxi(): AIG is combinational.\n" ); return 0; } pAbc->pGia->vInitClasses = Gia_ManMaxiTest( pAbc->pGia, vTemp = pAbc->pGia->vInitClasses, nFrames, nWords, nTimeOut, fSim, fVerbose ); Vec_IntFreeP( &vTemp ); return 0; usage: Abc_Print( -2, "usage: &maxi [-FWT num] [-svh]\n" ); Abc_Print( -2, "\t experimental procedure\n" ); Abc_Print( -2, "\t-F num : the number of timeframes [default = %d]\n", nFrames ); Abc_Print( -2, "\t-W num : the number of machine words [default = %d]\n", nWords ); Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-s : toggles using ternary simulation [default = %s]\n", fSim? "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_CommandAbc9Bmci( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Gia_ManBmciTest( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose ); int c, nFrames = 1000, nWords = 1000, nTimeOut = 0, fSim = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FWTsvh" ) ) != 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 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nWords < 0 ) goto usage; break; case 'T': 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 's': fSim ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Bmci(): There is no AIG.\n" ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9Bmci(): AIG is combinational.\n" ); return 0; } if ( pAbc->pGia->vInitClasses == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Bmci(): Init array is not given.\n" ); return 0; } Gia_ManBmciTest( pAbc->pGia, pAbc->pGia->vInitClasses, nFrames, nWords, nTimeOut, fSim, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &bmci [-FWT num] [-svh]\n" ); Abc_Print( -2, "\t experimental procedure\n" ); Abc_Print( -2, "\t-F num : the number of timeframes [default = %d]\n", nFrames ); Abc_Print( -2, "\t-W num : the number of machine words [default = %d]\n", nWords ); Abc_Print( -2, "\t-T num : approximate global runtime limit in seconds [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-s : toggles using ternary simulation [default = %s]\n", fSim? "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_CommandAbc9PoXsim( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Int_t * Gia_ManPoXSim( Gia_Man_t * p, int nFrames, int fVerbose ); int c, nFrames = 1000, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != 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 ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Bmci(): There is no AIG.\n" ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9Bmci(): AIG is combinational.\n" ); return 0; } Vec_IntFreeP( &pAbc->vAbcObjIds ); pAbc->vAbcObjIds = Gia_ManPoXSim( pAbc->pGia, nFrames, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &poxsim [-F num] [-vh]\n" ); Abc_Print( -2, "\t X-valued simulation of the multi-output sequential miter\n" ); Abc_Print( -2, "\t-F num : the number of timeframes [default = %d]\n", nFrames ); 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_CommandAbc9Demiter( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; int c, fDumpFiles = 0, fDumpFilesTwo = 0, fDual = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ftdvh" ) ) != EOF ) { switch ( c ) { case 'f': fDumpFiles ^= 1; break; case 't': fDumpFilesTwo ^= 1; break; case 'd': fDual ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Demiter(): There is no AIG.\n" ); return 0; } if ( fDumpFiles || fDumpFilesTwo ) { char pName0[1000] = "miter_part0.aig"; char pName1[1000] = "miter_part1.aig"; Gia_Man_t * pPart1, * pPart2; if ( Gia_ManPoNum(pAbc->pGia) % 2 != 0 ) { Abc_Print( -1, "Abc_CommandAbc9Demiter(): Does not look like a dual-output miter.\n" ); return 0; } if ( fDumpFilesTwo ) Gia_ManDemiterTwoWords( pAbc->pGia, &pPart1, &pPart2 ); else Gia_ManDemiterDual( pAbc->pGia, &pPart1, &pPart2 ); if ( pAbc->pGia->pSpec ) { char * pGen = Extra_FileNameGeneric(pAbc->pGia->pSpec); sprintf( pName0, "%s_1.aig", pGen ); sprintf( pName1, "%s_2.aig", pGen ); ABC_FREE( pGen ); } Gia_AigerWrite( pPart1, pName0, 0, 0 ); Gia_AigerWrite( pPart2, pName1, 0, 0 ); Gia_ManStop( pPart1 ); Gia_ManStop( pPart2 ); if ( fDumpFilesTwo ) printf( "Two parts of the two-word miter are dumped into files \"%s\" and \"%s\".\n", pName0, pName1 ); else printf( "Two parts of the dual-output miter are dumped into files \"%s\" and \"%s\".\n", pName0, pName1 ); return 0; } if ( Gia_ManPoNum(pAbc->pGia) != 1 ) { Abc_Print( -1, "Abc_CommandAbc9Demiter(): Miter should have one output.\n" ); return 0; } if ( fDual ) pTemp = Gia_ManDemiterToDual( pAbc->pGia ); else pTemp = Gia_ManDupDemiter( pAbc->pGia, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); if ( fVerbose ) Gia_ManPrintStatsMiter( pTemp, 0 ); return 0; usage: Abc_Print( -2, "usage: &demiter [-ftdvh]\n" ); Abc_Print( -2, "\t decomposes a miter (by default, tries to extract an OR gate)\n" ); Abc_Print( -2, "\t-f : write files with two sides of a dual-output miter [default = %s]\n", fDumpFiles? "yes": "no" ); Abc_Print( -2, "\t-t : write files with two sides of a two-word miter [default = %s]\n", fDumpFilesTwo? "yes": "no" ); Abc_Print( -2, "\t-d : take single-output and decompose into dual-output [default = %s]\n", fDual? "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_CommandAbc9Fadds( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManDupWithNaturalBoxes( Gia_Man_t * p, int nFaddMin, int fVerbose ); extern Gia_Man_t * Gia_ManDupWithArtificialBoxes( Gia_Man_t * p, int DelayC, int nPathMin, int nPathMax, int nPathLimit, int fUseFanout, int fXorTrick, int fIgnoreBoxDelays, int fVerbose ); Gia_Man_t * pTemp, * pTemp2; int c, nFaddMin = 3, fUseNat = 0, fUseArt = 0, fVerbose = 0; int DelayC = 0, nPathMin = 3, nPathMax = 32, nPathLimit = 50, fUseFanout = 0, fUseXorTrick = 0, fIgnoreBoxDelays = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NBSLPnafxbvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nFaddMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFaddMin < 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; } DelayC = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( DelayC < 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; } nPathMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPathMin < 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; } nPathMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPathMax < 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; } nPathLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPathLimit < 0 ) goto usage; break; case 'n': fUseNat ^= 1; break; case 'a': fUseArt ^= 1; break; case 'f': fUseFanout ^= 1; break; case 'x': fUseXorTrick ^= 1; break; case 'b': fIgnoreBoxDelays ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Fadds(): There is no AIG.\n" ); return 0; } if ( fUseNat ) pTemp = Gia_ManDupWithNaturalBoxes( pAbc->pGia, nFaddMin, fVerbose ); else { pTemp = Gia_ManDup( pAbc->pGia ); Gia_ManTransferTiming( pTemp, pAbc->pGia ); } if ( fUseArt ) pTemp2 = Gia_ManDupWithArtificialBoxes( pTemp, DelayC, nPathMin, nPathMax, nPathLimit, fUseFanout, fUseXorTrick, fIgnoreBoxDelays, fVerbose ); else { pTemp2 = Gia_ManDup( pTemp ); Gia_ManTransferTiming( pTemp2, pTemp ); } Gia_ManStop( pTemp ); Abc_FrameUpdateGia( pAbc, pTemp2 ); return 0; usage: Abc_Print( -2, "usage: &fadds [-NBSLP num] [-nafxvh]\n" ); Abc_Print( -2, "\t detects full-adder chains and puts them into white boxes\n" ); Abc_Print( -2, "\t-n : toggles detecting natural full-adder chains [default = %s]\n", fUseNat? "yes": "no" ); Abc_Print( -2, "\t-N num : minimum length of a natural full-adder chain to detect [default = %d]\n", nFaddMin ); Abc_Print( -2, "\t-a : toggles detecting artificial full-adder chains [default = %s]\n", fUseArt? "yes": "no" ); Abc_Print( -2, "\t-B num : full-adder box delay (percentage of AND-gate delay) [default = %d]\n", DelayC ); Abc_Print( -2, "\t-S num : minimum length of an artificial full-adder chain [default = %d]\n", nPathMin ); Abc_Print( -2, "\t-L num : maximum length of an artificial full-adder chain [default = %d]\n", nPathMax ); Abc_Print( -2, "\t-P num : maximum number of artificial full-adder chains to detect [default = %d]\n", nPathLimit ); Abc_Print( -2, "\t-f : toggles allowing external fanouts in artificial chains [default = %s]\n", fUseFanout? "yes": "no" ); Abc_Print( -2, "\t-x : toggles using XOR to generate fanouts in artificial chains [default = %s]\n", fUseXorTrick? "yes": "no" ); Abc_Print( -2, "\t-b : toggles ignoring boxes when computing delays [default = %s]\n", fIgnoreBoxDelays? "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_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) { Vec_Int_t * vOrder = NULL; int c, fSimple = 1, fSigned = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "asvwh" ) ) != EOF ) { switch ( c ) { case 'a': fSimple ^= 1; break; case 's': fSigned ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Esop(): There is no AIG.\n" ); return 0; } vOrder = fSimple ? NULL : Gia_PolynReorder( pAbc->pGia, fVerbose, fVeryVerbose ); Gia_PolynBuild( pAbc->pGia, vOrder, fSigned, fVerbose, fVeryVerbose ); Vec_IntFreeP( &vOrder ); return 0; usage: Abc_Print( -2, "usage: &polyn [-asvwh]\n" ); Abc_Print( -2, "\t derives algebraic polynomial from AIG\n" ); Abc_Print( -2, "\t-a : toggles simple computation [default = %s]\n", fSimple? "yes": "no" ); Abc_Print( -2, "\t-s : toggles signed computation [default = %s]\n", fSigned? "yes": "no" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9ATree( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_PolynCoreDetectTest( Gia_Man_t * pGia ); Gia_Man_t * pTemp = NULL; int c, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vwh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Esop(): There is no AIG.\n" ); return 0; } pTemp = Gia_PolynCoreDetectTest( pAbc->pGia ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &atree [-vwh]\n" ); Abc_Print( -2, "\t extracts adder tree rooting in primary outputs\n" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Acec( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Cec_ParCec_t ParsCec, * pPars = &ParsCec; Gia_Man_t * pSecond; char * FileName, * pTemp; char ** pArgvNew; int c, nArgcNew, fMiter = 0, fDualOutput = 0, fTwoOutput = 0; Cec_ManCecSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CTnmdtvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBTLimit < 0 ) goto usage; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } pPars->TimeLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeLimit < 0 ) goto usage; break; case 'n': pPars->fNaive ^= 1; break; case 'm': fMiter ^= 1; break; case 'd': fDualOutput ^= 1; break; case 't': fTwoOutput ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fMiter ) { Gia_Man_t * pGia0, * pGia1, * pDual; if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Acec(): There is no AIG.\n" ); return 1; } if ( fDualOutput ) { if ( Gia_ManPoNum(pAbc->pGia) & 1 ) { Abc_Print( -1, "The dual-output miter should have an even number of outputs.\n" ); return 1; } if ( !pPars->fSilent ) Abc_Print( 1, "Assuming the current network is a double-output miter. (Conflict limit = %d.)\n", pPars->nBTLimit ); Gia_ManDemiterDual( pAbc->pGia, &pGia0, &pGia1 ); pAbc->Status = Gia_PolynCec( pGia0, pGia1, pPars ); } else if ( fTwoOutput ) { if ( Gia_ManPoNum(pAbc->pGia) & 1 ) { Abc_Print( -1, "The dual-output miter should have an even number of outputs.\n" ); return 1; } if ( !pPars->fSilent ) Abc_Print( 1, "Assuming the current network is a two-word miter. (Conflict limit = %d.)\n", pPars->nBTLimit ); Gia_ManDemiterTwoWords( pAbc->pGia, &pGia0, &pGia1 ); pAbc->Status = Gia_PolynCec( pGia0, pGia1, pPars ); } else { if ( !pPars->fSilent ) Abc_Print( 1, "Assuming the current network is a single-output miter. (Conflict limit = %d.)\n", pPars->nBTLimit ); pDual = Gia_ManDemiterToDual( pAbc->pGia ); Gia_ManDemiterDual( pDual, &pGia0, &pGia1 ); Gia_ManStop( pDual ); pAbc->Status = Gia_PolynCec( pGia0, pGia1, pPars ); } Abc_FrameReplaceCex( pAbc, &pGia0->pCexComb ); Gia_ManStop( pGia0 ); Gia_ManStop( pGia1 ); return 0; } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { if ( pAbc->pGia->pSpec == NULL ) { Abc_Print( -1, "File name is not given on the command line.\n" ); return 1; } FileName = pAbc->pGia->pSpec; } else 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 ); pSecond = Gia_AigerRead( FileName, 0, 0, 0 ); if ( pSecond == NULL ) { Abc_Print( -1, "Reading AIGER has failed.\n" ); return 0; } pAbc->Status = Gia_PolynCec( pAbc->pGia, pSecond, pPars ); Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); Gia_ManStop( pSecond ); return 0; usage: Abc_Print( -2, "usage: &acec [-CT num] [-nmdtvh]\n" ); Abc_Print( -2, "\t combinational equivalence checking for arithmetic circuits\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-n : toggle using naive SAT-based checking [default = %s]\n", pPars->fNaive? "yes":"no"); Abc_Print( -2, "\t-m : toggle miter vs. two circuits [default = %s]\n", fMiter? "miter":"two circuits"); Abc_Print( -2, "\t-d : toggle using dual output miter [default = %s]\n", fDualOutput? "yes":"no"); Abc_Print( -2, "\t-t : toggle using two-word miter [default = %s]\n", fTwoOutput? "yes":"no"); Abc_Print( -2, "\t-v : toggle 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_CommandAbc9Esop( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes ); Gia_Man_t * pTemp; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Esop(): There is no AIG.\n" ); return 0; } pTemp = Eso_ManCompute( pAbc->pGia, fVerbose, NULL ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &esop [-vh]\n" ); Abc_Print( -2, "\t derives Exclusive Sum of Products from AIG\n" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Exorcism( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_ExorcismMain( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOut, int Quality, int Verbosity, int nCubesMax, int fUseQCost ); extern Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes ); Vec_Wec_t * vEsop = NULL; char * pFileNameOut = NULL; int c, Quality = 2, Verbosity = 0, nCubesMax = 20000, fUseQCost = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "QVCqvh" ) ) != EOF ) { switch ( c ) { case 'Q': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" ); goto usage; } Quality = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Quality < 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; } Verbosity = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Verbosity < 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; } nCubesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCubesMax < 0 ) goto usage; break; case 'q': fUseQCost ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Exorcism(): There is no AIG.\n" ); return 0; } // get the output file name if ( argc == globalUtilOptind + 1 ) pFileNameOut = argv[globalUtilOptind]; // generate starting cover and run minimization Eso_ManCompute( pAbc->pGia, fVerbose, &vEsop ); Abc_ExorcismMain( vEsop, Gia_ManCiNum(pAbc->pGia), Gia_ManCoNum(pAbc->pGia), pFileNameOut, Quality, Verbosity, nCubesMax, fUseQCost ); Vec_WecFree( vEsop ); return 0; usage: Abc_Print( -2, "usage: &exorcism [-Q N] [-V N] [-C N] -q \n" ); Abc_Print( -2, " performs heuristic exclusive sum-of-project minimization\n" ); Abc_Print( -2, " -Q N : minimization quality [default = %d]\n", Quality); Abc_Print( -2, " increasing this number improves quality and adds to runtime\n"); Abc_Print( -2, " -V N : verbosity level [default = %d]\n", Verbosity); Abc_Print( -2, " 0 = no output; 1 = outline; 2 = verbose\n"); Abc_Print( -2, " -C N : maximum number of cubes in startign cover [default = %d]\n", nCubesMax ); Abc_Print( -2, " -q : toggle using quantum cost [default = %s]\n", fUseQCost? "yes": "no" ); Abc_Print( -2, " : the output file name in ESOP-PLA format\n"); Abc_Print( -2, "\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManPerformMfs( Gia_Man_t * p, Sfm_Par_t * pPars ); Gia_Man_t * pTemp; int c; Sfm_Par_t Pars, * pPars = &Pars; Sfm_ParSetDefault( pPars ); pPars->nTfoLevMax = 5; pPars->nDepthMax = 100; pPars->nWinSizeMax = 2000; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCNdaevwh" ) ) != 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 < 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 '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 'd': pPars->fRrOnly ^= 1; break; case 'a': pPars->fArea ^= 1; break; case 'e': pPars->fMoreEffort ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Mfs(): There is no AIG.\n" ); return 0; } if ( Gia_ManBufNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Mfs(): This command does not work with barrier buffers.\n" ); return 1; } if ( !Gia_ManHasMapping(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current AIG has no mapping.\n" ); return 0; } pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &mfs [-WFDMLCN ] [-daevwh]\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-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-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_CommandAbc9CexCut( Abc_Frame_t * pAbc, int argc, char ** argv ) { return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9CexMerge( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Cex_t * pCexNew; int c; int iFrStart = 0; int iFrStop = ABC_INFINITY; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FGvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } iFrStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrStart < 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; } iFrStop = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrStop < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: Abc_Print( -2, "Unknown switch.\n"); goto usage; } } if ( pAbc->pCex == NULL ) { Abc_Print( 1, "There is no current cex.\n"); return 0; } if ( pAbc->pCex2 == NULL ) { Abc_Print( 1, "There is no saved cex.\n"); return 0; } if ( iFrStop - iFrStart < pAbc->pCex->iFrame ) { Abc_Print( 1, "Current CEX does not allow to shorten the saved CEX.\n"); return 0; } pCexNew = Abc_CexMerge( pAbc->pCex2, pAbc->pCex, iFrStart, iFrStop ); if ( pCexNew == NULL ) { Abc_Print( 1, "Merging CEXes has failed.\n"); return 0; } // replace the saved CEX ABC_FREE( pAbc->pCex2 ); pAbc->pCex2 = pCexNew; return 0; usage: Abc_Print( -2, "usage: &cexmerge [-FG num] [-vh]\n" ); Abc_Print( -2, "\t merges the current CEX into the saved one\n" ); Abc_Print( -2, "\t and sets the resulting CEX as the saved one\n" ); Abc_Print( -2, "\t-F num : 0-based number of the starting frame [default = %d]\n", iFrStart ); Abc_Print( -2, "\t-G num : 0-based number of the ending frame [default = %d]\n", iFrStop ); 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_CommandAbc9CexMin( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Cex_t * Gia_ManCexMin( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int nRealPis, int fJustMax, int fUseAll, int fVerbose ); Abc_Cex_t * pCexNew; int iFrameStart = 0; int nRealPis = -1; int fJustMax = 1; int fUseAll = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FNjavh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } iFrameStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrameStart < 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; } nRealPis = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRealPis < 0 ) goto usage; break; case 'j': fJustMax ^= 1; break; case 'a': fUseAll ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9CexMin(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "Abc_CommandAbc9CexMin(): The network is combinational.\n" ); return 0; } if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Abc_CommandAbc9CexMin(): There is no counter-example.\n" ); return 1; } pCexNew = Gia_ManCexMin( pAbc->pGia, pAbc->pCex, iFrameStart, nRealPis, fJustMax, fUseAll, fVerbose ); if ( pCexNew ) Abc_FrameReplaceCex( pAbc, &pCexNew ); return 0; usage: Abc_Print( -2, "usage: &cexmin [-FN num] [-javh]\n" ); Abc_Print( -2, "\t minimizes a deep counter-example\n" ); Abc_Print( -2, "\t-F num : starting timeframe for minimization [default = %d]\n", iFrameStart ); Abc_Print( -2, "\t-N num : the number of real primary inputs [default = %d]\n", nRealPis ); Abc_Print( -2, "\t-j : toggle computing all justifying assignments [default = %s]\n", fJustMax? "yes": "no" ); Abc_Print( -2, "\t-a : toggle using all terminal objects [default = %s]\n", fUseAll? "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_CommandAbc9AbsDerive( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp = NULL; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9AbsDerive(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( pAbc->pGia->vFlopClasses == NULL ) { Abc_Print( -1, "Abstraction flop map is missing.\n" ); return 0; } pTemp = Gia_ManDupAbsFlops( pAbc->pGia, pAbc->pGia->vFlopClasses ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: Abc_Print( -2, "usage: &abs_derive [-vh]\n" ); Abc_Print( -2, "\t derives abstracted model using the pre-computed flop map\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_CommandAbc9AbsRefine( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Gia_Man_t * pTemp = NULL; int c; int nFfToAddMax = 0; int fTryFour = 1; int fSensePath = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Mtsvh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nFfToAddMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFfToAddMax < 0 ) goto usage; break; case 't': fTryFour ^= 1; break; case 's': fSensePath ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9AbsRefine(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Abc_CommandAbc9AbsRefine(): There is no counter-example.\n" ); return 1; } pAbc->Status = Gia_ManCexAbstractionRefine( pAbc->pGia, pAbc->pCex, nFfToAddMax, fTryFour, fSensePath, fVerbose ); Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &abs_refine [-M ] [-tsvh]\n" ); Abc_Print( -2, "\t refines the pre-computed flop map using the counter-example\n" ); Abc_Print( -2, "\t-M num : the max number of flops to add (0 = not used) [default = %d]\n", nFfToAddMax ); Abc_Print( -2, "\t-t : toggle trying four abstractions instead of one [default = %s]\n", fTryFour? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using the path sensitization algorithm [default = %s]\n", fSensePath? "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_CommandAbc9GlaDerive( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp = NULL; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9GlaDerive(): There is no AIG.\n" ); return 1; } /* if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } */ if ( pAbc->pGia->vGateClasses == NULL ) { Abc_Print( -1, "Abstraction gate map is missing.\n" ); return 0; } pTemp = Gia_ManDupAbsGates( pAbc->pGia, pAbc->pGia->vGateClasses ); Gia_ManStop( pTemp ); pTemp = Gia_ManDupAbsGates( pAbc->pGia, pAbc->pGia->vGateClasses ); Abc_FrameUpdateGia( pAbc, pTemp ); // Abc_Print( 1,"This command is currently not enabled.\n" ); return 0; usage: Abc_Print( -2, "usage: &gla_derive [-vh]\n" ); Abc_Print( -2, "\t derives abstracted model using the pre-computed gate map\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_CommandAbc9GlaRefine( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Gia_ManNewRefine( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int iFrameExtra, int fVerbose ); int iFrameStart = 0; int iFrameExtra = 0; int fMinCut = 1; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FGmvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } iFrameStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrameStart < 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; } iFrameExtra = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iFrameExtra < 0 ) goto usage; break; case 'm': fMinCut ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9GlaRefine(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Abc_CommandAbc9GlaRefine(): There is no counter-example.\n" ); return 1; } pAbc->Status = Gia_ManNewRefine( pAbc->pGia, pAbc->pCex, iFrameStart, iFrameExtra, fVerbose ); Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &gla_refine [-FG num] [-vh]\n" ); Abc_Print( -2, "\t refines the pre-computed gate map using the counter-example\n" ); Abc_Print( -2, "\t-F num : starting timeframe for suffix refinement [default = %d]\n", iFrameStart ); Abc_Print( -2, "\t-G num : the number of additional timeframes to try [default = %d]\n", iFrameExtra ); // Abc_Print( -2, "\t-m : toggle using min-cut to derive the refinements [default = %s]\n", fMinCut? "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_CommandAbc9GlaShrink( Abc_Frame_t * pAbc, int argc, char ** argv ) { int fUsePdr = 0; int fUseSat = 1; int fUseBdd = 0; int nFrameMax = 0; int nTimeOut = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FTpsbvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFrameMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFrameMax < 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; } nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeOut < 0 ) goto usage; break; case 'p': fUsePdr ^= 1; break; case 's': fUseSat ^= 1; break; case 'b': fUseBdd ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9GlaShrink(): There is no AIG.\n" ); return 1; } if ( pAbc->pGia->vGateClasses == NULL ) { Abc_Print( -1, "Abc_CommandAbc9GlaShrink(): There is no gate-level abstraction.\n" ); return 0; } Gia_ManShrinkGla( pAbc->pGia, nFrameMax, nTimeOut, fUsePdr, fUseSat, fUseBdd, fVerbose ); return 0; usage: Abc_Print( -2, "usage: &gla_shrink [-FT num] [-psbvh]\n" ); Abc_Print( -2, "\t shrinks the abstraction by removing redundant objects\n" ); Abc_Print( -2, "\t-F num : the maximum timeframe to check to [default = %d]\n", nFrameMax ); Abc_Print( -2, "\t-T num : the timeout per call, in seconds [default = %d]\n", nTimeOut ); Abc_Print( -2, "\t-p : toggle using PDR for checking [default = %s]\n", fUsePdr? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using BMC for checking [default = %s]\n", fUseSat? "yes": "no" ); Abc_Print( -2, "\t-b : toggle using BDDs for checking [default = %s]\n", fUseBdd? "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_CommandAbc9Gla( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abs_Par_t Pars, * pPars = &Pars; int c, fNewAlgo = 1; Abs_ParSetDefaults( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FSCLDETRQPBAtfardmnscbpquwvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesMax < 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->nFramesStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesStart < 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->nConfLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->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; } pPars->nLearnedStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedStart < 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->nLearnedDelta = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedDelta < 0 ) goto usage; break; case 'E': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } pPars->nLearnedPerce = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedPerce < 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->nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOut < 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->nRatioMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRatioMin < 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; } pPars->nRatioMin2 = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRatioMin2 < 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->nRatioMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRatioMax < 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->nFramesNoChangeLim = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesNoChangeLim < 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; } pPars->pFileVabs = argv[globalUtilOptind]; globalUtilOptind++; break; case 't': pPars->fUseTermVars ^= 1; break; case 'f': pPars->fPropFanout ^= 1; break; case 'a': pPars->fAddLayer ^= 1; break; case 'r': pPars->fNewRefine ^= 1; break; case 'd': pPars->fDumpVabs ^= 1; break; case 'm': pPars->fDumpMabs ^= 1; break; case 'n': fNewAlgo ^= 1; break; case 's': pPars->fUseSkip ^= 1; break; case 'c': pPars->fUseSimple ^= 1; break; case 'b': pPars->fSkipHash ^= 1; break; case 'p': pPars->fUseFullProof ^= 1; break; case 'q': pPars->fCallProver ^= 1; break; case 'u': pPars->fSimpProver ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "There is no AIG.\n" ); return 0; } /* if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } */ if ( Gia_ManPoNum(pAbc->pGia) > 1 ) { Abc_Print( 1, "The network is more than one PO (run \"orpos\").\n" ); return 0; } if ( pPars->nFramesMax < 0 ) { Abc_Print( 1, "The number of starting frames should be a positive integer.\n" ); return 0; } if ( pPars->nFramesMax && pPars->nFramesStart > pPars->nFramesMax ) { Abc_Print( 1, "The starting frame is larger than the max number of frames.\n" ); return 0; } if ( fNewAlgo ) pAbc->Status = Gia_ManPerformGla( pAbc->pGia, pPars ); else pAbc->Status = Gia_ManPerformGlaOld( pAbc->pGia, pPars, 0 ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &gla [-FSCLDETRQPB num] [-A file] [-fardmnscbpquwvh]\n" ); Abc_Print( -2, "\t fixed-time-frame gate-level proof- and cex-based abstraction\n" ); Abc_Print( -2, "\t-F num : the max number of timeframes to unroll [default = %d]\n", pPars->nFramesMax ); Abc_Print( -2, "\t-S num : the starting time frame (0=unused) [default = %d]\n", pPars->nFramesStart ); Abc_Print( -2, "\t-C num : the max number of SAT solver conflicts (0=unused) [default = %d]\n", pPars->nConfLimit ); Abc_Print( -2, "\t-L num : the max number of learned clauses to keep (0=unused) [default = %d]\n", pPars->nLearnedStart ); Abc_Print( -2, "\t-D num : delta value for learned clause removal [default = %d]\n", pPars->nLearnedDelta ); Abc_Print( -2, "\t-E num : ratio percentage for learned clause removal [default = %d]\n", pPars->nLearnedPerce ); Abc_Print( -2, "\t-T num : an approximate timeout, in seconds [default = %d]\n", pPars->nTimeOut ); Abc_Print( -2, "\t-R num : stop when abstraction size exceeds num %% (0<=num<=100) [default = %d]\n", pPars->nRatioMin ); Abc_Print( -2, "\t-Q num : stop when abstraction size exceeds num %% during refinement (0<=num<=100) [default = %d]\n", pPars->nRatioMin2 ); Abc_Print( -2, "\t-P num : maximum percentage of added objects before a restart (0<=num<=100) [default = %d]\n", pPars->nRatioMax ); Abc_Print( -2, "\t-B num : the number of stable frames to call prover or dump abstraction [default = %d]\n", pPars->nFramesNoChangeLim ); Abc_Print( -2, "\t-A file : file name for dumping abstrated model [default = \"glabs.aig\"]\n" ); Abc_Print( -2, "\t-f : toggle propagating fanout implications [default = %s]\n", pPars->fPropFanout? "yes": "no" ); Abc_Print( -2, "\t-a : toggle refinement by adding one layers of gates [default = %s]\n", pPars->fAddLayer? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using improved refinement heuristics [default = %s]\n", pPars->fNewRefine? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dumping abstracted model into a file [default = %s]\n", pPars->fDumpVabs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle dumping abstraction map into a file [default = %s]\n", pPars->fDumpMabs? "yes": "no" ); Abc_Print( -2, "\t-n : toggle using new algorithms [default = %s]\n", fNewAlgo? "yes": "no" ); Abc_Print( -2, "\t-s : toggle skipping previously proved timeframes [default = %s]\n", pPars->fUseSkip? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using naive (2-input AND node) CNF encoding [default = %s]\n", pPars->fUseSimple? "yes": "no" ); Abc_Print( -2, "\t-b : toggle CNF construction without hashing [default = %s]\n", pPars->fSkipHash? "yes": "no" ); Abc_Print( -2, "\t-p : toggle using full-proof for UNSAT cores [default = %s]\n", pPars->fUseFullProof? "yes": "no" ); Abc_Print( -2, "\t-q : toggle calling the prover [default = %s]\n", pPars->fCallProver? "yes": "no" ); Abc_Print( -2, "\t-u : toggle enabling simplifation before calling the prover [default = %s]\n", pPars->fSimpProver? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing more verbose information [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_CommandAbc9Vta( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abs_Par_t Pars, * pPars = &Pars; int c; Abs_ParSetDefaults( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FSPCLDETRAtradvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFramesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesMax < 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->nFramesStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesStart < 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->nFramesPast = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFramesPast < 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->nConfLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->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; } pPars->nLearnedStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedStart < 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->nLearnedDelta = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedDelta < 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->nLearnedPerce = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLearnedPerce < 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->nTimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeOut < 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->nRatioMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nRatioMin < 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; } pPars->pFileVabs = argv[globalUtilOptind]; globalUtilOptind++; break; case 't': pPars->fUseTermVars ^= 1; break; case 'r': pPars->fUseRollback ^= 1; break; case 'a': pPars->fAddLayer ^= 1; break; case 'd': pPars->fDumpVabs ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "There is no AIG.\n" ); return 0; } if ( Gia_ManRegNum(pAbc->pGia) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( Gia_ManPoNum(pAbc->pGia) > 1 ) { Abc_Print( 1, "The network is more than one PO (run \"orpos\").\n" ); return 0; } if ( pPars->nFramesMax < 0 ) { Abc_Print( 1, "The number of starting frames should be a positive integer.\n" ); return 0; } if ( pPars->nFramesMax && pPars->nFramesStart > pPars->nFramesMax ) { Abc_Print( 1, "The starting frame is larger than the max number of frames.\n" ); return 0; } pAbc->Status = Gia_VtaPerform( pAbc->pGia, pPars ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); return 0; usage: Abc_Print( -2, "usage: &vta [-FSPCLDETR num] [-A file] [-tradvh]\n" ); Abc_Print( -2, "\t variable-time-frame gate-level proof- and cex-based abstraction\n" ); Abc_Print( -2, "\t-F num : the max number of timeframes to unroll [default = %d]\n", pPars->nFramesMax ); Abc_Print( -2, "\t-S num : the starting time frame (0=unused) [default = %d]\n", pPars->nFramesStart ); Abc_Print( -2, "\t-P num : the number of previous frames for UNSAT core [default = %d]\n", pPars->nFramesPast ); Abc_Print( -2, "\t-C num : the max number of SAT solver conflicts (0=unused) [default = %d]\n", pPars->nConfLimit ); Abc_Print( -2, "\t-L num : the max number of learned clauses to keep (0=unused) [default = %d]\n", pPars->nLearnedStart ); Abc_Print( -2, "\t-D num : delta value for learned clause removal [default = %d]\n", pPars->nLearnedDelta ); Abc_Print( -2, "\t-E num : ratio percentage for learned clause removal [default = %d]\n", pPars->nLearnedPerce ); Abc_Print( -2, "\t-T num : an approximate timeout, in seconds [default = %d]\n", pPars->nTimeOut ); Abc_Print( -2, "\t-R num : minimum percentage of abstracted objects (0<=num<=100) [default = %d]\n", pPars->nRatioMin ); Abc_Print( -2, "\t-A file : file name for dumping abstrated model [default = \"vabs.aig\"]\n" ); Abc_Print( -2, "\t-t : toggle using terminal variables [default = %s]\n", pPars->fUseTermVars? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using rollback after the starting frames [default = %s]\n", pPars->fUseRollback? "yes": "no" ); Abc_Print( -2, "\t-a : toggle refinement by adding one layers of gates [default = %s]\n", pPars->fAddLayer? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dumping abstracted model into a file [default = %s]\n", pPars->fDumpVabs? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAbc9Vta2Gla( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Vta2Gla(): There is no AIG.\n" ); return 0; } if ( pAbc->pGia->vObjClasses == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Vta2Gla(): There is no variable-time-frame abstraction is defined.\n" ); return 0; } Vec_IntFreeP( &pAbc->pGia->vGateClasses ); pAbc->pGia->vGateClasses = Gia_VtaConvertToGla( pAbc->pGia, pAbc->pGia->vObjClasses ); Vec_IntFreeP( &pAbc->pGia->vObjClasses ); return 0; usage: Abc_Print( -2, "usage: &vta_gla [-vh]\n" ); Abc_Print( -2, "\t maps variable- into fixed-time-frame gate-level abstraction\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_CommandAbc9Gla2Vta( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, fVerbose = 0; int nFrames = pAbc->nFrames; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != 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 ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Gla2Vta(): There is no AIG.\n" ); return 0; } if ( pAbc->pGia->vGateClasses == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Gla2Vta(): There is no gate-level abstraction is defined.\n" ); return 0; } if ( pAbc->nFrames < 1 ) { Abc_Print( -1, "Abc_CommandAbc9Gla2Vta(): The number of timeframes (%d) should be a positive integer.\n", nFrames ); return 0; } Vec_IntFreeP( &pAbc->pGia->vObjClasses ); pAbc->pGia->vObjClasses = Gia_VtaConvertFromGla( pAbc->pGia, pAbc->pGia->vGateClasses, nFrames ); Vec_IntFreeP( &pAbc->pGia->vGateClasses ); return 0; usage: Abc_Print( -2, "usage: &gla_vta [-F num] [-vh]\n" ); Abc_Print( -2, "\t maps fixed- into variable-time-frame gate-level abstraction\n" ); Abc_Print( -2, "\t-F num : timeframes in the resulting variable-time-frame abstraction [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_CommandAbc9Fla2Gla( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Fla2Gla(): There is no AIG.\n" ); return 0; } if ( pAbc->pGia->vFlopClasses == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Fla2Gla(): There is no gate-level abstraction is defined.\n" ); return 0; } Vec_IntFreeP( &pAbc->pGia->vGateClasses ); pAbc->pGia->vGateClasses = Gia_FlaConvertToGla( pAbc->pGia, pAbc->pGia->vFlopClasses ); Vec_IntFreeP( &pAbc->pGia->vFlopClasses ); return 0; usage: Abc_Print( -2, "usage: &fla_gla [-vh]\n" ); Abc_Print( -2, "\t maps flop-level into gate-level abstraction\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_CommandAbc9Gla2Fla( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Gla2Fla(): There is no AIG.\n" ); return 0; } if ( pAbc->pGia->vGateClasses == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Gla2Fla(): There is no gate-level abstraction is defined.\n" ); return 0; } Vec_IntFreeP( &pAbc->pGia->vFlopClasses ); pAbc->pGia->vFlopClasses = Gia_GlaConvertToFla( pAbc->pGia, pAbc->pGia->vGateClasses ); Vec_IntFreeP( &pAbc->pGia->vGateClasses ); return 0; usage: Abc_Print( -2, "usage: &gla_fla [-vh]\n" ); Abc_Print( -2, "\t maps gate-level into flop-level abstraction\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_CommandAbc9Test( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Gia_Man_t * pTemp = NULL; int c, fVerbose = 0; int nFrames = 5; int fSwitch = 0; int nWords = 1000; int nProcs = 2; // extern Gia_Man_t * Gia_VtaTest( Gia_Man_t * p ); // extern int Gia_ManSuppSizeTest( Gia_Man_t * p ); // extern void Gia_VtaTest( Gia_Man_t * p, int nFramesStart, int nFramesMax, int nConfMax, int nTimeMax, int fVerbose ); // extern void Gia_IsoTest( Gia_Man_t * p, int fVerbose ); // extern void Ga2_ManComputeTest( Gia_Man_t * p ); // extern void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ); // extern void Gia_IsoTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ); // extern void Unr_ManTest( Gia_Man_t * pGia, int nFrames ); // extern int Gia_ManVerify( Gia_Man_t * pGia ); // extern Gia_Man_t * Gia_ManOptimizeRing( Gia_Man_t * p ); // extern void Gia_ManCollectSeqTest( Gia_Man_t * p ); // extern Gia_Man_t * Gia_SweeperFraigTest( Gia_Man_t * p, int nWords, int nConfs, int fVerbose ); // extern Gia_Man_t * Bmc_CexDepthTest( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames, int fVerbose ); // extern Gia_Man_t * Bmc_CexTarget( Gia_Man_t * p, int nFrames ); // extern void Gia_ManMuxProfiling( Gia_Man_t * p ); // extern Gia_Man_t * Mig_ManTest( Gia_Man_t * pGia ); // extern Gia_Man_t * Gia_ManInterTest( Gia_Man_t * p ); // extern Gia_Man_t * Llb_ReachableStatesGia( Gia_Man_t * p ); // extern Gia_Man_t * Unm_ManTest( Gia_Man_t * pGia ); // extern void Agi_ManTest( Gia_Man_t * pGia ); // extern void Gia_ManCheckFalseTest( Gia_Man_t * p, int nSlackMax ); // extern void Gia_ParTest( Gia_Man_t * p, int nWords, int nProcs ); // extern void Gia_ManTisTest( Gia_Man_t * pInit ); extern void Gia_Iso3Test( Gia_Man_t * p ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WPFsvh" ) ) != EOF ) { switch ( c ) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nWords < 0 ) goto usage; break; case '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 '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 's': fSwitch ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Test(): There is no AIG.\n" ); return 1; } /* if ( pAbc->pCex == NULL ) { Abc_Print( -1, "Abc_CommandAbc9Test(): There is no CEX.\n" ); return 1; } */ // Gia_ManFrontTest( pAbc->pGia ); // Gia_ManReduceConst( pAbc->pGia, 1 ); // Sat_ManTest( pAbc->pGia, Gia_ManCo(pAbc->pGia, 0), 0 ); // Gia_ManTestDistance( pAbc->pGia ); // Gia_SatSolveTest( pAbc->pGia ); // For_ManExperiment( pAbc->pGia, 20, 1, 1 ); // Gia_ManUnrollSpecial( pAbc->pGia, 5, 100, 1 ); // pAbc->pGia = Gia_ManDupSelf( pTemp = pAbc->pGia ); // pAbc->pGia = Gia_ManRemoveEnables( pTemp = pAbc->pGia ); // Cbs_ManSolveTest( pAbc->pGia ); // pAbc->pGia = Gia_VtaTest( pTemp = pAbc->pGia ); // Gia_ManStopP( &pTemp ); // Gia_ManSuppSizeTest( pAbc->pGia ); // Gia_VtaTest( pAbc->pGia, 10, 100000, 0, 0, 1 ); // Gia_IsoTest( pAbc->pGia, fVerbose ); // Ga2_ManComputeTest( pAbc->pGia ); // Bmc_CexTest( pAbc->pGia, pAbc->pCex, fVerbose ); // Gia_IsoTest( pAbc->pGia, pAbc->pCex, 0 ); // Unr_ManTest( pAbc->pGia, nFrames ); // Gia_ManVerifyWithBoxes( pAbc->pGia ); // Gia_ManCollectSeqTest( pAbc->pGia ); // pTemp = Gia_ManOptimizeRing( pAbc->pGia ); // pTemp = Gia_SweeperFraigTest( pAbc->pGia, 4, 1000, 0 ); // Abc_FrameUpdateGia( pAbc, pTemp ); // pTemp = Bmc_CexDepthTest( pAbc->pGia, pAbc->pCex, nFrames, fVerbose ); // pTemp = Bmc_CexTarget( pAbc->pGia, nFrames ); // Abc_FrameUpdateGia( pAbc, pTemp ); // Gia_ManMuxProfiling( pAbc->pGia ); // pTemp = Mig_ManTest( pAbc->pGia ); // Abc_FrameUpdateGia( pAbc, pTemp ); // pTemp = Gia_ManInterTest( pAbc->pGia ); // Abc_FrameUpdateGia( pAbc, pTemp ); // pTemp = Llb_ReachableStatesGia( pAbc->pGia ); // Abc_FrameUpdateGia( pAbc, pTemp ); // Unm_ManTest( pAbc->pGia ); // Agi_ManTest( pAbc->pGia ); // Gia_ManResubTest( pAbc->pGia ); // Jf_ManTestCnf( pAbc->pGia ); // Gia_ManCheckFalseTest( pAbc->pGia, nFrames ); // Gia_ParTest( pAbc->pGia, nWords, nProcs ); // Gia_PolynExplore( pAbc->pGia ); // Gia_ManTestSatEnum( pAbc->pGia ); // printf( "\nThis command is currently disabled.\n\n" ); return 0; usage: Abc_Print( -2, "usage: &test [-FW num] [-svh]\n" ); Abc_Print( -2, "\t testing various procedures\n" ); Abc_Print( -2, "\t-F num: the number of timeframes [default = %d]\n", nFrames ); Abc_Print( -2, "\t-W num: the number of machine words [default = %d]\n", nWords ); Abc_Print( -2, "\t-s : toggle enable (yes) vs. disable (no) [default = %s]\n", fSwitch? "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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #include "abciUnfold2.c" ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcAttach.c000066400000000000000000000306711300674244400236710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcAttach.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Attaches the library gates to the current network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcAttach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ATTACH_FULL (~((unsigned)0)) #define ATTACH_MASK(n) ((~((unsigned)0)) >> (32-(n))) static void Abc_AttachSetupTruthTables( unsigned uTruths[][2] ); static void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthNode ); static Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm ); static int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode ); static int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] ); static void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm ); static char ** s_pPerms = NULL; static int s_nPerms; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Attaches gates from the current library to the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkAttach( Abc_Ntk_t * pNtk ) { Mio_Library_t * pGenlib; unsigned ** puTruthGates; unsigned uTruths[6][2]; Abc_Obj_t * pNode; Mio_Gate_t ** ppGates; int nGates, nFanins, i; assert( Abc_NtkIsSopLogic(pNtk) ); // check that the library is available pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pGenlib == NULL ) { printf( "The current library is not available.\n" ); return 0; } // start the truth tables Abc_AttachSetupTruthTables( uTruths ); // collect all the gates ppGates = Mio_CollectRoots( pGenlib, 6, (float)1.0e+20, 1, &nGates, 0 ); // derive the gate truth tables puTruthGates = ABC_ALLOC( unsigned *, nGates ); puTruthGates[0] = ABC_ALLOC( unsigned, 2 * nGates ); for ( i = 1; i < nGates; i++ ) puTruthGates[i] = puTruthGates[i-1] + 2; for ( i = 0; i < nGates; i++ ) Mio_DeriveTruthTable( ppGates[i], uTruths, Mio_GateReadPinNum(ppGates[i]), 6, puTruthGates[i] ); // assign the gates to pNode->pCopy Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachNode( pNtk, pNode, i ) { nFanins = Abc_ObjFaninNum(pNode); if ( nFanins == 0 ) { if ( Abc_SopIsConst1((char *)pNode->pData) ) pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst1(pGenlib); else pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst0(pGenlib); } else if ( nFanins == 1 ) { if ( Abc_SopIsBuf((char *)pNode->pData) ) pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadBuf(pGenlib); else pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadInv(pGenlib); } else if ( nFanins > 6 ) { printf( "Cannot attach gate with more than 6 inputs to node %s.\n", Abc_ObjName(pNode) ); ABC_FREE( puTruthGates[0] ); ABC_FREE( puTruthGates ); ABC_FREE( ppGates ); return 0; } else if ( !Abc_NodeAttach( pNode, ppGates, puTruthGates, nGates, uTruths ) ) { printf( "Could not attach the library gate to node %s.\n", Abc_ObjName(pNode) ); ABC_FREE( puTruthGates[0] ); ABC_FREE( puTruthGates ); ABC_FREE( ppGates ); return 0; } } ABC_FREE( puTruthGates[0] ); ABC_FREE( puTruthGates ); ABC_FREE( ppGates ); ABC_FREE( s_pPerms ); // perform the final transformation Abc_NtkForEachNode( pNtk, pNode, i ) { if ( pNode->pCopy == NULL ) { printf( "Some elementary gates (constant, buffer, or inverter) are missing in the library.\n" ); return 0; } } // replace SOP representation by the gate representation Abc_NtkForEachNode( pNtk, pNode, i ) pNode->pData = pNode->pCopy, pNode->pCopy = NULL; pNtk->ntkFunc = ABC_FUNC_MAP; Extra_MmFlexStop( (Extra_MmFlex_t *)pNtk->pManFunc ); pNtk->pManFunc = pGenlib; printf( "Library gates are successfully attached to the nodes.\n" ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkAttach: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] ) { int Perm[10]; int pTempInts[10]; unsigned uTruthNode[2]; Abc_Obj_t * pFanin; Mio_Gate_t * pGate; int nFanins, i; // compute the node's truth table Abc_AttachComputeTruth( (char *)pNode->pData, uTruths, uTruthNode ); // find the matching gate and permutation pGate = Abc_AttachFind( ppGates, puTruthGates, nGates, uTruthNode, Perm ); if ( pGate == NULL ) return 0; // permute the fanins nFanins = Abc_ObjFaninNum(pNode); Abc_ObjForEachFanin( pNode, pFanin, i ) pTempInts[i] = pFanin->Id; for ( i = 0; i < nFanins; i++ ) pNode->vFanins.pArray[Perm[i]] = pTempInts[i]; // set the gate pNode->pCopy = (Abc_Obj_t *)pGate; return 1; } /**Function************************************************************* Synopsis [Sets up the truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AttachSetupTruthTables( unsigned uTruths[][2] ) { int m, v; for ( v = 0; v < 5; v++ ) uTruths[v][0] = 0; // set up the truth tables for ( m = 0; m < 32; m++ ) for ( v = 0; v < 5; v++ ) if ( m & (1 << v) ) uTruths[v][0] |= (1 << m); // make adjustments for the case of 6 variables for ( v = 0; v < 5; v++ ) uTruths[v][1] = uTruths[v][0]; uTruths[5][0] = 0; uTruths[5][1] = ATTACH_FULL; } /**Function************************************************************* Synopsis [Compute the truth table of the node's cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthRes ) { // Mvc_Cube_t * pCube; unsigned uSignCube[2]; int Value; // int nInputs = pCover->nBits/2; int nInputs = 6; int nFanins = Abc_SopGetVarNum(pSop); char * pCube; int k; // make sure that the number of input truth tables in equal to the number of gate inputs assert( nInputs < 7 ); // clean the resulting truth table uTruthRes[0] = 0; uTruthRes[1] = 0; if ( nInputs < 6 ) { // consider the case when only one unsigned can be used // Mvc_CoverForEachCube( pCover, pCube ) Abc_SopForEachCube( pSop, nFanins, pCube ) { uSignCube[0] = ATTACH_FULL; // Mvc_CubeForEachVarValue( pCover, pCube, Var, Value ) Abc_CubeForEachVar( pCube, Value, k ) { if ( Value == '0' ) uSignCube[0] &= ~uTruthsIn[k][0]; else if ( Value == '1' ) uSignCube[0] &= uTruthsIn[k][0]; } uTruthRes[0] |= uSignCube[0]; } if ( Abc_SopGetPhase(pSop) == 0 ) uTruthRes[0] = ~uTruthRes[0]; if ( nInputs < 5 ) uTruthRes[0] &= ATTACH_MASK(1<= 0 ) { for ( v = 0; v < 6; v++ ) Perm[v] = v; return ppGates[iNum]; } // get permutations if ( s_pPerms == NULL ) { s_pPerms = Extra_Permutations( 6 ); s_nPerms = Extra_Factorial( 6 ); } // try permutations for ( i = 0; i < s_nPerms; i++ ) { Abc_TruthPermute( s_pPerms[i], 6, uTruthNode, uTruthPerm ); if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthPerm )) >= 0 ) { for ( v = 0; v < 6; v++ ) Perm[v] = (int)s_pPerms[i][v]; return ppGates[iNum]; } } return NULL; } /**Function************************************************************* Synopsis [Find the gate by truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode ) { int i; for ( i = 0; i < nGates; i++ ) if ( puTruthGates[i][0] == uTruthNode[0] && puTruthGates[i][1] == uTruthNode[1] ) return i; return -1; } /**Function************************************************************* Synopsis [Permutes the 6-input truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm ) { int nMints, iMintPerm, iMint, v; uTruthPerm[0] = uTruthPerm[1] = 0; nMints = (1 << nVars); for ( iMint = 0; iMint < nMints; iMint++ ) { if ( (uTruthNode[iMint>>5] & (1 << (iMint&31))) == 0 ) continue; iMintPerm = 0; for ( v = 0; v < nVars; v++ ) if ( iMint & (1 << v) ) iMintPerm |= (1 << pPerm[v]); uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31)); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcAuto.c000066400000000000000000000201331300674244400233650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcAuto.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Computation of autosymmetries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcAuto.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD static void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive ); static void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ) { DdManager * dd; // the BDD manager used to hold shared BDDs DdNode ** pbGlobal; // temporary storage for global BDDs char ** pInputNames; // pointers to the CI names char ** pOutputNames; // pointers to the CO names int nOutputs, nInputs, i; Vec_Ptr_t * vFuncsGlob; Abc_Obj_t * pObj; // compute the global BDDs if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose) == NULL ) return; // get information about the network nInputs = Abc_NtkCiNum(pNtk); nOutputs = Abc_NtkCoNum(pNtk); // dd = pNtk->pManGlob; dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk ); // complement the global functions vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); pbGlobal = (DdNode **)Vec_PtrArray( vFuncsGlob ); // get the network names pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); pOutputNames = Abc_NtkCollectCioNames( pNtk, 1 ); // print the size of the BDDs if ( fVerbose ) printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); // allocate additional variables for ( i = 0; i < nInputs; i++ ) Cudd_bddNewVar( dd ); assert( Cudd_ReadSize(dd) == 2 * nInputs ); // create ZDD variables in the manager Cudd_zddVarsFromBddVars( dd, 2 ); // perform the analysis of the primary output functions for auto-symmetry if ( Output == -1 ) Abc_NtkAutoPrintAll( dd, nInputs, pbGlobal, nOutputs, pInputNames, pOutputNames, fNaive ); else Abc_NtkAutoPrintOne( dd, nInputs, pbGlobal, Output, pInputNames, pOutputNames, fNaive ); // deref the PO functions // Abc_NtkFreeGlobalBdds( pNtk ); // stop the global BDD manager // Extra_StopManager( pNtk->pManGlob ); // pNtk->pManGlob = NULL; Abc_NtkFreeGlobalBdds( pNtk, 1 ); ABC_FREE( pInputNames ); ABC_FREE( pOutputNames ); Vec_PtrFree( vFuncsGlob ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive ) { DdNode * bSpace1, * bSpace2, * bCanVars, * bReduced, * zEquations; double nMints; int nSupp, SigCounter, o; int nAutos; int nAutoSyms; int nAutoSymsMax; int nAutoSymsMaxSupp; int nAutoSymOuts; int nSuppSizeMax; abctime clk; nAutoSymOuts = 0; nAutoSyms = 0; nAutoSymsMax = 0; nAutoSymsMaxSupp = 0; nSuppSizeMax = 0; clk = Abc_Clock(); SigCounter = 0; for ( o = 0; o < nOutputs; o++ ) { // bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[o] ); Cudd_Ref( bSpace1 ); bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[o], pbOutputs[o] ); Cudd_Ref( bSpace1 ); bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars ); bReduced = Extra_bddSpaceReduce( dd, pbOutputs[o], bCanVars ); Cudd_Ref( bReduced ); zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations ); nSupp = Cudd_SupportSize( dd, bSpace1 ); nMints = Cudd_CountMinterm( dd, bSpace1, nSupp ); nAutos = Extra_Base2LogDouble(nMints); printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", o, nSupp, nAutos ); if ( nAutos > 0 ) { nAutoSymOuts++; nAutoSyms += nAutos; if ( nAutoSymsMax < nAutos ) { nAutoSymsMax = nAutos; nAutoSymsMaxSupp = nSupp; } } if ( nSuppSizeMax < nSupp ) nSuppSizeMax = nSupp; //ABC_PRB( dd, bCanVars ); //ABC_PRB( dd, bReduced ); //Cudd_PrintMinterm( dd, bReduced ); //printf( "The equations are:\n" ); //Cudd_zddPrintCover( dd, zEquations ); //printf( "\n" ); //fflush( stdout ); bSpace2 = Extra_bddSpaceFromMatrixPos( dd, zEquations ); Cudd_Ref( bSpace2 ); //ABC_PRB( dd, bSpace1 ); //ABC_PRB( dd, bSpace2 ); if ( bSpace1 != bSpace2 ) printf( "Spaces are NOT EQUAL!\n" ); // else // printf( "Spaces are equal.\n" ); Cudd_RecursiveDeref( dd, bSpace1 ); Cudd_RecursiveDeref( dd, bSpace2 ); Cudd_RecursiveDeref( dd, bCanVars ); Cudd_RecursiveDeref( dd, bReduced ); Cudd_RecursiveDerefZdd( dd, zEquations ); } printf( "The cumulative statistics for all outputs:\n" ); printf( "Ins=%3d ", nInputs ); printf( "InMax=%3d ", nSuppSizeMax ); printf( "Outs=%3d ", nOutputs ); printf( "Auto=%3d ", nAutoSymOuts ); printf( "SumK=%3d ", nAutoSyms ); printf( "KMax=%2d ", nAutoSymsMax ); printf( "Supp=%3d ", nAutoSymsMaxSupp ); printf( "Time=%4.2f ", (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC) ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive ) { DdNode * bSpace1, * bCanVars, * bReduced, * zEquations; double nMints; int nSupp, SigCounter; int nAutos; SigCounter = 0; bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[Output] ); Cudd_Ref( bSpace1 ); // bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[Output], pbOutputs[Output] ); Cudd_Ref( bSpace1 ); bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars ); bReduced = Extra_bddSpaceReduce( dd, pbOutputs[Output], bCanVars ); Cudd_Ref( bReduced ); zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations ); nSupp = Cudd_SupportSize( dd, bSpace1 ); nMints = Cudd_CountMinterm( dd, bSpace1, nSupp ); nAutos = Extra_Base2LogDouble(nMints); printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", Output, nSupp, nAutos ); Cudd_RecursiveDeref( dd, bSpace1 ); Cudd_RecursiveDeref( dd, bCanVars ); Cudd_RecursiveDeref( dd, bReduced ); Cudd_RecursiveDerefZdd( dd, zEquations ); } #else void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ) {} #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcBalance.c000066400000000000000000000516351300674244400240150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcBalance.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Performs global balancing of the AIG by the number of levels.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, int fDuplicate, int fSelective, int fUpdateLevel ); static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, int fSelective, int fUpdateLevel ); static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, int fSelective ); static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fDuplicate, int fSelective ); static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ); static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Balances the AIG network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, int fDuplicate, int fSelective, int fUpdateLevel ) { // extern void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); Abc_Ntk_t * pNtkAig; assert( Abc_NtkIsStrash(pNtk) ); // compute the required times if ( fSelective ) { Abc_NtkStartReverseLevels( pNtk, 0 ); Abc_NtkMarkCriticalNodes( pNtk ); } // perform balancing pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // transfer HAIG // Abc_NtkHaigTranfer( pNtk, pNtkAig ); // perform balancing Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel ); Abc_NtkFinalize( pNtk, pNtkAig ); Abc_AigCleanup( (Abc_Aig_t *)pNtkAig->pManFunc ); // undo the required times if ( fSelective ) { Abc_NtkStopReverseLevels( pNtk ); Abc_NtkCleanMarkA( pNtk ); } if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkAig ) ) { printf( "Abc_NtkBalance: The network check has failed.\n" ); Abc_NtkDelete( pNtkAig ); return NULL; } //Abc_NtkPrintCiLevels( pNtkAig ); return pNtkAig; } /**Function************************************************************* Synopsis [Balances the AIG network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, int fDuplicate, int fSelective, int fUpdateLevel ) { ProgressBar * pProgress; Vec_Vec_t * vStorage; Abc_Obj_t * pNode; int i; // transfer level Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy->Level = pNode->Level; // set the level of PIs of AIG according to the arrival times of the old network Abc_NtkSetNodeLevelsArrival( pNtk ); // allocate temporary storage for supergates vStorage = Vec_VecStart( 10 ); // perform balancing of POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); if ( pNtk->nBarBufs == 0 ) { Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Abc_NodeBalance_rec( pNtkAig, Abc_ObjFanin0(pNode), vStorage, 0, fDuplicate, fSelective, fUpdateLevel ); } } else { Abc_NtkForEachLiPo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Abc_NodeBalance_rec( pNtkAig, Abc_ObjFanin0(pNode), vStorage, 0, fDuplicate, fSelective, fUpdateLevel ); if ( i < pNtk->nBarBufs ) Abc_ObjFanout0(Abc_ObjFanout0(pNode))->Level = Abc_ObjFanin0(pNode)->Level; } } Extra_ProgressBarStop( pProgress ); Vec_VecFree( vStorage ); } /**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 Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) { Abc_Obj_t * pNodeRight, * pNodeLeft; 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; pNodeRight = (Abc_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 pNodeLeft = (Abc_Obj_t *)Vec_PtrEntry( vSuper, Current ); // if the level of this node is different, quit the loop if ( Abc_ObjRegular(pNodeLeft)->Level != Abc_ObjRegular(pNodeRight)->Level ) break; } Current++; // get the node, for which the equality holds pNodeLeft = (Abc_Obj_t *)Vec_PtrEntry( vSuper, Current ); assert( Abc_ObjRegular(pNodeLeft)->Level == Abc_ObjRegular(pNodeRight)->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 Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBound ) { Abc_Obj_t * pNode1, * pNode2, * pNode3; int RightBound, i; // get the right bound RightBound = Vec_PtrSize(vSuper) - 2; assert( LeftBound <= RightBound ); if ( LeftBound == RightBound ) return; // get the two last nodes pNode1 = (Abc_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); pNode2 = (Abc_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); // find the first node that can be shared for ( i = RightBound; i >= LeftBound; i-- ) { pNode3 = (Abc_Obj_t *)Vec_PtrEntry( vSuper, i ); if ( Abc_AigAndLookup( (Abc_Aig_t *)pNtkNew->pManFunc, pNode1, pNode3 ) ) { if ( pNode3 == pNode2 ) return; Vec_PtrWriteEntry( vSuper, i, pNode2 ); Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); return; } } /* // we did not find the node to share, randomize choice { int Choice = rand() % (RightBound - LeftBound + 1); pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); if ( pNode3 == pNode2 ) return; Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 ); Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); } */ } /**Function************************************************************* Synopsis [Rebalances the multi-input node rooted at pNodeOld.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, int fDuplicate, int fSelective, int fUpdateLevel ) { Abc_Aig_t * pMan = (Abc_Aig_t *)pNtkNew->pManFunc; Abc_Obj_t * pNodeNew, * pNode1, * pNode2; Vec_Ptr_t * vSuper; int i, LeftBound; assert( !Abc_ObjIsComplement(pNodeOld) ); // return if the result if known if ( pNodeOld->pCopy ) return pNodeOld->pCopy; assert( Abc_ObjIsNode(pNodeOld) ); // get the implication supergate // Abc_NodeBalanceConeExor( pNodeOld ); vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, Level, fDuplicate, fSelective ); if ( vSuper->nSize == 0 ) { // it means that the supergate contains two nodes in the opposite polarity pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pNtkNew)); return pNodeOld->pCopy; } // for each old node, derive the new well-balanced node for ( i = 0; i < vSuper->nSize; i++ ) { pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular((Abc_Obj_t *)vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel ); vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement((Abc_Obj_t *)vSuper->pArray[i]) ); } if ( vSuper->nSize < 2 ) printf( "BUG!\n" ); // sort the new nodes by level in the decreasing order Vec_PtrSort( vSuper, (int (*)(void))Abc_NodeCompareLevelsDecrease ); // balance the nodes assert( vSuper->nSize > 1 ); while ( vSuper->nSize > 1 ) { // find the left bound on the node to be paired LeftBound = (!fUpdateLevel)? 0 : Abc_NodeBalanceFindLeft( vSuper ); // find the node that can be shared (if no such node, randomize choice) Abc_NodeBalancePermute( pNtkNew, vSuper, LeftBound ); // pull out the last two nodes pNode1 = (Abc_Obj_t *)Vec_PtrPop(vSuper); pNode2 = (Abc_Obj_t *)Vec_PtrPop(vSuper); Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) ); } // make sure the balanced node is not assigned assert( pNodeOld->pCopy == NULL ); // mark the old node with the new node pNodeOld->pCopy = (Abc_Obj_t *)vSuper->pArray[0]; vSuper->nSize = 0; // if ( Abc_ObjRegular(pNodeOld->pCopy) == Abc_AigConst1(pNtkNew) ) // printf( "Constant node\n" ); // assert( pNodeOld->Level >= Abc_ObjRegular(pNodeOld->pCopy)->Level ); return pNodeOld->pCopy; } /**Function************************************************************* Synopsis [Collects the nodes in the cone delimited by fMarkA==1.] Description [Returns -1 if the AND-cone has the same node in both polarities. Returns 1 if the AND-cone has the same node in the same polarity. Returns 0 if the AND-cone has no repeated nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, int fSelective ) { Vec_Ptr_t * vNodes; int RetValue, i; assert( !Abc_ObjIsComplement(pNode) ); // extend the storage if ( Vec_VecSize( vStorage ) <= Level ) Vec_VecPush( vStorage, Level, 0 ); // get the temporary array of nodes vNodes = Vec_VecEntry( vStorage, Level ); Vec_PtrClear( vNodes ); // collect the nodes in the implication supergate RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate, fSelective ); assert( vNodes->nSize > 1 ); // unmark the visited nodes for ( i = 0; i < vNodes->nSize; i++ ) Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->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 [Collects the nodes in the cone delimited by fMarkA==1.] Description [Returns -1 if the AND-cone has the same node in both polarities. Returns 1 if the AND-cone has the same node in the same polarity. Returns 0 if the AND-cone has no repeated nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fDuplicate, int fSelective ) { int RetValue1, RetValue2, i; // check if the node is visited if ( Abc_ObjRegular(pNode)->fMarkB ) { // check if the node occurs in the same polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == pNode ) return 1; // check if the node is present in the opposite polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) return -1; assert( 0 ); return 0; } // if the new node is complemented or a PI, another gate begins if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || (!fDuplicate && !fSelective && (Abc_ObjFanoutNum(pNode) > 1)) || Vec_PtrSize(vSuper) > 10000) ) { Vec_PtrPush( vSuper, pNode ); Abc_ObjRegular(pNode)->fMarkB = 1; return 0; } assert( !Abc_ObjIsComplement(pNode) ); assert( Abc_ObjIsNode(pNode) ); // go through the branches RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate, fSelective ); RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate, fSelective ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; // return 1 if at least one branch has a duplicate return RetValue1 || RetValue2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeBalanceConeExor_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst ) { int RetValue1, RetValue2, i; // check if the node occurs in the same polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == pNode ) return 1; // if the new node is complemented or a PI, another gate begins if ( !fFirst && (!pNode->fExor || !Abc_ObjIsNode(pNode)) ) { Vec_PtrPush( vSuper, pNode ); return 0; } assert( !Abc_ObjIsComplement(pNode) ); assert( Abc_ObjIsNode(pNode) ); assert( pNode->fExor ); // go through the branches RetValue1 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin0(Abc_ObjFanin0(pNode)), vSuper, 0 ); RetValue2 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin1(Abc_ObjFanin0(pNode)), vSuper, 0 ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; // return 1 if at least one branch has a duplicate return RetValue1 || RetValue2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ) { Vec_Ptr_t * vSuper; if ( !pNode->fExor ) return NULL; vSuper = Vec_PtrAlloc( 10 ); Abc_NodeBalanceConeExor_rec( pNode, vSuper, 1 ); printf( "%d ", Vec_PtrSize(vSuper) ); Vec_PtrFree( vSuper ); return NULL; } /**Function************************************************************* Synopsis [Collects the nodes in the implication supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeFindCone_rec( Abc_Obj_t * pNode ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNodeC, * pNodeT, * pNodeE; int RetValue, i; assert( !Abc_ObjIsComplement(pNode) ); if ( Abc_ObjIsCi(pNode) ) return NULL; // start the new array vNodes = Vec_PtrAlloc( 4 ); // if the node is the MUX collect its fanins if ( Abc_NodeIsMuxType(pNode) ) { pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); Vec_PtrPush( vNodes, Abc_ObjRegular(pNodeC) ); Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeT) ); Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeE) ); } else { // collect the nodes in the implication supergate RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, 1, 0 ); assert( vNodes->nSize > 1 ); // unmark the visited nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) Abc_ObjRegular(pNode)->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; } // call for the fanin Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { pNode = Abc_ObjRegular(pNode); if ( pNode->pCopy ) continue; pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode ); } return vNodes; } /**Function************************************************************* Synopsis [Attaches the implication supergates to internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachCo( pNtk, pNode, i ) { pNode = Abc_ObjFanin0(pNode); if ( pNode->pCopy ) continue; pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode ); } } /**Function************************************************************* Synopsis [Attaches the implication supergates to internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; Abc_NtkForEachNode( pNtk, pNode, i ) if ( pNode->pCopy ) { Vec_PtrFree( (Vec_Ptr_t *)pNode->pCopy ); pNode->pCopy = NULL; } } /**Function************************************************************* Synopsis [Compute levels of implication supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkBalanceLevel_rec( Abc_Obj_t * pNode ) { Vec_Ptr_t * vSuper; Abc_Obj_t * pFanin; int i, LevelMax; assert( !Abc_ObjIsComplement(pNode) ); if ( pNode->Level > 0 ) return pNode->Level; if ( Abc_ObjIsCi(pNode) ) return 0; vSuper = (Vec_Ptr_t *)pNode->pCopy; assert( vSuper != NULL ); LevelMax = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vSuper, pFanin, i ) { pFanin = Abc_ObjRegular(pFanin); Abc_NtkBalanceLevel_rec(pFanin); if ( LevelMax < (int)pFanin->Level ) LevelMax = pFanin->Level; } pNode->Level = LevelMax + 1; return pNode->Level; } /**Function************************************************************* Synopsis [Compute levels of implication supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBalanceLevel( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; Abc_NtkForEachObj( pNtk, pNode, i ) pNode->Level = 0; Abc_NtkForEachCo( pNtk, pNode, i ) Abc_NtkBalanceLevel_rec( Abc_ObjFanin0(pNode) ); } /**Function************************************************************* Synopsis [Marks the nodes on the critical and near critical paths.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= 1 ) pNode->fMarkA = 1, Counter++; printf( "The number of nodes on the critical paths = %6d (%5.2f %%)\n", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcBidec.c000066400000000000000000000120141300674244400234620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcBidec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface to bi-decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "bool/bdc/bdc.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Resynthesizes nodes using bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ) { unsigned * pTruth; Bdc_Fun_t * pFunc; int nNodes, i; assert( nVars <= 16 ); // derive truth table pTruth = Hop_ManConvertAigToTruth( pHop, Hop_Regular(pRoot), nVars, vTruth, 0 ); if ( Hop_IsComplement(pRoot) ) Extra_TruthNot( pTruth, pTruth, nVars ); // perform power-aware decomposition if ( dProb >= 0.0 ) { float Prob = (float)2.0 * dProb * (1.0 - dProb); assert( Prob >= 0.0 && Prob <= 0.5 ); if ( Prob >= 0.4 ) { Extra_TruthNot( puCare, puCare, nVars ); if ( dProb > 0.5 ) // more 1s than 0s Extra_TruthOr( pTruth, pTruth, puCare, nVars ); else Extra_TruthSharp( pTruth, pTruth, puCare, nVars ); Extra_TruthNot( puCare, puCare, nVars ); // decompose truth table Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 ); } else { // decompose truth table Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); } } else { // decompose truth table Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); } // convert back into HOP Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) ); for ( i = 0; i < nVars; i++ ) Bdc_FuncSetCopy( Bdc_ManFunc( p, i+1 ), Hop_ManPi( pHop, i ) ); nNodes = Bdc_ManNodeNum(p); for ( i = nVars + 1; i < nNodes; i++ ) { pFunc = Bdc_ManFunc( p, i ); Bdc_FuncSetCopy( pFunc, Hop_And( pHop, Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) ); } return Bdc_FunCopyHop( Bdc_ManRoot(p) ); } /**Function************************************************************* Synopsis [Resynthesizes nodes using bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ) { Bdc_Par_t Pars = {0}, * pPars = &Pars; Bdc_Man_t * p; Abc_Obj_t * pObj; Vec_Int_t * vTruth; int i, nGainTotal = 0, nNodes1, nNodes2; abctime clk = Abc_Clock(); assert( Abc_NtkIsLogic(pNtk) ); if ( !Abc_NtkToAig(pNtk) ) return; pPars->nVarsMax = Abc_NtkGetFaninMax( pNtk ); pPars->fVerbose = fVerbose; if ( pPars->nVarsMax > 15 ) { if ( fVerbose ) printf( "Resynthesis is not performed for nodes with more than 15 inputs.\n" ); pPars->nVarsMax = 15; } vTruth = Vec_IntAlloc( 0 ); p = Bdc_ManAlloc( pPars ); Abc_NtkForEachNode( pNtk, pObj, i ) { if ( Abc_ObjFaninNum(pObj) > 15 ) continue; nNodes1 = Hop_DagSize((Hop_Obj_t *)pObj->pData); pObj->pData = Abc_NodeIfNodeResyn( p, (Hop_Man_t *)pNtk->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj), vTruth, NULL, -1.0 ); nNodes2 = Hop_DagSize((Hop_Obj_t *)pObj->pData); nGainTotal += nNodes1 - nNodes2; } Bdc_ManFree( p ); Vec_IntFree( vTruth ); if ( fVerbose ) { printf( "Total gain in AIG nodes = %d. ", nGainTotal ); ABC_PRT( "Total runtime", Abc_Clock() - clk ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcBm.c000066400000000000000000001720721300674244400230250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Boolean Matching package.] Synopsis [Check P-equivalence and PP-equivalence of two circuits.] Author [Hadi Katebi] Affiliation [University of Michigan] Date [Ver. 1.0. Started - January, 2009.] Revision [No revisions so far] Comments [This is the cleaned up version of the code I used for DATE 2010 publication.] [If you have any question or if you find a bug, contact me at hadik@umich.edu.] [I don't guarantee that I can fix all the bugs, but I can definitely point you to the right direction so you can fix the bugs yourself]. Debugging [There are some part of the code that are commented out. Those parts mostly print the contents of the data structures to the standard output. Un-comment them if you find them useful for debugging.] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/sim/sim.h" #include "sat/bsat/satSolver.h" //#include "bdd/extrab/extraBdd.h" ABC_NAMESPACE_IMPL_START #define FALSE 0 #define TRUE 1 int match1by1(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1, Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton, int ii, int idx); int Abc_NtkBmSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iMatchPairs, Vec_Ptr_t * oMatchPairs, Vec_Int_t * mismatch, int mode); void getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep) { Vec_Ptr_t * vSuppFun; int i, j; vSuppFun = Sim_ComputeFunSupp(pNtk, 0); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { char * seg = (char *)vSuppFun->pArray[i]; for(j = 0; j < Abc_NtkPiNum(pNtk); j+=8) { if(((*seg) & 0x01) == 0x01) Vec_IntPushOrder(oDep[i], j); if(((*seg) & 0x02) == 0x02) Vec_IntPushOrder(oDep[i], j+1); if(((*seg) & 0x04) == 0x04) Vec_IntPushOrder(oDep[i], j+2); if(((*seg) & 0x08) == 0x08) Vec_IntPushOrder(oDep[i], j+3); if(((*seg) & 0x10) == 0x10) Vec_IntPushOrder(oDep[i], j+4); if(((*seg) & 0x20) == 0x20) Vec_IntPushOrder(oDep[i], j+5); if(((*seg) & 0x40) == 0x40) Vec_IntPushOrder(oDep[i], j+6); if(((*seg) & 0x80) == 0x80) Vec_IntPushOrder(oDep[i], j+7); seg++; } } for(i = 0; i < Abc_NtkPoNum(pNtk); i++) for(j = 0; j < Vec_IntSize(oDep[i]); j++) Vec_IntPush(iDep[Vec_IntEntry(oDep[i], j)], i); /*for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { printf("Output %d: ", i); for(j = 0; j < Vec_IntSize(oDep[i]); j++) printf("%d ", Vec_IntEntry(oDep[i], j)); printf("\n"); } printf("\n"); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) { printf("Input %d: ", i); for(j = 0; j < Vec_IntSize(iDep[i]); j++) printf("%d ", Vec_IntEntry(iDep[i], j)); printf("\n"); } printf("\n"); */ } void initMatchList(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep, Vec_Int_t** iMatch, int* iLastItem, Vec_Int_t** oMatch, int* oLastItem, int* iGroup, int* oGroup, int p_equivalence) { int i, j, curr; Vec_Int_t** temp; if(!p_equivalence) { temp = ABC_ALLOC( Vec_Int_t*, Abc_NtkPiNum(pNtk)+1); for(i = 0; i < Abc_NtkPiNum(pNtk)+1; i++) temp[i] = Vec_IntAlloc( 0 ); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) Vec_IntPush(temp[Vec_IntSize(oDep[i])], i); curr = 0; for(i = 0; i < Abc_NtkPiNum(pNtk)+1; i++) { if(Vec_IntSize(temp[i]) == 0) Vec_IntFree( temp[i] ); else { oMatch[curr] = temp[i]; for(j = 0; j < Vec_IntSize(temp[i]); j++) oGroup[Vec_IntEntry(oMatch[curr], j)] = curr; curr++; } } *oLastItem = curr; ABC_FREE( temp ); } else { // the else part fixes the outputs for P-equivalence checking for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { Vec_IntPush(oMatch[i], i); oGroup[i] = i; (*oLastItem) = Abc_NtkPoNum(pNtk); } } /*for(j = 0; j < *oLastItem; j++) { printf("oMatch %d: ", j); for(i = 0; i < Vec_IntSize(oMatch[j]); i++) printf("%d ", Vec_IntEntry(oMatch[j], i)); printf("\n"); } for(i = 0; i < Abc_NtkPoNum(pNtk); i++) printf("%d: %d ", i, oGroup[i]);*/ ////////////////////////////////////////////////////////////////////////////// temp = ABC_ALLOC( Vec_Int_t*, Abc_NtkPoNum(pNtk)+1 ); for(i = 0; i < Abc_NtkPoNum(pNtk)+1; i++) temp[i] = Vec_IntAlloc( 0 ); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) Vec_IntPush(temp[Vec_IntSize(iDep[i])], i); curr = 0; for(i = 0; i < Abc_NtkPoNum(pNtk)+1; i++) { if(Vec_IntSize(temp[i]) == 0) Vec_IntFree( temp[i] ); else { iMatch[curr] = temp[i]; for(j = 0; j < Vec_IntSize(iMatch[curr]); j++) iGroup[Vec_IntEntry(iMatch[curr], j)] = curr; curr++; } } *iLastItem = curr; ABC_FREE( temp ); /*printf("\n"); for(j = 0; j < *iLastItem; j++) { printf("iMatch %d: ", j); for(i = 0; i < Vec_IntSize(iMatch[j]); i++) printf("%d ", Vec_IntEntry(iMatch[j], i)); printf("\n"); } for(i = 0; i < Abc_NtkPiNum(pNtk); i++) printf("%d: %d ", i, iGroup[i]); printf("\n");*/ } void iSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, int* oGroup) { int i, j, k; Vec_Int_t * temp; Vec_Int_t * oGroupList; oGroupList = Vec_IntAlloc( 10 ); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) { if(Vec_IntSize(iDep[i]) == 1) continue; temp = Vec_IntAlloc( Vec_IntSize(iDep[i]) ); for(j = 0; j < Vec_IntSize(iDep[i]); j++) Vec_IntPushUniqueOrder(oGroupList, oGroup[Vec_IntEntry(iDep[i], j)]); for(j = 0; j < Vec_IntSize(oGroupList); j++) { for(k = 0; k < Vec_IntSize(iDep[i]); k++) if(oGroup[Vec_IntEntry(iDep[i], k)] == Vec_IntEntry(oGroupList, j)) { Vec_IntPush( temp, Vec_IntEntry(iDep[i], k) ); Vec_IntRemove( iDep[i], Vec_IntEntry(iDep[i], k) ); k--; } } Vec_IntFree( iDep[i] ); iDep[i] = temp; Vec_IntClear( oGroupList ); /*printf("Input %d: ", i); for(j = 0; j < Vec_IntSize(iDep[i]); j++) printf("%d ", Vec_IntEntry(iDep[i], j)); printf("\n");*/ } Vec_IntFree( oGroupList ); } void oSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, int* iGroup) { int i, j, k; Vec_Int_t * temp; Vec_Int_t * iGroupList; iGroupList = Vec_IntAlloc( 10 ); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { if(Vec_IntSize(oDep[i]) == 1) continue; temp = Vec_IntAlloc( Vec_IntSize(oDep[i]) ); for(j = 0; j < Vec_IntSize(oDep[i]); j++) Vec_IntPushUniqueOrder(iGroupList, iGroup[Vec_IntEntry(oDep[i], j)]); for(j = 0; j < Vec_IntSize(iGroupList); j++) { for(k = 0; k < Vec_IntSize(oDep[i]); k++) if(iGroup[Vec_IntEntry(oDep[i], k)] == Vec_IntEntry(iGroupList, j)) { Vec_IntPush( temp, Vec_IntEntry(oDep[i], k) ); Vec_IntRemove( oDep[i], Vec_IntEntry(oDep[i], k) ); k--; } } Vec_IntFree( oDep[i] ); oDep[i] = temp; Vec_IntClear( iGroupList ); /*printf("Output %d: ", i); for(j = 0; j < Vec_IntSize(oDep[i]); j++) printf("%d ", Vec_IntEntry(oDep[i], j)); printf("\n");*/ } Vec_IntFree( iGroupList ); } int oSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, Vec_Int_t** oMatch, int* oGroup, int* oLastItem, int* iGroup) { int i, j, k; int numOfItemsAdded; Vec_Int_t * array, * sortedArray; numOfItemsAdded = 0; for(i = 0; i < *oLastItem; i++) { if(Vec_IntSize(oMatch[i]) == 1) continue; array = Vec_IntAlloc( Vec_IntSize(oMatch[i]) ); sortedArray = Vec_IntAlloc( Vec_IntSize(oMatch[i]) ); for(j = 0; j < Vec_IntSize(oMatch[i]); j++) { int factor, encode; encode = 0; factor = 1; for(k = 0; k < Vec_IntSize(oDep[Vec_IntEntry(oMatch[i], j)]); k++) encode += iGroup[Vec_IntEntry(oDep[Vec_IntEntry(oMatch[i], j)], k)] * factor; Vec_IntPush(array, encode); Vec_IntPushUniqueOrder(sortedArray, encode); if( encode < 0) printf("WARNING! Integer overflow!"); //printf("%d ", Vec_IntEntry(array, j)); } while( Vec_IntSize(sortedArray) > 1 ) { for(k = 0; k < Vec_IntSize(oMatch[i]); k++) { if(Vec_IntEntry(array, k) == Vec_IntEntryLast(sortedArray)) { Vec_IntPush(oMatch[*oLastItem+numOfItemsAdded], Vec_IntEntry(oMatch[i], k)); oGroup[Vec_IntEntry(oMatch[i], k)] = *oLastItem+numOfItemsAdded; Vec_IntRemove( oMatch[i], Vec_IntEntry(oMatch[i], k) ); Vec_IntRemove( array, Vec_IntEntry(array, k) ); k--; } } numOfItemsAdded++; Vec_IntPop(sortedArray); } Vec_IntFree( array ); Vec_IntFree( sortedArray ); //printf("\n"); } *oLastItem += numOfItemsAdded; /*printf("\n"); for(j = 0; j < *oLastItem ; j++) { printf("oMatch %d: ", j); for(i = 0; i < Vec_IntSize(oMatch[j]); i++) printf("%d ", Vec_IntEntry(oMatch[j], i)); printf("\n"); }*/ return numOfItemsAdded; } int iSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** iMatch, int* iGroup, int* iLastItem, int* oGroup) { int i, j, k; int numOfItemsAdded = 0; Vec_Int_t * array, * sortedArray; for(i = 0; i < *iLastItem; i++) { if(Vec_IntSize(iMatch[i]) == 1) continue; array = Vec_IntAlloc( Vec_IntSize(iMatch[i]) ); sortedArray = Vec_IntAlloc( Vec_IntSize(iMatch[i]) ); for(j = 0; j < Vec_IntSize(iMatch[i]); j++) { int factor, encode; encode = 0; factor = 1; for(k = 0; k < Vec_IntSize(iDep[Vec_IntEntry(iMatch[i], j)]); k++) encode += oGroup[Vec_IntEntry(iDep[Vec_IntEntry(iMatch[i], j)], k)] * factor; Vec_IntPush(array, encode); Vec_IntPushUniqueOrder(sortedArray, encode); //printf("%d ", Vec_IntEntry(array, j)); } while( Vec_IntSize(sortedArray) > 1 ) { for(k = 0; k < Vec_IntSize(iMatch[i]); k++) { if(Vec_IntEntry(array, k) == Vec_IntEntryLast(sortedArray)) { Vec_IntPush(iMatch[*iLastItem+numOfItemsAdded], Vec_IntEntry(iMatch[i], k)); iGroup[Vec_IntEntry(iMatch[i], k)] = *iLastItem+numOfItemsAdded; Vec_IntRemove( iMatch[i], Vec_IntEntry(iMatch[i], k) ); Vec_IntRemove( array, Vec_IntEntry(array, k) ); k--; } } numOfItemsAdded++; Vec_IntPop(sortedArray); } Vec_IntFree( array ); Vec_IntFree( sortedArray ); //printf("\n"); } *iLastItem += numOfItemsAdded; /*printf("\n"); for(j = 0; j < *iLastItem ; j++) { printf("iMatch %d: ", j); for(i = 0; i < Vec_IntSize(iMatch[j]); i++) printf("%d ", Vec_IntEntry(iMatch[j], i)); printf("\n"); }*/ return numOfItemsAdded; } Vec_Ptr_t ** findTopologicalOrder( Abc_Ntk_t * pNtk ) { Vec_Ptr_t ** vNodes; Abc_Obj_t * pObj, * pFanout; int i, k; extern void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); // start the array of nodes vNodes = ABC_ALLOC(Vec_Ptr_t *, Abc_NtkPiNum(pNtk)); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) vNodes[i] = Vec_PtrAlloc(50); Abc_NtkForEachCi( pNtk, pObj, i ) { // set the traversal ID Abc_NtkIncrementTravId( pNtk ); Abc_NodeSetTravIdCurrent( pObj ); pObj = Abc_ObjFanout0Ntk(pObj); Abc_ObjForEachFanout( pObj, pFanout, k ) Abc_NtkDfsReverse_rec( pFanout, vNodes[i] ); } return vNodes; } int * Abc_NtkSimulateOneNode( Abc_Ntk_t * pNtk, int * pModel, int input, Vec_Ptr_t ** topOrder ) { Abc_Obj_t * pNode; Vec_Ptr_t * vNodes; int * pValues, Value0, Value1, i; vNodes = Vec_PtrAlloc( 50 ); /* printf( "Counter example: " ); Abc_NtkForEachCi( pNtk, pNode, i ) printf( " %d", pModel[i] ); printf( "\n" ); */ // increment the trav ID Abc_NtkIncrementTravId( pNtk ); // set the CI values Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)1; pNode = Abc_NtkCi(pNtk, input); pNode->iTemp = pModel[input]; // simulate in the topological order for(i = Vec_PtrSize(topOrder[input])-1; i >= 0; i--) { pNode = (Abc_Obj_t *)Vec_PtrEntry(topOrder[input], i); Value0 = ((int)(ABC_PTRUINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); Value1 = ((int)(ABC_PTRUINT_T)Abc_ObjFanin1(pNode)->pCopy) ^ Abc_ObjFaninC1(pNode); if( pNode->iTemp != (Value0 & Value1)) { pNode->iTemp = (Value0 & Value1); Vec_PtrPush(vNodes, pNode); } } // fill the output values pValues = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) pValues[i] = ((int)(ABC_PTRUINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); pNode = Abc_NtkCi(pNtk, input); if(pNode->pCopy == (Abc_Obj_t *)1) pNode->pCopy = (Abc_Obj_t *)0; else pNode->pCopy = (Abc_Obj_t *)1; for(i = 0; i < Vec_PtrSize(vNodes); i++) { pNode = (Abc_Obj_t *)Vec_PtrEntry(vNodes, i); if(pNode->pCopy == (Abc_Obj_t *)1) pNode->pCopy = (Abc_Obj_t *)0; else pNode->pCopy = (Abc_Obj_t *)1; } Vec_PtrFree( vNodes ); return pValues; } int refineIOBySimulation(Abc_Ntk_t *pNtk, Vec_Int_t** iMatch, int* iLastItem, int * iGroup, Vec_Int_t** iDep, Vec_Int_t** oMatch, int* oLastItem, int * oGroup, Vec_Int_t** oDep, char * vPiValues, int * observability, Vec_Ptr_t ** topOrder) { Abc_Obj_t * pObj; int * pModel;//, ** pModel2; int * output, * output2; int lastItem; int i, j, k; Vec_Int_t * iComputedNum, * iComputedNumSorted; Vec_Int_t * oComputedNum; // encoding the number of flips int factor; int isRefined = FALSE; pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) pModel[i] = vPiValues[i] - '0'; Abc_NtkForEachLatch( pNtk, pObj, i ) pModel[Abc_NtkPiNum(pNtk)+i] = pObj->iData - 1; output = Abc_NtkVerifySimulatePattern( pNtk, pModel ); oComputedNum = Vec_IntAlloc( Abc_NtkPoNum(pNtk) ); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) Vec_IntPush(oComputedNum, 0); /****************************************************************************************/ /********** group outputs that produce 1 and outputs that produce 0 together ************/ lastItem = *oLastItem; for(i = 0; i < lastItem && (*oLastItem) != Abc_NtkPoNum(pNtk); i++) { int flag = FALSE; if(Vec_IntSize(oMatch[i]) == 1) continue; for(j = 1; j < Vec_IntSize(oMatch[i]); j++) if(output[Vec_IntEntry(oMatch[i], 0)] != output[Vec_IntEntry(oMatch[i], j)]) { flag = TRUE; break; } if(flag) { for(j = 0; j < Vec_IntSize(oMatch[i]); j++) if(output[Vec_IntEntry(oMatch[i], j)]) { Vec_IntPush(oMatch[*oLastItem], Vec_IntEntry(oMatch[i], j)); oGroup[Vec_IntEntry(oMatch[i], j)] = *oLastItem; Vec_IntRemove(oMatch[i], Vec_IntEntry(oMatch[i], j)); j--; } (*oLastItem)++; } } if( (*oLastItem) > lastItem ) { isRefined = TRUE; iSortDependencies(pNtk, iDep, oGroup); } /****************************************************************************************/ /************* group inputs that make the same number of flips in outpus ****************/ lastItem = *iLastItem; for(i = 0; i < lastItem && (*iLastItem) != Abc_NtkPiNum(pNtk); i++) { int num; if(Vec_IntSize(iMatch[i]) == 1) continue; iComputedNum = Vec_IntAlloc( Vec_IntSize(iMatch[i]) ); iComputedNumSorted = Vec_IntAlloc( Vec_IntSize(iMatch[i]) ); for(j = 0; j < Vec_IntSize(iMatch[i]); j++) { if( vPiValues[Vec_IntEntry(iMatch[i], j)] == '0' ) pModel[Vec_IntEntry(iMatch[i], j)] = 1; else pModel[Vec_IntEntry(iMatch[i], j)] = 0; //output2 = Abc_NtkVerifySimulatePattern( pNtk, pModel ); output2 = Abc_NtkSimulateOneNode( pNtk, pModel, Vec_IntEntry(iMatch[i], j), topOrder ); num = 0; factor = 1; for(k = 0; k < Vec_IntSize(iDep[Vec_IntEntry(iMatch[i], j)]); k++) { int outputIndex = Vec_IntEntry(iDep[Vec_IntEntry(iMatch[i], j)], k); if(output2[outputIndex]) num += (oGroup[outputIndex] + 1) * factor; if(output[outputIndex] != output2[outputIndex]) { int temp = Vec_IntEntry(oComputedNum, outputIndex) + i + 1; Vec_IntWriteEntry(oComputedNum, outputIndex, temp); observability[Vec_IntEntry(iMatch[i], j)]++; } } Vec_IntPush(iComputedNum, num); Vec_IntPushUniqueOrder(iComputedNumSorted, num); pModel[Vec_IntEntry(iMatch[i], j)] = vPiValues[Vec_IntEntry(iMatch[i], j)] - '0'; ABC_FREE( output2 ); } while( Vec_IntSize( iComputedNumSorted ) > 1 ) { for(k = 0; k < Vec_IntSize(iMatch[i]); k++) { if(Vec_IntEntry(iComputedNum, k) == Vec_IntEntryLast(iComputedNumSorted) ) { Vec_IntPush(iMatch[*iLastItem], Vec_IntEntry(iMatch[i], k)); iGroup[Vec_IntEntry(iMatch[i], k)] = *iLastItem; Vec_IntRemove( iMatch[i], Vec_IntEntry(iMatch[i], k) ); Vec_IntRemove( iComputedNum, Vec_IntEntry(iComputedNum, k) ); k--; } } (*iLastItem)++; Vec_IntPop( iComputedNumSorted ); } Vec_IntFree( iComputedNum ); Vec_IntFree( iComputedNumSorted ); } if( (*iLastItem) > lastItem ) { isRefined = TRUE; oSortDependencies(pNtk, oDep, iGroup); } /****************************************************************************************/ /********** encode the number of flips in each output by flipping the outputs ***********/ /********** and group all the outputs that have the same encoding ***********/ lastItem = *oLastItem; for(i = 0; i < lastItem && (*oLastItem) != Abc_NtkPoNum(pNtk); i++) { Vec_Int_t * encode, * sortedEncode; // encoding the number of flips if(Vec_IntSize(oMatch[i]) == 1) continue; encode = Vec_IntAlloc( Vec_IntSize(oMatch[i]) ); sortedEncode = Vec_IntAlloc( Vec_IntSize(oMatch[i]) ); for(j = 0; j < Vec_IntSize(oMatch[i]); j++) { Vec_IntPush(encode, Vec_IntEntry(oComputedNum, Vec_IntEntry(oMatch[i], j)) ); Vec_IntPushUniqueOrder( sortedEncode, Vec_IntEntry(encode, j) ); } while( Vec_IntSize(sortedEncode) > 1 ) { for(j = 0; j < Vec_IntSize(oMatch[i]); j++) if(Vec_IntEntry(encode, j) == Vec_IntEntryLast(sortedEncode)) { Vec_IntPush(oMatch[*oLastItem], Vec_IntEntry(oMatch[i], j)); oGroup[Vec_IntEntry(oMatch[i], j)] = *oLastItem; Vec_IntRemove( oMatch[i], Vec_IntEntry(oMatch[i], j) ); Vec_IntRemove( encode, Vec_IntEntry(encode, j) ); j --; } (*oLastItem)++; Vec_IntPop( sortedEncode ); } Vec_IntFree( encode ); Vec_IntFree( sortedEncode ); } if( (*oLastItem) > lastItem ) isRefined = TRUE; ABC_FREE( pModel ); ABC_FREE( output ); Vec_IntFree( oComputedNum ); return isRefined; } Abc_Ntk_t * Abc_NtkMiterBm( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iCurrMatch, Vec_Ptr_t * oCurrMatch ) { char Buffer[1000]; Abc_Ntk_t * pNtkMiter; pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); pNtkMiter->pName = Extra_UtilStrsav(Buffer); //Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); { Abc_Obj_t * pObj, * pObjNew; int i; Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter); Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter); // create new PIs and remember them in the old PIs if(iCurrMatch == NULL) { Abc_NtkForEachCi( pNtk1, pObj, i ) { pObjNew = Abc_NtkCreatePi( pNtkMiter ); // remember this PI in the old PIs pObj->pCopy = pObjNew; pObj = Abc_NtkCi(pNtk2, i); pObj->pCopy = pObjNew; // add name Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } } else { for(i = 0; i < Vec_PtrSize( iCurrMatch ); i += 2) { pObjNew = Abc_NtkCreatePi( pNtkMiter ); pObj = (Abc_Obj_t *)Vec_PtrEntry(iCurrMatch, i); pObj->pCopy = pObjNew; pObj = (Abc_Obj_t *)Vec_PtrEntry(iCurrMatch, i+1); pObj->pCopy = pObjNew; // add name Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } } // create the only PO pObjNew = Abc_NtkCreatePo( pNtkMiter ); // add the PO name Abc_ObjAssignName( pObjNew, "miter", NULL ); } // Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsDfsOrdered(pNtk1) ); Abc_AigForEachAnd( pNtk1, pNode, i ) pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } // Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsDfsOrdered(pNtk2) ); Abc_AigForEachAnd( pNtk2, pNode, i ) pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } // Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); { Vec_Ptr_t * vPairs; Abc_Obj_t * pMiter; int i; vPairs = Vec_PtrAlloc( 100 ); // collect the CO nodes for the miter if(oCurrMatch != NULL) { for(i = 0; i < Vec_PtrSize( oCurrMatch ); i += 2) { Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oCurrMatch, i)) ); Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oCurrMatch, i+1)) ); } } else { Abc_Obj_t * pNode; Abc_NtkForEachCo( pNtk1, pNode, i ) { Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); pNode = Abc_NtkCo( pNtk2, i ); Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); } } pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairs, 0 ); Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); Vec_PtrFree(vPairs); } //Abc_AigCleanup(pNtkMiter->pManFunc); return pNtkMiter; } int * pValues1__, * pValues2__; void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, Vec_Int_t * mismatch ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int nErrors, nPrinted, i, iNode = -1; assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) ); // get the CO values under this model pValues1__ = Abc_NtkVerifySimulatePattern( pNtk1, pModel ); pValues2__ = Abc_NtkVerifySimulatePattern( pNtk2, pModel ); // count the mismatches nErrors = 0; for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) nErrors += (int)( pValues1__[i] != pValues2__[i] ); //printf( "Verification failed for at least %d outputs: ", nErrors ); // print the first 3 outputs nPrinted = 0; for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) if ( pValues1__[i] != pValues2__[i] ) { if ( iNode == -1 ) iNode = i; //printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); if ( ++nPrinted == 3 ) break; } /*if ( nPrinted != nErrors ) printf( " ..." ); printf( "\n" );*/ // report mismatch for the first output if ( iNode >= 0 ) { /*printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] ); printf( "Input pattern: " );*/ // collect PIs in the cone pNode = Abc_NtkCo(pNtk1,iNode); vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 ); // set the PI numbers Abc_NtkForEachCi( pNtk1, pNode, i ) pNode->iTemp = i; // print the model pNode = (Abc_Obj_t *)Vec_PtrEntry( vNodes, 0 ); if ( Abc_ObjIsCi(pNode) ) { Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { assert( Abc_ObjIsCi(pNode) ); //printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)pNode->pCopy] ); Vec_IntPush(mismatch, Abc_ObjId(pNode)-1); Vec_IntPush(mismatch, pModel[(int)(size_t)pNode->pCopy]); } } //printf( "\n" ); Vec_PtrFree( vNodes ); } free( pValues1__ ); free( pValues2__ ); } int Abc_NtkMiterSatBm( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fVerbose, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects) { static sat_solver * pSat = NULL; lbool status; int RetValue; abctime clk; extern int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ); extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); if ( pNumConfs ) *pNumConfs = 0; if ( pNumInspects ) *pNumInspects = 0; assert( Abc_NtkLatchNum(pNtk) == 0 ); // if ( Abc_NtkPoNum(pNtk) > 1 ) // fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) ); // load clauses into the sat_solver clk = Abc_Clock(); pSat = (sat_solver *)Abc_NtkMiterSatCreate( pNtk, 0 ); if ( pSat == NULL ) return 1; //printf( "%d \n", pSat->clauses.size ); //sat_solver_delete( pSat ); //return 1; // printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); // PRT( "Time", Abc_Clock() - clk ); // simplify the problem clk = Abc_Clock(); status = sat_solver_simplify(pSat); // printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); // PRT( "Time", Abc_Clock() - clk ); if ( status == 0 ) { sat_solver_delete( pSat ); // printf( "The problem is UNSATISFIABLE after simplification.\n" ); return 1; } // solve the miter clk = Abc_Clock(); if ( fVerbose ) pSat->verbosity = 1; status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) { // printf( "The problem timed out.\n" ); RetValue = -1; } else if ( status == l_True ) { // printf( "The problem is SATISFIABLE.\n" ); RetValue = 0; } else if ( status == l_False ) { // printf( "The problem is UNSATISFIABLE.\n" ); RetValue = 1; } else assert( 0 ); // PRT( "SAT sat_solver time", Abc_Clock() - clk ); // printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); // if the problem is SAT, get the counterexample if ( status == l_True ) { // Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk ); Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); Vec_IntFree( vCiIds ); } // free the sat_solver if ( fVerbose ) Sat_SolverPrintStats( stdout, pSat ); if ( pNumConfs ) *pNumConfs = (int)pSat->stats.conflicts; if ( pNumInspects ) *pNumInspects = (int)pSat->stats.inspects; //sat_solver_store_write( pSat, "trace.cnf" ); sat_solver_store_free( pSat ); sat_solver_delete( pSat ); return RetValue; } int Abc_NtkBmSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Vec_Ptr_t * iMatchPairs, Vec_Ptr_t * oMatchPairs, Vec_Int_t * mismatch, int mode) { extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); Abc_Ntk_t * pMiter = NULL; Abc_Ntk_t * pCnf; int RetValue; // get the miter of the two networks if( mode == 0 ) { //Abc_NtkDelete( pMiter ); pMiter = Abc_NtkMiterBm( pNtk1, pNtk2, iMatchPairs, oMatchPairs ); } else if( mode == 1 ) // add new outputs { int i; Abc_Obj_t * pObj; Vec_Ptr_t * vPairs; Abc_Obj_t * pNtkMiter; vPairs = Vec_PtrAlloc( 100 ); Abc_NtkForEachCo( pMiter, pObj, i ) Abc_ObjRemoveFanins( pObj ); for(i = 0; i < Vec_PtrSize( oMatchPairs ); i += 2) { Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oMatchPairs, i)) ); Vec_PtrPush( vPairs, Abc_ObjChild0Copy((Abc_Obj_t *)Vec_PtrEntry(oMatchPairs, i+1)) ); } pNtkMiter = Abc_AigMiter( (Abc_Aig_t *)pMiter->pManFunc, vPairs, 0 ); Abc_ObjAddFanin( Abc_NtkPo(pMiter,0), pNtkMiter ); Vec_PtrFree( vPairs); } else if( mode == 2 ) // add some outputs { } else if( mode == 3) // remove all outputs { } if ( pMiter == NULL ) { printf("Miter computation has failed."); return -1; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0) { /*printf("Networks are NOT EQUIVALENT after structural hashing."); */ // report the error if(mismatch != NULL) { pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel, mismatch ); ABC_FREE( pMiter->pModel ); } Abc_NtkDelete( pMiter ); return RetValue; } if( RetValue == 1 ) { /*printf("Networks are equivalent after structural hashing."); */ Abc_NtkDelete( pMiter ); return RetValue; } // convert the miter into a CNF //if(mode == 0) pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); Abc_NtkDelete( pMiter ); if ( pCnf == NULL ) { printf("Renoding for CNF has failed."); return -1; } // solve the CNF using the SAT solver RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)10000, (ABC_INT64_T)0, 0, NULL, NULL); /*if ( RetValue == -1 ) printf("Networks are undecided (SAT solver timed out)."); else if ( RetValue == 0 ) printf("Networks are NOT EQUIVALENT after SAT."); else printf("Networks are equivalent after SAT."); */ if ( mismatch != NULL && pCnf->pModel ) Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel, mismatch ); ABC_FREE( pCnf->pModel ); Abc_NtkDelete( pCnf ); return RetValue; } int checkEquivalence( Abc_Ntk_t * pNtk1, Vec_Int_t* matchedInputs1, Vec_Int_t * matchedOutputs1, Abc_Ntk_t * pNtk2, Vec_Int_t* matchedInputs2, Vec_Int_t * matchedOutputs2) { Vec_Ptr_t * iMatchPairs, * oMatchPairs; int i; int result; iMatchPairs = Vec_PtrAlloc( Abc_NtkPiNum( pNtk1 ) * 2); oMatchPairs = Vec_PtrAlloc( Abc_NtkPoNum( pNtk1 ) * 2); for(i = 0; i < Abc_NtkPiNum(pNtk1); i++) { Vec_PtrPush(iMatchPairs, Abc_NtkPi(pNtk2, Vec_IntEntry(matchedInputs2, i))); Vec_PtrPush(iMatchPairs, Abc_NtkPi(pNtk1, Vec_IntEntry(matchedInputs1, i))); } for(i = 0; i < Abc_NtkPoNum(pNtk1); i++) { Vec_PtrPush(oMatchPairs, Abc_NtkPo(pNtk2, Vec_IntEntry(matchedOutputs2, i))); Vec_PtrPush(oMatchPairs, Abc_NtkPo(pNtk1, Vec_IntEntry(matchedOutputs1, i))); } result = Abc_NtkBmSat(pNtk1, pNtk2, iMatchPairs, oMatchPairs, NULL, 0); if( result ) printf("*** Circuits are equivalent ***\n"); else printf("*** Circuits are NOT equivalent ***\n"); Vec_PtrFree( iMatchPairs ); Vec_PtrFree( oMatchPairs ); return result; } Abc_Ntk_t * computeCofactor(Abc_Ntk_t * pNtk, Vec_Ptr_t ** nodesInLevel, int * bitVector, Vec_Int_t * currInputs) { Abc_Ntk_t * subNtk; Abc_Obj_t * pObj, * pObjNew; int i, j, numOfLevels; numOfLevels = Abc_AigLevel( pNtk ); // number of levels excludes PI/POs // start a new network subNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); subNtk->pName = Extra_UtilStrsav("subNtk"); Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(subNtk); // clean the node copy fields and mark the nodes that need to be copied to the new network Abc_NtkCleanCopy( pNtk ); if(bitVector != NULL) { for(i = 0; i < Abc_NtkPiNum(pNtk); i++) if(bitVector[i]) { pObj = Abc_NtkPi(pNtk, i); pObj->pCopy = (Abc_Obj_t *)(1); } } for(i = 0; i < Vec_IntSize(currInputs); i++) { pObj = Abc_NtkPi(pNtk, Vec_IntEntry(currInputs, i)); pObjNew = Abc_NtkDupObj( subNtk, pObj, 1 ); pObj->pCopy = pObjNew; } // i = 0 are the inputs and the inputs are not added to the 2d array ( nodesInLevel ) for( i = 0; i <= numOfLevels; i++ ) for( j = 0; j < Vec_PtrSize( nodesInLevel[i] ); j++) { pObj = (Abc_Obj_t *)Vec_PtrEntry( nodesInLevel[i], j ); if(Abc_ObjChild0Copy(pObj) == NULL && Abc_ObjChild1Copy(pObj) == NULL) pObj->pCopy = NULL; else if(Abc_ObjChild0Copy(pObj) == NULL && Abc_ObjChild1Copy(pObj) == (void*)(1)) pObj->pCopy = NULL; else if(Abc_ObjChild0Copy(pObj) == NULL && (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) ) pObj->pCopy = NULL; else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && Abc_ObjChild1Copy(pObj) == NULL) pObj->pCopy = NULL; else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && Abc_ObjChild1Copy(pObj) == (void*)(1)) pObj->pCopy = (Abc_Obj_t *)(1); else if(Abc_ObjChild0Copy(pObj) == (void*)(1) && (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) ) pObj->pCopy = Abc_ObjChild1Copy(pObj); else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) && Abc_ObjChild1Copy(pObj) == NULL ) pObj->pCopy = NULL; else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) && Abc_ObjChild1Copy(pObj) == (void*)(1) ) pObj->pCopy = Abc_ObjChild0Copy(pObj); else if( (Abc_ObjChild0Copy(pObj) != (NULL) && Abc_ObjChild0Copy(pObj) != (void*)(1)) && (Abc_ObjChild1Copy(pObj) != (NULL) && Abc_ObjChild1Copy(pObj) != (void*)(1)) ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)subNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); } for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { pObj = Abc_NtkPo(pNtk, i); pObjNew = Abc_NtkDupObj( subNtk, pObj, 1 ); if( Abc_ObjChild0Copy(pObj) == NULL) { Abc_ObjAddFanin( pObjNew, Abc_AigConst1(subNtk)); pObjNew->fCompl0 = 1; } else if( Abc_ObjChild0Copy(pObj) == (void*)(1) ) { Abc_ObjAddFanin( pObjNew, Abc_AigConst1(subNtk)); pObjNew->fCompl0 = 0; } else Abc_ObjAddFanin( pObjNew, Abc_ObjChild0Copy(pObj) ); } return subNtk; } FILE *matchFile; int matchNonSingletonOutputs(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1, Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton, Abc_Ntk_t * subNtk1, Abc_Ntk_t * subNtk2, Vec_Ptr_t * oMatchPairs, Vec_Int_t * oNonSingleton, int oI, int idx, int ii, int iidx) { static int MATCH_FOUND; int i; int j, temp; Vec_Int_t * mismatch; int * skipList; static int counter = 0; MATCH_FOUND = FALSE; if( oI == Vec_IntSize( oNonSingleton ) ) { if( iNonSingleton != NULL) if( match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, ii, iidx) ) MATCH_FOUND = TRUE; if( iNonSingleton == NULL) MATCH_FOUND = TRUE; return MATCH_FOUND; } i = Vec_IntEntry(oNonSingleton, oI); mismatch = Vec_IntAlloc(10); skipList = ABC_ALLOC(int, Vec_IntSize(oMatch1[i])); for(j = 0; j < Vec_IntSize(oMatch1[i]); j++) skipList[j] = FALSE; Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk1, Vec_IntEntry(oMatch1[i], idx)) ); Vec_IntPush(matchedOutputs1, Vec_IntEntry(oMatch1[i], idx)); for(j = 0; j < Vec_IntSize( oMatch2[i] ) && MATCH_FOUND == FALSE; j++) { if( Vec_IntEntry(oMatch2[i], j) == -1 || skipList[j] == TRUE) continue; Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk2, Vec_IntEntry(oMatch2[i], j))); Vec_IntPush(matchedOutputs2, Vec_IntEntry(oMatch2[i], j)); counter++; if( Abc_NtkBmSat( subNtk1, subNtk2, NULL, oMatchPairs, mismatch, 0) ) { /*fprintf(matchFile, "%s matched to %s\n", Abc_ObjName(Abc_NtkPo(pNtk1, Vec_IntEntry(oMatch1[i], idx))), Abc_ObjName(Abc_NtkPo(pNtk2, Vec_IntEntry(oMatch2[i], j)))); */ temp = Vec_IntEntry(oMatch2[i], j); Vec_IntWriteEntry(oMatch2[i], j, -1); if(idx != Vec_IntSize( oMatch1[i] ) - 1) // call the same function with idx+1 matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, subNtk1, subNtk2, oMatchPairs, oNonSingleton, oI, idx+1, ii, iidx); else // call the same function with idx = 0 and oI++ matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, subNtk1, subNtk2, oMatchPairs, oNonSingleton, oI+1, 0, ii, iidx); Vec_IntWriteEntry(oMatch2[i], j, temp); } else { int * output1, * output2; int k; Abc_Obj_t * pObj; int * pModel; char * vPiValues; vPiValues = ABC_ALLOC( char, Abc_NtkPiNum(subNtk1) + 1); vPiValues[Abc_NtkPiNum(subNtk1)] = '\0'; for(k = 0; k < Abc_NtkPiNum(subNtk1); k++) vPiValues[k] = '0'; for(k = 0; k < Vec_IntSize(mismatch); k += 2) vPiValues[Vec_IntEntry(mismatch, k)] = Vec_IntEntry(mismatch, k+1); pModel = ABC_ALLOC( int, Abc_NtkCiNum(subNtk1) ); Abc_NtkForEachPi( subNtk1, pObj, k ) pModel[k] = vPiValues[k] - '0'; Abc_NtkForEachLatch( subNtk1, pObj, k ) pModel[Abc_NtkPiNum(subNtk1)+k] = pObj->iData - 1; output1 = Abc_NtkVerifySimulatePattern( subNtk1, pModel ); Abc_NtkForEachLatch( subNtk2, pObj, k ) pModel[Abc_NtkPiNum(subNtk2)+k] = pObj->iData - 1; output2 = Abc_NtkVerifySimulatePattern( subNtk2, pModel ); for(k = 0; k < Vec_IntSize( oMatch1[i] ); k++) if(output1[Vec_IntEntry(oMatch1[i], idx)] != output2[Vec_IntEntry(oMatch2[i], k)]) { skipList[k] = TRUE; /*printf("Output is SKIPPED");*/ } ABC_FREE( vPiValues ); ABC_FREE( pModel ); ABC_FREE( output1 ); ABC_FREE( output2 ); } if(MATCH_FOUND == FALSE ) { Vec_PtrPop(oMatchPairs); Vec_IntPop(matchedOutputs2); } } if(MATCH_FOUND == FALSE ) { Vec_PtrPop(oMatchPairs); Vec_IntPop(matchedOutputs1); } if(MATCH_FOUND && counter != 0) { /*printf("Number of OUTPUT SAT instances = %d", counter);*/ counter = 0; } ABC_FREE( mismatch ); ABC_FREE( skipList ); return MATCH_FOUND; } int match1by1(Abc_Ntk_t * pNtk1, Vec_Ptr_t ** nodesInLevel1, Vec_Int_t ** iMatch1, Vec_Int_t ** iDep1, Vec_Int_t * matchedInputs1, int * iGroup1, Vec_Int_t ** oMatch1, int * oGroup1, Abc_Ntk_t * pNtk2, Vec_Ptr_t ** nodesInLevel2, Vec_Int_t ** iMatch2, Vec_Int_t ** iDep2, Vec_Int_t * matchedInputs2, int * iGroup2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t * matchedOutputs1, Vec_Int_t * matchedOutputs2, Vec_Int_t * oMatchedGroups, Vec_Int_t * iNonSingleton, int ii, int idx) { static int MATCH_FOUND = FALSE; Abc_Ntk_t * subNtk1, * subNtk2; Vec_Int_t * oNonSingleton; Vec_Ptr_t * oMatchPairs; int * skipList; int j, m; int i; static int counter = 0; MATCH_FOUND = FALSE; if( ii == Vec_IntSize(iNonSingleton) ) { MATCH_FOUND = TRUE; return TRUE; } i = Vec_IntEntry(iNonSingleton, ii); if( idx == Vec_IntSize(iMatch1[i]) ) { // call again with the next element in iNonSingleton return match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, ii+1, 0); } oNonSingleton = Vec_IntAlloc(10); oMatchPairs = Vec_PtrAlloc(100); skipList = ABC_ALLOC(int, Vec_IntSize(iMatch1[i])); for(j = 0; j < Vec_IntSize(iMatch1[i]); j++) skipList[j] = FALSE; Vec_IntPush(matchedInputs1, Vec_IntEntry(iMatch1[i], idx)); idx++; if(idx == 1) { for(j = 0; j < Vec_IntSize(iDep1[Vec_IntEntryLast(iMatch1[i])]); j++) { if( Vec_IntSize(oMatch1[oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]]) == 1 ) continue; if( Vec_IntFind( oMatchedGroups, oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]) != -1) continue; Vec_IntPushUnique(oNonSingleton, oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]); Vec_IntPushUnique(oMatchedGroups, oGroup1[Vec_IntEntry(iDep1[Vec_IntEntryLast(iMatch1[i])], j)]); } } subNtk1 = computeCofactor(pNtk1, nodesInLevel1, NULL, matchedInputs1); for(j = idx-1; j < Vec_IntSize(iMatch2[i]) && MATCH_FOUND == FALSE; j++) { int tempJ; Vec_Int_t * mismatch; if( skipList[j] ) continue; mismatch = Vec_IntAlloc(10); Vec_IntPush(matchedInputs2, Vec_IntEntry(iMatch2[i], j)); subNtk2 = computeCofactor(pNtk2, nodesInLevel2, NULL, matchedInputs2); for(m = 0; m < Vec_IntSize(matchedOutputs1); m++) { Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk1, Vec_IntEntry(matchedOutputs1, m))); Vec_PtrPush(oMatchPairs, Abc_NtkPo(subNtk2, Vec_IntEntry(matchedOutputs2, m))); } counter++; if( Abc_NtkBmSat( subNtk2, subNtk1, NULL, oMatchPairs, mismatch, 0) ) { if(idx-1 != j) { tempJ = Vec_IntEntry(iMatch2[i], idx-1); Vec_IntWriteEntry(iMatch2[i], idx-1, Vec_IntEntry(iMatch2[i], j)); Vec_IntWriteEntry(iMatch2[i], j, tempJ); } /*fprintf(matchFile, "%s matched to %s\n", Abc_ObjName(Abc_NtkPi(pNtk1, Vec_IntEntry(iMatch1[i], idx-1))), Abc_ObjName(Abc_NtkPi(pNtk2, Vec_IntEntry(iMatch2[i], j))));*/ // we look for a match for outputs in oNonSingleton matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, subNtk1, subNtk2, oMatchPairs, oNonSingleton, 0, 0, ii, idx); if(idx-1 != j) { tempJ = Vec_IntEntry(iMatch2[i], idx-1); Vec_IntWriteEntry(iMatch2[i], idx-1, Vec_IntEntry(iMatch2[i], j)); Vec_IntWriteEntry(iMatch2[i], j, tempJ); } } else { Abc_Ntk_t * FpNtk1, * FpNtk2; int * bitVector1, * bitVector2; Vec_Int_t * currInputs1, * currInputs2; Vec_Ptr_t * vSupp; Abc_Obj_t * pObj; int suppNum1 = 0; int * suppNum2; bitVector1 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk1) ); bitVector2 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk2) ); currInputs1 = Vec_IntAlloc(10); currInputs2 = Vec_IntAlloc(10); suppNum2 = ABC_ALLOC(int, Vec_IntSize(iMatch2[i])-idx+1); for(m = 0; m < Abc_NtkPiNum(pNtk1); m++) { bitVector1[m] = 0; bitVector2[m] = 0; } for(m = 0; m < Vec_IntSize(iMatch2[i])-idx+1; m++) suppNum2[m]= 0; // First of all set the value of the inputs that are already matched and are in mismatch for(m = 0; m < Vec_IntSize(mismatch); m += 2) { int n = Vec_IntEntry(mismatch, m); bitVector1[Vec_IntEntry(matchedInputs1, n)] = Vec_IntEntry(mismatch, m+1); bitVector2[Vec_IntEntry(matchedInputs2, n)] = Vec_IntEntry(mismatch, m+1); } for(m = idx-1; m < Vec_IntSize(iMatch1[i]); m++) { Vec_IntPush(currInputs1, Vec_IntEntry(iMatch1[i], m)); Vec_IntPush(currInputs2, Vec_IntEntry(iMatch2[i], m)); } // Then add all the inputs that are not yet matched to the currInputs for(m = 0; m < Abc_NtkPiNum(pNtk1); m++) { if(Vec_IntFind( matchedInputs1, m ) == -1) Vec_IntPushUnique(currInputs1, m); if(Vec_IntFind( matchedInputs2, m ) == -1) Vec_IntPushUnique(currInputs2, m); } FpNtk1 = computeCofactor(pNtk1, nodesInLevel1, bitVector1, currInputs1); FpNtk2 = computeCofactor(pNtk2, nodesInLevel2, bitVector2, currInputs2); Abc_NtkForEachPo( FpNtk1, pObj, m ) { int n; vSupp = Abc_NtkNodeSupport( FpNtk1, &pObj, 1 ); for(n = 0; n < vSupp->nSize; n++) if( Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n]) == 1 ) suppNum1 += Vec_IntFind( matchedOutputs1, m) + 1; Vec_PtrFree( vSupp ); } Abc_NtkForEachPo( FpNtk2, pObj, m ) { int n; vSupp = Abc_NtkNodeSupport( FpNtk2, &pObj, 1 ); for(n = 0; n < vSupp->nSize; n++) if( (int)Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1 < (Vec_IntSize(iMatch2[i]))-idx+1 && (int)Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1 >= 0) suppNum2[Abc_ObjId((Abc_Obj_t *)vSupp->pArray[n])-1] += Vec_IntFind( matchedOutputs2, m) + 1; Vec_PtrFree( vSupp ); } /*if(suppNum1 != 0) printf("Ntk1 is trigged"); if(suppNum2[0] != 0) printf("Ntk2 is trigged");*/ for(m = 0; m < Vec_IntSize(iMatch2[i])-idx+1; m++) if(suppNum2[m] != suppNum1) { skipList[m+idx-1] = TRUE; /*printf("input is skipped");*/ } Abc_NtkDelete( FpNtk1 ); Abc_NtkDelete( FpNtk2 ); ABC_FREE( bitVector1 ); ABC_FREE( bitVector2 ); Vec_IntFree( currInputs1 ); Vec_IntFree( currInputs2 ); ABC_FREE( suppNum2 ); } Vec_PtrClear(oMatchPairs); Abc_NtkDelete( subNtk2 ); Vec_IntFree(mismatch); //Vec_IntWriteEntry(iMatch2[i], j, tempJ); if( MATCH_FOUND == FALSE ) Vec_IntPop(matchedInputs2); } if( MATCH_FOUND == FALSE ) { Vec_IntPop(matchedInputs1); if(idx == 1) { for(m = 0; m < Vec_IntSize(oNonSingleton); m++) Vec_IntPop( oMatchedGroups ); } } Vec_IntFree( oNonSingleton ); Vec_PtrFree( oMatchPairs ); ABC_FREE( skipList ); Abc_NtkDelete( subNtk1 ); if(MATCH_FOUND && counter != 0) { /*printf("Number of INPUT SAT instances = %d\n", counter);*/ counter = 0; } return MATCH_FOUND; } float refineBySAT(Abc_Ntk_t * pNtk1, Vec_Int_t ** iMatch1, int * iGroup1, Vec_Int_t ** iDep1, int* iLastItem1, Vec_Int_t ** oMatch1, int * oGroup1, Vec_Int_t ** oDep1, int* oLastItem1, int * observability1, Abc_Ntk_t * pNtk2, Vec_Int_t ** iMatch2, int * iGroup2, Vec_Int_t ** iDep2, int* iLastItem2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t ** oDep2, int* oLastItem2, int * observability2) { int i, j; Abc_Obj_t * pObj; Vec_Int_t * iNonSingleton; Vec_Int_t * matchedInputs1, * matchedInputs2; Vec_Int_t * matchedOutputs1, * matchedOutputs2; Vec_Ptr_t ** nodesInLevel1, ** nodesInLevel2; Vec_Int_t * oMatchedGroups; FILE *result; int matchFound; abctime clk = Abc_Clock(); float satTime = 0.0; /*matchFile = fopen("satmatch.txt", "w");*/ iNonSingleton = Vec_IntAlloc(10); matchedInputs1 = Vec_IntAlloc( Abc_NtkPiNum(pNtk1) ); matchedInputs2 = Vec_IntAlloc( Abc_NtkPiNum(pNtk2) ); matchedOutputs1 = Vec_IntAlloc( Abc_NtkPoNum(pNtk1) ); matchedOutputs2 = Vec_IntAlloc( Abc_NtkPoNum(pNtk2) ); nodesInLevel1 = ABC_ALLOC( Vec_Ptr_t *, Abc_AigLevel( pNtk1 ) + 1); // why numOfLevels+1? because the inputs are in level 0 for(i = 0; i <= Abc_AigLevel( pNtk1 ); i++) nodesInLevel1[i] = Vec_PtrAlloc( 20 ); // bucket sort the objects based on their levels Abc_AigForEachAnd( pNtk1, pObj, i ) Vec_PtrPush(nodesInLevel1[Abc_ObjLevel(pObj)], pObj); nodesInLevel2 = ABC_ALLOC( Vec_Ptr_t *, Abc_AigLevel( pNtk2 ) + 1); // why numOfLevels+1? because the inputs are in level 0 for(i = 0; i <= Abc_AigLevel( pNtk2 ); i++) nodesInLevel2[i] = Vec_PtrAlloc( 20 ); // bucket sort the objects based on their levels Abc_AigForEachAnd( pNtk2, pObj, i ) Vec_PtrPush(nodesInLevel2[Abc_ObjLevel(pObj)], pObj); oMatchedGroups = Vec_IntAlloc( 10 ); for(i = 0; i < *iLastItem1; i++) { if(Vec_IntSize(iMatch1[i]) == 1) { Vec_IntPush(matchedInputs1, Vec_IntEntryLast(iMatch1[i])); Vec_IntPush(matchedInputs2, Vec_IntEntryLast(iMatch2[i])); } else Vec_IntPush(iNonSingleton, i); } for(i = 0; i < *oLastItem1; i++) { if(Vec_IntSize(oMatch1[i]) == 1) { Vec_IntPush(matchedOutputs1, Vec_IntEntryLast(oMatch1[i])); Vec_IntPush(matchedOutputs2, Vec_IntEntryLast(oMatch2[i])); } } for(i = 0; i < Vec_IntSize(iNonSingleton) - 1; i++) { for(j = i + 1; j < Vec_IntSize(iNonSingleton); j++) if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] > observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] ) { int temp = Vec_IntEntry(iNonSingleton, i); Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) ); Vec_IntWriteEntry( iNonSingleton, j, temp ); } else if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] == observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] ) { if( Vec_IntSize(iMatch2[Vec_IntEntry(iNonSingleton, j)]) < Vec_IntSize(iMatch2[Vec_IntEntry(iNonSingleton, i)]) ) { int temp = Vec_IntEntry(iNonSingleton, i); Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) ); Vec_IntWriteEntry( iNonSingleton, j, temp ); } } } /*for(i = 0; i < Vec_IntSize(iNonSingleton) - 1; i++) { for(j = i + 1; j < Vec_IntSize(iNonSingleton); j++) if( Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, j)])]]) > Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, i)])]]) ) { int temp = Vec_IntEntry(iNonSingleton, i); Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) ); Vec_IntWriteEntry( iNonSingleton, j, temp ); } else if( Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, j)])]]) == Vec_IntSize(oDep2[oGroup2[Vec_IntEntryLast(iMatch2[Vec_IntEntry(iNonSingleton, i)])]]) ) { if( observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, j)], 0)] > observability2[Vec_IntEntry(iMatch2[Vec_IntEntry(iNonSingleton, i)], 0)] ) { int temp = Vec_IntEntry(iNonSingleton, i); Vec_IntWriteEntry( iNonSingleton, i, Vec_IntEntry(iNonSingleton, j) ); Vec_IntWriteEntry( iNonSingleton, j, temp ); } } }*/ matchFound = match1by1(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup2, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, iNonSingleton, 0, 0); if( matchFound && Vec_IntSize(matchedOutputs1) != Abc_NtkPoNum(pNtk1) ) { Vec_Int_t * oNonSingleton; Vec_Ptr_t * oMatchPairs; Abc_Ntk_t * subNtk1, * subNtk2; oNonSingleton = Vec_IntAlloc( 10 ); oMatchPairs = Vec_PtrAlloc(Abc_NtkPoNum(pNtk1) * 2); for(i = 0; i < *oLastItem1; i++) if( Vec_IntSize(oMatch1[i]) > 1 && Vec_IntFind( oMatchedGroups, i) == -1 ) Vec_IntPush(oNonSingleton, i); subNtk1 = computeCofactor(pNtk1, nodesInLevel1, NULL, matchedInputs1); subNtk2 = computeCofactor(pNtk2, nodesInLevel2, NULL, matchedInputs2); matchFound = matchNonSingletonOutputs(pNtk1, nodesInLevel1, iMatch1, iDep1, matchedInputs1, iGroup1, oMatch1, oGroup1, pNtk2, nodesInLevel2, iMatch2, iDep2, matchedInputs2, iGroup1, oMatch2, oGroup2, matchedOutputs1, matchedOutputs2, oMatchedGroups, NULL, subNtk1, subNtk2, oMatchPairs, oNonSingleton, 0, 0, 0, 0); Vec_IntFree( oNonSingleton ); Vec_PtrFree( oMatchPairs ); Abc_NtkDelete(subNtk1); Abc_NtkDelete(subNtk2); } satTime = (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC); if( matchFound ) { checkEquivalence( pNtk1, matchedInputs1, matchedOutputs1, pNtk2, matchedInputs2, matchedOutputs2); result = fopen("IOmatch.txt", "w"); fprintf(result, "I/O = %d / %d \n\n", Abc_NtkPiNum(pNtk1), Abc_NtkPoNum(pNtk1)); for(i = 0; i < Vec_IntSize(matchedInputs1) ; i++) fprintf(result, "{%s}\t{%s}\n", Abc_ObjName(Abc_NtkPi(pNtk1, Vec_IntEntry(matchedInputs1, i))), Abc_ObjName(Abc_NtkPi(pNtk2, Vec_IntEntry(matchedInputs2, i))) ); fprintf(result, "\n-----------------------------------------\n"); for(i = 0; i < Vec_IntSize(matchedOutputs1) ; i++) fprintf(result, "{%s}\t{%s}\n", Abc_ObjName(Abc_NtkPo(pNtk1, Vec_IntEntry(matchedOutputs1, i))), Abc_ObjName(Abc_NtkPo(pNtk2, Vec_IntEntry(matchedOutputs2, i))) ); fclose( result ); } Vec_IntFree( matchedInputs1 ); Vec_IntFree( matchedInputs2 ); Vec_IntFree( matchedOutputs1 ); Vec_IntFree( matchedOutputs2 ); Vec_IntFree( iNonSingleton ); Vec_IntFree( oMatchedGroups ); for(i = 0; i <= Abc_AigLevel( pNtk1 ); i++) Vec_PtrFree( nodesInLevel1[i] ); for(i = 0; i <= Abc_AigLevel( pNtk2 ); i++) Vec_PtrFree( nodesInLevel2[i] ); ABC_FREE( nodesInLevel1 ); ABC_FREE( nodesInLevel2 ); /*fclose(matchFile);*/ return satTime; } int checkListConsistency(Vec_Int_t ** iMatch1, Vec_Int_t ** oMatch1, Vec_Int_t ** iMatch2, Vec_Int_t ** oMatch2, int iLastItem1, int oLastItem1, int iLastItem2, int oLastItem2) { //int i; if(iLastItem1 != iLastItem2 || oLastItem1 != oLastItem2) return FALSE; /*for(i = 0; i < iLastItem1; i++) { if(Vec_IntSize(iMatch1[i]) != Vec_IntSize(iMatch2[i])) return FALSE; } for(i = 0; i < oLastItem1; i++) { if(Vec_IntSize(oMatch1[i]) != Vec_IntSize(oMatch2[i])) return FALSE; }*/ return TRUE; } void bmGateWay( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int p_equivalence ) { Vec_Int_t ** iDep1, ** oDep1; Vec_Int_t ** iDep2, ** oDep2; Vec_Int_t ** iMatch1, ** oMatch1; Vec_Int_t ** iMatch2, ** oMatch2; int * iGroup1, * oGroup1; int * iGroup2, * oGroup2; int iLastItem1, oLastItem1; int iLastItem2, oLastItem2; int i, j; char * vPiValues1, * vPiValues2; int * observability1, * observability2; abctime clk = Abc_Clock(); float initTime; float simulTime; float satTime; Vec_Ptr_t ** topOrder1 = NULL, ** topOrder2 = NULL; extern void getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep); extern void initMatchList(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep, Vec_Int_t** iMatch, int* iLastItem, Vec_Int_t** oMatch, int* oLastItem, int* iGroup, int* oGroup, int p_equivalence); extern void iSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, int* oGroup); extern void oSortDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, int* iGroup); extern int iSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** iMatch, int* iGroup, int* iLastItem, int* oGroup); extern int oSplitByDep(Abc_Ntk_t *pNtk, Vec_Int_t** oDep, Vec_Int_t** oMatch, int* oGroup, int* oLastItem, int* iGroup); extern Vec_Ptr_t ** findTopologicalOrder(Abc_Ntk_t * pNtk); extern int refineIOBySimulation(Abc_Ntk_t *pNtk, Vec_Int_t** iMatch, int* iLastItem, int * iGroup, Vec_Int_t** iDep, Vec_Int_t** oMatch, int* oLastItem, int * oGroup, Vec_Int_t** oDep, char * vPiValues, int * observability, Vec_Ptr_t ** topOrder); extern float refineBySAT(Abc_Ntk_t * pNtk1, Vec_Int_t ** iMatch1, int * iGroup1, Vec_Int_t ** iDep1, int* iLastItem1, Vec_Int_t ** oMatch1, int * oGroup1, Vec_Int_t ** oDep1, int* oLastItem1, int * observability1, Abc_Ntk_t * pNtk2, Vec_Int_t ** iMatch2, int * iGroup2, Vec_Int_t ** iDep2, int* iLastItem2, Vec_Int_t ** oMatch2, int * oGroup2, Vec_Int_t ** oDep2, int* oLastItem2, int * observability2); int checkListConsistency(Vec_Int_t ** iMatch1, Vec_Int_t ** oMatch1, Vec_Int_t ** iMatch2, Vec_Int_t ** oMatch2, int iLastItem1, int oLastItem1, int iLastItem2, int oLastItem2); iDep1 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPiNum(pNtk1) ); oDep1 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPoNum(pNtk1) ); iDep2 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPiNum(pNtk2) ); oDep2 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPoNum(pNtk2) ); iMatch1 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPiNum(pNtk1) ); oMatch1 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPoNum(pNtk1) ); iMatch2 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPiNum(pNtk2) ); oMatch2 = ABC_ALLOC( Vec_Int_t*, (unsigned)Abc_NtkPoNum(pNtk2) ); iGroup1 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk1) ); oGroup1 = ABC_ALLOC( int, Abc_NtkPoNum(pNtk1) ); iGroup2 = ABC_ALLOC( int, Abc_NtkPiNum(pNtk2) ); oGroup2 = ABC_ALLOC( int, Abc_NtkPoNum(pNtk2) ); vPiValues1 = ABC_ALLOC( char, Abc_NtkPiNum(pNtk1) + 1); vPiValues1[Abc_NtkPiNum(pNtk1)] = '\0'; vPiValues2 = ABC_ALLOC( char, Abc_NtkPiNum(pNtk2) + 1); vPiValues2[Abc_NtkPiNum(pNtk2)] = '\0'; observability1 = ABC_ALLOC(int, (unsigned)Abc_NtkPiNum(pNtk1)); observability2 = ABC_ALLOC(int, (unsigned)Abc_NtkPiNum(pNtk2)); for(i = 0; i < Abc_NtkPiNum(pNtk1); i++) { iDep1[i] = Vec_IntAlloc( 1 ); iMatch1[i] = Vec_IntAlloc( 1 ); iDep2[i] = Vec_IntAlloc( 1 ); iMatch2[i] = Vec_IntAlloc( 1 ); vPiValues1[i] = '0'; vPiValues2[i] = '0'; observability1[i] = 0; observability2[i] = 0; } for(i = 0; i < Abc_NtkPoNum(pNtk1); i++) { oDep1[i] = Vec_IntAlloc( 1 ); oMatch1[i] = Vec_IntAlloc( 1 ); oDep2[i] = Vec_IntAlloc( 1 ); oMatch2[i] = Vec_IntAlloc( 1 ); } /************* Strashing ************/ pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 ); pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 ); printf("Network strashing is done!\n"); /************************************/ /******* Getting Dependencies *******/ getDependencies(pNtk1, iDep1, oDep1); getDependencies(pNtk2, iDep2, oDep2); printf("Getting dependencies is done!\n"); /************************************/ /***** Intializing match lists ******/ initMatchList(pNtk1, iDep1, oDep1, iMatch1, &iLastItem1, oMatch1, &oLastItem1, iGroup1, oGroup1, p_equivalence); initMatchList(pNtk2, iDep2, oDep2, iMatch2, &iLastItem2, oMatch2, &oLastItem2, iGroup2, oGroup2, p_equivalence); printf("Initializing match lists is done!\n"); /************************************/ if( !checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2) ) { fprintf( stdout, "I/O dependencies of two circuits are different.\n"); goto freeAndExit; } printf("Refining IOs by dependencies ..."); // split match lists further by checking dependencies do { int iNumOfItemsAdded = 1, oNumOfItemsAdded = 1; do { if( oNumOfItemsAdded ) { iSortDependencies(pNtk1, iDep1, oGroup1); iSortDependencies(pNtk2, iDep2, oGroup2); } if( iNumOfItemsAdded ) { oSortDependencies(pNtk1, oDep1, iGroup1); oSortDependencies(pNtk2, oDep2, iGroup2); } if( iLastItem1 < Abc_NtkPiNum(pNtk1) ) { iSplitByDep(pNtk1, iDep1, iMatch1, iGroup1, &iLastItem1, oGroup1); if( oLastItem1 < Abc_NtkPoNum(pNtk1) ) oSplitByDep(pNtk1, oDep1, oMatch1, oGroup1, &oLastItem1, iGroup1); } if( iLastItem2 < Abc_NtkPiNum(pNtk2) ) iNumOfItemsAdded = iSplitByDep(pNtk2, iDep2, iMatch2, iGroup2, &iLastItem2, oGroup2); else iNumOfItemsAdded = 0; if( oLastItem2 < Abc_NtkPoNum(pNtk2) ) oNumOfItemsAdded = oSplitByDep(pNtk2, oDep2, oMatch2, oGroup2, &oLastItem2, iGroup2); else oNumOfItemsAdded = 0; if(!checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2)) { fprintf( stdout, "I/O dependencies of two circuits are different.\n"); goto freeAndExit; } }while(iNumOfItemsAdded != 0 || oNumOfItemsAdded != 0); }while(0); printf(" done!\n"); initTime = ((float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC)); clk = Abc_Clock(); topOrder1 = findTopologicalOrder(pNtk1); topOrder2 = findTopologicalOrder(pNtk2); printf("Refining IOs by simulation ..."); do { int counter = 0; int ioSuccess1, ioSuccess2; do { for(i = 0; i < iLastItem1; i++) { int temp = (int)(SIM_RANDOM_UNSIGNED % 2); if(Vec_IntSize(iMatch1[i]) != Vec_IntSize(iMatch2[i])) { fprintf( stdout, "Input refinement by simulation finds two circuits different.\n"); goto freeAndExit; } for(j = 0; j < Vec_IntSize(iMatch1[i]); j++) { vPiValues1[Vec_IntEntry(iMatch1[i], j)] = temp + '0'; vPiValues2[Vec_IntEntry(iMatch2[i], j)] = temp + '0'; } } ioSuccess1 = refineIOBySimulation(pNtk1, iMatch1, &iLastItem1, iGroup1, iDep1, oMatch1, &oLastItem1, oGroup1, oDep1, vPiValues1, observability1, topOrder1); ioSuccess2 = refineIOBySimulation(pNtk2, iMatch2, &iLastItem2, iGroup2, iDep2, oMatch2, &oLastItem2, oGroup2, oDep2, vPiValues2, observability2, topOrder2); if(ioSuccess1 && ioSuccess2) counter = 0; else counter++; if(ioSuccess1 != ioSuccess2 || !checkListConsistency(iMatch1, oMatch1, iMatch2, oMatch2, iLastItem1, oLastItem1, iLastItem2, oLastItem2)) { fprintf( stdout, "Input refinement by simulation finds two circuits different.\n"); goto freeAndExit; } }while(counter <= 200); }while(0); printf(" done!\n"); simulTime = (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC); printf("SAT-based search started ...\n"); satTime = refineBySAT(pNtk1, iMatch1, iGroup1, iDep1, &iLastItem1, oMatch1, oGroup1, oDep1, &oLastItem1, observability1, pNtk2, iMatch2, iGroup2, iDep2, &iLastItem2, oMatch2, oGroup2, oDep2, &oLastItem2, observability2); printf( "Init Time = %4.2f\n", initTime ); printf( "Simulation Time = %4.2f\n", simulTime ); printf( "SAT Time = %4.2f\n", satTime ); printf( "Overall Time = %4.2f\n", initTime + simulTime + satTime ); freeAndExit: for(i = 0; i < iLastItem1 ; i++) { Vec_IntFree( iMatch1[i] ); Vec_IntFree( iMatch2[i] ); } for(i = 0; i < oLastItem1 ; i++) { Vec_IntFree( oMatch1[i] ); Vec_IntFree( oMatch2[i] ); } for(i = 0; i < Abc_NtkPiNum(pNtk1); i++) { Vec_IntFree( iDep1[i] ); Vec_IntFree( iDep2[i] ); if(topOrder1 != NULL) { Vec_PtrFree( topOrder1[i] ); Vec_PtrFree( topOrder2[i] ); } } for(i = 0; i < Abc_NtkPoNum(pNtk1); i++) { Vec_IntFree( oDep1[i] ); Vec_IntFree( oDep2[i] ); } ABC_FREE( iMatch1 ); ABC_FREE( iMatch2 ); ABC_FREE( oMatch1 ); ABC_FREE( oMatch2 ); ABC_FREE( iDep1 ); ABC_FREE( iDep2 ); ABC_FREE( oDep1 ); ABC_FREE( oDep2 ); ABC_FREE( iGroup1 ); ABC_FREE( iGroup2 ); ABC_FREE( oGroup1 ); ABC_FREE( oGroup2 ); ABC_FREE( vPiValues1 ); ABC_FREE( vPiValues2 ); ABC_FREE( observability1 ); ABC_FREE( observability2 ); if(topOrder1 != NULL) { ABC_FREE( topOrder1 ); ABC_FREE( topOrder2 ); } }ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcBmc.c000066400000000000000000000076001300674244400231620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcBmc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Performs bounded model check.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/ivy/ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ); static void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose ) { Ivy_FraigParams_t Params, * pParams = &Params; Ivy_Man_t * pMan, * pFrames, * pFraig; Vec_Ptr_t * vMapping; // convert to IVY manager pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); // generate timeframes pFrames = Ivy_ManFrames( pMan, Abc_NtkLatchNum(pNtk), nFrames, fInit, &vMapping ); // fraig the timeframes Ivy_FraigParamsDefault( pParams ); pParams->nBTLimitNode = ABC_INFINITY; pParams->fVerbose = 0; pParams->fProve = 0; pFraig = Ivy_FraigPerform( pFrames, pParams ); printf( "Frames have %6d nodes. ", Ivy_ManNodeNum(pFrames) ); printf( "Fraig has %6d nodes.\n", Ivy_ManNodeNum(pFraig) ); // report the classes // if ( fVerbose ) // Abc_NtkBmcReport( pMan, pFrames, pFraig, vMapping, nFrames ); // free stuff Vec_PtrFree( vMapping ); Ivy_ManStop( pFraig ); Ivy_ManStop( pFrames ); Ivy_ManStop( pMan ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames ) { Ivy_Obj_t * pFirst1, * pFirst2 = NULL, * pFirst3 = NULL; int i, f, nIdMax, Prev2, Prev3; nIdMax = Ivy_ManObjIdMax(pMan); // check what is the number of nodes in each frame Prev2 = Prev3 = 0; for ( f = 0; f < nFrames; f++ ) { Ivy_ManForEachNode( pMan, pFirst1, i ) { pFirst2 = Ivy_Regular( (Ivy_Obj_t *)Vec_PtrEntry(vMapping, f * nIdMax + pFirst1->Id) ); if ( Ivy_ObjIsConst1(pFirst2) || pFirst2->Type == 0 ) continue; pFirst3 = Ivy_Regular( pFirst2->pEquiv ); if ( Ivy_ObjIsConst1(pFirst3) || pFirst3->Type == 0 ) continue; break; } assert(pFirst2); assert(pFirst3); if ( f ) printf( "Frame %3d : Strash = %5d Fraig = %5d\n", f, pFirst2->Id - Prev2, pFirst3->Id - Prev3 ); Prev2 = pFirst2->Id; Prev3 = pFirst3->Id; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcCas.c000066400000000000000000000074751300674244400232010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcCas.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Decomposition of shared BDDs into LUT cascade.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcCas.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START /* This LUT cascade synthesis algorithm is described in the paper: A. Mishchenko and T. Sasao, "Encoding of Boolean functions and its application to LUT cascade synthesis", Proc. IWLS '02, pp. 115-120. http://www.eecs.berkeley.edu/~alanmi/publications/2002/iwls02_enc.pdf */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD extern int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) { DdManager * dd; DdNode ** ppOutputs; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode; char * pFileGeneric; int fBddSizeMax = 500000; int i, fReorder = 1; abctime clk = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); // compute the global BDDs if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) return NULL; if ( fVerbose ) { DdManager * dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk ); printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); ABC_PRT( "BDD construction time", Abc_Clock() - clk ); } // collect global BDDs dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk ); ppOutputs = ABC_ALLOC( DdNode *, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) ppOutputs[i] = (DdNode *)Abc_ObjGlobalBdd(pNode); // call the decomposition pFileGeneric = Extra_FileNameGeneric( pNtk->pSpec ); if ( !Abc_CascadeExperiment( pFileGeneric, dd, ppOutputs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), nLutSize, fCheck, fVerbose ) ) { // the LUT size is too small } // for now, duplicate the network pNtkNew = Abc_NtkDup( pNtk ); // cleanup Abc_NtkFreeGlobalBdds( pNtk, 1 ); ABC_FREE( ppOutputs ); ABC_FREE( pFileGeneric ); // if ( pNtk->pExdc ) // pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkCollapse: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } #else Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) { return NULL; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcCascade.c000066400000000000000000001012441300674244400240030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcCascade.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Collapsing the network into two-levels.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/reo/reo.h" #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD #define BDD_FUNC_MAX 256 //extern void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ); extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derive BDD of the characteristic function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_ResBuildBdd( Abc_Ntk_t * pNtk, DdManager * dd ) { Vec_Ptr_t * vNodes, * vBdds, * vLocals; Abc_Obj_t * pObj, * pFanin; DdNode * bFunc, * bPart, * bTemp, * bVar; int i, k; assert( Abc_NtkIsSopLogic(pNtk) ); assert( Abc_NtkCoNum(pNtk) <= 3 ); vBdds = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), Cudd_bddIthVar(dd, i) ); // create internal node BDDs vNodes = Abc_NtkDfs( pNtk, 0 ); vLocals = Vec_PtrAlloc( 6 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { if ( Abc_ObjFaninNum(pObj) == 0 ) { bFunc = Cudd_NotCond( Cudd_ReadOne(dd), Abc_SopIsConst0((char *)pObj->pData) ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc ); continue; } Vec_PtrClear( vLocals ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_PtrPush( vLocals, Vec_PtrEntry(vBdds, Abc_ObjId(pFanin)) ); bFunc = Abc_ConvertSopToBdd( dd, (char *)pObj->pData, (DdNode **)Vec_PtrArray(vLocals) ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc ); } Vec_PtrFree( vLocals ); // create char function bFunc = Cudd_ReadOne( dd ); Cudd_Ref( bFunc ); Abc_NtkForEachCo( pNtk, pObj, i ) { bVar = Cudd_bddIthVar( dd, i + Abc_NtkCiNum(pNtk) ); bTemp = (DdNode *)Vec_PtrEntry( vBdds, Abc_ObjFaninId0(pObj) ); bPart = Cudd_bddXnor( dd, bTemp, bVar ); Cudd_Ref( bPart ); bFunc = Cudd_bddAnd( dd, bTemp = bFunc, bPart ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bPart ); } // dereference Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Cudd_RecursiveDeref( dd, (DdNode *)Vec_PtrEntry(vBdds, Abc_ObjId(pObj)) ); Vec_PtrFree( vBdds ); Vec_PtrFree( vNodes ); // reorder Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); Cudd_Deref( bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Initializes variable partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ResStartPart( int nInputs, unsigned uParts[], int nParts ) { int i, Group, Left, Shift = 0, Count = 0; Group = nInputs / nParts; Left = nInputs % nParts; for ( i = 0; i < Left; i++ ) { uParts[i] = (~((~0) << (Group+1))) << Shift; Shift += Group+1; } for ( ; i < nParts; i++ ) { uParts[i] = (~((~0) << Group)) << Shift; Shift += Group; } for ( i = 0; i < nParts; i++ ) Count += Extra_WordCountOnes( uParts[i] ); assert( Count == nInputs ); } /**Function************************************************************* Synopsis [Initializes variable partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ResStartPart2( int nInputs, unsigned uParts[], int nParts ) { int i, Count = 0; for ( i = 0; i < nParts; i++ ) uParts[i] = 0; for ( i = 0; i < nInputs; i++ ) uParts[i % nParts] |= (1 << i); for ( i = 0; i < nParts; i++ ) Count += Extra_WordCountOnes( uParts[i] ); assert( Count == nInputs ); } /**Function************************************************************* Synopsis [Returns one if unique pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ResCheckUnique( char Pats[], int nPats, int pat ) { int i; for ( i = 0; i < nPats; i++ ) if ( Pats[i] == pat ) return 0; return 1; } /**Function************************************************************* Synopsis [Check if pattern is decomposable with non-strict.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ResCheckNonStrict( char Pattern[], int nVars, int nBits ) { static char Pat0[256], Pat1[256]; int v, m, nPats0, nPats1, nNumber = (1 << (nBits - 1)); int Result = 0; for ( v = 0; v < nVars; v++ ) { nPats0 = nPats1 = 0; for ( m = 0; m < (1< nNumber ) break; } } else { if ( Abc_ResCheckUnique( Pat1, nPats1, Pattern[m] ) ) { Pat1[ nPats1++ ] = Pattern[m]; if ( nPats1 > nNumber ) break; } } } if ( m == (1<vars[i]; assert( nVars <= 8 ); // compute cofactors vCofs = Vec_PtrAlloc( 100 ); for ( i = 0; i < (1 << nVars); i++ ) { bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); bCof = Cudd_Cofactor( dd, bFunc, bCube ); Cudd_Ref( bCof ); Cudd_RecursiveDeref( dd, bCube ); Vec_PtrForEachEntry( DdNode *, vCofs, bTemp, k ) if ( bTemp == bCof ) break; if ( k < Vec_PtrSize(vCofs) ) Cudd_RecursiveDeref( dd, bCof ); else Vec_PtrPush( vCofs, bCof ); Pattern[i] = k; } Result = Vec_PtrSize( vCofs ); Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i ) Cudd_RecursiveDeref( dd, bCof ); Vec_PtrFree( vCofs ); if ( pCheck ) { *pCheck = Abc_ResCheckNonStrict( Pattern, nVars, Abc_Base2Log(Result) ); /* if ( *pCheck == 1 && nVars == 4 && Result == 8 ) { for ( i = 0; i < (1 << nVars); i++ ) printf( "%d ", Pattern[i] ); i = 0; } */ } return Result; } /**Function************************************************************* Synopsis [Computes cost of the partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ResCost( DdManager * dd, DdNode * bFunc, unsigned uMask, int * pnCofs, int * pCheck ) { int nCofs = Abc_ResCofCount( dd, bFunc, uMask, pCheck ); int n2Log = Abc_Base2Log( nCofs ); if ( pnCofs ) *pnCofs = nCofs; return 10000 * n2Log + (nCofs - (1 << (n2Log-1))) * (nCofs - (1 << (n2Log-1))); } /**Function************************************************************* Synopsis [Migrates variables between the two groups.] Description [Returns 1 if there is change.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ResMigrate( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int iPart1, int iPart2 ) { unsigned uParts2[2] = { uParts[iPart1], uParts[iPart2] }; int i, k, CostCur, CostBest, fChange = 0; assert( (uParts[iPart1] & uParts[iPart2]) == 0 ); CostBest = Abc_ResCost( dd, bFunc, uParts[iPart1], NULL, NULL ) + Abc_ResCost( dd, bFunc, uParts[iPart2], NULL, NULL ); for ( i = 0; i < nInputs; i++ ) if ( uParts[iPart1] & (1 << i) ) { for ( k = 0; k < nInputs; k++ ) if ( uParts[iPart2] & (1 << k) ) { if ( i == k ) continue; uParts[iPart1] ^= (1 << i) | (1 << k); uParts[iPart2] ^= (1 << i) | (1 << k); CostCur = Abc_ResCost( dd, bFunc, uParts[iPart1], NULL, NULL ) + Abc_ResCost( dd, bFunc, uParts[iPart2], NULL, NULL ); if ( CostCur < CostBest ) { CostCur = CostBest; uParts2[0] = uParts[iPart1]; uParts2[1] = uParts[iPart2]; fChange = 1; } uParts[iPart1] ^= (1 << i) | (1 << k); uParts[iPart2] ^= (1 << i) | (1 << k); } } uParts[iPart1] = uParts2[0]; uParts[iPart2] = uParts2[1]; return fChange; } /**Function************************************************************* Synopsis [Migrates variables between the two groups.] Description [Returns 1 if there is change.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ResPrint( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int nParts ) { int i, k, nCofs, Cost, CostAll = 0, fCheck; for ( i = 0; i < nParts; i++ ) { Cost = Abc_ResCost( dd, bFunc, uParts[i], &nCofs, &fCheck ); CostAll += Cost; for ( k = 0; k < nInputs; k++ ) printf( "%c", (uParts[i] & (1 << k))? 'a' + k : '-' ); printf( " %2d %d-%d %6d ", nCofs, Abc_Base2Log(nCofs), fCheck, Cost ); } printf( "%4d\n", CostAll ); } /**Function************************************************************* Synopsis [PrintCompute the number of distinct cofactors in the BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ResPrintAllCofs( DdManager * dd, DdNode * bFunc, int nInputs, int nCofMax ) { int i, k, nBits, nCofs, Cost, fCheck; for ( i = 0; i < (1< 6 ) continue; Cost = Abc_ResCost( dd, bFunc, i, &nCofs, &fCheck ); if ( nCofs > nCofMax ) continue; for ( k = 0; k < nInputs; k++ ) printf( "%c", (i & (1 << k))? 'a' + k : '-' ); printf( " n=%2d c=%2d l=%d-%d %6d\n", Extra_WordCountOnes(i), nCofs, Abc_Base2Log(nCofs), fCheck, Cost ); } } /**Function************************************************************* Synopsis [Compute the number of distinct cofactors in the BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ResSwapRandom( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int nParts, int nTimes ) { int i, k, n, iPart1, iPart2; for ( n = 0; n < nTimes; ) { // get the vars i = k = 0; while ( i == k ) { i = rand() % nInputs; k = rand() % nInputs; } // find the groups for ( iPart1 = 0; iPart1 < nParts; iPart1++ ) if ( uParts[iPart1] & (1 << i) ) break; for ( iPart2 = 0; iPart2 < nParts; iPart2++ ) if ( uParts[iPart2] & (1 << k) ) break; if ( iPart1 == iPart2 ) continue; // swap the vars uParts[iPart1] ^= (1 << i) | (1 << k); uParts[iPart2] ^= (1 << i) | (1 << k); n++; //printf( " " ); //Abc_ResPrint( dd, bFunc, nInputs, uParts, nParts ); } } /**Function************************************************************* Synopsis [Compute the number of distinct cofactors in the BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ResPartition( DdManager * dd, DdNode * bFunc, int nInputs ) { int nIters = 5; unsigned uParts[10]; int i, fChange = 1; int nSuppSize = Cudd_SupportSize( dd, bFunc ); printf( "Ins =%3d. Outs =%2d. Nodes =%3d. Supp =%2d.\n", nInputs, dd->size-nInputs, Cudd_DagSize(bFunc), nSuppSize ); //Abc_ResPrintAllCofs( dd, bFunc, nInputs, 4 ); if ( nSuppSize <= 6 ) { printf( "Support is less or equal than 6\n" ); return; } if ( nInputs <= 12 ) { Abc_ResStartPart( nInputs, uParts, 2 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 ); for ( i = 0; i < nIters; i++ ) { if ( i ) { printf( "Randomizing... \n" ); Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 2, 20 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 ); } fChange = 1; while ( fChange ) { fChange = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 ); } } } else if ( nInputs > 12 && nInputs <= 18 ) { Abc_ResStartPart( nInputs, uParts, 3 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); for ( i = 0; i < nIters; i++ ) { if ( i ) { printf( "Randomizing... \n" ); Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 3, 20 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); } fChange = 1; while ( fChange ) { fChange = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 2 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 2 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); } } } else if ( nInputs > 18 && nInputs <= 24 ) { Abc_ResStartPart( nInputs, uParts, 4 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); for ( i = 0; i < nIters; i++ ) { if ( i ) { printf( "Randomizing... \n" ); Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 4, 20 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); } fChange = 1; while ( fChange ) { fChange = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 2 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 3 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 2 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 3 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 2, 3 ); Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); } } } // else assert( 0 ); } /**Function************************************************************* Synopsis [Compute the number of distinct cofactors in the BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ResPartitionTest( Abc_Ntk_t * pNtk ) { DdManager * dd; DdNode * bFunc; dd = Cudd_Init( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); bFunc = Abc_ResBuildBdd( pNtk, dd ); Cudd_Ref( bFunc ); Abc_ResPartition( dd, bFunc, Abc_NtkCiNum(pNtk) ); Cudd_RecursiveDeref( dd, bFunc ); Extra_StopManager( dd ); } /**Function************************************************************* Synopsis [Compute the number of distinct cofactors in the BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkBddCofCount( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nVars ) { Vec_Ptr_t * vCofs; DdNode * bCof, * bCube; int i, Result; vCofs = Vec_PtrAlloc( 100 ); for ( i = 0; i < (1 << nVars); i++ ) { bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); bCof = Cudd_Cofactor( dd, bFunc, bCube ); Cudd_Ref( bCof ); Cudd_RecursiveDeref( dd, bCube ); if ( Vec_PtrPushUnique( vCofs, bCof ) ) Cudd_RecursiveDeref( dd, bCof ); } Result = Vec_PtrSize( vCofs ); Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i ) Cudd_RecursiveDeref( dd, bCof ); Vec_PtrFree( vCofs ); return Result; } /**Function************************************************************* Synopsis [Compute the number of distinct cofactors in the BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkExploreCofs2( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nIns, int nLutSize ) { int i; printf( "Inputs = %2d. Nodes = %2d. LutSize = %2d.\n", nIns, Cudd_DagSize(bFunc), nLutSize ); for ( i = 0; i <= nIns - nLutSize; i++ ) printf( "[%2d %2d] : %3d\n", i, i+nLutSize-1, Abc_NtkBddCofCount(dd, bFunc, dd->vars+i, nLutSize) ); } /**Function************************************************************* Synopsis [Compute the number of distinct cofactors in the BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkExploreCofs( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nIns, int nLutSize ) { DdManager * ddNew; DdNode * bFuncNew; DdNode * pbVarsNew[32]; int i, k, c, nCofs, nBits; ddNew = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_ShuffleHeap( ddNew, dd->invperm ); bFuncNew = Cudd_bddTransfer( dd, ddNew, bFunc ); Cudd_Ref( bFuncNew ); for ( i = 0; i < (1 << nIns); i++ ) { nBits = Extra_WordCountOnes(i); if ( nBits != nLutSize && nBits != nLutSize -1 && nBits != nLutSize -2 ) continue; for ( c = k = 0; k < nIns; k++ ) { if ( (i & (1 << k)) == 0 ) continue; // pbVarsNew[c++] = pbVars[k]; pbVarsNew[c++] = ddNew->vars[k]; } nCofs = Abc_NtkBddCofCount(ddNew, bFuncNew, pbVarsNew, c); if ( nCofs > 8 ) continue; for ( c = k = 0; k < nIns; k++ ) { if ( (i & (1 << k)) == 0 ) { printf( "-" ); continue; } printf( "%c", k + 'a' ); } printf( " : %2d\n", nCofs ); } Cudd_RecursiveDeref( ddNew, bFuncNew ); Extra_StopManager( ddNew ); } /**Function************************************************************* Synopsis [Find the constant node corresponding to the encoded output value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkBddFindAddConst( DdManager * dd, DdNode * bFunc, int nOuts ) { int i, TermMask = 0; DdNode * bFunc0, * bFunc1, * bConst0, * bConst1; bConst0 = Cudd_ReadLogicZero( dd ); bConst1 = Cudd_ReadOne( dd ); for ( i = 0; i < nOuts; i++ ) { if ( Cudd_IsComplement(bFunc) ) { bFunc0 = Cudd_Not(Cudd_E(bFunc)); bFunc1 = Cudd_Not(Cudd_T(bFunc)); } else { bFunc0 = Cudd_E(bFunc); bFunc1 = Cudd_T(bFunc); } assert( bFunc0 == bConst0 || bFunc1 == bConst0 ); if ( bFunc0 == bConst0 ) { TermMask ^= (1 << i); bFunc = bFunc1; } else bFunc = bFunc0; } assert( bFunc == bConst1 ); return Cudd_addConst( dd, TermMask ); } /**Function************************************************************* Synopsis [Recursively construct ADD for BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkBddToAdd_rec( DdManager * dd, DdNode * bFunc, int nOuts, stmm_table * tTable, int fCompl ) { DdNode * aFunc0, * aFunc1, * aFunc; DdNode ** ppSlot; assert( !Cudd_IsComplement(bFunc) ); if ( stmm_find_or_add( tTable, (char *)bFunc, (char ***)&ppSlot ) ) return *ppSlot; if ( (int)bFunc->index >= Cudd_ReadSize(dd) - nOuts ) { assert( Cudd_ReadPerm(dd, bFunc->index) >= Cudd_ReadSize(dd) - nOuts ); aFunc = Abc_NtkBddFindAddConst( dd, Cudd_NotCond(bFunc, fCompl), nOuts ); Cudd_Ref( aFunc ); } else { aFunc0 = Abc_NtkBddToAdd_rec( dd, Cudd_Regular(cuddE(bFunc)), nOuts, tTable, fCompl ^ Cudd_IsComplement(cuddE(bFunc)) ); aFunc1 = Abc_NtkBddToAdd_rec( dd, cuddT(bFunc), nOuts, tTable, fCompl ); aFunc = Cudd_addIte( dd, Cudd_addIthVar(dd, bFunc->index), aFunc1, aFunc0 ); Cudd_Ref( aFunc ); } return (*ppSlot = aFunc); } /**Function************************************************************* Synopsis [R] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkBddToAdd( DdManager * dd, DdNode * bFunc, int nOuts ) { DdNode * aFunc, * aTemp, * bTemp; stmm_table * tTable; stmm_generator * gen; tTable = stmm_init_table( st__ptrcmp, st__ptrhash ); aFunc = Abc_NtkBddToAdd_rec( dd, Cudd_Regular(bFunc), nOuts, tTable, Cudd_IsComplement(bFunc) ); stmm_foreach_item( tTable, gen, (char **)&bTemp, (char **)&aTemp ) Cudd_RecursiveDeref( dd, aTemp ); stmm_free_table( tTable ); Cudd_Deref( aFunc ); return aFunc; } /**Function************************************************************* Synopsis [Recursively construct ADD for BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkAddToBdd_rec( DdManager * dd, DdNode * aFunc, int nIns, int nOuts, stmm_table * tTable ) { DdNode * bFunc0, * bFunc1, * bFunc; DdNode ** ppSlot; assert( !Cudd_IsComplement(aFunc) ); if ( stmm_find_or_add( tTable, (char *)aFunc, (char ***)&ppSlot ) ) return *ppSlot; if ( Cudd_IsConstant(aFunc) ) { assert( Cudd_ReadSize(dd) >= nIns + nOuts ); bFunc = Extra_bddBitsToCube( dd, (int)Cudd_V(aFunc), nOuts, dd->vars + nIns, 1 ); Cudd_Ref( bFunc ); } else { assert( aFunc->index < nIns ); bFunc0 = Abc_NtkAddToBdd_rec( dd, cuddE(aFunc), nIns, nOuts, tTable ); bFunc1 = Abc_NtkAddToBdd_rec( dd, cuddT(aFunc), nIns, nOuts, tTable ); bFunc = Cudd_bddIte( dd, Cudd_bddIthVar(dd, aFunc->index), bFunc1, bFunc0 ); Cudd_Ref( bFunc ); } return (*ppSlot = bFunc); } /**Function************************************************************* Synopsis [R] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkAddToBdd( DdManager * dd, DdNode * aFunc, int nIns, int nOuts ) { DdNode * bFunc, * bTemp, * aTemp; stmm_table * tTable; stmm_generator * gen; tTable = stmm_init_table( st__ptrcmp, st__ptrhash ); bFunc = Abc_NtkAddToBdd_rec( dd, aFunc, nIns, nOuts, tTable ); stmm_foreach_item( tTable, gen, (char **)&aTemp, (char **)&bTemp ) Cudd_RecursiveDeref( dd, bTemp ); stmm_free_table( tTable ); Cudd_Deref( bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Computes the characteristic function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkBddDecCharFunc( DdManager * dd, DdNode ** pFuncs, int nOuts, int Mask, int nBits ) { DdNode * bFunc, * bTemp, * bExor, * bVar; int i, Count = 0; bFunc = Cudd_ReadOne( dd ); Cudd_Ref( bFunc ); for ( i = 0; i < nOuts; i++ ) { if ( (Mask & (1 << i)) == 0 ) continue; Count++; bVar = Cudd_bddIthVar( dd, dd->size - nOuts + i ); bExor = Cudd_bddXor( dd, pFuncs[i], bVar ); Cudd_Ref( bExor ); bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_Not(bExor) ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bExor ); } Cudd_Deref( bFunc ); assert( Count == nBits ); return bFunc; } /**Function************************************************************* Synopsis [Evaluate Sasao's decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkBddDecTry( reo_man * pReo, DdManager * dd, DdNode ** pFuncs, int nIns, int nOuts, int Mask, int nBits ) { // int fReorder = 0; DdNode * bFunc;//, * aFunc, * aFuncNew; // derive the characteristic function bFunc = Abc_NtkBddDecCharFunc( dd, pFuncs, nOuts, Mask, nBits ); Cudd_Ref( bFunc ); /* // transfer to ADD aFunc = Abc_NtkBddToAdd( dd, bFunc, nOuts ); Cudd_Ref( aFunc ); Cudd_RecursiveDeref( dd, bFunc ); //Abc_NodeShowBddOne( dd, aFunc ); // perform reordering for BDD width if ( fReorder ) { aFuncNew = Extra_Reorder( pReo, dd, aFunc, NULL ); Cudd_Ref( aFuncNew ); printf( "Before = %d. After = %d.\n", Cudd_DagSize(aFunc), Cudd_DagSize(aFuncNew) ); Cudd_RecursiveDeref( dd, aFunc ); } else aFuncNew = aFunc; // get back to BDD bFunc = Abc_NtkAddToBdd( dd, aFuncNew, nIns, nOuts ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, aFuncNew ); //Abc_NodeShowBddOne( dd, bFunc ); // print the result // reoProfileWidthPrint( pReo ); */ Cudd_Deref( bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Evaluate Sasao's decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkBddDecInt( reo_man * pReo, DdManager * dd, DdNode ** pFuncs, int nIns, int nOuts ) { /* int i, k; for ( i = 1; i <= nOuts; i++ ) { for ( k = 0; k < (1<pName = Extra_UtilStrsav(pNtk->pName); // create inputs for CIs pNodeNew = Abc_NtkCreateNode( pNtkNew ); Abc_NtkForEachCi( pNtk, pNode, i ) { pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); Abc_ObjAssignName( pNode->pCopy, Abc_ObjName(pNode), NULL ); } // create inputs for COs Abc_NtkForEachCo( pNtk, pNode, i ) { pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); Abc_ObjAssignName( pNode->pCopy, Abc_ObjName(pNode), NULL ); } // transfer BDD pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFunc ); Cudd_Ref( (DdNode *)pNodeNew->pData ); // transfer BDD into to be the local function pNodePo = Abc_NtkCreatePo( pNtkNew ); Abc_ObjAddFanin( pNodePo, pNodeNew ); Abc_ObjAssignName( pNodePo, "out", NULL ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateFromCharFunc(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Evaluate Sasao's decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkBddDec( Abc_Ntk_t * pNtk, int fVerbose ) { int nBddSizeMax = 1000000; int fDropInternal = 0; int fReorder = 1; Abc_Ntk_t * pNtkNew; reo_man * pReo; DdManager * dd; DdNode * pFuncs[BDD_FUNC_MAX]; DdNode * bFunc; Abc_Obj_t * pNode; int i; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkCoNum(pNtk) <= BDD_FUNC_MAX ); dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddSizeMax, fDropInternal, fReorder, fVerbose ); if ( dd == NULL ) { Abc_Print( -1, "Construction of global BDDs has failed.\n" ); return NULL; } // collect global BDDs Abc_NtkForEachCo( pNtk, pNode, i ) pFuncs[i] = (DdNode *)Abc_ObjGlobalBdd(pNode); // create new variables at the bottom assert( dd->size == Abc_NtkCiNum(pNtk) ); for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) Cudd_addNewVarAtLevel( dd, dd->size ); // prepare reordering engine pReo = Extra_ReorderInit( Abc_NtkCiNum(pNtk), 1000 ); Extra_ReorderSetMinimizationType( pReo, REO_MINIMIZE_WIDTH ); Extra_ReorderSetVerification( pReo, 1 ); Extra_ReorderSetVerbosity( pReo, 1 ); // derive characteristic function bFunc = Abc_NtkBddDecInt( pReo, dd, pFuncs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk) ); Cudd_Ref( bFunc ); Extra_ReorderQuit( pReo ); Abc_NtkExploreCofs( dd, bFunc, dd->vars, Abc_NtkCiNum(pNtk), 6 ); // create new network // pNtkNew = Abc_NtkCreateFromCharFunc( pNtk, dd, bFunc ); pNtkNew = Abc_NtkDup( pNtk ); // cleanup Cudd_RecursiveDeref( dd, bFunc ); Abc_NtkFreeGlobalBdds( pNtk, 1 ); return pNtkNew; } #else Abc_Ntk_t * Abc_NtkBddDec( Abc_Ntk_t * pNtk, int fVerbose ) { return NULL; } #endif ABC_NAMESPACE_IMPL_END //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcCollapse.c000066400000000000000000001102771300674244400242300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcCollapse.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Collapsing the network into two-levels.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/gia/gia.h" #include "misc/vec/vecWec.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.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_NodeMinimumBase2( 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; } // add fanins vFanins = Vec_PtrAlloc( Abc_ObjFaninNum(pNode) ); Abc_NodeCollectFanins( pNode, vFanins ); Vec_IntClear( &pNode->vFanins ); for ( i = 0; i < vFanins->nSize; i++ ) if ( vSupport->pArray[i] != 0 ) // useful Vec_IntPush( &pNode->vFanins, Abc_ObjId((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_NtkMinimumBase2( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pFanin; int i, k, Counter; assert( Abc_NtkIsBddLogic(pNtk) ); // remove all fanouts Abc_NtkForEachObj( pNtk, pNode, i ) Vec_IntClear( &pNode->vFanouts ); // add useful fanins Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += Abc_NodeMinimumBase2( pNode ); // add fanouts Abc_NtkForEachObj( pNtk, pNode, i ) Abc_ObjForEachFanin( pNode, pFanin, k ) Vec_IntPush( &pFanin->vFanouts, Abc_ObjId(pNode) ); return Counter; } /**Function************************************************************* Synopsis [Collapses the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ) { Abc_Obj_t * pNodeNew, * pTemp; int i; // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); // add the fanins in the order, in which they appear in the reordered manager Abc_NtkForEachCi( pNtkNew, pTemp, i ) Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, dd->invperm[i]) ); // transfer the function pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFunc ); Cudd_Ref( (DdNode *)pNodeNew->pData ); return pNodeNew; } Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pDriver, * pNodeNew; DdManager * dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk ); int i; // extract don't-care and compute ISOP if ( pNtk->pExdc ) { DdManager * ddExdc = NULL; DdNode * bBddMin, * bBddDc, * bBddL, * bBddU; assert( Abc_NtkIsStrash(pNtk->pExdc) ); assert( Abc_NtkCoNum(pNtk->pExdc) == 1 ); // compute the global BDDs if ( Abc_NtkBuildGlobalBdds(pNtk->pExdc, 10000000, 1, 1, 0) == NULL ) return NULL; // transfer tot the same manager ddExdc = (DdManager *)Abc_NtkGlobalBddMan( pNtk->pExdc ); bBddDc = (DdNode *)Abc_ObjGlobalBdd(Abc_NtkCo(pNtk->pExdc, 0)); bBddDc = Cudd_bddTransfer( ddExdc, dd, bBddDc ); Cudd_Ref( bBddDc ); Abc_NtkFreeGlobalBdds( pNtk->pExdc, 1 ); // minimize the output Abc_NtkForEachCo( pNtk, pNode, i ) { bBddMin = (DdNode *)Abc_ObjGlobalBdd(pNode); // derive lower and uppwer bound bBddL = Cudd_bddAnd( dd, bBddMin, Cudd_Not(bBddDc) ); Cudd_Ref( bBddL ); bBddU = Cudd_bddAnd( dd, Cudd_Not(bBddMin), Cudd_Not(bBddDc) ); Cudd_Ref( bBddU ); Cudd_RecursiveDeref( dd, bBddMin ); // compute new one bBddMin = Cudd_bddIsop( dd, bBddL, Cudd_Not(bBddU) ); Cudd_Ref( bBddMin ); Cudd_RecursiveDeref( dd, bBddL ); Cudd_RecursiveDeref( dd, bBddU ); // update global BDD Abc_ObjSetGlobalBdd( pNode, bBddMin ); //Extra_bddPrint( dd, bBddMin ); printf( "\n" ); } Cudd_RecursiveDeref( dd, bBddDc ); } // start the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); // make sure the new manager has the same number of inputs Cudd_bddIthVar( (DdManager *)pNtkNew->pManFunc, dd->size-1 ); // process the POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); pDriver = Abc_ObjFanin0(pNode); if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) ) { Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy ); continue; } pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, (DdNode *)Abc_ObjGlobalBdd(pNode) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Extra_ProgressBarStop( pProgress ); return pNtkNew; } Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ) { Abc_Ntk_t * pNtkNew; abctime clk = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); // compute the global BDDs if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) return NULL; if ( fVerbose ) { DdManager * dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk ); printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); ABC_PRT( "BDD construction time", Abc_Clock() - clk ); } // create the new network pNtkNew = Abc_NtkFromGlobalBdds( pNtk ); Abc_NtkFreeGlobalBdds( pNtk, 1 ); if ( pNtkNew == NULL ) return NULL; // make the network minimum base Abc_NtkMinimumBase2( pNtkNew ); if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkCollapse: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } #else Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ) { return NULL; } #endif #if 0 /**Function************************************************************* Synopsis [Derives GIA for the cone of one output and computes its SOP.] 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_NtkClpOneGia( Abc_Ntk_t * pNtk, int iCo, Vec_Int_t * vSupp ) { int i, iCi, iLit; Abc_Obj_t * pNode; Gia_Man_t * pNew, * pTemp; pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( pNtk->pName ); pNew->pSpec = Abc_UtilStrsav( pNtk->pSpec ); Gia_ManHashStart( pNew ); // primary inputs Abc_AigConst1(pNtk)->iTemp = 1; Vec_IntForEachEntry( vSupp, iCi, i ) Abc_NtkCi(pNtk, iCi)->iTemp = Gia_ManAppendCi(pNew); // create the first cone Abc_NtkIncrementTravId( pNtk ); pNode = Abc_NtkCo( pNtk, iCo ); 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; } Vec_Str_t * Abc_NtkClpOne( Abc_Ntk_t * pNtk, int iCo, int nCubeLim, int nBTLimit, int fVerbose, int fCanon, int fReverse, Vec_Int_t * vSupp ) { Vec_Str_t * vSop; abctime clk = Abc_Clock(); extern Vec_Str_t * Bmc_CollapseOne( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ); Gia_Man_t * pGia = Abc_NtkClpOneGia( pNtk, iCo, vSupp ); if ( fVerbose ) printf( "Output %4d: Supp = %4d. Cone =%6d.\n", iCo, Vec_IntSize(vSupp), Gia_ManAndNum(pGia) ); vSop = Bmc_CollapseOne( pGia, nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); Gia_ManStop( pGia ); if ( vSop == NULL ) return NULL; if ( Vec_StrSize(vSop) == 4 ) // constant Vec_IntClear(vSupp); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return vSop; } /**Function************************************************************* Synopsis [Collect structural support for all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Abc_NtkCreateCoSupps( Abc_Ntk_t * pNtk, int fVerbose ) { abctime clk = Abc_Clock(); Abc_Obj_t * pNode; int i; Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachCi( pNtk, pNode, i ) Vec_IntPush( Vec_WecEntry(vSupps, pNode->Id), i ); Abc_NtkForEachNode( pNtk, pNode, i ) Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Abc_ObjFanin0(pNode)->Id), Vec_WecEntry(vSupps, Abc_ObjFanin1(pNode)->Id), Vec_WecEntry(vSupps, pNode->Id) ); if ( fVerbose ) Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); return vSupps; } /**Function************************************************************* Synopsis [Derive array of COs sorted by cone size in the reverse order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareByTemp( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { int Diff = (*pp2)->iTemp - (*pp1)->iTemp; 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; } Vec_Ptr_t * Abc_NtkCreateCoOrder( Abc_Ntk_t * pNtk, Vec_Wec_t * vSupps ) { Abc_Obj_t * pNode; int i; Vec_Ptr_t * vNodes = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { pNode->iTemp = Vec_IntSize( Vec_WecEntry(vSupps, Abc_ObjFaninId0(pNode)) ); Vec_PtrPush( vNodes, pNode ); } // order objects alphabetically qsort( (void *)Vec_PtrArray(vNodes), Vec_PtrSize(vNodes), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareByTemp ); // cleanup // Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) // printf( "%s %d ", Abc_ObjName(pNode), pNode->iTemp ); // printf( "\n" ); return vNodes; } /**Function************************************************************* Synopsis [SAT-based collapsing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkFromSopsOne( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int iCo, Vec_Int_t * vSupp, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { Abc_Obj_t * pNodeNew; Vec_Str_t * vSop; int i, iCi; // compute SOP of the node vSop = Abc_NtkClpOne( pNtk, iCo, nCubeLim, nBTLimit, fVerbose, fCanon, fReverse, vSupp ); if ( vSop == NULL ) return NULL; // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); // add fanins if ( Vec_StrSize(vSop) > 4 ) // non-constant SOP Vec_IntForEachEntry( vSupp, iCi, i ) Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, iCi) ); // transfer the function pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_StrArray(vSop) ); Vec_StrFree( vSop ); return pNodeNew; } Abc_Ntk_t * Abc_NtkFromSops( Abc_Ntk_t * pNtk, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fVerbose ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pDriver, * pNodeNew; Vec_Ptr_t * vDriverCopy, * vCoNodes, * vDfsNodes; Vec_Int_t * vNodeCoIds, * vLevel; Vec_Wec_t * vSupps; int i; // Abc_NtkForEachCi( pNtk, pNode, i ) // printf( "%d ", Abc_ObjFanoutNum(pNode) ); // printf( "\n" ); // compute structural supports vSupps = Abc_NtkCreateCoSupps( pNtk, fVerbose ); // order CO nodes by support size vCoNodes = Abc_NtkCreateCoOrder( pNtk, vSupps ); // compute cost of the largest node if ( nCubeLim > 0 ) { word Cost; pNode = (Abc_Obj_t *)Vec_PtrEntry( vCoNodes, 0 ); vDfsNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 ); vLevel = Vec_WecEntry( vSupps, Abc_ObjFaninId0(pNode) ); Cost = (word)Vec_PtrSize(vDfsNodes) * (word)Vec_IntSize(vLevel) * (word)nCubeLim; if ( Cost > (word)nCostMax ) { printf( "Cost of the largest output cone exceeded the limit (%d * %d * %d > %d).\n", Vec_PtrSize(vDfsNodes), Vec_IntSize(vLevel), nCubeLim, nCostMax ); Vec_PtrFree( vDfsNodes ); Vec_PtrFree( vCoNodes ); Vec_WecFree( vSupps ); return NULL; } Vec_PtrFree( vDfsNodes ); } // collect CO IDs in this order vNodeCoIds = Vec_IntAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) pNode->iTemp = i; Vec_PtrForEachEntry( Abc_Obj_t *, vCoNodes, pNode, i ) Vec_IntPush( vNodeCoIds, pNode->iTemp ); // start the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // collect driver copies vDriverCopy = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); // Abc_NtkForEachCo( pNtk, pNode, i ) Vec_PtrForEachEntry( Abc_Obj_t *, vCoNodes, pNode, i ) Vec_PtrPush( vDriverCopy, Abc_ObjFanin0(pNode)->pCopy ); // process the POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); // Abc_NtkForEachCo( pNtk, pNode, i ) Vec_PtrForEachEntry( Abc_Obj_t *, vCoNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); pDriver = Abc_ObjFanin0(pNode); if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) ) { Abc_ObjAddFanin( pNode->pCopy, (Abc_Obj_t *)Vec_PtrEntry(vDriverCopy, i) ); continue; } if ( Abc_ObjIsCi(pDriver) ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNodeNew, (Abc_Obj_t *)Vec_PtrEntry(vDriverCopy, i) ); pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_ObjFaninC0(pNode) ? "0 1\n" : "1 1\n" ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); continue; } if ( pDriver == Abc_AigConst1(pNtk) ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_ObjFaninC0(pNode) ? " 0\n" : " 1\n" ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); continue; } pNodeNew = Abc_NtkFromSopsOne( pNtkNew, pNtk, Vec_IntEntry(vNodeCoIds, i), Vec_WecEntry(vSupps, Abc_ObjFanin0(pNode)->Id), nCubeLim, nBTLimit, fCanon, fReverse, i ? 0 : fVerbose ); if ( pNodeNew == NULL ) { Abc_NtkDelete( pNtkNew ); pNtkNew = NULL; break; } Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Vec_PtrFree( vDriverCopy ); Vec_PtrFree( vCoNodes ); Vec_IntFree( vNodeCoIds ); Vec_WecFree( vSupps ); Extra_ProgressBarStop( pProgress ); return pNtkNew; } Abc_Ntk_t * Abc_NtkCollapseSat( Abc_Ntk_t * pNtk, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fVerbose ) { Abc_Ntk_t * pNtkNew; assert( Abc_NtkIsStrash(pNtk) ); // create the new network pNtkNew = Abc_NtkFromSops( pNtk, nCubeLim, nBTLimit, nCostMax, fCanon, fReverse, fVerbose ); if ( pNtkNew == NULL ) return NULL; if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkCollapseSat: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } #endif extern Vec_Wec_t * Gia_ManCreateCoSupps( Gia_Man_t * p, int fVerbose ); extern int Gia_ManCoLargestSupp( Gia_Man_t * p, Vec_Wec_t * vSupps ); extern Vec_Wec_t * Gia_ManIsoStrashReduceInt( Gia_Man_t * p, Vec_Wec_t * vSupps, int fVerbose ); extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); /**Function************************************************************* Synopsis [Derives GIA for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkClpGia_rec( Gia_Man_t * pNew, Abc_Obj_t * pNode ) { int iLit0, iLit1; if ( pNode->iTemp >= 0 ) return pNode->iTemp; assert( Abc_ObjIsNode( pNode ) ); iLit0 = Abc_NtkClpGia_rec( pNew, Abc_ObjFanin0(pNode) ); iLit1 = Abc_NtkClpGia_rec( pNew, Abc_ObjFanin1(pNode) ); iLit0 = Abc_LitNotCond( iLit0, Abc_ObjFaninC0(pNode) ); iLit1 = Abc_LitNotCond( iLit1, Abc_ObjFaninC1(pNode) ); return (pNode->iTemp = Gia_ManAppendAnd(pNew, iLit0, iLit1)); } Gia_Man_t * Abc_NtkClpGia( Abc_Ntk_t * pNtk ) { int i, iLit; Gia_Man_t * pNew; Abc_Obj_t * pNode; assert( Abc_NtkIsStrash(pNtk) ); pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( pNtk->pName ); pNew->pSpec = Abc_UtilStrsav( pNtk->pSpec ); Abc_NtkForEachObj( pNtk, pNode, i ) pNode->iTemp = -1; Abc_AigConst1(pNtk)->iTemp = 1; Abc_NtkForEachCi( pNtk, pNode, i ) pNode->iTemp = Gia_ManAppendCi(pNew); Abc_NtkForEachCo( pNtk, pNode, i ) { iLit = Abc_NtkClpGia_rec( pNew, Abc_ObjFanin0(pNode) ); iLit = Abc_LitNotCond( iLit, Abc_ObjFaninC0(pNode) ); Gia_ManAppendCo( pNew, iLit ); } return pNew; } /**Function************************************************************* Synopsis [Minimize SOP by removing redundant variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define Abc_NtkSopForEachCube( pSop, nVars, pCube ) for ( pCube = (pSop); *pCube; pCube += (nVars) + 3 ) int Abc_NtkCollapseReduce( Vec_Str_t * vSop, Vec_Int_t * vSupp, Vec_Int_t * vClass, Vec_Wec_t * vSupps ) { int j = 0, i, k, iCo, iVar, nVars = Vec_IntSize(vSupp); char * pCube, * pSop = Vec_StrArray(vSop); Vec_Int_t * vPres; if ( Vec_StrSize(vSop) == 4 ) // constant { Vec_IntForEachEntry( vClass, iCo, i ) Vec_IntClear( Vec_WecEntry(vSupps, iCo) ); return 1; } vPres = Vec_IntStart( nVars ); Abc_NtkSopForEachCube( pSop, nVars, pCube ) for ( k = 0; k < nVars; k++ ) if ( pCube[k] != '-' ) Vec_IntWriteEntry( vPres, k, 1 ); if ( Vec_IntCountZero(vPres) == 0 ) { Vec_IntFree( vPres ); return 0; } // reduce cubes Abc_NtkSopForEachCube( pSop, nVars, pCube ) for ( k = 0; k < nVars + 3; k++ ) if ( k >= nVars || Vec_IntEntry(vPres, k) ) Vec_StrWriteEntry( vSop, j++, pCube[k] ); Vec_StrWriteEntry( vSop, j++, '\0' ); Vec_StrShrink( vSop, j ); // reduce support Vec_IntForEachEntry( vClass, iCo, i ) { j = 0; vSupp = Vec_WecEntry( vSupps, iCo ); Vec_IntForEachEntry( vSupp, iVar, k ) if ( Vec_IntEntry(vPres, k) ) Vec_IntWriteEntry( vSupp, j++, iVar ); Vec_IntShrink( vSupp, j ); } Vec_IntFree( vPres ); // if ( Vec_IntSize(vSupp) != Abc_SopGetVarNum(Vec_StrArray(vSop)) ) // printf( "Mismatch!!!\n" ); return 1; } /**Function************************************************************* Synopsis [Derives SAT solver for one output from the shared CNF.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Abc_NtkClpDeriveSatSolver( Cnf_Dat_t * pCnf, int iCoObjId, Vec_Int_t * vSupp, Vec_Int_t * vAnds, Vec_Int_t * vMap, sat_solver ** ppSat1, sat_solver ** ppSat2, sat_solver ** ppSat3 ) { int i, k, iObj, status, nVars = 2; // int i, k, iObj, status, nVars = 1; Vec_Int_t * vLits = Vec_IntAlloc( 16 ); sat_solver * pSat = sat_solver_new(); if ( ppSat1 ) *ppSat1 = sat_solver_new(); if ( ppSat2 ) *ppSat2 = sat_solver_new(); if ( ppSat3 ) *ppSat3 = sat_solver_new(); // assign SAT variable numbers Vec_IntWriteEntry( vMap, iCoObjId, nVars++ ); Vec_IntForEachEntry( vSupp, iObj, k ) Vec_IntWriteEntry( vMap, iObj, nVars++ ); Vec_IntForEachEntry( vAnds, iObj, k ) if ( pCnf->pObj2Clause[iObj] != -1 ) Vec_IntWriteEntry( vMap, iObj, nVars++ ); // Vec_IntForEachEntry( vSupp, iObj, k ) // Vec_IntWriteEntry( vMap, iObj, nVars++ ); // create clauses for the internal nodes and for the output sat_solver_setnvars( pSat, nVars ); if ( ppSat1 ) sat_solver_setnvars( *ppSat1, nVars ); if ( ppSat2 ) sat_solver_setnvars( *ppSat2, nVars ); if ( ppSat3 ) sat_solver_setnvars( *ppSat3, nVars ); Vec_IntPush( vAnds, iCoObjId ); Vec_IntForEachEntry( vAnds, iObj, k ) { int iClaBeg, iClaEnd, * pLit; if ( pCnf->pObj2Clause[iObj] == -1 ) continue; iClaBeg = pCnf->pObj2Clause[iObj]; iClaEnd = iClaBeg + pCnf->pObj2Count[iObj]; assert( iClaBeg < iClaEnd ); for ( i = iClaBeg; i < iClaEnd; i++ ) { Vec_IntClear( vLits ); for ( pLit = pCnf->pClauses[i]; pLit < pCnf->pClauses[i+1]; pLit++ ) Vec_IntPush( vLits, Abc_Lit2LitV(Vec_IntArray(vMap), *pLit) ); status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); assert( status ); (void) status; if ( ppSat1 ) sat_solver_addclause( *ppSat1, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); if ( ppSat2 ) sat_solver_addclause( *ppSat2, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); if ( ppSat3 ) sat_solver_addclause( *ppSat3, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); } } Vec_IntPop( vAnds ); Vec_IntFree( vLits ); assert( nVars == sat_solver_nvars(pSat) ); return pSat; } /**Function************************************************************* Synopsis [Computes SOPs for each output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Abc_NtkClpGiaOne( Gia_Man_t * p, int iCo, int nCubeLim, int nBTLimit, int fCanon, int fReverse, Vec_Int_t * vSupp, int fVerbose, Vec_Int_t * vClass, Vec_Wec_t * vSupps ) { Vec_Str_t * vSop; abctime clk = Abc_Clock(); extern Vec_Str_t * Bmc_CollapseOneOld( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ); Gia_Man_t * pGia = Gia_ManDupCones( p, &iCo, 1, 1 ); if ( fVerbose ) printf( "Output %4d: Supp = %4d. Cone =%6d.\n", iCo, Vec_IntSize(vSupp), Gia_ManAndNum(pGia) ); vSop = Bmc_CollapseOneOld( pGia, nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); Gia_ManStop( pGia ); if ( vSop == NULL ) return NULL; Abc_NtkCollapseReduce( vSop, vSupp, vClass, vSupps ); if ( fVerbose ) printf( "Supp new = %4d. Sop = %4d. ", Vec_IntSize(vSupp), Vec_StrSize(vSop)/(Vec_IntSize(vSupp) +3) ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return vSop; } Vec_Str_t * Abc_NtkClpGiaOne2( Cnf_Dat_t * pCnf, Gia_Man_t * p, int iCo, int nCubeLim, int nBTLimit, int fCanon, int fReverse, Vec_Int_t * vSupp, Vec_Int_t * vMap, int fVerbose, Vec_Int_t * vClass, Vec_Wec_t * vSupps ) { Vec_Str_t * vSop; sat_solver * pSat, * pSat1 = NULL, * pSat2 = NULL, * pSat3 = NULL; Gia_Obj_t * pObj; abctime clk = Abc_Clock(); extern Vec_Str_t * Bmc_CollapseOne_int( sat_solver * pSat, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ); extern Vec_Str_t * Bmc_CollapseOne_int2( sat_solver * pSat, sat_solver * pSat2, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ); extern Vec_Str_t * Bmc_CollapseOne_int3( sat_solver * pSat, sat_solver * pSat1, sat_solver * pSat2, sat_solver * pSat3, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ); int i, iCoObjId = Gia_ObjId( p, Gia_ManCo(p, iCo) ); Vec_Int_t * vAnds = Vec_IntAlloc( 100 ); Vec_Int_t * vSuppObjs = Vec_IntAlloc( 100 ); Gia_ManForEachCiVec( vSupp, p, pObj, i ) Vec_IntPush( vSuppObjs, Gia_ObjId(p, pObj) ); Gia_ManIncrementTravId( p ); Gia_ManCollectAnds( p, &iCoObjId, 1, vAnds, NULL ); assert( Vec_IntSize(vAnds) > 0 ); // pSat = Abc_NtkClpDeriveSatSolver( pCnf, iCoObjId, vSuppObjs, vAnds, vMap, &pSat1, &pSat2, &pSat3 ); pSat = Abc_NtkClpDeriveSatSolver( pCnf, iCoObjId, vSuppObjs, vAnds, vMap, NULL, NULL, NULL ); Vec_IntFree( vSuppObjs ); if ( fVerbose ) printf( "Output %4d: Supp = %4d. Cone =%6d.\n", iCo, Vec_IntSize(vSupp), Vec_IntSize(vAnds) ); // vSop = Bmc_CollapseOne_int3( pSat, pSat1, pSat2, pSat3, Vec_IntSize(vSupp), nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); // vSop = Bmc_CollapseOne_int2( pSat, pSat1, Vec_IntSize(vSupp), nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); vSop = Bmc_CollapseOne_int( pSat, Vec_IntSize(vSupp), nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); sat_solver_delete( pSat ); if ( pSat1 ) sat_solver_delete( pSat1 ); if ( pSat2 ) sat_solver_delete( pSat2 ); if ( pSat3 ) sat_solver_delete( pSat3 ); Vec_IntFree( vAnds ); if ( vSop == NULL ) return NULL; Abc_NtkCollapseReduce( vSop, vSupp, vClass, vSupps ); if ( fVerbose ) printf( "Supp new = %4d. Sop = %4d. ", Vec_IntSize(vSupp), Vec_StrSize(vSop)/(Vec_IntSize(vSupp) +3) ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return vSop; } Vec_Ptr_t * Abc_GiaDeriveSops( Abc_Ntk_t * pNtkNew, Gia_Man_t * p, Vec_Wec_t * vSupps, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fCnfShared, int fVerbose ) { ProgressBar * pProgress; abctime clk = Abc_Clock(); Vec_Ptr_t * vSops = NULL, * vSopsRepr; Vec_Int_t * vReprs, * vClass, * vReprSuppSizes; int i, k, Entry, iCo, * pOrder; Vec_Wec_t * vClasses; Cnf_Dat_t * pCnf = NULL; Vec_Int_t * vMap = NULL; // derive classes of outputs vClasses = Gia_ManIsoStrashReduceInt( p, vSupps, 0 ); if ( fVerbose ) { printf( "Considering %d (out of %d) outputs. ", Vec_WecSize(vClasses), Gia_ManCoNum(p) ); Abc_PrintTime( 1, "Reduction time", Abc_Clock() - clk ); } // derive representatives vReprs = Vec_WecCollectFirsts( vClasses ); vReprSuppSizes = Vec_IntAlloc( Vec_IntSize(vReprs) ); Vec_IntForEachEntry( vReprs, Entry, i ) Vec_IntPush( vReprSuppSizes, Vec_IntSize(Vec_WecEntry(vSupps, Entry)) ); pOrder = Abc_MergeSortCost( Vec_IntArray(vReprSuppSizes), Vec_IntSize(vReprSuppSizes) ); Vec_IntFree( vReprSuppSizes ); // consider SOPs for representatives if ( fCnfShared ) { vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); pCnf = Mf_ManGenerateCnf( p, 8, 1, 0, 0 ); } vSopsRepr = Vec_PtrStart( Vec_IntSize(vReprs) ); pProgress = Extra_ProgressBarStart( stdout, Vec_IntSize(vReprs) ); Extra_ProgressBarUpdate( pProgress, 0, NULL ); for ( i = 0; i < Vec_IntSize(vReprs); i++ ) { int iEntry = pOrder[Vec_IntSize(vReprs) - 1 - i]; int iCoThis = Vec_IntEntry( vReprs, iEntry ); Vec_Int_t * vSupp = Vec_WecEntry( vSupps, iCoThis ); Vec_Str_t * vSop; if ( Vec_IntSize(vSupp) < 2 ) { Vec_PtrWriteEntry( vSopsRepr, iEntry, (void *)(ABC_PTRINT_T)1 ); continue; } if ( fCnfShared && !fCanon ) vSop = Abc_NtkClpGiaOne2( pCnf, p, iCoThis, nCubeLim, nBTLimit, fCanon, fReverse, vSupp, vMap, i ? 0 : fVerbose, Vec_WecEntry(vClasses, iEntry), vSupps ); else vSop = Abc_NtkClpGiaOne( p, iCoThis, nCubeLim, nBTLimit, fCanon, fReverse, vSupp, i ? 0 : fVerbose, Vec_WecEntry(vClasses, iEntry), vSupps ); if ( vSop == NULL ) goto finish; assert( Vec_IntSize( Vec_WecEntry(vSupps, iCoThis) ) == Abc_SopGetVarNum(Vec_StrArray(vSop)) ); Extra_ProgressBarUpdate( pProgress, i, NULL ); Vec_PtrWriteEntry( vSopsRepr, iEntry, Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_StrArray(vSop) ) ); Vec_StrFree( vSop ); } Extra_ProgressBarStop( pProgress ); if ( fCnfShared ) { Cnf_DataFree( pCnf ); Vec_IntFree( vMap ); } // derive SOPs for each output vSops = Vec_PtrStart( Gia_ManCoNum(p) ); Vec_WecForEachLevel ( vClasses, vClass, i ) Vec_IntForEachEntry( vClass, iCo, k ) Vec_PtrWriteEntry( vSops, iCo, Vec_PtrEntry(vSopsRepr, i) ); assert( Vec_PtrCountZero(vSops) == 0 ); /* // verify for ( i = 0; i < Gia_ManCoNum(p); i++ ) { Vec_Int_t * vSupp = Vec_WecEntry( vSupps, i ); char * pSop = (char *)Vec_PtrEntry( vSops, i ); assert( Vec_IntSize(vSupp) == Abc_SopGetVarNum(pSop) ); } */ // cleanup finish: ABC_FREE( pOrder ); Vec_IntFree( vReprs ); Vec_WecFree( vClasses ); Vec_PtrFree( vSopsRepr ); return vSops; } Abc_Ntk_t * Abc_NtkFromSopsInt( Abc_Ntk_t * pNtk, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fCnfShared, int fVerbose ) { Abc_Ntk_t * pNtkNew; Gia_Man_t * pGia; Vec_Wec_t * vSupps; Vec_Int_t * vSupp; Vec_Ptr_t * vSops; Abc_Obj_t * pNode, * pNodeNew, * pDriver; int i, k, iCi; pGia = Abc_NtkClpGia( pNtk ); vSupps = Gia_ManCreateCoSupps( pGia, fVerbose ); // check the largest output if ( nCubeLim > 0 && nCostMax > 0 ) { int iCoMax = Gia_ManCoLargestSupp( pGia, vSupps ); int iObjMax = Gia_ObjId( pGia, Gia_ManCo(pGia, iCoMax) ); int nSuppMax = Vec_IntSize( Vec_WecEntry(vSupps, iCoMax) ); int nNodeMax = Gia_ManConeSize( pGia, &iObjMax, 1 ); word Cost = (word)nNodeMax * (word)nSuppMax * (word)nCubeLim; if ( Cost > (word)nCostMax ) { printf( "Cost of the largest output cone exceeded the limit (%d * %d * %d > %d).\n", nNodeMax, nSuppMax, nCubeLim, nCostMax ); Gia_ManStop( pGia ); Vec_WecFree( vSupps ); return NULL; } } pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); vSops = Abc_GiaDeriveSops( pNtkNew, pGia, vSupps, nCubeLim, nBTLimit, nCostMax, fCanon, fReverse, fCnfShared, fVerbose ); Gia_ManStop( pGia ); if ( vSops == NULL ) { Vec_WecFree( vSupps ); Abc_NtkDelete( pNtkNew ); return NULL; } Abc_NtkForEachCo( pNtk, pNode, i ) { pDriver = Abc_ObjFanin0(pNode); if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) ) { Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy ); continue; } if ( Abc_ObjIsCi(pDriver) ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNodeNew, pDriver->pCopy ); pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_ObjFaninC0(pNode) ? "0 1\n" : "1 1\n" ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); continue; } if ( pDriver == Abc_AigConst1(pNtk) ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_ObjFaninC0(pNode) ? " 0\n" : " 1\n" ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); continue; } pNodeNew = Abc_NtkCreateNode( pNtkNew ); vSupp = Vec_WecEntry( vSupps, i ); Vec_IntForEachEntry( vSupp, iCi, k ) Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, iCi) ); pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, (const char*)Vec_PtrEntry( vSops, i ) ); assert( pNodeNew->pData != (void *)(ABC_PTRINT_T)1 ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Vec_WecFree( vSupps ); Vec_PtrFree( vSops ); Abc_NtkSortSops( pNtkNew ); return pNtkNew; } Abc_Ntk_t * Abc_NtkCollapseSat( Abc_Ntk_t * pNtk, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fCnfShared, int fVerbose ) { Abc_Ntk_t * pNtkNew; assert( Abc_NtkIsStrash(pNtk) ); pNtkNew = Abc_NtkFromSopsInt( pNtk, nCubeLim, nBTLimit, nCostMax, fCanon, fReverse, fCnfShared, fVerbose ); if ( pNtkNew == NULL ) return NULL; if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkCollapseSat: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcCut.c000066400000000000000000000524701300674244400232210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface to cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/cut/cut.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); extern int nTotal, nGood, nEqual; static Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCutsSubtractFanunt( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC; int i, Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !Abc_NodeIsMuxType(pObj) ) continue; pFanC = Abc_NodeRecognizeMux( pObj, &pFan1, &pFan0 ); pFanC = Abc_ObjRegular(pFanC); pFan0 = Abc_ObjRegular(pFan0); assert( pFanC->vFanouts.nSize > 1 ); pFanC->vFanouts.nSize--; Counter++; if ( Abc_NodeIsExorType(pObj) ) { assert( pFan0->vFanouts.nSize > 1 ); pFan0->vFanouts.nSize--; Counter++; } } printf("Substracted %d fanouts\n", Counter ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCutsAddFanunt( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFan0, * pFan1, * pFanC; int i, Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !Abc_NodeIsMuxType(pObj) ) continue; pFanC = Abc_NodeRecognizeMux( pObj, &pFan1, &pFan0 ); pFanC = Abc_ObjRegular(pFanC); pFan0 = Abc_ObjRegular(pFan0); pFanC->vFanouts.nSize++; Counter++; if ( Abc_NodeIsExorType(pObj) ) { pFan0->vFanouts.nSize++; Counter++; } } printf("Added %d fanouts\n", Counter ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) { ProgressBar * pProgress; Cut_Man_t * p; Cut_Cut_t * pList; Abc_Obj_t * pObj, * pNode; Vec_Ptr_t * vNodes; Vec_Int_t * vChoices; int i; abctime clk = Abc_Clock(); extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); if ( pParams->fAdjust ) Abc_NtkCutsSubtractFanunt( pNtk ); nTotal = nGood = nEqual = 0; assert( Abc_NtkIsStrash(pNtk) ); // start the manager pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); p = Cut_ManStart( pParams ); // compute node attributes if local or global cuts are requested if ( pParams->fGlobal || pParams->fLocal ) { extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) ); } // prepare for cut dropping if ( pParams->fDrop ) Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); // set cuts for PIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( p, pObj->Id ); // compute cuts for internal nodes vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs vChoices = Vec_IntAlloc( 100 ); pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // when we reached a CO, it is time to deallocate the cuts if ( Abc_ObjIsCo(pObj) ) { if ( pParams->fDrop ) Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); continue; } // skip constant node, it has no cuts // if ( Abc_NodeIsConst(pObj) ) // continue; Extra_ProgressBarUpdate( pProgress, i, NULL ); // compute the cuts to the internal node pList = (Cut_Cut_t *)Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); if ( pParams->fNpnSave && pList ) { extern void Npn_ManSaveOne( unsigned * puTruth, int nVars ); Cut_Cut_t * pCut; for ( pCut = pList; pCut; pCut = pCut->pNext ) if ( pCut->nLeaves >= 4 ) Npn_ManSaveOne( Cut_CutReadTruth(pCut), pCut->nLeaves ); } // consider dropping the fanins cuts if ( pParams->fDrop ) { Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); } // add cuts due to choices if ( Abc_AigNodeIsChoice(pObj) ) { Vec_IntClear( vChoices ); for ( pNode = pObj; pNode; pNode = (Abc_Obj_t *)pNode->pData ) Vec_IntPush( vChoices, pNode->Id ); Cut_NodeUnionCuts( p, vChoices ); } } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); Vec_IntFree( vChoices ); Cut_ManPrintStats( p ); ABC_PRT( "TOTAL", Abc_Clock() - clk ); // printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) ); //Abc_NtkPrintCuts( p, pNtk, 0 ); // Cut_ManPrintStatsToFile( p, pNtk->pSpec, Abc_Clock() - clk ); // temporary printout of stats if ( nTotal ) printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); if ( pParams->fAdjust ) Abc_NtkCutsAddFanunt( pNtk ); return p; } /**Function************************************************************* Synopsis [Cut computation using the oracle.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) { Abc_Obj_t * pObj; Vec_Ptr_t * vNodes; int i; //, clk = Abc_Clock(); int fDrop = Cut_OracleReadDrop(p); assert( Abc_NtkIsStrash(pNtk) ); // prepare cut droppping if ( fDrop ) Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); // set cuts for PIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_OracleNodeSetTriv( p, pObj->Id ); // compute cuts for internal nodes vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // when we reached a CO, it is time to deallocate the cuts if ( Abc_ObjIsCo(pObj) ) { if ( fDrop ) Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); continue; } // skip constant node, it has no cuts // if ( Abc_NodeIsConst(pObj) ) // continue; // compute the cuts to the internal node Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); // consider dropping the fanins cuts if ( fDrop ) { Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); } } Vec_PtrFree( vNodes ); //ABC_PRT( "Total", Abc_Clock() - clk ); //Abc_NtkPrintCuts_( p, pNtk, 0 ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) { /* Cut_Man_t * p; Abc_Obj_t * pObj, * pNode; int i, nIters, fStatus; Vec_Int_t * vChoices; abctime clk = Abc_Clock(); assert( Abc_NtkIsSeq(pNtk) ); assert( pParams->fSeq ); // assert( Abc_NtkIsDfsOrdered(pNtk) ); // start the manager pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk ); p = Cut_ManStart( pParams ); // set cuts for the constant node and the PIs pObj = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( p, pObj->Id ); Abc_NtkForEachPi( pNtk, pObj, i ) { //printf( "Setting trivial cut %d.\n", pObj->Id ); Cut_NodeSetTriv( p, pObj->Id ); } // label the cutset nodes and set their number in the array // assign the elementary cuts to the cutset nodes Abc_SeqForEachCutsetNode( pNtk, pObj, i ) { assert( pObj->fMarkC == 0 ); pObj->fMarkC = 1; pObj->pCopy = (Abc_Obj_t *)i; Cut_NodeSetTriv( p, pObj->Id ); //printf( "Setting trivial cut %d.\n", pObj->Id ); } // process the nodes vChoices = Vec_IntAlloc( 100 ); for ( nIters = 0; nIters < 10; nIters++ ) { //printf( "ITERATION %d:\n", nIters ); // compute the cuts for the internal nodes Abc_AigForEachAnd( pNtk, pObj, i ) { Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); // add cuts due to choices if ( Abc_AigNodeIsChoice(pObj) ) { Vec_IntClear( vChoices ); for ( pNode = pObj; pNode; pNode = pNode->pData ) Vec_IntPush( vChoices, pNode->Id ); Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 ); } } // merge the new cuts with the old cuts Abc_NtkForEachPi( pNtk, pObj, i ) Cut_NodeNewMergeWithOld( p, pObj->Id ); Abc_AigForEachAnd( pNtk, pObj, i ) Cut_NodeNewMergeWithOld( p, pObj->Id ); // for the cutset, transfer temp cuts to new cuts fStatus = 0; Abc_SeqForEachCutsetNode( pNtk, pObj, i ) fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i ); if ( fStatus == 0 ) break; } Vec_IntFree( vChoices ); // if the status is not finished, transfer new to old for the cutset Abc_SeqForEachCutsetNode( pNtk, pObj, i ) Cut_NodeNewMergeWithOld( p, pObj->Id ); // transfer the old cuts to the new positions Abc_NtkForEachObj( pNtk, pObj, i ) Cut_NodeOldTransferToNew( p, pObj->Id ); // unlabel the cutset nodes Abc_SeqForEachCutsetNode( pNtk, pObj, i ) pObj->fMarkC = 0; if ( pParams->fVerbose ) { Cut_ManPrintStats( p ); ABC_PRT( "TOTAL ", Abc_Clock() - clk ); printf( "Converged after %d iterations.\n", nIters ); } //Abc_NtkPrintCuts( p, pNtk, 1 ); return p; */ return NULL; } /**Function************************************************************* Synopsis [Computes area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ) { Abc_Obj_t * pObj; int Counter, i; Counter = 0; Abc_NtkForEachCo( pNtk, pObj, i ) Counter += Cut_ManMappingArea_rec( p, Abc_ObjFaninId0(pObj) ); return Counter; } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) { void * pList; if ( (pList = Abc_NodeReadCuts( p, pObj )) ) return pList; Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); return Abc_NodeGetCuts( p, pObj, fDag, fTree ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) { Abc_Obj_t * pFanin; int fDagNode, fTriv, TreeCode = 0; // assert( Abc_NtkIsStrash(pObj->pNtk) ); assert( Abc_ObjFaninNum(pObj) == 2 ); // check if the node is a DAG node fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); // increment the counter of DAG nodes if ( fDagNode ) Cut_ManIncrementDagNodes( (Cut_Man_t *)p ); // add the trivial cut if the node is a DAG node, or if we compute all cuts fTriv = fDagNode || !fDag; // check if fanins are DAG nodes if ( fTree ) { pFanin = Abc_ObjFanin0(pObj); TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); pFanin = Abc_ObjFanin1(pObj); TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); } // changes due to the global/local cut computation { Cut_Params_t * pParams = Cut_ManReadParams((Cut_Man_t *)p); if ( pParams->fLocal ) { Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs((Cut_Man_t *)p); fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id ); if ( fDagNode ) Cut_ManIncrementDagNodes( (Cut_Man_t *)p ); // fTriv = fDagNode || !pParams->fGlobal; fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id ); TreeCode = 0; pFanin = Abc_ObjFanin0(pObj); TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id ); pFanin = Abc_ObjFanin1(pObj); TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1); } } return Cut_NodeComputeCuts( (Cut_Man_t *)p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) { /* int CutSetNum; assert( Abc_NtkIsSeq(pObj->pNtk) ); assert( Abc_ObjFaninNum(pObj) == 2 ); fTriv = pObj->fMarkC ? 0 : fTriv; CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum ); */ } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) { return Cut_NodeReadCutsNew( (Cut_Man_t *)p, pObj->Id ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ) { Cut_NodeFreeCuts( (Cut_Man_t *)p, pObj->Id ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ) { Cut_Cut_t * pList; Abc_Obj_t * pObj; int i; printf( "Cuts of the network:\n" ); Abc_NtkForEachObj( pNtk, pObj, i ) { pList = (Cut_Cut_t *)Abc_NodeReadCuts( (Cut_Man_t *)p, pObj ); printf( "Node %s:\n", Abc_ObjName(pObj) ); Cut_CutPrintList( pList, fSeq ); } } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ) { Cut_Cut_t * pList; Abc_Obj_t * pObj; pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 ); pList = (Cut_Cut_t *)Abc_NodeReadCuts( (Cut_Man_t *)p, pObj ); printf( "Node %s:\n", Abc_ObjName(pObj) ); Cut_CutPrintList( pList, fSeq ); } /**Function************************************************************* Synopsis [Assigns global attributes randomly.] Description [Old code.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { Vec_Int_t * vAttrs; // Vec_Ptr_t * vNodes; Abc_Obj_t * pObj;//, * pTemp; int i;//, k; int nNodesTotal = 0, nMffcsTotal = 0; extern Vec_Ptr_t * Abc_NodeMffcInsideCollect( Abc_Obj_t * pNode ); vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); // Abc_NtkForEachCi( pNtk, pObj, i ) // Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); Abc_NtkForEachObj( pNtk, pObj, i ) { if ( Abc_ObjIsNode(pObj) ) nNodesTotal++; if ( Abc_ObjIsCo(pObj) && Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) nMffcsTotal += Abc_NodeMffcSize( Abc_ObjFanin0(pObj) ); // if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) ) // if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) ) if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) ) { int nMffc = Abc_NodeMffcSize(pObj); nMffcsTotal += Abc_NodeMffcSize(pObj); // printf( "%d ", nMffc ); if ( nMffc > 2 || Abc_ObjFanoutNum(pObj) > 8 ) Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); } } /* Abc_NtkForEachObj( pNtk, pObj, i ) { if ( Vec_IntEntry( vAttrs, pObj->Id ) ) { vNodes = Abc_NodeMffcInsideCollect( pObj ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pTemp, k ) if ( pTemp != pObj ) Vec_IntWriteEntry( vAttrs, pTemp->Id, 0 ); Vec_PtrFree( vNodes ); } } */ printf( "Total nodes = %d. Total MFFC nodes = %d.\n", nNodesTotal, nMffcsTotal ); return vAttrs; } /**Function************************************************************* Synopsis [Assigns global attributes randomly.] Description [Old code.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSubDagSize_rec( Abc_Obj_t * pObj, Vec_Int_t * vAttrs ) { if ( Abc_NodeIsTravIdCurrent(pObj) ) return 0; Abc_NodeSetTravIdCurrent(pObj); if ( Vec_IntEntry( vAttrs, pObj->Id ) ) return 0; if ( Abc_ObjIsCi(pObj) ) return 1; assert( Abc_ObjFaninNum(pObj) == 2 ); return 1 + Abc_NtkSubDagSize_rec(Abc_ObjFanin0(pObj), vAttrs) + Abc_NtkSubDagSize_rec(Abc_ObjFanin1(pObj), vAttrs); } /**Function************************************************************* Synopsis [Assigns global attributes randomly.] Description [Old code.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkGetNodeAttributes2( Abc_Ntk_t * pNtk ) { Vec_Int_t * vAttrs; Abc_Obj_t * pObj; int i, nSize; assert( Abc_NtkIsDfsOrdered(pNtk) ); vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); Abc_NtkForEachObj( pNtk, pObj, i ) { // skip no-nodes and nodes without fanouts if ( pObj->Id == 0 || !(Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) ) continue; // the node has more than one fanout - count its sub-DAG size Abc_NtkIncrementTravId( pNtk ); nSize = Abc_NtkSubDagSize_rec( pObj, vAttrs ); if ( nSize > 15 ) Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); } return vAttrs; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDar.c000066400000000000000000004654711300674244400232050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDar.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [DAG-aware rewriting.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDar.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "aig/gia/giaAig.h" #include "opt/dar/dar.h" #include "sat/cnf/cnf.h" #include "proof/fra/fra.h" #include "proof/fraig/fraig.h" #include "proof/int/int.h" #include "proof/dch/dch.h" #include "proof/ssw/ssw.h" #include "opt/cgt/cgt.h" #include "bdd/bbr/bbr.h" #include "aig/gia/gia.h" #include "proof/cec/cec.h" #include "opt/csw/csw.h" #include "proof/pdr/pdr.h" #include "sat/bmc/bmc.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjCompareById( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { return Abc_ObjId(Abc_ObjRegular(*pp1)) - Abc_ObjId(Abc_ObjRegular(*pp2)); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_CollectTopOr_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vSuper ) { if ( Abc_ObjIsComplement(pObj) || !Abc_ObjIsNode(pObj) ) { Vec_PtrPush( vSuper, pObj ); return; } // go through the branches Abc_CollectTopOr_rec( Abc_ObjChild0(pObj), vSuper ); Abc_CollectTopOr_rec( Abc_ObjChild1(pObj), vSuper ); } void Abc_CollectTopOr( Abc_Obj_t * pObj, Vec_Ptr_t * vSuper ) { Vec_PtrClear( vSuper ); if ( Abc_ObjIsComplement(pObj) ) { Abc_CollectTopOr_rec( Abc_ObjNot(pObj), vSuper ); Vec_PtrUniqify( vSuper, (int (*)())Abc_ObjCompareById ); } else Vec_PtrPush( vSuper, Abc_ObjNot(pObj) ); } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [The returned map maps new PO IDs into old ones.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Abc_NtkToDarBmc( Abc_Ntk_t * pNtk, Vec_Int_t ** pvMap ) { Aig_Man_t * pMan; Abc_Obj_t * pObj, * pTemp; Vec_Ptr_t * vDrivers; Vec_Ptr_t * vSuper; int i, k, nDontCares; // print warning about initial values nDontCares = 0; Abc_NtkForEachLatch( pNtk, pObj, i ) if ( Abc_LatchIsInitDc(pObj) ) { Abc_LatchSetInit0(pObj); nDontCares++; } if ( nDontCares ) { Abc_Print( 1, "Warning: %d registers in this network have don't-care init values.\n", nDontCares ); Abc_Print( 1, "The don't-care are assumed to be 0. The result may not verify.\n" ); Abc_Print( 1, "Use command \"print_latch\" to see the init values of registers.\n" ); Abc_Print( 1, "Use command \"zero\" to convert or \"init\" to change the values.\n" ); } // collect the drivers vSuper = Vec_PtrAlloc( 100 ); vDrivers = Vec_PtrAlloc( 100 ); if ( pvMap ) *pvMap = Vec_IntAlloc( 100 ); Abc_NtkForEachPo( pNtk, pObj, i ) { if ( pNtk->nConstrs && i >= pNtk->nConstrs ) { Vec_PtrPush( vDrivers, Abc_ObjNot(Abc_ObjChild0(pObj)) ); if ( pvMap ) Vec_IntPush( *pvMap, i ); continue; } Abc_CollectTopOr( Abc_ObjChild0(pObj), vSuper ); Vec_PtrForEachEntry( Abc_Obj_t *, vSuper, pTemp, k ) { Vec_PtrPush( vDrivers, pTemp ); if ( pvMap ) Vec_IntPush( *pvMap, i ); } } Vec_PtrFree( vSuper ); // create network pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 ); pMan->nConstrs = pNtk->nConstrs; pMan->nBarBufs = pNtk->nBarBufs; pMan->pName = Extra_UtilStrsav( pNtk->pName ); pMan->pSpec = Extra_UtilStrsav( pNtk->pSpec ); // transfer the pointers to the basic nodes Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreateCi(pMan); // create flops Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNotCond( Abc_ObjFanout0(pObj)->pCopy, Abc_LatchIsInit1(pObj) ); // copy internal nodes Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) ); // create the POs Vec_PtrForEachEntry( Abc_Obj_t *, vDrivers, pTemp, k ) Aig_ObjCreateCo( pMan, (Aig_Obj_t *)Abc_ObjNotCond(Abc_ObjRegular(pTemp)->pCopy, !Abc_ObjIsComplement(pTemp)) ); Vec_PtrFree( vDrivers ); // create flops Abc_NtkForEachLatchInput( pNtk, pObj, i ) Aig_ObjCreateCo( pMan, (Aig_Obj_t *)Abc_ObjNotCond(Abc_ObjChild0Copy(pObj), Abc_LatchIsInit1(Abc_ObjFanout0(pObj))) ); // remove dangling nodes Aig_ManSetRegNum( pMan, Abc_NtkLatchNum(pNtk) ); Aig_ManCleanup( pMan ); if ( !Aig_ManCheck( pMan ) ) { Abc_Print( 1, "Abc_NtkToDarBmc: AIG check has failed.\n" ); Aig_ManStop( pMan ); return NULL; } return pMan; } /**Function************************************************************* Synopsis [Collects information about what flops have unknown values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkFindDcLatches( Abc_Ntk_t * pNtk ) { Vec_Int_t * vUnknown; Abc_Obj_t * pObj; int i; vUnknown = Vec_IntStart( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pObj, i ) if ( Abc_LatchIsInitDc(pObj) ) { Vec_IntWriteEntry( vUnknown, i, 1 ); Abc_LatchSetInit0(pObj); } return vUnknown; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [Assumes that registers are ordered after PIs/POs.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ) { Vec_Ptr_t * vNodes; Aig_Man_t * pMan; Aig_Obj_t * pObjNew; Abc_Obj_t * pObj; int i, nNodes, nDontCares; // make sure the latches follow PIs/POs if ( fRegisters ) { assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) if ( i < Abc_NtkPiNum(pNtk) ) { assert( Abc_ObjIsPi(pObj) ); if ( !Abc_ObjIsPi(pObj) ) Abc_Print( 1, "Abc_NtkToDar(): Temporary bug: The PI ordering is wrong!\n" ); } else assert( Abc_ObjIsBo(pObj) ); Abc_NtkForEachCo( pNtk, pObj, i ) if ( i < Abc_NtkPoNum(pNtk) ) { assert( Abc_ObjIsPo(pObj) ); if ( !Abc_ObjIsPo(pObj) ) Abc_Print( 1, "Abc_NtkToDar(): Temporary bug: The PO ordering is wrong!\n" ); } else assert( Abc_ObjIsBi(pObj) ); // print warning about initial values nDontCares = 0; Abc_NtkForEachLatch( pNtk, pObj, i ) if ( Abc_LatchIsInitDc(pObj) ) { Abc_LatchSetInit0(pObj); nDontCares++; } if ( nDontCares ) { Abc_Print( 1, "Warning: %d registers in this network have don't-care init values.\n", nDontCares ); Abc_Print( 1, "The don't-care are assumed to be 0. The result may not verify.\n" ); Abc_Print( 1, "Use command \"print_latch\" to see the init values of registers.\n" ); Abc_Print( 1, "Use command \"zero\" to convert or \"init\" to change the values.\n" ); } } // create the manager pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 ); pMan->fCatchExor = fExors; pMan->nConstrs = pNtk->nConstrs; pMan->nBarBufs = pNtk->nBarBufs; pMan->pName = Extra_UtilStrsav( pNtk->pName ); pMan->pSpec = Extra_UtilStrsav( pNtk->pSpec ); // transfer the pointers to the basic nodes Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); Abc_NtkForEachCi( pNtk, pObj, i ) { pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreateCi(pMan); // initialize logic level of the CIs ((Aig_Obj_t *)pObj->pCopy)->Level = pObj->Level; } // complement the 1-values registers if ( fRegisters ) { Abc_NtkForEachLatch( pNtk, pObj, i ) if ( Abc_LatchIsInit1(pObj) ) Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy); } // perform the conversion of the internal nodes (assumes DFS ordering) // pMan->fAddStrash = 1; vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) // Abc_NtkForEachNode( pNtk, pObj, i ) { pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) ); // Abc_Print( 1, "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id ); } Vec_PtrFree( vNodes ); pMan->fAddStrash = 0; // create the POs Abc_NtkForEachCo( pNtk, pObj, i ) Aig_ObjCreateCo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) ); // complement the 1-valued registers Aig_ManSetRegNum( pMan, Abc_NtkLatchNum(pNtk) ); if ( fRegisters ) Aig_ManForEachLiSeq( pMan, pObjNew, i ) if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) ) pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0); // remove dangling nodes nNodes = (Abc_NtkGetChoiceNum(pNtk) == 0)? Aig_ManCleanup( pMan ) : 0; if ( !fExors && nNodes ) Abc_Print( 1, "Abc_NtkToDar(): Unexpected %d dangling nodes when converting to AIG!\n", nNodes ); //Aig_ManDumpVerilog( pMan, "test.v" ); // save the number of registers if ( fRegisters ) { Aig_ManSetRegNum( pMan, Abc_NtkLatchNum(pNtk) ); pMan->vFlopNums = Vec_IntStartNatural( pMan->nRegs ); // pMan->vFlopNums = NULL; // pMan->vOnehots = Abc_NtkConverLatchNamesIntoNumbers( pNtk ); if ( pNtk->vOnehots ) pMan->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots ); } if ( !Aig_ManCheck( pMan ) ) { Abc_Print( 1, "Abc_NtkToDar: AIG check has failed.\n" ); Aig_ManStop( pMan ); return NULL; } return pMan; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [Assumes that registers are ordered after PIs/POs.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Abc_NtkToDarChoices( Abc_Ntk_t * pNtk ) { Aig_Man_t * pMan; Abc_Obj_t * pObj, * pPrev, * pFanin; Vec_Ptr_t * vNodes; int i; vNodes = Abc_AigDfs( pNtk, 0, 0 ); // create the manager pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 ); pMan->nConstrs = pNtk->nConstrs; pMan->nBarBufs = pNtk->nBarBufs; pMan->pName = Extra_UtilStrsav( pNtk->pName ); pMan->pSpec = Extra_UtilStrsav( pNtk->pSpec ); if ( Abc_NtkGetChoiceNum(pNtk) ) { pMan->pEquivs = ABC_ALLOC( Aig_Obj_t *, Abc_NtkObjNum(pNtk) ); memset( pMan->pEquivs, 0, sizeof(Aig_Obj_t *) * Abc_NtkObjNum(pNtk) ); } // transfer the pointers to the basic nodes Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreateCi(pMan); // perform the conversion of the internal nodes (assumes DFS ordering) Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) ); // Abc_Print( 1, "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id ); if ( Abc_AigNodeIsChoice( pObj ) ) { for ( pPrev = pObj, pFanin = (Abc_Obj_t *)pObj->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData ) Aig_ObjSetEquiv( pMan, (Aig_Obj_t *)pPrev->pCopy, (Aig_Obj_t *)pFanin->pCopy ); // Aig_ManCreateChoice( pIfMan, (Aig_Obj_t *)pNode->pCopy ); } } Vec_PtrFree( vNodes ); // create the POs Abc_NtkForEachCo( pNtk, pObj, i ) Aig_ObjCreateCo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) ); // complement the 1-valued registers Aig_ManSetRegNum( pMan, 0 ); if ( !Aig_ManCheck( pMan ) ) { Abc_Print( 1, "Abc_NtkToDar: AIG check has failed.\n" ); Aig_ManStop( pMan ); return NULL; } return pMan; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Aig_Obj_t * pObj; int i; assert( pMan->nAsserts == 0 ); // assert( Aig_ManRegNum(pMan) == Abc_NtkLatchNum(pNtkOld) ); // perform strashing pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); pNtkNew->nConstrs = pMan->nConstrs; pNtkNew->nBarBufs = pNtkOld->nBarBufs; // transfer the pointers to the basic nodes Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); Aig_ManForEachCi( pMan, pObj, i ) { pObj->pData = Abc_NtkCi(pNtkNew, i); // initialize logic level of the CIs ((Abc_Obj_t *)pObj->pData)->Level = pObj->Level; } // rebuild the AIG vNodes = Aig_ManDfs( pMan, 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); else pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // connect the PO nodes Aig_ManForEachCo( pMan, pObj, i ) { if ( pMan->nAsserts && i == Aig_ManCoNum(pMan) - pMan->nAsserts ) break; Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); } // if there are assertions, add them if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkFromDar(): Network check has failed.\n" ); //Abc_NtkPrintCiLevels( pNtkNew ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [This procedure should be called after seq sweeping, which changes the number of registers.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjNew, * pLatch; Aig_Obj_t * pObj, * pObjLo, * pObjLi; int i, iNodeId, nDigits; assert( pMan->nAsserts == 0 ); assert( pNtkOld->nBarBufs == 0 ); // assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) ); // perform strashing pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); pNtkNew->nConstrs = pMan->nConstrs; pNtkNew->nBarBufs = pMan->nBarBufs; // consider the case of target enlargement if ( Abc_NtkCiNum(pNtkNew) < Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) ) { for ( i = Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) - Abc_NtkCiNum(pNtkNew); i > 0; i-- ) { pObjNew = Abc_NtkCreatePi( pNtkNew ); Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL ); } Abc_NtkOrderCisCos( pNtkNew ); } assert( Abc_NtkCiNum(pNtkNew) == Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) ); assert( Abc_NtkCoNum(pNtkNew) == Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) ); // transfer the pointers to the basic nodes Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); Aig_ManForEachPiSeq( pMan, pObj, i ) pObj->pData = Abc_NtkCi(pNtkNew, i); // create as many latches as there are registers in the manager Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) { pObjNew = Abc_NtkCreateLatch( pNtkNew ); pObjLi->pData = Abc_NtkCreateBi( pNtkNew ); pObjLo->pData = Abc_NtkCreateBo( pNtkNew ); Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)pObjLi->pData ); Abc_ObjAddFanin( (Abc_Obj_t *)pObjLo->pData, pObjNew ); Abc_LatchSetInit0( pObjNew ); } // rebuild the AIG vNodes = Aig_ManDfs( pMan, 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); else pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // connect the PO nodes Aig_ManForEachCo( pMan, pObj, i ) { // if ( pMan->nAsserts && i == Aig_ManCoNum(pMan) - pMan->nAsserts ) // break; iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(Abc_NtkCo(pNtkNew, i)), ABC_OBJ_PI, ABC_OBJ_BO ); if ( iNodeId >= 0 ) pObjNew = Abc_NtkObj( pNtkNew, iNodeId ); else pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew ); } if ( pMan->vFlopNums == NULL ) Abc_NtkAddDummyBoxNames( pNtkNew ); else { /* { int i, k, iFlop, Counter = 0; FILE * pFile; pFile = fopen( "out.txt", "w" ); fAbc_Print( 1, pFile, "The total of %d registers were removed (out of %d):\n", Abc_NtkLatchNum(pNtkOld)-Vec_IntSize(pMan->vFlopNums), Abc_NtkLatchNum(pNtkOld) ); for ( i = 0; i < Abc_NtkLatchNum(pNtkOld); i++ ) { Vec_IntForEachEntry( pMan->vFlopNums, iFlop, k ) { if ( i == iFlop ) break; } if ( k == Vec_IntSize(pMan->vFlopNums) ) fAbc_Print( 1, pFile, "%6d (%6d) : %s\n", ++Counter, i, Abc_ObjName( Abc_ObjFanout0(Abc_NtkBox(pNtkOld, i)) ) ); } fclose( pFile ); //Abc_Print( 1, "\n" ); } */ assert( Abc_NtkBoxNum(pNtkOld) == Abc_NtkLatchNum(pNtkOld) ); nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtkNew) ); Abc_NtkForEachLatch( pNtkNew, pObjNew, i ) { pLatch = Abc_NtkBox( pNtkOld, Vec_IntEntry( pMan->vFlopNums, i ) ); iNodeId = Nm_ManFindIdByName( pNtkNew->pManName, Abc_ObjName(Abc_ObjFanout0(pLatch)), ABC_OBJ_PO ); if ( iNodeId >= 0 ) { Abc_ObjAssignName( pObjNew, Abc_ObjNameDummy("l", i, nDigits), NULL ); Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjNameDummy("li", i, nDigits), NULL ); Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjNameDummy("lo", i, nDigits), NULL ); //Abc_Print( 1, "happening %s -> %s\n", Abc_ObjName(Abc_ObjFanin0(pObjNew)), Abc_ObjName(Abc_ObjFanout0(pObjNew)) ); continue; } Abc_ObjAssignName( pObjNew, Abc_ObjName(pLatch), NULL ); Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pLatch)), NULL ); Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pLatch)), NULL ); } } // if there are assertions, add them if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkFromDar(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [This procedure should be called after seq sweeping, which changes the number of registers.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjNew; Aig_Obj_t * pObj, * pObjLo, * pObjLi; int i; assert( pMan->nAsserts == 0 ); // perform strashing pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkNew->nConstrs = pMan->nConstrs; pNtkNew->nBarBufs = pMan->nBarBufs; // duplicate the name and the spec // pNtkNew->pName = Extra_UtilStrsav(pMan->pName); // pNtkNew->pSpec = Extra_UtilStrsav(pMan->pSpec); Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); // create PIs Aig_ManForEachPiSeq( pMan, pObj, i ) { pObjNew = Abc_NtkCreatePi( pNtkNew ); // Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL ); pObj->pData = pObjNew; } // create POs Aig_ManForEachPoSeq( pMan, pObj, i ) { pObjNew = Abc_NtkCreatePo( pNtkNew ); // Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjNew), NULL ); pObj->pData = pObjNew; } assert( Abc_NtkCiNum(pNtkNew) == Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) ); assert( Abc_NtkCoNum(pNtkNew) == Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) ); // create as many latches as there are registers in the manager Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) { pObjNew = Abc_NtkCreateLatch( pNtkNew ); pObjLi->pData = Abc_NtkCreateBi( pNtkNew ); pObjLo->pData = Abc_NtkCreateBo( pNtkNew ); Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)pObjLi->pData ); Abc_ObjAddFanin( (Abc_Obj_t *)pObjLo->pData, pObjNew ); Abc_LatchSetInit0( pObjNew ); // Abc_ObjAssignName( (Abc_Obj_t *)pObjLi->pData, Abc_ObjName((Abc_Obj_t *)pObjLi->pData), NULL ); // Abc_ObjAssignName( (Abc_Obj_t *)pObjLo->pData, Abc_ObjName((Abc_Obj_t *)pObjLo->pData), NULL ); } // rebuild the AIG vNodes = Aig_ManDfs( pMan, 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); else pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // connect the PO nodes Aig_ManForEachCo( pMan, pObj, i ) { pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew ); } Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); Abc_NtkAddDummyBoxNames( pNtkNew ); // check the resulting AIG if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkFromAigPhase(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Creates local function of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_ObjHopFromGia_rec( Hop_Man_t * pHopMan, Gia_Man_t * p, int Id, Vec_Ptr_t * vCopies ) { Gia_Obj_t * pObj; Hop_Obj_t * gFunc, * gFunc0, * gFunc1; if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return (Hop_Obj_t *)Vec_PtrEntry( vCopies, Id ); Gia_ObjSetTravIdCurrentId(p, Id); pObj = Gia_ManObj(p, Id); assert( Gia_ObjIsAnd(pObj) ); // compute the functions of the children gFunc0 = Abc_ObjHopFromGia_rec( pHopMan, p, Gia_ObjFaninId0(pObj, Id), vCopies ); gFunc1 = Abc_ObjHopFromGia_rec( pHopMan, p, Gia_ObjFaninId1(pObj, Id), vCopies ); // get the function of the cut gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, Gia_ObjFaninC0(pObj)), Hop_NotCond(gFunc1, Gia_ObjFaninC1(pObj)) ); Vec_PtrWriteEntry( vCopies, Id, gFunc ); return gFunc; } Hop_Obj_t * Abc_ObjHopFromGia( Hop_Man_t * pHopMan, Gia_Man_t * p, int GiaId, Vec_Ptr_t * vCopies ) { int k, iFan; assert( Gia_ObjIsLut(p, GiaId) ); assert( Gia_ObjLutSize(p, GiaId) > 0 ); Gia_ManIncrementTravId( p ); Gia_LutForEachFanin( p, GiaId, iFan, k ) { Gia_ObjSetTravIdCurrentId(p, iFan); Vec_PtrWriteEntry( vCopies, iFan, Hop_IthVar(pHopMan, k) ); } return Abc_ObjHopFromGia_rec( pHopMan, p, GiaId, vCopies ); } /**Function************************************************************* Synopsis [Converts the network from the mapped GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p ) { int fVerbose = 0; int fDuplicate = 0; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjNew, * pObjNewLi, * pObjNewLo, * pConst0 = NULL; Gia_Obj_t * pObj, * pObjLi, * pObjLo; Vec_Ptr_t * vReflect; int i, k, iFan, nDupGates; assert( Gia_ManHasMapping(p) || p->pMuxes ); pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, Gia_ManHasMapping(p) ? ABC_FUNC_AIG : ABC_FUNC_SOP, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(p->pName); pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec); Gia_ManFillValue( p ); // create constant pConst0 = Abc_NtkCreateNodeConst0( pNtkNew ); Gia_ManConst0(p)->Value = Abc_ObjId(pConst0); // create PIs Gia_ManForEachPi( p, pObj, i ) pObj->Value = Abc_ObjId( Abc_NtkCreatePi( pNtkNew ) ); // create POs Gia_ManForEachPo( p, pObj, i ) pObj->Value = Abc_ObjId( Abc_NtkCreatePo( pNtkNew ) ); // create as many latches as there are registers in the manager Gia_ManForEachRiRo( p, pObjLi, pObjLo, i ) { pObjNew = Abc_NtkCreateLatch( pNtkNew ); pObjNewLi = Abc_NtkCreateBi( pNtkNew ); pObjNewLo = Abc_NtkCreateBo( pNtkNew ); Abc_ObjAddFanin( pObjNew, pObjNewLi ); Abc_ObjAddFanin( pObjNewLo, pObjNew ); pObjLi->Value = Abc_ObjId( pObjNewLi ); pObjLo->Value = Abc_ObjId( pObjNewLo ); Abc_LatchSetInit0( pObjNew ); } // rebuild the AIG if ( p->pMuxes ) { Gia_ManForEachAnd( p, pObj, i ) { pObjNew = Abc_NtkCreateNode( pNtkNew ); if ( Gia_ObjIsMuxId(p, i) ) { Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ObjFanin2(p, pObj))) ); Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ObjFanin1(pObj))) ); Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ObjFanin0(pObj))) ); pObjNew->pData = Abc_SopCreateMux( (Mem_Flex_t *)pNtkNew->pManFunc ); if ( Gia_ObjFaninC2(p, pObj) ) Abc_SopComplementVar( (char *)pObjNew->pData, 0 ); if ( Gia_ObjFaninC1(pObj) ) Abc_SopComplementVar( (char *)pObjNew->pData, 1 ); if ( Gia_ObjFaninC0(pObj) ) Abc_SopComplementVar( (char *)pObjNew->pData, 2 ); } else if ( Gia_ObjIsXor(pObj) ) { Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ObjFanin0(pObj))) ); Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ObjFanin1(pObj))) ); pObjNew->pData = Abc_SopCreateXor( (Mem_Flex_t *)pNtkNew->pManFunc, 2 ); if ( Gia_ObjFaninC0(pObj) ) Abc_SopComplementVar( (char *)pObjNew->pData, 0 ); if ( Gia_ObjFaninC1(pObj) ) Abc_SopComplementVar( (char *)pObjNew->pData, 1 ); } else { Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ObjFanin0(pObj))) ); Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ObjFanin1(pObj))) ); pObjNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, 2, NULL ); if ( Gia_ObjFaninC0(pObj) ) Abc_SopComplementVar( (char *)pObjNew->pData, 0 ); if ( Gia_ObjFaninC1(pObj) ) Abc_SopComplementVar( (char *)pObjNew->pData, 1 ); } pObj->Value = Abc_ObjId( pObjNew ); } } else { vReflect = Vec_PtrStart( Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { pObj = Gia_ManObj(p, i); assert( pObj->Value == ~0 ); if ( Gia_ObjLutSize(p, i) == 0 ) { pObj->Value = Abc_ObjId(pConst0); continue; } pObjNew = Abc_NtkCreateNode( pNtkNew ); Gia_LutForEachFanin( p, i, iFan, k ) Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtkNew, Gia_ObjValue(Gia_ManObj(p, iFan))) ); pObjNew->pData = Abc_ObjHopFromGia( (Hop_Man_t *)pNtkNew->pManFunc, p, i, vReflect ); pObj->Value = Abc_ObjId( pObjNew ); } Vec_PtrFree( vReflect ); } // connect the PO nodes Gia_ManForEachCo( p, pObj, i ) { pObjNew = Abc_NtkObj( pNtkNew, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), Abc_ObjNotCond( pObjNew, Gia_ObjFaninC0(pObj) ) ); } // create names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); Abc_NtkAddDummyBoxNames( pNtkNew ); // decouple the PO driver nodes to reduce the number of levels nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, fDuplicate ); if ( fVerbose && nDupGates && !Abc_FrameReadFlag("silentmode") ) { if ( !fDuplicate ) printf( "Added %d buffers/inverters to decouple the CO drivers.\n", nDupGates ); else printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); } // remove const node if it is not used if ( !Abc_ObjIsNone(pConst0) && Abc_ObjFanoutNum(pConst0) == 0 ) Abc_NtkDeleteObj( pConst0 ); assert( Gia_ManPiNum(p) == Abc_NtkPiNum(pNtkNew) ); assert( Gia_ManPoNum(p) == Abc_NtkPoNum(pNtkNew) ); assert( Gia_ManRegNum(p) == Abc_NtkLatchNum(pNtkNew) ); // check the resulting AIG if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the network from the mapped GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_NtkFromCellWrite( Vec_Int_t * vCopyLits, int i, int c, int Id ) { Vec_IntWriteEntry( vCopyLits, Abc_Var2Lit(i, c), Id ); } static inline Abc_Obj_t * Abc_NtkFromCellRead( Abc_Ntk_t * p, Vec_Int_t * vCopyLits, int i, int c ) { Abc_Obj_t * pObjNew; int iObjNew = Vec_IntEntry( vCopyLits, Abc_Var2Lit(i, c) ); if ( iObjNew >= 0 ) return Abc_NtkObj(p, iObjNew); // opposite phase should be already constructed assert( 0 ); if ( i == 0 ) pObjNew = c ? Abc_NtkCreateNodeConst1(p) : Abc_NtkCreateNodeConst0(p); else { iObjNew = Vec_IntEntry( vCopyLits, Abc_Var2Lit(i, !c) ); assert( iObjNew >= 0 ); pObjNew = Abc_NtkCreateNodeInv( p, Abc_NtkObj(p, iObjNew) ); } Abc_NtkFromCellWrite( vCopyLits, i, c, Abc_ObjId(pObjNew) ); return pObjNew; } Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p ) { int fFixDrivers = 1; int fDuplicate = 1; int fVerbose = 0; Abc_Ntk_t * pNtkNew; Vec_Int_t * vCopyLits; Abc_Obj_t * pObjNew, * pObjNewLi, * pObjNewLo; Gia_Obj_t * pObj, * pObjLi, * pObjLo; int i, k, iLit, iFanLit, nCells, fNeedConst[2] = {0}; Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); assert( Gia_ManHasCellMapping(p) ); // start network pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_MAP, 1 ); pNtkNew->pName = Extra_UtilStrsav(p->pName); pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec); assert( pNtkNew->pManFunc == Abc_FrameReadLibGen() ); vCopyLits = Vec_IntStartFull( 2*Gia_ManObjNum(p) ); // create PIs Gia_ManForEachPi( p, pObj, i ) Abc_NtkFromCellWrite( vCopyLits, Gia_ObjId(p, pObj), 0, Abc_ObjId( Abc_NtkCreatePi( pNtkNew ) ) ); // create POs Gia_ManForEachPo( p, pObj, i ) Abc_NtkFromCellWrite( vCopyLits, Gia_ObjId(p, pObj), 0, Abc_ObjId( Abc_NtkCreatePo( pNtkNew ) ) ); // create as many latches as there are registers in the manager Gia_ManForEachRiRo( p, pObjLi, pObjLo, i ) { pObjNew = Abc_NtkCreateLatch( pNtkNew ); pObjNewLi = Abc_NtkCreateBi( pNtkNew ); pObjNewLo = Abc_NtkCreateBo( pNtkNew ); Abc_ObjAddFanin( pObjNew, pObjNewLi ); Abc_ObjAddFanin( pObjNewLo, pObjNew ); // pObjLi->Value = Abc_ObjId( pObjNewLi ); // pObjLo->Value = Abc_ObjId( pObjNewLo ); Abc_NtkFromCellWrite( vCopyLits, Gia_ObjId(p, pObjLi), 0, Abc_ObjId( pObjNewLi ) ); Abc_NtkFromCellWrite( vCopyLits, Gia_ObjId(p, pObjLo), 0, Abc_ObjId( pObjNewLo ) ); Abc_LatchSetInit0( pObjNew ); } // create constants Gia_ManForEachCo( p, pObj, i ) if ( Gia_ObjFaninId0p(p, pObj) == 0 ) fNeedConst[Gia_ObjFaninC0(pObj)] = 1; Gia_ManForEachBuf( p, pObj, i ) if ( Gia_ObjFaninId0p(p, pObj) == 0 ) fNeedConst[Gia_ObjFaninC0(pObj)] = 1; if ( fNeedConst[0] ) Abc_NtkFromCellWrite( vCopyLits, 0, 0, Abc_ObjId(Abc_NtkCreateNodeConst0(pNtkNew)) ); if ( fNeedConst[1] ) Abc_NtkFromCellWrite( vCopyLits, 0, 1, Abc_ObjId(Abc_NtkCreateNodeConst1(pNtkNew)) ); // rebuild the AIG Gia_ManForEachCell( p, iLit ) { int fSkip = 0; if ( Gia_ObjIsCellBuf(p, iLit) ) { assert( !Abc_LitIsCompl(iLit) ); // build buffer pObjNew = Abc_NtkCreateNode( pNtkNew ); iFanLit = Gia_ObjFaninLit0p( p, Gia_ManObj(p, Abc_Lit2Var(iLit)) ); Abc_ObjAddFanin( pObjNew, Abc_NtkFromCellRead(pNtkNew, vCopyLits, Abc_Lit2Var(iFanLit), Abc_LitIsCompl(iFanLit)) ); pObjNew->pData = NULL; // barrier buffer assert( Abc_ObjIsBarBuf(pObjNew) ); pNtkNew->nBarBufs2++; } else if ( Gia_ObjIsCellInv(p, iLit) ) { int iLitNot = Abc_LitNot(iLit); if ( !Abc_LitIsCompl(iLit) ) // positive phase { // build negative phase assert( Vec_IntEntry(vCopyLits, iLitNot) == -1 ); assert( Gia_ObjCellId(p, iLitNot) > 0 ); pObjNew = Abc_NtkCreateNode( pNtkNew ); Gia_CellForEachFanin( p, iLitNot, iFanLit, k ) Abc_ObjAddFanin( pObjNew, Abc_NtkFromCellRead(pNtkNew, vCopyLits, Abc_Lit2Var(iFanLit), Abc_LitIsCompl(iFanLit)) ); pObjNew->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)pNtkNew->pManFunc, pCells[Gia_ObjCellId(p, iLitNot)].pName, NULL ); Abc_NtkFromCellWrite( vCopyLits, Abc_Lit2Var(iLitNot), Abc_LitIsCompl(iLitNot), Abc_ObjId(pObjNew) ); fSkip = 1; } else // negative phase { // positive phase is available assert( Vec_IntEntry(vCopyLits, iLitNot) != -1 ); } // build inverter pObjNew = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pObjNew, Abc_NtkFromCellRead(pNtkNew, vCopyLits, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLitNot)) ); pObjNew->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)pNtkNew->pManFunc, pCells[3].pName, NULL ); } else { assert( Gia_ObjCellId(p, iLit) >= 0 ); pObjNew = Abc_NtkCreateNode( pNtkNew ); Gia_CellForEachFanin( p, iLit, iFanLit, k ) Abc_ObjAddFanin( pObjNew, Abc_NtkFromCellRead(pNtkNew, vCopyLits, Abc_Lit2Var(iFanLit), Abc_LitIsCompl(iFanLit)) ); pObjNew->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)pNtkNew->pManFunc, pCells[Gia_ObjCellId(p, iLit)].pName, NULL ); } assert( Vec_IntEntry(vCopyLits, iLit) == -1 ); Abc_NtkFromCellWrite( vCopyLits, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit), Abc_ObjId(pObjNew) ); // skip next iLit += fSkip; } // connect the PO nodes Gia_ManForEachCo( p, pObj, i ) { pObjNew = Abc_NtkFromCellRead( pNtkNew, vCopyLits, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew ); } // create names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); Abc_NtkAddDummyBoxNames( pNtkNew ); // decouple the PO driver nodes to reduce the number of levels if ( fFixDrivers ) { int nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, fDuplicate ); if ( fVerbose && nDupGates && !Abc_FrameReadFlag("silentmode") ) { if ( !fDuplicate ) printf( "Added %d buffers/inverters to decouple the CO drivers.\n", nDupGates ); else printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); } } assert( Gia_ManPiNum(p) == Abc_NtkPiNum(pNtkNew) ); assert( Gia_ManPoNum(p) == Abc_NtkPoNum(pNtkNew) ); assert( Gia_ManRegNum(p) == Abc_NtkLatchNum(pNtkNew) ); Vec_IntFree( vCopyLits ); ABC_FREE( pCells ); // check the resulting AIG if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [This procedure should be called after seq sweeping, which changes the number of registers.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkAfterTrim( Aig_Man_t * pMan, Abc_Ntk_t * pNtkOld ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjNew, * pObjOld; Aig_Obj_t * pObj, * pObjLo, * pObjLi; int i; assert( pMan->nAsserts == 0 ); assert( pNtkOld->nBarBufs == 0 ); assert( Aig_ManRegNum(pMan) <= Abc_NtkLatchNum(pNtkOld) ); assert( Saig_ManPiNum(pMan) <= Abc_NtkCiNum(pNtkOld) ); assert( Saig_ManPoNum(pMan) == Abc_NtkPoNum(pNtkOld) ); assert( pMan->vCiNumsOrig != NULL ); // perform strashing pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkNew->nConstrs = pMan->nConstrs; pNtkNew->nBarBufs = pMan->nBarBufs; // duplicate the name and the spec // pNtkNew->pName = Extra_UtilStrsav(pMan->pName); // pNtkNew->pSpec = Extra_UtilStrsav(pMan->pSpec); Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); // create PIs Aig_ManForEachPiSeq( pMan, pObj, i ) { pObjNew = Abc_NtkCreatePi( pNtkNew ); pObj->pData = pObjNew; // find the name pObjOld = Abc_NtkCi( pNtkOld, Vec_IntEntry(pMan->vCiNumsOrig, i) ); Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjOld), NULL ); } // create POs Aig_ManForEachPoSeq( pMan, pObj, i ) { pObjNew = Abc_NtkCreatePo( pNtkNew ); pObj->pData = pObjNew; // find the name pObjOld = Abc_NtkCo( pNtkOld, i ); Abc_ObjAssignName( pObjNew, Abc_ObjName(pObjOld), NULL ); } assert( Abc_NtkCiNum(pNtkNew) == Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) ); assert( Abc_NtkCoNum(pNtkNew) == Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) ); // create as many latches as there are registers in the manager Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) { pObjNew = Abc_NtkCreateLatch( pNtkNew ); pObjLi->pData = Abc_NtkCreateBi( pNtkNew ); pObjLo->pData = Abc_NtkCreateBo( pNtkNew ); Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)pObjLi->pData ); Abc_ObjAddFanin( (Abc_Obj_t *)pObjLo->pData, pObjNew ); Abc_LatchSetInit0( pObjNew ); // find the name pObjOld = Abc_NtkCi( pNtkOld, Vec_IntEntry(pMan->vCiNumsOrig, Saig_ManPiNum(pMan)+i) ); Abc_ObjAssignName( (Abc_Obj_t *)pObjLo->pData, Abc_ObjName(pObjOld), NULL ); // find the name pObjOld = Abc_NtkCo( pNtkOld, Saig_ManPoNum(pMan)+i ); Abc_ObjAssignName( (Abc_Obj_t *)pObjLi->pData, Abc_ObjName(pObjOld), NULL ); } // rebuild the AIG vNodes = Aig_ManDfs( pMan, 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); else pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // connect the PO nodes Aig_ManForEachCo( pMan, pObj, i ) { pObjNew = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjNew ); } // check the resulting AIG if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkAfterTrim(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) { Abc_Ntk_t * pNtkNew; Aig_Obj_t * pObj, * pTemp; int i; assert( pMan->pEquivs != NULL ); assert( Aig_ManBufNum(pMan) == 0 ); // perform strashing pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); pNtkNew->nConstrs = pMan->nConstrs; pNtkNew->nBarBufs = pNtkOld->nBarBufs; // transfer the pointers to the basic nodes Aig_ManCleanData( pMan ); Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); Aig_ManForEachCi( pMan, pObj, i ) pObj->pData = Abc_NtkCi(pNtkNew, i); // rebuild the AIG Aig_ManForEachNode( pMan, pObj, i ) { pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); if ( (pTemp = Aig_ObjEquiv(pMan, pObj)) ) { assert( pTemp->pData != NULL ); ((Abc_Obj_t *)pObj->pData)->pData = ((Abc_Obj_t *)pTemp->pData); } } // connect the PO nodes Aig_ManForEachCo( pMan, pObj, i ) Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkFromDar(): Network check has failed.\n" ); // verify topological order if ( 0 ) { Abc_Obj_t * pNode; Abc_NtkForEachNode( pNtkNew, pNode, i ) if ( Abc_AigNodeIsChoice( pNode ) ) { int Counter = 0; for ( pNode = Abc_ObjEquiv(pNode); pNode; pNode = Abc_ObjEquiv(pNode) ) Counter++; printf( "%d ", Counter ); } printf( "\n" ); } return pNtkNew; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromDarSeq( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; Aig_Obj_t * pObj; int i; // assert( Aig_ManLatchNum(pMan) > 0 ); assert( pNtkOld->nBarBufs == 0 ); // perform strashing pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); pNtkNew->nConstrs = pMan->nConstrs; pNtkNew->nBarBufs = pMan->nBarBufs; // transfer the pointers to the basic nodes Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); Aig_ManForEachCi( pMan, pObj, i ) pObj->pData = Abc_NtkPi(pNtkNew, i); // create latches of the new network Aig_ManForEachObj( pMan, pObj, i ) { pObjNew = Abc_NtkCreateLatch( pNtkNew ); pFaninNew0 = Abc_NtkCreateBi( pNtkNew ); pFaninNew1 = Abc_NtkCreateBo( pNtkNew ); Abc_ObjAddFanin( pObjNew, pFaninNew0 ); Abc_ObjAddFanin( pFaninNew1, pObjNew ); Abc_LatchSetInit0( pObjNew ); pObj->pData = Abc_ObjFanout0( pObjNew ); } Abc_NtkAddDummyBoxNames( pNtkNew ); // rebuild the AIG vNodes = Aig_ManDfs( pMan, 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { // add the first fanin pObj->pData = pFaninNew0 = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); if ( Aig_ObjIsBuf(pObj) ) continue; // add the second fanin pFaninNew1 = (Abc_Obj_t *)Aig_ObjChild1Copy(pObj); // create the new node if ( Aig_ObjIsExor(pObj) ) pObj->pData = pObjNew = Abc_AigXor( (Abc_Aig_t *)pNtkNew->pManFunc, pFaninNew0, pFaninNew1 ); else pObj->pData = pObjNew = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pFaninNew0, pFaninNew1 ); } Vec_PtrFree( vNodes ); // connect the PO nodes Aig_ManForEachCo( pMan, pObj, i ) { pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj ); Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), pFaninNew ); } // connect the latches Aig_ManForEachObj( pMan, pObj, i ) { pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj ); Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0((Abc_Obj_t *)pObj->pData)), pFaninNew ); } if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkFromIvySeq(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Collects CI of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Vec_Ptr_t * vNames; vNames = Vec_PtrAlloc( 100 ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_PtrPush( vNames, Extra_UtilStrsav(Abc_ObjName(pObj)) ); return vNames; } /**Function************************************************************* Synopsis [Collects CO of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Vec_Ptr_t * vNames; vNames = Vec_PtrAlloc( 100 ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_PtrPush( vNames, Extra_UtilStrsav(Abc_ObjName(pObj)) ); return vNames; } /**Function************************************************************* Synopsis [Collect latch values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkGetLatchValues( Abc_Ntk_t * pNtk ) { Vec_Int_t * vInits; Abc_Obj_t * pLatch; int i; vInits = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( Abc_LatchIsInit0(pLatch) ) Vec_IntPush( vInits, 0 ); else if ( Abc_LatchIsInit1(pLatch) ) Vec_IntPush( vInits, 1 ); else if ( Abc_LatchIsInitDc(pLatch) ) Vec_IntPush( vInits, 2 ); else assert( 0 ); } return vInits; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkAig = NULL; Aig_Man_t * pMan; extern void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim ); assert( Abc_NtkIsStrash(pNtk) ); // convert to the AIG manager pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; // perform computation // Fra_ManPartitionTest( pMan, 4 ); pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); // make sure everything is okay if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) ) { Abc_Print( 1, "Abc_NtkDar: The network check has failed.\n" ); Abc_NtkDelete( pNtkAig ); return NULL; } return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ) { Fra_Par_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; Fra_ParamsDefault( pPars ); pPars->nBTLimitNode = nConfLimit; pPars->fChoicing = fChoicing; pPars->fDoSparse = fDoSparse; pPars->fSpeculate = fSpeculate; pPars->fProve = fProve; pPars->fVerbose = fVerbose; pMan = Fra_FraigPerform( pTemp = pMan, pPars ); if ( fChoicing ) pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); else pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pTemp ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarFraigPart( Abc_Ntk_t * pNtk, int nPartSize, int nConfLimit, int nLevelMax, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; pMan = Aig_ManFraigPartitioned( pTemp = pMan, nPartSize, nConfLimit, nLevelMax, fVerbose ); Aig_ManStop( pTemp ); pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ) { // extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; pMan = Csw_Sweep( pTemp = pMan, nCutsMax, nLeafMax, fVerbose ); pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pTemp ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ) { Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig; abctime clk; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; // Aig_ManPrintStats( pMan ); /* // Aig_ManSupports( pMan ); { Vec_Vec_t * vParts; vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL ); Vec_VecFree( vParts ); } */ Dar_ManRewrite( pMan, pPars ); // pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel ); // Aig_ManStop( pTemp ); clk = Abc_Clock(); pMan = Aig_ManDupDfs( pTemp = pMan ); Aig_ManStop( pTemp ); //ABC_PRT( "time", Abc_Clock() - clk ); // Aig_ManPrintStats( pMan ); pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ) { Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig; abctime clk; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; // Aig_ManPrintStats( pMan ); Dar_ManRefactor( pMan, pPars ); // pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel ); // Aig_ManStop( pTemp ); clk = Abc_Clock(); pMan = Aig_ManDupDfs( pTemp = pMan ); Aig_ManStop( pTemp ); //ABC_PRT( "time", Abc_Clock() - clk ); // Aig_ManPrintStats( pMan ); pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ) { Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig; abctime clk; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; // Aig_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fFanout, fPower, fVerbose ); Aig_ManStop( pTemp ); //ABC_PRT( "time", Abc_Clock() - clk ); // Aig_ManPrintStats( pMan ); pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ) { Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; pMan = Dar_ManChoice( pTemp = pMan, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose ); Aig_ManStop( pTemp ); pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars ) { extern Gia_Man_t * Dar_NewChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fLightSynth, int fVerbose ); extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ); Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig; Gia_Man_t * pGia; abctime clk; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; clk = Abc_Clock(); if ( pPars->fSynthesis ) pGia = Dar_NewChoiceSynthesis( pMan, 1, 1, pPars->fPower, pPars->fLightSynth, pPars->fVerbose ); else { pGia = Gia_ManFromAig( pMan ); Aig_ManStop( pMan ); } pPars->timeSynth = Abc_Clock() - clk; if ( pPars->fUseGia ) pMan = Cec_ComputeChoices( pGia, pPars ); else { pMan = Gia_ManToAigSkip( pGia, 3 ); Gia_ManStop( pGia ); pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); Aig_ManStop( pTemp ); } pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ) { Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig; abctime clk; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; // Aig_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Dar_ManRwsat( pTemp = pMan, fBalance, fVerbose ); Aig_ManStop( pTemp ); //ABC_PRT( "time", Abc_Clock() - clk ); // Aig_ManPrintStats( pMan ); pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkConstructFromCnf( Abc_Ntk_t * pNtk, Cnf_Man_t * p, Vec_Ptr_t * vMapped ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pNodeNew; Aig_Obj_t * pObj, * pLeaf; Cnf_Cut_t * pCut; Vec_Int_t * vCover; unsigned uTruth; int i, k, nDupGates; // create the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // make the mapper point to the new network Aig_ManConst1(p->pManAig)->pData = Abc_NtkCreateNodeConst1(pNtkNew); Abc_NtkForEachCi( pNtk, pNode, i ) Aig_ManCi(p->pManAig, i)->pData = pNode->pCopy; // process the nodes in topological order vCover = Vec_IntAlloc( 1 << 16 ); Vec_PtrForEachEntry( Aig_Obj_t *, vMapped, pObj, i ) { // create new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); // add fanins according to the cut pCut = (Cnf_Cut_t *)pObj->pData; Cnf_CutForEachLeaf( p->pManAig, pCut, pLeaf, k ) Abc_ObjAddFanin( pNodeNew, (Abc_Obj_t *)pLeaf->pData ); // add logic function if ( pCut->nFanins < 5 ) { uTruth = 0xFFFF & *Cnf_CutTruth(pCut); Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vCover ); pNodeNew->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, pCut->nFanins, vCover ); } else pNodeNew->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, pCut->nFanins, pCut->vIsop[1] ); // save the node pObj->pData = pNodeNew; } Vec_IntFree( vCover ); // add the CO drivers Abc_NtkForEachCo( pNtk, pNode, i ) { pObj = Aig_ManCo(p->pManAig, i); pNodeNew = Abc_ObjNotCond( (Abc_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } // remove the constant node if not used pNodeNew = (Abc_Obj_t *)Aig_ManConst1(p->pManAig)->pData; if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) Abc_NtkDeleteObj( pNodeNew ); // minimize the node // Abc_NtkSweep( pNtkNew, 0 ); // decouple the PO driver nodes to reduce the number of levels nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); // if ( nDupGates && If_ManReadVerbose(pIfMan) ) // Abc_Print( 1, "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); if ( !Abc_NtkCheck( pNtkNew ) ) Abc_Print( 1, "Abc_NtkConstructFromCnf(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName, int fFastAlgo, int fChangePol, int fVerbose ) { // Vec_Ptr_t * vMapped = NULL; Aig_Man_t * pMan; // Cnf_Man_t * pManCnf = NULL; Cnf_Dat_t * pCnf; Abc_Ntk_t * pNtkNew = NULL; abctime clk = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); // convert to the AIG manager pMan = Abc_NtkToDar( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; if ( !Aig_ManCheck( pMan ) ) { Abc_Print( 1, "Abc_NtkDarToCnf: AIG check has failed.\n" ); Aig_ManStop( pMan ); return NULL; } // perform balance if ( fVerbose ) Aig_ManPrintStats( pMan ); // derive CNF if ( fFastAlgo ) pCnf = Cnf_DeriveFast( pMan, 0 ); else pCnf = Cnf_Derive( pMan, 0 ); // adjust polarity if ( fChangePol ) Cnf_DataTranformPolarity( pCnf, 0 ); // print stats // if ( fVerbose ) { Abc_Print( 1, "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /* // write the network for verification pManCnf = Cnf_ManRead(); vMapped = Cnf_ManScanMapping( pManCnf, 1, 0 ); pNtkNew = Abc_NtkConstructFromCnf( pNtk, pManCnf, vMapped ); Vec_PtrFree( vMapped ); */ // write CNF into a file Cnf_DataWriteIntoFile( pCnf, pFileName, 0, NULL, NULL ); Cnf_DataFree( pCnf ); Cnf_ManFree(); Aig_ManStop( pMan ); return pNtkNew; } /**Function************************************************************* Synopsis [Solves combinational miter using a SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose ) { Aig_Man_t * pMan; int RetValue;//, clk = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkLatchNum(pNtk) == 0 ); // assert( Abc_NtkPoNum(pNtk) == 1 ); pMan = Abc_NtkToDar( pNtk, 0, 0 ); RetValue = Fra_FraigSat( pMan, nConfLimit, nInsLimit, nLearnedStart, nLearnedDelta, nLearnedPerce, fAlignPol, fAndOuts, fNewSolver, fVerbose ); pNtk->pModel = (int *)pMan->pData, pMan->pData = NULL; Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Solves combinational miter using a SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkPartitionedSat( Abc_Ntk_t * pNtk, int nAlgo, int nPartSize, int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose ) { extern int Aig_ManPartitionedSat( Aig_Man_t * pNtk, int nAlgo, int nPartSize, int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose ); Aig_Man_t * pMan; int RetValue;//, clk = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkLatchNum(pNtk) == 0 ); pMan = Abc_NtkToDar( pNtk, 0, 0 ); RetValue = Aig_ManPartitionedSat( pMan, nAlgo, nPartSize, nConfPart, nConfTotal, fAlignPol, fSynthesize, fVerbose ); pNtk->pModel = (int *)pMan->pData, pMan->pData = NULL; Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarCec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int fPartition, int fVerbose ) { Aig_Man_t * pMan, * pMan1, * pMan2; Abc_Ntk_t * pMiter; int RetValue; abctime clkTotal = Abc_Clock(); /* { extern void Cec_ManVerifyTwoAigs( Aig_Man_t * pAig0, Aig_Man_t * pAig1, int fVerbose ); Aig_Man_t * pAig0 = Abc_NtkToDar( pNtk1, 0, 0 ); Aig_Man_t * pAig1 = Abc_NtkToDar( pNtk2, 0, 0 ); Cec_ManVerifyTwoAigs( pAig0, pAig1, 1 ); Aig_ManStop( pAig0 ); Aig_ManStop( pAig1 ); return 1; } */ // cannot partition if it is already a miter if ( pNtk2 == NULL && fPartition == 1 ) { Abc_Print( 1, "Abc_NtkDarCec(): Switching to non-partitioned CEC for the miter.\n" ); fPartition = 0; } // if partitioning is selected, call partitioned CEC if ( fPartition ) { pMan1 = Abc_NtkToDar( pNtk1, 0, 0 ); pMan2 = Abc_NtkToDar( pNtk2, 0, 0 ); RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, 100, 1, fVerbose ); Aig_ManStop( pMan1 ); Aig_ManStop( pMan2 ); goto finish; } if ( pNtk2 != NULL ) { // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0, 0, 0 ); if ( pMiter == NULL ) { Abc_Print( 1, "Miter computation has failed.\n" ); return 0; } } else { pMiter = Abc_NtkDup( pNtk1 ); } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { // extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); Abc_Print( 1, "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error if ( pNtk2 == NULL ) pNtk1->pModel = Abc_NtkVerifyGetCleanModel( pNtk1, 1 ); // pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); // Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); // ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return 0; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); Abc_Print( 1, "Networks are equivalent after structural hashing.\n" ); return 1; } // derive the AIG manager pMan = Abc_NtkToDar( pMiter, 0, 0 ); Abc_NtkDelete( pMiter ); if ( pMan == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return -1; } // perform verification RetValue = Fra_FraigCec( &pMan, 100000, fVerbose ); // transfer model if given if ( pNtk2 == NULL ) pNtk1->pModel = (int *)pMan->pData, pMan->pData = NULL; Aig_ManStop( pMan ); finish: // report the miter if ( RetValue == 1 ) { Abc_Print( 1, "Networks are equivalent. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } else if ( RetValue == 0 ) { Abc_Print( 1, "Networks are NOT EQUIVALENT. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } else { Abc_Print( 1, "Networks are UNDECIDED. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } fflush( stdout ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, Fra_Ssw_t * pPars ) { Fraig_Params_t Params; Abc_Ntk_t * pNtkAig = NULL, * pNtkFraig; Aig_Man_t * pMan, * pTemp; abctime clk = Abc_Clock(); // preprocess the miter by fraiging it // (note that for each functional class, fraiging leaves one representative; // so fraiging does not reduce the number of functions represented by nodes Fraig_ParamsSetDefault( &Params ); Params.nBTLimit = 100000; if ( pPars->fFraiging && pPars->nPartSize == 0 ) { pNtkFraig = Abc_NtkFraig( pNtk, &Params, 0, 0 ); if ( pPars->fVerbose ) { ABC_PRT( "Initial fraiging time", Abc_Clock() - clk ); } } else pNtkFraig = Abc_NtkDup( pNtk ); pMan = Abc_NtkToDar( pNtkFraig, 0, 1 ); Abc_NtkDelete( pNtkFraig ); if ( pMan == NULL ) return NULL; // pPars->TimeLimit = 5.0; pMan = Fra_FraigInduction( pTemp = pMan, pPars ); Aig_ManStop( pTemp ); if ( pMan ) { if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); else { Abc_Obj_t * pObj; int i; pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Abc_NtkForEachLatch( pNtkAig, pObj, i ) Abc_LatchSetInit0( pObj ); } Aig_ManStop( pMan ); } return pNtkAig; } /**Function************************************************************* Synopsis [Print Latch Equivalence Classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintLatchEquivClasses( Abc_Ntk_t * pNtk, Aig_Man_t * pAig ) { int header_dumped = 0; int num_orig_latches = Abc_NtkLatchNum(pNtk); char **pNames = ABC_ALLOC( char *, num_orig_latches ); int *p_irrelevant = ABC_ALLOC( int, num_orig_latches ); char * pFlopName, * pReprName; Aig_Obj_t * pFlop, * pRepr; Abc_Obj_t * pNtkFlop; int repr_idx; int i; Abc_NtkForEachLatch( pNtk, pNtkFlop, i ) { char *temp_name = Abc_ObjName( Abc_ObjFanout0(pNtkFlop) ); pNames[i] = ABC_ALLOC( char , strlen(temp_name)+1); strcpy(pNames[i], temp_name); } i = 0; Aig_ManSetCioIds( pAig ); Saig_ManForEachLo( pAig, pFlop, i ) { p_irrelevant[i] = false; pFlopName = pNames[i]; pRepr = Aig_ObjRepr(pAig, pFlop); if ( pRepr == NULL ) { // Abc_Print( 1, "Nothing equivalent to flop %s\n", pFlopName); // p_irrelevant[i] = true; continue; } if (!header_dumped) { Abc_Print( 1, "Here are the flop equivalences:\n"); header_dumped = true; } // pRepr is representative of the equivalence class, to which pFlop belongs if ( Aig_ObjIsConst1(pRepr) ) { Abc_Print( 1, "Original flop %s is proved equivalent to constant.\n", pFlopName ); // Abc_Print( 1, "Original flop # %d is proved equivalent to constant.\n", i ); continue; } assert( Saig_ObjIsLo( pAig, pRepr ) ); repr_idx = Aig_ObjCioId(pRepr) - Saig_ManPiNum(pAig); pReprName = pNames[repr_idx]; Abc_Print( 1, "Original flop %s is proved equivalent to flop %s.\n", pFlopName, pReprName ); // Abc_Print( 1, "Original flop # %d is proved equivalent to flop # %d.\n", i, repr_idx ); } header_dumped = false; for (i=0; ifFlopVerbose ) Abc_NtkPrintLatchEquivClasses(pNtk, pTemp); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); else { Abc_Obj_t * pObj; int i; pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Abc_NtkForEachLatch( pNtkAig, pObj, i ) Abc_LatchSetInit0( pObj ); } Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Computes latch correspondence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ) { Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig = NULL; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, NULL, 0.0 ); Aig_ManStop( pTemp ); if ( pMan ) { if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); else { Abc_Obj_t * pObj; int i; pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Abc_NtkForEachLatch( pNtkAig, pObj, i ) Abc_LatchSetInit0( pObj ); } Aig_ManStop( pMan ); } return pNtkAig; } /**Function************************************************************* Synopsis [Computes latch correspondence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarLcorrNew( Abc_Ntk_t * pNtk, int nVarsMax, int nConfMax, int fVerbose ) { Ssw_Pars_t Pars, * pPars = &Pars; Aig_Man_t * pMan, * pTemp; Abc_Ntk_t * pNtkAig = NULL; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; Ssw_ManSetDefaultParams( pPars ); pPars->fLatchCorrOpt = 1; pPars->nBTLimit = nConfMax; pPars->nSatVarMax = nVarsMax; pPars->fVerbose = fVerbose; pMan = Ssw_SignalCorrespondence( pTemp = pMan, pPars ); Aig_ManStop( pTemp ); if ( pMan ) { if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); else { Abc_Obj_t * pObj; int i; pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Abc_NtkForEachLatch( pNtkAig, pObj, i ) Abc_LatchSetInit0( pObj ); } Aig_ManStop( pMan ); } return pNtkAig; } /* #include #include "misc/util/utilMem.h" static void sigfunc( int signo ) { if (signo == SIGINT) { Abc_Print( 1, "SIGINT received!\n"); s_fInterrupt = 1; } } */ /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarBmc( Abc_Ntk_t * pNtk, int nStart, int nFrames, int nSizeMax, int nNodeDelta, int nTimeOut, int nBTLimit, int nBTLimitAll, int fRewrite, int fNewAlgo, int fOrDecomp, int nCofFanLit, int fVerbose, int * piFrames ) { Aig_Man_t * pMan; Vec_Int_t * vMap = NULL; int status, RetValue = -1; abctime clk = Abc_Clock(); abctime nTimeLimit = nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; // derive the AIG manager if ( fOrDecomp ) pMan = Abc_NtkToDarBmc( pNtk, &vMap ); else pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return RetValue; } assert( pMan->nRegs > 0 ); assert( vMap == NULL || Vec_IntSize(vMap) == Saig_ManPoNum(pMan) ); if ( fVerbose && vMap && Abc_NtkPoNum(pNtk) != Saig_ManPoNum(pMan) ) Abc_Print( 1, "Expanded %d outputs into %d outputs using OR decomposition.\n", Abc_NtkPoNum(pNtk), Saig_ManPoNum(pMan) ); // perform verification if ( fNewAlgo ) // command 'bmc' { int iFrame; RetValue = Saig_ManBmcSimple( pMan, nFrames, nSizeMax, nBTLimit, fRewrite, fVerbose, &iFrame, nCofFanLit ); if ( piFrames ) *piFrames = iFrame; ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; if ( RetValue == 1 ) Abc_Print( 1, "Incorrect return value. " ); else if ( RetValue == -1 ) { Abc_Print( 1, "No output asserted in %d frames. Resource limit reached ", Abc_MaxInt(iFrame+1,0) ); if ( nTimeLimit && Abc_Clock() > nTimeLimit ) Abc_Print( 1, "(timeout %d sec). ", nTimeLimit ); else Abc_Print( 1, "(conf limit %d). ", nBTLimit ); } else // if ( RetValue == 0 ) { Abc_Cex_t * pCex = pNtk->pSeqModel; Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pCex->iPo, pNtk->pName, pCex->iFrame ); } ABC_PRT( "Time", Abc_Clock() - clk ); } else { RetValue = Saig_BmcPerform( pMan, nStart, nFrames, nNodeDelta, nTimeOut, nBTLimit, nBTLimitAll, fVerbose, 0, piFrames, 0 ); ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; } // verify counter-example if ( pNtk->pSeqModel ) { status = Saig_ManVerifyCex( pMan, pNtk->pSeqModel ); if ( status == 0 ) Abc_Print( 1, "Abc_NtkDarBmc(): Counter-example verification has FAILED.\n" ); } Aig_ManStop( pMan ); // update the counter-example if ( pNtk->pSeqModel && vMap ) pNtk->pSeqModel->iPo = Vec_IntEntry( vMap, pNtk->pSeqModel->iPo ); Vec_IntFreeP( &vMap ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarBmc3( Abc_Ntk_t * pNtk, Saig_ParBmc_t * pPars, int fOrDecomp ) { Aig_Man_t * pMan; Vec_Int_t * vMap = NULL; int status, RetValue = -1; abctime clk = Abc_Clock(); abctime nTimeOut = pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; if ( fOrDecomp && !pPars->fSolveAll ) pMan = Abc_NtkToDarBmc( pNtk, &vMap ); else pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return RetValue; } assert( pMan->nRegs > 0 ); if ( pPars->fVerbose && vMap && Abc_NtkPoNum(pNtk) != Saig_ManPoNum(pMan) ) Abc_Print( 1, "Expanded %d outputs into %d outputs using OR decomposition.\n", Abc_NtkPoNum(pNtk), Saig_ManPoNum(pMan) ); RetValue = Saig_ManBmcScalable( pMan, pPars ); ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; if ( !pPars->fSilent ) { if ( RetValue == 1 ) { Abc_Print( 1, "Explored all reachable states after completing %d frames. ", 1<nFailOuts == 0 ) { Abc_Print( 1, "No output asserted in %d frames. Resource limit reached ", Abc_MaxInt(pPars->iFrame+1,0) ); if ( nTimeOut && Abc_Clock() > nTimeOut ) Abc_Print( 1, "(timeout %d sec). ", pPars->nTimeOut ); else Abc_Print( 1, "(conf limit %d). ", pPars->nConfLimit ); } else { Abc_Print( 1, "The total of %d outputs asserted in %d frames. Resource limit reached ", pPars->nFailOuts, pPars->iFrame ); if ( Abc_Clock() > nTimeOut ) Abc_Print( 1, "(timeout %d sec). ", pPars->nTimeOut ); else Abc_Print( 1, "(conf limit %d). ", pPars->nConfLimit ); } } else // if ( RetValue == 0 ) { if ( !pPars->fSolveAll ) { Abc_Cex_t * pCex = pNtk->pSeqModel; Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pCex->iPo, pNtk->pName, pCex->iFrame ); } else { int nOutputs = Saig_ManPoNum(pMan) - Saig_ManConstrNum(pMan); if ( pMan->vSeqModelVec == NULL || Vec_PtrCountZero(pMan->vSeqModelVec) == nOutputs ) Abc_Print( 1, "None of the %d outputs is found to be SAT", nOutputs ); else if ( Vec_PtrCountZero(pMan->vSeqModelVec) == 0 ) Abc_Print( 1, "All %d outputs are found to be SAT", nOutputs ); else { Abc_Print( 1, "Some outputs are SAT (%d out of %d)", nOutputs - Vec_PtrCountZero(pMan->vSeqModelVec), nOutputs ); if ( pPars->nDropOuts ) Abc_Print( 1, " while others timed out (%d out of %d)", pPars->nDropOuts, nOutputs ); } Abc_Print( 1, " after %d frames", pPars->iFrame+2 ); Abc_Print( 1, ". " ); } } ABC_PRT( "Time", Abc_Clock() - clk ); } if ( RetValue == 0 && pPars->fSolveAll ) { if ( pNtk->vSeqModelVec ) Vec_PtrFreeFree( pNtk->vSeqModelVec ); pNtk->vSeqModelVec = pMan->vSeqModelVec; pMan->vSeqModelVec = NULL; } if ( pNtk->pSeqModel ) { status = Saig_ManVerifyCex( pMan, pNtk->pSeqModel ); if ( status == 0 ) Abc_Print( 1, "Abc_NtkDarBmc3(): Counter-example verification has FAILED.\n" ); } Aig_ManStop( pMan ); // update the counter-example if ( pNtk->pSeqModel && vMap ) pNtk->pSeqModel->iPo = Vec_IntEntry( vMap, pNtk->pSeqModel->iPo ); Vec_IntFreeP( &vMap ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarBmcInter_int( Aig_Man_t * pMan, Inter_ManParams_t * pPars, Aig_Man_t ** ppNtkRes ) { int RetValue = -1, iFrame; abctime clk = Abc_Clock(); int nTotalProvedSat = 0; assert( pMan->nRegs > 0 ); if ( ppNtkRes ) *ppNtkRes = NULL; if ( pPars->fUseSeparate ) { Aig_Man_t * pTemp, * pAux; Aig_Obj_t * pObjPo; int i, Counter = 0; Saig_ManForEachPo( pMan, pObjPo, i ) { if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pMan) ) continue; if ( pPars->fVerbose ) Abc_Print( 1, "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pMan) ); pTemp = Aig_ManDupOneOutput( pMan, i, 1 ); pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 ); Aig_ManStop( pAux ); if ( Aig_ManRegNum(pTemp) == 0 ) { pTemp->pSeqModel = NULL; RetValue = Fra_FraigSat( pTemp, pPars->nBTLimit, 0, 0, 0, 0, 0, 0, 0, 0 ); if ( pTemp->pData ) pTemp->pSeqModel = Abc_CexCreate( Aig_ManRegNum(pMan), Saig_ManPiNum(pMan), (int *)pTemp->pData, 0, i, 1 ); // pNtk->pModel = pTemp->pData, pTemp->pData = NULL; } else RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &iFrame ); if ( pTemp->pSeqModel ) { if ( pPars->fDropSatOuts ) { Abc_Print( 1, "Output %d proved SAT in frame %d (replacing by const 0 and continuing...)\n", i, pTemp->pSeqModel->iFrame ); Aig_ObjPatchFanin0( pMan, pObjPo, Aig_ManConst0(pMan) ); Aig_ManStop( pTemp ); nTotalProvedSat++; continue; } else { Abc_Cex_t * pCex; pCex = pMan->pSeqModel = pTemp->pSeqModel; pTemp->pSeqModel = NULL; pCex->iPo = i; Aig_ManStop( pTemp ); break; } } // if solved, remove the output if ( RetValue == 1 ) { Aig_ObjPatchFanin0( pMan, pObjPo, Aig_ManConst0(pMan) ); // Abc_Print( 1, "Output %3d : Solved ", i ); } else { Counter++; // Abc_Print( 1, "Output %3d : Undec ", i ); } // Aig_ManPrintStats( pTemp ); Aig_ManStop( pTemp ); Abc_Print( 1, "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pMan) ); } Aig_ManCleanup( pMan ); if ( pMan->pSeqModel == NULL ) { Abc_Print( 1, "Interpolation left %d (out of %d) outputs unsolved \n", Counter, Saig_ManPoNum(pMan) ); if ( Counter ) RetValue = -1; } if ( ppNtkRes ) { pTemp = Aig_ManDupUnsolvedOutputs( pMan, 1 ); *ppNtkRes = Aig_ManScl( pTemp, 1, 1, 0, -1, -1, 0, 0 ); Aig_ManStop( pTemp ); } } else { RetValue = Inter_ManPerformInterpolation( pMan, pPars, &iFrame ); } if ( nTotalProvedSat ) Abc_Print( 1, "The total of %d outputs proved SAT and replaced by const 0 in this run.\n", nTotalProvedSat ); if ( RetValue == 1 ) Abc_Print( 1, "Property proved. " ); else if ( RetValue == 0 ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pMan->pSeqModel ? pMan->pSeqModel->iPo : -1, pMan->pName, iFrame ); else if ( RetValue == -1 ) Abc_Print( 1, "Property UNDECIDED. " ); else assert( 0 ); ABC_PRT( "Time", Abc_Clock() - clk ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarBmcInter( Abc_Ntk_t * pNtk, Inter_ManParams_t * pPars, Abc_Ntk_t ** ppNtkRes ) { Aig_Man_t * pMan; int RetValue; if ( ppNtkRes ) *ppNtkRes = NULL; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return -1; } if ( pPars->fUseSeparate && ppNtkRes ) { Aig_Man_t * pManNew; RetValue = Abc_NtkDarBmcInter_int( pMan, pPars, &pManNew ); *ppNtkRes = Abc_NtkFromAigPhase( pManNew ); Aig_ManStop( pManNew ); } else { RetValue = Abc_NtkDarBmcInter_int( pMan, pPars, NULL ); } ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk ) { char * pFileNameGeneric, pFileName0[1000], pFileName1[1000]; Aig_Man_t * pMan, * pPart0, * pPart1;//, * pMiter; // derive the AIG manager pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) { Abc_Print( 1, "Converting network into AIG has failed.\n" ); return 0; } // if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) ) if ( !Saig_ManDemiterSimpleDiff( pMan, &pPart0, &pPart1 ) ) { Aig_ManStop( pMan ); Abc_Print( 1, "Demitering has failed.\n" ); return 0; } // create file names pFileNameGeneric = Extra_FileNameGeneric( pNtk->pSpec ? pNtk->pSpec : pNtk->pName ); // sprintf( pFileName0, "%s%s", pFileNameGeneric, "_part0.aig" ); // sprintf( pFileName1, "%s%s", pFileNameGeneric, "_part1.aig" ); sprintf( pFileName0, "%s", "part0.aig" ); sprintf( pFileName1, "%s", "part1.aig" ); ABC_FREE( pFileNameGeneric ); // dump files Ioa_WriteAiger( pPart0, pFileName0, 0, 0 ); Ioa_WriteAiger( pPart1, pFileName1, 0, 0 ); Abc_Print( 1, "Demitering produced two files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); // create two-level miter // pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 ); // Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL ); // Aig_ManStop( pMiter ); // Abc_Print( 1, "The new miter is written into file \"%s\".\n", "miter01.blif" ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); Aig_ManStop( pMan ); return 1; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarDemiterNew( Abc_Ntk_t * pNtk ) { char * pFileNameGeneric, pFileName0[1000], pFileName1[1000]; Aig_Man_t * pMan, * pPart0, * pPart1;//, * pMiter; // derive the AIG manager pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) { Abc_Print( 1, "Converting network into AIG has failed.\n" ); return 0; } Saig_ManDemiterNew( pMan ); Aig_ManStop( pMan ); return 1; // if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) ) if ( !Saig_ManDemiterSimpleDiff( pMan, &pPart0, &pPart1 ) ) { Abc_Print( 1, "Demitering has failed.\n" ); return 0; } // create file names pFileNameGeneric = Extra_FileNameGeneric( pNtk->pSpec ); sprintf( pFileName0, "%s%s", pFileNameGeneric, "_part0.aig" ); sprintf( pFileName1, "%s%s", pFileNameGeneric, "_part1.aig" ); ABC_FREE( pFileNameGeneric ); // dump files Ioa_WriteAiger( pPart0, pFileName0, 0, 0 ); Ioa_WriteAiger( pPart1, pFileName1, 0, 0 ); Abc_Print( 1, "Demitering produced two files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); // create two-level miter // pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 ); // Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL ); // Aig_ManStop( pMiter ); // Abc_Print( 1, "The new miter is written into file \"%s\".\n", "miter01.blif" ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); Aig_ManStop( pMan ); return 1; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarDemiterDual( Abc_Ntk_t * pNtk, int fVerbose ) { char * pFileNameGeneric, pFileName0[1000], pFileName1[1000]; Aig_Man_t * pMan, * pPart0, * pPart1;//, * pMiter; if ( (Abc_NtkPoNum(pNtk) & 1) ) { Abc_Print( 1, "The number of POs should be even.\n" ); return 0; } // derive the AIG manager pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) { Abc_Print( 1, "Converting network into AIG has failed.\n" ); return 0; } // if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) ) if ( !Saig_ManDemiterDual( pMan, &pPart0, &pPart1 ) ) { Abc_Print( 1, "Demitering has failed.\n" ); return 0; } // create new AIG ABC_FREE( pPart0->pName ); pPart0->pName = Abc_UtilStrsav( "part0" ); // create new AIGs ABC_FREE( pPart1->pName ); pPart1->pName = Abc_UtilStrsav( "part1" ); // create file names pFileNameGeneric = Extra_FileNameGeneric( pNtk->pSpec ); // sprintf( pFileName0, "%s%s", pFileNameGeneric, "_part0.aig" ); // sprintf( pFileName1, "%s%s", pFileNameGeneric, "_part1.aig" ); sprintf( pFileName0, "%s", "part0.aig" ); sprintf( pFileName1, "%s", "part1.aig" ); ABC_FREE( pFileNameGeneric ); Ioa_WriteAiger( pPart0, pFileName0, 0, 0 ); Ioa_WriteAiger( pPart1, pFileName1, 0, 0 ); Abc_Print( 1, "Demitering produced two files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); // dump files if ( fVerbose ) { // Abc_Print( 1, "Init: " ); Aig_ManPrintStats( pMan ); // Abc_Print( 1, "Part1: " ); Aig_ManPrintStats( pPart0 ); // Abc_Print( 1, "Part2: " ); Aig_ManPrintStats( pPart1 ); } // create two-level miter // pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 ); // Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL ); // Aig_ManStop( pMiter ); // Abc_Print( 1, "The new miter is written into file \"%s\".\n", "miter01.blif" ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); Aig_ManStop( pMan ); return 1; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarProve( Abc_Ntk_t * pNtk, Fra_Sec_t * pSecPar, int nBmcFramesMax, int nBmcConfMax ) { Aig_Man_t * pMan; int iFrame = -1, RetValue = -1; abctime clkTotal = Abc_Clock(); if ( pSecPar->fTryComb || Abc_NtkLatchNum(pNtk) == 0 ) { Prove_Params_t Params, * pParams = &Params; Abc_Ntk_t * pNtkComb; int RetValue; abctime clk = Abc_Clock(); if ( Abc_NtkLatchNum(pNtk) == 0 ) Abc_Print( 1, "The network has no latches. Running CEC.\n" ); // create combinational network pNtkComb = Abc_NtkDup( pNtk ); Abc_NtkMakeComb( pNtkComb, 1 ); // solve it using combinational equivalence checking Prove_ParamsSetDefault( pParams ); pParams->fVerbose = 1; RetValue = Abc_NtkIvyProve( &pNtkComb, pParams ); // transfer model if given // pNtk->pModel = pNtkComb->pModel; pNtkComb->pModel = NULL; if ( RetValue == 0 && (Abc_NtkLatchNum(pNtk) == 0) ) { pNtk->pModel = pNtkComb->pModel; pNtkComb->pModel = NULL; Abc_Print( 1, "Networks are not equivalent.\n" ); ABC_PRT( "Time", Abc_Clock() - clk ); if ( pSecPar->fReportSolution ) { Abc_Print( 1, "SOLUTION: FAIL " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } return RetValue; } Abc_NtkDelete( pNtkComb ); // return the result, if solved if ( RetValue == 1 ) { Abc_Print( 1, "Networks are equivalent after CEC. " ); ABC_PRT( "Time", Abc_Clock() - clk ); if ( pSecPar->fReportSolution ) { Abc_Print( 1, "SOLUTION: PASS " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } return RetValue; } } // derive the AIG manager pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return -1; } assert( pMan->nRegs > 0 ); if ( pSecPar->fTryBmc ) { RetValue = Saig_BmcPerform( pMan, 0, nBmcFramesMax, 2000, 0, nBmcConfMax, 0, pSecPar->fVerbose, 0, &iFrame, 0 ); if ( RetValue == 0 ) { Abc_Print( 1, "Networks are not equivalent.\n" ); if ( pSecPar->fReportSolution ) { Abc_Print( 1, "SOLUTION: FAIL " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } // return the counter-example generated ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; Aig_ManStop( pMan ); return RetValue; } } // perform verification if ( pSecPar->fUseNewProver ) { RetValue = Ssw_SecGeneralMiter( pMan, NULL ); } else { RetValue = Fra_FraigSec( pMan, pSecPar, NULL ); ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; if ( pNtk->pSeqModel ) { Abc_Cex_t * pCex = pNtk->pSeqModel; Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.\n", pCex->iPo, pNtk->pName, pCex->iFrame ); if ( !Saig_ManVerifyCex( pMan, pNtk->pSeqModel ) ) Abc_Print( 1, "Abc_NtkDarProve(): Counter-example verification has FAILED.\n" ); } } Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Fra_Sec_t * pSecPar ) { // Fraig_Params_t Params; Aig_Man_t * pMan; Abc_Ntk_t * pMiter;//, * pTemp; int RetValue; // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0, 0, 0 ); if ( pMiter == NULL ) { Abc_Print( 1, "Miter computation has failed.\n" ); return 0; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); Abc_Print( 1, "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, pSecPar->nFramesMax ); // Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, pSecPar->nFramesMax ); ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return 0; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); Abc_Print( 1, "Networks are equivalent after structural hashing.\n" ); return 1; } // commented out because sometimes the problem became non-inductive /* // preprocess the miter by fraiging it // (note that for each functional class, fraiging leaves one representative; // so fraiging does not reduce the number of functions represented by nodes Fraig_ParamsSetDefault( &Params ); Params.nBTLimit = 100000; pMiter = Abc_NtkFraig( pTemp = pMiter, &Params, 0, 0 ); Abc_NtkDelete( pTemp ); RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); Abc_Print( 1, "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return 0; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); Abc_Print( 1, "Networks are equivalent after structural hashing.\n" ); return 1; } */ // derive the AIG manager pMan = Abc_NtkToDar( pMiter, 0, 1 ); Abc_NtkDelete( pMiter ); if ( pMan == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return -1; } assert( pMan->nRegs > 0 ); // perform verification RetValue = Fra_FraigSec( pMan, pSecPar, NULL ); Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarPdr( Abc_Ntk_t * pNtk, Pdr_Par_t * pPars ) { int RetValue = -1; abctime clk = Abc_Clock(); Aig_Man_t * pMan; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) { Abc_Print( 1, "Converting network into AIG has failed.\n" ); return -1; } RetValue = Pdr_ManSolve( pMan, pPars ); pPars->nDropOuts = Saig_ManPoNum(pMan) - pPars->nProveOuts - pPars->nFailOuts; if ( !pPars->fSilent ) { if ( pPars->fSolveAll ) Abc_Print( 1, "Properties: All = %d. Proved = %d. Disproved = %d. Undecided = %d. ", Saig_ManPoNum(pMan), pPars->nProveOuts, pPars->nFailOuts, pPars->nDropOuts ); else if ( RetValue == 1 ) Abc_Print( 1, "Property proved. " ); else { if ( RetValue == 0 ) { if ( pMan->pSeqModel == NULL ) Abc_Print( 1, "Abc_NtkDarPdr(): Counter-example is not available.\n" ); else { Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pMan->pSeqModel->iPo, pNtk->pName, pMan->pSeqModel->iFrame ); if ( !Saig_ManVerifyCex( pMan, pMan->pSeqModel ) ) Abc_Print( 1, "Abc_NtkDarPdr(): Counter-example verification has FAILED.\n" ); } } else if ( RetValue == -1 ) Abc_Print( 1, "Property UNDECIDED. " ); else assert( 0 ); } ABC_PRT( "Time", Abc_Clock() - clk ); /* Abc_Print( 1, "Status: " ); if ( pPars->pOutMap ) { int i; for ( i = 0; i < Saig_ManPoNum(pMan); i++ ) if ( pPars->pOutMap[i] == 1 ) Abc_Print( 1, "%d=%s ", i, "unsat" ); else if ( pPars->pOutMap[i] == 0 ) Abc_Print( 1, "%d=%s ", i, "sat" ); else if ( pPars->pOutMap[i] < 0 ) Abc_Print( 1, "%d=%s ", i, "undec" ); else assert( 0 ); } Abc_Print( 1, "\n" ); */ } ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; if ( pNtk->vSeqModelVec ) Vec_PtrFreeFree( pNtk->vSeqModelVec ); pNtk->vSeqModelVec = pMan->vSeqModelVec; pMan->vSeqModelVec = NULL; Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarAbSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fVerbose ) { Aig_Man_t * pMan1, * pMan2 = NULL; int RetValue; // derive AIG manager pMan1 = Abc_NtkToDar( pNtk1, 0, 1 ); if ( pMan1 == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return -1; } assert( Aig_ManRegNum(pMan1) > 0 ); // derive AIG manager if ( pNtk2 ) { pMan2 = Abc_NtkToDar( pNtk2, 0, 1 ); if ( pMan2 == NULL ) { Aig_ManStop( pMan1 ); Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return -1; } assert( Aig_ManRegNum(pMan2) > 0 ); if ( Saig_ManPiNum(pMan1) != Saig_ManPiNum(pMan2) ) { Aig_ManStop( pMan1 ); Aig_ManStop( pMan2 ); Abc_Print( 1, "The networks have different number of PIs.\n" ); return -1; } if ( Saig_ManPoNum(pMan1) != Saig_ManPoNum(pMan2) ) { Aig_ManStop( pMan1 ); Aig_ManStop( pMan2 ); Abc_Print( 1, "The networks have different number of POs.\n" ); return -1; } if ( Aig_ManRegNum(pMan1) != Aig_ManRegNum(pMan2) ) { Aig_ManStop( pMan1 ); Aig_ManStop( pMan2 ); Abc_Print( 1, "The networks have different number of flops.\n" ); return -1; } } // perform verification RetValue = Ssw_SecSpecialMiter( pMan1, pMan2, nFrames, fVerbose ); Aig_ManStop( pMan1 ); if ( pMan2 ) Aig_ManStop( pMan2 ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarSimSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Ssw_Pars_t * pPars ) { Aig_Man_t * pMan1, * pMan2 = NULL; int RetValue; // derive AIG manager pMan1 = Abc_NtkToDar( pNtk1, 0, 1 ); if ( pMan1 == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return -1; } assert( Aig_ManRegNum(pMan1) > 0 ); // derive AIG manager if ( pNtk2 ) { pMan2 = Abc_NtkToDar( pNtk2, 0, 1 ); if ( pMan2 == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return -1; } assert( Aig_ManRegNum(pMan2) > 0 ); } // perform verification RetValue = Ssw_SecWithSimilarity( pMan1, pMan2, pPars ); Aig_ManStop( pMan1 ); if ( pMan2 ) Aig_ManStop( pMan2 ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarMatch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nDist, int fVerbose ) { extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan1, * pMan2 = NULL, * pManRes; Vec_Int_t * vPairs; assert( Abc_NtkIsStrash(pNtk1) ); // derive AIG manager pMan1 = Abc_NtkToDar( pNtk1, 0, 1 ); if ( pMan1 == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return NULL; } assert( Aig_ManRegNum(pMan1) > 0 ); // derive AIG manager if ( pNtk2 ) { pMan2 = Abc_NtkToDar( pNtk2, 0, 1 ); if ( pMan2 == NULL ) { Abc_Print( 1, "Converting miter into AIG has failed.\n" ); return NULL; } assert( Aig_ManRegNum(pMan2) > 0 ); } // perform verification vPairs = Saig_StrSimPerformMatching( pMan1, pMan2, nDist, 1, &pManRes ); pNtkAig = Abc_NtkFromAigPhase( pManRes ); if ( vPairs ) Vec_IntFree( vPairs ); if ( pManRes ) Aig_ManStop( pManRes ); Aig_ManStop( pMan1 ); if ( pMan2 ) Aig_ManStop( pMan2 ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 ) { extern void Aig_ManPrintControlFanouts( Aig_Man_t * p ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; if ( fSaveNames ) { Aig_ManSeqCleanup( pMan ); if ( fLatchConst && pMan->nRegs ) pMan = Aig_ManConstReduce( pMan, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); if ( fLatchEqual && pMan->nRegs ) pMan = Aig_ManReduceLaches( pMan, fVerbose ); } else { if ( pMan->vFlopNums ) Vec_IntFree( pMan->vFlopNums ); pMan->vFlopNums = NULL; pMan = Aig_ManScl( pTemp = pMan, fLatchConst, fLatchEqual, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); Aig_ManStop( pTemp ); } pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); //Aig_ManPrintControlFanouts( pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; // Aig_ManReduceLachesCount( pMan ); if ( pMan->vFlopNums ) Vec_IntFree( pMan->vFlopNums ); pMan->vFlopNums = NULL; pMan = Rtm_ManRetime( pTemp = pMan, 1, nStepsMax, fVerbose ); Aig_ManStop( pTemp ); // pMan = Aig_ManReduceLaches( pMan, 1 ); // pMan = Aig_ManConstReduce( pMan, 1, 0 ); pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarRetimeF( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; // Aig_ManReduceLachesCount( pMan ); if ( pMan->vFlopNums ) Vec_IntFree( pMan->vFlopNums ); pMan->vFlopNums = NULL; pMan = Aig_ManRetimeFrontier( pTemp = pMan, nStepsMax ); Aig_ManStop( pTemp ); // pMan = Aig_ManReduceLaches( pMan, 1 ); // pMan = Aig_ManConstReduce( pMan, 1, 0 ); pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarRetimeMostFwd( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose ) { extern Aig_Man_t * Saig_ManRetimeForward( Aig_Man_t * p, int nIters, int fVerbose ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; // Aig_ManReduceLachesCount( pMan ); if ( pMan->vFlopNums ) Vec_IntFree( pMan->vFlopNums ); pMan->vFlopNums = NULL; pMan = Saig_ManRetimeForward( pTemp = pMan, nMaxIters, fVerbose ); Aig_ManStop( pTemp ); // pMan = Aig_ManReduceLaches( pMan, 1 ); // pMan = Aig_ManConstReduce( pMan, 1, 0 ); pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarRetimeMinArea( Abc_Ntk_t * pNtk, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ) { extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; if ( pMan->vFlopNums ) Vec_IntFree( pMan->vFlopNums ); pMan->vFlopNums = NULL; pMan = Saig_ManRetimeMinArea( pTemp = pMan, nMaxIters, fForwardOnly, fBackwardOnly, fInitial, fVerbose ); Aig_ManStop( pTemp ); pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarRetimeStep( Abc_Ntk_t * pNtk, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; if ( pMan->vFlopNums ) Vec_IntFree( pMan->vFlopNums ); pMan->vFlopNums = NULL; Aig_ManPrintStats(pMan); Saig_ManRetimeSteps( pMan, 1000, 1, 0 ); Aig_ManPrintStats(pMan); pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* Abc_Ntk_t * Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk, int nIters, int nSteps, int fRetimingOnly, int fAddBugs, int fUseCnf, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; if ( pMan->vFlopNums ) Vec_IntFree( pMan->vFlopNums ); pMan->vFlopNums = NULL; pMan = Saig_ManHaigRecord( pTemp = pMan, nIters, nSteps, fRetimingOnly, fAddBugs, fUseCnf, fVerbose ); Aig_ManStop( pTemp ); pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } */ /**Function************************************************************* Synopsis [Performs random simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fMiter, int fVerbose, char * pFileSim ) { Aig_Man_t * pMan; Abc_Cex_t * pCex; int status, RetValue = -1; abctime clk = Abc_Clock(); if ( Abc_NtkGetChoiceNum(pNtk) ) { Abc_Print( 1, "Removing %d choices from the AIG.\n", Abc_NtkGetChoiceNum(pNtk) ); Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); } pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( fNew ) { Gia_Man_t * pGia; Gia_ParSim_t Pars, * pPars = &Pars; Gia_ManSimSetDefaultParams( pPars ); pPars->nWords = nWords; pPars->nIters = nFrames; pPars->TimeLimit = TimeOut; pPars->fCheckMiter = fMiter; pPars->fVerbose = fVerbose; pGia = Gia_ManFromAig( pMan ); if ( Gia_ManSimSimulate( pGia, pPars ) ) { if ( pGia->pCexSeq ) { Abc_Print( 1, "Simulation of %d frames with %d words asserted output %d in frame %d. ", nFrames, nWords, pGia->pCexSeq->iPo, pGia->pCexSeq->iFrame ); status = Saig_ManVerifyCex( pMan, pGia->pCexSeq ); if ( status == 0 ) Abc_Print( 1, "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" ); } ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pGia->pCexSeq; pGia->pCexSeq = NULL; RetValue = 0; } else { Abc_Print( 1, "Simulation of %d frames with %d words did not assert the outputs. ", nFrames, nWords ); } Gia_ManStop( pGia ); } else // comb/seq simulator { Fra_Sml_t * pSml; if ( pFileSim != NULL ) { assert( Abc_NtkLatchNum(pNtk) == 0 ); pSml = Fra_SmlSimulateCombGiven( pMan, pFileSim, fMiter, fVerbose ); } else if ( Abc_NtkLatchNum(pNtk) == 0 ) pSml = Fra_SmlSimulateComb( pMan, nWords, fMiter ); else pSml = Fra_SmlSimulateSeq( pMan, 0, nFrames, nWords, fMiter ); if ( pSml->fNonConstOut ) { pCex = Fra_SmlGetCounterExample( pSml ); if ( pCex ) { Abc_Print( 1, "Simulation of %d frame%s with %d word%s asserted output %d in frame %d. ", pSml->nFrames, pSml->nFrames == 1 ? "": "s", pSml->nWordsFrame, pSml->nWordsFrame == 1 ? "": "s", pCex->iPo, pCex->iFrame ); status = Saig_ManVerifyCex( pMan, pCex ); if ( status == 0 ) Abc_Print( 1, "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" ); } ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pCex; RetValue = 0; } else { Abc_Print( 1, "Simulation of %d frames with %d words did not assert the outputs. ", nFrames, nWords ); } Fra_SmlStop( pSml ); } ABC_PRT( "Time", Abc_Clock() - clk ); Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Performs random simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarSeqSim3( Abc_Ntk_t * pNtk, Ssw_RarPars_t * pPars ) { Aig_Man_t * pMan; int status, RetValue = -1; // abctime clk = Abc_Clock(); if ( Abc_NtkGetChoiceNum(pNtk) ) { Abc_Print( 1, "Removing %d choices from the AIG.\n", Abc_NtkGetChoiceNum(pNtk) ); Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); } pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( Ssw_RarSimulate( pMan, pPars ) == 0 ) { if ( pMan->pSeqModel ) { // Abc_Print( 1, "Simulation of %d frames with %d words asserted output %d in frame %d. ", // nFrames, nWords, pMan->pSeqModel->iPo, pMan->pSeqModel->iFrame ); status = Saig_ManVerifyCex( pMan, pMan->pSeqModel ); if ( status == 0 ) Abc_Print( 1, "Abc_NtkDarSeqSim(): Counter-example verification has FAILED.\n" ); } ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; RetValue = 0; } else { // Abc_Print( 1, "Simulation of %d frames with %d words did not assert the outputs. ", // nFrames, nWords ); } if ( pNtk->vSeqModelVec ) Vec_PtrFreeFree( pNtk->vSeqModelVec ); pNtk->vSeqModelVec = pMan->vSeqModelVec; pMan->vSeqModelVec = NULL; // ABC_PRT( "Time", Abc_Clock() - clk ); pNtk->pData = pMan->pData; pMan->pData = NULL; Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarClau( Abc_Ntk_t * pNtk, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose ) { extern int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose ); extern int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClauses, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose ); Aig_Man_t * pMan; if ( fTarget && Abc_NtkPoNum(pNtk) != 1 ) { Abc_Print( 1, "The number of outputs should be 1.\n" ); return 1; } pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return 1; // Aig_ManReduceLachesCount( pMan ); if ( pMan->vFlopNums ) Vec_IntFree( pMan->vFlopNums ); pMan->vFlopNums = NULL; // Fra_Clau( pMan, nStepsMax, fVerbose, fVeryVerbose ); Fra_Claus( pMan, nFrames, nPref, nClauses, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fBmc, fRefs, fTarget, fVerbose, fVeryVerbose ); Aig_ManStop( pMan ); return 1; } /**Function************************************************************* Synopsis [Performs targe enlargement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; pMan = Aig_ManFrames( pTemp = pMan, nFrames, 0, 1, 1, 1, NULL ); Aig_ManStop( pTemp ); pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs targe enlargement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarTempor( Abc_Ntk_t * pNtk, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose ) { extern Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; pTemp = Saig_ManTempor( pMan, nFrames, TimeOut, nConfLimit, fUseBmc, fUseTransSigs, fVerbose, fVeryVerbose ); Aig_ManStop( pMan ); if ( pTemp == NULL ) return Abc_NtkDup( pNtk ); pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pTemp ); Aig_ManStop( pTemp ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs induction for property only.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarInduction( Abc_Ntk_t * pNtk, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose ) { Aig_Man_t * pMan; abctime clkTotal = Abc_Clock(); int RetValue; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return -1; RetValue = Saig_ManInduction( pMan, nTimeOut, nFramesMax, nConfMax, fUnique, fUniqueAll, fGetCex, fVerbose, fVeryVerbose ); if ( RetValue == 1 ) { Abc_Print( 1, "Networks are equivalent. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } else if ( RetValue == 0 ) { Abc_Print( 1, "Networks are NOT EQUIVALENT. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } else { Abc_Print( 1, "Networks are UNDECIDED. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( fGetCex ) { ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; } Aig_ManStop( pMan ); return RetValue; } /**Function************************************************************* Synopsis [Interplates two networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkInterOne( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fRelation, int fVerbose ) { extern Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fRelation, int fVerbose ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pManOn, * pManOff, * pManAig; if ( Abc_NtkCoNum(pNtkOn) != 1 || Abc_NtkCoNum(pNtkOff) != 1 ) { Abc_Print( 1, "Currently works only for single-output networks.\n" ); return NULL; } if ( Abc_NtkCiNum(pNtkOn) != Abc_NtkCiNum(pNtkOff) ) { Abc_Print( 1, "The number of PIs should be the same.\n" ); return NULL; } // create internal AIGs pManOn = Abc_NtkToDar( pNtkOn, 0, 0 ); if ( pManOn == NULL ) return NULL; pManOff = Abc_NtkToDar( pNtkOff, 0, 0 ); if ( pManOff == NULL ) return NULL; // derive the interpolant pManAig = Aig_ManInter( pManOn, pManOff, fRelation, fVerbose ); if ( pManAig == NULL ) { Abc_Print( 1, "Interpolant computation failed.\n" ); return NULL; } Aig_ManStop( pManOn ); Aig_ManStop( pManOff ); // for the relation, add an extra input if ( fRelation ) { Abc_Obj_t * pObj; pObj = Abc_NtkCreatePi( pNtkOff ); Abc_ObjAssignName( pObj, "New", NULL ); } // create logic network pNtkAig = Abc_NtkFromDar( pNtkOff, pManAig ); Aig_ManStop( pManAig ); return pNtkAig; } /**Function************************************************************* Synopsis [Fast interpolation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkInterFast( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fVerbose ) { extern void Aig_ManInterFast( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose ); Aig_Man_t * pManOn, * pManOff; // create internal AIGs pManOn = Abc_NtkToDar( pNtkOn, 0, 0 ); if ( pManOn == NULL ) return; pManOff = Abc_NtkToDar( pNtkOff, 0, 0 ); if ( pManOff == NULL ) return; Aig_ManInterFast( pManOn, pManOff, fVerbose ); Aig_ManStop( pManOn ); Aig_ManStop( pManOff ); } abctime timeCnf; abctime timeSat; abctime timeInt; /**Function************************************************************* Synopsis [Interplates two networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fRelation, int fVerbose ) { Abc_Ntk_t * pNtkOn1, * pNtkOff1, * pNtkInter1, * pNtkInter; Abc_Obj_t * pObj; int i; //, clk = Abc_Clock(); if ( Abc_NtkCoNum(pNtkOn) != Abc_NtkCoNum(pNtkOff) ) { Abc_Print( 1, "Currently works only for networks with equal number of POs.\n" ); return NULL; } // compute the fast interpolation time // Abc_NtkInterFast( pNtkOn, pNtkOff, fVerbose ); // consider the case of one output if ( Abc_NtkCoNum(pNtkOn) == 1 ) return Abc_NtkInterOne( pNtkOn, pNtkOff, fRelation, fVerbose ); // start the new network pNtkInter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkInter->pName = Extra_UtilStrsav(pNtkOn->pName); Abc_NtkForEachPi( pNtkOn, pObj, i ) Abc_NtkDupObj( pNtkInter, pObj, 1 ); // process each POs separately timeCnf = 0; timeSat = 0; timeInt = 0; Abc_NtkForEachCo( pNtkOn, pObj, i ) { pNtkOn1 = Abc_NtkCreateCone( pNtkOn, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 1 ); if ( Abc_ObjFaninC0(pObj) ) Abc_ObjXorFaninC( Abc_NtkPo(pNtkOn1, 0), 0 ); pObj = Abc_NtkCo(pNtkOff, i); pNtkOff1 = Abc_NtkCreateCone( pNtkOff, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 1 ); if ( Abc_ObjFaninC0(pObj) ) Abc_ObjXorFaninC( Abc_NtkPo(pNtkOff1, 0), 0 ); if ( Abc_NtkNodeNum(pNtkOn1) == 0 ) pNtkInter1 = Abc_NtkDup( pNtkOn1 ); else if ( Abc_NtkNodeNum(pNtkOff1) == 0 ) { pNtkInter1 = Abc_NtkDup( pNtkOff1 ); Abc_ObjXorFaninC( Abc_NtkPo(pNtkInter1, 0), 0 ); } else pNtkInter1 = Abc_NtkInterOne( pNtkOn1, pNtkOff1, 0, fVerbose ); if ( pNtkInter1 ) { Abc_NtkAppend( pNtkInter, pNtkInter1, 1 ); Abc_NtkDelete( pNtkInter1 ); } Abc_NtkDelete( pNtkOn1 ); Abc_NtkDelete( pNtkOff1 ); } // ABC_PRT( "CNF", timeCnf ); // ABC_PRT( "SAT", timeSat ); // ABC_PRT( "Int", timeInt ); // ABC_PRT( "Slow interpolation time", Abc_Clock() - clk ); // return the network if ( !Abc_NtkCheck( pNtkInter ) ) Abc_Print( 1, "Abc_NtkAttachBottom(): Network check has failed.\n" ); return pNtkInter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintSccs( Abc_Ntk_t * pNtk, int fVerbose ) { // extern Vec_Ptr_t * Aig_ManRegPartitionLinear( Aig_Man_t * pAig, int nPartSize ); Aig_Man_t * pMan; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return; Aig_ManComputeSccs( pMan ); // Aig_ManRegPartitionLinear( pMan, 1000 ); Aig_ManStop( pMan ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarPrintCone( Abc_Ntk_t * pNtk ) { extern void Saig_ManPrintCones( Aig_Man_t * pAig ); Aig_Man_t * pMan; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return 0; assert( Aig_ManRegNum(pMan) > 0 ); Saig_ManPrintCones( pMan ); Aig_ManStop( pMan ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkBalanceExor( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) { extern void Dar_BalancePrintStats( Aig_Man_t * p ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp;//, * pTemp2; assert( Abc_NtkIsStrash(pNtk) ); // derive AIG with EXORs pMan = Abc_NtkToDar( pNtk, 1, 0 ); if ( pMan == NULL ) return NULL; // Aig_ManPrintStats( pMan ); if ( fVerbose ) Dar_BalancePrintStats( pMan ); // perform balancing pTemp = Dar_ManBalance( pMan, fUpdateLevel ); // Aig_ManPrintStats( pTemp ); // create logic network pNtkAig = Abc_NtkFromDar( pNtk, pTemp ); Aig_ManStop( pTemp ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkPhaseAbstract( Abc_Ntk_t * pNtk, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose ) { extern Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose ); Vec_Int_t * vInits; Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; vInits = Abc_NtkGetLatchValues(pNtk); pMan = Saig_ManPhaseAbstract( pTemp = pMan, vInits, nFrames, nPref, fIgnore, fPrint, fVerbose ); Vec_IntFree( vInits ); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); // pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); // pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkPhaseFrameNum( Abc_Ntk_t * pNtk ) { extern int Saig_ManPhaseFrameNum( Aig_Man_t * p, Vec_Int_t * vInits ); Vec_Int_t * vInits; Aig_Man_t * pMan; int nFrames; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return 1; vInits = Abc_NtkGetLatchValues(pNtk); nFrames = Saig_ManPhaseFrameNum( pMan, vInits ); Vec_IntFree( vInits ); Aig_ManStop( pMan ); return nFrames; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarSynchOne( Abc_Ntk_t * pNtk, int nWords, int fVerbose ) { extern Aig_Man_t * Saig_SynchSequenceApply( Aig_Man_t * pAig, int nWords, int fVerbose ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; pMan = Saig_SynchSequenceApply( pTemp = pMan, nWords, fVerbose ); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarSynch( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nWords, int fVerbose ) { extern Aig_Man_t * Saig_Synchronize( Aig_Man_t * pAig1, Aig_Man_t * pAig2, int nWords, int fVerbose ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan1, * pMan2, * pMan; pMan1 = Abc_NtkToDar( pNtk1, 0, 1 ); if ( pMan1 == NULL ) return NULL; pMan2 = Abc_NtkToDar( pNtk2, 0, 1 ); if ( pMan2 == NULL ) { Aig_ManStop( pMan1 ); return NULL; } pMan = Saig_Synchronize( pMan1, pMan2, nWords, fVerbose ); Aig_ManStop( pMan1 ); Aig_ManStop( pMan2 ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); // pNtkAig->pName = Extra_UtilStrsav("miter"); // pNtkAig->pSpec = NULL; Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarClockGate( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, Cgt_Par_t * pPars ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan1, * pMan2 = NULL, * pMan; pMan1 = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan1 == NULL ) return NULL; if ( pCare ) { pMan2 = Abc_NtkToDar( pCare, 0, 0 ); if ( pMan2 == NULL ) { Aig_ManStop( pMan1 ); return NULL; } } pMan = Cgt_ClockGating( pMan1, pMan2, pPars ); Aig_ManStop( pMan1 ); if ( pMan2 ) Aig_ManStop( pMan2 ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarExtWin( Abc_Ntk_t * pNtk, int nObjId, int nDist, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan1, * pMan; Aig_Obj_t * pObj; pMan1 = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan1 == NULL ) return NULL; if ( nObjId == -1 ) { pObj = Saig_ManFindPivot( pMan1 ); Abc_Print( 1, "Selected object %d as a window pivot.\n", pObj->Id ); } else { if ( nObjId >= Aig_ManObjNumMax(pMan1) ) { Aig_ManStop( pMan1 ); Abc_Print( 1, "The ID is too large.\n" ); return NULL; } pObj = Aig_ManObj( pMan1, nObjId ); if ( pObj == NULL ) { Aig_ManStop( pMan1 ); Abc_Print( 1, "Object with ID %d does not exist.\n", nObjId ); return NULL; } if ( !Saig_ObjIsLo(pMan1, pObj) && !Aig_ObjIsNode(pObj) ) { Aig_ManStop( pMan1 ); Abc_Print( 1, "Object with ID %d is not a node or reg output.\n", nObjId ); return NULL; } } pMan = Saig_ManWindowExtract( pMan1, pObj, nDist ); Aig_ManStop( pMan1 ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarInsWin( Abc_Ntk_t * pNtk, Abc_Ntk_t * pCare, int nObjId, int nDist, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan1, * pMan2 = NULL, * pMan; Aig_Obj_t * pObj; pMan1 = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan1 == NULL ) return NULL; if ( nObjId == -1 ) { pObj = Saig_ManFindPivot( pMan1 ); Abc_Print( 1, "Selected object %d as a window pivot.\n", pObj->Id ); } else { if ( nObjId >= Aig_ManObjNumMax(pMan1) ) { Aig_ManStop( pMan1 ); Abc_Print( 1, "The ID is too large.\n" ); return NULL; } pObj = Aig_ManObj( pMan1, nObjId ); if ( pObj == NULL ) { Aig_ManStop( pMan1 ); Abc_Print( 1, "Object with ID %d does not exist.\n", nObjId ); return NULL; } if ( !Saig_ObjIsLo(pMan1, pObj) && !Aig_ObjIsNode(pObj) ) { Aig_ManStop( pMan1 ); Abc_Print( 1, "Object with ID %d is not a node or reg output.\n", nObjId ); return NULL; } } if ( pCare ) { pMan2 = Abc_NtkToDar( pCare, 0, 0 ); if ( pMan2 == NULL ) { Aig_ManStop( pMan1 ); return NULL; } } pMan = Saig_ManWindowInsert( pMan1, pObj, nDist, pMan2 ); Aig_ManStop( pMan1 ); if ( pMan2 ) Aig_ManStop( pMan2 ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarFrames( Abc_Ntk_t * pNtk, int nPrefix, int nFrames, int fInit, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; pMan = Saig_ManTimeframeSimplify( pTemp = pMan, nPrefix, nFrames, fInit, fVerbose ); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs phase abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarCleanupAig( Abc_Ntk_t * pNtk, int fCleanupPis, int fCleanupPos, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; if ( fCleanupPis ) { int Temp = Aig_ManCiCleanup( pMan ); if ( fVerbose ) Abc_Print( 1, "Cleanup removed %d primary inputs without fanout.\n", Temp ); } if ( fCleanupPos ) { int Temp = Aig_ManCoCleanup( pMan ); if ( fVerbose ) Abc_Print( 1, "Cleanup removed %d primary outputs driven by const-0.\n", Temp ); } pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDarReach( Abc_Ntk_t * pNtk, Saig_ParBbr_t * pPars ) { Aig_Man_t * pMan; int RetValue; pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return -1; RetValue = Aig_ManVerifyUsingBdds( pMan, pPars ); ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); pNtk->pSeqModel = pMan->pSeqModel; pMan->pSeqModel = NULL; Aig_ManStop( pMan ); return RetValue; } ABC_NAMESPACE_IMPL_END #include "map/amap/amap.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Amap_ManProduceNetwork( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapping ) { // extern void * Abc_FrameReadLibGen(); Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Amap_Out_t * pRes; Vec_Ptr_t * vNodesNew; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNodeNew, * pFaninNew; int i, k, iPis, iPos, nDupGates; // make sure gates exist in the current library Vec_PtrForEachEntry( Amap_Out_t *, vMapping, pRes, i ) if ( pRes->pName && Mio_LibraryReadGateByName( pLib, pRes->pName, NULL ) == NULL ) { Abc_Print( 1, "Current library does not contain gate \"%s\".\n", pRes->pName ); return NULL; } // create the network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP ); pNtkNew->pManFunc = pLib; iPis = iPos = 0; vNodesNew = Vec_PtrAlloc( Vec_PtrSize(vMapping) ); Vec_PtrForEachEntry( Amap_Out_t *, vMapping, pRes, i ) { if ( pRes->Type == -1 ) pNodeNew = Abc_NtkCi( pNtkNew, iPis++ ); else if ( pRes->Type == 1 ) pNodeNew = Abc_NtkCo( pNtkNew, iPos++ ); else { pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Mio_LibraryReadGateByName( pLib, pRes->pName, NULL ); } for ( k = 0; k < pRes->nFans; k++ ) { pFaninNew = (Abc_Obj_t *)Vec_PtrEntry( vNodesNew, pRes->pFans[k] ); Abc_ObjAddFanin( pNodeNew, pFaninNew ); } Vec_PtrPush( vNodesNew, pNodeNew ); } Vec_PtrFree( vNodesNew ); assert( iPis == Abc_NtkCiNum(pNtkNew) ); assert( iPos == Abc_NtkCoNum(pNtkNew) ); // decouple the PO driver nodes to reduce the number of levels nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // if ( nDupGates && Map_ManReadVerbose(pMan) ) // Abc_Print( 1, "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); return pNtkNew; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars ) { extern Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars ); Vec_Ptr_t * vMapping; Abc_Ntk_t * pNtkAig = NULL; Aig_Man_t * pMan; Aig_MmFlex_t * pMem; assert( Abc_NtkIsStrash(pNtk) ); // convert to the AIG manager pMan = Abc_NtkToDarChoices( pNtk ); if ( pMan == NULL ) return NULL; // perform computation vMapping = Amap_ManTest( pMan, pPars ); Aig_ManStop( pMan ); if ( vMapping == NULL ) return NULL; pMem = (Aig_MmFlex_t *)Vec_PtrPop( vMapping ); pNtkAig = Amap_ManProduceNetwork( pNtk, vMapping ); Aig_MmFlexStop( pMem, 0 ); Vec_PtrFree( vMapping ); // make sure everything is okay if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) ) { Abc_Print( 1, "Abc_NtkDar: The network check has failed.\n" ); Abc_NtkDelete( pNtkAig ); return NULL; } return pNtkAig; } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDarConstr( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose ) { Aig_Man_t * pMan;//, * pMan2;//, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return; if ( fStruct ) Saig_ManDetectConstrTest( pMan ); else Saig_ManDetectConstrFuncTest( pMan, nFrames, nConfs, nProps, fOldAlgo, fVerbose ); Aig_ManStop( pMan ); } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarOutdec( Abc_Ntk_t * pNtk, int nLits, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; pMan = Saig_ManDecPropertyOutput( pTemp = pMan, nLits, fVerbose ); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pMan->pName); pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarUnfold( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; if ( fStruct ) pMan = Saig_ManDupUnfoldConstrs( pTemp = pMan ); else pMan = Saig_ManDupUnfoldConstrsFunc( pTemp = pMan, nFrames, nConfs, nProps, fOldAlgo, fVerbose ); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pMan->pName); pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarFold( Abc_Ntk_t * pNtk, int fCompl, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; pMan = Saig_ManDupFoldConstrsFunc( pTemp = pMan, fCompl, fVerbose ); Aig_ManStop( pTemp ); pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pMan->pName); pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec); Aig_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDarConstrProfile( Abc_Ntk_t * pNtk, int fVerbose ) { extern int Ssw_ManProfileConstraints( Aig_Man_t * p, int nWords, int nFrames, int fVerbose ); extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Aig_Man_t * pMan; // Vec_Int_t * vProbOne; // Aig_Obj_t * pObj; // int i, Entry; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkConstrNum(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return; // value in the init state // Abc_AigSetNodePhases( pNtk ); /* // derive probabilities vProbOne = Saig_ManComputeSwitchProbs( pMan, 48, 16, 1 ); // iterate over the constraint outputs Saig_ManForEachPo( pMan, pObj, i ) { Entry = Vec_IntEntry( vProbOne, Aig_ObjId(pObj) ); if ( i < Saig_ManPoNum(pMan) - Saig_ManConstrNum(pMan) ) Abc_Print( 1, "Primary output : ", i ); else Abc_Print( 1, "Constraint %3d : ", i-(Saig_ManPoNum(pMan) - Saig_ManConstrNum(pMan)) ); Abc_Print( 1, "ProbOne = %f ", Abc_Int2Float(Entry) ); Abc_Print( 1, "AllZeroValue = %d ", Aig_ObjPhase(pObj) ); Abc_Print( 1, "\n" ); } */ // double-check Ssw_ManProfileConstraints( pMan, 16, 64, 1 ); Abc_Print( 1, "TwoFrameSatValue = %d.\n", Ssw_ManSetConstrPhases(pMan, 2, NULL) ); // clean up // Vec_IntFree( vProbOne ); Aig_ManStop( pMan ); } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDarTest( Abc_Ntk_t * pNtk, int Num ) { // extern void Saig_ManDetectConstr( Aig_Man_t * p ); // extern void Saig_ManDetectConstrFuncTest( Aig_Man_t * p ); // extern void Saig_ManFoldConstrTest( Aig_Man_t * pAig ); extern void Llb_ManComputeDomsTest( Aig_Man_t * pAig, int Num ); // extern void Fsim_ManTest( Aig_Man_t * pAig ); extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ); // Vec_Int_t * vPairs; Aig_Man_t * pMan;//, * pMan2;//, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return; /* Aig_ManSetRegNum( pMan, pMan->nRegs ); Aig_ManPrintStats( pMan ); Saig_ManDumpBlif( pMan, "_temp_.blif" ); Aig_ManStop( pMan ); pMan = Saig_ManReadBlif( "_temp_.blif" ); Aig_ManPrintStats( pMan ); */ /* Aig_ManSetRegNum( pMan, pMan->nRegs ); pTemp = Ssw_SignalCorrespondeceTestPairs( pMan ); Aig_ManStop( pTemp ); */ /* // Ssw_SecSpecialMiter( pMan, NULL, 2, 1 ); pMan2 = Aig_ManDupSimple(pMan); vPairs = Saig_StrSimPerformMatching( pMan, pMan2, 0, 1, NULL ); Vec_IntFree( vPairs ); Aig_ManStop( pMan ); Aig_ManStop( pMan2 ); */ // Ioa_WriteAigerBufferTest( pMan, "test.aig", 0, 0 ); // Saig_ManFoldConstrTest( pMan ); { extern void Saig_ManBmcSectionsTest( Aig_Man_t * p ); extern void Saig_ManBmcTerSimTest( Aig_Man_t * p ); extern void Saig_ManBmcSupergateTest( Aig_Man_t * p ); extern void Saig_ManBmcMappingTest( Aig_Man_t * p ); // Saig_ManBmcSectionsTest( pMan ); // Saig_ManBmcTerSimTest( pMan ); // Saig_ManBmcSupergateTest( pMan ); // Saig_ManBmcMappingTest( pMan ); } { // void Pdr_ManEquivClasses( Aig_Man_t * pMan ); // Pdr_ManEquivClasses( pMan ); } // Llb_ManComputeDomsTest( pMan, Num ); { extern void Llb_ManMinCutTest( Aig_Man_t * pMan, int Num ); extern void Llb_BddStructAnalysis( Aig_Man_t * pMan ); extern void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num ); // Llb_BddStructAnalysis( pMan ); // Llb_ManMinCutTest( pMan, Num ); // Llb_NonlinExperiment( pMan, Num ); } // Saig_MvManSimulate( pMan, 1 ); // Saig_ManDetectConstr( pMan ); // Saig_ManDetectConstrFuncTest( pMan ); // Fsim_ManTest( pMan ); Aig_ManStop( pMan ); } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk ) { // extern Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ); /* extern Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig ); Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; Aig_ManSetRegNum( pMan, pMan->nRegs ); pMan = Ssw_SignalCorrespondeceTestPairs( pTemp = pMan ); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Aig_ManStop( pMan ); return pNtkAig; */ Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan;//, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; /* Aig_ManSetRegNum( pMan, pMan->nRegs ); pMan = Saig_ManDualRail( pTemp = pMan, 1 ); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Aig_ManStop( pMan ); */ pNtkAig = Abc_NtkFromDar( pNtk, pMan ); Aig_ManStop( pMan ); return pNtkAig; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #include "abcDarUnfold2.c" ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDarUnfold2.c000066400000000000000000000042321300674244400244170ustar00rootroot00000000000000/**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarFold2( Abc_Ntk_t * pNtk, int fCompl, int fVerbose , int); Abc_Ntk_t * Abc_NtkDarUnfold2( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; int typeII_cnt = 0; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; if ( fStruct ){ assert(0);//pMan = Saig_ManDupUnfoldConstrs( pTemp = pMan ); }else pMan = Saig_ManDupUnfoldConstrsFunc2( pTemp = pMan, nFrames, nConfs, nProps, fOldAlgo, fVerbose , &typeII_cnt); Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; // typeII_cnt = pMan->nConstrsTypeII; pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pMan->pName); pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec); Aig_ManStop( pMan ); return pNtkAig;//Abc_NtkDarFold2(pNtkAig, 0, fVerbose, typeII_cnt); //return pNtkAig; } /**Function************************************************************* Synopsis [Performs BDD-based reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDarFold2( Abc_Ntk_t * pNtk, int fCompl, int fVerbose , int typeII_cnt ) { Abc_Ntk_t * pNtkAig; Aig_Man_t * pMan, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) return NULL; pMan = Saig_ManDupFoldConstrsFunc2( pTemp = pMan, fCompl, fVerbose, typeII_cnt ); Aig_ManStop( pTemp ); pNtkAig = Abc_NtkFromAigPhase( pMan ); pNtkAig->pName = Extra_UtilStrsav(pMan->pName); pNtkAig->pSpec = Extra_UtilStrsav(pMan->pSpec); Aig_ManStop( pMan ); return pNtkAig; } berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDebug.c000066400000000000000000000154521300674244400235130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDebug.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Automated debugging procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDebug.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ); static Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtk, int ObjNum, int fConst1 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Takes a network and a procedure to test.] Description [The network demonstrates the bug in the procedure. Procedure should return 1 if the bug is demonstrated.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ) { Abc_Ntk_t * pNtkMod; char * pFileName = "bug_found.blif"; int i, nSteps, nIter, ModNum, RandNum = 1; abctime clk, clkTotal = Abc_Clock(); assert( Abc_NtkIsLogic(pNtk) ); srand( 0x123123 ); // create internal copy of the network pNtk = Abc_NtkDup(pNtk); if ( !(*pFuncError)( pNtk ) ) { printf( "The original network does not cause the bug. Quitting.\n" ); Abc_NtkDelete( pNtk ); return; } // perform incremental modifications for ( nIter = 0; ; nIter++ ) { clk = Abc_Clock(); // count how many ways of modifying the network exists nSteps = 2 * Abc_NtkCountFaninsTotal(pNtk); // try modifying the network as many times RandNum ^= rand(); for ( i = 0; i < nSteps; i++ ) { // get the shifted number of bug ModNum = (i + RandNum) % nSteps; // get the modified network pNtkMod = Abc_NtkAutoDebugModify( pNtk, ModNum/2, ModNum%2 ); // write the network Io_WriteBlifLogic( pNtk, "bug_temp.blif", 1 ); // check if the bug is still there if ( (*pFuncError)( pNtkMod ) ) // bug is still there { Abc_NtkDelete( pNtk ); pNtk = pNtkMod; break; } else // no bug Abc_NtkDelete( pNtkMod ); } printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d. ", nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i ); ABC_PRT( "Time", Abc_Clock() - clk ); if ( i == nSteps ) // could not modify it while preserving the bug break; } // write out the final network Io_WriteBlifLogic( pNtk, pFileName, 1 ); printf( "Final network written into file \"%s\". ", pFileName ); ABC_PRT( "Total time", Abc_Clock() - clkTotal ); Abc_NtkDelete( pNtk ); } /**Function************************************************************* Synopsis [Counts the total number of fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFanin; int i, k, Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) { if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) continue; if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) continue; if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) continue; Counter++; } return Counter; } /**Function************************************************************* Synopsis [Returns the node and fanin to be modified.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_Obj_t ** ppFanin ) { Abc_Obj_t * pObj, * pFanin; int i, k, Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) { if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) continue; if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) continue; if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) continue; if ( Counter++ == Step ) { *ppObj = pObj; *ppFanin = pFanin; return 1; } } return 0; } /**Function************************************************************* Synopsis [Perform modification with the given number.] Description [Modification consists of replacing the node by a constant.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 ) { extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); Abc_Ntk_t * pNtk; Abc_Obj_t * pObj, * pFanin, * pConst; // copy the network pNtk = Abc_NtkDup( pNtkInit ); assert( Abc_NtkNodeNum(pNtk) == Abc_NtkNodeNum(pNtkInit) ); // find the object number Abc_NtkFindGivenFanin( pNtk, Step, &pObj, &pFanin ); // consider special case if ( Abc_ObjIsPo(pObj) && Abc_NodeIsConst(pFanin) ) { Abc_NtkDeleteAll_rec( pObj ); return pNtk; } // plug in a constant node pConst = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); Abc_ObjTransferFanout( pFanin, pConst ); Abc_NtkDeleteAll_rec( pFanin ); Abc_NtkSweep( pNtk, 0 ); Abc_NtkCleanupSeq( pNtk, 0, 0, 0 ); Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); Abc_NtkCycleInitStateSop( pNtk, 50, 0 ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDec.c000066400000000000000000000512471300674244400231620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures for testing and comparing decomposition algorithms.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "misc/extra/extra.h" #include "misc/vec/vec.h" #include "bool/bdc/bdc.h" #include "bool/dec/dec.h" #include "bool/kit/kit.h" #include "opt/dau/dau.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // decomposition type // 0 - none // 1 - factoring // 2 - bi-decomposition // 3 - DSD // data-structure to store a bunch of truth tables typedef struct Abc_TtStore_t_ Abc_TtStore_t; struct Abc_TtStore_t_ { int nVars; int nWords; int nFuncs; word ** pFuncs; }; // read/write/flip i-th bit of a bit string table: static inline int Abc_TruthGetBit( word * p, int i ) { return (int)(p[i>>6] >> (i & 63)) & 1; } static inline void Abc_TruthSetBit( word * p, int i ) { p[i>>6] |= (((word)1)<<(i & 63)); } static inline void Abc_TruthXorBit( word * p, int i ) { p[i>>6] ^= (((word)1)<<(i & 63)); } // read/write k-th digit d of a hexadecimal number: static inline int Abc_TruthGetHex( word * p, int k ) { return (int)(p[k>>4] >> ((k<<2) & 63)) & 15; } static inline void Abc_TruthSetHex( word * p, int k, int d ) { p[k>>4] |= (((word)d)<<((k<<2) & 63)); } static inline void Abc_TruthXorHex( word * p, int k, int d ) { p[k>>4] ^= (((word)d)<<((k<<2) & 63)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // read one hex character static inline int Abc_TruthReadHexDigit( char HexChar ) { if ( HexChar >= '0' && HexChar <= '9' ) return HexChar - '0'; if ( HexChar >= 'A' && HexChar <= 'F' ) return HexChar - 'A' + 10; if ( HexChar >= 'a' && HexChar <= 'f' ) return HexChar - 'a' + 10; assert( 0 ); // not a hexadecimal symbol return -1; // return value which makes no sense } // write one hex character static inline void Abc_TruthWriteHexDigit( FILE * pFile, int HexDigit ) { assert( HexDigit >= 0 && HexDigit < 16 ); if ( HexDigit < 10 ) fprintf( pFile, "%d", HexDigit ); else fprintf( pFile, "%c", 'A' + HexDigit-10 ); } // read one truth table in hexadecimal void Abc_TruthReadHex( word * pTruth, char * pString, int nVars ) { int nWords = (nVars < 7)? 1 : (1 << (nVars-6)); int k, Digit, nDigits = (nVars < 7) ? (1 << (nVars-2)) : (nWords << 4); char EndSymbol; // skip the first 2 symbols if they are "0x" if ( pString[0] == '0' && pString[1] == 'x' ) pString += 2; // get the last symbol EndSymbol = pString[nDigits]; // the end symbol of the TT (the one immediately following hex digits) // should be one of the following: space, a new-line, or a zero-terminator // (note that on Windows symbols '\r' can be inserted before each '\n') assert( EndSymbol == ' ' || EndSymbol == '\n' || EndSymbol == '\r' || EndSymbol == '\0' ); // read hexadecimal digits in the reverse order // (the last symbol in the string is the least significant digit) for ( k = 0; k < nDigits; k++ ) { Digit = Abc_TruthReadHexDigit( pString[nDigits - 1 - k] ); assert( Digit >= 0 && Digit < 16 ); Abc_TruthSetHex( pTruth, k, Digit ); } } // write one truth table in hexadecimal (do not add end-of-line!) void Abc_TruthWriteHex( FILE * pFile, word * pTruth, int nVars ) { int nDigits, Digit, k; nDigits = (1 << (nVars-2)); for ( k = 0; k < nDigits; k++ ) { Digit = Abc_TruthGetHex( pTruth, k ); assert( Digit >= 0 && Digit < 16 ); Abc_TruthWriteHexDigit( pFile, Digit ); } } /**Function************************************************************* Synopsis [Allocate/Deallocate storage for truth tables..] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_TtStore_t * Abc_TruthStoreAlloc( int nVars, int nFuncs ) { Abc_TtStore_t * p; int i; p = (Abc_TtStore_t *)malloc( sizeof(Abc_TtStore_t) ); p->nVars = nVars; p->nWords = (nVars < 7) ? 1 : (1 << (nVars-6)); p->nFuncs = nFuncs; // alloc storage for 'nFuncs' truth tables as one chunk of memory p->pFuncs = (word **)malloc( (sizeof(word *) + sizeof(word) * p->nWords) * p->nFuncs ); // assign and clean the truth table storage p->pFuncs[0] = (word *)(p->pFuncs + p->nFuncs); memset( p->pFuncs[0], 0, sizeof(word) * p->nWords * p->nFuncs ); // split it up into individual truth tables for ( i = 1; i < p->nFuncs; i++ ) p->pFuncs[i] = p->pFuncs[i-1] + p->nWords; return p; } Abc_TtStore_t * Abc_TruthStoreAlloc2( int nVars, int nFuncs, word * pBuffer ) { Abc_TtStore_t * p; int i; p = (Abc_TtStore_t *)malloc( sizeof(Abc_TtStore_t) ); p->nVars = nVars; p->nWords = (nVars < 7) ? 1 : (1 << (nVars-6)); p->nFuncs = nFuncs; // alloc storage for 'nFuncs' truth tables as one chunk of memory p->pFuncs = (word **)malloc( sizeof(word *) * p->nFuncs ); // assign and clean the truth table storage p->pFuncs[0] = pBuffer; // split it up into individual truth tables for ( i = 1; i < p->nFuncs; i++ ) p->pFuncs[i] = p->pFuncs[i-1] + p->nWords; return p; } void Abc_TtStoreFree( Abc_TtStore_t * p, int nVarNum ) { if ( nVarNum >= 0 ) ABC_FREE( p->pFuncs[0] ); ABC_FREE( p->pFuncs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Read file contents.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FileSize( char * pFileName ) { FILE * pFile; int nFileSize; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return -1; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); fclose( pFile ); return nFileSize; } /**Function************************************************************* Synopsis [Read file contents.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_FileRead( char * pFileName ) { FILE * pFile; char * pBuffer; int nFileSize, RetValue; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return NULL; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = (char *)malloc( nFileSize + 3 ); RetValue = fread( pBuffer, nFileSize, 1, pFile ); // add several empty lines at the end // (these will be used to signal the end of parsing) pBuffer[ nFileSize + 0] = '\n'; pBuffer[ nFileSize + 1] = '\n'; // terminate the string with '\0' pBuffer[ nFileSize + 2] = '\0'; fclose( pFile ); return pBuffer; } /**Function************************************************************* Synopsis [Determine the number of variables by reading the first line.] Description [Determine the number of functions by counting the lines.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthGetParams( char * pFileName, int * pnVars, int * pnTruths ) { char * pContents; int i, nVars, nLines; // prepare the output if ( pnVars ) *pnVars = 0; if ( pnTruths ) *pnTruths = 0; // read data from file pContents = Abc_FileRead( pFileName ); if ( pContents == NULL ) return; // count the number of symbols before the first space or new-line // (note that on Windows symbols '\r' can be inserted before each '\n') for ( i = 0; pContents[i]; i++ ) if ( pContents[i] == ' ' || pContents[i] == '\n' || pContents[i] == '\r' ) break; if ( pContents[i] == 0 ) printf( "Strange, the input file does not have spaces and new-lines...\n" ); // acount for the fact that truth tables may have "0x" at the beginning of each line if ( pContents[0] == '0' && pContents[1] == 'x' ) i = i - 2; // determine the number of variables for ( nVars = 0; nVars < 32; nVars++ ) if ( 4 * i == (1 << nVars) ) // the number of bits equal to the size of truth table break; if ( nVars < 2 || nVars > 16 ) { printf( "Does not look like the input file contains truth tables...\n" ); return; } if ( pnVars ) *pnVars = nVars; // determine the number of functions by counting the lines nLines = 0; for ( i = 0; pContents[i]; i++ ) nLines += (pContents[i] == '\n'); if ( pnTruths ) *pnTruths = nLines; ABC_FREE( pContents ); } /**Function************************************************************* Synopsis [Read truth tables from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthStoreRead( char * pFileName, Abc_TtStore_t * p ) { char * pContents; int i, nLines; pContents = Abc_FileRead( pFileName ); if ( pContents == NULL ) return; // here it is assumed (without checking!) that each line of the file // begins with a string of hexadecimal chars followed by space // the file will be read till the first empty line (pContents[i] == '\n') // (note that Abc_FileRead() added several empty lines at the end of the file contents) for ( nLines = i = 0; pContents[i] != '\n'; ) { // read one line Abc_TruthReadHex( p->pFuncs[nLines++], &pContents[i], p->nVars ); // skip till after the end-of-line symbol // (note that end-of-line symbol is also skipped) while ( pContents[i++] != '\n' ); } // adjust the number of functions read // (we may have allocated more storage because some lines in the file were empty) assert( p->nFuncs >= nLines ); p->nFuncs = nLines; ABC_FREE( pContents ); } /**Function************************************************************* Synopsis [Write truth tables into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p, int fBinary ) { FILE * pFile; char pBuffer[1000]; int i, nBytes = 8 * Abc_Truth6WordNum( p->nVars ); pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } for ( i = 0; i < p->nFuncs; i++ ) { if ( fBinary ) fwrite( p->pFuncs[i], nBytes, 1, pFile ); else { Abc_TruthWriteHex( pFile, p->pFuncs[i], p->nVars ), fprintf( pFile, " " ); Dau_DsdDecompose( p->pFuncs[i], p->nVars, 0, (int)(p->nVars <= 10), pBuffer ); fprintf( pFile, "%s\n", pBuffer ); } } fclose( pFile ); } /**Function************************************************************* Synopsis [Read truth tables from input file and write them into output file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_TtStore_t * Abc_TtStoreLoad( char * pFileName, int nVarNum ) { Abc_TtStore_t * p; if ( nVarNum < 0 ) { int nVars, nTruths; // figure out how many truth table and how many variables Abc_TruthGetParams( pFileName, &nVars, &nTruths ); if ( nVars < 2 || nVars > 16 || nTruths == 0 ) return NULL; // allocate data-structure p = Abc_TruthStoreAlloc( nVars, nTruths ); // read info from file Abc_TruthStoreRead( pFileName, p ); } else { char * pBuffer; int nFileSize = Abc_FileSize( pFileName ); int nBytes = (1 << (nVarNum-3)); int nTruths = nFileSize / nBytes; if ( nFileSize == -1 ) return NULL; assert( nVarNum >= 6 ); if ( nFileSize % nBytes != 0 ) Abc_Print( 0, "The file size (%d) is divided by the truth table size (%d) with remainder (%d).\n", nFileSize, nBytes, nFileSize % nBytes ); // read file contents pBuffer = Abc_FileRead( pFileName ); // allocate data-structure p = Abc_TruthStoreAlloc2( nVarNum, nTruths, (word *)pBuffer ); } return p; } /**Function************************************************************* Synopsis [Read truth tables from input file and write them into output file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TtStoreTest( char * pFileName ) { Abc_TtStore_t * p; char * pFileInput = pFileName; char * pFileOutput = "out.txt"; // read info from file p = Abc_TtStoreLoad( pFileInput, -1 ); if ( p == NULL ) return; // write into another file Abc_TtStoreWrite( pFileOutput, p, 0 ); // delete data-structure Abc_TtStoreFree( p, -1 ); printf( "Input file \"%s\" was copied into output file \"%s\".\n", pFileInput, pFileOutput ); } /**Function************************************************************* Synopsis [Apply decomposition to the truth table.] Description [Returns the number of AIG nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthDecPerform( Abc_TtStore_t * p, int DecType, int fVerbose ) { abctime clk = Abc_Clock(); int i, nNodes = 0; char * pAlgoName = NULL; if ( DecType == 1 ) pAlgoName = "factoring"; else if ( DecType == 2 ) pAlgoName = "bi-decomp"; else if ( DecType == 3 ) pAlgoName = "DSD"; else if ( DecType == 4 ) pAlgoName = "fast DSD"; else if ( DecType == 5 ) pAlgoName = "analysis"; if ( pAlgoName ) printf( "Applying %-10s to %8d func%s of %2d vars... ", pAlgoName, p->nFuncs, (p->nFuncs == 1 ? "":"s"), p->nVars ); if ( fVerbose ) printf( "\n" ); if ( DecType == 1 ) { // perform algebraic factoring and count AIG nodes Dec_Graph_t * pFForm; Vec_Int_t * vCover; Vec_Str_t * vStr; char * pSopStr; vStr = Vec_StrAlloc( 10000 ); vCover = Vec_IntAlloc( 1 << 16 ); for ( i = 0; i < p->nFuncs; i++ ) { // extern int Abc_IsopTest( word * pFunc, int nVars, Vec_Int_t * vCover ); // if ( i == 0 ) printf( "\n" ); // Abc_IsopTest( p->pFuncs[i], p->nVars, vCover ); // continue; if ( fVerbose ) printf( "%7d : ", i ); pSopStr = Kit_PlaFromTruthNew( (unsigned *)p->pFuncs[i], p->nVars, vCover, vStr ); pFForm = Dec_Factor( pSopStr ); nNodes += Dec_GraphNodeNum( pFForm ); if ( fVerbose ) Dec_GraphPrint( stdout, pFForm, NULL, NULL ); Dec_GraphFree( pFForm ); } Vec_IntFree( vCover ); Vec_StrFree( vStr ); } else if ( DecType == 2 ) { // perform bi-decomposition and count AIG nodes Bdc_Man_t * pManDec; Bdc_Par_t Pars = {0}, * pPars = &Pars; pPars->nVarsMax = p->nVars; pManDec = Bdc_ManAlloc( pPars ); for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); Bdc_ManDecompose( pManDec, (unsigned *)p->pFuncs[i], NULL, p->nVars, NULL, 1000 ); nNodes += Bdc_ManAndNum( pManDec ); if ( fVerbose ) Bdc_ManDecPrint( pManDec ); } Bdc_ManFree( pManDec ); } else if ( DecType == 3 ) { // perform disjoint-support decomposition and count AIG nodes // (non-DSD blocks are decomposed into 2:1 MUXes, each counting as 3 AIG nodes) Kit_DsdNtk_t * pNtk; for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); pNtk = Kit_DsdDecomposeMux( (unsigned *)p->pFuncs[i], p->nVars, 3 ); if ( fVerbose ) Kit_DsdPrintExpanded( pNtk ), printf( "\n" ); nNodes += Kit_DsdCountAigNodes( pNtk ); Kit_DsdNtkFree( pNtk ); } } else if ( DecType == 4 ) { char pDsd[DAU_MAX_STR]; for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); Dau_DsdDecompose( p->pFuncs[i], p->nVars, 0, 1, pDsd ); if ( fVerbose ) printf( "%s\n", pDsd ); nNodes += Dau_DsdCountAnds( pDsd ); } } else if ( DecType == 5 ) { for ( i = 0; i < p->nFuncs; i++ ) { extern void Dau_DecTrySets( word * pInit, int nVars, int fVerbose ); int nSuppSize = Abc_TtSupportSize( p->pFuncs[i], p->nVars ); if ( fVerbose ) printf( "%7d : ", i ); Dau_DecTrySets( p->pFuncs[i], nSuppSize, fVerbose ); if ( fVerbose ) printf( "\n" ); } } else assert( 0 ); printf( "AIG nodes =%9d ", nNodes ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Apply decomposition to truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthDecTest( char * pFileName, int DecType, int nVarNum, int fVerbose ) { Abc_TtStore_t * p; // allocate data-structure p = Abc_TtStoreLoad( pFileName, nVarNum ); if ( p == NULL ) return; // consider functions from the file Abc_TruthDecPerform( p, DecType, fVerbose ); // delete data-structure Abc_TtStoreFree( p, nVarNum ); // printf( "Finished decomposing truth tables from file \"%s\".\n", pFileName ); } /**Function************************************************************* Synopsis [Testbench for decomposition algorithms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_DecTest( char * pFileName, int DecType, int nVarNum, int fVerbose ) { if ( fVerbose ) printf( "Using truth tables from file \"%s\"...\n", pFileName ); if ( DecType == 0 ) { if ( nVarNum < 0 ) Abc_TtStoreTest( pFileName ); } else if ( DecType >= 1 && DecType <= 5 ) Abc_TruthDecTest( pFileName, DecType, nVarNum, fVerbose ); else printf( "Unknown decomposition type value (%d).\n", DecType ); fflush( stdout ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDetect.c000066400000000000000000000156601300674244400236760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDetect.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Detect conditions.] Author [Alan Mishchenko, Dao Ai Quoc] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 7, 2016.] Revision [$Id: abcDetect.c,v 1.00 2016/06/07 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "misc/vec/vecHsh.h" #include "misc/util/utilNam.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef enum { ABC_FIN_NONE = 0, // 0: unknown ABC_FIN_SA0, // 1: ABC_FIN_SA1, // 2: ABC_FIN_NEG, // 3: ABC_FIN_RDOB_AND, // 4: ABC_FIN_RDOB_NAND, // 5: ABC_FIN_RDOB_OR, // 6: ABC_FIN_RDOB_NOR, // 7: ABC_FIN_RDOB_XOR, // 8: ABC_FIN_RDOB_NXOR, // 9: ABC_FIN_RDOB_NOT, // 10: ABC_FIN_RDOB_BUFF, // 11: ABC_FIN_RDOB_LAST // 12: } Abc_FinType_t; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Recognize type.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadFinType( char * pThis ) { if ( !strcmp(pThis, "SA0") ) return ABC_FIN_SA0; if ( !strcmp(pThis, "SA1") ) return ABC_FIN_SA1; if ( !strcmp(pThis, "NEG") ) return ABC_FIN_NEG; if ( !strcmp(pThis, "RDOB_AND") ) return ABC_FIN_RDOB_AND; if ( !strcmp(pThis, "RDOB_NAND") ) return ABC_FIN_RDOB_NAND; if ( !strcmp(pThis, "RDOB_OR") ) return ABC_FIN_RDOB_OR; if ( !strcmp(pThis, "RDOB_NOR") ) return ABC_FIN_RDOB_NOR; if ( !strcmp(pThis, "RDOB_XOR") ) return ABC_FIN_RDOB_XOR; if ( !strcmp(pThis, "RDOB_NXOR") ) return ABC_FIN_RDOB_NXOR; if ( !strcmp(pThis, "RDOB_NOT") ) return ABC_FIN_RDOB_NOT; if ( !strcmp(pThis, "RDOB_BUFF") ) return ABC_FIN_RDOB_BUFF; return ABC_FIN_NONE; } char * Io_WriteFinType( int Type ) { if ( Type == ABC_FIN_SA0 ) return "SA0"; if ( Type == ABC_FIN_SA1 ) return "SA1"; if ( Type == ABC_FIN_NEG ) return "NEG"; if ( Type == ABC_FIN_RDOB_AND ) return "RDOB_AND" ; if ( Type == ABC_FIN_RDOB_NAND ) return "RDOB_NAND"; if ( Type == ABC_FIN_RDOB_OR ) return "RDOB_OR" ; if ( Type == ABC_FIN_RDOB_NOR ) return "RDOB_NOR" ; if ( Type == ABC_FIN_RDOB_XOR ) return "RDOB_XOR" ; if ( Type == ABC_FIN_RDOB_NXOR ) return "RDOB_NXOR"; if ( Type == ABC_FIN_RDOB_NOT ) return "RDOB_NOT" ; if ( Type == ABC_FIN_RDOB_BUFF ) return "RDOB_BUFF"; return "Unknown"; } /**Function************************************************************* Synopsis [Read information from file.] Description [Returns information as a set of pairs: (ObjId, TypeId). Uses the current network to map ObjName given in the file into ObjId.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Io_ReadFins( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ) { char Buffer[1000]; Abc_Obj_t * pObj; Abc_Nam_t * pNam; Vec_Int_t * vMap; Vec_Int_t * vPairs = NULL; int i, Type, iObj, fFound, nLines = 1; FILE * pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\" for reading.\n", pFileName ); return NULL; } // map CI/node names into their IDs pNam = Abc_NamStart( 1000, 10 ); vMap = Vec_IntAlloc( 1000 ); Vec_IntPush( vMap, -1 ); Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj) ) continue; Abc_NamStrFindOrAdd( pNam, Abc_ObjName(pObj), &fFound ); if ( fFound ) { printf( "The same name \"%s\" appears twice among CIs and internal nodes.\n", Abc_ObjName(pObj) ); goto finish; } Vec_IntPush( vMap, Abc_ObjId(pObj) ); } assert( Vec_IntSize(vMap) == Abc_NamObjNumMax(pNam) ); // read file lines vPairs = Vec_IntAlloc( 1000 ); Vec_IntPushTwo( vPairs, -1, -1 ); while ( fgets(Buffer, 1000, pFile) != NULL ) { // read line number char * pToken = strtok( Buffer, " \n\r\t" ); if ( nLines++ != atoi(pToken) ) { printf( "Line numbers are not consecutive. Quitting.\n" ); Vec_IntFreeP( &vPairs ); goto finish; } // read object name and find its ID pToken = strtok( NULL, " \n\r\t" ); iObj = Abc_NamStrFind( pNam, pToken ); if ( !iObj ) { printf( "Cannot find object with name \"%s\".\n", pToken ); continue; } // read type pToken = strtok( NULL, " \n\r\t" ); Type = Io_ReadFinType( pToken ); if ( Type == ABC_FIN_NONE ) { printf( "Cannot read type \"%s\" of object \"%s\".\n", pToken, Abc_ObjName(Abc_NtkObj(pNtk, iObj)) ); continue; } Vec_IntPushTwo( vPairs, Vec_IntEntry(vMap, iObj), Type ); } assert( Vec_IntSize(vPairs) == 2 * nLines ); printf( "Finished reading %d lines.\n", nLines - 1 ); // verify the reader by printing the results if ( fVerbose ) Vec_IntForEachEntryDoubleStart( vPairs, iObj, Type, i, 2 ) printf( "%-10d%-10s%-10s\n", i/2, Abc_ObjName(Abc_NtkObj(pNtk, iObj)), Io_WriteFinType(Type) ); finish: Vec_IntFree( vMap ); Abc_NamDeref( pNam ); fclose( pFile ); return vPairs; } /**Function************************************************************* Synopsis [Top-level procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose ) { printf( "This procedure is currently not used.\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDress.c000066400000000000000000000160041300674244400235370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDress.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Transfers names from one netlist to the other.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDress.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk ); static void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose ); extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transfers names from one netlist to the other.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDress( Abc_Ntk_t * pNtkLogic, char * pFileName, int fVerbose ) { Abc_Ntk_t * pNtkOrig, * pNtkLogicOrig; Abc_Ntk_t * pMiter, * pMiterFraig; stmm_table * tMapping; assert( Abc_NtkIsLogic(pNtkLogic) ); // get the original netlist pNtkOrig = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 1 ); if ( pNtkOrig == NULL ) return; assert( Abc_NtkIsNetlist(pNtkOrig) ); Abc_NtkCleanCopy(pNtkLogic); Abc_NtkCleanCopy(pNtkOrig); // convert it into the logic network pNtkLogicOrig = Abc_NtkToLogic( pNtkOrig ); // check that the networks have the same PIs/POs/latches if ( !Abc_NtkCompareSignals( pNtkLogic, pNtkLogicOrig, 1, 1 ) ) { Abc_NtkDelete( pNtkOrig ); Abc_NtkDelete( pNtkLogicOrig ); return; } // convert the current logic network into an AIG pMiter = Abc_NtkStrash( pNtkLogic, 1, 0, 0 ); // convert it into the AIG and make the netlist point to the AIG Abc_NtkAppend( pMiter, pNtkLogicOrig, 1 ); Abc_NtkTransferCopy( pNtkOrig ); Abc_NtkDelete( pNtkLogicOrig ); if ( fVerbose ) { printf( "After mitering:\n" ); printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); } // fraig the miter (miter nodes point to the fraiged miter) pMiterFraig = Abc_NtkIvyFraig( pMiter, 100, 1, 0, 1, 0 ); // make netlists point to the fraiged miter Abc_NtkTransferCopy( pNtkLogic ); Abc_NtkTransferCopy( pNtkOrig ); Abc_NtkDelete( pMiter ); if ( fVerbose ) { printf( "After fraiging:\n" ); printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); } // derive mapping from the fraiged nodes into their prototype nodes in the original netlist tMapping = Abc_NtkDressDeriveMapping( pNtkOrig ); // transfer the names to the new netlist Abc_NtkDressTransferNames( pNtkLogic, tMapping, fVerbose ); // clean up stmm_free_table( tMapping ); Abc_NtkDelete( pMiterFraig ); Abc_NtkDelete( pNtkOrig ); } /**Function************************************************************* Synopsis [Returns the mapping from the fraig nodes point into the nodes of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk ) { stmm_table * tResult; Abc_Obj_t * pNode, * pNodeMap, * pNodeFraig; int i; assert( Abc_NtkIsNetlist(pNtk) ); tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); Abc_NtkForEachNode( pNtk, pNode, i ) { // get the fraiged node pNodeFraig = Abc_ObjRegular(pNode->pCopy); // if this node is already mapped, skip if ( stmm_is_member( tResult, (char *)pNodeFraig ) ) continue; // get the mapping of this node pNodeMap = Abc_ObjNotCond( pNode, Abc_ObjIsComplement(pNode->pCopy) ); // add the mapping stmm_insert( tResult, (char *)pNodeFraig, (char *)pNodeMap ); } return tResult; } /**Function************************************************************* Synopsis [Attaches the names of to the new netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose ) { Abc_Obj_t * pNet, * pNode, * pNodeMap, * pNodeFraig; char * pName; int i, Counter = 0, CounterInv = 0, CounterInit = stmm_count(tMapping); assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { // if the node already has a name, quit pName = Nm_ManFindNameById( pNtk->pManName, pNode->Id ); if ( pName != NULL ) continue; // get the fraiged node pNodeFraig = Abc_ObjRegular(pNode->pCopy); // find the matching node of the original netlist if ( !stmm_lookup( tMapping, (char *)pNodeFraig, (char **)&pNodeMap ) ) continue; // find the true match pNodeMap = Abc_ObjNotCond( pNodeMap, Abc_ObjIsComplement(pNode->pCopy) ); // get the name pNet = Abc_ObjFanout0(Abc_ObjRegular(pNodeMap)); pName = Nm_ManFindNameById( pNet->pNtk->pManName, pNet->Id ); assert( pName != NULL ); // set the name if ( Abc_ObjIsComplement(pNodeMap) ) { Abc_ObjAssignName( pNode, pName, "_inv" ); CounterInv++; } else { Abc_ObjAssignName( pNode, pName, NULL ); Counter++; } // remove the name stmm_delete( tMapping, (char **)&pNodeFraig, (char **)&pNodeMap ); } if ( fVerbose ) { printf( "Total number of names collected = %5d.\n", CounterInit ); printf( "Total number of names assigned = %5d. (Dir = %5d. Compl = %5d.)\n", Counter + CounterInv, Counter, CounterInv ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDress2.c000066400000000000000000000445451300674244400236340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDressw.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Transfers names from one netlist to the other.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDressw.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/aig/aig.h" #include "proof/dch/dch.h" ABC_NAMESPACE_IMPL_START /* Procedure Abc_NtkDressComputeEquivs() implemented in this file computes equivalence classes of objects of the two networks (pNtk1 and pNtk2). It is possible that pNtk1 is the network before synthesis and pNtk2 is the network after synthesis. The equiv classes of nodes from these networks can be used to transfer the names from pNtk1 to pNtk2, or vice versa. The above procedure returns the array (Vec_Ptr_t) of integer arrays (Vec_Int_t). Each of the integer arrays contains entries of one equivalence class. Each entry (EquivId) contains the following information: (1) object ID, which is a number 'num', such that 0 <= 'num' < MaxId where MaxId is the largest ID of nodes in a network (2) the polarity of the node, which is a binary number, 0 or 1, giving the node's value when pattern (000...0) is applied to the inputs (3) the number of the network, 0 or 1, which stands for pNtk1 and pNtk2, respectively The first array in the array of arrays is empty, or contains nodes that are equivalent to a constant (if such nodes appear in the network). Given EquivID defined above, use the APIs below to get its components. */ // declarations to be added to the application code extern int Abc_ObjEquivId2ObjId( int EquivId ); extern int Abc_ObjEquivId2Polar( int EquivId ); extern int Abc_ObjEquivId2NtkId( int EquivId ); // definition that may remain in this file int Abc_ObjEquivId2ObjId( int EquivId ) { return EquivId >> 2; } int Abc_ObjEquivId2Polar( int EquivId ) { return (EquivId >> 1) & 1; } int Abc_ObjEquivId2NtkId( int EquivId ) { return EquivId & 1; } //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the dual-output miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManCreateDualOutputMiter( Aig_Man_t * p1, Aig_Man_t * p2 ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( Aig_ManCiNum(p1) == Aig_ManCiNum(p2) ); assert( Aig_ManCoNum(p1) == Aig_ManCoNum(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 outputs for ( i = 0; i < Aig_ManCoNum(p1); i++ ) { Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1, i)) ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(Aig_ManCo(p2, i)) ); } Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Sets polarity attribute of each object in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDressMapSetPolarity( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pAnd; int i; // each node refers to the the strash copy whose polarity is set Abc_NtkForEachObj( pNtk, pObj, i ) { if ( (pAnd = Abc_ObjRegular(pObj->pCopy)) && Abc_ObjType(pAnd) != ABC_OBJ_NONE ) // strashed object is present and legal pObj->fPhase = pAnd->fPhase ^ Abc_ObjIsComplement(pObj->pCopy); } } /**Function************************************************************* Synopsis [Create mapping of node IDs of pNtk into equiv classes of pMiter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkDressMapClasses( Aig_Man_t * pMiter, Abc_Ntk_t * pNtk ) { Vec_Int_t * vId2Lit; Abc_Obj_t * pObj, * pAnd; Aig_Obj_t * pObjMan, * pObjMiter, * pObjRepr; int i; vId2Lit = Vec_IntAlloc( 0 ); Vec_IntFill( vId2Lit, Abc_NtkObjNumMax(pNtk), -1 ); Abc_NtkForEachNode( pNtk, pObj, i ) { // get the pointer to the miter node corresponding to pObj if ( (pAnd = Abc_ObjRegular(pObj->pCopy)) && Abc_ObjType(pAnd) != ABC_OBJ_NONE && // strashed node is present and legal (pObjMan = Aig_Regular((Aig_Obj_t *)pAnd->pCopy)) && Aig_ObjType(pObjMan) != AIG_OBJ_NONE && // AIG node is present and legal (pObjMiter = Aig_Regular((Aig_Obj_t *)pObjMan->pData)) && Aig_ObjType(pObjMiter) != AIG_OBJ_NONE ) // miter node is present and legal { // get the representative of the miter node pObjRepr = Aig_ObjRepr( pMiter, pObjMiter ); pObjRepr = pObjRepr? pObjRepr : pObjMiter; // map pObj (whose ID is i) into the repr node ID (i.e. equiv class) Vec_IntWriteEntry( vId2Lit, i, Aig_ObjId(pObjRepr) ); } } return vId2Lit; } /**Function************************************************************* Synopsis [Returns the vector of given equivalence class of objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_ObjDressClass( Vec_Ptr_t * vRes, Vec_Int_t * vClass2Num, int Class ) { int ClassNumber; assert( Class > 0 ); ClassNumber = Vec_IntEntry( vClass2Num, Class ); assert( ClassNumber != 0 ); if ( ClassNumber > 0 ) return (Vec_Int_t *)Vec_PtrEntry( vRes, ClassNumber ); // previous class // create new class Vec_IntWriteEntry( vClass2Num, Class, Vec_PtrSize(vRes) ); Vec_PtrPush( vRes, Vec_IntAlloc(4) ); return (Vec_Int_t *)Vec_PtrEntryLast( vRes ); } /**Function************************************************************* Synopsis [Returns the ID of a node in an equivalence class.] Description [The ID is composed of three parts: object ID, followed by one bit telling the phase of this node, followed by one bit telling the network to which this node belongs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjDressMakeId( Abc_Ntk_t * pNtk, int ObjId, int iNtk ) { return (ObjId << 2) | (Abc_NtkObj(pNtk,ObjId)->fPhase << 1) | iNtk; } /**Function************************************************************* Synopsis [Computes equivalence classes of objects in pNtk1 and pNtk2.] Description [Internal procedure.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDressMapIds( Aig_Man_t * pMiter, Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) { Vec_Ptr_t * vRes; Vec_Int_t * vId2Lit1, * vId2Lit2, * vCounts0, * vCounts1, * vClassC, * vClass2Num; int i, Class; // start the classes vRes = Vec_PtrAlloc( 1000 ); // set polarity of the nodes Abc_NtkDressMapSetPolarity( pNtk1 ); Abc_NtkDressMapSetPolarity( pNtk2 ); // create mapping of node IDs of pNtk1/pNtk2 into the IDs of equiv classes of pMiter vId2Lit1 = Abc_NtkDressMapClasses( pMiter, pNtk1 ); vId2Lit2 = Abc_NtkDressMapClasses( pMiter, pNtk2 ); // count the number of nodes in each equivalence class vCounts0 = Vec_IntStart( Aig_ManObjNumMax(pMiter) ); Vec_IntForEachEntry( vId2Lit1, Class, i ) if ( Class >= 0 ) Vec_IntAddToEntry( vCounts0, Class, 1 ); vCounts1 = Vec_IntStart( Aig_ManObjNumMax(pMiter) ); Vec_IntForEachEntry( vId2Lit2, Class, i ) if ( Class >= 0 ) Vec_IntAddToEntry( vCounts1, Class, 1 ); // get the costant class vClassC = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vId2Lit1, Class, i ) if ( Class == 0 ) Vec_IntPush( vClassC, Abc_ObjDressMakeId(pNtk1, i, 0) ); Vec_IntForEachEntry( vId2Lit2, Class, i ) if ( Class == 0 ) Vec_IntPush( vClassC, Abc_ObjDressMakeId(pNtk2, i, 1) ); Vec_PtrPush( vRes, vClassC ); // map repr node IDs into class numbers vClass2Num = Vec_IntAlloc( 0 ); Vec_IntFill( vClass2Num, Aig_ManObjNumMax(pMiter), -1 ); // keep classes having at least one element from pNtk1 and one from pNtk2 Vec_IntForEachEntry( vId2Lit1, Class, i ) if ( Class > 0 && Vec_IntEntry(vCounts0, Class) && Vec_IntEntry(vCounts1, Class) ) Vec_IntPush( Abc_ObjDressClass(vRes, vClass2Num, Class), Abc_ObjDressMakeId(pNtk1, i, 0) ); Vec_IntForEachEntry( vId2Lit2, Class, i ) if ( Class > 0 && Vec_IntEntry(vCounts0, Class) && Vec_IntEntry(vCounts1, Class) ) Vec_IntPush( Abc_ObjDressClass(vRes, vClass2Num, Class), Abc_ObjDressMakeId(pNtk2, i, 1) ); // package them accordingly Vec_IntFree( vClass2Num ); Vec_IntFree( vCounts0 ); Vec_IntFree( vCounts1 ); Vec_IntFree( vId2Lit1 ); Vec_IntFree( vId2Lit2 ); return vRes; } /**Function************************************************************* Synopsis [Computes equivalence classes of objects in pNtk1 and pNtk2.] Description [Returns the array (Vec_Ptr_t) of integer arrays (Vec_Int_t). Each of the integer arrays contains entries of one equivalence class. Each entry contains the following information: the network number (0/1), the polarity (0/1) and the object ID in the the network (0 <= num < MaxId) where MaxId is the largest number of an ID of an object in that network.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDressComputeEquivs( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose ) { Dch_Pars_t Pars, * pPars = &Pars; Abc_Ntk_t * pAig1, * pAig2; Aig_Man_t * pMan1, * pMan2, * pMiter; Vec_Ptr_t * vRes; assert( !Abc_NtkIsStrash(pNtk1) ); assert( !Abc_NtkIsStrash(pNtk2) ); // convert network into AIG pAig1 = Abc_NtkStrash( pNtk1, 1, 1, 0 ); pAig2 = Abc_NtkStrash( pNtk2, 1, 1, 0 ); pMan1 = Abc_NtkToDar( pAig1, 0, 0 ); pMan2 = Abc_NtkToDar( pAig2, 0, 0 ); // derive the miter pMiter = Aig_ManCreateDualOutputMiter( pMan1, pMan2 ); // set up parameters for SAT sweeping Dch_ManSetDefaultParams( pPars ); pPars->nBTLimit = nConflictLimit; pPars->fVerbose = fVerbose; // perform SAT sweeping Dch_ComputeEquivalences( pMiter, pPars ); // now, pMiter is annotated with the equivl class info // convert this info into the resulting array vRes = Abc_NtkDressMapIds( pMiter, pNtk1, pNtk2 ); Aig_ManStop( pMiter ); Aig_ManStop( pMan1 ); Aig_ManStop( pMan2 ); Abc_NtkDelete( pAig1 ); Abc_NtkDelete( pAig2 ); return vRes; } /**Function************************************************************* Synopsis [Prints information about node equivalences.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDressPrintEquivs( Vec_Ptr_t * vRes ) { Vec_Int_t * vClass; int i, k, Entry; Vec_PtrForEachEntry( Vec_Int_t *, vRes, vClass, i ) { printf( "Class %5d : ", i ); printf( "Num =%5d ", Vec_IntSize(vClass) ); Vec_IntForEachEntry( vClass, Entry, k ) printf( "%5d%c%d ", Abc_ObjEquivId2ObjId(Entry), Abc_ObjEquivId2Polar(Entry)? '-':'+', Abc_ObjEquivId2NtkId(Entry) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Prints information about node equivalences.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDressPrintStats( Vec_Ptr_t * vRes, int nNodes0, int nNodes1, abctime Time ) { Vec_Int_t * vClass; int i, k, Entry; int NegAll[2] = {0}, PosAll[2] = {0}, PairsAll = 0, PairsOne = 0; int Pos[2], Neg[2]; // count the number of equivalences in each class Vec_PtrForEachEntry( Vec_Int_t *, vRes, vClass, i ) { Pos[0] = Pos[1] = 0; Neg[0] = Neg[1] = 0; Vec_IntForEachEntry( vClass, Entry, k ) { if ( Abc_ObjEquivId2NtkId(Entry) ) { if ( Abc_ObjEquivId2Polar(Entry) ) Neg[1]++; // negative polarity in network 1 else Pos[1]++; // positive polarity in network 1 } else { if ( Abc_ObjEquivId2Polar(Entry) ) Neg[0]++; // negative polarity in network 0 else Pos[0]++; // positive polarity in network 0 } } PosAll[0] += Pos[0]; // total positive polarity in network 0 PosAll[1] += Pos[1]; // total positive polarity in network 1 NegAll[0] += Neg[0]; // total negative polarity in network 0 NegAll[1] += Neg[1]; // total negative polarity in network 1 // assuming that the name can be transferred to only one node PairsAll += Abc_MinInt(Neg[0] + Pos[0], Neg[1] + Pos[1]); PairsOne += Abc_MinInt(Neg[0], Neg[1]) + Abc_MinInt(Pos[0], Pos[1]); } printf( "Total number of equiv classes = %7d.\n", Vec_PtrSize(vRes) ); printf( "Participating nodes from both networks = %7d.\n", NegAll[0]+PosAll[0]+NegAll[1]+PosAll[1] ); printf( "Participating nodes from the first network = %7d. (%7.2f %% of nodes)\n", NegAll[0]+PosAll[0], 100.0*(NegAll[0]+PosAll[0])/(nNodes0+1) ); printf( "Participating nodes from the second network = %7d. (%7.2f %% of nodes)\n", NegAll[1]+PosAll[1], 100.0*(NegAll[1]+PosAll[1])/(nNodes1+1) ); printf( "Node pairs (any polarity) = %7d. (%7.2f %% of names can be moved)\n", PairsAll, 100.0*PairsAll/(nNodes0+1) ); printf( "Node pairs (same polarity) = %7d. (%7.2f %% of names can be moved)\n", PairsOne, 100.0*PairsOne/(nNodes0+1) ); ABC_PRT( "Total runtime", Time ); } /**Function************************************************************* Synopsis [Transfers IDs from pNtk1 to pNtk2 using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDress2Transfer( Abc_Ntk_t * pNtk0, Abc_Ntk_t * pNtk1, Vec_Ptr_t * vRes, int fVerbose ) { Vec_Int_t * vClass; Abc_Obj_t * pObj0, * pObj1; int i, k, fComp0, fComp1, Entry; int CounterInv = 0, Counter = 0; char * pName; Vec_PtrForEachEntry( Vec_Int_t *, vRes, vClass, i ) { pObj0 = pObj1 = NULL; fComp0 = fComp1 = 0; Vec_IntForEachEntry( vClass, Entry, k ) { if ( Abc_ObjEquivId2NtkId(Entry) ) { pObj1 = Abc_NtkObj( pNtk1, Abc_ObjEquivId2ObjId(Entry) ); fComp1 = Abc_ObjEquivId2Polar(Entry); } else { pObj0 = Abc_NtkObj( pNtk0, Abc_ObjEquivId2ObjId(Entry) ); fComp0 = Abc_ObjEquivId2Polar(Entry); } } if ( pObj0 == NULL || pObj1 == NULL ) continue; // if the node already has a name, quit pName = Nm_ManFindNameById( pNtk0->pManName, pObj0->Id ); if ( pName != NULL ) continue; // if the other node has no name, quit pName = Nm_ManFindNameById( pNtk1->pManName, pObj1->Id ); if ( pName == NULL ) continue; // assign name if ( fComp0 ^ fComp1 ) { Abc_ObjAssignName( pObj0, pName, "_inv" ); CounterInv++; } else { Abc_ObjAssignName( pObj0, pName, NULL ); Counter++; } } if ( fVerbose ) { printf( "Total number of names assigned = %5d. (Dir = %5d. Compl = %5d.)\n", Counter + CounterInv, Counter, CounterInv ); } } /**Function************************************************************* Synopsis [Transfers names from pNtk1 to pNtk2.] Description [Internally calls new procedure for mapping node IDs of both networks into the shared equivalence classes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDress2( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose ) { Vec_Ptr_t * vRes; abctime clk = Abc_Clock(); vRes = Abc_NtkDressComputeEquivs( pNtk1, pNtk2, nConflictLimit, fVerbose ); // Abc_NtkDressPrintEquivs( vRes ); Abc_NtkDressPrintStats( vRes, Abc_NtkNodeNum(pNtk1), Abc_NtkNodeNum(pNtk1), Abc_Clock() - clk ); Abc_NtkDress2Transfer( pNtk1, pNtk2, vRes, fVerbose ); Vec_VecFree( (Vec_Vec_t *)vRes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDress3.c000066400000000000000000000312311300674244400236210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDress3.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Transfers names from one netlist to the other.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDress3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/io/ioAbc.h" #include "proof/cec/cec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Compute equivalence classes of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkComputeGiaEquivs( Gia_Man_t * pGia, int nConfs, int fVerbose ) { Gia_Man_t * pTemp; Cec_ParFra_t ParsFra, * pPars = &ParsFra; Cec_ManFraSetDefaultParams( pPars ); pPars->fUseOrigIds = 1; pPars->fSatSweeping = 1; pPars->nBTLimit = nConfs; pPars->fVerbose = fVerbose; pTemp = Cec_ManSatSweeping( pGia, pPars, 0 ); Gia_ManStop( pTemp ); pTemp = Gia_ManOrigIdsReduce( pGia, pGia->vIdsEquiv ); Gia_ManStop( pTemp ); } /**Function************************************************************* Synopsis [Converts AIG from HOP to GIA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ConvertHopToGia_rec1( Gia_Man_t * p, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Abc_ConvertHopToGia_rec1( p, Hop_ObjFanin0(pObj) ); Abc_ConvertHopToGia_rec1( p, Hop_ObjFanin1(pObj) ); pObj->iData = Gia_ManHashAnd( p, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } void Abc_ConvertHopToGia_rec2( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) return; Abc_ConvertHopToGia_rec2( Hop_ObjFanin0(pObj) ); Abc_ConvertHopToGia_rec2( Hop_ObjFanin1(pObj) ); assert( Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjClearMarkA( pObj ); } int Abc_ConvertHopToGia( Gia_Man_t * p, Hop_Obj_t * pRoot ) { assert( !Hop_IsComplement(pRoot) ); if ( Hop_ObjIsConst1( pRoot ) ) return 1; Abc_ConvertHopToGia_rec1( p, pRoot ); Abc_ConvertHopToGia_rec2( pRoot ); return pRoot->iData; } /**Function************************************************************* Synopsis [Add logic from pNtk to the AIG manager p.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAigToGiaOne( Gia_Man_t * p, Abc_Ntk_t * pNtk, Vec_Int_t * vMap ) { Hop_Man_t * pHopMan; Hop_Obj_t * pHopObj; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin; int i, k; assert( Abc_NtkIsAigLogic(pNtk) ); pHopMan = (Hop_Man_t *)pNtk->pManFunc; Hop_ManConst1(pHopMan)->iData = 1; // image primary inputs Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachCi( pNtk, pNode, i ) pNode->iTemp = Gia_ManCiLit(p, Vec_IntEntry(vMap, i)); // iterate through nodes used in the mapping vNodes = Abc_NtkDfs( pNtk, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { Abc_ObjForEachFanin( pNode, pFanin, k ) Hop_ManPi(pHopMan, k)->iData = pFanin->iTemp; pHopObj = Hop_Regular( (Hop_Obj_t *)pNode->pData ); assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) ); if ( Hop_DagSize(pHopObj) > 0 ) Abc_ConvertHopToGia( p, pHopObj ); pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) ); } Vec_PtrFree( vNodes ); // create primary outputs Abc_NtkForEachCo( pNtk, pNode, i ) Gia_ManAppendCo( p, Abc_ObjFanin0(pNode)->iTemp ); } Gia_Man_t * Abc_NtkAigToGiaTwo( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fByName ) { Gia_Man_t * p; Gia_Obj_t * pObj; Abc_Obj_t * pNode; Vec_Int_t * vMap1, * vMap2; int i, Index = 0; assert( Abc_NtkIsAigLogic(pNtk1) ); assert( Abc_NtkIsAigLogic(pNtk2) ); // find common variables if ( fByName ) { int nCommon = 0; vMap1 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk1) ); vMap2 = Vec_IntAlloc( Abc_NtkCiNum(pNtk2) ); Abc_NtkForEachCi( pNtk1, pNode, i ) pNode->iTemp = Index++; assert( Index == Abc_NtkCiNum(pNtk1) ); Abc_NtkForEachCi( pNtk2, pNode, i ) { int Num = Nm_ManFindIdByName( pNtk1->pManName, Abc_ObjName(pNode), ABC_OBJ_PI ); if ( Num < 0 ) Num = Nm_ManFindIdByName( pNtk1->pManName, Abc_ObjName(pNode), ABC_OBJ_BO ); assert( Num < 0 || Abc_ObjIsCi(Abc_NtkObj(pNtk1, Num)) ); if ( Num >= 0 ) Vec_IntPush( vMap2, Abc_NtkObj(pNtk1, Num)->iTemp ), nCommon++; else Vec_IntPush( vMap2, Index++ ); } // report printf( "Matched %d vars by name.", nCommon ); if ( nCommon != Abc_NtkCiNum(pNtk1) ) printf( " Netlist1 has %d unmatched vars.", Abc_NtkCiNum(pNtk1) - nCommon ); if ( nCommon != Abc_NtkCiNum(pNtk2) ) printf( " Netlist2 has %d unmatched vars.", Abc_NtkCiNum(pNtk2) - nCommon ); printf( "\n" ); } else { vMap1 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk1) ); vMap2 = Vec_IntStartNatural( Abc_NtkCiNum(pNtk2) ); Index = Abc_MaxInt( Vec_IntSize(vMap1), Vec_IntSize(vMap2) ); // report printf( "Matched %d vars by order.", Abc_MinInt(Abc_NtkCiNum(pNtk1), Abc_NtkCiNum(pNtk2)) ); if ( Abc_NtkCiNum(pNtk1) < Abc_NtkCiNum(pNtk2) ) printf( " The last %d vars of Netlist2 are unmatched vars.", Abc_NtkCiNum(pNtk2) - Abc_NtkCiNum(pNtk1) ); if ( Abc_NtkCiNum(pNtk1) > Abc_NtkCiNum(pNtk2) ) printf( " The last %d vars of Netlist1 are unmatched vars.", Abc_NtkCiNum(pNtk1) - Abc_NtkCiNum(pNtk2) ); printf( "\n" ); } // create new manager p = Gia_ManStart( 10000 ); p->pName = Abc_UtilStrsav( Abc_NtkName(pNtk1) ); p->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk1) ); for ( i = 0; i < Index; i++ ) Gia_ManAppendCi(p); // add logic Gia_ManHashAlloc( p ); Abc_NtkAigToGiaOne( p, pNtk1, vMap1 ); Abc_NtkAigToGiaOne( p, pNtk2, vMap2 ); Gia_ManHashStop( p ); Vec_IntFree( vMap1 ); Vec_IntFree( vMap2 ); // add extra POs to dangling nodes Gia_ManCreateValueRefs( p ); Gia_ManForEachAnd( p, pObj, i ) if ( pObj->Value == 0 ) Gia_ManAppendCo( p, Abc_Var2Lit(i, 0) ); return p; } /**Function************************************************************* Synopsis [Collect equivalence class information.] Description [Each class is represented as follows: ... where is nodeId with 1-bit for complement and 1-bit for network.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_NtkCollectAddOne( int iNtk, int iObj, int iGiaLit, Gia_Man_t * pGia, Vec_Int_t * vGia2Cla, Vec_Int_t * vNexts[2] ) { int iRepr = Gia_ObjReprSelf( pGia, Abc_Lit2Var(iGiaLit) ); int Compl = Abc_LitIsCompl(iGiaLit) ^ Gia_ObjPhase(Gia_ManObj(pGia, iRepr)) ^ Gia_ObjPhase(Gia_ManObj(pGia, Abc_Lit2Var(iGiaLit))); int Added = Abc_Var2Lit( Abc_Var2Lit(iObj, Compl), iNtk ); int Entry = Vec_IntEntry( vGia2Cla, iRepr ); Vec_IntWriteEntry( vNexts[iNtk], iObj, Entry ); Vec_IntWriteEntry( vGia2Cla, iRepr, Added ); } Vec_Int_t * Abc_NtkCollectEquivClasses( Abc_Ntk_t * pNtks[2], Gia_Man_t * pGia ) { Vec_Int_t * vClass = Vec_IntAlloc( 100 ); Vec_Int_t * vClasses = Vec_IntAlloc( 1000 ); Vec_Int_t * vGia2Cla = Vec_IntStartFull( Gia_ManObjNum(pGia) ); // mapping objId into classId Vec_Int_t * vNexts[2] = { Vec_IntStartFull(Abc_NtkObjNumMax(pNtks[0])), Vec_IntStartFull(Abc_NtkObjNumMax(pNtks[1])) }; Abc_Obj_t * pObj; int n, i, k, Entry, fCompl; Abc_NtkForEachCi( pNtks[0], pObj, i ) Abc_NtkCollectAddOne( 0, Abc_ObjId(pObj), pObj->iTemp, pGia, vGia2Cla, vNexts ); for ( n = 0; n < 2; n++ ) Abc_NtkForEachNode( pNtks[n], pObj, i ) Abc_NtkCollectAddOne( n, Abc_ObjId(pObj), pObj->iTemp, pGia, vGia2Cla, vNexts ); Vec_IntForEachEntry( vGia2Cla, Entry, i ) { Vec_IntClear( vClass ); for ( ; Entry >= 0; Entry = Vec_IntEntry(vNexts[Entry&1], Entry>>2) ) Vec_IntPush( vClass, Entry ); if ( Vec_IntSize(vClass) < 2 ) continue; Vec_IntReverseOrder( vClass ); fCompl = 2 & Vec_IntEntry( vClass, 0 ); Vec_IntForEachEntry( vClass, Entry, k ) Vec_IntWriteEntry( vClass, k, Entry ^ fCompl ); Vec_IntPush( vClasses, Vec_IntSize(vClass) ); Vec_IntAppend( vClasses, vClass ); } Vec_IntFree( vGia2Cla ); Vec_IntFree( vNexts[0] ); Vec_IntFree( vNexts[1] ); Vec_IntFree( vClass ); return vClasses; } /**Function************************************************************* Synopsis [Write the output file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDumpEquivFile( char * pFileName, Vec_Int_t * vClasses, Abc_Ntk_t * pNtks[2] ) { int i, c, k, Entry; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file %s for writing.\n", pFileName ); return; } fprintf( pFile, "# Node equivalences computed by ABC for networks \"%s\" and \"%s\" on %s\n\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]), Extra_TimeStamp() ); for ( i = c = 0; i < Vec_IntSize(vClasses); c++, i += 1 + Vec_IntEntry(vClasses, i) ) { Vec_IntForEachEntryStartStop( vClasses, Entry, k, i + 1, i + 1 + Vec_IntEntry(vClasses, i) ) { Abc_Ntk_t * pNtk = pNtks[Entry & 1]; char * pObjName = Abc_ObjName( Abc_NtkObj(pNtk, Entry>>2) ); fprintf( pFile, "%d:%s:%s%s\n", c+1, Abc_NtkName(pNtk), (Entry&2) ? "NOT:":"", pObjName ); } fprintf( pFile, "\n" ); } fclose( pFile ); } /**Function************************************************************* Synopsis [Compute and dump equivalent name classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose ) { //abctime clk = Abc_Clock(); Vec_Int_t * vClasses; // derive shared AIG for the two networks Gia_Man_t * pGia = Abc_NtkAigToGiaTwo( pNtks[0], pNtks[1], fByName ); if ( fVerbose ) printf( "Computing equivalences for networks \"%s\" and \"%s\" with conflict limit %d.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]), nConfs ); // compute equivalences in this AIG Abc_NtkComputeGiaEquivs( pGia, nConfs, fVerbose ); //if ( fVerbose ) // Abc_PrintTime( 1, "Equivalence computation time", Abc_Clock() - clk ); if ( fVerbose ) Gia_ManPrintStats( pGia, NULL ); // collect equivalence class information vClasses = Abc_NtkCollectEquivClasses( pNtks, pGia ); Gia_ManStop( pGia ); // dump information into the output file Abc_NtkDumpEquivFile( pFileName, vClasses, pNtks ); Vec_IntFree( vClasses ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcDsd.c000066400000000000000000000564751300674244400232110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Decomposes the network using disjoint-support decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.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 static Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort ); static void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ); static Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ); static void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, int fRecursive, int * pCounters ); static int Abc_NodeIsForDsd( Abc_Obj_t * pNode ); static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the DSD network.] Description [Takes the strashed network (pNtk), derives global BDDs for the combinational outputs of this network, and decomposes these BDDs using disjoint support decomposition. Finally, constructs and return a new network, which is topologically equivalent to the decomposition tree. Allocates and frees a new BDD manager and a new DSD manager.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort ) { DdManager * dd; Abc_Ntk_t * pNtkNew; assert( Abc_NtkIsStrash(pNtk) ); dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); if ( dd == NULL ) return NULL; if ( fVerbose ) printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); // transform the result of mapping into a BDD network pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort ); Extra_StopManager( dd ); if ( pNtkNew == NULL ) return NULL; // copy EXDC network if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkDsdGlobal: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Constructs the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort ) { char ** ppNamesCi, ** ppNamesCo; Vec_Ptr_t * vFuncsGlob; Dsd_Manager_t * pManDsd; Abc_Ntk_t * pNtkNew; DdManager * dd; Abc_Obj_t * pObj; int i; // complement the global functions vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) ); // perform the decomposition dd = (DdManager *)Abc_NtkGlobalBddMan(pNtk); pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose ); if ( pManDsd == NULL ) { Vec_PtrFree( vFuncsGlob ); Cudd_Quit( dd ); return NULL; } Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) ); Vec_PtrFree( vFuncsGlob ); Abc_NtkFreeGlobalBdds( pNtk, 0 ); // start the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); // make sure the new manager has enough inputs Cudd_bddIthVar( (DdManager *)pNtkNew->pManFunc, dd->size-1 ); // put the results into the new network (save new CO drivers in old CO drivers) Abc_NtkDsdConstruct( pManDsd, pNtk, pNtkNew ); // finalize the new network Abc_NtkFinalize( pNtk, pNtkNew ); // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); if ( fPrint ) { ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 ); ppNamesCo = Abc_NtkCollectCioNames( pNtk, 1 ); if ( fVerbose ) Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, fShort, -1 ); else Dsd_TreePrint2( stdout, pManDsd, ppNamesCi, ppNamesCo, -1 ); ABC_FREE( ppNamesCi ); ABC_FREE( ppNamesCo ); } // stop the DSD manager Dsd_ManagerStop( pManDsd ); return pNtkNew; } /**Function************************************************************* Synopsis [Constructs the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { Dsd_Node_t ** ppNodesDsd; Dsd_Node_t * pNodeDsd; Abc_Obj_t * pNode, * pNodeNew, * pDriver; int i, nNodesDsd; // save the CI nodes in the DSD nodes Abc_AigConst1(pNtk)->pCopy = pNodeNew = Abc_NtkCreateNodeConst1(pNtkNew); Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), (int)(ABC_PTRINT_T)pNodeNew ); Abc_NtkForEachCi( pNtk, pNode, i ) { pNodeDsd = Dsd_ManagerReadInput( pManDsd, i ); Dsd_NodeSetMark( pNodeDsd, (int)(ABC_PTRINT_T)pNode->pCopy ); } // collect DSD nodes in DFS order (leaves and const1 are not collected) ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd ); for ( i = 0; i < nNodesDsd; i++ ) Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew, NULL ); ABC_FREE( ppNodesDsd ); // set the pointers to the CO drivers Abc_NtkForEachCo( pNtk, pNode, i ) { pDriver = Abc_ObjFanin0( pNode ); if ( !Abc_ObjIsNode(pDriver) ) continue; if ( !Abc_AigNodeIsAnd(pDriver) ) continue; pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i ); pNodeNew = (Abc_Obj_t *)(ABC_PTRINT_T)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) ); assert( !Abc_ObjIsComplement(pNodeNew) ); pDriver->pCopy = Abc_ObjNotCond( pNodeNew, Dsd_IsComplement(pNodeDsd) ); } } /**Function************************************************************* Synopsis [Performs DSD using the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ) { DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd ); DdManager * ddNew = (DdManager *)pNtkNew->pManFunc; Dsd_Node_t * pFaninDsd; Abc_Obj_t * pNodeNew, * pFanin; DdNode * bLocal, * bTemp, * bVar; Dsd_Type_t Type; int i, nDecs; // create the new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); // add the fanins Type = Dsd_NodeReadType( pNodeDsd ); nDecs = Dsd_NodeReadDecsNum( pNodeDsd ); assert( nDecs > 1 ); for ( i = 0; i < nDecs; i++ ) { pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); pFanin = (Abc_Obj_t *)(ABC_PTRINT_T)Dsd_NodeReadMark(Dsd_Regular(pFaninDsd)); Abc_ObjAddFanin( pNodeNew, pFanin ); assert( Type == DSD_NODE_OR || !Dsd_IsComplement(pFaninDsd) ); } // create the local function depending on the type of the node ddNew = (DdManager *)pNtkNew->pManFunc; switch ( Type ) { case DSD_NODE_CONST1: { bLocal = ddNew->one; Cudd_Ref( bLocal ); break; } case DSD_NODE_OR: { bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal ); for ( i = 0; i < nDecs; i++ ) { pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); bVar = Cudd_NotCond( ddNew->vars[i], Dsd_IsComplement(pFaninDsd) ); bLocal = Cudd_bddOr( ddNew, bTemp = bLocal, bVar ); Cudd_Ref( bLocal ); Cudd_RecursiveDeref( ddNew, bTemp ); } break; } case DSD_NODE_EXOR: { bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal ); for ( i = 0; i < nDecs; i++ ) { bLocal = Cudd_bddXor( ddNew, bTemp = bLocal, ddNew->vars[i] ); Cudd_Ref( bLocal ); Cudd_RecursiveDeref( ddNew, bTemp ); } break; } case DSD_NODE_PRIME: { if ( pCounters ) { if ( nDecs < 10 ) pCounters[nDecs]++; else pCounters[10]++; } bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd ); Cudd_Ref( bLocal ); bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal ); /* if ( nDecs == 3 ) { Extra_bddPrint( ddDsd, bTemp ); printf( "\n" ); } */ Cudd_RecursiveDeref( ddDsd, bTemp ); // bLocal is now in the new BDD manager break; } default: { assert( 0 ); break; } } pNodeNew->pData = bLocal; Dsd_NodeSetMark( pNodeDsd, (int)(ABC_PTRINT_T)pNodeNew ); return pNodeNew; } /**Function************************************************************* Synopsis [Recursively decomposes internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, int fVerbose, int fRecursive ) { Dsd_Manager_t * pManDsd; DdManager * dd = (DdManager *)pNtk->pManFunc; Vec_Ptr_t * vNodes; int i; int pCounters[11] = {0}; assert( Abc_NtkIsBddLogic(pNtk) ); // make the network minimum base Abc_NtkMinimumBase( pNtk ); // start the DSD manager pManDsd = Dsd_ManagerStart( dd, dd->size, 0 ); // collect nodes for decomposition vNodes = Abc_NtkCollectNodesForDsd( pNtk ); for ( i = 0; i < vNodes->nSize; i++ ) Abc_NodeDecompDsdAndMux( (Abc_Obj_t *)vNodes->pArray[i], vNodes, pManDsd, fRecursive, pCounters ); Vec_PtrFree( vNodes ); if ( fVerbose ) { printf( "Number of non-decomposable functions:\n" ); for ( i = 3; i < 10; i++ ) printf( "Inputs = %d. Functions = %6d.\n", i, pCounters[i] ); printf( "Inputs > %d. Functions = %6d.\n", 9, pCounters[10] ); } // stop the DSD manager Dsd_ManagerStop( pManDsd ); // make sure everything is okay if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkDsdRecursive: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Collects the nodes that may need decomposition.] Description [The nodes that do not need decomposition are those whose BDD has more internal nodes than the support size.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int i; vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_NodeIsForDsd(pNode) ) Vec_PtrPush( vNodes, pNode ); } return vNodes; } /**Function************************************************************* Synopsis [Performs decomposition of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, int fRecursive, int * pCounters ) { DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; Abc_Obj_t * pRoot = NULL, * pFanin, * pNode1, * pNode2, * pNodeC; Dsd_Node_t ** ppNodesDsd, * pNodeDsd, * pFaninDsd; int i, nNodesDsd, iVar, fCompl; // try disjoint support decomposition pNodeDsd = Dsd_DecomposeOne( pManDsd, (DdNode *)pNode->pData ); fCompl = Dsd_IsComplement( pNodeDsd ); pNodeDsd = Dsd_Regular( pNodeDsd ); // determine what decomposition to use if ( !fRecursive || Dsd_NodeReadDecsNum(pNodeDsd) != Abc_ObjFaninNum(pNode) ) { // perform DSD // set the inputs Abc_ObjForEachFanin( pNode, pFanin, i ) { pFaninDsd = Dsd_ManagerReadInput( pManDsd, i ); Dsd_NodeSetMark( pFaninDsd, (int)(ABC_PTRINT_T)pFanin ); } // construct the intermediate nodes ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd ); for ( i = 0; i < nNodesDsd; i++ ) { pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters ); if ( Abc_NodeIsForDsd(pRoot) && fRecursive ) Vec_PtrPush( vNodes, pRoot ); } ABC_FREE( ppNodesDsd ); assert(pRoot); // remove the current fanins Abc_ObjRemoveFanins( pNode ); // add fanin to the root Abc_ObjAddFanin( pNode, pRoot ); // update the function to be that of buffer Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData ); pNode->pData = Cudd_NotCond( (DdNode *)dd->vars[0], fCompl ); Cudd_Ref( (DdNode *)pNode->pData ); } else // perform MUX-decomposition { // get the cofactoring variable iVar = Abc_NodeFindMuxVar( dd, (DdNode *)pNode->pData, Abc_ObjFaninNum(pNode) ); pNodeC = Abc_ObjFanin( pNode, iVar ); // get the negative cofactor pNode1 = Abc_NtkCloneObj( pNode ); pNode1->pData = Cudd_Cofactor( dd, (DdNode *)pNode->pData, Cudd_Not(dd->vars[iVar]) ); Cudd_Ref( (DdNode *)pNode1->pData ); Abc_NodeMinimumBase( pNode1 ); if ( Abc_NodeIsForDsd(pNode1) ) Vec_PtrPush( vNodes, pNode1 ); // get the positive cofactor pNode2 = Abc_NtkCloneObj( pNode ); pNode2->pData = Cudd_Cofactor( dd, (DdNode *)pNode->pData, dd->vars[iVar] ); Cudd_Ref( (DdNode *)pNode2->pData ); Abc_NodeMinimumBase( pNode2 ); if ( Abc_NodeIsForDsd(pNode2) ) Vec_PtrPush( vNodes, pNode2 ); // remove the current fanins Abc_ObjRemoveFanins( pNode ); // add new fanins Abc_ObjAddFanin( pNode, pNodeC ); Abc_ObjAddFanin( pNode, pNode2 ); Abc_ObjAddFanin( pNode, pNode1 ); // update the function to be that of MUX Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData ); pNode->pData = Cudd_bddIte( dd, dd->vars[0], dd->vars[1], dd->vars[2] ); Cudd_Ref( (DdNode *)pNode->pData ); } } /**Function************************************************************* Synopsis [Checks if the node should be decomposed by DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsForDsd( Abc_Obj_t * pNode ) { // DdManager * dd = pNode->pNtk->pManFunc; // DdNode * bFunc, * bFunc0, * bFunc1; assert( Abc_ObjIsNode(pNode) ); // if ( Cudd_DagSize(pNode->pData)-1 > Abc_ObjFaninNum(pNode) ) // return 1; // return 0; /* // this does not catch things like a(b+c), which should be decomposed for ( bFunc = Cudd_Regular(pNode->pData); !cuddIsConstant(bFunc); ) { bFunc0 = Cudd_Regular( cuddE(bFunc) ); bFunc1 = cuddT(bFunc); if ( bFunc0 == b1 ) bFunc = bFunc1; else if ( bFunc1 == b1 || bFunc0 == bFunc1 ) bFunc = bFunc0; else return 1; } */ if ( Abc_ObjFaninNum(pNode) > 2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Determines a cofactoring variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ) { DdNode * bVar, * bCof0, * bCof1; int SuppSumMin = 1000000; int i, nSSD, nSSQ, iVar; // printf( "\n\nCofactors:\n\n" ); iVar = -1; for ( i = 0; i < nVars; i++ ) { bVar = dd->vars[i]; bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); bCof1 = Cudd_Cofactor( dd, bFunc, bVar ); Cudd_Ref( bCof1 ); // nodD = Cudd_DagSize(bCof0); // nodQ = Cudd_DagSize(bCof1); // printf( "+%02d: D=%2d. Q=%2d. ", i, nodD, nodQ ); // printf( "S=%2d. D=%2d. ", nodD + nodQ, abs(nodD-nodQ) ); nSSD = Cudd_SupportSize( dd, bCof0 ); nSSQ = Cudd_SupportSize( dd, bCof1 ); // printf( "SD=%2d. SQ=%2d. ", nSSD, nSSQ ); // printf( "S=%2d. D=%2d. ", nSSD + nSSQ, abs(nSSD - nSSQ) ); // printf( "Cost=%3d. ", Cost(nodD,nodQ,nSSD,nSSQ) ); // printf( "\n" ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); if ( SuppSumMin > nSSD + nSSQ ) { SuppSumMin = nSSD + nSSQ; iVar = i; } } return iVar; } /**Function******************************************************************** Synopsis [Computes the positive polarty cube composed of the first vars in the array.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddComputeSum( DdManager * dd, DdNode ** pbCubes, int nCubes ) { DdNode * bRes, * bTemp; int i; bRes = b0; Cudd_Ref( bRes ); for ( i = 0; i < nCubes; i++ ) { bRes = Cudd_bddOr( dd, bTemp = bRes, pbCubes[i] ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); return bRes; } /**Function************************************************************* Synopsis [Derives network with the given percentage of on-set and off-set minterms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkSparsifyInternalOne( DdManager * ddNew, DdNode * bFunc, int nFanins, int nPerc ) { int nSpace = (int)Cudd_CountMinterm( ddNew, bFunc, nFanins ); int i, nMints = Abc_MaxInt( 1, (int)(0.01 * nPerc * nSpace) ); DdNode ** pbMints = Cudd_bddPickArbitraryMinterms( ddNew, bFunc, ddNew->vars, nFanins, nMints ); DdNode * bRes; for ( i = 0; i < nMints; i++ ) Cudd_Ref( pbMints[i] ); bRes = Extra_bddComputeSum( ddNew, pbMints, nMints ); Cudd_Ref( bRes ); for ( i = 0; i < nMints; i++ ) Cudd_RecursiveDeref( ddNew, pbMints[i] ); Cudd_Deref( bRes ); ABC_FREE( pbMints ); return bRes; } Abc_Ntk_t * Abc_NtkSparsifyInternal( Abc_Ntk_t * pNtk, int nPerc, int fVerbose ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pDriver, * pFanin; DdNode * bFunc, * bFuncOld; DdManager * ddNew; int i, k, c; // start the new network pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); Abc_NtkForEachCi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // make sure the new manager has enough inputs ddNew = (DdManager *)pNtkNew->pManFunc; Cudd_bddIthVar( ddNew, Abc_NtkCiNum(pNtk)-1 ); // go through the outputs Abc_NtkForEachCo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0( pObj ); if ( Abc_ObjIsCi(pDriver) ) { Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjAddFanin( pObj->pCopy, Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)) ); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), "_on" ); Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjAddFanin( pObj->pCopy, Abc_ObjNotCond(pDriver->pCopy, !Abc_ObjFaninC0(pObj)) ); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), "_off" ); continue; } if ( Abc_ObjFaninNum(pDriver) == 0 ) { Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFaninC0(pObj) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew) ); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), "_on" ); Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFaninC0(pObj) ? Abc_NtkCreateNodeConst1(pNtkNew) : Abc_NtkCreateNodeConst0(pNtkNew) ); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), "_off" ); continue; } assert( Abc_ObjFaninNum(pObj) > 0 ); // onset/offset for ( c = 0; c < 2; c++ ) { Cudd_Srandom( 0 ); Abc_NtkDupObj( pNtkNew, pDriver, 0 ); Abc_ObjForEachFanin( pDriver, pFanin, k ) Abc_ObjAddFanin( pDriver->pCopy, pFanin->pCopy ); bFuncOld = Cudd_NotCond( (DdNode *)pDriver->pCopy->pData, c ); bFunc = Abc_NtkSparsifyInternalOne( ddNew, bFuncOld, Abc_ObjFaninNum(pDriver), nPerc ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( ddNew, bFuncOld ); pDriver->pCopy->pData = bFunc; Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy ); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), (char*)(c ? "_off" : "_on") ); } } Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); return pNtkNew; } Abc_Ntk_t * Abc_NtkSparsify( Abc_Ntk_t * pNtk, int nPerc, int fVerbose ) { Abc_Ntk_t * pNtkNew; assert( Abc_NtkIsComb(pNtk) ); assert( Abc_NtkIsBddLogic(pNtk) ); pNtkNew = Abc_NtkSparsifyInternal( pNtk, nPerc, fVerbose ); if ( pNtkNew == NULL ) return NULL; if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkSparsify: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } #else Abc_Ntk_t * Abc_NtkSparsify( Abc_Ntk_t * pNtk, int nPerc, int fVerbose ) { return NULL; } Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort ) { return NULL; } int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, int fVerbose, int fRecursive ) { return 0; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcEspresso.c000066400000000000000000000153361300674244400242710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcEspresso.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to minimize SOPs using Espresso.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcEspresso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "misc/espresso/espresso.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NodeEspresso( Abc_Obj_t * pNode ); static pset_family Abc_SopToEspresso( char * pSop ); static char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover ); static pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Minimizes SOP representations using Espresso.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ) { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsLogic(pNtk) ); // convert the network to have SOPs if ( Abc_NtkHasMapping(pNtk) ) Abc_NtkMapToSop(pNtk); else if ( Abc_NtkHasBdd(pNtk) ) { if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) { printf( "Abc_NtkEspresso(): Converting to SOPs has failed.\n" ); return; } } // minimize SOPs of all nodes Abc_NtkForEachNode( pNtk, pNode, i ) if ( i ) Abc_NodeEspresso( pNode ); } /**Function************************************************************* Synopsis [Minimizes SOP representation of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeEspresso( Abc_Obj_t * pNode ) { extern void define_cube_size( int n ); pset_family Cover; int fCompl; assert( Abc_ObjIsNode(pNode) ); // define the cube for this node define_cube_size( Abc_ObjFaninNum(pNode) ); // create the Espresso cover fCompl = Abc_SopIsComplement( pNode->pData ); Cover = Abc_SopToEspresso( pNode->pData ); // perform minimization Cover = Abc_EspressoMinimize( Cover, NULL ); // deletes also cover // convert back onto the node's SOP representation pNode->pData = Abc_SopFromEspresso( pNode->pNtk->pManFunc, Cover ); if ( fCompl ) Abc_SopComplement( pNode->pData ); sf_free(Cover); } /**Function************************************************************* Synopsis [Converts SOP in ABC into SOP representation in Espresso.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ pset_family Abc_SopToEspresso( char * pSop ) { char * pCube; pset_family Cover; pset set; int nCubes, nVars, Value, v; if ( pSop == NULL ) return NULL; nVars = Abc_SopGetVarNum(pSop); nCubes = Abc_SopGetCubeNum(pSop); assert( cube.size == 2 * nVars ); if ( Abc_SopIsConst0(pSop) ) { Cover = sf_new(0, cube.size); return Cover; } if ( Abc_SopIsConst1(pSop) ) { Cover = sf_new(1, cube.size); set = GETSET(Cover, Cover->count++); set_copy( set, cube.fullset ); return Cover; } // create the cover Cover = sf_new(nCubes, cube.size); // fill in the cubes Abc_SopForEachCube( pSop, nVars, pCube ) { set = GETSET(Cover, Cover->count++); set_copy( set, cube.fullset ); Abc_CubeForEachVar( pCube, Value, v ) { if ( Value == '0' ) set_remove(set, 2*v+1); else if ( Value == '1' ) set_remove(set, 2*v); } } return Cover; } /**Function************************************************************* Synopsis [Converts SOP representation in Espresso into SOP in ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover ) { pset set; char * pSop, * pCube; int Lit, nVars, nCubes, i, k; nVars = Cover->sf_size/2; nCubes = Cover->count; pSop = Abc_SopStart( pMan, nCubes, nVars ); // go through the cubes i = 0; Abc_SopForEachCube( pSop, nVars, pCube ) { set = GETSET(Cover, i++); for ( k = 0; k < nVars; k++ ) { Lit = GETINPUT(set, k); if ( Lit == ZERO ) pCube[k] = '0'; else if ( Lit == ONE ) pCube[k] = '1'; } } return pSop; } /**Function************************************************************* Synopsis [Minimizes the cover using Espresso.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset ) { pset_family pOffset; int fNewDcset, i; int fSimple = 0; int fSparse = 0; if ( fSimple ) { for ( i = 0; i < cube.num_vars; i++ ) pOnset = d1merge( pOnset, i ); pOnset = sf_contain( pOnset ); return pOnset; } // create the dcset fNewDcset = (pDcset == NULL); if ( pDcset == NULL ) pDcset = sf_new( 1, cube.size ); pDcset->wsize = pOnset->wsize; pDcset->sf_size = pOnset->sf_size; // derive the offset if ( pDcset->sf_size == 0 || pDcset->count == 0 ) pOffset = complement(cube1list(pOnset)); else pOffset = complement(cube2list(pOnset, pDcset)); // perform minimization skip_make_sparse = !fSparse; pOnset = espresso( pOnset, pDcset, pOffset ); // free covers sf_free( pOffset ); if ( fNewDcset ) sf_free( pDcset ); return pOnset; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcExact.c000066400000000000000000003273001300674244400235270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcExact.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Find minimum size networks with a SAT solver.] Author [Mathias Soeken] Affiliation [EPFL] Date [Ver. 1.0. Started - July 15, 2016.] Revision [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ /* This implementation is based on Exercises 477 and 478 in * Donald E. Knuth TAOCP Fascicle 6 (Satisfiability) Section 7.2.2.2 */ #include "base/abc/abc.h" #include "aig/gia/gia.h" #include "misc/util/utilTruth.h" #include "misc/vec/vecInt.h" #include "misc/vec/vecPtr.h" #include "proof/cec/cec.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*********************************************************************** Synopsis [Some truth table helper functions.] ***********************************************************************/ static word s_Truths8[32] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0xFFFFFFFFFFFFFFFF) }; static word s_Truths8Neg[32] = { ABC_CONST(0x5555555555555555), ABC_CONST(0x5555555555555555), ABC_CONST(0x5555555555555555), ABC_CONST(0x5555555555555555), ABC_CONST(0x3333333333333333), ABC_CONST(0x3333333333333333), ABC_CONST(0x3333333333333333), ABC_CONST(0x3333333333333333), ABC_CONST(0x0F0F0F0F0F0F0F0F), ABC_CONST(0x0F0F0F0F0F0F0F0F), ABC_CONST(0x0F0F0F0F0F0F0F0F), ABC_CONST(0x0F0F0F0F0F0F0F0F), ABC_CONST(0x00FF00FF00FF00FF), ABC_CONST(0x00FF00FF00FF00FF), ABC_CONST(0x00FF00FF00FF00FF), ABC_CONST(0x00FF00FF00FF00FF), ABC_CONST(0x0000FFFF0000FFFF), ABC_CONST(0x0000FFFF0000FFFF), ABC_CONST(0x0000FFFF0000FFFF), ABC_CONST(0x0000FFFF0000FFFF), ABC_CONST(0x00000000FFFFFFFF), ABC_CONST(0x00000000FFFFFFFF), ABC_CONST(0x00000000FFFFFFFF), ABC_CONST(0x00000000FFFFFFFF), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0xFFFFFFFFFFFFFFFF), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }; static int Abc_TtIsSubsetWithMask( word * pSmall, word * pLarge, word * pMask, int nWords ) { int w; for ( w = 0; w < nWords; ++w ) if ( ( pSmall[w] & pLarge[w] & pMask[w] ) != ( pSmall[w] & pMask[w] ) ) return 0; return 1; } static int Abc_TtCofsOppositeWithMask( word * pTruth, word * pMask, int nWords, int iVar ) { if ( iVar < 6 ) { int w, Shift = ( 1 << iVar ); for ( w = 0; w < nWords; ++w ) if ( ( ( pTruth[w] << Shift ) & s_Truths6[iVar] & pMask[w] ) != ( ~pTruth[w] & s_Truths6[iVar] & pMask[w] ) ) return 0; return 1; } else { int w, Step = ( 1 << ( iVar - 6 ) ); word * p = pTruth, * m = pMask, * pLimit = pTruth + nWords; for ( ; p < pLimit; p += 2 * Step, m += 2 * Step ) for ( w = 0; w < Step; ++w ) if ( ( p[w] & m[w] ) != ( ~p[w + Step] & m[w + Step] ) ) return 0; return 1; } } // checks whether we can decompose as OP(x^p, g) where OP in {AND, OR} and p in {0, 1} // returns p if OP = AND, and 2 + p if OP = OR static int Abc_TtIsTopDecomposable( word * pTruth, word * pMask, int nWords, int iVar ) { assert( iVar < 8 ); if ( Abc_TtIsSubsetWithMask( pTruth, &s_Truths8[iVar << 2], pMask, nWords ) ) return 1; if ( Abc_TtIsSubsetWithMask( pTruth, &s_Truths8Neg[iVar << 2], pMask, nWords ) ) return 2; if ( Abc_TtIsSubsetWithMask( &s_Truths8[iVar << 2], pTruth, pMask, nWords ) ) return 3; if ( Abc_TtIsSubsetWithMask( &s_Truths8Neg[iVar << 2], pTruth, pMask, nWords ) ) return 4; if ( Abc_TtCofsOppositeWithMask( pTruth, pMask, nWords, iVar ) ) return 5; return 0; } // checks whether we can decompose as OP(x1, OP(x2, OP(x3, ...))) where pVars = {x1, x2, x3, ...} // OP can be different and vars can be complemented static int Abc_TtIsStairDecomposable( word * pTruth, int nWords, int * pVars, int nSize, int * pStairFunc ) { int i, d; word pMask[4]; word pCopy[4]; Abc_TtCopy( pCopy, pTruth, nWords, 0 ); Abc_TtMask( pMask, nWords, nWords * 64 ); for ( i = 0; i < nSize; ++i ) { d = Abc_TtIsTopDecomposable( pCopy, pMask, nWords, pVars[i] ); if ( !d ) return 0; /* not decomposable */ pStairFunc[i] = d; switch ( d ) { case 1: /* AND(x, g) */ case 4: /* OR(!x, g) */ Abc_TtAnd( pMask, pMask, &s_Truths8[pVars[i] << 2], nWords, 0 ); break; case 2: /* AND(!x, g) */ case 3: /* OR(x, g) */ Abc_TtAnd( pMask, pMask, &s_Truths8Neg[pVars[i] << 2], nWords, 0 ); break; case 5: Abc_TtXor( pCopy, pCopy, &s_Truths8[pVars[i] << 2], nWords, 0 ); break; } } return 1; /* decomposable */ } /*********************************************************************** Synopsis [Some printing utilities.] ***********************************************************************/ static inline void Abc_DebugPrint( const char* str, int fCond ) { if ( fCond ) { printf( "%s", str ); fflush( stdout ); } } static inline void Abc_DebugPrintInt( const char* fmt, int n, int fCond ) { if ( fCond ) { printf( fmt, n ); fflush( stdout ); } } static inline void Abc_DebugPrintIntInt( const char* fmt, int n1, int n2, int fCond ) { if ( fCond ) { printf( fmt, n1, n2 ); fflush( stdout ); } } static inline void Abc_DebugErase( int n, int fCond ) { int i; if ( fCond ) { for ( i = 0; i < n; ++i ) printf( "\b" ); fflush( stdout ); } } /*********************************************************************** Synopsis [BMS.] ***********************************************************************/ #define ABC_EXACT_SOL_NVARS 0 #define ABC_EXACT_SOL_NFUNC 1 #define ABC_EXACT_SOL_NGATES 2 #define ANSI_COLOR_RED "\x1b[31m" #define ANSI_COLOR_GREEN "\x1b[32m" #define ANSI_COLOR_YELLOW "\x1b[33m" #define ANSI_COLOR_BLUE "\x1b[34m" #define ANSI_COLOR_MAGENTA "\x1b[35m" #define ANSI_COLOR_CYAN "\x1b[36m" #define ANSI_COLOR_RESET "\x1b[0m" typedef struct Ses_Man_t_ Ses_Man_t; struct Ses_Man_t_ { sat_solver * pSat; /* SAT solver */ word * pSpec; /* specification */ int bSpecInv; /* remembers whether spec was inverted for normalization */ int nSpecVars; /* number of variables in specification */ int nSpecFunc; /* number of functions to synthesize */ int nSpecWords; /* number of words for function */ int nRows; /* number of rows in the specification (without 0) */ int nMaxDepth; /* maximum depth (-1 if depth is not constrained) */ int nMaxDepthTmp; /* temporary copy to modify nMaxDepth temporarily */ int * pArrTimeProfile; /* arrival times of inputs (NULL if arrival times are ignored) */ int pArrTimeProfileTmp[8]; /* temporary copy to modify pArrTimeProfile temporarily */ int nArrTimeDelta; /* delta to the original arrival times (arrival times are normalized to have 0 as minimum element) */ int nArrTimeMax; /* maximum normalized arrival time */ int nBTLimit; /* conflict limit */ int fMakeAIG; /* create AIG instead of general network */ int fVerbose; /* be verbose */ int fVeryVerbose; /* be very verbose */ int fExtractVerbose; /* be verbose about solution extraction */ int fSatVerbose; /* be verbose about SAT solving */ int fReasonVerbose; /* be verbose about give-up reasons */ word pTtValues[4]; /* truth table values to assign */ Vec_Int_t * vPolar; /* variables with positive polarity */ Vec_Int_t * vAssump; /* assumptions */ int nGates; /* number of gates */ int nStartGates; /* number of gates to start search (-1), i.e., to start from 1 gate, one needs to specify 0 */ int nMaxGates; /* maximum number of gates given max. delay and arrival times */ int fDecStructure; /* set to 1 or higher if nSpecFunc = 1 and f = x_i OP g(X \ {x_i}), otherwise 0 (determined when solving) */ int pDecVars; /* mask of variables that can be decomposed at top-level */ Vec_Int_t * vStairDecVars; /* list of stair decomposable variables */ int pStairDecFunc[8]; /* list of stair decomposable functions */ word pTtObjs[100]; /* temporary truth tables */ int nSimVars; /* number of simulation vars x(i, t) */ int nOutputVars; /* number of output variables g(h, i) */ int nGateVars; /* number of gate variables f(i, p, q) */ int nSelectVars; /* number of select variables s(i, j, k) */ int nDepthVars; /* number of depth variables d(i, j) */ int nSimOffset; /* offset where gate variables start */ int nOutputOffset; /* offset where output variables start */ int nGateOffset; /* offset where gate variables start */ int nSelectOffset; /* offset where select variables start */ int nDepthOffset; /* offset where depth variables start */ int fHitResLimit; /* SAT solver gave up due to resource limit */ abctime timeSat; /* SAT runtime */ abctime timeSatSat; /* SAT runtime (sat instance) */ abctime timeSatUnsat; /* SAT runtime (unsat instance) */ abctime timeSatUndef; /* SAT runtime (undef instance) */ abctime timeInstance; /* creating instance runtime */ abctime timeTotal; /* all runtime */ int nSatCalls; /* number of SAT calls */ int nUnsatCalls; /* number of UNSAT calls */ int nUndefCalls; /* number of UNDEF calls */ int nDebugOffset; /* for debug printing */ }; /*********************************************************************** Synopsis [Store truth tables based on normalized arrival times.] ***********************************************************************/ // The hash table is a list of pointers to Ses_TruthEntry_t elements, which // are arranged in a linked list, each of which pointing to a linked list // of Ses_TimesEntry_t elements which contain the char* representation of the // optimum netlist according to then normalized arrival times: typedef struct Ses_TimesEntry_t_ Ses_TimesEntry_t; struct Ses_TimesEntry_t_ { int pArrTimeProfile[8]; /* normalized arrival time profile */ int fResLimit; /* solution found after resource limit */ Ses_TimesEntry_t * next; /* linked list pointer */ char * pNetwork; /* pointer to char array representation of optimum network */ }; typedef struct Ses_TruthEntry_t_ Ses_TruthEntry_t; struct Ses_TruthEntry_t_ { word pTruth[4]; /* truth table for comparison */ int nVars; /* number of variables */ Ses_TruthEntry_t * next; /* linked list pointer */ Ses_TimesEntry_t * head; /* pointer to head of sub list with arrival times */ }; #define SES_STORE_TABLE_SIZE 1024 typedef struct Ses_Store_t_ Ses_Store_t; struct Ses_Store_t_ { int fMakeAIG; /* create AIG instead of general network */ int fVerbose; /* be verbose */ int fVeryVerbose; /* be very verbose */ int nBTLimit; /* conflict limit */ int nEntriesCount; /* number of entries */ int nValidEntriesCount; /* number of entries with network */ Ses_TruthEntry_t * pEntries[SES_STORE_TABLE_SIZE]; /* hash table for truth table entries */ sat_solver * pSat; /* own SAT solver instance to reuse when calling exact algorithm */ FILE * pDebugEntries; /* debug unsynth. (rl) entries */ char * szDBName; /* if given, database is written every time a new entry is added */ /* statistics */ unsigned long nCutCount; /* number of cuts investigated */ unsigned long pCutCount[9]; /* -> per cut size */ unsigned long nUnsynthesizedImp; /* number of cuts which couldn't be optimized at all, opt. stopped because of imp. constraints */ unsigned long pUnsynthesizedImp[9]; /* -> per cut size */ unsigned long nUnsynthesizedRL; /* number of cuts which couldn't be optimized at all, opt. stopped because of resource limits */ unsigned long pUnsynthesizedRL[9]; /* -> per cut size */ unsigned long nSynthesizedTrivial; /* number of cuts which could be synthesized trivially (n < 2) */ unsigned long pSynthesizedTrivial[9]; /* -> per cut size */ unsigned long nSynthesizedImp; /* number of cuts which could be synthesized, opt. stopped because of imp. constraints */ unsigned long pSynthesizedImp[9]; /* -> per cut size */ unsigned long nSynthesizedRL; /* number of cuts which could be synthesized, opt. stopped because of resource limits */ unsigned long pSynthesizedRL[9]; /* -> per cut size */ unsigned long nCacheHits; /* number of cache hits */ unsigned long pCacheHits[9]; /* -> per cut size */ unsigned long nSatCalls; /* number of total SAT calls */ unsigned long nUnsatCalls; /* number of total UNSAT calls */ unsigned long nUndefCalls; /* number of total UNDEF calls */ abctime timeExact; /* Exact synthesis runtime */ abctime timeSat; /* SAT runtime */ abctime timeSatSat; /* SAT runtime (sat instance) */ abctime timeSatUnsat; /* SAT runtime (unsat instance) */ abctime timeSatUndef; /* SAT runtime (undef instance) */ abctime timeInstance; /* creating instance runtime */ abctime timeTotal; /* all runtime */ }; static Ses_Store_t * s_pSesStore = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NormalizeArrivalTimes( int * pArrTimeProfile, int nVars, int * maxNormalized ) { int * p = pArrTimeProfile, * pEnd = pArrTimeProfile + nVars; int delta = *p; while ( ++p < pEnd ) if ( *p < delta ) delta = *p; *maxNormalized = 0; p = pArrTimeProfile; while ( p < pEnd ) { *p -= delta; if ( *p > *maxNormalized ) *maxNormalized = *p; ++p; } *maxNormalized += 1; return delta; } static inline Ses_Store_t * Ses_StoreAlloc( int nBTLimit, int fMakeAIG, int fVerbose ) { Ses_Store_t * pStore = ABC_CALLOC( Ses_Store_t, 1 ); pStore->fMakeAIG = fMakeAIG; pStore->fVerbose = fVerbose; pStore->nBTLimit = nBTLimit; memset( pStore->pEntries, 0, SES_STORE_TABLE_SIZE ); pStore->pSat = sat_solver_new(); return pStore; } static inline void Ses_StoreClean( Ses_Store_t * pStore ) { int i; Ses_TruthEntry_t * pTEntry, * pTEntry2; Ses_TimesEntry_t * pTiEntry, * pTiEntry2; for ( i = 0; i < SES_STORE_TABLE_SIZE; ++i ) if ( pStore->pEntries[i] ) { pTEntry = pStore->pEntries[i]; while ( pTEntry ) { pTiEntry = pTEntry->head; while ( pTiEntry ) { ABC_FREE( pTiEntry->pNetwork ); pTiEntry2 = pTiEntry; pTiEntry = pTiEntry->next; ABC_FREE( pTiEntry2 ); } pTEntry2 = pTEntry; pTEntry = pTEntry->next; ABC_FREE( pTEntry2 ); } } sat_solver_delete( pStore->pSat ); if ( pStore->szDBName ) ABC_FREE( pStore->szDBName ); ABC_FREE( pStore ); } static inline int Ses_StoreTableHash( word * pTruth, int nVars ) { static int s_Primes[4] = { 1291, 1699, 1999, 2357 }; int i; unsigned uHash = 0; for ( i = 0; i < Abc_TtWordNum( nVars ); ++i ) uHash ^= pTruth[i] * s_Primes[i & 0xf]; return (int)(uHash % SES_STORE_TABLE_SIZE ); } static inline int Ses_StoreTruthEqual( Ses_TruthEntry_t * pEntry, word * pTruth, int nVars ) { int i; if ( pEntry->nVars != nVars ) return 0; for ( i = 0; i < Abc_TtWordNum( nVars ); ++i ) if ( pEntry->pTruth[i] != pTruth[i] ) return 0; return 1; } static inline void Ses_StoreTruthCopy( Ses_TruthEntry_t * pEntry, word * pTruthSrc, int nVars ) { int i; pEntry->nVars = nVars; for ( i = 0; i < Abc_TtWordNum( nVars ); ++i ) pEntry->pTruth[i] = pTruthSrc[i]; } static inline int Ses_StoreTimesEqual( int * pTimes1, int * pTimes2, int nVars ) { int i; for ( i = 0; i < nVars; ++i ) if ( pTimes1[i] != pTimes2[i] ) return 0; return 1; } static inline void Ses_StoreTimesCopy( int * pTimesDest, int * pTimesSrc, int nVars ) { int i; for ( i = 0; i < nVars; ++i ) pTimesDest[i] = pTimesSrc[i]; } static inline void Ses_StorePrintEntry( Ses_TruthEntry_t * pEntry, Ses_TimesEntry_t * pTiEntry ) { int i; printf( "f = " ); Abc_TtPrintHexRev( stdout, pEntry->pTruth, pEntry->nVars ); printf( ", n = %d", pEntry->nVars ); printf( ", arrival =" ); for ( i = 0; i < pEntry->nVars; ++i ) printf( " %d", pTiEntry->pArrTimeProfile[i] ); printf( "\n" ); } static inline void Ses_StorePrintDebugEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pNormalArrTime, int nMaxDepth, char * pSol, int nStartGates ) { int l; fprintf( pStore->pDebugEntries, "abc -c \"exact -v -C %d", pStore->nBTLimit ); if ( s_pSesStore->fMakeAIG ) fprintf( pStore->pDebugEntries, " -a" ); fprintf( pStore->pDebugEntries, " -S %d -D %d -A", nStartGates + 1, nMaxDepth ); for ( l = 0; l < nVars; ++l ) fprintf( pStore->pDebugEntries, "%c%d", ( l == 0 ? ' ' : ',' ), pNormalArrTime[l] ); fprintf( pStore->pDebugEntries, " " ); Abc_TtPrintHexRev( pStore->pDebugEntries, pTruth, nVars ); fprintf( pStore->pDebugEntries, "\" # " ); if ( !pSol ) fprintf( pStore->pDebugEntries, "no " ); fprintf( pStore->pDebugEntries, "solution found before\n" ); } static void Abc_ExactNormalizeArrivalTimesForNetwork( int nVars, int * pArrTimeProfile, char * pSol ) { int nGates, i, j, k, nMax; Vec_Int_t * vLevels; nGates = pSol[ABC_EXACT_SOL_NGATES]; /* printf( "NORMALIZE\n" ); */ /* printf( " #vars = %d\n", nVars ); */ /* printf( " #gates = %d\n", nGates ); */ vLevels = Vec_IntAllocArrayCopy( pArrTimeProfile, nVars ); /* compute level of each gate based on arrival time profile (to compute depth) */ for ( i = 0; i < nGates; ++i ) { j = pSol[3 + i * 4 + 2]; k = pSol[3 + i * 4 + 3]; Vec_IntPush( vLevels, Abc_MaxInt( Vec_IntEntry( vLevels, j ), Vec_IntEntry( vLevels, k ) ) + 1 ); /* printf( " gate %d = (%d,%d)\n", nVars + i, j, k ); */ } /* Vec_IntPrint( vLevels ); */ /* reset all levels except for the last one */ for ( i = 0; i < nVars + nGates - 1; ++i ) Vec_IntSetEntry( vLevels, i, Vec_IntEntry( vLevels, nVars + nGates - 1 ) ); /* Vec_IntPrint( vLevels ); */ /* compute levels from top to bottom */ for ( i = nGates - 1; i >= 0; --i ) { j = pSol[3 + i * 4 + 2]; k = pSol[3 + i * 4 + 3]; Vec_IntSetEntry( vLevels, j, Abc_MinInt( Vec_IntEntry( vLevels, j ), Vec_IntEntry( vLevels, nVars + i ) - 1 ) ); Vec_IntSetEntry( vLevels, k, Abc_MinInt( Vec_IntEntry( vLevels, k ), Vec_IntEntry( vLevels, nVars + i ) - 1 ) ); } /* Vec_IntPrint( vLevels ); */ /* normalize arrival times */ Abc_NormalizeArrivalTimes( Vec_IntArray( vLevels ), nVars, &nMax ); memcpy( pArrTimeProfile, Vec_IntArray( vLevels ), sizeof(int) * nVars ); /* printf( " nMax = %d\n", nMax ); */ /* Vec_IntPrint( vLevels ); */ Vec_IntFree( vLevels ); } static void Ses_StoreWrite( Ses_Store_t * pStore, const char * pFilename, int fSynthImp, int fSynthRL, int fUnsynthImp, int fUnsynthRL ) { int i; char zero = '\0'; unsigned long nEntries = 0; Ses_TruthEntry_t * pTEntry; Ses_TimesEntry_t * pTiEntry; FILE * pFile; pFile = fopen( pFilename, "wb" ); if (pFile == NULL) { printf( "cannot open file \"%s\" for writing\n", pFilename ); return; } if ( fSynthImp ) nEntries += pStore->nSynthesizedImp; if ( fSynthRL ) nEntries += pStore->nSynthesizedRL; if ( fUnsynthImp ) nEntries += pStore->nUnsynthesizedImp; if ( fUnsynthRL ) nEntries += pStore->nUnsynthesizedRL; fwrite( &nEntries, sizeof( unsigned long ), 1, pFile ); for ( i = 0; i < SES_STORE_TABLE_SIZE; ++i ) if ( pStore->pEntries[i] ) { pTEntry = pStore->pEntries[i]; while ( pTEntry ) { pTiEntry = pTEntry->head; while ( pTiEntry ) { if ( !fSynthImp && pTiEntry->pNetwork && !pTiEntry->fResLimit ) { pTiEntry = pTiEntry->next; continue; } if ( !fSynthRL && pTiEntry->pNetwork && pTiEntry->fResLimit ) { pTiEntry = pTiEntry->next; continue; } if ( !fUnsynthImp && !pTiEntry->pNetwork && !pTiEntry->fResLimit ) { pTiEntry = pTiEntry->next; continue; } if ( !fUnsynthRL && !pTiEntry->pNetwork && pTiEntry->fResLimit ) { pTiEntry = pTiEntry->next; continue; } fwrite( pTEntry->pTruth, sizeof( word ), 4, pFile ); fwrite( &pTEntry->nVars, sizeof( int ), 1, pFile ); fwrite( pTiEntry->pArrTimeProfile, sizeof( int ), 8, pFile ); fwrite( &pTiEntry->fResLimit, sizeof( int ), 1, pFile ); if ( pTiEntry->pNetwork ) { fwrite( pTiEntry->pNetwork, sizeof( char ), 3 + 4 * pTiEntry->pNetwork[ABC_EXACT_SOL_NGATES] + 2 + pTiEntry->pNetwork[ABC_EXACT_SOL_NVARS], pFile ); } else { fwrite( &zero, sizeof( char ), 1, pFile ); fwrite( &zero, sizeof( char ), 1, pFile ); fwrite( &zero, sizeof( char ), 1, pFile ); } pTiEntry = pTiEntry->next; } pTEntry = pTEntry->next; } } fclose( pFile ); } // pArrTimeProfile is normalized // returns 1 if and only if a new TimesEntry has been created int Ses_StoreAddEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile, char * pSol, int fResLimit ) { int key, fAdded; Ses_TruthEntry_t * pTEntry; Ses_TimesEntry_t * pTiEntry; if ( pSol ) Abc_ExactNormalizeArrivalTimesForNetwork( nVars, pArrTimeProfile, pSol ); key = Ses_StoreTableHash( pTruth, nVars ); pTEntry = pStore->pEntries[key]; /* does truth table already exist? */ while ( pTEntry ) { if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) ) break; else pTEntry = pTEntry->next; } /* entry does not yet exist, so create new one and enqueue */ if ( !pTEntry ) { pTEntry = ABC_CALLOC( Ses_TruthEntry_t, 1 ); Ses_StoreTruthCopy( pTEntry, pTruth, nVars ); pTEntry->next = pStore->pEntries[key]; pStore->pEntries[key] = pTEntry; } /* does arrival time already exist? */ pTiEntry = pTEntry->head; while ( pTiEntry ) { if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) ) break; else pTiEntry = pTiEntry->next; } /* entry does not yet exist, so create new one and enqueue */ if ( !pTiEntry ) { pTiEntry = ABC_CALLOC( Ses_TimesEntry_t, 1 ); Ses_StoreTimesCopy( pTiEntry->pArrTimeProfile, pArrTimeProfile, nVars ); pTiEntry->pNetwork = pSol; pTiEntry->fResLimit = fResLimit; pTiEntry->next = pTEntry->head; pTEntry->head = pTiEntry; /* item has been added */ fAdded = 1; pStore->nEntriesCount++; if ( pSol ) pStore->nValidEntriesCount++; } else { //assert( 0 ); /* item was already present */ fAdded = 0; } /* statistics */ if ( pSol ) { if ( fResLimit ) { pStore->nSynthesizedRL++; pStore->pSynthesizedRL[nVars]++; } else { pStore->nSynthesizedImp++; pStore->pSynthesizedImp[nVars]++; } } else { if ( fResLimit ) { pStore->nUnsynthesizedRL++; pStore->pUnsynthesizedRL[nVars]++; } else { pStore->nUnsynthesizedImp++; pStore->pUnsynthesizedImp[nVars]++; } } if ( fAdded && pStore->szDBName ) Ses_StoreWrite( pStore, pStore->szDBName, 1, 0, 0, 0 ); return fAdded; } // pArrTimeProfile is normalized // returns 1 if entry was in store, pSol may still be 0 if it couldn't be computed int Ses_StoreGetEntrySimple( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile, char ** pSol ) { int key; Ses_TruthEntry_t * pTEntry; Ses_TimesEntry_t * pTiEntry; key = Ses_StoreTableHash( pTruth, nVars ); pTEntry = pStore->pEntries[key]; /* find truth table entry */ while ( pTEntry ) { if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) ) break; else pTEntry = pTEntry->next; } /* no entry found? */ if ( !pTEntry ) return 0; /* find times entry */ pTiEntry = pTEntry->head; while ( pTiEntry ) { if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) ) break; else pTiEntry = pTiEntry->next; } /* no entry found? */ if ( !pTiEntry ) return 0; *pSol = pTiEntry->pNetwork; return 1; } int Ses_StoreGetEntry( Ses_Store_t * pStore, word * pTruth, int nVars, int * pArrTimeProfile, char ** pSol ) { int key; Ses_TruthEntry_t * pTEntry; Ses_TimesEntry_t * pTiEntry; int pTimes[8]; key = Ses_StoreTableHash( pTruth, nVars ); pTEntry = pStore->pEntries[key]; /* find truth table entry */ while ( pTEntry ) { if ( Ses_StoreTruthEqual( pTEntry, pTruth, nVars ) ) break; else pTEntry = pTEntry->next; } /* no entry found? */ if ( !pTEntry ) return 0; /* find times entry */ pTiEntry = pTEntry->head; while ( pTiEntry ) { /* found after normalization wrt. to network */ if ( pTiEntry->pNetwork ) { memcpy( pTimes, pArrTimeProfile, sizeof(int) * nVars ); Abc_ExactNormalizeArrivalTimesForNetwork( nVars, pTimes, pTiEntry->pNetwork ); if ( Ses_StoreTimesEqual( pTimes, pTiEntry->pArrTimeProfile, nVars ) ) break; } /* found for non synthesized network */ else if ( Ses_StoreTimesEqual( pArrTimeProfile, pTiEntry->pArrTimeProfile, nVars ) ) break; else pTiEntry = pTiEntry->next; } /* no entry found? */ if ( !pTiEntry ) return 0; *pSol = pTiEntry->pNetwork; return 1; } static void Ses_StoreRead( Ses_Store_t * pStore, const char * pFilename, int fSynthImp, int fSynthRL, int fUnsynthImp, int fUnsynthRL ) { int i; unsigned long nEntries; word pTruth[4]; int nVars, fResLimit; int pArrTimeProfile[8]; char pHeader[3]; char * pNetwork; FILE * pFile; int value; if ( pStore->szDBName ) { printf( "cannot read from database when szDBName is set" ); return; } pFile = fopen( pFilename, "rb" ); if (pFile == NULL) { printf( "cannot open file \"%s\" for reading\n", pFilename ); return; } value = fread( &nEntries, sizeof( unsigned long ), 1, pFile ); for ( i = 0; i < (int)nEntries; ++i ) { value = fread( pTruth, sizeof( word ), 4, pFile ); value = fread( &nVars, sizeof( int ), 1, pFile ); value = fread( pArrTimeProfile, sizeof( int ), 8, pFile ); value = fread( &fResLimit, sizeof( int ), 1, pFile ); value = fread( pHeader, sizeof( char ), 3, pFile ); if ( pHeader[0] == '\0' ) pNetwork = NULL; else { pNetwork = ABC_CALLOC( char, 3 + 4 * pHeader[ABC_EXACT_SOL_NGATES] + 2 + pHeader[ABC_EXACT_SOL_NVARS] ); pNetwork[0] = pHeader[0]; pNetwork[1] = pHeader[1]; pNetwork[2] = pHeader[2]; value = fread( pNetwork + 3, sizeof( char ), 4 * pHeader[ABC_EXACT_SOL_NGATES] + 2 + pHeader[ABC_EXACT_SOL_NVARS], pFile ); } if ( !fSynthImp && pNetwork && !fResLimit ) continue; if ( !fSynthRL && pNetwork && fResLimit ) continue; if ( !fUnsynthImp && !pNetwork && !fResLimit ) continue; if ( !fUnsynthRL && !pNetwork && fResLimit ) continue; Ses_StoreAddEntry( pStore, pTruth, nVars, pArrTimeProfile, pNetwork, fResLimit ); } fclose( pFile ); printf( "read %lu entries from file\n", nEntries ); } // computes top decomposition of variables wrt. to AND and OR static inline void Ses_ManComputeTopDec( Ses_Man_t * pSes ) { int l; word pMask[4]; Abc_TtMask( pMask, pSes->nSpecWords, pSes->nSpecWords * 64 ); for ( l = 0; l < pSes->nSpecVars; ++l ) if ( Abc_TtIsTopDecomposable( pSes->pSpec, pMask, pSes->nSpecWords, l ) ) pSes->pDecVars |= ( 1 << l ); } static inline Ses_Man_t * Ses_ManAlloc( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int fMakeAIG, int nBTLimit, int fVerbose ) { int h, i; Ses_Man_t * p = ABC_CALLOC( Ses_Man_t, 1 ); p->pSat = NULL; p->bSpecInv = 0; for ( h = 0; h < nFunc; ++h ) if ( pTruth[h << 2] & 1 ) { for ( i = 0; i < 4; ++i ) pTruth[(h << 2) + i] = ~pTruth[(h << 2) + i]; p->bSpecInv |= ( 1 << h ); } p->pSpec = pTruth; p->nSpecVars = nVars; p->nSpecFunc = nFunc; p->nSpecWords = Abc_TtWordNum( nVars ); p->nRows = ( 1 << nVars ) - 1; p->nMaxDepth = nMaxDepth; p->pArrTimeProfile = nMaxDepth >= 0 ? pArrTimeProfile : NULL; if ( p->pArrTimeProfile ) p->nArrTimeDelta = Abc_NormalizeArrivalTimes( p->pArrTimeProfile, nVars, &p->nArrTimeMax ); else p->nArrTimeDelta = p->nArrTimeMax = 0; p->fMakeAIG = fMakeAIG; p->nBTLimit = nBTLimit; p->fVerbose = fVerbose; p->fVeryVerbose = 0; p->fExtractVerbose = 0; p->fSatVerbose = 0; p->vPolar = Vec_IntAlloc( 100 ); p->vAssump = Vec_IntAlloc( 10 ); p->vStairDecVars = Vec_IntAlloc( nVars ); if ( p->nSpecFunc == 1 ) Ses_ManComputeTopDec( p ); return p; } static inline void Ses_ManCleanLight( Ses_Man_t * pSes ) { int h, i; for ( h = 0; h < pSes->nSpecFunc; ++h ) if ( ( pSes->bSpecInv >> h ) & 1 ) for ( i = 0; i < 4; ++i ) pSes->pSpec[(h << 2) + i] = ~( pSes->pSpec[(h << 2) + i] ); if ( pSes->pArrTimeProfile ) for ( i = 0; i < pSes->nSpecVars; ++i ) pSes->pArrTimeProfile[i] += pSes->nArrTimeDelta; Vec_IntFree( pSes->vPolar ); Vec_IntFree( pSes->vAssump ); Vec_IntFree( pSes->vStairDecVars ); ABC_FREE( pSes ); } static inline void Ses_ManClean( Ses_Man_t * pSes ) { if ( pSes->pSat ) sat_solver_delete( pSes->pSat ); Ses_ManCleanLight( pSes ); } /**Function************************************************************* Synopsis [Access variables based on indexes.] ***********************************************************************/ static inline int Ses_ManSimVar( Ses_Man_t * pSes, int i, int t ) { assert( i < pSes->nGates ); assert( t < pSes->nRows ); return pSes->nSimOffset + pSes->nRows * i + t; } static inline int Ses_ManOutputVar( Ses_Man_t * pSes, int h, int i ) { assert( h < pSes->nSpecFunc ); assert( i < pSes->nGates ); return pSes->nOutputOffset + pSes->nGates * h + i; } static inline int Ses_ManGateVar( Ses_Man_t * pSes, int i, int p, int q ) { assert( i < pSes->nGates ); assert( p < 2 ); assert( q < 2 ); assert( p > 0 || q > 0 ); return pSes->nGateOffset + i * 3 + ( p << 1 ) + q - 1; } static inline int Ses_ManSelectVar( Ses_Man_t * pSes, int i, int j, int k ) { int a; int offset; assert( i < pSes->nGates ); assert( k < pSes->nSpecVars + i ); assert( j < k ); offset = pSes->nSelectOffset; for ( a = pSes->nSpecVars; a < pSes->nSpecVars + i; ++a ) offset += a * ( a - 1 ) / 2; return offset + ( -j * ( 1 + j - 2 * ( pSes->nSpecVars + i ) ) ) / 2 + ( k - j - 1 ); } static inline int Ses_ManDepthVar( Ses_Man_t * pSes, int i, int j ) { assert( i < pSes->nGates ); assert( j <= pSes->nArrTimeMax + i ); return pSes->nDepthOffset + i * pSes->nArrTimeMax + ( ( i * ( i + 1 ) ) / 2 ) + j; } /**Function************************************************************* Synopsis [Compute truth table from a solution.] ***********************************************************************/ static word * Ses_ManDeriveTruth( Ses_Man_t * pSes, char * pSol, int fInvert ) { int i, f, j, k, w, nGates = pSol[ABC_EXACT_SOL_NGATES]; char * p; word * pTruth = NULL, * pTruth0, * pTruth1; assert( pSol[ABC_EXACT_SOL_NFUNC] == 1 ); p = pSol + 3; memset( pSes->pTtObjs, 0, sizeof( word ) * 4 * nGates ); for ( i = 0; i < nGates; ++i ) { f = *p++; assert( *p++ == 2 ); j = *p++; k = *p++; pTruth0 = j < pSes->nSpecVars ? &s_Truths8[j << 2] : &pSes->pTtObjs[( j - pSes->nSpecVars ) << 2]; pTruth1 = k < pSes->nSpecVars ? &s_Truths8[k << 2] : &pSes->pTtObjs[( k - pSes->nSpecVars ) << 2]; pTruth = &pSes->pTtObjs[i << 2]; if ( f & 1 ) for ( w = 0; w < pSes->nSpecWords; ++w ) pTruth[w] |= ~pTruth0[w] & pTruth1[w]; if ( ( f >> 1 ) & 1 ) for ( w = 0; w < pSes->nSpecWords; ++w ) pTruth[w] |= pTruth0[w] & ~pTruth1[w]; if ( ( f >> 2 ) & 1 ) for ( w = 0; w < pSes->nSpecWords; ++w ) pTruth[w] |= pTruth0[w] & pTruth1[w]; } assert( Abc_Lit2Var( *p ) == nGates - 1 ); if ( fInvert && Abc_LitIsCompl( *p ) ) Abc_TtNot( pTruth, pSes->nSpecWords ); return pTruth; } /**Function************************************************************* Synopsis [Setup variables to find network with nGates gates.] ***********************************************************************/ static void Ses_ManCreateVars( Ses_Man_t * pSes, int nGates ) { int i; if ( pSes->fSatVerbose ) { printf( "create variables for network with %d functions over %d variables and %d/%d gates\n", pSes->nSpecFunc, pSes->nSpecVars, nGates, pSes->nMaxGates ); } pSes->nGates = nGates; pSes->nSimVars = nGates * pSes->nRows; pSes->nOutputVars = pSes->nSpecFunc * nGates; pSes->nGateVars = nGates * 3; pSes->nSelectVars = 0; for ( i = pSes->nSpecVars; i < pSes->nSpecVars + nGates; ++i ) pSes->nSelectVars += ( i * ( i - 1 ) ) / 2; pSes->nDepthVars = pSes->nMaxDepth > 0 ? nGates * pSes->nArrTimeMax + ( nGates * ( nGates + 1 ) ) / 2 : 0; /* pSes->nSimOffset = 0; */ /* pSes->nOutputOffset = pSes->nSimVars; */ /* pSes->nGateOffset = pSes->nSimVars + pSes->nOutputVars; */ /* pSes->nSelectOffset = pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars; */ /* pSes->nDepthOffset = pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars + pSes->nSelectVars; */ pSes->nDepthOffset = 0; pSes->nSelectOffset = pSes->nDepthVars; pSes->nGateOffset = pSes->nDepthVars + pSes->nSelectVars; pSes->nOutputOffset = pSes->nDepthVars + pSes->nSelectVars + pSes->nGateVars; pSes->nSimOffset = pSes->nDepthVars + pSes->nSelectVars + pSes->nGateVars + pSes->nOutputVars; /* pSes->nDepthOffset = 0; */ /* pSes->nSelectOffset = pSes->nDepthVars; */ /* pSes->nOutputOffset = pSes->nDepthVars + pSes->nSelectVars; */ /* pSes->nGateOffset = pSes->nDepthVars + pSes->nSelectVars + pSes->nOutputVars; */ /* pSes->nSimOffset = pSes->nDepthVars + pSes->nSelectVars + pSes->nOutputVars + pSes->nGateVars; */ /* if we already have a SAT solver, then restart it (this saves a lot of time) */ if ( pSes->pSat ) sat_solver_restart( pSes->pSat ); else pSes->pSat = sat_solver_new(); sat_solver_setnvars( pSes->pSat, pSes->nSimVars + pSes->nOutputVars + pSes->nGateVars + pSes->nSelectVars + pSes->nDepthVars ); } /**Function************************************************************* Synopsis [Create clauses.] ***********************************************************************/ static inline void Ses_ManGateCannotHaveChild( Ses_Man_t * pSes, int i, int j ) { int k; for ( k = 0; k < j; ++k ) Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, k, j ), 1 ) ); for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ) ); } static inline void Ses_ManCreateMainClause( Ses_Man_t * pSes, int t, int i, int j, int k, int a, int b, int c ) { int pLits[5], ctr = 0; pLits[ctr++] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, i, t ), a ); if ( j < pSes->nSpecVars ) { if ( ( ( ( t + 1 ) & ( 1 << j ) ) ? 1 : 0 ) != b ) return; } else pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, j - pSes->nSpecVars, t ), b ); if ( k < pSes->nSpecVars ) { if ( ( ( ( t + 1 ) & ( 1 << k ) ) ? 1 : 0 ) != c ) return; } else pLits[ctr++] = Abc_Var2Lit( Ses_ManSimVar( pSes, k - pSes->nSpecVars, t ), c ); if ( b > 0 || c > 0 ) pLits[ctr++] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, b, c ), 1 - a ); sat_solver_addclause( pSes->pSat, pLits, pLits + ctr ); } static int inline Ses_ManCreateTruthTableClause( Ses_Man_t * pSes, int t ) { int i, j, k, h; int pLits[3]; for ( i = 0; i < pSes->nGates; ++i ) { /* main clauses */ for ( j = 0; j < pSes->nSpecVars + i; ++j ) for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) { Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 0, 1 ); Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 1, 0 ); Ses_ManCreateMainClause( pSes, t, i, j, k, 0, 1, 1 ); Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 0, 0 ); Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 0, 1 ); Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 1, 0 ); Ses_ManCreateMainClause( pSes, t, i, j, k, 1, 1, 1 ); } /* output clauses */ if ( pSes->nSpecFunc != 1 ) for ( h = 0; h < pSes->nSpecFunc; ++h ) { pLits[0] = Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManSimVar( pSes, i, t ), 1 - Abc_TtGetBit( &pSes->pSpec[h << 2], t + 1 ) ); if ( !sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ) return 0; } } if ( pSes->nSpecFunc == 1 ) Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManSimVar( pSes, pSes->nGates - 1, t ), 1 - Abc_TtGetBit( pSes->pSpec, t + 1 ) ) ); return 1; } static int Ses_ManCreateClauses( Ses_Man_t * pSes ) { extern int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ); int h, i, j, k, t, ii, jj, kk, p, q; int pLits[3]; Vec_Int_t * vLits = NULL; for ( t = 0; t < pSes->nRows; ++t ) { if ( Abc_TtGetBit( pSes->pTtValues, t ) ) if ( !Ses_ManCreateTruthTableClause( pSes, t ) ) return 0; } /* if there is only one output, we know it must point to the last gate */ if ( pSes->nSpecFunc == 1 ) { for ( i = 0; i < pSes->nGates - 1; ++i ) Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManOutputVar( pSes, 0, i ), 1 ) ); Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManOutputVar( pSes, 0, pSes->nGates - 1 ), 0 ) ); vLits = Vec_IntAlloc( 0u ); } else { vLits = Vec_IntAlloc( 0u ); /* some output is selected */ for ( h = 0; h < pSes->nSpecFunc; ++h ) { Vec_IntGrowResize( vLits, pSes->nGates ); for ( i = 0; i < pSes->nGates; ++i ) Vec_IntSetEntry( vLits, i, Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 0 ) ); sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntArray( vLits ) + pSes->nGates ); } } /* each gate has two operands */ for ( i = 0; i < pSes->nGates; ++i ) { Vec_IntGrowResize( vLits, ( ( pSes->nSpecVars + i ) * ( pSes->nSpecVars + i - 1 ) ) / 2 ); jj = 0; for ( j = 0; j < pSes->nSpecVars + i; ++j ) for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) Vec_IntSetEntry( vLits, jj++, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 0 ) ); sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntArray( vLits ) + jj ); } /* gate decomposition (makes it worse) */ /* if ( fDecVariable >= 0 && pSes->nGates >= 2 ) */ /* { */ /* pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, pSes->nGates - 1, fDecVariable, pSes->nSpecVars + pSes->nGates - 2 ), 0 ); */ /* if ( !sat_solver_addclause( pSes->pSat, pLits, pLits + 1 ) ) */ /* { */ /* Vec_IntFree( vLits ); */ /* return 0; */ /* } */ /* for ( k = 1; k < pSes->nSpecVars + pSes->nGates - 1; ++k ) */ /* for ( j = 0; j < k; ++j ) */ /* if ( j != fDecVariable || k != pSes->nSpecVars + pSes->nGates - 2 ) */ /* { */ /* pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, pSes->nGates - 1, j, k ), 1 ); */ /* if ( !sat_solver_addclause( pSes->pSat, pLits, pLits + 1 ) ) */ /* { */ /* Vec_IntFree( vLits ); */ /* return 0; */ /* } */ /* } */ /* } */ /* only AIG */ if ( pSes->fMakeAIG ) { for ( i = 0; i < pSes->nGates; ++i ) { /* not 2 ones */ pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 ); pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 0 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ); pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 0 ); pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ); pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 0 ); pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 ); pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ); } } /* only binary clauses */ if ( 1 ) /* TODO: add some meaningful parameter */ { for ( i = 0; i < pSes->nGates; ++i ) { pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 0 ); pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 0 ); pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 0 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ); pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 0 ); pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ); pLits[0] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 0, 1 ), 0 ); pLits[1] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 0 ), 1 ); pLits[2] = Abc_Var2Lit( Ses_ManGateVar( pSes, i, 1, 1 ), 1 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ); } for ( i = 0; i < pSes->nGates; ++i ) for ( k = 1; k < pSes->nSpecVars + i; ++k ) for ( j = 0; j < k; ++j ) { pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); for ( kk = 1; kk < pSes->nSpecVars + i; ++kk ) for ( jj = 0; jj < kk; ++jj ) { if ( k == kk && j == jj ) continue; pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, jj, kk ), 1 ); if ( pLits[0] < pLits[1] ) sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ); } } /* Vec_IntGrowResize( vLits, pSes->nGates * ( pSes->nSpecVars + pSes->nGates - 2 ) ); */ /* for ( j = 0; j < pSes->nSpecVars; ++j ) */ /* { */ /* jj = 0; */ /* for ( i = 0; i < pSes->nGates; ++i ) */ /* { */ /* for ( k = 0; k < j; ++k ) */ /* Vec_IntSetEntry( vLits, jj++, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, k, j ), 0 ) ); */ /* for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) */ /* Vec_IntSetEntry( vLits, jj++, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 0 ) ); */ /* } */ /* sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntArray( vLits ) + jj ); */ /* } */ } /* EXTRA stair decomposition */ if (Vec_IntSize( pSes->vStairDecVars ) ) { Vec_IntForEachEntry( pSes->vStairDecVars, j, i ) { if ( pSes->nGates - 2 - i < j ) { continue; } Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManSelectVar( pSes, pSes->nGates - 1 - i, j, pSes->nSpecVars + pSes->nGates - 2 - i ), 0 ) ); //printf( "dec %d for var %d\n", pSes->pStairDecFunc[i], j ); switch ( pSes->pStairDecFunc[i] ) { case 1: /* AND(x,g) */ Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 0, 1 ), 1 ) ); //Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 0 ), 1 ) ); //Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 1 ), 0 ) ); break; case 2: /* AND(!x,g) */ //Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 0, 1 ), 0 ) ); Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 0 ), 1 ) ); Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 1 ), 1 ) ); break; case 3: /* OR(x,g) */ //Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 0, 1 ), 0 ) ); Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 0 ), 0 ) ); Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 1 ), 0 ) ); break; case 4: /* OR(!x,g) */ ////Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 0, 1 ), 0 ) ); ////Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 0 ), 1 ) ); ////Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 1 ), 0 ) ); break; case 5: /* XOR(x,g) */ Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 0, 1 ), 0 ) ); Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 0 ), 0 ) ); Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManGateVar( pSes, pSes->nGates - 1 - i, 1, 1 ), 1 ) ); break; default: printf( "func: %d\n", pSes->pStairDecFunc[i] ); assert( 0 ); } } } /* EXTRA clauses: use gate i at least once */ Vec_IntGrowResize( vLits, pSes->nSpecFunc + pSes->nGates * ( pSes->nSpecVars + pSes->nGates - 2 ) ); for ( i = 0; i < pSes->nGates; ++i ) { jj = 0; for ( h = 0; h < pSes->nSpecFunc; ++h ) Vec_IntSetEntry( vLits, jj++, Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 0 ) ); for ( ii = i + 1; ii < pSes->nGates; ++ii ) { for ( j = 0; j < pSes->nSpecVars + i; ++j ) Vec_IntSetEntry( vLits, jj++, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, j, pSes->nSpecVars + i ), 0 ) ); for ( j = pSes->nSpecVars + i + 1; j < pSes->nSpecVars + ii; ++j ) Vec_IntSetEntry( vLits, jj++, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, pSes->nSpecVars + i, j ), 0 ) ); } sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntArray( vLits ) + jj ); } Vec_IntFree( vLits ); /* EXTRA clauses: co-lexicographic order */ for ( i = 0; i < pSes->nGates - 1; ++i ) { for ( k = 2; k < pSes->nSpecVars + i; ++k ) { for ( j = 1; j < k; ++j ) for ( jj = 0; jj < j; ++jj ) { pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i + 1, jj, k ), 1 ); } for ( j = 0; j < k; ++j ) for ( kk = 1; kk < k; ++kk ) for ( jj = 0; jj < kk; ++jj ) { pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i + 1, jj, kk ), 1 ); } } } /* EXTRA clauses: symmetric variables */ if ( /*pSes->nMaxDepth == -1 &&*/ pSes->nSpecFunc == 1 ) /* only check if there is one output function */ for ( q = 1; q < pSes->nSpecVars; ++q ) for ( p = 0; p < q; ++p ) if ( Extra_TruthVarsSymm( (unsigned*)( pSes->pSpec ), pSes->nSpecVars, p, q ) && ( !pSes->pArrTimeProfile || ( pSes->pArrTimeProfile[p] <= pSes->pArrTimeProfile[q] ) ) ) { if ( pSes->fSatVerbose ) printf( "variables %d and %d are symmetric\n", p, q ); for ( i = 0; i < pSes->nGates; ++i ) for ( j = 0; j < q; ++j ) { if ( j == p ) continue; vLits = Vec_IntAlloc( 0 ); Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, q ), 1 ) ); for ( ii = 0; ii < i; ++ii ) for ( kk = 1; kk < pSes->nSpecVars + ii; ++kk ) for ( jj = 0; jj < kk; ++jj ) if ( jj == p || kk == p ) Vec_IntPush( vLits, Abc_Var2Lit( Ses_ManSelectVar( pSes, ii, jj, kk ), 0 ) ); sat_solver_addclause( pSes->pSat, Vec_IntArray( vLits ), Vec_IntLimit( vLits ) ); Vec_IntFree( vLits ); } } return 1; } static int Ses_ManCreateDepthClauses( Ses_Man_t * pSes ) { int i, j, k, jj, kk, d, h; int pLits[3]; for ( i = 0; i < pSes->nGates; ++i ) { /* propagate depths from children */ for ( k = 1; k < i; ++k ) for ( j = 0; j < k; ++j ) { pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, pSes->nSpecVars + j, pSes->nSpecVars + k ), 1 ); for ( jj = 0; jj <= pSes->nArrTimeMax + j; ++jj ) { pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, j, jj ), 1 ); pLits[2] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, jj + 1 ), 0 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ); } } for ( k = 0; k < i; ++k ) for ( j = 0; j < pSes->nSpecVars + k; ++j ) { pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, pSes->nSpecVars + k ), 1 ); for ( kk = 0; kk <= pSes->nArrTimeMax + k; ++kk ) { pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, k, kk ), 1 ); pLits[2] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, kk + 1 ), 0 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 3 ); } } /* propagate depths from arrival times at PIs */ if ( pSes->pArrTimeProfile ) { for ( k = 1; k < pSes->nSpecVars + i; ++k ) for ( j = 0; j < ( ( k < pSes->nSpecVars ) ? k : pSes->nSpecVars ); ++j ) { d = pSes->pArrTimeProfile[j]; if ( k < pSes->nSpecVars && pSes->pArrTimeProfile[k] > d ) d = pSes->pArrTimeProfile[k]; pLits[0] = Abc_Var2Lit( Ses_ManSelectVar( pSes, i, j, k ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, d ), 0 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ); } } else /* arrival times are 0 */ Vec_IntPush( pSes->vAssump, Abc_Var2Lit( Ses_ManDepthVar( pSes, i, 0 ), 0 ) ); /* reverse order encoding of depth variables */ for ( j = 1; j <= pSes->nArrTimeMax + i; ++j ) { pLits[0] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, j ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, j - 1 ), 0 ); sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ); } /* constrain maximum depth */ if ( pSes->nMaxDepth < pSes->nArrTimeMax + i ) for ( h = 0; h < pSes->nSpecFunc; ++h ) { pLits[0] = Abc_Var2Lit( Ses_ManOutputVar( pSes, h, i ), 1 ); pLits[1] = Abc_Var2Lit( Ses_ManDepthVar( pSes, i, pSes->nMaxDepth ), 1 ); if ( !sat_solver_addclause( pSes->pSat, pLits, pLits + 2 ) ) return 0; } } return 1; } /**Function************************************************************* Synopsis [Solve.] ***********************************************************************/ static inline double Sat_Wrd2Dbl( word w ) { return (double)(unsigned)(w&0x3FFFFFFF) + (double)(1<<30)*(unsigned)(w>>30); } static inline int Ses_ManSolve( Ses_Man_t * pSes ) { int status; abctime timeStart, timeDelta; if ( pSes->fSatVerbose ) { printf( "SAT CL: %7d VA: %5d", sat_solver_nclauses( pSes->pSat ), sat_solver_nvars( pSes->pSat ) ); fflush( stdout ); } timeStart = Abc_Clock(); status = sat_solver_solve( pSes->pSat, Vec_IntArray( pSes->vAssump ), Vec_IntLimit( pSes->vAssump ), pSes->nBTLimit, 0, 0, 0 ); timeDelta = Abc_Clock() - timeStart; if ( pSes->fSatVerbose ) printf( " RE: %2d ST: %4.f CO: %7.0f DE: %6.0f PR: %6.0f\n", status, Sat_Wrd2Dbl( pSes->pSat->stats.starts ), Sat_Wrd2Dbl( pSes->pSat->stats.conflicts ), Sat_Wrd2Dbl( pSes->pSat->stats.decisions ), Sat_Wrd2Dbl( pSes->pSat->stats.propagations ) ); //Sat_SolverPrintStats( stdout, pSes->pSat ); pSes->timeSat += timeDelta; if ( status == l_True ) { pSes->nSatCalls++; pSes->timeSatSat += timeDelta; return 1; } else if ( status == l_False ) { pSes->nUnsatCalls++; pSes->timeSatUnsat += timeDelta; return 0; } else { pSes->nUndefCalls++; pSes->timeSatUndef += timeDelta; if ( pSes->fSatVerbose ) { printf( "resource limit reached\n" ); } return 2; } } /**Function************************************************************* Synopsis [Extract solution.] ***********************************************************************/ // char is an array of short integers that stores the synthesized network // using the following format // | nvars | nfunc | ngates | gate[1] | ... | gate[ngates] | func[1] | .. | func[nfunc] | // nvars: integer with number of variables // nfunc: integer with number of functions // ngates: integer with number of gates // gate[i]: | op | nfanin | fanin[1] | ... | fanin[nfanin] | // op: integer of gate's truth table (divided by 2, because gate is normal) // nfanin: integer with number of fanins // fanin[i]: integer to primary input or other gate // func[i]: | fanin | delay | pin[1] | ... | pin[nvars] | // fanin: integer as literal to some gate (not primary input), can be complemented // delay: maximum delay to output (taking arrival times into account, not normalized) or 0 if not specified // pin[i]: pin to pin delay to input i or 0 if not specified or if there is no connection to input i // NOTE: since outputs can only point to gates, delay and pin-to-pin times cannot be 0 static char * Ses_ManExtractSolution( Ses_Man_t * pSes ) { int nSol, h, i, j, k, l, aj, ak, d, nOp; char * pSol, * p; int * pPerm = NULL; /* will be a 2d array [i][l] where is is gate id and l is PI id */ /* compute length of solution, for now all gates have 2 inputs */ nSol = 3 + pSes->nGates * 4 + pSes->nSpecFunc * ( 2 + pSes->nSpecVars ); p = pSol = ABC_CALLOC( char, nSol ); /* header */ *p++ = pSes->nSpecVars; *p++ = pSes->nSpecFunc; *p++ = pSes->nGates; /* gates */ for ( i = 0; i < pSes->nGates; ++i ) { nOp = sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 0, 1 ) ); nOp |= sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 1, 0 ) ) << 1; nOp |= sat_solver_var_value( pSes->pSat, Ses_ManGateVar( pSes, i, 1, 1 ) ) << 2; *p++ = nOp; *p++ = 2; if ( pSes->fExtractVerbose ) printf( "add gate %d with operation %d", pSes->nSpecVars + i, nOp ); for ( k = 0; k < pSes->nSpecVars + i; ++k ) for ( j = 0; j < k; ++j ) if ( sat_solver_var_value( pSes->pSat, Ses_ManSelectVar( pSes, i, j, k ) ) ) { if ( pSes->fExtractVerbose ) printf( " and operands %d and %d", j, k ); *p++ = j; *p++ = k; k = pSes->nSpecVars + i; break; } if ( pSes->fExtractVerbose ) { if ( pSes->nMaxDepth > 0 ) { printf( " and depth vector " ); for ( j = 0; j <= pSes->nArrTimeMax + i; ++j ) printf( "%d", sat_solver_var_value( pSes->pSat, Ses_ManDepthVar( pSes, i, j ) ) ); } printf( "\n" ); } } /* pin-to-pin delay */ if ( pSes->nMaxDepth != -1 ) { pPerm = ABC_CALLOC( int, pSes->nGates * pSes->nSpecVars ); for ( i = 0; i < pSes->nGates; ++i ) { /* since all gates are binary for now */ j = pSol[3 + i * 4 + 2]; k = pSol[3 + i * 4 + 3]; for ( l = 0; l < pSes->nSpecVars; ++l ) { /* pin-to-pin delay to input l of child nodes */ aj = j < pSes->nSpecVars ? 0 : pPerm[(j - pSes->nSpecVars) * pSes->nSpecVars + l]; ak = k < pSes->nSpecVars ? 0 : pPerm[(k - pSes->nSpecVars) * pSes->nSpecVars + l]; if ( aj == 0 && ak == 0 ) pPerm[i * pSes->nSpecVars + l] = ( l == j || l == k ) ? 1 : 0; else pPerm[i * pSes->nSpecVars + l] = Abc_MaxInt( aj, ak ) + 1; } } } /* outputs */ for ( h = 0; h < pSes->nSpecFunc; ++h ) for ( i = 0; i < pSes->nGates; ++i ) if ( sat_solver_var_value( pSes->pSat, Ses_ManOutputVar( pSes, h, i ) ) ) { *p++ = Abc_Var2Lit( i, ( pSes->bSpecInv >> h ) & 1 ); d = 0; if ( pSes->nMaxDepth != -1 ) for ( l = 0; l < pSes->nSpecVars; ++l ) { if ( pSes->pArrTimeProfile ) d = Abc_MaxInt( d, pSes->pArrTimeProfile[l] + pPerm[i * pSes->nSpecVars + l] ); else d = Abc_MaxInt( d, pPerm[i * pSes->nSpecVars + l] ); } *p++ = d; if ( pSes->pArrTimeProfile && pSes->fExtractVerbose ) printf( "output %d points to gate %d and has normalized delay %d (nArrTimeDelta = %d)\n", h, pSes->nSpecVars + i, d, pSes->nArrTimeDelta ); for ( l = 0; l < pSes->nSpecVars; ++l ) { d = ( pSes->nMaxDepth != -1 ) ? pPerm[i * pSes->nSpecVars + l] : 0; if ( pSes->pArrTimeProfile && pSes->fExtractVerbose ) printf( " pin-to-pin arrival time from input %d is %d (pArrTimeProfile = %d)\n", l, d, pSes->pArrTimeProfile[l] ); *p++ = d; } } /* pin-to-pin delays */ if ( pSes->nMaxDepth != -1 ) ABC_FREE( pPerm ); /* have we used all the fields? */ assert( ( p - pSol ) == nSol ); /* printf( "found network: " ); */ /* Abc_TtPrintHexRev( stdout, Ses_ManDeriveTruth( pSes, pSol, 1 ), pSes->nSpecVars ); */ /* printf( "\n" ); */ return pSol; } static Abc_Ntk_t * Ses_ManExtractNtk( char const * pSol ) { int h, i; char const * p; Abc_Ntk_t * pNtk; Abc_Obj_t * pObj; Vec_Ptr_t * pGates, * vNames; char pGateTruth[5]; char * pSopCover; pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); pNtk->pName = Extra_UtilStrsav( "exact" ); pGates = Vec_PtrAlloc( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] ); pGateTruth[3] = '0'; pGateTruth[4] = '\0'; vNames = Abc_NodeGetFakeNames( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NFUNC] ); /* primary inputs */ Vec_PtrPush( pNtk->vObjs, NULL ); for ( i = 0; i < pSol[ABC_EXACT_SOL_NVARS]; ++i ) { pObj = Abc_NtkCreatePi( pNtk ); Abc_ObjAssignName( pObj, (char*)Vec_PtrEntry( vNames, i ), NULL ); Vec_PtrPush( pGates, pObj ); } /* gates */ p = pSol + 3; for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) { pGateTruth[2] = '0' + ( *p & 1 ); pGateTruth[1] = '0' + ( ( *p >> 1 ) & 1 ); pGateTruth[0] = '0' + ( ( *p >> 2 ) & 1 ); ++p; assert( *p == 2 ); /* binary gate */ ++p; pSopCover = Abc_SopFromTruthBin( pGateTruth ); pObj = Abc_NtkCreateNode( pNtk ); pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSopCover ); Vec_PtrPush( pGates, pObj ); ABC_FREE( pSopCover ); Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); } /* outputs */ for ( h = 0; h < pSol[ABC_EXACT_SOL_NFUNC]; ++h ) { pObj = Abc_NtkCreatePo( pNtk ); Abc_ObjAssignName( pObj, (char*)Vec_PtrEntry( vNames, pSol[ABC_EXACT_SOL_NVARS] + h ), NULL ); if ( Abc_LitIsCompl( *p ) ) Abc_ObjAddFanin( pObj, Abc_NtkCreateNodeInv( pNtk, (Abc_Obj_t *)Vec_PtrEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ) ) ); else Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ) ); p += ( 2 + pSol[ABC_EXACT_SOL_NVARS] ); } Abc_NodeFreeNames( vNames ); Vec_PtrFree( pGates ); if ( !Abc_NtkCheck( pNtk ) ) printf( "Ses_ManExtractSolution(): Network check has failed.\n" ); return pNtk; } static Gia_Man_t * Ses_ManExtractGia( char const * pSol ) { int h, i; char const * p; Gia_Man_t * pGia; Vec_Int_t * pGates; Vec_Ptr_t * vNames; int nObj, nChild1, nChild2, fChild1Comp, fChild2Comp; pGia = Gia_ManStart( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] + pSol[ABC_EXACT_SOL_NFUNC] + 1 ); pGia->nConstrs = 0; pGia->pName = Extra_UtilStrsav( "exact" ); pGates = Vec_IntAlloc( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NGATES] ); vNames = Abc_NodeGetFakeNames( pSol[ABC_EXACT_SOL_NVARS] + pSol[ABC_EXACT_SOL_NFUNC] ); /* primary inputs */ pGia->vNamesIn = Vec_PtrStart( pSol[ABC_EXACT_SOL_NVARS] ); for ( i = 0; i < pSol[ABC_EXACT_SOL_NVARS]; ++i ) { nObj = Gia_ManAppendCi( pGia ); Vec_IntPush( pGates, nObj ); Vec_PtrSetEntry( pGia->vNamesIn, i, Extra_UtilStrsav( (const char*)Vec_PtrEntry( vNames, i ) ) ); } /* gates */ p = pSol + 3; for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) { assert( p[1] == 2 ); nChild1 = Vec_IntEntry( pGates, p[2] ); nChild2 = Vec_IntEntry( pGates, p[3] ); fChild1Comp = fChild2Comp = 0; if ( *p & 1 ) { nChild1 = Abc_LitNot( nChild1 ); fChild1Comp = 1; } if ( ( *p >> 1 ) & 1 ) { nChild2 = Abc_LitNot( nChild2 ); fChild2Comp = 1; } nObj = Gia_ManAppendAnd( pGia, nChild1, nChild2 ); if ( fChild1Comp && fChild2Comp ) { assert( ( *p >> 2 ) & 1 ); nObj = Abc_LitNot( nObj ); } Vec_IntPush( pGates, nObj ); p += 4; } /* outputs */ pGia->vNamesOut = Vec_PtrStart( pSol[ABC_EXACT_SOL_NFUNC] ); for ( h = 0; h < pSol[ABC_EXACT_SOL_NFUNC]; ++h ) { nObj = Vec_IntEntry( pGates, pSol[ABC_EXACT_SOL_NVARS] + Abc_Lit2Var( *p ) ); if ( Abc_LitIsCompl( *p ) ) nObj = Abc_LitNot( nObj ); Gia_ManAppendCo( pGia, nObj ); Vec_PtrSetEntry( pGia->vNamesOut, h, Extra_UtilStrsav( (const char*)Vec_PtrEntry( vNames, pSol[ABC_EXACT_SOL_NVARS] + h ) ) ); p += ( 2 + pSol[ABC_EXACT_SOL_NVARS] ); } Abc_NodeFreeNames( vNames ); Vec_IntFree( pGates ); return pGia; } /**Function************************************************************* Synopsis [Debug.] ***********************************************************************/ static void Ses_ManPrintRuntime( Ses_Man_t * pSes ) { printf( "Runtime breakdown:\n" ); ABC_PRTP( "Sat ", pSes->timeSat, pSes->timeTotal ); ABC_PRTP( " Sat ", pSes->timeSatSat, pSes->timeTotal ); ABC_PRTP( " Unsat ", pSes->timeSatUnsat, pSes->timeTotal ); ABC_PRTP( " Undef ", pSes->timeSatUndef, pSes->timeTotal ); ABC_PRTP( "Instance", pSes->timeInstance, pSes->timeTotal ); ABC_PRTP( "ALL ", pSes->timeTotal, pSes->timeTotal ); } static inline void Ses_ManPrintFuncs( Ses_Man_t * pSes ) { int h; printf( "find optimum circuit for %d %d-variable functions:\n", pSes->nSpecFunc, pSes->nSpecVars ); for ( h = 0; h < pSes->nSpecFunc; ++h ) { printf( " func %d: ", h + 1 ); Abc_TtPrintHexRev( stdout, &pSes->pSpec[h >> 2], pSes->nSpecVars ); printf( "\n" ); } if ( pSes->nMaxDepth != -1 ) { printf( " max depth = %d\n", pSes->nMaxDepth ); if ( pSes->pArrTimeProfile ) { printf( " arrival times =" ); for ( h = 0; h < pSes->nSpecVars; ++h ) printf( " %d", pSes->pArrTimeProfile[h] ); printf( "\n" ); } } } static inline void Ses_ManPrintVars( Ses_Man_t * pSes ) { int h, i, j, k, p, q, t; for ( i = 0; i < pSes->nGates; ++i ) for ( t = 0; t < pSes->nRows; ++t ) printf( "x(%d, %d) : %d\n", i, t, Ses_ManSimVar( pSes, i, t ) ); for ( h = 0; h < pSes->nSpecFunc; ++h ) for ( i = 0; i < pSes->nGates; ++i ) printf( "h(%d, %d) : %d\n", h, i, Ses_ManOutputVar( pSes, h, i ) ); for ( i = 0; i < pSes->nGates; ++i ) for ( p = 0; p <= 1; ++p ) for ( q = 0; q <= 1; ++ q) { if ( p == 0 && q == 0 ) { continue; } printf( "f(%d, %d, %d) : %d\n", i, p, q, Ses_ManGateVar( pSes, i, p, q ) ); } for ( i = 0; i < pSes->nGates; ++i ) for ( j = 0; j < pSes->nSpecVars + i; ++j ) for ( k = j + 1; k < pSes->nSpecVars + i; ++k ) printf( "s(%d, %d, %d) : %d\n", i, j, k, Ses_ManSelectVar( pSes, i, j, k ) ); if ( pSes->nMaxDepth > 0 ) for ( i = 0; i < pSes->nGates; ++i ) for ( j = 0; j <= i; ++j ) printf( "d(%d, %d) : %d\n", i, j, Ses_ManDepthVar( pSes, i, j ) ); } /**Function************************************************************* Synopsis [Synthesis algorithm.] ***********************************************************************/ static void Ses_ManComputeMaxGates( Ses_Man_t * pSes ) { int s = 1, lvl = pSes->nMaxDepth, avail = pSes->nSpecVars, l; pSes->nMaxGates = 0; /* s is the number of gates we have in the current level */ while ( s && /* while there are nodes to branch from */ lvl && /* while we are at some level */ avail * 2 > s /* while there are still enough available nodes (heuristic) */ ) { /* erase from s if we have arriving nodes */ for ( l = 0; l < pSes->nSpecVars; ++l ) if ( pSes->pArrTimeProfile[l] == lvl ) { --s; --avail; } --lvl; pSes->nMaxGates += s; s *= 2; } } // returns 0, if current max depth and arrival times are not consistent static int Ses_CheckDepthConsistency( Ses_Man_t * pSes ) { int l, i, fAdded, nLevel; int fMaxGatesLevel2 = 1; Vec_IntClear( pSes->vStairDecVars ); pSes->fDecStructure = 0; for ( l = 0; l < pSes->nSpecVars; ++l ) { if ( pSes->pArrTimeProfile[l] >= pSes->nMaxDepth ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible arrival time (depth = %d, input = %d, arrival time = %d)", pSes->nMaxDepth, l, pSes->pArrTimeProfile[l] ); return 0; } else if ( pSes->nSpecFunc == 1 && pSes->pArrTimeProfile[l] + 1 == pSes->nMaxDepth ) { if ( ( pSes->fDecStructure == 1 && pSes->nSpecVars > 2 ) || pSes->fDecStructure == 2 ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible decomposition (depth = %d, input = %d, arrival time = %d)", pSes->nMaxDepth, l, pSes->pArrTimeProfile[l] ); return 0; } pSes->fDecStructure++; /* A subset B <=> A and B = A */ if ( !( ( pSes->pDecVars >> l ) & 1 ) ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible decomposition (depth = %d, input = %d, arrival time = %d)", pSes->nMaxDepth, l, pSes->pArrTimeProfile[l] ); return 0; } } } /* more complicated decomposition */ if ( pSes->fDecStructure ) { nLevel = 1; while ( 1 ) { fAdded = 0; for ( l = 0; l < pSes->nSpecVars; ++l ) if ( pSes->pArrTimeProfile[l] + nLevel == pSes->nMaxDepth ) { if ( fAdded ) { assert( nLevel == Vec_IntSize( pSes->vStairDecVars ) ); if ( fAdded > 1 || ( nLevel + 1 < pSes->nSpecVars ) ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible decomposition at level %d", nLevel ); return 0; } } else { Vec_IntPush( pSes->vStairDecVars, l ); } fAdded++; } if ( !fAdded ) break; ++nLevel; } if ( Vec_IntSize( pSes->vStairDecVars ) && !Abc_TtIsStairDecomposable( pSes->pSpec, pSes->nSpecWords, Vec_IntArray( pSes->vStairDecVars ), Vec_IntSize( pSes->vStairDecVars ), pSes->pStairDecFunc ) ) { if ( pSes->fReasonVerbose ) { printf( "give up due to impossible stair decomposition at level %d: ", nLevel ); Vec_IntPrint( pSes->vStairDecVars ); } return 0; } } /* check if depth's match with structure at second level from top */ if ( pSes->fDecStructure ) fMaxGatesLevel2 = ( pSes->nSpecVars == 3 ) ? 2 : 1; else fMaxGatesLevel2 = ( pSes->nSpecVars == 4 ) ? 4 : 3; i = 0; for ( l = 0; l < pSes->nSpecVars; ++l ) if ( pSes->pArrTimeProfile[l] + 2 == pSes->nMaxDepth ) if ( ++i > fMaxGatesLevel2 ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible decomposition at second level (depth = %d, input = %d, arrival time = %d)", pSes->nMaxDepth, l, pSes->pArrTimeProfile[l] ); return 0; } /* check if depth's match with structure at third level from top */ if ( pSes->nSpecVars > 4 && pSes->fDecStructure && i == 1 ) /* we have f = AND(x_i, AND(x_j, g)) (x_i and x_j may be complemented) */ { i = 0; for ( l = 0; l < pSes->nSpecVars; ++l ) if ( pSes->pArrTimeProfile[l] + 3 == pSes->nMaxDepth ) if ( ++i > 1 ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible decomposition at third level (depth = %d, input = %d, arrival time = %d)", pSes->nMaxDepth, l, pSes->pArrTimeProfile[l] ); return 0; } } return 1; } // returns 0, if current max depth and #gates are not consistent static int Ses_CheckGatesConsistency( Ses_Man_t * pSes, int nGates ) { /* give up if number of gates is impossible for given depth */ if ( pSes->nMaxDepth != -1 && nGates >= ( 1 << pSes->nMaxDepth ) ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible depth (depth = %d, gates = %d)", pSes->nMaxDepth, nGates ); return 0; } /* give up if number of gates is impossible for given depth and arrival times */ if ( pSes->nMaxDepth != -1 && pSes->pArrTimeProfile && nGates > pSes->nMaxGates ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible depth and arrival times (depth = %d, gates = %d)", pSes->nMaxDepth, nGates ); return 0; } if ( pSes->fDecStructure && nGates >= ( 1 << ( pSes->nMaxDepth - 1 ) ) + 1 ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible depth in AND-dec structure (depth = %d, gates = %d)", pSes->nMaxDepth, nGates ); return 0; } /* give up if number of gates gets practically too large */ if ( nGates >= ( 1 << pSes->nSpecVars ) ) { if ( pSes->fReasonVerbose ) printf( "give up due to impossible number of gates" ); return 0; } return 1; } static void Abc_ExactCopyDepthAndArrivalTimes( int nVars, int nDepthFrom, int * nDepthTo, int * pTimesFrom, int * pTimesTo ) { int l; *nDepthTo = nDepthFrom; for ( l = 0; l < nVars; ++l ) pTimesTo[l] = pTimesFrom[l]; } static void Ses_ManStoreDepthAndArrivalTimes( Ses_Man_t * pSes ) { if ( pSes->nMaxDepth == -1 ) return; Abc_ExactCopyDepthAndArrivalTimes( pSes->nSpecVars, pSes->nMaxDepth, &pSes->nMaxDepthTmp, pSes->pArrTimeProfile, pSes->pArrTimeProfileTmp ); } static void Ses_ManRestoreDepthAndArrivalTimes( Ses_Man_t * pSes ) { if ( pSes->nMaxDepth == -1 ) return; Abc_ExactCopyDepthAndArrivalTimes( pSes->nSpecVars, pSes->nMaxDepthTmp, &pSes->nMaxDepth, pSes->pArrTimeProfileTmp, pSes->pArrTimeProfile ); } static void Abc_ExactAdjustDepthAndArrivalTimes( int nVars, int nGates, int nDepthFrom, int * nDepthTo, int * pTimesFrom, int * pTimesTo, int nTimesMax ) { int l; *nDepthTo = Abc_MinInt( nDepthFrom, nGates ); for ( l = 0; l < nVars; ++l ) pTimesTo[l] = Abc_MinInt( pTimesFrom[l], Abc_MaxInt( 0, nGates - 1 - nTimesMax + pTimesFrom[l] ) ); } static void Ses_AdjustDepthAndArrivalTimes( Ses_Man_t * pSes, int nGates ) { Abc_ExactAdjustDepthAndArrivalTimes( pSes->nSpecVars, nGates, pSes->nMaxDepthTmp, &pSes->nMaxDepth, pSes->pArrTimeProfileTmp, pSes->pArrTimeProfile, pSes->nArrTimeMax - 1 ); } /* return: (2: continue, 1: found, 0: gave up) */ static int Ses_ManFindNetworkExact( Ses_Man_t * pSes, int nGates ) { int f, fSat; abctime timeStart; /* solve */ timeStart = Abc_Clock(); Vec_IntClear( pSes->vPolar ); Vec_IntClear( pSes->vAssump ); Ses_ManCreateVars( pSes, nGates ); if ( pSes->nMaxDepth != -1 ) { f = Ses_ManCreateDepthClauses( pSes ); pSes->timeInstance += ( Abc_Clock() - timeStart ); if ( !f ) return 2; /* proven UNSAT while creating clauses */ } sat_solver_set_polarity( pSes->pSat, Vec_IntArray( pSes->vPolar ), Vec_IntSize( pSes->vPolar ) ); /* first solve */ fSat = Ses_ManSolve( pSes ); if ( fSat == 0 ) return 2; /* UNSAT, continue with next # of gates */ else if ( fSat == 2 ) { pSes->fHitResLimit = 1; return 0; } timeStart = Abc_Clock(); f = Ses_ManCreateClauses( pSes ); pSes->timeInstance += ( Abc_Clock() - timeStart ); if ( !f ) return 2; /* proven UNSAT while creating clauses */ fSat = Ses_ManSolve( pSes ); if ( fSat == 1 ) return 1; else if ( fSat == 2 ) { pSes->fHitResLimit = 1; return 0; } return 2; /* UNSAT continue */ } // is there a network for a given number of gates /* return: (3: impossible, 2: continue, 1: found, 0: gave up) */ static int Ses_ManFindNetworkExactCEGAR( Ses_Man_t * pSes, int nGates, char ** pSol ) { int fRes, iMint, fSat; word pTruth[4]; /* debug */ Abc_DebugErase( pSes->nDebugOffset + ( nGates > 10 ? 5 : 4 ), pSes->fVeryVerbose ); Abc_DebugPrintIntInt( " (%d/%d)", nGates, pSes->nMaxGates, pSes->fVeryVerbose ); /* do #gates and max depth allow for a network? */ if ( !Ses_CheckGatesConsistency( pSes, nGates ) ) return 3; fRes = Ses_ManFindNetworkExact( pSes, nGates ); if ( fRes != 1 ) return fRes; while ( true ) { *pSol = Ses_ManExtractSolution( pSes ); Abc_TtXor( pTruth, Ses_ManDeriveTruth( pSes, *pSol, 0 ), pSes->pSpec, pSes->nSpecWords, 0 ); iMint = Abc_TtFindFirstBit( pTruth, pSes->nSpecVars ); if ( iMint == -1 ) { assert( fRes == 1 ); return 1; } ABC_FREE( *pSol ); //Abc_TtSetBit( pSes->pTtValues, iMint - 1 ); if ( !Ses_ManCreateTruthTableClause( pSes, iMint - 1 ) ) /* UNSAT, continue */ return 2; if ( ( fSat = Ses_ManSolve( pSes ) ) == 1 ) continue; return ( fSat == 2 ) ? 0 : 2; } } // find minimum size by increasing the number of gates static char * Ses_ManFindMinimumSizeBottomUp( Ses_Man_t * pSes ) { int nGates = pSes->nStartGates, fRes; char * pSol = NULL; /* store whether call was unsuccessful due to resource limit and not due to impossible constraint */ pSes->fHitResLimit = 0; pSes->nDebugOffset = pSes->nMaxGates >= 10 ? 3 : 2; /* adjust number of gates if there is a stair decomposition */ if ( Vec_IntSize( pSes->vStairDecVars ) ) nGates = Abc_MaxInt( nGates, Vec_IntSize( pSes->vStairDecVars ) - 1 ); //Ses_ManStoreDepthAndArrivalTimes( pSes ); memset( pSes->pTtValues, 0, 4 * sizeof( word ) ); Abc_DebugPrintIntInt( " (%d/%d)", nGates, pSes->nMaxGates, pSes->fVeryVerbose ); while ( true ) { ++nGates; fRes = Ses_ManFindNetworkExactCEGAR( pSes, nGates, &pSol ); if ( fRes == 0 ) { pSes->fHitResLimit = 1; break; } else if ( fRes == 1 || fRes == 3 ) break; } Abc_DebugErase( pSes->nDebugOffset + ( nGates >= 10 ? 5 : 4 ), pSes->fVeryVerbose ); return pSol; } static char * Ses_ManFindMinimumSizeTopDown( Ses_Man_t * pSes, int nMinGates ) { int nGates = pSes->nMaxGates, fRes; char * pSol = NULL, * pSol2 = NULL; pSes->fHitResLimit = 0; Abc_DebugPrintIntInt( " (%d/%d)", nGates, pSes->nMaxGates, pSes->fVeryVerbose ); while ( true ) { fRes = Ses_ManFindNetworkExactCEGAR( pSes, nGates, &pSol2 ); if ( fRes == 0 ) { pSes->fHitResLimit = 1; break; } else if ( fRes == 2 || fRes == 3 ) break; pSol = pSol2; if ( nGates == nMinGates ) break; --nGates; } Abc_DebugErase( pSes->nDebugOffset + ( nGates >= 10 ? 5 : 4 ), pSes->fVeryVerbose ); return pSol; } static char * Ses_ManFindMinimumSize( Ses_Man_t * pSes ) { char * pSol; /* do the arrival times allow for a network? */ if ( pSes->nMaxDepth != -1 && pSes->pArrTimeProfile ) { if ( !Ses_CheckDepthConsistency( pSes ) ) return 0; Ses_ManComputeMaxGates( pSes ); } pSol = Ses_ManFindMinimumSizeBottomUp( pSes ); if ( !pSol && pSes->fHitResLimit && pSes->nGates != pSes->nMaxGates ) return Ses_ManFindMinimumSizeTopDown( pSes, pSes->nGates + 1 ); else return pSol; } /**Function************************************************************* Synopsis [Find minimum size networks with a SAT solver.] Description [If nMaxDepth is -1, then depth constraints are ignored. If nMaxDepth is not -1, one can set pArrTimeProfile which should have the length of nVars. One can ignore pArrTimeProfile by setting it to NULL.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int nBTLimit, int nStartGates, int fVerbose ) { Ses_Man_t * pSes; char * pSol; Abc_Ntk_t * pNtk = NULL; abctime timeStart; /* some checks */ assert( nVars >= 2 && nVars <= 8 ); timeStart = Abc_Clock(); pSes = Ses_ManAlloc( pTruth, nVars, nFunc, nMaxDepth, pArrTimeProfile, 0, nBTLimit, fVerbose ); pSes->nStartGates = nStartGates; pSes->fReasonVerbose = 1; pSes->fSatVerbose = 1; if ( fVerbose ) Ses_ManPrintFuncs( pSes ); if ( ( pSol = Ses_ManFindMinimumSize( pSes ) ) != NULL ) { pNtk = Ses_ManExtractNtk( pSol ); ABC_FREE( pSol ); } pSes->timeTotal = Abc_Clock() - timeStart; if ( fVerbose ) Ses_ManPrintRuntime( pSes ); /* cleanup */ Ses_ManClean( pSes ); return pNtk; } Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrTimeProfile, int nBTLimit, int nStartGates, int fVerbose ) { Ses_Man_t * pSes; char * pSol; Gia_Man_t * pGia = NULL; abctime timeStart; /* some checks */ assert( nVars >= 2 && nVars <= 8 ); timeStart = Abc_Clock(); pSes = Ses_ManAlloc( pTruth, nVars, nFunc, nMaxDepth, pArrTimeProfile, 1, nBTLimit, fVerbose ); pSes->nStartGates = nStartGates; pSes->fVeryVerbose = 1; pSes->fExtractVerbose = 0; pSes->fSatVerbose = 0; pSes->fReasonVerbose = 1; if ( fVerbose ) Ses_ManPrintFuncs( pSes ); if ( ( pSol = Ses_ManFindMinimumSize( pSes ) ) != NULL ) { pGia = Ses_ManExtractGia( pSol ); ABC_FREE( pSol ); } pSes->timeTotal = Abc_Clock() - timeStart; if ( fVerbose ) Ses_ManPrintRuntime( pSes ); /* cleanup */ Ses_ManClean( pSes ); return pGia; } /**Function************************************************************* Synopsis [Some test cases.] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromTruthTable( word * pTruth, int nVars ) { Abc_Ntk_t * pNtk; Mem_Flex_t * pMan; char * pSopCover; pMan = Mem_FlexStart(); pSopCover = Abc_SopCreateFromTruth( pMan, nVars, (unsigned*)pTruth ); pNtk = Abc_NtkCreateWithNode( pSopCover ); Abc_NtkShortNames( pNtk ); Mem_FlexStop( pMan, 0 ); return pNtk; } void Abc_ExactTestSingleOutput( int fVerbose ) { extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); word pTruth[4] = {0xcafe, 0, 0, 0}; Abc_Ntk_t * pNtk, * pNtk2, * pNtk3, * pNtk4; int pArrTimeProfile[4] = {6, 2, 8, 5}; pNtk = Abc_NtkFromTruthTable( pTruth, 4 ); pNtk2 = Abc_NtkFindExact( pTruth, 4, 1, -1, NULL, 0, 0, fVerbose ); Abc_NtkShortNames( pNtk2 ); Abc_NtkCecSat( pNtk, pNtk2, 10000, 0 ); assert( pNtk2 ); assert( Abc_NtkNodeNum( pNtk2 ) == 6 ); Abc_NtkDelete( pNtk2 ); pNtk3 = Abc_NtkFindExact( pTruth, 4, 1, 3, NULL, 0, 0, fVerbose ); Abc_NtkShortNames( pNtk3 ); Abc_NtkCecSat( pNtk, pNtk3, 10000, 0 ); assert( pNtk3 ); assert( Abc_NtkLevel( pNtk3 ) <= 3 ); Abc_NtkDelete( pNtk3 ); pNtk4 = Abc_NtkFindExact( pTruth, 4, 1, 9, pArrTimeProfile, 50000, 0, fVerbose ); Abc_NtkShortNames( pNtk4 ); Abc_NtkCecSat( pNtk, pNtk4, 10000, 0 ); assert( pNtk4 ); assert( Abc_NtkLevel( pNtk4 ) <= 9 ); Abc_NtkDelete( pNtk4 ); assert( !Abc_NtkFindExact( pTruth, 4, 1, 2, NULL, 50000, 0, fVerbose ) ); assert( !Abc_NtkFindExact( pTruth, 4, 1, 8, pArrTimeProfile, 50000, 0, fVerbose ) ); Abc_NtkDelete( pNtk ); } void Abc_ExactTestSingleOutputAIG( int fVerbose ) { word pTruth[4] = {0xcafe, 0, 0, 0}; Abc_Ntk_t * pNtk; Gia_Man_t * pGia, * pGia2, * pGia3, * pGia4, * pMiter; Cec_ParCec_t ParsCec, * pPars = &ParsCec; int pArrTimeProfile[4] = {6, 2, 8, 5}; Cec_ManCecSetDefaultParams( pPars ); pNtk = Abc_NtkFromTruthTable( pTruth, 4 ); Abc_NtkToAig( pNtk ); pGia = Abc_NtkAigToGia( pNtk, 1 ); pGia2 = Gia_ManFindExact( pTruth, 4, 1, -1, NULL, 0, 0, fVerbose ); pMiter = Gia_ManMiter( pGia, pGia2, 0, 1, 0, 0, 1 ); assert( pMiter ); Cec_ManVerify( pMiter, pPars ); Gia_ManStop( pMiter ); pGia3 = Gia_ManFindExact( pTruth, 4, 1, 3, NULL, 0, 0, fVerbose ); pMiter = Gia_ManMiter( pGia, pGia3, 0, 1, 0, 0, 1 ); assert( pMiter ); Cec_ManVerify( pMiter, pPars ); Gia_ManStop( pMiter ); pGia4 = Gia_ManFindExact( pTruth, 4, 1, 9, pArrTimeProfile, 50000, 0, fVerbose ); pMiter = Gia_ManMiter( pGia, pGia4, 0, 1, 0, 0, 1 ); assert( pMiter ); Cec_ManVerify( pMiter, pPars ); Gia_ManStop( pMiter ); assert( !Gia_ManFindExact( pTruth, 4, 1, 2, NULL, 50000, 0, fVerbose ) ); assert( !Gia_ManFindExact( pTruth, 4, 1, 8, pArrTimeProfile, 50000, 0, fVerbose ) ); Gia_ManStop( pGia ); Gia_ManStop( pGia2 ); Gia_ManStop( pGia3 ); Gia_ManStop( pGia4 ); } void Abc_ExactTest( int fVerbose ) { Abc_ExactTestSingleOutput( fVerbose ); Abc_ExactTestSingleOutputAIG( fVerbose ); printf( "\n" ); } /**Function************************************************************* Synopsis [APIs for integraging with the mapper.] ***********************************************************************/ // may need to have a static pointer to the SAT-based synthesis engine and/or loaded library // this procedure should return 1, if the engine/library are available, and 0 otherwise int Abc_ExactIsRunning() { return s_pSesStore != NULL; } // this procedure returns the number of inputs of the library // for example, somebody may try to map into 10-cuts while the library only contains 8-functions int Abc_ExactInputNum() { return 8; } // start exact store manager void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, int fVeryVerbose, const char * pFilename ) { if ( !s_pSesStore ) { s_pSesStore = Ses_StoreAlloc( nBTLimit, fMakeAIG, fVerbose ); s_pSesStore->fVeryVerbose = fVeryVerbose; if ( pFilename ) { Ses_StoreRead( s_pSesStore, pFilename, 1, 0, 0, 0 ); s_pSesStore->szDBName = ABC_CALLOC( char, strlen( pFilename ) + 1 ); strcpy( s_pSesStore->szDBName, pFilename ); } if ( s_pSesStore->fVeryVerbose ) { s_pSesStore->pDebugEntries = fopen( "bms.debug", "w" ); } } else printf( "BMS manager already started\n" ); } // stop exact store manager void Abc_ExactStop( const char * pFilename ) { if ( s_pSesStore ) { if ( pFilename ) Ses_StoreWrite( s_pSesStore, pFilename, 1, 0, 0, 0 ); if ( s_pSesStore->pDebugEntries ) fclose( s_pSesStore->pDebugEntries ); Ses_StoreClean( s_pSesStore ); } else printf( "BMS manager has not been started\n" ); } // show statistics about store manager void Abc_ExactStats() { int i; if ( !s_pSesStore ) { printf( "BMS manager has not been started\n" ); return; } printf( "-------------------------------------------------------------------------------------------------------------------------------\n" ); printf( " 0 1 2 3 4 5 6 7 8 total\n" ); printf( "-------------------------------------------------------------------------------------------------------------------------------\n" ); printf( "number of considered cuts :" ); for ( i = 0; i < 9; ++i ) printf( "%10lu", s_pSesStore->pCutCount[i] ); printf( "%10lu\n", s_pSesStore->nCutCount ); printf( " - trivial :" ); for ( i = 0; i < 9; ++i ) printf( "%10lu", s_pSesStore->pSynthesizedTrivial[i] ); printf( "%10lu\n", s_pSesStore->nSynthesizedTrivial ); printf( " - synth (imp) :" ); for ( i = 0; i < 9; ++i ) printf( "%10lu", s_pSesStore->pSynthesizedImp[i] ); printf( "%10lu\n", s_pSesStore->nSynthesizedImp ); printf( " - synth (res) :" ); for ( i = 0; i < 9; ++i ) printf( "%10lu", s_pSesStore->pSynthesizedRL[i] ); printf( "%10lu\n", s_pSesStore->nSynthesizedRL ); printf( " - not synth (imp) :" ); for ( i = 0; i < 9; ++i ) printf( "%10lu", s_pSesStore->pUnsynthesizedImp[i] ); printf( "%10lu\n", s_pSesStore->nUnsynthesizedImp ); printf( " - not synth (res) :" ); for ( i = 0; i < 9; ++i ) printf( "%10lu", s_pSesStore->pUnsynthesizedRL[i] ); printf( "%10lu\n", s_pSesStore->nUnsynthesizedRL ); printf( " - cache hits :" ); for ( i = 0; i < 9; ++i ) printf( "%10lu", s_pSesStore->pCacheHits[i] ); printf( "%10lu\n", s_pSesStore->nCacheHits ); printf( "-------------------------------------------------------------------------------------------------------------------------------\n" ); printf( "number of entries : %d\n", s_pSesStore->nEntriesCount ); printf( "number of valid entries : %d\n", s_pSesStore->nValidEntriesCount ); printf( "number of invalid entries : %d\n", s_pSesStore->nEntriesCount - s_pSesStore->nValidEntriesCount ); printf( "-------------------------------------------------------------------------------------------------------------------------------\n" ); printf( "number of SAT calls : %lu\n", s_pSesStore->nSatCalls ); printf( "number of UNSAT calls : %lu\n", s_pSesStore->nUnsatCalls ); printf( "number of UNDEF calls : %lu\n", s_pSesStore->nUndefCalls ); printf( "-------------------------------------------------------------------------------------------------------------------------------\n" ); printf( "Runtime breakdown:\n" ); ABC_PRTP( "Exact ", s_pSesStore->timeExact, s_pSesStore->timeTotal ); ABC_PRTP( " Sat ", s_pSesStore->timeSat, s_pSesStore->timeTotal ); ABC_PRTP( " Sat ", s_pSesStore->timeSatSat, s_pSesStore->timeTotal ); ABC_PRTP( " Unsat ", s_pSesStore->timeSatUnsat, s_pSesStore->timeTotal ); ABC_PRTP( " Undef ", s_pSesStore->timeSatUndef, s_pSesStore->timeTotal ); ABC_PRTP( " Instance", s_pSesStore->timeInstance, s_pSesStore->timeTotal ); ABC_PRTP( "Other ", s_pSesStore->timeTotal - s_pSesStore->timeExact, s_pSesStore->timeTotal ); ABC_PRTP( "ALL ", s_pSesStore->timeTotal, s_pSesStore->timeTotal ); } // this procedure takes TT and input arrival times (pArrTimeProfile) and return the smallest output arrival time; // it also returns the pin-to-pin delays (pPerm) between each cut leaf and the cut output and the cut area cost (Cost) // the area cost should not exceed 2048, if the cut is implementable; otherwise, it should be ABC_INFINITY int Abc_ExactDelayCost( word * pTruth, int nVars, int * pArrTimeProfile, char * pPerm, int * Cost, int AigLevel ) { int i, nMaxArrival, nDelta, l; Ses_Man_t * pSes = NULL; char * pSol = NULL, * pSol2 = NULL, * p; int pNormalArrTime[8]; int Delay = ABC_INFINITY, nMaxDepth, fResLimit; abctime timeStart = Abc_Clock(), timeStartExact; /* some checks */ if ( nVars < 0 || nVars > 8 ) { printf( "invalid truth table size %d\n", nVars ); assert( 0 ); } /* statistics */ s_pSesStore->nCutCount++; s_pSesStore->pCutCount[nVars]++; if ( nVars == 0 ) { s_pSesStore->nSynthesizedTrivial++; s_pSesStore->pSynthesizedTrivial[0]++; *Cost = 0; s_pSesStore->timeTotal += ( Abc_Clock() - timeStart ); return 0; } if ( nVars == 1 ) { s_pSesStore->nSynthesizedTrivial++; s_pSesStore->pSynthesizedTrivial[1]++; *Cost = 0; pPerm[0] = (char)0; s_pSesStore->timeTotal += ( Abc_Clock() - timeStart ); return pArrTimeProfile[0]; } for ( l = 0; l < nVars; ++l ) pNormalArrTime[l] = pArrTimeProfile[l]; nDelta = Abc_NormalizeArrivalTimes( pNormalArrTime, nVars, &nMaxArrival ); *Cost = ABC_INFINITY; if ( Ses_StoreGetEntry( s_pSesStore, pTruth, nVars, pNormalArrTime, &pSol ) ) { s_pSesStore->nCacheHits++; s_pSesStore->pCacheHits[nVars]++; } else { if ( s_pSesStore->fVeryVerbose ) { printf( ANSI_COLOR_CYAN ); Abc_TtPrintHexRev( stdout, pTruth, nVars ); printf( ANSI_COLOR_RESET ); printf( " [%d", pNormalArrTime[0] ); for ( l = 1; l < nVars; ++l ) printf( " %d", pNormalArrTime[l] ); printf( "]@%d:", AigLevel ); fflush( stdout ); } nMaxDepth = pNormalArrTime[0]; for ( i = 1; i < nVars; ++i ) nMaxDepth = Abc_MaxInt( nMaxDepth, pNormalArrTime[i] ); nMaxDepth += nVars + 1; if ( AigLevel != -1 ) nMaxDepth = Abc_MinInt( AigLevel - nDelta, nMaxDepth + nVars + 1 ); timeStartExact = Abc_Clock(); pSes = Ses_ManAlloc( pTruth, nVars, 1 /* nSpecFunc */, nMaxDepth, pNormalArrTime, s_pSesStore->fMakeAIG, s_pSesStore->nBTLimit, s_pSesStore->fVerbose ); pSes->fVeryVerbose = s_pSesStore->fVeryVerbose; pSes->pSat = s_pSesStore->pSat; pSes->nStartGates = nVars - 2; while ( pSes->nMaxDepth ) /* there is improvement */ { if ( s_pSesStore->fVeryVerbose ) { printf( " %d", pSes->nMaxDepth ); fflush( stdout ); } if ( ( pSol2 = Ses_ManFindMinimumSize( pSes ) ) != NULL ) { if ( s_pSesStore->fVeryVerbose ) { if ( pSes->nMaxDepth >= 10 ) printf( "\b" ); printf( "\b" ANSI_COLOR_GREEN "%d" ANSI_COLOR_RESET, pSes->nMaxDepth ); } if ( pSol ) ABC_FREE( pSol ); pSol = pSol2; pSes->nMaxDepth--; } else { if ( s_pSesStore->fVeryVerbose ) { if ( pSes->nMaxDepth >= 10 ) printf( "\b" ); printf( "\b%s%d" ANSI_COLOR_RESET, pSes->fHitResLimit ? ANSI_COLOR_RED : ANSI_COLOR_YELLOW, pSes->nMaxDepth ); } break; } } if ( s_pSesStore->fVeryVerbose ) printf( " \n" ); /* log unsuccessful case for debugging */ if ( s_pSesStore->pDebugEntries && pSes->fHitResLimit ) Ses_StorePrintDebugEntry( s_pSesStore, pTruth, nVars, pNormalArrTime, pSes->nMaxDepth, pSol, nVars - 2 ); pSes->timeTotal = Abc_Clock() - timeStartExact; /* statistics */ s_pSesStore->nSatCalls += pSes->nSatCalls; s_pSesStore->nUnsatCalls += pSes->nUnsatCalls; s_pSesStore->nUndefCalls += pSes->nUndefCalls; s_pSesStore->timeSat += pSes->timeSat; s_pSesStore->timeSatSat += pSes->timeSatSat; s_pSesStore->timeSatUnsat += pSes->timeSatUnsat; s_pSesStore->timeSatUndef += pSes->timeSatUndef; s_pSesStore->timeInstance += pSes->timeInstance; s_pSesStore->timeExact += pSes->timeTotal; /* cleanup (we need to clean before adding since pTruth may have been modified by pSes) */ fResLimit = pSes->fHitResLimit; Ses_ManCleanLight( pSes ); /* store solution */ Ses_StoreAddEntry( s_pSesStore, pTruth, nVars, pNormalArrTime, pSol, fResLimit ); } if ( pSol ) { *Cost = pSol[ABC_EXACT_SOL_NGATES]; p = pSol + 3 + 4 * pSol[ABC_EXACT_SOL_NGATES] + 1; Delay = *p++; for ( l = 0; l < nVars; ++l ) pPerm[l] = *p++; } if ( pSol ) { int Delay2 = 0; for ( l = 0; l < nVars; ++l ) { //printf( "%d ", pPerm[l] ); Delay2 = Abc_MaxInt( Delay2, pArrTimeProfile[l] + pPerm[l] ); } //printf( " output arrival = %d recomputed = %d\n", Delay, Delay2 ); //if ( Delay != Delay2 ) //{ // printf( "^--- BUG!\n" ); // assert( 0 ); //} s_pSesStore->timeTotal += ( Abc_Clock() - timeStart ); return Delay2; } else { assert( *Cost == ABC_INFINITY ); s_pSesStore->timeTotal += ( Abc_Clock() - timeStart ); return ABC_INFINITY; } } // this procedure returns a new node whose output in terms of the given fanins // has the smallest possible arrival time (in agreement with the above Abc_ExactDelayCost) Abc_Obj_t * Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk ) { char * pSol = NULL; int i, j, nMaxArrival; int pNormalArrTime[8]; char const * p; Abc_Obj_t * pObj; Vec_Ptr_t * pGates; char pGateTruth[5]; char * pSopCover; abctime timeStart = Abc_Clock(); if ( nVars == 0 ) { s_pSesStore->timeTotal += ( Abc_Clock() - timeStart ); return (pTruth[0] & 1) ? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); } if ( nVars == 1 ) { s_pSesStore->timeTotal += ( Abc_Clock() - timeStart ); return (pTruth[0] & 1) ? Abc_NtkCreateNodeInv(pNtk, pFanins[0]) : Abc_NtkCreateNodeBuf(pNtk, pFanins[0]); } for ( i = 0; i < nVars; ++i ) pNormalArrTime[i] = pArrTimeProfile[i]; Abc_NormalizeArrivalTimes( pNormalArrTime, nVars, &nMaxArrival ); assert( Ses_StoreGetEntry( s_pSesStore, pTruth, nVars, pNormalArrTime, &pSol ) ); if ( !pSol ) { s_pSesStore->timeTotal += ( Abc_Clock() - timeStart ); return NULL; } assert( pSol[ABC_EXACT_SOL_NVARS] == nVars ); assert( pSol[ABC_EXACT_SOL_NFUNC] == 1 ); pGates = Vec_PtrAlloc( nVars + pSol[ABC_EXACT_SOL_NGATES] ); pGateTruth[3] = '0'; pGateTruth[4] = '\0'; /* primary inputs */ for ( i = 0; i < nVars; ++i ) { assert( pFanins[i] ); Vec_PtrPush( pGates, pFanins[i] ); } /* gates */ p = pSol + 3; for ( i = 0; i < pSol[ABC_EXACT_SOL_NGATES]; ++i ) { pGateTruth[2] = '0' + ( *p & 1 ); pGateTruth[1] = '0' + ( ( *p >> 1 ) & 1 ); pGateTruth[0] = '0' + ( ( *p >> 2 ) & 1 ); ++p; assert( *p == 2 ); /* binary gate */ ++p; /* invert truth table if we are last gate and inverted */ if ( i + 1 == pSol[ABC_EXACT_SOL_NGATES] && Abc_LitIsCompl( *( p + 2 ) ) ) for ( j = 0; j < 4; ++j ) pGateTruth[j] = ( pGateTruth[j] == '0' ) ? '1' : '0'; pSopCover = Abc_SopFromTruthBin( pGateTruth ); pObj = Abc_NtkCreateNode( pNtk ); assert( pObj ); pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSopCover ); Vec_PtrPush( pGates, pObj ); ABC_FREE( pSopCover ); Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); Abc_ObjAddFanin( pObj, (Abc_Obj_t *)Vec_PtrEntry( pGates, *p++ ) ); } /* output */ pObj = (Abc_Obj_t *)Vec_PtrEntry( pGates, nVars + Abc_Lit2Var( *p ) ); Vec_PtrFree( pGates ); s_pSesStore->timeTotal += ( Abc_Clock() - timeStart ); return pObj; } void Abc_ExactStoreTest( int fVerbose ) { int i; word pTruth[4] = {0xcafe, 0, 0, 0}; int pArrTimeProfile[4] = {6, 2, 8, 5}; Abc_Ntk_t * pNtk; Abc_Obj_t * pFanins[4]; Vec_Ptr_t * vNames; char pPerm[4]; int Cost; pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); pNtk->pName = Extra_UtilStrsav( "exact" ); vNames = Abc_NodeGetFakeNames( 4u ); /* primary inputs */ Vec_PtrPush( pNtk->vObjs, NULL ); for ( i = 0; i < 4; ++i ) { pFanins[i] = Abc_NtkCreatePi( pNtk ); Abc_ObjAssignName( pFanins[i], (char*)Vec_PtrEntry( vNames, i ), NULL ); } Abc_NodeFreeNames( vNames ); Abc_ExactStart( 10000, 1, fVerbose, 0, NULL ); assert( !Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); assert( Abc_ExactDelayCost( pTruth, 4, pArrTimeProfile, pPerm, &Cost, 12 ) == 1 ); assert( Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); (*pArrTimeProfile)++; assert( !Abc_ExactBuildNode( pTruth, 4, pArrTimeProfile, pFanins, pNtk ) ); (*pArrTimeProfile)--; Abc_ExactStop( NULL ); Abc_NtkDelete( pNtk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcExtract.c000066400000000000000000000613721300674244400241010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcShare.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Shared logic extraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcShare.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define SHARE_NUM 2 typedef struct Abc_ShaMan_t_ Abc_ShaMan_t; struct Abc_ShaMan_t_ { int nMultiSize; int fVerbose; Abc_Ntk_t * pNtk; Vec_Ptr_t * vBuckets; Vec_Int_t * vObj2Lit; int nStartCols; int nCountGates; int nFoundGates; }; static inline word Abc_NtkSharePack( int Lev, int Id ) { return (((word)Lev) << 32) | Id; } static inline int Abc_NtkShareUnpackLev( word Num ) { return (Num >> 32); } static inline int Abc_NtkShareUnpackId( word Num ) { return Num & 0xFFFFFFFF; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Working with the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ShaMan_t * Abc_ShaManStart( Abc_Ntk_t * pNtk ) { Abc_ShaMan_t * p; p = ABC_CALLOC( Abc_ShaMan_t, 1 ); p->pNtk = pNtk; p->vObj2Lit = Vec_IntAlloc( 1000 ); return p; } void Abc_ShaManStop( Abc_ShaMan_t * p ) { Vec_Ptr_t * vBucket; int i; Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i ) Vec_VecFree( (Vec_Vec_t *)vBucket ); Vec_PtrFreeP( &p->vBuckets ); Vec_IntFreeP( &p->vObj2Lit ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collects one multi-input gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Abc_NtkShareSuperXor( Abc_Obj_t * pObj, int * pfCompl, int * pCounter ) { Abc_Ntk_t * pNtk = Abc_ObjNtk(pObj); Abc_Obj_t * pObjC, * pObj0, * pObj1, * pRoot = NULL; Vec_Wrd_t * vSuper; word Num, NumNext; int i, k, fCompl = 0; assert( !Abc_ObjIsComplement(pObj) ); assert( Abc_NodeIsExorType(pObj) ); // start iteration vSuper = Vec_WrdAlloc( 10 ); Vec_WrdPush( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj), Abc_ObjId(pObj)) ); while ( Vec_WrdSize(vSuper) > 0 ) { // make sure there are no duplicates Num = Vec_WrdEntry( vSuper, 0 ); Vec_WrdForEachEntryStart( vSuper, NumNext, i, 1 ) { assert( Num < NumNext ); Num = NumNext; } // extract XOR gate decomposable on the topmost level Vec_WrdForEachEntryReverse( vSuper, Num, i ) { pRoot = Abc_NtkObj( pNtk, Abc_NtkShareUnpackId(Num) ); if ( Abc_NodeIsExorType(pRoot) ) { Vec_WrdRemove( vSuper, Num ); break; } } if ( i == -1 ) break; // extract pObjC = Abc_NodeRecognizeMux( pRoot, &pObj1, &pObj0 ); assert( pObj1 == Abc_ObjNot(pObj0) ); fCompl ^= Abc_ObjIsComplement(pObjC); pObjC = Abc_ObjRegular(pObjC); fCompl ^= Abc_ObjIsComplement(pObj0); pObj0 = Abc_ObjRegular(pObj0); Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObjC), Abc_ObjId(pObjC)) ); Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj0), Abc_ObjId(pObj0)) ); (*pCounter)++; // remove duplicates k = 0; Vec_WrdForEachEntry( vSuper, Num, i ) { if ( i + 1 == Vec_WrdSize(vSuper) ) { Vec_WrdWriteEntry( vSuper, k++, Num ); break; } NumNext = Vec_WrdEntry( vSuper, i+1 ); assert( Num <= NumNext ); if ( Num == NumNext ) i++; else Vec_WrdWriteEntry( vSuper, k++, Num ); } Vec_WrdShrink( vSuper, k ); } *pfCompl = fCompl; Vec_WrdForEachEntry( vSuper, Num, i ) Vec_WrdWriteEntry( vSuper, i, Abc_NtkShareUnpackId(Num) ); return vSuper; } Vec_Wrd_t * Abc_NtkShareSuperAnd( Abc_Obj_t * pObj, int * pCounter ) { Abc_Ntk_t * pNtk = Abc_ObjNtk(pObj); Abc_Obj_t * pObj0, * pObj1, * pRoot = NULL; Vec_Wrd_t * vSuper; word Num, NumNext; int i, k; assert( !Abc_ObjIsComplement(pObj) ); // start iteration vSuper = Vec_WrdAlloc( 10 ); Vec_WrdPush( vSuper, Abc_NtkSharePack(Abc_ObjLevel(pObj), Abc_ObjToLit(pObj)) ); while ( Vec_WrdSize(vSuper) > 0 ) { // make sure there are no duplicates Num = Vec_WrdEntry( vSuper, 0 ); Vec_WrdForEachEntryStart( vSuper, NumNext, i, 1 ) { assert( Num < NumNext ); Num = NumNext; } // extract AND gate decomposable on the topmost level Vec_WrdForEachEntryReverse( vSuper, Num, i ) { pRoot = Abc_ObjFromLit( pNtk, Abc_NtkShareUnpackId(Num) ); if ( !Abc_ObjIsComplement(pRoot) && Abc_ObjIsNode(pRoot) ) { Vec_WrdRemove( vSuper, Num ); break; } } if ( i == -1 ) break; assert( Abc_ObjIsNode(pRoot) ); // extract pObj0 = Abc_ObjChild0(pRoot); pObj1 = Abc_ObjChild1(pRoot); assert( Abc_ObjIsNode(Abc_ObjRegular(pObj0)) || Abc_ObjIsCi(Abc_ObjRegular(pObj0)) ); assert( Abc_ObjIsNode(Abc_ObjRegular(pObj1)) || Abc_ObjIsCi(Abc_ObjRegular(pObj1)) ); Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(Abc_ObjRegular(pObj0)), Abc_ObjToLit(pObj0)) ); Vec_WrdPushOrder( vSuper, Abc_NtkSharePack(Abc_ObjLevel(Abc_ObjRegular(pObj1)), Abc_ObjToLit(pObj1)) ); (*pCounter)++; // remove duplicates k = 0; Vec_WrdForEachEntry( vSuper, Num, i ) { if ( i + 1 == Vec_WrdSize(vSuper) ) { Vec_WrdWriteEntry( vSuper, k++, Num ); break; } NumNext = Vec_WrdEntry( vSuper, i+1 ); assert( Num <= NumNext ); if ( Num + 1 == NumNext && (NumNext & 1) ) // pos_lit & neg_lit = 0 { Vec_WrdClear( vSuper ); return vSuper; } if ( Num < NumNext ) Vec_WrdWriteEntry( vSuper, k++, Num ); } Vec_WrdShrink( vSuper, k ); } Vec_WrdForEachEntry( vSuper, Num, i ) Vec_WrdWriteEntry( vSuper, i, Abc_NtkShareUnpackId(Num) ); return vSuper; } /**Function************************************************************* Synopsis [Creates multi-input XOR representation for the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTraverseSupersXor_rec( Abc_ShaMan_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vInputs ) { if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsCi(pObj) ) return; assert( Abc_ObjIsNode(pObj) ); if ( Abc_NodeIsExorType(pObj) ) { Vec_Wrd_t * vSuper; int k, fCompl; word Num; vSuper = Abc_NtkShareSuperXor( pObj, &fCompl, &p->nFoundGates ); if ( Vec_WrdSize(vSuper) <= 1 || Vec_WrdSize(vSuper) >= p->nMultiSize ) { Vec_WrdForEachEntry( vSuper, Num, k ) { Vec_Int_t * vInput = (Vec_Int_t *)Vec_PtrEntry( vInputs, (int)Num ); if ( vInput == NULL ) { vInput = Vec_IntAlloc( 10 ); Vec_IntPush( vInput, Abc_Var2Lit((int)Num, 0) ); Vec_IntPush( vInput, Abc_ObjLevel(Abc_NtkObj(p->pNtk, (int)Num)) ); assert( SHARE_NUM == Vec_IntSize(vInput) ); Vec_PtrWriteEntry( vInputs, (int)Num, vInput ); } Vec_IntPush( vInput, Vec_IntSize(p->vObj2Lit) ); } Vec_IntPush( p->vObj2Lit, Abc_Var2Lit(Abc_ObjId(pObj), fCompl) ); } // call recursively Vec_WrdForEachEntry( vSuper, Num, k ) Abc_NtkTraverseSupersXor_rec( p, Abc_NtkObj(p->pNtk, (int)Num), vInputs ); Vec_WrdFree( vSuper ); } else { Abc_NtkTraverseSupersXor_rec( p, Abc_ObjFanin0(pObj), vInputs ); Abc_NtkTraverseSupersXor_rec( p, Abc_ObjFanin1(pObj), vInputs ); } } void Abc_NtkTraverseSupersAnd_rec( Abc_ShaMan_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vInputs ) { Vec_Wrd_t * vSuper; word Num; int k; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsCi(pObj) ) return; assert( Abc_ObjIsNode(pObj) ); vSuper = Abc_NtkShareSuperAnd( pObj, &p->nFoundGates ); if ( Vec_WrdSize(vSuper) <= 1 || Vec_WrdSize(vSuper) >= p->nMultiSize ) { Vec_WrdForEachEntry( vSuper, Num, k ) { Vec_Int_t * vInput = (Vec_Int_t *)Vec_PtrEntry( vInputs, (int)Num ); if ( vInput == NULL ) { vInput = Vec_IntAlloc( 10 ); Vec_IntPush( vInput, (int)Num ); Vec_IntPush( vInput, Abc_ObjLevel(Abc_NtkObj(p->pNtk, Abc_Lit2Var((int)Num))) ); assert( SHARE_NUM == Vec_IntSize(vInput) ); Vec_PtrWriteEntry( vInputs, (int)Num, vInput ); } Vec_IntPush( vInput, Vec_IntSize(p->vObj2Lit) ); } Vec_IntPush( p->vObj2Lit, Abc_ObjToLit(pObj) ); } // call recursively Vec_WrdForEachEntry( vSuper, Num, k ) Abc_NtkTraverseSupersAnd_rec( p, Abc_NtkObj(p->pNtk, Abc_Lit2Var((int)Num)), vInputs ); Vec_WrdFree( vSuper ); } void Abc_NtkTraverseSupers( Abc_ShaMan_t * p, int fAnd ) { Vec_Ptr_t * vInputs; Vec_Int_t * vInput; Abc_Obj_t * pObj; int i, nOnesMax; // create mapping of nodes into their column vectors vInputs = Vec_PtrStart( Abc_NtkObjNumMax(p->pNtk) * (1 + fAnd) ); Abc_NtkIncrementTravId( p->pNtk ); if ( fAnd ) { Abc_NtkForEachCo( p->pNtk, pObj, i ) if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) Abc_NtkTraverseSupersAnd_rec( p, Abc_ObjFanin0(pObj), vInputs ); } else { Abc_NtkForEachCo( p->pNtk, pObj, i ) if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) Abc_NtkTraverseSupersXor_rec( p, Abc_ObjFanin0(pObj), vInputs ); } p->nStartCols = Vec_IntSize(p->vObj2Lit); // find the largest number of 1s nOnesMax = 0; Vec_PtrForEachEntry( Vec_Int_t *, vInputs, vInput, i ) if ( vInput ) nOnesMax = Abc_MaxInt( nOnesMax, Vec_IntSize(vInput)-SHARE_NUM ); // create buckets assert( p->vBuckets == NULL ); p->vBuckets = Vec_PtrAlloc( nOnesMax + 1 ); for ( i = 0; i <= nOnesMax; i++ ) Vec_PtrPush( p->vBuckets, Vec_PtrAlloc(10) ); // load vectors into buckets Vec_PtrForEachEntry( Vec_Int_t *, vInputs, vInput, i ) if ( vInput ) Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vInput)-SHARE_NUM), vInput ); Vec_PtrFree( vInputs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSharePrint( Abc_ShaMan_t * p ) { Vec_Ptr_t * vBucket; Vec_Int_t * vInput; int i, k, j, ObjId; char * pBuffer = ABC_ALLOC( char, Vec_IntSize(p->vObj2Lit) + 1 ); int * pCounters = ABC_CALLOC( int, Vec_IntSize(p->vObj2Lit) + 1 ); int nTotal = 0; Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i ) Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, j ) { for ( k = 0; k < Vec_IntSize(p->vObj2Lit); k++ ) pBuffer[k] = '0'; pBuffer[k] = 0; Vec_IntForEachEntryStart( vInput, ObjId, k, SHARE_NUM ) { assert( ObjId < Vec_IntSize(p->vObj2Lit) ); pBuffer[ObjId] = '1'; pCounters[ObjId]++; } printf( "%4d%3d: %s\n", Vec_IntEntry(vInput, 0), Vec_IntEntry(vInput, 1), pBuffer ); } for ( i = 0; i < Vec_IntSize(p->vObj2Lit); i++ ) if ( pCounters[i] > 0 ) printf( "%d=%d ", i, pCounters[i] ); printf( "\n" ); nTotal = 0; for ( i = 0; i < p->nStartCols; i++ ) nTotal += pCounters[i] - 1; printf( "Total = %d. ", nTotal ); printf( "Gates = %d.\n", Vec_IntSize(p->vObj2Lit) - p->nStartCols + nTotal ); ABC_FREE( pCounters ); ABC_FREE( pBuffer ); printf( "Bucket contents: " ); Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i ) printf( "%d ", Vec_PtrSize(vBucket) ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDumpBlif( Abc_Ntk_t * p ) { FILE * pFile; Vec_Ptr_t * vSupp; Abc_Obj_t * pObj; int i, k; pFile = fopen( "multi_and.blif", "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file.\n" ); return; } fprintf( pFile, ".model %s\n", "multi_and" ); fprintf( pFile, ".inputs" ); for ( i = 0; i < Abc_NtkCiNum(p); i++ ) fprintf( pFile, " i%d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); for ( i = 0; i < Abc_NtkCoNum(p); i++ ) fprintf( pFile, " o%d", i ); fprintf( pFile, "\n" ); Abc_NtkForEachCi( p, pObj, i ) pObj->iTemp = i; for ( i = 0; i < Abc_NtkCoNum(p); i++ ) { pObj = Abc_NtkCo( p, i ); vSupp = Abc_NtkNodeSupport( p, &pObj, 1 ); fprintf( pFile, ".names" ); Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k ) fprintf( pFile, " i%d", pObj->iTemp ); fprintf( pFile, " o%d\n", i ); Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k ) fprintf( pFile, "1" ); fprintf( pFile, " 1\n" ); Vec_PtrFree( vSupp ); } fprintf( pFile, ".end\n\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkShareFindBestMatch( Vec_Ptr_t * vBuckets, Vec_Int_t ** pvInput, Vec_Int_t ** pvInput2 ) { int nPoolSize = 40; Vec_Ptr_t * vPool = Vec_PtrAlloc( nPoolSize ); Vec_Ptr_t * vBucket; Vec_Int_t * vInput, * vInput2, * vInputBest = NULL, * vInputBest2 = NULL; int i, k, Cost, CostBest = 0, Delay, DelayBest = 0; Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vBuckets, vBucket, i ) Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, k ) { Vec_PtrPush( vPool, vInput ); if ( Vec_PtrSize(vPool) == nPoolSize ) goto outside; } outside: Vec_PtrForEachEntryReverse( Vec_Int_t *, vPool, vInput, i ) Vec_PtrForEachEntryReverse( Vec_Int_t *, vPool, vInput2, k ) { if ( i == k ) continue; vInput->pArray += SHARE_NUM; vInput2->pArray += SHARE_NUM; vInput->nSize -= SHARE_NUM; vInput2->nSize -= SHARE_NUM; Cost = Vec_IntTwoCountCommon(vInput, vInput2); vInput->pArray -= SHARE_NUM; vInput2->pArray -= SHARE_NUM; vInput->nSize += SHARE_NUM; vInput2->nSize += SHARE_NUM; if ( Cost < 2 ) continue; Delay = Abc_MaxInt( Vec_IntEntry(vInput, 1), Vec_IntEntry(vInput2, 1) ); if ( CostBest < Cost || (CostBest == Cost && (DelayBest > Delay)) ) { CostBest = Cost; DelayBest = Delay; vInputBest = vInput; vInputBest2 = vInput2; } } Vec_PtrFree( vPool ); *pvInput = vInputBest; *pvInput2 = vInputBest2; if ( vInputBest == NULL ) return; Vec_PtrRemove( (Vec_Ptr_t *)Vec_PtrEntry(vBuckets, Vec_IntSize(vInputBest)-SHARE_NUM), (Vec_Int_t *)vInputBest ); Vec_PtrRemove( (Vec_Ptr_t *)Vec_PtrEntry(vBuckets, Vec_IntSize(vInputBest2)-SHARE_NUM), (Vec_Int_t *)vInputBest2 ); } void Abc_NtkShareOptimize( Abc_ShaMan_t * p, int fAnd ) { Abc_Obj_t * pObj, * pObj0, * pObj1; Vec_Int_t * vInput, * vInput2; Vec_Int_t * vNew, * vOld1, * vOld2; int i; for ( i = 0; ; i++ ) { Abc_NtkShareFindBestMatch( p->vBuckets, &vInput, &vInput2 ); if ( vInput == NULL ) break; // create new node pObj0 = Abc_ObjFromLit( p->pNtk, Vec_IntEntry(vInput, 0) ); pObj1 = Abc_ObjFromLit( p->pNtk, Vec_IntEntry(vInput2, 0) ); if ( fAnd ) pObj = Abc_AigAnd( (Abc_Aig_t *)p->pNtk->pManFunc, pObj0, pObj1 ); else pObj = Abc_AigXor( (Abc_Aig_t *)p->pNtk->pManFunc, pObj0, pObj1 ); p->nCountGates++; // save new node vOld1 = Vec_IntAlloc( 16 ); Vec_IntPush( vOld1, Vec_IntEntry(vInput, 0) ); Vec_IntPush( vOld1, Vec_IntEntry(vInput, 1) ); vOld2 = Vec_IntAlloc( 16 ); Vec_IntPush( vOld2, Vec_IntEntry(vInput2, 0) ); Vec_IntPush( vOld2, Vec_IntEntry(vInput2, 1) ); vNew = Vec_IntAlloc( 16 ); Vec_IntPush( vNew, Abc_ObjToLit(pObj) ); Vec_IntPush( vNew, Abc_ObjLevel(Abc_ObjRegular(pObj)) ); // compute new arrays vInput->pArray += SHARE_NUM; vInput2->pArray += SHARE_NUM; vInput->nSize -= SHARE_NUM; vInput2->nSize -= SHARE_NUM; Vec_IntTwoSplit( vInput, vInput2, vNew, vOld1, vOld2 ); vInput->pArray -= SHARE_NUM; vInput2->pArray -= SHARE_NUM; vInput->nSize += SHARE_NUM; vInput2->nSize += SHARE_NUM; // add to the old ones Vec_IntPush( vOld1, Vec_IntSize(p->vObj2Lit) ); Vec_IntPush( vOld2, Vec_IntSize(p->vObj2Lit) ); Vec_IntPush( p->vObj2Lit, Abc_ObjToLit(pObj) ); Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vOld1)-SHARE_NUM), vOld1 ); Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vOld2)-SHARE_NUM), vOld2 ); Vec_PtrPush( (Vec_Ptr_t *)Vec_PtrEntry(p->vBuckets, Vec_IntSize(vNew)-SHARE_NUM), vNew ); Vec_IntFree( vInput ); Vec_IntFree( vInput2 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkUpdateNetwork( Abc_ShaMan_t * p, int fAnd ) { Abc_Ntk_t * pNtk; Vec_Int_t * vInput, * vMap2Repl; Vec_Ptr_t * vOrig, * vRepl, * vBucket; Abc_Obj_t * pObj, * pNew; int i, j, k, ObjId, iLit; int iLitConst1 = Abc_ObjToLit( Abc_AigConst1(p->pNtk) ); vOrig = Vec_PtrAlloc( p->nStartCols ); vRepl = Vec_PtrAlloc( p->nStartCols ); for ( i = 0; i < p->nStartCols; i++ ) { iLit = Vec_IntEntry( p->vObj2Lit, i ); assert( !fAnd || !Abc_LitIsCompl(iLit) ); pObj = Abc_NtkObj( p->pNtk, Abc_Lit2Var(iLit) ); if ( fAnd ) pNew = Abc_AigConst1(p->pNtk); else pNew = Abc_ObjNotCond( Abc_AigConst1(p->pNtk), !Abc_LitIsCompl(iLit) ); Vec_PtrPush( vOrig, pObj ); Vec_PtrPush( vRepl, pNew ); p->nCountGates--; } // go through the columns Vec_PtrForEachEntry( Vec_Ptr_t *, p->vBuckets, vBucket, i ) Vec_PtrForEachEntry( Vec_Int_t *, vBucket, vInput, j ) { Vec_IntForEachEntryStart( vInput, ObjId, k, SHARE_NUM ) { assert( ObjId < Vec_IntSize(p->vObj2Lit) ); if ( ObjId >= p->nStartCols ) break; assert( ObjId < p->nStartCols ); iLit = Vec_IntEntry( vInput, 0 ); pNew = (Abc_Obj_t *)Vec_PtrEntry( vRepl, ObjId ); if ( fAnd ) pNew = Abc_AigAnd( (Abc_Aig_t *)p->pNtk->pManFunc, pNew, Abc_ObjFromLit(p->pNtk, iLit) ); else pNew = Abc_AigXor( (Abc_Aig_t *)p->pNtk->pManFunc, pNew, Abc_ObjFromLit(p->pNtk, iLit) ); Vec_PtrWriteEntry( vRepl, ObjId, pNew ); p->nCountGates++; } } if ( p->fVerbose ) printf( "Total gates collected = %d. Total gates constructed = %d.\n", p->nFoundGates, p->nCountGates ); // create map of originals vMap2Repl = Vec_IntStartFull( Abc_NtkObjNumMax(p->pNtk) ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrig, pObj, i ) { // printf( "Replacing %d by %d.\n", Abc_ObjId(pObj), Abc_ObjToLit((Abc_Obj_t *)Vec_PtrEntry(vRepl, i)) ); Vec_IntWriteEntry( vMap2Repl, Abc_ObjId(pObj), Abc_ObjToLit((Abc_Obj_t *)Vec_PtrEntry(vRepl, i)) ); } Vec_PtrFree( vOrig ); Vec_PtrFree( vRepl ); // update fanin pointers Abc_NtkForEachObj( p->pNtk, pObj, i ) { if ( Abc_ObjIsCo(pObj) || Abc_ObjIsNode(pObj) ) { iLit = Vec_IntEntry( vMap2Repl, Abc_ObjFaninId0(pObj) ); if ( iLit >= 0 ) { if ( iLit == iLitConst1 && fAnd ) { pObj->fCompl0 ^= 1; Vec_IntWriteEntry( &pObj->vFanins, 0, Abc_Lit2Var(iLitConst1) ); } else { pObj->fCompl0 ^= Abc_LitIsCompl(iLit); Vec_IntWriteEntry( &pObj->vFanins, 0, Abc_Lit2Var(iLit) ); } } } if ( Abc_ObjIsNode(pObj) ) { iLit = Vec_IntEntry( vMap2Repl, Abc_ObjFaninId1(pObj) ); if ( iLit >= 0 ) { if ( iLit == iLitConst1 && fAnd ) { pObj->fCompl1 ^= 1; Vec_IntWriteEntry( &pObj->vFanins, 1, Abc_Lit2Var(iLitConst1) ); } else { pObj->fCompl1 ^= Abc_LitIsCompl(iLit); Vec_IntWriteEntry( &pObj->vFanins, 1, Abc_Lit2Var(iLit) ); } } } } Vec_IntFree( vMap2Repl ); // pNtk = Abc_NtkRestrash( p->pNtk, 1 ); if ( fAnd ) pNtk = Abc_NtkBalance( p->pNtk, 0, 0, 1 ); else pNtk = Abc_NtkBalanceExor( p->pNtk, 1, 0 ); return pNtk; } /**Function************************************************************* Synopsis [Extracts one multi-output XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkShareXor( Abc_Ntk_t * pNtk, int nMultiSize, int fAnd, int fVerbose ) { Abc_Ntk_t * pNtkNew; Abc_ShaMan_t * p; assert( Abc_NtkIsStrash(pNtk) ); // Abc_NtkDumpBlif( pNtk ); p = Abc_ShaManStart( pNtk ); p->nMultiSize = nMultiSize; p->fVerbose = fVerbose; Abc_NtkTraverseSupers( p, fAnd ); if ( p->nStartCols < 2 ) { Abc_ShaManStop( p ); return Abc_NtkDup( pNtk ); } if ( fVerbose ) Abc_NtkSharePrint( p ); Abc_NtkShareOptimize( p, fAnd ); if ( fVerbose ) Abc_NtkSharePrint( p ); pNtkNew = Abc_NtkUpdateNetwork( p, fAnd ); Abc_ShaManStop( p ); return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcFlop.c000066400000000000000000000023501300674244400233560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFlop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Flop dependency visualization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFlop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcFpga.c000066400000000000000000000234051300674244400233370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFpga.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface with the FPGA mapping package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFpga.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "map/fpga/fpgaInt.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ); static Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ); static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Interface with the FPGA mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ) { int fShowSwitching = 1; Abc_Ntk_t * pNtkNew; Fpga_Man_t * pMan; Vec_Int_t * vSwitching = NULL; float * pSwitching = NULL; int Num; assert( Abc_NtkIsStrash(pNtk) ); // print a warning about choice nodes if ( (Num = Abc_NtkGetChoiceNum( pNtk )) ) Abc_Print( 0, "Performing LUT mapping with %d choices.\n", Num ); // compute switching activity fShowSwitching |= fSwitching; if ( fShowSwitching ) { extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); pSwitching = (float *)vSwitching->pArray; } // perform FPGA mapping pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fLatchPaths, fVerbose ); if ( pSwitching ) { assert(vSwitching); Vec_IntFree( vSwitching ); } if ( pMan == NULL ) return NULL; Fpga_ManSetSwitching( pMan, fSwitching ); Fpga_ManSetLatchPaths( pMan, fLatchPaths ); Fpga_ManSetLatchNum( pMan, Abc_NtkLatchNum(pNtk) ); Fpga_ManSetDelayTarget( pMan, DelayTarget ); if ( !Fpga_Mapping( pMan ) ) { Fpga_ManFree( pMan ); return NULL; } // transform the result of mapping into a BDD network pNtkNew = Abc_NtkFromFpga( pMan, pNtk ); if ( pNtkNew == NULL ) return NULL; Fpga_ManFree( pMan ); // make the network minimum base Abc_NtkMinimumBase( pNtkNew ); if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkFpga: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Load the network into FPGA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ) { Fpga_Man_t * pMan; ProgressBar * pProgress; Fpga_Node_t * pNodeFpga; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin, * pPrev; float * pfArrivals; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the mapping manager and set its parameters pMan = Fpga_ManCreate( Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), fVerbose ); if ( pMan == NULL ) return NULL; Fpga_ManSetAreaRecovery( pMan, fRecovery ); Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); pfArrivals = Abc_NtkGetCiArrivalFloats(pNtk); if ( fLatchPaths ) { for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) pfArrivals[i] = -FPGA_FLOAT_LARGE; } Fpga_ManSetInputArrivals( pMan, pfArrivals ); // create PIs and remember them in the old nodes Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan); Abc_NtkForEachCi( pNtk, pNode, i ) { pNodeFpga = Fpga_ManReadInputs(pMan)[i]; pNode->pCopy = (Abc_Obj_t *)pNodeFpga; if ( pSwitching ) Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); } // load the AIG into the mapper vNodes = Abc_AigDfs( pNtk, 0, 0 ); pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // add the node to the mapper pNodeFpga = Fpga_NodeAnd( pMan, Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), Fpga_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); assert( pNode->pCopy == NULL ); // remember the node pNode->pCopy = (Abc_Obj_t *)pNodeFpga; if ( pSwitching ) Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); // set up the choice node if ( Abc_AigNodeIsChoice( pNode ) ) for ( pPrev = pNode, pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData ) { Fpga_NodeSetNextE( (Fpga_Node_t *)pPrev->pCopy, (Fpga_Node_t *)pFanin->pCopy ); Fpga_NodeSetRepr( (Fpga_Node_t *)pFanin->pCopy, (Fpga_Node_t *)pNode->pCopy ); } } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); // set the primary outputs without copying the phase Abc_NtkForEachCo( pNtk, pNode, i ) Fpga_ManReadOutputs(pMan)[i] = (Fpga_Node_t *)Abc_ObjFanin0(pNode)->pCopy; return pMan; } /**Function************************************************************* Synopsis [Creates the mapped network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pNodeNew; int i, nDupGates; // create the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); // make the mapper point to the new network Fpga_CutsCleanSign( pMan ); Fpga_ManCleanData0( pMan ); Abc_NtkForEachCi( pNtk, pNode, i ) Fpga_NodeSetData0( Fpga_ManReadInputs(pMan)[i], (char *)pNode->pCopy ); // set the constant node // if ( Fpga_NodeReadRefs(Fpga_ManReadConst1(pMan)) > 0 ) Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NtkCreateNodeConst1(pNtkNew) ); // process the nodes in topological order pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); pNodeNew = Abc_NodeFromFpga_rec( pNtkNew, Fpga_ManReadOutputs(pMan)[i] ); assert( !Abc_ObjIsComplement(pNodeNew) ); Abc_ObjFanin0(pNode)->pCopy = pNodeNew; } Extra_ProgressBarStop( pProgress ); // finalize the new network Abc_NtkFinalize( pNtk, pNtkNew ); // remove the constant node if not used pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0(Fpga_ManReadConst1(pMan)); if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) Abc_NtkDeleteObj( pNodeNew ); // decouple the PO driver nodes to reduce the number of levels nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); if ( nDupGates && Fpga_ManReadVerbose(pMan) ) printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); return pNtkNew; } /**Function************************************************************* Synopsis [Derive one node after FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ) { Fpga_Cut_t * pCutBest; Fpga_Node_t ** ppLeaves; Abc_Obj_t * pNodeNew; int i, nLeaves; assert( !Fpga_IsComplement(pNodeFpga) ); // return if the result if known pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0( pNodeFpga ); if ( pNodeNew ) return pNodeNew; assert( Fpga_NodeIsAnd(pNodeFpga) ); // get the parameters of the best cut pCutBest = Fpga_NodeReadCutBest( pNodeFpga ); ppLeaves = Fpga_CutReadLeaves( pCutBest ); nLeaves = Fpga_CutReadLeavesNum( pCutBest ); // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < nLeaves; i++ ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromFpga_rec(pNtkNew, ppLeaves[i]) ); // derive the function of this node pNodeNew->pData = Fpga_TruthsCutBdd( pNtkNew->pManFunc, pCutBest ); Cudd_Ref( (DdNode *)pNodeNew->pData ); Fpga_NodeSetData0( pNodeFpga, (char *)pNodeNew ); return pNodeNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcFpgaFast.c000066400000000000000000000161211300674244400241520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFpgaFast.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Fast FPGA mapper.] Author [Sungmin Cho] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFpgaFast.c,v 1.00 2006/09/02 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/ivy/ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ); static Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ); static Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes ); static inline void Abc_ObjSetIvy2Abc( Ivy_Man_t * p, int IvyId, Abc_Obj_t * pObjAbc ) { assert(Vec_PtrEntry((Vec_Ptr_t *)p->pCopy, IvyId) == NULL); assert(!Abc_ObjIsComplement(pObjAbc)); Vec_PtrWriteEntry( (Vec_Ptr_t *)p->pCopy, IvyId, pObjAbc ); } static inline Abc_Obj_t * Abc_ObjGetIvy2Abc( Ivy_Man_t * p, int IvyId ) { return (Abc_Obj_t *)Vec_PtrEntry( (Vec_Ptr_t *)p->pCopy, IvyId ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs fast FPGA mapping of the network.] Description [Takes the AIG to be mapped, the LUT size, and verbosity flag. Produces the new network by fast FPGA mapping of the current network. If the current network in ABC in not an AIG, the user should run command "strash" to make sure that the current network into an AIG before calling this procedure.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose ) { Ivy_Man_t * pMan; Abc_Ntk_t * pNtkNew; // make sure the network is an AIG assert( Abc_NtkIsStrash(pNtk) ); // convert the network into the AIG pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); // perform fast FPGA mapping Ivy_FastMapPerform( pMan, nLutSize, fRecovery, fVerbose ); // convert back into the ABC network pNtkNew = Ivy_ManFpgaToAbc( pNtk, pMan ); Ivy_FastMapStop( pMan ); Ivy_ManStop( pMan ); // make sure that the final network passes the test if ( pNtkNew != NULL && !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkFastMap: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Constructs the ABC network after mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjAbc, * pObj; Ivy_Obj_t * pObjIvy; Vec_Int_t * vNodes; int i; // start mapping from Ivy into Abc pMan->pCopy = Vec_PtrStart( Ivy_ManObjIdMax(pMan) + 1 ); // start the new ABC network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); // transfer the pointers to the basic nodes Abc_ObjSetIvy2Abc( pMan, Ivy_ManConst1(pMan)->Id, Abc_NtkCreateNodeConst1(pNtkNew) ); Abc_NtkForEachCi( pNtkNew, pObjAbc, i ) Abc_ObjSetIvy2Abc( pMan, Ivy_ManPi(pMan, i)->Id, pObjAbc ); // recursively construct the network vNodes = Vec_IntAlloc( 100 ); Ivy_ManForEachPo( pMan, pObjIvy, i ) { // get the new ABC node corresponding to the old fanin of the PO in IVY pObjAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ObjFanin0(pObjIvy), vNodes ); // consider the case of complemented fanin of the PO if ( Ivy_ObjFaninC0(pObjIvy) ) // complement { if ( Abc_ObjIsCi(pObjAbc) ) pObjAbc = Abc_NtkCreateNodeInv( pNtkNew, pObjAbc ); else { // clone the node pObj = Abc_NtkCloneObj( pObjAbc ); // set complemented functions pObj->pData = Hop_Not( (Hop_Obj_t *)pObjAbc->pData ); // return the new node pObjAbc = pObj; } } Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjAbc ); } Vec_IntFree( vNodes ); Vec_PtrFree( (Vec_Ptr_t *)pMan->pCopy ); pMan->pCopy = NULL; // remove dangling nodes Abc_NtkCleanup( pNtkNew, 0 ); // fix CIs feeding directly into COs Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); return pNtkNew; } /**Function************************************************************* Synopsis [Recursively construct the new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes ) { Vec_Int_t Supp, * vSupp = &Supp; Abc_Obj_t * pObjAbc, * pFaninAbc; Ivy_Obj_t * pNodeIvy; int i, Entry; // skip the node if it is a constant or already processed pObjAbc = Abc_ObjGetIvy2Abc( pMan, pObjIvy->Id ); if ( pObjAbc ) return pObjAbc; assert( Ivy_ObjIsAnd(pObjIvy) || Ivy_ObjIsExor(pObjIvy) ); // get the support of K-LUT Ivy_FastMapReadSupp( pMan, pObjIvy, vSupp ); // create new ABC node and its fanins pObjAbc = Abc_NtkCreateNode( pNtkNew ); Vec_IntForEachEntry( vSupp, Entry, i ) { pFaninAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ManObj(pMan, Entry), vNodes ); Abc_ObjAddFanin( pObjAbc, pFaninAbc ); } // collect the nodes used in the cut Ivy_ManCollectCut( pMan, pObjIvy, vSupp, vNodes ); // create the local function Ivy_ManForEachNodeVec( pMan, vNodes, pNodeIvy, i ) { if ( i < Vec_IntSize(vSupp) ) pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_IthVar( (Hop_Man_t *)pNtkNew->pManFunc, i ); else pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_And( (Hop_Man_t *)pNtkNew->pManFunc, (Hop_Obj_t *)Ivy_ObjChild0Equiv(pNodeIvy), (Hop_Obj_t *)Ivy_ObjChild1Equiv(pNodeIvy) ); } // set the local function pObjAbc->pData = (Abc_Obj_t *)pObjIvy->pEquiv; // set the node Abc_ObjSetIvy2Abc( pMan, pObjIvy->Id, pObjAbc ); return pObjAbc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcFraig.c000066400000000000000000000670661300674244400235250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFraig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures interfacing with the FRAIG package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFraig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "proof/fraig/fraig.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); static Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ); static void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs ); extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc ); static void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); static int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ); static void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Interfaces the network with the FRAIG package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) { Fraig_Params_t * pPars = (Fraig_Params_t *)pParams; Abc_Ntk_t * pNtkNew; Fraig_Man_t * pMan; // check if EXDC is present if ( fExdc && pNtk->pExdc == NULL ) fExdc = 0, printf( "Warning: Networks has no EXDC.\n" ); // perform fraiging pMan = (Fraig_Man_t *)Abc_NtkToFraig( pNtk, pParams, fAllNodes, fExdc ); // add algebraic choices // if ( pPars->fChoicing ) // Fraig_ManAddChoices( pMan, 0, 6 ); // prove the miter if asked to if ( pPars->fTryProve ) Fraig_ManProveMiter( pMan ); // reconstruct FRAIG in the new network if ( fExdc ) pNtkNew = Abc_NtkFromFraig2( pMan, pNtk ); else pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); Fraig_ManFree( pMan ); if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkFraig: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Transforms the strashed network into FRAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) { int fInternal = ((Fraig_Params_t *)pParams)->fInternal; Fraig_Man_t * pMan; ProgressBar * pProgress = NULL; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int i; assert( Abc_NtkIsStrash(pNtk) ); // create the FRAIG manager pMan = Fraig_ManCreate( (Fraig_Params_t *)pParams ); // map the constant node Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan); // create PIs and remember them in the old nodes Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, i); // perform strashing vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 ); if ( !fInternal ) pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjFaninNum(pNode) == 0 ) continue; if ( pProgress ) Extra_ProgressBarUpdate( pProgress, i, NULL ); pNode->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, Fraig_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ), Fraig_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ) ); } if ( pProgress ) Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); // use EXDC to change the mapping of nodes into FRAIG nodes if ( fExdc ) Abc_NtkFraigRemapUsingExdc( pMan, pNtk ); // set the primary outputs Abc_NtkForEachCo( pNtk, pNode, i ) Fraig_ManSetPo( pMan, (Fraig_Node_t *)Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); return pMan; } /**Function************************************************************* Synopsis [Derives EXDC node for the given network.] Description [Assumes that EXDCs of all POs are the same. Returns the EXDC of the first PO.] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc ) { Abc_Ntk_t * pNtkStrash; Abc_Obj_t * pObj; Fraig_Node_t * gResult; char ** ppNames; int i, k; // strash the EXDC network pNtkStrash = Abc_NtkStrash( pNtkExdc, 0, 0, 0 ); Abc_NtkCleanCopy( pNtkStrash ); Abc_AigConst1(pNtkStrash)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan); // set the mapping of the PI nodes ppNames = Abc_NtkCollectCioNames( pNtkMain, 0 ); Abc_NtkForEachCi( pNtkStrash, pObj, i ) { for ( k = 0; k < Abc_NtkCiNum(pNtkMain); k++ ) if ( strcmp( Abc_ObjName(pObj), ppNames[k] ) == 0 ) { pObj->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, k); break; } assert( pObj->pCopy != NULL ); } ABC_FREE( ppNames ); // build FRAIG for each node Abc_AigForEachAnd( pNtkStrash, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFaninC0(pObj) ), Fraig_NotCond( Abc_ObjFanin1(pObj)->pCopy, (int)Abc_ObjFaninC1(pObj) ) ); // get the EXDC to be returned pObj = Abc_NtkPo( pNtkStrash, 0 ); gResult = Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFaninC0(pObj) ); Abc_NtkDelete( pNtkStrash ); return gResult; } /**Function************************************************************* Synopsis [Changes mapping of the old nodes into FRAIG nodes using EXDC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) { Fraig_Node_t * gNodeNew, * gNodeExdc; stmm_table * tTable; stmm_generator * gen; Abc_Obj_t * pNode, * pNodeBest; Abc_Obj_t * pClass, ** ppSlot; Vec_Ptr_t * vNexts; int i; // get the global don't-cares assert( pNtk->pExdc ); gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc ); // save the next pointers vNexts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) Vec_PtrWriteEntry( vNexts, pNode->Id, pNode->pNext ); // find the classes of AIG nodes which have FRAIG nodes assigned Abc_NtkCleanNext( pNtk ); tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); Abc_NtkForEachNode( pNtk, pNode, i ) if ( pNode->pCopy ) { gNodeNew = Fraig_NodeAnd( pMan, (Fraig_Node_t *)pNode->pCopy, Fraig_Not(gNodeExdc) ); if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(gNodeNew), (char ***)&ppSlot ) ) *ppSlot = NULL; pNode->pNext = *ppSlot; *ppSlot = pNode; } // for reach non-trival class, find the node with minimum level, and replace other nodes by it Abc_AigSetNodePhases( pNtk ); stmm_foreach_item( tTable, gen, (char **)&gNodeNew, (char **)&pClass ) { if ( pClass->pNext == NULL ) continue; // find the node with minimum level pNodeBest = pClass; for ( pNode = pClass->pNext; pNode; pNode = pNode->pNext ) if ( pNodeBest->Level > pNode->Level ) pNodeBest = pNode; // remap the class nodes for ( pNode = pClass; pNode; pNode = pNode->pNext ) pNode->pCopy = Abc_ObjNotCond( pNodeBest->pCopy, pNode->fPhase ^ pNodeBest->fPhase ); } stmm_free_table( tTable ); // restore the next pointers Abc_NtkCleanNext( pNtk ); Abc_NtkForEachNode( pNtk, pNode, i ) pNode->pNext = (Abc_Obj_t *)Vec_PtrEntry( vNexts, pNode->Id ); Vec_PtrFree( vNexts ); } /**Function************************************************************* Synopsis [Transforms FRAIG into strashed network with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pNodeNew; int i; // create the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // make the mapper point to the new network Abc_NtkForEachCi( pNtk, pNode, i ) Fraig_NodeSetData1( Fraig_ManReadIthVar(pMan, i), (Fraig_Node_t *)pNode->pCopy ); // set the constant node Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew) ); // process the nodes in topological order pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); pNodeNew = Abc_NodeFromFraig_rec( pNtkNew, Fraig_ManReadOutputs(pMan)[i] ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Extra_ProgressBarStop( pProgress ); Abc_NtkReassignIds( pNtkNew ); return pNtkNew; } /**Function************************************************************* Synopsis [Transforms into AIG one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ) { Abc_Obj_t * pRes, * pRes0, * pRes1, * pResMin, * pResCur; Fraig_Node_t * pNodeTemp, * pNodeFraigR = Fraig_Regular(pNodeFraig); void ** ppTail; // check if the node was already considered if ( (pRes = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeFraigR)) ) return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) ); // solve the children pRes0 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadOne(pNodeFraigR) ); pRes1 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadTwo(pNodeFraigR) ); // derive the new node pRes = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pRes0, pRes1 ); pRes->fPhase = Fraig_NodeReadSimInv( pNodeFraigR ); // if the node has an equivalence class, find its representative if ( Fraig_NodeReadRepr(pNodeFraigR) == NULL && Fraig_NodeReadNextE(pNodeFraigR) != NULL ) { // go through the FRAIG nodes belonging to this equivalence class // and find the representative node (the node with the smallest level) pResMin = pRes; for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) ) { assert( Fraig_NodeReadData1(pNodeTemp) == NULL ); pResCur = Abc_NodeFromFraig_rec( pNtkNew, pNodeTemp ); if ( pResMin->Level > pResCur->Level ) pResMin = pResCur; } // link the nodes in such a way that representative goes first ppTail = &pResMin->pData; if ( pRes != pResMin ) { *ppTail = pRes; ppTail = &pRes->pData; } for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) ) { pResCur = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeTemp); assert( pResCur ); if ( pResMin == pResCur ) continue; *ppTail = pResCur; ppTail = &pResCur->pData; } assert( *ppTail == NULL ); // update the phase of the node pRes = Abc_ObjNotCond( pResMin, (pRes->fPhase ^ pResMin->fPhase) ); } Fraig_NodeSetData1( pNodeFraigR, (Fraig_Node_t *)pRes ); return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) ); } /**Function************************************************************* Synopsis [Transforms FRAIG into strashed network without choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; stmm_table * tTable; Vec_Ptr_t * vNodeReprs; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pRepr, ** ppSlot; int i; // map the nodes into their lowest level representives tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); pNode = Abc_AigConst1(pNtk); if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) *ppSlot = pNode; Abc_NtkForEachCi( pNtk, pNode, i ) if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) *ppSlot = pNode; Abc_NtkForEachNode( pNtk, pNode, i ) if ( pNode->pCopy ) { if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) *ppSlot = pNode; else if ( (*ppSlot)->Level > pNode->Level ) *ppSlot = pNode; } // save representatives for each node vNodeReprs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) if ( pNode->pCopy ) { if ( !stmm_lookup( tTable, (char *)Fraig_Regular(pNode->pCopy), (char **)&pRepr ) ) assert( 0 ); if ( pNode != pRepr ) Vec_PtrWriteEntry( vNodeReprs, pNode->Id, pRepr ); } stmm_free_table( tTable ); // create the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // perform strashing Abc_AigSetNodePhases( pNtk ); Abc_NtkIncrementTravId( pNtk ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs ); } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodeReprs ); // finalize the network Abc_NtkFinalize( pNtk, pNtkNew ); return pNtkNew; } /**Function************************************************************* Synopsis [Transforms into AIG one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs ) { Abc_Obj_t * pRepr; // skip the PIs and constants if ( Abc_ObjFaninNum(pNode) < 2 ) return; // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); assert( Abc_ObjIsNode( pNode ) ); // get the node's representative if ( (pRepr = (Abc_Obj_t *)Vec_PtrEntry(vNodeReprs, pNode->Id)) ) { Abc_NtkFromFraig2_rec( pNtkNew, pRepr, vNodeReprs ); pNode->pCopy = Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pNode->fPhase ); return; } Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs ); Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin1(pNode), vNodeReprs ); pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } /**Function************************************************************* Synopsis [Interfaces the network with the FRAIG package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; if ( !Abc_NtkIsSopLogic(pNtk) ) { printf( "Abc_NtkFraigTrust: Trust mode works for netlists and logic SOP networks.\n" ); return NULL; } if ( !Abc_NtkFraigTrustCheck(pNtk) ) { printf( "Abc_NtkFraigTrust: The network does not look like an AIG with choice nodes.\n" ); return NULL; } // perform strashing pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); Abc_NtkFraigTrustOne( pNtk, pNtkNew ); Abc_NtkFinalize( pNtk, pNtkNew ); Abc_NtkReassignIds( pNtkNew ); // print a warning about choice nodes printf( "Warning: The resulting AIG contains %d choice nodes.\n", Abc_NtkGetChoiceNum( pNtkNew ) ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkFraigTrust: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Checks whether the node can be processed in the trust mode.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, nFanins; Abc_NtkForEachNode( pNtk, pNode, i ) { nFanins = Abc_ObjFaninNum(pNode); if ( nFanins < 2 ) continue; if ( nFanins == 2 && Abc_SopIsAndType((char *)pNode->pData) ) continue; if ( !Abc_SopIsOrType((char *)pNode->pData) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Interfaces the network with the FRAIG package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { ProgressBar * pProgress; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pNodeNew, * pObj; int i; // perform strashing vNodes = Abc_NtkDfs( pNtk, 0 ); pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // get the node assert( Abc_ObjIsNode(pNode) ); // strash the node pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode ); // get the old object if ( Abc_NtkIsNetlist(pNtk) ) pObj = Abc_ObjFanout0( pNode ); // the fanout net else pObj = pNode; // the node itself // make sure the node is not yet strashed assert( pObj->pCopy == NULL ); // mark the old object with the new AIG node pObj->pCopy = pNodeNew; } Vec_PtrFree( vNodes ); Extra_ProgressBarStop( pProgress ); } /**Function************************************************************* Synopsis [Transforms one node into a FRAIG in the trust mode.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) { Abc_Obj_t * pSum, * pFanin; void ** ppTail; int i, nFanins, fCompl; assert( Abc_ObjIsNode(pNode) ); // get the number of node's fanins nFanins = Abc_ObjFaninNum( pNode ); assert( nFanins == Abc_SopGetVarNum((char *)pNode->pData) ); // check if it is a constant if ( nFanins == 0 ) return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Abc_SopIsConst0((char *)pNode->pData) ); if ( nFanins == 1 ) return Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_SopIsInv((char *)pNode->pData) ); if ( nFanins == 2 && Abc_SopIsAndType((char *)pNode->pData) ) return Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, !Abc_SopGetIthCareLit((char *)pNode->pData,0) ), Abc_ObjNotCond( Abc_ObjFanin1(pNode)->pCopy, !Abc_SopGetIthCareLit((char *)pNode->pData,1) ) ); assert( Abc_SopIsOrType((char *)pNode->pData) ); fCompl = Abc_SopGetIthCareLit((char *)pNode->pData,0); // get the root of the choice node (the first fanin) pSum = Abc_ObjFanin0(pNode)->pCopy; // connect other fanins ppTail = &pSum->pData; Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( i == 0 ) continue; *ppTail = pFanin->pCopy; ppTail = &pFanin->pCopy->pData; // set the complemented bit of this cut if ( fCompl ^ Abc_SopGetIthCareLit((char *)pNode->pData, i) ) pFanin->pCopy->fPhase = 1; } assert( *ppTail == NULL ); return pSum; } /**Function************************************************************* Synopsis [Interfaces the network with the FRAIG package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd ) { Vec_Ptr_t * vStore; Abc_Ntk_t * pNtk; // create the network to be stored pNtk = Abc_NtkStrash( pNtkAdd, 0, 0, 0 ); if ( pNtk == NULL ) { printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" ); return 0; } // get the network currently stored vStore = Abc_FrameReadStore(); if ( Vec_PtrSize(vStore) > 0 ) { // check that the networks have the same PIs extern int Abc_NodeCompareCiCo( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); if ( !Abc_NodeCompareCiCo(pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0)) ) { // reorder PIs of pNtk2 according to pNtk1 if ( !Abc_NtkCompareSignals( pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0), 1, 1 ) ) { printf( "Trying to store the network with different primary inputs.\n" ); printf( "The previously stored networks are deleted and this one is added.\n" ); Abc_NtkFraigStoreClean(); } } } Vec_PtrPush( vStore, pNtk ); // printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) ); return 1; } /**Function************************************************************* Synopsis [Interfaces the network with the FRAIG package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFraigRestore( int nPatsRand, int nPatsDyna, int nBTLimit ) { extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ); Fraig_Params_t Params; Vec_Ptr_t * vStore; Abc_Ntk_t * pNtk, * pFraig; int nWords1, nWords2, nWordsMin; // abctime clk = Abc_Clock(); // get the stored network vStore = Abc_FrameReadStore(); if ( Vec_PtrSize(vStore) == 0 ) { printf( "There are no network currently in storage.\n" ); return NULL; } // printf( "Currently stored %d networks will be fraiged.\n", Vec_PtrSize(vStore) ); pNtk = (Abc_Ntk_t *)Vec_PtrEntry( vStore, 0 ); // swap the first and last network // this should lead to the primary choice being "better" because of synthesis if ( Vec_PtrSize(vStore) > 1 ) { pNtk = (Abc_Ntk_t *)Vec_PtrPop( vStore ); Vec_PtrPush( vStore, Vec_PtrEntry(vStore,0) ); Vec_PtrWriteEntry( vStore, 0, pNtk ); } // to determine the number of simulation patterns // use the following strategy // at least 64 words (32 words random and 32 words dynamic) // no more than 256M for one circuit (128M + 128M) nWords1 = 32; nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk)); nWordsMin = Abc_MinInt( nWords1, nWords2 ); // set parameters for fraiging Fraig_ParamsSetDefault( &Params ); Params.nPatsRand = nPatsRand ? nPatsRand : nWordsMin * 32; // the number of words of random simulation info Params.nPatsDyna = nPatsDyna ? nPatsDyna : nWordsMin * 32; // the number of words of dynamic simulation info Params.nBTLimit = nBTLimit; // the max number of backtracks to perform Params.fFuncRed = 1; // performs only one level hashing Params.fFeedBack = 1; // enables solver feedback Params.fDist1Pats = 1; // enables distance-1 patterns Params.fDoSparse = 1; // performs equiv tests for sparse functions Params.fChoicing = 1; // enables recording structural choices Params.fTryProve = 0; // tries to solve the final miter Params.fInternal = 1; // does not show progress bar Params.fVerbose = 0; // the verbosiness flag // perform partitioned computation of structural choices pFraig = Abc_NtkFraigPartitioned( vStore, &Params ); Abc_NtkFraigStoreClean(); //ABC_PRT( "Total choicing time", Abc_Clock() - clk ); return pFraig; } /**Function************************************************************* Synopsis [Interfaces the network with the FRAIG package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigStoreClean() { Vec_Ptr_t * vStore; Abc_Ntk_t * pNtk; int i; vStore = Abc_FrameReadStore(); Vec_PtrForEachEntry( Abc_Ntk_t *, vStore, pNtk, i ) Abc_NtkDelete( pNtk ); Vec_PtrClear( vStore ); } /**Function************************************************************* Synopsis [Checks the correctness of stored networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig ) { Abc_Obj_t * pNode0, * pNode1; int nPoOrig, nPoFinal, nStored; int i, k; // check that the PO functions are correct nPoFinal = Abc_NtkPoNum(pFraig); nStored = Abc_FrameReadStoreSize(); assert( nPoFinal % nStored == 0 ); nPoOrig = nPoFinal / nStored; for ( i = 0; i < nPoOrig; i++ ) { pNode0 = Abc_ObjFanin0( Abc_NtkPo(pFraig, i) ); for ( k = 1; k < nStored; k++ ) { pNode1 = Abc_ObjFanin0( Abc_NtkPo(pFraig, k*nPoOrig+i) ); if ( pNode0 != pNode1 ) printf( "Verification for PO #%d of network #%d has failed. The PO function is not used.\n", i+1, k+1 ); } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcFx.c000066400000000000000000001326401300674244400230410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFx.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Implementation of traditional "fast_extract" algorithm.] Author [Alan Mishchenko, Bruno Schmitt] Affiliation [UC Berkeley, UFRGS] Date [Ver. 1.0. Started - April 26, 2013.] Revision [$Id: abcFx.c,v 1.00 2013/04/26 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "misc/vec/vecWec.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecHsh.h" #include "opt/fxch/Fxch.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* The code in this file implements the traditional "fast_extract" algorithm, which extracts two-cube divisors concurrently with single-cube two-literal divisors, as proposed in the TCAD'92 paper by J. Rajski and J. Vasudevamurthi. Integration notes: It is assumed that each object (primary input or internal node) in the original network is associated with a unique integer number, called object identifier (ObjId, for short). The user's input data given to 'fast_extract" is an array of cubes (pMan->vCubes). Each cube is an array of integers, in which the first entry contains ObjId of the node, to which this cube belongs in the original network. The following entries of a cube are SOP literals of this cube. Each literal is represtned as 2*FaninId + ComplAttr, where FaninId is ObjId of the fanin node and ComplAttr is 1 if literal is complemented, and 0 otherwise. The user's output data produced by 'fast_extract' is also an array of cubes (pMan->vCubes). If no divisors have been extracted, the output array is the same as the input array. If some divisors have been extracted, the output array contains updated old cubes and new cubes representing the extracted divisors. The new divisors have their ObjId starting from the largest ObjId used in the cubes. To give the user more flexibility, which may be needed when some ObjIds are already used for primary output nodes, which do not participate in fast_extract, the parameter ObjIdMax is passed to procedure Fx_FastExtract(). The new divisors will receive their ObjId starting from ObjIdMax onward, as divisor extaction proceeds. The following two requirements are imposed on the input and output array of cubes: (1) The array of cubes should be sorted by the first entry in each cube (that is, cubes belonging to the same node should form a contiguous range). (2) Literals in a cube should be sorted in the increasing order of the integer numbers. To integrate this code into a calling application, such as ABC, the input cube array should be generated (below this is done by the procedure Abc_NtkFxRetrieve) and the output cube array should be incorporated into the current network (below this is done by the procedure Abc_NtkFxInsert). In essence, the latter procedure performs the following: - removes the current fanins and SOPs of each node in the network - adds new nodes for each new divisor introduced by "fast_extract" - populates fanins and SOPs of each node, both old and new, as indicaded by the resulting cube array. Implementation notes: The implementation is optimized for simplicity and speed of computation. (1) Main input/output data-structure (pMan->vCubes) is the array of cubes which is dynamically updated by the algorithm. (2) Auxiliary data-structure (pMan->vLits) is the array of arrays. The i-th array contains IDs of cubes which have literal i. It may be convenient to think about the first (second) array as rows (columns) of a sparse matrix, although the sparse matrix data-structure is not used in the proposed implementation. (3) Hash table (pMan->pHash) hashes the normalized divisors (represented as integer arrays) into integer numbers. (4) Array of divisor weights (pMan->vWeights), that is, the number of SOP literals to be saved by extacting each divisor. (5) Priority queue (pMan->vPrio), which sorts divisor (integer numbers) by their weight (6) Integer array (pMan->vVarCube), which maps each ObjId into the first cube of this object, or -1, if there is no cubes as in the case of a primary input. */ typedef struct Fx_Man_t_ Fx_Man_t; struct Fx_Man_t_ { // user's data Vec_Wec_t * vCubes; // cube -> lit int LitCountMax;// max size of divisor to extract int fCanonDivs; // use only AND/XOR/MUX // internal data Vec_Wec_t * vLits; // lit -> cube Vec_Int_t * vCounts; // literal counts (currently not used) Hsh_VecMan_t * pHash; // hash table for normalized divisors Vec_Flt_t * vWeights; // divisor weights Vec_Que_t * vPrio; // priority queue for divisors by weight Vec_Int_t * vVarCube; // mapping ObjId into its first cube Vec_Int_t * vLevels; // variable levels // temporary data to update the data-structure when a divisor is extracted Vec_Int_t * vCubesS; // single cubes for the given divisor Vec_Int_t * vCubesD; // cube pairs for the given divisor Vec_Int_t * vCompls; // complemented attribute of each cube pair Vec_Int_t * vCubeFree; // cube-free divisor Vec_Int_t * vDiv; // selected divisor Vec_Int_t * vSCC; // single cubes containment cubes // statistics abctime timeStart; // starting time int nVars; // original problem variables int nLits; // the number of SOP literals int nDivs; // the number of extracted divisors int nCompls; // the number of complements int nPairsS; // number of lit pairs int nPairsD; // number of cube pairs int nDivsS; // single cube divisors int nDivMux[3]; // 0 = mux, 1 = compl mux, 2 = no mux }; static inline int Fx_ManGetFirstVarCube( Fx_Man_t * p, Vec_Int_t * vCube ) { return Vec_IntEntry( p->vVarCube, Vec_IntEntry(vCube, 0) ); } #define Fx_ManForEachCubeVec( vVec, vCubes, vCube, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((vCube) = Vec_WecEntry(vCubes, Vec_IntEntry(vVec, i))); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Retrieves SOP information for fast_extract.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Abc_NtkFxRetrieve( Abc_Ntk_t * pNtk ) { Vec_Wec_t * vCubes; Vec_Int_t * vCube; Abc_Obj_t * pNode; char * pCube, * pSop; int nVars, i, v, Lit; assert( Abc_NtkIsSopLogic(pNtk) ); vCubes = Vec_WecAlloc( 1000 ); Abc_NtkForEachNode( pNtk, pNode, i ) { pSop = (char *)pNode->pData; nVars = Abc_SopGetVarNum(pSop); assert( nVars == Abc_ObjFaninNum(pNode) ); // if ( nVars < 2 ) continue; Abc_SopForEachCube( pSop, nVars, pCube ) { vCube = Vec_WecPushLevel( vCubes ); Vec_IntPush( vCube, Abc_ObjId(pNode) ); Abc_CubeForEachVar( pCube, Lit, v ) { if ( Lit == '0' ) Vec_IntPush( vCube, Abc_Var2Lit(Abc_ObjFaninId(pNode, v), 1) ); else if ( Lit == '1' ) Vec_IntPush( vCube, Abc_Var2Lit(Abc_ObjFaninId(pNode, v), 0) ); } Vec_IntSelectSort( Vec_IntArray(vCube) + 1, Vec_IntSize(vCube) - 1 ); } } return vCubes; } /**Function************************************************************* Synopsis [Inserts SOP information after fast_extract.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFxInsert( Abc_Ntk_t * pNtk, Vec_Wec_t * vCubes ) { Vec_Int_t * vCube, * vPres, * vFirst, * vCount; Abc_Obj_t * pNode, * pFanin; char * pCube, * pSop; int i, k, v, Lit, iFanin, iNodeMax = 0; assert( Abc_NtkIsSopLogic(pNtk) ); // check that cubes have no gaps and are ordered by first node Lit = -1; Vec_WecForEachLevel( vCubes, vCube, i ) { assert( Vec_IntSize(vCube) > 0 ); assert( Lit <= Vec_IntEntry(vCube, 0) ); Lit = Vec_IntEntry(vCube, 0); } // find the largest index Vec_WecForEachLevel( vCubes, vCube, i ) iNodeMax = Abc_MaxInt( iNodeMax, Vec_IntEntry(vCube, 0) ); // quit if nothing changes if ( iNodeMax < Abc_NtkObjNumMax(pNtk) ) { printf( "The network is unchanged by fast extract.\n" ); return; } // create new nodes for ( i = Abc_NtkObjNumMax(pNtk); i <= iNodeMax; i++ ) { pNode = Abc_NtkCreateNode( pNtk ); assert( i == (int)Abc_ObjId(pNode) ); } // create node fanins vFirst = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); vCount = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); Vec_WecForEachLevel( vCubes, vCube, i ) { iFanin = Vec_IntEntry( vCube, 0 ); if ( Vec_IntEntry(vCount, iFanin) == 0 ) Vec_IntWriteEntry( vFirst, iFanin, i ); Vec_IntAddToEntry( vCount, iFanin, 1 ); } // create node SOPs vPres = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { // if ( Vec_IntEntry(vCount, i) == 0 ) continue; Abc_ObjRemoveFanins( pNode ); // create fanins assert( Vec_IntEntry(vCount, i) > 0 ); for ( k = 0; k < Vec_IntEntry(vCount, i); k++ ) { vCube = Vec_WecEntry( vCubes, Vec_IntEntry(vFirst, i) + k ); assert( Vec_IntEntry( vCube, 0 ) == i ); Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) { pFanin = Abc_NtkObj(pNtk, Abc_Lit2Var(Lit)); if ( Vec_IntEntry(vPres, Abc_ObjId(pFanin)) >= 0 ) continue; Vec_IntWriteEntry(vPres, Abc_ObjId(pFanin), Abc_ObjFaninNum(pNode)); Abc_ObjAddFanin( pNode, pFanin ); } } // create SOP pSop = pCube = Abc_SopStart( (Mem_Flex_t *)pNtk->pManFunc, Vec_IntEntry(vCount, i), Abc_ObjFaninNum(pNode) ); for ( k = 0; k < Vec_IntEntry(vCount, i); k++ ) { vCube = Vec_WecEntry( vCubes, Vec_IntEntry(vFirst, i) + k ); assert( Vec_IntEntry( vCube, 0 ) == i ); Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) { pFanin = Abc_NtkObj(pNtk, Abc_Lit2Var(Lit)); iFanin = Vec_IntEntry(vPres, Abc_ObjId(pFanin)); assert( iFanin >= 0 && iFanin < Abc_ObjFaninNum(pNode) ); pCube[iFanin] = Abc_LitIsCompl(Lit) ? '0' : '1'; } pCube += Abc_ObjFaninNum(pNode) + 3; } // complement SOP if the original one was complemented if ( pNode->pData && Abc_SopIsComplement((char *)pNode->pData) ) Abc_SopComplement( pSop ); pNode->pData = pSop; // clean fanins Abc_ObjForEachFanin( pNode, pFanin, v ) Vec_IntWriteEntry( vPres, Abc_ObjId(pFanin), -1 ); } Vec_IntFree( vFirst ); Vec_IntFree( vCount ); Vec_IntFree( vPres ); } /**Function************************************************************* Synopsis [Makes sure the nodes do not have complemented and duplicated fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFxCheck( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; // Abc_NtkForEachObj( pNtk, pNode, i ) // Abc_ObjPrint( stdout, pNode ); Abc_NtkForEachNode( pNtk, pNode, i ) if ( !Vec_IntCheckUniqueSmall( &pNode->vFanins ) ) return 0; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ) { extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ); Vec_Wec_t * vCubes; assert( Abc_NtkIsSopLogic(pNtk) ); // check unique fanins if ( !Abc_NtkFxCheck(pNtk) ) { printf( "Abc_NtkFastExtract: Nodes have duplicated fanins. FX is not performed.\n" ); return 0; } // collect information about the covers vCubes = Abc_NtkFxRetrieve( pNtk ); // call the fast extract procedure if ( Fx_FastExtract( vCubes, Abc_NtkObjNumMax(pNtk), nNewNodesMax, LitCountMax, fCanonDivs, fVerbose, fVeryVerbose ) > 0 ) { // update the network Abc_NtkFxInsert( pNtk, vCubes ); Vec_WecFree( vCubes ); if ( !Abc_NtkCheck( pNtk ) ) printf( "Abc_NtkFxPerform: The network check has failed.\n" ); return 1; } else printf( "Warning: The network has not been changed by \"fx\".\n" ); Vec_WecFree( vCubes ); return 0; } /**Function************************************************************* Synopsis [Starting the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fx_Man_t * Fx_ManStart( Vec_Wec_t * vCubes ) { Fx_Man_t * p; p = ABC_CALLOC( Fx_Man_t, 1 ); p->vCubes = vCubes; // temporary data p->vCubesS = Vec_IntAlloc( 100 ); p->vCubesD = Vec_IntAlloc( 100 ); p->vCompls = Vec_IntAlloc( 100 ); p->vCubeFree = Vec_IntAlloc( 100 ); p->vDiv = Vec_IntAlloc( 100 ); p->vSCC = Vec_IntAlloc( 100 ); return p; } void Fx_ManStop( Fx_Man_t * p ) { // Vec_WecFree( p->vCubes ); Vec_WecFree( p->vLits ); Vec_IntFree( p->vCounts ); Hsh_VecManStop( p->pHash ); Vec_FltFree( p->vWeights ); Vec_QueFree( p->vPrio ); Vec_IntFree( p->vVarCube ); Vec_IntFree( p->vLevels ); // temporary data Vec_IntFree( p->vCubesS ); Vec_IntFree( p->vCubesD ); Vec_IntFree( p->vCompls ); Vec_IntFree( p->vCubeFree ); Vec_IntFree( p->vDiv ); Vec_IntFree( p->vSCC ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Compute levels of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fx_ManComputeLevelDiv( Fx_Man_t * p, Vec_Int_t * vCubeFree ) { int i, Lit, Level = 0; Vec_IntForEachEntry( vCubeFree, Lit, i ) Level = Abc_MaxInt( Level, Vec_IntEntry(p->vLevels, Abc_Lit2Var(Abc_Lit2Var(Lit))) ); return Abc_MinInt( Level, 800 ); } static inline int Fx_ManComputeLevelCube( Fx_Man_t * p, Vec_Int_t * vCube ) { int k, Lit, Level = 0; Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) Level = Abc_MaxInt( Level, Vec_IntEntry(p->vLevels, Abc_Lit2Var(Lit)) ); return Level; } void Fx_ManComputeLevel( Fx_Man_t * p ) { Vec_Int_t * vCube; int i, iVar, iFirst = 0; iVar = Vec_IntEntry( Vec_WecEntry(p->vCubes,0), 0 ); p->vLevels = Vec_IntStart( p->nVars ); Vec_WecForEachLevel( p->vCubes, vCube, i ) { if ( iVar != Vec_IntEntry(vCube, 0) ) { // add the number of cubes Vec_IntAddToEntry( p->vLevels, iVar, i - iFirst ); iVar = Vec_IntEntry(vCube, 0); iFirst = i; } Vec_IntUpdateEntry( p->vLevels, iVar, Fx_ManComputeLevelCube(p, vCube) ); } } /**Function************************************************************* Synopsis [Printing procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fx_PrintDivArray( Vec_Int_t * vDiv ) { int i, Lit; Vec_IntForEachEntry( vDiv, Lit, i ) if ( !Abc_LitIsCompl(Lit) ) printf( "%d(1)", Abc_Lit2Var(Lit) ); printf( " + " ); Vec_IntForEachEntry( vDiv, Lit, i ) if ( Abc_LitIsCompl(Lit) ) printf( "%d(2)", Abc_Lit2Var(Lit) ); } static inline void Fx_PrintDiv( Fx_Man_t * p, int iDiv ) { int i; printf( "%4d : ", p->nDivs ); printf( "Div %7d : ", iDiv ); printf( "Weight %12.5f ", Vec_FltEntry(p->vWeights, iDiv) ); Fx_PrintDivArray( Hsh_VecReadEntry(p->pHash, iDiv) ); for ( i = Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) + 3; i < 16; i++ ) printf( " " ); printf( "Lits =%7d ", p->nLits ); printf( "Divs =%8d ", Hsh_VecSize(p->pHash) ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->timeStart ); } static void Fx_PrintDivisors( Fx_Man_t * p ) { int iDiv; for ( iDiv = 0; iDiv < Vec_FltSize(p->vWeights); iDiv++ ) Fx_PrintDiv( p, iDiv ); } static void Fx_PrintStats( Fx_Man_t * p, abctime clk ) { printf( "Cubes =%8d ", Vec_WecSizeUsed(p->vCubes) ); printf( "Lits =%8d ", Vec_WecSizeUsed(p->vLits) ); printf( "Divs =%8d ", Hsh_VecSize(p->pHash) ); printf( "Divs+ =%8d ", Vec_QueSize(p->vPrio) ); printf( "Compl =%8d ", p->nDivMux[1] ); printf( "Extr =%7d ", p->nDivs ); Abc_PrintTime( 1, "Time", clk ); } /**Function************************************************************* Synopsis [Returns 1 if the divisor should be complemented.] Description [Normalizes the divisor by putting, first, positive control literal first and, second, positive data1 literal. As the result, a MUX divisor is (ab + !ac) and an XOR divisor is (ab + !a!b).] SideEffects [] SeeAlso [] ***********************************************************************/ static int Fx_ManDivNormalize( Vec_Int_t * vCubeFree ) // return 1 if complemented { int * L = Vec_IntArray(vCubeFree); int RetValue = 0, LitA0 = -1, LitB0 = -1, LitA1 = -1, LitB1 = -1; assert( Vec_IntSize(vCubeFree) == 4 ); if ( Abc_LitIsCompl(L[0]) != Abc_LitIsCompl(L[1]) && (L[0] >> 2) == (L[1] >> 2) ) // diff cubes, same vars { if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[3]) ) return -1; LitA0 = Abc_Lit2Var(L[0]), LitB0 = Abc_Lit2Var(L[1]); if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[2]) ) { assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[3]) ); LitA1 = Abc_Lit2Var(L[2]), LitB1 = Abc_Lit2Var(L[3]); } else { assert( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) ); assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[2]) ); LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[2]); } } else if ( Abc_LitIsCompl(L[1]) != Abc_LitIsCompl(L[2]) && (L[1] >> 2) == (L[2] >> 2) ) { if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) ) return -1; LitA0 = Abc_Lit2Var(L[1]), LitB0 = Abc_Lit2Var(L[2]); if ( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[0]) ) LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[3]); else LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[0]); } else if ( Abc_LitIsCompl(L[2]) != Abc_LitIsCompl(L[3]) && (L[2] >> 2) == (L[3] >> 2) ) { if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[1]) ) return -1; LitA0 = Abc_Lit2Var(L[2]), LitB0 = Abc_Lit2Var(L[3]); if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[0]) ) LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[1]); else LitA1 = Abc_Lit2Var(L[1]), LitB1 = Abc_Lit2Var(L[0]); } else return -1; assert( LitA0 == Abc_LitNot(LitB0) ); if ( Abc_LitIsCompl(LitA0) ) { ABC_SWAP( int, LitA0, LitB0 ); ABC_SWAP( int, LitA1, LitB1 ); } assert( !Abc_LitIsCompl(LitA0) ); if ( Abc_LitIsCompl(LitA1) ) { LitA1 = Abc_LitNot(LitA1); LitB1 = Abc_LitNot(LitB1); RetValue = 1; } assert( !Abc_LitIsCompl(LitA1) ); // arrange literals in such as a way that // - the first two literals are control literals from different cubes // - the third literal is non-complented data input // - the forth literal is possibly complemented data input L[0] = Abc_Var2Lit( LitA0, 0 ); L[1] = Abc_Var2Lit( LitB0, 1 ); L[2] = Abc_Var2Lit( LitA1, 0 ); L[3] = Abc_Var2Lit( LitB1, 1 ); return RetValue; } /**Function************************************************************* Synopsis [Find a cube-free divisor of the two cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fx_ManDivFindCubeFree( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vCubeFree, int * fWarning ) { int * pBeg1 = Vec_IntArray( vArr1 ) + 1; // skip variable ID int * pBeg2 = Vec_IntArray( vArr2 ) + 1; // skip variable ID int * pEnd1 = Vec_IntLimit( vArr1 ); int * pEnd2 = Vec_IntLimit( vArr2 ); int Counter = 0, fAttr0 = 0, fAttr1 = 1; Vec_IntClear( vCubeFree ); while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) pBeg1++, pBeg2++, Counter++; else if ( *pBeg1 < *pBeg2 ) Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) ); else { if ( Vec_IntSize(vCubeFree) == 0 ) fAttr0 = 1, fAttr1 = 0; Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) ); } } while ( pBeg1 < pEnd1 ) Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) ); while ( pBeg2 < pEnd2 ) Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) ); if ( Vec_IntSize(vCubeFree) == 0 ) printf( "The SOP has duplicated cubes.\n" ); else if ( Vec_IntSize(vCubeFree) == 1 ) return -1; else if ( Vec_IntSize( vCubeFree ) == 3 ) { int * pArray = Vec_IntArray( vCubeFree ); if ( Abc_Lit2Var( pArray[0] ) == Abc_LitNot( Abc_Lit2Var( pArray[1] ) ) ) { if ( Abc_LitIsCompl( pArray[0] ) == Abc_LitIsCompl( pArray[2] ) ) Vec_IntDrop( vCubeFree, 0 ); else Vec_IntDrop( vCubeFree, 1 ); } else if ( Abc_Lit2Var( pArray[1] ) == Abc_LitNot( Abc_Lit2Var( pArray[2] ) ) ) { if ( Abc_LitIsCompl( pArray[1] ) == Abc_LitIsCompl( pArray[0] ) ) Vec_IntDrop( vCubeFree, 1 ); else Vec_IntDrop( vCubeFree, 2 ); } if ( Vec_IntSize( vCubeFree ) == 2 ) { int Lit0 = Abc_Lit2Var( pArray[0] ), Lit1 = Abc_Lit2Var( pArray[1] ); if ( Lit0 > Lit1 ) ABC_SWAP( int, Lit0, Lit1 ); Vec_IntWriteEntry( vCubeFree, 0, Abc_Var2Lit( Lit0, 0 ) ); Vec_IntWriteEntry( vCubeFree, 1, Abc_Var2Lit( Lit1, 1 ) ); } } assert( !Abc_LitIsCompl(Vec_IntEntry(vCubeFree, 0)) ); return Counter; } /**Function************************************************************* Synopsis [Procedures operating on a two-cube divisor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fx_ManDivFindPivots( Vec_Int_t * vDiv, int * pLit0, int * pLit1 ) { int i, Lit; *pLit0 = -1; *pLit1 = -1; Vec_IntForEachEntry( vDiv, Lit, i ) { if ( Abc_LitIsCompl(Lit) ) { if ( *pLit1 == -1 ) *pLit1 = Abc_Lit2Var(Lit); } else { if ( *pLit0 == -1 ) *pLit0 = Abc_Lit2Var(Lit); } if ( *pLit0 >= 0 && *pLit1 >= 0 ) return; } } static inline int Fx_ManDivRemoveLits( Vec_Int_t * vCube, Vec_Int_t * vDiv, int fCompl ) { int i, Lit, Count = 0; assert( !fCompl || Vec_IntSize(vDiv) == 4 ); Vec_IntForEachEntry( vDiv, Lit, i ) { Count += Vec_IntRemove1( vCube, Abc_Lit2Var(Lit) ^ (fCompl && i > 1) ); // the last two lits can be complemented if ( Vec_IntSize( vDiv ) == 2 ) Count += Vec_IntRemove1( vCube, Abc_LitNot( Abc_Lit2Var(Lit) ) ); } return Count; } static inline void Fx_ManDivAddLits( Vec_Int_t * vCube, Vec_Int_t * vCube2, Vec_Int_t * vDiv ) { int i, Lit, * pArray; // Vec_IntClear( vCube ); // Vec_IntClear( vCube2 ); Vec_IntForEachEntry( vDiv, Lit, i ) if ( Abc_LitIsCompl(Lit) ) Vec_IntPush( vCube2, Abc_Lit2Var(Lit) ); else Vec_IntPush( vCube, Abc_Lit2Var(Lit) ); if ( Vec_IntSize(vDiv) == 4 && Vec_IntSize(vCube) == 3 ) { assert( Vec_IntSize(vCube2) == 3 ); pArray = Vec_IntArray(vCube); if ( pArray[1] > pArray[2] ) ABC_SWAP( int, pArray[1], pArray[2] ); pArray = Vec_IntArray(vCube2); if ( pArray[1] > pArray[2] ) ABC_SWAP( int, pArray[1], pArray[2] ); } } /**Function************************************************************* Synopsis [Setting up the data-structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fx_ManCreateLiterals( Fx_Man_t * p, int nVars ) { Vec_Int_t * vCube; int i, k, Lit, Count; // find the number of variables p->nVars = p->nLits = 0; Vec_WecForEachLevel( p->vCubes, vCube, i ) { assert( Vec_IntSize(vCube) > 0 ); p->nVars = Abc_MaxInt( p->nVars, Vec_IntEntry(vCube, 0) ); p->nLits += Vec_IntSize(vCube) - 1; Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) p->nVars = Abc_MaxInt( p->nVars, Abc_Lit2Var(Lit) ); } // p->nVars++; assert( p->nVars < nVars ); p->nVars = nVars; // count literals p->vCounts = Vec_IntStart( 2*p->nVars ); Vec_WecForEachLevel( p->vCubes, vCube, i ) Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) Vec_IntAddToEntry( p->vCounts, Lit, 1 ); // start literals p->vLits = Vec_WecStart( 2*p->nVars ); Vec_IntForEachEntry( p->vCounts, Count, Lit ) Vec_IntGrow( Vec_WecEntry(p->vLits, Lit), Count ); // fill out literals Vec_WecForEachLevel( p->vCubes, vCube, i ) Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) Vec_WecPush( p->vLits, Lit, i ); // create mapping of variable into the first cube p->vVarCube = Vec_IntStartFull( p->nVars ); Vec_WecForEachLevel( p->vCubes, vCube, i ) if ( Vec_IntEntry(p->vVarCube, Vec_IntEntry(vCube, 0)) == -1 ) Vec_IntWriteEntry( p->vVarCube, Vec_IntEntry(vCube, 0), i ); } int Fx_ManCubeSingleCubeDivisors( Fx_Man_t * p, Vec_Int_t * vPivot, int fRemove, int fUpdate ) { int k, n, Lit, Lit2, iDiv; if ( Vec_IntSize(vPivot) < 2 ) return 0; Vec_IntForEachEntryStart( vPivot, Lit, k, 1 ) Vec_IntForEachEntryStart( vPivot, Lit2, n, k+1 ) { assert( Lit < Lit2 ); Vec_IntClear( p->vCubeFree ); Vec_IntPush( p->vCubeFree, Abc_Var2Lit(Abc_LitNot(Lit), 0) ); Vec_IntPush( p->vCubeFree, Abc_Var2Lit(Abc_LitNot(Lit2), 1) ); iDiv = Hsh_VecManAdd( p->pHash, p->vCubeFree ); if ( !fRemove ) { if ( Vec_FltSize(p->vWeights) == iDiv ) { Vec_FltPush(p->vWeights, -2 + 0.9 - 0.001 * Fx_ManComputeLevelDiv(p, p->vCubeFree)); p->nDivsS++; } assert( iDiv < Vec_FltSize(p->vWeights) ); Vec_FltAddToEntry( p->vWeights, iDiv, 1 ); p->nPairsS++; } else { assert( iDiv < Vec_FltSize(p->vWeights) ); Vec_FltAddToEntry( p->vWeights, iDiv, -1 ); p->nPairsS--; } if ( fUpdate ) { if ( Vec_QueIsMember(p->vPrio, iDiv) ) Vec_QueUpdate( p->vPrio, iDiv ); else if ( !fRemove ) Vec_QuePush( p->vPrio, iDiv ); } } return Vec_IntSize(vPivot) * (Vec_IntSize(vPivot) - 1) / 2; } void Fx_ManCubeDoubleCubeDivisors( Fx_Man_t * p, int iFirst, Vec_Int_t * vPivot, int fRemove, int fUpdate, int * fWarning ) { Vec_Int_t * vCube; int i, iDiv, Base; Vec_WecForEachLevelStart( p->vCubes, vCube, i, iFirst ) { if ( Vec_IntSize(vCube) == 0 || vCube == vPivot ) continue; if ( Vec_WecIntHasMark(vCube) && Vec_WecIntHasMark(vPivot) && vCube > vPivot ) continue; if ( Vec_IntEntry(vCube, 0) != Vec_IntEntry(vPivot, 0) ) break; Base = Fx_ManDivFindCubeFree( vCube, vPivot, p->vCubeFree, fWarning ); if ( Base == -1 ) { if ( fRemove == 0 ) { if ( Vec_IntSize( vCube ) > Vec_IntSize( vPivot ) ) Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vCube ) ); else Vec_IntPush( p->vSCC, Vec_WecLevelId( p->vCubes, vPivot ) ); } continue; } if ( Vec_IntSize(p->vCubeFree) == 4 ) { int Value = Fx_ManDivNormalize( p->vCubeFree ); if ( Value == 0 ) p->nDivMux[0]++; else if ( Value == 1 ) p->nDivMux[1]++; else p->nDivMux[2]++; if ( p->fCanonDivs && Value < 0 ) continue; } if ( p->LitCountMax && p->LitCountMax < Vec_IntSize(p->vCubeFree) ) continue; if ( p->fCanonDivs && Vec_IntSize(p->vCubeFree) == 3 ) continue; iDiv = Hsh_VecManAdd( p->pHash, p->vCubeFree ); if ( !fRemove ) { if ( iDiv == Vec_FltSize(p->vWeights) ) Vec_FltPush(p->vWeights, -Vec_IntSize(p->vCubeFree) + 0.9 - 0.0009 * Fx_ManComputeLevelDiv(p, p->vCubeFree)); assert( iDiv < Vec_FltSize(p->vWeights) ); Vec_FltAddToEntry( p->vWeights, iDiv, Base + Vec_IntSize(p->vCubeFree) - 1 ); p->nPairsD++; } else { assert( iDiv < Vec_FltSize(p->vWeights) ); Vec_FltAddToEntry( p->vWeights, iDiv, -(Base + Vec_IntSize(p->vCubeFree) - 1) ); p->nPairsD--; } if ( fUpdate ) { if ( Vec_QueIsMember(p->vPrio, iDiv) ) Vec_QueUpdate( p->vPrio, iDiv ); else if ( !fRemove ) Vec_QuePush( p->vPrio, iDiv ); } } } void Fx_ManCreateDivisors( Fx_Man_t * p ) { Vec_Int_t * vCube; float Weight; int i, fWarning = 0; // alloc hash table assert( p->pHash == NULL ); p->pHash = Hsh_VecManStart( 1000 ); p->vWeights = Vec_FltAlloc( 1000 ); // create single-cube two-literal divisors Vec_WecForEachLevel( p->vCubes, vCube, i ) Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 0 ); // add - no update assert( p->nDivsS == Vec_FltSize(p->vWeights) ); // create two-cube divisors Vec_WecForEachLevel( p->vCubes, vCube, i ) Fx_ManCubeDoubleCubeDivisors( p, i+1, vCube, 0, 0, &fWarning ); // add - no update // create queue with all divisors p->vPrio = Vec_QueAlloc( Vec_FltSize(p->vWeights) ); Vec_QueSetPriority( p->vPrio, Vec_FltArrayP(p->vWeights) ); Vec_FltForEachEntry( p->vWeights, Weight, i ) if ( Weight > 0.0 ) Vec_QuePush( p->vPrio, i ); } /**Function************************************************************* Synopsis [Compress the cubes by removing unused ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fx_ManCompressCubes( Vec_Wec_t * vCubes, Vec_Int_t * vLit2Cube ) { int i, CubeId, k = 0; Vec_IntForEachEntry( vLit2Cube, CubeId, i ) if ( Vec_IntSize(Vec_WecEntry(vCubes, CubeId)) > 0 ) Vec_IntWriteEntry( vLit2Cube, k++, CubeId ); Vec_IntShrink( vLit2Cube, k ); } /**Function************************************************************* Synopsis [Find command cube pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fx_ManGetCubeVar( Vec_Wec_t * vCubes, int iCube ) { return Vec_IntEntry( Vec_WecEntry(vCubes, iCube), 0 ); } void Fx_ManFindCommonPairs( Vec_Wec_t * vCubes, Vec_Int_t * vPart0, Vec_Int_t * vPart1, Vec_Int_t * vPairs, Vec_Int_t * vCompls, Vec_Int_t * vDiv, Vec_Int_t * vCubeFree, int * fWarning ) { int * pBeg1 = vPart0->pArray; int * pBeg2 = vPart1->pArray; int * pEnd1 = vPart0->pArray + vPart0->nSize; int * pEnd2 = vPart1->pArray + vPart1->nSize; int i, k, i_, k_, fCompl, CubeId1, CubeId2; Vec_IntClear( vPairs ); Vec_IntClear( vCompls ); while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { CubeId1 = Fx_ManGetCubeVar(vCubes, *pBeg1); CubeId2 = Fx_ManGetCubeVar(vCubes, *pBeg2); if ( CubeId1 == CubeId2 ) { for ( i = 1; pBeg1+i < pEnd1; i++ ) if ( CubeId1 != Fx_ManGetCubeVar(vCubes, pBeg1[i]) ) break; for ( k = 1; pBeg2+k < pEnd2; k++ ) if ( CubeId1 != Fx_ManGetCubeVar(vCubes, pBeg2[k]) ) break; for ( i_ = 0; i_ < i; i_++ ) for ( k_ = 0; k_ < k; k_++ ) { if ( pBeg1[i_] == pBeg2[k_] ) continue; Fx_ManDivFindCubeFree( Vec_WecEntry(vCubes, pBeg1[i_]), Vec_WecEntry(vCubes, pBeg2[k_]), vCubeFree, fWarning ); fCompl = (Vec_IntSize(vCubeFree) == 4 && Fx_ManDivNormalize(vCubeFree) == 1); if ( !Vec_IntEqual( vDiv, vCubeFree ) ) continue; Vec_IntPush( vPairs, pBeg1[i_] ); Vec_IntPush( vPairs, pBeg2[k_] ); Vec_IntPush( vCompls, fCompl ); } pBeg1 += i; pBeg2 += k; } else if ( CubeId1 < CubeId2 ) pBeg1++; else pBeg2++; } } /**Function************************************************************* Synopsis [Updates the data-structure when one divisor is selected.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fx_ManUpdate( Fx_Man_t * p, int iDiv, int * fWarning ) { Vec_Int_t * vCube, * vCube2, * vLitP = NULL, * vLitN = NULL; Vec_Int_t * vDiv = p->vDiv; int i, k, Lit0, Lit1, iVarNew = 0, RetValue, Level; float Diff = Vec_FltEntry(p->vWeights, iDiv) - (float)((int)Vec_FltEntry(p->vWeights, iDiv)); assert( Diff > 0.0 && Diff < 1.0 ); // get the divisor and select pivot variables p->nDivs++; Vec_IntClear( vDiv ); Vec_IntAppend( vDiv, Hsh_VecReadEntry(p->pHash, iDiv) ); Fx_ManDivFindPivots( vDiv, &Lit0, &Lit1 ); assert( Lit0 >= 0 && Lit1 >= 0 ); // collect single-cube-divisor cubes Vec_IntClear( p->vCubesS ); if ( Vec_IntSize(vDiv) == 2 ) { Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Abc_LitNot(Lit0)) ); Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Abc_LitNot(Lit1)) ); Vec_IntTwoRemoveCommon( Vec_WecEntry(p->vLits, Abc_LitNot(Lit0)), Vec_WecEntry(p->vLits, Abc_LitNot(Lit1)), p->vCubesS ); } // collect double-cube-divisor cube pairs Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Lit0) ); Fx_ManCompressCubes( p->vCubes, Vec_WecEntry(p->vLits, Lit1) ); Fx_ManFindCommonPairs( p->vCubes, Vec_WecEntry(p->vLits, Lit0), Vec_WecEntry(p->vLits, Lit1), p->vCubesD, p->vCompls, vDiv, p->vCubeFree, fWarning ); // subtract cost of single-cube divisors Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i ) Fx_ManCubeSingleCubeDivisors( p, vCube, 1, 1 ); // remove - update Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i ) Fx_ManCubeSingleCubeDivisors( p, vCube, 1, 1 ); // remove - update // mark the cubes to be removed Vec_WecMarkLevels( p->vCubes, p->vCubesS ); Vec_WecMarkLevels( p->vCubes, p->vCubesD ); // subtract cost of double-cube divisors Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i ) Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning ); // remove - update Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i ) Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning ); // remove - update // unmark the cubes to be removed Vec_WecUnmarkLevels( p->vCubes, p->vCubesS ); Vec_WecUnmarkLevels( p->vCubes, p->vCubesD ); if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->pHash, iDiv)) == 2 ) goto ExtractFromPairs; // create new divisor iVarNew = Vec_WecSize( p->vLits ) / 2; assert( Vec_IntSize(p->vVarCube) == iVarNew ); Vec_IntPush( p->vVarCube, Vec_WecSize(p->vCubes) ); vCube = Vec_WecPushLevel( p->vCubes ); Vec_IntPush( vCube, iVarNew ); if ( Vec_IntSize(vDiv) == 2 ) { Vec_IntPush( vCube, Abc_LitNot(Lit0) ); Vec_IntPush( vCube, Abc_LitNot(Lit1) ); Level = 1 + Fx_ManComputeLevelCube( p, vCube ); } else { vCube2 = Vec_WecPushLevel( p->vCubes ); vCube = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 2 ); Vec_IntPush( vCube2, iVarNew ); Fx_ManDivAddLits( vCube, vCube2, vDiv ); Level = 2 + Abc_MaxInt( Fx_ManComputeLevelCube(p, vCube), Fx_ManComputeLevelCube(p, vCube2) ); } assert( Vec_IntSize(p->vLevels) == iVarNew ); Vec_IntPush( p->vLevels, Level ); // do not add new cubes to the matrix p->nLits += Vec_IntSize( vDiv ); // create new literals vLitP = Vec_WecPushLevel( p->vLits ); vLitN = Vec_WecPushLevel( p->vLits ); vLitP = Vec_WecEntry( p->vLits, Vec_WecSize(p->vLits) - 2 ); // create updated single-cube divisor cubes Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i ) { RetValue = Vec_IntRemove1( vCube, Abc_LitNot(Lit0) ); RetValue += Vec_IntRemove1( vCube, Abc_LitNot(Lit1) ); assert( RetValue == 2 ); Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) ); Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); p->nLits--; } // create updated double-cube divisor cube pairs ExtractFromPairs: k = 0; p->nCompls = 0; assert( Vec_IntSize(p->vCubesD) % 2 == 0 ); assert( Vec_IntSize(p->vCubesD) == 2 * Vec_IntSize(p->vCompls) ); for ( i = 0; i < Vec_IntSize(p->vCubesD); i += 2 ) { int fCompl = Vec_IntEntry(p->vCompls, i/2); p->nCompls += fCompl; vCube = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i) ); vCube2 = Vec_WecEntry( p->vCubes, Vec_IntEntry(p->vCubesD, i+1) ); RetValue = Fx_ManDivRemoveLits( vCube, vDiv, fCompl ); // cube 2*i RetValue += Fx_ManDivRemoveLits( vCube2, vDiv, fCompl ); // cube 2*i+1 assert( RetValue == Vec_IntSize(vDiv) || RetValue == Vec_IntSize( vDiv ) + 1); if ( iVarNew > 0 ) { if ( Vec_IntSize(vDiv) == 2 || fCompl ) { Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 1) ); Vec_IntPush( vLitN, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID } else { Vec_IntPush( vCube, Abc_Var2Lit(iVarNew, 0) ); Vec_IntPush( vLitP, Vec_WecLevelId(p->vCubes, vCube) ); // MAKE SURE vCube IS SORTED BY ID } } p->nLits -= Vec_IntSize(vDiv) + Vec_IntSize(vCube2) - 2; // remove second cube Vec_IntWriteEntry( p->vCubesD, k++, Vec_WecLevelId(p->vCubes, vCube) ); Vec_IntClear( vCube2 ); } assert( k == Vec_IntSize(p->vCubesD) / 2 ); Vec_IntShrink( p->vCubesD, k ); Vec_IntSort( p->vCubesD, 0 ); //Vec_IntSort( vLitN, 0 ); //Vec_IntSort( vLitP, 0 ); // add cost of single-cube divisors Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i ) Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 1 ); // add - update Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i ) Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 1 ); // add - update // mark the cubes to be removed Vec_WecMarkLevels( p->vCubes, p->vCubesS ); Vec_WecMarkLevels( p->vCubes, p->vCubesD ); // add cost of double-cube divisors Fx_ManForEachCubeVec( p->vCubesS, p->vCubes, vCube, i ) Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 0, 1, fWarning ); // add - update Fx_ManForEachCubeVec( p->vCubesD, p->vCubes, vCube, i ) Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 0, 1, fWarning ); // add - update // unmark the cubes to be removed Vec_WecUnmarkLevels( p->vCubes, p->vCubesS ); Vec_WecUnmarkLevels( p->vCubes, p->vCubesD ); // Deal with SCC if ( Vec_IntSize( p->vSCC ) ) { Vec_IntUniqify( p->vSCC ); Fx_ManForEachCubeVec( p->vSCC, p->vCubes, vCube, i ) { Fx_ManCubeDoubleCubeDivisors( p, Fx_ManGetFirstVarCube(p, vCube), vCube, 1, 1, fWarning ); // remove - update Vec_IntClear( vCube ); } Vec_IntClear( p->vSCC ); } // add cost of the new divisor if ( Vec_IntSize(vDiv) > 2 ) { vCube = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 2 ); vCube2 = Vec_WecEntry( p->vCubes, Vec_WecSize(p->vCubes) - 1 ); Fx_ManCubeSingleCubeDivisors( p, vCube, 0, 1 ); // add - update Fx_ManCubeSingleCubeDivisors( p, vCube2, 0, 1 ); // add - update Vec_IntForEachEntryStart( vCube, Lit0, i, 1 ) Vec_WecPush( p->vLits, Lit0, Vec_WecLevelId(p->vCubes, vCube) ); Vec_IntForEachEntryStart( vCube2, Lit0, i, 1 ) Vec_WecPush( p->vLits, Lit0, Vec_WecLevelId(p->vCubes, vCube2) ); } // remove these cubes from the lit array of the divisor Vec_IntForEachEntry( vDiv, Lit0, i ) { Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_Lit2Var(Lit0)), p->vCubesD ); if ( (p->nCompls && i > 1) || Vec_IntSize( vDiv ) == 2 ) // the last two lits are possibly complemented Vec_IntTwoRemove( Vec_WecEntry(p->vLits, Abc_LitNot(Abc_Lit2Var(Lit0))), p->vCubesD ); } } /**Function************************************************************* Synopsis [Implements the traditional fast_extract algorithm.] Description [J. Rajski and J. Vasudevamurthi, "The testability- preserving concurrent decomposition and factorization of Boolean expressions", IEEE TCAD, Vol. 11, No. 6, June 1992, pp. 778-793.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ) { int fVeryVeryVerbose = 0; int i, iDiv, fWarning = 0; Fx_Man_t * p; abctime clk = Abc_Clock(); // initialize the data-structure p = Fx_ManStart( vCubes ); p->LitCountMax = LitCountMax; p->fCanonDivs = fCanonDivs; Fx_ManCreateLiterals( p, ObjIdMax ); Fx_ManComputeLevel( p ); Fx_ManCreateDivisors( p ); if ( fVeryVerbose ) Fx_PrintDivisors( p ); if ( fVerbose ) Fx_PrintStats( p, Abc_Clock() - clk ); // perform extraction p->timeStart = Abc_Clock(); for ( i = 0; i < nNewNodesMax && Vec_QueTopPriority(p->vPrio) > 0.0; i++ ) { iDiv = Vec_QuePop(p->vPrio); if ( fVeryVerbose ) Fx_PrintDiv( p, iDiv ); Fx_ManUpdate( p, iDiv, &fWarning ); if ( fVeryVeryVerbose ) Fx_PrintDivisors( p ); } if ( fVerbose ) Fx_PrintStats( p, Abc_Clock() - clk ); Fx_ManStop( p ); // return the result Vec_WecRemoveEmpty( vCubes ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcFxu.c000066400000000000000000000216361300674244400232300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFxu.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface with the fast extract package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFxu.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/fxu/fxu.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ); static void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); extern int Fxu_FastExtract( Fxu_Data_t * pData ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sets default values of the FXU parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSetDefaultFxParams( Fxu_Data_t * p ) { memset( p, 0, sizeof(Fxu_Data_t) ); p->nSingleMax = 20000; p->nPairsMax = 30000; p->nNodesExt =1000000; p->WeightMin = 0; p->LitCountMax= 4; p->fOnlyS = 0; p->fOnlyD = 0; p->fUse0 = 0; p->fUseCompl = 1; p->fVerbose = 0; } /**Function************************************************************* Synopsis [Performs fast_extract on the current network.] Description [Takes the network and the maximum number of nodes to extract. Uses the concurrent double-cube and single cube divisor extraction procedure. Modifies the network in the end, after extracting all nodes. Note that Ntk_NetworkSweep() may increase the performance of this procedure because the single-literal nodes will not be created in the sparse matrix. Returns 1 if the network has been changed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) { assert( Abc_NtkIsLogic(pNtk) ); // if the network is already in the SOP form, it may come from BLIF file // and it may not be SCC-free, in which case FXU will not work correctly if ( Abc_NtkIsSopLogic(pNtk) ) { // to make sure the SOPs are SCC-free // Abc_NtkSopToBdd(pNtk); // Abc_NtkBddToSop(pNtk); } // get the network in the SOP form if ( !Abc_NtkToSop(pNtk, -1, ABC_INFINITY) ) { printf( "Abc_NtkFastExtract(): Converting to SOPs has failed.\n" ); return 0; } // check if the network meets the requirements if ( !Abc_NtkFxuCheck(pNtk) ) { printf( "Abc_NtkFastExtract: Nodes have duplicated or complemented fanins. FXU is not performed.\n" ); return 0; } // sweep removes useless nodes Abc_NtkCleanup( pNtk, 0 ); // collect information about the covers Abc_NtkFxuCollectInfo( pNtk, p ); // call the fast extract procedure if ( Fxu_FastExtract(p) > 0 ) { // update the network Abc_NtkFxuReconstruct( pNtk, p ); // make sure everything is okay if ( !Abc_NtkCheck( pNtk ) ) printf( "Abc_NtkFastExtract: The network check has failed.\n" ); return 1; } else printf( "Warning: The network has not been changed by \"fx\".\n" ); return 0; } /**Function************************************************************* Synopsis [Makes sure the nodes do not have complemented and duplicated fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pFanin1, * pFanin2; int n, i, k; Abc_NtkForEachNode( pNtk, pNode, n ) { Abc_ObjForEachFanin( pNode, pFanin1, i ) { if ( i < 2 && Abc_ObjFaninC(pNode, i) ) return 0; Abc_ObjForEachFanin( pNode, pFanin2, k ) { if ( i == k ) continue; if ( pFanin1 == pFanin2 ) return 0; } } } return 1; } /**Function************************************************************* Synopsis [Collect information about the network for fast_extract.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) { Abc_Obj_t * pNode; int i; // add information to the manager p->pManSop = (Mem_Flex_t *)pNtk->pManFunc; p->vSops = Vec_PtrAlloc(0); p->vFanins = Vec_PtrAlloc(0); p->vSopsNew = Vec_PtrAlloc(0); p->vFaninsNew = Vec_PtrAlloc(0); Vec_PtrFill( p->vSops, Abc_NtkObjNumMax(pNtk), NULL ); Vec_PtrFill( p->vFanins, Abc_NtkObjNumMax(pNtk), NULL ); Vec_PtrFill( p->vSopsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL ); Vec_PtrFill( p->vFaninsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL ); // add SOPs and fanin array Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_SopGetVarNum((char *)pNode->pData) < 2 ) continue; if ( Abc_SopGetCubeNum((char *)pNode->pData) < 1 ) continue; p->vSops->pArray[i] = pNode->pData; p->vFanins->pArray[i] = &pNode->vFanins; } p->nNodesOld = Abc_NtkObjNumMax(pNtk); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ) { int i; // free the arrays of new fanins if ( p->vFaninsNew ) for ( i = 0; i < p->vFaninsNew->nSize; i++ ) if ( p->vFaninsNew->pArray[i] ) Vec_IntFree( (Vec_Int_t *)p->vFaninsNew->pArray[i] ); // free the arrays if ( p->vSops ) Vec_PtrFree( p->vSops ); if ( p->vSopsNew ) Vec_PtrFree( p->vSopsNew ); if ( p->vFanins ) Vec_PtrFree( p->vFanins ); if ( p->vFaninsNew ) Vec_PtrFree( p->vFaninsNew ); // ABC_FREE( p ); } /**Function************************************************************* Synopsis [Reconstructs the network after FX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) { Vec_Int_t * vFanins; Abc_Obj_t * pNode, * pFanin; int i, k; assert( p->vFanins->nSize < p->vFaninsNew->nSize ); // create the new nodes for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ ) { // start the node pNode = Abc_NtkCreateNode( pNtk ); assert( i == (int)pNode->Id ); } // update the old nodes for ( i = 0; i < p->vFanins->nSize; i++ ) { // the new array of fanins vFanins = (Vec_Int_t *)p->vFaninsNew->pArray[i]; if ( vFanins == NULL ) continue; // remove old fanins pNode = Abc_NtkObj( pNtk, i ); Abc_ObjRemoveFanins( pNode ); // add new fanins vFanins = (Vec_Int_t *)p->vFaninsNew->pArray[i]; for ( k = 0; k < vFanins->nSize; k++ ) { pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] ); Abc_ObjAddFanin( pNode, pFanin ); } pNode->pData = p->vSopsNew->pArray[i]; assert( pNode->pData != NULL ); } // set up the new nodes for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ ) { // get the new node pNode = Abc_NtkObj( pNtk, i ); // add the fanins vFanins = (Vec_Int_t *)p->vFaninsNew->pArray[i]; for ( k = 0; k < vFanins->nSize; k++ ) { pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] ); Abc_ObjAddFanin( pNode, pFanin ); } pNode->pData = p->vSopsNew->pArray[i]; assert( pNode->pData != NULL ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcGen.c000066400000000000000000000640321300674244400231740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcGen.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to generate various type of circuits.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcGen.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_WriteFullAdder( FILE * pFile ) { int fNaive = 0; fprintf( pFile, ".model FA\n" ); fprintf( pFile, ".inputs a b cin\n" ); fprintf( pFile, ".outputs s cout\n" ); if ( fNaive ) { fprintf( pFile, ".names a b k\n" ); fprintf( pFile, "10 1\n" ); fprintf( pFile, "01 1\n" ); fprintf( pFile, ".names k cin s\n" ); fprintf( pFile, "10 1\n" ); fprintf( pFile, "01 1\n" ); fprintf( pFile, ".names a b cin cout\n" ); fprintf( pFile, "11- 1\n" ); fprintf( pFile, "1-1 1\n" ); fprintf( pFile, "-11 1\n" ); } else { fprintf( pFile, ".names a b and1\n" ); fprintf( pFile, "11 1\n" ); fprintf( pFile, ".names a b and1_\n" ); fprintf( pFile, "00 1\n" ); fprintf( pFile, ".names and1 and1_ xor\n" ); fprintf( pFile, "00 1\n" ); fprintf( pFile, ".names cin xor and2\n" ); fprintf( pFile, "11 1\n" ); fprintf( pFile, ".names cin xor and2_\n" ); fprintf( pFile, "00 1\n" ); fprintf( pFile, ".names and2 and2_ s\n" ); fprintf( pFile, "00 1\n" ); fprintf( pFile, ".names and1 and2 cout\n" ); fprintf( pFile, "00 0\n" ); } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); } void Abc_WriteAdder( FILE * pFile, int nVars ) { int i, nDigits = Abc_Base10Log( nVars ); assert( nVars > 0 ); fprintf( pFile, ".model ADD%d\n", nVars ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " a%0*d", nDigits, i ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " b%0*d", nDigits, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); for ( i = 0; i <= nVars; i++ ) fprintf( pFile, " s%0*d", nDigits, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".names c\n" ); if ( nVars == 1 ) fprintf( pFile, ".subckt FA a=a0 b=b0 cin=c s=y0 cout=s1\n" ); else { fprintf( pFile, ".subckt FA a=a%0*d b=b%0*d cin=c s=s%0*d cout=%0*d\n", nDigits, 0, nDigits, 0, nDigits, 0, nDigits, 0 ); for ( i = 1; i < nVars-1; i++ ) fprintf( pFile, ".subckt FA a=a%0*d b=b%0*d cin=%0*d s=s%0*d cout=%0*d\n", nDigits, i, nDigits, i, nDigits, i-1, nDigits, i, nDigits, i ); fprintf( pFile, ".subckt FA a=a%0*d b=b%0*d cin=%0*d s=s%0*d cout=s%0*d\n", nDigits, i, nDigits, i, nDigits, i-1, nDigits, i, nDigits, i+1 ); } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); Abc_WriteFullAdder( pFile ); } void Abc_GenAdder( char * pFileName, int nVars ) { FILE * pFile; assert( nVars > 0 ); pFile = fopen( pFileName, "w" ); fprintf( pFile, "# %d-bit ripple-carry adder generated by ABC on %s\n", nVars, Extra_TimeStamp() ); Abc_WriteAdder( pFile, nVars ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_WriteMulti( FILE * pFile, int nVars ) { int i, k, nDigits = Abc_Base10Log( nVars ), nDigits2 = Abc_Base10Log( 2*nVars ); assert( nVars > 0 ); fprintf( pFile, ".model Multi%d\n", nVars ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " a%0*d", nDigits, i ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " b%0*d", nDigits, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); for ( i = 0; i < 2*nVars; i++ ) fprintf( pFile, " m%0*d", nDigits2, i ); fprintf( pFile, "\n" ); for ( i = 0; i < 2*nVars; i++ ) fprintf( pFile, ".names x%0*d_%0*d\n", nDigits, 0, nDigits2, i ); for ( k = 0; k < nVars; k++ ) { for ( i = 0; i < 2 * nVars; i++ ) if ( i >= k && i < k + nVars ) fprintf( pFile, ".names b%0*d a%0*d y%0*d_%0*d\n11 1\n", nDigits, k, nDigits, i-k, nDigits, k, nDigits2, i ); else fprintf( pFile, ".names y%0*d_%0*d\n", nDigits, k, nDigits2, i ); fprintf( pFile, ".subckt ADD%d", 2*nVars ); for ( i = 0; i < 2*nVars; i++ ) fprintf( pFile, " a%0*d=x%0*d_%0*d", nDigits2, i, nDigits, k, nDigits2, i ); for ( i = 0; i < 2*nVars; i++ ) fprintf( pFile, " b%0*d=y%0*d_%0*d", nDigits2, i, nDigits, k, nDigits2, i ); for ( i = 0; i <= 2*nVars; i++ ) fprintf( pFile, " s%0*d=x%0*d_%0*d", nDigits2, i, nDigits, k+1, nDigits2, i ); fprintf( pFile, "\n" ); } for ( i = 0; i < 2 * nVars; i++ ) fprintf( pFile, ".names x%0*d_%0*d m%0*d\n1 1\n", nDigits, k, nDigits2, i, nDigits2, i ); fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); Abc_WriteAdder( pFile, 2*nVars ); } void Abc_GenMulti( char * pFileName, int nVars ) { FILE * pFile; assert( nVars > 0 ); pFile = fopen( pFileName, "w" ); fprintf( pFile, "# %d-bit multiplier generated by ABC on %s\n", nVars, Extra_TimeStamp() ); Abc_WriteMulti( pFile, nVars ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_WriteComp( FILE * pFile ) { fprintf( pFile, ".model Comp\n" ); fprintf( pFile, ".inputs a b\n" ); fprintf( pFile, ".outputs x y\n" ); fprintf( pFile, ".names a b x\n" ); fprintf( pFile, "11 1\n" ); fprintf( pFile, ".names a b y\n" ); fprintf( pFile, "1- 1\n" ); fprintf( pFile, "-1 1\n" ); fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); } void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ) { int i; fprintf( pFile, ".model Layer%d\n", fSkip1 ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " x%02d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " y%02d", i ); fprintf( pFile, "\n" ); if ( fSkip1 ) { fprintf( pFile, ".names x00 y00\n" ); fprintf( pFile, "1 1\n" ); i = 1; } else i = 0; for ( ; i + 1 < nVars; i += 2 ) fprintf( pFile, ".subckt Comp a=x%02d b=x%02d x=y%02d y=y%02d\n", i, i+1, i, i+1 ); if ( i < nVars ) { fprintf( pFile, ".names x%02d y%02d\n", i, i ); fprintf( pFile, "1 1\n" ); } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenSorter( char * pFileName, int nVars ) { FILE * pFile; int i, k, Counter, nDigits; assert( nVars > 1 ); pFile = fopen( pFileName, "w" ); fprintf( pFile, "# %d-bit sorter generated by ABC on %s\n", nVars, Extra_TimeStamp() ); fprintf( pFile, ".model Sorter%02d\n", nVars ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " x%02d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " y%02d", i ); fprintf( pFile, "\n" ); Counter = 0; nDigits = Abc_Base10Log( (nVars-2)*nVars ); if ( nVars == 2 ) fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" ); else { fprintf( pFile, ".subckt Layer0" ); for ( k = 0; k < nVars; k++ ) fprintf( pFile, " x%02d=x%02d", k, k ); for ( k = 0; k < nVars; k++ ) fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); fprintf( pFile, "\n" ); Counter -= nVars; for ( i = 1; i < 2*nVars-2; i++ ) { fprintf( pFile, ".subckt Layer%d", (i&1) ); for ( k = 0; k < nVars; k++ ) fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); for ( k = 0; k < nVars; k++ ) fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); fprintf( pFile, "\n" ); Counter -= nVars; } fprintf( pFile, ".subckt Layer%d", (i&1) ); for ( k = 0; k < nVars; k++ ) fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); for ( k = 0; k < nVars; k++ ) fprintf( pFile, " y%02d=y%02d", k, k ); fprintf( pFile, "\n" ); } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); Abc_WriteLayer( pFile, nVars, 0 ); Abc_WriteLayer( pFile, nVars, 1 ); Abc_WriteComp( pFile ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_WriteCell( FILE * pFile ) { fprintf( pFile, ".model cell\n" ); fprintf( pFile, ".inputs px1 px2 py1 py2 x y\n" ); fprintf( pFile, ".outputs fx fy\n" ); fprintf( pFile, ".names x y a\n" ); fprintf( pFile, "11 1\n" ); fprintf( pFile, ".names px1 a x nx\n" ); fprintf( pFile, "11- 1\n" ); fprintf( pFile, "0-1 1\n" ); fprintf( pFile, ".names py1 a y ny\n" ); fprintf( pFile, "11- 1\n" ); fprintf( pFile, "0-1 1\n" ); fprintf( pFile, ".names px2 nx fx\n" ); fprintf( pFile, "10 1\n" ); fprintf( pFile, "01 1\n" ); fprintf( pFile, ".names py2 ny fy\n" ); fprintf( pFile, "10 1\n" ); fprintf( pFile, "01 1\n" ); fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenMesh( char * pFileName, int nVars ) { FILE * pFile; int i, k; assert( nVars > 0 ); pFile = fopen( pFileName, "w" ); fprintf( pFile, "# %dx%d mesh generated by ABC on %s\n", nVars, nVars, Extra_TimeStamp() ); fprintf( pFile, ".model mesh%d\n", nVars ); for ( i = 0; i < nVars; i++ ) for ( k = 0; k < nVars; k++ ) { fprintf( pFile, ".inputs" ); fprintf( pFile, " p%d%dx1", i, k ); fprintf( pFile, " p%d%dx2", i, k ); fprintf( pFile, " p%d%dy1", i, k ); fprintf( pFile, " p%d%dy2", i, k ); fprintf( pFile, "\n" ); } fprintf( pFile, ".inputs" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " v%02d v%02d", 2*i, 2*i+1 ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); fprintf( pFile, " fx00" ); fprintf( pFile, "\n" ); for ( i = 0; i < nVars; i++ ) // horizontal for ( k = 0; k < nVars; k++ ) // vertical { fprintf( pFile, ".subckt cell" ); fprintf( pFile, " px1=p%d%dx1", i, k ); fprintf( pFile, " px2=p%d%dx2", i, k ); fprintf( pFile, " py1=p%d%dy1", i, k ); fprintf( pFile, " py2=p%d%dy2", i, k ); if ( k == nVars - 1 ) fprintf( pFile, " x=v%02d", i ); else fprintf( pFile, " x=fx%d%d", i, k+1 ); if ( i == nVars - 1 ) fprintf( pFile, " y=v%02d", nVars+k ); else fprintf( pFile, " y=fy%d%d", i+1, k ); // outputs fprintf( pFile, " fx=fx%d%d", i, k ); fprintf( pFile, " fy=fy%d%d", i, k ); fprintf( pFile, "\n" ); } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); Abc_WriteCell( pFile ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_WriteKLut( FILE * pFile, int nLutSize ) { int i, iVar, iNext, nPars = (1 << nLutSize); fprintf( pFile, "\n" ); fprintf( pFile, ".model lut%d\n", nLutSize ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nPars; i++ ) fprintf( pFile, " p%02d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nLutSize; i++ ) fprintf( pFile, " i%d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs o\n" ); fprintf( pFile, ".names n01 o\n" ); fprintf( pFile, "1 1\n" ); // write internal MUXes iVar = 0; iNext = 2; for ( i = 1; i < nPars; i++ ) { if ( i == iNext ) { iNext *= 2; iVar++; } if ( iVar == nLutSize - 1 ) fprintf( pFile, ".names i%d p%02d p%02d n%02d\n", iVar, 2*(i-nPars/2), 2*(i-nPars/2)+1, i ); else fprintf( pFile, ".names i%d n%02d n%02d n%02d\n", iVar, 2*i, 2*i+1, i ); fprintf( pFile, "01- 1\n" ); fprintf( pFile, "1-1 1\n" ); } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Generates structure of L K-LUTs implementing an N-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ) { int fGenerateFunc = 1; FILE * pFile; int nVarsLut = (1 << nLutSize); // the number of LUT variables int nVarsLog = Abc_Base2Log( nVars + nLuts - 1 ); // the number of encoding vars int nVarsDeg = (1 << nVarsLog); // the number of LUT variables (total) int nParsLut = nLuts * (1 << nLutSize); // the number of LUT params int nParsVar = nLuts * nLutSize * nVarsLog; // the number of var params int i, j, k; assert( nVars > 0 ); pFile = fopen( pFileName, "w" ); fprintf( pFile, "# Structure with %d %d-LUTs for %d-var function generated by ABC on %s\n", nLuts, nLutSize, nVars, Extra_TimeStamp() ); fprintf( pFile, ".model struct%dx%d_%d\n", nLuts, nLutSize, nVars ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nParsLut; i++ ) { // if ( i % (1 << nLutSize) == 0 && i != (nLuts - 1) * (1 << nLutSize) ) // continue; fprintf( pFile, " pl%02d", i ); } fprintf( pFile, "\n" ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nParsVar; i++ ) fprintf( pFile, " pv%02d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " v%02d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); // fprintf( pFile, " v%02d", nVars + nLuts - 1 ); fprintf( pFile, " out" ); fprintf( pFile, "\n" ); fprintf( pFile, ".names Gnd\n" ); fprintf( pFile, " 0\n" ); // generate function if ( fGenerateFunc ) { fprintf( pFile, ".names v%02d func out\n", nVars + nLuts - 1 ); fprintf( pFile, "00 1\n11 1\n" ); fprintf( pFile, ".names" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " v%02d", i ); fprintf( pFile, " func\n" ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, "1" ); fprintf( pFile, " 1\n" ); } else fprintf( pFile, ".names v%02d out\n1 1\n", nVars + nLuts - 1 ); // generate LUTs for ( i = 0; i < nLuts; i++ ) { fprintf( pFile, ".subckt lut%d", nLutSize ); // generate config parameters for ( k = 0; k < nVarsLut; k++ ) fprintf( pFile, " p%02d=pl%02d", k, i * nVarsLut + k ); // generate the inputs for ( k = 0; k < nLutSize; k++ ) fprintf( pFile, " i%d=s%02d", k, i * nLutSize + k ); // generate the output fprintf( pFile, " o=v%02d", nVars + i ); fprintf( pFile, "\n" ); } // generate LUT inputs for ( i = 0; i < nLuts; i++ ) { for ( j = 0; j < nLutSize; j++ ) { fprintf( pFile, ".subckt lut%d", nVarsLog ); // generate config parameters for ( k = 0; k < nVarsDeg; k++ ) { if ( k < nVars + nLuts - 1 && k < nVars + i ) fprintf( pFile, " p%02d=v%02d", k, k ); else fprintf( pFile, " p%02d=Gnd", k ); } // generate the inputs for ( k = 0; k < nVarsLog; k++ ) fprintf( pFile, " i%d=pv%02d", k, (i * nLutSize + j) * nVarsLog + k ); // generate the output fprintf( pFile, " o=s%02d", i * nLutSize + j ); fprintf( pFile, "\n" ); } } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); // generate LUTs Abc_WriteKLut( pFile, nLutSize ); if ( nVarsLog != nLutSize ) Abc_WriteKLut( pFile, nVarsLog ); fclose( pFile ); } /**Function************************************************************* Synopsis [Generates structure of L K-LUTs implementing an N-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenOneHot( char * pFileName, int nVars ) { FILE * pFile; int i, k, Counter, nDigitsIn, nDigitsOut; pFile = fopen( pFileName, "w" ); fprintf( pFile, "# One-hotness condition for %d vars generated by ABC on %s\n", nVars, Extra_TimeStamp() ); fprintf( pFile, ".model 1hot_%dvars\n", nVars ); fprintf( pFile, ".inputs" ); nDigitsIn = Abc_Base10Log( nVars ); for ( i = 0; i < nVars; i++ ) fprintf( pFile, " i%0*d", nDigitsIn, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); nDigitsOut = Abc_Base10Log( nVars * (nVars - 1) / 2 ); for ( i = 0; i < nVars * (nVars - 1) / 2; i++ ) fprintf( pFile, " o%0*d", nDigitsOut, i ); fprintf( pFile, "\n" ); Counter = 0; for ( i = 0; i < nVars; i++ ) for ( k = i+1; k < nVars; k++ ) { fprintf( pFile, ".names i%0*d i%0*d o%0*d\n", nDigitsIn, i, nDigitsIn, k, nDigitsOut, Counter ); fprintf( pFile, "11 0\n" ); Counter++; } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Generates structure of L K-LUTs implementing an N-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenOneHotIntervals( char * pFileName, int nPis, int nRegs, Vec_Ptr_t * vOnehots ) { Vec_Int_t * vLine; FILE * pFile; int i, j, k, iReg1, iReg2, Counter, Counter2, nDigitsIn, nDigitsOut; pFile = fopen( pFileName, "w" ); fprintf( pFile, "# One-hotness with %d vars and %d regs generated by ABC on %s\n", nPis, nRegs, Extra_TimeStamp() ); fprintf( pFile, "# Used %d intervals of 1-hot registers: { ", Vec_PtrSize(vOnehots) ); Counter = 0; Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vLine, k ) { fprintf( pFile, "%d ", Vec_IntSize(vLine) ); Counter += Vec_IntSize(vLine) * (Vec_IntSize(vLine) - 1) / 2; } fprintf( pFile, "}\n" ); fprintf( pFile, ".model 1hot_%dvars_%dregs\n", nPis, nRegs ); fprintf( pFile, ".inputs" ); nDigitsIn = Abc_Base10Log( nPis+nRegs ); for ( i = 0; i < nPis+nRegs; i++ ) fprintf( pFile, " i%0*d", nDigitsIn, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); nDigitsOut = Abc_Base10Log( Counter ); for ( i = 0; i < Counter; i++ ) fprintf( pFile, " o%0*d", nDigitsOut, i ); fprintf( pFile, "\n" ); Counter2 = 0; Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vLine, k ) { Vec_IntForEachEntry( vLine, iReg1, i ) Vec_IntForEachEntryStart( vLine, iReg2, j, i+1 ) { fprintf( pFile, ".names i%0*d i%0*d o%0*d\n", nDigitsIn, nPis+iReg1, nDigitsIn, nPis+iReg2, nDigitsOut, Counter2 ); fprintf( pFile, "11 0\n" ); Counter2++; } } assert( Counter == Counter2 ); fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); fclose( pFile ); } ABC_NAMESPACE_IMPL_END #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Generates structure of L K-LUTs implementing an N-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenRandom( char * pFileName, int nPis ) { FILE * pFile; unsigned * pTruth; int i, b, w, nWords = Abc_TruthWordNum( nPis ); int nDigitsIn; Aig_ManRandom( 1 ); pTruth = ABC_ALLOC( unsigned, nWords ); for ( w = 0; w < nWords; w++ ) pTruth[w] = Aig_ManRandom( 0 ); pFile = fopen( pFileName, "w" ); fprintf( pFile, "# Random function with %d inputs generated by ABC on %s\n", nPis, Extra_TimeStamp() ); fprintf( pFile, ".model rand%d\n", nPis ); fprintf( pFile, ".inputs" ); nDigitsIn = Abc_Base10Log( nPis ); for ( i = 0; i < nPis; i++ ) fprintf( pFile, " i%0*d", nDigitsIn, i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs f\n" ); fprintf( pFile, ".names" ); nDigitsIn = Abc_Base10Log( nPis ); for ( i = 0; i < nPis; i++ ) fprintf( pFile, " i%0*d", nDigitsIn, i ); fprintf( pFile, " f\n" ); for ( i = 0; i < (1<= 0; b-- ) fprintf( pFile, "%d", (i>>b)&1 ); fprintf( pFile, " 1\n" ); } fprintf( pFile, ".end\n" ); fprintf( pFile, "\n" ); fclose( pFile ); ABC_FREE( pTruth ); } /**Function************************************************************* Synopsis [Generates structure of L K-LUTs implementing an N-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenFsmCond( Vec_Str_t * vCond, int nPis, int Prob ) { int i, Rand; Vec_StrClear( vCond ); for ( i = 0; i < nPis; i++ ) { Rand = Aig_ManRandom( 0 ); if ( Rand % 100 > Prob ) Vec_StrPush( vCond, '-' ); else if ( Rand & 1 ) Vec_StrPush( vCond, '1' ); else Vec_StrPush( vCond, '0' ); } Vec_StrPush( vCond, '\0' ); } void Abc_GenFsm( char * pFileName, int nPis, int nPos, int nStates, int nLines, int ProbI, int ProbO ) { FILE * pFile; Vec_Wrd_t * vStates; Vec_Str_t * vCond; int i, iState, iState2; int nDigits = Abc_Base10Log( nStates ); Aig_ManRandom( 1 ); vStates = Vec_WrdAlloc( nLines ); vCond = Vec_StrAlloc( 1000 ); for ( i = 0; i < nStates; ) { iState = Aig_ManRandom( 0 ) % nStates; if ( iState == i ) continue; Vec_WrdPush( vStates, ((word)i << 32) | iState ); i++; } for ( ; i < nLines; ) { iState = Aig_ManRandom( 0 ) % nStates; iState2 = Aig_ManRandom( 0 ) % nStates; if ( iState2 == iState ) continue; Vec_WrdPush( vStates, ((word)iState << 32) | iState2 ); i++; } Vec_WrdSort( vStates, 0 ); // write the file pFile = fopen( pFileName, "w" ); fprintf( pFile, "# This random FSM was generated by ABC on %s\n", Extra_TimeStamp() ); fprintf( pFile, "# Command line was: \"genfsm -I %d -O %d -S %d -L %d -P %d -Q %d %s\"\n", nPis, nPos, nStates, nLines, ProbI, ProbO, pFileName ); fprintf( pFile, "# FSM has %d inputs, %d outputs, %d states, and %d products\n", nPis, nPos, nStates, nLines ); fprintf( pFile, ".i %d\n", nPis ); fprintf( pFile, ".o %d\n", nPos ); fprintf( pFile, ".p %d\n", nLines ); fprintf( pFile, ".s %d\n", nStates ); for ( i = 0; i < nLines; i++ ) { Abc_GenFsmCond( vCond, nPis, ProbI ); fprintf( pFile, "%s ", Vec_StrArray(vCond) ); fprintf( pFile, "%0*d ", nDigits, (int)(Vec_WrdEntry(vStates, i) >> 32) ); fprintf( pFile, "%0*d ", nDigits, (int)(Vec_WrdEntry(vStates, i)) ); if ( nPos > 0 ) { Abc_GenFsmCond( vCond, nPos, ProbO ); fprintf( pFile, "%s", Vec_StrArray(vCond) ); } fprintf( pFile, "\n" ); } fprintf( pFile, ".e" ); fprintf( pFile, "\n" ); fclose( pFile ); Vec_WrdFree( vStates ); Vec_StrFree( vCond ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcHaig.c000066400000000000000000000402451300674244400233330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcHaig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Implements history AIG for combinational rewriting.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcHaig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects the nodes in the classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkHaigCollectMembers( Hop_Man_t * p ) { Vec_Ptr_t * vObjs; Hop_Obj_t * pObj; int i; vObjs = Vec_PtrAlloc( 4098 ); Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { if ( pObj->pData == NULL ) continue; pObj->pData = Hop_ObjRepr( pObj ); Vec_PtrPush( vObjs, pObj ); } return vObjs; } /**Function************************************************************* Synopsis [Creates classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkHaigCreateClasses( Vec_Ptr_t * vMembers ) { Vec_Ptr_t * vClasses; Hop_Obj_t * pObj, * pRepr; int i; // count classes vClasses = Vec_PtrAlloc( 4098 ); Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) { pRepr = (Hop_Obj_t *)pObj->pData; assert( pRepr->pData == NULL ); if ( pRepr->fMarkA == 0 ) // new { pRepr->fMarkA = 1; Vec_PtrPush( vClasses, pRepr ); } } // set representatives as representatives Vec_PtrForEachEntry( Hop_Obj_t *, vClasses, pObj, i ) { pObj->fMarkA = 0; pObj->pData = pObj; } // go through the members and update Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) { pRepr = (Hop_Obj_t *)pObj->pData; if ( ((Hop_Obj_t *)pRepr->pData)->Id > pObj->Id ) pRepr->pData = pObj; } // change representatives of the class Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) { pRepr = (Hop_Obj_t *)pObj->pData; pObj->pData = pRepr->pData; assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); } // update classes Vec_PtrForEachEntry( Hop_Obj_t *, vClasses, pObj, i ) { pRepr = (Hop_Obj_t *)pObj->pData; assert( pRepr->pData == pRepr ); // pRepr->pData = NULL; Vec_PtrWriteEntry( vClasses, i, pRepr ); Vec_PtrPush( vMembers, pObj ); } Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) if ( pObj->pData == pObj ) pObj->pData = NULL; /* Vec_PtrForEachEntry( Hop_Obj_t *, vMembers, pObj, i ) { printf( "ObjId = %4d : ", pObj->Id ); if ( pObj->pData == NULL ) { printf( "NULL" ); } else { printf( "%4d", ((Hop_Obj_t *)pObj->pData)->Id ); assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); } printf( "\n" ); } */ return vClasses; } /**Function************************************************************* Synopsis [Counts how many data members have non-trivial fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkHaigCountFans( Hop_Man_t * p ) { Hop_Obj_t * pObj; int i, Counter = 0; Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { if ( pObj->pData == NULL ) continue; if ( Hop_ObjRefs(pObj) > 0 ) Counter++; } printf( "The number of class members with fanouts = %5d.\n", Counter ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hop_Obj_t * Hop_ObjReprHop( Hop_Obj_t * pObj ) { Hop_Obj_t * pRepr; assert( pObj->pNext != NULL ); if ( pObj->pData == NULL ) return pObj->pNext; pRepr = (Hop_Obj_t *)pObj->pData; assert( pRepr->pData == pRepr ); return Hop_NotCond( pRepr->pNext, pObj->fPhase ^ pRepr->fPhase ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hop_Obj_t * Hop_ObjChild0Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin0(pObj)), Hop_ObjFaninC0(pObj) ); } static inline Hop_Obj_t * Hop_ObjChild1Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin1(pObj)), Hop_ObjFaninC1(pObj) ); } /**Function************************************************************* Synopsis [Stops history AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Man_t * Abc_NtkHaigReconstruct( Hop_Man_t * p ) { Hop_Man_t * pNew; Hop_Obj_t * pObj; int i, Counter = 0; Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) pObj->pNext = NULL; // start the HOP package pNew = Hop_ManStart(); pNew->vObjs = Vec_PtrAlloc( p->nCreated ); Vec_PtrPush( pNew->vObjs, Hop_ManConst1(pNew) ); // map the constant node Hop_ManConst1(p)->pNext = Hop_ManConst1(pNew); // map the CIs Hop_ManForEachPi( p, pObj, i ) pObj->pNext = Hop_ObjCreatePi(pNew); // map the internal nodes Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { if ( !Hop_ObjIsNode(pObj) ) continue; pObj->pNext = Hop_And( pNew, Hop_ObjChild0Hop(pObj), Hop_ObjChild1Hop(pObj) ); // assert( !Hop_IsComplement(pObj->pNext) ); if ( Hop_ManConst1(pNew) == Hop_Regular(pObj->pNext) ) Counter++; if ( pObj->pData ) // member of the class Hop_Regular(pObj->pNext)->pData = Hop_Regular(((Hop_Obj_t *)pObj->pData)->pNext); } // printf( " Counter = %d.\n", Counter ); // transfer the POs Hop_ManForEachPo( p, pObj, i ) Hop_ObjCreatePo( pNew, Hop_ObjChild0Hop(pObj) ); // check the new manager if ( !Hop_ManCheck(pNew) ) { printf( "Abc_NtkHaigReconstruct: Check for History AIG has failed.\n" ); Hop_ManStop(pNew); return NULL; } return pNew; } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkHaigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld ) { if ( pNode == NULL ) return 0; if ( pNode == pOld ) return 1; // check the trivial cases if ( Abc_ObjIsCi(pNode) ) return 0; assert( Abc_ObjIsNode(pNode) ); // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return 0; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // check the children if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) ) return 1; if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) ) return 1; // check equivalent nodes return Abc_NtkHaigCheckTfi_rec( (Abc_Obj_t *)pNode->pData, pOld ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkHaigCheckTfi( Abc_Ntk_t * pNtk, Abc_Obj_t * pOld, Abc_Obj_t * pNew ) { assert( !Abc_ObjIsComplement(pOld) ); assert( !Abc_ObjIsComplement(pNew) ); Abc_NtkIncrementTravId(pNtk); return Abc_NtkHaigCheckTfi_rec( pNew, pOld ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Abc_Obj_t * Hop_ObjChild0Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin0(pObj)->pNext, Hop_ObjFaninC0(pObj) ); } static inline Abc_Obj_t * Hop_ObjChild1Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin1(pObj)->pNext, Hop_ObjFaninC1(pObj) ); } /**Function************************************************************* Synopsis [Stops history AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p ) { Abc_Ntk_t * pNtkAig; Abc_Obj_t * pObjOld, * pObjAbcThis, * pObjAbcRepr; Hop_Obj_t * pObj; int i; assert( p->nCreated == Vec_PtrSize(p->vObjs) ); // start the new network pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // transfer new nodes to the PIs of HOP Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig ); Hop_ManForEachPi( p, pObj, i ) pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i ); // construct new nodes Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { if ( !Hop_ObjIsNode(pObj) ) continue; pObj->pNext = (Hop_Obj_t *)Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); assert( !Hop_IsComplement(pObj->pNext) ); } // set the COs Abc_NtkForEachCo( pNtk, pObjOld, i ) Abc_ObjAddFanin( pObjOld->pCopy, Hop_ObjChild0Next(Hop_ManPo(p,i)) ); // construct choice nodes Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { // skip the node without choices if ( pObj->pData == NULL ) continue; // skip the representative of the class if ( pObj->pData == pObj ) continue; // do not create choices for constant 1 and PIs if ( !Hop_ObjIsNode((Hop_Obj_t *)pObj->pData) ) continue; // get the corresponding new nodes pObjAbcThis = (Abc_Obj_t *)pObj->pNext; pObjAbcRepr = (Abc_Obj_t *)((Hop_Obj_t *)pObj->pData)->pNext; // the new node cannot be already in the class assert( pObjAbcThis->pData == NULL ); // the new node cannot have fanouts assert( Abc_ObjFanoutNum(pObjAbcThis) == 0 ); // these should be different nodes assert( pObjAbcRepr != pObjAbcThis ); // do not create choices if there is a path from pObjAbcThis to pObjAbcRepr if ( !Abc_NtkHaigCheckTfi( pNtkAig, pObjAbcRepr, pObjAbcThis ) ) { // find the last node in the class while ( pObjAbcRepr->pData ) pObjAbcRepr = (Abc_Obj_t *)pObjAbcRepr->pData; // add the new node at the end of the list pObjAbcRepr->pData = pObjAbcThis; } } // finish the new network // Abc_NtkFinalize( pNtk, pNtkAig ); // Abc_AigCleanup( pNtkAig->pManFunc ); // check correctness of the network if ( !Abc_NtkCheck( pNtkAig ) ) { printf( "Abc_NtkHaigUse: The network check has failed.\n" ); Abc_NtkDelete( pNtkAig ); return NULL; } return pNtkAig; } /**Function************************************************************* Synopsis [Resets representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkHaigResetReprsOld( Hop_Man_t * pMan ) { Vec_Ptr_t * vMembers, * vClasses; // collect members of the classes and make them point to reprs vMembers = Abc_NtkHaigCollectMembers( pMan ); printf( "Collected %6d class members.\n", Vec_PtrSize(vMembers) ); // create classes vClasses = Abc_NtkHaigCreateClasses( vMembers ); printf( "Collected %6d classes. (Ave = %5.2f)\n", Vec_PtrSize(vClasses), (float)(Vec_PtrSize(vMembers))/Vec_PtrSize(vClasses) ); Vec_PtrFree( vMembers ); Vec_PtrFree( vClasses ); } /**Function************************************************************* Synopsis [Resets representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkHaigResetReprs( Hop_Man_t * p ) { Hop_Obj_t * pObj, * pRepr; int i, nClasses, nMembers, nFanouts, nNormals; // clear self-classes Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { // fix the strange situation of double-loop pRepr = (Hop_Obj_t *)pObj->pData; if ( pRepr && pRepr->pData == pObj ) pRepr->pData = pRepr; // remove self-loops if ( pObj->pData == pObj ) pObj->pData = NULL; } // set representatives Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { if ( pObj->pData == NULL ) continue; // get representative of the node pRepr = Hop_ObjRepr( pObj ); pRepr->pData = pRepr; // set the representative pObj->pData = pRepr; } // make each class point to the smallest topological order Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { if ( pObj->pData == NULL ) continue; pRepr = Hop_ObjRepr( pObj ); if ( pRepr->Id > pObj->Id ) { pRepr->pData = pObj; pObj->pData = pObj; } else pObj->pData = pRepr; } // count classes, members, and fanouts - and verify nMembers = nClasses = nFanouts = nNormals = 0; Vec_PtrForEachEntry( Hop_Obj_t *, p->vObjs, pObj, i ) { if ( pObj->pData == NULL ) continue; // count members nMembers++; // count the classes and fanouts if ( pObj->pData == pObj ) nClasses++; else if ( Hop_ObjRefs(pObj) > 0 ) nFanouts++; else nNormals++; // compare representatives pRepr = Hop_ObjRepr( pObj ); assert( pObj->pData == pRepr ); assert( pRepr->Id <= pObj->Id ); } // printf( "Nodes = %7d. Member = %7d. Classes = %6d. Fanouts = %6d. Normals = %6d.\n", // Hop_ManNodeNum(p), nMembers, nClasses, nFanouts, nNormals ); return nFanouts; } /**Function************************************************************* Synopsis [Transform HOP manager into the one without loops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) { Abc_Ntk_t * pNtkAig; Hop_Man_t * pManTemp; // iteratively reconstruct the HOP manager to create choice nodes while ( Abc_NtkHaigResetReprs( pMan ) ) { pMan = Abc_NtkHaigReconstruct( pManTemp = pMan ); Hop_ManStop( pManTemp ); } // traverse in the topological order and create new AIG pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan ); Hop_ManStop( pMan ); return pNtkAig; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcIf.c000066400000000000000000000737501300674244400230300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcIf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface with the FPGA mapping package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "map/if/if.h" #include "bool/kit/kit.h" #include "aig/aig/aig.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ); extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ); static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ); static Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk ); extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Interface with the FPGA mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManComputeSwitching( If_Man_t * pIfMan ) { abctime clk = Abc_Clock(); Gia_Man_t * pNew; Vec_Int_t * vCopy; If_Obj_t * pIfObj; int i; assert( pIfMan->vSwitching == NULL ); // create the new manager pNew = Gia_ManStart( If_ManObjNum(pIfMan) ); vCopy = Vec_IntAlloc( If_ManObjNum(pIfMan) ); // constant and inputs Vec_IntPush( vCopy, 1 ); If_ManForEachCi( pIfMan, pIfObj, i ) Vec_IntPush( vCopy, Gia_ManAppendCi(pNew) ); // internal nodes If_ManForEachNode( pIfMan, pIfObj, i ) { int iLit0 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin0(pIfObj)->Id), If_ObjFaninC0(pIfObj) ); int iLit1 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin1(pIfObj)->Id), If_ObjFaninC1(pIfObj) ); Vec_IntPush( vCopy, Gia_ManAppendAnd(pNew, iLit0, iLit1) ); } // outputs If_ManForEachCo( pIfMan, pIfObj, i ) { int iLit0 = Abc_LitNotCond( Vec_IntEntry(vCopy, If_ObjFanin0(pIfObj)->Id), If_ObjFaninC0(pIfObj) ); Vec_IntPush( vCopy, Gia_ManAppendCo(pNew, iLit0) ); } assert( Vec_IntSize(vCopy) == If_ManObjNum(pIfMan) ); Vec_IntFree( vCopy ); // compute switching activity pIfMan->vSwitching = Gia_ManComputeSwitchProbs( pNew, 48, 16, 0 ); Gia_ManStop( pNew ); if ( pIfMan->pPars->fVerbose ) Abc_PrintTime( 1, "Computing switching activity", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Interface with the FPGA mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) { Abc_Ntk_t * pNtkNew, * pTemp; If_Man_t * pIfMan; assert( Abc_NtkIsStrash(pNtk) ); // get timing information pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // update timing info to reflect logic level if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib) && pNtk->pManTime ) { int c; if ( pNtk->AndGateDelay == 0.0 ) { if ( Abc_FrameReadLibGen() ) pNtk->AndGateDelay = Mio_LibraryReadDelayAigNode((Mio_Library_t *)Abc_FrameReadLibGen()); if ( pNtk->AndGateDelay == 0.0 ) { pNtk->AndGateDelay = 1.0; printf( "The AIG-node delay is not set. Assuming unit-delay.\n" ); } } for ( c = 0; c < Abc_NtkCiNum(pNtk); c++ ) pPars->pTimesArr[c] /= pNtk->AndGateDelay; for ( c = 0; c < Abc_NtkCoNum(pNtk); c++ ) pPars->pTimesReq[c] /= pNtk->AndGateDelay; } // set the latch paths if ( pPars->fLatchPaths && pPars->pTimesArr ) { int c; for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ ) pPars->pTimesArr[c] = -ABC_INFINITY; } // create FPGA mapper pIfMan = Abc_NtkToIf( pNtk, pPars ); if ( pIfMan == NULL ) return NULL; if ( pPars->fPower ) If_ManComputeSwitching( pIfMan ); // 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 ); } // perform FPGA mapping if ( !If_ManPerformMapping( pIfMan ) ) { If_ManStop( pIfMan ); return NULL; } // transform the result of mapping into the new network pNtkNew = Abc_NtkFromIf( pIfMan, pNtk ); if ( pNtkNew == NULL ) return NULL; If_ManStop( pIfMan ); if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib ) { pNtkNew = Abc_NtkStrash( pTemp = pNtkNew, 0, 0, 0 ); Abc_NtkDelete( pTemp ); } else if ( pPars->fBidec && pPars->nLutSize <= 8 ) Abc_NtkBidecResyn( pNtkNew, 0 ); // duplicate EXDC if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkIf: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Load the network into FPGA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline If_Obj_t * Abc_ObjIfCopy( Abc_Obj_t * pNode ) { return (If_Obj_t *)pNode->pCopy; } If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) { ProgressBar * pProgress; If_Man_t * pIfMan; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pPrev; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the mapping manager and set its parameters pIfMan = If_ManStart( pPars ); pIfMan->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) ); // print warning about excessive memory usage if ( 1.0 * Abc_NtkObjNum(pNtk) * 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 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) ); // create PIs and remember them in the old nodes Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan ); Abc_NtkForEachCi( pNtk, pNode, i ) { pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan ); // transfer logic level information Abc_ObjIfCopy(pNode)->Level = pNode->Level; } // load the AIG into the mapper pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); vNodes = Abc_AigDfs( pNtk, 0, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, "Initial" ); // add the node to the mapper pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan, If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin0(pNode)), Abc_ObjFaninC0(pNode) ), If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin1(pNode)), Abc_ObjFaninC1(pNode) ) ); // set up the choice node if ( Abc_AigNodeIsChoice( pNode ) ) { Abc_Obj_t * pEquiv; // int Counter = 0; assert( If_ObjId(Abc_ObjIfCopy(pNode)) > If_ObjId(Abc_ObjIfCopy(Abc_ObjEquiv(pNode))) ); for ( pPrev = pNode, pEquiv = Abc_ObjEquiv(pPrev); pEquiv; pPrev = pEquiv, pEquiv = Abc_ObjEquiv(pPrev) ) If_ObjSetChoice( Abc_ObjIfCopy(pPrev), Abc_ObjIfCopy(pEquiv) );//, Counter++; // printf( "%d ", Counter ); If_ManCreateChoice( pIfMan, Abc_ObjIfCopy(pNode) ); } } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); // set the primary outputs without copying the phase Abc_NtkForEachCo( pNtk, pNode, i ) pNode->pCopy = (Abc_Obj_t *)If_ManCreateCo( pIfMan, If_NotCond( Abc_ObjIfCopy(Abc_ObjFanin0(pNode)), Abc_ObjFaninC0(pNode) ) ); return pIfMan; } /**Function************************************************************* Synopsis [Box mapping procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_MapBoxSetPrevNext( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id ) { Abc_Obj_t * pNode; pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2); Vec_IntWriteEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(pNode)), Id ); pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4); Vec_IntWriteEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(pNode)), Id ); } static inline int Abc_MapBox2Next( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id ) { Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4); return Vec_IntEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(pNode)) ); } static inline int Abc_MapBox2Prev( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id ) { Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2); return Vec_IntEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(pNode)) ); } /**Function************************************************************* Synopsis [Creates the mapped network.] Description [Assuming the copy field of the mapped nodes are NULL.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pNodeNew; Vec_Int_t * vCover; int i, nDupGates; // create the new network if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->fUserSesLib || pIfMan->pPars->nGateSize > 0 ) pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); else pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); // prepare the mapping manager If_ManCleanNodeCopy( pIfMan ); If_ManCleanCutData( pIfMan ); // make the mapper point to the new network If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) ); Abc_NtkForEachCi( pNtk, pNode, i ) If_ObjSetCopy( If_ManCi(pIfMan, i), pNode->pCopy ); // process the nodes in topological order vCover = Vec_IntAlloc( 1 << 16 ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, "Final" ); pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManCo(pIfMan, i)), vCover ); pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManCo(pIfMan, i)) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Extra_ProgressBarStop( pProgress ); Vec_IntFree( vCover ); // remove the constant node if not used pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) ); if ( Abc_ObjFanoutNum(pNodeNew) == 0 && !Abc_ObjIsNone(pNodeNew) ) Abc_NtkDeleteObj( pNodeNew ); // minimize the node if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) Abc_NtkSweep( pNtkNew, 0 ); if ( pIfMan->pPars->fUseBdds ) Abc_NtkBddReorder( pNtkNew, 0 ); // decouple the PO driver nodes to reduce the number of levels nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, !pIfMan->pPars->fUseBuffs ); if ( nDupGates && pIfMan->pPars->fVerbose && !Abc_FrameReadFlag("silentmode") ) { if ( pIfMan->pPars->fUseBuffs ) printf( "Added %d buffers/inverters to decouple the CO drivers.\n", nDupGates ); else printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); } return pNtkNew; } /**Function************************************************************* Synopsis [Rebuilds GIA from mini AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_NodeBuildFromMiniInt( Hop_Man_t * pMan, Vec_Int_t * vAig, int nLeaves ) { assert( Vec_IntSize(vAig) > 0 ); assert( Vec_IntEntryLast(vAig) < 2 ); if ( Vec_IntSize(vAig) == 1 ) // const { assert( nLeaves == 0 ); return Hop_NotCond( Hop_ManConst0(pMan), Vec_IntEntry(vAig, 0) ); } if ( Vec_IntSize(vAig) == 2 ) // variable { assert( Vec_IntEntry(vAig, 0) == 0 ); assert( nLeaves == 1 ); return Hop_NotCond( Hop_IthVar(pMan, 0), Vec_IntEntry(vAig, 1) ); } else { int i, iVar0, iVar1, iLit0, iLit1; Hop_Obj_t * piLit0, * piLit1, * piLit = NULL; assert( Vec_IntSize(vAig) & 1 ); Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i ) { iVar0 = Abc_Lit2Var( iLit0 ); iVar1 = Abc_Lit2Var( iLit1 ); piLit0 = Hop_NotCond( iVar0 < nLeaves ? Hop_IthVar(pMan, iVar0) : (Hop_Obj_t *)Vec_PtrEntry((Vec_Ptr_t *)vAig, iVar0 - nLeaves), Abc_LitIsCompl(iLit0) ); piLit1 = Hop_NotCond( iVar1 < nLeaves ? Hop_IthVar(pMan, iVar1) : (Hop_Obj_t *)Vec_PtrEntry((Vec_Ptr_t *)vAig, iVar1 - nLeaves), Abc_LitIsCompl(iLit1) ); piLit = Hop_And( pMan, piLit0, piLit1 ); assert( (i & 1) == 0 ); Vec_PtrWriteEntry( (Vec_Ptr_t *)vAig, Abc_Lit2Var(i), piLit ); // overwriting entries } assert( i == Vec_IntSize(vAig) - 1 ); piLit = Hop_NotCond( piLit, Vec_IntEntry(vAig, i) ); Vec_IntClear( vAig ); // useless return piLit; } } Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pCut, int fUseDsd ) { int Delay; if ( fUseDsd ) Delay = If_CutDsdBalanceEval( p, pCut, p->vArray ); else Delay = If_CutSopBalanceEval( p, pCut, p->vArray ); assert( Delay >= 0 ); return Abc_NodeBuildFromMiniInt( pMan, p->vArray, If_CutLeaveNum(pCut) ); } /**Function************************************************************* Synopsis [Derive one node after FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ) { Abc_Obj_t * pNodeNew; If_Cut_t * pCutBest; If_Obj_t * pIfLeaf; int i; // return if the result if known pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj ); if ( pNodeNew ) return pNodeNew; assert( pIfObj->Type == IF_AND ); // get the parameters of the best cut pCutBest = If_ObjCutBest( pIfObj ); if ( pIfMan->pPars->fUserSesLib ) { // create the subgraph composed of Abc_Obj_t nodes based on the given cut Abc_Obj_t * pFanins[IF_MAX_FUNC_LUTSIZE]; If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) pFanins[i] = Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover); pNodeNew = Abc_ExactBuildNode( If_CutTruthW(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), If_CutArrTimeProfile(pIfMan, pCutBest), pFanins, pNtkNew ); If_ObjSetCopy( pIfObj, pNodeNew ); return pNodeNew; } // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); // if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays ) if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize ) If_CutRotatePins( pIfMan, pCutBest ); if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } else { If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); } // set the level of the new node pNodeNew->Level = Abc_ObjLevelNew( pNodeNew ); // derive the function of this node if ( pIfMan->pPars->fTruth ) { if ( pIfMan->pPars->fUseBdds ) { // transform truth table into the BDD #ifdef ABC_USE_CUDD pNodeNew->pData = Kit_TruthToBdd( (DdManager *)pNtkNew->pManFunc, If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), 0 ); Cudd_Ref((DdNode *)pNodeNew->pData); #endif } else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) { // transform truth table into the BDD #ifdef ABC_USE_CUDD pNodeNew->pData = Kit_TruthToBdd( (DdManager *)pNtkNew->pManFunc, If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), 1 ); Cudd_Ref((DdNode *)pNodeNew->pData); #endif } else if ( pIfMan->pPars->fUseSops || pIfMan->pPars->nGateSize > 0 ) { // transform truth table into the SOP int RetValue = Kit_TruthIsop( If_CutTruth(pIfMan, pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 ); assert( RetValue == 0 || RetValue == 1 ); // check the case of constant cover if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) { assert( RetValue == 0 ); pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), NULL ); pNodeNew = (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew); } else { // derive the AIG for that tree pNodeNew->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), vCover ); if ( RetValue ) Abc_SopComplement( (char *)pNodeNew->pData ); } } else if ( pIfMan->pPars->fDelayOpt ) pNodeNew->pData = Abc_NodeBuildFromMini( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, 0 ); else if ( pIfMan->pPars->fDsdBalance ) pNodeNew->pData = Abc_NodeBuildFromMini( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, 1 ); else if ( pIfMan->pPars->fUserRecLib ) { extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ); pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj ); } else { extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); word * pTruth = If_CutTruthW(pIfMan, pCutBest); if ( pIfMan->pPars->fUseTtPerm ) for ( i = 0; i < (int)pCutBest->nLeaves; i++ ) if ( If_CutLeafBit(pCutBest, i) ) Abc_TtFlip( pTruth, Abc_TtWordNum(pCutBest->nLeaves), i ); pNodeNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover ); // if ( pIfMan->pPars->fUseBat ) // Bat_ManFuncPrintCell( *pTruth ); } // complement the node if the cut was complemented if ( pCutBest->fCompl && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDsdBalance ) Abc_NodeComplement( pNodeNew ); } else { pNodeNew->pData = Abc_NodeIfToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pIfObj ); } If_ObjSetCopy( pIfObj, pNodeNew ); return pNodeNew; } /**Function************************************************************* Synopsis [Recursively derives the truth table for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) { If_Cut_t * pCut; Hop_Obj_t * gFunc, * gFunc0, * gFunc1; // get the best cut pCut = If_ObjCutBest(pIfObj); // if the cut is visited, return the result if ( If_CutData(pCut) ) return (Hop_Obj_t *)If_CutData(pCut); // compute the functions of the children gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited ); gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited ); // get the function of the cut gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) ); assert( If_CutData(pCut) == NULL ); If_CutSetData( pCut, gFunc ); // add this cut to the visited list Vec_PtrPush( vVisited, pCut ); return gFunc; } /**Function************************************************************* Synopsis [Recursively derives the truth table for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) { If_Cut_t * pCut; If_Obj_t * pTemp; Hop_Obj_t * gFunc, * gFunc0, * gFunc1; // get the best cut pCut = If_ObjCutBest(pIfObj); // if the cut is visited, return the result if ( If_CutData(pCut) ) return (Hop_Obj_t *)If_CutData(pCut); // mark the node as visited Vec_PtrPush( vVisited, pCut ); // insert the worst case If_CutSetData( pCut, (void *)1 ); // skip in case of primary input if ( If_ObjIsCi(pIfObj) ) return (Hop_Obj_t *)If_CutData(pCut); // compute the functions of the children for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) { gFunc0 = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin0, vVisited ); if ( gFunc0 == (void *)1 ) continue; gFunc1 = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin1, vVisited ); if ( gFunc1 == (void *)1 ) continue; // both branches are solved gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pTemp->fCompl0), Hop_NotCond(gFunc1, pTemp->fCompl1) ); if ( pTemp->fPhase != pIfObj->fPhase ) gFunc = Hop_Not(gFunc); If_CutSetData( pCut, gFunc ); break; } return (Hop_Obj_t *)If_CutData(pCut); } /**Function************************************************************* Synopsis [Derives the truth table for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ) { If_Cut_t * pCut; Hop_Obj_t * gFunc; If_Obj_t * pLeaf; int i; // get the best cut pCut = If_ObjCutBest(pIfObj); assert( pCut->nLeaves > 1 ); // set the leaf variables If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) ); // recursively compute the function while collecting visited cuts Vec_PtrClear( pIfMan->vTemp ); gFunc = Abc_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); if ( gFunc == (void *)1 ) { printf( "Abc_NodeIfToHop(): Computing local AIG has failed.\n" ); return NULL; } // clean the cuts If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) If_CutSetData( If_ObjCutBest(pLeaf), NULL ); Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) If_CutSetData( pCut, NULL ); return gFunc; } /**Function************************************************************* Synopsis [Comparison for two nodes with the flow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjCompareFlow( Abc_Obj_t ** ppNode0, Abc_Obj_t ** ppNode1 ) { float Flow0 = Abc_Int2Float((int)(ABC_PTRINT_T)(*ppNode0)->pCopy); float Flow1 = Abc_Int2Float((int)(ABC_PTRINT_T)(*ppNode1)->pCopy); if ( Flow0 > Flow1 ) return -1; if ( Flow0 < Flow1 ) return 1; return 0; } /**Function************************************************************* Synopsis [Orders AIG nodes so that nodes from larger cones go first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFindGoodOrder_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { if ( !Abc_ObjIsNode(pNode) ) return; assert( Abc_ObjIsNode( pNode ) ); // 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_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes ); Abc_NtkFindGoodOrder_rec( Abc_ObjFanin1(pNode), vNodes ); // add the node after the fanins have been added Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Orders AIG nodes so that nodes from larger cones go first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes, * vCos; Abc_Obj_t * pNode, * pFanin0, * pFanin1; float Flow0, Flow1; int i; // initialize the flow Abc_AigConst1(pNtk)->pCopy = NULL; Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = NULL; // compute the flow Abc_AigForEachAnd( pNtk, pNode, i ) { pFanin0 = Abc_ObjFanin0(pNode); pFanin1 = Abc_ObjFanin1(pNode); Flow0 = Abc_Int2Float((int)(ABC_PTRINT_T)pFanin0->pCopy)/Abc_ObjFanoutNum(pFanin0); Flow1 = Abc_Int2Float((int)(ABC_PTRINT_T)pFanin1->pCopy)/Abc_ObjFanoutNum(pFanin1); pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Abc_Float2Int(Flow0 + Flow1+(float)1.0); } // find the flow of the COs vCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy; // pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int((float)Abc_ObjFanin0(pNode)->Level); Vec_PtrPush( vCos, pNode ); } // sort nodes in the increasing order of the flow qsort( (Abc_Obj_t **)Vec_PtrArray(vCos), Abc_NtkCoNum(pNtk), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *))Abc_ObjCompareFlow ); // verify sorting pFanin0 = (Abc_Obj_t *)Vec_PtrEntry(vCos, 0); pFanin1 = (Abc_Obj_t *)Vec_PtrEntryLast(vCos); assert( Abc_Int2Float((int)(ABC_PTRINT_T)pFanin0->pCopy) >= Abc_Int2Float((int)(ABC_PTRINT_T)pFanin1->pCopy) ); // collect the nodes in the topological order from the new array Abc_NtkIncrementTravId( pNtk ); vNodes = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vCos, pNode, i ) Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes ); Vec_PtrFree( vCos ); return vNodes; } /**Function************************************************************* Synopsis [Sets PO drivers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMarkMux( Abc_Obj_t * pDriver, Abc_Obj_t ** ppNode1, Abc_Obj_t ** ppNode2 ) { Abc_Obj_t * pNodeC, * pNodeT, * pNodeE; If_Obj_t * pIfObj; *ppNode1 = NULL; *ppNode2 = NULL; if ( pDriver == NULL ) return; if ( !Abc_NodeIsMuxType(pDriver) ) return; pNodeC = Abc_NodeRecognizeMux( pDriver, &pNodeT, &pNodeE ); pIfObj = If_Regular( (If_Obj_t *)Abc_ObjFanin0(pDriver)->pCopy ); if ( If_ObjIsAnd(pIfObj) ) pIfObj->fSkipCut = 1; pIfObj = If_Regular( (If_Obj_t *)Abc_ObjFanin1(pDriver)->pCopy ); if ( If_ObjIsAnd(pIfObj) ) pIfObj->fSkipCut = 1; pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeC)->pCopy ); if ( If_ObjIsAnd(pIfObj) ) pIfObj->fSkipCut = 1; /* pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeT)->pCopy ); if ( If_ObjIsAnd(pIfObj) ) pIfObj->fSkipCut = 1; pIfObj = If_Regular( (If_Obj_t *)Abc_ObjRegular(pNodeE)->pCopy ); if ( If_ObjIsAnd(pIfObj) ) pIfObj->fSkipCut = 1; */ *ppNode1 = Abc_ObjRegular(pNodeC); *ppNode2 = Abc_ObjRegular(pNodeT); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcIfMux.c000066400000000000000000000247441300674244400235210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcIf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface with the FPGA mapping package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_NtkFuncCof0( int t, int v ) { static int s_Truth[3] = { 0xAA, 0xCC, 0xF0 }; return 0xff & ((t & ~s_Truth[v]) | ((t & ~s_Truth[v]) << (1<> (1<> (1<nLeaves < 3 ) return 1; if ( pCut->nLeaves == 3 && uLookup[0xff & *If_CutTruth(p, pCut)] ) return 1; return (1 << pCut->nLeaves) - 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcIfif.c000066400000000000000000000266421300674244400233450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcIfif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Experiment with technology mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcIfif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define IFIF_MAX_LEAVES 6 typedef struct Abc_IffObj_t_ Abc_IffObj_t; struct Abc_IffObj_t_ { float Delay[IFIF_MAX_LEAVES+1]; // separate delay // int nLeaves; // int pLeaves[IFIF_MAX_LEAVES]; }; typedef struct Abc_IffMan_t_ Abc_IffMan_t; struct Abc_IffMan_t_ { Abc_Ntk_t * pNtk; Ifif_Par_t * pPars; // internal data int nObjs; Abc_IffObj_t * pObjs; }; static inline Abc_IffObj_t * Abc_IffObj( Abc_IffMan_t * p, int i ) { assert( i >= 0 && i < p->nObjs ); return p->pObjs + i; } static inline float Abc_IffDelay( Abc_IffMan_t * p, Abc_Obj_t * pObj, int fDelay1 ) { return Abc_IffObj(p, Abc_ObjId(pObj))->Delay[fDelay1]; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_IffMan_t * Abc_NtkIfifStart( Abc_Ntk_t * pNtk, Ifif_Par_t * pPars ) { Abc_IffMan_t * p; p = ABC_CALLOC( Abc_IffMan_t, 1 ); p->pNtk = pNtk; p->pPars = pPars; // internal data p->nObjs = Abc_NtkObjNumMax( pNtk ); p->pObjs = ABC_CALLOC( Abc_IffObj_t, p->nObjs ); return p; } void Abc_NtkIfifStop( Abc_IffMan_t * p ) { // internal data ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collects fanins into ppNodes in decreasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjSortByDelay( Abc_IffMan_t * p, Abc_Obj_t * pObj, int fDelay1, Abc_Obj_t ** ppNodes ) { Abc_Obj_t * pFanin; int i, a, k = 0; Abc_ObjForEachFanin( pObj, pFanin, i ) { ppNodes[k++] = pFanin; if ( Abc_ObjIsCi(pFanin) ) continue; for ( a = k-1; a > 0; a-- ) if ( Abc_IffDelay(p, ppNodes[a-1], fDelay1) + p->pPars->pLutDelays[a-1] < Abc_IffDelay(p, ppNodes[a], fDelay1) + p->pPars->pLutDelays[a] ) ABC_SWAP( Abc_Obj_t *, ppNodes[a-1], ppNodes[a] ); } /* for ( a = 1; a < k; a++ ) { float D1 = Abc_IffDelay(p, ppNodes[a-1], fDelay1); float D2 = Abc_IffDelay(p, ppNodes[a], fDelay1); if ( Abc_ObjIsCi(ppNodes[a-1]) || Abc_ObjIsCi(ppNodes[a]) ) continue; assert( Abc_IffDelay(p, ppNodes[a-1], fDelay1) + p->pPars->pLutDelays[a-1] >= Abc_IffDelay(p, ppNodes[a], fDelay1) + p->pPars->pLutDelays[a] - 0.01 ); } */ } /**Function************************************************************* Synopsis [This is the delay which object has all by itself.] Description [This delay is stored in Delay0.] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_ObjDelay0( Abc_IffMan_t * p, Abc_Obj_t * pObj ) { int i; float Delay0 = 0; Abc_Obj_t * ppNodes[6]; Abc_ObjSortByDelay( p, pObj, 1, ppNodes ); for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) Delay0 = Abc_MaxFloat( Delay0, Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i] ); return Delay0; } /**Function************************************************************* Synopsis [This is the delay object has in the structure.] Description [This delay is stored in Delay1.] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_ObjDelay1( Abc_IffMan_t * p, Abc_Obj_t * pObj ) { int i, fVeryVerbose = 0; // Abc_IffObj_t * pIfif = Abc_IffObj( p, Abc_ObjId(pObj) ); Abc_Obj_t * ppNodes[6]; float Delay1, DelayNew; if ( Abc_ObjFaninNum(pObj) == 0 ) return 0; // sort fanins by delay1+LutDelay Abc_ObjSortByDelay( p, pObj, 1, ppNodes ); // print verbose results if ( fVeryVerbose ) { printf( "Object %d Level %d\n", Abc_ObjId(pObj), Abc_ObjLevel(pObj) ); for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) { printf( "Fanin %d : ", i ); printf( "D0 %3.2f ", Abc_IffDelay(p, ppNodes[i], 0) ); printf( "D0* %3.2f ", Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire ); printf( "D1 %3.2f", Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i] ); printf( "\n" ); } printf( "\n" ); } /* // for the first nDegree delays, sort them by the minimum Delay1+LutDelay and Delay0-Wire+LutDelay Delay1 = 0; pIfif->nLeaves = 0; for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) { if ( Abc_ObjIsNode(ppNodes[i]) && pIfif->nLeaves < p->pPars->nDegree ) { DelayNew = Abc_MinFloat( Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i], Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire ); pIfif->pLeaves[pIfif->nLeaves++] = Abc_ObjId(ppNodes[i]); } else DelayNew = Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i]; Delay1 = Abc_MaxFloat( Delay1, DelayNew ); } */ // for the first nDegree delays, sort them by the minimum Delay1+LutDelay and Delay0-Wire+LutDelay Delay1 = 0; for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) { if ( i < p->pPars->nDegree ) DelayNew = Abc_MinFloat( Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i], Abc_IffDelay(p, ppNodes[i], 0) + p->pPars->pLutDelays[i] - p->pPars->DelayWire ); else DelayNew = Abc_IffDelay(p, ppNodes[i], 1) + p->pPars->pLutDelays[i]; Delay1 = Abc_MaxFloat( Delay1, DelayNew ); } assert( Delay1 > 0 ); return Delay1; } /**Function************************************************************* Synopsis [This is the delay which object has all by itself.] Description [This delay is stored in Delay0.] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_ObjDelayDegree( Abc_IffMan_t * p, Abc_Obj_t * pObj, int d ) { int i; float Delay0 = 0, DelayNew; Abc_Obj_t * ppNodes[6]; assert( d >= 0 && d <= p->pPars->nDegree ); Abc_ObjSortByDelay( p, pObj, p->pPars->nDegree, ppNodes ); for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) { DelayNew = Abc_IffDelay(p, ppNodes[i], p->pPars->nDegree) + p->pPars->pLutDelays[i]; if ( i == 0 && d > 0 ) DelayNew = Abc_MinFloat(DelayNew, Abc_IffDelay(p, ppNodes[i], d-1) + p->pPars->pLutDelays[i] - p->pPars->DelayWire ); Delay0 = Abc_MaxFloat( Delay0, DelayNew ); } return Delay0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPerformIfif( Abc_Ntk_t * pNtk, Ifif_Par_t * pPars ) { Abc_IffMan_t * p; Abc_IffObj_t * pIffObj; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; float Delay, Delay10, DegreeFinal; int i, d, Count10; assert( pPars->pLutLib->LutMax >= 0 && pPars->pLutLib->LutMax <= IFIF_MAX_LEAVES ); assert( pPars->nLutSize >= 0 && pPars->nLutSize <= IFIF_MAX_LEAVES ); assert( pPars->nDegree >= 0 && pPars->nDegree <= IFIF_MAX_LEAVES ); // convert to AIGs Abc_NtkToAig( pNtk ); Abc_NtkLevel( pNtk ); // print parameters if ( pPars->fVerbose ) { printf( "Running mapper into LUT structures with the following parameters:\n" ); printf( "Pin+Wire: {" ); for ( i = 0; i < pPars->pLutLib->LutMax; i++ ) printf( " %3.2f", pPars->pLutDelays[i] ); printf( " } " ); printf( "Wire %3.2f Degree %d Type: %s\n", pPars->DelayWire, pPars->nDegree, pPars->fCascade? "Cascade" : "Cluster" ); } // start manager p = Abc_NtkIfifStart( pNtk, pPars ); // printf( "Running experiment with LUT delay %d and degree %d (LUT size is %d).\n", DelayWire, nDegree, nLutSize ); // compute the delay vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { assert( Abc_ObjIsNode(pObj) ); pIffObj = Abc_IffObj( p, Abc_ObjId(pObj) ); if ( pPars->fCascade ) { for ( d = 0; d <= pPars->nDegree; d++ ) pIffObj->Delay[d] = Abc_ObjDelayDegree( p, pObj, d ); } else { pIffObj->Delay[0] = Abc_ObjDelay0( p, pObj ); pIffObj->Delay[1] = Abc_ObjDelay1( p, pObj ); } } // get final degree number if ( pPars->fCascade ) DegreeFinal = pPars->nDegree; else DegreeFinal = 1; if ( p->pPars->fVeryVerbose ) Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { printf( "Node %3d : Lev =%3d ", Abc_ObjId(pObj), Abc_ObjLevel(pObj) ); for ( d = 0; d <= DegreeFinal; d++ ) printf( "Del%d =%4.2f ", d, Abc_IffDelay(p, pObj, d) ); printf( "\n" ); } Vec_PtrFree( vNodes ); // consider delay at the outputs Delay = 0; Abc_NtkForEachCo( pNtk, pObj, i ) Delay = Abc_MaxFloat( Delay, Abc_IffDelay(p, Abc_ObjFanin0(pObj), DegreeFinal) ); Delay10 = 0.9 * Delay; // consider delay at the outputs Count10 = 0; Abc_NtkForEachCo( pNtk, pObj, i ) if ( Abc_IffDelay(p, Abc_ObjFanin0(pObj), DegreeFinal) >= Delay10 ) Count10++; printf( "Critical delay %5.2f. Critical outputs %5.2f %%\n", Delay, 100.0 * Count10 / Abc_NtkCoNum(pNtk) ); // printf( "%.2f %.2f\n", Delay, 100.0 * Count10 / Abc_NtkCoNum(pNtk) ); // derive a new network // stop manager Abc_NtkIfifStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcIvy.c000066400000000000000000001103441300674244400232300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcIvy.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Strashing of the current network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcIvy.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "bool/dec/dec.h" #include "proof/fra/fra.h" #include "aig/ivy/ivy.h" #include "proof/fraig/fraig.h" #include "map/mio/mio.h" #include "aig/aig/aig.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern void Aig_ManStop( Aig_Man_t * pMan ); //extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ); extern Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ); extern void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ); //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan ); static Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig ); static Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld ); static void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ); static Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode ); static Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); static Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); static Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); typedef int Abc_Edge_t; static inline Abc_Edge_t Abc_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } static inline int Abc_EdgeId( Abc_Edge_t Edge ) { return Edge >> 1; } static inline int Abc_EdgeIsComplement( Abc_Edge_t Edge ) { return Edge & 1; } static inline Abc_Edge_t Abc_EdgeRegular( Abc_Edge_t Edge ) { return (Edge >> 1) << 1; } static inline Abc_Edge_t Abc_EdgeNot( Abc_Edge_t Edge ) { return Edge ^ 1; } static inline Abc_Edge_t Abc_EdgeNotCond( Abc_Edge_t Edge, int fCond ) { return Edge ^ fCond; } static inline Abc_Edge_t Abc_EdgeFromNode( Abc_Obj_t * pNode ) { return Abc_EdgeCreate( Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ); } static inline Abc_Obj_t * Abc_EdgeToNode( Abc_Ntk_t * p, Abc_Edge_t Edge ) { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_EdgeId(Edge)), Abc_EdgeIsComplement(Edge) ); } static inline Abc_Obj_t * Abc_ObjFanin0Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ); } static inline Abc_Obj_t * Abc_ObjFanin1Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ); } static Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ); extern int timeRetime; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prepares the IVY package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ) { Ivy_Man_t * pMan; //timeRetime = Abc_Clock(); assert( !Abc_NtkIsNetlist(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) { if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) { printf( "Abc_NtkIvyBefore(): Converting to SOPs has failed.\n" ); return NULL; } } if ( fSeq && Abc_NtkCountSelfFeedLatches(pNtk) ) { printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); // return NULL; } // print warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); // convert to the AIG manager pMan = Abc_NtkToIvy( pNtk ); if ( !Ivy_ManCheck( pMan ) ) { printf( "AIG check has failed.\n" ); Ivy_ManStop( pMan ); return NULL; } // Ivy_ManPrintStats( pMan ); if ( fSeq ) { int nLatches = Abc_NtkLatchNum(pNtk); Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, fUseDc ); Ivy_ManMakeSeq( pMan, nLatches, vInit->pArray ); Vec_IntFree( vInit ); // Ivy_ManPrintStats( pMan ); } //timeRetime = Abc_Clock() - timeRetime; return pMan; } /**Function************************************************************* Synopsis [Prepares the IVY package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvyAfter( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan, int fSeq, int fHaig ) { Abc_Ntk_t * pNtkAig; int nNodes, fCleanup = 1; // convert from the AIG manager if ( fSeq ) pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan, fHaig ); else pNtkAig = Abc_NtkFromIvy( pNtk, pMan ); // report the cleanup results if ( !fHaig && fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); // duplicate EXDC if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); // 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 [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan; pMan = Abc_NtkIvyBefore( pNtk, 1, 0 ); if ( pMan == NULL ) return NULL; pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); Ivy_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose ) { Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan; abctime clk; // int i; /* extern int nMoves; extern int nMovesS; extern int nClauses; extern int timeInv; nMoves = 0; nMovesS = 0; nClauses = 0; timeInv = 0; */ pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); if ( pMan == NULL ) return NULL; //timeRetime = Abc_Clock(); clk = Abc_Clock(); Ivy_ManHaigStart( pMan, fVerbose ); // Ivy_ManRewriteSeq( pMan, 0, 0 ); // for ( i = 0; i < nIters; i++ ) // Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 ); //printf( "%d ", Ivy_ManNodeNum(pMan) ); Ivy_ManRewriteSeq( pMan, 0, 0 ); Ivy_ManRewriteSeq( pMan, 0, 0 ); Ivy_ManRewriteSeq( pMan, 1, 0 ); //printf( "%d ", Ivy_ManNodeNum(pMan) ); //printf( "%d ", Ivy_ManNodeNum(pMan->pHaig) ); //ABC_PRT( " ", Abc_Clock() - clk ); //printf( "\n" ); /* printf( "Moves = %d. ", nMoves ); printf( "MovesS = %d. ", nMovesS ); printf( "Clauses = %d. ", nClauses ); ABC_PRT( "Time", timeInv ); */ // Ivy_ManRewriteSeq( pMan, 1, 0 ); //printf( "Haig size = %d.\n", Ivy_ManNodeNum(pMan->pHaig) ); // Ivy_ManHaigPostprocess( pMan, fVerbose ); //timeRetime = Abc_Clock() - timeRetime; // write working AIG into the current network // pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); // write HAIG into the current network pNtkAig = Abc_NtkIvyAfter( pNtk, pMan->pHaig, 1, 1 ); Ivy_ManHaigStop( pMan ); Ivy_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ) { Ivy_Man_t * pMan; pMan = Abc_NtkIvyBefore( pNtk, 1, 0 ); if ( pMan == NULL ) return; Ivy_CutComputeAll( pMan, nInputs ); Ivy_ManStop( pMan ); } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ) { Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan; pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; //timeRetime = Abc_Clock(); Ivy_ManRewritePre( pMan, fUpdateLevel, fUseZeroCost, fVerbose ); //timeRetime = Abc_Clock() - timeRetime; pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); Ivy_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ) { Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan; pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); if ( pMan == NULL ) return NULL; //timeRetime = Abc_Clock(); Ivy_ManRewriteSeq( pMan, fUseZeroCost, fVerbose ); //timeRetime = Abc_Clock() - timeRetime; // Ivy_ManRewriteSeq( pMan, 1, 0 ); // Ivy_ManRewriteSeq( pMan, 1, 0 ); pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); Ivy_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvyResyn0( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) { Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan, * pTemp; pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; pMan = Ivy_ManResyn0( pTemp = pMan, fUpdateLevel, fVerbose ); Ivy_ManStop( pTemp ); pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); Ivy_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) { Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan, * pTemp; pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; pMan = Ivy_ManResyn( pTemp = pMan, fUpdateLevel, fVerbose ); Ivy_ManStop( pTemp ); pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); Ivy_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ) { Ivy_FraigParams_t Params, * pParams = &Params; Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan, * pTemp; pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; Ivy_FraigParamsDefault( pParams ); pParams->nBTLimitMiter = nConfLimit; pParams->fVerbose = fVerbose; // pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); pMan = Ivy_FraigMiter( pTemp = pMan, pParams ); Ivy_ManStop( pTemp ); pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); Ivy_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Sets the final nodes to point to the original nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig ) { Abc_Obj_t * pObj; Ivy_Obj_t * pObjIvy, * pObjFraig; int i; pObj = Abc_AigConst1(pNtk); pObj->pCopy = Abc_AigConst1(pNtkAig); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = Abc_NtkCi(pNtkAig, i); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pCopy = Abc_NtkCo(pNtkAig, i); Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pCopy = Abc_NtkBox(pNtkAig, i); Abc_NtkForEachNode( pNtk, pObj, i ) { pObjIvy = (Ivy_Obj_t *)pObj->pCopy; if ( pObjIvy == NULL ) continue; pObjFraig = Ivy_ObjEquiv( pObjIvy ); if ( pObjFraig == NULL ) continue; pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId ); pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) ); } } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ) { Ivy_FraigParams_t Params, * pParams = &Params; Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan, * pTemp; pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); if ( pMan == NULL ) return NULL; Ivy_FraigParamsDefault( pParams ); pParams->nBTLimitNode = nConfLimit; pParams->fVerbose = fVerbose; pParams->fProve = fProve; pParams->fDoSparse = fDoSparse; pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); // transfer the pointers if ( fTransfer == 1 ) { Vec_Ptr_t * vCopies; vCopies = Abc_NtkSaveCopy( pNtk ); pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); Abc_NtkLoadCopy( pNtk, vCopies ); Vec_PtrFree( vCopies ); Abc_NtkTransferPointers( pNtk, pNtkAig ); } else pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); Ivy_ManStop( pTemp ); Ivy_ManStop( pMan ); return pNtkAig; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ) { Prove_Params_t * pParams = (Prove_Params_t *)pPars; Abc_Ntk_t * pNtk = *ppNtk, * pNtkTemp; Abc_Obj_t * pObj, * pFanin; Ivy_Man_t * pMan; Aig_Man_t * pMan2; int RetValue; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); // experiment with various parameters settings // pParams->fUseBdds = 1; // pParams->fBddReorder = 1; // pParams->nTotalBacktrackLimit = 10000; // strash the network if it is not strashed already if ( !Abc_NtkIsStrash(pNtk) ) { pNtk = Abc_NtkStrash( pNtkTemp = pNtk, 0, 1, 0 ); Abc_NtkDelete( pNtkTemp ); } // check the case when the 0000 simulation pattern detect the bug pObj = Abc_NtkPo(pNtk,0); pFanin = Abc_ObjFanin0(pObj); if ( Abc_ObjFanin0(pObj)->fPhase != (unsigned)Abc_ObjFaninC0(pObj) ) { pNtk->pModel = ABC_CALLOC( int, Abc_NtkCiNum(pNtk) ); return 0; } // changed in "src\sat\fraig\fraigMan.c" // pParams->nMiteringLimitStart = 300; // starting mitering limit // to be // pParams->nMiteringLimitStart = 5000; // starting mitering limit // if SAT only, solve without iteration // RetValue = Abc_NtkMiterSat( pNtk, 2*(ABC_INT64_T)pParams->nMiteringLimitStart, (ABC_INT64_T)0, 0, NULL, NULL ); pMan2 = Abc_NtkToDar( pNtk, 0, 0 ); RetValue = Fra_FraigSat( pMan2, (ABC_INT64_T)pParams->nMiteringLimitStart, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 ); pNtk->pModel = (int *)pMan2->pData, pMan2->pData = NULL; Aig_ManStop( pMan2 ); // pNtk->pModel = Aig_ManReleaseData( pMan2 ); if ( RetValue >= 0 ) return RetValue; // apply AIG rewriting if ( pParams->fUseRewriting && Abc_NtkNodeNum(pNtk) > 500 ) { // abctime clk = Abc_Clock(); //printf( "Before rwsat = %d. ", Abc_NtkNodeNum(pNtk) ); pParams->fUseRewriting = 0; pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); //printf( "After rwsat = %d. ", Abc_NtkNodeNum(pNtk) ); //ABC_PRT( "Time", Abc_Clock() - clk ); } // convert ABC network into IVY network pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); // solve the CEC problem RetValue = Ivy_FraigProve( &pMan, pParams ); // RetValue = -1; // convert IVY network into ABC network pNtk = Abc_NtkIvyAfter( pNtkTemp = pNtk, pMan, 0, 0 ); Abc_NtkDelete( pNtkTemp ); // transfer model if given pNtk->pModel = (int *)pMan->pData; pMan->pData = NULL; Ivy_ManStop( pMan ); // try to prove it using brute force SAT with good CNF encoding if ( RetValue < 0 ) { pMan2 = Abc_NtkToDar( pNtk, 0, 0 ); // dump the miter before entering high-effort solving if ( pParams->fVerbose ) { char pFileName[100]; sprintf( pFileName, "cecmiter.aig" ); Ioa_WriteAiger( pMan2, pFileName, 0, 0 ); printf( "Intermediate reduced miter is written into file \"%s\".\n", pFileName ); } RetValue = Fra_FraigSat( pMan2, pParams->nMiteringLimitLast, 0, 0, 0, 0, 0, 0, 0, pParams->fVerbose ); pNtk->pModel = (int *)pMan2->pData, pMan2->pData = NULL; Aig_ManStop( pMan2 ); } // try to prove it using brute force BDDs #ifdef ABC_USE_CUDD if ( RetValue < 0 && pParams->fUseBdds ) { if ( pParams->fVerbose ) { printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); fflush( stdout ); } pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); if ( pNtk ) { Abc_NtkDelete( pNtkTemp ); RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero((DdManager *)pNtk->pManFunc)) ); } else pNtk = pNtkTemp; } #endif // return the result *ppNtk = pNtk; return RetValue; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ) { // Abc_Ntk_t * pNtkAig; Ivy_Man_t * pMan;//, * pTemp; // int fCleanup = 1; // int nNodes; // int nLatches = Abc_NtkLatchNum(pNtk); Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, 0 ); assert( !Abc_NtkIsNetlist(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) { if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) { Vec_IntFree( vInit ); printf( "Abc_NtkIvy(): Converting to SOPs has failed.\n" ); return NULL; } } if ( Abc_NtkCountSelfFeedLatches(pNtk) ) { printf( "Warning: The network has %d self-feeding latches. Quitting.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); return NULL; } // print warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); // convert to the AIG manager pMan = Abc_NtkToIvy( pNtk ); if ( !Ivy_ManCheck( pMan ) ) { Vec_IntFree( vInit ); printf( "AIG check has failed.\n" ); Ivy_ManStop( pMan ); return NULL; } // Ivy_MffcTest( pMan ); // Ivy_ManPrintStats( pMan ); // pMan = Ivy_ManBalance( pTemp = pMan, 1 ); // Ivy_ManStop( pTemp ); // Ivy_ManSeqRewrite( pMan, 0, 0 ); // Ivy_ManTestCutsAlg( pMan ); // Ivy_ManTestCutsBool( pMan ); // Ivy_ManRewriteAlg( pMan, 1, 1 ); // pMan = Ivy_ManResyn( pTemp = pMan, 1, 0 ); // Ivy_ManStop( pTemp ); // Ivy_ManTestCutsAll( pMan ); // Ivy_ManTestCutsTravAll( pMan ); // Ivy_ManPrintStats( pMan ); // Ivy_ManPrintStats( pMan ); // Ivy_ManRewritePre( pMan, 1, 0, 0 ); // Ivy_ManPrintStats( pMan ); // printf( "\n" ); // Ivy_ManPrintStats( pMan ); // Ivy_ManMakeSeq( pMan, nLatches, pInit ); // Ivy_ManPrintStats( pMan ); // Ivy_ManRequiredLevels( pMan ); // Ivy_FastMapPerform( pMan, 8 ); Ivy_ManStop( pMan ); return NULL; /* // convert from the AIG manager pNtkAig = Abc_NtkFromIvy( pNtk, pMan ); // pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan ); Ivy_ManStop( pMan ); // report the cleanup results if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); // duplicate EXDC if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkAig ) ) { ABC_FREE( pInit ); printf( "Abc_NtkStrash: The network check has failed.\n" ); Abc_NtkDelete( pNtkAig ); return NULL; } ABC_FREE( pInit ); return pNtkAig; */ } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan ) { Vec_Int_t * vNodes; Abc_Ntk_t * pNtk; Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; Ivy_Obj_t * pNode; int i; // perform strashing pNtk = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); // transfer the pointers to the basic nodes Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) ); Abc_NtkForEachCi( pNtkOld, pObj, i ) Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy ); // rebuild the AIG vNodes = Ivy_ManDfs( pMan ); Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i ) { // add the first fanin pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode ); if ( Ivy_ObjIsBuf(pNode) ) { pNode->TravId = Abc_EdgeFromNode( pFaninNew0 ); continue; } // add the second fanin pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode ); // create the new node if ( Ivy_ObjIsExor(pNode) ) pObjNew = Abc_AigXor( (Abc_Aig_t *)pNtk->pManFunc, pFaninNew0, pFaninNew1 ); else pObjNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pFaninNew0, pFaninNew1 ); pNode->TravId = Abc_EdgeFromNode( pObjNew ); } // connect the PO nodes Abc_NtkForEachCo( pNtkOld, pObj, i ) { pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) ); Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); } Vec_IntFree( vNodes ); if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkFromIvy(): Network check has failed.\n" ); return pNtk; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig ) { Vec_Int_t * vNodes, * vLatches; Abc_Ntk_t * pNtk; Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; Ivy_Obj_t * pNode, * pTemp; int i; // assert( Ivy_ManLatchNum(pMan) > 0 ); // perform strashing pNtk = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); // transfer the pointers to the basic nodes Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) ); Abc_NtkForEachPi( pNtkOld, pObj, i ) Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy ); // create latches of the new network vNodes = Ivy_ManDfsSeq( pMan, &vLatches ); Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i ) { pObjNew = Abc_NtkCreateLatch( pNtk ); pFaninNew0 = Abc_NtkCreateBi( pNtk ); pFaninNew1 = Abc_NtkCreateBo( pNtk ); Abc_ObjAddFanin( pObjNew, pFaninNew0 ); Abc_ObjAddFanin( pFaninNew1, pObjNew ); if ( fHaig || Ivy_ObjInit(pNode) == IVY_INIT_DC ) Abc_LatchSetInitDc( pObjNew ); else if ( Ivy_ObjInit(pNode) == IVY_INIT_1 ) Abc_LatchSetInit1( pObjNew ); else if ( Ivy_ObjInit(pNode) == IVY_INIT_0 ) Abc_LatchSetInit0( pObjNew ); else assert( 0 ); pNode->TravId = Abc_EdgeFromNode( pFaninNew1 ); } Abc_NtkAddDummyBoxNames( pNtk ); // rebuild the AIG Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i ) { // add the first fanin pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode ); if ( Ivy_ObjIsBuf(pNode) ) { pNode->TravId = Abc_EdgeFromNode( pFaninNew0 ); continue; } // add the second fanin pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode ); // create the new node if ( Ivy_ObjIsExor(pNode) ) pObjNew = Abc_AigXor( (Abc_Aig_t *)pNtk->pManFunc, pFaninNew0, pFaninNew1 ); else pObjNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pFaninNew0, pFaninNew1 ); pNode->TravId = Abc_EdgeFromNode( pObjNew ); // process the choice nodes if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) { pFaninNew = Abc_EdgeToNode( pNtk, pNode->TravId ); // pFaninNew->fPhase = 0; assert( !Ivy_IsComplement(pNode->pEquiv) ); for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) { pFaninNew1 = Abc_EdgeToNode( pNtk, pTemp->TravId ); // pFaninNew1->fPhase = Ivy_IsComplement( pTemp->pEquiv ); pFaninNew->pData = pFaninNew1; pFaninNew = pFaninNew1; } pFaninNew->pData = NULL; // printf( "Writing choice node %d.\n", pNode->Id ); } } // connect the PO nodes Abc_NtkForEachPo( pNtkOld, pObj, i ) { pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) ); Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); } // connect the latches Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i ) { pFaninNew = Abc_ObjFanin0Ivy( pNtk, pNode ); Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(pNtk, i)), pFaninNew ); } Vec_IntFree( vLatches ); Vec_IntFree( vNodes ); if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" ); return pNtk; } /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld ) { Ivy_Man_t * pMan; Abc_Obj_t * pObj; Ivy_Obj_t * pFanin; int i; // create the manager assert( Abc_NtkHasSop(pNtkOld) || Abc_NtkIsStrash(pNtkOld) ); pMan = Ivy_ManStart(); // create the PIs if ( Abc_NtkIsStrash(pNtkOld) ) Abc_AigConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Ivy_ManConst1(pMan); Abc_NtkForEachCi( pNtkOld, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Ivy_ObjCreatePi(pMan); // perform the conversion of the internal nodes Abc_NtkStrashPerformAig( pNtkOld, pMan ); // create the POs Abc_NtkForEachCo( pNtkOld, pObj, i ) { pFanin = (Ivy_Obj_t *)Abc_ObjFanin0(pObj)->pCopy; pFanin = Ivy_NotCond( pFanin, Abc_ObjFaninC0(pObj) ); Ivy_ObjCreatePo( pMan, pFanin ); } Ivy_ManCleanup( pMan ); return pMan; } /**Function************************************************************* Synopsis [Prepares the network for strashing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) { // ProgressBar * pProgress; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int i; vNodes = Abc_NtkDfs( pNtk, 0 ); // pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { // Extra_ProgressBarUpdate( pProgress, i, NULL ); pNode->pCopy = (Abc_Obj_t *)Abc_NodeStrashAig( pMan, pNode ); } // Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Strashes one logic node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode ) { int fUseFactor = 1; char * pSop; Ivy_Obj_t * pFanin0, * pFanin1; assert( Abc_ObjIsNode(pNode) ); // consider the case when the graph is an AIG if ( Abc_NtkIsStrash(pNode->pNtk) ) { if ( Abc_AigNodeIsConst(pNode) ) return Ivy_ManConst1(pMan); pFanin0 = (Ivy_Obj_t *)Abc_ObjFanin0(pNode)->pCopy; pFanin0 = Ivy_NotCond( pFanin0, Abc_ObjFaninC0(pNode) ); pFanin1 = (Ivy_Obj_t *)Abc_ObjFanin1(pNode)->pCopy; pFanin1 = Ivy_NotCond( pFanin1, Abc_ObjFaninC1(pNode) ); return Ivy_And( pMan, pFanin0, pFanin1 ); } // get the SOP of the node if ( Abc_NtkHasMapping(pNode->pNtk) ) pSop = Mio_GateReadSop((Mio_Gate_t *)pNode->pData); else pSop = (char *)pNode->pData; // consider the constant node if ( Abc_NodeIsConst(pNode) ) return Ivy_NotCond( Ivy_ManConst1(pMan), Abc_SopIsConst0(pSop) ); // decide when to use factoring if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 && !Abc_SopIsExorType(pSop) ) return Abc_NodeStrashAigFactorAig( pMan, pNode, pSop ); return Abc_NodeStrashAigSopAig( pMan, pNode, pSop ); } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ) { Abc_Obj_t * pFanin; Ivy_Obj_t * pAnd, * pSum; char * pCube; int i, nFanins; int fExor = Abc_SopIsExorType(pSop); // get the number of node's fanins nFanins = Abc_ObjFaninNum( pNode ); assert( nFanins == Abc_SopGetVarNum(pSop) ); // go through the cubes of the node's SOP pSum = Ivy_Not( Ivy_ManConst1(pMan) ); Abc_SopForEachCube( pSop, nFanins, pCube ) { // create the AND of literals pAnd = Ivy_ManConst1(pMan); Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net { if ( pCube[i] == '1' ) pAnd = Ivy_And( pMan, pAnd, (Ivy_Obj_t *)pFanin->pCopy ); else if ( pCube[i] == '0' ) pAnd = Ivy_And( pMan, pAnd, Ivy_Not((Ivy_Obj_t *)pFanin->pCopy) ); } // add to the sum of cubes if ( fExor ) pSum = Ivy_Exor( pMan, pSum, pAnd ); else pSum = Ivy_Or( pMan, pSum, pAnd ); } // decide whether to complement the result if ( Abc_SopIsComplement(pSop) ) pSum = Ivy_Not(pSum); return pSum; } /**Function************************************************************* Synopsis [Strashed n-input XOR function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ) { Abc_Obj_t * pFanin; Ivy_Obj_t * pSum; int i, nFanins; // get the number of node's fanins nFanins = Abc_ObjFaninNum( pNode ); assert( nFanins == Abc_SopGetVarNum(pSop) ); // go through the cubes of the node's SOP pSum = Ivy_Not( Ivy_ManConst1(pMan) ); for ( i = 0; i < nFanins; i++ ) { pFanin = Abc_ObjFanin( pNode, i ); pSum = Ivy_Exor( pMan, pSum, (Ivy_Obj_t *)pFanin->pCopy ); } if ( Abc_SopIsComplement(pSop) ) pSum = Ivy_Not(pSum); return pSum; } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pRoot, char * pSop ) { Dec_Graph_t * pFForm; Dec_Node_t * pNode; Ivy_Obj_t * pAnd; int i; // extern Ivy_Obj_t * Dec_GraphToNetworkAig( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ); // assert( 0 ); // perform factoring pFForm = Dec_Factor( pSop ); // collect the fanins Dec_GraphForEachLeaf( pFForm, pNode, i ) pNode->pFunc = Abc_ObjFanin(pRoot,i)->pCopy; // perform strashing // pAnd = Dec_GraphToNetworkAig( pMan, pFForm ); pAnd = Dec_GraphToNetworkIvy( pMan, pFForm ); // pAnd = NULL; Dec_GraphFree( pFForm ); return pAnd; } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ) { Abc_Obj_t * pLatch; Vec_Int_t * vArray; int i; vArray = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( fUseDcs || Abc_LatchIsInitDc(pLatch) ) Vec_IntPush( vArray, IVY_INIT_DC ); else if ( Abc_LatchIsInit1(pLatch) ) Vec_IntPush( vArray, IVY_INIT_1 ); else if ( Abc_LatchIsInit0(pLatch) ) Vec_IntPush( vArray, IVY_INIT_0 ); else assert( 0 ); } return vArray; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcLog.c000066400000000000000000000163071300674244400232060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcLog.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Log file printing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcLog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* Log file format (Jiang, Mon, 28 Sep 2009; updated by Alan in Jan 2011) <0-based_output_num> <0-based_frame> : default is empty line. : default is empty line is one of the following: "snl_SAT", "snl_UNSAT", "snl_UNK", "snl_ABORT". is the number of timeframes exhaustively explored without counter-examples <0-based_output_num> only need to be given if the problem is SAT. <0-based_frame> only need to be given if the problem is SAT and <0-based_frame> is different from . : initial state : input vector and are strings of 0/1/- ( - means don't care). The length is equivalent to #input*#. */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pCex, int Status, int nFrames, char * pCommand ) { FILE * pFile; int i; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Cannot open log file for writing \"%s\".\n" , pFileName ); return; } // write if ( Status == 1 ) fprintf( pFile, "snl_UNSAT" ); else if ( Status == 0 ) fprintf( pFile, "snl_SAT" ); else if ( Status == -1 ) fprintf( pFile, "snl_UNK" ); else printf( "Abc_NtkWriteLogFile(): Cannot recognize solving status.\n" ); fprintf( pFile, " " ); // write fprintf( pFile, "%d", nFrames ); fprintf( pFile, " " ); // write fprintf( pFile, "%s", pCommand ? pCommand : "unknown" ); if ( pCex && Status == 0 ) fprintf( pFile, " %d", pCex->iPo ); // write if ( pCex && pCex->iFrame != nFrames ) fprintf( pFile, " %d", pCex->iFrame ); fprintf( pFile, "\n" ); // write if ( pCex == NULL ) fprintf( pFile, "NULL" ); else { for ( i = 0; i < pCex->nRegs; i++ ) fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData,i) ); } fprintf( pFile, "\n" ); // write if ( pCex == NULL ) fprintf( pFile, "NULL" ); else { assert( pCex->nBits - pCex->nRegs == pCex->nPis * (pCex->iFrame + 1) ); for ( i = pCex->nRegs; i < pCex->nBits; i++ ) fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData,i) ); } fprintf( pFile, "\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkReadLogFile( char * pFileName, Abc_Cex_t ** ppCex, int * pnFrames ) { FILE * pFile; Abc_Cex_t * pCex; Vec_Int_t * vNums; char Buffer[1000], * pToken, * RetValue; int c, nRegs = -1, nFrames = -1, iPo = -1, Status = -1, nFrames2 = -1; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open log file for reading \"%s\".\n" , pFileName ); return -1; } RetValue = fgets( Buffer, 1000, pFile ); if ( !strncmp( Buffer, "snl_UNSAT", strlen("snl_UNSAT") ) ) { Status = 1; nFrames = atoi( Buffer + strlen("snl_UNSAT") ); } else if ( !strncmp( Buffer, "snl_SAT", strlen("snl_SAT") ) ) { Status = 0; // nFrames = atoi( Buffer + strlen("snl_SAT") ); pToken = strtok( Buffer + strlen("snl_SAT"), " \t\n" ); nFrames = atoi( pToken ); pToken = strtok( NULL, " \t\n" ); pToken = strtok( NULL, " \t\n" ); if ( pToken != NULL ) { iPo = atoi( pToken ); pToken = strtok( NULL, " \t\n" ); if ( pToken ) nFrames2 = atoi( pToken ); } // else // printf( "Warning! The current status is SAT but the current CEX is not given.\n" ); } else if ( !strncmp( Buffer, "snl_UNK", strlen("snl_UNK") ) ) { Status = -1; nFrames = atoi( Buffer + strlen("snl_UNK") ); } else { printf( "Unrecognized status.\n" ); } // found regs till the new line vNums = Vec_IntAlloc( 100 ); while ( (c = fgetc(pFile)) != EOF ) { if ( c == '\n' ) break; if ( c == '0' || c == '1' ) Vec_IntPush( vNums, c - '0' ); } nRegs = Vec_IntSize(vNums); // skip till the new line while ( (c = fgetc(pFile)) != EOF ) { if ( c == '0' || c == '1' ) Vec_IntPush( vNums, c - '0' ); } fclose( pFile ); if ( Vec_IntSize(vNums) ) { int iFrameCex = (nFrames2 == -1) ? nFrames : nFrames2; if ( nRegs < 0 ) { printf( "Cannot read register number.\n" ); Vec_IntFree( vNums ); return -1; } if ( Vec_IntSize(vNums)-nRegs == 0 ) { printf( "Cannot read counter example.\n" ); Vec_IntFree( vNums ); return -1; } if ( (Vec_IntSize(vNums)-nRegs) % (iFrameCex + 1) != 0 ) { printf( "Incorrect number of bits.\n" ); Vec_IntFree( vNums ); return -1; } pCex = Abc_CexAlloc( nRegs, (Vec_IntSize(vNums)-nRegs)/(iFrameCex + 1), iFrameCex + 1 ); pCex->iPo = iPo; pCex->iFrame = iFrameCex; assert( Vec_IntSize(vNums) == pCex->nBits ); for ( c = 0; c < pCex->nBits; c++ ) if ( Vec_IntEntry(vNums, c) ) Abc_InfoSetBit( pCex->pData, c ); Vec_IntFree( vNums ); if ( ppCex ) *ppCex = pCex; else ABC_FREE( pCex ); } else Vec_IntFree( vNums ); if ( pnFrames ) *pnFrames = nFrames; return Status; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcLut.c000066400000000000000000000633661300674244400232400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcLut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Superchoicing for K-LUTs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/cut/cut.h" ABC_NAMESPACE_IMPL_START #define LARGE_LEVEL 1000000 //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define SCL_LUT_MAX 6 // the maximum LUT size #define SCL_VARS_MAX 15 // the maximum number of variables #define SCL_NODE_MAX 1000 // the maximum number of nodes typedef struct Abc_ManScl_t_ Abc_ManScl_t; struct Abc_ManScl_t_ { // paramers int nLutSize; // the LUT size int nCutSizeMax; // the max number of leaves of the cone int nNodesMax; // the max number of divisors in the cone int nWords; // the number of machine words in sim info // structural representation of the cone Vec_Ptr_t * vLeaves; // leaves of the cut Vec_Ptr_t * vVolume; // volume of the cut int pBSet[SCL_VARS_MAX]; // bound set // functional representation of the cone unsigned * uTruth; // truth table of the cone // representation of truth tables unsigned ** uVars; // elementary truth tables unsigned ** uSims; // truth tables of the nodes unsigned ** uCofs; // truth tables of the cofactors }; static Vec_Ptr_t * s_pLeaves = NULL; static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ); static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ); static void Abc_ManSclStop( Abc_ManScl_t * p ); static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ); static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj ); static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs superchoicing for K-LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ) { ProgressBar * pProgress; Abc_ManCut_t * pManCut; Abc_ManScl_t * pManScl; Cut_Man_t * pManCuts; Abc_Obj_t * pObj, * pFanin, * pObjTop; int i, LevelMax, nNodes; int nNodesTried, nNodesDec, nNodesExist, nNodesUsed; assert( Abc_NtkIsSopLogic(pNtk) ); if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX ) { printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX ); return 0; } if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX ) { printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX ); return 0; } assert( nLutSize <= SCL_LUT_MAX ); assert( nCutSizeMax <= SCL_VARS_MAX ); nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0; // set the delays of the CIs Abc_NtkForEachCi( pNtk, pObj, i ) pObj->Level = 0; //Abc_NtkLevel( pNtk ); // start the managers pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 ); pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize ); pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 ); s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut ); pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut ); // process each internal node (assuming topological order of nodes!!!) nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachObj( pNtk, pObj, i ) { // if ( i != nNodes-1 ) // continue; Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( i >= nNodes ) break; if ( Abc_ObjFaninNum(pObj) != 2 ) continue; nNodesTried++; // map this node using regular cuts // pObj->Level = 0; Abc_NodeLutMap( pManCuts, pObj ); // compute the cut pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 ); if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize ) continue; // get the volume of the cut if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX ) continue; nNodesDec++; // decompose the cut pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj ); if ( pObjTop == NULL ) continue; nNodesExist++; // if there is no delay improvement, skip; otherwise, update level if ( pObjTop->Level >= pObj->Level ) { Abc_NtkDeleteObj_rec( pObjTop, 1 ); continue; } pObj->Level = pObjTop->Level; nNodesUsed++; } Extra_ProgressBarStop( pProgress ); // delete the managers Abc_ManSclStop( pManScl ); Abc_NtkManCutStop( pManCut ); Cut_ManStop( pManCuts ); // get the largest arrival time LevelMax = 0; Abc_NtkForEachCo( pNtk, pObj, i ) { pFanin = Abc_ObjFanin0( pObj ); // skip inv/buf if ( Abc_ObjFaninNum(pFanin) == 1 ) pFanin = Abc_ObjFanin0( pFanin ); // get the new level LevelMax = Abc_MaxInt( LevelMax, (int)pFanin->Level ); } if ( fVerbose ) printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n", nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize ); // if ( fVerbose ) // printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize ); // clean the data field Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pNext = NULL; // check if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Performs LUT mapping of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ) { Cut_Cut_t * pCut; Abc_Obj_t * pFanin; int i, DelayMax; pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 ); assert( pCut != NULL ); assert( pObj->Level == 0 ); // go through the cuts pObj->Level = LARGE_LEVEL; for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { DelayMax = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] ); // assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological if ( DelayMax < (int)pFanin->Level ) DelayMax = pFanin->Level; } if ( (int)pObj->Level > DelayMax ) pObj->Level = DelayMax; } assert( pObj->Level < LARGE_LEVEL ); pObj->Level++; // printf( "%d(%d) ", pObj->Id, pObj->Level ); } /**Function************************************************************* Synopsis [Starts the cut manager for rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ) { static Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pManCut; Abc_Obj_t * pObj; int i; // start the cut manager memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = nLutSize; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 500; // the max number of cuts kept at a node pParams->fTruth = 0; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fSeq = 0; // compute sequential cuts pParams->fDrop = 0; // drop cuts on the fly pParams->fVerbose = 0; // the verbosiness flag pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); pManCut = Cut_ManStart( pParams ); if ( pParams->fDrop ) Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); // set cuts for PIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( pManCut, pObj->Id ); return pManCut; } /**Function************************************************************* Synopsis [Starts the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ) { Abc_ManScl_t * p; int i, k; assert( sizeof(unsigned) == 4 ); p = ABC_ALLOC( Abc_ManScl_t, 1 ); memset( p, 0, sizeof(Abc_ManScl_t) ); p->nLutSize = nLutSize; p->nCutSizeMax = nCutSizeMax; p->nNodesMax = nNodesMax; p->nWords = Extra_TruthWordNum(nCutSizeMax); // allocate simulation info p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 ); p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 ); p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 ); memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 ); // assign elementary truth tables for ( k = 0; k < p->nCutSizeMax; k++ ) for ( i = 0; i < p->nWords * 32; i++ ) if ( i & (1 << k) ) p->uVars[k][i>>5] |= (1 << (i&31)); // other data structures // p->vBound = Vec_IntAlloc( nCutSizeMax ); return p; } /**Function************************************************************* Synopsis [Stops the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManSclStop( Abc_ManScl_t * p ) { // Vec_IntFree( p->vBound ); ABC_FREE( p->uVars ); ABC_FREE( p->uSims ); ABC_FREE( p->uCofs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl ) { Abc_Obj_t * pObj; unsigned * puData0, * puData1, * puData = NULL; char * pSop; int i, k; // set elementary truth tables Vec_PtrForEachEntry( Abc_Obj_t *, pManScl->vLeaves, pObj, i ) pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i]; // compute truth tables for internal nodes Vec_PtrForEachEntry( Abc_Obj_t *, pManScl->vVolume, pObj, i ) { // set storage for the node's simulation info pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i]; // get pointer to the simulation info puData = (unsigned *)pObj->pNext; puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext; puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext; // simulate pSop = (char *)pObj->pData; if ( pSop[0] == '0' && pSop[1] == '0' ) for ( k = 0; k < pManScl->nWords; k++ ) puData[k] = ~puData0[k] & ~puData1[k]; else if ( pSop[0] == '0' ) for ( k = 0; k < pManScl->nWords; k++ ) puData[k] = ~puData0[k] & puData1[k]; else if ( pSop[1] == '0' ) for ( k = 0; k < pManScl->nWords; k++ ) puData[k] = puData0[k] & ~puData1[k]; else for ( k = 0; k < pManScl->nWords; k++ ) puData[k] = puData0[k] & puData1[k]; } return puData; } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume ) { if ( pObj->fMarkC ) return; pObj->fMarkC = 1; assert( Abc_ObjFaninNum(pObj) == 2 ); Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume ); Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume ); Vec_PtrPush( vVolume, pObj ); } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) { Abc_Obj_t * pObj; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkC = 1; Vec_PtrClear( vVolume ); Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkC = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vVolume, pObj, i ) pObj->fMarkC = 0; } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) { if ( pObj->fMarkB ) { Vec_PtrPush( vLeaves, pObj ); pObj->fMarkB = 0; } if ( pObj->fMarkC ) return; pObj->fMarkC = 1; assert( Abc_ObjFaninNum(pObj) == 2 ); Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume ); Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume ); Vec_PtrPush( vVolume, pObj ); } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [Orders the leaves topologically.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) { Abc_Obj_t * pObj; int i, nLeaves; nLeaves = Vec_PtrSize(vLeaves); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkB = pObj->fMarkC = 1; Vec_PtrClear( vVolume ); Vec_PtrClear( vLeaves ); Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume ); assert( Vec_PtrSize(vLeaves) == nLeaves ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkC = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vVolume, pObj, i ) pObj->fMarkC = 0; } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars ) { int i; for ( i = nVars - 1; i >= 0; i-- ) if ( uPhase & (1 << i) ) Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) ); } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeGetLevel( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i, Level; Level = 0; Abc_ObjForEachFanin( pObj, pFanin, i ) Level = Abc_MaxInt( Level, (int)pFanin->Level ); return Level + 1; } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin, * pObjNew; int i, nVars, uSupport, nSuppVars; // collect the cone using DFS (excluding leaves) Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume ); assert( Vec_PtrEntryLast(p->vVolume) == pObj ); // compute the truth table p->uTruth = Abc_NodeSuperChoiceTruth( p ); // get the support of this truth table nVars = Vec_PtrSize(p->vLeaves); uSupport = Extra_TruthSupport(p->uTruth, nVars); nSuppVars = Extra_WordCountOnes(uSupport); assert( nSuppVars <= nVars ); if ( nSuppVars == 0 ) { pObj->Level = 0; return NULL; } if ( nSuppVars == 1 ) { // find the variable for ( i = 0; i < nVars; i++ ) if ( uSupport & (1 << i) ) break; assert( i < nVars ); pFanin = (Abc_Obj_t *)Vec_PtrEntry( p->vLeaves, i ); pObj->Level = pFanin->Level; return NULL; } // support-minimize the truth table if ( nSuppVars != nVars ) { Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport ); Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars ); } // return NULL; // decompose the truth table recursively while ( Vec_PtrSize(p->vLeaves) > p->nLutSize ) if ( !Abc_NodeDecomposeStep( p ) ) { Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pFanin, i ) if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 ) Abc_NtkDeleteObj_rec( pFanin, 1 ); return NULL; } // create the topmost node pObjNew = Abc_NtkCreateNode( pObj->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pFanin, i ) Abc_ObjAddFanin( pObjNew, pFanin ); // create the function pObjNew->pData = Abc_SopCreateFromTruth( (Mem_Flex_t *)pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP pObjNew->Level = Abc_NodeGetLevel( pObjNew ); return pObjNew; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in increasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 ) { Abc_Obj_t * pNode1, * pNode2; pNode1 = (Abc_Obj_t *)Vec_PtrEntry(s_pLeaves, *pp1); pNode2 = (Abc_Obj_t *)Vec_PtrEntry(s_pLeaves, *pp2); if ( pNode1->Level < pNode2->Level ) return -1; if ( pNode1->Level > pNode2->Level ) return 1; return 0; } /**Function************************************************************* Synopsis [Selects the earliest arriving nodes from the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize ) { Abc_Obj_t * pTemp[SCL_VARS_MAX]; int i, k, kBest, LevelMin; assert( nLutSize < nVars ); assert( nVars <= SCL_VARS_MAX ); // copy nodes into the internal storage // printf( "(" ); for ( i = 0; i < nVars; i++ ) { pTemp[i] = pLeaves[i]; // printf( " %d", pLeaves[i]->Level ); } // printf( " )\n" ); // choose one node at a time for ( i = 0; i < nLutSize; i++ ) { kBest = -1; LevelMin = LARGE_LEVEL; for ( k = 0; k < nVars; k++ ) if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level ) { LevelMin = pTemp[k]->Level; kBest = k; } pBSet[i] = kBest; pTemp[kBest] = NULL; } } /**Function************************************************************* Synopsis [Performs superchoicing for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeDecomposeStep( Abc_ManScl_t * p ) { static char pCofClasses[1<vLeaves, 0))->pNtk; // find the earliest nodes nVars = Vec_PtrSize(p->vLeaves); assert( nVars > p->nLutSize ); /* for ( v = 0; v < nVars; v++ ) p->pBSet[v] = v; qsort( (void *)p->pBSet, nVars, sizeof(int), (int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc ); */ Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize ); assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <= ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level ); // cofactor w.r.t. the selected variables Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars ); c = 2; for ( v = 0; v < p->nLutSize; v++ ) for ( k = 0; k < (1<uCofs[c], p->uCofs[c/2], nVars ); Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars ); Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] ); Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] ); c += 2; } assert( c == (2 << p->nLutSize) ); // count unique cofactors nClasses = 0; nCofs = (1 << p->nLutSize); for ( i = 0; i < nCofs; i++ ) { pTruthCof = p->uCofs[ nCofs + i ]; for ( k = 0; k < nClasses; k++ ) { pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) ) { pCofClasses[k][(int)nCofClasses[k]++ ] = i; break; } } if ( k != nClasses ) continue; // not found pCofClasses[nClasses][0] = i; nCofClasses[nClasses] = 1; nClasses++; if ( nClasses > nCofs/2 ) return 0; } // the number of cofactors is acceptable nVarsNew = Abc_Base2Log( nClasses ); assert( nVarsNew < p->nLutSize ); // create the remainder truth table // for each class of cofactors, multiply cofactor truth table by its code Extra_TruthClear( p->uTruth, nVars ); for ( k = 0; k < nClasses; k++ ) { pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; for ( v = 0; v < nVarsNew; v++ ) if ( k & (1 << v) ) Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); else Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars ); } // create nodes pTruth = p->uCofs[0]; for ( v = 0; v < nVarsNew; v++ ) { Extra_TruthClear( pTruth, p->nLutSize ); for ( k = 0; k < nClasses; k++ ) if ( k & (1 << v) ) for ( i = 0; i < nCofClasses[k]; i++ ) { pTruthCof = p->uCofs[1]; Extra_TruthFill( pTruthCof, p->nLutSize ); for ( w = 0; w < p->nLutSize; w++ ) if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) ) Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); else Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize ); } // implement the node pObjNew = Abc_NtkCreateNode( pNtk ); for ( i = 0; i < p->nLutSize; i++ ) { pFanin = (Abc_Obj_t *)Vec_PtrEntry( p->vLeaves, p->pBSet[i] ); Abc_ObjAddFanin( pObjNew, pFanin ); } // create the function pObjNew->pData = Abc_SopCreateFromTruth( (Mem_Flex_t *)pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP pObjNew->Level = Abc_NodeGetLevel( pObjNew ); pNodesNew[v] = pObjNew; } // put the new nodes back into the list for ( v = 0; v < nVarsNew; v++ ) Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] ); // compute the variables that should be removed uPhase = 0; for ( v = nVarsNew; v < p->nLutSize; v++ ) uPhase |= (1 << p->pBSet[v]); // remove entries from the array Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars ); // update truth table Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase ); Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcLutmin.c000066400000000000000000000647021300674244400237370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcLutmin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Minimization of the number of LUTs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcLutmin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START /* Implememented here is the algorithm for minimal-LUT decomposition described in the paper: T. Sasao et al. "On the number of LUTs to implement logic functions", To appear in Proc. IWLS'09. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Check if a LUT can absort a fanin.] Description [The fanins are (c, d0, d1).] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjCheckAbsorb( Abc_Obj_t * pObj, Abc_Obj_t * pPivot, int nLutSize, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pFanin; int i; assert( Abc_ObjIsNode(pObj) && Abc_ObjIsNode(pPivot) ); // add fanins of the node Vec_PtrClear( vFanins ); Abc_ObjForEachFanin( pObj, pFanin, i ) if ( pFanin != pPivot ) Vec_PtrPush( vFanins, pFanin ); // add fanins of the fanin Abc_ObjForEachFanin( pPivot, pFanin, i ) { Vec_PtrPushUnique( vFanins, pFanin ); if ( Vec_PtrSize(vFanins) > nLutSize ) return 0; } return 1; } /**Function************************************************************* Synopsis [Check how many times a LUT can absorb a fanin.] Description [The fanins are (c, d0, d1).] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCheckAbsorb( Abc_Ntk_t * pNtk, int nLutSize ) { Vec_Int_t * vCounts; Vec_Ptr_t * vFanins; Abc_Obj_t * pObj, * pFanin; int i, k, Counter = 0, Counter2 = 0; abctime clk = Abc_Clock(); vCounts = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); vFanins = Vec_PtrAlloc( 100 ); Abc_NtkForEachNode( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( Abc_ObjIsNode(pFanin) && Abc_ObjCheckAbsorb( pObj, pFanin, nLutSize, vFanins ) ) { Vec_IntAddToEntry( vCounts, Abc_ObjId(pFanin), 1 ); Counter++; } Vec_PtrFree( vFanins ); Abc_NtkForEachNode( pNtk, pObj, i ) if ( Vec_IntEntry(vCounts, Abc_ObjId(pObj)) == Abc_ObjFanoutNum(pObj) ) { // printf( "%d ", Abc_ObjId(pObj) ); Counter2++; } printf( "Absorted = %6d. (%6.2f %%) Fully = %6d. (%6.2f %%) ", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk), Counter2, 100.0 * Counter2 / Abc_NtkNodeNum(pNtk) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Implements 2:1 MUX using one 3-LUT.] Description [The fanins are (c, d0, d1).] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkBddMux21( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) { DdManager * dd = (DdManager *)pNtkNew->pManFunc; Abc_Obj_t * pNode; DdNode * bSpin, * bCof0, * bCof1; pNode = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNode, pFanins[0] ); Abc_ObjAddFanin( pNode, pFanins[1] ); Abc_ObjAddFanin( pNode, pFanins[2] ); bSpin = Cudd_bddIthVar(dd, 0); bCof0 = Cudd_bddIthVar(dd, 1); bCof1 = Cudd_bddIthVar(dd, 2); pNode->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNode->pData ); return pNode; } /**Function************************************************************* Synopsis [Implements 4:1 MUX using one 6-LUT.] Description [The fanins are (c0, c1, d00, d01, d10, d11).] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkBddMux411( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) { DdManager * dd = (DdManager *)pNtkNew->pManFunc; Abc_Obj_t * pNode; DdNode * bSpin, * bCof0, * bCof1; pNode = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNode, pFanins[0] ); Abc_ObjAddFanin( pNode, pFanins[1] ); Abc_ObjAddFanin( pNode, pFanins[2] ); Abc_ObjAddFanin( pNode, pFanins[3] ); Abc_ObjAddFanin( pNode, pFanins[4] ); Abc_ObjAddFanin( pNode, pFanins[5] ); bSpin = Cudd_bddIthVar(dd, 1); bCof0 = Cudd_bddIte( dd, bSpin, Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof0 ); bCof1 = Cudd_bddIte( dd, bSpin, Cudd_bddIthVar(dd, 5), Cudd_bddIthVar(dd, 4) ); Cudd_Ref( bCof1 ); bSpin = Cudd_bddIthVar(dd, 0); pNode->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNode->pData ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); return pNode; } /**Function************************************************************* Synopsis [Implementes 4:1 MUX using two 4-LUTs.] Description [The fanins are (c0, c1, d00, d01, d10, d11).] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkBddMux412( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) { DdManager * dd = (DdManager *)pNtkNew->pManFunc; Abc_Obj_t * pNodeBot, * pNodeTop; DdNode * bSpin, * bCof0, * bCof1; // bottom node pNodeBot = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNodeBot, pFanins[0] ); Abc_ObjAddFanin( pNodeBot, pFanins[1] ); Abc_ObjAddFanin( pNodeBot, pFanins[2] ); Abc_ObjAddFanin( pNodeBot, pFanins[3] ); bSpin = Cudd_bddIthVar(dd, 0); bCof0 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof0 ); bCof1 = Cudd_bddIthVar(dd, 1); pNodeBot->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNodeBot->pData ); Cudd_RecursiveDeref( dd, bCof0 ); // top node pNodeTop = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNodeTop, pFanins[0] ); Abc_ObjAddFanin( pNodeTop, pNodeBot ); Abc_ObjAddFanin( pNodeTop, pFanins[4] ); Abc_ObjAddFanin( pNodeTop, pFanins[5] ); bSpin = Cudd_bddIthVar(dd, 0); bCof0 = Cudd_bddIthVar(dd, 1); bCof1 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof1 ); pNodeTop->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNodeTop->pData ); Cudd_RecursiveDeref( dd, bCof1 ); return pNodeTop; } /**Function************************************************************* Synopsis [Implementes 4:1 MUX using two 4-LUTs.] Description [The fanins are (c0, c1, d00, d01, d10, d11).] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkBddMux412a( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) { DdManager * dd = (DdManager *)pNtkNew->pManFunc; Abc_Obj_t * pNodeBot, * pNodeTop; DdNode * bSpin, * bCof0, * bCof1; // bottom node pNodeBot = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNodeBot, pFanins[1] ); Abc_ObjAddFanin( pNodeBot, pFanins[2] ); Abc_ObjAddFanin( pNodeBot, pFanins[3] ); bSpin = Cudd_bddIthVar(dd, 0); bCof0 = Cudd_bddIthVar(dd, 1); bCof1 = Cudd_bddIthVar(dd, 2); pNodeBot->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNodeBot->pData ); // top node pNodeTop = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNodeTop, pFanins[0] ); Abc_ObjAddFanin( pNodeTop, pFanins[1] ); Abc_ObjAddFanin( pNodeTop, pNodeBot ); Abc_ObjAddFanin( pNodeTop, pFanins[4] ); Abc_ObjAddFanin( pNodeTop, pFanins[5] ); bSpin = Cudd_bddIthVar(dd, 0); bCof0 = Cudd_bddIthVar(dd, 2); bCof1 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 4), Cudd_bddIthVar(dd, 3) ); Cudd_Ref( bCof1 ); pNodeTop->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNodeTop->pData ); Cudd_RecursiveDeref( dd, bCof1 ); return pNodeTop; } /**Function************************************************************* Synopsis [Implements 4:1 MUX using three 2:1 MUXes.] Description [The fanins are (c0, c1, d00, d01, d10, d11).] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkBddMux413( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] ) { Abc_Obj_t * pNodesBot[3], * pNodesTop[3]; // left bottom pNodesBot[0] = pFanins[1]; pNodesBot[1] = pFanins[2]; pNodesBot[2] = pFanins[3]; pNodesTop[1] = Abc_NtkBddMux21( pNtkNew, pNodesBot ); // right bottom pNodesBot[0] = pFanins[1]; pNodesBot[1] = pFanins[4]; pNodesBot[2] = pFanins[5]; pNodesTop[2] = Abc_NtkBddMux21( pNtkNew, pNodesBot ); // top node pNodesTop[0] = pFanins[0]; return Abc_NtkBddMux21( pNtkNew, pNodesTop ); } /**Function************************************************************* Synopsis [Finds unique cofactors of the function on the given level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkBddCofactors_rec( DdManager * dd, DdNode * bNode, int iCof, int iLevel, int nLevels ) { DdNode * bNode0, * bNode1; if ( Cudd_IsConstant(bNode) || iLevel == nLevels ) return bNode; if ( Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bNode) ) > iLevel ) { bNode0 = bNode; bNode1 = bNode; } else if ( Cudd_IsComplement(bNode) ) { bNode0 = Cudd_Not(cuddE(Cudd_Regular(bNode))); bNode1 = Cudd_Not(cuddT(Cudd_Regular(bNode))); } else { bNode0 = cuddE(bNode); bNode1 = cuddT(bNode); } if ( (iCof >> (nLevels-1-iLevel)) & 1 ) return Abc_NtkBddCofactors_rec( dd, bNode1, iCof, iLevel + 1, nLevels ); return Abc_NtkBddCofactors_rec( dd, bNode0, iCof, iLevel + 1, nLevels ); } /**Function************************************************************* Synopsis [Finds unique cofactors of the function on the given level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkBddCofactors( DdManager * dd, DdNode * bNode, int Level ) { Vec_Ptr_t * vCofs; int i, nCofs = (1< 0 && Level < 10 ); vCofs = Vec_PtrAlloc( 8 ); for ( i = 0; i < nCofs; i++ ) Vec_PtrPush( vCofs, Abc_NtkBddCofactors_rec( dd, bNode, i, 0, Level ) ); return vCofs; } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_PtrSortCompare( void ** pp1, void ** pp2 ) { if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Converts the node to MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateCofLut( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bCof, Abc_Obj_t * pNode, int Level ) { int fVerbose = 0; DdNode * bFuncNew; Abc_Obj_t * pNodeNew; int i; assert( Abc_ObjFaninNum(pNode) > Level ); // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); // add the fanins in the order, in which they appear in the reordered manager for ( i = Level; i < Abc_ObjFaninNum(pNode); i++ ) Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNode, i)->pCopy ); if ( fVerbose ) { Extra_bddPrint( dd, bCof ); printf( "\n" ); printf( "\n" ); } // transfer the function bFuncNew = Extra_bddMove( dd, bCof, -Level ); Cudd_Ref( bFuncNew ); if ( fVerbose ) { Extra_bddPrint( dd, bFuncNew ); printf( "\n" ); printf( "\n" ); } pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFuncNew ); Cudd_Ref( (DdNode *)pNodeNew->pData ); //Extra_bddPrint( pNtkNew->pManFunc, pNodeNew->pData ); //printf( "\n" ); //printf( "\n" ); Cudd_RecursiveDeref( dd, bFuncNew ); return pNodeNew; } /**Function************************************************************* Synopsis [Performs one step of Ashenhurst-Curtis decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkBddCurtis( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vCofs, Vec_Ptr_t * vUniq ) { DdManager * ddOld = (DdManager *)pNode->pNtk->pManFunc; DdManager * ddNew = (DdManager *)pNtkNew->pManFunc; DdNode * bCof, * bUniq, * bMint, * bTemp, * bFunc, * bBits[10], ** pbCodeVars; Abc_Obj_t * pNodeNew = NULL, * pNodeBS[10]; int nLutSize = Abc_Base2Log( Vec_PtrSize(vCofs) ); int nBits = Abc_Base2Log( Vec_PtrSize(vUniq) ); int b, c, u, i; assert( nBits + 2 <= nLutSize ); assert( nLutSize < Abc_ObjFaninNum(pNode) ); // start BDDs for the decompoosed blocks for ( b = 0; b < nBits; b++ ) bBits[b] = Cudd_ReadLogicZero(ddNew), Cudd_Ref( bBits[b] ); // add each bound set minterm to one of the blccks Vec_PtrForEachEntry( DdNode *, vCofs, bCof, c ) { Vec_PtrForEachEntry( DdNode *, vUniq, bUniq, u ) if ( bUniq == bCof ) break; assert( u < Vec_PtrSize(vUniq) ); for ( b = 0; b < nBits; b++ ) { if ( ((u >> b) & 1) == 0 ) continue; bMint = Extra_bddBitsToCube( ddNew, c, nLutSize, ddNew->vars, 1 ); Cudd_Ref( bMint ); bBits[b] = Cudd_bddOr( ddNew, bTemp = bBits[b], bMint ); Cudd_Ref( bBits[b] ); Cudd_RecursiveDeref( ddNew, bTemp ); Cudd_RecursiveDeref( ddNew, bMint ); } } // create bound set nodes for ( b = 0; b < nBits; b++ ) { pNodeBS[b] = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < nLutSize; i++ ) Abc_ObjAddFanin( pNodeBS[b], Abc_ObjFanin(pNode, i)->pCopy ); pNodeBS[b]->pData = bBits[b]; // takes ref } // create composition node pNodeNew = Abc_NtkCreateNode( pNtkNew ); // add free set variables first for ( i = nLutSize; i < Abc_ObjFaninNum(pNode); i++ ) Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNode, i)->pCopy ); // add code bit variables next for ( b = 0; b < nBits; b++ ) Abc_ObjAddFanin( pNodeNew, pNodeBS[b] ); // derive function of the composition node bFunc = Cudd_ReadLogicZero(ddNew); Cudd_Ref( bFunc ); pbCodeVars = ddNew->vars + Abc_ObjFaninNum(pNode) - nLutSize; Vec_PtrForEachEntry( DdNode *, vUniq, bUniq, u ) { bUniq = Extra_bddMove( ddOld, bUniq, -nLutSize ); Cudd_Ref( bUniq ); bUniq = Extra_TransferLevelByLevel( ddOld, ddNew, bTemp = bUniq ); Cudd_Ref( bUniq ); Cudd_RecursiveDeref( ddOld, bTemp ); bMint = Extra_bddBitsToCube( ddNew, u, nBits, pbCodeVars, 0 ); Cudd_Ref( bMint ); bMint = Cudd_bddAnd( ddNew, bTemp = bMint, bUniq ); Cudd_Ref( bMint ); Cudd_RecursiveDeref( ddNew, bTemp ); Cudd_RecursiveDeref( ddNew, bUniq ); bFunc = Cudd_bddOr( ddNew, bTemp = bFunc, bMint ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( ddNew, bTemp ); Cudd_RecursiveDeref( ddNew, bMint ); } pNodeNew->pData = bFunc; // takes ref return pNodeNew; } /**Function************************************************************* Synopsis [Tries to decompose using cofactoring into two LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkBddFindCofactor( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLutSize ) { Abc_Obj_t * pNodeBot, * pNodeTop; DdManager * ddOld = (DdManager *)pNode->pNtk->pManFunc; DdManager * ddNew = (DdManager *)pNtkNew->pManFunc; DdNode * bCof0 = NULL, * bCof1 = NULL, * bSupp, * bTemp, * bVar; DdNode * bCof0n, * bCof1n; int i, iCof, iFreeVar, fCof1Smaller = -1; assert( Abc_ObjFaninNum(pNode) == nLutSize + 1 ); for ( iCof = 0; iCof < Abc_ObjFaninNum(pNode); iCof++ ) { bVar = Cudd_bddIthVar( ddOld, iCof ); bCof0 = Cudd_Cofactor( ddOld, (DdNode *)pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); bCof1 = Cudd_Cofactor( ddOld, (DdNode *)pNode->pData, bVar ); Cudd_Ref( bCof1 ); if ( Cudd_SupportSize( ddOld, bCof0 ) <= nLutSize - 2 ) { fCof1Smaller = 0; break; } if ( Cudd_SupportSize( ddOld, bCof1 ) <= nLutSize - 2 ) { fCof1Smaller = 1; break; } Cudd_RecursiveDeref( ddOld, bCof0 ); Cudd_RecursiveDeref( ddOld, bCof1 ); } if ( iCof == Abc_ObjFaninNum(pNode) ) return NULL; // find unused variable bSupp = Cudd_Support( ddOld, fCof1Smaller? bCof1 : bCof0 ); Cudd_Ref( bSupp ); iFreeVar = -1; for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) { assert( i == Cudd_ReadPerm(ddOld, i) ); if ( i == iCof ) continue; for ( bTemp = bSupp; !Cudd_IsConstant(bTemp); bTemp = cuddT(bTemp) ) if ( i == (int)Cudd_NodeReadIndex(bTemp) ) break; if ( Cudd_IsConstant(bTemp) ) { iFreeVar = i; break; } } assert( iFreeVar != iCof && iFreeVar < Abc_ObjFaninNum(pNode) ); Cudd_RecursiveDeref( ddOld, bSupp ); // transfer the cofactors bCof0n = Extra_TransferLevelByLevel( ddOld, ddNew, bCof0 ); Cudd_Ref( bCof0n ); bCof1n = Extra_TransferLevelByLevel( ddOld, ddNew, bCof1 ); Cudd_Ref( bCof1n ); Cudd_RecursiveDeref( ddOld, bCof0 ); Cudd_RecursiveDeref( ddOld, bCof1 ); // create bottom node pNodeBot = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) Abc_ObjAddFanin( pNodeBot, Abc_ObjFanin(pNode, i)->pCopy ); pNodeBot->pData = fCof1Smaller? bCof0n : bCof1n; // create top node pNodeTop = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) if ( i == iFreeVar ) Abc_ObjAddFanin( pNodeTop, pNodeBot ); else Abc_ObjAddFanin( pNodeTop, Abc_ObjFanin(pNode, i)->pCopy ); // derive the new function pNodeTop->pData = Cudd_bddIte( ddNew, Cudd_bddIthVar(ddNew, iCof), fCof1Smaller? bCof1n : Cudd_bddIthVar(ddNew, iFreeVar), fCof1Smaller? Cudd_bddIthVar(ddNew, iFreeVar) : bCof0n ); Cudd_Ref( (DdNode *)pNodeTop->pData ); Cudd_RecursiveDeref( ddNew, fCof1Smaller? bCof1n : bCof0n ); return pNodeTop; } /**Function************************************************************* Synopsis [Decompose the function once.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkBddDecompose( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLutSize, int fVerbose ) { Vec_Ptr_t * vCofs, * vUniq; DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; DdNode * bCof; Abc_Obj_t * pNodeNew = NULL; Abc_Obj_t * pCofs[20]; int i; assert( Abc_ObjFaninNum(pNode) > nLutSize ); // try to decompose with two LUTs (the best case for Supp = LutSize + 1) if ( Abc_ObjFaninNum(pNode) == nLutSize + 1 ) { pNodeNew = Abc_NtkBddFindCofactor( pNtkNew, pNode, nLutSize ); if ( pNodeNew != NULL ) { if ( fVerbose ) printf( "Decomposing %d-input node %d using MUX.\n", Abc_ObjFaninNum(pNode), Abc_ObjId(pNode) ); return pNodeNew; } } // cofactor w.r.t. the bound set variables vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, nLutSize ); vUniq = Vec_PtrDup( vCofs ); Vec_PtrUniqify( vUniq, (int (*)())Vec_PtrSortCompare ); // only perform decomposition with it is support reduring with two less vars if( Vec_PtrSize(vUniq) > (1 << (nLutSize-2)) ) { Vec_PtrFree( vCofs ); vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, 2 ); if ( fVerbose ) printf( "Decomposing %d-input node %d using cofactoring with %d cofactors.\n", Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vCofs) ); // implement the cofactors pCofs[0] = Abc_ObjFanin(pNode, 0)->pCopy; pCofs[1] = Abc_ObjFanin(pNode, 1)->pCopy; Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i ) pCofs[2+i] = Abc_NtkCreateCofLut( pNtkNew, dd, bCof, pNode, 2 ); if ( nLutSize == 4 ) pNodeNew = Abc_NtkBddMux412( pNtkNew, pCofs ); else if ( nLutSize == 5 ) pNodeNew = Abc_NtkBddMux412a( pNtkNew, pCofs ); else if ( nLutSize == 6 ) pNodeNew = Abc_NtkBddMux411( pNtkNew, pCofs ); else assert( 0 ); } // alternative decompose using MUX-decomposition else { if ( fVerbose ) printf( "Decomposing %d-input node %d using Curtis with %d unique columns.\n", Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vUniq) ); pNodeNew = Abc_NtkBddCurtis( pNtkNew, pNode, vCofs, vUniq ); } Vec_PtrFree( vCofs ); Vec_PtrFree( vUniq ); return pNodeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkLutminConstruct( Abc_Ntk_t * pNtkClp, Abc_Ntk_t * pNtkDec, int nLutSize, int fVerbose ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin; int i, k; vNodes = Abc_NtkDfs( pNtkClp, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjFaninNum(pNode) <= nLutSize ) { pNode->pCopy = Abc_NtkDupObj( pNtkDec, pNode, 0 ); Abc_ObjForEachFanin( pNode, pFanin, k ) Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); } else pNode->pCopy = Abc_NtkBddDecompose( pNtkDec, pNode, nLutSize, fVerbose ); } Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkLutminInt( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ) { extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); Abc_Ntk_t * pNtkDec; // minimize BDDs // Abc_NtkBddReorder( pNtk, fVerbose ); Abc_NtkBddReorder( pNtk, 0 ); // decompose one output at a time pNtkDec = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); // make sure the new manager has enough inputs Cudd_bddIthVar( (DdManager *)pNtkDec->pManFunc, Abc_NtkGetFaninMax(pNtk) ); // put the results into the new network (save new CO drivers in old CO drivers) Abc_NtkLutminConstruct( pNtk, pNtkDec, nLutSize, fVerbose ); // finalize the new network Abc_NtkFinalize( pNtk, pNtkDec ); // make the network minimum base Abc_NtkMinimumBase( pNtkDec ); return pNtkDec; } /**Function************************************************************* Synopsis [Performs minimum-LUT decomposition of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) { extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtkNew, * pTemp; int i; if ( nLutSize < 4 ) { printf( "The LUT count (%d) should be at least 4.\n", nLutSize ); return NULL; } if ( nLutSize > 6 ) { printf( "The LUT count (%d) should not exceed 6.\n", nLutSize ); return NULL; } // create internal representation if ( Abc_NtkIsStrash(pNtkInit) ) pNtkNew = Abc_NtkDup( pNtkInit ); else pNtkNew = Abc_NtkStrash( pNtkInit, 0, 1, 0 ); // collapse the network pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0 ); Abc_NtkDelete( pTemp ); if ( pNtkNew == NULL ) return NULL; // convert it to BDD if ( !Abc_NtkIsBddLogic(pNtkNew) ) Abc_NtkToBdd( pNtkNew ); // iterate decomposition for ( i = 0; Abc_NtkGetFaninMax(pNtkNew) > nLutSize; i++ ) { if ( fVerbose ) printf( "*** Iteration %d:\n", i+1 ); if ( fVerbose ) printf( "Decomposing network with %d nodes and %d max fanin count for K = %d.\n", Abc_NtkNodeNum(pNtkNew), Abc_NtkGetFaninMax(pNtkNew), nLutSize ); pNtkNew = Abc_NtkLutminInt( pTemp = pNtkNew, nLutSize, fVerbose ); Abc_NtkDelete( pTemp ); } // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // merge functionally equivalent nodes Abc_NtkFraigSweep( pNtkNew, 1, 0, 0, 0 ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkLutmin: The network check has failed.\n" ); return 0; } return pNtkNew; } #else Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose ) { return NULL; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMap.c000066400000000000000000001076721300674244400232100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMap.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface with the SC mapping package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "map/mio/mio.h" #include "map/mapper/mapper.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ); static Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ); static Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); static Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); static Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ); static void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); static void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase ); static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Interface with the mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fVerbose ) { static int fUseMulti = 0; int fShowSwitching = 1; Abc_Ntk_t * pNtkNew; Map_Man_t * pMan; Vec_Int_t * vSwitching = NULL; float * pSwitching = NULL; abctime clk, clkTotal = Abc_Clock(); Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); assert( Abc_NtkIsStrash(pNtk) ); // derive library from SCL // if the library is created here, it will be deleted when pSuperLib is deleted in Map_SuperLibFree() if ( Abc_FrameReadLibScl() && Abc_SclHasDelayInfo( Abc_FrameReadLibScl() ) ) { if ( pLib && Mio_LibraryHasProfile(pLib) ) pLib = Abc_SclDeriveGenlib( Abc_FrameReadLibScl(), pLib, Slew, Gain, nGatesMin, fVerbose ); else pLib = Abc_SclDeriveGenlib( Abc_FrameReadLibScl(), NULL, Slew, Gain, nGatesMin, fVerbose ); if ( Abc_FrameReadLibGen() ) { Mio_LibraryTransferDelays( (Mio_Library_t *)Abc_FrameReadLibGen(), pLib ); Mio_LibraryTransferProfile( pLib, (Mio_Library_t *)Abc_FrameReadLibGen() ); } // remove supergate library Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() ); Abc_FrameSetLibSuper( NULL ); } // quit if there is no library if ( pLib == NULL ) { printf( "The current library is not available.\n" ); return 0; } if ( AreaMulti != 0.0 ) fUseMulti = 1, printf( "The cell areas are multiplied by the factor: ^ (%.2f).\n", AreaMulti ); if ( DelayMulti != 0.0 ) fUseMulti = 1, printf( "The cell delays are multiplied by the factor: ^ (%.2f).\n", DelayMulti ); // penalize large gates by increasing their area if ( AreaMulti != 0.0 ) Mio_LibraryMultiArea( pLib, AreaMulti ); if ( DelayMulti != 0.0 ) Mio_LibraryMultiDelay( pLib, DelayMulti ); // derive the supergate library if ( fUseMulti || Abc_FrameReadLibSuper() == NULL ) { if ( fVerbose ) printf( "Converting \"%s\" into supergate library \"%s\".\n", Mio_LibraryReadName(pLib), Extra_FileNameGenericAppend(Mio_LibraryReadName(pLib), ".super") ); // compute supergate library to be used for mapping if ( Mio_LibraryHasProfile(pLib) ) printf( "Abc_NtkMap(): Genlib library has profile.\n" ); Map_SuperLibDeriveFromGenlib( pLib, fVerbose ); } // return the library to normal if ( AreaMulti != 0.0 ) Mio_LibraryMultiArea( (Mio_Library_t *)Abc_FrameReadLibGen(), -AreaMulti ); if ( DelayMulti != 0.0 ) Mio_LibraryMultiDelay( (Mio_Library_t *)Abc_FrameReadLibGen(), -DelayMulti ); // print a warning about choice nodes if ( fVerbose && Abc_NtkGetChoiceNum( pNtk ) ) printf( "Performing mapping with choices.\n" ); // compute switching activity fShowSwitching |= fSwitching; if ( fShowSwitching ) { extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); pSwitching = (float *)vSwitching->pArray; } // perform the mapping pMan = Abc_NtkToMap( pNtk, DelayTarget, fRecovery, pSwitching, fVerbose ); if ( pSwitching ) Vec_IntFree( vSwitching ); if ( pMan == NULL ) return NULL; clk = Abc_Clock(); Map_ManSetSwitching( pMan, fSwitching ); Map_ManSetSkipFanout( pMan, fSkipFanout ); if ( fUseProfile ) Map_ManSetUseProfile( pMan ); if ( LogFan != 0 ) Map_ManCreateNodeDelays( pMan, LogFan ); if ( !Map_Mapping( pMan ) ) { Map_ManFree( pMan ); return NULL; } // Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), Abc_Clock()-clk ); // reconstruct the network after mapping pNtkNew = Abc_NtkFromMap( pMan, pNtk ); if ( Mio_LibraryHasProfile(pLib) ) Mio_LibraryTransferProfile2( (Mio_Library_t *)Abc_FrameReadLibGen(), pLib ); Map_ManFree( pMan ); if ( pNtkNew == NULL ) return NULL; if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); if ( fVerbose ) { ABC_PRT( "Total runtime", Abc_Clock() - clkTotal ); } // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkMap: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Load the network into manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Time_t * Abc_NtkMapCopyCiArrival( Abc_Ntk_t * pNtk, Abc_Time_t * ppTimes ) { Map_Time_t * p; int i; p = ABC_CALLOC( Map_Time_t, Abc_NtkCiNum(pNtk) ); for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ ) { p[i].Fall = ppTimes[i].Fall; p[i].Rise = ppTimes[i].Rise; p[i].Worst = Abc_MaxFloat( p[i].Fall, p[i].Rise ); } ABC_FREE( ppTimes ); return p; } Map_Time_t * Abc_NtkMapCopyCoRequired( Abc_Ntk_t * pNtk, Abc_Time_t * ppTimes ) { Map_Time_t * p; int i; p = ABC_CALLOC( Map_Time_t, Abc_NtkCoNum(pNtk) ); for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) { p[i].Fall = ppTimes[i].Fall; p[i].Rise = ppTimes[i].Rise; p[i].Worst = Abc_MaxFloat( p[i].Fall, p[i].Rise ); } ABC_FREE( ppTimes ); return p; } /**Function************************************************************* Synopsis [Load the network into manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Time_t * Abc_NtkMapCopyCiArrivalCon( Abc_Ntk_t * pNtk ) { Map_Time_t * p; int i; p = ABC_CALLOC( Map_Time_t, Abc_NtkCiNum(pNtk) ); for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ ) p[i].Fall = p[i].Rise = p[i].Worst = Scl_Int2Flt( Scl_ConGetInArr(i) ); return p; } Map_Time_t * Abc_NtkMapCopyCoRequiredCon( Abc_Ntk_t * pNtk ) { Map_Time_t * p; int i; p = ABC_CALLOC( Map_Time_t, Abc_NtkCoNum(pNtk) ); for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) p[i].Fall = p[i].Rise = p[i].Worst = Scl_Int2Flt( Scl_ConGetOutReq(i) ); return p; } /**Function************************************************************* Synopsis [Load the network into manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ) { Map_Man_t * pMan; Map_Node_t * pNodeMap; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin, * pPrev; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the mapping manager and set its parameters pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, fVerbose ); if ( pMan == NULL ) return NULL; Map_ManSetAreaRecovery( pMan, fRecovery ); Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); Map_ManSetDelayTarget( pMan, (float)DelayTarget ); // set arrival and requireds if ( Scl_ConIsRunning() && Scl_ConHasInArrs() ) Map_ManSetInputArrivals( pMan, Abc_NtkMapCopyCiArrivalCon(pNtk) ); else Map_ManSetInputArrivals( pMan, Abc_NtkMapCopyCiArrival(pNtk, Abc_NtkGetCiArrivalTimes(pNtk)) ); if ( Scl_ConIsRunning() && Scl_ConHasOutReqs() ) Map_ManSetOutputRequireds( pMan, Abc_NtkMapCopyCoRequiredCon(pNtk) ); else Map_ManSetOutputRequireds( pMan, Abc_NtkMapCopyCoRequired(pNtk, Abc_NtkGetCoRequiredTimes(pNtk)) ); // create PIs and remember them in the old nodes Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan); Abc_NtkForEachCi( pNtk, pNode, i ) { if ( i == Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) break; pNodeMap = Map_ManReadInputs(pMan)[i]; pNode->pCopy = (Abc_Obj_t *)pNodeMap; if ( pSwitching ) Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); } // load the AIG into the mapper vNodes = Abc_AigDfsMap( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsLatch(pNode) ) { pFanin = Abc_ObjFanin0(pNode); pNodeMap = Map_NodeBuf( pMan, Map_NotCond( Abc_ObjFanin0(pFanin)->pCopy, (int)Abc_ObjFaninC0(pFanin) ) ); Abc_ObjFanout0(pNode)->pCopy = (Abc_Obj_t *)pNodeMap; continue; } assert( Abc_ObjIsNode(pNode) ); // add the node to the mapper pNodeMap = Map_NodeAnd( pMan, Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ), Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ) ); assert( pNode->pCopy == NULL ); // remember the node pNode->pCopy = (Abc_Obj_t *)pNodeMap; if ( pSwitching ) Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); // set up the choice node if ( Abc_AigNodeIsChoice( pNode ) ) for ( pPrev = pNode, pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData ) { Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy ); Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy ); } } assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs ); Vec_PtrFree( vNodes ); // set the primary outputs in the required phase Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i == Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) break; Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ); } return pMan; } /**Function************************************************************* Synopsis [Creates the mapped network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ) { Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Mio_Gate_t * pRoot; Map_Super_t ** ppFanins; Abc_Obj_t * pNodeNew, * pNodeFanin; int nFanins, Number, i; // get the parameters of the supergate pRoot = Map_SuperReadRoot(pSuper); if ( pRoot == NULL ) { Number = Map_SuperReadNum(pSuper); if ( Number < nNodePis ) { return pNodePis[Number]; } else { // assert( 0 ); /* It might happen that a super gate with 5 inputs is constructed that * actually depends only on the first four variables; i.e the fifth is a * don't care -- in that case we connect constant node for the fifth * (since the cut only has 4 variables). An interesting question is what * if the first variable (and not the fifth one is the redundant one; * can that happen?) */ return Abc_NtkCreateNodeConst0(pNtkNew); } } pRoot = Mio_LibraryReadGateByName( pLib, Mio_GateReadName(pRoot), NULL ); // get information about the fanins of the supergate nFanins = Map_SuperReadFaninNum( pSuper ); ppFanins = Map_SuperReadFanins( pSuper ); // create a new node with these fanins pNodeNew = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < nFanins; i++ ) { pNodeFanin = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, ppFanins[i], pNodePis, nNodePis ); Abc_ObjAddFanin( pNodeNew, pNodeFanin ); } pNodeNew->pData = pRoot; return pNodeNew; } Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ) { Abc_Obj_t * pNodePIs[10]; Abc_Obj_t * pNodeNew; Map_Node_t ** ppLeaves; Map_Cut_t * pCutBest; Map_Super_t * pSuperBest; unsigned uPhaseBest; int i, fInvPin, nLeaves; // make sure the node can be implemented in this phase assert( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL || Map_NodeIsConst(pNodeMap) ); // check if the phase is already implemented pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase ); if ( pNodeNew ) return pNodeNew; // get the information about the best cut pCutBest = Map_NodeReadCutBest( pNodeMap, fPhase ); pSuperBest = Map_CutReadSuperBest( pCutBest, fPhase ); uPhaseBest = Map_CutReadPhaseBest( pCutBest, fPhase ); nLeaves = Map_CutReadLeavesNum( pCutBest ); ppLeaves = Map_CutReadLeaves( pCutBest ); // collect the PI nodes for ( i = 0; i < nLeaves; i++ ) { fInvPin = ((uPhaseBest & (1 << i)) > 0); pNodePIs[i] = Abc_NodeFromMap_rec( pNtkNew, ppLeaves[i], !fInvPin ); assert( pNodePIs[i] != NULL ); } // implement the supergate pNodeNew = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, pSuperBest, pNodePIs, nLeaves ); Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeNew ); return pNodeNew; } Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ) { Abc_Obj_t * pNodeNew, * pNodeInv; // check the case of constant node if ( Map_NodeIsConst(pNodeMap) ) { pNodeNew = fPhase? Abc_NtkCreateNodeConst1(pNtkNew) : Abc_NtkCreateNodeConst0(pNtkNew); if ( pNodeNew->pData == NULL ) printf( "Error creating mapped network: Library does not have a constant %d gate.\n", fPhase ); return pNodeNew; } // check if the phase is already implemented pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase ); if ( pNodeNew ) return pNodeNew; // implement the node if the best cut is assigned if ( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL ) return Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, fPhase ); // if the cut is not assigned, implement the node assert( Map_NodeReadCutBest(pNodeMap, !fPhase) != NULL || Map_NodeIsConst(pNodeMap) ); pNodeNew = Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, !fPhase ); // add the inverter pNodeInv = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNodeInv, pNodeNew ); pNodeInv->pData = Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen()); // set the inverter Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeInv ); return pNodeInv; } Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Map_Node_t * pNodeMap; Abc_Obj_t * pNode, * pNodeNew; int i, nDupGates; assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs ); // create the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP ); // make the mapper point to the new network Map_ManCleanData( pMan ); Abc_NtkForEachCi( pNtk, pNode, i ) { if ( i >= Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) break; Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); } Abc_NtkForEachCi( pNtk, pNode, i ) { if ( i < Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) continue; Map_NodeSetData( Map_ManReadBufs(pMan)[i - (Abc_NtkCiNum(pNtk) - pNtk->nBarBufs)], 1, (char *)pNode->pCopy ); } // assign the mapping of the required phase to the POs Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) continue; pNodeMap = Map_ManReadBufDriver( pMan, i - (Abc_NtkCoNum(pNtk) - pNtk->nBarBufs) ); pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) ); assert( !Abc_ObjIsComplement(pNodeNew) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) break; pNodeMap = Map_ManReadOutputs(pMan)[i]; pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) ); assert( !Abc_ObjIsComplement(pNodeNew) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } // decouple the PO driver nodes to reduce the number of levels nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); // if ( nDupGates && Map_ManReadVerbose(pMan) ) // printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); return pNtkNew; } /**Function************************************************************* Synopsis [Interface with the mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Map_Man_t * pMan; assert( Abc_NtkIsStrash(pNtk) ); // check that the library is available if ( Abc_FrameReadLibGen() == NULL ) { printf( "The current library is not available.\n" ); return 0; } // derive the supergate library if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) { // printf( "A simple supergate library is derived from gate library \"%s\".\n", // Mio_LibraryReadName((Mio_Library_t *)Abc_FrameReadLibGen()) ); Map_SuperLibDeriveFromGenlib( (Mio_Library_t *)Abc_FrameReadLibGen(), 0 ); } // print a warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Performing mapping with choices.\n" ); // perform the mapping pMan = Abc_NtkToMap( pNtk, -1, 1, NULL, 0 ); if ( pMan == NULL ) return NULL; if ( !Map_Mapping( pMan ) ) { Map_ManFree( pMan ); return NULL; } // reconstruct the network after mapping pNtkNew = Abc_NtkFromMapSuperChoice( pMan, pNtk ); if ( pNtkNew == NULL ) return NULL; Map_ManFree( pMan ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkMap: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Creates the mapped network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) { extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); ProgressBar * pProgress; Abc_Ntk_t * pNtkNew, * pNtkNew2; Abc_Obj_t * pNode; int i; // save the pointer to the mapped nodes Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pNext = pNode->pCopy; Abc_NtkForEachPo( pNtk, pNode, i ) pNode->pNext = pNode->pCopy; Abc_NtkForEachNode( pNtk, pNode, i ) pNode->pNext = pNode->pCopy; // duplicate the network pNtkNew2 = Abc_NtkDup( pNtk ); pNtkNew = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 ); if ( !Abc_NtkBddToSop( pNtkNew, -1, ABC_INFINITY ) ) { printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" ); return NULL; } // set the old network to point to the new network Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = pNode->pCopy->pCopy; Abc_NtkForEachPo( pNtk, pNode, i ) pNode->pCopy = pNode->pCopy->pCopy; Abc_NtkForEachNode( pNtk, pNode, i ) pNode->pCopy = pNode->pCopy->pCopy; Abc_NtkDelete( pNtkNew2 ); // set the pointers from the mapper to the new nodes Abc_NtkForEachCi( pNtk, pNode, i ) { Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) ); Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); } Abc_NtkForEachNode( pNtk, pNode, i ) { // if ( Abc_NodeIsConst(pNode) ) // continue; Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) ); Map_NodeSetData( (Map_Node_t *)pNode->pNext, 1, (char *)pNode->pCopy ); } // assign the mapping of the required phase to the POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // if ( Abc_NodeIsConst(pNode) ) // continue; Abc_NodeSuperChoice( pNtkNew, pNode ); } Extra_ProgressBarStop( pProgress ); return pNtkNew; } /**Function************************************************************* Synopsis [Creates the mapped network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) { Map_Node_t * pMapNode = (Map_Node_t *)pNode->pNext; Map_Cut_t * pCuts, * pTemp; pCuts = Map_NodeReadCuts(pMapNode); for ( pTemp = Map_CutReadNext(pCuts); pTemp; pTemp = Map_CutReadNext(pTemp) ) { Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 0 ); Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 1 ); } } /**Function************************************************************* Synopsis [Constructs the nodes corrresponding to one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase ) { Abc_Obj_t * pNodePIs[10]; Map_Node_t ** ppLeaves; Map_Super_t * pSuperBest; unsigned uPhaseBest; int i, fInvPin, nLeaves; pSuperBest = Map_CutReadSuperBest( pCut, fPhase ); if ( pSuperBest == NULL ) return; // get the information about the best cut uPhaseBest = Map_CutReadPhaseBest( pCut, fPhase ); nLeaves = Map_CutReadLeavesNum( pCut ); ppLeaves = Map_CutReadLeaves( pCut ); // collect the PI nodes for ( i = 0; i < nLeaves; i++ ) { fInvPin = ((uPhaseBest & (1 << i)) > 0); pNodePIs[i] = (Abc_Obj_t *)Map_NodeReadData( ppLeaves[i], !fInvPin ); assert( pNodePIs[i] != NULL ); } // implement the supergate Abc_NodeFromMapSuperChoice_rec( pNtkNew, pSuperBest, pNodePIs, nLeaves ); } /**Function************************************************************* Synopsis [Constructs the nodes corrresponding to one supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ) { Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Mio_Gate_t * pRoot; Map_Super_t ** ppFanins; Abc_Obj_t * pNodeNew, * pNodeFanin; int nFanins, Number, i; // get the parameters of the supergate pRoot = Map_SuperReadRoot(pSuper); if ( pRoot == NULL ) { Number = Map_SuperReadNum(pSuper); if ( Number < nNodePis ) { return pNodePis[Number]; } else { // assert( 0 ); /* It might happen that a super gate with 5 inputs is constructed that * actually depends only on the first four variables; i.e the fifth is a * don't care -- in that case we connect constant node for the fifth * (since the cut only has 4 variables). An interesting question is what * if the first variable (and not the fifth one is the redundant one; * can that happen?) */ return Abc_NtkCreateNodeConst0(pNtkNew); } } pRoot = Mio_LibraryReadGateByName( pLib, Mio_GateReadName(pRoot), NULL ); // get information about the fanins of the supergate nFanins = Map_SuperReadFaninNum( pSuper ); ppFanins = Map_SuperReadFanins( pSuper ); // create a new node with these fanins pNodeNew = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < nFanins; i++ ) { pNodeFanin = Abc_NodeFromMapSuperChoice_rec( pNtkNew, ppFanins[i], pNodePis, nNodePis ); Abc_ObjAddFanin( pNodeNew, pNodeFanin ); } pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Mio_GateReadSop(pRoot) ); return pNodeNew; } /**Function************************************************************* Synopsis [Returns the twin node if it exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkFetchTwinNode( Abc_Obj_t * pNode ) { Abc_Obj_t * pNode2; Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData; assert( Abc_NtkHasMapping(pNode->pNtk) ); if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL ) return NULL; // assuming the twin node is following next if ( (int)Abc_ObjId(pNode) == Abc_NtkObjNumMax(pNode->pNtk) - 1 ) return NULL; pNode2 = Abc_NtkObj( pNode->pNtk, Abc_ObjId(pNode) + 1 ); if ( pNode2 == NULL || !Abc_ObjIsNode(pNode2) || Abc_ObjFaninNum(pNode) != Abc_ObjFaninNum(pNode2) ) return NULL; if ( Mio_GateReadTwin(pGate) != (Mio_Gate_t *)pNode2->pData ) return NULL; return pNode2; } /**Function************************************************************* Synopsis [Dumps mapped network in the mini-mapped format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkWriteMiniMapping( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Vec_Int_t * vMapping; Vec_Str_t * vGates; Abc_Obj_t * pObj, * pFanin; int i, k, nNodes, nFanins, nExtra, * pArray; assert( Abc_NtkHasMapping(pNtk) ); // collect nodes in the DFS order vNodes = Abc_NtkDfs( pNtk, 0 ); // assign unique numbers nNodes = nFanins = 0; Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = nNodes++; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->iTemp = nNodes++, nFanins += Abc_ObjFaninNum(pObj); // allocate attay to store mapping (4 counters + fanins for each node + PO drivers + gate names) vMapping = Vec_IntAlloc( 4 + Abc_NtkNodeNum(pNtk) + nFanins + Abc_NtkCoNum(pNtk) + 10000 ); // write the numbers of CI/CO/Node/FF Vec_IntPush( vMapping, Abc_NtkCiNum(pNtk) ); Vec_IntPush( vMapping, Abc_NtkCoNum(pNtk) ); Vec_IntPush( vMapping, Abc_NtkNodeNum(pNtk) ); Vec_IntPush( vMapping, Abc_NtkLatchNum(pNtk) ); // write the nodes vGates = Vec_StrAlloc( 10000 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Vec_IntPush( vMapping, Abc_ObjFaninNum(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vMapping, pFanin->iTemp ); // remember this gate (to be added to the mapping later) Vec_StrPrintStr( vGates, Mio_GateReadName((Mio_Gate_t *)pObj->pData) ); Vec_StrPush( vGates, '\0' ); } // write the COs literals Abc_NtkForEachCo( pNtk, pObj, i ) Vec_IntPush( vMapping, Abc_ObjFanin0(pObj)->iTemp ); // finish off the array nExtra = 4 - Vec_StrSize(vGates) % 4; for ( i = 0; i < nExtra; i++ ) Vec_StrPush( vGates, '\0' ); // add gates to the array assert( Vec_StrSize(vGates) % 4 == 0 ); nExtra = Vec_StrSize(vGates) / 4; pArray = (int *)Vec_StrArray(vGates); for ( i = 0; i < nExtra; i++ ) Vec_IntPush( vMapping, pArray[i] ); // cleanup and return Vec_PtrFree( vNodes ); Vec_StrFree( vGates ); return vMapping; } /**Function************************************************************* Synopsis [Prints mapped network represented in mini-mapped format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintMiniMapping( int * pArray ) { int nCis, nCos, nNodes, nFlops; int i, k, nLeaves, Pos = 4; char * pBuffer, * pName; nCis = pArray[0]; nCos = pArray[1]; nNodes = pArray[2]; nFlops = pArray[3]; printf( "Mapped network has %d CIs, %d COs, %d gates, and %d flops.\n", nCis, nCos, nNodes, nFlops ); printf( "The first %d object IDs (from 0 to %d) are reserved for the CIs.\n", nCis, nCis - 1 ); for ( i = 0; i < nNodes; i++ ) { printf( "Node %d has fanins {", nCis + i ); nLeaves = pArray[Pos++]; for ( k = 0; k < nLeaves; k++ ) printf( " %d", pArray[Pos++] ); printf( " }\n" ); } for ( i = 0; i < nCos; i++ ) printf( "CO %d is driven by node %d\n", i, pArray[Pos++] ); pBuffer = (char *)(pArray + Pos); for ( i = 0; i < nNodes; i++ ) { pName = pBuffer; pBuffer += strlen(pName) + 1; printf( "Node %d has gate \"%s\"\n", nCis + i, pName ); } } /**Function************************************************************* Synopsis [This procedure outputs an array representing mini-mapped network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Abc_NtkOutputMiniMapping( void * pAbc0 ) { Abc_Frame_t * pAbc = (Abc_Frame_t *)pAbc0; Abc_Ntk_t * pNtk; Vec_Int_t * vMapping; int * pArray; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pNtk = Abc_FrameReadNtk( pAbc ); if ( pNtk == NULL ) printf( "Current network in ABC framework is not defined.\n" ); if ( !Abc_NtkHasMapping(pNtk) ) printf( "Current network in ABC framework is not mapped.\n" ); // derive mini-mapping vMapping = Abc_NtkWriteMiniMapping( pNtk ); pArray = Vec_IntArray( vMapping ); ABC_FREE( vMapping ); // print mini-mapping (optional) // Abc_NtkPrintMiniMapping( pArray ); // return the array representation of mini-mapping return pArray; } /**Function************************************************************* Synopsis [Test for mini-mapped format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTestMiniMapping( Abc_Ntk_t * p ) { Vec_Int_t * vMapping; vMapping = Abc_NtkWriteMiniMapping( p ); Abc_NtkPrintMiniMapping( Vec_IntArray(vMapping) ); printf( "Array has size %d ints.\n", Vec_IntSize(vMapping) ); Vec_IntFree( vMapping ); } /**Function************************************************************* Synopsis [These APIs set arrival/required times of CIs/COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSetCiArrivalTime( void * pAbc0, int iCi, float Rise, float Fall ) { Abc_Frame_t * pAbc = (Abc_Frame_t *)pAbc0; Abc_Ntk_t * pNtk; Abc_Obj_t * pNode; if ( pAbc == NULL ) { printf( "ABC framework is not initialized by calling Abc_Start()\n" ); return; } pNtk = Abc_FrameReadNtk( pAbc ); if ( pNtk == NULL ) { printf( "Current network in ABC framework is not defined.\n" ); return; } if ( iCi < 0 || iCi >= Abc_NtkCiNum(pNtk) ) { printf( "CI index is not valid.\n" ); return; } pNode = Abc_NtkCi( pNtk, iCi ); Abc_NtkTimeSetArrival( pNtk, Abc_ObjId(pNode), Rise, Fall ); } void Abc_NtkSetCoRequiredTime( void * pAbc0, int iCo, float Rise, float Fall ) { Abc_Frame_t * pAbc = (Abc_Frame_t *)pAbc0; Abc_Ntk_t * pNtk; Abc_Obj_t * pNode; if ( pAbc == NULL )\ { printf( "ABC framework is not initialized by calling Abc_Start()\n" ); return; } pNtk = Abc_FrameReadNtk( pAbc ); if ( pNtk == NULL ) { printf( "Current network in ABC framework is not defined.\n" ); return; } if ( iCo < 0 || iCo >= Abc_NtkCoNum(pNtk) ) { printf( "CO index is not valid.\n" ); return; } pNode = Abc_NtkCo( pNtk, iCo ); Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pNode), Rise, Fall ); } /**Function************************************************************* Synopsis [This APIs set AND gate delay.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSetAndGateDelay( void * pAbc0, float Delay ) { Abc_Frame_t * pAbc = (Abc_Frame_t *)pAbc0; Abc_Ntk_t * pNtk; if ( pAbc == NULL ) { printf( "ABC framework is not initialized by calling Abc_Start()\n" ); return; } pNtk = Abc_FrameReadNtk( pAbc ); if ( pNtk == NULL ) { printf( "Current network in ABC framework is not defined.\n" ); return; } pNtk->AndGateDelay = Delay; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMeasure.c000066400000000000000000000336541300674244400240720ustar00rootroot00000000000000/**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 "base/abc/abc.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintMeasures( unsigned * pTruth, int nVars ) { unsigned uCofs[10][32]; int i, k, nOnes; // total pairs nOnes = Kit_TruthCountOnes( uCofs[0], nVars ); printf( "Total = %d.\n", nOnes * ((1 << nVars) - nOnes) ); // print measures for individual variables for ( i = 0; i < nVars; i++ ) { Kit_TruthUniqueNew( uCofs[0], pTruth, nVars, i ); nOnes = Kit_TruthCountOnes( uCofs[0], nVars ); printf( "%7d ", nOnes ); } printf( "\n" ); // consider pairs for ( i = 0; i < nVars; i++ ) for ( k = 0; k < nVars; k++ ) { if ( i == k ) { printf( " " ); continue; } Kit_TruthCofactor0New( uCofs[0], pTruth, nVars, i ); Kit_TruthCofactor1New( uCofs[1], pTruth, nVars, i ); Kit_TruthCofactor0New( uCofs[2], uCofs[0], nVars, k ); // 00 Kit_TruthCofactor1New( uCofs[3], uCofs[0], nVars, k ); // 01 Kit_TruthCofactor0New( uCofs[4], uCofs[1], nVars, k ); // 10 Kit_TruthCofactor1New( uCofs[5], uCofs[1], nVars, k ); // 11 Kit_TruthAndPhase( uCofs[6], uCofs[2], uCofs[5], nVars, 0, 1 ); // 00 & 11' Kit_TruthAndPhase( uCofs[7], uCofs[2], uCofs[5], nVars, 1, 0 ); // 00' & 11 Kit_TruthAndPhase( uCofs[8], uCofs[3], uCofs[4], nVars, 0, 1 ); // 01 & 10' Kit_TruthAndPhase( uCofs[9], uCofs[3], uCofs[4], nVars, 1, 0 ); // 01' & 10 nOnes = Kit_TruthCountOnes( uCofs[6], nVars ) + Kit_TruthCountOnes( uCofs[7], nVars ) + Kit_TruthCountOnes( uCofs[8], nVars ) + Kit_TruthCountOnes( uCofs[9], nVars ); printf( "%7d ", nOnes ); if ( k == nVars - 1 ) printf( "\n" ); } printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj ) { if ( pObj == Abc_AigConst1(pObj->pNtk) ) { printf( "1" ); return; } if ( Abc_ObjIsPi(pObj) ) { printf( "%c", pObj->Id - 1 + 'a' ); return; } printf( "(" ); Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); if ( Abc_ObjFaninC0(pObj) ) printf( "\'" ); Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) ); if ( Abc_ObjFaninC1(pObj) ) printf( "\'" ); printf( ")" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes ) { Abc_Obj_t * pObj; unsigned uTruth0, uTruth1; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy); uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy); if ( Abc_ObjFaninC0(pObj) ) uTruth0 = ~uTruth0; if ( Abc_ObjFaninC1(pObj) ) uTruth1 = ~uTruth1; pObj->pCopy = (Abc_Obj_t *)(uTruth0 & uTruth1); } return uTruth0 & uTruth1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_Ntk4VarTable( Abc_Ntk_t * pNtk ) { static unsigned u4VarTruths[4] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00 }; static unsigned u4VarTts[222] = { 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016a, 0x016b, 0x016e, 0x016f, 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186, 0x0187, 0x0189, 0x018b, 0x018f, 0x0196, 0x0197, 0x0198, 0x0199, 0x019a, 0x019b, 0x019e, 0x019f, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bc, 0x01bd, 0x01be, 0x01bf, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035e, 0x035f, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, 0x037c, 0x037d, 0x037e, 0x03c0, 0x03c1, 0x03c3, 0x03c5, 0x03c6, 0x03c7, 0x03cf, 0x03d4, 0x03d5, 0x03d6, 0x03d7, 0x03d8, 0x03d9, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0662, 0x0663, 0x0666, 0x0667, 0x0669, 0x066b, 0x066f, 0x0672, 0x0673, 0x0676, 0x0678, 0x0679, 0x067a, 0x067b, 0x067e, 0x0690, 0x0691, 0x0693, 0x0696, 0x0697, 0x069f, 0x06b0, 0x06b1, 0x06b2, 0x06b3, 0x06b4, 0x06b5, 0x06b6, 0x06b7, 0x06b9, 0x06bd, 0x06f0, 0x06f1, 0x06f2, 0x06f6, 0x06f9, 0x0776, 0x0778, 0x0779, 0x077a, 0x077e, 0x07b0, 0x07b1, 0x07b4, 0x07b5, 0x07b6, 0x07bc, 0x07e0, 0x07e1, 0x07e2, 0x07e3, 0x07e6, 0x07e9, 0x07f0, 0x07f1, 0x07f2, 0x07f8, 0x0ff0, 0x1668, 0x1669, 0x166a, 0x166b, 0x166e, 0x167e, 0x1681, 0x1683, 0x1686, 0x1687, 0x1689, 0x168b, 0x168e, 0x1696, 0x1697, 0x1698, 0x1699, 0x169a, 0x169b, 0x169e, 0x16a9, 0x16ac, 0x16ad, 0x16bc, 0x16e9, 0x177e, 0x178e, 0x1796, 0x1798, 0x179a, 0x17ac, 0x17e8, 0x18e7, 0x19e1, 0x19e3, 0x19e6, 0x1bd8, 0x1be4, 0x1ee1, 0x3cc3, 0x6996 }; int Counters[222] = {0}; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; unsigned uTruth; int i, k, Count = 0; unsigned short * puCanons = NULL; unsigned char * puMap = NULL; Extra_Truth4VarNPN( &puCanons, NULL, NULL, &puMap ); // set elementary truth tables assert( Abc_NtkPiNum(pNtk) == 4 ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)0xFFFFFFFF; Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)u4VarTruths[i]; // create truth tables Abc_NtkForEachPo( pNtk, pObj, i ) { vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); if ( Vec_PtrSize(vNodes) == 0 ) uTruth = (unsigned)Abc_ObjFanin0(pObj)->pCopy; else uTruth = Abc_Ntk4VarObj( vNodes ); if ( (uTruth & 0xFFFF) < (~uTruth & 0xFFFF) ) uTruth = uTruth & 0xFFFF; else uTruth = ~uTruth & 0xFFFF; for ( k = 0; k < 222; k++ ) if ( u4VarTts[k] == uTruth ) break; if ( k == 222 ) continue; /* // if ( uTruth == 1725 ) if ( k == 96 ) { printf( "%d : ", Vec_PtrSize(vNodes) ); Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); printf( "\n" ); } */ Counters[k]++; // Counters[ puMap[uTruth & 0xFFFF] ]++; Vec_PtrFree( vNodes ); } ABC_FREE( puCanons ); ABC_FREE( puMap ); Count = 0; for ( k = 0; k < 222; k++ ) { printf( "%d/%x/%d ", k, u4VarTts[k], Counters[k] ); Count += Counters[k]; } printf( " Total = %d\n", Count ); } /**Function************************************************************* Synopsis [Returns 1 if there are no more than 2 unique cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkPrintOneDecompCheckCofList( unsigned * uCofs, int nCofs ) { int i, Ind = -1; assert( nCofs > 2 ); for ( i = 1; i < nCofs; i++ ) { if ( uCofs[i] == uCofs[0] ) continue; if ( Ind == -1 ) { Ind = i; continue; } if ( uCofs[i] == uCofs[Ind] ) continue; return 0; } return 1; } /**Function************************************************************* Synopsis [Checks all cofactors with the given mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkPrintOneDecompCheck( unsigned * uCofs, int nCofs, unsigned uMask ) { unsigned pCofs[32][32]; int nCofNums[32] = {0}; int uMasks[32]; int nGroups = 0; int i, k; for ( i = 0; i < nCofs; i++ ) { // find group of this cof for ( k = 0; k < nGroups; k++ ) if ( (int)(i & uMask) == uMasks[k] ) break; if ( k == nGroups ) { uMasks[k] = (i & uMask); nGroups++; } // save cof in the group pCofs[k][ nCofNums[k]++ ] = uCofs[i]; assert( nCofNums[k] <= 32 ); assert( nGroups <= 32 ); } // check the groups for ( i = 0; i < nGroups; i++ ) if ( !Abc_NtkPrintOneDecompCheckCofList(pCofs[i], nCofNums[i]) ) return 0; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintOneDecomp_rec( unsigned * uCofs, int nCofs, int nVars, unsigned uMask, int * pBestSize, unsigned * puBestMask ) { unsigned uMaskNew; int v, last, Counter = 0; // find the last variable in the mask for ( v = 0; v < nVars; v++ ) if ( uMask & (1< 3 ) return; // try adding one variable after the last for ( v = last + 1; v < nVars; v++ ) { uMaskNew = uMask | (1 << v); if ( !Abc_NtkPrintOneDecompCheck( uCofs, nCofs, uMaskNew ) ) continue; if ( *pBestSize < Counter + 1 ) { *pBestSize = Counter + 1; *puBestMask = uMaskNew; } // try other masks Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, uMaskNew, pBestSize, puBestMask ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintOneDecomp( unsigned * pTruth, int nVars ) { int BoundSet = 6; unsigned uCofs[64], uMask, uBestMask = 0; int i, nCofs, nMints, nMintShift, BestSize = 1; assert( nVars > BoundSet ); assert( nVars <= BoundSet + 5 ); // at most 5 variable cofactors // collect the cofactors nCofs = (1 << BoundSet); nMints = (1 << (nVars-BoundSet)); nMintShift = 0; uMask = Kit_CubeMask( nMints ); for ( i = 0; i < nCofs; i++ ) { uCofs[i] = (pTruth[nMintShift/32] >> (nMintShift % 32)) & uMask; nMintShift += nMints; } // try removing variables for ( i = 0; i < BoundSet; i++ ) Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, (1 << i), &BestSize, &uBestMask ); printf( "Best size = %d ", BestSize ); printf( "Best mask = " ); Extra_PrintBinary( stdout, &uBestMask, nVars ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintOneDec( unsigned * pTruth, int nVars ) { unsigned uCof[(1<<11)], * pOut = uCof, * pIn = pTruth, * pTemp; int nDiffs[16]; int Order[16]; int i, fChange, Temp, Counter; // find the ordering for ( i = 0; i < nVars; i++ ) { Kit_TruthUniqueNew( uCof, pTruth, nVars, i ); nDiffs[i] = Kit_TruthCountOnes( uCof, nVars ); Order[i] = i; } // permute truth table to least active variable first Counter = 0; do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( nDiffs[i] <= nDiffs[i+1] ) continue; fChange = 1; Counter++; Temp = nDiffs[i]; nDiffs[i] = nDiffs[i+1]; nDiffs[i+1] = Temp; Temp = Order[i]; Order[i] = Order[i+1]; Order[i+1] = Temp; Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; } } while ( fChange ); // swap if it was moved an even number of times if ( Counter & 1 ) Extra_TruthCopy( pOut, pIn, nVars ); // call the decomposition Abc_NtkPrintOneDecomp( pTruth, nVars ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMerge.c000066400000000000000000000261421300674244400235220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMerge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [LUT merging algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/aig/aig.h" #include "opt/nwk/nwkMerge.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Marks the fanins of the node with the current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMarkFanins_rec( Abc_Obj_t * pLut, int nLevMin ) { Abc_Obj_t * pNext; int i; if ( !Abc_ObjIsNode(pLut) ) return; if ( Abc_NodeIsTravIdCurrent( pLut ) ) return; Abc_NodeSetTravIdCurrent( pLut ); if ( Abc_ObjLevel(pLut) < nLevMin ) return; Abc_ObjForEachFanin( pLut, pNext, i ) Abc_NtkMarkFanins_rec( pNext, nLevMin ); } /**Function************************************************************* Synopsis [Marks the fanouts of the node with the current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMarkFanouts_rec( Abc_Obj_t * pLut, int nLevMax, int nFanMax ) { Abc_Obj_t * pNext; int i; if ( !Abc_ObjIsNode(pLut) ) return; if ( Abc_NodeIsTravIdCurrent( pLut ) ) return; Abc_NodeSetTravIdCurrent( pLut ); if ( Abc_ObjLevel(pLut) > nLevMax ) return; if ( Abc_ObjFanoutNum(pLut) > nFanMax ) return; Abc_ObjForEachFanout( pLut, pNext, i ) Abc_NtkMarkFanouts_rec( pNext, nLevMax, nFanMax ); } /**Function************************************************************* Synopsis [Collects the circle of nodes around the given set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) { Abc_Obj_t * pObj, * pNext; int i, k; Vec_PtrClear( vNext ); Vec_PtrForEachEntry( Abc_Obj_t *, vStart, pObj, i ) { Abc_ObjForEachFanin( pObj, pNext, k ) { if ( !Abc_ObjIsNode(pNext) ) continue; if ( Abc_NodeIsTravIdCurrent( pNext ) ) continue; Abc_NodeSetTravIdCurrent( pNext ); Vec_PtrPush( vNext, pNext ); } Abc_ObjForEachFanout( pObj, pNext, k ) { if ( !Abc_ObjIsNode(pNext) ) continue; if ( Abc_NodeIsTravIdCurrent( pNext ) ) continue; Abc_NodeSetTravIdCurrent( pNext ); if ( Abc_ObjFanoutNum(pNext) > nFanMax ) continue; Vec_PtrPush( vNext, pNext ); } } } /**Function************************************************************* Synopsis [Collects the circle of nodes removes from the given one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectNonOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) { Vec_Ptr_t * vTemp; Abc_Obj_t * pObj; int i, k; Vec_PtrClear( vCands ); if ( pPars->nMaxSuppSize - Abc_ObjFaninNum(pLut) <= 1 ) return; // collect nodes removed by this distance assert( pPars->nMaxDistance > 0 ); Vec_PtrClear( vStart ); Vec_PtrPush( vStart, pLut ); Abc_NtkIncrementTravId( pLut->pNtk ); Abc_NodeSetTravIdCurrent( pLut ); for ( i = 1; i <= pPars->nMaxDistance; i++ ) { Abc_NtkCollectCircle( vStart, vNext, pPars->nMaxFanout ); vTemp = vStart; vStart = vNext; vNext = vTemp; // collect the nodes in vStart Vec_PtrForEachEntry( Abc_Obj_t *, vStart, pObj, k ) Vec_PtrPush( vCands, pObj ); } // mark the TFI/TFO nodes Abc_NtkIncrementTravId( pLut->pNtk ); if ( pPars->fUseTfiTfo ) Abc_NodeSetTravIdCurrent( pLut ); else { Abc_NodeSetTravIdPrevious( pLut ); Abc_NtkMarkFanins_rec( pLut, Abc_ObjLevel(pLut) - pPars->nMaxDistance ); Abc_NodeSetTravIdPrevious( pLut ); Abc_NtkMarkFanouts_rec( pLut, Abc_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); } // collect nodes satisfying the following conditions: // - they are close enough in terms of distance // - they are not in the TFI/TFO of the LUT // - they have no more than the given number of fanins // - they have no more than the given diff in delay k = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vCands, pObj, i ) { if ( Abc_NodeIsTravIdCurrent(pObj) ) continue; if ( Abc_ObjFaninNum(pLut) + Abc_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) continue; if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) continue; Vec_PtrWriteEntry( vCands, k++, pObj ); } Vec_PtrShrink( vCands, k ); } /**Function************************************************************* Synopsis [Count the total number of fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountTotalFanins( Abc_Obj_t * pLut, Abc_Obj_t * pCand ) { Abc_Obj_t * pFanin; int i, nCounter = Abc_ObjFaninNum(pLut); Abc_ObjForEachFanin( pCand, pFanin, i ) nCounter += !pFanin->fMarkC; return nCounter; } /**Function************************************************************* Synopsis [Collects overlapping candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) { Abc_Obj_t * pFanin, * pObj; int i, k; // mark fanins of pLut Abc_ObjForEachFanin( pLut, pFanin, i ) pFanin->fMarkC = 1; // collect the matching fanouts of each fanin of the node Vec_PtrClear( vCands ); Abc_NtkIncrementTravId( pLut->pNtk ); Abc_NodeSetTravIdCurrent( pLut ); Abc_ObjForEachFanin( pLut, pFanin, i ) { if ( !Abc_ObjIsNode(pFanin) ) continue; if ( Abc_ObjFanoutNum(pFanin) > pPars->nMaxFanout ) continue; Abc_ObjForEachFanout( pFanin, pObj, k ) { if ( !Abc_ObjIsNode(pObj) ) continue; if ( Abc_NodeIsTravIdCurrent( pObj ) ) continue; Abc_NodeSetTravIdCurrent( pObj ); // check the difference in delay if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) continue; // check the total number of fanins of the node if ( Abc_NtkCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) continue; Vec_PtrPush( vCands, pObj ); } } // unmark fanins of pLut Abc_ObjForEachFanin( pLut, pFanin, i ) pFanin->fMarkC = 0; } /**Function************************************************************* Synopsis [Performs LUT merging with parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars ) { Nwk_Grf_t * p; Vec_Int_t * vResult; Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; Abc_Obj_t * pLut, * pCand; int i, k, nVertsMax, nCands; abctime clk = Abc_Clock(); // count the number of vertices nVertsMax = 0; Abc_NtkForEachNode( pNtk, pLut, i ) nVertsMax += (int)(Abc_ObjFaninNum(pLut) <= pPars->nMaxLutSize); p = Nwk_ManGraphAlloc( nVertsMax ); // create graph vStart = Vec_PtrAlloc( 1000 ); vNext = Vec_PtrAlloc( 1000 ); vCands1 = Vec_PtrAlloc( 1000 ); vCands2 = Vec_PtrAlloc( 1000 ); nCands = 0; Abc_NtkForEachNode( pNtk, pLut, i ) { if ( Abc_ObjFaninNum(pLut) > pPars->nMaxLutSize ) continue; Abc_NtkCollectOverlapCands( pLut, vCands1, pPars ); if ( pPars->fUseDiffSupp ) Abc_NtkCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) continue; nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2); // save candidates Vec_PtrForEachEntry( Abc_Obj_t *, vCands1, pCand, k ) Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); Vec_PtrForEachEntry( Abc_Obj_t *, vCands2, pCand, k ) Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); // print statistics about this node if ( pPars->fVeryVerbose ) printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", Abc_ObjId(pLut), Abc_ObjFaninNum(pLut), Abc_ObjFaninNum(pLut), Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); } Vec_PtrFree( vStart ); Vec_PtrFree( vNext ); Vec_PtrFree( vCands1 ); Vec_PtrFree( vCands2 ); if ( pPars->fVerbose ) { printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands ); ABC_PRT( "Deriving graph", Abc_Clock() - clk ); } // solve the graph problem clk = Abc_Clock(); Nwk_ManGraphSolve( p ); if ( pPars->fVerbose ) { printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); ABC_PRT( "Solving", Abc_Clock() - clk ); Nwk_ManGraphReportMemoryUsage( p ); } vResult = p->vPairs; p->vPairs = NULL; /* for ( i = 0; i < vResult->nSize; i += 2 ) printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); printf( "\n" ); */ Nwk_ManGraphFree( p ); return vResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMffc.c000066400000000000000000001175711300674244400233450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMffc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Computing multi-output maximum fanout-free cones.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMffc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Dereferences and collects the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MffcDeref_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; if ( Abc_ObjIsCi(pNode) ) return; Abc_ObjForEachFanin( pNode, pFanin, i ) { assert( pFanin->vFanouts.nSize > 0 ); if ( --pFanin->vFanouts.nSize == 0 ) Abc_MffcDeref_rec( pFanin, vNodes ); } if ( vNodes ) Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [References the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MffcRef_rec( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i; if ( Abc_ObjIsCi(pNode) ) return; Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( pFanin->vFanouts.nSize++ == 0 ) Abc_MffcRef_rec( pFanin ); } } /**Function************************************************************* Synopsis [Collects nodes belonging to the MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MffcCollectNodes( Abc_Obj_t ** pNodes, int nNodes, Vec_Ptr_t * vNodes ) { int i; Vec_PtrClear( vNodes ); for ( i = 0; i < nNodes; i++ ) Abc_MffcDeref_rec( pNodes[i], vNodes ); for ( i = 0; i < nNodes; i++ ) Abc_MffcRef_rec( pNodes[i] ); } /**Function************************************************************* Synopsis [Collects leaves of the MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MffcCollectLeaves( Vec_Ptr_t * vNodes, Vec_Ptr_t * vLeaves ) { Abc_Obj_t * pNode, * pFanin; int i, k; assert( Vec_PtrSize(vNodes) > 0 ); pNode = (Abc_Obj_t *)Vec_PtrEntry( vNodes, 0 ); // label them Abc_NtkIncrementTravId( pNode->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) Abc_NodeSetTravIdCurrent( pNode ); // collect non-labeled fanins Vec_PtrClear( vLeaves ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) Abc_ObjForEachFanin( pNode, pFanin, k ) { if ( Abc_NodeIsTravIdCurrent(pFanin) ) continue; Abc_NodeSetTravIdCurrent( pFanin ); Vec_PtrPush( vLeaves, pFanin ); } } /**Function************************************************************* Synopsis [Collects internal nodes that are roots of MFFCs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NktMffcMarkRoots( Abc_Ntk_t * pNtk, int fSkipPis ) { Vec_Ptr_t * vRoots, * vNodes, * vLeaves; Abc_Obj_t * pObj, * pLeaf; int i, k; Abc_NtkCleanMarkA( pNtk ); // mark the drivers of combinational outputs vRoots = Vec_PtrAlloc( 1000 ); Abc_NtkForEachCo( pNtk, pObj, i ) { pObj = Abc_ObjFanin0( pObj ); // if ( Abc_ObjIsCi(pObj) || Abc_ObjFaninNum(pObj) == 0 || pObj->fMarkA ) if ( Abc_ObjIsCi(pObj) || pObj->fMarkA ) continue; pObj->fMarkA = 1; Vec_PtrPush( vRoots, pObj ); } // explore starting from the drivers vNodes = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { if ( Abc_ObjIsCi(pObj) ) continue; // collect internal nodes Abc_MffcCollectNodes( &pObj, 1, vNodes ); // collect leaves Abc_MffcCollectLeaves( vNodes, vLeaves ); // add non-PI leaves Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pLeaf, k ) { if ( (fSkipPis && Abc_ObjIsCi(pLeaf)) || pLeaf->fMarkA ) continue; pLeaf->fMarkA = 1; Vec_PtrPush( vRoots, pLeaf ); } } Vec_PtrFree( vLeaves ); Vec_PtrFree( vNodes ); Abc_NtkCleanMarkA( pNtk ); return vRoots; } /**Function************************************************************* Synopsis [Collect fanout reachable root nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcCollectFanout_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts ) { Abc_Obj_t * pFanout; int i; if ( Abc_ObjIsCo(pObj) ) return; if ( Abc_ObjFanoutNum(pObj) > 64 ) return; if ( Abc_NodeIsTravIdCurrent(pObj) ) return; Abc_NodeSetTravIdCurrent(pObj); if ( pObj->fMarkA ) { if ( pObj->vFanouts.nSize > 0 ) Vec_PtrPush( vFanouts, pObj ); return; } Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_NktMffcCollectFanout_rec( pFanout, vFanouts ); } /**Function************************************************************* Synopsis [Collect fanout reachable root nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcCollectFanout( Abc_Obj_t ** pNodes, int nNodes, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vFanouts ) { Abc_Obj_t * pFanin, * pFanout; int i, k; // dereference nodes for ( i = 0; i < nNodes; i++ ) Abc_MffcDeref_rec( pNodes[i], NULL ); // collect fanouts Vec_PtrClear( vFanouts ); pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, 0 ); Abc_NtkIncrementTravId( pFanin->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pFanin, i ) Abc_ObjForEachFanout( pFanin, pFanout, k ) Abc_NktMffcCollectFanout_rec( pFanout, vFanouts ); // reference nodes for ( i = 0; i < nNodes; i++ ) Abc_MffcRef_rec( pNodes[i] ); } /**Function************************************************************* Synopsis [Grow one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NktMffcGrowOne( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppObjs, int nObjs, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vFanouts ) { Abc_Obj_t * pFanout, * pFanoutBest = NULL; double CostBest = 0.0; int i, k; Abc_MffcCollectNodes( ppObjs, nObjs, vNodes ); Abc_MffcCollectLeaves( vNodes, vLeaves ); // collect fanouts of all fanins Abc_NktMffcCollectFanout( ppObjs, nObjs, vLeaves, vFanouts ); // try different fanouts Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i ) { for ( k = 0; k < nObjs; k++ ) if ( pFanout == ppObjs[k] ) break; if ( k < nObjs ) continue; ppObjs[nObjs] = pFanout; Abc_MffcCollectNodes( ppObjs, nObjs+1, vNodes ); Abc_MffcCollectLeaves( vNodes, vLeaves ); if ( pFanoutBest == NULL || CostBest < 1.0 * Vec_PtrSize(vNodes)/Vec_PtrSize(vLeaves) ) { CostBest = 1.0 * Vec_PtrSize(vNodes)/Vec_PtrSize(vLeaves); pFanoutBest = pFanout; } } return pFanoutBest; } /**Function************************************************************* Synopsis [Procedure to increase MFF size by pairing nodes.] Description [For each node in the array vRoots, find a matching node, so that the ratio of nodes inside to the leaf nodes is maximized.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NktMffcGrowRoots( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) { Vec_Ptr_t * vRoots1, * vNodes, * vLeaves, * vFanouts; Abc_Obj_t * pObj, * pRoot2, * pNodes[2]; int i; Abc_NtkCleanMarkA( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) pObj->fMarkA = 1; vRoots1 = Vec_PtrAlloc( 100 ); vNodes = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); vFanouts = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { pNodes[0] = pObj; pRoot2 = Abc_NktMffcGrowOne( pNtk, pNodes, 1, vNodes, vLeaves, vFanouts ); Vec_PtrPush( vRoots1, pRoot2 ); } Vec_PtrFree( vNodes ); Vec_PtrFree( vLeaves ); Vec_PtrFree( vFanouts ); Abc_NtkCleanMarkA( pNtk ); return vRoots1; } /**Function************************************************************* Synopsis [Procedure to increase MFF size by pairing nodes.] Description [For each node in the array vRoots, find a matching node, so that the ratio of nodes inside to the leaf nodes is maximized.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NktMffcGrowRootsAgain( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Ptr_t * vRoots1 ) { Vec_Ptr_t * vRoots2, * vNodes, * vLeaves, * vFanouts; Abc_Obj_t * pObj, * pRoot2, * ppObjs[3]; int i; Abc_NtkCleanMarkA( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) pObj->fMarkA = 1; vRoots2 = Vec_PtrAlloc( 100 ); vNodes = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); vFanouts = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { ppObjs[0] = pObj; ppObjs[1] = (Abc_Obj_t *)Vec_PtrEntry( vRoots1, i ); if ( ppObjs[1] == NULL ) { Vec_PtrPush( vRoots2, NULL ); continue; } pRoot2 = Abc_NktMffcGrowOne( pNtk, ppObjs, 2, vNodes, vLeaves, vFanouts ); Vec_PtrPush( vRoots2, pRoot2 ); } Vec_PtrFree( vNodes ); Vec_PtrFree( vLeaves ); Vec_PtrFree( vFanouts ); Abc_NtkCleanMarkA( pNtk ); assert( Vec_PtrSize(vRoots) == Vec_PtrSize(vRoots2) ); return vRoots2; } /**Function************************************************************* Synopsis [Testbench.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcPrint( char * pFileName, Abc_Obj_t ** pNodes, int nNodes, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLeaves ) { FILE * pFile; Abc_Obj_t * pObj, * pFanin; int i, k; // convert the network Abc_NtkToSop( pNodes[0]->pNtk, -1, ABC_INFINITY ); // write the file pFile = fopen( pFileName, "wb" ); fprintf( pFile, ".model %s_part\n", pNodes[0]->pNtk->pName ); fprintf( pFile, ".inputs" ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) fprintf( pFile, " %s", Abc_ObjName(pObj) ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); for ( i = 0; i < nNodes; i++ ) fprintf( pFile, " %s", Abc_ObjName(pNodes[i]) ); fprintf( pFile, "\n" ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { fprintf( pFile, ".names" ); Abc_ObjForEachFanin( pObj, pFanin, k ) fprintf( pFile, " %s", Abc_ObjName(pFanin) ); fprintf( pFile, " %s", Abc_ObjName(pObj) ); fprintf( pFile, "\n%s", (char *)pObj->pData ); } fprintf( pFile, ".end\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Testbench.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcPrintInt( char * pFileName, Abc_Ntk_t * pNtk, Vec_Int_t * vRoots, Vec_Int_t * vNodes, Vec_Int_t * vLeaves ) { FILE * pFile; Abc_Obj_t * pObj, * pFanin; int i, k; // convert the network Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); // write the file pFile = fopen( pFileName, "wb" ); fprintf( pFile, ".model %s_part\n", pNtk->pName ); fprintf( pFile, ".inputs" ); Abc_NtkForEachObjVec( vLeaves, pNtk, pObj, i ) fprintf( pFile, " %s", Abc_ObjName(pObj) ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); Abc_NtkForEachObjVec( vRoots, pNtk, pObj, i ) fprintf( pFile, " %s", Abc_ObjName(pObj) ); fprintf( pFile, "\n" ); Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) { fprintf( pFile, ".names" ); Abc_ObjForEachFanin( pObj, pFanin, k ) fprintf( pFile, " %s", Abc_ObjName(pFanin) ); fprintf( pFile, " %s", Abc_ObjName(pObj) ); fprintf( pFile, "\n%s", (char *)pObj->pData ); } fprintf( pFile, ".end\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Testbench.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcTest( Abc_Ntk_t * pNtk ) { char pFileName[1000]; Vec_Ptr_t * vRoots, * vRoots1, * vRoots2, * vNodes, * vLeaves; Abc_Obj_t * pNodes[3], * pObj; int i, nNodes = 0, nNodes2 = 0; vRoots = Abc_NktMffcMarkRoots( pNtk, 1 ); vRoots1 = Abc_NktMffcGrowRoots( pNtk, vRoots ); vRoots2 = Abc_NktMffcGrowRootsAgain( pNtk, vRoots, vRoots1 ); vNodes = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { printf( "%6d : ", i ); Abc_MffcCollectNodes( &pObj, 1, vNodes ); Abc_MffcCollectLeaves( vNodes, vLeaves ); nNodes += Vec_PtrSize(vNodes); printf( "%6d ", Abc_ObjId(pObj) ); printf( "Vol =%3d ", Vec_PtrSize(vNodes) ); printf( "Cut =%3d ", Vec_PtrSize(vLeaves) ); if ( Vec_PtrSize(vLeaves) < 2 ) { printf( "\n" ); continue; } pNodes[0] = pObj; pNodes[1] = (Abc_Obj_t *)Vec_PtrEntry( vRoots1, i ); pNodes[2] = (Abc_Obj_t *)Vec_PtrEntry( vRoots2, i ); if ( pNodes[1] == NULL || pNodes[2] == NULL ) { printf( "\n" ); continue; } Abc_MffcCollectNodes( pNodes, 3, vNodes ); Abc_MffcCollectLeaves( vNodes, vLeaves ); nNodes2 += Vec_PtrSize(vNodes); printf( "%6d ", Abc_ObjId(pNodes[1]) ); printf( "%6d ", Abc_ObjId(pNodes[2]) ); printf( "Vol =%3d ", Vec_PtrSize(vNodes) ); printf( "Cut =%3d ", Vec_PtrSize(vLeaves) ); printf( "%4.2f ", 1.0 * Vec_PtrSize(vNodes)/Vec_PtrSize(vLeaves) ); printf( "\n" ); // generate file if ( Vec_PtrSize(vNodes) < 10 ) continue; sprintf( pFileName, "%s_mffc%04d_%02d.blif", Abc_NtkName(pNtk), Abc_ObjId(pObj), Vec_PtrSize(vNodes) ); Abc_NktMffcPrint( pFileName, pNodes, 3, vNodes, vLeaves ); } printf( "Total nodes = %d. Root nodes = %d. Mffc nodes = %d. Mffc nodes2 = %d.\n", Abc_NtkNodeNum(pNtk), Vec_PtrSize(vRoots), nNodes, nNodes2 ); Vec_PtrFree( vNodes ); Vec_PtrFree( vLeaves ); Vec_PtrFree( vRoots ); Vec_PtrFree( vRoots1 ); Vec_PtrFree( vRoots2 ); } /**Function************************************************************* Synopsis [Create the network of supernodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcTestSuper( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vRoots, * vFanins, * vFanouts, * vNodes, * vLeaves; Abc_Obj_t * pObj, * pFanin; Vec_Int_t * vCounts, * vNumbers, * vSizes, * vMarks; Vec_Int_t * vNode1, * vNode2; int i, k, Entry, nSizes; abctime clk = Abc_Clock(); vRoots = Abc_NktMffcMarkRoots( pNtk, 1 ); vFanins = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); vFanouts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); vCounts = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); vNode1 = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); vNode2 = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); vSizes = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); vMarks = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); // create fanins/fanouts Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { Vec_PtrWriteEntry( vFanins, Abc_ObjId(pObj), Vec_IntAlloc(8) ); Vec_PtrWriteEntry( vFanouts, Abc_ObjId(pObj), Vec_IntAlloc(8) ); } // add fanins/fanouts vNodes = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { Abc_MffcCollectNodes( &pObj, 1, vNodes ); Abc_MffcCollectLeaves( vNodes, vLeaves ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pFanin, k ) { if ( !Abc_ObjIsNode(pFanin) ) continue; Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vFanins, Abc_ObjId(pObj)), Abc_ObjId(pFanin) ); Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pFanin)), Abc_ObjId(pObj) ); // count how many times each object is a fanin Vec_IntAddToEntry( vCounts, Abc_ObjId(pFanin), 1 ); } Vec_IntWriteEntry( vSizes, Abc_ObjId(pObj), Vec_PtrSize(vNodes) ); } Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { Abc_MffcCollectNodes( &pObj, 1, vNodes ); Abc_MffcCollectLeaves( vNodes, vLeaves ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pFanin, k ) { if ( !Abc_ObjIsNode(pFanin) ) continue; if ( Vec_IntEntry(vCounts, Abc_ObjId(pFanin)) != 2 ) continue; if ( Vec_IntEntry(vNode1, Abc_ObjId(pFanin)) == 0 ) Vec_IntWriteEntry( vNode1, Abc_ObjId(pFanin), Abc_ObjId(pObj) ); else //if ( Vec_IntEntry(vNode2, Abc_ObjId(pFanin)) == 0 ) Vec_IntWriteEntry( vNode2, Abc_ObjId(pFanin), Abc_ObjId(pObj) ); Vec_IntWriteEntry( vMarks, Abc_ObjId(pFanin), 1 ); Vec_IntWriteEntry( vMarks, Abc_ObjId(pObj), 1 ); } } // count sizes nSizes = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { if ( Vec_IntEntry( vMarks, Abc_ObjId(pObj) ) ) nSizes += Vec_IntEntry( vSizes, Abc_ObjId(pObj) ); } printf( "Included = %6d. Total = %6d. (%6.2f %%)\n", nSizes, Abc_NtkNodeNum(pNtk), 100.0 * nSizes / Abc_NtkNodeNum(pNtk) ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { if ( Vec_IntEntry(vCounts, Abc_ObjId(pObj)) != 2 ) continue; printf( "%d ", Vec_IntEntry( vSizes, Abc_ObjId(pObj) ) + Vec_IntEntry( vSizes, Vec_IntEntry(vNode1, Abc_ObjId(pObj)) ) + Vec_IntEntry( vSizes, Vec_IntEntry(vNode2, Abc_ObjId(pObj)) ) ); } printf( "\n" ); // print how many times they appear vNumbers = Vec_IntStart( 32 ); Vec_IntForEachEntry( vCounts, Entry, i ) { /* if ( Entry == 2 ) { pObj = Abc_NtkObj( pNtk, i ); Abc_MffcCollectNodes( &pObj, 1, vNodes ); Abc_MffcCollectLeaves( vNodes, vLeaves ); printf( "%d(%d) ", Vec_PtrSize(vNodes), Vec_PtrSize(vLeaves) ); } */ if ( Entry == 0 ) continue; if ( Entry <= 10 ) Vec_IntAddToEntry( vNumbers, Entry, 1 ); else if ( Entry <= 100 ) Vec_IntAddToEntry( vNumbers, 10 + Entry/10, 1 ); else if ( Entry < 1000 ) Vec_IntAddToEntry( vNumbers, 20 + Entry/100, 1 ); else Vec_IntAddToEntry( vNumbers, 30, 1 ); } for ( i = 1; i <= 10; i++ ) if ( Vec_IntEntry(vNumbers,i) ) printf( " n = %4d %6d\n", i, Vec_IntEntry(vNumbers,i) ); for ( i = 11; i <= 20; i++ ) if ( Vec_IntEntry(vNumbers,i) ) printf( "%4d < n <= %4d %6d\n", 10*(i-10), 10*(i-9), Vec_IntEntry(vNumbers,i) ); for ( i = 21; i < 30; i++ ) if ( Vec_IntEntry(vNumbers,i) ) printf( "%4d < n <= %4d %6d\n", 100*(i-20), 100*(i-19), Vec_IntEntry(vNumbers,i) ); if ( Vec_IntEntry(vNumbers,31) ) printf( " n > 1000 %6d\n", Vec_IntEntry(vNumbers,30) ); printf( "Total MFFCs = %d. ", Vec_PtrSize(vRoots) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Vec_IntFree( vNumbers ); Vec_PtrFree( vNodes ); Vec_PtrFree( vLeaves ); // delete fanins/fanouts Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vFanins, Abc_ObjId(pObj)) ); Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pObj)) ); } Vec_IntFree( vCounts ); Vec_PtrFree( vFanouts ); Vec_PtrFree( vFanins ); Vec_PtrFree( vRoots ); } /**Function************************************************************* Synopsis [Collects the leaves and the roots of the window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffCollectLeafRoot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots ) { Abc_Obj_t * pObj, * pNext; int i, k; // mark Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->fMarkA = 1; // collect leaves Vec_PtrClear( vLeaves ); Abc_NtkIncrementTravId( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_ObjForEachFanin( pObj, pNext, k ) { if ( pNext->fMarkA || Abc_NodeIsTravIdCurrent(pNext) ) continue; Abc_NodeSetTravIdCurrent(pNext); Vec_PtrPush( vLeaves, pNext ); } // collect roots Vec_PtrClear( vRoots ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Abc_ObjForEachFanout( pObj, pNext, k ) if ( !pNext->fMarkA ) { Vec_PtrPush( vRoots, pObj ); break; } } // unmark Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->fMarkA = 0; } /**Function************************************************************* Synopsis [Collects the leaves and the roots of the window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffCollectLeafRootInt( Abc_Ntk_t * pNtk, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vRoots ) { Abc_Obj_t * pObj, * pNext; int i, k; // mark Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) pObj->fMarkA = 1; // collect leaves Vec_IntClear( vLeaves ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pNext, k ) { if ( pNext->fMarkA || Abc_NodeIsTravIdCurrent(pNext) ) continue; Abc_NodeSetTravIdCurrent(pNext); Vec_IntPush( vLeaves, Abc_ObjId(pNext) ); } // collect roots if ( vRoots ) { Vec_IntClear( vRoots ); Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) { Abc_ObjForEachFanout( pObj, pNext, k ) if ( !pNext->fMarkA ) { Vec_IntPush( vRoots, Abc_ObjId(pObj) ); break; } } } // unmark Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) pObj->fMarkA = 0; } /**Function************************************************************* Synopsis [Create the network of supernodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcTestIdeaOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) { Vec_Ptr_t * vNodes, * vLeaves, * vRoots, * vVolume; Vec_Ptr_t * vLeaves2, * vRoots2, * vVolume2; Abc_Obj_t * pNode, * pNodeBest = pObj; double Cost, CostBest = 0.0; int i, k; vNodes = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); vRoots = Vec_PtrAlloc( 100 ); vVolume = Vec_PtrAlloc( 100 ); vLeaves2 = Vec_PtrAlloc( 100 ); vRoots2 = Vec_PtrAlloc( 100 ); vVolume2 = Vec_PtrAlloc( 100 ); printf( "\n" ); for ( i = 1; i <= 16; i++ ) { Vec_PtrPush( vNodes, pNodeBest ); Abc_NktMffCollectLeafRoot( pNtk, vNodes, vLeaves, vRoots ); Abc_MffcCollectNodes( (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots), vVolume ); printf( "%2d : Node =%6d (%2d%3d) Cost =%6.2f ", i, Abc_ObjId(pNodeBest), Abc_ObjFaninNum(pNodeBest), Abc_ObjFanoutNum(pNodeBest), CostBest ); printf( "Leaf =%2d Root =%2d Vol =%2d\n", Vec_PtrSize(vLeaves), Vec_PtrSize(vRoots), Vec_PtrSize(vVolume) ); // try including different nodes pNodeBest = NULL; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, k ) { if ( !Abc_ObjIsNode(pNode) ) continue; Vec_PtrPush( vNodes, pNode ); Abc_NktMffCollectLeafRoot( pNtk, vNodes, vLeaves2, vRoots2 ); Abc_MffcCollectNodes( (Abc_Obj_t **)Vec_PtrArray(vRoots2), Vec_PtrSize(vRoots2), vVolume2 ); Cost = 1.0 * Vec_PtrSize(vVolume2) / (Vec_PtrSize(vLeaves2) + 3 * Vec_PtrSize(vRoots2)); if ( pNodeBest == NULL || CostBest < Cost ) { pNodeBest = pNode; CostBest = Cost; } Vec_PtrPop( vNodes ); } Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pNode, k ) { if ( Vec_PtrFind(vNodes, pNode) >= 0 ) continue; if ( !Abc_ObjIsNode(pNode) ) continue; Vec_PtrPush( vNodes, pNode ); Abc_NktMffCollectLeafRoot( pNtk, vNodes, vLeaves2, vRoots2 ); Abc_MffcCollectNodes( (Abc_Obj_t **)Vec_PtrArray(vRoots2), Vec_PtrSize(vRoots2), vVolume2 ); Cost = 1.0 * Vec_PtrSize(vVolume2) / (Vec_PtrSize(vLeaves2) + 3 * Vec_PtrSize(vRoots2)); if ( pNodeBest == NULL || CostBest < Cost ) { pNodeBest = pNode; CostBest = Cost; } Vec_PtrPop( vNodes ); } if ( pNodeBest == NULL ) break; } Vec_PtrFree( vNodes ); Vec_PtrFree( vLeaves ); Vec_PtrFree( vRoots ); Vec_PtrFree( vVolume ); Vec_PtrFree( vLeaves2 ); Vec_PtrFree( vRoots2 ); Vec_PtrFree( vVolume2 ); } /**Function************************************************************* Synopsis [Create the network of supernodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcTestIdea( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachNode( pNtk, pObj, i ) if ( Abc_ObjIsNode(pObj) && Abc_ObjId(pObj) % 100 == 0 ) Abc_NktMffcTestIdeaOne( pNtk, pObj ); } /**Function************************************************************* Synopsis [Creates MFFCs and their fanins/fanouts/volumes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NktMffcDerive( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvFanins, Vec_Ptr_t ** pvFanouts, Vec_Ptr_t ** pvVolumes ) { Vec_Ptr_t * vRoots, * vFanins, * vFanouts, * vVolumes, * vNodes, * vLeaves; Abc_Obj_t * pObj, * pFanin; int i, k; abctime clk = Abc_Clock(); // create roots vRoots = Abc_NktMffcMarkRoots( pNtk, 0 ); // create fanins/fanouts/volumes vFanins = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); vFanouts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); vVolumes = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { Vec_PtrWriteEntry( vFanins, Abc_ObjId(pObj), Vec_IntAlloc(8) ); Vec_PtrWriteEntry( vFanouts, Abc_ObjId(pObj), Vec_IntAlloc(8) ); Vec_PtrWriteEntry( vVolumes, Abc_ObjId(pObj), Vec_IntAlloc(8) ); } // add fanins/fanouts vNodes = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { if ( Abc_ObjIsCi(pObj) ) continue; Abc_MffcCollectNodes( &pObj, 1, vNodes ); Abc_MffcCollectLeaves( vNodes, vLeaves ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pFanin, k ) { Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vFanins, Abc_ObjId(pObj)), Abc_ObjId(pFanin) ); Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pFanin)), Abc_ObjId(pObj) ); } Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pFanin, k ) Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj)), Abc_ObjId(pFanin) ); } Vec_PtrFree( vNodes ); Vec_PtrFree( vLeaves ); // sort Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { Vec_IntSort( (Vec_Int_t *)Vec_PtrEntry(vFanins, Abc_ObjId(pObj)), 0 ); Vec_IntSort( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pObj)), 0 ); } // return *pvFanins = vFanins; *pvFanouts = vFanouts; *pvVolumes = vVolumes; return vRoots; } /**Function************************************************************* Synopsis [Frees MFFCs and their fanins/fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcFree( Vec_Ptr_t * vRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vFanouts, Vec_Ptr_t * vVolumes ) { Abc_Obj_t * pObj; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vFanins, Abc_ObjId(pObj)) ); Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vFanouts, Abc_ObjId(pObj)) ); Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj)) ); } Vec_PtrFree( vVolumes ); Vec_PtrFree( vFanouts ); Vec_PtrFree( vFanins ); Vec_PtrFree( vRoots ); } /**Function************************************************************* Synopsis [Returns the cost of two supports.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Abc_NktMffcCostTwo( Vec_Int_t * vSupp1, Vec_Int_t * vSupp2, int Volume, int Limit ) { int nCommon = Vec_IntTwoCountCommon( vSupp1, vSupp2 ); //printf( "s1=%2d s2=%2d c=%2d v=%2d ", Vec_IntSize(vSupp1), Vec_IntSize(vSupp2), nCommon, Volume ); if ( Vec_IntSize(vSupp1) + Vec_IntSize(vSupp2) - nCommon > Limit ) return (double)-ABC_INFINITY; return 0.6 * nCommon - 1.2 * Vec_IntSize(vSupp2) + 0.8 * Volume; } /**Function************************************************************* Synopsis [Returns support of the group.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NktMffcSupport( Vec_Ptr_t * vThis, Vec_Ptr_t * vFanins ) { Vec_Int_t * vIns, * vIns2, * vTemp; Abc_Obj_t * pObj; int i; vIns = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vThis, pObj, i ) { vIns2 = (Vec_Int_t *)Vec_PtrEntry( vFanins, Abc_ObjId(pObj) ); vIns = Vec_IntTwoMerge( vTemp = vIns, vIns2 ); Vec_IntFree( vTemp ); } return vIns; } /**Function************************************************************* Synopsis [Returns the best merger for the cluster of given node (pPivot).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NktMffcFindBest( Abc_Ntk_t * pNtk, Vec_Int_t * vMarks, Vec_Int_t * vIns, Vec_Ptr_t * vFanins, Vec_Ptr_t * vFanouts, Vec_Ptr_t * vVolumes, int Limit ) { Vec_Int_t * vIns2, * vOuts, * vOuts2, * vTemp; Abc_Obj_t * pPivot2, * pObj, * pObjBest = NULL; double Cost, CostBest = (double)-ABC_INFINITY; int i, Volume; // collect the fanouts of the fanins vOuts = Vec_IntAlloc( 100 ); Abc_NtkForEachObjVec( vIns, pNtk, pObj, i ) { vOuts2 = (Vec_Int_t *)Vec_PtrEntry( vFanouts, Abc_ObjId(pObj) ); if ( Vec_IntSize(vOuts2) > 16 ) continue; vOuts = Vec_IntTwoMerge( vTemp = vOuts, vOuts2 ); Vec_IntFree( vTemp ); } // check the pairs Abc_NtkForEachObjVec( vOuts, pNtk, pPivot2, i ) { if ( Vec_IntEntry(vMarks, Abc_ObjId(pPivot2)) == 0 ) continue; vIns2 = (Vec_Int_t *)Vec_PtrEntry( vFanins, Abc_ObjId(pPivot2) ); Volume = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pPivot2))); Cost = Abc_NktMffcCostTwo( vIns, vIns2, Volume, Limit ); //printf( "%5d %2d\n", Abc_ObjId(pPivot2), Cost ); if ( Cost == (double)-ABC_INFINITY ) continue; if ( pObjBest == NULL || CostBest < Cost ) { pObjBest = pPivot2; CostBest = Cost; } } //printf( "Choosing %d\n", pObjBest->Id ); Vec_IntFree( vOuts ); return pObjBest; } /**Function************************************************************* Synopsis [Processes one cluster.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NktMffcSaveOne( Vec_Ptr_t * vThis, Vec_Ptr_t * vVolumes ) { Vec_Int_t * vVolume, * vResult; Abc_Obj_t * pObj; int i, k, Entry; vResult = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vThis, pObj, i ) { vVolume = (Vec_Int_t *)Vec_PtrEntry( vVolumes, Abc_ObjId(pObj) ); Vec_IntForEachEntry( vVolume, Entry, k ) Vec_IntPush( vResult, Entry ); } return vResult; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareVolumeDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { int Diff = Abc_ObjRegular(*pp1)->iTemp - Abc_ObjRegular(*pp2)->iTemp; 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 [Create the network of supernodes.] Description [Returns array of interger arrays of IDs of nodes included in a disjoint structural decomposition of the network.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NktMffcServer( Abc_Ntk_t * pNtk, int nInMax, int nOutMax ) { Vec_Ptr_t * vResult, * vThis; Vec_Ptr_t * vPivots, * vFanins, * vFanouts, * vVolumes; Vec_Int_t * vLeaves, * vMarks; Abc_Obj_t * pObj, * pObj2; int i, k; assert( nOutMax >= 1 && nOutMax <= 32 ); vResult = Vec_PtrAlloc( 100 ); // create fanins/fanouts vPivots = Abc_NktMffcDerive( pNtk, &vFanins, &vFanouts, &vVolumes ); // sort by their MFFC size Vec_PtrForEachEntry( Abc_Obj_t *, vPivots, pObj, i ) pObj->iTemp = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj))); Vec_PtrSort( vPivots, (int (*)(void))Abc_NodeCompareVolumeDecrease ); // create marks vMarks = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); Vec_PtrForEachEntry( Abc_Obj_t *, vPivots, pObj, i ) if ( Abc_ObjIsNode(pObj) && Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vVolumes, Abc_ObjId(pObj))) > 1 ) Vec_IntWriteEntry( vMarks, Abc_ObjId(pObj), 1 ); // consider nodes in the order of the marks vThis = Vec_PtrAlloc( 10 ); // while ( 1 ) Vec_PtrForEachEntry( Abc_Obj_t *, vPivots, pObj, i ) { // pObj = Abc_NtkObj( pNtk, 589 ); if ( Vec_IntEntry(vMarks, Abc_ObjId(pObj)) == 0 ) continue; // start the set Vec_PtrClear( vThis ); Vec_PtrPush( vThis, pObj ); Vec_IntWriteEntry( vMarks, Abc_ObjId(pObj), 0 ); // quit if exceeded the limit vLeaves = (Vec_Int_t *)Vec_PtrEntry( vFanins, Abc_ObjId(pObj) ); if ( Vec_IntSize(vLeaves) > nInMax ) { Vec_PtrPush( vResult, Abc_NktMffcSaveOne(vThis, vVolumes) ); continue; } // try adding one node at a time for ( k = 1; k < nOutMax; k++ ) { // quit if exceeded the limit vLeaves = Abc_NktMffcSupport( vThis, vFanins ); assert( Vec_IntSize(vLeaves) <= nInMax ); pObj2 = Abc_NktMffcFindBest( pNtk, vMarks, vLeaves, vFanins, vFanouts, vVolumes, nInMax ); Vec_IntFree( vLeaves ); // quit if there is no extension if ( pObj2 == NULL ) break; Vec_PtrPush( vThis, pObj2 ); Vec_IntWriteEntry( vMarks, Abc_ObjId(pObj2), 0 ); } Vec_PtrPush( vResult, Abc_NktMffcSaveOne(vThis, vVolumes) ); // break; } Vec_PtrFree( vThis ); Vec_IntFree( vMarks ); // delele fanins/outputs Abc_NktMffcFree( vPivots, vFanins, vFanouts, vVolumes ); return vResult; } /**Function************************************************************* Synopsis [Testbench.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NktMffcServerTest( Abc_Ntk_t * pNtk ) { char pFileName[1000]; Vec_Ptr_t * vGlobs; Vec_Int_t * vGlob, * vLeaves, * vRoots; double Cost, CostAll = 0.0; int i, k, Entry, nNodes = 0; abctime clk = Abc_Clock(); vGlobs = Abc_NktMffcServer( pNtk, 18, 3 ); vLeaves = Vec_IntAlloc( 100 ); vRoots = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( Vec_Int_t *, vGlobs, vGlob, i ) { nNodes += Vec_IntSize(vGlob); Abc_NktMffCollectLeafRootInt( pNtk, vGlob, vLeaves, vRoots ); if ( Vec_IntSize(vGlob) <= Vec_IntSize(vRoots) ) continue; Cost = 1.0 * Vec_IntSize(vGlob)/(Vec_IntSize(vLeaves) + Vec_IntSize(vRoots)); CostAll += Cost; if ( Cost < 0.5 ) continue; printf( "%6d : Root =%3d. Leaf =%3d. Node =%4d. ", i, Vec_IntSize(vRoots), Vec_IntSize(vLeaves), Vec_IntSize(vGlob) ); printf( "Cost =%6.2f ", Cost ); Vec_IntForEachEntry( vRoots, Entry, k ) printf( "%d ", Entry ); printf( "\n" ); sprintf( pFileName, "%sc%04di%02dn%02d.blif", Abc_NtkName(pNtk), i, Vec_IntSize(vLeaves), Vec_IntSize(vGlob) ); Abc_NktMffcPrintInt( pFileName, pNtk, vRoots, vGlob, vLeaves ); } Vec_IntFree( vLeaves ); Vec_IntFree( vRoots ); Vec_PtrForEachEntry( Vec_Int_t *, vGlobs, vGlob, i ) Vec_IntFree( vGlob ); Vec_PtrFree( vGlobs ); printf( "Total = %6d. Nodes = %6d. ", Abc_NtkNodeNum(pNtk), nNodes ); printf( "Cost = %6.2f ", CostAll ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } ABC_NAMESPACE_IMPL_END //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMfs.c000066400000000000000000000376611300674244400232200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMfs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Optimization with don't-cares.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "bool/kit/kit.h" #include "opt/sfm/sfm.h" #include "base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkAssignIDs( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; vNodes = Abc_NtkDfs( pNtk, 0 ); Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = i; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->iTemp = Abc_NtkCiNum(pNtk) + i; Abc_NtkForEachCo( pNtk, pObj, i ) pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + i; return vNodes; } Vec_Ptr_t * Abc_NtkAssignIDs2( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = i; vNodes = Vec_PtrAlloc( Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) { pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes); Vec_PtrPush( vNodes, pObj ); } assert( Vec_PtrSize(vNodes) == Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + i; return vNodes; } /**Function************************************************************* Synopsis [Extracts information about the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sfm_Ntk_t * Abc_NtkExtractMfs( Abc_Ntk_t * pNtk, int nFirstFixed ) { Vec_Ptr_t * vNodes; Vec_Wec_t * vFanins; Vec_Str_t * vFixed; Vec_Wrd_t * vTruths; Vec_Int_t * vArray; Abc_Obj_t * pObj, * pFanin; int i, k, nObjs; vNodes = nFirstFixed ? Abc_NtkAssignIDs2(pNtk) : Abc_NtkAssignIDs(pNtk); nObjs = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + Abc_NtkCoNum(pNtk); vFanins = Vec_WecStart( nObjs ); vFixed = Vec_StrStart( nObjs ); vTruths = Vec_WrdStart( nObjs ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { word uTruth = Abc_SopToTruth((char *)pObj->pData, Abc_ObjFaninNum(pObj)); Vec_WrdWriteEntry( vTruths, pObj->iTemp, uTruth ); if ( uTruth == 0 || ~uTruth == 0 ) continue; vArray = Vec_WecEntry( vFanins, pObj->iTemp ); Vec_IntGrow( vArray, Abc_ObjFaninNum(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vArray, pFanin->iTemp ); } Abc_NtkForEachCo( pNtk, pObj, i ) { vArray = Vec_WecEntry( vFanins, pObj->iTemp ); Vec_IntGrow( vArray, Abc_ObjFaninNum(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vArray, pFanin->iTemp ); } Vec_PtrFree( vNodes ); for ( i = Abc_NtkCiNum(pNtk); i < Abc_NtkCiNum(pNtk) + nFirstFixed; i++ ) Vec_StrWriteEntry( vFixed, i, (char)1 ); // update fixed assert( nFirstFixed >= 0 && nFirstFixed < Abc_NtkNodeNum(pNtk) ); // for ( i = Abc_NtkCiNum(pNtk); i + Abc_NtkCoNum(pNtk) < Abc_NtkObjNum(pNtk); i++ ) // if ( rand() % 10 == 0 ) // Vec_StrWriteEntry( vFixed, i, (char)1 ); return Sfm_NtkConstruct( vFanins, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), vFixed, NULL, vTruths ); } Sfm_Ntk_t * Abc_NtkExtractMfs2( Abc_Ntk_t * pNtk, int iPivot ) { Vec_Ptr_t * vNodes; Vec_Wec_t * vFanins; Vec_Str_t * vFixed; Vec_Wrd_t * vTruths; Vec_Int_t * vArray; Abc_Obj_t * pObj, * pFanin; int i, k, nObjs; vNodes = Abc_NtkAssignIDs2(pNtk); nObjs = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + Abc_NtkCoNum(pNtk); vFanins = Vec_WecStart( nObjs ); vFixed = Vec_StrStart( nObjs ); vTruths = Vec_WrdStart( nObjs ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { word uTruth = Abc_SopToTruth((char *)pObj->pData, Abc_ObjFaninNum(pObj)); Vec_WrdWriteEntry( vTruths, pObj->iTemp, uTruth ); if ( uTruth == 0 || ~uTruth == 0 ) continue; vArray = Vec_WecEntry( vFanins, pObj->iTemp ); Vec_IntGrow( vArray, Abc_ObjFaninNum(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vArray, pFanin->iTemp ); } Abc_NtkForEachCo( pNtk, pObj, i ) { vArray = Vec_WecEntry( vFanins, pObj->iTemp ); Vec_IntGrow( vArray, Abc_ObjFaninNum(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vArray, pFanin->iTemp ); } Vec_PtrFree( vNodes ); // set fixed attributes Abc_NtkForEachNode( pNtk, pObj, i ) if ( i >= iPivot ) Vec_StrWriteEntry( vFixed, pObj->iTemp, (char)1 ); return Sfm_NtkConstruct( vFanins, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), vFixed, NULL, vTruths ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkInsertMfs( Abc_Ntk_t * pNtk, Sfm_Ntk_t * p ) { Vec_Int_t * vCover, * vMap, * vArray; Abc_Obj_t * pNode; word * pTruth; int i, k, Fanin; // map new IDs into old nodes vMap = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachCi( pNtk, pNode, i ) Vec_IntWriteEntry( vMap, pNode->iTemp, Abc_ObjId(pNode) ); Abc_NtkForEachNode( pNtk, pNode, i ) if ( pNode->iTemp > 0 ) Vec_IntWriteEntry( vMap, pNode->iTemp, Abc_ObjId(pNode) ); // remove old fanins Abc_NtkForEachNode( pNtk, pNode, i ) if ( !Sfm_NodeReadFixed(p, pNode->iTemp) ) Abc_ObjRemoveFanins( pNode ); // create new fanins vCover = Vec_IntAlloc( 1 << 16 ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( pNode->iTemp == 0 || Sfm_NodeReadFixed(p, pNode->iTemp) ) continue; if ( !Sfm_NodeReadUsed(p, pNode->iTemp) ) { Abc_NtkDeleteObj( pNode ); continue; } // update fanins vArray = Sfm_NodeReadFanins( p, pNode->iTemp ); Vec_IntForEachEntry( vArray, Fanin, k ) Abc_ObjAddFanin( pNode, Abc_NtkObj(pNtk, Vec_IntEntry(vMap, Fanin)) ); // update function pTruth = Sfm_NodeReadTruth( p, pNode->iTemp ); if ( pTruth[0] == 0 ) pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ); else if ( ~pTruth[0] == 0 ) pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" ); else { int RetValue = Kit_TruthIsop( (unsigned *)pTruth, Vec_IntSize(vArray), vCover, 1 ); assert( Vec_IntSize(vArray) > 0 ); assert( RetValue == 0 || RetValue == 1 ); pNode->pData = Abc_SopCreateFromIsop( (Mem_Flex_t *)pNtk->pManFunc, Vec_IntSize(vArray), vCover ); if ( RetValue ) Abc_SopComplement( (char *)pNode->pData ); } assert( Abc_SopGetVarNum((char *)pNode->pData) == Vec_IntSize(vArray) ); } Vec_IntFree( vCover ); Vec_IntFree( vMap ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkPerformMfs( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ) { Sfm_Ntk_t * p; int nFaninMax, nNodes; assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkSweep( pNtk, 0 ); // count fanouts nFaninMax = Abc_NtkGetFaninMax( pNtk ); if ( nFaninMax > 6 ) { Abc_Print( 1, "Currently \"mfs\" cannot process the network containing nodes with more than 6 fanins.\n" ); return 0; } if ( !Abc_NtkHasSop(pNtk) ) if ( !Abc_NtkToSop( pNtk, -1, ABC_INFINITY ) ) { printf( "Conversion to SOP has failed due to low resource limit.\n" ); return 0; } // collect information p = Abc_NtkExtractMfs( pNtk, pPars->nFirstFixed ); // perform optimization nNodes = Sfm_NtkPerform( p, pPars ); if ( nNodes == 0 ) { // Abc_Print( 1, "The network is not changed by \"mfs\".\n" ); } else { Abc_NtkInsertMfs( pNtk, p ); if( pPars->fVerbose ) Abc_Print( 1, "The network has %d nodes changed by \"mfs\".\n", nNodes ); } Sfm_NtkFree( p ); return 1; } /**Function************************************************************* Synopsis [Unrolls logic network while dropping some next-state functions.] Description [Returns the unrolled network.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkUnrollAndDrop( Abc_Ntk_t * p, int nFrames, int nFramesAdd, Vec_Int_t * vFlops, int * piPivot ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pFanin, * pNode; Vec_Ptr_t * vNodes; int i, k, f, Value; assert( nFramesAdd >= 0 ); assert( Abc_NtkIsLogic(p) ); assert( Vec_IntSize(vFlops) == Abc_NtkLatchNum(p) ); *piPivot = -1; // start the network pNtk = Abc_NtkAlloc( p->ntkType, p->ntkFunc, 1 ); pNtk->pName = Extra_UtilStrsav(Abc_NtkName(p)); // add CIs for the new network Abc_NtkForEachCi( p, pNode, i ) pNode->pCopy = Abc_NtkCreatePi( pNtk ); // iterate unrolling vNodes = Abc_NtkDfs( p, 0 ); for ( f = 0; f <= nFrames + nFramesAdd; f++ ) { if ( f > 0 ) { Abc_NtkForEachPi( p, pNode, i ) pNode->pCopy = Abc_NtkCreatePi( pNtk ); } Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { Abc_NtkDupObj( pNtk, pNode, 0 ); Abc_ObjForEachFanin( pNode, pFanin, k ) Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); } Abc_NtkForEachCo( p, pNode, i ) pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy; Abc_NtkForEachPo( p, pNode, i ) Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNode->pCopy ); // add buffers if ( f == 0 ) { *piPivot = Abc_NtkObjNum(pNtk); // Abc_NtkForEachLatchInput( p, pNode, i ) // pNode->pCopy = Abc_NtkCreateNodeBuf( pNtk, pNode->pCopy ); } // transfer to flop outputs Abc_NtkForEachLatch( p, pNode, i ) Abc_ObjFanout0(pNode)->pCopy = Abc_ObjFanin0(pNode)->pCopy; // add final POs if ( f > nFramesAdd ) { Vec_IntForEachEntry( vFlops, Value, i ) { if ( Value == 0 ) continue; pNode = Abc_NtkCo( p, Abc_NtkPoNum(p) + i ); Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNode->pCopy ); } } } Vec_PtrFree( vNodes ); Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); // perform combinational cleanup Abc_NtkCleanup( pNtk, 0 ); if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); return pNtk; } /**Function************************************************************* Synopsis [Updates the original network to include optimized nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkReinsertNodes( Abc_Ntk_t * p, Abc_Ntk_t * pNtk, int iPivot ) { Abc_Obj_t * pNode, * pNodeNew, * pFaninNew; Vec_Ptr_t * vNodes; int i, k; assert( Abc_NtkIsLogic(p) ); assert( Abc_NtkCiNum(p) <= Abc_NtkCiNum(pNtk) ); vNodes = Abc_NtkDfs( p, 0 ); // clean old network Abc_NtkCleanCopy( p ); Abc_NtkForEachNode( p, pNode, i ) { Abc_ObjRemoveFanins( pNode ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pManFunc, (char *)" 0\n" ); } // map CIs Abc_NtkForEachCi( p, pNode, i ) Abc_NtkCi(pNtk, i)->pCopy = pNode; // map internal nodes assert( Vec_PtrSize(vNodes) + Abc_NtkCiNum(p) + Abc_NtkPoNum(p) == iPivot ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { pNodeNew = Abc_NtkObj( pNtk, Abc_NtkCiNum(p) + i + 1 ); if ( pNodeNew == NULL ) continue; pNodeNew->pCopy = pNode; } // connect internal nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { pNodeNew = Abc_NtkObj( pNtk, Abc_NtkCiNum(p) + i + 1 ); if ( pNodeNew == NULL ) continue; assert( pNodeNew->pCopy == pNode ); Abc_ObjForEachFanin( pNodeNew, pFaninNew, k ) Abc_ObjAddFanin( pNodeNew->pCopy, pFaninNew->pCopy ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pManFunc, (char *)pNodeNew->pData ); } Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Performs MFS for the unrolled network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsAfterICheck( Abc_Ntk_t * p, int nFrames, int nFramesAdd, Vec_Int_t * vFlops, Sfm_Par_t * pPars ) { Sfm_Ntk_t * pp; int nFaninMax, nNodes; Abc_Ntk_t * pNtk; int iPivot; assert( Abc_NtkIsLogic(p) ); // count fanouts nFaninMax = Abc_NtkGetFaninMax( p ); if ( nFaninMax > 6 ) { Abc_Print( 1, "Currently \"mfs\" cannot process the network containing nodes with more than 6 fanins.\n" ); return 0; } if ( !Abc_NtkHasSop(p) ) Abc_NtkToSop( p, -1, ABC_INFINITY ); // derive unfolded network pNtk = Abc_NtkUnrollAndDrop( p, nFrames, nFramesAdd, vFlops, &iPivot ); Io_WriteBlifLogic( pNtk, "unroll_dump.blif", 0 ); // collect information pp = Abc_NtkExtractMfs2( pNtk, iPivot ); // perform optimization nNodes = Sfm_NtkPerform( pp, pPars ); if ( nNodes == 0 ) { // Abc_Print( 1, "The network is not changed by \"mfs\".\n" ); } else { Abc_NtkInsertMfs( pNtk, pp ); if( pPars->fVerbose ) Abc_Print( 1, "The network has %d nodes changed by \"mfs\".\n", nNodes ); Abc_NtkReinsertNodes( p, pNtk, iPivot ); } Abc_NtkDelete( pNtk ); Sfm_NtkFree( pp ); // perform final sweep Abc_NtkSweep( p, 0 ); if ( !Abc_NtkHasSop(p) ) Abc_NtkToSop( p, -1, ABC_INFINITY ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMini.c000066400000000000000000000170611300674244400233570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMini.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface to the minimalistic AIG package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "aig/miniaig/miniaig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFanin0Copy( Abc_Ntk_t * pNtk, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id ) { int Lit = Mini_AigNodeFanin0( p, Id ); int AbcLit = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); return Abc_ObjFromLit( pNtk, AbcLit ); } Abc_Obj_t * Abc_NodeFanin1Copy( Abc_Ntk_t * pNtk, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id ) { int Lit = Mini_AigNodeFanin1( p, Id ); int AbcLit = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); return Abc_ObjFromLit( pNtk, AbcLit ); } Abc_Ntk_t * Abc_NtkFromMiniAig( Mini_Aig_t * p ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pObj; Vec_Int_t * vCopies; int i, nNodes; // get the number of nodes nNodes = Mini_AigNodeNum(p); // create ABC network pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtk->pName = Abc_UtilStrsav( "MiniAig" ); // create mapping from MiniAIG objects into ABC objects vCopies = Vec_IntAlloc( nNodes ); Vec_IntPush( vCopies, Abc_LitNot(Abc_ObjToLit(Abc_AigConst1(pNtk))) ); // iterate through the objects for ( i = 1; i < nNodes; i++ ) { if ( Mini_AigNodeIsPi( p, i ) ) pObj = Abc_NtkCreatePi(pNtk); else if ( Mini_AigNodeIsPo( p, i ) ) Abc_ObjAddFanin( (pObj = Abc_NtkCreatePo(pNtk)), Abc_NodeFanin0Copy(pNtk, vCopies, p, i) ); else if ( Mini_AigNodeIsAnd( p, i ) ) pObj = Abc_AigAnd((Abc_Aig_t *)pNtk->pManFunc, Abc_NodeFanin0Copy(pNtk, vCopies, p, i), Abc_NodeFanin1Copy(pNtk, vCopies, p, i)); else assert( 0 ); Vec_IntPush( vCopies, Abc_ObjToLit(pObj) ); } assert( Vec_IntSize(vCopies) == nNodes ); Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); Vec_IntFree( vCopies ); Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" ); // add latches if ( Mini_AigRegNum(p) > 0 ) { extern Abc_Ntk_t * Abc_NtkRestrashWithLatches( Abc_Ntk_t * pNtk, int nLatches ); Abc_Ntk_t * pTemp; pNtk = Abc_NtkRestrashWithLatches( pTemp = pNtk, Mini_AigRegNum(p) ); Abc_NtkDelete( pTemp ); } return pNtk; } /**Function************************************************************* Synopsis [Converts the network from ABC into the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeFanin0Copy2( Abc_Obj_t * pObj ) { return Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, Abc_ObjFaninC0(pObj) ); } int Abc_NodeFanin1Copy2( Abc_Obj_t * pObj ) { return Abc_LitNotCond( Abc_ObjFanin1(pObj)->iTemp, Abc_ObjFaninC1(pObj) ); } Mini_Aig_t * Abc_NtkToMiniAig( Abc_Ntk_t * pNtk ) { Mini_Aig_t * p; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsStrash(pNtk) ); // create the manager p = Mini_AigStart(); // create mapping from MiniAIG into ABC objects Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->iTemp = Mini_AigLitConst1(); // create primary inputs Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = Mini_AigCreatePi(p); // create internal nodes Abc_NtkForEachNode( pNtk, pObj, i ) pObj->iTemp = Mini_AigAnd( p, Abc_NodeFanin0Copy2(pObj), Abc_NodeFanin1Copy2(pObj) ); // create primary outputs Abc_NtkForEachCo( pNtk, pObj, i ) pObj->iTemp = Mini_AigCreatePo( p, Abc_NodeFanin0Copy2(pObj) ); // set registers Mini_AigSetRegNum( p, Abc_NtkLatchNum(pNtk) ); return p; } /**Function************************************************************* Synopsis [Procedures to update internal ABC network using AIG node array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkInputMiniAig( Abc_Frame_t * pAbc, void * p ) { Abc_Ntk_t * pNtk; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pNtk = Abc_NtkFromMiniAig( (Mini_Aig_t *)p ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); // Abc_NtkDelete( pNtk ); } void * Abc_NtkOutputMiniAig( Abc_Frame_t * pAbc ) { Abc_Ntk_t * pNtk; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pNtk = Abc_FrameReadNtk( pAbc ); if ( pNtk == NULL ) printf( "Current network in ABC framework is not defined.\n" ); return Abc_NtkToMiniAig( pNtk ); } void Abc_NtkSetFlopNum( Abc_Frame_t * pAbc, int nFlops ) { extern void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nFlops ); Abc_Ntk_t * pNtk; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pNtk = Abc_FrameReadNtk( pAbc ); if ( pNtk == NULL ) printf( "Current network in ABC framework is not defined.\n" ); Abc_NtkMakeSeq( pNtk, nFlops ); } /**Function************************************************************* Synopsis [Testing the above code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMiniAigTest( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Mini_Aig_t * p; p = Abc_NtkToMiniAig( pNtk ); pNtkNew = Abc_NtkFromMiniAig( p ); Mini_AigStop( p ); Abc_NtkPrintStats( pNtkNew, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); Abc_NtkDelete( pNtkNew ); // test dumping p = Abc_NtkToMiniAig( pNtk ); Mini_AigDump( p, "miniaig.data" ); Mini_AigPrintStats( p ); Mini_AigStop( p ); p = Mini_AigLoad( "miniaig.data" ); Mini_AigPrintStats( p ); Mini_AigStop( p ); } /* if ( pNtk ) { extern void Abc_NtkMiniAigTest( Abc_Ntk_t * pNtk ); Abc_NtkMiniAigTest( pNtk ); } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMiter.c000066400000000000000000001163311300674244400235430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMiter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to derive the miter of two circuits.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti ); static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fMulti ); static void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ); static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fImplic, int fMulti ); static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame ); // to be exported typedef void (*AddFrameMapping)( Abc_Obj_t*, Abc_Obj_t*, int, void*); extern Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ); static void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the miter of two networks.] Description [Preprocesses the networks to make sure that they are strashed.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti ) { Abc_Ntk_t * pTemp = NULL; int fRemove1, fRemove2; assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); // check that the networks have the same PIs/POs/latches if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, fImplic, fComb ) ) return NULL; // make sure the circuits are strashed fRemove1 = (!Abc_NtkIsStrash(pNtk1) || Abc_NtkGetChoiceNum(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0)); fRemove2 = (!Abc_NtkIsStrash(pNtk2) || Abc_NtkGetChoiceNum(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0)); if ( pNtk1 && pNtk2 ) pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize, fImplic, fMulti ); if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); return pTemp; } /**Function************************************************************* Synopsis [Derives the miter of two sequential networks.] Description [Assumes that the networks are strashed.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti ) { char Buffer[1000]; Abc_Ntk_t * pNtkMiter; assert( Abc_NtkIsStrash(pNtk1) ); assert( Abc_NtkIsStrash(pNtk2) ); // start the new network pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); pNtkMiter->pName = Extra_UtilStrsav(Buffer); // perform strashing Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize, fMulti ); Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize, fImplic, fMulti ); Abc_AigCleanup((Abc_Aig_t *)pNtkMiter->pManFunc); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkMiter ) ) { printf( "Abc_NtkMiter: The network check has failed.\n" ); Abc_NtkDelete( pNtkMiter ); return NULL; } return pNtkMiter; } /**Function************************************************************* Synopsis [Prepares the network for mitering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fMulti ) { Abc_Obj_t * pObj, * pObjNew; int i; // clean the copy field in all objects // Abc_NtkCleanCopy( pNtk1 ); // Abc_NtkCleanCopy( pNtk2 ); Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter); Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter); if ( fComb ) { // create new PIs and remember them in the old PIs Abc_NtkForEachCi( pNtk1, pObj, i ) { pObjNew = Abc_NtkCreatePi( pNtkMiter ); // remember this PI in the old PIs pObj->pCopy = pObjNew; pObj = Abc_NtkCi(pNtk2, i); pObj->pCopy = pObjNew; // add name Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } if ( nPartSize <= 0 ) { // create POs if ( fMulti ) { Abc_NtkForEachCo( pNtk1, pObj, i ) { pObjNew = Abc_NtkCreatePo( pNtkMiter ); Abc_ObjAssignName( pObjNew, "miter", Abc_ObjName(pObjNew) ); } } else { pObjNew = Abc_NtkCreatePo( pNtkMiter ); Abc_ObjAssignName( pObjNew, "miter", NULL ); } } } else { // create new PIs and remember them in the old PIs Abc_NtkForEachPi( pNtk1, pObj, i ) { pObjNew = Abc_NtkCreatePi( pNtkMiter ); // remember this PI in the old PIs pObj->pCopy = pObjNew; pObj = Abc_NtkPi(pNtk2, i); pObj->pCopy = pObjNew; // add name Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } if ( nPartSize <= 0 ) { // create POs if ( fMulti ) { Abc_NtkForEachPo( pNtk1, pObj, i ) { pObjNew = Abc_NtkCreatePo( pNtkMiter ); Abc_ObjAssignName( pObjNew, "miter", Abc_ObjName(pObjNew) ); } } else { pObjNew = Abc_NtkCreatePo( pNtkMiter ); Abc_ObjAssignName( pObjNew, "miter", NULL ); } } // create the latches Abc_NtkForEachLatch( pNtk1, pObj, i ) { pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); // add names Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_1" ); Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_1" ); Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_1" ); } Abc_NtkForEachLatch( pNtk2, pObj, i ) { pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); // add name Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_2" ); Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_2" ); Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_2" ); } } } /**Function************************************************************* Synopsis [Performs mitering for one network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ) { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsDfsOrdered(pNtk) ); Abc_AigForEachAnd( pNtk, pNode, i ) pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } /**Function************************************************************* Synopsis [Performs mitering for one network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int i; // map the constant nodes Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter); // perform strashing vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) if ( Abc_AigNodeIsAnd(pNode) ) pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Finalizes the miter by adding the output part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fImplic, int fMulti ) { Vec_Ptr_t * vPairs; Abc_Obj_t * pMiter, * pNode; int i; assert( nPartSize == 0 || fMulti == 0 ); // collect the PO pairs from both networks vPairs = Vec_PtrAlloc( 100 ); if ( fComb ) { // collect the CO nodes for the miter Abc_NtkForEachCo( pNtk1, pNode, i ) { if ( fMulti ) { pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild0Copy(Abc_NtkCo(pNtk2, i)) ); Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,i), pMiter ); } else { Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); pNode = Abc_NtkCo( pNtk2, i ); Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); } } } else { // collect the PO nodes for the miter Abc_NtkForEachPo( pNtk1, pNode, i ) { if ( fMulti ) { pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild0Copy(Abc_NtkCo(pNtk2, i)) ); Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,i), pMiter ); } else { Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); pNode = Abc_NtkPo( pNtk2, i ); Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); } } // connect new latches Abc_NtkForEachLatch( pNtk1, pNode, i ) Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); Abc_NtkForEachLatch( pNtk2, pNode, i ) Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); } // add the miter if ( nPartSize <= 0 ) { if ( !fMulti ) { pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairs, fImplic ); Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); } } else { char Buffer[1024]; Vec_Ptr_t * vPairsPart; int nParts, i, k, iCur; assert( Vec_PtrSize(vPairs) == 2 * Abc_NtkCoNum(pNtk1) ); // create partitions nParts = Abc_NtkCoNum(pNtk1) / nPartSize + (int)((Abc_NtkCoNum(pNtk1) % nPartSize) > 0); vPairsPart = Vec_PtrAlloc( nPartSize ); for ( i = 0; i < nParts; i++ ) { Vec_PtrClear( vPairsPart ); for ( k = 0; k < nPartSize; k++ ) { iCur = i * nPartSize + k; if ( iCur >= Abc_NtkCoNum(pNtk1) ) break; Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur ) ); Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur+1) ); } pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkMiter->pManFunc, vPairsPart, fImplic ); pNode = Abc_NtkCreatePo( pNtkMiter ); Abc_ObjAddFanin( pNode, pMiter ); // assign the name to the node if ( nPartSize == 1 ) sprintf( Buffer, "%s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); else sprintf( Buffer, "%d", i ); Abc_ObjAssignName( pNode, "miter_", Buffer ); } Vec_PtrFree( vPairsPart ); } Vec_PtrFree( vPairs ); } /**Function************************************************************* Synopsis [Derives the AND of two miters.] Description [The network should have the same names of PIs.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ) { char Buffer[1000]; Abc_Ntk_t * pNtkMiter; Abc_Obj_t * pOutput1, * pOutput2; Abc_Obj_t * pRoot1, * pRoot2, * pMiter; assert( Abc_NtkIsStrash(pNtk1) ); assert( Abc_NtkIsStrash(pNtk2) ); assert( 1 == Abc_NtkCoNum(pNtk1) ); assert( 1 == Abc_NtkCoNum(pNtk2) ); assert( 0 == Abc_NtkLatchNum(pNtk1) ); assert( 0 == Abc_NtkLatchNum(pNtk2) ); assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); // start the new network pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); // sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); sprintf( Buffer, "product" ); pNtkMiter->pName = Extra_UtilStrsav(Buffer); // perform strashing Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1, -1, 0 ); Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); // Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 ); pRoot1 = Abc_NtkPo(pNtk1,0); pRoot2 = Abc_NtkPo(pNtk2,0); pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) ); pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, (int)Abc_ObjFaninC0(pRoot2) ^ fCompl2 ); // create the miter of the two outputs if ( fOr ) pMiter = Abc_AigOr( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); else pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkMiter ) ) { printf( "Abc_NtkMiterAnd: The network check has failed.\n" ); Abc_NtkDelete( pNtkMiter ); return NULL; } return pNtkMiter; } /**Function************************************************************* Synopsis [Derives the cofactor of the miter w.r.t. the set of vars.] Description [The array of variable values contains -1/0/1 for each PI. -1 means this PI remains, 0/1 means this PI is set to 0/1.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) { char Buffer[1000]; Abc_Ntk_t * pNtkMiter; Abc_Obj_t * pRoot, * pOutput1; int Value, i; assert( Abc_NtkIsStrash(pNtk) ); assert( 1 == Abc_NtkCoNum(pNtk) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); // start the new network pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); sprintf( Buffer, "%s_miter", pNtk->pName ); pNtkMiter->pName = Extra_UtilStrsav(Buffer); // get the root output pRoot = Abc_NtkCo( pNtk, 0 ); // perform strashing Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 ); // set the first cofactor Vec_IntForEachEntry( vPiValues, Value, i ) { if ( Value == -1 ) continue; if ( Value == 0 ) { Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); continue; } if ( Value == 1 ) { Abc_NtkCi(pNtk, i)->pCopy = Abc_AigConst1(pNtkMiter); continue; } assert( 0 ); } // add the first cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); // save the output pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); // create the miter of the two outputs Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkMiter ) ) { printf( "Abc_NtkMiterCofactor: The network check has failed.\n" ); Abc_NtkDelete( pNtkMiter ); return NULL; } return pNtkMiter; } /**Function************************************************************* Synopsis [Derives the miter of two cofactors of one output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ) { char Buffer[1000]; Abc_Ntk_t * pNtkMiter; Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; assert( Abc_NtkIsStrash(pNtk) ); assert( Out < Abc_NtkCoNum(pNtk) ); assert( In1 < Abc_NtkCiNum(pNtk) ); assert( In2 < Abc_NtkCiNum(pNtk) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); // start the new network pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) ); pNtkMiter->pName = Extra_UtilStrsav(Buffer); // get the root output pRoot = Abc_NtkCo( pNtk, Out ); // perform strashing Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 ); // set the first cofactor Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); if ( In2 >= 0 ) Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter); // add the first cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); // save the output pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; // set the second cofactor Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter); if ( In2 >= 0 ) Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); // add the second cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); // save the output pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; // create the miter of the two outputs pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkMiter ) ) { printf( "Abc_NtkMiter: The network check has failed.\n" ); Abc_NtkDelete( pNtkMiter ); return NULL; } return pNtkMiter; } /**Function************************************************************* Synopsis [Derives the miter of two cofactors of one output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ) { Abc_Ntk_t * pNtkMiter; Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; assert( Abc_NtkIsStrash(pNtk) ); assert( 1 == Abc_NtkCoNum(pNtk) ); assert( In < Abc_NtkCiNum(pNtk) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); // start the new network pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); // get the root output pRoot = Abc_NtkCo( pNtk, 0 ); // perform strashing Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1, 0 ); // set the first cofactor Abc_NtkCi(pNtk, In)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); // add the first cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); // save the output // pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); // set the second cofactor Abc_NtkCi(pNtk, In)->pCopy = Abc_AigConst1(pNtkMiter); // add the second cofactor Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); // save the output // pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); // create the miter of the two outputs if ( fExist ) pMiter = Abc_AigOr( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); else pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtkMiter->pManFunc, pOutput1, pOutput2 ); Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkMiter ) ) { printf( "Abc_NtkMiter: The network check has failed.\n" ); Abc_NtkDelete( pNtkMiter ); return NULL; } return pNtkMiter; } /**Function************************************************************* Synopsis [Quantifies all the PIs existentially from the only PO of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkTemp; Abc_Obj_t * pObj; int i; assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) { if ( Abc_ObjFanoutNum(pObj) == 0 ) continue; pNtk = Abc_NtkMiterQuantify( pNtkTemp = pNtk, i, 1 ); Abc_NtkDelete( pNtkTemp ); } return pNtk; } /**Function************************************************************* Synopsis [Checks the status of the miter.] Description [Return 0 if the miter is sat for at least one output. Return 1 if the miter is unsat for all its outputs. Returns -1 if the miter is undecided for some outputs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ) { Abc_Obj_t * pNodePo, * pChild; int i; assert( Abc_NtkIsStrash(pMiter) ); Abc_NtkForEachPo( pMiter, pNodePo, i ) { pChild = Abc_ObjChild0( pNodePo ); // check if the output is constant 1 if ( Abc_AigNodeIsConst(pChild) ) { assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) ); if ( !Abc_ObjIsComplement(pChild) ) { // if the miter is constant 1, return immediately // printf( "MITER IS CONSTANT 1!\n" ); return 0; } } /* // check if the output is not constant 0 else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) ) { return 0; } */ // if the miter is undecided (or satisfiable), return immediately else return -1; } // return 1, meaning all outputs are constant zero return 1; } /**Function************************************************************* Synopsis [Reports the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ) { Abc_Obj_t * pChild, * pNode; int i; if ( Abc_NtkPoNum(pMiter) == 1 ) { pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) ); if ( Abc_AigNodeIsConst(pChild) ) { if ( Abc_ObjIsComplement(pChild) ) printf( "Unsatisfiable.\n" ); else printf( "Satisfiable. (Constant 1).\n" ); } else printf( "Satisfiable.\n" ); } else { Abc_NtkForEachPo( pMiter, pNode, i ) { pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) ); printf( "Output #%2d : ", i ); if ( Abc_AigNodeIsConst(pChild) ) { if ( Abc_ObjIsComplement(pChild) ) printf( "Unsatisfiable.\n" ); else printf( "Satisfiable. (Constant 1).\n" ); } else printf( "Satisfiable.\n" ); } } } /**Function************************************************************* Synopsis [Derives the timeframes of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial, int fVerbose ) { char Buffer[1000]; ProgressBar * pProgress; Abc_Ntk_t * pNtkFrames; Abc_Obj_t * pLatch, * pLatchOut; int i, Counter; assert( nFrames > 0 ); assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkIsDfsOrdered(pNtk) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); // start the new network pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); pNtkFrames->pName = Extra_UtilStrsav(Buffer); // map the constant nodes Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames); // create new latches (or their initial values) and remember them in the new latches if ( !fInitial ) { Abc_NtkForEachLatch( pNtk, pLatch, i ) Abc_NtkDupBox( pNtkFrames, pLatch, 1 ); } else { Counter = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { pLatchOut = Abc_ObjFanout0(pLatch); if ( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI { pLatchOut->pCopy = Abc_NtkCreatePi(pNtkFrames); Abc_ObjAssignName( pLatchOut->pCopy, Abc_ObjName(pLatchOut), NULL ); Counter++; } else pLatchOut->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); } if ( Counter ) printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); } // create the timeframes pProgress = Extra_ProgressBarStart( stdout, nFrames ); for ( i = 0; i < nFrames; i++ ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Abc_NtkAddFrame( pNtkFrames, pNtk, i ); } Extra_ProgressBarStop( pProgress ); // connect the new latches to the outputs of the last frame if ( !fInitial ) { // we cannot use pLatch->pCopy here because pLatch->pCopy is used for temporary storage of strashed values Abc_NtkForEachLatch( pNtk, pLatch, i ) Abc_ObjAddFanin( Abc_ObjFanin0(pLatch)->pCopy, Abc_ObjFanout0(pLatch)->pCopy ); } // remove dangling nodes Abc_AigCleanup( (Abc_Aig_t *)pNtkFrames->pManFunc ); // reorder the latches Abc_NtkOrderCisCos( pNtkFrames ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkFrames ) ) { printf( "Abc_NtkFrames: The network check has failed.\n" ); Abc_NtkDelete( pNtkFrames ); return NULL; } return pNtkFrames; } /**Function************************************************************* Synopsis [Adds one time frame to the new network.] Description [Assumes that the latches of the old network point to the outputs of the previous frame of the new network (pLatch->pCopy). In the end, updates the latches of the old network to point to the outputs of the current frame of the new network.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame ) { int fVerbose = 0; int NodeBef = Abc_NtkNodeNum(pNtkFrames); char Buffer[10]; Abc_Obj_t * pNode, * pLatch; int i; // create the prefix to be added to the node names sprintf( Buffer, "_%02d", iFrame ); // add the new PI nodes Abc_NtkForEachPi( pNtk, pNode, i ) Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); // add the internal nodes Abc_AigForEachAnd( pNtk, pNode, i ) pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); // add the new POs Abc_NtkForEachPo( pNtk, pNode, i ) { Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); } // transfer the implementation of the latch inputs to the latch outputs Abc_NtkForEachLatch( pNtk, pLatch, i ) pLatch->pCopy = Abc_ObjChild0Copy(Abc_ObjFanin0(pLatch)); Abc_NtkForEachLatch( pNtk, pLatch, i ) Abc_ObjFanout0(pLatch)->pCopy = pLatch->pCopy; // nodes after if ( fVerbose ) printf( "F = %4d : Total = %6d. Nodes = %6d. Prop = %s.\n", iFrame, Abc_NtkNodeNum(pNtk), Abc_NtkNodeNum(pNtkFrames)-NodeBef, Abc_AigNodeIsConst( Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pCopy ) ? "proof" : "unknown" ); } /**Function************************************************************* Synopsis [Derives the timeframes of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ) { /* char Buffer[1000]; ProgressBar * pProgress; Abc_Ntk_t * pNtkFrames; Vec_Ptr_t * vNodes; Abc_Obj_t * pLatch, * pLatchNew; int i, Counter; assert( nFrames > 0 ); assert( Abc_NtkIsStrash(pNtk) ); // start the new network pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); pNtkFrames->pName = Extra_UtilStrsav(Buffer); // create new latches (or their initial values) and remember them in the new latches if ( !fInitial ) { Abc_NtkForEachLatch( pNtk, pLatch, i ) { Abc_NtkDupObj( pNtkFrames, pLatch ); if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); } } else { Counter = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI { pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames); Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL ); Counter++; } else { pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); } if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); } if ( Counter ) printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); } // create the timeframes vNodes = Abc_NtkDfs( pNtk, 0 ); pProgress = Extra_ProgressBarStart( stdout, nFrames ); for ( i = 0; i < nFrames; i++ ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg ); } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); // connect the new latches to the outputs of the last frame if ( !fInitial ) { Abc_NtkForEachLatch( pNtk, pLatch, i ) { pLatchNew = Abc_NtkBox(pNtkFrames, i); Abc_ObjAddFanin( pLatchNew, pLatch->pCopy ); Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL ); } } Abc_NtkForEachLatch( pNtk, pLatch, i ) pLatch->pNext = NULL; // remove dangling nodes Abc_AigCleanup( pNtkFrames->pManFunc ); // reorder the latches Abc_NtkOrderCisCos( pNtkFrames ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkFrames ) ) { printf( "Abc_NtkFrames: The network check has failed.\n" ); Abc_NtkDelete( pNtkFrames ); return NULL; } return pNtkFrames; */ return NULL; } /**Function************************************************************* Synopsis [Adds one time frame to the new network.] Description [Assumes that the latches of the old network point to the outputs of the previous frame of the new network (pLatch->pCopy). In the end, updates the latches of the old network to point to the outputs of the current frame of the new network.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ) { /* char Buffer[10]; Abc_Obj_t * pNode, * pNodeNew, * pLatch; Abc_Obj_t * pConst1, * pConst1New; int i; // get the constant nodes pConst1 = Abc_AigConst1(pNtk); pConst1New = Abc_AigConst1(pNtkFrames); // create the prefix to be added to the node names sprintf( Buffer, "_%02d", iFrame ); // add the new PI nodes Abc_NtkForEachPi( pNtk, pNode, i ) { pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); } // add the internal nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( pNode == pConst1 ) pNodeNew = pConst1New; else pNodeNew = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); pNode->pCopy = pNodeNew; if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); } // add the new POs Abc_NtkForEachPo( pNtk, pNode, i ) { pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); Abc_ObjAddFanin( pNodeNew, Abc_ObjChild0Copy(pNode) ); Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); } // transfer the implementation of the latch drivers to the latches // it is important that these two steps are performed it two loops // and not in the same loop Abc_NtkForEachLatch( pNtk, pLatch, i ) pLatch->pNext = Abc_ObjChild0Copy(pLatch); Abc_NtkForEachLatch( pNtk, pLatch, i ) pLatch->pCopy = pLatch->pNext; Abc_NtkForEachLatch( pNtk, pLatch, i ) { if (addFrameMapping) { // don't give Mike complemented pointers because he doesn't like it if (Abc_ObjIsComplement(pLatch->pCopy)) { pNodeNew = Abc_NtkCreateNode( pNtkFrames ); Abc_ObjAddFanin( pNodeNew, pLatch->pCopy ); assert(Abc_ObjFaninNum(pNodeNew) == 1); pNodeNew->Level = 1 + Abc_ObjRegular(pLatch->pCopy)->Level; pLatch->pNext = pNodeNew; pLatch->pCopy = pNodeNew; } addFrameMapping(pLatch->pCopy, pLatch, iFrame+1, arg); } } */ } /**Function************************************************************* Synopsis [Splits the miter into two logic cones combined by an EXOR] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDemiter( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode; Abc_Obj_t * pPoNew; Vec_Ptr_t * vNodes1, * vNodes2; int nCommon, i; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 1 ); if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) { printf( "The root of the miter is not an EXOR gate.\n" ); return 0; } pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB ); assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) ); if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) ) { pNodeA = Abc_ObjNot(pNodeA); pNodeB = Abc_ObjNot(pNodeB); } // add the PO corresponding to control input pPoNew = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pPoNew, pNodeC ); Abc_ObjAssignName( pPoNew, "addOut1", NULL ); // add the PO corresponding to other input pPoNew = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pPoNew, pNodeB ); Abc_ObjAssignName( pPoNew, "addOut2", NULL ); // mark the nodes in the first cone pNodeB = Abc_ObjRegular(pNodeB); vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 ); vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode, i ) pNode->fMarkA = 1; nCommon = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes2, pNode, i ) nCommon += pNode->fMarkA; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode, i ) pNode->fMarkA = 0; printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon ); Vec_PtrFree( vNodes1 ); Vec_PtrFree( vNodes2 ); // reorder the latches Abc_NtkOrderCisCos( pNtk ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtk ) ) printf( "Abc_NtkDemiter: The network check has failed.\n" ); return 1; } /**Function************************************************************* Synopsis [Computes OR or AND of the POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor ) { Abc_Obj_t * pNode, * pMiter; int i; assert( Abc_NtkIsStrash(pNtk) ); // assert( Abc_NtkLatchNum(pNtk) == 0 ); if ( Abc_NtkPoNum(pNtk) == 1 ) return 1; // start the result if ( fAnd ) pMiter = Abc_AigConst1(pNtk); else pMiter = Abc_ObjNot( Abc_AigConst1(pNtk) ); // perform operations on the POs Abc_NtkForEachPo( pNtk, pNode, i ) if ( fAnd ) pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); else if ( fXor ) pMiter = Abc_AigXor( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); else pMiter = Abc_AigOr( (Abc_Aig_t *)pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); // remove the POs and their names for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- ) Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) ); assert( Abc_NtkPoNum(pNtk) == 0 ); // create the new PO pNode = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pNode, pMiter ); Abc_ObjAssignName( pNode, "miter", NULL ); Abc_NtkOrderCisCos( pNtk ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkOrPos: The network check has failed.\n" ); return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMulti.c000066400000000000000000000507011300674244400235530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMulti.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures which transform an AIG into multi-input AND-graph.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD static void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ); static DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins ); static DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ); static void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ); static void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk ); static void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ); static void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk ); static void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk ); static void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transforms the AIG into nodes.] Description [Threhold is the max number of nodes duplicated at a node.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ) { Abc_Ntk_t * pNtkNew; assert( Abc_NtkIsStrash(pNtk) ); assert( nThresh >= 0 ); assert( nFaninMax > 1 ); // print a warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" ); // define the boundary if ( fCnf ) Abc_NtkMultiSetBoundsCnf( pNtk ); else if ( fMulti ) Abc_NtkMultiSetBoundsMulti( pNtk, nThresh ); else if ( fSimple ) Abc_NtkMultiSetBoundsSimple( pNtk ); else if ( fFactor ) Abc_NtkMultiSetBoundsFactor( pNtk ); else Abc_NtkMultiSetBounds( pNtk, nThresh, nFaninMax ); // perform renoding for this boundary pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); Abc_NtkMultiInt( pNtk, pNtkNew ); Abc_NtkFinalize( pNtk, pNtkNew ); // make the network minimum base Abc_NtkMinimumBase( pNtkNew ); // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // report the number of CNF objects if ( fCnf ) { // int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew); // printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses ); } //printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) ); if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkMulti: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Transforms the AIG into nodes.] Description [Threhold is the max number of nodes duplicated at a node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { ProgressBar * pProgress; Abc_Obj_t * pNode, * pConst1, * pNodeNew; int i; // set the constant node pConst1 = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pConst1) > 0 ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Cudd_ReadOne( (DdManager *)pNtkNew->pManFunc ); Cudd_Ref( (DdNode *)pNodeNew->pData ); pConst1->pCopy = pNodeNew; } // perform renoding for POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) continue; Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) ); } Extra_ProgressBarStop( pProgress ); // clean the boundaries and data field in the old network Abc_NtkForEachObj( pNtk, pNode, i ) { pNode->fMarkA = 0; pNode->pData = NULL; } } /**Function************************************************************* Synopsis [Find the best multi-input node rooted at the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ) { Vec_Ptr_t * vCone; Abc_Obj_t * pNodeNew; int i; assert( !Abc_ObjIsComplement(pNodeOld) ); // return if the result if known if ( pNodeOld->pCopy ) return pNodeOld->pCopy; assert( Abc_ObjIsNode(pNodeOld) ); assert( !Abc_AigNodeIsConst(pNodeOld) ); assert( pNodeOld->fMarkA ); //printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) ); // collect the renoding cone vCone = Vec_PtrAlloc( 10 ); Abc_NtkMultiCone( pNodeOld, vCone ); // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < vCone->nSize; i++ ) Abc_ObjAddFanin( pNodeNew, Abc_NtkMulti_rec(pNtkNew, (Abc_Obj_t *)vCone->pArray[i]) ); // derive the function of this node pNodeNew->pData = Abc_NtkMultiDeriveBdd( (DdManager *)pNtkNew->pManFunc, pNodeOld, vCone ); Cudd_Ref( (DdNode *)pNodeNew->pData ); Vec_PtrFree( vCone ); // remember the node pNodeOld->pCopy = pNodeNew; return pNodeOld->pCopy; } /**Function************************************************************* Synopsis [Derives the local BDD of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ) { Abc_Obj_t * pFaninOld; DdNode * bFunc; int i; assert( !Abc_AigNodeIsConst(pNodeOld) ); assert( Abc_ObjIsNode(pNodeOld) ); // set the elementary BDD variables for the input nodes for ( i = 0; i < vFaninsOld->nSize; i++ ) { pFaninOld = (Abc_Obj_t *)vFaninsOld->pArray[i]; pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( (DdNode *)pFaninOld->pData ); pFaninOld->fMarkC = 1; } // call the recursive BDD computation bFunc = Abc_NtkMultiDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc ); // dereference the intermediate nodes for ( i = 0; i < vFaninsOld->nSize; i++ ) { pFaninOld = (Abc_Obj_t *)vFaninsOld->pArray[i]; Cudd_RecursiveDeref( dd, (DdNode *)pFaninOld->pData ); pFaninOld->fMarkC = 0; } Cudd_Deref( bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Derives the local BDD of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins ) { DdNode * bFunc, * bFunc0, * bFunc1; assert( !Abc_ObjIsComplement(pNode) ); // if the result is available return if ( pNode->fMarkC ) { assert( pNode->pData ); // network has a cycle return (DdNode *)pNode->pData; } // mark the node as visited pNode->fMarkC = 1; Vec_PtrPush( vFanins, pNode ); // compute the result for both branches bFunc0 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 ); bFunc1 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 ); bFunc0 = Cudd_NotCond( bFunc0, (long)Abc_ObjFaninC0(pNode) ); bFunc1 = Cudd_NotCond( bFunc1, (long)Abc_ObjFaninC1(pNode) ); // get the final result bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bFunc0 ); Cudd_RecursiveDeref( dd, bFunc1 ); // set the result pNode->pData = bFunc; assert( pNode->pData ); return bFunc; } /**Function************************************************************* Synopsis [Limits the cones to be no more than the given size.] Description [Returns 1 if the last cone was limited. Returns 0 if no changes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMultiLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst ) { int nNodes0, nNodes1; assert( !Abc_ObjIsComplement(pNode) ); // check if the node should be added to the fanins if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) ) { Vec_PtrPushUnique( vCone, pNode ); return 0; } // if we cannot stop in this branch, collect all nodes if ( !fCanStop ) { Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 ); Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); return 0; } // if we can stop, try the left branch first, and return if we stopped assert( vCone->nSize == 0 ); if ( Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) ) return 1; // save the number of nodes in the left branch and call for the right branch nNodes0 = vCone->nSize; assert( nNodes0 <= nFaninMax ); Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); // check the number of nodes if ( vCone->nSize <= nFaninMax ) return 0; // the number of nodes exceeds the limit // get the number of nodes in the right branch vCone->nSize = 0; Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); // if this number exceeds the limit, solve the problem for this branch if ( vCone->nSize > nFaninMax ) { int RetValue; vCone->nSize = 0; RetValue = Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 ); assert( RetValue == 1 ); return 1; } nNodes1 = vCone->nSize; assert( nNodes1 <= nFaninMax ); if ( nNodes0 >= nNodes1 ) { // the left branch is larger - cut it assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 ); Abc_ObjFanin(pNode,0)->fMarkA = 1; } else { // the right branch is larger - cut it assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 ); Abc_ObjFanin(pNode,1)->fMarkA = 1; } return 1; } /**Function************************************************************* Synopsis [Limits the cones to be no more than the given size.] Description [Returns 1 if the last cone was limited. Returns 0 if no changes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMultiLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax ) { vCone->nSize = 0; return Abc_NtkMultiLimit_rec( pNode, vCone, nFaninMax, 1, 1 ); } /**Function************************************************************* Synopsis [Sets the expansion boundary for multi-input nodes.] Description [The boundary includes the set of PIs and all nodes such that when expanding over the node we duplicate no more than nThresh nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ) { Vec_Ptr_t * vCone = Vec_PtrAlloc(10); Abc_Obj_t * pNode; int i, nFanouts, nConeSize; // make sure the mark is not set Abc_NtkForEachObj( pNtk, pNode, i ) assert( pNode->fMarkA == 0 ); // mark the nodes where expansion stops using pNode->fMarkA Abc_NtkForEachNode( pNtk, pNode, i ) { // skip PI/PO nodes // if ( Abc_NodeIsConst(pNode) ) // continue; // mark the nodes with multiple fanouts nFanouts = Abc_ObjFanoutNum(pNode); nConeSize = Abc_NodeMffcSize(pNode); if ( (nFanouts - 1) * nConeSize > nThresh ) pNode->fMarkA = 1; } // mark the PO drivers Abc_NtkForEachCo( pNtk, pNode, i ) Abc_ObjFanin0(pNode)->fMarkA = 1; // make sure the fanin limit is met Abc_NtkForEachNode( pNtk, pNode, i ) { // skip PI/PO nodes // if ( Abc_NodeIsConst(pNode) ) // continue; if ( pNode->fMarkA == 0 ) continue; // continue cutting branches until it meets the fanin limit while ( Abc_NtkMultiLimit(pNode, vCone, nFaninMax) ); assert( vCone->nSize <= nFaninMax ); } Vec_PtrFree(vCone); /* // make sure the fanin limit is met Abc_NtkForEachNode( pNtk, pNode, i ) { // skip PI/PO nodes // if ( Abc_NodeIsConst(pNode) ) // continue; if ( pNode->fMarkA == 0 ) continue; Abc_NtkMultiCone( pNode, vCone ); assert( vCone->nSize <= nFaninMax ); } */ } /**Function************************************************************* Synopsis [Sets the expansion boundary for conversion into CNF.] Description [The boundary includes the set of PIs, the roots of MUXes, the nodes with multiple fanouts and the nodes with complemented outputs.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, nMuxes; // make sure the mark is not set Abc_NtkForEachObj( pNtk, pNode, i ) assert( pNode->fMarkA == 0 ); // mark the nodes where expansion stops using pNode->fMarkA Abc_NtkForEachNode( pNtk, pNode, i ) { // skip PI/PO nodes // if ( Abc_NodeIsConst(pNode) ) // continue; // mark the nodes with multiple fanouts if ( Abc_ObjFanoutNum(pNode) > 1 ) pNode->fMarkA = 1; // mark the nodes that are roots of MUXes if ( Abc_NodeIsMuxType( pNode ) ) { pNode->fMarkA = 1; Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1; Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1; Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1; Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1; } else // mark the complemented edges { if ( Abc_ObjFaninC0(pNode) ) Abc_ObjFanin0(pNode)->fMarkA = 1; if ( Abc_ObjFaninC1(pNode) ) Abc_ObjFanin1(pNode)->fMarkA = 1; } } // mark the PO drivers Abc_NtkForEachCo( pNtk, pNode, i ) Abc_ObjFanin0(pNode)->fMarkA = 1; // count the number of MUXes nMuxes = 0; Abc_NtkForEachNode( pNtk, pNode, i ) { // skip PI/PO nodes // if ( Abc_NodeIsConst(pNode) ) // continue; if ( Abc_NodeIsMuxType(pNode) && Abc_ObjFanin0(pNode)->fMarkA == 0 && Abc_ObjFanin1(pNode)->fMarkA == 0 ) nMuxes++; } // printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); } /**Function************************************************************* Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ) { Abc_Obj_t * pNode; int i, nFanouts, nConeSize; // make sure the mark is not set Abc_NtkForEachObj( pNtk, pNode, i ) assert( pNode->fMarkA == 0 ); // mark the nodes where expansion stops using pNode->fMarkA Abc_NtkForEachNode( pNtk, pNode, i ) { // skip PI/PO nodes // if ( Abc_NodeIsConst(pNode) ) // continue; // mark the nodes with multiple fanouts // if ( Abc_ObjFanoutNum(pNode) > 1 ) // pNode->fMarkA = 1; // mark the nodes with multiple fanouts nFanouts = Abc_ObjFanoutNum(pNode); nConeSize = Abc_NodeMffcSizeStop(pNode); if ( (nFanouts - 1) * nConeSize > nThresh ) pNode->fMarkA = 1; // mark the children if they are pointed by the complemented edges if ( Abc_ObjFaninC0(pNode) ) Abc_ObjFanin0(pNode)->fMarkA = 1; if ( Abc_ObjFaninC1(pNode) ) Abc_ObjFanin1(pNode)->fMarkA = 1; } // mark the PO drivers Abc_NtkForEachCo( pNtk, pNode, i ) Abc_ObjFanin0(pNode)->fMarkA = 1; } /**Function************************************************************* Synopsis [Sets a simple boundary.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; // make sure the mark is not set Abc_NtkForEachObj( pNtk, pNode, i ) assert( pNode->fMarkA == 0 ); // mark the nodes where expansion stops using pNode->fMarkA Abc_NtkForEachNode( pNtk, pNode, i ) pNode->fMarkA = 1; } /**Function************************************************************* Synopsis [Sets a factor-cut boundary.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; // make sure the mark is not set Abc_NtkForEachObj( pNtk, pNode, i ) assert( pNode->fMarkA == 0 ); // mark the nodes where expansion stops using pNode->fMarkA Abc_NtkForEachNode( pNtk, pNode, i ) pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode)); // mark the PO drivers Abc_NtkForEachCo( pNtk, pNode, i ) Abc_ObjFanin0(pNode)->fMarkA = 1; } /**Function************************************************************* Synopsis [Collects the fanins of a large node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) { assert( !Abc_ObjIsComplement(pNode) ); if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) ) { Vec_PtrPushUnique( vCone, pNode ); return; } Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone ); Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone ); } /**Function************************************************************* Synopsis [Collects the fanins of a large node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) { assert( !Abc_ObjIsComplement(pNode) ); assert( Abc_ObjIsNode(pNode) ); vCone->nSize = 0; Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone ); Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone ); } #else Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ) { return NULL; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcMv.c000066400000000000000000000301051300674244400230370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Multi-valued decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD typedef struct Mv_Man_t_ Mv_Man_t; struct Mv_Man_t_ { int nInputs; // the number of 4-valued input variables int nFuncs; // the number of 4-valued functions DdManager * dd; // representation of functions DdNode * bValues[15][4]; // representation of i-sets DdNode * bValueDcs[15][4]; // representation of i-sets don't-cares DdNode * bFuncs[15]; // representation of functions }; static void Abc_MvDecompose( Mv_Man_t * p ); static void Abc_MvPrintStats( Mv_Man_t * p ); static void Abc_MvRead( Mv_Man_t * p ); static void Abc_MvDeref( Mv_Man_t * p ); static DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvExperiment() { Mv_Man_t * p; // get the functions p = ABC_ALLOC( Mv_Man_t, 1 ); memset( p, 0, sizeof(Mv_Man_t) ); p->dd = Cudd_Init( 32, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); p->nFuncs = 15; p->nInputs = 9; Abc_MvRead( p ); // process the functions Abc_MvPrintStats( p ); // Cudd_ReduceHeap( p->dd, CUDD_REORDER_SYMM_SIFT, 1 ); // Abc_MvPrintStats( p ); // try detecting support reducing bound set Abc_MvDecompose( p ); // remove the manager Abc_MvDeref( p ); Extra_StopManager( p->dd ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvPrintStats( Mv_Man_t * p ) { int i, v; for ( i = 0; i < 15; i++ ) { printf( "%2d : ", i ); printf( "%3d (%2d) ", Cudd_DagSize(p->bFuncs[i])-1, Cudd_SupportSize(p->dd, p->bFuncs[i]) ); for ( v = 0; v < 4; v++ ) printf( "%d = %3d (%2d) ", v, Cudd_DagSize(p->bValues[i][v])-1, Cudd_SupportSize(p->dd, p->bValues[i][v]) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ) { DdNode * bCube, * bVar, * bTemp; int i; bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); for ( i = 0; i < nVars; i++ ) { if ( pLine[i] == '-' ) continue; else if ( pLine[i] == '0' ) // 0 bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) ); else if ( pLine[i] == '1' ) // 1 bVar = Cudd_bddIthVar(dd, 29-i); else assert(0); bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bCube ); return bCube; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvRead( Mv_Man_t * p ) { FILE * pFile; char Buffer[1000], * pLine; DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum; int i, v; // start the cube bCubeSum = Cudd_ReadLogicZero(p->dd); Cudd_Ref( bCubeSum ); // start the values for ( i = 0; i < 15; i++ ) for ( v = 0; v < 4; v++ ) { p->bValues[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValues[i][v] ); p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValueDcs[i][v] ); } // read the file pFile = fopen( "input.pla", "r" ); while ( fgets( Buffer, 1000, pFile ) ) { if ( Buffer[0] == '#' ) continue; if ( Buffer[0] == '.' ) { if ( Buffer[1] == 'e' ) break; continue; } // get the cube bCube = Abc_MvReadCube( p->dd, Buffer, 18 ); Cudd_Ref( bCube ); // add it to the values of the output functions pLine = Buffer + 19; for ( i = 0; i < 15; i++ ) { if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' ) { for ( v = 0; v < 4; v++ ) { p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube ); Cudd_Ref( p->bValueDcs[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } continue; } else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0 v = 0; else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1 v = 1; else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2 v = 2; else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3 v = 3; else assert( 0 ); // add the value p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } // add the cube bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube ); Cudd_Ref( bCubeSum ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bCube ); } // add the complement of the domain to all values for ( i = 0; i < 15; i++ ) for ( v = 0; v < 4; v++ ) { if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) ) continue; p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) ); Cudd_Ref( p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, bTemp ); } printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) ); Cudd_RecursiveDeref( p->dd, bCubeSum ); // create each output function for ( i = 0; i < 15; i++ ) { p->bFuncs[i] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bFuncs[i] ); for ( v = 0; v < 4; v++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) ); bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( p->dd, bCube ); // add the value p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd ); Cudd_Ref( p->bFuncs[i] ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bProd ); } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvDeref( Mv_Man_t * p ) { int i, v; for ( i = 0; i < 15; i++ ) for ( v = 0; v < 4; v++ ) { Cudd_RecursiveDeref( p->dd, p->bValues[i][v] ); Cudd_RecursiveDeref( p->dd, p->bValueDcs[i][v] ); } for ( i = 0; i < 15; i++ ) Cudd_RecursiveDeref( p->dd, p->bFuncs[i] ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MvDecompose( Mv_Man_t * p ) { DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes; int k, i1, i2, v1, v2;//, c1, c2, Counter; bVar0 = Cudd_bddIthVar(p->dd, 30); bVar1 = Cudd_bddIthVar(p->dd, 31); bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); for ( k = 0; k < p->nFuncs; k++ ) { printf( "FUNCTION %d\n", k ); for ( i1 = 0; i1 < p->nFuncs; i1++ ) for ( i2 = i1+1; i2 < p->nFuncs; i2++ ) { Vec_Ptr_t * vCofs; for ( v1 = 0; v1 < 4; v1++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1 ), ((v1 & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) ); bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube1 ); for ( v2 = 0; v2 < 4; v2++ ) { bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2 ), ((v2 & 1) == 0) ); bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) ); bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube2 ); bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 ); Cudd_Ref( bVarCube ); bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube ); Cudd_Ref( bCofs[v1 * 4 + v2] ); Cudd_RecursiveDeref( p->dd, bVarCube ); Cudd_RecursiveDeref( p->dd, bVarCube2 ); } Cudd_RecursiveDeref( p->dd, bVarCube1 ); } /* // check the compatibility of cofactors Counter = 0; for ( c1 = 0; c1 < 16; c1++ ) { for ( c2 = 0; c2 <= c1; c2++ ) printf( " " ); for ( c2 = c1+1; c2 < 16; c2++ ) { bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube ); Cudd_Ref( bRes ); if ( bRes == Cudd_ReadOne(p->dd) ) { printf( "+" ); Counter++; } else { printf( " " ); } Cudd_RecursiveDeref( p->dd, bRes ); } printf( "\n" ); } */ vCofs = Vec_PtrAlloc( 16 ); for ( v1 = 0; v1 < 4; v1++ ) for ( v2 = 0; v2 < 4; v2++ ) Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] ); printf( "%d ", Vec_PtrSize(vCofs) ); Vec_PtrFree( vCofs ); // free the cofactors for ( v1 = 0; v1 < 4; v1++ ) for ( v2 = 0; v2 < 4; v2++ ) Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] ); printf( "\n" ); // printf( "%2d, %2d : %3d\n", i1, i2, Counter ); } } Cudd_RecursiveDeref( p->dd, bCube ); } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcNpn.c000066400000000000000000000325631300674244400232220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcNpn.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures for testing and comparing semi-canonical forms.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcNpn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "misc/extra/extra.h" #include "misc/vec/vec.h" #include "bool/kit/kit.h" #include "bool/lucky/lucky.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // semi-canonical form types // 0 - none // 1 - based on counting 1s in cofactors // 2 - based on minimum truth table value // 3 - exact NPN // data-structure to store a bunch of truth tables typedef struct Abc_TtStore_t_ Abc_TtStore_t; struct Abc_TtStore_t_ { int nVars; int nWords; int nFuncs; word ** pFuncs; }; extern Abc_TtStore_t * Abc_TtStoreLoad( char * pFileName, int nVarNum ); extern void Abc_TtStoreFree( Abc_TtStore_t * p, int nVarNum ); extern void Abc_TtStoreWrite( char * pFileName, Abc_TtStore_t * p, int fBinary ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Counts the number of unique truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // returns hash key of the truth table static inline int Abc_TruthHashKey( word * pFunc, int nWords, int nTableSize ) { static unsigned s_BigPrimes[7] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457}; int w; word Key = 0; for ( w = 0; w < nWords; w++ ) Key += pFunc[w] * s_BigPrimes[w % 7]; return (int)(Key % nTableSize); } // returns 1 if the entry with this truth table exits static inline int Abc_TruthHashLookup( word ** pFuncs, int iThis, int nWords, int * pTable, int * pNexts, int Key ) { int iThat; for ( iThat = pTable[Key]; iThat != -1; iThat = pNexts[iThat] ) if ( !memcmp( pFuncs[iThat], pFuncs[iThis], sizeof(word) * nWords ) ) return 1; return 0; } // hashes truth tables and collects unique ones int Abc_TruthNpnCountUnique( Abc_TtStore_t * p ) { // allocate hash table int nTableSize = Abc_PrimeCudd(p->nFuncs); int * pTable = ABC_FALLOC( int, nTableSize ); int * pNexts = ABC_FALLOC( int, nTableSize ); // hash functions int i, k, Key; for ( i = 0; i < p->nFuncs; i++ ) { Key = Abc_TruthHashKey( p->pFuncs[i], p->nWords, nTableSize ); if ( Abc_TruthHashLookup( p->pFuncs, i, p->nWords, pTable, pNexts, Key ) ) // found equal p->pFuncs[i] = NULL; else // there is no equal (the first time this one occurs so far) pNexts[i] = pTable[Key], pTable[Key] = i; } ABC_FREE( pTable ); ABC_FREE( pNexts ); // count the number of unqiue functions assert( p->pFuncs[0] != NULL ); for ( i = k = 1; i < p->nFuncs; i++ ) if ( p->pFuncs[i] != NULL ) p->pFuncs[k++] = p->pFuncs[i]; return (p->nFuncs = k); } /**Function************************************************************* Synopsis [Counts the number of unique truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int nWords = 0; // unfortunate global variable int Abc_TruthCompare( word ** p1, word ** p2 ) { return memcmp(*p1, *p2, sizeof(word) * nWords); } int Abc_TruthNpnCountUniqueSort( Abc_TtStore_t * p ) { int i, k; // sort them by value nWords = p->nWords; assert( nWords > 0 ); qsort( (void *)p->pFuncs, p->nFuncs, sizeof(word *), (int(*)(const void *,const void *))Abc_TruthCompare ); // count the number of unqiue functions for ( i = k = 1; i < p->nFuncs; i++ ) if ( memcmp( p->pFuncs[i-1], p->pFuncs[i], sizeof(word) * nWords ) ) p->pFuncs[k++] = p->pFuncs[i]; return (p->nFuncs = k); } /**Function************************************************************* Synopsis [Prints out one NPN transform.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthNpnPrint( char * pCanonPermInit, unsigned uCanonPhase, int nVars ) { char pCanonPerm[16]; int i; assert( nVars <= 16 ); for ( i = 0; i < nVars; i++ ) pCanonPerm[i] = pCanonPermInit ? pCanonPermInit[i] : 'a' + i; printf( " %c = ( ", Abc_InfoHasBit(&uCanonPhase, nVars) ? 'Z':'z' ); for ( i = 0; i < nVars; i++ ) printf( "%c%s", pCanonPerm[i] + ('A'-'a') * Abc_InfoHasBit(&uCanonPhase, pCanonPerm[i]-'a'), i == nVars-1 ? "":"," ); printf( " ) " ); } /**Function************************************************************* Synopsis [Apply decomposition to the truth table.] Description [Returns the number of AIG nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthNpnPerform( Abc_TtStore_t * p, int NpnType, int fVerbose ) { unsigned pAux[2048]; word pAuxWord[1024], pAuxWord1[1024]; char pCanonPerm[16]; unsigned uCanonPhase=0; abctime clk = Abc_Clock(); int i; char * pAlgoName = NULL; if ( NpnType == 0 ) pAlgoName = "uniqifying "; else if ( NpnType == 1 ) pAlgoName = "exact NPN "; else if ( NpnType == 2 ) pAlgoName = "counting 1s "; else if ( NpnType == 3 ) pAlgoName = "Jake's hybrid fast "; else if ( NpnType == 4 ) pAlgoName = "Jake's hybrid good "; else if ( NpnType == 5 ) pAlgoName = "new hybrid fast "; else if ( NpnType == 6 ) pAlgoName = "new phase flipping "; else if ( NpnType == 7 ) pAlgoName = "new hier. matching "; assert( p->nVars <= 16 ); if ( pAlgoName ) printf( "Applying %-20s to %8d func%s of %2d vars... ", pAlgoName, p->nFuncs, (p->nFuncs == 1 ? "":"s"), p->nVars ); if ( fVerbose ) printf( "\n" ); if ( NpnType == 0 ) { for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); if ( fVerbose ) Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), printf( "\n" ); } } else if ( NpnType == 1 ) { permInfo* pi; Abc_TruthNpnCountUnique(p); pi = setPermInfoPtr(p->nVars); for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); simpleMinimal(p->pFuncs[i], pAuxWord, pAuxWord1, pi, p->nVars); if ( fVerbose ) Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" ); } freePermInfoPtr(pi); } else if ( NpnType == 2 ) { for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); resetPCanonPermArray(pCanonPerm, p->nVars); uCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pFuncs[i], pAux, p->nVars, pCanonPerm ); if ( fVerbose ) Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" ); } } else if ( NpnType == 3 ) { for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); resetPCanonPermArray(pCanonPerm, p->nVars); uCanonPhase = luckyCanonicizer_final_fast( p->pFuncs[i], p->nVars, pCanonPerm ); if ( fVerbose ) Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" ); } } else if ( NpnType == 4 ) { for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); resetPCanonPermArray(pCanonPerm, p->nVars); uCanonPhase = luckyCanonicizer_final_fast1( p->pFuncs[i], p->nVars, pCanonPerm ); if ( fVerbose ) Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" ); } } else if ( NpnType == 5 ) { for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); uCanonPhase = Abc_TtCanonicize( p->pFuncs[i], p->nVars, pCanonPerm ); if ( fVerbose ) Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(pCanonPerm, uCanonPhase, p->nVars), printf( "\n" ); } } else if ( NpnType == 6 ) { for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); uCanonPhase = Abc_TtCanonicizePhase( p->pFuncs[i], p->nVars ); if ( fVerbose ) Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(NULL, uCanonPhase, p->nVars), printf( "\n" ); } } else if ( NpnType == 7 ) { extern unsigned Abc_TtCanonicizeHie( Abc_TtMan_t * p, word * pTruth, int nVars, char * pCanonPerm, int fExact ); extern Abc_TtMan_t * Abc_TtManStart( int nVars ); extern void Abc_TtManStop( Abc_TtMan_t * p ); extern int Abc_TtManNumClasses( Abc_TtMan_t * p ); int fExact = 0; Abc_TtMan_t * pMan = Abc_TtManStart( p->nVars ); for ( i = 0; i < p->nFuncs; i++ ) { if ( fVerbose ) printf( "%7d : ", i ); uCanonPhase = Abc_TtCanonicizeHie( pMan, p->pFuncs[i], p->nVars, pCanonPerm, fExact ); if ( fVerbose ) // Extra_PrintHex( stdout, (unsigned *)p->pFuncs[i], p->nVars ), Abc_TruthNpnPrint(NULL, uCanonPhase, p->nVars), printf( "\n" ); printf( "\n" ); } // nClasses = Abc_TtManNumClasses( pMan ); Abc_TtManStop( pMan ); } else assert( 0 ); clk = Abc_Clock() - clk; printf( "Classes =%9d ", Abc_TruthNpnCountUnique(p) ); Abc_PrintTime( 1, "Time", clk ); } /**Function************************************************************* Synopsis [Apply decomposition to truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthNpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose ) { Abc_TtStore_t * p; char * pFileNameOut; // read info from file p = Abc_TtStoreLoad( pFileName, nVarNum ); if ( p == NULL ) return; // consider functions from the file Abc_TruthNpnPerform( p, NpnType, fVerbose ); // write the result if ( fDumpRes ) { if ( fBinary ) pFileNameOut = Extra_FileNameGenericAppend( pFileName, "_out.tt" ); else pFileNameOut = Extra_FileNameGenericAppend( pFileName, "_out.txt" ); Abc_TtStoreWrite( pFileNameOut, p, fBinary ); if ( fVerbose ) printf( "The resulting functions are written into file \"%s\".\n", pFileNameOut ); } // delete data-structure Abc_TtStoreFree( p, nVarNum ); // printf( "Finished computing canonical forms for functions from file \"%s\".\n", pFileName ); } /**Function************************************************************* Synopsis [Testbench for decomposition algorithms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose ) { if ( fVerbose ) printf( "Using truth tables from file \"%s\"...\n", pFileName ); if ( NpnType >= 0 && NpnType <= 7 ) Abc_TruthNpnTest( pFileName, NpnType, nVarNum, fDumpRes, fBinary, fVerbose ); else printf( "Unknown canonical form value (%d).\n", NpnType ); fflush( stdout ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcNpnSave.c000066400000000000000000000503701300674244400240350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcNpnSave.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface with the FPGA mapping package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: abcNpnSave.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Npn_Obj_t_ Npn_Obj_t; typedef struct Npn_Man_t_ Npn_Man_t; struct Npn_Obj_t_ { word uTruth; // truth table int Count; // occurrences int iNext; // next entry }; struct Npn_Man_t_ { Npn_Obj_t * pBuffer; // all NPN entries int * pBins; // hash table int nBins; // hash table size int nBufferSize; // buffer size int nEntries; // entry count }; static inline Npn_Obj_t * Npn_ManObj( Npn_Man_t * p, int i ) { assert( i < p->nBufferSize ); return i ? p->pBuffer + i : NULL; } static inline int Npn_ManObjNum( Npn_Man_t * p, Npn_Obj_t * pObj ) { assert( p->pBuffer < pObj ); return pObj - p->pBuffer; } 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) }; static Npn_Man_t * pNpnMan = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_TruthPermute_rec( char * pStr, int mid, int end ) { static int count = 0; char * pTemp = Abc_UtilStrsav(pStr); char e; int i; if ( mid == end ) { printf( "%03d: %s\n", count++, pTemp ); return ; } for ( i = mid; i <= end; i++ ) { e = pTemp[mid]; pTemp[mid] = pTemp[i]; pTemp[i] = e; Npn_TruthPermute_rec( pTemp, mid + 1, end ); e = pTemp[mid]; pTemp[mid] = pTemp[i]; pTemp[i] = e; } ABC_FREE( pTemp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Npn_TruthHasVar( word t, int v ) { return ((t & Truth[v]) >> (1<> 1) & ABC_CONST(0x5555555555555555)); t = (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333)); t = (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F)); t = (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF)); t = (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF)); return (t & ABC_CONST(0x00000000FFFFFFFF)) + (t>>32); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Npn_TruthChangePhase( word t, int v ) { return ((t & Truth[v]) >> (1<> (1 << v)); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Npn_TruthCanon( word t, int nVars, int * pPhase ) { int fUsePolarity = 0; int fUsePermutation = 0; char Temp, pSigs[13], pCanonPerm[6]; int v, fChange, CanonPhase = 0; assert( nVars < 7 ); pSigs[12] = Npn_TruthCountOnes( t ); if ( pSigs[12] > 32 ) { t = ~t; pSigs[12] = 64 - pSigs[12]; CanonPhase |= (1 << 6); } if ( fUsePolarity || fUsePermutation ) { for ( v = 0; v < nVars; v++ ) { pCanonPerm[v] = v; pSigs[2*v+1] = Npn_TruthCountOnes( t & Truth[v] ); pSigs[2*v] = pSigs[12] - pSigs[2*v+1]; } } if ( fUsePolarity ) { for ( v = 0; v < nVars; v++ ) { if ( pSigs[2*v] >= pSigs[2*v+1] ) continue; CanonPhase |= (1 << v); Temp = pSigs[2*v]; pSigs[2*v] = pSigs[2*v+1]; pSigs[2*v+1] = Temp; t = Npn_TruthChangePhase( t, v ); } } if ( fUsePermutation ) { do { fChange = 0; for ( v = 0; v < nVars-1; v++ ) { if ( fUsePolarity ) { if ( pSigs[2*v] >= pSigs[2*(v+1)] ) continue; } else { if ( Abc_MinInt(pSigs[2*v],pSigs[2*v+1]) >= Abc_MinInt(pSigs[2*(v+1)],pSigs[2*(v+1)+1]) ) continue; } fChange = 1; Temp = pCanonPerm[v]; pCanonPerm[v] = pCanonPerm[v+1]; pCanonPerm[v+1] = Temp; Temp = pSigs[2*v]; pSigs[2*v] = pSigs[2*(v+1)]; pSigs[2*(v+1)] = Temp; Temp = pSigs[2*v+1]; pSigs[2*v+1] = pSigs[2*(v+1)+1]; pSigs[2*(v+1)+1] = Temp; t = Npn_TruthSwapAdjacentVars( t, v ); } } while ( fChange ); } if ( pPhase ) { *pPhase = 0; for ( v = 0; v < nVars; v++ ) *pPhase |= (pCanonPerm[v] << (4 * v)); *pPhase |= (CanonPhase << 24); } return t; } /**Function************************************************************* Synopsis [Computes the hash key.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Npn_ManHash( Npn_Man_t * p, word uTruth ) { word Key = (uTruth * (word)101) ^ (uTruth * (word)733) ^ (uTruth * (word)1777); return (int)(Key % (word)p->nBins); } /**Function************************************************************* Synopsis [Resizes the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_ManResize( Npn_Man_t * p ) { Npn_Obj_t * pEntry, * pNext; int * 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( int, p->nBins ); // rehash the entries from the old table Counter = 1; for ( i = 0; i < nBinsOld; i++ ) for ( pEntry = Npn_ManObj(p, pBinsOld[i]), pNext = pEntry ? Npn_ManObj(p, pEntry->iNext) : NULL; pEntry; pEntry = pNext, pNext = pEntry ? Npn_ManObj(p, pEntry->iNext) : NULL ) { // get the place where this entry goes ppPlace = p->pBins + Npn_ManHash( p, pEntry->uTruth ); // add the entry to the list pEntry->iNext = *ppPlace; *ppPlace = Npn_ManObjNum( p, pEntry ); Counter++; } assert( Counter == p->nEntries ); ABC_FREE( pBinsOld ); //ABC_PRT( "Hash table resizing time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Adds one entry to the table.] Description [Increments ref counter by 1.] SideEffects [] SeeAlso [] ***********************************************************************/ Npn_Obj_t * Npn_ManAdd( Npn_Man_t * p, word uTruth ) { Npn_Obj_t * pEntry; int * pPlace, Key = Npn_ManHash( p, uTruth ); // resize the link storage if needed if ( p->nEntries == p->nBufferSize ) { p->nBufferSize *= 2; p->pBuffer = ABC_REALLOC( Npn_Obj_t, p->pBuffer, p->nBufferSize ); } // find the entry for ( pEntry = Npn_ManObj(p, p->pBins[Key]), pPlace = p->pBins + Key; pEntry; pPlace = &pEntry->iNext, pEntry = Npn_ManObj(p, pEntry->iNext) ) if ( pEntry->uTruth == uTruth ) { pEntry->Count++; return pEntry; } // create new entry *pPlace = p->nEntries; assert( p->nEntries < p->nBufferSize ); pEntry = Npn_ManObj( p, p->nEntries++ ); pEntry->uTruth = uTruth; pEntry->Count = 1; pEntry->iNext = 0; // resize the table if needed if ( p->nEntries > 3 * p->nBins ) Npn_ManResize( p ); return pEntry; } /**Function************************************************************* Synopsis [Fills table from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_ManRead( Npn_Man_t * p, char * pFileName ) { char pBuffer[1000]; char * pToken; Npn_Obj_t * pEntry; unsigned Truth[2]; word uTruth; FILE * pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName ); return; } // read lines from the file while ( fgets( pBuffer, 1000, pFile ) != NULL ) { pToken = strtok( pBuffer, " \t\n" ); if ( pToken == NULL ) continue; if ( pToken[0] == '#' ) continue; if ( strlen(pToken) != 16 ) { Abc_Print( 0, "Skipping token %s that does not look like a 16-digit hex number.\n" ); continue; } // extract truth table Extra_ReadHexadecimal( Truth, pToken, 6 ); uTruth = (((word)Truth[1]) << 32) | (word)Truth[0]; // add truth table pEntry = Npn_ManAdd( p, uTruth ); assert( pEntry->Count == 1 ); // read area pToken = strtok( NULL, " \t\n" ); pEntry->Count = atoi(pToken); } fclose( pFile ); } /**Function************************************************************* Synopsis [Comparison procedure for two entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Npn_ManCompareEntries( Npn_Obj_t ** pp1, Npn_Obj_t ** pp2 ) { if ( (*pp1)->Count > (*pp2)->Count ) return -1; if ( (*pp1)->Count < (*pp2)->Count ) return 1; return 0; } /**Function************************************************************* Synopsis [Adds one entry to the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_ManWrite( Npn_Man_t * p, char * pFileName ) { Vec_Ptr_t * vEntries; Npn_Obj_t * pEntry; FILE * pFile = fopen( pFileName, "w" ); int i; if ( pFile == NULL ) { Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName ); return; } vEntries = Vec_PtrAlloc( p->nEntries ); for ( i = 0; i < p->nBins; i++ ) for ( pEntry = Npn_ManObj(p, p->pBins[i]); pEntry; pEntry = Npn_ManObj(p, pEntry->iNext) ) Vec_PtrPush( vEntries, pEntry ); Vec_PtrSort( vEntries, (int (*)())Npn_ManCompareEntries ); Vec_PtrForEachEntry( Npn_Obj_t *, vEntries, pEntry, i ) { Extra_PrintHexadecimal( pFile, (unsigned *)&pEntry->uTruth, 6 ); fprintf( pFile, " %d %d\n", pEntry->Count, Npn_TruthSuppSize(pEntry->uTruth, 6) ); } fclose( pFile ); Vec_PtrFree( vEntries ); } /**Function************************************************************* Synopsis [Creates the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Npn_Man_t * Npn_ManStart( char * pFileName ) { Npn_Man_t * p; p = ABC_CALLOC( Npn_Man_t, 1 ); if ( pFileName == NULL ) { p->nBufferSize = 1000000; p->nBufferSize = 100; p->pBuffer = ABC_ALLOC( Npn_Obj_t, p->nBufferSize ); p->nBins = Abc_PrimeCudd( p->nBufferSize / 2 ); p->pBins = ABC_CALLOC( int, p->nBins ); p->nEntries = 1; } else { FILE * pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { Abc_Print( -1, "Cannot open NPN function file \"%s\".\n", pFileName ); return NULL; } fclose( pFile ); p->nBufferSize = 4 * ( Extra_FileSize(pFileName) / 20 ); p->pBuffer = ABC_ALLOC( Npn_Obj_t, p->nBufferSize ); p->nBins = Abc_PrimeCudd( p->nBufferSize / 2 ); p->pBins = ABC_CALLOC( int, p->nBins ); p->nEntries = 1; Npn_ManRead( p, pFileName ); } return p; } /**Function************************************************************* Synopsis [Deletes the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_ManStop( Npn_Man_t * p ) { ABC_FREE( p->pBuffer ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Cleans the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_ManClean() { if ( pNpnMan != NULL ) { Npn_ManStop( pNpnMan ); pNpnMan = NULL; } } /**Function************************************************************* Synopsis [Loads functions from a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_ManLoad( char * pFileName ) { // Npn_TruthPermute_rec( "012345", 0, 5 ); if ( pNpnMan != NULL ) { Abc_Print( 1, "Removing old table with %d entries.\n", pNpnMan->nEntries ); Npn_ManStop( pNpnMan ); } pNpnMan = Npn_ManStart( pFileName ); Abc_Print( 1, "Created new table with %d entries from file \"%s\".\n", pNpnMan->nEntries, pFileName ); } /**Function************************************************************* Synopsis [Saves functions into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_ManSave( char * pFileName ) { if ( pNpnMan == NULL ) { Abc_Print( 1, "There is no table with entries.\n" ); return; } Npn_ManWrite( pNpnMan, pFileName ); Abc_Print( 1, "Dumped table with %d entries from file \"%s\".\n", pNpnMan->nEntries, pFileName ); } /**Function************************************************************* Synopsis [Saves one function into storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Npn_ManSaveOne( unsigned * puTruth, int nVars ) { word uTruth = (((word)puTruth[1]) << 32) | (word)puTruth[0]; assert( nVars >= 0 && nVars <= 6 ); if ( pNpnMan == NULL ) { Abc_Print( 1, "Creating new table with 0 entries.\n" ); pNpnMan = Npn_ManStart( NULL ); } // skip truth tables that do not depend on some vars if ( !Npn_TruthIsMinBase( uTruth ) ) return; // extend truth table to look like 6-input uTruth = Npn_TruthPadWord( uTruth, nVars ); // semi(!)-NPN-canonize the truth table uTruth = Npn_TruthCanon( uTruth, 6, NULL ); // add to storage Npn_ManAdd( pNpnMan, uTruth ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcNtbdd.c000066400000000000000000000521351300674244400235170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcNtbdd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to translate between the BDD and the network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/saig/saig.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ); static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st__table * tBdd2Node ); static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Constructs the network isomorphic to the given BDD.] Description [Assumes that the BDD depends on the variables whose indexes correspond to the names in the array (pNamesPi). Otherwise, returns NULL. The resulting network comes with one node, whose functionality is equal to the given BDD. To decompose this BDD into the network of multiplexers use Abc_NtkBddToMuxes(). To decompose this BDD into an And-Inverter Graph, use Abc_NtkStrash().] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd0, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ) { DdManager * dd = (DdManager *)dd0; Abc_Ntk_t * pNtk; Vec_Ptr_t * vNamesPiFake = NULL; Abc_Obj_t * pNode, * pNodePi, * pNodePo; DdNode * bSupp, * bTemp; char * pName; int i; // supply fake names if real names are not given if ( pNamePo == NULL ) pNamePo = "F"; if ( vNamesPi == NULL ) { vNamesPiFake = Abc_NodeGetFakeNames( dd->size ); vNamesPi = vNamesPiFake; } // make sure BDD depends on the variables whose index // does not exceed the size of the array with PI names bSupp = Cudd_Support( dd, (DdNode *)bFunc ); Cudd_Ref( bSupp ); for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) if ( (int)Cudd_NodeReadIndex(bTemp) >= Vec_PtrSize(vNamesPi) ) break; Cudd_RecursiveDeref( dd, bSupp ); if ( bTemp != Cudd_ReadOne(dd) ) return NULL; // start the network pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); pNtk->pName = Extra_UtilStrsav(pNamePo); // make sure the new manager has enough inputs Cudd_bddIthVar( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vNamesPi) ); // add the PIs corresponding to the names Vec_PtrForEachEntry( char *, vNamesPi, pName, i ) Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), pName, NULL ); // create the node pNode = Abc_NtkCreateNode( pNtk ); pNode->pData = (DdNode *)Cudd_bddTransfer( dd, (DdManager *)pNtk->pManFunc, (DdNode *)bFunc ); Cudd_Ref((DdNode *)pNode->pData); Abc_NtkForEachPi( pNtk, pNodePi, i ) Abc_ObjAddFanin( pNode, pNodePi ); // create the only PO pNodePo = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pNodePo, pNode ); Abc_ObjAssignName( pNodePo, pNamePo, NULL ); // make the network minimum base Abc_NtkMinimumBase( pNtk ); if ( vNamesPiFake ) Abc_NodeFreeNames( vNamesPiFake ); if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkDeriveFromBdd(): Network check has failed.\n" ); return pNtk; } /**Function************************************************************* Synopsis [Creates the network isomorphic to the union of local BDDs of the nodes.] Description [The nodes of the local BDDs are converted into the network nodes with logic functions equal to the MUX.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; assert( Abc_NtkIsBddLogic(pNtk) ); pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); Abc_NtkBddToMuxesPerform( pNtk, pNtkNew ); Abc_NtkFinalize( pNtk, pNtkNew ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkBddToMuxes: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Converts the network to MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { ProgressBar * pProgress; Abc_Obj_t * pNode, * pNodeNew; Vec_Ptr_t * vNodes; int i; // perform conversion in the topological order vNodes = Abc_NtkDfs( pNtk, 0 ); pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // convert one node assert( Abc_ObjIsNode(pNode) ); pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew ); // mark the old node with the new one assert( pNode->pCopy == NULL ); pNode->pCopy = pNodeNew; } Vec_PtrFree( vNodes ); Extra_ProgressBarStop( pProgress ); } /**Function************************************************************* Synopsis [Converts the node to MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ) { DdManager * dd = (DdManager *)pNodeOld->pNtk->pManFunc; DdNode * bFunc = (DdNode *)pNodeOld->pData; Abc_Obj_t * pFaninOld, * pNodeNew; st__table * tBdd2Node; int i; // 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 Abc_ObjForEachFanin( pNodeOld, pFaninOld, i ) st__insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pFaninOld->pCopy ); // create the new nodes recursively pNodeNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node ); st__free_table( tBdd2Node ); if ( Cudd_IsComplement(bFunc) ) pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew ); return pNodeNew; } /**Function************************************************************* Synopsis [Converts the node to MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st__table * tBdd2Node ) { Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC; assert( !Cudd_IsComplement(bFunc) ); if ( bFunc == b1 ) return Abc_NtkCreateNodeConst1(pNtkNew); if ( st__lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) ) return pNodeNew; // solve for the children nodes pNodeNew0 = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNtkNew, tBdd2Node ); if ( Cudd_IsComplement(cuddE(bFunc)) ) pNodeNew0 = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew0 ); pNodeNew1 = Abc_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNtkNew, tBdd2Node ); if ( ! st__lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeNewC ) ) assert( 0 ); // create the MUX node pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 ); st__insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew ); return pNodeNew; } /**Function************************************************************* Synopsis [Derives global BDDs for the COs of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) { ProgressBar * pProgress; Abc_Obj_t * pObj, * pFanin; Vec_Att_t * pAttMan; DdManager * dd; DdNode * bFunc; int i, k, Counter; // remove dangling nodes Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); // start the manager assert( Abc_NtkGlobalBdd(pNtk) == NULL ); dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); pAttMan = Vec_AttAlloc( Abc_NtkObjNumMax(pNtk) + 1, dd, (void (*)(void*))Extra_StopManager, NULL, (void (*)(void*,void*))Cudd_RecursiveDeref ); Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD, pAttMan ); // set reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); // assign the constant node BDD pObj = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pObj) > 0 ) { bFunc = dd->one; Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); } // set the elementary variables Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) { bFunc = dd->vars[i]; // bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i]; Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); } // collect the global functions of the COs Counter = 0; // construct the BDDs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) { bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); if ( bFunc == NULL ) { if ( fVerbose ) printf( "Constructing global BDDs is aborted.\n" ); Abc_NtkFreeGlobalBdds( pNtk, 0 ); Cudd_Quit( dd ); // reset references Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBi(pObj) ) pObj->vFanouts.nSize = 0; Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) pFanin->vFanouts.nSize++; return NULL; } bFunc = Cudd_NotCond( bFunc, (int)Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); Abc_ObjSetGlobalBdd( pObj, bFunc ); } Extra_ProgressBarStop( pProgress ); /* // derefence the intermediate BDDs Abc_NtkForEachNode( pNtk, pObj, i ) if ( pObj->pCopy ) { Cudd_RecursiveDeref( dd, (DdNode *)pObj->pCopy ); pObj->pCopy = NULL; } */ /* // make sure all nodes are derefed Abc_NtkForEachObj( pNtk, pObj, i ) { if ( pObj->pCopy != NULL ) printf( "Abc_NtkBuildGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id ); if ( pObj->vFanouts.nSize > 0 ) printf( "Abc_NtkBuildGlobalBdds() error: Node %d has refs assigned\n", pObj->Id ); } */ // reset references Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBi(pObj) ) pObj->vFanouts.nSize = 0; Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) pFanin->vFanouts.nSize++; // reorder one more time if ( fReorder ) { Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); Cudd_AutodynDisable( dd ); } // Cudd_PrintInfo( dd, stdout ); return dd; } /**Function************************************************************* Synopsis [Derives the global BDD for one AIG node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) { DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC; int fDetectMuxes = 0; assert( !Abc_ObjIsComplement(pNode) ); if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) { Extra_ProgressBarStop( pProgress ); if ( fVerbose ) printf( "The number of live nodes reached %d.\n", nBddSizeMax ); fflush( stdout ); return NULL; } // if the result is available return if ( Abc_ObjGlobalBdd(pNode) == NULL ) { Abc_Obj_t * pNodeC, * pNode0, * pNode1; pNode0 = Abc_ObjFanin0(pNode); pNode1 = Abc_ObjFanin1(pNode); // check for the special case when it is MUX/EXOR if ( fDetectMuxes && Abc_ObjGlobalBdd(pNode0) == NULL && Abc_ObjGlobalBdd(pNode1) == NULL && Abc_ObjIsNode(pNode0) && Abc_ObjFanoutNum(pNode0) == 1 && Abc_ObjIsNode(pNode1) && Abc_ObjFanoutNum(pNode1) == 1 && Abc_NodeIsMuxType(pNode) ) { // deref the fanins pNode0->vFanouts.nSize--; pNode1->vFanouts.nSize--; // recognize the MUX pNodeC = Abc_NodeRecognizeMux( pNode, &pNode1, &pNode0 ); assert( Abc_ObjFanoutNum(pNodeC) > 1 ); // dereference the control once (the second time it will be derefed when BDDs are computed) pNodeC->vFanouts.nSize--; // compute the result for all branches bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFuncC == NULL ) return NULL; Cudd_Ref( bFuncC ); bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc0 == NULL ) return NULL; Cudd_Ref( bFunc0 ); bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc1 == NULL ) return NULL; Cudd_Ref( bFunc1 ); // complement the branch BDDs bFunc0 = Cudd_NotCond( bFunc0, (int)Abc_ObjIsComplement(pNode0) ); bFunc1 = Cudd_NotCond( bFunc1, (int)Abc_ObjIsComplement(pNode1) ); // get the final result bFunc = Cudd_bddIte( dd, bFuncC, bFunc1, bFunc0 ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bFunc0 ); Cudd_RecursiveDeref( dd, bFunc1 ); Cudd_RecursiveDeref( dd, bFuncC ); // add the number of used nodes (*pCounter) += 3; } else { // compute the result for both branches bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc0 == NULL ) return NULL; Cudd_Ref( bFunc0 ); bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc1 == NULL ) return NULL; Cudd_Ref( bFunc1 ); bFunc0 = Cudd_NotCond( bFunc0, (int)Abc_ObjFaninC0(pNode) ); bFunc1 = Cudd_NotCond( bFunc1, (int)Abc_ObjFaninC1(pNode) ); // get the final result bFunc = Cudd_bddAndLimit( dd, bFunc0, bFunc1, nBddSizeMax ); if ( bFunc == NULL ) return NULL; Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bFunc0 ); Cudd_RecursiveDeref( dd, bFunc1 ); // add the number of used nodes (*pCounter)++; } // set the result assert( Abc_ObjGlobalBdd(pNode) == NULL ); Abc_ObjSetGlobalBdd( pNode, bFunc ); // increment the progress bar if ( pProgress ) Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); } // prepare the return value bFunc = (DdNode *)Abc_ObjGlobalBdd(pNode); // dereference BDD at the node if ( --pNode->vFanouts.nSize == 0 && fDropInternal ) { Cudd_Deref( bFunc ); Abc_ObjSetGlobalBdd( pNode, NULL ); } return bFunc; } /**Function************************************************************* Synopsis [Frees the global BDDs of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ) { return Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, fFreeMan ); } /**Function************************************************************* Synopsis [Returns the shared size of global BDDs of the COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vFuncsGlob; Abc_Obj_t * pObj; int RetValue, i; // complement the global functions vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); Vec_PtrFree( vFuncsGlob ); return RetValue; } /**Function************************************************************* Synopsis [Computes the BDD of the logic cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) { /* Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pNodeR; DdManager * dd; DdNode * bFunc; double Result; int i; pNodeR = Abc_ObjRegular(pNode); assert( Abc_NtkIsStrash(pNodeR->pNtk) ); Abc_NtkCleanCopy( pNodeR->pNtk ); // get the CIs in the support of the node vNodes = Abc_NtkNodeSupport( pNodeR->pNtk, &pNodeR, 1 ); // start the manager dd = Cudd_Init( Vec_PtrSize(vNodes), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); // assign elementary BDDs for the CIs Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)dd->vars[i]; // build the BDD of the cone bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, 1, NULL, NULL, 1 ); Cudd_Ref( bFunc ); bFunc = Cudd_NotCond( bFunc, pNode != pNodeR ); // count minterms Result = Cudd_CountMinterm( dd, bFunc, dd->size ); // get the percentagle Result *= 100.0; for ( i = 0; i < dd->size; i++ ) Result /= 2; // clean up Cudd_Quit( dd ); Vec_PtrFree( vNodes ); return Result; */ return 0.0; } /**Function************************************************************* Synopsis [Experiment with BDD-based representation of implications.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBddImplicationTest() { DdManager * dd; DdNode * bImp, * bSum, * bTemp; int nVars = 200; int nImps = 200; int i; abctime clk; clk = Abc_Clock(); dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SIFT ); bSum = b0; Cudd_Ref( bSum ); for ( i = 0; i < nImps; i++ ) { printf( "." ); bImp = Cudd_bddAnd( dd, dd->vars[rand()%nVars], dd->vars[rand()%nVars] ); Cudd_Ref( bImp ); bSum = Cudd_bddOr( dd, bTemp = bSum, bImp ); Cudd_Ref( bSum ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bImp ); } printf( "The BDD before = %d.\n", Cudd_DagSize(bSum) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SIFT, 1 ); printf( "The BDD after = %d.\n", Cudd_DagSize(bSum) ); ABC_PRT( "Time", Abc_Clock() - clk ); Cudd_RecursiveDeref( dd, bSum ); Cudd_Quit( dd ); } #else double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) { return 0.0; } Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ) { return NULL; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcOdc.c000066400000000000000000001116231300674244400231670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcOdc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Scalable computation of observability don't-cares.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcOdc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_DC_MAX_NODES (1<<15) typedef unsigned short Odc_Lit_t; typedef struct Odc_Obj_t_ Odc_Obj_t; // 16 bytes struct Odc_Obj_t_ { Odc_Lit_t iFan0; // first fanin Odc_Lit_t iFan1; // second fanin Odc_Lit_t iNext; // next node in the hash table unsigned short TravId; // the traversal ID unsigned uData; // the computed data unsigned uMask; // the variable mask }; struct Odc_Man_t_ { // dont'-care parameters int nVarsMax; // the max number of cut variables int nLevels; // the number of ODC levels int fVerbose; // the verbosiness flag int fVeryVerbose;// the verbosiness flag to print per-node stats int nPercCutoff; // cutoff percentage // windowing Abc_Obj_t * pNode; // the node for windowing Vec_Ptr_t * vLeaves; // the number of the cut Vec_Ptr_t * vRoots; // the roots of the cut Vec_Ptr_t * vBranches; // additional inputs // internal AIG package // objects int nPis; // number of PIs (nVarsMax + 32) int nObjs; // number of objects (Const1, PIs, ANDs) int nObjsAlloc; // number of objects allocated Odc_Obj_t * pObjs; // objects Odc_Lit_t iRoot; // the root object unsigned short nTravIds; // the number of travIDs // structural hashing Odc_Lit_t * pTable; // hash table int nTableSize; // hash table size Vec_Int_t * vUsedSpots; // the used spots // truth tables int nBits; // the number of bits int nWords; // the number of words Vec_Ptr_t * vTruths; // truth tables for each node Vec_Ptr_t * vTruthsElem; // elementary truth tables for the PIs unsigned * puTruth; // the place where the resulting truth table does // statistics int nWins; // the number of windows processed int nWinsEmpty; // the number of empty windows int nSimsEmpty; // the number of empty simulation infos int nQuantsOver; // the number of quantification overflows int nWinsFinish; // the number of windows that finished int nTotalDcs; // total percentage of DCs // runtime abctime timeClean; // windowing abctime timeWin; // windowing abctime timeMiter; // computing the miter abctime timeSim; // simulation abctime timeQuant; // quantification abctime timeTruth; // truth table abctime timeTotal; // useful runtime abctime timeAbort; // aborted runtime }; // quantity of different objects static inline int Odc_PiNum( Odc_Man_t * p ) { return p->nPis; } static inline int Odc_NodeNum( Odc_Man_t * p ) { return p->nObjs - p->nPis - 1; } static inline int Odc_ObjNum( Odc_Man_t * p ) { return p->nObjs; } // complemented attributes of objects static inline int Odc_IsComplement( Odc_Lit_t Lit ) { return Lit & (Odc_Lit_t)1; } static inline Odc_Lit_t Odc_Regular( Odc_Lit_t Lit ) { return Lit & ~(Odc_Lit_t)1; } static inline Odc_Lit_t Odc_Not( Odc_Lit_t Lit ) { return Lit ^ (Odc_Lit_t)1; } static inline Odc_Lit_t Odc_NotCond( Odc_Lit_t Lit, int c ) { return Lit ^ (Odc_Lit_t)(c!=0); } // specialized Literals static inline Odc_Lit_t Odc_Const0() { return 1; } static inline Odc_Lit_t Odc_Const1() { return 0; } static inline Odc_Lit_t Odc_Var( Odc_Man_t * p, int i ) { assert( i >= 0 && i < p->nPis ); return (i+1) << 1; } static inline int Odc_IsConst( Odc_Lit_t Lit ) { return Lit < (Odc_Lit_t)2; } static inline int Odc_IsTerm( Odc_Man_t * p, Odc_Lit_t Lit ) { return (int)(Lit>>1) <= p->nPis; } // accessing internal storage static inline Odc_Obj_t * Odc_ObjNew( Odc_Man_t * p ) { assert( p->nObjs < p->nObjsAlloc ); return p->pObjs + p->nObjs++; } static inline Odc_Lit_t Odc_Obj2Lit( Odc_Man_t * p, Odc_Obj_t * pObj ) { assert( pObj ); return (pObj - p->pObjs) << 1; } static inline Odc_Obj_t * Odc_Lit2Obj( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) && (int)(Lit>>1) < p->nObjs ); return p->pObjs + (Lit>>1); } // fanins and their complements static inline Odc_Lit_t Odc_ObjChild0( Odc_Obj_t * pObj ) { return pObj->iFan0; } static inline Odc_Lit_t Odc_ObjChild1( Odc_Obj_t * pObj ) { return pObj->iFan1; } static inline Odc_Lit_t Odc_ObjFanin0( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan0); } static inline Odc_Lit_t Odc_ObjFanin1( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan1); } static inline int Odc_ObjFaninC0( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan0); } static inline int Odc_ObjFaninC1( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan1); } // traversal IDs static inline void Odc_ManIncrementTravId( Odc_Man_t * p ) { p->nTravIds++; } static inline void Odc_ObjSetTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } static inline int Odc_ObjIsTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } // truth tables static inline unsigned * Odc_ObjTruth( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) ); return (unsigned *) Vec_PtrEntry(p->vTruths, Lit >> 1); } // iterators #define Odc_ForEachPi( p, Lit, i ) \ for ( i = 0; (i < Odc_PiNum(p)) && (((Lit) = Odc_Var(p, i)), 1); i++ ) #define Odc_ForEachAnd( p, pObj, i ) \ for ( i = 1 + Odc_CiNum(p); (i < Odc_ObjNum(p)) && ((pObj) = (p)->pObjs + i); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the don't-care manager.] Description [The parameters are the max number of cut variables, the number of fanout levels used for the ODC computation, and verbosiness.] SideEffects [] SeeAlso [] ***********************************************************************/ Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ) { Odc_Man_t * p; unsigned * pData; int i, k; p = ABC_ALLOC( Odc_Man_t, 1 ); memset( p, 0, sizeof(Odc_Man_t) ); assert( nVarsMax > 4 && nVarsMax < 16 ); assert( nLevels > 0 && nLevels < 10 ); srand( 0xABC ); // dont'-care parameters p->nVarsMax = nVarsMax; p->nLevels = nLevels; p->fVerbose = fVerbose; p->fVeryVerbose = fVeryVerbose; p->nPercCutoff = 10; // windowing p->vRoots = Vec_PtrAlloc( 128 ); p->vBranches = Vec_PtrAlloc( 128 ); // internal AIG package // allocate room for objects p->nObjsAlloc = ABC_DC_MAX_NODES; p->pObjs = ABC_ALLOC( Odc_Obj_t, p->nObjsAlloc * sizeof(Odc_Obj_t) ); p->nPis = nVarsMax + 32; p->nObjs = 1 + p->nPis; memset( p->pObjs, 0, p->nObjs * sizeof(Odc_Obj_t) ); // set the PI masks for ( i = 0; i < 32; i++ ) p->pObjs[1 + p->nVarsMax + i].uMask = (1 << i); // allocate hash table p->nTableSize = p->nObjsAlloc/3 + 1; p->pTable = ABC_ALLOC( Odc_Lit_t, p->nTableSize * sizeof(Odc_Lit_t) ); memset( p->pTable, 0, p->nTableSize * sizeof(Odc_Lit_t) ); p->vUsedSpots = Vec_IntAlloc( 1000 ); // truth tables p->nWords = Abc_TruthWordNum( p->nVarsMax ); p->nBits = p->nWords * 8 * sizeof(unsigned); p->vTruths = Vec_PtrAllocSimInfo( p->nObjsAlloc, p->nWords ); p->vTruthsElem = Vec_PtrAllocSimInfo( p->nVarsMax, p->nWords ); // set elementary truth tables Abc_InfoFill( (unsigned *)Vec_PtrEntry(p->vTruths, 0), p->nWords ); for ( k = 0; k < p->nVarsMax; k++ ) { // pData = Odc_ObjTruth( p, Odc_Var(p, k) ); pData = (unsigned *)Vec_PtrEntry( p->vTruthsElem, k ); Abc_InfoClear( pData, p->nWords ); for ( i = 0; i < p->nBits; i++ ) if ( i & (1 << k) ) pData[i>>5] |= (1 << (i&31)); } // set random truth table for the additional inputs for ( k = p->nVarsMax; k < p->nPis; k++ ) { pData = Odc_ObjTruth( p, Odc_Var(p, k) ); Abc_InfoRandom( pData, p->nWords ); } // set the miter to the unused value p->iRoot = 0xffff; return p; } /**Function************************************************************* Synopsis [Clears the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareClear( Odc_Man_t * p ) { abctime clk = Abc_Clock(); // clean the structural hashing table if ( Vec_IntSize(p->vUsedSpots) > p->nTableSize/3 ) // more than one third memset( p->pTable, 0, sizeof(Odc_Lit_t) * p->nTableSize ); else { int iSpot, i; Vec_IntForEachEntry( p->vUsedSpots, iSpot, i ) p->pTable[iSpot] = 0; } Vec_IntClear( p->vUsedSpots ); // reset the number of nodes p->nObjs = 1 + p->nPis; // reset the root node p->iRoot = 0xffff; p->timeClean += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Frees the don't-care manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareFree( Odc_Man_t * p ) { if ( p->fVerbose ) { printf( "Wins = %5d. Empty = %5d. SimsEmpty = %5d. QuantOver = %5d. WinsFinish = %5d.\n", p->nWins, p->nWinsEmpty, p->nSimsEmpty, p->nQuantsOver, p->nWinsFinish ); printf( "Ave DCs per window = %6.2f %%. Ave DCs per finished window = %6.2f %%.\n", 1.0*p->nTotalDcs/p->nWins, 1.0*p->nTotalDcs/p->nWinsFinish ); printf( "Runtime stats of the ODC manager:\n" ); ABC_PRT( "Cleaning ", p->timeClean ); ABC_PRT( "Windowing ", p->timeWin ); ABC_PRT( "Miter ", p->timeMiter ); ABC_PRT( "Simulation ", p->timeSim ); ABC_PRT( "Quantifying ", p->timeQuant ); ABC_PRT( "Truth table ", p->timeTruth ); ABC_PRT( "TOTAL ", p->timeTotal ); ABC_PRT( "Aborted ", p->timeAbort ); } Vec_PtrFree( p->vRoots ); Vec_PtrFree( p->vBranches ); Vec_PtrFree( p->vTruths ); Vec_PtrFree( p->vTruthsElem ); Vec_IntFree( p->vUsedSpots ); ABC_FREE( p->pObjs ); ABC_FREE( p->pTable ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Marks the TFO of the collected nodes up to the given level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanout; int i; if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit || pObj == pNode ) return; if ( Abc_NodeIsTravIdCurrent(pObj) ) return; Abc_NodeSetTravIdCurrent( pObj ); //////////////////////////////////////// // try to reduce the runtime if ( Abc_ObjFanoutNum(pObj) > 100 ) return; //////////////////////////////////////// Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_NtkDontCareWinSweepLeafTfo_rec( pFanout, nLevelLimit, pNode ); } /**Function************************************************************* Synopsis [Marks the TFO of the collected nodes up to the given level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareWinSweepLeafTfo( Odc_Man_t * p ) { Abc_Obj_t * pObj; int i; Abc_NtkIncrementTravId( p->pNode->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i ) Abc_NtkDontCareWinSweepLeafTfo_rec( pObj, p->pNode->Level + p->nLevels, p->pNode ); } /**Function************************************************************* Synopsis [Recursively collects the roots.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareWinCollectRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots ) { Abc_Obj_t * pFanout; int i; assert( Abc_ObjIsNode(pObj) ); assert( Abc_NodeIsTravIdCurrent(pObj) ); // check if the node has all fanouts marked Abc_ObjForEachFanout( pObj, pFanout, i ) if ( !Abc_NodeIsTravIdCurrent(pFanout) ) break; // if some of the fanouts are unmarked, add the node to the root if ( i < Abc_ObjFanoutNum(pObj) ) { Vec_PtrPushUnique( vRoots, pObj ); return; } // otherwise, call recursively Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_NtkDontCareWinCollectRoots_rec( pFanout, vRoots ); } /**Function************************************************************* Synopsis [Collects the roots of the window.] Description [Roots of the window are the nodes that have at least one fanout that it not in the TFO of the leaves.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareWinCollectRoots( Odc_Man_t * p ) { assert( !Abc_NodeIsTravIdCurrent(p->pNode) ); // mark the node with the old traversal ID Abc_NodeSetTravIdCurrent( p->pNode ); // collect the roots Vec_PtrClear( p->vRoots ); Abc_NtkDontCareWinCollectRoots_rec( p->pNode, p->vRoots ); } /**Function************************************************************* Synopsis [Recursively adds missing nodes and leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDontCareWinAddMissing_rec( Odc_Man_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; // skip the already collected leaves and branches if ( Abc_NodeIsTravIdCurrent(pObj) ) return 1; // if this is not an internal node - make it a new branch if ( !Abc_NodeIsTravIdPrevious(pObj) || Abc_ObjIsCi(pObj) ) //|| (int)pObj->Level <= p->nLevLeaves ) { Abc_NodeSetTravIdCurrent( pObj ); Vec_PtrPush( p->vBranches, pObj ); return Vec_PtrSize(p->vBranches) <= 32; } // visit the fanins of the node Abc_ObjForEachFanin( pObj, pFanin, i ) if ( !Abc_NtkDontCareWinAddMissing_rec( p, pFanin ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Adds to the window nodes and leaves in the TFI of the roots.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDontCareWinAddMissing( Odc_Man_t * p ) { Abc_Obj_t * pObj; int i; // set the leaves Abc_NtkIncrementTravId( p->pNode->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); // explore from the roots Vec_PtrClear( p->vBranches ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i ) if ( !Abc_NtkDontCareWinAddMissing_rec( p, pObj ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Computes window for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDontCareWindow( Odc_Man_t * p ) { // mark the TFO of the collected nodes up to the given level (p->pNode->Level + p->nWinTfoMax) Abc_NtkDontCareWinSweepLeafTfo( p ); // find the roots of the window Abc_NtkDontCareWinCollectRoots( p ); if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) { // printf( "Empty window\n" ); return 0; } // add the nodes in the TFI of the roots that are not yet in the window if ( !Abc_NtkDontCareWinAddMissing( p ) ) { // printf( "Too many branches (%d)\n", Vec_PtrSize(p->vBranches) ); return 0; } return 1; } /**Function************************************************************* Synopsis [Performing hashing of two AIG Literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Odc_HashKey( Odc_Lit_t iFan0, Odc_Lit_t iFan1, int TableSize ) { unsigned Key = 0; Key ^= Odc_Regular(iFan0) * 7937; Key ^= Odc_Regular(iFan1) * 2971; Key ^= Odc_IsComplement(iFan0) * 911; Key ^= Odc_IsComplement(iFan1) * 353; return Key % TableSize; } /**Function************************************************************* Synopsis [Checks if the given name node already exists in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Odc_Lit_t * Odc_HashLookup( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) { Odc_Obj_t * pObj; Odc_Lit_t * pEntry; unsigned uHashKey; assert( iFan0 < iFan1 ); // get the hash key for this node uHashKey = Odc_HashKey( iFan0, iFan1, p->nTableSize ); // remember the spot in the hash table that will be used if ( p->pTable[uHashKey] == 0 ) Vec_IntPush( p->vUsedSpots, uHashKey ); // find the entry for ( pEntry = p->pTable + uHashKey; *pEntry; pEntry = &pObj->iNext ) { pObj = Odc_Lit2Obj( p, *pEntry ); if ( pObj->iFan0 == iFan0 && pObj->iFan1 == iFan1 ) return pEntry; } return pEntry; } /**Function************************************************************* Synopsis [Finds node by structural hashing or creates a new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Odc_Lit_t Odc_And( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) { Odc_Obj_t * pObj; Odc_Lit_t * pEntry; unsigned uMask0, uMask1; int Temp; // consider trivial cases if ( iFan0 == iFan1 ) return iFan0; if ( iFan0 == Odc_Not(iFan1) ) return Odc_Const0(); if ( Odc_Regular(iFan0) == Odc_Const1() ) return iFan0 == Odc_Const1() ? iFan1 : Odc_Const0(); if ( Odc_Regular(iFan1) == Odc_Const1() ) return iFan1 == Odc_Const1() ? iFan0 : Odc_Const0(); // canonicize the fanin order if ( iFan0 > iFan1 ) Temp = iFan0, iFan0 = iFan1, iFan1 = Temp; // check if a node with these fanins exists pEntry = Odc_HashLookup( p, iFan0, iFan1 ); if ( *pEntry ) return *pEntry; // create a new node pObj = Odc_ObjNew( p ); pObj->iFan0 = iFan0; pObj->iFan1 = iFan1; pObj->iNext = 0; pObj->TravId = 0; // set the mask uMask0 = Odc_Lit2Obj(p, Odc_Regular(iFan0))->uMask; uMask1 = Odc_Lit2Obj(p, Odc_Regular(iFan1))->uMask; pObj->uMask = uMask0 | uMask1; // add to the table *pEntry = Odc_Obj2Lit( p, pObj ); return *pEntry; } /**Function************************************************************* Synopsis [Boolean OR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Odc_Lit_t Odc_Or( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) { return Odc_Not( Odc_And(p, Odc_Not(iFan0), Odc_Not(iFan1)) ); } /**Function************************************************************* Synopsis [Boolean XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Odc_Lit_t Odc_Xor( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) { return Odc_Or( p, Odc_And(p, iFan0, Odc_Not(iFan1)), Odc_And(p, Odc_Not(iFan0), iFan1) ); } /**Function************************************************************* Synopsis [Transfers the window into the AIG package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NtkDontCareTransfer_rec( Odc_Man_t * p, Abc_Obj_t * pNode, Abc_Obj_t * pPivot ) { unsigned uData0, uData1; Odc_Lit_t uLit0, uLit1, uRes0, uRes1; assert( !Abc_ObjIsComplement(pNode) ); // skip visited objects if ( Abc_NodeIsTravIdCurrent(pNode) ) return pNode->pCopy; Abc_NodeSetTravIdCurrent(pNode); assert( Abc_ObjIsNode(pNode) ); // consider the case when the node is the pivot if ( pNode == pPivot ) return pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)((Odc_Const1() << 16) | Odc_Const0()); // compute the cofactors uData0 = (unsigned)(ABC_PTRUINT_T)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin0(pNode), pPivot ); uData1 = (unsigned)(ABC_PTRUINT_T)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin1(pNode), pPivot ); // find the 0-cofactor uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Abc_ObjFaninC0(pNode) ); uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Abc_ObjFaninC1(pNode) ); uRes0 = Odc_And( p, uLit0, uLit1 ); // find the 1-cofactor uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Abc_ObjFaninC0(pNode) ); uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Abc_ObjFaninC1(pNode) ); uRes1 = Odc_And( p, uLit0, uLit1 ); // find the result return pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)((uRes1 << 16) | uRes0); } /**Function************************************************************* Synopsis [Transfers the window into the AIG package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDontCareTransfer( Odc_Man_t * p ) { Abc_Obj_t * pObj; Odc_Lit_t uRes0, uRes1; Odc_Lit_t uLit; unsigned uData; int i; Abc_NtkIncrementTravId( p->pNode->pNtk ); // set elementary variables at the leaves Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i ) { uLit = Odc_Var( p, i ); pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)((uLit << 16) | uLit); Abc_NodeSetTravIdCurrent(pObj); } // set elementary variables at the branched Vec_PtrForEachEntry( Abc_Obj_t *, p->vBranches, pObj, i ) { uLit = Odc_Var( p, i+p->nVarsMax ); pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)((uLit << 16) | uLit); Abc_NodeSetTravIdCurrent(pObj); } // compute the AIG for the window p->iRoot = Odc_Const0(); Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i ) { uData = (unsigned)(ABC_PTRUINT_T)Abc_NtkDontCareTransfer_rec( p, pObj, p->pNode ); // get the cofactors uRes0 = uData & 0xffff; uRes1 = uData >> 16; // compute the miter // assert( uRes0 != uRes1 ); // may be false if the node is redundant w.r.t. this root uLit = Odc_Xor( p, uRes0, uRes1 ); p->iRoot = Odc_Or( p, p->iRoot, uLit ); } return 1; } /**Function************************************************************* Synopsis [Recursively computes the pair of cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uMask ) { Odc_Obj_t * pObj; unsigned uData0, uData1; Odc_Lit_t uLit0, uLit1, uRes0, uRes1; assert( !Odc_IsComplement(Lit) ); // skip visited objects pObj = Odc_Lit2Obj( p, Lit ); if ( Odc_ObjIsTravIdCurrent(p, pObj) ) return pObj->uData; Odc_ObjSetTravIdCurrent(p, pObj); // skip objects out of the cone if ( (pObj->uMask & uMask) == 0 ) return pObj->uData = ((Lit << 16) | Lit); // consider the case when the node is the var if ( pObj->uMask == uMask && Odc_IsTerm(p, Lit) ) return pObj->uData = ((Odc_Const1() << 16) | Odc_Const0()); // compute the cofactors uData0 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin0(pObj), uMask ); uData1 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin1(pObj), uMask ); // find the 0-cofactor uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Odc_ObjFaninC0(pObj) ); uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Odc_ObjFaninC1(pObj) ); uRes0 = Odc_And( p, uLit0, uLit1 ); // find the 1-cofactor uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Odc_ObjFaninC0(pObj) ); uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Odc_ObjFaninC1(pObj) ); uRes1 = Odc_And( p, uLit0, uLit1 ); // find the result return pObj->uData = ((uRes1 << 16) | uRes0); } /**Function************************************************************* Synopsis [Quantifies the branch variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDontCareQuantify( Odc_Man_t * p ) { Odc_Lit_t uRes0, uRes1; unsigned uData; int i; assert( p->iRoot < 0xffff ); assert( Vec_PtrSize(p->vBranches) <= 32 ); // the mask size for ( i = 0; i < Vec_PtrSize(p->vBranches); i++ ) { // compute the cofactors w.r.t. this variable Odc_ManIncrementTravId( p ); uData = Abc_NtkDontCareCofactors_rec( p, Odc_Regular(p->iRoot), (1 << i) ); uRes0 = Odc_NotCond( (Odc_Lit_t)(uData & 0xffff), Odc_IsComplement(p->iRoot) ); uRes1 = Odc_NotCond( (Odc_Lit_t)(uData >> 16), Odc_IsComplement(p->iRoot) ); // quantify this variable existentially p->iRoot = Odc_Or( p, uRes0, uRes1 ); // check the limit if ( Odc_ObjNum(p) > ABC_DC_MAX_NODES/2 ) return 0; } assert( p->nObjs <= p->nObjsAlloc ); return 1; } /**Function************************************************************* Synopsis [Set elementary truth tables for PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareSimulateSetElem2( Odc_Man_t * p ) { unsigned * pData; int i, k; for ( k = 0; k < p->nVarsMax; k++ ) { pData = Odc_ObjTruth( p, Odc_Var(p, k) ); Abc_InfoClear( pData, p->nWords ); for ( i = 0; i < p->nBits; i++ ) if ( i & (1 << k) ) pData[i>>5] |= (1 << (i&31)); } } /**Function************************************************************* Synopsis [Set elementary truth tables for PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareSimulateSetElem( Odc_Man_t * p ) { unsigned * pData, * pData2; int k; for ( k = 0; k < p->nVarsMax; k++ ) { pData = Odc_ObjTruth( p, Odc_Var(p, k) ); pData2 = (unsigned *)Vec_PtrEntry( p->vTruthsElem, k ); Abc_InfoCopy( pData, pData2, p->nWords ); } } /**Function************************************************************* Synopsis [Set random simulation words for PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareSimulateSetRand( Odc_Man_t * p ) { unsigned * pData; int w, k, Number; for ( w = 0; w < p->nWords; w++ ) { Number = rand(); for ( k = 0; k < p->nVarsMax; k++ ) { pData = Odc_ObjTruth( p, Odc_Var(p, k) ); pData[w] = (Number & (1<nWords; w++ ) if ( puTruth[w] ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareTruthOne( Odc_Man_t * p, Odc_Lit_t Lit ) { Odc_Obj_t * pObj; unsigned * pInfo, * pInfo1, * pInfo2; int k, fComp1, fComp2; assert( !Odc_IsComplement( Lit ) ); assert( !Odc_IsTerm( p, Lit ) ); // get the truth tables pObj = Odc_Lit2Obj( p, Lit ); pInfo = Odc_ObjTruth( p, Lit ); pInfo1 = Odc_ObjTruth( p, Odc_ObjFanin0(pObj) ); pInfo2 = Odc_ObjTruth( p, Odc_ObjFanin1(pObj) ); fComp1 = Odc_ObjFaninC0( pObj ); fComp2 = Odc_ObjFaninC1( pObj ); // simulate if ( fComp1 && fComp2 ) for ( k = 0; k < p->nWords; k++ ) pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; else if ( fComp1 && !fComp2 ) for ( k = 0; k < p->nWords; k++ ) pInfo[k] = ~pInfo1[k] & pInfo2[k]; else if ( !fComp1 && fComp2 ) for ( k = 0; k < p->nWords; k++ ) pInfo[k] = pInfo1[k] & ~pInfo2[k]; else // if ( fComp1 && fComp2 ) for ( k = 0; k < p->nWords; k++ ) pInfo[k] = pInfo1[k] & pInfo2[k]; } /**Function************************************************************* Synopsis [Computes the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDontCareSimulate_rec( Odc_Man_t * p, Odc_Lit_t Lit ) { Odc_Obj_t * pObj; assert( !Odc_IsComplement(Lit) ); // skip terminals if ( Odc_IsTerm(p, Lit) ) return; // skip visited objects pObj = Odc_Lit2Obj( p, Lit ); if ( Odc_ObjIsTravIdCurrent(p, pObj) ) return; Odc_ObjSetTravIdCurrent(p, pObj); // call recursively Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin0(pObj) ); Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin1(pObj) ); // construct the truth table Abc_NtkDontCareTruthOne( p, Lit ); } /**Function************************************************************* Synopsis [Computes the truth table of the care set.] Description [Returns the number of ones in the simulation info.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDontCareSimulate( Odc_Man_t * p, unsigned * puTruth ) { Odc_ManIncrementTravId( p ); Abc_NtkDontCareSimulate_rec( p, Odc_Regular(p->iRoot) ); Abc_InfoCopy( puTruth, Odc_ObjTruth(p, Odc_Regular(p->iRoot)), p->nWords ); if ( Odc_IsComplement(p->iRoot) ) Abc_InfoNot( puTruth, p->nWords ); return Extra_TruthCountOnes( puTruth, p->nVarsMax ); } /**Function************************************************************* Synopsis [Computes the truth table of the care set.] Description [Returns the number of ones in the simulation info.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDontCareSimulateBefore( Odc_Man_t * p, unsigned * puTruth ) { int nIters = 2; int nRounds, Counter, r; // decide how many rounds to simulate nRounds = p->nBits / p->nWords; Counter = 0; for ( r = 0; r < nIters; r++ ) { Abc_NtkDontCareSimulateSetRand( p ); Abc_NtkDontCareSimulate( p, puTruth ); Counter += Abc_NtkDontCareCountMintsWord( p, puTruth ); } // normalize Counter = Counter * nRounds / nIters; return Counter; } /**Function************************************************************* Synopsis [Computes ODCs for the node in terms of the cut variables.] Description [Returns the number of don't care minterms in the truth table. In particular, this procedure returns 0 if there is no don't-cares.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ) { int nMints, RetValue; abctime clk, clkTotal = Abc_Clock(); p->nWins++; // set the parameters assert( !Abc_ObjIsComplement(pNode) ); assert( Abc_ObjIsNode(pNode) ); assert( Vec_PtrSize(vLeaves) <= p->nVarsMax ); p->vLeaves = vLeaves; p->pNode = pNode; // compute the window clk = Abc_Clock(); RetValue = Abc_NtkDontCareWindow( p ); p->timeWin += Abc_Clock() - clk; if ( !RetValue ) { p->timeAbort += Abc_Clock() - clkTotal; Abc_InfoFill( puTruth, p->nWords ); p->nWinsEmpty++; return 0; } if ( p->fVeryVerbose ) { printf( " %5d : ", pNode->Id ); printf( "Leaf = %2d ", Vec_PtrSize(p->vLeaves) ); printf( "Root = %2d ", Vec_PtrSize(p->vRoots) ); printf( "Bran = %2d ", Vec_PtrSize(p->vBranches) ); printf( " | " ); } // transfer the window into the AIG package clk = Abc_Clock(); Abc_NtkDontCareTransfer( p ); p->timeMiter += Abc_Clock() - clk; // simulate to estimate the amount of don't-cares clk = Abc_Clock(); nMints = Abc_NtkDontCareSimulateBefore( p, puTruth ); p->timeSim += Abc_Clock() - clk; if ( p->fVeryVerbose ) { printf( "AIG = %5d ", Odc_NodeNum(p) ); printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits ); } // if there is less then the given percentage of don't-cares, skip if ( 100.0 * (p->nBits - nMints) / p->nBits < 1.0 * p->nPercCutoff ) { p->timeAbort += Abc_Clock() - clkTotal; if ( p->fVeryVerbose ) printf( "Simulation cutoff.\n" ); Abc_InfoFill( puTruth, p->nWords ); p->nSimsEmpty++; return 0; } // quantify external variables clk = Abc_Clock(); RetValue = Abc_NtkDontCareQuantify( p ); p->timeQuant += Abc_Clock() - clk; if ( !RetValue ) { p->timeAbort += Abc_Clock() - clkTotal; if ( p->fVeryVerbose ) printf( "=== Overflow! ===\n" ); Abc_InfoFill( puTruth, p->nWords ); p->nQuantsOver++; return 0; } // get the truth table clk = Abc_Clock(); Abc_NtkDontCareSimulateSetElem( p ); nMints = Abc_NtkDontCareSimulate( p, puTruth ); p->timeTruth += Abc_Clock() - clk; if ( p->fVeryVerbose ) { printf( "AIG = %5d ", Odc_NodeNum(p) ); printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits ); printf( "\n" ); } p->timeTotal += Abc_Clock() - clkTotal; p->nWinsFinish++; p->nTotalDcs += (int)(100.0 * (p->nBits - nMints) / p->nBits); return nMints; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcOrder.c000066400000000000000000000100701300674244400235270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcOrder.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Exploring static BDD variable orders.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Changes the order of primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ) { Vec_Ptr_t * vSupp; vSupp = Abc_NtkSupport( pNtk ); Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse ); Vec_PtrFree( vSupp ); } /**Function************************************************************* Synopsis [Implements the given variable order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ) { char Buffer[1000]; FILE * pFile; Vec_Ptr_t * vSupp; Abc_Obj_t * pObj; pFile = fopen( pFileName, "r" ); vSupp = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); while ( fscanf( pFile, "%s", Buffer ) == 1 ) { pObj = Abc_NtkFindCi( pNtk, Buffer ); if ( pObj == NULL || !Abc_ObjIsCi(pObj) ) { printf( "Name \"%s\" is not a PI name. Cannot use this order.\n", Buffer ); Vec_PtrFree( vSupp ); fclose( pFile ); return; } Vec_PtrPush( vSupp, pObj ); } fclose( pFile ); if ( Vec_PtrSize(vSupp) != Abc_NtkCiNum(pNtk) ) { printf( "The number of names in the order (%d) is not the same as the number of PIs (%d).\n", Vec_PtrSize(vSupp), Abc_NtkCiNum(pNtk) ); Vec_PtrFree( vSupp ); return; } Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse ); Vec_PtrFree( vSupp ); } /**Function************************************************************* Synopsis [Changes the order of primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse ) { Abc_Obj_t * pObj; int i; assert( Vec_PtrSize(vSupp) == Abc_NtkCiNum(pNtk) ); // order CIs using the array if ( fReverse ) Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) Vec_PtrWriteEntry( pNtk->vCis, Vec_PtrSize(vSupp)-1-i, pObj ); else Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) Vec_PtrWriteEntry( pNtk->vCis, i, pObj ); // order PIs accordingly Vec_PtrClear( pNtk->vPis ); Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjIsPi(pObj) ) Vec_PtrPush( pNtk->vPis, pObj ); // Abc_NtkForEachCi( pNtk, pObj, i ) // printf( "%s ", Abc_ObjName(pObj) ); // printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcPart.c000066400000000000000000001135321300674244400233710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcPart.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Output partitioning package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcPart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "base/cmd/cmd.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Supp_Man_t_ Supp_Man_t; struct Supp_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 Supp_One_t_ Supp_One_t; struct Supp_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 Supp_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); } static inline char * Supp_OneNext( char * pPart ) { return *((char **)pPart); } static inline void Supp_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Start the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize ) { Supp_Man_t * p; p = ABC_ALLOC( Supp_Man_t, 1 ); memset( p, 0, sizeof(Supp_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 Supp_ManStop( Supp_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 * Supp_ManFetch( Supp_Man_t * p, int nSize ) { int Type, nSizeReal; char * pMemory; assert( nSize > 0 ); Type = Supp_SizeType( nSize, p->nStepSize ); Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); if ( (pMemory = (char *)Vec_PtrEntry( p->vFree, Type )) ) { Vec_PtrWriteEntry( p->vFree, Type, Supp_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 Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize ) { int Type; Type = Supp_SizeType( nSize, p->nStepSize ); Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); Supp_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 Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs ) { Supp_One_t * pPart; pPart = (Supp_One_t *)Supp_ManFetch( p, sizeof(Supp_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 Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry ) { assert( pEntry->nOuts <= pEntry->nOutsAlloc ); assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); Supp_ManRecycle( p, (char *)pEntry, sizeof(Supp_One_t) + sizeof(int) * pEntry->nOutsAlloc ); } /**Function************************************************************* Synopsis [Merges two entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs ) { Supp_One_t * p = Supp_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 * Supp_ManTransferEntry( Supp_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 [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pNext; int i, k; assert( Abc_NtkIsStrash(pNtk) ); vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) ); Abc_NtkIncrementTravId( pNtk ); // add the constant-1 nodes pObj = Abc_AigConst1(pNtk); Abc_NodeSetTravIdCurrent( pObj ); Vec_PtrPush( vNodes, pObj ); // add the CIs/nodes/COs in the topological order Abc_NtkForEachNode( pNtk, pObj, i ) { // check the fanins and add CIs Abc_ObjForEachFanin( pObj, pNext, k ) if ( Abc_ObjIsCi(pNext) && !Abc_NodeIsTravIdCurrent(pNext) ) { Abc_NodeSetTravIdCurrent( pNext ); Vec_PtrPush( vNodes, pNext ); } // add the node Vec_PtrPush( vNodes, pObj ); // check the fanouts and add COs Abc_ObjForEachFanout( pObj, pNext, k ) if ( Abc_ObjIsCo(pNext) && !Abc_NodeIsTravIdCurrent(pNext) ) { Abc_NodeSetTravIdCurrent( pNext ); Vec_PtrPush( vNodes, pNext ); } } return vNodes; } /**Function************************************************************* Synopsis [Computes supports of the POs.] Description [Returns the ptr-vector of int-vectors.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkComputeSupportsSmart( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vSupports; Vec_Ptr_t * vNodes; Vec_Int_t * vSupp; Supp_Man_t * p; Supp_One_t * pPart0, * pPart1; Abc_Obj_t * pObj; int i; // set the number of PIs/POs Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i; Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i; // start the support computation manager p = Supp_ManStart( 1 << 20, 1 << 6 ); // consider objects in the topological order vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkCleanCopy(pNtk); // order the nodes so that the PIs and POs follow naturally vNodes = Abc_NtkDfsNatural( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { if ( Abc_ObjIsNode(pObj) ) { pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy; pPart1 = (Supp_One_t *)Abc_ObjFanin1(pObj)->pCopy; pObj->pCopy = (Abc_Obj_t *)Supp_ManMergeEntry( p, pPart0, pPart1, Abc_ObjFanoutNum(pObj) ); assert( pPart0->nRefs > 0 ); if ( --pPart0->nRefs == 0 ) Supp_ManRecycleEntry( p, pPart0 ); assert( pPart1->nRefs > 0 ); if ( --pPart1->nRefs == 0 ) Supp_ManRecycleEntry( p, pPart1 ); continue; } if ( Abc_ObjIsCo(pObj) ) { pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy; // only save the CO if it is non-trivial if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) { vSupp = Supp_ManTransferEntry(pPart0); Vec_IntPush( vSupp, (int)(ABC_PTRINT_T)pObj->pNext ); Vec_PtrPush( vSupports, vSupp ); } assert( pPart0->nRefs > 0 ); if ( --pPart0->nRefs == 0 ) Supp_ManRecycleEntry( p, pPart0 ); continue; } if ( Abc_ObjIsCi(pObj) ) { if ( Abc_ObjFanoutNum(pObj) ) { pPart0 = (Supp_One_t *)Supp_ManFetchEntry( p, 1, Abc_ObjFanoutNum(pObj) ); pPart0->pOuts[ pPart0->nOuts++ ] = (int)(ABC_PTRINT_T)pObj->pNext; pObj->pCopy = (Abc_Obj_t *)pPart0; } continue; } if ( pObj == Abc_AigConst1(pNtk) ) { if ( Abc_ObjFanoutNum(pObj) ) pObj->pCopy = (Abc_Obj_t *)Supp_ManFetchEntry( p, 0, Abc_ObjFanoutNum(pObj) ); continue; } assert( 0 ); } Vec_PtrFree( vNodes ); //printf( "Memory usage = %d MB.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) ); Supp_ManStop( p ); // sort supports by size Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); // clear the number of PIs/POs Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pNext = NULL; Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pNext = NULL; /* Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSupp, i ) printf( "%d ", Vec_IntSize(vSupp) ); printf( "\n" ); */ return vSupports; } /**Function************************************************************* Synopsis [Computes supports of the POs using naive method.] Description [Returns the ptr-vector of int-vectors.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkComputeSupportsNaive( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vSupp, * vSupports; Vec_Int_t * vSuppI; Abc_Obj_t * pObj, * pTemp; int i, k; // set the PI numbers Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i; // save the CI numbers vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) { if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) continue; vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); vSuppI = (Vec_Int_t *)vSupp; Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pTemp, k ) Vec_IntWriteEntry( vSuppI, k, (int)(ABC_PTRINT_T)pTemp->pNext ); Vec_IntSort( vSuppI, 0 ); // append the number of this output Vec_IntPush( vSuppI, i ); // save the support in the vector Vec_PtrPush( vSupports, vSuppI ); } // clean the CI numbers Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pNext = NULL; // sort supports by size Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); /* Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSuppI, i ) printf( "%d ", Vec_IntSize(vSuppI) ); printf( "\n" ); */ return vSupports; } /**Function************************************************************* Synopsis [Start bitwise support representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Abc_NtkSuppCharStart( 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 bitwise support representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSuppCharAdd( 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 bitwise support representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSuppCharCommon( 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 Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nSuppSizeLimit, Vec_Int_t * vOne ) { /* Vec_Int_t * vPartSupp, * vPart; double Attract, Repulse, Cost, CostBest; int i, nCommon, iBest; iBest = -1; CostBest = 0.0; Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vPartSupp, i ) { vPart = Vec_PtrEntry( vPartsAll, i ); if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) >= nPartSizeLimit ) continue; nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne ); if ( nCommon == 0 ) continue; if ( nCommon == Vec_IntSize(vOne) ) return i; Attract = 1.0 * nCommon / Vec_IntSize(vOne); if ( Vec_IntSize(vPartSupp) < 100 ) Repulse = 1.0; else Repulse = log10( Vec_IntSize(vPartSupp) / 10.0 ); Cost = pow( Attract, pow(Repulse, 5.0) ); if ( CostBest < Cost ) { CostBest = Cost; iBest = i; } } if ( CostBest < 0.6 ) return -1; return iBest; */ Vec_Int_t * vPartSupp;//, * vPart; int Attract, Repulse, Value, ValueBest; int i, nCommon, iBest; // int nCommon2; iBest = -1; ValueBest = 0; Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vPartSupp, i ) { // skip partitions with too many outputs // vPart = Vec_PtrEntry( vPartsAll, i ); // if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit ) // continue; // find the number of common variables between this output and the partitions // nCommon2 = Vec_IntTwoCountCommon( vPartSupp, vOne ); nCommon = Abc_NtkSuppCharCommon( (unsigned *)Vec_PtrEntry(vPartSuppsChar, i), vOne ); // assert( nCommon2 == nCommon ); // if no common variables, continue searching if ( nCommon == 0 ) continue; // if all variables are common, the best partition if found if ( nCommon == Vec_IntSize(vOne) ) return i; // skip partitions whose size exceeds the limit if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit ) continue; // figure out might be the good partition for this one 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 Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, 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 == Abc_NtkCoNum(pNtk) ); printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) ); } /**Function************************************************************* Synopsis [Perform the smart partitioning.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPartitionCompact( 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 [Returns the ptr-vector of int-vectors.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose ) { ProgressBar * pProgress; Vec_Ptr_t * vPartSuppsChar; Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll; Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; int i, iPart, iOut, timeFind = 0; abctime clk, clk2; // compute the supports for all outputs clk = Abc_Clock(); // vSupps = Abc_NtkComputeSupportsNaive( pNtk ); vSupps = Abc_NtkComputeSupportsSmart( pNtk ); if ( fVerbose ) { ABC_PRT( "Supps", Abc_Clock() - clk ); } // start char-based support representation vPartSuppsChar = Vec_PtrAlloc( 1000 ); // create partitions clk = Abc_Clock(); vPartsAll = Vec_PtrAlloc( 256 ); vPartSuppsAll = Vec_PtrAlloc( 256 ); pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vSupps) ); Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // if ( i % 1000 == 0 ) // printf( "CIs = %6d. COs = %6d. Processed = %6d (out of %6d). Parts = %6d.\r", // Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), i, Vec_PtrSize(vSupps), Vec_PtrSize(vPartsAll) ); // get the output number iOut = Vec_IntPop(vOne); // find closely matching part clk2 = Abc_Clock(); iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nSuppSizeLimit, vOne ); timeFind += Abc_Clock() - clk2; 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( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) ); } 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 ); Abc_NtkSuppCharAdd( (unsigned *)Vec_PtrEntry(vPartSuppsChar, iPart), vOne, Abc_NtkCiNum(pNtk) ); } } Extra_ProgressBarStop( pProgress ); // stop char-based support representation Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsChar, vTemp, i ) ABC_FREE( vTemp ); Vec_PtrFree( vPartSuppsChar ); //printf( "\n" ); if ( fVerbose ) { ABC_PRT( "Parts", Abc_Clock() - clk ); //ABC_PRT( "Find ", timeFind ); } clk = Abc_Clock(); // remember number of supports 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 // Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); if ( fVerbose ) { ABC_PRT( "Comps", Abc_Clock() - clk ); } if ( fVerbose ) printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); // Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); // cleanup Vec_VecFree( (Vec_Vec_t *)vSupps ); Vec_VecFree( (Vec_Vec_t *)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, Abc_NtkCo(pNtk, iOut) ); Vec_IntFree( vPart ); Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); } */ return vPartsAll; } /**Function************************************************************* Synopsis [Perform the naive partitioning.] Description [Returns the ptr-vector of int-vectors.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize ) { Vec_Ptr_t * vParts; Abc_Obj_t * pObj; int nParts, i; nParts = (Abc_NtkCoNum(pNtk) / nPartSize) + ((Abc_NtkCoNum(pNtk) % nPartSize) > 0); vParts = (Vec_Ptr_t *)Vec_VecStart( nParts ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vParts, i / nPartSize), i ); return vParts; } /**Function************************************************************* Synopsis [Converts from intergers to pointers for the given network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOutsPtr ) { int Out, i; Vec_PtrClear( vOutsPtr ); Vec_IntForEachEntry( vOuts, Out, i ) Vec_PtrPush( vOutsPtr, Abc_NtkCo(pNtk, Out) ); } /**Function************************************************************* Synopsis [Returns representative of the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkPartStitchFindRepr_rec( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) { Abc_Obj_t * pRepr; pRepr = (Abc_Obj_t *)Vec_PtrEntry( vEquiv, pObj->Id ); if ( pRepr == NULL || pRepr == pObj ) return pObj; return Abc_NtkPartStitchFindRepr_rec( vEquiv, pRepr ); } /**Function************************************************************* Synopsis [Returns the representative of the fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Abc_Obj_t * Abc_NtkPartStitchCopy0( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) { Abc_Obj_t * pFan = Abc_ObjFanin0( pObj ); Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan ); return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ (int)Abc_ObjFaninC1(pObj) ); } static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) { Abc_Obj_t * pFan = Abc_ObjFanin1( pObj ); Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan ); return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ (int)Abc_ObjFaninC1(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hop_Obj_t * Hop_ObjChild0Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin0(pObj)->pNext, Abc_ObjFaninC0(pObj) ); } static inline Hop_Obj_t * Hop_ObjChild1Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin1(pObj)->pNext, Abc_ObjFaninC1(pObj) ); } /**Function************************************************************* Synopsis [Stitches together several networks with choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk ) { Hop_Man_t * pMan; Abc_Obj_t * pObj; int i; // start the HOP package pMan = Hop_ManStart(); pMan->vObjs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) + 1 ); Vec_PtrPush( pMan->vObjs, Hop_ManConst1(pMan) ); // map constant node and PIs Abc_AigConst1(pNtk)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pNext = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); // map the internal nodes Abc_AigForEachAnd( pNtk, pObj, i ) { pObj->pNext = (Abc_Obj_t *)Hop_And( pMan, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); assert( !Abc_ObjIsComplement(pObj->pNext) ); } // set the choice nodes Abc_AigForEachAnd( pNtk, pObj, i ) { if ( pObj->pCopy ) ((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext; } // transfer the POs Abc_NtkForEachCo( pNtk, pObj, i ) Hop_ObjCreatePo( pMan, Hop_ObjChild0Next(pObj) ); // check the new manager if ( !Hop_ManCheck(pMan) ) printf( "Abc_NtkPartStartHop: HOP manager check has failed.\n" ); return pMan; } /**Function************************************************************* Synopsis [Stitches together several networks with choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts ) { extern Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ); Hop_Man_t * pMan; Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew, * pNtkTemp; Abc_Obj_t * pObj, * pFanin; int i, k, iNodeId; // start a new network similar to the original one assert( Abc_NtkIsStrash(pNtk) ); pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // annotate parts to point to the new network Vec_PtrForEachEntry( Abc_Ntk_t *, vParts, pNtkTemp, i ) { assert( Abc_NtkIsStrash(pNtkTemp) ); Abc_NtkCleanCopy( pNtkTemp ); // map the CI nodes Abc_AigConst1(pNtkTemp)->pCopy = Abc_AigConst1(pNtkNew); Abc_NtkForEachCi( pNtkTemp, pObj, k ) { iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); if ( iNodeId == -1 ) { printf( "Cannot find CI node %s in the original network.\n", Abc_ObjName(pObj) ); return NULL; } pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); } // add the internal nodes while saving representatives vNodes = Abc_AigDfs( pNtkTemp, 1, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, k ) { pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); assert( !Abc_ObjIsComplement(pObj->pCopy) ); if ( Abc_AigNodeIsChoice(pObj) ) for ( pFanin = (Abc_Obj_t *)pObj->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) pFanin->pCopy->pCopy = pObj->pCopy; } Vec_PtrFree( vNodes ); // map the CO nodes Abc_NtkForEachCo( pNtkTemp, pObj, k ) { iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); if ( iNodeId == -1 ) { printf( "Cannot find CO node %s in the original network.\n", Abc_ObjName(pObj) ); return NULL; } pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); } } // connect the remaining POs /* Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = Abc_NtkCi( pNtkNew, i ); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pCopy = Abc_NtkCo( pNtkNew, i ); */ Abc_NtkForEachCo( pNtk, pObj, i ) { if ( Abc_ObjFaninNum(pObj->pCopy) == 0 ) Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); } // transform into the HOP manager pMan = Abc_NtkPartStartHop( pNtkNew ); pNtkNew = Abc_NtkHopRemoveLoops( pNtkTemp = pNtkNew, pMan ); Abc_NtkDelete( pNtkTemp ); // check correctness of the new network if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkPartStitchChoices: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Stitches together several networks with choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ) { Vec_Ptr_t * vParts, * vFraigs, * vOnePtr; Vec_Int_t * vOne; Abc_Ntk_t * pNtk, * pNtk2, * pNtkAig, * pNtkFraig; int i, k; // perform partitioning pNtk = (Abc_Ntk_t *)Vec_PtrEntry( vStore, 0 ); assert( Abc_NtkIsStrash(pNtk) ); // vParts = Abc_NtkPartitionNaive( pNtk, 20 ); vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); // fraig each partition vOnePtr = Vec_PtrAlloc( 1000 ); vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) ); Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i ) { // start the partition Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); // add nodes to the partition Vec_PtrForEachEntryStart( Abc_Ntk_t *, vStore, pNtk2, k, 1 ) { Abc_NtkConvertCos( pNtk2, vOne, vOnePtr ); Abc_NtkAppendToCone( pNtkAig, pNtk2, vOnePtr ); } printf( "Fraiging part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pNtkAig), Abc_NtkPoNum(pNtkAig), Abc_NtkNodeNum(pNtkAig), Abc_AigLevel(pNtkAig) ); // fraig the partition pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 1, 0 ); Vec_PtrPush( vFraigs, pNtkFraig ); Abc_NtkDelete( pNtkAig ); } printf( " \r" ); Vec_VecFree( (Vec_Vec_t *)vParts ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); // derive the final network pNtkFraig = Abc_NtkPartStitchChoices( pNtk, vFraigs ); Vec_PtrForEachEntry( Abc_Ntk_t *, vFraigs, pNtkAig, i ) Abc_NtkDelete( pNtkAig ); Vec_PtrFree( vFraigs ); Vec_PtrFree( vOnePtr ); return pNtkFraig; } /**Function************************************************************* Synopsis [Stitches together several networks with choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ) { Vec_Ptr_t * vParts, * vFraigs, * vOnePtr; Vec_Int_t * vOne; Abc_Ntk_t * pNtkAig, * pNtkFraig; int i; abctime clk = Abc_Clock(); // perform partitioning assert( Abc_NtkIsStrash(pNtk) ); // vParts = Abc_NtkPartitionNaive( pNtk, 20 ); vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); // fraig each partition vOnePtr = Vec_PtrAlloc( 1000 ); vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) ); Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i ) { Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0, 0 ); Vec_PtrPush( vFraigs, pNtkFraig ); Abc_NtkDelete( pNtkAig ); printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); } Vec_VecFree( (Vec_Vec_t *)vParts ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); // derive the final network Vec_PtrForEachEntry( Abc_Ntk_t *, vFraigs, pNtkAig, i ) Abc_NtkDelete( pNtkAig ); Vec_PtrFree( vFraigs ); Vec_PtrFree( vOnePtr ); ABC_PRT( "Partitioned fraiging time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcPlace.c000066400000000000000000000155431300674244400235120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcPlace.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface with a placer.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcPlace.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" // placement includes #include "phys/place/place_base.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// AbstractCell *abstractCells = NULL; ConcreteCell *cells = NULL; ConcreteNet *nets = NULL; int nAllocSize = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates a new cell.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_PlaceCreateCell( Abc_Obj_t * pObj, int fAnd ) { assert( cells[pObj->Id].m_id == 0 ); cells[pObj->Id].m_id = pObj->Id; cells[pObj->Id].m_label = ""; cells[pObj->Id].m_parent = &(abstractCells[fAnd]); cells[pObj->Id].m_fixed = 0; addConcreteCell(&(cells[pObj->Id])); } /**Function************************************************************* Synopsis [Updates the net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_PlaceUpdateNet( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int k; // free the old array of net terminals if ( nets[pObj->Id].m_terms ) free( nets[pObj->Id].m_terms ); // fill in the net with the new information nets[pObj->Id].m_id = pObj->Id; nets[pObj->Id].m_weight = 1.0; nets[pObj->Id].m_numTerms = Abc_ObjFanoutNum(pObj); //fanout nets[pObj->Id].m_terms = ALLOC(ConcreteCell*, Abc_ObjFanoutNum(pObj)); Abc_ObjForEachFanout( pObj, pFanout, k ) nets[pObj->Id].m_terms[k] = &(cells[pFanout->Id]); addConcreteNet(&(nets[pObj->Id])); } /**Function************************************************************* Synopsis [Returns the placement cost of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pObj; // double x, y; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) { // pObj->Id } return 0.0; } /**Function************************************************************* Synopsis [Updates placement after one step of rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets ) { Abc_Obj_t * pObj, * pFanin; int i, k; Vec_Ptr_t * vCells, * vNets; // start the arrays of new cells and nets vCells = Vec_PtrAlloc( 16 ); vNets = Vec_PtrAlloc( 32 ); // go through the new nodes Vec_PtrForEachEntry( Abc_Obj_t *, vAddedCells, pObj, i ) { assert( !Abc_ObjIsComplement(pObj) ); Abc_PlaceCreateCell( pObj, 1 ); Abc_PlaceUpdateNet( pObj ); // add the new cell and its fanin nets to temporary storage Vec_PtrPush( vCells, &(cells[pObj->Id]) ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_PtrPushUnique( vNets, &(nets[pFanin->Id]) ); } // go through the modified nets Vec_PtrForEachEntry( Abc_Obj_t *, vUpdatedNets, pObj, i ) { assert( !Abc_ObjIsComplement(pObj) ); if ( Abc_ObjType(pObj) == ABC_OBJ_NONE ) // dead node continue; Abc_PlaceUpdateNet( pObj ); } // update the placement // fastPlace( Vec_PtrSize(vCells), (ConcreteCell **)Vec_PtrArray(vCells), // Vec_PtrSize(vNets), (ConcreteNet **)Vec_PtrArray(vNets) ); // clean up Vec_PtrFree( vCells ); Vec_PtrFree( vNets ); } /**Function************************************************************* Synopsis [This procedure is called before the writing start.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_PlaceBegin( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; // allocate and clean internal storage nAllocSize = 5 * Abc_NtkObjNumMax(pNtk); cells = REALLOC(ConcreteCell, cells, nAllocSize); nets = REALLOC(ConcreteNet, nets, nAllocSize); memset( cells, 0, sizeof(ConcreteCell) * nAllocSize ); memset( nets, 0, sizeof(ConcreteNet) * nAllocSize ); // create AbstractCells // 1: pad // 2: and if (!abstractCells) abstractCells = ALLOC(AbstractCell,2); abstractCells[0].m_height = 1.0; abstractCells[0].m_width = 1.0; abstractCells[0].m_label = "pio"; abstractCells[0].m_pad = 1; abstractCells[1].m_height = 1.0; abstractCells[1].m_width = 1.0; abstractCells[1].m_label = "and"; abstractCells[1].m_pad = 0; // input pads Abc_NtkForEachCi( pNtk, pObj, i ) Abc_PlaceCreateCell( pObj, 0 ); // ouput pads Abc_NtkForEachCo( pNtk, pObj, i ) Abc_PlaceCreateCell( pObj, 0 ); // AND nodes Abc_AigForEachAnd( pNtk, pObj, i ) Abc_PlaceCreateCell( pObj, 1 ); // all nets Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj) ) continue; Abc_PlaceUpdateNet( pObj ); } globalPreplace((float)0.8); globalPlace(); } /**Function************************************************************* Synopsis [This procedure is called after the writing completes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_PlaceEnd( Abc_Ntk_t * pNtk ) { int i; // clean up for ( i = 0; i < nAllocSize; i++ ) FREE( nets[i].m_terms ); FREE( abstractCells ); FREE( cells ); FREE( nets ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcPrint.c000066400000000000000000002014571300674244400235630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcPrint.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Printing statistics.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcPrint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "base/abc/abc.h" #include "bool/dec/dec.h" #include "base/main/main.h" #include "map/mio/mio.h" #include "aig/aig/aig.h" #include "map/if/if.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif #ifdef WIN32 #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //extern int s_TotalNodes = 0; //extern int s_TotalChanges = 0; abctime s_MappingTime = 0; int s_MappingMem = 0; abctime s_ResubTime = 0; abctime s_ResynTime = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [If the network is best, saves it in "best.blif" and returns 1.] Description [If the networks are incomparable, saves the new network, returns its parameters in the internal parameter structure, and returns 1. If the new network is not a logic network, quits without saving and returns 0.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk ) { extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ); static struct ParStruct { char * pName; // name of the best saved network int Depth; // depth of the best saved network int Flops; // flops in the best saved network int Nodes; // nodes in the best saved network int Edges; // edges in the best saved network int nPis; // the number of primary inputs int nPos; // the number of primary outputs } ParsNew, ParsBest = { 0 }; char * pFileNameOut; // free storage for the name if ( pNtk == NULL ) { ABC_FREE( ParsBest.pName ); return 0; } // quit if not a logic network if ( !Abc_NtkIsLogic(pNtk) ) return 0; // get the parameters ParsNew.Depth = Abc_NtkLevel( pNtk ); ParsNew.Flops = Abc_NtkLatchNum( pNtk ); ParsNew.Nodes = Abc_NtkNodeNum( pNtk ); ParsNew.Edges = Abc_NtkGetTotalFanins( pNtk ); ParsNew.nPis = Abc_NtkPiNum( pNtk ); ParsNew.nPos = Abc_NtkPoNum( pNtk ); // reset the parameters if the network has the same name if ( ParsBest.pName == NULL || strcmp(ParsBest.pName, pNtk->pName) || ParsBest.Depth > ParsNew.Depth || (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops > ParsNew.Flops) || (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops == ParsNew.Flops && ParsBest.Edges > ParsNew.Edges) ) { ABC_FREE( ParsBest.pName ); ParsBest.pName = Extra_UtilStrsav( pNtk->pName ); ParsBest.Depth = ParsNew.Depth; ParsBest.Flops = ParsNew.Flops; ParsBest.Nodes = ParsNew.Nodes; ParsBest.Edges = ParsNew.Edges; ParsBest.nPis = ParsNew.nPis; ParsBest.nPos = ParsNew.nPos; // writ the network if ( strcmp(pNtk->pSpec + strlen(pNtk->pSpec) - strlen("_best.blif"), "_best.blif") ) pFileNameOut = Extra_FileNameGenericAppend( pNtk->pSpec, "_best.blif" ); else pFileNameOut = pNtk->pSpec; Io_Write( pNtk, pFileNameOut, IO_FILE_BLIF ); return 1; } return 0; } /**Function************************************************************* Synopsis [Collects memory usage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Abc_NtkMemory( Abc_Ntk_t * p ) { Abc_Obj_t * pObj; int i; double Memory = sizeof(Abc_Ntk_t); Memory += sizeof(Abc_Obj_t) * Abc_NtkObjNum(p); Memory += Vec_PtrMemory(p->vPis); Memory += Vec_PtrMemory(p->vPos); Memory += Vec_PtrMemory(p->vCis); Memory += Vec_PtrMemory(p->vCos); Memory += Vec_PtrMemory(p->vObjs); Memory += Vec_IntMemory(&p->vTravIds); Memory += Vec_IntMemory(p->vLevelsR); Abc_NtkForEachObj( p, pObj, i ) Memory += sizeof(int) * (Vec_IntCap(&pObj->vFanins) + Vec_IntCap(&pObj->vFanouts)); return Memory; } /**Function************************************************************* Synopsis [Marks nodes for power-optimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Vec_Int_t * vSwitching; float * pSwitching; Abc_Ntk_t * pNtkStr; Aig_Man_t * pAig; Aig_Obj_t * pObjAig; Abc_Obj_t * pObjAbc, * pObjAbc2; float Result = (float)0; int i; // strash the network pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 ); Abc_NtkForEachObj( pNtk, pObjAbc, i ) if ( Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)->Type == ABC_FUNC_NONE || (!Abc_ObjIsCi(pObjAbc) && !Abc_ObjIsNode(pObjAbc)) ) pObjAbc->pTemp = NULL; // map network into an AIG pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) ); vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 ); pSwitching = (float *)vSwitching->pArray; Abc_NtkForEachObj( pNtk, pObjAbc, i ) { if ( (pObjAbc2 = Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)) && (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc2->pTemp)) ) { Result += Abc_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id]; // Abc_ObjPrint( stdout, pObjAbc ); // printf( "%d = %.2f\n", i, Abc_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id] ); } } Vec_IntFree( vSwitching ); Aig_ManStop( pAig ); Abc_NtkDelete( pNtkStr ); return Result; } /**Function************************************************************* Synopsis [Compute area using LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_NtkGetArea( Abc_Ntk_t * pNtk ) { If_LibLut_t * pLutLib; Abc_Obj_t * pObj; float Counter = 0.0; int i; assert( Abc_NtkIsLogic(pNtk) ); // get the library pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); if ( pLutLib && pLutLib->LutMax >= Abc_NtkGetFaninMax(pNtk) ) { Abc_NtkForEachNode( pNtk, pObj, i ) Counter += pLutLib->pLutAreas[Abc_ObjFaninNum(pObj)]; } return Counter; } /**Function************************************************************* Synopsis [Print the vital stats of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 ) { int nSingles = fSkipBuf ? Abc_NtkGetBufNum(pNtk) : 0; if ( fPrintMuxes && Abc_NtkIsStrash(pNtk) ) { extern int Abc_NtkCountMuxes( Abc_Ntk_t * pNtk ); int nXors = Abc_NtkGetExorNum(pNtk); int nMuxs = Abc_NtkCountMuxes(pNtk) - nXors; int nAnds = Abc_NtkNodeNum(pNtk) - (nMuxs + nXors) * 3 - nSingles; Abc_Print( 1, "XMA stats: " ); Abc_Print( 1,"Xor =%7d (%6.2f %%) ", nXors, 300.0 * nXors / Abc_NtkNodeNum(pNtk) ); Abc_Print( 1,"Mux =%7d (%6.2f %%) ", nMuxs, 300.0 * nMuxs / Abc_NtkNodeNum(pNtk) ); Abc_Print( 1,"And =%7d (%6.2f %%)", nAnds, 100.0 * nAnds / Abc_NtkNodeNum(pNtk) ); Abc_Print( 1,"\n" ); return; } if ( fSaveBest ) Abc_NtkCompareAndSaveBest( pNtk ); /* if ( fDumpResult ) { char Buffer[1000] = {0}; const char * pNameGen = pNtk->pSpec? Extra_FileNameGeneric( pNtk->pSpec ) : "nameless_"; sprintf( Buffer, "%s_dump.blif", pNameGen ); Io_Write( pNtk, Buffer, IO_FILE_BLIF ); if ( pNtk->pSpec ) ABC_FREE( pNameGen ); } */ // if ( Abc_NtkIsStrash(pNtk) ) // Abc_AigCountNext( pNtk->pManFunc ); #ifdef WIN32 SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 15 ); // bright Abc_Print( 1,"%-30s:", pNtk->pName ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal #else Abc_Print( 1,"%s%-30s:%s", "\033[1;37m", pNtk->pName, "\033[0m" ); // bright #endif Abc_Print( 1," i/o =%5d/%5d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); if ( Abc_NtkConstrNum(pNtk) ) Abc_Print( 1,"(c=%d)", Abc_NtkConstrNum(pNtk) ); Abc_Print( 1," lat =%5d", Abc_NtkLatchNum(pNtk) ); if ( pNtk->nBarBufs ) Abc_Print( 1,"(b=%d)", pNtk->nBarBufs ); if ( Abc_NtkIsNetlist(pNtk) ) { Abc_Print( 1," net =%5d", Abc_NtkNetNum(pNtk) ); Abc_Print( 1," nd =%5d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles ); Abc_Print( 1," wbox =%3d", Abc_NtkWhiteboxNum(pNtk) ); Abc_Print( 1," bbox =%3d", Abc_NtkBlackboxNum(pNtk) ); } else if ( Abc_NtkIsStrash(pNtk) ) { Abc_Print( 1," and =%7d", Abc_NtkNodeNum(pNtk) ); if ( Abc_NtkGetChoiceNum(pNtk) ) Abc_Print( 1," (choice = %d)", Abc_NtkGetChoiceNum(pNtk) ); } else { Abc_Print( 1," nd =%6d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles ); Abc_Print( 1," edge =%7d", Abc_NtkGetTotalFanins(pNtk) - nSingles ); } if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) ) { } else if ( Abc_NtkHasSop(pNtk) ) { Abc_Print( 1," cube =%6d", Abc_NtkGetCubeNum(pNtk) - nSingles ); if ( fFactored ) Abc_Print( 1," lit(sop) =%6d", Abc_NtkGetLitNum(pNtk) - nSingles ); if ( fFactored ) Abc_Print( 1," lit(fac) =%6d", Abc_NtkGetLitFactNum(pNtk) - nSingles ); } else if ( Abc_NtkHasAig(pNtk) ) Abc_Print( 1," aig =%6d", Abc_NtkGetAigNodeNum(pNtk) - nSingles ); else if ( Abc_NtkHasBdd(pNtk) ) Abc_Print( 1," bdd =%6d", Abc_NtkGetBddNodeNum(pNtk) - nSingles ); else if ( Abc_NtkHasMapping(pNtk) ) { int fHasTimeMan = (int)(pNtk->pManTime != NULL); assert( pNtk->pManFunc == Abc_FrameReadLibGen() ); Abc_Print( 1," area =%5.2f", Abc_NtkGetMappedArea(pNtk) ); Abc_Print( 1," delay =%5.2f", Abc_NtkDelayTrace(pNtk, NULL, NULL, 0) ); if ( !fHasTimeMan && pNtk->pManTime ) { Abc_ManTimeStop( pNtk->pManTime ); pNtk->pManTime = NULL; } } else if ( !Abc_NtkHasBlackbox(pNtk) ) { assert( 0 ); } if ( Abc_NtkIsStrash(pNtk) ) { extern int Abc_NtkGetMultiRefNum( Abc_Ntk_t * pNtk ); Abc_Print( 1," lev =%3d", Abc_AigLevel(pNtk) ); // Abc_Print( 1," ff = %5d", Abc_NtkNodeNum(pNtk) + 2 * (Abc_NtkCoNum(pNtk)+Abc_NtkGetMultiRefNum(pNtk)) ); // Abc_Print( 1," var = %5d", Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk)+Abc_NtkGetMultiRefNum(pNtk) ); } else Abc_Print( 1," lev = %d", Abc_NtkLevel(pNtk) ); if ( pNtk->nBarBufs2 ) Abc_Print( 1," buf = %d", pNtk->nBarBufs2 ); if ( fUseLutLib && Abc_FrameReadLibLut() ) Abc_Print( 1," delay =%5.2f", Abc_NtkDelayTraceLut(pNtk, 1) ); if ( fUseLutLib && Abc_FrameReadLibLut() ) Abc_Print( 1," area =%5.2f", Abc_NtkGetArea(pNtk) ); if ( fPower ) Abc_Print( 1," power =%7.2f", Abc_NtkMfsTotalSwitching(pNtk) ); if ( fGlitch ) { extern float Abc_NtkMfsTotalGlitching( Abc_Ntk_t * pNtk ); if ( Abc_NtkIsLogic(pNtk) && Abc_NtkGetFaninMax(pNtk) <= 6 ) Abc_Print( 1," glitch =%7.2f %%", Abc_NtkMfsTotalGlitching(pNtk) ); else printf( "\nCurrently computes glitching only for K-LUT networks with K <= 6." ); } if ( fPrintMem ) Abc_Print( 1," mem =%5.2f MB", Abc_NtkMemory(pNtk)/(1<<20) ); Abc_Print( 1,"\n" ); // print the statistic into a file if ( fDumpResult ) { FILE * pTable = fopen( "abcstats.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) ); fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); fprintf( pTable, "\n" ); fclose( pTable ); } /* { FILE * pTable; pTable = fopen( "ibm/seq_stats.txt", "a+" ); // fprintf( pTable, "%s ", pNtk->pName ); // fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); fprintf( pTable, "\n" ); fclose( pTable ); } */ /* // print the statistic into a file { FILE * pTable; pTable = fopen( "ucsb/stats.txt", "a+" ); // fprintf( pTable, "%s ", pNtk->pSpec ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); // fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) ); // fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) ); fprintf( pTable, "\n" ); fclose( pTable ); } */ /* // print the statistic into a file { FILE * pTable; pTable = fopen( "x/stats_new.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); // fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); // fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) ); fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) ); // fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) ); fprintf( pTable, "\n" ); fclose( pTable ); s_ResynTime = 0; } */ /* // print the statistic into a file { static int Counter = 0; extern int timeRetime; FILE * pTable; Counter++; pTable = fopen( "d/stats.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); // fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); fprintf( pTable, "\n" ); fclose( pTable ); } s_TotalNodes += Abc_NtkNodeNum(pNtk); printf( "Total nodes = %6d %6.2f MB Changes = %6d.\n", s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges ); */ // if ( Abc_NtkHasSop(pNtk) ) // printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) ); fflush( stdout ); if ( pNtk->pExdc ) Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem ); } /**Function************************************************************* Synopsis [Prints PIs/POs and LIs/LOs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops ) { Abc_Obj_t * pObj; int i; fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) fprintf( pFile, " %d=%s", i, Abc_ObjName(pObj) ); // fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) ); fprintf( pFile, "\n" ); fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) ); Abc_NtkForEachPo( pNtk, pObj, i ) fprintf( pFile, " %d=%s", i, Abc_ObjName(pObj) ); fprintf( pFile, "\n" ); if ( !fPrintFlops ) return; fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pObj, i ) fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj), Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Prints statistics about latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pLatch, * pFanin; int i, Counter0, Counter1, Counter2; int InitNums[4], Init; assert( !Abc_NtkIsNetlist(pNtk) ); if ( Abc_NtkLatchNum(pNtk) == 0 ) { fprintf( pFile, "The network is combinational.\n" ); return; } for ( i = 0; i < 4; i++ ) InitNums[i] = 0; Counter0 = Counter1 = Counter2 = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { Init = Abc_LatchInit( pLatch ); assert( Init < 4 ); InitNums[Init]++; pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); if ( Abc_NtkIsLogic(pNtk) ) { if ( !Abc_NodeIsConst(pFanin) ) continue; } else if ( Abc_NtkIsStrash(pNtk) ) { if ( !Abc_AigNodeIsConst(pFanin) ) continue; } else assert( 0 ); // the latch input is a constant node Counter0++; if ( Abc_LatchIsInitDc(pLatch) ) { Counter1++; continue; } // count the number of cases when the constant is equal to the initial value if ( Abc_NtkIsStrash(pNtk) ) { if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) ) Counter2++; } else { if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) ) Counter2++; } } // fprintf( pFile, "%-15s: ", pNtk->pName ); fprintf( pFile, "Total latches = %5d. Init0 = %d. Init1 = %d. InitDC = %d. Const data = %d.\n", Abc_NtkLatchNum(pNtk), InitNums[1], InitNums[2], InitNums[3], Counter0 ); // fprintf( pFile, "Const fanin = %3d. DC init = %3d. Matching init = %3d. ", Counter0, Counter1, Counter2 ); // fprintf( pFile, "Self-feed latches = %2d.\n", -1 ); //Abc_NtkCountSelfFeedLatches(pNtk) ); } /**Function************************************************************* Synopsis [Prints the distribution of fanins/fanouts in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFaninFanoutCounters( Abc_Ntk_t * pNtk, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR ) { Abc_Obj_t * pNode; int i, nFanins, nFanouts; int nFaninsMax = 0, nFanoutsMax = 0; Abc_NtkForEachObj( pNtk, pNode, i ) { nFaninsMax = Abc_MaxInt( nFaninsMax, Abc_ObjFaninNum(pNode) ); nFanoutsMax = Abc_MaxInt( nFanoutsMax, Abc_ObjFanoutNum(pNode) ); } Vec_IntFill( vFan, nFaninsMax + 1, 0 ); Vec_IntFill( vFon, nFanoutsMax + 1, 0 ); Vec_IntFill( vFanR, nFaninsMax + 1, 0 ); Vec_IntFill( vFonR, nFanoutsMax + 1, 0 ); Abc_NtkForEachObjReverse( pNtk, pNode, i ) { nFanins = Abc_ObjFaninNum( pNode ); nFanouts = Abc_ObjFanoutNum( pNode ); Vec_IntAddToEntry( vFan, nFanins, 1 ); Vec_IntAddToEntry( vFon, nFanouts, 1 ); Vec_IntWriteEntry( vFanR, nFanins, i ); Vec_IntWriteEntry( vFonR, nFanouts, i ); } } void Abc_NtkInputOutputCounters( Abc_Ntk_t * pNtk, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR ) { Abc_Obj_t * pNode; int i, nFanins, nFanouts; int nFaninsMax = 0, nFanoutsMax = 0; Abc_NtkForEachCi( pNtk, pNode, i ) nFanoutsMax = Abc_MaxInt( nFanoutsMax, Abc_ObjFanoutNum(pNode) ); Abc_NtkForEachCo( pNtk, pNode, i ) nFaninsMax = Abc_MaxInt( nFaninsMax, Abc_ObjFaninNum(Abc_ObjFanin0(pNode)) ); Vec_IntFill( vFan, nFaninsMax + 1, 0 ); Vec_IntFill( vFon, nFanoutsMax + 1, 0 ); Vec_IntFill( vFanR, nFaninsMax + 1, 0 ); Vec_IntFill( vFonR, nFanoutsMax + 1, 0 ); Abc_NtkForEachCi( pNtk, pNode, i ) { nFanouts = Abc_ObjFanoutNum( pNode ); Vec_IntAddToEntry( vFon, nFanouts, 1 ); Vec_IntWriteEntry( vFonR, nFanouts, Abc_ObjId(pNode) ); } Abc_NtkForEachCo( pNtk, pNode, i ) { nFanins = Abc_ObjFaninNum( Abc_ObjFanin0(pNode) ); Vec_IntAddToEntry( vFan, nFanins, 1 ); Vec_IntWriteEntry( vFanR, nFanins, Abc_ObjId(pNode) ); } } Vec_Int_t * Abc_NtkCollectCoSupps( Abc_Ntk_t * pNtk, int fVerbose ) { abctime clk = Abc_Clock(); Abc_Obj_t * pNode; int i, k; Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_Int_t * vFanin, * vFanout, * vTemp = Vec_IntAlloc( 0 ); Vec_Int_t * vSuppsCo = Vec_IntAlloc( Abc_NtkCoNum(pNtk) ); Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachCi( pNtk, pNode, i ) Vec_IntPush( Vec_WecEntry(vSupps, Abc_ObjId(pNode)), i ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode)); for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ ) { vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId(pNode, k)); Vec_IntTwoMerge2( vFanout, vFanin, vTemp ); ABC_SWAP( Vec_Int_t, *vFanout, *vTemp ); } } Abc_NtkForEachCo( pNtk, pNode, i ) Vec_IntPush( vSuppsCo, Vec_IntSize(Vec_WecEntry(vSupps, Abc_ObjFaninId0(pNode))) ); Vec_WecFree( vSupps ); Vec_PtrFree( vNodes ); Vec_IntFree( vTemp ); if ( fVerbose ) Abc_PrintTime( 1, "Input support computation", Abc_Clock() - clk ); //Vec_IntPrint( vSuppsCo ); return vSuppsCo; } Vec_Int_t * Abc_NtkCollectCiSupps( Abc_Ntk_t * pNtk, int fVerbose ) { abctime clk = Abc_Clock(); Abc_Obj_t * pNode; int i, k; Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_Int_t * vFanin, * vFanout, * vTemp = Vec_IntAlloc( 0 ); Vec_Int_t * vSuppsCi = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode)); vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId0(pNode)); Vec_IntPush( vFanout, i ); Vec_IntTwoMerge2( vFanin, vFanout, vTemp ); ABC_SWAP( Vec_Int_t, *vFanin, *vTemp ); } Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pNode, i ) { vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode)); for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ ) { vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId(pNode, k)); Vec_IntTwoMerge2( vFanin, vFanout, vTemp ); ABC_SWAP( Vec_Int_t, *vFanin, *vTemp ); } } Abc_NtkForEachCi( pNtk, pNode, i ) Vec_IntPush( vSuppsCi, Vec_IntSize(Vec_WecEntry(vSupps, Abc_ObjId(pNode))) ); Vec_WecFree( vSupps ); Vec_PtrFree( vNodes ); Vec_IntFree( vTemp ); if ( fVerbose ) Abc_PrintTime( 1, "Output support computation", Abc_Clock() - clk ); //Vec_IntPrint( vSuppsCi ); return vSuppsCi; } void Abc_NtkInOutSupportCounters( Abc_Ntk_t * pNtk, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR ) { Abc_Obj_t * pNode; Vec_Int_t * vSuppsCo = Abc_NtkCollectCoSupps( pNtk, 1 ); Vec_Int_t * vSuppsCi = Abc_NtkCollectCiSupps( pNtk, 1 ); int i, nFanins, nFanouts; int nFaninsMax = Vec_IntFindMax( vSuppsCo ); int nFanoutsMax = Vec_IntFindMax( vSuppsCi ); Vec_IntFill( vFan, nFaninsMax + 1, 0 ); Vec_IntFill( vFon, nFanoutsMax + 1, 0 ); Vec_IntFill( vFanR, nFaninsMax + 1, 0 ); Vec_IntFill( vFonR, nFanoutsMax + 1, 0 ); Abc_NtkForEachCo( pNtk, pNode, i ) { nFanins = Vec_IntEntry( vSuppsCo, i ); Vec_IntAddToEntry( vFan, nFanins, 1 ); Vec_IntWriteEntry( vFanR, nFanins, Abc_ObjId(pNode) ); } Abc_NtkForEachCi( pNtk, pNode, i ) { nFanouts = Vec_IntEntry( vSuppsCi, i ); Vec_IntAddToEntry( vFon, nFanouts, 1 ); Vec_IntWriteEntry( vFonR, nFanouts, Abc_ObjId(pNode) ); } Vec_IntFree( vSuppsCo ); Vec_IntFree( vSuppsCi ); } Vec_Int_t * Abc_NtkCollectCoCones( Abc_Ntk_t * pNtk, int fVerbose ) { abctime clk = Abc_Clock(); Abc_Obj_t * pNode; int i, k; Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_Int_t * vFanin, * vFanout, * vTemp = Vec_IntAlloc( 0 ); Vec_Int_t * vSuppsCo = Vec_IntAlloc( Abc_NtkCoNum(pNtk) ); Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode)); for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ ) { vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId(pNode, k)); Vec_IntTwoMerge2( vFanout, vFanin, vTemp ); ABC_SWAP( Vec_Int_t, *vFanout, *vTemp ); } Vec_IntPush( vFanout, i ); } Abc_NtkForEachCo( pNtk, pNode, i ) Vec_IntPush( vSuppsCo, Vec_IntSize(Vec_WecEntry(vSupps, Abc_ObjFaninId0(pNode))) ); Vec_WecFree( vSupps ); Vec_PtrFree( vNodes ); Vec_IntFree( vTemp ); if ( fVerbose ) Abc_PrintTime( 1, "Input cone computation", Abc_Clock() - clk ); //Vec_IntPrint( vSuppsCo ); return vSuppsCo; } Vec_Int_t * Abc_NtkCollectCiCones( Abc_Ntk_t * pNtk, int fVerbose ) { abctime clk = Abc_Clock(); Abc_Obj_t * pNode; int i, k; Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_Int_t * vFanin, * vFanout, * vTemp = Vec_IntAlloc( 0 ); Vec_Int_t * vSuppsCi = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) ); Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pNode, i ) { vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode)); Vec_IntPush( vFanout, i ); for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ ) { vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId(pNode, k)); Vec_IntTwoMerge2( vFanin, vFanout, vTemp ); ABC_SWAP( Vec_Int_t, *vFanin, *vTemp ); } } Abc_NtkForEachCi( pNtk, pNode, i ) Vec_IntPush( vSuppsCi, Vec_IntSize(Vec_WecEntry(vSupps, Abc_ObjId(pNode))) ); Vec_WecFree( vSupps ); Vec_PtrFree( vNodes ); Vec_IntFree( vTemp ); if ( fVerbose ) Abc_PrintTime( 1, "Output cone computation", Abc_Clock() - clk ); //Vec_IntPrint( vSuppsCi ); return vSuppsCi; } void Abc_NtkInOutConeCounters( Abc_Ntk_t * pNtk, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR ) { Abc_Obj_t * pNode; Vec_Int_t * vSuppsCo = Abc_NtkCollectCoCones( pNtk, 1 ); Vec_Int_t * vSuppsCi = Abc_NtkCollectCiCones( pNtk, 1 ); int i, nFanins, nFanouts; int nFaninsMax = Vec_IntFindMax( vSuppsCo ); int nFanoutsMax = Vec_IntFindMax( vSuppsCi ); Vec_IntFill( vFan, nFaninsMax + 1, 0 ); Vec_IntFill( vFon, nFanoutsMax + 1, 0 ); Vec_IntFill( vFanR, nFaninsMax + 1, 0 ); Vec_IntFill( vFonR, nFanoutsMax + 1, 0 ); Abc_NtkForEachCo( pNtk, pNode, i ) { nFanins = Vec_IntEntry( vSuppsCo, i ); Vec_IntAddToEntry( vFan, nFanins, 1 ); Vec_IntWriteEntry( vFanR, nFanins, Abc_ObjId(pNode) ); } Abc_NtkForEachCi( pNtk, pNode, i ) { nFanouts = Vec_IntEntry( vSuppsCi, i ); Vec_IntAddToEntry( vFon, nFanouts, 1 ); Vec_IntWriteEntry( vFonR, nFanouts, Abc_ObjId(pNode) ); } Vec_IntFree( vSuppsCo ); Vec_IntFree( vSuppsCi ); } void Abc_NtkPrintDistribInternal( FILE * pFile, Abc_Ntk_t * pNtk, char * pFanins, char * pFanouts, char * pNode, char * pFanin, char * pFanout, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR ) { int k, nSizeMax = Abc_MaxInt( Vec_IntSize(vFan), Vec_IntSize(vFon) ); fprintf( pFile, "The distribution of %s and %s in the network:\n", pFanins, pFanouts ); fprintf( pFile, " Number %s with %s %s with %s Repr1 Repr2\n", pNode, pFanin, pNode, pFanout ); for ( k = 0; k < nSizeMax; k++ ) { int EntryFan = k < Vec_IntSize(vFan) ? Vec_IntEntry(vFan, k) : 0; int EntryFon = k < Vec_IntSize(vFon) ? Vec_IntEntry(vFon, k) : 0; if ( EntryFan == 0 && EntryFon == 0 ) continue; fprintf( pFile, "%5d : ", k ); if ( EntryFan == 0 ) fprintf( pFile, " " ); else fprintf( pFile, "%12d ", EntryFan ); fprintf( pFile, " " ); if ( EntryFon == 0 ) fprintf( pFile, " " ); else fprintf( pFile, "%12d ", EntryFon ); fprintf( pFile, " " ); if ( EntryFan == 0 ) fprintf( pFile, " " ); else fprintf( pFile, "%12s ", Abc_ObjName(Abc_NtkObj(pNtk, Vec_IntEntry(vFanR, k))) ); fprintf( pFile, " " ); if ( EntryFon == 0 ) fprintf( pFile, " " ); else fprintf( pFile, "%12s ", Abc_ObjName(Abc_NtkObj(pNtk, Vec_IntEntry(vFonR, k))) ); fprintf( pFile, "\n" ); } } void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUseFanio, int fUsePio, int fUseSupp, int fUseCone ) { Vec_Int_t * vFan = Vec_IntAlloc( 0 ); Vec_Int_t * vFon = Vec_IntAlloc( 0 ); Vec_Int_t * vFanR = Vec_IntAlloc( 0 ); Vec_Int_t * vFonR = Vec_IntAlloc( 0 ); assert( fUseFanio + fUsePio + fUseSupp + fUseCone == 1 ); if ( fUseFanio ) { Abc_NtkFaninFanoutCounters( pNtk, vFan, vFon, vFanR, vFonR ); Abc_NtkPrintDistribInternal( pFile, pNtk, "fanins", "fanouts", "Nodes", "fanin", "fanout", vFan, vFon, vFanR, vFonR ); } else if ( fUsePio ) { Abc_NtkInputOutputCounters( pNtk, vFan, vFon, vFanR, vFonR ); Abc_NtkPrintDistribInternal( pFile, pNtk, "fanins", "fanouts", "I/O", "fanin", "fanout", vFan, vFon, vFanR, vFonR ); } else if ( fUseSupp ) { Abc_NtkInOutSupportCounters( pNtk, vFan, vFon, vFanR, vFonR ); Abc_NtkPrintDistribInternal( pFile, pNtk, "input supports", "output supports", "I/O", "in-supp", "out-supp", vFan, vFon, vFanR, vFonR ); } else if ( fUseCone ) { Abc_NtkInOutConeCounters( pNtk, vFan, vFon, vFanR, vFonR ); Abc_NtkPrintDistribInternal( pFile, pNtk, "input cones", "output cones", "I/O", "in-cone", "out-cone", vFan, vFon, vFanR, vFonR ); } Vec_IntFree( vFan ); Vec_IntFree( vFon ); Vec_IntFree( vFanR ); Vec_IntFree( vFonR ); } /**Function************************************************************* Synopsis [Prints the distribution of fanins/fanouts in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t * pNtk, int fMffc ) { char Buffer[100]; Abc_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; Abc_NtkForEachNode( pNtk, pNode, i ) { if ( fMffc && Abc_ObjFanoutNum(pNode) == 1 ) continue; nFanins = Abc_ObjFaninNum(pNode); if ( Abc_NtkIsNetlist(pNtk) ) nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) ); else if ( fMffc ) nFanouts = Abc_NodeMffcSize(pNode); else nFanouts = Abc_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 Abc_NtkForEachNode( pNtk, pNode, i ) { if ( fMffc && Abc_ObjFanoutNum(pNode) == 1 ) continue; nFanins = Abc_ObjFaninNum(pNode); if ( Abc_NtkIsNetlist(pNtk) ) nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) ); else if ( fMffc ) nFanouts = Abc_NodeMffcSize(pNode); else nFanouts = Abc_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 ); } fprintf( pFile, "The distribution of fanins and fanouts in the network:\n" ); fprintf( pFile, " 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 ) fprintf( pFile, "%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 ); fprintf( pFile, "%15s : ", Buffer ); } if ( vFanins->pArray[k] == 0 ) fprintf( pFile, " " ); else fprintf( pFile, "%12d ", vFanins->pArray[k] ); fprintf( pFile, " " ); if ( vFanouts->pArray[k] == 0 ) fprintf( pFile, " " ); else fprintf( pFile, "%12d ", vFanouts->pArray[k] ); fprintf( pFile, "\n" ); } Vec_IntFree( vFanins ); Vec_IntFree( vFanouts ); fprintf( pFile, "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f.\n", nFaninsMax, 1.0*nFaninsAll/Abc_NtkNodeNum(pNtk), nFanoutsMax, 1.0*nFanoutsAll/Abc_NtkNodeNum(pNtk) ); /* Abc_NtkForEachCi( pNtk, pNode, i ) { printf( "%d ", Abc_ObjFanoutNum(pNode) ); } printf( "\n" ); */ } /**Function************************************************************* Synopsis [Prints the fanins/fanouts of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ) { Abc_Obj_t * pNode2; int i; if ( Abc_ObjIsPo(pNode) ) pNode = Abc_ObjFanin0(pNode); fprintf( pFile, "Node %s", Abc_ObjName(pNode) ); fprintf( pFile, "\n" ); fprintf( pFile, "Fanins (%d): ", Abc_ObjFaninNum(pNode) ); Abc_ObjForEachFanin( pNode, pNode2, i ) fprintf( pFile, " %s", Abc_ObjName(pNode2) ); fprintf( pFile, "\n" ); fprintf( pFile, "Fanouts (%d): ", Abc_ObjFaninNum(pNode) ); Abc_ObjForEachFanout( pNode, pNode2, i ) fprintf( pFile, " %s", Abc_ObjName(pNode2) ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Prints the MFFCs of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; extern void Abc_NodeMffcConeSuppPrint( Abc_Obj_t * pNode ); Abc_NtkForEachNode( pNtk, pNode, i ) if ( Abc_ObjFanoutNum(pNode) > 1 ) Abc_NodeMffcConeSuppPrint( pNode ); } /**Function************************************************************* Synopsis [Prints the factored form of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ) { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsSopLogic(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) Abc_NodePrintFactor( pFile, pNode, fUseRealNames ); } /**Function************************************************************* Synopsis [Prints the factored form of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ) { Dec_Graph_t * pGraph; Vec_Ptr_t * vNamesIn; if ( Abc_ObjIsCo(pNode) ) pNode = Abc_ObjFanin0(pNode); if ( Abc_ObjIsPi(pNode) ) { fprintf( pFile, "Skipping the PI node.\n" ); return; } if ( Abc_ObjIsLatch(pNode) ) { fprintf( pFile, "Skipping the latch.\n" ); return; } assert( Abc_ObjIsNode(pNode) ); pGraph = Dec_Factor( (char *)pNode->pData ); if ( fUseRealNames ) { vNamesIn = Abc_NodeGetFaninNames(pNode); Dec_GraphPrint( stdout, pGraph, (char **)vNamesIn->pArray, Abc_ObjName(pNode) ); Abc_NodeFreeNames( vNamesIn ); } else Dec_GraphPrint( stdout, pGraph, (char **)NULL, Abc_ObjName(pNode) ); Dec_GraphFree( pGraph ); } /**Function************************************************************* Synopsis [Prints the level stats of the PO node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fVerbose ) { Abc_Obj_t * pNode; int i, k, Length; if ( fListNodes ) { int nLevels; nLevels = Abc_NtkLevel(pNtk); printf( "Nodes by level:\n" ); for ( i = 0; i <= nLevels; i++ ) { printf( "%2d : ", i ); Abc_NtkForEachNode( pNtk, pNode, k ) if ( (int)pNode->Level == i ) printf( " %s", Abc_ObjName(pNode) ); printf( "\n" ); } return; } // print the delay profile if ( fProfile && Abc_NtkHasMapping(pNtk) ) { int nIntervals = 12; float DelayMax, DelayCur, DelayDelta; int * pLevelCounts; int DelayInt, nOutsSum, nOutsTotal; // get the max delay and delta DelayMax = Abc_NtkDelayTrace( pNtk, NULL, NULL, 0 ); DelayDelta = DelayMax/nIntervals; // collect outputs by delay pLevelCounts = ABC_ALLOC( int, nIntervals ); memset( pLevelCounts, 0, sizeof(int) * nIntervals ); Abc_NtkForEachCo( pNtk, pNode, i ) { if ( Abc_ObjIsNode(Abc_ObjFanin0(pNode)) && Abc_ObjFaninNum(Abc_ObjFanin0(pNode)) == 0 ) DelayInt = 0; else { DelayCur = Abc_NodeReadArrivalWorst( Abc_ObjFanin0(pNode) ); DelayInt = (int)(DelayCur / DelayDelta); if ( DelayInt >= nIntervals ) DelayInt = nIntervals - 1; } pLevelCounts[DelayInt]++; } nOutsSum = 0; nOutsTotal = Abc_NtkCoNum(pNtk); for ( i = 0; i < nIntervals; i++ ) { nOutsSum += pLevelCounts[i]; printf( "[%8.2f - %8.2f] : COs = %4d. %5.1f %%\n", DelayDelta * i, DelayDelta * (i+1), pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal ); } ABC_FREE( pLevelCounts ); return; } else if ( fProfile ) { int LevelMax, * pLevelCounts; int nOutsSum, nOutsTotal; if ( !Abc_NtkIsStrash(pNtk) ) Abc_NtkLevel(pNtk); LevelMax = 0; Abc_NtkForEachCo( pNtk, pNode, i ) if ( LevelMax < (int)Abc_ObjFanin0(pNode)->Level ) LevelMax = Abc_ObjFanin0(pNode)->Level; pLevelCounts = ABC_ALLOC( int, LevelMax + 1 ); memset( pLevelCounts, 0, sizeof(int) * (LevelMax + 1) ); Abc_NtkForEachCo( pNtk, pNode, i ) pLevelCounts[Abc_ObjFanin0(pNode)->Level]++; nOutsSum = 0; nOutsTotal = Abc_NtkCoNum(pNtk); for ( i = 0; i <= LevelMax; i++ ) if ( pLevelCounts[i] ) { nOutsSum += pLevelCounts[i]; printf( "Level = %4d. COs = %4d. %5.1f %%\n", i, pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal ); } ABC_FREE( pLevelCounts ); return; } assert( Abc_NtkIsStrash(pNtk) ); if ( fVerbose ) { // find the longest name Length = 0; Abc_NtkForEachCo( pNtk, pNode, i ) if ( Length < (int)strlen(Abc_ObjName(pNode)) ) Length = strlen(Abc_ObjName(pNode)); if ( Length < 5 ) Length = 5; // print stats for each output Abc_NtkForEachCo( pNtk, pNode, i ) { fprintf( pFile, "CO %4d : %*s ", i, Length, Abc_ObjName(pNode) ); Abc_NodePrintLevel( pFile, pNode ); } } } /**Function************************************************************* Synopsis [Prints the factored form of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ) { Abc_Obj_t * pDriver; Vec_Ptr_t * vNodes; pDriver = Abc_ObjIsCo(pNode)? Abc_ObjFanin0(pNode) : pNode; if ( Abc_ObjIsPi(pDriver) ) { fprintf( pFile, "Primary input.\n" ); return; } if ( Abc_ObjIsLatch(pDriver) ) { fprintf( pFile, "Latch.\n" ); return; } if ( Abc_NodeIsConst(pDriver) ) { fprintf( pFile, "Constant %d.\n", !Abc_ObjFaninC0(pNode) ); return; } // print the level fprintf( pFile, "Level = %3d. ", pDriver->Level ); // print the size of MFFC fprintf( pFile, "Mffc = %5d. ", Abc_NodeMffcSize(pDriver) ); // print the size of the shole cone vNodes = Abc_NtkDfsNodes( pNode->pNtk, &pDriver, 1 ); fprintf( pFile, "Cone = %5d. ", Vec_PtrSize(vNodes) ); Vec_PtrFree( vNodes ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Prints the factored form of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ) { #ifdef ABC_USE_CUDD Vec_Ptr_t * vNamesIn; if ( fUseRealNames ) { vNamesIn = Abc_NodeGetFaninNames(pNode); Extra_PrintKMap( stdout, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, Cudd_Not(pNode->pData), Abc_ObjFaninNum(pNode), NULL, 0, (char **)vNamesIn->pArray ); Abc_NodeFreeNames( vNamesIn ); } else Extra_PrintKMap( stdout, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, Cudd_Not(pNode->pData), Abc_ObjFaninNum(pNode), NULL, 0, NULL ); #endif } /**Function************************************************************* Synopsis [Prints statistics about gates used in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary, int fUpdateProfile ) { Abc_Obj_t * pObj; int fHasBdds, i; int CountConst, CountBuf, CountInv, CountAnd, CountOr, CountOther, CounterTotal, TotalDiff = 0; char * pSop; if ( fUseLibrary && Abc_NtkHasMapping(pNtk) ) { Mio_Gate_t ** ppGates; double Area, AreaTotal; int Counter, nGates, i, nGateNameLen; // clean value of all gates nGates = Mio_LibraryReadGateNum( (Mio_Library_t *)pNtk->pManFunc ); ppGates = Mio_LibraryReadGateArray( (Mio_Library_t *)pNtk->pManFunc ); for ( i = 0; i < nGates; i++ ) { Mio_GateSetValue( ppGates[i], 0 ); if ( fUpdateProfile ) Mio_GateSetProfile2( ppGates[i], 0 ); } // count the gates by name CounterTotal = 0; Abc_NtkForEachNodeNotBarBuf( pNtk, pObj, i ) { if ( i == 0 ) continue; Mio_GateSetValue( (Mio_Gate_t *)pObj->pData, 1 + Mio_GateReadValue((Mio_Gate_t *)pObj->pData) ); if ( fUpdateProfile ) Mio_GateIncProfile2( (Mio_Gate_t *)pObj->pData ); CounterTotal++; // assuming that twin gates follow each other if ( Abc_NtkFetchTwinNode(pObj) ) i++; } // determine the longest gate name nGateNameLen = 5; for ( i = 0; i < nGates; i++ ) { Counter = Mio_GateReadValue( ppGates[i] ); if ( Counter == 0 ) continue; nGateNameLen = Abc_MaxInt( nGateNameLen, strlen(Mio_GateReadName(ppGates[i])) ); } // print the gates AreaTotal = Abc_NtkGetMappedArea(pNtk); for ( i = 0; i < nGates; i++ ) { Counter = Mio_GateReadValue( ppGates[i] ); if ( Counter == 0 && Mio_GateReadProfile(ppGates[i]) == 0 ) continue; if ( Mio_GateReadPinNum(ppGates[i]) > 1 ) TotalDiff += Abc_AbsInt( Mio_GateReadProfile(ppGates[i]) - Mio_GateReadProfile2(ppGates[i]) ); Area = Counter * Mio_GateReadArea( ppGates[i] ); printf( "%-*s Fanin = %2d Instance = %8d Area = %10.2f %6.2f %% %8d %8d %s\n", nGateNameLen, Mio_GateReadName( ppGates[i] ), Mio_GateReadPinNum( ppGates[i] ), Counter, Area, 100.0 * Area / AreaTotal, Mio_GateReadProfile(ppGates[i]), Mio_GateReadProfile2(ppGates[i]), Mio_GateReadForm(ppGates[i]) ); } printf( "%-*s Instance = %8d Area = %10.2f %6.2f %% AbsDiff = %d\n", nGateNameLen, "TOTAL", CounterTotal, AreaTotal, 100.0, TotalDiff ); return; } if ( Abc_NtkIsAigLogic(pNtk) ) return; // transform logic functions from BDD to SOP if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) ) { if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) { printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" ); return; } } // get hold of the SOP of the node CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0; Abc_NtkForEachNodeNotBarBuf( pNtk, pObj, i ) { if ( i == 0 ) continue; if ( Abc_NtkHasMapping(pNtk) ) pSop = Mio_GateReadSop((Mio_Gate_t *)pObj->pData); else pSop = (char *)pObj->pData; // collect the stats if ( Abc_SopIsConst0(pSop) || Abc_SopIsConst1(pSop) ) CountConst++; else if ( Abc_SopIsBuf(pSop) ) CountBuf++; else if ( Abc_SopIsInv(pSop) ) CountInv++; else if ( (!Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop)) || ( Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop)) ) CountAnd++; else if ( ( Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop)) || (!Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop)) ) CountOr++; else CountOther++; CounterTotal++; } printf( "Const = %8d %6.2f %%\n", CountConst , 100.0 * CountConst / CounterTotal ); printf( "Buffer = %8d %6.2f %%\n", CountBuf , 100.0 * CountBuf / CounterTotal ); printf( "Inverter = %8d %6.2f %%\n", CountInv , 100.0 * CountInv / CounterTotal ); printf( "And = %8d %6.2f %%\n", CountAnd , 100.0 * CountAnd / CounterTotal ); printf( "Or = %8d %6.2f %%\n", CountOr , 100.0 * CountOr / CounterTotal ); printf( "Other = %8d %6.2f %%\n", CountOther , 100.0 * CountOther / CounterTotal ); printf( "TOTAL = %8d %6.2f %%\n", CounterTotal, 100.0 * CounterTotal / CounterTotal ); // convert the network back into BDDs if this is how it was if ( fHasBdds ) Abc_NtkSopToBdd(pNtk); } /**Function************************************************************* Synopsis [Prints statistics about gates used in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes1, * vNodes2; Abc_Obj_t * pObj1, * pObj2, * pNode1, * pNode2; int i, k, m, n, Counter; // print the template printf( "Statistics about sharing of logic nodes among the CO pairs.\n" ); printf( "(CO1,CO2)=NumShared : " ); // go though the CO pairs Abc_NtkForEachCo( pNtk, pObj1, i ) { vNodes1 = Abc_NtkDfsNodes( pNtk, &pObj1, 1 ); // mark the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode1, m ) pNode1->fMarkA = 1; // go through the second COs Abc_NtkForEachCo( pNtk, pObj2, k ) { if ( i >= k ) continue; vNodes2 = Abc_NtkDfsNodes( pNtk, &pObj2, 1 ); // count the number of marked Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes2, pNode2, n ) Counter += pNode2->fMarkA; // print printf( "(%d,%d)=%d ", i, k, Counter ); Vec_PtrFree( vNodes2 ); } // unmark the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode1, m ) pNode1->fMarkA = 0; Vec_PtrFree( vNodes1 ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Prints info for each output cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountPis( Vec_Ptr_t * vSupp ) { Abc_Obj_t * pObj; int i, Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) Counter += Abc_ObjIsPi(pObj); return Counter; } void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk, int fMatrix ) { Vec_Ptr_t * vSupp, * vNodes; Abc_Obj_t * pObj; int i, k, nPis; printf( "Structural support info:\n" ); Abc_NtkForEachCo( pNtk, pObj, i ) { vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); nPis = Abc_NtkCountPis( vSupp ); printf( "%5d %20s : Cone = %5d. Supp = %5d. (PIs = %5d. FFs = %5d.)\n", i, Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize, nPis, vSupp->nSize - nPis ); Vec_PtrFree( vNodes ); Vec_PtrFree( vSupp ); } if ( !fMatrix ) { Abc_NtkCleanMarkA( pNtk ); return; } Abc_NtkForEachCi( pNtk, pObj, k ) pObj->fMarkA = 0; printf( "Actual support info:\n" ); Abc_NtkForEachCo( pNtk, pObj, i ) { vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k ) pObj->fMarkA = 1; Vec_PtrFree( vSupp ); Abc_NtkForEachCi( pNtk, pObj, k ) printf( "%d", pObj->fMarkA ); printf( "\n" ); Abc_NtkForEachCi( pNtk, pObj, k ) pObj->fMarkA = 0; } Abc_NtkCleanMarkA( pNtk ); } /**Function************************************************************* Synopsis [Prints information about the object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; fprintf( pFile, "Object %5d : ", pObj->Id ); switch ( pObj->Type ) { case ABC_OBJ_NONE: fprintf( pFile, "NONE " ); break; case ABC_OBJ_CONST1: fprintf( pFile, "Const1 " ); break; case ABC_OBJ_PI: fprintf( pFile, "PI " ); break; case ABC_OBJ_PO: fprintf( pFile, "PO " ); break; case ABC_OBJ_BI: fprintf( pFile, "BI " ); break; case ABC_OBJ_BO: fprintf( pFile, "BO " ); break; case ABC_OBJ_NET: fprintf( pFile, "Net " ); break; case ABC_OBJ_NODE: fprintf( pFile, "Node " ); break; case ABC_OBJ_LATCH: fprintf( pFile, "Latch " ); break; case ABC_OBJ_WHITEBOX: fprintf( pFile, "Whitebox" ); break; case ABC_OBJ_BLACKBOX: fprintf( pFile, "Blackbox" ); break; default: assert(0); break; } // print the fanins fprintf( pFile, " Fanins ( " ); Abc_ObjForEachFanin( pObj, pFanin, i ) fprintf( pFile, "%d ", pFanin->Id ); fprintf( pFile, ") " ); /* fprintf( pFile, " Fanouts ( " ); Abc_ObjForEachFanout( pObj, pFanin, i ) fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' ); fprintf( pFile, ") " ); */ // print the logic function if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) ) fprintf( pFile, " %s", (char*)pObj->pData ); else if ( Abc_ObjIsNode(pObj) && Abc_NtkIsMappedLogic(pObj->pNtk) ) fprintf( pFile, " %s\n", Mio_GateReadName((Mio_Gate_t *)pObj->pData) ); else fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Checks the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintMiter( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pChild, * pConst1 = Abc_AigConst1(pNtk); int i, iOut = -1; abctime Time = Abc_Clock(); int nUnsat = 0; int nSat = 0; int nUndec = 0; int nPis = 0; Abc_NtkForEachPi( pNtk, pObj, i ) nPis += (int)( Abc_ObjFanoutNum(pObj) > 0 ); Abc_NtkForEachPo( pNtk, pObj, i ) { pChild = Abc_ObjChild0(pObj); // check if the output is constant 0 if ( pChild == Abc_ObjNot(pConst1) ) nUnsat++; // check if the output is constant 1 else if ( pChild == pConst1 ) { nSat++; if ( iOut == -1 ) iOut = i; } // check if the output is a primary input else if ( Abc_ObjIsPi(Abc_ObjRegular(pChild)) ) { nSat++; if ( iOut == -1 ) iOut = i; } // check if the output is 1 for the 0000 pattern else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) ) { nSat++; if ( iOut == -1 ) iOut = i; } else nUndec++; } printf( "Miter: I =%6d", nPis ); printf( " N =%7d", Abc_NtkNodeNum(pNtk) ); printf( " ? =%7d", nUndec ); printf( " U =%6d", nUnsat ); printf( " S =%6d", nSat ); Time = Abc_Clock() - Time; printf(" %7.2f sec\n", (float)(Time)/(float)(CLOCKS_PER_SEC)); if ( iOut >= 0 ) printf( "The first satisfiable output is number %d (%s).\n", iOut, Abc_ObjName( Abc_NtkPo(pNtk, iOut) ) ); } /**Function************************************************************* Synopsis [Checks the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintPoEquivs( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pDriver, * pRepr; int i, iRepr; Vec_Int_t * vMap = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachPo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); if ( Abc_NtkIsStrash(pNtk) && pDriver == Abc_AigConst1(pNtk) ) { printf( "%s = Const%d\n", Abc_ObjName(pObj), !Abc_ObjFaninC0(pObj) ); continue; } else if ( !Abc_NtkIsStrash(pNtk) && Abc_NodeIsConst(pDriver) ) { printf( "%s = Const%d\n", Abc_ObjName(pObj), Abc_NodeIsConst1(pDriver) ); continue; } iRepr = Vec_IntEntry( vMap, Abc_ObjId(pDriver) ); if ( iRepr == -1 ) { Vec_IntWriteEntry( vMap, Abc_ObjId(pDriver), i ); continue; } pRepr = Abc_NtkCo(pNtk, iRepr); printf( "%s = %s%s\n", Abc_ObjName(pObj), Abc_ObjFaninC0(pRepr) == Abc_ObjFaninC0(pObj) ? "" : "!", Abc_ObjName(pRepr) ); } Vec_IntFree( vMap ); } typedef struct Gli_Man_t_ Gli_Man_t; extern Gli_Man_t * Gli_ManAlloc( int nObjs, int nRegs, int nFanioPairs ); extern void Gli_ManStop( Gli_Man_t * p ); extern int Gli_ManCreateCi( Gli_Man_t * p, int nFanouts ); extern int Gli_ManCreateCo( Gli_Man_t * p, int iFanin ); extern int Gli_ManCreateNode( Gli_Man_t * p, Vec_Int_t * vFanins, int nFanouts, unsigned * puTruth ); extern void Gli_ManSwitchesAndGlitches( Gli_Man_t * p, int nPatterns, float PiTransProb, int fVerbose ); extern int Gli_ObjNumSwitches( Gli_Man_t * p, int iNode ); extern int Gli_ObjNumGlitches( Gli_Man_t * p, int iNode ); /**Function************************************************************* Synopsis [Returns the percentable of increased power due to glitching.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_NtkMfsTotalGlitching( Abc_Ntk_t * pNtk ) { int nSwitches, nGlitches; Gli_Man_t * p; Vec_Ptr_t * vNodes; Vec_Int_t * vFanins, * vTruth; Abc_Obj_t * pObj, * pFanin; unsigned * puTruth; int i, k; assert( Abc_NtkIsLogic(pNtk) ); assert( Abc_NtkGetFaninMax(pNtk) <= 6 ); if ( Abc_NtkGetFaninMax(pNtk) > 6 ) { printf( "Abc_NtkMfsTotalGlitching() This procedure works only for mapped networks with LUTs size up to 6 inputs.\n" ); return -1.0; } Abc_NtkToAig( pNtk ); vNodes = Abc_NtkDfs( pNtk, 0 ); vFanins = Vec_IntAlloc( 6 ); vTruth = Vec_IntAlloc( 1 << 12 ); // derive network for glitch computation p = Gli_ManAlloc( Vec_PtrSize(vNodes) + Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk), Abc_NtkLatchNum(pNtk), Abc_NtkGetTotalFanins(pNtk) + Abc_NtkCoNum(pNtk) ); Abc_NtkForEachObj( pNtk, pObj, i ) pObj->iTemp = -1; Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = Gli_ManCreateCi( p, Abc_ObjFanoutNum(pObj) ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Vec_IntClear( vFanins ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vFanins, pFanin->iTemp ); puTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNtk->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj), vTruth, 0 ); pObj->iTemp = Gli_ManCreateNode( p, vFanins, Abc_ObjFanoutNum(pObj), puTruth ); } Abc_NtkForEachCo( pNtk, pObj, i ) Gli_ManCreateCo( p, Abc_ObjFanin0(pObj)->iTemp ); // compute glitching Gli_ManSwitchesAndGlitches( p, 4000, 1.0/8.0, 0 ); // compute the ratio nSwitches = nGlitches = 0; Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->iTemp >= 0 ) { nSwitches += Abc_ObjFanoutNum(pObj) * Gli_ObjNumSwitches(p, pObj->iTemp); nGlitches += Abc_ObjFanoutNum(pObj) * Gli_ObjNumGlitches(p, pObj->iTemp); } Gli_ManStop( p ); Vec_PtrFree( vNodes ); Vec_IntFree( vTruth ); Vec_IntFree( vFanins ); return nSwitches ? 100.0*(nGlitches-nSwitches)/nSwitches : 0.0; } /**Function************************************************************* Synopsis [Prints K-map of 6-var function represented by truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_Show6VarFunc( word F0, word F1 ) { // order of cells in the Karnaugh map // int Cells[8] = { 0, 1, 3, 2, 6, 7, 5, 4 }; int Cells[8] = { 0, 4, 6, 2, 3, 7, 5, 1 }; // intermediate variables int s; // symbol counter int h; // horizontal coordinate; int v; // vertical coordinate; assert( (F0 & F1) == 0 ); // output minterms above for ( s = 0; s < 4; s++ ) printf( " " ); printf( " " ); for ( h = 0; h < 8; h++ ) { for ( s = 0; s < 3; s++ ) printf( "%d", ((Cells[h] >> (2-s)) & 1) ); printf( " " ); } printf( "\n" ); // output horizontal line above for ( s = 0; s < 4; s++ ) printf( " " ); printf( "+" ); for ( h = 0; h < 8; h++ ) { for ( s = 0; s < 3; s++ ) printf( "-" ); printf( "+" ); } printf( "\n" ); // output lines with function values for ( v = 0; v < 8; v++ ) { for ( s = 0; s < 3; s++ ) printf( "%d", ((Cells[v] >> (2-s)) & 1) ); printf( " |" ); for ( h = 0; h < 8; h++ ) { printf( " " ); if ( ((F0 >> ((Cells[v]*8)+Cells[h])) & 1) ) printf( "0" ); else if ( ((F1 >> ((Cells[v]*8)+Cells[h])) & 1) ) printf( "1" ); else printf( " " ); printf( " |" ); } printf( "\n" ); // output horizontal line above for ( s = 0; s < 4; s++ ) printf( " " ); // printf( "%c", v == 7 ? '+' : '|' ); printf( "+" ); for ( h = 0; h < 8; h++ ) { for ( s = 0; s < 3; s++ ) printf( "-" ); // printf( "%c", v == 7 ? '+' : '|' ); printf( "%c", (v == 7 || h == 7) ? '+' : '|' ); } printf( "\n" ); } } /**Function************************************************************* Synopsis [Prints K-map of 6-var function represented by truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkShow6VarFunc( char * pF0, char * pF1 ) { word F0, F1; if ( strlen(pF0) != 16 ) { printf( "Wrong length (%d) of 6-var truth table.\n", (int)strlen(pF0) ); return; } if ( strlen(pF1) != 16 ) { printf( "Wrong length (%d) of 6-var truth table.\n", (int)strlen(pF1) ); return; } Extra_ReadHexadecimal( (unsigned *)&F0, pF0, 6 ); Extra_ReadHexadecimal( (unsigned *)&F1, pF1, 6 ); Abc_Show6VarFunc( F0, F1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcProve.c000066400000000000000000000326111300674244400235540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcProve.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Proves the miter using AIG rewriting, FRAIGing, and SAT solving.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcProve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "base/abc/abc.h" #include "proof/fraig/fraig.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, ABC_INT64_T nInspLimit, int * pRetValue, int * pNumFails, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects ); static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, abctime clk, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Attempts to solve the miter using a number of tricks.] Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns a simplified version of the original network (or a constant 0 network). In case the network is not a constant zero and a SAT assignment is found, pNtk->pModel contains a satisfying assignment.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) { Prove_Params_t * pParams = (Prove_Params_t *)pPars; Abc_Ntk_t * pNtk, * pNtkTemp; int RetValue = -1, nIter, nSatFails, Counter; abctime clk; //, timeStart = Abc_Clock(); ABC_INT64_T nSatConfs, nSatInspects, nInspectLimit; // get the starting network pNtk = *ppNtk; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 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(); RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)pParams->nMiteringLimitLast, (ABC_INT64_T)0, 0, NULL, NULL ); Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); *ppNtk = pNtk; return RetValue; } // check the current resource limits 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 brute-force SAT clk = Abc_Clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (ABC_INT64_T)nInspectLimit, 0, &nSatConfs, &nSatInspects ); Abc_NtkMiterPrint( pNtk, "SAT solving", 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" ); *ppNtk = pNtk; return -1; } // try rewriting if ( pParams->fUseRewriting ) { clk = Abc_Clock(); Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); // Counter = 1; while ( 1 ) { /* extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 ); Abc_NtkDelete( pNtkTemp ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; */ /* Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; */ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; } Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose ); } if ( pParams->fUseFraiging ) { // try FRAIGing clk = Abc_Clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects ); Abc_NtkDelete( pNtkTemp ); Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose ); // printf( "NumFails = %d\n", nSatFails ); 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" ); *ppNtk = pNtk; return -1; } } } // try to prove it using brute force SAT #ifdef ABC_USE_CUDD if ( RetValue < 0 && pParams->fUseBdds ) { if ( pParams->fVerbose ) { printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); fflush( stdout ); } clk = Abc_Clock(); pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); if ( pNtk ) { Abc_NtkDelete( pNtkTemp ); RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero((DdManager *)pNtk->pManFunc)) ); } else pNtk = pNtkTemp; Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose ); } #endif if ( RetValue < 0 ) { if ( pParams->fVerbose ) { printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); fflush( stdout ); } clk = Abc_Clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; RetValue = Abc_NtkMiterSat( pNtk, (ABC_INT64_T)pParams->nMiteringLimitLast, (ABC_INT64_T)nInspectLimit, 0, NULL, NULL ); Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); } // assign the model if it was proved by rewriting (const 1 miter) if ( RetValue == 0 && pNtk->pModel == NULL ) { pNtk->pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) ); memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) ); } *ppNtk = pNtk; return RetValue; } /**Function************************************************************* Synopsis [Attempts to solve the miter using a number of tricks.] Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, ABC_INT64_T nInspLimit, int * pRetValue, int * pNumFails, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects ) { Abc_Ntk_t * pNtkNew; Fraig_Params_t Params, * pParams = &Params; Fraig_Man_t * pMan; int nWords1, nWords2, nWordsMin, RetValue; int * pModel; // to determine the number of simulation patterns // use the following strategy // at least 64 words (32 words random and 32 words dynamic) // no more than 256M for one circuit (128M + 128M) nWords1 = 32; nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk)); nWordsMin = Abc_MinInt( nWords1, nWords2 ); // set the FRAIGing parameters Fraig_ParamsSetDefault( pParams ); pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info pParams->nBTLimit = nBTLimit; // the max number of backtracks pParams->nSeconds = -1; // the runtime limit pParams->fTryProve = 0; // do not try to prove the final miter pParams->fDoSparse = 1; // try proving sparse functions pParams->fVerbose = 0; pParams->nInspLimit = nInspLimit; // transform the target into a fraig pMan = (Fraig_Man_t *)Abc_NtkToFraig( pNtk, pParams, 0, 0 ); Fraig_ManProveMiter( pMan ); RetValue = Fraig_ManCheckMiter( pMan ); // create the network pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); // save model if ( RetValue == 0 ) { pModel = Fraig_ManReadModel( pMan ); ABC_FREE( pNtkNew->pModel ); pNtkNew->pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtkNew) ); memcpy( pNtkNew->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtkNew) ); } // save the return values *pRetValue = RetValue; *pNumFails = Fraig_ManReadSatFails( pMan ); *pNumConfs = Fraig_ManReadConflicts( pMan ); *pNumInspects = Fraig_ManReadInspects( pMan ); // delete the fraig manager Fraig_ManFree( pMan ); return pNtkNew; } /**Function************************************************************* Synopsis [Attempts to solve the miter using a number of tricks.] Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, abctime clk, int fVerbose ) { if ( !fVerbose ) return; printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), Abc_NtkIsStrash(pNtk)? Abc_AigLevel(pNtk) : Abc_NtkLevel(pNtk) ); ABC_PRT( pString, Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Implements resynthesis for CEC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMiterRwsat( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkTemp; Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcQbf.c000066400000000000000000000242021300674244400231660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcQbf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Implementation of a simple QBF solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcQbf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START /* Implementation of a simple QBF solver along the lines of A. Solar-Lezama, L. Tancau, R. Bodik, V. Saraswat, and S. Seshia, "Combinatorial sketching for finite programs", 12th International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS 2006), San Jose, CA, October 2006. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); static void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ); static void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ); static void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ); static void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ); extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fAlignPol, int fAndOuts, int fNewSolver, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Solve the QBF problem EpAx[M(p,x)].] Description [Variables p go first, followed by variable x. The number of parameters is nPars. The miter is in pNtk. The miter expresses EQUALITY of the implementation and spec.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int nItersMax, int fDumpCnf, int fVerbose ) { Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp; Vec_Int_t * vPiValues; abctime clkTotal = Abc_Clock(), clkS, clkV; int nIters, nInputs, RetValue, fFound = 0; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkIsComb(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 1 ); assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) ); // assert( Abc_NtkPiNum(pNtk)-nPars < 32 ); nInputs = Abc_NtkPiNum(pNtk) - nPars; if ( fDumpCnf ) { // original problem: \exists p \forall x \exists y. M(p,x,y) // negated problem: \forall p \exists x \exists y. !M(p,x,y) extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Aig_Man_t * pMan = Abc_NtkToDar( pNtk, 0, 0 ); Cnf_Dat_t * pCnf = Cnf_Derive( pMan, 0 ); Vec_Int_t * vVarMap, * vForAlls, * vExists; Aig_Obj_t * pObj; char * pFileName; int i, Entry; // create var map vVarMap = Vec_IntStart( pCnf->nVars ); Aig_ManForEachCi( pMan, pObj, i ) if ( i < nPars ) Vec_IntWriteEntry( vVarMap, pCnf->pVarNums[Aig_ObjId(pObj)], 1 ); // create various maps vForAlls = Vec_IntAlloc( nPars ); vExists = Vec_IntAlloc( Abc_NtkPiNum(pNtk) - nPars ); Vec_IntForEachEntry( vVarMap, Entry, i ) if ( Entry ) Vec_IntPush( vForAlls, i ); else Vec_IntPush( vExists, i ); // generate CNF pFileName = Extra_FileNameGenericAppend( pNtk->pSpec, ".qdimacs" ); Cnf_DataWriteIntoFile( pCnf, pFileName, 0, vForAlls, vExists ); Aig_ManStop( pMan ); Cnf_DataFree( pCnf ); Vec_IntFree( vForAlls ); Vec_IntFree( vExists ); Vec_IntFree( vVarMap ); printf( "The 2QBF formula was written into file \"%s\".\n", pFileName ); return; } // initialize the synthesized network with 0000-combination vPiValues = Vec_IntStart( Abc_NtkPiNum(pNtk) ); // create random init value { int i; srand( time(NULL) ); for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) Vec_IntWriteEntry( vPiValues, i, rand() & 1 ); } Abc_NtkVectorClearPars( vPiValues, nPars ); pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues ); if ( fVerbose ) { printf( "Iter %2d : ", 0 ); printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) ); Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars ); printf( "\n" ); } // iteratively solve for ( nIters = 0; nIters < nItersMax; nIters++ ) { // solve the synthesis instance clkS = Abc_Clock(); // RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL ); RetValue = Abc_NtkDSat( pNtkSyn, (ABC_INT64_T)0, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 ); clkS = Abc_Clock() - clkS; if ( RetValue == 0 ) Abc_NtkModelToVector( pNtkSyn, vPiValues ); if ( RetValue == 1 ) { break; } if ( RetValue == -1 ) { printf( "Synthesis timed out.\n" ); break; } // there is a counter-example // construct the verification instance Abc_NtkVectorClearVars( pNtk, vPiValues, nPars ); pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues ); // complement the output Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 ); // solve the verification instance clkV = Abc_Clock(); RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL ); clkV = Abc_Clock() - clkV; if ( RetValue == 0 ) Abc_NtkModelToVector( pNtkVer, vPiValues ); Abc_NtkDelete( pNtkVer ); if ( RetValue == 1 ) { fFound = 1; break; } if ( RetValue == -1 ) { printf( "Verification timed out.\n" ); break; } // there is a counter-example // create a new synthesis network Abc_NtkVectorClearPars( vPiValues, nPars ); pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues ); // add to the synthesis instance pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 ); Abc_NtkDelete( pNtkSyn2 ); Abc_NtkDelete( pNtkTemp ); if ( fVerbose ) { printf( "Iter %2d : ", nIters+1 ); printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) ); Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars ); printf( " " ); ABC_PRT( "Syn", clkS ); // ABC_PRT( "Ver", clkV ); } if ( nIters+1 == nItersMax ) break; } Abc_NtkDelete( pNtkSyn ); // report the results if ( fFound ) { int nZeros = Vec_IntCountZero( vPiValues ); printf( "Parameters: " ); Abc_NtkVectorPrintPars( vPiValues, nPars ); printf( " Statistics: 0=%d 1=%d\n", nZeros, Vec_IntSize(vPiValues) - nZeros ); printf( "Solved after %d interations. ", nIters ); } else if ( nIters == nItersMax ) printf( "Unsolved after %d interations. ", nIters ); else if ( nIters == nItersMax ) printf( "Quit after %d interatios. ", nItersMax ); else printf( "Implementation does not exist. " ); ABC_PRT( "Total runtime", Abc_Clock() - clkTotal ); Vec_IntFree( vPiValues ); } /**Function************************************************************* Synopsis [Translates model into the vector of values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) { int * pModel, i; pModel = pNtk->pModel; for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) Vec_IntWriteEntry( vPiValues, i, pModel[i] ); } /**Function************************************************************* Synopsis [Clears parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ) { int i; for ( i = 0; i < nPars; i++ ) Vec_IntWriteEntry( vPiValues, i, -1 ); } /**Function************************************************************* Synopsis [Clears variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) { int i; for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) Vec_IntWriteEntry( vPiValues, i, -1 ); } /**Function************************************************************* Synopsis [Clears variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ) { int i; for ( i = 0; i < nPars; i++ ) printf( "%d", Vec_IntEntry(vPiValues,i) ); } /**Function************************************************************* Synopsis [Clears variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) { int i; for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) printf( "%d", Vec_IntEntry(vPiValues,i) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcQuant.c000066400000000000000000000347511300674244400235600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcQuant.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [AIG-based variable quantification.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcQuant.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs fast synthesis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSynthesize( Abc_Ntk_t ** ppNtk, int fMoreEffort ) { extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); Abc_Ntk_t * pNtk, * pNtkTemp; pNtk = *ppNtk; Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); if ( fMoreEffort ) { Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); pNtk = Abc_NtkIvyFraig( pNtkTemp = pNtk, 100, 1, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); } *ppNtk = pNtk; } /**Function************************************************************* Synopsis [Existentially quantifies one variable.] Description [] SideEffects [This procedure creates dangling nodes in the AIG.] SeeAlso [] ***********************************************************************/ int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pNext, * pFanin; int i; assert( Abc_NtkIsStrash(pNtk) ); assert( iVar < Abc_NtkCiNum(pNtk) ); // collect the internal nodes pObj = Abc_NtkCi( pNtk, iVar ); vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 ); // assign the cofactors of the CI node to be constants pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pNtk) ); pObj->pData = Abc_AigConst1(pNtk); // quantify the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj ) { pFanin = Abc_ObjFanin0(pObj); if ( !Abc_NodeIsTravIdCurrent(pFanin) ) { pFanin->pCopy = pFanin; pFanin->pData = pFanin; } pFanin = Abc_ObjFanin1(pObj); if ( !Abc_NodeIsTravIdCurrent(pFanin) ) { pFanin->pCopy = pFanin; pFanin->pData = pFanin; } pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) ); } } Vec_PtrFree( vNodes ); // update the affected COs Abc_NtkForEachCo( pNtk, pObj, i ) { if ( !Abc_NodeIsTravIdCurrent(pObj) ) continue; pFanin = Abc_ObjFanin0(pObj); // get the result of quantification if ( fUniv ) pNext = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); else pNext = Abc_AigOr( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); pNext = Abc_ObjNotCond( pNext, Abc_ObjFaninC0(pObj) ); if ( Abc_ObjRegular(pNext) == pFanin ) continue; // update the fanins of the CO Abc_ObjPatchFanin( pObj, pFanin, pNext ); // if ( Abc_ObjFanoutNum(pFanin) == 0 ) // Abc_AigDeleteNode( pNtk->pManFunc, pFanin ); } // make sure the node has no fanouts // pObj = Abc_NtkCi( pNtk, iVar ); // assert( Abc_ObjFanoutNum(pObj) == 0 ); return 1; } /**Function************************************************************* Synopsis [Constructs the transition relation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ) { char Buffer[1000]; Vec_Ptr_t * vPairs; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pMiter; int i, nLatches; int fSynthesis = 1; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkLatchNum(pNtk) ); nLatches = Abc_NtkLatchNum(pNtk); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); // duplicate the name and the spec sprintf( Buffer, "%s_TR", pNtk->pName ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); // pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); Abc_NtkCleanCopy( pNtk ); // create current state variables Abc_NtkForEachLatchOutput( pNtk, pObj, i ) { pObj->pCopy = Abc_NtkCreatePi(pNtkNew); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } // create next state variables Abc_NtkForEachLatchInput( pNtk, pObj, i ) Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL ); // create PI variables Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); // create the PO Abc_NtkCreatePo( pNtkNew ); // restrash the nodes (assuming a topological order of the old network) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); // create the function of the primary output assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); vPairs = Vec_PtrAlloc( 2*nLatches ); Abc_NtkForEachLatchInput( pNtk, pObj, i ) { Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pObj) ); Vec_PtrPush( vPairs, Abc_NtkPi(pNtkNew, i+nLatches) ); } pMiter = Abc_AigMiter( (Abc_Aig_t *)pNtkNew->pManFunc, vPairs, 0 ); Vec_PtrFree( vPairs ); // add the primary output Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), Abc_ObjNot(pMiter) ); Abc_ObjAssignName( Abc_NtkPo(pNtkNew,0), "rel", NULL ); // quantify inputs if ( fInputs ) { assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) + 2*nLatches ); for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- ) // for ( i = 2*nLatches; i < Abc_NtkPiNum(pNtkNew); i++ ) { Abc_NtkQuantify( pNtkNew, 0, i, fVerbose ); // if ( fSynthesis && (i % 3 == 2) ) if ( fSynthesis ) { Abc_NtkCleanData( pNtkNew ); Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc ); Abc_NtkSynthesize( &pNtkNew, 1 ); } // printf( "Var = %3d. Nodes = %6d. ", Abc_NtkPiNum(pNtkNew) - 1 - i, Abc_NtkNodeNum(pNtkNew) ); // printf( "Var = %3d. Nodes = %6d. ", i - 2*nLatches, Abc_NtkNodeNum(pNtkNew) ); } // printf( "\n" ); Abc_NtkCleanData( pNtkNew ); Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc ); for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- ) { pObj = Abc_NtkPi( pNtkNew, i ); assert( Abc_ObjFanoutNum(pObj) == 0 ); Abc_NtkDeleteObj( pObj ); } } // check consistency of the network if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkTransRel: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Performs one image computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkInitialState( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pMiter; int i, nVars = Abc_NtkPiNum(pNtk)/2; assert( Abc_NtkIsStrash(pNtk) ); // start the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // compute the all-zero state in terms of the CS variables pMiter = Abc_AigConst1(pNtkNew); for ( i = 0; i < nVars; i++ ) pMiter = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pMiter, Abc_ObjNot( Abc_NtkPi(pNtkNew, i) ) ); // add the PO Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter ); return pNtkNew; } /**Function************************************************************* Synopsis [Swaps current state and next state variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSwapVariables( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pMiter, * pObj, * pObj0, * pObj1; int i, nVars = Abc_NtkPiNum(pNtk)/2; assert( Abc_NtkIsStrash(pNtk) ); // start the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // update the PIs for ( i = 0; i < nVars; i++ ) { pObj0 = Abc_NtkPi( pNtk, i ); pObj1 = Abc_NtkPi( pNtk, i+nVars ); pMiter = pObj0->pCopy; pObj0->pCopy = pObj1->pCopy; pObj1->pCopy = pMiter; } // restrash Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); // add the PO pMiter = Abc_ObjChild0Copy( Abc_NtkPo(pNtk,0) ); Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter ); return pNtkNew; } /**Function************************************************************* Synopsis [Performs reachability analisys.] Description [Assumes that the input is the transition relation.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtkRel, int nIters, int fVerbose ) { Abc_Obj_t * pObj; Abc_Ntk_t * pNtkFront, * pNtkReached, * pNtkNext, * pNtkTemp; int i, v, nVars, nNodesOld, nNodesNew, nNodesPrev; int fFixedPoint = 0; int fSynthesis = 1; int fMoreEffort = 1; abctime clk; assert( Abc_NtkIsStrash(pNtkRel) ); assert( Abc_NtkLatchNum(pNtkRel) == 0 ); assert( Abc_NtkPiNum(pNtkRel) % 2 == 0 ); // compute the network composed of the initial states pNtkFront = Abc_NtkInitialState( pNtkRel ); pNtkReached = Abc_NtkDup( pNtkFront ); //Abc_NtkShow( pNtkReached, 0, 0, 0 ); // if ( fVerbose ) // printf( "Transition relation = %6d.\n", Abc_NtkNodeNum(pNtkRel) ); // perform iterations of reachability analysis nNodesPrev = Abc_NtkNodeNum(pNtkFront); nVars = Abc_NtkPiNum(pNtkRel)/2; for ( i = 0; i < nIters; i++ ) { clk = Abc_Clock(); // get the set of next states pNtkNext = Abc_NtkMiterAnd( pNtkRel, pNtkFront, 0, 0 ); Abc_NtkDelete( pNtkFront ); // quantify the current state variables for ( v = 0; v < nVars; v++ ) { Abc_NtkQuantify( pNtkNext, 0, v, fVerbose ); if ( fSynthesis && (v % 3 == 2) ) { Abc_NtkCleanData( pNtkNext ); Abc_AigCleanup( (Abc_Aig_t *)pNtkNext->pManFunc ); Abc_NtkSynthesize( &pNtkNext, fMoreEffort ); } } Abc_NtkCleanData( pNtkNext ); Abc_AigCleanup( (Abc_Aig_t *)pNtkNext->pManFunc ); if ( fSynthesis ) Abc_NtkSynthesize( &pNtkNext, 1 ); // map the next states into the current states pNtkNext = Abc_NtkSwapVariables( pNtkTemp = pNtkNext ); Abc_NtkDelete( pNtkTemp ); // check the termination condition if ( Abc_ObjFanin0(Abc_NtkPo(pNtkNext,0)) == Abc_AigConst1(pNtkNext) ) { fFixedPoint = 1; printf( "Fixed point is reached!\n" ); Abc_NtkDelete( pNtkNext ); break; } // compute new front pNtkFront = Abc_NtkMiterAnd( pNtkNext, pNtkReached, 0, 1 ); Abc_NtkDelete( pNtkNext ); // add the reached states pNtkReached = Abc_NtkMiterAnd( pNtkTemp = pNtkReached, pNtkFront, 1, 0 ); Abc_NtkDelete( pNtkTemp ); // compress the size of Front nNodesOld = Abc_NtkNodeNum(pNtkFront); if ( fSynthesis ) { Abc_NtkSynthesize( &pNtkFront, fMoreEffort ); Abc_NtkSynthesize( &pNtkReached, fMoreEffort ); } nNodesNew = Abc_NtkNodeNum(pNtkFront); // print statistics if ( fVerbose ) { printf( "I = %3d : Reach = %6d Fr = %6d FrM = %6d %7.2f %% ", i + 1, Abc_NtkNodeNum(pNtkReached), nNodesOld, nNodesNew, 100.0*(nNodesNew-nNodesPrev)/nNodesPrev ); ABC_PRT( "T", Abc_Clock() - clk ); } nNodesPrev = Abc_NtkNodeNum(pNtkFront); } if ( !fFixedPoint ) fprintf( stdout, "Reachability analysis stopped after %d iterations.\n", nIters ); // complement the output to represent the set of unreachable states Abc_ObjXorFaninC( Abc_NtkPo(pNtkReached,0), 0 ); // remove next state variables for ( i = 2*nVars - 1; i >= nVars; i-- ) { pObj = Abc_NtkPi( pNtkReached, i ); assert( Abc_ObjFanoutNum(pObj) == 0 ); Abc_NtkDeleteObj( pObj ); } // check consistency of the network if ( !Abc_NtkCheck( pNtkReached ) ) { printf( "Abc_NtkReachability: The network check has failed.\n" ); Abc_NtkDelete( pNtkReached ); return NULL; } return pNtkReached; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcReach.c000066400000000000000000000264201300674244400235040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcReach.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Performs reachability analysis.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Computes the initial state and sets up the variable map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkInitStateVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) { DdNode ** pbVarsX, ** pbVarsY; DdNode * bTemp, * bProd, * bVar; Abc_Obj_t * pLatch; int i; // set the variable mapping for Cudd_bddVarMap() pbVarsX = ABC_ALLOC( DdNode *, dd->size ); pbVarsY = ABC_ALLOC( DdNode *, dd->size ); bProd = b1; Cudd_Ref( bProd ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ]; pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ]; // get the initial value of the latch bVar = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) ); bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) ); ABC_FREE( pbVarsX ); ABC_FREE( pbVarsY ); Cudd_Deref( bProd ); return bProd; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode ** Abc_NtkCreatePartitions( DdManager * dd, Abc_Ntk_t * pNtk, int fReorder, int fVerbose ) { DdNode ** pbParts; DdNode * bVar; Abc_Obj_t * pNode; int i; // extand the BDD manager to represent NS variables assert( dd->size == Abc_NtkCiNum(pNtk) ); Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 ); // enable reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); else Cudd_AutodynDisable( dd ); // compute the transition relation pbParts = ABC_ALLOC( DdNode *, Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pNode, i ) { bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); pbParts[i] = Cudd_bddXnor( dd, bVar, (DdNode *)Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( pbParts[i] ); } // free the global BDDs Abc_NtkFreeGlobalBdds( pNtk, 0 ); // reorder and disable reordering if ( fReorder ) { if ( fVerbose ) fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Abc_NtkLatchNum(pNtk)) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); Cudd_AutodynDisable( dd ); if ( fVerbose ) fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Abc_NtkLatchNum(pNtk)) ); } return pbParts; } /**Function************************************************************* Synopsis [Computes the set of unreachable states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkComputeReachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode ** pbParts, DdNode * bInitial, DdNode * bOutput, int nBddMax, int nIterMax, int fPartition, int fReorder, int fVerbose ) { int fInternalReorder = 0; Extra_ImageTree_t * pTree = NULL; Extra_ImageTree2_t * pTree2 = NULL; DdNode * bReached, * bCubeCs; DdNode * bCurrent, * bNext = NULL, * bTemp; DdNode ** pbVarsY; Abc_Obj_t * pLatch; int i, nIters, nBddSize; int nThreshold = 10000; // collect the NS variables // set the variable mapping for Cudd_bddVarMap() pbVarsY = ABC_ALLOC( DdNode *, dd->size ); Abc_NtkForEachLatch( pNtk, pLatch, i ) pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ]; // start the image computation bCubeCs = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) ); Cudd_Ref( bCubeCs ); if ( fPartition ) pTree = Extra_bddImageStart( dd, bCubeCs, Abc_NtkLatchNum(pNtk), pbParts, Abc_NtkLatchNum(pNtk), pbVarsY, fVerbose ); else pTree2 = Extra_bddImageStart2( dd, bCubeCs, Abc_NtkLatchNum(pNtk), pbParts, Abc_NtkLatchNum(pNtk), pbVarsY, fVerbose ); ABC_FREE( pbVarsY ); Cudd_RecursiveDeref( dd, bCubeCs ); // perform reachability analisys bCurrent = bInitial; Cudd_Ref( bCurrent ); bReached = bInitial; Cudd_Ref( bReached ); assert( nIterMax > 1 ); // required to not deref uninitialized bNext for ( nIters = 1; nIters <= nIterMax; nIters++ ) { // compute the next states if ( fPartition ) bNext = Extra_bddImageCompute( pTree, bCurrent ); else bNext = Extra_bddImageCompute2( pTree2, bCurrent ); Cudd_Ref( bNext ); Cudd_RecursiveDeref( dd, bCurrent ); // remap these states into the current state vars bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); Cudd_RecursiveDeref( dd, bTemp ); // check if there are any new states if ( Cudd_bddLeq( dd, bNext, bReached ) ) break; // check the BDD size nBddSize = Cudd_DagSize(bNext); if ( nBddSize > nBddMax ) break; // check the result if ( !Cudd_bddLeq( dd, bNext, Cudd_Not(bOutput) ) ) { printf( "The miter is proved REACHABLE in %d iterations. ", nIters ); Cudd_RecursiveDeref( dd, bReached ); bReached = NULL; break; } // get the new states bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); // minimize the new states with the reached states // bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); // Cudd_RecursiveDeref( dd, bTemp ); // add to the reached states bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bNext ); if ( fVerbose ) fprintf( stdout, "Iteration = %3d. BDD = %5d. ", nIters, nBddSize ); if ( fInternalReorder && fReorder && nBddSize > nThreshold ) { if ( fVerbose ) fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); Cudd_AutodynDisable( dd ); if ( fVerbose ) fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) ); nThreshold *= 2; } if ( fVerbose ) fprintf( stdout, "\r" ); } Cudd_RecursiveDeref( dd, bNext ); // undo the image tree if ( fPartition ) Extra_bddImageTreeDelete( pTree ); else Extra_bddImageTreeDelete2( pTree2 ); if ( bReached == NULL ) return NULL; // report the stats if ( fVerbose ) { double nMints = Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) ); if ( nIters > nIterMax || Cudd_DagSize(bReached) > nBddMax ) fprintf( stdout, "Reachability analysis is stopped after %d iterations.\n", nIters ); else fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters ); fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Abc_NtkLatchNum(pNtk)) ); fflush( stdout ); } //ABC_PRB( dd, bReached ); Cudd_Deref( bReached ); if ( nIters > nIterMax || Cudd_DagSize(bReached) > nBddMax ) printf( "Verified ONLY FOR STATES REACHED in %d iterations. \n", nIters ); printf( "The miter is proved unreachable in %d iteration. ", nIters ); return bReached; } /**Function************************************************************* Synopsis [Performs reachability to see if any .] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkVerifyUsingBdds( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fPartition, int fReorder, int fVerbose ) { DdManager * dd; DdNode ** pbParts; DdNode * bOutput, * bReached, * bInitial; int i; abctime clk = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 1 ); assert( Abc_ObjFanoutNum(Abc_NtkPo(pNtk,0)) == 0 ); // PO should go first // compute the global BDDs of the latches dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddMax, 1, fReorder, fVerbose ); if ( dd == NULL ) { printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", nBddMax ); return; } if ( fVerbose ) printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); // save the output BDD bOutput = (DdNode *)Abc_ObjGlobalBdd(Abc_NtkPo(pNtk,0)); Cudd_Ref( bOutput ); // create partitions pbParts = Abc_NtkCreatePartitions( dd, pNtk, fReorder, fVerbose ); // create the initial state and the variable map bInitial = Abc_NtkInitStateVarMap( dd, pNtk, fVerbose ); Cudd_Ref( bInitial ); // check the result if ( !Cudd_bddLeq( dd, bInitial, Cudd_Not(bOutput) ) ) printf( "The miter is proved REACHABLE in the initial state. " ); else { // compute the reachable states bReached = Abc_NtkComputeReachable( dd, pNtk, pbParts, bInitial, bOutput, nBddMax, nIterMax, fPartition, fReorder, fVerbose ); if ( bReached != NULL ) { Cudd_Ref( bReached ); Cudd_RecursiveDeref( dd, bReached ); } } // cleanup Cudd_RecursiveDeref( dd, bOutput ); Cudd_RecursiveDeref( dd, bInitial ); for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ ) Cudd_RecursiveDeref( dd, pbParts[i] ); ABC_FREE( pbParts ); Extra_StopManager( dd ); // report the runtime ABC_PRT( "Time", Abc_Clock() - clk ); fflush( stdout ); } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcRec3.c000066400000000000000000001500651300674244400232610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcRec2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Record of semi-canonical AIG subgraphs.] Author [Allan Yang, Alan Mishchenko] Affiliation [Fudan University in Shanghai, UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "map/if/if.h" #include "bool/kit/kit.h" #include "aig/gia/giaAig.h" #include "misc/vec/vecMem.h" #include "opt/dau/dau.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START #define LMS_VAR_MAX 16 // LMS_VAR_MAX >= 6 #define LMS_MAX_WORD (1<<(LMS_VAR_MAX-6)) //#define LMS_USE_OLD_FORM //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* This LMS manager can be used in two modes: - library constuction - AIG level minimization To switch from library construction to AIG level minimization LSM manager should be restarted by dumping GIA (rec_dump3 .aig) and starting LMS manager again (rec_start3 .aig). */ typedef struct Lms_Man_t_ Lms_Man_t; struct Lms_Man_t_ { // parameters int nVars; // the number of variables int nWords; // the number of TT words int nCuts; // the max number of cuts to use int fFuncOnly; // record only functions int fLibConstr; // this manager is used for library construction // internal data for library construction Gia_Man_t * pGia; // the record Vec_Mem_t * vTtMem; // truth table memory and hash table // Vec_Mem_t * vTtMem2; // truth table memory and hash table Vec_Int_t * vTruthIds; // truth table IDs of each PO // internal data for AIG level minimization (allocated the first time it is called) Vec_Int_t * vTruthPo; // first PO where this canonicized truth table was seen Vec_Wrd_t * vDelays; // pin-to-pin delays of each PO Vec_Str_t * vAreas; // number of AND gates in each PO Vec_Int_t * vFreqs; // subgraph usage frequencies Vec_Int_t * vTruthFreqs; // truth table usage frequencies // temporaries Vec_Ptr_t * vNodes; // the temporary nodes Vec_Ptr_t * vLabelsP; // temporary storage for HOP node labels Vec_Int_t * vLabels; // temporary storage for AIG node labels Vec_Str_t * vSupps; // used temporarily by TT dumping word pTemp1[LMS_MAX_WORD]; // copy of the truth table word pTemp2[LMS_MAX_WORD]; // copy of the truth table // statistics int nTried; int nFilterSize; int nFilterRedund; int nFilterVolume; int nFilterTruth; int nFilterError; int nFilterSame; int nAdded; int nAddedFuncs; int nHoleInTheWall; // runtime abctime timeTruth; abctime timeCanon; abctime timeBuild; abctime timeCheck; abctime timeInsert; abctime timeOther; abctime timeTotal; }; static Lms_Man_t * s_pMan3 = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Compute delay/area profiles of POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lms_DelayGet( word D, int v ) { assert(v >= 0 && v < LMS_VAR_MAX); return (int)((D >> (v << 2)) & 0xF); } static inline void Lms_DelaySet( word * pD, int v, int d ) { assert(v >= 0 && v < LMS_VAR_MAX); assert(d >= 0 && d < LMS_VAR_MAX); *pD |= ((word)d << (v << 2)); } static inline word Lms_DelayInit( int v ) { assert(v >= 0 && v < LMS_VAR_MAX); return (word)1 << (v << 2); } static inline word Lms_DelayMax( word D1, word D2, int nVars ) { int v, Max; word D = 0; for ( v = 0; v < nVars; v++ ) if ( (Max = Abc_MaxInt(Lms_DelayGet(D1, v), Lms_DelayGet(D2, v))) ) Lms_DelaySet( &D, v, Abc_MinInt(Max + 1, 15) ); return D; } static inline word Lms_DelayDecrement( word D1, int nVars ) { int v; word D = 0; for ( v = 0; v < nVars; v++ ) if ( Lms_DelayGet(D1, v) ) Lms_DelaySet( &D, v, Lms_DelayGet(D1, v) - 1 ); return D; } static inline int Lms_DelayEqual( word D1, word D2, int nVars ) // returns 1 if D1 has the same delays than D2 { int v; for ( v = 0; v < nVars; v++ ) if ( Lms_DelayGet(D1, v) != Lms_DelayGet(D2, v) ) return 0; return 1; } static inline int Lms_DelayDom( word D1, word D2, int nVars ) // returns 1 if D1 has the same or smaller delays than D2 { int v; for ( v = 0; v < nVars; v++ ) if ( Lms_DelayGet(D1, v) > Lms_DelayGet(D2, v) ) return 0; return 1; } static inline void Lms_DelayPrint( word D, int nVars ) { int v; printf( "Delay profile = {" ); for ( v = 0; v < nVars; v++ ) printf( " %d", Lms_DelayGet(D, v) ); printf( " }\n" ); } Vec_Wrd_t * Lms_GiaDelays( Gia_Man_t * p ) { Vec_Wrd_t * vDelays, * vResult; Gia_Obj_t * pObj; int i; // compute delay profiles of all objects vDelays = Vec_WrdAlloc( Gia_ManObjNum(p) ); Vec_WrdPush( vDelays, 0 ); // const 0 Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) Vec_WrdPush( vDelays, Lms_DelayMax( Vec_WrdEntry(vDelays, Gia_ObjFaninId0(pObj, i)), Vec_WrdEntry(vDelays, Gia_ObjFaninId1(pObj, i)), Gia_ManCiNum(p) ) ); else if ( Gia_ObjIsCo(pObj) ) Vec_WrdPush( vDelays, Lms_DelayDecrement( Vec_WrdEntry(vDelays, Gia_ObjFaninId0(pObj, i)), Gia_ManCiNum(p) ) ); else if ( Gia_ObjIsCi(pObj) ) Vec_WrdPush( vDelays, Lms_DelayInit( Gia_ObjCioId(pObj) ) ); else assert( 0 ); } // collect delay profiles of COs only vResult = Vec_WrdAlloc( Gia_ManCoNum(p) ); Gia_ManForEachCo( p, pObj, i ) Vec_WrdPush( vResult, Vec_WrdEntry(vDelays, Gia_ObjId(p, pObj)) ); Vec_WrdFree( vDelays ); return vResult; } void Lms_ObjAreaMark_rec( Gia_Obj_t * pObj ) { if ( pObj->fMark0 || Gia_ObjIsCi(pObj) ) return; pObj->fMark0 = 1; Lms_ObjAreaMark_rec( Gia_ObjFanin0(pObj) ); Lms_ObjAreaMark_rec( Gia_ObjFanin1(pObj) ); } int Lms_ObjAreaUnmark_rec( Gia_Obj_t * pObj ) { if ( !pObj->fMark0 || Gia_ObjIsCi(pObj) ) return 0; pObj->fMark0 = 0; return 1 + Lms_ObjAreaUnmark_rec( Gia_ObjFanin0(pObj) ) + Lms_ObjAreaUnmark_rec( Gia_ObjFanin1(pObj) ); } int Lms_ObjArea( Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Lms_ObjAreaMark_rec( pObj ); return Lms_ObjAreaUnmark_rec( pObj ); } Vec_Str_t * Lms_GiaAreas( Gia_Man_t * p ) { Vec_Str_t * vAreas; Gia_Obj_t * pObj; int i; vAreas = Vec_StrAlloc( Gia_ManCoNum(p) ); Gia_ManForEachCo( p, pObj, i ) Vec_StrPush( vAreas, (char)(Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ? Lms_ObjArea(Gia_ObjFanin0(pObj)) : 0) ); return vAreas; } Vec_Str_t * Lms_GiaSuppSizes( Gia_Man_t * p ) { Vec_Str_t * vResult; Vec_Str_t * vSupps; Gia_Obj_t * pObj; int i; vSupps = Vec_StrAlloc( Gia_ManObjNum(p) ); Vec_StrPush( vSupps, 0 ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) Vec_StrPush( vSupps, (char)Abc_MaxInt( Vec_StrEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_StrEntry(vSupps, Gia_ObjFaninId1(pObj, i)) ) ); else if ( Gia_ObjIsCo(pObj) ) Vec_StrPush( vSupps, Vec_StrEntry(vSupps, Gia_ObjFaninId0(pObj, i)) ); else if ( Gia_ObjIsCi(pObj) ) Vec_StrPush( vSupps, (char)(Gia_ObjCioId(pObj)+1) ); else assert( 0 ); } assert( Vec_StrSize(vSupps) == Gia_ManObjNum(p) ); vResult = Vec_StrAlloc( Gia_ManCoNum(p) ); Gia_ManForEachCo( p, pObj, i ) Vec_StrPush( vResult, Vec_StrEntry(vSupps, Gia_ObjId(p, pObj)) ); Vec_StrFree( vSupps ); return vResult; } void Lms_GiaProfilesPrint( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Vec_Wrd_t * vDelays; Vec_Str_t * vAreas; vDelays = Lms_GiaDelays( p ); vAreas = Lms_GiaAreas( p ); Gia_ManForEachPo( p, pObj, i ) { printf( "%6d : ", i ); printf( "A = %2d ", Vec_StrEntry(vAreas, i) ); Lms_DelayPrint( Vec_WrdEntry(vDelays, i), Gia_ManPiNum(p) ); // Lms_GiaPrintSubgraph( p, pObj ); // printf( "\n" ); } Vec_WrdFree( vDelays ); Vec_StrFree( vAreas ); } /**Function************************************************************* Synopsis [Prints one GIA subgraph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lms_GiaPrintSubgraph_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( !pObj->fMark0 || Gia_ObjIsCi(pObj) ) return; pObj->fMark0 = 0; assert( Gia_ObjIsAnd(pObj) ); Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin0(pObj) ); Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin1(pObj) ); Gia_ObjPrint( p, pObj ); } void Lms_GiaPrintSubgraph( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) { Lms_ObjAreaMark_rec( Gia_ObjFanin0(pObj) ); Lms_GiaPrintSubgraph_rec( p, Gia_ObjFanin0(pObj) ); } else Gia_ObjPrint( p, Gia_ObjFanin0(pObj) ); Gia_ObjPrint( p, pObj ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Lms_Man_t * Lms_ManStart( Gia_Man_t * pGia, int nVars, int nCuts, int fFuncOnly, int fVerbose ) { Lms_Man_t * p; abctime clk, clk2 = Abc_Clock(); // if GIA is given, use the number of variables from GIA nVars = pGia ? Gia_ManCiNum(pGia) : nVars; assert( nVars >= 6 && nVars <= LMS_VAR_MAX ); // allocate manager p = ABC_CALLOC( Lms_Man_t, 1 ); // parameters p->nVars = nVars; p->nCuts = nCuts; p->nWords = Abc_Truth6WordNum( nVars ); p->fFuncOnly = fFuncOnly; // internal data for library construction p->vTtMem = Vec_MemAlloc( p->nWords, 12 ); // 32 KB/page for 6-var functions // p->vTtMem2 = Vec_MemAlloc( p->nWords, 12 ); // 32 KB/page for 6-var functions Vec_MemHashAlloc( p->vTtMem, 10000 ); // Vec_MemHashAlloc( p->vTtMem2, 10000 ); if ( fFuncOnly ) return p; p->vTruthIds = Vec_IntAlloc( 10000 ); if ( pGia == NULL ) { int i; p->pGia = Gia_ManStart( 10000 ); p->pGia->pName = Abc_UtilStrsav( "record" ); for ( i = 0; i < nVars; i++ ) Gia_ManAppendCi( p->pGia ); } else { Gia_Obj_t * pObj; word * pTruth; int i, Index, Prev = -1; p->pGia = pGia; // populate the manager with subgraphs present in GIA p->nAdded = Gia_ManCoNum( p->pGia ); Gia_ManForEachCo( p->pGia, pObj, i ) { clk = Abc_Clock(); pTruth = Gia_ObjComputeTruthTable( p->pGia, pObj ); p->timeTruth += Abc_Clock() - clk; clk = Abc_Clock(); Index = Vec_MemHashInsert( p->vTtMem, pTruth ); p->timeInsert += Abc_Clock() - clk; assert( Index == Prev || Index == Prev + 1 ); // GIA subgraphs should be ordered Vec_IntPush( p->vTruthIds, Index ); Prev = Index; } } // temporaries p->vNodes = Vec_PtrAlloc( 1000 ); p->vLabelsP = Vec_PtrAlloc( 1000 ); p->vLabels = Vec_IntAlloc( 1000 ); p->timeTotal += Abc_Clock() - clk2; return p; } void Lms_ManStop( Lms_Man_t * p ) { // temporaries Vec_IntFreeP( &p->vLabels ); Vec_PtrFreeP( &p->vLabelsP ); Vec_PtrFreeP( &p->vNodes ); // internal data for AIG level minimization Vec_IntFreeP( &p->vTruthPo ); Vec_WrdFreeP( &p->vDelays ); Vec_StrFreeP( &p->vAreas ); Vec_IntFreeP( &p->vFreqs ); Vec_IntFreeP( &p->vTruthFreqs ); // internal data for library construction Vec_IntFreeP( &p->vTruthIds ); Vec_MemHashFree( p->vTtMem ); // Vec_MemHashFree( p->vTtMem2 ); Vec_MemFree( p->vTtMem ); // Vec_MemFree( p->vTtMem2 ); Gia_ManStopP( &p->pGia ); ABC_FREE( p ); } void Lms_ManPrepare( Lms_Man_t * p ) { // compute the first PO for each semi-canonical form int i, Entry; assert( !p->fLibConstr ); assert( p->vTruthPo == NULL ); p->vTruthPo = Vec_IntStartFull( Vec_MemEntryNum(p->vTtMem)+1 ); assert( Vec_IntFindMin(p->vTruthIds) >= 0 ); assert( Vec_IntFindMax(p->vTruthIds) < Vec_MemEntryNum(p->vTtMem) ); Vec_IntForEachEntry( p->vTruthIds, Entry, i ) if ( Vec_IntEntry(p->vTruthPo, Entry) == -1 ) Vec_IntWriteEntry( p->vTruthPo, Entry, i ); Vec_IntWriteEntry( p->vTruthPo, Vec_MemEntryNum(p->vTtMem), Gia_ManCoNum(p->pGia) ); // compute delay/area and init frequency assert( p->vDelays == NULL ); assert( p->vAreas == NULL ); assert( p->vFreqs == NULL ); p->vDelays = Lms_GiaDelays( p->pGia ); p->vAreas = Lms_GiaAreas( p->pGia ); p->vFreqs = Vec_IntStart( Gia_ManCoNum(p->pGia) ); } void Lms_ManPrintFuncStats( Lms_Man_t * p ) { Vec_Str_t * vSupps; int Counters[LMS_VAR_MAX+1] = {0}, CountersS[LMS_VAR_MAX+1] = {0}; int i, Entry, Next; if ( p->pGia == NULL ) return; if ( p->fLibConstr ) return; if ( p->vTruthPo == NULL ) Lms_ManPrepare( p ); vSupps = Lms_GiaSuppSizes( p->pGia ); Vec_IntForEachEntry( p->vTruthPo, Entry, i ) { if ( i == Vec_IntSize(p->vTruthPo) - 1 ) break; Next = Vec_IntEntry( p->vTruthPo, i+1 ); Counters[(int)Vec_StrEntry(vSupps, Entry)]++; CountersS[(int)Vec_StrEntry(vSupps, Entry)] += Next - Entry; } for ( i = 0; i <= LMS_VAR_MAX; i++ ) if ( Counters[i] ) printf( "Inputs = %2d. Funcs = %8d. Subgrs = %8d. Ratio = %6.2f.\n", i, Counters[i], CountersS[i], 1.0*CountersS[i]/Counters[i] ); Vec_StrFree( vSupps ); } void Lms_ManPrintFreqStats( Lms_Man_t * p ) { int CountDsdNpn[3] = {0}; // full/part/none int CountDsdAll[3] = {0}; // full/part/none int CountStepNpn[3] = {0}; // full/1step/complex int CountStepAll[3] = {0}; // full/1step/complex char pBuffer[1000]; int nSuppSize; int nNonDecSize; word * pTruth; int i, Freq, Status; printf( "Cuts = %10d. ", p->nTried ); // printf( "Funcs = %10d (%6.2f %%). ", Vec_MemEntryNum(p->vTtMem2), 100.0*Vec_MemEntryNum(p->vTtMem2)/p->nTried ); printf( "Class = %10d (%6.2f %%). ", Vec_MemEntryNum(p->vTtMem), 100.0*Vec_MemEntryNum(p->vTtMem)/p->nTried ); printf( "\n" ); // return; Vec_IntForEachEntry( p->vTruthFreqs, Freq, i ) { pTruth = Vec_MemReadEntry(p->vTtMem, i); /* printf( "%6d -- %6d : ", i, Freq ); Kit_DsdWriteFromTruth( pBuffer, (unsigned *)pTruth, p->nVars ); printf( "%s\n", pBuffer ); */ nSuppSize = Abc_TtSupportSize( pTruth, p->nVars ); nNonDecSize = Dau_DsdDecompose( pTruth, p->nVars, 0, 0, pBuffer ); if ( nNonDecSize == 0 ) { CountDsdNpn[0]++; CountDsdAll[0] += Freq; } else if ( nNonDecSize < nSuppSize ) { CountDsdNpn[1]++; CountDsdAll[1] += Freq; } else // non-dec { CountDsdNpn[2]++; CountDsdAll[2] += Freq; } if ( nNonDecSize == 0 ) { CountStepNpn[0]++; CountStepAll[0] += Freq; continue; } // check the non dec core Status = Dau_DsdCheck1Step( NULL, pTruth, nNonDecSize, NULL ); if ( Status >= 0 ) { CountStepNpn[1]++; CountStepAll[1] += Freq; } else { assert( Status == -2 ); CountStepNpn[2]++; CountStepAll[2] += Freq; } } // print the results printf( "NPN: " ); printf( "Full = %6.2f %% ", 100.0 * CountDsdNpn[0] / Vec_MemEntryNum(p->vTtMem) ); printf( "Part = %6.2f %% ", 100.0 * CountDsdNpn[1] / Vec_MemEntryNum(p->vTtMem) ); printf( "None = %6.2f %% ", 100.0 * CountDsdNpn[2] / Vec_MemEntryNum(p->vTtMem) ); // printf( "\n" ); printf( " " ); // print the results printf( "All: " ); printf( "Full = %6.2f %% ", 100.0 * CountDsdAll[0] / p->nTried ); printf( "Part = %6.2f %% ", 100.0 * CountDsdAll[1] / p->nTried ); printf( "None = %6.2f %% ", 100.0 * CountDsdAll[2] / p->nTried ); printf( "\n" ); // print the results printf( "NPN: " ); printf( "Full = %6.2f %% ", 100.0 * CountStepNpn[0] / Vec_MemEntryNum(p->vTtMem) ); printf( "1stp = %6.2f %% ", 100.0 * CountStepNpn[1] / Vec_MemEntryNum(p->vTtMem) ); printf( "Comp = %6.2f %% ", 100.0 * CountStepNpn[2] / Vec_MemEntryNum(p->vTtMem) ); // printf( "\n" ); printf( " " ); // print the results printf( "All: " ); printf( "Full = %6.2f %% ", 100.0 * CountStepAll[0] / p->nTried ); printf( "1stp = %6.2f %% ", 100.0 * CountStepAll[1] / p->nTried ); printf( "Comp = %6.2f %% ", 100.0 * CountStepAll[2] / p->nTried ); printf( "\n" ); } void Lms_ManPrint( Lms_Man_t * p ) { // Gia_ManPrintStats( p->pGia, 0, 0 ); printf( "Library with %d vars has %d classes and %d AIG subgraphs with %d AND nodes.\n", p->nVars, Vec_MemEntryNum(p->vTtMem), p->nAdded, p->pGia ? Gia_ManAndNum(p->pGia) : 0 ); // Lms_ManPrintFreqStats( p ); Lms_ManPrintFuncStats( p ); p->nAddedFuncs = Vec_MemEntryNum(p->vTtMem); printf( "Subgraphs tried = %10d. (%6.2f %%)\n", p->nTried, !p->nTried? 0 : 100.0*p->nTried/p->nTried ); printf( "Subgraphs filtered by support size = %10d. (%6.2f %%)\n", p->nFilterSize, !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried ); printf( "Subgraphs filtered by structural redundancy = %10d. (%6.2f %%)\n", p->nFilterRedund, !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried ); printf( "Subgraphs filtered by volume = %10d. (%6.2f %%)\n", p->nFilterVolume, !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried ); printf( "Subgraphs filtered by TT redundancy = %10d. (%6.2f %%)\n", p->nFilterTruth, !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried ); printf( "Subgraphs filtered by error = %10d. (%6.2f %%)\n", p->nFilterError, !p->nTried? 0 : 100.0*p->nFilterError/p->nTried ); printf( "Subgraphs filtered by isomorphism = %10d. (%6.2f %%)\n", p->nFilterSame, !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried ); printf( "Subgraphs added = %10d. (%6.2f %%)\n", p->nAdded, !p->nTried? 0 : 100.0*p->nAdded/p->nTried ); printf( "Functions added = %10d. (%6.2f %%)\n", p->nAddedFuncs, !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried ); if ( p->nHoleInTheWall ) printf( "Cuts whose logic structure has a hole = %10d. (%6.2f %%)\n", p->nHoleInTheWall, !p->nTried? 0 : 100.0*p->nHoleInTheWall/p->nTried ); p->timeOther = p->timeTotal - p->timeTruth - p->timeCanon - p->timeBuild - p->timeCheck - p->timeInsert; ABC_PRTP( "Runtime: Truth ", p->timeTruth, p->timeTotal ); ABC_PRTP( "Runtime: Canon ", p->timeCanon, p->timeTotal ); ABC_PRTP( "Runtime: Build ", p->timeBuild, p->timeTotal ); ABC_PRTP( "Runtime: Check ", p->timeCheck, p->timeTotal ); ABC_PRTP( "Runtime: Insert", p->timeInsert, p->timeTotal ); ABC_PRTP( "Runtime: Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "Runtime: TOTAL ", p->timeTotal, p->timeTotal ); } /**Function************************************************************* Synopsis [Recanonicizes the library and add it to the current library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRecLibMerge3( Gia_Man_t * pLib ) { int fCheck = 0; Lms_Man_t * p = s_pMan3; Gia_Man_t * pGia = p->pGia; Vec_Str_t * vSupps; char pCanonPerm[LMS_VAR_MAX]; unsigned uCanonPhase; word * pTruth; int i, k, Index, iFanin0, iFanin1, nLeaves; Gia_Obj_t * pObjPo, * pDriver, * pTemp = NULL; abctime clk, clk2 = Abc_Clock(); if ( Gia_ManCiNum(pLib) != Gia_ManCiNum(pGia) ) { printf( "The number of Library inputs (%d) differs from the number of Gia inputs (%d).\n", Gia_ManCiNum(pLib), Gia_ManCiNum(pGia) ); return; } assert( Gia_ManCiNum(pLib) == Gia_ManCiNum(pGia) ); // create hash table if not available if ( pGia->pHTable == NULL ) Gia_ManHashStart( pGia ); // add AIG subgraphs vSupps = Lms_GiaSuppSizes( pLib ); Gia_ManForEachCo( pLib, pObjPo, k ) { // get support size nLeaves = Vec_StrEntry(vSupps, k); assert( nLeaves > 1 ); // compute the truth table clk = Abc_Clock(); pTruth = Gia_ObjComputeTruthTable( pLib, Gia_ObjFanin0(pObjPo) ); p->timeTruth += Abc_Clock() - clk; // semi-canonicize clk = Abc_Clock(); memcpy( p->pTemp1, pTruth, p->nWords * sizeof(word) ); #ifdef LMS_USE_OLD_FORM uCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm ); #else uCanonPhase = Abc_TtCanonicize( p->pTemp1, nLeaves, pCanonPerm ); #endif Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars ); p->timeCanon += Abc_Clock() - clk; // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth if ( nLeaves == 2 && Abc_TtSupportSize(pTruth, 2) != 2 ) continue; clk = Abc_Clock(); // map cut leaves into elementary variables of GIA for ( i = 0; i < nLeaves; i++ ) Gia_ManCi( pLib, pCanonPerm[i] )->Value = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManPi(pGia, i)), (uCanonPhase >> i) & 1 ); // build internal nodes assert( Vec_IntSize(pLib->vTtNodes) > 0 ); Gia_ManForEachObjVec( pLib->vTtNodes, pLib, pTemp, i ) { iFanin0 = Abc_LitNotCond( Gia_ObjFanin0(pTemp)->Value, Gia_ObjFaninC0(pTemp) ); iFanin1 = Abc_LitNotCond( Gia_ObjFanin1(pTemp)->Value, Gia_ObjFaninC1(pTemp) ); pTemp->Value = Gia_ManHashAnd( pGia, iFanin0, iFanin1 ); } p->timeBuild += Abc_Clock() - clk; // check if this node is already driving a PO assert( Gia_ObjIsAnd(pTemp) ); pDriver = Gia_ManObj(pGia, Abc_Lit2Var(pTemp->Value)); if ( pDriver->fMark1 ) { p->nFilterSame++; continue; } pDriver->fMark1 = 1; // create output Gia_ManAppendCo( pGia, Abc_LitNotCond( pTemp->Value, (uCanonPhase >> nLeaves) & 1 ) ); // verify truth table if ( fCheck ) { clk = Abc_Clock(); pTemp = Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1); pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1) ); p->timeCheck += Abc_Clock() - clk; if ( memcmp( p->pTemp1, pTruth, p->nWords * sizeof(word) ) != 0 ) { Kit_DsdPrintFromTruth( (unsigned *)pTruth, nLeaves ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)p->pTemp1, nLeaves ); printf( "\n" ); printf( "Truth table verification has failed.\n" ); // drive PO with constant Gia_ManPatchCoDriver( pGia, Gia_ManCoNum(pGia)-1, 0 ); // save truth table ID Vec_IntPush( p->vTruthIds, -1 ); p->nFilterTruth++; continue; } } clk = Abc_Clock(); // add the resulting truth table to the hash table Index = Vec_MemHashInsert( p->vTtMem, p->pTemp1 ); // save truth table ID Vec_IntPush( p->vTruthIds, Index ); assert( Gia_ManCoNum(pGia) == Vec_IntSize(p->vTruthIds) ); p->nAdded++; p->timeInsert += Abc_Clock() - clk; } Vec_StrFree( vSupps ); p->timeTotal += Abc_Clock() - clk2; } /**Function************************************************************* Synopsis [Evaluates one cut during library construction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRecAddCut3( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ) { Lms_Man_t * p = s_pMan3; char pCanonPerm[LMS_VAR_MAX]; unsigned uCanonPhase; int i, Index, iFanin0, iFanin1, fHole; int nLeaves = If_CutLeaveNum(pCut); Vec_Ptr_t * vNodes = p->vNodes; Gia_Man_t * pGia = p->pGia; Gia_Obj_t * pDriver; If_Obj_t * pIfObj = NULL; word * pTruth; abctime clk; p->nTried++; // skip small cuts assert( p->nVars == (int)pCut->nLimit ); if ( nLeaves < 2 || (nLeaves == 2 && Abc_TtSupportSize(If_CutTruthW(pIfMan, pCut), 2) != 2) ) { p->nFilterSize++; return 1; } // if ( p->vTtMem2 ) // Vec_MemHashInsert( p->vTtMem2, If_CutTruthW(pCut) ); // semi-canonicize truth table clk = Abc_Clock(); memcpy( p->pTemp1, If_CutTruthW(pIfMan, pCut), p->nWords * sizeof(word) ); #ifdef LMS_USE_OLD_FORM uCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm ); #else uCanonPhase = Abc_TtCanonicize( p->pTemp1, nLeaves, pCanonPerm ); #endif Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars ); p->timeCanon += Abc_Clock() - clk; // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth if ( p->pGia == NULL ) { clk = Abc_Clock(); // add the resulting truth table to the hash table Index = Vec_MemHashInsert( p->vTtMem, p->pTemp1 ); /* if ( p->vTruthFreqs == NULL ) p->vTruthFreqs = Vec_IntAlloc( 1000 ); assert( Index <= Vec_IntSize(p->vTruthFreqs) ); if ( Index < Vec_IntSize(p->vTruthFreqs) ) Vec_IntAddToEntry( p->vTruthFreqs, Index, 1 ); else Vec_IntPush( p->vTruthFreqs, 1 ); */ p->nAdded++; p->timeInsert += Abc_Clock() - clk; return 1; } // collect internal nodes and skip redundant cuts clk = Abc_Clock(); If_CutTraverse( pIfMan, pRoot, pCut, vNodes ); p->timeTruth += Abc_Clock() - clk; if ( Vec_PtrSize(vNodes) > 253 ) { p->nFilterSize++; return 1; } clk = Abc_Clock(); // map cut leaves into elementary variables of GIA for ( i = 0; i < nLeaves; i++ ) If_ManObj( pIfMan, pCut->pLeaves[(int)pCanonPerm[i]] )->iCopy = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManPi(pGia, i)), (uCanonPhase >> i) & 1 ); // build internal nodes fHole = 0; assert( Vec_PtrSize(vNodes) > 0 ); Vec_PtrForEachEntryStart( If_Obj_t *, vNodes, pIfObj, i, nLeaves ) { if ( If_ObjIsCi(pIfObj) ) { pIfObj->iCopy = 0; fHole = 1; continue; } iFanin0 = Abc_LitNotCond( If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj) ); iFanin1 = Abc_LitNotCond( If_ObjFanin1(pIfObj)->iCopy, If_ObjFaninC1(pIfObj) ); pIfObj->iCopy = Gia_ManHashAnd( pGia, iFanin0, iFanin1 ); } p->nHoleInTheWall += fHole; p->timeBuild += Abc_Clock() - clk; // check if this node is already driving a PO assert( If_ObjIsAnd(pIfObj) ); pDriver = Gia_ManObj(pGia, Abc_Lit2Var(pIfObj->iCopy)); if ( pDriver->fMark1 ) { p->nFilterSame++; return 1; } pDriver->fMark1 = 1; // create output Gia_ManAppendCo( pGia, Abc_LitNotCond( pIfObj->iCopy, (uCanonPhase >> nLeaves) & 1 ) ); // verify truth table clk = Abc_Clock(); pTruth = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, Gia_ManCoNum(pGia)-1) ); p->timeCheck += Abc_Clock() - clk; if ( memcmp( p->pTemp1, pTruth, p->nWords * sizeof(word) ) != 0 ) { /* Kit_DsdPrintFromTruth( pTruth, nLeaves ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)p->pTemp1, nLeaves ); printf( "\n" ); printf( "Truth table verification has failed.\n" ); */ // drive PO with constant Gia_ManPatchCoDriver( pGia, Gia_ManCoNum(pGia)-1, 0 ); // save truth table ID Vec_IntPush( p->vTruthIds, -1 ); p->nFilterTruth++; return 1; } clk = Abc_Clock(); // add the resulting truth table to the hash table Index = Vec_MemHashInsert( p->vTtMem, p->pTemp1 ); // save truth table ID Vec_IntPush( p->vTruthIds, Index ); assert( Gia_ManCoNum(pGia) == Vec_IntSize(p->vTruthIds) ); p->nAdded++; p->timeInsert += Abc_Clock() - clk; return 1; } /**Function************************************************************* Synopsis [Top level procedure for library construction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRecAdd3( Abc_Ntk_t * pNtk, int fUseSOPB ) { extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); If_Par_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtkNew; int clk = Abc_Clock(); if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Performing recoding structures with choices.\n" ); // remember that the manager was used for library construction s_pMan3->fLibConstr = 1; // create hash table if not available if ( s_pMan3->pGia && s_pMan3->pGia->pHTable == NULL ) Gia_ManHashStart( s_pMan3->pGia ); // set defaults memset( pPars, 0, sizeof(If_Par_t) ); // user-controlable paramters pPars->nLutSize = s_pMan3->nVars; pPars->nCutsMax = s_pMan3->nCuts; pPars->DelayTarget = -1; pPars->Epsilon = (float)0.005; pPars->fArea = 1; // internal parameters if ( fUseSOPB ) { pPars->fTruth = 1; pPars->fCutMin = 0; pPars->fUsePerm = 1; pPars->fDelayOpt = 1; } else { pPars->fTruth = 1; pPars->fCutMin = 1; pPars->fUsePerm = 0; pPars->fDelayOpt = 0; } pPars->fSkipCutFilter = 0; pPars->pFuncCost = NULL; pPars->pFuncUser = Abc_NtkRecAddCut3; // perform recording pNtkNew = Abc_NtkIf( pNtk, pPars ); Abc_NtkDelete( pNtkNew ); s_pMan3->timeTotal += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Returns min AIG level at the output fo the cut using the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_CutComputeDelay( If_Man_t * p, If_Cut_t * pCut, char * pCanonPerm, word DelayProfile ) { If_Obj_t* pLeaf; int nLeaves = If_CutLeaveNum(pCut); int i, delayTemp, delayMax = -ABC_INFINITY; for ( i = 0; i < nLeaves; i++ ) { pLeaf = If_ManObj(p, (pCut)->pLeaves[(int)pCanonPerm[i]]); delayTemp = If_ObjCutBest(pLeaf)->Delay + Lms_DelayGet(DelayProfile, i); delayMax = Abc_MaxInt( delayMax, delayTemp ); } return delayMax; } static inline int If_CutFindBestStruct( If_Man_t * pIfMan, If_Cut_t * pCut, char * pCanonPerm, unsigned * puCanonPhase, int * pBestPo ) { Lms_Man_t * p = s_pMan3; int i, * pTruthId, iFirstPo, iFirstPoNext, iBestPo; int BestDelay = ABC_INFINITY, BestArea = ABC_INFINITY, Delay, Area; int uSupport, nLeaves = If_CutLeaveNum( pCut ); char * pPerm = If_CutPerm( pCut ); word DelayProfile; abctime clk; pCut->fUser = 1; // compute support uSupport = Abc_TtSupport( If_CutTruthW(pIfMan, pCut), nLeaves ); if ( uSupport == 0 ) { pCut->Cost = 1; for ( i = 0; i < nLeaves; i++ ) pPerm[i] = IF_BIG_CHAR; return 0; } if ( !Abc_TtSuppIsMinBase(uSupport) || uSupport == 1 ) { assert( Abc_TtSuppOnlyOne(uSupport) ); pCut->Cost = 1; for ( i = 0; i < nLeaves; i++ ) pPerm[i] = IF_BIG_CHAR; pPerm[Abc_TtSuppFindFirst(uSupport)] = 0; return If_ObjCutBest(If_ManObj(pIfMan, pCut->pLeaves[Abc_TtSuppFindFirst(uSupport)]))->Delay; } assert( Gia_WordCountOnes(uSupport) == nLeaves ); // semicanonicize the function clk = Abc_Clock(); memcpy( p->pTemp1, If_CutTruthW(pIfMan, pCut), p->nWords * sizeof(word) ); #ifdef LMS_USE_OLD_FORM *puCanonPhase = Kit_TruthSemiCanonicize( (unsigned *)p->pTemp1, (unsigned *)p->pTemp2, nLeaves, pCanonPerm ); #else *puCanonPhase = Abc_TtCanonicize( p->pTemp1, nLeaves, pCanonPerm ); #endif Abc_TtStretch5( (unsigned *)p->pTemp1, nLeaves, p->nVars ); p->timeCanon += Abc_Clock() - clk; // get TT ID for the given class pTruthId = Vec_MemHashLookup( p->vTtMem, p->pTemp1 ); if ( *pTruthId == -1 ) { pCut->Cost = IF_COST_MAX; pCut->fUseless = 1; return ABC_INFINITY; } // note that array p->vTruthPo contains the first PO for the given truth table // other POs belonging to the same equivalence class follow immediately after this one // to iterate through the POs, we need to perform the following steps // find the first PO of this class iFirstPo = Vec_IntEntry( p->vTruthPo, *pTruthId ); // find the first PO of the next class iFirstPoNext = Vec_IntEntry( p->vTruthPo, *pTruthId+1 ); // iterate through the subgraphs of this class iBestPo = -1; for ( i = iFirstPo; i < iFirstPoNext; i++ ) { Delay = If_CutComputeDelay( pIfMan, pCut, pCanonPerm, Vec_WrdEntry(p->vDelays, i) ); Area = Vec_StrEntry(p->vAreas, i); if ( iBestPo == -1 || BestDelay > Delay || (BestDelay == Delay && BestArea > Area) ) { iBestPo = i; BestDelay = Delay; BestArea = Area; } } if ( pBestPo ) *pBestPo = iBestPo; // mark as user cut. DelayProfile = Vec_WrdEntry(p->vDelays, iBestPo); pCut->Cost = Vec_StrEntry(p->vAreas, iBestPo); for ( i = 0; i < nLeaves; i++ ) pPerm[(int)pCanonPerm[i]] = Lms_DelayGet(DelayProfile, i); if ( 0 ) { int Max = 0, Two = 0, pTimes[16]; for ( i = 0; i < nLeaves; i++ ) pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(pIfMan, pCut, i))->Delay; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) Max = Abc_MaxInt( Max, pTimes[i] ); for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) if ( pTimes[i] != Max ) Two = Abc_MaxInt( Two, pTimes[i] ); if ( Two + 2 < Max && Max + 3 < BestDelay ) { for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) printf( "%3d ", pTimes[i] ); for ( ; i < pIfMan->pPars->nLutSize; i++ ) printf( " " ); printf( "-> %3d ", BestDelay ); Dau_DsdPrintFromTruth( If_CutTruthW(pIfMan, pCut), If_CutLeaveNum(pCut) ); } } return BestDelay; } int If_CutDelayRecCost3( If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pObj ) { Lms_Man_t * p = s_pMan3; char pCanonPerm[LMS_VAR_MAX]; unsigned uCanonPhase; // make sure the cut functions match the library assert( p->nVars == (int)pCut->nLimit ); // if this assertion fires, it means that LMS manager was used for library construction // in this case, GIA has to be written out and the manager restarted as described above assert( !p->fLibConstr ); if ( p->vTruthPo == NULL ) Lms_ManPrepare( p ); // return the delay of the best structure return If_CutFindBestStruct( pIfMan, pCut, pCanonPerm, &uCanonPhase, NULL ); } /**Function************************************************************* Synopsis [Reexpresses the best structure of the cut in the HOP manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj ) { Lms_Man_t * p = s_pMan3; char pCanonPerm[LMS_VAR_MAX]; unsigned uCanonPhase; Hop_Obj_t * pFan0, * pFan1, * pHopObj; Gia_Man_t * pGia = p->pGia; Gia_Obj_t * pGiaPo, * pGiaTemp = NULL; int i, uSupport, BestPo = -1, nLeaves = If_CutLeaveNum(pCut); assert( pIfMan->pPars->fCutMin == 1 ); // compute support uSupport = Abc_TtSupport( If_CutTruthW(pIfMan, pCut), nLeaves ); if ( uSupport == 0 ) return Hop_NotCond( Hop_ManConst0(pMan), If_CutTruthIsCompl(pCut) ); if ( !Abc_TtSuppIsMinBase(uSupport) || uSupport == 1 ) { assert( Abc_TtSuppOnlyOne(uSupport) ); return Hop_NotCond( Hop_IthVar(pMan, Abc_TtSuppFindFirst(uSupport)), If_CutTruthIsCompl(pCut) ); } assert( Gia_WordCountOnes(uSupport) == nLeaves ); // get the best output for this node If_CutFindBestStruct( pIfMan, pCut, pCanonPerm, &uCanonPhase, &BestPo ); assert( BestPo >= 0 ); pGiaPo = Gia_ManCo( pGia, BestPo ); // collect internal nodes into pGia->vTtNodes if ( pGia->vTtNodes == NULL ) pGia->vTtNodes = Vec_IntAlloc( 256 ); assert( Gia_ObjIsAnd( Gia_ObjFanin0(pGiaPo) ) ); Gia_ObjCollectInternal( pGia, Gia_ObjFanin0(pGiaPo) ); assert( Vec_IntSize(pGia->vTtNodes) > 0 ); // collect HOP nodes for leaves Vec_PtrClear( p->vLabelsP ); for ( i = 0; i < nLeaves; i++ ) Vec_PtrPush( p->vLabelsP, Hop_NotCond(Hop_IthVar(pMan, pCanonPerm[i]), (uCanonPhase >> i) & 1) ); // compute HOP nodes for internal nodes Gia_ManForEachObjVec( pGia->vTtNodes, pGia, pGiaTemp, i ) { pGiaTemp->fMark0 = 0; // unmark node marked by Gia_ObjCollectInternal() if ( Gia_ObjIsAnd(Gia_ObjFanin0(pGiaTemp)) ) pFan0 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, Gia_ObjFanin0(pGiaTemp)) + nLeaves); else pFan0 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjCioId(Gia_ObjFanin0(pGiaTemp))); pFan0 = Hop_NotCond(pFan0, Gia_ObjFaninC0(pGiaTemp)); if ( Gia_ObjIsAnd(Gia_ObjFanin1(pGiaTemp)) ) pFan1 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, Gia_ObjFanin1(pGiaTemp)) + nLeaves); else pFan1 = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjCioId(Gia_ObjFanin1(pGiaTemp))); pFan1 = Hop_NotCond(pFan1, Gia_ObjFaninC1(pGiaTemp)); pHopObj = Hop_And(pMan, pFan0, pFan1); Vec_PtrPush(p->vLabelsP, pHopObj); } // get the final result assert( Gia_ObjIsAnd(pGiaTemp) ); pHopObj = (Hop_Obj_t *)Vec_PtrEntry(p->vLabelsP, Gia_ObjNum(pGia, pGiaTemp) + nLeaves); // complement the result if needed return Hop_NotCond( pHopObj, Gia_ObjFaninC0(pGiaPo) ^ ((uCanonPhase >> nLeaves) & 1) ); } /**Function************************************************************* Synopsis [Reexpresses the best structure of the cut in the GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_RecToGia3( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, int fHash ) { Lms_Man_t * p = s_pMan3; char pCanonPerm[LMS_VAR_MAX]; unsigned uCanonPhase; int iFan0, iFan1, iGiaObj; Gia_Man_t * pGia = p->pGia; Gia_Obj_t * pGiaPo, * pGiaTemp = NULL; int i, uSupport, BestPo = -1, nLeaves = If_CutLeaveNum(pCut); assert( pIfMan->pPars->fCutMin == 1 ); assert( nLeaves == Vec_IntSize(vLeaves) ); // compute support uSupport = Abc_TtSupport( If_CutTruthW(pIfMan, pCut), nLeaves ); if ( uSupport == 0 ) return Abc_LitNotCond( 0, If_CutTruthIsCompl(pCut) ); if ( !Abc_TtSuppIsMinBase(uSupport) || uSupport == 1 ) { assert( Abc_TtSuppOnlyOne(uSupport) ); return Abc_LitNotCond( Vec_IntEntry(vLeaves, Abc_TtSuppFindFirst(uSupport)), If_CutTruthIsCompl(pCut) ); } assert( Gia_WordCountOnes(uSupport) == nLeaves ); // get the best output for this node If_CutFindBestStruct( pIfMan, pCut, pCanonPerm, &uCanonPhase, &BestPo ); assert( BestPo >= 0 ); pGiaPo = Gia_ManCo( pGia, BestPo ); // collect internal nodes into pGia->vTtNodes if ( pGia->vTtNodes == NULL ) pGia->vTtNodes = Vec_IntAlloc( 256 ); assert( Gia_ObjIsAnd( Gia_ObjFanin0(pGiaPo) ) ); Gia_ObjCollectInternal( pGia, Gia_ObjFanin0(pGiaPo) ); assert( Vec_IntSize(pGia->vTtNodes) > 0 ); // collect GIA nodes for leaves Vec_IntClear( p->vLabels ); for (i = 0; i < nLeaves; i++) Vec_IntPush( p->vLabels, Abc_LitNotCond(Vec_IntEntry(vLeaves, pCanonPerm[i]), (uCanonPhase >> i) & 1) ); // compute HOP nodes for internal nodes Gia_ManForEachObjVec( pGia->vTtNodes, pGia, pGiaTemp, i ) { pGiaTemp->fMark0 = 0; // unmark node marked by Gia_ObjCollectInternal() if ( Gia_ObjIsAnd(Gia_ObjFanin0(pGiaTemp)) ) iFan0 = Vec_IntEntry(p->vLabels, Gia_ObjNum(pGia, Gia_ObjFanin0(pGiaTemp)) + nLeaves); else iFan0 = Vec_IntEntry(p->vLabels, Gia_ObjCioId(Gia_ObjFanin0(pGiaTemp))); iFan0 = Abc_LitNotCond(iFan0, Gia_ObjFaninC0(pGiaTemp)); if ( Gia_ObjIsAnd(Gia_ObjFanin1(pGiaTemp)) ) iFan1 = Vec_IntEntry(p->vLabels, Gia_ObjNum(pGia, Gia_ObjFanin1(pGiaTemp)) + nLeaves); else iFan1 = Vec_IntEntry(p->vLabels, Gia_ObjCioId(Gia_ObjFanin1(pGiaTemp))); iFan1 = Abc_LitNotCond(iFan1, Gia_ObjFaninC1(pGiaTemp)); if ( fHash ) iGiaObj = Gia_ManHashAnd(pMan, iFan0, iFan1); else iGiaObj = Gia_ManAppendAnd(pMan, iFan0, iFan1); Vec_IntPush(p->vLabels, iGiaObj); } // get the final result assert( Gia_ObjIsAnd(pGiaTemp) ); iGiaObj = Vec_IntEntry(p->vLabels, Gia_ObjNum(pGia, pGiaTemp) + nLeaves); // complement the result if needed return Abc_LitNotCond( iGiaObj, Gia_ObjFaninC0(pGiaPo) ^ ((uCanonPhase >> nLeaves) & 1) ^ pCut->fCompl ); } /**Function************************************************************* Synopsis [Reduces GIA to contain only useful COs and internal nodes.] Description [During library construction, redundant nodes are added. Some COs are found to be useless because their TT does not match the (semi-canonicized TT) of the cut, etc. This procedure reduces GIA to contains only useful (non-redundant, non-dominated) COs and the corresponding internal nodes. This procedure replaces GIA by a new GIA and creates new vTruthIds. The COs with the same truth table have adjacent IDs. This procedure does not change the truth tables.] SideEffects [] SeeAlso [] ***********************************************************************/ // count how many times TT occurs Vec_Int_t * Lms_GiaCountTruths( Lms_Man_t * p ) { Vec_Int_t * vCounts = Vec_IntStart( Vec_MemEntryNum(p->vTtMem) ); int i, Entry; Vec_IntForEachEntry( p->vTruthIds, Entry, i ) if ( Entry >= 0 ) Vec_IntAddToEntry( vCounts, Entry, 1 ); return vCounts; } // collect PO indexes worth visiting Vec_Int_t * Lms_GiaCollectUsefulCos( Lms_Man_t * p ) { Vec_Int_t * vBegins = Vec_IntAlloc( Vec_MemEntryNum(p->vTtMem) ); Vec_Int_t * vUseful = Vec_IntStartFull( Gia_ManCoNum(p->pGia) + Vec_MemEntryNum(p->vTtMem) ); Vec_Int_t * vCounts = Lms_GiaCountTruths( p ); int i, Entry, * pPlace, SumTotal = 0; // mark up the place for POs Vec_IntForEachEntry( vCounts, Entry, i ) { assert( Entry > 0 ); Vec_IntPush( vBegins, SumTotal ); SumTotal += Entry + 1; // printf( "%d ", Entry ); } Vec_IntPush( vBegins, SumTotal ); // fill out POs in their places Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 ); Vec_IntForEachEntry( p->vTruthIds, Entry, i ) { if ( Entry < 0 ) continue; pPlace = Vec_IntEntryP( vUseful, Vec_IntEntry(vBegins, Entry) + Vec_IntEntry(vCounts, Entry) ); assert( *pPlace == -1 ); *pPlace = i; Vec_IntAddToEntry( vCounts, Entry, 1 ); } Vec_IntFree( vBegins ); Vec_IntFree( vCounts ); return vUseful; } // collect non-dominated COs Vec_Int_t * Lms_GiaFindNonRedundantCos( Lms_Man_t * p ) { Vec_Int_t * vRemain; Vec_Int_t * vUseful; Vec_Wrd_t * vDelays; int i, k, EntryI, EntryK; word D1, D2; vDelays = Lms_GiaDelays( p->pGia ); vUseful = Lms_GiaCollectUsefulCos( p ); Vec_IntForEachEntry( vUseful, EntryI, i ) { if ( EntryI < 0 ) continue; D1 = Vec_WrdEntry(vDelays, EntryI); assert( D1 > 0 ); Vec_IntForEachEntryStart( vUseful, EntryK, k, i+1 ) { if ( EntryK == -1 ) break; if ( EntryK == -2 ) continue; D2 = Vec_WrdEntry(vDelays, EntryK); assert( D2 > 0 ); if ( Lms_DelayDom(D1, D2, Gia_ManCiNum(p->pGia)) ) // D1 dominate D2 { Vec_IntWriteEntry( vUseful, k, -2 ); continue; } if ( Lms_DelayDom(D2, D1, Gia_ManCiNum(p->pGia)) ) // D2 dominate D1 { Vec_IntWriteEntry( vUseful, i, -2 ); break; } } } vRemain = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( vUseful, EntryI, i ) if ( EntryI >= 0 ) Vec_IntPush( vRemain, EntryI ); Vec_IntFree( vUseful ); Vec_WrdFree( vDelays ); return vRemain; } // replace GIA and vTruthIds by filtered ones void Lms_GiaNormalize( Lms_Man_t * p ) { Gia_Man_t * pGiaNew; Gia_Obj_t * pObj; Vec_Int_t * vRemain; Vec_Int_t * vTruthIdsNew; int i, Entry, Prev = -1, Next; // collect non-redundant COs vRemain = Lms_GiaFindNonRedundantCos( p ); // change these to be useful literals vTruthIdsNew = Vec_IntAlloc( Vec_IntSize(vRemain) ); Vec_IntForEachEntry( vRemain, Entry, i ) { pObj = Gia_ManCo(p->pGia, Entry); assert( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ); Vec_IntWriteEntry( vRemain, i, Gia_ObjFaninLit0p(p->pGia, pObj) ); // create new truth IDs Next = Vec_IntEntry(p->vTruthIds, Gia_ObjCioId(pObj)); assert( Prev <= Next ); Vec_IntPush( vTruthIdsNew, Next ); Prev = Next; } // create a new GIA Gia_ManForEachObj( p->pGia, pObj, i ) assert( pObj->fMark0 == 0 ); for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) Gia_ManPatchCoDriver( p->pGia, i, 0 ); Vec_IntForEachEntry( vRemain, Entry, i ) Gia_ManAppendCo( p->pGia, Entry ); // pGiaNew = Gia_ManCleanup( p->pGia ); pGiaNew = Gia_ManCleanupOutputs( p->pGia, Gia_ManCoNum(p->pGia) - Vec_IntSize(vRemain) ); Gia_ManStop( p->pGia ); p->pGia = pGiaNew; Vec_IntFree( vRemain ); // update truth IDs Vec_IntFree( p->vTruthIds ); p->vTruthIds = vTruthIdsNew; // Vec_IntPrint( vTruthIdsNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRecTruthCompare( int * p1, int * p2 ) { int Diff = Vec_StrEntry( s_pMan3->vSupps, *p1 ) - Vec_StrEntry( s_pMan3->vSupps, *p2 ); if ( Diff ) return Diff; return memcmp( Vec_MemReadEntry(s_pMan3->vTtMem, *p1), Vec_MemReadEntry(s_pMan3->vTtMem, *p2), sizeof(word) * s_pMan3->nWords ); } void Abc_NtkRecDumpTt3( char * pFileName, int fBinary ) { FILE * pFile; char pBuffer[1000]; Lms_Man_t * p = s_pMan3; Vec_Int_t * vEntries; word * pTruth; int i, Entry, nVars = p->nVars; int nEntries = Vec_MemEntryNum(p->vTtMem); if ( nEntries == 0 ) { printf( "There is not truth tables.\n" ); return; } pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "The file cannot be opened.\n" ); return; } p->vSupps = Vec_StrAlloc( nEntries ); Vec_MemForEachEntry( p->vTtMem, pTruth, i ) Vec_StrPush( p->vSupps, (char)Abc_TtSupportSize(pTruth, nVars) ); vEntries = Vec_IntStartNatural( nEntries ); qsort( (void *)Vec_IntArray(vEntries), nEntries, sizeof(int), (int(*)(const void *,const void *))Abc_NtkRecTruthCompare ); Vec_StrFreeP( &p->vSupps ); // write the file Vec_IntForEachEntry( vEntries, Entry, i ) { pTruth = Vec_MemReadEntry(p->vTtMem, Entry); if ( fBinary ) { fwrite( pTruth, 1, sizeof(word) * p->nWords, pFile ); continue; } Extra_PrintHex( pFile, (unsigned *)pTruth, nVars ); fprintf( pFile, " " ); // Kit_DsdWriteFromTruth( pBuffer, (unsigned *)pTruth, nVars ); Dau_DsdDecompose( pTruth, p->nVars, 0, (int)(nVars <= 10), pBuffer ); fprintf( pFile, "%s\n", pBuffer ); } fclose( pFile ); Vec_IntFree( vEntries ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRecInputNum3() { return Gia_ManCiNum(s_pMan3->pGia); } int Abc_NtkRecIsRunning3() { return s_pMan3 != NULL; } Gia_Man_t * Abc_NtkRecGetGia3() { abctime clk = Abc_Clock(); printf( "Before normalizing: Library has %d classes and %d AIG subgraphs with %d AND nodes.\n", Vec_MemEntryNum(s_pMan3->vTtMem), Gia_ManPoNum(s_pMan3->pGia), Gia_ManAndNum(s_pMan3->pGia) ); Lms_GiaNormalize( s_pMan3 ); printf( "After normalizing: Library has %d classes and %d AIG subgraphs with %d AND nodes.\n", Vec_MemEntryNum(s_pMan3->vTtMem), Gia_ManPoNum(s_pMan3->pGia), Gia_ManAndNum(s_pMan3->pGia) ); Abc_PrintTime( 1, "Normalization runtime", Abc_Clock() - clk ); s_pMan3->fLibConstr = 0; return s_pMan3->pGia; } void Abc_NtkRecPs3(int fPrintLib) { Lms_ManPrint( s_pMan3 ); } void Abc_NtkRecStart3( Gia_Man_t * p, int nVars, int nCuts, int fFuncOnly, int fVerbose ) { assert( s_pMan3 == NULL ); s_pMan3 = Lms_ManStart( p, nVars, nCuts, fFuncOnly, fVerbose ); } void Abc_NtkRecStop3() { assert( s_pMan3 != NULL ); Lms_ManStop( s_pMan3 ); s_pMan3 = NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcReconv.c000066400000000000000000000611761300674244400237250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcReconv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Computation of reconvergence-driven cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcReconv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Abc_ManCut_t_ { // user specified parameters int nNodeSizeMax; // the limit on the size of the supernode int nConeSizeMax; // the limit on the size of the containing cone int nNodeFanStop; // the limit on the size of the supernode int nConeFanStop; // the limit on the size of the containing cone // internal parameters Vec_Ptr_t * vNodeLeaves; // fanins of the collapsed node (the cut) Vec_Ptr_t * vConeLeaves; // fanins of the containing cone Vec_Ptr_t * vVisited; // the visited nodes Vec_Vec_t * vLevels; // the data structure to compute TFO nodes Vec_Ptr_t * vNodesTfo; // the nodes in the TFO of the cut }; static int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ); static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ); static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Unmarks the TFI cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_NodesMark( Vec_Ptr_t * vVisited ) { Abc_Obj_t * pNode; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i ) pNode->fMarkA = 1; } /**Function************************************************************* Synopsis [Unmarks the TFI cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited ) { Abc_Obj_t * pNode; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i ) pNode->fMarkA = 0; } /**Function************************************************************* Synopsis [Unmarks the TFI cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited ) { Abc_Obj_t * pNode; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i ) pNode->fMarkB = 0; } /**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 Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit ) { int Cost; // make sure the node is in the construction zone assert( pNode->fMarkB == 1 ); // cannot expand over the PI node if ( Abc_ObjIsCi(pNode) ) return 999; // get the cost of the cone Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB); // always accept if the number of leaves does not increase if ( Cost < 2 ) return Cost; // skip nodes with many fanouts if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) return 999; // return the number of nodes that will be on the leaves if this node is removed return Cost; } /**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 Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit, Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 ) { Abc_Obj_t * pFanin0, * pFanin1, * pTemp; Abc_Obj_t * pGrand, * pGrandToAdd; // make sure the node is in the construction zone assert( pNode->fMarkB == 1 ); // cannot expand over the PI node if ( Abc_ObjIsCi(pNode) ) return 999; // skip nodes with many fanouts // if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) // return 999; // get the children pFanin0 = Abc_ObjFanin0(pNode); pFanin1 = Abc_ObjFanin1(pNode); assert( !pFanin0->fMarkB && !pFanin1->fMarkB ); // count the number of unique grandchildren that will be included // return infinite cost if this number if more than 1 if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) ) return 999; // consider the special case when a non-CI fanin can be dropped if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB ) { *ppLeafToAdd = pFanin1; *pNodeToMark1 = pFanin0; *pNodeToMark2 = NULL; return 1; } if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB ) { *ppLeafToAdd = pFanin0; *pNodeToMark1 = pFanin1; *pNodeToMark2 = NULL; return 1; } // make the first node CI if any if ( Abc_ObjIsCi(pFanin1) ) pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp; // consider the first node pGrandToAdd = NULL; if ( Abc_ObjIsCi(pFanin0) ) { *pNodeToMark1 = NULL; pGrandToAdd = pFanin0; } else { *pNodeToMark1 = pFanin0; pGrand = Abc_ObjFanin0(pFanin0); if ( !pGrand->fMarkB ) { if ( pGrandToAdd && pGrandToAdd != pGrand ) return 999; pGrandToAdd = pGrand; } pGrand = Abc_ObjFanin1(pFanin0); if ( !pGrand->fMarkB ) { if ( pGrandToAdd && pGrandToAdd != pGrand ) return 999; pGrandToAdd = pGrand; } } // consider the second node *pNodeToMark2 = pFanin1; pGrand = Abc_ObjFanin0(pFanin1); if ( !pGrand->fMarkB ) { if ( pGrandToAdd && pGrandToAdd != pGrand ) return 999; pGrandToAdd = pGrand; } pGrand = Abc_ObjFanin1(pFanin1); if ( !pGrand->fMarkB ) { if ( pGrandToAdd && pGrandToAdd != pGrand ) return 999; pGrandToAdd = pGrand; } assert( pGrandToAdd != NULL ); *ppLeafToAdd = pGrandToAdd; return 1; } /**Function************************************************************* Synopsis [Finds a fanin-limited, reconvergence-driven cut for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, int fContain ) { Abc_Obj_t * pNode; int i; assert( !Abc_ObjIsComplement(pRoot) ); assert( Abc_ObjIsNode(pRoot) ); // start the visited nodes and mark them Vec_PtrClear( p->vVisited ); Vec_PtrPush( p->vVisited, pRoot ); Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) ); Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) ); pRoot->fMarkB = 1; Abc_ObjFanin0(pRoot)->fMarkB = 1; Abc_ObjFanin1(pRoot)->fMarkB = 1; // start the cut Vec_PtrClear( p->vNodeLeaves ); Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) ); Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) ); // compute the cut while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) ); assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax ); // return if containing cut is not requested if ( !fContain ) { // unmark both fMarkA and fMarkB in tbe TFI Abc_NodesUnmarkB( p->vVisited ); return p->vNodeLeaves; } //printf( "\n\n\n" ); // compute the containing cut assert( p->nNodeSizeMax < p->nConeSizeMax ); // copy the current boundary Vec_PtrClear( p->vConeLeaves ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodeLeaves, pNode, i ) Vec_PtrPush( p->vConeLeaves, pNode ); // compute the containing cut while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) ); assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax ); // unmark TFI using fMarkA and fMarkB Abc_NodesUnmarkB( p->vVisited ); return p->vNodeLeaves; } /**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 Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ) { Abc_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( Abc_Obj_t *, vLeaves, pNode, i ) { CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit ); //printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur ); // if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level if ( CostBest > CostCur || (CostBest == CostCur && pNode->Level > pFaninBest->Level) ) { CostBest = CostCur; pFaninBest = pNode; } if ( CostBest == 0 ) break; } if ( pFaninBest == NULL ) return 0; // return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); assert( CostBest < 3 ); if ( vLeaves->nSize - 1 + CostBest > nSizeLimit ) return 0; // return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); assert( Abc_ObjIsNode(pFaninBest) ); // remove the node from the array Vec_PtrRemove( vLeaves, pFaninBest ); //printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) ); // add the left child to the fanins pNext = Abc_ObjFanin0(pFaninBest); if ( !pNext->fMarkB ) { //printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); pNext->fMarkB = 1; Vec_PtrPush( vLeaves, pNext ); Vec_PtrPush( vVisited, pNext ); } // add the right child to the fanins pNext = Abc_ObjFanin1(pFaninBest); if ( !pNext->fMarkB ) { //printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); pNext->fMarkB = 1; Vec_PtrPush( vLeaves, pNext ); Vec_PtrPush( vVisited, pNext ); } assert( vLeaves->nSize <= nSizeLimit ); // keep doing this return 1; } /**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 across two levels of fanins (this is why it is called a two-level construction procedure).] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ) { Abc_Obj_t * pNode = NULL, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2; int CostCur = 0, i; // find the best fanin Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i ) { CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 ); if ( CostCur < 2 ) break; } if ( CostCur > 2 ) return 0; // remove the node from the array Vec_PtrRemove( vLeaves, pNode ); // add the node to the leaves if ( pLeafToAdd ) { assert( !pLeafToAdd->fMarkB ); pLeafToAdd->fMarkB = 1; Vec_PtrPush( vLeaves, pLeafToAdd ); Vec_PtrPush( vVisited, pLeafToAdd ); } // mark the other nodes if ( pNodeToMark1 ) { assert( !pNodeToMark1->fMarkB ); pNodeToMark1->fMarkB = 1; Vec_PtrPush( vVisited, pNodeToMark1 ); } if ( pNodeToMark2 ) { assert( !pNodeToMark2->fMarkB ); pNodeToMark2->fMarkB = 1; Vec_PtrPush( vVisited, pNodeToMark2 ); } // keep doing this return 1; } /**Function************************************************************* Synopsis [Get the nodes contained in the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins ) { Abc_Obj_t * pTemp; int i; // mark the fanins of the cone Abc_NodesMark( vLeaves ); // collect the nodes in the DFS order Vec_PtrClear( vVisited ); // add the fanins if ( fIncludeFanins ) Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pTemp, i ) Vec_PtrPush( vVisited, pTemp ); // add other nodes for ( i = 0; i < nRoots; i++ ) Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited ); // unmark both sets Abc_NodesUnmark( vLeaves ); Abc_NodesUnmark( vVisited ); } /**Function************************************************************* Synopsis [Marks the TFI cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ) { if ( pNode->fMarkA == 1 ) return; // visit transitive fanin if ( Abc_ObjIsNode(pNode) ) { Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited ); Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited ); } assert( pNode->fMarkA == 0 ); pNode->fMarkA = 1; Vec_PtrPush( vVisited, pNode ); } #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Returns BDD representing the logic function of the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited ) { Abc_Obj_t * pNode; DdNode * bFunc0, * bFunc1, * bFunc = NULL; int i; // get the nodes in the cut without fanins in the DFS order Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 ); // set the elementary BDDs Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i ) pNode->pCopy = (Abc_Obj_t *)pbVars[i]; // compute the BDDs for the collected nodes Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i ) { assert( !Abc_ObjIsPi(pNode) ); bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ); bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ); bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); pNode->pCopy = (Abc_Obj_t *)bFunc; } assert(bFunc); Cudd_Ref( bFunc ); // dereference the intermediate ones Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i ) Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); Cudd_Deref( bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Returns BDD representing the transition relation of the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited ) { DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult; Abc_Obj_t * pNode; int i; // get the nodes in the cut without fanins in the DFS order Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 ); // set the elementary BDDs Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i ) pNode->pCopy = (Abc_Obj_t *)pbVarsX[i]; // compute the BDDs for the collected nodes Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i ) { bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ); bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ); bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); pNode->pCopy = (Abc_Obj_t *)bFunc; } // compute the transition relation of the cone bTrans = b1; Cudd_Ref( bTrans ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pNode, i ) { bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] ); Cudd_Ref( bFunc ); bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc ); Cudd_Ref( bTrans ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bFunc ); } // dereference the intermediate ones Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i ) Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); // compute don't-cares bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize ); Cudd_Ref( bCube ); bResult = Cudd_bddExistAbstract( dd, bTrans, bCube ); Cudd_Ref( bResult ); bResult = Cudd_Not( bResult ); Cudd_RecursiveDeref( dd, bCube ); Cudd_RecursiveDeref( dd, bTrans ); Cudd_Deref( bResult ); return bResult; } #endif /**Function************************************************************* Synopsis [Starts the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ) { Abc_ManCut_t * p; p = ABC_ALLOC( Abc_ManCut_t, 1 ); memset( p, 0, sizeof(Abc_ManCut_t) ); p->vNodeLeaves = Vec_PtrAlloc( 100 ); p->vConeLeaves = Vec_PtrAlloc( 100 ); p->vVisited = Vec_PtrAlloc( 100 ); p->vLevels = Vec_VecAlloc( 100 ); p->vNodesTfo = Vec_PtrAlloc( 100 ); p->nNodeSizeMax = nNodeSizeMax; p->nConeSizeMax = nConeSizeMax; p->nNodeFanStop = nNodeFanStop; p->nConeFanStop = nConeFanStop; return p; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkManCutStop( Abc_ManCut_t * p ) { Vec_PtrFree( p->vNodeLeaves ); Vec_PtrFree( p->vConeLeaves ); Vec_PtrFree( p->vVisited ); Vec_VecFree( p->vLevels ); Vec_PtrFree( p->vNodesTfo ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the leaves of the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ) { return p->vConeLeaves; } /**Function************************************************************* Synopsis [Returns the leaves of the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ) { return p->vNodeLeaves; } /**Function************************************************************* Synopsis [Returns the leaves of the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ) { return p->vVisited; } /**Function************************************************************* Synopsis [Collects the TFO of the cut in the topological order.] Description [TFO of the cut is defined as a set of nodes, for which the cut is a cut, that is, every path from the collected nodes to the CIs goes through a node in the cut. The nodes are collected if their level does not exceed the given number (LevelMax). The nodes are returned in the topological order. If the root node is given, its MFFC is marked, so that the collected nodes do not contain any nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax ) { Abc_Ntk_t * pNtk = pRoot->pNtk; Vec_Ptr_t * vVec; Abc_Obj_t * pNode, * pFanout; int i, k, v, LevelMin; assert( Abc_NtkIsStrash(pNtk) ); // assuming that the structure is clean Vec_VecForEachLevel( p->vLevels, vVec, i ) assert( vVec->nSize == 0 ); // put fanins into the structure while labeling them Abc_NtkIncrementTravId( pNtk ); LevelMin = -1; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i ) { if ( pNode->Level > (unsigned)LevelMax ) continue; Abc_NodeSetTravIdCurrent( pNode ); Vec_VecPush( p->vLevels, pNode->Level, pNode ); if ( LevelMin < (int)pNode->Level ) LevelMin = pNode->Level; } assert( LevelMin >= 0 ); // mark MFFC if ( pRoot ) Abc_NodeMffcLabelAig( pRoot ); // go through the levels up Vec_PtrClear( p->vNodesTfo ); Vec_VecForEachEntryStart( Abc_Obj_t *, p->vLevels, pNode, i, k, LevelMin ) { if ( i > LevelMax ) break; // if the node is not marked, it is not a fanin if ( !Abc_NodeIsTravIdCurrent(pNode) ) { // check if it belongs to the TFO if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) || !Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) ) continue; // save the node in the TFO and label it Vec_PtrPush( p->vNodesTfo, pNode ); Abc_NodeSetTravIdCurrent( pNode ); } // go through the fanouts and add them to the structure if they meet the conditions Abc_ObjForEachFanout( pNode, pFanout, v ) { // skip if fanout is a CO or its level exceeds if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax ) continue; // skip if it is already added or if it is in MFFC if ( Abc_NodeIsTravIdCurrent(pFanout) ) continue; // add it to the structure but do not mark it (until tested later) Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout ); } } // clear the levelized structure Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin ) { if ( i > LevelMax ) break; Vec_PtrClear( vVec ); } return p->vNodesTfo; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcRefactor.c000066400000000000000000000342051300674244400242270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcRefactor.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Resynthesis based on collapsing and refactoring.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcRefactor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "bool/dec/dec.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Abc_ManRef_t_ Abc_ManRef_t; struct Abc_ManRef_t_ { // user specified parameters int nNodeSizeMax; // the limit on the size of the supernode int nConeSizeMax; // the limit on the size of the containing cone int fVerbose; // the verbosity flag // internal data structures Vec_Ptr_t * vVars; // truth tables Vec_Ptr_t * vFuncs; // functions Vec_Int_t * vMemory; // memory Vec_Str_t * vCube; // temporary Vec_Int_t * vForm; // temporary Vec_Ptr_t * vVisited; // temporary Vec_Ptr_t * vLeaves; // temporary // node statistics int nLastGain; int nNodesConsidered; int nNodesRefactored; int nNodesGained; int nNodesBeg; int nNodesEnd; // runtime statistics abctime timeCut; abctime timeTru; abctime timeDcs; abctime timeSop; abctime timeFact; abctime timeEval; abctime timeRes; abctime timeNtk; abctime timeTotal; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns function of the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word * Abc_NodeConeTruth( Vec_Ptr_t * vVars, Vec_Ptr_t * vFuncs, int nWordsMax, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited ) { Abc_Obj_t * pNode; word * pTruth0, * pTruth1, * pTruth = NULL; int i, k, nWords = Abc_Truth6WordNum( Vec_PtrSize(vLeaves) ); // get nodes in the cut without fanins in the DFS order Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 ); // set elementary functions Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i ) pNode->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vVars, i ); // prepare functions for ( i = Vec_PtrSize(vFuncs); i < Vec_PtrSize(vVisited); i++ ) Vec_PtrPush( vFuncs, ABC_ALLOC(word, nWordsMax) ); // compute functions for the collected nodes Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i ) { assert( !Abc_ObjIsPi(pNode) ); pTruth0 = (word *)Abc_ObjFanin0(pNode)->pCopy; pTruth1 = (word *)Abc_ObjFanin1(pNode)->pCopy; pTruth = (word *)Vec_PtrEntry( vFuncs, i ); if ( Abc_ObjFaninC0(pNode) ) { if ( Abc_ObjFaninC1(pNode) ) for ( k = 0; k < nWords; k++ ) pTruth[k] = ~pTruth0[k] & ~pTruth1[k]; else for ( k = 0; k < nWords; k++ ) pTruth[k] = ~pTruth0[k] & pTruth1[k]; } else { if ( Abc_ObjFaninC1(pNode) ) for ( k = 0; k < nWords; k++ ) pTruth[k] = pTruth0[k] & ~pTruth1[k]; else for ( k = 0; k < nWords; k++ ) pTruth[k] = pTruth0[k] & pTruth1[k]; } pNode->pCopy = (Abc_Obj_t *)pTruth; } return pTruth; } int Abc_NodeConeIsConst0( word * pTruth, int nVars ) { int k, nWords = Abc_Truth6WordNum( nVars ); for ( k = 0; k < nWords; k++ ) if ( pTruth[k] ) return 0; return 1; } int Abc_NodeConeIsConst1( word * pTruth, int nVars ) { int k, nWords = Abc_Truth6WordNum( nVars ); for ( k = 0; k < nWords; k++ ) if ( ~pTruth[k] ) return 0; return 1; } /**Function************************************************************* Synopsis [Resynthesizes the node using refactoring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ) { extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); int fVeryVerbose = 0; int nVars = Vec_PtrSize(vFanins); int nWordsMax = Abc_Truth6WordNum(p->nNodeSizeMax); Dec_Graph_t * pFForm; Abc_Obj_t * pFanin; word * pTruth; abctime clk; int i, nNodesSaved, nNodesAdded, Required; p->nNodesConsidered++; Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; // get the function of the cut clk = Abc_Clock(); pTruth = Abc_NodeConeTruth( p->vVars, p->vFuncs, nWordsMax, pNode, vFanins, p->vVisited ); p->timeTru += Abc_Clock() - clk; if ( pTruth == NULL ) return NULL; // always accept the case of constant node if ( Abc_NodeConeIsConst0(pTruth, nVars) || Abc_NodeConeIsConst1(pTruth, nVars) ) { p->nLastGain = Abc_NodeMffcSize( pNode ); p->nNodesGained += p->nLastGain; p->nNodesRefactored++; return Abc_NodeConeIsConst0(pTruth, nVars) ? Dec_GraphCreateConst0() : Dec_GraphCreateConst1(); } // get the factored form clk = Abc_Clock(); pFForm = (Dec_Graph_t *)Kit_TruthToGraph( (unsigned *)pTruth, nVars, p->vMemory ); p->timeFact += Abc_Clock() - clk; // mark the fanin boundary // (can mark only essential fanins, belonging to bNodeFunc!) Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pFanin, i ) pFanin->vFanouts.nSize++; // label MFFC with current traversal ID Abc_NtkIncrementTravId( pNode->pNtk ); nNodesSaved = Abc_NodeMffcLabelAig( pNode ); // unmark the fanin boundary and set the fanins as leaves in the form Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pFanin, i ) { pFanin->vFanouts.nSize--; Dec_GraphNode(pFForm, i)->pFunc = pFanin; } // detect how many new nodes will be added (while taking into account reused nodes) clk = Abc_Clock(); nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required ); p->timeEval += Abc_Clock() - clk; // quit if there is no improvement if ( nNodesAdded == -1 || (nNodesAdded == nNodesSaved && !fUseZeros) ) { Dec_GraphFree( pFForm ); return NULL; } // compute the total gain in the number of nodes p->nLastGain = nNodesSaved - nNodesAdded; p->nNodesGained += p->nLastGain; p->nNodesRefactored++; // report the progress if ( fVeryVerbose ) { printf( "Node %6s : ", Abc_ObjName(pNode) ); printf( "Cone = %2d. ", vFanins->nSize ); printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pFForm) ); printf( "MFFC = %2d. ", nNodesSaved ); printf( "Add = %2d. ", nNodesAdded ); printf( "GAIN = %2d. ", p->nLastGain ); printf( "\n" ); } return pFForm; } /**Function************************************************************* Synopsis [Starts the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, int fUseDcs, int fVerbose ) { Abc_ManRef_t * p; p = ABC_ALLOC( Abc_ManRef_t, 1 ); memset( p, 0, sizeof(Abc_ManRef_t) ); p->vCube = Vec_StrAlloc( 100 ); p->vVisited = Vec_PtrAlloc( 100 ); p->nNodeSizeMax = nNodeSizeMax; p->nConeSizeMax = nConeSizeMax; p->fVerbose = fVerbose; p->vVars = Vec_PtrAllocTruthTables( Abc_MaxInt(nNodeSizeMax, 6) ); p->vFuncs = Vec_PtrAlloc( 100 ); p->vMemory = Vec_IntAlloc( 1 << 16 ); return p; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkManRefStop( Abc_ManRef_t * p ) { Vec_PtrFreeFree( p->vFuncs ); Vec_PtrFree( p->vVars ); Vec_IntFree( p->vMemory ); Vec_PtrFree( p->vVisited ); Vec_StrFree( p->vCube ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkManRefPrintStats( Abc_ManRef_t * p ) { printf( "Refactoring statistics:\n" ); printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); printf( "Nodes refactored = %8d.\n", p->nNodesRefactored ); printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); ABC_PRT( "Cuts ", p->timeCut ); ABC_PRT( "Resynthesis", p->timeRes ); ABC_PRT( " BDD ", p->timeTru ); ABC_PRT( " DCs ", p->timeDcs ); ABC_PRT( " SOP ", p->timeSop ); ABC_PRT( " FF ", p->timeFact ); ABC_PRT( " Eval ", p->timeEval ); ABC_PRT( "AIG update ", p->timeNtk ); ABC_PRT( "TOTAL ", p->timeTotal ); } /**Function************************************************************* Synopsis [Performs incremental resynthesis of the AIG.] Description [Starting from each node, computes a reconvergence-driven cut, derives BDD of the cut function, constructs ISOP, factors the ISOP, and replaces the current implementation of the MFFC of the node by the new factored form, if the number of AIG nodes is reduced and the total number of levels of the AIG network is not increated. Returns the number of AIG nodes saved.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ) { extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); ProgressBar * pProgress; Abc_ManRef_t * pManRef; Abc_ManCut_t * pManCut; Dec_Graph_t * pFForm; Vec_Ptr_t * vFanins; Abc_Obj_t * pNode; abctime clk, clkStart = Abc_Clock(); int i, nNodes; assert( Abc_NtkIsStrash(pNtk) ); // cleanup the AIG Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); // start the managers pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 ); pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose ); pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCut ); // compute the reverse levels if level update is requested if ( fUpdateLevel ) Abc_NtkStartReverseLevels( pNtk, 0 ); // resynthesize each node once pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // skip the constant node // if ( Abc_NodeIsConst(pNode) ) // continue; // skip persistant nodes if ( Abc_NodeIsPersistant(pNode) ) continue; // skip the nodes with many fanouts if ( Abc_ObjFanoutNum(pNode) > 1000 ) continue; // stop if all nodes have been tried once if ( i >= nNodes ) break; // compute a reconvergence-driven cut clk = Abc_Clock(); vFanins = Abc_NodeFindCut( pManCut, pNode, fUseDcs ); pManRef->timeCut += Abc_Clock() - clk; // evaluate this cut clk = Abc_Clock(); pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); pManRef->timeRes += Abc_Clock() - clk; if ( pFForm == NULL ) continue; // acceptable replacement found, update the graph clk = Abc_Clock(); Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRef->nLastGain ); pManRef->timeNtk += Abc_Clock() - clk; Dec_GraphFree( pFForm ); } Extra_ProgressBarStop( pProgress ); pManRef->timeTotal = Abc_Clock() - clkStart; pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk); // print statistics of the manager if ( fVerbose ) Abc_NtkManRefPrintStats( pManRef ); // delete the managers Abc_NtkManCutStop( pManCut ); Abc_NtkManRefStop( pManRef ); // put the nodes into the DFS order and reassign their IDs Abc_NtkReassignIds( pNtk ); // Abc_AigCheckFaninOrder( pNtk->pManFunc ); // fix the levels if ( fUpdateLevel ) Abc_NtkStopReverseLevels( pNtk ); else Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkRefactor: The network check has failed.\n" ); return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcRenode.c000066400000000000000000000240771300674244400237040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcRenode.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: abcRenode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "map/if/if.h" #include "bool/kit/kit.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #include "bdd/reo/reo.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD static int Abc_NtkRenodeEvalAig( If_Man_t * p, If_Cut_t * pCut ); static int Abc_NtkRenodeEvalBdd( If_Man_t * p, If_Cut_t * pCut ); static int Abc_NtkRenodeEvalSop( If_Man_t * p, If_Cut_t * pCut ); static int Abc_NtkRenodeEvalCnf( If_Man_t * p, If_Cut_t * pCut ); static int Abc_NtkRenodeEvalMv( If_Man_t * p, If_Cut_t * pCut ); static reo_man * s_pReo = NULL; static DdManager * s_pDd = NULL; static Vec_Int_t * s_vMemory = NULL; static Vec_Int_t * s_vMemory2 = NULL; static int nDsdCounter = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs renoding as technology mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ) { extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); If_Par_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtkNew; if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Performing renoding with choices.\n" ); nDsdCounter = 0; // set defaults memset( pPars, 0, sizeof(If_Par_t) ); // user-controlable paramters pPars->nLutSize = nFaninMax; pPars->nCutsMax = nCubeMax; pPars->nFlowIters = nFlowIters; pPars->nAreaIters = nAreaIters; pPars->DelayTarget = -1; pPars->Epsilon = (float)0.005; pPars->fPreprocess = 1; pPars->fArea = fArea; pPars->fFancy = 0; pPars->fExpRed = 0; // pPars->fLatchPaths = 0; pPars->fVerbose = fVerbose; // internal parameters pPars->fTruth = 1; pPars->fUsePerm = 1; pPars->nLatchesCi = 0; pPars->nLatchesCo = 0; pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); pPars->pTimesArr = NULL; pPars->pTimesArr = NULL; pPars->fUseBdds = fUseBdds; pPars->fUseSops = fUseSops; pPars->fUseCnfs = fUseCnfs; pPars->fUseMv = fUseMv; if ( fUseBdds ) pPars->pFuncCost = Abc_NtkRenodeEvalBdd; else if ( fUseSops ) pPars->pFuncCost = Abc_NtkRenodeEvalSop; else if ( fUseCnfs ) { pPars->fArea = 1; pPars->pFuncCost = Abc_NtkRenodeEvalCnf; } else if ( fUseMv ) pPars->pFuncCost = Abc_NtkRenodeEvalMv; else pPars->pFuncCost = Abc_NtkRenodeEvalAig; // start the manager if ( fUseBdds ) { assert( s_pReo == NULL ); s_pDd = Cudd_Init( nFaninMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); s_pReo = Extra_ReorderInit( nFaninMax, 100 ); pPars->pReoMan = s_pReo; } else { assert( s_vMemory == NULL ); s_vMemory = Vec_IntAlloc( 1 << 16 ); s_vMemory2 = Vec_IntAlloc( 1 << 16 ); } // perform mapping/renoding pNtkNew = Abc_NtkIf( pNtk, pPars ); // start the manager if ( fUseBdds ) { Extra_StopManager( s_pDd ); Extra_ReorderQuit( s_pReo ); s_pReo = NULL; s_pDd = NULL; } else { Vec_IntFree( s_vMemory ); Vec_IntFree( s_vMemory2 ); s_vMemory = NULL; s_vMemory2 = NULL; } // printf( "Decomposed %d functions.\n", nDsdCounter ); return pNtkNew; } /**Function************************************************************* Synopsis [Computes the cost based on the factored form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRenodeEvalAig( If_Man_t * p, If_Cut_t * pCut ) { char * pPerm = If_CutPerm( pCut ); Kit_Graph_t * pGraph; int i, nNodes; pGraph = Kit_TruthToGraph( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory ); if ( pGraph == NULL ) { for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pPerm[i] = 100; return IF_COST_MAX; } nNodes = Kit_GraphNodeNum( pGraph ); for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) ); Kit_GraphFree( pGraph ); return nNodes; } /**Function************************************************************* Synopsis [Computes the cost based on the BDD size after reordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRenodeEvalBdd( If_Man_t * p, If_Cut_t * pCut ) { char * pPerm = If_CutPerm( pCut ); int pOrder[IF_MAX_LUTSIZE]; DdNode * bFunc, * bFuncNew; int i, k, nNodes; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pPerm[i] = pOrder[i] = -100; bFunc = Kit_TruthToBdd( s_pDd, If_CutTruth(p, pCut), If_CutLeaveNum(pCut), 0 ); Cudd_Ref( bFunc ); bFuncNew = Extra_Reorder( s_pReo, s_pDd, bFunc, pOrder ); Cudd_Ref( bFuncNew ); for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ ) if ( pOrder[i] >= 0 ) pPerm[pOrder[i]] = ++k; // double-check this! nNodes = -1 + Cudd_DagSize( bFuncNew ); Cudd_RecursiveDeref( s_pDd, bFuncNew ); Cudd_RecursiveDeref( s_pDd, bFunc ); return nNodes; } /**Function************************************************************* Synopsis [Computes the cost based on ISOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRenodeEvalSop( If_Man_t * p, If_Cut_t * pCut ) { char * pPerm = If_CutPerm( pCut ); int i, RetValue; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pPerm[i] = 1; RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory, 1 ); if ( RetValue == -1 ) return IF_COST_MAX; assert( RetValue == 0 || RetValue == 1 ); return Vec_IntSize( s_vMemory ); } /**Function************************************************************* Synopsis [Computes the cost based on two ISOPs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRenodeEvalCnf( If_Man_t * p, If_Cut_t * pCut ) { char * pPerm = If_CutPerm( pCut ); int i, RetValue, nClauses; // set internal mapper parameters for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pPerm[i] = 1; // compute ISOP for the positive phase RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); if ( RetValue == -1 ) return IF_COST_MAX; assert( RetValue == 0 || RetValue == 1 ); nClauses = Vec_IntSize( s_vMemory ); // compute ISOP for the negative phase Kit_TruthNot( If_CutTruth(p, pCut), If_CutTruth(p, pCut), If_CutLeaveNum(pCut) ); RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); Kit_TruthNot( If_CutTruth(p, pCut), If_CutTruth(p, pCut), If_CutLeaveNum(pCut) ); if ( RetValue == -1 ) return IF_COST_MAX; assert( RetValue == 0 || RetValue == 1 ); nClauses += Vec_IntSize( s_vMemory ); return nClauses; } /**Function************************************************************* Synopsis [Computes the cost of MV-SOP of the cut function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRenodeEvalMv( If_Man_t * p, If_Cut_t * pCut ) { char * pPerm = If_CutPerm( pCut ); int i, RetValue; // set internal mapper parameters for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pPerm[i] = 1; // compute ISOP for the positive phase RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); if ( RetValue == -1 ) return IF_COST_MAX; assert( RetValue == 0 || RetValue == 1 ); // compute ISOP for the negative phase Kit_TruthNot( If_CutTruth(p, pCut), If_CutTruth(p, pCut), If_CutLeaveNum(pCut) ); RetValue = Kit_TruthIsop( If_CutTruth(p, pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 ); Kit_TruthNot( If_CutTruth(p, pCut), If_CutTruth(p, pCut), If_CutLeaveNum(pCut) ); if ( RetValue == -1 ) return IF_COST_MAX; assert( RetValue == 0 || RetValue == 1 ); // return the cost of the cut RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 ); if ( RetValue >= IF_COST_MAX ) return IF_COST_MAX; return RetValue; } #else Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ) { return NULL; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcReorder.c000066400000000000000000000067331300674244400240710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcReorder.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Reordering local BDDs of the nodes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcReorder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/reo/reo.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Reorders BDD of the local function of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; DdNode * bFunc; int * pOrder, i; // create the temporary array for the variable order pOrder = ABC_ALLOC( int, Abc_ObjFaninNum(pNode) ); for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) pOrder[i] = -1; // reorder the BDD bFunc = Extra_Reorder( p, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, pOrder ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData ); pNode->pData = bFunc; // update the fanin order Abc_ObjForEachFanin( pNode, pFanin, i ) pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ]; Abc_ObjForEachFanin( pNode, pFanin, i ) pNode->vFanins.pArray[i] = pOrder[i]; ABC_FREE( pOrder ); } /**Function************************************************************* Synopsis [Reorders BDDs of the local functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ) { reo_man * p; Abc_Obj_t * pNode; int i; Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjFaninNum(pNode) < 3 ) continue; if ( fVerbose ) fprintf( stdout, "%10s: ", Abc_ObjName(pNode) ); if ( fVerbose ) fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize((DdNode *)pNode->pData) ); Abc_NodeBddReorder( p, pNode ); if ( fVerbose ) fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize((DdNode *)pNode->pData) ); } Extra_ReorderQuit( p ); } #else void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ) {} #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcRestruct.c000066400000000000000000001461221300674244400242770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcRestruct.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: abcRestruct.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "bool/dec/dec.h" #include "opt/cut/cut.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 #define RST_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) typedef struct Abc_ManRst_t_ Abc_ManRst_t; struct Abc_ManRst_t_ { // the network Abc_Ntk_t * pNtk; // the network for restructuring // user specified parameters int nCutMax; // the limit on the size of the supernode int fUpdateLevel; // turns on watching the number of levels int fUseZeros; // turns on zero-cost replacements int fVerbose; // the verbosity flag // internal data structures DdManager * dd; // the BDD manager Dsd_Manager_t * pManDsd; // the DSD manager Vec_Ptr_t * vVisited; // temporary Vec_Ptr_t * vLeaves; // temporary Vec_Ptr_t * vDecs; // temporary Vec_Ptr_t * vTemp; // temporary Vec_Int_t * vSims; // temporary Vec_Int_t * vRands; // temporary Vec_Int_t * vOnes; // temporary Vec_Int_t * vBinate; // temporary Vec_Int_t * vTwos; // temporary // node statistics int nLastGain; int nCutsConsidered; int nCutsExplored; int nNodesConsidered; int nNodesRestructured; int nNodesGained; // runtime statistics int timeCut; int timeBdd; int timeDsd; int timeEval; int timeRes; int timeNtk; int timeTotal; }; static Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ); static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ); static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut ); static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ); static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ); static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, int fUpdateLevel, int fUseZeros, int fVerbose ); static void Abc_NtkManRstStop( Abc_ManRst_t * p ); static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Implements AIG restructuring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, int fUpdateLevel, int fUseZeros, int fVerbose ) { extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); ProgressBar * pProgress; Abc_ManRst_t * pManRst; Cut_Man_t * pManCut; Cut_Cut_t * pCutList; Dec_Graph_t * pGraph; Abc_Obj_t * pNode; abctime clk, clkStart = Abc_Clock(); int fMulti = 1; int fResub = 0; int i, nNodes; assert( Abc_NtkIsStrash(pNtk) ); // cleanup the AIG Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); Abc_NtkCleanCopy(pNtk); // compute the reverse levels if level update is requested if ( fUpdateLevel ) Abc_NtkStartReverseLevels( pNtk, 0 ); // start the restructuring manager pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose ); pManRst->pNtk = pNtk; // start the cut manager clk = Abc_Clock(); pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti ); pManRst->timeCut += Abc_Clock() - clk; // pNtk->pManCut = pManCut; // resynthesize each node once nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // skip the constant node // if ( Abc_NodeIsConst(pNode) ) // continue; // skip persistant nodes if ( Abc_NodeIsPersistant(pNode) ) continue; // skip the node if it is inside the tree // if ( Abc_ObjFanoutNum(pNode) < 2 ) // continue; // skip the nodes with too many fanouts if ( Abc_ObjFanoutNum(pNode) > 1000 ) continue; // stop if all nodes have been tried once if ( i >= nNodes ) break; // get the cuts for the given node clk = Abc_Clock(); pCutList = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti, 0 ); pManRst->timeCut += Abc_Clock() - clk; // perform restructuring clk = Abc_Clock(); if ( fResub ) pGraph = Abc_NodeResubstitute( pManRst, pNode, pCutList ); else pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList ); pManRst->timeRes += Abc_Clock() - clk; if ( pGraph == NULL ) continue; // acceptable replacement found, update the graph clk = Abc_Clock(); Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain ); pManRst->timeNtk += Abc_Clock() - clk; Dec_GraphFree( pGraph ); } Extra_ProgressBarStop( pProgress ); pManRst->timeTotal = Abc_Clock() - clkStart; // print statistics of the manager // if ( fVerbose ) Abc_NtkManRstPrintStats( pManRst ); // delete the managers Cut_ManStop( pManCut ); Abc_NtkManRstStop( pManRst ); // put the nodes into the DFS order and reassign their IDs Abc_NtkReassignIds( pNtk ); // Abc_AigCheckFaninOrder( pNtk->pManFunc ); // fix the levels if ( fUpdateLevel ) Abc_NtkStopReverseLevels( pNtk ); else Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkRefactor: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot, int nNodesSaved ) { Abc_Obj_t * pNode, * pFanout;//, * pFanin; int i, k; // start with the leaves Vec_PtrClear( p->vDecs ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pNode, i ) { Vec_PtrPush( p->vDecs, pNode ); assert( pNode->fMarkC == 0 ); pNode->fMarkC = 1; } // explore the fanouts Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pNode, i ) { // if the fanout has both fanins in the set, add it Abc_ObjForEachFanout( pNode, pFanout, k ) { if ( pFanout->fMarkC || Abc_ObjIsPo(pFanout) ) continue; if ( Abc_ObjFanin0(pFanout)->fMarkC && Abc_ObjFanin1(pFanout)->fMarkC ) { Vec_PtrPush( p->vDecs, pFanout ); pFanout->fMarkC = 1; } } } // unmark the nodes Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pNode, i ) pNode->fMarkC = 0; /* // print the nodes Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) ) { printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " ); // find the first fanin Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pFanin, k ) if ( Abc_ObjFanin0(pNode) == pFanin ) break; if ( k < Vec_PtrSize(p->vLeaves) ) printf( "%c", 'a' + k ); else printf( "%d", k ); printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); // find the second fanin Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pFanin, k ) if ( Abc_ObjFanin1(pNode) == pFanin ) break; if ( k < Vec_PtrSize(p->vLeaves) ) printf( "%c", 'a' + k ); else printf( "%d", k ); printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); printf( "\n" ); } */ printf( "%d\n", Vec_PtrSize(p->vDecs)-nNodesSaved-Vec_PtrSize(p->vLeaves) ); } /**Function************************************************************* Synopsis [Starts the cut manager for rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ) { Dec_Graph_t * pGraph; Cut_Cut_t * pCut; // int nCuts; p->nNodesConsidered++; /* // count the number of cuts with four inputs or more nCuts = 0; for ( pCut = pCutList; pCut; pCut = pCut->pNext ) nCuts += (int)(pCut->nLeaves > 3); printf( "-----------------------------------\n" ); printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts ); */ // go through the interesting cuts for ( pCut = pCutList; pCut; pCut = pCut->pNext ) { if ( pCut->nLeaves < 4 ) continue; if ( (pGraph = Abc_NodeRestructureCut( p, pNode, pCut )) ) return pGraph; } return NULL; } /**Function************************************************************* Synopsis [Starts the cut manager for rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) { extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited ); Dec_Graph_t * pGraph; Dsd_Node_t * pNodeDsd; Abc_Obj_t * pLeaf; DdNode * bFunc; int nNodesSaved, nNodesAdded; int Required, nMaxSize, clk, i; int fVeryVerbose = 0; p->nCutsConsidered++; // get the required time for the node Required = p->fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY; // collect the leaves of the cut Vec_PtrClear( p->vLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pLeaf = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]); if ( pLeaf == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes return NULL; Vec_PtrPush( p->vLeaves, pLeaf ); } clk = Abc_Clock(); // collect the internal nodes of the cut // Abc_NodeConeCollect( &pRoot, 1, p->vLeaves, p->vVisited, 0 ); // derive the BDD of the cut bFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pRoot, p->vLeaves, p->vVisited ); Cudd_Ref( bFunc ); p->timeBdd += Abc_Clock() - clk; // consider the special case, when the function is a constant if ( Cudd_IsConstant(bFunc) ) { p->nLastGain = Abc_NodeMffcSize( pRoot ); p->nNodesGained += p->nLastGain; p->nNodesRestructured++; Cudd_RecursiveDeref( p->dd, bFunc ); if ( Cudd_IsComplement(bFunc) ) return Dec_GraphCreateConst0(); return Dec_GraphCreateConst1(); } clk = Abc_Clock(); // try disjoint support decomposition pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc ); p->timeDsd += Abc_Clock() - clk; // skip nodes with non-decomposable blocks Dsd_TreeNodeGetInfoOne( pNodeDsd, NULL, &nMaxSize ); if ( nMaxSize > 3 ) { Cudd_RecursiveDeref( p->dd, bFunc ); return NULL; } /* // skip nodes that cannot be improved if ( Vec_PtrSize(p->vVisited) <= Dsd_TreeGetAigCost(pNodeDsd) ) { Cudd_RecursiveDeref( p->dd, bFunc ); return NULL; } */ p->nCutsExplored++; // mark the fanin boundary // (can mark only essential fanins, belonging to bNodeFunc!) Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pLeaf, i ) pLeaf->vFanouts.nSize++; // label MFFC with current traversal ID Abc_NtkIncrementTravId( pRoot->pNtk ); nNodesSaved = Abc_NodeMffcLabelAig( pRoot ); // unmark the fanin boundary and set the fanins as leaves in the form Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pLeaf, i ) pLeaf->vFanouts.nSize--; /* if ( nNodesSaved < 3 ) { Cudd_RecursiveDeref( p->dd, bFunc ); return NULL; } */ /* printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d.\n", pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), nNodesSaved ); Dsd_NodePrint( stdout, pNodeDsd ); Abc_RestructNodeDivisors( p, pRoot ); if ( pRoot->Id == 433 ) { int x = 0; } */ // Abc_RestructNodeDivisors( p, pRoot, nNodesSaved ); // detect how many new nodes will be added (while taking into account reused nodes) clk = Abc_Clock(); if ( nMaxSize > 3 ) pGraph = NULL; else pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded ); // pGraph = NULL; p->timeEval += Abc_Clock() - clk; // quit if there is no improvement if ( pGraph == NULL || nNodesAdded == -1 || (nNodesAdded == nNodesSaved && !p->fUseZeros) ) { Cudd_RecursiveDeref( p->dd, bFunc ); if ( pGraph ) Dec_GraphFree( pGraph ); return NULL; } /* // print stats printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d. New MFFC = %2d. Gain = %d.\n", pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), nNodesSaved, nNodesAdded, (nNodesAdded == -1)? 0 : nNodesSaved-nNodesAdded ); // Dsd_NodePrint( stdout, pNodeDsd ); // Dec_GraphPrint( stdout, pGraph, NULL, NULL ); */ // compute the total gain in the number of nodes p->nLastGain = nNodesSaved - nNodesAdded; p->nNodesGained += p->nLastGain; p->nNodesRestructured++; // report the progress if ( fVeryVerbose ) { printf( "Node %6s : ", Abc_ObjName(pRoot) ); printf( "Cone = %2d. ", p->vLeaves->nSize ); printf( "BDD = %2d. ", Cudd_DagSize(bFunc) ); printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pGraph) ); printf( "MFFC = %2d. ", nNodesSaved ); printf( "Add = %2d. ", nNodesAdded ); printf( "GAIN = %2d. ", p->nLastGain ); printf( "\n" ); } Cudd_RecursiveDeref( p->dd, bFunc ); return pGraph; } /**Function************************************************************* Synopsis [Moves closer to the end the node that is best for sharing.] Description [If the flag is set, tries to find an EXOR, otherwise, tries to find an OR.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeEdgeDsdPermute( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Vec_Int_t * vEdges, int fExor ) { Dec_Edge_t eNode1, eNode2, eNode3; Abc_Obj_t * pNode1, * pNode2, * pNode3, * pTemp; int LeftBound = 0, RightBound, i; // get the right bound RightBound = Vec_IntSize(vEdges) - 2; assert( LeftBound <= RightBound ); if ( LeftBound == RightBound ) return; // get the two last nodes eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound + 1) ); eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound ) ); pNode1 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode1.Node )->pFunc; pNode2 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode2.Node )->pFunc; pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); // quit if the last node does not exist if ( pNode1 == NULL ) return; // find the first node that can be shared for ( i = RightBound; i >= LeftBound; i-- ) { // get the third node eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, i) ); pNode3 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode3.Node )->pFunc; pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl ); if ( pNode3 == NULL ) continue; // check if the node exists if ( fExor ) { if ( pNode1 && pNode3 ) { pTemp = Abc_AigXorLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode3, NULL ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) continue; if ( pNode3 == pNode2 ) return; Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) ); Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) ); return; } } else { if ( pNode1 && pNode3 ) { pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) continue; if ( eNode3.Node == eNode2.Node ) return; Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) ); Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) ); return; } } } } /**Function************************************************************* Synopsis [Adds the new edge in the given order.] Description [Similar to Vec_IntPushOrder, except in decreasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeEdgeDsdPushOrdered( Dec_Graph_t * pGraph, Vec_Int_t * vEdges, int Edge ) { int i, NodeOld, NodeNew; vEdges->nSize++; for ( i = vEdges->nSize-2; i >= 0; i-- ) { NodeOld = Dec_IntToEdge(vEdges->pArray[i]).Node; NodeNew = Dec_IntToEdge(Edge).Node; // use <= because we are trying to push the new (non-existent) nodes as far as possible if ( Dec_GraphNode(pGraph, NodeOld)->Level <= Dec_GraphNode(pGraph, NodeNew)->Level ) vEdges->pArray[i+1] = vEdges->pArray[i]; else break; } vEdges->pArray[i+1] = Edge; } /**Function************************************************************* Synopsis [Evaluation one DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, int Required, int nNodesSaved, int * pnNodesAdded ) { Dec_Edge_t eNode1, eNode2, eNode3, eResult, eQuit = { 0, 2006 }; Abc_Obj_t * pNode1, * pNode2, * pNode3, * pNode4, * pTemp; Dsd_Node_t * pChildDsd; Dsd_Type_t DecType; Vec_Int_t * vEdges; int Level1, Level2, Level3, Level4; int i, Index, fCompl, Type; // remove the complemented attribute fCompl = Dsd_IsComplement( pNodeDsd ); pNodeDsd = Dsd_Regular( pNodeDsd ); // consider the trivial case DecType = Dsd_NodeReadType( pNodeDsd ); if ( DecType == DSD_NODE_BUF ) { Index = Dsd_NodeReadFunc(pNodeDsd)->index; assert( Index < Dec_GraphLeaveNum(pGraph) ); eResult = Dec_EdgeCreate( Index, fCompl ); return eResult; } assert( DecType == DSD_NODE_OR || DecType == DSD_NODE_EXOR || DecType == DSD_NODE_PRIME ); // solve the problem for the children vEdges = Vec_IntAlloc( Dsd_NodeReadDecsNum(pNodeDsd) ); Dsd_NodeForEachChild( pNodeDsd, i, pChildDsd ) { eResult = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pChildDsd, Required, nNodesSaved, pnNodesAdded ); if ( eResult.Node == eQuit.Node ) // infeasible { Vec_IntFree( vEdges ); return eQuit; } // order the inputs only if this is OR or EXOR if ( DecType == DSD_NODE_PRIME ) Vec_IntPush( vEdges, Dec_EdgeToInt(eResult) ); else Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eResult) ); } // the edges are sorted by the level of their nodes in decreasing order // consider special cases if ( DecType == DSD_NODE_OR ) { // try to balance the nodes by delay assert( Vec_IntSize(vEdges) > 1 ); while ( Vec_IntSize(vEdges) > 1 ) { // permute the last two entries if ( Vec_IntSize(vEdges) > 2 ) Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 0 ); // get the two last nodes eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) ); eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) ); pNode1 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode1.Node )->pFunc; pNode2 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode2.Node )->pFunc; pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); // check if the new node exists pNode3 = NULL; if ( pNode1 && pNode2 ) { pNode3 = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); pNode3 = !pNode3? NULL : Abc_ObjNot(pNode3); } // create the new node eNode3 = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 ); // set level Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + Abc_MaxInt(Level1, Level2); // get the new node if possible if ( pNode3 ) { Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl); Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level ); } if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) ) { (*pnNodesAdded)++; if ( *pnNodesAdded > nNodesSaved ) { Vec_IntFree( vEdges ); return eQuit; } } // add the resulting node to the form Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) ); } // get the last node eResult = Dec_IntToEdge( Vec_IntPop(vEdges) ); Vec_IntFree( vEdges ); // complement the graph if the node was complemented eResult.fCompl ^= fCompl; return eResult; } if ( DecType == DSD_NODE_EXOR ) { // try to balance the nodes by delay assert( Vec_IntSize(vEdges) > 1 ); while ( Vec_IntSize(vEdges) > 1 ) { // permute the last two entries if ( Vec_IntSize(vEdges) > 2 ) Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 1 ); // get the two last nodes eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) ); eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) ); pNode1 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode1.Node )->pFunc; pNode2 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode2.Node )->pFunc; pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); // check if the new node exists Type = 0; pNode3 = NULL; if ( pNode1 && pNode2 ) pNode3 = Abc_AigXorLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode2, &Type ); // create the new node eNode3 = Dec_GraphAddNodeXor( pGraph, eNode1, eNode2, Type ); // should have the same structure as in AIG // set level Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + Abc_MaxInt(Level1, Level2); // get the new node if possible if ( pNode3 ) { Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl); Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level ); } if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) ) { (*pnNodesAdded)++; if ( !pNode1 || !pNode2 ) (*pnNodesAdded) += 2; else if ( Type == 0 ) { pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) (*pnNodesAdded)++; pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) (*pnNodesAdded)++; } else { pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) (*pnNodesAdded)++; pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode2 ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) (*pnNodesAdded)++; } if ( *pnNodesAdded > nNodesSaved ) { Vec_IntFree( vEdges ); return eQuit; } } // add the resulting node to the form Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) ); } // get the last node eResult = Dec_IntToEdge( Vec_IntPop(vEdges) ); Vec_IntFree( vEdges ); // complement the graph if the node is complemented eResult.fCompl ^= fCompl; return eResult; } if ( DecType == DSD_NODE_PRIME ) { DdNode * bLocal, * bVar, * bCofT, * bCofE; bLocal = Dsd_TreeGetPrimeFunction( pManRst->dd, pNodeDsd ); Cudd_Ref( bLocal ); //Extra_bddPrint( pManRst->dd, bLocal ); bVar = pManRst->dd->vars[0]; bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) { Cudd_RecursiveDeref( pManRst->dd, bCofE ); Cudd_RecursiveDeref( pManRst->dd, bCofT ); bVar = pManRst->dd->vars[1]; bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) { Cudd_RecursiveDeref( pManRst->dd, bCofE ); Cudd_RecursiveDeref( pManRst->dd, bCofT ); bVar = pManRst->dd->vars[2]; bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) { Cudd_RecursiveDeref( pManRst->dd, bCofE ); Cudd_RecursiveDeref( pManRst->dd, bCofT ); Cudd_RecursiveDeref( pManRst->dd, bLocal ); Vec_IntFree( vEdges ); return eQuit; } } } Cudd_RecursiveDeref( pManRst->dd, bLocal ); // we found the control variable (bVar) and the var-cofactors (bCofT, bCofE) // find the graph nodes eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, bVar->index) ); eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofT)->index) ); eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofE)->index) ); // add the complements to the graph nodes eNode2.fCompl ^= Cudd_IsComplement(bCofT); eNode3.fCompl ^= Cudd_IsComplement(bCofE); // because the cofactors are vars, we can just as well deref them here Cudd_RecursiveDeref( pManRst->dd, bCofE ); Cudd_RecursiveDeref( pManRst->dd, bCofT ); // find the ABC nodes pNode1 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode1.Node )->pFunc; pNode2 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode2.Node )->pFunc; pNode3 = (Abc_Obj_t *)Dec_GraphNode( pGraph, eNode3.Node )->pFunc; pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl ); // check if the new node exists Type = 0; pNode4 = NULL; if ( pNode1 && pNode2 && pNode3 ) pNode4 = Abc_AigMuxLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode2, pNode3, &Type ); // create the new node eResult = Dec_GraphAddNodeMux( pGraph, eNode1, eNode2, eNode3, Type ); // should have the same structure as AIG // set level Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + Abc_MaxInt( Abc_MaxInt(Level1, Level2), Level3 ); // get the new node if possible if ( pNode4 ) { Dec_GraphNode( pGraph, eResult.Node )->pFunc = Abc_ObjNotCond(pNode4, eResult.fCompl); Level4 = Dec_GraphNode( pGraph, eResult.Node )->Level; assert( Required == ABC_INFINITY || Level4 == (int)Abc_ObjRegular(pNode4)->Level ); } if ( !pNode4 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode4)) ) { (*pnNodesAdded)++; if ( Type == 0 ) { if ( !pNode1 || !pNode2 ) (*pnNodesAdded)++; else { pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, pNode2 ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) (*pnNodesAdded)++; } if ( !pNode1 || !pNode3 ) (*pnNodesAdded)++; else { pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) (*pnNodesAdded)++; } } else { if ( !pNode1 || !pNode2 ) (*pnNodesAdded)++; else { pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) (*pnNodesAdded)++; } if ( !pNode1 || !pNode3 ) (*pnNodesAdded)++; else { pTemp = Abc_AigAndLookup( (Abc_Aig_t *)pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) ); if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) (*pnNodesAdded)++; } } if ( *pnNodesAdded > nNodesSaved ) { Vec_IntFree( vEdges ); return eQuit; } } Vec_IntFree( vEdges ); // complement the graph if the node was complemented eResult.fCompl ^= fCompl; return eResult; } Vec_IntFree( vEdges ); return eQuit; } /**Function************************************************************* Synopsis [Evaluation one DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ) { Dec_Graph_t * pGraph; Dec_Edge_t gEdge; Abc_Obj_t * pLeaf; Dec_Node_t * pNode; int i; // create the graph and set the leaves pGraph = Dec_GraphCreate( Vec_PtrSize(pManRst->vLeaves) ); Dec_GraphForEachLeaf( pGraph, pNode, i ) { pLeaf = (Abc_Obj_t *)Vec_PtrEntry( pManRst->vLeaves, i ); pNode->pFunc = pLeaf; pNode->Level = pLeaf->Level; } // create the decomposition structure from the DSD *pnNodesAdded = 0; gEdge = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pNodeDsd, Required, nNodesSaved, pnNodesAdded ); if ( gEdge.Node > 1000 ) // infeasible { *pnNodesAdded = -1; Dec_GraphFree( pGraph ); return NULL; } // quit if the root node is the same pLeaf = (Abc_Obj_t *)Dec_GraphNode( pGraph, gEdge.Node )->pFunc; if ( Abc_ObjRegular(pLeaf) == pRoot ) { *pnNodesAdded = -1; Dec_GraphFree( pGraph ); return NULL; } Dec_GraphSetRoot( pGraph, gEdge ); return pGraph; } /**Function************************************************************* Synopsis [Starts the cut manager for rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ) { static Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pManCut; Abc_Obj_t * pObj; int i; // start the cut manager memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = nCutMax; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 250; // the max number of cuts kept at a node pParams->fTruth = 0; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fSeq = 0; // compute sequential cuts pParams->fDrop = 0; // drop cuts on the fly pParams->fDag = fDag; // compute DAG cuts pParams->fTree = 0; // compute tree cuts pParams->fVerbose = 0; // the verbosiness flag pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); pManCut = Cut_ManStart( pParams ); if ( pParams->fDrop ) Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); // set cuts for PIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( pManCut, pObj->Id ); return pManCut; } /**Function************************************************************* Synopsis [Starts the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, int fUpdateLevel, int fUseZeros, int fVerbose ) { Abc_ManRst_t * p; p = ABC_ALLOC( Abc_ManRst_t, 1 ); memset( p, 0, sizeof(Abc_ManRst_t) ); // set the parameters p->nCutMax = nCutMax; p->fUpdateLevel = fUpdateLevel; p->fUseZeros = fUseZeros; p->fVerbose = fVerbose; // start the BDD manager p->dd = Cudd_Init( p->nCutMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_zddVarsFromBddVars( p->dd, 2 ); // start the DSD manager p->pManDsd = Dsd_ManagerStart( p->dd, p->dd->size, 0 ); // other temp datastructures p->vVisited = Vec_PtrAlloc( 100 ); p->vLeaves = Vec_PtrAlloc( 100 ); p->vDecs = Vec_PtrAlloc( 100 ); p->vTemp = Vec_PtrAlloc( 100 ); p->vSims = Vec_IntAlloc( 100 ); p->vOnes = Vec_IntAlloc( 100 ); p->vBinate = Vec_IntAlloc( 100 ); p->vTwos = Vec_IntAlloc( 100 ); p->vRands = Vec_IntAlloc( 20 ); { int i; for ( i = 0; i < 20; i++ ) Vec_IntPush( p->vRands, (int)RST_RANDOM_UNSIGNED ); } return p; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkManRstStop( Abc_ManRst_t * p ) { Dsd_ManagerStop( p->pManDsd ); Extra_StopManager( p->dd ); Vec_PtrFree( p->vDecs ); Vec_PtrFree( p->vLeaves ); Vec_PtrFree( p->vVisited ); Vec_PtrFree( p->vTemp ); Vec_IntFree( p->vSims ); Vec_IntFree( p->vOnes ); Vec_IntFree( p->vBinate ); Vec_IntFree( p->vTwos ); Vec_IntFree( p->vRands ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ) { printf( "Refactoring statistics:\n" ); printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); printf( "Cuts considered = %8d.\n", p->nCutsConsidered ); printf( "Cuts explored = %8d.\n", p->nCutsExplored ); printf( "Nodes restructured = %8d.\n", p->nNodesRestructured ); printf( "Calculated gain = %8d.\n", p->nNodesGained ); ABC_PRT( "Cuts ", p->timeCut ); ABC_PRT( "Resynthesis", p->timeRes ); ABC_PRT( " BDD ", p->timeBdd ); ABC_PRT( " DSD ", p->timeDsd ); ABC_PRT( " Eval ", p->timeEval ); ABC_PRT( "AIG update ", p->timeNtk ); ABC_PRT( "TOTAL ", p->timeTotal ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_Abc_NodeResubCollectDivs( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) { Abc_Obj_t * pNode, * pFanout; int i, k; // collect the leaves of the cut Vec_PtrClear( p->vDecs ); Abc_NtkIncrementTravId( pRoot->pNtk ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pNode = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]); if ( pNode == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes return 0; Vec_PtrPush( p->vDecs, pNode ); Abc_NodeSetTravIdCurrent( pNode ); } // explore the fanouts Vec_PtrForEachEntry( Abc_Obj_t *, p->vDecs, pNode, i ) { // if the fanout has both fanins in the set, add it Abc_ObjForEachFanout( pNode, pFanout, k ) { if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsPo(pFanout) ) continue; if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) ) { Vec_PtrPush( p->vDecs, pFanout ); Abc_NodeSetTravIdCurrent( pFanout ); } } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeResubMffc_rec( Abc_Obj_t * pNode ) { if ( Abc_NodeIsTravIdCurrent(pNode) ) return 0; Abc_NodeSetTravIdCurrent( pNode ); return 1 + Abc_NodeResubMffc_rec( Abc_ObjFanin0(pNode) ) + Abc_NodeResubMffc_rec( Abc_ObjFanin1(pNode) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeResubMffc( Abc_ManRst_t * p, Vec_Ptr_t * vDecs, int nLeaves, Abc_Obj_t * pRoot ) { Abc_Obj_t * pObj; int Counter, i, k; // increment the traversal ID for the leaves Abc_NtkIncrementTravId( pRoot->pNtk ); // label the leaves Vec_PtrForEachEntryStop( Abc_Obj_t *, vDecs, pObj, i, nLeaves ) Abc_NodeSetTravIdCurrent( pObj ); // make sure the node is in the cone and is no one of the leaves assert( Abc_NodeIsTravIdPrevious(pRoot) ); Counter = Abc_NodeResubMffc_rec( pRoot ); // move the labeled nodes to the end Vec_PtrClear( p->vTemp ); k = 0; Vec_PtrForEachEntryStart( Abc_Obj_t *, vDecs, pObj, i, nLeaves ) if ( Abc_NodeIsTravIdCurrent(pObj) ) Vec_PtrPush( p->vTemp, pObj ); else Vec_PtrWriteEntry( vDecs, k++, pObj ); // add the labeled nodes Vec_PtrForEachEntry( Abc_Obj_t *, p->vTemp, pObj, i ) Vec_PtrWriteEntry( vDecs, k++, pObj ); assert( k == Vec_PtrSize(p->vDecs) ); assert( pRoot == Vec_PtrEntryLast(p->vDecs) ); return Counter; } /**Function************************************************************* Synopsis [Performs simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeMffcSimulate( Vec_Ptr_t * vDecs, int nLeaves, Vec_Int_t * vRands, Vec_Int_t * vSims ) { Abc_Obj_t * pObj; unsigned uData0, uData1, uData; int i; // initialize random simulation data Vec_IntClear( vSims ); Vec_PtrForEachEntryStop( Abc_Obj_t *, vDecs, pObj, i, nLeaves ) { uData = (unsigned)Vec_IntEntry( vRands, i ); pObj->pData = (void *)(ABC_PTRUINT_T)uData; Vec_IntPush( vSims, uData ); } // simulate Vec_PtrForEachEntryStart( Abc_Obj_t *, vDecs, pObj, i, nLeaves ) { uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData; uData1 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pData; uData = (Abc_ObjFaninC0(pObj)? ~uData0 : uData0) & (Abc_ObjFaninC1(pObj)? ~uData1 : uData1); pObj->pData = (void *)(ABC_PTRUINT_T)uData; Vec_IntPush( vSims, uData ); } } /**Function************************************************************* Synopsis [Full equality check.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCheckFull( Abc_ManRst_t * p, Dec_Graph_t * pGraph ) { return 1; } /**Function************************************************************* Synopsis [Detect contants.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeMffcConstants( Abc_ManRst_t * p, Vec_Int_t * vSims ) { Dec_Graph_t * pGraph = NULL; unsigned uRoot; // get the root node uRoot = (unsigned)Vec_IntEntryLast( vSims ); // get the graph if the node looks constant if ( uRoot == 0 ) pGraph = Dec_GraphCreateConst0(); else if ( uRoot == ~(unsigned)0 ) pGraph = Dec_GraphCreateConst1(); // check the graph assert(pGraph); if ( Abc_NodeCheckFull( p, pGraph ) ) return pGraph; Dec_GraphFree( pGraph ); return NULL; } /**Function************************************************************* Synopsis [Detect single non-overlaps.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeMffcSingleVar( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) { Dec_Graph_t * pGraph; unsigned uRoot, uNode; int i; Vec_IntClear( vOnes ); Vec_IntClear( p->vBinate ); uRoot = (unsigned)Vec_IntEntryLast( vSims ); for ( i = 0; i < nNodes; i++ ) { uNode = (unsigned)Vec_IntEntry( vSims, i ); if ( uRoot == uNode || uRoot == ~uNode ) { pGraph = Dec_GraphCreate( 1 ); Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, i ); Dec_GraphSetRoot( pGraph, Dec_IntToEdge( (int)(uRoot == ~uNode) ) ); // check the graph if ( Abc_NodeCheckFull( p, pGraph ) ) return pGraph; Dec_GraphFree( pGraph ); } if ( (uRoot & uNode) == 0 ) Vec_IntPush( vOnes, i << 1 ); else if ( (uRoot & ~uNode) == 0 ) Vec_IntPush( vOnes, (i << 1) + 1 ); else Vec_IntPush( p->vBinate, i ); } return NULL; } /**Function************************************************************* Synopsis [Detect single non-overlaps.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeMffcSingleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) { Dec_Graph_t * pGraph; Dec_Edge_t eNode0, eNode1, eRoot; unsigned uRoot; int i, k; uRoot = (unsigned)Vec_IntEntryLast( vSims ); for ( i = 0; i < vOnes->nSize; i++ ) for ( k = i+1; k < vOnes->nSize; k++ ) if ( ~uRoot == ((unsigned)vOnes->pArray[i] | (unsigned)vOnes->pArray[k]) ) { eNode0 = Dec_IntToEdge( vOnes->pArray[i] ^ 1 ); eNode1 = Dec_IntToEdge( vOnes->pArray[k] ^ 1 ); pGraph = Dec_GraphCreate( 2 ); Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, eNode0.Node ); Dec_GraphNode( pGraph, 1 )->pFunc = Vec_PtrEntry( p->vDecs, eNode1.Node ); eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); Dec_GraphSetRoot( pGraph, eRoot ); if ( Abc_NodeCheckFull( p, pGraph ) ) return pGraph; Dec_GraphFree( pGraph ); } return NULL; } /**Function************************************************************* Synopsis [Detect single non-overlaps.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeMffcDoubleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) { // Dec_Graph_t * pGraph; // unsigned uRoot, uNode; // int i; return NULL; } /**Function************************************************************* Synopsis [Evaluates resubstution of one cut.] Description [Returns the graph to add if any.] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeResubEval( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) { Dec_Graph_t * pGraph; int nNodesSaved; // collect the nodes in the cut if ( !Abc_Abc_NodeResubCollectDivs( p, pRoot, pCut ) ) return NULL; // label MFFC and count its size nNodesSaved = Abc_NodeResubMffc( p, p->vDecs, pCut->nLeaves, pRoot ); assert( nNodesSaved > 0 ); // simulate MFFC Abc_NodeMffcSimulate( p->vDecs, pCut->nLeaves, p->vRands, p->vSims ); // check for constant output pGraph = Abc_NodeMffcConstants( p, p->vSims ); if ( pGraph ) { p->nNodesGained += nNodesSaved; p->nNodesRestructured++; return pGraph; } // check for one literal (fill up the ones array) pGraph = Abc_NodeMffcSingleVar( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); if ( pGraph ) { p->nNodesGained += nNodesSaved; p->nNodesRestructured++; return pGraph; } if ( nNodesSaved == 1 ) return NULL; // look for one node pGraph = Abc_NodeMffcSingleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); if ( pGraph ) { p->nNodesGained += nNodesSaved - 1; p->nNodesRestructured++; return pGraph; } if ( nNodesSaved == 2 ) return NULL; // look for two nodes pGraph = Abc_NodeMffcDoubleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); if ( pGraph ) { p->nNodesGained += nNodesSaved - 2; p->nNodesRestructured++; return pGraph; } if ( nNodesSaved == 3 ) return NULL; /* // look for MUX/EXOR pGraph = Abc_NodeMffcMuxNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved ); if ( pGraph ) { p->nNodesGained += nNodesSaved - 1; p->nNodesRestructured++; return pGraph; } */ return NULL; } /**Function************************************************************* Synopsis [Performs resubstution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ) { Dec_Graph_t * pGraph, * pGraphBest = NULL; Cut_Cut_t * pCut; int nCuts; p->nNodesConsidered++; // count the number of cuts with four inputs or more nCuts = 0; for ( pCut = pCutList; pCut; pCut = pCut->pNext ) nCuts += (int)(pCut->nLeaves > 3); printf( "-----------------------------------\n" ); printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts ); // go through the interesting cuts for ( pCut = pCutList; pCut; pCut = pCut->pNext ) { if ( pCut->nLeaves < 4 ) continue; pGraph = Abc_NodeResubEval( p, pNode, pCut ); if ( pGraph == NULL ) continue; if ( !pGraphBest || Dec_GraphNodeNum(pGraph) < Dec_GraphNodeNum(pGraphBest) ) { if ( pGraphBest ) Dec_GraphFree(pGraphBest); pGraphBest = pGraph; } else Dec_GraphFree(pGraph); } return pGraphBest; } #else int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, int fUpdateLevel, int fUseZeros, int fVerbose ) { return 1; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcResub.c000066400000000000000000002142171300674244400235450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcResub.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Resubstitution manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "bool/dec/dec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_RS_DIV1_MAX 150 // the max number of divisors to consider #define ABC_RS_DIV2_MAX 500 // the max number of pair-wise divisors to consider typedef struct Abc_ManRes_t_ Abc_ManRes_t; struct Abc_ManRes_t_ { // paramers int nLeavesMax; // the max number of leaves in the cone int nDivsMax; // the max number of divisors in the cone // representation of the cone Abc_Obj_t * pRoot; // the root of the cone int nLeaves; // the number of leaves int nDivs; // the number of all divisor (including leaves) int nMffc; // the size of MFFC int nLastGain; // the gain the number of nodes Vec_Ptr_t * vDivs; // the divisors // representation of the simulation info int nBits; // the number of simulation bits int nWords; // the number of unsigneds for siminfo Vec_Ptr_t * vSims; // simulation info unsigned * pInfo; // pointer to simulation info // observability don't-cares unsigned * pCareSet; // internal divisor storage Vec_Ptr_t * vDivs1UP; // the single-node unate divisors Vec_Ptr_t * vDivs1UN; // the single-node unate divisors Vec_Ptr_t * vDivs1B; // the single-node binate divisors Vec_Ptr_t * vDivs2UP0; // the double-node unate divisors Vec_Ptr_t * vDivs2UP1; // the double-node unate divisors Vec_Ptr_t * vDivs2UN0; // the double-node unate divisors Vec_Ptr_t * vDivs2UN1; // the double-node unate divisors // other data Vec_Ptr_t * vTemp; // temporary array of nodes // runtime statistics abctime timeCut; abctime timeTruth; abctime timeRes; abctime timeDiv; abctime timeMffc; abctime timeSim; abctime timeRes1; abctime timeResD; abctime timeRes2; abctime timeRes3; abctime timeNtk; abctime timeTotal; // improvement statistics int nUsedNodeC; int nUsedNode0; int nUsedNode1Or; int nUsedNode1And; int nUsedNode2Or; int nUsedNode2And; int nUsedNode2OrAnd; int nUsedNode2AndOr; int nUsedNode3OrAnd; int nUsedNode3AndOr; int nUsedNodeTotal; int nTotalDivs; int nTotalLeaves; int nTotalGain; int nNodesBeg; int nNodesEnd; }; // external procedures static Abc_ManRes_t* Abc_ManResubStart( int nLeavesMax, int nDivsMax ); static void Abc_ManResubStop( Abc_ManRes_t * p ); static Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, int fUpdateLevel, int fVerbose ); static void Abc_ManResubCleanup( Abc_ManRes_t * p ); static void Abc_ManResubPrint( Abc_ManRes_t * p ); // other procedures static int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ); static void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ); static void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); static void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ); static void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ); static Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p ); static Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p ); static Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required ); static Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ); static Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required ); static Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ); static Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ); static int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); extern abctime s_ResubTime; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs incremental resynthesis of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ) { extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); ProgressBar * pProgress; Abc_ManRes_t * pManRes; Abc_ManCut_t * pManCut; Odc_Man_t * pManOdc = NULL; Dec_Graph_t * pFForm; Vec_Ptr_t * vLeaves; Abc_Obj_t * pNode; abctime clk, clkStart = Abc_Clock(); int i, nNodes; assert( Abc_NtkIsStrash(pNtk) ); // cleanup the AIG Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); // start the managers pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 ); pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX ); if ( nLevelsOdc > 0 ) pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose ); // compute the reverse levels if level update is requested if ( fUpdateLevel ) Abc_NtkStartReverseLevels( pNtk, 0 ); if ( Abc_NtkLatchNum(pNtk) ) { Abc_NtkForEachLatch(pNtk, pNode, i) pNode->pNext = (Abc_Obj_t *)pNode->pData; } // resynthesize each node once pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // skip the constant node // if ( Abc_NodeIsConst(pNode) ) // continue; // skip persistant nodes if ( Abc_NodeIsPersistant(pNode) ) continue; // skip the nodes with many fanouts if ( Abc_ObjFanoutNum(pNode) > 1000 ) continue; // stop if all nodes have been tried once if ( i >= nNodes ) break; // compute a reconvergence-driven cut clk = Abc_Clock(); vLeaves = Abc_NodeFindCut( pManCut, pNode, 0 ); // vLeaves = Abc_CutFactorLarge( pNode, nCutMax ); pManRes->timeCut += Abc_Clock() - clk; /* if ( fVerbose && vLeaves ) printf( "Node %6d : Leaves = %3d. Volume = %3d.\n", pNode->Id, Vec_PtrSize(vLeaves), Abc_CutVolumeCheck(pNode, vLeaves) ); if ( vLeaves == NULL ) continue; */ // get the don't-cares if ( pManOdc ) { clk = Abc_Clock(); Abc_NtkDontCareClear( pManOdc ); Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet ); pManRes->timeTruth += Abc_Clock() - clk; } // evaluate this cut clk = Abc_Clock(); pFForm = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose ); // Vec_PtrFree( vLeaves ); // Abc_ManResubCleanup( pManRes ); pManRes->timeRes += Abc_Clock() - clk; if ( pFForm == NULL ) continue; pManRes->nTotalGain += pManRes->nLastGain; /* if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 ) { printf( "%6d : L = %2d. V = %2d. Mffc = %2d. Divs = %3d. Up = %3d. Un = %3d. B = %3d.\n", pNode->Id, pManRes->nLeaves, Abc_CutVolumeCheck(pNode, vLeaves), pManRes->nMffc, pManRes->nDivs, pManRes->vDivs1UP->nSize, pManRes->vDivs1UN->nSize, pManRes->vDivs1B->nSize ); Abc_ManResubPrintDivs( pManRes, pNode, vLeaves ); } */ // acceptable replacement found, update the graph clk = Abc_Clock(); Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRes->nLastGain ); pManRes->timeNtk += Abc_Clock() - clk; Dec_GraphFree( pFForm ); } Extra_ProgressBarStop( pProgress ); pManRes->timeTotal = Abc_Clock() - clkStart; pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk); // print statistics if ( fVerbose ) Abc_ManResubPrint( pManRes ); // delete the managers Abc_ManResubStop( pManRes ); Abc_NtkManCutStop( pManCut ); if ( pManOdc ) Abc_NtkDontCareFree( pManOdc ); // clean the data field Abc_NtkForEachObj( pNtk, pNode, i ) pNode->pData = NULL; if ( Abc_NtkLatchNum(pNtk) ) { Abc_NtkForEachLatch(pNtk, pNode, i) pNode->pData = pNode->pNext, pNode->pNext = NULL; } // put the nodes into the DFS order and reassign their IDs Abc_NtkReassignIds( pNtk ); // Abc_AigCheckFaninOrder( pNtk->pManFunc ); // fix the levels if ( fUpdateLevel ) Abc_NtkStopReverseLevels( pNtk ); else Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkRefactor: The network check has failed.\n" ); return 0; } s_ResubTime = Abc_Clock() - clkStart; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ManRes_t * Abc_ManResubStart( int nLeavesMax, int nDivsMax ) { Abc_ManRes_t * p; unsigned * pData; int i, k; assert( sizeof(unsigned) == 4 ); p = ABC_ALLOC( Abc_ManRes_t, 1 ); memset( p, 0, sizeof(Abc_ManRes_t) ); p->nLeavesMax = nLeavesMax; p->nDivsMax = nDivsMax; p->vDivs = Vec_PtrAlloc( p->nDivsMax ); // allocate simulation info p->nBits = (1 << p->nLeavesMax); p->nWords = (p->nBits <= 32)? 1 : (p->nBits / 32); p->pInfo = ABC_ALLOC( unsigned, p->nWords * (p->nDivsMax + 1) ); memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nLeavesMax ); p->vSims = Vec_PtrAlloc( p->nDivsMax ); for ( i = 0; i < p->nDivsMax; i++ ) Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords ); // assign the care set p->pCareSet = p->pInfo + p->nDivsMax * p->nWords; Abc_InfoFill( p->pCareSet, p->nWords ); // set elementary truth tables for ( k = 0; k < p->nLeavesMax; k++ ) { pData = (unsigned *)p->vSims->pArray[k]; for ( i = 0; i < p->nBits; i++ ) if ( i & (1 << k) ) pData[i>>5] |= (1 << (i&31)); } // create the remaining divisors p->vDivs1UP = Vec_PtrAlloc( p->nDivsMax ); p->vDivs1UN = Vec_PtrAlloc( p->nDivsMax ); p->vDivs1B = Vec_PtrAlloc( p->nDivsMax ); p->vDivs2UP0 = Vec_PtrAlloc( p->nDivsMax ); p->vDivs2UP1 = Vec_PtrAlloc( p->nDivsMax ); p->vDivs2UN0 = Vec_PtrAlloc( p->nDivsMax ); p->vDivs2UN1 = Vec_PtrAlloc( p->nDivsMax ); p->vTemp = Vec_PtrAlloc( p->nDivsMax ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManResubStop( Abc_ManRes_t * p ) { Vec_PtrFree( p->vDivs ); Vec_PtrFree( p->vSims ); Vec_PtrFree( p->vDivs1UP ); Vec_PtrFree( p->vDivs1UN ); Vec_PtrFree( p->vDivs1B ); Vec_PtrFree( p->vDivs2UP0 ); Vec_PtrFree( p->vDivs2UP1 ); Vec_PtrFree( p->vDivs2UN0 ); Vec_PtrFree( p->vDivs2UN1 ); Vec_PtrFree( p->vTemp ); ABC_FREE( p->pInfo ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManResubPrint( Abc_ManRes_t * p ) { printf( "Used constants = %6d. ", p->nUsedNodeC ); ABC_PRT( "Cuts ", p->timeCut ); printf( "Used replacements = %6d. ", p->nUsedNode0 ); ABC_PRT( "Resub ", p->timeRes ); printf( "Used single ORs = %6d. ", p->nUsedNode1Or ); ABC_PRT( " Div ", p->timeDiv ); printf( "Used single ANDs = %6d. ", p->nUsedNode1And ); ABC_PRT( " Mffc ", p->timeMffc ); printf( "Used double ORs = %6d. ", p->nUsedNode2Or ); ABC_PRT( " Sim ", p->timeSim ); printf( "Used double ANDs = %6d. ", p->nUsedNode2And ); ABC_PRT( " 1 ", p->timeRes1 ); printf( "Used OR-AND = %6d. ", p->nUsedNode2OrAnd ); ABC_PRT( " D ", p->timeResD ); printf( "Used AND-OR = %6d. ", p->nUsedNode2AndOr ); ABC_PRT( " 2 ", p->timeRes2 ); printf( "Used OR-2ANDs = %6d. ", p->nUsedNode3OrAnd ); ABC_PRT( "Truth ", p->timeTruth ); //ABC_PRT( " 3 ", p->timeRes3 ); printf( "Used AND-2ORs = %6d. ", p->nUsedNode3AndOr ); ABC_PRT( "AIG ", p->timeNtk ); printf( "TOTAL = %6d. ", p->nUsedNodeC + p->nUsedNode0 + p->nUsedNode1Or + p->nUsedNode1And + p->nUsedNode2Or + p->nUsedNode2And + p->nUsedNode2OrAnd + p->nUsedNode2AndOr + p->nUsedNode3OrAnd + p->nUsedNode3AndOr ); ABC_PRT( "TOTAL ", p->timeTotal ); printf( "Total leaves = %8d.\n", p->nTotalLeaves ); printf( "Total divisors = %8d.\n", p->nTotalDivs ); // printf( "Total gain = %8d.\n", p->nTotalGain ); printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManResubCollectDivs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vInternal ) { // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pNode) ) return; Abc_NodeSetTravIdCurrent(pNode); // collect the fanins Abc_ManResubCollectDivs_rec( Abc_ObjFanin0(pNode), vInternal ); Abc_ManResubCollectDivs_rec( Abc_ObjFanin1(pNode), vInternal ); // collect the internal node if ( pNode->fMarkA == 0 ) Vec_PtrPush( vInternal, pNode ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ) { Abc_Obj_t * pNode, * pFanout; int i, k, Limit, Counter; Vec_PtrClear( p->vDivs1UP ); Vec_PtrClear( p->vDivs1UN ); Vec_PtrClear( p->vDivs1B ); // add the leaves of the cuts to the divisors Vec_PtrClear( p->vDivs ); Abc_NtkIncrementTravId( pRoot->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i ) { Vec_PtrPush( p->vDivs, pNode ); Abc_NodeSetTravIdCurrent( pNode ); } // mark nodes in the MFFC Vec_PtrForEachEntry( Abc_Obj_t *, p->vTemp, pNode, i ) pNode->fMarkA = 1; // collect the cone (without MFFC) Abc_ManResubCollectDivs_rec( pRoot, p->vDivs ); // unmark the current MFFC Vec_PtrForEachEntry( Abc_Obj_t *, p->vTemp, pNode, i ) pNode->fMarkA = 0; // check if the number of divisors is not exceeded if ( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp) >= Vec_PtrSize(p->vSims) - p->nLeavesMax ) return 0; // get the number of divisors to collect Limit = Vec_PtrSize(p->vSims) - p->nLeavesMax - (Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp)); // explore the fanouts, which are not in the MFFC Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pNode, i ) { if ( Abc_ObjFanoutNum(pNode) > 100 ) { // printf( "%d ", Abc_ObjFanoutNum(pNode) ); continue; } // if the fanout has both fanins in the set, add it Abc_ObjForEachFanout( pNode, pFanout, k ) { if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsCo(pFanout) || (int)pFanout->Level > Required ) continue; if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) ) { if ( Abc_ObjFanin0(pFanout) == pRoot || Abc_ObjFanin1(pFanout) == pRoot ) continue; Vec_PtrPush( p->vDivs, pFanout ); Abc_NodeSetTravIdCurrent( pFanout ); // quit computing divisors if there is too many of them if ( ++Counter == Limit ) goto Quits; } } } Quits : // get the number of divisors p->nDivs = Vec_PtrSize(p->vDivs); // add the nodes in the MFFC Vec_PtrForEachEntry( Abc_Obj_t *, p->vTemp, pNode, i ) Vec_PtrPush( p->vDivs, pNode ); assert( pRoot == Vec_PtrEntryLast(p->vDivs) ); assert( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) <= Vec_PtrSize(p->vSims) - p->nLeavesMax ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ) { Abc_Obj_t * pFanin, * pNode; int i, k; // print the nodes Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pNode, i ) { if ( i < Vec_PtrSize(vLeaves) ) { printf( "%6d : %c\n", pNode->Id, 'a'+i ); continue; } printf( "%6d : %2d = ", pNode->Id, i ); // find the first fanin Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pFanin, k ) if ( Abc_ObjFanin0(pNode) == pFanin ) break; if ( k < Vec_PtrSize(vLeaves) ) printf( "%c", 'a' + k ); else printf( "%d", k ); printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); // find the second fanin Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pFanin, k ) if ( Abc_ObjFanin1(pNode) == pFanin ) break; if ( k < Vec_PtrSize(vLeaves) ) printf( "%c", 'a' + k ); else printf( "%d", k ); printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); if ( pNode == pRoot ) printf( " root" ); printf( "\n" ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Performs simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ) { Abc_Obj_t * pObj; unsigned * puData0, * puData1, * puData; int i, k; assert( Vec_PtrSize(vDivs) - nLeaves <= Vec_PtrSize(vSims) - nLeavesMax ); // simulate Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, i ) { if ( i < nLeaves ) { // initialize the leaf pObj->pData = Vec_PtrEntry( vSims, i ); continue; } // set storage for the node's simulation info pObj->pData = Vec_PtrEntry( vSims, i - nLeaves + nLeavesMax ); // get pointer to the simulation info puData = (unsigned *)pObj->pData; puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pData; puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pData; // simulate if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) ) for ( k = 0; k < nWords; k++ ) puData[k] = ~puData0[k] & ~puData1[k]; else if ( Abc_ObjFaninC0(pObj) ) for ( k = 0; k < nWords; k++ ) puData[k] = ~puData0[k] & puData1[k]; else if ( Abc_ObjFaninC1(pObj) ) for ( k = 0; k < nWords; k++ ) puData[k] = puData0[k] & ~puData1[k]; else for ( k = 0; k < nWords; k++ ) puData[k] = puData0[k] & puData1[k]; } // normalize Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, i ) { puData = (unsigned *)pObj->pData; pObj->fPhase = (puData[0] & 1); if ( pObj->fPhase ) for ( k = 0; k < nWords; k++ ) puData[k] = ~puData[k]; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubQuit0( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ) { Dec_Graph_t * pGraph; Dec_Edge_t eRoot; pGraph = Dec_GraphCreate( 1 ); Dec_GraphNode( pGraph, 0 )->pFunc = pObj; eRoot = Dec_EdgeCreate( 0, pObj->fPhase ); Dec_GraphSetRoot( pGraph, eRoot ); if ( pRoot->fPhase ) Dec_GraphComplement( pGraph ); return pGraph; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubQuit1( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, int fOrGate ) { Dec_Graph_t * pGraph; Dec_Edge_t eRoot, eNode0, eNode1; assert( pObj0 != pObj1 ); assert( !Abc_ObjIsComplement(pObj0) ); assert( !Abc_ObjIsComplement(pObj1) ); pGraph = Dec_GraphCreate( 2 ); Dec_GraphNode( pGraph, 0 )->pFunc = pObj0; Dec_GraphNode( pGraph, 1 )->pFunc = pObj1; eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase ); eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase ); if ( fOrGate ) eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); else eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); Dec_GraphSetRoot( pGraph, eRoot ); if ( pRoot->fPhase ) Dec_GraphComplement( pGraph ); return pGraph; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubQuit21( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate ) { Dec_Graph_t * pGraph; Dec_Edge_t eRoot, eNode0, eNode1, eNode2; assert( pObj0 != pObj1 ); assert( !Abc_ObjIsComplement(pObj0) ); assert( !Abc_ObjIsComplement(pObj1) ); assert( !Abc_ObjIsComplement(pObj2) ); pGraph = Dec_GraphCreate( 3 ); Dec_GraphNode( pGraph, 0 )->pFunc = pObj0; Dec_GraphNode( pGraph, 1 )->pFunc = pObj1; Dec_GraphNode( pGraph, 2 )->pFunc = pObj2; eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase ); eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase ); eNode2 = Dec_EdgeCreate( 2, pObj2->fPhase ); if ( fOrGate ) { eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); eRoot = Dec_GraphAddNodeOr( pGraph, eNode2, eRoot ); } else { eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); eRoot = Dec_GraphAddNodeAnd( pGraph, eNode2, eRoot ); } Dec_GraphSetRoot( pGraph, eRoot ); if ( pRoot->fPhase ) Dec_GraphComplement( pGraph ); return pGraph; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubQuit2( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate ) { Dec_Graph_t * pGraph; Dec_Edge_t eRoot, ePrev, eNode0, eNode1, eNode2; assert( pObj0 != pObj1 ); assert( pObj0 != pObj2 ); assert( pObj1 != pObj2 ); assert( !Abc_ObjIsComplement(pObj0) ); pGraph = Dec_GraphCreate( 3 ); Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0); Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1); Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2); eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ); if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) { eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ); eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); ePrev = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 ); } else { eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) ); eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); ePrev = Dec_GraphAddNodeAnd( pGraph, eNode1, eNode2 ); } if ( fOrGate ) eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, ePrev ); else eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, ePrev ); Dec_GraphSetRoot( pGraph, eRoot ); if ( pRoot->fPhase ) Dec_GraphComplement( pGraph ); return pGraph; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubQuit3( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, Abc_Obj_t * pObj3, int fOrGate ) { Dec_Graph_t * pGraph; Dec_Edge_t eRoot, ePrev0, ePrev1, eNode0, eNode1, eNode2, eNode3; assert( pObj0 != pObj1 ); assert( pObj2 != pObj3 ); pGraph = Dec_GraphCreate( 4 ); Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0); Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1); Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2); Dec_GraphNode( pGraph, 3 )->pFunc = Abc_ObjRegular(pObj3); if ( Abc_ObjIsComplement(pObj0) && Abc_ObjIsComplement(pObj1) ) { eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ); eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ); ePrev0 = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) ) { eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ); ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 ); } else { eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) ); ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 ); } } else { eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ^ Abc_ObjIsComplement(pObj0) ); eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) ); ePrev0 = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) ) { eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ); ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 ); } else { eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) ); ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 ); } } if ( fOrGate ) eRoot = Dec_GraphAddNodeOr( pGraph, ePrev0, ePrev1 ); else eRoot = Dec_GraphAddNodeAnd( pGraph, ePrev0, ePrev1 ); Dec_GraphSetRoot( pGraph, eRoot ); if ( pRoot->fPhase ) Dec_GraphComplement( pGraph ); return pGraph; } /**Function************************************************************* Synopsis [Derives single-node unate/binate divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ) { Abc_Obj_t * pObj; unsigned * puData, * puDataR; int i, w; Vec_PtrClear( p->vDivs1UP ); Vec_PtrClear( p->vDivs1UN ); Vec_PtrClear( p->vDivs1B ); puDataR = (unsigned *)p->pRoot->pData; Vec_PtrForEachEntryStop( Abc_Obj_t *, p->vDivs, pObj, i, p->nDivs ) { if ( (int)pObj->Level > Required - 1 ) continue; puData = (unsigned *)pObj->pData; // check positive containment for ( w = 0; w < p->nWords; w++ ) // if ( puData[w] & ~puDataR[w] ) if ( puData[w] & ~puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs1UP, pObj ); continue; } // check negative containment for ( w = 0; w < p->nWords; w++ ) // if ( ~puData[w] & puDataR[w] ) if ( ~puData[w] & puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs1UN, pObj ); continue; } // add the node to binates Vec_PtrPush( p->vDivs1B, pObj ); } } /**Function************************************************************* Synopsis [Derives double-node unate/binate divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ) { Abc_Obj_t * pObj0, * pObj1; unsigned * puData0, * puData1, * puDataR; int i, k, w; Vec_PtrClear( p->vDivs2UP0 ); Vec_PtrClear( p->vDivs2UP1 ); Vec_PtrClear( p->vDivs2UN0 ); Vec_PtrClear( p->vDivs2UN1 ); puDataR = (unsigned *)p->pRoot->pData; Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1B, pObj0, i ) { if ( (int)pObj0->Level > Required - 2 ) continue; puData0 = (unsigned *)pObj0->pData; Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1B, pObj1, k, i + 1 ) { if ( (int)pObj1->Level > Required - 2 ) continue; puData1 = (unsigned *)pObj1->pData; if ( Vec_PtrSize(p->vDivs2UP0) < ABC_RS_DIV2_MAX ) { // get positive unate divisors for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] & puData1[w]) & ~puDataR[w] ) if ( (puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs2UP0, pObj0 ); Vec_PtrPush( p->vDivs2UP1, pObj1 ); } for ( w = 0; w < p->nWords; w++ ) // if ( (~puData0[w] & puData1[w]) & ~puDataR[w] ) if ( (~puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) ); Vec_PtrPush( p->vDivs2UP1, pObj1 ); } for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] ) if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs2UP0, pObj0 ); Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) ); } for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] | puData1[w]) & ~puDataR[w] ) if ( (puData0[w] | puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) ); Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) ); } } if ( Vec_PtrSize(p->vDivs2UN0) < ABC_RS_DIV2_MAX ) { // get negative unate divisors for ( w = 0; w < p->nWords; w++ ) // if ( ~(puData0[w] & puData1[w]) & puDataR[w] ) if ( ~(puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs2UN0, pObj0 ); Vec_PtrPush( p->vDivs2UN1, pObj1 ); } for ( w = 0; w < p->nWords; w++ ) // if ( ~(~puData0[w] & puData1[w]) & puDataR[w] ) if ( ~(~puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) ); Vec_PtrPush( p->vDivs2UN1, pObj1 ); } for ( w = 0; w < p->nWords; w++ ) // if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] ) if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs2UN0, pObj0 ); Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) ); } for ( w = 0; w < p->nWords; w++ ) // if ( ~(puData0[w] | puData1[w]) & puDataR[w] ) if ( ~(puData0[w] | puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) ); Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) ); } } } } // printf( "%d %d ", Vec_PtrSize(p->vDivs2UP0), Vec_PtrSize(p->vDivs2UN0) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p ) { Dec_Graph_t * pGraph; unsigned * upData; int w; upData = (unsigned *)p->pRoot->pData; for ( w = 0; w < p->nWords; w++ ) // if ( upData[w] ) if ( upData[w] & p->pCareSet[w] ) // care set break; if ( w != p->nWords ) return NULL; // get constant node graph if ( p->pRoot->fPhase ) pGraph = Dec_GraphCreateConst1(); else pGraph = Dec_GraphCreateConst0(); return pGraph; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p ) { Abc_Obj_t * pObj; unsigned * puData, * puDataR; int i, w; puDataR = (unsigned *)p->pRoot->pData; Vec_PtrForEachEntryStop( Abc_Obj_t *, p->vDivs, pObj, i, p->nDivs ) { puData = (unsigned *)pObj->pData; for ( w = 0; w < p->nWords; w++ ) // if ( puData[w] != puDataR[w] ) if ( (puData[w] ^ puDataR[w]) & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) return Abc_ManResubQuit0( p->pRoot, pObj ); } return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required ) { Abc_Obj_t * pObj0, * pObj1; unsigned * puData0, * puData1, * puDataR; int i, k, w; puDataR = (unsigned *)p->pRoot->pData; // check positive unate divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UP, pObj0, i ) { puData0 = (unsigned *)pObj0->pData; Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UP, pObj1, k, i + 1 ) { puData1 = (unsigned *)pObj1->pData; for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] | puData1[w]) != puDataR[w] ) if ( ((puData0[w] | puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { p->nUsedNode1Or++; return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 1 ); } } } // check negative unate divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UN, pObj0, i ) { puData0 = (unsigned *)pObj0->pData; Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UN, pObj1, k, i + 1 ) { puData1 = (unsigned *)pObj1->pData; for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] & puData1[w]) != puDataR[w] ) if ( ((puData0[w] & puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { p->nUsedNode1And++; return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 0 ); } } } return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ) { Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObjMax, * pObjMin0 = NULL, * pObjMin1 = NULL; unsigned * puData0, * puData1, * puData2, * puDataR; int i, k, j, w, LevelMax; puDataR = (unsigned *)p->pRoot->pData; // check positive unate divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UP, pObj0, i ) { puData0 = (unsigned *)pObj0->pData; Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UP, pObj1, k, i + 1 ) { puData1 = (unsigned *)pObj1->pData; Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UP, pObj2, j, k + 1 ) { puData2 = (unsigned *)pObj2->pData; for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] | puData1[w] | puData2[w]) != puDataR[w] ) if ( ((puData0[w] | puData1[w] | puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { LevelMax = Abc_MaxInt( pObj0->Level, Abc_MaxInt(pObj1->Level, pObj2->Level) ); assert( LevelMax <= Required - 1 ); pObjMax = NULL; if ( (int)pObj0->Level == LevelMax ) pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2; if ( (int)pObj1->Level == LevelMax ) { if ( pObjMax ) continue; pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2; } if ( (int)pObj2->Level == LevelMax ) { if ( pObjMax ) continue; pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1; } p->nUsedNode2Or++; assert(pObjMin0); assert(pObjMin1); return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 1 ); } } } } // check negative unate divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UN, pObj0, i ) { puData0 = (unsigned *)pObj0->pData; Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UN, pObj1, k, i + 1 ) { puData1 = (unsigned *)pObj1->pData; Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs1UN, pObj2, j, k + 1 ) { puData2 = (unsigned *)pObj2->pData; for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] & puData1[w] & puData2[w]) != puDataR[w] ) if ( ((puData0[w] & puData1[w] & puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; if ( w == p->nWords ) { LevelMax = Abc_MaxInt( pObj0->Level, Abc_MaxInt(pObj1->Level, pObj2->Level) ); assert( LevelMax <= Required - 1 ); pObjMax = NULL; if ( (int)pObj0->Level == LevelMax ) pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2; if ( (int)pObj1->Level == LevelMax ) { if ( pObjMax ) continue; pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2; } if ( (int)pObj2->Level == LevelMax ) { if ( pObjMax ) continue; pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1; } p->nUsedNode2And++; assert(pObjMin0); assert(pObjMin1); return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 0 ); } } } } return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required ) { Abc_Obj_t * pObj0, * pObj1, * pObj2; unsigned * puData0, * puData1, * puData2, * puDataR; int i, k, w; puDataR = (unsigned *)p->pRoot->pData; // check positive unate divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UP, pObj0, i ) { puData0 = (unsigned *)pObj0->pData; Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs2UP0, pObj1, k ) { pObj2 = (Abc_Obj_t *)Vec_PtrEntry( p->vDivs2UP1, k ); puData1 = (unsigned *)Abc_ObjRegular(pObj1)->pData; puData2 = (unsigned *)Abc_ObjRegular(pObj2)->pData; if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) { for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] | (puData1[w] | puData2[w])) != puDataR[w] ) if ( ((puData0[w] | (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; } else if ( Abc_ObjIsComplement(pObj1) ) { for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] | (~puData1[w] & puData2[w])) != puDataR[w] ) if ( ((puData0[w] | (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; } else if ( Abc_ObjIsComplement(pObj2) ) { for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] | (puData1[w] & ~puData2[w])) != puDataR[w] ) if ( ((puData0[w] | (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; } else { for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] | (puData1[w] & puData2[w])) != puDataR[w] ) if ( ((puData0[w] | (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; } if ( w == p->nWords ) { p->nUsedNode2OrAnd++; return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 1 ); } } } // check negative unate divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs1UN, pObj0, i ) { puData0 = (unsigned *)pObj0->pData; Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs2UN0, pObj1, k ) { pObj2 = (Abc_Obj_t *)Vec_PtrEntry( p->vDivs2UN1, k ); puData1 = (unsigned *)Abc_ObjRegular(pObj1)->pData; puData2 = (unsigned *)Abc_ObjRegular(pObj2)->pData; if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) { for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] & (puData1[w] | puData2[w])) != puDataR[w] ) if ( ((puData0[w] & (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; } else if ( Abc_ObjIsComplement(pObj1) ) { for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] & (~puData1[w] & puData2[w])) != puDataR[w] ) if ( ((puData0[w] & (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; } else if ( Abc_ObjIsComplement(pObj2) ) { for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] & (puData1[w] & ~puData2[w])) != puDataR[w] ) if ( ((puData0[w] & (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; } else { for ( w = 0; w < p->nWords; w++ ) // if ( (puData0[w] & (puData1[w] & puData2[w])) != puDataR[w] ) if ( ((puData0[w] & (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; } if ( w == p->nWords ) { p->nUsedNode2AndOr++; return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 0 ); } } } return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ) { Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObj3; unsigned * puData0, * puData1, * puData2, * puData3, * puDataR; int i, k, w = 0, Flag; puDataR = (unsigned *)p->pRoot->pData; // check positive unate divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs2UP0, pObj0, i ) { pObj1 = (Abc_Obj_t *)Vec_PtrEntry( p->vDivs2UP1, i ); puData0 = (unsigned *)Abc_ObjRegular(pObj0)->pData; puData1 = (unsigned *)Abc_ObjRegular(pObj1)->pData; Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2); Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs2UP0, pObj2, k, i + 1 ) { pObj3 = (Abc_Obj_t *)Vec_PtrEntry( p->vDivs2UP1, k ); puData2 = (unsigned *)Abc_ObjRegular(pObj2)->pData; puData3 = (unsigned *)Abc_ObjRegular(pObj3)->pData; Flag = (Flag & 12) | ((int)Abc_ObjIsComplement(pObj2) << 1) | (int)Abc_ObjIsComplement(pObj3); assert( Flag < 16 ); switch( Flag ) { case 0: // 0000 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) if ( (((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 1: // 0001 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) if ( (((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 2: // 0010 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) if ( (((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 3: // 0011 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) if ( (((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 4: // 0100 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 5: // 0101 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 6: // 0110 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) if ( (((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 7: // 0111 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) if ( (((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 8: // 1000 for ( w = 0; w < p->nWords; w++ ) // if ( ((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) if ( (((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 9: // 1001 for ( w = 0; w < p->nWords; w++ ) // if ( ((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) if ( (((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 10: // 1010 for ( w = 0; w < p->nWords; w++ ) // if ( ((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) if ( (((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 11: // 1011 for ( w = 0; w < p->nWords; w++ ) // if ( ((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) if ( (((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 12: // 1100 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) if ( (((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set break; break; case 13: // 1101 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) if ( (((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) break; break; case 14: // 1110 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) if ( (((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) break; break; case 15: // 1111 for ( w = 0; w < p->nWords; w++ ) // if ( ((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) if ( (((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) break; break; } if ( w == p->nWords ) { p->nUsedNode3OrAnd++; return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 1 ); } } } /* // check negative unate divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs2UN0, pObj0, i ) { pObj1 = Vec_PtrEntry( p->vDivs2UN1, i ); puData0 = Abc_ObjRegular(pObj0)->pData; puData1 = Abc_ObjRegular(pObj1)->pData; Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2); Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs2UN0, pObj2, k, i + 1 ) { pObj3 = Vec_PtrEntry( p->vDivs2UN1, k ); puData2 = Abc_ObjRegular(pObj2)->pData; puData3 = Abc_ObjRegular(pObj3)->pData; Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3); assert( Flag < 16 ); switch( Flag ) { case 0: // 0000 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) break; break; case 1: // 0001 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) break; break; case 2: // 0010 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) break; break; case 3: // 0011 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) break; break; case 4: // 0100 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) break; break; case 5: // 0101 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) break; break; case 6: // 0110 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] & ~puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) break; break; case 7: // 0111 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] & ~puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) break; break; case 8: // 1000 for ( w = 0; w < p->nWords; w++ ) if ( ((~puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) break; break; case 9: // 1001 for ( w = 0; w < p->nWords; w++ ) if ( ((~puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) break; break; case 10: // 1010 for ( w = 0; w < p->nWords; w++ ) if ( ((~puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) break; break; case 11: // 1011 for ( w = 0; w < p->nWords; w++ ) if ( ((~puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) break; break; case 12: // 1100 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] | puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) break; break; case 13: // 1101 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] | puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) break; break; case 14: // 1110 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] | puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) break; break; case 15: // 1111 for ( w = 0; w < p->nWords; w++ ) if ( ((puData0[w] | puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) break; break; } if ( w == p->nWords ) { p->nUsedNode3AndOr++; return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 0 ); } } } */ return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManResubCleanup( Abc_ManRes_t * p ) { Abc_Obj_t * pObj; int i; Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pObj, i ) pObj->pData = NULL; Vec_PtrClear( p->vDivs ); p->pRoot = NULL; } /**Function************************************************************* Synopsis [Evaluates resubstution of one cut.] Description [Returns the graph to add if any.] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, int fUpdateLevel, int fVerbose ) { extern int Abc_NodeMffcInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ); Dec_Graph_t * pGraph; int Required; abctime clk; Required = fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY; assert( nSteps >= 0 ); assert( nSteps <= 3 ); p->pRoot = pRoot; p->nLeaves = Vec_PtrSize(vLeaves); p->nLastGain = -1; // collect the MFFC clk = Abc_Clock(); p->nMffc = Abc_NodeMffcInside( pRoot, vLeaves, p->vTemp ); p->timeMffc += Abc_Clock() - clk; assert( p->nMffc > 0 ); // collect the divisor nodes clk = Abc_Clock(); if ( !Abc_ManResubCollectDivs( p, pRoot, vLeaves, Required ) ) return NULL; p->timeDiv += Abc_Clock() - clk; p->nTotalDivs += p->nDivs; p->nTotalLeaves += p->nLeaves; // simulate the nodes clk = Abc_Clock(); Abc_ManResubSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords ); p->timeSim += Abc_Clock() - clk; clk = Abc_Clock(); // consider constants if ( (pGraph = Abc_ManResubQuit( p )) ) { p->nUsedNodeC++; p->nLastGain = p->nMffc; return pGraph; } // consider equal nodes if ( (pGraph = Abc_ManResubDivs0( p )) ) { p->timeRes1 += Abc_Clock() - clk; p->nUsedNode0++; p->nLastGain = p->nMffc; return pGraph; } if ( nSteps == 0 || p->nMffc == 1 ) { p->timeRes1 += Abc_Clock() - clk; return NULL; } // get the one level divisors Abc_ManResubDivsS( p, Required ); // consider one node if ( (pGraph = Abc_ManResubDivs1( p, Required )) ) { p->timeRes1 += Abc_Clock() - clk; p->nLastGain = p->nMffc - 1; return pGraph; } p->timeRes1 += Abc_Clock() - clk; if ( nSteps == 1 || p->nMffc == 2 ) return NULL; clk = Abc_Clock(); // consider triples if ( (pGraph = Abc_ManResubDivs12( p, Required )) ) { p->timeRes2 += Abc_Clock() - clk; p->nLastGain = p->nMffc - 2; return pGraph; } p->timeRes2 += Abc_Clock() - clk; // get the two level divisors clk = Abc_Clock(); Abc_ManResubDivsD( p, Required ); p->timeResD += Abc_Clock() - clk; // consider two nodes clk = Abc_Clock(); if ( (pGraph = Abc_ManResubDivs2( p, Required )) ) { p->timeRes2 += Abc_Clock() - clk; p->nLastGain = p->nMffc - 2; return pGraph; } p->timeRes2 += Abc_Clock() - clk; if ( nSteps == 2 || p->nMffc == 3 ) return NULL; // consider two nodes clk = Abc_Clock(); if ( (pGraph = Abc_ManResubDivs3( p, Required )) ) { p->timeRes3 += Abc_Clock() - clk; p->nLastGain = p->nMffc - 3; return pGraph; } p->timeRes3 += Abc_Clock() - clk; if ( nSteps == 3 || p->nLeavesMax == 4 ) return NULL; return NULL; } /**Function************************************************************* Synopsis [Computes the volume and checks if the cut is feasible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CutVolumeCheck_rec( Abc_Obj_t * pObj ) { // quit if the node is visited (or if it is a leaf) if ( Abc_NodeIsTravIdCurrent(pObj) ) return 0; Abc_NodeSetTravIdCurrent(pObj); // report the error if ( Abc_ObjIsCi(pObj) ) printf( "Abc_CutVolumeCheck() ERROR: The set of nodes is not a cut!\n" ); // count the number of nodes in the leaves return 1 + Abc_CutVolumeCheck_rec( Abc_ObjFanin0(pObj) ) + Abc_CutVolumeCheck_rec( Abc_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Computes the volume and checks if the cut is feasible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) { Abc_Obj_t * pObj; int i; // mark the leaves Abc_NtkIncrementTravId( pNode->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); // traverse the nodes starting from the given one and count them return Abc_CutVolumeCheck_rec( pNode ); } /**Function************************************************************* Synopsis [Computes the factor cut of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_CutFactor_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) { if ( pObj->fMarkA ) return; if ( Abc_ObjIsCi(pObj) || (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) ) { Vec_PtrPush( vLeaves, pObj ); pObj->fMarkA = 1; return; } Abc_CutFactor_rec( Abc_ObjFanin0(pObj), vLeaves ); Abc_CutFactor_rec( Abc_ObjFanin1(pObj), vLeaves ); } /**Function************************************************************* Synopsis [Computes the factor cut of the node.] Description [Factor-cut is the cut at a node in terms of factor-nodes. Factor-nodes are roots of the node trees (MUXes/EXORs are counted as single nodes). Factor-cut is unique for the given node.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_CutFactor( Abc_Obj_t * pNode ) { Vec_Ptr_t * vLeaves; Abc_Obj_t * pObj; int i; assert( !Abc_ObjIsCi(pNode) ); vLeaves = Vec_PtrAlloc( 10 ); Abc_CutFactor_rec( Abc_ObjFanin0(pNode), vLeaves ); Abc_CutFactor_rec( Abc_ObjFanin1(pNode), vLeaves ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->fMarkA = 0; return vLeaves; } /**Function************************************************************* Synopsis [Cut computation.] Description [This cut computation works as follows: It starts with the factor cut at the node. If the factor-cut is large, quit. It supports the set of leaves of the cut under construction and labels all nodes in the cut under construction, including the leaves. It computes the factor-cuts of the leaves and checks if it is easible to add any of them. If it is, it randomly chooses one feasible and continues.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ) { Vec_Ptr_t * vLeaves, * vFactors, * vFact, * vNext; Vec_Int_t * vFeasible; Abc_Obj_t * pLeaf, * pTemp; int i, k, Counter, RandLeaf; int BestCut, BestShare; assert( Abc_ObjIsNode(pNode) ); // get one factor-cut vLeaves = Abc_CutFactor( pNode ); if ( Vec_PtrSize(vLeaves) > nLeavesMax ) { Vec_PtrFree(vLeaves); return NULL; } if ( Vec_PtrSize(vLeaves) == nLeavesMax ) return vLeaves; // initialize the factor cuts for the leaves vFactors = Vec_PtrAlloc( nLeavesMax ); Abc_NtkIncrementTravId( pNode->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pLeaf, i ) { Abc_NodeSetTravIdCurrent( pLeaf ); if ( Abc_ObjIsCi(pLeaf) ) Vec_PtrPush( vFactors, NULL ); else Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) ); } // construct larger factor cuts vFeasible = Vec_IntAlloc( nLeavesMax ); while ( 1 ) { BestCut = -1, BestShare = -1; // find the next feasible cut to add Vec_IntClear( vFeasible ); Vec_PtrForEachEntry( Vec_Ptr_t *, vFactors, vFact, i ) { if ( vFact == NULL ) continue; // count the number of unmarked leaves of this factor cut Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vFact, pTemp, k ) Counter += !Abc_NodeIsTravIdCurrent(pTemp); // if the number of new leaves is smaller than the diff, it is feasible if ( Counter <= nLeavesMax - Vec_PtrSize(vLeaves) + 1 ) { Vec_IntPush( vFeasible, i ); if ( BestCut == -1 || BestShare < Vec_PtrSize(vFact) - Counter ) BestCut = i, BestShare = Vec_PtrSize(vFact) - Counter; } } // quit if there is no feasible factor cuts if ( Vec_IntSize(vFeasible) == 0 ) break; // randomly choose one leaf and get its factor cut // RandLeaf = Vec_IntEntry( vFeasible, rand() % Vec_IntSize(vFeasible) ); // choose the cut that has most sharing with the other cuts RandLeaf = BestCut; pLeaf = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, RandLeaf ); vNext = (Vec_Ptr_t *)Vec_PtrEntry( vFactors, RandLeaf ); // unmark this leaf Abc_NodeSetTravIdPrevious( pLeaf ); // remove this cut from the leaves and factor cuts for ( i = RandLeaf; i < Vec_PtrSize(vLeaves)-1; i++ ) { Vec_PtrWriteEntry( vLeaves, i, Vec_PtrEntry(vLeaves, i+1) ); Vec_PtrWriteEntry( vFactors, i, Vec_PtrEntry(vFactors,i+1) ); } Vec_PtrShrink( vLeaves, Vec_PtrSize(vLeaves) -1 ); Vec_PtrShrink( vFactors, Vec_PtrSize(vFactors)-1 ); // add new leaves, compute their factor cuts Vec_PtrForEachEntry( Abc_Obj_t *, vNext, pLeaf, i ) { if ( Abc_NodeIsTravIdCurrent(pLeaf) ) continue; Abc_NodeSetTravIdCurrent( pLeaf ); Vec_PtrPush( vLeaves, pLeaf ); if ( Abc_ObjIsCi(pLeaf) ) Vec_PtrPush( vFactors, NULL ); else Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) ); } Vec_PtrFree( vNext ); assert( Vec_PtrSize(vLeaves) <= nLeavesMax ); if ( Vec_PtrSize(vLeaves) == nLeavesMax ) break; } // remove temporary storage Vec_PtrForEachEntry( Vec_Ptr_t *, vFactors, vFact, i ) if ( vFact ) Vec_PtrFree( vFact ); Vec_PtrFree( vFactors ); Vec_IntFree( vFeasible ); return vLeaves; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcRewrite.c000066400000000000000000000306671300674244400241130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcRewrite.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Technology-independent resynthesis of the AIG based on DAG aware rewriting.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcRewrite.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/rwr/rwr.h" #include "bool/dec/dec.h" ABC_NAMESPACE_IMPL_START /* The ideas realized in this package are inspired by the paper: Per Bjesse, Arne Boralv, "DAG-aware circuit compression for formal verification", Proc. ICCAD 2004, pp. 42-49. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ); static void Abc_NodePrintCuts( Abc_Obj_t * pNode ); static void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); extern void Abc_PlaceBegin( Abc_Ntk_t * pNtk ); extern void Abc_PlaceEnd( Abc_Ntk_t * pNtk ); extern void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs incremental rewriting of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ) { extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); ProgressBar * pProgress; Cut_Man_t * pManCut; Rwr_Man_t * pManRwr; Abc_Obj_t * pNode; // Vec_Ptr_t * vAddedCells = NULL, * vUpdatedNets = NULL; Dec_Graph_t * pGraph; int i, nNodes, nGain, fCompl; abctime clk, clkStart = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); // cleanup the AIG Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); /* { Vec_Vec_t * vParts; vParts = Abc_NtkPartitionSmart( pNtk, 50, 1 ); Vec_VecFree( vParts ); } */ // start placement package // if ( fPlaceEnable ) // { // Abc_PlaceBegin( pNtk ); // vAddedCells = Abc_AigUpdateStart( pNtk->pManFunc, &vUpdatedNets ); // } // start the rewriting manager pManRwr = Rwr_ManStart( 0 ); if ( pManRwr == NULL ) return 0; // compute the reverse levels if level update is requested if ( fUpdateLevel ) Abc_NtkStartReverseLevels( pNtk, 0 ); // start the cut manager clk = Abc_Clock(); pManCut = Abc_NtkStartCutManForRewrite( pNtk ); Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk ); pNtk->pManCut = pManCut; if ( fVeryVerbose ) Rwr_ScoresClean( pManRwr ); // resynthesize each node once pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // stop if all nodes have been tried once if ( i >= nNodes ) break; // skip persistant nodes if ( Abc_NodeIsPersistant(pNode) ) continue; // skip the nodes with many fanouts if ( Abc_ObjFanoutNum(pNode) > 1000 ) continue; // for each cut, try to resynthesize it nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUpdateLevel, fUseZeros, fPlaceEnable ); if ( !(nGain > 0 || (nGain == 0 && fUseZeros)) ) continue; // if we end up here, a rewriting step is accepted // get hold of the new subgraph to be added to the AIG pGraph = (Dec_Graph_t *)Rwr_ManReadDecs(pManRwr); fCompl = Rwr_ManReadCompl(pManRwr); // reset the array of the changed nodes if ( fPlaceEnable ) Abc_AigUpdateReset( (Abc_Aig_t *)pNtk->pManFunc ); // complement the FF if needed if ( fCompl ) Dec_GraphComplement( pGraph ); clk = Abc_Clock(); Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); Rwr_ManAddTimeUpdate( pManRwr, Abc_Clock() - clk ); if ( fCompl ) Dec_GraphComplement( pGraph ); // use the array of changed nodes to update placement // if ( fPlaceEnable ) // Abc_PlaceUpdate( vAddedCells, vUpdatedNets ); } Extra_ProgressBarStop( pProgress ); Rwr_ManAddTimeTotal( pManRwr, Abc_Clock() - clkStart ); // print stats pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk); if ( fVerbose ) Rwr_ManPrintStats( pManRwr ); // Rwr_ManPrintStatsFile( pManRwr ); if ( fVeryVerbose ) Rwr_ScoresReport( pManRwr ); // delete the managers Rwr_ManStop( pManRwr ); Cut_ManStop( pManCut ); pNtk->pManCut = NULL; // start placement package // if ( fPlaceEnable ) // { // Abc_PlaceEnd( pNtk ); // Abc_AigUpdateStop( pNtk->pManFunc ); // } // put the nodes into the DFS order and reassign their IDs { // abctime clk = Abc_Clock(); Abc_NtkReassignIds( pNtk ); // ABC_PRT( "time", Abc_Clock() - clk ); } // Abc_AigCheckFaninOrder( pNtk->pManFunc ); // fix the levels if ( fUpdateLevel ) Abc_NtkStopReverseLevels( pNtk ); else Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkRewrite: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Starts the cut manager for rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ) { static Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pManCut; Abc_Obj_t * pObj; int i; // start the cut manager memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = 4; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 250; // the max number of cuts kept at a node pParams->fTruth = 1; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fSeq = 0; // compute sequential cuts pParams->fDrop = 0; // drop cuts on the fly pParams->fVerbose = 0; // the verbosiness flag pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); pManCut = Cut_ManStart( pParams ); if ( pParams->fDrop ) Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); // set cuts for PIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( pManCut, pObj->Id ); return pManCut; } /**Function************************************************************* Synopsis [Prints the cuts at the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodePrintCuts( Abc_Obj_t * pNode ) { Vec_Ptr_t * vCuts; Cut_Cut_t * pCut; int k; printf( "\nNode %s\n", Abc_ObjName(pNode) ); vCuts = (Vec_Ptr_t *)pNode->pCopy; Vec_PtrForEachEntry( Cut_Cut_t *, vCuts, pCut, k ) { Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 ); printf( " " ); Cut_CutPrint( pCut, 0 ); printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManRewritePrintDivs( Vec_Ptr_t * vDivs, int nLeaves ) { Abc_Obj_t * pFanin, * pNode, * pRoot; int i, k; pRoot = (Abc_Obj_t *)Vec_PtrEntryLast(vDivs); // print the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pNode, i ) { if ( i < nLeaves ) { printf( "%6d : %c\n", pNode->Id, 'a'+i ); continue; } printf( "%6d : %2d = ", pNode->Id, i ); // find the first fanin Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pFanin, k ) if ( Abc_ObjFanin0(pNode) == pFanin ) break; if ( k < nLeaves ) printf( "%c", 'a' + k ); else printf( "%d", k ); printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); // find the second fanin Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pFanin, k ) if ( Abc_ObjFanin1(pNode) == pFanin ) break; if ( k < nLeaves ) printf( "%c", 'a' + k ); else printf( "%d", k ); printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); if ( pNode == pRoot ) printf( " root" ); printf( "\n" ); } printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManShowCutCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vDivs ) { if ( Abc_NodeIsTravIdCurrent(pNode) ) return; Abc_NodeSetTravIdCurrent(pNode); Abc_ManShowCutCone_rec( Abc_ObjFanin0(pNode), vDivs ); Abc_ManShowCutCone_rec( Abc_ObjFanin1(pNode), vDivs ); Vec_PtrPush( vDivs, pNode ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) { Abc_Ntk_t * pNtk = pNode->pNtk; Abc_Obj_t * pObj; Vec_Ptr_t * vDivs; int i; vDivs = Vec_PtrAlloc( 100 ); Abc_NtkIncrementTravId( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) { Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pObj) ); Vec_PtrPush( vDivs, Abc_ObjRegular(pObj) ); } Abc_ManShowCutCone_rec( pNode, vDivs ); Abc_ManRewritePrintDivs( vDivs, Vec_PtrSize(vLeaves) ); Vec_PtrFree( vDivs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_RwrExpWithCut_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, int fUseA ) { if ( Vec_PtrFind(vLeaves, pNode) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pNode)) >= 0 ) { if ( fUseA ) Abc_ObjRegular(pNode)->fMarkA = 1; else Abc_ObjRegular(pNode)->fMarkB = 1; return; } assert( Abc_ObjIsNode(pNode) ); Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, fUseA ); Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, fUseA ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_RwrExpWithCut( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) { Abc_Obj_t * pObj; int i, CountA, CountB; Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, 1 ); Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, 0 ); CountA = CountB = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) { CountA += Abc_ObjRegular(pObj)->fMarkA; CountB += Abc_ObjRegular(pObj)->fMarkB; Abc_ObjRegular(pObj)->fMarkA = 0; Abc_ObjRegular(pObj)->fMarkB = 0; } printf( "(%d,%d:%d) ", CountA, CountB, CountA+CountB-Vec_PtrSize(vLeaves) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcRpo.c000066400000000000000000000323731300674244400232260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcRpo.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Rpo package.] Synopsis [Procedures for executing RPO.] Author [Mayler G. A. Martins / Vinicius Callegaro] Affiliation [UFRGS] Date [Ver. 1.0. Started - May 08, 2013.] Revision [$Id: abcRpo.c,v 1.00 2013/05/08 00:00:00 mgamartins Exp $] ***********************************************************************/ #include "misc/extra/extra.h" #include "bool/rpo/rpo.h" #include "bool/rpo/literal.h" ABC_NAMESPACE_IMPL_START // data-structure to store a bunch of truth tables typedef struct Rpo_TtStore_t_ Rpo_TtStore_t; struct Rpo_TtStore_t_ { int nVars; int nWords; int nFuncs; word ** pFuncs; }; // read/write/flip i-th bit of a bit string table: static inline int Abc_TruthGetBit(word * p, int i) { return (int) (p[i >> 6] >> (i & 63)) & 1; } static inline void Abc_TruthSetBit(word * p, int i) { p[i >> 6] |= (((word) 1) << (i & 63)); } static inline void Abc_TruthXorBit(word * p, int i) { p[i >> 6] ^= (((word) 1) << (i & 63)); } // read/write k-th digit d of a hexadecimal number: static inline int Abc_TruthGetHex(word * p, int k) { return (int) (p[k >> 4] >> ((k << 2) & 63)) & 15; } static inline void Abc_TruthSetHex(word * p, int k, int d) { p[k >> 4] |= (((word) d) << ((k << 2) & 63)); } static inline void Abc_TruthXorHex(word * p, int k, int d) { p[k >> 4] ^= (((word) d) << ((k << 2) & 63)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // read one hex character static inline int Abc_TruthReadHexDigit(char HexChar) { if (HexChar >= '0' && HexChar <= '9') return HexChar - '0'; if (HexChar >= 'A' && HexChar <= 'F') return HexChar - 'A' + 10; if (HexChar >= 'a' && HexChar <= 'f') return HexChar - 'a' + 10; assert(0); // not a hexadecimal symbol return -1; // return value which makes no sense } // write one hex character static inline void Abc_TruthWriteHexDigit(FILE * pFile, int HexDigit) { assert(HexDigit >= 0 && HexDigit < 16); if (HexDigit < 10) fprintf(pFile, "%d", HexDigit); else fprintf(pFile, "%c", 'A' + HexDigit - 10); } // read one truth table in hexadecimal static void Abc_TruthReadHex(word * pTruth, char * pString, int nVars) { int nWords = (nVars < 7) ? 1 : (1 << (nVars - 6)); int k, Digit, nDigits = (nVars < 7) ? (1 << (nVars-2)) : (nWords << 4); char EndSymbol; // skip the first 2 symbols if they are "0x" if (pString[0] == '0' && pString[1] == 'x') pString += 2; // get the last symbol EndSymbol = pString[nDigits]; // the end symbol of the TT (the one immediately following hex digits) // should be one of the following: space, a new-line, or a zero-terminator // (note that on Windows symbols '\r' can be inserted before each '\n') assert(EndSymbol == ' ' || EndSymbol == '\n' || EndSymbol == '\r' || EndSymbol == '\0'); // read hexadecimal digits in the reverse order // (the last symbol in the string is the least significant digit) for (k = 0; k < nDigits; k++) { Digit = Abc_TruthReadHexDigit(pString[nDigits - 1 - k]); assert(Digit >= 0 && Digit < 16); Abc_TruthSetHex(pTruth, k, Digit); } } // write one truth table in hexadecimal (do not add end-of-line!) static void Abc_TruthWriteHex(FILE * pFile, word * pTruth, int nVars) { int nDigits, Digit, k; nDigits = (1 << (nVars - 2)); for (k = 0; k < nDigits; k++) { Digit = Abc_TruthGetHex(pTruth, k); assert(Digit >= 0 && Digit < 16); Abc_TruthWriteHexDigit(pFile, Digit); } } /**Function************************************************************* Synopsis [Allocate/Deallocate storage for truth tables..] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Rpo_TtStore_t * Abc_TruthStoreAlloc(int nVars, int nFuncs) { Rpo_TtStore_t * p; int i; p = (Rpo_TtStore_t *) malloc(sizeof (Rpo_TtStore_t)); p->nVars = nVars; p->nWords = (nVars < 7) ? 1 : (1 << (nVars - 6)); p->nFuncs = nFuncs; // alloc storage for 'nFuncs' truth tables as one chunk of memory p->pFuncs = (word **) malloc((sizeof (word *) + sizeof (word) * p->nWords) * p->nFuncs); // assign and clean the truth table storage p->pFuncs[0] = (word *) (p->pFuncs + p->nFuncs); memset(p->pFuncs[0], 0, sizeof (word) * p->nWords * p->nFuncs); // split it up into individual truth tables for (i = 1; i < p->nFuncs; i++) p->pFuncs[i] = p->pFuncs[i - 1] + p->nWords; return p; } static Rpo_TtStore_t * Abc_TruthStoreAlloc2(int nVars, int nFuncs, word * pBuffer) { Rpo_TtStore_t * p; int i; p = (Rpo_TtStore_t *) malloc(sizeof (Rpo_TtStore_t)); p->nVars = nVars; p->nWords = (nVars < 7) ? 1 : (1 << (nVars - 6)); p->nFuncs = nFuncs; // alloc storage for 'nFuncs' truth tables as one chunk of memory p->pFuncs = (word **) malloc(sizeof (word *) * p->nFuncs); // assign and clean the truth table storage p->pFuncs[0] = pBuffer; // split it up into individual truth tables for (i = 1; i < p->nFuncs; i++) p->pFuncs[i] = p->pFuncs[i - 1] + p->nWords; return p; } static void Abc_TtStoreFree(Rpo_TtStore_t * p, int nVarNum) { if (nVarNum >= 0) ABC_FREE(p->pFuncs[0]); ABC_FREE(p->pFuncs); ABC_FREE(p); } /**Function************************************************************* Synopsis [Read file contents.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ extern int Abc_FileSize(char * pFileName); /**Function************************************************************* Synopsis [Read file contents.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ extern char * Abc_FileRead(char * pFileName); /**Function************************************************************* Synopsis [Determine the number of variables by reading the first line.] Description [Determine the number of functions by counting the lines.] SideEffects [] SeeAlso [] ***********************************************************************/ extern void Abc_TruthGetParams(char * pFileName, int * pnVars, int * pnTruths); /**Function************************************************************* Synopsis [Read truth tables from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_TruthStoreRead(char * pFileName, Rpo_TtStore_t * p) { char * pContents; int i, nLines; pContents = Abc_FileRead(pFileName); if (pContents == NULL) return; // here it is assumed (without checking!) that each line of the file // begins with a string of hexadecimal chars followed by space // the file will be read till the first empty line (pContents[i] == '\n') // (note that Abc_FileRead() added several empty lines at the end of the file contents) for (nLines = i = 0; pContents[i] != '\n';) { // read one line Abc_TruthReadHex(p->pFuncs[nLines++], &pContents[i], p->nVars); // skip till after the end-of-line symbol // (note that end-of-line symbol is also skipped) while (pContents[i++] != '\n'); } // adjust the number of functions read // (we may have allocated more storage because some lines in the file were empty) assert(p->nFuncs >= nLines); p->nFuncs = nLines; ABC_FREE(pContents); } /**Function************************************************************* Synopsis [Write truth tables into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_TtStoreWrite(char * pFileName, Rpo_TtStore_t * p, int fBinary) { FILE * pFile; int i, nBytes = 8 * Abc_Truth6WordNum(p->nVars); pFile = fopen(pFileName, "wb"); if (pFile == NULL) { printf("Cannot open file \"%s\" for writing.\n", pFileName); return; } for (i = 0; i < p->nFuncs; i++) { if (fBinary) fwrite(p->pFuncs[i], nBytes, 1, pFile); else Abc_TruthWriteHex(pFile, p->pFuncs[i], p->nVars), fprintf(pFile, "\n"); } fclose(pFile); } /**Function************************************************************* Synopsis [Read truth tables from input file and write them into output file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Rpo_TtStore_t * Abc_TtStoreLoad(char * pFileName, int nVarNum) { Rpo_TtStore_t * p; if (nVarNum < 0) { int nVars, nTruths; // figure out how many truth table and how many variables Abc_TruthGetParams(pFileName, &nVars, &nTruths); if (nVars < 2 || nVars > 16 || nTruths == 0) return NULL; // allocate data-structure p = Abc_TruthStoreAlloc(nVars, nTruths); // read info from file Abc_TruthStoreRead(pFileName, p); } else { char * pBuffer; int nFileSize = Abc_FileSize(pFileName); int nBytes = (1 << (nVarNum - 3)); // why mishchencko put -3? ### int nTruths = nFileSize / nBytes; //Abc_Print(-2,"nFileSize=%d,nTruths=%d\n",nFileSize, nTruths); if (nFileSize == -1) return NULL; assert(nVarNum >= 6); if (nFileSize % nBytes != 0) Abc_Print(0, "The file size (%d) is divided by the truth table size (%d) with remainder (%d).\n", nFileSize, nBytes, nFileSize % nBytes); // read file contents pBuffer = Abc_FileRead(pFileName); // allocate data-structure p = Abc_TruthStoreAlloc2(nVarNum, nTruths, (word *) pBuffer); } return p; } /**Function************************************************************* Synopsis [Apply decomposition to the truth table.] Description [Returns the number of AIG nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthRpoPerform(Rpo_TtStore_t * p, int nThreshold, int fVerbose) { clock_t clk = clock(); int i; int rpoCount = 0; Literal_t* lit; float percent; for (i = 0; i < p->nFuncs; i++) { // if(i>1000) { // continue; // } //// // if(i!= 2196 ) { //5886 // continue; // } if(fVerbose) { Abc_Print(-2,"%d: ", i+1); } lit = Rpo_Factorize((unsigned *) p->pFuncs[i], p->nVars, nThreshold, fVerbose); if (lit != NULL) { if(fVerbose) { Abc_Print(-2, "Solution : %s\n", lit->expression->pArray); Abc_Print(-2, "\n\n"); } Lit_Free(lit); rpoCount++; } else { if(fVerbose) { Abc_Print(-2, "null\n"); Abc_Print(-2, "\n\n"); } } } percent = (rpoCount * 100.0) / p->nFuncs; Abc_Print(-2,"%d of %d (%.2f %%) functions are RPO.\n", rpoCount,p->nFuncs,percent); Abc_PrintTime(1, "Time", clock() - clk); } /**Function************************************************************* Synopsis [Apply decomposition to truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TruthRpoTest(char * pFileName, int nVarNum, int nThreshold, int fVerbose) { Rpo_TtStore_t * p; // allocate data-structure // if (fVerbose) { // Abc_Print(-2, "Number of variables = %d\n", nVarNum); // } p = Abc_TtStoreLoad(pFileName, nVarNum); if (fVerbose) { Abc_Print(-2, "Number of variables = %d\n", p->nVars); } // consider functions from the file Abc_TruthRpoPerform(p, nThreshold, fVerbose); // delete data-structure Abc_TtStoreFree(p, nVarNum); // printf( "Finished decomposing truth tables from file \"%s\".\n", pFileName ); } /**Function************************************************************* Synopsis [Testbench for decomposition algorithms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_RpoTest(char * pFileName, int nVarNum,int nThreshold, int fVerbose) { if (fVerbose) { printf("Using truth tables from file \"%s\"...\n", pFileName); } Abc_TruthRpoTest(pFileName, nVarNum, nThreshold, fVerbose); fflush(stdout); return 0; } /////////////////////ert truth table to /////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcRr.c000066400000000000000000001024571300674244400230520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcRr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Redundancy removal.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "proof/fraig/fraig.h" #include "opt/sim/sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Abc_RRMan_t_ Abc_RRMan_t; struct Abc_RRMan_t_ { // the parameters Abc_Ntk_t * pNtk; // the network int nFaninLevels; // the number of fanin levels int nFanoutLevels; // the number of fanout levels // the node/fanin/fanout Abc_Obj_t * pNode; // the node Abc_Obj_t * pFanin; // the fanin Abc_Obj_t * pFanout; // the fanout // the intermediate cones Vec_Ptr_t * vFaninLeaves; // the leaves of the fanin cone Vec_Ptr_t * vFanoutRoots; // the roots of the fanout cone // the window Vec_Ptr_t * vLeaves; // the leaves of the window Vec_Ptr_t * vCone; // the internal nodes of the window Vec_Ptr_t * vRoots; // the roots of the window Abc_Ntk_t * pWnd; // the window derived for the edge // the miter Abc_Ntk_t * pMiter; // the miter derived from the window Prove_Params_t * pParams; // the miter proving parameters // statistical variables int nNodesOld; // the old number of nodes int nLevelsOld; // the old number of levels int nEdgesTried; // the number of nodes tried int nEdgesRemoved; // the number of nodes proved abctime timeWindow; // the time to construct the window abctime timeMiter; // the time to construct the miter abctime timeProve; // the time to prove the miter abctime timeUpdate; // the network update time abctime timeTotal; // the total runtime }; static Abc_RRMan_t * Abc_RRManStart(); static void Abc_RRManStop( Abc_RRMan_t * p ); static void Abc_RRManPrintStats( Abc_RRMan_t * p ); static void Abc_RRManClean( Abc_RRMan_t * p ); static int Abc_NtkRRProve( Abc_RRMan_t * p ); static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ); static int Abc_NtkRRWindow( Abc_RRMan_t * p ); static int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ); static int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ); static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ); static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ); static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ); static void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ); static void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Removes stuck-at redundancies.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ) { ProgressBar * pProgress; Abc_RRMan_t * p; Abc_Obj_t * pNode, * pFanin, * pFanout; int i, k, m, nNodes, RetValue; abctime clk, clkTotal = Abc_Clock(); // start the manager p = Abc_RRManStart(); p->pNtk = pNtk; p->nFaninLevels = nFaninLevels; p->nFanoutLevels = nFanoutLevels; p->nNodesOld = Abc_NtkNodeNum(pNtk); p->nLevelsOld = Abc_AigLevel(pNtk); // remember latch values // Abc_NtkForEachLatch( pNtk, pNode, i ) // pNode->pNext = pNode->pData; // go through the nodes Abc_NtkCleanCopy(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); Abc_NtkRRSimulateStart(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // stop if all nodes have been tried once if ( i >= nNodes ) break; // skip the constant node // if ( Abc_NodeIsConst(pNode) ) // continue; // skip persistant nodes if ( Abc_NodeIsPersistant(pNode) ) continue; // skip the nodes with many fanouts if ( Abc_ObjFanoutNum(pNode) > 1000 ) continue; // construct the window if ( !fUseFanouts ) { Abc_ObjForEachFanin( pNode, pFanin, k ) { // skip the nodes with only one fanout (tree nodes) if ( Abc_ObjFanoutNum(pFanin) == 1 ) continue; /* if ( pFanin->Id == 228 && pNode->Id == 2649 ) { int k = 0; } */ p->nEdgesTried++; Abc_RRManClean( p ); p->pNode = pNode; p->pFanin = pFanin; p->pFanout = NULL; clk = Abc_Clock(); RetValue = Abc_NtkRRWindow( p ); p->timeWindow += Abc_Clock() - clk; if ( !RetValue ) continue; /* if ( pFanin->Id == 228 && pNode->Id == 2649 ) { Abc_NtkShowAig( p->pWnd, 0 ); } */ clk = Abc_Clock(); RetValue = Abc_NtkRRProve( p ); p->timeMiter += Abc_Clock() - clk; if ( !RetValue ) continue; //printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k ); clk = Abc_Clock(); Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); p->timeUpdate += Abc_Clock() - clk; p->nEdgesRemoved++; break; } continue; } // use the fanouts Abc_ObjForEachFanin( pNode, pFanin, k ) Abc_ObjForEachFanout( pNode, pFanout, m ) { // skip the nodes with only one fanout (tree nodes) // if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 ) // continue; p->nEdgesTried++; Abc_RRManClean( p ); p->pNode = pNode; p->pFanin = pFanin; p->pFanout = pFanout; clk = Abc_Clock(); RetValue = Abc_NtkRRWindow( p ); p->timeWindow += Abc_Clock() - clk; if ( !RetValue ) continue; clk = Abc_Clock(); RetValue = Abc_NtkRRProve( p ); p->timeMiter += Abc_Clock() - clk; if ( !RetValue ) continue; clk = Abc_Clock(); Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); p->timeUpdate += Abc_Clock() - clk; p->nEdgesRemoved++; break; } } Abc_NtkRRSimulateStop(pNtk); Extra_ProgressBarStop( pProgress ); p->timeTotal = Abc_Clock() - clkTotal; if ( fVerbose ) Abc_RRManPrintStats( p ); Abc_RRManStop( p ); // restore latch values // Abc_NtkForEachLatch( pNtk, pNode, i ) // pNode->pData = pNode->pNext, pNode->pNext = NULL; // put the nodes into the DFS order and reassign their IDs Abc_NtkReassignIds( pNtk ); Abc_NtkLevel( pNtk ); // check if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkRR: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Start the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_RRMan_t * Abc_RRManStart() { Abc_RRMan_t * p; p = ABC_ALLOC( Abc_RRMan_t, 1 ); memset( p, 0, sizeof(Abc_RRMan_t) ); p->vFaninLeaves = Vec_PtrAlloc( 100 ); // the leaves of the fanin cone p->vFanoutRoots = Vec_PtrAlloc( 100 ); // the roots of the fanout cone p->vLeaves = Vec_PtrAlloc( 100 ); // the leaves of the window p->vCone = Vec_PtrAlloc( 100 ); // the internal nodes of the window p->vRoots = Vec_PtrAlloc( 100 ); // the roots of the window p->pParams = ABC_ALLOC( Prove_Params_t, 1 ); memset( p->pParams, 0, sizeof(Prove_Params_t) ); Prove_ParamsSetDefault( p->pParams ); return p; } /**Function************************************************************* Synopsis [Stop the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_RRManStop( Abc_RRMan_t * p ) { Abc_RRManClean( p ); Vec_PtrFree( p->vFaninLeaves ); Vec_PtrFree( p->vFanoutRoots ); Vec_PtrFree( p->vLeaves ); Vec_PtrFree( p->vCone ); Vec_PtrFree( p->vRoots ); ABC_FREE( p->pParams ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stop the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_RRManPrintStats( Abc_RRMan_t * p ) { double Ratio = 100.0*(p->nNodesOld - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld; printf( "Redundancy removal statistics:\n" ); printf( "Edges tried = %6d.\n", p->nEdgesTried ); printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried ); printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio ); printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) ); ABC_PRT( "Windowing ", p->timeWindow ); ABC_PRT( "Miter ", p->timeMiter ); ABC_PRT( " Construct ", p->timeMiter - p->timeProve ); ABC_PRT( " Prove ", p->timeProve ); ABC_PRT( "Update ", p->timeUpdate ); ABC_PRT( "TOTAL ", p->timeTotal ); } /**Function************************************************************* Synopsis [Clean the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_RRManClean( Abc_RRMan_t * p ) { p->pNode = NULL; p->pFanin = NULL; p->pFanout = NULL; Vec_PtrClear( p->vFaninLeaves ); Vec_PtrClear( p->vFanoutRoots ); Vec_PtrClear( p->vLeaves ); Vec_PtrClear( p->vCone ); Vec_PtrClear( p->vRoots ); if ( p->pWnd ) Abc_NtkDelete( p->pWnd ); if ( p->pMiter ) Abc_NtkDelete( p->pMiter ); p->pWnd = NULL; p->pMiter = NULL; } /**Function************************************************************* Synopsis [Returns 1 if the miter is constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRRProve( Abc_RRMan_t * p ) { Abc_Ntk_t * pWndCopy; int RetValue; abctime clk; // Abc_NtkShowAig( p->pWnd, 0 ); pWndCopy = Abc_NtkDup( p->pWnd ); Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL ); if ( !Abc_NtkIsDfsOrdered(pWndCopy) ) Abc_NtkReassignIds(pWndCopy); p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1, 0, 0, 0 ); Abc_NtkDelete( pWndCopy ); clk = Abc_Clock(); RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams ); p->timeProve += Abc_Clock() - clk; if ( RetValue == 1 ) return 1; return 0; } /**Function************************************************************* Synopsis [Updates the network after redundancy removal.] Description [This procedure assumes that non-control value of the fanin was proved redundant. It is okay to concentrate on non-control values because the control values can be seen as redundancy of the fanout edge.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ) { Abc_Obj_t * pNodeNew, * pFanoutNew; assert( pFanout == NULL ); assert( !Abc_ObjIsComplement(pNode) ); assert( !Abc_ObjIsComplement(pFanin) ); assert( !Abc_ObjIsComplement(pFanout) ); // find the node after redundancy removal if ( pFanin == Abc_ObjFanin0(pNode) ) pNodeNew = Abc_ObjChild1(pNode); else if ( pFanin == Abc_ObjFanin1(pNode) ) pNodeNew = Abc_ObjChild0(pNode); else assert( 0 ); // replace if ( pFanout == NULL ) { Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pNode, pNodeNew, 1 ); return 1; } // find the fanout after redundancy removal if ( pNode == Abc_ObjFanin0(pFanout) ) pFanoutNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) ); else if ( pNode == Abc_ObjFanin1(pFanout) ) pFanoutNew = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) ); else assert( 0 ); // replace Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pFanout, pFanoutNew, 1 ); return 1; } /**Function************************************************************* Synopsis [Constructs window for checking RR.] Description [If the window (p->pWnd) with the given scope (p->nFaninLevels, p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1. The levels are measured from the fanin node (pFanin) and the fanout node (pEdgeFanout), respectively.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRRWindow( Abc_RRMan_t * p ) { Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout; int i, LevelMin, LevelMax, RetValue; // get the edge pEdgeFanout = p->pFanout? p->pFanout : p->pNode; pEdgeFanin = p->pFanout? p->pNode : p->pFanin; // get the minimum and maximum levels of the window LevelMin = Abc_MaxInt( 0, ((int)p->pFanin->Level) - p->nFaninLevels ); LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels; // start the TFI leaves with the fanin Abc_NtkIncrementTravId( p->pNtk ); Abc_NodeSetTravIdCurrent( p->pFanin ); Vec_PtrPush( p->vFaninLeaves, p->pFanin ); // mark the TFI cone and collect the leaves down to the given level while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) ); // mark the leaves with the new TravId Abc_NtkIncrementTravId( p->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninLeaves, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); // traverse the TFO cone of the leaves (while skipping the edge) // (a) mark the nodes in the cone using the current TravId // (b) collect the nodes that have external fanouts into p->vFanoutRoots while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) ); // mark the fanout roots Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanoutRoots, pObj, i ) pObj->fMarkA = 1; // collect roots reachable from the fanout (p->vRoots) RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 ); // unmark the fanout roots Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanoutRoots, pObj, i ) pObj->fMarkA = 0; // return if the window is infeasible if ( RetValue == 0 ) return 0; // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves) // using the previous marks coming from the TFO cone Abc_NtkIncrementTravId( p->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i ) Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin ); // create a new network p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots ); return 1; } /**Function************************************************************* Synopsis [Marks the nodes in the TFI and collects their leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ) { Abc_Obj_t * pObj, * pNext; int i, k, LevelMax, nSize; assert( LevelLimit >= 0 ); // find the maximum level of leaves LevelMax = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) if ( LevelMax < (int)pObj->Level ) LevelMax = pObj->Level; // if the nodes are all PIs, LevelMax == 0 if ( LevelMax <= LevelLimit ) return 0; // expand the nodes with the minimum level nSize = Vec_PtrSize(vLeaves); Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pObj, i, nSize ) { if ( LevelMax != (int)pObj->Level ) continue; Abc_ObjForEachFanin( pObj, pNext, k ) { if ( Abc_NodeIsTravIdCurrent(pNext) ) continue; Abc_NodeSetTravIdCurrent( pNext ); Vec_PtrPush( vLeaves, pNext ); } } // remove old nodes (cannot remove a PI) k = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) { if ( LevelMax == (int)pObj->Level ) continue; Vec_PtrWriteEntry( vLeaves, k++, pObj ); } Vec_PtrShrink( vLeaves, k ); if ( Vec_PtrSize(vLeaves) > 2000 ) return 0; return 1; } /**Function************************************************************* Synopsis [Marks the nodes in the TFO and collects their roots.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ) { Abc_Obj_t * pObj, * pNext; int i, k, LevelMin, nSize, fObjIsRoot; // find the minimum level of leaves LevelMin = ABC_INFINITY; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) if ( LevelMin > (int)pObj->Level ) LevelMin = pObj->Level; // if the minimum level exceed the limit, we are done if ( LevelMin > LevelLimit ) return 0; // expand the nodes with the minimum level nSize = Vec_PtrSize(vLeaves); Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pObj, i, nSize ) { if ( LevelMin != (int)pObj->Level ) continue; fObjIsRoot = 0; Abc_ObjForEachFanout( pObj, pNext, k ) { // check if the fanout is outside of the cone if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit ) { fObjIsRoot = 1; continue; } // skip the edge under check if ( pObj == pEdgeFanin && pNext == pEdgeFanout ) continue; // skip the visited fanouts if ( Abc_NodeIsTravIdCurrent(pNext) ) continue; Abc_NodeSetTravIdCurrent( pNext ); Vec_PtrPush( vLeaves, pNext ); } if ( fObjIsRoot ) Vec_PtrPush( vRoots, pObj ); } // remove old nodes k = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) { if ( LevelMin == (int)pObj->Level ) continue; Vec_PtrWriteEntry( vLeaves, k++, pObj ); } Vec_PtrShrink( vLeaves, k ); if ( Vec_PtrSize(vLeaves) > 2000 ) return 0; return 1; } /**Function************************************************************* Synopsis [Collects the roots in the TFO of the node.] Description [Note that this procedure can be improved by marking and skipping the visited nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ) { Abc_Obj_t * pFanout; int i; // if we encountered a node outside of the TFO cone of the fanins, quit if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit ) return 0; // if we encountered a node on the boundary, add it to the roots if ( pNode->fMarkA ) { Vec_PtrPushUnique( vRoots, pNode ); return 1; } // mark the node with the current TravId (needed to have all internal nodes marked) Abc_NodeSetTravIdCurrent( pNode ); // traverse the fanouts Abc_ObjForEachFanout( pNode, pFanout, i ) if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Collects the leaves and cone of the roots.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ) { Abc_Obj_t * pFanin; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pNode) ) return; // add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit ) { Abc_NodeSetTravIdCurrent( pNode ); Vec_PtrPush( vLeaves, pNode ); return; } // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // call for the node's fanins Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit ); // add the node to the cone in topological order Vec_PtrPush( vCone, pNode ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj; int fCheck = 1; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav( "temp" ); // map the constant nodes Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // create and map the PIs Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->pCopy = Abc_NtkCreatePi(pNtkNew); // copy the AND gates Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); // compare the number of nodes before and after if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) ) printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n", Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) ); // create the POs Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { assert( !Abc_ObjIsComplement(pObj->pCopy) ); Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy ); } // add the PI/PO names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); // check if ( fCheck && !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkWindow: The network check has failed.\n" ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Starts simulation to detect non-redundant edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; unsigned uData, uData0, uData1; int i; Abc_AigConst1(pNtk)->pData = (void *)~((unsigned)0); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pData = (void *)(ABC_PTRUINT_T)SIM_RANDOM_UNSIGNED; Abc_NtkForEachNode( pNtk, pObj, i ) { if ( i == 0 ) continue; uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData; uData1 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pData; uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; assert( pObj->pData == NULL ); pObj->pData = (void *)(ABC_PTRUINT_T)uData; } } /**Function************************************************************* Synopsis [Stops simulation to detect non-redundant edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pData = NULL; } static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ); static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ); static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ); /**Function************************************************************* Synopsis [Simulation to detect non-redundant edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes, * vField; Vec_Str_t * vTargets; Abc_Obj_t * pObj; unsigned uData, uData0, uData1; int PrevCi, Phase, i, k; // start the candidates vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 ); Abc_NtkForEachNode( pNtk, pObj, i ) { Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1); Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1); Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase ); } // simulate patters and store them in copy Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)SIM_RANDOM_UNSIGNED; Abc_NtkForEachNode( pNtk, pObj, i ) { if ( i == 0 ) continue; uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData; uData1 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pData; uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)uData; } // store the result in data Abc_NtkForEachCo( pNtk, pObj, i ) { uData0 = (unsigned)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData; if ( Abc_ObjFaninC0(pObj) ) pObj->pData = (void *)(ABC_PTRUINT_T)~uData0; else pObj->pData = (void *)(ABC_PTRUINT_T)uData0; } // refine the candidates for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i ) { vNodes = Vec_PtrAlloc( 10 ); Abc_NtkIncrementTravId( pNtk ); for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ ) { Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes ); if ( Vec_PtrSize(vNodes) > 128 ) break; } // collect the marked nodes in the topological order vField = Vec_PtrAlloc( 10 ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pObj, k ) Sim_CollectNodes_rec( pObj, vField ); // simulate these nodes Sim_SimulateCollected( vTargets, vNodes, vField ); // prepare for the next loop Vec_PtrFree( vNodes ); } // clean Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pData = NULL; return vTargets; } /**Function************************************************************* Synopsis [Collects nodes starting from the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanout; char Entry; int k; if ( Abc_NodeIsTravIdCurrent(pRoot) ) return; Abc_NodeSetTravIdCurrent( pRoot ); // save the reached targets Entry = Vec_StrEntry(vTargets, pRoot->Id); if ( Entry & 1 ) Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) ); if ( Entry & 2 ) Vec_PtrPush( vNodes, pRoot ); // explore the fanouts Abc_ObjForEachFanout( pRoot, pFanout, k ) Sim_TraverseNodes_rec( pFanout, vTargets, vNodes ); } /**Function************************************************************* Synopsis [Collects nodes starting from the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ) { Abc_Obj_t * pFanin; int i; if ( Abc_NodeIsTravIdCurrent(pRoot) ) return; if ( !Abc_NodeIsTravIdPrevious(pRoot) ) return; Abc_NodeSetTravIdCurrent( pRoot ); Abc_ObjForEachFanin( pRoot, pFanin, i ) Sim_CollectNodes_rec( pFanin, vField ); if ( !Abc_ObjIsCo(pRoot) ) pRoot->pData = (void *)(ABC_PTRUINT_T)Vec_PtrSize(vField); Vec_PtrPush( vField, pRoot ); } /**Function************************************************************* Synopsis [Simulate the given nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ) { Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved; Vec_Ptr_t * vSims; unsigned * pUnsigned, * pUnsignedF; int i, k, Phase, fCompl; // get simulation info vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 ); // simulate the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vField, pObj, i ) { if ( Abc_ObjIsCi(pObj) ) { pUnsigned = (unsigned *)Vec_PtrEntry( vSims, i ); for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) pUnsigned[k] = (unsigned)(ABC_PTRUINT_T)pObj->pCopy; continue; } if ( Abc_ObjIsCo(pObj) ) { pUnsigned = (unsigned *)Vec_PtrEntry( vSims, i ); pUnsignedF = (unsigned *)Vec_PtrEntry( vSims, (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pData ); if ( Abc_ObjFaninC0(pObj) ) for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) pUnsigned[k] = ~pUnsignedF[k]; else for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) pUnsigned[k] = pUnsignedF[k]; // update targets for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) { if ( pUnsigned[k] == (unsigned)(ABC_PTRUINT_T)pObj->pData ) continue; pDisproved = (Abc_Obj_t *)Vec_PtrEntry( vNodes, k ); fCompl = Abc_ObjIsComplement(pDisproved); pDisproved = Abc_ObjRegular(pDisproved); Phase = Vec_StrEntry( vTargets, pDisproved->Id ); if ( fCompl ) Phase = (Phase & 2); else Phase = (Phase & 1); Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase ); } continue; } // simulate the node pFanin0 = Abc_ObjFanin0(pObj); pFanin1 = Abc_ObjFanin1(pObj); } } /* { unsigned uData; if ( pFanin == Abc_ObjFanin0(pNode) ) { uData = (unsigned)Abc_ObjFanin1(pNode)->pData; uData = Abc_ObjFaninC1(pNode)? ~uData : uData; } else if ( pFanin == Abc_ObjFanin1(pNode) ) { uData = (unsigned)Abc_ObjFanin0(pNode)->pData; uData = Abc_ObjFaninC0(pNode)? ~uData : uData; } uData ^= (unsigned)pNode->pData; // Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" ); if ( Extra_WordCountOnes(uData) > 8 ) continue; } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcSat.c000066400000000000000000001003271300674244400232100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to solve the miter using the internal SAT sat_solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "base/cmd/cmd.h" #include "sat/bsat/satSolver.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ); extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); static int nMuxes; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Attempts to solve the miter using an internal SAT sat_solver.] Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] SideEffects [] SeeAlso [] ***********************************************************************/ 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 ) { sat_solver * pSat; lbool status; int RetValue; abctime clk; if ( pNumConfs ) *pNumConfs = 0; if ( pNumInspects ) *pNumInspects = 0; assert( Abc_NtkLatchNum(pNtk) == 0 ); // if ( Abc_NtkPoNum(pNtk) > 1 ) // fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) ); // load clauses into the sat_solver clk = Abc_Clock(); pSat = (sat_solver *)Abc_NtkMiterSatCreate( pNtk, 0 ); if ( pSat == NULL ) return 1; //printf( "%d \n", pSat->clauses.size ); //sat_solver_delete( pSat ); //return 1; // printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); // ABC_PRT( "Time", Abc_Clock() - clk ); // simplify the problem clk = Abc_Clock(); status = sat_solver_simplify(pSat); // printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); // ABC_PRT( "Time", Abc_Clock() - clk ); if ( status == 0 ) { sat_solver_delete( pSat ); // printf( "The problem is UNSATISFIABLE after simplification.\n" ); return 1; } // solve the miter clk = Abc_Clock(); if ( fVerbose ) pSat->verbosity = 1; status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) { // printf( "The problem timed out.\n" ); RetValue = -1; } else if ( status == l_True ) { // printf( "The problem is SATISFIABLE.\n" ); RetValue = 0; } else if ( status == l_False ) { // printf( "The problem is UNSATISFIABLE.\n" ); RetValue = 1; } else assert( 0 ); // ABC_PRT( "SAT sat_solver time", Abc_Clock() - clk ); // printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); // if the problem is SAT, get the counterexample if ( status == l_True ) { // Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk ); Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); Vec_IntFree( vCiIds ); } // free the sat_solver if ( fVerbose ) Sat_SolverPrintStats( stdout, pSat ); if ( pNumConfs ) *pNumConfs = (int)pSat->stats.conflicts; if ( pNumInspects ) *pNumInspects = (int)pSat->stats.inspects; sat_solver_store_write( pSat, "trace.cnf" ); sat_solver_store_free( pSat ); sat_solver_delete( pSat ); return RetValue; } /**Function************************************************************* Synopsis [Returns the array of CI IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkGetCiSatVarNums( 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, (int)(ABC_PTRINT_T)pObj->pCopy ); return vCiIds; } /**Function************************************************************* Synopsis [Adds trivial clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkClauseTriv( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) { //printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses ); vVars->nSize = 0; Vec_IntPush( vVars, toLitCond( (int)(ABC_PTRINT_T)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) ); // Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) ); return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } /**Function************************************************************* Synopsis [Adds trivial clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkClauseTop( sat_solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars ) { Abc_Obj_t * pNode; int i; //printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses ); vVars->nSize = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) Vec_IntPush( vVars, toLitCond( (int)(ABC_PTRINT_T)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) ); // Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) ); return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } /**Function************************************************************* Synopsis [Adds trivial clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkClauseAnd( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, Vec_Int_t * vVars ) { int fComp1, Var, Var1, i; //printf( "Adding AND %d. (%d) %d\n", pNode->Id, vSuper->nSize+1, (int)pSat->sat_solver_stats.clauses ); assert( !Abc_ObjIsComplement( pNode ) ); assert( Abc_ObjIsNode( pNode ) ); // nVars = sat_solver_nvars(pSat); Var = (int)(ABC_PTRINT_T)pNode->pCopy; // Var = pNode->Id; // assert( Var < nVars ); for ( i = 0; i < vSuper->nSize; i++ ) { // get the predecessor nodes // get the complemented attributes of the nodes fComp1 = Abc_ObjIsComplement((Abc_Obj_t *)vSuper->pArray[i]); // determine the variable numbers Var1 = (int)(ABC_PTRINT_T)Abc_ObjRegular((Abc_Obj_t *)vSuper->pArray[i])->pCopy; // Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id; // check that the variables are in the SAT manager // assert( Var1 < nVars ); // suppose the AND-gate is A * B = C // add !A => !C or A + !C // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); vVars->nSize = 0; Vec_IntPush( vVars, toLitCond(Var1, fComp1) ); Vec_IntPush( vVars, toLitCond(Var, 1 ) ); if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) return 0; } // add A & B => C or !A + !B + C // fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); vVars->nSize = 0; for ( i = 0; i < vSuper->nSize; i++ ) { // get the predecessor nodes // get the complemented attributes of the nodes fComp1 = Abc_ObjIsComplement((Abc_Obj_t *)vSuper->pArray[i]); // determine the variable numbers Var1 = (int)(ABC_PTRINT_T)Abc_ObjRegular((Abc_Obj_t *)vSuper->pArray[i])->pCopy; // Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id; // add this variable to the array Vec_IntPush( vVars, toLitCond(Var1, !fComp1) ); } Vec_IntPush( vVars, toLitCond(Var, 0) ); return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } /**Function************************************************************* Synopsis [Adds trivial clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkClauseMux( sat_solver * pSat, Abc_Obj_t * pNode, Abc_Obj_t * pNodeC, Abc_Obj_t * pNodeT, Abc_Obj_t * pNodeE, Vec_Int_t * vVars ) { int VarF, VarI, VarT, VarE, fCompT, fCompE; //printf( "Adding mux %d. %d\n", pNode->Id, (int)pSat->sat_solver_stats.clauses ); assert( !Abc_ObjIsComplement( pNode ) ); assert( Abc_NodeIsMuxType( pNode ) ); // get the variable numbers VarF = (int)(ABC_PTRINT_T)pNode->pCopy; VarI = (int)(ABC_PTRINT_T)pNodeC->pCopy; VarT = (int)(ABC_PTRINT_T)Abc_ObjRegular(pNodeT)->pCopy; VarE = (int)(ABC_PTRINT_T)Abc_ObjRegular(pNodeE)->pCopy; // VarF = (int)pNode->Id; // VarI = (int)pNodeC->Id; // VarT = (int)Abc_ObjRegular(pNodeT)->Id; // VarE = (int)Abc_ObjRegular(pNodeE)->Id; // get the complementation flags fCompT = Abc_ObjIsComplement(pNodeT); fCompE = Abc_ObjIsComplement(pNodeE); // f = ITE(i, t, e) // i' + t' + f // i' + t + f' // i + e' + f // i + e + f' // create four clauses vVars->nSize = 0; Vec_IntPush( vVars, toLitCond(VarI, 1) ); Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) ); Vec_IntPush( vVars, toLitCond(VarF, 0) ); if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) return 0; vVars->nSize = 0; Vec_IntPush( vVars, toLitCond(VarI, 1) ); Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) ); Vec_IntPush( vVars, toLitCond(VarF, 1) ); if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) return 0; vVars->nSize = 0; Vec_IntPush( vVars, toLitCond(VarI, 0) ); Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) ); Vec_IntPush( vVars, toLitCond(VarF, 0) ); if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) return 0; vVars->nSize = 0; Vec_IntPush( vVars, toLitCond(VarI, 0) ); Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) ); Vec_IntPush( vVars, toLitCond(VarF, 1) ); if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) return 0; if ( VarT == VarE ) { // assert( fCompT == !fCompE ); return 1; } // two additional clauses // t' & e' -> f' t + e + f' // t & e -> f t' + e' + f vVars->nSize = 0; Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) ); Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) ); Vec_IntPush( vVars, toLitCond(VarF, 1) ); if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) return 0; vVars->nSize = 0; Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) ); Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) ); Vec_IntPush( vVars, toLitCond(VarF, 0) ); return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); } /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux ) { int RetValue1, RetValue2, i; // check if the node is visited if ( Abc_ObjRegular(pNode)->fMarkB ) { // check if the node occurs in the same polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == pNode ) return 1; // check if the node is present in the opposite polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) return -1; assert( 0 ); return 0; } // if the new node is complemented or a PI, another gate begins if ( !fFirst ) if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || (fStopAtMux && Abc_NodeIsMuxType(pNode)) ) { Vec_PtrPush( vSuper, pNode ); Abc_ObjRegular(pNode)->fMarkB = 1; return 0; } assert( !Abc_ObjIsComplement(pNode) ); assert( Abc_ObjIsNode(pNode) ); // go through the branches RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux ); RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; // return 1 if at least one branch has a duplicate return RetValue1 || RetValue2; } /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes ) { int RetValue, i; assert( !Abc_ObjIsComplement(pNode) ); // collect the nodes in the implication supergate Vec_PtrClear( vNodes ); RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux ); assert( vNodes->nSize > 1 ); // unmark the visited nodes for ( i = 0; i < vNodes->nSize; i++ ) Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->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; } /**Function************************************************************* Synopsis [Computes the factor of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkNodeFactor( Abc_Obj_t * pObj, int nLevelMax ) { // nLevelMax = ((nLevelMax)/2)*3; assert( (int)pObj->Level <= nLevelMax ); // return (int)(100000000.0 * pow(0.999, nLevelMax - pObj->Level)); return (int)(100000000.0 * (1 + 0.01 * pObj->Level)); // return (int)(100000000.0 / ((nLevelMax)/2)*3 - pObj->Level); } /**Function************************************************************* Synopsis [Sets up the SAT sat_solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE; Vec_Ptr_t * vNodes, * vSuper; Vec_Int_t * vVars; int i, k, fUseMuxes = 1; // int fOrderCiVarsFirst = 0; int RetValue = 0; assert( Abc_NtkIsStrash(pNtk) ); // clean the CI node pointers Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = NULL; // start the data structures vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the sat_solver vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause // add the clause for the constant node pNode = Abc_AigConst1(pNtk); pNode->fMarkA = 1; pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize; Vec_PtrPush( vNodes, pNode ); Abc_NtkClauseTriv( pSat, pNode, vVars ); /* // add the PI variables first Abc_NtkForEachCi( pNtk, pNode, i ) { pNode->fMarkA = 1; pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; Vec_PtrPush( vNodes, pNode ); } */ // collect the nodes that need clauses and top-level assignments Vec_PtrClear( vSuper ); Abc_NtkForEachCo( pNtk, pNode, i ) { // get the fanin pFanin = Abc_ObjFanin0(pNode); // create the node's variable if ( pFanin->fMarkA == 0 ) { pFanin->fMarkA = 1; pFanin->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize; Vec_PtrPush( vNodes, pFanin ); } // add the trivial clause Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) ); } if ( !Abc_NtkClauseTop( pSat, vSuper, vVars ) ) goto Quits; // add the clauses Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { assert( !Abc_ObjIsComplement(pNode) ); if ( !Abc_AigNodeIsAnd(pNode) ) continue; //printf( "%d ", pNode->Id ); // add the clauses if ( fUseMuxes && Abc_NodeIsMuxType(pNode) ) { nMuxes++; pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); Vec_PtrClear( vSuper ); Vec_PtrPush( vSuper, pNodeC ); Vec_PtrPush( vSuper, pNodeT ); Vec_PtrPush( vSuper, pNodeE ); // add the fanin nodes to explore Vec_PtrForEachEntry( Abc_Obj_t *, vSuper, pFanin, k ) { pFanin = Abc_ObjRegular(pFanin); if ( pFanin->fMarkA == 0 ) { pFanin->fMarkA = 1; pFanin->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize; Vec_PtrPush( vNodes, pFanin ); } } // add the clauses if ( !Abc_NtkClauseMux( pSat, pNode, pNodeC, pNodeT, pNodeE, vVars ) ) goto Quits; } else { // get the supergate Abc_NtkCollectSupergate( pNode, fUseMuxes, vSuper ); // add the fanin nodes to explore Vec_PtrForEachEntry( Abc_Obj_t *, vSuper, pFanin, k ) { pFanin = Abc_ObjRegular(pFanin); if ( pFanin->fMarkA == 0 ) { pFanin->fMarkA = 1; pFanin->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize; Vec_PtrPush( vNodes, pFanin ); } } // add the clauses if ( vSuper->nSize == 0 ) { if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) ) // if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) ) goto Quits; } else { if ( !Abc_NtkClauseAnd( pSat, pNode, vSuper, vVars ) ) goto Quits; } } } /* // set preferred variables if ( fOrderCiVarsFirst ) { int * pPrefVars = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) ); int nVars = 0; Abc_NtkForEachCi( pNtk, pNode, i ) { if ( pNode->fMarkA == 0 ) continue; pPrefVars[nVars++] = (int)pNode->pCopy; } nVars = Abc_MinInt( nVars, 10 ); ASat_SolverSetPrefVars( pSat, pPrefVars, nVars ); } */ /* Abc_NtkForEachObj( pNtk, pNode, i ) { if ( !pNode->fMarkA ) continue; printf( "%10s : ", Abc_ObjName(pNode) ); printf( "%3d\n", (int)pNode->pCopy ); } printf( "\n" ); */ RetValue = 1; Quits : // delete Vec_IntFree( vVars ); Vec_PtrFree( vNodes ); Vec_PtrFree( vSuper ); return RetValue; } /**Function************************************************************* Synopsis [Sets up the SAT sat_solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ) { sat_solver * pSat; Abc_Obj_t * pNode; int RetValue, i; //, clk = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) ); if ( Abc_NtkIsBddLogic(pNtk) ) return Abc_NtkMiterSatCreateLogic(pNtk, fAllPrimes); nMuxes = 0; pSat = sat_solver_new(); //sat_solver_store_alloc( pSat ); RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk ); sat_solver_store_mark_roots( pSat ); Abc_NtkForEachObj( pNtk, pNode, i ) pNode->fMarkA = 0; // ASat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 ); if ( RetValue == 0 ) { sat_solver_delete(pSat); return NULL; } // printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); // ABC_PRT( "Creating sat_solver", Abc_Clock() - clk ); return pSat; } #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Adds clauses for the internal node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars ) { Abc_Obj_t * pFanin; int i, c, nFanins; int RetValue; char * pCube; nFanins = Abc_ObjFaninNum( pNode ); assert( nFanins == Abc_SopGetVarNum( pSop0 ) ); // if ( nFanins == 0 ) if ( Cudd_Regular((Abc_Obj_t *)pNode->pData) == Cudd_ReadOne((DdManager *)pNode->pNtk->pManFunc) ) { vVars->nSize = 0; // if ( Abc_SopIsConst1(pSop1) ) if ( !Cudd_IsComplement(pNode->pData) ) Vec_IntPush( vVars, toLit(pNode->Id) ); else Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); if ( !RetValue ) { printf( "The CNF is trivially UNSAT.\n" ); return 0; } return 1; } // add clauses for the negative phase for ( c = 0; ; c++ ) { // get the cube pCube = pSop0 + c * (nFanins + 3); if ( *pCube == 0 ) break; // add the clause vVars->nSize = 0; Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( pCube[i] == '0' ) Vec_IntPush( vVars, toLit(pFanin->Id) ); else if ( pCube[i] == '1' ) Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); } Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); if ( !RetValue ) { printf( "The CNF is trivially UNSAT.\n" ); return 0; } } // add clauses for the positive phase for ( c = 0; ; c++ ) { // get the cube pCube = pSop1 + c * (nFanins + 3); if ( *pCube == 0 ) break; // add the clause vVars->nSize = 0; Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( pCube[i] == '0' ) Vec_IntPush( vVars, toLit(pFanin->Id) ); else if ( pCube[i] == '1' ) Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); } Vec_IntPush( vVars, toLit(pNode->Id) ); RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); if ( !RetValue ) { printf( "The CNF is trivially UNSAT.\n" ); return 0; } } return 1; } /**Function************************************************************* Synopsis [Adds clauses for the PO node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) { Abc_Obj_t * pFanin; int RetValue; pFanin = Abc_ObjFanin0(pNode); if ( Abc_ObjFaninC0(pNode) ) { vVars->nSize = 0; Vec_IntPush( vVars, toLit(pFanin->Id) ); Vec_IntPush( vVars, toLit(pNode->Id) ); RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); if ( !RetValue ) { printf( "The CNF is trivially UNSAT.\n" ); return 0; } vVars->nSize = 0; Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); if ( !RetValue ) { printf( "The CNF is trivially UNSAT.\n" ); return 0; } } else { vVars->nSize = 0; Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); Vec_IntPush( vVars, toLit(pNode->Id) ); RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); if ( !RetValue ) { printf( "The CNF is trivially UNSAT.\n" ); return 0; } vVars->nSize = 0; Vec_IntPush( vVars, toLit(pFanin->Id) ); Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); if ( !RetValue ) { printf( "The CNF is trivially UNSAT.\n" ); return 0; } } vVars->nSize = 0; Vec_IntPush( vVars, toLit(pNode->Id) ); RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); if ( !RetValue ) { printf( "The CNF is trivially UNSAT.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Sets up the SAT sat_solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ) { sat_solver * pSat; Mem_Flex_t * pMmFlex; Abc_Obj_t * pNode; Vec_Str_t * vCube; Vec_Int_t * vVars; char * pSop0, * pSop1; int i; assert( Abc_NtkIsBddLogic(pNtk) ); // transfer the IDs to the copy field Abc_NtkForEachPi( pNtk, pNode, i ) pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)pNode->Id; // start the data structures pSat = sat_solver_new(); sat_solver_store_alloc( pSat ); pMmFlex = Mem_FlexStart(); vCube = Vec_StrAlloc( 100 ); vVars = Vec_IntAlloc( 100 ); // add clauses for each internal nodes Abc_NtkForEachNode( pNtk, pNode, i ) { // derive SOPs for both phases of the node Abc_NodeBddToCnf( pNode, pMmFlex, vCube, fAllPrimes, &pSop0, &pSop1 ); // add the clauses to the sat_solver if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) ) { sat_solver_delete( pSat ); pSat = NULL; goto finish; } } // add clauses for each PO Abc_NtkForEachPo( pNtk, pNode, i ) { if ( !Abc_NodeAddClausesTop( pSat, pNode, vVars ) ) { sat_solver_delete( pSat ); pSat = NULL; goto finish; } } sat_solver_store_mark_roots( pSat ); finish: // delete Vec_StrFree( vCube ); Vec_IntFree( vVars ); Mem_FlexStop( pMmFlex, 0 ); return pSat; } #else sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ) { return NULL; } #endif /**Function************************************************************* Synopsis [Writes CNF for the sorter with N inputs asserting Q ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkWriteSorterCnf( char * pFileName, int nVars, int nQueens ) { char Command[100]; void * pAbc; Abc_Ntk_t * pNtk; Abc_Obj_t * pObj, * ppNodes[2], * ppRoots[2]; Vec_Ptr_t * vNodes; FILE * pFile; int i, Counter; if ( nQueens <= 0 && nQueens >= nVars ) { printf( "The number of queens (Q = %d) should belong to the interval: 0 < Q < %d.\n", nQueens, nQueens); return; } assert( nQueens > 0 && nQueens < nVars ); pAbc = Abc_FrameGetGlobalFrame(); // generate sorter sprintf( Command, "gen -s -N %d sorter%d.blif", nVars, nVars ); if ( Cmd_CommandExecute( (Abc_Frame_t *)pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return; } // read the file sprintf( Command, "read sorter%d.blif; strash", nVars ); if ( Cmd_CommandExecute( (Abc_Frame_t *)pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return; } // get the current network pNtk = Abc_FrameReadNtk((Abc_Frame_t *)pAbc); // collect the nodes for the given two primary outputs ppNodes[0] = Abc_NtkPo( pNtk, nVars - nQueens - 1 ); ppNodes[1] = Abc_NtkPo( pNtk, nVars - nQueens ); ppRoots[0] = Abc_ObjFanin0( ppNodes[0] ); ppRoots[1] = Abc_ObjFanin0( ppNodes[1] ); vNodes = Abc_NtkDfsNodes( pNtk, ppRoots, 2 ); // assign CNF variables Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)~0; Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Counter++; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Counter++; /* OutVar = pCnf->pVarNums[ pObj->Id ]; pVars[0] = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ]; pVars[1] = pCnf->pVarNums[ Aig_ObjFanin1(pObj)->Id ]; // positive phase *pClas++ = pLits; *pLits++ = 2 * OutVar; *pLits++ = 2 * pVars[0] + !Aig_ObjFaninC0(pObj); *pLits++ = 2 * pVars[1] + !Aig_ObjFaninC1(pObj); // negative phase *pClas++ = pLits; *pLits++ = 2 * OutVar + 1; *pLits++ = 2 * pVars[0] + Aig_ObjFaninC0(pObj); *pClas++ = pLits; *pLits++ = 2 * OutVar + 1; *pLits++ = 2 * pVars[1] + Aig_ObjFaninC1(pObj); */ // add clauses for these nodes pFile = fopen( pFileName, "w" ); fprintf( pFile, "c CNF for %d-bit sorter with %d bits set to 1 generated by ABC.\n", nVars, nQueens ); fprintf( pFile, "p cnf %d %d\n", Counter, 3 * Vec_PtrSize(vNodes) + 2 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // positive phase fprintf( pFile, "%d %s%d %s%d 0\n", 1+(int)(ABC_PTRINT_T)pObj->pCopy, Abc_ObjFaninC0(pObj)? "" : "-", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC1(pObj)? "" : "-", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin1(pObj)->pCopy ); // negative phase fprintf( pFile, "-%d %s%d 0\n", 1+(int)(ABC_PTRINT_T)pObj->pCopy, Abc_ObjFaninC0(pObj)? "-" : "", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin0(pObj)->pCopy ); fprintf( pFile, "-%d %s%d 0\n", 1+(int)(ABC_PTRINT_T)pObj->pCopy, Abc_ObjFaninC1(pObj)? "-" : "", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin1(pObj)->pCopy ); } Vec_PtrFree( vNodes ); /* *pClas++ = pLits; *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); */ // assert the first literal to zero fprintf( pFile, "%s%d 0\n", Abc_ObjFaninC0(ppNodes[0])? "" : "-", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin0(ppNodes[0])->pCopy ); // assert the second literal to one fprintf( pFile, "%s%d 0\n", Abc_ObjFaninC0(ppNodes[1])? "-" : "", 1+(int)(ABC_PTRINT_T)Abc_ObjFanin0(ppNodes[1])->pCopy ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcSaucy.c000066400000000000000000002725041300674244400235540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcSaucy.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Symmetry Detection Package.] Synopsis [Finds symmetries under permutation (but not negation) of I/Os.] Author [Hadi Katebi] Affiliation [University of Michigan] Date [Ver. 1.0. Started - April, 2012.] Revision [No revisions so far] Comments [] Debugging [There are some part of the code that are commented out. Those parts mostly print the contents of the data structures to the standard output. Un-comment them if you find them useful for debugging.] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/sim/sim.h" ABC_NAMESPACE_IMPL_START /* on/off switches */ #define REFINE_BY_SIM_1 0 #define REFINE_BY_SIM_2 0 #define BACKTRACK_BY_SAT 1 #define SELECT_DYNAMICALLY 0 /* number of iterations for sim1 and sim2 refinements */ int NUM_SIM1_ITERATION; int NUM_SIM2_ITERATION; /* conflict analysis */ #define CLAUSE_DECAY 0.9 #define MAX_LEARNTS 50 /* * saucy.c * * by Paul T. Darga * and Mark Liffiton * and Hadi Katebi * * Copyright (C) 2004, The Regents of the University of Michigan * See the LICENSE file for details. */ struct saucy_stats { double grpsize_base; int grpsize_exp; int levels; int nodes; int bads; int gens; int support; }; struct saucy_graph { int n; int e; int *adj; int *edg; }; struct coloring { int *lab; /* Labelling of objects */ int *unlab; /* Inverse of lab */ int *cfront; /* Pointer to front of cells */ int *clen; /* Length of cells (defined for cfront's) */ }; struct sim_result { int *inVec; int *outVec; int inVecSignature; int outVecOnes; double activity; }; struct saucy { /* Graph data */ int n; /* Size of domain */ int *adj; /* Neighbors of k: edg[adj[k]]..edg[adj[k+1]] */ int *edg; /* Actual neighbor data */ int *dadj; /* Fanin neighbor indices, for digraphs */ int *dedg; /* Fanin neighbor data, for digraphs */ /* Coloring data */ struct coloring left, right; int *nextnon; /* Forward next-nonsingleton pointers */ int *prevnon; /* Backward next-nonsingleton pointers */ /* Refinement: inducers */ char *indmark; /* Induce marks */ int *ninduce; /* Nonsingletons that might induce refinement */ int *sinduce; /* Singletons that might induce refinement */ int nninduce; /* Size of ninduce stack */ int nsinduce; /* Size of sinduce stack */ /* Refinement: marked cells */ int *clist; /* List of cells marked for refining */ int csize; /* Number of cells in clist */ /* Refinement: workspace */ char *stuff; /* Bit vector, but one char per bit */ int *ccount; /* Number of connections to refining cell */ int *bucket; /* Workspace */ int *count; /* Num vertices with same adj count to ref cell */ int *junk; /* More workspace */ int *gamma; /* Working permutation */ int *conncnts; /* Connection counts for cell fronts */ /* Search data */ int lev; /* Current search tree level */ int anc; /* Level of greatest common ancestor with zeta */ int *anctar; /* Copy of target cell at anc */ int kanctar; /* Location within anctar to iterate from */ int *start; /* Location of target at each level */ int indmin; /* Used for group size computation */ int match; /* Have we not diverged from previous left? */ /* Search: orbit partition */ int *theta; /* Running approximation of orbit partition */ int *thsize; /* Size of cells in theta, defined for mcrs */ int *thnext; /* Next rep in list (circular list) */ int *thprev; /* Previous rep in list */ int *threp; /* First rep for a given cell front */ int *thfront; /* The cell front associated with this rep */ /* Search: split record */ int *splitvar; /* The actual value of the splits on the left-most branch */ int *splitwho; /* List of where splits occurred */ int *splitfrom; /* List of cells which were split */ int *splitlev; /* Where splitwho/from begins for each level */ int nsplits; /* Number of splits at this point */ /* Search: differences from leftmost */ char *diffmark; /* Marked for diff labels */ int *diffs; /* List of diff labels */ int *difflev; /* How many labels diffed at each level */ int ndiffs; /* Current number of diffs */ int *undifflev; /* How many diff labels fixed at each level */ int nundiffs; /* Current number of diffs in singletons (fixed) */ int *unsupp; /* Inverted diff array */ int *specmin; /* Speculated mappings */ int *pairs; /* Not-undiffed diffs that can make two-cycles */ int *unpairs; /* Indices into pairs */ int npairs; /* Number of such pairs */ int *diffnons; /* Diffs that haven't been undiffed */ int *undiffnons; /* Inverse of that */ int ndiffnons; /* Number of such diffs */ /* Polymorphic functions */ int (*split)(struct saucy *, struct coloring *, int, int); int (*is_automorphism)(struct saucy *); int (*ref_singleton)(struct saucy *, struct coloring *, int); int (*ref_nonsingle)(struct saucy *, struct coloring *, int); void (*select_decomposition)(struct saucy *, int *, int *, int *); /* Statistics structure */ struct saucy_stats *stats; /* New data structures for Boolean formulas */ Abc_Ntk_t * pNtk; Abc_Ntk_t * pNtk_permuted; int * depAdj; int * depEdg; Vec_Int_t ** iDep, ** oDep; Vec_Int_t ** obs, ** ctrl; Vec_Ptr_t ** topOrder; Vec_Ptr_t * randomVectorArray_sim1; int * randomVectorSplit_sim1; Vec_Ptr_t * randomVectorArray_sim2; int * randomVectorSplit_sim2; char * marks; int * pModel; Vec_Ptr_t * satCounterExamples; double activityInc; int fBooleanMatching; int fPrintTree; int fLookForSwaps; FILE * gFile; int (*refineBySim1)(struct saucy *, struct coloring *); int (*refineBySim2)(struct saucy *, struct coloring *); int (*print_automorphism)(FILE *f, int n, const int *gamma, int nsupp, const int *support, char * marks, Abc_Ntk_t * pNtk); }; static int *ints(int n) { return ABC_ALLOC(int, n); } static int *zeros(int n) { return ABC_CALLOC(int, n); } static char *bits(int n) { return ABC_CALLOC(char, n); } static char * getVertexName(Abc_Ntk_t *pNtk, int v); static int * generateProperInputVector(Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randomVector); static int ifInputVectorsAreConsistent(struct saucy * s, int * leftVec, int * rightVec); static int ifOutputVectorsAreConsistent(struct saucy * s, int * leftVec, int * rightVec); static Vec_Ptr_t ** findTopologicalOrder(Abc_Ntk_t * pNtk); static void getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep); static struct saucy_graph * buildDepGraph (Abc_Ntk_t *pNtk, Vec_Int_t ** iDep, Vec_Int_t ** oDep); static struct saucy_graph * buildSim1Graph(Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randVec, Vec_Int_t ** iDep, Vec_Int_t ** oDep); static struct saucy_graph * buildSim2Graph(Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randVec, Vec_Int_t ** iDep, Vec_Int_t ** oDep, Vec_Ptr_t ** topOrder, Vec_Int_t ** obs, Vec_Int_t ** ctrl); static Vec_Int_t * assignRandomBitsToCells(Abc_Ntk_t * pNtk, struct coloring *c); static int Abc_NtkCecSat_saucy(Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel); static struct sim_result * analyzeConflict(Abc_Ntk_t * pNtk, int * pModel, int fVerbose); static void bumpActivity (struct saucy * s, struct sim_result * cex); static void reduceDB(struct saucy * s); static int print_automorphism_ntk(FILE *f, int n, const int *gamma, int nsupp, const int *support, char * marks, Abc_Ntk_t * pNtk) { int i, j, k; /* We presume support is already sorted */ for (i = 0; i < nsupp; ++i) { k = support[i]; /* Skip elements already seen */ if (marks[k]) continue; /* Start an orbit */ marks[k] = 1; fprintf(f, "(%s", getVertexName(pNtk, k)); /* Mark and notify elements in this orbit */ for (j = gamma[k]; j != k; j = gamma[j]) { marks[j] = 1; fprintf(f, " %s", getVertexName(pNtk, j)); } /* Finish off the orbit */ fprintf(f, ")"); } fprintf(f, "\n"); /* Clean up after ourselves */ for (i = 0; i < nsupp; ++i) { marks[support[i]] = 0; } return 1; } static int print_automorphism_ntk2(FILE *f, int n, const int *gamma, int nsupp, const int *support, char * marks, Abc_Ntk_t * pNtk) { int i, j, k; /* We presume support is already sorted */ for (i = 0; i < nsupp; ++i) { k = support[i]; /* Skip elements already seen */ if (marks[k]) continue; /* Start an orbit */ marks[k] = 1; fprintf(f, "%d", k-1); /* Mark and notify elements in this orbit */ for (j = gamma[k]; j != k; j = gamma[j]) { marks[j] = 1; fprintf(f, " %d ", j-1); } /* Finish off the orbit */ } fprintf(f, "-1\n"); /* Clean up after ourselves */ for (i = 0; i < nsupp; ++i) { marks[support[i]] = 0; } return 1; } static int print_automorphism_quiet(FILE *f, int n, const int *gamma, int nsupp, const int *support, char * marks, Abc_Ntk_t * pNtk) { return 1; } static int array_find_min(const int *a, int n) { const int *start = a, *end = a + n, *min = a; while (++a != end) { if (*a < *min) min = a; } return min - start; } static void swap(int *a, int x, int y) { int tmp = a[x]; a[x] = a[y]; a[y] = tmp; } static void sift_up(int *a, int k) { int p; do { p = k / 2; if (a[k] <= a[p]) { return; } else { swap(a, k, p); k = p; } } while (k > 1); } static void sift_down(int *a, int n) { int p = 1, k = 2; while (k <= n) { if (k < n && a[k] < a[k+1]) ++k; if (a[p] < a[k]) { swap(a, p, k); p = k; k = 2 * p; } else { return; } } } static void heap_sort(int *a, int n) { int i; for (i = 1; i < n; ++i) { sift_up(a-1, i+1); } --i; while (i > 0) { swap(a, 0, i); sift_down(a-1, i--); } } static void insertion_sort(int *a, int n) { int i, j, k; for (i = 1; i < n; ++i) { k = a[i]; for (j = i; j > 0 && a[j-1] > k; --j) { a[j] = a[j-1]; } a[j] = k; } } static int partition(int *a, int n, int m) { int f = 0, b = n; for (;;) { while (a[f] <= m) ++f; do --b; while (m <= a[b]); if (f < b) { swap(a, f, b); ++f; } else break; } return f; } static int log_base2(int n) { int k = 0; while (n > 1) { ++k; n >>= 1; } return k; } static int median(int a, int b, int c) { if (a <= b) { if (b <= c) return b; if (a <= c) return c; return a; } else { if (a <= c) return a; if (b <= c) return c; return b; } } static void introsort_loop(int *a, int n, int lim) { int p; while (n > 16) { if (lim == 0) { heap_sort(a, n); return; } --lim; p = partition(a, n, median(a[0], a[n/2], a[n-1])); introsort_loop(a + p, n - p, lim); n = p; } } static void introsort(int *a, int n) { introsort_loop(a, n, 2 * log_base2(n)); insertion_sort(a, n); } static int do_find_min(struct coloring *c, int t) { return array_find_min(c->lab + t, c->clen[t] + 1) + t; } static int find_min(struct saucy *s, int t) { return do_find_min(&s->right, t); } static void set_label(struct coloring *c, int index, int value) { c->lab[index] = value; c->unlab[value] = index; } static void swap_labels(struct coloring *c, int a, int b) { int tmp = c->lab[a]; set_label(c, a, c->lab[b]); set_label(c, b, tmp); } static void move_to_back(struct saucy *s, struct coloring *c, int k) { int cf = c->cfront[k]; int cb = cf + c->clen[cf]; int offset = s->conncnts[cf]++; /* Move this connected label to the back of its cell */ swap_labels(c, cb - offset, c->unlab[k]); /* Add it to the cell list if it's the first one swapped */ if (!offset) s->clist[s->csize++] = cf; } static void data_mark(struct saucy *s, struct coloring *c, int k) { int cf = c->cfront[k]; /* Move connects to the back of nonsingletons */ if (c->clen[cf]) move_to_back(s, c, k); } static void data_count(struct saucy *s, struct coloring *c, int k) { int cf = c->cfront[k]; /* Move to back and count the number of connections */ if (c->clen[cf] && !s->ccount[k]++) move_to_back(s, c, k); } static int check_mapping(struct saucy *s, const int *adj, const int *edg, int k) { int i, gk, ret = 1; /* Mark gamma of neighbors */ for (i = adj[k]; i != adj[k+1]; ++i) { s->stuff[s->gamma[edg[i]]] = 1; } /* Check neighbors of gamma */ gk = s->gamma[k]; for (i = adj[gk]; ret && i != adj[gk+1]; ++i) { ret = s->stuff[edg[i]]; } /* Clear out bit vector before we leave */ for (i = adj[k]; i != adj[k+1]; ++i) { s->stuff[s->gamma[edg[i]]] = 0; } return ret; } static int add_conterexample(struct saucy *s, struct sim_result * cex) { int i; int nins = Abc_NtkPiNum(s->pNtk); struct sim_result * savedcex; cex->inVecSignature = 0; for (i = 0; i < nins; i++) { if (cex->inVec[i]) { cex->inVecSignature += (cex->inVec[i] * i * i); cex->inVecSignature ^= 0xABCD; } } for (i = 0; i < Vec_PtrSize(s->satCounterExamples); i++) { savedcex = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i); if (savedcex->inVecSignature == cex->inVecSignature) { //bumpActivity(s, savedcex); return 0; } } Vec_PtrPush(s->satCounterExamples, cex); bumpActivity(s, cex); return 1; } static int is_undirected_automorphism(struct saucy *s) { int i, j, ret; for (i = 0; i < s->ndiffs; ++i) { j = s->unsupp[i]; if (!check_mapping(s, s->adj, s->edg, j)) return 0; } ret = Abc_NtkCecSat_saucy(s->pNtk, s->pNtk_permuted, s->pModel); if( BACKTRACK_BY_SAT && !ret ) { struct sim_result * cex; cex = analyzeConflict( s->pNtk, s->pModel, s->fPrintTree ); add_conterexample(s, cex); cex = analyzeConflict( s->pNtk_permuted, s->pModel, s->fPrintTree ); add_conterexample(s, cex); s->activityInc *= (1 / CLAUSE_DECAY); if (Vec_PtrSize(s->satCounterExamples) >= MAX_LEARNTS) reduceDB(s); } return ret; } static int is_directed_automorphism(struct saucy *s) { int i, j; for (i = 0; i < s->ndiffs; ++i) { j = s->unsupp[i]; if (!check_mapping(s, s->adj, s->edg, j)) return 0; if (!check_mapping(s, s->dadj, s->dedg, j)) return 0; } return 1; } static void add_induce(struct saucy *s, struct coloring *c, int who) { if (!c->clen[who]) { s->sinduce[s->nsinduce++] = who; } else { s->ninduce[s->nninduce++] = who; } s->indmark[who] = 1; } static void fix_fronts(struct coloring *c, int cf, int ff) { int i, end = cf + c->clen[cf]; for (i = ff; i <= end; ++i) { c->cfront[c->lab[i]] = cf; } } static void array_indirect_sort(int *a, const int *b, int n) { int h, i, j, k; /* Shell sort, as implemented in nauty, (C) Brendan McKay */ j = n / 3; h = 1; do { h = 3 * h + 1; } while (h < j); do { for (i = h; i < n; ++i) { k = a[i]; for (j = i; b[a[j-h]] > b[k]; ) { a[j] = a[j-h]; if ((j -= h) < h) break; } a[j] = k; } h /= 3; } while (h > 0); } static int at_terminal(struct saucy *s) { return s->nsplits == s->n; } static void add_diffnon(struct saucy *s, int k) { /* Only add if we're in a consistent state */ if (s->ndiffnons == -1) return; s->undiffnons[k] = s->ndiffnons; s->diffnons[s->ndiffnons++] = k; } static void remove_diffnon(struct saucy *s, int k) { int j; if (s->undiffnons[k] == -1) return; j = s->diffnons[--s->ndiffnons]; s->diffnons[s->undiffnons[k]] = j; s->undiffnons[j] = s->undiffnons[k]; s->undiffnons[k] = -1; } static void add_diff(struct saucy *s, int k) { if (!s->diffmark[k]) { s->diffmark[k] = 1; s->diffs[s->ndiffs++] = k; add_diffnon(s, k); } } static int is_a_pair(struct saucy *s, int k) { return s->unpairs[k] != -1; } static int in_cell_range(struct coloring *c, int ff, int cf) { int cb = cf + c->clen[cf]; return cf <= ff && ff <= cb; } static void add_pair(struct saucy *s, int k) { if (s->npairs != -1) { s->unpairs[k] = s->npairs; s->pairs[s->npairs++] = k; } } static void eat_pair(struct saucy *s, int k) { int j; j = s->pairs[--s->npairs]; s->pairs[s->unpairs[k]] = j; s->unpairs[j] = s->unpairs[k]; s->unpairs[k] = -1; } static void pick_all_the_pairs(struct saucy *s) { int i; for (i = 0; i < s->npairs; ++i) { s->unpairs[s->pairs[i]] = -1; } s->npairs = 0; } static void clear_undiffnons(struct saucy *s) { int i; for (i = 0 ; i < s->ndiffnons ; ++i) { s->undiffnons[s->diffnons[i]] = -1; } } static void fix_diff_singleton(struct saucy *s, int cf) { int r = s->right.lab[cf]; int l = s->left.lab[cf]; int rcfl; if (!s->right.clen[cf] && r != l) { /* Make sure diff is marked */ add_diff(s, r); /* It is now undiffed since it is singleton */ ++s->nundiffs; remove_diffnon(s, r); /* Mark the other if not singleton already */ rcfl = s->right.cfront[l]; if (s->right.clen[rcfl]) { add_diff(s, l); /* Check for pairs */ if (in_cell_range(&s->right, s->left.unlab[r], rcfl)) { add_pair(s, l); } } /* Otherwise we might be eating a pair */ else if (is_a_pair(s, r)) { eat_pair(s, r); } } } static void fix_diff_subtract(struct saucy *s, int cf, const int *a, const int *b) { int i, k; int cb = cf + s->right.clen[cf]; /* Mark the contents of the first set */ for (i = cf; i <= cb; ++i) { s->stuff[a[i]] = 1; } /* Add elements from second set not present in the first */ for (i = cf; i <= cb; ++i) { k = b[i]; if (!s->stuff[k]) add_diff(s, k); } /* Clear the marks of the first set */ for (i = cf; i <= cb; ++i) { s->stuff[a[i]] = 0; } } static void fix_diffs(struct saucy *s, int cf, int ff) { int min; /* Check for singleton cases in both cells */ fix_diff_singleton(s, cf); fix_diff_singleton(s, ff); /* If they're both nonsingleton, do subtraction on smaller */ if (s->right.clen[cf] && s->right.clen[ff]) { min = s->right.clen[cf] < s->right.clen[ff] ? cf : ff; fix_diff_subtract(s, min, s->left.lab, s->right.lab); fix_diff_subtract(s, min, s->right.lab, s->left.lab); } } static void split_color(struct coloring *c, int cf, int ff) { int cb, fb; /* Fix lengths */ fb = ff - 1; cb = cf + c->clen[cf]; c->clen[cf] = fb - cf; c->clen[ff] = cb - ff; /* Fix cell front pointers */ fix_fronts(c, ff, ff); } static void split_common(struct saucy *s, struct coloring *c, int cf, int ff) { split_color(c, cf, ff); /* Add to refinement */ if (s->indmark[cf] || c->clen[ff] < c->clen[cf]) { add_induce(s, c, ff); } else { add_induce(s, c, cf); } } static int split_left(struct saucy *s, struct coloring *c, int cf, int ff) { /* Record the split */ s->splitwho[s->nsplits] = ff; s->splitfrom[s->nsplits] = cf; ++s->nsplits; /* Do common splitting tasks */ split_common(s, c, cf, ff); /* Always succeeds */ return 1; } static int split_init(struct saucy *s, struct coloring *c, int cf, int ff) { split_left(s, c, cf, ff); /* Maintain nonsingleton list for finding new targets */ if (c->clen[ff]) { s->prevnon[s->nextnon[cf]] = ff; s->nextnon[ff] = s->nextnon[cf]; s->prevnon[ff] = cf; s->nextnon[cf] = ff; } if (!c->clen[cf]) { s->nextnon[s->prevnon[cf]] = s->nextnon[cf]; s->prevnon[s->nextnon[cf]] = s->prevnon[cf]; } /* Always succeeds */ return 1; } static int split_other(struct saucy *s, struct coloring *c, int cf, int ff) { int k = s->nsplits; /* Verify the split with init */ if (s->splitwho[k] != ff || s->splitfrom[k] != cf || k >= s->splitlev[s->lev]) { return 0; } ++s->nsplits; /* Do common splitting tasks */ split_common(s, c, cf, ff); /* Fix differences with init */ fix_diffs(s, cf, ff); /* If we got this far we succeeded */ return 1; } static int print_partition(struct coloring *left, struct coloring *right, int n, Abc_Ntk_t * pNtk, int fNames) { int i, j; printf("top = |"); for(i = 0; i < n; i += (left->clen[i]+1)) { for(j = 0; j < (left->clen[i]+1); j++) { if (fNames) printf("%s ", getVertexName(pNtk, left->lab[i+j])); else printf("%d ", left->lab[i+j]); } if((i+left->clen[i]+1) < n) printf("|"); } printf("|\n"); /*printf("(cfront = {"); for (i = 0; i < n; i++) printf("%d ", left->cfront[i]); printf("})\n");*/ if (right == NULL) return 1; printf("bot = |"); for(i = 0; i < n; i += (right->clen[i]+1)) { for(j = 0; j < (right->clen[i]+1); j++) { if (fNames) printf("%s ", getVertexName(pNtk, right->lab[i+j])); else printf("%d ", right->lab[i+j]); } if((i+right->clen[i]+1) < n) printf("|"); } printf("|\n"); /*printf("(cfront = {"); for (i = 0; i < n; i++) printf("%d ", right->cfront[i]); printf("})\n");*/ return 1; } static int refine_cell(struct saucy *s, struct coloring *c, int (*refine)(struct saucy *, struct coloring *, int)) { int i, cf, ret = 1; /* * The connected list must be consistent. This is for * detecting mappings across nodes at a given level. However, * at the root of the tree, we never have to map with another * node, so we lack this consistency constraint in that case. */ if (s->lev > 1) introsort(s->clist, s->csize); /* Now iterate over the marked cells */ for (i = 0; ret && i < s->csize; ++i) { cf = s->clist[i]; ret = refine(s, c, cf); } /* Clear the connected marks */ for (i = 0; i < s->csize; ++i) { cf = s->clist[i]; s->conncnts[cf] = 0; } s->csize = 0; return ret; } static int maybe_split(struct saucy *s, struct coloring *c, int cf, int ff) { return cf == ff ? 1 : s->split(s, c, cf, ff); } static int ref_single_cell(struct saucy *s, struct coloring *c, int cf) { int zcnt = c->clen[cf] + 1 - s->conncnts[cf]; return maybe_split(s, c, cf, cf + zcnt); } static int ref_singleton(struct saucy *s, struct coloring *c, const int *adj, const int *edg, int cf) { int i, k = c->lab[cf]; /* Find the cells we're connected to, and mark our neighbors */ for (i = adj[k]; i != adj[k+1]; ++i) { data_mark(s, c, edg[i]); } /* Refine the cells we're connected to */ return refine_cell(s, c, ref_single_cell); } static int ref_singleton_directed(struct saucy *s, struct coloring *c, int cf) { return ref_singleton(s, c, s->adj, s->edg, cf) && ref_singleton(s, c, s->dadj, s->dedg, cf); } static int ref_singleton_undirected(struct saucy *s, struct coloring *c, int cf) { return ref_singleton(s, c, s->adj, s->edg, cf); } static int ref_nonsingle_cell(struct saucy *s, struct coloring *c, int cf) { int cnt, i, cb, nzf, ff, fb, bmin, bmax; /* Find the front and back */ cb = cf + c->clen[cf]; nzf = cb - s->conncnts[cf] + 1; /* Prepare the buckets */ ff = nzf; cnt = s->ccount[c->lab[ff]]; s->count[ff] = bmin = bmax = cnt; s->bucket[cnt] = 1; /* Iterate through the rest of the vertices */ while (++ff <= cb) { cnt = s->ccount[c->lab[ff]]; /* Initialize intermediate buckets */ while (bmin > cnt) s->bucket[--bmin] = 0; while (bmax < cnt) s->bucket[++bmax] = 0; /* Mark this count */ ++s->bucket[cnt]; s->count[ff] = cnt; } /* If they all had the same count, bail */ if (bmin == bmax && cf == nzf) return 1; ff = fb = nzf; /* Calculate bucket locations, sizes */ for (i = bmin; i <= bmax; ++i, ff = fb) { if (!s->bucket[i]) continue; fb = ff + s->bucket[i]; s->bucket[i] = fb; } /* Repair the partition nest */ for (i = nzf; i <= cb; ++i) { s->junk[--s->bucket[s->count[i]]] = c->lab[i]; } for (i = nzf; i <= cb; ++i) { set_label(c, i, s->junk[i]); } /* Split; induce */ for (i = bmax; i > bmin; --i) { ff = s->bucket[i]; if (ff && !s->split(s, c, cf, ff)) return 0; } /* If there was a zero area, then there's one more cell */ return maybe_split(s, c, cf, s->bucket[bmin]); } static int ref_nonsingle(struct saucy *s, struct coloring *c, const int *adj, const int *edg, int cf) { int i, j, k, ret; const int cb = cf + c->clen[cf]; const int size = cb - cf + 1; /* Double check for nonsingles which became singles later */ if (cf == cb) { return ref_singleton(s, c, adj, edg, cf); } /* Establish connected list */ memcpy(s->junk, c->lab + cf, size * sizeof(int)); for (i = 0; i < size; ++i) { k = s->junk[i]; for (j = adj[k]; j != adj[k+1]; ++j) { data_count(s, c, edg[j]); } } /* Refine the cells we're connected to */ ret = refine_cell(s, c, ref_nonsingle_cell); /* Clear the counts; use lab because junk was overwritten */ for (i = cf; i <= cb; ++i) { k = c->lab[i]; for (j = adj[k]; j != adj[k+1]; ++j) { s->ccount[edg[j]] = 0; } } return ret; } static int ref_nonsingle_directed(struct saucy *s, struct coloring *c, int cf) { return ref_nonsingle(s, c, s->adj, s->edg, cf) && ref_nonsingle(s, c, s->dadj, s->dedg, cf); } static int ref_nonsingle_undirected(struct saucy *s, struct coloring *c, int cf) { return ref_nonsingle(s, c, s->adj, s->edg, cf); } static void clear_refine(struct saucy *s) { int i; for (i = 0; i < s->nninduce; ++i) { s->indmark[s->ninduce[i]] = 0; } for (i = 0; i < s->nsinduce; ++i) { s->indmark[s->sinduce[i]] = 0; } s->nninduce = s->nsinduce = 0; } static int refine(struct saucy *s, struct coloring *c) { int front; /* Keep going until refinement stops */ while (1) { /* If discrete, bail */ if (at_terminal(s)) { clear_refine(s); return 1; }; /* Look for something else to refine on */ if (s->nsinduce) { front = s->sinduce[--s->nsinduce]; s->indmark[front] = 0; if (!s->ref_singleton(s, c, front)) break; } else if (s->nninduce) { front = s->ninduce[--s->nninduce]; s->indmark[front] = 0; if (!s->ref_nonsingle(s, c, front)) break; } else { return 1; }; } clear_refine(s); return 0; } static int refineByDepGraph(struct saucy *s, struct coloring *c) { s->adj = s->depAdj; s->edg = s->depEdg; return refine(s, c); } static int backtrackBysatCounterExamples(struct saucy *s, struct coloring *c) { int i, j, res; struct sim_result * cex1, * cex2; int * flag = zeros(Vec_PtrSize(s->satCounterExamples)); if (c == &s->left) return 1; if (Vec_PtrSize(s->satCounterExamples) == 0) return 1; for (i = 0; i < Vec_PtrSize(s->satCounterExamples); i++) { cex1 = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i); for (j = 0; j < Vec_PtrSize(s->satCounterExamples); j++) { if (flag[j]) continue; cex2 = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, j); res = ifInputVectorsAreConsistent(s, cex1->inVec, cex2->inVec); if (res == -2) { flag[j] = 1; continue; } if (res == -1) break; if (res == 0) continue; if (cex1->outVecOnes != cex2->outVecOnes) { bumpActivity(s, cex1); bumpActivity(s, cex2); ABC_FREE(flag); return 0; } /* if two input vectors produce the same number of ones (look above), and * pNtk's number of outputs is 1, then output vectors are definitely consistent. */ if (Abc_NtkPoNum(s->pNtk) == 1) continue; if (!ifOutputVectorsAreConsistent(s, cex1->outVec, cex2->outVec)) { bumpActivity(s, cex1); bumpActivity(s, cex2); ABC_FREE(flag); return 0; } } } ABC_FREE(flag); return 1; } static int refineBySim1_init(struct saucy *s, struct coloring *c) { struct saucy_graph *g; Vec_Int_t * randVec; int i, j; int allOutputsAreDistinguished; int nsplits; if (Abc_NtkPoNum(s->pNtk) == 1) return 1; for (i = 0; i < NUM_SIM1_ITERATION; i++) { /* if all outputs are distinguished, quit */ allOutputsAreDistinguished = 1; for (j = 0; j < Abc_NtkPoNum(s->pNtk); j++) { if (c->clen[j]) { allOutputsAreDistinguished = 0; break; } } if (allOutputsAreDistinguished) break; randVec = assignRandomBitsToCells(s->pNtk, c); g = buildSim1Graph(s->pNtk, c, randVec, s->iDep, s->oDep); assert(g != NULL); s->adj = g->adj; s->edg = g->edg; nsplits = s->nsplits; for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); refine(s, c); if (s->nsplits > nsplits) { i = 0; /* reset i */ /* do more refinement by dependency graph */ for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); refineByDepGraph(s, c); } Vec_IntFree(randVec); ABC_FREE( g->adj ); ABC_FREE( g->edg ); ABC_FREE( g ); } return 1; } static int refineBySim1_left(struct saucy *s, struct coloring *c) { struct saucy_graph *g; Vec_Int_t * randVec; int i, j; int allOutputsAreDistinguished; int nsplits; if (Abc_NtkPoNum(s->pNtk) == 1) return 1; for (i = 0; i < NUM_SIM1_ITERATION; i++) { /* if all outputs are distinguished, quit */ allOutputsAreDistinguished = 1; for (j = 0; j < Abc_NtkPoNum(s->pNtk); j++) { if (c->clen[j]) { allOutputsAreDistinguished = 0; break; } } if (allOutputsAreDistinguished) break; randVec = assignRandomBitsToCells(s->pNtk, c); g = buildSim1Graph(s->pNtk, c, randVec, s->iDep, s->oDep); assert(g != NULL); s->adj = g->adj; s->edg = g->edg; nsplits = s->nsplits; for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); refine(s, c); if (s->nsplits > nsplits) { /* save the random vector */ Vec_PtrPush(s->randomVectorArray_sim1, randVec); i = 0; /* reset i */ /* do more refinement by dependency graph */ for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); refineByDepGraph(s, c); } else Vec_IntFree(randVec); ABC_FREE( g->adj ); ABC_FREE( g->edg ); ABC_FREE( g ); } s->randomVectorSplit_sim1[s->lev] = Vec_PtrSize(s->randomVectorArray_sim1); return 1; } static int refineBySim1_other(struct saucy *s, struct coloring *c) { struct saucy_graph *g; Vec_Int_t * randVec; int i, j; int ret, nsplits; for (i = s->randomVectorSplit_sim1[s->lev-1]; i < s->randomVectorSplit_sim1[s->lev]; i++) { randVec = (Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim1, i); g = buildSim1Graph(s->pNtk, c, randVec, s->iDep, s->oDep); if (g == NULL) { assert(c == &s->right); return 0; } s->adj = g->adj; s->edg = g->edg; nsplits = s->nsplits; for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); ret = refine(s, c); if (s->nsplits == nsplits) { assert(c == &s->right); ret = 0; } if (ret) { /* do more refinement now by dependency graph */ for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); ret = refineByDepGraph(s, c); } ABC_FREE( g->adj ); ABC_FREE( g->edg ); ABC_FREE( g ); if (!ret) return 0; } return 1; } static int refineBySim2_init(struct saucy *s, struct coloring *c) { struct saucy_graph *g; Vec_Int_t * randVec; int i, j; int nsplits; for (i = 0; i < NUM_SIM2_ITERATION; i++) { randVec = assignRandomBitsToCells(s->pNtk, c); g = buildSim2Graph(s->pNtk, c, randVec, s->iDep, s->oDep, s->topOrder, s->obs, s->ctrl); assert(g != NULL); s->adj = g->adj; s->edg = g->edg; nsplits = s->nsplits; for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); refine(s, c); if (s->nsplits > nsplits) { i = 0; /* reset i */ /* do more refinement by dependency graph */ for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); refineByDepGraph(s, c); } Vec_IntFree(randVec); ABC_FREE( g->adj ); ABC_FREE( g->edg ); ABC_FREE( g ); } return 1; } static int refineBySim2_left(struct saucy *s, struct coloring *c) { struct saucy_graph *g; Vec_Int_t * randVec; int i, j; int nsplits; for (i = 0; i < NUM_SIM2_ITERATION; i++) { randVec = assignRandomBitsToCells(s->pNtk, c); g = buildSim2Graph(s->pNtk, c, randVec, s->iDep, s->oDep, s->topOrder, s->obs, s->ctrl); assert(g != NULL); s->adj = g->adj; s->edg = g->edg; nsplits = s->nsplits; for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); refine(s, c); if (s->nsplits > nsplits) { /* save the random vector */ Vec_PtrPush(s->randomVectorArray_sim2, randVec); i = 0; /* reset i */ /* do more refinement by dependency graph */ for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); refineByDepGraph(s, c); } else Vec_IntFree(randVec); ABC_FREE( g->adj ); ABC_FREE( g->edg ); ABC_FREE( g ); } s->randomVectorSplit_sim2[s->lev] = Vec_PtrSize(s->randomVectorArray_sim2); return 1; } static int refineBySim2_other(struct saucy *s, struct coloring *c) { struct saucy_graph *g; Vec_Int_t * randVec; int i, j; int ret, nsplits; for (i = s->randomVectorSplit_sim2[s->lev-1]; i < s->randomVectorSplit_sim2[s->lev]; i++) { randVec = (Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim2, i); g = buildSim2Graph(s->pNtk, c, randVec, s->iDep, s->oDep, s->topOrder, s->obs, s->ctrl); if (g == NULL) { assert(c == &s->right); return 0; } s->adj = g->adj; s->edg = g->edg; nsplits = s->nsplits; for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); ret = refine(s, c); if (s->nsplits == nsplits) { assert(c == &s->right); ret = 0; } if (ret) { /* do more refinement by dependency graph */ for (j = 0; j < s->n; j += c->clen[j]+1) add_induce(s, c, j); ret = refineByDepGraph(s, c); } ABC_FREE( g->adj ); ABC_FREE( g->edg ); ABC_FREE( g ); if (!ret) { assert(c == &s->right); return 0; } } return 1; } static int check_OPP_only_has_swaps(struct saucy *s, struct coloring *c) { int j, cell; Vec_Int_t * left_cfront, * right_cfront; if (c == &s->left) return 1; left_cfront = Vec_IntAlloc (1); right_cfront = Vec_IntAlloc (1); for (cell = 0; cell < s->n; cell += (s->left.clen[cell]+1)) { for (j = cell; j <= (cell+s->left.clen[cell]); j++) { Vec_IntPush(left_cfront, s->left.cfront[s->right.lab[j]]); Vec_IntPush(right_cfront, s->right.cfront[s->left.lab[j]]); } Vec_IntSortUnsigned(left_cfront); Vec_IntSortUnsigned(right_cfront); for (j = 0; j < Vec_IntSize(left_cfront); j++) { if (Vec_IntEntry(left_cfront, j) != Vec_IntEntry(right_cfront, j)) { Vec_IntFree(left_cfront); Vec_IntFree(right_cfront); return 0; } } Vec_IntClear(left_cfront); Vec_IntClear(right_cfront); } Vec_IntFree(left_cfront); Vec_IntFree(right_cfront); return 1; } static int check_OPP_for_Boolean_matching(struct saucy *s, struct coloring *c) { int j, cell; int countN1Left, countN2Left; int countN1Right, countN2Right; char *name; if (c == &s->left) return 1; for (cell = 0; cell < s->n; cell += (s->right.clen[cell]+1)) { countN1Left = countN2Left = countN1Right = countN2Right = 0; for (j = cell; j <= (cell+s->right.clen[cell]); j++) { name = getVertexName(s->pNtk, s->left.lab[j]); assert(name[0] == 'N' && name[2] == ':'); if (name[1] == '1') countN1Left++; else { assert(name[1] == '2'); countN2Left++; } name = getVertexName(s->pNtk, s->right.lab[j]); assert(name[0] == 'N' && name[2] == ':'); if (name[1] == '1') countN1Right++; else { assert(name[1] == '2'); countN2Right++; } } if (countN1Left != countN2Right || countN2Left != countN1Right) return 0; } return 1; } static int double_check_OPP_isomorphism(struct saucy *s, struct coloring * c) { /* This is the new enhancement in saucy 3.0 */ int i, j, v, sum1, sum2, xor1, xor2; if (c == &s->left) return 1; for (i = s->nsplits - 1; i > s->splitlev[s->lev-1]; --i) { v = c->lab[s->splitwho[i]]; sum1 = xor1 = 0; for (j = s->adj[v]; j < s->adj[v+1]; j++) { sum1 += c->cfront[s->edg[j]]; xor1 ^= c->cfront[s->edg[j]]; } v = s->left.lab[s->splitwho[i]]; sum2 = xor2 = 0; for (j = s->adj[v]; j < s->adj[v+1]; j++) { sum2 += s->left.cfront[s->edg[j]]; xor2 ^= s->left.cfront[s->edg[j]]; } if ((sum1 != sum2) || (xor1 != xor2)) return 0; v = c->lab[s->splitfrom[i]]; sum1 = xor1 = 0; for (j = s->adj[v]; j < s->adj[v+1]; j++) { sum1 += c->cfront[s->edg[j]]; xor1 ^= c->cfront[s->edg[j]]; } v = s->left.lab[s->splitfrom[i]]; sum2 = xor2 = 0; for (j = s->adj[v]; j < s->adj[v+1]; j++) { sum2 += s->left.cfront[s->edg[j]]; xor2 ^= s->left.cfront[s->edg[j]]; } if ((sum1 != sum2) || (xor1 != xor2)) return 0; } return 1; } static int descend(struct saucy *s, struct coloring *c, int target, int min) { int back = target + c->clen[target]; /* Count this node */ ++s->stats->nodes; /* Move the minimum label to the back */ swap_labels(c, min, back); /* Split the cell */ s->difflev[s->lev] = s->ndiffs; s->undifflev[s->lev] = s->nundiffs; ++s->lev; s->split(s, c, target, back); /* Now go and do some work */ //print_partition(&s->left, NULL, s->n, s->pNtk, 1); if (!refineByDepGraph(s, c)) return 0; /* if we are looking for a Boolean matching, check the OPP and * backtrack if the OPP maps part of one network to itself */ if (s->fBooleanMatching && !check_OPP_for_Boolean_matching(s, c)) return 0; //print_partition(&s->left, NULL, s->n, s->pNtk, 1); if (REFINE_BY_SIM_1 && !s->refineBySim1(s, c)) return 0; //print_partition(&s->left, NULL, s->n, s->pNtk, 1); if (REFINE_BY_SIM_2 && !s->refineBySim2(s, c)) return 0; /* do the check once more, maybe the check fails, now that refinement is complete */ if (s->fBooleanMatching && !check_OPP_for_Boolean_matching(s, c)) return 0; if (s->fLookForSwaps && !check_OPP_only_has_swaps(s, c)) return 0; if (!double_check_OPP_isomorphism(s, c)) return 0; return 1; } static int select_smallest_max_connected_cell(struct saucy *s, int start, int end) { int smallest_cell = -1, cell; int smallest_cell_size = s->n; int max_connections = -1; int * connection_list = zeros(s->n); cell = start; while( !s->left.clen[cell] ) cell++; while( cell < end ) { if (s->left.clen[cell] <= smallest_cell_size) { int i, connections = 0;; for (i = s->depAdj[s->left.lab[cell]]; i < s->depAdj[s->left.lab[cell]+1]; i++) { if (!connection_list[s->depEdg[i]]) { connections++; connection_list[s->depEdg[i]] = 1; } } if ((s->left.clen[cell] < smallest_cell_size) || (connections > max_connections)) { smallest_cell_size = s->left.clen[cell]; max_connections = connections; smallest_cell = cell; } for (i = s->depAdj[s->left.lab[cell]]; i < s->depAdj[s->left.lab[cell]+1]; i++) connection_list[s->depEdg[i]] = 0; } cell = s->nextnon[cell]; } ABC_FREE( connection_list ); return smallest_cell; } static int descend_leftmost(struct saucy *s) { int target, min; /* Keep going until we're discrete */ //print_partition(&s->left, NULL, s->n, s->pNtk, 1); while (!at_terminal(s)) { //target = min = s->nextnon[-1]; if (s->nextnon[-1] < Abc_NtkPoNum(s->pNtk)) target = min = select_smallest_max_connected_cell(s, s->nextnon[-1], Abc_NtkPoNum(s->pNtk)); else target = min = select_smallest_max_connected_cell(s, Abc_NtkPoNum(s->pNtk), s->n); if (s->fPrintTree) printf("%s->%s\n", getVertexName(s->pNtk, s->left.lab[min]), getVertexName(s->pNtk, s->left.lab[min])); s->splitvar[s->lev] = s->left.lab[min]; s->start[s->lev] = target; s->splitlev[s->lev] = s->nsplits; if (!descend(s, &s->left, target, min)) return 0; } s->splitlev[s->lev] = s->n; return 1; } /* * If the remaining nonsingletons in this partition match exactly * those nonsingletons from the leftmost branch of the search tree, * then there is no point in continuing descent. */ static int zeta_fixed(struct saucy *s) { return s->ndiffs == s->nundiffs; } static void select_dynamically(struct saucy *s, int *target, int *lmin, int *rmin) { /* Both clens are equal; this clarifies the code a bit */ const int *clen = s->left.clen; int i, k; //int cf; /* * If there's a pair, use it. pairs[0] should always work, * but we use a checked loop instead because I'm not 100% sure * I'm "unpairing" at every point I should be. */ for (i = 0; i < s->npairs; ++i) { k = s->pairs[i]; *target = s->right.cfront[k]; *lmin = s->left.unlab[s->right.lab[s->left.unlab[k]]]; *rmin = s->right.unlab[k]; if (clen[*target] && in_cell_range(&s->left, *lmin, *target) && in_cell_range(&s->right, *rmin, *target)) return; } /* Diffnons is only consistent when there are no baddies */ /*if (s->ndiffnons != -1) { *target = *lmin = *rmin = s->right.cfront[s->diffnons[0]]; return; }*/ /* Pick any old target cell and element */ /*for (i = 0; i < s->ndiffs; ++i) { cf = s->right.cfront[s->diffs[i]]; if (clen[cf]) { *lmin = *rmin = *target = cf; return; } }*/ for (i = 0; i < s->n; i += (clen[i]+1)) { if (!clen[i]) continue; *rmin = *lmin = *target = i; if (s->right.cfront[s->left.lab[*lmin]] == *target) *rmin = s->right.unlab[s->left.lab[*lmin]]; return; } /* we should never get here */ abort(); } static void select_statically(struct saucy *s, int *target, int *lmin, int *rmin) { int i; *target = *rmin = s->left.cfront[s->splitvar[s->lev]]; *lmin = s->left.unlab[s->splitvar[s->lev]]; /* try to map identically! */ for (i = *rmin; i <= (*rmin + s->right.clen[*target]); i++) if (s->right.lab[*rmin] == s->left.lab[*lmin]) { *rmin = i; break; } } static int descend_left(struct saucy *s) { int target, lmin, rmin; /* Check that we ended at the right spot */ if (s->nsplits != s->splitlev[s->lev]) return 0; /* Keep going until we're discrete */ while (!at_terminal(s) /*&& !zeta_fixed(s)*/) { /* We can pick any old target cell and element */ s->select_decomposition(s, &target, &lmin, &rmin); if (s->fPrintTree) { //printf("in level %d: %d->%d\n", s->lev, s->left.lab[lmin], s->right.lab[rmin]); printf("in level %d: %s->%s\n", s->lev, getVertexName(s->pNtk, s->left.lab[lmin]), getVertexName(s->pNtk, s->right.lab[rmin])); } /* Check if we need to refine on the left */ s->match = 0; s->start[s->lev] = target; s->split = split_left; if (SELECT_DYNAMICALLY) { s->refineBySim1 = refineBySim1_left; s->refineBySim2 = refineBySim2_left; } descend(s, &s->left, target, lmin); s->splitlev[s->lev] = s->nsplits; s->split = split_other; if (SELECT_DYNAMICALLY) { s->refineBySim1 = refineBySim1_other; s->refineBySim2 = refineBySim2_other; } --s->lev; s->nsplits = s->splitlev[s->lev]; /* Now refine on the right and ensure matching */ s->specmin[s->lev] = s->right.lab[rmin]; if (!descend(s, &s->right, target, rmin)) return 0; if (s->nsplits != s->splitlev[s->lev]) return 0; } return 1; } static int find_representative(int k, int *theta) { int rep, tmp; /* Find the minimum cell representative */ for (rep = k; rep != theta[rep]; rep = theta[rep]); /* Update all intermediaries */ while (theta[k] != rep) { tmp = theta[k]; theta[k] = rep; k = tmp; } return rep; } static void update_theta(struct saucy *s) { int i, k, x, y, tmp; for (i = 0; i < s->ndiffs; ++i) { k = s->unsupp[i]; x = find_representative(k, s->theta); y = find_representative(s->gamma[k], s->theta); if (x != y) { if (x > y) { tmp = x; x = y; y = tmp; } s->theta[y] = x; s->thsize[x] += s->thsize[y]; s->thnext[s->thprev[y]] = s->thnext[y]; s->thprev[s->thnext[y]] = s->thprev[y]; s->threp[s->thfront[y]] = s->thnext[y]; } } } static int theta_prune(struct saucy *s) { int start = s->start[s->lev]; int label, rep, irep; irep = find_representative(s->indmin, s->theta); while (s->kanctar) { label = s->anctar[--s->kanctar]; rep = find_representative(label, s->theta); if (rep == label && rep != irep) { return s->right.unlab[label] - start; } } return -1; } static int orbit_prune(struct saucy *s) { int i, label, fixed, min = -1; int k = s->start[s->lev]; int size = s->right.clen[k] + 1; int *cell = s->right.lab + k; /* The previously fixed value */ fixed = cell[size-1]; /* Look for the next minimum cell representative */ for (i = 0; i < size-1; ++i) { label = cell[i]; /* Skip things we've already considered */ if (label <= fixed) continue; /* Skip things that we'll consider later */ if (min != -1 && label > cell[min]) continue; /* New candidate minimum */ min = i; } return min; } static void note_anctar_reps(struct saucy *s) { int i, j, k, m, f, rep, tmp; /* * Undo the previous level's splits along leftmost so that we * join the appropriate lists of theta reps. */ for (i = s->splitlev[s->anc+1]-1; i >= s->splitlev[s->anc]; --i) { f = s->splitfrom[i]; j = s->threp[f]; k = s->threp[s->splitwho[i]]; s->thnext[s->thprev[j]] = k; s->thnext[s->thprev[k]] = j; tmp = s->thprev[j]; s->thprev[j] = s->thprev[k]; s->thprev[k] = tmp; for (m = k; m != j; m = s->thnext[m]) { s->thfront[m] = f; } } /* * Just copy over the target's reps and sort by cell size, in * the hopes of trimming some otherwise redundant generators. */ s->kanctar = 0; s->anctar[s->kanctar++] = rep = s->threp[s->start[s->lev]]; for (k = s->thnext[rep]; k != rep; k = s->thnext[k]) { s->anctar[s->kanctar++] = k; } array_indirect_sort(s->anctar, s->thsize, s->kanctar); } static void multiply_index(struct saucy *s, int k) { if ((s->stats->grpsize_base *= k) > 1e10) { s->stats->grpsize_base /= 1e10; s->stats->grpsize_exp += 10; } } static int backtrack_leftmost(struct saucy *s) { int rep = find_representative(s->indmin, s->theta); int repsize = s->thsize[rep]; int min = -1; pick_all_the_pairs(s); clear_undiffnons(s); s->ndiffs = s->nundiffs = s->npairs = s->ndiffnons = 0; if (repsize != s->right.clen[s->start[s->lev]]+1) { min = theta_prune(s); } if (min == -1) { multiply_index(s, repsize); } return min; } static int backtrack_other(struct saucy *s) { int cf = s->start[s->lev]; int cb = cf + s->right.clen[cf]; int spec = s->specmin[s->lev]; int min; /* Avoid using pairs until we get back to leftmost. */ pick_all_the_pairs(s); clear_undiffnons(s); s->npairs = s->ndiffnons = -1; if (s->right.lab[cb] == spec) { min = find_min(s, cf); if (min == cb) { min = orbit_prune(s); } else { min -= cf; } } else { min = orbit_prune(s); if (min != -1 && s->right.lab[min + cf] == spec) { swap_labels(&s->right, min + cf, cb); min = orbit_prune(s); } } return min; } static void rewind_coloring(struct saucy *s, struct coloring *c, int lev) { int i, cf, ff, splits = s->splitlev[lev]; for (i = s->nsplits - 1; i >= splits; --i) { cf = s->splitfrom[i]; ff = s->splitwho[i]; c->clen[cf] += c->clen[ff] + 1; fix_fronts(c, cf, ff); } } static void rewind_simulation_vectors(struct saucy *s, int lev) { int i; for (i = s->randomVectorSplit_sim1[lev]; i < Vec_PtrSize(s->randomVectorArray_sim1); i++) Vec_IntFree((Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim1, i)); Vec_PtrShrink(s->randomVectorArray_sim1, s->randomVectorSplit_sim1[lev]); for (i = s->randomVectorSplit_sim2[lev]; i < Vec_PtrSize(s->randomVectorArray_sim2); i++) Vec_IntFree((Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim2, i)); Vec_PtrShrink(s->randomVectorArray_sim2, s->randomVectorSplit_sim2[lev]); } static int do_backtrack(struct saucy *s) { int i, cf, cb; /* Undo the splits up to this level */ rewind_coloring(s, &s->right, s->lev); s->nsplits = s->splitlev[s->lev]; /* Rewind diff information */ for (i = s->ndiffs - 1; i >= s->difflev[s->lev]; --i) { s->diffmark[s->diffs[i]] = 0; } s->ndiffs = s->difflev[s->lev]; s->nundiffs = s->undifflev[s->lev]; /* Point to the target cell */ cf = s->start[s->lev]; cb = cf + s->right.clen[cf]; /* Update ancestor with zeta if we've rewound more */ if (s->anc > s->lev) { s->anc = s->lev; s->indmin = s->left.lab[cb]; s->match = 1; note_anctar_reps(s); } /* Perform backtracking appropriate to our location */ return s->lev == s->anc ? backtrack_leftmost(s) : backtrack_other(s); } static int backtrack_loop(struct saucy *s) { int min; /* Backtrack as long as we're exhausting target cells */ for (--s->lev; s->lev; --s->lev) { min = do_backtrack(s); if (min != -1) return min + s->start[s->lev]; } return -1; } static int backtrack(struct saucy *s) { int min, old, tmp; old = s->nsplits; min = backtrack_loop(s); tmp = s->nsplits; s->nsplits = old; rewind_coloring(s, &s->left, s->lev+1); s->nsplits = tmp; if (SELECT_DYNAMICALLY) rewind_simulation_vectors(s, s->lev+1); return min; } static int backtrack_bad(struct saucy *s) { int min, old, tmp; old = s->lev; min = backtrack_loop(s); if (BACKTRACK_BY_SAT) { int oldLev = s->lev; while (!backtrackBysatCounterExamples(s, &s->right)) { min = backtrack_loop(s); if (!s->lev) { if (s->fPrintTree) printf("Backtrack by SAT from level %d to %d\n", oldLev, 0); return -1; } } if (s->fPrintTree) if (s->lev < oldLev) printf("Backtrack by SAT from level %d to %d\n", oldLev, s->lev); } tmp = s->nsplits; s->nsplits = s->splitlev[old]; rewind_coloring(s, &s->left, s->lev+1); s->nsplits = tmp; if (SELECT_DYNAMICALLY) rewind_simulation_vectors(s, s->lev+1); return min; } void prepare_permutation_ntk(struct saucy *s) { int i; Abc_Obj_t * pObj, * pObjPerm; int numouts = Abc_NtkPoNum(s->pNtk); Nm_ManFree( s->pNtk_permuted->pManName ); s->pNtk_permuted->pManName = Nm_ManCreate( Abc_NtkCiNum(s->pNtk) + Abc_NtkCoNum(s->pNtk) + Abc_NtkBoxNum(s->pNtk) ); for (i = 0; i < s->n; ++i) { if (i < numouts) { pObj = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk->vPos, i); pObjPerm = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk_permuted->vPos, s->gamma[i]); } else { pObj = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk->vPis, i - numouts); pObjPerm = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk_permuted->vPis, s->gamma[i] - numouts); } Abc_ObjAssignName( pObjPerm, Abc_ObjName(pObj), NULL ); } Abc_NtkOrderObjsByName( s->pNtk_permuted, 1 ); /* print the permutation */ /*for (i = 0; i < s->ndiffs; ++i) printf(" %d->%d", s->unsupp[i], s->diffs[i]); printf("\n"); Abc_NtkForEachCo( s->pNtk, pObj, i ) printf (" %d", Abc_ObjId(pObj)-1-Abc_NtkPiNum(s->pNtk)); Abc_NtkForEachCi( s->pNtk, pObj, i ) printf (" %d", Abc_ObjId(pObj)-1+Abc_NtkPoNum(s->pNtk)); printf("\n"); Abc_NtkForEachCo( s->pNtk_permuted, pObj, i ) printf (" %d", Abc_ObjId(pObj)-1-Abc_NtkPiNum(s->pNtk_permuted)); Abc_NtkForEachCi( s->pNtk_permuted, pObj, i ) printf (" %d", Abc_ObjId(pObj)-1+Abc_NtkPoNum(s->pNtk_permuted)); printf("\n");*/ } static void prepare_permutation(struct saucy *s) { int i, k; for (i = 0; i < s->ndiffs; ++i) { k = s->right.unlab[s->diffs[i]]; s->unsupp[i] = s->left.lab[k]; s->gamma[s->left.lab[k]] = s->right.lab[k]; } prepare_permutation_ntk(s); } void unprepare_permutation_ntk(struct saucy *s) { int i; Abc_Obj_t * pObj, * pObjPerm; int numouts = Abc_NtkPoNum(s->pNtk); Nm_ManFree( s->pNtk_permuted->pManName ); s->pNtk_permuted->pManName = Nm_ManCreate( Abc_NtkCiNum(s->pNtk) + Abc_NtkCoNum(s->pNtk) + Abc_NtkBoxNum(s->pNtk) ); for (i = 0; i < s->n; ++i) { if (i < numouts) { pObj = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk->vPos, s->gamma[i]); pObjPerm = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk_permuted->vPos, i); } else { pObj = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk->vPis, s->gamma[i] - numouts); pObjPerm = (Abc_Obj_t *)Vec_PtrEntry(s->pNtk_permuted->vPis, i - numouts); } Abc_ObjAssignName( pObjPerm, Abc_ObjName(pObj), NULL ); } Abc_NtkOrderObjsByName( s->pNtk_permuted, 1 ); } static void unprepare_permutation(struct saucy *s) { int i; unprepare_permutation_ntk(s); for (i = 0; i < s->ndiffs; ++i) { s->gamma[s->unsupp[i]] = s->unsupp[i]; } } static int do_search(struct saucy *s) { int min; unprepare_permutation(s); /* Backtrack to the ancestor with zeta */ if (s->lev > s->anc) s->lev = s->anc + 1; /* Perform additional backtracking */ min = backtrack(s); if (s->fBooleanMatching && (s->stats->grpsize_base > 1 || s->stats->grpsize_exp > 0)) return 0; if (s->fPrintTree && s->lev > 0) { //printf("in level %d: %d->%d\n", s->lev, s->left.lab[s->splitwho[s->nsplits]], s->right.lab[min]); printf("in level %d: %s->%s\n", s->lev, getVertexName(s->pNtk, s->left.lab[s->splitwho[s->nsplits]]), getVertexName(s->pNtk, s->right.lab[min])); } /* Keep going while there are tree nodes to expand */ while (s->lev) { /* Descend to a new leaf node */ if (descend(s, &s->right, s->start[s->lev], min) && descend_left(s)) { /* Prepare permutation */ prepare_permutation(s); /* If we found an automorphism, return it */ if (s->is_automorphism(s)) { ++s->stats->gens; s->stats->support += s->ndiffs; update_theta(s); s->print_automorphism(s->gFile, s->n, s->gamma, s->ndiffs, s->unsupp, s->marks, s->pNtk); unprepare_permutation(s); return 1; } else { unprepare_permutation(s); } } /* If we get here, something went wrong; backtrack */ ++s->stats->bads; min = backtrack_bad(s); if (s->fPrintTree) { printf("BAD NODE\n"); if (s->lev > 0) { //printf("in level %d: %d->%d\n", s->lev, s->left.lab[s->splitwho[s->nsplits]], s->right.lab[min]); printf("in level %d: %s->%s\n", s->lev, getVertexName(s->pNtk, s->left.lab[s->splitwho[s->nsplits]]), getVertexName(s->pNtk, s->right.lab[min])); } } } /* Normalize group size */ while (s->stats->grpsize_base >= 10.0) { s->stats->grpsize_base /= 10; ++s->stats->grpsize_exp; } return 0; } void saucy_search( Abc_Ntk_t * pNtk, struct saucy *s, int directed, const int *colors, struct saucy_stats *stats) { int i, j, max = 0; struct saucy_graph *g; extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ); /* Save network information */ s->pNtk = pNtk; s->pNtk_permuted = Abc_NtkDup( pNtk ); /* Builde dependency graph */ g = buildDepGraph(pNtk, s->iDep, s->oDep); /* Save graph information */ s->n = g->n; s->depAdj = g->adj; s->depEdg = g->edg; /*s->dadj = g->adj + g->n + 1; s->dedg = g->edg + g->e;*/ /* Save client information */ s->stats = stats; /* Polymorphism */ if (directed) { s->is_automorphism = is_directed_automorphism; s->ref_singleton = ref_singleton_directed; s->ref_nonsingle = ref_nonsingle_directed; } else { s->is_automorphism = is_undirected_automorphism; s->ref_singleton = ref_singleton_undirected; s->ref_nonsingle = ref_nonsingle_undirected; } /* Initialize scalars */ s->indmin = 0; s->lev = s->anc = 1; s->ndiffs = s->nundiffs = s->ndiffnons = 0; s->activityInc = 1; /* The initial orbit partition is discrete */ for (i = 0; i < s->n; ++i) { s->theta[i] = i; } /* The initial permutation is the identity */ for (i = 0; i < s->n; ++i) { s->gamma[i] = i; } /* Initially every cell of theta has one element */ for (i = 0; i < s->n; ++i) { s->thsize[i] = 1; } /* Every theta rep list is singleton */ for (i = 0; i < s->n; ++i) { s->thprev[i] = s->thnext[i] = i; } /* We have no pairs yet */ s->npairs = 0; for (i = 0; i < s->n; ++i) { s->unpairs[i] = -1; } /* Ensure no stray pointers in undiffnons, which is checked by removed_diffnon() */ for (i = 0; i < s->n; ++i) { s->undiffnons[i] = -1; } /* Initialize stats */ s->stats->grpsize_base = 1.0; s->stats->grpsize_exp = 0; s->stats->nodes = 1; s->stats->bads = s->stats->gens = s->stats->support = 0; /* Prepare for refinement */ s->nninduce = s->nsinduce = 0; s->csize = 0; /* Count cell sizes */ for (i = 0; i < s->n; ++i) { s->ccount[colors[i]]++; if (max < colors[i]) max = colors[i]; } s->nsplits = max + 1; /* Build cell lengths */ s->left.clen[0] = s->ccount[0] - 1; for (i = 0; i < max; ++i) { s->left.clen[s->ccount[i]] = s->ccount[i+1] - 1; s->ccount[i+1] += s->ccount[i]; } /* Build the label array */ for (i = 0; i < s->n; ++i) { set_label(&s->left, --s->ccount[colors[i]], i); } /* Clear out ccount */ for (i = 0; i <= max; ++i) { s->ccount[i] = 0; } /* Update refinement stuff based on initial partition */ for (i = 0; i < s->n; i += s->left.clen[i]+1) { add_induce(s, &s->left, i); fix_fronts(&s->left, i, i); } /* Prepare lists based on cell lengths */ for (i = 0, j = -1; i < s->n; i += s->left.clen[i] + 1) { if (!s->left.clen[i]) continue; s->prevnon[i] = j; s->nextnon[j] = i; j = i; } /* Fix the end */ s->prevnon[s->n] = j; s->nextnon[j] = s->n; /* Preprocessing after initial coloring */ s->split = split_init; s->refineBySim1 = refineBySim1_init; s->refineBySim2 = refineBySim2_init; //print_partition(&s->left, NULL, s->n, s->pNtk, 1); printf("Initial Refine by Dependency graph ... "); refineByDepGraph(s, &s->left); //print_partition(&s->left, NULL, s->n, s->pNtk, 1); printf("done!\n"); printf("Initial Refine by Simulation ... "); if (REFINE_BY_SIM_1) s->refineBySim1(s, &s->left); //print_partition(&s->left, NULL, s->n, s->pNtk, 1); if (REFINE_BY_SIM_2) s->refineBySim2(s, &s->left); //print_partition(&s->left, NULL, s->n, s->pNtk, 1); printf("done!\n\t--------------------\n"); /* Descend along the leftmost branch and compute zeta */ s->refineBySim1 = refineBySim1_left; s->refineBySim2 = refineBySim2_left; descend_leftmost(s); s->split = split_other; s->refineBySim1 = refineBySim1_other; s->refineBySim2 = refineBySim2_other; /* Our common ancestor with zeta is the current level */ s->stats->levels = s->anc = s->lev; /* Copy over this data to our non-leftmost coloring */ memcpy(s->right.lab, s->left.lab, s->n * sizeof(int)); memcpy(s->right.unlab, s->left.unlab, s->n * sizeof(int)); memcpy(s->right.clen, s->left.clen, s->n * sizeof(int)); memcpy(s->right.cfront, s->left.cfront, s->n * sizeof(int)); /* The reps are just the labels at this point */ memcpy(s->threp, s->left.lab, s->n * sizeof(int)); memcpy(s->thfront, s->left.unlab, s->n * sizeof(int)); /* choose cell selection method */ if (SELECT_DYNAMICALLY) s->select_decomposition = select_dynamically; else s->select_decomposition = select_statically; /* Keep running till we're out of automorphisms */ while (do_search(s)); } void saucy_free(struct saucy *s) { int i; ABC_FREE(s->undiffnons); ABC_FREE(s->diffnons); ABC_FREE(s->unpairs); ABC_FREE(s->pairs); ABC_FREE(s->thfront); ABC_FREE(s->threp); ABC_FREE(s->thnext); ABC_FREE(s->thprev); ABC_FREE(s->specmin); ABC_FREE(s->anctar); ABC_FREE(s->thsize); ABC_FREE(s->undifflev); ABC_FREE(s->difflev); ABC_FREE(s->diffs); ABC_FREE(s->diffmark); ABC_FREE(s->conncnts); ABC_FREE(s->unsupp); ABC_FREE(s->splitlev); ABC_FREE(s->splitfrom); ABC_FREE(s->splitwho); ABC_FREE(s->splitvar); ABC_FREE(s->right.unlab); ABC_FREE(s->right.lab); ABC_FREE(s->left.unlab); ABC_FREE(s->left.lab); ABC_FREE(s->theta); ABC_FREE(s->junk); ABC_FREE(s->gamma); ABC_FREE(s->start); ABC_FREE(s->prevnon); free(s->nextnon-1); ABC_FREE(s->clist); ABC_FREE(s->ccount); ABC_FREE(s->count); ABC_FREE(s->bucket); ABC_FREE(s->stuff); ABC_FREE(s->right.clen); ABC_FREE(s->right.cfront); ABC_FREE(s->left.clen); ABC_FREE(s->left.cfront); ABC_FREE(s->indmark); ABC_FREE(s->sinduce); ABC_FREE(s->ninduce); ABC_FREE(s->depAdj); ABC_FREE(s->depEdg); ABC_FREE(s->marks); for (i = 0; i < Abc_NtkPiNum(s->pNtk); i++) { Vec_IntFree( s->iDep[i] ); Vec_IntFree( s->obs[i] ); Vec_PtrFree( s->topOrder[i] ); } for (i = 0; i < Abc_NtkPoNum(s->pNtk); i++) { Vec_IntFree( s->oDep[i] ); Vec_IntFree( s->ctrl[i] ); } for (i = 0; i < Vec_PtrSize(s->randomVectorArray_sim1); i++) Vec_IntFree((Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim1, i)); for (i = 0; i < Vec_PtrSize(s->randomVectorArray_sim2); i++) Vec_IntFree((Vec_Int_t *)Vec_PtrEntry(s->randomVectorArray_sim2, i)); Vec_PtrFree( s->randomVectorArray_sim1 ); Vec_PtrFree( s->randomVectorArray_sim2 ); ABC_FREE(s->randomVectorSplit_sim1); ABC_FREE(s->randomVectorSplit_sim2); Abc_NtkDelete( s->pNtk_permuted ); for (i = 0; i < Vec_PtrSize(s->satCounterExamples); i++) { struct sim_result * cex = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i); ABC_FREE( cex->inVec ); ABC_FREE( cex->outVec ); ABC_FREE( cex ); } Vec_PtrFree(s->satCounterExamples); ABC_FREE( s->pModel ); ABC_FREE( s->iDep ); ABC_FREE( s->oDep ); ABC_FREE( s->obs ); ABC_FREE( s->ctrl ); ABC_FREE( s->topOrder ); ABC_FREE(s); } struct saucy * saucy_alloc(Abc_Ntk_t * pNtk) { int i; int numouts = Abc_NtkPoNum(pNtk); int numins = Abc_NtkPiNum(pNtk); int n = numins + numouts; struct saucy *s = ABC_ALLOC(struct saucy, 1); if (s == NULL) return NULL; s->ninduce = ints(n); s->sinduce = ints(n); s->indmark = bits(n); s->left.cfront = zeros(n); s->left.clen = ints(n); s->right.cfront = zeros(n); s->right.clen = ints(n); s->stuff = bits(n+1); s->bucket = ints(n+2); s->count = ints(n+1); s->ccount = zeros(n); s->clist = ints(n); s->nextnon = ints(n+1) + 1; s->prevnon = ints(n+1); s->anctar = ints(n); s->start = ints(n); s->gamma = ints(n); s->junk = ints(n); s->theta = ints(n); s->thsize = ints(n); s->left.lab = ints(n); s->left.unlab = ints(n); s->right.lab = ints(n); s->right.unlab = ints(n); s->splitvar = ints(n); s->splitwho = ints(n); s->splitfrom = ints(n); s->splitlev = ints(n+1); s->unsupp = ints(n); s->conncnts = zeros(n); s->diffmark = bits(n); s->diffs = ints(n); s->difflev = ints(n); s->undifflev = ints(n); s->specmin = ints(n); s->thnext = ints(n); s->thprev = ints(n); s->threp = ints(n); s->thfront = ints(n); s->pairs = ints(n); s->unpairs = ints(n); s->diffnons = ints(n); s->undiffnons = ints(n); s->marks = bits(n); s->iDep = ABC_ALLOC( Vec_Int_t*, numins ); s->oDep = ABC_ALLOC( Vec_Int_t*, numouts ); s->obs = ABC_ALLOC( Vec_Int_t*, numins ); s->ctrl = ABC_ALLOC( Vec_Int_t*, numouts ); for(i = 0; i < numins; i++) { s->iDep[i] = Vec_IntAlloc( 1 ); s->obs[i] = Vec_IntAlloc( 1 ); } for(i = 0; i < numouts; i++) { s->oDep[i] = Vec_IntAlloc( 1 ); s->ctrl[i] = Vec_IntAlloc( 1 ); } s->randomVectorArray_sim1 = Vec_PtrAlloc( n ); s->randomVectorSplit_sim1 = zeros( n ); s->randomVectorArray_sim2 = Vec_PtrAlloc( n ); s->randomVectorSplit_sim2= zeros( n ); s->satCounterExamples = Vec_PtrAlloc( 1 ); s->pModel = ints( numins ); if (s->ninduce && s->sinduce && s->left.cfront && s->left.clen && s->right.cfront && s->right.clen && s->stuff && s->bucket && s->count && s->ccount && s->clist && s->nextnon-1 && s->prevnon && s->start && s->gamma && s->theta && s->left.unlab && s->right.lab && s->right.unlab && s->left.lab && s->splitvar && s->splitwho && s->junk && s->splitfrom && s->splitlev && s->thsize && s->unsupp && s->conncnts && s->anctar && s->diffmark && s->diffs && s->indmark && s->thnext && s->thprev && s->threp && s->thfront && s->pairs && s->unpairs && s->diffnons && s->undiffnons && s->difflev && s->undifflev && s->specmin) { return s; } else { saucy_free(s); return NULL; } } static void print_stats(FILE *f, struct saucy_stats stats ) { fprintf(f, "group size = %fe%d\n", stats.grpsize_base, stats.grpsize_exp); fprintf(f, "levels = %d\n", stats.levels); fprintf(f, "nodes = %d\n", stats.nodes); fprintf(f, "generators = %d\n", stats.gens); fprintf(f, "total support = %d\n", stats.support); fprintf(f, "average support = %.2f\n",(double)(stats.support)/(double)(stats.gens)); fprintf(f, "nodes per generator = %.2f\n",(double)(stats.nodes)/(double)(stats.gens)); fprintf(f, "bad nodes = %d\n", stats.bads); } /* From this point up are SAUCY functions*/ ///////////////////////////////////////////////////////////////////////////////////////////////////////// /* From this point down are new functions */ static char * getVertexName(Abc_Ntk_t *pNtk, int v) { Abc_Obj_t * pObj; int numouts = Abc_NtkPoNum(pNtk); if (v < numouts) pObj = (Abc_Obj_t *)Vec_PtrEntry(pNtk->vPos, v); else pObj = (Abc_Obj_t *)Vec_PtrEntry(pNtk->vPis, v - numouts); return Abc_ObjName(pObj); } static Vec_Ptr_t ** findTopologicalOrder( Abc_Ntk_t * pNtk ) { Vec_Ptr_t ** vNodes; Abc_Obj_t * pObj, * pFanout; int i, k; extern void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); /* start the array of nodes */ vNodes = ABC_ALLOC(Vec_Ptr_t *, Abc_NtkPiNum(pNtk)); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) vNodes[i] = Vec_PtrAlloc(50); Abc_NtkForEachCi( pNtk, pObj, i ) { /* set the traversal ID */ Abc_NtkIncrementTravId( pNtk ); Abc_NodeSetTravIdCurrent( pObj ); pObj = Abc_ObjFanout0Ntk(pObj); Abc_ObjForEachFanout( pObj, pFanout, k ) Abc_NtkDfsReverse_rec( pFanout, vNodes[i] ); } return vNodes; } static void getDependencies(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep) { Vec_Ptr_t * vSuppFun; int i, j; vSuppFun = Sim_ComputeFunSupp(pNtk, 0); for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { char * seg = (char *)vSuppFun->pArray[i]; for(j = 0; j < Abc_NtkPiNum(pNtk); j+=8) { if(((*seg) & 0x01) == 0x01) Vec_IntPushOrder(oDep[i], j); if(((*seg) & 0x02) == 0x02) Vec_IntPushOrder(oDep[i], j+1); if(((*seg) & 0x04) == 0x04) Vec_IntPushOrder(oDep[i], j+2); if(((*seg) & 0x08) == 0x08) Vec_IntPushOrder(oDep[i], j+3); if(((*seg) & 0x10) == 0x10) Vec_IntPushOrder(oDep[i], j+4); if(((*seg) & 0x20) == 0x20) Vec_IntPushOrder(oDep[i], j+5); if(((*seg) & 0x40) == 0x40) Vec_IntPushOrder(oDep[i], j+6); if(((*seg) & 0x80) == 0x80) Vec_IntPushOrder(oDep[i], j+7); seg++; } } for(i = 0; i < Abc_NtkPoNum(pNtk); i++) for(j = 0; j < Vec_IntSize(oDep[i]); j++) Vec_IntPush(iDep[Vec_IntEntry(oDep[i], j)], i); /*for(i = 0; i < Abc_NtkPoNum(pNtk); i++) { printf("Output %d: ", i); for(j = 0; j < Vec_IntSize(oDep[i]); j++) printf("%d ", Vec_IntEntry(oDep[i], j)); printf("\n"); } printf("\n"); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) { printf("Input %d: ", i); for(j = 0; j < Vec_IntSize(iDep[i]); j++) printf("%d ", Vec_IntEntry(iDep[i], j)); printf("\n"); } printf("\n"); */ } static void getDependenciesDummy(Abc_Ntk_t *pNtk, Vec_Int_t** iDep, Vec_Int_t** oDep) { int i, j; /* let's assume that every output is dependent on every input */ for(i = 0; i < Abc_NtkPoNum(pNtk); i++) for(j = 0; j < Abc_NtkPiNum(pNtk); j++) Vec_IntPush(oDep[i], j); for(i = 0; i < Abc_NtkPiNum(pNtk); i++) for(j = 0; j < Abc_NtkPoNum(pNtk); j++) Vec_IntPush(iDep[i], j); } static struct saucy_graph * buildDepGraph(Abc_Ntk_t *pNtk, Vec_Int_t ** iDep, Vec_Int_t ** oDep) { int i, j, k; struct saucy_graph *g = NULL; int n, e, *adj, *edg; n = Abc_NtkPoNum(pNtk) + Abc_NtkPiNum(pNtk); for (e = 0, i = 0; i < Abc_NtkPoNum(pNtk); i++) e += Vec_IntSize(oDep[i]); g = ABC_ALLOC(struct saucy_graph, 1); adj = zeros(n+1); edg = ints(2*e); g->n = n; g->e = e; g->adj = adj; g->edg = edg; adj[0] = 0; for (i = 0; i < n; i++) { /* first add outputs and then inputs */ if ( i < Abc_NtkPoNum(pNtk)) { adj[i+1] = adj[i] + Vec_IntSize(oDep[i]); for (k = 0, j = adj[i]; j < adj[i+1]; j++, k++) edg[j] = Vec_IntEntry(oDep[i], k) + Abc_NtkPoNum(pNtk); } else { adj[i+1] = adj[i] + Vec_IntSize(iDep[i-Abc_NtkPoNum(pNtk)]); for (k = 0, j = adj[i]; j < adj[i+1]; j++, k++) edg[j] = Vec_IntEntry(iDep[i-Abc_NtkPoNum(pNtk)], k); } } /* print graph for testing */ /*for (i = 0; i < n; i++) { printf("%d: ", i); for (j = adj[i]; j < adj[i+1]; j++) printf("%d ", edg[j]); printf("\n"); }*/ return g; } static Vec_Int_t * assignRandomBitsToCells(Abc_Ntk_t * pNtk, struct coloring *c) { Vec_Int_t * randVec = Vec_IntAlloc( 1 ); int i, bit; for (i = 0; i < Abc_NtkPiNum(pNtk); i += (c->clen[i+Abc_NtkPoNum(pNtk)]+1)) { bit = (int)(SIM_RANDOM_UNSIGNED % 2); Vec_IntPush(randVec, bit); } return randVec; } static int * generateProperInputVector( Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randomVector ) { int * vPiValues; int i, j, k, bit, input; int numouts = Abc_NtkPoNum(pNtk); int numins = Abc_NtkPiNum(pNtk); int n = numouts + numins; vPiValues = ABC_ALLOC( int, numins); for (i = numouts, k = 0; i < n; i += (c->clen[i]+1), k++) { if (k == Vec_IntSize(randomVector)) break; bit = Vec_IntEntry(randomVector, k); for (j = i; j <= (i + c->clen[i]); j++) { input = c->lab[j] - numouts; vPiValues[input] = bit; } } //if (k != Vec_IntSize(randomVector)) { if (i < n) { ABC_FREE( vPiValues ); return NULL; } return vPiValues; } static int ifInputVectorsAreConsistent( struct saucy * s, int * leftVec, int * rightVec ) { /* This function assumes that left and right partitions are isomorphic */ int i, j; int lab; int left_bit, right_bit; int numouts = Abc_NtkPoNum(s->pNtk); int n = numouts + Abc_NtkPiNum(s->pNtk); for (i = numouts; i < n; i += (s->right.clen[i]+1)) { lab = s->left.lab[i] - numouts; left_bit = leftVec[lab]; for (j = i+1; j <= (i + s->right.clen[i]); j++) { lab = s->left.lab[j] - numouts; if (left_bit != leftVec[lab]) return -1; } lab = s->right.lab[i] - numouts; right_bit = rightVec[lab]; for (j = i+1; j <= (i + s->right.clen[i]); j++) { lab = s->right.lab[j] - numouts; if (right_bit != rightVec[lab]) return 0; } if (left_bit != right_bit) return 0; } return 1; } static int ifOutputVectorsAreConsistent( struct saucy * s, int * leftVec, int * rightVec ) { /* This function assumes that left and right partitions are isomorphic */ int i, j; int count1, count2; for (i = 0; i < Abc_NtkPoNum(s->pNtk); i += (s->right.clen[i]+1)) { count1 = count2 = 0; for (j = i; j <= (i + s->right.clen[i]); j++) { if (leftVec[s->left.lab[j]]) count1++; if (rightVec[s->right.lab[j]]) count2++; } if (count1 != count2) return 0; } return 1; } static struct saucy_graph * buildSim1Graph( Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randVec, Vec_Int_t ** iDep, Vec_Int_t ** oDep ) { int i, j, k; struct saucy_graph *g; int n, e, *adj, *edg; int * vPiValues, * output; int numOneOutputs = 0; int numouts = Abc_NtkPoNum(pNtk); int numins = Abc_NtkPiNum(pNtk); vPiValues = generateProperInputVector(pNtk, c, randVec); if (vPiValues == NULL) return NULL; output = Abc_NtkVerifySimulatePattern(pNtk, vPiValues); for (i = 0; i < numouts; i++) { if (output[i]) numOneOutputs++; } g = ABC_ALLOC(struct saucy_graph, 1); n = numouts + numins; e = numins * numOneOutputs; adj = ints(n+1); edg = ints(2*e); g->n = n; g->e = e; g->adj = adj; g->edg = edg; adj[0] = 0; for (i = 0; i < numouts; i++) { if (output[i]) { adj[i+1] = adj[i] + Vec_IntSize(oDep[i]); for (j = adj[i], k = 0; j < adj[i+1]; j++, k++) edg[j] = Vec_IntEntry(oDep[i], k) + numouts; } else { adj[i+1] = adj[i]; } } for (i = 0; i < numins; i++) { adj[i+numouts+1] = adj[i+numouts]; for (k = 0, j = adj[i+numouts]; k < Vec_IntSize(iDep[i]); k++) { if (output[Vec_IntEntry(iDep[i], k)]) { edg[j++] = Vec_IntEntry(iDep[i], k); adj[i+numouts+1]++; } } } /* print graph */ /*for (i = 0; i < n; i++) { printf("%d: ", i); for (j = adj[i]; j < adj[i+1]; j++) printf("%d ", edg[j]); printf("\n"); }*/ ABC_FREE( vPiValues ); ABC_FREE( output ); return g; } static struct saucy_graph * buildSim2Graph( Abc_Ntk_t * pNtk, struct coloring *c, Vec_Int_t * randVec, Vec_Int_t ** iDep, Vec_Int_t ** oDep, Vec_Ptr_t ** topOrder, Vec_Int_t ** obs, Vec_Int_t ** ctrl ) { int i, j, k; struct saucy_graph *g = NULL; int n, e = 0, *adj, *edg; int * vPiValues; int * output, * output2; int numouts = Abc_NtkPoNum(pNtk); int numins = Abc_NtkPiNum(pNtk); extern int * Abc_NtkSimulateOneNode( Abc_Ntk_t * , int * , int , Vec_Ptr_t ** ); vPiValues = generateProperInputVector(pNtk, c, randVec); if (vPiValues == NULL) return NULL; output = Abc_NtkVerifySimulatePattern( pNtk, vPiValues ); for (i = 0; i < numins; i++) { if (!c->clen[c->cfront[i+numouts]]) continue; if (vPiValues[i] == 0) vPiValues[i] = 1; else vPiValues[i] = 0; output2 = Abc_NtkSimulateOneNode( pNtk, vPiValues, i, topOrder ); for (j = 0; j < Vec_IntSize(iDep[i]); j++) { if (output[Vec_IntEntry(iDep[i], j)] != output2[Vec_IntEntry(iDep[i], j)]) { Vec_IntPush(obs[i], Vec_IntEntry(iDep[i], j)); Vec_IntPush(ctrl[Vec_IntEntry(iDep[i], j)], i); e++; } } if (vPiValues[i] == 0) vPiValues[i] = 1; else vPiValues[i] = 0; ABC_FREE( output2 ); } /* build the graph */ g = ABC_ALLOC(struct saucy_graph, 1); n = numouts + numins; adj = ints(n+1); edg = ints(2*e); g->n = n; g->e = e; g->adj = adj; g->edg = edg; adj[0] = 0; for (i = 0; i < numouts; i++) { adj[i+1] = adj[i] + Vec_IntSize(ctrl[i]); for (k = 0, j = adj[i]; j < adj[i+1]; j++, k++) edg[j] = Vec_IntEntry(ctrl[i], k) + numouts; } for (i = 0; i < numins; i++) { adj[i+numouts+1] = adj[i+numouts] + Vec_IntSize(obs[i]); for (k = 0, j = adj[i+numouts]; j < adj[i+numouts+1]; j++, k++) edg[j] = Vec_IntEntry(obs[i], k); } /* print graph */ /*for (i = 0; i < n; i++) { printf("%d: ", i); for (j = adj[i]; j < adj[i+1]; j++) printf("%d ", edg[j]); printf("\n"); }*/ ABC_FREE( output ); ABC_FREE( vPiValues ); for (j = 0; j < numins; j++) Vec_IntClear(obs[j]); for (j = 0; j < numouts; j++) Vec_IntClear(ctrl[j]); return g; } static void bumpActivity( struct saucy * s, struct sim_result * cex ) { int i; struct sim_result * cex2; if ( (cex->activity += s->activityInc) > 1e20 ) { /* Rescale: */ for (i = 0; i < Vec_PtrSize(s->satCounterExamples); i++) { cex2 = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i); cex2->activity *= 1e-20; } s->activityInc *= 1e-20; } } static void reduceDB( struct saucy * s ) { int i, j; double extra_lim = s->activityInc / Vec_PtrSize(s->satCounterExamples); /* Remove any clause below this activity */ struct sim_result * cex; while (Vec_PtrSize(s->satCounterExamples) > (0.7 * MAX_LEARNTS)) { for (i = j = 0; i < Vec_PtrSize(s->satCounterExamples); i++) { cex = (struct sim_result *)Vec_PtrEntry(s->satCounterExamples, i); if (cex->activity < extra_lim) { ABC_FREE(cex->inVec); ABC_FREE(cex->outVec); ABC_FREE(cex); } else if (j < i) { Vec_PtrWriteEntry(s->satCounterExamples, j, cex); j++; } } //printf("Database size reduced from %d to %d\n", Vec_PtrSize(s->satCounterExamples), j); Vec_PtrShrink(s->satCounterExamples, j); extra_lim *= 2; } assert(Vec_PtrSize(s->satCounterExamples) <= (0.7 * MAX_LEARNTS)); } static struct sim_result * analyzeConflict( Abc_Ntk_t * pNtk, int * pModel, int fVerbose ) { Abc_Obj_t * pNode; int i, count = 0; int * pValues; struct sim_result * cex; int numouts = Abc_NtkPoNum(pNtk); int numins = Abc_NtkPiNum(pNtk); cex = ABC_ALLOC(struct sim_result, 1); cex->inVec = ints( numins ); cex->outVec = ints( numouts ); /* get the CO values under this model */ pValues = Abc_NtkVerifySimulatePattern( pNtk, pModel ); Abc_NtkForEachCi( pNtk, pNode, i ) cex->inVec[Abc_ObjId(pNode)-1] = pModel[i]; Abc_NtkForEachCo( pNtk, pNode, i ) { cex->outVec[Abc_ObjId(pNode)-numins-1] = pValues[i]; if (pValues[i]) count++; } cex->outVecOnes = count; cex->activity = 0; if (fVerbose) { Abc_NtkForEachCi( pNtk, pNode, i ) printf(" %s=%d", Abc_ObjName(pNode), pModel[i]); printf("\n"); } ABC_FREE( pValues ); return cex; } static int Abc_NtkCecSat_saucy( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ) { extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); Abc_Ntk_t * pMiter; Abc_Ntk_t * pCnf; int RetValue; int nConfLimit; int nInsLimit; int i; nConfLimit = 10000; nInsLimit = 0; /* get the miter of the two networks */ pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0, 0, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); exit(1); } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { //printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); /* report the error */ pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); for (i = 0; i < Abc_NtkPiNum(pNtk1); i++) pModel[i] = pMiter->pModel[i]; ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return 0; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); //printf( "Networks are equivalent after structural hashing.\n" ); return 1; } /* convert the miter into a CNF */ pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); Abc_NtkDelete( pMiter ); if ( pCnf == NULL ) { printf( "Renoding for CNF has failed.\n" ); exit(1); } /* solve the CNF using the SAT solver */ RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, 0, NULL, NULL ); if ( RetValue == -1 ) { printf( "Networks are undecided (SAT solver timed out).\n" ); exit(1); } /*else if ( RetValue == 0 ) printf( "Networks are NOT EQUIVALENT after SAT.\n" ); else printf( "Networks are equivalent after SAT.\n" );*/ if ( pCnf->pModel ) { for (i = 0; i < Abc_NtkPiNum(pNtk1); i++) pModel[i] = pCnf->pModel[i]; } ABC_FREE( pCnf->pModel ); Abc_NtkDelete( pCnf ); return RetValue; } void saucyGateWay( Abc_Ntk_t * pNtkOrig, Abc_Obj_t * pNodePo, FILE * gFile, int fBooleanMatching, int fLookForSwaps, int fFixOutputs, int fFixInputs, int fQuiet, int fPrintTree ) { Abc_Ntk_t * pNtk; struct saucy *s; struct saucy_stats stats; int *colors; int i, clk = clock(); if (pNodePo == NULL) pNtk = Abc_NtkDup( pNtkOrig ); else pNtk = Abc_NtkCreateCone( pNtkOrig, Abc_ObjFanin0(pNodePo), Abc_ObjName(pNodePo), 0 ); if (Abc_NtkPiNum(pNtk) == 0) { Abc_Print( 0, "This output is not dependent on any input\n" ); Abc_NtkDelete( pNtk ); return; } s = saucy_alloc( pNtk ); /******* Getting Dependencies *******/ printf("Build functional dependency graph (dependency stats are below) ... "); getDependencies( pNtk, s->iDep, s->oDep ); printf("\t--------------------\n"); /************************************/ /* Finding toplogical orde */ s->topOrder = findTopologicalOrder( pNtk ); /* Setting graph colors: outputs = 0 and inputs = 1 */ colors = ints(Abc_NtkPoNum(pNtk) + Abc_NtkPiNum(pNtk)); if (fFixOutputs) { for (i = 0; i < Abc_NtkPoNum(pNtk); i++) colors[i] = i; } else { for (i = 0; i < Abc_NtkPoNum(pNtk); i++) colors[i] = 0; } if (fFixInputs) { int c = (fFixOutputs) ? Abc_NtkPoNum(pNtk) : 1; for (i = 0; i < Abc_NtkPiNum(pNtk); i++) colors[i+Abc_NtkPoNum(pNtk)] = c+i; } else { int c = (fFixOutputs) ? Abc_NtkPoNum(pNtk) : 1; for (i = 0; i < Abc_NtkPiNum(pNtk); i++) colors[i+Abc_NtkPoNum(pNtk)] = c; } /* Are we looking for Boolean matching? */ s->fBooleanMatching = fBooleanMatching; if (fBooleanMatching) { NUM_SIM1_ITERATION = 50; NUM_SIM2_ITERATION = 50; } else { NUM_SIM1_ITERATION = 200; NUM_SIM2_ITERATION = 200; } /* Set the print automorphism routine */ if (!fQuiet) s->print_automorphism = print_automorphism_ntk; else s->print_automorphism = print_automorphism_quiet; /* Set the output file for generators */ if (gFile == NULL) s->gFile = stdout; else s->gFile = gFile; /* Set print tree option */ s->fPrintTree = fPrintTree; /* Set input permutations option */ s->fLookForSwaps = fLookForSwaps; saucy_search(pNtk, s, 0, colors, &stats); print_stats(stdout, stats); if (fBooleanMatching) { if (stats.grpsize_base > 1 || stats.grpsize_exp > 0) printf("*** Networks are equivalent ***\n"); else printf("*** Networks are NOT equivalent ***\n"); } saucy_free(s); Abc_NtkDelete(pNtk); if (1) { FILE * hadi = fopen("hadi.txt", "a"); fprintf(hadi, "group size = %fe%d\n", stats.grpsize_base, stats.grpsize_exp); fclose(hadi); } ABC_PRT( "Runtime", clock() - clk ); }ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcScorr.c000066400000000000000000000350161300674244400235530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcScorr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Signal correspondence testing procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcScorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/io/ioAbc.h" #include "aig/saig/saig.h" #include "proof/ssw/ssw.h" #include "aig/gia/gia.h" #include "proof/cec/cec.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Tst_Dat_t_ Tst_Dat_t; struct Tst_Dat_t_ { Abc_Ntk_t * pNetlist; Aig_Man_t * pAig; Gia_Man_t * pGia; Vec_Int_t * vId2Name; char * pFileNameOut; int fFlopOnly; int fFfNdOnly; int fDumpBmc; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkMapGiaIntoNameId( Abc_Ntk_t * pNetlist, Aig_Man_t * pAig, Gia_Man_t * pGia ) { Vec_Int_t * vId2Name; Abc_Obj_t * pNet, * pNode, * pAnd; Aig_Obj_t * pObjAig; int i; vId2Name = Vec_IntAlloc( 0 ); Vec_IntFill( vId2Name, pGia ? Gia_ManObjNum(pGia) : Aig_ManObjNumMax(pAig), ~0 ); // copy all names Abc_NtkForEachNet( pNetlist, pNet, i ) { pNode = Abc_ObjFanin0(pNet)->pCopy; if ( pNode && (pAnd = Abc_ObjRegular(pNode->pCopy)) && (pObjAig = (Aig_Obj_t *)Abc_ObjRegular(pAnd->pCopy)) && Aig_ObjType(pObjAig) != AIG_OBJ_NONE ) { if ( pGia == NULL ) Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) ); else Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); } } // overwrite CO names Abc_NtkForEachCo( pNetlist, pNode, i ) { pNet = Abc_ObjFanin0(pNode); pNode = pNode->pCopy; if ( pNode && (pAnd = Abc_ObjRegular(pNode->pCopy)) && (pObjAig = (Aig_Obj_t *)Abc_ObjRegular(pAnd->pCopy)) && Aig_ObjType(pObjAig) != AIG_OBJ_NONE ) { if ( pGia == NULL ) Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) ); else Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); } } // overwrite CI names Abc_NtkForEachCi( pNetlist, pNode, i ) { pNet = Abc_ObjFanout0(pNode); pNode = pNode->pCopy; if ( pNode && (pAnd = Abc_ObjRegular(pNode->pCopy)) && (pObjAig = (Aig_Obj_t *)Abc_ObjRegular(pAnd->pCopy)) && Aig_ObjType(pObjAig) != AIG_OBJ_NONE ) { if ( pGia == NULL ) Vec_IntWriteEntry( vId2Name, Aig_ObjId(pObjAig), Abc_ObjId(pNet) ); else Vec_IntWriteEntry( vId2Name, Abc_Lit2Var(pObjAig->iData), Abc_ObjId(pNet) ); } } return vId2Name; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_NtkTestScorrGetName( Abc_Ntk_t * pNetlist, Vec_Int_t * vId2Name, int Id ) { // Abc_Obj_t * pObj; //printf( "trying to get name for %d\n", Id ); if ( Vec_IntEntry(vId2Name, Id) == ~0 ) return NULL; // pObj = Abc_NtkObj( pNetlist, Vec_IntEntry(vId2Name, Id) ); // pObj = Abc_ObjFanin0(pObj); // assert( Abc_ObjIsCi(pObj) ); return Nm_ManFindNameById( pNetlist->pManName, Vec_IntEntry(vId2Name, Id) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkTestScorrWriteEquivPair( Abc_Ntk_t * pNetlist, Vec_Int_t * vId2Name, int Id1, int Id2, FILE * pFile, int fPol ) { char * pName1 = Abc_NtkTestScorrGetName( pNetlist, vId2Name, Id1 ); char * pName2 = Abc_NtkTestScorrGetName( pNetlist, vId2Name, Id2 ); if ( pName1 == NULL || pName2 == NULL ) return 0; fprintf( pFile, "%s=%s%s\n", pName1, fPol? "~": "", pName2 ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkTestScorrWriteEquivConst( Abc_Ntk_t * pNetlist, Vec_Int_t * vId2Name, int Id1, FILE * pFile, int fPol ) { char * pName1 = Abc_NtkTestScorrGetName( pNetlist, vId2Name, Id1 ); if ( pName1 == NULL ) return 0; fprintf( pFile, "%s=%s%s\n", pName1, fPol? "~": "", "const0" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_NtkBmcFileName( char * pName ) { static char Buffer[1000]; char * pNameGeneric = Extra_FileNameGeneric( pName ); sprintf( Buffer, "%s_bmc%s", pNameGeneric, pName + strlen(pNameGeneric) ); ABC_FREE( pNameGeneric ); return Buffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkTestScorrWriteEquivGia( Tst_Dat_t * pData ) { Abc_Ntk_t * pNetlist = pData->pNetlist; Vec_Int_t * vId2Name = pData->vId2Name; Gia_Man_t * pGia = pData->pGia; char * pFileNameOut = pData->pFileNameOut; FILE * pFile; Gia_Obj_t * pObj, * pRepr; int i, Counter = 0; if ( pData->fDumpBmc ) { pData->fDumpBmc = 0; pFileNameOut = Abc_NtkBmcFileName( pFileNameOut ); } pFile = fopen( pFileNameOut, "wb" ); Gia_ManSetPhase( pGia ); Gia_ManForEachObj( pGia, pObj, i ) { if ( !Gia_ObjHasRepr(pGia, i) ) continue; pRepr = Gia_ManObj( pGia,Gia_ObjRepr(pGia, i) ); if ( pData->fFlopOnly ) { if ( !Gia_ObjIsRo(pGia, pObj) || !(Gia_ObjIsRo(pGia, pRepr)||Gia_ObjIsConst0(pRepr)) ) continue; } else if ( pData->fFfNdOnly ) { if ( !Gia_ObjIsRo(pGia, pObj) && !(Gia_ObjIsRo(pGia, pRepr)||Gia_ObjIsConst0(pRepr)) ) continue; } if ( Gia_ObjRepr(pGia, i) == 0 ) Counter += Abc_NtkTestScorrWriteEquivConst( pNetlist, vId2Name, i, pFile, Gia_ObjPhase(pObj) ); else Counter += Abc_NtkTestScorrWriteEquivPair( pNetlist, vId2Name, Gia_ObjRepr(pGia, i), i, pFile, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); } fclose( pFile ); printf( "%d pairs of sequentially equivalent nodes are written into file \"%s\".\n", Counter, pFileNameOut ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkTestScorrWriteEquivAig( Tst_Dat_t * pData ) { Abc_Ntk_t * pNetlist = pData->pNetlist; Vec_Int_t * vId2Name = pData->vId2Name; Aig_Man_t * pAig = pData->pAig; char * pFileNameOut = pData->pFileNameOut; FILE * pFile; Aig_Obj_t * pObj, * pRepr; int i, Counter = 0; if ( pData->fDumpBmc ) { pData->fDumpBmc = 0; pFileNameOut = Abc_NtkBmcFileName( pFileNameOut ); } pFile = fopen( pFileNameOut, "wb" ); Aig_ManForEachObj( pAig, pObj, i ) { if ( (pRepr = Aig_ObjRepr(pAig, pObj)) == NULL ) continue; if ( pData->fFlopOnly ) { if ( !Saig_ObjIsLo(pAig, pObj) || !(Saig_ObjIsLo(pAig, pRepr)||pRepr==Aig_ManConst1(pAig)) ) continue; } else if ( pData->fFfNdOnly ) { if ( !Saig_ObjIsLo(pAig, pObj) && !(Saig_ObjIsLo(pAig, pRepr)||pRepr==Aig_ManConst1(pAig)) ) continue; } if ( pRepr == Aig_ManConst1(pAig) ) Counter += Abc_NtkTestScorrWriteEquivConst( pNetlist, vId2Name, Aig_ObjId(pObj), pFile, Aig_ObjPhase(pObj) ); else Counter += Abc_NtkTestScorrWriteEquivPair( pNetlist, vId2Name, Aig_ObjId(pRepr), Aig_ObjId(pObj), pFile, Aig_ObjPhase(pRepr) ^ Aig_ObjPhase(pObj) ); } fclose( pFile ); printf( "%d pairs of sequentially equivalent nodes are written into file \"%s\".\n", Counter, pFileNameOut ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkTestScorr( char * pFileNameIn, char * pFileNameOut, int nStepsMax, int nBTLimit, int fNewAlgo, int fFlopOnly, int fFfNdOnly, 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 ); FILE * pFile; Tst_Dat_t Data, * pData = &Data; Vec_Int_t * vId2Name; Abc_Ntk_t * pNetlist, * pLogic, * pStrash, * pResult; Aig_Man_t * pAig, * pTempAig; Gia_Man_t * pGia, * pTempGia; // int Counter = 0; // check the files pFile = fopen( pFileNameIn, "rb" ); if ( pFile == NULL ) { printf( "Input file \"%s\" cannot be opened.\n", pFileNameIn ); return NULL; } fclose( pFile ); // check the files pFile = fopen( pFileNameOut, "wb" ); if ( pFile == NULL ) { printf( "Output file \"%s\" cannot be opened.\n", pFileNameOut ); return NULL; } fclose( pFile ); // derive AIG for signal correspondence pNetlist = Io_ReadNetlist( pFileNameIn, Io_ReadFileType(pFileNameIn), 1 ); if ( pNetlist == NULL ) { printf( "Reading input file \"%s\" has failed.\n", pFileNameIn ); return NULL; } pLogic = Abc_NtkToLogic( pNetlist ); if ( pLogic == NULL ) { Abc_NtkDelete( pNetlist ); printf( "Deriving logic network from input file %s has failed.\n", pFileNameIn ); return NULL; } if ( Extra_FileIsType( pFileNameIn, ".bench", ".BENCH", NULL ) ) { // get the init file name char * pFileNameInit = Extra_FileNameGenericAppend( pLogic->pSpec, ".init" ); pFile = fopen( pFileNameInit, "rb" ); if ( pFile == NULL ) { printf( "Init file \"%s\" cannot be opened.\n", pFileNameInit ); return NULL; } Io_ReadBenchInit( pLogic, pFileNameInit ); Abc_NtkConvertDcLatches( pLogic ); if ( fVerbose ) printf( "Initial state was derived from file \"%s\".\n", pFileNameInit ); } pStrash = Abc_NtkStrash( pLogic, 0, 1, 0 ); if ( pStrash == NULL ) { Abc_NtkDelete( pLogic ); Abc_NtkDelete( pNetlist ); printf( "Deriving strashed network from input file %s has failed.\n", pFileNameIn ); return NULL; } pAig = Abc_NtkToDar( pStrash, 0, 1 ); // performs "zero" internally // the newer computation (&scorr) if ( fNewAlgo ) { Cec_ParCor_t CorPars, * pCorPars = &CorPars; Cec_ManCorSetDefaultParams( pCorPars ); pCorPars->nBTLimit = nBTLimit; pCorPars->nStepsMax = nStepsMax; pCorPars->fVerbose = fVerbose; pCorPars->fUseCSat = 1; pGia = Gia_ManFromAig( pAig ); // prepare the data-structure memset( pData, 0, sizeof(Tst_Dat_t) ); pData->pNetlist = pNetlist; pData->pAig = NULL; pData->pGia = pGia; pData->vId2Name = vId2Name = Abc_NtkMapGiaIntoNameId( pNetlist, pAig, pGia ); pData->pFileNameOut = pFileNameOut; pData->fFlopOnly = fFlopOnly; pData->fFfNdOnly = fFfNdOnly; pData->fDumpBmc = 1; pCorPars->pData = pData; pCorPars->pFunc = (void *)Abc_NtkTestScorrWriteEquivGia; // call signal correspondence pTempGia = Cec_ManLSCorrespondence( pGia, pCorPars ); pTempAig = Gia_ManToAigSimple( pTempGia ); Gia_ManStop( pTempGia ); Gia_ManStop( pGia ); } // the older computation (scorr) else { Ssw_Pars_t SswPars, * pSswPars = &SswPars; Ssw_ManSetDefaultParams( pSswPars ); pSswPars->nBTLimit = nBTLimit; pSswPars->nStepsMax = nStepsMax; pSswPars->fVerbose = fVerbose; // preSswPare the data-structure memset( pData, 0, sizeof(Tst_Dat_t) ); pData->pNetlist = pNetlist; pData->pAig = pAig; pData->pGia = NULL; pData->vId2Name = vId2Name = Abc_NtkMapGiaIntoNameId( pNetlist, pAig, NULL ); pData->pFileNameOut = pFileNameOut; pData->fFlopOnly = fFlopOnly; pData->fFfNdOnly = fFfNdOnly; pData->fDumpBmc = 1; pSswPars->pData = pData; pSswPars->pFunc = (void *)Abc_NtkTestScorrWriteEquivAig; // call signal correspondence pTempAig = Ssw_SignalCorrespondence( pAig, pSswPars ); } // create the resulting AIG pResult = Abc_NtkFromDarSeqSweep( pStrash, pTempAig ); // cleanup Vec_IntFree( vId2Name ); Aig_ManStop( pAig ); Aig_ManStop( pTempAig ); Abc_NtkDelete( pStrash ); Abc_NtkDelete( pLogic ); Abc_NtkDelete( pNetlist ); return pResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcSense.c000066400000000000000000000166061300674244400235440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcSense.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 "base/abc/abc.h" #include "proof/fraig/fraig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Copies the topmost levels of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkSensitivityMiter_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) { assert( !Abc_ObjIsComplement(pNode) ); if ( pNode->pCopy ) return pNode->pCopy; Abc_NtkSensitivityMiter_rec( pNtkNew, Abc_ObjFanin0(pNode) ); Abc_NtkSensitivityMiter_rec( pNtkNew, Abc_ObjFanin1(pNode) ); return pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } /**Function************************************************************* Synopsis [Creates miter for the sensitivity analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSensitivityMiter( Abc_Ntk_t * pNtk, int iVar ) { Abc_Ntk_t * pMiter; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pNext, * pFanin, * pOutput, * pObjNew; int i; assert( Abc_NtkIsStrash(pNtk) ); assert( iVar < Abc_NtkCiNum(pNtk) ); // duplicate the network pMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pMiter->pName = Extra_UtilStrsav(pNtk->pName); pMiter->pSpec = Extra_UtilStrsav(pNtk->pSpec); // assign the PIs Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pMiter); Abc_AigConst1(pNtk)->pData = Abc_AigConst1(pMiter); Abc_NtkForEachCi( pNtk, pObj, i ) { pObj->pCopy = Abc_NtkCreatePi( pMiter ); pObj->pData = pObj->pCopy; } Abc_NtkAddDummyPiNames( pMiter ); // assign the cofactors of the CI node to be constants pObj = Abc_NtkCi( pNtk, iVar ); pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pMiter) ); pObj->pData = Abc_AigConst1(pMiter); // collect the internal nodes vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj ) { pFanin = Abc_ObjFanin0(pObj); if ( !Abc_NodeIsTravIdCurrent(pFanin) ) pFanin->pData = Abc_NtkSensitivityMiter_rec( pMiter, pFanin ); pFanin = Abc_ObjFanin1(pObj); if ( !Abc_NodeIsTravIdCurrent(pFanin) ) pFanin->pData = Abc_NtkSensitivityMiter_rec( pMiter, pFanin ); pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) ); } } Vec_PtrFree( vNodes ); // update the affected COs pOutput = Abc_ObjNot( Abc_AigConst1(pMiter) ); Abc_NtkForEachCo( pNtk, pObj, i ) { if ( !Abc_NodeIsTravIdCurrent(pObj) ) continue; // get the result of quantification if ( i == Abc_NtkCoNum(pNtk) - 1 ) { pOutput = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, pOutput, Abc_ObjChild0Data(pObj) ); pOutput = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, pOutput, Abc_ObjChild0Copy(pObj) ); } else { pNext = Abc_AigXor( (Abc_Aig_t *)pMiter->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); pOutput = Abc_AigOr( (Abc_Aig_t *)pMiter->pManFunc, pOutput, pNext ); } } // add the PO node and name pObjNew = Abc_NtkCreatePo(pMiter); Abc_ObjAddFanin( pObjNew, pOutput ); Abc_ObjAssignName( pObjNew, "miter", NULL ); // make sure everything is okay if ( !Abc_NtkCheck( pMiter ) ) { printf( "Abc_NtkSensitivityMiter: The network check has failed.\n" ); Abc_NtkDelete( pMiter ); return NULL; } return pMiter; } /**Function************************************************************* Synopsis [Computing sensitivity of POs to POs under constraints.] Description [The input network is a combinatonal AIG. The last output is a constraint. The procedure returns the list of number of PIs, such that at least one PO depends on this PI, under the constraint.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkSensitivity( Abc_Ntk_t * pNtk, int nConfLim, int fVerbose ) { ProgressBar * pProgress; Prove_Params_t Params, * pParams = &Params; Vec_Int_t * vResult = NULL; Abc_Ntk_t * pMiter; Abc_Obj_t * pObj; int RetValue, i; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkLatchNum(pNtk) == 0 ); // set up solving parameters Prove_ParamsSetDefault( pParams ); pParams->nItersMax = 3; pParams->nMiteringLimitLast = nConfLim; // iterate through the PIs vResult = Vec_IntAlloc( 100 ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCiNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // generate the sensitivity miter pMiter = Abc_NtkSensitivityMiter( pNtk, i ); // solve the miter using CEC engine RetValue = Abc_NtkIvyProve( &pMiter, pParams ); if ( RetValue == -1 ) // undecided Vec_IntPush( vResult, i ); else if ( RetValue == 0 ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel ); if ( pSimInfo[0] != 1 ) printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); // else // printf( "Networks are NOT EQUIVALENT.\n" ); ABC_FREE( pSimInfo ); Vec_IntPush( vResult, i ); } Abc_NtkDelete( pMiter ); } Extra_ProgressBarStop( pProgress ); if ( fVerbose ) { printf( "The outputs are sensitive to %d (out of %d) inputs:\n", Vec_IntSize(vResult), Abc_NtkCiNum(pNtk) ); Vec_IntForEachEntry( vResult, RetValue, i ) printf( "%d ", RetValue ); printf( "\n" ); } return vResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcSpeedup.c000066400000000000000000001023551300674244400240710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcSpeedup.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Delay trace and speedup.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcSpeedup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "map/if/if.h" #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline float Abc_ObjArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pLutTimes[3*pNode->Id+0]; } static inline float Abc_ObjRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pLutTimes[3*pNode->Id+1]; } static inline float Abc_ObjSlack( Abc_Obj_t * pNode ) { return pNode->pNtk->pLutTimes[3*pNode->Id+2]; } static inline void Abc_ObjSetArrival( Abc_Obj_t * pNode, float Time ) { pNode->pNtk->pLutTimes[3*pNode->Id+0] = Time; } static inline void Abc_ObjSetRequired( Abc_Obj_t * pNode, float Time ) { pNode->pNtk->pLutTimes[3*pNode->Id+1] = Time; } static inline void Abc_ObjSetSlack( Abc_Obj_t * pNode, float Time ) { pNode->pNtk->pLutTimes[3*pNode->Id+2] = Time; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sorts the pins in the decreasing order of delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDelayTraceSortPins( Abc_Obj_t * pNode, int * pPinPerm, float * pPinDelays ) { Abc_Obj_t * pFanin; int i, j, best_i, temp; // start the trivial permutation and collect pin delays Abc_ObjForEachFanin( pNode, pFanin, i ) { pPinPerm[i] = i; pPinDelays[i] = Abc_ObjArrival(pFanin); } // 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 < Abc_ObjFaninNum(pNode)-1; i++ ) { best_i = i; for ( j = i+1; j < Abc_ObjFaninNum(pNode); 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( Abc_ObjFaninNum(pNode) == 0 || pPinPerm[0] < Abc_ObjFaninNum(pNode) ); for ( i = 1; i < Abc_ObjFaninNum(pNode); i++ ) { assert( pPinPerm[i] < Abc_ObjFaninNum(pNode) ); assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_NtkDelayTraceLut( Abc_Ntk_t * pNtk, int fUseLutLib ) { int fUseSorting = 1; int pPinPerm[32]; float pPinDelays[32]; If_LibLut_t * pLutLib; Abc_Obj_t * pNode, * pFanin; Vec_Ptr_t * vNodes; float tArrival, tRequired, tSlack, * pDelays; int i, k; assert( Abc_NtkIsLogic(pNtk) ); // get the library pLutLib = fUseLutLib? (If_LibLut_t *)Abc_FrameReadLibLut() : NULL; if ( pLutLib && pLutLib->LutMax < Abc_NtkGetFaninMax(pNtk) ) { printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", pLutLib->LutMax, Abc_NtkGetFaninMax(pNtk) ); return -ABC_INFINITY; } // initialize the arrival times ABC_FREE( pNtk->pLutTimes ); pNtk->pLutTimes = ABC_ALLOC( float, 3 * Abc_NtkObjNumMax(pNtk) ); for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ ) { pNtk->pLutTimes[3*i+0] = pNtk->pLutTimes[3*i+2] = 0; pNtk->pLutTimes[3*i+1] = ABC_INFINITY; } // propagate arrival times vNodes = Abc_NtkDfs( pNtk, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { tArrival = -ABC_INFINITY; if ( pLutLib == NULL ) { Abc_ObjForEachFanin( pNode, pFanin, k ) if ( tArrival < Abc_ObjArrival(pFanin) + 1.0 ) tArrival = Abc_ObjArrival(pFanin) + 1.0; } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)]; Abc_ObjForEachFanin( pNode, pFanin, k ) if ( tArrival < Abc_ObjArrival(pFanin) + pDelays[0] ) tArrival = Abc_ObjArrival(pFanin) + pDelays[0]; } else { pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)]; if ( fUseSorting ) { Abc_NtkDelayTraceSortPins( pNode, pPinPerm, pPinDelays ); Abc_ObjForEachFanin( pNode, pFanin, k ) if ( tArrival < Abc_ObjArrival(Abc_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] ) tArrival = Abc_ObjArrival(Abc_ObjFanin(pNode,pPinPerm[k])) + pDelays[k]; } else { Abc_ObjForEachFanin( pNode, pFanin, k ) if ( tArrival < Abc_ObjArrival(pFanin) + pDelays[k] ) tArrival = Abc_ObjArrival(pFanin) + pDelays[k]; } } if ( Abc_ObjFaninNum(pNode) == 0 ) tArrival = 0.0; Abc_ObjSetArrival( pNode, tArrival ); } Vec_PtrFree( vNodes ); // get the latest arrival times tArrival = -ABC_INFINITY; Abc_NtkForEachCo( pNtk, pNode, i ) if ( tArrival < Abc_ObjArrival(Abc_ObjFanin0(pNode)) ) tArrival = Abc_ObjArrival(Abc_ObjFanin0(pNode)); // initialize the required times Abc_NtkForEachCo( pNtk, pNode, i ) if ( Abc_ObjRequired(Abc_ObjFanin0(pNode)) > tArrival ) Abc_ObjSetRequired( Abc_ObjFanin0(pNode), tArrival ); // propagate the required times vNodes = Abc_NtkDfsReverse( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( pLutLib == NULL ) { tRequired = Abc_ObjRequired(pNode) - (float)1.0; Abc_ObjForEachFanin( pNode, pFanin, k ) if ( Abc_ObjRequired(pFanin) > tRequired ) Abc_ObjSetRequired( pFanin, tRequired ); } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)]; tRequired = Abc_ObjRequired(pNode) - pDelays[0]; Abc_ObjForEachFanin( pNode, pFanin, k ) if ( Abc_ObjRequired(pFanin) > tRequired ) Abc_ObjSetRequired( pFanin, tRequired ); } else { pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)]; if ( fUseSorting ) { Abc_NtkDelayTraceSortPins( pNode, pPinPerm, pPinDelays ); Abc_ObjForEachFanin( pNode, pFanin, k ) { tRequired = Abc_ObjRequired(pNode) - pDelays[k]; if ( Abc_ObjRequired(Abc_ObjFanin(pNode,pPinPerm[k])) > tRequired ) Abc_ObjSetRequired( Abc_ObjFanin(pNode,pPinPerm[k]), tRequired ); } } else { Abc_ObjForEachFanin( pNode, pFanin, k ) { tRequired = Abc_ObjRequired(pNode) - pDelays[k]; if ( Abc_ObjRequired(pFanin) > tRequired ) Abc_ObjSetRequired( pFanin, tRequired ); } } } // set slack for this object tSlack = Abc_ObjRequired(pNode) - Abc_ObjArrival(pNode); assert( tSlack + 0.001 > 0.0 ); Abc_ObjSetSlack( pNode, tSlack < 0.0 ? 0.0 : tSlack ); } Vec_PtrFree( vNodes ); return tArrival; } /**Function************************************************************* Synopsis [Delay tracing of the LUT mapped network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDelayTracePrint( Abc_Ntk_t * pNtk, int fUseLutLib, int fVerbose ) { Abc_Obj_t * pNode; If_LibLut_t * pLutLib; int i, Nodes, * pCounters; float tArrival, tDelta, nSteps, Num; // get the library pLutLib = fUseLutLib? (If_LibLut_t *)Abc_FrameReadLibLut() : NULL; if ( pLutLib && pLutLib->LutMax < Abc_NtkGetFaninMax(pNtk) ) { printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", pLutLib->LutMax, Abc_NtkGetFaninMax(pNtk) ); return; } // decide how many steps nSteps = fUseLutLib ? 20 : Abc_NtkLevel(pNtk); pCounters = ABC_ALLOC( int, nSteps + 1 ); memset( pCounters, 0, sizeof(int)*(nSteps + 1) ); // perform delay trace tArrival = Abc_NtkDelayTraceLut( pNtk, fUseLutLib ); tDelta = tArrival / nSteps; // count how many nodes have slack in the corresponding intervals Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjFaninNum(pNode) == 0 ) continue; Num = Abc_ObjSlack(pNode) / tDelta; assert( Num >=0 && Num <= nSteps ); pCounters[(int)Num]++; } // print the results printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, fUseLutLib? "LUT library" : "unit-delay" ); Nodes = 0; for ( i = 0; i < nSteps; i++ ) { Nodes += pCounters[i]; printf( "%3d %s : %5d (%6.2f %%)\n", fUseLutLib? 5*(i+1) : i+1, fUseLutLib? "%":"lev", Nodes, 100.0*Nodes/Abc_NtkNodeNum(pNtk) ); } ABC_FREE( pCounters ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld ) { // check the trivial cases if ( pNode == NULL ) return 0; if ( Abc_ObjIsCi(pNode) ) return 0; if ( pNode == pOld ) return 1; // skip the visited node if ( Abc_NodeIsTravIdCurrent( pNode ) ) return 0; Abc_NodeSetTravIdCurrent( pNode ); // check the children if ( Abc_AigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) ) return 1; if ( Abc_AigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) ) return 1; // check equivalent nodes return Abc_AigCheckTfi_rec( (Abc_Obj_t *)pNode->pData, pOld ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigCheckTfi( Abc_Obj_t * pNew, Abc_Obj_t * pOld ) { assert( !Abc_ObjIsComplement(pNew) ); assert( !Abc_ObjIsComplement(pOld) ); Abc_NtkIncrementTravId( pNew->pNtk ); return Abc_AigCheckTfi_rec( pNew, pOld ); } /**Function************************************************************* Synopsis [Adds strashed nodes for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSpeedupNode_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { if ( Abc_NodeIsTravIdCurrent(pNode) ) return 1; if ( Abc_ObjIsCi(pNode) ) return 0; assert( Abc_ObjIsNode(pNode) ); Abc_NodeSetTravIdCurrent( pNode ); if ( !Abc_NtkSpeedupNode_rec( Abc_ObjFanin0(pNode), vNodes ) ) return 0; if ( !Abc_NtkSpeedupNode_rec( Abc_ObjFanin1(pNode), vNodes ) ) return 0; Vec_PtrPush( vNodes, pNode ); return 1; } /**Function************************************************************* Synopsis [Adds strashed nodes for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSpeedupNode( Abc_Ntk_t * pNtk, Abc_Ntk_t * pAig, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vTimes ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pObj2, * pAnd; Abc_Obj_t * ppCofs[32]; int nCofs, i, k, nSkip; // quit of regulars are the same Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj2, k ) if ( i != k && Abc_ObjRegular(pObj->pCopy) == Abc_ObjRegular(pObj2->pCopy) ) { // printf( "Identical after structural hashing!!!\n" ); return; } // collect the AIG nodes vNodes = Vec_PtrAlloc( 100 ); Abc_NtkIncrementTravId( pAig ); Abc_NodeSetTravIdCurrent( Abc_AigConst1(pAig) ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) { pAnd = pObj->pCopy; Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pAnd) ); } // traverse from the root node pAnd = pNode->pCopy; if ( !Abc_NtkSpeedupNode_rec( Abc_ObjRegular(pAnd), vNodes ) ) { // printf( "Bad node!!!\n" ); Vec_PtrFree( vNodes ); return; } // derive cofactors nCofs = (1 << Vec_PtrSize(vTimes)); for ( i = 0; i < nCofs; i++ ) { Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, k ) { pAnd = pObj->pCopy; Abc_ObjRegular(pAnd)->pCopy = Abc_ObjRegular(pAnd); } Vec_PtrForEachEntry( Abc_Obj_t *, vTimes, pObj, k ) { pAnd = pObj->pCopy; Abc_ObjRegular(pAnd)->pCopy = Abc_ObjNotCond( Abc_AigConst1(pAig), ((i & (1<pCopy = Abc_AigAnd( (Abc_Aig_t *)pAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); // save the result pAnd = pNode->pCopy; ppCofs[i] = Abc_ObjNotCond( Abc_ObjRegular(pAnd)->pCopy, Abc_ObjIsComplement(pAnd) ); } Vec_PtrFree( vNodes ); //Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), ppCofs[0] ); //Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), ppCofs[1] ); // collect the resulting tree Vec_PtrForEachEntry( Abc_Obj_t *, vTimes, pObj, k ) for ( nSkip = (1<pCopy; ppCofs[i] = Abc_AigMux( (Abc_Aig_t *)pAig->pManFunc, Abc_ObjRegular(pAnd), ppCofs[i+nSkip], ppCofs[i] ); } //Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), ppCofs[0] ); // create choice node pAnd = Abc_ObjRegular(pNode->pCopy); // repr pObj = Abc_ObjRegular(ppCofs[0]); // new if ( pAnd->pData == NULL && pObj->pData == NULL && !Abc_AigNodeIsConst(pObj) && !Abc_AigCheckTfi(pObj, pAnd) ) { pObj->pData = pAnd->pData; pAnd->pData = pObj; } } /**Function************************************************************* Synopsis [Determines timing-critical edges of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Abc_NtkDelayTraceTCEdges( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, float tDelta, int fUseLutLib ) { int pPinPerm[32]; float pPinDelays[32]; If_LibLut_t * pLutLib; Abc_Obj_t * pFanin; unsigned uResult = 0; float tRequired, * pDelays; int k; pLutLib = fUseLutLib? (If_LibLut_t *)Abc_FrameReadLibLut() : NULL; tRequired = Abc_ObjRequired(pNode); if ( pLutLib == NULL ) { Abc_ObjForEachFanin( pNode, pFanin, k ) if ( tRequired < Abc_ObjArrival(pFanin) + 1.0 + tDelta ) uResult |= (1 << k); } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)]; Abc_ObjForEachFanin( pNode, pFanin, k ) if ( tRequired < Abc_ObjArrival(pFanin) + pDelays[0] + tDelta ) uResult |= (1 << k); } else { pDelays = pLutLib->pLutDelays[Abc_ObjFaninNum(pNode)]; Abc_NtkDelayTraceSortPins( pNode, pPinPerm, pPinDelays ); Abc_ObjForEachFanin( pNode, pFanin, k ) if ( tRequired < Abc_ObjArrival(Abc_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] + tDelta ) uResult |= (1 << pPinPerm[k]); } return uResult; } /**Function************************************************************* Synopsis [Adds choices to speed up the network by the given percentage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSpeedup( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ) { Abc_Ntk_t * pNtkNew; Vec_Ptr_t * vTimeCries, * vTimeFanins; Abc_Obj_t * pNode, * pFanin, * pFanin2; float tDelta, tArrival; int i, k, k2, Counter, CounterRes, nTimeCris; unsigned * puTCEdges; // perform delay trace tArrival = Abc_NtkDelayTraceLut( pNtk, fUseLutLib ); 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_ALLOC( unsigned, Abc_NtkObjNumMax(pNtk) ); memset( puTCEdges, 0, sizeof(unsigned) * Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjSlack(pNode) >= tDelta ) continue; puTCEdges[pNode->Id] = Abc_NtkDelayTraceTCEdges( pNtk, pNode, tDelta, fUseLutLib ); } if ( fVerbose ) { Counter = CounterRes = 0; Abc_NtkForEachNode( pNtk, pNode, i ) { Abc_ObjForEachFanin( pNode, pFanin, k ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjSlack(pFanin) < tDelta ) Counter++; CounterRes += Extra_WordCountOnes( puTCEdges[pNode->Id] ); } printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", Abc_NtkGetTotalFanins(pNtk), Counter, CounterRes, 1.0*CounterRes/Counter ); } // start the resulting network pNtkNew = Abc_NtkStrash( pNtk, 0, 1, 0 ); // collect nodes to be used for resynthesis Counter = CounterRes = 0; vTimeCries = Vec_PtrAlloc( 16 ); vTimeFanins = Vec_PtrAlloc( 16 ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjSlack(pNode) >= tDelta ) continue; // count the number of non-PI timing-critical nodes nTimeCris = 0; Abc_ObjForEachFanin( pNode, pFanin, k ) if ( !Abc_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<Id] & (1<Id] & (1< Degree) ) if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) ) continue; CounterRes++; // collect second generation nodes Vec_PtrClear( vTimeFanins ); Abc_ObjForEachFanin( pNode, pFanin, k ) { if ( Abc_ObjIsCi(pFanin) ) Vec_PtrPushUnique( vTimeFanins, pFanin ); else Abc_ObjForEachFanin( pFanin, pFanin2, k2 ) Vec_PtrPushUnique( vTimeFanins, pFanin2 ); } // print the results if ( fVeryVerbose ) { printf( "%5d Node %5d : %d %2d %2d ", Counter, pNode->Id, nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) ); Abc_ObjForEachFanin( pNode, pFanin, k ) printf( "%d(%.2f)%s ", pFanin->Id, Abc_ObjSlack(pFanin), (puTCEdges[pNode->Id] & (1< Degree ) continue; // order the fanins in the increasing order of criticalily if ( Vec_PtrSize(vTimeCries) > 1 ) { pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) { Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); } } if ( Vec_PtrSize(vTimeCries) > 2 ) { pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 2 ); if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) { Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 2, pFanin ); } pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) { Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); } } // add choice Abc_NtkSpeedupNode( pNtk, pNtkNew, pNode, vTimeFanins, vTimeCries ); } Vec_PtrFree( vTimeCries ); Vec_PtrFree( vTimeFanins ); ABC_FREE( puTCEdges ); if ( fVerbose ) printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", Abc_NtkNodeNum(pNtk), Counter, CounterRes, 1.0*CounterRes/Counter ); // remove invalid choice nodes Abc_AigForEachAnd( pNtkNew, pNode, i ) if ( pNode->pData ) { if ( Abc_ObjFanoutNum((Abc_Obj_t *)pNode->pData) > 0 ) pNode->pData = NULL; } // return the result return pNtkNew; } /**Function************************************************************* Synopsis [Marks nodes for power-optimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Vec_Int_t * vProbs; Vec_Int_t * vSwitching; float * pProbability; float * pSwitching; Abc_Ntk_t * pNtkStr; Aig_Man_t * pAig; Aig_Obj_t * pObjAig; Abc_Obj_t * pObjAbc, * pObjAbc2; int i; // start the resulting array vProbs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); pProbability = (float *)vProbs->pArray; // strash the network pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 ); Abc_NtkForEachObj( pNtk, pObjAbc, i ) if ( Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)->Type == ABC_FUNC_NONE ) pObjAbc->pTemp = NULL; // map network into an AIG pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) ); vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, fProbOne ); pSwitching = (float *)vSwitching->pArray; Abc_NtkForEachObj( pNtk, pObjAbc, i ) { if ( (pObjAbc2 = Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)) && (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc2->pTemp)) ) pProbability[pObjAbc->Id] = pSwitching[pObjAig->Id]; } Vec_IntFree( vSwitching ); Aig_ManStop( pAig ); Abc_NtkDelete( pNtkStr ); return vProbs; } /**Function************************************************************* Synopsis [Marks nodes for power-optimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPowerPrint( Abc_Ntk_t * pNtk, Vec_Int_t * vProbs ) { Abc_Obj_t * pObj; float * pProb, TotalProb = 0.0, ProbThis, Probs[6] = {0.0}; int i, nNodes = 0, nEdges = 0, Counter[6] = {0}; pProb = (float *)vProbs->pArray; assert( Vec_IntSize(vProbs) >= Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPi(pObj) ) continue; nNodes++; nEdges += Abc_ObjFanoutNum(pObj); ProbThis = pProb[i] * Abc_ObjFanoutNum(pObj); TotalProb += ProbThis; assert( pProb[i] >= 0.0 && pProb[i] <= 1.0 ); if ( pProb[i] >= 0.5 ) { Counter[5]++; Probs[5] += ProbThis; } else if ( pProb[i] >= 0.4 ) { Counter[4]++; Probs[4] += ProbThis; } else if ( pProb[i] >= 0.3 ) { Counter[3]++; Probs[3] += ProbThis; } else if ( pProb[i] >= 0.2 ) { Counter[2]++; Probs[2] += ProbThis; } else if ( pProb[i] >= 0.1 ) { Counter[1]++; Probs[1] += ProbThis; } else { Counter[0]++; Probs[0] += ProbThis; } } printf( "Node distribution: " ); for ( i = 0; i < 6; i++ ) printf( "n%d%d = %6.2f%% ", i, i+1, 100.0 * Counter[i]/nNodes ); printf( "\n" ); printf( "Power distribution: " ); for ( i = 0; i < 6; i++ ) printf( "p%d%d = %6.2f%% ", i, i+1, 100.0 * Probs[i]/TotalProb ); printf( "\n" ); printf( "Total probs = %7.2f. ", TotalProb ); printf( "Total edges = %d. ", nEdges ); printf( "Average = %7.2f. ", TotalProb / nEdges ); printf( "\n" ); } /**Function************************************************************* Synopsis [Determines timing-critical edges of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Abc_NtkPowerCriticalEdges( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, float Limit, Vec_Int_t * vProbs ) { Abc_Obj_t * pFanin; float * pProb = (float *)vProbs->pArray; unsigned uResult = 0; int k; Abc_ObjForEachFanin( pNode, pFanin, k ) if ( pProb[pFanin->Id] >= Limit ) uResult |= (1 << k); return uResult; } /**Function************************************************************* Synopsis [Adds choices to speed up the network by the given percentage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ) { Abc_Ntk_t * pNtkNew; Vec_Int_t * vProbs; Vec_Ptr_t * vTimeCries, * vTimeFanins; Abc_Obj_t * pNode, * pFanin, * pFanin2; float * pProb, Limit; int i, k, k2, Counter, CounterRes, nTimeCris; unsigned * puPCEdges; // compute the limit Limit = 0.5 - (1.0 * Percentage / 100); // perform computation of switching probability vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); pProb = (float *)vProbs->pArray; // compute percentage of wires of each type if ( fVerbose ) Abc_NtkPowerPrint( pNtk, vProbs ); // mark the power critical nodes and edges puPCEdges = ABC_ALLOC( unsigned, Abc_NtkObjNumMax(pNtk) ); memset( puPCEdges, 0, sizeof(unsigned) * Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( pProb[pNode->Id] < Limit ) continue; puPCEdges[pNode->Id] = Abc_NtkPowerCriticalEdges( pNtk, pNode, Limit, vProbs ); } /* if ( fVerbose ) { Counter = CounterRes = 0; Abc_NtkForEachNode( pNtk, pNode, i ) { Counter += Abc_ObjFaninNum(pNode); CounterRes += Extra_WordCountOnes( puPCEdges[pNode->Id] ); } printf( "Edges: Total = %7d. Critical = %7d. Ratio = %4.2f\n", Counter, CounterRes, 1.0*CounterRes/Counter ); } */ // start the resulting network pNtkNew = Abc_NtkStrash( pNtk, 0, 1, 0 ); // collect nodes to be used for resynthesis Counter = CounterRes = 0; vTimeCries = Vec_PtrAlloc( 16 ); vTimeFanins = Vec_PtrAlloc( 16 ); Abc_NtkForEachNode( pNtk, pNode, i ) { // if ( pProb[pNode->Id] < Limit ) // continue; // count the number of non-PI power-critical nodes nTimeCris = 0; Abc_ObjForEachFanin( pNode, pFanin, k ) if ( !Abc_ObjIsCi(pFanin) && (puPCEdges[pNode->Id] & (1<Id] & (1<Id] & (1< Degree) ) if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) ) continue; CounterRes++; // collect second generation nodes Vec_PtrClear( vTimeFanins ); Abc_ObjForEachFanin( pNode, pFanin, k ) { if ( Abc_ObjIsCi(pFanin) ) Vec_PtrPushUnique( vTimeFanins, pFanin ); else Abc_ObjForEachFanin( pFanin, pFanin2, k2 ) Vec_PtrPushUnique( vTimeFanins, pFanin2 ); } // print the results if ( fVeryVerbose ) { printf( "%5d Node %5d : %d %2d %2d ", Counter, pNode->Id, nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) ); Abc_ObjForEachFanin( pNode, pFanin, k ) printf( "%d(%.2f)%s ", pFanin->Id, pProb[pFanin->Id], (puPCEdges[pNode->Id] & (1< Degree ) continue; // order the fanins in the increasing order of criticalily if ( Vec_PtrSize(vTimeCries) > 1 ) { pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); // if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) if ( pProb[pFanin->Id] > pProb[pFanin2->Id] ) { Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); } } if ( Vec_PtrSize(vTimeCries) > 2 ) { pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 2 ); // if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) if ( pProb[pFanin->Id] > pProb[pFanin2->Id] ) { Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 2, pFanin ); } pFanin = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); pFanin2 = (Abc_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); // if ( Abc_ObjSlack(pFanin) < Abc_ObjSlack(pFanin2) ) if ( pProb[pFanin->Id] > pProb[pFanin2->Id] ) { Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); } } // add choice Abc_NtkSpeedupNode( pNtk, pNtkNew, pNode, vTimeFanins, vTimeCries ); } Vec_PtrFree( vTimeCries ); Vec_PtrFree( vTimeFanins ); ABC_FREE( puPCEdges ); if ( fVerbose ) printf( "Nodes: Total = %7d. Power-critical = %7d. Workable = %7d. Ratio = %4.2f\n", Abc_NtkNodeNum(pNtk), Counter, CounterRes, 1.0*CounterRes/Counter ); // remove invalid choice nodes Abc_AigForEachAnd( pNtkNew, pNode, i ) if ( pNode->pData ) { if ( Abc_ObjFanoutNum((Abc_Obj_t *)pNode->pData) > 0 ) pNode->pData = NULL; } // return the result Vec_IntFree( vProbs ); return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcStrash.c000066400000000000000000000735431300674244400237360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcStrash.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Strashing of the current network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "bool/dec/dec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reapplies structural hashing to the AIG.] Description [Because of the structural hashing, this procedure should not change the number of nodes. It is useful to detect the bugs in the original AIG.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, int fCleanup ) { // extern int timeRetime; Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkAig; Abc_Obj_t * pObj; int i, nNodes;//, RetValue; assert( Abc_NtkIsStrash(pNtk) ); //timeRetime = Abc_Clock(); // print warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // restrash the nodes (assuming a topological order of the old network) vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // finalize the network Abc_NtkFinalize( pNtk, pNtkAig ); // print warning about self-feed latches // if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) // printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); // perform cleanup if requested if ( fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) { // printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); } // duplicate EXDC if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkAig ) ) { printf( "Abc_NtkStrash: The network check has failed.\n" ); Abc_NtkDelete( pNtkAig ); return NULL; } //timeRetime = Abc_Clock() - timeRetime; // if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) // printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); return pNtkAig; } /**Function************************************************************* Synopsis [Performs structural hashing by generating random number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRestrashRandom_rec( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) { if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); if ( !Abc_ObjIsNode(pObj) ) return; if ( rand() & 1 ) { Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin0(pObj) ); Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin1(pObj) ); } else { Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin1(pObj) ); Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin0(pObj) ); } pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); } /**Function************************************************************* Synopsis [Reapplies structural hashing to the AIG.] Description [Because of the structural hashing, this procedure should not change the number of nodes. It is useful to detect the bugs in the original AIG.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRestrashRandom( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkAig; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsStrash(pNtk) ); // print warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // restrash the nodes (assuming a topological order of the old network) Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_NtkRestrashRandom_rec( pNtkAig, Abc_ObjFanin0(pObj) ); // finalize the network Abc_NtkFinalize( pNtk, pNtkAig ); // duplicate EXDC if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); // 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 [Reapplies structural hashing to the AIG.] Description [Because of the structural hashing, this procedure should not change the number of nodes. It is useful to detect the bugs in the original AIG.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, int fCleanup ) { // extern int timeRetime; Abc_Ntk_t * pNtkAig; Abc_Obj_t * pObj; int i, nNodes;//, RetValue; int Counter = 0; assert( Abc_NtkIsStrash(pNtk) ); //timeRetime = Abc_Clock(); // print warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // complement the 1-values registers Abc_NtkForEachLatch( pNtk, pObj, i ) { if ( Abc_LatchIsInitDc(pObj) ) Counter++; else if ( Abc_LatchIsInit1(pObj) ) Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy); } if ( Counter ) printf( "Converting %d flops from don't-care to zero initial value.\n", Counter ); // 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 ); // complement the 1-valued registers Abc_NtkForEachLatch( pNtkAig, pObj, i ) if ( Abc_LatchIsInit1(pObj) ) { Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 ); // if latch has PO as one of its fanouts change latch name if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pObj) ) ) { Nm_ManDeleteIdName( pObj->pNtk->pManName, Abc_ObjFanout0(pObj)->Id ); Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjName(Abc_ObjFanout0(pObj)), "_inv" ); } } // set all constant-0 values Abc_NtkForEachLatch( pNtkAig, pObj, i ) Abc_LatchSetInit0( pObj ); // print warning about self-feed latches // if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) // printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); // perform cleanup if requested if ( fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); // duplicate EXDC if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); // transfer name IDs if ( pNtk->vNameIds ) Abc_NtkTransferNameIds( pNtk, pNtkAig ); if ( pNtk->vNameIds ) Abc_NtkUpdateNameIds( pNtkAig ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkAig ) ) { printf( "Abc_NtkStrash: The network check has failed.\n" ); Abc_NtkDelete( pNtkAig ); return NULL; } //timeRetime = Abc_Clock() - timeRetime; // if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) // printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); return pNtkAig; } /**Function************************************************************* Synopsis [Transforms logic network into structurally hashed AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ) { Abc_Ntk_t * pNtkAig; int nNodes; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); // consider the special case when the network is already structurally hashed if ( Abc_NtkIsStrash(pNtk) ) return Abc_NtkRestrash( pNtk, fCleanup ); // convert the node representation in the logic network to the AIG form if ( !Abc_NtkToAig(pNtk) ) { printf( "Converting to AIGs has failed.\n" ); return NULL; } // perform strashing // Abc_NtkCleanCopy( pNtk ); pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord ); Abc_NtkFinalize( pNtk, pNtkAig ); // transfer name IDs if ( pNtk->vNameIds ) Abc_NtkTransferNameIds( pNtk, pNtkAig ); // print warning about self-feed latches // if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) // printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); // perform cleanup if requested nNodes = fCleanup? Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc) : 0; // if ( nNodes ) // printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); // duplicate EXDC if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkStrash( pNtk->pExdc, fAllNodes, fCleanup, fRecord ); // 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 [Appends the second network to the first.] Description [Modifies the first network by adding the logic of the second. Performs structural hashing while appending the networks. Does not change the second network. Returns 0 if the appending failed, 1 otherise.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ) { Abc_Obj_t * pObj; char * pName; int i, nNewCis; // the first network should be an AIG assert( Abc_NtkIsStrash(pNtk1) ); assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) ); if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) ) { printf( "Converting to AIGs has failed.\n" ); return 0; } // check that the networks have the same PIs // reorder PIs of pNtk2 according to pNtk1 if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) ) printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" ); // perform strashing nNewCis = 0; Abc_NtkCleanCopy( pNtk2 ); if ( Abc_NtkIsStrash(pNtk2) ) Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1); Abc_NtkForEachCi( pNtk2, pObj, i ) { pName = Abc_ObjName(pObj); pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj)); if ( pObj->pCopy == NULL ) { pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1); nNewCis++; } } if ( nNewCis ) printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis ); // add pNtk2 to pNtk1 while strashing if ( Abc_NtkIsLogic(pNtk2) ) Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 ); else Abc_NtkForEachNode( pNtk2, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); // add the COs of the second network if ( fAddPos ) { Abc_NtkForEachPo( pNtk2, pObj, i ) { Abc_NtkDupObj( pNtk1, pObj, 0 ); Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } } else { Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew; int fCompl, iNodeId; // OR the choices Abc_NtkForEachCo( pNtk2, pObj, i ) { iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); // if ( iNodeId < 0 ) // continue; assert( iNodeId >= 0 ); pObjOld = Abc_NtkObj( pNtk1, iNodeId ); // derive the new driver pDriverOld = Abc_ObjChild0( pObjOld ); pDriverNew = Abc_ObjChild0Copy( pObj ); pDriverNew = Abc_AigOr( (Abc_Aig_t *)pNtk1->pManFunc, pDriverOld, pDriverNew ); if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) ) continue; // replace the old driver by the new driver fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase; Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) ); } } // make sure that everything is okay if ( !Abc_NtkCheck( pNtk1 ) ) { printf( "Abc_NtkAppend: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Prepares the network for strashing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNodeOld; int i; //, clk = Abc_Clock(); assert( Abc_NtkIsLogic(pNtkOld) ); assert( Abc_NtkIsStrash(pNtkNew) ); // vNodes = Abc_NtkDfs( pNtkOld, fAllNodes ); vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes ); //printf( "Nodes = %d. ", Vec_PtrSize(vNodes) ); //ABC_PRT( "Time", Abc_Clock() - clk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNodeOld, i ) { if ( Abc_ObjIsBarBuf(pNodeOld) ) pNodeOld->pCopy = Abc_ObjChild0Copy(pNodeOld); else pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord ); } Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Transfers the AIG from one manager into another.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) ); Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) ); pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Strashes one logic node.] Description [Assume the network is in the AIG form] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord ) { Hop_Man_t * pMan; Hop_Obj_t * pRoot; Abc_Obj_t * pFanin; int i; assert( Abc_ObjIsNode(pNodeOld) ); assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) ); // get the local AIG manager and the local root node pMan = (Hop_Man_t *)pNodeOld->pNtk->pManFunc; pRoot = (Hop_Obj_t *)pNodeOld->pData; // check the constant case if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) ); // perform special case-strashing using the record of AIG subgraphs /* if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() ) { extern Vec_Int_t * Abc_NtkRecMemory(); extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); int nVars = Abc_NtkRecVarNum(); Vec_Int_t * vMemory = Abc_NtkRecMemory(); unsigned * pTruth = Hop_ManConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 ); assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept if ( Hop_IsComplement(pRoot) ) Extra_TruthNot( pTruth, pTruth, nVars ); if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) ) return pNodeOld->pCopy; } */ // set elementary variables Abc_ObjForEachFanin( pNodeOld, pFanin, i ) Hop_IthVar(pMan, i)->pData = pFanin->pCopy; // strash the AIG of this node Abc_NodeStrash_rec( (Abc_Aig_t *)pNtkNew->pManFunc, Hop_Regular(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); // return the final node return Abc_ObjNotCond( (Abc_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Copies the topmost levels of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut ) { assert( !Abc_ObjIsComplement(pNode) ); if ( pNode->pCopy ) return pNode->pCopy; if ( pNode->Level <= (unsigned)LevelCut ) return pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut ); Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut ); return pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); } /**Function************************************************************* Synopsis [Copies the topmost levels of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjNew, * pObjPo; int LevelCut; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkCoNum(pNtk) == 1 ); // get the cutoff level LevelCut = Abc_MaxInt( 0, Abc_AigLevel(pNtk) - nLevels ); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // create PIs below the cut and nodes above the cut Abc_NtkCleanCopy( pNtk ); pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut ); pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) ); // add the PO node and name pObjPo = Abc_NtkCreatePo(pNtkNew); Abc_ObjAddFanin( pObjPo, pObjNew ); Abc_NtkAddDummyPiNames( pNtkNew ); Abc_ObjAssignName( pObjPo, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkTopmost: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_CompareNodeIds( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { if ( Abc_ObjRegular(*pp1)->Id < Abc_ObjRegular(*pp2)->Id ) return -1; if ( Abc_ObjRegular(*pp1)->Id > Abc_ObjRegular(*pp2)->Id ) // return 1; return 0; } /**Function************************************************************* Synopsis [Collects the large supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeGetSuper( Abc_Obj_t * pNode ) { Vec_Ptr_t * vSuper, * vFront; Abc_Obj_t * pAnd, * pFanin; int i; assert( Abc_ObjIsNode(pNode) && !Abc_ObjIsComplement(pNode) ); vSuper = Vec_PtrAlloc( 100 ); // explore the frontier vFront = Vec_PtrAlloc( 100 ); Vec_PtrPush( vFront, pNode ); Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pAnd, i ) { pFanin = Abc_ObjChild0(pAnd); if ( Abc_ObjIsNode(pFanin) && !Abc_ObjIsComplement(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) Vec_PtrPush( vFront, pFanin ); else Vec_PtrPush( vSuper, pFanin ); pFanin = Abc_ObjChild1(pAnd); if ( Abc_ObjIsNode(pFanin) && !Abc_ObjIsComplement(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) Vec_PtrPush( vFront, pFanin ); else Vec_PtrPush( vSuper, pFanin ); } Vec_PtrFree( vFront ); // reverse the array of pointers to start with lower IDs vFront = Vec_PtrAlloc( Vec_PtrSize(vSuper) ); Vec_PtrForEachEntryReverse( Abc_Obj_t *, vSuper, pNode, i ) Vec_PtrPush( vFront, pNode ); Vec_PtrFree( vSuper ); vSuper = vFront; // uniquify and return the frontier Vec_PtrUniqify( vSuper, (int (*)())Vec_CompareNodeIds ); return vSuper; } /**Function************************************************************* Synopsis [Copies the topmost levels of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkTopAnd( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes, * vOrder; Abc_Ntk_t * pNtkAig; Abc_Obj_t * pObj, * pDriver, * pObjPo; int i, nNodes; assert( Abc_NtkIsStrash(pNtk) ); // get the first PO pObjPo = Abc_NtkPo(pNtk, 0); vNodes = Abc_NodeGetSuper( Abc_ObjChild0(pObjPo) ); assert( Vec_PtrSize(vNodes) >= 2 ); // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) Abc_NtkCleanCopy( pNtk ); pNtkAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkAig->pName = Extra_UtilStrsav(pNtk->pName); pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec); Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkAig); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkAig, pObj, 1 ); // restrash the nodes reachable from the roots vOrder = Abc_NtkDfsIterNodes( pNtk, vNodes ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); Vec_PtrFree( vOrder ); // finalize the network Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { pObjPo = Abc_NtkCreatePo(pNtkAig); pDriver = Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj)); Abc_ObjAddFanin( pObjPo, pDriver ); Abc_ObjAssignName( pObjPo, Abc_ObjName(pObjPo), NULL ); } Vec_PtrFree( vNodes ); // perform cleanup if requested if ( (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) printf( "Abc_NtkTopAnd(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); // 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 [Writes the AIG into a file for parsing.] Description [Ordering: c0, pis, ands, pos. ] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkWriteAig( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; Vec_Int_t * vId2Num; Abc_Obj_t * pObj; int i, iLit; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkLatchNum(pNtk) == 0 ); if ( pFileName == NULL ) pFile = stdout; else pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Cannot open output file.\n" ); return; } vId2Num = Vec_IntAlloc( 2*Abc_NtkObjNumMax(pNtk) ); Vec_IntFill( vId2Num, 2*Abc_NtkObjNumMax(pNtk), -1 ); iLit = 0; Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(Abc_AigConst1(pNtk))+1, iLit++ ); Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(Abc_AigConst1(pNtk))+0, iLit++ ); Abc_NtkForEachPi( pNtk, pObj, i ) { Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+0, iLit++ ); Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+1, iLit++ ); } Abc_AigForEachAnd( pNtk, pObj, i ) { Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+0, iLit++ ); Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+1, iLit++ ); } fprintf( pFile, "{\n" ); fprintf( pFile, " \"%s\", ", Abc_NtkName(pNtk) ); fprintf( pFile, "// pi=%d po=%d and=%d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) ); fprintf( pFile, "\n" ); fprintf( pFile, " { " ); Abc_NtkForEachPi( pNtk, pObj, i ) fprintf( pFile, "\"%s\",", Abc_ObjName(pObj) ); fprintf( pFile, "NULL },\n" ); fprintf( pFile, " { " ); Abc_NtkForEachPo( pNtk, pObj, i ) fprintf( pFile, "\"%s\",", Abc_ObjName(pObj) ); fprintf( pFile, "NULL },\n" ); fprintf( pFile, " { " ); Abc_AigForEachAnd( pNtk, pObj, i ) fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId0(pObj) + Abc_ObjFaninC0(pObj)) ); fprintf( pFile, "0 },\n" ); fprintf( pFile, " { " ); Abc_AigForEachAnd( pNtk, pObj, i ) fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId1(pObj) + Abc_ObjFaninC1(pObj)) ); fprintf( pFile, "0 },\n" ); fprintf( pFile, " { " ); Abc_NtkForEachPo( pNtk, pObj, i ) fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId0(pObj) + Abc_ObjFaninC0(pObj)) ); fprintf( pFile, "0 },\n" ); fprintf( pFile, "},\n" ); if ( pFile != stdout ) fclose( pFile ); Vec_IntFree( vId2Num ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkPutOnTop( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtk2 ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; assert( Abc_NtkIsLogic(pNtk) ); assert( Abc_NtkIsLogic(pNtk2) ); assert( Abc_NtkPoNum(pNtk) == Abc_NtkPiNum(pNtk2) ); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); Abc_NtkCleanCopy( pNtk2 ); // duplicate the name and the spec pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); // add internal nodes vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } Vec_PtrFree( vNodes ); // transfer to the POs Abc_NtkForEachPi( pNtk2, pObj, i ) pObj->pCopy = Abc_ObjChild0Copy( Abc_NtkPo(pNtk, i) ); // add internal nodes vNodes = Abc_NtkDfs( pNtk2, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } Vec_PtrFree( vNodes ); // clone CIs/CIs/boxes Abc_NtkForEachPo( pNtk2, pObj, i ) { Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); } if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkPutOnTop(): Network check has failed.\n" ); return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcSweep.c000066400000000000000000001004001300674244400235340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Technology dependent sweep.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "proof/fraig/fraig.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); static stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ); static void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, int fVerbose ); static void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ); static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ); static int Abc_NodeDroppingCost( Abc_Obj_t * pNode ); static int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ); static void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sweping functionally equivalence nodes.] Description [Removes gates with equivalent functionality. Works for both technology-independent and mapped networks. If the flag is set, allows adding inverters at the gate outputs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ) { Fraig_Params_t Params; Abc_Ntk_t * pNtkAig; Fraig_Man_t * pMan; stmm_table * tEquiv; Abc_Obj_t * pObj; int i, fUseTrick; assert( !Abc_NtkIsStrash(pNtk) ); // save gate assignments fUseTrick = 0; if ( Abc_NtkIsMappedLogic(pNtk) ) { fUseTrick = 1; Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pNext = (Abc_Obj_t *)pObj->pData; } // derive the AIG pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 ); // reconstruct gate assignments if ( fUseTrick ) { // extern void * Abc_FrameReadLibGen(); Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc ); pNtk->pManFunc = Abc_FrameReadLibGen(); pNtk->ntkFunc = ABC_FUNC_MAP; Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pData = pObj->pNext, pObj->pNext = NULL; } // perform fraiging of the AIG Fraig_ParamsSetDefault( &Params ); Params.fInternal = 1; pMan = (Fraig_Man_t *)Abc_NtkToFraig( pNtkAig, &Params, 0, 0 ); // cannot use EXDC with FRAIG because it can create classes of equivalent FRAIG nodes // with representative nodes that do not correspond to the nodes with the current network // update FRAIG using EXDC if ( fExdc ) { if ( pNtk->pExdc == NULL ) printf( "Warning: Networks has no EXDC.\n" ); else Abc_NtkFraigSweepUsingExdc( pMan, pNtk ); } // assign levels to the nodes of the network Abc_NtkLevel( pNtk ); // collect the classes of equivalent nets tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose ); // transform the network into the equivalent one Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose ); stmm_free_table( tEquiv ); // free the manager Fraig_ManFree( pMan ); Abc_NtkDelete( pNtkAig ); // cleanup the dangling nodes if ( Abc_NtkHasMapping(pNtk) ) Abc_NtkCleanup( pNtk, fVerbose ); else Abc_NtkSweep( pNtk, fVerbose ); // check if ( !Abc_NtkCheck( pNtk ) ) { printf( "Abc_NtkFraigSweep: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Sweep the network using EXDC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) { Fraig_Node_t * gNodeExdc, * gNode, * gNodeRes; Abc_Obj_t * pNode, * pNodeAig; int i; extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkExdc ); assert( pNtk->pExdc ); // derive FRAIG node representing don't-cares in the EXDC network gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc ); // update the node pointers Abc_NtkForEachNode( pNtk, pNode, i ) { // skip the constant input nodes if ( Abc_ObjFaninNum(pNode) == 0 ) continue; // get the strashed node pNodeAig = pNode->pCopy; // skip the dangling nodes if ( pNodeAig == NULL ) continue; // get the FRAIG node gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, (int)Abc_ObjIsComplement(pNodeAig) ); // perform ANDing with EXDC gNodeRes = Fraig_NodeAnd( pMan, gNode, Fraig_Not(gNodeExdc) ); // write the node back Abc_ObjRegular(pNodeAig)->pCopy = (Abc_Obj_t *)Fraig_NotCond( gNodeRes, (int)Abc_ObjIsComplement(pNodeAig) ); } } /**Function************************************************************* Synopsis [Collects equivalence classes of node in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ) { Abc_Obj_t * pList, * pNode, * pNodeAig; Fraig_Node_t * gNode; Abc_Obj_t ** ppSlot; stmm_table * tStrash2Net; stmm_table * tResult; stmm_generator * gen; int c, Counter; // create mapping of strashed nodes into the corresponding network nodes tStrash2Net = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); Abc_NtkForEachNode( pNtk, pNode, c ) { // skip the constant input nodes if ( Abc_ObjFaninNum(pNode) == 0 ) continue; // get the strashed node pNodeAig = pNode->pCopy; // skip the dangling nodes if ( pNodeAig == NULL ) continue; // skip the nodes that fanout into COs if ( Abc_NodeFindCoFanout(pNode) ) continue; // get the FRAIG node gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, (int)Abc_ObjIsComplement(pNodeAig) ); if ( !stmm_find_or_add( tStrash2Net, (char *)Fraig_Regular(gNode), (char ***)&ppSlot ) ) *ppSlot = NULL; // add the node to the list pNode->pNext = *ppSlot; *ppSlot = pNode; // mark the node if it is complemented pNode->fPhase = Fraig_IsComplement(gNode); } // print the classes c = 0; Counter = 0; tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); stmm_foreach_item( tStrash2Net, gen, (char **)&gNode, (char **)&pList ) { // skip the trival classes if ( pList == NULL || pList->pNext == NULL ) continue; // add the non-trival class stmm_insert( tResult, (char *)pList, NULL ); // count nodes in the non-trival classes for ( pNode = pList; pNode; pNode = pNode->pNext ) Counter++; if ( fVeryVerbose ) { printf( "Class %2d : {", c ); for ( pNode = pList; pNode; pNode = pNode->pNext ) { pNode->pCopy = NULL; printf( " %s", Abc_ObjName(pNode) ); printf( "(%c)", pNode->fPhase? '-' : '+' ); printf( "(%d)", pNode->Level ); } printf( " }\n" ); c++; } } if ( fVerbose || fVeryVerbose ) { printf( "Sweeping stats for network \"%s\":\n", pNtk->pName ); printf( "Internal nodes = %d. Different functions (up to compl) = %d.\n", Abc_NtkNodeNum(pNtk), stmm_count(tStrash2Net) ); printf( "Non-trivial classes = %d. Nodes in non-trivial classes = %d.\n", stmm_count(tResult), Counter ); } stmm_free_table( tStrash2Net ); return tResult; } /**Function************************************************************* Synopsis [Transforms the network using the equivalence relation on nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, int fVerbose ) { stmm_generator * gen; Abc_Obj_t * pList; if ( stmm_count(tEquiv) == 0 ) return; // merge nodes in the classes if ( Abc_NtkHasMapping( pNtk ) ) { Abc_NtkDelayTrace( pNtk, NULL, NULL, 0 ); stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL ) Abc_NtkFraigMergeClassMapped( pNtk, pList, fUseInv, fVerbose ); } else { stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL ) Abc_NtkFraigMergeClass( pNtk, pList, fUseInv, fVerbose ); } } /**Function************************************************************* Synopsis [Transforms the list of one-phase equivalent nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ) { Abc_Obj_t * pListDir, * pListInv; Abc_Obj_t * pNodeMin, * pNode, * pNext; float Arrival1, Arrival2; assert( pChain ); assert( pChain->pNext ); // divide the nodes into two parts: // those that need the invertor and those that don't need pListDir = pListInv = NULL; for ( pNode = pChain, pNext = pChain->pNext; pNode; pNode = pNext, pNext = pNode? pNode->pNext : NULL ) { // check to which class the node belongs if ( pNode->fPhase == 1 ) { pNode->pNext = pListDir; pListDir = pNode; } else { pNode->pNext = pListInv; pListInv = pNode; } } // find the node with the smallest number of logic levels pNodeMin = pListDir; for ( pNode = pListDir; pNode; pNode = pNode->pNext ) { Arrival1 = Abc_NodeReadArrivalWorst(pNodeMin); Arrival2 = Abc_NodeReadArrivalWorst(pNode ); // assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); // assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); if ( Arrival1 > Arrival2 || (Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level) || (Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level && Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode)) ) pNodeMin = pNode; } // move the fanouts of the direct nodes for ( pNode = pListDir; pNode; pNode = pNode->pNext ) if ( pNode != pNodeMin ) Abc_ObjTransferFanout( pNode, pNodeMin ); // find the node with the smallest number of logic levels pNodeMin = pListInv; for ( pNode = pListInv; pNode; pNode = pNode->pNext ) { Arrival1 = Abc_NodeReadArrivalWorst(pNodeMin); Arrival2 = Abc_NodeReadArrivalWorst(pNode ); // assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); // assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); if ( Arrival1 > Arrival2 || (Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level) || (Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level && Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode)) ) pNodeMin = pNode; } // move the fanouts of the direct nodes for ( pNode = pListInv; pNode; pNode = pNode->pNext ) if ( pNode != pNodeMin ) Abc_ObjTransferFanout( pNode, pNodeMin ); } /**Function************************************************************* Synopsis [Process one equivalence class of nodes.] Description [This function does not remove the nodes. It only switches around the connections.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ) { Abc_Obj_t * pListDir, * pListInv; Abc_Obj_t * pNodeMin, * pNodeMinInv; Abc_Obj_t * pNode, * pNext; assert( pChain ); assert( pChain->pNext ); // find the node with the smallest number of logic levels pNodeMin = pChain; for ( pNode = pChain->pNext; pNode; pNode = pNode->pNext ) if ( pNodeMin->Level > pNode->Level || ( pNodeMin->Level == pNode->Level && Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) ) pNodeMin = pNode; // divide the nodes into two parts: // those that need the invertor and those that don't need pListDir = pListInv = NULL; for ( pNode = pChain, pNext = pChain->pNext; pNode; pNode = pNext, pNext = pNode? pNode->pNext : NULL ) { if ( pNode == pNodeMin ) continue; // check to which class the node belongs if ( pNodeMin->fPhase == pNode->fPhase ) { pNode->pNext = pListDir; pListDir = pNode; } else { pNode->pNext = pListInv; pListInv = pNode; } } // move the fanouts of the direct nodes for ( pNode = pListDir; pNode; pNode = pNode->pNext ) Abc_ObjTransferFanout( pNode, pNodeMin ); // skip if there are no inverted nodes if ( pListInv == NULL ) return; // add the invertor pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin ); // move the fanouts of the inverted nodes for ( pNode = pListInv; pNode; pNode = pNode->pNext ) Abc_ObjTransferFanout( pNode, pNodeMinInv ); } /**Function************************************************************* Synopsis [Returns the number of literals saved if this node becomes useless.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeDroppingCost( Abc_Obj_t * pNode ) { return 1; } /**Function************************************************************* Synopsis [Removes dangling nodes.] Description [Returns the number of nodes removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ) { Vec_Ptr_t * vNodes; int Counter; assert( Abc_NtkIsLogic(pNtk) ); // mark the nodes reachable from the POs vNodes = Abc_NtkDfs( pNtk, 0 ); Counter = Abc_NtkReduceNodes( pNtk, vNodes ); if ( fVerbose ) printf( "Cleanup removed %d dangling nodes.\n", Counter ); Vec_PtrFree( vNodes ); return Counter; } /**Function************************************************************* Synopsis [Removes dangling nodes.] Description [Returns the number of nodes removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCleanupNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fVerbose ) { Vec_Ptr_t * vNodes, * vStarts; Abc_Obj_t * pObj; int i, Counter; assert( Abc_NtkIsLogic(pNtk) ); // collect starting nodes into one array vStarts = Vec_PtrAlloc( 1000 ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_PtrPush( vStarts, pObj ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) if ( pObj ) Vec_PtrPush( vStarts, pObj ); // mark the nodes reachable from the POs vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vStarts), Vec_PtrSize(vStarts) ); Vec_PtrFree( vStarts ); Counter = Abc_NtkReduceNodes( pNtk, vNodes ); if ( fVerbose ) printf( "Cleanup removed %d dangling nodes.\n", Counter ); Vec_PtrFree( vNodes ); return Counter; } /**Function************************************************************* Synopsis [Preserves the nodes collected in the array.] Description [Returns the number of nodes removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pNode; int i, Counter; assert( Abc_NtkIsLogic(pNtk) ); // mark the nodes reachable from the POs Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) pNode->fMarkA = 1; // remove the non-marked nodes Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) if ( pNode->fMarkA == 0 ) { Abc_NtkDeleteObj( pNode ); Counter++; } // unmark the remaining nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) pNode->fMarkA = 0; // check if ( !Abc_NtkCheck( pNtk ) ) printf( "Abc_NtkCleanup: The network check has failed.\n" ); return Counter; } #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Replaces the local function by its cofactor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, int fConst0 ) { DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; DdNode * bVar, * bTemp; int iFanin; assert( Abc_NtkIsBddLogic(pNode->pNtk) ); 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; } bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iFanin), fConst0 ); pNode->pData = Cudd_Cofactor( dd, bTemp = (DdNode *)pNode->pData, bVar ); Cudd_Ref( (DdNode *)pNode->pData ); Cudd_RecursiveDeref( dd, bTemp ); } /**Function************************************************************* Synopsis [Tranditional sweep of the network.] Description [Propagates constant and single-input node, removes dangling nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanout, * pDriver; int i, nNodesOld; assert( Abc_NtkIsLogic(pNtk) ); // convert network to BDD representation if ( !Abc_NtkToBdd(pNtk) ) { fprintf( stdout, "Converting to BDD has failed.\n" ); return 1; } // perform cleanup nNodesOld = Abc_NtkNodeNum(pNtk); Abc_NtkCleanup( pNtk, 0 ); // prepare nodes for sweeping Abc_NtkRemoveDupFanins(pNtk); Abc_NtkMinimumBase(pNtk); // collect sweepable nodes vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) if ( Abc_ObjFaninNum(pNode) < 2 ) Vec_PtrPush( vNodes, pNode ); // sweep the nodes while ( Vec_PtrSize(vNodes) > 0 ) { // get any sweepable node pNode = (Abc_Obj_t *)Vec_PtrPop(vNodes); if ( !Abc_ObjIsNode(pNode) ) continue; // get any non-CO fanout of this node pFanout = Abc_NodeFindNonCoFanout(pNode); if ( pFanout == NULL ) continue; assert( Abc_ObjIsNode(pFanout) ); // transform the function of the fanout if ( Abc_ObjFaninNum(pNode) == 0 ) Abc_NodeConstantInput( pFanout, pNode, Abc_NodeIsConst0(pNode) ); else { assert( Abc_ObjFaninNum(pNode) == 1 ); pDriver = Abc_ObjFanin0(pNode); if ( Abc_NodeIsInv(pNode) ) Abc_NodeComplementInput( pFanout, pNode ); Abc_ObjPatchFanin( pFanout, pNode, pDriver ); } Abc_NodeRemoveDupFanins( pFanout ); Abc_NodeMinimumBase( pFanout ); // check if the fanout should be added if ( Abc_ObjFaninNum(pFanout) < 2 ) Vec_PtrPush( vNodes, pFanout ); // check if the node has other fanouts if ( Abc_ObjFanoutNum(pNode) > 0 ) Vec_PtrPush( vNodes, pNode ); else Abc_NtkDeleteObj_rec( pNode, 1 ); } Vec_PtrFree( vNodes ); // sweep a node into its CO fanout if all of this is true: // (a) this node is a single-input node // (b) the driver of the node has only one fanout (this node) // (c) the driver is a node Abc_NtkForEachCo( pNtk, pFanout, i ) { pNode = Abc_ObjFanin0(pFanout); if ( Abc_ObjFaninNum(pNode) != 1 ) continue; pDriver = Abc_ObjFanin0(pNode); if ( !(Abc_ObjFanoutNum(pDriver) == 1 && Abc_ObjIsNode(pDriver)) ) continue; // trasform this CO if ( Abc_NodeIsInv(pNode) ) pDriver->pData = Cudd_Not(pDriver->pData); Abc_ObjPatchFanin( pFanout, pNode, pDriver ); } // perform cleanup Abc_NtkCleanup( pNtk, 0 ); // report if ( fVerbose ) printf( "Sweep removed %d nodes.\n", nNodesOld - Abc_NtkNodeNum(pNtk) ); return nNodesOld - Abc_NtkNodeNum(pNtk); } #else int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ) { return 1; } #endif /**Function************************************************************* Synopsis [Removes all objects whose trav ID is not current.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeRemoveNonCurrentObjects( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int Counter, i; int fVerbose = 0; // report on the nodes to be deleted if ( fVerbose ) { printf( "These nodes will be deleted: \n" ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent( pObj ) ) { printf( " " ); Abc_ObjPrint( stdout, pObj ); } } // delete the nodes Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent( pObj ) ) { Abc_NtkDeleteObj( pObj ); Counter++; } return Counter; } /**Function************************************************************* Synopsis [Check if the fanin of this latch is a constant.] Description [Returns 0/1 if constant; -1 if not a constant.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSetTravId_rec( Abc_Obj_t * pObj ) { Abc_NodeSetTravIdCurrent(pObj); if ( Abc_ObjFaninNum(pObj) == 0 ) return; assert( Abc_ObjFaninNum(pObj) == 1 ); Abc_NtkSetTravId_rec( Abc_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [Check if the fanin of this latch is a constant.] Description [Returns 0/1 if constant; -1 if not a constant.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckConstant_rec( Abc_Obj_t * pObj ) { if ( Abc_ObjFaninNum(pObj) == 0 ) { if ( !Abc_ObjIsNode(pObj) ) return -1; if ( Abc_NodeIsConst0(pObj) ) return 0; if ( Abc_NodeIsConst1(pObj) ) return 1; assert( 0 ); return -1; } if ( Abc_ObjIsLatch(pObj) || Abc_ObjFaninNum(pObj) > 1 ) return -1; if ( !Abc_ObjIsNode(pObj) || Abc_NodeIsBuf(pObj) ) return Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) ); if ( Abc_NodeIsInv(pObj) ) { int RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) ); if ( RetValue == 0 ) return 1; if ( RetValue == 1 ) return 0; return RetValue; } assert( 0 ); return -1; } /**Function************************************************************* Synopsis [Removes redundant latches.] Description [The redundant latches are of two types: - Latches fed by a constant which matches the init value of the latch. - Latches fed by a constant which does not match the init value of the latch can be all replaced by one latch.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLatchSweep( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pFanin, * pLatch, * pLatchPivot = NULL; int Counter, RetValue, i; Counter = 0; // go through the latches Abc_NtkForEachLatch( pNtk, pLatch, i ) { // check if the latch has constant input RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pLatch) ); if ( RetValue == -1 ) continue; // found a latch with constant fanin if ( (RetValue == 1 && Abc_LatchIsInit0(pLatch)) || (RetValue == 0 && Abc_LatchIsInit1(pLatch)) ) { // fanin constant differs from the latch init value if ( pLatchPivot == NULL ) { pLatchPivot = pLatch; continue; } if ( Abc_LatchInit(pLatch) != Abc_LatchInit(pLatchPivot) ) // add inverter pFanin = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanout0(pLatchPivot) ); else pFanin = Abc_ObjFanout0(pLatchPivot); } else pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); // replace latch Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pFanin ); // delete the extra nodes Abc_NtkDeleteObj_rec( Abc_ObjFanout0(pLatch), 0 ); Counter++; } return Counter; } /**Function************************************************************* Synopsis [Replaces autonumnous logic by free inputs.] Description [Assumes that non-autonomous logic is marked with the current ID.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pFanin; Vec_Ptr_t * vNodes; int i, k, Counter; // collect the nodes that feed into the reachable logic vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachObj( pNtk, pNode, i ) { // skip non-visited fanins if ( !Abc_NodeIsTravIdCurrent(pNode) ) continue; // look for non-visited fanins Abc_ObjForEachFanin( pNode, pFanin, k ) { // skip visited fanins if ( Abc_NodeIsTravIdCurrent(pFanin) ) continue; // skip constants and latches fed by constants if ( Abc_NtkCheckConstant_rec(pFanin) != -1 || (Abc_ObjIsBo(pFanin) && Abc_NtkCheckConstant_rec(Abc_ObjFanin0(Abc_ObjFanin0(pFanin))) != -1) ) { Abc_NtkSetTravId_rec( pFanin ); continue; } assert( !Abc_ObjIsLatch(pFanin) ); Vec_PtrPush( vNodes, pFanin ); } } Vec_PtrUniqify( vNodes, (int (*)(void))Abc_ObjPointerCompare ); // replace these nodes by the PIs Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { pFanin = Abc_NtkCreatePi(pNtk); Abc_ObjAssignName( pFanin, Abc_ObjName(pFanin), NULL ); Abc_NodeSetTravIdCurrent( pFanin ); Abc_ObjTransferFanout( pNode, pFanin ); } Counter = Vec_PtrSize(vNodes); Vec_PtrFree( vNodes ); return Counter; } /**Function************************************************************* Synopsis [Sequential cleanup.] Description [Performs three tasks: - Removes logic that does not feed into POs. - Removes latches driven by constant values equal to the initial state. - Replaces the autonomous components by additional PI variables.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ) { Vec_Ptr_t * vNodes; int Counter; assert( Abc_NtkIsLogic(pNtk) ); // mark the nodes reachable from the POs vNodes = Abc_NtkDfsSeq( pNtk ); Vec_PtrFree( vNodes ); // remove the non-marked nodes Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); if ( fVerbose ) printf( "Cleanup removed %4d dangling objects.\n", Counter ); // check if some of the latches can be removed if ( fLatchSweep ) { Counter = Abc_NtkLatchSweep( pNtk ); if ( fVerbose ) printf( "Cleanup removed %4d redundant latches.\n", Counter ); } // detect the autonomous components if ( fAutoSweep ) { vNodes = Abc_NtkDfsSeqReverse( pNtk ); Vec_PtrFree( vNodes ); // replace them by PIs Counter = Abc_NtkReplaceAutonomousLogic( pNtk ); if ( fVerbose ) printf( "Cleanup added %4d additional PIs.\n", Counter ); // remove the non-marked nodes Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); if ( fVerbose ) printf( "Cleanup removed %4d autonomous objects.\n", Counter ); } // check if ( !Abc_NtkCheck( pNtk ) ) printf( "Abc_NtkCleanupSeq: The network check has failed.\n" ); return 1; } /**Function************************************************************* Synopsis [Sweep to remove buffers and inverters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSweepBufsInvs( Abc_Ntk_t * pNtk, int fVerbose ) { Hop_Man_t * pMan; Abc_Obj_t * pObj, * pFanin; int i, k, fChanges = 1, Counter = 0; assert( Abc_NtkIsLogic(pNtk) ); // convert network to BDD representation if ( !Abc_NtkToAig(pNtk) ) { fprintf( stdout, "Converting to SOP has failed.\n" ); return 1; } // get AIG manager pMan = (Hop_Man_t *)pNtk->pManFunc; // label selected nodes Abc_NtkIncrementTravId( pNtk ); // iterate till no improvement while ( fChanges ) { fChanges = 0; Abc_NtkForEachObj( pNtk, pObj, i ) { Abc_ObjForEachFanin( pObj, pFanin, k ) { // do not eliminate marked fanins if ( Abc_NodeIsTravIdCurrent(pFanin) ) continue; // do not eliminate constant nodes if ( !Abc_ObjIsNode(pFanin) || Abc_ObjFaninNum(pFanin) != 1 ) continue; // do not eliminate inverters into COs if ( Abc_ObjIsCo(pObj) && Abc_NodeIsInv(pFanin) ) continue; // do not eliminate buffers connecting PIs and POs // if ( Abc_ObjIsCo(pObj) && Abc_ObjIsCi(Abc_ObjFanin0(pFanin)) ) // continue; fChanges = 1; Counter++; // update function of the node if ( Abc_NodeIsInv(pFanin) ) pObj->pData = Hop_Compose( pMan, (Hop_Obj_t *)pObj->pData, Hop_Not(Hop_IthVar(pMan, k)), k ); // update the fanin Abc_ObjPatchFanin( pObj, pFanin, Abc_ObjFanin0(pFanin) ); if ( Abc_ObjFanoutNum(pFanin) == 0 ) Abc_NtkDeleteObj(pFanin); } } } if ( fVerbose ) printf( "Removed %d single input nodes.\n", Counter ); return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcSymm.c000066400000000000000000000166611300674244400234150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcSymm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Computation of two-variable symmetries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcSymm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "opt/sim/sim.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ); static void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ); static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ); static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [The top level procedure to compute symmetries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ) { if ( fUseBdds || fNaive ) Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose ); else Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose ); } /**Function************************************************************* Synopsis [Symmetry computation using simulation and SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ) { // extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ); int nSymms = Sim_ComputeTwoVarSymms( pNtk, fVerbose ); printf( "The total number of symmetries is %d.\n", nSymms ); } /**Function************************************************************* Synopsis [Symmetry computation using BDDs (both naive and smart).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ) { DdManager * dd; abctime clk, clkBdd, clkSym; int fGarbCollect = 1; // compute the global functions clk = Abc_Clock(); dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, fVerbose ); printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) ); Cudd_AutodynDisable( dd ); if ( !fGarbCollect ) Cudd_DisableGarbageCollection( dd ); Cudd_zddVarsFromBddVars( dd, 2 ); clkBdd = Abc_Clock() - clk; // create the collapsed network clk = Abc_Clock(); Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose ); clkSym = Abc_Clock() - clk; // undo the global functions Abc_NtkFreeGlobalBdds( pNtk, 1 ); printf( "Statistics of BDD-based symmetry detection:\n" ); printf( "Algorithm = %s. Reordering = %s. Garbage collection = %s.\n", fNaive? "naive" : "fast", fReorder? "yes" : "no", fGarbCollect? "yes" : "no" ); ABC_PRT( "Constructing BDDs", clkBdd ); ABC_PRT( "Computing symms ", clkSym ); ABC_PRT( "TOTAL ", clkBdd + clkSym ); } /**Function************************************************************* Synopsis [Symmetry computation using BDDs (both naive and smart).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) { Extra_SymmInfo_t * pSymms; Abc_Obj_t * pNode; DdNode * bFunc; int nSymms = 0; int nSupps = 0; int i; // compute symmetry info for each PO Abc_NtkForEachCo( pNtk, pNode, i ) { // bFunc = pNtk->vFuncsGlob->pArray[i]; bFunc = (DdNode *)Abc_ObjGlobalBdd( pNode ); nSupps += Cudd_SupportSize( dd, bFunc ); if ( Cudd_IsConstant(bFunc) ) continue; if ( fNaive ) pSymms = Extra_SymmPairsComputeNaive( dd, bFunc ); else pSymms = Extra_SymmPairsCompute( dd, bFunc ); nSymms += pSymms->nSymms; if ( fVerbose ) { printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms ); Ntk_NetworkSymmsPrint( pNtk, pSymms ); } //Extra_SymmPairsPrint( pSymms ); Extra_SymmPairsDissolve( pSymms ); } printf( "Total number of vars in functional supports = %8d.\n", nSupps ); printf( "Total number of two-variable symmetries = %8d.\n", nSymms ); } /**Function************************************************************* Synopsis [Printing symmetry groups from the symmetry data structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ) { char ** pInputNames; int * pVarTaken; int i, k, nVars, nSize, fStart; // get variable names nVars = Abc_NtkCiNum(pNtk); pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); // alloc the array of marks pVarTaken = ABC_ALLOC( int, nVars ); memset( pVarTaken, 0, sizeof(int) * nVars ); // print the groups fStart = 1; nSize = pSymms->nVars; for ( i = 0; i < nSize; i++ ) { // skip the variable already considered if ( pVarTaken[i] ) continue; // find all the vars symmetric with this one for ( k = 0; k < nSize; k++ ) { if ( k == i ) continue; if ( pSymms->pSymms[i][k] == 0 ) continue; // vars i and k are symmetric assert( pVarTaken[k] == 0 ); // there is a new symmetry pair if ( fStart == 1 ) { // start a new symmetry class fStart = 0; printf( " { %s", pInputNames[ pSymms->pVars[i] ] ); // mark the var as taken pVarTaken[i] = 1; } printf( " %s", pInputNames[ pSymms->pVars[k] ] ); // mark the var as taken pVarTaken[k] = 1; } if ( fStart == 0 ) { printf( " }" ); fStart = 1; } } printf( "\n" ); ABC_FREE( pInputNames ); ABC_FREE( pVarTaken ); } #else void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ) {} #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcTim.c000066400000000000000000000476721300674244400232270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcTim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Testing hierarchy/timing manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcTim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/gia/giaAig.h" #include "misc/tim/tim.h" #include "opt/dar/dar.h" #include "proof/dch/dch.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define TIM_TEST_BOX_RATIO 200 // assume that every TIM_TEST_BOX_RATIO'th object is a white box static inline int Abc_NodeIsWhiteBox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return Abc_ObjId(pObj) % TIM_TEST_BOX_RATIO == 0 && Abc_ObjFaninNum(pObj) > 0 && Abc_ObjFaninNum(pObj) < 10; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives GIA for the output of the local function of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTestTimNodeStrash_rec( Gia_Man_t * pGia, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Abc_NtkTestTimNodeStrash_rec( pGia, Hop_ObjFanin0(pObj) ); Abc_NtkTestTimNodeStrash_rec( pGia, Hop_ObjFanin1(pObj) ); pObj->iData = Gia_ManHashAnd( pGia, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } int Abc_NtkTestTimNodeStrash( Gia_Man_t * pGia, Abc_Obj_t * pNode ) { Hop_Man_t * pMan; Hop_Obj_t * pRoot; Abc_Obj_t * pFanin; int i; assert( Abc_ObjIsNode(pNode) ); assert( Abc_NtkIsAigLogic(pNode->pNtk) ); // get the local AIG manager and the local root node pMan = (Hop_Man_t *)pNode->pNtk->pManFunc; pRoot = (Hop_Obj_t *)pNode->pData; // check the constant case if ( Abc_NodeIsConst(pNode) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) return !Hop_IsComplement(pRoot); // set elementary variables Abc_ObjForEachFanin( pNode, pFanin, i ) Hop_IthVar(pMan, i)->iData = pFanin->iTemp; // strash the AIG of this node Abc_NtkTestTimNodeStrash_rec( pGia, Hop_Regular(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); // return the final node with complement if needed return Abc_LitNotCond( Hop_Regular(pRoot)->iData, Hop_IsComplement(pRoot) ); } #if 0 /**Function************************************************************* Synopsis [Derives GIA manager using special pins to denote box boundaries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkTestPinDeriveGia( Abc_Ntk_t * pNtk, int fWhiteBoxOnly, int fVerbose ) { Gia_Man_t * pTemp; Gia_Man_t * pGia = NULL; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin; int i, k, iPinLit = 0; // prepare logic network assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkToAig( pNtk ); // construct GIA Abc_NtkFillTemp( pNtk ); pGia = Gia_ManStart( Abc_NtkObjNumMax(pNtk) ); Gia_ManHashAlloc( pGia ); // create primary inputs Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = Gia_ManAppendCi(pGia); // create internal nodes in a topologic order from white boxes vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // input side if ( !fWhiteBoxOnly || Abc_NodeIsWhiteBox(pObj) ) { // create special pintype for this node iPinLit = Gia_ManAppendPinType( pGia, 1 ); // create input pins Abc_ObjForEachFanin( pObj, pFanin, k ) pFanin->iTemp = Gia_ManAppendAnd( pGia, pFanin->iTemp, iPinLit ); } // perform GIA construction pObj->iTemp = Abc_NtkTestTimNodeStrash( pGia, pObj ); // output side if ( !fWhiteBoxOnly || Abc_NodeIsWhiteBox(pObj) ) { // create special pintype for this node iPinLit = Gia_ManAppendPinType( pGia, 1 ); // create output pins pObj->iTemp = Gia_ManAppendAnd( pGia, pObj->iTemp, iPinLit ); } } Vec_PtrFree( vNodes ); // create primary outputs Abc_NtkForEachCo( pNtk, pObj, i ) pObj->iTemp = Gia_ManAppendCo( pGia, Abc_ObjFanin0(pObj)->iTemp ); // finalize GIA Gia_ManHashStop( pGia ); Gia_ManSetRegNum( pGia, 0 ); // clean up GIA pGia = Gia_ManCleanup( pTemp = pGia ); Gia_ManStop( pTemp ); return pGia; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTestPinGia( Abc_Ntk_t * pNtk, int fWhiteBoxOnly, int fVerbose ) { Gia_Man_t * pGia; char * pFileName = "testpin.aig"; pGia = Abc_NtkTestPinDeriveGia( pNtk, fWhiteBoxOnly, fVerbose ); Gia_AigerWrite( pGia, pFileName, 0, 0 ); Gia_ManStop( pGia ); printf( "AIG with pins derived from mapped network \"%s\" was written into file \"%s\".\n", Abc_NtkName(pNtk), pFileName ); } #endif /**Function************************************************************* Synopsis [Collect nodes reachable from this box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTestTimCollectCone_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsCi(pObj) ) return; assert( Abc_ObjIsNode( pObj ) ); Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_NtkTestTimCollectCone_rec( pFanin, vNodes ); Vec_PtrPush( vNodes, pObj ); } Vec_Ptr_t * Abc_NtkTestTimCollectCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) { Vec_Ptr_t * vCone = Vec_PtrAlloc( 1000 ); if ( pObj != NULL ) { // collect for one node assert( Abc_ObjIsNode(pObj) ); assert( !Abc_NodeIsTravIdCurrent( pObj ) ); Abc_NtkTestTimCollectCone_rec( pObj, vCone ); // remove the node because it is a white box Vec_PtrPop( vCone ); } else { // collect for all COs Abc_Obj_t * pObj; int i; Abc_NtkForEachCo( pNtk, pObj, i ) Abc_NtkTestTimCollectCone_rec( Abc_ObjFanin0(pObj), vCone ); } return vCone; } /**Function************************************************************* Synopsis [Create arrival times] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Flt_t * Abc_NtkTestCreateArrivals( int nInputs ) { Vec_Flt_t * p; int i; p = Vec_FltAlloc( nInputs ); for ( i = 0; i < nInputs; i++ ) Vec_FltPush( p, 1.0*(i % 10) ); return p; } Vec_Flt_t * Abc_NtkTestCreateRequired( int nOutputs ) { Vec_Flt_t * p; int i; p = Vec_FltAlloc( nOutputs ); for ( i = 0; i < nOutputs; i++ ) Vec_FltPush( p, 100.0 + 1.0*i ); return p; } /**Function************************************************************* Synopsis [Derives GIA manager together with the hierachy manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkTestTimDeriveGia( Abc_Ntk_t * pNtk, int fVerbose ) { Gia_Man_t * pTemp; Gia_Man_t * pGia = NULL; Gia_Man_t * pHoles = NULL; Tim_Man_t * pTim = NULL; Vec_Int_t * vGiaCoLits, * vGiaCoLits2; Vec_Flt_t * vArrTimes, * vReqTimes; Abc_Obj_t * pObj, * pFanin; int i, k, Entry, curPi, curPo, BoxUniqueId; int nBoxFaninMax = 0; assert( Abc_NtkIsTopo(pNtk) ); Abc_NtkFillTemp( pNtk ); // create white boxes curPi = Abc_NtkCiNum(pNtk); curPo = Abc_NtkCoNum(pNtk); Abc_NtkForEachNode( pNtk, pObj, i ) { pObj->fMarkA = Abc_NodeIsWhiteBox( pObj ); if ( !pObj->fMarkA ) continue; nBoxFaninMax = Abc_MaxInt( nBoxFaninMax, Abc_ObjFaninNum(pObj) ); curPi++; curPo += Abc_ObjFaninNum(pObj); if ( fVerbose ) printf( "Selecting node %6d as white boxes with %d inputs and %d output.\n", i, Abc_ObjFaninNum(pObj), 1 ); } // construct GIA pGia = Gia_ManStart( Abc_NtkObjNumMax(pNtk) ); pHoles = Gia_ManStart( 1000 ); for ( i = 0; i < curPi; i++ ) Gia_ManAppendCi(pGia); for ( i = 0; i < nBoxFaninMax; i++ ) Gia_ManAppendCi(pHoles); Gia_ManHashAlloc( pGia ); Gia_ManHashAlloc( pHoles ); // construct the timing manager pTim = Tim_ManStart( curPi, curPo ); // assign primary inputs curPi = 0; curPo = 0; Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManCi(pGia, curPi++)), 0 ); // create internal nodes in a topologic order from white boxes vGiaCoLits = Vec_IntAlloc( 1000 ); vGiaCoLits2 = Vec_IntAlloc( 1000 ); Abc_NtkForEachNode( pNtk, pObj, i ) { if ( !pObj->fMarkA ) // not a white box { pObj->iTemp = Abc_NtkTestTimNodeStrash( pGia, pObj ); continue; } // create box BoxUniqueId = Abc_ObjFaninNum(pObj); // in this case, the node size is the ID of its delay table Tim_ManCreateBox( pTim, curPo, Abc_ObjFaninNum(pObj), curPi, 1, BoxUniqueId, 0 ); curPo += Abc_ObjFaninNum(pObj); // handle box inputs Abc_ObjForEachFanin( pObj, pFanin, k ) { // save CO drivers for the AIG Vec_IntPush( vGiaCoLits, pFanin->iTemp ); // load CI nodes for the Holes pFanin->iTemp = Abc_Var2Lit( Gia_ObjId(pHoles, Gia_ManCi(pHoles, k)), 0 ); } // handle logic of the box pObj->iTemp = Abc_NtkTestTimNodeStrash( pHoles, pObj ); // handle box outputs // save CO drivers for the Holes Vec_IntPush( vGiaCoLits2, pObj->iTemp ); // Gia_ManAppendCo( pHoles, pObj->iTemp ); // load CO drivers for the AIG pObj->iTemp = Abc_Var2Lit( Gia_ObjId(pGia, Gia_ManCi(pGia, curPi++)), 0 ); } Abc_NtkCleanMarkA( pNtk ); // create COs of the AIG Abc_NtkForEachCo( pNtk, pObj, i ) Gia_ManAppendCo( pGia, Abc_ObjFanin0(pObj)->iTemp ); Vec_IntForEachEntry( vGiaCoLits, Entry, i ) Gia_ManAppendCo( pGia, Entry ); Vec_IntFree( vGiaCoLits ); // second AIG Vec_IntForEachEntry( vGiaCoLits2, Entry, i ) Gia_ManAppendCo( pHoles, Entry ); Vec_IntFree( vGiaCoLits2 ); // check parameters curPo += Abc_NtkPoNum( pNtk ); assert( curPi == Gia_ManPiNum(pGia) ); assert( curPo == Gia_ManPoNum(pGia) ); // finalize GIA Gia_ManHashStop( pGia ); Gia_ManSetRegNum( pGia, 0 ); Gia_ManHashStop( pHoles ); Gia_ManSetRegNum( pHoles, 0 ); // clean up GIA pGia = Gia_ManCleanup( pTemp = pGia ); Gia_ManStop( pTemp ); pHoles = Gia_ManCleanup( pTemp = pHoles ); Gia_ManStop( pTemp ); // attach the timing manager assert( pGia->pManTime == NULL ); pGia->pManTime = pTim; // derive hierarchy manager from box info and input/output arrival/required info vArrTimes = Abc_NtkTestCreateArrivals( Abc_NtkPiNum(pNtk) ); vReqTimes = Abc_NtkTestCreateRequired( Abc_NtkPoNum(pNtk) ); Tim_ManPrint( (Tim_Man_t *)pGia->pManTime ); Tim_ManCreate( (Tim_Man_t *)pGia->pManTime, Abc_FrameReadLibBox(), vArrTimes, vReqTimes ); Tim_ManPrint( (Tim_Man_t *)pGia->pManTime ); Vec_FltFree( vArrTimes ); Vec_FltFree( vReqTimes ); Gia_AigerWrite( pHoles, "holes00.aig", 0, 0 ); // return pGia->pAigExtra = pHoles; return pGia; } /**Function************************************************************* Synopsis [Performs synthesis with or without structural choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkTestTimPerformSynthesis( Gia_Man_t * p, int fChoices ) { Gia_Man_t * pGia; Aig_Man_t * pNew, * pTemp; Dch_Pars_t Pars, * pPars = &Pars; Dch_ManSetDefaultParams( pPars ); pNew = Gia_ManToAig( p, 0 ); if ( fChoices ) pNew = Dar_ManChoiceNew( pNew, pPars ); else { pNew = Dar_ManCompress2( pTemp = pNew, 1, 1, 1, 0, 0 ); Aig_ManStop( pTemp ); } pGia = Gia_ManFromAig( pNew ); Aig_ManStop( pNew ); return pGia; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManVerifyChoices( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, iRepr, iNode, fProb = 0; assert( p->pReprs ); // mark nodes Gia_ManCleanMark0(p); Gia_ManForEachClass( p, iRepr ) Gia_ClassForEachObj1( p, iRepr, iNode ) { if ( Gia_ObjIsHead(p, iNode) ) printf( "Member %d of choice class %d is a representative.\n", iNode, iRepr ), fProb = 1; if ( Gia_ManObj( p, iNode )->fMark0 == 1 ) printf( "Node %d participates in more than one choice node.\n", iNode ), fProb = 1; Gia_ManObj( p, iNode )->fMark0 = 1; } Gia_ManCleanMark0(p); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjHasRepr(p, Gia_ObjFaninId0(pObj, i)) ) printf( "Fanin 0 of AND node %d has a repr.\n", i ), fProb = 1; if ( Gia_ObjHasRepr(p, Gia_ObjFaninId1(pObj, i)) ) printf( "Fanin 1 of AND node %d has a repr.\n", i ), fProb = 1; } else if ( Gia_ObjIsCo(pObj) ) { if ( Gia_ObjHasRepr(p, Gia_ObjFaninId0(pObj, i)) ) printf( "Fanin 0 of CO node %d has a repr.\n", i ), fProb = 1; } } // if ( !fProb ) // printf( "GIA with choices is correct.\n" ); } /**Function************************************************************* Synopsis [Reverse the order of nodes in equiv classes.] Description [If the flag is 1, assumed current increasing order ] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManReverseClasses( Gia_Man_t * p, int fNowIncreasing ) { Vec_Int_t * vCollected; Vec_Int_t * vClass; int i, k, iRepr, iNode, iPrev; // collect classes vCollected = Vec_IntAlloc( 100 ); Gia_ManForEachClass( p, iRepr ) Vec_IntPush( vCollected, iRepr ); // correct each class vClass = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vCollected, iRepr, i ) { Vec_IntClear( vClass ); Vec_IntPush( vClass, iRepr ); Gia_ClassForEachObj1( p, iRepr, iNode ) { if ( fNowIncreasing ) assert( iRepr < iNode ); else assert( iRepr > iNode ); Vec_IntPush( vClass, iNode ); } // if ( !fNowIncreasing ) // Vec_IntSort( vClass, 1 ); // reverse the class iPrev = 0; iRepr = Vec_IntEntryLast( vClass ); Vec_IntForEachEntry( vClass, iNode, k ) { if ( fNowIncreasing ) Gia_ObjSetReprRev( p, iNode, iNode == iRepr ? GIA_VOID : iRepr ); else Gia_ObjSetRepr( p, iNode, iNode == iRepr ? GIA_VOID : iRepr ); Gia_ObjSetNext( p, iNode, iPrev ); iPrev = iNode; } } Vec_IntFree( vCollected ); Vec_IntFree( vClass ); // verify Gia_ManForEachClass( p, iRepr ) Gia_ClassForEachObj1( p, iRepr, iNode ) if ( fNowIncreasing ) assert( Gia_ObjRepr(p, iNode) == iRepr && iRepr > iNode ); else assert( Gia_ObjRepr(p, iNode) == iRepr && iRepr < iNode ); } /**Function************************************************************* Synopsis [Tests the hierarchy-timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTestTimByWritingFile( Gia_Man_t * pGia, char * pFileName ) { Gia_Man_t * pGia2; // normalize choices if ( Gia_ManHasChoices(pGia) ) { Gia_ManVerifyChoices( pGia ); Gia_ManReverseClasses( pGia, 0 ); } // write file Gia_AigerWrite( pGia, pFileName, 0, 0 ); // unnormalize choices if ( Gia_ManHasChoices(pGia) ) Gia_ManReverseClasses( pGia, 1 ); // read file pGia2 = Gia_AigerRead( pFileName, 0, 1, 1 ); // normalize choices if ( Gia_ManHasChoices(pGia2) ) { Gia_ManVerifyChoices( pGia2 ); Gia_ManReverseClasses( pGia2, 1 ); } // compare resulting managers if ( Gia_ManCompare( pGia, pGia2 ) ) printf( "Verification suceessful.\n" ); Gia_ManStop( pGia2 ); } /**Function************************************************************* Synopsis [Tests construction and serialization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTestTim( Abc_Ntk_t * pNtk, int fVerbose ) { int fUseChoices = 0; Gia_Man_t * pGia, * pTemp; // this test only works for a logic network (for example, network with LUT mapping) assert( Abc_NtkIsLogic(pNtk) ); // make sure local functions of the nodes are in the AIG form Abc_NtkToAig( pNtk ); // create GIA manager (pGia) with hierarhy/timing manager attached (pGia->pManTime) // while assuming that some nodes are white boxes (see Abc_NodeIsWhiteBox) pGia = Abc_NtkTestTimDeriveGia( pNtk, fVerbose ); printf( "Created GIA manager for network with %d white boxes.\n", Tim_ManBoxNum((Tim_Man_t *)pGia->pManTime) ); // print the timing manager if ( fVerbose ) Tim_ManPrint( (Tim_Man_t *)pGia->pManTime ); // test writing both managers into a file and reading them back Abc_NtkTestTimByWritingFile( pGia, "test1.aig" ); // perform synthesis pGia = Abc_NtkTestTimPerformSynthesis( pTemp = pGia, fUseChoices ); Gia_ManStop( pTemp ); // test writing both managers into a file and reading them back Abc_NtkTestTimByWritingFile( pGia, "test2.aig" ); Gia_ManStop( pGia ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcTiming.c000066400000000000000000001336251300674244400237170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcTiming.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Computation of timing info for mapped circuits.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "base/abc/abc.h" #include "base/main/main.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Abc_ManTime_t_ { Abc_Time_t tArrDef; Abc_Time_t tReqDef; Vec_Ptr_t * vArrs; Vec_Ptr_t * vReqs; Abc_Time_t tInDriveDef; Abc_Time_t tOutLoadDef; Abc_Time_t * tInDrive; Abc_Time_t * tOutLoad; }; #define TOLERANCE 0.001 static inline int Abc_FloatEqual( float x, float y ) { return fabs(x-y) < TOLERANCE; } // static functions static Abc_ManTime_t * Abc_ManTimeStart( Abc_Ntk_t * pNtk ); static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ); // accessing the arrival and required times of a node static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return (Abc_Time_t *)pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; } static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return (Abc_Time_t *)pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the arrival.required time of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ) { assert( pNtk->pManTime ); return &pNtk->pManTime->tArrDef; } Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ) { assert( pNtk->pManTime ); return &pNtk->pManTime->tReqDef; } Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ) { assert( pNode->pNtk->pManTime ); return Abc_NodeArrival(pNode); } Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ) { assert( pNode->pNtk->pManTime ); return Abc_NodeRequired(pNode); } float Abc_NtkReadDefaultArrivalWorst( Abc_Ntk_t * pNtk ) { return 0.5 * pNtk->pManTime->tArrDef.Rise + 0.5 * pNtk->pManTime->tArrDef.Fall; } float Abc_NtkReadDefaultRequiredWorst( Abc_Ntk_t * pNtk ) { return 0.5 * pNtk->pManTime->tReqDef.Rise + 0.5 * pNtk->pManTime->tReqDef.Fall; } float Abc_NodeReadArrivalAve( Abc_Obj_t * pNode ) { return 0.5 * Abc_NodeArrival(pNode)->Rise + 0.5 * Abc_NodeArrival(pNode)->Fall; } float Abc_NodeReadRequiredAve( Abc_Obj_t * pNode ) { return 0.5 * Abc_NodeReadRequired(pNode)->Rise + 0.5 * Abc_NodeReadRequired(pNode)->Fall; } float Abc_NodeReadArrivalWorst( Abc_Obj_t * pNode ) { return Abc_MaxFloat( Abc_NodeArrival(pNode)->Rise, Abc_NodeArrival(pNode)->Fall ); } float Abc_NodeReadRequiredWorst( Abc_Obj_t * pNode ) { return Abc_MinFloat( Abc_NodeReadRequired(pNode)->Rise, Abc_NodeReadRequired(pNode)->Fall ); } /**Function************************************************************* Synopsis [Reads the input drive / output load of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Time_t * Abc_NtkReadDefaultInputDrive( Abc_Ntk_t * pNtk ) { assert( pNtk->pManTime ); return &pNtk->pManTime->tInDriveDef; } Abc_Time_t * Abc_NtkReadDefaultOutputLoad( Abc_Ntk_t * pNtk ) { assert( pNtk->pManTime ); return &pNtk->pManTime->tOutLoadDef; } Abc_Time_t * Abc_NodeReadInputDrive( Abc_Ntk_t * pNtk, int iPi ) { assert( pNtk->pManTime ); return pNtk->pManTime->tInDrive ? pNtk->pManTime->tInDrive + iPi : NULL; } Abc_Time_t * Abc_NodeReadOutputLoad( Abc_Ntk_t * pNtk, int iPo ) { assert( pNtk->pManTime ); return pNtk->pManTime->tOutLoad ? pNtk->pManTime->tOutLoad + iPo : NULL; } float Abc_NodeReadInputDriveWorst( Abc_Ntk_t * pNtk, int iPi ) { return Abc_MaxFloat( Abc_NodeReadInputDrive(pNtk, iPi)->Rise, Abc_NodeReadInputDrive(pNtk, iPi)->Fall ); } float Abc_NodeReadOutputLoadWorst( Abc_Ntk_t * pNtk, int iPo ) { return Abc_MaxFloat( Abc_NodeReadOutputLoad(pNtk, iPo)->Rise, Abc_NodeReadOutputLoad(pNtk, iPo)->Fall ); } /**Function************************************************************* Synopsis [Sets the default arrival time for the network.] Description [Please note that .default_input_arrival and .default_output_required should precede .input_arrival and .output required. Otherwise, an overwrite may happen.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ) { Abc_Obj_t * pObj; int i; if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); pNtk->pManTime->tArrDef.Rise = Rise; pNtk->pManTime->tArrDef.Fall = Fall; // set the arrival times for each input Abc_NtkForEachCi( pNtk, pObj, i ) Abc_NtkTimeSetArrival( pNtk, Abc_ObjId(pObj), Rise, Fall ); } void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ) { Abc_Obj_t * pObj; int i; if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); pNtk->pManTime->tReqDef.Rise = Rise; pNtk->pManTime->tReqDef.Fall = Fall; // set the required times for each output Abc_NtkForEachCo( pNtk, pObj, i ) Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pObj), Rise, Fall ); } /**Function************************************************************* Synopsis [Sets the arrival time for an object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) { Vec_Ptr_t * vTimes; Abc_Time_t * pTime; if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); // set the arrival time vTimes = pNtk->pManTime->vArrs; pTime = (Abc_Time_t *)vTimes->pArray[ObjId]; pTime->Rise = Rise; pTime->Fall = Fall; } void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) { Vec_Ptr_t * vTimes; Abc_Time_t * pTime; if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); // set the required time vTimes = pNtk->pManTime->vReqs; pTime = (Abc_Time_t *)vTimes->pArray[ObjId]; pTime->Rise = Rise; pTime->Fall = Fall; } /**Function************************************************************* Synopsis [Sets the default arrival time for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTimeSetDefaultInputDrive( Abc_Ntk_t * pNtk, float Rise, float Fall ) { // if ( Rise == 0.0 && Fall == 0.0 ) // return; if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); pNtk->pManTime->tInDriveDef.Rise = Rise; pNtk->pManTime->tInDriveDef.Fall = Fall; if ( pNtk->pManTime->tInDrive != NULL ) { int i; for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ ) if ( pNtk->pManTime->tInDrive[i].Rise == 0 && pNtk->pManTime->tInDrive[i].Fall == 0 ) pNtk->pManTime->tInDrive[i] = pNtk->pManTime->tInDriveDef; } } void Abc_NtkTimeSetDefaultOutputLoad( Abc_Ntk_t * pNtk, float Rise, float Fall ) { // if ( Rise == 0.0 && Fall == 0.0 ) // return; if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); pNtk->pManTime->tOutLoadDef.Rise = Rise; pNtk->pManTime->tOutLoadDef.Fall = Fall; if ( pNtk->pManTime->tOutLoad != NULL ) { int i; for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) if ( pNtk->pManTime->tOutLoad[i].Rise == 0 && pNtk->pManTime->tOutLoad[i].Fall == 0 ) pNtk->pManTime->tOutLoad[i] = pNtk->pManTime->tOutLoadDef; } } /**Function************************************************************* Synopsis [Sets the arrival time for an object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTimeSetInputDrive( Abc_Ntk_t * pNtk, int PiNum, float Rise, float Fall ) { Abc_Time_t * pTime; assert( PiNum >= 0 && PiNum < Abc_NtkCiNum(pNtk) ); if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); if ( pNtk->pManTime->tInDriveDef.Rise == Rise && pNtk->pManTime->tInDriveDef.Fall == Fall ) return; if ( pNtk->pManTime->tInDrive == NULL ) { int i; pNtk->pManTime->tInDrive = ABC_CALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) ); for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ ) pNtk->pManTime->tInDrive[i] = pNtk->pManTime->tInDriveDef; } pTime = pNtk->pManTime->tInDrive + PiNum; pTime->Rise = Rise; pTime->Fall = Fall; } void Abc_NtkTimeSetOutputLoad( Abc_Ntk_t * pNtk, int PoNum, float Rise, float Fall ) { Abc_Time_t * pTime; assert( PoNum >= 0 && PoNum < Abc_NtkCoNum(pNtk) ); if ( pNtk->pManTime == NULL ) pNtk->pManTime = Abc_ManTimeStart(pNtk); if ( pNtk->pManTime->tOutLoadDef.Rise == Rise && pNtk->pManTime->tOutLoadDef.Fall == Fall ) return; if ( pNtk->pManTime->tOutLoad == NULL ) { int i; pNtk->pManTime->tOutLoad = ABC_CALLOC( Abc_Time_t, Abc_NtkCoNum(pNtk) ); for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) pNtk->pManTime->tOutLoad[i] = pNtk->pManTime->tOutLoadDef; } pTime = pNtk->pManTime->tOutLoad + PoNum; pTime->Rise = Rise; pTime->Fall = Fall; } /**Function************************************************************* Synopsis [Finalizes the timing manager after setting arr/req times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkOld ) { Abc_Obj_t * pObj; Abc_Time_t ** ppTimes; int i; assert( pNtkOld == NULL || pNtkOld->pManTime != NULL ); assert( pNtkOld == NULL || Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkOld) ); assert( pNtkOld == NULL || Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkOld) ); if ( pNtk->pManTime == NULL ) return; // create timing manager with default values Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); // set global defaults from pNtkOld if ( pNtkOld ) { pNtk->pManTime->tArrDef = pNtkOld->pManTime->tArrDef; pNtk->pManTime->tReqDef = pNtkOld->pManTime->tReqDef; pNtk->AndGateDelay = pNtkOld->AndGateDelay; } // set the default timing for CI and COs ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; Abc_NtkForEachCi( pNtk, pObj, i ) *ppTimes[pObj->Id] = pNtkOld ? *Abc_NodeReadArrival(Abc_NtkCi(pNtkOld, i)) : pNtk->pManTime->tArrDef; ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray; Abc_NtkForEachCo( pNtk, pObj, i ) *ppTimes[pObj->Id] = pNtkOld ? *Abc_NodeReadRequired(Abc_NtkCo(pNtkOld, i)) : pNtk->pManTime->tReqDef; } /**Function************************************************************* Synopsis [This procedure scales user timing by multiplicative factor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTimeScale( Abc_Ntk_t * pNtk, float Scale ) { Abc_Obj_t * pObj; Abc_Time_t ** ppTimes, * pTime; int i; if ( pNtk->pManTime == NULL ) return; // arrival pNtk->pManTime->tArrDef.Fall *= Scale; pNtk->pManTime->tArrDef.Rise *= Scale; // departure pNtk->pManTime->tReqDef.Fall *= Scale; pNtk->pManTime->tReqDef.Rise *= Scale; // set the default timing ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; Abc_NtkForEachCi( pNtk, pObj, i ) { pTime = ppTimes[pObj->Id]; pTime->Fall *= Scale; pTime->Rise *= Scale; } // set the default timing ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray; Abc_NtkForEachCo( pNtk, pObj, i ) { pTime = ppTimes[pObj->Id]; pTime->Fall *= Scale; pTime->Rise *= Scale; } } /**Function************************************************************* Synopsis [Prepares the timing manager for delay trace.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; Abc_Time_t ** ppTimes, * pTime; int i; // if there is no timing manager, allocate and initialize if ( pNtk->pManTime == NULL ) { pNtk->pManTime = Abc_ManTimeStart(pNtk); Abc_NtkTimeInitialize( pNtk, NULL ); return; } // if timing manager is given, expand it if necessary Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); // clean arrivals except for PIs ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; Abc_NtkForEachNode( pNtk, pObj, i ) { pTime = ppTimes[pObj->Id]; pTime->Fall = pTime->Rise = Abc_ObjFaninNum(pObj) ? -ABC_INFINITY : 0; // set contant node arrivals to zero } Abc_NtkForEachCo( pNtk, pObj, i ) { pTime = ppTimes[pObj->Id]; pTime->Fall = pTime->Rise = -ABC_INFINITY; } // clean required except for POs ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray; Abc_NtkForEachNode( pNtk, pObj, i ) { pTime = ppTimes[pObj->Id]; pTime->Fall = pTime->Rise = ABC_INFINITY; } Abc_NtkForEachCi( pNtk, pObj, i ) { pTime = ppTimes[pObj->Id]; pTime->Fall = pTime->Rise = ABC_INFINITY; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ManTime_t * Abc_ManTimeStart( Abc_Ntk_t * pNtk ) { int fUseZeroDefaultOutputRequired = 1; Abc_ManTime_t * p; Abc_Obj_t * pObj; int i; p = pNtk->pManTime = ABC_ALLOC( Abc_ManTime_t, 1 ); memset( p, 0, sizeof(Abc_ManTime_t) ); p->vArrs = Vec_PtrAlloc( 0 ); p->vReqs = Vec_PtrAlloc( 0 ); // set default default input=arrivals (assumed to be 0) // set default default output-requireds (can be either 0 or +infinity, based on the flag) p->tReqDef.Rise = fUseZeroDefaultOutputRequired ? 0 : ABC_INFINITY; p->tReqDef.Fall = fUseZeroDefaultOutputRequired ? 0 : ABC_INFINITY; // extend manager Abc_ManTimeExpand( p, Abc_NtkObjNumMax(pNtk) + 1, 0 ); // set the default timing for CIs Abc_NtkForEachCi( pNtk, pObj, i ) Abc_NtkTimeSetArrival( pNtk, Abc_ObjId(pObj), p->tArrDef.Rise, p->tArrDef.Rise ); // set the default timing for COs Abc_NtkForEachCo( pNtk, pObj, i ) Abc_NtkTimeSetRequired( pNtk, Abc_ObjId(pObj), p->tReqDef.Rise, p->tReqDef.Rise ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManTimeStop( Abc_ManTime_t * p ) { if ( p->tInDrive ) ABC_FREE( p->tInDrive ); if ( p->tOutLoad ) ABC_FREE( p->tOutLoad ); if ( Vec_PtrSize(p->vArrs) > 0 ) ABC_FREE( p->vArrs->pArray[0] ); Vec_PtrFree( p->vArrs ); if ( Vec_PtrSize(p->vReqs) > 0 ) ABC_FREE( p->vReqs->pArray[0] ); Vec_PtrFree( p->vReqs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Duplicates the timing manager with the PI/PO timing info.] Description [The PIs/POs of the new network should be allocated.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) { extern void Abc_NtkTimePrint( Abc_Ntk_t * pNtk ); Abc_Obj_t * pObj; Abc_Time_t ** ppTimesOld, ** ppTimesNew; int i; if ( pNtkOld->pManTime == NULL ) return; assert( Abc_NtkCiNum(pNtkOld) == Abc_NtkCiNum(pNtkNew) ); assert( Abc_NtkCoNum(pNtkOld) == Abc_NtkCoNum(pNtkNew) ); assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) ); // create the new timing manager pNtkNew->pManTime = Abc_ManTimeStart(pNtkNew); Abc_ManTimeExpand( pNtkNew->pManTime, Abc_NtkObjNumMax(pNtkNew), 0 ); // set the default timing pNtkNew->pManTime->tArrDef = pNtkOld->pManTime->tArrDef; pNtkNew->pManTime->tReqDef = pNtkOld->pManTime->tReqDef; // set the CI timing ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vArrs->pArray; ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vArrs->pArray; Abc_NtkForEachCi( pNtkOld, pObj, i ) *ppTimesNew[ Abc_NtkCi(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; // set the CO timing ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vReqs->pArray; ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vReqs->pArray; Abc_NtkForEachCo( pNtkOld, pObj, i ) *ppTimesNew[ Abc_NtkCo(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; // duplicate input drive pNtkNew->pManTime->tInDriveDef = pNtkOld->pManTime->tInDriveDef; pNtkNew->pManTime->tOutLoadDef = pNtkOld->pManTime->tOutLoadDef; if ( pNtkOld->pManTime->tInDrive ) { pNtkNew->pManTime->tInDrive = ABC_ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtkOld) ); memcpy( pNtkNew->pManTime->tInDrive, pNtkOld->pManTime->tInDrive, sizeof(Abc_Time_t) * Abc_NtkCiNum(pNtkOld) ); } if ( pNtkOld->pManTime->tOutLoad ) { pNtkNew->pManTime->tOutLoad = ABC_ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtkOld) ); memcpy( pNtkNew->pManTime->tOutLoad, pNtkOld->pManTime->tOutLoad, sizeof(Abc_Time_t) * Abc_NtkCoNum(pNtkOld) ); } } /**Function************************************************************* Synopsis [Prints out the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTimePrint( Abc_Ntk_t * pNtk ) { if ( pNtk->pManTime == NULL ) printf( "There is no timing manager\n" ); else { Abc_Obj_t * pObj; int i; printf( "Default arrival = %8f\n", pNtk->pManTime->tArrDef.Fall ); printf( "Default required = %8f\n", pNtk->pManTime->tReqDef.Fall ); printf( "Inputs (%d):\n", Abc_NtkCiNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) printf( "%20s arrival = %8f required = %8f\n", Abc_ObjName(pObj), Abc_NodeReadArrivalWorst(pObj), Abc_NodeReadRequiredWorst(pObj) ); printf( "Outputs (%d):\n", Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) printf( "%20s arrival = %8f required = %8f\n", Abc_ObjName(pObj), Abc_NodeReadArrivalWorst(pObj), Abc_NodeReadRequiredWorst(pObj) ); } } /**Function************************************************************* Synopsis [Expends the storage for timing information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ) { Vec_Ptr_t * vTimes; Abc_Time_t * ppTimes, * ppTimesOld, * pTime; int nSizeOld, nSizeNew, i; nSizeOld = p->vArrs->nSize; if ( nSizeOld >= nSize ) return; nSizeNew = fProgressive? 2 * nSize : nSize; if ( nSizeNew < 100 ) nSizeNew = 100; vTimes = p->vArrs; Vec_PtrGrow( vTimes, nSizeNew ); vTimes->nSize = nSizeNew; ppTimesOld = ( nSizeOld == 0 )? NULL : (Abc_Time_t *)vTimes->pArray[0]; ppTimes = ABC_REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); for ( i = 0; i < nSizeNew; i++ ) vTimes->pArray[i] = ppTimes + i; for ( i = nSizeOld; i < nSizeNew; i++ ) { pTime = (Abc_Time_t *)vTimes->pArray[i]; pTime->Rise = -ABC_INFINITY; pTime->Fall = -ABC_INFINITY; } vTimes = p->vReqs; Vec_PtrGrow( vTimes, nSizeNew ); vTimes->nSize = nSizeNew; ppTimesOld = ( nSizeOld == 0 )? NULL : (Abc_Time_t *)vTimes->pArray[0]; ppTimes = ABC_REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); for ( i = 0; i < nSizeNew; i++ ) vTimes->pArray[i] = ppTimes + i; for ( i = nSizeOld; i < nSizeNew; i++ ) { pTime = (Abc_Time_t *)vTimes->pArray[i]; pTime->Rise = ABC_INFINITY; pTime->Fall = ABC_INFINITY; } } /**Function************************************************************* Synopsis [Sets the CI node levels according to the arrival info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld ) { Abc_Obj_t * pNodeOld, * pNodeNew; float tAndDelay; int i; if ( pNtkOld->pManTime == NULL ) return; if ( Abc_FrameReadLibGen() == NULL || Mio_LibraryReadNand2((Mio_Library_t *)Abc_FrameReadLibGen()) == NULL ) return; tAndDelay = Mio_LibraryReadDelayNand2Max((Mio_Library_t *)Abc_FrameReadLibGen()); Abc_NtkForEachCi( pNtkOld, pNodeOld, i ) { pNodeNew = pNodeOld->pCopy; pNodeNew->Level = (int)(Abc_NodeReadArrivalWorst(pNodeOld) / tAndDelay); } } /**Function************************************************************* Synopsis [Sets the CI node levels according to the arrival info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ) { Abc_Time_t * p; Abc_Obj_t * pNode; int i; p = ABC_CALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) ); if ( pNtk->pManTime == NULL ) return p; // set the PI arrival times Abc_NtkForEachCi( pNtk, pNode, i ) p[i] = *Abc_NodeArrival(pNode); return p; } Abc_Time_t * Abc_NtkGetCoRequiredTimes( Abc_Ntk_t * pNtk ) { Abc_Time_t * p; Abc_Obj_t * pNode; int i; p = ABC_CALLOC( Abc_Time_t, Abc_NtkCoNum(pNtk) ); if ( pNtk->pManTime == NULL ) return p; // set the PO required times Abc_NtkForEachCo( pNtk, pNode, i ) p[i] = *Abc_NodeRequired(pNode); return p; } /**Function************************************************************* Synopsis [Sets the CI node levels according to the arrival info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ) { float * p; Abc_Obj_t * pNode; int i; p = ABC_CALLOC( float, Abc_NtkCiNum(pNtk) ); if ( pNtk->pManTime == NULL ) return p; // set the PI arrival times Abc_NtkForEachCi( pNtk, pNode, i ) p[i] = Abc_NodeReadArrivalWorst(pNode); return p; } float * Abc_NtkGetCoRequiredFloats( Abc_Ntk_t * pNtk ) { float * p; Abc_Obj_t * pNode; int i; if ( pNtk->pManTime == NULL ) return NULL; // set the PO required times p = ABC_CALLOC( float, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) p[i] = Abc_NodeReadRequiredWorst(pNode); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkDelayTraceSlackStart( Abc_Ntk_t * pNtk ) { Vec_Int_t * vSlacks; Abc_Obj_t * pObj; int i, k; vSlacks = Vec_IntAlloc( Abc_NtkObjNumMax(pNtk) + Abc_NtkGetTotalFanins(pNtk) ); Vec_IntFill( vSlacks, Abc_NtkObjNumMax(pNtk), -1 ); Abc_NtkForEachNode( pNtk, pObj, i ) { Vec_IntWriteEntry( vSlacks, i, Vec_IntSize(vSlacks) ); for ( k = 0; k < Abc_ObjFaninNum(pObj); k++ ) Vec_IntPush( vSlacks, -1 ); } // assert( Abc_MaxInt(16, Vec_IntSize(vSlacks)) == Vec_IntCap(vSlacks) ); return vSlacks; } /**Function************************************************************* Synopsis [Read/write edge slacks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Abc_NtkDelayTraceSlack( Vec_Int_t * vSlacks, Abc_Obj_t * pObj, int iFanin ) { return Abc_Int2Float( Vec_IntEntry( vSlacks, Vec_IntEntry(vSlacks, Abc_ObjId(pObj)) + iFanin ) ); } static inline void Abc_NtkDelayTraceSetSlack( Vec_Int_t * vSlacks, Abc_Obj_t * pObj, int iFanin, float Num ) { Vec_IntWriteEntry( vSlacks, Vec_IntEntry(vSlacks, Abc_ObjId(pObj)) + iFanin, Abc_Float2Int(Num) ); } /**Function************************************************************* Synopsis [Find most-critical path (the path with smallest slacks).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDelayTraceCritPath_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNode, Abc_Obj_t * pLeaf, Vec_Int_t * vBest ) { Abc_Obj_t * pFanin, * pFaninBest = NULL; float SlackMin = ABC_INFINITY; int i; // check primary inputs if ( Abc_ObjIsCi(pNode) ) return (pLeaf == NULL || pLeaf == pNode); assert( Abc_ObjIsNode(pNode) ); // check visited if ( Abc_NodeIsTravIdCurrent( pNode ) ) return Vec_IntEntry(vBest, Abc_ObjId(pNode)) >= 0; Abc_NodeSetTravIdCurrent( pNode ); // check the node assert( Abc_ObjIsNode(pNode) ); Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( !Abc_NtkDelayTraceCritPath_rec( vSlacks, pFanin, pLeaf, vBest ) ) continue; if ( pFaninBest == NULL || SlackMin > Abc_NtkDelayTraceSlack(vSlacks, pNode, i) ) { pFaninBest = pFanin; SlackMin = Abc_NtkDelayTraceSlack(vSlacks, pNode, i); } } if ( pFaninBest != NULL ) Vec_IntWriteEntry( vBest, Abc_ObjId(pNode), Abc_NodeFindFanin(pNode, pFaninBest) ); return (pFaninBest != NULL); } /**Function************************************************************* Synopsis [Find most-critical path (the path with smallest slacks).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDelayTraceCritPathCollect_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNode, Vec_Int_t * vBest, Vec_Ptr_t * vPath ) { assert( Abc_ObjIsCi(pNode) || Abc_ObjIsNode(pNode) ); if ( Abc_ObjIsNode(pNode) ) { int iFanin = Vec_IntEntry( vBest, Abc_ObjId(pNode) ); assert( iFanin >= 0 ); Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin(pNode, iFanin), vBest, vPath ); } Vec_PtrPush( vPath, pNode ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks ) { Abc_Obj_t * pFanin; Abc_Time_t * pTimeIn, * pTimeOut; float tDelayBlockRise, tDelayBlockFall; Mio_PinPhase_t PinPhase; Mio_Pin_t * pPin; int i; // start the arrival time of the node pTimeOut = Abc_NodeArrival(pNode); pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY; // consider the buffer if ( Abc_ObjIsBarBuf(pNode) ) { pTimeIn = Abc_NodeArrival(Abc_ObjFanin0(pNode)); *pTimeOut = *pTimeIn; return; } // go through the pins of the gate pPin = Mio_GateReadPins((Mio_Gate_t *)pNode->pData); Abc_ObjForEachFanin( pNode, pFanin, i ) { pTimeIn = Abc_NodeArrival(pFanin); // get the interesting parameters of this pin PinPhase = Mio_PinReadPhase(pPin); tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); // compute the arrival times of the positive phase if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present { if ( pTimeOut->Rise < pTimeIn->Rise + tDelayBlockRise ) pTimeOut->Rise = pTimeIn->Rise + tDelayBlockRise; if ( pTimeOut->Fall < pTimeIn->Fall + tDelayBlockFall ) pTimeOut->Fall = pTimeIn->Fall + tDelayBlockFall; } if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present { if ( pTimeOut->Rise < pTimeIn->Fall + tDelayBlockRise ) pTimeOut->Rise = pTimeIn->Fall + tDelayBlockRise; if ( pTimeOut->Fall < pTimeIn->Rise + tDelayBlockFall ) pTimeOut->Fall = pTimeIn->Rise + tDelayBlockFall; } pPin = Mio_PinReadNext(pPin); } // compute edge slacks if ( vSlacks ) { float Slack; // go through the pins of the gate pPin = Mio_GateReadPins((Mio_Gate_t *)pNode->pData); Abc_ObjForEachFanin( pNode, pFanin, i ) { pTimeIn = Abc_NodeArrival(pFanin); // get the interesting parameters of this pin PinPhase = Mio_PinReadPhase(pPin); tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); // compute the arrival times of the positive phase Slack = ABC_INFINITY; if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present { Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Rise + tDelayBlockRise - pTimeOut->Rise) ); Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Fall + tDelayBlockFall - pTimeOut->Fall) ); } if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present { Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Fall + tDelayBlockRise - pTimeOut->Rise) ); Slack = Abc_MinFloat( Slack, Abc_AbsFloat(pTimeIn->Rise + tDelayBlockFall - pTimeOut->Fall) ); } pPin = Mio_PinReadNext(pPin); Abc_NtkDelayTraceSetSlack( vSlacks, pNode, i, Slack ); } } } /**Function************************************************************* Synopsis [Performs delay-trace of the network. If input (pIn) or output (pOut) are given, finds the most-timing-critical path between them and prints it to the standard output. If input and/or output are not given, finds the most-critical path in the network and prints it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, int fPrint ) { Vec_Int_t * vSlacks = NULL; Abc_Obj_t * pNode, * pDriver; Vec_Ptr_t * vNodes; Abc_Time_t * pTime; float tArrivalMax; int i; assert( Abc_NtkIsMappedLogic(pNtk) ); assert( pOut == NULL || Abc_ObjIsCo(pOut) ); assert( pIn == NULL || Abc_ObjIsCi(pIn) ); // create slacks (need slacks if printing is requested even if pIn/pOut are not given) if ( pOut || pIn || fPrint ) vSlacks = Abc_NtkDelayTraceSlackStart( pNtk ); // compute the timing Abc_NtkTimePrepare( pNtk ); vNodes = Abc_NtkDfs( pNtk, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) Abc_NodeDelayTraceArrival( pNode, vSlacks ); Vec_PtrFree( vNodes ); // get the latest arrival times tArrivalMax = -ABC_INFINITY; Abc_NtkForEachCo( pNtk, pNode, i ) { pDriver = Abc_ObjFanin0(pNode); pTime = Abc_NodeArrival(pDriver); if ( tArrivalMax < Abc_MaxFloat(pTime->Fall, pTime->Rise) ) tArrivalMax = Abc_MaxFloat(pTime->Fall, pTime->Rise); } // determine the output to print if ( fPrint && pOut == NULL ) { Abc_NtkForEachCo( pNtk, pNode, i ) { pDriver = Abc_ObjFanin0(pNode); pTime = Abc_NodeArrival(pDriver); if ( tArrivalMax == Abc_MaxFloat(pTime->Fall, pTime->Rise) ) pOut = pNode; } assert( pOut != NULL ); } if ( fPrint ) { Vec_Ptr_t * vPath = Vec_PtrAlloc( 100 ); Vec_Int_t * vBest = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) ); // traverse to determine the critical path Abc_NtkIncrementTravId( pNtk ); if ( !Abc_NtkDelayTraceCritPath_rec( vSlacks, Abc_ObjFanin0(pOut), pIn, vBest ) ) { if ( pIn == NULL ) printf( "The logic cone of PO \"%s\" has no primary inputs.\n", Abc_ObjName(pOut) ); else printf( "There is no combinational path between PI \"%s\" and PO \"%s\".\n", Abc_ObjName(pIn), Abc_ObjName(pOut) ); } else { float Slack = 0.0, SlackAdd; int k, iFanin, Length = 0; Abc_Obj_t * pFanin; // check the additional slack SlackAdd = Abc_NodeReadRequiredWorst(pOut) - Abc_NodeReadArrivalWorst(Abc_ObjFanin0(pOut)); // collect the critical path Abc_NtkDelayTraceCritPathCollect_rec( vSlacks, Abc_ObjFanin0(pOut), vBest, vPath ); if ( pIn == NULL ) pIn = (Abc_Obj_t *)Vec_PtrEntry( vPath, 0 ); // find the longest gate name Vec_PtrForEachEntry( Abc_Obj_t *, vPath, pNode, i ) if ( Abc_ObjIsNode(pNode) ) Length = Abc_MaxInt( Length, strlen(Mio_GateReadName((Mio_Gate_t *)pNode->pData)) ); // print critical path Abc_NtkLevel( pNtk ); printf( "Critical path from PI \"%s\" to PO \"%s\":\n", Abc_ObjName(pIn), Abc_ObjName(pOut) ); Vec_PtrForEachEntry( Abc_Obj_t *, vPath, pNode, i ) { printf( "Level %3d : ", Abc_ObjLevel(pNode) ); if ( Abc_ObjIsCi(pNode) ) { printf( "Primary input \"%s\". ", Abc_ObjName(pNode) ); printf( "Arrival time =%6.1f. ", Abc_NodeReadArrivalWorst(pNode) ); printf( "\n" ); continue; } if ( Abc_ObjIsCo(pNode) ) { printf( "Primary output \"%s\". ", Abc_ObjName(pNode) ); printf( "Arrival =%6.1f. ", Abc_NodeReadArrivalWorst(pNode) ); } else { assert( Abc_ObjIsNode(pNode) ); iFanin = Abc_NodeFindFanin( pNode, (Abc_Obj_t *)Vec_PtrEntry(vPath,i-1) ); Slack = Abc_NtkDelayTraceSlack(vSlacks, pNode, iFanin); printf( "%10s/", Abc_ObjName(pNode) ); printf( "%-4s", Mio_GateReadPinName((Mio_Gate_t *)pNode->pData, iFanin) ); printf( " (%s)", Mio_GateReadName((Mio_Gate_t *)pNode->pData) ); for ( k = strlen(Mio_GateReadName((Mio_Gate_t *)pNode->pData)); k < Length; k++ ) printf( " " ); printf( " " ); printf( "Arrival =%6.1f. ", Abc_NodeReadArrivalWorst(pNode) ); printf( "I/O times: (" ); Abc_ObjForEachFanin( pNode, pFanin, k ) printf( "%s%.1f", (k? ", ":""), Abc_NodeReadArrivalWorst(pFanin) ); // printf( " -> %.1f)", Abc_NodeReadArrival(pNode)->Worst + Slack + SlackAdd ); printf( " -> %.1f)", Abc_NodeReadArrivalWorst(pNode) ); } printf( "\n" ); } printf( "Level %3d : ", Abc_ObjLevel(Abc_ObjFanin0(pOut)) + 1 ); printf( "Primary output \"%s\". ", Abc_ObjName(pOut) ); printf( "Required time = %6.1f. ", Abc_NodeReadRequiredWorst(pOut) ); printf( "Path slack = %6.1f.\n", SlackAdd ); } Vec_PtrFree( vPath ); Vec_IntFree( vBest ); } Vec_IntFreeP( &vSlacks ); return tArrivalMax; } /**Function************************************************************* Synopsis [Computes the level of the node using its fanin levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjLevelNew( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i, Level = 0; Abc_ObjForEachFanin( pObj, pFanin, i ) Level = Abc_MaxFloat( Level, Abc_ObjLevel(pFanin) ); return Level + (int)(Abc_ObjFaninNum(pObj) > 0); } /**Function************************************************************* Synopsis [Computes the reverse level of the node using its fanout levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, LevelCur, Level = 0; Abc_ObjForEachFanout( pObj, pFanout, i ) { LevelCur = Abc_ObjReverseLevel( pFanout ); Level = Abc_MaxFloat( Level, LevelCur ); } return Level + 1; } /**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 Abc_ObjRequiredLevel( Abc_Obj_t * pObj ) { Abc_Ntk_t * pNtk = pObj->pNtk; assert( pNtk->vLevelsR ); return pNtk->LevelMax + 1 - Abc_ObjReverseLevel(pObj); } /**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 [] ***********************************************************************/ int Abc_ObjReverseLevel( Abc_Obj_t * pObj ) { Abc_Ntk_t * pNtk = pObj->pNtk; assert( pNtk->vLevelsR ); Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); return Vec_IntEntry(pNtk->vLevelsR, 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 [] ***********************************************************************/ void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ) { Abc_Ntk_t * pNtk = pObj->pNtk; assert( pNtk->vLevelsR ); Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR ); } /**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 Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; // remember the maximum number of direct levels pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease; // start the reverse levels pNtk->vLevelsR = Vec_IntAlloc( 0 ); Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 ); // compute levels in reverse topological order vNodes = Abc_NtkDfsReverse( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Cleans the data structures used to compute required levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ) { assert( pNtk->vLevelsR ); Vec_IntFree( pNtk->vLevelsR ); pNtk->vLevelsR = NULL; pNtk->LevelMax = 0; } /**Function************************************************************* Synopsis [Incrementally updates level of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) { Abc_Obj_t * pFanout, * pTemp; int LevelOld, Lev, k, m; // int Counter = 0, CounterMax = 0; // check if level has changed LevelOld = Abc_ObjLevel(pObjNew); if ( LevelOld == Abc_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( vLevels ); Vec_VecPush( vLevels, LevelOld, pObjNew ); pObjNew->fMarkA = 1; // recursively update level Vec_VecForEachEntryStart( Abc_Obj_t *, vLevels, pTemp, Lev, k, LevelOld ) { // Counter--; pTemp->fMarkA = 0; assert( Abc_ObjLevel(pTemp) == Lev ); Abc_ObjSetLevel( pTemp, Abc_ObjLevelNew(pTemp) ); // if the level did not change, no need to check the fanout levels if ( Abc_ObjLevel(pTemp) == Lev ) continue; // schedule fanout for level update Abc_ObjForEachFanout( pTemp, pFanout, m ) { if ( !Abc_ObjIsCo(pFanout) && !pFanout->fMarkA ) { assert( Abc_ObjLevel(pFanout) >= Lev ); Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout ); // Counter++; // CounterMax = Abc_MaxFloat( CounterMax, Counter ); pFanout->fMarkA = 1; } } } // printf( "%d ", CounterMax ); } /**Function************************************************************* Synopsis [Incrementally updates level of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) { Abc_Obj_t * pFanin, * pTemp; int LevelOld, LevFanin, Lev, k, m; // check if level has changed LevelOld = Abc_ObjReverseLevel(pObjNew); if ( LevelOld == Abc_ObjReverseLevelNew(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( vLevels ); Vec_VecPush( vLevels, LevelOld, pObjNew ); pObjNew->fMarkA = 1; // recursively update level Vec_VecForEachEntryStart( Abc_Obj_t *, vLevels, pTemp, Lev, k, LevelOld ) { pTemp->fMarkA = 0; LevelOld = Abc_ObjReverseLevel(pTemp); assert( LevelOld == Lev ); Abc_ObjSetReverseLevel( pTemp, Abc_ObjReverseLevelNew(pTemp) ); // if the level did not change, no need to check the fanout levels if ( Abc_ObjReverseLevel(pTemp) == Lev ) continue; // schedule fanins for level update Abc_ObjForEachFanin( pTemp, pFanin, m ) { if ( !Abc_ObjIsCi(pFanin) && !pFanin->fMarkA ) { LevFanin = Abc_ObjReverseLevel( pFanin ); assert( LevFanin >= Lev ); Vec_VecPush( vLevels, LevFanin, pFanin ); pFanin->fMarkA = 1; } } } } /**Function************************************************************* Synopsis [Replaces the node and incrementally updates levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) { // replace the old node by the new node pObjNew->Level = pObj->Level; Abc_ObjReplace( pObj, pObjNew ); // update the level of the node Abc_NtkUpdateLevel( pObjNew, vLevels ); Abc_ObjSetReverseLevel( pObjNew, 0 ); Abc_NtkUpdateReverseLevel( pObjNew, vLevels ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcUnate.c000066400000000000000000000120061300674244400235310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcUnate.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: abcUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD static void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ); static void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Detects unate variables of the multi-output function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ) { if ( fUseBdds || fUseNaive ) Abc_NtkPrintUnateBdd( pNtk, fUseNaive, fVerbose ); else Abc_NtkPrintUnateSat( pNtk, fVerbose ); } /**Function************************************************************* Synopsis [Detects unate variables using BDDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ) { Abc_Obj_t * pNode; Extra_UnateInfo_t * p; DdManager * dd; // the BDD manager used to hold shared BDDs // DdNode ** pbGlobal; // temporary storage for global BDDs int TotalSupps = 0; int TotalUnate = 0; int i; abctime clk = Abc_Clock(); abctime clkBdd, clkUnate; // compute the global BDDs dd = (DdManager *)Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose); if ( dd == NULL ) return; clkBdd = Abc_Clock() - clk; // get information about the network // dd = pNtk->pManGlob; // dd = (DdManager *)Abc_NtkGlobalBddMan( pNtk ); // pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob ); // print the size of the BDDs printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); // perform naive BDD-based computation if ( fUseNaive ) { Abc_NtkForEachCo( pNtk, pNode, i ) { // p = Extra_UnateComputeSlow( dd, pbGlobal[i] ); p = Extra_UnateComputeSlow( dd, (DdNode *)Abc_ObjGlobalBdd(pNode) ); if ( fVerbose ) Extra_UnateInfoPrint( p ); TotalSupps += p->nVars; TotalUnate += p->nUnate; Extra_UnateInfoDissolve( p ); } } // perform smart BDD-based computation else { // create ZDD variables in the manager Cudd_zddVarsFromBddVars( dd, 2 ); Abc_NtkForEachCo( pNtk, pNode, i ) { // p = Extra_UnateComputeFast( dd, pbGlobal[i] ); p = Extra_UnateComputeFast( dd, (DdNode *)Abc_ObjGlobalBdd(pNode) ); if ( fVerbose ) Extra_UnateInfoPrint( p ); TotalSupps += p->nVars; TotalUnate += p->nUnate; Extra_UnateInfoDissolve( p ); } } clkUnate = Abc_Clock() - clk - clkBdd; // print stats printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n", Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), TotalSupps, TotalUnate ); ABC_PRT( "Glob BDDs", clkBdd ); ABC_PRT( "Unateness", clkUnate ); ABC_PRT( "Total ", Abc_Clock() - clk ); // deref the PO functions // Abc_NtkFreeGlobalBdds( pNtk ); // stop the global BDD manager // Extra_StopManager( pNtk->pManGlob ); // pNtk->pManGlob = NULL; Abc_NtkFreeGlobalBdds( pNtk, 1 ); } /**Function************************************************************* Synopsis [Detects unate variables using SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose ) { } #else void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ){} #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcUnreach.c000066400000000000000000000320441300674244400240460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcUnreach.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Computes unreachable states for small benchmarks.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcUnreach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD static DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ); static DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ); static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bRelation, DdNode * bInitial, int fVerbose ); static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Extracts sequential DCs of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, int fVerbose ) { int fReorder = 1; DdManager * dd; DdNode * bRelation, * bInitial, * bUnreach; // remove EXDC network if present if ( pNtk->pExdc ) { Abc_NtkDelete( pNtk->pExdc ); pNtk->pExdc = NULL; } // compute the global BDDs of the latches dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); if ( dd == NULL ) return 0; if ( fVerbose ) printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); // create the transition relation (dereferenced global BDDs) bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose ); Cudd_Ref( bRelation ); // create the initial state and the variable map bInitial = Abc_NtkInitStateAndVarMap( dd, pNtk, fVerbose ); Cudd_Ref( bInitial ); // compute the unreachable states bUnreach = Abc_NtkComputeUnreachable( dd, pNtk, bRelation, bInitial, fVerbose ); Cudd_Ref( bUnreach ); Cudd_RecursiveDeref( dd, bRelation ); Cudd_RecursiveDeref( dd, bInitial ); // reorder and disable reordering if ( fReorder ) { if ( fVerbose ) fprintf( stdout, "BDD nodes in the unreachable states before reordering %d.\n", Cudd_DagSize(bUnreach) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); Cudd_AutodynDisable( dd ); if ( fVerbose ) fprintf( stdout, "BDD nodes in the unreachable states after reordering %d.\n", Cudd_DagSize(bUnreach) ); } // allocate ZDD variables Cudd_zddVarsFromBddVars( dd, 2 ); // create the EXDC network representing the unreachable states if ( pNtk->pExdc ) Abc_NtkDelete( pNtk->pExdc ); pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach ); Cudd_RecursiveDeref( dd, bUnreach ); Extra_StopManager( dd ); // pNtk->pManGlob = NULL; // make sure that everything is okay if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) ) { printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" ); Abc_NtkDelete( pNtk->pExdc ); return 0; } return 1; } /**Function************************************************************* Synopsis [Computes the transition relation of the network.] Description [Assumes that the global BDDs are computed.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) { DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs; Abc_Obj_t * pNode; int fReorder = 1; int i; // extand the BDD manager to represent NS variables assert( dd->size == Abc_NtkCiNum(pNtk) ); Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 ); // enable reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); else Cudd_AutodynDisable( dd ); // compute the transition relation bRel = b1; Cudd_Ref( bRel ); Abc_NtkForEachLatch( pNtk, pNode, i ) { bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); // bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); bProd = Cudd_bddXnor( dd, bVar, (DdNode *)Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } // free the global BDDs // Abc_NtkFreeGlobalBdds( pNtk ); Abc_NtkFreeGlobalBdds( pNtk, 0 ); // quantify the PI variables bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs ); bRel = Cudd_bddExistAbstract( dd, bTemp = bRel, bInputs ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bInputs ); // reorder and disable reordering if ( fReorder ) { if ( fVerbose ) fprintf( stdout, "BDD nodes in the transition relation before reordering %d.\n", Cudd_DagSize(bRel) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); Cudd_AutodynDisable( dd ); if ( fVerbose ) fprintf( stdout, "BDD nodes in the transition relation after reordering %d.\n", Cudd_DagSize(bRel) ); } Cudd_Deref( bRel ); return bRel; } /**Function************************************************************* Synopsis [Computes the initial state and sets up the variable map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) { DdNode ** pbVarsX, ** pbVarsY; DdNode * bTemp, * bProd, * bVar; Abc_Obj_t * pLatch; int i; // set the variable mapping for Cudd_bddVarMap() pbVarsX = ABC_ALLOC( DdNode *, dd->size ); pbVarsY = ABC_ALLOC( DdNode *, dd->size ); bProd = b1; Cudd_Ref( bProd ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ]; pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ]; // get the initial value of the latch bVar = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) ); bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) ); ABC_FREE( pbVarsX ); ABC_FREE( pbVarsY ); Cudd_Deref( bProd ); return bProd; } /**Function************************************************************* Synopsis [Computes the set of unreachable states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bTrans, DdNode * bInitial, int fVerbose ) { DdNode * bRelation, * bReached, * bCubeCs; DdNode * bCurrent, * bNext, * bTemp; int nIters, nMints; // perform reachability analisys bCurrent = bInitial; Cudd_Ref( bCurrent ); bReached = bInitial; Cudd_Ref( bReached ); bRelation = bTrans; Cudd_Ref( bRelation ); bCubeCs = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) ); Cudd_Ref( bCubeCs ); for ( nIters = 1; ; nIters++ ) { // compute the next states bNext = Cudd_bddAndAbstract( dd, bRelation, bCurrent, bCubeCs ); Cudd_Ref( bNext ); Cudd_RecursiveDeref( dd, bCurrent ); // remap these states into the current state vars bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); Cudd_RecursiveDeref( dd, bTemp ); // check if there are any new states if ( Cudd_bddLeq( dd, bNext, bReached ) ) break; // get the new states bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); // minimize the new states with the reached states // bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); // Cudd_RecursiveDeref( dd, bTemp ); // add to the reached states bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bNext ); // minimize the transition relation // bRelation = Cudd_bddConstrain( dd, bTemp = bRelation, Cudd_Not(bReached) ); Cudd_Ref( bRelation ); // Cudd_RecursiveDeref( dd, bTemp ); } Cudd_RecursiveDeref( dd, bRelation ); Cudd_RecursiveDeref( dd, bCubeCs ); Cudd_RecursiveDeref( dd, bNext ); // report the stats if ( fVerbose ) { nMints = (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) ); fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters ); fprintf( stdout, "The number of minterms in the reachable state set = %d. (%6.2f %%)\n", nMints, 100.0*nMints/(1<pName = Extra_UtilStrsav( "exdc" ); pNtkNew->pSpec = NULL; // create PIs corresponding to LOs Abc_NtkForEachLatchOutput( pNtk, pNode, i ) Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pNode), NULL ); // cannot ADD POs here because pLatch->pCopy point to the PIs // create a new node pNodeNew = Abc_NtkCreateNode(pNtkNew); // add the fanins corresponding to latch outputs Abc_NtkForEachLatchOutput( pNtk, pNode, i ) Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); // create the logic function pPermute = ABC_ALLOC( int, dd->size ); for ( i = 0; i < dd->size; i++ ) pPermute[i] = -1; Abc_NtkForEachLatch( pNtk, pNode, i ) pPermute[Abc_NtkPiNum(pNtk) + i] = i; // remap the functions pNodeNew->pData = Extra_TransferPermute( dd, (DdManager *)pNtkNew->pManFunc, bUnreach, pPermute ); Cudd_Ref( (DdNode *)pNodeNew->pData ); ABC_FREE( pPermute ); Abc_NodeMinimumBase( pNodeNew ); // for each CO, create PO (skip POs equal to CIs because of name conflict) Abc_NtkForEachPo( pNtk, pNode, i ) if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL ); Abc_NtkForEachLatchInput( pNtk, pNode, i ) Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL ); // link to the POs of the network Abc_NtkForEachPo( pNtk, pNode, i ) if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); Abc_NtkForEachLatchInput( pNtk, pNode, i ) Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); // remove the extra nodes Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc ); // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // transform the network to the SOP representation if ( !Abc_NtkBddToSop( pNtkNew, -1, ABC_INFINITY ) ) { printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" ); return NULL; } return pNtkNew; // return NULL; } #else int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, int fVerbose ) { return 1; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcVerify.c000066400000000000000000001056351300674244400237340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcVerify.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Combinational and sequential verification for two networks.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcVerify.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "base/cmd/cmd.h" #include "proof/fraig/fraig.h" #include "opt/sim/sim.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include "aig/gia/gia.h" #include "proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ); extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Verifies combinational equivalence by brute-force SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ) { extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); Abc_Ntk_t * pMiter; Abc_Ntk_t * pCnf; int RetValue; // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0, 0, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); printf( "Networks are equivalent after structural hashing.\n" ); return; } // convert the miter into a CNF pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); Abc_NtkDelete( pMiter ); if ( pCnf == NULL ) { printf( "Renoding for CNF has failed.\n" ); return; } // solve the CNF using the SAT solver RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, 0, NULL, NULL ); if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out).\n" ); else if ( RetValue == 0 ) printf( "Networks are NOT EQUIVALENT after SAT.\n" ); else printf( "Networks are equivalent after SAT.\n" ); if ( pCnf->pModel ) Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel ); ABC_FREE( pCnf->pModel ); Abc_NtkDelete( pCnf ); } /**Function************************************************************* Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) { Prove_Params_t Params, * pParams = &Params; // Fraig_Params_t Params; // Fraig_Man_t * pMan; Abc_Ntk_t * pMiter, * pTemp; Abc_Ntk_t * pExdc = NULL; int RetValue; if ( pNtk1->pExdc != NULL || pNtk2->pExdc != NULL ) { if ( pNtk1->pExdc != NULL && pNtk2->pExdc != NULL ) { printf( "Comparing EXDC of the two networks:\n" ); Abc_NtkCecFraig( pNtk1->pExdc, pNtk2->pExdc, nSeconds, fVerbose ); printf( "Comparing networks under EXDC of the first network.\n" ); pExdc = pNtk1->pExdc; } else if ( pNtk1->pExdc != NULL ) { printf( "Second network has no EXDC. Comparing main networks under EXDC of the first network.\n" ); pExdc = pNtk1->pExdc; } else if ( pNtk2->pExdc != NULL ) { printf( "First network has no EXDC. Comparing main networks under EXDC of the second network.\n" ); pExdc = pNtk2->pExdc; } else assert( 0 ); } // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0, 0, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } // add EXDC to the miter if ( pExdc ) { assert( Abc_NtkPoNum(pMiter) == 1 ); assert( Abc_NtkPoNum(pExdc) == 1 ); pMiter = Abc_NtkMiter( pTemp = pMiter, pExdc, 1, 0, 1, 0 ); Abc_NtkDelete( pTemp ); } // handle trivial case RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return; } if ( RetValue == 1 ) { printf( "Networks are equivalent after structural hashing.\n" ); Abc_NtkDelete( pMiter ); return; } /* // convert the miter into a FRAIG Fraig_ParamsSetDefault( &Params ); Params.fVerbose = fVerbose; Params.nSeconds = nSeconds; // Params.fFuncRed = 0; // Params.nPatsRand = 0; // Params.nPatsDyna = 0; pMan = (Fraig_Man_t *)Abc_NtkToFraig( pMiter, &Params, 0, 0 ); Fraig_ManProveMiter( pMan ); // analyze the result RetValue = Fraig_ManCheckMiter( pMan ); // report the result if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out on the final miter).\n" ); else if ( RetValue == 1 ) printf( "Networks are equivalent after fraiging.\n" ); else if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); Abc_NtkVerifyReportError( pNtk1, pNtk2, Fraig_ManReadModel(pMan) ); } else assert( 0 ); // delete the fraig manager Fraig_ManFree( pMan ); // delete the miter Abc_NtkDelete( pMiter ); */ // solve the CNF using the SAT solver Prove_ParamsSetDefault( pParams ); pParams->nItersMax = 5; // RetValue = Abc_NtkMiterProve( &pMiter, pParams ); // pParams->fVerbose = 1; RetValue = Abc_NtkIvyProve( &pMiter, pParams ); if ( RetValue == -1 ) printf( "Networks are undecided (resource limits is reached).\n" ); else if ( RetValue == 0 ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel ); if ( pSimInfo[0] != 1 ) printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); else printf( "Networks are NOT EQUIVALENT.\n" ); ABC_FREE( pSimInfo ); } else printf( "Networks are equivalent.\n" ); if ( pMiter->pModel ) Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); Abc_NtkDelete( pMiter ); } /**Function************************************************************* Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ) { Prove_Params_t Params, * pParams = &Params; Abc_Ntk_t * pMiter, * pMiterPart; Abc_Obj_t * pObj; int i, RetValue, Status, nOutputs; // solve the CNF using the SAT solver Prove_ParamsSetDefault( pParams ); pParams->nItersMax = 5; // pParams->fVerbose = 1; assert( nPartSize > 0 ); // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize, 0, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return; } if ( RetValue == 1 ) { printf( "Networks are equivalent after structural hashing.\n" ); Abc_NtkDelete( pMiter ); return; } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); // solve the problem iteratively for each output of the miter Status = 1; nOutputs = 0; Abc_NtkForEachPo( pMiter, pObj, i ) { if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) ) { if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0 RetValue = 1; else RetValue = 0; pMiterPart = NULL; } else { // get the cone of this output pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 ); if ( Abc_ObjFaninC0(pObj) ) Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 ); // solve the cone // RetValue = Abc_NtkMiterProve( &pMiterPart, pParams ); RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); } if ( RetValue == -1 ) { printf( "Networks are undecided (resource limits is reached).\r" ); Status = -1; } else if ( RetValue == 0 ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); if ( pSimInfo[0] != 1 ) printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); else printf( "Networks are NOT EQUIVALENT. \n" ); ABC_FREE( pSimInfo ); Status = 0; break; } else { printf( "Finished part %5d (out of %5d)\r", i+1, Abc_NtkPoNum(pMiter) ); nOutputs += nPartSize; } // if ( pMiter->pModel ) // Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); if ( pMiterPart ) Abc_NtkDelete( pMiterPart ); } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); if ( Status == 1 ) printf( "Networks are equivalent. \n" ); else if ( Status == -1 ) printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); Abc_NtkDelete( pMiter ); } /**Function************************************************************* Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) { extern Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose ); extern void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOnePtr ); Vec_Ptr_t * vParts, * vOnePtr; Vec_Int_t * vOne; Prove_Params_t Params, * pParams = &Params; Abc_Ntk_t * pMiter, * pMiterPart; int i, RetValue, Status, nOutputs; // solve the CNF using the SAT solver Prove_ParamsSetDefault( pParams ); pParams->nItersMax = 5; // pParams->fVerbose = 1; // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 1, 0, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return; } if ( RetValue == 1 ) { printf( "Networks are equivalent after structural hashing.\n" ); Abc_NtkDelete( pMiter ); return; } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); // partition the outputs vParts = Abc_NtkPartitionSmart( pMiter, 300, 0 ); // fraig each partition Status = 1; nOutputs = 0; vOnePtr = Vec_PtrAlloc( 1000 ); Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i ) { // get this part of the miter Abc_NtkConvertCos( pMiter, vOne, vOnePtr ); pMiterPart = Abc_NtkCreateConeArray( pMiter, vOnePtr, 0 ); Abc_NtkCombinePos( pMiterPart, 0, 0 ); // check the miter for being constant RetValue = Abc_NtkMiterIsConstant( pMiterPart ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after partitioning.\n" ); Abc_NtkDelete( pMiterPart ); break; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiterPart ); continue; } printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pMiterPart), Abc_NtkPoNum(pMiterPart), Abc_NtkNodeNum(pMiterPart), Abc_AigLevel(pMiterPart) ); fflush( stdout ); // solve the problem RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); if ( RetValue == -1 ) { printf( "Networks are undecided (resource limits is reached).\r" ); Status = -1; } else if ( RetValue == 0 ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); if ( pSimInfo[0] != 1 ) printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); else printf( "Networks are NOT EQUIVALENT. \n" ); ABC_FREE( pSimInfo ); Status = 0; Abc_NtkDelete( pMiterPart ); break; } else { // printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); nOutputs += Vec_IntSize(vOne); } Abc_NtkDelete( pMiterPart ); } printf( " \r" ); Vec_VecFree( (Vec_Vec_t *)vParts ); Vec_PtrFree( vOnePtr ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); if ( Status == 1 ) printf( "Networks are equivalent. \n" ); else if ( Status == -1 ) printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); Abc_NtkDelete( pMiter ); } /**Function************************************************************* Synopsis [Verifies sequential equivalence by brute-force SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ) { extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); Abc_Ntk_t * pMiter; Abc_Ntk_t * pFrames; Abc_Ntk_t * pCnf; int RetValue; // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0, 0, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { Abc_NtkDelete( pMiter ); printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); return; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); printf( "Networks are equivalent after structural hashing.\n" ); return; } // create the timeframes pFrames = Abc_NtkFrames( pMiter, nFrames, 1, 0 ); Abc_NtkDelete( pMiter ); if ( pFrames == NULL ) { printf( "Frames computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pFrames ); if ( RetValue == 0 ) { Abc_NtkDelete( pFrames ); printf( "Networks are NOT EQUIVALENT after framing.\n" ); return; } if ( RetValue == 1 ) { Abc_NtkDelete( pFrames ); printf( "Networks are equivalent after framing.\n" ); return; } // convert the miter into a CNF pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 ); Abc_NtkDelete( pFrames ); if ( pCnf == NULL ) { printf( "Renoding for CNF has failed.\n" ); return; } // solve the CNF using the SAT solver RetValue = Abc_NtkMiterSat( pCnf, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, 0, NULL, NULL ); if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out).\n" ); else if ( RetValue == 0 ) printf( "Networks are NOT EQUIVALENT after SAT.\n" ); else printf( "Networks are equivalent after SAT.\n" ); Abc_NtkDelete( pCnf ); } /**Function************************************************************* Synopsis [Verifies combinational equivalence by fraiging followed by SAT] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ) { Fraig_Params_t Params; Fraig_Man_t * pMan; Abc_Ntk_t * pMiter; Abc_Ntk_t * pFrames; int RetValue; // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0, 0, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return 0; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return 0; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiter ); printf( "Networks are equivalent after structural hashing.\n" ); return 1; } // create the timeframes pFrames = Abc_NtkFrames( pMiter, nFrames, 1, 0 ); Abc_NtkDelete( pMiter ); if ( pFrames == NULL ) { printf( "Frames computation has failed.\n" ); return 0; } RetValue = Abc_NtkMiterIsConstant( pFrames ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after framing.\n" ); // report the error pFrames->pModel = Abc_NtkVerifyGetCleanModel( pFrames, 1 ); // Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pFrames->pModel, nFrames ); ABC_FREE( pFrames->pModel ); Abc_NtkDelete( pFrames ); return 0; } if ( RetValue == 1 ) { Abc_NtkDelete( pFrames ); printf( "Networks are equivalent after framing.\n" ); return 1; } // convert the miter into a FRAIG Fraig_ParamsSetDefault( &Params ); Params.fVerbose = fVerbose; Params.nSeconds = nSeconds; // Params.fFuncRed = 0; // Params.nPatsRand = 0; // Params.nPatsDyna = 0; pMan = (Fraig_Man_t *)Abc_NtkToFraig( pFrames, &Params, 0, 0 ); Fraig_ManProveMiter( pMan ); // analyze the result RetValue = Fraig_ManCheckMiter( pMan ); // report the result if ( RetValue == -1 ) printf( "Networks are undecided (SAT solver timed out on the final miter).\n" ); else if ( RetValue == 1 ) printf( "Networks are equivalent after fraiging.\n" ); else if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); // Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, Fraig_ManReadModel(pMan), nFrames ); } else assert( 0 ); // delete the fraig manager Fraig_ManFree( pMan ); // delete the miter Abc_NtkDelete( pFrames ); return RetValue == 1; } /**Function************************************************************* Synopsis [Returns a dummy pattern full of zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ) { int * pModel = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) * nFrames ); memset( pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) * nFrames ); return pModel; } /**Function************************************************************* Synopsis [Returns the PO values under the given input pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ) { Abc_Obj_t * pNode; int * pValues, Value0, Value1, i; int fStrashed = 0; if ( !Abc_NtkIsStrash(pNtk) ) { pNtk = Abc_NtkStrash(pNtk, 0, 0, 0); fStrashed = 1; } /* printf( "Counter example: " ); Abc_NtkForEachCi( pNtk, pNode, i ) printf( " %d", pModel[i] ); printf( "\n" ); */ // increment the trav ID Abc_NtkIncrementTravId( pNtk ); // set the CI values Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)1; Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)pModel[i]; // simulate in the topological order Abc_NtkForEachNode( pNtk, pNode, i ) { Value0 = ((int)(ABC_PTRINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ (int)Abc_ObjFaninC0(pNode); Value1 = ((int)(ABC_PTRINT_T)Abc_ObjFanin1(pNode)->pCopy) ^ (int)Abc_ObjFaninC1(pNode); pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)(Value0 & Value1); } // fill the output values pValues = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) pValues[i] = ((int)(ABC_PTRINT_T)Abc_ObjFanin0(pNode)->pCopy) ^ (int)Abc_ObjFaninC0(pNode); if ( fStrashed ) Abc_NtkDelete( pNtk ); return pValues; } /**Function************************************************************* Synopsis [Reports mismatch between the two networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int * pValues1, * pValues2; int nErrors, nPrinted, i, iNode = -1; assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) ); // get the CO values under this model pValues1 = Abc_NtkVerifySimulatePattern( pNtk1, pModel ); pValues2 = Abc_NtkVerifySimulatePattern( pNtk2, pModel ); // count the mismatches nErrors = 0; for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) nErrors += (int)( pValues1[i] != pValues2[i] ); printf( "Verification failed for at least %d outputs: ", nErrors ); // print the first 3 outputs nPrinted = 0; for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) if ( pValues1[i] != pValues2[i] ) { if ( iNode == -1 ) iNode = i; printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); if ( ++nPrinted == 3 ) break; } if ( nPrinted != nErrors ) printf( " ..." ); printf( "\n" ); // report mismatch for the first output if ( iNode >= 0 ) { printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] ); printf( "Input pattern: " ); // collect PIs in the cone pNode = Abc_NtkCo(pNtk1,iNode); vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 ); // set the PI numbers Abc_NtkForEachCi( pNtk1, pNode, i ) pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)i; // print the model pNode = (Abc_Obj_t *)Vec_PtrEntry( vNodes, 0 ); if ( Abc_ObjIsCi(pNode) ) { Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { assert( Abc_ObjIsCi(pNode) ); printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)(ABC_PTRINT_T)pNode->pCopy] ); } } printf( "\n" ); Vec_PtrFree( vNodes ); } ABC_FREE( pValues1 ); ABC_FREE( pValues2 ); } /**Function************************************************************* Synopsis [Computes the COs in the support of the PO in the given frame.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkGetSeqPoSupp( Abc_Ntk_t * pNtk, int iFrame, int iNumPo ) { Abc_Ntk_t * pFrames; Abc_Obj_t * pObj, * pNodePo; Vec_Ptr_t * vSupp; int i, k; // get the timeframes of the network pFrames = Abc_NtkFrames( pNtk, iFrame + 1, 0, 0 ); //Abc_NtkShowAig( pFrames ); // get the PO of the timeframes pNodePo = Abc_NtkPo( pFrames, iFrame * Abc_NtkPoNum(pNtk) + iNumPo ); // set the support vSupp = Abc_NtkNodeSupport( pFrames, &pNodePo, 1 ); // mark the support of the frames Abc_NtkForEachCi( pFrames, pObj, i ) pObj->pCopy = NULL; Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) pObj->pCopy = (Abc_Obj_t *)1; // mark the support of the network if the support of the timeframes is marked Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = NULL; Abc_NtkForEachLatch( pNtk, pObj, i ) if ( Abc_NtkBox(pFrames, i)->pCopy ) pObj->pCopy = (Abc_Obj_t *)1; Abc_NtkForEachPi( pNtk, pObj, i ) for ( k = 0; k <= iFrame; k++ ) if ( Abc_NtkPi(pFrames, k*Abc_NtkPiNum(pNtk) + i)->pCopy ) pObj->pCopy = (Abc_Obj_t *)1; // free stuff Vec_PtrFree( vSupp ); Abc_NtkDelete( pFrames ); } /**Function************************************************************* Synopsis [Reports mismatch between the two sequential networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ) { Vec_Ptr_t * vInfo1, * vInfo2; Abc_Obj_t * pObj, * pObjError, * pObj1, * pObj2; int ValueError1 = -1, ValueError2 = -1; unsigned * pPats1, * pPats2; int i, o, k, nErrors, iFrameError = -1, iNodePo = -1, nPrinted; int fRemove1 = 0, fRemove2 = 0; if ( !Abc_NtkIsStrash(pNtk1) ) fRemove1 = 1, pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 ); if ( !Abc_NtkIsStrash(pNtk2) ) fRemove2 = 1, pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 ); // simulate sequential circuits vInfo1 = Sim_SimulateSeqModel( pNtk1, nFrames, pModel ); vInfo2 = Sim_SimulateSeqModel( pNtk2, nFrames, pModel ); // look for a discrepancy in the PO values nErrors = 0; pObjError = NULL; for ( i = 0; i < nFrames; i++ ) { if ( pObjError ) break; Abc_NtkForEachPo( pNtk1, pObj1, o ) { pObj2 = Abc_NtkPo( pNtk2, o ); pPats1 = Sim_SimInfoGet(vInfo1, pObj1); pPats2 = Sim_SimInfoGet(vInfo2, pObj2); if ( pPats1[i] == pPats2[i] ) continue; nErrors++; if ( pObjError == NULL ) { pObjError = pObj1; iFrameError = i; iNodePo = o; ValueError1 = (pPats1[i] > 0); ValueError2 = (pPats2[i] > 0); } } } if ( pObjError == NULL ) { printf( "No output mismatches detected.\n" ); Sim_UtilInfoFree( vInfo1 ); Sim_UtilInfoFree( vInfo2 ); if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); return; } printf( "Verification failed for at least %d output%s of frame %d: ", nErrors, (nErrors>1? "s":""), iFrameError+1 ); // print the first 3 outputs nPrinted = 0; Abc_NtkForEachPo( pNtk1, pObj1, o ) { pObj2 = Abc_NtkPo( pNtk2, o ); pPats1 = Sim_SimInfoGet(vInfo1, pObj1); pPats2 = Sim_SimInfoGet(vInfo2, pObj2); if ( pPats1[iFrameError] == pPats2[iFrameError] ) continue; printf( " %s", Abc_ObjName(pObj1) ); if ( ++nPrinted == 3 ) break; } if ( nPrinted != nErrors ) printf( " ..." ); printf( "\n" ); // mark CIs of the networks in the cone of influence of this output Abc_NtkGetSeqPoSupp( pNtk1, iFrameError, iNodePo ); Abc_NtkGetSeqPoSupp( pNtk2, iFrameError, iNodePo ); // report mismatch for the first output printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", Abc_ObjName(pObjError), ValueError1, ValueError2 ); printf( "The cone of influence of output %s in Network1:\n", Abc_ObjName(pObjError) ); printf( "PIs: " ); Abc_NtkForEachPi( pNtk1, pObj, i ) if ( pObj->pCopy ) printf( "%s ", Abc_ObjName(pObj) ); printf( "\n" ); printf( "Latches: " ); Abc_NtkForEachLatch( pNtk1, pObj, i ) if ( pObj->pCopy ) printf( "%s ", Abc_ObjName(pObj) ); printf( "\n" ); printf( "The cone of influence of output %s in Network2:\n", Abc_ObjName(pObjError) ); printf( "PIs: " ); Abc_NtkForEachPi( pNtk2, pObj, i ) if ( pObj->pCopy ) printf( "%s ", Abc_ObjName(pObj) ); printf( "\n" ); printf( "Latches: " ); Abc_NtkForEachLatch( pNtk2, pObj, i ) if ( pObj->pCopy ) printf( "%s ", Abc_ObjName(pObj) ); printf( "\n" ); // print the patterns for ( i = 0; i <= iFrameError; i++ ) { printf( "Frame %d: ", i+1 ); printf( "PI(1):" ); Abc_NtkForEachPi( pNtk1, pObj, k ) if ( pObj->pCopy ) printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 ); printf( " " ); printf( "L(1):" ); Abc_NtkForEachLatch( pNtk1, pObj, k ) if ( pObj->pCopy ) printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 ); printf( " " ); printf( "%s(1):", Abc_ObjName(pObjError) ); printf( "%d", Sim_SimInfoGet(vInfo1, pObjError)[i] > 0 ); printf( " " ); printf( "PI(2):" ); Abc_NtkForEachPi( pNtk2, pObj, k ) if ( pObj->pCopy ) printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 ); printf( " " ); printf( "L(2):" ); Abc_NtkForEachLatch( pNtk2, pObj, k ) if ( pObj->pCopy ) printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 ); printf( " " ); printf( "%s(2):", Abc_ObjName(pObjError) ); printf( "%d", Sim_SimInfoGet(vInfo2, pObjError)[i] > 0 ); printf( "\n" ); } Abc_NtkForEachCi( pNtk1, pObj, i ) pObj->pCopy = NULL; Abc_NtkForEachCi( pNtk2, pObj, i ) pObj->pCopy = NULL; Sim_UtilInfoFree( vInfo1 ); Sim_UtilInfoFree( vInfo2 ); if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); } /**Function************************************************************* Synopsis [Simulates buggy miter emailed by Mike.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSimulteBuggyMiter( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; int * pModel1, * pModel2, * pResult1, * pResult2; char * vPiValues1 = "01001011100000000011010110101000000"; char * vPiValues2 = "11001101011101011111110100100010001"; assert( strlen(vPiValues1) == (unsigned)Abc_NtkPiNum(pNtk) ); assert( 1 == Abc_NtkPoNum(pNtk) ); pModel1 = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) pModel1[i] = vPiValues1[i] - '0'; Abc_NtkForEachLatch( pNtk, pObj, i ) pModel1[Abc_NtkPiNum(pNtk)+i] = ((int)(ABC_PTRINT_T)pObj->pData) - 1; pResult1 = Abc_NtkVerifySimulatePattern( pNtk, pModel1 ); printf( "Value = %d\n", pResult1[0] ); pModel2 = ABC_ALLOC( int, Abc_NtkCiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) pModel2[i] = vPiValues2[i] - '0'; Abc_NtkForEachLatch( pNtk, pObj, i ) pModel2[Abc_NtkPiNum(pNtk)+i] = pResult1[Abc_NtkPoNum(pNtk)+i]; pResult2 = Abc_NtkVerifySimulatePattern( pNtk, pModel2 ); printf( "Value = %d\n", pResult2[0] ); ABC_FREE( pModel1 ); ABC_FREE( pModel2 ); ABC_FREE( pResult1 ); ABC_FREE( pResult2 ); } /**Function************************************************************* Synopsis [Returns the PO values under the given input pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsTrueCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Aig_Man_t * pMan; int status = 0, fStrashed = 0; if ( !Abc_NtkIsStrash(pNtk) ) { pNtk = Abc_NtkStrash(pNtk, 0, 0, 0); fStrashed = 1; } pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan ) { status = Saig_ManVerifyCex( pMan, pCex ); Aig_ManStop( pMan ); } if ( fStrashed ) Abc_NtkDelete( pNtk ); return status; } /**Function************************************************************* Synopsis [Returns 1 if the number of PIs matches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsValidCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex ) { return Abc_NtkPiNum(pNtk) == pCex->nPis; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abcXsim.c000066400000000000000000000163541300674244400234070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcXsim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Using X-valued simulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcXsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define XVS0 ABC_INIT_ZERO #define XVS1 ABC_INIT_ONE #define XVSX ABC_INIT_DC static inline void Abc_ObjSetXsim( Abc_Obj_t * pObj, int Value ) { pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Value; } static inline int Abc_ObjGetXsim( Abc_Obj_t * pObj ) { return (int)(ABC_PTRINT_T)pObj->pCopy; } static inline int Abc_XsimInv( int Value ) { if ( Value == XVS0 ) return XVS1; if ( Value == XVS1 ) return XVS0; assert( Value == XVSX ); return XVSX; } static inline int Abc_XsimAnd( int Value0, int Value1 ) { if ( Value0 == XVS0 || Value1 == XVS0 ) return XVS0; if ( Value0 == XVSX || Value1 == XVSX ) return XVSX; assert( Value0 == XVS1 && Value1 == XVS1 ); return XVS1; } static inline int Abc_XsimRand2() { // return (rand() & 1) ? XVS1 : XVS0; return (Gia_ManRandom(0) & 1) ? XVS1 : XVS0; } static inline int Abc_XsimRand3() { int RetValue; do { // RetValue = rand() & 3; RetValue = Gia_ManRandom(0) & 3; } while ( RetValue == 0 ); return RetValue; } static inline int Abc_ObjGetXsimFanin0( Abc_Obj_t * pObj ) { int RetValue; RetValue = Abc_ObjGetXsim(Abc_ObjFanin0(pObj)); return Abc_ObjFaninC0(pObj)? Abc_XsimInv(RetValue) : RetValue; } static inline int Abc_ObjGetXsimFanin1( Abc_Obj_t * pObj ) { int RetValue; RetValue = Abc_ObjGetXsim(Abc_ObjFanin1(pObj)); return Abc_ObjFaninC1(pObj)? Abc_XsimInv(RetValue) : RetValue; } static inline void Abc_XsimPrint( FILE * pFile, int Value ) { if ( Value == XVS0 ) { fprintf( pFile, "0" ); return; } if ( Value == XVS1 ) { fprintf( pFile, "1" ); return; } assert( Value == XVSX ); fprintf( pFile, "x" ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs X-valued simulation of the sequential network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose ) { Abc_Obj_t * pObj; int i, f; assert( Abc_NtkIsStrash(pNtk) ); // srand( 0x12341234 ); Gia_ManRandom( 1 ); // start simulation Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); if ( fXInputs ) { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, XVSX ); } else { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); } if ( fXState ) { Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX ); } else { Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) ); } // simulate and print the result fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" ); for ( f = 0; f < nFrames; f++ ) { Abc_AigForEachAnd( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); // print out fprintf( stdout, "%2d : ", f ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); fprintf( stdout, " : " ); Abc_NtkForEachLatch( pNtk, pObj, i ) { // if ( Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) != XVSX ) // printf( " %s=", Abc_ObjName(pObj) ); Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) ); } fprintf( stdout, " : " ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); fprintf( stdout, "\n" ); // assign input values if ( fXInputs ) { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, XVSX ); } else { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); } // transfer the latch values Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); } } /**Function************************************************************* Synopsis [Cycles the circuit to create a new initial state.] Description [Simulates the circuit with random (or ternary) input for the given number of timeframes to get a better initial state.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fUseXval, int fVerbose ) { Abc_Obj_t * pObj; int i, f; assert( Abc_NtkIsStrash(pNtk) ); // srand( 0x12341234 ); Gia_ManRandom( 1 ); // initialize the values Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) ); // simulate for the given number of timeframes for ( f = 0; f < nFrames; f++ ) { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, fUseXval? ABC_INIT_DC : Abc_XsimRand2() ); // Abc_ObjSetXsim( pObj, ABC_INIT_ONE ); Abc_AigForEachAnd( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); } // set the final values Abc_NtkForEachLatch( pNtk, pObj, i ) { pObj->pData = (void *)(ABC_PTRINT_T)Abc_ObjGetXsim(Abc_ObjFanout0(pObj)); // printf( "%d", Abc_LatchIsInit1(pObj) ); } // printf( "\n" ); } /////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/abciUnfold2.c000066400000000000000000000131631300674244400241440ustar00rootroot00000000000000 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandUnfold2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int nFrames; int nConfs; int nProps; int fStruct = 0; int fOldAlgo = 0; int fVerbose; int c; extern Abc_Ntk_t * Abc_NtkDarUnfold2( Abc_Ntk_t * pNtk, int nFrames, int nConfs, int nProps, int fStruct, int fOldAlgo, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nFrames = 1; nConfs = 1000; nProps = 1000; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CPvh" ) ) != 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 '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 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nProps = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nProps < 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_NtkIsComb(pNtk) ) { Abc_Print( -1, "The network is combinational.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkConstrNum(pNtk) > 0 ) { Abc_Print( -1, "Constraints are already extracted.\n" ); return 0; } if ( Abc_NtkPoNum(pNtk) > 1 && !fStruct ) { Abc_Print( -1, "Functional constraint extraction works for single-output miters (use \"orpos\").\n" ); return 0; } // modify the current network pNtkRes = Abc_NtkDarUnfold2( pNtk, nFrames, nConfs, nProps, fStruct, fOldAlgo, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( 1,"Transformation has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: unfold2 [-FCP num] [-savh]\n" ); Abc_Print( -2, "\t unfold hidden constraints as separate outputs\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts in SAT solving [default = %d]\n", nConfs ); Abc_Print( -2, "\t-P num : the max number of constraint propagations [default = %d]\n", nProps ); 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; } int Abc_CommandFold2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int fCompl; int fVerbose; int c; extern Abc_Ntk_t * Abc_NtkDarFold2( Abc_Ntk_t * pNtk, int fCompl, int fVerbose , int); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fCompl = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF ) { switch ( c ) { /* case 'c': */ /* fCompl ^= 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, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkConstrNum(pNtk) == 0 ) { Abc_Print( 0, "The network has no constraints.\n" ); return 0; } if ( Abc_NtkIsComb(pNtk) ) Abc_Print( 0, "The network is combinational.\n" ); // modify the current network pNtkRes = Abc_NtkDarFold2( pNtk, fCompl, fVerbose ,0); if ( pNtkRes == NULL ) { Abc_Print( 1,"Transformation has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: fold [-cvh]\n" ); Abc_Print( -2, "\t folds constraints represented as separate outputs\n" ); // Abc_Print( -2, "\t-c : toggle complementing constraints while folding [default = %s]\n", fCompl? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/fahout_cut.c000066400000000000000000000261231300674244400241550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMerge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [LUT merging algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/aig/aig.h" #include "aig/nwk/nwkMerge.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Marks the fanins of the node with the current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMarkFanins_rec( Abc_Obj_t * pLut, int nLevMin ) { Abc_Obj_t * pNext; int i; if ( !Abc_ObjIsNode(pLut) ) return; if ( Abc_NodeIsTravIdCurrent( pLut ) ) return; Abc_NodeSetTravIdCurrent( pLut ); if ( Abc_ObjLevel(pLut) < nLevMin ) return; Abc_ObjForEachFanin( pLut, pNext, i ) Abc_NtkMarkFanins_rec( pNext, nLevMin ); } /**Function************************************************************* Synopsis [Marks the fanouts of the node with the current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMarkFanouts_rec( Abc_Obj_t * pLut, int nLevMax, int nFanMax ) { Abc_Obj_t * pNext; int i; if ( !Abc_ObjIsNode(pLut) ) return; if ( Abc_NodeIsTravIdCurrent( pLut ) ) return; Abc_NodeSetTravIdCurrent( pLut ); if ( Abc_ObjLevel(pLut) > nLevMax ) return; if ( Abc_ObjFanoutNum(pLut) > nFanMax ) return; Abc_ObjForEachFanout( pLut, pNext, i ) Abc_NtkMarkFanouts_rec( pNext, nLevMax, nFanMax ); } /**Function************************************************************* Synopsis [Collects the circle of nodes around the given set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) { Abc_Obj_t * pObj, * pNext; int i, k; Vec_PtrClear( vNext ); Vec_PtrForEachEntry( Vec_Int_t *, vStart, pObj, i ) { Abc_ObjForEachFanin( pObj, pNext, k ) { if ( !Abc_ObjIsNode(pNext) ) continue; if ( Abc_NodeIsTravIdCurrent( pNext ) ) continue; Abc_NodeSetTravIdCurrent( pNext ); Vec_PtrPush( vNext, pNext ); } Abc_ObjForEachFanout( pObj, pNext, k ) { if ( !Abc_ObjIsNode(pNext) ) continue; if ( Abc_NodeIsTravIdCurrent( pNext ) ) continue; Abc_NodeSetTravIdCurrent( pNext ); if ( Abc_ObjFanoutNum(pNext) > nFanMax ) continue; Vec_PtrPush( vNext, pNext ); } } } /**Function************************************************************* Synopsis [Collects the circle of nodes removes from the given one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectNonOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) { Vec_Ptr_t * vTemp; Abc_Obj_t * pObj; int i, k; Vec_PtrClear( vCands ); if ( pPars->nMaxSuppSize - Abc_ObjFaninNum(pLut) <= 1 ) return; // collect nodes removed by this distance assert( pPars->nMaxDistance > 0 ); Vec_PtrClear( vStart ); Vec_PtrPush( vStart, pLut ); Abc_NtkIncrementTravId( pLut->pNtk ); Abc_NodeSetTravIdCurrent( pLut ); for ( i = 1; i <= pPars->nMaxDistance; i++ ) { Abc_NtkCollectCircle( vStart, vNext, pPars->nMaxFanout ); vTemp = vStart; vStart = vNext; vNext = vTemp; // collect the nodes in vStart Vec_PtrForEachEntry( Vec_Int_t *, vStart, pObj, k ) Vec_PtrPush( vCands, pObj ); } // mark the TFI/TFO nodes Abc_NtkIncrementTravId( pLut->pNtk ); if ( pPars->fUseTfiTfo ) Abc_NodeSetTravIdCurrent( pLut ); else { Abc_NodeSetTravIdPrevious( pLut ); Abc_NtkMarkFanins_rec( pLut, Abc_ObjLevel(pLut) - pPars->nMaxDistance ); Abc_NodeSetTravIdPrevious( pLut ); Abc_NtkMarkFanouts_rec( pLut, Abc_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); } // collect nodes satisfying the following conditions: // - they are close enough in terms of distance // - they are not in the TFI/TFO of the LUT // - they have no more than the given number of fanins // - they have no more than the given diff in delay k = 0; Vec_PtrForEachEntry( Vec_Int_t *, vCands, pObj, i ) { if ( Abc_NodeIsTravIdCurrent(pObj) ) continue; if ( Abc_ObjFaninNum(pLut) + Abc_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) continue; if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) continue; Vec_PtrWriteEntry( vCands, k++, pObj ); } Vec_PtrShrink( vCands, k ); } /**Function************************************************************* Synopsis [Count the total number of fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountTotalFanins( Abc_Obj_t * pLut, Abc_Obj_t * pCand ) { Abc_Obj_t * pFanin; int i, nCounter = Abc_ObjFaninNum(pLut); Abc_ObjForEachFanin( pCand, pFanin, i ) nCounter += !pFanin->fMarkC; return nCounter; } /**Function************************************************************* Synopsis [Collects overlapping candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) { Abc_Obj_t * pFanin, * pObj; int i, k; // mark fanins of pLut Abc_ObjForEachFanin( pLut, pFanin, i ) pFanin->fMarkC = 1; // collect the matching fanouts of each fanin of the node Vec_PtrClear( vCands ); Abc_NtkIncrementTravId( pLut->pNtk ); Abc_NodeSetTravIdCurrent( pLut ); Abc_ObjForEachFanin( pLut, pFanin, i ) { if ( !Abc_ObjIsNode(pFanin) ) continue; if ( Abc_ObjFanoutNum(pFanin) > pPars->nMaxFanout ) continue; Abc_ObjForEachFanout( pFanin, pObj, k ) { if ( !Abc_ObjIsNode(pObj) ) continue; if ( Abc_NodeIsTravIdCurrent( pObj ) ) continue; Abc_NodeSetTravIdCurrent( pObj ); // check the difference in delay if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) continue; // check the total number of fanins of the node if ( Abc_NtkCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) continue; Vec_PtrPush( vCands, pObj ); } } // unmark fanins of pLut Abc_ObjForEachFanin( pLut, pFanin, i ) pFanin->fMarkC = 0; } /**Function************************************************************* Synopsis [Performs LUT merging with parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars ) { Nwk_Grf_t * p; Vec_Int_t * vResult; Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; Abc_Obj_t * pLut, * pCand; int i, k, nVertsMax, nCands; clock_t clk = clock(); // count the number of vertices nVertsMax = 0; Abc_NtkForEachNode( pNtk, pLut, i ) nVertsMax += (int)(Abc_ObjFaninNum(pLut) <= pPars->nMaxLutSize); p = Nwk_ManGraphAlloc( nVertsMax ); // create graph vStart = Vec_PtrAlloc( 1000 ); vNext = Vec_PtrAlloc( 1000 ); vCands1 = Vec_PtrAlloc( 1000 ); vCands2 = Vec_PtrAlloc( 1000 ); nCands = 0; Abc_NtkForEachNode( pNtk, pLut, i ) { if ( Abc_ObjFaninNum(pLut) > pPars->nMaxLutSize ) continue; Abc_NtkCollectOverlapCands( pLut, vCands1, pPars ); if ( pPars->fUseDiffSupp ) Abc_NtkCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) continue; nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2); // save candidates Vec_PtrForEachEntry( Vec_Int_t *, vCands1, pCand, k ) Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); Vec_PtrForEachEntry( Vec_Int_t *, vCands2, pCand, k ) Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); // print statistics about this node if ( pPars->fVeryVerbose ) printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", Abc_ObjId(pLut), Abc_ObjFaninNum(pLut), Abc_ObjFaninNum(pLut), Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); } Vec_PtrFree( vStart ); Vec_PtrFree( vNext ); Vec_PtrFree( vCands1 ); Vec_PtrFree( vCands2 ); if ( pPars->fVerbose ) { printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands ); ABC_PRT( "Deriving graph", clock() - clk ); } // solve the graph problem clk = clock(); Nwk_ManGraphSolve( p ); if ( pPars->fVerbose ) { printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); ABC_PRT( "Solving", clock() - clk ); Nwk_ManGraphReportMemoryUsage( p ); } vResult = p->vPairs; p->vPairs = NULL; /* for ( i = 0; i < vResult->nSize; i += 2 ) printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); printf( "\n" ); */ Nwk_ManGraphFree( p ); return vResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/abci/module.make000066400000000000000000000040011300674244400237630ustar00rootroot00000000000000SRC += src/base/abci/abc.c \ src/base/abci/abcAttach.c \ src/base/abci/abcAuto.c \ src/base/abci/abcBalance.c \ src/base/abci/abcBidec.c \ src/base/abci/abcBm.c \ src/base/abci/abcBmc.c \ src/base/abci/abcCas.c \ src/base/abci/abcCascade.c \ src/base/abci/abcCollapse.c \ src/base/abci/abcCut.c \ src/base/abci/abcDar.c \ src/base/abci/abcDebug.c \ src/base/abci/abcDec.c \ src/base/abci/abcDetect.c \ src/base/abci/abcDress.c \ src/base/abci/abcDress2.c \ src/base/abci/abcDress3.c \ src/base/abci/abcDsd.c \ src/base/abci/abcExact.c \ src/base/abci/abcExtract.c \ src/base/abci/abcFraig.c \ src/base/abci/abcFx.c \ src/base/abci/abcFxu.c \ src/base/abci/abcGen.c \ src/base/abci/abcHaig.c \ src/base/abci/abcIf.c \ src/base/abci/abcIfif.c \ src/base/abci/abcIfMux.c \ src/base/abci/abcIvy.c \ src/base/abci/abcLog.c \ src/base/abci/abcLut.c \ src/base/abci/abcLutmin.c \ src/base/abci/abcMap.c \ src/base/abci/abcMerge.c \ src/base/abci/abcMfs.c \ src/base/abci/abcMini.c \ src/base/abci/abcMiter.c \ src/base/abci/abcMulti.c \ src/base/abci/abcNtbdd.c \ src/base/abci/abcNpn.c \ src/base/abci/abcNpnSave.c \ src/base/abci/abcOdc.c \ src/base/abci/abcOrder.c \ src/base/abci/abcPart.c \ src/base/abci/abcPrint.c \ src/base/abci/abcProve.c \ src/base/abci/abcQbf.c \ src/base/abci/abcQuant.c \ src/base/abci/abcRec3.c \ src/base/abci/abcReconv.c \ src/base/abci/abcReach.c \ src/base/abci/abcRefactor.c \ src/base/abci/abcRenode.c \ src/base/abci/abcReorder.c \ src/base/abci/abcRestruct.c \ src/base/abci/abcResub.c \ src/base/abci/abcRewrite.c \ src/base/abci/abcRpo.c \ src/base/abci/abcRr.c \ src/base/abci/abcSat.c \ src/base/abci/abcSaucy.c \ src/base/abci/abcScorr.c \ src/base/abci/abcSense.c \ src/base/abci/abcSpeedup.c \ src/base/abci/abcStrash.c \ src/base/abci/abcSweep.c \ src/base/abci/abcSymm.c \ src/base/abci/abcTim.c \ src/base/abci/abcTiming.c \ src/base/abci/abcUnate.c \ src/base/abci/abcUnreach.c \ src/base/abci/abcVerify.c \ src/base/abci/abcXsim.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/000077500000000000000000000000001300674244400214735ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bac.c000066400000000000000000000027131300674244400223670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bac.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Parses several flavors of word-level Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bac.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bac.h000066400000000000000000001536711300674244400224060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bac.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 - November 29, 2014.] Revision [$Id: bac.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__bac__bac_h #define ABC__base__bac__bac_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "misc/extra/extra.h" #include "misc/util/utilNam.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // network objects typedef enum { BAC_OBJ_NONE = 0, // 0: unused BAC_OBJ_PI, // 1: input BAC_OBJ_PO, // 2: output BAC_OBJ_BI, // 3: box input BAC_OBJ_BO, // 4: box output BAC_OBJ_BOX, // 5: box BAC_BOX_CF, BAC_BOX_CT, BAC_BOX_CX, BAC_BOX_CZ, BAC_BOX_BUF, BAC_BOX_INV, BAC_BOX_AND, BAC_BOX_NAND, BAC_BOX_OR, BAC_BOX_NOR, BAC_BOX_XOR, BAC_BOX_XNOR, BAC_BOX_SHARP, BAC_BOX_SHARPL, BAC_BOX_MUX, BAC_BOX_MAJ, BAC_BOX_RAND, BAC_BOX_RNAND, BAC_BOX_ROR, BAC_BOX_RNOR, BAC_BOX_RXOR, BAC_BOX_RXNOR, BAC_BOX_LAND, BAC_BOX_LNAND, BAC_BOX_LOR, BAC_BOX_LNOR, BAC_BOX_LXOR, BAC_BOX_LXNOR, BAC_BOX_NMUX, BAC_BOX_SEL, BAC_BOX_PSEL, BAC_BOX_ENC, BAC_BOX_PENC, BAC_BOX_DEC, BAC_BOX_EDEC, BAC_BOX_ADD, BAC_BOX_SUB, BAC_BOX_MUL, BAC_BOX_DIV, BAC_BOX_MOD, BAC_BOX_REM, BAC_BOX_POW, BAC_BOX_MIN, BAC_BOX_ABS, BAC_BOX_LTHAN, BAC_BOX_LETHAN, BAC_BOX_METHAN, BAC_BOX_MTHAN, BAC_BOX_EQU, BAC_BOX_NEQU, BAC_BOX_SHIL, BAC_BOX_SHIR, BAC_BOX_ROTL, BAC_BOX_ROTR, BAC_BOX_GATE, BAC_BOX_LUT, BAC_BOX_ASSIGN, BAC_BOX_TRI, BAC_BOX_RAM, BAC_BOX_RAMR, BAC_BOX_RAMW, BAC_BOX_RAMWC, BAC_BOX_RAMBOX, BAC_BOX_LATCH, BAC_BOX_LATCHRS, BAC_BOX_DFF, BAC_BOX_DFFRS, BAC_BOX_UNKNOWN // 67 } Bac_ObjType_t; // name types typedef enum { BAC_NAME_BIN = 0, // 0: binary variable BAC_NAME_WORD, // 1: first bit of word-level variable BAC_NAME_INFO, // 2: first bit of special variable BAC_NAME_INDEX, // 3: index of word-level variable } Bac_NameType_t; typedef struct Bac_Ntk_t_ Bac_Ntk_t; typedef struct Bac_Man_t_ Bac_Man_t; // network struct Bac_Ntk_t_ { Bac_Man_t * pDesign; // design int NameId; // name ID int iCopy; // copy module int iBoxNtk; // instance network ID int iBoxObj; // instance object ID int Count; // object counter int Mark; // visit mark // interface Vec_Int_t vInputs; // inputs Vec_Int_t vOutputs; // outputs Vec_Int_t vInfo; // input/output/wire info // object attributes Vec_Str_t vType; // types Vec_Int_t vFanin; // fanin Vec_Int_t vIndex; // index Vec_Int_t vName; // original NameId or InstId Vec_Int_t vFanout; // fanout Vec_Int_t vCopy; // copy // other Vec_Int_t vArray; Vec_Int_t vArray2; }; // design struct Bac_Man_t_ { // design names char * pName; // design name char * pSpec; // spec file name Abc_Nam_t * pStrs; // string manager Abc_Nam_t * pMods; // module name manager // internal data int iRoot; // root network int nNtks; // number of current networks Bac_Ntk_t * pNtks; // networks // user data Vec_Str_t * vOut; Vec_Str_t * vOut2; Vec_Int_t vBuf2RootNtk; Vec_Int_t vBuf2RootObj; Vec_Int_t vBuf2LeafNtk; Vec_Int_t vBuf2LeafObj; void * pMioLib; void ** ppGraphs; int ElemGates[4]; char * pPrimNames[BAC_BOX_UNKNOWN]; char * pPrimSymbs[BAC_BOX_UNKNOWN]; }; static inline char * Bac_ManName( Bac_Man_t * p ) { return p->pName; } static inline char * Bac_ManSpec( Bac_Man_t * p ) { return p->pSpec; } static inline int Bac_ManNtkNum( Bac_Man_t * p ) { return p->nNtks; } static inline int Bac_ManPrimNum( Bac_Man_t * p ) { return Abc_NamObjNumMax(p->pMods) - Bac_ManNtkNum(p); } static inline int Bac_ManNtkIsOk( Bac_Man_t * p, int i ) { return i > 0 && i <= Bac_ManNtkNum(p); } static inline Bac_Ntk_t * Bac_ManNtk( Bac_Man_t * p, int i ) { return Bac_ManNtkIsOk(p, i) ? p->pNtks + i : NULL; } static inline int Bac_ManNtkFindId( Bac_Man_t * p, char * pName ) { return Abc_NamStrFind(p->pMods, pName); } static inline Bac_Ntk_t * Bac_ManNtkFind( Bac_Man_t * p, char * pName ) { return Bac_ManNtk( p, Bac_ManNtkFindId(p, pName) ); } static inline Bac_Ntk_t * Bac_ManRoot( Bac_Man_t * p ) { return Bac_ManNtk(p, p->iRoot); } static inline char * Bac_ManStr( Bac_Man_t * p, int i ) { return Abc_NamStr(p->pStrs, i); } static inline int Bac_ManStrId( Bac_Man_t * p, char * pStr ) { return Abc_NamStrFind(p->pStrs, pStr); } static inline char * Bac_ManPrimName( Bac_Man_t * p, Bac_ObjType_t Type ) { return p->pPrimNames[Type]; } static inline char * Bac_ManPrimSymb( Bac_Man_t * p, Bac_ObjType_t Type ) { return p->pPrimSymbs[Type]; } static inline int Bac_NtkId( Bac_Ntk_t * p ) { int i = p - p->pDesign->pNtks; assert(Bac_ManNtkIsOk(p->pDesign, i)); return i; } static inline Bac_Man_t * Bac_NtkMan( Bac_Ntk_t * p ) { return p->pDesign; } static inline int Bac_NtkNameId( Bac_Ntk_t * p ) { return p->NameId; } static inline char * Bac_NtkName( Bac_Ntk_t * p ) { return Bac_ManStr(p->pDesign, Bac_NtkNameId(p)); } static inline int Bac_NtkCopy( Bac_Ntk_t * p ) { return p->iCopy; } static inline Bac_Ntk_t * Bac_NtkCopyNtk(Bac_Man_t * pNew, Bac_Ntk_t * p) { return Bac_ManNtk(pNew, Bac_NtkCopy(p)); } static inline void Bac_NtkSetCopy( Bac_Ntk_t * p, int i ) { assert(p->iCopy == -1); p->iCopy = i; } static inline int Bac_NtkObjNum( Bac_Ntk_t * p ) { return Vec_StrSize(&p->vType); } static inline int Bac_NtkObjNumAlloc( Bac_Ntk_t * p ) { return Vec_StrCap(&p->vType); } static inline int Bac_NtkPiNum( Bac_Ntk_t * p ) { return Vec_IntSize(&p->vInputs); } static inline int Bac_NtkPoNum( Bac_Ntk_t * p ) { return Vec_IntSize(&p->vOutputs); } static inline int Bac_NtkPioNum( Bac_Ntk_t * p ) { return Bac_NtkPiNum(p) + Bac_NtkPoNum(p); } static inline int Bac_NtkPiNumAlloc( Bac_Ntk_t * p ) { return Vec_IntCap(&p->vInputs); } static inline int Bac_NtkPoNumAlloc( Bac_Ntk_t * p ) { return Vec_IntCap(&p->vOutputs); } static inline int Bac_NtkBiNum( Bac_Ntk_t * p ) { return Vec_StrCountEntryLit(&p->vType, (char)BAC_OBJ_BI); } static inline int Bac_NtkBoNum( Bac_Ntk_t * p ) { return Vec_StrCountEntryLit(&p->vType, (char)BAC_OBJ_BO); } static inline int Bac_NtkCiNum( Bac_Ntk_t * p ) { return Bac_NtkPiNum(p) + Bac_NtkBoNum(p); } static inline int Bac_NtkCoNum( Bac_Ntk_t * p ) { return Bac_NtkPoNum(p) + Bac_NtkBiNum(p); } static inline int Bac_NtkBoxNum( Bac_Ntk_t * p ) { return Bac_NtkObjNum(p) - Vec_StrCountSmallerLit(&p->vType, (char)BAC_OBJ_BOX); } static inline int Bac_NtkPrimNum( Bac_Ntk_t * p ) { return Vec_StrCountLargerLit(&p->vType, (char)BAC_OBJ_BOX); } static inline int Bac_NtkUserNum( Bac_Ntk_t * p ) { return Vec_StrCountEntryLit(&p->vType, (char)BAC_OBJ_BOX); } static inline int Bac_NtkPi( Bac_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vInputs, i); } static inline int Bac_NtkPo( Bac_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vOutputs, i); } static inline char * Bac_NtkStr( Bac_Ntk_t * p, int i ) { return Bac_ManStr(p->pDesign, i); } static inline Bac_Ntk_t * Bac_NtkHostNtk( Bac_Ntk_t * p ) { return p->iBoxNtk > 0 ? Bac_ManNtk(p->pDesign, p->iBoxNtk) : NULL; } static inline int Bac_NtkHostObj( Bac_Ntk_t * p ) { return p->iBoxObj; } static inline void Bac_NtkSetHost( Bac_Ntk_t * p, int n, int i ) { assert(p->iBoxNtk == -1); p->iBoxNtk = n; p->iBoxObj = i; } static inline int Bac_InfoRange( int Beg, int End ) { return End > Beg ? End - Beg + 1 : Beg - End + 1; } static inline int Bac_NtkInfoNum( Bac_Ntk_t * p ) { return Vec_IntSize(&p->vInfo)/3; } static inline int Bac_NtkInfoNumAlloc( Bac_Ntk_t * p ) { return Vec_IntCap(&p->vInfo)/3; } static inline int Bac_NtkInfoType( Bac_Ntk_t * p, int i ) { return Abc_Lit2Att2(Vec_IntEntry(&p->vInfo, 3*i)); } static inline int Bac_NtkInfoName( Bac_Ntk_t * p, int i ) { return Abc_Lit2Var2(Vec_IntEntry(&p->vInfo, 3*i)); } static inline int Bac_NtkInfoBeg( Bac_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vInfo, 3*i+1); } static inline int Bac_NtkInfoEnd( Bac_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vInfo, 3*i+2); } static inline int Bac_NtkInfoRange( Bac_Ntk_t * p, int i ) { int* a = Vec_IntEntryP(&p->vInfo, 3*i); return a[1]>=0 ? Bac_InfoRange( a[1], a[2] ) : 1; } static inline int Bac_NtkInfoIndex( Bac_Ntk_t * p, int i, int j ) { int* a = Vec_IntEntryP(&p->vInfo, 3*i); assert(a[1]>=0); return a[1]vInfo, i); Vec_IntPushTwo(&p->vInfo, b, e); } static inline void Bac_NtkSetInfoName( Bac_Ntk_t * p, int i, int n){ Vec_IntWriteEntry( &p->vInfo, 3*i, n ); } static inline void Bac_NtkStartNames( Bac_Ntk_t * p ) { assert(Bac_NtkObjNumAlloc(p)); Vec_IntFill(&p->vName, Bac_NtkObjNumAlloc(p), 0); } static inline void Bac_NtkStartFanouts( Bac_Ntk_t * p ) { assert(Bac_NtkObjNumAlloc(p)); Vec_IntFill(&p->vFanout, Bac_NtkObjNumAlloc(p), 0); } static inline void Bac_NtkStartCopies( Bac_Ntk_t * p ) { assert(Bac_NtkObjNumAlloc(p)); Vec_IntFill(&p->vCopy, Bac_NtkObjNumAlloc(p), -1); } static inline void Bac_NtkFreeNames( Bac_Ntk_t * p ) { Vec_IntErase(&p->vName); } static inline void Bac_NtkFreeFanouts( Bac_Ntk_t * p ) { Vec_IntErase(&p->vFanout); } static inline void Bac_NtkFreeCopies( Bac_Ntk_t * p ) { Vec_IntErase(&p->vCopy); } static inline int Bac_NtkHasNames( Bac_Ntk_t * p ) { return p->vName.pArray != NULL; } static inline int Bac_NtkHasFanouts( Bac_Ntk_t * p ) { return p->vFanout.pArray != NULL; } static inline int Bac_NtkHasCopies( Bac_Ntk_t * p ) { return p->vCopy.pArray != NULL; } static inline int Bac_TypeIsBox( Bac_ObjType_t Type ) { return Type >= BAC_OBJ_BOX && Type < BAC_BOX_UNKNOWN; } static inline Bac_NameType_t Bac_NameType( int n ) { assert( n ); return (Bac_NameType_t)Abc_Lit2Att2( n ); } static inline int Bac_CharIsDigit( char c ) { return c >= '0' && c <= '9'; } static inline Bac_ObjType_t Bac_ObjType( Bac_Ntk_t * p, int i ) { return (Bac_ObjType_t)Abc_Lit2Var((int)(unsigned char)Vec_StrEntry(&p->vType, i)); } static inline int Bac_ObjIsPi( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) == BAC_OBJ_PI; } static inline int Bac_ObjIsPo( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) == BAC_OBJ_PO; } static inline int Bac_ObjIsPio( Bac_Ntk_t * p, int i ) { return Bac_ObjIsPi(p, i) || Bac_ObjIsPo(p, i); } static inline int Bac_ObjIsBi( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) == BAC_OBJ_BI; } static inline int Bac_ObjIsBo( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) == BAC_OBJ_BO; } static inline int Bac_ObjIsBio( Bac_Ntk_t * p, int i ) { return Bac_ObjIsBi(p, i) || Bac_ObjIsBo(p, i); } static inline int Bac_ObjIsBox( Bac_Ntk_t * p, int i ) { return Bac_TypeIsBox(Bac_ObjType(p, i)); } static inline int Bac_ObjIsBoxUser( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) == BAC_OBJ_BOX; } static inline int Bac_ObjIsBoxPrim( Bac_Ntk_t * p, int i ) { return Bac_ObjIsBox(p, i) && !Bac_ObjIsBoxUser(p, i); } static inline int Bac_ObjIsGate( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) == BAC_BOX_GATE; } static inline int Bac_ObjIsCi( Bac_Ntk_t * p, int i ) { return Bac_ObjIsPi(p, i) || Bac_ObjIsBo(p, i); } static inline int Bac_ObjIsCo( Bac_Ntk_t * p, int i ) { return Bac_ObjIsPo(p, i) || Bac_ObjIsBi(p, i); } static inline int Bac_ObjIsCio( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) < BAC_OBJ_BOX; } static inline int Bac_ObjIsConst( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) >= BAC_BOX_CF && Bac_ObjType(p, i) <= BAC_BOX_CZ; } static inline int Bac_ObjIsConstBin( Bac_Ntk_t * p, int i ) { return Bac_ObjType(p, i) == BAC_BOX_CF || Bac_ObjType(p, i) == BAC_BOX_CT; } static inline int Bac_ObjBit( Bac_Ntk_t * p, int i ) { assert(!Bac_ObjIsBox(p, i)); return Abc_LitIsCompl((int)Vec_StrEntry(&p->vType, i)); } static inline void Bac_ObjSetBit( Bac_Ntk_t * p, int i ) { char *q = Vec_StrArray(&p->vType); assert(!Bac_ObjIsBox(p, i)); q[i] = (char)Abc_LitNot((int)q[i]); } static inline int Bac_ObjFanin( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsCo(p, i)); return Vec_IntEntry(&p->vFanin, i); } static inline int Bac_ObjIndex( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsCio(p, i)); return Vec_IntEntry(&p->vIndex, i); } static inline int Bac_ObjNameInt( Bac_Ntk_t * p, int i ) { assert(!Bac_ObjIsCo(p, i)); return Vec_IntEntry(&p->vName, i); } static inline int Bac_ObjName( Bac_Ntk_t * p, int i ) { return Bac_ObjIsCo(p, i) ? Bac_ObjNameInt(p, Bac_ObjFanin(p,i)) : Bac_ObjNameInt(p, i); } static inline Bac_NameType_t Bac_ObjNameType( Bac_Ntk_t * p, int i ) { return Bac_NameType( Bac_ObjName(p, i) ); } static inline int Bac_ObjNameId( Bac_Ntk_t * p, int i ) { return Abc_Lit2Var2( Bac_ObjName(p, i) ); } static inline char * Bac_ObjNameStr( Bac_Ntk_t * p, int i ) { assert(Bac_ObjNameType(p, i) <= BAC_NAME_WORD); return Bac_NtkStr(p, Bac_ObjNameId(p, i)); } static inline int Bac_ObjCopy( Bac_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vCopy, i); } static inline int Bac_ObjFanout( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsCi(p, i)); return Vec_IntEntry(&p->vFanout, i); } static inline int Bac_ObjNextFanout( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsCo(p, i)); return Vec_IntEntry(&p->vFanout, i); } static inline void Bac_ObjSetFanout( Bac_Ntk_t * p, int i, int x ) { assert(Bac_ObjIsCi(p, i)); Vec_IntSetEntry(&p->vFanout, i, x); } static inline void Bac_ObjSetNextFanout( Bac_Ntk_t * p,int i,int x){ assert(Bac_ObjIsCo(p, i)); Vec_IntSetEntry(&p->vFanout, i, x); } static inline void Bac_ObjCleanFanin( Bac_Ntk_t * p, int i ) { assert(Bac_ObjFanin(p, i) >= 0 && Bac_ObjIsCo(p, i)); Vec_IntSetEntry( &p->vFanin, i, -1); } static inline void Bac_ObjSetFanin( Bac_Ntk_t * p, int i, int x ) { assert(Bac_ObjFanin(p, i) == -1 && Bac_ObjIsCo(p, i)); Vec_IntSetEntry( &p->vFanin, i, x); } static inline void Bac_ObjSetIndex( Bac_Ntk_t * p, int i, int x ) { assert(Bac_ObjIndex(p, i) == -1); Vec_IntSetEntry( &p->vIndex, i, x ); } static inline void Bac_ObjSetName( Bac_Ntk_t * p, int i, int x ) { assert(Bac_ObjName(p, i) == 0 && !Bac_ObjIsCo(p, i)); Vec_IntSetEntry( &p->vName, i, x ); } static inline void Bac_ObjSetCopy( Bac_Ntk_t * p, int i, int x ) { assert(Bac_ObjCopy(p, i) == -1); Vec_IntSetEntry( &p->vCopy, i, x ); } static inline int Bac_ObjGetConst( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsCi(p, i)); return Bac_ObjIsBo(p, i) && Bac_ObjIsConst(p, i-1) ? Bac_ObjType(p, i-1) : 0; } static inline int Bac_BoxBiNum( Bac_Ntk_t * p, int i ) { int s = i-1; assert(Bac_ObjIsBox(p, i)); while (--i >= 0 && Bac_ObjIsBi(p, i)) {} return s - i; } static inline int Bac_BoxBoNum( Bac_Ntk_t * p, int i ) { int s = i+1; assert(Bac_ObjIsBox(p, i)); while (++i < Bac_NtkObjNum(p) && Bac_ObjIsBo(p, i)) {} return i - s; } static inline int Bac_BoxSize( Bac_Ntk_t * p, int i ) { return 1 + Bac_BoxBiNum(p, i) + Bac_BoxBoNum(p, i); } static inline int Bac_BoxBi( Bac_Ntk_t * p, int b, int i ) { assert(Bac_ObjIsBox(p, b)); return b - 1 - i; } static inline int Bac_BoxBo( Bac_Ntk_t * p, int b, int i ) { assert(Bac_ObjIsBox(p, b)); return b + 1 + i; } //static inline int Bac_BoxBiBox( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsBi(p, i)); return i + 1 + Bac_ObjIndex(p, i); } static inline int Bac_BoxBoBox( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsBo(p, i)); return i - 1 - Bac_ObjIndex(p, i); } static inline int Bac_BoxFanin( Bac_Ntk_t * p, int b, int i ) { return Bac_ObjFanin(p, Bac_BoxBi(p, b, i)); } static inline int Bac_BoxFaninBox( Bac_Ntk_t * p, int b, int i ) { return Bac_BoxBoBox(p, Bac_BoxFanin(p, b, i)); } static inline int Bac_BoxBiRange( Bac_Ntk_t * p, int i ) { int s = i; assert(Bac_ObjIsBi(p, i) && !Bac_ObjBit(p, i)); while (--i >= 0 && Bac_ObjIsBi(p, i) && Bac_ObjBit(p, i)) {} return s - i; } static inline int Bac_BoxBoRange( Bac_Ntk_t * p, int i ) { int s = i; assert(Bac_ObjIsBo(p, i) && !Bac_ObjBit(p, i)); while (++i < Bac_NtkObjNum(p) && Bac_ObjIsBo(p, i) && Bac_ObjBit(p, i)) {} return i - s; } static inline int Bac_ObjPiRange( Bac_Ntk_t * p, int i ) { int s = i; assert(Bac_ObjIsPi(p, i) && !Bac_ObjBit(p, i)); while (++i < Bac_NtkObjNum(p) && Bac_ObjIsPi(p, i) && Bac_ObjBit(p, i)) {} return i - s; } static inline int Bac_BoxNtkId( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsBox(p, i)); return Vec_IntEntry(&p->vFanin, i); } static inline void Bac_BoxSetNtkId( Bac_Ntk_t * p, int i, int x ) { assert(Bac_ObjIsBox(p, i)&&Bac_ManNtkIsOk(p->pDesign, x));Vec_IntSetEntry(&p->vFanin, i, x);} //static inline int Bac_BoxBiNtkId( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsBi(p, i)); return Bac_BoxNtkId(p, Bac_BoxBiBox(p, i)); } static inline int Bac_BoxBoNtkId( Bac_Ntk_t * p, int i ) { assert(Bac_ObjIsBo(p, i)); return Bac_BoxNtkId(p, Bac_BoxBoBox(p, i)); } static inline Bac_Ntk_t * Bac_BoxNtk( Bac_Ntk_t * p, int i ) { return Bac_ManNtk( p->pDesign, Bac_BoxNtkId(p, i) ); } //static inline Bac_Ntk_t * Bac_BoxBiNtk( Bac_Ntk_t * p, int i ) { return Bac_ManNtk( p->pDesign, Bac_BoxBiNtkId(p, i) ); } static inline Bac_Ntk_t * Bac_BoxBoNtk( Bac_Ntk_t * p, int i ) { return Bac_ManNtk( p->pDesign, Bac_BoxBoNtkId(p, i) ); } static inline char * Bac_BoxNtkName( Bac_Ntk_t * p, int i ) { return Abc_NamStr( p->pDesign->pMods, Bac_BoxNtkId(p, i) ); } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// #define Bac_ManForEachNtk( p, pNtk, i ) \ for ( i = 1; (i <= Bac_ManNtkNum(p)) && (((pNtk) = Bac_ManNtk(p, i)), 1); i++ ) #define Bac_NtkForEachPi( p, iObj, i ) \ for ( i = 0; (i < Bac_NtkPiNum(p)) && (((iObj) = Bac_NtkPi(p, i)), 1); i++ ) #define Bac_NtkForEachPo( p, iObj, i ) \ for ( i = 0; (i < Bac_NtkPoNum(p)) && (((iObj) = Bac_NtkPo(p, i)), 1); i++ ) #define Bac_NtkForEachPoDriver( p, iObj, i ) \ for ( i = 0; (i < Bac_NtkPoNum(p)) && (((iObj) = Bac_ObjFanin(p, Bac_NtkPo(p, i))), 1); i++ ) #define Bac_NtkForEachPiMain( p, iObj, i ) \ for ( i = 0; (i < Bac_NtkPiNum(p)) && (((iObj) = Bac_NtkPi(p, i)), 1); i++ ) if ( Bac_ObjBit(p, iObj) ) {} else #define Bac_NtkForEachPoMain( p, iObj, i ) \ for ( i = 0; (i < Bac_NtkPoNum(p)) && (((iObj) = Bac_NtkPo(p, i)), 1); i++ ) if ( Bac_ObjBit(p, iObj) ) {} else #define Bac_NtkForEachObj( p, i ) if ( !Bac_ObjType(p, i) ) {} else \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) #define Bac_NtkForEachObjType( p, Type, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)) && (((Type) = Bac_ObjType(p, i)), 1); i++ ) if ( !Type ) {} else #define Bac_NtkForEachBox( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsBox(p, i) ) {} else #define Bac_NtkForEachBoxUser( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsBoxUser(p, i) ) {} else #define Bac_NtkForEachBoxPrim( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsBoxPrim(p, i) ) {} else #define Bac_NtkForEachCi( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsCi(p, i) ) {} else #define Bac_NtkForEachCo( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsCo(p, i) ) {} else #define Bac_NtkForEachCio( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsCio(p, i) ){} else #define Bac_NtkForEachBi( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsBi(p, i) ){} else #define Bac_NtkForEachBo( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsBo(p, i) ){} else #define Bac_NtkForEachBio( p, i ) \ for ( i = 0; (i < Bac_NtkObjNum(p)); i++ ) if ( !Bac_ObjIsBio(p, i) ){} else #define Bac_BoxForEachBi( p, iBox, iTerm, i ) \ for ( iTerm = iBox - 1, i = 0; iTerm >= 0 && Bac_ObjIsBi(p, iTerm); iTerm--, i++ ) #define Bac_BoxForEachBo( p, iBox, iTerm, i ) \ for ( iTerm = iBox + 1, i = 0; iTerm < Bac_NtkObjNum(p) && Bac_ObjIsBo(p, iTerm); iTerm++, i++ ) #define Bac_BoxForEachBiReverse( p, iBox, iTerm, i ) \ for ( i = Bac_BoxBiNum(p, iBox), iTerm = iBox - i--; Bac_ObjIsBi(p, iTerm); iTerm++, i-- ) #define Bac_BoxForEachBiMain( p, iBox, iTerm, i ) \ for ( iTerm = iBox - 1, i = 0; iTerm >= 0 && Bac_ObjIsBi(p, iTerm); iTerm--, i++ ) if ( Bac_ObjBit(p, iTerm) ) {} else #define Bac_BoxForEachBoMain( p, iBox, iTerm, i ) \ for ( iTerm = iBox + 1, i = 0; iTerm < Bac_NtkObjNum(p) && Bac_ObjIsBo(p, iTerm); iTerm++, i++ ) if ( Bac_ObjBit(p, iTerm) ) {} else #define Bac_BoxForEachFanin( p, iBox, iFanin, i ) \ for ( i = 0; iBox - 1 - i >= 0 && Bac_ObjIsBi(p, iBox - 1 - i) && (((iFanin) = Bac_BoxFanin(p, iBox, i)), 1); i++ ) #define Bac_BoxForEachFaninBox( p, iBox, iFanin, i ) \ for ( i = 0; iBox - 1 - i >= 0 && Bac_ObjIsBi(p, iBox - 1 - i) && (((iFanin) = Bac_BoxFaninBox(p, iBox, i)), 1); i++ ) #define Bac_ObjForEachFanout( p, iCi, iCo ) \ for ( iCo = Bac_ObjFanout(p, iCi); iCo; iCo = Bac_ObjNextFanout(p, iCo) ) #define Bac_BoxForEachFanoutBox( p, iBox, iCo, iFanBox ) \ for ( assert(Bac_BoxBoNum(p, iBox) == 1), iCo = Bac_ObjFanout(p, Bac_BoxBo(p, iBox, 0)); iCo && ((iFanBox = Bac_BoxBiBox(p, iCo)), 1); iCo = Bac_ObjNextFanout(p, iCo) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Object APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Bac_ObjAlloc( Bac_Ntk_t * p, Bac_ObjType_t Type, int Fanin ) { int iObj = Bac_NtkObjNum(p); assert( iObj == Vec_IntSize(&p->vFanin) ); if ( Type == BAC_OBJ_PI ) Vec_IntPush( &p->vInputs, iObj ); else if ( Type == BAC_OBJ_PO ) Vec_IntPush( &p->vOutputs, iObj ); Vec_StrPush( &p->vType, (char)Abc_Var2Lit(Type, 0) ); Vec_IntPush( &p->vFanin, Fanin ); return iObj; } static inline int Bac_ObjDup( Bac_Ntk_t * pNew, Bac_Ntk_t * p, int i ) { int iObj = Bac_ObjAlloc( pNew, Bac_ObjType(p, i), Bac_ObjIsBox(p, i) ? Bac_BoxNtkId(p, i) : -1 ); if ( Bac_NtkHasNames(p) && Bac_NtkHasNames(pNew) && !Bac_ObjIsCo(p, i) ) Bac_ObjSetName( pNew, iObj, Bac_ObjName(p, i) ); Bac_ObjSetCopy( p, i, iObj ); return iObj; } static inline int Bac_BoxAlloc( Bac_Ntk_t * p, Bac_ObjType_t Type, int nIns, int nOuts, int iNtk ) { int i, iObj; for ( i = nIns - 1; i >= 0; i-- ) Bac_ObjAlloc( p, BAC_OBJ_BI, -1 ); iObj = Bac_ObjAlloc( p, Type, iNtk ); for ( i = 0; i < nOuts; i++ ) Bac_ObjAlloc( p, BAC_OBJ_BO, -1 ); return iObj; } static inline int Bac_BoxDup( Bac_Ntk_t * pNew, Bac_Ntk_t * p, int iBox ) { int i, iTerm, iBoxNew; Bac_BoxForEachBiReverse( p, iBox, iTerm, i ) Bac_ObjDup( pNew, p, iTerm ); iBoxNew = Bac_ObjDup( pNew, p, iBox ); if ( Bac_NtkHasNames(p) && Bac_NtkHasNames(pNew) && Bac_ObjName(p, iBox) ) Bac_ObjSetName( pNew, iBoxNew, Bac_ObjName(p, iBox) ); if ( Bac_BoxNtk(p, iBox) ) Bac_BoxSetNtkId( pNew, iBoxNew, Bac_NtkCopy(Bac_BoxNtk(p, iBox)) ); Bac_BoxForEachBo( p, iBox, iTerm, i ) Bac_ObjDup( pNew, p, iTerm ); return iBoxNew; } static inline void Bac_BoxDelete( Bac_Ntk_t * p, int iBox ) { int iStart = iBox - Bac_BoxBiNum(p, iBox); int i, iStop = iBox + Bac_BoxBoNum(p, iBox); for ( i = iStart; i <= iStop; i++ ) { Vec_StrWriteEntry( &p->vType, i, (char)0 ); Vec_IntWriteEntry( &p->vFanin, i, -1 ); if ( Bac_NtkHasNames(p) ) Vec_IntWriteEntry( &p->vName, i, 0 ); if ( Bac_NtkHasFanouts(p) ) Vec_IntWriteEntry( &p->vFanout, i, 0 ); } } static inline void Bac_BoxReplace( Bac_Ntk_t * p, int iBox, int * pArray, int nSize ) { extern void Bac_NtkUpdateFanout( Bac_Ntk_t * p, int iOld, int iNew ); int i, Limit = Bac_BoxBoNum(p, iBox); assert( Limit == nSize ); for ( i = 0; i < Limit; i++ ) Bac_NtkUpdateFanout( p, Bac_BoxBo(p, iBox, i), pArray[i] ); } static inline Vec_Int_t * Bac_BoxCollectRanges( Bac_Ntk_t * p, int iBox ) { static Vec_Int_t Bits, * vBits = &Bits; static int pArray[10]; int i, iTerm; assert( !Bac_ObjIsBoxUser(p, iBox) ); // initialize array vBits->pArray = pArray; vBits->nSize = 0; vBits->nCap = 10; // iterate through inputs Bac_BoxForEachBiMain( p, iBox, iTerm, i ) Vec_IntPush( vBits, Bac_BoxBiRange(p, iTerm) ); // iterate through outputs Bac_BoxForEachBoMain( p, iBox, iTerm, i ) Vec_IntPush( vBits, Bac_BoxBoRange(p, iTerm) ); assert( Vec_IntSize(vBits) < 10 ); //Vec_IntPrint( vBits ); return vBits; } /**Function************************************************************* Synopsis [Prints vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrPrint( Vec_Str_t * p, int fInt ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( fInt ) printf( "%d ", (int)p->pArray[i] ); else printf( "%c ", p->pArray[i] ); printf( "\n" ); } /**Function************************************************************* Synopsis [Network APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Bac_NtkAlloc( Bac_Ntk_t * pNew, int NameId, int nIns, int nOuts, int nObjs ) { int NtkId, fFound; assert( pNew->pDesign != NULL ); assert( Bac_NtkPiNum(pNew) == 0 ); assert( Bac_NtkPoNum(pNew) == 0 ); pNew->NameId = NameId; pNew->iCopy = -1; pNew->iBoxNtk = -1; pNew->iBoxObj = -1; Vec_IntGrow( &pNew->vInputs, nIns ); Vec_IntGrow( &pNew->vOutputs, nOuts ); Vec_StrGrow( &pNew->vType, nObjs ); Vec_IntGrow( &pNew->vFanin, nObjs ); // check if the network is unique NtkId = Abc_NamStrFindOrAdd( pNew->pDesign->pMods, Bac_NtkStr(pNew, NameId), &fFound ); if ( fFound ) printf( "Network with name %s already exists.\n", Bac_NtkStr(pNew, NameId) ); else assert( NtkId == Bac_NtkId(pNew) ); } static inline void Bac_NtkDup( Bac_Ntk_t * pNew, Bac_Ntk_t * p ) { int i, iObj; assert( pNew != p ); Bac_NtkAlloc( pNew, Bac_NtkNameId(p), Bac_NtkPiNum(p), Bac_NtkPoNum(p), Bac_NtkObjNum(p) ); if ( Vec_IntSize(&p->vInfo) ) Vec_IntAppend( &pNew->vInfo, &p->vInfo ); Bac_NtkStartCopies( p ); if ( Bac_NtkHasNames(p) ) Bac_NtkStartNames( pNew ); Bac_NtkForEachPi( p, iObj, i ) Bac_ObjDup( pNew, p, iObj ); Bac_NtkForEachBox( p, iObj ) Bac_BoxDup( pNew, p, iObj ); Bac_NtkForEachPo( p, iObj, i ) Bac_ObjDup( pNew, p, iObj ); Bac_NtkForEachCo( p, iObj ) Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iObj), Bac_ObjCopy(p, Bac_ObjFanin(p, iObj)) ); //Bac_NtkFreeCopies( p ); // needed for name transfer and host ntk assert( Bac_NtkObjNum(pNew) == Bac_NtkObjNumAlloc(pNew) ); } static inline void Bac_NtkDupUserBoxes( Bac_Ntk_t * pNew, Bac_Ntk_t * p ) { int i, iObj; assert( pNew != p ); Bac_NtkAlloc( pNew, Bac_NtkNameId(p), Bac_NtkPiNum(p), Bac_NtkPoNum(p), Bac_NtkObjNum(p) + 3*Bac_NtkCoNum(p) ); if ( Vec_IntSize(&p->vInfo) ) Vec_IntAppend( &pNew->vInfo, &p->vInfo ); Bac_NtkStartCopies( p ); Bac_NtkForEachPi( p, iObj, i ) Bac_ObjDup( pNew, p, iObj ); Bac_NtkForEachPo( p, iObj, i ) Bac_ObjDup( pNew, p, iObj ); Bac_NtkForEachBoxUser( p, iObj ) Bac_BoxDup( pNew, p, iObj ); // connect feed-throughs Bac_NtkForEachCo( p, iObj ) if ( Bac_ObjCopy(p, iObj) >= 0 && Bac_ObjCopy(p, Bac_ObjFanin(p, iObj)) >= 0 ) Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iObj), Bac_ObjCopy(p, Bac_ObjFanin(p, iObj)) ); } static inline void Bac_NtkMoveNames( Bac_Ntk_t * pNew, Bac_Ntk_t * p ) { int i, iBox, iObj; assert( Bac_NtkHasNames(p) ); assert( !Bac_NtkHasNames(pNew) ); Bac_NtkStartNames( pNew ); Bac_NtkForEachPi( p, iObj, i ) Bac_ObjSetName( pNew, Bac_ObjCopy(p, iObj), Bac_ObjName(p, iObj) ); Bac_NtkForEachBoxUser( p, iBox ) { Bac_ObjSetName( pNew, Bac_ObjCopy(p, iBox), Bac_ObjName(p, iBox) ); Bac_BoxForEachBo( p, iBox, iObj, i ) Bac_ObjSetName( pNew, Bac_ObjCopy(p, iObj), Bac_ObjName(p, iObj) ); } Bac_NtkForEachBoxUser( p, iBox ) Bac_BoxForEachBi( p, iBox, iObj, i ) if ( !Bac_ObjName(pNew, Bac_ObjFanin(pNew, Bac_ObjCopy(p, iObj))) ) Bac_ObjSetName( pNew, Bac_ObjFanin(pNew, Bac_ObjCopy(p, iObj)), Bac_ObjName(p, iObj) ); Bac_NtkForEachPo( p, iObj, i ) if ( !Bac_ObjName(pNew, Bac_ObjFanin(pNew, Bac_ObjCopy(p, iObj))) ) Bac_ObjSetName( pNew, Bac_ObjFanin(pNew, Bac_ObjCopy(p, iObj)), Bac_ObjName(p, iObj) ); } static inline void Bac_NtkFree( Bac_Ntk_t * p ) { Vec_IntErase( &p->vInputs ); Vec_IntErase( &p->vOutputs ); Vec_IntErase( &p->vInfo ); Vec_StrErase( &p->vType ); Vec_IntErase( &p->vFanin ); Vec_IntErase( &p->vIndex ); Vec_IntErase( &p->vName ); Vec_IntErase( &p->vFanout ); Vec_IntErase( &p->vCopy ); Vec_IntErase( &p->vArray ); Vec_IntErase( &p->vArray2 ); } static inline int Bac_NtkMemory( Bac_Ntk_t * p ) { int nMem = sizeof(Bac_Ntk_t); nMem += (int)Vec_IntMemory(&p->vInputs); nMem += (int)Vec_IntMemory(&p->vOutputs); nMem += (int)Vec_IntMemory(&p->vInfo); nMem += (int)Vec_StrMemory(&p->vType); nMem += (int)Vec_IntMemory(&p->vFanin); nMem += (int)Vec_IntMemory(&p->vIndex); nMem += (int)Vec_IntMemory(&p->vName); nMem += (int)Vec_IntMemory(&p->vFanout); nMem += (int)Vec_IntMemory(&p->vCopy); return nMem; } static inline void Bac_NtkPrintStats( Bac_Ntk_t * p ) { printf( "pi =%5d ", Bac_NtkPiNum(p) ); printf( "pi =%5d ", Bac_NtkPoNum(p) ); printf( "box =%6d ", Bac_NtkBoxNum(p) ); printf( "clp =%7d ", p->Count ); printf( "obj =%7d ", Bac_NtkObjNum(p) ); printf( "%s ", Bac_NtkName(p) ); if ( Bac_NtkHostNtk(p) > 0 ) printf( "-> %s", Bac_NtkName(Bac_NtkHostNtk(p)) ); printf( "\n" ); } static inline void Bac_NtkDeriveIndex( Bac_Ntk_t * p ) { int i, iObj, iTerm; Vec_IntFill( &p->vIndex, Bac_NtkObjNum(p), -1 ); Bac_NtkForEachPi( p, iObj, i ) Bac_ObjSetIndex( p, iObj, i ); Bac_NtkForEachPo( p, iObj, i ) Bac_ObjSetIndex( p, iObj, i ); Bac_NtkForEachBox( p, iObj ) { Bac_BoxForEachBi( p, iObj, iTerm, i ) Bac_ObjSetIndex( p, iTerm, i ); Bac_BoxForEachBo( p, iObj, iTerm, i ) Bac_ObjSetIndex( p, iTerm, i ); } } static inline void Bac_NtkPrint( Bac_Ntk_t * p ) { int i, Type, Value, Beg, End; printf( "Interface (%d):\n", Bac_NtkInfoNum(p) ); Vec_IntForEachEntryTriple( &p->vInfo, Value, Beg, End, i ) { printf( "%6d : ", i ); printf( "Type =%3d ", Bac_NtkInfoType(p, i/3) ); if ( Beg >= 0 ) printf( "[%d:%d] ", End, Beg ); else printf( " " ); printf( "Name =%3d ", Bac_NtkInfoName(p, i/3) ); if ( Bac_NtkInfoName(p, i/3) ) printf( "%s", Bac_NtkStr( p, Bac_NtkInfoName(p, i/3) ) ); printf( "\n" ); } printf( "Objects (%d):\n", Bac_NtkObjNum(p) ); Bac_NtkForEachObjType( p, Type, i ) { printf( "%6d : ", i ); printf( "Type =%3d ", Type ); if ( Bac_ObjIsCo(p, i) ) printf( "Fanin =%6d ", Bac_ObjFanin(p, i) ); else if ( Bac_NtkHasNames(p) && Bac_ObjName(p, i) ) { printf( "Name =%6d(%d) ", Bac_ObjNameId(p, i), Bac_ObjNameType(p, i) ); if ( Bac_ObjNameType(p, i) <= BAC_NAME_WORD ) printf( "%s", Bac_ObjNameStr(p, i) ); } printf( "\n" ); } } /**Function************************************************************* Synopsis [Manager APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Bac_Man_t * Bac_ManAlloc( char * pFileName, int nNtks ) { extern void Bac_ManSetupTypes( char ** pNames, char ** pSymbs ); Bac_Ntk_t * pNtk; int i; Bac_Man_t * pNew = ABC_CALLOC( Bac_Man_t, 1 ); pNew->pName = Extra_FileDesignName( pFileName ); pNew->pSpec = Abc_UtilStrsav( pFileName ); pNew->pStrs = Abc_NamStart( 1000, 24 ); pNew->pMods = Abc_NamStart( 1000, 24 ); pNew->iRoot = 1; pNew->nNtks = nNtks; pNew->pNtks = ABC_CALLOC( Bac_Ntk_t, pNew->nNtks + 1 ); Bac_ManForEachNtk( pNew, pNtk, i ) pNtk->pDesign = pNew; Bac_ManSetupTypes( pNew->pPrimNames, pNew->pPrimSymbs ); return pNew; } static inline Bac_Man_t * Bac_ManStart( Bac_Man_t * p, int nNtks ) { Bac_Ntk_t * pNtk; int i; Bac_Man_t * pNew = ABC_CALLOC( Bac_Man_t, 1 ); pNew->pName = Abc_UtilStrsav( Bac_ManName(p) ); pNew->pSpec = Abc_UtilStrsav( Bac_ManSpec(p) ); pNew->pStrs = Abc_NamRef( p->pStrs ); pNew->pMods = Abc_NamStart( 1000, 24 ); pNew->iRoot = 1; pNew->nNtks = nNtks; pNew->pNtks = ABC_CALLOC( Bac_Ntk_t, nNtks + 1 ); Bac_ManForEachNtk( pNew, pNtk, i ) pNtk->pDesign = pNew; return pNew; } static inline Bac_Man_t * Bac_ManDup( Bac_Man_t * p ) { Bac_Ntk_t * pNtk, * pHost; int i; Bac_Man_t * pNew = Bac_ManStart( p, Bac_ManNtkNum(p) ); Bac_ManForEachNtk( p, pNtk, i ) Bac_NtkSetCopy( pNtk, i ); Bac_ManForEachNtk( p, pNtk, i ) Bac_NtkDup( Bac_NtkCopyNtk(pNew, pNtk), pNtk ); Bac_ManForEachNtk( p, pNtk, i ) if ( (pHost = Bac_NtkHostNtk(pNtk)) ) Bac_NtkSetHost( Bac_NtkCopyNtk(pNew, pNtk), Bac_NtkCopy(pHost), Bac_ObjCopy(pHost, Bac_NtkHostObj(pNtk)) ); return pNew; } static inline Bac_Man_t * Bac_ManDupUserBoxes( Bac_Man_t * p ) { Bac_Ntk_t * pNtk, * pHost; int i; Bac_Man_t * pNew = Bac_ManStart( p, Bac_ManNtkNum(p) ); Bac_ManForEachNtk( p, pNtk, i ) Bac_NtkSetCopy( pNtk, i ); Bac_ManForEachNtk( p, pNtk, i ) Bac_NtkDupUserBoxes( Bac_NtkCopyNtk(pNew, pNtk), pNtk ); Bac_ManForEachNtk( p, pNtk, i ) if ( (pHost = Bac_NtkHostNtk(pNtk)) ) Bac_NtkSetHost( Bac_NtkCopyNtk(pNew, pNtk), Bac_NtkCopy(pHost), Bac_ObjCopy(pHost, Bac_NtkHostObj(pNtk)) ); return pNew; } static inline void Bac_ManMoveNames( Bac_Man_t * pNew, Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int i; Bac_ManForEachNtk( p, pNtk, i ) Bac_NtkMoveNames( Bac_NtkCopyNtk(pNew, pNtk), pNtk ); } static inline void Bac_ManFree( Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int i; Bac_ManForEachNtk( p, pNtk, i ) Bac_NtkFree( pNtk ); Vec_IntErase( &p->vBuf2LeafNtk ); Vec_IntErase( &p->vBuf2LeafObj ); Vec_IntErase( &p->vBuf2RootNtk ); Vec_IntErase( &p->vBuf2RootObj ); Abc_NamDeref( p->pStrs ); Abc_NamDeref( p->pMods ); ABC_FREE( p->pName ); ABC_FREE( p->pSpec ); ABC_FREE( p->pNtks ); ABC_FREE( p ); } static inline int Bac_ManMemory( Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int i; int nMem = sizeof(Bac_Man_t); if ( p->pName ) nMem += (int)strlen(p->pName); if ( p->pSpec ) nMem += (int)strlen(p->pSpec); nMem += Abc_NamMemUsed(p->pStrs); nMem += Abc_NamMemUsed(p->pMods); Bac_ManForEachNtk( p, pNtk, i ) nMem += Bac_NtkMemory( pNtk ); return nMem; } static inline int Bac_ManObjNum( Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int i, Count = 0; Bac_ManForEachNtk( p, pNtk, i ) Count += Bac_NtkObjNum(pNtk); return Count; } static inline int Bac_ManNodeNum( Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int i, Count = 0; Bac_ManForEachNtk( p, pNtk, i ) Count += Bac_NtkBoxNum( pNtk ); return Count; } static inline int Bac_ManBoxNum_rec( Bac_Ntk_t * p ) { int iObj, Counter = 0; if ( p->Count >= 0 ) return p->Count; Bac_NtkForEachBox( p, iObj ) Counter += Bac_ObjIsBoxUser(p, iObj) ? Bac_ManBoxNum_rec( Bac_BoxNtk(p, iObj) ) : 1; return (p->Count = Counter); } static inline int Bac_ManBoxNum( Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int i; Bac_ManForEachNtk( p, pNtk, i ) pNtk->Count = -1; return Bac_ManBoxNum_rec( Bac_ManRoot(p) ); } static inline void Bac_ManPrintStats( Bac_Man_t * p, int nModules, int fVerbose ) { Bac_Ntk_t * pNtk; int i; Bac_Ntk_t * pRoot = Bac_ManRoot( p ); printf( "%-12s : ", Bac_ManName(p) ); printf( "pi =%5d ", Bac_NtkPiNum(pRoot) ); printf( "po =%5d ", Bac_NtkPoNum(pRoot) ); printf( "pri =%4d ", Bac_ManPrimNum(p) ); printf( "mod =%6d ", Bac_ManNtkNum(p) ); printf( "box =%7d ", Bac_ManNodeNum(p) ); printf( "obj =%7d ", Bac_ManObjNum(p) ); printf( "mem =%6.3f MB", 1.0*Bac_ManMemory(p)/(1<<20) ); printf( "\n" ); Bac_ManBoxNum( p ); Bac_ManForEachNtk( p, pNtk, i ) { if ( i == nModules+1 ) break; printf( "Module %5d : ", i ); Bac_NtkPrintStats( pNtk ); } } /**Function************************************************************* Synopsis [Other APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Bac_ObjType_t Ptr_SopToType( char * pSop ) { if ( !strcmp(pSop, " 0\n") ) return BAC_BOX_CF; if ( !strcmp(pSop, " 1\n") ) return BAC_BOX_CT; if ( !strcmp(pSop, "1 1\n") ) return BAC_BOX_BUF; if ( !strcmp(pSop, "0 1\n") ) return BAC_BOX_INV; if ( !strcmp(pSop, "11 1\n") ) return BAC_BOX_AND; if ( !strcmp(pSop, "00 1\n") ) return BAC_BOX_NOR; if ( !strcmp(pSop, "00 0\n") ) return BAC_BOX_OR; if ( !strcmp(pSop, "-1 1\n1- 1\n") ) return BAC_BOX_OR; if ( !strcmp(pSop, "1- 1\n-1 1\n") ) return BAC_BOX_OR; if ( !strcmp(pSop, "01 1\n10 1\n") ) return BAC_BOX_XOR; if ( !strcmp(pSop, "10 1\n01 1\n") ) return BAC_BOX_XOR; if ( !strcmp(pSop, "11 1\n00 1\n") ) return BAC_BOX_XNOR; if ( !strcmp(pSop, "00 1\n11 1\n") ) return BAC_BOX_XNOR; if ( !strcmp(pSop, "10 1\n") ) return BAC_BOX_SHARP; if ( !strcmp(pSop, "01 1\n") ) return BAC_BOX_SHARPL; assert( 0 ); return BAC_OBJ_NONE; } static inline char * Ptr_SopToTypeName( char * pSop ) { if ( !strcmp(pSop, " 0\n") ) return "BAC_BOX_C0"; if ( !strcmp(pSop, " 1\n") ) return "BAC_BOX_C1"; if ( !strcmp(pSop, "1 1\n") ) return "BAC_BOX_BUF"; if ( !strcmp(pSop, "0 1\n") ) return "BAC_BOX_INV"; if ( !strcmp(pSop, "11 1\n") ) return "BAC_BOX_AND"; if ( !strcmp(pSop, "00 1\n") ) return "BAC_BOX_NOR"; if ( !strcmp(pSop, "00 0\n") ) return "BAC_BOX_OR"; if ( !strcmp(pSop, "-1 1\n1- 1\n") ) return "BAC_BOX_OR"; if ( !strcmp(pSop, "1- 1\n-1 1\n") ) return "BAC_BOX_OR"; if ( !strcmp(pSop, "01 1\n10 1\n") ) return "BAC_BOX_XOR"; if ( !strcmp(pSop, "10 1\n01 1\n") ) return "BAC_BOX_XOR"; if ( !strcmp(pSop, "11 1\n00 1\n") ) return "BAC_BOX_XNOR"; if ( !strcmp(pSop, "00 1\n11 1\n") ) return "BAC_BOX_XNOR"; if ( !strcmp(pSop, "10 1\n") ) return "BAC_BOX_SHARP"; if ( !strcmp(pSop, "01 1\n") ) return "BAC_BOX_SHARPL"; assert( 0 ); return NULL; } static inline char * Ptr_TypeToName( Bac_ObjType_t Type ) { if ( Type == BAC_BOX_CF ) return "const0"; if ( Type == BAC_BOX_CT ) return "const1"; if ( Type == BAC_BOX_CX ) return "constX"; if ( Type == BAC_BOX_CZ ) return "constZ"; if ( Type == BAC_BOX_BUF ) return "buf"; if ( Type == BAC_BOX_INV ) return "not"; if ( Type == BAC_BOX_AND ) return "and"; if ( Type == BAC_BOX_NAND ) return "nand"; if ( Type == BAC_BOX_OR ) return "or"; if ( Type == BAC_BOX_NOR ) return "nor"; if ( Type == BAC_BOX_XOR ) return "xor"; if ( Type == BAC_BOX_XNOR ) return "xnor"; if ( Type == BAC_BOX_MUX ) return "mux"; if ( Type == BAC_BOX_MAJ ) return "maj"; if ( Type == BAC_BOX_SHARP ) return "sharp"; if ( Type == BAC_BOX_SHARPL) return "sharpl"; assert( 0 ); return "???"; } static inline char * Ptr_TypeToSop( Bac_ObjType_t Type ) { if ( Type == BAC_BOX_CF ) return " 0\n"; if ( Type == BAC_BOX_CT ) return " 1\n"; if ( Type == BAC_BOX_CX ) return " 0\n"; if ( Type == BAC_BOX_CZ ) return " 0\n"; if ( Type == BAC_BOX_BUF ) return "1 1\n"; if ( Type == BAC_BOX_INV ) return "0 1\n"; if ( Type == BAC_BOX_AND ) return "11 1\n"; if ( Type == BAC_BOX_NAND ) return "11 0\n"; if ( Type == BAC_BOX_OR ) return "00 0\n"; if ( Type == BAC_BOX_NOR ) return "00 1\n"; if ( Type == BAC_BOX_XOR ) return "01 1\n10 1\n"; if ( Type == BAC_BOX_XNOR ) return "00 1\n11 1\n"; if ( Type == BAC_BOX_SHARP ) return "10 1\n"; if ( Type == BAC_BOX_SHARPL) return "01 1\n"; if ( Type == BAC_BOX_MUX ) return "11- 1\n0-1 1\n"; if ( Type == BAC_BOX_MAJ ) return "11- 1\n1-1 1\n-11 1\n"; assert( 0 ); return "???"; } /*=== bacCom.c ===============================================================*/ extern void Abc_FrameImportPtr( Vec_Ptr_t * vPtr ); extern Vec_Ptr_t * Abc_FrameExportPtr(); /*=== bacBlast.c =============================================================*/ extern int Bac_NtkBuildLibrary( Bac_Man_t * p ); extern Gia_Man_t * Bac_ManExtract( Bac_Man_t * p, int fBuffers, int fVerbose ); extern Bac_Man_t * Bac_ManInsertGia( Bac_Man_t * p, Gia_Man_t * pGia ); extern void * Bac_ManInsertAbc( Bac_Man_t * p, void * pAbc ); /*=== bacCba.c ===============================================================*/ extern Bac_Man_t * Bac_ManReadBac( char * pFileName ); extern void Bac_ManWriteBac( char * pFileName, Bac_Man_t * p ); /*=== bacNtk.c ===============================================================*/ extern char * Bac_NtkGenerateName( Bac_Ntk_t * p, Bac_ObjType_t Type, Vec_Int_t * vBits ); extern Bac_ObjType_t Bac_NameToType( char * pName ); extern Vec_Int_t * Bac_NameToRanges( char * pName ); extern void Bac_NtkUpdateFanout( Bac_Ntk_t * p, int iOld, int iNew ); extern void Bac_ManDeriveFanout( Bac_Man_t * p ); //extern void Bac_ManAssignInternNames( Bac_Man_t * p ); extern void Bac_ManAssignInternWordNames( Bac_Man_t * p ); extern Bac_Man_t * Bac_ManCollapse( Bac_Man_t * p ); extern void Bac_ManSetupTypes( char ** pNames, char ** pSymbs ); /*=== bacPtr.c ===============================================================*/ extern void Bac_PtrFree( Vec_Ptr_t * vDes ); extern int Bac_PtrMemory( Vec_Ptr_t * vDes ); extern void Bac_PtrDumpBlif( char * pFileName, Vec_Ptr_t * vDes ); extern void Bac_PtrDumpVerilog( char * pFileName, Vec_Ptr_t * vDes ); extern Vec_Ptr_t * Bac_PtrTransformTest( Vec_Ptr_t * vDes ); /*=== bacPtrAbc.c ============================================================*/ extern Bac_Man_t * Bac_PtrTransformToCba( Vec_Ptr_t * vDes ); extern Vec_Ptr_t * Bac_PtrDeriveFromCba( Bac_Man_t * p ); /*=== bacPrsBuild.c ==========================================================*/ extern Bac_Man_t * Psr_ManBuildCba( char * pFileName, Vec_Ptr_t * vDes ); /*=== bacReadBlif.c ==========================================================*/ extern Vec_Ptr_t * Psr_ManReadBlif( char * pFileName ); /*=== bacReadSmt.c ===========================================================*/ extern Vec_Ptr_t * Psr_ManReadSmt( char * pFileName ); /*=== bacReadVer.c ===========================================================*/ extern Vec_Ptr_t * Psr_ManReadVerilog( char * pFileName ); /*=== bacWriteBlif.c =========================================================*/ extern void Psr_ManWriteBlif( char * pFileName, Vec_Ptr_t * p ); extern void Bac_ManWriteBlif( char * pFileName, Bac_Man_t * p ); /*=== bacWriteVer.c ==========================================================*/ extern void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * p ); extern void Bac_ManWriteVerilog( char * pFileName, Bac_Man_t * p, int fUseAssign ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacBac.c000066400000000000000000000224521300674244400227770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacBac.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Verilog parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacBac.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Read CBA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int BacManReadBacLine( Vec_Str_t * vOut, int * pPos, char * pBuffer, char * pLimit ) { char c; while ( (c = Vec_StrEntry(vOut, (*pPos)++)) != '\n' && pBuffer < pLimit ) *pBuffer++ = c; *pBuffer = 0; return pBuffer < pLimit; } int BacManReadBacNameAndNums( char * pBuffer, int * Num1, int * Num2, int * Num3, int * Num4 ) { *Num1 = *Num2 = *Num3 = *Num4 = -1; // read name while ( *pBuffer && *pBuffer != ' ' ) pBuffer++; if ( !*pBuffer ) return 0; assert( *pBuffer == ' ' ); *pBuffer = 0; // read Num1 *Num1 = atoi(++pBuffer); while ( *pBuffer && *pBuffer != ' ' ) pBuffer++; if ( !*pBuffer ) return 0; // read Num2 assert( *pBuffer == ' ' ); *Num2 = atoi(++pBuffer); while ( *pBuffer && *pBuffer != ' ' ) pBuffer++; if ( !*pBuffer ) return 1; // read Num3 assert( *pBuffer == ' ' ); *Num3 = atoi(++pBuffer); while ( *pBuffer && *pBuffer != ' ' ) pBuffer++; if ( !*pBuffer ) return 1; // read Num4 assert( *pBuffer == ' ' ); *Num4 = atoi(++pBuffer); return 1; } void Bac_ManReadBacVecStr( Vec_Str_t * vOut, int * pPos, Vec_Str_t * p, int nSize ) { memcpy( Vec_StrArray(p), Vec_StrArray(vOut) + *pPos, nSize ); *pPos += nSize; p->nSize = nSize; assert( Vec_StrSize(p) == Vec_StrCap(p) ); } void Bac_ManReadBacVecInt( Vec_Str_t * vOut, int * pPos, Vec_Int_t * p, int nSize ) { memcpy( Vec_IntArray(p), Vec_StrArray(vOut) + *pPos, nSize ); *pPos += nSize; p->nSize = nSize / 4; assert( Vec_IntSize(p) == Vec_IntCap(p) ); } void Bac_ManReadBacNtk( Vec_Str_t * vOut, int * pPos, Bac_Ntk_t * pNtk ) { int i, Type; //char * pName; int iObj, NameId; Bac_ManReadBacVecStr( vOut, pPos, &pNtk->vType, Bac_NtkObjNumAlloc(pNtk) ); Bac_ManReadBacVecInt( vOut, pPos, &pNtk->vFanin, 4 * Bac_NtkObjNumAlloc(pNtk) ); Bac_ManReadBacVecInt( vOut, pPos, &pNtk->vInfo, 12 * Bac_NtkInfoNumAlloc(pNtk) ); Bac_NtkForEachObjType( pNtk, Type, i ) { if ( Type == BAC_OBJ_PI ) Vec_IntPush( &pNtk->vInputs, i ); if ( Type == BAC_OBJ_PO ) Vec_IntPush( &pNtk->vOutputs, i ); } assert( Bac_NtkPiNum(pNtk) == Bac_NtkPiNumAlloc(pNtk) ); assert( Bac_NtkPoNum(pNtk) == Bac_NtkPoNumAlloc(pNtk) ); assert( Bac_NtkObjNum(pNtk) == Bac_NtkObjNumAlloc(pNtk) ); assert( Bac_NtkInfoNum(pNtk) == Bac_NtkInfoNumAlloc(pNtk) ); /* // read input/output/box names Bac_NtkForEachPiMain( pNtk, iObj, i ) { pName = Vec_StrEntryP( vOut, Pos ); NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL ); Pos += strlen(pName) + 1; } Bac_NtkForEachPoMain( pNtk, iObj, i ) { pName = Vec_StrEntryP( vOut, Pos ); NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL ); Pos += strlen(pName) + 1; } Bac_NtkForEachBox( pNtk, iObj ) { pName = Vec_StrEntryP( vOut, Pos ); NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL ); Pos += strlen(pName) + 1; } */ } Bac_Man_t * Bac_ManReadBacInt( Vec_Str_t * vOut ) { Bac_Man_t * p; Bac_Ntk_t * pNtk; char Buffer[1000] = "#"; int i, NameId, Pos = 0, nNtks, Num1, Num2, Num3, Num4; while ( Buffer[0] == '#' ) if ( !BacManReadBacLine(vOut, &Pos, Buffer, Buffer+1000) ) return NULL; if ( !BacManReadBacNameAndNums(Buffer, &nNtks, &Num2, &Num3, &Num4) ) return NULL; // start manager assert( nNtks > 0 ); p = Bac_ManAlloc( Buffer, nNtks ); // start networks Bac_ManForEachNtk( p, pNtk, i ) { if ( !BacManReadBacLine(vOut, &Pos, Buffer, Buffer+1000) ) { Bac_ManFree( p ); return NULL; } if ( !BacManReadBacNameAndNums(Buffer, &Num1, &Num2, &Num3, &Num4) ) { Bac_ManFree( p ); return NULL; } assert( Num1 >= 0 && Num2 >= 0 && Num3 >= 0 ); NameId = Abc_NamStrFindOrAdd( p->pStrs, Buffer, NULL ); Bac_NtkAlloc( pNtk, NameId, Num1, Num2, Num3 ); Vec_IntFill( &pNtk->vInfo, 3 * Num4, -1 ); } // read networks Bac_ManForEachNtk( p, pNtk, i ) Bac_ManReadBacNtk( vOut, &Pos, pNtk ); assert( Bac_ManNtkNum(p) == nNtks ); assert( Pos == Vec_StrSize(vOut) ); return p; } Bac_Man_t * Bac_ManReadBac( char * pFileName ) { Bac_Man_t * p; FILE * pFile; Vec_Str_t * vOut; int nFileSize; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return NULL; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); rewind( pFile ); // load the contents vOut = Vec_StrAlloc( nFileSize ); vOut->nSize = vOut->nCap; assert( nFileSize == Vec_StrSize(vOut) ); nFileSize = fread( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); assert( nFileSize == Vec_StrSize(vOut) ); fclose( pFile ); // read the networks p = Bac_ManReadBacInt( vOut ); if ( p != NULL ) { ABC_FREE( p->pSpec ); p->pSpec = Abc_UtilStrsav( pFileName ); } Vec_StrFree( vOut ); return p; } /**Function************************************************************* Synopsis [Write CBA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_ManWriteBacNtk( Vec_Str_t * vOut, Bac_Ntk_t * pNtk ) { //char * pName; int iObj, NameId; Vec_StrPushBuffer( vOut, (char *)Vec_StrArray(&pNtk->vType), Bac_NtkObjNum(pNtk) ); Vec_StrPushBuffer( vOut, (char *)Vec_IntArray(&pNtk->vFanin), 4 * Bac_NtkObjNum(pNtk) ); Vec_StrPushBuffer( vOut, (char *)Vec_IntArray(&pNtk->vInfo), 12 * Bac_NtkInfoNum(pNtk) ); /* // write input/output/box names Bac_NtkForEachPiMain( pNtk, iObj, i ) { pName = Bac_ObjNameStr( pNtk, iObj ); Vec_StrPrintStr( vOut, pName ); Vec_StrPush( vOut, '\0' ); } Bac_NtkForEachPoMain( pNtk, iObj, i ) { pName = Bac_ObjNameStr( pNtk, iObj ); Vec_StrPrintStr( vOut, pName ); Vec_StrPush( vOut, '\0' ); } Bac_NtkForEachBox( pNtk, iObj ) { pName = Bac_ObjNameStr( pNtk, iObj ); Vec_StrPrintStr( vOut, pName ); Vec_StrPush( vOut, '\0' ); } */ } void Bac_ManWriteBacInt( Vec_Str_t * vOut, Bac_Man_t * p ) { char Buffer[1000]; Bac_Ntk_t * pNtk; int i; sprintf( Buffer, "# Design \"%s\" written by ABC on %s\n", Bac_ManName(p), Extra_TimeStamp() ); Vec_StrPrintStr( vOut, Buffer ); // write short info sprintf( Buffer, "%s %d \n", Bac_ManName(p), Bac_ManNtkNum(p) ); Vec_StrPrintStr( vOut, Buffer ); Bac_ManForEachNtk( p, pNtk, i ) { sprintf( Buffer, "%s %d %d %d %d \n", Bac_NtkName(pNtk), Bac_NtkPiNum(pNtk), Bac_NtkPoNum(pNtk), Bac_NtkObjNum(pNtk), Bac_NtkInfoNum(pNtk) ); Vec_StrPrintStr( vOut, Buffer ); } Bac_ManForEachNtk( p, pNtk, i ) Bac_ManWriteBacNtk( vOut, pNtk ); } void Bac_ManWriteBac( char * pFileName, Bac_Man_t * p ) { Vec_Str_t * vOut; assert( p->pMioLib == NULL ); vOut = Vec_StrAlloc( 10000 ); Bac_ManWriteBacInt( vOut, p ); if ( Vec_StrSize(vOut) > 0 ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); fclose( pFile ); } } Vec_StrFree( vOut ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacBlast.c000066400000000000000000000536471300674244400233710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacBlast.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Bit-blasting of the netlist.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacBlast.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "base/abc/abc.h" #include "map/mio/mio.h" #include "bool/dec/dec.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_ManPrepareGates( Bac_Man_t * p ) { Dec_Graph_t ** ppGraphs; int i; if ( p->pMioLib == NULL ) return; ppGraphs = ABC_CALLOC( Dec_Graph_t *, Abc_NamObjNumMax(p->pMods) ); for ( i = 1; i < Abc_NamObjNumMax(p->pMods); i++ ) { char * pGateName = Abc_NamStr( p->pMods, i ); Mio_Gate_t * pGate = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pMioLib, pGateName, NULL ); if ( pGate != NULL ) ppGraphs[i] = Dec_Factor( Mio_GateReadSop(pGate) ); } assert( p->ppGraphs == NULL ); p->ppGraphs = (void **)ppGraphs; } void Bac_ManUndoGates( Bac_Man_t * p ) { int i; if ( p->pMioLib == NULL ) return; for ( i = 1; i < Abc_NamObjNumMax(p->pMods); i++ ) if ( p->ppGraphs[i] ) Dec_GraphFree( (Dec_Graph_t *)p->ppGraphs[i] ); ABC_FREE( p->ppGraphs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_ManAddBarbuf( Gia_Man_t * pNew, int iRes, Bac_Man_t * p, int iLNtk, int iLObj, int iRNtk, int iRObj, Vec_Int_t * vMap ) { int iBufLit, iIdLit; if ( iRes == 0 || iRes == 1 ) return iRes; assert( iRes > 0 ); if ( vMap && Abc_Lit2Var(iRes) < Vec_IntSize(vMap) && (iIdLit = Vec_IntEntry(vMap, Abc_Lit2Var(iRes))) >= 0 && Vec_IntEntry(&p->vBuf2LeafNtk, Abc_Lit2Var(iIdLit)) == iLNtk && Vec_IntEntry(&p->vBuf2RootNtk, Abc_Lit2Var(iIdLit)) == iRNtk ) return Abc_LitNotCond( Vec_IntEntry(pNew->vBarBufs, Abc_Lit2Var(iIdLit)), Abc_LitIsCompl(iRes) ^ Abc_LitIsCompl(iIdLit) ); assert( Bac_ManNtkIsOk(p, iLNtk) && Bac_ManNtkIsOk(p, iRNtk) ); Vec_IntPush( &p->vBuf2LeafNtk, iLNtk ); Vec_IntPush( &p->vBuf2LeafObj, iLObj ); Vec_IntPush( &p->vBuf2RootNtk, iRNtk ); Vec_IntPush( &p->vBuf2RootObj, iRObj ); iBufLit = Gia_ManAppendBuf( pNew, iRes ); if ( vMap ) { Vec_IntSetEntryFull( vMap, Abc_Lit2Var(iRes), Abc_Var2Lit(Vec_IntSize(pNew->vBarBufs), Abc_LitIsCompl(iRes)) ); Vec_IntPush( pNew->vBarBufs, iBufLit ); } return iBufLit; } int Bac_ManExtract_rec( Gia_Man_t * pNew, Bac_Ntk_t * p, int i, int fBuffers, Vec_Int_t * vMap ) { int iRes = Bac_ObjCopy( p, i ); if ( iRes >= 0 ) return iRes; if ( Bac_ObjIsCo(p, i) ) iRes = Bac_ManExtract_rec( pNew, p, Bac_ObjFanin(p, i), fBuffers, vMap ); else if ( Bac_ObjIsPi(p, i) ) { Bac_Ntk_t * pHost = Bac_NtkHostNtk( p ); int iObj = Bac_BoxBi( pHost, Bac_NtkHostObj(p), Bac_ObjIndex(p, i) ); iRes = Bac_ManExtract_rec( pNew, pHost, iObj, fBuffers, vMap ); if ( fBuffers ) iRes = Bac_ManAddBarbuf( pNew, iRes, p->pDesign, Bac_NtkId(p), i, Bac_NtkId(pHost), iObj, vMap ); } else if ( Bac_ObjIsBo(p, i) ) { int iBox = Bac_BoxBoBox(p, i); if ( Bac_ObjIsBoxUser(p, iBox) ) // user box { Bac_Ntk_t * pBox = Bac_BoxBoNtk( p, i ); int iObj = Bac_NtkPo( pBox, Bac_ObjIndex(p, i) ); iRes = Bac_ManExtract_rec( pNew, pBox, iObj, fBuffers, vMap ); if ( fBuffers ) iRes = Bac_ManAddBarbuf( pNew, iRes, p->pDesign, Bac_NtkId(p), i, Bac_NtkId(pBox), iObj, vMap ); } else // primitive { int iFanin, nLits, pLits[16]; assert( Bac_ObjIsBoxPrim(p, iBox) ); Bac_BoxForEachFanin( p, iBox, iFanin, nLits ) pLits[nLits] = Bac_ManExtract_rec( pNew, p, iFanin, fBuffers, vMap ); assert( nLits <= 16 ); if ( p->pDesign->ppGraphs ) // mapped gate { extern int Gia_ManFactorGraph( Gia_Man_t * p, Dec_Graph_t * pFForm, Vec_Int_t * vLeaves ); Dec_Graph_t * pGraph = (Dec_Graph_t *)p->pDesign->ppGraphs[Bac_BoxNtkId(p, iBox)]; Vec_Int_t Leaves = { nLits, nLits, pLits }; assert( pGraph != NULL ); return Gia_ManFactorGraph( pNew, pGraph, &Leaves ); } else { Bac_ObjType_t Type = Bac_ObjType(p, iBox); if ( nLits == 0 ) { if ( Type == BAC_BOX_CF ) iRes = 0; else if ( Type == BAC_BOX_CT ) iRes = 1; else assert( 0 ); } else if ( nLits == 1 ) { if ( Type == BAC_BOX_BUF ) iRes = pLits[0]; else if ( Type == BAC_BOX_INV ) iRes = Abc_LitNot( pLits[0] ); else assert( 0 ); } else if ( nLits == 2 ) { if ( Type == BAC_BOX_AND ) iRes = Gia_ManHashAnd( pNew, pLits[0], pLits[1] ); else if ( Type == BAC_BOX_NAND ) iRes = Abc_LitNot( Gia_ManHashAnd( pNew, pLits[0], pLits[1] ) ); else if ( Type == BAC_BOX_OR ) iRes = Gia_ManHashOr( pNew, pLits[0], pLits[1] ); else if ( Type == BAC_BOX_NOR ) iRes = Abc_LitNot( Gia_ManHashOr( pNew, pLits[0], pLits[1] ) ); else if ( Type == BAC_BOX_XOR ) iRes = Gia_ManHashXor( pNew, pLits[0], pLits[1] ); else if ( Type == BAC_BOX_XNOR ) iRes = Abc_LitNot( Gia_ManHashXor( pNew, pLits[0], pLits[1] ) ); else if ( Type == BAC_BOX_SHARP ) iRes = Gia_ManHashAnd( pNew, pLits[0], Abc_LitNot(pLits[1]) ); else if ( Type == BAC_BOX_SHARPL ) iRes = Gia_ManHashAnd( pNew, Abc_LitNot(pLits[0]), pLits[1] ); else assert( 0 ); } else if ( nLits == 3 ) { if ( Type == BAC_BOX_MUX ) iRes = Gia_ManHashMux( pNew, pLits[0], pLits[1], pLits[2] ); else if ( Type == BAC_BOX_MAJ ) iRes = Gia_ManHashMaj( pNew, pLits[0], pLits[1], pLits[2] ); else if ( Type == BAC_BOX_ADD ) { int iRes0 = Gia_ManHashAnd( pNew, pLits[1], pLits[2] ); int iRes1 = Gia_ManHashOr( pNew, pLits[1], pLits[2] ); assert( Bac_BoxBoNum(p, iBox) == 2 ); if ( Bac_BoxBo(p, iBox, 0) == i ) // sum iRes = Gia_ManHashXor( pNew, pLits[0], Gia_ManHashAnd(pNew, Abc_LitNot(iRes0), iRes1) ); else if ( Bac_BoxBo(p, iBox, 1) == i ) // cout iRes = Gia_ManHashOr( pNew, iRes0, Gia_ManHashAnd(pNew, pLits[0], iRes1) ); else assert( 0 ); } else assert( 0 ); } else assert( 0 ); } } } else assert( 0 ); Bac_ObjSetCopy( p, i, iRes ); return iRes; } Gia_Man_t * Bac_ManExtract( Bac_Man_t * p, int fBuffers, int fVerbose ) { Bac_Ntk_t * pNtk, * pRoot = Bac_ManRoot(p); Gia_Man_t * pNew, * pTemp; Vec_Int_t * vMap = NULL; int i, iObj; Vec_IntClear( &p->vBuf2LeafNtk ); Vec_IntClear( &p->vBuf2LeafObj ); Vec_IntClear( &p->vBuf2RootNtk ); Vec_IntClear( &p->vBuf2RootObj ); Bac_ManForEachNtk( p, pNtk, i ) { Bac_NtkDeriveIndex( pNtk ); Bac_NtkStartCopies( pNtk ); } // start the manager pNew = Gia_ManStart( Bac_ManNodeNum(p) ); pNew->pName = Abc_UtilStrsav(p->pName); pNew->pSpec = Abc_UtilStrsav(p->pSpec); // primary inputs Bac_NtkForEachPi( pRoot, iObj, i ) Bac_ObjSetCopy( pRoot, iObj, Gia_ManAppendCi(pNew) ); // internal nodes Gia_ManHashAlloc( pNew ); pNew->vBarBufs = Vec_IntAlloc( 10000 ); vMap = Vec_IntStartFull( 10000 ); Bac_ManPrepareGates( p ); Bac_NtkForEachPo( pRoot, iObj, i ) Bac_ManExtract_rec( pNew, pRoot, iObj, fBuffers, vMap ); Bac_ManUndoGates( p ); Vec_IntFreeP( &vMap ); Gia_ManHashStop( pNew ); // primary outputs Bac_NtkForEachPo( pRoot, iObj, i ) Gia_ManAppendCo( pNew, Bac_ObjCopy(pRoot, iObj) ); assert( Vec_IntSize(&p->vBuf2LeafNtk) == pNew->nBufs ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); //Gia_ManPrintStats( pNew, NULL ); return pNew; } /**Function************************************************************* Synopsis [Mark each GIA node with the network it belongs to.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_ManMarkNodesGia( Bac_Man_t * p, Gia_Man_t * pGia ) { Gia_Obj_t * pObj; int i, Count = 0; assert( Vec_IntSize(&p->vBuf2LeafNtk) == Gia_ManBufNum(pGia) ); Gia_ManConst0(pGia)->Value = 1; Gia_ManForEachPi( pGia, pObj, i ) pObj->Value = 1; Gia_ManForEachAnd( pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) pObj->Value = Vec_IntEntry( &p->vBuf2LeafNtk, Count++ ); else { pObj->Value = Gia_ObjFanin0(pObj)->Value; assert( pObj->Value == Gia_ObjFanin1(pObj)->Value ); } } assert( Count == Gia_ManBufNum(pGia) ); Gia_ManForEachPo( pGia, pObj, i ) { assert( Gia_ObjFanin0(pObj)->Value == 1 ); pObj->Value = 1; } } void Bac_ManRemapBarbufs( Bac_Man_t * pNew, Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int Entry, i; //assert( Vec_IntSize(&p->vBuf2RootNtk) ); assert( !Vec_IntSize(&pNew->vBuf2RootNtk) ); Vec_IntAppend( &pNew->vBuf2RootNtk, &p->vBuf2RootNtk ); Vec_IntAppend( &pNew->vBuf2RootObj, &p->vBuf2RootObj ); Vec_IntAppend( &pNew->vBuf2LeafNtk, &p->vBuf2LeafNtk ); Vec_IntAppend( &pNew->vBuf2LeafObj, &p->vBuf2LeafObj ); Vec_IntForEachEntry( &p->vBuf2LeafObj, Entry, i ) { pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2LeafNtk, i) ); Vec_IntWriteEntry( &pNew->vBuf2LeafObj, i, Bac_ObjCopy(pNtk, Entry) ); } Vec_IntForEachEntry( &p->vBuf2RootObj, Entry, i ) { pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, i) ); Vec_IntWriteEntry( &pNew->vBuf2RootObj, i, Bac_ObjCopy(pNtk, Entry) ); } } void Bac_NtkCreateAndConnectBuffer( Gia_Man_t * pGia, Gia_Obj_t * pObj, Bac_Ntk_t * p, int iTerm ) { int iObj; if ( pGia && Gia_ObjFaninId0p(pGia, pObj) > 0 ) { iObj = Bac_ObjAlloc( p, BAC_OBJ_BI, Gia_ObjFanin0(pObj)->Value ); Bac_ObjAlloc( p, Gia_ObjFaninC0(pObj) ? BAC_BOX_INV : BAC_BOX_BUF, -1 ); } else { Bac_ObjAlloc( p, pGia && Gia_ObjFaninC0(pObj) ? BAC_BOX_CT : BAC_BOX_CF, -1 ); } iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 ); Bac_ObjSetFanin( p, iTerm, iObj ); } void Bac_NtkInsertGia( Bac_Man_t * p, Gia_Man_t * pGia ) { Bac_Ntk_t * pNtk, * pRoot = Bac_ManRoot( p ); int i, j, k, iBox, iTerm, Count = 0; Gia_Obj_t * pObj; Gia_ManConst0(pGia)->Value = ~0; Gia_ManForEachPi( pGia, pObj, i ) pObj->Value = Bac_NtkPi( pRoot, i ); Gia_ManForEachAnd( pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, Count) ); iTerm = Vec_IntEntry( &p->vBuf2RootObj, Count ); assert( Bac_ObjIsCo(pNtk, iTerm) ); if ( Bac_ObjFanin(pNtk, iTerm) == -1 ) // not a feedthrough Bac_NtkCreateAndConnectBuffer( pGia, pObj, pNtk, iTerm ); // prepare leaf pObj->Value = Vec_IntEntry( &p->vBuf2LeafObj, Count++ ); } else { int iLit0 = Gia_ObjFanin0(pObj)->Value; int iLit1 = Gia_ObjFanin1(pObj)->Value; Bac_ObjType_t Type; pNtk = Bac_ManNtk( p, pObj->Value ); if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) Type = BAC_BOX_NOR; else if ( Gia_ObjFaninC1(pObj) ) Type = BAC_BOX_SHARP; else if ( Gia_ObjFaninC0(pObj) ) { Type = BAC_BOX_SHARP; ABC_SWAP( int, iLit0, iLit1 ); } else Type = BAC_BOX_AND; // create box iTerm = Bac_ObjAlloc( pNtk, BAC_OBJ_BI, iLit1 ); iTerm = Bac_ObjAlloc( pNtk, BAC_OBJ_BI, iLit0 ); Bac_ObjAlloc( pNtk, Type, -1 ); pObj->Value = Bac_ObjAlloc( pNtk, BAC_OBJ_BO, -1 ); } } assert( Count == Gia_ManBufNum(pGia) ); // create constant 0 drivers for COs without barbufs Bac_ManForEachNtk( p, pNtk, i ) { Bac_NtkForEachBox( pNtk, iBox ) Bac_BoxForEachBi( pNtk, iBox, iTerm, j ) if ( Bac_ObjFanin(pNtk, iTerm) == -1 ) Bac_NtkCreateAndConnectBuffer( NULL, NULL, pNtk, iTerm ); Bac_NtkForEachPo( pNtk, iTerm, k ) if ( pNtk != pRoot && Bac_ObjFanin(pNtk, iTerm) == -1 ) Bac_NtkCreateAndConnectBuffer( NULL, NULL, pNtk, iTerm ); } // create node and connect POs Gia_ManForEachPo( pGia, pObj, i ) if ( Bac_ObjFanin(pRoot, Bac_NtkPo(pRoot, i)) == -1 ) // not a feedthrough Bac_NtkCreateAndConnectBuffer( pGia, pObj, pRoot, Bac_NtkPo(pRoot, i) ); } Bac_Man_t * Bac_ManInsertGia( Bac_Man_t * p, Gia_Man_t * pGia ) { Bac_Man_t * pNew = Bac_ManDupUserBoxes( p ); Bac_ManMarkNodesGia( p, pGia ); Bac_ManRemapBarbufs( pNew, p ); Bac_NtkInsertGia( pNew, pGia ); Bac_ManMoveNames( pNew, p ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bac_Man_t * Bac_ManBlastTest( Bac_Man_t * p ) { Gia_Man_t * pGia = Bac_ManExtract( p, 1, 0 ); Bac_Man_t * pNew = Bac_ManInsertGia( p, pGia ); Gia_ManStop( pGia ); return pNew; } /**Function************************************************************* Synopsis [Mark each GIA node with the network it belongs to.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_NodeIsSeriousGate( Abc_Obj_t * p ) { return Abc_ObjIsNode(p) && Abc_ObjFaninNum(p) > 0 && !Abc_ObjIsBarBuf(p); } void Bac_ManMarkNodesAbc( Bac_Man_t * p, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFanin; int i, k, Count = 0; assert( Vec_IntSize(&p->vBuf2LeafNtk) == pNtk->nBarBufs2 ); Abc_NtkForEachPi( pNtk, pObj, i ) pObj->iTemp = 1; Abc_NtkForEachNode( pNtk, pObj, i ) { if ( Abc_ObjIsBarBuf(pObj) ) pObj->iTemp = Vec_IntEntry( &p->vBuf2LeafNtk, Count++ ); else if ( Abc_NodeIsSeriousGate(pObj) ) { pObj->iTemp = Abc_ObjFanin0(pObj)->iTemp; Abc_ObjForEachFanin( pObj, pFanin, k ) assert( pObj->iTemp == pFanin->iTemp ); } } Abc_NtkForEachPo( pNtk, pObj, i ) { if ( !Abc_NodeIsSeriousGate(Abc_ObjFanin0(pObj)) ) continue; assert( Abc_ObjFanin0(pObj)->iTemp == 1 ); pObj->iTemp = Abc_ObjFanin0(pObj)->iTemp; } assert( Count == pNtk->nBarBufs2 ); } void Bac_NtkCreateOrConnectFanin( Abc_Obj_t * pFanin, Bac_Ntk_t * p, int iTerm ) { int iObj; if ( pFanin && Abc_NodeIsSeriousGate(pFanin) )//&& Bac_ObjName(p, pFanin->iTemp) == -1 ) // gate without name { iObj = pFanin->iTemp; } else if ( pFanin && (Abc_ObjIsPi(pFanin) || Abc_ObjIsBarBuf(pFanin) || Abc_NodeIsSeriousGate(pFanin)) ) // PI/BO or gate with name { iObj = Bac_ObjAlloc( p, BAC_OBJ_BI, pFanin->iTemp ); Bac_ObjAlloc( p, BAC_BOX_GATE, p->pDesign->ElemGates[2] ); // buffer iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 ); } else { assert( !pFanin || Abc_NodeIsConst0(pFanin) || Abc_NodeIsConst1(pFanin) ); Bac_ObjAlloc( p, BAC_BOX_GATE, p->pDesign->ElemGates[(pFanin && Abc_NodeIsConst1(pFanin))] ); // const 0/1 iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 ); } Bac_ObjSetFanin( p, iTerm, iObj ); } void Bac_NtkPrepareLibrary( Bac_Man_t * p, Mio_Library_t * pLib ) { Mio_Gate_t * pGate; Mio_Gate_t * pGate0 = Mio_LibraryReadConst0( pLib ); Mio_Gate_t * pGate1 = Mio_LibraryReadConst1( pLib ); Mio_Gate_t * pGate2 = Mio_LibraryReadBuf( pLib ); if ( !pGate0 || !pGate1 || !pGate2 ) { printf( "The library does not have one of the elementary gates.\n" ); return; } p->ElemGates[0] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate0), NULL ); p->ElemGates[1] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate1), NULL ); p->ElemGates[2] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate2), NULL ); Mio_LibraryForEachGate( pLib, pGate ) if ( pGate != pGate0 && pGate != pGate1 && pGate != pGate2 ) Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate), NULL ); assert( Abc_NamObjNumMax(p->pMods) > 1 ); } int Bac_NtkBuildLibrary( Bac_Man_t * p ) { int RetValue = 1; Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pLib == NULL ) printf( "The standard cell library is not available.\n" ), RetValue = 0; else Bac_NtkPrepareLibrary( p, pLib ); p->pMioLib = pLib; return RetValue; } void Bac_NtkInsertNtk( Bac_Man_t * p, Abc_Ntk_t * pNtk ) { Bac_Ntk_t * pCbaNtk, * pRoot = Bac_ManRoot( p ); int i, j, k, iBox, iTerm, Count = 0; Abc_Obj_t * pObj; assert( Abc_NtkHasMapping(pNtk) ); Bac_NtkPrepareLibrary( p, (Mio_Library_t *)pNtk->pManFunc ); p->pMioLib = pNtk->pManFunc; Abc_NtkForEachPi( pNtk, pObj, i ) pObj->iTemp = Bac_NtkPi( pRoot, i ); Abc_NtkForEachNode( pNtk, pObj, i ) { if ( Abc_ObjIsBarBuf(pObj) ) { pCbaNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, Count) ); iTerm = Vec_IntEntry( &p->vBuf2RootObj, Count ); assert( Bac_ObjIsCo(pCbaNtk, iTerm) ); if ( Bac_ObjFanin(pCbaNtk, iTerm) == -1 ) // not a feedthrough Bac_NtkCreateOrConnectFanin( Abc_ObjFanin0(pObj), pCbaNtk, iTerm ); // prepare leaf pObj->iTemp = Vec_IntEntry( &p->vBuf2LeafObj, Count++ ); } else if ( Abc_NodeIsSeriousGate(pObj) ) { pCbaNtk = Bac_ManNtk( p, pObj->iTemp ); for ( k = Abc_ObjFaninNum(pObj)-1; k >= 0; k-- ) iTerm = Bac_ObjAlloc( pCbaNtk, BAC_OBJ_BI, Abc_ObjFanin(pObj, k)->iTemp ); Bac_ObjAlloc( pCbaNtk, BAC_BOX_GATE, Abc_NamStrFind(p->pMods, Mio_GateReadName((Mio_Gate_t *)pObj->pData)) ); pObj->iTemp = Bac_ObjAlloc( pCbaNtk, BAC_OBJ_BO, -1 ); } } assert( Count == pNtk->nBarBufs2 ); // create constant 0 drivers for COs without barbufs Bac_ManForEachNtk( p, pCbaNtk, i ) { Bac_NtkForEachBox( pCbaNtk, iBox ) Bac_BoxForEachBi( pCbaNtk, iBox, iTerm, j ) if ( Bac_ObjFanin(pCbaNtk, iTerm) == -1 ) Bac_NtkCreateOrConnectFanin( NULL, pCbaNtk, iTerm ); Bac_NtkForEachPo( pCbaNtk, iTerm, k ) if ( pCbaNtk != pRoot && Bac_ObjFanin(pCbaNtk, iTerm) == -1 ) Bac_NtkCreateOrConnectFanin( NULL, pCbaNtk, iTerm ); } // create node and connect POs Abc_NtkForEachPo( pNtk, pObj, i ) if ( Bac_ObjFanin(pRoot, Bac_NtkPo(pRoot, i)) == -1 ) // not a feedthrough Bac_NtkCreateOrConnectFanin( Abc_ObjFanin0(pObj), pRoot, Bac_NtkPo(pRoot, i) ); } void * Bac_ManInsertAbc( Bac_Man_t * p, void * pAbc ) { Abc_Ntk_t * pNtk = (Abc_Ntk_t *)pAbc; Bac_Man_t * pNew = Bac_ManDupUserBoxes( p ); Bac_ManMarkNodesAbc( p, pNtk ); Bac_ManRemapBarbufs( pNew, p ); Bac_NtkInsertNtk( pNew, pNtk ); Bac_ManMoveNames( pNew, p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacCom.c000066400000000000000000000550001300674244400230230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacCom.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Command handlers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacCom.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "bacPrs.h" #include "proof/cec/cec.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Bac_CommandRead ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Bac_CommandWrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Bac_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Bac_CommandPut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Bac_CommandGet ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Bac_CommandClp ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Bac_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Bac_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static inline Bac_Man_t * Bac_AbcGetMan( Abc_Frame_t * pAbc ) { return (Bac_Man_t *)pAbc->pAbcBac; } static inline void Bac_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcBac ) Bac_ManFree(Bac_AbcGetMan(pAbc)); } static inline void Bac_AbcUpdateMan( Abc_Frame_t * pAbc, Bac_Man_t * p ) { Bac_AbcFreeMan(pAbc); pAbc->pAbcBac = p; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [Accessing current Bac_Ntk_t.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Abc_FrameImportPtr( Vec_Ptr_t * vPtr ) { Bac_Man_t * p; if ( Abc_FrameGetGlobalFrame() == NULL ) { printf( "ABC framework is not started.\n" ); return; } p = Bac_PtrTransformToCba( vPtr ); if ( p == NULL ) printf( "Converting from Ptr failed.\n" ); Bac_AbcUpdateMan( Abc_FrameGetGlobalFrame(), p ); } Vec_Ptr_t * Abc_FrameExportPtr() { Vec_Ptr_t * vPtr; Bac_Man_t * p; if ( Abc_FrameGetGlobalFrame() == NULL ) { printf( "ABC framework is not started.\n" ); return NULL; } p = Bac_AbcGetMan( Abc_FrameGetGlobalFrame() ); if ( p == NULL ) printf( "There is no CBA design present.\n" ); vPtr = Bac_PtrDeriveFromCba( p ); if ( vPtr == NULL ) printf( "Converting to Ptr has failed.\n" ); return vPtr; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Bac_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "New word level", "@_read", Bac_CommandRead, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@_write", Bac_CommandWrite, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@_ps", Bac_CommandPs, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@_put", Bac_CommandPut, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@_get", Bac_CommandGet, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@_clp", Bac_CommandClp, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@_cec", Bac_CommandCec, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@_test", Bac_CommandTest, 0 ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Bac_End( Abc_Frame_t * pAbc ) { Bac_AbcFreeMan( pAbc ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Bac_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Bac_Man_t * p = NULL; Vec_Ptr_t * vDes = NULL; char * pFileName = NULL; int c, fUseAbc = 0, fUsePtr = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "apvh" ) ) != EOF ) { switch ( c ) { case 'a': fUseAbc ^= 1; break; case 'p': fUsePtr ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { printf( "Bac_CommandRead(): Input file name should be given on the command line.\n" ); return 0; } // get the file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "r" )) == NULL ) { Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", ".smt", ".bac", NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); Abc_Print( 1, "\n" ); return 0; } fclose( pFile ); // perform reading if ( fUseAbc || fUsePtr ) { extern Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pAbcNtk = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 0 ); Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pAbcNtk ); p = Bac_PtrTransformToCba( vDes ); Bac_PtrFree( vDes ); // points to names in pAbcNtk if ( p ) { ABC_FREE( p->pSpec ); p->pSpec = Abc_UtilStrsav( pAbcNtk->pSpec ); } Abc_NtkDelete( pAbcNtk ); } else if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) ) { vDes = Psr_ManReadBlif( pFileName ); if ( vDes && Vec_PtrSize(vDes) ) p = Psr_ManBuildCba( pFileName, vDes ); if ( vDes ) Psr_ManVecFree( vDes ); } else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) { vDes = Psr_ManReadVerilog( pFileName ); if ( vDes && Vec_PtrSize(vDes) ) p = Psr_ManBuildCba( pFileName, vDes ); if ( vDes ) Psr_ManVecFree( vDes ); } else if ( !strcmp( Extra_FileNameExtension(pFileName), "smt" ) ) { vDes = NULL;//Psr_ManReadSmt( pFileName ); if ( vDes && Vec_PtrSize(vDes) ) p = Psr_ManBuildCba( pFileName, vDes ); if ( vDes ) Psr_ManVecFree( vDes ); } else if ( !strcmp( Extra_FileNameExtension(pFileName), "bac" ) ) { p = Bac_ManReadBac( pFileName ); } else { printf( "Unrecognized input file extension.\n" ); return 0; } Bac_AbcUpdateMan( pAbc, p ); return 0; usage: Abc_Print( -2, "usage: @_read [-apvh] \n" ); Abc_Print( -2, "\t reads hierarchical design in BLIF or Verilog\n" ); Abc_Print( -2, "\t-a : toggle using old ABC parser [default = %s]\n", fUseAbc? "yes": "no" ); Abc_Print( -2, "\t-p : toggle using Ptr construction [default = %s]\n", fUsePtr? "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 Bac_CommandWrite( Abc_Frame_t * pAbc, int argc, char ** argv ) { Bac_Man_t * p = Bac_AbcGetMan(pAbc); char * pFileName = NULL; int fUseAssign = 1; int fUsePtr = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "apvh" ) ) != EOF ) { switch ( c ) { case 'a': fUseAssign ^= 1; break; case 'p': fUsePtr ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Bac_CommandWrite(): There is no current design.\n" ); return 0; } if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; else if ( argc == globalUtilOptind && p ) pFileName = Extra_FileNameGenericAppend( Bac_ManName(p), "_out.v" ); else { printf( "Output file name should be given on the command line.\n" ); return 0; } // perform writing if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) ) Bac_ManWriteBlif( pFileName, p ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) { if ( fUsePtr ) { Vec_Ptr_t * vPtr = Bac_PtrDeriveFromCba( p ); if ( vPtr == NULL ) printf( "Converting to Ptr has failed.\n" ); else { Bac_PtrDumpVerilog( pFileName, vPtr ); Bac_PtrFree( vPtr ); } } else Bac_ManWriteVerilog( pFileName, p, fUseAssign ); } else if ( !strcmp( Extra_FileNameExtension(pFileName), "bac" ) ) Bac_ManWriteBac( pFileName, p ); else { printf( "Unrecognized output file extension.\n" ); return 0; } return 0; usage: Abc_Print( -2, "usage: @_write [-apvh]\n" ); Abc_Print( -2, "\t writes the design into a file in BLIF or Verilog\n" ); Abc_Print( -2, "\t-a : toggle using assign-statement for primitives [default = %s]\n", fUseAssign? "yes": "no" ); Abc_Print( -2, "\t-p : toggle using Ptr construction (mapped Verilog only) [default = %s]\n", fUsePtr? "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 Bac_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv ) { Bac_Man_t * p = Bac_AbcGetMan(pAbc); int c, nModules = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nModules = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nModules < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Bac_CommandPs(): There is no current design.\n" ); return 0; } Bac_ManPrintStats( p, nModules, fVerbose ); return 0; usage: Abc_Print( -2, "usage: @_ps [-M num] [-vh]\n" ); Abc_Print( -2, "\t prints statistics\n" ); Abc_Print( -2, "\t-M num : the number of first modules to report [default = %d]\n", nModules ); 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 Bac_CommandPut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Bac_Man_t * p = Bac_AbcGetMan(pAbc); Gia_Man_t * pGia = NULL; int c, fBarBufs = 1, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF ) { switch ( c ) { case 'b': fBarBufs ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Bac_CommandPut(): There is no current design.\n" ); return 0; } pGia = Bac_ManExtract( p, fBarBufs, fVerbose ); if ( pGia == NULL ) { Abc_Print( 1, "Bac_CommandPut(): Conversion to AIG has failed.\n" ); return 0; } Abc_FrameUpdateGia( pAbc, pGia ); return 0; usage: Abc_Print( -2, "usage: @_put [-bvh]\n" ); Abc_Print( -2, "\t extracts AIG from the hierarchical design\n" ); Abc_Print( -2, "\t-b : toggle using barrier buffers [default = %s]\n", fBarBufs? "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 Bac_CommandGet( Abc_Frame_t * pAbc, int argc, char ** argv ) { Bac_Man_t * pNew = NULL, * p = Bac_AbcGetMan(pAbc); int c, fMapped = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF ) { switch ( c ) { case 'm': fMapped ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Bac_CommandGet(): There is no current design.\n" ); return 0; } if ( fMapped ) { if ( pAbc->pNtkCur == NULL ) { Abc_Print( 1, "Bac_CommandGet(): There is no current mapped design.\n" ); return 0; } pNew = (Bac_Man_t *)Bac_ManInsertAbc( p, pAbc->pNtkCur ); } else { if ( pAbc->pGia == NULL ) { Abc_Print( 1, "Bac_CommandGet(): There is no current AIG.\n" ); return 0; } pNew = Bac_ManInsertGia( p, pAbc->pGia ); } Bac_AbcUpdateMan( pAbc, pNew ); return 0; usage: Abc_Print( -2, "usage: @_get [-mvh]\n" ); Abc_Print( -2, "\t inserts AIG or mapped network into the hierarchical design\n" ); Abc_Print( -2, "\t-m : toggle using mapped network from main-space [default = %s]\n", fMapped? "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 Bac_CommandClp( Abc_Frame_t * pAbc, int argc, char ** argv ) { Bac_Man_t * pNew = NULL, * p = Bac_AbcGetMan(pAbc); 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 ( p == NULL ) { Abc_Print( 1, "Bac_CommandGet(): There is no current design.\n" ); return 0; } pNew = Bac_ManCollapse( p ); Bac_AbcUpdateMan( pAbc, pNew ); return 0; usage: Abc_Print( -2, "usage: @_clp [-vh]\n" ); Abc_Print( -2, "\t collapses the current hierarchical design\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 Bac_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Bac_Man_t * p = Bac_AbcGetMan(pAbc); Gia_Man_t * pFirst, * pSecond, * pMiter; Cec_ParCec_t ParsCec, * pPars = &ParsCec; Vec_Ptr_t * vDes; char * FileName, * pStr, ** pArgvNew; int c, nArgcNew, fDumpMiter = 0; FILE * pFile; Cec_ManCecSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Bac_CommandCec(): There is no current design.\n" ); return 0; } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { if ( p->pSpec == NULL ) { Abc_Print( -1, "File name is not given on the command line.\n" ); return 1; } FileName = p->pSpec; } else FileName = pArgvNew[0]; // fix the wrong symbol for ( pStr = FileName; *pStr; pStr++ ) if ( *pStr == '>' ) *pStr = '\\'; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".v", ".blif", NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); // extract AIG from the current design pFirst = Bac_ManExtract( p, 0, 0 ); if ( pFirst == NULL ) { Abc_Print( -1, "Extracting AIG from the current design has failed.\n" ); return 0; } // extract AIG from the second design if ( !strcmp( Extra_FileNameExtension(FileName), "blif" ) ) vDes = Psr_ManReadBlif( FileName ); else if ( !strcmp( Extra_FileNameExtension(FileName), "v" ) ) vDes = Psr_ManReadVerilog( FileName ); else assert( 0 ); p = Psr_ManBuildCba( FileName, vDes ); Psr_ManVecFree( vDes ); pSecond = Bac_ManExtract( p, 0, 0 ); Bac_ManFree( p ); if ( pSecond == NULL ) { Gia_ManStop( pFirst ); Abc_Print( -1, "Extracting AIG from the original design has failed.\n" ); return 0; } // compute the miter pMiter = Gia_ManMiter( pFirst, pSecond, 0, 1, 0, 0, pPars->fVerbose ); if ( pMiter ) { if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 ); } pAbc->Status = Cec_ManVerify( pMiter, pPars ); //Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); Gia_ManStop( pMiter ); } Gia_ManStop( pFirst ); Gia_ManStop( pSecond ); return 0; usage: Abc_Print( -2, "usage: @_cec [-vh]\n" ); Abc_Print( -2, "\t combinational equivalence checking\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Bac_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Psr_ManReadBlifTest(); extern void Psr_ManReadVerilogTest(); extern void Psr_SmtReadSmtTest(); //Bac_Man_t * p = Bac_AbcGetMan(pAbc); 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 ( p == NULL ) { Abc_Print( 1, "Bac_CommandTest(): There is no current design.\n" ); return 0; } */ //Bac_PtrTransformTestTest(); //Psr_ManReadVerilogTest(); //Psr_SmtReadSmtTest(); return 0; usage: Abc_Print( -2, "usage: @_test [-vh]\n" ); Abc_Print( -2, "\t experiments with word-level networks\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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacLib.c000066400000000000000000000027111300674244400230140ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacLib.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Library procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacLib.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacNtk.c000066400000000000000000000474261300674244400230560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacNtk.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Netlist manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacNtk.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Bac_Pair_t_ Bac_Pair_t; struct Bac_Pair_t_ { Bac_ObjType_t Type; char * pName; char * pSymb; }; static const char * s_Pref = "ABC_"; static Bac_Pair_t s_Types[BAC_BOX_UNKNOWN] = { { BAC_OBJ_NONE, "NONE", NULL }, { BAC_OBJ_PI, "PI", NULL }, { BAC_OBJ_PO, "PO", NULL }, { BAC_OBJ_BI, "BI", NULL }, { BAC_OBJ_BO, "BO", NULL }, { BAC_OBJ_BOX, "BOX", NULL }, { BAC_BOX_CF, "CF", "o" }, { BAC_BOX_CT, "CT", "o" }, { BAC_BOX_CX, "CX", "o" }, { BAC_BOX_CZ, "CZ", "o" }, { BAC_BOX_BUF, "BUF", "ao" }, { BAC_BOX_INV, "INV", "ao" }, { BAC_BOX_AND, "AND", "abo" }, { BAC_BOX_NAND, "NAND", "abo" }, { BAC_BOX_OR, "OR", "abo" }, { BAC_BOX_NOR, "NOR", "abo" }, { BAC_BOX_XOR, "XOR", "abo" }, { BAC_BOX_XNOR, "XNOR", "abo" }, { BAC_BOX_SHARP, "SHARP", "abo" }, { BAC_BOX_SHARPL, "SHARPL", "abo" }, { BAC_BOX_MUX, "MUX", "cabo" }, { BAC_BOX_MAJ, "MAJ", "abco" }, { BAC_BOX_RAND, "RAND", "ao" }, { BAC_BOX_RNAND, "RNAND", "ao" }, { BAC_BOX_ROR, "ROR", "ao" }, { BAC_BOX_RNOR, "RNOR", "ao" }, { BAC_BOX_RXOR, "RXOR", "ao" }, { BAC_BOX_RXNOR, "RXNOR", "ao" }, { BAC_BOX_LAND, "LAND", "abo" }, { BAC_BOX_LNAND, "LNAND", "abo" }, { BAC_BOX_LOR, "LOR", "abo" }, { BAC_BOX_LNOR, "LNOR", "abo" }, { BAC_BOX_LXOR, "LXOR", "abo" }, { BAC_BOX_LXNOR, "LXNOR", "abo" }, { BAC_BOX_NMUX, "NMUX", "abo" }, { BAC_BOX_SEL, "SEL", "abo" }, { BAC_BOX_PSEL, "PSEL", "iabo" }, { BAC_BOX_ENC, "ENC", "ao" }, { BAC_BOX_PENC, "PENC", "ao" }, { BAC_BOX_DEC, "DEC", "ao" }, { BAC_BOX_EDEC, "EDEC", "abo" }, { BAC_BOX_ADD, "ADD", "iabso" }, { BAC_BOX_SUB, "SUB", "abo" }, { BAC_BOX_MUL, "MUL", "abo" }, { BAC_BOX_DIV, "DIV", "abo" }, { BAC_BOX_MOD, "MOD", "abo" }, { BAC_BOX_REM, "REM", "abo" }, { BAC_BOX_POW, "POW", "abo" }, { BAC_BOX_MIN, "MIN", "ao" }, { BAC_BOX_ABS, "ABS", "ao" }, { BAC_BOX_LTHAN, "LTHAN", "iabo" }, { BAC_BOX_LETHAN, "LETHAN", "abo" }, { BAC_BOX_METHAN, "METHAN", "abo" }, { BAC_BOX_MTHAN, "MTHAN", "abo" }, { BAC_BOX_EQU, "EQU", "abo" }, { BAC_BOX_NEQU, "NEQU", "abo" }, { BAC_BOX_SHIL, "SHIL", "abo" }, { BAC_BOX_SHIR, "SHIR", "abo" }, { BAC_BOX_ROTL, "ROTL", "abo" }, { BAC_BOX_ROTR, "ROTR", "abo" }, { BAC_BOX_GATE, "GATE", "io" }, { BAC_BOX_LUT, "LUT", "io" }, { BAC_BOX_ASSIGN, "ASSIGN", "abo" }, { BAC_BOX_TRI, "TRI", "abo" }, { BAC_BOX_RAM, "RAM", "eadro" }, { BAC_BOX_RAMR, "RAMR", "eamo" }, { BAC_BOX_RAMW, "RAMW", "eado" }, { BAC_BOX_RAMWC, "RAMWC", "ceado" }, { BAC_BOX_RAMBOX, "RAMBOX", "io" }, { BAC_BOX_LATCH, "LATCH", "dvsgq" }, { BAC_BOX_LATCHRS, "LATCHRS", "dsrgq" }, { BAC_BOX_DFF, "DFF", "dvscq" }, { BAC_BOX_DFFRS, "DFFRS", "dsrcq" } }; static inline int Bac_GetTypeId( Bac_ObjType_t Type ) { int i; for ( i = 1; i < BAC_BOX_UNKNOWN; i++ ) if ( s_Types[i].Type == Type ) return i; return -1; } void Bac_ManSetupTypes( char ** pNames, char ** pSymbs ) { int Type; for ( Type = 1; Type < BAC_BOX_UNKNOWN; Type++ ) { int Id = Bac_GetTypeId( (Bac_ObjType_t)Type ); pNames[Type] = s_Types[Id].pName; pSymbs[Type] = s_Types[Id].pSymb; } } char * Bac_NtkGenerateName( Bac_Ntk_t * p, Bac_ObjType_t Type, Vec_Int_t * vBits ) { static char Buffer[100]; char * pTemp; int i, Bits; char * pName = Bac_ManPrimName( p->pDesign, Type ); char * pSymb = Bac_ManPrimSymb( p->pDesign, Type ); assert( Vec_IntSize(vBits) == (int)strlen(pSymb) ); sprintf( Buffer, "%s%s_", s_Pref, pName ); pTemp = Buffer + strlen(Buffer); Vec_IntForEachEntry( vBits, Bits, i ) { sprintf( pTemp, "%c%d", pSymb[i], Bits ); pTemp += strlen(pTemp); } //Vec_IntPrint( vBits ); //printf( "%s\n", Buffer ); return Buffer; } Bac_ObjType_t Bac_NameToType( char * pName ) { int i; if ( strncmp(pName, s_Pref, strlen(s_Pref)) ) return BAC_OBJ_NONE; pName += strlen(s_Pref); for ( i = 1; i < BAC_BOX_UNKNOWN; i++ ) if ( !strncmp(pName, s_Types[i].pName, strlen(s_Types[i].pName)) ) return s_Types[i].Type; return BAC_OBJ_NONE; } Vec_Int_t * Bac_NameToRanges( char * pName ) { static Vec_Int_t Bits, * vBits = &Bits; static int pArray[10]; char * pTemp; int Num = 0, Count = 0; // initialize array vBits->pArray = pArray; vBits->nSize = 0; vBits->nCap = 10; // check the name assert( !strncmp(pName, s_Pref, strlen(s_Pref)) ); for ( pTemp = pName; *pTemp && !Bac_CharIsDigit(*pTemp); pTemp++ ); assert( Bac_CharIsDigit(*pTemp) ); for ( ; *pTemp; pTemp++ ) { if ( Bac_CharIsDigit(*pTemp) ) Num = 10 * Num + *pTemp - '0'; else Vec_IntPush( vBits, Num ), Count += Num, Num = 0; } assert( Num > 0 ); Vec_IntPush( vBits, Num ); Count += Num; assert( Vec_IntSize(vBits) <= 10 ); return vBits; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Replaces fanin iOld by iNew in all fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_NtkUpdateFanout( Bac_Ntk_t * p, int iOld, int iNew ) { int iCo; assert( Bac_ObjIsCi(p, iOld) ); assert( Bac_ObjIsCi(p, iNew) ); Bac_ObjForEachFanout( p, iOld, iCo ) { assert( Bac_ObjFanin(p, iCo) == iOld ); Bac_ObjCleanFanin( p, iCo ); Bac_ObjSetFanin( p, iCo, iNew ); } Bac_ObjSetFanout( p, iNew, Bac_ObjFanout(p, iOld) ); Bac_ObjSetFanout( p, iOld, 0 ); } /**Function************************************************************* Synopsis [Derives fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_NtkDeriveFanout( Bac_Ntk_t * p ) { int iCi, iCo; assert( !Bac_NtkHasFanouts(p) ); Bac_NtkStartFanouts( p ); Bac_NtkForEachCo( p, iCo ) { assert( !Bac_ObjNextFanout(p, iCo) ); iCi = Bac_ObjFanin(p, iCo); if ( Bac_ObjFanout(p, iCi) ) Bac_ObjSetNextFanout( p, Bac_ObjFanout(p, iCi), iCo ); Bac_ObjSetFanout( p, iCi, iCo ); } Bac_NtkForEachCo( p, iCo ) if ( !Bac_ObjNextFanout(p, iCo) ) Bac_ObjSetFanout( p, Bac_ObjFanin(p, iCo), iCo ); } void Bac_ManDeriveFanout( Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int i; Bac_ManForEachNtk( p, pNtk, i ) Bac_NtkDeriveFanout( pNtk ); } /**Function************************************************************* Synopsis [Assigns word-level names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_ManAssignInternTwo( Bac_Ntk_t * p, int iNum, int nDigits, char * pPref, Vec_Int_t * vMap ) { char Buffer[16]; int i, NameId = 0; for ( i = 0; !NameId || Vec_IntEntry(vMap, NameId); i++ ) { if ( i == 0 ) sprintf( Buffer, "%s%0*d", pPref, nDigits, iNum ); else sprintf( Buffer, "%s%0*d_%d", pPref, nDigits, iNum, i ); NameId = Abc_NamStrFindOrAdd( p->pDesign->pStrs, Buffer, NULL ); } Vec_IntWriteEntry( vMap, NameId, 1 ); return NameId; } int Bac_ManAssignCountNames( Bac_Ntk_t * p ) { int i, iObj, iBox, Count = 0; Bac_NtkForEachPiMain( p, iObj, i ) if ( !Bac_ObjNameInt(p, iObj) ) Count++; Bac_NtkForEachBox( p, iBox ) Bac_BoxForEachBoMain( p, iBox, iObj, i ) if ( !Bac_ObjNameInt(p, iObj) ) Count++; return Count; } void Bac_ManAssignInternWordNamesNtk( Bac_Ntk_t * p, Vec_Int_t * vMap ) { int k, iObj, iTerm, iName = -1, iBit = -1; int nDigits, nPis = 0, nPos = 0, nNames = 1; // start names if ( !Bac_NtkHasNames(p) ) Bac_NtkStartNames(p); nDigits = Abc_Base10Log( Bac_ManAssignCountNames(p) ); // populate map with the currently used names Bac_NtkForEachCi( p, iObj ) if ( Bac_ObjNameInt(p, iObj) ) Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 1 ); Bac_NtkForEachBox( p, iObj ) if ( Bac_ObjNameInt(p, iObj) ) Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 1 ); // assign CI names Bac_NtkForEachCi( p, iObj ) { if ( Bac_ObjNameInt(p, iObj) ) { iName = -1; iBit = -1; continue; } if ( Bac_ObjBit(p, iObj) ) { assert( iBit > 0 ); Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iBit++, BAC_NAME_INDEX) ); } else { //int Type = Bac_ObjType(p, iObj); int Range = Bac_ObjIsPi(p, iObj) ? Bac_ObjPiRange(p, iObj) : Bac_BoxBoRange(p, iObj); iName = Bac_ManAssignInternTwo( p, nNames++, nDigits, (char*)(Bac_ObjIsPi(p, iObj) ? "i":"n"), vMap ); if ( Range == 1 ) Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_BIN) ); else Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_WORD) ); iBit = 1; } } // transfer names to the interface if ( Bac_NtkInfoNum(p) ) { for ( k = 0; k < Bac_NtkInfoNum(p); k++ ) { //char * pName = Bac_NtkName(p); if ( Bac_NtkInfoType(p, k) == 1 ) // PI { iObj = Bac_NtkPi(p, nPis); assert( !Bac_ObjBit(p, iObj) ); assert( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD ); Bac_NtkSetInfoName( p, k, Abc_Var2Lit2(Bac_ObjNameId(p, iObj), 1) ); nPis += Bac_NtkInfoRange(p, k); } else if ( Bac_NtkInfoType(p, k) == 2 ) // PO { iObj = Bac_NtkPo(p, nPos); assert( !Bac_ObjBit(p, iObj) ); iObj = Bac_ObjFanin(p, iObj); assert( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD ); Bac_NtkSetInfoName( p, k, Abc_Var2Lit2(Bac_ObjNameId(p, iObj), 2) ); nPos += Bac_NtkInfoRange(p, k); } else assert( 0 ); } assert( nPis == Bac_NtkPiNum(p) ); assert( nPos == Bac_NtkPoNum(p) ); } // assign instance names nDigits = Abc_Base10Log( Bac_NtkObjNum(p) ); Bac_NtkForEachBox( p, iObj ) if ( !Bac_ObjNameInt(p, iObj) ) { iName = Bac_ManAssignInternTwo( p, iObj, nDigits, "g", vMap ); Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_BIN) ); } // unmark all names Bac_NtkForEachPi( p, iObj, k ) if ( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD ) Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 0 ); Bac_NtkForEachBox( p, iObj ) { Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 0 ); Bac_BoxForEachBo( p, iObj, iTerm, k ) if ( Bac_ObjNameType(p, iTerm) <= BAC_NAME_WORD ) Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iTerm), 0 ); } // printf( "Generated %d word-level names.\n", nNames-1 ); } void Bac_ManAssignInternWordNames( Bac_Man_t * p ) { Vec_Int_t * vMap = Vec_IntStart( 2*Bac_ManObjNum(p) ); Bac_Ntk_t * pNtk; int i; Bac_ManForEachNtk( p, pNtk, i ) Bac_ManAssignInternWordNamesNtk( pNtk, vMap ); assert( Vec_IntCountEntry(vMap, 0) == Vec_IntSize(vMap) ); Vec_IntFree( vMap ); } /**Function************************************************************* Synopsis [Count number of objects after collapsing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_ManClpObjNum_rec( Bac_Ntk_t * p ) { int i, Counter = 0; if ( p->Count >= 0 ) return p->Count; Bac_NtkForEachBox( p, i ) Counter += Bac_ObjIsBoxUser(p, i) ? Bac_ManClpObjNum_rec( Bac_BoxNtk(p, i) ) + 3*Bac_BoxBoNum(p, i) : Bac_BoxSize(p, i); return (p->Count = Counter); } int Bac_ManClpObjNum( Bac_Man_t * p ) { Bac_Ntk_t * pNtk; int i; Bac_ManForEachNtk( p, pNtk, i ) pNtk->Count = -1; return Bac_NtkPioNum( Bac_ManRoot(p) ) + Bac_ManClpObjNum_rec( Bac_ManRoot(p) ); } /**Function************************************************************* Synopsis [Collects boxes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_NtkDfs_rec( Bac_Ntk_t * p, int iObj, Vec_Int_t * vBoxes ) { int k, iFanin; if ( Bac_ObjIsBo(p, iObj) == 1 ) { Bac_NtkDfs_rec( p, Bac_ObjFanin(p, iObj), vBoxes ); return; } assert( Bac_ObjIsPi(p, iObj) || Bac_ObjIsBox(p, iObj) ); if ( Bac_ObjCopy(p, iObj) > 0 ) // visited return; Bac_ObjSetCopy( p, iObj, 1 ); Bac_BoxForEachFanin( p, iObj, iFanin, k ) Bac_NtkDfs_rec( p, iFanin, vBoxes ); Vec_IntPush( vBoxes, iObj ); } Vec_Int_t * Bac_NtkDfs( Bac_Ntk_t * p ) { int i, iObj; Vec_Int_t * vBoxes = Vec_IntAlloc( Bac_NtkBoxNum(p) ); Bac_NtkStartCopies( p ); // -1 = not visited; 1 = finished Bac_NtkForEachPi( p, iObj, i ) Bac_ObjSetCopy( p, iObj, 1 ); Bac_NtkForEachPo( p, iObj, i ) Bac_NtkDfs_rec( p, Bac_ObjFanin(p, iObj), vBoxes ); return vBoxes; } /**Function************************************************************* Synopsis [Collects user boxes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_NtkDfsUserBoxes_rec( Bac_Ntk_t * p, int iObj, Vec_Int_t * vBoxes ) { int k, iFanin; assert( Bac_ObjIsBoxUser(p, iObj) ); if ( Bac_ObjCopy(p, iObj) == 1 ) // visited return 1; if ( Bac_ObjCopy(p, iObj) == 0 ) // loop return 0; Bac_ObjSetCopy( p, iObj, 0 ); Bac_BoxForEachFanin( p, iObj, iFanin, k ) if ( Bac_ObjIsBo(p, iFanin) && Bac_ObjIsBoxUser(p, Bac_ObjFanin(p, iFanin)) ) if ( !Bac_NtkDfsUserBoxes_rec( p, Bac_ObjFanin(p, iFanin), vBoxes ) ) return 0; Vec_IntPush( vBoxes, iObj ); Bac_ObjSetCopy( p, iObj, 1 ); return 1; } int Bac_NtkDfsUserBoxes( Bac_Ntk_t * p ) { int iObj; Bac_NtkStartCopies( p ); // -1 = not visited; 0 = on the path; 1 = finished Vec_IntClear( &p->vArray ); Bac_NtkForEachBoxUser( p, iObj ) if ( !Bac_NtkDfsUserBoxes_rec( p, iObj, &p->vArray ) ) { printf( "Cyclic dependency of user boxes is detected.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_NtkCollapse_rec( Bac_Ntk_t * pNew, Bac_Ntk_t * p, Vec_Int_t * vSigs ) { int i, iObj, iObjNew, iTerm; Bac_NtkStartCopies( p ); // set PI copies assert( Vec_IntSize(vSigs) == Bac_NtkPiNum(p) ); Bac_NtkForEachPi( p, iObj, i ) Bac_ObjSetCopy( p, iObj, Vec_IntEntry(vSigs, i) ); // duplicate internal objects and create buffers for hierarchy instances Bac_NtkForEachBox( p, iObj ) if ( Bac_ObjIsBoxPrim( p, iObj ) ) Bac_BoxDup( pNew, p, iObj ); else { Bac_BoxForEachBo( p, iObj, iTerm, i ) { iObjNew = Bac_ObjAlloc( pNew, BAC_OBJ_BI, -1 ); iObjNew = Bac_ObjAlloc( pNew, BAC_BOX_BUF, -1 ); // buffer iObjNew = Bac_ObjAlloc( pNew, BAC_OBJ_BO, -1 ); Bac_ObjSetCopy( p, iTerm, iObjNew ); } } // duplicate user modules and connect objects Bac_NtkForEachBox( p, iObj ) if ( Bac_ObjIsBoxPrim( p, iObj ) ) { Bac_BoxForEachBi( p, iObj, iTerm, i ) Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iTerm), Bac_ObjCopy(p, Bac_ObjFanin(p, iTerm)) ); } else { Vec_IntClear( vSigs ); Bac_BoxForEachBi( p, iObj, iTerm, i ) Vec_IntPush( vSigs, Bac_ObjCopy(p, Bac_ObjFanin(p, iTerm)) ); Bac_NtkCollapse_rec( pNew, Bac_BoxNtk(p, iObj), vSigs ); assert( Vec_IntSize(vSigs) == Bac_BoxBoNum(p, iObj) ); Bac_BoxForEachBo( p, iObj, iTerm, i ) Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iTerm)-2, Vec_IntEntry(vSigs, i) ); } // collect POs Vec_IntClear( vSigs ); Bac_NtkForEachPo( p, iObj, i ) Vec_IntPush( vSigs, Bac_ObjCopy(p, Bac_ObjFanin(p, iObj)) ); } Bac_Man_t * Bac_ManCollapse( Bac_Man_t * p ) { int i, iObj; Vec_Int_t * vSigs = Vec_IntAlloc( 1000 ); Bac_Man_t * pNew = Bac_ManStart( p, 1 ); Bac_Ntk_t * pRoot = Bac_ManRoot( p ); Bac_Ntk_t * pRootNew = Bac_ManRoot( pNew ); Bac_NtkAlloc( pRootNew, Bac_NtkNameId(pRoot), Bac_NtkPiNum(pRoot), Bac_NtkPoNum(pRoot), Bac_ManClpObjNum(p) ); if ( Vec_IntSize(&pRoot->vInfo) ) Vec_IntAppend( &pRootNew->vInfo, &pRoot->vInfo ); Bac_NtkForEachPi( pRoot, iObj, i ) Vec_IntPush( vSigs, Bac_ObjAlloc(pRootNew, BAC_OBJ_PI, -1) ); Bac_NtkCollapse_rec( pRootNew, pRoot, vSigs ); assert( Vec_IntSize(vSigs) == Bac_NtkPoNum(pRoot) ); Bac_NtkForEachPo( pRoot, iObj, i ) Bac_ObjAlloc( pRootNew, BAC_OBJ_PO, Vec_IntEntry(vSigs, i) ); assert( Bac_NtkObjNum(pRootNew) == Bac_NtkObjNumAlloc(pRootNew) ); Vec_IntFree( vSigs ); // transfer PI/PO names if ( Bac_NtkHasNames(pRoot) ) { Bac_NtkStartNames( pRootNew ); Bac_NtkForEachPi( pRoot, iObj, i ) Bac_ObjSetName( pRootNew, Bac_NtkPi(pRootNew, i), Bac_ObjName(pRoot, iObj) ); Bac_NtkForEachPoDriver( pRoot, iObj, i ) if ( !Bac_ObjIsPi(pRoot, iObj) ) Bac_ObjSetName( pRootNew, Bac_ObjCopy(pRoot, iObj), Bac_ObjName(pRoot, iObj) ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacOper.c000066400000000000000000000311271300674244400232160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacOper.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Operator procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacOper.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_BoxCreate( Bac_Ntk_t * p, Bac_ObjType_t Type, Vec_Int_t * vFanins, int nInA, int nInB, int nOuts ) { char pName[100]; int i, iObj, iFanin; assert( BAC_OBJ_BOX < Type && Type < BAC_BOX_UNKNOWN ); if ( BAC_BOX_CF <= Type && Type <= BAC_BOX_CZ ) { sprintf( pName, "ABCCTo%d", nOuts ); assert( 0 == Vec_IntSize(vFanins) ); iObj = Bac_BoxAlloc( p, Type, 0, nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) ); } else if ( BAC_BOX_BUF <= Type && Type <= BAC_BOX_INV ) { char * pPref[2] = { "ABCBUF", "ABCINV" }; assert( nInA == nOuts ); assert( nInA == Vec_IntSize(vFanins) ); sprintf( pName, "%sa%do%d", pPref[Type - BAC_BOX_BUF], nInA, nOuts ); iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) ); } else if ( BAC_BOX_AND <= Type && Type <= BAC_BOX_XNOR ) { char * pPref[6] = { "ABCAND", "ABCNAND", "ABCOR", "ABCNOR", "ABCXOR", "ABCXNOR" }; assert( nInA == nOuts && nInB == nOuts ); assert( nInA + nInB == Vec_IntSize(vFanins) ); sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_AND], nInA, nInB, nOuts ); iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) ); } else if ( Type == BAC_BOX_MUX ) { char * pPref[1] = { "ABCMUX" }; assert( nInA == nOuts && nInB == nOuts ); assert( 1 + nInA + nInB == Vec_IntSize(vFanins) ); sprintf( pName, "%sc%da%db%do%d", pPref[Type - BAC_BOX_MUX], 1, nInA, nInB, nOuts ); iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) ); } else if ( Type == BAC_BOX_MAJ ) { char * pPref[1] = { "ABCMAJ" }; assert( nInA == 1 && nInB == 1 && nOuts == 1 ); assert( 3 == Vec_IntSize(vFanins) ); sprintf( pName, "%sa%db%dc%do%d", pPref[Type - BAC_BOX_MAJ], 1, 1, 1, 1 ); iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) ); } else if ( BAC_BOX_RAND <= Type && Type <= BAC_BOX_RXNOR ) { char * pPref[6] = { "ABCRAND", "ABCRNAND", "ABCROR", "ABCRNOR", "ABCRXOR", "ABCRXNOR" }; assert( nInA == nInB && 1 == nOuts ); assert( nInA + nInB == Vec_IntSize(vFanins) ); sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_RAND], nInA, nInB, nOuts ); iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) ); } else if ( Type == BAC_BOX_SEL ) { char * pPref[1] = { "ABCSEL" }; assert( nInA * nOuts == nInB ); assert( nInA + nInB == Vec_IntSize(vFanins) ); sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_SEL], nInA, nInB, nOuts ); iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) ); } else if ( Type == BAC_BOX_PSEL ) { char * pPref[1] = { "ABCPSEL" }; assert( nInA * nOuts == nInB ); assert( 1 + nInA + nInB == Vec_IntSize(vFanins) ); sprintf( pName, "%si%da%db%do%d", pPref[Type - BAC_BOX_SEL], 1, nInA, nInB, nOuts ); iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) ); } // add fanins Vec_IntForEachEntry( vFanins, iFanin, i ) Bac_ObjSetFanin( p, Bac_BoxBi(p, iObj, i), iFanin ); return iObj; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_ObjClpWide( Bac_Ntk_t * p, int iBox ) { Bac_ObjType_t Type = Bac_ObjType( p, iBox ); int nBis = Bac_BoxBiNum(p, iBox); int nBos = Bac_BoxBoNum(p, iBox); int i, k, iObj; assert( nBos > 1 ); Vec_IntClear( &p->vArray ); if ( BAC_BOX_BUF <= Type && Type <= BAC_BOX_INV ) { for ( i = 0; i < nBos; i++ ) { Vec_IntFill( &p->vArray2, 1, Bac_BoxFanin(p, iBox, i) ); iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, -1, 1 ); Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) ); } } else if ( BAC_BOX_AND <= Type && Type <= BAC_BOX_XNOR ) { assert( nBis == 2 * nBos ); for ( i = 0; i < nBos; i++ ) { Vec_IntFillTwo( &p->vArray2, 2, Bac_BoxFanin(p, iBox, i), Bac_BoxFanin(p, iBox, nBos+i) ); iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, 1, 1 ); Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) ); } } else if ( Type == BAC_BOX_MUX ) { assert( nBis - 1 == 2 * nBos ); for ( i = 0; i < nBos; i++ ) { Vec_IntFill( &p->vArray2, 1, Bac_BoxFanin(p, iBox, 0) ); Vec_IntPushTwo( &p->vArray2, Bac_BoxFanin(p, iBox, 1+i), Bac_BoxFanin(p, iBox, 1+nBos+i) ); iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, 1, 1 ); Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) ); } } else if ( Type == BAC_BOX_NMUX ) { int n, nIns = nBis / nBos; assert( nBis % nBos == 0 ); for ( n = 1; n < 32; n++ ) if ( n + (1 << n) == nIns ) break; assert( n > 1 && n < 32 ); for ( i = 0; i < nBos; i++ ) { Vec_IntClear( &p->vArray2 ); for ( k = 0; k < n; k++ ) Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, k) ); for ( k = 0; k < (1 << n); k++ ) Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, n + (1 << n) * i + k) ); iObj = Bac_BoxCreate( p, Type, &p->vArray2, n, (1 << n), 1 ); Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) ); } } else if ( Type == BAC_BOX_SEL ) { } else if ( Type == BAC_BOX_PSEL ) { } else if ( Type == BAC_BOX_DFF || Type == BAC_BOX_LATCH ) { } else if ( Type == BAC_BOX_DFFRS || Type == BAC_BOX_LATCHRS ) { } else assert( 0 ); Bac_BoxReplace( p, iBox, Vec_IntArray(&p->vArray), Vec_IntSize(&p->vArray) ); return iBox; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_ObjClpArith( Bac_Ntk_t * p, int iBox ) { Bac_ObjType_t Type = Bac_ObjType( p, iBox ); int i, iObj = -1; int nBis = 0;//Bac_NtkReadRangesPrim( Bac_BoxNtkName(p, iObj), &p->vArray, 0 ); assert( nBis == Bac_BoxBiNum(p, iBox) ); if ( Type == BAC_BOX_ADD ) { int Carry = Bac_BoxFanin(p, iBox, 0); int nBits = Vec_IntEntry(&p->vArray, 1); assert( Vec_IntSize(&p->vArray) == 3 ); assert( Vec_IntEntry(&p->vArray, 0) == 1 ); assert( Vec_IntEntry(&p->vArray, 2) == nBits ); Vec_IntClear( &p->vArray ); for ( i = 0; i < nBits; i++ ) { Vec_IntFill( &p->vArray2, 1, Carry ); Vec_IntPushTwo( &p->vArray2, Bac_BoxFanin(p, iBox, 1+i), Bac_BoxFanin(p, iBox, 1+nBits+i) ); iObj = Bac_BoxCreate( p, BAC_BOX_ADD, &p->vArray2, 1, 1, 1 ); Carry = Bac_BoxBo(p, iObj, 1); Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) ); } Vec_IntPush( &p->vArray, Carry ); } else if ( Type == BAC_BOX_SUB ) { int iConst, nBits = Vec_IntEntry(&p->vArray, 0); assert( Vec_IntSize(&p->vArray) == 2 ); assert( Vec_IntEntry(&p->vArray, 1) == nBits ); // create inverter Vec_IntClear( &p->vArray2 ); for ( i = 0; i < nBits; i++ ) Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, nBits+i) ); iObj = Bac_BoxCreate( p, BAC_BOX_INV, &p->vArray2, nBits, -1, nBits ); // create constant Vec_IntClear( &p->vArray2 ); iConst = Bac_BoxCreate( p, BAC_BOX_CT, &p->vArray2, -1, -1, 1 ); // collect fanins Vec_IntFill( &p->vArray2, 1, iConst+1 ); for ( i = 0; i < nBits; i++ ) Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, i) ); for ( i = 0; i < nBits; i++ ) Vec_IntPush( &p->vArray2, Bac_BoxBo(p, iObj, i) ); // create adder iObj = Bac_BoxCreate( p, BAC_BOX_ADD, &p->vArray2, nBits, nBits, nBits ); // collect fanins Vec_IntClear( &p->vArray ); for ( i = 0; i < nBits; i++ ) Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, i) ); } else if ( Type == BAC_BOX_MUL ) { } else if ( Type == BAC_BOX_DIV ) { } else if ( Type == BAC_BOX_MOD ) { } else if ( Type == BAC_BOX_REM ) { } else if ( Type == BAC_BOX_POW ) { } else if ( Type == BAC_BOX_MIN ) { } else if ( Type == BAC_BOX_ABS ) { } else if ( Type == BAC_BOX_LTHAN ) { } else if ( Type == BAC_BOX_LETHAN ) { } else if ( Type == BAC_BOX_METHAN ) { } else if ( Type == BAC_BOX_MTHAN ) { } else if ( Type == BAC_BOX_EQU ) { } else if ( Type == BAC_BOX_NEQU ) { } else if ( Type == BAC_BOX_SHIL ) { } else if ( Type == BAC_BOX_SHIR ) { } else if ( Type == BAC_BOX_ROTL ) { } else if ( Type == BAC_BOX_ROTR ) { } Bac_BoxReplace( p, iBox, Vec_IntArray(&p->vArray), Vec_IntSize(&p->vArray) ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_ObjClpMemory( Bac_Ntk_t * p, int iBox ) { int i, En, iNext, nItems = Bac_BoxBiNum(p, iBox); assert( Bac_ObjType(p, iBox) == BAC_BOX_RAMBOX ); assert( Bac_BoxBiNum(p, iBox) == Bac_BoxBoNum(p, iBox) ); // for each fanin of RAMBOX, make sure address width is the same Bac_BoxForEachFaninBox( p, iBox, iNext, i ) assert( Bac_ObjType(p, iNext) == BAC_BOX_RAMWC ); // create decoders, selectors and flops for ( i = 0; i < nItems; i++ ) { int BoxW = Bac_ObjFanin(p, Bac_BoxBi(p, iBox, i)); int BoxR = Bac_ObjFanout(p, Bac_BoxBo(p, iBox, 0)); assert( Bac_ObjType(p, BoxW) == BAC_BOX_RAMWC ); assert( Bac_ObjType(p, BoxR) == BAC_BOX_RAMR ); // create enable Vec_IntFillTwo( &p->vArray2, 2, Bac_BoxFanin(p, BoxW, 1), Bac_BoxFanin(p, BoxR, 0) ); En = Bac_BoxCreate( p, BAC_BOX_AND, &p->vArray2, 1, 1, 1 ); En = Bac_BoxBo( p, En, 0 ); // collect address } // for each fanout of RAMBOX, makes ure address width is the same // Bac_BoxForEachFanoutBox( p, iBox, iNext, i ) // assert( Bac_ObjType(p, iNext) == BAC_BOX_RAMR ); // create selectors and connect them return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacPrs.h000066400000000000000000000343621300674244400230660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacPrs.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Parser declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacPrs.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__prs__prs_h #define ABC__base__prs__prs_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "misc/util/utilNam.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START // parser name types typedef enum { BAC_PRS_NAME = 0, // 0: name/variable BAC_PRS_SLICE, // 1: slice BAC_PRS_CONST, // 2: constant BAC_PRS_CONCAT, // 3: concatentation } Psr_ManType_t; //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // network typedef struct Psr_Ntk_t_ Psr_Ntk_t; struct Psr_Ntk_t_ { // general info int iModuleName; unsigned fMapped : 1; unsigned fSlices : 1; unsigned fHasC0s : 1; unsigned fHasC1s : 1; unsigned fHasCXs : 1; unsigned fHasCZs : 1; Abc_Nam_t * pStrs; // interface Vec_Int_t vOrder; // order of signals // signal names Vec_Int_t vInouts; // inouts Vec_Int_t vInputs; // inputs Vec_Int_t vOutputs; // outputs Vec_Int_t vWires; // wires // signal ranges Vec_Int_t vInoutsR; // inouts Vec_Int_t vInputsR; // inputs Vec_Int_t vOutputsR; // outputs Vec_Int_t vWiresR; // wires // slices/concatenations/objects Vec_Int_t vSlices; // NameId + RangeId Vec_Int_t vConcats; // array of NameId/SliceId/ConstId Vec_Int_t vBoxes; // ModuleId + InstId + array of pairs {FormNameId, ActSignalId(NameId/SliceId/ConstId/ConcatId)} Vec_Int_t vObjs; // box handles }; // parser typedef struct Psr_Man_t_ Psr_Man_t; struct Psr_Man_t_ { // input data char * pName; // file name char * pBuffer; // file contents char * pLimit; // end of file char * pCur; // current position Abc_Nam_t * pStrs; // string manager Psr_Ntk_t * pNtk; // current network Vec_Ptr_t * vNtks; // input networks // temporary data Vec_Str_t vCover; // one SOP cover Vec_Int_t vTemp; // array of tokens Vec_Int_t vTemp2; // array of tokens // statistics Vec_Int_t vKnown; Vec_Int_t vFailed; Vec_Int_t vSucceeded; // error handling int fUsingTemp2; // vTemp2 is in use char ErrorStr[1000]; // error }; static inline Psr_Ntk_t * Psr_ManNtk( Vec_Ptr_t * vPrs, int i ) { return i >= 0 && i < Vec_PtrSize(vPrs) ? (Psr_Ntk_t *)Vec_PtrEntry(vPrs, i) : NULL; } static inline Psr_Ntk_t * Psr_ManRoot( Vec_Ptr_t * vPrs ) { return Psr_ManNtk(vPrs, 0); } static inline Abc_Nam_t * Psr_ManNameMan( Vec_Ptr_t * vPrs ) { return Psr_ManRoot(vPrs)->pStrs; } static inline int Psr_NtkId( Psr_Ntk_t * p ) { return p->iModuleName; } static inline int Psr_NtkPioNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vInouts); } static inline int Psr_NtkPiNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vInputs); } static inline int Psr_NtkPoNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vOutputs); } static inline int Psr_NtkBoxNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); } static inline int Psr_NtkObjNum( Psr_Ntk_t * p ) { return Psr_NtkPioNum(p) + Psr_NtkPiNum(p) + Psr_NtkPoNum(p) + Psr_NtkBoxNum(p); } static inline char * Psr_NtkStr( Psr_Ntk_t * p, int h ) { return Abc_NamStr(p->pStrs, h); } static inline char * Psr_NtkName( Psr_Ntk_t * p ) { return Psr_NtkStr(p, Psr_NtkId(p)); } static inline int Psr_NtkSigName( Psr_Ntk_t * p, int i ) { if (!p->fSlices) return i; assert(Abc_Lit2Att2(i) == BAC_PRS_NAME); return Abc_Lit2Var2(i); } static inline int Psr_SliceName( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h); } static inline int Psr_SliceRange( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h+1); } static inline int Psr_CatSize( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vConcats, h); } static inline int * Psr_CatArray( Psr_Ntk_t * p, int h ) { return Vec_IntEntryP(&p->vConcats, h+1); } static inline Vec_Int_t * Psr_CatSignals( Psr_Ntk_t * p, int h ) { static Vec_Int_t V; V.nSize = V.nCap = Psr_CatSize(p, h); V.pArray = Psr_CatArray(p, h); return &V; } static inline int Psr_BoxHand( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vObjs, i); } static inline int Psr_BoxSize( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i))-2; } static inline int Psr_BoxIONum( Psr_Ntk_t * p, int i ) { return Psr_BoxSize(p, i) / 2; } static inline int Psr_BoxNtk( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+1); } static inline void Psr_BoxSetNtk( Psr_Ntk_t * p, int i, int m ) { Vec_IntWriteEntry(&p->vBoxes, Psr_BoxHand(p, i)+1, m); } static inline int Psr_BoxName( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+2); } static inline int Psr_BoxIsNode( Psr_Ntk_t * p, int i ) { return!Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+3); } // no formal names static inline int * Psr_BoxArray( Psr_Ntk_t * p, int i ) { return Vec_IntEntryP(&p->vBoxes, Psr_BoxHand(p, i)+3); } static inline Vec_Int_t * Psr_BoxSignals( Psr_Ntk_t * p, int i ) { static Vec_Int_t V; V.nSize = V.nCap = Psr_BoxSize(p, i); V.pArray = Psr_BoxArray(p, i); return &V; } #define Psr_ManForEachNameVec( vVec, p, pName, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pName) = Abc_NamStr(p->pStrs, Vec_IntEntry(vVec,i))); i++ ) #define Psr_NtkForEachPio( p, NameId, i ) \ for ( i = 0; i < Psr_NtkPioNum(p) && ((NameId) = Vec_IntEntry(&p->vInouts, i)); i++ ) #define Psr_NtkForEachPi( p, NameId, i ) \ for ( i = 0; i < Psr_NtkPiNum(p) && ((NameId) = Vec_IntEntry(&p->vInputs, i)); i++ ) #define Psr_NtkForEachPo( p, NameId, i ) \ for ( i = 0; i < Psr_NtkPoNum(p) && ((NameId) = Vec_IntEntry(&p->vOutputs, i)); i++ ) #define Psr_NtkForEachBox( p, vVec, i ) \ for ( i = 0; i < Psr_NtkBoxNum(p) && ((vVec) = Psr_BoxSignals(p, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // create error message static inline int Psr_ManErrorSet( Psr_Man_t * p, char * pError, int Value ) { assert( !p->ErrorStr[0] ); sprintf( p->ErrorStr, "%s", pError ); return Value; } // clear error message static inline void Psr_ManErrorClear( Psr_Man_t * p ) { p->ErrorStr[0] = '\0'; } // print error message static inline int Psr_ManErrorPrint( Psr_Man_t * p ) { char * pThis; int iLine = 0; if ( !p->ErrorStr[0] ) return 1; for ( pThis = p->pBuffer; pThis < p->pCur; pThis++ ) iLine += (int)(*pThis == '\n'); printf( "Line %d: %s\n", iLine, p->ErrorStr ); return 0; } // parsing network static inline void Psr_ManInitializeNtk( Psr_Man_t * p, int iName, int fSlices ) { assert( p->pNtk == NULL ); p->pNtk = ABC_CALLOC( Psr_Ntk_t, 1 ); p->pNtk->iModuleName = iName; p->pNtk->fSlices = fSlices; p->pNtk->pStrs = Abc_NamRef( p->pStrs ); Vec_PtrPush( p->vNtks, p->pNtk ); } static inline void Psr_ManFinalizeNtk( Psr_Man_t * p ) { assert( p->pNtk != NULL ); p->pNtk = NULL; } // parsing slice/concatentation/box static inline int Psr_NtkAddSlice( Psr_Ntk_t * p, int Name, int Range ) { int Value = Vec_IntSize(&p->vSlices); Vec_IntPushTwo( &p->vSlices, Name, Range ); return Value; } static inline int Psr_NtkAddConcat( Psr_Ntk_t * p, Vec_Int_t * vTemp ) { int Value; if ( !(Vec_IntSize(&p->vConcats) & 1) ) Vec_IntPush(&p->vConcats, -1); Value = Vec_IntSize(&p->vConcats); assert( Value & 1 ); Vec_IntPush( &p->vConcats, Vec_IntSize(vTemp) ); Vec_IntAppend( &p->vConcats, vTemp ); return Value; } static inline void Psr_NtkAddBox( Psr_Ntk_t * p, int ModName, int InstName, Vec_Int_t * vTemp ) { int Value; assert( Vec_IntSize(vTemp) % 2 == 0 ); if ( !(Vec_IntSize(&p->vBoxes) & 1) ) Vec_IntPush(&p->vBoxes, -1); Value = Vec_IntSize(&p->vBoxes); assert( Value & 1 ); Vec_IntPush( &p->vObjs, Value ); // create entry Vec_IntPush( &p->vBoxes, Vec_IntSize(vTemp)+2 ); Vec_IntPush( &p->vBoxes, ModName ); Vec_IntPush( &p->vBoxes, InstName ); Vec_IntAppend( &p->vBoxes, vTemp ); } static inline char * Psr_ManLoadFile( char * pFileName, char ** ppLimit ) { char * pBuffer; int nFileSize, RetValue; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file.\n" ); return NULL; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nFileSize + 16 ); pBuffer[0] = '\n'; RetValue = fread( pBuffer+1, nFileSize, 1, pFile ); fclose( pFile ); // terminate the string with '\0' pBuffer[nFileSize + 1] = '\n'; pBuffer[nFileSize + 2] = '\0'; *ppLimit = pBuffer + nFileSize + 3; return pBuffer; } static inline Psr_Man_t * Psr_ManAlloc( char * pFileName ) { Psr_Man_t * p; char * pBuffer, * pLimit; pBuffer = Psr_ManLoadFile( pFileName, &pLimit ); if ( pBuffer == NULL ) return NULL; p = ABC_CALLOC( Psr_Man_t, 1 ); p->pName = pFileName; p->pBuffer = pBuffer; p->pLimit = pLimit; p->pCur = pBuffer; p->pStrs = Abc_NamStart( 1000, 24 ); p->vNtks = Vec_PtrAlloc( 100 ); return p; } static inline void Psr_NtkFree( Psr_Ntk_t * p ) { if ( p->pStrs ) Abc_NamDeref( p->pStrs ); Vec_IntErase( &p->vOrder ); Vec_IntErase( &p->vInouts ); Vec_IntErase( &p->vInputs ); Vec_IntErase( &p->vOutputs ); Vec_IntErase( &p->vWires ); Vec_IntErase( &p->vInoutsR ); Vec_IntErase( &p->vInputsR ); Vec_IntErase( &p->vOutputsR ); Vec_IntErase( &p->vWiresR ); Vec_IntErase( &p->vSlices ); Vec_IntErase( &p->vConcats ); Vec_IntErase( &p->vBoxes ); Vec_IntErase( &p->vObjs ); ABC_FREE( p ); } static inline void Psr_ManVecFree( Vec_Ptr_t * vPrs ) { Psr_Ntk_t * pNtk; int i; Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i ) Psr_NtkFree( pNtk ); Vec_PtrFree( vPrs ); } static inline void Psr_ManFree( Psr_Man_t * p ) { if ( p->pStrs ) Abc_NamDeref( p->pStrs ); if ( p->vNtks ) Psr_ManVecFree( p->vNtks ); // temporary Vec_StrErase( &p->vCover ); Vec_IntErase( &p->vTemp ); Vec_IntErase( &p->vTemp2 ); Vec_IntErase( &p->vKnown ); Vec_IntErase( &p->vFailed ); Vec_IntErase( &p->vSucceeded ); ABC_FREE( p->pBuffer ); ABC_FREE( p ); } static inline int Psr_NtkMemory( Psr_Ntk_t * p ) { int nMem = sizeof(Psr_Ntk_t); nMem += Vec_IntMemory( &p->vOrder ); nMem += Vec_IntMemory( &p->vInouts ); nMem += Vec_IntMemory( &p->vInputs ); nMem += Vec_IntMemory( &p->vOutputs ); nMem += Vec_IntMemory( &p->vWires ); nMem += Vec_IntMemory( &p->vInoutsR ); nMem += Vec_IntMemory( &p->vInputsR ); nMem += Vec_IntMemory( &p->vOutputsR ); nMem += Vec_IntMemory( &p->vWiresR ); nMem += Vec_IntMemory( &p->vSlices ); nMem += Vec_IntMemory( &p->vBoxes ); nMem += Vec_IntMemory( &p->vConcats ); return nMem; } static inline int Psr_ManMemory( Vec_Ptr_t * vPrs ) { Psr_Ntk_t * pNtk; int i; int nMem = Vec_PtrMemory(vPrs); Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i ) nMem += Psr_NtkMemory( pNtk ); nMem += Abc_NamMemUsed(Psr_ManNameMan(vPrs)); return nMem; } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== bac.c ========================================================*/ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacPrsBuild.c000066400000000000000000000333071300674244400240370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacPrsBuild.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Parse tree to netlist transformation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacPrsBuild.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "bacPrs.h" #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Psr_ManIsMapped( Psr_Ntk_t * pNtk ) { Vec_Int_t * vSigs; int iBox; Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pLib == NULL ) return 0; Psr_NtkForEachBox( pNtk, vSigs, iBox ) if ( !Psr_BoxIsNode(pNtk, iBox) ) { int NtkId = Psr_BoxNtk( pNtk, iBox ); if ( Mio_LibraryReadGateByName(pLib, Psr_NtkStr(pNtk, NtkId), NULL) ) return 1; } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Psr_NtkCountObjects( Psr_Ntk_t * pNtk ) { Vec_Int_t * vFanins; int i, Count = Psr_NtkObjNum(pNtk); Psr_NtkForEachBox( pNtk, vFanins, i ) Count += Psr_BoxIONum(pNtk, i); return Count; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // replaces NameIds of formal names by their index in the box model void Psr_ManRemapOne( Vec_Int_t * vSigs, Psr_Ntk_t * pNtkBox, Vec_Int_t * vMap ) { int i, NameId; // map formal names into I/O indexes Psr_NtkForEachPi( pNtkBox, NameId, i ) { assert( Vec_IntEntry(vMap, NameId) == -1 ); Vec_IntWriteEntry( vMap, NameId, i + 1 ); // +1 to keep 1st form input non-zero } Psr_NtkForEachPo( pNtkBox, NameId, i ) { assert( Vec_IntEntry(vMap, NameId) == -1 ); Vec_IntWriteEntry( vMap, NameId, Psr_NtkPiNum(pNtkBox) + i + 1 ); // +1 to keep 1st form input non-zero } // remap box assert( Vec_IntSize(vSigs) % 2 == 0 ); Vec_IntForEachEntry( vSigs, NameId, i ) { assert( Vec_IntEntry(vMap, NameId) != -1 ); Vec_IntWriteEntry( vSigs, i++, Vec_IntEntry(vMap, NameId) ); } // unmap formal inputs Psr_NtkForEachPi( pNtkBox, NameId, i ) Vec_IntWriteEntry( vMap, NameId, -1 ); Psr_NtkForEachPo( pNtkBox, NameId, i ) Vec_IntWriteEntry( vMap, NameId, -1 ); } void Psr_ManRemapGate( Vec_Int_t * vSigs ) { int i, FormId; Vec_IntForEachEntry( vSigs, FormId, i ) Vec_IntWriteEntry( vSigs, i, i/2 + 1 ), i++; } void Psr_ManRemapBoxes( Bac_Man_t * pNew, Vec_Ptr_t * vDes, Psr_Ntk_t * pNtk, Vec_Int_t * vMap ) { Vec_Int_t * vSigs; int iBox; Psr_NtkForEachBox( pNtk, vSigs, iBox ) if ( !Psr_BoxIsNode(pNtk, iBox) ) { int NtkId = Psr_BoxNtk( pNtk, iBox ); int NtkIdNew = Bac_ManNtkFindId( pNew, Psr_NtkStr(pNtk, NtkId) ); assert( NtkIdNew > 0 ); Psr_BoxSetNtk( pNtk, iBox, NtkIdNew ); if ( NtkIdNew <= Bac_ManNtkNum(pNew) ) Psr_ManRemapOne( vSigs, Psr_ManNtk(vDes, NtkIdNew-1), vMap ); //else // Psr_ManRemapGate( vSigs ); } } void Psr_ManCleanMap( Psr_Ntk_t * pNtk, Vec_Int_t * vMap ) { Vec_Int_t * vSigs; int i, k, NameId, Sig; Psr_NtkForEachPi( pNtk, NameId, i ) Vec_IntWriteEntry( vMap, NameId, -1 ); Psr_NtkForEachBox( pNtk, vSigs, i ) Vec_IntForEachEntryDouble( vSigs, NameId, Sig, k ) Vec_IntWriteEntry( vMap, Psr_NtkSigName(pNtk, Sig), -1 ); Psr_NtkForEachPo( pNtk, NameId, i ) Vec_IntWriteEntry( vMap, NameId, -1 ); } // create maps of NameId and boxes void Psr_ManBuildNtk( Bac_Ntk_t * pNew, Vec_Ptr_t * vDes, Psr_Ntk_t * pNtk, Vec_Int_t * vMap, Vec_Int_t * vBoxes ) { Psr_Ntk_t * pNtkBox; Vec_Int_t * vSigs; int iBox; int i, Index, NameId, iObj, iConst0, iTerm; int iNonDriven = -1, nNonDriven = 0; assert( Psr_NtkPioNum(pNtk) == 0 ); Psr_ManRemapBoxes( pNew->pDesign, vDes, pNtk, vMap ); Bac_NtkStartNames( pNew ); // create primary inputs Psr_NtkForEachPi( pNtk, NameId, i ) { if ( Vec_IntEntry(vMap, NameId) != -1 ) printf( "Primary inputs %d and %d have the same name.\n", Vec_IntEntry(vMap, NameId), i ); iObj = Bac_ObjAlloc( pNew, BAC_OBJ_PI, -1 ); Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(NameId, BAC_NAME_BIN) ); Vec_IntWriteEntry( vMap, NameId, iObj ); } // create box outputs Vec_IntClear( vBoxes ); Psr_NtkForEachBox( pNtk, vSigs, iBox ) if ( !Psr_BoxIsNode(pNtk, iBox) ) { pNtkBox = Psr_ManNtk( vDes, Psr_BoxNtk(pNtk, iBox)-1 ); if ( pNtkBox == NULL ) { iObj = Bac_BoxAlloc( pNew, BAC_BOX_GATE, Vec_IntSize(vSigs)/2-1, 1, Psr_BoxNtk(pNtk, iBox) ); Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(Psr_BoxName(pNtk, iBox), BAC_NAME_BIN) ); // consider box output NameId = Vec_IntEntryLast( vSigs ); NameId = Psr_NtkSigName( pNtk, NameId ); if ( Vec_IntEntry(vMap, NameId) != -1 ) printf( "Box output name %d is already driven.\n", NameId ); iTerm = Bac_BoxBo( pNew, iObj, 0 ); Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) ); Vec_IntWriteEntry( vMap, NameId, iTerm ); } else { iObj = Bac_BoxAlloc( pNew, BAC_OBJ_BOX, Psr_NtkPiNum(pNtkBox), Psr_NtkPoNum(pNtkBox), Psr_BoxNtk(pNtk, iBox) ); Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(Psr_BoxName(pNtk, iBox), BAC_NAME_BIN) ); Bac_NtkSetHost( Bac_ManNtk(pNew->pDesign, Psr_BoxNtk(pNtk, iBox)), Bac_NtkId(pNew), iObj ); Vec_IntForEachEntry( vSigs, Index, i ) { i++; if ( --Index < Psr_NtkPiNum(pNtkBox) ) continue; assert( Index - Psr_NtkPiNum(pNtkBox) < Psr_NtkPoNum(pNtkBox) ); // consider box output NameId = Vec_IntEntry( vSigs, i ); NameId = Psr_NtkSigName( pNtk, NameId ); if ( Vec_IntEntry(vMap, NameId) != -1 ) printf( "Box output name %d is already driven.\n", NameId ); iTerm = Bac_BoxBo( pNew, iObj, Index - Psr_NtkPiNum(pNtkBox) ); Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) ); Vec_IntWriteEntry( vMap, NameId, iTerm ); } } // remember box Vec_IntPush( vBoxes, iObj ); } else { iObj = Bac_BoxAlloc( pNew, (Bac_ObjType_t)Psr_BoxNtk(pNtk, iBox), Psr_BoxIONum(pNtk, iBox)-1, 1, -1 ); // consider box output NameId = Vec_IntEntryLast( vSigs ); NameId = Psr_NtkSigName( pNtk, NameId ); if ( Vec_IntEntry(vMap, NameId) != -1 ) printf( "Node output name %d is already driven.\n", NameId ); iTerm = Bac_BoxBo( pNew, iObj, 0 ); Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) ); Vec_IntWriteEntry( vMap, NameId, iTerm ); // remember box Vec_IntPush( vBoxes, iObj ); } // add fanins for box inputs Psr_NtkForEachBox( pNtk, vSigs, iBox ) if ( !Psr_BoxIsNode(pNtk, iBox) ) { pNtkBox = Psr_ManNtk( vDes, Psr_BoxNtk(pNtk, iBox)-1 ); iObj = Vec_IntEntry( vBoxes, iBox ); if ( pNtkBox == NULL ) { Vec_IntForEachEntryStop( vSigs, Index, i, Vec_IntSize(vSigs)-2 ) { i++; NameId = Vec_IntEntry( vSigs, i ); NameId = Psr_NtkSigName( pNtk, NameId ); iTerm = Bac_BoxBi( pNew, iObj, i/2 ); if ( Vec_IntEntry(vMap, NameId) == -1 ) { iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 ); Vec_IntWriteEntry( vMap, NameId, iConst0+1 ); if ( iNonDriven == -1 ) iNonDriven = NameId; nNonDriven++; } Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) ); } } else { Vec_IntForEachEntry( vSigs, Index, i ) { i++; if ( --Index >= Psr_NtkPiNum(pNtkBox) ) continue; NameId = Vec_IntEntry( vSigs, i ); NameId = Psr_NtkSigName( pNtk, NameId ); iTerm = Bac_BoxBi( pNew, iObj, Index ); if ( Vec_IntEntry(vMap, NameId) == -1 ) { iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 ); Vec_IntWriteEntry( vMap, NameId, iConst0+1 ); if ( iNonDriven == -1 ) iNonDriven = NameId; nNonDriven++; } Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) ); } } } else { iObj = Vec_IntEntry( vBoxes, iBox ); Vec_IntForEachEntryStop( vSigs, Index, i, Vec_IntSize(vSigs)-2 ) { NameId = Vec_IntEntry( vSigs, ++i ); NameId = Psr_NtkSigName( pNtk, NameId ); iTerm = Bac_BoxBi( pNew, iObj, i/2 ); if ( Vec_IntEntry(vMap, NameId) == -1 ) { iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 ); Vec_IntWriteEntry( vMap, NameId, iConst0+1 ); if ( iNonDriven == -1 ) iNonDriven = NameId; nNonDriven++; } Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) ); } } // add fanins for primary outputs Psr_NtkForEachPo( pNtk, NameId, i ) if ( Vec_IntEntry(vMap, NameId) == -1 ) { iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 ); Vec_IntWriteEntry( vMap, NameId, iConst0+1 ); if ( iNonDriven == -1 ) iNonDriven = NameId; nNonDriven++; } Psr_NtkForEachPo( pNtk, NameId, i ) iObj = Bac_ObjAlloc( pNew, BAC_OBJ_PO, Vec_IntEntry(vMap, NameId) ); if ( nNonDriven ) printf( "Module %s has %d non-driven nets (for example, %s).\n", Psr_NtkName(pNtk), nNonDriven, Psr_NtkStr(pNtk, iNonDriven) ); Psr_ManCleanMap( pNtk, vMap ); // setup info Vec_IntForEachEntry( &pNtk->vOrder, NameId, i ) Bac_NtkAddInfo( pNew, NameId, -1, -1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bac_Man_t * Psr_ManBuildCba( char * pFileName, Vec_Ptr_t * vDes ) { Psr_Ntk_t * pNtk = Psr_ManRoot( vDes ); int i; Bac_Man_t * pNew = Bac_ManAlloc( pFileName, Vec_PtrSize(vDes) ); Vec_Int_t * vMap = Vec_IntStartFull( Abc_NamObjNumMax(pNtk->pStrs) + 1 ); Vec_Int_t * vTmp = Vec_IntAlloc( Psr_NtkBoxNum(pNtk) ); Abc_NamDeref( pNew->pStrs ); pNew->pStrs = Abc_NamRef( pNtk->pStrs ); Vec_PtrForEachEntry( Psr_Ntk_t *, vDes, pNtk, i ) Bac_NtkAlloc( Bac_ManNtk(pNew, i+1), Psr_NtkId(pNtk), Psr_NtkPiNum(pNtk), Psr_NtkPoNum(pNtk), Psr_NtkCountObjects(pNtk) ); if ( (pNtk->fMapped || (pNtk->fSlices && Psr_ManIsMapped(pNtk))) && !Bac_NtkBuildLibrary(pNew) ) Bac_ManFree(pNew), pNew = NULL; else Vec_PtrForEachEntry( Psr_Ntk_t *, vDes, pNtk, i ) Psr_ManBuildNtk( Bac_ManNtk(pNew, i+1), vDes, pNtk, vMap, vTmp ); assert( Vec_IntCountEntry(vMap, -1) == Vec_IntSize(vMap) ); Vec_IntFree( vMap ); Vec_IntFree( vTmp ); // Vec_StrPrint( &Bac_ManNtk(pNew, 1)->vType, 1 ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacPrsTrans.c000066400000000000000000000252341300674244400240670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacPrsTrans.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Parse tree to netlist transformation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacPrsTrans.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "bacPrs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Bac_Trip_t_ Bac_Trip_t; struct Bac_Trip_t_ { Bac_ObjType_t Type; char * pName; char * pCode; char * pSigs[6]; }; /* static Bac_Trip_t s_Types[100] = { { BAC_BOX_CT , "VERIFIC_PWR", "1", {"o"} }, { BAC_BOX_CF , "VERIFIC_GND", "1", {"o"} }, { BAC_BOX_CX , "VERIFIC_X", "1", {"o"} }, { BAC_BOX_CZ , "VERIFIC_Z", "1", {"o"} }, { BAC_BOX_INV , "VERIFIC_INV", "11", {"i","o"} }, { BAC_BOX_BUF , "VERIFIC_BUF", "11", {"i","o"} }, { BAC_BOX_AND , "VERIFIC_AND", "111", {"a0","a1","o"} }, { BAC_BOX_NAND , "VERIFIC_NAND", "111", {"a0","a1","o"} }, { BAC_BOX_OR , "VERIFIC_OR", "111", {"a0","a1","o"} }, { BAC_BOX_NOR , "VERIFIC_NOR", "111", {"a0","a1","o"} }, { BAC_BOX_XOR , "VERIFIC_XOR", "111", {"a0","a1","o"} }, { BAC_BOX_XNOR , "VERIFIC_XNOR", "111", {"a0","a1","o"} }, { BAC_BOX_MUX , "VERIFIC_MUX", "1111", {"c","a1","a0","o"} }, // changed order { (Bac_ObjType_t)-1, "VERIFIC_PULLUP", "1", {"o"} }, { (Bac_ObjType_t)-1, "VERIFIC_PULLDOWN", "1", {"o"} }, { BAC_BOX_TRI , "VERIFIC_TRI", "111", {"i","c","o"} }, { BAC_BOX_LATCH , "VERIFIC_DLATCH", "11111", {"d","async_val","async_cond","gate","q"} }, // changed order { BAC_BOX_LATCHRS , "VERIFIC_DLATCHRS", "11111", {"d","s","r","gate","q"} }, // changed order { BAC_BOX_DFF , "VERIFIC_DFF", "11111", {"d","async_val","async_cond","clk","q"} }, // changed order { BAC_BOX_DFFRS , "VERIFIC_DFFRS", "11111", {"d","s","r","clk","q"} }, // changed order { (Bac_ObjType_t)-1, "VERIFIC_NMOS", "111", {"c","d","o"} }, { (Bac_ObjType_t)-1, "VERIFIC_PMOS", "111", {"c","d","o"} }, { (Bac_ObjType_t)-1, "VERIFIC_CMOS", "1111", {"d","nc","pc","o"} }, { (Bac_ObjType_t)-1, "VERIFIC_TRAN", "111", {"inout1","inout2","control"} }, { BAC_BOX_ADD , "VERIFIC_FADD", "11111", {"cin","a","b","o","cout"} }, { (Bac_ObjType_t)-1, "VERIFIC_RCMOS", "1111", {"d","nc","pc","o"} }, { (Bac_ObjType_t)-1, "VERIFIC_RNMOS", "111", {"c","d","o"} }, { (Bac_ObjType_t)-1, "VERIFIC_RPMOS", "111", {"c","d","o"} }, { (Bac_ObjType_t)-1, "VERIFIC_RTRAN", "111", {"inout1","inout2","control"} }, { (Bac_ObjType_t)-1, "VERIFIC_HDL_ASSERTION", "1", {"condition"} }, { BAC_BOX_ADD , "add_", "1aba1", {"cin","a","b","o","cout"} }, { BAC_BOX_MUL , "mult_", "ab?", {"a","b","o"} }, // ? = a * b { BAC_BOX_DIV , "div_", "ab?", {"a","b","o"} }, // ? = { BAC_BOX_MOD , "mod_", "ab?", {"a","b","o"} }, // ? = { BAC_BOX_REM , "rem_", "ab?", {"a","b","o"} }, // ? = { BAC_BOX_SHIL , "shift_left_", "1aba", {"cin","a","amount","o"} }, { BAC_BOX_SHIR , "shift_right_", "1aba", {"cin","a","amount","o"} }, { BAC_BOX_ROTL , "rotate_left_", "aba", {"a","amount","o"} }, { BAC_BOX_ROTR , "rotate_right_", "aba", {"a","amount","o"} }, { BAC_BOX_RAND , "reduce_and_", "ab1", {"a","o"} }, { BAC_BOX_ROR , "reduce_or_", "ab1", {"a","o"} }, { BAC_BOX_RXOR , "reduce_xor_", "ab1", {"a","o"} }, { BAC_BOX_RNAND , "reduce_nand_", "ab1", {"a","o"} }, { BAC_BOX_RNOR , "reduce_nor_", "ab1", {"a","o"} }, { BAC_BOX_RXNOR , "reduce_xnor_", "ab1", {"a","o"} }, { BAC_BOX_LTHAN , "LessThan_", "1ab1", {"cin","a","b","o"} }, { BAC_BOX_NMUX , "Mux_", "ab1", {"sel","data","o"} }, { BAC_BOX_SEL , "Select_", "aaa", {"sel","data","o"} }, { BAC_BOX_DEC , "Decoder_", "a?", {"a","o"} }, // ? = (1 << a) { BAC_BOX_EDEC , "EnabledDecoder_", "1a?", {"en","i","o"} }, // ? = (1 << a) { BAC_BOX_PSEL , "PrioSelect_", "1aaa", {"cin","sel","data","o"} }, { BAC_BOX_RAM , "DualPortRam_", "1abab", {"write_enable","write_address","write_data","read_address","read_data"} }, { BAC_BOX_RAMR , "ReadPort_", "1a1b", {"read_enable", "read_address", "RAM", "read_data" } }, { BAC_BOX_RAMW , "WritePort_", "1ab1", {"write_enable","write_address","write_data", "RAM"} }, { BAC_BOX_RAMWC , "ClockedWritePort_", "11ab1", {"clk","write_enable","write_address","write_data", "RAM"} }, { BAC_BOX_LUT , "lut", "?", {"i","o"} }, { BAC_BOX_AND , "and_", "aaa", {"a","b","o"} }, { BAC_BOX_OR , "or_", "aaa", {"a","b","o"} }, { BAC_BOX_XOR , "xor_", "aaa", {"a","b","o"} }, { BAC_BOX_NAND , "nand_", "aaa", {"a","b","o"} }, { BAC_BOX_NOR , "nor_", "aaa", {"a","b","o"} }, { BAC_BOX_XNOR , "xnor_", "aaa", {"a","b","o"} }, { BAC_BOX_BUF , "buf_", "aa", {"i","o"} }, { BAC_BOX_INV , "inv_", "aa", {"i","o"} }, { BAC_BOX_TRI , "tri_", "a1a", {"i","c","o"} }, { BAC_BOX_SUB , "sub_", "aaa", {"a","b","o"} }, { BAC_BOX_MIN , "unary_minus_", "aa", {"i","o"} }, { BAC_BOX_EQU , "equal_", "aa1", {"a","b","o"} }, { BAC_BOX_NEQU , "not_equal_", "aa1", {"a","b","o"} }, { BAC_BOX_MUX , "mux_", "1aaa", {"cond","d1","d0","o"} }, // changed order { BAC_BOX_NMUX , "wide_mux_", "ab?", {"sel","data","o"} }, // ? = b / (1 << a) { BAC_BOX_SEL , "wide_select_", "ab?", {"sel","data","o"} }, // ? = b / a { BAC_BOX_DFF , "wide_dff_", "aaa1a", {"d","async_val","async_cond","clock","q"} }, { BAC_BOX_DFFRS , "wide_dlatch_", "aaa1a", {"d","set","reset","clock","q"} }, { BAC_BOX_LATCHRS , "wide_dffrs_", "aaa1a", {"d","set","reset","clock","q"} }, { BAC_BOX_LATCH , "wide_dlatchrs_", "aaa1a", {"d","async_val","async_cond","clock","q"} }, { BAC_BOX_PSEL , "wide_prio_select_", "ab??", {"sel","data","carry_in","o"} }, // ? = b / a { BAC_BOX_POW , "pow_", "abc", {"a","b","o"} }, // ? = { BAC_BOX_PENC , "PrioEncoder_", "a?", {"sel","o"} }, { BAC_BOX_ABS , "abs", "aa", {"i","o"} } }; */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Count range size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Psr_ManRangeSizeName( Psr_Ntk_t * p, int Name ) { return 1; } static inline int Psr_ManRangeSizeRange( Psr_Ntk_t * p, int Range ) { char * pStr; int Left, Right; if ( Range == 0 ) return 1; pStr = Psr_NtkStr( p, Range ); assert( pStr[0] == '[' ); Left = Right = atoi( pStr + 1 ); pStr = strstr( pStr, "=" ); if ( pStr ) Right = atoi( pStr + 1 ); return 1 + (Left > Right ? Left - Right : Right - Left); } static inline int Psr_ManRangeSizeConst( Psr_Ntk_t * p, int Const ) { return atoi( Psr_NtkStr(p, Const) ); } static inline int Psr_ManRangeSizeConcat( Psr_Ntk_t * p, int Con ) { extern int Psr_ManRangeSizeArray( Psr_Ntk_t * p, Vec_Int_t * vSlices, int Start, int Stop ); Vec_Int_t * vSigs = Psr_CatSignals(p, Con); return Psr_ManRangeSizeArray( p, vSigs, 0, Vec_IntSize(vSigs) ); } static inline int Psr_ManRangeSizeSignal( Psr_Ntk_t * p, int Sig ) { int Value = Abc_Lit2Var2( Sig ); Psr_ManType_t Type = (Psr_ManType_t)Abc_Lit2Att2( Sig ); if ( Type == BAC_PRS_NAME ) return Psr_ManRangeSizeName( p, Value ); if ( Type == BAC_PRS_SLICE ) return Psr_ManRangeSizeRange( p, Psr_SliceRange(p, Value) ); if ( Type == BAC_PRS_CONST ) return Psr_ManRangeSizeConst( p, Value ); if ( Type == BAC_PRS_CONCAT ) return Psr_ManRangeSizeConcat( p, Value ); assert( 0 ); return 0; } int Psr_ManRangeSizeArray( Psr_Ntk_t * p, Vec_Int_t * vSlices, int Start, int Stop ) { int i, Sig, Count = 0; assert( Vec_IntSize(vSlices) > 0 ); Vec_IntForEachEntryStartStop( vSlices, Sig, i, Start, Stop ) Count += Psr_ManRangeSizeSignal( p, Sig ); return Count; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacPtr.c000066400000000000000000000436761300674244400230720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacPtr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Simple interface with external tools.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacPtr.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "map/mio/mio.h" #include "bac.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* design = array containing design name (as the first entry in the array) followed by pointers to modules module = array containing module name (as the first entry in the array) followed by pointers to 6 arrays: {array of input names; array of output names; array of nodes; array of boxes, array of floating-point input-arrival times; array of floating-point output-required times} node = array containing output name, followed by node type, followed by input names box = array containing model name, instance name, followed by pairs of formal/actual names for each port Comments: - in describing boxes - input formal/actual name pairs should be listed before output name pairs - the order of formal names should be the same as the order of inputs/outputs in the module description - all formal names present in the module description should be listed - if an input pin is not driven or an output pin has no fanout, the actual pin name is NULL - word-level formal name "a" is written as bit-level names (a[0]. a[1], etc) ordered LSB to MSB - the boxes can appear in any order (topological order is not expected) - in description of nodes and boxes, primitive names should be given as char*-strings ("AndT", "OrT", etc) - constant 0/1 nets should be driven by constant nodes having primitive names "Const0T" and "Const1T" - primitive modules should not be written, but the list of primitives and formal names should be provided - currently only "boxes" are supported (the array of "nodes" should contain no entries) - arrays of input-arrival/output-required times in the module description are optional */ // elementary gates typedef enum { PTR_GATE_NONE = 0, PTR_GATE_C0, // Const0T PTR_GATE_C1, // Const1T PTR_GATE_BUF, // BufT PTR_GATE_INV, // InvT PTR_GATE_AND, // AndT PTR_GATE_NAND, // NandT PTR_GATE_OR, // OrT PTR_GATE_NOR, // NorT PTR_GATE_XOR, // XorT PTR_GATE_XNOR, // XnorT PTR_GATE_UNKNOWN } Ptr_ObjType_t; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Free Ptr.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_PtrFreeNtk( Vec_Ptr_t * vNtk ) { Vec_PtrFree( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1) ); Vec_PtrFree( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2) ); Vec_VecFree( (Vec_Vec_t *)Vec_PtrEntry(vNtk, 3) ); Vec_VecFree( (Vec_Vec_t *)Vec_PtrEntry(vNtk, 4) ); if ( Vec_PtrSize(vNtk) > 5 ) Vec_FltFree( (Vec_Flt_t *)Vec_PtrEntry(vNtk, 5) ); if ( Vec_PtrSize(vNtk) > 6 ) Vec_FltFree( (Vec_Flt_t *)Vec_PtrEntry(vNtk, 6) ); Vec_PtrFree( vNtk ); } void Bac_PtrFree( Vec_Ptr_t * vDes ) { Vec_Ptr_t * vNtk; int i; if ( !vDes ) return; Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 ) Bac_PtrFreeNtk( vNtk ); Vec_PtrFree( vDes ); } /**Function************************************************************* Synopsis [Count memory used by Ptr.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bac_PtrMemoryArray( Vec_Ptr_t * vArray ) { return (int)Vec_PtrMemory(vArray); } int Bac_PtrMemoryArrayArray( Vec_Ptr_t * vArrayArray ) { Vec_Ptr_t * vArray; int i, nBytes = 0; Vec_PtrForEachEntry( Vec_Ptr_t *, vArrayArray, vArray, i ) nBytes += Bac_PtrMemoryArray(vArray); return nBytes; } int Bac_PtrMemoryNtk( Vec_Ptr_t * vNtk ) { int nBytes = (int)Vec_PtrMemory(vNtk); nBytes += Bac_PtrMemoryArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1) ); nBytes += Bac_PtrMemoryArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2) ); nBytes += Bac_PtrMemoryArrayArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3) ); nBytes += Bac_PtrMemoryArrayArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) ); return nBytes; } int Bac_PtrMemory( Vec_Ptr_t * vDes ) { Vec_Ptr_t * vNtk; int i, nBytes = (int)Vec_PtrMemory(vDes); Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 ) nBytes += Bac_PtrMemoryNtk(vNtk); return nBytes; } /**Function************************************************************* Synopsis [Dumping Ptr into a BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_PtrDumpSignalsBlif( FILE * pFile, Vec_Ptr_t * vSigs, int fSkipLastComma ) { char * pSig; int i; Vec_PtrForEachEntry( char *, vSigs, pSig, i ) fprintf( pFile, " %s", pSig ); } void Bac_PtrDumpBoxBlif( FILE * pFile, Vec_Ptr_t * vBox ) { char * pName; int i; fprintf( pFile, ".subckt" ); fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 0) ); //fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 1) ); // do not write intance name in BLIF Vec_PtrForEachEntryStart( char *, vBox, pName, i, 2 ) fprintf( pFile, " %s=%s", pName, (char *)Vec_PtrEntry(vBox, i+1) ), i++; fprintf( pFile, "\n" ); } void Bac_PtrDumpBoxesBlif( FILE * pFile, Vec_Ptr_t * vBoxes ) { Vec_Ptr_t * vBox; int i; Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i ) Bac_PtrDumpBoxBlif( pFile, vBox ); } void Bac_PtrDumpModuleBlif( FILE * pFile, Vec_Ptr_t * vNtk ) { fprintf( pFile, ".model %s\n", (char *)Vec_PtrEntry(vNtk, 0) ); fprintf( pFile, ".inputs" ); Bac_PtrDumpSignalsBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 0 ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); Bac_PtrDumpSignalsBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 1 ); fprintf( pFile, "\n" ); assert( Vec_PtrSize((Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3)) == 0 ); // no nodes; only boxes Bac_PtrDumpBoxesBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) ); fprintf( pFile, ".end\n\n" ); } void Bac_PtrDumpBlif( char * pFileName, Vec_Ptr_t * vDes ) { FILE * pFile; Vec_Ptr_t * vNtk; int i; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "// Design \"%s\" written via Ptr in ABC on %s\n\n", (char *)Vec_PtrEntry(vDes, 0), Extra_TimeStamp() ); Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 ) Bac_PtrDumpModuleBlif( pFile, vNtk ); fclose( pFile ); } /**Function************************************************************* Synopsis [Dumping Ptr into a Verilog file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_PtrDumpSignalsVerilog( FILE * pFile, Vec_Ptr_t * vSigs, int fAlwaysComma ) { char * pSig; int i; Vec_PtrForEachEntry( char *, vSigs, pSig, i ) fprintf( pFile, " %s%s", pSig, (fAlwaysComma || i < Vec_PtrSize(vSigs) - 1) ? ",":"" ); } void Bac_PtrDumpBoxVerilog( FILE * pFile, Vec_Ptr_t * vBox ) { char * pName; int i; fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 0) ); fprintf( pFile, " %s (", (char *)Vec_PtrEntry(vBox, 1) ); // write intance name in Verilog Vec_PtrForEachEntryStart( char *, vBox, pName, i, 2 ) fprintf( pFile, ".%s(%s)%s", pName, (char *)Vec_PtrEntry(vBox, i+1), i < Vec_PtrSize(vBox) - 2 ? ", ":"" ), i++; fprintf( pFile, ");\n" ); } void Bac_PtrDumpBoxesVerilog( FILE * pFile, Vec_Ptr_t * vBoxes ) { Vec_Ptr_t * vBox; int i; Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i ) Bac_PtrDumpBoxVerilog( pFile, vBox ); } void Bac_PtrDumpModuleVerilog( FILE * pFile, Vec_Ptr_t * vNtk ) { fprintf( pFile, "module %s (\n ", (char *)Vec_PtrEntry(vNtk, 0) ); Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 1 ); Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 0 ); fprintf( pFile, "\n );\n" ); fprintf( pFile, " input" ); Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 0 ); fprintf( pFile, ";\n" ); fprintf( pFile, " output" ); Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 0 ); fprintf( pFile, ";\n" ); assert( Vec_PtrSize((Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3)) == 0 ); // no nodes; only boxes Bac_PtrDumpBoxesVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) ); fprintf( pFile, "endmodule\n\n" ); } void Bac_PtrDumpVerilog( char * pFileName, Vec_Ptr_t * vDes ) { FILE * pFile; Vec_Ptr_t * vNtk; int i; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "// Design \"%s\" written via Ptr in ABC on %s\n\n", (char *)Vec_PtrEntry(vDes, 0), Extra_TimeStamp() ); Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 ) Bac_PtrDumpModuleVerilog( pFile, vNtk ); fclose( pFile ); } /**Function************************************************************* Synopsis [Collect elementary gates from the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_ManCollectGateNameOne( Mio_Library_t * pLib, Ptr_ObjType_t Type, word Truth, Vec_Ptr_t * vGateNames ) { Mio_Gate_t * pGate = Mio_LibraryReadGateByTruth( pLib, Truth ); if ( pGate != NULL ) Vec_PtrWriteEntry( vGateNames, Type, Mio_GateReadName(pGate) ); } Vec_Ptr_t * Bac_ManCollectGateNamesByTruth( Mio_Library_t * pLib ) { static word uTruths6[3] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), }; Vec_Ptr_t * vGateNames = Vec_PtrStart( PTR_GATE_UNKNOWN ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_C0, 0, vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_C1, ~(word)0, vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_BUF, uTruths6[0], vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_INV, ~uTruths6[0], vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_AND, (uTruths6[0] & uTruths6[1]), vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_NAND, ~(uTruths6[0] & uTruths6[1]), vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_OR, (uTruths6[0] | uTruths6[1]), vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_NOR, ~(uTruths6[0] | uTruths6[1]), vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_XOR, (uTruths6[0] ^ uTruths6[1]), vGateNames ); Bac_ManCollectGateNameOne( pLib, PTR_GATE_XNOR, ~(uTruths6[0] ^ uTruths6[1]), vGateNames ); return vGateNames; } /**Function************************************************************* Synopsis [This procedure transforms tech-ind Ptr into mapped Ptr.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_PtrUpdateBox( Vec_Ptr_t * vBox, Vec_Ptr_t * vGatesNames ) { Mio_Gate_t * pGate; Mio_Pin_t * pPin; int i = 1; Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); // update gate name char * pNameNew, * pName = (char *)Vec_PtrEntry(vBox, 0); if ( !strcmp(pName, "Const0T") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_C0); else if ( !strcmp(pName, "Const1T") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_C1); else if ( !strcmp(pName, "BufT") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_BUF); else if ( !strcmp(pName, "InvT") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_INV); else if ( !strcmp(pName, "AndT") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_AND); else if ( !strcmp(pName, "NandT") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_NAND); else if ( !strcmp(pName, "OrT") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_OR); else if ( !strcmp(pName, "NorT") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_NOR); else if ( !strcmp(pName, "XorT") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_XOR); else if ( !strcmp(pName, "XnorT") ) pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_XNOR); else // user hierarchy return; ABC_FREE( pName ); Vec_PtrWriteEntry( vBox, 0, Abc_UtilStrsav(pNameNew) ); // remove instance name pName = (char *)Vec_PtrEntry(vBox, 1); ABC_FREE( pName ); Vec_PtrWriteEntry( vBox, 1, NULL ); // update formal input names pGate = Mio_LibraryReadGateByName( pLib, pNameNew, NULL ); Mio_GateForEachPin( pGate, pPin ) { pName = (char *)Vec_PtrEntry( vBox, 2 * i ); ABC_FREE( pName ); pNameNew = Mio_PinReadName(pPin); Vec_PtrWriteEntry( vBox, 2 * i++, Abc_UtilStrsav(pNameNew) ); } // update output name pName = (char *)Vec_PtrEntry( vBox, 2 * i ); pNameNew = Mio_GateReadOutName(pGate); Vec_PtrWriteEntry( vBox, 2 * i++, Abc_UtilStrsav(pNameNew) ); assert( 2 * i == Vec_PtrSize(vBox) ); } Vec_Ptr_t * Bac_PtrTransformSigs( Vec_Ptr_t * vSig ) { char * pName; int i; Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vSig) ); Vec_PtrForEachEntry( char *, vSig, pName, i ) Vec_PtrPush( vNew, Abc_UtilStrsav(pName) ); return vNew; } Vec_Ptr_t * Bac_PtrTransformBox( Vec_Ptr_t * vBox, Vec_Ptr_t * vGatesNames ) { char * pName; int i; Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vBox) ); Vec_PtrForEachEntry( char *, vBox, pName, i ) Vec_PtrPush( vNew, Abc_UtilStrsav(pName) ); if ( vGatesNames ) Bac_PtrUpdateBox( vNew, vGatesNames ); return vNew; } Vec_Ptr_t * Bac_PtrTransformBoxes( Vec_Ptr_t * vBoxes, Vec_Ptr_t * vGatesNames ) { Vec_Ptr_t * vBox; int i; Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vBoxes) ); Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i ) Vec_PtrPush( vNew, Bac_PtrTransformBox(vBox, vGatesNames) ); return vNew; } Vec_Ptr_t * Bac_PtrTransformNtk( Vec_Ptr_t * vNtk, Vec_Ptr_t * vGatesNames ) { char * pName = (char *)Vec_PtrEntry(vNtk, 0); Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1); Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2); Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4); Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vNtk) ); Vec_PtrPush( vNew, Abc_UtilStrsav(pName) ); Vec_PtrPush( vNew, Bac_PtrTransformSigs(vInputs) ); Vec_PtrPush( vNew, Bac_PtrTransformSigs(vOutputs) ); Vec_PtrPush( vNew, Vec_PtrAllocExact(0) ); Vec_PtrPush( vNew, Bac_PtrTransformBoxes(vBoxes, vGatesNames) ); return vNew; } Vec_Ptr_t * Bac_PtrTransformTest( Vec_Ptr_t * vDes ) { Mio_Library_t * pLib; Vec_Ptr_t * vGatesNames; Vec_Ptr_t * vNtk, * vNew; int i; // dump BLIF before transformation Bac_PtrDumpBlif( "test1.blif", vDes ); if ( Abc_FrameGetGlobalFrame() == NULL ) { printf( "ABC framework is not started.\n" ); return NULL; } pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pLib == NULL ) { printf( "Standard cell library is not entered.\n" ); return NULL; } vGatesNames = Bac_ManCollectGateNamesByTruth( pLib ); // transform vNew = Vec_PtrAllocExact( Vec_PtrSize(vDes) ); Vec_PtrPush( vNew, Abc_UtilStrsav((char *)Vec_PtrEntry(vDes, 0)) ); Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 ) Vec_PtrPush( vNew, Bac_PtrTransformNtk(vNtk, vGatesNames) ); // dump BLIF after transformation Bac_PtrDumpBlif( "test2.blif", vNew ); Vec_PtrFree( vGatesNames ); return vNew; } /**Function************************************************************* Synopsis [Test the testing procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_PtrTransformTestTest() { char * pFileName = "c/hie/dump/1/netlist_1.v"; Abc_Ntk_t * pNtk = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 0 ); extern Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk ); Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pNtk ); Vec_Ptr_t * vNew = Bac_PtrTransformTest( vDes ); Bac_PtrFree( vDes ); Bac_PtrFree( vNew ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacPtrAbc.c000066400000000000000000000446671300674244400235010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacPtrAbc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Simple interface with external tools.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacPtrAbc.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "base/abc/abc.h" #include "map/mio/mio.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Node type conversions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ptr_HopToType( Abc_Obj_t * pObj ) { static word uTruth, uTruths6[3] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), }; assert( Abc_ObjIsNode(pObj) ); uTruth = Hop_ManComputeTruth6( (Hop_Man_t *)Abc_ObjNtk(pObj)->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj) ); /* if ( uTruth == 0 ) return "BAC_BOX_C0"; if ( uTruth == ~(word)0 ) return "BAC_BOX_C1"; if ( uTruth == uTruths6[0] ) return "BAC_BOX_BUF"; if ( uTruth == ~uTruths6[0] ) return "BAC_BOX_INV"; if ( uTruth == (uTruths6[0] & uTruths6[1]) ) return "BAC_BOX_AND"; if ( uTruth ==~(uTruths6[0] & uTruths6[1]) ) return "BAC_BOX_NAND"; if ( uTruth == (uTruths6[0] | uTruths6[1]) ) return "BAC_BOX_OR"; if ( uTruth ==~(uTruths6[0] | uTruths6[1]) ) return "BAC_BOX_NOR"; if ( uTruth == (uTruths6[0] ^ uTruths6[1]) ) return "BAC_BOX_XOR"; if ( uTruth ==~(uTruths6[0] ^ uTruths6[1]) ) return "BAC_BOX_XNOR"; */ if ( uTruth == 0 ) return "Const0T"; if ( uTruth == ~(word)0 ) return "Const1T"; if ( uTruth == uTruths6[0] ) return "BufT"; if ( uTruth == ~uTruths6[0] ) return "InvT"; if ( uTruth == (uTruths6[0] & uTruths6[1]) ) return "AndT"; if ( uTruth ==~(uTruths6[0] & uTruths6[1]) ) return "NandT"; if ( uTruth == (uTruths6[0] | uTruths6[1]) ) return "OrT"; if ( uTruth ==~(uTruths6[0] | uTruths6[1]) ) return "NorT"; if ( uTruth == (uTruths6[0] ^ uTruths6[1]) ) return "XorT"; if ( uTruth ==~(uTruths6[0] ^ uTruths6[1]) ) return "XnorT"; assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [Create Ptr from Abc_Ntk_t.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ptr_AbcObjName( Abc_Obj_t * pObj ) { if ( Abc_ObjIsNet(pObj) || Abc_ObjIsBox(pObj) ) return Abc_ObjName(pObj); if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ) return Ptr_AbcObjName(Abc_ObjFanout0(pObj)); if ( Abc_ObjIsCo(pObj) ) return Ptr_AbcObjName(Abc_ObjFanin0(pObj)); assert( 0 ); return NULL; } static int Ptr_CheckArray( Vec_Ptr_t * vArray ) { assert( Vec_PtrSize(vArray) == Vec_PtrCap(vArray) ); return 1; } Vec_Ptr_t * Ptr_AbcDeriveNode( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; Vec_Ptr_t * vNode = Vec_PtrAllocExact( 2 + 2 * (1 + Abc_ObjFaninNum(pObj)) ); assert( Abc_ObjIsNode(pObj) ); if ( Abc_NtkHasAig(pObj->pNtk) ) Vec_PtrPush( vNode, Ptr_HopToType(pObj) ); else if ( Abc_NtkHasSop(pObj->pNtk) ) Vec_PtrPush( vNode, Ptr_SopToTypeName((char *)pObj->pData) ); else assert( 0 ); Vec_PtrPush( vNode, Ptr_AbcObjName(pObj) ); assert( Abc_ObjFaninNum(pObj) <= 2 ); Abc_ObjForEachFanin( pObj, pFanin, i ) { Vec_PtrPush( vNode, (void*)(i ? "r" : "l") ); Vec_PtrPush( vNode, Ptr_AbcObjName(pFanin) ); } Vec_PtrPush( vNode, (void*)("o") ); Vec_PtrPush( vNode, Ptr_AbcObjName(pObj) ); assert( Ptr_CheckArray(vNode) ); return vNode; } Vec_Ptr_t * Ptr_AbcDeriveBox( Abc_Obj_t * pObj ) { Abc_Obj_t * pNext; int i; Abc_Ntk_t * pNtk = Abc_ObjModel(pObj); Vec_Ptr_t * vBox = Vec_PtrAllocExact( 2 + 2 * Abc_ObjFaninNum(pObj) + 2 * Abc_ObjFanoutNum(pObj) ); assert( Abc_ObjIsBox(pObj) ); Vec_PtrPush( vBox, Abc_NtkName(pNtk) ); Vec_PtrPush( vBox, Ptr_AbcObjName(pObj) ); Abc_ObjForEachFanin( pObj, pNext, i ) { Vec_PtrPush( vBox, Ptr_AbcObjName(Abc_NtkPi(pNtk, i)) ); Vec_PtrPush( vBox, Ptr_AbcObjName(pNext) ); } Abc_ObjForEachFanout( pObj, pNext, i ) { Vec_PtrPush( vBox, Ptr_AbcObjName(Abc_NtkPo(pNtk, i)) ); Vec_PtrPush( vBox, Ptr_AbcObjName(pNext) ); } assert( Ptr_CheckArray(vBox) ); return vBox; } Vec_Ptr_t * Ptr_AbcDeriveBoxes( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Vec_Ptr_t * vBoxes = Vec_PtrAllocExact( Abc_NtkBoxNum(pNtk) + Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachBox( pNtk, pObj, i ) Vec_PtrPush( vBoxes, Ptr_AbcDeriveBox(pObj) ); Abc_NtkForEachNode( pNtk, pObj, i ) Vec_PtrPush( vBoxes, Ptr_AbcDeriveNode(pObj) ); assert( Ptr_CheckArray(vBoxes) ); return vBoxes; } Vec_Ptr_t * Ptr_AbcDeriveInputs( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Abc_NtkPiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) Vec_PtrPush( vSigs, Ptr_AbcObjName(pObj) ); assert( Ptr_CheckArray(vSigs) ); return vSigs; } Vec_Ptr_t * Ptr_AbcDeriveOutputs( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Abc_NtkPoNum(pNtk) ); Abc_NtkForEachPo( pNtk, pObj, i ) Vec_PtrPush( vSigs, Ptr_AbcObjName(pObj) ); assert( Ptr_CheckArray(vSigs) ); return vSigs; } Vec_Ptr_t * Ptr_AbcDeriveNtk( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNtk = Vec_PtrAllocExact( 5 ); Vec_PtrPush( vNtk, Abc_NtkName(pNtk) ); Vec_PtrPush( vNtk, Ptr_AbcDeriveInputs(pNtk) ); Vec_PtrPush( vNtk, Ptr_AbcDeriveOutputs(pNtk) ); Vec_PtrPush( vNtk, Vec_PtrAllocExact(0) ); Vec_PtrPush( vNtk, Ptr_AbcDeriveBoxes(pNtk) ); assert( Ptr_CheckArray(vNtk) ); return vNtk; } Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vDes; Abc_Ntk_t * pTemp; int i; vDes = Vec_PtrAllocExact( 1 + Vec_PtrSize(pNtk->pDesign->vModules) ); Vec_PtrPush( vDes, pNtk->pDesign->pName ); Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) Vec_PtrPush( vDes, Ptr_AbcDeriveNtk(pTemp) ); assert( Ptr_CheckArray(vDes) ); return vDes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ptr_ManExperiment( Abc_Ntk_t * pNtk ) { abctime clk = Abc_Clock(); char * pFileName = Extra_FileNameGenericAppend(pNtk->pDesign->pName, "_out.blif"); Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pNtk ); printf( "Converting to Ptr: Memory = %6.3f MB ", 1.0*Bac_PtrMemory(vDes)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Bac_PtrDumpBlif( pFileName, vDes ); printf( "Finished writing output file \"%s\". ", pFileName ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Bac_PtrFree( vDes ); } /**Function************************************************************* Synopsis [Create Bac_Man_t from tech-ind Ptr.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ptr_NameToType( char * pSop ) { if ( !strcmp(pSop, "Const0T") ) return BAC_BOX_CF; if ( !strcmp(pSop, "Const1T") ) return BAC_BOX_CT; if ( !strcmp(pSop, "BufT") ) return BAC_BOX_BUF; if ( !strcmp(pSop, "InvT") ) return BAC_BOX_INV; if ( !strcmp(pSop, "AndT") ) return BAC_BOX_AND; if ( !strcmp(pSop, "NandT") ) return BAC_BOX_NAND; if ( !strcmp(pSop, "OrT") ) return BAC_BOX_OR; if ( !strcmp(pSop, "NorT") ) return BAC_BOX_NOR; if ( !strcmp(pSop, "XorT") ) return BAC_BOX_XOR; if ( !strcmp(pSop, "XnorT") ) return BAC_BOX_XNOR; return BAC_OBJ_BOX; } int Ptr_ManCountNtk( Vec_Ptr_t * vNtk ) { Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1); Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2); Vec_Ptr_t * vNodes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3); Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4); Vec_Ptr_t * vBox; int i, Counter = 0; assert( Vec_PtrSize(vNodes) == 0 ); Counter += Vec_PtrSize(vInputs); Counter += Vec_PtrSize(vOutputs); Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i ) Counter += Vec_PtrSize(vBox)/2; return Counter; } int Bac_BoxCountOutputs( Bac_Ntk_t * pNtk, char * pBoxNtk ) { int ModuleId = Bac_ManNtkFindId( pNtk->pDesign, pBoxNtk ); if ( ModuleId == 0 ) return 1; return Bac_NtkPoNumAlloc( Bac_ManNtk(pNtk->pDesign, ModuleId) ); } int Bac_NtkDeriveFromPtr( Bac_Ntk_t * pNtk, Vec_Ptr_t * vNtk, Vec_Int_t * vMap, Vec_Int_t * vBox2Id ) { char * pName, * pModuleName = (char *)Vec_PtrEntry(vNtk, 0); Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1); Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2); Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4), * vBox; int i, k, iObj, iTerm, NameId; // start network with the given name NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pModuleName, NULL ); assert( Bac_NtkNameId(pNtk) == NameId ); // map driven NameIds into their ObjIds for PIs Vec_PtrForEachEntry( char *, vInputs, pName, i ) { NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL ); if ( Vec_IntGetEntryFull(vMap, NameId) != -1 ) { printf( "PI with name \"%s\" is not unique module \"%s\".\n", pName, pModuleName ); return 0; } iObj = Bac_ObjAlloc( pNtk, BAC_OBJ_PI, -1 ); Bac_ObjSetName( pNtk, iObj, Abc_Var2Lit2(NameId, BAC_NAME_BIN) ); Vec_IntSetEntryFull( vMap, NameId, iObj ); Bac_NtkAddInfo( pNtk, Abc_Var2Lit2(NameId, 1), -1, -1 ); } // map driven NameIds into their ObjIds for BOs Vec_IntClear( vBox2Id ); Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i ) { char * pBoxNtk = (char *)Vec_PtrEntry(vBox, 0); char * pBoxName = (char *)Vec_PtrEntry(vBox, 1); int nOutputs = Bac_BoxCountOutputs( pNtk, pBoxNtk ); int nInputs = Vec_PtrSize(vBox)/2 - nOutputs - 1; int NtkId = Bac_ManNtkFindId( pNtk->pDesign, pBoxNtk ); assert( Vec_PtrSize(vBox) % 2 == 0 ); assert( nOutputs > 0 && 2*(nOutputs + 1) <= Vec_PtrSize(vBox) ); iObj = Bac_BoxAlloc( pNtk, (Bac_ObjType_t)Ptr_NameToType(pBoxNtk), nInputs, nOutputs, NtkId ); if ( NtkId > 0 ) Bac_NtkSetHost( Bac_ManNtk(pNtk->pDesign, NtkId), Bac_NtkId(pNtk), iObj ); Bac_ObjSetName( pNtk, iObj, Abc_Var2Lit2(Abc_NamStrFindOrAdd(pNtk->pDesign->pStrs, pBoxName, NULL), BAC_NAME_BIN) ); Bac_BoxForEachBo( pNtk, iObj, iTerm, k ) { pName = (char *)Vec_PtrEntry( vBox, Vec_PtrSize(vBox) - 2*(nOutputs - k) + 1 ); NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL ); if ( Vec_IntGetEntryFull(vMap, NameId) != -1 ) { printf( "Signal \"%s\" has multiple drivers in module \"%s\".\n", pName, pModuleName ); return 0; } Bac_ObjSetName( pNtk, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) ); Vec_IntSetEntryFull( vMap, NameId, iTerm ); } Vec_IntPush( vBox2Id, iObj ); } assert( Vec_IntSize(vBox2Id) == Vec_PtrSize(vBoxes) ); // connect BIs Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i ) { iObj = Vec_IntEntry( vBox2Id, i ); Bac_BoxForEachBi( pNtk, iObj, iTerm, k ) { pName = (char *)Vec_PtrEntry( vBox, 2*(k + 1) + 1 ); NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL ); if ( Vec_IntGetEntryFull(vMap, NameId) == -1 ) printf( "Signal \"%s\" in not driven in module \"%s\".\n", pName, pModuleName ); Bac_ObjSetFanin( pNtk, iTerm, Vec_IntGetEntryFull(vMap, NameId) ); } } // connect POs Vec_PtrForEachEntry( char *, vOutputs, pName, i ) { NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL ); if ( Vec_IntGetEntryFull(vMap, NameId) == -1 ) printf( "PO with name \"%s\" in not driven in module \"%s\".\n", pName, pModuleName ); iObj = Bac_ObjAlloc( pNtk, BAC_OBJ_PO, Vec_IntGetEntryFull(vMap, NameId) ); Bac_NtkAddInfo( pNtk, Abc_Var2Lit2(NameId, 2), -1, -1 ); } // update map Bac_NtkForEachCi( pNtk, iObj ) Vec_IntSetEntryFull( vMap, Bac_ObjNameId(pNtk, iObj), -1 ); // double check Vec_IntForEachEntry( vMap, iObj, i ) assert( iObj == -1 ); assert( Bac_NtkObjNum(pNtk) == Vec_StrCap(&pNtk->vType) ); return 1; } Bac_Man_t * Bac_PtrTransformToCba( Vec_Ptr_t * vDes ) { char * pName = (char *)Vec_PtrEntry(vDes, 0); Bac_Man_t * pNew = Bac_ManAlloc( pName, Vec_PtrSize(vDes) - 1 ); Vec_Int_t * vMap = Vec_IntStartFull( 1000 ); Vec_Int_t * vBox2Id = Vec_IntAlloc( 1000 ); // create interfaces Bac_Ntk_t * pNtk; int i; Bac_ManForEachNtk( pNew, pNtk, i ) { Vec_Ptr_t * vNtk = (Vec_Ptr_t *)Vec_PtrEntry(vDes, i); Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1); Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2); int NameId = Abc_NamStrFindOrAdd( pNew->pStrs, (char *)Vec_PtrEntry(vNtk, 0), NULL ); Bac_NtkAlloc( pNtk, NameId, Vec_PtrSize(vInputs), Vec_PtrSize(vOutputs), Ptr_ManCountNtk(vNtk) ); Bac_NtkStartNames( pNtk ); } // parse the networks Bac_ManForEachNtk( pNew, pNtk, i ) { Vec_Ptr_t * vNtk = (Vec_Ptr_t *)Vec_PtrEntry(vDes, i); if ( !Bac_NtkDeriveFromPtr( pNtk, vNtk, vMap, vBox2Id ) ) break; } if ( i <= Bac_ManNtkNum(pNew) ) Bac_ManFree(pNew), pNew = NULL; Vec_IntFree( vBox2Id ); Vec_IntFree( vMap ); return pNew; } /**Function************************************************************* Synopsis [Create Ptr from mapped Bac_Man_t.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Bac_NtkTransformToPtrBox( Bac_Ntk_t * p, int iBox ) { int i, iTerm, fUser = Bac_ObjIsBoxUser( p, iBox ); Bac_Ntk_t * pBoxNtk = Bac_BoxNtk( p, iBox ); Mio_Library_t * pLib = (Mio_Library_t *)p->pDesign->pMioLib; Mio_Gate_t * pGate = pLib ? Mio_LibraryReadGateByName( pLib, Bac_BoxNtkName(p, iBox), NULL ) : NULL; Vec_Ptr_t * vBox = Vec_PtrAllocExact( 2*Bac_BoxSize(p, iBox) ); Vec_PtrPush( vBox, Bac_BoxNtkName(p, iBox) ); Vec_PtrPush( vBox, Bac_ObjNameStr(p, iBox) ); Bac_BoxForEachBi( p, iBox, iTerm, i ) { Vec_PtrPush( vBox, fUser ? Bac_ObjNameStr(pBoxNtk, Bac_NtkPi(pBoxNtk, i)) : Mio_GateReadPinName(pGate, i) ); Vec_PtrPush( vBox, Bac_ObjNameStr(p, iTerm) ); } Bac_BoxForEachBo( p, iBox, iTerm, i ) { Vec_PtrPush( vBox, fUser ? Bac_ObjNameStr(pBoxNtk, Bac_NtkPo(pBoxNtk, i)) : Mio_GateReadOutName(pGate) ); Vec_PtrPush( vBox, Bac_ObjNameStr(p, iTerm) ); } assert( Ptr_CheckArray(vBox) ); return vBox; } Vec_Ptr_t * Bac_NtkTransformToPtrBoxes( Bac_Ntk_t * p ) { int iBox; Vec_Ptr_t * vBoxes = Vec_PtrAllocExact( Bac_NtkBoxNum(p) ); Bac_NtkForEachBox( p, iBox ) Vec_PtrPush( vBoxes, Bac_NtkTransformToPtrBox(p, iBox) ); assert( Ptr_CheckArray(vBoxes) ); return vBoxes; } Vec_Ptr_t * Bac_NtkTransformToPtrInputs( Bac_Ntk_t * p ) { int i, iTerm; Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Bac_NtkPiNum(p) ); Bac_NtkForEachPi( p, iTerm, i ) Vec_PtrPush( vSigs, Bac_ObjNameStr(p, iTerm) ); assert( Ptr_CheckArray(vSigs) ); return vSigs; } Vec_Ptr_t * Bac_NtkTransformToPtrOutputs( Bac_Ntk_t * p ) { int i, iTerm; Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Bac_NtkPoNum(p) ); Bac_NtkForEachPo( p, iTerm, i ) Vec_PtrPush( vSigs, Bac_ObjNameStr(p, iTerm) ); assert( Ptr_CheckArray(vSigs) ); return vSigs; } Vec_Ptr_t * Bac_NtkTransformToPtr( Bac_Ntk_t * p ) { Vec_Ptr_t * vNtk = Vec_PtrAllocExact(5); Vec_PtrPush( vNtk, Bac_NtkName(p) ); Vec_PtrPush( vNtk, Bac_NtkTransformToPtrInputs(p) ); Vec_PtrPush( vNtk, Bac_NtkTransformToPtrOutputs(p) ); Vec_PtrPush( vNtk, Vec_PtrAllocExact(0) ); Vec_PtrPush( vNtk, Bac_NtkTransformToPtrBoxes(p) ); assert( Ptr_CheckArray(vNtk) ); return vNtk; } Vec_Ptr_t * Bac_PtrDeriveFromCba( Bac_Man_t * p ) { Vec_Ptr_t * vDes; Bac_Ntk_t * pTemp; int i; if ( p == NULL ) return NULL; if ( p->pMioLib == NULL ) { printf( "Cannot transform CBA network into Ptr because it is not mapped.\n" ); return NULL; } Bac_ManAssignInternWordNames( p ); vDes = Vec_PtrAllocExact( 1 + Bac_ManNtkNum(p) ); Vec_PtrPush( vDes, p->pName ); Bac_ManForEachNtk( p, pTemp, i ) Vec_PtrPush( vDes, Bac_NtkTransformToPtr(pTemp) ); assert( Ptr_CheckArray(vDes) ); return vDes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacReadBlif.c000066400000000000000000000373201300674244400237620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacReadBlif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [BLIF parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "bacPrs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // BLIF keywords typedef enum { PRS_BLIF_NONE = 0, // 0: unused PRS_BLIF_MODEL, // 1: .model PRS_BLIF_INOUTS, // 2: .inouts PRS_BLIF_INPUTS, // 3: .inputs PRS_BLIF_OUTPUTS, // 4: .outputs PRS_BLIF_NAMES, // 5: .names PRS_BLIF_SUBCKT, // 6: .subckt PRS_BLIF_GATE, // 7: .gate PRS_BLIF_LATCH, // 8: .latch PRS_BLIF_SHORT, // 9: .short PRS_BLIF_END, // 10: .end PRS_BLIF_UNKNOWN // 11: unknown } Bac_BlifType_t; static const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = { NULL, // 0: unused ".model", // 1: .model ".inouts", // 2: .inputs ".inputs", // 3: .inputs ".outputs", // 4: .outputs ".names", // 5: .names ".subckt", // 6: .subckt ".gate", // 7: .gate ".latch", // 8: .latch ".short", // 9: .short ".end", // 10: .end NULL // 11: unknown }; static inline void Psr_NtkAddBlifDirectives( Psr_Man_t * p ) { int i; for ( i = 1; s_BlifTypes[i]; i++ ) Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL ); assert( Abc_NamObjNumMax(p->pStrs) == i ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reading characters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Psr_CharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r'; } static inline int Psr_CharIsStop( char c ) { return c == '#' || c == '\\' || c == '\n' || c == '='; } static inline int Psr_CharIsLit( char c ) { return c == '0' || c == '1' || c == '-'; } static inline int Psr_ManIsSpace( Psr_Man_t * p ) { return Psr_CharIsSpace(*p->pCur); } static inline int Psr_ManIsStop( Psr_Man_t * p ) { return Psr_CharIsStop(*p->pCur); } static inline int Psr_ManIsLit( Psr_Man_t * p ) { return Psr_CharIsLit(*p->pCur); } static inline int Psr_ManIsChar( Psr_Man_t * p, char c ) { return *p->pCur == c; } static inline int Psr_ManIsChar2( Psr_Man_t * p, char c ) { return *p->pCur++ == c; } static inline void Psr_ManSkip( Psr_Man_t * p ) { p->pCur++; } static inline char Psr_ManSkip2( Psr_Man_t * p ) { return *p->pCur++; } /**Function************************************************************* Synopsis [Reading names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Psr_ManSkipToChar( Psr_Man_t * p, char c ) { while ( !Psr_ManIsChar(p, c) ) Psr_ManSkip(p); } static inline void Psr_ManSkipSpaces( Psr_Man_t * p ) { while ( 1 ) { while ( Psr_ManIsSpace(p) ) Psr_ManSkip(p); if ( Psr_ManIsChar(p, '\\') ) { Psr_ManSkipToChar( p, '\n' ); Psr_ManSkip(p); continue; } if ( Psr_ManIsChar(p, '#') ) Psr_ManSkipToChar( p, '\n' ); break; } assert( !Psr_ManIsSpace(p) ); } static inline int Psr_ManReadName( Psr_Man_t * p ) { char * pStart; Psr_ManSkipSpaces( p ); if ( Psr_ManIsChar(p, '\n') ) return 0; pStart = p->pCur; while ( !Psr_ManIsSpace(p) && !Psr_ManIsStop(p) ) Psr_ManSkip(p); if ( pStart == p->pCur ) return 0; return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); } static inline int Psr_ManReadList( Psr_Man_t * p, Vec_Int_t * vOrder, int Type ) { int iToken; Vec_IntClear( &p->vTemp ); while ( (iToken = Psr_ManReadName(p)) ) { Vec_IntPush( &p->vTemp, iToken ); Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) ); } if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Signal list is empty.", 1); return 0; } static inline int Psr_ManReadList2( Psr_Man_t * p ) { int iToken; Vec_IntClear( &p->vTemp ); while ( (iToken = Psr_ManReadName(p)) ) Vec_IntPushTwo( &p->vTemp, 0, iToken ); if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Signal list is empty.", 1); return 0; } static inline int Psr_ManReadList3( Psr_Man_t * p ) { Vec_IntClear( &p->vTemp ); while ( !Psr_ManIsChar(p, '\n') ) { int iToken = Psr_ManReadName(p); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read formal name.", 1); Vec_IntPush( &p->vTemp, iToken ); Psr_ManSkipSpaces( p ); if ( !Psr_ManIsChar2(p, '=') ) return Psr_ManErrorSet(p, "Cannot find symbol \"=\".", 1); iToken = Psr_ManReadName(p); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read actual name.", 1); Vec_IntPush( &p->vTemp, iToken ); Psr_ManSkipSpaces( p ); } if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1); if ( Vec_IntSize(&p->vTemp) % 2 ) return Psr_ManErrorSet(p, "The number of formal/actual names is not even.", 1); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Psr_ManReadCube( Psr_Man_t * p ) { assert( Psr_ManIsLit(p) ); while ( Psr_ManIsLit(p) ) Vec_StrPush( &p->vCover, Psr_ManSkip2(p) ); Psr_ManSkipSpaces( p ); if ( Psr_ManIsChar(p, '\n') ) { if ( Vec_StrSize(&p->vCover) != 1 ) return Psr_ManErrorSet(p, "Cannot read cube.", 1); // fix single literal cube by adding space Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) ); Vec_StrWriteEntry( &p->vCover, 0, ' ' ); Vec_StrPush( &p->vCover, '\n' ); return 0; } if ( !Psr_ManIsLit(p) ) return Psr_ManErrorSet(p, "Cannot read output literal.", 1); Vec_StrPush( &p->vCover, ' ' ); Vec_StrPush( &p->vCover, Psr_ManSkip2(p) ); Vec_StrPush( &p->vCover, '\n' ); Psr_ManSkipSpaces( p ); if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Cannot read end of cube.", 1); return 0; } static inline void Psr_ManSaveCover( Psr_Man_t * p ) { int iToken; if ( Vec_StrSize(&p->vCover) == 0 ) p->pNtk->fHasC0s = 1; else if ( Vec_StrSize(&p->vCover) == 2 ) { if ( Vec_StrEntryLast(&p->vCover) == '0' ) p->pNtk->fHasC0s = 1; else if ( Vec_StrEntryLast(&p->vCover) == '1' ) p->pNtk->fHasC1s = 1; else assert( 0 ); } assert( Vec_StrSize(&p->vCover) > 0 ); Vec_StrPush( &p->vCover, '\0' ); //iToken = Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL ); iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) ); Vec_StrClear( &p->vCover ); // set the cover to the module of this box assert( Psr_BoxNtk(p->pNtk, Psr_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0 Psr_BoxSetNtk( p->pNtk, Psr_NtkBoxNum(p->pNtk)-1, iToken ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Psr_ManReadInouts( Psr_Man_t * p ) { if ( Psr_ManReadList(p, &p->pNtk->vOrder, 3) ) return 1; Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp ); return 0; } static inline int Psr_ManReadInputs( Psr_Man_t * p ) { if ( Psr_ManReadList(p, &p->pNtk->vOrder, 1) ) return 1; Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp ); return 0; } static inline int Psr_ManReadOutputs( Psr_Man_t * p ) { if ( Psr_ManReadList(p, &p->pNtk->vOrder, 2) ) return 1; Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp ); return 0; } static inline int Psr_ManReadNode( Psr_Man_t * p ) { if ( Psr_ManReadList2(p) ) return 1; // save results Psr_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function return 0; } static inline int Psr_ManReadBox( Psr_Man_t * p, int fGate ) { int iToken = Psr_ManReadName(p); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read model name.", 1); if ( Psr_ManReadList3(p) ) return 1; // save results Psr_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp ); if ( fGate ) p->pNtk->fMapped = 1; return 0; } static inline int Psr_ManReadLatch( Psr_Man_t * p ) { int iToken = Psr_ManReadName(p); Vec_IntClear( &p->vTemp ); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read latch input.", 1); Vec_IntWriteEntry( &p->vTemp, 1, iToken ); iToken = Psr_ManReadName(p); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read latch output.", 1); Vec_IntWriteEntry( &p->vTemp, 0, iToken ); Psr_ManSkipSpaces( p ); if ( Psr_ManIsChar(p, '0') ) iToken = 0; else if ( Psr_ManIsChar(p, '1') ) iToken = 1; else iToken = 2; Psr_ManSkipToChar( p, '\n' ); // save results Psr_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch return 0; } static inline int Psr_ManReadShort( Psr_Man_t * p ) { int iToken = Psr_ManReadName(p); Vec_IntClear( &p->vTemp ); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read .short input.", 1); Vec_IntWriteEntry( &p->vTemp, 1, iToken ); iToken = Psr_ManReadName(p); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read .short output.", 1); Vec_IntWriteEntry( &p->vTemp, 0, iToken ); Psr_ManSkipSpaces( p ); if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .short line.", 1); // save results iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL ); Psr_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp ); return 0; } static inline int Psr_ManReadModel( Psr_Man_t * p ) { int iToken; if ( p->pNtk != NULL ) return Psr_ManErrorSet(p, "Parsing previous model is unfinished.", 1); iToken = Psr_ManReadName(p); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read model name.", 1); Psr_ManInitializeNtk( p, iToken, 0 ); Psr_ManSkipSpaces( p ); if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .model line.", 1); return 0; } static inline int Psr_ManReadEnd( Psr_Man_t * p ) { if ( p->pNtk == 0 ) return Psr_ManErrorSet(p, "Directive .end without .model.", 1); //printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) ); Psr_ManFinalizeNtk( p ); Psr_ManSkipSpaces( p ); if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .end line.", 1); return 0; } static inline int Psr_ManReadDirective( Psr_Man_t * p ) { int iToken; if ( !Psr_ManIsChar(p, '.') ) return Psr_ManReadCube( p ); if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node Psr_ManSaveCover( p ); iToken = Psr_ManReadName( p ); if ( iToken == PRS_BLIF_MODEL ) return Psr_ManReadModel( p ); if ( iToken == PRS_BLIF_INOUTS ) return Psr_ManReadInouts( p ); if ( iToken == PRS_BLIF_INPUTS ) return Psr_ManReadInputs( p ); if ( iToken == PRS_BLIF_OUTPUTS ) return Psr_ManReadOutputs( p ); if ( iToken == PRS_BLIF_NAMES ) return Psr_ManReadNode( p ); if ( iToken == PRS_BLIF_SUBCKT ) return Psr_ManReadBox( p, 0 ); if ( iToken == PRS_BLIF_GATE ) return Psr_ManReadBox( p, 1 ); if ( iToken == PRS_BLIF_LATCH ) return Psr_ManReadLatch( p ); if ( iToken == PRS_BLIF_SHORT ) return Psr_ManReadShort( p ); if ( iToken == PRS_BLIF_END ) return Psr_ManReadEnd( p ); printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) ); return 1; } static inline int Psr_ManReadLines( Psr_Man_t * p ) { while ( p->pCur[1] != '\0' ) { assert( Psr_ManIsChar(p, '\n') ); Psr_ManSkip(p); Psr_ManSkipSpaces( p ); if ( Psr_ManIsChar(p, '\n') ) continue; if ( Psr_ManReadDirective(p) ) return 1; } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Psr_ManReadBlif( char * pFileName ) { Vec_Ptr_t * vPrs = NULL; Psr_Man_t * p = Psr_ManAlloc( pFileName ); if ( p == NULL ) return NULL; Psr_NtkAddBlifDirectives( p ); Psr_ManReadLines( p ); if ( Psr_ManErrorPrint(p) ) ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks ); Psr_ManFree( p ); return vPrs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Psr_ManReadBlifTest() { abctime clk = Abc_Clock(); extern void Psr_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs ); // Vec_Ptr_t * vPrs = Psr_ManReadBlif( "aga/ray/ray_hie_oper.blif" ); Vec_Ptr_t * vPrs = Psr_ManReadBlif( "c/hie/dump/1/netlist_1_out8.blif" ); if ( !vPrs ) return; printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) ); printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) ); printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // Abc_NamPrint( p->pStrs ); Psr_ManWriteBlif( "c/hie/dump/1/netlist_1_out8_out.blif", vPrs ); Psr_ManVecFree( vPrs ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacReadSmt.c000066400000000000000000000023461300674244400236510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacReadSmt.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [BLIF parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacReadSmt.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacReadVer.c000066400000000000000000001010031300674244400236300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacReadVer.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [BLIF writer.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacReadVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "bacPrs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // Verilog keywords typedef enum { PRS_VER_NONE = 0, // 0: unused PRS_VER_INPUT, // 1: input PRS_VER_OUTPUT, // 2: output PRS_VER_INOUT, // 3: inout PRS_VER_WIRE, // 4: wire PRS_VER_MODULE, // 5: module PRS_VER_ASSIGN, // 6: assign PRS_VER_REG, // 7: reg PRS_VER_ALWAYS, // 8: always PRS_VER_DEFPARAM, // 9: always PRS_VER_BEGIN, // 10: begin PRS_VER_END, // 11: end PRS_VER_ENDMODULE, // 12: endmodule PRS_VER_UNKNOWN // 13: unknown } Bac_VerType_t; static const char * s_VerTypes[PRS_VER_UNKNOWN+1] = { NULL, // 0: unused "input", // 1: input "output", // 2: output "inout", // 3: inout "wire", // 4: wire "module", // 5: module "assign", // 6: assign "reg", // 7: reg "always", // 8: always "defparam", // 9: defparam "begin", // 10: begin "end", // 11: end "endmodule", // 12: endmodule NULL // 13: unknown }; static inline void Psr_NtkAddVerilogDirectives( Psr_Man_t * p ) { int i; for ( i = 1; s_VerTypes[i]; i++ ) Abc_NamStrFindOrAdd( p->pStrs, (char *)s_VerTypes[i], NULL ); assert( Abc_NamObjNumMax(p->pStrs) == i ); } // character recognition static inline int Psr_CharIsSpace( char c ) { return (c == ' ' || c == '\t' || c == '\r' || c == '\n'); } static inline int Psr_CharIsDigit( char c ) { return (c >= '0' && c <= '9'); } static inline int Psr_CharIsDigitB( char c ) { return (c == '0' || c == '1' || c == 'x' || c == 'z'); } static inline int Psr_CharIsDigitH( char c ) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } static inline int Psr_CharIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } static inline int Psr_CharIsSymb1( char c ) { return Psr_CharIsChar(c) || c == '_'; } static inline int Psr_CharIsSymb2( char c ) { return Psr_CharIsSymb1(c) || Psr_CharIsDigit(c) || c == '$'; } static inline int Psr_ManIsChar( Psr_Man_t * p, char c ) { return p->pCur[0] == c; } static inline int Psr_ManIsChar1( Psr_Man_t * p, char c ) { return p->pCur[1] == c; } static inline int Psr_ManIsDigit( Psr_Man_t * p ) { return Psr_CharIsDigit(*p->pCur); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // collect predefined modules names static const char * s_VerilogModules[100] = { "const0", // BAC_BOX_CF, "const1", // BAC_BOX_CT, "constX", // BAC_BOX_CX, "constZ", // BAC_BOX_CZ, "buf", // BAC_BOX_BUF, "not", // BAC_BOX_INV, "and", // BAC_BOX_AND, "nand", // BAC_BOX_NAND, "or", // BAC_BOX_OR, "nor", // BAC_BOX_NOR, "xor", // BAC_BOX_XOR, "xnor", // BAC_BOX_XNOR, "sharp", // BAC_BOX_SHARP, "mux", // BAC_BOX_MUX, "maj", // BAC_BOX_MAJ, NULL }; static const char * s_KnownModules[100] = { "VERIFIC_", "add_", "mult_", "div_", "mod_", "rem_", "shift_left_", "shift_right_", "rotate_left_", "rotate_right_", "reduce_and_", "reduce_or_", "reduce_xor_", "reduce_nand_", "reduce_nor_", "reduce_xnor_", "LessThan_", "Mux_", "Select_", "Decoder_", "EnabledDecoder_", "PrioSelect_", "DualPortRam_", "ReadPort_", "WritePort_", "ClockedWritePort_", "lut", "and_", "or_", "xor_", "nand_", "nor_", "xnor_", "buf_", "inv_", "tri_", "sub_", "unary_minus_", "equal_", "not_equal_", "mux_", "wide_mux_", "wide_select_", "wide_dff_", "wide_dlatch_", "wide_dffrs_", "wide_dlatchrs_", "wide_prio_select_", "pow_", "PrioEncoder_", "abs", NULL }; // check if it is a Verilog predefined module static inline int Psr_ManIsVerilogModule( Psr_Man_t * p, char * pName ) { int i; for ( i = 0; s_VerilogModules[i]; i++ ) if ( !strcmp(pName, s_VerilogModules[i]) ) return BAC_BOX_CF + i; return 0; } // check if it is a known module static inline int Psr_ManIsKnownModule( Psr_Man_t * p, char * pName ) { int i; for ( i = 0; s_KnownModules[i]; i++ ) if ( !strncmp(pName, s_KnownModules[i], strlen(s_KnownModules[i])) ) return i; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // skips Verilog comments (returns 1 if some comments were skipped) static inline int Psr_ManUtilSkipComments( Psr_Man_t * p ) { if ( !Psr_ManIsChar(p, '/') ) return 0; if ( Psr_ManIsChar1(p, '/') ) { for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) if ( Psr_ManIsChar(p, '\n') ) { p->pCur++; return 1; } } else if ( Psr_ManIsChar1(p, '*') ) { for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) if ( Psr_ManIsChar(p, '*') && Psr_ManIsChar1(p, '/') ) { p->pCur++; p->pCur++; return 1; } } return 0; } static inline int Psr_ManUtilSkipName( Psr_Man_t * p ) { if ( !Psr_ManIsChar(p, '\\') ) return 0; for ( p->pCur++; p->pCur < p->pLimit; p->pCur++ ) if ( Psr_ManIsChar(p, ' ') ) { p->pCur++; return 1; } return 0; } // skip any number of spaces and comments static inline int Psr_ManUtilSkipSpaces( Psr_Man_t * p ) { while ( p->pCur < p->pLimit ) { while ( Psr_CharIsSpace(*p->pCur) ) p->pCur++; if ( !*p->pCur ) return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); if ( !Psr_ManUtilSkipComments(p) ) return 0; } return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); } // skip everything including comments until the given char static inline int Psr_ManUtilSkipUntil( Psr_Man_t * p, char c ) { while ( p->pCur < p->pLimit ) { if ( Psr_ManIsChar(p, c) ) return 1; if ( Psr_ManUtilSkipComments(p) ) continue; if ( Psr_ManUtilSkipName(p) ) continue; p->pCur++; } return 0; } // skip everything including comments until the given word static inline int Psr_ManUtilSkipUntilWord( Psr_Man_t * p, char * pWord ) { char * pPlace = strstr( p->pCur, pWord ); if ( pPlace == NULL ) return 1; p->pCur = pPlace + strlen(pWord); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Psr_ManReadName( Psr_Man_t * p ) { char * pStart = p->pCur; if ( Psr_ManIsChar(p, '\\') ) // escaped name { pStart = ++p->pCur; while ( !Psr_ManIsChar(p, ' ') ) p->pCur++; } else if ( Psr_CharIsSymb1(*p->pCur) ) // simple name { p->pCur++; while ( Psr_CharIsSymb2(*p->pCur) ) p->pCur++; } else return 0; return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); } static inline int Psr_ManReadNameList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb ) { Vec_IntClear( vTemp ); while ( 1 ) { int Item = Psr_ManReadName(p); if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read name in the list.", 0); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 1.", 0); if ( Item == PRS_VER_WIRE ) continue; Vec_IntPush( vTemp, Item ); if ( Psr_ManIsChar(p, LastSymb) ) break; if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 2.", 0); } return 1; } static inline int Psr_ManReadConstant( Psr_Man_t * p ) { char * pStart = p->pCur; assert( Psr_ManIsDigit(p) ); while ( Psr_ManIsDigit(p) ) p->pCur++; if ( !Psr_ManIsChar(p, '\'') ) return Psr_ManErrorSet(p, "Cannot read constant.", 0); p->pCur++; if ( Psr_ManIsChar(p, 'b') ) { p->pCur++; while ( Psr_CharIsDigitB(*p->pCur) ) { if ( *p->pCur == '0' ) p->pNtk->fHasC0s = 1; else if ( *p->pCur == '1' ) p->pNtk->fHasC1s = 1; else if ( *p->pCur == 'x' ) p->pNtk->fHasCXs = 1; else if ( *p->pCur == 'z' ) p->pNtk->fHasCZs = 1; p->pCur++; } } else if ( Psr_ManIsChar(p, 'h') ) { p->pCur++; p->pNtk->fHasC0s = 1; while ( Psr_CharIsDigitH(*p->pCur) ) { if ( *p->pCur != '0' ) p->pNtk->fHasC1s = 1; p->pCur++; } } else if ( Psr_ManIsChar(p, 'd') ) { p->pCur++; p->pNtk->fHasC0s = 1; while ( Psr_ManIsDigit(p) ) { if ( *p->pCur != '0' ) p->pNtk->fHasC1s = 1; p->pCur++; } } else return Psr_ManErrorSet(p, "Cannot read radix of constant.", 0); return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); } static inline int Psr_ManReadRange( Psr_Man_t * p ) { assert( Psr_ManIsChar(p, '[') ); Vec_StrClear( &p->vCover ); Vec_StrPush( &p->vCover, *p->pCur++ ); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 3.", 0); if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0); while ( Psr_ManIsDigit(p) ) Vec_StrPush( &p->vCover, *p->pCur++ ); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 4.", 0); if ( Psr_ManIsChar(p, ':') ) { Vec_StrPush( &p->vCover, *p->pCur++ ); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 5.", 0); if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0); while ( Psr_ManIsDigit(p) ) Vec_StrPush( &p->vCover, *p->pCur++ ); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 6.", 0); } if ( !Psr_ManIsChar(p, ']') ) return Psr_ManErrorSet(p, "Cannot read closing brace in range specification.", 0); Vec_StrPush( &p->vCover, *p->pCur++ ); Vec_StrPush( &p->vCover, '\0' ); return Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL ); } static inline int Psr_ManReadConcat( Psr_Man_t * p, Vec_Int_t * vTemp2 ) { extern int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ); assert( Psr_ManIsChar(p, '{') ); p->pCur++; if ( !Psr_ManReadSignalList( p, vTemp2, '}', 0 ) ) return Psr_ManErrorSet(p, "Error number 7.", 0); // check final assert( Psr_ManIsChar(p, '}') ); p->pCur++; // return special case assert( Vec_IntSize(vTemp2) > 0 ); if ( Vec_IntSize(vTemp2) == 1 ) return Vec_IntEntry(vTemp2, 0); return Abc_Var2Lit2( Psr_NtkAddConcat(p->pNtk, vTemp2), BAC_PRS_CONCAT ); } static inline int Psr_ManReadSignal( Psr_Man_t * p ) { int Item; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 8.", 0); if ( Psr_ManIsDigit(p) ) { Item = Psr_ManReadConstant(p); if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 9.", 0); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 10.", 0); return Abc_Var2Lit2( Item, BAC_PRS_CONST ); } if ( Psr_ManIsChar(p, '{') ) { if ( p->fUsingTemp2 ) return Psr_ManErrorSet(p, "Cannot read nested concatenations.", 0); p->fUsingTemp2 = 1; Item = Psr_ManReadConcat(p, &p->vTemp2); p->fUsingTemp2 = 0; if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 11.", 0); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 12.", 0); return Item; } else { Item = Psr_ManReadName( p ); if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 13.", 0); // was return 1; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 14.", 0); if ( Psr_ManIsChar(p, '[') ) { int Range = Psr_ManReadRange(p); if ( Range == 0 ) return Psr_ManErrorSet(p, "Error number 15.", 0); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 16.", 0); return Abc_Var2Lit2( Psr_NtkAddSlice(p->pNtk, Item, Range), BAC_PRS_SLICE ); } return Abc_Var2Lit2( Item, BAC_PRS_NAME ); } } int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ) { Vec_IntClear( vTemp ); while ( 1 ) { int Item = Psr_ManReadSignal(p); if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read signal in the list.", 0); if ( fAddForm ) Vec_IntPush( vTemp, 0 ); Vec_IntPush( vTemp, Item ); if ( Psr_ManIsChar(p, LastSymb) ) break; if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0); p->pCur++; } return 1; } static inline int Psr_ManReadSignalList2( Psr_Man_t * p, Vec_Int_t * vTemp ) { int FormId, ActItem; Vec_IntClear( vTemp ); assert( Psr_ManIsChar(p, '.') ); while ( Psr_ManIsChar(p, '.') ) { p->pCur++; FormId = Psr_ManReadName( p ); if ( FormId == 0 ) return Psr_ManErrorSet(p, "Cannot read formal name of the instance.", 0); if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot read \"(\" in the instance.", 0); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 17.", 0); ActItem = Psr_ManReadSignal( p ); if ( ActItem == 0 ) return Psr_ManErrorSet(p, "Cannot read actual name of the instance.", 0); if ( !Psr_ManIsChar(p, ')') ) return Psr_ManErrorSet(p, "Cannot read \")\" in the instance.", 0); p->pCur++; Vec_IntPushTwo( vTemp, FormId, ActItem ); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 18.", 0); if ( Psr_ManIsChar(p, ')') ) break; if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 19.", 0); } assert( Vec_IntSize(vTemp) > 0 ); assert( Vec_IntSize(vTemp) % 2 == 0 ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Psr_ManReadDeclaration( Psr_Man_t * p, int Type ) { int i, NameId, RangeId = 0; Vec_Int_t * vNames[4] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts, &p->pNtk->vWires }; Vec_Int_t * vNamesR[4] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR, &p->pNtk->vWiresR }; assert( Type >= PRS_VER_INPUT && Type <= PRS_VER_WIRE ); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 20.", 0); if ( Psr_ManIsChar(p, '[') && !(RangeId = Psr_ManReadRange(p)) ) return Psr_ManErrorSet(p, "Error number 21.", 0); if ( !Psr_ManReadNameList( p, &p->vTemp, ';' ) ) return Psr_ManErrorSet(p, "Error number 22.", 0); Vec_IntForEachEntry( &p->vTemp, NameId, i ) { Vec_IntPush( vNames[Type - PRS_VER_INPUT], NameId ); Vec_IntPush( vNamesR[Type - PRS_VER_INPUT], RangeId ); if ( Type < PRS_VER_WIRE ) Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(NameId, Type) ); } return 1; } static inline int Psr_ManReadAssign( Psr_Man_t * p ) { int OutItem, InItem, fCompl = 0, fCompl2 = 0, Oper = 0; // read output name OutItem = Psr_ManReadSignal( p ); if ( OutItem == 0 ) return Psr_ManErrorSet(p, "Cannot read output in assign-statement.", 0); if ( !Psr_ManIsChar(p, '=') ) return Psr_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 23.", 0); if ( Psr_ManIsChar(p, '~') ) { fCompl = 1; p->pCur++; } // read first name InItem = Psr_ManReadSignal( p ); if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read first input name in the assign-statement.", 0); Vec_IntClear( &p->vTemp ); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, InItem ); // check unary operator if ( Psr_ManIsChar(p, ';') ) { Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, OutItem ); Oper = fCompl ? BAC_BOX_INV : BAC_BOX_BUF; Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); return 1; } if ( Psr_ManIsChar(p, '&') ) Oper = BAC_BOX_AND; else if ( Psr_ManIsChar(p, '|') ) Oper = BAC_BOX_OR; else if ( Psr_ManIsChar(p, '^') ) Oper = BAC_BOX_XOR; else if ( Psr_ManIsChar(p, '?') ) Oper = BAC_BOX_MUX; else return Psr_ManErrorSet(p, "Unrecognized operator in the assign-statement.", 0); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 24.", 0); if ( Psr_ManIsChar(p, '~') ) { fCompl2 = 1; p->pCur++; } // read second name InItem = Psr_ManReadSignal( p ); if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read second input name in the assign-statement.", 0); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, InItem ); // read third argument if ( Oper == BAC_BOX_MUX ) { assert( fCompl == 0 ); if ( !Psr_ManIsChar(p, ':') ) return Psr_ManErrorSet(p, "Expected colon in the MUX assignment.", 0); p->pCur++; // read third name InItem = Psr_ManReadSignal( p ); if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read third input name in the assign-statement.", 0); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, InItem ); if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expected semicolon at the end of the assign-statement.", 0); } else { // figure out operator if ( Oper == BAC_BOX_AND ) { if ( fCompl && !fCompl2 ) Oper = BAC_BOX_SHARPL; else if ( !fCompl && fCompl2 ) Oper = BAC_BOX_SHARP; else if ( fCompl && fCompl2 ) Oper = BAC_BOX_NOR; } else if ( Oper == BAC_BOX_OR ) { if ( fCompl && fCompl2 ) Oper = BAC_BOX_NAND; else assert( !fCompl && !fCompl2 ); } else if ( Oper == BAC_BOX_XOR ) { if ( fCompl && !fCompl2 ) Oper = BAC_BOX_XNOR; else assert( !fCompl && !fCompl2 ); } } // write binary operator Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, OutItem ); Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); return 1; } static inline int Psr_ManReadInstance( Psr_Man_t * p, int Func ) { int InstId, Status; /* static Counter = 0; if ( ++Counter == 7 ) { int s=0; } */ if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 25.", 0); if ( (InstId = Psr_ManReadName(p)) ) if (Psr_ManUtilSkipSpaces(p)) return Psr_ManErrorSet(p, "Error number 26.", 0); if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Expecting \"(\" in module instantiation.", 0); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 27.", 0); if ( Psr_ManIsChar(p, '.') ) // box Status = Psr_ManReadSignalList2(p, &p->vTemp); else // node { //char * s = Abc_NamStr(p->pStrs, Func); // translate elementary gate int iFuncNew = Psr_ManIsVerilogModule(p, Abc_NamStr(p->pStrs, Func)); if ( iFuncNew == 0 ) return Psr_ManErrorSet(p, "Cannot find elementary gate.", 0); Func = iFuncNew; Status = Psr_ManReadSignalList( p, &p->vTemp, ')', 1 ); } if ( Status == 0 ) return Psr_ManErrorSet(p, "Error number 28.", 0); assert( Psr_ManIsChar(p, ')') ); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 29.", 0); if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expecting semicolon in the instance.", 0); // add box Psr_NtkAddBox( p->pNtk, Func, InstId, &p->vTemp ); return 1; } static inline int Psr_ManReadArguments( Psr_Man_t * p ) { int iRange = 0, iType = -1; Vec_Int_t * vSigs[3] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts }; Vec_Int_t * vSigsR[3] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR }; assert( Psr_ManIsChar(p, '(') ); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 30.", 0); while ( 1 ) { int iName = Psr_ManReadName( p ); if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 31.", 0); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 32.", 0); if ( iName >= PRS_VER_INPUT && iName <= PRS_VER_INOUT ) // declaration { iType = iName; if ( Psr_ManIsChar(p, '[') ) { iRange = Psr_ManReadRange(p); if ( iRange == 0 ) return Psr_ManErrorSet(p, "Error number 33.", 0); if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 34.", 0); } iName = Psr_ManReadName( p ); if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 35.", 0); } if ( iType > 0 ) { Vec_IntPush( vSigs[iType - PRS_VER_INPUT], iName ); Vec_IntPush( vSigsR[iType - PRS_VER_INPUT], iRange ); Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(iName, iType) ); } if ( Psr_ManIsChar(p, ')') ) break; if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 36.", 0); } // check final assert( Psr_ManIsChar(p, ')') ); return 1; } // this procedure can return: // 0 = reached end-of-file; 1 = successfully parsed; 2 = recognized as primitive; 3 = failed and skipped; 4 = error (failed and could not skip) static inline int Psr_ManReadModule( Psr_Man_t * p ) { int iToken, Status; if ( p->pNtk != NULL ) return Psr_ManErrorSet(p, "Parsing previous module is unfinished.", 4); if ( Psr_ManUtilSkipSpaces(p) ) { Psr_ManErrorClear( p ); return 0; } // read keyword iToken = Psr_ManReadName( p ); if ( iToken != PRS_VER_MODULE ) return Psr_ManErrorSet(p, "Cannot read \"module\" keyword.", 4); if ( Psr_ManUtilSkipSpaces(p) ) return 4; // read module name iToken = Psr_ManReadName( p ); if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read module name.", 4); if ( Psr_ManIsKnownModule(p, Abc_NamStr(p->pStrs, iToken)) ) { if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4); //printf( "Warning! Skipped known module \"%s\".\n", Abc_NamStr(p->pStrs, iToken) ); Vec_IntPush( &p->vKnown, iToken ); return 2; } Psr_ManInitializeNtk( p, iToken, 1 ); // skip arguments if ( Psr_ManUtilSkipSpaces(p) ) return 4; if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot find \"(\" in the argument declaration.", 4); if ( !Psr_ManReadArguments(p) ) return 4; assert( *p->pCur == ')' ); p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return 4; // read declarations and instances while ( Psr_ManIsChar(p, ';') ) { p->pCur++; if ( Psr_ManUtilSkipSpaces(p) ) return 4; iToken = Psr_ManReadName( p ); if ( iToken == PRS_VER_ENDMODULE ) { Vec_IntPush( &p->vSucceeded, p->pNtk->iModuleName ); Psr_ManFinalizeNtk( p ); return 1; } if ( iToken >= PRS_VER_INPUT && iToken <= PRS_VER_WIRE ) // declaration Status = Psr_ManReadDeclaration( p, iToken ); else if ( iToken == PRS_VER_REG || iToken == PRS_VER_DEFPARAM ) // unsupported keywords Status = Psr_ManUtilSkipUntil( p, ';' ); else // read instance { if ( iToken == PRS_VER_ASSIGN ) Status = Psr_ManReadAssign( p ); else Status = Psr_ManReadInstance( p, iToken ); if ( Status == 0 ) { if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4); //printf( "Warning! Failed to parse \"%s\". Adding module \"%s\" as blackbox.\n", // Abc_NamStr(p->pStrs, iToken), Abc_NamStr(p->pStrs, p->pNtk->iModuleName) ); Vec_IntPush( &p->vFailed, p->pNtk->iModuleName ); // cleanup Vec_IntErase( &p->pNtk->vWires ); Vec_IntErase( &p->pNtk->vWiresR ); Vec_IntErase( &p->pNtk->vSlices ); Vec_IntErase( &p->pNtk->vConcats ); Vec_IntErase( &p->pNtk->vBoxes ); Vec_IntErase( &p->pNtk->vObjs ); p->fUsingTemp2 = 0; // add Psr_ManFinalizeNtk( p ); Psr_ManErrorClear( p ); return 3; } } if ( !Status ) return 4; if ( Psr_ManUtilSkipSpaces(p) ) return 4; } return Psr_ManErrorSet(p, "Cannot find \";\" in the module definition.", 4); } static inline int Psr_ManReadDesign( Psr_Man_t * p ) { while ( 1 ) { int RetValue = Psr_ManReadModule( p ); if ( RetValue == 0 ) // end of file break; if ( RetValue == 1 ) // successfully parsed continue; if ( RetValue == 2 ) // recognized as primitive continue; if ( RetValue == 3 ) // failed and skipped continue; if ( RetValue == 4 ) // error return 0; assert( 0 ); } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Psr_ManPrintModules( Psr_Man_t * p ) { char * pName; int i; printf( "Succeeded parsing %d models:\n", Vec_IntSize(&p->vSucceeded) ); Psr_ManForEachNameVec( &p->vSucceeded, p, pName, i ) printf( " %s", pName ); printf( "\n" ); printf( "Skipped %d known models:\n", Vec_IntSize(&p->vKnown) ); Psr_ManForEachNameVec( &p->vKnown, p, pName, i ) printf( " %s", pName ); printf( "\n" ); printf( "Skipped %d failed models:\n", Vec_IntSize(&p->vFailed) ); Psr_ManForEachNameVec( &p->vFailed, p, pName, i ) printf( " %s", pName ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Psr_ManReadVerilog( char * pFileName ) { Vec_Ptr_t * vPrs = NULL; Psr_Man_t * p = Psr_ManAlloc( pFileName ); if ( p == NULL ) return NULL; Psr_NtkAddVerilogDirectives( p ); Psr_ManReadDesign( p ); //Psr_ManPrintModules( p ); if ( Psr_ManErrorPrint(p) ) ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks ); Psr_ManFree( p ); return vPrs; } void Psr_ManReadVerilogTest( char * pFileName ) { abctime clk = Abc_Clock(); extern void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * p ); Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "c/hie/dump/1/netlist_1.v" ); // Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/me/me_wide.v" ); // Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/ray/ray_wide.v" ); if ( !vPrs ) return; printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) ); printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) ); printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Psr_ManWriteVerilog( "c/hie/dump/1/netlist_1_out_new.v", vPrs ); // Psr_ManWriteVerilog( "aga/me/me_wide_out.v", vPrs ); // Psr_ManWriteVerilog( "aga/ray/ray_wide_out.v", vPrs ); // Abc_NamPrint( p->pStrs ); Psr_ManVecFree( vPrs ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacWriteBlif.c000066400000000000000000000203251300674244400241760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacWriteBlif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Verilog parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacWriteBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "bacPrs.h" #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writing parser state into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Psr_ManWriteBlifArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vFanins ) { int i, NameId; Vec_IntForEachEntry( vFanins, NameId, i ) fprintf( pFile, " %s", Psr_NtkStr(p, NameId) ); fprintf( pFile, "\n" ); } static void Psr_ManWriteBlifLines( FILE * pFile, Psr_Ntk_t * p ) { Vec_Int_t * vBox; int i, k, FormId, ActId; Psr_NtkForEachBox( p, vBox, i ) { int NtkId = Psr_BoxNtk(p, i); assert( Psr_BoxIONum(p, i) > 0 ); assert( Vec_IntSize(vBox) % 2 == 0 ); if ( NtkId == -1 ) // latch { fprintf( pFile, ".latch" ); fprintf( pFile, " %s", Psr_NtkStr(p, Vec_IntEntry(vBox, 1)) ); fprintf( pFile, " %s", Psr_NtkStr(p, Vec_IntEntry(vBox, 3)) ); fprintf( pFile, " %c\n", '0' + Psr_BoxName(p, i) ); } else if ( Psr_BoxIsNode(p, i) ) // node { fprintf( pFile, ".names" ); Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) fprintf( pFile, " %s", Psr_NtkStr(p, ActId) ); fprintf( pFile, "\n%s", Psr_NtkStr(p, NtkId) ); } else // box { fprintf( pFile, ".subckt" ); fprintf( pFile, " %s", Psr_NtkStr(p, NtkId) ); Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) fprintf( pFile, " %s=%s", Psr_NtkStr(p, FormId), Psr_NtkStr(p, ActId) ); fprintf( pFile, "\n" ); } } } static void Psr_ManWriteBlifNtk( FILE * pFile, Psr_Ntk_t * p ) { // write header fprintf( pFile, ".model %s\n", Psr_NtkStr(p, p->iModuleName) ); if ( Vec_IntSize(&p->vInouts) ) fprintf( pFile, ".inouts" ); if ( Vec_IntSize(&p->vInouts) ) Psr_ManWriteBlifArray( pFile, p, &p->vInouts ); fprintf( pFile, ".inputs" ); Psr_ManWriteBlifArray( pFile, p, &p->vInputs ); fprintf( pFile, ".outputs" ); Psr_ManWriteBlifArray( pFile, p, &p->vOutputs ); // write objects Psr_ManWriteBlifLines( pFile, p ); fprintf( pFile, ".end\n\n" ); } void Psr_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs ) { Psr_Ntk_t * pNtk = Psr_ManRoot(vPrs); FILE * pFile = fopen( pFileName, "wb" ); int i; if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# Design \"%s\" written by ABC on %s\n\n", Psr_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() ); Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i ) Psr_ManWriteBlifNtk( pFile, pNtk ); fclose( pFile ); } /**Function************************************************************* Synopsis [Write elaborated design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bac_ManWriteBlifGate( FILE * pFile, Bac_Ntk_t * p, Mio_Gate_t * pGate, Vec_Int_t * vFanins, int iObj ) { int iFanin, i; Vec_IntForEachEntry( vFanins, iFanin, i ) fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, i), Bac_ObjNameStr(p, iFanin) ); fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Bac_ObjNameStr(p, iObj) ); fprintf( pFile, "\n" ); } void Bac_ManWriteBlifArray( FILE * pFile, Bac_Ntk_t * p, Vec_Int_t * vFanins, int iObj ) { int iFanin, i; Vec_IntForEachEntry( vFanins, iFanin, i ) fprintf( pFile, " %s", Bac_ObjNameStr(p, iFanin) ); if ( iObj >= 0 ) fprintf( pFile, " %s", Bac_ObjNameStr(p, iObj) ); fprintf( pFile, "\n" ); } void Bac_ManWriteBlifArray2( FILE * pFile, Bac_Ntk_t * p, int iObj ) { int iTerm, i; Bac_Ntk_t * pModel = Bac_BoxNtk( p, iObj ); Bac_NtkForEachPi( pModel, iTerm, i ) fprintf( pFile, " %s=%s", Bac_ObjNameStr(pModel, iTerm), Bac_ObjNameStr(p, Bac_BoxBi(p, iObj, i)) ); Bac_NtkForEachPo( pModel, iTerm, i ) fprintf( pFile, " %s=%s", Bac_ObjNameStr(pModel, iTerm), Bac_ObjNameStr(p, Bac_BoxBo(p, iObj, i)) ); fprintf( pFile, "\n" ); } void Bac_ManWriteBlifLines( FILE * pFile, Bac_Ntk_t * p ) { int i, k, iTerm; Bac_NtkForEachBox( p, i ) { if ( Bac_ObjIsBoxUser(p, i) ) { fprintf( pFile, ".subckt" ); fprintf( pFile, " %s", Bac_NtkName(Bac_BoxNtk(p, i)) ); Bac_ManWriteBlifArray2( pFile, p, i ); } else if ( Bac_ObjIsGate(p, i) ) { char * pGateName = Abc_NamStr(p->pDesign->pMods, Bac_BoxNtkId(p, i)); Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL ); fprintf( pFile, ".gate %s", pGateName ); Bac_BoxForEachBi( p, i, iTerm, k ) fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, k), Bac_ObjNameStr(p, iTerm) ); Bac_BoxForEachBo( p, i, iTerm, k ) fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Bac_ObjNameStr(p, iTerm) ); fprintf( pFile, "\n" ); } else { fprintf( pFile, ".names" ); Bac_BoxForEachBi( p, i, iTerm, k ) fprintf( pFile, " %s", Bac_ObjNameStr(p, Bac_ObjFanin(p, iTerm)) ); Bac_BoxForEachBo( p, i, iTerm, k ) fprintf( pFile, " %s", Bac_ObjNameStr(p, iTerm) ); fprintf( pFile, "\n%s", Ptr_TypeToSop(Bac_ObjType(p, i)) ); } } } void Bac_ManWriteBlifNtk( FILE * pFile, Bac_Ntk_t * p ) { assert( Vec_IntSize(&p->vFanin) == Bac_NtkObjNum(p) ); // write header fprintf( pFile, ".model %s\n", Bac_NtkName(p) ); fprintf( pFile, ".inputs" ); Bac_ManWriteBlifArray( pFile, p, &p->vInputs, -1 ); fprintf( pFile, ".outputs" ); Bac_ManWriteBlifArray( pFile, p, &p->vOutputs, -1 ); // write objects Bac_ManWriteBlifLines( pFile, p ); fprintf( pFile, ".end\n\n" ); } void Bac_ManWriteBlif( char * pFileName, Bac_Man_t * p ) { FILE * pFile; Bac_Ntk_t * pNtk; int i; // check the library if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() ) { printf( "Genlib library used in the mapped design is not longer a current library.\n" ); return; } pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# Design \"%s\" written via CBA package in ABC on %s\n\n", Bac_ManName(p), Extra_TimeStamp() ); Bac_ManAssignInternWordNames( p ); Bac_ManForEachNtk( p, pNtk, i ) Bac_ManWriteBlifNtk( pFile, pNtk ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacWriteSmt.c000066400000000000000000000027361300674244400240730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacWriteSmt.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Verilog parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacWriteSmt.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/bacWriteVer.c000066400000000000000000000647771300674244400241010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bacWriteVer.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Verilog writer.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: bacWriteVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bac.h" #include "bacPrs.h" #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writing parser state into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Psr_ManWriteVerilogConcat( FILE * pFile, Psr_Ntk_t * p, int Con ) { extern void Psr_ManWriteVerilogArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs, int Start, int Stop, int fOdd ); Vec_Int_t * vSigs = Psr_CatSignals(p, Con); fprintf( pFile, "{" ); Psr_ManWriteVerilogArray( pFile, p, vSigs, 0, Vec_IntSize(vSigs), 0 ); fprintf( pFile, "}" ); } static void Psr_ManWriteVerilogSignal( FILE * pFile, Psr_Ntk_t * p, int Sig ) { int Value = Abc_Lit2Var2( Sig ); Psr_ManType_t Type = (Psr_ManType_t)Abc_Lit2Att2( Sig ); if ( Type == BAC_PRS_NAME || Type == BAC_PRS_CONST ) fprintf( pFile, "%s", Psr_NtkStr(p, Value) ); else if ( Type == BAC_PRS_SLICE ) fprintf( pFile, "%s%s", Psr_NtkStr(p, Psr_SliceName(p, Value)), Psr_NtkStr(p, Psr_SliceRange(p, Value)) ); else if ( Type == BAC_PRS_CONCAT ) Psr_ManWriteVerilogConcat( pFile, p, Value ); else assert( 0 ); } void Psr_ManWriteVerilogArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs, int Start, int Stop, int fOdd ) { int i, Sig; assert( Vec_IntSize(vSigs) > 0 ); Vec_IntForEachEntryStartStop( vSigs, Sig, i, Start, Stop ) { if ( fOdd && !(i & 1) ) continue; Psr_ManWriteVerilogSignal( pFile, p, Sig ); fprintf( pFile, "%s", i == Stop - 1 ? "" : ", " ); } } static void Psr_ManWriteVerilogArray2( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs ) { int i, FormId, ActSig; assert( Vec_IntSize(vSigs) % 2 == 0 ); Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i ) { fprintf( pFile, "." ); fprintf( pFile, "%s", Psr_NtkStr(p, FormId) ); fprintf( pFile, "(" ); Psr_ManWriteVerilogSignal( pFile, p, ActSig ); fprintf( pFile, ")%s", (i == Vec_IntSize(vSigs) - 2) ? "" : ", " ); } } static void Psr_ManWriteVerilogMux( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs ) { int i, FormId, ActSig; char * pStrs[4] = { " = ", " ? ", " : ", ";\n" }; assert( Vec_IntSize(vSigs) == 8 ); fprintf( pFile, " assign " ); Psr_ManWriteVerilogSignal( pFile, p, Vec_IntEntryLast(vSigs) ); fprintf( pFile, "%s", pStrs[0] ); Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i ) { Psr_ManWriteVerilogSignal( pFile, p, ActSig ); fprintf( pFile, "%s", pStrs[1+i/2] ); if ( i == 4 ) break; } } static void Psr_ManWriteVerilogBoxes( FILE * pFile, Psr_Ntk_t * p ) { Vec_Int_t * vBox; int i; Psr_NtkForEachBox( p, vBox, i ) { Bac_ObjType_t NtkId = (Bac_ObjType_t)Psr_BoxNtk(p, i); if ( NtkId == BAC_BOX_MUX ) Psr_ManWriteVerilogMux( pFile, p, vBox ); else if ( Psr_BoxIsNode(p, i) ) // node ------- check order of fanins { fprintf( pFile, " %s (", Ptr_TypeToName(NtkId) ); Psr_ManWriteVerilogSignal( pFile, p, Vec_IntEntryLast(vBox) ); if ( Psr_BoxIONum(p, i) > 1 ) fprintf( pFile, ", " ); Psr_ManWriteVerilogArray( pFile, p, vBox, 0, Vec_IntSize(vBox)-2, 1 ); fprintf( pFile, ");\n" ); } else // box { //char * s = Psr_NtkStr(p, Vec_IntEntry(vBox, 0)); fprintf( pFile, " %s %s (", Psr_NtkStr(p, NtkId), Psr_BoxName(p, i) ? Psr_NtkStr(p, Psr_BoxName(p, i)) : "" ); Psr_ManWriteVerilogArray2( pFile, p, vBox ); fprintf( pFile, ");\n" ); } } } static void Psr_ManWriteVerilogIos( FILE * pFile, Psr_Ntk_t * p, int SigType ) { int NameId, RangeId, i; char * pSigNames[4] = { "inout", "input", "output", "wire" }; Vec_Int_t * vSigs[4] = { &p->vInouts, &p->vInputs, &p->vOutputs, &p->vWires }; Vec_Int_t * vSigsR[4] = { &p->vInoutsR, &p->vInputsR, &p->vOutputsR, &p->vWiresR }; if ( SigType == 3 ) fprintf( pFile, "\n" ); Vec_IntForEachEntryTwo( vSigs[SigType], vSigsR[SigType], NameId, RangeId, i ) fprintf( pFile, " %s %s%s;\n", pSigNames[SigType], RangeId ? Psr_NtkStr(p, RangeId) : "", Psr_NtkStr(p, NameId) ); } static void Psr_ManWriteVerilogIoOrder( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vOrder ) { int i, NameId; Vec_IntForEachEntry( vOrder, NameId, i ) fprintf( pFile, "%s%s", Psr_NtkStr(p, NameId), i == Vec_IntSize(vOrder) - 1 ? "" : ", " ); } static void Psr_ManWriteVerilogNtk( FILE * pFile, Psr_Ntk_t * p ) { int s; // write header fprintf( pFile, "module %s (\n ", Psr_NtkStr(p, p->iModuleName) ); Psr_ManWriteVerilogIoOrder( pFile, p, &p->vOrder ); fprintf( pFile, "\n );\n" ); // write declarations for ( s = 0; s < 4; s++ ) Psr_ManWriteVerilogIos( pFile, p, s ); fprintf( pFile, "\n" ); // write objects Psr_ManWriteVerilogBoxes( pFile, p ); fprintf( pFile, "endmodule\n\n" ); } void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * vPrs ) { Psr_Ntk_t * pNtk = Psr_ManRoot(vPrs); int i; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "// Design \"%s\" written by ABC on %s\n\n", Psr_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() ); Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i ) Psr_ManWriteVerilogNtk( pFile, pNtk ); fclose( pFile ); } /**Function************************************************************* Synopsis [Writing word-level Verilog.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // compute range of a name (different from range of a multi-bit wire) static inline int Bac_ObjGetRange( Bac_Ntk_t * p, int iObj ) { int i, NameId = Bac_ObjName(p, iObj); assert( Bac_ObjIsCi(p, iObj) ); // if ( Bac_NameType(NameId) == BAC_NAME_INDEX ) // NameId = Bac_ObjName(p, iObj - Abc_Lit2Var2(NameId)); assert( Bac_NameType(NameId) == BAC_NAME_WORD || Bac_NameType(NameId) == BAC_NAME_INFO ); for ( i = iObj + 1; i < Bac_NtkObjNum(p); i++ ) if ( !Bac_ObjIsCi(p, i) || Bac_ObjNameType(p, i) != BAC_NAME_INDEX ) break; return i - iObj; } static inline void Bac_ManWriteVar( Bac_Ntk_t * p, int RealName ) { Vec_StrPrintStr( p->pDesign->vOut, Bac_NtkStr(p, RealName) ); } static inline void Bac_ManWriteRange( Bac_Ntk_t * p, int Beg, int End ) { Vec_Str_t * vStr = p->pDesign->vOut; Vec_StrPrintStr( vStr, "[" ); if ( End >= 0 ) { Vec_StrPrintNum( vStr, End ); Vec_StrPrintStr( vStr, ":" ); } Vec_StrPrintNum( vStr, Beg ); Vec_StrPrintStr( vStr, "]" ); } static inline void Bac_ManWriteConstBit( Bac_Ntk_t * p, int iObj, int fHead ) { Vec_Str_t * vStr = p->pDesign->vOut; int Const = Bac_ObjGetConst(p, iObj); assert( Const ); if ( fHead ) Vec_StrPrintStr( vStr, "1\'b" ); if ( Const == BAC_BOX_CF ) Vec_StrPush( vStr, '0' ); else if ( Const == BAC_BOX_CT ) Vec_StrPush( vStr, '1' ); else if ( Const == BAC_BOX_CX ) Vec_StrPush( vStr, 'x' ); else if ( Const == BAC_BOX_CZ ) Vec_StrPush( vStr, 'z' ); else assert( 0 ); } static inline int Bac_ManFindRealNameId( Bac_Ntk_t * p, int iObj ) { int NameId = Bac_ObjName(p, iObj); assert( Bac_ObjIsCi(p, iObj) ); if ( Bac_NameType(NameId) == BAC_NAME_INDEX ) NameId = Bac_ObjName(p, iObj - Abc_Lit2Var2(NameId)); if ( Bac_NameType(NameId) == BAC_NAME_INFO ) return Bac_NtkInfoName(p, Abc_Lit2Var2(NameId)); assert( Bac_NameType(NameId) == BAC_NAME_BIN || Bac_NameType(NameId) == BAC_NAME_WORD ); return Abc_Lit2Var2(NameId); } static inline int Bac_ManFindRealIndex( Bac_Ntk_t * p, int iObj ) { int iBit = 0, NameId = Bac_ObjName(p, iObj); assert( Bac_ObjIsCi(p, iObj) ); assert( Bac_NameType(NameId) != BAC_NAME_BIN ); if ( Bac_NameType(NameId) == BAC_NAME_INDEX ) NameId = Bac_ObjName(p, iObj - (iBit = Abc_Lit2Var2(NameId))); if ( Bac_NameType(NameId) == BAC_NAME_INFO ) return Bac_NtkInfoIndex(p, Abc_Lit2Var2(NameId), iBit); assert( Bac_NameType(NameId) == BAC_NAME_WORD ); return iBit; } static inline void Bac_ManWriteSig( Bac_Ntk_t * p, int iObj ) { if ( Bac_ObjIsCo(p, iObj) ) iObj = Bac_ObjFanin(p, iObj); assert( Bac_ObjIsCi(p, iObj) ); if ( Bac_ObjGetConst(p, iObj) ) Bac_ManWriteConstBit( p, iObj, 1 ); else { int NameId = Bac_ObjName(p, iObj); if ( Bac_NameType(NameId) == BAC_NAME_BIN ) Bac_ManWriteVar( p, Abc_Lit2Var2(NameId) ); else { Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, iObj) ); Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, iObj), -1 ); } } } static inline void Bac_ManWriteConcat( Bac_Ntk_t * p, int iStart, int nObjs ) { Vec_Str_t * vStr = p->pDesign->vOut; assert( nObjs >= 1 ); if ( nObjs == 1 ) { Bac_ManWriteSig( p, iStart ); return; } Vec_StrPrintStr( vStr, "{" ); if ( Bac_ObjIsBo(p, iStart) ) // box output { int i; for ( i = iStart + nObjs - 1; i >= iStart; i-- ) { if ( Bac_ObjNameType(p, i) == BAC_NAME_INDEX ) continue; if ( Vec_StrEntryLast(vStr) != '{' ) Vec_StrPrintStr( vStr, ", " ); Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, i) ); } } else if ( Bac_ObjIsBi(p, iStart) ) // box input { int e, b, k, NameId; for ( e = iStart - nObjs + 1; e <= iStart; ) { if ( Vec_StrEntryLast(vStr) != '{' ) Vec_StrPrintStr( vStr, ", " ); // write constant if ( Bac_ObjGetConst(p, Bac_ObjFanin(p, e)) ) { int fBinary = Bac_ObjIsConstBin(p, Bac_ObjFanin(p, e)-1); for ( b = e + 1; b <= iStart; b++ ) { if ( !Bac_ObjGetConst(p, Bac_ObjFanin(p, b)) ) break; if ( !Bac_ObjIsConstBin(p, Bac_ObjFanin(p, b)-1) ) fBinary = 0; } Vec_StrPrintNum( vStr, b - e ); if ( fBinary && b - e > 8 ) // write hex if more than 8 bits { int Digit = 0, nBits = ((b - e) & 3) ? (b - e) & 3 : 4; Vec_StrPrintStr( vStr, "\'h" ); for ( k = e; k < b; k++ ) { Digit = 2*Digit + Bac_ObjGetConst(p, Bac_ObjFanin(p, k)) - BAC_BOX_CF; assert( Digit < 16 ); if ( --nBits == 0 ) { Vec_StrPush( vStr, (char)(Digit < 10 ? '0' + Digit : 'a' + Digit - 10) ); nBits = 4; Digit = 0; } } assert( nBits == 4 ); assert( Digit == 0 ); } else { Vec_StrPrintStr( vStr, "\'b" ); for ( k = e; k < b; k++ ) Bac_ManWriteConstBit( p, Bac_ObjFanin(p, k), 0 ); } e = b; continue; } // try replication for ( b = e + 1; b <= iStart; b++ ) if ( Bac_ObjFanin(p, b) != Bac_ObjFanin(p, e) ) break; if ( b > e + 2 ) // more than two { Vec_StrPrintNum( vStr, b - e ); Vec_StrPrintStr( vStr, "{" ); Bac_ManWriteSig( p, e ); Vec_StrPrintStr( vStr, "}" ); e = b; continue; } NameId = Bac_ObjName(p, Bac_ObjFanin(p, e)); if ( Bac_NameType(NameId) == BAC_NAME_BIN ) { Bac_ManWriteVar( p, Abc_Lit2Var2(NameId) ); e++; continue; } // find end of the slice for ( b = e + 1; b <= iStart; b++ ) if ( Bac_ObjFanin(p, e) - Bac_ObjFanin(p, b) != b - e ) break; // write signal name Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, Bac_ObjFanin(p, e)) ); if ( b == e + 1 ) // literal Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, Bac_ObjFanin(p, e)), -1 ); else // slice or complete variable { // consider first variable of the slice int f = Bac_ObjFanin( p, b-1 ); assert( Bac_ObjNameType(p, f) != BAC_NAME_BIN ); if ( Bac_ObjNameType(p, f) == BAC_NAME_INDEX || Bac_ObjGetRange(p, f) != b - e ) // slice Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, f), Bac_ManFindRealIndex(p, Bac_ObjFanin(p, e)) ); // else this is complete variable } e = b; } } else assert( 0 ); Vec_StrPrintStr( vStr, "}" ); } static inline void Bac_ManWriteGate( Bac_Ntk_t * p, int iObj ) { Vec_Str_t * vStr = p->pDesign->vOut; int iTerm, k; char * pGateName = Abc_NamStr(p->pDesign->pMods, Bac_BoxNtkId(p, iObj)); Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, pGateName ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" ); Vec_StrPrintStr( vStr, " (" ); Bac_BoxForEachBi( p, iObj, iTerm, k ) { Vec_StrPrintStr( vStr, k ? ", ." : "." ); Vec_StrPrintStr( vStr, Mio_GateReadPinName(pGate, k) ); Vec_StrPrintStr( vStr, "(" ); Bac_ManWriteSig( p, iTerm ); Vec_StrPrintStr( vStr, ")" ); } Bac_BoxForEachBo( p, iObj, iTerm, k ) { Vec_StrPrintStr( vStr, Bac_BoxBiNum(p, iObj) ? ", ." : "." ); Vec_StrPrintStr( vStr, Mio_GateReadOutName(pGate) ); Vec_StrPrintStr( vStr, "(" ); Bac_ManWriteSig( p, iTerm ); Vec_StrPrintStr( vStr, ")" ); } Vec_StrPrintStr( vStr, ");\n" ); } static inline void Bac_ManWriteAssign( Bac_Ntk_t * p, int iObj ) { Vec_Str_t * vStr = p->pDesign->vOut; Bac_ObjType_t Type = Bac_ObjType(p, iObj); int nInputs = Bac_BoxBiNum(p, iObj); int nOutputs = Bac_BoxBoNum(p, iObj); assert( nOutputs == 1 ); Vec_StrPrintStr( vStr, " assign " ); Bac_ManWriteSig( p, iObj + 1 ); Vec_StrPrintStr( vStr, " = " ); if ( nInputs == 0 ) { if ( Type == BAC_BOX_CF ) Vec_StrPrintStr( vStr, "1\'b0" ); else if ( Type == BAC_BOX_CT ) Vec_StrPrintStr( vStr, "1\'b1" ); else if ( Type == BAC_BOX_CX ) Vec_StrPrintStr( vStr, "1\'bx" ); else if ( Type == BAC_BOX_CZ ) Vec_StrPrintStr( vStr, "1\'bz" ); else assert( 0 ); } else if ( nInputs == 1 ) { if ( Type == BAC_BOX_INV ) Vec_StrPrintStr( vStr, "~" ); else assert( Type == BAC_BOX_BUF ); Bac_ManWriteSig( p, iObj - 1 ); } else if ( nInputs == 2 ) { if ( Type == BAC_BOX_NAND || Type == BAC_BOX_NOR || Type == BAC_BOX_XNOR || Type == BAC_BOX_SHARPL ) Vec_StrPrintStr( vStr, "~" ); Bac_ManWriteSig( p, iObj - 1 ); if ( Type == BAC_BOX_AND || Type == BAC_BOX_SHARPL ) Vec_StrPrintStr( vStr, " & " ); else if ( Type == BAC_BOX_SHARP || Type == BAC_BOX_NOR ) Vec_StrPrintStr( vStr, " & ~" ); else if ( Type == BAC_BOX_OR ) Vec_StrPrintStr( vStr, " | " ); else if ( Type == BAC_BOX_NAND ) Vec_StrPrintStr( vStr, " | ~" ); else if ( Type == BAC_BOX_XOR || Type == BAC_BOX_XNOR ) Vec_StrPrintStr( vStr, " ^ " ); else assert( 0 ); Bac_ManWriteSig( p, iObj - 2 ); } Vec_StrPrintStr( vStr, ";\n" ); } void Bac_ManWriteVerilogBoxes( Bac_Ntk_t * p, int fUseAssign ) { Vec_Str_t * vStr = p->pDesign->vOut; int iObj, k, i, o, StartPos; Bac_NtkForEachBox( p, iObj ) // .subckt/.gate/box (formal/actual binding) { // skip constants if ( Bac_ObjIsConst(p, iObj) ) continue; // write mapped if ( Bac_ObjIsGate(p, iObj) ) { Bac_ManWriteGate( p, iObj ); continue; } // write primitives as assign-statements if ( !Bac_ObjIsBoxUser(p, iObj) && fUseAssign ) { Bac_ManWriteAssign( p, iObj ); continue; } // write header StartPos = Vec_StrSize(vStr); if ( Bac_ObjIsBoxUser(p, iObj) ) { int Value, Beg, End, Range; Bac_Ntk_t * pModel = Bac_BoxNtk( p, iObj ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Bac_NtkName(pModel) ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" ); Vec_StrPrintStr( vStr, " (" ); // write arguments i = o = 0; assert( Bac_NtkInfoNum(pModel) ); Vec_IntForEachEntryTriple( &pModel->vInfo, Value, Beg, End, k ) { int NameId = Abc_Lit2Var2( Value ); int Type = Abc_Lit2Att2( Value ); Vec_StrPrintStr( vStr, k ? ", " : "" ); if ( Vec_StrSize(vStr) > StartPos + 70 ) { StartPos = Vec_StrSize(vStr); Vec_StrPrintStr( vStr, "\n " ); } Vec_StrPrintStr( vStr, "." ); Vec_StrPrintStr( vStr, Bac_NtkStr(p, NameId) ); Vec_StrPrintStr( vStr, "(" ); Range = Bac_InfoRange( Beg, End ); assert( Range > 0 ); if ( Type == 1 ) Bac_ManWriteConcat( p, Bac_BoxBi(p, iObj, i), Range ), i += Range; else if ( Type == 2 ) Bac_ManWriteConcat( p, Bac_BoxBo(p, iObj, o), Range ), o += Range; else assert( 0 ); Vec_StrPrintStr( vStr, ")" ); } assert( i == Bac_BoxBiNum(p, iObj) ); assert( o == Bac_BoxBoNum(p, iObj) ); } else { int iTerm, k, Range, iSig = 0; Vec_Int_t * vBits = Bac_BoxCollectRanges( p, iObj ); char * pName = Bac_NtkGenerateName( p, Bac_ObjType(p, iObj), vBits ); char * pSymbs = Bac_ManPrimSymb( p->pDesign, Bac_ObjType(p, iObj) ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, pName ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" ); Vec_StrPrintStr( vStr, " (" ); // write inputs Bac_BoxForEachBiMain( p, iObj, iTerm, k ) { Range = Vec_IntEntry( vBits, iSig ); Vec_StrPrintStr( vStr, iSig ? ", " : "" ); if ( Vec_StrSize(vStr) > StartPos + 70 ) { StartPos = Vec_StrSize(vStr); Vec_StrPrintStr( vStr, "\n " ); } Vec_StrPrintStr( vStr, "." ); Vec_StrPush( vStr, pSymbs[iSig] ); Vec_StrPrintStr( vStr, "(" ); Bac_ManWriteConcat( p, iTerm, Range ); Vec_StrPrintStr( vStr, ")" ); iSig++; } Bac_BoxForEachBoMain( p, iObj, iTerm, k ) { Range = Vec_IntEntry( vBits, iSig ); Vec_StrPrintStr( vStr, iSig ? ", " : "" ); if ( Vec_StrSize(vStr) > StartPos + 70 ) { StartPos = Vec_StrSize(vStr); Vec_StrPrintStr( vStr, "\n " ); } Vec_StrPrintStr( vStr, "." ); Vec_StrPush( vStr, pSymbs[iSig] ); Vec_StrPrintStr( vStr, "(" ); Bac_ManWriteConcat( p, iTerm, Range ); Vec_StrPrintStr( vStr, ")" ); iSig++; } assert( iSig == Vec_IntSize(vBits) ); } Vec_StrPrintStr( vStr, ");\n" ); } } void Bac_ManWriteVerilogNtk( Bac_Ntk_t * p, int fUseAssign ) { char * pKeyword[4] = { "wire ", "input ", "output ", "inout " }; Vec_Str_t * vStr = p->pDesign->vOut; int k, iObj, iTerm, Value, Beg, End, Length, fHaveWires, StartPos; // assert( Bac_NtkInfoNum(p) ); assert( Vec_IntSize(&p->vFanin) == Bac_NtkObjNum(p) ); // Bac_NtkPrint( p ); // write header Vec_StrPrintStr( vStr, "module " ); Vec_StrPrintStr( vStr, Bac_NtkName(p) ); Vec_StrPrintStr( vStr, " (\n " ); StartPos = Vec_StrSize(vStr); Vec_IntForEachEntryTriple( &p->vInfo, Value, Beg, End, k ) if ( Abc_Lit2Att2(Value) != 0 ) { Vec_StrPrintStr( vStr, k ? ", " : "" ); if ( Vec_StrSize(vStr) > StartPos + 70 ) { StartPos = Vec_StrSize(vStr); Vec_StrPrintStr( vStr, "\n " ); } Bac_ManWriteVar( p, Abc_Lit2Var2(Value) ); } Vec_StrPrintStr( vStr, "\n );\n" ); // write inputs/outputs Vec_IntForEachEntryTriple( &p->vInfo, Value, Beg, End, k ) if ( Abc_Lit2Att2(Value) != 0 ) { Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, pKeyword[Abc_Lit2Att2(Value)] ); if ( Beg >= 0 ) Bac_ManWriteRange( p, Beg, End ); Bac_ManWriteVar( p, Abc_Lit2Var2(Value) ); Vec_StrPrintStr( vStr, ";\n" ); } Vec_StrPrintStr( vStr, "\n" ); // write word-level wires Bac_NtkForEachBox( p, iObj ) if ( !Bac_ObjIsConst(p, iObj) ) Bac_BoxForEachBo( p, iObj, iTerm, k ) if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_WORD || Bac_ObjNameType(p, iTerm) == BAC_NAME_INFO ) { Vec_StrPrintStr( vStr, " wire " ); Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, iTerm), Bac_ManFindRealIndex(p, iTerm + Bac_ObjGetRange(p, iTerm) - 1) ); Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, iTerm) ); Vec_StrPrintStr( vStr, ";\n" ); } // check if there are any wires left fHaveWires = 0; Bac_NtkForEachBox( p, iObj ) if ( !Bac_ObjIsConst(p, iObj) ) Bac_BoxForEachBo( p, iObj, iTerm, k ) if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_BIN ) { fHaveWires = 1; iObj = Bac_NtkObjNum(p); break; } // write bit-level wires if ( fHaveWires ) { Length = 7; Vec_StrPrintStr( vStr, "\n wire " ); Bac_NtkForEachBox( p, iObj ) if ( !Bac_ObjIsConst(p, iObj) ) Bac_BoxForEachBo( p, iObj, iTerm, k ) if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_BIN ) { if ( Length > 72 ) Vec_StrPrintStr( vStr, ";\n wire " ), Length = 7; if ( Length > 7 ) Vec_StrPrintStr( vStr, ", " ); Vec_StrPrintStr( vStr, Bac_ObjNameStr(p, iTerm) ); Length += strlen(Bac_ObjNameStr(p, iTerm)); } Vec_StrPrintStr( vStr, ";\n" ); } Vec_StrPrintStr( vStr, "\n" ); // write objects Bac_ManWriteVerilogBoxes( p, fUseAssign ); Vec_StrPrintStr( vStr, "endmodule\n\n" ); } void Bac_ManWriteVerilog( char * pFileName, Bac_Man_t * p, int fUseAssign ) { Bac_Ntk_t * pNtk; int i; // check the library if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() ) { printf( "Genlib library used in the mapped design is not longer a current library.\n" ); return; } // derive the stream p->vOut = Vec_StrAlloc( 10000 ); p->vOut2 = Vec_StrAlloc( 1000 ); Vec_StrPrintStr( p->vOut, "// Design \"" ); Vec_StrPrintStr( p->vOut, Bac_ManName(p) ); Vec_StrPrintStr( p->vOut, "\" written via CBA package in ABC on " ); Vec_StrPrintStr( p->vOut, Extra_TimeStamp() ); Vec_StrPrintStr( p->vOut, "\n\n" ); Bac_ManAssignInternWordNames( p ); Bac_ManForEachNtk( p, pNtk, i ) Bac_ManWriteVerilogNtk( pNtk, fUseAssign ); // dump into file if ( p->vOut && Vec_StrSize(p->vOut) > 0 ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { fwrite( Vec_StrArray(p->vOut), 1, Vec_StrSize(p->vOut), pFile ); fclose( pFile ); } } Vec_StrFreeP( &p->vOut ); Vec_StrFreeP( &p->vOut2 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/bac/module.make000066400000000000000000000006671300674244400236300ustar00rootroot00000000000000SRC += src/base/bac/bacBlast.c \ src/base/bac/bacBac.c \ src/base/bac/bacCom.c \ src/base/bac/bacLib.c \ src/base/bac/bacNtk.c \ src/base/bac/bacPrsBuild.c \ src/base/bac/bacPrsTrans.c \ src/base/bac/bacPtr.c \ src/base/bac/bacPtrAbc.c \ src/base/bac/bacReadBlif.c \ src/base/bac/bacReadSmt.c \ src/base/bac/bacReadVer.c \ src/base/bac/bacWriteBlif.c \ src/base/bac/bacWriteSmt.c \ src/base/bac/bacWriteVer.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/000077500000000000000000000000001300674244400214735ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cba.c000066400000000000000000000026531300674244400223720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cba.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 21, 2015.] Revision [$Id: cba.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cba.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cba.h000066400000000000000000001775201300674244400224050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cba.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: cba.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__cba__cba_h #define ABC__base__cba__cba_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "misc/extra/extra.h" #include "misc/util/utilNam.h" #include "misc/vec/vecHash.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // network objects typedef enum { CBA_OBJ_NONE = 0, // 00: unused CBA_OBJ_PI, // 01: input CBA_OBJ_PO, // 02: output CBA_OBJ_BOX, // 03: box CBA_BOX_CF, // 04: CBA_BOX_CT, // 05: CBA_BOX_CX, // 06: CBA_BOX_CZ, // 07: CBA_BOX_BUF, // 08: CBA_BOX_INV, // 09: CBA_BOX_AND, // 10: CBA_BOX_NAND, // 11: CBA_BOX_OR, // 12: CBA_BOX_NOR, // 13: CBA_BOX_XOR, // 14: CBA_BOX_XNOR, // 15: CBA_BOX_SHARP, // 16: CBA_BOX_SHARPL, // 17: CBA_BOX_MUX, // 18: CBA_BOX_MAJ, // 19: CBA_BOX_ABC, // 20: CBA_BOX_BA, // 21: CBA_BOX_BO, // 22: CBA_BOX_BX, // 23: CBA_BOX_BN, // 24: CBA_BOX_BAO, // 25: CBA_BOX_BOA, // 26: CBA_BOX_RAND, // 27: CBA_BOX_RNAND, // 28: CBA_BOX_ROR, // 29: CBA_BOX_RNOR, // 30: CBA_BOX_RXOR, // 31: CBA_BOX_RXNOR, // 32: CBA_BOX_LNOT, // 33 CBA_BOX_LAND, // 34: CBA_BOX_LNAND, // 35: CBA_BOX_LOR, // 36: CBA_BOX_LNOR, // 37: CBA_BOX_LXOR, // 38: CBA_BOX_LXNOR, // 39: CBA_BOX_NMUX, // 40: CBA_BOX_SEL, // 41: CBA_BOX_PSEL, // 42: CBA_BOX_ENC, // 43: CBA_BOX_PENC, // 44: CBA_BOX_DEC, // 45: CBA_BOX_EDEC, // 46: CBA_BOX_ADD, // 47: CBA_BOX_SUB, // 48: CBA_BOX_MUL, // 49: CBA_BOX_SMUL, // 50: CBA_BOX_DIV, // 51: CBA_BOX_MOD, // 52: CBA_BOX_REM, // 53: CBA_BOX_POW, // 54: CBA_BOX_MIN, // 55: CBA_BOX_SQRT, // 56: CBA_BOX_ABS, // 57: CBA_BOX_SLTHAN, // 58: CBA_BOX_LTHAN, // 59: CBA_BOX_LETHAN, // 60: CBA_BOX_METHAN, // 61: CBA_BOX_MTHAN, // 62: CBA_BOX_EQU, // 63: CBA_BOX_NEQU, // 64: CBA_BOX_SHIL, // 65: CBA_BOX_SHIR, // 66: CBA_BOX_SHILA, // 67: CBA_BOX_SHIRA, // 68: CBA_BOX_ROTL, // 69: CBA_BOX_ROTR, // 70: CBA_BOX_NODE, // 71: CBA_BOX_LUT, // 72: CBA_BOX_GATE, // 73: CBA_BOX_TABLE, // 74: CBA_BOX_TRI, // 75: CBA_BOX_RAM, // 76: CBA_BOX_RAMR, // 77: CBA_BOX_RAMW, // 78: CBA_BOX_RAMWC, // 79: CBA_BOX_RAML, // 80: CBA_BOX_RAMS, // 81: CBA_BOX_RAMBOX, // 82: CBA_BOX_LATCH, // 83: CBA_BOX_LATCHRS, // 84: CBA_BOX_DFF, // 85: CBA_BOX_DFFCPL, // 86: CBA_BOX_DFFRS, // 87: CBA_BOX_SLICE, // 88: CBA_BOX_CONCAT, // 89: CBA_BOX_LAST // 90 } Cba_ObjType_t; typedef struct Cba_Ntk_t_ Cba_Ntk_t; typedef struct Cba_Man_t_ Cba_Man_t; // network struct Cba_Ntk_t_ { Cba_Man_t * pDesign; // design int Id; // network ID int NameId; // name ID int iCopy; // copy module unsigned Mark : 1; // visit mark unsigned fComb: 1; // the network is combinational unsigned fSeq : 1; // the network is sequential // interface Vec_Int_t vInputs; // inputs Vec_Int_t vOutputs; // outputs Vec_Int_t vOrder; // order Vec_Int_t vSeq; // sequential objects // stucture Vec_Str_t vObjType; // type Vec_Int_t vObjFin0; // fanins Vec_Int_t vObjFon0; // outputs Vec_Int_t vFinFon; // fons Vec_Int_t vFonObj; // object // optional Vec_Int_t vObjCopy; // copy Vec_Int_t vObjFunc; // function Vec_Int_t vObjName; // name Vec_Int_t vObjAttr; // attribute offset Vec_Int_t vAttrSto; // attribute storage Vec_Int_t vFonCopy; // copy Vec_Int_t vFonName; // name Vec_Int_t vFonRange;// range Vec_Int_t vFonPrev; // fanout: prev fon Vec_Int_t vFonNext; // fanout: next fon Vec_Int_t vFinFon0; // fanout: first fon Vec_Int_t vFinObj; // object Vec_Int_t vNtkObjs; // instances Vec_Int_t vFonBits; // fon mapping into AIG nodes // other Vec_Ptr_t * vOther; // various data Vec_Int_t vArray0; Vec_Int_t vArray1; }; // design struct Cba_Man_t_ { // design names char * pName; // design name char * pSpec; // spec file name Abc_Nam_t * pStrs; // string manager Abc_Nam_t * pFuns; // constant manager Abc_Nam_t * pMods; // module name manager Hash_IntMan_t * vHash; // variable ranges Vec_Int_t vNameMap; // mapping names Vec_Int_t vNameMap2;// mapping names Vec_Int_t vUsed; // used map entries Vec_Int_t vUsed2; // used map entries char * pTypeNames[CBA_BOX_LAST]; int nObjs[CBA_BOX_LAST]; // counter of objects of each type int nAnds[CBA_BOX_LAST]; // counter of AND gates after blasting // internal data int iRoot; // root network Vec_Ptr_t vNtks; // networks // user data int nOpens; Vec_Str_t vOut; Vec_Str_t vOut2; void * pMioLib; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline char * Cba_ManName( Cba_Man_t * p ) { return p->pName; } static inline char * Cba_ManSpec( Cba_Man_t * p ) { return p->pSpec; } static inline int Cba_ManNtkNum( Cba_Man_t * p ) { return Vec_PtrSize(&p->vNtks)-1; } static inline int Cba_ManNtkIsOk( Cba_Man_t * p, int i ) { return i > 0 && i <= Cba_ManNtkNum(p); } static inline Cba_Ntk_t * Cba_ManNtk( Cba_Man_t * p, int i ) { return Cba_ManNtkIsOk(p, i) ? (Cba_Ntk_t *)Vec_PtrEntry(&p->vNtks, i) : NULL; } static inline int Cba_ManNtkFindId( Cba_Man_t * p, char * pName ) { return Abc_NamStrFind(p->pMods, pName); } static inline Cba_Ntk_t * Cba_ManNtkFind( Cba_Man_t * p, char * pName ) { return Cba_ManNtk( p, Cba_ManNtkFindId(p, pName) ); } static inline Cba_Ntk_t * Cba_ManRoot( Cba_Man_t * p ) { return Cba_ManNtk(p, p->iRoot); } static inline char * Cba_ManStr( Cba_Man_t * p, int i ) { return Abc_NamStr(p->pStrs, i); } static inline int Cba_ManStrId( Cba_Man_t * p, char * pStr ) { return Abc_NamStrFind(p->pStrs, pStr); } static inline int Cba_ManNameIdMax( Cba_Man_t * p ) { return Abc_NamObjNumMax(p->pStrs) + 1; } static inline char * Cba_ManConst( Cba_Man_t * p, int i ) { return Abc_NamStr(p->pFuns, i); } static inline int Cba_ManConstId( Cba_Man_t * p, char * pStr ) { return Abc_NamStrFind(p->pFuns, pStr); } static inline int Cba_ManConstIdMax( Cba_Man_t * p ) { return Abc_NamObjNumMax(p->pFuns) + 1; } static inline Cba_Man_t * Cba_NtkMan( Cba_Ntk_t * p ) { return p->pDesign; } static inline Cba_Ntk_t * Cba_NtkNtk( Cba_Ntk_t * p, int i ) { return Cba_ManNtk(p->pDesign, i); } static inline int Cba_NtkId( Cba_Ntk_t * p ) { return p->Id; } static inline int Cba_NtkPi( Cba_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vInputs, i); } static inline int Cba_NtkPo( Cba_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vOutputs, i); } static inline int Cba_NtkPioOrder( Cba_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vOrder, i); } static inline int Cba_NtkBoxSeq( Cba_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vSeq, i); } static inline Abc_Nam_t * Cba_NtkNam( Cba_Ntk_t * p ) { return p->pDesign->pStrs; } static inline char * Cba_NtkStr( Cba_Ntk_t * p, int i ) { return Cba_ManStr(p->pDesign, i); } static inline int Cba_NtkStrId( Cba_Ntk_t * p, char * pName ) { return Cba_ManStrId(p->pDesign, pName); } static inline char * Cba_NtkConst( Cba_Ntk_t * p, int i ) { return Cba_ManConst(p->pDesign, i); } static inline char * Cba_NtkSop( Cba_Ntk_t * p, int i ) { return Cba_ManConst(p->pDesign, i); } static inline int Cba_NtkNameId( Cba_Ntk_t * p ) { return p->NameId; } static inline char * Cba_NtkName( Cba_Ntk_t * p ) { return Cba_NtkStr(p, p->NameId); } static inline char * Cba_NtkTypeName( Cba_Ntk_t * p, int Type ) { return p->pDesign->pTypeNames[Type]; } static inline int Cba_NtkCopy( Cba_Ntk_t * p ) { return p->iCopy; } static inline Cba_Ntk_t * Cba_NtkCopyNtk(Cba_Man_t * pNew, Cba_Ntk_t * p) { return Cba_ManNtk(pNew, Cba_NtkCopy(p)); } static inline void Cba_NtkSetCopy( Cba_Ntk_t * p, int i ) { assert(p->iCopy == 0); p->iCopy = i; } static inline int Cba_NtkHashRange( Cba_Ntk_t * p, int l, int r ) { return Hash_Int2ManInsert( p->pDesign->vHash, l, r, 0 ); } static inline int Cba_NtkRangeLeft( Cba_Ntk_t * p, int h ) { return h ? Hash_IntObjData0( p->pDesign->vHash, h ) : 0; } static inline int Cba_NtkRangeRight( Cba_Ntk_t * p, int h ) { return h ? Hash_IntObjData1( p->pDesign->vHash, h ) : 0; } static inline int Cba_NtkRangeSize( Cba_Ntk_t * p, int h ) { int l = Cba_NtkRangeLeft(p, h), r = Cba_NtkRangeRight(p, h); return 1 + (l > r ? l-r : r-l);} static inline int Cba_NtkPiNum( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vInputs); } static inline int Cba_NtkPoNum( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vOutputs); } static inline int Cba_NtkPioNum( Cba_Ntk_t * p ) { return Cba_NtkPiNum(p) + Cba_NtkPoNum(p); } static inline int Cba_NtkPiNumAlloc( Cba_Ntk_t * p ) { return Vec_IntCap(&p->vInputs); } static inline int Cba_NtkPoNumAlloc( Cba_Ntk_t * p ) { return Vec_IntCap(&p->vOutputs); } static inline int Cba_NtkPioOrderNum( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vOrder); } static inline int Cba_NtkObjNum( Cba_Ntk_t * p ) { return Vec_StrSize(&p->vObjType)-1; } static inline int Cba_NtkObjNumAlloc( Cba_Ntk_t * p ) { return Vec_StrCap(&p->vObjType)-1; } static inline int Cba_NtkFinNum( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFinFon)-1; } static inline int Cba_NtkFinNumAlloc( Cba_Ntk_t * p ) { return Vec_IntCap(&p->vFinFon)-1; } static inline int Cba_NtkFonNum( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFonObj)-1; } static inline int Cba_NtkFonNumAlloc( Cba_Ntk_t * p ) { return Vec_IntCap(&p->vFonObj)-1; } static inline int Cba_NtkTypeNum( Cba_Ntk_t * p, int Type ) { return Vec_StrCountEntry(&p->vObjType, (char)Type); } static inline int Cba_NtkBoxNum( Cba_Ntk_t * p ) { return Cba_NtkObjNum(p) - Cba_NtkPioNum(p); } static inline int Cba_NtkBoxUserNum( Cba_Ntk_t * p ) { return Cba_NtkTypeNum(p, CBA_OBJ_BOX); } static inline int Cba_NtkBoxPrimNum( Cba_Ntk_t * p ) { return Vec_StrCountLarger(&p->vObjType, (char)CBA_OBJ_BOX); } static inline int Cba_NtkBoxSeqNum( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vSeq); } static inline void Cba_NtkCleanObjCopies( Cba_Ntk_t * p ) { Vec_IntFill(&p->vObjCopy, Vec_StrCap(&p->vObjType), -1); } static inline void Cba_NtkCleanObjFuncs( Cba_Ntk_t * p ) { Vec_IntFill(&p->vObjFunc, Vec_StrCap(&p->vObjType), 0); } static inline void Cba_NtkCleanObjNames( Cba_Ntk_t * p ) { Vec_IntFill(&p->vObjName, Vec_StrCap(&p->vObjType), 0); } static inline void Cba_NtkCleanObjAttrs( Cba_Ntk_t * p ) { Vec_IntFill(&p->vObjAttr, Vec_StrCap(&p->vObjType), 0); Vec_IntFill(&p->vAttrSto, 1, -1); } static inline void Cba_NtkCleanFonCopies( Cba_Ntk_t * p ) { Vec_IntFill(&p->vFonCopy, Vec_IntCap(&p->vFonObj), 0); } static inline void Cba_NtkCleanFonNames( Cba_Ntk_t * p ) { Vec_IntFill(&p->vFonName, Vec_IntCap(&p->vFonObj), 0); } static inline void Cba_NtkCleanFonRanges( Cba_Ntk_t * p ) { Vec_IntFill(&p->vFonRange, Vec_IntCap(&p->vFonObj), 0); } static inline void Cba_NtkCleanFonPrevs( Cba_Ntk_t * p ) { Vec_IntFill(&p->vFonPrev, Vec_IntCap(&p->vFonObj), 0); } static inline void Cba_NtkCleanFonNexts( Cba_Ntk_t * p ) { Vec_IntFill(&p->vFonNext, Vec_IntCap(&p->vFonObj), 0); } static inline void Cba_NtkCleanFinFon0( Cba_Ntk_t * p ) { Vec_IntFill(&p->vFinFon0, Vec_IntCap(&p->vFinFon), 0); } static inline void Cba_NtkCleanFinObjs( Cba_Ntk_t * p ) { Vec_IntFill(&p->vFinObj, Vec_IntCap(&p->vFinFon), 0); } static inline int Cba_NtkHasObjCopies( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vObjCopy) > 0; } static inline int Cba_NtkHasObjFuncs( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vObjFunc) > 0; } static inline int Cba_NtkHasObjNames( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vObjName) > 0; } static inline int Cba_NtkHasObjAttrs( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vObjAttr) > 0; } static inline int Cba_NtkHasFonCopies( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFonCopy) > 0; } static inline int Cba_NtkHasFonNames( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFonName) > 0; } static inline int Cba_NtkHasFonRanges( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFonRange) > 0; } static inline int Cba_NtkHasFonPrevs( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFonPrev) > 0; } static inline int Cba_NtkHasFonNexts( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFonNext) > 0; } static inline int Cba_NtkHasFinFon0( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFinFon0) > 0; } static inline int Cba_NtkHasFinObjs( Cba_Ntk_t * p ) { return Vec_IntSize(&p->vFinObj) > 0; } static inline void Cba_NtkFreeObjCopies( Cba_Ntk_t * p ) { Vec_IntErase(&p->vObjCopy); } static inline void Cba_NtkFreeObjFuncs( Cba_Ntk_t * p ) { Vec_IntErase(&p->vObjFunc); } static inline void Cba_NtkFreeObjNames( Cba_Ntk_t * p ) { Vec_IntErase(&p->vObjName); } static inline void Cba_NtkFreeObjAttrs( Cba_Ntk_t * p ) { Vec_IntErase(&p->vObjAttr); } static inline void Cba_NtkFreeFonCopies( Cba_Ntk_t * p ) { Vec_IntErase(&p->vFonCopy); } static inline void Cba_NtkFreeFonNames( Cba_Ntk_t * p ) { Vec_IntErase(&p->vFonName); } static inline void Cba_NtkFreeFonRanges( Cba_Ntk_t * p ) { Vec_IntErase(&p->vFonRange); } static inline void Cba_NtkFreeFonPrevs( Cba_Ntk_t * p ) { Vec_IntErase(&p->vFonPrev); } static inline void Cba_NtkFreeFonNexts( Cba_Ntk_t * p ) { Vec_IntErase(&p->vFonNext); } static inline void Cba_NtkFreeFinFon0( Cba_Ntk_t * p ) { Vec_IntErase(&p->vFinFon0); } static inline void Cba_NtkFreeFinObjs( Cba_Ntk_t * p ) { Vec_IntErase(&p->vFinObj); } static inline Cba_ObjType_t Cba_ObjType( Cba_Ntk_t * p, int i ) { assert(i>0); return (Cba_ObjType_t)(int)(unsigned char)Vec_StrEntry(&p->vObjType, i); } static inline void Cba_ObjCleanType( Cba_Ntk_t * p, int i ) { assert(i>0); Vec_StrWriteEntry( &p->vObjType, i, (char)CBA_OBJ_NONE ); } static inline int Cba_TypeIsBox( Cba_ObjType_t Type ) { return Type >= CBA_OBJ_BOX && Type < CBA_BOX_LAST; } static inline int Cba_TypeIsSeq( Cba_ObjType_t Type ) { return Type >= CBA_BOX_RAM && Type <= CBA_BOX_DFFRS; } static inline int Cba_TypeIsUnary( Cba_ObjType_t Type ) { return Type == CBA_BOX_BUF || Type == CBA_BOX_INV || Type == CBA_BOX_LNOT || Type == CBA_BOX_MIN || Type == CBA_BOX_SQRT || Type == CBA_BOX_ABS || (Type >= CBA_BOX_RAND && Type <= CBA_BOX_RXNOR); } static inline int Cba_TypeIsMux( Cba_ObjType_t Type ) { return Type == CBA_BOX_MUX || Type == CBA_BOX_NMUX || Type == CBA_BOX_SEL || Type == CBA_BOX_PSEL; } static inline int Cba_ObjIsPi( Cba_Ntk_t * p, int i ) { return Cba_ObjType(p, i) == CBA_OBJ_PI; } static inline int Cba_ObjIsPo( Cba_Ntk_t * p, int i ) { return Cba_ObjType(p, i) == CBA_OBJ_PO; } static inline int Cba_ObjIsPio( Cba_Ntk_t * p, int i ) { return Cba_ObjIsPi(p, i) || Cba_ObjIsPo(p, i); } static inline int Cba_ObjIsBox( Cba_Ntk_t * p, int i ) { return Cba_TypeIsBox(Cba_ObjType(p, i)); } static inline int Cba_ObjIsBoxUser( Cba_Ntk_t * p, int i ) { return Cba_ObjType(p, i) == CBA_OBJ_BOX; } static inline int Cba_ObjIsBoxPrim( Cba_Ntk_t * p, int i ) { return Cba_ObjType(p, i) > CBA_OBJ_BOX && Cba_ObjType(p, i) < CBA_BOX_LAST; } static inline int Cba_ObjIsGate( Cba_Ntk_t * p, int i ) { return Cba_ObjType(p, i) == CBA_BOX_GATE; } static inline int Cba_ObjIsSlice( Cba_Ntk_t * p, int i ) { return Cba_ObjType(p, i) == CBA_BOX_SLICE; } static inline int Cba_ObjIsConcat( Cba_Ntk_t * p, int i ) { return Cba_ObjType(p, i) == CBA_BOX_CONCAT; } static inline int Cba_ObjIsUnary( Cba_Ntk_t * p, int i ) { return Cba_TypeIsUnary(Cba_ObjType(p, i)); } static inline int Cba_ObjFin0( Cba_Ntk_t * p, int i ) { assert(i>0); return Vec_IntEntry(&p->vObjFin0, i); } static inline int Cba_ObjFon0( Cba_Ntk_t * p, int i ) { assert(i>0); return Vec_IntEntry(&p->vObjFon0, i); } static inline int Cba_ObjFin( Cba_Ntk_t * p, int i, int k ) { assert(i>0); return Cba_ObjFin0(p, i) + k; } static inline int Cba_ObjFon( Cba_Ntk_t * p, int i, int k ) { assert(i>0); return Cba_ObjFon0(p, i) + k; } static inline int Cba_ObjFinNum( Cba_Ntk_t * p, int i ) { assert(i>0); return Cba_ObjFin0(p, i+1) - Cba_ObjFin0(p, i); } static inline int Cba_ObjFonNum( Cba_Ntk_t * p, int i ) { assert(i>0); return Cba_ObjFon0(p, i+1) - Cba_ObjFon0(p, i); } static inline int Cba_ObjCopy( Cba_Ntk_t * p, int i ) { assert(i>0); assert( Cba_NtkHasObjCopies(p) ); return Vec_IntGetEntryFull(&p->vObjCopy, i); } static inline int Cba_ObjFunc( Cba_Ntk_t * p, int i ) { assert(i>0); assert( Cba_NtkHasObjFuncs(p) ); return Vec_IntGetEntry(&p->vObjFunc, i); } static inline int Cba_ObjName( Cba_Ntk_t * p, int i ) { assert(i>0); assert( Cba_NtkHasObjNames(p) ); return Vec_IntGetEntry(&p->vObjName, i); } static inline char * Cba_ObjNameStr( Cba_Ntk_t * p, int i ) { assert(i>0); return Cba_NtkStr(p, Cba_ObjName(p, i)); } static inline int Cba_ObjAttr( Cba_Ntk_t * p, int i ) { assert(i>=0); return Cba_NtkHasObjAttrs(p) ? Vec_IntGetEntry(&p->vObjAttr, i) : 0; } static inline int Cba_ObjAttrSize( Cba_Ntk_t * p, int i ) { assert(i>=0); return Cba_ObjAttr(p, i) ? Vec_IntEntry(&p->vAttrSto, Cba_ObjAttr(p, i)) : 0; } static inline int * Cba_ObjAttrArray( Cba_Ntk_t * p, int i ) { assert(i>=0); return Cba_ObjAttr(p, i) ? Vec_IntEntryP(&p->vAttrSto, Cba_ObjAttr(p, i)+1) : NULL; } static inline int Cba_ObjAttrValue( Cba_Ntk_t * p, int i, int x ) { int k, s = Cba_ObjAttrSize(p, i), * a = Cba_ObjAttrArray(p, i); for ( k = 0; k < s; k += 2) if (a[k] == x) return a[k+1]; return 0; } static inline void Cba_ObjSetCopy( Cba_Ntk_t * p, int i, int x ) { assert(Cba_ObjCopy(p, i) == -1); Vec_IntSetEntry( &p->vObjCopy, i, x ); } static inline void Cba_ObjSetFunc( Cba_Ntk_t * p, int i, int x ) { assert(Cba_ObjFunc(p, i) == 0); Vec_IntSetEntry( &p->vObjFunc, i, x ); } static inline void Cba_ObjSetName( Cba_Ntk_t * p, int i, int x ) { assert(Cba_ObjName(p, i) == 0); Vec_IntSetEntry( &p->vObjName, i, x ); } static inline void Cba_ObjSetAttrs( Cba_Ntk_t * p, int i, int * a, int s ) { assert(Cba_ObjAttr(p, i) == 0); if ( !a ) return; Vec_IntSetEntry(&p->vObjAttr, i, Vec_IntSize(&p->vAttrSto)); Vec_IntPush(&p->vAttrSto, s); Vec_IntPushArray(&p->vAttrSto, a, s); } static inline int Cba_FinFon( Cba_Ntk_t * p, int f ) { assert(f>0); return Vec_IntEntry(&p->vFinFon, f); } static inline void Cba_PatchFinFon( Cba_Ntk_t * p, int f, int x ) { assert(f>0); Vec_IntWriteEntry(&p->vFinFon, f, x); } static inline int Cba_ObjFinFon( Cba_Ntk_t * p, int i, int k ) { assert(i>0); return Cba_FinFon(p, Cba_ObjFin(p, i, k)); } static inline int * Cba_ObjFinFons( Cba_Ntk_t * p, int i ) { assert(i>0); return Vec_IntEntryP(&p->vFinFon, Cba_ObjFin0(p, i)); } static inline void Cba_ObjSetFinFon( Cba_Ntk_t * p, int i, int k, int x ) { assert(i>0); assert(Cba_ObjFinFon(p, i, k)== 0); Vec_IntWriteEntry(&p->vFinFon, Cba_ObjFin(p, i, k), x); } static inline void Cba_ObjCleanFinFon( Cba_Ntk_t * p, int i, int k) { assert(i>0); assert(Cba_ObjFinFon(p, i, k)!= 0); Vec_IntWriteEntry(&p->vFinFon, Cba_ObjFin(p, i, k), 0); } static inline void Cba_ObjPatchFinFon( Cba_Ntk_t * p, int i, int k, int x){ assert(i>0); Cba_ObjCleanFinFon(p, i, k); Cba_ObjSetFinFon(p, i, k, x); } static inline int Cba_ObjNtkId( Cba_Ntk_t * p, int i ) { assert(i>0); return (Cba_ObjIsBoxUser(p, i) && Cba_NtkHasObjFuncs(p)) ? Cba_ObjFunc(p, i) : 0;} static inline Cba_Ntk_t * Cba_ObjNtk( Cba_Ntk_t * p, int i ) { assert(i>0); return Cba_NtkNtk(p, Cba_ObjNtkId(p, i)); } static inline void Cba_ObjSetNtkId( Cba_Ntk_t * p, int i, int x ) { assert(i>0); assert(Cba_ObjIsBoxUser(p, i)); Cba_ObjSetFunc( p, i, x ); } static inline int Cba_ObjIsSeq( Cba_Ntk_t * p, int i ) { assert(i>0); return Cba_ObjIsBoxUser(p, i) ? Cba_ObjNtk(p, i)->fSeq : Cba_TypeIsSeq(Cba_ObjType(p, i)); } static inline int Cba_FonIsReal( int f ) { return f > 0; } static inline int Cba_FonIsConst( int f ) { return f < 0; } static inline int Cba_FonConst( int f ) { assert(Cba_FonIsConst(f)); return -f-1; } static inline int Cba_FonFromConst( int c ) { assert(c >= 0); return -c-1; } static inline int Cba_FonConstRangeSize( Cba_Ntk_t * p, int f ) { assert(Cba_FonIsConst(f)); return atoi(Cba_NtkConst(p, Cba_FonConst(f))); } static inline int Cba_FonConstSigned( Cba_Ntk_t * p, int f ) { assert(Cba_FonIsConst(f)); return strchr(Cba_NtkConst(p, Cba_FonConst(f)), 's') != NULL; } static inline int Cba_FonObj( Cba_Ntk_t * p, int f ) { return Cba_FonIsReal(f) ? Vec_IntEntry(&p->vFonObj, f) : 0; } static inline int Cba_FonRangeId( Cba_Ntk_t * p, int f ) { assert(Cba_FonIsReal(f)); return Cba_NtkHasFonRanges(p)?Vec_IntGetEntry(&p->vFonRange, f):0;} static inline int Cba_FonRange( Cba_Ntk_t * p, int f ) { assert(Cba_FonIsReal(f)); return Abc_Lit2Var( Cba_FonRangeId(p, f) ); } static inline int Cba_FonLeft( Cba_Ntk_t * p, int f ) { return Cba_NtkRangeLeft(p, Cba_FonRange(p, f)); } static inline int Cba_FonRight( Cba_Ntk_t * p, int f ) { return Cba_NtkRangeRight(p, Cba_FonRange(p, f)); } static inline int Cba_FonSigned( Cba_Ntk_t * p, int f ) { return Cba_FonIsConst(f) ? Cba_FonConstSigned(p, f) : Abc_LitIsCompl(Cba_FonRangeId(p, f)); } static inline int Cba_FonRangeSize( Cba_Ntk_t * p, int f ) { return Cba_FonIsConst(f) ? Cba_FonConstRangeSize(p, f):Cba_NtkRangeSize(p, Cba_FonRange(p, f)); } static inline void Cba_FonSetRangeSign( Cba_Ntk_t * p, int f, int x ) { assert(Cba_NtkHasFonRanges(p)); Vec_IntSetEntry(&p->vFonRange, f, x); } static inline void Cba_FonSetRange( Cba_Ntk_t * p, int f, int x ) { assert(Cba_NtkHasFonRanges(p)); Vec_IntSetEntry(&p->vFonRange, f, Abc_Var2Lit(x,0)); } static inline void Cba_FonHashRange( Cba_Ntk_t * p, int f, int l, int r ) { Cba_FonSetRange( p, f, Cba_NtkHashRange(p, l, r) ); } static inline int Cba_FonCopy( Cba_Ntk_t * p, int f ) { return Cba_FonIsReal(f) ? Vec_IntEntry(&p->vFonCopy, f) : f; } static inline void Cba_FonSetCopy( Cba_Ntk_t * p, int f, int x ) { assert(Cba_FonIsReal(f)); assert(Cba_FonCopy(p, f) == 0); Vec_IntWriteEntry(&p->vFonCopy, f, x); } static inline int Cba_FonName( Cba_Ntk_t * p, int f ) { assert(Cba_NtkHasFonNames(p)); assert(Cba_FonIsReal(f)); return Vec_IntGetEntry( &p->vFonName, f ); } static inline char * Cba_FonNameStr( Cba_Ntk_t * p, int f ) { assert(Cba_NtkHasFonNames(p)); assert(Cba_FonIsReal(f)); return Cba_NtkStr(p, Cba_FonName(p, f)); } static inline void Cba_FonSetName( Cba_Ntk_t * p, int f, int x ) { assert(Cba_NtkHasFonNames(p)); assert(Cba_FonIsReal(f)); assert(Cba_FonName(p, f) == 0); Vec_IntSetEntry(&p->vFonName, f, x); } static inline void Cba_FonCleanName( Cba_Ntk_t * p, int f ) { assert(Cba_NtkHasFonNames(p)); assert(Cba_FonIsReal(f)); assert(Cba_FonName(p, f) != 0); Vec_IntSetEntry(&p->vFonName, f, 0); } static inline void Cba_FonPatchName( Cba_Ntk_t * p, int f, int x) { assert(Cba_NtkHasFonNames(p)); assert(Cba_FonIsReal(f)); Cba_FonCleanName(p, f); Cba_FonSetName(p, f, x); } static inline int Cba_FonIndex( Cba_Ntk_t * p, int f ) { assert(Cba_FonIsReal(f)); return f - Cba_ObjFon0( p, Cba_FonObj(p, f) ); } static inline int Cba_FonNtkId( Cba_Ntk_t * p, int f ) { assert(Cba_FonIsReal(f)); return Cba_ObjNtkId( p, Cba_FonObj(p, f) ); } static inline Cba_Ntk_t * Cba_FonNtk( Cba_Ntk_t * p, int f ) { assert(Cba_FonIsReal(f)); return Cba_ObjNtk( p, Cba_FonObj(p, f) ); } static inline int Cba_ObjFanin( Cba_Ntk_t * p, int i, int k ) { assert(i>0); return Cba_FonObj( p, Cba_ObjFinFon(p, i, k) ); } static inline int Cba_ObjLeft( Cba_Ntk_t * p, int i ) { return Cba_FonLeft( p, Cba_ObjFon0(p, i) ); } static inline int Cba_ObjRight( Cba_Ntk_t * p, int i ) { return Cba_FonRight( p, Cba_ObjFon0(p, i) ); } static inline int Cba_ObjRangeSize( Cba_Ntk_t * p, int i ) { return Cba_FonRangeSize( p, Cba_ObjFon0(p, i) ); } static inline int Cba_ObjSigned( Cba_Ntk_t * p, int i ) { return Cba_FonSigned( p, Cba_ObjFon0(p, i) ); } static inline int Cba_ObjSign( Cba_Ntk_t * p, int i ) { return Abc_Var2Lit( Cba_FonRangeSize(p, i), Cba_ObjSigned(p, i) ); } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// #define Cba_ManForEachNtk( p, pNtk, i ) \ for ( i = 1; (i <= Cba_ManNtkNum(p)) && (((pNtk) = Cba_ManNtk(p, i)), 1); i++ ) #define Cba_NtkForEachPi( p, iObj, i ) \ for ( i = 0; (i < Cba_NtkPiNum(p)) && (((iObj) = Cba_NtkPi(p, i)), 1); i++ ) #define Cba_NtkForEachPo( p, iObj, i ) \ for ( i = 0; (i < Cba_NtkPoNum(p)) && (((iObj) = Cba_NtkPo(p, i)), 1); i++ ) #define Cba_NtkForEachBoxSeq( p, iObj, i ) \ for ( i = 0; (i < Cba_NtkBoxSeqNum(p)) && (((iObj) = Cba_NtkBoxSeq(p, i)), 1); i++ ) #define Cba_NtkForEachPioOrder( p, iObj, i ) \ for ( i = 0; (i < Cba_NtkPioOrderNum(p)) && (((iObj) = Cba_NtkPioOrder(p, i)), 1); i++ ) #define Cba_NtkForEachPiFon( p, iObj, iFon, i ) \ for ( i = 0; (i < Cba_NtkPiNum(p)) && (((iObj) = Cba_NtkPi(p, i)), 1) && (((iFon) = Cba_ObjFon0(p, iObj)), 1); i++ ) #define Cba_NtkForEachPoDriverFon( p, iObj, iFon, i ) \ for ( i = 0; (i < Cba_NtkPoNum(p)) && (((iObj) = Cba_NtkPo(p, i)), 1) && (((iFon) = Cba_ObjFinFon(p, iObj, 0)), 1); i++ ) #define Cba_NtkForEachPoDriver( p, iObj, i ) \ for ( i = 0; (i < Cba_NtkPoNum(p)) && (((iObj) = Cba_ObjFanin(p, Cba_NtkPo(p, i), 0)), 1); i++ ) #define Cba_NtkForEachObj( p, i ) \ for ( i = 1; i < Vec_StrSize(&p->vObjType); i++ ) if ( !Cba_ObjType(p, i) ) {} else #define Cba_NtkForEachObjType( p, Type, i ) \ for ( i = 1; i < Vec_StrSize(&p->vObjType) && (((Type) = Cba_ObjType(p, i)), 1); i++ ) if ( !Type ) {} else #define Cba_NtkForEachBox( p, i ) \ for ( i = 1; i < Vec_StrSize(&p->vObjType); i++ ) if ( !Cba_ObjIsBox(p, i) ) {} else #define Cba_NtkForEachBoxComb( p, i ) \ for ( i = 1; i < Vec_StrSize(&p->vObjType); i++ ) if ( !Cba_ObjIsBox(p, i) || Cba_ObjIsSeq(p, i) ) {} else #define Cba_NtkForEachBoxUser( p, i ) \ for ( i = 1; i < Vec_StrSize(&p->vObjType); i++ ) if ( !Cba_ObjIsBoxUser(p, i) ) {} else #define Cba_NtkForEachBoxPrim( p, i ) \ for ( i = 1; i < Vec_StrSize(&p->vObjType); i++ ) if ( !Cba_ObjIsBoxPrim(p, i) ) {} else #define Cba_NtkForEachFon( p, i ) \ for ( i = 1; i < Vec_IntSize(&p->vFonObj); i++ ) #define Cba_NtkForEachFinFon( p, iFon, iFin ) \ for ( iFin = 1; iFin < Vec_IntSize(&p->vFinFon) && (((iFon) = Vec_IntEntry(&p->vFinFon, iFin)), 1); iFin++ ) if ( !iFon ) {} else #define Cba_NtkForEachFonName( p, NameId, iFon ) \ for ( iFon = 1; iFon < Vec_IntSize(&p->vFonName) && (((NameId) = Vec_IntEntry(&p->vFonName, iFon)), 1); iFon++ ) if ( !NameId ) {} else #define Cba_ObjForEachFin( p, iObj, iFin, k ) \ for ( k = 0, iFin = Cba_ObjFin0(p, iObj); iFin < Cba_ObjFin0(p, iObj+1); iFin++, k++ ) #define Cba_ObjForEachFon( p, iObj, iFon, k ) \ for ( k = 0, iFon = Cba_ObjFon0(p, iObj); iFon < Cba_ObjFon0(p, iObj+1); iFon++, k++ ) #define Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) \ for ( k = 0, iFin = Cba_ObjFin0(p, iObj); iFin < Cba_ObjFin0(p, iObj+1) && ((iFon = Cba_FinFon(p, iFin)), 1); iFin++, k++ ) #define Cba_ObjForEachFinFanin( p, iObj, iFin, iFanin, k ) \ for ( k = 0, iFin = Cba_ObjFin0(p, iObj); iFin < Cba_ObjFin0(p, iObj+1) && ((iFanin = Cba_FonObj(p, Cba_FinFon(p, iFin))), 1); iFin++, k++ ) #define Cba_ObjForEachFinFaninReal( p, iObj, iFin, iFanin, k ) \ for ( k = 0, iFin = Cba_ObjFin0(p, iObj); iFin < Cba_ObjFin0(p, iObj+1) && ((iFanin = Cba_FonObj(p, Cba_FinFon(p, iFin))), 1); iFin++, k++ ) if ( !iFanin ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Object APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cba_ObjAlloc( Cba_Ntk_t * p, Cba_ObjType_t Type, int nFins, int nFons ) { int i, iObj = Vec_StrSize(&p->vObjType); if ( Type == CBA_OBJ_PI ) Vec_IntPush( &p->vInputs, iObj ); else if ( Type == CBA_OBJ_PO ) Vec_IntPush( &p->vOutputs, iObj ); Vec_StrPush( &p->vObjType, (char)Type ); // add fins for ( i = 0; i < nFins; i++ ) Vec_IntPush( &p->vFinFon, 0 ); if ( Vec_IntSize(&p->vObjFin0) ) Vec_IntPush( &p->vObjFin0, Vec_IntSize(&p->vFinFon) ); // add fons for ( i = 0; i < nFons; i++ ) Vec_IntPush( &p->vFonObj, iObj ); if ( Vec_IntSize(&p->vObjFon0) ) Vec_IntPush( &p->vObjFon0, Vec_IntSize(&p->vFonObj) ); return iObj; } static inline int Cba_ObjDup( Cba_Ntk_t * pNew, Cba_Ntk_t * p, int i ) { int iObj = Cba_ObjAlloc( pNew, Cba_ObjType(p, i), Cba_ObjFinNum(p, i), Cba_ObjFonNum(p, i) ); Cba_ObjSetCopy( p, i, iObj ); return iObj; } static inline void Cba_ObjDelete( Cba_Ntk_t * p, int i ) { int k, iFin, iFon; Cba_ObjCleanType( p, i ); Cba_ObjForEachFin( p, i, iFin, k ) Vec_IntWriteEntry( &p->vFinFon, iFin, 0 ); Cba_ObjForEachFon( p, i, iFon, k ) Vec_IntWriteEntry( &p->vFonObj, iFon, 0 ); } /**Function************************************************************* Synopsis [Network APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cba_Ntk_t * Cba_NtkAlloc( Cba_Man_t * p, int NameId, int nIns, int nOuts, int nObjs, int nFins, int nFons ) { Cba_Ntk_t * pNew = ABC_CALLOC( Cba_Ntk_t, 1 ); assert( nIns >= 0 && nOuts >= 0 && nObjs >= 0 && nFins >= 0 && nFons >= 0 ); pNew->Id = Vec_PtrSize(&p->vNtks); Vec_PtrPush( &p->vNtks, pNew ); pNew->NameId = NameId; pNew->pDesign = p; Vec_IntGrow( &pNew->vInputs, nIns ); Vec_IntGrow( &pNew->vOutputs, nOuts ); Vec_StrGrow( &pNew->vObjType, nObjs+1 ); Vec_StrPush( &pNew->vObjType, (char)CBA_OBJ_NONE ); Vec_IntGrow( &pNew->vObjFin0, nObjs+2 ); Vec_IntPush( &pNew->vObjFin0, 0 ); Vec_IntPush( &pNew->vObjFin0, 1 ); Vec_IntGrow( &pNew->vObjFon0, nObjs+2 ); Vec_IntPush( &pNew->vObjFon0, 0 ); Vec_IntPush( &pNew->vObjFon0, 1 ); Vec_IntGrow( &pNew->vFinFon, nFins+1 ); Vec_IntPush( &pNew->vFinFon, 0 ); Vec_IntGrow( &pNew->vFonObj, nFons+1 ); Vec_IntPush( &pNew->vFonObj, 0 ); return pNew; } static inline void Cba_NtkFree( Cba_Ntk_t * p ) { // interface Vec_IntErase( &p->vInputs ); Vec_IntErase( &p->vOutputs ); Vec_IntErase( &p->vOrder ); Vec_IntErase( &p->vSeq ); // stucture Vec_StrErase( &p->vObjType ); Vec_IntErase( &p->vObjFin0 ); Vec_IntErase( &p->vObjFon0 ); Vec_IntErase( &p->vFinFon ); Vec_IntErase( &p->vFonObj ); // optional Vec_IntErase( &p->vObjCopy ); Vec_IntErase( &p->vObjFunc ); Vec_IntErase( &p->vObjName ); Vec_IntErase( &p->vObjAttr ); Vec_IntErase( &p->vAttrSto ); Vec_IntErase( &p->vFonCopy ); Vec_IntErase( &p->vFonName ); Vec_IntErase( &p->vFonRange ); Vec_IntErase( &p->vFonPrev ); Vec_IntErase( &p->vFonNext ); Vec_IntErase( &p->vFinFon0 ); Vec_IntErase( &p->vFinObj ); Vec_IntErase( &p->vNtkObjs ); Vec_IntErase( &p->vFonBits ); // other Vec_IntErase( &p->vArray0 ); Vec_IntErase( &p->vArray1 ); if ( p->vOther ) Vec_VecFree( (Vec_Vec_t *)p->vOther ); ABC_FREE( p ); } static inline int Cba_NtkNewStrId( Cba_Ntk_t * pNtk, const char * format, ... ) { Abc_Nam_t * p = Cba_NtkNam( pNtk ); Vec_Str_t * vBuf = Abc_NamBuffer( p ); int nAdded, nSize = 1000; va_list args; va_start( args, format ); Vec_StrGrow( vBuf, Vec_StrSize(vBuf) + nSize ); nAdded = vsnprintf( Vec_StrLimit(vBuf), nSize, format, args ); if ( nAdded > nSize ) { Vec_StrGrow( vBuf, Vec_StrSize(vBuf) + nAdded + nSize ); nSize = vsnprintf( Vec_StrLimit(vBuf), nAdded, format, args ); assert( nSize == nAdded ); } va_end( args ); return Abc_NamStrFindOrAddLim( p, Vec_StrLimit(vBuf), Vec_StrLimit(vBuf) + nAdded, NULL ); } static inline int Cba_ManNewConstId( Cba_Ntk_t * p, Vec_Str_t * vBits ) { Vec_Str_t * vOut = Abc_NamBuffer(Cba_NtkNam(p)); Vec_StrPrintF( vOut, "%d\'b%s", Vec_StrSize(vBits)-1, Vec_StrArray(vBits) ); return Abc_NamStrFindOrAdd(p->pDesign->pFuns, Vec_StrArray(vOut), NULL); } static inline int Cba_ManNewConstZero( Cba_Ntk_t * p, int nBits ) { Vec_Str_t * vOut = Abc_NamBuffer(Cba_NtkNam(p)); Vec_StrPrintF( vOut, "%d\'b%0s", nBits, "" ); return Abc_NamStrFindOrAdd(p->pDesign->pFuns, Vec_StrArray(vOut), NULL); } static inline void Cba_NtkAdd( Cba_Man_t * p, Cba_Ntk_t * pNtk ) { int fFound, NtkId = Abc_NamStrFindOrAdd( p->pMods, Cba_NtkName(pNtk), &fFound ); if ( fFound ) printf( "Network with name \"%s\" already exists.\n", Cba_NtkName(pNtk) ); else assert( NtkId == pNtk->Id ); } static inline void Cba_NtkUpdate( Cba_Man_t * p, Cba_Ntk_t * pNtk ) { int fFound, NtkId = Abc_NamStrFindOrAdd( p->pMods, Cba_NtkName(pNtk), &fFound ); if ( !fFound ) printf( "Network with name \"%s\" does not exist.\n", Cba_NtkName(pNtk) ); else { Cba_NtkFree( Cba_ManNtk(p, NtkId) ); Vec_PtrWriteEntry( &p->vNtks, NtkId, pNtk ); } } static inline Vec_Int_t * Cba_NtkCollect( Cba_Ntk_t * p ) { int iObj; Vec_Int_t * vObjs = Vec_IntAlloc( Cba_NtkObjNum(p) ); Cba_NtkForEachObj( p, iObj ) Vec_IntPush( vObjs, iObj ); return vObjs; } static inline int Cba_NtkIsSeq( Cba_Ntk_t * p ) { int iObj; if ( p->fSeq ) return 1; if ( p->fComb ) return 0; assert( !p->fSeq && !p->fComb ); Cba_NtkForEachBox( p, iObj ) if ( Cba_ObjIsBoxUser(p, iObj) ) { if ( Cba_NtkIsSeq( Cba_ObjNtk(p, iObj) ) ) { p->fSeq = 1; return 1; } } else if ( Cba_ObjIsSeq(p, iObj) ) { p->fSeq = 1; return 1; } p->fComb = 1; return 0; } static inline void Cba_NtkPrepareSeq( Cba_Ntk_t * p ) { int iObj; assert( Cba_NtkBoxSeqNum(p) == 0 ); if ( !Cba_NtkIsSeq(p) ) return; Cba_NtkForEachBox( p, iObj ) if ( Cba_ObjIsSeq(p, iObj) ) Vec_IntPush( &p->vSeq, iObj ); // Cba_NtkObjOrder( p, &p->vSeq, NULL ); } static inline void Cba_NtkCountParams( Cba_Ntk_t * p, Vec_Int_t * vObjs, int * nPis, int * nPos, int * nFins, int * nFons ) { int i, iObj; *nPis = *nPos = *nFins = *nFons = 0; Vec_IntForEachEntry( vObjs, iObj, i ) { *nPis += Cba_ObjIsPi(p, iObj); *nPos += Cba_ObjIsPo(p, iObj); *nFins += Cba_ObjFinNum(p, iObj); *nFons += Cba_ObjFonNum(p, iObj); } } static inline Cba_Ntk_t * Cba_NtkDup( Cba_Man_t * pMan, Cba_Ntk_t * p, Vec_Int_t * vObjs ) { Cba_Ntk_t * pNew; int i, k, iObj, iObjNew, iFin, iFon; int nPis, nPos, nFins, nFons; Cba_NtkCountParams( p, vObjs, &nPis, &nPos, &nFins, &nFons ); pNew = Cba_NtkAlloc( pMan, Cba_NtkNameId(p), nPis, nPos, Vec_IntSize(vObjs), nFins, nFons ); Cba_NtkCleanObjCopies( p ); Cba_NtkCleanFonCopies( p ); Vec_IntForEachEntry( vObjs, iObj, i ) { iObjNew = Cba_ObjDup( pNew, p, iObj ); Cba_ObjForEachFon( p, iObj, iFon, k ) Cba_FonSetCopy( p, iFon, Cba_ObjFon(pNew, iObjNew, k) ); } Vec_IntForEachEntry( vObjs, iObj, i ) { iObjNew = Cba_ObjCopy( p, iObj ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) Cba_ObjSetFinFon( pNew, iObjNew, k, Cba_FonCopy(p, iFon) ); } //Cba_NtkFreeObjCopies( p ); //Cba_NtkFreeFonCopies( p ); assert( Cba_NtkObjNum(pNew) == Cba_NtkObjNumAlloc(pNew) ); Cba_NtkSetCopy( p, Cba_NtkId(pNew) ); return pNew; } static inline Cba_Ntk_t * Cba_NtkDupOrder( Cba_Man_t * pMan, Cba_Ntk_t * p, Vec_Int_t*(* pFuncOrder)(Cba_Ntk_t*) ) { Cba_Ntk_t * pNew; Vec_Int_t * vObjs = pFuncOrder ? pFuncOrder(p) : Cba_NtkCollect(p); if ( vObjs == NULL ) return NULL; pNew = Cba_NtkDup( pMan, p, vObjs ); Vec_IntFree( vObjs ); //Cba_NtkPrepareSeq( pNew ); return pNew; } static inline void Cba_NtkDupAttrs( Cba_Ntk_t * pNew, Cba_Ntk_t * p ) { int i, iObj; assert( Vec_IntSize(&pNew->vOrder) == 0 ); Cba_NtkForEachPioOrder( p, iObj, i ) Vec_IntPush( &pNew->vOrder, Cba_ObjCopy(p, iObj) ); // Vec_IntRemapArray( &p->vObjCopy, &p->vOrder, &pNew->vOrder, Cba_NtkPioOrderNum(p) ); // Vec_IntRemapArray( &p->vObjCopy, &p->vSeq, &pNew->vSeq, Cba_NtkBoxSeqNum(p) ); // transfer object attributes Vec_IntRemapArray( &p->vObjCopy, &p->vObjFunc, &pNew->vObjFunc, Cba_NtkObjNum(pNew) + 1 ); Vec_IntRemapArray( &p->vObjCopy, &p->vObjName, &pNew->vObjName, Cba_NtkObjNum(pNew) + 1 ); Vec_IntRemapArray( &p->vObjCopy, &p->vObjAttr, &pNew->vObjAttr, Cba_NtkObjNum(pNew) + 1 ); // transfer fon attributes Vec_IntRemapArray( &p->vFonCopy, &p->vFonName, &pNew->vFonName, Cba_NtkFonNum(pNew) + 1 ); Vec_IntRemapArray( &p->vFonCopy, &p->vFonRange, &pNew->vFonRange, Cba_NtkFonNum(pNew) + 1 ); // duplicate attributes Vec_IntAppend( &pNew->vAttrSto, &p->vAttrSto ); pNew->vOther = p->vOther ? (Vec_Ptr_t *)Vec_VecDup( (Vec_Vec_t *)p->vOther ) : NULL; } static inline int Cba_NtkMemory( Cba_Ntk_t * p ) { int nMem = sizeof(Cba_Ntk_t); // interface nMem += (int)Vec_IntMemory(&p->vInputs); nMem += (int)Vec_IntMemory(&p->vOutputs); nMem += (int)Vec_IntMemory(&p->vOrder); nMem += (int)Vec_IntMemory(&p->vSeq); // stucture nMem += (int)Vec_StrMemory(&p->vObjType); nMem += (int)Vec_IntMemory(&p->vObjFin0); nMem += (int)Vec_IntMemory(&p->vObjFon0); nMem += (int)Vec_IntMemory(&p->vFinFon); nMem += (int)Vec_IntMemory(&p->vFonObj); // optional nMem += (int)Vec_IntMemory(&p->vObjCopy ); nMem += (int)Vec_IntMemory(&p->vObjFunc ); nMem += (int)Vec_IntMemory(&p->vObjName ); nMem += (int)Vec_IntMemory(&p->vObjAttr ); nMem += (int)Vec_IntMemory(&p->vAttrSto ); nMem += (int)Vec_IntMemory(&p->vFonCopy ); nMem += (int)Vec_IntMemory(&p->vFonName ); nMem += (int)Vec_IntMemory(&p->vFonRange ); nMem += (int)Vec_IntMemory(&p->vFonPrev ); nMem += (int)Vec_IntMemory(&p->vFonNext ); nMem += (int)Vec_IntMemory(&p->vFinFon0 ); nMem += (int)Vec_IntMemory(&p->vFinObj ); nMem += (int)Vec_IntMemory(&p->vNtkObjs ); nMem += (int)Vec_IntMemory(&p->vFonBits ); // other nMem += (int)Vec_IntMemory(&p->vArray1 ); nMem += (int)Vec_IntMemory(&p->vArray1 ); return nMem; } static inline void Cba_NtkPrintStats( Cba_Ntk_t * p ) { printf( "pi =%5d ", Cba_NtkPiNum(p) ); printf( "po =%5d ", Cba_NtkPoNum(p) ); printf( "seq =%5d ", Cba_NtkBoxSeqNum(p) ); printf( "box =%5d ", Cba_NtkBoxNum(p) ); printf( "prim =%5d ", Cba_NtkBoxPrimNum(p) ); printf( "user =%5d ", Cba_NtkBoxUserNum(p) ); //printf( "topo =%4s ", Cba_NtkIsTopoOrder(p) ? "yes" : "no" ); printf( " %s ", Cba_NtkName(p) ); if ( Vec_IntSize(&p->vNtkObjs) ) printf( "-> %s", Cba_NtkName(Cba_NtkNtk(p, Vec_IntEntry(&p->vNtkObjs, 0))) ); printf( "\n" ); // Vec_StrIntPrint( &p->vObjType ); } static inline void Cba_NtkPrint( Cba_Ntk_t * p ) { int i, Type; printf( "Interface (%d):\n", Cba_NtkPioNum(p) ); printf( "Objects (%d):\n", Cba_NtkObjNum(p) ); Cba_NtkForEachObjType( p, Type, i ) { printf( "%6d : ", i ); printf( "Type =%3d ", Type ); printf( "Fins = %d ", Cba_ObjFinNum(p, i) ); printf( "Fons = %d ", Cba_ObjFonNum(p, i) ); if ( Cba_NtkHasObjNames(p) && Cba_ObjName(p, i) ) printf( "%s", Cba_ObjNameStr(p, i) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Manager APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cba_Man_t * Cba_ManAlloc( char * pFileName, int nNtks, Abc_Nam_t * pStrs, Abc_Nam_t * pFuns, Abc_Nam_t * pMods, Hash_IntMan_t * vHash ) { Cba_Man_t * pNew = ABC_CALLOC( Cba_Man_t, 1 ); pNew->pName = Extra_FileDesignName( pFileName ); pNew->pSpec = Abc_UtilStrsav( pFileName ); pNew->pStrs = pStrs ? pStrs : Abc_NamStart( 1000, 24 ); pNew->pFuns = pFuns ? pFuns : Abc_NamStart( 100, 24 ); pNew->pMods = pMods ? pMods : Abc_NamStart( 100, 24 ); pNew->vHash = vHash ? vHash : Hash_IntManStart( 1000 ); if ( pFuns == NULL ) { Abc_NamStrFindOrAdd(pNew->pFuns, "1\'b0", NULL); Abc_NamStrFindOrAdd(pNew->pFuns, "1\'b1", NULL); Abc_NamStrFindOrAdd(pNew->pFuns, "1\'bx", NULL); Abc_NamStrFindOrAdd(pNew->pFuns, "1\'bz", NULL); } // if ( vHash == NULL ) // Hash_Int2ManInsert( pNew->vHash, 0, 0, 0 ); Vec_PtrGrow( &pNew->vNtks, nNtks+1 ); Vec_PtrPush( &pNew->vNtks, NULL ); // set default root module pNew->iRoot = 1; return pNew; } static inline void Cba_ManDupTypeNames( Cba_Man_t * pNew, Cba_Man_t * p ) { memcpy( pNew->pTypeNames, p->pTypeNames, sizeof(void *) * CBA_BOX_LAST ); } static inline Cba_Man_t * Cba_ManDup( Cba_Man_t * p, Vec_Int_t*(* pFuncOrder)(Cba_Ntk_t*) ) { Cba_Ntk_t * pNtk, * pNtkNew; int i; Cba_Man_t * pNew = Cba_ManAlloc( p->pSpec, Cba_ManNtkNum(p), Abc_NamRef(p->pStrs), Abc_NamRef(p->pFuns), Abc_NamStart(100, 24), Hash_IntManRef(p->vHash) ); Cba_ManDupTypeNames( pNew, p ); Cba_ManForEachNtk( p, pNtk, i ) { pNtkNew = Cba_NtkDupOrder( pNew, pNtk, pFuncOrder ); Cba_NtkAdd( pNew, pNtkNew ); Cba_NtkDupAttrs( pNtkNew, pNtk ); } // Cba_ManForEachNtk( p, pNtk, i ) // if ( (pHost = Cba_NtkHostNtk(pNtk)) ) // Cba_NtkSetHost( Cba_NtkCopyNtk(pNew, pNtk), Cba_NtkCopy(pHost), Cba_ObjCopy(pHost, Cba_NtkHostObj(pNtk)) ); pNew->iRoot = Cba_ManNtkNum(pNew); return pNew; } static inline void Cba_ManPrepareSeq( Cba_Man_t * p ) { Cba_Ntk_t * pNtk; int i; Cba_ManForEachNtk( p, pNtk, i ) Cba_NtkPrepareSeq( pNtk ); } static inline void Cba_ManFree( Cba_Man_t * p ) { Cba_Ntk_t * pNtk; int i; Cba_ManForEachNtk( p, pNtk, i ) Cba_NtkFree( pNtk ); ABC_FREE( p->vNtks.pArray ); Abc_NamDeref( p->pStrs ); Abc_NamDeref( p->pFuns ); Abc_NamDeref( p->pMods ); Hash_IntManDeref( p->vHash ); Vec_IntErase( &p->vNameMap ); Vec_IntErase( &p->vUsed ); Vec_IntErase( &p->vNameMap2 ); Vec_IntErase( &p->vUsed2 ); Vec_StrErase( &p->vOut ); Vec_StrErase( &p->vOut2 ); ABC_FREE( p->pName ); ABC_FREE( p->pSpec ); ABC_FREE( p ); } static inline int Cba_ManGetMap( Cba_Man_t * p, int i ) { return Vec_IntGetEntry(&p->vNameMap, i); } static inline void Cba_ManSetMap( Cba_Man_t * p, int i, int x ) { assert( Vec_IntGetEntry(&p->vNameMap, i) == 0 ); Vec_IntSetEntry( &p->vNameMap, i, x ); Vec_IntPush( &p->vUsed, i ); } static inline void Cba_ManUnsetMap( Cba_Man_t * p, int i ) { Vec_IntSetEntry( &p->vNameMap, i, 0 ); } static inline void Cba_ManCleanMap( Cba_Man_t * p ) { int i, Entry; Vec_IntForEachEntry( &p->vUsed, Entry, i ) Vec_IntWriteEntry( &p->vNameMap, Entry, 0 ); Vec_IntClear( &p->vUsed ); } static inline int Cba_NtkGetMap( Cba_Ntk_t * p, int i ) { return Cba_ManGetMap(p->pDesign, i); } static inline void Cba_NtkSetMap( Cba_Ntk_t * p, int i, int x ) { Cba_ManSetMap(p->pDesign, i, x); } static inline void Cba_NtkUnsetMap( Cba_Ntk_t * p, int i ) { Cba_ManUnsetMap(p->pDesign, i); } static inline void Cba_NtkCleanMap( Cba_Ntk_t * p ) { Cba_ManCleanMap(p->pDesign); } static inline int Cba_ManGetMap2( Cba_Man_t * p, int i ) { return Vec_IntGetEntry(&p->vNameMap2, i); } static inline void Cba_ManSetMap2( Cba_Man_t * p, int i, int x ) { assert( Vec_IntGetEntry(&p->vNameMap2, i) == 0 ); Vec_IntSetEntry( &p->vNameMap2, i, x ); Vec_IntPush( &p->vUsed2, i ); } static inline void Cba_ManUnsetMap2( Cba_Man_t * p, int i ) { Vec_IntSetEntry( &p->vNameMap2, i, 0 ); } static inline void Cba_ManCleanMap2( Cba_Man_t * p ) { int i, Entry; Vec_IntForEachEntry( &p->vUsed2, Entry, i ) Vec_IntWriteEntry( &p->vNameMap2, Entry, 0 ); Vec_IntClear( &p->vUsed2 ); } static inline int Cba_NtkGetMap2( Cba_Ntk_t * p, int i ) { return Cba_ManGetMap2(p->pDesign, i); } static inline void Cba_NtkSetMap2( Cba_Ntk_t * p, int i, int x ) { Cba_ManSetMap2(p->pDesign, i, x); } static inline void Cba_NtkUnsetMap2( Cba_Ntk_t * p, int i ) { Cba_ManUnsetMap2(p->pDesign, i); } static inline void Cba_NtkCleanMap2( Cba_Ntk_t * p ) { Cba_ManCleanMap2(p->pDesign); } static inline int Cba_ManMemory( Cba_Man_t * p ) { Cba_Ntk_t * pNtk; int i; int nMem = sizeof(Cba_Man_t); nMem += p->pName ? (int)strlen(p->pName) : 0; nMem += p->pSpec ? (int)strlen(p->pSpec) : 0; nMem += Abc_NamMemUsed(p->pStrs); nMem += Abc_NamMemUsed(p->pFuns); nMem += Abc_NamMemUsed(p->pMods); nMem += (int)Vec_IntMemory(&p->vNameMap ); nMem += (int)Vec_IntMemory(&p->vUsed ); nMem += (int)Vec_StrMemory(&p->vOut ); nMem += (int)Vec_StrMemory(&p->vOut2 ); nMem += (int)Vec_PtrMemory(&p->vNtks); Cba_ManForEachNtk( p, pNtk, i ) nMem += Cba_NtkMemory( pNtk ); return nMem; } static inline int Cba_ManObjNum( Cba_Man_t * p ) { Cba_Ntk_t * pNtk; int i, Count = 0; Cba_ManForEachNtk( p, pNtk, i ) Count += Cba_NtkObjNum(pNtk); return Count; } static inline int Cba_ManBoxNum( Cba_Man_t * p ) { Cba_Ntk_t * pNtk; int i, Count = 0; Cba_ManForEachNtk( p, pNtk, i ) Count += Cba_NtkBoxNum( pNtk ); return Count; } static inline void Cba_ManBoxNumRec_rec( Cba_Ntk_t * p, int * pCountP, int * pCountU ) { int iObj, Id = Cba_NtkId(p); if ( pCountP[Id] >= 0 ) return; pCountP[Id] = pCountU[Id] = 0; Cba_NtkForEachObj( p, iObj ) { if ( Cba_ObjIsBoxUser(p, iObj) ) { Cba_ManBoxNumRec_rec( Cba_ObjNtk(p, iObj), pCountP, pCountU ); pCountP[Id] += pCountP[Cba_ObjNtkId(p, iObj)]; pCountU[Id] += pCountU[Cba_ObjNtkId(p, iObj)] + 1; } else pCountP[Id] += 1; } } static inline void Cba_ManBoxNumRec( Cba_Man_t * p, int * pnPrims, int * pnUsers ) { Cba_Ntk_t * pNtk = Cba_ManRoot(p); int * pCountP = ABC_FALLOC( int, Cba_ManNtkNum(p) + 1 ); int * pCountU = ABC_FALLOC( int, Cba_ManNtkNum(p) + 1 ); Cba_ManBoxNumRec_rec( pNtk, pCountP, pCountU ); *pnPrims = pCountP[Cba_NtkId(pNtk)]; *pnUsers = pCountU[Cba_NtkId(pNtk)]; ABC_FREE( pCountP ); ABC_FREE( pCountU ); } static inline void Cba_ManPrintStats( Cba_Man_t * p, int nModules, int fVerbose ) { Cba_Ntk_t * pNtk; int i, nPrims, nUsers; Cba_Ntk_t * pRoot = Cba_ManRoot( p ); Cba_ManBoxNumRec( p, &nPrims, &nUsers ); printf( "%-12s : ", Cba_ManName(p) ); printf( "pi =%5d ", Cba_NtkPiNum(pRoot) ); printf( "po =%5d ", Cba_NtkPoNum(pRoot) ); printf( "mod =%5d ", Cba_ManNtkNum(p) ); printf( "box =%5d ", nPrims + nUsers ); printf( "prim =%5d ", nPrims ); printf( "user =%5d ", nUsers ); printf( "mem =%6.3f MB", 1.0*Cba_ManMemory(p)/(1<<20) ); printf( "\n" ); Cba_ManForEachNtk( p, pNtk, i ) { if ( i == nModules+1 ) break; printf( "Module %5d : ", i ); Cba_NtkPrintStats( pNtk ); } } /**Function************************************************************* Synopsis [Name handling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cba_NtkAddMissingFonNames( Cba_Ntk_t * p, char * pPref ) { int iFon, NameId, Index; // populate map Cba_ManCleanMap( p->pDesign ); Vec_IntForEachEntryStart( &p->vFonName, NameId, iFon, 1 ) if ( NameId ) Cba_ManSetMap( p->pDesign, NameId, iFon ); // check remaining ones Vec_IntForEachEntryStart( &p->vFonName, NameId, iFon, 1 ) { if ( NameId ) continue; NameId = Cba_NtkNewStrId(p, "%s%d", pPref, iFon); for ( Index = 1; Cba_ManGetMap(p->pDesign, NameId); Index++ ) NameId = Cba_NtkNewStrId(p, "%s%d_%d", pPref, iFon, Index); Cba_FonSetName( p, iFon, NameId ); Cba_ManSetMap( p->pDesign, NameId, iFon ); } } static inline void Cba_NtkCreateFonNames( Cba_Ntk_t * p, char * pPref ) { int i, iObj, iFon;//, NameId; Cba_NtkCleanFonNames( p ); Cba_NtkForEachPiFon( p, iObj, iFon, i ) if ( !Cba_FonName(p, iFon) ) Cba_FonSetName( p, iFon, Cba_ObjName(p, iObj) ); Cba_NtkForEachPoDriverFon( p, iObj, iFon, i ) if ( Cba_FonIsReal(iFon) && !Cba_FonName(p, iFon) ) Cba_FonSetName( p, iFon, Cba_ObjName(p, iObj) ); // Vec_IntForEachEntryStart( &p->vFonName, NameId, iFon, 1 ) // if ( NameId == 0 ) // Vec_IntWriteEntry( &p->vFonName, iFon, Cba_NtkNewStrId(p, "%s%d", pPref, iFon) ); Cba_NtkAddMissingFonNames( p, pPref ); } static inline void Cba_NtkMissingFonNames( Cba_Ntk_t * p, char * pPref ) { int i, iObj, iFon;//, NameId; Cba_NtkForEachPiFon( p, iObj, iFon, i ) if ( !Cba_FonName(p, iFon) ) Cba_FonSetName( p, iFon, Cba_ObjName(p, iObj) ); Cba_NtkForEachPoDriverFon( p, iObj, iFon, i ) if ( Cba_FonIsReal(iFon) && !Cba_FonName(p, iFon) ) Cba_FonSetName( p, iFon, Cba_ObjName(p, iObj) ); // Vec_IntForEachEntryStart( &p->vFonName, NameId, iFon, 1 ) // if ( NameId == 0 ) // Cba_FonSetName( p, iFon, Cba_NtkNewStrId(p, "%s%d", pPref, iFon) ); Cba_NtkAddMissingFonNames( p, pPref ); } /*=== cbaBlast.c =============================================================*/ extern Gia_Man_t * Cba_ManBlast( Cba_Man_t * p, int fBarBufs, int fSeq, int fVerbose ); extern Cba_Man_t * Cba_ManInsertGia( Cba_Man_t * p, Gia_Man_t * pGia ); extern Cba_Man_t * Cba_ManInsertAbc( Cba_Man_t * p, void * pAbc ); /*=== cbaCba.c ===============================================================*/ extern Cba_Man_t * Cba_ManReadCba( char * pFileName ); extern void Cba_ManWriteCba( char * pFileName, Cba_Man_t * p ); /*=== cbaCom.c ===============================================================*/ /*=== cbaNtk.c ===============================================================*/ extern void Cba_NtkPrintStatsFull( Cba_Ntk_t * p, int fDistrib, int fVerbose ); extern void Cba_NtkPrintNodes( Cba_Ntk_t * p, int Type ); extern void Cba_NtkPrintDistribOld( Cba_Ntk_t * p ); extern void Cba_ManPrintDistrib( Cba_Man_t * p ); //extern void Cba_ManPrepareTypeNames( Cba_Man_t * p ); extern void Cba_NtkObjOrder( Cba_Ntk_t * p, Vec_Int_t * vObjs, Vec_Int_t * vNameIds ); extern int Cba_NtkCiFonNum( Cba_Ntk_t * p ); extern int Cba_NtkCoFinNum( Cba_Ntk_t * p ); extern int Cba_NtkCheckComboLoop( Cba_Ntk_t * p ); extern int Cba_ManIsTopoOrder( Cba_Man_t * p ); extern Vec_Int_t * Cba_NtkCollectDfs( Cba_Ntk_t * p ); extern Cba_Man_t * Cba_ManCollapse( Cba_Man_t * p ); extern Cba_Man_t * Cba_ManExtractGroup( Cba_Man_t * p, Vec_Int_t * vObjs ); extern Cba_Man_t * Cba_ManDeriveFromGia( Cba_Man_t * p, Gia_Man_t * pGia, int fUseXor ); extern Cba_Man_t * Cba_ManInsertGroup( Cba_Man_t * p, Vec_Int_t * vObjs, Cba_Ntk_t * pSyn ); /*=== cbaReadBlif.c ==========================================================*/ extern Cba_Man_t * Prs_ManBuildCbaBlif( char * pFileName, Vec_Ptr_t * vDes ); extern void Prs_ManReadBlifTest( char * pFileName ); extern Cba_Man_t * Cba_ManReadBlif( char * pFileName ); /*=== cbaReadVer.c ===========================================================*/ extern Cba_Man_t * Prs_ManBuildCbaVerilog( char * pFileName, Vec_Ptr_t * vDes ); extern void Prs_ManReadVerilogTest( char * pFileName ); extern Cba_Man_t * Cba_ManReadVerilog( char * pFileName ); /*=== cbaWriteBlif.c =========================================================*/ extern void Prs_ManWriteBlif( char * pFileName, Vec_Ptr_t * p ); extern void Cba_ManWriteBlif( char * pFileName, Cba_Man_t * p ); /*=== cbaWriteVer.c ==========================================================*/ extern void Cba_ManCreatePrimMap( char ** pMap ); extern char * Cba_ManGetSliceName( Cba_Ntk_t * p, int iFon, int RangeId ); extern void Prs_ManWriteVerilog( char * pFileName, Vec_Ptr_t * p ); extern void Cba_ManWriteVerilog( char * pFileName, Cba_Man_t * p, int fInlineConcat ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaBlast.c000066400000000000000000001274731300674244400233700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaBlast.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Collapsing word-level design.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 21, 2015.] Revision [$Id: cbaBlast.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cba.h" #include "base/abc/abc.h" #include "map/mio/mio.h" #include "bool/dec/dec.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Helper functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cba_NtkPrepareBits( Cba_Ntk_t * p ) { int i, nBits = 0; Cba_NtkCleanFonCopies( p ); Cba_NtkForEachFon( p, i ) { Cba_FonSetCopy( p, i, nBits ); nBits += Cba_FonRangeSize( p, i ); } return nBits; } int * Cba_VecCopy( Vec_Int_t * vOut, int * pArray, int nSize ) { int i; Vec_IntClear( vOut ); for( i = 0; i < nSize; i++) Vec_IntPush( vOut, pArray[i] ); return Vec_IntArray( vOut ); } int Cba_ReadHexDigit( char HexChar ) { if ( HexChar >= '0' && HexChar <= '9' ) return HexChar - '0'; if ( HexChar >= 'A' && HexChar <= 'F' ) return HexChar - 'A' + 10; if ( HexChar >= 'a' && HexChar <= 'f' ) return HexChar - 'a' + 10; assert( 0 ); // not a hexadecimal symbol return -1; // return value which makes no sense } void Cba_BlastConst( Cba_Ntk_t * p, Vec_Int_t * vOut, int iFon, int nTotal, int fSigned ) { char * pConst = Cba_NtkConst(p, Cba_FonConst(iFon)); char * pLimit = pConst + strlen(pConst); int i, Number, nBits = atoi( pConst ); assert( nBits <= nTotal ); while ( *pConst >= '0' && *pConst <= '9' ) pConst++; assert( *pConst == '\'' ); pConst++; if ( *pConst == 's' ) // assume signedness is already used in setting fSigned pConst++; Vec_IntClear( vOut ); if ( *pConst == 'b' ) { while ( --pLimit > pConst ) Vec_IntPush( vOut, *pLimit == '0' ? 0 : 1 ); } else if ( *pConst == 'h' ) { while ( --pLimit > pConst ) { Number = Cba_ReadHexDigit( *pLimit ); for ( i = 0; i < 4; i++ ) Vec_IntPush( vOut, (Number >> i) & 1 ); } if ( Vec_IntSize(vOut) > nTotal ) Vec_IntShrink( vOut, nTotal ); } else if ( *pConst == 'd' ) { Number = atoi( pConst+1 ); assert( Number <= 0x7FFFFFFF ); for ( i = 0; i < 32; i++ ) Vec_IntPush( vOut, (Number >> i) & 1 ); if ( Vec_IntSize(vOut) > nTotal ) Vec_IntShrink( vOut, nTotal ); } else assert( 0 ); if ( fSigned && Vec_IntSize(vOut) < nTotal ) Vec_IntFillExtra( vOut, nTotal - Vec_IntSize(vOut), Vec_IntEntryLast(vOut) ); } int * Cba_VecLoadFanins( Cba_Ntk_t * p, Vec_Int_t * vOut, int iFon, int * pFanins, int nFanins, int nTotal, int fSigned ) { assert( nFanins <= nTotal ); if ( Cba_FonIsReal(iFon) ) { int i, Fill = fSigned ? pFanins[nFanins-1] : 0; Vec_IntClear( vOut ); for( i = 0; i < nTotal; i++) Vec_IntPush( vOut, i < nFanins ? pFanins[i] : Fill ); } else if ( Cba_FonIsConst(iFon) ) Cba_BlastConst( p, vOut, iFon, nTotal, fSigned ); else if ( iFon == 0 ) // undriven input Vec_IntFill( vOut, nTotal, 0 ); else assert( 0 ); assert( Vec_IntSize(vOut) == nTotal ); return Vec_IntArray( vOut ); } int Cba_NtkMuxTree_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 = Cba_NtkMuxTree_rec( pNew, pCtrl, nCtrl-1, vData, Shift ); iLit1 = Cba_NtkMuxTree_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) ); return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); } /**Function************************************************************* Synopsis [Bit blasting for specific operations.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cba_BlastShiftRight( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes ) { int * pRes = Cba_VecCopy( vRes, pNum, nNum ); int Fill = fSticky ? pNum[nNum-1] : 0; int i, j, fShort = 0; if ( nShift > 32 ) nShift = 32; assert( nShift <= 32 ); for( i = 0; i < nShift; i++ ) for( j = 0; j < nNum - fSticky; j++ ) { if( fShort || j + (1<= nNum ) { pRes[j] = Gia_ManHashMux( pNew, pShift[i], Fill, pRes[j] ); if ( (1< nNum ) fShort = 1; } else pRes[j] = Gia_ManHashMux( pNew, pShift[i], pRes[j+(1< 32 ) nShift = 32; assert( nShift <= 32 ); for( i = 0; i < nShift; i++ ) for( j = nNum-1; j >= fSticky; j-- ) { if( fShort || (1< j ) { pRes[j] = Gia_ManHashMux( pNew, pShift[i], Fill, pRes[j] ); if ( (1< nNum ) fShort = 1; } else pRes[j] = Gia_ManHashMux( pNew, pShift[i], pRes[j-(1<= (1<= 0; k-- ) { iRes = Gia_ManHashMux( pNew, iKnown, iRes, Gia_ManHashAnd(pNew, Abc_LitNot(pArg0[k]), pArg1[k]) ); iKnown = Gia_ManHashOr( pNew, iKnown, Gia_ManHashXor(pNew, pArg0[k], pArg1[k]) ); if ( iKnown == 1 ) break; } return iRes; } void Cba_BlastLess_rec( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits, int * pYes, int * pNo ) { if ( nBits > 1 ) { int Yes = Gia_ManHashAnd( pNew, Abc_LitNot(pArg0[nBits-1]), pArg1[nBits-1] ), YesR; int No = Gia_ManHashAnd( pNew, Abc_LitNot(pArg1[nBits-1]), pArg0[nBits-1] ), NoR; if ( Yes == 1 || No == 1 ) { *pYes = Yes; *pNo = No; return; } Cba_BlastLess_rec( pNew, pArg0, pArg1, nBits-1, &YesR, &NoR ); *pYes = Gia_ManHashOr( pNew, Yes, Gia_ManHashAnd(pNew, Abc_LitNot(No), YesR) ); *pNo = Gia_ManHashOr( pNew, No, Gia_ManHashAnd(pNew, Abc_LitNot(Yes), NoR ) ); return; } assert( nBits == 1 ); *pYes = Gia_ManHashAnd( pNew, Abc_LitNot(pArg0[0]), pArg1[0] ); *pNo = Gia_ManHashAnd( pNew, Abc_LitNot(pArg1[0]), pArg0[0] ); } int Cba_BlastLess( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits ) { int Yes, No; if ( nBits == 0 ) return 0; Cba_BlastLess_rec( pNew, pArg0, pArg1, nBits, &Yes, &No ); return Yes; } int Cba_BlastLessSigned( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits ) { int iDiffSign = Gia_ManHashXor( pNew, pArg0[nBits-1], pArg1[nBits-1] ); return Gia_ManHashMux( pNew, iDiffSign, pArg0[nBits-1], Cba_BlastLess(pNew, pArg0, pArg1, nBits-1) ); } void Cba_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps ) { int fUseXor = 0; if ( fUseXor ) { int Xor = Gia_ManHashXor(pNew, a, b); int And1 = Gia_ManHashAnd(pNew, a, b); int And2 = Gia_ManHashAnd(pNew, c, Xor); *ps = Gia_ManHashXor(pNew, c, Xor); *pc = Gia_ManHashOr (pNew, And1, And2); } else { int And1 = Gia_ManHashAnd(pNew, a, b); int And1_= Gia_ManHashAnd(pNew, Abc_LitNot(a), Abc_LitNot(b)); int Xor = Abc_LitNot(Gia_ManHashOr(pNew, And1, And1_)); int And2 = Gia_ManHashAnd(pNew, c, Xor); int And2_= Gia_ManHashAnd(pNew, Abc_LitNot(c), Abc_LitNot(Xor)); *ps = Abc_LitNot(Gia_ManHashOr(pNew, And2, And2_)); *pc = Gia_ManHashOr (pNew, And1, And2); } } int Cba_BlastAdder( Gia_Man_t * pNew, int Carry, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0 { int b; for ( b = 0; b < nBits; b++ ) Cba_BlastFullAdder( pNew, pAdd0[b], pAdd1[b], Carry, &Carry, &pAdd0[b] ); return Carry; } void Cba_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0 { int b, Carry = 1; for ( b = 0; b < nBits; b++ ) Cba_BlastFullAdder( pNew, pAdd0[b], Abc_LitNot(pAdd1[b]), Carry, &Carry, &pAdd0[b] ); } void Cba_BlastMinus( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vRes ) { int * pRes = Cba_VecCopy( vRes, pNum, nNum ); int i, invert = 0; for ( i = 0; i < nNum; i++ ) { pRes[i] = Gia_ManHashMux( pNew, invert, Abc_LitNot(pRes[i]), pRes[i] ); invert = Gia_ManHashOr( pNew, invert, pNum[i] ); } } void Cba_BlastMultiplier2( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits, Vec_Int_t * vTemp, Vec_Int_t * vRes ) { int i, j; Vec_IntFill( vRes, nBits, 0 ); for ( i = 0; i < nBits; i++ ) { Vec_IntFill( vTemp, i, 0 ); for ( j = 0; Vec_IntSize(vTemp) < nBits; j++ ) Vec_IntPush( vTemp, Gia_ManHashAnd(pNew, pArg0[j], pArg1[i]) ); assert( Vec_IntSize(vTemp) == nBits ); Cba_BlastAdder( pNew, 0, Vec_IntArray(vRes), Vec_IntArray(vTemp), nBits ); } } void Cba_BlastFullAdderCtrl( Gia_Man_t * pNew, int a, int ac, int b, int c, int * pc, int * ps, int fNeg ) { int And = Abc_LitNotCond( Gia_ManHashAnd(pNew, a, ac), fNeg ); Cba_BlastFullAdder( pNew, And, b, c, pc, ps ); } void Cba_BlastFullAdderSubtr( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps, int fSub ) { Cba_BlastFullAdder( pNew, Gia_ManHashXor(pNew, a, fSub), b, c, pc, ps ); } void Cba_BlastMultiplier( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vTemp, Vec_Int_t * vRes, int fSigned ) { int * pRes, * pArgC, * pArgS, a, b, Carry = fSigned; assert( nArgA > 0 && nArgB > 0 ); assert( fSigned == 0 || fSigned == 1 ); // prepare result Vec_IntFill( vRes, nArgA + nArgB, 0 ); pRes = Vec_IntArray( vRes ); // prepare intermediate storage Vec_IntFill( vTemp, 2 * nArgA, 0 ); pArgC = Vec_IntArray( vTemp ); pArgS = pArgC + nArgA; // create matrix for ( b = 0; b < nArgB; b++ ) for ( a = 0; a < nArgA; a++ ) Cba_BlastFullAdderCtrl( pNew, pArgA[a], pArgB[b], pArgS[a], pArgC[a], &pArgC[a], a ? &pArgS[a-1] : &pRes[b], fSigned && ((a+1 == nArgA) ^ (b+1 == nArgB)) ); // final addition pArgS[nArgA-1] = fSigned; for ( a = 0; a < nArgA; a++ ) Cba_BlastFullAdderCtrl( pNew, 1, pArgC[a], pArgS[a], Carry, &Carry, &pRes[nArgB+a], 0 ); } void Cba_BlastDivider( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) { int * pRes = Cba_VecCopy( vRes, pNum, nNum ); int * pQuo = ABC_ALLOC( int, nNum ); int * pTemp = ABC_ALLOC( int, nNum ); int i, j, known, borrow, y_bit, top_bit; assert( nNum == nDiv ); for ( j = nNum - 1; j >= 0; j-- ) { known = 0; for ( i = nNum - 1; i > nNum - 1 - j; i-- ) { known = Gia_ManHashOr( pNew, known, pDiv[i] ); if( known == 1 ) break; } pQuo[j] = known; for ( i = nNum - 1; i >= 0; i-- ) { if ( known == 1 ) break; y_bit = (i >= j) ? pDiv[i-j] : 0; pQuo[j] = Gia_ManHashMux( pNew, known, pQuo[j], Gia_ManHashAnd( pNew, y_bit, Abc_LitNot(pRes[i]) ) ); known = Gia_ManHashOr( pNew, known, Gia_ManHashXor(pNew, y_bit, pRes[i])); } pQuo[j] = Abc_LitNot(pQuo[j]); if ( pQuo[j] == 0 ) continue; borrow = 0; for ( i = 0; i < nNum; i++ ) { top_bit = Gia_ManHashMux( pNew, borrow, Abc_LitNot(pRes[i]), pRes[i] ); y_bit = (i >= j) ? pDiv[i-j] : 0; borrow = Gia_ManHashMux( pNew, pRes[i], Gia_ManHashAnd(pNew, borrow, y_bit), Gia_ManHashOr(pNew, borrow, y_bit) ); pTemp[i] = Gia_ManHashXor( pNew, top_bit, y_bit ); } if ( pQuo[j] == 1 ) Cba_VecCopy( vRes, pTemp, nNum ); else for( i = 0; i < nNum; i++ ) pRes[i] = Gia_ManHashMux( pNew, pQuo[j], pTemp[i], pRes[i] ); } ABC_FREE( pTemp ); if ( fQuo ) Cba_VecCopy( vRes, pQuo, nNum ); ABC_FREE( pQuo ); } // non-restoring divider void Cba_BlastDivider2( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) { int i, * pRes = Vec_IntArray(vRes); int k, * pQuo = ABC_ALLOC( int, nNum ); assert( nNum > 0 && nDiv > 0 ); assert( Vec_IntSize(vRes) < nNum + nDiv ); for ( i = 0; i < nNum + nDiv; i++ ) pRes[i] = i < nNum ? pNum[i] : 0; for ( i = nNum-1; i >= 0; i-- ) { int Cntrl = i == nNum-1 ? 1 : pQuo[i+1]; int Carry = Cntrl; for ( k = 0; k <= nDiv; k++ ) Cba_BlastFullAdderSubtr( pNew, k < nDiv ? pDiv[k] : 0, pRes[i+k], Carry, &Carry, &pRes[i+k], Cntrl ); pQuo[i] = Abc_LitNot(pRes[i+nDiv]); } if ( fQuo ) Cba_VecCopy( vRes, pQuo, nNum ); else { int Carry = 0, Temp; for ( k = 0; k < nDiv; k++ ) { Cba_BlastFullAdder( pNew, pDiv[k], pRes[k], Carry, &Carry, &Temp ); pRes[k] = Gia_ManHashMux( pNew, pQuo[0], pRes[k], Temp ); } Vec_IntShrink( vRes, nDiv ); } ABC_FREE( pQuo ); } void Cba_BlastDividerSigned( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) { Vec_Int_t * vNum = Vec_IntAlloc( nNum ); Vec_Int_t * vDiv = Vec_IntAlloc( nDiv ); Vec_Int_t * vRes00 = Vec_IntAlloc( nNum + nDiv ); Vec_Int_t * vRes01 = Vec_IntAlloc( nNum + nDiv ); Vec_Int_t * vRes10 = Vec_IntAlloc( nNum + nDiv ); Vec_Int_t * vRes11 = Vec_IntAlloc( nNum + nDiv ); Vec_Int_t * vRes2 = Vec_IntAlloc( nNum ); int k, iDiffSign = Gia_ManHashXor( pNew, pNum[nNum-1], pDiv[nDiv-1] ); Cba_BlastMinus( pNew, pNum, nNum, vNum ); Cba_BlastMinus( pNew, pDiv, nDiv, vDiv ); Cba_BlastDivider( pNew, pNum, nNum, pDiv, nDiv, fQuo, vRes00 ); Cba_BlastDivider( pNew, pNum, nNum, Vec_IntArray(vDiv), nDiv, fQuo, vRes01 ); Cba_BlastDivider( pNew, Vec_IntArray(vNum), nNum, pDiv, nDiv, fQuo, vRes10 ); Cba_BlastDivider( pNew, Vec_IntArray(vNum), nNum, Vec_IntArray(vDiv), nDiv, fQuo, vRes11 ); Vec_IntClear( vRes ); for ( k = 0; k < nNum; k++ ) { int Data0 = Gia_ManHashMux( pNew, pDiv[nDiv-1], Vec_IntEntry(vRes01,k), Vec_IntEntry(vRes00,k) ); int Data1 = Gia_ManHashMux( pNew, pDiv[nDiv-1], Vec_IntEntry(vRes11,k), Vec_IntEntry(vRes10,k) ); Vec_IntPush( vRes, Gia_ManHashMux(pNew, pNum[nNum-1], Data1, Data0) ); } Cba_BlastMinus( pNew, Vec_IntArray(vRes), nNum, vRes2 ); for ( k = 0; k < nNum; k++ ) Vec_IntWriteEntry( vRes, k, Gia_ManHashMux(pNew, fQuo ? iDiffSign : pNum[nNum-1], Vec_IntEntry(vRes2,k), Vec_IntEntry(vRes,k)) ); Vec_IntFree( vNum ); Vec_IntFree( vDiv ); Vec_IntFree( vRes00 ); Vec_IntFree( vRes01 ); Vec_IntFree( vRes10 ); Vec_IntFree( vRes11 ); Vec_IntFree( vRes2 ); assert( Vec_IntSize(vRes) == nNum ); } void Cba_BlastZeroCondition( Gia_Man_t * pNew, int * pDiv, int nDiv, Vec_Int_t * vRes ) { int i, Entry, iLit = Cba_BlastReduction( pNew, pDiv, nDiv, CBA_BOX_ROR ); Vec_IntForEachEntry( vRes, Entry, i ) Vec_IntWriteEntry( vRes, i, Gia_ManHashAnd(pNew, iLit, Entry) ); } void Cba_BlastTable( Gia_Man_t * pNew, word * pTable, int * pFans, int nFans, int nOuts, Vec_Int_t * vRes ) { extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); Vec_Int_t * vMemory = Vec_IntAlloc( 0 ); Vec_Int_t vLeaves = { nFans, nFans, pFans }; word * pTruth = ABC_ALLOC( word, Abc_TtWordNum(nFans) ); int o, i, m, iLit, nMints = (1 << nFans); Vec_IntClear( vRes ); for ( o = 0; o < nOuts; o++ ) { // derive truth table memset( pTruth, 0, sizeof(word) * Abc_TtWordNum(nFans) ); for ( m = 0; m < nMints; m++ ) for ( i = 0; i < nFans; i++ ) if ( Abc_TtGetBit( pTable, m * nFans + i ) ) Abc_TtSetBit( pTruth, m ); // implement truth table if ( nFans < 6 ) pTruth[0] = Abc_Tt6Stretch( pTruth[0], nFans ); iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, nFans, vMemory, &vLeaves, 1 ); Vec_IntPush( vRes, iLit ); } Vec_IntFree( vMemory ); ABC_FREE( pTruth ); } void Cba_BlastPower( Gia_Man_t * pNew, int * pNum, int nNum, int * pExp, int nExp, Vec_Int_t * vTemp, Vec_Int_t * vRes ) { Vec_Int_t * vDegrees = Vec_IntAlloc( 2*nNum ); Vec_Int_t * vResTemp = Vec_IntAlloc( 2*nNum ); int i, * pDegrees = NULL, * pRes = Vec_IntArray(vRes); int k, * pResTemp = Vec_IntArray(vResTemp); Vec_IntFill( vRes, nNum, 0 ); Vec_IntWriteEntry( vRes, 0, 1 ); for ( i = 0; i < nExp; i++ ) { if ( i == 0 ) pDegrees = Cba_VecCopy( vDegrees, pNum, nNum ); else { Cba_BlastMultiplier2( pNew, pDegrees, pDegrees, nNum, vTemp, vResTemp ); pDegrees = Cba_VecCopy( vDegrees, pResTemp, nNum ); } Cba_BlastMultiplier2( pNew, pRes, pDegrees, nNum, vTemp, vResTemp ); for ( k = 0; k < nNum; k++ ) pRes[k] = Gia_ManHashMux( pNew, pExp[i], pResTemp[k], pRes[k] ); } Vec_IntFree( vResTemp ); Vec_IntFree( vDegrees ); } void Cba_BlastSqrt( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_Int_t * vRes ) { int * pRes, * pSum, * pSumP; int i, k, Carry = -1; assert( nNum % 2 == 0 ); Vec_IntFill( vRes, nNum/2, 0 ); Vec_IntFill( vTmp, 2*nNum, 0 ); pRes = Vec_IntArray( vRes ); pSum = Vec_IntArray( vTmp ); pSumP = pSum + nNum; for ( i = 0; i < nNum/2; i++ ) { pSumP[0] = pNum[nNum-2*i-2]; pSumP[1] = pNum[nNum-2*i-1]; for ( k = 0; k < i+1; k++ ) pSumP[k+2] = pSum[k]; for ( k = 0; k < i + 3; k++ ) { if ( k >= 2 && k < i + 2 ) // middle ones Cba_BlastFullAdder( pNew, pSumP[k], Abc_LitNot(pRes[i-k+1]), Carry, &Carry, &pSum[k] ); else Cba_BlastFullAdder( pNew, pSumP[k], Abc_LitNot(k ? Carry:1), 1, &Carry, &pSum[k] ); if ( k == 0 || k > i ) Carry = Abc_LitNot(Carry); } pRes[i] = Abc_LitNot(Carry); for ( k = 0; k < i + 3; k++ ) pSum[k] = Gia_ManHashMux( pNew, pRes[i], pSum[k], pSumP[k] ); } Vec_IntReverseOrder( vRes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cba_NtkBlast( Cba_Ntk_t * p, int fSeq ) { int fUseOldMultiplierBlasting = 0; Gia_Man_t * pTemp, * pNew; Vec_Int_t * vTemp0, * vTemp1, * vTemp2, * vRes; Vec_Str_t * vInit = fSeq ? Vec_StrAlloc(100) : NULL; Vec_Int_t * vBits = &p->vFonBits; int nBits = Cba_NtkPrepareBits( p ); int * pFans0, * pFans1, * pFans2; int nRange, nRange0, nRange1, nRange2; int Type, iFon, iFon0, iFon1, iFon2, fSigned01; int i, k, b, iFin, iObj, iLit, nAndPrev; Vec_IntClear( vBits ); Vec_IntGrow( vBits, nBits ); vTemp0 = Vec_IntAlloc( 1000 ); vTemp1 = Vec_IntAlloc( 1000 ); vTemp2 = Vec_IntAlloc( 1000 ); vRes = Vec_IntAlloc( 1000 ); // clean AND-gate counters memset( p->pDesign->nAnds, 0, sizeof(int) * CBA_BOX_LAST ); // create AIG manager pNew = Gia_ManStart( 5 * Cba_NtkObjNum(p) + 1000 ); pNew->pName = Abc_UtilStrsav( Cba_ManName(p->pDesign) ); Gia_ManHashAlloc( pNew ); // blast in the topological order Cba_NtkForEachObj( p, i ) { Type = Cba_ObjType(p, i); if ( Type == CBA_OBJ_PO ) continue; assert( Vec_IntSize(vBits) == Cba_FonCopy(p, Cba_ObjFon0(p, i)) ); nRange = Cba_ObjRangeSize(p, i); assert( nRange > 0 ); if ( Cba_ObjIsPi(p, i) || Cba_ObjIsSeq(p, i) ) { for ( k = 0; k < nRange; k++ ) Vec_IntPush( vBits, Gia_ManAppendCi(pNew) ); assert( Type == CBA_BOX_DFFCPL || Cba_ObjFonNum(p, i) == 1 ); continue; } assert( Cba_ObjFinNum(p, i) > 0 ); iFon0 = Cba_ObjFinNum(p, i) > 0 ? Cba_ObjFinFon(p, i, 0) : -1; iFon1 = Cba_ObjFinNum(p, i) > 1 ? Cba_ObjFinFon(p, i, 1) : -1; iFon2 = Cba_ObjFinNum(p, i) > 2 ? Cba_ObjFinFon(p, i, 2) : -1; nRange0 = Cba_ObjFinNum(p, i) > 0 ? Cba_FonRangeSize(p, iFon0) : -1; nRange1 = Cba_ObjFinNum(p, i) > 1 ? Cba_FonRangeSize(p, iFon1) : -1; nRange2 = Cba_ObjFinNum(p, i) > 2 ? Cba_FonRangeSize(p, iFon2) : -1; pFans0 = (Cba_ObjFinNum(p, i) > 0 && Cba_FonIsReal(iFon0)) ? Vec_IntEntryP( vBits, Cba_FonCopy(p, iFon0) ) : NULL; pFans1 = (Cba_ObjFinNum(p, i) > 1 && Cba_FonIsReal(iFon1)) ? Vec_IntEntryP( vBits, Cba_FonCopy(p, iFon1) ) : NULL; pFans2 = (Cba_ObjFinNum(p, i) > 2 && Cba_FonIsReal(iFon2)) ? Vec_IntEntryP( vBits, Cba_FonCopy(p, iFon2) ) : NULL; fSigned01 = (Cba_ObjFinNum(p, i) > 1 && Cba_FonSigned(p, iFon0) && Cba_FonSigned(p, iFon1)); nAndPrev = Gia_ManAndNum(pNew); Vec_IntClear( vRes ); if ( Type == CBA_BOX_SLICE ) { int Left = Cba_ObjLeft( p, i ); int Right = Cba_ObjRight( p, i ); int Left0 = Cba_FonLeft( p, iFon0 ); int Right0 = Cba_FonRight( p, iFon0 ); if ( Left > Right ) { assert( Left0 > Right0 ); for ( k = Right; k <= Left; k++ ) Vec_IntPush( vRes, pFans0[k - Right0] ); } else { assert( Left < Right && Left0 < Right0 ); for ( k = Right; k >= Left; k-- ) Vec_IntPush( vRes, pFans0[k - Right0] ); } } else if ( Type == CBA_BOX_CONCAT ) { int iFinT, iFonT, nTotal = 0; Cba_ObjForEachFinFon( p, i, iFinT, iFonT, k ) nTotal += Cba_FonRangeSize( p, iFonT ); assert( nRange == nTotal ); Cba_ObjForEachFinFon( p, i, iFinT, iFonT, k ) { nRange0 = Cba_FonRangeSize( p, iFonT ); pFans0 = Cba_FonIsReal(iFonT) ? Vec_IntEntryP( vBits, Cba_FonCopy(p, iFonT) ) : NULL; pFans0 = Cba_VecLoadFanins( p, vTemp0, iFonT, pFans0, nRange0, nRange0, Cba_FonSigned(p, iFonT) ); for ( b = 0; b < nRange0; b++ ) Vec_IntPush( vRes, pFans0[b] ); } } else if ( Type == CBA_BOX_BUF ) { int nRangeMax = Abc_MaxInt( nRange0, nRange ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, Cba_FonSigned(p, iFon0) ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, pArg0[k] ); } else if ( Type >= CBA_BOX_CF && Type <= CBA_BOX_CZ ) { assert( 0 ); //word * pTruth = (word *)Cba_ObjFanins(p, i); //for ( k = 0; k < nRange; k++ ) // Vec_IntPush( vRes, Abc_TtGetBit(pTruth, k) ); } else if ( Type == CBA_BOX_MUX || Type == CBA_BOX_NMUX ) { // It is strange and disturbing that Verilog standard treats these statements differently: // Statement 1: // assign o = i ? b : a; // Statement 2: // always @( i or a or b ) // begin // case ( i ) // 0 : o = a ; // 1 : o = b ; // endcase // end // If a is signed and b is unsigned, Statement 1 does not sign-extend a, while Statement 2 does. // The signedness of o does not matter. // // Below we (somewhat arbitrarily) distinguish these two by assuming that // Statement 1 has three fanins, while Statement 2 has more than three fanins. // int iFinT, iFonT, fSigned = 1; assert( nRange0 >= 1 && Cba_ObjFinNum(p, i) >= 3 ); assert( 1 + (1 << nRange0) == Cba_ObjFinNum(p, i) ); Cba_ObjForEachFinFon( p, i, iFinT, iFonT, k ) if ( k > 0 ) fSigned &= Cba_FonSigned(p, iFonT); for ( b = 0; b < nRange; b++ ) { Vec_IntClear( vTemp0 ); Cba_ObjForEachFinFon( p, i, iFinT, iFonT, k ) if ( k > 0 ) { nRange1 = Cba_FonRangeSize( p, iFonT ); pFans1 = Cba_FonIsReal(iFonT) ? Vec_IntEntryP( vBits, Cba_FonCopy(p, iFonT) ) : NULL; if ( Cba_ObjFinNum(p, i) == 3 ) // Statement 1 Vec_IntPush( vTemp0, k < nRange1 ? pFans1[k] : (fSigned? pFans1[nRange1-1] : 0) ); else // Statement 2 Vec_IntPush( vTemp0, k < nRange1 ? pFans1[k] : (Cba_FonSigned(p, iFonT)? pFans1[nRange1-1] : 0) ); } Vec_IntPush( vRes, Cba_NtkMuxTree_rec(pNew, pFans0, nRange0, vTemp0, 0) ); } } else if ( Type == CBA_BOX_SHIR || Type == CBA_BOX_SHIRA || Type == CBA_BOX_SHIL || Type == CBA_BOX_SHILA ) { int nRangeMax = Abc_MaxInt( nRange, nRange0 ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, Cba_FonSigned(p, iFon0) ); if ( Type == CBA_BOX_SHIR || Type == CBA_BOX_SHIRA ) Cba_BlastShiftRight( pNew, pArg0, nRangeMax, pFans1, nRange1, Cba_FonSigned(p, iFon0) && Type == CBA_BOX_SHIRA, vRes ); else Cba_BlastShiftLeft( pNew, pArg0, nRangeMax, pFans1, nRange1, 0, vRes ); Vec_IntShrink( vRes, nRange ); } else if ( Type == CBA_BOX_ROTR ) { assert( nRange0 == nRange ); Cba_BlastRotateRight( pNew, pFans0, nRange0, pFans1, nRange1, vRes ); } else if ( Type == CBA_BOX_ROTL ) { assert( nRange0 == nRange ); Cba_BlastRotateLeft( pNew, pFans0, nRange0, pFans1, nRange1, vRes ); } else if ( Type == CBA_BOX_INV ) { int nRangeMax = Abc_MaxInt( nRange, nRange0 ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, Cba_FonSigned(p, iFon0) ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Abc_LitNot(pArg0[k]) ); } else if ( Type == CBA_BOX_AND ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Gia_ManHashAnd(pNew, pArg0[k], pArg1[k]) ); } else if ( Type == CBA_BOX_OR ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Gia_ManHashOr(pNew, pArg0[k], pArg1[k]) ); } else if ( Type == CBA_BOX_XOR ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Gia_ManHashXor(pNew, pArg0[k], pArg1[k]) ); } else if ( Type == CBA_BOX_LNOT ) { iLit = Cba_BlastReduction( pNew, pFans0, nRange0, CBA_BOX_ROR ); Vec_IntFill( vRes, 1, Abc_LitNot(iLit) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( Type == CBA_BOX_LAND ) { int iLit0 = Cba_BlastReduction( pNew, pFans0, nRange0, CBA_BOX_ROR ); int iLit1 = Cba_BlastReduction( pNew, pFans1, nRange1, CBA_BOX_ROR ); Vec_IntFill( vRes, 1, Gia_ManHashAnd(pNew, iLit0, iLit1) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( Type == CBA_BOX_LOR ) { int iLit0 = Cba_BlastReduction( pNew, pFans0, nRange0, CBA_BOX_ROR ); int iLit1 = Cba_BlastReduction( pNew, pFans1, nRange1, CBA_BOX_ROR ); Vec_IntFill( vRes, 1, Gia_ManHashOr(pNew, iLit0, iLit1) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( Type == CBA_BOX_LXOR ) { int iLit0 = Cba_BlastReduction( pNew, pFans0, nRange0, CBA_BOX_ROR ); int iLit1 = Cba_BlastReduction( pNew, pFans1, nRange1, CBA_BOX_ROR ); Vec_IntFill( vRes, 1, Gia_ManHashXor(pNew, iLit0, iLit1) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( Type == CBA_BOX_EQU || Type == CBA_BOX_NEQU ) { int iLit = 0, nRangeMax = Abc_MaxInt( nRange0, nRange1 ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); for ( k = 0; k < nRangeMax; k++ ) iLit = Gia_ManHashOr( pNew, iLit, Gia_ManHashXor(pNew, pArg0[k], pArg1[k]) ); Vec_IntFill( vRes, 1, Abc_LitNotCond(iLit, Type == CBA_BOX_EQU) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( Type == CBA_BOX_LTHAN || Type == CBA_BOX_METHAN || Type == CBA_BOX_MTHAN || Type == CBA_BOX_LETHAN ) { int nRangeMax = Abc_MaxInt( nRange0, nRange1 ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); int fSwap = (Type == CBA_BOX_MTHAN || Type == CBA_BOX_LETHAN); int fCompl = (Type == CBA_BOX_METHAN || Type == CBA_BOX_LETHAN); if ( fSwap ) ABC_SWAP( int *, pArg0, pArg1 ); if ( fSigned01 ) iLit = Cba_BlastLessSigned( pNew, pArg0, pArg1, nRangeMax ); else iLit = Cba_BlastLess( pNew, pArg0, pArg1, nRangeMax ); iLit = Abc_LitNotCond( iLit, fCompl ); Vec_IntFill( vRes, 1, iLit ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( Type == CBA_BOX_RAND || Type == CBA_BOX_ROR || Type == CBA_BOX_RXOR ) { Vec_IntPush( vRes, Cba_BlastReduction( pNew, pFans0, nRange0, Type ) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( Type == CBA_BOX_ADD ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange1, nRange2) ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, 1, 1, 0 ); int * pArg1 = Cba_VecLoadFanins( p, vRes, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); int * pArg2 = Cba_VecLoadFanins( p, vTemp1, iFon2, pFans2, nRange2, nRangeMax, fSigned01 ); int Carry = Cba_BlastAdder( pNew, pArg0[0], pArg1, pArg2, nRange ); // result is in pArg1 (vRes) assert( nRange0 == 1 ); Vec_IntShrink( vRes, nRange ); Vec_IntPush( vRes, Carry ); } else if ( Type == CBA_BOX_SUB ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Cba_VecLoadFanins( p, vRes, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); Cba_BlastSubtract( pNew, pArg0, pArg1, nRange ); // result is in pFan0 (vRes) Vec_IntShrink( vRes, nRange ); } else if ( Type == CBA_BOX_MUL ) { if ( fUseOldMultiplierBlasting ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); Cba_BlastMultiplier2( pNew, pArg0, pArg1, nRange, vTemp2, vRes ); Vec_IntShrink( vRes, nRange ); } else { int nRangeMax = Abc_MaxInt(nRange0, nRange1); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); Cba_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned01 ); if ( nRange > nRangeMax + nRangeMax ) Vec_IntFillExtra( vRes, nRange, fSigned01 ? Vec_IntEntryLast(vRes) : 0 ); else Vec_IntShrink( vRes, nRange ); assert( Vec_IntSize(vRes) == nRange ); } } else if ( Type == CBA_BOX_DIV || Type == CBA_BOX_MOD ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, fSigned01 ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRangeMax, fSigned01 ); if ( fSigned01 ) Cba_BlastDividerSigned( pNew, pArg0, nRangeMax, pArg1, nRangeMax, Type == CBA_BOX_DIV, vRes ); else Cba_BlastDivider( pNew, pArg0, nRangeMax, pArg1, nRangeMax, Type == CBA_BOX_DIV, vRes ); Vec_IntShrink( vRes, nRange ); if ( Type == CBA_BOX_DIV ) Cba_BlastZeroCondition( pNew, pFans1, nRange1, vRes ); } else if ( Type == CBA_BOX_MIN ) { int nRangeMax = Abc_MaxInt( nRange0, nRange ); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, Cba_FonSigned(p, iFon0) ); Cba_BlastMinus( pNew, pArg0, nRangeMax, vRes ); Vec_IntShrink( vRes, nRange ); } else if ( Type == CBA_BOX_POW ) { int nRangeMax = Abc_MaxInt(nRange0, nRange); int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRangeMax, Cba_FonSigned(p, iFon0) ); int * pArg1 = Cba_VecLoadFanins( p, vTemp1, iFon1, pFans1, nRange1, nRange1, Cba_FonSigned(p, iFon1) ); Cba_BlastPower( pNew, pArg0, nRangeMax, pArg1, nRange1, vTemp2, vRes ); Vec_IntShrink( vRes, nRange ); } else if ( Type == CBA_BOX_SQRT ) { int * pArg0 = Cba_VecLoadFanins( p, vTemp0, iFon0, pFans0, nRange0, nRange0 + (nRange0 & 1), 0 ); nRange0 += (nRange0 & 1); Cba_BlastSqrt( pNew, pArg0, nRange0, vTemp2, vRes ); if ( nRange > Vec_IntSize(vRes) ) Vec_IntFillExtra( vRes, nRange, 0 ); else Vec_IntShrink( vRes, nRange ); } else if ( Type == CBA_BOX_TABLE ) { assert( 0 ); //Cba_BlastTable( pNew, Cba_ObjTable(p, p, i), pFans0, nRange0, nRange, vRes ); } else assert( 0 ); Vec_IntAppend( vBits, vRes ); p->pDesign->nAnds[Type] += Gia_ManAndNum(pNew) - nAndPrev; } assert( nBits == Vec_IntSize(vBits) ); p->pDesign->nAnds[0] = Gia_ManAndNum(pNew); // create COs Cba_NtkForEachPo( p, iObj, i ) { Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) { nRange = Cba_FonRangeSize( p, iFon ); pFans0 = Cba_FonIsReal(iFon) ? Vec_IntEntryP( vBits, Cba_FonCopy(p, iFon) ) : NULL; pFans0 = Cba_VecLoadFanins( p, vTemp0, iFon, pFans0, nRange, nRange, Cba_FonSigned(p, iFon) ); for ( b = 0; b < nRange; b++ ) Gia_ManAppendCo( pNew, pFans0[b] ); } } Cba_NtkForEachBoxSeq( p, iObj, i ) { if ( fSeq ) { assert( Cba_ObjType(p, iObj) == CBA_BOX_DFFCPL ); iFon0 = Cba_ObjFinFon( p, iObj, 0 ); iFon1 = Cba_ObjFinFon( p, iObj, 1 ); nRange0 = Cba_FonRangeSize( p, iFon0 ); nRange1 = Cba_FonRangeSize( p, iFon1 ); assert( nRange0 == nRange1 ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) { nRange = Cba_FonRangeSize( p, iFon ); pFans0 = Cba_FonIsReal(iFon) ? Vec_IntEntryP( vBits, Cba_FonCopy(p, iFon) ) : NULL; pFans0 = Cba_VecLoadFanins( p, vTemp0, iFon, pFans0, nRange0, nRange0, Cba_FonSigned(p, iFon) ); if ( k == 0 ) { for ( b = 0; b < nRange; b++ ) Gia_ManAppendCo( pNew, pFans0[b] ); } else if ( k == 1 ) { for ( b = 0; b < nRange; b++ ) if ( pFans0[b] == 0 ) Vec_StrPush( vInit, '0' ); else if ( pFans0[b] == 1 ) Vec_StrPush( vInit, '1' ); else Vec_StrPush( vInit, 'x' ); } else break; } } else // combinational { Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) { nRange = Cba_FonRangeSize( p, iFon ); pFans0 = Cba_FonIsReal(iFon) ? Vec_IntEntryP( vBits, Cba_FonCopy(p, iFon) ) : NULL; pFans0 = Cba_VecLoadFanins( p, vTemp0, iFon, pFans0, nRange, nRange, Cba_FonSigned(p, iFon) ); for ( b = 0; b < nRange; b++ ) Gia_ManAppendCo( pNew, pFans0[b] ); } } } Vec_IntFree( vTemp0 ); Vec_IntFree( vTemp1 ); Vec_IntFree( vTemp2 ); Vec_IntFree( vRes ); // finalize AIG pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManDupRemapLiterals( vBits, pTemp ); Gia_ManStop( pTemp ); // transform AIG with init state if ( fSeq ) { Gia_ManSetRegNum( pNew, Vec_StrSize(vInit) ); Vec_StrPush( vInit, '\0' ); pNew = Gia_ManDupZeroUndc( pTemp = pNew, Vec_StrArray(vInit), 0, 1 ); Gia_ManDupRemapLiterals( vBits, pTemp ); Gia_ManStop( pTemp ); Vec_StrFreeP( &vInit ); } //Vec_IntErase( vBits ); //Vec_IntErase( &p->vCopies ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cba_ManBlast( Cba_Man_t * p, int fBarBufs, int fSeq, int fVerbose ) { return Cba_NtkBlast( Cba_ManRoot(p), fSeq ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cba_Man_t * Cba_ManInsertGia( Cba_Man_t * p, Gia_Man_t * pGia ) { return NULL; } Cba_Man_t * Cba_ManInsertAbc( Cba_Man_t * p, void * pAbc ) { Abc_Ntk_t * pNtk = (Abc_Ntk_t *)pAbc; return (Cba_Man_t *)pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaCba.c000066400000000000000000000031251300674244400227730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaCba.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Reading binary representation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 21, 2015.] Revision [$Id: cbaCba.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cba.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cba_Man_t * Cba_ManReadCba( char * pFileName ) { return NULL; } void Cba_ManWriteCba( char * pFileName, Cba_Man_t * p ) { } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaCom.c000066400000000000000000000555671300674244400230450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaCom.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Command handlers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: cbaCom.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cba.h" #include "proof/cec/cec.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Cba_CommandRead ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Cba_CommandWrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Cba_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Cba_CommandPut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Cba_CommandGet ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Cba_CommandClp ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Cba_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Cba_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Cba_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static inline Cba_Man_t * Cba_AbcGetMan( Abc_Frame_t * pAbc ) { return (Cba_Man_t *)pAbc->pAbcCba; } static inline void Cba_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcCba ) Cba_ManFree(Cba_AbcGetMan(pAbc)); } static inline void Cba_AbcUpdateMan( Abc_Frame_t * pAbc, Cba_Man_t * p ) { Cba_AbcFreeMan(pAbc); pAbc->pAbcCba = p; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Cba_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "New word level", "@read", Cba_CommandRead, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@write", Cba_CommandWrite, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@ps", Cba_CommandPs, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@put", Cba_CommandPut, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@get", Cba_CommandGet, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@clp", Cba_CommandClp, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@blast", Cba_CommandBlast, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@cec", Cba_CommandCec, 0 ); Cmd_CommandAdd( pAbc, "New word level", "@test", Cba_CommandTest, 0 ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Cba_End( Abc_Frame_t * pAbc ) { Cba_AbcFreeMan( pAbc ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Cba_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Cba_Man_t * p = NULL; char * pFileName = NULL; int c, fTest = 0, fDfs = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "tdvh" ) ) != EOF ) { switch ( c ) { case 't': fTest ^= 1; break; case 'd': fDfs ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { printf( "Cba_CommandRead(): Input file name should be given on the command line.\n" ); return 0; } // get the file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "r" )) == NULL ) { Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", ".smt", ".cba", NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); Abc_Print( 1, "\n" ); return 0; } fclose( pFile ); if ( fTest ) { if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) ) Prs_ManReadBlifTest( pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) Prs_ManReadVerilogTest( pFileName ); else { printf( "Unrecognized input file extension.\n" ); return 0; } return 0; } if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) ) p = Cba_ManReadBlif( pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) p = Cba_ManReadVerilog( pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) ) p = Cba_ManReadCba( pFileName ); else { printf( "Unrecognized input file extension.\n" ); return 0; } if ( fDfs ) { Cba_Man_t * pTemp; p = Cba_ManDup( pTemp = p, Cba_NtkCollectDfs ); Cba_ManFree( pTemp ); } Cba_AbcUpdateMan( pAbc, p ); return 0; usage: Abc_Print( -2, "usage: @read [-tdvh] \n" ); Abc_Print( -2, "\t reads hierarchical design\n" ); Abc_Print( -2, "\t-t : toggle testing the parser [default = %s]\n", fTest? "yes": "no" ); Abc_Print( -2, "\t-d : toggle computing DFS ordering [default = %s]\n", fDfs? "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 Cba_CommandWrite( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cba_Man_t * p = Cba_AbcGetMan(pAbc); char * pFileName = NULL; int fInclineCats = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF ) { switch ( c ) { case 'c': fInclineCats ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Cba_CommandWrite(): There is no current design.\n" ); return 0; } if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; else if ( argc == globalUtilOptind && p ) { pFileName = Extra_FileNameGenericAppend( Cba_ManSpec(p) ? Cba_ManSpec(p) : Cba_ManName(p), "_out.v" ); printf( "Generated output file name \"%s\".\n", pFileName ); } else { printf( "Output file name should be given on the command line.\n" ); return 0; } // perform writing if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) ) Cba_ManWriteBlif( pFileName, p ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) Cba_ManWriteVerilog( pFileName, p, fInclineCats ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) ) Cba_ManWriteCba( pFileName, p ); else { printf( "Unrecognized output file extension.\n" ); return 0; } return 0; usage: Abc_Print( -2, "usage: @write [-cvh]\n" ); Abc_Print( -2, "\t writes the design into a file in BLIF or Verilog\n" ); Abc_Print( -2, "\t-c : toggle inlining input concatenations [default = %s]\n", fInclineCats? "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 Cba_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cba_Man_t * p = Cba_AbcGetMan(pAbc); int nModules = 0; int fShowMulti = 0; int fShowAdder = 0; int fDistrib = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Mmadvh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nModules = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nModules < 0 ) goto usage; break; case 'm': fShowMulti ^= 1; break; case 'a': fShowAdder ^= 1; break; case 'd': fDistrib ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Cba_CommandPs(): There is no current design.\n" ); return 0; } if ( nModules ) { Cba_ManPrintStats( p, nModules, fVerbose ); return 0; } Cba_NtkPrintStatsFull( Cba_ManRoot(p), fDistrib, fVerbose ); if ( fShowMulti ) Cba_NtkPrintNodes( Cba_ManRoot(p), CBA_BOX_MUL ); if ( fShowAdder ) Cba_NtkPrintNodes( Cba_ManRoot(p), CBA_BOX_ADD ); return 0; usage: Abc_Print( -2, "usage: @ps [-M num] [-madvh]\n" ); Abc_Print( -2, "\t prints statistics\n" ); Abc_Print( -2, "\t-M num : the number of first modules to report [default = %d]\n", nModules ); Abc_Print( -2, "\t-m : toggle printing multipliers [default = %s]\n", fShowMulti? "yes": "no" ); Abc_Print( -2, "\t-a : toggle printing adders [default = %s]\n", fShowAdder? "yes": "no" ); Abc_Print( -2, "\t-d : toggle printing distrubition [default = %s]\n", fDistrib? "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 Cba_CommandPut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cba_Man_t * p = Cba_AbcGetMan(pAbc); Gia_Man_t * pGia = NULL; int c, fBarBufs = 1, fSeq = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "bsvh" ) ) != EOF ) { switch ( c ) { case 'b': fBarBufs ^= 1; break; case 's': fSeq ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Cba_CommandPut(): There is no current design.\n" ); return 0; } pGia = Cba_ManBlast( p, fBarBufs, fSeq, fVerbose ); if ( pGia == NULL ) { Abc_Print( 1, "Cba_CommandPut(): Conversion to AIG has failed.\n" ); return 0; } Abc_FrameUpdateGia( pAbc, pGia ); return 0; usage: Abc_Print( -2, "usage: @put [-bsvh]\n" ); Abc_Print( -2, "\t extracts AIG from the hierarchical design\n" ); Abc_Print( -2, "\t-b : toggle using barrier buffers [default = %s]\n", fBarBufs? "yes": "no" ); Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "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 Cba_CommandGet( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cba_Man_t * pNew = NULL, * p = Cba_AbcGetMan(pAbc); int c, fMapped = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF ) { switch ( c ) { case 'm': fMapped ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Cba_CommandGet(): There is no current design.\n" ); return 0; } if ( fMapped ) { if ( pAbc->pNtkCur == NULL ) { Abc_Print( 1, "Cba_CommandGet(): There is no current mapped design.\n" ); return 0; } pNew = Cba_ManInsertAbc( p, pAbc->pNtkCur ); } else { if ( pAbc->pGia == NULL ) { Abc_Print( 1, "Cba_CommandGet(): There is no current AIG.\n" ); return 0; } pNew = Cba_ManInsertGia( p, pAbc->pGia ); } Cba_AbcUpdateMan( pAbc, pNew ); return 0; usage: Abc_Print( -2, "usage: @get [-mvh]\n" ); Abc_Print( -2, "\t extracts AIG or mapped network into the hierarchical design\n" ); Abc_Print( -2, "\t-m : toggle using mapped network from main-space [default = %s]\n", fMapped? "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 Cba_CommandClp( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cba_Man_t * pNew = NULL, * p = Cba_AbcGetMan(pAbc); 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 ( p == NULL ) { Abc_Print( 1, "Cba_CommandGet(): There is no current design.\n" ); return 0; } pNew = Cba_ManCollapse( p ); Cba_AbcUpdateMan( pAbc, pNew ); return 0; usage: Abc_Print( -2, "usage: @clp [-vh]\n" ); Abc_Print( -2, "\t collapses the current hierarchical design\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 Cba_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pNew = NULL; Cba_Man_t * p = Cba_AbcGetMan(pAbc); int c, 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; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Cba_CommandBlast(): There is no current design.\n" ); return 0; } pNew = Cba_ManBlast( p, 0, fSeq, fVerbose ); if ( pNew == NULL ) { Abc_Print( 1, "Cba_CommandBlast(): Bit-blasting has failed.\n" ); return 0; } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: Abc_Print( -2, "usage: @blast [-svh]\n" ); Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" ); Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "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 Cba_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cba_Man_t * p = Cba_AbcGetMan(pAbc), * pTemp; Gia_Man_t * pFirst, * pSecond, * pMiter; Cec_ParCec_t ParsCec, * pPars = &ParsCec; char * pFileName, * pStr, ** pArgvNew; int c, nArgcNew, fDumpMiter = 0; FILE * pFile; Cec_ManCecSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Cba_CommandCec(): There is no current design.\n" ); return 0; } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { if ( p->pSpec == NULL ) { Abc_Print( -1, "File name is not given on the command line.\n" ); return 1; } pFileName = p->pSpec; } else pFileName = pArgvNew[0]; // fix the wrong symbol for ( pStr = pFileName; *pStr; pStr++ ) if ( *pStr == '>' ) *pStr = '\\'; if ( (pFile = fopen( pFileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); // extract AIG from the current design pFirst = Cba_ManBlast( p, 0, 0, 0 ); if ( pFirst == NULL ) { Abc_Print( -1, "Extracting AIG from the current design has failed.\n" ); return 0; } // extract AIG from the second design if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) ) pTemp = Cba_ManReadBlif( pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) pTemp = Cba_ManReadVerilog( pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) ) pTemp = Cba_ManReadCba( pFileName ); else assert( 0 ); pSecond = Cba_ManBlast( pTemp, 0, 0, 0 ); Cba_ManFree( pTemp ); if ( pSecond == NULL ) { Gia_ManStop( pFirst ); Abc_Print( -1, "Extracting AIG from the original design has failed.\n" ); return 0; } // compute the miter pMiter = Gia_ManMiter( pFirst, pSecond, 0, 1, 0, 0, pPars->fVerbose ); if ( pMiter ) { if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 ); } pAbc->Status = Cec_ManVerify( pMiter, pPars ); //Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); Gia_ManStop( pMiter ); } Gia_ManStop( pFirst ); Gia_ManStop( pSecond ); return 0; usage: Abc_Print( -2, "usage: @cec [-vh]\n" ); Abc_Print( -2, "\t combinational equivalence checking\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Cba_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cba_Man_t * p = Cba_AbcGetMan(pAbc); 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 ( p == NULL ) { Abc_Print( 1, "Cba_CommandTest(): There is no current design.\n" ); return 0; } return 0; usage: Abc_Print( -2, "usage: @test [-vh]\n" ); Abc_Print( -2, "\t experiments with word-level networks\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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaNtk.c000066400000000000000000001362301300674244400230460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaNtk.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Network manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 21, 2015.] Revision [$Id: cbaNtk.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "cba.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prints distribution of operator types.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdSelectSortCost2( word * pArray, int nSize, word * pCosts ) { int i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pCosts[j] < pCosts[best_i] ) best_i = j; ABC_SWAP( word, pArray[i], pArray[best_i] ); ABC_SWAP( word, pCosts[i], pCosts[best_i] ); } } static inline word Cba_NtkPrintDistribMakeSign( int s, int s0, int s1 ) { return ((word)s1 << 42) | ((word)s0 << 21) | (word)s; } static inline void Cba_NtkPrintDistribFromSign( word sss, int * s, int * s0, int * s1 ) { *s1 = (int)(sss >> 42); *s0 = (int)(sss >> 21) & 0x1FFFFF; *s = (int)sss & 0x1FFFFF; } static inline void Cba_NtkPrintDistribAddOne( Vec_Ptr_t * vTypes, Vec_Ptr_t * vOccurs, int Type, word Sign ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, Type ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, Type ); word Entry; int i; Vec_WrdForEachEntry( vType, Entry, i ) if ( Entry == Sign ) { Vec_WrdAddToEntry( vOccur, i, 1 ); return; } Vec_WrdPush( vType, Sign ); Vec_WrdPush( vOccur, 1 ); } void Cba_NtkPrintDistribSortOne( Vec_Ptr_t * vTypes, Vec_Ptr_t * vOccurs, int Type ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, Type ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, Type ); Vec_WrdSelectSortCost2( Vec_WrdArray(vType), Vec_WrdSize(vType), Vec_WrdArray(vOccur) ); Vec_WrdReverseOrder( vType ); Vec_WrdReverseOrder( vOccur ); } void Cba_NtkPrintDistrib( Cba_Ntk_t * p, int fVerbose ) { Vec_Ptr_t * vTypes, * vOccurs; Vec_Int_t * vAnds = Vec_IntStart( CBA_BOX_LAST ); int iRnObj = -1, nCountRange = 0; int i, k, s, s0, s1; word Sign; Cba_ObjType_t Type; char * pTypeNames[CBA_BOX_LAST]; Cba_ManCreatePrimMap( pTypeNames ); // allocate statistics arrays vTypes = Vec_PtrStart( CBA_BOX_LAST ); vOccurs = Vec_PtrStart( CBA_BOX_LAST ); for ( i = 0; i < CBA_BOX_LAST; i++ ) Vec_PtrWriteEntry( vTypes, i, Vec_WrdAlloc(16) ); for ( i = 0; i < CBA_BOX_LAST; i++ ) Vec_PtrWriteEntry( vOccurs, i, Vec_WrdAlloc(16) ); // add nodes Cba_NtkForEachObj( p, i ) { // char * pName = Cba_ObjName(p, i); Type = Cba_ObjType( p, i ); if ( Cba_ObjSign(p, i) > 0x1FFFFF ) printf( "Object %6d has range %d, which is reduced to %d in the statistics.\n", i, Cba_ObjRangeSize(p, i), Cba_ObjRangeSize(p, i) & 0xFFFFF ); if ( Cba_ObjLeft(p, i) && Cba_ObjRight(p, i) ) { if ( iRnObj == -1 ) iRnObj = 1; nCountRange++; } // 0-input types if ( Cba_ObjIsPi(p, i) || (Type == CBA_BOX_BUF && Cba_FonIsConst(Cba_ObjFinFon(p, i, 0))) || Type == CBA_BOX_CONCAT ) Sign = Cba_NtkPrintDistribMakeSign( Cba_ObjSign(p, i), 0, 0 ); // 1-input types else if ( Cba_TypeIsUnary(Type) ) Sign = Cba_NtkPrintDistribMakeSign( Cba_ObjSign(p, i), Cba_ObjSign(p, Cba_ObjFinFon(p, i, 0)), 0 ); // 2-input types (including MUX) else if ( Cba_ObjFinNum(p, i) == 1 ) Sign = Cba_NtkPrintDistribMakeSign( Cba_ObjSign(p, i), Cba_ObjSign(p, Cba_ObjFinFon(p, i, 0)), 0 ); else { assert( Cba_ObjFinNum(p, i) >= 2 ); Sign = Cba_NtkPrintDistribMakeSign( Cba_ObjSign(p, i), Cba_ObjSign(p, Cba_ObjFinFon(p, i, 0)), Cba_ObjSign(p, Cba_ObjFinFon(p, i, 1)) ); } // add to storage Cba_NtkPrintDistribAddOne( vTypes, vOccurs, Type, Sign ); // count the number of AIG nodes if ( Type == CBA_BOX_MUX ) Vec_IntAddToEntry( vAnds, CBA_BOX_MUX, 3 * Cba_ObjRangeSize(p, i) * (Cba_ObjFinNum(p, i) - 2) ); else if ( Type == CBA_BOX_SHIR ) Vec_IntAddToEntry( vAnds, CBA_BOX_SHIR, Abc_MinInt(Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)), Abc_Base2Log(Cba_ObjRangeSize(p, i))) * 3 ); else if ( Type == CBA_BOX_SHIRA ) Vec_IntAddToEntry( vAnds, CBA_BOX_SHIRA, Cba_ObjRangeSize(p, i) * Abc_MinInt(Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)), Abc_Base2Log(Cba_ObjRangeSize(p, i))) * 3 ); else if ( Type == CBA_BOX_SHIL ) Vec_IntAddToEntry( vAnds, CBA_BOX_SHIL, Cba_ObjRangeSize(p, i) * Abc_MinInt(Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)), Abc_Base2Log(Cba_ObjRangeSize(p, i))) * 3 ); else if ( Type == CBA_BOX_SHILA ) Vec_IntAddToEntry( vAnds, CBA_BOX_SHILA, Cba_ObjRangeSize(p, i) * Abc_MinInt(Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)), Abc_Base2Log(Cba_ObjRangeSize(p, i))) * 3 ); else if ( Type == CBA_BOX_ROTR ) Vec_IntAddToEntry( vAnds, CBA_BOX_ROTR, Cba_ObjRangeSize(p, i) * Abc_MinInt(Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)), Abc_Base2Log(Cba_ObjRangeSize(p, i))) * 3 ); else if ( Type == CBA_BOX_ROTL ) Vec_IntAddToEntry( vAnds, CBA_BOX_ROTL, Cba_ObjRangeSize(p, i) * Abc_MinInt(Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)), Abc_Base2Log(Cba_ObjRangeSize(p, i))) * 3 ); else if ( Type == CBA_BOX_INV ) Vec_IntAddToEntry( vAnds, CBA_BOX_INV, 0 ); else if ( Type == CBA_BOX_AND ) Vec_IntAddToEntry( vAnds, CBA_BOX_AND, Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) ); else if ( Type == CBA_BOX_OR ) Vec_IntAddToEntry( vAnds, CBA_BOX_OR, Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) ); else if ( Type == CBA_BOX_XOR ) Vec_IntAddToEntry( vAnds, CBA_BOX_XOR, 3 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) ); else if ( Type == CBA_BOX_SLICE ) Vec_IntAddToEntry( vAnds, CBA_BOX_SLICE, 0 ); else if ( Type == CBA_BOX_CONCAT ) Vec_IntAddToEntry( vAnds, CBA_BOX_CONCAT, 0 ); else if ( Type == CBA_BOX_LNOT ) Vec_IntAddToEntry( vAnds, CBA_BOX_LNOT, Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 1 ); else if ( Type == CBA_BOX_LAND ) Vec_IntAddToEntry( vAnds, CBA_BOX_LAND, Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) + Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 1)) - 1 ); else if ( Type == CBA_BOX_LOR ) Vec_IntAddToEntry( vAnds, CBA_BOX_LOR, Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) + Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 1)) - 1 ); else if ( Type == CBA_BOX_LXOR ) Vec_IntAddToEntry( vAnds, CBA_BOX_LXOR, Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) + Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 1)) + 1 ); else if ( Type == CBA_BOX_EQU ) Vec_IntAddToEntry( vAnds, CBA_BOX_EQU, 4 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 1 ); else if ( Type == CBA_BOX_NEQU ) Vec_IntAddToEntry( vAnds, CBA_BOX_NEQU, 4 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 1 ); else if ( Type == CBA_BOX_LTHAN ) Vec_IntAddToEntry( vAnds, CBA_BOX_LTHAN, 6 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 6 ); else if ( Type == CBA_BOX_MTHAN ) Vec_IntAddToEntry( vAnds, CBA_BOX_MTHAN, 6 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 6 ); else if ( Type == CBA_BOX_LETHAN ) Vec_IntAddToEntry( vAnds, CBA_BOX_LETHAN, 6 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 6 ); else if ( Type == CBA_BOX_METHAN ) Vec_IntAddToEntry( vAnds, CBA_BOX_METHAN, 6 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 6 ); else if ( Type == CBA_BOX_RAND ) Vec_IntAddToEntry( vAnds, CBA_BOX_RAND, Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 1 ); else if ( Type == CBA_BOX_ROR ) Vec_IntAddToEntry( vAnds, CBA_BOX_ROR, Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 1 ); else if ( Type == CBA_BOX_RXOR ) Vec_IntAddToEntry( vAnds, CBA_BOX_RXOR, 3 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 3 ); else if ( Type == CBA_BOX_ADD ) Vec_IntAddToEntry( vAnds, CBA_BOX_ADD, 9 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) ); else if ( Type == CBA_BOX_SUB ) Vec_IntAddToEntry( vAnds, CBA_BOX_SUB, 9 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) ); else if ( Type == CBA_BOX_MUL ) Vec_IntAddToEntry( vAnds, CBA_BOX_MUL, 9 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 1)) ); else if ( Type == CBA_BOX_DIV ) Vec_IntAddToEntry( vAnds, CBA_BOX_DIV, 13 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 19 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) + 10 ); else if ( Type == CBA_BOX_MOD ) Vec_IntAddToEntry( vAnds, CBA_BOX_MOD, 13 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 7 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) - 2 ); else if ( Type == CBA_BOX_POW ) Vec_IntAddToEntry( vAnds, CBA_BOX_POW, 10 * (int)pow(Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)),Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0))) ); else if ( Type == CBA_BOX_MIN ) Vec_IntAddToEntry( vAnds, CBA_BOX_MIN, 4 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) ); else if ( Type == CBA_BOX_SQRT ) Vec_IntAddToEntry( vAnds, CBA_BOX_SQRT, 11 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) / 8 + 5 * Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)) / 2 - 5 ); } if ( nCountRange ) { printf( "Warning: %d objects of the design have non-zero-based ranges.\n", nCountRange ); printf( "In particular, object %6d with name \"%s\" has range %d=[%d:%d]\n", iRnObj, Cba_FonNameStr(p, Cba_ObjFon0(p, iRnObj)), Cba_ObjRangeSize(p, iRnObj), Cba_ObjLeft(p, iRnObj), Cba_ObjRight(p, iRnObj) ); } // print by occurrence printf( "ID : name occurrence and2 (occurrence)=. ...\n" ); for ( i = 0; i < CBA_BOX_LAST; i++ ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, i ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, i ); if ( p->pDesign->nObjs[i] == 0 ) continue; printf( "%2d : %-8s %6d%8d ", i, pTypeNames[i], p->pDesign->nObjs[i], Vec_IntEntry(vAnds, i) ); // sort by occurence Cba_NtkPrintDistribSortOne( vTypes, vOccurs, i ); Vec_WrdForEachEntry( vType, Sign, k ) { Cba_NtkPrintDistribFromSign( Sign, &s, &s0, &s1 ); if ( ((k % 6) == 5 && s1) || ((k % 8) == 7 && !s1) ) printf( "\n " ); printf( "(%d)", (int)Vec_WrdEntry( vOccur, k ) ); printf( "%s%d", Abc_LitIsCompl(s)?"-":"", Abc_Lit2Var(s) ); if ( s0 ) printf( "=%s%d", Abc_LitIsCompl(s0)?"-":"", Abc_Lit2Var(s0) ); if ( s1 ) printf( ".%s%d", Abc_LitIsCompl(s1)?"-":"", Abc_Lit2Var(s1) ); printf( " " ); } printf( "\n" ); } Vec_VecFree( (Vec_Vec_t *)vTypes ); Vec_VecFree( (Vec_Vec_t *)vOccurs ); Vec_IntFree( vAnds ); } void Cba_NtkPrintNodes( Cba_Ntk_t * p, int Type ) { int i, iFon0, iFon1, Counter = 0; char * pTypeNames[CBA_BOX_LAST]; Cba_ManCreatePrimMap( pTypeNames ); printf( "Operation %s\n", pTypeNames[Type] ); Cba_NtkForEachObj( p, i ) { if ( (int)Type != Type ) continue; iFon0 = Cba_ObjFinFon(p, i, 0); iFon1 = Cba_ObjFinFon(p, i, 1); printf( "%8d :", Counter++ ); printf( "%8d : ", i ); printf( "%3d%s = ", Cba_ObjRangeSize(p, i), Cba_ObjSigned(p, i) ? "s" : " " ); printf( "%3d%s %s ", Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 0)), Cba_ObjSigned(p, iFon0) ? "s" : " ", pTypeNames[Type] ); printf( "%3d%s ", Cba_ObjRangeSize(p, Cba_ObjFinFon(p, i, 1)), Cba_ObjSigned(p, iFon1) ? "s" : " " ); printf( " : " ); printf( "%-12s = ", Cba_ObjNameStr(p, i) ); printf( "%-12s %s ", Cba_FonIsConst(iFon0) ? Cba_NtkConst(p, Cba_FonConst(iFon0)) : Cba_FonNameStr(p, iFon0), pTypeNames[Type] ); printf( "%-12s ", Cba_FonIsConst(iFon1) ? Cba_NtkConst(p, Cba_FonConst(iFon1)) : Cba_FonNameStr(p, iFon1) ); printf( "\n" ); } } void Cba_NtkPrintStatsFull( Cba_Ntk_t * p, int fDistrib, int fVerbose ) { int i; char * pTypeNames[CBA_BOX_LAST]; Cba_ManCreatePrimMap( pTypeNames ); printf( "%-20s : ", Cba_NtkName(p) ); printf( "PI = %4d ", Cba_NtkPiNum(p) ); printf( "PO = %4d ", Cba_NtkPoNum(p) ); printf( "FF = %4d ", Cba_NtkBoxSeqNum(p) ); printf( "Obj = %6d ", Cba_NtkObjNum(p) ); printf( "Mem = %.3f MB", 1.0*Cba_NtkMemory(p)/(1<<20) ); printf( "\n" ); if ( fDistrib ) { Cba_NtkPrintDistrib( p, fVerbose ); return; } if ( !fVerbose ) return; printf( "Node type statistics:\n" ); for ( i = 1; i < CBA_BOX_LAST; i++ ) { if ( !p->pDesign->nObjs[i] ) continue; if ( p->pDesign->nAnds[0] && p->pDesign->nAnds[i] ) printf( "%2d : %-8s %6d %7.2f %%\n", i, pTypeNames[i], p->pDesign->nObjs[i], 100.0*p->pDesign->nAnds[i]/p->pDesign->nAnds[0] ); else printf( "%2d : %-8s %6d\n", i, pTypeNames[i], p->pDesign->nObjs[i] ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cba_NtkCollectDistrib( Cba_Ntk_t * p, int * pCounts, int * pUserCounts ) { int i; Cba_NtkForEachBox( p, i ) if ( Cba_ObjIsBoxUser(p, i) ) pUserCounts[Cba_ObjNtkId(p, i)]++; else pCounts[Cba_ObjType(p, i)]++; } void Cba_NtkPrintDistribStat( Cba_Ntk_t * p, int * pCounts, int * pUserCounts ) { Cba_Ntk_t * pNtk; int i; printf( "Primitives (%d):\n", Cba_NtkBoxPrimNum(p) ); for ( i = 0; i < CBA_BOX_LAST; i++ ) if ( pCounts[i] ) printf( "%-20s = %5d\n", Cba_NtkTypeName(p, i), pCounts[i] ); printf( "User hierarchy (%d):\n", Cba_NtkBoxUserNum(p) ); Cba_ManForEachNtk( p->pDesign, pNtk, i ) if ( pUserCounts[i] ) printf( "%-20s = %5d\n", Cba_NtkName(pNtk), pUserCounts[i] ); } void Cba_NtkPrintDistribOld( Cba_Ntk_t * p ) { int pCounts[CBA_BOX_LAST] = {0}; int * pUserCounts = ABC_CALLOC( int, Cba_ManNtkNum(p->pDesign) + 1 ); Cba_ManCreatePrimMap( p->pDesign->pTypeNames ); Cba_NtkCollectDistrib( p, pCounts, pUserCounts ); Cba_NtkPrintDistribStat( p, pCounts, pUserCounts ); ABC_FREE( pUserCounts ); } void Cba_ManPrintDistribStat( Cba_Man_t * p, int * pCounts, int * pUserCounts ) { Cba_Ntk_t * pNtk = Cba_ManRoot(p); int i; printf( "Primitives:\n" ); for ( i = 0; i < CBA_BOX_LAST; i++ ) if ( pCounts[i] ) printf( "%-20s = %5d\n", Cba_NtkTypeName(pNtk, i), pCounts[i] ); printf( "User hierarchy:\n" ); Cba_ManForEachNtk( p, pNtk, i ) if ( pUserCounts[i] ) printf( "%-20s = %5d\n", Cba_NtkName(pNtk), pUserCounts[i] ); } void Cba_ManPrintDistrib( Cba_Man_t * p ) { Cba_Ntk_t * pNtk; int i; int pCounts[CBA_BOX_LAST] = {0}; int * pUserCounts = ABC_CALLOC( int, Cba_ManNtkNum(p) + 1 ); Cba_ManCreatePrimMap( p->pTypeNames ); Cba_ManForEachNtk( p, pNtk, i ) Cba_NtkCollectDistrib( pNtk, pCounts, pUserCounts ); Cba_ManPrintDistribStat( p, pCounts, pUserCounts ); ABC_FREE( pUserCounts ); } /**Function************************************************************* Synopsis [Order objects by box type and then by name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // compares two numbers with the first mismatching char in i-th position static inline int Cba_CharIsDigit( char c ) { return c >= '0' && c <= '9'; } int Cba_StrCmpInt( char * p1, char * p2, int i ) { // check if one of the mismatching chars is a digit if ( Cba_CharIsDigit(p1[i]) || Cba_CharIsDigit(p2[i]) ) { // if previous (equal) char was a digit or if this is first digit on both sides, scroll back if ( (i > 0 && Cba_CharIsDigit(p1[i-1])) || (Cba_CharIsDigit(p1[i]) && Cba_CharIsDigit(p2[i])) ) { int Num1, Num2; // find the first digit for ( --i; i >= 0; i-- ) if ( !Cba_CharIsDigit(p1[i]) ) break; i++; // current char is digit assert( Cba_CharIsDigit(p1[i]) ); assert( Cba_CharIsDigit(p2[i]) ); // previous char does not exist or is not a digit assert( i == 0 || !Cba_CharIsDigit(p1[i-1]) ); assert( i == 0 || !Cba_CharIsDigit(p2[i-1]) ); // compare numbers Num1 = atoi( p1 + i ); Num2 = atoi( p2 + i ); if ( Num1 < Num2 ) return -1; if ( Num1 > Num2 ) return 1; assert( 0 ); return 0; } } // compare as usual if ( p1[i] < p2[i] ) return -1; if ( p1[i] > p2[i] ) return 1; assert( 0 ); return 0; } int Cba_StrCmp( char ** pp1, char ** pp2 ) { char * p1 = *pp1; char * p2 = *pp2; int i; for ( i = 0; p1[i] && p2[i]; i++ ) if ( p1[i] != p2[i] ) return Cba_StrCmpInt( p1, p2, i ); assert( !p1[i] || !p2[i] ); return Cba_StrCmpInt( p1, p2, i ); } void Cba_NtkObjOrder( Cba_Ntk_t * p, Vec_Int_t * vObjs, Vec_Int_t * vNameIds ) { char Buffer[1000], * pName; Vec_Ptr_t * vNames; int i, iObj; if ( Vec_IntSize(vObjs) < 2 ) return; vNames = Vec_PtrAlloc( Vec_IntSize(vObjs) ); Vec_IntForEachEntry( vObjs, iObj, i ) { char * pTypeName = Cba_NtkTypeName( p, Cba_ObjType(p, iObj) ); char * pInstName = vNameIds ? Cba_NtkStr(p, Vec_IntEntry(vNameIds, i)) : Cba_ObjNameStr(p, iObj); sprintf( Buffer, "%s_%s_%d", pTypeName, pInstName, iObj ); Vec_PtrPush( vNames, Abc_UtilStrsav(Buffer) ); } // print before // Vec_PtrForEachEntry( char *, vNames, pName, i ) // printf( "%s \n", pName ); // printf( "\n" ); // do the sorting Vec_PtrSort( vNames, (int (*)(void))Cba_StrCmp ); // print after // Vec_PtrForEachEntry( char *, vNames, pName, i ) // printf( "%s \n", pName ); // printf( "\n" ); // reload in a new order Vec_IntClear( vObjs ); Vec_PtrForEachEntry( char *, vNames, pName, i ) Vec_IntPush( vObjs, atoi(strrchr(pName, '_')+1) ); Vec_PtrFreeFree( vNames ); } /**Function************************************************************* Synopsis [Returns the number of CI fons.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cba_NtkCiFonNum( Cba_Ntk_t * p ) { int i, iObj, Count = Cba_NtkPiNum(p); Cba_NtkForEachBoxSeq( p, iObj, i ) Count += Cba_ObjFonNum(p, iObj); return Count; } int Cba_NtkCoFinNum( Cba_Ntk_t * p ) { int i, iObj, Count = Cba_NtkPoNum(p); Cba_NtkForEachBoxSeq( p, iObj, i ) Count += Cba_ObjFinNum(p, iObj); return Count; } /**Function************************************************************* Synopsis [Returns 1 if the manager is in the topo order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cba_NtkIsTopoOrder( Cba_Ntk_t * p ) { int i, k, iObj, iFin, iFanin, fTopo = 1; Vec_Bit_t * vVisited = Vec_BitStart( Cba_NtkObjNum(p) + 1 ); // mark PIs and seq objects Cba_NtkForEachPi( p, iObj, i ) Vec_BitWriteEntry( vVisited, iObj, 1 ); Cba_NtkForEachBoxSeq( p, iObj, i ) Vec_BitWriteEntry( vVisited, iObj, 1 ); // visit combinational nodes Cba_NtkForEachBox( p, iObj ) if ( !Cba_ObjIsSeq(p, iObj) ) { Cba_ObjForEachFinFaninReal( p, iObj, iFin, iFanin, k ) if ( !Vec_BitEntry(vVisited, iFanin) ) fTopo = 0; if ( !fTopo ) break; Vec_BitWriteEntry( vVisited, iObj, 1 ); } // visit POs and seq objects if ( fTopo ) Cba_NtkForEachPo( p, iObj, i ) { Cba_ObjForEachFinFaninReal( p, iObj, iFin, iFanin, k ) if ( !Vec_BitEntry(vVisited, iFanin) ) fTopo = 0; if ( !fTopo ) break; } if ( fTopo ) Cba_NtkForEachBoxSeq( p, iObj, i ) { Cba_ObjForEachFinFaninReal( p, iObj, iFin, iFanin, k ) if ( !Vec_BitEntry(vVisited, iFanin) ) fTopo = 0; if ( !fTopo ) break; } Vec_BitFree( vVisited ); return fTopo; } int Cba_ManIsTopoOrder( Cba_Man_t * p ) { Cba_Ntk_t * pNtk; int i; Cba_ManForEachNtk( p, pNtk, i ) if ( !Cba_NtkIsTopoOrder(pNtk) ) return 0; return 1; } /**Function************************************************************* Synopsis [Collects user boxes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cba_NtkCheckComboLoop_rec( Cba_Ntk_t * p, int iObj ) { int k, iFin, iFanin; if ( Cba_ObjIsPi(p, iObj) ) return 1; if ( Cba_ObjCopy(p, iObj) == 1 ) // visited return 1; if ( Cba_ObjCopy(p, iObj) == 0 ) // loop return 0; Cba_ObjSetCopy( p, iObj, 0 ); Cba_ObjForEachFinFaninReal( p, iObj, iFin, iFanin, k ) if ( !Cba_ObjIsSeq(p, iFanin) ) if ( !Cba_NtkCheckComboLoop_rec( p, iFanin ) ) return 0; //Cba_ObjSetCopy( p, iObj, 1 ); Vec_IntSetEntry( &p->vObjCopy, iObj, 1 ); return 1; } int Cba_NtkCheckComboLoop( Cba_Ntk_t * p ) { int iObj; Cba_NtkCleanObjCopies( p ); // -1 = not visited; 0 = on the path; 1 = finished Cba_NtkForEachBox( p, iObj ) if ( !Cba_ObjIsSeq(p, iObj) ) if ( !Cba_NtkCheckComboLoop_rec( p, iObj ) ) { printf( "Cyclic dependency of user boxes is detected.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Find one missing object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cba_NtkFindMissing( Vec_Int_t * vObjs, int nObjs ) { Vec_Int_t * vMap = Vec_IntStartFull( nObjs + 1 ); int i, iObj; Vec_IntForEachEntry( vObjs, iObj, i ) Vec_IntWriteEntry( vMap, iObj, i ); Vec_IntForEachEntryStart( vMap, i, iObj, 1 ) if ( i == -1 ) { Vec_IntFree( vMap ); return iObj; } Vec_IntFree( vMap ); return -1; } /**Function************************************************************* Synopsis [Collect nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cba_NtkCollectDfs_rec( Cba_Ntk_t * p, int iObj, Vec_Int_t * vObjs ) { int iFin, iFanin, k; if ( !Cba_ObjCopy(p, iObj) ) return; Cba_ObjSetCopy( p, iObj, 0 ); Cba_ObjForEachFinFaninReal( p, iObj, iFin, iFanin, k ) Cba_NtkCollectDfs_rec( p, iFanin, vObjs ); Vec_IntPush( vObjs, iObj ); } Vec_Int_t * Cba_NtkCollectDfs( Cba_Ntk_t * p ) { int i, k, iObj, iFin, iFanin; Vec_Int_t * vObjs = Vec_IntAlloc( Cba_NtkObjNum(p) ); // collect PIs and seq boxes Cba_NtkForEachPi( p, iObj, i ) Vec_IntPush( vObjs, iObj ); Cba_NtkForEachBoxSeq( p, iObj, i ) Vec_IntPush( vObjs, iObj ); // prepare leaves Cba_NtkCleanObjCopies( p ); Vec_IntForEachEntry( vObjs, iObj, i ) Cba_ObjSetCopy( p, iObj, 0 ); // collect internal Cba_NtkForEachPo( p, iObj, i ) Cba_ObjForEachFinFaninReal( p, iObj, iFin, iFanin, k ) Cba_NtkCollectDfs_rec( p, iFanin, vObjs ); Cba_NtkForEachBoxSeq( p, iObj, i ) Cba_ObjForEachFinFaninReal( p, iObj, iFin, iFanin, k ) Cba_NtkCollectDfs_rec( p, iFanin, vObjs ); // collect POs Cba_NtkForEachPo( p, iObj, i ) Vec_IntPush( vObjs, iObj ); assert( Vec_IntSize(vObjs) <= Cba_NtkObjNum(p) ); if ( Vec_IntSize(vObjs) != Cba_NtkObjNum(p) && !Abc_FrameReadFlag("silentmode") ) { int iObj = Cba_NtkFindMissing( vObjs, Cba_NtkObjNum(p) ); printf( "Warning: DSF ordering for module \"%s\" collected %d out of %d objects.\n", Cba_NtkName(p), Vec_IntSize(vObjs), Cba_NtkObjNum(p) ); printf( " For example, object %d with name \"%s\" is not reachable from outputs.\n", iObj, iObj > 0 ? Cba_FonNameStr( p, Cba_ObjFon0(p, iObj) ) : "" ); } return vObjs; } /**Function************************************************************* Synopsis [Count number of objects after collapsing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cba_ManGetClpStats_rec( Cba_Ntk_t * p, int * pCountN, int * pCountI, int * pCountO ) { int iObj, Id = Cba_NtkId(p); if ( pCountN[Id] >= 0 ) return; pCountN[Id] = pCountI[Id] = pCountO[Id] = 0; Cba_NtkForEachObj( p, iObj ) if ( Cba_ObjIsBoxPrim(p, iObj) ) { pCountN[Id] += 1; pCountI[Id] += Cba_ObjFinNum(p, iObj); pCountO[Id] += Cba_ObjFonNum(p, iObj); } else if ( Cba_ObjIsBoxUser(p, iObj) ) { int NtkId = Cba_ObjNtkId(p, iObj); Cba_ManGetClpStats_rec( Cba_ObjNtk(p, iObj), pCountN, pCountI, pCountO ); pCountN[Id] += pCountN[NtkId] + Cba_ObjFonNum(p, iObj); pCountI[Id] += pCountI[NtkId] + Cba_ObjFonNum(p, iObj); pCountO[Id] += pCountO[NtkId] + Cba_ObjFonNum(p, iObj); } } void Cba_ManGetClpStats( Cba_Man_t * p, int * nObjs, int * nFins, int * nFons ) { int * pCountN = ABC_FALLOC( int, Cba_ManNtkNum(p) + 1 ); int * pCountI = ABC_FALLOC( int, Cba_ManNtkNum(p) + 1 ); int * pCountO = ABC_FALLOC( int, Cba_ManNtkNum(p) + 1 ); Cba_Ntk_t * pRoot = Cba_ManRoot(p); Cba_ManGetClpStats_rec( pRoot, pCountN, pCountI, pCountO ); *nObjs = Cba_NtkPioNum(pRoot) + pCountN[Cba_NtkId(pRoot)]; *nFins = Cba_NtkPoNum(pRoot) + pCountI[Cba_NtkId(pRoot)]; *nFons = Cba_NtkPiNum(pRoot) + pCountO[Cba_NtkId(pRoot)]; ABC_FREE( pCountN ); ABC_FREE( pCountI ); ABC_FREE( pCountO ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cba_NtkCollapse_rec( Cba_Ntk_t * pNew, Cba_Ntk_t * p, Vec_Int_t * vSigs ) { int i, iObj, iObjNew, iFin, iFon; Cba_NtkCleanObjCopies( p ); Cba_NtkCleanFonCopies( p ); // set PI copies assert( Vec_IntSize(vSigs) == Cba_NtkPiNum(p) ); Cba_NtkForEachPiFon( p, iObj, iFon, i ) Cba_FonSetCopy( p, iFon, Vec_IntEntry(vSigs, i) ); // duplicate primitives and create buffers for user instances Cba_NtkForEachObj( p, iObj ) if ( Cba_ObjIsBoxPrim( p, iObj ) ) { iObjNew = Cba_ObjDup( pNew, p, iObj ); Cba_ObjForEachFon( p, iObj, iFon, i ) Cba_FonSetCopy( p, iFon, Cba_ObjFon(pNew, iObjNew, i) ); if ( Cba_ObjAttr(p, iObj) ) Cba_ObjSetAttrs( pNew, iObjNew, Cba_ObjAttrArray(p, iObj), Cba_ObjAttrSize(p, iObj) ); } else if ( Cba_ObjIsBoxUser( p, iObj ) ) { Cba_ObjForEachFon( p, iObj, iFon, i ) { iObjNew = Cba_ObjAlloc( pNew, CBA_BOX_BUF, 1, 1 ); Cba_FonSetCopy( p, iFon, Cba_ObjFon0(pNew, iObjNew) ); } } // connect primitives and collapse user instances Cba_NtkForEachObj( p, iObj ) if ( Cba_ObjIsBoxPrim( p, iObj ) ) { iObjNew = Cba_ObjCopy( p, iObj ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i ) Cba_ObjSetFinFon( pNew, iObjNew, i, Cba_FonCopy(p, iFon) ); } else if ( Cba_ObjIsBoxUser( p, iObj ) ) { Vec_IntClear( vSigs ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i ) Vec_IntPush( vSigs, Cba_FonCopy(p, iFon) ); assert( Vec_IntSize(vSigs) == Cba_ObjFinNum(p, iObj) ); Cba_NtkCollapse_rec( pNew, Cba_ObjNtk(p, iObj), vSigs ); assert( Vec_IntSize(vSigs) == Cba_ObjFonNum(p, iObj) ); Cba_ObjForEachFon( p, iObj, iFon, i ) { iObjNew = Cba_FonObj( pNew, Cba_FonCopy(p, iFon) ); // buffer Cba_ObjSetFinFon( pNew, iObjNew, 0, Vec_IntEntry(vSigs, i) ); } } // collect POs Vec_IntClear( vSigs ); Cba_NtkForEachPoDriverFon( p, iObj, iFon, i ) Vec_IntPush( vSigs, Cba_FonCopy(p, iFon) ); } Cba_Man_t * Cba_ManCollapse( Cba_Man_t * p ) { Cba_Man_t * pNew = Cba_ManAlloc( p->pSpec, 1, Abc_NamRef(p->pStrs), Abc_NamRef(p->pFuns), Abc_NamStart(100, 24), Hash_IntManRef(p->vHash) ); Cba_Ntk_t * pRoot = Cba_ManRoot( p ), * pRootNew; Vec_Int_t * vSigs = Vec_IntAlloc( 1000 ); int i, iObj, iObjNew, iFon, nObjs = 0, nFins = 0, nFons = 0; Cba_ManDupTypeNames( pNew, p ); Cba_ManGetClpStats( p, &nObjs, &nFins, &nFons ); pRootNew = Cba_NtkAlloc( pNew, Cba_NtkNameId(pRoot), Cba_NtkPiNum(pRoot), Cba_NtkPoNum(pRoot), nObjs, nFins, nFons ); Cba_NtkAdd( pNew, pRootNew ); if ( Cba_NtkHasObjNames(pRoot) ) Cba_NtkCleanObjNames( pRootNew ); if ( Cba_NtkHasFonNames(pRoot) ) Cba_NtkCleanFonNames( pRootNew ); if ( Cba_NtkHasObjAttrs(pRoot) ) Cba_NtkCleanObjAttrs( pRootNew ); if ( Cba_ObjAttr(pRoot, 0) ) Cba_ObjSetAttrs( pRootNew, 0, Cba_ObjAttrArray(pRoot, 0), Cba_ObjAttrSize(pRoot, 0) ); Cba_NtkCleanObjCopies( pRoot ); Cba_NtkForEachPiFon( pRoot, iObj, iFon, i ) { iObjNew = Cba_ObjDup( pRootNew, pRoot, iObj ); Vec_IntPush( vSigs, Cba_ObjFon0(pRootNew, iObjNew) ); if ( Cba_NtkHasObjNames(pRoot) ) Cba_ObjSetName( pRootNew, iObjNew, Cba_ObjName(pRoot, iObj) ); if ( Cba_NtkHasFonNames(pRoot) ) Cba_FonSetName( pRootNew, Cba_ObjFon0(pRootNew, iObjNew), Cba_FonName(pRoot, iFon) ); if ( Cba_ObjAttr(pRoot, iObj) ) Cba_ObjSetAttrs( pRootNew, iObjNew, Cba_ObjAttrArray(pRoot, iObj), Cba_ObjAttrSize(pRoot, iObj) ); } assert( Vec_IntSize(vSigs) == Cba_NtkPiNum(pRoot) ); Cba_NtkCollapse_rec( pRootNew, pRoot, vSigs ); assert( Vec_IntSize(vSigs) == Cba_NtkPoNum(pRoot) ); Cba_NtkForEachPoDriverFon( pRoot, iObj, iFon, i ) { iObjNew = Cba_ObjDup( pRootNew, pRoot, iObj ); Cba_ObjSetFinFon( pRootNew, iObjNew, 0, Vec_IntEntry(vSigs, i) ); if ( Cba_NtkHasObjNames(pRoot) ) Cba_ObjSetName( pRootNew, iObjNew, Cba_ObjName(pRoot, iObj) ); if ( Cba_NtkHasFonNames(pRoot) ) Cba_FonSetName( pRootNew, Vec_IntEntry(vSigs, i), Cba_FonName(pRoot, iFon) ); if ( Cba_ObjAttr(pRoot, iObj) ) Cba_ObjSetAttrs( pRootNew, iObjNew, Cba_ObjAttrArray(pRoot, iObj), Cba_ObjAttrSize(pRoot, iObj) ); } Vec_IntFree( vSigs ); assert( Cba_NtkObjNum(pRootNew) == Cba_NtkObjNumAlloc(pRootNew) ); assert( Cba_NtkFinNum(pRootNew) == Cba_NtkFinNumAlloc(pRootNew) ); assert( Cba_NtkFonNum(pRootNew) == Cba_NtkFonNumAlloc(pRootNew) ); // create internal node names Cba_NtkMissingFonNames( pRootNew, "m" ); //Cba_NtkPrepareSeq( pRootNew ); return pNew; } /**Function************************************************************* Synopsis [Performs the reverse of collapsing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Cba_NtkCollectInFons( Cba_Ntk_t * p, Vec_Int_t * vObjs ) { Vec_Int_t * vFons = Vec_IntAlloc( 100 ); Vec_Bit_t * vVisFons = Vec_BitStart( Cba_NtkFonNum(p) + 1 ); int i, k, iObj, iFin, iFon, Entry; // mark fanin fons Vec_IntForEachEntry( vObjs, iObj, i ) Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) if ( iFon > 0 ) Vec_BitWriteEntry( vVisFons, iFon, 1 ); // unmark internal fons Vec_IntForEachEntry( vObjs, iObj, i ) Cba_ObjForEachFon( p, iObj, iFon, k ) Vec_BitWriteEntry( vVisFons, iFon, 0 ); // collect fons Vec_BitForEachEntry( vVisFons, Entry, iFon ) if ( Entry ) Vec_IntPush( vFons, iFon ); Vec_BitFree( vVisFons ); return vFons; } Vec_Int_t * Cba_NtkCollectOutFons( Cba_Ntk_t * p, Vec_Int_t * vObjs ) { Vec_Int_t * vFons = Vec_IntAlloc( 100 ); Vec_Bit_t * vMapObjs = Vec_BitStart( Cba_NtkObjNum(p) + 1 ); Vec_Bit_t * vVisFons = Vec_BitStart( Cba_NtkFonNum(p) + 1 ); int i, k, iObj, iFin, iFon; // map objects Vec_IntForEachEntry( vObjs, iObj, i ) Vec_BitWriteEntry( vMapObjs, iObj, 1 ); // mark those used by non-objects Cba_NtkForEachObj( p, iObj ) if ( !Vec_BitEntry(vMapObjs, iObj) ) Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) if ( iFon > 0 ) Vec_BitWriteEntry( vVisFons, iFon, 1 ); // collect pointed fons among those in objects Vec_IntForEachEntry( vObjs, iObj, i ) Cba_ObjForEachFon( p, iObj, iFon, k ) if ( Vec_BitEntry(vVisFons, iFon) ) Vec_IntPush( vFons, iFon ); Vec_BitFree( vMapObjs ); Vec_BitFree( vVisFons ); return vFons; } void Cba_NtkCollectGroupStats( Cba_Ntk_t * p, Vec_Int_t * vObjs, int * pnFins, int * pnFons ) { int i, iObj, nFins = 0, nFons = 0; Vec_IntForEachEntry( vObjs, iObj, i ) { nFins += Cba_ObjFinNum(p, iObj); nFons += Cba_ObjFonNum(p, iObj); } *pnFins = nFins; *pnFons = nFons; } void Cba_ManExtractGroupInt( Cba_Ntk_t * pNew, Cba_Ntk_t * p, Vec_Int_t * vObjs, Vec_Int_t * vFonIns, Vec_Int_t * vFonOuts ) { int i, k, iObj, iObjNew, iFin, iFon; Cba_NtkCleanObjCopies( p ); Cba_NtkCleanFonCopies( p ); // create inputs and map fons Vec_IntForEachEntry( vFonIns, iFon, i ) { iObjNew = Cba_ObjAlloc( pNew, CBA_OBJ_PI, 0, 1 ); Cba_FonSetCopy( p, iFon, Cba_ObjFon0(pNew, iObjNew) ); if ( Cba_NtkHasObjNames(p) ) Cba_ObjSetName( pNew, iObjNew, Cba_ObjName(p, Cba_FonObj(p, iFon)) ); if ( Cba_NtkHasFonNames(p) ) Cba_FonSetName( pNew, Cba_ObjFon0(pNew, iObjNew), Cba_FonName(p, iFon) ); } // create internal Vec_IntForEachEntry( vObjs, iObj, i ) { iObjNew = Cba_ObjDup( pNew, p, iObj ); if ( Cba_NtkHasObjNames(p) ) Cba_ObjSetName( pNew, iObjNew, Cba_ObjName(p, iObj) ); Cba_ObjForEachFon( p, iObj, iFon, k ) { Cba_FonSetCopy( p, iFon, Cba_ObjFon(pNew, iObjNew, k) ); if ( Cba_NtkHasFonNames(p) ) Cba_FonSetName( pNew, Cba_ObjFon(pNew, iObjNew, k), Cba_FonName(p, iFon) ); } } // connect internal Vec_IntForEachEntry( vObjs, iObj, i ) { iObjNew = Cba_ObjCopy( p, iObj ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) Cba_ObjSetFinFon( pNew, iObjNew, k, Cba_FonCopy(p, iFon) ); } // create POs Vec_IntForEachEntry( vFonOuts, iFon, i ) { iObjNew = Cba_ObjAlloc( pNew, CBA_OBJ_PO, 1, 0 ); if ( Cba_NtkHasObjNames(p) ) Cba_ObjSetName( pNew, iObjNew, Cba_FonName(p, iFon) ); Cba_ObjSetFinFon( pNew, iObjNew, 0, Cba_FonCopy(p, iFon) ); } assert( Cba_NtkObjNum(pNew) == Cba_NtkObjNumAlloc(pNew) ); assert( Cba_NtkFinNum(pNew) == Cba_NtkFinNumAlloc(pNew) ); assert( Cba_NtkFonNum(pNew) == Cba_NtkFonNumAlloc(pNew) ); } Cba_Man_t * Cba_ManExtractGroup( Cba_Man_t * p, Vec_Int_t * vObjs ) { Cba_Man_t * pNew = Cba_ManAlloc( p->pSpec, 1, Abc_NamRef(p->pStrs), Abc_NamRef(p->pFuns), Abc_NamStart(100, 24), Hash_IntManRef(p->vHash) ); Cba_Ntk_t * pRoot = Cba_ManRoot( p ), * pRootNew; Vec_Int_t * vFonIns = Cba_NtkCollectInFons( pRoot, vObjs ); Vec_Int_t * vFonOuts = Cba_NtkCollectOutFons( pRoot, vObjs ); int nObjs, nFins, nFons; Cba_ManDupTypeNames( pNew, p ); // collect stats Cba_NtkCollectGroupStats( pRoot, vObjs, &nFins, &nFons ); nObjs = Vec_IntSize(vObjs) + Vec_IntSize(vFonIns) + Vec_IntSize(vFonOuts); nFins += Vec_IntSize(vFonOuts); nFons += Vec_IntSize(vFonIns); // create network pRootNew = Cba_NtkAlloc( pNew, Cba_NtkNameId(pRoot), Vec_IntSize(vFonIns), Vec_IntSize(vFonOuts), nObjs, nFins, nFons ); Cba_NtkAdd( pNew, pRootNew ); if ( Cba_NtkHasObjNames(pRoot) ) Cba_NtkCleanObjNames( pRootNew ); if ( Cba_NtkHasFonNames(pRoot) ) Cba_NtkCleanFonNames( pRootNew ); // add group nodes Cba_ManExtractGroupInt( pRootNew, pRoot, vObjs, vFonIns, vFonOuts ); Cba_NtkMissingFonNames( pRootNew, "b" ); //Cba_NtkPrepareSeq( pRootNew ); // cleanup Vec_IntFree( vFonIns ); Vec_IntFree( vFonOuts ); return pNew; } /**Function************************************************************* Synopsis [Derives the design from the GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cba_NtkInsertGiaLit( Cba_Ntk_t * p, int iLit, Vec_Int_t * vLit2Fon, int fUseXor ) { int iObjNew; if ( iLit == 0 || iLit == 1 ) return Cba_FonFromConst(iLit); if ( Vec_IntEntry(vLit2Fon, iLit) >= 0 ) return Vec_IntEntry(vLit2Fon, iLit); assert( Abc_LitIsCompl(iLit) ); assert( Vec_IntEntry(vLit2Fon, Abc_LitNot(iLit)) >= 0 ); // create inverter if ( fUseXor ) { iObjNew = Cba_ObjAlloc( p, CBA_BOX_XOR, 2, 1 ); Cba_ObjSetFinFon( p, iObjNew, 0, Vec_IntEntry(vLit2Fon, Abc_LitNot(iLit)) ); Cba_ObjSetFinFon( p, iObjNew, 1, Cba_FonFromConst(1) ); } else { iObjNew = Cba_ObjAlloc( p, CBA_BOX_INV, 1, 1 ); Cba_ObjSetFinFon( p, iObjNew, 0, Vec_IntEntry(vLit2Fon, Abc_LitNot(iLit)) ); } // save the result Vec_IntWriteEntry( vLit2Fon, iLit, Cba_ObjFon0(p, iObjNew) ); return Cba_ObjFon0(p, iObjNew); } static inline int Cba_NtkInsertGiaObj( Cba_Ntk_t * p, Gia_Man_t * pGia, int iObj, Vec_Int_t * vLit2Fon, int fUseXor ) { Gia_Obj_t * pObj = Gia_ManObj( pGia, iObj ); int iLit0 = Gia_ObjFaninLit0( pObj, iObj ); int iLit1 = Gia_ObjFaninLit1( pObj, iObj ); int iFon0 = Cba_NtkInsertGiaLit( p, iLit0, vLit2Fon, fUseXor ); int iFon1 = Cba_NtkInsertGiaLit( p, iLit1, vLit2Fon, fUseXor ); int iObjNew; if ( Gia_ObjIsMux(pGia, pObj) ) { int iLit2 = Gia_ObjFaninLit2( pGia, iObj ); int iFon2 = Cba_NtkInsertGiaLit( p, iLit2, vLit2Fon, fUseXor ); iObjNew = Cba_ObjAlloc( p, CBA_BOX_MUX, 3, 1 ); Cba_ObjSetFinFon( p, iObjNew, 0, iFon2 ); Cba_ObjSetFinFon( p, iObjNew, 1, iFon1 ); Cba_ObjSetFinFon( p, iObjNew, 2, iFon0 ); } else { assert( Gia_ObjIsAnd(pObj) ); iObjNew = Cba_ObjAlloc( p, Gia_ObjIsXor(pObj) ? CBA_BOX_XOR : CBA_BOX_AND, 2, 1 ); Cba_ObjSetFinFon( p, iObjNew, 0, iFon0 ); Cba_ObjSetFinFon( p, iObjNew, 1, iFon1 ); } Vec_IntWriteEntry( vLit2Fon, Abc_Var2Lit(iObj, 0), Cba_ObjFon0(p, iObjNew) ); return iObjNew; } Cba_Man_t * Cba_ManDeriveFromGia( Cba_Man_t * pOld, Gia_Man_t * pGia, int fUseXor ) { Cba_Man_t * p = Cba_ManAlloc( pGia->pSpec, 1, pOld ? Abc_NamRef(pOld->pStrs) : NULL, pOld ? Abc_NamRef(pOld->pFuns) : NULL, NULL, NULL ); Cba_Ntk_t * pNtk = Cba_NtkAlloc( p, Abc_NamStrFindOrAdd(p->pStrs, pGia->pName, NULL), Gia_ManCiNum(pGia), Gia_ManCoNum(pGia), 1000, 2000, 2000 ); Vec_Int_t * vLit2Fon = Vec_IntStartFull( 2*Gia_ManObjNum(pGia) ); int i, iObj, iObjNew, NameId, iLit0, iFon0; Gia_Obj_t * pObj; //Cba_ManPrepareTypeNames( p ); Cba_NtkAdd( p, pNtk ); Cba_NtkCleanObjNames( pNtk ); Gia_ManForEachCiId( pGia, iObj, i ) { NameId = pGia->vNamesIn? Abc_NamStrFindOrAdd(p->pStrs, (char*)Vec_PtrEntry(pGia->vNamesIn, i), NULL) : Cba_NtkNewStrId(pNtk, "i%d", i); iObjNew = Cba_ObjAlloc( pNtk, CBA_OBJ_PI, 0, 1 ); Cba_ObjSetName( pNtk, iObjNew, NameId ); Vec_IntWriteEntry( vLit2Fon, Abc_Var2Lit(iObj, 0), Cba_ObjFon0(pNtk, iObjNew) ); } Gia_ManForEachAndId( pGia, iObj ) Cba_NtkInsertGiaObj( pNtk, pGia, iObj, vLit2Fon, fUseXor ); // create inverters if needed Gia_ManForEachCoId( pGia, iObj, i ) { pObj = Gia_ManObj( pGia, iObj ); iLit0 = Gia_ObjFaninLit0( pObj, iObj ); iFon0 = Cba_NtkInsertGiaLit( pNtk, iLit0, vLit2Fon, fUseXor ); // can be const! } Gia_ManForEachCoId( pGia, iObj, i ) { pObj = Gia_ManObj( pGia, iObj ); iLit0 = Gia_ObjFaninLit0( pObj, iObj ); iFon0 = Cba_NtkInsertGiaLit( pNtk, iLit0, vLit2Fon, fUseXor ); // can be const! iObjNew = Cba_ObjAlloc( pNtk, CBA_BOX_BUF, 1, 1 ); Cba_ObjSetFinFon( pNtk, iObjNew, 0, iFon0 ); iFon0 = Cba_ObjFon0(pNtk, iObjNew); // non-const fon unique for this output NameId = pGia->vNamesOut? Abc_NamStrFindOrAdd(p->pStrs, (char*)Vec_PtrEntry(pGia->vNamesOut, i), NULL) : Cba_NtkNewStrId(pNtk, "o%d", i); iObjNew = Cba_ObjAlloc( pNtk, CBA_OBJ_PO, 1, 0 ); Cba_ObjSetName( pNtk, iObjNew, NameId ); Cba_ObjSetFinFon( pNtk, iObjNew, 0, iFon0 ); } Cba_NtkCleanFonNames( pNtk ); Cba_NtkCreateFonNames( pNtk, "a" ); Vec_IntFree( vLit2Fon ); return p; } /**Function************************************************************* Synopsis [Inserts the network into the root module instead of objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cba_NtkInsertGroup( Cba_Ntk_t * p, Vec_Int_t * vObjs, Cba_Ntk_t * pSyn ) { Vec_Int_t * vFonIns = Cba_NtkCollectInFons( p, vObjs ); Vec_Int_t * vFonOuts = Cba_NtkCollectOutFons( p, vObjs ); int k, iObj, iObjNew, iFin, iFon; assert( Cba_NtkPiNum(pSyn) == Vec_IntSize(vFonIns) ); assert( Cba_NtkPoNum(pSyn) == Vec_IntSize(vFonOuts) ); // mark AIG with the input fons Cba_NtkCleanFonCopies( pSyn ); Cba_NtkForEachPiFon( pSyn, iObj, iFon, k ) Cba_FonSetCopy( pSyn, iFon, Vec_IntEntry(vFonIns, k) ); Vec_IntFree( vFonIns ); // build up internal nodes Cba_NtkCleanObjCopies( pSyn ); Cba_NtkForEachBox( pSyn, iObj ) { iObjNew = Cba_ObjDup( p, pSyn, iObj ); Cba_ObjForEachFon( pSyn, iObj, iFon, k ) Cba_FonSetCopy( pSyn, iFon, Cba_ObjFon(p, iObjNew, k) ); } // connect internal nodes Cba_NtkForEachBox( pSyn, iObj ) { iObjNew = Cba_ObjCopy( pSyn, iObj ); Cba_ObjForEachFinFon( pSyn, iObj, iFin, iFon, k ) Cba_ObjSetFinFon( p, iObjNew, k, Cba_FonCopy(pSyn, iFon) ); } // connect output fons Cba_NtkCleanFonCopies( p ); if ( Cba_NtkHasFonNames(p) ) Vec_IntFillExtra( &p->vFonName, Cba_NtkFonNum(p) + 1, 0 ); Cba_NtkForEachPoDriverFon( pSyn, iObj, iFon, k ) { assert( Cba_FonIsReal(Cba_FonCopy(pSyn, iFon)) ); Cba_FonSetCopy( p, Vec_IntEntry(vFonOuts, k), Cba_FonCopy(pSyn, iFon) ); // transfer names if ( Cba_NtkHasFonNames(p) ) { Cba_FonSetName( p, Cba_FonCopy(pSyn, iFon), Cba_FonName(p, Vec_IntEntry(vFonOuts, k)) ); Cba_FonCleanName( p, Vec_IntEntry(vFonOuts, k) ); } } Vec_IntFree( vFonOuts ); // delete nodes // Vec_IntForEachEntry( vObjs, iObj, k ) // Cba_ObjDelete( p, iObj ); // update fins pointing to output fons to point to the new fons Cba_NtkForEachFinFon( p, iFon, iFin ) if ( Cba_FonIsReal(iFon) && Cba_FonCopy(p, iFon) ) Cba_PatchFinFon( p, iFin, Cba_FonCopy(p, iFon) ); Cba_NtkMissingFonNames( p, "j" ); /* // duplicate in DFS order pNew = Cba_NtkDupOrder( p->pDesign, p, Cba_NtkCollectDfs ); Cba_NtkDupAttrs( pNew, p ); // replace "p" with "pNew" Cba_NtkUpdate( Cba_NtkMan(p), pNew ); // removes "p" return pNew; */ } Cba_Man_t * Cba_ManInsertGroup( Cba_Man_t * p, Vec_Int_t * vObjs, Cba_Ntk_t * pSyn ) { Cba_NtkInsertGroup( Cba_ManRoot(p), vObjs, pSyn ); Cba_NtkCheckComboLoop( Cba_ManRoot(p) ); return Cba_ManDup( p, Cba_NtkCollectDfs ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaPrs.h000066400000000000000000000526551300674244400230730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaPrs.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Parser declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: cbaPrs.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__prs__prs_h #define ABC__base__prs__prs_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "misc/util/utilNam.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START // Verilog keywords typedef enum { PRS_VER_NONE = 0, // 0: unused PRS_VER_INPUT, // 1: input PRS_VER_OUTPUT, // 2: output PRS_VER_INOUT, // 3: inout PRS_VER_WIRE, // 4: wire PRS_VER_REG, // 5: reg PRS_VER_MODULE, // 6: module PRS_VER_ASSIGN, // 7: assign PRS_VER_ALWAYS, // 8: always PRS_VER_FUNCTION, // 9: function PRS_VER_DEFPARAM, // 10: defparam PRS_VER_BEGIN, // 11: begin PRS_VER_END, // 12: end PRS_VER_CASE, // 13: case PRS_VER_ENDCASE, // 14: endcase PRS_VER_SIGNED, // 15: signed PRS_VER_ENDMODULE, // 16: endmodule PRS_VER_UNKNOWN // 17: unknown } Cba_VerType_t; // parser name types typedef enum { CBA_PRS_NAME = 0, // 0: name/variable CBA_PRS_SLICE, // 1: slice CBA_PRS_CONST, // 2: constant CBA_PRS_CONCAT, // 3: concatentation } Prs_ManType_t; //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // network typedef struct Prs_Ntk_t_ Prs_Ntk_t; struct Prs_Ntk_t_ { // general info int iModuleName; unsigned fMapped : 1; unsigned fSlices : 1; unsigned fHasC0s : 1; unsigned fHasC1s : 1; unsigned fHasCXs : 1; unsigned fHasCZs : 1; Abc_Nam_t * pStrs; Abc_Nam_t * pFuns; Hash_IntMan_t * vHash; // interface Vec_Int_t vOrder; // order of signals // signal names Vec_Int_t vInouts; // inouts Vec_Int_t vInputs; // inputs Vec_Int_t vOutputs; // outputs Vec_Int_t vWires; // wires // signal ranges Vec_Int_t vInoutsR; // inouts Vec_Int_t vInputsR; // inputs Vec_Int_t vOutputsR; // outputs Vec_Int_t vWiresR; // wires // slices/concatenations/objects Vec_Int_t vSlices; // NameId + RangeId Vec_Int_t vConcats; // array of NameId/SliceId/ConstId Vec_Int_t vBoxes; // ModuleId + InstId + array of pairs {FormNameId, ActSignalId(NameId/SliceId/ConstId/ConcatId)} Vec_Int_t vObjs; // box handles }; // parser typedef struct Prs_Man_t_ Prs_Man_t; struct Prs_Man_t_ { // input data char * pName; // file name char * pBuffer; // file contents char * pLimit; // end of file char * pCur; // current position Abc_Nam_t * pStrs; // string manager Abc_Nam_t * pFuns; // cover manager Hash_IntMan_t * vHash; // variable ranges Prs_Ntk_t * pNtk; // current network Vec_Ptr_t * vNtks; // input networks // temporary data Vec_Str_t vCover; // one SOP cover Vec_Int_t vTemp; // array of tokens Vec_Int_t vTemp2; // array of tokens Vec_Int_t vTemp3; // array of tokens Vec_Int_t vTemp4; // array of tokens // statistics Vec_Int_t vKnown; Vec_Int_t vFailed; Vec_Int_t vSucceeded; // error handling int nOpens; // open port counter int fUsingTemp2; // vTemp2 is in use int FuncNameId; // temp value int FuncRangeId; // temp value char ErrorStr[1000]; // error }; static inline Prs_Ntk_t * Prs_ManNtk( Vec_Ptr_t * vPrs, int i ) { return i >= 0 && i < Vec_PtrSize(vPrs) ? (Prs_Ntk_t *)Vec_PtrEntry(vPrs, i) : NULL; } static inline Prs_Ntk_t * Prs_ManRoot( Vec_Ptr_t * vPrs ) { return Prs_ManNtk(vPrs, 0); } static inline Abc_Nam_t * Prs_ManNameMan( Vec_Ptr_t * vPrs ) { return Prs_ManRoot(vPrs)->pStrs; } static inline Abc_Nam_t * Prs_ManFuncMan( Vec_Ptr_t * vPrs ) { return Prs_ManRoot(vPrs)->pFuns; } static inline int Prs_NtkId( Prs_Ntk_t * p ) { return p->iModuleName; } static inline int Prs_NtkPioNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vInouts); } static inline int Prs_NtkPiNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vInputs); } static inline int Prs_NtkPoNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vOutputs); } static inline int Prs_NtkBoxNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); } static inline int Prs_NtkObjNum( Prs_Ntk_t * p ) { return Prs_NtkPioNum(p) + Prs_NtkPiNum(p) + Prs_NtkPoNum(p) + Prs_NtkBoxNum(p); } static inline char * Prs_NtkStr( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pStrs, h); } static inline char * Prs_NtkSop( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pFuns, h); } static inline char * Prs_NtkConst( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pFuns, h); } static inline char * Prs_NtkName( Prs_Ntk_t * p ) { return Prs_NtkStr(p, Prs_NtkId(p)); } static inline int Prs_NtkSigName( Prs_Ntk_t * p, int i ) { if (!p->fSlices) return i; assert(Abc_Lit2Att2(i) == CBA_PRS_NAME); return Abc_Lit2Var2(i); } static inline int Ptr_NtkRangeSize( Prs_Ntk_t * p, int h ) { int l = Hash_IntObjData0(p->vHash, h), r = Hash_IntObjData1(p->vHash, h); return 1 + (l > r ? l-r : r-l); } static inline int Prs_SliceName( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h); } static inline int Prs_SliceRange( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h+1); } static inline int Prs_CatSize( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vConcats, h); } static inline int * Prs_CatArray( Prs_Ntk_t * p, int h ) { return Vec_IntEntryP(&p->vConcats, h+1); } static inline Vec_Int_t * Prs_CatSignals( Prs_Ntk_t * p, int h ) { static Vec_Int_t V; V.nSize = V.nCap = Prs_CatSize(p, h); V.pArray = Prs_CatArray(p, h); return &V; } static inline int Prs_BoxHand( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vObjs, i); } static inline int Prs_BoxSize( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i))-2; } static inline int Prs_BoxIONum( Prs_Ntk_t * p, int i ) { return Prs_BoxSize(p, i) / 2; } static inline int Prs_BoxNtk( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+1); } static inline void Prs_BoxSetNtk( Prs_Ntk_t * p, int i, int m ) { Vec_IntWriteEntry(&p->vBoxes, Prs_BoxHand(p, i)+1, m); } static inline int Prs_BoxName( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+2); } static inline int Prs_BoxIsNode( Prs_Ntk_t * p, int i ) { return!Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+3); } // no formal names static inline int * Prs_BoxArray( Prs_Ntk_t * p, int i ) { return Vec_IntEntryP(&p->vBoxes, Prs_BoxHand(p, i)+3); } static inline Vec_Int_t * Prs_BoxSignals( Prs_Ntk_t * p, int i ) { static Vec_Int_t V; V.nSize = V.nCap = Prs_BoxSize(p, i); V.pArray = Prs_BoxArray(p, i); return &V; } #define Prs_ManForEachNameVec( vVec, p, pName, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pName) = Abc_NamStr(p->pStrs, Vec_IntEntry(vVec,i))); i++ ) #define Prs_NtkForEachPio( p, NameId, i ) \ for ( i = 0; i < Prs_NtkPioNum(p) && ((NameId) = Vec_IntEntry(&p->vInouts, i)); i++ ) #define Prs_NtkForEachPi( p, NameId, i ) \ for ( i = 0; i < Prs_NtkPiNum(p) && ((NameId) = Vec_IntEntry(&p->vInputs, i)); i++ ) #define Prs_NtkForEachPo( p, NameId, i ) \ for ( i = 0; i < Prs_NtkPoNum(p) && ((NameId) = Vec_IntEntry(&p->vOutputs, i)); i++ ) #define Prs_NtkForEachBox( p, vVec, i ) \ for ( i = 0; i < Prs_NtkBoxNum(p) && ((vVec) = Prs_BoxSignals(p, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // create error message static inline int Prs_ManErrorSet( Prs_Man_t * p, char * pError, int Value ) { assert( !p->ErrorStr[0] ); sprintf( p->ErrorStr, "%s", pError ); return Value; } // clear error message static inline void Prs_ManErrorClear( Prs_Man_t * p ) { p->ErrorStr[0] = '\0'; } // print error message static inline int Prs_ManErrorPrint( Prs_Man_t * p ) { char * pThis; int iLine = 0; if ( !p->ErrorStr[0] ) return 1; for ( pThis = p->pBuffer; pThis < p->pCur; pThis++ ) iLine += (int)(*pThis == '\n'); printf( "Line %d: %s\n", iLine, p->ErrorStr ); return 0; } // parsing network static inline void Prs_ManInitializeNtk( Prs_Man_t * p, int iName, int fSlices ) { assert( p->pNtk == NULL ); p->pNtk = ABC_CALLOC( Prs_Ntk_t, 1 ); p->pNtk->iModuleName = iName; p->pNtk->fSlices = fSlices; p->pNtk->pStrs = Abc_NamRef( p->pStrs ); p->pNtk->pFuns = Abc_NamRef( p->pFuns ); p->pNtk->vHash = Hash_IntManRef( p->vHash ); Vec_PtrPush( p->vNtks, p->pNtk ); } static inline void Prs_ManFinalizeNtk( Prs_Man_t * p ) { assert( p->pNtk != NULL ); p->pNtk = NULL; } static inline int Prs_ManNewStrId( Prs_Man_t * p, const char * format, ... ) { Abc_Nam_t * pStrs = p->pStrs; Vec_Str_t * vBuf = Abc_NamBuffer( pStrs ); int nAdded, nSize = 1000; va_list args; va_start( args, format ); Vec_StrGrow( vBuf, Vec_StrSize(vBuf) + nSize ); nAdded = vsnprintf( Vec_StrLimit(vBuf), nSize, format, args ); if ( nAdded > nSize ) { Vec_StrGrow( vBuf, Vec_StrSize(vBuf) + nAdded + nSize ); nSize = vsnprintf( Vec_StrLimit(vBuf), nAdded, format, args ); assert( nSize == nAdded ); } va_end( args ); return Abc_NamStrFindOrAddLim( pStrs, Vec_StrLimit(vBuf), Vec_StrLimit(vBuf) + nAdded, NULL ); } // parsing slice/concatentation/box static inline int Prs_NtkAddSlice( Prs_Ntk_t * p, int Name, int Range ) { int Value = Vec_IntSize(&p->vSlices); Vec_IntPushTwo( &p->vSlices, Name, Range ); return Value; } static inline int Prs_NtkAddConcat( Prs_Ntk_t * p, Vec_Int_t * vTemp ) { int Value; if ( !(Vec_IntSize(&p->vConcats) & 1) ) Vec_IntPush(&p->vConcats, -1); Value = Vec_IntSize(&p->vConcats); assert( Value & 1 ); Vec_IntPush( &p->vConcats, Vec_IntSize(vTemp) ); Vec_IntAppend( &p->vConcats, vTemp ); return Value; } static inline void Prs_NtkAddBox( Prs_Ntk_t * p, int ModName, int InstName, Vec_Int_t * vTemp ) { int Value; assert( Vec_IntSize(vTemp) % 2 == 0 ); if ( !(Vec_IntSize(&p->vBoxes) & 1) ) Vec_IntPush(&p->vBoxes, -1); Value = Vec_IntSize(&p->vBoxes); assert( Value & 1 ); Vec_IntPush( &p->vObjs, Value ); // create entry Vec_IntPush( &p->vBoxes, Vec_IntSize(vTemp)+2 ); Vec_IntPush( &p->vBoxes, ModName ); Vec_IntPush( &p->vBoxes, InstName ); Vec_IntAppend( &p->vBoxes, vTemp ); } static inline char * Prs_ManLoadFile( char * pFileName, char ** ppLimit ) { char * pBuffer; int nFileSize, RetValue; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file.\n" ); return NULL; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nFileSize + 16 ); pBuffer[0] = '\n'; RetValue = fread( pBuffer+1, nFileSize, 1, pFile ); fclose( pFile ); // terminate the string with '\0' pBuffer[nFileSize + 1] = '\n'; pBuffer[nFileSize + 2] = '\0'; *ppLimit = pBuffer + nFileSize + 3; return pBuffer; } static inline Prs_Man_t * Prs_ManAlloc( char * pFileName ) { Prs_Man_t * p; p = ABC_CALLOC( Prs_Man_t, 1 ); if ( pFileName ) { char * pBuffer, * pLimit; pBuffer = Prs_ManLoadFile( pFileName, &pLimit ); if ( pBuffer == NULL ) return NULL; p->pName = pFileName; p->pBuffer = pBuffer; p->pLimit = pLimit; p->pCur = pBuffer; } p->pStrs = Abc_NamStart( 1000, 24 ); p->pFuns = Abc_NamStart( 100, 24 ); p->vHash = Hash_IntManStart( 1000 ); p->vNtks = Vec_PtrAlloc( 100 ); return p; } static inline void Prs_NtkFree( Prs_Ntk_t * p ) { if ( p->pStrs ) Abc_NamDeref( p->pStrs ); if ( p->pFuns ) Abc_NamDeref( p->pFuns ); if ( p->vHash ) Hash_IntManDeref( p->vHash ); Vec_IntErase( &p->vOrder ); Vec_IntErase( &p->vInouts ); Vec_IntErase( &p->vInputs ); Vec_IntErase( &p->vOutputs ); Vec_IntErase( &p->vWires ); Vec_IntErase( &p->vInoutsR ); Vec_IntErase( &p->vInputsR ); Vec_IntErase( &p->vOutputsR ); Vec_IntErase( &p->vWiresR ); Vec_IntErase( &p->vSlices ); Vec_IntErase( &p->vConcats ); Vec_IntErase( &p->vBoxes ); Vec_IntErase( &p->vObjs ); ABC_FREE( p ); } static inline void Prs_ManVecFree( Vec_Ptr_t * vPrs ) { Prs_Ntk_t * pNtk; int i; Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i ) Prs_NtkFree( pNtk ); Vec_PtrFree( vPrs ); } static inline void Prs_ManFree( Prs_Man_t * p ) { if ( p->pStrs ) Abc_NamDeref( p->pStrs ); if ( p->pFuns ) Abc_NamDeref( p->pFuns ); if ( p->vHash ) Hash_IntManDeref( p->vHash ); if ( p->vNtks ) Prs_ManVecFree( p->vNtks ); // temporary Vec_StrErase( &p->vCover ); Vec_IntErase( &p->vTemp ); Vec_IntErase( &p->vTemp2 ); Vec_IntErase( &p->vTemp3 ); Vec_IntErase( &p->vTemp4 ); Vec_IntErase( &p->vKnown ); Vec_IntErase( &p->vFailed ); Vec_IntErase( &p->vSucceeded ); ABC_FREE( p->pBuffer ); ABC_FREE( p ); } static inline int Prs_NtkMemory( Prs_Ntk_t * p ) { int nMem = sizeof(Prs_Ntk_t); nMem += Vec_IntMemory( &p->vOrder ); nMem += Vec_IntMemory( &p->vInouts ); nMem += Vec_IntMemory( &p->vInputs ); nMem += Vec_IntMemory( &p->vOutputs ); nMem += Vec_IntMemory( &p->vWires ); nMem += Vec_IntMemory( &p->vInoutsR ); nMem += Vec_IntMemory( &p->vInputsR ); nMem += Vec_IntMemory( &p->vOutputsR ); nMem += Vec_IntMemory( &p->vWiresR ); nMem += Vec_IntMemory( &p->vSlices ); nMem += Vec_IntMemory( &p->vBoxes ); nMem += Vec_IntMemory( &p->vConcats ); return nMem; } static inline int Prs_ManMemory( Vec_Ptr_t * vPrs ) { Prs_Ntk_t * pNtk; int i; int nMem = Vec_PtrMemory(vPrs); Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i ) nMem += Prs_NtkMemory( pNtk ); nMem += Abc_NamMemUsed(Prs_ManNameMan(vPrs)); return nMem; } /**Function************************************************************* Synopsis [Other APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cba_ObjType_t Ptr_SopToType( char * pSop ) { if ( !strcmp(pSop, " 0\n") ) return CBA_BOX_CF; if ( !strcmp(pSop, " 1\n") ) return CBA_BOX_CT; if ( !strcmp(pSop, "1 1\n") ) return CBA_BOX_BUF; if ( !strcmp(pSop, "0 1\n") ) return CBA_BOX_INV; if ( !strcmp(pSop, "11 1\n") ) return CBA_BOX_AND; if ( !strcmp(pSop, "00 1\n") ) return CBA_BOX_NOR; if ( !strcmp(pSop, "00 0\n") ) return CBA_BOX_OR; if ( !strcmp(pSop, "-1 1\n1- 1\n") ) return CBA_BOX_OR; if ( !strcmp(pSop, "1- 1\n-1 1\n") ) return CBA_BOX_OR; if ( !strcmp(pSop, "01 1\n10 1\n") ) return CBA_BOX_XOR; if ( !strcmp(pSop, "10 1\n01 1\n") ) return CBA_BOX_XOR; if ( !strcmp(pSop, "11 1\n00 1\n") ) return CBA_BOX_XNOR; if ( !strcmp(pSop, "00 1\n11 1\n") ) return CBA_BOX_XNOR; if ( !strcmp(pSop, "10 1\n") ) return CBA_BOX_SHARP; if ( !strcmp(pSop, "01 1\n") ) return CBA_BOX_SHARPL; assert( 0 ); return CBA_OBJ_NONE; } static inline char * Ptr_SopToTypeName( char * pSop ) { if ( !strcmp(pSop, " 0\n") ) return "CBA_BOX_C0"; if ( !strcmp(pSop, " 1\n") ) return "CBA_BOX_C1"; if ( !strcmp(pSop, "1 1\n") ) return "CBA_BOX_BUF"; if ( !strcmp(pSop, "0 1\n") ) return "CBA_BOX_INV"; if ( !strcmp(pSop, "11 1\n") ) return "CBA_BOX_AND"; if ( !strcmp(pSop, "00 1\n") ) return "CBA_BOX_NOR"; if ( !strcmp(pSop, "00 0\n") ) return "CBA_BOX_OR"; if ( !strcmp(pSop, "-1 1\n1- 1\n") ) return "CBA_BOX_OR"; if ( !strcmp(pSop, "1- 1\n-1 1\n") ) return "CBA_BOX_OR"; if ( !strcmp(pSop, "01 1\n10 1\n") ) return "CBA_BOX_XOR"; if ( !strcmp(pSop, "10 1\n01 1\n") ) return "CBA_BOX_XOR"; if ( !strcmp(pSop, "11 1\n00 1\n") ) return "CBA_BOX_XNOR"; if ( !strcmp(pSop, "00 1\n11 1\n") ) return "CBA_BOX_XNOR"; if ( !strcmp(pSop, "10 1\n") ) return "CBA_BOX_SHARP"; if ( !strcmp(pSop, "01 1\n") ) return "CBA_BOX_SHARPL"; assert( 0 ); return NULL; } static inline char * Ptr_TypeToName( Cba_ObjType_t Type ) { if ( Type == CBA_BOX_CF ) return "const0"; if ( Type == CBA_BOX_CT ) return "const1"; if ( Type == CBA_BOX_CX ) return "constX"; if ( Type == CBA_BOX_CZ ) return "constZ"; if ( Type == CBA_BOX_BUF ) return "buf"; if ( Type == CBA_BOX_INV ) return "not"; if ( Type == CBA_BOX_AND ) return "and"; if ( Type == CBA_BOX_NAND ) return "nand"; if ( Type == CBA_BOX_OR ) return "or"; if ( Type == CBA_BOX_NOR ) return "nor"; if ( Type == CBA_BOX_XOR ) return "xor"; if ( Type == CBA_BOX_XNOR ) return "xnor"; if ( Type == CBA_BOX_MUX ) return "mux"; if ( Type == CBA_BOX_MAJ ) return "maj"; if ( Type == CBA_BOX_SHARP ) return "sharp"; if ( Type == CBA_BOX_SHARPL) return "sharpl"; if ( Type == CBA_BOX_TRI) return "bufifl"; assert( 0 ); return "???"; } static inline char * Ptr_TypeToSop( Cba_ObjType_t Type ) { if ( Type == CBA_BOX_CF ) return " 0\n"; if ( Type == CBA_BOX_CT ) return " 1\n"; if ( Type == CBA_BOX_CX ) return " 0\n"; if ( Type == CBA_BOX_CZ ) return " 0\n"; if ( Type == CBA_BOX_BUF ) return "1 1\n"; if ( Type == CBA_BOX_INV ) return "0 1\n"; if ( Type == CBA_BOX_AND ) return "11 1\n"; if ( Type == CBA_BOX_NAND ) return "11 0\n"; if ( Type == CBA_BOX_OR ) return "00 0\n"; if ( Type == CBA_BOX_NOR ) return "00 1\n"; if ( Type == CBA_BOX_XOR ) return "01 1\n10 1\n"; if ( Type == CBA_BOX_XNOR ) return "00 1\n11 1\n"; if ( Type == CBA_BOX_SHARP ) return "10 1\n"; if ( Type == CBA_BOX_SHARPL) return "01 1\n"; if ( Type == CBA_BOX_MUX ) return "11- 1\n0-1 1\n"; if ( Type == CBA_BOX_MAJ ) return "11- 1\n1-1 1\n-11 1\n"; assert( 0 ); return "???"; } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cbaReadVer.c ========================================================*/ extern void Prs_NtkAddVerilogDirectives( Prs_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaReadBlif.c000066400000000000000000000547411300674244400237700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaReadBlif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [BLIF parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: cbaReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cba.h" #include "cbaPrs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // BLIF keywords typedef enum { PRS_BLIF_NONE = 0, // 0: unused PRS_BLIF_MODEL, // 1: .model PRS_BLIF_INOUTS, // 2: .inouts PRS_BLIF_INPUTS, // 3: .inputs PRS_BLIF_OUTPUTS, // 4: .outputs PRS_BLIF_NAMES, // 5: .names PRS_BLIF_SUBCKT, // 6: .subckt PRS_BLIF_GATE, // 7: .gate PRS_BLIF_LATCH, // 8: .latch PRS_BLIF_SHORT, // 9: .short PRS_BLIF_END, // 10: .end PRS_BLIF_UNKNOWN // 11: unknown } Cba_BlifType_t; static const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = { NULL, // 0: unused ".model", // 1: .model ".inouts", // 2: .inputs ".inputs", // 3: .inputs ".outputs", // 4: .outputs ".names", // 5: .names ".subckt", // 6: .subckt ".gate", // 7: .gate ".latch", // 8: .latch ".short", // 9: .short ".end", // 10: .end NULL // 11: unknown }; static inline void Prs_NtkAddBlifDirectives( Prs_Man_t * p ) { int i; for ( i = 1; s_BlifTypes[i]; i++ ) Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL ); assert( Abc_NamObjNumMax(p->pStrs) == i ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reading characters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Prs_CharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r'; } static inline int Prs_CharIsStop( char c ) { return c == '#' || c == '\\' || c == '\n' || c == '='; } static inline int Prs_CharIsLit( char c ) { return c == '0' || c == '1' || c == '-'; } static inline int Prs_ManIsSpace( Prs_Man_t * p ) { return Prs_CharIsSpace(*p->pCur); } static inline int Prs_ManIsStop( Prs_Man_t * p ) { return Prs_CharIsStop(*p->pCur); } static inline int Prs_ManIsLit( Prs_Man_t * p ) { return Prs_CharIsLit(*p->pCur); } static inline int Prs_ManIsChar( Prs_Man_t * p, char c ) { return *p->pCur == c; } static inline int Prs_ManIsChar2( Prs_Man_t * p, char c ) { return *p->pCur++ == c; } static inline void Prs_ManSkip( Prs_Man_t * p ) { p->pCur++; } static inline char Prs_ManSkip2( Prs_Man_t * p ) { return *p->pCur++; } /**Function************************************************************* Synopsis [Reading names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Prs_ManSkipToChar( Prs_Man_t * p, char c ) { while ( !Prs_ManIsChar(p, c) ) Prs_ManSkip(p); } static inline void Prs_ManSkipSpaces( Prs_Man_t * p ) { while ( 1 ) { while ( Prs_ManIsSpace(p) ) Prs_ManSkip(p); if ( Prs_ManIsChar(p, '\\') ) { Prs_ManSkipToChar( p, '\n' ); Prs_ManSkip(p); continue; } if ( Prs_ManIsChar(p, '#') ) Prs_ManSkipToChar( p, '\n' ); break; } assert( !Prs_ManIsSpace(p) ); } static inline int Prs_ManReadName( Prs_Man_t * p ) { char * pStart; Prs_ManSkipSpaces( p ); if ( Prs_ManIsChar(p, '\n') ) return 0; pStart = p->pCur; while ( !Prs_ManIsSpace(p) && !Prs_ManIsStop(p) ) Prs_ManSkip(p); if ( pStart == p->pCur ) return 0; return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); } static inline int Prs_ManReadList( Prs_Man_t * p, Vec_Int_t * vOrder, int Type ) { int iToken; Vec_IntClear( &p->vTemp ); while ( (iToken = Prs_ManReadName(p)) ) { Vec_IntPush( &p->vTemp, iToken ); Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) ); } if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Signal list is empty.", 1); return 0; } static inline int Prs_ManReadList2( Prs_Man_t * p ) { int iToken; Vec_IntClear( &p->vTemp ); while ( (iToken = Prs_ManReadName(p)) ) Vec_IntPushTwo( &p->vTemp, 0, iToken ); if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Signal list is empty.", 1); return 0; } static inline int Prs_ManReadList3( Prs_Man_t * p ) { Vec_IntClear( &p->vTemp ); while ( !Prs_ManIsChar(p, '\n') ) { int iToken = Prs_ManReadName(p); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read formal name.", 1); Vec_IntPush( &p->vTemp, iToken ); Prs_ManSkipSpaces( p ); if ( !Prs_ManIsChar2(p, '=') ) return Prs_ManErrorSet(p, "Cannot find symbol \"=\".", 1); iToken = Prs_ManReadName(p); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read actual name.", 1); Vec_IntPush( &p->vTemp, iToken ); Prs_ManSkipSpaces( p ); } if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1); if ( Vec_IntSize(&p->vTemp) % 2 ) return Prs_ManErrorSet(p, "The number of formal/actual names is not even.", 1); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Prs_ManReadCube( Prs_Man_t * p ) { assert( Prs_ManIsLit(p) ); while ( Prs_ManIsLit(p) ) Vec_StrPush( &p->vCover, Prs_ManSkip2(p) ); Prs_ManSkipSpaces( p ); if ( Prs_ManIsChar(p, '\n') ) { if ( Vec_StrSize(&p->vCover) != 1 ) return Prs_ManErrorSet(p, "Cannot read cube.", 1); // fix single literal cube by adding space Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) ); Vec_StrWriteEntry( &p->vCover, 0, ' ' ); Vec_StrPush( &p->vCover, '\n' ); return 0; } if ( !Prs_ManIsLit(p) ) return Prs_ManErrorSet(p, "Cannot read output literal.", 1); Vec_StrPush( &p->vCover, ' ' ); Vec_StrPush( &p->vCover, Prs_ManSkip2(p) ); Vec_StrPush( &p->vCover, '\n' ); Prs_ManSkipSpaces( p ); if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Cannot read end of cube.", 1); return 0; } static inline void Prs_ManSaveCover( Prs_Man_t * p ) { int iToken; if ( Vec_StrSize(&p->vCover) == 0 ) p->pNtk->fHasC0s = 1; else if ( Vec_StrSize(&p->vCover) == 2 ) { if ( Vec_StrEntryLast(&p->vCover) == '0' ) p->pNtk->fHasC0s = 1; else if ( Vec_StrEntryLast(&p->vCover) == '1' ) p->pNtk->fHasC1s = 1; else assert( 0 ); } assert( Vec_StrSize(&p->vCover) > 0 ); Vec_StrPush( &p->vCover, '\0' ); // iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) ); iToken = Abc_NamStrFindOrAdd( p->pFuns, Vec_StrArray(&p->vCover), NULL ); Vec_StrClear( &p->vCover ); // set the cover to the module of this box assert( Prs_BoxNtk(p->pNtk, Prs_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0 Prs_BoxSetNtk( p->pNtk, Prs_NtkBoxNum(p->pNtk)-1, iToken ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Prs_ManReadInouts( Prs_Man_t * p ) { if ( Prs_ManReadList(p, &p->pNtk->vOrder, 3) ) return 1; Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp ); return 0; } static inline int Prs_ManReadInputs( Prs_Man_t * p ) { if ( Prs_ManReadList(p, &p->pNtk->vOrder, 1) ) return 1; Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp ); return 0; } static inline int Prs_ManReadOutputs( Prs_Man_t * p ) { if ( Prs_ManReadList(p, &p->pNtk->vOrder, 2) ) return 1; Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp ); return 0; } static inline int Prs_ManReadNode( Prs_Man_t * p ) { if ( Prs_ManReadList2(p) ) return 1; // save results Prs_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function return 0; } static inline int Prs_ManReadBox( Prs_Man_t * p, int fGate ) { int iToken = Prs_ManReadName(p); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read model name.", 1); if ( Prs_ManReadList3(p) ) return 1; // save results Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp ); if ( fGate ) p->pNtk->fMapped = 1; return 0; } static inline int Prs_ManReadLatch( Prs_Man_t * p ) { int iToken = Prs_ManReadName(p); Vec_IntClear( &p->vTemp ); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read latch input.", 1); Vec_IntWriteEntry( &p->vTemp, 1, iToken ); iToken = Prs_ManReadName(p); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read latch output.", 1); Vec_IntWriteEntry( &p->vTemp, 0, iToken ); Prs_ManSkipSpaces( p ); if ( Prs_ManIsChar(p, '0') ) iToken = 0; else if ( Prs_ManIsChar(p, '1') ) iToken = 1; else iToken = 2; Prs_ManSkipToChar( p, '\n' ); // save results Prs_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch return 0; } static inline int Prs_ManReadShort( Prs_Man_t * p ) { int iToken = Prs_ManReadName(p); Vec_IntClear( &p->vTemp ); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read .short input.", 1); Vec_IntWriteEntry( &p->vTemp, 1, iToken ); iToken = Prs_ManReadName(p); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read .short output.", 1); Vec_IntWriteEntry( &p->vTemp, 0, iToken ); Prs_ManSkipSpaces( p ); if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .short line.", 1); // save results iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL ); Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp ); return 0; } static inline int Prs_ManReadModel( Prs_Man_t * p ) { int iToken; if ( p->pNtk != NULL ) return Prs_ManErrorSet(p, "Parsing previous model is unfinished.", 1); iToken = Prs_ManReadName(p); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read model name.", 1); Prs_ManInitializeNtk( p, iToken, 0 ); Prs_ManSkipSpaces( p ); if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .model line.", 1); return 0; } static inline int Prs_ManReadEnd( Prs_Man_t * p ) { if ( p->pNtk == 0 ) return Prs_ManErrorSet(p, "Directive .end without .model.", 1); //printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) ); Prs_ManFinalizeNtk( p ); Prs_ManSkipSpaces( p ); if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .end line.", 1); return 0; } static inline int Prs_ManReadDirective( Prs_Man_t * p ) { int iToken; if ( !Prs_ManIsChar(p, '.') ) return Prs_ManReadCube( p ); if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node Prs_ManSaveCover( p ); iToken = Prs_ManReadName( p ); if ( iToken == PRS_BLIF_MODEL ) return Prs_ManReadModel( p ); if ( iToken == PRS_BLIF_INOUTS ) return Prs_ManReadInouts( p ); if ( iToken == PRS_BLIF_INPUTS ) return Prs_ManReadInputs( p ); if ( iToken == PRS_BLIF_OUTPUTS ) return Prs_ManReadOutputs( p ); if ( iToken == PRS_BLIF_NAMES ) return Prs_ManReadNode( p ); if ( iToken == PRS_BLIF_SUBCKT ) return Prs_ManReadBox( p, 0 ); if ( iToken == PRS_BLIF_GATE ) return Prs_ManReadBox( p, 1 ); if ( iToken == PRS_BLIF_LATCH ) return Prs_ManReadLatch( p ); if ( iToken == PRS_BLIF_SHORT ) return Prs_ManReadShort( p ); if ( iToken == PRS_BLIF_END ) return Prs_ManReadEnd( p ); printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) ); return 1; } static inline int Prs_ManReadLines( Prs_Man_t * p ) { while ( p->pCur[1] != '\0' ) { assert( Prs_ManIsChar(p, '\n') ); Prs_ManSkip(p); Prs_ManSkipSpaces( p ); if ( Prs_ManIsChar(p, '\n') ) continue; if ( Prs_ManReadDirective(p) ) return 1; } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Prs_ManReadBlif( char * pFileName ) { Vec_Ptr_t * vPrs = NULL; Prs_Man_t * p = Prs_ManAlloc( pFileName ); if ( p == NULL ) return NULL; Abc_NamStrFindOrAdd( p->pFuns, " 0\n", NULL ); Abc_NamStrFindOrAdd( p->pFuns, " 1\n", NULL ); Prs_NtkAddBlifDirectives( p ); Prs_ManReadLines( p ); if ( Prs_ManErrorPrint(p) ) ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks ); Prs_ManFree( p ); return vPrs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Prs_ManReadBlifTest( char * pFileName ) { abctime clk = Abc_Clock(); Vec_Ptr_t * vPrs = Prs_ManReadBlif( pFileName ); if ( !vPrs ) return; printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) ); printf( "NameIDs = %d. ", Abc_NamObjNumMax(Prs_ManNameMan(vPrs)) ); printf( "Memory = %.2f MB. ", 1.0*Prs_ManMemory(vPrs)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // Abc_NamPrint( p->pStrs ); Prs_ManWriteBlif( Extra_FileNameGenericAppend(pFileName, "_out.blif"), vPrs ); Prs_ManVecFree( vPrs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Prs_CreateBlifFindFon( Cba_Ntk_t * p, int NameId ) { int iFon = Cba_NtkGetMap( p, NameId ); if ( iFon ) return iFon; printf( "Network \"%s\": Signal \"%s\" is not driven.\n", Cba_NtkName(p), Cba_NtkStr(p, NameId) ); return 0; } void Prs_CreateBlifPio( Cba_Ntk_t * p, Prs_Ntk_t * pNtk ) { int i, NameId, iObj, iFon; Cba_NtkCleanObjFuncs( p ); Cba_NtkCleanObjNames( p ); Cba_NtkCleanFonNames( p ); // create inputs Prs_NtkForEachPi( pNtk, NameId, i ) { iObj = Cba_ObjAlloc( p, CBA_OBJ_PI, 0, 1 ); Cba_ObjSetName( p, iObj, NameId ); iFon = Cba_ObjFon0(p, iObj); Cba_FonSetName( p, iFon, NameId ); Cba_NtkSetMap( p, NameId, iFon ); Vec_IntPush( &p->vOrder, iObj ); } // create outputs Prs_NtkForEachPo( pNtk, NameId, i ) { iObj = Cba_ObjAlloc( p, CBA_OBJ_PO, 1, 0 ); Cba_ObjSetName( p, iObj, NameId ); Vec_IntPush( &p->vOrder, iObj ); } } int Prs_CreateBlifNtk( Cba_Ntk_t * p, Prs_Ntk_t * pNtk ) { Vec_Int_t * vBox; int i, k, iObj, iTerm, iFon, FormId, ActId; // map inputs Cba_NtkCleanMap( p ); Cba_NtkForEachPi( p, iObj, i ) Cba_NtkSetMap( p, Cba_ObjName(p, iObj), Cba_ObjFon0(p, iObj) ); // create objects Prs_NtkForEachBox( pNtk, vBox, i ) { int FuncId = Prs_BoxNtk(pNtk, i); assert( Prs_BoxIONum(pNtk, i) > 0 ); assert( Vec_IntSize(vBox) % 2 == 0 ); if ( FuncId == -1 ) // latch { iObj = Cba_ObjAlloc( p, CBA_BOX_DFFRS, 4, 1 ); Cba_NtkSetMap( p, Vec_IntEntry(vBox, 3), Cba_ObjFon0(p, iObj) ); // latch output Cba_ObjSetFunc( p, iObj, Prs_BoxName(pNtk, i)+1 ); // init + 1 } else if ( Prs_BoxIsNode(pNtk, i) ) // node { iObj = Cba_ObjAlloc( p, CBA_BOX_NODE, Prs_BoxIONum(pNtk, i)-1, 1 ); Cba_FonSetName( p, Cba_ObjFon0(p, iObj), Vec_IntEntryLast(vBox) ); // node output Cba_NtkSetMap( p, Vec_IntEntryLast(vBox), Cba_ObjFon0(p, iObj) ); Cba_ObjSetFunc( p, iObj, FuncId ); } else // box { Cba_Ntk_t * pBox = Cba_ManNtkFind( p->pDesign, Prs_NtkStr(pNtk, FuncId) ); iObj = Cba_ObjAlloc( p, CBA_OBJ_BOX, Cba_NtkPiNum(pBox), Cba_NtkPoNum(pBox) ); Cba_ObjSetFunc( p, iObj, Cba_NtkId(pBox) ); // mark PO objects Cba_NtkCleanMap2( p ); Cba_NtkForEachPo( pBox, iTerm, k ) Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 ); // map box fons Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) if ( Cba_NtkGetMap2(p, FormId) ) { iFon = Cba_ObjFon(p, iObj, Cba_NtkGetMap2(p, FormId)-1); Cba_FonSetName( p, iFon, ActId ); Cba_NtkSetMap( p, ActId, iFon ); } } } // connect objects Prs_NtkForEachBox( pNtk, vBox, i ) { iObj = Cba_NtkPiNum(p) + Cba_NtkPoNum(p) + i + 1; if ( Prs_BoxNtk(pNtk, i) == -1 ) // latch { assert( Cba_ObjType(p, iObj) == CBA_BOX_DFFRS ); iFon = Prs_CreateBlifFindFon( p, Vec_IntEntry(vBox, 1) ); // latch input if ( iFon ) Cba_ObjSetFinFon( p, iObj, 0, iFon ); } else if ( Prs_BoxIsNode(pNtk, i) ) // node { assert( Cba_ObjType(p, iObj) == CBA_BOX_NODE ); Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) { if ( k == 2 * Cba_ObjFinNum(p, iObj) ) // stop at node output break; iFon = Prs_CreateBlifFindFon( p, ActId ); if ( iFon ) Cba_ObjSetFinFon( p, iObj, k/2, iFon ); } } else // box { // mark PI objects Cba_Ntk_t * pBox = Cba_ObjNtk(p, iObj); assert( Cba_NtkPiNum(pBox) == Cba_ObjFinNum(p, iObj) ); assert( Cba_NtkPoNum(pBox) == Cba_ObjFonNum(p, iObj) ); Cba_NtkCleanMap2( p ); Cba_NtkForEachPi( pBox, iTerm, k ) Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 ); // connect box fins Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) if ( Cba_NtkGetMap2(p, FormId) ) { iFon = Prs_CreateBlifFindFon( p, ActId ); if ( iFon ) Cba_ObjSetFinFon( p, iObj, Cba_NtkGetMap2(p, FormId)-1, iFon ); } } } // connect outputs Cba_NtkForEachPo( p, iObj, i ) { iFon = Prs_CreateBlifFindFon( p, Cba_ObjName(p, iObj) ); if ( iFon ) Cba_ObjSetFinFon( p, iObj, 0, iFon ); } return 0; } Cba_Man_t * Prs_ManBuildCbaBlif( char * pFileName, Vec_Ptr_t * vDes ) { Prs_Ntk_t * pPrsNtk; int i, fError = 0; Prs_Ntk_t * pPrsRoot = Prs_ManRoot(vDes); // start the manager Abc_Nam_t * pStrs = Abc_NamRef(pPrsRoot->pStrs); Abc_Nam_t * pFuns = Abc_NamRef(pPrsRoot->pFuns); Abc_Nam_t * pMods = Abc_NamStart( 100, 24 ); Cba_Man_t * p = Cba_ManAlloc( pFileName, Vec_PtrSize(vDes), pStrs, pFuns, pMods, NULL ); // initialize networks Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i ) { Cba_Ntk_t * pNtk = Cba_NtkAlloc( p, Prs_NtkId(pPrsNtk), Prs_NtkPiNum(pPrsNtk), Prs_NtkPoNum(pPrsNtk), Prs_NtkObjNum(pPrsNtk), 100, 100 ); Prs_CreateBlifPio( pNtk, pPrsNtk ); Cba_NtkAdd( p, pNtk ); } // create networks Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i ) { printf( "Elaboration module \"%s\"...\n", Prs_NtkName(pPrsNtk) ); fError = Prs_CreateBlifNtk( Cba_ManNtk(p, i+1), pPrsNtk ); if ( fError ) break; } if ( fError ) printf( "Quitting because of errors.\n" ); else Cba_ManPrepareSeq( p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cba_Man_t * Cba_ManReadBlif( char * pFileName ) { Cba_Man_t * p = NULL; Vec_Ptr_t * vDes = Prs_ManReadBlif( pFileName ); if ( vDes && Vec_PtrSize(vDes) ) p = Prs_ManBuildCbaBlif( pFileName, vDes ); if ( vDes ) Prs_ManVecFree( vDes ); return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaReadVer.c000066400000000000000000002741011300674244400236420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaReadVer.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [BLIF writer.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: cbaReadVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cba.h" #include "cbaPrs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static const char * s_VerTypes[PRS_VER_UNKNOWN+1] = { NULL, // 0: unused "input", // 1: input "output", // 2: output "inout", // 3: inout "wire", // 4: wire "reg", // 5: reg "module", // 6: module "assign", // 7: assign "always", // 8: always "function", // 9: function "defparam", // 10: defparam "begin", // 11: begin "end", // 12: end "case", // 13: case "endcase", // 14: endcase "signed", // 15: signed "endmodule", // 16: endmodule NULL // 17: unknown }; void Prs_NtkAddVerilogDirectives( Prs_Man_t * p ) { int i; for ( i = 1; s_VerTypes[i]; i++ ) Abc_NamStrFindOrAdd( p->pStrs, (char *)s_VerTypes[i], NULL ); assert( Abc_NamObjNumMax(p->pStrs) == i ); } // character recognition static inline int Prs_CharIsSpace( char c ) { return (c == ' ' || c == '\t' || c == '\r' || c == '\n'); } static inline int Prs_CharIsDigit( char c ) { return (c >= '0' && c <= '9'); } static inline int Prs_CharIsDigitB( char c ) { return (c == '0' || c == '1' || c == 'x' || c == 'z'); } static inline int Prs_CharIsDigitH( char c ) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } static inline int Prs_CharIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } static inline int Prs_CharIsSymb1( char c ) { return Prs_CharIsChar(c) || c == '_'; } static inline int Prs_CharIsSymb2( char c ) { return Prs_CharIsSymb1(c) || Prs_CharIsDigit(c) || c == '$'; } static inline int Prs_ManIsChar( Prs_Man_t * p, char c ) { return p->pCur[0] == c; } static inline int Prs_ManIsChar1( Prs_Man_t * p, char c ) { return p->pCur[1] == c; } static inline int Prs_ManIsDigit( Prs_Man_t * p ) { return Prs_CharIsDigit(*p->pCur); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // predefined primitives typedef struct Prs_VerPrim_t_ Prs_VerPrim_t; struct Prs_VerPrim_t_ { int Type; char * pName; }; static const Prs_VerPrim_t s_VerilogPrims[16] = { {CBA_BOX_BUF, "buf" }, {CBA_BOX_INV, "not" }, {CBA_BOX_AND, "and" }, {CBA_BOX_NAND, "nand" }, {CBA_BOX_OR, "or" }, {CBA_BOX_NOR, "nor" }, {CBA_BOX_XOR, "xor" }, {CBA_BOX_XNOR, "xnor" }, {CBA_BOX_TRI, "bufif1"}, {0} }; // predefined operator names static const char * s_VerNames[100] = { NULL, "VERIFIC_", "add_", "mult_", "div_", "mod_", "rem_", "shift_left_", "shift_right_", "rotate_left_", "rotate_right_", "reduce_and_", "reduce_or_", "reduce_xor_", "reduce_nand_", "reduce_nor_", "reduce_xnor_", "LessThan_", "Mux_", "Select_", "Decoder_", "EnabledDecoder_", "PrioSelect_", "DualPortRam_", "ReadPort_", "WritePort_", "ClockedWritePort_", "lut", "and_", "or_", "xor_", "nand_", "nor_", "xnor_", "buf_", "inv_", "tri_", "sub_", "unary_minus_", "equal_", "not_equal_", "mux_", "wide_mux_", "wide_select_", "wide_dff_", "wide_dlatch_", "wide_dffrs_", "wide_dlatchrs_", "wide_prio_select_", "pow_", "PrioEncoder_", "abs_", "CPL_NMACROFF", "CPL_MACROFF", "CPL_FF", NULL }; typedef struct Prs_VerInfo_t_ Prs_VerInfo_t; struct Prs_VerInfo_t_ { int Type; int nInputs; char * pTypeName; char * pSigNames[6]; }; static const Prs_VerInfo_t s_VerInfo[100] = { {-1, 0, NULL, /* "PRIM_NONE" */ {NULL}}, {CBA_BOX_CT, 0, "VERIFIC_PWR", /* "PRIM_PWR" */ {"o"}}, {CBA_BOX_CF, 0, "VERIFIC_GND", /* "PRIM_GND" */ {"o"}}, {CBA_BOX_CX, 0, "VERIFIC_X", /* "PRIM_X" */ {"o"}}, {CBA_BOX_CZ, 0, "VERIFIC_Z", /* "PRIM_Z" */ {"o"}}, {CBA_BOX_INV, 1, "VERIFIC_INV", /* "PRIM_INV" */ {"i","o"}}, {CBA_BOX_BUF, 1, "VERIFIC_BUF", /* "PRIM_BUF" */ {"i","o"}}, {CBA_BOX_AND, 1, "VERIFIC_AND", /* "PRIM_AND" */ {"a0","a1","o"}}, {CBA_BOX_NAND, 2, "VERIFIC_NAND", /* "PRIM_NAND" */ {"a0","a1","o"}}, {CBA_BOX_OR, 2, "VERIFIC_OR", /* "PRIM_OR" */ {"a0","a1","o"}}, {CBA_BOX_NOR, 2, "VERIFIC_NOR", /* "PRIM_NOR" */ {"a0","a1","o"}}, {CBA_BOX_XOR, 2, "VERIFIC_XOR", /* "PRIM_XOR" */ {"a0","a1","o"}}, {CBA_BOX_XNOR, 2, "VERIFIC_XNOR", /* "PRIM_XNOR" */ {"a0","a1","o"}}, {CBA_BOX_MUX, 3, "VERIFIC_MUX", /* "PRIM_MUX" */ {"c","a1","a0","o"}}, // changed order {-1, 0, "VERIFIC_PULLUP", /* "PRIM_PULLUP" */ {"o"}}, {-1, 0, "VERIFIC_PULLDOWN", /* "PRIM_PULLDOWN" */ {"o"}}, {CBA_BOX_TRI, 3, "VERIFIC_TRI", /* "PRIM_TRI" */ {"i","c","o"}}, {CBA_BOX_LATCHRS, 4, "VERIFIC_DLATCHRS", /* "PRIM_DLATCHRS" */ {"d","s","r","gate","q"}}, // changed order {CBA_BOX_LATCH, 4, "VERIFIC_DLATCH", /* "PRIM_DLATCH" */ {"d","async_val","async_cond","gate","q"}}, // changed order {CBA_BOX_DFFRS, 4, "VERIFIC_DFFRS", /* "PRIM_DFFRS" */ {"d","s","r","clk","q"}}, // changed order {CBA_BOX_DFF, 4, "VERIFIC_DFF", /* "PRIM_DFF" */ {"d","async_val","async_cond","clk","q"}}, // changed order {-1, 2, "VERIFIC_NMOS", /* "PRIM_NMOS" */ {"c","d","o"}}, {-1, 2, "VERIFIC_PMOS", /* "PRIM_PMOS" */ {"c","d","o"}}, {-1, 3, "VERIFIC_CMOS", /* "PRIM_CMOS" */ {"d","nc","pc","o"}}, {-1, 2, "VERIFIC_TRAN", /* "PRIM_TRAN" */ {"inout1","inout2","control"}}, {CBA_BOX_ADD, 3, "VERIFIC_FADD", /* "PRIM_FADD" */ {"cin","a","b","o","cout"}}, {-1, 3, "VERIFIC_RCMOS", /* "PRIM_RCMOS" */ {"d","nc","pc","o"}}, {-1, 2, "VERIFIC_RNMOS", /* "PRIM_RNMOS" */ {"c","d","o"}}, {-1, 2, "VERIFIC_RPMOS", /* "PRIM_RPMOS" */ {"c","d","o"}}, {-1, 2, "VERIFIC_RTRAN", /* "PRIM_RTRAN" */ {"inout1","inout2","control"}}, {-1, 0, "VERIFIC_HDL_ASSERTION", /* "PRIM_HDL_ASSERTION" */ {"condition"}}, {CBA_BOX_ADD, 3, "add_", /* "OPER_ADDER" */ {"cin","a","b","o","cout"}}, {CBA_BOX_MUL, 2, "mult_", /* "OPER_MULTIPLIER" */ {"a","b","o"}}, {CBA_BOX_DIV, 2, "div_", /* "OPER_DIVIDER" */ {"a","b","o"}}, {CBA_BOX_MOD, 2, "mod_", /* "OPER_MODULO" */ {"a","b","o"}}, {CBA_BOX_REM, 2, "rem_", /* "OPER_REMAINDER" */ {"a","b","o"}}, {CBA_BOX_SHIL, 3, "shift_left_", /* "OPER_SHIFT_LEFT" */ {"cin","a","amount","o"}}, {CBA_BOX_SHIR, 3, "shift_right_", /* "OPER_SHIFT_RIGHT" */ {"cin","a","amount","o"}}, {CBA_BOX_ROTL, 2, "rotate_left_", /* "OPER_ROTATE_LEFT" */ {"a","amount","o"}}, {CBA_BOX_ROTR, 2, "rotate_right_", /* "OPER_ROTATE_RIGHT" */ {"a","amount","o"}}, {CBA_BOX_RAND, 1, "reduce_and_", /* "OPER_REDUCE_AND" */ {"a","o"}}, {CBA_BOX_ROR, 1, "reduce_or_", /* "OPER_REDUCE_OR" */ {"a","o"}}, {CBA_BOX_RXOR, 1, "reduce_xor_", /* "OPER_REDUCE_XOR" */ {"a","o"}}, {CBA_BOX_RNAND, 1, "reduce_nand_", /* "OPER_REDUCE_NAND" */ {"a","o"}}, {CBA_BOX_RNOR, 1, "reduce_nor_", /* "OPER_REDUCE_NOR" */ {"a","o"}}, {CBA_BOX_RXNOR, 1, "reduce_xnor_", /* "OPER_REDUCE_XNOR" */ {"a","o"}}, {CBA_BOX_LTHAN, 3, "LessThan_", /* "OPER_LESSTHAN" */ {"cin","a","b","o"}}, {CBA_BOX_NMUX, 2, "Mux_", /* "OPER_NTO1MUX" */ {"sel","data","o"}}, {CBA_BOX_SEL, 2, "Select_", /* "OPER_SELECTOR" */ {"sel","data","o"}}, {CBA_BOX_DEC, 1, "Decoder_", /* "OPER_DECODER" */ {"a","o"}}, {CBA_BOX_EDEC, 2, "EnabledDecoder_", /* "OPER_ENABLED_DECODER" */ {"en","i","o"}}, {CBA_BOX_PSEL, 3, "PrioSelect_", /* "OPER_PRIO_SELECTOR" */ {"cin","sel","data","o"}}, {CBA_BOX_RAM, 4, "DualPortRam_", /* "OPER_DUAL_PORT_RAM" */ {"write_enable","write_address","write_data","read_address","read_data"}}, {CBA_BOX_RAMR, 3, "ReadPort_", /* "OPER_READ_PORT" */ {"read_enable", "read_address", "Ram", "read_data" }}, {CBA_BOX_RAMW, 3, "WritePort_", /* "OPER_WRITE_PORT" */ {"write_enable","write_address","write_data", "Ram"}}, {CBA_BOX_RAMWC, 4, "ClockedWritePort_", /* "OPER_CLOCKED_WRITE_PORT" */ {"clk","write_enable","write_address","write_data", "Ram"}}, {CBA_BOX_LUT, 1, "lut", /* "OPER_LUT" */ {"i","o"}}, {CBA_BOX_AND, 2, "and_", /* "OPER_WIDE_AND" */ {"a","b","o"}}, {CBA_BOX_OR, 2, "or_", /* "OPER_WIDE_OR" */ {"a","b","o"}}, {CBA_BOX_XOR, 2, "xor_", /* "OPER_WIDE_XOR" */ {"a","b","o"}}, {CBA_BOX_NAND, 2, "nand_", /* "OPER_WIDE_NAND" */ {"a","b","o"}}, {CBA_BOX_NOR, 2, "nor_", /* "OPER_WIDE_NOR" */ {"a","b","o"}}, {CBA_BOX_XNOR, 2, "xnor_", /* "OPER_WIDE_XNOR" */ {"a","b","o"}}, {CBA_BOX_BUF, 1, "buf_", /* "OPER_WIDE_BUF" */ {"i","o"}}, {CBA_BOX_INV, 1, "inv_", /* "OPER_WIDE_INV" */ {"i","o"}}, {CBA_BOX_TRI, 2, "tri_", /* "OPER_WIDE_TRI" */ {"i","c","o"}}, {CBA_BOX_SUB, 2, "sub_", /* "OPER_MINUS" */ {"a","b","o"}}, {CBA_BOX_MIN, 1, "unary_minus_", /* "OPER_UMINUS" */ {"i","o"}}, {CBA_BOX_EQU, 2, "equal_", /* "OPER_EQUAL" */ {"a","b","o"}}, {CBA_BOX_NEQU, 2, "not_equal_", /* "OPER_NEQUAL" */ {"a","b","o"}}, {CBA_BOX_MUX, 3, "mux_", /* "OPER_WIDE_MUX" */ {"cond","d1","d0","o"}}, // changed order {CBA_BOX_NMUX, 2, "wide_mux_", /* "OPER_WIDE_NTO1MUX" */ {"sel","data","o"}}, {CBA_BOX_SEL, 2, "wide_select_", /* "OPER_WIDE_SELECTOR" */ {"sel","data","o"}}, {CBA_BOX_DFF, 4, "wide_dff_", /* "OPER_WIDE_DFF" */ {"d","async_val","async_cond","clock","q"}}, {CBA_BOX_DFFRS, 4, "wide_dffrs_", /* "OPER_WIDE_DFFRS" */ {"d","set","reset","clock","q"}}, {CBA_BOX_LATCHRS, 4, "wide_dlatchrs_", /* "OPER_WIDE_DLATCHRS" */ {"d","set","reset","clock","q"}}, {CBA_BOX_LATCH, 4, "wide_dlatch_", /* "OPER_WIDE_DLATCH" */ {"d","async_val","async_cond","clock","q"}}, {CBA_BOX_PSEL, 3, "wide_prio_select_", /* "OPER_WIDE_PRIO_SELECTOR" */ {"sel","data","carry_in","o"}}, {CBA_BOX_POW, 2, "pow_", /* "OPER_POW" */ {"a","b","o"}}, {CBA_BOX_PENC, 1, "PrioEncoder_", /* "OPER_PRIO_ENCODER" */ {"sel","o"}}, {CBA_BOX_ABS, 1, "abs_", /* "OPER_ABS" */ {"i","o"}}, {CBA_BOX_DFFCPL, 4, "CPL_FF", /* "OPER_WIDE_DFF - 2" */ {"d","arstval","arst","clk","q","qbar"}}, {-1, 0, NULL, /* "PRIM_END" */ {NULL}} }; // check if it is a Verilog predefined module static inline int Prs_ManIsVerilogPrim( char * pName ) { int i; for ( i = 0; s_VerilogPrims[i].pName; i++ ) if ( !strcmp(pName, s_VerilogPrims[i].pName) ) return s_VerilogPrims[i].Type; return 0; } // check if it is a known module static inline int Prs_ManIsKnownModule( char * pName ) { int i, Length; for ( i = 1; s_VerNames[i]; i++ ) { Length = strlen(s_VerNames[i]); // if ( !strncmp(pName, s_VerNames[i], Length) && (i == 1 || (pName[Length] >= '0' && pName[Length] <= '9')) ) if ( !strncmp(pName, s_VerNames[i], Length) ) return i; } return 0; } // check if it is a known module static inline int Prs_ManFindType( char * pName, int * pInputs, int fOut, char *** ppNames ) { int i, Length; *pInputs = -1; for ( i = 1; s_VerInfo[i].pTypeName; i++ ) { Length = strlen(s_VerInfo[i].pTypeName); if ( !strncmp(pName, s_VerInfo[i].pTypeName, Length) ) { *pInputs = s_VerInfo[i].nInputs; *ppNames = (char **)s_VerInfo[i].pSigNames + (fOut ? s_VerInfo[i].nInputs : 0); return s_VerInfo[i].Type; } } return CBA_OBJ_BOX; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // skips Verilog comments (returns 1 if some comments were skipped) static inline int Prs_ManUtilSkipComments( Prs_Man_t * p ) { if ( !Prs_ManIsChar(p, '/') ) return 0; if ( Prs_ManIsChar1(p, '/') ) { for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) if ( Prs_ManIsChar(p, '\n') ) { p->pCur++; return 1; } } else if ( Prs_ManIsChar1(p, '*') ) { for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ ) if ( Prs_ManIsChar(p, '*') && Prs_ManIsChar1(p, '/') ) { p->pCur++; p->pCur++; return 1; } } return 0; } static inline int Prs_ManUtilSkipName( Prs_Man_t * p ) { if ( !Prs_ManIsChar(p, '\\') ) return 0; for ( p->pCur++; p->pCur < p->pLimit; p->pCur++ ) if ( Prs_ManIsChar(p, ' ') ) { p->pCur++; return 1; } return 0; } // skip any number of spaces and comments static inline int Prs_ManUtilSkipSpaces( Prs_Man_t * p ) { while ( p->pCur < p->pLimit ) { while ( Prs_CharIsSpace(*p->pCur) ) p->pCur++; if ( !*p->pCur ) return Prs_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); if ( !Prs_ManUtilSkipComments(p) ) return 0; } return Prs_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1); } // skip everything including comments until the given char static inline int Prs_ManUtilSkipUntil( Prs_Man_t * p, char c ) { while ( p->pCur < p->pLimit ) { if ( Prs_ManIsChar(p, c) ) return 1; if ( Prs_ManUtilSkipComments(p) ) continue; if ( Prs_ManUtilSkipName(p) ) continue; p->pCur++; } return 0; } // skip everything including comments until the given word static inline int Prs_ManUtilSkipUntilWord( Prs_Man_t * p, char * pWord ) { char * pPlace = strstr( p->pCur, pWord ); if ( pPlace == NULL ) return 1; p->pCur = pPlace + strlen(pWord); return 0; } // detect two symbols on the same line static inline int Prs_ManUtilDetectTwo( Prs_Man_t * p, char Sym1, char Sym2 ) { char * pTemp; for ( pTemp = p->pCur; *pTemp != ';'; pTemp++ ) if ( *pTemp == Sym1 && *pTemp == Sym2 ) return 1; return 0; } // find closing paren static inline char * Prs_ManFindClosingParenthesis( Prs_Man_t * p, char Open, char Close ) { char * pTemp; int Counter = 0; int fNotName = 1; assert( Prs_ManIsChar(p, Open) ); for ( pTemp = p->pCur; *pTemp; pTemp++ ) { if ( fNotName ) { if ( *pTemp == Open ) Counter++; if ( *pTemp == Close ) Counter--; if ( Counter == 0 ) return pTemp; } if ( *pTemp == '\\' ) fNotName = 0; else if ( !fNotName && *pTemp == ' ' ) fNotName = 1; } return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Prs_ManReadName( Prs_Man_t * p ) { char * pStart = p->pCur; if ( Prs_ManIsChar(p, '\\') ) // escaped name { pStart = ++p->pCur; while ( !Prs_ManIsChar(p, ' ') ) p->pCur++; } else if ( Prs_CharIsSymb1(*p->pCur) ) // simple name { p->pCur++; while ( Prs_CharIsSymb2(*p->pCur) ) p->pCur++; } else return 0; return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL ); } static inline int Prs_ManReadNameList( Prs_Man_t * p, Vec_Int_t * vTemp, char LastSymb ) { Vec_IntClear( vTemp ); while ( 1 ) { int Item = Prs_ManReadName(p); if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read name in the list.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 1.", 0); if ( Item == PRS_VER_WIRE ) continue; Vec_IntPush( vTemp, Item ); if ( Prs_ManIsChar(p, LastSymb) ) break; if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the list.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 2.", 0); } return 1; } static inline int Prs_ManReadConstant( Prs_Man_t * p ) { char * pStart = p->pCur; assert( Prs_ManIsDigit(p) ); while ( Prs_ManIsDigit(p) ) p->pCur++; if ( !Prs_ManIsChar(p, '\'') ) return Abc_NamStrFindOrAddLim( p->pFuns, pStart, p->pCur, NULL ); p->pCur++; if ( Prs_ManIsChar(p, 's') ) p->pCur++; if ( Prs_ManIsChar(p, 'b') ) { p->pCur++; while ( Prs_CharIsDigitB(*p->pCur) ) { if ( *p->pCur == '0' ) p->pNtk->fHasC0s = 1; else if ( *p->pCur == '1' ) p->pNtk->fHasC1s = 1; else if ( *p->pCur == 'x' ) p->pNtk->fHasCXs = 1; else if ( *p->pCur == 'z' ) p->pNtk->fHasCZs = 1; p->pCur++; } } else if ( Prs_ManIsChar(p, 'h') ) { p->pCur++; p->pNtk->fHasC0s = 1; while ( Prs_CharIsDigitH(*p->pCur) ) { if ( *p->pCur != '0' ) p->pNtk->fHasC1s = 1; p->pCur++; } } else if ( Prs_ManIsChar(p, 'd') ) { p->pCur++; p->pNtk->fHasC0s = 1; while ( Prs_ManIsDigit(p) ) { if ( *p->pCur != '0' ) p->pNtk->fHasC1s = 1; p->pCur++; } } else return Prs_ManErrorSet(p, "Cannot read radix of constant.", 0); return Abc_NamStrFindOrAddLim( p->pFuns, pStart, p->pCur, NULL ); } static inline int Prs_ManReadRange( Prs_Man_t * p ) { int Left, Right; assert( Prs_ManIsChar(p, '[') ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 3.", 0); if ( !Prs_ManIsDigit(p) ) return Prs_ManErrorSet(p, "Cannot read digit in range specification.", 0); Left = Right = atoi(p->pCur); while ( Prs_ManIsDigit(p) ) p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 4.", 0); if ( Prs_ManIsChar(p, ':') ) { p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 5.", 0); if ( !Prs_ManIsDigit(p) ) return Prs_ManErrorSet(p, "Cannot read digit in range specification.", 0); Right = atoi(p->pCur); while ( Prs_ManIsDigit(p) ) p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 6.", 0); } if ( !Prs_ManIsChar(p, ']') ) return Prs_ManErrorSet(p, "Cannot read closing brace in range specification.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 6a.", 0); return Hash_Int2ManInsert( p->vHash, Left, Right, 0 ); } static inline int Prs_ManReadConcat( Prs_Man_t * p, Vec_Int_t * vTemp2 ) { extern int Prs_ManReadSignalList( Prs_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ); assert( Prs_ManIsChar(p, '{') ); p->pCur++; if ( !Prs_ManReadSignalList( p, vTemp2, '}', 0 ) ) return Prs_ManErrorSet(p, "Error number 7.", 0); // check final assert( Prs_ManIsChar(p, '}') ); p->pCur++; // return special case assert( Vec_IntSize(vTemp2) > 0 ); if ( Vec_IntSize(vTemp2) == 1 ) return Vec_IntEntry(vTemp2, 0); return Abc_Var2Lit2( Prs_NtkAddConcat(p->pNtk, vTemp2), CBA_PRS_CONCAT ); } static inline int Prs_ManReadSignal( Prs_Man_t * p ) { int Item; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 8.", 0); if ( Prs_ManIsDigit(p) ) { Item = Prs_ManReadConstant(p); if ( Item == 0 ) return 0; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); return Abc_Var2Lit2( Item, CBA_PRS_CONST ); } if ( Prs_ManIsChar(p, '{') ) { if ( Prs_CharIsDigit(p->pCur[1]) ) { p->pCur++; if ( Prs_ManIsDigit(p) ) { int i, Num = atoi(p->pCur); while ( Prs_ManIsDigit(p) ) p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); assert( Prs_ManIsChar(p, '{') ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); Item = Prs_ManReadSignal( p ); assert( Prs_ManIsChar(p, '}') ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); // add to concat all, expect the last one assert( p->fUsingTemp2 ); for ( i = 0; i < Num-1; i++ ) Vec_IntPush( &p->vTemp2, Item ); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); assert( Prs_ManIsChar(p, '}') ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 10.", 0); return Item; } } if ( p->fUsingTemp2 ) return Prs_ManErrorSet(p, "Cannot read nested concatenations.", 0); p->fUsingTemp2 = 1; Item = Prs_ManReadConcat(p, &p->vTemp2); p->fUsingTemp2 = 0; if ( Item == 0 ) return 0; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 12.", 0); return Item; } else { Item = Prs_ManReadName( p ); if ( Item == 0 ) return 1; // no actual name if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 14.", 0); if ( Prs_ManIsChar(p, '[') ) { int Range = Prs_ManReadRange(p); if ( Range == 0 ) return Prs_ManErrorSet(p, "Error number 15.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 16.", 0); return Abc_Var2Lit2( Prs_NtkAddSlice(p->pNtk, Item, Range), CBA_PRS_SLICE ); } return Abc_Var2Lit2( Item, CBA_PRS_NAME ); } } int Prs_ManReadSignalList( Prs_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm ) { Vec_IntClear( vTemp ); while ( 1 ) { int Item = Prs_ManReadSignal(p); if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read signal in the list.", 0); if ( fAddForm ) Vec_IntPush( vTemp, 0 ); Vec_IntPush( vTemp, Item ); if ( Prs_ManIsChar(p, LastSymb) ) break; if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the list.", 0); p->pCur++; } return 1; } static inline int Prs_ManReadSignalList2( Prs_Man_t * p, Vec_Int_t * vTemp ) { int FormId, ActItem; Vec_IntClear( vTemp ); assert( Prs_ManIsChar(p, '.') ); while ( Prs_ManIsChar(p, '.') ) { p->pCur++; FormId = Prs_ManReadName( p ); if ( FormId == 0 ) return Prs_ManErrorSet(p, "Cannot read formal name of the instance.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 17.", 0); if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Cannot read \"(\" in the instance.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 17.", 0); ActItem = Prs_ManReadSignal( p ); if ( ActItem == 0 ) return Prs_ManErrorSet(p, "Cannot read actual name of an instance.", 0); if ( !Prs_ManIsChar(p, ')') ) return Prs_ManErrorSet(p, "Cannot read \")\" in the instance.", 0); p->pCur++; if ( ActItem != 1 ) Vec_IntPushTwo( vTemp, FormId, ActItem ); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 18.", 0); if ( Prs_ManIsChar(p, ')') ) break; if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the instance.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 19.", 0); } assert( Vec_IntSize(vTemp) > 0 ); assert( Vec_IntSize(vTemp) % 2 == 0 ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Prs_ManReadFunction( Prs_Man_t * p ) { // this is a hack to read functions produced by ABC Verilog writer p->FuncNameId = p->FuncRangeId = 0; if ( Prs_ManUtilSkipUntilWord( p, "_func_" ) ) return Prs_ManErrorSet(p, "Cannot find \"_func_\" keyword.", 0); p->pCur -= 6; p->FuncNameId = Prs_ManReadName( p ); if ( p->FuncNameId == 0 ) return Prs_ManErrorSet(p, "Error number 30a.", 0); if ( Prs_ManUtilSkipUntilWord( p, "input" ) ) return Prs_ManErrorSet(p, "Cannot find \"input\" keyword.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 30b.", 0); if ( Prs_ManIsChar(p, '[') ) p->FuncRangeId = Prs_ManReadRange(p); else if ( Prs_ManReadName(p) == PRS_VER_SIGNED ) { if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 30c.", 0); if ( Prs_ManIsChar(p, '[') ) p->FuncRangeId = Prs_ManReadRange(p); } if ( Prs_ManUtilSkipUntilWord( p, "endfunction" ) ) return Prs_ManErrorSet(p, "Cannot find \"endfunction\" keyword.", 0); return 1; } static inline int Prs_ManReadAlways( Prs_Man_t * p ) { // this is a hack to read always-statement representing case-statement int iToken; char * pClose; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23.", 0); if ( !Prs_ManIsChar(p, '@') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); pClose = Prs_ManFindClosingParenthesis( p, '(', ')' ); if ( pClose == NULL ) return Prs_ManErrorSet(p, "Expecting closing parenthesis 1.", 0); p->pCur = pClose; if ( !Prs_ManIsChar(p, ')') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); p->pCur++; // read begin if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); iToken = Prs_ManReadName( p ); if ( iToken != PRS_VER_BEGIN ) return Prs_ManErrorSet(p, "Cannot read \"begin\" keyword.", 0); // read case if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); iToken = Prs_ManReadName( p ); if ( iToken != PRS_VER_CASE ) return Prs_ManErrorSet(p, "Cannot read \"case\" keyword.", 0); // read control if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); iToken = Prs_ManReadSignal( p ); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); if ( !Prs_ManIsChar(p, ')') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); p->pCur++; // save control Vec_IntClear( &p->vTemp3 ); Vec_IntPushTwo( &p->vTemp3, 0, 0 ); // output will go here Vec_IntPushTwo( &p->vTemp3, 0, iToken ); // read conditions if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); if ( !Prs_ManIsDigit(p) ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); while ( Prs_ManIsDigit(p) ) { while ( Prs_ManIsDigit(p) ) p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); if ( !Prs_ManIsChar(p, ':') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); // read output iToken = Prs_ManReadSignal( p ); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); if ( !Prs_ManIsChar(p, '=') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); p->pCur++; // save output Vec_IntWriteEntry( &p->vTemp3, 1, iToken ); // read input iToken = Prs_ManReadSignal( p ); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); if ( !Prs_ManIsChar(p, ';') ) return Prs_ManErrorSet(p, "Cannot parse always statement.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); // save input Vec_IntPushTwo( &p->vTemp3, 0, iToken ); } // read endcase if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); iToken = Prs_ManReadName( p ); if ( iToken != PRS_VER_ENDCASE ) return Prs_ManErrorSet(p, "Cannot read \"endcase\" keyword.", 0); // read end if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); iToken = Prs_ManReadName( p ); if ( iToken != PRS_VER_END ) return Prs_ManErrorSet(p, "Cannot read \"end\" keyword.", 0); // save binary operator Prs_NtkAddBox( p->pNtk, CBA_BOX_NMUX, 0, &p->vTemp3 ); return 1; } /* static inline int Prs_ManReadExpression( Prs_Man_t * p, int OutItem ) { int InItem, fCompl = 0, fCompl2 = 0, Oper = 0; // read output name if ( Prs_ManIsChar(p, '~') ) { fCompl = 1; p->pCur++; } // write output name Vec_IntClear( &p->vTemp ); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, OutItem ); // read first name InItem = Prs_ManReadSignal( p ); if ( InItem == 0 ) return Prs_ManErrorSet(p, "Cannot read first input name in the assign-statement.", 0); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, InItem ); // check unary operator if ( Prs_ManIsChar(p, ';') ) { Oper = fCompl ? CBA_BOX_INV : CBA_BOX_BUF; Prs_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); return 1; } if ( Prs_ManIsChar(p, '&') ) Oper = CBA_BOX_AND; else if ( Prs_ManIsChar(p, '|') ) Oper = CBA_BOX_OR; else if ( Prs_ManIsChar(p, '^') ) Oper = CBA_BOX_XOR; else if ( Prs_ManIsChar(p, '?') ) Oper = CBA_BOX_MUX; else return Prs_ManErrorSet(p, "Unrecognized operator in the assign-statement.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); if ( Prs_ManIsChar(p, '~') ) { fCompl2 = 1; p->pCur++; } // read second name InItem = Prs_ManReadSignal( p ); if ( InItem == 0 ) return Prs_ManErrorSet(p, "Cannot read second input name in the assign-statement.", 0); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, InItem ); // read third argument if ( Oper == CBA_BOX_MUX ) { assert( fCompl == 0 ); if ( !Prs_ManIsChar(p, ':') ) return Prs_ManErrorSet(p, "Expected colon in the MUX assignment.", 0); p->pCur++; // read third name InItem = Prs_ManReadSignal( p ); if ( InItem == 0 ) return Prs_ManErrorSet(p, "Cannot read third input name in the assign-statement.", 0); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, InItem ); if ( !Prs_ManIsChar(p, ';') ) return Prs_ManErrorSet(p, "Expected semicolon at the end of the assign-statement.", 0); } else { // figure out operator if ( Oper == CBA_BOX_AND ) { if ( fCompl && !fCompl2 ) Oper = CBA_BOX_SHARPL; else if ( !fCompl && fCompl2 ) Oper = CBA_BOX_SHARP; else if ( fCompl && fCompl2 ) Oper = CBA_BOX_NOR; } else if ( Oper == CBA_BOX_OR ) { if ( fCompl && fCompl2 ) Oper = CBA_BOX_NAND; else assert( !fCompl && !fCompl2 ); } else if ( Oper == CBA_BOX_XOR ) { if ( fCompl && !fCompl2 ) Oper = CBA_BOX_XNOR; else assert( !fCompl && !fCompl2 ); } } // save binary operator Prs_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp ); return 1; } */ static inline int Prs_ManReadExpression( Prs_Man_t * p, int OutItem ) { char * pClose; int Item, Type = CBA_OBJ_NONE; int fRotating = 0; // write output name Vec_IntClear( &p->vTemp ); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, OutItem ); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); if ( Prs_ManIsChar(p, '(') ) { // THIS IS A HACK TO DETECT rotating shifters: try to find both << and >> on the same line if ( Prs_ManUtilDetectTwo(p, '>', '>') && Prs_ManUtilDetectTwo(p, '<', '<') ) fRotating = 1; pClose = Prs_ManFindClosingParenthesis( p, '(', ')' ); if ( pClose == NULL ) return Prs_ManErrorSet(p, "Expecting closing parenthesis 1.", 0); *p->pCur = *pClose = ' '; } if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); // read constant or concatenation if ( Prs_ManIsDigit(p) || Prs_ManIsChar(p, '{') ) { Item = Prs_ManReadSignal( p ); // write constant Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, Item ); Type = CBA_BOX_BUF; } else if ( Prs_ManIsChar(p, '!') || Prs_ManIsChar(p, '~') || Prs_ManIsChar(p, '@') || Prs_ManIsChar(p, '&') || Prs_ManIsChar(p, '|') || Prs_ManIsChar(p, '^') || Prs_ManIsChar(p, '-') ) { if ( Prs_ManIsChar(p, '!') ) Type = CBA_BOX_LNOT; else if ( Prs_ManIsChar(p, '~') ) Type = CBA_BOX_INV; else if ( Prs_ManIsChar(p, '@') ) Type = CBA_BOX_SQRT; else if ( Prs_ManIsChar(p, '&') ) Type = CBA_BOX_RAND; else if ( Prs_ManIsChar(p, '|') ) Type = CBA_BOX_ROR; else if ( Prs_ManIsChar(p, '^') ) Type = CBA_BOX_RXOR; else if ( Prs_ManIsChar(p, '-') ) Type = CBA_BOX_MIN; else assert( 0 ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); // skip parentheses if ( Prs_ManIsChar(p, '(') ) { pClose = Prs_ManFindClosingParenthesis( p, '(', ')' ); if ( pClose == NULL ) return Prs_ManErrorSet(p, "Expecting closing parenthesis 2.", 0); *p->pCur = *pClose = ' '; } if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); // read first name Item = Prs_ManReadSignal( p ); if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read name after a unary operator.", 0); Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, Item ); } else { // read first name Item = Prs_ManReadSignal( p ); if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read name after a binary operator.", 0); // check if this is a recent function if ( Abc_Lit2Var2(Item) == p->FuncNameId ) { int Status, nInputs, RangeSize; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Error number 24.", 0); p->pCur++; Status = Prs_ManReadSignalList( p, &p->vTemp, ')', 1 ); nInputs = Vec_IntSize(&p->vTemp)/2; RangeSize = p->FuncRangeId ? Ptr_NtkRangeSize(p->pNtk, p->FuncRangeId) : 1; p->FuncNameId = p->FuncRangeId = 0; if ( Status == 0 ) return 0; if ( nInputs == 1 ) Type = CBA_BOX_DEC; else if ( nInputs == RangeSize + 1 ) Type = CBA_BOX_SEL; else if ( nInputs == (1 << RangeSize) + 1 ) Type = CBA_BOX_NMUX; else return Prs_ManErrorSet(p, "Cannot determine word-level operator.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); // save word-level operator Vec_IntInsert( &p->vTemp, 0, 0 ); Vec_IntInsert( &p->vTemp, 1, OutItem ); Prs_NtkAddBox( p->pNtk, Type, 0, &p->vTemp ); return 1; } Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, Item ); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); assert( !Prs_ManIsChar(p, '[') ); // get the next symbol if ( Prs_ManIsChar(p, ',') || Prs_ManIsChar(p, ';') ) Type = CBA_BOX_BUF; else if ( Prs_ManIsChar(p, '?') ) { p->pCur++; Item = Prs_ManReadSignal( p ); if ( Item == 0 ) return 0; Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, Item ); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); if ( !Prs_ManIsChar(p, ':') ) return Prs_ManErrorSet(p, "MUX lacks the colon symbol (:).", 0); p->pCur++; Item = Prs_ManReadSignal( p ); if ( Item == 0 ) return 0; Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, Item ); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); assert( Vec_IntSize(&p->vTemp) == 8 ); //ABC_SWAP( int, Vec_IntArray(&p->vTemp)[3], Vec_IntArray(&p->vTemp)[5] ); Type = CBA_BOX_MUX; } else { if ( p->pCur[0] == '>' && p->pCur[1] == '>' && p->pCur[2] != '>' ) p->pCur += 2, Type = fRotating ? CBA_BOX_ROTR : CBA_BOX_SHIR; else if ( p->pCur[0] == '>' && p->pCur[1] == '>' && p->pCur[2] == '>' ) p->pCur += 3, Type = CBA_BOX_SHIRA; else if ( p->pCur[0] == '<' && p->pCur[1] == '<' && p->pCur[2] != '<' ) p->pCur += 2, Type = fRotating ? CBA_BOX_ROTL : CBA_BOX_SHIL; else if ( p->pCur[0] == '<' && p->pCur[1] == '<' && p->pCur[2] == '<' ) p->pCur += 3, Type = CBA_BOX_SHILA; else if ( p->pCur[0] == '&' && p->pCur[1] != '&' ) p->pCur += 1, Type = CBA_BOX_AND; else if ( p->pCur[0] == '|' && p->pCur[1] != '|' ) p->pCur += 1, Type = CBA_BOX_OR; else if ( p->pCur[0] == '^' && p->pCur[1] != '^' ) p->pCur += 1, Type = CBA_BOX_XOR; else if ( p->pCur[0] == '&' && p->pCur[1] == '&' ) p->pCur += 2, Type = CBA_BOX_LAND; else if ( p->pCur[0] == '|' && p->pCur[1] == '|' ) p->pCur += 2, Type = CBA_BOX_LOR; else if ( p->pCur[0] == '=' && p->pCur[1] == '=' ) p->pCur += 2, Type = CBA_BOX_EQU; else if ( p->pCur[0] == '!' && p->pCur[1] == '=' ) p->pCur += 2, Type = CBA_BOX_NEQU; else if ( p->pCur[0] == '<' && p->pCur[1] != '=' ) p->pCur += 1, Type = CBA_BOX_LTHAN; else if ( p->pCur[0] == '>' && p->pCur[1] != '=' ) p->pCur += 1, Type = CBA_BOX_MTHAN; else if ( p->pCur[0] == '<' && p->pCur[1] == '=' ) p->pCur += 2, Type = CBA_BOX_LETHAN; else if ( p->pCur[0] == '>' && p->pCur[1] == '=' ) p->pCur += 2, Type = CBA_BOX_METHAN; else if ( p->pCur[0] == '+' ) p->pCur += 1, Type = CBA_BOX_ADD; else if ( p->pCur[0] == '-' ) p->pCur += 1, Type = CBA_BOX_SUB; else if ( p->pCur[0] == '*' && p->pCur[1] != '*' ) p->pCur += 1, Type = CBA_BOX_MUL; else if ( p->pCur[0] == '/' ) p->pCur += 1, Type = CBA_BOX_DIV; else if ( p->pCur[0] == '%' ) p->pCur += 1, Type = CBA_BOX_MOD; else if ( p->pCur[0] == '*' && p->pCur[1] == '*' ) p->pCur += 2, Type = CBA_BOX_POW; else return Prs_ManErrorSet(p, "Unsupported operation.", 0); Item = Prs_ManReadSignal( p ); if ( Item == 0 ) return 0; Vec_IntPush( &p->vTemp, 0 ); Vec_IntPush( &p->vTemp, Item ); // for adder insert carry-in if ( Type == CBA_BOX_ADD ) Vec_IntInsert( &p->vTemp, 2, 0 ); if ( Type == CBA_BOX_ADD ) Vec_IntInsert( &p->vTemp, 3, 0 ); } } if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 24.", 0); // make sure there is nothing left there if ( fRotating ) { Prs_ManUtilSkipUntilWord(p, ";"); p->pCur--; } else if ( !Prs_ManIsChar(p, ',') && !Prs_ManIsChar(p, ';') ) return Prs_ManErrorSet(p, "Trailing symbols on this line.", 0); // save binary operator Prs_NtkAddBox( p->pNtk, Type, 0, &p->vTemp ); return 1; } static inline int Prs_ManReadDeclaration( Prs_Man_t * p, int Type ) { int i, Item = 0, NameId, RangeId = 0, fSigned = 0; Vec_Int_t * vNames[4] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts, &p->pNtk->vWires }; Vec_Int_t * vNamesR[4] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR, &p->pNtk->vWiresR }; assert( Type >= PRS_VER_INPUT && Type <= PRS_VER_WIRE ); // read first word if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 20.", 0); if ( Prs_ManIsChar(p, '[') && !(RangeId = Prs_ManReadRange(p)) ) return Prs_ManErrorSet(p, "Error number 21.", 0); Item = Prs_ManReadName(p); if ( Item == PRS_VER_SIGNED ) { fSigned = 1; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 20.", 0); if ( Prs_ManIsChar(p, '[') && !(RangeId = Prs_ManReadRange(p)) ) return Prs_ManErrorSet(p, "Error number 21.", 0); Item = Prs_ManReadName(p); } if ( Item == PRS_VER_WIRE ) { if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 20.", 0); if ( Prs_ManIsChar(p, '[') && !(RangeId = Prs_ManReadRange(p)) ) return Prs_ManErrorSet(p, "Error number 21.", 0); Item = Prs_ManReadName(p); } // read variable names Vec_IntClear( &p->vTemp3 ); while ( 1 ) { if ( Item == 0 ) return Prs_ManErrorSet(p, "Cannot read name in the list.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 22a", 0); if ( Item == PRS_VER_WIRE ) continue; Vec_IntPush( &p->vTemp3, Item ); if ( Prs_ManIsChar(p, '=') ) { if ( Type == PRS_VER_INPUT ) return Prs_ManErrorSet(p, "Input cannot be defined", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23.", 0); if ( !Prs_ManReadExpression(p, Abc_Var2Lit2(Item, CBA_PRS_NAME)) ) return 0; } if ( Prs_ManIsChar(p, ';') ) break; if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the list.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 22b.", 0); Item = Prs_ManReadName(p); } Vec_IntForEachEntry( &p->vTemp3, NameId, i ) { Vec_IntPush( vNames[Type - PRS_VER_INPUT], NameId ); Vec_IntPush( vNamesR[Type - PRS_VER_INPUT], Abc_Var2Lit(RangeId, fSigned) ); if ( Type < PRS_VER_WIRE ) Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(NameId, Type) ); } return 1; } static inline int Prs_ManReadInstance( Prs_Man_t * p, int Func ) { int InstId, Status; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 25.", 0); if ( Prs_ManIsChar(p, '#') ) { p->pCur++; while ( Prs_ManIsDigit(p) ) p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 25.", 0); } if ( (InstId = Prs_ManReadName(p)) ) if (Prs_ManUtilSkipSpaces(p)) return Prs_ManErrorSet(p, "Error number 26.", 0); if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Expecting \"(\" in module instantiation.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 27.", 0); if ( Prs_ManIsChar(p, '.') ) // box Status = Prs_ManReadSignalList2(p, &p->vTemp); else // node { //char * s = Abc_NamStr(p->pStrs, Func); // translate elementary gate int iFuncNew = Prs_ManIsVerilogPrim(Abc_NamStr(p->pStrs, Func)); if ( iFuncNew == 0 ) return Prs_ManErrorSet(p, "Cannot find elementary gate.", 0); Func = iFuncNew; Status = Prs_ManReadSignalList( p, &p->vTemp, ')', 1 ); } if ( Status == 0 ) return Prs_ManErrorSet(p, "Error number 28.", 0); assert( Prs_ManIsChar(p, ')') ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 29.", 0); if ( !Prs_ManIsChar(p, ';') ) return Prs_ManErrorSet(p, "Expecting semicolon in the instance.", 0); // add box Prs_NtkAddBox( p->pNtk, Func, InstId, &p->vTemp ); return 1; } static inline int Prs_ManReadArguments( Prs_Man_t * p ) { int iRange = 0, iType = -1; Vec_Int_t * vSigs[3] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts }; Vec_Int_t * vSigsR[3] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR }; assert( Prs_ManIsChar(p, '(') ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 30.", 0); if ( Prs_ManIsChar(p, ')') ) return 1; while ( 1 ) { int fEscape = Prs_ManIsChar(p, '\\'); int iName = Prs_ManReadName( p ); int fSigned = 0; if ( iName == 0 ) return Prs_ManErrorSet(p, "Error number 31.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 32.", 0); if ( iName >= PRS_VER_INPUT && iName <= PRS_VER_INOUT && !fEscape ) // declaration { iType = iName; if ( Prs_ManIsChar(p, '[') ) { iRange = Prs_ManReadRange(p); if ( iRange == 0 ) return Prs_ManErrorSet(p, "Error number 33.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 34.", 0); } iName = Prs_ManReadName( p ); if ( iName == 0 ) return Prs_ManErrorSet(p, "Error number 35.", 0); if ( iName == PRS_VER_SIGNED ) { fSigned = 1; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 32.", 0); if ( Prs_ManIsChar(p, '[') ) { iRange = Prs_ManReadRange(p); if ( iRange == 0 ) return Prs_ManErrorSet(p, "Error number 33.", 0); if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 34.", 0); } iName = Prs_ManReadName( p ); if ( iName == 0 ) return Prs_ManErrorSet(p, "Error number 35.", 0); } } if ( iType > 0 ) { Vec_IntPush( vSigs[iType - PRS_VER_INPUT], iName ); Vec_IntPush( vSigsR[iType - PRS_VER_INPUT], Abc_Var2Lit(iRange, fSigned) ); Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(iName, iType) ); } if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 36.", 0); if ( Prs_ManIsChar(p, ')') ) break; if ( !Prs_ManIsChar(p, ',') ) return Prs_ManErrorSet(p, "Expecting comma in the instance.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 36.", 0); } // check final assert( Prs_ManIsChar(p, ')') ); return 1; } // this procedure can return: // 0 = reached end-of-file; 1 = successfully parsed; 2 = recognized as primitive; 3 = failed and skipped; 4 = error (failed and could not skip) static inline int Prs_ManReadModule( Prs_Man_t * p ) { int iToken, Status, fAlways = 0; if ( p->pNtk != NULL ) return Prs_ManErrorSet(p, "Parsing previous module is unfinished.", 4); if ( Prs_ManUtilSkipSpaces(p) ) { Prs_ManErrorClear( p ); return 0; } // read keyword while ( Prs_ManIsChar(p, '`') ) { Prs_ManUtilSkipUntilWord(p, "\n"); if ( Prs_ManUtilSkipSpaces(p) ) { Prs_ManErrorClear( p ); return 0; } } iToken = Prs_ManReadName( p ); if ( iToken != PRS_VER_MODULE ) return Prs_ManErrorSet(p, "Cannot read \"module\" keyword.", 4); if ( Prs_ManUtilSkipSpaces(p) ) return 4; // read module name iToken = Prs_ManReadName( p ); if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read module name.", 4); if ( Prs_ManIsKnownModule(Abc_NamStr(p->pStrs, iToken)) ) { if ( Prs_ManUtilSkipUntilWord( p, "endmodule" ) ) return Prs_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4); //printf( "Warning! Skipped known module \"%s\".\n", Abc_NamStr(p->pStrs, iToken) ); Vec_IntPush( &p->vKnown, iToken ); return 2; } Prs_ManInitializeNtk( p, iToken, 1 ); // skip arguments if ( Prs_ManUtilSkipSpaces(p) ) return 4; if ( !Prs_ManIsChar(p, '(') ) return Prs_ManErrorSet(p, "Cannot find \"(\" in the argument declaration.", 4); if ( !Prs_ManReadArguments(p) ) return 4; assert( *p->pCur == ')' ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return 4; // read declarations and instances while ( Prs_ManIsChar(p, ';') || fAlways ) { if ( !fAlways ) p->pCur++; fAlways = 0; if ( Prs_ManUtilSkipSpaces(p) ) return 4; iToken = Prs_ManReadName( p ); if ( iToken == PRS_VER_ENDMODULE ) { Vec_IntPush( &p->vSucceeded, p->pNtk->iModuleName ); Prs_ManFinalizeNtk( p ); return 1; } if ( iToken >= PRS_VER_INPUT && iToken <= PRS_VER_REG ) // declaration Status = Prs_ManReadDeclaration( p, iToken == PRS_VER_REG ? PRS_VER_WIRE : iToken ); else if ( iToken == PRS_VER_REG || iToken == PRS_VER_DEFPARAM ) // unsupported keywords Status = Prs_ManUtilSkipUntil( p, ';' ); else // read instance { if ( iToken == PRS_VER_ASSIGN ) { // read output name int OutItem = Prs_ManReadSignal( p ); if ( OutItem == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); if ( !Prs_ManIsChar(p, '=') ) return Prs_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23.", 0); // read expression while ( 1 ) { if ( !Prs_ManReadExpression(p, OutItem) ) return 0; if ( Prs_ManIsChar(p, ';') ) break; assert( Prs_ManIsChar(p, ',') ); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23a.", 0); // read output name OutItem = Prs_ManReadSignal( p ); if ( OutItem == 0 ) return Prs_ManErrorSet(p, "Cannot read output in assign-statement.", 0); if ( !Prs_ManIsChar(p, '=') ) return Prs_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0); p->pCur++; if ( Prs_ManUtilSkipSpaces(p) ) return Prs_ManErrorSet(p, "Error number 23.", 0); } } else if ( iToken == PRS_VER_ALWAYS ) Status = Prs_ManReadAlways(p), fAlways = 1; else if ( iToken == PRS_VER_FUNCTION ) Status = Prs_ManReadFunction(p), fAlways = 1; else Status = Prs_ManReadInstance( p, iToken ); if ( Status == 0 ) { return 4; if ( Prs_ManUtilSkipUntilWord( p, "endmodule" ) ) return Prs_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4); //printf( "Warning! Failed to parse \"%s\". Adding module \"%s\" as blackbox.\n", // Abc_NamStr(p->pStrs, iToken), Abc_NamStr(p->pStrs, p->pNtk->iModuleName) ); Vec_IntPush( &p->vFailed, p->pNtk->iModuleName ); // cleanup Vec_IntErase( &p->pNtk->vWires ); Vec_IntErase( &p->pNtk->vWiresR ); Vec_IntErase( &p->pNtk->vSlices ); Vec_IntErase( &p->pNtk->vConcats ); Vec_IntErase( &p->pNtk->vBoxes ); Vec_IntErase( &p->pNtk->vObjs ); p->fUsingTemp2 = 0; // add Prs_ManFinalizeNtk( p ); Prs_ManErrorClear( p ); return 3; } } if ( !Status ) return 4; if ( Prs_ManUtilSkipSpaces(p) ) return 4; } return Prs_ManErrorSet(p, "Cannot find \";\" in the module definition.", 4); } static inline int Prs_ManReadDesign( Prs_Man_t * p ) { while ( 1 ) { int RetValue = Prs_ManReadModule( p ); if ( RetValue == 0 ) // end of file break; if ( RetValue == 1 ) // successfully parsed continue; if ( RetValue == 2 ) // recognized as primitive continue; if ( RetValue == 3 ) // failed and skipped continue; if ( RetValue == 4 ) // error return 0; assert( 0 ); } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Prs_ManPrintModules( Prs_Man_t * p ) { char * pName; int i; printf( "Succeeded parsing %d models:\n", Vec_IntSize(&p->vSucceeded) ); Prs_ManForEachNameVec( &p->vSucceeded, p, pName, i ) printf( " %s", pName ); printf( "\n" ); printf( "Skipped %d known models:\n", Vec_IntSize(&p->vKnown) ); Prs_ManForEachNameVec( &p->vKnown, p, pName, i ) printf( " %s", pName ); printf( "\n" ); printf( "Skipped %d failed models:\n", Vec_IntSize(&p->vFailed) ); Prs_ManForEachNameVec( &p->vFailed, p, pName, i ) printf( " %s", pName ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Prs_ManReadVerilog( char * pFileName ) { Vec_Ptr_t * vPrs = NULL; Prs_Man_t * p = Prs_ManAlloc( pFileName ); if ( p == NULL ) return NULL; Abc_NamStrFindOrAdd( p->pFuns, "1\'b0", NULL ); Abc_NamStrFindOrAdd( p->pFuns, "1\'b1", NULL ); Abc_NamStrFindOrAdd( p->pFuns, "1\'bx", NULL ); Abc_NamStrFindOrAdd( p->pFuns, "1\'bz", NULL ); Prs_NtkAddVerilogDirectives( p ); Prs_ManReadDesign( p ); Prs_ManPrintModules( p ); if ( Prs_ManErrorPrint(p) ) ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks ); Prs_ManFree( p ); return vPrs; } void Prs_ManReadVerilogTest( char * pFileName ) { abctime clk = Abc_Clock(); Vec_Ptr_t * vPrs = Prs_ManReadVerilog( pFileName ); if ( !vPrs ) return; printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) ); printf( "NameIDs = %d. ", Abc_NamObjNumMax(Prs_ManNameMan(vPrs)) ); printf( "Memory = %.2f MB. ", 1.0*Prs_ManMemory(vPrs)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Prs_ManWriteVerilog( Extra_FileNameGenericAppend(pFileName, "_out.v"), vPrs ); // Abc_NamPrint( Prs_ManNameMan(vPrs) ); Prs_ManVecFree( vPrs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Prs_CreateVerilogFindFon( Cba_Ntk_t * p, int NameId ) { int iFon = Cba_NtkGetMap( p, NameId ); if ( iFon ) return iFon; printf( "Network \"%s\": Signal \"%s\" is not driven.\n", Cba_NtkName(p), Cba_NtkStr(p, NameId) ); return 0; } int Prs_CreateSlice( Cba_Ntk_t * p, int iFon, Prs_Ntk_t * pNtk, int Range ) { int iObj, iFonNew, NameId; assert( Cba_FonIsReal(iFon) ); // check existing slice NameId = Cba_NtkNewStrId( p, Cba_ManGetSliceName(p, iFon, Range) ); iFonNew = Cba_NtkGetMap( p, NameId ); if ( iFonNew ) return iFonNew; // create slice iObj = Cba_ObjAlloc( p, CBA_BOX_SLICE, 1, 1 ); Cba_ObjSetName( p, iObj, NameId ); Cba_ObjSetFinFon( p, iObj, 0, iFon ); iFonNew = Cba_ObjFon0(p, iObj); Cba_FonSetRange( p, iFonNew, Range ); Cba_FonSetName( p, iFonNew, NameId ); Cba_NtkSetMap( p, NameId, iFonNew ); return iFonNew; } int Prs_CreateCatIn( Cba_Ntk_t * p, Prs_Ntk_t * pNtk, int Con ) { extern int Prs_CreateSignalIn( Cba_Ntk_t * p, Prs_Ntk_t * pNtk, int Sig ); int i, Sig, iObj, iFon, NameId, nBits = 0; Vec_Int_t * vSigs = Prs_CatSignals(pNtk, Con); // create input concatenation iObj = Cba_ObjAlloc( p, CBA_BOX_CONCAT, Vec_IntSize(vSigs), 1 ); iFon = Cba_ObjFon0(p, iObj); //sprintf( Buffer, "_icc%d_", iObj ); //NameId = Cba_NtkNewStrId( p, Buffer ); NameId = Cba_NtkNewStrId( p, "_icc%d_", iObj ); Cba_FonSetName( p, iFon, NameId ); Cba_NtkSetMap( p, NameId, iFon ); // set inputs Vec_IntForEachEntry( vSigs, Sig, i ) { iFon = Prs_CreateSignalIn( p, pNtk, Sig ); if ( iFon ) Cba_ObjSetFinFon( p, iObj, i, iFon ); if ( iFon ) nBits += Cba_FonRangeSize( p, iFon ); } iFon = Cba_ObjFon0(p, iObj); Cba_FonSetRange( p, iFon, Cba_NtkHashRange(p, nBits-1, 0) ); return Cba_ObjFon0(p, iObj); } int Prs_CreateSignalIn( Cba_Ntk_t * p, Prs_Ntk_t * pNtk, int Sig ) { int iFon, Value = Abc_Lit2Var2( Sig ); Prs_ManType_t Type = (Prs_ManType_t)Abc_Lit2Att2( Sig ); if ( !Sig ) return 0; if ( Type == CBA_PRS_NAME ) return Prs_CreateVerilogFindFon( p, Cba_NtkNewStrId(p, Prs_NtkStr(pNtk, Value)) ); if ( Type == CBA_PRS_CONST ) return Cba_FonFromConst( Value ); if ( Type == CBA_PRS_SLICE ) { iFon = Prs_CreateVerilogFindFon( p, Cba_NtkNewStrId(p, Prs_NtkStr(pNtk, Prs_SliceName(pNtk, Value))) ); if ( !iFon ) return 0; return Prs_CreateSlice( p, iFon, pNtk, Prs_SliceRange(pNtk, Value) ); } assert( Type == CBA_PRS_CONCAT ); return Prs_CreateCatIn( p, pNtk, Value ); } int Prs_CreateRange( Cba_Ntk_t * p, int iFon, int NameId ) { int RangeId = -Cba_NtkGetMap(p, NameId); if ( RangeId < 0 ) // this variable is already created return Cba_FonRangeSize( p, -RangeId ); Cba_NtkUnsetMap( p, NameId ); Cba_NtkSetMap( p, NameId, iFon ); if ( RangeId == 0 ) return 1; assert( RangeId > 0 ); Cba_FonSetRangeSign( p, iFon, RangeId ); return Cba_FonRangeSize( p, iFon ); } void Prs_CreateSignalOut( Cba_Ntk_t * p, int iFon, Prs_Ntk_t * pNtk, int Sig ) { int i, iFonNew, NameOut, RangeOut, NameId, RangeId, RangeSize, nBits = 0; Prs_ManType_t SigType = (Prs_ManType_t)Abc_Lit2Att2( Sig ); int SigValue = Abc_Lit2Var2( Sig ); if ( !Sig ) return; if ( SigType == CBA_PRS_NAME ) { NameId = SigValue; if ( !strncmp(Cba_NtkStr(p, NameId), "Open_", 5) ) return; Cba_FonSetName( p, iFon, NameId ); Prs_CreateRange( p, iFon, NameId ); return; } // create name for this fan NameOut = Cba_NtkNewStrId( p, "_occ%d_", iFon ); Cba_FonSetName( p, iFon, NameOut ); Cba_NtkSetMap( p, NameOut, iFon ); // consider special cases if ( SigType == CBA_PRS_SLICE ) { NameId = Prs_SliceName(pNtk, SigValue); RangeId = Prs_SliceRange(pNtk, SigValue); nBits = Cba_NtkRangeSize(p, RangeId); // save this slice Vec_IntPushThree( &p->vArray0, NameId, RangeId, iFon ); } else if ( SigType == CBA_PRS_CONCAT ) { Vec_Int_t * vSigs = Prs_CatSignals(pNtk, SigValue); Vec_IntReverseOrder( vSigs ); Vec_IntForEachEntry( vSigs, Sig, i ) { SigType = (Prs_ManType_t)Abc_Lit2Att2( Sig ); SigValue = Abc_Lit2Var2( Sig ); if ( SigType == CBA_PRS_NAME ) { int iObjBuf, iFonBuf; // create buffer NameId = SigValue; if ( !strncmp(Cba_NtkStr(p, NameId), "Open_", 5) ) { nBits++; continue; } iObjBuf = Cba_ObjAlloc( p, CBA_BOX_BUF, 1, 1 ); iFonBuf = Cba_ObjFon0(p, iObjBuf); Cba_FonSetName( p, iFonBuf, NameId ); RangeSize = Prs_CreateRange( p, iFonBuf, NameId ); RangeOut = Cba_NtkHashRange(p, nBits+RangeSize-1, nBits); // create slice iFonNew = Prs_CreateSlice( p, iFon, pNtk, RangeOut ); Cba_ObjSetFinFon( p, iObjBuf, 0, iFonNew ); } else if ( SigType == CBA_PRS_SLICE ) { NameId = Prs_SliceName(pNtk, SigValue); RangeId = Prs_SliceRange(pNtk, SigValue); RangeSize = Cba_NtkRangeSize(p, RangeId); RangeOut = Cba_NtkHashRange(p, nBits+RangeSize-1, nBits); // create slice iFonNew = Prs_CreateSlice( p, iFon, pNtk, RangeOut ); // save this slice Vec_IntPushThree( &p->vArray0, NameId, RangeId, iFonNew ); } else assert( 0 ); // increment complete range nBits += RangeSize; } Vec_IntReverseOrder( vSigs ); } else assert( 0 ); // set the range for the output Cba_FonHashRange( p, iFon, nBits-1, 0 ); } void Prs_CreateOutConcat( Cba_Ntk_t * p, int * pSlices, int nSlices ) { Vec_Int_t * vBits = &p->vArray1; int NameId = pSlices[0]; int RangeId = -Cba_NtkGetMap(p, NameId); int LeftId = Cba_NtkRangeLeft( p, RangeId ); int RightId = Cba_NtkRangeRight( p, RangeId ); int BotId = Abc_MinInt( LeftId, RightId ); int TopId = Abc_MaxInt( LeftId, RightId ); int i, k, iObj, iFon, nParts, Prev, nBits; assert( RangeId > 0 ); Vec_IntFill( vBits, Abc_MaxInt(LeftId, RightId) + 1, 0 ); // fill up with slices for ( i = 0; i < nSlices; i++ ) { int Range = pSlices[3*i+1]; int iFon = pSlices[3*i+2]; int Left = Cba_NtkRangeLeft( p, Range ); int Right = Cba_NtkRangeRight( p, Range ); int Bot = Abc_MinInt( Left, Right ); int Top = Abc_MaxInt( Left, Right ); assert( NameId == pSlices[3*i+0] && iFon > 0 ); assert( BotId <= Bot && Top <= TopId ); for ( k = Bot; k <= Top; k++ ) { assert( Vec_IntEntry(vBits, k) == 0 ); Vec_IntWriteEntry( vBits, k, iFon ); } } // check how many parts we have Prev = -1; nParts = 0; Vec_IntForEachEntryStartStop( vBits, iFon, i, BotId, TopId+1 ) { if ( Prev != iFon ) nParts++; Prev = iFon; } // create new concatenation iObj = Cba_ObjAlloc( p, CBA_BOX_CONCAT, nParts, 1 ); iFon = Cba_ObjFon0(p, iObj); Cba_FonSetName( p, iFon, NameId ); Prs_CreateRange( p, iFon, NameId ); // set inputs k = 0; Prev = -1; nBits = 0; Vec_IntForEachEntryStartStop( vBits, iFon, i, BotId, TopId+1 ) { if ( Prev == -1 || Prev == iFon ) nBits++; else { if ( Prev == 0 ) // create constant Prev = Cba_ManNewConstZero( p, nBits ); assert( nBits == Cba_FonRangeSize(p, Prev) ); Cba_ObjSetFinFon( p, iObj, nParts-1-k++, Prev ); nBits = 1; } Prev = iFon; } assert( nBits == Cba_FonRangeSize(p, Prev) ); Cba_ObjSetFinFon( p, iObj, nParts-1-k++, Prev ); assert( k == nParts ); } // looks at multi-bit signal; if one bit is repeated, returns this bit; otherwise, returns -1 int Prs_CreateBitSignal( Prs_Ntk_t * pNtk, int Sig ) { Vec_Int_t * vSigs; int i, SigTemp, SigOne = -1, Value = Abc_Lit2Var2( Sig ); Prs_ManType_t Type = (Prs_ManType_t)Abc_Lit2Att2( Sig ); if ( Type == CBA_PRS_NAME || Type == CBA_PRS_SLICE ) return -1; if ( Type == CBA_PRS_CONST ) { int fOnly0 = 1, fOnly1 = 1; char * pConst = Prs_NtkConst(pNtk, Value); pConst = strchr( pConst, '\'' ) + 1; assert( *pConst == 'b' ); while ( *++pConst ) if ( *pConst == '0' ) fOnly1 = 0; else if ( *pConst == '1' ) fOnly0 = 0; if ( fOnly0 ) return Abc_Var2Lit2( 1, CBA_PRS_CONST ); // const0 if ( fOnly1 ) return Abc_Var2Lit2( 2, CBA_PRS_CONST ); // const1 return -1; } assert( Type == CBA_PRS_CONCAT ); vSigs = Prs_CatSignals( pNtk, Value ); Vec_IntForEachEntry( vSigs, SigTemp, i ) { Value = Abc_Lit2Var2( SigTemp ); Type = (Prs_ManType_t)Abc_Lit2Att2( SigTemp ); if ( Type != CBA_PRS_NAME ) return -1; if ( SigOne == -1 ) SigOne = Value; else if ( SigOne != Value ) return -1; } assert( SigOne >= 0 ); return Abc_Var2Lit2( SigOne, CBA_PRS_NAME ); } int Prs_CreateFlopSetReset( Cba_Ntk_t * p, Prs_Ntk_t * pNtk, Vec_Int_t * vBox, int * pIndexSet, int * pIndexRst, int * pBitSet, int * pBitRst ) { int iSigSet = -1, iSigRst = -1; int IndexSet = -1, IndexRst = -1; int FormId, ActId, k; // mark set and reset Cba_NtkCleanMap2( p ); Cba_NtkSetMap2( p, Cba_NtkStrId(p, "set"), 1 ); Cba_NtkSetMap2( p, Cba_NtkStrId(p, "reset"), 2 ); // check the inputs Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) if ( Cba_NtkGetMap2(p, FormId) == 1 ) // set iSigSet = ActId, IndexSet = k+1; else if ( Cba_NtkGetMap2(p, FormId) == 2 ) // reset iSigRst = ActId, IndexRst = k+1; assert( iSigSet >= 0 && iSigRst >= 0 ); if ( pIndexSet ) *pBitSet = 0; if ( pIndexRst ) *pBitRst = 0; if ( pBitSet ) *pBitSet = 0; if ( pBitRst ) *pBitRst = 0; if ( iSigSet == -1 || iSigRst == -1 ) return 0; iSigSet = Prs_CreateBitSignal(pNtk, iSigSet); iSigRst = Prs_CreateBitSignal(pNtk, iSigRst); if ( iSigSet == -1 || iSigRst == -1 ) return 0; if ( pIndexSet ) *pIndexSet = IndexSet; if ( pIndexRst ) *pIndexRst = IndexRst; if ( pBitSet ) *pBitSet = iSigSet; if ( pBitRst ) *pBitRst = iSigRst; return 1; } char * Prs_CreateDetectRamPort( Prs_Ntk_t * pNtk, Vec_Int_t * vBox, int NameRamId ) { int i, FormId, ActId; Vec_IntForEachEntryDouble( vBox, FormId, ActId, i ) if ( FormId == NameRamId ) return Abc_NamStr(pNtk->pStrs, Abc_Lit2Var2(ActId)); return NULL; } int Prs_CreateGetMemSize( char * pName ) { char * pPtr1 = strchr( pName, '_' ); char * pPtr2 = strchr( pPtr1+1, '_' ); int Num1 = atoi( pPtr1 + 1 ); int Num2 = atoi( pPtr2 + 1 ); assert( Num1 + Abc_Base2Log(Num2) < 32 ); return (1 << Num1) * Num2; } Vec_Ptr_t * Prs_CreateDetectRams( Prs_Ntk_t * pNtk ) { Vec_Ptr_t * vAllRams = NULL, * vRam; Vec_Int_t * vBox, * vBoxCopy; char * pNtkName, * pRamName; int NameRamId = Abc_NamStrFind( pNtk->pStrs, "Ram" ); int i, k, fWrite; Prs_NtkForEachBox( pNtk, vBox, i ) { if ( Prs_BoxIsNode(pNtk, i) ) // node continue; pNtkName = Prs_NtkStr(pNtk, Prs_BoxNtk(pNtk, i)); fWrite = !strncmp(pNtkName, "ClockedWritePort_", strlen("ClockedWritePort_")); if ( fWrite || !strncmp(pNtkName, "ReadPort_", strlen("ReadPort_")) ) { pRamName = Prs_CreateDetectRamPort( pNtk, vBox, NameRamId ); assert( pRamName ); if ( vAllRams == NULL ) vAllRams = Vec_PtrAlloc( 4 ); Vec_PtrForEachEntry( Vec_Ptr_t *, vAllRams, vRam, k ) if ( pRamName == (char *)Vec_PtrEntry(vRam, 0) ) { if ( fWrite ) { vBoxCopy = Vec_IntDup(vBox); Vec_IntPush( vBoxCopy, i ); Vec_PtrPush( vRam, vBoxCopy ); } break; } if ( k < Vec_PtrSize(vAllRams) ) continue; vRam = Vec_PtrAlloc( 4 ); Vec_PtrPush( vRam, pRamName ); Vec_PtrPush( vRam, Abc_Int2Ptr(Prs_CreateGetMemSize(pNtkName)) ); if ( fWrite ) { vBoxCopy = Vec_IntDup(vBox); Vec_IntPush( vBoxCopy, i ); Vec_PtrPush( vRam, vBoxCopy ); } Vec_PtrPush( vAllRams, vRam ); } } return vAllRams; } void Prs_CreateVerilogPio( Cba_Ntk_t * p, Prs_Ntk_t * pNtk ) { int i, NameId, RangeId, iObj, iFon; Cba_NtkCleanObjFuncs( p ); Cba_NtkCleanObjNames( p ); Cba_NtkCleanFonNames( p ); Cba_NtkCleanFonRanges( p ); // create inputs Cba_NtkCleanMap( p ); assert( Vec_IntSize(&pNtk->vInouts) == 0 ); Vec_IntForEachEntryTwo( &pNtk->vInputs, &pNtk->vInputsR, NameId, RangeId, i ) { iObj = Cba_ObjAlloc( p, CBA_OBJ_PI, 0, 1 ); Cba_ObjSetName( p, iObj, NameId ); // direct name iFon = Cba_ObjFon0(p, iObj); Cba_FonSetRangeSign( p, iFon, RangeId ); Cba_FonSetName( p, iFon, NameId ); Cba_NtkSetMap( p, NameId, iObj ); } // create outputs Vec_IntForEachEntryTwo( &pNtk->vOutputs, &pNtk->vOutputsR, NameId, RangeId, i ) { iObj = Cba_ObjAlloc( p, CBA_OBJ_PO, 1, 0 ); Cba_ObjSetName( p, iObj, NameId ); // direct name Cba_NtkSetMap( p, NameId, iObj ); } // create order Vec_IntForEachEntry( &pNtk->vOrder, NameId, i ) { iObj = Prs_CreateVerilogFindFon( p, Abc_Lit2Var2(NameId) ); // labeled name if ( iObj ) Vec_IntPush( &p->vOrder, iObj ); } } int Prs_CreateVerilogNtk( Cba_Ntk_t * p, Prs_Ntk_t * pNtk ) { Vec_Int_t * vBox2Obj = Vec_IntStart( Prs_NtkBoxNum(pNtk) ); Vec_Int_t * vBox; Vec_Ptr_t * vAllRams, * vRam; int i, k, iObj, iTerm, iFon, FormId, ActId, RangeId, NameId, Type; // map inputs Cba_NtkCleanMap( p ); Cba_NtkForEachPi( p, iObj, i ) Cba_NtkSetMap( p, Cba_ObjName(p, iObj), Cba_ObjFon0(p, iObj) ); // map wire names into their rangeID Vec_IntForEachEntryTwo( &pNtk->vWires, &pNtk->vWiresR, NameId, RangeId, i ) Cba_NtkSetMap( p, NameId, -RangeId ); Vec_IntForEachEntryTwo( &pNtk->vOutputs, &pNtk->vOutputsR, NameId, RangeId, i ) Cba_NtkSetMap( p, NameId, -RangeId ); // collect RAMs and create boxes vAllRams = Prs_CreateDetectRams( pNtk ); if ( vAllRams ) Vec_PtrForEachEntry( Vec_Ptr_t *, vAllRams, vRam, i ) { char * pRamName = (char *)Vec_PtrEntry( vRam, 0 ); int MemSize = Abc_Ptr2Int( (char *)Vec_PtrEntry( vRam, 1 ) ); //char Buffer[1000]; sprintf( Buffer, "%s_box", pRamName ); //NameId = Cba_NtkNewStrId( p, Buffer ); NameId = Cba_NtkNewStrId( p, "%s_box", pRamName ); // create RAM object iObj = Cba_ObjAlloc( p, CBA_BOX_RAMBOX, Vec_PtrSize(vRam)-2, 1 ); Cba_ObjSetName( p, iObj, NameId ); iFon = Cba_ObjFon0(p, iObj); NameId = Cba_NtkNewStrId( p, pRamName ); Cba_FonSetName( p, iFon, NameId ); Prs_CreateRange( p, iFon, NameId ); assert( Cba_FonLeft(p, iFon) <= MemSize-1 ); assert( Cba_FonRight(p, iFon) == 0 ); //Cba_VerificSaveLineFile( p, iObj, pNet->Linefile() ); // create write ports feeding into this object Vec_PtrForEachEntryStart( Vec_Int_t *, vRam, vBox, k, 2 ) { int iObjNew = Cba_ObjAlloc( p, CBA_BOX_RAMWC, 4, 1 ); int Line = Vec_IntPop( vBox ); Vec_IntWriteEntry( vBox2Obj, Line, iObjNew ); if ( Prs_BoxName(pNtk, Line) ) Cba_ObjSetName( p, iObjNew, Prs_BoxName(pNtk, Line) ); //Cba_VerificSaveLineFile( p, iObjNew, pInst->Linefile() ); // connect output iFon = Cba_ObjFon0(p, iObjNew); Cba_FonSetRange( p, iFon, Cba_NtkHashRange(p, MemSize-1, 0) ); //sprintf( Buffer, "%s_wp%d", pRamName, k-2 ); //NameId = Cba_NtkNewStrId( p, Buffer ); NameId = Cba_NtkNewStrId( p, "%s_wp%d", pRamName, k-2 ); Cba_FonSetName( p, iFon, NameId ); Cba_NtkSetMap( p, NameId, iFon ); // connet to RAM object Cba_ObjSetFinFon( p, iObj, (k++)-2, iFon ); Vec_IntFree( vBox ); } Vec_PtrFree( vRam ); } Vec_PtrFreeP( &vAllRams ); // create objects Vec_IntClear( &p->vArray0 ); Prs_NtkForEachBox( pNtk, vBox, i ) { if ( Prs_BoxIsNode(pNtk, i) ) // node { Type = Prs_BoxNtk(pNtk, i); iObj = Cba_ObjAlloc( p, (Cba_ObjType_t)Type, Prs_BoxIONum(pNtk, i)-1, Type == CBA_BOX_ADD ? 2 : 1 ); Prs_CreateSignalOut( p, Cba_ObjFon0(p, iObj), pNtk, Vec_IntEntry(vBox, 1) ); // node output } else // box { Cba_Ntk_t * pBox = NULL; int nInputs, nOutputs = 1; char ** pOutNames = NULL, * pNtkName = Prs_NtkStr(pNtk, Prs_BoxNtk(pNtk, i)); Type = Prs_ManFindType( pNtkName, &nInputs, 1, &pOutNames ); if ( Type == CBA_BOX_RAMWC ) continue; if ( Type == CBA_OBJ_BOX ) { pBox = Cba_ManNtkFind( p->pDesign, pNtkName ); if ( pBox == NULL ) { printf( "Fatal error: Cannot find module \"%s\".\n", pNtkName ); continue; } nInputs = Cba_NtkPiNum(pBox); nOutputs = Cba_NtkPoNum(pBox); } else if ( Type == CBA_BOX_ADD || Type == CBA_BOX_DFFCPL ) nOutputs = 2; else if ( Type == CBA_BOX_NMUX ) { if ( !strncmp(pNtkName, "wide_mux_", strlen("wide_mux_")) ) nInputs = 1 + (1 << atoi(pNtkName+strlen("wide_mux_"))); else if ( !strncmp(pNtkName, "Mux_", strlen("Mux_")) ) nInputs = 1 + (1 << atoi(pNtkName+strlen("Mux_"))); else assert( 0 ); } else if ( Type == CBA_BOX_SEL ) { if ( !strncmp(pNtkName, "wide_select_", strlen("wide_select_")) ) nInputs = 1 + atoi(pNtkName+strlen("wide_select_")); else if ( !strncmp(pNtkName, "Select_", strlen("Select_")) ) nInputs = 1 + atoi(pNtkName+strlen("Select_")); else assert( 0 ); } else if ( (Type == CBA_BOX_DFFRS || Type == CBA_BOX_LATCHRS) && !strncmp(pNtkName, "wide_", strlen("wide_")) && !Prs_CreateFlopSetReset(p, pNtk, vBox, NULL, NULL, NULL, NULL) ) nInputs = atoi(pNtkName+strlen(Type == CBA_BOX_DFFRS ? "wide_dffrs_" : "wide_latchrs_")), nOutputs = 1, Type = CBA_BOX_CONCAT; // create object iObj = Cba_ObjAlloc( p, (Cba_ObjType_t)Type, nInputs, nOutputs ); if ( pBox ) Cba_ObjSetFunc( p, iObj, Cba_NtkId(pBox) ); // mark PO objects Cba_NtkCleanMap2( p ); if ( pBox ) Cba_NtkForEachPo( pBox, iTerm, k ) Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 ); else for ( k = 0; k < nOutputs; k++ ) Cba_NtkSetMap2( p, Cba_NtkStrId(p, pOutNames[k]), k+1 ); // map box fons Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) if ( Cba_NtkGetMap2(p, FormId) ) { iFon = Cba_ObjFon(p, iObj, Cba_NtkGetMap2(p, FormId)-1); Prs_CreateSignalOut( p, iFon, pNtk, ActId ); } } Vec_IntWriteEntry( vBox2Obj, i, iObj ); if ( Prs_BoxName(pNtk, i) ) Cba_ObjSetName( p, iObj, Prs_BoxName(pNtk, i) ); //Cba_VerificSaveLineFile( p, iObj, pInst->Linefile() ); } // create concatenations for split signals if ( Vec_IntSize(&p->vArray0) ) { int Prev = -1, Index = 0; Vec_IntSortMulti( &p->vArray0, 3, 0 ); Vec_IntForEachEntryTriple( &p->vArray0, NameId, RangeId, iFon, i ) { if ( Prev != -1 && Prev != NameId ) Prs_CreateOutConcat( p, Vec_IntArray(&p->vArray0) + Index, (i - Index)/3 ), Index = i; Prev = NameId; } Prs_CreateOutConcat( p, Vec_IntArray(&p->vArray0) + Index, (i - Index)/3 ), Index = i; //Cba_VerificSaveLineFile( p, iObj, pInst->Linefile() ); } // connect objects Prs_NtkForEachBox( pNtk, vBox, i ) { iObj = Vec_IntEntry( vBox2Obj, i ); if ( Prs_BoxIsNode(pNtk, i) ) // node { Type = Prs_BoxNtk(pNtk, i); Vec_IntForEachEntryDoubleStart( vBox, FormId, ActId, k, 2 ) { iFon = Prs_CreateSignalIn( p, pNtk, ActId ); if ( iFon ) Cba_ObjSetFinFon( p, iObj, k/2-1, iFon ); } } else // box { int nInputs = -1; char ** pInNames = NULL, * pNtkName = Prs_NtkStr(pNtk, Prs_BoxNtk(pNtk, i)); Type = Prs_ManFindType( pNtkName, &nInputs, 0, &pInNames ); if ( (Type == CBA_BOX_DFFRS || Type == CBA_BOX_LATCHRS) && !strncmp(pNtkName, "wide_", strlen("wide_")) ) { int IndexSet = -1, IndexRst = -1, iBitSet = -1, iBitRst = -1; int Status = Prs_CreateFlopSetReset( p, pNtk, vBox, &IndexSet, &IndexRst, &iBitSet, &iBitRst ); if ( Status ) { Vec_IntWriteEntry( vBox, IndexSet, iBitSet ); Vec_IntWriteEntry( vBox, IndexRst, iBitRst ); // updated box should be fine } else { int w, Width = atoi( pNtkName + strlen(Type == CBA_BOX_DFFRS ? "wide_dffrs_" : "wide_latchrs_") ); assert( Cba_ObjType(p, iObj) == CBA_BOX_CONCAT ); // prepare inputs assert( nInputs >= 0 ); Cba_NtkCleanMap2( p ); for ( k = 0; k < nInputs; k++ ) Cba_NtkSetMap2( p, Cba_NtkStrId(p, pInNames[k]), k+1 ); // create bit-level objects for ( w = 0; w < Width; w++ ) { // create bit-level flop int iObjNew = Cba_ObjAlloc( p, (Cba_ObjType_t)Type, 4, 1 ); if ( Prs_BoxName(pNtk, i) ) { NameId = Cba_NtkNewStrId( p, "%s[%d]", Prs_NtkStr(pNtk, Prs_BoxName(pNtk, i)), w ); Cba_ObjSetName( p, iObjNew, NameId ); } //Cba_VerificSaveLineFile( p, iObjNew, pInst->Linefile() ); // set output fon iFon = Cba_ObjFon0(p, iObjNew); { NameId = Cba_NtkNewStrId( p, "%s[%d]", Cba_FonNameStr(p, Cba_ObjFon0(p, iObj)), w ); Cba_FonSetName( p, iFon, NameId ); } // no need to map this name because it may be produced elsewhere //Cba_NtkSetMap( p, NameId, iFon ); // add the flop Cba_ObjSetFinFon( p, iObj, Width-1-w, iFon ); // create bit-level flops Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) if ( Cba_NtkGetMap2(p, FormId) ) { int Index = Cba_NtkGetMap2(p, FormId)-1; iFon = Prs_CreateSignalIn( p, pNtk, ActId ); assert( iFon ); // create bit-select node for data/set/reset (but not for clock) if ( Index < 3 ) // not clock iFon = Prs_CreateSlice( p, iFon, pNtk, 0 ); Cba_ObjSetFinFon( p, iObjNew, Index, iFon ); } } continue; } } assert( Type == Cba_ObjType(p, iObj) ); //assert( nInputs == -1 || nInputs == Cba_ObjFinNum(p, iObj) ); // mark PI objects Cba_NtkCleanMap2( p ); if ( Type == CBA_OBJ_BOX ) { Cba_Ntk_t * pBox = Cba_ObjNtk(p, iObj); assert( Cba_NtkPiNum(pBox) == Cba_ObjFinNum(p, iObj) ); assert( Cba_NtkPoNum(pBox) == Cba_ObjFonNum(p, iObj) ); Cba_NtkForEachPi( pBox, iTerm, k ) Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 ); } else { assert( nInputs >= 0 ); for ( k = 0; k < nInputs; k++ ) Cba_NtkSetMap2( p, Cba_NtkStrId(p, pInNames[k]), k+1 ); } // connect box fins Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) if ( Cba_NtkGetMap2(p, FormId) ) { int Index = Cba_NtkGetMap2(p, FormId)-1; int nBits = Cba_ObjFinNum(p, iObj); assert( Index < nBits ); iFon = Prs_CreateSignalIn( p, pNtk, ActId ); if ( iFon ) Cba_ObjSetFinFon( p, iObj, Index, iFon ); } // special cases if ( Type == CBA_BOX_NMUX || Type == CBA_BOX_SEL ) { int FonCat = Cba_ObjFinFon( p, iObj, 1 ); int nBits = Cba_FonRangeSize( p, FonCat ); int nParts = Cba_ObjFinNum(p, iObj) - 1; int Slice = nBits / nParts; int nFins = Cba_ObjFinNum(p, iObj); assert( Cba_ObjFinNum(p, iObj) >= 2 ); assert( Slice * nParts == nBits ); assert( nFins == 1 + nParts ); Cba_ObjCleanFinFon( p, iObj, 1 ); // create buffer for the constant if ( FonCat < 0 ) { int iObjNew = Cba_ObjAlloc( p, CBA_BOX_BUF, 1, 1 ); Cba_ObjSetFinFon( p, iObjNew, 0, FonCat ); FonCat = Cba_ObjFon0( p, iObjNew ); NameId = Cba_NtkNewStrId( p, "_buf_const_%d", iObjNew ); Cba_FonSetName( p, FonCat, NameId ); Cba_FonSetRange( p, FonCat, Cba_NtkHashRange(p, nBits-1, 0) ); } for ( k = 0; k < nParts; k++ ) { // iFon = Prs_CreateSlice( p, FonCat, pNtk, Cba_NtkHashRange(p, (nParts-1-k)*Slice+Slice-1, (nParts-1-k)*Slice) ); iFon = Prs_CreateSlice( p, FonCat, pNtk, Cba_NtkHashRange(p, k*Slice+Slice-1, k*Slice) ); Cba_ObjSetFinFon( p, iObj, k+1, iFon ); } } } // if carry-in is not supplied, use constant 0 if ( Type == CBA_BOX_ADD && Cba_ObjFinFon(p, iObj, 0) == 0 ) Cba_ObjSetFinFon( p, iObj, 0, Cba_FonFromConst(1) ); // if set or reset are not supplied, use constant 0 if ( Type == CBA_BOX_DFFRS && Cba_ObjFinFon(p, iObj, 1) == 0 ) Cba_ObjSetFinFon( p, iObj, 1, Cba_FonFromConst(1) ); if ( Type == CBA_BOX_DFFRS && Cba_ObjFinFon(p, iObj, 2) == 0 ) Cba_ObjSetFinFon( p, iObj, 2, Cba_FonFromConst(1) ); } Vec_IntFree( vBox2Obj ); // connect outputs Vec_IntForEachEntryTwo( &pNtk->vOutputs, &pNtk->vOutputsR, NameId, RangeId, i ) { iObj = Cba_NtkPo( p, i ); assert( NameId == Cba_ObjName(p, iObj) ); // direct name iFon = Prs_CreateVerilogFindFon( p, NameId ); if ( !iFon ) continue; Cba_ObjSetFinFon( p, iObj, 0, iFon ); if ( RangeId ) { assert( Cba_NtkRangeLeft(p, Abc_Lit2Var(RangeId)) == Cba_FonLeft(p, iFon) ); assert( Cba_NtkRangeRight(p, Abc_Lit2Var(RangeId)) == Cba_FonRight(p, iFon) ); } } return 0; } Cba_Man_t * Prs_ManBuildCbaVerilog( char * pFileName, Vec_Ptr_t * vDes ) { Prs_Ntk_t * pPrsNtk; int i, fError = 0; Prs_Ntk_t * pPrsRoot = Prs_ManRoot(vDes); // start the manager Abc_Nam_t * pStrs = Abc_NamRef(pPrsRoot->pStrs); Abc_Nam_t * pFuns = Abc_NamRef(pPrsRoot->pFuns); Abc_Nam_t * pMods = Abc_NamStart( 100, 24 ); Cba_Man_t * p = Cba_ManAlloc( pFileName, Vec_PtrSize(vDes), pStrs, pFuns, pMods, Hash_IntManRef(pPrsRoot->vHash) ); // initialize networks Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i ) { Cba_Ntk_t * pNtk = Cba_NtkAlloc( p, Prs_NtkId(pPrsNtk), Prs_NtkPiNum(pPrsNtk), Prs_NtkPoNum(pPrsNtk), Prs_NtkObjNum(pPrsNtk), 100, 100 ); Prs_CreateVerilogPio( pNtk, pPrsNtk ); Cba_NtkAdd( p, pNtk ); } // create networks Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i ) { printf( "Building module \"%s\"...\n", Prs_NtkName(pPrsNtk) ); fError = Prs_CreateVerilogNtk( Cba_ManNtk(p, i+1), pPrsNtk ); if ( fError ) break; } if ( fError ) printf( "Quitting because of errors.\n" ); else Cba_ManPrepareSeq( p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cba_Man_t * Cba_ManReadVerilog( char * pFileName ) { Cba_Man_t * p = NULL; Vec_Ptr_t * vDes = Prs_ManReadVerilog( pFileName ); if ( vDes && Vec_PtrSize(vDes) ) p = Prs_ManBuildCbaVerilog( pFileName, vDes ); if ( vDes ) Prs_ManVecFree( vDes ); return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaWriteBlif.c000066400000000000000000000171351300674244400242030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaWriteBlif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Verilog parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: cbaWriteBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cba.h" #include "cbaPrs.h" #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writing parser state into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Prs_ManWriteBlifArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vFanins ) { int i, NameId; Vec_IntForEachEntry( vFanins, NameId, i ) fprintf( pFile, " %s", Prs_NtkStr(p, NameId) ); fprintf( pFile, "\n" ); } static void Prs_ManWriteBlifLines( FILE * pFile, Prs_Ntk_t * p ) { Vec_Int_t * vBox; int i, k, FormId, ActId; Prs_NtkForEachBox( p, vBox, i ) { int NtkId = Prs_BoxNtk(p, i); assert( Prs_BoxIONum(p, i) > 0 ); assert( Vec_IntSize(vBox) % 2 == 0 ); if ( NtkId == -1 ) // latch { fprintf( pFile, ".latch" ); fprintf( pFile, " %s", Prs_NtkStr(p, Vec_IntEntry(vBox, 1)) ); fprintf( pFile, " %s", Prs_NtkStr(p, Vec_IntEntry(vBox, 3)) ); fprintf( pFile, " %c\n", '0' + Prs_BoxName(p, i) ); } else if ( Prs_BoxIsNode(p, i) ) // node { fprintf( pFile, ".names" ); Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) fprintf( pFile, " %s", Prs_NtkStr(p, ActId) ); fprintf( pFile, "\n%s", Prs_NtkSop(p, NtkId) ); } else // box { fprintf( pFile, ".subckt" ); fprintf( pFile, " %s", Prs_NtkStr(p, NtkId) ); Vec_IntForEachEntryDouble( vBox, FormId, ActId, k ) fprintf( pFile, " %s=%s", Prs_NtkStr(p, FormId), Prs_NtkStr(p, ActId) ); fprintf( pFile, "\n" ); } } } static void Prs_ManWriteBlifNtk( FILE * pFile, Prs_Ntk_t * p ) { // write header fprintf( pFile, ".model %s\n", Prs_NtkStr(p, p->iModuleName) ); if ( Vec_IntSize(&p->vInouts) ) fprintf( pFile, ".inouts" ); if ( Vec_IntSize(&p->vInouts) ) Prs_ManWriteBlifArray( pFile, p, &p->vInouts ); fprintf( pFile, ".inputs" ); Prs_ManWriteBlifArray( pFile, p, &p->vInputs ); fprintf( pFile, ".outputs" ); Prs_ManWriteBlifArray( pFile, p, &p->vOutputs ); // write objects Prs_ManWriteBlifLines( pFile, p ); fprintf( pFile, ".end\n\n" ); } void Prs_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs ) { Prs_Ntk_t * pNtk = Prs_ManRoot(vPrs); FILE * pFile = fopen( pFileName, "wb" ); int i; if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# Design \"%s\" written by ABC on %s\n\n", Prs_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() ); Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i ) Prs_ManWriteBlifNtk( pFile, pNtk ); fclose( pFile ); } /**Function************************************************************* Synopsis [Write elaborated design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cba_ManWriteBlifLines( FILE * pFile, Cba_Ntk_t * p ) { int k, iObj, iFin, iFon; Cba_NtkForEachBox( p, iObj ) { if ( Cba_ObjIsBoxUser(p, iObj) ) { Cba_Ntk_t * pNtk = Cba_ObjNtk( p, iObj ); fprintf( pFile, ".subckt" ); fprintf( pFile, " %s", Cba_NtkName(pNtk) ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) fprintf( pFile, " %s=%s", Cba_ObjNameStr(pNtk, Cba_NtkPi(pNtk, k)), Cba_FonNameStr(p, iFon) ); Cba_ObjForEachFon( p, iObj, iFon, k ) fprintf( pFile, " %s=%s", Cba_ObjNameStr(pNtk, Cba_NtkPo(pNtk, k)), Cba_FonNameStr(p, iFon) ); fprintf( pFile, "\n" ); } else if ( Cba_ObjIsGate(p, iObj) ) { char * pGateName = Abc_NamStr(p->pDesign->pMods, Cba_ObjNtkId( p, iObj )); Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL ); fprintf( pFile, ".gate %s", pGateName ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, k), Cba_FonNameStr(p, iFon) ); Cba_ObjForEachFon( p, iObj, iFon, k ) fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Cba_FonNameStr(p, iFon) ); fprintf( pFile, "\n" ); } else { fprintf( pFile, ".names" ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k ) fprintf( pFile, " %s", Cba_FonNameStr(p, iFon) ); fprintf( pFile, " %s", Cba_FonNameStr(p, Cba_ObjFon0(p, iObj)) ); fprintf( pFile, "\n%s", Cba_NtkSop(p, Cba_ObjFunc(p, iObj)) ); } } } void Cba_ManWriteBlifArray( FILE * pFile, Cba_Ntk_t * p, Vec_Int_t * vObjs ) { int iObj, i; Vec_IntForEachEntry( vObjs, iObj, i ) fprintf( pFile, " %s", Cba_ObjNameStr(p, iObj) ); fprintf( pFile, "\n" ); } void Cba_ManWriteBlifNtk( FILE * pFile, Cba_Ntk_t * p ) { // write header fprintf( pFile, ".model %s\n", Cba_NtkName(p) ); fprintf( pFile, ".inputs" ); Cba_ManWriteBlifArray( pFile, p, &p->vInputs ); fprintf( pFile, ".outputs" ); Cba_ManWriteBlifArray( pFile, p, &p->vOutputs ); // write objects Cba_ManWriteBlifLines( pFile, p ); fprintf( pFile, ".end\n\n" ); } void Cba_ManWriteBlif( char * pFileName, Cba_Man_t * p ) { FILE * pFile; Cba_Ntk_t * pNtk; int i; // check the library if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() ) { printf( "Genlib library used in the mapped design is not longer a current library.\n" ); return; } pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# Design \"%s\" written via CBA package in ABC on %s\n\n", Cba_ManName(p), Extra_TimeStamp() ); // Cba_ManAssignInternWordNames( p ); Cba_ManForEachNtk( p, pNtk, i ) Cba_ManWriteBlifNtk( pFile, pNtk ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/cbaWriteVer.c000066400000000000000000001236521300674244400240650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cbaWriteVer.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [Verilog writer.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 29, 2014.] Revision [$Id: cbaWriteVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cba.h" #include "cbaPrs.h" #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cba_ManCreatePrimMap( char ** pMap ) { memset( pMap, 0, sizeof(char *) * CBA_BOX_LAST ); pMap[ CBA_BOX_SLICE ] = "sli"; pMap[ CBA_BOX_CONCAT ] = "icc"; pMap[ CBA_BOX_BUF ] = ""; pMap[ CBA_BOX_INV ] = "~"; pMap[ CBA_BOX_AND ] = "&"; pMap[ CBA_BOX_NAND ] = "&"; pMap[ CBA_BOX_OR ] = "|"; pMap[ CBA_BOX_NOR ] = "|"; pMap[ CBA_BOX_XOR ] = "^"; pMap[ CBA_BOX_XNOR ] = "^"; pMap[ CBA_BOX_SHARP ] = "&"; pMap[ CBA_BOX_SHARPL ] = "&"; pMap[ CBA_BOX_MUX ] = "?"; pMap[ CBA_BOX_MAJ ] = "maj"; pMap[ CBA_BOX_RAND ] = "&"; pMap[ CBA_BOX_RNAND ] = "~&"; pMap[ CBA_BOX_ROR ] = "|"; pMap[ CBA_BOX_RNOR ] = "~|"; pMap[ CBA_BOX_RXOR ] = "^"; pMap[ CBA_BOX_RXNOR ] = "~^"; pMap[ CBA_BOX_LNOT ] = "!"; pMap[ CBA_BOX_LAND ] = "&&"; pMap[ CBA_BOX_LNAND ] = "logic nand"; pMap[ CBA_BOX_LOR ] = "||"; pMap[ CBA_BOX_LNOR ] = "logic nor"; pMap[ CBA_BOX_LXOR ] = "^^"; pMap[ CBA_BOX_LXNOR ] = "logic xnor"; pMap[ CBA_BOX_NMUX ] = "nmux"; pMap[ CBA_BOX_SEL ] = "sel"; pMap[ CBA_BOX_PSEL ] = "prio-select"; pMap[ CBA_BOX_ENC ] = "enc"; pMap[ CBA_BOX_PENC ] = "prio-enc"; pMap[ CBA_BOX_DEC ] = "dec"; pMap[ CBA_BOX_EDEC ] = "enable-dec"; pMap[ CBA_BOX_ADD ] = "+"; pMap[ CBA_BOX_SUB ] = "-"; pMap[ CBA_BOX_MUL ] = "*"; pMap[ CBA_BOX_DIV ] = "/"; pMap[ CBA_BOX_MOD ] = "%"; pMap[ CBA_BOX_REM ] = "%"; pMap[ CBA_BOX_POW ] = "**"; pMap[ CBA_BOX_MIN ] = "-"; pMap[ CBA_BOX_SQRT ] = "@"; pMap[ CBA_BOX_ABS ] = "abs"; pMap[ CBA_BOX_LTHAN ] = "<"; pMap[ CBA_BOX_LETHAN ] = "<="; pMap[ CBA_BOX_METHAN ] = ">="; pMap[ CBA_BOX_MTHAN ] = ">"; pMap[ CBA_BOX_EQU ] = "=="; pMap[ CBA_BOX_NEQU ] = "!="; pMap[ CBA_BOX_SHIL ] = "<<"; pMap[ CBA_BOX_SHIR ] = ">>"; pMap[ CBA_BOX_SHILA ] = "<<<"; pMap[ CBA_BOX_SHIRA ] = ">>>"; pMap[ CBA_BOX_ROTL ] = "rotL"; pMap[ CBA_BOX_ROTR ] = "rotR"; pMap[ CBA_BOX_TRI ] = "tri"; pMap[ CBA_BOX_RAM ] = "ram"; pMap[ CBA_BOX_RAMR ] = "ramR"; pMap[ CBA_BOX_RAMW ] = "ramW"; pMap[ CBA_BOX_RAMWC ] = "ramWC"; pMap[ CBA_BOX_RAMBOX ] = "ramBox"; pMap[ CBA_BOX_LATCH ] = "lat"; pMap[ CBA_BOX_LATCHRS] = "latrs"; pMap[ CBA_BOX_DFF ] = "dff"; pMap[ CBA_BOX_DFFRS ] = "dffrs"; } /**Function************************************************************* Synopsis [Writing parser state into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Prs_NameIsLegalInVerilog( char * pName, int NameId ) { // 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 ( NameId < 13 ) // see PRS_VER_UNKNOWN in cbaReadVer.c return 0; 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 * Prs_ObjGetName( Prs_Ntk_t * p, int NameId ) { char * pName = Prs_NtkStr(p, NameId); if ( pName == NULL ) return pName; if ( Prs_NameIsLegalInVerilog(pName, NameId) ) return pName; return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "\\%s ", pName ); } static inline char * Prs_ManWriteRange( Prs_Ntk_t * p, int RangeId, int fSlice ) { int Left = RangeId ? Hash_IntObjData0( p->vHash, RangeId ) : 0; int Right = RangeId ? Hash_IntObjData1( p->vHash, RangeId ) : 0; if ( Left == Right && fSlice ) return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "[%d]", Right ); else return Vec_StrPrintF( Abc_NamBuffer(p->pStrs), "[%d:%d]", Left, Right ); } static void Prs_ManWriteVerilogConcat( FILE * pFile, Prs_Ntk_t * p, int Con ) { extern void Prs_ManWriteVerilogArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs, int fOdd ); Vec_Int_t * vSigs = Prs_CatSignals(p, Con); fprintf( pFile, "{" ); Prs_ManWriteVerilogArray( pFile, p, vSigs, 0 ); fprintf( pFile, "}" ); } static void Prs_ManWriteVerilogSignal( FILE * pFile, Prs_Ntk_t * p, int Sig ) { int Value = Abc_Lit2Var2( Sig ); Prs_ManType_t Type = (Prs_ManType_t)Abc_Lit2Att2( Sig ); if ( Type == CBA_PRS_NAME ) fprintf( pFile, "%s", Prs_ObjGetName(p, Value) ); else if ( Type == CBA_PRS_CONST ) fprintf( pFile, "%s", Prs_NtkConst(p, Value) ); else if ( Type == CBA_PRS_SLICE ) fprintf( pFile, "%s%s", Prs_ObjGetName(p, Prs_SliceName(p, Value)), Prs_ManWriteRange(p, Prs_SliceRange(p, Value), 1) ); else if ( Type == CBA_PRS_CONCAT ) Prs_ManWriteVerilogConcat( pFile, p, Value ); else assert( 0 ); } void Prs_ManWriteVerilogArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs, int fOdd ) { int i, Sig, fFirst = 1; assert( Vec_IntSize(vSigs) > 0 ); Vec_IntForEachEntry( vSigs, Sig, i ) { if ( fOdd && !(i & 1) ) continue; fprintf( pFile, "%s", fFirst ? "" : ", " ); Prs_ManWriteVerilogSignal( pFile, p, Sig ); fFirst = 0; } } static void Prs_ManWriteVerilogArray2( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs ) { int i, FormId, ActSig; assert( Vec_IntSize(vSigs) % 2 == 0 ); Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i ) { fprintf( pFile, "." ); fprintf( pFile, "%s", Prs_ObjGetName(p, FormId) ); fprintf( pFile, "(" ); Prs_ManWriteVerilogSignal( pFile, p, ActSig ); fprintf( pFile, ")%s", (i == Vec_IntSize(vSigs) - 2) ? "" : ", " ); } } static void Prs_ManWriteVerilogMux( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vSigs ) { int i, FormId, ActSig; char * pStrs[4] = { " = ", " ? ", " : ", ";\n" }; assert( Vec_IntSize(vSigs) == 8 ); fprintf( pFile, " assign " ); Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vSigs, 1) ); fprintf( pFile, "%s", pStrs[0] ); Vec_IntForEachEntryDoubleStart( vSigs, FormId, ActSig, i, 2 ) { Prs_ManWriteVerilogSignal( pFile, p, ActSig ); fprintf( pFile, "%s", pStrs[i/2] ); } } static void Prs_ManWriteVerilogBoxes( FILE * pFile, Prs_Ntk_t * p, char ** pTypeNames ) { Vec_Int_t * vBox; int i, k; Prs_NtkForEachBox( p, vBox, i ) { Cba_ObjType_t NtkId = (Cba_ObjType_t)Prs_BoxNtk(p, i); //char * pNtkName = Prs_ObjGetName(p, Prs_BoxName(p, i)); if ( NtkId == CBA_BOX_MUX && Prs_BoxIsNode(p, i) ) Prs_ManWriteVerilogMux( pFile, p, vBox ); else if ( Prs_BoxIsNode(p, i) ) // node { fprintf( pFile, " assign " ); Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 1) ); fprintf( pFile, " = " ); if ( Cba_TypeIsUnary(NtkId) ) { fprintf( pFile, "%s", pTypeNames[NtkId] ); Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) ); } else if ( NtkId == CBA_BOX_NMUX ) { Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) ); fprintf( pFile, " ? " ); for ( k = 5; k < Vec_IntSize(vBox); k += 2 ) { if ( k > 5 ) fprintf( pFile, " : " ); Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, k) ); } } else if ( NtkId == CBA_BOX_ADD ) { if ( Vec_IntEntry(vBox, 3) ) { Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) ); fprintf( pFile, " %s ", pTypeNames[NtkId] ); } Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 5) ); fprintf( pFile, " %s ", pTypeNames[NtkId] ); Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 7) ); } else { Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 3) ); fprintf( pFile, " %s ", pTypeNames[NtkId] ); Prs_ManWriteVerilogSignal( pFile, p, Vec_IntEntry(vBox, 5) ); } fprintf( pFile, ";\n" ); } else // box { fprintf( pFile, " %s %s ( ", Prs_ObjGetName(p, NtkId), Prs_BoxName(p, i) ? Prs_ObjGetName(p, Prs_BoxName(p, i)) : "" ); Prs_ManWriteVerilogArray2( pFile, p, vBox ); fprintf( pFile, " );\n" ); } } } static void Prs_ManWriteVerilogIos( FILE * pFile, Prs_Ntk_t * p, int SigType ) { int NameId, RangeId, i; char * pSigNames[4] = { "inout", "input", "output", "wire" }; Vec_Int_t * vSigs[4] = { &p->vInouts, &p->vInputs, &p->vOutputs, &p->vWires }; Vec_Int_t * vSigsR[4] = { &p->vInoutsR, &p->vInputsR, &p->vOutputsR, &p->vWiresR }; if ( SigType == 3 ) fprintf( pFile, "\n" ); Vec_IntForEachEntryTwo( vSigs[SigType], vSigsR[SigType], NameId, RangeId, i ) { fprintf( pFile, " %s %s%s", pSigNames[SigType], Abc_LitIsCompl(RangeId) ? "signed " : "", RangeId ? Prs_ManWriteRange(p, Abc_Lit2Var(RangeId), 0) : "" ); fprintf( pFile, "%s;\n", Prs_ObjGetName(p, NameId) ); } } static void Prs_ManWriteVerilogIoOrder( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vOrder ) { int i, NameId; Vec_IntForEachEntry( vOrder, NameId, i ) fprintf( pFile, "%s%s", Prs_ObjGetName(p, Abc_Lit2Var2(NameId)), i == Vec_IntSize(vOrder) - 1 ? "" : ", " ); } static void Prs_ManWriteVerilogNtk( FILE * pFile, Prs_Ntk_t * p, char ** pTypeNames ) { int s; // write header fprintf( pFile, "module %s (\n ", Prs_ObjGetName(p, p->iModuleName) ); Prs_ManWriteVerilogIoOrder( pFile, p, &p->vOrder ); fprintf( pFile, "\n );\n" ); // write declarations for ( s = 0; s < 4; s++ ) Prs_ManWriteVerilogIos( pFile, p, s ); fprintf( pFile, "\n" ); // write objects Prs_ManWriteVerilogBoxes( pFile, p, pTypeNames ); fprintf( pFile, "endmodule\n\n" ); } void Prs_ManWriteVerilog( char * pFileName, Vec_Ptr_t * vPrs ) { char * pTypeNames[CBA_BOX_LAST]; Prs_Ntk_t * pNtk = Prs_ManRoot(vPrs); int i; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } Cba_ManCreatePrimMap( pTypeNames ); fprintf( pFile, "// Design \"%s\" written by ABC on %s\n\n", Prs_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() ); Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i ) Prs_ManWriteVerilogNtk( pFile, pNtk, pTypeNames ); fclose( pFile ); } static inline int Cba_NameIsLegalInVerilog( char * pName, int NameId ) { // 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 ( NameId < 13 ) // see PRS_VER_UNKNOWN in cbaReadVer.c return 0; 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 * Cba_ObjGetName( Cba_Ntk_t * p, int i ) { char * pName = Cba_ObjNameStr(p, i); if ( pName == NULL ) return pName; if ( Cba_NameIsLegalInVerilog(pName, Cba_ObjName(p, i)) ) return pName; return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s ", pName ); } char * Cba_FonGetName( Cba_Ntk_t * p, int i ) { char * pName = Cba_FonNameStr(p, i); if ( pName == NULL ) return pName; if ( Cba_ObjType(p, Cba_FonObj(p, i)) == CBA_BOX_SLICE ) return pName; if ( Cba_NameIsLegalInVerilog(pName, Cba_FonName(p, i)) ) return pName; return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s ", pName ); } char * Cba_ManGetSliceName( Cba_Ntk_t * p, int iFon, int RangeId ) { int Left = Cba_NtkRangeLeft(p, RangeId); int Right = Cba_NtkRangeRight(p, RangeId); char * pName = Cba_FonNameStr(p, iFon); if ( Cba_NameIsLegalInVerilog(pName, Cba_FonName(p, iFon)) ) if ( Left == Right ) return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "%s[%d]", pName, Right ); else return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "%s[%d:%d]", pName, Left, Right ); else if ( Left == Right ) return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s [%d]", pName, Right ); else return Vec_StrPrintF( Abc_NamBuffer(Cba_NtkNam(p)), "\\%s [%d:%d]", pName, Left, Right ); } void Cba_ManWriteFonRange( Cba_Ntk_t * p, int iFon ) { Vec_Str_t * vStr = &p->pDesign->vOut; if ( !iFon || Cba_FonIsConst(iFon) || (Cba_FonRangeSize(p, iFon) == 1 && Cba_FonRight(p, iFon) == 0) ) return; if ( Cba_FonSigned(p, iFon) ) Vec_StrPrintF( vStr, "signed " ); Vec_StrPrintF( vStr, "[%d:%d] ", Cba_FonLeft(p, iFon), Cba_FonRight(p, iFon) ); } void Cba_ManWriteFonName( Cba_Ntk_t * p, int iFon, int fInlineConcat, int fInput ) { extern void Cba_ManWriteConcat( Cba_Ntk_t * p, int iObj ); Vec_Str_t * vStr = &p->pDesign->vOut; if ( !iFon || (!Cba_FonIsConst(iFon) && !Cba_FonName(p, iFon)) ) Vec_StrPrintF( vStr, "Open_%d", Cba_NtkMan(p)->nOpens++ ); // Vec_StrPrintF( vStr, "1\'b0" ); else if ( fInlineConcat && !Cba_FonIsConst(iFon) && Cba_ObjIsConcat(p, Cba_FonObj(p, iFon)) ) Cba_ManWriteConcat( p, Cba_FonObj(p, iFon) ); else { int Range = fInput ? Cba_FonRangeSize( p, iFon ) : 0; if ( fInput && Range > 1 ) Vec_StrPush( vStr, '{' ); Vec_StrPrintStr( vStr, Cba_FonIsConst(iFon) ? Cba_NtkConst(p, Cba_FonConst(iFon)) : Cba_FonGetName(p, iFon) ); if ( fInput && Range > 1 ) Vec_StrPush( vStr, '}' ); } } void Cba_ManWriteConcat( Cba_Ntk_t * p, int iObj ) { int i, iFin, iFon; Vec_Str_t * vStr = &p->pDesign->vOut; assert( Cba_ObjIsConcat(p, iObj) ); Vec_StrPush( vStr, '{' ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i ) { Vec_StrPrintStr( vStr, i ? ", " : "" ); Cba_ManWriteFonName( p, iFon, 1, 0 ); } Vec_StrPush( vStr, '}' ); } int Cba_ManWriteLineFile( Cba_Ntk_t * p, int iObj, int FileAttr, int LineAttr ) { Vec_Str_t * vStr = &p->pDesign->vOut; int FileId = 0, LineId = 0; if ( FileAttr && (FileId = Cba_ObjAttrValue(p, iObj, FileAttr)) ) { LineId = Cba_ObjAttrValue(p, iObj, LineAttr); Vec_StrPrintF( vStr, " // %s(%d)", Cba_NtkStr(p, FileId), LineId ); return 1; } return 0; } void Cba_ManWriteVerilogNtk( Cba_Ntk_t * p, int fInlineConcat ) { Vec_Str_t * vStr = &p->pDesign->vOut; int i, k, iObj, iFin, iFon, StartPos, Status; int FileAttr = Cba_NtkStrId( p, "file" ); int LineAttr = Cba_NtkStrId( p, "line" ); int fUseNewLine = (int)(Cba_NtkPioNum(p) > 5); // mark PO fons Vec_Bit_t * vPoFons = Vec_BitStart( Cba_NtkFonNum(p)+1 ); Cba_NtkForEachPoDriverFon( p, iObj, iFon, i ) if ( Cba_FonIsReal(iFon) && Cba_FonName(p, iFon) == Cba_ObjName(p, iObj) ) Vec_BitWriteEntry( vPoFons, iFon, 1 ); // write header Vec_StrPrintStr( vStr, "module " ); Vec_StrPrintStr( vStr, Cba_NtkName(p) ); Vec_StrPrintStr( vStr, fUseNewLine ? " (\n " : " ( " ); StartPos = Vec_StrSize(vStr); Cba_NtkForEachPioOrder( p, iObj, i ) { Vec_StrPrintStr( vStr, i ? ", " : "" ); if ( Vec_StrSize(vStr) > StartPos + 70 ) { StartPos = Vec_StrSize(vStr); Vec_StrPrintStr( vStr, "\n " ); } Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) ); } Vec_StrPrintStr( vStr, fUseNewLine ? "\n );" : " );" ); Cba_ManWriteLineFile( p, 0, FileAttr, LineAttr ); Vec_StrPrintStr( vStr, fUseNewLine ? "\n" : "\n\n" ); // write inputs/outputs Cba_NtkForEachPioOrder( p, iObj, i ) { int Offset = Vec_StrSize(vStr); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Cba_ObjIsPi(p, iObj) ? "input " : "output " ); Cba_ManWriteFonRange( p, Cba_ObjIsPi(p, iObj) ? Cba_ObjFon0(p, iObj) : Cba_ObjFinFon(p, iObj, 0) ); Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) ); Vec_StrPrintF( vStr, ";%*s", Offset + 40 - Vec_StrSize(vStr), "" ); Cba_ManWriteLineFile( p, iObj, FileAttr, LineAttr ); Vec_StrPush( vStr, '\n' ); } Vec_StrPrintStr( vStr, "\n" ); // write objects Cba_NtkForEachBox( p, iObj ) { // char * pNameNtk = Cba_NtkName(p); // char * pNameInst = Cba_ObjGetName(p, iObj); int Type = Cba_ObjType(p, iObj); if ( Cba_ObjIsSlice(p, iObj) ) continue; if ( fInlineConcat && Cba_ObjIsConcat(p, iObj) ) continue; if ( Cba_ObjIsBoxUser(p, iObj) ) { Cba_Ntk_t * pNtk = Cba_ObjNtk(p, iObj); // write output wire declarations Cba_ObjForEachFon( p, iObj, iFon, i ) { if ( Vec_BitEntry(vPoFons, iFon) ) continue; Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFon ); Cba_ManWriteFonName( p, iFon, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); } // write box Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Cba_NtkName(pNtk) ); Vec_StrPush( vStr, ' ' ); if ( Cba_ObjName(p, iObj) ) Vec_StrPrintF( vStr, "%s ", Cba_ObjGetName(p, iObj) ); // write input binding Vec_StrPrintStr( vStr, "( " ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i ) { Vec_StrPrintF( vStr, "%s.%s(", i ? ", " : "", Cba_ObjGetName(pNtk, Cba_NtkPi(pNtk, i)) ); Cba_ManWriteFonName( p, iFon, fInlineConcat, 1 ); Vec_StrPush( vStr, ')' ); } // write output binding Cba_ObjForEachFon( p, iObj, iFon, i ) { Vec_StrPrintF( vStr, "%s.%s(", Cba_ObjFinNum(p, iObj) ? ", " : "", Cba_ObjGetName(pNtk, Cba_NtkPo(pNtk, i)) ); Cba_ManWriteFonName( p, iFon, 0, 1 ); Vec_StrPush( vStr, ')' ); } Vec_StrPrintStr( vStr, ");" ); } else if ( Type == CBA_BOX_RAMWC || Type == CBA_BOX_RAMBOX || Type == CBA_BOX_RAMR ) { int Num = (Type == CBA_BOX_RAMWC) ? 0 : (Type == CBA_BOX_RAMR ? 1 : 2); // write / read / box char * pBoxName[3] = { "RAM_WRITE", "RAM_READ", "RAM_BOX" }; char * pOutputs[3] = { "ram", "rdata", "out" }; char * pInputs[3][4] = { {"clk", "wen", "waddr", "wdata"}, {"ren", "raddr", "ram"}, {"in0", "in1", "in2", "in3"} }; // write declaration for the output int iFonOut = Cba_ObjFon0(p, iObj); if ( Vec_BitEntry(vPoFons, iFonOut) ) Vec_StrPrintStr( vStr, " assign " ); else { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFonOut ); } Cba_ManWriteFonName( p, iFonOut, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); // write box Vec_StrPrintF( vStr, " %s( ", pBoxName[Num] ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i ) { Vec_StrPrintF( vStr, "%s.%s(", i ? ", " : "", pInputs[Num][i] ); Cba_ManWriteFonName( p, iFon, fInlineConcat, 1 ); Vec_StrPush( vStr, ')' ); } Vec_StrPrintF( vStr, "%s.%s(", Cba_ObjFinNum(p, iObj) ? ", " : "", pOutputs[Num] ); Cba_ManWriteFonName( p, iFonOut, 0, 1 ); Vec_StrPrintStr( vStr, ") );" ); } else if ( Type == CBA_BOX_NMUX || Type == CBA_BOX_SEL ) { int fUseSel = Type == CBA_BOX_SEL; int nBits = fUseSel ? Cba_ObjFinNum(p, iObj) - 1 : Abc_Base2Log(Cba_ObjFinNum(p, iObj) - 1); int iFonIn = Cba_ObjFinFon(p, iObj, 0); int iFonOut = Cba_ObjFon0(p, iObj); // function [15:0] res; Vec_StrPrintStr( vStr, " function " ); Cba_ManWriteFonRange( p, iFonOut ); Vec_StrPrintStr( vStr, "_func_" ); Cba_ManWriteFonName( p, iFonOut, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); // input [1:0] s; Vec_StrPrintStr( vStr, " input " ); Cba_ManWriteFonRange( p, iFonIn ); Vec_StrPrintStr( vStr, "s;\n" ); // input [15:0] d0, d1, d2, d3; Vec_StrPrintStr( vStr, " input " ); Cba_ManWriteFonRange( p, iFonOut ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i ) { if ( i == 0 ) continue; Vec_StrPrintF( vStr, "%sd%d", i > 1 ? ", " : "", i-1 ); } Vec_StrPrintStr( vStr, ";\n" ); // casez (s) Vec_StrPrintStr( vStr, " casez(s)" ); if ( fUseSel ) Vec_StrPrintStr( vStr, " // synopsys full_case parallel_case" ); Vec_StrPrintStr( vStr, "\n" ); // 2'b00: res = b[15:0]; Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i ) { if ( i == 0 ) continue; Vec_StrPrintF( vStr, " %d\'b", nBits ); if ( fUseSel ) { Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + nBits, '?' ); Vec_StrWriteEntry( vStr, Vec_StrSize(vStr) - i, '1' ); } else { for ( k = nBits-1; k >= 0; k-- ) Vec_StrPrintNum( vStr, ((i-1) >> k) & 1 ); } Vec_StrPrintStr( vStr, ": _func_" ); Cba_ManWriteFonName( p, iFonOut, 0, 0 ); Vec_StrPrintF( vStr, " = d%d;\n", i-1 ); } Vec_StrPrintStr( vStr, " endcase\n" ); Vec_StrPrintStr( vStr, " endfunction\n" ); // assign z = res(a, b, s); if ( Vec_BitEntry(vPoFons, iFonOut) ) Vec_StrPrintStr( vStr, " assign " ); else { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFonOut ); } Cba_ManWriteFonName( p, iFonOut, fInlineConcat, 0 ); Vec_StrPrintStr( vStr, " = _func_" ); Cba_ManWriteFonName( p, iFonOut, 0, 0 ); Vec_StrPrintStr( vStr, " ( " ); Cba_ObjForEachFinFon( p, iObj, iFin, iFon, i ) { Vec_StrPrintStr( vStr, i ? ", " : "" ); Cba_ManWriteFonName( p, iFon, fInlineConcat, 0 ); } Vec_StrPrintStr( vStr, " );" ); } else if ( Type == CBA_BOX_DEC ) { int iFonIn = Cba_ObjFinFon(p, iObj, 0); int iFonOut = Cba_ObjFon0(p, iObj); int nBitsIn = Cba_FonRangeSize(p, iFonIn); int nBitsOut = Cba_FonRangeSize(p, iFonOut); assert( (1 << nBitsIn) == nBitsOut ); // function [15:0] res; Vec_StrPrintStr( vStr, " function " ); Cba_ManWriteFonRange( p, iFonOut ); Vec_StrPrintStr( vStr, "_func_" ); Cba_ManWriteFonName( p, iFonOut, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); // input [1:0] i; Vec_StrPrintStr( vStr, " input " ); Cba_ManWriteFonRange( p, iFonIn ); Vec_StrPrintStr( vStr, "i;\n" ); // casez (i) Vec_StrPrintStr( vStr, " casez(i)\n" ); // 2'b00: res = 4'b0001; for ( i = 0; i < (1 << nBitsIn); i++ ) { Vec_StrPrintF( vStr, " %d\'b", nBitsIn ); for ( k = nBitsIn-1; k >= 0; k-- ) Vec_StrPrintNum( vStr, (i >> k) & 1 ); Vec_StrPrintStr( vStr, ": _func_" ); Cba_ManWriteFonName( p, iFonOut, 0, 0 ); Vec_StrPrintF( vStr, " = %d\'b%0*d;\n", nBitsOut, nBitsOut, 0 ); Vec_StrWriteEntry( vStr, Vec_StrSize(vStr) - i - 3, '1' ); } Vec_StrPrintStr( vStr, " endcase\n" ); Vec_StrPrintStr( vStr, " endfunction\n" ); // assign z = res(i, o); if ( Vec_BitEntry(vPoFons, iFonOut) ) Vec_StrPrintStr( vStr, " assign " ); else { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFonOut ); } Cba_ManWriteFonName( p, iFonOut, fInlineConcat, 0 ); Vec_StrPrintStr( vStr, " = _func_" ); Cba_ManWriteFonName( p, iFonOut, 0, 0 ); Vec_StrPrintStr( vStr, " ( " ); Cba_ManWriteFonName( p, iFonIn, fInlineConcat, 0 ); Vec_StrPrintStr( vStr, " );" ); } else if ( Type == CBA_BOX_DFFRS || Type == CBA_BOX_LATCHRS ) { int fUseFlop = Type == CBA_BOX_DFFRS; int iFonQ = Cba_ObjFon0(p, iObj); int iFonD = Cba_ObjFinFon(p, iObj, 0); int iFonSet = Cba_ObjFinFon(p, iObj, 1); int iFonRst = Cba_ObjFinFon(p, iObj, 2); int iFonC = Cba_ObjFinFon(p, iObj, 3); int Range = Cba_FonRangeSize( p, iFonQ ); assert( Cba_FonRangeSize(p, iFonSet) == 1 && Cba_FonRangeSize(p, iFonRst) == 1 ); // reg [3:0] Q; Vec_StrPrintStr( vStr, " reg " ); Cba_ManWriteFonRange( p, iFonQ ); Cba_ManWriteFonName( p, iFonQ, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); // always @(posedge C or posedge PRE) Vec_StrPrintStr( vStr, " always @(" ); if ( fUseFlop ) Vec_StrPrintStr( vStr, "posedge " ); Cba_ManWriteFonName( p, iFonC, 0, 0 ); if ( !fUseFlop ) { Vec_StrPrintStr( vStr, " or " ); Cba_ManWriteFonName( p, iFonD, 0, 0 ); } if ( iFonSet > 0 ) { Vec_StrPrintStr( vStr, " or " ); if ( fUseFlop ) Vec_StrPrintStr( vStr, "posedge " ); Cba_ManWriteFonName( p, iFonSet, 0, 0 ); } if ( iFonRst > 0 ) { Vec_StrPrintStr( vStr, " or " ); if ( fUseFlop ) Vec_StrPrintStr( vStr, "posedge " ); Cba_ManWriteFonName( p, iFonRst, 0, 0 ); } Vec_StrPrintStr( vStr, ")\n" ); // if (Set) Q <= 4'b1111; if ( iFonSet > 0 ) { Vec_StrPrintStr( vStr, " if (" ); Cba_ManWriteFonName( p, iFonSet, 0, 0 ); Vec_StrPrintStr( vStr, ") " ); Cba_ManWriteFonName( p, iFonQ, 0, 0 ); Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " ); // value 1 Vec_StrPrintNum( vStr, Range ); Vec_StrPrintStr( vStr, "\'b" ); Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + Range, '1' ); Vec_StrPrintStr( vStr, ";\n" ); // Vec_StrPrintF( vStr, "\'b1" ); } if ( iFonRst > 0 ) { Vec_StrPrintStr( vStr, iFonSet > 0 ? " else if (" : " if (" ); Cba_ManWriteFonName( p, iFonRst, 0, 0 ); Vec_StrPrintStr( vStr, ") " ); Cba_ManWriteFonName( p, iFonQ, 0, 0 ); Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " ); // value 0 Vec_StrPrintNum( vStr, Range ); Vec_StrPrintStr( vStr, "\'b" ); Vec_StrFillExtra( vStr, Vec_StrSize(vStr) + Range, '0' ); Vec_StrPrintStr( vStr, ";\n" ); // Vec_StrPrintF( vStr, "\'b0" ); } Vec_StrPrintStr( vStr, (iFonSet > 0 || iFonRst > 0) ? " else " : " " ); if ( !fUseFlop ) { Vec_StrPrintStr( vStr, " if (" ); Cba_ManWriteFonName( p, iFonC, 0, 0 ); Vec_StrPrintStr( vStr, ") " ); } Cba_ManWriteFonName( p, iFonQ, 0, 0 ); Vec_StrPrintStr( vStr, fUseFlop ? " <= " : " = " ); Cba_ManWriteFonName( p, iFonD, fInlineConcat, 0 ); Vec_StrPrintStr( vStr, ";" ); } else if ( Type == CBA_BOX_DFFCPL ) { // CPL_FF#32 inst_reg( .d(s1), .arstval(s2), .arst(s3), .clk(s4), .q(s5), .qbar(s6) ); int iFon0 = Cba_ObjFon0(p, iObj); int iFon1 = Cba_ObjFon(p, iObj, 1); int Range = Cba_FonRangeSize( p, iFon0 ); if ( !Vec_BitEntry(vPoFons, iFon0) ) { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFon0 ); Cba_ManWriteFonName( p, iFon0, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); } if ( !Vec_BitEntry(vPoFons, iFon1) && Cba_FonName(p, iFon1) ) { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFon1 ); Cba_ManWriteFonName( p, iFon1, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); } Vec_StrPrintStr( vStr, " CPL_FF" ); if ( Range > 1 ) Vec_StrPrintF( vStr, "#%d", Range ); Vec_StrPrintStr( vStr, " " ); if ( Cba_ObjName(p, iObj) ) Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) ); Vec_StrPrintStr( vStr, " ( .d(" ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, "), .arstval(" ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, "), .arst(" ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, "), .clk(" ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 3), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, "), .q(" ); Cba_ManWriteFonName( p, iFon0, fInlineConcat, 0 ); Vec_StrPrintStr( vStr, "), .qbar(" ); if ( Cba_FonName(p, iFon1) ) Cba_ManWriteFonName( p, iFon1, fInlineConcat, 0 ); Vec_StrPrintStr( vStr, ") );" ); } else if ( Type == CBA_BOX_ADD ) { int iFon0 = Cba_ObjFon0(p, iObj); int iFon1 = Cba_ObjFon(p, iObj, 1); // write outputs if ( Cba_FonName(p, iFon1) ) { if ( !Vec_BitEntry(vPoFons, iFon0) ) { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFon0 ); Cba_ManWriteFonName( p, iFon0, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); } if ( !Vec_BitEntry(vPoFons, iFon1) ) { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFon1 ); Cba_ManWriteFonName( p, iFon1, 0, 0 ); Vec_StrPrintStr( vStr, ";\n" ); } Vec_StrPrintStr( vStr, " assign {" ); Cba_ManWriteFonName( p, iFon1, 0, 0 ); Vec_StrPrintStr( vStr, ", " ); Cba_ManWriteFonName( p, iFon0, 0, 0 ); Vec_StrPrintStr( vStr, "} = " ); } else { if ( Vec_BitEntry(vPoFons, iFon0) ) Vec_StrPrintStr( vStr, " assign " ); else { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, iFon0 ); } Cba_ManWriteFonName( p, iFon0, 0, 0 ); Vec_StrPrintStr( vStr, " = " ); } // write carry-in if ( Cba_ObjFinFon(p, iObj, 0) && Cba_ObjFinFon(p, iObj, 0) != Cba_FonFromConst(1) ) { Vec_StrPush( vStr, ' ' ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 ); Vec_StrPush( vStr, ' ' ); Vec_StrPrintStr( vStr, "+" ); } Vec_StrPush( vStr, ' ' ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 ); Vec_StrPush( vStr, ' ' ); Vec_StrPrintStr( vStr, "+" ); Vec_StrPush( vStr, ' ' ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 ); Vec_StrPush( vStr, ';' ); } else { if ( Vec_BitEntry(vPoFons, Cba_ObjFon0(p, iObj)) ) Vec_StrPrintStr( vStr, " assign " ); else { Vec_StrPrintStr( vStr, " wire " ); Cba_ManWriteFonRange( p, Cba_ObjFon0(p, iObj) ); } Cba_ManWriteFonName( p, Cba_ObjFon0(p, iObj), 0, 0 ); Vec_StrPrintStr( vStr, " = " ); if ( Cba_ObjIsConcat(p, iObj) ) Cba_ManWriteConcat( p, iObj ); else if ( Type == CBA_BOX_MUX ) { Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, " ? " ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, " : " ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 ); } else if ( Type == CBA_BOX_ROTL || Type == CBA_BOX_ROTR ) { // wire [27:0] s4960 = (s57 >> 17) | (s57 << 11); int Range = Cba_FonRangeSize( p, Cba_ObjFon0(p, iObj) ); int iFinFon1 = Cba_ObjFinFon(p, iObj, 1); Vec_StrPush( vStr, '(' ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, Type == CBA_BOX_ROTL ? " << " : " >> " ); if ( Cba_FonIsConst(iFinFon1) ) Vec_StrPrintNum( vStr, Cba_FonConst(iFinFon1) ); else Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, ") | (" ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 ); Vec_StrPrintStr( vStr, Type == CBA_BOX_ROTL ? " >> " : " << " ); if ( Cba_FonIsConst(iFinFon1) ) Vec_StrPrintNum( vStr, Range - Cba_FonConst(iFinFon1) ); else { Vec_StrPush( vStr, '(' ); Vec_StrPrintNum( vStr, Range ); Vec_StrPrintStr( vStr, " - " ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 ); Vec_StrPush( vStr, ')' ); } Vec_StrPush( vStr, ')' ); } else if ( Type == CBA_BOX_LTHAN ) { int fLessThan = (Cba_ObjFinFon(p, iObj, 0) == Cba_FonFromConst(1)); // const0 Vec_StrPush( vStr, ' ' ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 ); Vec_StrPush( vStr, ' ' ); Vec_StrPrintStr( vStr, fLessThan ? "<" : "<=" ); Vec_StrPush( vStr, ' ' ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 2), fInlineConcat, 0 ); } else if ( Cba_TypeIsUnary((Cba_ObjType_t)Type) ) { Vec_StrPrintStr( vStr, Cba_NtkTypeName(p, Type) ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 ); } else if ( Cba_NtkTypeName(p, Type) ) // binary operation { int fCompl = (Type == CBA_BOX_NAND || Type == CBA_BOX_NOR || Type == CBA_BOX_XNOR); if ( fCompl ) Vec_StrPrintStr( vStr, "!(" ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 0), fInlineConcat, 0 ); Vec_StrPush( vStr, ' ' ); Vec_StrPrintStr( vStr, Cba_NtkTypeName(p, Type) ); Vec_StrPush( vStr, ' ' ); Cba_ManWriteFonName( p, Cba_ObjFinFon(p, iObj, 1), fInlineConcat, 0 ); if ( fCompl ) Vec_StrPrintStr( vStr, ")" ); } else // unknown { char * pName = Cba_FonGetName(p, Cba_ObjFon0(p, iObj)); Vec_StrPrintStr( vStr, "" ); printf( "Cba_ManWriteVerilog(): In module \"%s\", cannot write object \"%s\" with output name \"%s\".\n", Cba_NtkName(p), Cba_ObjGetName(p, iObj), pName ); } Vec_StrPush( vStr, ';' ); } // write attributes Status = Cba_ManWriteLineFile( p, iObj, FileAttr, LineAttr ); if ( !Cba_ObjIsBoxUser(p, iObj) && Cba_ObjName(p, iObj) ) { if ( !Status ) Vec_StrPrintStr( vStr, " //" ); Vec_StrPrintStr( vStr, " name=" ); Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) ); } Vec_StrPush( vStr, '\n' ); } // write remaining outputs Cba_NtkForEachPo( p, iObj, i ) { iFon = Cba_ObjFinFon(p, iObj, 0); if ( !iFon || (!Cba_FonIsConst(iFon) && Cba_FonName(p, iFon) == Cba_ObjName(p, iObj)) ) // already written continue; Vec_StrPrintStr( vStr, " assign " ); Vec_StrPrintStr( vStr, Cba_ObjGetName(p, iObj) ); Vec_StrPrintStr( vStr, " = " ); Cba_ManWriteFonName( p, iFon, fInlineConcat, 0 ); Vec_StrPush( vStr, ';' ); Vec_StrPush( vStr, '\n' ); } Vec_StrPrintStr( vStr, "\n" ); Vec_StrPrintStr( vStr, "endmodule\n\n" ); Vec_BitFree( vPoFons ); } void Cba_ManWriteVerilog( char * pFileName, Cba_Man_t * p, int fInlineConcat ) { Cba_Ntk_t * pNtk; int i; // check the library if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() ) { printf( "Genlib library used in the mapped design is not longer a current library.\n" ); return; } Cba_ManCreatePrimMap( p->pTypeNames ); // derive the stream p->nOpens = 1; Vec_StrClear( &p->vOut ); Vec_StrClear( &p->vOut2 ); Vec_StrPrintStr( &p->vOut, "// Design \"" ); Vec_StrPrintStr( &p->vOut, Cba_ManName(p) ); Vec_StrPrintStr( &p->vOut, "\" written via CBA package in ABC on " ); Vec_StrPrintStr( &p->vOut, Extra_TimeStamp() ); Vec_StrPrintStr( &p->vOut, "\n\n" ); Cba_ManForEachNtk( p, pNtk, i ) Cba_ManWriteVerilogNtk( pNtk, fInlineConcat ); // dump into file if ( Vec_StrSize(&p->vOut) > 0 ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { fwrite( Vec_StrArray(&p->vOut), 1, Vec_StrSize(&p->vOut), pFile ); fclose( pFile ); } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cba/module.make000066400000000000000000000003431300674244400236170ustar00rootroot00000000000000SRC += src/base/cba/cbaBlast.c \ src/base/cba/cbaCba.c \ src/base/cba/cbaCom.c \ src/base/cba/cbaNtk.c \ src/base/cba/cbaReadBlif.c \ src/base/cba/cbaReadVer.c \ src/base/cba/cbaWriteBlif.c \ src/base/cba/cbaWriteVer.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/000077500000000000000000000000001300674244400215115ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmd.c000066400000000000000000002253261300674244400224320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Command file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifdef WIN32 #include #else #include #endif #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "cmdInt.h" #include "misc/util/utilSignal.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int CmdCommandTime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandEcho ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandQuit ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandAbcrc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandHistory ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandAlias ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandUnalias ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandHelp ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandSource ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandSetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandUnsetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandUndo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandRecall ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandEmpty ( Abc_Frame_t * pAbc, int argc, char ** argv ); #if defined(WIN32) && !defined(__cplusplus) static int CmdCommandScanDir ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandRenameFiles ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandScrGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); #endif static int CmdCommandVersion ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandStarter ( Abc_Frame_t * pAbc, int argc, char ** argv ); extern int Cmd_CommandAbcLoadPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [Initializes the command package.] SideEffects [Commands are added to the command table.] SeeAlso [Cmd_End] ******************************************************************************/ void Cmd_Init( Abc_Frame_t * pAbc ) { pAbc->tCommands = st__init_table(strcmp, st__strhash); pAbc->tAliases = st__init_table(strcmp, st__strhash); pAbc->tFlags = st__init_table(strcmp, st__strhash); pAbc->aHistory = Vec_PtrAlloc( 100 ); Cmd_HistoryRead( pAbc ); Cmd_CommandAdd( pAbc, "Basic", "time", CmdCommandTime, 0 ); Cmd_CommandAdd( pAbc, "Basic", "echo", CmdCommandEcho, 0 ); Cmd_CommandAdd( pAbc, "Basic", "quit", CmdCommandQuit, 0 ); Cmd_CommandAdd( pAbc, "Basic", "abcrc", CmdCommandAbcrc, 0 ); Cmd_CommandAdd( pAbc, "Basic", "history", CmdCommandHistory, 0 ); Cmd_CommandAdd( pAbc, "Basic", "alias", CmdCommandAlias, 0 ); Cmd_CommandAdd( pAbc, "Basic", "unalias", CmdCommandUnalias, 0 ); Cmd_CommandAdd( pAbc, "Basic", "help", CmdCommandHelp, 0 ); Cmd_CommandAdd( pAbc, "Basic", "source", CmdCommandSource, 0 ); Cmd_CommandAdd( pAbc, "Basic", "set", CmdCommandSetVariable, 0 ); Cmd_CommandAdd( pAbc, "Basic", "unset", CmdCommandUnsetVariable, 0 ); Cmd_CommandAdd( pAbc, "Basic", "undo", CmdCommandUndo, 0 ); Cmd_CommandAdd( pAbc, "Basic", "recall", CmdCommandRecall, 0 ); Cmd_CommandAdd( pAbc, "Basic", "empty", CmdCommandEmpty, 0 ); #if defined(WIN32) && !defined(__cplusplus) Cmd_CommandAdd( pAbc, "Basic", "scandir", CmdCommandScanDir, 0 ); Cmd_CommandAdd( pAbc, "Basic", "renamefiles", CmdCommandRenameFiles, 0 ); Cmd_CommandAdd( pAbc, "Basic", "ls", CmdCommandLs, 0 ); Cmd_CommandAdd( pAbc, "Basic", "scrgen", CmdCommandScrGen, 0 ); #endif Cmd_CommandAdd( pAbc, "Basic", "version", CmdCommandVersion, 0 ); Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1 ); Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1 ); Cmd_CommandAdd( pAbc, "Various", "capo", CmdCommandCapo, 0 ); Cmd_CommandAdd( pAbc, "Various", "starter", CmdCommandStarter, 0 ); Cmd_CommandAdd( pAbc, "Various", "load_plugin", Cmd_CommandAbcLoadPlugIn, 0 ); } /**Function******************************************************************** Synopsis [Ends the command package.] Description [Ends the command package. Tables are freed.] SideEffects [] SeeAlso [] ******************************************************************************/ void Cmd_End( Abc_Frame_t * pAbc ) { st__generator * gen; char * pKey, * pValue; Cmd_HistoryWrite( pAbc, ABC_INFINITY ); // st__free_table( pAbc->tCommands, (void (*)()) 0, CmdCommandFree ); // st__free_table( pAbc->tAliases, (void (*)()) 0, CmdCommandAliasFree ); // st__free_table( pAbc->tFlags, free, free ); st__foreach_item( pAbc->tCommands, gen, (const char **)&pKey, (char **)&pValue ) CmdCommandFree( (Abc_Command *)pValue ); st__free_table( pAbc->tCommands ); st__foreach_item( pAbc->tAliases, gen, (const char **)&pKey, (char **)&pValue ) CmdCommandAliasFree( (Abc_Alias *)pValue ); st__free_table( pAbc->tAliases ); st__foreach_item( pAbc->tFlags, gen, (const char **)&pKey, (char **)&pValue ) ABC_FREE( pKey ), ABC_FREE( pValue ); st__free_table( pAbc->tFlags ); Vec_PtrFreeFree( pAbc->aHistory ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; int fClear; fClear = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fClear ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fClear ) { pAbc->TimeTotal += pAbc->TimeCommand; pAbc->TimeCommand = 0.0; return 0; } if ( argc != globalUtilOptind ) { goto usage; } pAbc->TimeTotal += pAbc->TimeCommand; fprintf( pAbc->Out, "elapse: %3.2f seconds, total: %3.2f seconds\n", pAbc->TimeCommand, pAbc->TimeTotal ); /* { FILE * pTable; pTable = fopen( "runtimes.txt", "a+" ); fprintf( pTable, "%4.2f\n", pAbc->TimeCommand ); fclose( pTable ); } */ pAbc->TimeCommand = 0.0; return 0; usage: fprintf( pAbc->Err, "usage: time [-ch]\n" ); fprintf( pAbc->Err, " \t\tprint the runtime since the last call\n" ); fprintf( pAbc->Err, " -c \t\tclears the elapsed time without printing it\n" ); fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv ) { int i; int c; int n = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF ) { switch ( c ) { case 'n': n = 0; break; case 'h': goto usage; break; default: goto usage; } } if (pAbc->Out == stdout){ for ( i = globalUtilOptind; i < argc; i++ ) Abc_Print( 1, "%s ", argv[i] ); if ( n ) Abc_Print( 1, "\n" ); }else{ for ( i = globalUtilOptind; i < argc; i++ ) fprintf( pAbc->Out, "%s ", argv[i] ); if ( n ) fprintf( pAbc->Out, "\n" ); fflush ( pAbc->Out ); } return 0; usage: fprintf( pAbc->Err, "usage: echo [-h] string \n" ); fprintf( pAbc->Err, " -n \t\tsuppress newline at the end\n" ); fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); return ( 1 ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; break; case 's': return -2; break; default: goto usage; } } if ( argc != globalUtilOptind ) goto usage; return -1; usage: fprintf( pAbc->Err, "usage: quit [-sh]\n" ); fprintf( pAbc->Err, " -h print the command usage\n" ); fprintf( pAbc->Err, " -s frees all the memory before quitting\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandAbcrc( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; break; default: goto usage; } } Abc_UtilsSource( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: abcrc [-h]\n" ); fprintf( pAbc->Err, " -h sources \"abc.rc\" from the current/parent/grandparent directory\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pName; int i, c; int nPrints = 20; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default : goto usage; } } if ( argc > globalUtilOptind + 1 ) goto usage; // get the number from the command line if ( argc == globalUtilOptind + 1 ) nPrints = atoi(argv[globalUtilOptind]); // print the commands Vec_PtrForEachEntryStart( char *, pAbc->aHistory, pName, i, Abc_MaxInt(0, Vec_PtrSize(pAbc->aHistory)-nPrints) ) fprintf( pAbc->Out, "%2d : %s\n", Vec_PtrSize(pAbc->aHistory)-i, pName ); return 0; usage: fprintf( pAbc->Err, "usage: history [-h] \n" ); fprintf( pAbc->Err, "\t lists the last commands entered on the command line\n" ); fprintf( pAbc->Err, "\t-h : print the command usage\n" ); fprintf( pAbc->Err, "\t : the maximum number of entries to show [default = %d]\n", nPrints ); return ( 1 ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandAlias( Abc_Frame_t * pAbc, int argc, char **argv ) { const char *key; char *value; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; break; default: goto usage; } } if ( argc == 1 ) { CmdPrintTable( pAbc->tAliases, 1 ); return 0; } else if ( argc == 2 ) { if ( st__lookup( pAbc->tAliases, argv[1], &value ) ) CmdCommandAliasPrint( pAbc, ( Abc_Alias * ) value ); return 0; } // delete any existing alias key = argv[1]; if ( st__delete( pAbc->tAliases, &key, &value ) ) CmdCommandAliasFree( ( Abc_Alias * ) value ); CmdCommandAliasAdd( pAbc, argv[1], argc - 2, argv + 2 ); return 0; usage: fprintf( pAbc->Err, "usage: alias [-h] [command [string]]\n" ); fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); return ( 1 ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv ) { int i; const char *key; char *value; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; break; default: goto usage; } } if ( argc < 2 ) { goto usage; } for ( i = 1; i < argc; i++ ) { key = argv[i]; if ( st__delete( pAbc->tAliases, &key, &value ) ) { CmdCommandAliasFree( ( Abc_Alias * ) value ); } } return 0; usage: fprintf( pAbc->Err, "usage: unalias [-h] alias_names\n" ); fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv ) { int fPrintAll, fDetails; int c; fPrintAll = 0; fDetails = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "adh" ) ) != EOF ) { switch ( c ) { case 'a': case 'v': fPrintAll ^= 1; break; break; case 'd': fDetails ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind ) goto usage; CmdCommandPrint( pAbc, fPrintAll, fDetails ); return 0; usage: fprintf( pAbc->Err, "usage: help [-a] [-d] [-h]\n" ); fprintf( pAbc->Err, " prints the list of available commands by group\n" ); fprintf( pAbc->Err, " -a toggle printing hidden commands [default = %s]\n", fPrintAll? "yes": "no" ); fprintf( pAbc->Err, " -d print usage details to all commands [default = %s]\n", fDetails? "yes": "no" ); fprintf( pAbc->Err, " -h print the command usage\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) { int c, echo, prompt, silent, interactive, quit_count, lp_count; int status = 0; /* initialize so that lint doesn't complain */ int lp_file_index, did_subst; char *prompt_string, *real_filename, line[ABC_MAX_STR], *command; FILE *fp; interactive = silent = prompt = echo = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ipsxh" ) ) != EOF ) { switch ( c ) { case 'i': /* a hack to distinguish EOF from stdin */ interactive = 1; break; case 'p': prompt ^= 1; break; case 's': silent ^= 1; break; case 'x': echo ^= 1; break; case 'h': goto usage; default: goto usage; } } /* added to avoid core-dumping when no script file is specified */ if ( argc == globalUtilOptind ) { goto usage; } lp_file_index = globalUtilOptind; lp_count = 0; /* * FIX (Tom, 5/7/95): I'm not sure what the purpose of this outer do loop * is. In particular, lp_file_index is never modified in the loop, so it * looks it would just read the same file over again. Also, SIS had * lp_count initialized to -1, and hence, any file sourced by SIS (if -l or * -t options on "source" were used in SIS) would actually be executed twice. */ pAbc->fSource = 1; do { char * pFileName, * pTemp; // get the input file name pFileName = argv[lp_file_index]; // fix the wrong symbol for ( pTemp = pFileName; *pTemp; pTemp++ ) if ( *pTemp == '>' ) *pTemp = '\\'; lp_count++; /* increment the loop counter */ fp = CmdFileOpen( pAbc, pFileName, "r", &real_filename, silent ); if ( fp == NULL ) { pAbc->fSource = 0; ABC_FREE( real_filename ); return !silent; /* error return if not silent */ } quit_count = 0; do { if ( prompt ) { prompt_string = Cmd_FlagReadByName( pAbc, "prompt" ); if ( prompt_string == NULL ) prompt_string = "abc> "; } else { prompt_string = NULL; } /* clear errors -- e.g., EOF reached from stdin */ clearerr( fp ); /* read another command line */ if ( fgets( line, ABC_MAX_STR, fp ) == NULL ) { if ( interactive ) { if ( quit_count++ < 5 ) { fprintf( pAbc->Err, "\nUse \"quit\" to leave ABC.\n" ); continue; } status = -1; /* fake a 'quit' */ } else { status = 0; /* successful end of 'source' ; loop? */ } break; } quit_count = 0; if ( echo ) { fprintf( pAbc->Out, "abc - > %s", line ); } command = CmdHistorySubstitution( pAbc, line, &did_subst ); if ( command == NULL ) { status = 1; break; } if ( did_subst ) { if ( interactive ) { fprintf( pAbc->Out, "%s\n", command ); } } if ( command != line ) { strcpy( line, command ); } if ( interactive && *line != '\0' ) { Cmd_HistoryAddCommand( pAbc, line ); if ( pAbc->Hst != NULL ) { fprintf( pAbc->Hst, "%s\n", line ); fflush( pAbc->Hst ); } } fflush( pAbc->Out ); status = Cmd_CommandExecute( pAbc, line ); } while ( status == 0 ); if ( fp != stdin ) { if ( status > 0 ) { fprintf( pAbc->Err, "** cmd error: aborting 'source %s'\n", real_filename ); } fclose( fp ); } ABC_FREE( real_filename ); } while ( ( status == 0 ) && ( lp_count <= 0 ) ); pAbc->fSource = 0; return status; usage: fprintf( pAbc->Err, "usage: source [-psxh] \n" ); fprintf( pAbc->Err, "\t-p supply prompt before reading each line [default = %s]\n", prompt? "yes": "no" ); fprintf( pAbc->Err, "\t-s silently ignore nonexistant file [default = %s]\n", silent? "yes": "no" ); fprintf( pAbc->Err, "\t-x echo each line as it is executed [default = %s]\n", echo? "yes": "no" ); fprintf( pAbc->Err, "\t-h print the command usage\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) { char *flag_value, *value; const char* key; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc == 0 || argc > 3 ) { goto usage; } else if ( argc == 1 ) { CmdPrintTable( pAbc->tFlags, 0 ); return 0; } else { key = argv[1]; if ( st__delete( pAbc->tFlags, &key, &value ) ) { ABC_FREE( key ); ABC_FREE( value ); } flag_value = argc == 2 ? Extra_UtilStrsav( "" ) : Extra_UtilStrsav( argv[2] ); // flag_value = argc == 2 ? NULL : Extra_UtilStrsav(argv[2]); st__insert( pAbc->tFlags, Extra_UtilStrsav(argv[1]), flag_value ); if ( strcmp( argv[1], "abcout" ) == 0 ) { if ( pAbc->Out != stdout ) fclose( pAbc->Out ); if ( strcmp( flag_value, "" ) == 0 ) flag_value = "-"; pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); if ( pAbc->Out == NULL ) pAbc->Out = stdout; #if HAVE_SETVBUF setvbuf( pAbc->Out, ( char * ) NULL, _IOLBF, 0 ); #endif } if ( strcmp( argv[1], "abcerr" ) == 0 ) { if ( pAbc->Err != stderr ) fclose( pAbc->Err ); if ( strcmp( flag_value, "" ) == 0 ) flag_value = "-"; pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); if ( pAbc->Err == NULL ) pAbc->Err = stderr; #if HAVE_SETVBUF setvbuf( pAbc->Err, ( char * ) NULL, _IOLBF, 0 ); #endif } if ( strcmp( argv[1], "history" ) == 0 ) { if ( pAbc->Hst != NULL ) fclose( pAbc->Hst ); if ( strcmp( flag_value, "" ) == 0 ) pAbc->Hst = NULL; else { pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); if ( pAbc->Hst == NULL ) pAbc->Hst = NULL; } } return 0; } usage: fprintf( pAbc->Err, "usage: set [-h] \n" ); fprintf( pAbc->Err, "\t sets the value of parameter \n" ); fprintf( pAbc->Err, "\t-h : print the command usage\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) { int i; const char *key; char *value; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; break; default: goto usage; } } if ( argc < 2 ) { goto usage; } for ( i = 1; i < argc; i++ ) { key = argv[i]; if ( st__delete( pAbc->tFlags, &key, &value ) ) { ABC_FREE( key ); ABC_FREE( value ); } } return 0; usage: fprintf( pAbc->Err, "usage: unset [-h] \n" ); fprintf( pAbc->Err, "\t removes the value of parameter \n" ); fprintf( pAbc->Err, "\t-h : print the command usage\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) { if ( argc == 2 && !strcmp(argv[1], "-h") ) goto usage; if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } // if there are no arguments on the command line // set the current network to be the network from the previous step if ( argc == 1 ) return CmdCommandRecall( pAbc, argc, argv ); usage: fprintf( pAbc->Err, "usage: undo\n" ); fprintf( pAbc->Err, " sets the current network to be the previously saved network\n" ); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk; int iStep, iStepFound; int nNetsToSave, c; char * pValue; int iStepStart, iStepStop; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } // get the number of networks to save pValue = Cmd_FlagReadByName( pAbc, "savesteps" ); // if the value of steps to save is not set, assume 1-level undo if ( pValue == NULL ) nNetsToSave = 1; else nNetsToSave = atoi(pValue); // if there are no arguments on the command line // set the current network to be the network from the previous step if ( argc == 1 ) { // get the previously saved network pNtk = Abc_NtkBackup(pAbc->pNtkCur); if ( pNtk == NULL ) fprintf( pAbc->Out, "There is no previously saved network.\n" ); else // set the current network to be the copy of the previous one Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) ); return 0; } if ( argc == 2 ) // the second argument is the number of the step to return to { // read the number of the step to return to iStep = atoi(argv[1]); // check whether it is reasonable if ( iStep >= pAbc->nSteps ) { iStepStart = pAbc->nSteps - nNetsToSave; if ( iStepStart <= 0 ) iStepStart = 1; iStepStop = pAbc->nSteps; if ( iStepStop <= 0 ) iStepStop = 1; if ( iStepStart == iStepStop ) fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop ); else fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop ); } else if ( iStep < 0 ) fprintf( pAbc->Out, "Cannot recall step %d.\n", iStep ); else if ( iStep == 0 ) Abc_FrameDeleteAllNetworks( pAbc ); else { // scroll backward through the list of networks // to determine if such a network exist iStepFound = 0; for ( pNtk = pAbc->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) ) if ( (iStepFound = Abc_NtkStep(pNtk)) == iStep ) break; if ( pNtk == NULL ) { iStepStart = iStepFound; if ( iStepStart <= 0 ) iStepStart = 1; iStepStop = pAbc->nSteps; if ( iStepStop <= 0 ) iStepStop = 1; if ( iStepStart == iStepStop ) fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop ); else fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop ); } else Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) ); } return 0; } usage: fprintf( pAbc->Err, "usage: recall -h \n" ); fprintf( pAbc->Err, " set the current network to be one of the previous networks\n" ); fprintf( pAbc->Err, " : level to return to [default = previous]\n" ); fprintf( pAbc->Err, " -h : print the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } Abc_FrameDeleteAllNetworks( pAbc ); Abc_FrameRestart( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: empty [-h]\n" ); fprintf( pAbc->Err, " removes all the currently stored networks\n" ); fprintf( pAbc->Err, " -h : print the command usage\n"); return 1; } #if 0 /**Function******************************************************************** Synopsis [Donald's version.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtkTemp; int id, c; while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; break; default: goto usage; } } if (globalUtilOptind <= argc) { pNtkTemp = pAbc->pNtk; pAbc->pNtk = pAbc->pNtkSaved; pAbc->pNtkSaved = pNtkTemp; } id = atoi(argv[globalUtilOptind]); pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id); if (!pNtkTemp) fprintf( pAbc->Err, "Snapshot %d does not exist\n", id); else pAbc->pNtk = Abc_NtkDup(pNtkTemp, Abc_NtkMan(pNtkTemp)); return 0; usage: fprintf( pAbc->Err, "usage: undo\n" ); fprintf( pAbc->Err, " swaps the current network and the backup network\n" ); return 1; } #endif #if defined(WIN32) && !defined(__cplusplus) #include // these structures are defined in but are for some reason invisible typedef unsigned long _fsize_t; // Could be 64 bits for Win32 struct _finddata_t { unsigned attrib; time_t time_create; // -1 for FAT file systems time_t time_access; // -1 for FAT file systems time_t time_write; _fsize_t size; char name[260]; }; extern long _findfirst( char *filespec, struct _finddata_t *fileinfo ); extern int _findnext( long handle, struct _finddata_t *fileinfo ); extern int _findclose( long handle ); //extern char * _getcwd( char * buffer, int maxlen ); //extern int _chdir( const char *dirname ); /**Function************************************************************* Synopsis [Command to print the contents of the current directory (Windows).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdCommandScanDir( Abc_Frame_t * pAbc, int argc, char **argv ) { struct _finddata_t c_file; char * pDirStr = NULL; char* pDirCur = NULL; long hFile; char c; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "D") ) != EOF ) { switch (c) { case 'D': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" ); goto usage; } pDirStr = argv[globalUtilOptind]; globalUtilOptind++; break; default: goto usage; } } if ( pDirStr ) { if( (pDirCur = _getcwd( NULL, 0 )) == NULL ) { printf( "Cannot read current directory\n" ); return 0; } if ( _chdir(pDirStr) ) { printf( "Cannot change to directory: %s\n", pDirStr ); return 0; } } if( (hFile = _findfirst( "*.txt", &c_file )) == -1L ) { if ( pDirStr ) printf( "No .txt files in the current directory.\n" ); else printf( "No .txt files in directory: %s\n", pDirStr ); } else { do { FILE * pFile = fopen( c_file.name, "rb" ); char * pStr1 = "Property UNDECIDED. Time ="; char * pStr2 = "Property proved. Time ="; char * pStr3 = "Time ="; char * pBuffer, * pPlace, * pThis, * pThat; char FileName[100]; float Time = 0; // get the file name sprintf( FileName, "%s", c_file.name ); pThis = strrchr( FileName, '_' ); pThat = strchr( FileName, '.' ); if ( pThis == NULL || pThat == NULL || pThis >= pThat ) { // printf( "Something is wrong with the file name %s\n", c_file.name ); continue; } *pThat = 0; pThis++; // get the time if ( pFile == NULL ) { printf( "Cannot open file %s\n", c_file.name ); continue; } fclose( pFile ); pBuffer = Extra_FileReadContents( c_file.name ); pPlace = strstr( pBuffer, pStr1 ); if ( pPlace == NULL ) { pPlace = strstr( pBuffer, pStr2 ); if ( pPlace == NULL ) { pPlace = strstr( pBuffer, pStr3 ); if ( pPlace == NULL ) { // printf( "Cannot find substrings in file %s\n", c_file.name ); ABC_FREE( pBuffer ); continue; } else pPlace += strlen( pStr3 ); } else pPlace += strlen( pStr2 ); } else pPlace += strlen( pStr1 ); sscanf( pPlace, "%f", &Time ); printf( "%s %.2f\n", pThis, Time ); ABC_FREE( pBuffer ); } while( _findnext( hFile, &c_file ) == 0 ); _findclose( hFile ); } if ( pDirStr ) { if ( _chdir(pDirCur) ) { ABC_FREE( pDirCur ); printf( "Cannot change to directory: %s\n", pDirCur ); return 0; } ABC_FREE( pDirCur ); } return 0; usage: fprintf( pAbc->Err, "usage: scandir [-D string]\n" ); fprintf( pAbc->Err, " performs custom scanning of the files in the given directory\n" ); fprintf( pAbc->Err, "\t-D str : the directory to read files from [default = current]\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmfFindNumber( char * pName ) { char * pTemp; for ( pTemp = pName; *pTemp; pTemp++ ) if ( *pTemp == '.' ) break; if ( *pTemp == 0 ) return -1; for ( --pTemp; pTemp > pName; pTemp-- ) if ( *pTemp < '0' || *pTemp > '9' ) { pTemp++; break; } if ( *pTemp == '.' ) return -2; return atoi( pTemp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void CnfDupFileUnzip( char * pOldName ) { extern char * Io_MvLoadFileBz2( char * pFileName, int * pnFileSize ); char pNewName[1000]; FILE * pFile; int nFileSize; char * pBuffer = Io_MvLoadFileBz2( pOldName, &nFileSize ); assert( strlen(pOldName) < 1000 ); sprintf( pNewName, "%s.v", pOldName ); pFile = fopen( pNewName, "wb" ); fwrite( pBuffer, nFileSize, 1, pFile ); fclose( pFile ); ABC_FREE( pBuffer ); } /**Function************************************************************* Synopsis [Command to print the contents of the current directory (Windows).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdCommandRenameFiles( Abc_Frame_t * pAbc, int argc, char **argv ) { struct _finddata_t c_file; long hFile; char pNewName[1000]; char * pDirStr = NULL; char * pDirCur = NULL; char * pNameNew = NULL; char * pNameExt = NULL; int c, i, nBase = 0; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "DENB") ) != EOF ) { switch (c) { case 'D': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" ); goto usage; } pDirStr = argv[globalUtilOptind]; globalUtilOptind++; break; case 'E': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-E\" should be followed by a string.\n" ); goto usage; } pNameExt = argv[globalUtilOptind]; globalUtilOptind++; break; case 'N': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-N\" should be followed by a string.\n" ); goto usage; } pNameNew = argv[globalUtilOptind]; globalUtilOptind++; break; case 'B': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-B\" should be followed by a positive integer.\n" ); goto usage; } nBase = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBase < 0 ) goto usage; break; default: goto usage; } } if ( pNameExt == NULL ) { printf( "Extension of the files should be given on the command line.\n" ); return 0; } if ( pDirStr ) { if( (pDirCur = _getcwd( NULL, 0 )) == NULL ) { printf( "Cannot read current directory\n" ); return 0; } if ( _chdir(pDirStr) ) { printf( "Cannot change to directory: %s\n", pDirStr ); return 0; } } sprintf( pNewName, "*.%s", pNameExt ); if( (hFile = _findfirst( pNewName, &c_file )) == -1L ) { if ( pDirStr ) printf( "No .aig files in the current directory.\n" ); else printf( "No .aig files in directory: %s\n", pDirStr ); } else { char * pName, * pOldName; int nDigits, * pOrder; Vec_Ptr_t * vNames = Vec_PtrAlloc( 1000 ); Vec_Int_t * vNums = Vec_IntAlloc( 1000 ); // collect names do { Vec_PtrPush( vNames, Abc_UtilStrsav(c_file.name) ); } while( _findnext( hFile, &c_file ) == 0 ); _findclose( hFile ); // sort files by number Vec_PtrForEachEntry( char *, vNames, pName, i ) { Vec_IntPush( vNums, CmfFindNumber(pName) ); if ( Vec_IntEntryLast(vNums) < 0 ) { printf( "Directory \"%s\" contains file (%s) with extension %s without number\n", pDirStr, pName, pNameExt ); Vec_PtrFreeFree( vNames ); Vec_IntFree( vNums ); return 0; } } // sort by number pOrder = Abc_QuickSortCost( Vec_IntArray(vNums), Vec_IntSize(vNums), 0 ); // rename files in that order // nDigits = Abc_Base10Log( nBase + Vec_IntSize(vNums) ); nDigits = Abc_Base10Log( nBase + Vec_IntEntry(vNums, pOrder[Vec_IntSize(vNums)-1]) + 1 ); for ( i = 0; i < Vec_IntSize(vNums); i++ ) { pOldName = (char *)Vec_PtrEntry( vNames, pOrder[i] ); sprintf( pNewName, "%s%0*d.%s", pNameNew ? pNameNew : "", nDigits, nBase+Vec_IntEntry(vNums, pOrder[i]), pNameExt ); rename( pOldName, pNewName ); printf( "%s -> %s\n", pOldName, pNewName ); // CnfDupFileUnzip( pOldName ); } // cleanup Vec_PtrFreeFree( vNames ); Vec_IntFree( vNums ); ABC_FREE( pOrder ); } if ( pDirStr ) { if ( _chdir(pDirCur) ) { ABC_FREE( pDirCur ); printf( "Cannot change to directory: %s\n", pDirCur ); return 0; } ABC_FREE( pDirCur ); } return 0; usage: fprintf( pAbc->Err, "usage: renamefiles [-DEN str] [-B num]\n" ); fprintf( pAbc->Err, " performs renaming of files in the given directory\n" ); fprintf( pAbc->Err, "\t-D str : the directory to read files from [default = current]\n" ); fprintf( pAbc->Err, "\t-E str : the extension of files to look for [default = none]\n" ); fprintf( pAbc->Err, "\t-N str : the root of the resulting files [default = none]\n" ); fprintf( pAbc->Err, "\t-B num : the base number for all files [default = %d]\n", nBase ); return 1; } /**Function************************************************************* Synopsis [Command to print the contents of the current directory (Windows).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv ) { struct _finddata_t c_file; long hFile; int fLong = 0; int fOnlyBLIF = 0; char Buffer[25]; int Counter = 0; int fPrintedNewLine; char c; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF ) { switch (c) { case 'l': fLong = 1; break; case 'b': fOnlyBLIF = 1; break; default: goto usage; } } // find first .mv file in current directory if( (hFile = _findfirst( ((fOnlyBLIF)? "*.mv": "*.*"), &c_file )) == -1L ) { if ( fOnlyBLIF ) fprintf( pAbc->Out, "No *.mv files in the current directory.\n" ); else fprintf( pAbc->Out, "No files in the current directory.\n" ); } else { if ( fLong ) { fprintf( pAbc->Out, " File Date Size | File Date Size \n" ); fprintf( pAbc->Out, " ----------------------------------------------------------------------------- \n" ); do { strcpy( Buffer, ctime( &(c_file.time_write) ) ); Buffer[16] = 0; fprintf( pAbc->Out, " %-17s %.24s%7ld", c_file.name, Buffer+4, c_file.size ); if ( ++Counter % 2 == 0 ) { fprintf( pAbc->Out, "\n" ); fPrintedNewLine = 1; } else { fprintf( pAbc->Out, " |" ); fPrintedNewLine = 0; } } while( _findnext( hFile, &c_file ) == 0 ); } else { do { fprintf( pAbc->Out, " %-18s", c_file.name ); if ( ++Counter % 4 == 0 ) { fprintf( pAbc->Out, "\n" ); fPrintedNewLine = 1; } else { fprintf( pAbc->Out, " " ); fPrintedNewLine = 0; } } while( _findnext( hFile, &c_file ) == 0 ); } if ( !fPrintedNewLine ) fprintf( pAbc->Out, "\n" ); _findclose( hFile ); } return 0; usage: fprintf( pAbc->Err, "usage: ls [-l] [-b]\n" ); fprintf( pAbc->Err, " print the file names in the current directory\n" ); fprintf( pAbc->Err, " -l : print in the long format [default = short]\n" ); fprintf( pAbc->Err, " -b : print only .mv files [default = all]\n" ); return 1; } /**Function************************************************************* Synopsis [Generates the script for running ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdCommandScrGen( Abc_Frame_t * pAbc, int argc, char **argv ) { struct _finddata_t c_file; long hFile; FILE * pFile = NULL; char * pFileStr = "test.s"; char * pDirStr = NULL; char * pComStr = "ps"; char * pWriteStr = NULL; char Buffer[1000], Line[2000]; int nFileNameMax, nFileNameCur; int Counter = 0; int fUseCurrent; char c; fUseCurrent = 0; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "FDCWch") ) != EOF ) { switch (c) { case 'F': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-F\" should be followed by a string.\n" ); goto usage; } pFileStr = argv[globalUtilOptind]; globalUtilOptind++; break; case 'D': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-D\" should be followed by a string.\n" ); goto usage; } pDirStr = argv[globalUtilOptind]; globalUtilOptind++; break; case 'C': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-C\" should be followed by a string.\n" ); goto usage; } pComStr = argv[globalUtilOptind]; globalUtilOptind++; break; case 'W': if ( globalUtilOptind >= argc ) { fprintf( pAbc->Err, "Command line switch \"-W\" should be followed by a string.\n" ); goto usage; } pWriteStr = argv[globalUtilOptind]; globalUtilOptind++; break; case 'c': fUseCurrent ^= 1; break; default: goto usage; } } // printf( "File = %s.\n", pFileStr ); // printf( "Dir = %s.\n", pDirStr ); // printf( "Com = %s.\n", pComStr ); if ( pDirStr == NULL ) fUseCurrent = 1; if ( _getcwd( Buffer, 1000 ) == NULL ) { printf( "Cannot get the current directory.\n" ); return 0; } if ( fUseCurrent ) pFile = fopen( pFileStr, "w" ); if ( pDirStr ) { if ( _chdir(pDirStr) ) { printf( "Cannot change to directory: %s\n", pDirStr ); return 0; } } if ( !fUseCurrent ) pFile = fopen( pFileStr, "w" ); if ( pFile == NULL ) { printf( "Cannot open file %s.\n", pFileStr ); if ( pDirStr && _chdir(Buffer) ) { printf( "Cannot change to the current directory: %s\n", Buffer ); return 0; } return 0; } // find the first file in the directory if( (hFile = _findfirst( "*.*", &c_file )) == -1L ) { if ( pDirStr ) printf( "No files in the current directory.\n" ); else printf( "No files in directory: %s\n", pDirStr ); if ( pDirStr && _chdir(Buffer) ) { printf( "Cannot change to the current directory: %s\n", Buffer ); return 0; } } // get the longest file name { nFileNameMax = 0; do { // skip script and txt files nFileNameCur = strlen(c_file.name); if ( c_file.name[nFileNameCur-1] == '.' ) continue; if ( nFileNameCur > 2 && c_file.name[nFileNameCur-1] == 's' && c_file.name[nFileNameCur-2] == '.' ) continue; if ( nFileNameCur > 4 && c_file.name[nFileNameCur-1] == 't' && c_file.name[nFileNameCur-2] == 'x' && c_file.name[nFileNameCur-3] == 't' && c_file.name[nFileNameCur-4] == '.' ) continue; if ( nFileNameMax < nFileNameCur ) nFileNameMax = nFileNameCur; } while( _findnext( hFile, &c_file ) == 0 ); _findclose( hFile ); } // print the script file { if( (hFile = _findfirst( "*.*", &c_file )) == -1L ) { if ( pDirStr ) printf( "No files in the current directory.\n" ); else printf( "No files in directory: %s\n", pDirStr ); } fprintf( pFile, "# Script file produced by ABC on %s\n", Extra_TimeStamp() ); fprintf( pFile, "# Command line was: scrgen -F %s -D %s -C \"%s\"%s%s\n", pFileStr, pDirStr, pComStr, pWriteStr?" -W ":"", pWriteStr?pWriteStr:"" ); do { // skip script and txt files nFileNameCur = strlen(c_file.name); if ( c_file.name[nFileNameCur-1] == '.' ) continue; if ( nFileNameCur > 2 && c_file.name[nFileNameCur-1] == 's' && c_file.name[nFileNameCur-2] == '.' ) continue; if ( nFileNameCur > 4 && c_file.name[nFileNameCur-1] == 't' && c_file.name[nFileNameCur-2] == 'x' && c_file.name[nFileNameCur-3] == 't' && c_file.name[nFileNameCur-4] == '.' ) continue; sprintf( Line, "r %s%s%-*s ; %s", pDirStr?pDirStr:"", pDirStr?"/":"", nFileNameMax, c_file.name, pComStr ); for ( c = (int)strlen(Line)-1; c >= 0; c-- ) if ( Line[c] == '\\' ) Line[c] = '/'; fprintf( pFile, "%s", Line ); if ( pWriteStr ) { sprintf( Line, " ; w %s/%-*s", pWriteStr, nFileNameMax, c_file.name ); for ( c = (int)strlen(Line)-1; c >= 0; c-- ) if ( Line[c] == '\\' ) Line[c] = '/'; fprintf( pFile, "%s", Line ); } fprintf( pFile, "\n", Line ); } while( _findnext( hFile, &c_file ) == 0 ); _findclose( hFile ); } fclose( pFile ); if ( pDirStr && _chdir(Buffer) ) { printf( "Cannot change to the current directory: %s\n", Buffer ); return 0; } // report if ( fUseCurrent ) printf( "Script file \"%s\" was saved in the current directory.\n", pFileStr ); else printf( "Script file \"%s\" was saved in directory: %s\n", pFileStr, pDirStr ); return 0; usage: fprintf( pAbc->Err, "usage: scrgen -F -D -C -W -ch\n" ); fprintf( pAbc->Err, "\t generates script for running ABC\n" ); fprintf( pAbc->Err, "\t-F str : the name of the script file [default = \"test.s\"]\n" ); fprintf( pAbc->Err, "\t-D str : the directory to read files from [default = current]\n" ); fprintf( pAbc->Err, "\t-C str : the sequence of commands to run [default = \"ps\"]\n" ); fprintf( pAbc->Err, "\t-W str : the directory to write the resulting files [default = no writing]\n" ); fprintf( pAbc->Err, "\t-c : toggle placing file in current/target dir [default = %s]\n", fUseCurrent? "current": "target" ); fprintf( pAbc->Err, "\t-h : print the command usage\n\n"); fprintf( pAbc->Err, "\tExample : scrgen -F test1.s -D a/in -C \"ps; st; ps\" -W a/out\n" ); return 1; } #endif #ifdef WIN32 #define unlink _unlink #endif /**Function******************************************************************** Synopsis [Calls SIS internally.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist; char * pNameWin = "sis.exe"; char * pNameUnix = "sis"; char Command[1000], Buffer[100]; char * pSisName; int i; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); if ( argc == 1 ) goto usage; if ( strcmp( argv[1], "-h" ) == 0 ) goto usage; if ( strcmp( argv[1], "-?" ) == 0 ) goto usage; if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); goto usage; } if ( strcmp( argv[0], "sis" ) != 0 ) { fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); goto usage; } // get the names from the resource file if ( Cmd_FlagReadByName(pAbc, "siswin") ) pNameWin = Cmd_FlagReadByName(pAbc, "siswin"); if ( Cmd_FlagReadByName(pAbc, "sisunix") ) pNameUnix = Cmd_FlagReadByName(pAbc, "sisunix"); // check if SIS is available if ( (pFile = fopen( pNameWin, "r" )) ) pSisName = pNameWin; else if ( (pFile = fopen( pNameUnix, "r" )) ) pSisName = pNameUnix; else if ( pFile == NULL ) { fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix ); goto usage; } fclose( pFile ); if ( Abc_NtkIsMappedLogic(pNtk) ) { Abc_NtkMapToSop(pNtk); printf( "The current network is unmapped before calling SIS.\n" ); } // write out the current network if ( Abc_NtkIsLogic(pNtk) ) Abc_NtkToSop(pNtk, -1, ABC_INFINITY); pNetlist = Abc_NtkToNetlist(pNtk); if ( pNetlist == NULL ) { fprintf( pErr, "Cannot produce the intermediate network.\n" ); goto usage; } Io_WriteBlif( pNetlist, "_sis_in.blif", 1, 0, 0 ); Abc_NtkDelete( pNetlist ); // create the file for sis sprintf( Command, "%s -x -c ", pSisName ); strcat ( Command, "\"" ); strcat ( Command, "read_blif _sis_in.blif" ); strcat ( Command, "; " ); for ( i = 1; i < argc; i++ ) { sprintf( Buffer, " %s", argv[i] ); strcat( Command, Buffer ); } strcat( Command, "; " ); strcat( Command, "write_blif _sis_out.blif" ); strcat( Command, "\"" ); // call SIS if ( Util_SignalSystem( Command ) ) { fprintf( pErr, "The following command has returned non-zero exit status:\n" ); fprintf( pErr, "\"%s\"\n", Command ); unlink( "_sis_in.blif" ); goto usage; } // read in the SIS output if ( (pFile = fopen( "_sis_out.blif", "r" )) == NULL ) { fprintf( pErr, "Cannot open SIS output file \"%s\".\n", "_sis_out.blif" ); unlink( "_sis_in.blif" ); goto usage; } fclose( pFile ); // set the new network pNtkNew = Io_Read( "_sis_out.blif", IO_FILE_BLIF, 1, 0 ); // set the original spec of the new network if ( pNtk->pSpec ) { ABC_FREE( pNtkNew->pSpec ); pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); // remove temporary networks unlink( "_sis_in.blif" ); unlink( "_sis_out.blif" ); return 0; usage: fprintf( pErr, "Usage: sis [-h] \n"); fprintf( pErr, " invokes SIS command for the current ABC network\n" ); fprintf( pErr, " (the executable of SIS should be in the same directory)\n" ); fprintf( pErr, " -h : print the command usage\n" ); fprintf( pErr, " : a SIS command (or a semicolon-separated list of commands in quotes)\n" ); fprintf( pErr, " Example 1: sis eliminate 0\n" ); fprintf( pErr, " Example 2: sis \"ps; rd; fx; ps\"\n" ); fprintf( pErr, " Example 3: sis source script.rugged\n" ); return 1; // error exit } /**Function******************************************************************** Synopsis [Calls SIS internally.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist; char Command[1000], Buffer[100]; char * pNameWin = "mvsis.exe"; char * pNameUnix = "mvsis"; char * pMvsisName; int i; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); if ( argc == 1 ) goto usage; if ( strcmp( argv[1], "-h" ) == 0 ) goto usage; if ( strcmp( argv[1], "-?" ) == 0 ) goto usage; if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); goto usage; } if ( strcmp( argv[0], "mvsis" ) != 0 ) { fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); goto usage; } // get the names from the resource file if ( Cmd_FlagReadByName(pAbc, "mvsiswin") ) pNameWin = Cmd_FlagReadByName(pAbc, "mvsiswin"); if ( Cmd_FlagReadByName(pAbc, "mvsisunix") ) pNameUnix = Cmd_FlagReadByName(pAbc, "mvsisunix"); // check if MVSIS is available if ( (pFile = fopen( pNameWin, "r" )) ) pMvsisName = pNameWin; else if ( (pFile = fopen( pNameUnix, "r" )) ) pMvsisName = pNameUnix; else if ( pFile == NULL ) { fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix ); goto usage; } fclose( pFile ); if ( Abc_NtkIsMappedLogic(pNtk) ) { Abc_NtkMapToSop(pNtk); printf( "The current network is unmapped before calling MVSIS.\n" ); } // write out the current network if ( Abc_NtkIsLogic(pNtk) ) Abc_NtkToSop(pNtk, -1, ABC_INFINITY); pNetlist = Abc_NtkToNetlist(pNtk); if ( pNetlist == NULL ) { fprintf( pErr, "Cannot produce the intermediate network.\n" ); goto usage; } Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1, 0, 0 ); Abc_NtkDelete( pNetlist ); // create the file for MVSIS sprintf( Command, "%s -x -c ", pMvsisName ); strcat ( Command, "\"" ); strcat ( Command, "read_blif _mvsis_in.blif" ); strcat ( Command, "; " ); for ( i = 1; i < argc; i++ ) { sprintf( Buffer, " %s", argv[i] ); strcat( Command, Buffer ); } strcat( Command, "; " ); strcat( Command, "write_blif _mvsis_out.blif" ); strcat( Command, "\"" ); // call MVSIS if ( Util_SignalSystem( Command ) ) { fprintf( pErr, "The following command has returned non-zero exit status:\n" ); fprintf( pErr, "\"%s\"\n", Command ); unlink( "_mvsis_in.blif" ); goto usage; } // read in the MVSIS output if ( (pFile = fopen( "_mvsis_out.blif", "r" )) == NULL ) { fprintf( pErr, "Cannot open MVSIS output file \"%s\".\n", "_mvsis_out.blif" ); unlink( "_mvsis_in.blif" ); goto usage; } fclose( pFile ); // set the new network pNtkNew = Io_Read( "_mvsis_out.blif", IO_FILE_BLIF, 1, 0 ); // set the original spec of the new network if ( pNtk->pSpec ) { ABC_FREE( pNtkNew->pSpec ); pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); // remove temporary networks unlink( "_mvsis_in.blif" ); unlink( "_mvsis_out.blif" ); return 0; usage: fprintf( pErr, "Usage: mvsis [-h] \n"); fprintf( pErr, " invokes MVSIS command for the current ABC network\n" ); fprintf( pErr, " (the executable of MVSIS should be in the same directory)\n" ); fprintf( pErr, " -h : print the command usage\n" ); fprintf( pErr, " : a MVSIS command (or a semicolon-separated list of commands in quotes)\n" ); fprintf( pErr, " Example 1: mvsis fraig_sweep\n" ); fprintf( pErr, " Example 2: mvsis \"ps; fxu; ps\"\n" ); fprintf( pErr, " Example 3: mvsis source mvsis.rugged\n" ); return 1; // error exit } /**Function************************************************************* Synopsis [Computes dimentions of the graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManGnuplotShow( char * pPlotFileName ) { FILE * pFile; void * pAbc; char * pProgNameGnuplotWin = "wgnuplot.exe"; char * pProgNameGnuplotUnix = "gnuplot"; char * pProgNameGnuplot = NULL; // read in the Capo plotting output if ( (pFile = fopen( pPlotFileName, "r" )) == NULL ) { fprintf( stdout, "Cannot open the plot file \"%s\".\n\n", pPlotFileName ); return; } fclose( pFile ); pAbc = Abc_FrameGetGlobalFrame(); // get the names from the plotting software if ( Cmd_FlagReadByName((Abc_Frame_t *)pAbc, "gnuplotwin") ) pProgNameGnuplotWin = Cmd_FlagReadByName((Abc_Frame_t *)pAbc, "gnuplotwin"); if ( Cmd_FlagReadByName((Abc_Frame_t *)pAbc, "gnuplotunix") ) pProgNameGnuplotUnix = Cmd_FlagReadByName((Abc_Frame_t *)pAbc, "gnuplotunix"); // check if Gnuplot is available if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) ) pProgNameGnuplot = pProgNameGnuplotWin; else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) ) pProgNameGnuplot = pProgNameGnuplotUnix; else if ( pFile == NULL ) { fprintf( stdout, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix ); return; } fclose( pFile ); // spawn the viewer #ifdef WIN32 if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 ) { fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot ); return; } #else { char Command[1000]; sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName ); if ( system( Command ) == -1 ) { fprintf( stdout, "Cannot execute \"%s\".\n", Command ); return; } } #endif } /**Function******************************************************************** Synopsis [Calls Capo internally.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNetlist; char Command[1000], Buffer[100]; char * pProgNameCapoWin = "capo.exe"; char * pProgNameCapoUnix = "capo"; char * pProgNameGnuplotWin = "wgnuplot.exe"; char * pProgNameGnuplotUnix = "gnuplot"; char * pProgNameCapo; char * pProgNameGnuplot; char * pPlotFileName; int i; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); if ( argc > 1 ) { if ( strcmp( argv[1], "-h" ) == 0 ) goto usage; if ( strcmp( argv[1], "-?" ) == 0 ) goto usage; } if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); goto usage; } if ( strcmp( argv[0], "capo" ) != 0 ) { fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); goto usage; } // get the names from the resource file if ( Cmd_FlagReadByName(pAbc, "capowin") ) pProgNameCapoWin = Cmd_FlagReadByName(pAbc, "capowin"); if ( Cmd_FlagReadByName(pAbc, "capounix") ) pProgNameCapoUnix = Cmd_FlagReadByName(pAbc, "capounix"); // check if capo is available if ( (pFile = fopen( pProgNameCapoWin, "r" )) ) pProgNameCapo = pProgNameCapoWin; else if ( (pFile = fopen( pProgNameCapoUnix, "r" )) ) pProgNameCapo = pProgNameCapoUnix; else if ( pFile == NULL ) { fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameCapoWin, pProgNameCapoUnix ); goto usage; } fclose( pFile ); if ( Abc_NtkIsMappedLogic(pNtk) ) { Abc_NtkMapToSop(pNtk); printf( "The current network is unmapped before calling Capo.\n" ); } // write out the current network if ( Abc_NtkIsLogic(pNtk) ) Abc_NtkToSop(pNtk, -1, ABC_INFINITY); pNetlist = Abc_NtkToNetlist(pNtk); if ( pNetlist == NULL ) { fprintf( pErr, "Cannot produce the intermediate network.\n" ); goto usage; } Io_WriteBlif( pNetlist, "_capo_in.blif", 1, 0, 0 ); Abc_NtkDelete( pNetlist ); // create the file for Capo sprintf( Command, "%s -f _capo_in.blif -log out.txt ", pProgNameCapo ); pPlotFileName = NULL; for ( i = 1; i < argc; i++ ) { sprintf( Buffer, " %s", argv[i] ); strcat( Command, Buffer ); if ( !strcmp( argv[i], "-plot" ) ) pPlotFileName = argv[i+1]; } // call Capo if ( Util_SignalSystem( Command ) ) { fprintf( pErr, "The following command has returned non-zero exit status:\n" ); fprintf( pErr, "\"%s\"\n", Command ); unlink( "_capo_in.blif" ); goto usage; } // remove temporary networks unlink( "_capo_in.blif" ); if ( pPlotFileName == NULL ) return 0; // get the file name sprintf( Buffer, "%s.plt", pPlotFileName ); pPlotFileName = Buffer; // read in the Capo plotting output if ( (pFile = fopen( pPlotFileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open the plot file \"%s\".\n\n", pPlotFileName ); goto usage; } fclose( pFile ); // get the names from the plotting software if ( Cmd_FlagReadByName(pAbc, "gnuplotwin") ) pProgNameGnuplotWin = Cmd_FlagReadByName(pAbc, "gnuplotwin"); if ( Cmd_FlagReadByName(pAbc, "gnuplotunix") ) pProgNameGnuplotUnix = Cmd_FlagReadByName(pAbc, "gnuplotunix"); // check if Gnuplot is available pProgNameGnuplot = NULL; if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) ) pProgNameGnuplot = pProgNameGnuplotWin; else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) ) pProgNameGnuplot = pProgNameGnuplotUnix; else if ( pFile == NULL ) { fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix ); goto usage; } fclose( pFile ); // spawn the viewer #ifdef WIN32 if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 ) { fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot ); goto usage; } #else { sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName ); if ( Util_SignalSystem( Command ) == -1 ) { fprintf( stdout, "Cannot execute \"%s\".\n", Command ); goto usage; } } #endif // remove temporary networks // unlink( pPlotFileName ); return 0; usage: fprintf( pErr, "Usage: capo [-h] \n"); fprintf( pErr, " peforms placement of the current network using Capo\n" ); fprintf( pErr, " a Capo binary should be present in the same directory\n" ); fprintf( pErr, " (if plotting, the Gnuplot binary should also be present)\n" ); fprintf( pErr, " -h : print the command usage\n" ); fprintf( pErr, " : a Capo command\n" ); fprintf( pErr, " Example 1: capo\n" ); fprintf( pErr, " (performs placement with default options)\n" ); fprintf( pErr, " Example 2: capo -AR -WS -save\n" ); fprintf( pErr, " (specifies the aspect ratio [default = 1.0] and\n" ); fprintf( pErr, " the whitespace percentage [0%%; 100%%) [default = 15%%])\n" ); fprintf( pErr, " Example 3: capo -plot \n" ); fprintf( pErr, " (produces and visualize it using Gnuplot)\n" ); fprintf( pErr, " Example 4: capo -help\n" ); fprintf( pErr, " (prints the default usage message of the Capo binary)\n" ); fprintf( pErr, " Please refer to the Capo webpage for additional information:\n" ); fprintf( pErr, " http://vlsicad.eecs.umich.edu/BK/PDtools/\n" ); return 1; // error exit } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdCommandStarter( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ); FILE * pFile; char * pFileName; char * pCommand = NULL; int c, nCores = 3; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NCvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nCores = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCores < 0 ) goto usage; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a string (possibly in quotes).\n" ); goto usage; } pCommand = argv[globalUtilOptind]; globalUtilOptind++; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { Abc_Print( -2, "The file name should be given on the command line.\n" ); return 1; } // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( pFileName, "open_path", "rb", 0 )) == NULL ) // if ( (pFile = fopen( pFileName, "rb" )) == NULL ) { Abc_Print( -2, "Cannot open input file \"%s\". ", pFileName ); if (( pFileName = Extra_FileGetSimilarName( pFileName, ".c", ".s", ".scr", ".script", NULL ) )) Abc_Print( -2, "Did you mean \"%s\"?", pFileName ); Abc_Print( -2, "\n" ); return 1; } fclose( pFile ); // run commands Cmd_RunStarter( pFileName, pAbc->sBinary, pCommand, nCores ); return 0; usage: Abc_Print( -2, "usage: starter [-N num] [-C cmd] [-vh] \n" ); Abc_Print( -2, "\t runs command lines listed in concurrently on CPUs\n" ); Abc_Print( -2, "\t-N num : the number of concurrent jobs including the controler [default = %d]\n", nCores ); Abc_Print( -2, "\t-C cmd : (optional) ABC command line to execute on benchmarks in \n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file name with ABC command lines (or benchmark names, if is given)\n"); return 1; } /**Function******************************************************************** Synopsis [Print the version string.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandVersion( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } printf("%s\n", Abc_UtilsGetVersion(pAbc)); return 0; usage: fprintf( pAbc->Err, "usage: version [-h]\n" ); fprintf( pAbc->Err, " print the version string\n" ); fprintf( pAbc->Err, " -h : print the command usage\n"); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmd.h000066400000000000000000000067241300674244400224360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmd.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [External declarations of the command package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__cmd__cmd_h #define ABC__base__cmd__cmd_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct MvCommand Abc_Command; // one command typedef struct MvAlias Abc_Alias; // one alias //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== cmd.c ===========================================================*/ extern void Cmd_Init( Abc_Frame_t * pAbc ); extern void Cmd_End( Abc_Frame_t * pAbc ); /*=== cmdApi.c ========================================================*/ typedef int (*Cmd_CommandFuncType)(Abc_Frame_t*, int, char**); extern int Cmd_CommandIsDefined( Abc_Frame_t * pAbc, const char * sName ); extern void Cmd_CommandAdd( Abc_Frame_t * pAbc, const char * sGroup, const char * sName, Cmd_CommandFuncType pFunc, int fChanges ); extern ABC_DLL int Cmd_CommandExecute( Abc_Frame_t * pAbc, const char * sCommand ); /*=== cmdFlag.c ========================================================*/ extern char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ); extern void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, const char * key ); extern void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, const char * key, char * value ); /*=== cmdHist.c ========================================================*/ extern void Cmd_HistoryAddCommand( Abc_Frame_t * pAbc, const char * command ); extern void Cmd_HistoryRead( Abc_Frame_t * p ); extern void Cmd_HistoryWrite( Abc_Frame_t * p, int Limit ); extern void Cmd_HistoryPrint( Abc_Frame_t * p, int Limit ); /*=== cmdLoad.c ========================================================*/ extern int CmdCommandLoad( Abc_Frame_t * pAbc, int argc, char ** argv ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdAlias.c000066400000000000000000000065561300674244400234060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdAlias.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures dealing with aliases in the command package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmdAlias.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "cmdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv ) { Abc_Alias * pAlias; int fStatus, i; pAlias = ABC_ALLOC(Abc_Alias, 1); pAlias->sName = Extra_UtilStrsav(sName); pAlias->argc = argc; pAlias->argv = ABC_ALLOC(char *, pAlias->argc); for(i = 0; i < argc; i++) pAlias->argv[i] = Extra_UtilStrsav(argv[i]); fStatus = st__insert( pAbc->tAliases, pAlias->sName, (char *) pAlias ); assert(!fStatus); } /**Function******************************************************************** Synopsis [required] Description [optional] SideEffects [required] SeeAlso [optional] ******************************************************************************/ void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias ) { int i; fprintf(pAbc->Out, "%-15s", pAlias->sName); for(i = 0; i < pAlias->argc; i++) fprintf( pAbc->Out, " %s", pAlias->argv[i] ); fprintf( pAbc->Out, "\n" ); } /**Function******************************************************************** Synopsis [required] Description [optional] SideEffects [required] SeeAlso [optional] ******************************************************************************/ char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand ) { Abc_Alias * pAlias; char * value; if (! st__lookup( pAbc->tAliases, sCommand, &value)) return sCommand; pAlias = (Abc_Alias *) value; return pAlias->argv[0]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void CmdCommandAliasFree( Abc_Alias * pAlias ) { CmdFreeArgv( pAlias->argc, pAlias->argv ); ABC_FREE(pAlias->sName); ABC_FREE(pAlias); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdApi.c000066400000000000000000000071021300674244400230520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdApi.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [External procedures of the command package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmdApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "cmdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cmd_CommandIsDefined( Abc_Frame_t * pAbc, const char * sName ) { return st__is_member( pAbc->tCommands, sName ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cmd_CommandAdd( Abc_Frame_t * pAbc, const char * sGroup, const char * sName, Cmd_CommandFuncType pFunc, int fChanges ) { const char * key; char * value; Abc_Command * pCommand; int fStatus; key = sName; if ( st__delete( pAbc->tCommands, &key, &value ) ) { // delete existing definition for this command fprintf( pAbc->Err, "Cmd warning: redefining '%s'\n", sName ); CmdCommandFree( (Abc_Command *)value ); } // create the new command pCommand = ABC_ALLOC( Abc_Command, 1 ); pCommand->sName = Extra_UtilStrsav( sName ); pCommand->sGroup = Extra_UtilStrsav( sGroup ); pCommand->pFunc = pFunc; pCommand->fChange = fChanges; fStatus = st__insert( pAbc->tCommands, pCommand->sName, (char *)pCommand ); assert( !fStatus ); // the command should not be in the table } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cmd_CommandExecute( Abc_Frame_t * pAbc, const char * sCommand ) { int fStatus = 0, argc, loop; const char * sCommandNext; char **argv; if ( !pAbc->fAutoexac && !pAbc->fSource ) Cmd_HistoryAddCommand(pAbc, sCommand); sCommandNext = sCommand; do { sCommandNext = CmdSplitLine( pAbc, sCommandNext, &argc, &argv ); loop = 0; fStatus = CmdApplyAlias( pAbc, &argc, &argv, &loop ); if ( fStatus == 0 ) fStatus = CmdCommandDispatch( pAbc, &argc, &argv ); CmdFreeArgv( argc, argv ); } while ( fStatus == 0 && *sCommandNext != '\0' ); return fStatus; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdFlag.c000066400000000000000000000062461300674244400232220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdFlag.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures working with flags.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmdFlag.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [Looks up value of flag in table of named values.] Description [The command parser maintains a table of named values. These are manipulated using the 'set' and 'unset' commands. The value of the named flag is returned, or NULL is returned if the flag has not been set.] SideEffects [] ******************************************************************************/ char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ) { char * value; if ( st__lookup(pAbc->tFlags, flag, &value) ) return value; return NULL; } /**Function******************************************************************** Synopsis [Updates a set value by calling instead of set command.] Description [Updates a set value by calling instead of set command.] SideEffects [] ******************************************************************************/ void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, const char * key, char * value ) { char * oldValue, * newValue; if ( !key ) return; if ( value ) newValue = Extra_UtilStrsav(value); else newValue = Extra_UtilStrsav(""); // newValue = NULL; if ( st__delete(pAbc->tFlags, &key, &oldValue) ) ABC_FREE(oldValue); st__insert( pAbc->tFlags, key, newValue ); } /**Function******************************************************************** Synopsis [Deletes a set value by calling instead of unset command.] Description [Deletes a set value by calling instead of unset command.] SideEffects [] ******************************************************************************/ void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, const char * key ) { char *value; if ( !key ) return; if ( st__delete( pAbc->tFlags, &key, &value ) ) { ABC_FREE(key); ABC_FREE(value); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdHist.c000066400000000000000000000123361300674244400232550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdHist.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures working with history.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmdHist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "cmd.h" #include "cmdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cmd_HistoryAddCommand( Abc_Frame_t * p, const char * command ) { int nLastLooked = 10; // do not add history if the same entry appears among the last entries int nLastSaved = 1000; // when saving a file, save no more than this number of last entries char Buffer[ABC_MAX_STR]; int Len; if ( p->fBatchMode ) return; Len = strlen(command); strcpy( Buffer, command ); if ( Buffer[Len-1] == '\n' ) Buffer[Len-1] = 0; if ( strlen(Buffer) > 3 && strncmp(Buffer,"set",3) && strncmp(Buffer,"unset",5) && strncmp(Buffer,"time",4) && strncmp(Buffer,"quit",4) && strncmp(Buffer,"alias",5) && // strncmp(Buffer,"source",6) && strncmp(Buffer,"history",7) && strncmp(Buffer,"hi ", 3) && strcmp(Buffer,"hi") && Buffer[strlen(Buffer)-1] != '?' ) { char * pStr = NULL; int i, Start = Abc_MaxInt( 0, Vec_PtrSize(p->aHistory) - nLastLooked ); // do not enter if the same command appears among nLastLooked commands Vec_PtrForEachEntryStart( char *, p->aHistory, pStr, i, Start ) if ( !strcmp(pStr, Buffer) ) break; if ( i == Vec_PtrSize(p->aHistory) ) { // add new entry Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) ); Cmd_HistoryWrite( p, nLastSaved ); } else { // put at the end Vec_PtrRemove( p->aHistory, pStr ); Vec_PtrPush( p->aHistory, pStr ); } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cmd_HistoryRead( Abc_Frame_t * p ) { #if defined(WIN32) char Buffer[ABC_MAX_STR]; FILE * pFile; assert( Vec_PtrSize(p->aHistory) == 0 ); pFile = fopen( "abc.history", "rb" ); if ( pFile == NULL ) return; while ( fgets( Buffer, ABC_MAX_STR, pFile ) != NULL ) { int Len = strlen(Buffer); if ( Buffer[Len-1] == '\n' ) Buffer[Len-1] = 0; Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) ); } fclose( pFile ); #endif } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cmd_HistoryWrite( Abc_Frame_t * p, int Limit ) { #if defined(WIN32) FILE * pFile; char * pStr; int i; pFile = fopen( "abc.history", "wb" ); if ( pFile == NULL ) { Abc_Print( 0, "Cannot open file \"abc.history\" for writing.\n" ); return; } Limit = Abc_MaxInt( 0, Vec_PtrSize(p->aHistory)-Limit ); Vec_PtrForEachEntryStart( char *, p->aHistory, pStr, i, Limit ) fprintf( pFile, "%s\n", pStr ); fclose( pFile ); #endif } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cmd_HistoryPrint( Abc_Frame_t * p, int Limit ) { #if defined(WIN32) char * pStr; int i; Limit = Abc_MaxInt( 0, Vec_PtrSize(p->aHistory)-Limit ); printf( "================== Command history ==================\n" ); Vec_PtrForEachEntryStart( char *, p->aHistory, pStr, i, Limit ) printf( "%s\n", pStr ); printf( "=====================================================\n" ); #endif } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdInt.h000066400000000000000000000073311300674244400231040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Internal declarations of the command package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmdInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__cmd__cmdInt_h #define ABC__base__cmd__cmdInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/main/mainInt.h" #include "cmd.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// struct MvCommand { char * sName; // the command name char * sGroup; // the group name Cmd_CommandFuncType pFunc; // the function to execute the command int fChange; // set to 1 to mark that the network is changed }; struct MvAlias { char * sName; // the alias name int argc; // the number of alias parts char ** argv; // the alias parts }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== cmdAlias.c =============-========================================*/ extern void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv ); extern void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias ); extern char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand ); extern void CmdCommandAliasFree( Abc_Alias * p ); /*=== cmdUtils.c =======================================================*/ extern int CmdCommandDispatch( Abc_Frame_t * pAbc, int * argc, char *** argv ); extern const char * CmdSplitLine( Abc_Frame_t * pAbc, const char * sCommand, int * argc, char *** argv ); extern int CmdApplyAlias( Abc_Frame_t * pAbc, int * argc, char *** argv, int * loop ); extern char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char * line, int * changed ); extern FILE * CmdFileOpen( Abc_Frame_t * pAbc, char * sFileName, char * sMode, char ** pFileNameReal, int silent ); extern void CmdFreeArgv( int argc, char ** argv ); extern char ** CmdAddToArgv( int argc, char ** argv ); extern void CmdCommandFree( Abc_Command * pCommand ); extern void CmdCommandPrint( Abc_Frame_t * pAbc, int fPrintAll, int fDetails ); extern void CmdPrintTable( st__table * tTable, int fAliases ); //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdLoad.c000066400000000000000000000135371300674244400232310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdApi.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [External procedures of the command package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmdApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "cmd.h" #include "cmdInt.h" #include "misc/util/utilSignal.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int CmdCommandLoad( Abc_Frame_t * pAbc, int argc, char ** argv ) { Vec_Str_t * vCommand; FILE * pFile; int i; vCommand = Vec_StrAlloc( 100 ); Vec_StrAppend( vCommand, "abccmd_" ); Vec_StrAppend( vCommand, argv[0] ); Vec_StrAppend( vCommand, ".exe" ); Vec_StrPush( vCommand, 0 ); // check if there is the binary if ( (pFile = fopen( Vec_StrArray(vCommand), "r" )) == NULL ) { Vec_StrFree( vCommand ); Abc_Print( -1, "Cannot run the binary \"%s\".\n\n", Vec_StrArray(vCommand) ); return 1; } fclose( pFile ); Vec_StrPop( vCommand ); // add other arguments for ( i = 1; i < argc; i++ ) { Vec_StrAppend( vCommand, " " ); Vec_StrAppend( vCommand, argv[i] ); } Vec_StrPush( vCommand, 0 ); // run the command line if ( Util_SignalSystem( Vec_StrArray(vCommand) ) ) { Vec_StrFree( vCommand ); Abc_Print( -1, "The following command has returned non-zero exit status:\n" ); Abc_Print( -1, "\"%s\"\n", Vec_StrArray(vCommand) ); return 1; } Vec_StrFree( vCommand ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #if defined(WIN32) && !defined(__cplusplus) #include // these structures are defined in but are for some reason invisible typedef unsigned long _fsize_t; // Could be 64 bits for Win32 struct _finddata_t { unsigned attrib; time_t time_create; // -1 for FAT file systems time_t time_access; // -1 for FAT file systems time_t time_write; _fsize_t size; char name[260]; }; extern long _findfirst( char *filespec, struct _finddata_t *fileinfo ); extern int _findnext( long handle, struct _finddata_t *fileinfo ); extern int _findclose( long handle ); //extern char * _getcwd( char * buffer, int maxlen ); //extern int _chdir( const char *dirname ); /**Function************************************************************* Synopsis [Collect file names ending with .exe] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * CmdCollectFileNames() { Vec_Ptr_t * vFileNames; struct _finddata_t c_file; long hFile; if( (hFile = _findfirst( "*.exe", &c_file )) == -1L ) { // Abc_Print( 0, "No files with extention \"%s\" in the current directory.\n", "exe" ); return NULL; } vFileNames = Vec_PtrAlloc( 100 ); do { Vec_PtrPush( vFileNames, Extra_UtilStrsav( c_file.name ) ); } while( _findnext( hFile, &c_file ) == 0 ); _findclose( hFile ); return vFileNames; } #else /**Function************************************************************* Synopsis [Collect file names ending with .exe] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * CmdCollectFileNames() { return NULL; } #endif /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Load_Init( Abc_Frame_t * pAbc ) { Vec_Ptr_t * vFileNames; char * pName, * pStop; int i; vFileNames = CmdCollectFileNames(); if ( vFileNames == NULL ) return; Vec_PtrForEachEntry( char *, vFileNames, pName, i ) { if ( strncmp( pName, "abccmd_", 7 ) ) continue; // get the command name // pName[6] = '!'; pStop = strstr( pName + 7, "." ); if ( pStop ) *pStop = 0; // add the command Cmd_CommandAdd( pAbc, "ZZ", pName+7, CmdCommandLoad, 0 ); // printf( "Loaded command \"%s\"\n", pName+7 ); } Vec_PtrFreeFree( vFileNames ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Load_End( Abc_Frame_t * pAbc ) { } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdPlugin.c000066400000000000000000000525411300674244400236060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdPlugin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Integrating external binary.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 29, 2010.] Revision [$Id: cmdPlugin.c,v 1.00 2010/09/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifdef WIN32 #include #include #else #include #endif #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "cmd.h" #include "cmdInt.h" #include "misc/util/utilSignal.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* -------- Original Message -------- Subject: ABC/ZZ integration Date: Wed, 29 Sep 2010 00:34:32 -0700 From: Niklas Een To: Alan Mishchenko Hi Alan, Since the interface is file-based, it is important that we generate good, unique filenames (we may run multiple instances of ABC in the same directory), so I have attached some portable code for doing that (tmpFile.c). You can integrate it appropriately. This is how my interface is meant to work: (1) As part of your call to Bip, give it first argument "-abc". This will alter Bip's behavior slightly. (2) To list the commands, call 'bip -list-commands'. My commands begin with a comma (so that's my prefix). (3) All commands expect an input file and an output file. The input file should be in AIGER format. The output will be a text file. Example: bip -input=tmp.aig -output=tmp.out ,pdr -check -prop=5 So you just auto-generate the two temporary files (output file is closed and left empty) and stitch the ABC command line at the end. All you need to check for is if the ABC line begins with a comma. (4) The result written to the output file will contain a number of object. Each object is on a separate line of the form: : That is: name, colon, space, data, newline. If you see a name you don't recognize, just skip that line (so you will ignore future extensions by me). I currently define the following objects: result: counter-example: proof-invariant: bug-free-depth: abstraction: "result:" is one of "proved", "failed", "undetermined" (=reached resource limit), "error" (only used by the abstraction command, and only if resource limit was so tight that the abstraction was still empty -- no abstraction is returned in this special case). "counter-example:" -- same format as before "proof-invariant:" contains an text-encoded single-output AIG. If you want you can parse it and validate the invariant. "bug-free-depth:" the depth up to which the procedure has checked for counter-example. Starts at -1 (not even the initial states have been verified). "abstraction:" -- same format as before (5) I propose that you add a command "load_plugin ". That way Bob can put Bip where ever he likes and just modify his abc_rc file. The intention is that ABC can read this file and act on it without knowing what particular command was used. If there is an abstraction, you will always apply it. If there is a "bug-free-depth" you will store that data somewhere so that Bob can query it through the Python interface, and so on. If we need different actions for different command, then we add a new object for the new action. // N. */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_GetBinaryName( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pTemp; int i; Vec_PtrForEachEntry( char *, pAbc->vPlugInComBinPairs, pTemp, i ) { i++; if ( strcmp( pTemp, argv[0] ) == 0 ) return (char *)Vec_PtrEntry( pAbc->vPlugInComBinPairs, i ); } assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [Read flop map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Abc_ManReadFile( char * pFileName ) { FILE * pFile; Vec_Str_t * vStr; int c; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return NULL; } vStr = Vec_StrAlloc( 100 ); while ( (c = fgetc(pFile)) != EOF ) Vec_StrPush( vStr, (char)c ); Vec_StrPush( vStr, '\0' ); fclose( pFile ); return vStr; } /**Function************************************************************* Synopsis [Read flop map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_ManReadBinary( char * pFileName, char * pToken ) { Vec_Int_t * vMap = NULL; Vec_Str_t * vStr; char * pStr; int i, Length; vStr = Abc_ManReadFile( pFileName ); if ( vStr == NULL ) return NULL; pStr = Vec_StrArray( vStr ); pStr = strstr( pStr, pToken ); if ( pStr != NULL ) { pStr += strlen( pToken ); vMap = Vec_IntAlloc( 100 ); Length = strlen( pStr ); for ( i = 0; i < Length; i++ ) { if ( pStr[i] == '0' || pStr[i] == '?' ) Vec_IntPush( vMap, 0 ); else if ( pStr[i] == '1' ) Vec_IntPush( vMap, 1 ); if ( ('a' <= pStr[i] && pStr[i] <= 'z') || ('A' <= pStr[i] && pStr[i] <= 'Z') ) break; } } Vec_StrFree( vStr ); return vMap; } /**Function************************************************************* Synopsis [Read flop map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ManReadInteger( char * pFileName, char * pToken ) { int Result = -1; Vec_Str_t * vStr; char * pStr; vStr = Abc_ManReadFile( pFileName ); if ( vStr == NULL ) return -1; pStr = Vec_StrArray( vStr ); pStr = strstr( pStr, pToken ); if ( pStr != NULL ) Result = atoi( pStr + strlen(pToken) ); Vec_StrFree( vStr ); return Result; } /**Function************************************************************* Synopsis [Read flop map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ManReadStatus( char * pFileName, char * pToken ) { int Result = -1; Vec_Str_t * vStr; char * pStr; vStr = Abc_ManReadFile( pFileName ); if ( vStr == NULL ) return -1; pStr = Vec_StrArray( vStr ); pStr = strstr( pStr, pToken ); if ( pStr != NULL ) { if ( strncmp(pStr+8, "proved", 6) == 0 ) Result = 1; else if ( strncmp(pStr+8, "failed", 6) == 0 ) Result = 0; } Vec_StrFree( vStr ); return Result; } /**Function************************************************************* Synopsis [Work-around to insert 0s for PIs without fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_ManExpandCex( Gia_Man_t * pGia, Vec_Int_t * vCex ) { Vec_Int_t * vCexNew; Gia_Obj_t * pObj; int i, k; // start with register outputs vCexNew = Vec_IntAlloc( Vec_IntSize(vCex) ); Gia_ManForEachRo( pGia, pObj, i ) Vec_IntPush( vCexNew, 0 ); ABC_FREE( pGia->pRefs ); Gia_ManCreateRefs( pGia ); k = Gia_ManRegNum( pGia ); while ( 1 ) { Gia_ManForEachPi( pGia, pObj, i ) { if ( Gia_ObjRefNum(pGia, pObj) == 0 ) Vec_IntPush( vCexNew, 0 ); else { if ( k == Vec_IntSize(vCex) ) break; Vec_IntPush( vCexNew, Vec_IntEntry(vCex, k++) ); } } if ( k == Vec_IntSize(vCex) ) break; } return vCexNew; } /**Function************************************************************* Synopsis [Procedure to convert the AIG from text into binary form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static unsigned textToBin(char* text, unsigned long text_sz) { char* dst = text; const char* src = text; unsigned sz, i; sscanf(src, "%u ", &sz); while(*src++ != ' '); for ( i = 0; i < sz; i += 3 ) { dst[0] = (char)( (unsigned)src[0] - '0') | (((unsigned)src[1] - '0') << 6); dst[1] = (char)(((unsigned)src[1] - '0') >> 2) | (((unsigned)src[2] - '0') << 4); dst[2] = (char)(((unsigned)src[2] - '0') >> 4) | (((unsigned)src[3] - '0') << 2); src += 4; dst += 3; } return sz; } /**Function************************************************************* Synopsis [Derives AIG from the text string in the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_ManReadAig( char * pFileName, char * pToken ) { Gia_Man_t * pGia = NULL; unsigned nBinaryPart; Vec_Str_t * vStr; char * pStr, * pEnd; vStr = Abc_ManReadFile( pFileName ); if ( vStr == NULL ) return NULL; pStr = Vec_StrArray( vStr ); pStr = strstr( pStr, pToken ); if ( pStr != NULL ) { // skip token pStr += strlen(pToken); // skip spaces while ( *pStr == ' ' ) pStr++; // set the end at newline for ( pEnd = pStr; *pEnd; pEnd++ ) if ( *pEnd == '\r' || *pEnd == '\n' ) { *pEnd = 0; break; } // convert into binary AIGER nBinaryPart = textToBin( pStr, strlen(pStr) ); // dump it into file if ( 0 ) { FILE * pFile = fopen( "test.aig", "wb" ); fwrite( pStr, 1, nBinaryPart, pFile ); fclose( pFile ); } // derive AIG pGia = Gia_AigerReadFromMemory( pStr, nBinaryPart, 0, 0, 0 ); } Vec_StrFree( vStr ); return pGia; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cmd_CommandAbcPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileIn, * pFileOut; Vec_Str_t * vCommand; Vec_Int_t * vCex; FILE * pFile; Gia_Man_t * pGia; int i, fd; abctime clk; int fLeaveFiles; /* Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); if ( pNtk == NULL ) { Abc_Print( -1, "Current network does not exist\n" ); return 1; } if ( !Abc_NtkIsStrash( pNtk) ) { Abc_Print( -1, "The current network is not an AIG. Cannot continue.\n" ); return 1; } */ if ( pAbc->pGia == NULL ) { if (argc == 2 && strcmp(argv[1], "-h") == 0) { // Run command to produce help string: vCommand = Vec_StrAlloc( 100 ); Vec_StrAppend( vCommand, Abc_GetBinaryName( pAbc, argc, argv ) ); Vec_StrAppend( vCommand, " -abc " ); Vec_StrAppend( vCommand, argv[0] ); Vec_StrAppend( vCommand, " -h" ); Vec_StrPush( vCommand, 0 ); Util_SignalSystem( Vec_StrArray(vCommand) ); Vec_StrFree( vCommand ); } else { Abc_Print( -1, "Current AIG does not exist (try command &ps).\n" ); } return 1; } // create temp file fd = Util_SignalTmpFile( "__abctmp_", ".aig", &pFileIn ); if ( fd == -1 ) { Abc_Print( -1, "Cannot create a temporary file.\n" ); return 1; } #ifdef WIN32 _close( fd ); #else close( fd ); #endif // create temp file fd = Util_SignalTmpFile( "__abctmp_", ".out", &pFileOut ); if ( fd == -1 ) { ABC_FREE( pFileIn ); Abc_Print( -1, "Cannot create a temporary file.\n" ); return 1; } #ifdef WIN32 _close( fd ); #else close( fd ); #endif // write current network into a file /* { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Aig_Man_t * pAig; pAig = Abc_NtkToDar( pNtk, 0, 1 ); Ioa_WriteAiger( pAig, pFileIn, 0, 0 ); Aig_ManStop( pAig ); } */ // check what to do with the files fLeaveFiles = 0; if ( strcmp( argv[argc-1], "!" ) == 0 ) { Abc_Print( 0, "Input file \"%s\" and output file \"%s\" are not deleted.\n", pFileIn, pFileOut ); fLeaveFiles = 1; argc--; } // create input file Gia_AigerWrite( pAbc->pGia, pFileIn, 0, 0 ); // create command line vCommand = Vec_StrAlloc( 100 ); Vec_StrAppend( vCommand, Abc_GetBinaryName( pAbc, argc, argv ) ); // add input/output file Vec_StrAppend( vCommand, " -abc" ); // Vec_StrAppend( vCommand, " -input=C:/_projects/abc/_TEST/hwmcc/139442p0.aig" ); Vec_StrAppend( vCommand, " -input=" ); Vec_StrAppend( vCommand, pFileIn ); Vec_StrAppend( vCommand, " -output=" ); Vec_StrAppend( vCommand, pFileOut ); // add other arguments for ( i = 0; i < argc; i++ ) { Vec_StrAppend( vCommand, " " ); Vec_StrAppend( vCommand, argv[i] ); } Vec_StrPush( vCommand, 0 ); // run the command line //printf( "Running command line: %s\n", Vec_StrArray(vCommand) ); clk = Abc_Clock(); if ( Util_SignalSystem( Vec_StrArray(vCommand) ) ) { Abc_Print( -1, "The following command has returned non-zero exit status:\n" ); Abc_Print( -1, "\"%s\"\n", Vec_StrArray(vCommand) ); return 1; } clk = Abc_Clock() - clk; Vec_StrFree( vCommand ); // check if the output file exists if ( (pFile = fopen( pFileOut, "r" )) == NULL ) { Abc_Print( -1, "There is no output file \"%s\".\n", pFileOut ); return 1; } fclose( pFile ); // process the output if ( Extra_FileSize(pFileOut) > 0 ) { // get status pAbc->Status = Abc_ManReadStatus( pFileOut, "result:" ); // get bug-free depth pAbc->nFrames = Abc_ManReadInteger( pFileOut, "bug-free-depth:" ); // get abstraction pAbc->pGia->vFlopClasses = Abc_ManReadBinary( pFileOut, "abstraction:" ); // get counter-example vCex = Abc_ManReadBinary( pFileOut, "counter-example:" ); if ( vCex ) { int nFrames, nRemain; nFrames = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) / Gia_ManPiNum(pAbc->pGia); nRemain = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) % Gia_ManPiNum(pAbc->pGia); if ( nRemain != 0 ) { Vec_Int_t * vTemp; Abc_Print( 1, "Adjusting counter-example by adding zeros for PIs without fanout.\n" ); // expand the counter-example to include PIs without fanout vCex = Abc_ManExpandCex( pAbc->pGia, vTemp = vCex ); Vec_IntFree( vTemp ); } nFrames = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) / Gia_ManPiNum(pAbc->pGia); nRemain = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) % Gia_ManPiNum(pAbc->pGia); if ( nRemain != 0 ) Abc_Print( 1, "Counter example has a wrong length.\n" ); else { Abc_Print( 1, "Problem is satisfiable. Found counter-example in frame %d. ", nFrames-1 ); Abc_PrintTime( 1, "Time", clk ); ABC_FREE( pAbc->pCex ); pAbc->pCex = Abc_CexCreate( Gia_ManRegNum(pAbc->pGia), Gia_ManPiNum(pAbc->pGia), Vec_IntArray(vCex), nFrames-1, 0, 0 ); // Abc_CexPrint( pAbc->pCex ); // if ( !Gia_ManVerifyCex( pAbc->pGia, pAbc->pCex, 0 ) ) // Abc_Print( 1, "Generated counter-example is INVALID.\n" ); // remporary work-around to detect the output number - October 18, 2010 pAbc->pCex->iPo = Gia_ManFindFailedPoCex( pAbc->pGia, pAbc->pCex, 0 ); if ( pAbc->pCex->iPo == -1 ) { Abc_Print( 1, "Generated counter-example is INVALID.\n" ); ABC_FREE( pAbc->pCex ); } else { Abc_Print( 1, "Returned counter-example successfully verified in ABC.\n" ); } } Vec_IntFreeP( &vCex ); } // get AIG if present pGia = Abc_ManReadAig( pFileOut, "aig:" ); if ( pGia != NULL ) { Gia_ManStopP( &pAbc->pGia ); pAbc->pGia = pGia; } } // clean up Util_SignalTmpFileRemove( pFileIn, fLeaveFiles ); Util_SignalTmpFileRemove( pFileOut, fLeaveFiles ); ABC_FREE( pFileIn ); ABC_FREE( pFileOut ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cmd_CommandAbcLoadPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv ) { int fPath, fVerbose; int fd = -1, RetValue = -1, c; FILE * pFile = NULL; char * pStrDirBin = NULL, * pStrSection = NULL; Vec_Str_t * sCommandLine = NULL; char * pTempFile = NULL; char pBuffer[1000]; // set defaults fPath = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vph" ) ) != EOF ) { switch ( c ) { case 'p': fPath ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } if ( argc != globalUtilOptind + 2 ) goto usage; pStrDirBin = argv[argc-2]; pStrSection = argv[argc-1]; // check if the file exists if ( !fPath ) { FILE* pFile = fopen( pStrDirBin, "r" ); if ( !pFile ) { Abc_Print( ABC_ERROR, "Cannot run the binary \"%s\". File does not exist.\n", pStrDirBin ); goto cleanup; } fclose( pFile ); } // create temp file fd = Util_SignalTmpFile( "__abctmp_", ".txt", &pTempFile ); if ( fd == -1 ) { Abc_Print( ABC_ERROR, "Cannot create a temporary file.\n" ); goto cleanup; } #ifdef WIN32 _close( fd ); #else close( fd ); #endif // get command list sCommandLine = Vec_StrAlloc(1000); Vec_StrPrintF(sCommandLine, "%s -abc -list-commands > %s", pStrDirBin, pTempFile ); Vec_StrPush(sCommandLine, '\0'); if(fVerbose) { Abc_Print(ABC_VERBOSE, "Running command %s\n", Vec_StrArray(sCommandLine)); } RetValue = Util_SignalSystem( Vec_StrArray(sCommandLine) ); if ( RetValue != 0 ) { Abc_Print( ABC_ERROR, "Command \"%s\" failed.\n", Vec_StrArray(sCommandLine) ); goto cleanup; } // create commands pFile = fopen( pTempFile, "r" ); if ( pFile == NULL ) { Abc_Print( -1, "Cannot open file with the list of commands.\n" ); RetValue = -1; goto cleanup; } while ( fgets( pBuffer, 1000, pFile ) != NULL ) { if ( pBuffer[strlen(pBuffer)-1] == '\n' ) pBuffer[strlen(pBuffer)-1] = 0; Cmd_CommandAdd( pAbc, pStrSection, pBuffer, Cmd_CommandAbcPlugIn, 1 ); Vec_PtrPush( pAbc->vPlugInComBinPairs, Extra_UtilStrsav(pBuffer) ); Vec_PtrPush( pAbc->vPlugInComBinPairs, Extra_UtilStrsav(pStrDirBin) ); if ( fVerbose ) { Abc_Print(ABC_VERBOSE, "Creating command %s with binary %s\n", pBuffer, pStrDirBin); } } cleanup: if( pFile ) fclose( pFile ); if( pTempFile ) Util_SignalTmpFileRemove( pTempFile, 0 ); Vec_StrFreeP(&sCommandLine); ABC_FREE( pTempFile ); return RetValue; usage: Abc_Print( -2, "usage: load_plugin [-pvh] \n" ); Abc_Print( -2, "\t loads external binary as a plugin\n" ); Abc_Print( -2, "\t-p : toggle searching the command in PATH [default = %s].\n", fPath? "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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdStarter.c000066400000000000000000000200141300674244400237620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdStarter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Command to start many instances of ABC in parallel.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmdStarter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/util/abc_global.h" #include "misc/extra/extra.h" #ifdef ABC_USE_PTHREADS #ifdef _WIN32 #include "../lib/pthread.h" #else #include #include #endif #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifndef ABC_USE_PTHREADS void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) {} #else // pthreads are used // the number of concurrently running threads static volatile int nThreadsRunning = 0; // mutex to control access to the number of threads pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedures executes one call to system().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_RunThread( void * pCommand ) { int status; // perform the call if ( system( (char *)pCommand ) ) { fprintf( stderr, "The following command has returned non-zero exit status:\n" ); fprintf( stderr, "\"%s\"\n\n", (char *)pCommand ); fflush( stdout ); } free( pCommand ); // decrement the number of threads runining status = pthread_mutex_lock(&mutex); assert(status == 0); nThreadsRunning--; status = pthread_mutex_unlock(&mutex); assert(status == 0); // quit this thread //printf("...Finishing %s\n", (char *)Command); pthread_exit( NULL ); assert(0); return NULL; } /**Function************************************************************* Synopsis [Takes file with commands to be executed and the number of CPUs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) { FILE * pFile, * pFileTemp; pthread_t * pThreadIds; char * BufferCopy, * Buffer; int nLines, LineMax, Line, Len; int i, c, status, Counter; abctime clk = Abc_Clock(); // check the number of cores if ( nCores < 2 ) { fprintf( stdout, "The number of cores (%d) should be more than 1.\n", nCores ); return; } // open the file and make sure it is available pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { fprintf( stdout, "Input file \"%s\" cannot be opened.\n", pFileName ); return; } // count the number of lines and the longest line nLines = LineMax = Line = 0; while ( (c = fgetc(pFile)) != EOF ) { Line++; if ( c != '\n' ) continue; nLines++; LineMax = Abc_MaxInt( LineMax, Line ); Line = 0; } nLines += 10; LineMax += LineMax + 100; LineMax += pBinary ? strlen(pBinary) : 0; LineMax += pCommand ? strlen(pCommand) : 0; // allocate storage Buffer = ABC_ALLOC( char, LineMax ); pThreadIds = ABC_ALLOC( pthread_t, nLines ); // check if all files can be opened if ( pCommand != NULL ) { // read file names rewind( pFile ); for ( i = 0; fgets( Buffer, LineMax, pFile ) != NULL; i++ ) { // remove trailing spaces for ( Len = strlen(Buffer) - 1; Len >= 0; Len-- ) if ( Buffer[Len] == '\n' || Buffer[Len] == '\r' || Buffer[Len] == '\t' || Buffer[Len] == ' ' ) Buffer[Len] = 0; else break; // get command from file if ( Buffer[0] == 0 || Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#' ) continue; // try to open the file pFileTemp = fopen( Buffer, "rb" ); if ( pFileTemp == NULL ) { fprintf( stdout, "Starter cannot open file \"%s\".\n", Buffer ); fflush( stdout ); ABC_FREE( pThreadIds ); ABC_FREE( Buffer ); fclose( pFile ); return; } } } // read commands and execute at most of them at a time rewind( pFile ); for ( i = 0; fgets( Buffer, LineMax, pFile ) != NULL; i++ ) { // remove trailing spaces for ( Len = strlen(Buffer) - 1; Len >= 0; Len-- ) if ( Buffer[Len] == '\n' || Buffer[Len] == '\r' || Buffer[Len] == '\t' || Buffer[Len] == ' ' ) Buffer[Len] = 0; else break; // get command from file if ( Buffer[0] == 0 || Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#' ) continue; // create command if ( pCommand != NULL ) { BufferCopy = ABC_ALLOC( char, LineMax ); sprintf( BufferCopy, "%s -c \"%s; %s\" > %s", pBinary, Buffer, pCommand, Extra_FileNameGenericAppend(Buffer, ".txt") ); } else BufferCopy = Abc_UtilStrsav( Buffer ); fprintf( stdout, "Calling: %s\n", (char *)BufferCopy ); fflush( stdout ); // wait till there is an empty thread while ( 1 ) { status = pthread_mutex_lock(&mutex); assert(status == 0); Counter = nThreadsRunning; status = pthread_mutex_unlock(&mutex); assert(status == 0); if ( Counter < nCores - 1 ) break; // Sleep( 100 ); } // increament the number of threads running status = pthread_mutex_lock(&mutex); assert(status == 0); nThreadsRunning++; status = pthread_mutex_unlock(&mutex); assert(status == 0); // create thread to execute this command status = pthread_create( &pThreadIds[i], NULL, Abc_RunThread, (void *)BufferCopy ); assert(status == 0); assert( i < nLines ); } ABC_FREE( pThreadIds ); ABC_FREE( Buffer ); fclose( pFile ); // wait for all the threads to finish while ( 1 ) { status = pthread_mutex_lock(&mutex); assert(status == 0); Counter = nThreadsRunning; status = pthread_mutex_unlock(&mutex); assert(status == 0); if ( Counter == 0 ) break; } // cleanup // status = pthread_mutex_destroy(&mutex); assert(status == 0); // mutex = PTHREAD_MUTEX_INITIALIZER; fprintf( stdout, "Finished processing commands in file \"%s\". ", pFileName ); Abc_PrintTime( 1, "Total wall time", Abc_Clock() - clk ); fflush( stdout ); } #endif // pthreads are used //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/cmdUtils.c000066400000000000000000000532351300674244400234510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cmdUtils.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Various utilities of the command package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cmdUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "cmdInt.h" #include ABC_NAMESPACE_IMPL_START // proper declaration of isspace //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int cmdCheckShellEscape( Abc_Frame_t * pAbc, int argc, char ** argv) { int RetValue; if (argv[0][0] == '!') { const int size = 4096; int i; char * buffer = ABC_ALLOC(char, 10000); strncpy (buffer, &argv[0][1], size); for (i = 1; i < argc; ++i) { strncat (buffer, " ", size); strncat (buffer, argv[i], size); } if (buffer[0] == 0) strncpy (buffer, "/bin/sh", size); RetValue = system (buffer); ABC_FREE( buffer ); // NOTE: Since we reconstruct the cmdline by concatenating // the parts, we lose information. So a command like // `!ls "file name"` will be sent to the system as // `ls file name` which is a BUG return 1; } else { return 0; } } /**Function************************************************************* Synopsis [Executes one command.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdCommandDispatch( Abc_Frame_t * pAbc, int * pargc, char *** pargv ) { int argc = *pargc; char ** argv = *pargv; char ** argv2; Abc_Ntk_t * pNetCopy; int (*pFunc) ( Abc_Frame_t *, int, char ** ); Abc_Command * pCommand; char * value; int fError; double clk; if ( argc == 0 ) return 0; if ( cmdCheckShellEscape( pAbc, argc, argv ) == 1 ) return 0; // get the command if ( ! st__lookup( pAbc->tCommands, argv[0], (char **)&pCommand ) ) { // the command is not in the table // if there is only one word with an extension, assume this is file to be read if ( argc == 1 && strstr( argv[0], "." ) ) { // add command 'read' assuming that this is the file name argv2 = CmdAddToArgv( argc, argv ); CmdFreeArgv( argc, argv ); argc = argc+1; argv = argv2; *pargc = argc; *pargv = argv; if ( ! st__lookup( pAbc->tCommands, argv[0], (char **)&pCommand ) ) assert( 0 ); } else { fprintf( pAbc->Err, "** cmd error: unknown command '%s'\n", argv[0] ); fprintf( pAbc->Err, "(this is likely caused by using an alias defined in \"abc.rc\"\n" ); fprintf( pAbc->Err, "without having this file in the current or parent directory)\n" ); return 1; } } // get the backup network if the command is going to change the network if ( pCommand->fChange ) { if ( pAbc->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) ) { pNetCopy = Abc_NtkDup( pAbc->pNtkCur ); Abc_FrameSetCurrentNetwork( pAbc, pNetCopy ); // swap the current network and the backup network // to prevent the effect of resetting the short names Abc_FrameSwapCurrentAndBackup( pAbc ); } } // execute the command clk = Extra_CpuTimeDouble(); pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc; fError = (*pFunc)( pAbc, argc, argv ); pAbc->TimeCommand += Extra_CpuTimeDouble() - clk; // automatic execution of arbitrary command after each command // usually this is a passive command ... if ( fError == 0 && !pAbc->fAutoexac ) { if ( st__lookup( pAbc->tFlags, "autoexec", &value ) ) { pAbc->fAutoexac = 1; fError = Cmd_CommandExecute( pAbc, value ); pAbc->fAutoexac = 0; } } return fError; } /**Function************************************************************* Synopsis [Splits the command line string into individual commands.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ const char * CmdSplitLine( Abc_Frame_t * pAbc, const char *sCommand, int *argc, char ***argv ) { const char *p, *start; char c; int i, j; char *new_arg; Vec_Ptr_t * vArgs; int single_quote, double_quote; vArgs = Vec_PtrAlloc( 10 ); p = sCommand; for ( ;; ) { // skip leading white space while ( isspace( ( int ) *p ) ) { p++; } // skip until end of this token single_quote = double_quote = 0; for ( start = p; ( c = *p ) != '\0'; p++ ) { if ( c == ';' || c == '#' || isspace( ( int ) c ) ) { if ( !single_quote && !double_quote ) { break; } } if ( c == '\'' ) { single_quote = !single_quote; } if ( c == '"' ) { double_quote = !double_quote; } } if ( single_quote || double_quote ) { ( void ) fprintf( pAbc->Err, "** cmd warning: ignoring unbalanced quote ...\n" ); } if ( start == p ) break; new_arg = ABC_ALLOC( char, p - start + 1 ); j = 0; for ( i = 0; i < p - start; i++ ) { c = start[i]; if ( ( c != '\'' ) && ( c != '\"' ) ) { new_arg[j++] = isspace( ( int ) c ) ? ' ' : start[i]; } } new_arg[j] = '\0'; Vec_PtrPush( vArgs, new_arg ); } *argc = vArgs->nSize; *argv = (char **)Vec_PtrReleaseArray( vArgs ); Vec_PtrFree( vArgs ); if ( *p == ';' ) { p++; } else if ( *p == '#' ) { for ( ; *p != 0; p++ ); // skip to end of line } return p; } /**Function************************************************************* Synopsis [Replaces parts of the command line string by aliases if given.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) { int i, argc, stopit, added, offset, did_subst, subst, fError, newc, j; const char *arg; char **argv, **newv; Abc_Alias *alias; argc = *argcp; argv = *argvp; stopit = 0; for ( ; *loop < 200; ( *loop )++ ) { if ( argc == 0 ) return 0; if ( stopit != 0 || st__lookup( pAbc->tAliases, argv[0], (char **) &alias ) == 0 ) { return 0; } if ( strcmp( argv[0], alias->argv[0] ) == 0 ) { stopit = 1; } ABC_FREE( argv[0] ); added = alias->argc - 1; /* shift all the arguments to the right */ if ( added != 0 ) { argv = ABC_REALLOC( char *, argv, argc + added ); for ( i = argc - 1; i >= 1; i-- ) { argv[i + added] = argv[i]; } for ( i = 1; i <= added; i++ ) { argv[i] = NULL; } argc += added; } subst = 0; for ( i = 0, offset = 0; i < alias->argc; i++, offset++ ) { arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst ); if ( arg == NULL ) { *argcp = argc; *argvp = argv; return ( 1 ); } if ( did_subst != 0 ) { subst = 1; } fError = 0; do { arg = CmdSplitLine( pAbc, arg, &newc, &newv ); /* * If there's a complete `;' terminated command in `arg', * when split_line() returns arg[0] != '\0'. */ if ( arg[0] == '\0' ) { /* just a bunch of words */ break; } fError = CmdApplyAlias( pAbc, &newc, &newv, loop ); if ( fError == 0 ) { fError = CmdCommandDispatch( pAbc, &newc, &newv ); } CmdFreeArgv( newc, newv ); } while ( fError == 0 ); if ( fError != 0 ) { *argcp = argc; *argvp = argv; return ( 1 ); } added = newc - 1; if ( added != 0 ) { argv = ABC_REALLOC( char *, argv, argc + added ); for ( j = argc - 1; j > offset; j-- ) { argv[j + added] = argv[j]; } argc += added; } for ( j = 0; j <= added; j++ ) { argv[j + offset] = newv[j]; } ABC_FREE( newv ); offset += added; } if ( subst == 1 ) { for ( i = offset; i < argc; i++ ) { ABC_FREE( argv[i] ); } argc = offset; } *argcp = argc; *argvp = argv; } fprintf( pAbc->Err, "** cmd warning: alias loop\n" ); return 1; } /**Function************************************************************* Synopsis [Performs history substitution (now, disabled).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char *line, int *changed ) { // as of today, no history substitution *changed = 0; return line; } /**Function************************************************************* Synopsis [Opens the file with path (now, disabled).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFileNameReal, int silent ) { char * sRealName, * sPathUsr, * sPathLib, * sPathAll; FILE * pFile; if (strcmp(sFileName, "-") == 0) { if (strcmp(sMode, "w") == 0) { sRealName = Extra_UtilStrsav( "stdout" ); pFile = stdout; } else { sRealName = Extra_UtilStrsav( "stdin" ); pFile = stdin; } } else { sRealName = NULL; if (strcmp(sMode, "r") == 0) { /* combine both pathes if exist */ sPathUsr = Cmd_FlagReadByName(pAbc,"open_path"); sPathLib = Cmd_FlagReadByName(pAbc,"lib_path"); if ( sPathUsr == NULL && sPathLib == NULL ) { sPathAll = NULL; } else if ( sPathUsr == NULL ) { sPathAll = Extra_UtilStrsav( sPathLib ); } else if ( sPathLib == NULL ) { sPathAll = Extra_UtilStrsav( sPathUsr ); } else { sPathAll = ABC_ALLOC( char, strlen(sPathLib)+strlen(sPathUsr)+5 ); sprintf( sPathAll, "%s:%s",sPathUsr, sPathLib ); } if ( sPathAll != NULL ) { sRealName = Extra_UtilFileSearch(sFileName, sPathAll, "r"); ABC_FREE( sPathAll ); } } if (sRealName == NULL) { sRealName = Extra_UtilTildeExpand(sFileName); } if ((pFile = fopen(sRealName, sMode)) == NULL) { if (! silent) { // perror(sRealName); Abc_Print( 1, "Cannot open file \"%s\".\n", sRealName ); } } else { // print the path/name of the resource file 'abc.rc' that is being loaded if ( !silent && strlen(sRealName) >= 6 && strcmp( sRealName + strlen(sRealName) - 6, "abc.rc" ) == 0 ) Abc_Print( 1, "Loading resource file \"%s\".\n", sRealName ); } } if ( pFileNameReal ) *pFileNameReal = sRealName; else ABC_FREE(sRealName); return pFile; } /**Function************************************************************* Synopsis [Frees the previously allocated argv array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void CmdFreeArgv( int argc, char **argv ) { int i; for ( i = 0; i < argc; i++ ) ABC_FREE( argv[i] ); ABC_FREE( argv ); } char ** CmdDupArgv( int argc, char **argv ) { char ** argvNew = ABC_ALLOC( char *, argc ); int i; for ( i = 0; i < argc; i++ ) argvNew[i] = Abc_UtilStrsav( argv[i] ); return argvNew; } /**Function************************************************************* Synopsis [Frees the previously allocated argv array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char ** CmdAddToArgv( int argc, char ** argv ) { char ** argv2; int i; argv2 = ABC_ALLOC( char *, argc + 1 ); argv2[0] = Extra_UtilStrsav( "read" ); // argv2[0] = Extra_UtilStrsav( "&r" ); for ( i = 0; i < argc; i++ ) argv2[i+1] = Extra_UtilStrsav( argv[i] ); return argv2; } /**Function************************************************************* Synopsis [Frees the previously allocated command.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void CmdCommandFree( Abc_Command * pCommand ) { ABC_FREE( pCommand->sGroup ); ABC_FREE( pCommand->sName ); ABC_FREE( pCommand ); } /**Function************************************************************* Synopsis [Prints commands alphabetically by group.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void CmdCommandPrint( Abc_Frame_t * pAbc, int fPrintAll, int fDetails ) { const char *key; char *value; st__generator * gen; Abc_Command ** ppCommands; Abc_Command * pCommands; int nCommands, iGroupStart, i, j; char * sGroupCur; int LenghtMax, nColumns, iCom = 0; FILE *backupErr = pAbc->Err; // put all commands into one array nCommands = st__count( pAbc->tCommands ); ppCommands = ABC_ALLOC( Abc_Command *, nCommands ); i = 0; st__foreach_item( pAbc->tCommands, gen, &key, &value ) { pCommands = (Abc_Command *)value; if ( fPrintAll || pCommands->sName[0] != '_' ) ppCommands[i++] = pCommands; } nCommands = i; // sort command by group and then by name, alphabetically qsort( (void *)ppCommands, nCommands, sizeof(Abc_Command *), (int (*)(const void *, const void *)) CmdCommandPrintCompare ); assert( CmdCommandPrintCompare( ppCommands, ppCommands + nCommands - 1 ) <= 0 ); // get the longest command name LenghtMax = 0; for ( i = 0; i < nCommands; i++ ) if ( LenghtMax < (int)strlen(ppCommands[i]->sName) ) LenghtMax = (int)strlen(ppCommands[i]->sName); // get the number of columns nColumns = 79 / (LenghtMax + 2); // print the starting message fprintf( pAbc->Out, " Welcome to ABC compiled on %s %s!", __DATE__, __TIME__ ); // print the command by group sGroupCur = NULL; iGroupStart = 0; pAbc->Err = pAbc->Out; for ( i = 0; i < nCommands; i++ ) if ( sGroupCur && strcmp( sGroupCur, ppCommands[i]->sGroup ) == 0 ) { // this command belongs to the same group as the previous one if ( iCom++ % nColumns == 0 ) fprintf( pAbc->Out, "\n" ); // print this command fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName ); } else { // this command starts the new group of commands // start the new group if ( fDetails && i != iGroupStart ) { // print help messages for all commands in the previous groups fprintf( pAbc->Out, "\n" ); for ( j = iGroupStart; j < i; j++ ) { char *tmp_cmd; fprintf( pAbc->Out, "\n" ); // fprintf( pAbc->Out, "--- %s ---\n", ppCommands[j]->sName ); tmp_cmd = ABC_ALLOC(char, strlen(ppCommands[j]->sName)+4); (void) sprintf(tmp_cmd, "%s -h", ppCommands[j]->sName); (void) Cmd_CommandExecute( pAbc, tmp_cmd ); ABC_FREE(tmp_cmd); } fprintf( pAbc->Out, "\n" ); fprintf( pAbc->Out, " ----------------------------------------------------------------------" ); iGroupStart = i; } fprintf( pAbc->Out, "\n" ); fprintf( pAbc->Out, "\n" ); fprintf( pAbc->Out, "%s commands:\n", ppCommands[i]->sGroup ); // print this command fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName ); // remember current command group sGroupCur = ppCommands[i]->sGroup; // reset the command counter iCom = 1; } if ( fDetails && i != iGroupStart ) { // print help messages for all commands in the previous groups fprintf( pAbc->Out, "\n" ); for ( j = iGroupStart; j < i; j++ ) { char *tmp_cmd; fprintf( pAbc->Out, "\n" ); // fprintf( pAbc->Out, "--- %s ---\n", ppCommands[j]->sName ); tmp_cmd = ABC_ALLOC(char, strlen(ppCommands[j]->sName)+4); (void) sprintf(tmp_cmd, "%s -h", ppCommands[j]->sName); (void) Cmd_CommandExecute( pAbc, tmp_cmd ); ABC_FREE(tmp_cmd); } } pAbc->Err = backupErr; fprintf( pAbc->Out, "\n" ); ABC_FREE( ppCommands ); } /**Function************************************************************* Synopsis [Comparision function used for sorting commands.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ) { Abc_Command * pC1 = *ppC1; Abc_Command * pC2 = *ppC2; int RetValue; RetValue = strcmp( pC1->sGroup, pC2->sGroup ); if ( RetValue < 0 ) return -1; if ( RetValue > 0 ) return 1; // the command belong to the same group // put commands with "_" at the end of the list if ( pC1->sName[0] != '_' && pC2->sName[0] == '_' ) return -1; if ( pC1->sName[0] == '_' && pC2->sName[0] != '_' ) return 1; RetValue = strcmp( pC1->sName, pC2->sName ); if ( RetValue < 0 ) return -1; if ( RetValue > 0 ) return 1; // should not be two indentical commands assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Comparision function used for sorting commands.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CmdNamePrintCompare( char ** ppC1, char ** ppC2 ) { return strcmp( *ppC1, *ppC2 ); } /**Function************************************************************* Synopsis [Comparision function used for sorting commands.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void CmdPrintTable( st__table * tTable, int fAliases ) { st__generator * gen; const char ** ppNames; const char * key; char* value; int nNames, i; // collect keys in the array ppNames = ABC_ALLOC( const char *, st__count(tTable) ); nNames = 0; st__foreach_item( tTable, gen, &key, &value ) ppNames[nNames++] = key; // sort array by name qsort( (void *)ppNames, nNames, sizeof(char *), (int (*)(const void *, const void *))CmdNamePrintCompare ); // print in this order for ( i = 0; i < nNames; i++ ) { st__lookup( tTable, ppNames[i], &value ); if ( fAliases ) CmdCommandAliasPrint( Abc_FrameGetGlobalFrame(), (Abc_Alias *)value ); else fprintf( stdout, "%-15s %-15s\n", ppNames[i], value ); } ABC_FREE( ppNames ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/cmd/module.make000066400000000000000000000003611300674244400236350ustar00rootroot00000000000000SRC += src/base/cmd/cmd.c \ src/base/cmd/cmdAlias.c \ src/base/cmd/cmdApi.c \ src/base/cmd/cmdFlag.c \ src/base/cmd/cmdHist.c \ src/base/cmd/cmdLoad.c \ src/base/cmd/cmdPlugin.c \ src/base/cmd/cmdStarter.c \ src/base/cmd/cmdUtils.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/000077500000000000000000000000001300674244400217235ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/exor.c000066400000000000000000001035401300674244400230470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [exor.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Exclusive sum-of-product minimization.] Synopsis [Main procedure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: exor.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// /// /// Implementation of EXORCISM - 4 /// /// An Exclusive Sum-of-Product Minimizer /// /// Alan Mishchenko /// /// /// //////////////////////////////////////////////////////////////////////// /// /// /// Main Module /// /// ESOP Minimization Task Coordinator /// /// /// /// 1) interprets command line /// /// 2) calls the approapriate reading procedure /// /// 3) calls the minimization module /// /// /// /// Ver. 1.0. Started - July 18, 2000. Last update - July 20, 2000 /// /// Ver. 1.1. Started - July 24, 2000. Last update - July 29, 2000 /// /// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 26, 2000 /// /// Ver. 1.6. Started - Sep 11, 2000. Last update - Sep 15, 2000 /// /// Ver. 1.7. Started - Sep 20, 2000. Last update - Sep 23, 2000 /// /// /// //////////////////////////////////////////////////////////////////////// /// This software was tested with the BDD package "CUDD", v.2.3.0 /// /// by Fabio Somenzi /// /// http://vlsi.colorado.edu/~fabio/ /// //////////////////////////////////////////////////////////////////////// #include "exor.h" ABC_NAMESPACE_IMPL_START /////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// // information about the cube cover cinfo g_CoverInfo; extern int s_fDecreaseLiterals; //////////////////////////////////////////////////////////////////////// /// EXTERNAL FUNCTIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION main() /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Number of negative literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* static int QCost[16][16] = { { 1}, // 0 { 1, 2}, // 1 { 5, 5, 6}, // 2 { 14, 14, 16, 18}, // 3 { 20, 20, 20, 22, 24}, // 4 { 32, 32, 32, 34, 36, 38}, // 5 { 44, 44, 44, 44, 46, 48, 50}, // 6 { 56, 56, 56, 56, 58, 60, 62, 64}, // 7 { 0 } }; */ int GetQCost( int nVars, int nNegs ) { int Extra; assert( nVars >= nNegs ); if ( nVars == 0 ) return 1; if ( nVars == 1 ) { if ( nNegs == 0 ) return 1; if ( nNegs == 1 ) return 2; } if ( nVars == 2 ) { if ( nNegs <= 1 ) return 5; if ( nNegs == 2 ) return 6; } if ( nVars == 3 ) { if ( nNegs <= 1 ) return 14; if ( nNegs == 2 ) return 16; if ( nNegs == 3 ) return 18; } Extra = nNegs - nVars/2; return 20 + 12 * (nVars - 4) + (Extra > 0 ? 2 * Extra : 0); } void GetQCostTest() { int i, k, Limit = 10; for ( i = 0; i < Limit; i++ ) { for ( k = 0; k <= i; k++ ) printf( "%4d ", GetQCost(i, k) ); printf( "\n" ); } } int ComputeQCost( Vec_Int_t * vCube ) { int i, Entry, nLitsN = 0; Vec_IntForEachEntry( vCube, Entry, i ) nLitsN += Abc_LitIsCompl(Entry); return GetQCost( Vec_IntSize(vCube), nLitsN ); } int ComputeQCostBits( Cube * p ) { extern varvalue GetVar( Cube* pC, int Var ); int v, nLits = 0, nLitsN = 0; for ( v = 0; v < g_CoverInfo.nVarsIn; v++ ) { int Value = GetVar( p, v ); if ( Value == VAR_NEG ) nLitsN++; else if ( Value == VAR_POS ) nLits++; } nLits += nLitsN; return GetQCost( nLits, nLitsN ); } int ToffoliGateCount( int controls, int lines ) { switch ( controls ) { case 0u: case 1u: return 0; break; case 2u: return 1; break; case 3u: return 4; break; case 4u: return ( ( ( lines + 1 ) / 2 ) >= controls ) ? 8 : 10; break; default: return ( ( ( lines + 1 ) / 2 ) >= controls ) ? 4 * ( controls - 2 ) : 8 * ( controls - 3 ); } } int ComputeQCostTcount( Vec_Int_t * vCube ) { return 7 * ToffoliGateCount( Vec_IntSize( vCube ), g_CoverInfo.nVarsIn + 1 ); } int ComputeQCostTcountBits( Cube * p ) { extern varvalue GetVar( Cube* pC, int Var ); int v, nLits = 0; for ( v = 0; v < g_CoverInfo.nVarsIn; v++ ) if ( GetVar( p, v ) != VAR_ABS ) nLits++; return 7 * ToffoliGateCount( nLits, g_CoverInfo.nVarsIn + 1 ); /* maybe just: 7 * ToffoliGateCount( p->a, g_CoverInfo.nVarsIn + 1 ); */ } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int ReduceEsopCover() { /////////////////////////////////////////////////////////////// // SIMPLIFICATION //////////////////////////////////////////////////////////////////// int nIterWithoutImprovement = 0; int nIterCount = 0; int GainTotal; int z; do { //START: if ( g_CoverInfo.Verbosity == 2 ) printf( "\nITERATION #%d\n\n", ++nIterCount ); else if ( g_CoverInfo.Verbosity == 1 ) printf( "." ); GainTotal = 0; GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); if ( nIterWithoutImprovement > (int)(g_CoverInfo.Quality>0) ) { GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|0 ); } if ( GainTotal ) nIterWithoutImprovement = 0; else nIterWithoutImprovement++; // if ( g_CoverInfo.Quality >= 2 && nIterWithoutImprovement == 2 ) // s_fDecreaseLiterals = 1; } while ( nIterWithoutImprovement < 1 + g_CoverInfo.Quality ); // improve the literal count s_fDecreaseLiterals = 1; for ( z = 0; z < 1; z++ ) { if ( g_CoverInfo.Verbosity == 2 ) printf( "\nITERATION #%d\n\n", ++nIterCount ); else if ( g_CoverInfo.Verbosity == 1 ) printf( "." ); GainTotal = 0; GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); // if ( GainTotal ) // { // nIterWithoutImprovement = 0; // goto START; // } } /* //////////////////////////////////////////////////////////////////// // Print statistics printf( "\nShallow simplification time is "; cout << (float)(clk2 - clk1)/(float)(CLOCKS_PER_SEC) << " sec\n" ); printf( "Deep simplification time is "; cout << (float)(Abc_Clock() - clk2)/(float)(CLOCKS_PER_SEC) << " sec\n" ); printf( "Cover after iterative simplification = " << s_nCubesInUse << endl; printf( "Reduced by initial cube writing = " << g_CoverInfo.nCubesBefore-nCubesAfterWriting << endl; printf( "Reduced by shallow simplification = " << nCubesAfterWriting-nCubesAfterShallow << endl; printf( "Reduced by deep simplification = " << nCubesAfterWriting-s_nCubesInUse << endl; // printf( "\nThe total number of cubes created = " << g_CoverInfo.cIDs << endl; // printf( "Total number of places in a queque = " << s_nPosAlloc << endl; // printf( "Minimum free places in queque-2 = " << s_nPosMax[0] << endl; // printf( "Minimum free places in queque-3 = " << s_nPosMax[1] << endl; // printf( "Minimum free places in queque-4 = " << s_nPosMax[2] << endl; */ //////////////////////////////////////////////////////////////////// // write the number of cubes into cover information assert ( g_CoverInfo.nCubesInUse + g_CoverInfo.nCubesFree == g_CoverInfo.nCubesAlloc ); // printf( "\nThe output cover is\n" ); // PrintCoverDebug( cout ); return 0; } ////////////////////////////////////////////////////////////////// // quite a good script ////////////////////////////////////////////////////////////////// /* long clk1 = Abc_Clock(); int nIterWithoutImprovement = 0; do { PrintQuequeStats(); GainTotal = 0; GainTotal += IterativelyApplyExorLink( DIST2, 0|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 0|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); if ( nIterWithoutImprovement > 2 ) { GainTotal += IterativelyApplyExorLink( DIST2, 0|0|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 0|2|4 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 ); } if ( nIterWithoutImprovement > 6 ) { GainTotal += IterativelyApplyExorLink( DIST2, 0|0|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 0|0|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 0|0|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 ); } if ( GainTotal ) nIterWithoutImprovement = 0; else nIterWithoutImprovement++; } while ( nIterWithoutImprovement < 12 ); nCubesAfterShallow = s_nCubesInUse; */ /* // alu4 - 439 long clk1 = Abc_Clock(); int nIterWithoutImprovement = 0; do { PrintQuequeStats(); GainTotal = 0; GainTotal += IterativelyApplyExorLink( DIST2, 1|0|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); if ( nIterWithoutImprovement > 2 ) { GainTotal += IterativelyApplyExorLink( DIST2, 0|0|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 0|2|4 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 ); } if ( nIterWithoutImprovement > 6 ) { GainTotal += IterativelyApplyExorLink( DIST2, 0|0|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 0|0|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 0|0|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 ); } if ( GainTotal ) nIterWithoutImprovement = 0; else nIterWithoutImprovement++; } while ( nIterWithoutImprovement < 12 ); */ /* // alu4 - 412 cubes, 700 sec long clk1 = Abc_Clock(); int nIterWithoutImprovement = 0; int nIterCount = 0; do { printf( "\nITERATION #" << ++nIterCount << endl << endl; GainTotal = 0; GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); if ( nIterWithoutImprovement > 3 ) { GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); } if ( nIterWithoutImprovement > 7 ) { GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); } if ( GainTotal ) nIterWithoutImprovement = 0; else nIterWithoutImprovement++; } while ( nIterWithoutImprovement < 12 ); */ /* // pretty good script // alu4 = 424 in 250 sec long clk1 = Abc_Clock(); int nIterWithoutImprovement = 0; int nIterCount = 0; do { printf( "\nITERATION #" << ++nIterCount << " |"; for ( int k = 0; k < nIterWithoutImprovement; k++ ) printf( "*"; for ( ; k < 11; k++ ) printf( "_"; printf( "|" << endl << endl; GainTotal = 0; GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); if ( nIterWithoutImprovement > 2 ) { GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); } if ( nIterWithoutImprovement > 4 ) { GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); } if ( GainTotal ) nIterWithoutImprovement = 0; else nIterWithoutImprovement++; } while ( nIterWithoutImprovement < 7 ); */ /* alu4 = 435 70 secs long clk1 = Abc_Clock(); int nIterWithoutImprovement = 0; int nIterCount = 0; do { printf( "\nITERATION #" << ++nIterCount << endl << endl; GainTotal = 0; GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); if ( GainTotal ) nIterWithoutImprovement = 0; else nIterWithoutImprovement++; } while ( nIterWithoutImprovement < 4 ); */ /* // the best previous long clk1 = Abc_Clock(); int nIterWithoutImprovement = 0; int nIterCount = 0; int GainTotal; do { if ( g_CoverInfo.Verbosity == 2 ) printf( "\nITERATION #" << ++nIterCount << endl << endl; else if ( g_CoverInfo.Verbosity == 1 ) cout << '.'; GainTotal = 0; GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); if ( nIterWithoutImprovement > 1 ) { GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 ); GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 ); GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 ); } if ( GainTotal ) nIterWithoutImprovement = 0; else nIterWithoutImprovement++; } // while ( nIterWithoutImprovement < 20 ); // while ( nIterWithoutImprovement < 7 ); while ( nIterWithoutImprovement < 1 + g_CoverInfo.Quality ); */ /* // the last tried long clk1 = Abc_Clock(); int nIterWithoutImprovement = 0; int nIterCount = 0; int GainTotal; do { if ( g_CoverInfo.Verbosity == 2 ) printf( "\nITERATION #" << ++nIterCount << endl << endl; else if ( g_CoverInfo.Verbosity == 1 ) cout << '.'; GainTotal = 0; GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); if ( nIterWithoutImprovement > (int)(g_CoverInfo.Quality>0) ) { GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|0 ); GainTotal += IterativelyApplyExorLink2( 1|2|0 ); GainTotal += IterativelyApplyExorLink3( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|4 ); GainTotal += IterativelyApplyExorLink2( 1|2|4 ); GainTotal += IterativelyApplyExorLink4( 1|2|0 ); } if ( GainTotal ) nIterWithoutImprovement = 0; else nIterWithoutImprovement++; } while ( nIterWithoutImprovement < 1 + g_CoverInfo.Quality ); */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void AddCubesToStartingCover( Vec_Wec_t * vEsop ) { Vec_Int_t * vCube; Cube * pNew; int * s_Level2Var; int * s_LevelValues; int c, i, k, Lit, Out; s_Level2Var = ABC_ALLOC( int, g_CoverInfo.nVarsIn ); s_LevelValues = ABC_ALLOC( int, g_CoverInfo.nVarsIn ); for ( i = 0; i < g_CoverInfo.nVarsIn; i++ ) s_Level2Var[i] = i; g_CoverInfo.nLiteralsBefore = 0; g_CoverInfo.QCostBefore = 0; Vec_WecForEachLevel( vEsop, vCube, c ) { // get the output of this cube Out = -Vec_IntPop(vCube) - 1; // fill in the cube with blanks for ( i = 0; i < g_CoverInfo.nVarsIn; i++ ) s_LevelValues[i] = VAR_ABS; Vec_IntForEachEntry( vCube, Lit, k ) { if ( Abc_LitIsCompl(Lit) ) s_LevelValues[Abc_Lit2Var(Lit)] = VAR_NEG; else s_LevelValues[Abc_Lit2Var(Lit)] = VAR_POS; } // get the new cube pNew = GetFreeCube(); // consider the need to clear the cube if ( pNew->pCubeDataIn[0] ) // this is a recycled cube { for ( i = 0; i < g_CoverInfo.nWordsIn; i++ ) pNew->pCubeDataIn[i] = 0; for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) pNew->pCubeDataOut[i] = 0; } InsertVarsWithoutClearing( pNew, s_Level2Var, g_CoverInfo.nVarsIn, s_LevelValues, Out ); // set literal counts pNew->a = Vec_IntSize(vCube); pNew->z = 1; pNew->q = ComputeQCost(vCube); // set the ID pNew->ID = g_CoverInfo.cIDs++; // skip through zero-ID if ( g_CoverInfo.cIDs == 256 ) g_CoverInfo.cIDs = 1; // add this cube to storage CheckForCloseCubes( pNew, 1 ); g_CoverInfo.nLiteralsBefore += Vec_IntSize(vCube); g_CoverInfo.QCostBefore += ComputeQCost(vCube); } ABC_FREE( s_Level2Var ); ABC_FREE( s_LevelValues ); assert ( g_CoverInfo.nCubesInUse + g_CoverInfo.nCubesFree == g_CoverInfo.nCubesAlloc ); } /**Function************************************************************* Synopsis [Performs heuristic minimization of ESOPs.] Description [Returns 1 on success, 0 on failure.] SideEffects [] SeeAlso [] ***********************************************************************/ int Exorcism( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOut ) { abctime clk1; int RemainderBits; int TotalWords; int MemTemp, MemTotal; /////////////////////////////////////////////////////////////////////// // STEPS of HEURISTIC ESOP MINIMIZATION /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // STEP 1: determine the size of the starting cover /////////////////////////////////////////////////////////////////////// assert( nIns > 0 ); // inputs RemainderBits = (nIns*2)%(sizeof(unsigned)*8); TotalWords = (nIns*2)/(sizeof(unsigned)*8) + (RemainderBits > 0); g_CoverInfo.nVarsIn = nIns; g_CoverInfo.nWordsIn = TotalWords; // outputs RemainderBits = (nOuts)%(sizeof(unsigned)*8); TotalWords = (nOuts)/(sizeof(unsigned)*8) + (RemainderBits > 0); g_CoverInfo.nVarsOut = nOuts; g_CoverInfo.nWordsOut = TotalWords; g_CoverInfo.cIDs = 1; // cubes clk1 = Abc_Clock(); // g_CoverInfo.nCubesBefore = CountTermsInPseudoKroneckerCover( g_Func.dd, nOuts ); g_CoverInfo.nCubesBefore = Vec_WecSize(vEsop); g_CoverInfo.TimeStart = Abc_Clock() - clk1; if ( g_CoverInfo.Verbosity ) { printf( "Starting cover generation time is %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeStart) ); printf( "The number of cubes in the starting cover is %d\n", g_CoverInfo.nCubesBefore ); } if ( g_CoverInfo.nCubesBefore > g_CoverInfo.nCubesMax ) { printf( "\nThe size of the starting cover is more than %d cubes. Quitting...\n", g_CoverInfo.nCubesMax ); return 0; } /////////////////////////////////////////////////////////////////////// // STEP 2: prepare internal data structures /////////////////////////////////////////////////////////////////////// g_CoverInfo.nCubesAlloc = g_CoverInfo.nCubesBefore + ADDITIONAL_CUBES; // allocate cube cover MemTotal = 0; MemTemp = AllocateCover( g_CoverInfo.nCubesAlloc, g_CoverInfo.nWordsIn, g_CoverInfo.nWordsOut ); if ( MemTemp == 0 ) { printf( "Unexpected memory allocation problem. Quitting...\n" ); return 0; } else MemTotal += MemTemp; // allocate cube sets MemTemp = AllocateCubeSets( g_CoverInfo.nVarsIn, g_CoverInfo.nVarsOut ); if ( MemTemp == 0 ) { printf( "Unexpected memory allocation problem. Quitting...\n" ); return 0; } else MemTotal += MemTemp; // allocate adjacency queques MemTemp = AllocateQueques( g_CoverInfo.nCubesAlloc*g_CoverInfo.nCubesAlloc/CUBE_PAIR_FACTOR ); if ( MemTemp == 0 ) { printf( "Unexpected memory allocation problem. Quitting...\n" ); return 0; } else MemTotal += MemTemp; if ( g_CoverInfo.Verbosity ) printf( "Dynamically allocated memory is %dK\n", MemTotal/1000 ); /////////////////////////////////////////////////////////////////////// // STEP 3: write the cube cover into the allocated storage /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// clk1 = Abc_Clock(); if ( g_CoverInfo.Verbosity ) printf( "Generating the starting cover...\n" ); AddCubesToStartingCover( vEsop ); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // STEP 4: iteratively improve the cover /////////////////////////////////////////////////////////////////////// if ( g_CoverInfo.Verbosity ) printf( "Performing minimization...\n" ); clk1 = Abc_Clock(); ReduceEsopCover(); g_CoverInfo.TimeMin = Abc_Clock() - clk1; // g_Func.TimeMin = (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC); if ( g_CoverInfo.Verbosity ) { printf( "\nMinimization time is %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeMin) ); printf( "\nThe number of cubes after minimization is %d\n", g_CoverInfo.nCubesInUse ); } /////////////////////////////////////////////////////////////////////// // STEP 5: save the cover into file /////////////////////////////////////////////////////////////////////// // if option is MULTI_OUTPUT, the output is written into the output file; // if option is SINGLE_NODE, the output is added to the input file // and written into the output file; in this case, the minimized nodes is // also stored in the temporary file "temp.blif" for verification // create the file name and write the output { char Buffer[1000]; sprintf( Buffer, "%s", pFileNameOut ? pFileNameOut : "temp.esop" ); WriteResultIntoFile( Buffer ); if ( g_CoverInfo.Verbosity ) printf( "Minimized cover has been written into file <%s>\n", Buffer ); } /////////////////////////////////////////////////////////////////////// // STEP 6: delocate memory /////////////////////////////////////////////////////////////////////// DelocateCubeSets(); DelocateCover(); DelocateQueques(); // return success return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ExorcismMain( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOut, int Quality, int Verbosity, int nCubesMax, int fUseQCost ) { memset( &g_CoverInfo, 0, sizeof(cinfo) ); g_CoverInfo.Quality = Quality; g_CoverInfo.Verbosity = Verbosity; g_CoverInfo.nCubesMax = nCubesMax; g_CoverInfo.fUseQCost = fUseQCost; if ( fUseQCost ) s_fDecreaseLiterals = 1; if ( g_CoverInfo.Verbosity ) { printf( "\nEXORCISM, Ver.4.7: Exclusive Sum-of-Product Minimizer\n" ); printf( "by Alan Mishchenko, Portland State University, July-September 2000\n\n" ); printf( "Incoming ESOP has %d inputs, %d outputs, and %d cubes.\n", nIns, nOuts, Vec_WecSize(vEsop) ); } PrepareBitSetModule(); if ( Exorcism( vEsop, nIns, nOuts, pFileNameOut ) == 0 ) { printf( "Something went wrong when minimizing the cover\n" ); return 0; } return 1; } /////////////////////////////////////////////////////////////////// //////////// End of File ///////////////// /////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/exor.h000066400000000000000000000162321300674244400230550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [exor.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Exclusive sum-of-product minimization.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: exor.h,v 1.0 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// /// /// Interface of EXORCISM - 4 /// /// An Exclusive Sum-of-Product Minimizer /// /// Alan Mishchenko /// /// /// //////////////////////////////////////////////////////////////////////// /// /// /// Main Module /// /// /// /// Ver. 1.0. Started - July 15, 2000. Last update - July 20, 2000 /// /// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 10, 2000 /// /// Ver. 1.7. Started - Sep 20, 2000. Last update - Sep 23, 2000 /// /// /// //////////////////////////////////////////////////////////////////////// /// This software was tested with the BDD package "CUDD", v.2.3.0 /// /// by Fabio Somenzi /// /// http://vlsi.colorado.edu/~fabio/ /// //////////////////////////////////////////////////////////////////////// #ifndef __EXORMAIN_H__ #define __EXORMAIN_H__ #include #include #include #include #include "misc/vec/vec.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // the number of bits per integer (can be 16, 32, 64 - tested for 32) #define BPI 32 #define BPIMASK 31 #define LOGBPI 5 // the maximum number of input variables #define MAXVARS 1000 // the number of cubes that are allocated additionally #define ADDITIONAL_CUBES 33 // the factor showing how many cube pairs will be allocated #define CUBE_PAIR_FACTOR 20 // the following number of cube pairs are allocated: // nCubesAlloc/CUBE_PAIR_FACTOR #if BPI == 64 #define DIFFERENT 0x5555555555555555 #define BIT_COUNT(w) (BitCount[(w)&0xffff] + BitCount[((w)>>16)&0xffff] + BitCount[((w)>>32)&0xffff] + BitCount[(w)>>48]) #elif BPI == 32 #define DIFFERENT 0x55555555 #define BIT_COUNT(w) (BitCount[(w)&0xffff] + BitCount[(w)>>16]) #else #define DIFFERENT 0x5555 #define BIT_COUNT(w) (BitCount[(w)]) #endif #define VarWord(element) ((element)>>LOGBPI) #define VarBit(element) ((element)&BPIMASK) #define TICKS_TO_SECONDS(time) ((float)(time)/(float)(CLOCKS_PER_SEC)) //////////////////////////////////////////////////////////////////////// /// CUBE COVER and CUBE typedefs /// //////////////////////////////////////////////////////////////////////// typedef enum { MULTI_OUTPUT = 1, SINGLE_NODE, MULTI_NODE } type; // infomation about the cover typedef struct cinfo_tag { int nVarsIn; // number of input binary variables in the cubes int nVarsOut; // number of output binary variables in the cubes int nWordsIn; // number of input words used to represent the cover int nWordsOut; // number of output words used to represent the cover int nCubesAlloc; // the number of allocated cubes int nCubesBefore; // number of cubes before simplification int nCubesInUse; // number of cubes after simplification int nCubesFree; // number of free cubes int nLiteralsBefore;// number of literals before int nLiteralsAfter; // number of literals after int QCostBefore; // q-cost before int QCostAfter; // q-cost after int cIDs; // the counter of cube IDs int Verbosity; // verbosity level int Quality; // quality int nCubesMax; // maximum number of cubes in starting cover int fUseQCost; // use q-cost instead of literal count abctime TimeRead; // reading time abctime TimeStart; // starting cover computation time abctime TimeMin; // pure minimization time } cinfo; // representation of one cube (24 bytes + bit info) typedef unsigned int drow; typedef unsigned char byte; typedef struct cube { byte fMark; // the flag which is TRUE if the cubes is enabled byte ID; // (almost) unique ID of the cube short a; // the number of literals short z; // the number of 1's in the output part short q; // user cost drow* pCubeDataIn; // a pointer to the bit string representing literals drow* pCubeDataOut; // a pointer to the bit string representing literals struct cube* Prev; // pointers to the previous/next cubes in the list/ring struct cube* Next; } Cube; // preparation extern void PrepareBitSetModule(); extern int WriteResultIntoFile( char * pFileName ); // iterative ExorLink extern int IterativelyApplyExorLink2( char fDistEnable ); extern int IterativelyApplyExorLink3( char fDistEnable ); extern int IterativelyApplyExorLink4( char fDistEnable ); // cube storage allocation/delocation extern int AllocateCubeSets( int nVarsIn, int nVarsOut ); extern void DelocateCubeSets(); // adjacency queque allocation/delocation procedures extern int AllocateQueques( int nPlaces ); extern void DelocateQueques(); extern int AllocateCover( int nCubes, int nWordsIn, int nWordsOut ); extern void DelocateCover(); extern void AddToFreeCubes( Cube* pC ); extern Cube* GetFreeCube(); // getting and returning free cubes to the heap extern void InsertVarsWithoutClearing( Cube * pC, int * pVars, int nVarsIn, int * pVarValues, int Output ); extern int CheckForCloseCubes( Cube* p, int fAddCube ); extern int FindDiffVars( int *pDiffVars, Cube* pC1, Cube* pC2 ); // determines the variables that are different in cubes pC1 and pC2 // returns the number of variables extern int ComputeQCost( Vec_Int_t * vCube ); extern int ComputeQCostBits( Cube * p ); extern int CountLiterals(); extern int CountQCost(); //////////////////////////////////////////////////////////////////////// /// VARVALUE and CUBEDIST enum typedefs /// //////////////////////////////////////////////////////////////////////// // literal values typedef enum { VAR_NEG = 1, VAR_POS, VAR_ABS } varvalue; // the flag in some function calls can take one of the follwing values typedef enum { DIST2, DIST3, DIST4 } cubedist; ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/exorBits.c000066400000000000000000000374761300674244400237070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [exorBits.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Exclusive sum-of-product minimization.] Synopsis [Bit-level procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: exorBits.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// /// /// Implementation of EXORCISM - 4 /// /// An Exclusive Sum-of-Product Minimizer /// /// /// /// Alan Mishchenko /// /// /// //////////////////////////////////////////////////////////////////////// /// /// /// EXOR-Oriented Bit String Manipulation /// /// /// /// Ver. 1.0. Started - July 18, 2000. Last update - July 20, 2000 /// /// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 10, 2000 /// /// /// //////////////////////////////////////////////////////////////////////// /// This software was tested with the BDD package "CUDD", v.2.3.0 /// /// by Fabio Somenzi /// /// http://vlsi.colorado.edu/~fabio/ /// //////////////////////////////////////////////////////////////////////// #include "exor.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// EXTERNAL VARIABLES /// //////////////////////////////////////////////////////////////////////// // information about the cube cover // the number of cubes is constantly updated when the cube cover is processed // in this module, only the number of variables (nVarsIn) and integers (nWordsIn) // is used, which do not change extern cinfo g_CoverInfo; //////////////////////////////////////////////////////////////////////// /// FUNCTIONS OF THIS MODULE /// //////////////////////////////////////////////////////////////////////// int GetDistance( Cube * pC1, Cube * pC2 ); // return the distance between two cubes int GetDistancePlus( Cube * pC1, Cube * pC2 ); int FindDiffVars( int * pDiffVars, Cube * pC1, Cube * pC2 ); // determine different variables in cubes from pCubes[] and writes them into pDiffVars // returns the number of different variables void InsertVars( Cube * pC, int * pVars, int nVarsIn, int * pVarValues ); //inline int VarWord( int element ); //inline int VarBit( int element ); varvalue GetVar( Cube * pC, int Var ); void ExorVar( Cube * pC, int Var, varvalue Val ); //////////////////////////////////////////////////////////////////////// /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// // the bit count for the first 256 integer numbers static unsigned char BitCount8[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; static int SparseNumbers[163] = { 0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85,256,257,260, 261,272,273,276,277,320,321,324,325,336,337,340,1024,1025, 1028,1029,1040,1041,1044,1045,1088,1089,1092,1093,1104,1105, 1108,1280,1281,1284,1285,1296,1297,1300,1344,1345,1348,1360, 4096,4097,4100,4101,4112,4113,4116,4117,4160,4161,4164,4165, 4176,4177,4180,4352,4353,4356,4357,4368,4369,4372,4416,4417, 4420,4432,5120,5121,5124,5125,5136,5137,5140,5184,5185,5188, 5200,5376,5377,5380,5392,5440,16384,16385,16388,16389,16400, 16401,16404,16405,16448,16449,16452,16453,16464,16465,16468, 16640,16641,16644,16645,16656,16657,16660,16704,16705,16708, 16720,17408,17409,17412,17413,17424,17425,17428,17472,17473, 17476,17488,17664,17665,17668,17680,17728,20480,20481,20484, 20485,20496,20497,20500,20544,20545,20548,20560,20736,20737, 20740,20752,20800,21504,21505,21508,21520,21568,21760 }; static unsigned char GroupLiterals[163][4] = { {0}, {0}, {1}, {0,1}, {2}, {0,2}, {1,2}, {0,1,2}, {3}, {0,3}, {1,3}, {0,1,3}, {2,3}, {0,2,3}, {1,2,3}, {0,1,2,3}, {4}, {0,4}, {1,4}, {0,1,4}, {2,4}, {0,2,4}, {1,2,4}, {0,1,2,4}, {3,4}, {0,3,4}, {1,3,4}, {0,1,3,4}, {2,3,4}, {0,2,3,4}, {1,2,3,4}, {5}, {0,5}, {1,5}, {0,1,5}, {2,5}, {0,2,5}, {1,2,5}, {0,1,2,5}, {3,5}, {0,3,5}, {1,3,5}, {0,1,3,5}, {2,3,5}, {0,2,3,5}, {1,2,3,5}, {4,5}, {0,4,5}, {1,4,5}, {0,1,4,5}, {2,4,5}, {0,2,4,5}, {1,2,4,5}, {3,4,5}, {0,3,4,5}, {1,3,4,5}, {2,3,4,5}, {6}, {0,6}, {1,6}, {0,1,6}, {2,6}, {0,2,6}, {1,2,6}, {0,1,2,6}, {3,6}, {0,3,6}, {1,3,6}, {0,1,3,6}, {2,3,6}, {0,2,3,6}, {1,2,3,6}, {4,6}, {0,4,6}, {1,4,6}, {0,1,4,6}, {2,4,6}, {0,2,4,6}, {1,2,4,6}, {3,4,6}, {0,3,4,6}, {1,3,4,6}, {2,3,4,6}, {5,6}, {0,5,6}, {1,5,6}, {0,1,5,6}, {2,5,6}, {0,2,5,6}, {1,2,5,6}, {3,5,6}, {0,3,5,6}, {1,3,5,6}, {2,3,5,6}, {4,5,6}, {0,4,5,6}, {1,4,5,6}, {2,4,5,6}, {3,4,5,6}, {7}, {0,7}, {1,7}, {0,1,7}, {2,7}, {0,2,7}, {1,2,7}, {0,1,2,7}, {3,7}, {0,3,7}, {1,3,7}, {0,1,3,7}, {2,3,7}, {0,2,3,7}, {1,2,3,7}, {4,7}, {0,4,7}, {1,4,7}, {0,1,4,7}, {2,4,7}, {0,2,4,7}, {1,2,4,7}, {3,4,7}, {0,3,4,7}, {1,3,4,7}, {2,3,4,7}, {5,7}, {0,5,7}, {1,5,7}, {0,1,5,7}, {2,5,7}, {0,2,5,7}, {1,2,5,7}, {3,5,7}, {0,3,5,7}, {1,3,5,7}, {2,3,5,7}, {4,5,7}, {0,4,5,7}, {1,4,5,7}, {2,4,5,7}, {3,4,5,7}, {6,7}, {0,6,7}, {1,6,7}, {0,1,6,7}, {2,6,7}, {0,2,6,7}, {1,2,6,7}, {3,6,7}, {0,3,6,7}, {1,3,6,7}, {2,3,6,7}, {4,6,7}, {0,4,6,7}, {1,4,6,7}, {2,4,6,7}, {3,4,6,7}, {5,6,7}, {0,5,6,7}, {1,5,6,7}, {2,5,6,7}, {3,5,6,7}, {4,5,6,7} }; // the bit count to 16-bit numbers #define FULL16BITS 0x10000 #define MARKNUMBER 200 static unsigned char BitGroupNumbers[FULL16BITS]; unsigned char BitCount[FULL16BITS]; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// void PrepareBitSetModule() // this function should be called before anything is done with the cube cover { // prepare bit count int i, k; int nLimit; nLimit = FULL16BITS; for ( i = 0; i < nLimit; i++ ) { BitCount[i] = BitCount8[ i & 0xff ] + BitCount8[ i>>8 ]; BitGroupNumbers[i] = MARKNUMBER; } // prepare bit groups for ( k = 0; k < 163; k++ ) BitGroupNumbers[ SparseNumbers[k] ] = k; /* // verify bit groups int n = 4368; char Buff[100]; cout << "The number is " << n << endl; cout << "The binary is " << itoa(n,Buff,2) << endl; cout << "BitGroupNumbers[n] is " << (int)BitGroupNumbers[n] << endl; cout << "The group literals are "; for ( int g = 0; g < 4; g++ ) cout << " " << (int)GroupLiterals[BitGroupNumbers[n]][g]; */ } //////////////////////////////////////////////////////////////////////// /// INLINE FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /* int VarWord( int element ) { return ( element >> LOGBPI ); } int VarBit( int element ) { return ( element & BPIMASK ); } */ varvalue GetVar( Cube * pC, int Var ) // returns VAR_NEG if var is neg, VAR_POS if var is pos, VAR_ABS if var is absent { int Bit = (Var<<1); int Value = ((pC->pCubeDataIn[VarWord(Bit)] >> VarBit(Bit)) & 3); assert( Value == VAR_NEG || Value == VAR_POS || Value == VAR_ABS ); return (varvalue)Value; } void ExorVar( Cube * pC, int Var, varvalue Val ) // EXORs the value Val with the value of variable Var in the given cube // ((cube[VAR_WORD((v)<<1)]) ^ ( (pol)<pCubeDataIn[VarWord(Bit)] ^= ( Val << VarBit(Bit) ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static int DiffVarCounter, cVars; static drow Temp1, Temp2, Temp; static drow LastNonZeroWord; static int LastNonZeroWordNum; int GetDistance( Cube * pC1, Cube * pC2 ) // finds and returns the distance between two cubes pC1 and pC2 { int i; DiffVarCounter = 0; for ( i = 0; i < g_CoverInfo.nWordsIn; i++ ) { Temp1 = pC1->pCubeDataIn[i] ^ pC2->pCubeDataIn[i]; Temp2 = (Temp1|(Temp1>>1)) & DIFFERENT; // count how many bits are one in this var difference DiffVarCounter += BIT_COUNT(Temp2); if ( DiffVarCounter > 4 ) return 5; } // check whether the output parts are different for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) if ( pC1->pCubeDataOut[i] ^ pC2->pCubeDataOut[i] ) { DiffVarCounter++; break; } return DiffVarCounter; } // place to put the number of the different variable and its value in the second cube extern int s_DiffVarNum; extern int s_DiffVarValueP_old; extern int s_DiffVarValueP_new; extern int s_DiffVarValueQ; int GetDistancePlus( Cube * pC1, Cube * pC2 ) // finds and returns the distance between two cubes pC1 and pC2 // if the distance is 1, returns the number of diff variable in VarNum { int i; DiffVarCounter = 0; LastNonZeroWordNum = -1; for ( i = 0; i < g_CoverInfo.nWordsIn; i++ ) { Temp1 = pC1->pCubeDataIn[i] ^ pC2->pCubeDataIn[i]; Temp2 = (Temp1|(Temp1>>1)) & DIFFERENT; // save the value of var difference, in case // the distance is one and we need to return the var number if ( Temp2 ) { LastNonZeroWordNum = i; LastNonZeroWord = Temp2; } // count how many bits are one in this var difference DiffVarCounter += BIT_COUNT(Temp2); if ( DiffVarCounter > 4 ) return 5; } // check whether the output parts are different for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) if ( pC1->pCubeDataOut[i] ^ pC2->pCubeDataOut[i] ) { DiffVarCounter++; break; } if ( DiffVarCounter == 1 ) { if ( LastNonZeroWordNum == -1 ) // the output is the only different variable s_DiffVarNum = -1; else { Temp = (LastNonZeroWord>>2); for ( i = 0; Temp; Temp>>=2, i++ ); s_DiffVarNum = LastNonZeroWordNum*BPI/2 + i; // save the old var value s_DiffVarValueP_old = GetVar( pC1, s_DiffVarNum ); s_DiffVarValueQ = GetVar( pC2, s_DiffVarNum ); // EXOR this value with the corresponding value in p cube ExorVar( pC1, s_DiffVarNum, (varvalue)s_DiffVarValueQ ); s_DiffVarValueP_new = GetVar( pC1, s_DiffVarNum ); } } return DiffVarCounter; } int FindDiffVars( int * pDiffVars, Cube * pC1, Cube * pC2 ) // determine different variables in two cubes and // writes them into pDiffVars[] // -1 is written into pDiffVars[0] if the cubes have different outputs // returns the number of different variables (including the output) { int i, v; DiffVarCounter = 0; // check whether the output parts of the cubes are different for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) if ( pC1->pCubeDataOut[i] != pC2->pCubeDataOut[i] ) { // they are different pDiffVars[0] = -1; DiffVarCounter = 1; break; } for ( i = 0; i < g_CoverInfo.nWordsIn; i++ ) { Temp1 = pC1->pCubeDataIn[i] ^ pC2->pCubeDataIn[i]; Temp2 = (Temp1|(Temp1>>1)) & DIFFERENT; // check the first part of this word Temp = Temp2 & 0xffff; cVars = BitCount[ Temp ]; if ( cVars ) { if ( cVars < 5 ) for ( v = 0; v < cVars; v++ ) { assert( BitGroupNumbers[Temp] != MARKNUMBER ); pDiffVars[ DiffVarCounter++ ] = i*16 + GroupLiterals[ BitGroupNumbers[Temp] ][v]; } else return 5; } if ( DiffVarCounter > 4 ) return 5; // check the second part of this word Temp = Temp2 >> 16; cVars = BitCount[ Temp ]; if ( cVars ) { if ( cVars < 5 ) for ( v = 0; v < cVars; v++ ) { assert( BitGroupNumbers[Temp] != MARKNUMBER ); pDiffVars[ DiffVarCounter++ ] = i*16 + 8 + GroupLiterals[ BitGroupNumbers[Temp] ][v]; } else return 5; } if ( DiffVarCounter > 4 ) return 5; } return DiffVarCounter; } void InsertVars( Cube * pC, int * pVars, int nVarsIn, int * pVarValues ) // corrects the given number of variables (nVarsIn) in pC->pCubeDataIn[] // variable numbers are given in pVarNumbers[], their values are in pVarValues[] // arrays pVarNumbers[] and pVarValues[] are provided by the user { int GlobalBit; int LocalWord; int LocalBit; int i; assert( nVarsIn > 0 && nVarsIn <= g_CoverInfo.nVarsIn ); for ( i = 0; i < nVarsIn; i++ ) { assert( pVars[i] >= 0 && pVars[i] < g_CoverInfo.nVarsIn ); assert( pVarValues[i] == VAR_NEG || pVarValues[i] == VAR_POS || pVarValues[i] == VAR_ABS ); GlobalBit = (pVars[i]<<1); LocalWord = VarWord(GlobalBit); LocalBit = VarBit(GlobalBit); // correct this variables pC->pCubeDataIn[LocalWord] = ((pC->pCubeDataIn[LocalWord]&(~(3<pCubeDataIn[] // variable numbers are given in pVarNumbers[], their values are in pVarValues[] // arrays pVarNumbers[] and pVarValues[] are provided by the user { int GlobalBit; int LocalWord; int LocalBit; int i; assert( nVarsIn > 0 && nVarsIn <= g_CoverInfo.nVarsIn ); for ( i = 0; i < nVarsIn; i++ ) { assert( pVars[i] >= 0 && pVars[i] < g_CoverInfo.nVarsIn ); assert( pVarValues[i] == VAR_NEG || pVarValues[i] == VAR_POS || pVarValues[i] == VAR_ABS ); GlobalBit = (pVars[i]<<1); LocalWord = VarWord(GlobalBit); LocalBit = VarBit(GlobalBit); // correct this variables pC->pCubeDataIn[LocalWord] |= ( pVarValues[i] << LocalBit ); } // insert the output bit pC->pCubeDataOut[VarWord(Output)] |= ( 1 << VarBit(Output) ); } /////////////////////////////////////////////////////////////////// //////////// End of File ///////////////// /////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/exorCubes.c000066400000000000000000000155721300674244400240400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [exorCubes.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Exclusive sum-of-product minimization.] Synopsis [Cube manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: exorCubes.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// /// /// Implementation of EXORCISM - 4 /// /// An Exclusive Sum-of-Product Minimizer /// /// /// /// Alan Mishchenko /// /// /// //////////////////////////////////////////////////////////////////////// /// /// /// Cube Allocation and Free Cube Management /// /// /// /// Ver. 1.0. Started - July 18, 2000. Last update - July 20, 2000 /// /// Ver. 1.1. Started - July 24, 2000. Last update - July 29, 2000 /// /// Ver. 1.2. Started - July 30, 2000. Last update - July 30, 2000 /// /// Ver. 1.5. Started - Aug 19, 2000. Last update - Aug 19, 2000 /// /// /// //////////////////////////////////////////////////////////////////////// /// This software was tested with the BDD package "CUDD", v.2.3.0 /// /// by Fabio Somenzi /// /// http://vlsi.colorado.edu/~fabio/ /// //////////////////////////////////////////////////////////////////////// #include "exor.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// EXTERNAL FUNCTIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// EXTERNAL VARIABLES /// //////////////////////////////////////////////////////////////////////// // information about the cube cover before and after simplification extern cinfo g_CoverInfo; //////////////////////////////////////////////////////////////////////// /// FUNCTIONS OF THIS MODULE /// //////////////////////////////////////////////////////////////////////// // cube cover memory allocation/delocation procedures // (called from the ExorMain module) int AllocateCover( int nCubes, int nWordsIn, int nWordsOut ); void DelocateCover(); // manipulation of the free cube list // (called from Pseudo-Kronecker, ExorList, and ExorLink modules) void AddToFreeCubes( Cube * pC ); Cube * GetFreeCube(); //////////////////////////////////////////////////////////////////////// /// EXPORTED VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// // the pointer to the allocated memory Cube ** s_pCoverMemory; // the list of free cubes Cube * s_CubesFree; /////////////////////////////////////////////////////////////////// /// CUBE COVER MEMORY MANAGEMENT // /////////////////////////////////////////////////////////////////// int AllocateCover( int nCubes, int nWordsIn, int nWordsOut ) // uses the cover parameters nCubes and nWords // to allocate-and-clean the cover in one large piece { int OneCubeSize; int OneInputSetSize; Cube ** pp; int TotalSize; int i, k; // determine the size of one cube WITH storage for bits OneCubeSize = sizeof(Cube) + (nWordsIn+nWordsOut)*sizeof(unsigned); // determine what is the amount of storage for the input part of the cube OneInputSetSize = nWordsIn*sizeof(unsigned); // allocate memory for the array of pointers pp = (Cube **)ABC_ALLOC( Cube *, nCubes ); if ( pp == NULL ) return 0; // determine the size of the total cube cover TotalSize = nCubes*OneCubeSize; // allocate and clear memory for the cover in one large piece pp[0] = (Cube *)ABC_ALLOC( char, TotalSize ); if ( pp[0] == NULL ) return 0; memset( pp[0], 0, TotalSize ); // assign pointers to cubes and bit strings inside this piece pp[0]->pCubeDataIn = (unsigned*)(pp[0] + 1); pp[0]->pCubeDataOut = (unsigned*)((char*)pp[0]->pCubeDataIn + OneInputSetSize); for ( i = 1; i < nCubes; i++ ) { pp[i] = (Cube *)((char*)pp[i-1] + OneCubeSize); pp[i]->pCubeDataIn = (unsigned*)(pp[i] + 1); pp[i]->pCubeDataOut = (unsigned*)((char*)pp[i]->pCubeDataIn + OneInputSetSize); } // connect the cubes into the list using Next pointers for ( k = 0; k < nCubes-1; k++ ) pp[k]->Next = pp[k+1]; // the last pointer is already set to NULL // assign the head of the free list s_CubesFree = pp[0]; // set the counters of the used and free cubes g_CoverInfo.nCubesInUse = 0; g_CoverInfo.nCubesFree = nCubes; // save the pointer to the allocated memory s_pCoverMemory = pp; assert ( g_CoverInfo.nCubesInUse + g_CoverInfo.nCubesFree == g_CoverInfo.nCubesAlloc ); return nCubes*sizeof(Cube *) + TotalSize; } void DelocateCover() { ABC_FREE( s_pCoverMemory[0] ); ABC_FREE( s_pCoverMemory ); } /////////////////////////////////////////////////////////////////// /// FREE CUBE LIST MANIPULATION FUNCTIONS /// /////////////////////////////////////////////////////////////////// void AddToFreeCubes( Cube * p ) { assert( p ); assert( p->Prev == NULL ); // the cube should not be in use assert( p->Next == NULL ); assert( p->ID ); p->Next = s_CubesFree; s_CubesFree = p; // set the ID of the cube to 0, // so that cube pair garbage collection could recognize it as different p->ID = 0; g_CoverInfo.nCubesFree++; } Cube * GetFreeCube() { Cube * p; assert( s_CubesFree ); p = s_CubesFree; s_CubesFree = s_CubesFree->Next; p->Next = NULL; g_CoverInfo.nCubesFree--; return p; } /////////////////////////////////////////////////////////////////// //////////// End of File ///////////////// /////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/exorLink.c000066400000000000000000000705451300674244400236750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [exorLink.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Exclusive sum-of-product minimization.] Synopsis [Cube iterators.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: exorLink.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// /// /// Implementation of EXORCISM - 4 /// /// An Exclusive Sum-of-Product Minimizer /// /// /// /// Alan Mishchenko /// /// /// //////////////////////////////////////////////////////////////////////// /// /// /// Generation of ExorLinked Cubes /// /// /// /// Ver. 1.0. Started - July 26, 2000. Last update - July 29, 2000 /// /// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 12, 2000 /// /// /// //////////////////////////////////////////////////////////////////////// /// This software was tested with the BDD package "CUDD", v.2.3.0 /// /// by Fabio Somenzi /// /// http://vlsi.colorado.edu/~fabio/ /// //////////////////////////////////////////////////////////////////////// #include "exor.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define LARGE_NUM 1000000 //////////////////////////////////////////////////////////////////////// /// EXTERNAL FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTIONS OF THIS MODULE /// //////////////////////////////////////////////////////////////////////// int ExorLinkCubeIteratorStart( Cube** pGroup, Cube* pC1, Cube* pC2, cubedist Dist ); // this function starts the Exor-Link iterator, which iterates // through the cube groups starting from the group with min literals // returns 1 on success, returns 0 if the cubes have wrong distance int ExorLinkCubeIteratorNext( Cube** pGroup ); // give the next group in the decreasing order of sum of literals // returns 1 on success, returns 0 if there are no more groups int ExorLinkCubeIteratorPick( Cube** pGroup, int g ); // gives the group #g in the order in which the groups were given // during iteration // returns 1 on success, returns 0 if something g is too large void ExorLinkCubeIteratorCleanUp( int fTakeLastGroup ); // removes the cubes from the store back into the list of free cubes // if fTakeLastGroup is 0, removes all cubes // if fTakeLastGroup is 1, does not store the last group //////////////////////////////////////////////////////////////////////// /// EXTERNAL VARIABLES /// //////////////////////////////////////////////////////////////////////// // information about the cube cover before extern cinfo g_CoverInfo; // new IDs are assigned only when it is known that the cubes are useful // this is done in ExorLinkCubeIteratorCleanUp(); // the head of the list of free cubes extern Cube* g_CubesFree; extern byte BitCount[]; //////////////////////////////////////////////////////////////////////// /// EXORLINK INFO /// //////////////////////////////////////////////////////////////////////// const int s_ELMax = 4; // ExorLink-2: there are 4 cubes, 2 literals each, combined into 2 groups // ExorLink-3: there are 12 cubes, 3 literals each, combined into 6 groups // ExorLink-4: there are 32 cubes, 4 literals each, combined into 24 groups // ExorLink-5: there are 80 cubes, 5 literals each, combined into 120 groups // Exorlink-n: there are n*2^(n-1) cubes, n literals each, combined into n! groups const int s_ELnCubes[4] = { 4, 12, 32, 80 }; const int s_ELnGroups[4] = { 2, 6, 24, 120 }; // value sets of cubes X{a0}Y{b0}Z{c0}U{d0} and X{a1}Y{b1}Z{c1}U{d1} // used to represent the ExorLink cube generation rules enum { vs0, vs1, vsX }; // vs0 = 0, // the value set of the first cube // vs1 = 1, // the value set of the second cube // vsX = 2 // EXOR of the value sets of the first and second cubes // representation of ExorLinked cubes static int s_ELCubeRules[3][32][4] = { { // ExorLink-2 Cube Generating Rules // | 0 | 1 | - sections // |-------| {vsX,vs0}, // cube 0 | | | {vsX,vs1}, // cube 1 | | 0 | {vs0,vsX}, // cube 2 | | | {vs1,vsX} // cube 3 | 0 | | }, { // ExorLink-3 Cube Generating Rules // | 0 | 1 | 2 | - sections // |-----------| {vsX,vs0,vs0}, // cube 0 | | | | {vsX,vs0,vs1}, // cube 1 | | | 0 | {vsX,vs1,vs0}, // cube 2 | | 0 | | {vsX,vs1,vs1}, // cube 3 | | 1 | 1 | {vs0,vsX,vs0}, // cube 4 | | | | {vs0,vsX,vs1}, // cube 5 | | | 2 | {vs1,vsX,vs0}, // cube 6 | 0 | | | {vs1,vsX,vs1}, // cube 7 | 1 | | 3 | {vs0,vs0,vsX}, // cube 8 | | | | {vs0,vs1,vsX}, // cube 9 | | 2 | | {vs1,vs0,vsX}, // cube 10 | 2 | | | {vs1,vs1,vsX} // cube 11 | 3 | 3 | | }, { // ExorLink-4 Rules Generating Rules // | 0 | 1 | 2 | 4 | - sections // |---------------| {vsX,vs0,vs0,vs0}, // cube 0 | | | | | {vsX,vs0,vs0,vs1}, // cube 1 | | | | 0 | {vsX,vs0,vs1,vs0}, // cube 2 | | | 0 | | {vsX,vs0,vs1,vs1}, // cube 3 | | | 1 | 1 | {vsX,vs1,vs0,vs0}, // cube 4 | | 0 | | | {vsX,vs1,vs0,vs1}, // cube 5 | | 1 | | 2 | {vsX,vs1,vs1,vs0}, // cube 6 | | 2 | 2 | | {vsX,vs1,vs1,vs1}, // cube 7 | | 3 | 3 | 3 | {vs0,vsX,vs0,vs0}, // cube 8 | | | | | {vs0,vsX,vs0,vs1}, // cube 9 | | | | 4 | {vs0,vsX,vs1,vs0}, // cube 10 | | | 4 | | {vs0,vsX,vs1,vs1}, // cube 11 | | | 5 | 5 | {vs1,vsX,vs0,vs0}, // cube 12 | 0 | | | | {vs1,vsX,vs0,vs1}, // cube 13 | 1 | | | 6 | {vs1,vsX,vs1,vs0}, // cube 14 | 2 | | 6 | | {vs1,vsX,vs1,vs1}, // cube 15 | 3 | | 7 | 7 | {vs0,vs0,vsX,vs0}, // cube 16 | | | | | {vs0,vs0,vsX,vs1}, // cube 17 | | | | 8 | {vs0,vs1,vsX,vs0}, // cube 18 | | 4 | | | {vs0,vs1,vsX,vs1}, // cube 19 | | 5 | | 9 | {vs1,vs0,vsX,vs0}, // cube 20 | 4 | | | | {vs1,vs0,vsX,vs1}, // cube 21 | 5 | | | 10| {vs1,vs1,vsX,vs0}, // cube 22 | 6 | 6 | | | {vs1,vs1,vsX,vs1}, // cube 23 | 7 | 7 | | 11| {vs0,vs0,vs0,vsX}, // cube 24 | | | | | {vs0,vs0,vs1,vsX}, // cube 25 | | | 8 | | {vs0,vs1,vs0,vsX}, // cube 26 | | 8 | | | {vs0,vs1,vs1,vsX}, // cube 27 | | 9 | 9 | | {vs1,vs0,vs0,vsX}, // cube 28 | 8 | | | | {vs1,vs0,vs1,vsX}, // cube 29 | 9 | | 10| | {vs1,vs1,vs0,vsX}, // cube 30 | 10| 10| | | {vs1,vs1,vs1,vsX} // cube 31 | 11| 11| 11| | } }; // these cubes are combined into groups static int s_ELGroupRules[3][24][4] = { { // ExorLink-2 Group Forming Rules {0,3}, // group 0 - section 0 {2,1} // group 1 - section 1 }, { // ExorLink-3 Group Forming Rules {0,6,11}, // group 0 - section 0 {0,7,10}, // group 1 {4,2,11}, // group 2 - section 1 {4,3,9}, // group 3 {8,1,7}, // group 4 - section 2 {8,3,5} // group 5 }, { // ExorLink-4 Group Forming Rules // section 0: (0-12)(1-13)(2-14)(3-15)(4-20)(5-21)(6-22)(7-23)(8-28)(9-29)(10-30)(11-31) {0,12,22,31}, // group 0 // {0,6,11}, // group 0 - section 0 {0,12,23,30}, // group 1 // {0,7,10}, // group 1 {0,20,14,31}, // group 2 // {4,2,11}, // group 2 {0,20,15,29}, // group 3 // {4,3,9}, // group 3 {0,28,13,23}, // group 4 // {8,1,7}, // group 4 {0,28,15,21}, // group 5 // {8,3,5} // group 5 // section 1: (0-4)(1-5)(2-6)(3-7)(4-18)(5-19)(6-22)(7-23)(8-26)(9-27)(10-30)(11-31) {8,4,22,31}, // group 6 {8,4,23,30}, // group 7 {8,18,6,31}, // group 8 {8,18,7,27}, // group 9 {8,26,5,23}, // group 10 {8,26,7,19}, // group 11 // section 2: (0-2)(1-3)(2-6)(3-7)(4-10)(5-11)(6-14)(7-15)(8-25)(9-27)(10-29)(11-31) {16,2,14,31}, // group 12 {16,2,15,29}, // group 13 {16,10,6,31}, // group 14 {16,10,7,27}, // group 15 {16,25,3,15}, // group 16 {16,25,7,11}, // group 17 // section 3: (0-1)(1-3)(2-5)(3-7)(4-9)(5-11)(6-13)(7-15)(8-17)(9-19)(10-21)(11-23) {24,1,13,23}, // group 18 {24,1,15,21}, // group 19 {24,9, 5,23}, // group 20 {24,9, 7,19}, // group 21 {24,17,3,15}, // group 22 {24,17,7,11} // group 23 } }; // it is assumed that if literals in the first cube, second cube // and their EXOR are 0 or 1 (as opposed to -), they are written // into a mask, which is used to count the number of literals in // the cube groups cubes // // below is the set of masks selecting literals belonging // to the given cube of the group static drow s_CubeLitMasks[3][32] = { { // ExorLink-2 Literal Counting Masks // v3 v2 v1 v0 // -xBA -xBA -xBA -xBA // ------------------- 0x14, // cube 0 <0000 0000 0001 0100> {vsX,vs0} 0x24, // cube 1 <0000 0000 0010 0100> {vsX,vs1} 0x41, // cube 2 <0000 0000 0100 0001> {vs0,vsX} 0x42, // cube 3 <0000 0000 0100 0010> {vs1,vsX} }, { // ExorLink-3 Literal Counting Masks 0x114, // cube 0 <0000 0001 0001 0100> {vsX,vs0,vs0} 0x214, // cube 1 <0000 0010 0001 0100> {vsX,vs0,vs1} 0x124, // cube 2 <0000 0001 0010 0100> {vsX,vs1,vs0} 0x224, // cube 3 <0000 0010 0010 0100> {vsX,vs1,vs1} 0x141, // cube 4 <0000 0001 0100 0001> {vs0,vsX,vs0} 0x241, // cube 5 <0000 0010 0100 0001> {vs0,vsX,vs1} 0x142, // cube 6 <0000 0001 0100 0010> {vs1,vsX,vs0} 0x242, // cube 7 <0000 0010 0100 0010> {vs1,vsX,vs1} 0x411, // cube 8 <0000 0100 0001 0001> {vs0,vs0,vsX} 0x421, // cube 9 <0000 0100 0010 0001> {vs0,vs1,vsX} 0x412, // cube 10 <0000 0100 0001 0010> {vs1,vs0,vsX} 0x422, // cube 11 <0000 0100 0010 0010> {vs1,vs1,vsX} }, { // ExorLink-4 Literal Counting Masks 0x1114, // cube 0 <0001 0001 0001 0100> {vsX,vs0,vs0,vs0} 0x2114, // cube 1 <0010 0001 0001 0100> {vsX,vs0,vs0,vs1} 0x1214, // cube 2 <0001 0010 0001 0100> {vsX,vs0,vs1,vs0} 0x2214, // cube 3 <0010 0010 0001 0100> {vsX,vs0,vs1,vs1} 0x1124, // cube 4 <0001 0001 0010 0100> {vsX,vs1,vs0,vs0} 0x2124, // cube 5 <0010 0001 0010 0100> {vsX,vs1,vs0,vs1} 0x1224, // cube 6 <0001 0010 0010 0100> {vsX,vs1,vs1,vs0} 0x2224, // cube 7 <0010 0010 0010 0100> {vsX,vs1,vs1,vs1} 0x1141, // cube 8 <0001 0001 0100 0001> {vs0,vsX,vs0,vs0} 0x2141, // cube 9 <0010 0001 0100 0001> {vs0,vsX,vs0,vs1} 0x1241, // cube 10 <0001 0010 0100 0001> {vs0,vsX,vs1,vs0} 0x2241, // cube 11 <0010 0010 0100 0001> {vs0,vsX,vs1,vs1} 0x1142, // cube 12 <0001 0001 0100 0010> {vs1,vsX,vs0,vs0} 0x2142, // cube 13 <0010 0001 0100 0010> {vs1,vsX,vs0,vs1} 0x1242, // cube 14 <0001 0010 0100 0010> {vs1,vsX,vs1,vs0} 0x2242, // cube 15 <0010 0010 0100 0010> {vs1,vsX,vs1,vs1} 0x1411, // cube 16 <0001 0100 0001 0001> {vs0,vs0,vsX,vs0} 0x2411, // cube 17 <0010 0100 0001 0001> {vs0,vs0,vsX,vs1} 0x1421, // cube 18 <0001 0100 0010 0001> {vs0,vs1,vsX,vs0} 0x2421, // cube 19 <0010 0100 0010 0001> {vs0,vs1,vsX,vs1} 0x1412, // cube 20 <0001 0100 0001 0010> {vs1,vs0,vsX,vs0} 0x2412, // cube 21 <0010 0100 0001 0010> {vs1,vs0,vsX,vs1} 0x1422, // cube 22 <0001 0100 0010 0010> {vs1,vs1,vsX,vs0} 0x2422, // cube 23 <0010 0100 0010 0010> {vs1,vs1,vsX,vs1} 0x4111, // cube 24 <0100 0001 0001 0001> {vs0,vs0,vs0,vsX} 0x4211, // cube 25 <0100 0010 0001 0001> {vs0,vs0,vs1,vsX} 0x4121, // cube 26 <0100 0001 0010 0001> {vs0,vs1,vs0,vsX} 0x4221, // cube 27 <0100 0010 0010 0001> {vs0,vs1,vs1,vsX} 0x4112, // cube 28 <0100 0001 0001 0010> {vs1,vs0,vs0,vsX} 0x4212, // cube 29 <0100 0010 0001 0010> {vs1,vs0,vs1,vsX} 0x4122, // cube 30 <0100 0001 0010 0010> {vs1,vs1,vs0,vsX} 0x4222, // cube 31 <0100 0010 0010 0010> {vs1,vs1,vs1,vsX} } }; static drow s_BitMasks[32] = { 0x00000001,0x00000002,0x00000004,0x00000008, 0x00000010,0x00000020,0x00000040,0x00000080, 0x00000100,0x00000200,0x00000400,0x00000800, 0x00001000,0x00002000,0x00004000,0x00008000, 0x00010000,0x00020000,0x00040000,0x00080000, 0x00100000,0x00200000,0x00400000,0x00800000, 0x01000000,0x02000000,0x04000000,0x08000000, 0x10000000,0x20000000,0x40000000,0x80000000 }; //////////////////////////////////////////////////////////////////////// /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// // this flag is TRUE as long as the storage is allocated static int fWorking; // set these flags to have minimum literal groups generated first static int fMinLitGroupsFirst[4] = { 0 /*dist2*/, 0 /*dist3*/, 0 /*dist4*/}; static int nDist; static int nCubes; static int nCubesInGroup; static int nGroups; static Cube *pCA, *pCB; // storage for variable numbers that are different in the cubes static int DiffVars[5]; static int* pDiffVars; static int nDifferentVars; // storage for the bits and words of different input variables static int nDiffVarsIn; static int DiffVarWords[5]; static int DiffVarBits[5]; // literal mask used to count the number of literals in the cubes static drow MaskLiterals; // the base for counting literals static int StartingLiterals; // the number of literals in each cube static int CubeLiterals[32]; static int BitShift; static int DiffVarValues[4][3]; static int Value; // the sorted array of groups in the increasing order of costs static int GroupCosts[32]; static int GroupCostBest; static int GroupCostBestNum; static int CubeNum; static int NewZ; static drow Temp; // the cubes currently created static Cube* ELCubes[32]; // the bit string with 1's corresponding to cubes in ELCubes[] // that constitute the last group static drow LastGroup; static int GroupOrder[24]; static drow VisitedGroups; static int nVisitedGroups; //int RemainderBits = (nVars*2)%(sizeof(drow)*8); //int TotalWords = (nVars*2)/(sizeof(drow)*8) + (RemainderBits > 0); static drow DammyBitData[(MAXVARS*2)/(sizeof(drow)*8)+(MAXVARS*2)%(sizeof(drow)*8)]; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINTIONS /// //////////////////////////////////////////////////////////////////////// // IDEA! if we already used a cube to count distances and it did not improve // there is no need to try it again with other group // (this idea works only for ExorLink-2 and -3) int ExorLinkCubeIteratorStart( Cube** pGroup, Cube* pC1, Cube* pC2, cubedist Dist ) // this function starts the Exor-Link iterator, which iterates // through the cube groups starting from the group with min literals // returns 1 on success, returns 0 if the cubes have wrong distance { int i, c; // check that everything is okey assert( pC1 != NULL ); assert( pC2 != NULL ); assert( !fWorking ); nDist = Dist; nCubes = Dist + 2; nCubesInGroup = s_ELnCubes[nDist]; nGroups = s_ELnGroups[Dist]; pCA = pC1; pCB = pC2; // find what variables are different in these two cubes // FindDiffVars returns DiffVars[0] < 0, if the output is different nDifferentVars = FindDiffVars( DiffVars, pCA, pCB ); if ( nCubes != nDifferentVars ) { // cout << "ExorLinkCubeIterator(): Distance mismatch"; // cout << " nCubes = " << nCubes << " nDiffVars = " << nDifferentVars << endl; fWorking = 0; return 0; } // copy the input variable cube data into DammyBitData[] for ( i = 0; i < g_CoverInfo.nWordsIn; i++ ) DammyBitData[i] = pCA->pCubeDataIn[i]; // find the number of different input variables nDiffVarsIn = ( DiffVars[0] >= 0 )? nCubes: nCubes-1; // assign the pointer to the place where the number of diff input vars is stored pDiffVars = ( DiffVars[0] >= 0 )? DiffVars: DiffVars+1; // find the bit offsets and remove different variables for ( i = 0; i < nDiffVarsIn; i++ ) { DiffVarWords[i] = ((2*pDiffVars[i]) >> LOGBPI) ; DiffVarBits[i] = ((2*pDiffVars[i]) & BPIMASK); // clear this position DammyBitData[ DiffVarWords[i] ] &= ~( 3 << DiffVarBits[i] ); } // extract the values from the cubes and create the mask of literals MaskLiterals = 0; // initialize the base for literal counts StartingLiterals = pCA->a; for ( i = 0, BitShift = 0; i < nDiffVarsIn; i++, BitShift++ ) { DiffVarValues[i][0] = ( pCA->pCubeDataIn[DiffVarWords[i]] >> DiffVarBits[i] ) & 3; if ( DiffVarValues[i][0] != VAR_ABS ) { MaskLiterals |= ( 1 << BitShift ); // update the base for literal counts StartingLiterals--; } BitShift++; DiffVarValues[i][1] = ( pCB->pCubeDataIn[DiffVarWords[i]] >> DiffVarBits[i] ) & 3; if ( DiffVarValues[i][1] != VAR_ABS ) MaskLiterals |= ( 1 << BitShift ); BitShift++; DiffVarValues[i][2] = DiffVarValues[i][0] ^ DiffVarValues[i][1]; if ( DiffVarValues[i][2] != VAR_ABS ) MaskLiterals |= ( 1 << BitShift ); BitShift++; } // count the number of additional literals in each cube of the group for ( i = 0; i < nCubesInGroup; i++ ) CubeLiterals[i] = BitCount[ MaskLiterals & s_CubeLitMasks[Dist][i] ]; // compute the costs of all groups for ( i = 0; i < nGroups; i++ ) // go over all cubes in the group for ( GroupCosts[i] = 0, c = 0; c < nCubes; c++ ) GroupCosts[i] += CubeLiterals[ s_ELGroupRules[Dist][i][c] ]; // find the best cost group if ( fMinLitGroupsFirst[Dist] ) { // find the minimum cost group GroupCostBest = LARGE_NUM; for ( i = 0; i < nGroups; i++ ) if ( GroupCostBest > GroupCosts[i] ) { GroupCostBest = GroupCosts[i]; GroupCostBestNum = i; } } else { // find the maximum cost group GroupCostBest = -1; for ( i = 0; i < nGroups; i++ ) if ( GroupCostBest < GroupCosts[i] ) { GroupCostBest = GroupCosts[i]; GroupCostBestNum = i; } } // create the cubes with min number of literals needed for the group LastGroup = 0; for ( c = 0; c < nCubes; c++ ) { CubeNum = s_ELGroupRules[Dist][GroupCostBestNum][c]; LastGroup |= s_BitMasks[CubeNum]; // bring a cube from the free cube list ELCubes[CubeNum] = GetFreeCube(); // copy the input bit data into the cube for ( i = 0; i < g_CoverInfo.nWordsIn; i++ ) ELCubes[CubeNum]->pCubeDataIn[i] = DammyBitData[i]; // copy the output bit data into the cube NewZ = 0; if ( DiffVars[0] >= 0 ) // the output is not involved in ExorLink { for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) ELCubes[CubeNum]->pCubeDataOut[i] = pCA->pCubeDataOut[i]; NewZ = pCA->z; } else // the output is involved { // determine where the output information comes from Value = s_ELCubeRules[Dist][CubeNum][nDiffVarsIn]; if ( Value == vs0 ) for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) { Temp = pCA->pCubeDataOut[i]; ELCubes[CubeNum]->pCubeDataOut[i] = Temp; NewZ += BIT_COUNT(Temp); } else if ( Value == vs1 ) for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) { Temp = pCB->pCubeDataOut[i]; ELCubes[CubeNum]->pCubeDataOut[i] = Temp; NewZ += BIT_COUNT(Temp); } else if ( Value == vsX ) for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) { Temp = pCA->pCubeDataOut[i] ^ pCB->pCubeDataOut[i]; ELCubes[CubeNum]->pCubeDataOut[i] = Temp; NewZ += BIT_COUNT(Temp); } } // set the variables that should be there for ( i = 0; i < nDiffVarsIn; i++ ) { Value = DiffVarValues[i][ s_ELCubeRules[Dist][CubeNum][i] ]; ELCubes[CubeNum]->pCubeDataIn[ DiffVarWords[i] ] |= ( Value << DiffVarBits[i] ); } // set the number of literals ELCubes[CubeNum]->a = StartingLiterals + CubeLiterals[CubeNum]; ELCubes[CubeNum]->z = NewZ; ELCubes[CubeNum]->q = ComputeQCostBits( ELCubes[CubeNum] ); // assign the ID ELCubes[CubeNum]->ID = g_CoverInfo.cIDs++; // skip through zero-ID if ( g_CoverInfo.cIDs == 256 ) g_CoverInfo.cIDs = 1; // prepare the return array pGroup[c] = ELCubes[CubeNum]; } // mark this group as visited VisitedGroups |= s_BitMasks[ GroupCostBestNum ]; // set the first visited group number GroupOrder[0] = GroupCostBestNum; // increment the counter of visited groups nVisitedGroups = 1; fWorking = 1; return 1; } int ExorLinkCubeIteratorNext( Cube** pGroup ) // give the next group in the decreasing order of sum of literals // returns 1 on success, returns 0 if there are no more groups { int i, c; // check that everything is okey assert( fWorking ); if ( nVisitedGroups == nGroups ) // we have iterated through all groups return 0; // find the min/max cost group if ( fMinLitGroupsFirst[nDist] ) // if ( nCubes == 4 ) { // find the minimum cost // go through all groups GroupCostBest = LARGE_NUM; for ( i = 0; i < nGroups; i++ ) if ( !(VisitedGroups & s_BitMasks[i]) && GroupCostBest > GroupCosts[i] ) { GroupCostBest = GroupCosts[i]; GroupCostBestNum = i; } assert( GroupCostBest != LARGE_NUM ); } else { // find the maximum cost // go through all groups GroupCostBest = -1; for ( i = 0; i < nGroups; i++ ) if ( !(VisitedGroups & s_BitMasks[i]) && GroupCostBest < GroupCosts[i] ) { GroupCostBest = GroupCosts[i]; GroupCostBestNum = i; } assert( GroupCostBest != -1 ); } // create the cubes needed for the group, if they are not created already LastGroup = 0; for ( c = 0; c < nCubes; c++ ) { CubeNum = s_ELGroupRules[nDist][GroupCostBestNum][c]; LastGroup |= s_BitMasks[CubeNum]; if ( ELCubes[CubeNum] == NULL ) // this cube does not exist { // bring a cube from the free cube list ELCubes[CubeNum] = GetFreeCube(); // copy the input bit data into the cube for ( i = 0; i < g_CoverInfo.nWordsIn; i++ ) ELCubes[CubeNum]->pCubeDataIn[i] = DammyBitData[i]; // copy the output bit data into the cube NewZ = 0; if ( DiffVars[0] >= 0 ) // the output is not involved in ExorLink { for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) ELCubes[CubeNum]->pCubeDataOut[i] = pCA->pCubeDataOut[i]; NewZ = pCA->z; } else // the output is involved { // determine where the output information comes from Value = s_ELCubeRules[nDist][CubeNum][nDiffVarsIn]; if ( Value == vs0 ) for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) { Temp = pCA->pCubeDataOut[i]; ELCubes[CubeNum]->pCubeDataOut[i] = Temp; NewZ += BIT_COUNT(Temp); } else if ( Value == vs1 ) for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) { Temp = pCB->pCubeDataOut[i]; ELCubes[CubeNum]->pCubeDataOut[i] = Temp; NewZ += BIT_COUNT(Temp); } else if ( Value == vsX ) for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) { Temp = pCA->pCubeDataOut[i] ^ pCB->pCubeDataOut[i]; ELCubes[CubeNum]->pCubeDataOut[i] = Temp; NewZ += BIT_COUNT(Temp); } } // set the variables that should be there for ( i = 0; i < nDiffVarsIn; i++ ) { Value = DiffVarValues[i][ s_ELCubeRules[nDist][CubeNum][i] ]; ELCubes[CubeNum]->pCubeDataIn[ DiffVarWords[i] ] |= ( Value << DiffVarBits[i] ); } // set the number of literals and output ones ELCubes[CubeNum]->a = StartingLiterals + CubeLiterals[CubeNum]; ELCubes[CubeNum]->z = NewZ; ELCubes[CubeNum]->q = ComputeQCostBits( ELCubes[CubeNum] ); assert( NewZ != 255 ); // assign the ID ELCubes[CubeNum]->ID = g_CoverInfo.cIDs++; // skip through zero-ID if ( g_CoverInfo.cIDs == 256 ) g_CoverInfo.cIDs = 1; } // prepare the return array pGroup[c] = ELCubes[CubeNum]; } // mark this group as visited VisitedGroups |= s_BitMasks[ GroupCostBestNum ]; // set the next visited group number and // increment the counter of visited groups GroupOrder[ nVisitedGroups++ ] = GroupCostBestNum; return 1; } int ExorLinkCubeIteratorPick( Cube** pGroup, int g ) // gives the group #g in the order in which the groups were given // during iteration // returns 1 on success, returns 0 if something is wrong (g is too large) { int GroupNum, c; assert( fWorking ); assert( g >= 0 && g < nGroups ); assert( VisitedGroups & s_BitMasks[g] ); GroupNum = GroupOrder[g]; // form the group LastGroup = 0; for ( c = 0; c < nCubes; c++ ) { CubeNum = s_ELGroupRules[nDist][GroupNum][c]; // remember this group as the last one LastGroup |= s_BitMasks[CubeNum]; assert( ELCubes[CubeNum] != NULL ); // this cube should exist // prepare the return array pGroup[c] = ELCubes[CubeNum]; } return 1; } void ExorLinkCubeIteratorCleanUp( int fTakeLastGroup ) // removes the cubes from the store back into the list of free cubes // if fTakeLastGroup is 0, removes all cubes // if fTakeLastGroup is 1, does not store the last group { int c; assert( fWorking ); // put cubes back // set the cube pointers to zero if ( fTakeLastGroup == 0 ) for ( c = 0; c < nCubesInGroup; c++ ) { ELCubes[c]->fMark = 0; AddToFreeCubes( ELCubes[c] ); ELCubes[c] = NULL; } else for ( c = 0; c < nCubesInGroup; c++ ) if ( ELCubes[c] ) { ELCubes[c]->fMark = 0; if ( (LastGroup & s_BitMasks[c]) == 0 ) // does not belong to the last group AddToFreeCubes( ELCubes[c] ); ELCubes[c] = NULL; } // set the cube groups to zero VisitedGroups = 0; // shut down the iterator fWorking = 0; } /////////////////////////////////////////////////////////////////// //////////// End of File ///////////////// /////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/exorList.c000066400000000000000000001204261300674244400237050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [exorList.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Exclusive sum-of-product minimization.] Synopsis [Cube lists.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: exorList.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// /// /// Implementation of EXORCISM - 4 /// /// An Exclusive Sum-of-Product Minimizer /// /// /// /// Alan Mishchenko /// /// /// //////////////////////////////////////////////////////////////////////// /// /// /// Iterative Cube Set Minimization /// /// Iterative ExorLink Procedure /// /// Support of Cube Pair Queques /// /// /// /// Ver. 1.0. Started - July 18, 2000. Last update - July 20, 2000 /// /// Ver. 1.1. Started - July 24, 2000. Last update - July 29, 2000 /// /// Ver. 1.2. Started - July 30, 2000. Last update - July 31, 2000 /// /// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 26, 2000 /// /// Ver. 1.5. Started - Aug 30, 2000. Last update - Aug 30, 2000 /// /// Ver. 1.6. Started - Sep 11, 2000. Last update - Sep 15, 2000 /// /// Ver. 1.7. Started - Sep 20, 2000. Last update - Sep 23, 2000 /// /// /// //////////////////////////////////////////////////////////////////////// /// This software was tested with the BDD package "CUDD", v.2.3.0 /// /// by Fabio Somenzi /// /// http://vlsi.colorado.edu/~fabio/ /// //////////////////////////////////////////////////////////////////////// #include "exor.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// EXTERNAL VARIABLES /// //////////////////////////////////////////////////////////////////////// // information about options and the cover extern cinfo g_CoverInfo; // the look-up table for the number of 1's in unsigned short extern unsigned char BitCount[]; //////////////////////////////////////////////////////////////////////// /// EXTERNAL FUNCTIONS /// //////////////////////////////////////////////////////////////////////// extern int GetDistance( Cube* pC1, Cube* pC2 ); // distance computation for two cubes extern int GetDistancePlus( Cube* pC1, Cube* pC2 ); extern void ExorVar( Cube* pC, int Var, varvalue Val ); extern void AddToFreeCubes( Cube* pC ); // returns a simplified cube back into the free list //extern void PrintCube( ostream& DebugStream, Cube* pC ); // debug output for cubes extern Cube* GetFreeCube(); //////////////////////////////////////////////////////////////////////// /// ExorLink Functions extern int ExorLinkCubeIteratorStart( Cube** pGroup, Cube* pC1, Cube* pC2, cubedist Dist ); // this function starts the Exor-Link IteratorCubePair, which iterates // through the cube groups starting from the group with min literals // returns 1 on success, returns 0 if the cubes have wrong distance extern int ExorLinkCubeIteratorNext( Cube** pGroup ); // give the next group in the decreasing order of sum of literals // returns 1 on success, returns 0 if there are no more groups extern int ExorLinkCubeIteratorPick( Cube** pGroup, int g ); // gives the group #g in the order in which the groups were given // during iteration // returns 1 on success, returns 0 if something g is too large extern void ExorLinkCubeIteratorCleanUp( int fTakeLastGroup ); // removes the cubes from the store back into the list of free cubes // if fTakeLastGroup is 0, removes all cubes // if fTakeLastGroup is 1, does not store the last group //////////////////////////////////////////////////////////////////////// /// FUNCTIONS OF THIS MODULE /// //////////////////////////////////////////////////////////////////////// // iterative ExorLink int IterativelyApplyExorLink2( char fDistEnable ); int IterativelyApplyExorLink3( char fDistEnable ); int IterativelyApplyExorLink4( char fDistEnable ); // function which performs distance computation and simplifes on the fly // it is also called from the Pseudo-Kronecker module when cubes are added int CheckForCloseCubes( Cube* p, int fAddCube ); int CheckAndInsert( Cube* p ); // this function changes the cube back after it was DIST-1 transformed void UndoRecentChanges(); //////////////////////////////////////////////////////////////////////// // iterating through adjucency pair queques (with authomatic garbage collection) // start an iterator through cubes of dist CubeDist, // the resulting pointers are written into ppC1 and ppC2 int IteratorCubePairStart( cubedist Dist, Cube** ppC1, Cube** ppC2 ); // gives the next VALID cube pair (the previous one is automatically dequequed) int IteratorCubePairNext(); //////////////////////////////////////////////////////////////////////// // the cube storage // cube storage allocation/delocation int AllocateCubeSets( int nVarsIn, int nVarsOut ); void DelocateCubeSets(); // insert/extract a cube into/from the storage void CubeInsert( Cube* p ); Cube* CubeExtract( Cube* p ); //////////////////////////////////////////////////////////////////////// // Cube Set Iterator Cube* IterCubeSetStart(); // starts an iterator that traverses all the cubes in the ring Cube* IterCubeSetNext(); // returns the next cube in the ring // to use it again after it has returned NULL, call IterCubeSetStart() first //////////////////////////////////////////////////////////////////////// // cube adjacency queques // adjacency queque allocation/delocation procedures int AllocateQueques( int nPlaces ); void DelocateQueques(); // conditional adding cube pairs to queques // reset temporarily stored new range of cube pairs static void NewRangeReset(); // add temporarily stored new range of cube pairs to the queque static void NewRangeAdd(); // insert one cube pair into the new range static void NewRangeInsertCubePair( cubedist Dist, Cube* p1, Cube* p2 ); static void MarkSet(); static void MarkRewind(); void PrintQuequeStats(); int GetQuequeStats( cubedist Dist ); // iterating through the queque (with authomatic garbage collection) // start an iterator through cubes of dist CubeDist, // the resulting pointers are written into ppC1 and ppC2 int IteratorCubePairStart( cubedist Dist, Cube** ppC1, Cube** ppC2 ); // gives the next VALID cube pair (the previous one is automatically dequequed) int IteratorCubePairNext(); //////////////////////////////////////////////////////////////////////// /// EXPORTED VARIABLES /// ////////////////////////////////////////////////////////////////////////` // the number of allocated places int s_nPosAlloc; // the maximum number of occupied places int s_nPosMax[3]; //////////////////////////////////////////////////////////////////////// /// Minimization Strategy /// //////////////////////////////////////////////////////////////////////// // 1) check that ExorLink for this cube pair can be performed // (it may happen that the group is outdated due to recent reshaping) // 2) find out what is the improvement achieved by each cube group // 3) depending on the distance, do the following: // a) if ( Dist == 2 ) // try both cube groups, // if one of them leads to improvement, take the cube group right away // if none of them leads to improment // - take the last one (because it reshapes) // - take the last one only in case it does not increase literals // b) if ( Dist == 3 ) // try groups one by one // if one of them leads to improvement, take the group right away // if none of them leads to improvement // - take the group which reshapes // - take the reshaping group only in case it does not increase literals // if none of them leads to reshaping, do not take any of them // c) if ( Dist == 4 ) // try groups one by one // if one of the leads to reshaping, take it right away // if none of them leads to reshaping, do not take any of them //////////////////////////////////////////////////////////////////////// /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// // Cube set is a list of cubes static Cube* s_List; /////////////////////////////////////////////////////////////////////////// // undo information /////////////////////////////////////////////////////////////////////////// static struct { int fInput; // 1 if the input was changed Cube* p; // the pointer to the modified cube int PrevQa; int PrevPa; int PrevQq; int PrevPq; int PrevPz; int Var; // the number of variable that was changed int Value; // the value what was there int PrevID; // the previous ID of the removed cube } s_ChangeStore; /////////////////////////////////////////////////////////////////////////// // enable pair accumulation // from the begginning (while the starting cover is generated) // only the distance 2 accumulation is enabled static int s_fDistEnable2 = 1; static int s_fDistEnable3; static int s_fDistEnable4; // temporary storage for cubes generated by the ExorLink iterator static Cube* s_CubeGroup[5]; // the marks telling whether the given cube is inserted static int s_fInserted[5]; // enable selection only those Dist2 and Dist3 that do not increase literals int s_fDecreaseLiterals = 0; // the counters for display static int s_cEnquequed; static int s_cAttempts; static int s_cReshapes; // the number of cubes before ExorLink starts static int s_nCubesBefore; // the distance code specific for each ExorLink static cubedist s_Dist; // other variables static int s_Gain; static int s_GainTotal; static int s_GroupCounter; static int s_GroupBest; static Cube *s_pC1, *s_pC2; //////////////////////////////////////////////////////////////////////// /// Iterative ExorLink Operation /// //////////////////////////////////////////////////////////////////////// int CheckAndInsert( Cube* p ) { // return CheckForCloseCubes( p, 1 ); CubeInsert( p ); return 0; } int IterativelyApplyExorLink2( char fDistEnable ) // MEMO: instead of inserting the cubes that have already been checked // by running CheckForCloseCubes again, try inserting them without checking // and observe the difference (it will save 50% of checking time) { int z; // this var is specific to ExorLink-2 s_Dist = (cubedist)0; // enable pair accumulation s_fDistEnable2 = fDistEnable & 1; s_fDistEnable3 = fDistEnable & 2; s_fDistEnable4 = fDistEnable & 4; // initialize counters s_cEnquequed = GetQuequeStats( s_Dist ); s_cAttempts = 0; s_cReshapes = 0; // remember the number of cubes before minimization s_nCubesBefore = g_CoverInfo.nCubesInUse; for ( z = IteratorCubePairStart( s_Dist, &s_pC1, &s_pC2 ); z; z = IteratorCubePairNext() ) { s_cAttempts++; // start ExorLink of the given Distance if ( ExorLinkCubeIteratorStart( s_CubeGroup, s_pC1, s_pC2, s_Dist ) ) { // extract old cubes from storage (to prevent EXORing with their derivitives) CubeExtract( s_pC1 ); CubeExtract( s_pC2 ); // mark the current position in the cube pair queques MarkSet(); // check the first group (generated by ExorLinkCubeIteratorStart()) if ( CheckForCloseCubes( s_CubeGroup[0], 0 ) ) { // the first cube leads to improvement - it is already inserted CheckForCloseCubes( s_CubeGroup[1], 1 ); // insert the second cube goto SUCCESS; } if ( CheckForCloseCubes( s_CubeGroup[1], 0 ) ) { // the second cube leads to improvement - it is already inserted CheckForCloseCubes( s_CubeGroup[0], 1 ); // insert the first cube // CheckAndInsert( s_CubeGroup[0] ); goto SUCCESS; } // the first group does not lead to improvement // rewind to the previously marked position in the cube pair queques MarkRewind(); // generate the second group ExorLinkCubeIteratorNext( s_CubeGroup ); // check the second group if ( CheckForCloseCubes( s_CubeGroup[0], 0 ) ) { // the first cube leads to improvement - it is already inserted CheckForCloseCubes( s_CubeGroup[1], 1 ); // insert the second cube goto SUCCESS; } if ( CheckForCloseCubes( s_CubeGroup[1], 0 ) ) { // the second cube leads to improvement - it is already inserted CheckForCloseCubes( s_CubeGroup[0], 1 ); // insert the first cube // CheckAndInsert( s_CubeGroup[0] ); goto SUCCESS; } // the second group does not lead to improvement // decide whether to accept the second group, depending on literals if ( s_fDecreaseLiterals ) { if ( g_CoverInfo.fUseQCost ? s_CubeGroup[0]->q + s_CubeGroup[1]->q >= s_pC1->q + s_pC2->q : s_CubeGroup[0]->a + s_CubeGroup[1]->a >= s_pC1->a + s_pC2->a ) // the group increases literals { // do not take the last group // rewind to the previously marked position in the cube pair queques MarkRewind(); // return the old cubes back to storage CubeInsert( s_pC1 ); CubeInsert( s_pC2 ); // clean the results of generating ExorLinked cubes ExorLinkCubeIteratorCleanUp( 0 ); continue; } } // take the last group // there is no need to test these cubes again, // because they have been tested and did not yield any improvement CubeInsert( s_CubeGroup[0] ); CubeInsert( s_CubeGroup[1] ); // CheckForCloseCubes( s_CubeGroup[0], 1 ); // CheckForCloseCubes( s_CubeGroup[1], 1 ); SUCCESS: // clean the results of generating ExorLinked cubes ExorLinkCubeIteratorCleanUp( 1 ); // take the last group // free old cubes AddToFreeCubes( s_pC1 ); AddToFreeCubes( s_pC2 ); // increate the counter s_cReshapes++; } } // print the report if ( g_CoverInfo.Verbosity == 2 ) { printf( "ExLink-%d", 2 ); printf( ": Que= %5d", s_cEnquequed ); printf( " Att= %4d", s_cAttempts ); printf( " Resh= %4d", s_cReshapes ); printf( " NoResh= %4d", s_cAttempts - s_cReshapes ); printf( " Cubes= %3d", g_CoverInfo.nCubesInUse ); printf( " (%d)", s_nCubesBefore - g_CoverInfo.nCubesInUse ); printf( " Lits= %5d", CountLiterals() ); printf( " QCost = %6d", CountQCost() ); printf( "\n" ); } // return the number of cubes gained in the process return s_nCubesBefore - g_CoverInfo.nCubesInUse; } int IterativelyApplyExorLink3( char fDistEnable ) { int z, c, d; // this var is specific to ExorLink-3 s_Dist = (cubedist)1; // enable pair accumulation s_fDistEnable2 = fDistEnable & 1; s_fDistEnable3 = fDistEnable & 2; s_fDistEnable4 = fDistEnable & 4; // initialize counters s_cEnquequed = GetQuequeStats( s_Dist ); s_cAttempts = 0; s_cReshapes = 0; // remember the number of cubes before minimization s_nCubesBefore = g_CoverInfo.nCubesInUse; for ( z = IteratorCubePairStart( s_Dist, &s_pC1, &s_pC2 ); z; z = IteratorCubePairNext() ) { s_cAttempts++; // start ExorLink of the given Distance if ( ExorLinkCubeIteratorStart( s_CubeGroup, s_pC1, s_pC2, s_Dist ) ) { // extract old cubes from storage (to prevent EXORing with their derivitives) CubeExtract( s_pC1 ); CubeExtract( s_pC2 ); // mark the current position in the cube pair queques MarkSet(); // check cube groups one by one s_GroupCounter = 0; do { // check the cubes of this group one by one for ( c = 0; c < 3; c++ ) if ( !s_CubeGroup[c]->fMark ) // this cube has not yet been checked { s_Gain = CheckForCloseCubes( s_CubeGroup[c], 0 ); // do not insert the cube, by default if ( s_Gain ) { // this cube leads to improvement or reshaping - it is already inserted // decide whether to accept this group based on literal count if ( s_fDecreaseLiterals && s_Gain == 1 ) if ( g_CoverInfo.fUseQCost ? s_CubeGroup[0]->q + s_CubeGroup[1]->q + s_CubeGroup[2]->q > s_pC1->q + s_pC2->q + s_ChangeStore.PrevQq : s_CubeGroup[0]->a + s_CubeGroup[1]->a + s_CubeGroup[2]->a > s_pC1->a + s_pC2->a + s_ChangeStore.PrevQa ) // the group increases literals { // do not take this group // remember the group s_GroupBest = s_GroupCounter; // undo changes to be able to continue checking other groups UndoRecentChanges(); break; } // take this group for ( d = 0; d < 3; d++ ) // insert other cubes if ( d != c ) { CheckForCloseCubes( s_CubeGroup[d], 1 ); // if ( s_CubeGroup[d]->fMark ) // CheckAndInsert( s_CubeGroup[d] ); // CheckOnlyOneCube( s_CubeGroup[d] ); // CheckForCloseCubes( s_CubeGroup[d], 1 ); // else // CheckForCloseCubes( s_CubeGroup[d], 1 ); } // clean the results of generating ExorLinked cubes ExorLinkCubeIteratorCleanUp( 1 ); // take the last group // free old cubes AddToFreeCubes( s_pC1 ); AddToFreeCubes( s_pC2 ); // update the counter s_cReshapes++; goto END_OF_LOOP; } else // mark the cube as checked s_CubeGroup[c]->fMark = 1; } // the group is not taken - find the new group s_GroupCounter++; // rewind to the previously marked position in the cube pair queques MarkRewind(); } while ( ExorLinkCubeIteratorNext( s_CubeGroup ) ); // none of the groups leads to improvement // return the old cubes back to storage CubeInsert( s_pC1 ); CubeInsert( s_pC2 ); // clean the results of generating ExorLinked cubes ExorLinkCubeIteratorCleanUp( 0 ); } END_OF_LOOP: {} } // print the report if ( g_CoverInfo.Verbosity == 2 ) { printf( "ExLink-%d", 3 ); printf( ": Que= %5d", s_cEnquequed ); printf( " Att= %4d", s_cAttempts ); printf( " Resh= %4d", s_cReshapes ); printf( " NoResh= %4d", s_cAttempts - s_cReshapes ); printf( " Cubes= %3d", g_CoverInfo.nCubesInUse ); printf( " (%d)", s_nCubesBefore - g_CoverInfo.nCubesInUse ); printf( " Lits= %5d", CountLiterals() ); printf( " QCost = %6d", CountQCost() ); printf( "\n" ); } // return the number of cubes gained in the process return s_nCubesBefore - g_CoverInfo.nCubesInUse; } int IterativelyApplyExorLink4( char fDistEnable ) { int z, c; // this var is specific to ExorLink-4 s_Dist = (cubedist)2; // enable pair accumulation s_fDistEnable2 = fDistEnable & 1; s_fDistEnable3 = fDistEnable & 2; s_fDistEnable4 = fDistEnable & 4; // initialize counters s_cEnquequed = GetQuequeStats( s_Dist ); s_cAttempts = 0; s_cReshapes = 0; // remember the number of cubes before minimization s_nCubesBefore = g_CoverInfo.nCubesInUse; for ( z = IteratorCubePairStart( s_Dist, &s_pC1, &s_pC2 ); z; z = IteratorCubePairNext() ) { s_cAttempts++; // start ExorLink of the given Distance if ( ExorLinkCubeIteratorStart( s_CubeGroup, s_pC1, s_pC2, s_Dist ) ) { // extract old cubes from storage (to prevent EXORing with their derivitives) CubeExtract( s_pC1 ); CubeExtract( s_pC2 ); // mark the current position in the cube pair queques MarkSet(); // check cube groups one by one do { // check the cubes of this group one by one s_GainTotal = 0; for ( c = 0; c < 4; c++ ) if ( !s_CubeGroup[c]->fMark ) // this cube has not yet been checked { s_Gain = CheckForCloseCubes( s_CubeGroup[c], 0 ); // do not insert the cube, by default // if the cube leads to gain, it is already inserted s_fInserted[c] = (int)(s_Gain>0); // increment the total gain s_GainTotal += s_Gain; } else s_fInserted[c] = 0; // the cube has already been checked - it is not inserted if ( s_GainTotal == 0 ) // the group does not lead to any gain { // mark the cubes for ( c = 0; c < 4; c++ ) s_CubeGroup[c]->fMark = 1; } else if ( s_GainTotal == 1 ) // the group does not lead to substantial gain, too { // undo changes to be able to continue checking groups UndoRecentChanges(); // mark those cubes that were not inserted for ( c = 0; c < 4; c++ ) s_CubeGroup[c]->fMark = !s_fInserted[c]; } else // if ( s_GainTotal > 1 ) // the group reshapes or improves { // accept the group for ( c = 0; c < 4; c++ ) // insert other cubes if ( !s_fInserted[c] ) CheckForCloseCubes( s_CubeGroup[c], 1 ); // CheckAndInsert( s_CubeGroup[c] ); // clean the results of generating ExorLinked cubes ExorLinkCubeIteratorCleanUp( 1 ); // take the last group // free old cubes AddToFreeCubes( s_pC1 ); AddToFreeCubes( s_pC2 ); // update the counter s_cReshapes++; goto END_OF_LOOP; } // rewind to the previously marked position in the cube pair queques MarkRewind(); } while ( ExorLinkCubeIteratorNext( s_CubeGroup ) ); // none of the groups leads to improvement // return the old cubes back to storage CubeInsert( s_pC1 ); CubeInsert( s_pC2 ); // clean the results of generating ExorLinked cubes ExorLinkCubeIteratorCleanUp( 0 ); } END_OF_LOOP: {} } // print the report if ( g_CoverInfo.Verbosity == 2 ) { printf( "ExLink-%d", 4 ); printf( ": Que= %5d", s_cEnquequed ); printf( " Att= %4d", s_cAttempts ); printf( " Resh= %4d", s_cReshapes ); printf( " NoResh= %4d", s_cAttempts - s_cReshapes ); printf( " Cubes= %3d", g_CoverInfo.nCubesInUse ); printf( " (%d)", s_nCubesBefore - g_CoverInfo.nCubesInUse ); printf( " Lits= %5d", CountLiterals() ); printf( " QCost = %6d", CountQCost() ); printf( "\n" ); } // return the number of cubes gained in the process return s_nCubesBefore - g_CoverInfo.nCubesInUse; } // local static variables Cube* s_q; int s_Distance; int s_DiffVarNum; int s_DiffVarValueP_old; int s_DiffVarValueP_new; int s_DiffVarValueQ; int CheckForCloseCubes( Cube* p, int fAddCube ) // checks the cube storage for a cube that is dist-0 and dist-1 removed // from the given one (p) if such a cube is found, extracts it from the data // structure, EXORs it with the given cube, adds the resultant cube // to the data structure and performed the same check for the resultant cube; // returns the number of cubes gained in the process of reduction; // if an adjacent cube is not found, inserts the cube only if (fAddCube==1)!!! { // start the new range NewRangeReset(); for ( s_q = s_List; s_q; s_q = s_q->Next ) { s_Distance = GetDistancePlus( p, s_q ); if ( s_Distance > 4 ) { } else if ( s_Distance == 4 ) { if ( s_fDistEnable4 ) NewRangeInsertCubePair( DIST4, p, s_q ); } else if ( s_Distance == 3 ) { if ( s_fDistEnable3 ) NewRangeInsertCubePair( DIST3, p, s_q ); } else if ( s_Distance == 2 ) { if ( s_fDistEnable2 ) NewRangeInsertCubePair( DIST2, p, s_q ); } else if ( s_Distance == 1 ) { // extract the cube from the data structure ////////////////////////////////////////////////////////// // store the changes s_ChangeStore.fInput = (s_DiffVarNum != -1); s_ChangeStore.p = p; s_ChangeStore.PrevQa = s_q->a; s_ChangeStore.PrevPa = p->a; s_ChangeStore.PrevQq = s_q->q; s_ChangeStore.PrevPq = p->q; s_ChangeStore.PrevPz = p->z; s_ChangeStore.Var = s_DiffVarNum; s_ChangeStore.Value = s_DiffVarValueQ; s_ChangeStore.PrevID = s_q->ID; ////////////////////////////////////////////////////////// CubeExtract( s_q ); // perform the EXOR of the two cubes and write the result into p // it is important that the resultant cube is written into p!!! if ( s_DiffVarNum == -1 ) { int i; // exor the output part p->z = 0; for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) { p->pCubeDataOut[i] ^= s_q->pCubeDataOut[i]; p->z += BIT_COUNT(p->pCubeDataOut[i]); } } else { // the cube has already been updated by GetDistancePlus() // modify the parameters of the number of literals in the new cube // p->a += s_UpdateLiterals[ s_DiffVarValueP ][ s_DiffVarValueQ ]; if ( s_DiffVarValueP_old == VAR_NEG || s_DiffVarValueP_old == VAR_POS ) p->a--; if ( s_DiffVarValueP_new == VAR_NEG || s_DiffVarValueP_new == VAR_POS ) p->a++; p->q = ComputeQCostBits(p); } // move q to the free cube list AddToFreeCubes( s_q ); // make sure that nobody with use the pairs created so far // NewRangeReset(); // call the function again for the new cube return 1 + CheckForCloseCubes( p, 1 ); } else // if ( Distance == 0 ) { // extract the second cube from the data structure and add them both to the free list AddToFreeCubes( p ); AddToFreeCubes( CubeExtract( s_q ) ); // make sure that nobody with use the pairs created so far NewRangeReset(); return 2; } } // add the cube to the data structure if needed if ( fAddCube ) CubeInsert( p ); // add temporarily stored new range of cube pairs to the queque NewRangeAdd(); return 0; } void UndoRecentChanges() { Cube * p, * q; // get back cube q that was deleted q = GetFreeCube(); // restore the ID q->ID = s_ChangeStore.PrevID; // insert the cube into storage again CubeInsert( q ); // extract cube p p = CubeExtract( s_ChangeStore.p ); // modify it back if ( s_ChangeStore.fInput ) // the input has changed { ExorVar( p, s_ChangeStore.Var, (varvalue)s_ChangeStore.Value ); p->a = s_ChangeStore.PrevPa; p->q = s_ChangeStore.PrevPq; // p->z did not change } else // if ( s_ChangeStore.fInput ) // the output has changed { int i; for ( i = 0; i < g_CoverInfo.nWordsOut; i++ ) p->pCubeDataOut[i] ^= q->pCubeDataOut[i]; p->z = s_ChangeStore.PrevPz; // p->a did not change } } /////////////////////////////////////////////////////////////////// /// CUBE SET MANIPULATION PROCEDURES /// /////////////////////////////////////////////////////////////////// // Cube set is a list of cubes //static Cube* s_List; /////////////////////////////////////////////////////////////////// /// Memory Allocation/Delocation /// /////////////////////////////////////////////////////////////////// int AllocateCubeSets( int nVarsIn, int nVarsOut ) { s_List = NULL; // clean other data s_fDistEnable2 = 1; s_fDistEnable3 = 0; s_fDistEnable4 = 0; memset( s_CubeGroup, 0, sizeof(void *) * 5 ); memset( s_fInserted, 0, sizeof(int) * 5 ); s_fDecreaseLiterals = 0; s_cEnquequed = 0; s_cAttempts = 0; s_cReshapes = 0; s_nCubesBefore = 0; s_Gain = 0; s_GainTotal = 0; s_GroupCounter = 0; s_GroupBest = 0; s_pC1 = s_pC2 = NULL; return 4; } void DelocateCubeSets() { } /////////////////////////////////////////////////////////////////// /// Insertion Operators /// /////////////////////////////////////////////////////////////////// void CubeInsert( Cube* p ) // inserts the cube into storage (puts it at the beginning of the list) { assert( p->Prev == NULL && p->Next == NULL ); assert( p->ID ); if ( s_List == NULL ) s_List = p; else { p->Next = s_List; s_List->Prev = p; s_List = p; } g_CoverInfo.nCubesInUse++; } Cube* CubeExtract( Cube* p ) // extracts the cube from storage { // assert( p->Prev && p->Next ); // can be done only with rings assert( p->ID ); // if ( s_List == p ) // s_List = p->Next; // if ( p->Prev ) // p->Prev->Next = p->Next; if ( s_List == p ) s_List = p->Next; else p->Prev->Next = p->Next; if ( p->Next ) p->Next->Prev = p->Prev; p->Prev = NULL; p->Next = NULL; g_CoverInfo.nCubesInUse--; return p; } /////////////////////////////////////////////////////////////////// /// CUBE ITERATOR /// /////////////////////////////////////////////////////////////////// // the iterator starts from the Head and stops when it sees NULL Cube* s_pCubeLast; /////////////////////////////////////////////////////////////////// /// Cube Set Iterator /// /////////////////////////////////////////////////////////////////// Cube* IterCubeSetStart() // starts an iterator that traverses all the cubes in the ring { assert( s_pCubeLast == NULL ); // check whether the List has cubes if ( s_List == NULL ) return NULL; return ( s_pCubeLast = s_List ); } Cube* IterCubeSetNext() // returns the next cube in the cube set // to use it again after it has returned NULL, first call IterCubeSetStart() { assert( s_pCubeLast ); return ( s_pCubeLast = s_pCubeLast->Next ); } /////////////////////////////////////////////////////////////////// //// ADJACENCY QUEQUES ////// /////////////////////////////////////////////////////////////////// typedef struct { Cube** pC1; // the pointer to the first cube Cube** pC2; // the pointer to the second cube byte* ID1; // the ID of the first cube byte* ID2; // the ID of the second cube int PosOut; // extract position int PosIn; // insert position int PosCur; // temporary insert position int PosMark; // the marked position int fEmpty; // this flag is 1 if there is nothing in the queque } que; static que s_Que[3]; // Dist-2, Dist-3, Dist-4 queques // the number of allocated places //int s_nPosAlloc; // the maximum number of occupied places //int s_nPosMax[3]; ////////////////////////////////////////////////////////////////////// // Conditional Adding Cube Pairs To Queques // ////////////////////////////////////////////////////////////////////// int GetPosDiff( int PosBeg, int PosEnd ) { return (PosEnd - PosBeg + s_nPosAlloc) % s_nPosAlloc; } void MarkSet() // sets marks in the cube pair queques { s_Que[0].PosMark = s_Que[0].PosIn; s_Que[1].PosMark = s_Que[1].PosIn; s_Que[2].PosMark = s_Que[2].PosIn; } void MarkRewind() // rewinds the queques to the previously set marks { s_Que[0].PosIn = s_Que[0].PosMark; s_Que[1].PosIn = s_Que[1].PosMark; s_Que[2].PosIn = s_Que[2].PosMark; } void NewRangeReset() // resets temporarily stored new range of cube pairs { s_Que[0].PosCur = s_Que[0].PosIn; s_Que[1].PosCur = s_Que[1].PosIn; s_Que[2].PosCur = s_Que[2].PosIn; } void NewRangeAdd() // adds temporarily stored new range of cube pairs to the queque { s_Que[0].PosIn = s_Que[0].PosCur; s_Que[1].PosIn = s_Que[1].PosCur; s_Que[2].PosIn = s_Que[2].PosCur; } void NewRangeInsertCubePair( cubedist Dist, Cube* p1, Cube* p2 ) // insert one cube pair into the new range { que* p = &s_Que[Dist]; int Pos = p->PosCur; if ( p->fEmpty || Pos != p->PosOut ) { p->pC1[Pos] = p1; p->pC2[Pos] = p2; p->ID1[Pos] = p1->ID; p->ID2[Pos] = p2->ID; p->PosCur = (p->PosCur+1)%s_nPosAlloc; } else assert(0); // cout << endl << "DIST-" << (int)(Dist+2) << ": Have run out of queque space!" << endl; } void PrintQuequeStats() { /* cout << endl << "Queque statistics: "; cout << " Alloc = " << s_nPosAlloc; cout << " DIST2 = " << GetPosDiff( s_Que[0].PosOut, s_Que[0].PosIn ); cout << " DIST3 = " << GetPosDiff( s_Que[1].PosOut, s_Que[1].PosIn ); cout << " DIST4 = " << GetPosDiff( s_Que[2].PosOut, s_Que[2].PosIn ); cout << endl; cout << endl; */ } int GetQuequeStats( cubedist Dist ) { return GetPosDiff( s_Que[Dist].PosOut, s_Que[Dist].PosIn ); } ////////////////////////////////////////////////////////////////////// // Queque Iterators // ////////////////////////////////////////////////////////////////////// // iterating through the queque (with authomatic garbage collection) // only one iterator can be active at a time static struct { int fStarted; // status of the iterator (1 if working) cubedist Dist; // the currently iterated queque Cube** ppC1; // the position where the first cube pointer goes Cube** ppC2; // the position where the second cube pointer goes int PosStop; // the stop position (to prevent the iterator from // choking when new pairs are added during iteration) int CutValue; // the number of literals below which the cubes are not used } s_Iter; static que* pQ; static Cube *p1, *p2; int IteratorCubePairStart( cubedist CubeDist, Cube** ppC1, Cube** ppC2 ) // start an iterator through cubes of dist CubeDist, // the resulting pointers are written into ppC1 and ppC2 // returns 1 if the first cube pair is found { int fEntryFound; assert( s_Iter.fStarted == 0 ); assert( CubeDist >= 0 && CubeDist <= 2 ); s_Iter.fStarted = 1; s_Iter.Dist = CubeDist; s_Iter.ppC1 = ppC1; s_Iter.ppC2 = ppC2; s_Iter.PosStop = s_Que[ CubeDist ].PosIn; // determine the cut value // s_Iter.CutValue = s_nLiteralsInUse/s_nCubesInUse/2; s_Iter.CutValue = -1; fEntryFound = 0; // go through the entries while there is something in the queque for ( pQ = &s_Que[ CubeDist ]; pQ->PosOut != s_Iter.PosStop; pQ->PosOut = (pQ->PosOut+1)%s_nPosAlloc ) { p1 = pQ->pC1[ pQ->PosOut ]; p2 = pQ->pC2[ pQ->PosOut ]; // check whether the entry is valid if ( p1->ID == pQ->ID1[ pQ->PosOut ] && p2->ID == pQ->ID2[ pQ->PosOut ] ) //&& //p1->x + p1->y + p2->x + p2->y > s_Iter.CutValue ) { fEntryFound = 1; break; } } if ( fEntryFound ) { // write the result into the pick-up place *ppC1 = pQ->pC1[ pQ->PosOut ]; *ppC2 = pQ->pC2[ pQ->PosOut ]; pQ->PosOut = (pQ->PosOut+1)%s_nPosAlloc; } else s_Iter.fStarted = 0; return fEntryFound; } int IteratorCubePairNext() // gives the next VALID cube pair (the previous one is automatically dequequed) { int fEntryFound = 0; assert( s_Iter.fStarted ); // go through the entries while there is something in the queque for ( pQ = &s_Que[ s_Iter.Dist ]; pQ->PosOut != s_Iter.PosStop; pQ->PosOut = (pQ->PosOut+1)%s_nPosAlloc ) { p1 = pQ->pC1[ pQ->PosOut ]; p2 = pQ->pC2[ pQ->PosOut ]; // check whether the entry is valid if ( p1->ID == pQ->ID1[ pQ->PosOut ] && p2->ID == pQ->ID2[ pQ->PosOut ] ) //&& //p1->x + p1->y + p2->x + p2->y > s_Iter.CutValue ) { fEntryFound = 1; break; } } if ( fEntryFound ) { // write the result into the pick-up place *(s_Iter.ppC1) = pQ->pC1[ pQ->PosOut ]; *(s_Iter.ppC2) = pQ->pC2[ pQ->PosOut ]; pQ->PosOut = (pQ->PosOut+1)%s_nPosAlloc; } else // iteration has finished s_Iter.fStarted = 0; return fEntryFound; } ////////////////////////////////////////////////////////////////////// // Allocation/Delocation // ////////////////////////////////////////////////////////////////////// int AllocateQueques( int nPlaces ) // nPlaces should be approximately nCubes*nCubes/10 // allocates memory for cube pair queques { int i; s_nPosAlloc = nPlaces; for ( i = 0; i < 3; i++ ) { // clean data memset( &s_Que[i], 0, sizeof(que) ); s_Que[i].pC1 = (Cube**) ABC_ALLOC( Cube*, nPlaces ); s_Que[i].pC2 = (Cube**) ABC_ALLOC( Cube*, nPlaces ); s_Que[i].ID1 = (byte*) ABC_ALLOC( byte, nPlaces ); s_Que[i].ID2 = (byte*) ABC_ALLOC( byte, nPlaces ); if ( s_Que[i].pC1==NULL || s_Que[i].pC2==NULL || s_Que[i].ID1==NULL || s_Que[i].ID2==NULL ) return 0; s_nPosMax[i] = 0; s_Que[i].fEmpty = 1; } return nPlaces * (sizeof(Cube*) + sizeof(Cube*) + 2*sizeof(byte) ); } void DelocateQueques() { int i; for ( i = 0; i < 3; i++ ) { ABC_FREE( s_Que[i].pC1 ); ABC_FREE( s_Que[i].pC2 ); ABC_FREE( s_Que[i].ID1 ); ABC_FREE( s_Que[i].ID2 ); } } /////////////////////////////////////////////////////////////////// //////////// End of File ///////////////// /////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/exorUtil.c000066400000000000000000000200771300674244400237100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [exorUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Exclusive sum-of-product minimization.] Synopsis [Utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: exorUtil.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// /// /// Implementation of EXORCISM - 4 /// /// An Exclusive Sum-of-Product Minimizer /// /// Alan Mishchenko /// /// /// //////////////////////////////////////////////////////////////////////// /// /// /// Utility Functions /// /// /// /// 1) allocating memory for and creating the ESOP cover /// /// 2) writing the resultant cover into an ESOP PLA file /// /// /// /// Ver. 1.0. Started - July 15, 2000. Last update - July 20, 2000 /// /// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 10, 2000 /// /// Ver. 1.5. Started - Aug 19, 2000. Last update - Aug 19, 2000 /// /// Ver. 1.7. Started - Sep 20, 2000. Last update - Sep 23, 2000 /// /// /// //////////////////////////////////////////////////////////////////////// /// This software was tested with the BDD package "CUDD", v.2.3.0 /// /// by Fabio Somenzi /// /// http://vlsi.colorado.edu/~fabio/ /// //////////////////////////////////////////////////////////////////////// #include "exor.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// EXTERNAL VARIABLES //// //////////////////////////////////////////////////////////////////////// // information about the options, the function, and the cover extern cinfo g_CoverInfo; //////////////////////////////////////////////////////////////////////// /// EXTERNAL FUNCTIONS /// //////////////////////////////////////////////////////////////////////// // Cube Cover Iterator // starts an iterator that traverses all the cubes in the ring extern Cube* IterCubeSetStart(); // returns the next cube in the ring extern Cube* IterCubeSetNext(); // retrieves the variable from the cube extern varvalue GetVar( Cube* pC, int Var ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// //////////// Cover Service Procedures ///////////////// /////////////////////////////////////////////////////////////////// int CountLiterals() { Cube* p; int LitCounter = 0; for ( p = IterCubeSetStart( ); p; p = IterCubeSetNext() ) LitCounter += p->a; return LitCounter; } int CountLiteralsCheck() { Cube* p; int Value, v; int LitCounter = 0; int LitCounterControl = 0; for ( p = IterCubeSetStart( ); p; p = IterCubeSetNext() ) { LitCounterControl += p->a; assert( p->fMark == 0 ); // write the input variables for ( v = 0; v < g_CoverInfo.nVarsIn; v++ ) { Value = GetVar( p, v ); if ( Value == VAR_NEG ) LitCounter++; else if ( Value == VAR_POS ) LitCounter++; else if ( Value != VAR_ABS ) { assert(0); } } } if ( LitCounterControl != LitCounter ) printf( "Warning! The recorded number of literals (%d) differs from the actual number (%d)\n", LitCounterControl, LitCounter ); return LitCounter; } int CountQCost() { Cube* p; int QCost = 0; int QCostControl = 0; for ( p = IterCubeSetStart( ); p; p = IterCubeSetNext() ) { QCostControl += p->q; QCost += ComputeQCostBits( p ); } // if ( QCostControl != QCost ) // printf( "Warning! The recorded number of literals (%d) differs from the actual number (%d)\n", QCostControl, QCost ); return QCost; } void WriteTableIntoFile( FILE * pFile ) // nCubesAlloc is the number of allocated cubes { int v, w; Cube * p; int cOutputs; int nOutput; int WordSize; for ( p = IterCubeSetStart( ); p; p = IterCubeSetNext() ) { assert( p->fMark == 0 ); // write the input variables for ( v = 0; v < g_CoverInfo.nVarsIn; v++ ) { int Value = GetVar( p, v ); if ( Value == VAR_NEG ) fprintf( pFile, "0" ); else if ( Value == VAR_POS ) fprintf( pFile, "1" ); else if ( Value == VAR_ABS ) fprintf( pFile, "-" ); else assert(0); } fprintf( pFile, " " ); // write the output variables cOutputs = 0; nOutput = g_CoverInfo.nVarsOut; WordSize = 8*sizeof( unsigned ); for ( w = 0; w < g_CoverInfo.nWordsOut; w++ ) for ( v = 0; v < WordSize; v++ ) { if ( p->pCubeDataOut[w] & (1< { FILE * pFile; time_t ltime; char * TimeStr; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( pFile, "\n\nCannot open the output file\n" ); return 1; } // get current time time( <ime ); TimeStr = asctime( localtime( <ime ) ); // get the number of literals g_CoverInfo.nLiteralsAfter = CountLiteralsCheck(); g_CoverInfo.QCostAfter = CountQCost(); fprintf( pFile, "# EXORCISM-4 output for command line arguments: " ); fprintf( pFile, "\"-Q %d -V %d\"\n", g_CoverInfo.Quality, g_CoverInfo.Verbosity ); fprintf( pFile, "# Minimization performed %s", TimeStr ); fprintf( pFile, "# Initial statistics: " ); fprintf( pFile, "Cubes = %d Literals = %d QCost = %d\n", g_CoverInfo.nCubesBefore, g_CoverInfo.nLiteralsBefore, g_CoverInfo.QCostBefore ); fprintf( pFile, "# Final statistics: " ); fprintf( pFile, "Cubes = %d Literals = %d QCost = %d\n", g_CoverInfo.nCubesInUse, g_CoverInfo.nLiteralsAfter, g_CoverInfo.QCostAfter ); fprintf( pFile, "# File reading and reordering time = %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeRead) ); fprintf( pFile, "# Starting cover generation time = %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeStart) ); fprintf( pFile, "# Pure ESOP minimization time = %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeMin) ); fprintf( pFile, ".i %d\n", g_CoverInfo.nVarsIn ); fprintf( pFile, ".o %d\n", g_CoverInfo.nVarsOut ); fprintf( pFile, ".p %d\n", g_CoverInfo.nCubesInUse ); fprintf( pFile, ".type esop\n" ); WriteTableIntoFile( pFile ); fprintf( pFile, ".e\n" ); fclose( pFile ); return 0; } /////////////////////////////////////////////////////////////////// //////////// End of File ///////////////// /////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/exor/module.make000066400000000000000000000002561300674244400240520ustar00rootroot00000000000000SRC += src/base/exor/exor.c \ src/base/exor/exorBits.c \ src/base/exor/exorCubes.c \ src/base/exor/exorLink.c \ src/base/exor/exorList.c \ src/base/exor/exorUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/000077500000000000000000000000001300674244400213555ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/io.c000066400000000000000000002753761300674244400221540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [io.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Command file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: io.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/main/mainInt.h" #include "aig/saig/saig.h" #include "proof/abs/abs.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int IoCommandRead ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBblif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadBench ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadDsd ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadEdif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadFins ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadInit ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadPlaMo ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadTruth ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadStatus ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandReadGig ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteAigerCex( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBblif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteBook ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteCnf2 ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteCex ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteDot ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteGml ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteList ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteSortCnf( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteTruth ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteTruths ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteStatus ( Abc_Frame_t * pAbc, int argc, char **argv ); static int IoCommandWriteSmv ( Abc_Frame_t * pAbc, int argc, char **argv ); extern void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk ); extern int glo_fMapped; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "I/O", "read", IoCommandRead, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_aiger", IoCommandReadAiger, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_baf", IoCommandReadBaf, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_bblif", IoCommandReadBblif, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_blif", IoCommandReadBlif, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_blif_mv", IoCommandReadBlifMv, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_bench", IoCommandReadBench, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_dsd", IoCommandReadDsd, 1 ); // Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_eqn", IoCommandReadEqn, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_fins", IoCommandReadFins, 0 ); Cmd_CommandAdd( pAbc, "I/O", "read_init", IoCommandReadInit, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_plamo", IoCommandReadPlaMo, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_truth", IoCommandReadTruth, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 ); Cmd_CommandAdd( pAbc, "I/O", "read_status", IoCommandReadStatus, 0 ); Cmd_CommandAdd( pAbc, "I/O", "&read_gig", IoCommandReadGig, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_aiger", IoCommandWriteAiger, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_aiger_cex", IoCommandWriteAigerCex, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_baf", IoCommandWriteBaf, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_bblif", IoCommandWriteBblif, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_book", IoCommandWriteBook, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_cex", IoCommandWriteCex, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 ); Cmd_CommandAdd( pAbc, "I/O", "&write_cnf", IoCommandWriteCnf2, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_dot", IoCommandWriteDot, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_eqn", IoCommandWriteEqn, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 ); // Cmd_CommandAdd( pAbc, "I/O", "write_list", IoCommandWriteList, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_verilog", IoCommandWriteVerilog, 0 ); // Cmd_CommandAdd( pAbc, "I/O", "write_verlib", IoCommandWriteVerLib, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_sorter_cnf", IoCommandWriteSortCnf, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_truth", IoCommandWriteTruth, 0 ); Cmd_CommandAdd( pAbc, "I/O", "&write_truths", IoCommandWriteTruths, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_status", IoCommandWriteStatus, 0 ); Cmd_CommandAdd( pAbc, "I/O", "write_smv", IoCommandWriteSmv, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_End( Abc_Frame_t * pAbc ) { } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Command[1000]; Abc_Ntk_t * pNtk; char * pFileName, * pTemp; int c, fCheck, fBarBufs, fReadGia; fCheck = 1; fBarBufs = 0; fReadGia = 0; glo_fMapped = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "mcbgh" ) ) != EOF ) { switch ( c ) { case 'm': glo_fMapped ^= 1; break; case 'c': fCheck ^= 1; break; case 'b': fBarBufs ^= 1; break; case 'g': fReadGia ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // fix the wrong symbol for ( pTemp = pFileName; *pTemp; pTemp++ ) if ( *pTemp == '>' || *pTemp == '\\' ) *pTemp = '/'; // read libraries Command[0] = 0; assert( strlen(pFileName) < 900 ); if ( !strcmp( Extra_FileNameExtension(pFileName), "genlib" ) ) sprintf( Command, "read_genlib %s", pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "lib" ) ) sprintf( Command, "read_lib %s", pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "scl" ) ) sprintf( Command, "read_scl %s", pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "super" ) ) sprintf( Command, "read_super %s", pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "constr" ) ) sprintf( Command, "read_constr %s", pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "c" ) ) sprintf( Command, "so %s", pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "dsd" ) ) sprintf( Command, "dsd_load %s", pFileName ); if ( Command[0] ) { Cmd_CommandExecute( pAbc, Command ); return 0; } if ( fReadGia ) { Abc_Ntk_t * pNtk = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), fCheck ); if ( pNtk ) { Gia_Man_t * pGia = Abc_NtkFlattenHierarchyGia( pNtk, NULL, 0 ); Abc_NtkDelete( pNtk ); if ( pGia == NULL ) { Abc_Print( 1, "Abc_CommandBlast(): Bit-blasting has failed.\n" ); return 0; } Abc_FrameUpdateGia( pAbc, pGia ); } return 0; } // check if the library is available if ( glo_fMapped && Abc_FrameReadLibGen() == NULL ) { Abc_Print( 1, "Cannot read mapped design when the library is not given.\n" ); return 0; } // read the file using the corresponding file reader pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck, fBarBufs ); if ( pNtk == NULL ) return 0; if ( Abc_NtkPiNum(pNtk) == 0 ) { Abc_Print( 0, "The new network has no primary inputs. It is recommended\n" ); Abc_Print( 1, "to add a dummy PI to make sure all commands work correctly.\n" ); } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameCopyLTLDataBase( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read [-mcbgh] \n" ); fprintf( pAbc->Err, "\t replaces the current network by the network read from \n" ); fprintf( pAbc->Err, "\t by calling the parser that matches the extension of \n" ); fprintf( pAbc->Err, "\t (to read a hierarchical design, use \"read_hie\")\n" ); fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-b : toggle reading barrier buffers [default = %s]\n", fBarBufs? "yes":"no" ); fprintf( pAbc->Err, "\t-g : toggle reading and flattening into &-space [default = %s]\n", fBarBufs? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fCheck; int c; fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_Read( pFileName, IO_FILE_AIGER, fCheck, 0 ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_aiger [-ch] \n" ); fprintf( pAbc->Err, "\t reads the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fCheck; int c; fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_Read( pFileName, IO_FILE_BAF, fCheck, 0 ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_baf [-ch] \n" ); fprintf( pAbc->Err, "\t reads the network in Binary Aig Format (BAF)\n" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadBblif( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fCheck; int c; fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_Read( pFileName, IO_FILE_BBLIF, fCheck, 0 ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_bblif [-ch] \n" ); fprintf( pAbc->Err, "\t reads the network in a binary BLIF format\n" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fReadAsAig; int fCheck; int fUseNewParser; int fSaveNames; int c; extern Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ); fCheck = 1; fReadAsAig = 0; fUseNewParser = 1; fSaveNames = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "nmach" ) ) != EOF ) { switch ( c ) { case 'n': fUseNewParser ^= 1; break; case 'm': fSaveNames ^= 1; break; case 'a': fReadAsAig ^= 1; break; case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader if ( fReadAsAig ) pNtk = Io_ReadBlifAsAig( pFileName, fCheck ); else if ( fUseNewParser ) pNtk = Io_Read( pFileName, IO_FILE_BLIF, fCheck, 0 ); else { Abc_Ntk_t * pTemp; pNtk = Io_ReadBlif( pFileName, fCheck ); if ( pNtk == NULL ) return 1; if ( fSaveNames ) Abc_NtkStartNameIds( pNtk ); pNtk = Abc_NtkToLogic( pTemp = pNtk ); if ( fSaveNames ) Abc_NtkTransferNameIds( pTemp, pNtk ); Abc_NtkDelete( pTemp ); } if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_blif [-nmach] \n" ); fprintf( pAbc->Err, "\t reads the network in binary BLIF format\n" ); fprintf( pAbc->Err, "\t (if this command does not work, try \"read\")\n" ); fprintf( pAbc->Err, "\t-n : toggle using old BLIF parser without hierarchy support [default = %s]\n", !fUseNewParser? "yes":"no" ); fprintf( pAbc->Err, "\t-m : toggle saving original circuit names into a file [default = %s]\n", fSaveNames? "yes":"no" ); fprintf( pAbc->Err, "\t-a : toggle creating AIG while reading the file [default = %s]\n", fReadAsAig? "yes":"no" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fCheck; int c; fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_Read( pFileName, IO_FILE_BLIFMV, fCheck, 0 ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_blif_mv [-ch] \n" ); fprintf( pAbc->Err, "\t reads the network in BLIF-MV format\n" ); fprintf( pAbc->Err, "\t (if this command does not work, try \"read\")\n" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fCheck; int c; fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_Read( pFileName, IO_FILE_BENCH, fCheck, 0 ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_bench [-ch] \n" ); fprintf( pAbc->Err, "\t reads the network in BENCH format\n" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pString; int fCheck; int c; extern Abc_Ntk_t * Io_ReadDsd( char * pFormula ); fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pString = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_ReadDsd( pString ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_dsd [-h] \n" ); fprintf( pAbc->Err, "\t parses a formula representing DSD of a function\n" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tformula : the formula representing disjoint-support decomposition (DSD)\n" ); fprintf( pAbc->Err, "\t Example of a formula: !(a*(b+CA(!d,e*f,c))*79B3(g,h,i,k))\n" ); fprintf( pAbc->Err, "\t where \'!\' is an INV, \'*\' is an AND, \'+\' is an XOR, \n" ); fprintf( pAbc->Err, "\t CA and 79B3 are hexadecimal representations of truth tables\n" ); fprintf( pAbc->Err, "\t (in this case CA=11001010 is truth table of MUX(Data0,Data1,Ctrl))\n" ); fprintf( pAbc->Err, "\t The lower chars (a,b,c,etc) are reserved for elementary variables.\n" ); fprintf( pAbc->Err, "\t The upper chars (A,B,C,etc) are reserved for hexadecimal digits.\n" ); fprintf( pAbc->Err, "\t No spaces are allowed in formulas. In parentheses, LSB goes first.\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fCheck; int c; fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_Read( pFileName, IO_FILE_EDIF, fCheck, 0 ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_edif [-ch] \n" ); fprintf( pAbc->Err, "\t reads the network in EDIF (works only for ISCAS benchmarks)\n" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fCheck; int c; fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_Read( pFileName, IO_FILE_EQN, fCheck, 0 ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_eqn [-ch] \n" ); fprintf( pAbc->Err, "\t reads the network in equation format\n" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadFins( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Int_t * Io_ReadFins( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); 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 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // check current network if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // compute information and save it in the network Vec_IntFreeP( &pNtk->vFins ); pNtk->vFins = Io_ReadFins( pNtk, pFileName, fVerbose ); return 0; usage: fprintf( pAbc->Err, "usage: read_fins [-vh] \n" ); fprintf( pAbc->Err, "\t reads the network in equation format\n" ); fprintf( pAbc->Err, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk; char * pFileName; int c; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 ) goto usage; if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } // get the input file name if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; else if ( pNtk->pSpec ) pFileName = Extra_FileNameGenericAppend( pNtk->pSpec, ".init" ); else { printf( "File name should be given on the command line.\n" ); return 1; } // read the file using the corresponding file reader pNtk = Abc_NtkDup( pNtk ); Io_ReadBenchInit( pNtk, pFileName ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_init [-h] \n" ); fprintf( pAbc->Err, "\t reads initial state of the network in BENCH format\n" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int c, fZeros = 0, fBoth = 0, fOnDc = 0, fSkipPrepro = 0, fCheck = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "zbdxch" ) ) != EOF ) { switch ( c ) { case 'z': fZeros ^= 1; break; case 'b': fBoth ^= 1; break; case 'd': fOnDc ^= 1; break; case 'x': fSkipPrepro ^= 1; break; case 'c': fCheck ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader if ( fZeros || fBoth || fOnDc || fSkipPrepro ) { Abc_Ntk_t * pTemp; pNtk = Io_ReadPla( pFileName, fZeros, fBoth, fOnDc, fSkipPrepro, fCheck ); if ( pNtk == NULL ) { printf( "Reading PLA file has failed.\n" ); return 1; } pNtk = Abc_NtkToLogic( pTemp = pNtk ); Abc_NtkDelete( pTemp ); } else pNtk = Io_Read( pFileName, IO_FILE_PLA, fCheck, 0 ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_pla [-zbdxch] \n" ); fprintf( pAbc->Err, "\t reads the network in PLA\n" ); fprintf( pAbc->Err, "\t-z : toggle reading on-set and off-set [default = %s]\n", fZeros? "off-set":"on-set" ); fprintf( pAbc->Err, "\t-b : toggle reading both on-set and off-set as on-set [default = %s]\n", fBoth? "off-set":"on-set" ); fprintf( pAbc->Err, "\t-d : toggle reading both on-set and dc-set as on-set [default = %s]\n", fOnDc? "off-set":"on-set" ); fprintf( pAbc->Err, "\t-x : toggle reading Exclusive SOP rather than SOP [default = %s]\n", fSkipPrepro? "yes":"no" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadPlaMo( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Mop_ManTest( char * pFileName, int fMerge, int fVerbose ); Abc_Ntk_t * pNtk; int c, fMerge = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF ) { switch ( c ) { case 'm': fMerge ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pNtk = Mop_ManTest( argv[globalUtilOptind], fMerge, fVerbose ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_plamo [-mvh] \n" ); fprintf( pAbc->Err, "\t reads the network in multi-output PLA\n" ); fprintf( pAbc->Err, "\t-m : toggle dist-1 merge for cubes with identical outputs [default = %s]\n", fMerge? "yes":"no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pSopCover; int fHex; int c; fHex = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF ) { switch ( c ) { case 'x': fHex ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } // convert truth table to SOP if ( fHex ) pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]); else pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]); if ( pSopCover == NULL || pSopCover[0] == 0 ) { ABC_FREE( pSopCover ); fprintf( pAbc->Err, "Reading truth table has failed.\n" ); return 1; } pNtk = Abc_NtkCreateWithNode( pSopCover ); ABC_FREE( pSopCover ); if ( pNtk == NULL ) { fprintf( pAbc->Err, "Deriving the network has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_truth [-xh] \n" ); fprintf( pAbc->Err, "\t creates network with node having given truth table\n" ); fprintf( pAbc->Err, "\t-x : toggles between bin and hex representation [default = %s]\n", fHex? "hex":"bin" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\ttruth : truth table with most signficant bit first (e.g. 1000 for AND(a,b))\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk; char * pFileName; int fCheck, fBarBufs; int c; fCheck = 1; fBarBufs = 0; glo_fMapped = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "mcbh" ) ) != EOF ) { switch ( c ) { case 'm': glo_fMapped ^= 1; break; case 'c': fCheck ^= 1; break; case 'b': fBarBufs ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // read the file using the corresponding file reader pNtk = Io_Read( pFileName, IO_FILE_VERILOG, fCheck, fBarBufs ); if ( pNtk == NULL ) return 1; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Abc_FrameClearVerifStatus( pAbc ); return 0; usage: fprintf( pAbc->Err, "usage: read_verilog [-mcbh] \n" ); fprintf( pAbc->Err, "\t reads the network in Verilog (IWLS 2002/2005 subset)\n" ); fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); fprintf( pAbc->Err, "\t-b : toggle reading barrier buffers [default = %s]\n", fBarBufs? "yes":"no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileName; FILE * pFile; int c; extern int Abc_NtkReadLogFile( char * pFileName, Abc_Cex_t ** ppCex, int * pnFrames ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName ); return 1; } fclose( pFile ); // set the new network Abc_FrameClearVerifStatus( pAbc ); pAbc->Status = Abc_NtkReadLogFile( pFileName, &pAbc->pCex, &pAbc->nFrames ); return 0; usage: fprintf( pAbc->Err, "usage: read_status [-ch] \n" ); fprintf( pAbc->Err, "\t reads verification log file\n" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandReadGig( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManReadGig( char * pFileName ); Gia_Man_t * pAig; char * pFileName; FILE * pFile; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "r" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName ); return 1; } fclose( pFile ); // set the new network pAig = Gia_ManReadGig( pFileName ); Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: fprintf( pAbc->Err, "usage: &read_gig [-h] \n" ); fprintf( pAbc->Err, "\t reads design in GIG format\n" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWrite( Abc_Frame_t * pAbc, int argc, char **argv ) { char Command[1000]; 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; // get the output file name pFileName = argv[globalUtilOptind]; // write libraries Command[0] = 0; assert( strlen(pFileName) < 900 ); if ( !strcmp( Extra_FileNameExtension(pFileName), "genlib" ) ) sprintf( Command, "write_genlib %s", pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "lib" ) ) sprintf( Command, "write_liberty %s", pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "dsd" ) ) sprintf( Command, "dsd_save %s", pFileName ); if ( Command[0] ) { Cmd_CommandExecute( pAbc, Command ); return 0; } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); return 0; usage: fprintf( pAbc->Err, "usage: write [-h] \n" ); fprintf( pAbc->Err, "\t writes the current network into by calling\n" ); fprintf( pAbc->Err, "\t the writer that matches the extension of \n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteHie( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pBaseName, * pFileName; int c; glo_fMapped = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) { switch ( c ) { case 'm': glo_fMapped ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 2 ) goto usage; // get the output file name pBaseName = argv[globalUtilOptind]; pFileName = argv[globalUtilOptind+1]; // call the corresponding file writer // Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); Io_WriteHie( pAbc->pNtkCur, pBaseName, pFileName ); return 0; usage: fprintf( pAbc->Err, "usage: write_hie [-h] \n" ); fprintf( pAbc->Err, "\t writes the current network into by calling\n" ); fprintf( pAbc->Err, "\t the hierarchical writer that matches the extension of \n" ); fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog for [default = %s]\n", glo_fMapped? "yes":"no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\torig : the name of the original file with the hierarchical design\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteAiger( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int fWriteSymbols; int fCompact; int fUnique; int fVerbose; int c; fWriteSymbols = 0; fCompact = 0; fUnique = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "scuvh" ) ) != EOF ) { switch ( c ) { case 's': fWriteSymbols ^= 1; break; case 'c': fCompact ^= 1; break; case 'u': fUnique ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) { fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); return 1; } if ( fUnique ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); Aig_Man_t * pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 ); Aig_Man_t * pCan = Saig_ManDupIsoCanonical( pAig, fVerbose ); Abc_Ntk_t * pTemp = Abc_NtkFromAigPhase( pCan ); Aig_ManStop( pCan ); Aig_ManStop( pAig ); Io_WriteAiger( pTemp, pFileName, fWriteSymbols, fCompact, fUnique ); Abc_NtkDelete( pTemp ); } else Io_WriteAiger( pAbc->pNtkCur, pFileName, fWriteSymbols, fCompact, fUnique ); return 0; usage: fprintf( pAbc->Err, "usage: write_aiger [-scuvh] \n" ); fprintf( pAbc->Err, "\t writes the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); fprintf( pAbc->Err, "\t-s : toggle saving I/O names [default = %s]\n", fWriteSymbols? "yes" : "no" ); fprintf( pAbc->Err, "\t-c : toggle writing more compactly [default = %s]\n", fCompact? "yes" : "no" ); fprintf( pAbc->Err, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes" : "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aig)\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteAigerCex( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pCex == NULL ) { fprintf( pAbc->Out, "There is no current CEX.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; Io_WriteAigerCex( pAbc->pCex, pAbc->pNtkCur, pAbc->pGia, pFileName ); return 0; usage: fprintf( pAbc->Err, "usage: write_aiger_cex [-h] \n" ); fprintf( pAbc->Err, "\t writes the current CEX in the AIGER format (http://fmv.jku.at/aiger)\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BAF ); return 0; usage: fprintf( pAbc->Err, "usage: write_baf [-h] \n" ); fprintf( pAbc->Err, "\t writes the network into a BLIF file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .baf)\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteBblif( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BBLIF ); return 0; usage: fprintf( pAbc->Err, "usage: write_bblif [-h] \n" ); fprintf( pAbc->Err, "\t writes the network into a binary BLIF file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .bblif)\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; char * pLutStruct = NULL; int c, fSpecial = 0; int fUseHie = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Sjah" ) ) != EOF ) { switch ( c ) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); goto usage; } pLutStruct = argv[globalUtilOptind]; globalUtilOptind++; if ( strlen(pLutStruct) != 2 && strlen(pLutStruct) != 3 ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by a 2- or 3-char string (e.g. \"44\" or \"555\").\n" ); goto usage; } break; case 'j': fSpecial ^= 1; break; case 'a': fUseHie ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer if ( fSpecial || pLutStruct ) Io_WriteBlifSpecial( pAbc->pNtkCur, pFileName, pLutStruct, fUseHie ); else Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIF ); return 0; usage: fprintf( pAbc->Err, "usage: write_blif [-S str] [-jah] \n" ); fprintf( pAbc->Err, "\t writes the network into a BLIF file\n" ); fprintf( pAbc->Err, "\t-S str : string representing the LUT structure [default = %s]\n", pLutStruct ? pLutStruct : "not used" ); fprintf( pAbc->Err, "\t-j : enables special BLIF writing [default = %s]\n", fSpecial? "yes" : "no" );; fprintf( pAbc->Err, "\t-a : enables hierarchical BLIF writing for LUT structures [default = %s]\n", fUseHie? "yes" : "no" );; fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .blif)\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteBlifMv( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIFMV ); return 0; usage: fprintf( pAbc->Err, "usage: write_blif_mv [-h] \n" ); fprintf( pAbc->Err, "\t writes the network into a BLIF-MV file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .mv)\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int fUseLuts; int c; fUseLuts = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { case 'l': fUseLuts ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer if ( !fUseLuts ) Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BENCH ); else if ( pAbc->pNtkCur ) { Abc_Ntk_t * pNtkTemp; pNtkTemp = Abc_NtkToNetlist( pAbc->pNtkCur ); Abc_NtkToAig( pNtkTemp ); Io_WriteBenchLut( pNtkTemp, pFileName ); Abc_NtkDelete( pNtkTemp ); } else printf( "There is no current network.\n" ); return 0; usage: fprintf( pAbc->Err, "usage: write_bench [-lh] \n" ); fprintf( pAbc->Err, "\t writes the network in BENCH format\n" ); fprintf( pAbc->Err, "\t-l : toggle using LUTs in the output [default = %s]\n", fUseLuts? "yes" : "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .bench)\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteBook( Abc_Frame_t * pAbc, int argc, char **argv ) { 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; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BOOK ); return 0; usage: fprintf( pAbc->Err, "usage: write_book [-h] [-options]\n" ); fprintf( pAbc->Err, "\t-h : prints the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aux, .nodes, .nets)\n" ); fprintf( pAbc->Err, "\t\n" ); fprintf( pAbc->Err, "\tThis command is developed by Myungchul Kim (University of Michigan).\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk; char * pFileName; int c; extern void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; pNtk = pAbc->pNtkCur; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer if ( !Abc_NtkIsLogic(pNtk) ) { fprintf( pAbc->Out, "The network should be a logic network (if it an AIG, use command \"logic\")\n" ); return 0; } Io_WriteCellNet( pNtk, pFileName ); return 0; usage: fprintf( pAbc->Err, "usage: write_cellnet [-h] \n" ); fprintf( pAbc->Err, "\t writes the network is the cellnet format\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; int fNewAlgo; int fFastAlgo; int fAllPrimes; int fChangePol; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName, int fFastAlgo, int fChangePol, int fVerbose ); fNewAlgo = 1; fFastAlgo = 0; fAllPrimes = 0; fChangePol = 1; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "nfpcvh" ) ) != EOF ) { switch ( c ) { case 'n': fNewAlgo ^= 1; break; case 'f': fFastAlgo ^= 1; break; case 'p': fAllPrimes ^= 1; break; case 'c': fChangePol ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // check if the feature will be used if ( Abc_NtkIsStrash(pAbc->pNtkCur) && fAllPrimes ) { fAllPrimes = 0; printf( "Warning: Selected option to write all primes has no effect when deriving CNF from AIG.\n" ); } // call the corresponding file writer if ( fFastAlgo ) Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName, 1, fChangePol, fVerbose ); else if ( fNewAlgo ) Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName, 0, fChangePol, fVerbose ); else if ( fAllPrimes ) Io_WriteCnf( pAbc->pNtkCur, pFileName, 1 ); else Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_CNF ); return 0; usage: fprintf( pAbc->Err, "usage: write_cnf [-nfpcvh] \n" ); fprintf( pAbc->Err, "\t generates CNF for the miter (see also \"&write_cnf\")\n" ); fprintf( pAbc->Err, "\t-n : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" ); fprintf( pAbc->Err, "\t-f : toggle using fast algorithm [default = %s]\n", fFastAlgo? "yes" : "no" ); fprintf( pAbc->Err, "\t-p : toggle using all primes to enhance implicativity [default = %s]\n", fAllPrimes? "yes" : "no" ); fprintf( pAbc->Err, "\t-c : toggle adjasting polarity of internal variables [default = %s]\n", fChangePol? "yes" : "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes" : "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteCnf2( Abc_Frame_t * pAbc, int argc, char **argv ) { extern void Jf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int fVerbose ); extern void Mf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); FILE * pFile; char * pFileName; int nLutSize = 6; int fNewAlgo = 1; int fCnfObjIds = 0; int fAddOrCla = 1; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Kaiovh" ) ) != 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 'a': fNewAlgo ^= 1; break; case 'i': fCnfObjIds ^= 1; break; case 'o': fAddOrCla ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "IoCommandWriteCnf2(): There is no AIG.\n" ); return 1; } if ( Gia_ManRegNum(pAbc->pGia) > 0 ) { Abc_Print( -1, "IoCommandWriteCnf2(): Works only for combinational miters.\n" ); return 0; } if ( nLutSize < 3 || nLutSize > 8 ) { Abc_Print( -1, "IoCommandWriteCnf2(): Invalid LUT size (%d).\n", nLutSize ); return 0; } if ( !fNewAlgo && !Sdm_ManCanRead() ) { Abc_Print( -1, "IoCommandWriteCnf2(): Cannot input precomputed DSD information.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return 0; } fclose( pFile ); if ( fNewAlgo ) Mf_ManDumpCnf( pAbc->pGia, pFileName, nLutSize, fCnfObjIds, fAddOrCla, fVerbose ); else Jf_ManDumpCnf( pAbc->pGia, pFileName, fVerbose ); return 0; usage: fprintf( pAbc->Err, "usage: &write_cnf [-Kaiovh] \n" ); fprintf( pAbc->Err, "\t writes CNF produced by a new generator\n" ); fprintf( pAbc->Err, "\t-K : the LUT size (3 <= num <= 8) [default = %d]\n", nLutSize ); fprintf( pAbc->Err, "\t-a : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" ); fprintf( pAbc->Err, "\t-i : toggle using AIG object IDs as CNF variables [default = %s]\n", fCnfObjIds? "yes" : "no" ); fprintf( pAbc->Err, "\t-o : toggle adding OR clause for the outputs [default = %s]\n", fAddOrCla? "yes" : "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes" : "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_DOT ); return 0; usage: fprintf( pAbc->Err, "usage: write_dot [-h] \n" ); fprintf( pAbc->Err, "\t writes the current network into a DOT file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } ABC_NAMESPACE_IMPL_END #include "proof/fra/fra.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteCex( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk; char * pFileName; int c, fNames = 0; int fMinimize = 0; int fUseOldMin = 0; int fCheckCex = 0; int forceSeq = 0; int fAiger = 0; int fPrintFull = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "snmocafvh" ) ) != EOF ) { switch ( c ) { case 's': forceSeq ^= 1; break; case 'n': fNames ^= 1; break; case 'm': fMinimize ^= 1; break; case 'o': fUseOldMin ^= 1; break; case 'c': fCheckCex ^= 1; break; case 'a': fAiger ^= 1; break; case 'f': fPrintFull ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } pNtk = pAbc->pNtkCur; if ( pNtk == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( pNtk->pModel == NULL && pAbc->pCex == NULL ) { fprintf( pAbc->Out, "Counter-example is not available.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) { printf( "File name is missing on the command line.\n" ); goto usage; } // get the input file name pFileName = argv[globalUtilOptind]; // write the counter-example into the file if ( pAbc->pCex ) { Abc_Cex_t * pCex = pAbc->pCex; Abc_Obj_t * pObj; FILE * pFile; int i, f; Abc_NtkForEachLatch( pNtk, pObj, i ) if ( !Abc_LatchIsInit0(pObj) ) { fprintf( stdout, "IoCommandWriteCex(): The init-state should be all-0 for counter-example to work.\n" ); fprintf( stdout, "Run commands \"undc\" and \"zero\" and then rerun the equivalence check.\n" ); return 1; } pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "IoCommandWriteCex(): Cannot open the output file \"%s\".\n", pFileName ); return 1; } if ( fPrintFull ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); Abc_Cex_t * pCexFull = Saig_ManExtendCex( pAig, pCex ); Aig_ManStop( pAig ); // output PI values (while skipping the minimized ones) assert( pCexFull->nBits == Abc_NtkCiNum(pNtk) * (pCex->iFrame + 1) ); for ( f = 0; f <= pCex->iFrame; f++ ) Abc_NtkForEachCi( pNtk, pObj, i ) fprintf( pFile, "%s@%d=%c ", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCexFull->pData, Abc_NtkCiNum(pNtk)*f + i) ); Abc_CexFreeP( &pCexFull ); } else if ( fNames ) { Abc_Cex_t * pCare = NULL; if ( fMinimize ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); if ( fUseOldMin ) { pCare = Saig_ManCbaFindCexCareBits( pAig, pCex, 0, fVerbose ); if ( fCheckCex ) Bmc_CexCareVerify( pAig, pCex, pCare, fVerbose ); } else pCare = Bmc_CexCareMinimize( pAig, pCex, fCheckCex, fVerbose ); Aig_ManStop( pAig ); } // output flop values (unaffected by the minimization) Abc_NtkForEachLatch( pNtk, pObj, i ) fprintf( pFile, "%s@0=%c ", Abc_ObjName(Abc_ObjFanout0(pObj)), '0'+!Abc_LatchIsInit0(pObj) ); // output PI values (while skipping the minimized ones) for ( f = 0; f <= pCex->iFrame; f++ ) Abc_NtkForEachPi( pNtk, pObj, i ) if ( !pCare || Abc_InfoHasBit(pCare->pData, pCare->nRegs+pCare->nPis*f + i) ) fprintf( pFile, "%s@%d=%c ", Abc_ObjName(pObj), f, '0'+Abc_InfoHasBit(pCex->pData, pCex->nRegs+pCex->nPis*f + i) ); Abc_CexFreeP( &pCare ); } else { Abc_NtkForEachLatch( pNtk, pObj, i ) fprintf( pFile, "%c", '0'+!Abc_LatchIsInit0(pObj) ); for ( i = pCex->nRegs; i < pCex->nBits; i++ ) { if ( fAiger && (i-pCex->nRegs)%pCex->nPis == 0) fprintf( pFile, "\n"); fprintf( pFile, "%c", '0'+Abc_InfoHasBit(pCex->pData, i) ); } } fprintf( pFile, "\n" ); fclose( pFile ); } else { Abc_Obj_t * pObj; FILE * pFile = fopen( pFileName, "w" ); int i; if ( pFile == NULL ) { fprintf( stdout, "IoCommandWriteCex(): Cannot open the output file \"%s\".\n", pFileName ); return 1; } if ( fNames ) { const char *cycle_ctr = forceSeq?"@0":""; Abc_NtkForEachPi( pNtk, pObj, i ) // fprintf( pFile, "%s=%c\n", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) ); fprintf( pFile, "%s%s=%c\n", Abc_ObjName(pObj), cycle_ctr, '0'+(pNtk->pModel[i]==1) ); } else { Abc_NtkForEachPi( pNtk, pObj, i ) fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) ); } fprintf( pFile, "\n" ); fclose( pFile ); } return 0; usage: fprintf( pAbc->Err, "usage: write_cex [-snmocfvh] \n" ); fprintf( pAbc->Err, "\t saves counter-example derived by \"sat\", \"iprove\", or \"dprove\"\n" ); fprintf( pAbc->Err, "\t the file contains values for each PI in the natural order\n" ); fprintf( pAbc->Err, "\t-s : always report a sequential ctrex (cycle 0 for comb) [default = %s]\n", forceSeq? "yes": "no" ); fprintf( pAbc->Err, "\t-n : write input names into the file [default = %s]\n", fNames? "yes": "no" ); fprintf( pAbc->Err, "\t-m : minimize counter-example by dropping don't-care values [default = %s]\n", fMinimize? "yes": "no" ); fprintf( pAbc->Err, "\t-o : use old counter-example minimization algorithm [default = %s]\n", fUseOldMin? "yes": "no" ); fprintf( pAbc->Err, "\t-c : check generated counter-example using ternary simulation [default = %s]\n", fCheckCex? "yes": "no" ); fprintf( pAbc->Err, "\t-a : print cex in AIGER 1.9 format [default = %s].\n", fAiger? "yes": "no" ); fprintf( pAbc->Err, "\t-f : enable printing flop values in each timeframe [default = %s].\n", fPrintFull? "yes": "no" ); fprintf( pAbc->Err, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_EQN ); return 0; usage: fprintf( pAbc->Err, "usage: write_eqn [-h] \n" ); fprintf( pAbc->Err, "\t writes the current network in the equation format\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_GML ); return 0; usage: fprintf( pAbc->Err, "usage: write_gml [-h] \n" ); fprintf( pAbc->Err, "\t writes network using graph representation formal GML\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int fUseHost; int c; printf( "This command currently does not work.\n" ); return 0; fUseHost = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) { switch ( c ) { case 'n': fUseHost ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; /* if ( !Abc_NtkIsSeq(pAbc->pNtkCur) ) { fprintf( stdout, "IoCommandWriteList(): Can write adjacency list for sequential AIGs only.\n" ); return 0; } */ // get the input file name pFileName = argv[globalUtilOptind]; // write the file Io_WriteList( pAbc->pNtkCur, pFileName, fUseHost ); return 0; usage: fprintf( pAbc->Err, "usage: write_list [-nh] \n" ); fprintf( pAbc->Err, "\t writes network using graph representation formal GML\n" ); fprintf( pAbc->Err, "\t-n : toggle writing host node [default = %s]\n", fUseHost? "yes":"no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c, fUseMoPla = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) { switch ( c ) { case 'm': fUseMoPla ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, fUseMoPla ? IO_FILE_MOPLA : IO_FILE_PLA ); return 0; usage: fprintf( pAbc->Err, "usage: write_pla [-mh] \n" ); fprintf( pAbc->Err, "\t writes the collapsed network into a PLA file\n" ); fprintf( pAbc->Err, "\t-m : toggle writing multi-output PLA [default = %s]\n", fUseMoPla? "yes":"no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG ); return 0; usage: fprintf( pAbc->Err, "usage: write_verilog [-h] \n" ); fprintf( pAbc->Err, "\t writes the current network in Verilog format\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteSortCnf( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; int nVars = 16; int nQueens = 4; extern void Abc_NtkWriteSorterCnf( char * pFileName, int nVars, int nQueens ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NQh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { fprintf( stdout, "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 'Q': if ( globalUtilOptind >= argc ) { fprintf( stdout, "Command line switch \"-Q\" should be followed by an integer.\n" ); goto usage; } nQueens = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nQueens <= 0 ) goto usage; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; Abc_NtkWriteSorterCnf( pFileName, nVars, nQueens ); // call the corresponding file writer return 0; usage: fprintf( pAbc->Err, "usage: write_sorter_cnf [-N ] [-Q ] \n" ); fprintf( pAbc->Err, "\t writes CNF for the sorter\n" ); fprintf( pAbc->Err, "\t-N num : the number of sorter bits [default = %d]\n", nVars ); fprintf( pAbc->Err, "\t-Q num : the number of bits to be asserted to 1 [default = %d]\n", nQueens ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteTruth( Abc_Frame_t * pAbc, int argc, char **argv ) { Vec_Int_t * vTruth; Abc_Ntk_t * pNtk = pAbc->pNtkCur; Abc_Obj_t * pNode; char * pFileName; FILE * pFile; unsigned * pTruth; int fReverse = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rh" ) ) != EOF ) { switch ( c ) { case 'r': fReverse ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { printf( "Current network is not available.\n" ); return 0; } if ( !Abc_NtkIsLogic(pNtk) ) { printf( "Current network should not an AIG. Run \"logic\".\n" ); return 0; } if ( Abc_NtkPoNum(pNtk) != 1 ) { printf( "Current network should have exactly one primary output.\n" ); return 0; } if ( Abc_NtkNodeNum(pNtk) != 1 ) { printf( "Current network should have exactly one node.\n" ); return 0; } pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); if ( Abc_ObjFaninNum(pNode) == 0 ) { printf( "Can only write logic function with 0 inputs.\n" ); return 0; } if ( Abc_ObjFaninNum(pNode) > 16 ) { printf( "Can only write logic function with no more than 16 inputs.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // convert to logic Abc_NtkToAig( pNtk ); vTruth = Vec_IntAlloc( 0 ); pTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNtk->pManFunc, (Hop_Obj_t *)pNode->pData, Abc_ObjFaninNum(pNode), vTruth, fReverse ); pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { Vec_IntFree( vTruth ); printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return 0; } Extra_PrintBinary( pFile, pTruth, 1<Err, "usage: write_truth [-rh] \n" ); fprintf( pAbc->Err, "\t writes truth table into a file\n" ); fprintf( pAbc->Err, "\t-r : toggle reversing bits in the truth table [default = %s]\n", fReverse? "yes":"no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteTruths( Abc_Frame_t * pAbc, int argc, char **argv ) { Gia_Obj_t * pObj; char * pFileName; FILE * pFile; word * pTruth; int nBytes; int fReverse = 0; int fBinary = 0; int c, i; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rbh" ) ) != EOF ) { switch ( c ) { case 'r': fReverse ^= 1; break; case 'b': fBinary ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pGia == NULL ) { Abc_Print( -1, "IoCommandWriteTruths(): There is no AIG.\n" ); return 1; } if ( Gia_ManPiNum(pAbc->pGia) > 16 ) { Abc_Print( -1, "IoCommandWriteTruths(): Can write truth tables up to 16 inputs.\n" ); return 0; } if ( Gia_ManPiNum(pAbc->pGia) < 3 ) { Abc_Print( -1, "IoCommandWriteTruths(): Can write truth tables for 3 inputs or more.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; // convert to logic pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return 0; } nBytes = 8 * Abc_Truth6WordNum( Gia_ManPiNum(pAbc->pGia) ); Gia_ManForEachCo( pAbc->pGia, pObj, i ) { pTruth = Gia_ObjComputeTruthTable( pAbc->pGia, pObj ); if ( fBinary ) fwrite( pTruth, nBytes, 1, pFile ); else Extra_PrintHex( pFile, (unsigned *)pTruth, Gia_ManPiNum(pAbc->pGia) ), fprintf( pFile, "\n" ); } fclose( pFile ); return 0; usage: fprintf( pAbc->Err, "usage: &write_truths [-rbh] \n" ); fprintf( pAbc->Err, "\t writes truth tables of each PO of GIA manager into a file\n" ); fprintf( pAbc->Err, "\t-r : toggle reversing bits in the truth table [default = %s]\n", fReverse? "yes":"no" ); fprintf( pAbc->Err, "\t-b : toggle using binary format [default = %s]\n", fBinary? "yes":"no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteStatus( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int c; extern void Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pCex, int Status, int nFrames, char * pCommand ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; Abc_NtkWriteLogFile( pFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, NULL ); return 0; usage: fprintf( pAbc->Err, "usage: write_status [-h] \n" ); fprintf( pAbc->Err, "\t writes verification log file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int IoCommandWriteSmv( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName; int fUseLuts; int c; fUseLuts = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkCur == NULL ) { fprintf( pAbc->Out, "Empty network.\n" ); return 0; } if ( argc != globalUtilOptind + 1 ) goto usage; // get the output file name pFileName = argv[globalUtilOptind]; // call the corresponding file writer Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_SMV ); return 0; usage: fprintf( pAbc->Err, "usage: write_smv [-h] \n" ); fprintf( pAbc->Err, "\t write the network in SMV format\n" ); fprintf( pAbc->Err, "\t-h : print the help message\n" ); fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .smv)\n" ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioAbc.h000066400000000000000000000220521300674244400225440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioAbc.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioAbc.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__io__ioAbc_h #define ABC__base__io__ioAbc_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" #include "misc/extra/extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // network functionality typedef enum { IO_FILE_NONE = 0, IO_FILE_AIGER, IO_FILE_BAF, IO_FILE_BBLIF, IO_FILE_BLIF, IO_FILE_BLIFMV, IO_FILE_BENCH, IO_FILE_BOOK, IO_FILE_CNF, IO_FILE_DOT, IO_FILE_EDIF, IO_FILE_EQN, IO_FILE_GML, IO_FILE_LIST, IO_FILE_PLA, IO_FILE_MOPLA, IO_FILE_SMV, IO_FILE_VERILOG, IO_FILE_UNKNOWN } Io_FileType_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define IO_WRITE_LINE_LENGTH 78 // the output line length //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== abcReadAiger.c ==========================================================*/ extern Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ); /*=== abcReadBaf.c ============================================================*/ extern Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ); /*=== abcReadBblif.c ============================================================*/ extern Abc_Ntk_t * Io_ReadBblif( char * pFileName, int fCheck ); /*=== abcReadBlif.c ===========================================================*/ extern Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ); /*=== abcReadBlifMv.c =========================================================*/ extern Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ); /*=== abcReadBench.c ==========================================================*/ extern Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ); extern void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcReadEdif.c ===========================================================*/ extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ); /*=== abcReadEqn.c ============================================================*/ extern Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ); /*=== abcReadPla.c ============================================================*/ extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fBoth, int fOnDc, int fSkipPrepro, int fCheck ); /*=== abcReadVerilog.c ========================================================*/ extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ); /*=== abcWriteAiger.c =========================================================*/ extern void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact, int fUnique ); extern void Io_WriteAigerCex( Abc_Cex_t * pCex, Abc_Ntk_t * pNtk, void * pG, char * pFileName ); /*=== abcWriteBaf.c ===========================================================*/ extern void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWriteBblif.c ===========================================================*/ extern void Io_WriteBblif( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWriteBlif.c ==========================================================*/ extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches, int fBb2Wb, int fSeq ); extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); extern void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie ); /*=== abcWriteBlifMv.c ==========================================================*/ extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteBench.c =========================================================*/ extern int Io_WriteBench( Abc_Ntk_t * pNtk, const char * FileName ); extern int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteBook.c =========================================================*/ extern void Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteCnf.c ===========================================================*/ extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes ); /*=== abcWriteDot.c ===========================================================*/ extern void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ); extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); /*=== abcWriteEqn.c ===========================================================*/ extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWriteGml.c ===========================================================*/ extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); /*=== abcWriteList.c ==========================================================*/ extern void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ); /*=== abcWritePla.c ===========================================================*/ extern int Io_WritePla( Abc_Ntk_t * pNtk, char * FileName ); extern int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteSmv.c ===========================================================*/ extern int Io_WriteSmv( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcWriteVerilog.c =======================================================*/ extern void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName ); /*=== abcUtil.c ===============================================================*/ extern Io_FileType_t Io_ReadFileType( char * pFileName ); extern Io_FileType_t Io_ReadLibType( char * pFileName ); extern Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ); extern Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck, int fBarBufs ); extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ); extern void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ); extern Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ); extern Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ); extern Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ); extern Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ); extern Abc_Obj_t * Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv ); extern Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ); extern Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, int fConst1 ); extern Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); extern Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioInt.h000066400000000000000000000036441300674244400226170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__io__ioInt_h #define ABC__base__io__ioInt_h ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadAiger.c000066400000000000000000000465241300674244400237070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadAiger.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: ioReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] ***********************************************************************/ // The code in this file is developed in collaboration with Mark Jarvin of Toronto. #include #include #include #include #include "misc/bzlib/bzlib.h" #include "misc/zlib/zlib.h" #include "ioAbc.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 [] ***********************************************************************/ static inline unsigned Io_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 * Io_WriteDecodeLiterals( char ** ppPos, int nEntries ) { Vec_Int_t * vLits; int Lit, LitPrev, Diff, i; vLits = Vec_IntAlloc( nEntries ); LitPrev = Io_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 = Io_ReadAigerDecode( ppPos ); Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1; Lit = Diff + LitPrev; Vec_IntPush( vLits, Lit ); LitPrev = Lit; } return vLits; } /**Function************************************************************* Synopsis [Reads the file into a character buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ typedef struct buflist { char buf[1<<20]; int nBuf; struct buflist * next; } buflist; static char * Ioa_ReadLoadFileBz2Aig( char * pFileName, int * pFileSize ) { FILE * pFile; int nFileSize = 0; char * pContents; BZFILE * b; int bzError; struct buflist * pNext; buflist * bufHead = NULL, * buf = NULL; int RetValue; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Ioa_ReadLoadFileBz2(): The file is unavailable (absent or open).\n" ); return NULL; } b = BZ2_bzReadOpen(&bzError,pFile,0,0,NULL,0); if (bzError != BZ_OK) { printf( "Ioa_ReadLoadFileBz2(): BZ2_bzReadOpen() failed with error %d.\n",bzError ); return NULL; } do { if (!bufHead) buf = bufHead = ABC_ALLOC( buflist, 1 ); else buf = buf->next = ABC_ALLOC( buflist, 1 ); nFileSize += buf->nBuf = BZ2_bzRead(&bzError,b,buf->buf,1<<20); buf->next = NULL; } while (bzError == BZ_OK); if (bzError == BZ_STREAM_END) { // we're okay char * p; int nBytes = 0; BZ2_bzReadClose(&bzError,b); p = pContents = ABC_ALLOC( char, nFileSize + 10 ); buf = bufHead; do { memcpy(p+nBytes,buf->buf,buf->nBuf); nBytes += buf->nBuf; // } while((buf = buf->next)); pNext = buf->next; ABC_FREE( buf ); } while((buf = pNext)); } else if (bzError == BZ_DATA_ERROR_MAGIC) { // not a BZIP2 file BZ2_bzReadClose(&bzError,b); fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); if ( nFileSize == 0 ) { printf( "Ioa_ReadLoadFileBz2(): The file is empty.\n" ); return NULL; } pContents = ABC_ALLOC( char, nFileSize + 10 ); rewind( pFile ); RetValue = fread( pContents, nFileSize, 1, pFile ); } else { // Some other error. printf( "Ioa_ReadLoadFileBz2(): Unable to read the compressed BLIF.\n" ); return NULL; } fclose( pFile ); // finish off the file with the spare .end line // some benchmarks suddenly break off without this line // strcpy( pContents + nFileSize, "\n.end\n" ); *pFileSize = nFileSize; return pContents; } /**Function************************************************************* Synopsis [Reads the file into a character buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static char * Ioa_ReadLoadFileGzAig( char * pFileName, int * pFileSize ) { const int READ_BLOCK_SIZE = 100000; gzFile pFile; char * pContents; int amtRead, readBlock, nFileSize = READ_BLOCK_SIZE; pFile = gzopen( pFileName, "rb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen pContents = ABC_ALLOC( char, nFileSize ); readBlock = 0; while ((amtRead = gzread(pFile, pContents + readBlock * READ_BLOCK_SIZE, READ_BLOCK_SIZE)) == READ_BLOCK_SIZE) { //printf("%d: read %d bytes\n", readBlock, amtRead); nFileSize += READ_BLOCK_SIZE; pContents = ABC_REALLOC(char, pContents, nFileSize); ++readBlock; } //printf("%d: read %d bytes\n", readBlock, amtRead); assert( amtRead != -1 ); // indicates a zlib error nFileSize -= (READ_BLOCK_SIZE - amtRead); gzclose(pFile); *pFileSize = nFileSize; return pContents; } /**Function************************************************************* Synopsis [Reads the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) { ProgressBar * pProgress; FILE * pFile; Vec_Ptr_t * vNodes, * vTerms; Vec_Int_t * vLits = NULL; Abc_Obj_t * pObj, * pNode0, * pNode1; Abc_Ntk_t * pNtkNew; int nTotal, nInputs, nOutputs, nLatches, nAnds; int nBad = 0, nConstr = 0, nJust = 0, nFair = 0; int nFileSize = -1, iTerm, nDigits, i; char * pContents, * pDrivers = NULL, * pSymbols, * pCur, * pName, * pType; unsigned uLit0, uLit1, uLit; int RetValue; // read the file into the buffer if ( !strncmp(pFileName+strlen(pFileName)-4,".bz2",4) ) pContents = Ioa_ReadLoadFileBz2Aig( pFileName, &nFileSize ); else if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) pContents = Ioa_ReadLoadFileGzAig( pFileName, &nFileSize ); else { // pContents = Ioa_ReadLoadFile( pFileName ); nFileSize = Extra_FileSize( pFileName ); pFile = fopen( pFileName, "rb" ); pContents = ABC_ALLOC( char, nFileSize ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); } // 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" ); ABC_FREE( pContents ); 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" ); ABC_FREE( pContents ); return NULL; } pCur++; // check the parameters if ( nTotal != nInputs + nLatches + nAnds ) { fprintf( stdout, "The number of objects does not match.\n" ); ABC_FREE( pContents ); return NULL; } if ( nJust || nFair ) { fprintf( stdout, "Reading AIGER files with liveness properties is currently not supported.\n" ); ABC_FREE( pContents ); 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 pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pName = Extra_FileNameGeneric( pFileName ); pNtkNew->pName = Extra_UtilStrsav( pName ); pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); ABC_FREE( pName ); pNtkNew->nConstrs = nConstr; // prepare the array of nodes vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); Vec_PtrPush( vNodes, Abc_ObjNot( Abc_AigConst1(pNtkNew) ) ); // create the PIs for ( i = 0; i < nInputs; i++ ) { pObj = Abc_NtkCreatePi(pNtkNew); Vec_PtrPush( vNodes, pObj ); } // create the POs for ( i = 0; i < nOutputs; i++ ) { pObj = Abc_NtkCreatePo(pNtkNew); } // create the latches nDigits = Abc_Base10Log( nLatches ); for ( i = 0; i < nLatches; i++ ) { pObj = Abc_NtkCreateLatch(pNtkNew); Abc_LatchSetInit0( pObj ); pNode0 = Abc_NtkCreateBi(pNtkNew); pNode1 = Abc_NtkCreateBo(pNtkNew); Abc_ObjAddFanin( pObj, pNode0 ); Abc_ObjAddFanin( pNode1, pObj ); Vec_PtrPush( vNodes, pNode1 ); // assign names to latch and its input // Abc_ObjAssignName( pObj, Abc_ObjNameDummy("_L", i, nDigits), NULL ); // printf( "Creating latch %s with input %d and output %d.\n", Abc_ObjName(pObj), pNode0->Id, pNode1->Id ); } if ( pContents[3] == ' ' ) // standard AIGER { // remember the beginning of latch/PO literals pDrivers = pCur; // scroll to the beginning of the binary data for ( i = 0; i < nLatches + nOutputs; ) if ( *pCur++ == '\n' ) i++; } else // modified AIGER { vLits = Io_WriteDecodeLiterals( &pCur, nLatches + nOutputs ); } // create the AND gates pProgress = Extra_ProgressBarStart( stdout, nAnds ); for ( i = 0; i < nAnds; i++ ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); uLit = ((i + 1 + nInputs + nLatches) << 1); uLit1 = uLit - Io_ReadAigerDecode( &pCur ); uLit0 = uLit1 - Io_ReadAigerDecode( &pCur ); // assert( uLit1 > uLit0 ); pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); pNode1 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); Vec_PtrPush( vNodes, Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pNode0, pNode1) ); } Extra_ProgressBarStop( pProgress ); // remember the place where symbols begin pSymbols = pCur; // read the latch driver literals pCur = pDrivers; if ( pContents[3] == ' ' ) // standard AIGER { Abc_NtkForEachLatchInput( pNtkNew, pObj, i ) { uLit0 = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; if ( *pCur == ' ' ) // read initial value { int Init; pCur++; Init = atoi( pCur ); if ( Init == 0 ) Abc_LatchSetInit0( Abc_NtkBox(pNtkNew, i) ); else if ( Init == 1 ) Abc_LatchSetInit1( Abc_NtkBox(pNtkNew, i) ); else { assert( Init == Abc_Var2Lit(1+Abc_NtkPiNum(pNtkNew)+i, 0) ); // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf Abc_LatchSetInitDc( Abc_NtkBox(pNtkNew, i) ); } while ( *pCur != ' ' && *pCur != '\n' ) pCur++; } if ( *pCur != '\n' ) { fprintf( stdout, "The initial value of latch number %d is not recongnized.\n", i ); return NULL; } pCur++; pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); Abc_ObjAddFanin( pObj, pNode0 ); } // read the PO driver literals Abc_NtkForEachPo( pNtkNew, pObj, i ) { uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); Abc_ObjAddFanin( pObj, pNode0 ); } } else { // read the latch driver literals Abc_NtkForEachLatchInput( pNtkNew, pObj, i ) { uLit0 = Vec_IntEntry( vLits, i ); pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Abc_ObjAddFanin( pObj, pNode0 ); } // read the PO driver literals Abc_NtkForEachPo( pNtkNew, pObj, i ) { uLit0 = Vec_IntEntry( vLits, i+Abc_NtkLatchNum(pNtkNew) ); pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Abc_ObjAddFanin( pObj, pNode0 ); } Vec_IntFree( vLits ); } // read the names if present pCur = pSymbols; if ( pCur < pContents + nFileSize && *pCur != 'c' ) { int Counter = 0; while ( pCur < pContents + nFileSize && *pCur != 'c' ) { // get the terminal type pType = pCur; if ( *pCur == 'i' ) vTerms = pNtkNew->vPis; else if ( *pCur == 'l' ) vTerms = pNtkNew->vBoxes; else if ( *pCur == 'o' || *pCur == 'b' || *pCur == 'c' || *pCur == 'j' || *pCur == 'f' ) vTerms = pNtkNew->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 = (Abc_Obj_t *)Vec_PtrEntry( vTerms, iTerm ); if ( *pType == 'l' ) pObj = Abc_ObjFanout0(pObj); // assign the name pName = pCur; while ( *pCur++ != '\n' ); // assign this name *(pCur-1) = 0; Abc_ObjAssignName( pObj, pName, NULL ); if ( *pType == 'l' ) { Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); } // mark the node as named pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); } // assign the remaining names Abc_NtkForEachPi( pNtkNew, pObj, i ) { if ( pObj->pCopy ) continue; Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); Counter++; } Abc_NtkForEachLatchOutput( pNtkNew, pObj, i ) { if ( pObj->pCopy ) continue; Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); Counter++; } Abc_NtkForEachPo( pNtkNew, pObj, i ) { if ( pObj->pCopy ) continue; Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); Counter++; } // if ( Counter ) // printf( "Io_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); } else { // printf( "Io_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); Abc_NtkShortNames( pNtkNew ); } // read the name of the model if given pCur = pSymbols; if ( pCur + 1 < pContents + nFileSize && *pCur == 'c' ) { pCur++; if ( *pCur == 'n' ) { pCur++; // read model name if ( strlen(pCur) > 0 ) { ABC_FREE( pNtkNew->pName ); pNtkNew->pName = Extra_UtilStrsav( pCur ); } } } // skipping the comments ABC_FREE( pContents ); Vec_PtrFree( vNodes ); // remove the extra nodes Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc ); // update polarity of the additional outputs if ( nBad || nConstr || nJust || nFair ) Abc_NtkInvertConstraints( pNtkNew ); // check the result if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) { printf( "Io_ReadAiger: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadBaf.c000066400000000000000000000132261300674244400233410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadBaf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read AIG in the binary format.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the AIG in the binary format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ) { ProgressBar * pProgress; FILE * pFile; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pNode0, * pNode1; Abc_Ntk_t * pNtkNew; int nInputs, nOutputs, nLatches, nAnds, nFileSize, Num, i; char * pContents, * pName, * pCur; unsigned * pBufferNode; int RetValue; // read the file into the buffer nFileSize = Extra_FileSize( pFileName ); pFile = fopen( pFileName, "rb" ); pContents = ABC_ALLOC( char, nFileSize ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); // skip the comments (comment lines begin with '#' and end with '\n') for ( pCur = pContents; *pCur == '#'; ) while ( *pCur++ != '\n' ); // read the name pName = pCur; while ( *pCur++ ); // read the number of inputs nInputs = atoi( pCur ); while ( *pCur++ ); // read the number of outputs nOutputs = atoi( pCur ); while ( *pCur++ ); // read the number of latches nLatches = atoi( pCur ); while ( *pCur++ ); // read the number of nodes nAnds = atoi( pCur ); while ( *pCur++ ); // allocate the empty AIG pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkNew->pName = Extra_UtilStrsav( pName ); pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); // prepare the array of nodes vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); Vec_PtrPush( vNodes, Abc_AigConst1(pNtkNew) ); // create the PIs for ( i = 0; i < nInputs; i++ ) { pObj = Abc_NtkCreatePi(pNtkNew); Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); Vec_PtrPush( vNodes, pObj ); } // create the POs for ( i = 0; i < nOutputs; i++ ) { pObj = Abc_NtkCreatePo(pNtkNew); Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); } // create the latches for ( i = 0; i < nLatches; i++ ) { pObj = Abc_NtkCreateLatch(pNtkNew); Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); pNode0 = Abc_NtkCreateBi(pNtkNew); Abc_ObjAssignName( pNode0, pCur, NULL ); while ( *pCur++ ); pNode1 = Abc_NtkCreateBo(pNtkNew); Abc_ObjAssignName( pNode1, pCur, NULL ); while ( *pCur++ ); Vec_PtrPush( vNodes, pNode1 ); Abc_ObjAddFanin( pObj, pNode0 ); Abc_ObjAddFanin( pNode1, pObj ); } // get the pointer to the beginning of the node array pBufferNode = (unsigned *)(pContents + (nFileSize - (2 * nAnds + nOutputs + nLatches) * sizeof(int)) ); // make sure we are at the place where the nodes begin if ( pBufferNode != (unsigned *)pCur ) { ABC_FREE( pContents ); Vec_PtrFree( vNodes ); Abc_NtkDelete( pNtkNew ); printf( "Warning: Internal reader error.\n" ); return NULL; } // create the AND gates pProgress = Extra_ProgressBarStart( stdout, nAnds ); for ( i = 0; i < nAnds; i++ ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, pBufferNode[2*i+0] >> 1), pBufferNode[2*i+0] & 1 ); pNode1 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, pBufferNode[2*i+1] >> 1), pBufferNode[2*i+1] & 1 ); Vec_PtrPush( vNodes, Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pNode0, pNode1) ); } Extra_ProgressBarStop( pProgress ); // read the POs Abc_NtkForEachCo( pNtkNew, pObj, i ) { Num = pBufferNode[2*nAnds+i]; if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) { Abc_ObjSetData( Abc_ObjFanout0(pObj), (void *)(ABC_PTRINT_T)(Num & 3) ); Num >>= 2; } pNode0 = Abc_ObjNotCond( (Abc_Obj_t *)Vec_PtrEntry(vNodes, Num >> 1), Num & 1 ); Abc_ObjAddFanin( pObj, pNode0 ); } ABC_FREE( pContents ); Vec_PtrFree( vNodes ); // remove the extra nodes // Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc ); // check the result if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) { printf( "Io_ReadBaf: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadBblif.c000066400000000000000000000253031300674244400236660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadBblif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read AIG in the binary format.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadBblif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "bool/dec/dec.h" #include "misc/bbl/bblif.h" ABC_NAMESPACE_IMPL_START // For description of Binary BLIF format, refer to "abc/src/aig/bbl/bblif.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Fnction************************************************************* Synopsis [Constructs ABC network from the manager.] Description [The ABC network is started, as well as the array vCopy, which will map the new ID of each object in the BBLIF manager into the ponter ot the corresponding object in the ABC. For each internal node, determined by Bbl_ObjIsLut(), the SOP representation is created by retrieving the SOP representation of the BBLIF object. Finally, the objects are connected using fanin/fanout creation, and the dummy names are assigned because ABC requires each CI/CO to have a name.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Bbl_ManToAbc( Bbl_Man_t * p ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pObjNew; Bbl_Obj_t * pObj, * pFanin; Vec_Ptr_t * vCopy; // start the network pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); pNtk->pName = Extra_UtilStrsav( Bbl_ManName(p) ); // create objects vCopy = Vec_PtrStart( 1000 ); Bbl_ManForEachObj( p, pObj ) { if ( Bbl_ObjIsInput(pObj) ) pObjNew = Abc_NtkCreatePi( pNtk ); else if ( Bbl_ObjIsOutput(pObj) ) pObjNew = Abc_NtkCreatePo( pNtk ); else if ( Bbl_ObjIsLut(pObj) ) pObjNew = Abc_NtkCreateNode( pNtk ); else assert( 0 ); if ( Bbl_ObjIsLut(pObj) ) pObjNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, Bbl_ObjSop(p, pObj) ); Vec_PtrSetEntry( vCopy, Bbl_ObjId(pObj), pObjNew ); } // connect objects Bbl_ManForEachObj( p, pObj ) Bbl_ObjForEachFanin( pObj, pFanin ) Abc_ObjAddFanin( (Abc_Obj_t *)Vec_PtrEntry(vCopy, Bbl_ObjId(pObj)), (Abc_Obj_t *)Vec_PtrEntry(vCopy, Bbl_ObjId(pFanin)) ); // finalize Vec_PtrFree( vCopy ); Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); if ( !Abc_NtkCheck( pNtk ) ) printf( "Bbl_ManToAbc(): Network check has failed.\n" ); return pNtk; } /**Fnction************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManDfs_rec( Bbl_Obj_t * pObj, Vec_Ptr_t * vNodes ) { extern void Bbl_ObjMark( Bbl_Obj_t * p ); extern int Bbl_ObjIsMarked( Bbl_Obj_t * p ); Bbl_Obj_t * pFanin; if ( Bbl_ObjIsMarked(pObj) || Bbl_ObjIsInput(pObj) ) return; Bbl_ObjForEachFanin( pObj, pFanin ) Bbl_ManDfs_rec( pFanin, vNodes ); assert( !Bbl_ObjIsMarked(pObj) ); // checks if acyclic Bbl_ObjMark( pObj ); Vec_PtrPush( vNodes, pObj ); } /**Fnction************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Bbl_ManDfs( Bbl_Man_t * p ) { Vec_Ptr_t * vNodes; Bbl_Obj_t * pObj; vNodes = Vec_PtrAlloc( 1000 ); Bbl_ManForEachObj( p, pObj ) if ( Bbl_ObjIsLut(pObj) ) Bbl_ManDfs_rec( pObj, vNodes ); return vNodes; } /**Fnction************************************************************* Synopsis [Constructs AIG in ABC from the manager.] Description [The ABC network is started, as well as the array vCopy, which will map the new ID of each object in the BBLIF manager into the ponter ot the corresponding AIG object in the ABC. For each internal node in a topological oder the AIG representation is created by factoring the SOP representation of the BBLIF object. Finally, the CO objects are created, and the dummy names are assigned because ABC requires each CI/CO to have a name.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Bbl_ManToAig( Bbl_Man_t * p ) { extern int Bbl_ManFncSize( Bbl_Man_t * p ); extern int Bbl_ObjFncHandle( Bbl_Obj_t * p ); extern Abc_Obj_t * Dec_GraphToAig( Abc_Ntk_t * pNtk, Dec_Graph_t * pFForm, Vec_Ptr_t * vFaninAigs ); int fVerbose = 0; Abc_Ntk_t * pNtk; Abc_Obj_t * pObjNew; Bbl_Obj_t * pObj, * pFanin; Vec_Ptr_t * vCopy, * vNodes, * vFaninAigs; Dec_Graph_t ** pFForms; int i; abctime clk; clk = Abc_Clock(); // map SOP handles into factored forms pFForms = ABC_CALLOC( Dec_Graph_t *, Bbl_ManFncSize(p) ); Bbl_ManForEachObj( p, pObj ) if ( pFForms[Bbl_ObjFncHandle(pObj)] == NULL ) pFForms[Bbl_ObjFncHandle(pObj)] = Dec_Factor( Bbl_ObjSop(p, pObj) ); if ( fVerbose ) ABC_PRT( "Fct", Abc_Clock() - clk ); // start the network pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtk->pName = Extra_UtilStrsav( Bbl_ManName(p) ); vCopy = Vec_PtrStart( 1000 ); // create CIs Bbl_ManForEachObj( p, pObj ) { if ( !Bbl_ObjIsInput(pObj) ) continue; Vec_PtrSetEntry( vCopy, Bbl_ObjId(pObj), Abc_NtkCreatePi(pNtk) ); } clk = Abc_Clock(); // create internal nodes vNodes = Bbl_ManDfs( p ); vFaninAigs = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Bbl_Obj_t *, vNodes, pObj, i ) { // collect fanin AIGs Vec_PtrClear( vFaninAigs ); Bbl_ObjForEachFanin( pObj, pFanin ) Vec_PtrPush( vFaninAigs, Vec_PtrEntry( vCopy, Bbl_ObjId(pFanin) ) ); // create the new node pObjNew = Dec_GraphToAig( pNtk, pFForms[Bbl_ObjFncHandle(pObj)], vFaninAigs ); Vec_PtrSetEntry( vCopy, Bbl_ObjId(pObj), pObjNew ); } Vec_PtrFree( vFaninAigs ); Vec_PtrFree( vNodes ); if ( fVerbose ) ABC_PRT( "AIG", Abc_Clock() - clk ); // create COs Bbl_ManForEachObj( p, pObj ) { if ( !Bbl_ObjIsOutput(pObj) ) continue; pObjNew = (Abc_Obj_t *)Vec_PtrEntry( vCopy, Bbl_ObjId(Bbl_ObjFaninFirst(pObj)) ); Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pObjNew ); } Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); // clear factored forms for ( i = Bbl_ManFncSize(p) - 1; i >= 0; i-- ) if ( pFForms[i] ) Dec_GraphFree( pFForms[i] ); ABC_FREE( pFForms ); // finalize clk = Abc_Clock(); Vec_PtrFree( vCopy ); Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); if ( fVerbose ) ABC_PRT( "Nam", Abc_Clock() - clk ); // if ( !Abc_NtkCheck( pNtk ) ) // printf( "Bbl_ManToAig(): Network check has failed.\n" ); return pNtk; } /**Fnction************************************************************* Synopsis [Verifies equivalence for two combinational networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManVerify( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) { extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); Abc_Ntk_t * pAig1, * pAig2; pAig1 = Abc_NtkStrash( pNtk1, 0, 1, 0 ); pAig2 = Abc_NtkStrash( pNtk2, 0, 1, 0 ); Abc_NtkShortNames( pAig1 ); Abc_NtkShortNames( pAig2 ); Abc_NtkCecFraig( pAig1, pAig2, 0, 0 ); Abc_NtkDelete( pAig1 ); Abc_NtkDelete( pAig2 ); } /**Fnction************************************************************* Synopsis [Performs testing of the new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManTest( Abc_Ntk_t * pNtk ) { extern Bbl_Man_t * Bbl_ManFromAbc( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pNtkNew; Bbl_Man_t * p, * pNew; char * pFileName = "test.bblif"; abctime clk, clk1, clk2, clk3, clk4, clk5; clk = Abc_Clock(); p = Bbl_ManFromAbc( pNtk ); Bbl_ManPrintStats( p ); clk1 = Abc_Clock() - clk; //Bbl_ManDumpBlif( p, "test_bbl.blif" ); // write into file and back clk = Abc_Clock(); Bbl_ManDumpBinaryBlif( p, pFileName ); clk2 = Abc_Clock() - clk; // read from file clk = Abc_Clock(); pNew = Bbl_ManReadBinaryBlif( pFileName ); Bbl_ManStop( p ); p = pNew; clk3 = Abc_Clock() - clk; // generate ABC network clk = Abc_Clock(); pNtkNew = Bbl_ManToAig( p ); // pNtkNew = Bbl_ManToAbc( p ); Bbl_ManStop( p ); clk4 = Abc_Clock() - clk; // equivalence check clk = Abc_Clock(); // Bbl_ManVerify( pNtk, pNtkNew ); Abc_NtkDelete( pNtkNew ); clk5 = Abc_Clock() - clk; printf( "Runtime stats:\n" ); ABC_PRT( "ABC to Man", clk1 ); ABC_PRT( "Writing ", clk2 ); ABC_PRT( "Reading ", clk3 ); ABC_PRT( "Man to ABC", clk4 ); ABC_PRT( "Verify ", clk5 ); } /**Function************************************************************* Synopsis [Reads the AIG in the binary format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBblif( char * pFileName, int fCheck ) { Bbl_Man_t * p; Abc_Ntk_t * pNtkNew; // read the file p = Bbl_ManReadBinaryBlif( pFileName ); pNtkNew = Bbl_ManToAig( p ); Bbl_ManStop( p ); // check the result if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) { printf( "Io_ReadBaf: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadBench.c000066400000000000000000000355671300674244400237040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadBench.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read BENCH files.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the network from a BENCH file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ) { Extra_FileReader_t * p; Abc_Ntk_t * pNtk; // start the file p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t,()=" ); if ( p == NULL ) return NULL; // read the network pNtk = Io_ReadBenchNetwork( p ); Extra_FileReaderFree( p ); if ( pNtk == NULL ) return NULL; // make sure that everything is okay with the network structure if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) { printf( "Io_ReadBench: The network check has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) { ProgressBar * pProgress; Vec_Ptr_t * vTokens; Abc_Ntk_t * pNtk; Abc_Obj_t * pNode, * pNet; Vec_Str_t * vString; unsigned uTruth[8]; char * pType, ** ppNames, * pString; int iLine, nNames, nDigits, fLutsPresent = 0; // allocate the empty network pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); pNtk->nConstrs = 0; // go through the lines of the file vString = Vec_StrAlloc( 100 ); pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); for ( iLine = 0; (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)); iLine++ ) { Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); if ( vTokens->nSize == 1 ) { printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); Vec_StrFree( vString ); Abc_NtkDelete( pNtk ); return NULL; } // get the type of the line if ( strncmp( (char *)vTokens->pArray[0], "INPUT", 5 ) == 0 ) Io_ReadCreatePi( pNtk, (char *)vTokens->pArray[1] ); else if ( strncmp( (char *)vTokens->pArray[0], "OUTPUT", 5 ) == 0 ) Io_ReadCreatePo( pNtk, (char *)vTokens->pArray[1] ); else { // get the node name and the node type pType = (char *)vTokens->pArray[1]; if ( strncmp(pType, "DFF", 3) == 0 ) // works for both DFF and DFFRSE { if ( Vec_PtrSize(vTokens) == 6 ) { // create primary input to represent flop output char pNetName[1000]; char * pName; int i; char * pFlopOut = (char *)vTokens->pArray[0]; Abc_Obj_t * pNet = Abc_NtkFindOrCreateNet( pNtk, pFlopOut ); Abc_Obj_t * pTerm = Abc_NtkCreatePi( pNtk ); Abc_ObjAddFanin( pNet, pTerm ); // create four primary outputs to represent flop inputs Vec_PtrForEachEntryStart( char *, vTokens, pName, i, 2 ) { sprintf( pNetName, "%s_%s", pFlopOut, pName ); pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); pTerm = Abc_NtkCreateNodeBuf( pNtk, pNet ); pNet = Abc_NtkFindOrCreateNet( pNtk, pNetName ); Abc_ObjAddFanin( pNet, pTerm ); pTerm = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pTerm, pNet ); } pNtk->nConstrs++; } else { pNode = Io_ReadCreateLatch( pNtk, (char *)vTokens->pArray[2], (char *)vTokens->pArray[0] ); // Abc_LatchSetInit0( pNode ); if ( pType[3] == '0' ) Abc_LatchSetInit0( pNode ); else if ( pType[3] == '1' ) Abc_LatchSetInit1( pNode ); else Abc_LatchSetInitDc( pNode ); } } else if ( strcmp(pType, "LUT") == 0 ) { fLutsPresent = 1; ppNames = (char **)vTokens->pArray + 3; nNames = vTokens->nSize - 3; // check the number of inputs if ( nNames > 8 ) { printf( "%s: Currently cannot read truth tables with more than 8 inputs (%d).\n", Extra_FileReaderGetFileName(p), nNames ); Vec_StrFree( vString ); Abc_NtkDelete( pNtk ); return NULL; } // get the hex string pString = (char *)vTokens->pArray[2]; if ( strncmp( pString, "0x", 2 ) ) { printf( "%s: The LUT signature (%s) does not look like a hexadecimal beginning with \"0x\".\n", Extra_FileReaderGetFileName(p), pString ); Vec_StrFree( vString ); Abc_NtkDelete( pNtk ); return NULL; } pString += 2; // pad the string with zero's if needed nDigits = (1 << nNames) / 4; if ( nDigits == 0 ) nDigits = 1; if ( strlen(pString) < (unsigned)nDigits ) { Vec_StrFill( vString, nDigits - strlen(pString), '0' ); Vec_StrPrintStr( vString, pString ); Vec_StrPush( vString, 0 ); pString = Vec_StrArray( vString ); } // read the hex number from the string if ( !Extra_ReadHexadecimal( uTruth, pString, nNames ) ) { printf( "%s: Reading hexadecimal number (%s) has failed.\n", Extra_FileReaderGetFileName(p), pString ); Vec_StrFree( vString ); Abc_NtkDelete( pNtk ); return NULL; } // check if the node is a constant node if ( Extra_TruthIsConst0(uTruth, nNames) ) { pNode = Io_ReadCreateNode( pNtk, (char *)vTokens->pArray[0], ppNames, 0 ); Abc_ObjSetData( pNode, Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ) ); } else if ( Extra_TruthIsConst1(uTruth, nNames) ) { pNode = Io_ReadCreateNode( pNtk, (char *)vTokens->pArray[0], ppNames, 0 ); Abc_ObjSetData( pNode, Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" ) ); } else { // create the node pNode = Io_ReadCreateNode( pNtk, (char *)vTokens->pArray[0], ppNames, nNames ); assert( nNames > 0 ); if ( nNames > 1 ) Abc_ObjSetData( pNode, Abc_SopCreateFromTruth((Mem_Flex_t *)pNtk->pManFunc, nNames, uTruth) ); else if ( pString[0] == '2' ) Abc_ObjSetData( pNode, Abc_SopCreateBuf((Mem_Flex_t *)pNtk->pManFunc) ); else if ( pString[0] == '1' ) Abc_ObjSetData( pNode, Abc_SopCreateInv((Mem_Flex_t *)pNtk->pManFunc) ); else { printf( "%s: Reading truth table (%s) of single-input node has failed.\n", Extra_FileReaderGetFileName(p), pString ); Vec_StrFree( vString ); Abc_NtkDelete( pNtk ); return NULL; } } } else { // create a new node and add it to the network ppNames = (char **)vTokens->pArray + 2; nNames = vTokens->nSize - 2; pNode = Io_ReadCreateNode( pNtk, (char *)vTokens->pArray[0], ppNames, nNames ); // assign the cover if ( strcmp(pType, "AND") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateAnd((Mem_Flex_t *)pNtk->pManFunc, nNames, NULL) ); else if ( strcmp(pType, "OR") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateOr((Mem_Flex_t *)pNtk->pManFunc, nNames, NULL) ); else if ( strcmp(pType, "NAND") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateNand((Mem_Flex_t *)pNtk->pManFunc, nNames) ); else if ( strcmp(pType, "NOR") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateNor((Mem_Flex_t *)pNtk->pManFunc, nNames) ); else if ( strcmp(pType, "XOR") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateXor((Mem_Flex_t *)pNtk->pManFunc, nNames) ); else if ( strcmp(pType, "NXOR") == 0 || strcmp(pType, "XNOR") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateNxor((Mem_Flex_t *)pNtk->pManFunc, nNames) ); else if ( strncmp(pType, "BUF", 3) == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateBuf((Mem_Flex_t *)pNtk->pManFunc) ); else if ( strcmp(pType, "NOT") == 0 ) Abc_ObjSetData( pNode, Abc_SopCreateInv((Mem_Flex_t *)pNtk->pManFunc) ); else if ( strncmp(pType, "MUX", 3) == 0 ) // Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, "1-0 1\n-11 1\n") ); Abc_ObjSetData( pNode, Abc_SopRegister((Mem_Flex_t *)pNtk->pManFunc, "0-1 1\n11- 1\n") ); else if ( strncmp(pType, "gnd", 3) == 0 ) Abc_ObjSetData( pNode, Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ) ); else if ( strncmp(pType, "vdd", 3) == 0 ) Abc_ObjSetData( pNode, Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" ) ); else { printf( "Io_ReadBenchNetwork(): Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) ); Vec_StrFree( vString ); Abc_NtkDelete( pNtk ); return NULL; } } } } Extra_ProgressBarStop( pProgress ); Vec_StrFree( vString ); // check if constant 0 is present if ( (pNet = Abc_NtkFindNet( pNtk, "gnd" )) ) { if ( Abc_ObjFaninNum(pNet) == 0 ) Io_ReadCreateConst( pNtk, "gnd", 0 ); } if ( (pNet = Abc_NtkFindNet( pNtk, "1" )) ) { if ( Abc_ObjFaninNum(pNet) == 0 ) { printf( "Io_ReadBenchNetwork(): Adding constant 0 fanin to non-driven net \"1\".\n" ); Io_ReadCreateConst( pNtk, "1", 0 ); } } // check if constant 1 is present if ( (pNet = Abc_NtkFindNet( pNtk, "vdd" )) ) { if ( Abc_ObjFaninNum(pNet) == 0 ) Io_ReadCreateConst( pNtk, "vdd", 1 ); } if ( (pNet = Abc_NtkFindNet( pNtk, "2" )) ) { if ( Abc_ObjFaninNum(pNet) == 0 ) { printf( "Io_ReadBenchNetwork(): Adding constant 1 fanin to non-driven net \"2\".\n" ); Io_ReadCreateConst( pNtk, "2", 1 ); } } Abc_NtkFinalizeRead( pNtk ); // if LUTs are present, collapse the truth tables into cubes if ( fLutsPresent ) { if ( !Abc_NtkToBdd(pNtk) ) { printf( "Io_ReadBenchNetwork(): Converting to BDD has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } if ( !Abc_NtkToSop(pNtk, -1, ABC_INFINITY) ) { printf( "Io_ReadBenchNetwork(): Converting to SOP has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } } return pNtk; } /**Function************************************************************* Synopsis [Reads initial state in BENCH format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ) { char pBuffer[1000]; FILE * pFile; char * pToken; Abc_Obj_t * pObj; int Num; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Io_ReadBenchInit(): Failed to open file \"%s\".\n", pFileName ); return; } while ( fgets( pBuffer, 999, pFile ) ) { pToken = strtok( pBuffer, " \n\t\r" ); // find the latch output Num = Nm_ManFindIdByName( pNtk->pManName, pToken, ABC_OBJ_BO ); if ( Num < 0 ) { printf( "Io_ReadBenchInit(): Cannot find register with output %s.\n", pToken ); continue; } pObj = Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); if ( !Abc_ObjIsLatch(pObj) ) { printf( "Io_ReadBenchInit(): The signal is not a register output %s.\n", pToken ); continue; } // assign the new init state pToken = strtok( NULL, " \n\t\r" ); if ( pToken[0] == '0' ) Abc_LatchSetInit0( pObj ); else if ( pToken[0] == '1' ) Abc_LatchSetInit1( pObj ); else if ( pToken[0] == '2' ) Abc_LatchSetInitDc( pObj ); else { printf( "Io_ReadBenchInit(): The signal %s has unknown initial value (%s).\n", Abc_ObjName(Abc_ObjFanout0(pObj)), pToken ); continue; } } fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadBlif.c000066400000000000000000001671241300674244400235340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadBlif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read BLIF files.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/main/main.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Io_ReadBlif_t_ Io_ReadBlif_t; // all reading info struct Io_ReadBlif_t_ { // general info about file char * pFileName; // the name of the file Extra_FileReader_t * pReader; // the input file reader // current processing info Abc_Ntk_t * pNtkMaster; // the primary network Abc_Ntk_t * pNtkCur; // the primary network int LineCur; // the line currently parsed // temporary storage for tokens Vec_Ptr_t * vTokens; // the current tokens Vec_Ptr_t * vNewTokens; // the temporary storage for the tokens Vec_Str_t * vCubes; // the temporary storage for the tokens // timing information Vec_Int_t * vInArrs; // input arrival Vec_Int_t * vOutReqs; // output required Vec_Int_t * vInDrives; // input drive Vec_Int_t * vOutLoads; // output load float DefInArrRise; // input arrival default float DefInArrFall; // input arrival default float DefOutReqRise;// output required default float DefOutReqFall;// output required default float DefInDriRise; // input drive default float DefInDriFall; // input drive default float DefOutLoadRise;// output load default float DefOutLoadFall;// output load default int fHaveDefInArr; // provided in the file int fHaveDefOutReq; // provided in the file int fHaveDefInDri; // provided in the file int fHaveDefOutLoad;// provided in the file // the error message FILE * Output; // the output stream char sError[1000]; // the error string generated during parsing int fError; // set to 1 when error occurs }; static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ); static void Io_ReadBlifFree( Io_ReadBlif_t * p ); static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ); static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ); static char * Io_ReadBlifCleanName( char * pName ); static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ); static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ); static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ); static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkDefaultOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkAndGateDelay( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); static int Io_ReadBlifCreateTiming( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the (hierarchical) network from the BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) { Io_ReadBlif_t * p; Abc_Ntk_t * pNtk; // start the file p = Io_ReadBlifFile( pFileName ); if ( p == NULL ) return NULL; // read the hierarchical network pNtk = Io_ReadBlifNetwork( p ); if ( pNtk == NULL ) { Io_ReadBlifFree( p ); return NULL; } pNtk->pSpec = Extra_UtilStrsav( pFileName ); Io_ReadBlifCreateTiming( p, pNtk ); Io_ReadBlifFree( p ); // make sure that everything is okay with the network structure if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) { printf( "Io_ReadBlif: The network check has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } return pNtk; } /**Function************************************************************* Synopsis [Iteratively reads several networks in the hierarchical design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) { Abc_Ntk_t * pNtk, * pNtkMaster; // read the name of the master network p->vTokens = Io_ReadBlifGetTokens(p); if ( p->vTokens == NULL || strcmp( (char *)p->vTokens->pArray[0], ".model" ) ) { p->LineCur = 0; sprintf( p->sError, "Wrong input file format." ); Io_ReadBlifPrintErrorMessage( p ); return NULL; } // read networks (with EXDC) pNtkMaster = NULL; while ( p->vTokens ) { // read the network and its EXDC if present pNtk = Io_ReadBlifNetworkOne( p ); if ( pNtk == NULL ) break; if ( p->vTokens && strcmp((char *)p->vTokens->pArray[0], ".exdc") == 0 ) { pNtk->pExdc = Io_ReadBlifNetworkOne( p ); if ( pNtk->pExdc == NULL ) break; Abc_NtkFinalizeRead( pNtk->pExdc ); } // add this network as part of the hierarchy if ( pNtkMaster == NULL ) // no master network so far { p->pNtkMaster = pNtkMaster = pNtk; continue; } /* // make sure hierarchy does not have the network with this name if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) ) { p->LineCur = 0; sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName ); Io_ReadBlifPrintErrorMessage( p ); Abc_NtkDelete( pNtk ); Abc_NtkDelete( pNtkMaster ); pNtkMaster = NULL; return NULL; } // add the network to the hierarchy if ( pNtkMaster->tName2Model == NULL ) pNtkMaster->tName2Model = stmm_init_table((int (*)(void))strcmp, (int (*)(void))stmm_strhash); stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk ); */ } /* // if there is a hierarchy, connect the boxes if ( pNtkMaster && pNtkMaster->tName2Model ) { if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) ) { Abc_NtkDelete( pNtkMaster ); return NULL; } } else */ if ( !p->fError ) Abc_NtkFinalizeRead( pNtkMaster ); // return the master network return pNtkMaster; } /**Function************************************************************* Synopsis [Reads one (main or exdc) network from the BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) { ProgressBar * pProgress = NULL; Abc_Ntk_t * pNtk; char * pDirective; int iLine, fTokensReady, fStatus; // make sure the tokens are present assert( p->vTokens != NULL ); // create the new network p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); // read the model name if ( strcmp( (char *)p->vTokens->pArray[0], ".model" ) == 0 ) { char * pToken, * pPivot; if ( Vec_PtrSize(p->vTokens) != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .model line does not have exactly two entries." ); Io_ReadBlifPrintErrorMessage( p ); return NULL; } for ( pPivot = pToken = (char *)Vec_PtrEntry(p->vTokens, 1); *pToken; pToken++ ) if ( *pToken == '/' || *pToken == '\\' ) pPivot = pToken+1; pNtk->pName = Extra_UtilStrsav( pPivot ); } else if ( strcmp( (char *)p->vTokens->pArray[0], ".exdc" ) != 0 ) { printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName, Extra_FileReaderGetLineNumber(p->pReader, 0), (char*)p->vTokens->pArray[0] ); Abc_NtkDelete(pNtk); p->pNtkCur = NULL; return NULL; } // read the inputs/outputs if ( p->pNtkMaster == NULL ) pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); fTokensReady = fStatus = 0; for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) { if ( p->pNtkMaster == NULL && iLine % 1000 == 0 ) Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); // consider different line types fTokensReady = 0; pDirective = (char *)p->vTokens->pArray[0]; if ( !strcmp( pDirective, ".names" ) ) { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; } else if ( !strcmp( pDirective, ".gate" ) ) fStatus = Io_ReadBlifNetworkGate( p, p->vTokens ); else if ( !strcmp( pDirective, ".latch" ) ) fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens ); else if ( !strcmp( pDirective, ".inputs" ) ) fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens ); else if ( !strcmp( pDirective, ".outputs" ) ) fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens ); else if ( !strcmp( pDirective, ".input_arrival" ) ) fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens ); else if ( !strcmp( pDirective, ".output_required" ) ) fStatus = Io_ReadBlifNetworkOutputRequired( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_input_arrival" ) ) fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_output_required" ) ) fStatus = Io_ReadBlifNetworkDefaultOutputRequired( p, p->vTokens ); else if ( !strcmp( pDirective, ".input_drive" ) ) fStatus = Io_ReadBlifNetworkInputDrive( p, p->vTokens ); else if ( !strcmp( pDirective, ".output_load" ) ) fStatus = Io_ReadBlifNetworkOutputLoad( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_input_drive" ) ) fStatus = Io_ReadBlifNetworkDefaultInputDrive( p, p->vTokens ); else if ( !strcmp( pDirective, ".default_output_load" ) ) fStatus = Io_ReadBlifNetworkDefaultOutputLoad( p, p->vTokens ); else if ( !strcmp( pDirective, ".and_gate_delay" ) ) fStatus = Io_ReadBlifNetworkAndGateDelay( p, p->vTokens ); // else if ( !strcmp( pDirective, ".subckt" ) ) // fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens ); else if ( !strcmp( pDirective, ".exdc" ) ) break; else if ( !strcmp( pDirective, ".end" ) ) { p->vTokens = Io_ReadBlifGetTokens(p); break; } else if ( !strcmp( pDirective, ".blackbox" ) ) { pNtk->ntkType = ABC_NTK_NETLIST; pNtk->ntkFunc = ABC_FUNC_BLACKBOX; Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); pNtk->pManFunc = NULL; } else printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName, Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective ); if ( p->vTokens == NULL ) // some files do not have ".end" in the end break; if ( fStatus == 1 ) { Extra_ProgressBarStop( pProgress ); Abc_NtkDelete( pNtk ); return NULL; } } if ( p->pNtkMaster == NULL ) Extra_ProgressBarStop( pProgress ); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { int i; for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePi( p->pNtkCur, (char *)vTokens->pArray[i] ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { int i; for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePo( p->pNtkCur, (char *)vTokens->pArray[i] ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Ntk_t * pNtk = p->pNtkCur; Abc_Obj_t * pLatch; int ResetValue; if ( vTokens->nSize < 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .latch line does not have enough tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the latch pLatch = Io_ReadCreateLatch( pNtk, (char *)vTokens->pArray[1], (char *)vTokens->pArray[2] ); // get the latch reset value if ( vTokens->nSize == 3 ) Abc_LatchSetInitDc( pLatch ); else { ResetValue = atoi((char *)vTokens->pArray[vTokens->nSize-1]); if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .latch line has an unknown reset value (%s).", (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } if ( ResetValue == 0 ) Abc_LatchSetInit0( pLatch ); else if ( ResetValue == 1 ) Abc_LatchSetInit1( pLatch ); else if ( ResetValue == 2 ) Abc_LatchSetInitDc( pLatch ); } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) { Vec_Ptr_t * vTokens = *pvTokens; Abc_Ntk_t * pNtk = p->pNtkCur; Abc_Obj_t * pNode; char * pToken, Char, ** ppNames; int nFanins, nNames; // create a new node and add it to the network if ( vTokens->nSize < 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .names line has less than two tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the node ppNames = (char **)vTokens->pArray + 1; nNames = vTokens->nSize - 2; pNode = Io_ReadCreateNode( pNtk, ppNames[nNames], ppNames, nNames ); // derive the functionality of the node p->vCubes->nSize = 0; nFanins = vTokens->nSize - 2; if ( nFanins == 0 ) { while ( (vTokens = Io_ReadBlifGetTokens(p)) ) { pToken = (char *)vTokens->pArray[0]; if ( pToken[0] == '.' ) break; // read the cube if ( vTokens->nSize != 1 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of tokens in the constant cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the cube Char = ((char *)vTokens->pArray[0])[0]; Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, Char ); Vec_StrPush( p->vCubes, '\n' ); } } else { while ( (vTokens = Io_ReadBlifGetTokens(p)) ) { pToken = (char *)vTokens->pArray[0]; if ( pToken[0] == '.' ) break; // read the cube if ( vTokens->nSize != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of tokens in the cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the cube Vec_StrPrintStr( p->vCubes, (char *)vTokens->pArray[0] ); // check the char Char = ((char *)vTokens->pArray[1])[0]; if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The output character in the constant cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, Char ); Vec_StrPush( p->vCubes, '\n' ); } } // if there is nothing there if ( p->vCubes->nSize == 0 ) { // create an empty cube Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, '0' ); Vec_StrPush( p->vCubes, '\n' ); } Vec_StrPush( p->vCubes, 0 ); // set the pointer to the functionality of the node Abc_ObjSetData( pNode, Abc_SopRegister((Mem_Flex_t *)pNtk->pManFunc, p->vCubes->pArray) ); // check the size if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum((char *)Abc_ObjData(pNode)) ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).", Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum((char *)Abc_ObjData(pNode)) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // return the last array of tokens *pvTokens = vTokens; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate, Mio_Gate_t * pTwin ) { Mio_Pin_t * pGatePin; char * pName, * pNamePin; int i, k, nSize, Length; nSize = Vec_PtrSize(vTokens); if ( pTwin == NULL ) { if ( nSize - 3 != Mio_GateReadPinNum(pGate) ) return 0; } else { if ( nSize - 3 != Mio_GateReadPinNum(pGate) && nSize - 4 != Mio_GateReadPinNum(pGate) ) return 0; } // check if the names are in order for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { pNamePin = Mio_PinReadName(pGatePin); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, i+2); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) continue; break; } if ( pTwin == NULL ) { if ( i == Mio_GateReadPinNum(pGate) ) return 1; // reorder the pins for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { pNamePin = Mio_PinReadName(pGatePin); Length = strlen(pNamePin); for ( k = 2; k < nSize; k++ ) { pName = (char *)Vec_PtrEntry(vTokens, k); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) { Vec_PtrPush( vTokens, pName ); break; } } } pNamePin = Mio_GateReadOutName(pGate); Length = strlen(pNamePin); for ( k = 2; k < nSize; k++ ) { pName = (char *)Vec_PtrEntry(vTokens, k); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) { Vec_PtrPush( vTokens, pName ); break; } } if ( Vec_PtrSize(vTokens) - nSize != nSize - 2 ) return 0; Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nSize ) Vec_PtrWriteEntry( vTokens, k - nSize + 2, pName ); Vec_PtrShrink( vTokens, nSize ); } else { if ( i != Mio_GateReadPinNum(pGate) ) // expect the correct order of input pins in the network with twin gates return 0; // check the last two entries if ( nSize - 3 == Mio_GateReadPinNum(pGate) ) // only one output is available { pNamePin = Mio_GateReadOutName(pGate); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pGate { Vec_PtrPush( vTokens, NULL ); return 1; } pNamePin = Mio_GateReadOutName(pTwin); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pTwin { pName = (char *)Vec_PtrPop( vTokens ); Vec_PtrPush( vTokens, NULL ); Vec_PtrPush( vTokens, pName ); return 1; } return 0; } if ( nSize - 4 == Mio_GateReadPinNum(pGate) ) // two outputs are available { pNamePin = Mio_GateReadOutName(pGate); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, nSize - 2); if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') ) return 0; pNamePin = Mio_GateReadOutName(pTwin); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') ) return 0; return 1; } assert( 0 ); } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Mio_Library_t * pGenlib; Mio_Gate_t * pGate; Abc_Obj_t * pNode; char ** ppNames; int i, nNames; // check that the library is available pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pGenlib == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The current library is not available." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create a new node and add it to the network if ( vTokens->nSize < 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .gate line has less than two tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // get the gate pGate = Mio_LibraryReadGateByName( pGenlib, (char *)vTokens->pArray[1], NULL ); if ( pGate == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find gate \"%s\" in the library.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // if this is the first line with gate, update the network type if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) { assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); p->pNtkCur->ntkFunc = ABC_FUNC_MAP; Mem_FlexStop( (Mem_Flex_t *)p->pNtkCur->pManFunc, 0 ); p->pNtkCur->pManFunc = pGenlib; } // reorder the formal inputs to be in the same order as in the gate if ( !Io_ReadBlifReorderFormalNames( vTokens, pGate, Mio_GateReadTwin(pGate) ) ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Mismatch in the fanins of gate \"%s\".", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // remove the formal parameter names for ( i = 2; i < vTokens->nSize; i++ ) { vTokens->pArray[i] = Io_ReadBlifCleanName( (char *)vTokens->pArray[i] ); if ( vTokens->pArray[i] == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Invalid gate input assignment." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } } // create the node if ( Mio_GateReadTwin(pGate) == NULL ) { nNames = vTokens->nSize - 3; ppNames = (char **)vTokens->pArray + 2; pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); Abc_ObjSetData( pNode, pGate ); } else { nNames = vTokens->nSize - 4; ppNames = (char **)vTokens->pArray + 2; assert( ppNames[nNames] != NULL || ppNames[nNames+1] != NULL ); if ( ppNames[nNames] ) { pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); Abc_ObjSetData( pNode, pGate ); } if ( ppNames[nNames+1] ) { pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames+1], ppNames, nNames ); Abc_ObjSetData( pNode, Mio_GateReadTwin(pGate) ); } } return 0; } /**Function************************************************************* Synopsis [Creates a multi-input multi-output box in the hierarchical design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pBox; Vec_Ptr_t * vNames; char * pName; int i; // create a new node and add it to the network if ( vTokens->nSize < 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .subcircuit line has less than three tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // store the names of formal/actual inputs/outputs of the box vNames = Vec_PtrAlloc( 10 ); Vec_PtrForEachEntryStart( char *, vTokens, pName, i, 1 ) // Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) ); Vec_PtrPush( vNames, Extra_UtilStrsav(pName) ); // memory leak!!! // create a new box and add it to the network pBox = Abc_NtkCreateBlackbox( p->pNtkCur ); // set the pointer to the node names Abc_ObjSetData( pBox, vNames ); // remember the line of the file pBox->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Extra_FileReaderGetLineNumber(p->pReader, 0); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Io_ReadBlifCleanName( char * pName ) { int i, Length; Length = strlen(pName); for ( i = 0; i < Length; i++ ) if ( pName[i] == '=' ) return pName + i + 1; return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".input_arrival", 14 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .input_arrival line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .input_arrival line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_arrival line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info //Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); Vec_IntPush( p->vInArrs, Abc_ObjFanin0(pNet)->Id ); Vec_IntPush( p->vInArrs, Abc_Float2Int((float)TimeRise) ); Vec_IntPush( p->vInArrs, Abc_Float2Int((float)TimeFall) ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".output_required", 16 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .output_required line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .output_required line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .output_required line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info // Abc_NtkTimeSetRequired( p->pNtkCur, Abc_ObjFanout0(pNet)->Id, (float)TimeRise, (float)TimeFall ); Vec_IntPush( p->vOutReqs, Abc_ObjFanout0(pNet)->Id ); Vec_IntPush( p->vOutReqs, Abc_Float2Int((float)TimeRise) ); Vec_IntPush( p->vOutReqs, Abc_Float2Int((float)TimeFall) ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".default_input_arrival", 23 ) == 0 ); if ( vTokens->nSize != 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .default_input_arrival line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_arrival line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info //Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall ); p->DefInArrRise = (float)TimeRise; p->DefInArrFall = (float)TimeFall; p->fHaveDefInArr = 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkDefaultOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".default_output_required", 25 ) == 0 ); if ( vTokens->nSize != 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .default_output_required line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_output_required line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info // Abc_NtkTimeSetDefaultRequired( p->pNtkCur, (float)TimeRise, (float)TimeFall ); p->DefOutReqRise = (float)TimeRise; p->DefOutReqFall = (float)TimeFall; p->fHaveDefOutReq = 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadFindCiId( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) { Abc_Obj_t * pTemp; int i; Abc_NtkForEachCi( pNtk, pTemp, i ) if ( pTemp == pObj ) return i; return -1; } int Io_ReadBlifNetworkInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".input_drive", 12 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .input_drive line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .input_drive line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_drive line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info //Abc_NtkTimeSetInputDrive( p->pNtkCur, Io_ReadFindCiId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanin0(pNet)->Id)), (float)TimeRise, (float)TimeFall ); Vec_IntPush( p->vInDrives, Io_ReadFindCiId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanin0(pNet)->Id)) ); Vec_IntPush( p->vInDrives, Abc_Float2Int((float)TimeRise) ); Vec_IntPush( p->vInDrives, Abc_Float2Int((float)TimeFall) ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadFindCoId( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) { Abc_Obj_t * pTemp; int i; Abc_NtkForEachPo( pNtk, pTemp, i ) if ( pTemp == pObj ) return i; return -1; } int Io_ReadBlifNetworkOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".output_load", 12 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .output_load line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .output_load line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .output_load line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info // Abc_NtkTimeSetOutputLoad( p->pNtkCur, Io_ReadFindCoId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanout0(pNet)->Id)), (float)TimeRise, (float)TimeFall ); Vec_IntPush( p->vOutLoads, Io_ReadFindCoId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanout0(pNet)->Id)) ); Vec_IntPush( p->vOutLoads, Abc_Float2Int((float)TimeRise) ); Vec_IntPush( p->vOutLoads, Abc_Float2Int((float)TimeFall) ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkDefaultInputDrive( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".default_input_drive", 21 ) == 0 ); if ( vTokens->nSize != 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .default_input_drive line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_drive line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info // Abc_NtkTimeSetDefaultInputDrive( p->pNtkCur, (float)TimeRise, (float)TimeFall ); p->DefInDriRise = (float)TimeRise; p->DefInDriFall = (float)TimeFall; p->fHaveDefInDri = 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkDefaultOutputLoad( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".default_output_load", 21 ) == 0 ); if ( vTokens->nSize != 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .default_output_load line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[1], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[2], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_output_load line.", (char*)vTokens->pArray[1], (char*)vTokens->pArray[2] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info // Abc_NtkTimeSetDefaultOutputLoad( p->pNtkCur, (float)TimeRise, (float)TimeFall ); p->DefOutLoadRise = (float)TimeRise; p->DefOutLoadFall = (float)TimeFall; p->fHaveDefOutLoad = 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkAndGateDelay( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { char * pFoo1; double AndGateDelay; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".and_gate_delay", 25 ) == 0 ); if ( vTokens->nSize != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments (%d) on .and_gate_delay line (should be 1).", vTokens->nSize-1 ); Io_ReadBlifPrintErrorMessage( p ); return 1; } AndGateDelay = strtod( (char *)vTokens->pArray[1], &pFoo1 ); if ( *pFoo1 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s) for AND gate delay in on .and_gate_delay line line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set timing info p->pNtkCur->AndGateDelay = (float)AndGateDelay; return 0; } /**Function************************************************************* Synopsis [Prints the error message including the file name and line number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) { p->fError = 1; if ( p->LineCur == 0 ) // the line number is not given fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); else // print the error message with the line number fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError ); } /**Function************************************************************* Synopsis [Gets the tokens taking into account the line breaks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) { Vec_Ptr_t * vTokens; char * pLastToken; int i; // get rid of the old tokens if ( p->vNewTokens->nSize > 0 ) { for ( i = 0; i < p->vNewTokens->nSize; i++ ) ABC_FREE( p->vNewTokens->pArray[i] ); p->vNewTokens->nSize = 0; } // get the new tokens vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p->pReader); if ( vTokens == NULL ) return vTokens; // check if there is a transfer to another line pLastToken = (char *)vTokens->pArray[vTokens->nSize - 1]; if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) return vTokens; // remove the slash pLastToken[ strlen(pLastToken)-1 ] = 0; if ( pLastToken[0] == 0 ) vTokens->nSize--; // load them into the new array for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); // load as long as there is the line break while ( 1 ) { // get the new tokens vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p->pReader); if ( vTokens->nSize == 0 ) return p->vNewTokens; // check if there is a transfer to another line pLastToken = (char *)vTokens->pArray[vTokens->nSize - 1]; if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) { // remove the slash pLastToken[ strlen(pLastToken)-1 ] = 0; if ( pLastToken[0] == 0 ) vTokens->nSize--; // load them into the new array for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); continue; } // otherwise, load them and break for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); break; } return p->vNewTokens; } /**Function************************************************************* Synopsis [Starts the reading data structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) { Extra_FileReader_t * pReader; Io_ReadBlif_t * p; // start the reader pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" ); if ( pReader == NULL ) return NULL; // start the reading data structure p = ABC_ALLOC( Io_ReadBlif_t, 1 ); memset( p, 0, sizeof(Io_ReadBlif_t) ); p->pFileName = pFileName; p->pReader = pReader; p->Output = stdout; p->vNewTokens = Vec_PtrAlloc( 100 ); p->vCubes = Vec_StrAlloc( 100 ); p->vInArrs = Vec_IntAlloc( 100 ); p->vOutReqs = Vec_IntAlloc( 100 ); p->vInDrives = Vec_IntAlloc( 100 ); p->vOutLoads = Vec_IntAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [Frees the data structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadBlifFree( Io_ReadBlif_t * p ) { Extra_FileReaderFree( p->pReader ); Vec_PtrFree( p->vNewTokens ); Vec_StrFree( p->vCubes ); Vec_IntFree( p->vInArrs ); Vec_IntFree( p->vOutReqs ); Vec_IntFree( p->vInDrives ); Vec_IntFree( p->vOutLoads ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Connect one box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model ) { Vec_Ptr_t * pNames; Abc_Ntk_t * pNtkModel; Abc_Obj_t * pObj, * pNet; char * pName = NULL, * pActual; int i, Length, Start = -1; // get the model for this box pNames = (Vec_Ptr_t *)pBox->pData; if ( !stmm_lookup( tName2Model, (char *)Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot find the model for subcircuit %s.", (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the fanins of the box Abc_NtkForEachPi( pNtkModel, pObj, i ) pObj->pCopy = NULL; if ( Abc_NtkPiNum(pNtkModel) == 0 ) Start = 1; else { Vec_PtrForEachEntryStart( char *, pNames, pName, i, 1 ) { pActual = Io_ReadBlifCleanName(pName); if ( pActual == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } Length = pActual - pName - 1; pName[Length] = 0; // find the PI net with this name pObj = Abc_NtkFindNet( pNtkModel, pName ); if ( pObj == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // get the PI pObj = Abc_ObjFanin0(pObj); // quit if this is not a PI net if ( !Abc_ObjIsPi(pObj) ) { pName[Length] = '='; Start = i; break; } // remember the actual name in the net if ( pObj->pCopy != NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pObj->pCopy = (Abc_Obj_t *)pActual; // quit if we processed all PIs if ( i == Abc_NtkPiNum(pNtkModel) ) { Start = i+1; break; } } } // create the fanins of the box Abc_NtkForEachPi( pNtkModel, pObj, i ) { pActual = (char *)pObj->pCopy; if ( pActual == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); Abc_ObjAddFanin( pBox, pNet ); } Abc_NtkForEachPi( pNtkModel, pObj, i ) pObj->pCopy = NULL; // create the fanouts of the box Abc_NtkForEachPo( pNtkModel, pObj, i ) pObj->pCopy = NULL; Vec_PtrForEachEntryStart( char *, pNames, pName, i, Start ) { pActual = Io_ReadBlifCleanName(pName); if ( pActual == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } Length = pActual - pName - 1; pName[Length] = 0; // find the PO net with this name pObj = Abc_NtkFindNet( pNtkModel, pName ); if ( pObj == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // get the PO pObj = Abc_ObjFanout0(pObj); if ( pObj->pCopy != NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pObj->pCopy = (Abc_Obj_t *)pActual; } // create the fanouts of the box Abc_NtkForEachPo( pNtkModel, pObj, i ) { pActual = (char *)pObj->pCopy; if ( pActual == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); Abc_ObjAddFanin( pNet, pBox ); } Abc_NtkForEachPo( pNtkModel, pObj, i ) pObj->pCopy = NULL; // remove the array of names, assign the pointer to the model Vec_PtrForEachEntry( char *, (Vec_Ptr_t *)pBox->pData, pName, i ) ABC_FREE( pName ); Vec_PtrFree( (Vec_Ptr_t *)pBox->pData ); pBox->pData = pNtkModel; return 0; } /**Function************************************************************* Synopsis [Connect the boxes in the hierarchy of networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model ) { Abc_Obj_t * pBox; int i; // go through the boxes Abc_NtkForEachBlackbox( pNtk, pBox, i ) if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) ) return 1; Abc_NtkFinalizeRead( pNtk ); return 0; } /**Function************************************************************* Synopsis [Creates timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifCreateTiming( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk ) { int Id, Rise, Fall, i; // set timing info //Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall ); // p->DefInArrRise = (float)TimeRise; // p->DefInArrFall = (float)TimeFall; if ( p->fHaveDefInArr ) Abc_NtkTimeSetDefaultArrival( pNtk, p->DefInArrRise, p->DefInArrFall ); // set timing info //Abc_NtkTimeSetDefaultRequired( p->pNtkCur, (float)TimeRise, (float)TimeFall ); // p->DefOutReqRise = (float)TimeRise; // p->DefOutReqFall = (float)TimeFall; if ( p->fHaveDefOutReq ) Abc_NtkTimeSetDefaultRequired( pNtk, p->DefOutReqRise, p->DefOutReqFall ); // set timing info //Abc_NtkTimeSetDefaultInputDrive( p->pNtkCur, (float)TimeRise, (float)TimeFall ); // p->DefInDriRise = (float)TimeRise; // p->DefInDriFall = (float)TimeFall; if ( p->fHaveDefInDri ) Abc_NtkTimeSetDefaultInputDrive( pNtk, p->DefInDriRise, p->DefInDriFall ); // set timing info //Abc_NtkTimeSetDefaultOutputLoad( p->pNtkCur, (float)TimeRise, (float)TimeFall ); // p->DefOutLoadRise = (float)TimeRise; // p->DefOutLoadFall = (float)TimeFall; if ( p->fHaveDefOutLoad ) Abc_NtkTimeSetDefaultOutputLoad( pNtk, p->DefOutLoadRise, p->DefOutLoadFall ); // set timing info //Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); // Vec_IntPush( p->vInArrs, Abc_ObjFanin0(pNet)->Id ); // Vec_IntPush( p->vInArrs, Abc_Float2Int((float)TimeRise) ); // Vec_IntPush( p->vInArrs, Abc_Float2Int((float)TimeFall) ); Vec_IntForEachEntryTriple( p->vInArrs, Id, Rise, Fall, i ) Abc_NtkTimeSetArrival( pNtk, Id, Abc_Int2Float(Rise), Abc_Int2Float(Fall) ); // set timing info //Abc_NtkTimeSetRequired( p->pNtkCur, Abc_ObjFanout0(pNet)->Id, (float)TimeRise, (float)TimeFall ); // Vec_IntPush( p->vOutReqs, Abc_ObjFanout0(pNet)->Id ); // Vec_IntPush( p->vOutReqs, Abc_Float2Int((float)TimeRise) ); // Vec_IntPush( p->vOutReqs, Abc_Float2Int((float)TimeFall) ); Vec_IntForEachEntryTriple( p->vOutReqs, Id, Rise, Fall, i ) Abc_NtkTimeSetRequired( pNtk, Id, Abc_Int2Float(Rise), Abc_Int2Float(Fall) ); // set timing info //Abc_NtkTimeSetInputDrive( p->pNtkCur, Io_ReadFindCiId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanin0(pNet)->Id)), (float)TimeRise, (float)TimeFall ); // Vec_IntPush( p->vInDrives, Io_ReadFindCiId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanin0(pNet)->Id)) ); // Vec_IntPush( p->vInDrives, Abc_Float2Int((float)TimeRise) ); // Vec_IntPush( p->vInDrives, Abc_Float2Int((float)TimeFall) ); Vec_IntForEachEntryTriple( p->vInDrives, Id, Rise, Fall, i ) Abc_NtkTimeSetInputDrive( pNtk, Id, Abc_Int2Float(Rise), Abc_Int2Float(Fall) ); // set timing info //Abc_NtkTimeSetOutputLoad( p->pNtkCur, Io_ReadFindCoId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanout0(pNet)->Id)), (float)TimeRise, (float)TimeFall ); // Vec_IntPush( p->vOutLoads, Io_ReadFindCoId(p->pNtkCur, Abc_NtkObj(p->pNtkCur, Abc_ObjFanout0(pNet)->Id)) ); // Vec_IntPush( p->vOutLoads, Abc_Float2Int((float)TimeRise) ); // Vec_IntPush( p->vOutLoads, Abc_Float2Int((float)TimeFall) ); Vec_IntForEachEntryTriple( p->vOutLoads, Id, Rise, Fall, i ) Abc_NtkTimeSetOutputLoad( pNtk, Id, Abc_Int2Float(Rise), Abc_Int2Float(Fall) ); return 1; } #if 0 /**Function************************************************************* Synopsis [Connect the boxes in the hierarchy of networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) { stmm_generator * gen; Abc_Ntk_t * pNtk; char * pName; // connect the master network if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) ) return 1; // connect other networks stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk ) if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) ) return 1; return 0; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadBlifAig.c000066400000000000000000000767161300674244400241630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadBlifAig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read BLIF file into AIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - December 23, 2006.] Revision [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "misc/vec/vecPtr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // latch initial values typedef enum { IO_BLIF_INIT_NONE = 0, // 0: unknown IO_BLIF_INIT_ZERO, // 1: zero IO_BLIF_INIT_ONE, // 2: one IO_BLIF_INIT_DC // 3: don't-care } Io_BlifInit_t; typedef struct Io_BlifObj_t_ Io_BlifObj_t; // parsing object struct Io_BlifObj_t_ { unsigned fPi : 1; // the object is a primary input unsigned fPo : 1; // the object is a primary output unsigned fLi : 1; // the object is a latch input unsigned fLo : 1; // the object is a latch output unsigned fDef : 1; // the object is defined as a table (node, PO, LI) unsigned fLoop : 1; // flag for loop detection unsigned Init : 2; // the latch initial state unsigned Offset : 24; // temporary number char * pName; // the name of this object void * pEquiv; // the AIG node representing this line Io_BlifObj_t * pNext; // the next obj in the hash table }; typedef struct Io_BlifMan_t_ Io_BlifMan_t; // parsing manager struct Io_BlifMan_t_ { // general info about file char * pFileName; // the name of the file char * pBuffer; // the begining of the file buffer Vec_Ptr_t * vLines; // the line beginnings // temporary objects Io_BlifObj_t * pObjects; // the storage for objects int nObjects; // the number of objects allocated int iObjNext; // the next free object // file lines char * pModel; // .model line Vec_Ptr_t * vInputs; // .inputs lines Vec_Ptr_t * vOutputs; // .outputs lines Vec_Ptr_t * vLatches; // .latches lines Vec_Ptr_t * vNames; // .names lines // network objects Vec_Ptr_t * vPis; // the PI structures Vec_Ptr_t * vPos; // the PO structures Vec_Ptr_t * vLis; // the LI structures Vec_Ptr_t * vLos; // the LO structures // mapping of names into objects Io_BlifObj_t ** pTable; // the hash table int nTableSize; // the hash table size // current processing info Abc_Ntk_t * pAig; // the network under construction Vec_Ptr_t * vTokens; // the current tokens char sError[512]; // the error string generated during parsing // statistics int nTablesRead; // the number of processed tables int nTablesLeft; // the number of dangling tables }; // static functions static Io_BlifMan_t * Io_BlifAlloc(); static void Io_BlifFree( Io_BlifMan_t * p ); static char * Io_BlifLoadFile( char * pFileName ); static void Io_BlifReadPreparse( Io_BlifMan_t * p ); static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ); static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ); static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ); static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ); static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ); static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ); static int Io_BlifParseConstruct( Io_BlifMan_t * p ); static int Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the network from the BLIF file as an AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ) { FILE * pFile; Io_BlifMan_t * p; Abc_Ntk_t * pAig; // check that the file is available pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Io_Blif(): The file is unavailable (absent or open).\n" ); return 0; } fclose( pFile ); // start the file reader p = Io_BlifAlloc(); p->pFileName = pFileName; p->pBuffer = Io_BlifLoadFile( pFileName ); if ( p->pBuffer == NULL ) { Io_BlifFree( p ); return NULL; } // prepare the file for parsing Io_BlifReadPreparse( p ); // construct the network pAig = Io_BlifParse( p ); if ( p->sError[0] ) fprintf( stdout, "%s\n", p->sError ); if ( pAig == NULL ) return NULL; Io_BlifFree( p ); // make sure that everything is okay with the network structure if ( fCheck && !Abc_NtkCheckRead( pAig ) ) { printf( "Io_Blif: The network check has failed.\n" ); Abc_NtkDelete( pAig ); return NULL; } return pAig; } /**Function************************************************************* Synopsis [Allocates the BLIF parsing structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Io_BlifMan_t * Io_BlifAlloc() { Io_BlifMan_t * p; p = ABC_ALLOC( Io_BlifMan_t, 1 ); memset( p, 0, sizeof(Io_BlifMan_t) ); p->vLines = Vec_PtrAlloc( 512 ); p->vInputs = Vec_PtrAlloc( 512 ); p->vOutputs = Vec_PtrAlloc( 512 ); p->vLatches = Vec_PtrAlloc( 512 ); p->vNames = Vec_PtrAlloc( 512 ); p->vTokens = Vec_PtrAlloc( 512 ); p->vPis = Vec_PtrAlloc( 512 ); p->vPos = Vec_PtrAlloc( 512 ); p->vLis = Vec_PtrAlloc( 512 ); p->vLos = Vec_PtrAlloc( 512 ); return p; } /**Function************************************************************* Synopsis [Frees the BLIF parsing structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_BlifFree( Io_BlifMan_t * p ) { if ( p->pAig ) Abc_NtkDelete( p->pAig ); if ( p->pBuffer ) ABC_FREE( p->pBuffer ); if ( p->pObjects ) ABC_FREE( p->pObjects ); if ( p->pTable ) ABC_FREE( p->pTable ); Vec_PtrFree( p->vLines ); Vec_PtrFree( p->vInputs ); Vec_PtrFree( p->vOutputs ); Vec_PtrFree( p->vLatches ); Vec_PtrFree( p->vNames ); Vec_PtrFree( p->vTokens ); Vec_PtrFree( p->vPis ); Vec_PtrFree( p->vPos ); Vec_PtrFree( p->vLis ); Vec_PtrFree( p->vLos ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Hashing for character strings.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static unsigned Io_BlifHashString( char * pName, int TableSize ) { static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; unsigned i, Key = 0; for ( i = 0; pName[i] != '\0'; i++ ) Key ^= s_Primes[i%10]*pName[i]*pName[i]; return Key % TableSize; } /**Function************************************************************* Synopsis [Checks if the given name exists in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName ) { Io_BlifObj_t ** ppEntry; for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) if ( !strcmp((*ppEntry)->pName, pName) ) return ppEntry; return ppEntry; } /**Function************************************************************* Synopsis [Finds or add the given name to the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName ) { Io_BlifObj_t ** ppEntry; ppEntry = Io_BlifHashLookup( p, pName ); if ( *ppEntry == NULL ) { assert( p->iObjNext < p->nObjects ); *ppEntry = p->pObjects + p->iObjNext++; (*ppEntry)->pName = pName; } return *ppEntry; } /**Function************************************************************* Synopsis [Collects the already split tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) { char * pCur; Vec_PtrClear( vTokens ); for ( pCur = pInput; pCur < pOutput; pCur++ ) { if ( *pCur == 0 ) continue; Vec_PtrPush( vTokens, pCur ); while ( *++pCur ); } } /**Function************************************************************* Synopsis [Splits the line into tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) { char * pCur; // clear spaces for ( pCur = pLine; *pCur != Stop; pCur++ ) if ( Io_BlifCharIsSpace(*pCur) ) *pCur = 0; // collect tokens Io_BlifCollectTokens( vTokens, pLine, pCur ); } /**Function************************************************************* Synopsis [Returns the 1-based number of the line in which the token occurs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken ) { char * pLine; int i; Vec_PtrForEachEntry( char *, p->vLines, pLine, i ) if ( pToken < pLine ) return i; return -1; } /**Function************************************************************* Synopsis [Conservatively estimates the number of primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifEstimatePiNum( Io_BlifMan_t * p ) { char * pCur; int i, fSpaces; int Counter = 0; Vec_PtrForEachEntry( char *, p->vInputs, pCur, i ) for ( fSpaces = 0; *pCur; pCur++ ) { if ( Io_BlifCharIsSpace(*pCur) ) { if ( !fSpaces ) Counter++; fSpaces = 1; } else fSpaces = 0; } return Counter; } /**Function************************************************************* Synopsis [Conservatively estimates the number of AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifEstimateAndNum( Io_BlifMan_t * p ) { Io_BlifObj_t * pObj; char * pCur; int i, CounterOne, Counter = 0; for ( i = 0; i < p->iObjNext; i++ ) { pObj = p->pObjects + i; if ( !pObj->fDef ) continue; CounterOne = 0; for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ ) if ( *pCur == '0' || *pCur == '1' ) CounterOne++; if ( CounterOne ) Counter += CounterOne - 1; } return Counter; } /**Function************************************************************* Synopsis [Reads the file into a character buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static char * Io_BlifLoadFile( char * pFileName ) { FILE * pFile; int nFileSize; char * pContents; int RetValue; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" ); return NULL; } fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); if ( nFileSize == 0 ) { fclose( pFile ); printf( "Io_BlifLoadFile(): The file is empty.\n" ); return NULL; } pContents = ABC_ALLOC( char, nFileSize + 10 ); rewind( pFile ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); // finish off the file with the spare .end line // some benchmarks suddenly break off without this line strcpy( pContents + nFileSize, "\n.end\n" ); return pContents; } /**Function************************************************************* Synopsis [Prepares the parsing.] Description [Performs several preliminary operations: - Cuts the file buffer into separate lines. - Removes comments and line extenders. - Sorts lines by directives. - Estimates the number of objects. - Allocates room for the objects. - Allocates room for the hash table.] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_BlifReadPreparse( Io_BlifMan_t * p ) { char * pCur, * pPrev; int i, fComment = 0; // parse the buffer into lines and remove comments Vec_PtrPush( p->vLines, p->pBuffer ); for ( pCur = p->pBuffer; *pCur; pCur++ ) { if ( *pCur == '\n' ) { *pCur = 0; fComment = 0; Vec_PtrPush( p->vLines, pCur + 1 ); } else if ( *pCur == '#' ) fComment = 1; // remove comments if ( fComment ) *pCur = 0; } // unfold the line extensions and sort lines by directive Vec_PtrForEachEntry( char *, p->vLines, pCur, i ) { if ( *pCur == 0 ) continue; // find previous non-space character for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) if ( !Io_BlifCharIsSpace(*pPrev) ) break; // if it is the line extender, overwrite it with spaces if ( *pPrev == '\\' ) { for ( ; *pPrev; pPrev++ ) *pPrev = ' '; *pPrev = ' '; continue; } // skip spaces at the beginning of the line while ( Io_BlifCharIsSpace(*pCur++) ); // parse directives if ( *(pCur-1) != '.' ) continue; if ( !strncmp(pCur, "names", 5) ) Vec_PtrPush( p->vNames, pCur ); else if ( !strncmp(pCur, "latch", 5) ) Vec_PtrPush( p->vLatches, pCur ); else if ( !strncmp(pCur, "inputs", 6) ) Vec_PtrPush( p->vInputs, pCur ); else if ( !strncmp(pCur, "outputs", 7) ) Vec_PtrPush( p->vOutputs, pCur ); else if ( !strncmp(pCur, "model", 5) ) p->pModel = pCur; else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) ) break; else { pCur--; if ( pCur[strlen(pCur)-1] == '\r' ) pCur[strlen(pCur)-1] = 0; fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur ); } } // count the number of objects p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512; // allocate memory for objects p->pObjects = ABC_ALLOC( Io_BlifObj_t, p->nObjects ); memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) ); // allocate memory for the hash table p->nTableSize = p->nObjects/2 + 1; p->pTable = ABC_ALLOC( Io_BlifObj_t *, p->nTableSize ); memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) ); } /**Function************************************************************* Synopsis [Reads the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ) { Abc_Ntk_t * pAig; char * pLine; int i; // parse the model if ( !Io_BlifParseModel( p, p->pModel ) ) return NULL; // parse the inputs Vec_PtrForEachEntry( char *, p->vInputs, pLine, i ) if ( !Io_BlifParseInputs( p, pLine ) ) return NULL; // parse the outputs Vec_PtrForEachEntry( char *, p->vOutputs, pLine, i ) if ( !Io_BlifParseOutputs( p, pLine ) ) return NULL; // parse the latches Vec_PtrForEachEntry( char *, p->vLatches, pLine, i ) if ( !Io_BlifParseLatch( p, pLine ) ) return NULL; // parse the nodes Vec_PtrForEachEntry( char *, p->vNames, pLine, i ) if ( !Io_BlifParseNames( p, pLine ) ) return NULL; // reconstruct the network from the parsed data if ( !Io_BlifParseConstruct( p ) ) return NULL; // return the network pAig = p->pAig; p->pAig = NULL; return pAig; } /**Function************************************************************* Synopsis [Parses the model line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ) { char * pToken; Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry( p->vTokens, 0 ); assert( !strcmp(pToken, "model") ); if ( Vec_PtrSize(p->vTokens) != 2 ) { sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) ); return 0; } p->pModel = (char *)Vec_PtrEntry( p->vTokens, 1 ); return 1; } /**Function************************************************************* Synopsis [Parses the inputs line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ) { Io_BlifObj_t * pObj; char * pToken; int i; Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry(p->vTokens, 0); assert( !strcmp(pToken, "inputs") ); Vec_PtrForEachEntryStart( char *, p->vTokens, pToken, i, 1 ) { pObj = Io_BlifHashFindOrAdd( p, pToken ); if ( pObj->fPi ) { sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken ); return 0; } pObj->fPi = 1; Vec_PtrPush( p->vPis, pObj ); } return 1; } /**Function************************************************************* Synopsis [Parses the outputs line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ) { Io_BlifObj_t * pObj; char * pToken; int i; Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry(p->vTokens, 0); assert( !strcmp(pToken, "outputs") ); Vec_PtrForEachEntryStart( char *, p->vTokens, pToken, i, 1 ) { pObj = Io_BlifHashFindOrAdd( p, pToken ); if ( pObj->fPo ) fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken ); pObj->fPo = 1; Vec_PtrPush( p->vPos, pObj ); } return 1; } /**Function************************************************************* Synopsis [Parses the latches line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ) { Io_BlifObj_t * pObj; char * pToken; int Init; Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry(p->vTokens,0); assert( !strcmp(pToken, "latch") ); if ( Vec_PtrSize(p->vTokens) < 3 ) { sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) ); return 0; } // get initial value if ( Vec_PtrSize(p->vTokens) > 3 ) Init = atoi( (char *)Vec_PtrEntry(p->vTokens,3) ); else Init = 2; if ( Init < 0 || Init > 2 ) { sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,3) ); return 0; } if ( Init == 0 ) Init = IO_BLIF_INIT_ZERO; else if ( Init == 1 ) Init = IO_BLIF_INIT_ONE; else // if ( Init == 2 ) Init = IO_BLIF_INIT_DC; // get latch input pObj = Io_BlifHashFindOrAdd( p, (char *)Vec_PtrEntry(p->vTokens,1) ); pObj->fLi = 1; Vec_PtrPush( p->vLis, pObj ); pObj->Init = Init; // get latch output pObj = Io_BlifHashFindOrAdd( p, (char *)Vec_PtrEntry(p->vTokens,2) ); if ( pObj->fPi ) { sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,2) ); return 0; } if ( pObj->fLo ) { sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), (char*)Vec_PtrEntry(p->vTokens,2) ); return 0; } pObj->fLo = 1; Vec_PtrPush( p->vLos, pObj ); pObj->Init = Init; return 1; } /**Function************************************************************* Synopsis [Parses the nodes line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ) { Io_BlifObj_t * pObj; char * pName; Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); assert( !strcmp((char *)Vec_PtrEntry(p->vTokens,0), "names") ); pName = (char *)Vec_PtrEntryLast( p->vTokens ); pObj = Io_BlifHashFindOrAdd( p, pName ); if ( pObj->fPi ) { sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName ); return 0; } if ( pObj->fLo ) { sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName ); return 0; } if ( pObj->fDef ) { sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName ); return 0; } pObj->fDef = 1; // remember offset to the first fanin name pObj->pName = pName; pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1); return 1; } /**Function************************************************************* Synopsis [Constructs the AIG from the file parsing info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins ) { char * pProduct, * pOutput; Abc_Obj_t * pRes, * pCube; int i, k, Polarity = -1; p->nTablesRead++; // get the tokens Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' ); if ( Vec_PtrSize(p->vTokens) == 0 ) return Abc_ObjNot( Abc_AigConst1(p->pAig) ); if ( Vec_PtrSize(p->vTokens) == 1 ) { pOutput = (char *)Vec_PtrEntry( p->vTokens, 0 ); if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) { sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput ); return NULL; } return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' ); } pProduct = (char *)Vec_PtrEntry( p->vTokens, 0 ); if ( Vec_PtrSize(p->vTokens) % 2 == 1 ) { sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) ); return NULL; } // parse the table pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) ); for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ ) { pProduct = (char *)Vec_PtrEntry( p->vTokens, 2*i + 0 ); pOutput = (char *)Vec_PtrEntry( p->vTokens, 2*i + 1 ); if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) ) { sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) ); return NULL; } if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) { sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput ); return NULL; } if ( Polarity == -1 ) Polarity = pOutput[0] - '0'; else if ( Polarity != pOutput[0] - '0' ) { sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity ); return NULL; } // parse one product product pCube = Abc_AigConst1(p->pAig); for ( k = 0; pProduct[k]; k++ ) { if ( pProduct[k] == '0' ) pCube = Abc_AigAnd( (Abc_Aig_t *)p->pAig->pManFunc, pCube, Abc_ObjNot((Abc_Obj_t *)Vec_PtrEntry(vFanins,k)) ); else if ( pProduct[k] == '1' ) pCube = Abc_AigAnd( (Abc_Aig_t *)p->pAig->pManFunc, pCube, (Abc_Obj_t *)Vec_PtrEntry(vFanins,k) ); else if ( pProduct[k] != '-' ) { sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] ); return NULL; } } pRes = Abc_AigOr( (Abc_Aig_t *)p->pAig->pManFunc, pRes, pCube ); } pRes = Abc_ObjNotCond( pRes, Polarity == 0 ); return pRes; } /**Function************************************************************* Synopsis [Constructs the AIG from the file parsing info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName ) { Vec_Ptr_t * vFanins; Abc_Obj_t * pFaninAbc; Io_BlifObj_t * pObjIo; char * pNameFanin; int i; // get the IO object with this name pObjIo = *Io_BlifHashLookup( p, pName ); if ( pObjIo == NULL ) { sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName ); return NULL; } // loop detection if ( pObjIo->fLoop ) { sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName ); return NULL; } // check if the AIG is already constructed if ( pObjIo->pEquiv ) return (Abc_Obj_t *)pObjIo->pEquiv; // mark this node on the path pObjIo->fLoop = 1; // construct the AIGs for the fanins vFanins = Vec_PtrAlloc( 8 ); Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName ); Vec_PtrForEachEntry( char *, vFanins, pNameFanin, i ) { pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin ); if ( pFaninAbc == NULL ) { Vec_PtrFree( vFanins ); return NULL; } Vec_PtrWriteEntry( vFanins, i, pFaninAbc ); } // construct the node pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins ); Vec_PtrFree( vFanins ); // unmark this node on the path pObjIo->fLoop = 0; // remember the new node return (Abc_Obj_t *)pObjIo->pEquiv; } /**Function************************************************************* Synopsis [Constructs the AIG from the file parsing info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_BlifParseConstruct( Io_BlifMan_t * p ) { Abc_Ntk_t * pAig; Io_BlifObj_t * pObjIo, * pObjIoInput; Abc_Obj_t * pObj, * pLatch; int i; // allocate the empty AIG pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pAig->pName = Extra_UtilStrsav( p->pModel ); pAig->pSpec = Extra_UtilStrsav( p->pFileName ); // create PIs Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPis, pObjIo, i ) { pObj = Abc_NtkCreatePi( pAig ); Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); pObjIo->pEquiv = pObj; } // create POs Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPos, pObjIo, i ) { pObj = Abc_NtkCreatePo( pAig ); Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); } // create latches Vec_PtrForEachEntry( Io_BlifObj_t *, p->vLos, pObjIo, i ) { // add the latch input terminal pObj = Abc_NtkCreateBi( pAig ); pObjIoInput = (Io_BlifObj_t *)Vec_PtrEntry( p->vLis, i ); Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL ); // add the latch box pLatch = Abc_NtkCreateLatch( pAig ); pLatch->pData = (void *)(ABC_PTRUINT_T)pObjIo->Init; Abc_ObjAssignName( pLatch, pObjIo->pName, "L" ); Abc_ObjAddFanin( pLatch, pObj ); // add the latch output terminal pObj = Abc_NtkCreateBo( pAig ); Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); Abc_ObjAddFanin( pObj, pLatch ); // set the value of the latch output // pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init ); pObjIo->pEquiv = pObj; } // traverse the nodes from the POs Vec_PtrForEachEntry( Io_BlifObj_t *, p->vPos, pObjIo, i ) { pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); if ( pObj == NULL ) return 0; Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj ); } // traverse the nodes from the latch inputs Vec_PtrForEachEntry( Io_BlifObj_t *, p->vLis, pObjIo, i ) { pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); if ( pObj == NULL ) return 0; // pObj = Abc_ObjNotCond( pObj, pObjIo->Init ); Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj ); } p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead; if ( p->nTablesLeft ) printf( "The number of dangling tables = %d.\n", p->nTablesLeft ); printf( "AND nodes = %6d. Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadBlifMv.c000066400000000000000000002337401300674244400240350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadBlifMv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read BLIF-MV file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 8, 2007.] Revision [$Id: ioReadBlifMv.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "misc/zlib/zlib.h" #include "misc/bzlib/bzlib.h" #include "base/abc/abc.h" #include "misc/vec/vecPtr.h" #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define IO_BLIFMV_MAXVALUES 256 //#define IO_VERBOSE_OUTPUT typedef struct Io_MvVar_t_ Io_MvVar_t; // parsing var typedef struct Io_MvMod_t_ Io_MvMod_t; // parsing model typedef struct Io_MvMan_t_ Io_MvMan_t; // parsing manager Vec_Ptr_t *vGlobalLtlArray; struct Io_MvVar_t_ { int nValues; // the number of values char ** pNames; // the value names }; struct Io_MvMod_t_ { // file lines char * pName; // .model line Vec_Ptr_t * vInputs; // .inputs lines Vec_Ptr_t * vOutputs; // .outputs lines Vec_Ptr_t * vLatches; // .latch lines Vec_Ptr_t * vFlops; // .flop lines Vec_Ptr_t * vResets; // .reset lines Vec_Ptr_t * vNames; // .names lines Vec_Ptr_t * vSubckts; // .subckt lines Vec_Ptr_t * vShorts; // .short lines Vec_Ptr_t * vOnehots; // .onehot lines Vec_Ptr_t * vMvs; // .mv lines Vec_Ptr_t * vConstrs; // .constraint lines Vec_Ptr_t * vLtlProperties; int fBlackBox; // indicates blackbox model // the resulting network Abc_Ntk_t * pNtk; Abc_Obj_t * pResetLatch; // the parent manager Io_MvMan_t * pMan; }; struct Io_MvMan_t_ { // general info about file int fBlifMv; // the file is BLIF-MV int fUseReset; // the reset circuitry is added char * pFileName; // the name of the file char * pBuffer; // the contents of the file Vec_Ptr_t * vLines; // the line beginnings // the results of reading Abc_Des_t * pDesign; // the design under construction int nNDnodes; // the counter of ND nodes // intermediate storage for models Vec_Ptr_t * vModels; // vector of models Io_MvMod_t * pLatest; // the current model // current processing info Vec_Ptr_t * vTokens; // the current tokens Vec_Ptr_t * vTokens2; // the current tokens Vec_Str_t * vFunc; // the local function // error reporting char sError[512]; // the error string generated during parsing // statistics int nTablesRead; // the number of processed tables int nTablesLeft; // the number of dangling tables }; // static functions static Io_MvMan_t * Io_MvAlloc(); static void Io_MvFree( Io_MvMan_t * p ); static Io_MvMod_t * Io_MvModAlloc(); static void Io_MvModFree( Io_MvMod_t * p ); static char * Io_MvLoadFile( char * pFileName ); static void Io_MvReadPreparse( Io_MvMan_t * p ); static int Io_MvReadInterfaces( Io_MvMan_t * p ); static Abc_Des_t * Io_MvParse( Io_MvMan_t * p ); static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineConstrs( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineFlop( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ); static Vec_Int_t * Io_MvParseLineOnehot( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ); static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineShortBlif( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineLtlProperty( Io_MvMod_t * p, char * pLine ); static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ); static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ); static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; } extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the network from the BLIF or BLIF-MV file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ) { FILE * pFile; Io_MvMan_t * p; Abc_Ntk_t * pNtk, * pExdc; Abc_Des_t * pDesign = NULL; char * pDesignName; int RetValue, i; char * pLtlProp; // check that the file is available pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" ); return 0; } fclose( pFile ); // start the file reader p = Io_MvAlloc(); p->fBlifMv = fBlifMv; p->fUseReset = 1; p->pFileName = pFileName; p->pBuffer = Io_MvLoadFile( pFileName ); if ( p->pBuffer == NULL ) { Io_MvFree( p ); return NULL; } // set the design name pDesignName = Extra_FileNameGeneric( pFileName ); p->pDesign = Abc_DesCreate( pDesignName ); ABC_FREE( pDesignName ); // free the HOP manager Hop_ManStop( (Hop_Man_t *)p->pDesign->pManFunc ); p->pDesign->pManFunc = NULL; // prepare the file for parsing Io_MvReadPreparse( p ); // parse interfaces of each network and construct the network if ( Io_MvReadInterfaces( p ) ) pDesign = Io_MvParse( p ); if ( p->sError[0] ) fprintf( stdout, "%s\n", p->sError ); Io_MvFree( p ); if ( pDesign == NULL ) return NULL; // pDesign should be linked to all models of the design // make sure that everything is okay with the network structure if ( fCheck ) { Vec_PtrForEachEntry( Abc_Ntk_t *, pDesign->vModules, pNtk, i ) { if ( !Abc_NtkCheckRead( pNtk ) ) { printf( "Io_ReadBlifMv: The network check has failed for model %s.\n", pNtk->pName ); Abc_DesFree( pDesign, NULL ); return NULL; } } } //Abc_DesPrint( pDesign ); // check if there is an EXDC network if ( Vec_PtrSize(pDesign->vModules) > 1 ) { pNtk = (Abc_Ntk_t *)Vec_PtrEntry(pDesign->vModules, 0); Vec_PtrForEachEntryStart( Abc_Ntk_t *, pDesign->vModules, pExdc, i, 1 ) if ( !strcmp(pExdc->pName, "EXDC") ) { assert( pNtk->pExdc == NULL ); pNtk->pExdc = pExdc; Vec_PtrRemove(pDesign->vModules, pExdc); pExdc->pDesign = NULL; i--; } else pNtk = pExdc; } // detect top-level model RetValue = Abc_DesFindTopLevelModels( pDesign ); pNtk = (Abc_Ntk_t *)Vec_PtrEntry( pDesign->vTops, 0 ); if ( RetValue > 1 ) printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", Vec_PtrSize(pDesign->vTops), pNtk->pName ); // extract the master network pNtk->pDesign = pDesign; pDesign->pManFunc = NULL; // verify the design for cyclic dependence assert( Vec_PtrSize(pDesign->vModules) > 0 ); if ( Vec_PtrSize(pDesign->vModules) == 1 ) { // printf( "Warning: The design is not hierarchical.\n" ); Abc_DesFree( pDesign, pNtk ); pNtk->pDesign = NULL; pNtk->pSpec = Extra_UtilStrsav( pFileName ); } else Abc_NtkIsAcyclicHierarchy( pNtk ); //Io_WriteBlifMv( pNtk, "_temp_.mv" ); if ( pNtk->pSpec == NULL ) pNtk->pSpec = Extra_UtilStrsav( pFileName ); vGlobalLtlArray = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( char *, vGlobalLtlArray, pLtlProp, i ) Vec_PtrPush( pNtk->vLtlProperties, pLtlProp ); Vec_PtrFreeP( &vGlobalLtlArray ); return pNtk; } /**Function************************************************************* Synopsis [Allocates the BLIF parsing structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Io_MvMan_t * Io_MvAlloc() { Io_MvMan_t * p; p = ABC_ALLOC( Io_MvMan_t, 1 ); memset( p, 0, sizeof(Io_MvMan_t) ); p->vLines = Vec_PtrAlloc( 512 ); p->vModels = Vec_PtrAlloc( 512 ); p->vTokens = Vec_PtrAlloc( 512 ); p->vTokens2 = Vec_PtrAlloc( 512 ); p->vFunc = Vec_StrAlloc( 512 ); return p; } /**Function************************************************************* Synopsis [Frees the BLIF parsing structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_MvFree( Io_MvMan_t * p ) { Io_MvMod_t * pMod; int i; if ( p->pDesign ) Abc_DesFree( p->pDesign, NULL ); if ( p->pBuffer ) ABC_FREE( p->pBuffer ); if ( p->vLines ) Vec_PtrFree( p->vLines ); if ( p->vModels ) { Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i ) Io_MvModFree( pMod ); Vec_PtrFree( p->vModels ); } Vec_PtrFree( p->vTokens ); Vec_PtrFree( p->vTokens2 ); Vec_StrFree( p->vFunc ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Allocates the BLIF parsing structure for one model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Io_MvMod_t * Io_MvModAlloc() { Io_MvMod_t * p; p = ABC_ALLOC( Io_MvMod_t, 1 ); memset( p, 0, sizeof(Io_MvMod_t) ); p->vInputs = Vec_PtrAlloc( 512 ); p->vOutputs = Vec_PtrAlloc( 512 ); p->vLatches = Vec_PtrAlloc( 512 ); p->vFlops = Vec_PtrAlloc( 512 ); p->vResets = Vec_PtrAlloc( 512 ); p->vNames = Vec_PtrAlloc( 512 ); p->vSubckts = Vec_PtrAlloc( 512 ); p->vShorts = Vec_PtrAlloc( 512 ); p->vOnehots = Vec_PtrAlloc( 512 ); p->vMvs = Vec_PtrAlloc( 512 ); p->vConstrs = Vec_PtrAlloc( 512 ); p->vLtlProperties = Vec_PtrAlloc( 512 ); return p; } /**Function************************************************************* Synopsis [Allocates the BLIF parsing structure for one model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_MvModFree( Io_MvMod_t * p ) { // if ( p->pNtk ) // Abc_NtkDelete( p->pNtk ); Vec_PtrFree( p->vLtlProperties ); Vec_PtrFree( p->vInputs ); Vec_PtrFree( p->vOutputs ); Vec_PtrFree( p->vLatches ); Vec_PtrFree( p->vFlops ); Vec_PtrFree( p->vResets ); Vec_PtrFree( p->vNames ); Vec_PtrFree( p->vSubckts ); Vec_PtrFree( p->vShorts ); Vec_PtrFree( p->vOnehots ); Vec_PtrFree( p->vMvs ); Vec_PtrFree( p->vConstrs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Counts the number of given chars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvCountChars( char * pLine, char Char ) { char * pCur; int Counter = 0; for ( pCur = pLine; *pCur; pCur++ ) if ( *pCur == Char ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Returns the place where the arrow is hiding.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static char * Io_MvFindArrow( char * pLine ) { char * pCur; for ( pCur = pLine; *(pCur+1); pCur++ ) if ( *pCur == '-' && *(pCur+1) == '>' ) { *pCur = ' '; *(pCur+1) = ' '; return pCur; } return NULL; } /**Function************************************************************* Synopsis [Collects the already split tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) { char * pCur; Vec_PtrClear( vTokens ); for ( pCur = pInput; pCur < pOutput; pCur++ ) { if ( *pCur == 0 ) continue; Vec_PtrPush( vTokens, pCur ); while ( *++pCur ); } } /**Function************************************************************* Synopsis [Splits the line into tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) { char * pCur; // clear spaces for ( pCur = pLine; *pCur != Stop; pCur++ ) if ( Io_MvCharIsSpace(*pCur) ) *pCur = 0; // collect tokens Io_MvCollectTokens( vTokens, pLine, pCur ); } /**Function************************************************************* Synopsis [Splits the line into tokens when .default may be present.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine ) { char * pCur; // clear spaces for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ ) if ( Io_MvCharIsSpace(*pCur) ) *pCur = 0; // collect tokens Io_MvCollectTokens( vTokens, pLine, pCur ); } /**Function************************************************************* Synopsis [Splits the line into tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char ) { char * pCur; // clear spaces for ( pCur = pLine; *pCur != Stop; pCur++ ) if ( Io_MvCharIsSpace(*pCur) || *pCur == Char ) *pCur = 0; // collect tokens Io_MvCollectTokens( vTokens, pLine, pCur ); } /**Function************************************************************* Synopsis [Returns the 1-based number of the line in which the token occurs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvGetLine( Io_MvMan_t * p, char * pToken ) { char * pLine; int i; Vec_PtrForEachEntry( char *, p->vLines, pLine, i ) if ( pToken < pLine ) return i; return -1; } /**Function************************************************************* Synopsis [Reads the file into a character buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ typedef struct buflist { char buf[1<<20]; int nBuf; struct buflist * next; } buflist; char * Io_MvLoadFileBz2( char * pFileName, int * pnFileSize ) { FILE * pFile; int nFileSize = 0; char * pContents; BZFILE * b; int bzError, RetValue; struct buflist * pNext; buflist * bufHead = NULL, * buf = NULL; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { Abc_Print( -1, "Io_MvLoadFileBz2(): The file is unavailable (absent or open).\n" ); return NULL; } b = BZ2_bzReadOpen(&bzError,pFile,0,0,NULL,0); if (bzError != BZ_OK) { Abc_Print( -1, "Io_MvLoadFileBz2(): BZ2_bzReadOpen() failed with error %d.\n",bzError ); return NULL; } do { if (!bufHead) buf = bufHead = ABC_ALLOC( buflist, 1 ); else buf = buf->next = ABC_ALLOC( buflist, 1 ); nFileSize += buf->nBuf = BZ2_bzRead(&bzError,b,buf->buf,1<<20); buf->next = NULL; } while (bzError == BZ_OK); if (bzError == BZ_STREAM_END) { // we're okay char * p; int nBytes = 0; BZ2_bzReadClose(&bzError,b); p = pContents = ABC_ALLOC( char, nFileSize + 10 ); buf = bufHead; do { memcpy(p+nBytes,buf->buf,buf->nBuf); nBytes += buf->nBuf; // } while((buf = buf->next)); pNext = buf->next; ABC_FREE( buf ); } while((buf = pNext)); } else if (bzError == BZ_DATA_ERROR_MAGIC) { // not a BZIP2 file BZ2_bzReadClose(&bzError,b); fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); if ( nFileSize == 0 ) { Abc_Print( -1, "Io_MvLoadFileBz2(): The file is empty.\n" ); return NULL; } pContents = ABC_ALLOC( char, nFileSize + 10 ); rewind( pFile ); RetValue = fread( pContents, nFileSize, 1, pFile ); } else { // Some other error. Abc_Print( -1, "Io_MvLoadFileBz2(): Unable to read the compressed BLIF.\n" ); return NULL; } fclose( pFile ); // finish off the file with the spare .end line // some benchmarks suddenly break off without this line strcpy( pContents + nFileSize, "\n.end\n" ); *pnFileSize = nFileSize; return pContents; } /**Function************************************************************* Synopsis [Reads the file into a character buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static char * Io_MvLoadFileGz( char * pFileName, int * pnFileSize ) { const int READ_BLOCK_SIZE = 100000; gzFile pFile; char * pContents; int amtRead, readBlock, nFileSize = READ_BLOCK_SIZE; pFile = gzopen( pFileName, "rb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen pContents = ABC_ALLOC( char, nFileSize ); readBlock = 0; while ((amtRead = gzread(pFile, pContents + readBlock * READ_BLOCK_SIZE, READ_BLOCK_SIZE)) == READ_BLOCK_SIZE) { //Abc_Print( 1,"%d: read %d bytes\n", readBlock, amtRead); nFileSize += READ_BLOCK_SIZE; pContents = ABC_REALLOC(char, pContents, nFileSize); ++readBlock; } //Abc_Print( 1,"%d: read %d bytes\n", readBlock, amtRead); assert( amtRead != -1 ); // indicates a zlib error nFileSize -= (READ_BLOCK_SIZE - amtRead); gzclose(pFile); *pnFileSize = nFileSize; return pContents; } /**Function************************************************************* Synopsis [Reads the file into a character buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static char * Io_MvLoadFile( char * pFileName ) { FILE * pFile; int nFileSize; char * pContents; int RetValue; if ( !strncmp(pFileName+strlen(pFileName)-4,".bz2",4) ) return Io_MvLoadFileBz2( pFileName, &nFileSize ); if ( !strncmp(pFileName+strlen(pFileName)-3,".gz",3) ) return Io_MvLoadFileGz( pFileName, &nFileSize ); pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" ); return NULL; } fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); if ( nFileSize == 0 ) { fclose( pFile ); printf( "Io_MvLoadFile(): The file is empty.\n" ); return NULL; } pContents = ABC_ALLOC( char, nFileSize + 10 ); rewind( pFile ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); // finish off the file with the spare .end line // some benchmarks suddenly break off without this line strcpy( pContents + nFileSize, "\n.end\n" ); return pContents; } /**Function************************************************************* Synopsis [Prepares the parsing.] Description [Performs several preliminary operations: - Cuts the file buffer into separate lines. - Removes comments and line extenders. - Sorts lines by directives. - Estimates the number of objects. - Allocates room for the objects. - Allocates room for the hash table.] SideEffects [] SeeAlso [] ***********************************************************************/ static void Io_MvReadPreparse( Io_MvMan_t * p ) { char * pCur, * pPrev; int i, fComment = 0; // parse the buffer into lines and remove comments Vec_PtrPush( p->vLines, p->pBuffer ); for ( pCur = p->pBuffer; *pCur; pCur++ ) { if ( *pCur == '\n' ) { *pCur = 0; // if ( *(pCur-1) == '\r' ) // *(pCur-1) = 0; fComment = 0; Vec_PtrPush( p->vLines, pCur + 1 ); } else if ( *pCur == '#' ) fComment = 1; // remove comments if ( fComment ) *pCur = 0; } // unfold the line extensions and sort lines by directive Vec_PtrForEachEntry( char *, p->vLines, pCur, i ) { if ( *pCur == 0 ) continue; // find previous non-space character for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) if ( !Io_MvCharIsSpace(*pPrev) ) break; // if it is the line extender, overwrite it with spaces if ( pPrev >= p->pBuffer && *pPrev == '\\' ) { for ( ; *pPrev; pPrev++ ) *pPrev = ' '; *pPrev = ' '; continue; } // skip spaces at the beginning of the line while ( Io_MvCharIsSpace(*pCur++) ); // parse directives if ( *(pCur-1) != '.' ) continue; if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) ) Vec_PtrPush( p->pLatest->vNames, pCur ); else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) ) continue; else if ( !strncmp( pCur, "ltlformula", 10 ) ) Vec_PtrPush( p->pLatest->vLtlProperties, pCur ); else if ( !strncmp(pCur, "latch", 5) ) Vec_PtrPush( p->pLatest->vLatches, pCur ); else if ( !strncmp(pCur, "flop", 4) ) Vec_PtrPush( p->pLatest->vFlops, pCur ); else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) ) Vec_PtrPush( p->pLatest->vResets, pCur ); else if ( !strncmp(pCur, "inputs", 6) ) Vec_PtrPush( p->pLatest->vInputs, pCur ); else if ( !strncmp(pCur, "outputs", 7) ) Vec_PtrPush( p->pLatest->vOutputs, pCur ); else if ( !strncmp(pCur, "subckt", 6) ) Vec_PtrPush( p->pLatest->vSubckts, pCur ); else if ( !strncmp(pCur, "short", 5) ) Vec_PtrPush( p->pLatest->vShorts, pCur ); else if ( !strncmp(pCur, "onehot", 6) ) Vec_PtrPush( p->pLatest->vOnehots, pCur ); else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) ) Vec_PtrPush( p->pLatest->vMvs, pCur ); else if ( !strncmp(pCur, "constraint", 10) ) Vec_PtrPush( p->pLatest->vConstrs, pCur ); else if ( !strncmp(pCur, "blackbox", 8) ) p->pLatest->fBlackBox = 1; else if ( !strncmp(pCur, "model", 5) ) { p->pLatest = Io_MvModAlloc(); p->pLatest->pName = pCur; p->pLatest->pMan = p; } else if ( !strncmp(pCur, "end", 3) ) { if ( p->pLatest ) Vec_PtrPush( p->vModels, p->pLatest ); p->pLatest = NULL; } else if ( !strncmp(pCur, "exdc", 4) ) { // fprintf( stdout, "Line %d: The design contains EXDC network (warning only).\n", Io_MvGetLine(p, pCur) ); fprintf( stdout, "Warning: The design contains EXDC network.\n" ); if ( p->pLatest ) Vec_PtrPush( p->vModels, p->pLatest ); p->pLatest = Io_MvModAlloc(); p->pLatest->pName = NULL; p->pLatest->pMan = p; } else if ( !strncmp(pCur, "attrib", 6) ) {} else if ( !strncmp(pCur, "delay", 5) ) {} else if ( !strncmp(pCur, "input_", 6) ) {} else if ( !strncmp(pCur, "output_", 7) ) {} else if ( !strncmp(pCur, "no_merge", 8) ) {} else if ( !strncmp(pCur, "wd", 2) ) {} // else if ( !strncmp(pCur, "inouts", 6) ) // {} else { pCur--; if ( pCur[strlen(pCur)-1] == '\r' ) pCur[strlen(pCur)-1] = 0; fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur ); } } } /**Function************************************************************* Synopsis [Parses interfaces of the models.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvReadInterfaces( Io_MvMan_t * p ) { Io_MvMod_t * pMod; char * pLine; int i, k, nOutsOld; // iterate through the models Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i ) { // parse the model if ( !Io_MvParseLineModel( pMod, pMod->pName ) ) return 0; // add model to the design if ( !Abc_DesAddModel( p->pDesign, pMod->pNtk ) ) { sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName ); return 0; } // parse the inputs Vec_PtrForEachEntry( char *, pMod->vInputs, pLine, k ) if ( !Io_MvParseLineInputs( pMod, pLine ) ) return 0; // parse the outputs Vec_PtrForEachEntry( char *, pMod->vOutputs, pLine, k ) if ( !Io_MvParseLineOutputs( pMod, pLine ) ) return 0; // parse the constraints nOutsOld = Abc_NtkPoNum(pMod->pNtk); Vec_PtrForEachEntry( char *, pMod->vConstrs, pLine, k ) if ( !Io_MvParseLineConstrs( pMod, pLine ) ) return 0; pMod->pNtk->nConstrs = Abc_NtkPoNum(pMod->pNtk) - nOutsOld; Vec_PtrForEachEntry( char *, pMod->vLtlProperties, pLine, k ) if ( !Io_MvParseLineLtlProperty( pMod, pLine ) ) return 0; // report the results #ifdef IO_VERBOSE_OUTPUT if ( Vec_PtrSize(p->vModels) > 1 ) printf( "Parsed %-32s: PI =%6d PO =%6d ND =%8d FF =%6d B =%6d\n", pMod->pNtk->pName, Abc_NtkPiNum(pMod->pNtk), Abc_NtkPoNum(pMod->pNtk), Vec_PtrSize(pMod->vNames), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vSubckts) ); #endif } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Abc_Des_t * Io_MvParse( Io_MvMan_t * p ) { Abc_Des_t * pDesign; Io_MvMod_t * pMod; char * pLine; int i, k; // iterate through the models Vec_PtrForEachEntry( Io_MvMod_t *, p->vModels, pMod, i ) { #ifdef IO_VERBOSE_OUTPUT if ( Vec_PtrSize(p->vModels) > 1 ) printf( "Parsing model %s...\n", pMod->pNtk->pName ); #endif // check if there any MV lines if ( Vec_PtrSize(pMod->vMvs) > 0 ) Abc_NtkStartMvVars( pMod->pNtk ); // parse the mv lines Vec_PtrForEachEntry( char *, pMod->vMvs, pLine, k ) if ( !Io_MvParseLineMv( pMod, pLine ) ) return NULL; // if reset lines are used there should be the same number of them as latches if ( Vec_PtrSize(pMod->vResets) > 0 ) { if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) ) { sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).", Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) ); return NULL; } // create binary latch with 1-data and 0-init if ( p->fUseReset ) pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv ); } // parse the flops Vec_PtrForEachEntry( char *, pMod->vFlops, pLine, k ) if ( !Io_MvParseLineFlop( pMod, pLine ) ) return NULL; // parse the latches Vec_PtrForEachEntry( char *, pMod->vLatches, pLine, k ) if ( !Io_MvParseLineLatch( pMod, pLine ) ) return NULL; // parse the reset lines if ( p->fUseReset ) Vec_PtrForEachEntry( char *, pMod->vResets, pLine, k ) if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) ) return NULL; // parse the nodes if ( p->fBlifMv ) { Vec_PtrForEachEntry( char *, pMod->vNames, pLine, k ) if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) ) return NULL; } else { Vec_PtrForEachEntry( char *, pMod->vNames, pLine, k ) if ( !Io_MvParseLineNamesBlif( pMod, pLine ) ) return NULL; Vec_PtrForEachEntry( char *, pMod->vShorts, pLine, k ) if ( !Io_MvParseLineShortBlif( pMod, pLine ) ) return NULL; } // parse the subcircuits Vec_PtrForEachEntry( char *, pMod->vSubckts, pLine, k ) if ( !Io_MvParseLineSubckt( pMod, pLine ) ) return NULL; // allow for blackboxes without .blackbox line if ( Abc_NtkLatchNum(pMod->pNtk) == 0 && Abc_NtkNodeNum(pMod->pNtk) == 0 && Abc_NtkBoxNum(pMod->pNtk) == 0 ) { if ( pMod->pNtk->ntkFunc == ABC_FUNC_SOP ) { Mem_FlexStop( (Mem_Flex_t *)pMod->pNtk->pManFunc, 0 ); pMod->pNtk->pManFunc = NULL; pMod->pNtk->ntkFunc = ABC_FUNC_BLACKBOX; } } // finalize the network Abc_NtkFinalizeRead( pMod->pNtk ); // read the one-hotness lines if ( Vec_PtrSize(pMod->vOnehots) > 0 ) { Vec_Int_t * vLine; Abc_Obj_t * pObj; // set register numbers Abc_NtkForEachLatch( pMod->pNtk, pObj, k ) pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)k; // derive register pMod->pNtk->vOnehots = Vec_PtrAlloc( Vec_PtrSize(pMod->vOnehots) ); Vec_PtrForEachEntry( char *, pMod->vOnehots, pLine, k ) { vLine = Io_MvParseLineOnehot( pMod, pLine ); if ( vLine == NULL ) return NULL; Vec_PtrPush( pMod->pNtk->vOnehots, vLine ); // printf( "Parsed %d one-hot registers.\n", Vec_IntSize(vLine) ); } // reset register numbers Abc_NtkForEachLatch( pMod->pNtk, pObj, k ) pObj->pNext = NULL; // print the result printf( "Parsed %d groups of 1-hot registers: { ", Vec_PtrSize(pMod->pNtk->vOnehots) ); Vec_PtrForEachEntry( Vec_Int_t *, pMod->pNtk->vOnehots, vLine, k ) printf( "%d ", Vec_IntSize(vLine) ); printf( "}\n" ); printf( "The total number of 1-hot registers = %d. (%.2f %%)\n", Vec_VecSizeSize( (Vec_Vec_t *)pMod->pNtk->vOnehots ), 100.0 * Vec_VecSizeSize( (Vec_Vec_t *)pMod->pNtk->vOnehots ) / Abc_NtkLatchNum(pMod->pNtk) ); { extern void Abc_GenOneHotIntervals( char * pFileName, int nPis, int nRegs, Vec_Ptr_t * vOnehots ); char * pFileName = Extra_FileNameGenericAppend( pMod->pMan->pFileName, "_1h.blif" ); Abc_GenOneHotIntervals( pFileName, Abc_NtkPiNum(pMod->pNtk), Abc_NtkLatchNum(pMod->pNtk), pMod->pNtk->vOnehots ); printf( "One-hotness condition is written into file \"%s\".\n", pFileName ); } } if ( Vec_PtrSize(pMod->vFlops) ) { printf( "Warning: The parser converted %d .flop lines into .latch lines\n", Vec_PtrSize(pMod->vFlops) ); printf( "(information about set, reset, enable of the flops may be lost).\n" ); } } if ( p->nNDnodes ) // printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes ); printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes ); // return the network pDesign = p->pDesign; p->pDesign = NULL; return pDesign; } /**Function************************************************************* Synopsis [Parses the model line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; char * pToken, * pPivot; if ( pLine == NULL ) { p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); p->pNtk->pName = Extra_UtilStrsav( "EXDC" ); return 1; } Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry( vTokens, 0 ); assert( !strcmp(pToken, "model") ); if ( Vec_PtrSize(vTokens) != 2 ) { sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); return 0; } if ( p->fBlackBox ) p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 ); else if ( p->pMan->fBlifMv ) p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 ); else p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); // for ( pPivot = pToken = Vec_PtrEntry(vTokens, 1); *pToken; pToken++ ) // if ( *pToken == '/' || *pToken == '\\' ) // pPivot = pToken+1; pPivot = pToken = (char *)Vec_PtrEntry(vTokens, 1); p->pNtk->pName = Extra_UtilStrsav( pPivot ); return 1; } /**Function************************************************************* Synopsis [Parses the inputs line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; char * pToken; int i; Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry(vTokens, 0); assert( !strcmp(pToken, "inputs") ); Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 ) Io_ReadCreatePi( p->pNtk, pToken ); return 1; } /**Function************************************************************* Synopsis [Parses the outputs line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; char * pToken; int i; Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry(vTokens, 0); assert( !strcmp(pToken, "outputs") ); Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 ) Io_ReadCreatePo( p->pNtk, pToken ); return 1; } /**Function************************************************************* Synopsis [Parses the outputs line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineConstrs( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; char * pToken; int i; Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry(vTokens, 0); assert( !strcmp(pToken, "constraint") ); Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 ) Io_ReadCreatePo( p->pNtk, pToken ); return 1; } /**Function************************************************************* Synopsis [Parses the LTL property line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineLtlProperty( Io_MvMod_t * p, char * pLine ) { int i, j; int quoteBegin, quoteEnd; char keyWordLtlFormula[11]; char *actualLtlFormula; //checking if the line begins with the keyword "ltlformula" and //progressing the pointer forword for( i=0; i<10; i++ ) keyWordLtlFormula[i] = pLine[i]; quoteBegin = i; keyWordLtlFormula[10] = '\0'; assert( strcmp( "ltlformula", keyWordLtlFormula ) == 0 ); while( pLine[i] != '"' ) i++; quoteBegin = i; i = strlen( pLine ); while( pLine[i] != '"' ) i--; quoteEnd = i; actualLtlFormula = (char *)malloc( sizeof(char) * (quoteEnd - quoteBegin) ); //printf("\nThe input ltl formula = "); for( i = quoteBegin + 1, j = 0; ipMan->vTokens; Abc_Obj_t * pObj, * pNet; char * pToken; int Init; Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry(vTokens,0); assert( !strcmp(pToken, "latch") ); if ( Vec_PtrSize(vTokens) < 3 ) { sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) ); return 0; } // create latch if ( p->pResetLatch == NULL ) { pObj = Io_ReadCreateLatch( p->pNtk, (char *)Vec_PtrEntry(vTokens,1), (char *)Vec_PtrEntry(vTokens,2) ); // get initial value if ( p->pMan->fBlifMv ) Abc_LatchSetInit0( pObj ); else { if ( Vec_PtrSize(vTokens) > 6 ) printf( "Warning: Line %d has .latch directive with unrecognized entries (the total of %d entries).\n", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); if ( Vec_PtrSize(vTokens) > 3 ) Init = atoi( (char *)Vec_PtrEntryLast(vTokens) ); else Init = 2; if ( Init < 0 || Init > 3 ) { sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) ); return 0; } if ( Init == 0 ) Abc_LatchSetInit0( pObj ); else if ( Init == 1 ) Abc_LatchSetInit1( pObj ); else // if ( Init == 2 ) Abc_LatchSetInitDc( pObj ); } } else { // get the net corresponding to the output of the latch pNet = Abc_NtkFindOrCreateNet( p->pNtk, (char *)Vec_PtrEntry(vTokens,2) ); // get the net corresponding to the latch output (feeding into reset MUX) pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") ); // create latch pObj = Io_ReadCreateLatch( p->pNtk, (char *)Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) ); // Abc_LatchSetInit0( pObj ); Abc_LatchSetInit0( pObj ); } return 1; } /**Function************************************************************* Synopsis [Parses the latches line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineFlop( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; Abc_Obj_t * pObj; char * pToken, * pOutput, * pInput; int i, Init = 2; assert( !p->pMan->fBlifMv ); Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); pToken = (char *)Vec_PtrEntry(vTokens,0); assert( !strcmp(pToken, "flop") ); // get flop output Vec_PtrForEachEntry( char *, vTokens, pToken, i ) if ( pToken[0] == 'Q' && pToken[1] == '=' ) break; if ( i == Vec_PtrSize(vTokens) ) { sprintf( p->pMan->sError, "Line %d: Cannot find flop output.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) ); return 0; } pOutput = pToken+2; // get flop input Vec_PtrForEachEntry( char *, vTokens, pToken, i ) if ( pToken[0] == 'D' && pToken[1] == '=' ) break; if ( i == Vec_PtrSize(vTokens) ) { sprintf( p->pMan->sError, "Line %d: Cannot find flop input.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) ); return 0; } pInput = pToken+2; // create latch pObj = Io_ReadCreateLatch( p->pNtk, pInput, pOutput ); // get the init value Vec_PtrForEachEntry( char *, vTokens, pToken, i ) { if ( !strncmp( pToken, "init=", 5 ) ) { Init = 0; if ( pToken[5] == '1' ) Init = 1; else if ( pToken[5] == '2' ) Init = 2; else if ( pToken[5] != '0' ) { sprintf( p->pMan->sError, "Line %d: Cannot read flop init value %s.", Io_MvGetLine(p->pMan, pToken), pToken ); return 0; } break; } } if ( Init < 0 || Init > 2 ) { sprintf( p->pMan->sError, "Line %d: Initial state of the flop is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), (char*)Vec_PtrEntry(vTokens,3) ); return 0; } if ( Init == 0 ) Abc_LatchSetInit0( pObj ); else if ( Init == 1 ) Abc_LatchSetInit1( pObj ); else // if ( Init == 2 ) Abc_LatchSetInitDc( pObj ); return 1; } /**Function************************************************************* Synopsis [Parses the subckt line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; Abc_Ntk_t * pModel; Abc_Obj_t * pBox, * pNet, * pTerm; char * pToken, * pName, * pName2, ** ppNames; int nEquals, Last, i, k; // split the line into tokens nEquals = Io_MvCountChars( pLine, '=' ); Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); pToken = (char *)Vec_PtrEntry(vTokens,0); assert( !strcmp(pToken, "subckt") ); //printf( "%d ", nEquals ); // get the model for this box pName = (char *)Vec_PtrEntry(vTokens,1); // skip instance name for now for ( pToken = pName; *pToken; pToken++ ) if ( *pToken == '|' ) { *pToken = 0; break; } // find the model pModel = Abc_DesFindModelByName( p->pMan->pDesign, pName ); if ( pModel == NULL ) { sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName ); return 0; } /* // check if the number of tokens is correct if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ) { sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).", Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ); return 0; } */ // get the names ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv; // create the box with these terminals if ( Abc_NtkHasBlackbox(pModel) ) pBox = Abc_NtkCreateBlackbox( p->pNtk ); else pBox = Abc_NtkCreateWhitebox( p->pNtk ); pBox->pData = pModel; if ( p->pMan->fBlifMv ) Abc_ObjAssignName( pBox, (char *)Vec_PtrEntry(vTokens,2), NULL ); // go through formal inputs Last = 0; Abc_NtkForEachPi( pModel, pTerm, i ) { // find this terminal among the actual inputs of the subcircuit pName2 = NULL; pName = Abc_ObjName(Abc_ObjFanout0(pTerm)); for ( k = 0; k < nEquals; k++ ) if ( !strcmp( ppNames[2*((k+Last)%nEquals)], pName ) ) { pName2 = ppNames[2*((k+Last)%nEquals)+1]; Last = k+Last+1; break; } /* if ( k == nEquals ) { sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.", Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); return 0; } */ if ( pName2 == NULL ) { Abc_Obj_t * pNode = Abc_NtkCreateNode( p->pNtk ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, " 0\n" ); pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNode, "abc") ); Abc_ObjAddFanin( pNet, pNode ); pTerm = Abc_NtkCreateBi( p->pNtk ); Abc_ObjAddFanin( pBox, pTerm ); Abc_ObjAddFanin( pTerm, pNet ); continue; } assert( pName2 != NULL ); // create the BI with the actual name pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName2 ); pTerm = Abc_NtkCreateBi( p->pNtk ); Abc_ObjAddFanin( pBox, pTerm ); Abc_ObjAddFanin( pTerm, pNet ); } // go through formal outputs Last = 0; Abc_NtkForEachPo( pModel, pTerm, i ) { // find this terminal among the actual outputs of the subcircuit pName2 = NULL; pName = Abc_ObjName(Abc_ObjFanin0(pTerm)); for ( k = 0; k < nEquals; k++ ) if ( !strcmp( ppNames[2*((k+Last)%nEquals)], pName ) ) { pName2 = ppNames[2*((k+Last)%nEquals)+1]; Last = k+Last+1; break; } /* if ( k == nEquals ) { sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.", Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); return 0; } */ // create the BI with the actual name pTerm = Abc_NtkCreateBo( p->pNtk ); pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName2 == NULL ? Abc_ObjNameSuffix(pTerm, "abc") : pName2 ); Abc_ObjAddFanin( pNet, pTerm ); Abc_ObjAddFanin( pTerm, pBox ); } return 1; } /**Function************************************************************* Synopsis [Parses the subckt line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Vec_Int_t * Io_MvParseLineOnehot( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; // Vec_Ptr_t * vResult; Vec_Int_t * vResult; Abc_Obj_t * pNet, * pTerm; char * pToken; int nEquals, i; // split the line into tokens nEquals = Io_MvCountChars( pLine, '=' ); Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); pToken = (char *)Vec_PtrEntry(vTokens,0); assert( !strcmp(pToken, "onehot") ); // iterate through the register names // vResult = Vec_PtrAlloc( Vec_PtrSize(vTokens) ); vResult = Vec_IntAlloc( Vec_PtrSize(vTokens) ); Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, 1 ) { // check if this register exists pNet = Abc_NtkFindNet( p->pNtk, pToken ); if ( pNet == NULL ) { sprintf( p->pMan->sError, "Line %d: Signal with name \"%s\" does not exist in the model \"%s\".", Io_MvGetLine(p->pMan, pToken), pToken, Abc_NtkName(p->pNtk) ); return NULL; } // check if this is register output net pTerm = Abc_ObjFanin0( pNet ); if ( pTerm == NULL || Abc_ObjFanin0(pTerm) == NULL || !Abc_ObjIsLatch(Abc_ObjFanin0(pTerm)) ) { sprintf( p->pMan->sError, "Line %d: Signal with name \"%s\" is not a register in the model \"%s\".", Io_MvGetLine(p->pMan, pToken), pToken, Abc_NtkName(p->pNtk) ); return NULL; } // save register name // Vec_PtrPush( vResult, Abc_ObjName(pNet) ); Vec_IntPush( vResult, (int)(ABC_PTRINT_T)Abc_ObjFanin0(pTerm)->pNext ); // printf( "%d(%d) ", (int)Abc_ObjFanin0(pTerm)->pNext, ((int)Abc_ObjFanin0(pTerm)->pData) -1 ); printf( "%d", ((int)(ABC_PTRINT_T)Abc_ObjFanin0(pTerm)->pData)-1 ); } printf( "\n" ); return vResult; } /**Function************************************************************* Synopsis [Parses the mv line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; Abc_Obj_t * pObj; Io_MvVar_t * pVar = NULL; Mem_Flex_t * pFlex; char * pName; int nCommas, nValues, i, k; // count commas and get the tokens nCommas = Io_MvCountChars( pLine, ',' ); Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' ); pName = (char *)Vec_PtrEntry(vTokens,0); assert( !strcmp(pName, "mv") ); // get the number of values if ( Vec_PtrSize(vTokens) <= nCommas + 2 ) { sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName) ); return 0; } nValues = atoi( (char *)Vec_PtrEntry(vTokens,nCommas+2) ); if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES ) { sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).", Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES ); return 0; } // if there is no symbolic values, quit if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 ) return 1; if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues ) { sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).", Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues ); return 0; } // go through variables pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( p->pNtk ); for ( i = 0; i <= nCommas; i++ ) { pName = (char *)Vec_PtrEntry( vTokens, i+1 ); pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName ); // allocate variable pVar = (Io_MvVar_t *)Mem_FlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); pVar->nValues = nValues; pVar->pNames = NULL; // create names if ( Vec_PtrSize(vTokens) > nCommas + 3 ) { pVar->pNames = (char **)Mem_FlexEntryFetch( pFlex, sizeof(char *) * nValues ); Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nCommas + 3 ) { pVar->pNames[k-(nCommas + 3)] = (char *)Mem_FlexEntryFetch( pFlex, strlen(pName) + 1 ); strcpy( pVar->pNames[k-(nCommas + 3)], pName ); } } // save the variable Abc_ObjSetMvVar( pObj, pVar ); } // make sure the names are unique assert(pVar); if ( pVar->pNames ) { for ( i = 0; i < nValues; i++ ) for ( k = i+1; k < nValues; k++ ) if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) ) { pName = (char *)Vec_PtrEntry(vTokens,0); sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.", Io_MvGetLine(p->pMan, pName), pVar->pNames[i] ); return 0; } } return 1; } /**Function************************************************************* Synopsis [Writes the values into the BLIF-MV representation for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc ) { char Buffer[10]; Abc_Obj_t * pFanin; int i; // add the fanin number of values Abc_ObjForEachFanin( pNode, pFanin, i ) { sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) ); Vec_StrPrintStr( vFunc, Buffer ); Vec_StrPush( vFunc, ' ' ); } // add the node number of values sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) ); Vec_StrPrintStr( vFunc, Buffer ); Vec_StrPush( vFunc, '\n' ); return 1; } /**Function************************************************************* Synopsis [Translated one literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit ) { char Buffer[10]; Io_MvVar_t * pVar; Abc_Obj_t * pFanin, * pNet; char * pCur, * pNext; int i; // consider the equality literal if ( pToken[0] == '=' ) { // find the fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) ) break; if ( i == Abc_ObjFaninNum(pNode) ) { sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.", Io_MvGetLine(p->pMan, pToken), pToken + 1 ); return 0; } Vec_StrPush( vFunc, '=' ); sprintf( Buffer, "%d", i ); Vec_StrPrintStr( vFunc, Buffer ); Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); return 1; } // consider regular literal assert( iLit < Abc_ObjFaninNum(pNode) ); pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode); pVar = (Io_MvVar_t *)Abc_ObjMvVar( pNet ); // if the var is absent or has no symbolic values quit if ( pVar == NULL || pVar->pNames == NULL ) { Vec_StrPrintStr( vFunc, pToken ); Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); return 1; } // parse the literal using symbolic values for ( pCur = pToken; *pCur; pCur++ ) { if ( Io_MvCharIsMvSymb(*pCur) ) { Vec_StrPush( vFunc, *pCur ); continue; } // find the next MvSymb char for ( pNext = pCur+1; *pNext; pNext++ ) if ( Io_MvCharIsMvSymb(*pNext) ) break; // look for the value name for ( i = 0; i < pVar->nValues; i++ ) if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) ) break; if ( i == pVar->nValues ) { *pNext = 0; sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".", Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) ); return 0; } // value name is found sprintf( Buffer, "%d", i ); Vec_StrPrintStr( vFunc, Buffer ); // update the pointer pCur = pNext - 1; } Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); return 1; } /**Function************************************************************* Synopsis [Constructs the MV-SOP cover from the file parsing info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut ) { Vec_Str_t * vFunc = p->pMan->vFunc; char * pFirst, * pToken; int iStart, i; // prepare the place for the cover Vec_StrClear( vFunc ); // write the number of values // Io_MvWriteValues( pNode, vFunc ); // get the first token pFirst = (char *)Vec_PtrEntry( vTokens2, 0 ); if ( pFirst[0] == '.' ) { // write the default literal Vec_StrPush( vFunc, 'd' ); pToken = (char *)Vec_PtrEntry(vTokens2, 1 + iOut); if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) return NULL; iStart = 1 + nOutputs; } else iStart = 0; // write the remaining literals while ( iStart < Vec_PtrSize(vTokens2) ) { // input literals for ( i = 0; i < nInputs; i++ ) { pToken = (char *)Vec_PtrEntry( vTokens2, iStart + i ); if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) ) return NULL; } // output literal pToken = (char *)Vec_PtrEntry( vTokens2, iStart + nInputs + iOut ); if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) return NULL; // update the counter iStart += nInputs + nOutputs; } Vec_StrPush( vFunc, '\0' ); return Vec_StrArray( vFunc ); } /**Function************************************************************* Synopsis [Adds reset circuitry corresponding to latch with pName.] Description [Returns the reset node's net.] SideEffects [] SeeAlso [] ***********************************************************************/ static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName ) { char Buffer[50]; Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet; Io_MvVar_t * pVar; // make sure the reset latch exists assert( p->pResetLatch != NULL ); // get the reset net pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch)); // get the output net pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); // get the data nets pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") ); pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") ); // duplicate MV variables if ( Abc_NtkMvVar(p->pNtk) ) { pVar = (Io_MvVar_t *)Abc_ObjMvVar( pOutNet ); Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); } // create the node pNode = Abc_NtkCreateNode( p->pNtk ); // create the output net Abc_ObjAddFanin( pOutNet, pNode ); // create the function if ( p->pMan->fBlifMv ) { // Vec_Att_t * p = Abc_NtkMvVar( pNtk ); // int nValues = Abc_ObjMvVarNum(pOutNet); // sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues ); sprintf( Buffer, "1 - - =1\n0 - - =2\n" ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, Buffer ); } else pNode->pData = Abc_SopCreateMux( (Mem_Flex_t *)p->pNtk->pManFunc ); // add nets Abc_ObjAddFanin( pNode, pResetLONet ); Abc_ObjAddFanin( pNode, pData1Net ); Abc_ObjAddFanin( pNode, pData0Net ); return pData0Net; } /**Function************************************************************* Synopsis [Parses the nodes line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset ) { Abc_Obj_t * pNet, * pNode; char * pName; // get the output name pName = (char *)Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut ); // create the node if ( fReset ) { pNet = Abc_NtkFindNet( p->pNtk, pName ); if ( pNet == NULL ) { sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName ); return 0; } /* if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) ) { sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName ); return 0; } */ // construct the reset circuit and get the reset net feeding into it pNet = Io_MvParseAddResetCircuit( p, pName ); // create fanins pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs ); assert( nInputs == Vec_PtrSize(vTokens) - 2 ); } else { pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); if ( Abc_ObjFaninNum(pNet) > 0 ) { sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); return 0; } pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs ); } // create the cover pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut ); if ( pNode->pData == NULL ) return 0; pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, (char *)pNode->pData ); //printf( "Finished parsing node \"%s\" with table:\n%s\n", pName, pNode->pData ); return 1; } /**Function************************************************************* Synopsis [Parses the nodes line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; Vec_Ptr_t * vTokens2 = p->pMan->vTokens2; Abc_Obj_t * pNet; char * pName, * pFirst, * pArrow; int nInputs, nOutputs, nLiterals, nLines, i; assert( p->pMan->fBlifMv ); // get the arrow if it is present pArrow = Io_MvFindArrow( pLine ); if ( !p->pMan->fBlifMv && pArrow ) { sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) ); return 0; } // split names line into tokens Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); if ( fReset ) assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "r") || !strcmp((char *)Vec_PtrEntry(vTokens,0), "reset") ); else assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "names") || !strcmp((char *)Vec_PtrEntry(vTokens,0), "table") ); // find the number of inputs and outputs nInputs = Vec_PtrSize(vTokens) - 2; nOutputs = 1; if ( pArrow != NULL ) { for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- ) if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) ) { nInputs--; nOutputs++; } } // split table into tokens pName = (char *)Vec_PtrEntryLast( vTokens ); Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) ); pFirst = (char *)Vec_PtrEntry( vTokens2, 0 ); if ( pFirst[0] == '.' ) { assert( pFirst[1] == 'd' ); nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs; } else nLiterals = Vec_PtrSize(vTokens2); // check the number of lines if ( nLiterals % (nInputs + nOutputs) != 0 ) { sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName ); return 0; } // check for the ND table nLines = nLiterals / (nInputs + nOutputs); if ( nInputs == 0 && nLines > 1 ) { // add the outputs to the PIs for ( i = 0; i < nOutputs; i++ ) { pName = (char *)Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i ); // get the net corresponding to this node pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName); if ( fReset ) { assert( p->pResetLatch != NULL ); // construct the reset circuit and get the reset net feeding into it pNet = Io_MvParseAddResetCircuit( p, pName ); } // add the new PI node // Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) ); // fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName ); p->pMan->nNDnodes++; Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) ); } return 1; } // iterate through the outputs for ( i = 0; i < nOutputs; i++ ) { if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Constructs the SOP cover from the file parsing info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; Vec_Str_t * vFunc = p->pMan->vFunc; char * pProduct, * pOutput, c; int i, Polarity = -1; p->pMan->nTablesRead++; // get the tokens Io_MvSplitIntoTokens( vTokens, pTable, '.' ); if ( Vec_PtrSize(vTokens) == 0 ) return Abc_SopCreateConst0( (Mem_Flex_t *)p->pNtk->pManFunc ); if ( Vec_PtrSize(vTokens) == 1 ) { pOutput = (char *)Vec_PtrEntry( vTokens, 0 ); c = pOutput[0]; if ( (c!='0'&&c!='1'&&c!='x'&&c!='n') || pOutput[1] ) { sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput ); return NULL; } return pOutput[0] == '0' ? Abc_SopCreateConst0((Mem_Flex_t *)p->pNtk->pManFunc) : Abc_SopCreateConst1((Mem_Flex_t *)p->pNtk->pManFunc); } pProduct = (char *)Vec_PtrEntry( vTokens, 0 ); if ( Vec_PtrSize(vTokens) % 2 == 1 ) { sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) ); return NULL; } // parse the table Vec_StrClear( vFunc ); for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ ) { pProduct = (char *)Vec_PtrEntry( vTokens, 2*i + 0 ); pOutput = (char *)Vec_PtrEntry( vTokens, 2*i + 1 ); if ( strlen(pProduct) != (unsigned)nFanins ) { sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins ); return NULL; } c = pOutput[0]; if ( (c!='0'&&c!='1'&&c!='x'&&c!='n') || pOutput[1] ) { sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput ); return NULL; } if ( Polarity == -1 ) Polarity = (c=='1' || c=='x'); else if ( Polarity != (c=='1' || c=='x') ) { sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity ); return NULL; } // parse one product Vec_StrPrintStr( vFunc, pProduct ); Vec_StrPush( vFunc, ' ' ); Vec_StrPush( vFunc, pOutput[0] ); Vec_StrPush( vFunc, '\n' ); } Vec_StrPush( vFunc, '\0' ); return Vec_StrArray( vFunc ); } /**Function************************************************************* Synopsis [Parses the nodes line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; Abc_Obj_t * pNet, * pNode; char * pName; assert( !p->pMan->fBlifMv ); Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); // parse the mapped node if ( !strcmp((char *)Vec_PtrEntry(vTokens,0), "gate") ) return Io_MvParseLineGateBlif( p, vTokens ); // parse the regular name line assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "names") ); pName = (char *)Vec_PtrEntryLast( vTokens ); pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); if ( Abc_ObjFaninNum(pNet) > 0 ) { sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); return 0; } // create fanins pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 ); // parse the table of this node pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) ); if ( pNode->pData == NULL ) return 0; pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, (char *)pNode->pData ); return 1; } ABC_NAMESPACE_IMPL_END #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Parses the nodes line.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineShortBlif( Io_MvMod_t * p, char * pLine ) { Vec_Ptr_t * vTokens = p->pMan->vTokens; Abc_Obj_t * pNet, * pNode; char * pName; assert( !p->pMan->fBlifMv ); Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); if ( Vec_PtrSize(vTokens) != 3 ) { sprintf( p->pMan->sError, "Line %d: Expecting three entries in the .short line.", Io_MvGetLine(p->pMan, (char *)Vec_PtrEntry(vTokens,0)) ); return 0; } // parse the regular name line assert( !strcmp((char *)Vec_PtrEntry(vTokens,0), "short") ); pName = (char *)Vec_PtrEntryLast( vTokens ); pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); if ( Abc_ObjFaninNum(pNet) > 0 ) { sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); return 0; } // create fanins pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), 1 ); // parse the table of this node if ( p->pNtk->ntkFunc == ABC_FUNC_MAP ) { Mio_Library_t * pGenlib; Mio_Gate_t * pGate; // check that the library is available pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pGenlib == NULL ) { sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) ); return 0; } // get the gate pGate = Mio_LibraryReadBuf( pGenlib ); if ( pGate == NULL ) { sprintf( p->pMan->sError, "Line %d: Cannot find buffer gate in the library.", Io_MvGetLine(p->pMan, pName) ); return 0; } Abc_ObjSetData( pNode, pGate ); } else pNode->pData = Abc_SopRegister( (Mem_Flex_t *)p->pNtk->pManFunc, "1 1\n" ); return 1; } /**Function************************************************************* Synopsis [Duplicate the MV variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ) { Mem_Flex_t * pFlex; Io_MvVar_t * pVarDup; int i; if ( pVar == NULL ) return NULL; pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( pNtk ); assert( pFlex != NULL ); pVarDup = (Io_MvVar_t *)Mem_FlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); pVarDup->nValues = pVar->nValues; pVarDup->pNames = NULL; if ( pVar->pNames == NULL ) return pVarDup; pVarDup->pNames = (char **)Mem_FlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues ); for ( i = 0; i < pVar->nValues; i++ ) { pVarDup->pNames[i] = (char *)Mem_FlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 ); strcpy( pVarDup->pNames[i], pVar->pNames[i] ); } return pVarDup; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static char * Io_ReadBlifCleanName( char * pName ) { int i, Length; Length = strlen(pName); for ( i = 0; i < Length; i++ ) if ( pName[i] == '=' ) return pName + i + 1; return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ) { extern int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate, Mio_Gate_t * pTwin ); Mio_Library_t * pGenlib; Mio_Gate_t * pGate; Abc_Obj_t * pNode; char ** ppNames, * pName; int i, nNames; pName = (char *)vTokens->pArray[0]; // check that the library is available pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pGenlib == NULL ) { sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) ); return 0; } // create a new node and add it to the network if ( vTokens->nSize < 2 ) { sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) ); return 0; } // get the gate pGate = Mio_LibraryReadGateByName( pGenlib, (char *)vTokens->pArray[1], NULL ); if ( pGate == NULL ) { sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), (char*)vTokens->pArray[1] ); return 0; } // if this is the first line with gate, update the network type if ( Abc_NtkNodeNum(p->pNtk) == 0 ) { assert( p->pNtk->ntkFunc == ABC_FUNC_SOP ); p->pNtk->ntkFunc = ABC_FUNC_MAP; Mem_FlexStop( (Mem_Flex_t *)p->pNtk->pManFunc, 0 ); p->pNtk->pManFunc = pGenlib; } // reorder the formal inputs to be in the same order as in the gate if ( !Io_ReadBlifReorderFormalNames( vTokens, pGate, Mio_GateReadTwin(pGate) ) ) { sprintf( p->pMan->sError, "Line %d: Mismatch in the fanins of gate \"%s\".", Io_MvGetLine(p->pMan, pName), (char*)vTokens->pArray[1] ); return 0; } // remove the formal parameter names for ( i = 2; i < vTokens->nSize; i++ ) { if ( vTokens->pArray[i] == NULL ) continue; vTokens->pArray[i] = Io_ReadBlifCleanName( (char *)vTokens->pArray[i] ); if ( vTokens->pArray[i] == NULL ) { sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) ); return 0; } } // create the node if ( Mio_GateReadTwin(pGate) == NULL ) { nNames = vTokens->nSize - 3; ppNames = (char **)vTokens->pArray + 2; pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames ); Abc_ObjSetData( pNode, pGate ); } else { nNames = vTokens->nSize - 4; ppNames = (char **)vTokens->pArray + 2; assert( ppNames[nNames] != NULL || ppNames[nNames+1] != NULL ); if ( ppNames[nNames] ) { pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames ); Abc_ObjSetData( pNode, pGate ); } if ( ppNames[nNames+1] ) { pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames+1], ppNames, nNames ); Abc_ObjSetData( pNode, Mio_GateReadTwin(pGate) ); } } return 1; } /**Function************************************************************* Synopsis [Box mapping procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_MapBoxSetPrevNext( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id ) { Abc_Obj_t * pNode; pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2); Vec_IntWriteEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))), Id ); pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4); Vec_IntWriteEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))), Id ); } static inline int Abc_MapBox2Next( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id ) { Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+4); return Vec_IntEntry( vMapIn, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); } static inline int Abc_MapBox2Prev( Vec_Ptr_t * vDrivers, Vec_Int_t * vMapIn, Vec_Int_t * vMapOut, int Id ) { Abc_Obj_t * pNode = (Abc_Obj_t *)Vec_PtrEntry(vDrivers, Id+2); return Vec_IntEntry( vMapOut, Abc_ObjId(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadDsd.c000066400000000000000000000204021300674244400233550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedure to read network from file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Finds the end of the part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Io_ReadDsdFindEnd( char * pCur ) { char * pEnd; int nParts = 0; assert( *pCur == '(' ); for ( pEnd = pCur; *pEnd; pEnd++ ) { if ( *pEnd == '(' ) nParts++; else if ( *pEnd == ')' ) nParts--; if ( nParts == 0 ) return pEnd; } return NULL; } /**Function************************************************************* Synopsis [Splits the formula into parts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadDsdStrSplit( char * pCur, char * pParts[], int * pTypeXor ) { int fAnd = 0, fXor = 0, fPri = 0, nParts = 0; assert( *pCur ); // process the parts while ( 1 ) { // save the current part pParts[nParts++] = pCur; // skip the complement if ( *pCur == '!' ) pCur++; // skip var if ( *pCur >= 'a' && *pCur <= 'z' ) pCur++; else { // skip hex truth table while ( (*pCur >= '0' && *pCur <= '9') || (*pCur >= 'A' && *pCur <= 'F') ) pCur++; // process parentheses if ( *pCur != '(' ) { printf( "Cannot find the opening parenthesis.\n" ); break; } // find the corresponding closing parenthesis pCur = Io_ReadDsdFindEnd( pCur ); if ( pCur == NULL ) { printf( "Cannot find the closing parenthesis.\n" ); break; } pCur++; } // check the end if ( *pCur == 0 ) break; // check symbol if ( *pCur != '*' && *pCur != '+' && *pCur != ',' ) { printf( "Wrong separating symbol.\n" ); break; } // remember the symbol fAnd |= (*pCur == '*'); fXor |= (*pCur == '+'); fPri |= (*pCur == ','); *pCur++ = 0; } // check separating symbols if ( fAnd + fXor + fPri > 1 ) { printf( "Different types of separating symbol ennPartsed.\n" ); return 0; } *pTypeXor = fXor; return nParts; } /**Function************************************************************* Synopsis [Recursively parses the formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadDsd_rec( Abc_Ntk_t * pNtk, char * pCur, char * pSop ) { Abc_Obj_t * pObj, * pFanin; char * pEnd, * pParts[32]; int i, nParts, TypeExor; // consider complemented formula if ( *pCur == '!' ) { pObj = Io_ReadDsd_rec( pNtk, pCur + 1, NULL ); return Abc_NtkCreateNodeInv( pNtk, pObj ); } if ( *pCur == '(' ) { assert( pCur[strlen(pCur)-1] == ')' ); pCur[strlen(pCur)-1] = 0; nParts = Io_ReadDsdStrSplit( pCur+1, pParts, &TypeExor ); if ( nParts == 0 ) { Abc_NtkDelete( pNtk ); return NULL; } pObj = Abc_NtkCreateNode( pNtk ); if ( pSop ) { // for ( i = nParts - 1; i >= 0; i-- ) for ( i = 0; i < nParts; i++ ) { pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); if ( pFanin == NULL ) return NULL; Abc_ObjAddFanin( pObj, pFanin ); } } else { for ( i = 0; i < nParts; i++ ) { pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); if ( pFanin == NULL ) return NULL; Abc_ObjAddFanin( pObj, pFanin ); } } if ( pSop ) pObj->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, pSop ); else if ( TypeExor ) pObj->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtk->pManFunc, nParts ); else pObj->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtk->pManFunc, nParts, NULL ); return pObj; } if ( *pCur >= 'a' && *pCur <= 'z' ) { assert( *(pCur+1) == 0 ); return Abc_NtkPi( pNtk, *pCur - 'a' ); } // skip hex truth table pEnd = pCur; while ( (*pEnd >= '0' && *pEnd <= '9') || (*pEnd >= 'A' && *pEnd <= 'F') ) pEnd++; if ( *pEnd != '(' ) { printf( "Cannot find the end of hexidecimal truth table.\n" ); return NULL; } // parse the truth table *pEnd = 0; pSop = Abc_SopFromTruthHex( pCur ); *pEnd = '('; pObj = Io_ReadDsd_rec( pNtk, pEnd, pSop ); ABC_FREE( pSop ); return pObj; } /**Function************************************************************* Synopsis [Derives the DSD network of the formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadDsd( char * pForm ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pObj, * pTop; Vec_Ptr_t * vNames; char * pCur, * pFormCopy; int i, nInputs; // count the number of elementary variables nInputs = 0; for ( pCur = pForm; *pCur; pCur++ ) if ( *pCur >= 'a' && *pCur <= 'z' ) nInputs = Abc_MaxInt( nInputs, *pCur - 'a' ); nInputs++; // create the network pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); pNtk->pName = Extra_UtilStrsav( "dsd" ); // create PIs vNames = Abc_NodeGetFakeNames( nInputs ); for ( i = 0; i < nInputs; i++ ) Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), (char *)Vec_PtrEntry(vNames, i), NULL ); Abc_NodeFreeNames( vNames ); // transform the formula by inserting parentheses // this transforms strings like PRIME(a,b,cd) into (PRIME((a),(b),(cd))) pCur = pFormCopy = ABC_ALLOC( char, 3 * strlen(pForm) + 10 ); *pCur++ = '('; for ( ; *pForm; pForm++ ) if ( *pForm == '(' ) { *pCur++ = '('; *pCur++ = '('; } else if ( *pForm == ')' ) { *pCur++ = ')'; *pCur++ = ')'; } else if ( *pForm == ',' ) { *pCur++ = ')'; *pCur++ = ','; *pCur++ = '('; } else *pCur++ = *pForm; *pCur++ = ')'; *pCur = 0; // parse the formula pObj = Io_ReadDsd_rec( pNtk, pFormCopy, NULL ); ABC_FREE( pFormCopy ); if ( pObj == NULL ) return NULL; // create output pTop = Abc_NtkCreatePo(pNtk); Abc_ObjAssignName( pTop, "F", NULL ); Abc_ObjAddFanin( pTop, pObj ); // create the only PO if ( !Abc_NtkCheck( pNtk ) ) { fprintf( stdout, "Io_ReadDsd(): Network check has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadEdif.c000066400000000000000000000221601300674244400235150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadEdif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedure to read ISCAS benchmarks in EDIF.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadEdif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the network from an EDIF file.] Description [Works only for the ISCAS benchmarks.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ) { Extra_FileReader_t * p; Abc_Ntk_t * pNtk; printf( "Currently this parser does not work!\n" ); return NULL; // start the file p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t()" ); if ( p == NULL ) return NULL; // read the network pNtk = Io_ReadEdifNetwork( p ); Extra_FileReaderFree( p ); if ( pNtk == NULL ) return NULL; // make sure that everything is okay with the network structure if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) { printf( "Io_ReadEdif: The network check has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) { ProgressBar * pProgress; Vec_Ptr_t * vTokens; Abc_Ntk_t * pNtk; Abc_Obj_t * pNet, * pObj, * pFanout; char * pGateName, * pNetName; int fTokensReady, iLine, i; // read the first line vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); if ( strcmp( (char *)vTokens->pArray[0], "edif" ) != 0 ) { printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); return NULL; } // allocate the empty network pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); // go through the lines of the file fTokensReady = 0; pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); for ( iLine = 1; fTokensReady || (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)); iLine++ ) { Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); // get the type of the line fTokensReady = 0; if ( strcmp( (char *)vTokens->pArray[0], "instance" ) == 0 ) { pNetName = (char *)vTokens->pArray[1]; pNet = Abc_NtkFindOrCreateNet( pNtk, pNetName ); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); pGateName = (char *)vTokens->pArray[1]; if ( strncmp( pGateName, "Flip", 4 ) == 0 ) { pObj = Abc_NtkCreateLatch( pNtk ); Abc_LatchSetInit0( pObj ); } else { pObj = Abc_NtkCreateNode( pNtk ); // pObj->pData = Abc_NtkRegisterName( pNtk, pGateName ); pObj->pData = Extra_UtilStrsav( pGateName ); // memory leak!!! } Abc_ObjAddFanin( pNet, pObj ); } else if ( strcmp( (char *)vTokens->pArray[0], "net" ) == 0 ) { pNetName = (char *)vTokens->pArray[1]; if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) continue; if ( strcmp( pNetName + strlen(pNetName) - 4, "_out" ) == 0 ) pNetName[strlen(pNetName) - 4] = 0; pNet = Abc_NtkFindNet( pNtk, pNetName ); assert( pNet ); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); while ( strcmp( (char *)vTokens->pArray[0], "portRef" ) == 0 ) { if ( strcmp( pNetName, (char *)vTokens->pArray[3] ) != 0 ) { pFanout = Abc_NtkFindNet( pNtk, (char *)vTokens->pArray[3] ); Abc_ObjAddFanin( Abc_ObjFanin0(pFanout), pNet ); } vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); } fTokensReady = 1; } else if ( strcmp( (char *)vTokens->pArray[0], "library" ) == 0 ) { vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); while ( strcmp( (char *)vTokens->pArray[0], "port" ) == 0 ) { pNetName = (char *)vTokens->pArray[1]; if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) { vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); continue; } if ( strcmp( pNetName + strlen(pNetName) - 3, "_PO" ) == 0 ) pNetName[strlen(pNetName) - 3] = 0; if ( strcmp( (char *)vTokens->pArray[3], "INPUT" ) == 0 ) Io_ReadCreatePi( pNtk, (char *)vTokens->pArray[1] ); else if ( strcmp( (char *)vTokens->pArray[3], "OUTPUT" ) == 0 ) Io_ReadCreatePo( pNtk, (char *)vTokens->pArray[1] ); else { printf( "%s (line %d): Wrong interface specification.\n", Extra_FileReaderGetFileName(p), iLine ); Abc_NtkDelete( pNtk ); return NULL; } vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p); } } else if ( strcmp( (char *)vTokens->pArray[0], "design" ) == 0 ) { ABC_FREE( pNtk->pName ); pNtk->pName = (char *)Extra_UtilStrsav( (char *)vTokens->pArray[3] ); break; } } Extra_ProgressBarStop( pProgress ); // assign logic functions Abc_NtkForEachNode( pNtk, pObj, i ) { if ( strncmp( (char *)pObj->pData, "And", 3 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateAnd((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); else if ( strncmp( (char *)pObj->pData, "Or", 2 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateOr((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); else if ( strncmp( (char *)pObj->pData, "Nand", 4 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateNand((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); else if ( strncmp( (char *)pObj->pData, "Nor", 3 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateNor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); else if ( strncmp( (char *)pObj->pData, "Exor", 4 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateXor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); else if ( strncmp( (char *)pObj->pData, "Exnor", 5 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateNxor((Mem_Flex_t *)pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); else if ( strncmp( (char *)pObj->pData, "Inv", 3 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateInv((Mem_Flex_t *)pNtk->pManFunc) ); else if ( strncmp( (char *)pObj->pData, "Buf", 3 ) == 0 ) Abc_ObjSetData( pObj, Abc_SopCreateBuf((Mem_Flex_t *)pNtk->pManFunc) ); else { printf( "%s: Unknown gate type \"%s\".\n", Extra_FileReaderGetFileName(p), (char*)pObj->pData ); Abc_NtkDelete( pNtk ); return NULL; } } // check if constants have been added // if ( pNet = Abc_NtkFindNet( pNtk, "VDD" ) ) // Io_ReadCreateConst( pNtk, "VDD", 1 ); // if ( pNet = Abc_NtkFindNet( pNtk, "GND" ) ) // Io_ReadCreateConst( pNtk, "GND", 0 ); Abc_NtkFinalizeRead( pNtk ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadEqn.c000066400000000000000000000170511300674244400233740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadEqn.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read equation format files.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ); static void Io_ReadEqnStrCompact( char * pStr ); static int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ); static void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the network from a BENCH file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ) { Extra_FileReader_t * p; Abc_Ntk_t * pNtk; // start the file p = Extra_FileReaderAlloc( pFileName, "#", ";", "=" ); if ( p == NULL ) return NULL; // read the network pNtk = Io_ReadEqnNetwork( p ); Extra_FileReaderFree( p ); if ( pNtk == NULL ) return NULL; // make sure that everything is okay with the network structure if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) { printf( "Io_ReadEqn: The network check has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) { ProgressBar * pProgress; Vec_Ptr_t * vTokens; Vec_Ptr_t * vVars; Abc_Ntk_t * pNtk; Abc_Obj_t * pNode; char * pNodeName, * pFormula, * pFormulaCopy, * pVarName; int iLine, i; // allocate the empty network pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_AIG, 1 ); // set the specs pNtk->pName = Extra_FileNameGeneric(Extra_FileReaderGetFileName(p)); pNtk->pSpec = Extra_UtilStrsav(Extra_FileReaderGetFileName(p)); // go through the lines of the file vVars = Vec_PtrAlloc( 100 ); pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); for ( iLine = 0; (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)); iLine++ ) { Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); // check if the first token contains anything Io_ReadEqnStrCompact( (char *)vTokens->pArray[0] ); if ( strlen((char *)vTokens->pArray[0]) == 0 ) break; // if the number of tokens is different from two, error if ( vTokens->nSize != 2 ) { printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); Abc_NtkDelete( pNtk ); return NULL; } // get the type of the line if ( strncmp( (char *)vTokens->pArray[0], "INORDER", 7 ) == 0 ) { Io_ReadEqnStrCutAt( (char *)vTokens->pArray[1], " \n\r\t", 0, vVars ); Vec_PtrForEachEntry( char *, vVars, pVarName, i ) Io_ReadCreatePi( pNtk, pVarName ); } else if ( strncmp( (char *)vTokens->pArray[0], "OUTORDER", 8 ) == 0 ) { Io_ReadEqnStrCutAt( (char *)vTokens->pArray[1], " \n\r\t", 0, vVars ); Vec_PtrForEachEntry( char *, vVars, pVarName, i ) Io_ReadCreatePo( pNtk, pVarName ); } else { extern Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ); // get hold of the node name and its formula pNodeName = (char *)vTokens->pArray[0]; pFormula = (char *)vTokens->pArray[1]; // compact the formula Io_ReadEqnStrCompact( pFormula ); // consider the case of the constant node if ( pFormula[1] == 0 && (pFormula[0] == '0' || pFormula[0] == '1') ) { pFormulaCopy = NULL; Vec_PtrClear( vVars ); } else { // make a copy of formula for names pFormulaCopy = Extra_UtilStrsav( pFormula ); // find the names of the fanins of this node Io_ReadEqnStrCutAt( pFormulaCopy, "!*+()", 1, vVars ); } // create the node pNode = Io_ReadCreateNode( pNtk, pNodeName, (char **)Vec_PtrArray(vVars), Vec_PtrSize(vVars) ); // derive the function pNode->pData = Parse_FormulaParserEqn( stdout, pFormula, vVars, (Hop_Man_t *)pNtk->pManFunc ); // remove the cubes ABC_FREE( pFormulaCopy ); } } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vVars ); Abc_NtkFinalizeRead( pNtk ); return pNtk; } /**Function************************************************************* Synopsis [Compacts the string by throwing away space-like chars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadEqnStrCompact( char * pStr ) { char * pCur, * pNew; for ( pNew = pCur = pStr; *pCur; pCur++ ) if ( !(*pCur == ' ' || *pCur == '\n' || *pCur == '\r' || *pCur == '\t') ) *pNew++ = *pCur; *pNew = 0; } /**Function************************************************************* Synopsis [Determines unique variables in the string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ) { char * pToken; int i; Vec_PtrForEachEntry( char *, vTokens, pToken, i ) if ( strcmp( pToken, pName ) == 0 ) return i; return -1; } /**Function************************************************************* Synopsis [Cuts the string into pieces using stop chars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ) { char * pToken; Vec_PtrClear( vTokens ); for ( pToken = strtok( pStr, pStop ); pToken; pToken = strtok( NULL, pStop ) ) if ( !fUniqueOnly || Io_ReadEqnStrFind( vTokens, pToken ) == -1 ) Vec_PtrPush( vTokens, pToken ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadPla.c000066400000000000000000000514571300674244400233750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadPla.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedure to read network from file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadPla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth, int fOnDc, int fSkipPrepro ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if cubes are distance-1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Io_ReadPlaPrintCube( word * p, int nVars ) { char Symbs[3] = {'-', '0', '1'}; int v; for ( v = 0; v < nVars; v++ ) printf( "%c", Symbs[Abc_TtGetQua(p, v)] ); printf( "\n" ); } /**Function************************************************************* Synopsis [Checks if cubes are distance-1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Io_ReadPlaDistance1( word * p, word * q, int nWords ) { word Test; int c, fFound = 0; for ( c = 0; c < nWords; c++ ) { if ( p[c] == q[c] ) continue; if ( fFound ) return 0; // check if the number of 1s is one // Test = ((p[c] ^ q[c]) & ((p[c] ^ q[c]) >> 1)) & ABC_CONST(0x5555555555555555); // exactly one 0/1 literal (but may be -/0 or -/1) Test = ((p[c] ^ q[c]) | ((p[c] ^ q[c]) >> 1)) & ABC_CONST(0x5555555555555555); if ( !Abc_TtOnlyOneOne(Test) ) return 0; fFound = 1; } return fFound; } static inline int Io_ReadPlaConsensus( word * p, word * q, int nWords, int * piVar ) { word Test; int c, fFound = 0; for ( c = 0; c < nWords; c++ ) { if ( p[c] == q[c] ) continue; if ( fFound ) return 0; // check if there is exactly one opposite literal (0/1) but may have other diffs (-/0 or -/1) Test = ((p[c] ^ q[c]) & ((p[c] ^ q[c]) >> 1)) & ABC_CONST(0x5555555555555555); if ( !Abc_TtOnlyOneOne(Test) ) return 0; fFound = 1; *piVar = c * 32 + Abc_Tt6FirstBit(Test)/2; } return fFound; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadPlaMarkIdentical( word ** pCs, int nCubes, int nWords, Vec_Bit_t * vMarks ) { int c1, c2; Vec_BitFill( vMarks, nCubes, 0 ); for ( c1 = 0; c1 < nCubes; c1++ ) if ( !Vec_BitEntry(vMarks, c1) ) for ( c2 = c1 + 1; c2 < nCubes; c2++ ) if ( !Vec_BitEntry(vMarks, c2) ) if ( Abc_TtEqual(pCs[c1], pCs[c2], nWords) ) Vec_BitWriteEntry( vMarks, c2, 1 ); } void Io_ReadPlaMarkContained( word ** pCs, int nCubes, int nWords, Vec_Bit_t * vMarks ) { int c1, c2; Vec_BitFill( vMarks, nCubes, 0 ); for ( c1 = 0; c1 < nCubes; c1++ ) if ( !Vec_BitEntry(vMarks, c1) ) for ( c2 = c1 + 1; c2 < nCubes; c2++ ) if ( !Vec_BitEntry(vMarks, c2) ) { if ( Abc_TtImply(pCs[c1], pCs[c2], nWords) ) Vec_BitWriteEntry( vMarks, c2, 1 ); else if ( Abc_TtImply(pCs[c2], pCs[c1], nWords) ) { Vec_BitWriteEntry( vMarks, c1, 1 ); break; } } } int Io_ReadPlaRemoveMarked( word ** pCs, int nCubes, int nWords, Vec_Bit_t * vMarks ) { int c1, c; for ( c1 = c = 0; c1 < nCubes; c1++ ) if ( !Vec_BitEntry(vMarks, c1) ) { if ( c == c1 ) c++; else Abc_TtCopy( pCs[c++], pCs[c1], nWords, 0 ); } return c; } int Io_ReadPlaMergeDistance1( word ** pCs, int nCubes, int nWords, Vec_Bit_t * vMarks ) { int c1, c2, Res, Counter = 0; Vec_BitFill( vMarks, nCubes, 0 ); for ( c1 = 0; c1 < nCubes; c1++ ) if ( !Vec_BitEntry(vMarks, c1) ) for ( c2 = c1 + 1; c2 < nCubes; c2++ ) if ( !Vec_BitEntry(vMarks, c2) ) { Res = Io_ReadPlaDistance1( pCs[c1], pCs[c2], nWords ); if ( !Res ) continue; Abc_TtAnd( pCs[c1], pCs[c1], pCs[c2], nWords, 0 ); Vec_BitWriteEntry( vMarks, c2, 1 ); Counter++; break; } return Counter; } int Io_ReadPlaSelfSubsumption( word ** pCs, int nCubes, int nWords, Vec_Bit_t * vMarks ) { int c1, c2, Res, Counter = 0, iVar = -1, Val0, Val1; Vec_BitFill( vMarks, nCubes, 0 ); for ( c1 = 0; c1 < nCubes; c1++ ) if ( !Vec_BitEntry(vMarks, c1) ) for ( c2 = c1 + 1; c2 < nCubes; c2++ ) if ( !Vec_BitEntry(vMarks, c2) ) { Res = Io_ReadPlaConsensus( pCs[c1], pCs[c2], nWords, &iVar ); if ( !Res ) continue; assert( iVar >= 0 && iVar < nWords*32 ); Val0 = Abc_TtGetQua( pCs[c1], iVar ); Val1 = Abc_TtGetQua( pCs[c2], iVar ); // remove values Abc_TtXorQua( pCs[c1], iVar, Val0 ); Abc_TtXorQua( pCs[c2], iVar, Val1 ); // check containment if ( Abc_TtImply(pCs[c1], pCs[c2], nWords) ) { Abc_TtXorQua( pCs[c1], iVar, Val0 ); Vec_BitWriteEntry( vMarks, c2, 1 ); Counter++; } else if ( Abc_TtImply(pCs[c2], pCs[c1], nWords) ) { Abc_TtXorQua( pCs[c2], iVar, Val1 ); Vec_BitWriteEntry( vMarks, c1, 1 ); Counter++; break; } else { Abc_TtXorQua( pCs[c1], iVar, Val0 ); Abc_TtXorQua( pCs[c2], iVar, Val1 ); } /* printf( "Var = %3d ", iVar ); printf( "Cube0 = %d ", Abc_TtGetQua(pCs[c1], iVar) ); printf( "Cube1 = %d ", Abc_TtGetQua(pCs[c2], iVar) ); printf( "\n" ); Io_ReadPlaPrintCube( pCs[c1], 32 * nWords ); Io_ReadPlaPrintCube( pCs[c2], 32 * nWords ); printf( "\n" ); */ break; } return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word ** Io_ReadPlaCubeSetup( Vec_Str_t * vSop ) { char * pSop = Vec_StrArray( vSop ), * pCube, Lit; int nCubes = Abc_SopGetCubeNum( pSop ); int nVars = Abc_SopGetVarNum( pSop ); int nWords = Abc_Bit6WordNum( 2*nVars ), c, v; word ** pCs = ABC_ALLOC( word *, nCubes ); pCs[0] = ABC_CALLOC( word, nCubes * nWords ); for ( c = 1; c < nCubes; c++ ) pCs[c] = pCs[c-1] + nWords; c = 0; Abc_SopForEachCube( pSop, nVars, pCube ) { Abc_CubeForEachVar( pCube, Lit, v ) if ( Lit == '0' ) Abc_TtSetBit( pCs[c], Abc_Var2Lit(v,0) ); else if ( Lit == '1' ) Abc_TtSetBit( pCs[c], Abc_Var2Lit(v,1) ); c++; } assert( c == nCubes ); return pCs; } void Io_ReadPlaCubeSetdown( Vec_Str_t * vSop, word ** pCs, int nCubes, int nVars ) { char Symbs[3] = {'-', '0', '1'}; int c, v; Vec_StrClear( vSop ); for ( c = 0; c < nCubes; c++ ) { for ( v = 0; v < nVars; v++ ) Vec_StrPush( vSop, Symbs[Abc_TtGetQua(pCs[c], v)] ); Vec_StrPrintStr( vSop, " 1\n" ); } Vec_StrPush( vSop, 0 ); } void Io_ReadPlaCubePreprocess( Vec_Str_t * vSop, int iCover, int fVerbose ) { word ** pCs = Io_ReadPlaCubeSetup( vSop ); int nCubes = Abc_SopGetCubeNum( Vec_StrArray(vSop) ); int nVars = Abc_SopGetVarNum( Vec_StrArray(vSop) ); int nWords = Abc_Bit6WordNum( 2*nVars ); int nCubesNew, Count, Iter = 0; Vec_Bit_t * vMarks = Vec_BitStart( nCubes ); if ( fVerbose ) printf( "Cover %5d : V =%5d C%d =%5d", iCover, nVars, Iter, nCubes ); do { Iter++; do { // remove contained Io_ReadPlaMarkContained( pCs, nCubes, nWords, vMarks ); nCubesNew = Io_ReadPlaRemoveMarked( pCs, nCubes, nWords, vMarks ); //if ( fVerbose ) // printf( " C =%5d", nCubes - nCubesNew ); nCubes = nCubesNew; // merge distance-1 Count = Io_ReadPlaMergeDistance1( pCs, nCubes, nWords, vMarks ); } while ( Count ); if ( fVerbose ) printf( " C%d =%5d", Iter, nCubes ); // try consensus //Count = Io_ReadPlaSelfSubsumption( pCs, nCubes, nWords, vMarks ); if ( fVerbose ) printf( "%4d", Count ); } while ( Count ); // translate Io_ReadPlaCubeSetdown( vSop, pCs, nCubes, nVars ); // finalize if ( fVerbose ) printf( "\n" ); Vec_BitFree( vMarks ); ABC_FREE( pCs[0] ); ABC_FREE( pCs ); } /**Function************************************************************* Synopsis [Reads the network from a PLA file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fBoth, int fOnDc, int fSkipPrepro, int fCheck ) { Extra_FileReader_t * p; Abc_Ntk_t * pNtk; // start the file p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t|" ); // p = Extra_FileReaderAlloc( pFileName, "", "\n\r", " \t|" ); if ( p == NULL ) return NULL; // read the network pNtk = Io_ReadPlaNetwork( p, fZeros, fBoth, fOnDc, fSkipPrepro ); Extra_FileReaderFree( p ); if ( pNtk == NULL ) return NULL; // make sure that everything is okay with the network structure if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) { printf( "Io_ReadPla: The network check has failed.\n" ); Abc_NtkDelete( pNtk ); return NULL; } return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth, int fOnDc, int fSkipPrepro ) { ProgressBar * pProgress; Vec_Ptr_t * vTokens; Abc_Ntk_t * pNtk; Abc_Obj_t * pTermPi, * pTermPo, * pNode; Vec_Str_t ** ppSops = NULL; char Buffer[100]; int nInputs = -1, nOutputs = -1, nProducts = -1; char * pCubeIn, * pCubeOut; int i, k, iLine, nDigits, nCubes; // allocate the empty network pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); // go through the lines of the file nCubes = 0; pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); while ( (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p)) ) { Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); iLine = Extra_FileReaderGetLineNumber( p, 0 ); // if it is the end of file, quit the loop if ( strncmp( (char *)vTokens->pArray[0], ".e", 2 ) == 0 ) break; // if it is type directive, ignore it for now if ( strncmp( (char *)vTokens->pArray[0], ".type", 5 ) == 0 ) continue; // if it is the model name, get the name if ( strcmp( (char *)vTokens->pArray[0], ".model" ) == 0 ) { ABC_FREE( pNtk->pName ); pNtk->pName = Extra_UtilStrsav( (char *)vTokens->pArray[1] ); continue; } if ( vTokens->nSize == 1 ) { printf( "%s (line %d): Wrong number of token.\n", Extra_FileReaderGetFileName(p), iLine ); Abc_NtkDelete( pNtk ); Extra_ProgressBarStop( pProgress ); ABC_FREE( ppSops ); return NULL; } if ( strcmp( (char *)vTokens->pArray[0], ".i" ) == 0 ) nInputs = atoi((char *)vTokens->pArray[1]); else if ( strcmp( (char *)vTokens->pArray[0], ".o" ) == 0 ) nOutputs = atoi((char *)vTokens->pArray[1]); else if ( strcmp( (char *)vTokens->pArray[0], ".p" ) == 0 ) nProducts = atoi((char *)vTokens->pArray[1]); else if ( strcmp( (char *)vTokens->pArray[0], ".ilb" ) == 0 ) { if ( vTokens->nSize - 1 != nInputs ) printf( "Warning: Mismatch between the number of PIs on the .i line (%d) and the number of PIs on the .ilb line (%d).\n", nInputs, vTokens->nSize - 1 ); for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePi( pNtk, (char *)vTokens->pArray[i] ); } else if ( strcmp( (char *)vTokens->pArray[0], ".ob" ) == 0 ) { if ( vTokens->nSize - 1 != nOutputs ) printf( "Warning: Mismatch between the number of POs on the .o line (%d) and the number of POs on the .ob line (%d).\n", nOutputs, vTokens->nSize - 1 ); for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePo( pNtk, (char *)vTokens->pArray[i] ); } else { // check if the input/output names are given if ( Abc_NtkPiNum(pNtk) == 0 ) { if ( nInputs == -1 ) { printf( "%s: The number of inputs is not specified.\n", Extra_FileReaderGetFileName(p) ); Abc_NtkDelete( pNtk ); Extra_ProgressBarStop( pProgress ); ABC_FREE( ppSops ); return NULL; } nDigits = Abc_Base10Log( nInputs ); for ( i = 0; i < nInputs; i++ ) { sprintf( Buffer, "x%0*d", nDigits, i ); Io_ReadCreatePi( pNtk, Buffer ); } } if ( Abc_NtkPoNum(pNtk) == 0 ) { if ( nOutputs == -1 ) { printf( "%s: The number of outputs is not specified.\n", Extra_FileReaderGetFileName(p) ); Abc_NtkDelete( pNtk ); Extra_ProgressBarStop( pProgress ); ABC_FREE( ppSops ); return NULL; } nDigits = Abc_Base10Log( nOutputs ); for ( i = 0; i < nOutputs; i++ ) { sprintf( Buffer, "z%0*d", nDigits, i ); Io_ReadCreatePo( pNtk, Buffer ); } } if ( Abc_NtkNodeNum(pNtk) == 0 ) { // first time here // create the PO drivers and add them // start the SOP covers ppSops = ABC_ALLOC( Vec_Str_t *, nOutputs ); Abc_NtkForEachPo( pNtk, pTermPo, i ) { ppSops[i] = Vec_StrAlloc( 100 ); // create the node pNode = Abc_NtkCreateNode(pNtk); // connect the node to the PO net Abc_ObjAddFanin( Abc_ObjFanin0Ntk(pTermPo), pNode ); // connect the node to the PI nets Abc_NtkForEachPi( pNtk, pTermPi, k ) Abc_ObjAddFanin( pNode, Abc_ObjFanout0Ntk(pTermPi) ); } } // read the cubes if ( vTokens->nSize != 2 ) { printf( "%s (line %d): Input and output cubes are not specified.\n", Extra_FileReaderGetFileName(p), iLine ); Abc_NtkDelete( pNtk ); Extra_ProgressBarStop( pProgress ); ABC_FREE( ppSops ); return NULL; } pCubeIn = (char *)vTokens->pArray[0]; pCubeOut = (char *)vTokens->pArray[1]; if ( (int)strlen(pCubeIn) != nInputs ) { printf( "%s (line %d): Input cube length (%d) differs from the number of inputs (%d).\n", Extra_FileReaderGetFileName(p), iLine, (int)strlen(pCubeIn), nInputs ); Abc_NtkDelete( pNtk ); return NULL; } if ( (int)strlen(pCubeOut) != nOutputs ) { printf( "%s (line %d): Output cube length (%d) differs from the number of outputs (%d).\n", Extra_FileReaderGetFileName(p), iLine, (int)strlen(pCubeOut), nOutputs ); Abc_NtkDelete( pNtk ); Extra_ProgressBarStop( pProgress ); ABC_FREE( ppSops ); return NULL; } if ( fZeros ) { for ( i = 0; i < nOutputs; i++ ) { if ( pCubeOut[i] == '0' ) { Vec_StrPrintStr( ppSops[i], pCubeIn ); Vec_StrPrintStr( ppSops[i], " 1\n" ); } } } else if ( fBoth ) { for ( i = 0; i < nOutputs; i++ ) { if ( pCubeOut[i] == '0' || pCubeOut[i] == '1' ) { Vec_StrPrintStr( ppSops[i], pCubeIn ); Vec_StrPrintStr( ppSops[i], " 1\n" ); } } } else if ( fOnDc ) { for ( i = 0; i < nOutputs; i++ ) { if ( pCubeOut[i] == '-' || pCubeOut[i] == '1' ) { Vec_StrPrintStr( ppSops[i], pCubeIn ); Vec_StrPrintStr( ppSops[i], " 1\n" ); } } } else { for ( i = 0; i < nOutputs; i++ ) { if ( pCubeOut[i] == '1' ) { Vec_StrPrintStr( ppSops[i], pCubeIn ); Vec_StrPrintStr( ppSops[i], " 1\n" ); } } } nCubes++; } } Extra_ProgressBarStop( pProgress ); if ( nProducts != -1 && nCubes != nProducts ) printf( "Warning: Mismatch between the number of cubes (%d) and the number on .p line (%d).\n", nCubes, nProducts ); // add the SOP covers Abc_NtkForEachPo( pNtk, pTermPo, i ) { pNode = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pTermPo) ); if ( ppSops[i]->nSize == 0 ) { Abc_ObjRemoveFanins(pNode); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ); Vec_StrFree( ppSops[i] ); continue; } Vec_StrPush( ppSops[i], 0 ); if ( !fSkipPrepro ) Io_ReadPlaCubePreprocess( ppSops[i], i, 0 ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, ppSops[i]->pArray ); Vec_StrFree( ppSops[i] ); } ABC_FREE( ppSops ); Abc_NtkFinalizeRead( pNtk ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadPlaMo.c000066400000000000000000000672541300674244400236730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadPlaMo.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedure to read network from file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadPlaMo.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Mop_Man_t_ Mop_Man_t; struct Mop_Man_t_ { int nIns; int nOuts; int nWordsIn; int nWordsOut; Vec_Wrd_t * vWordsIn; Vec_Wrd_t * vWordsOut; Vec_Int_t * vCubes; Vec_Int_t * vFree; }; static inline int Mop_ManIsSopSymb( char c ) { return c == '0' || c == '1' || c == '-'; } static inline int Mop_ManIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; } static inline word * Mop_ManCubeIn( Mop_Man_t * p, int i ) { return Vec_WrdEntryP(p->vWordsIn, p->nWordsIn * i); } static inline word * Mop_ManCubeOut( Mop_Man_t * p, int i ) { return Vec_WrdEntryP(p->vWordsOut, p->nWordsOut * i); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mop_Man_t * Mop_ManAlloc( int nIns, int nOuts, int nCubes ) { Mop_Man_t * p = ABC_CALLOC( Mop_Man_t, 1 ); p->nIns = nIns; p->nOuts = nOuts; p->nWordsIn = Abc_Bit6WordNum( 2 * nIns ); p->nWordsOut = Abc_Bit6WordNum( nOuts ); p->vWordsIn = Vec_WrdStart( 2 * p->nWordsIn * nCubes ); p->vWordsOut = Vec_WrdStart( 2 * p->nWordsOut * nCubes ); p->vCubes = Vec_IntAlloc( 2 * nCubes ); p->vFree = Vec_IntAlloc( 2 * nCubes ); return p; } void Mop_ManStop( Mop_Man_t * p ) { Vec_WrdFree( p->vWordsIn ); Vec_WrdFree( p->vWordsOut ); Vec_IntFree( p->vCubes ); Vec_IntFree( p->vFree ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Reads the file into a character buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mop_ManLoadFile( char * pFileName ) { FILE * pFile; int nFileSize, RetValue; char * pContents; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { Abc_Print( -1, "Mop_ManLoadFile(): The file is unavailable (absent or open).\n" ); return NULL; } fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); if ( nFileSize == 0 ) { Abc_Print( -1, "Mop_ManLoadFile(): The file is empty.\n" ); return NULL; } pContents = ABC_ALLOC( char, nFileSize + 10 ); rewind( pFile ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); strcpy( pContents + nFileSize, "\n" ); return pContents; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mop_ManReadParams( char * pBuffer, int * pnIns, int * pnOuts ) { char * pIns = strstr( pBuffer, ".i " ); char * pOuts = strstr( pBuffer, ".o " ); char * pStr = pBuffer; int nCubes = 0; if ( pIns == NULL || pOuts == NULL ) return -1; *pnIns = atoi( pIns + 2 ); *pnOuts = atoi( pOuts + 2 ); while ( *pStr ) nCubes += (*pStr++ == '\n'); return nCubes; } Mop_Man_t * Mop_ManRead( char * pFileName ) { Mop_Man_t * p; int nIns, nOuts, nCubes, iCube; char * pToken, * pBuffer = Mop_ManLoadFile( pFileName ); if ( pBuffer == NULL ) return NULL; nCubes = Mop_ManReadParams( pBuffer, &nIns, &nOuts ); if ( nCubes == -1 ) return NULL; p = Mop_ManAlloc( nIns, nOuts, nCubes ); // get the first cube pToken = strtok( pBuffer, "\n" ); while ( pToken ) { while ( Mop_ManIsSpace(*pToken) ) pToken++; if ( Mop_ManIsSopSymb(*pToken) ) break; pToken = strtok( NULL, "\n" ); } // read cubes for ( iCube = 0; pToken && Mop_ManIsSopSymb(*pToken); iCube++ ) { char * pTokenCopy = pToken; int i, o, nVars[2] = {nIns, nOuts}; word * pCube[2] = { Mop_ManCubeIn(p, iCube), Mop_ManCubeOut(p, iCube) }; for ( o = 0; o < 2; o++ ) { while ( Mop_ManIsSpace(*pToken) ) pToken++; for ( i = 0; i < nVars[o]; i++, pToken++ ) { if ( !Mop_ManIsSopSymb(*pToken) ) { printf( "Cannot read cube %d (%s).\n", iCube+1, pTokenCopy ); ABC_FREE( pBuffer ); Mop_ManStop( p ); return NULL; } if ( o == 1 ) { if ( *pToken == '1' ) Abc_TtSetBit( pCube[o], i ); } else if ( *pToken == '0' ) Abc_TtSetBit( pCube[o], 2*i ); else if ( *pToken == '1' ) Abc_TtSetBit( pCube[o], 2*i+1 ); } } assert( iCube < nCubes ); Vec_IntPush( p->vCubes, iCube ); pToken = strtok( NULL, "\n" ); } for ( ; iCube < 2 * nCubes; iCube++ ) Vec_IntPush( p->vFree, iCube ); ABC_FREE( pBuffer ); return p; } void Mop_ManPrintOne( Mop_Man_t * p, int iCube ) { int k; char Symb[4] = { '-', '0', '1', '?' }; word * pCubeIn = Mop_ManCubeIn( p, iCube ); word * pCubeOut = Mop_ManCubeOut( p, iCube ); for ( k = 0; k < p->nIns; k++ ) printf( "%c", Symb[Abc_TtGetQua(pCubeIn, k)] ); printf( " " ); for ( k = 0; k < p->nOuts; k++ ) printf( "%d", Abc_TtGetBit(pCubeOut, k) ); printf( "\n" ); } void Mop_ManPrint( Mop_Man_t * p ) { int i, iCube; printf( ".%d\n", p->nIns ); printf( ".%d\n", p->nOuts ); Vec_IntForEachEntry( p->vCubes, iCube, i ) Mop_ManPrintOne( p, iCube ); printf( ".e\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mop_ManCountOnes( word * pCube, int nWords ) { int w, Count = 0; for ( w = 0; w < nWords; w++ ) Count += Abc_TtCountOnes( pCube[w] ); return Count; } static inline int Mop_ManCountOutputLits( Mop_Man_t * p ) { int i, iCube, nOutLits = 0; Vec_IntForEachEntry( p->vCubes, iCube, i ) nOutLits += Mop_ManCountOnes( Mop_ManCubeOut(p, iCube), p->nWordsOut ); return nOutLits; } static inline Vec_Wec_t * Mop_ManCreateGroups( Mop_Man_t * p ) { int i, iCube; Vec_Wec_t * vGroups = Vec_WecStart( p->nIns ); Vec_IntForEachEntry( p->vCubes, iCube, i ) Vec_WecPush( vGroups, Mop_ManCountOnes(Mop_ManCubeIn(p, iCube), p->nWordsIn), iCube ); return vGroups; } static inline int Mop_ManUnCreateGroups( Mop_Man_t * p, Vec_Wec_t * vGroups ) { int i, c1, iCube1; int nBefore = Vec_IntSize(p->vCubes); Vec_Int_t * vGroup; Vec_IntClear( p->vCubes ); Vec_WecForEachLevel( vGroups, vGroup, i ) Vec_IntForEachEntry( vGroup, iCube1, c1 ) if ( iCube1 != -1 ) Vec_IntPush( p->vCubes, iCube1 ); return nBefore - Vec_IntSize(p->vCubes); } static inline int Mop_ManCheckContain( word * pBig, word * pSmall, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( pSmall[w] != (pSmall[w] & pBig[w]) ) return 0; return 1; } static inline void Mop_ManRemoveEmpty( Mop_Man_t * p ) { int w, i, k = 0, iCube; Vec_IntForEachEntry( p->vCubes, iCube, i ) { word * pCube = Mop_ManCubeOut( p, iCube ); for ( w = 0; w < p->nWordsOut; w++ ) if ( pCube[w] ) break; if ( w < p->nWordsOut ) Vec_IntWriteEntry( p->vCubes, k++, iCube ); } Vec_IntShrink( p->vCubes, k ); } /**Function************************************************************* Synopsis [Count how many times each variable appears in the input parts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mop_ManCollectStats( Mop_Man_t * p ) { int i, v, iCube, nVars = 32 * p->nWordsIn; Vec_Int_t * vStats = Vec_IntStart( nVars ); Vec_IntForEachEntry( p->vCubes, iCube, i ) { word * pCube = Mop_ManCubeIn(p, iCube); int nOutLits = Mop_ManCountOnes( Mop_ManCubeOut(p, iCube), p->nWordsOut ); for ( v = 0; v < nVars; v++ ) if ( Abc_TtGetQua(pCube, v) ) Vec_IntAddToEntry( vStats, v, nOutLits ); } return vStats; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // knowing that cubes are distance-1, find the different input variable static inline int Mop_ManFindDiffVar( word * pCube1, word * pCube2, int nWords ) { int w, i; for ( w = 0; w < nWords; w++ ) { word Xor = pCube1[w] ^ pCube2[w]; for ( i = 0; i < 32; i++ ) if ( (Xor >> (i << 1)) & 0x3 ) return w * 32 + i; } assert( 0 ); return -1; } // check containment of input parts of two cubes static inline int Mop_ManCheckDist1( word * pCube1, word * pCube2, int nWords ) { int w, fFound1 = 0; for ( w = 0; w < nWords; w++ ) { word Xor = pCube1[w] ^ pCube2[w]; if ( Xor == 0 ) // equal continue; if ( (Xor ^ (Xor >> 1)) & ABC_CONST(0x5555555555555555) ) // not pairs return 0; Xor &= (Xor >> 1) & ABC_CONST(0x5555555555555555); if ( Xor == 0 ) // not equal and not distance-1 return 0; if ( fFound1 ) // distance-2 or more return 0; if ( (Xor & (Xor-1)) ) // distance-2 or more return 0; fFound1 = 1; // distance 1 so far } return fFound1; } // compresses cubes in the group static inline void Map_ManGroupCompact( Vec_Int_t * vGroup ) { int i, Entry, k = 0; Vec_IntForEachEntry( vGroup, Entry, i ) if ( Entry != -1 ) Vec_IntWriteEntry( vGroup, k++, Entry ); Vec_IntShrink( vGroup, k ); } // takes cubes with identical literal count and removes duplicates int Mop_ManRemoveIdentical( Mop_Man_t * p, Vec_Int_t * vGroup ) { int w, c1, c2, iCube1, iCube2, nEqual = 0; Vec_IntForEachEntry( vGroup, iCube1, c1 ) if ( iCube1 != -1 ) { word * pCube1Out, * pCube1 = Mop_ManCubeIn( p, iCube1 ); Vec_IntForEachEntryStart( vGroup, iCube2, c2, c1+1 ) if ( iCube2 != -1 ) { word * pCube2Out, * pCube2 = Mop_ManCubeIn( p, iCube2 ); if ( memcmp(pCube1, pCube2, sizeof(word)*p->nWordsIn) ) continue; // merge cubes pCube1Out = Mop_ManCubeOut( p, iCube1 ); pCube2Out = Mop_ManCubeOut( p, iCube2 ); for ( w = 0; w < p->nWordsOut; w++ ) pCube1Out[w] |= pCube2Out[w]; Vec_IntWriteEntry( vGroup, c2, -1 ); Vec_IntPush( p->vFree, iCube2 ); nEqual++; } } if ( nEqual ) Map_ManGroupCompact( vGroup ); return nEqual; } // reduces the set of pairs Vec_Int_t * Mop_ManCompatiblePairs( Vec_Int_t * vPairs, int nObjs ) { int i, Entry, Entry2; Vec_Int_t * vCounts = Vec_IntStart( nObjs ); Vec_Int_t * vPairsNew = Vec_IntAlloc( Vec_IntSize(vPairs) ); Vec_IntForEachEntry( vPairs, Entry, i ) Vec_IntAddToEntry( vCounts, Entry, 1 ); // include pairs which have those that appear only once Vec_IntForEachEntryDouble( vPairs, Entry, Entry2, i ) if ( Vec_IntEntry(vCounts, Entry) == 1 || Vec_IntEntry(vCounts, Entry2) == 1 ) { if ( Vec_IntEntry(vCounts, Entry) == 1 ) Vec_IntPushTwo( vPairsNew, Entry, Entry2 ); else Vec_IntPushTwo( vPairsNew, Entry2, Entry ); Vec_IntWriteEntry( vCounts, Entry, -1 ); Vec_IntWriteEntry( vCounts, Entry2, -1 ); } // add those remaining pairs that are both present Vec_IntForEachEntryDouble( vPairs, Entry, Entry2, i ) if ( Vec_IntEntry(vCounts, Entry) > 0 && Vec_IntEntry(vCounts, Entry2) > 0 ) { Vec_IntPushTwo( vPairsNew, Entry, Entry2 ); Vec_IntWriteEntry( vCounts, Entry, -1 ); Vec_IntWriteEntry( vCounts, Entry2, -1 ); } // add remaining pairs Vec_IntForEachEntryDouble( vPairs, Entry, Entry2, i ) if ( Vec_IntEntry(vCounts, Entry) > 0 || Vec_IntEntry(vCounts, Entry2) > 0 ) { if ( Vec_IntEntry(vCounts, Entry) > 0 ) Vec_IntPushTwo( vPairsNew, Entry, Entry2 ); else Vec_IntPushTwo( vPairsNew, Entry2, Entry ); Vec_IntWriteEntry( vCounts, Entry, -1 ); Vec_IntWriteEntry( vCounts, Entry2, -1 ); } Vec_IntFree( vCounts ); // verify the result if ( 0 ) { Vec_Int_t * vTemp1 = Vec_IntDup( vPairs ); Vec_Int_t * vTemp2 = Vec_IntDup( vPairsNew ); Vec_IntUniqify( vTemp1 ); Vec_IntUniqify( vTemp2 ); assert( Vec_IntEqual( vTemp1, vTemp2 ) ); Vec_IntFree( vTemp1 ); Vec_IntFree( vTemp2 ); } return vPairsNew; } // detects pairs of distance-1 cubes with identical outputs Vec_Int_t * Mop_ManFindDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup ) { int c1, c2, iCube1, iCube2; Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vGroup, iCube1, c1 ) { word * pCube1Out, * pCube1 = Mop_ManCubeIn( p, iCube1 ); Vec_IntForEachEntryStart( vGroup, iCube2, c2, c1+1 ) { word * pCube2Out, * pCube2 = Mop_ManCubeIn( p, iCube2 ); if ( !Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ) continue; pCube1Out = Mop_ManCubeOut( p, iCube1 ); pCube2Out = Mop_ManCubeOut( p, iCube2 ); if ( !memcmp(pCube1Out, pCube2Out, sizeof(word)*p->nWordsOut) ) Vec_IntPushTwo( vPairs, c1, c2 ); } } return vPairs; } // merge distance-1 with identical output part int Mop_ManMergeDist1Pairs( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev, Vec_Int_t * vStats, int nLimit ) { Vec_Int_t * vPairs = Mop_ManFindDist1Pairs( p, vGroup ); Vec_Int_t * vPairsNew = Mop_ManCompatiblePairs( vPairs, Vec_IntSize(vGroup) ); int nCubes = Vec_IntSize(vGroup) + Vec_IntSize(vGroupPrev); int w, i, c1, c2, iCubeNew, iVar; // move cubes to the previous group word * pCube, * pCube1, * pCube2; Vec_Int_t * vToFree = Vec_IntAlloc( Vec_IntSize(vPairsNew) ); Vec_IntForEachEntryDouble( vPairsNew, c1, c2, i ) { pCube1 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c1) ); pCube2 = Mop_ManCubeIn( p, Vec_IntEntry(vGroup, c2) ); assert( Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ); // skip those cubes that have frequently appearing variables iVar = Mop_ManFindDiffVar( pCube1, pCube2, p->nWordsIn ); if ( Vec_IntEntry( vStats, iVar ) > nLimit ) continue; Vec_IntPush( vToFree, c1 ); Vec_IntPush( vToFree, c2 ); iCubeNew = Vec_IntPop( p->vFree ); pCube = Mop_ManCubeIn( p, iCubeNew ); for ( w = 0; w < p->nWordsIn; w++ ) pCube[w] = pCube1[w] & pCube2[w]; pCube = Mop_ManCubeOut( p, iCubeNew ); pCube1 = Mop_ManCubeOut( p, Vec_IntEntry(vGroup, c1) ); pCube2 = Mop_ManCubeOut( p, Vec_IntEntry(vGroup, c2) ); assert( !memcmp(pCube1, pCube2, sizeof(word)*p->nWordsOut) ); for ( w = 0; w < p->nWordsOut; w++ ) pCube[w] = pCube1[w]; Vec_IntPush( vGroupPrev, iCubeNew ); } // Vec_IntForEachEntry( vPairsNew, c1, i ) Vec_IntForEachEntry( vToFree, c1, i ) { if ( Vec_IntEntry(vGroup, c1) == -1 ) continue; Vec_IntPush( p->vFree, Vec_IntEntry(vGroup, c1) ); Vec_IntWriteEntry( vGroup, c1, -1 ); } Vec_IntFree( vToFree ); if ( Vec_IntSize(vPairsNew) > 0 ) Map_ManGroupCompact( vGroup ); Vec_IntFree( vPairs ); Vec_IntFree( vPairsNew ); return nCubes - Vec_IntSize(vGroup) - Vec_IntSize(vGroupPrev); } // merge distance-1 with contained output part int Mop_ManMergeDist1Pairs2( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroupPrev ) { int w, c1, c2, iCube1, iCube2, Count = 0; Vec_IntForEachEntry( vGroup, iCube1, c1 ) if ( iCube1 != -1 ) { word * pCube1Out, * pCube1 = Mop_ManCubeIn( p, iCube1 ); Vec_IntForEachEntryStart( vGroup, iCube2, c2, c1+1 ) if ( iCube2 != -1 ) { word * pCube2Out, * pCube2 = Mop_ManCubeIn( p, iCube2 ); if ( !Mop_ManCheckDist1(pCube1, pCube2, p->nWordsIn) ) continue; pCube1Out = Mop_ManCubeOut( p, iCube1 ); pCube2Out = Mop_ManCubeOut( p, iCube2 ); assert( memcmp(pCube1Out, pCube2Out, sizeof(word)*p->nWordsOut) ); if ( Mop_ManCheckContain(pCube1Out, pCube2Out, p->nWordsOut) ) // pCube1 has more outputs { // update the input part for ( w = 0; w < p->nWordsIn; w++ ) pCube2[w] &= pCube1[w]; // sharp the output part for ( w = 0; w < p->nWordsOut; w++ ) pCube1Out[w] &= ~pCube2Out[w]; // move to another group Vec_IntPush( vGroupPrev, iCube2 ); Vec_IntWriteEntry( vGroup, c2, -1 ); Count++; } else if ( Mop_ManCheckContain(pCube2Out, pCube1Out, p->nWordsOut) ) // pCube2 has more outputs { // update the input part for ( w = 0; w < p->nWordsIn; w++ ) pCube1[w] &= pCube2[w]; // sharp the output part for ( w = 0; w < p->nWordsOut; w++ ) pCube2Out[w] &= ~pCube1Out[w]; // move to another group Vec_IntPush( vGroupPrev, iCube1 ); Vec_IntWriteEntry( vGroup, c1, -1 ); Count++; } } } if ( Count ) Map_ManGroupCompact( vGroup ); return Count; } int Mop_ManMergeDist1All( Mop_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vStats, int nLimit ) { Vec_Int_t * vGroup; int i, nEqual, nReduce, Count = 0; Vec_WecForEachLevelReverse( vGroups, vGroup, i ) { if ( Vec_IntSize(vGroup) == 0 ) continue; if ( i == 0 ) { printf( "Detected constant-1 cover.\n" ); fflush( stdout ); return -1; } nEqual = Mop_ManRemoveIdentical( p, vGroup ); nReduce = Mop_ManMergeDist1Pairs( p, vGroup, Vec_WecEntry(vGroups, i-1), vStats, nLimit ); //Mop_ManMergeDist1Pairs2( p, vGroup, Vec_WecEntry(vGroups, i-1) ); Count += nEqual + nReduce; //printf( "Group %3d : Equal =%5d. Reduce =%5d.\n", i, nEqual, nReduce ); } return Count; } // reduce contained cubes int Mop_ManMergeContainTwo( Mop_Man_t * p, Vec_Int_t * vGroup, Vec_Int_t * vGroup2 ) { int w, c1, c2, iCube1, iCube2, Count = 0; Vec_IntForEachEntry( vGroup, iCube1, c1 ) { word * pCube1Out, * pCube1 = Mop_ManCubeIn( p, iCube1 ); Vec_IntForEachEntry( vGroup2, iCube2, c2 ) if ( iCube2 != -1 ) { word * pCube2Out, * pCube2 = Mop_ManCubeIn( p, iCube2 ); if ( !Mop_ManCheckContain(pCube2, pCube1, p->nWordsIn) ) continue; pCube1Out = Mop_ManCubeOut( p, iCube1 ); pCube2Out = Mop_ManCubeOut( p, iCube2 ); for ( w = 0; w < p->nWordsOut; w++ ) pCube2Out[w] &= ~pCube1Out[w]; for ( w = 0; w < p->nWordsOut; w++ ) if ( pCube2Out[w] ) break; if ( w < p->nWordsOut ) // has output literals continue; // remove larger cube Vec_IntWriteEntry( vGroup2, c2, -1 ); Vec_IntPush( p->vFree, iCube2 ); Count++; } } if ( Count ) Map_ManGroupCompact( vGroup2 ); return Count; } int Mop_ManMergeContainAll( Mop_Man_t * p, Vec_Wec_t * vGroups ) { Vec_Int_t * vGroup, * vGroup2; int i, k, Count = 0; Vec_WecForEachLevel( vGroups, vGroup, i ) { Count += Mop_ManRemoveIdentical( p, vGroup ); Vec_WecForEachLevelStart( vGroups, vGroup2, k, i+1 ) Count += Mop_ManMergeContainTwo( p, vGroup, vGroup2 ); } return Count; } void Mop_ManReduce2( Mop_Man_t * p ) { abctime clk = Abc_Clock(); int nCubes = Vec_IntSize(p->vCubes); Vec_Int_t * vStats = Mop_ManCollectStats( p ); Vec_Wec_t * vGroups = Mop_ManCreateGroups( p ); int nLimit = ABC_INFINITY; // 5 * Vec_IntSum(vStats) / Vec_IntSize(vStats) + 1; int nOutLits = Mop_ManCountOutputLits( p ); int Count1 = Mop_ManMergeContainAll( p, vGroups ); int Count2 = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit ); int Count3 = Mop_ManMergeContainAll( p, vGroups ); int Count4 = Mop_ManMergeDist1All( p, vGroups, vStats, nLimit ); int Count5 = Mop_ManMergeContainAll( p, vGroups ); int Removed = Mop_ManUnCreateGroups( p, vGroups ); int nOutLits2 = Mop_ManCountOutputLits( p ); Vec_WecFree( vGroups ); //Vec_IntPrint( vStats ); Vec_IntFree( vStats ); assert( Removed == Count1 + Count2 + Count3 ); // report printf( "Cubes: %d -> %d. C = %d. M = %d. C = %d. M = %d. C = %d. Output lits: %d -> %d. ", nCubes, Vec_IntSize(p->vCubes), Count1, Count2, Count3, Count4, Count5, nOutLits, nOutLits2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mop_ManReduce( Mop_Man_t * p ) { abctime clk = Abc_Clock(); Vec_Int_t * vGroup, * vGroup2; int i, k, nOutLits, nOutLits2, nEqual = 0, nContain = 0; Vec_Wec_t * vGroups = Mop_ManCreateGroups( p ); // initial stats nOutLits = Mop_ManCountOutputLits( p ); // check identical cubes within each group Vec_WecForEachLevel( vGroups, vGroup, i ) nEqual += Mop_ManRemoveIdentical( p, vGroup ); // check contained cubes Vec_WecForEachLevel( vGroups, vGroup, i ) Vec_WecForEachLevelStart( vGroups, vGroup2, k, i+1 ) nContain += Mop_ManMergeContainTwo( p, vGroup, vGroup2 ); // final stats nOutLits2 = Mop_ManCountOutputLits( p ); Mop_ManUnCreateGroups( p, vGroups ); Vec_WecFree( vGroups ); // report printf( "Total = %d. Reduced %d equal and %d contained cubes. Output lits: %d -> %d. ", Vec_IntSize(p->vCubes), nEqual, nContain, nOutLits, nOutLits2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Mop_ManCubeCount( Mop_Man_t * p ) { int i, k, iCube; Vec_Wec_t * vOuts = Vec_WecStart( p->nOuts ); Vec_IntForEachEntry( p->vCubes, iCube, i ) if ( iCube != -1 ) { word * pCube = Mop_ManCubeOut( p, iCube ); for ( k = 0; k < p->nOuts; k++ ) if ( Abc_TtGetBit( pCube, k ) ) Vec_WecPush( vOuts, k, iCube ); } return vOuts; } Abc_Ntk_t * Mop_ManDerive( Mop_Man_t * p, char * pFileName ) { int i, k, c, iCube; char Symb[4] = { '-', '0', '1', '?' }; // cube symbols Vec_Str_t * vSop = Vec_StrAlloc( 1000 ); // storage for one SOP Vec_Wec_t * vOuts = Mop_ManCubeCount( p ); // cube count for each output Abc_Ntk_t * pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); pNtk->pName = Extra_UtilStrsav( pFileName ); pNtk->pSpec = Extra_UtilStrsav( pFileName ); for ( i = 0; i < p->nIns; i++ ) Abc_NtkCreatePi(pNtk); for ( i = 0; i < p->nOuts; i++ ) { Vec_Int_t * vThis = Vec_WecEntry( vOuts, i ); Abc_Obj_t * pPo = Abc_NtkCreatePo(pNtk); Abc_Obj_t * pNode = Abc_NtkCreateNode(pNtk); Abc_ObjAddFanin( pPo, pNode ); if ( Vec_IntSize(vThis) == 0 ) { pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ); continue; } for ( k = 0; k < p->nIns; k++ ) Abc_ObjAddFanin( pNode, Abc_NtkPi(pNtk, k) ); Vec_StrClear( vSop ); Vec_IntForEachEntry( vThis, iCube, c ) { word * pCube = Mop_ManCubeIn( p, iCube ); for ( k = 0; k < p->nIns; k++ ) Vec_StrPush( vSop, Symb[Abc_TtGetQua(pCube, k)] ); Vec_StrAppend( vSop, " 1\n" ); } Vec_StrPush( vSop, '\0' ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, Vec_StrArray(vSop) ); } Vec_StrFree( vSop ); Vec_WecFree( vOuts ); Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Mop_ManTest( char * pFileName, int fMerge, int fVerbose ) { Abc_Ntk_t * pNtk = NULL; Mop_Man_t * p = Mop_ManRead( pFileName ); if ( p == NULL ) return NULL; Mop_ManRemoveEmpty( p ); //Mop_ManPrint( p ); if ( fMerge ) Mop_ManReduce2( p ); else Mop_ManReduce( p ); //Mop_ManPrint( p ); pNtk = Mop_ManDerive( p, pFileName ); Mop_ManStop( p ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioReadVerilog.c000066400000000000000000000060311300674244400242540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioReadVerilog.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedure to read network from file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioReadVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/ver/ver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //extern Abc_Des_t * Ver_ParseFile( char * pFileName, Abc_Des_t * pGateLib, int fCheck, int fUseMemMan ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads hierarchical design from the Verilog file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ) { Abc_Ntk_t * pNtk, * pTemp; Abc_Des_t * pDesign; int i, RetValue; // parse the verilog file pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 ); if ( pDesign == NULL ) return NULL; // detect top-level model RetValue = Abc_DesFindTopLevelModels( pDesign ); pNtk = (Abc_Ntk_t *)Vec_PtrEntry( pDesign->vTops, 0 ); if ( RetValue > 1 ) { printf( "Warning: The design has %d root-level modules: ", Vec_PtrSize(pDesign->vTops) ); Vec_PtrForEachEntry( Abc_Ntk_t *, pDesign->vTops, pTemp, i ) printf( " %s", Abc_NtkName(pTemp) ); printf( "\n" ); printf( "The first one (%s) will be used.\n", pNtk->pName ); } // extract the master network pNtk->pDesign = pDesign; pDesign->pManFunc = NULL; // verify the design for cyclic dependence assert( Vec_PtrSize(pDesign->vModules) > 0 ); if ( Vec_PtrSize(pDesign->vModules) == 1 ) { // printf( "Warning: The design is not hierarchical.\n" ); Abc_DesFree( pDesign, pNtk ); pNtk->pDesign = NULL; pNtk->pSpec = Extra_UtilStrsav( pFileName ); } else { // check that there is no cyclic dependency Abc_NtkIsAcyclicHierarchy( pNtk ); } //Io_WriteVerilog( pNtk, "_temp.v" ); // Abc_NtkPrintBoxInfo( pNtk ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioUtil.c000066400000000000000000000641461300674244400230010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write the network in BENCH format.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the file type.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Io_FileType_t Io_ReadFileType( char * pFileName ) { char * pExt; if ( pFileName == NULL ) return IO_FILE_NONE; pExt = Extra_FileNameExtension( pFileName ); if ( pExt == NULL ) return IO_FILE_NONE; if ( !strcmp( pExt, "aig" ) ) return IO_FILE_AIGER; if ( !strcmp( pExt, "baf" ) ) return IO_FILE_BAF; if ( !strcmp( pExt, "bblif" ) ) return IO_FILE_BBLIF; if ( !strcmp( pExt, "blif" ) ) return IO_FILE_BLIF; if ( !strcmp( pExt, "bench" ) ) return IO_FILE_BENCH; if ( !strcmp( pExt, "cnf" ) ) return IO_FILE_CNF; if ( !strcmp( pExt, "dot" ) ) return IO_FILE_DOT; if ( !strcmp( pExt, "edif" ) ) return IO_FILE_EDIF; if ( !strcmp( pExt, "eqn" ) ) return IO_FILE_EQN; if ( !strcmp( pExt, "gml" ) ) return IO_FILE_GML; if ( !strcmp( pExt, "list" ) ) return IO_FILE_LIST; if ( !strcmp( pExt, "mv" ) ) return IO_FILE_BLIFMV; if ( !strcmp( pExt, "pla" ) ) return IO_FILE_PLA; if ( !strcmp( pExt, "smv" ) ) return IO_FILE_SMV; if ( !strcmp( pExt, "v" ) ) return IO_FILE_VERILOG; return IO_FILE_UNKNOWN; } /**Function************************************************************* Synopsis [Read the network from a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ) { FILE * pFile; Abc_Ntk_t * pNtk; if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) { fprintf( stdout, "Generic file reader requires a known file extension to open \"%s\".\n", pFileName ); return NULL; } // check if the file exists pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { fprintf( stdout, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" )) ) fprintf( stdout, "Did you mean \"%s\"?", pFileName ); fprintf( stdout, "\n" ); return NULL; } fclose( pFile ); // read the AIG if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF || FileType == IO_FILE_BBLIF ) { if ( FileType == IO_FILE_AIGER ) pNtk = Io_ReadAiger( pFileName, fCheck ); else if ( FileType == IO_FILE_BAF ) pNtk = Io_ReadBaf( pFileName, fCheck ); else // if ( FileType == IO_FILE_BBLIF ) pNtk = Io_ReadBblif( pFileName, fCheck ); if ( pNtk == NULL ) { fprintf( stdout, "Reading AIG from file has failed.\n" ); return NULL; } return pNtk; } // read the new netlist if ( FileType == IO_FILE_BLIF ) // pNtk = Io_ReadBlif( pFileName, fCheck ); pNtk = Io_ReadBlifMv( pFileName, 0, fCheck ); else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) pNtk = Io_ReadBlifMv( pFileName, 1, fCheck ); else if ( FileType == IO_FILE_BENCH ) pNtk = Io_ReadBench( pFileName, fCheck ); else if ( FileType == IO_FILE_EDIF ) pNtk = Io_ReadEdif( pFileName, fCheck ); else if ( FileType == IO_FILE_EQN ) pNtk = Io_ReadEqn( pFileName, fCheck ); else if ( FileType == IO_FILE_PLA ) pNtk = Io_ReadPla( pFileName, 0, 0, 0, 0, fCheck ); else if ( FileType == IO_FILE_VERILOG ) pNtk = Io_ReadVerilog( pFileName, fCheck ); else { fprintf( stderr, "Unknown file format.\n" ); return NULL; } if ( pNtk == NULL ) { fprintf( stdout, "Reading network from file has failed.\n" ); return NULL; } if ( fCheck && (Abc_NtkBlackboxNum(pNtk) || Abc_NtkWhiteboxNum(pNtk)) ) { int i, fCycle = 0; Abc_Ntk_t * pModel; fprintf( stdout, "Warning: The network contains hierarchy.\n" ); Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) if ( !Abc_NtkIsAcyclicWithBoxes( pModel ) ) fCycle = 1; if ( fCycle ) { Abc_NtkDelete( pNtk ); return NULL; } } return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t *temporaryLtlStore( Abc_Ntk_t *pNtk ) { Vec_Ptr_t *tempStore; char *pFormula; int i; if( pNtk && Vec_PtrSize( pNtk->vLtlProperties ) > 0 ) { tempStore = Vec_PtrAlloc( Vec_PtrSize( pNtk->vLtlProperties ) ); Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pFormula, i ) Vec_PtrPush( tempStore, pFormula ); assert( Vec_PtrSize( tempStore ) == Vec_PtrSize( pNtk->vLtlProperties ) ); return tempStore; } else return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void updateLtlStoreOfNtk( Abc_Ntk_t *pNtk, Vec_Ptr_t *tempLtlStore ) { int i; char *pFormula; assert( tempLtlStore != NULL ); Vec_PtrForEachEntry( char *, tempLtlStore, pFormula, i ) Vec_PtrPush( pNtk->vLtlProperties, pFormula ); } /**Function************************************************************* Synopsis [Read the network from a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck, int fBarBufs ) { Abc_Ntk_t * pNtk, * pTemp; Vec_Ptr_t * vLtl; // get the netlist pNtk = Io_ReadNetlist( pFileName, FileType, fCheck ); if ( pNtk == NULL ) return NULL; vLtl = temporaryLtlStore( pNtk ); if ( !Abc_NtkIsNetlist(pNtk) ) return pNtk; // derive barbufs if ( fBarBufs ) { pNtk = Abc_NtkToBarBufs( pTemp = pNtk ); Abc_NtkDelete( pTemp ); assert( Abc_NtkIsLogic(pNtk) ); return pNtk; } // flatten logic hierarchy assert( Abc_NtkIsNetlist(pNtk) ); if ( Abc_NtkWhiteboxNum(pNtk) > 0 ) { pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk ); Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) { fprintf( stdout, "Flattening logic hierarchy has failed.\n" ); return NULL; } } // convert blackboxes if ( Abc_NtkBlackboxNum(pNtk) > 0 ) { printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) ); pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk ); Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) { fprintf( stdout, "Converting blackboxes has failed.\n" ); return NULL; } } // consider the case of BLIF-MV if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) { pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk ); Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) { fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" ); return NULL; } return pNtk; } // convert the netlist into the logic network pNtk = Abc_NtkToLogic( pTemp = pNtk ); if( vLtl ) updateLtlStoreOfNtk( pNtk, vLtl ); Abc_NtkDelete( pTemp ); if ( pNtk == NULL ) { fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" ); return NULL; } return pNtk; } /**Function************************************************************* Synopsis [Write the network into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ) { Abc_Ntk_t * pNtkTemp, * pNtkCopy; // check if the current network is available if ( pNtk == NULL ) { fprintf( stdout, "Empty network.\n" ); return; } // check if the file extension if given if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) { fprintf( stdout, "The generic file writer requires a known file extension.\n" ); return; } // write the AIG formats if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) { if ( !Abc_NtkIsStrash(pNtk) ) { fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); return; } if ( FileType == IO_FILE_AIGER ) Io_WriteAiger( pNtk, pFileName, 1, 0, 0 ); else //if ( FileType == IO_FILE_BAF ) Io_WriteBaf( pNtk, pFileName ); return; } // write non-netlist types if ( FileType == IO_FILE_CNF ) { Io_WriteCnf( pNtk, pFileName, 0 ); return; } if ( FileType == IO_FILE_DOT ) { Io_WriteDot( pNtk, pFileName ); return; } if ( FileType == IO_FILE_GML ) { Io_WriteGml( pNtk, pFileName ); return; } if ( FileType == IO_FILE_BBLIF ) { if ( !Abc_NtkIsLogic(pNtk) ) { fprintf( stdout, "Writing Binary BLIF is only possible for logic networks.\n" ); return; } if ( !Abc_NtkHasSop(pNtk) ) Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); Io_WriteBblif( pNtk, pFileName ); return; } /* if ( FileType == IO_FILE_BLIFMV ) { Io_WriteBlifMv( pNtk, pFileName ); return; } */ // convert logic network into netlist if ( FileType == IO_FILE_PLA ) { if ( Abc_NtkLevel(pNtk) > 1 ) { fprintf( stdout, "PLA writing is available for collapsed networks.\n" ); return; } if ( Abc_NtkIsComb(pNtk) ) pNtkTemp = Abc_NtkToNetlist( pNtk ); else { fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" ); pNtkCopy = Abc_NtkDup( pNtk ); Abc_NtkMakeComb( pNtkCopy, 0 ); pNtkTemp = Abc_NtkToNetlist( pNtk ); Abc_NtkDelete( pNtkCopy ); } if ( !Abc_NtkToSop( pNtkTemp, 1, ABC_INFINITY ) ) return; } else if ( FileType == IO_FILE_MOPLA ) { pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); } else if ( FileType == IO_FILE_BENCH ) { if ( !Abc_NtkIsStrash(pNtk) ) { fprintf( stdout, "Writing traditional BENCH is available for AIGs only (use \"write_bench\").\n" ); return; } pNtkTemp = Abc_NtkToNetlistBench( pNtk ); } else if ( FileType == IO_FILE_SMV ) { if ( !Abc_NtkIsStrash(pNtk) ) { fprintf( stdout, "Writing traditional SMV is available for AIGs only.\n" ); return; } pNtkTemp = Abc_NtkToNetlistBench( pNtk ); } else pNtkTemp = Abc_NtkToNetlist( pNtk ); if ( pNtkTemp == NULL ) { fprintf( stdout, "Converting to netlist has failed.\n" ); return; } if ( FileType == IO_FILE_BLIF ) { if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) Abc_NtkToSop( pNtkTemp, -1, ABC_INFINITY ); Io_WriteBlif( pNtkTemp, pFileName, 1, 0, 0 ); } else if ( FileType == IO_FILE_BLIFMV ) { if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) ) return; Io_WriteBlifMv( pNtkTemp, pFileName ); } else if ( FileType == IO_FILE_BENCH ) Io_WriteBench( pNtkTemp, pFileName ); else if ( FileType == IO_FILE_BOOK ) Io_WriteBook( pNtkTemp, pFileName ); else if ( FileType == IO_FILE_PLA ) Io_WritePla( pNtkTemp, pFileName ); else if ( FileType == IO_FILE_MOPLA ) Io_WriteMoPla( pNtkTemp, pFileName ); else if ( FileType == IO_FILE_EQN ) { if ( !Abc_NtkHasAig(pNtkTemp) ) Abc_NtkToAig( pNtkTemp ); Io_WriteEqn( pNtkTemp, pFileName ); } else if ( FileType == IO_FILE_SMV ) Io_WriteSmv( pNtkTemp, pFileName ); else if ( FileType == IO_FILE_VERILOG ) { if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) Abc_NtkToAig( pNtkTemp ); Io_WriteVerilog( pNtkTemp, pFileName ); } else fprintf( stderr, "Unknown file format.\n" ); Abc_NtkDelete( pNtkTemp ); } /**Function************************************************************* Synopsis [Write the network into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ) { Abc_Ntk_t * pNtkTemp, * pNtkResult, * pNtkBase = NULL; int i; // check if the current network is available if ( pNtk == NULL ) { fprintf( stdout, "Empty network.\n" ); return; } // read the base network assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF ) pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 ); else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 ); else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG ) pNtkBase = Io_ReadVerilog( pBaseName, 1 ); else fprintf( stderr, "Unknown input file format.\n" ); if ( pNtkBase == NULL ) return; // flatten logic hierarchy if present if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 && pNtk->nBarBufs == 0 ) { pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase ); Abc_NtkDelete( pNtkTemp ); if ( pNtkBase == NULL ) return; } // reintroduce the boxes into the netlist if ( pNtk->nBarBufs > 0 ) { // derive the netlist pNtkResult = Abc_NtkToNetlist( pNtk ); pNtkResult = Abc_NtkFromBarBufs( pNtkBase, pNtkTemp = pNtkResult ); Abc_NtkDelete( pNtkTemp ); if ( pNtkResult ) printf( "Hierarchy writer replaced %d barbufs by hierarchy boundaries.\n", pNtk->nBarBufs ); } else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) { if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) { printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" ); Abc_NtkDelete( pNtkBase ); return; } // convert the current network to BLIF-MV assert( !Abc_NtkIsNetlist(pNtk) ); pNtkResult = Abc_NtkToNetlist( pNtk ); if ( !Abc_NtkConvertToBlifMv( pNtkResult ) ) { Abc_NtkDelete( pNtkBase ); return; } // reintroduce the network pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult ); Abc_NtkDelete( pNtkTemp ); } else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) { // derive the netlist pNtkResult = Abc_NtkToNetlist( pNtk ); pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult ); Abc_NtkDelete( pNtkTemp ); if ( pNtkResult ) printf( "Hierarchy writer reintroduced %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtkBase) ); } else { printf( "Warning: The output network does not contain blackboxes.\n" ); pNtkResult = Abc_NtkToNetlist( pNtk ); } Abc_NtkDelete( pNtkBase ); if ( pNtkResult == NULL ) return; // write the resulting network if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF ) { if ( pNtkResult->pDesign ) { Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkResult->pDesign->vModules, pNtkTemp, i ) if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) Abc_NtkToSop( pNtkTemp, -1, ABC_INFINITY ); } else { if ( !Abc_NtkHasSop(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) Abc_NtkToSop( pNtkResult, -1, ABC_INFINITY ); } Io_WriteBlif( pNtkResult, pFileName, 1, 0, 0 ); } else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG ) { if ( pNtkResult->pDesign ) { Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkResult->pDesign->vModules, pNtkTemp, i ) if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) Abc_NtkToAig( pNtkTemp ); } else { if ( !Abc_NtkHasAig(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) Abc_NtkToAig( pNtkResult ); } Io_WriteVerilog( pNtkResult, pFileName ); } else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) { Io_WriteBlifMv( pNtkResult, pFileName ); } else fprintf( stderr, "Unknown output file format.\n" ); Abc_NtkDelete( pNtkResult ); } /**Function************************************************************* Synopsis [Creates PI terminal and net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pNet, * pTerm; // get the PI net pNet = Abc_NtkFindNet( pNtk, pName ); if ( pNet ) printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); // add the PI node pTerm = Abc_NtkCreatePi( pNtk ); Abc_ObjAddFanin( pNet, pTerm ); return pTerm; } /**Function************************************************************* Synopsis [Creates PO terminal and net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pNet, * pTerm; // get the PO net pNet = Abc_NtkFindNet( pNtk, pName ); if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); // add the PO node pTerm = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pTerm, pNet ); return pTerm; } /**Function************************************************************* Synopsis [Create a latch with the given input/output.] Description [By default, the latch value is unknown (ABC_INIT_NONE).] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) { Abc_Obj_t * pLatch, * pTerm, * pNet; // get the LI net pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI ); // add the BO terminal pTerm = Abc_NtkCreateBi( pNtk ); Abc_ObjAddFanin( pTerm, pNet ); // add the latch box pLatch = Abc_NtkCreateLatch( pNtk ); Abc_ObjAddFanin( pLatch, pTerm ); // add the BI terminal pTerm = Abc_NtkCreateBo( pNtk ); Abc_ObjAddFanin( pTerm, pLatch ); // get the LO net pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); Abc_ObjAddFanin( pNet, pTerm ); // set latch name Abc_ObjAssignName( pLatch, pNetLO, "L" ); return pLatch; } /**Function************************************************************* Synopsis [Create the reset latch with data=1 and init=0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ) { Abc_Obj_t * pLatch, * pNode; Abc_Obj_t * pNetLI, * pNetLO; // create latch with 0 init value // pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" ); pNetLI = Abc_NtkCreateNet( pNtk ); pNetLO = Abc_NtkCreateNet( pNtk ); Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL ); Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL ); pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) ); // set the initial value Abc_LatchSetInit0( pLatch ); // feed the latch with constant1- node // pNode = Abc_NtkCreateNode( pNtk ); // pNode->pData = Abc_SopRegister( (Extra_MmFlex_t *)pNtk->pManFunc, "2\n1\n" ); pNode = Abc_NtkCreateNodeConst1( pNtk ); Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode ); return pLatch; } /**Function************************************************************* Synopsis [Create node and the net driven by it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ) { Abc_Obj_t * pNet, * pNode; int i; // create a new node pNode = Abc_NtkCreateNode( pNtk ); // add the fanin nets for ( i = 0; i < nInputs; i++ ) { pNet = Abc_NtkFindOrCreateNet( pNtk, pNamesIn[i] ); Abc_ObjAddFanin( pNode, pNet ); } // add the fanout net pNet = Abc_NtkFindOrCreateNet( pNtk, pNameOut ); Abc_ObjAddFanin( pNet, pNode ); return pNode; } /**Function************************************************************* Synopsis [Create a constant 0 node driving the net with this name.] Description [Assumes that the net already exists.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, int fConst1 ) { Abc_Obj_t * pNet, * pTerm; pTerm = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); pNet = Abc_NtkFindNet(pNtk, pName); assert( pNet ); Abc_ObjAddFanin( pNet, pTerm ); return pTerm; } /**Function************************************************************* Synopsis [Create an inverter or buffer for the given net.] Description [Assumes that the nets already exist.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) { Abc_Obj_t * pNet, * pNode; pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); pNode = Abc_NtkCreateNodeInv(pNtk, pNet); pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); Abc_ObjAddFanin( pNet, pNode ); return pNode; } /**Function************************************************************* Synopsis [Create an inverter or buffer for the given net.] Description [Assumes that the nets already exist.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) { Abc_Obj_t * pNet, * pNode; pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); pNode = Abc_NtkCreateNodeBuf(pNtk, pNet); pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); Abc_ObjAddFanin( pNet, pNode ); return pNet; } /**Function************************************************************* Synopsis [Provide an fopen replacement with path lookup] Description [Provide an fopen replacement where the path stored in pathvar MVSIS variable is used to look up the path for name. Returns NULL if file cannot be opened.] SideEffects [] SeeAlso [] ***********************************************************************/ FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ) { char * t = 0, * c = 0, * i; if ( PathVar == 0 ) { return fopen( FileName, Mode ); } else { if ( (c = Abc_FrameReadFlag( (char*)PathVar )) ) { char ActualFileName[4096]; FILE * fp = 0; t = Extra_UtilStrsav( c ); for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") ) { #ifdef WIN32 _snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); #else snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); #endif if ( ( fp = fopen ( ActualFileName, Mode ) ) ) { if ( fVerbose ) fprintf ( stdout, "Using file %s\n", ActualFileName ); ABC_FREE( t ); return fp; } } ABC_FREE( t ); return 0; } else { return fopen( FileName, Mode ); } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteAiger.c000066400000000000000000001020651300674244400241170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteAiger.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: ioWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] ***********************************************************************/ // The code in this file is developed in collaboration with Mark Jarvin of Toronto. #include #include #include #include #include "misc/bzlib/bzlib.h" #include "misc/zlib/zlib.h" #include "ioAbc.h" ABC_NAMESPACE_IMPL_START #ifdef _WIN32 #define vsnprintf _vsnprintf #endif //////////////////////////////////////////////////////////////////////// /// 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 unsigned Io_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } static unsigned Io_ObjAigerNum( Abc_Obj_t * pObj ) { return (unsigned)(ABC_PTRINT_T)pObj->pCopy; } static void Io_ObjSetAigerNum( Abc_Obj_t * pObj, unsigned Num ) { pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)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 Io_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 [Create the array of literals to be written.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Io_WriteAigerLiterals( Abc_Ntk_t * pNtk ) { Vec_Int_t * vLits; Abc_Obj_t * pObj, * pDriver; int i; vLits = Vec_IntAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachLatchInput( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); Vec_IntPush( vLits, Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); } Abc_NtkForEachPo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); Vec_IntPush( vLits, Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); } return vLits; } /**Function************************************************************* Synopsis [Creates the binary encoded array of literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Io_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 = Io_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 = Io_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 * Io_WriteDecodeLiterals( char ** ppPos, int nEntries ); char * pPos = Vec_StrArray( vBinary ); Vec_Int_t * vTemp = Io_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 ); } } */ return vBinary; } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteAiger_old( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact ) { ProgressBar * pProgress; FILE * pFile; Abc_Obj_t * pObj, * pDriver, * pLatch; int i, nNodes, nBufferSize, Pos, fExtended; unsigned char * pBuffer; unsigned uLit0, uLit1, uLit; fExtended = Abc_NtkConstrNum(pNtk); assert( Abc_NtkIsStrash(pNtk) ); Abc_NtkForEachLatch( pNtk, pObj, i ) if ( !Abc_LatchIsInit0(pObj) ) { if ( !fCompact ) { fExtended = 1; break; } fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); return; } // start the output stream pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); return; } // set the node numbers to be used in the output file nNodes = 0; Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ ); Abc_NtkForEachCi( pNtk, pObj, i ) Io_ObjSetAigerNum( pObj, nNodes++ ); Abc_AigForEachAnd( pNtk, pObj, i ) Io_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" : "", Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), Abc_NtkPiNum(pNtk), Abc_NtkLatchNum(pNtk), fExtended ? 0 : Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) ); // write the extended header "B C J F" if ( fExtended ) fprintf( pFile, " %u %u", Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk), Abc_NtkConstrNum(pNtk) ); 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 Abc_NtkInvertConstraints( pNtk ); if ( !fCompact ) { // write latch drivers Abc_NtkForEachLatch( pNtk, pLatch, i ) { pObj = Abc_ObjFanin0(pLatch); pDriver = Abc_ObjFanin0(pObj); uLit = Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ); if ( Abc_LatchIsInit0(pLatch) ) fprintf( pFile, "%u\n", uLit ); else if ( Abc_LatchIsInit1(pLatch) ) fprintf( pFile, "%u 1\n", uLit ); else { // Both None and DC are written as 'uninitialized' e.g. a free boolean value assert( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ); fprintf( pFile, "%u %u\n", uLit, Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanout0(pLatch)), 0 ) ); } } // write PO drivers Abc_NtkForEachPo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); } } else { Vec_Int_t * vLits = Io_WriteAigerLiterals( pNtk ); Vec_Str_t * vBinary = Io_WriteEncodeLiterals( vLits ); fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); Vec_StrFree( vBinary ); Vec_IntFree( vLits ); } Abc_NtkInvertConstraints( pNtk ); // write the nodes into the buffer Pos = 0; nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_AigForEachAnd( pNtk, pObj, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); uLit = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 ); uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) ); uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) ); if ( uLit0 > uLit1 ) { unsigned Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } assert( uLit1 < uLit ); Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit - uLit1) ); Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit1 - uLit0) ); if ( Pos > nBufferSize - 10 ) { printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); fclose( pFile ); return; } } assert( Pos < nBufferSize ); Extra_ProgressBarStop( pProgress ); // write the buffer fwrite( pBuffer, 1, Pos, pFile ); ABC_FREE( pBuffer ); // write the symbol table if ( fWriteSymbols ) { // write PIs Abc_NtkForEachPi( pNtk, pObj, i ) fprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) ); // write latches Abc_NtkForEachLatch( pNtk, pObj, i ) fprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) ); // write POs Abc_NtkForEachPo( pNtk, pObj, i ) if ( !fExtended ) fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) ); else if ( i < Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) ) fprintf( pFile, "b%d %s\n", i, Abc_ObjName(pObj) ); else fprintf( pFile, "c%d %s\n", i - (Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk)), Abc_ObjName(pObj) ); } // write the comment fprintf( pFile, "c\n" ); if ( pNtk->pName && strlen(pNtk->pName) > 0 ) fprintf( pFile, ".model %s\n", pNtk->pName ); fprintf( pFile, "This file was produced by ABC on %s\n", Extra_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 Io_WriteAigerGz( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ) { ProgressBar * pProgress; gzFile pFile; Abc_Obj_t * pObj, * pDriver, * pLatch; int i, nNodes, Pos, nBufferSize, fExtended; unsigned char * pBuffer; unsigned uLit0, uLit1, uLit; assert( Abc_NtkIsStrash(pNtk) ); // start the output stream pFile = gzopen( pFileName, "wb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen if ( pFile == NULL ) { fprintf( stdout, "Io_WriteAigerGz(): Cannot open the output file \"%s\".\n", pFileName ); return; } fExtended = Abc_NtkConstrNum(pNtk); // set the node numbers to be used in the output file nNodes = 0; Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ ); Abc_NtkForEachCi( pNtk, pObj, i ) Io_ObjSetAigerNum( pObj, nNodes++ ); Abc_AigForEachAnd( pNtk, pObj, i ) Io_ObjSetAigerNum( pObj, nNodes++ ); // write the header "M I L O A" where M = I + L + A gzprintf( pFile, "aig %u %u %u %u %u", Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), Abc_NtkPiNum(pNtk), Abc_NtkLatchNum(pNtk), fExtended ? 0 : Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) ); // write the extended header "B C J F" if ( fExtended ) gzprintf( pFile, " %u %u", Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk), Abc_NtkConstrNum(pNtk) ); gzprintf( 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 // write latch drivers Abc_NtkInvertConstraints( pNtk ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { pObj = Abc_ObjFanin0(pLatch); pDriver = Abc_ObjFanin0(pObj); uLit = Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ); if ( Abc_LatchIsInit0(pLatch) ) gzprintf( pFile, "%u\n", uLit ); else if ( Abc_LatchIsInit1(pLatch) ) gzprintf( pFile, "%u 1\n", uLit ); else { // Both None and DC are written as 'uninitialized' e.g. a free boolean value assert( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ); gzprintf( pFile, "%u %u\n", uLit, Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanout0(pLatch)), 0 ) ); } } // write PO drivers Abc_NtkForEachPo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); gzprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); } Abc_NtkInvertConstraints( pNtk ); // write the nodes into the buffer Pos = 0; nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_AigForEachAnd( pNtk, pObj, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); uLit = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 ); uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) ); uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) ); if ( uLit0 > uLit1 ) { unsigned Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } assert( uLit1 < uLit ); Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); if ( Pos > nBufferSize - 10 ) { printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); gzclose( pFile ); return; } } assert( Pos < nBufferSize ); Extra_ProgressBarStop( pProgress ); // write the buffer gzwrite(pFile, pBuffer, Pos); ABC_FREE( pBuffer ); // write the symbol table if ( fWriteSymbols ) { // write PIs Abc_NtkForEachPi( pNtk, pObj, i ) gzprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) ); // write latches Abc_NtkForEachLatch( pNtk, pObj, i ) gzprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) ); // write POs Abc_NtkForEachPo( pNtk, pObj, i ) if ( !fExtended ) gzprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) ); else if ( i < Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) ) gzprintf( pFile, "b%d %s\n", i, Abc_ObjName(pObj) ); else gzprintf( pFile, "c%d %s\n", i - (Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk)), Abc_ObjName(pObj) ); } // write the comment gzprintf( pFile, "c\n" ); if ( pNtk->pName && strlen(pNtk->pName) > 0 ) gzprintf( pFile, ".model %s\n", pNtk->pName ); gzprintf( pFile, "This file was produced by ABC on %s\n", Extra_TimeStamp() ); gzprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); gzclose( pFile ); } /**Function************************************************************* Synopsis [Procedure to write data into BZ2 file.] Description [Based on the vsnprintf() man page.] SideEffects [] SeeAlso [] ***********************************************************************/ typedef struct bz2file { FILE * f; BZFILE * b; char * buf; int nBytes; int nBytesMax; } bz2file; int fprintfBz2Aig( bz2file * b, char * fmt, ... ) { if (b->b) { char * newBuf; int bzError; va_list ap; while (1) { va_start(ap,fmt); b->nBytes = vsnprintf(b->buf,b->nBytesMax,fmt,ap); va_end(ap); if (b->nBytes > -1 && b->nBytes < b->nBytesMax) break; if (b->nBytes > -1) b->nBytesMax = b->nBytes + 1; else b->nBytesMax *= 2; if ((newBuf = ABC_REALLOC( char,b->buf,b->nBytesMax )) == NULL) return -1; else b->buf = newBuf; } BZ2_bzWrite( &bzError, b->b, b->buf, b->nBytes ); if (bzError == BZ_IO_ERROR) { fprintf( stdout, "Ioa_WriteBlif(): I/O error writing to compressed stream.\n" ); return -1; } return b->nBytes; } else { int n; va_list ap; va_start(ap,fmt); n = vfprintf( b->f, fmt, ap); va_end(ap); return n; } } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols, int fCompact, int fUnique ) { ProgressBar * pProgress; // FILE * pFile; Abc_Obj_t * pObj, * pDriver, * pLatch; int i, nNodes, nBufferSize, bzError, Pos, fExtended; unsigned char * pBuffer; unsigned uLit0, uLit1, uLit; bz2file b; // define unique writing if ( fUnique ) { fWriteSymbols = 0; fCompact = 0; } fExtended = Abc_NtkConstrNum(pNtk); // check that the network is valid assert( Abc_NtkIsStrash(pNtk) ); Abc_NtkForEachLatch( pNtk, pObj, i ) if ( !Abc_LatchIsInit0(pObj) ) { if ( !fCompact ) { fExtended = 1; break; } fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); return; } // write the GZ file if (!strncmp(pFileName+strlen(pFileName)-3,".gz",3)) { Io_WriteAigerGz( pNtk, pFileName, fWriteSymbols ); return; } memset(&b,0,sizeof(b)); b.nBytesMax = (1<<12); b.buf = ABC_ALLOC( char,b.nBytesMax ); // start the output stream b.f = fopen( pFileName, "wb" ); if ( b.f == NULL ) { fprintf( stdout, "Ioa_WriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); ABC_FREE(b.buf); return; } if (!strncmp(pFileName+strlen(pFileName)-4,".bz2",4)) { b.b = BZ2_bzWriteOpen( &bzError, b.f, 9, 0, 0 ); if ( bzError != BZ_OK ) { BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL ); fprintf( stdout, "Ioa_WriteBlif(): Cannot start compressed stream.\n" ); fclose( b.f ); ABC_FREE(b.buf); return; } } // set the node numbers to be used in the output file nNodes = 0; Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ ); Abc_NtkForEachCi( pNtk, pObj, i ) Io_ObjSetAigerNum( pObj, nNodes++ ); Abc_AigForEachAnd( pNtk, pObj, i ) Io_ObjSetAigerNum( pObj, nNodes++ ); // write the header "M I L O A" where M = I + L + A fprintfBz2Aig( &b, "aig%s %u %u %u %u %u", fCompact? "2" : "", Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), Abc_NtkPiNum(pNtk), Abc_NtkLatchNum(pNtk), fExtended ? 0 : Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) ); // write the extended header "B C J F" if ( fExtended ) fprintfBz2Aig( &b, " %u %u", Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk), Abc_NtkConstrNum(pNtk) ); fprintfBz2Aig( &b, "\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 Abc_NtkInvertConstraints( pNtk ); if ( !fCompact ) { // write latch drivers Abc_NtkForEachLatch( pNtk, pLatch, i ) { pObj = Abc_ObjFanin0(pLatch); pDriver = Abc_ObjFanin0(pObj); uLit = Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ); if ( Abc_LatchIsInit0(pLatch) ) fprintfBz2Aig( &b, "%u\n", uLit ); else if ( Abc_LatchIsInit1(pLatch) ) fprintfBz2Aig( &b, "%u 1\n", uLit ); else { // Both None and DC are written as 'uninitialized' e.g. a free boolean value assert( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ); fprintfBz2Aig( &b, "%u %u\n", uLit, Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanout0(pLatch)), 0 ) ); } } // write PO drivers Abc_NtkForEachPo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); fprintfBz2Aig( &b, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); } } else { Vec_Int_t * vLits = Io_WriteAigerLiterals( pNtk ); Vec_Str_t * vBinary = Io_WriteEncodeLiterals( vLits ); if ( !b.b ) fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), b.f ); else { BZ2_bzWrite( &bzError, b.b, Vec_StrArray(vBinary), Vec_StrSize(vBinary) ); if (bzError == BZ_IO_ERROR) { fprintf( stdout, "Io_WriteAiger(): I/O error writing to compressed stream.\n" ); fclose( b.f ); ABC_FREE(b.buf); Vec_StrFree( vBinary ); return; } } Vec_StrFree( vBinary ); Vec_IntFree( vLits ); } Abc_NtkInvertConstraints( pNtk ); // write the nodes into the buffer Pos = 0; nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_AigForEachAnd( pNtk, pObj, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); uLit = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 ); uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) ); uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) ); if ( uLit0 > uLit1 ) { unsigned Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } assert( uLit1 < uLit ); Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit - uLit1) ); Pos = Io_WriteAigerEncode( pBuffer, Pos, (unsigned)(uLit1 - uLit0) ); if ( Pos > nBufferSize - 10 ) { printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); fclose( b.f ); ABC_FREE(b.buf); Extra_ProgressBarStop( pProgress ); return; } } assert( Pos < nBufferSize ); Extra_ProgressBarStop( pProgress ); // write the buffer if ( !b.b ) fwrite( pBuffer, 1, Pos, b.f ); else { BZ2_bzWrite( &bzError, b.b, pBuffer, Pos ); if (bzError == BZ_IO_ERROR) { fprintf( stdout, "Io_WriteAiger(): I/O error writing to compressed stream.\n" ); fclose( b.f ); ABC_FREE(b.buf); return; } } ABC_FREE( pBuffer ); // write the symbol table if ( fWriteSymbols ) { // write PIs Abc_NtkForEachPi( pNtk, pObj, i ) fprintfBz2Aig( &b, "i%d %s\n", i, Abc_ObjName(pObj) ); // write latches Abc_NtkForEachLatch( pNtk, pObj, i ) fprintfBz2Aig( &b, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) ); // write POs Abc_NtkForEachPo( pNtk, pObj, i ) if ( !fExtended ) fprintfBz2Aig( &b, "o%d %s\n", i, Abc_ObjName(pObj) ); else if ( i < Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) ) fprintfBz2Aig( &b, "b%d %s\n", i, Abc_ObjName(pObj) ); else fprintfBz2Aig( &b, "c%d %s\n", i - (Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk)), Abc_ObjName(pObj) ); } // write the comment fprintfBz2Aig( &b, "c" ); if ( !fUnique ) { if ( pNtk->pName && strlen(pNtk->pName) > 0 ) fprintfBz2Aig( &b, "\n%s%c", pNtk->pName, '\0' ); fprintfBz2Aig( &b, "\nThis file was written by ABC on %s\n", Extra_TimeStamp() ); fprintfBz2Aig( &b, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); } // close the file if (b.b) { BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL ); if (bzError == BZ_IO_ERROR) { fprintf( stdout, "Io_WriteAiger(): I/O error closing compressed stream.\n" ); fclose( b.f ); ABC_FREE(b.buf); return; } } fclose( b.f ); ABC_FREE(b.buf); } ABC_NAMESPACE_IMPL_END #include "aig/gia/giaAig.h" #include "aig/saig/saig.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteAigerCex( Abc_Cex_t * pCex, Abc_Ntk_t * pNtk, void * pG, char * pFileName ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); FILE * pFile; Aig_Man_t * pAig; Aig_Obj_t * pObj, * pObj2; Gia_Man_t * pGia = (Gia_Man_t *)pG; int k, f, b; assert( pCex != NULL ); // derive AIG if ( pNtk != NULL && Abc_NtkPiNum(pNtk) == pCex->nPis && Abc_NtkLatchNum(pNtk) == pCex->nRegs ) { pAig = Abc_NtkToDar( pNtk, 0, 1 ); } else if ( pGia != NULL && Gia_ManPiNum(pGia) == pCex->nPis && Gia_ManRegNum(pGia) == pCex->nRegs ) { pAig = Gia_ManToAigSimple( pGia ); } else { printf( "AIG parameters do not match those of the CEX.\n" ); return; } // create output file pFile = fopen( pFileName, "wb" ); fprintf( pFile, "1\n" ); b = pCex->nRegs; for ( k = 0; k < pCex->nRegs; k++ ) fprintf( pFile, "0" ); fprintf( pFile, " " ); Aig_ManCleanMarkA( pAig ); for ( f = 0; f <= pCex->iFrame; f++ ) { for ( k = 0; k < pCex->nPis; k++ ) { fprintf( pFile, "%d", Abc_InfoHasBit(pCex->pData, b) ); Aig_ManCi( pAig, k )->fMarkA = Abc_InfoHasBit(pCex->pData, b++); } fprintf( pFile, " " ); Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkA = (Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkA ^ Aig_ObjFaninC1(pObj)); Aig_ManForEachCo( pAig, pObj, k ) pObj->fMarkA = (Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj)); Saig_ManForEachPo( pAig, pObj, k ) fprintf( pFile, "%d", pObj->fMarkA ); fprintf( pFile, " " ); Saig_ManForEachLi( pAig, pObj, k ) fprintf( pFile, "%d", pObj->fMarkA ); fprintf( pFile, "\n" ); if ( f == pCex->iFrame ) break; Saig_ManForEachLi( pAig, pObj, k ) fprintf( pFile, "%d", pObj->fMarkA ); fprintf( pFile, " " ); Saig_ManForEachLiLo( pAig, pObj, pObj2, k ) pObj2->fMarkA = pObj->fMarkA; } assert( b == pCex->nBits ); fclose( pFile ); Aig_ManCleanMarkA( pAig ); Aig_ManStop( pAig ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteBaf.c000066400000000000000000000150061300674244400235560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteBaf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write AIG in the binary format.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* Binary Aig Format The motivation for this format is to have - compact binary representation of large AIGs (~10x more compact than BLIF) - consequently, fast reading/writing of large AIGs (~10x faster than BLIF) - representation for all tech-ind info related to an AIG - human-readable file header The header: (1) May contain several lines of human-readable comments. Each comment line begins with symbol '#' and ends with symbol '\n'. (2) Always contains the following data. - benchmark name - number of primary inputs - number of primary outputs - number of latches - number of AIG nodes (excluding the constant 1 node) Each entry is followed by 0-byte (character '\0'): (3) Next follow the names of the PIs, POs, and latches in this order. Each name is followed by 0-byte (character '\0'). Inside each set of names (PIs, POs, latches) there should be no identical names but the PO names may coincide with PI/latch names. The body: (1) First part of the body contains binary information about the internal AIG nodes. Each internal AIG node is represented using two edges (each edge is a 4-byte integer). Each integer is the fanin ID followed by 1-bit representation of the complemented attribute. (For example, complemented edge to node 10 will be represented as 2*10 + 1 = 21.) The IDs of the nodes are created as follows: Constant 1 node has ID=0. CIs (PIs and latch outputs) have 1-based IDs assigned in that order. Each node in the array of the internal AIG nodes has the ID assigned in that order. The constant 1 node is not written into the file. (2) Second part of the body contains binary information about the edges connecting the COs (POs and latch inputs) to the internal AIG nodes. Each edge is a 4-byte integer the same way as a node fanin. The latch initial value (2 bits) is stored in this integer. */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the AIG in the binary format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ) { ProgressBar * pProgress; FILE * pFile; Abc_Obj_t * pObj; int i, nNodes, nAnds, nBufferSize; unsigned * pBufferNode; assert( Abc_NtkIsStrash(pNtk) ); // start the output stream pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteBaf(): Cannot open the output file \"%s\".\n", pFileName ); return; } // write the comment fprintf( pFile, "# BAF (Binary Aig Format) for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the network name fprintf( pFile, "%s%c", pNtk->pName, 0 ); // write the number of PIs fprintf( pFile, "%d%c", Abc_NtkPiNum(pNtk), 0 ); // write the number of POs fprintf( pFile, "%d%c", Abc_NtkPoNum(pNtk), 0 ); // write the number of latches fprintf( pFile, "%d%c", Abc_NtkLatchNum(pNtk), 0 ); // write the number of internal nodes fprintf( pFile, "%d%c", Abc_NtkNodeNum(pNtk), 0 ); // write PIs Abc_NtkForEachPi( pNtk, pObj, i ) fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); // write POs Abc_NtkForEachPo( pNtk, pObj, i ) fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); // write latches Abc_NtkForEachLatch( pNtk, pObj, i ) { fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanin0(pObj)), 0 ); fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanout0(pObj)), 0 ); } // set the node numbers to be used in the output file Abc_NtkCleanCopy( pNtk ); nNodes = 1; Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)nNodes++; Abc_AigForEachAnd( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)nNodes++; // write the nodes into the buffer nAnds = 0; nBufferSize = Abc_NtkNodeNum(pNtk) * 2 + Abc_NtkCoNum(pNtk); pBufferNode = ABC_ALLOC( unsigned, nBufferSize ); pProgress = Extra_ProgressBarStart( stdout, nBufferSize ); Abc_AigForEachAnd( pNtk, pObj, i ) { Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); pBufferNode[nAnds++] = (((int)(ABC_PTRINT_T)Abc_ObjFanin0(pObj)->pCopy) << 1) | (int)Abc_ObjFaninC0(pObj); pBufferNode[nAnds++] = (((int)(ABC_PTRINT_T)Abc_ObjFanin1(pObj)->pCopy) << 1) | (int)Abc_ObjFaninC1(pObj); } // write the COs into the buffer Abc_NtkForEachCo( pNtk, pObj, i ) { Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); pBufferNode[nAnds] = (((int)(ABC_PTRINT_T)Abc_ObjFanin0(pObj)->pCopy) << 1) | (int)Abc_ObjFaninC0(pObj); if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) pBufferNode[nAnds] = (pBufferNode[nAnds] << 2) | ((int)(ABC_PTRINT_T)Abc_ObjData(Abc_ObjFanout0(pObj)) & 3); nAnds++; } Extra_ProgressBarStop( pProgress ); assert( nBufferSize == nAnds ); // write the buffer fwrite( pBufferNode, 1, sizeof(int) * nBufferSize, pFile ); fclose( pFile ); ABC_FREE( pBufferNode ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteBblif.c000066400000000000000000000075531300674244400241140ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteBblif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write AIG in the binary format.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteBblif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "misc/bbl/bblif.h" ABC_NAMESPACE_IMPL_START // For description of Binary BLIF format, refer to "abc/src/aig/bbl/bblif.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Fnction************************************************************* Synopsis [Construct manager from the ABC network.] Description [In the ABC network each object has a unique integer ID. This ID is used when we construct objects of the BBLIF manager corresponding to each object of the ABC network. The objects can be added to the manager in any order (although below they are added in the topological order), but by the time fanin/fanout connections are created, corresponding objects are already constructed. In the end the checking procedure is called.] SideEffects [] SeeAlso [] ***********************************************************************/ Bbl_Man_t * Bbl_ManFromAbc( Abc_Ntk_t * pNtk ) { Bbl_Man_t * p; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin; int i, k; assert( Abc_NtkIsSopLogic(pNtk) ); // start the data manager p = Bbl_ManStart( Abc_NtkName(pNtk) ); // collect internal nodes to be added vNodes = Abc_NtkDfs( pNtk, 0 ); // create combinational inputs Abc_NtkForEachCi( pNtk, pObj, i ) Bbl_ManCreateObject( p, BBL_OBJ_CI, Abc_ObjId(pObj), 0, NULL ); // create internal nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Bbl_ManCreateObject( p, BBL_OBJ_NODE, Abc_ObjId(pObj), Abc_ObjFaninNum(pObj), (char *)pObj->pData ); // create combinational outputs Abc_NtkForEachCo( pNtk, pObj, i ) Bbl_ManCreateObject( p, BBL_OBJ_CO, Abc_ObjId(pObj), 1, NULL ); // create fanin/fanout connections for internal nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) Bbl_ManAddFanin( p, Abc_ObjId(pObj), Abc_ObjId(pFanin) ); // create fanin/fanout connections for combinational outputs Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) Bbl_ManAddFanin( p, Abc_ObjId(pObj), Abc_ObjId(pFanin) ); Vec_PtrFree( vNodes ); // sanity check Bbl_ManCheck( p ); return p; } /**Function************************************************************* Synopsis [Writes the AIG in the binary format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBblif( Abc_Ntk_t * pNtk, char * pFileName ) { Bbl_Man_t * p; p = Bbl_ManFromAbc( pNtk ); //Bbl_ManPrintStats( p ); //Bbl_ManDumpBlif( p, "test_bbl.blif" ); Bbl_ManDumpBinaryBlif( p, pFileName ); Bbl_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteBench.c000066400000000000000000000247221300674244400241120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteBench.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write the network in BENCH format.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ); static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ); static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ); static int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ); static int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the network in BENCH format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteBench( Abc_Ntk_t * pNtk, const char * pFileName ) { Abc_Ntk_t * pExdc; FILE * pFile; assert( Abc_NtkIsSopNetlist(pNtk) ); if ( !Io_WriteBenchCheckNames(pNtk) ) { fprintf( stdout, "Io_WriteBench(): Signal names in this benchmark contain parentheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); return 0; } pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); return 0; } fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the network Io_WriteBenchOne( pFile, pNtk ); // write EXDC network if it exists pExdc = Abc_NtkExdc( pNtk ); if ( pExdc ) printf( "Io_WriteBench: EXDC is not written (warning).\n" ); // finalize the file fclose( pFile ); return 1; } /**Function************************************************************* Synopsis [Writes the network in BENCH format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Obj_t * pNode; int i; // write the PIs/POs/latches Abc_NtkForEachPi( pNtk, pNode, i ) fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); Abc_NtkForEachPo( pNtk, pNode, i ) fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); Abc_NtkForEachLatch( pNtk, pNode, i ) fprintf( pFile, "%-11s = DFF(%s)\n", Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); // write internal nodes pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Io_WriteBenchOneNode( pFile, pNode ); } Extra_ProgressBarStop( pProgress ); return 1; } /**Function************************************************************* Synopsis [Writes the network in BENCH format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ) { int nFanins; assert( Abc_ObjIsNode(pNode) ); nFanins = Abc_ObjFaninNum(pNode); if ( nFanins == 0 ) { // write the constant 1 node assert( Abc_NodeIsConst1(pNode) ); fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, " = vdd\n" ); } else if ( nFanins == 1 ) { // write the interver/buffer if ( Abc_NodeIsBuf(pNode) ) { fprintf( pFile, "%-11s = BUFF(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); } else { fprintf( pFile, "%-11s = NOT(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); } } else { // write the AND gate fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, " = AND(%s, ", Abc_ObjName(Abc_ObjFanin0(pNode)) ); fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin1(pNode)) ); } return 1; } /**Function************************************************************* Synopsis [Writes the network in BENCH format with LUTs and DFFRSE.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * pFileName ) { Abc_Ntk_t * pExdc; FILE * pFile; assert( Abc_NtkIsAigNetlist(pNtk) ); if ( !Io_WriteBenchCheckNames(pNtk) ) { fprintf( stdout, "Io_WriteBenchLut(): Signal names in this benchmark contain parentheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); return 0; } pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); return 0; } fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the network Io_WriteBenchLutOne( pFile, pNtk ); // write EXDC network if it exists pExdc = Abc_NtkExdc( pNtk ); if ( pExdc ) printf( "Io_WriteBench: EXDC is not written (warning).\n" ); // finalize the file fclose( pFile ); return 1; } /**Function************************************************************* Synopsis [Writes the network in BENCH format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Obj_t * pNode; Vec_Int_t * vMemory; int i; // write the PIs/POs/latches Abc_NtkForEachPi( pNtk, pNode, i ) fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); Abc_NtkForEachPo( pNtk, pNode, i ) fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); Abc_NtkForEachLatch( pNtk, pNode, i ) fprintf( pFile, "%-11s = DFFRSE( %s, gnd, gnd, gnd, gnd )\n", Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); //Abc_NtkLevel(pNtk); // write internal nodes vMemory = Vec_IntAlloc( 10000 ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Io_WriteBenchLutOneNode( pFile, pNode, vMemory ); } Extra_ProgressBarStop( pProgress ); Vec_IntFree( vMemory ); return 1; } /**Function************************************************************* Synopsis [Writes the network in BENCH format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ) { Abc_Obj_t * pFanin; unsigned * pTruth; int i, nFanins; assert( Abc_ObjIsNode(pNode) ); nFanins = Abc_ObjFaninNum(pNode); assert( nFanins <= 8 ); // compute the truth table pTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNode->pNtk->pManFunc, Hop_Regular((Hop_Obj_t *)pNode->pData), nFanins, vTruth, 0 ); if ( Hop_IsComplement((Hop_Obj_t *)pNode->pData) ) Extra_TruthNot( pTruth, pTruth, nFanins ); // consider simple cases if ( Extra_TruthIsConst0(pTruth, nFanins) ) { fprintf( pFile, "%-11s = gnd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return 1; } if ( Extra_TruthIsConst1(pTruth, nFanins) ) { fprintf( pFile, "%-11s = vdd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return 1; } if ( nFanins == 1 ) { fprintf( pFile, "%-11s = LUT 0x%d ( %s )\n", Abc_ObjName(Abc_ObjFanout0(pNode)), Abc_NodeIsBuf(pNode)? 2 : 1, Abc_ObjName(Abc_ObjFanin0(pNode)) ); return 1; } // write it in the hexadecimal form fprintf( pFile, "%-11s = LUT 0x", Abc_ObjName(Abc_ObjFanout0(pNode)) ); Extra_PrintHexadecimal( pFile, pTruth, nFanins ); /* { extern void Kit_DsdTest( unsigned * pTruth, int nVars ); Abc_ObjForEachFanin( pNode, pFanin, i ) printf( "%c%d ", 'a'+i, Abc_ObjFanin0(pFanin)->Level ); printf( "\n" ); Kit_DsdTest( pTruth, nFanins ); } if ( pNode->Id % 1000 == 0 ) { int x = 0; } */ // write the fanins fprintf( pFile, " (" ); Abc_ObjForEachFanin( pNode, pFanin, i ) fprintf( pFile, " %s%s", Abc_ObjName(pFanin), ((i==nFanins-1)? "" : ",") ); fprintf( pFile, " )\n" ); return 1; } /**Function************************************************************* Synopsis [Returns 1 if the names cannot be written into the bench file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; char * pName; int i; Abc_NtkForEachObj( pNtk, pObj, i ) for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ ) if ( *pName == '(' || *pName == ')' ) return 0; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteBlif.c000066400000000000000000001342361300674244400237510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteBlif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write BLIF files.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/main/main.h" #include "map/mio/mio.h" #include "bool/kit/kit.h" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq ); static void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq ); static void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); static void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); static void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ); static void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); static int Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ); static void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Write the network into a BLIF file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) { Abc_Ntk_t * pNtkTemp; // derive the netlist pNtkTemp = Abc_NtkToNetlist(pNtk); if ( pNtkTemp == NULL ) { fprintf( stdout, "Writing BLIF has failed.\n" ); return; } Io_WriteBlif( pNtkTemp, FileName, fWriteLatches, 0, 0 ); Abc_NtkDelete( pNtkTemp ); } /**Function************************************************************* Synopsis [Write the network into a BLIF file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches, int fBb2Wb, int fSeq ) { FILE * pFile; Abc_Ntk_t * pNtkTemp; int i; assert( Abc_NtkIsNetlist(pNtk) ); // start writing the file pFile = fopen( FileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteBlif(): Cannot open the output file.\n" ); return; } fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the master network Io_NtkWrite( pFile, pNtk, fWriteLatches, fBb2Wb, fSeq ); // make sure there is no logic hierarchy // assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); // write the hierarchy if present if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) { Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNtkTemp, i ) { if ( pNtkTemp == pNtk ) continue; fprintf( pFile, "\n\n" ); Io_NtkWrite( pFile, pNtkTemp, fWriteLatches, fBb2Wb, fSeq ); } } fclose( pFile ); } /**Function************************************************************* Synopsis [Write the network into a BLIF file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq ) { Abc_Ntk_t * pExdc; assert( Abc_NtkIsNetlist(pNtk) ); // write the model name fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); // write the network Io_NtkWriteOne( pFile, pNtk, fWriteLatches, fBb2Wb, fSeq ); // write EXDC network if it exists pExdc = Abc_NtkExdc( pNtk ); if ( pExdc ) { fprintf( pFile, "\n" ); fprintf( pFile, ".exdc\n" ); Io_NtkWriteOne( pFile, pExdc, fWriteLatches, fBb2Wb, fSeq ); } // finalize the file fprintf( pFile, ".end\n" ); } /**Function************************************************************* Synopsis [Write one network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteConvertedBox( FILE * pFile, Abc_Ntk_t * pNtk, int fSeq ) { Abc_Obj_t * pObj; int i, v; if ( fSeq ) { fprintf( pFile, ".attrib white box seq\n" ); } else { fprintf( pFile, ".attrib white box comb\n" ); fprintf( pFile, ".delay 1\n" ); } Abc_NtkForEachPo( pNtk, pObj, i ) { // write the .names line fprintf( pFile, ".names" ); Io_NtkWritePis( pFile, pNtk, 1 ); if ( fSeq ) fprintf( pFile, " %s_in\n", Abc_ObjName(Abc_ObjFanin0(pObj)) ); else fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanin0(pObj)) ); for ( v = 0; v < Abc_NtkPiNum(pNtk); v++ ) fprintf( pFile, "1" ); fprintf( pFile, " 1\n" ); if ( fSeq ) fprintf( pFile, ".latch %s_in %s 1\n", Abc_ObjName(Abc_ObjFanin0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); } } /**Function************************************************************* Synopsis [Write one network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches, int fBb2Wb, int fSeq ) { ProgressBar * pProgress; Abc_Obj_t * pNode, * pLatch; int i, Length; // write the PIs fprintf( pFile, ".inputs" ); Io_NtkWritePis( pFile, pNtk, fWriteLatches ); fprintf( pFile, "\n" ); // write the POs fprintf( pFile, ".outputs" ); Io_NtkWritePos( pFile, pNtk, fWriteLatches ); fprintf( pFile, "\n" ); // write the blackbox if ( Abc_NtkHasBlackbox( pNtk ) ) { if ( fBb2Wb ) Io_NtkWriteConvertedBox( pFile, pNtk, fSeq ); else fprintf( pFile, ".blackbox\n" ); return; } // write the timing info Io_WriteTimingInfo( pFile, pNtk ); // write the latches if ( fWriteLatches && !Abc_NtkIsComb(pNtk) ) { fprintf( pFile, "\n" ); Abc_NtkForEachLatch( pNtk, pLatch, i ) Io_NtkWriteLatch( pFile, pLatch ); fprintf( pFile, "\n" ); } // write the subcircuits // assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) { fprintf( pFile, "\n" ); Abc_NtkForEachBlackbox( pNtk, pNode, i ) Io_NtkWriteSubckt( pFile, pNode ); fprintf( pFile, "\n" ); Abc_NtkForEachWhitebox( pNtk, pNode, i ) Io_NtkWriteSubckt( pFile, pNode ); fprintf( pFile, "\n" ); } // write each internal node Length = Abc_NtkHasMapping(pNtk)? Mio_LibraryReadGateNameMax((Mio_Library_t *)pNtk->pManFunc) : 0; pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( Io_NtkWriteNode( pFile, pNode, Length ) ) // skip the next node i++; } Extra_ProgressBarStop( pProgress ); } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) { Abc_Obj_t * pTerm, * pNet; int LineLength; int AddedLength; int NameCounter; int i; LineLength = 7; NameCounter = 0; if ( fWriteLatches ) { Abc_NtkForEachPi( pNtk, pTerm, i ) { pNet = Abc_ObjFanout0(pTerm); // get the line length after this name is written AddedLength = strlen(Abc_ObjName(pNet)) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", Abc_ObjName(pNet) ); LineLength += AddedLength; NameCounter++; } } else { Abc_NtkForEachCi( pNtk, pTerm, i ) { pNet = Abc_ObjFanout0(pTerm); // get the line length after this name is written AddedLength = strlen(Abc_ObjName(pNet)) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", Abc_ObjName(pNet) ); LineLength += AddedLength; NameCounter++; } } } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) { Abc_Obj_t * pTerm, * pNet; int LineLength; int AddedLength; int NameCounter; int i; LineLength = 8; NameCounter = 0; if ( fWriteLatches ) { Abc_NtkForEachPo( pNtk, pTerm, i ) { pNet = Abc_ObjFanin0(pTerm); // get the line length after this name is written AddedLength = strlen(Abc_ObjName(pNet)) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", Abc_ObjName(pNet) ); LineLength += AddedLength; NameCounter++; } } else { Abc_NtkForEachCo( pNtk, pTerm, i ) { pNet = Abc_ObjFanin0(pTerm); // get the line length after this name is written AddedLength = strlen(Abc_ObjName(pNet)) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", Abc_ObjName(pNet) ); LineLength += AddedLength; NameCounter++; } } } /**Function************************************************************* Synopsis [Write the latch into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ) { Abc_Ntk_t * pModel = (Abc_Ntk_t *)pNode->pData; Abc_Obj_t * pTerm; int i; // write the subcircuit // fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); fprintf( pFile, ".subckt %s", Abc_NtkName(pModel) ); // write pairs of the formal=actual names Abc_NtkForEachPi( pModel, pTerm, i ) { fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); pTerm = Abc_ObjFanin( pNode, i ); fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); } Abc_NtkForEachPo( pModel, pTerm, i ) { fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); pTerm = Abc_ObjFanout( pNode, i ); fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); } fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Write the latch into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ) { Abc_Obj_t * pNetLi, * pNetLo; int Reset; pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); Reset = (int)(ABC_PTRUINT_T)Abc_ObjData( pLatch ); // write the latch line fprintf( pFile, ".latch" ); fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); fprintf( pFile, " %d\n", Reset-1 ); } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) { Abc_Obj_t * pNet; int LineLength; int AddedLength; int NameCounter; char * pName; int i; LineLength = 6; NameCounter = 0; Abc_ObjForEachFanin( pNode, pNet, i ) { // get the fanin name pName = Abc_ObjName(pNet); // get the line length after the fanin name is written AddedLength = strlen(pName) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", pName ); LineLength += AddedLength; NameCounter++; } // get the output name pName = Abc_ObjName(Abc_ObjFanout0(pNode)); // get the line length after the output name is written AddedLength = strlen(pName) + 1; if ( NameCounter && LineLength + AddedLength > 75 ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", pName ); } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteSubcktFanins( FILE * pFile, Abc_Obj_t * pNode ) { Abc_Obj_t * pNet; int LineLength; int AddedLength; int NameCounter; char * pName; int i; LineLength = 6; NameCounter = 0; // get the output name pName = Abc_ObjName(Abc_ObjFanout0(pNode)); // get the line length after the output name is written AddedLength = strlen(pName) + 1; fprintf( pFile, " m%d", Abc_ObjId(pNode) ); // get the input names Abc_ObjForEachFanin( pNode, pNet, i ) { // get the fanin name pName = Abc_ObjName(pNet); // get the line length after the fanin name is written AddedLength = strlen(pName) + 3; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %c=%s", 'a'+i, pName ); LineLength += AddedLength; NameCounter++; } // get the output name pName = Abc_ObjName(Abc_ObjFanout0(pNode)); // get the line length after the output name is written AddedLength = strlen(pName) + 3; if ( NameCounter && LineLength + AddedLength > 75 ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %c=%s", 'o', pName ); } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) { static int fReport = 0; Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData; Mio_Pin_t * pGatePin; Abc_Obj_t * pNode2; int i; fprintf( pFile, " %-*s ", Length, Mio_GateReadName(pGate) ); for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) fprintf( pFile, "%s=%s ", Mio_PinReadName(pGatePin), Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); assert ( i == Abc_ObjFaninNum(pNode) ); fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName( Abc_ObjFanout0(pNode) ) ); if ( Mio_GateReadTwin(pGate) == NULL ) return 0; pNode2 = Abc_NtkFetchTwinNode( pNode ); if ( pNode2 == NULL ) { if ( !fReport ) fReport = 1, printf( "Warning: Missing second output of gate(s) \"%s\".\n", Mio_GateReadName(pGate) ); return 0; } fprintf( pFile, " %s=%s", Mio_GateReadOutName((Mio_Gate_t *)pNode2->pData), Abc_ObjName( Abc_ObjFanout0(pNode2) ) ); return 1; } /**Function************************************************************* Synopsis [Write the node into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ) { int RetValue = 0; if ( Abc_NtkHasMapping(pNode->pNtk) ) { // write the .gate line if ( Abc_ObjIsBarBuf(pNode) ) { fprintf( pFile, ".barbuf " ); fprintf( pFile, "%s %s", Abc_ObjName(Abc_ObjFanin0(pNode)), Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, "\n" ); } else { fprintf( pFile, ".gate" ); RetValue = Io_NtkWriteNodeGate( pFile, pNode, Length ); fprintf( pFile, "\n" ); } } else { // write the .names line fprintf( pFile, ".names" ); Io_NtkWriteNodeFanins( pFile, pNode ); fprintf( pFile, "\n" ); // write the cubes fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) ); } return RetValue; } /**Function************************************************************* Synopsis [Write the node into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_NtkWriteNodeSubckt( FILE * pFile, Abc_Obj_t * pNode, int Length ) { int RetValue = 0; fprintf( pFile, ".subckt" ); Io_NtkWriteSubcktFanins( pFile, pNode ); fprintf( pFile, "\n" ); return RetValue; } /**Function************************************************************* Synopsis [Writes the timing info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; Abc_Time_t * pTime, * pTimeDefIn, * pTimeDefOut; int i; if ( pNtk->pManTime == NULL ) return; fprintf( pFile, "\n" ); if ( pNtk->AndGateDelay != 0.0 ) fprintf( pFile, ".and_gate_delay %g\n", pNtk->AndGateDelay ); pTimeDefIn = Abc_NtkReadDefaultArrival( pNtk ); //if ( pTimeDefIn->Rise != 0.0 || pTimeDefIn->Fall != 0.0 ) fprintf( pFile, ".default_input_arrival %g %g\n", pTimeDefIn->Rise, pTimeDefIn->Fall ); pTimeDefOut = Abc_NtkReadDefaultRequired( pNtk ); //if ( pTimeDefOut->Rise != ABC_INFINITY || pTimeDefOut->Fall != ABC_INFINITY ) fprintf( pFile, ".default_output_required %g %g\n", pTimeDefOut->Rise, pTimeDefOut->Fall ); fprintf( pFile, "\n" ); Abc_NtkForEachPi( pNtk, pNode, i ) { pTime = Abc_NodeReadArrival(pNode); if ( pTime->Rise == pTimeDefIn->Rise && pTime->Fall == pTimeDefIn->Fall ) continue; fprintf( pFile, ".input_arrival %s %g %g\n", Abc_ObjName(Abc_ObjFanout0(pNode)), pTime->Rise, pTime->Fall ); } Abc_NtkForEachPo( pNtk, pNode, i ) { pTime = Abc_NodeReadRequired(pNode); if ( pTime->Rise == pTimeDefOut->Rise && pTime->Fall == pTimeDefOut->Fall ) continue; fprintf( pFile, ".output_required %s %g %g\n", Abc_ObjName(Abc_ObjFanin0(pNode)), pTime->Rise, pTime->Fall ); } fprintf( pFile, "\n" ); pTimeDefIn = Abc_NtkReadDefaultInputDrive( pNtk ); if ( pTimeDefIn->Rise != 0.0 || pTimeDefIn->Fall != 0.0 ) fprintf( pFile, ".default_input_drive %g %g\n", pTimeDefIn->Rise, pTimeDefIn->Fall ); if ( Abc_NodeReadInputDrive( pNtk, 0 ) ) Abc_NtkForEachPi( pNtk, pNode, i ) { pTime = Abc_NodeReadInputDrive( pNtk, i ); if ( pTime->Rise == pTimeDefIn->Rise && pTime->Fall == pTimeDefIn->Fall ) continue; fprintf( pFile, ".input_drive %s %g %g\n", Abc_ObjName(Abc_ObjFanout0(pNode)), pTime->Rise, pTime->Fall ); } pTimeDefOut = Abc_NtkReadDefaultOutputLoad( pNtk ); if ( pTimeDefOut->Rise != 0.0 || pTimeDefOut->Fall != 0.0 ) fprintf( pFile, ".default_output_load %g %g\n", pTimeDefOut->Rise, pTimeDefOut->Fall ); if ( Abc_NodeReadOutputLoad( pNtk, 0 ) ) Abc_NtkForEachPo( pNtk, pNode, i ) { pTime = Abc_NodeReadOutputLoad( pNtk, i ); if ( pTime->Rise == pTimeDefOut->Rise && pTime->Fall == pTimeDefOut->Fall ) continue; fprintf( pFile, ".output_load %s %g %g\n", Abc_ObjName(Abc_ObjFanin0(pNode)), pTime->Rise, pTime->Fall ); } fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkConvertBb2Wb( char * pFileNameIn, char * pFileNameOut, int fSeq, int fVerbose ) { FILE * pFile; Abc_Ntk_t * pNetlist; // check the files pFile = fopen( pFileNameIn, "rb" ); if ( pFile == NULL ) { printf( "Input file \"%s\" cannot be opened.\n", pFileNameIn ); return; } fclose( pFile ); // check the files pFile = fopen( pFileNameOut, "wb" ); if ( pFile == NULL ) { printf( "Output file \"%s\" cannot be opened.\n", pFileNameOut ); return; } fclose( pFile ); // derive AIG for signal correspondence pNetlist = Io_ReadNetlist( pFileNameIn, Io_ReadFileType(pFileNameIn), 1 ); if ( pNetlist == NULL ) { printf( "Reading input file \"%s\" has failed.\n", pFileNameIn ); return; } Io_WriteBlif( pNetlist, pFileNameOut, 1, 1, fSeq ); Abc_NtkDelete( pNetlist ); } /**Function************************************************************* Synopsis [Transforms truth table into an SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Io_NtkDeriveSop( Mem_Flex_t * pMem, word uTruth, int nVars, Vec_Int_t * vCover ) { char * pSop; int RetValue = Kit_TruthIsop( (unsigned *)&uTruth, nVars, vCover, 1 ); assert( RetValue == 0 || RetValue == 1 ); // check the case of constant cover if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) { char * pStr0 = " 0\n", * pStr1 = " 1\n"; assert( RetValue == 0 ); return Vec_IntSize(vCover) == 0 ? pStr0 : pStr1; } // derive the AIG for that tree pSop = Abc_SopCreateFromIsop( pMem, nVars, vCover ); if ( RetValue ) Abc_SopComplement( pSop ); return pSop; } /**Function************************************************************* Synopsis [Write the node into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteNodeInt( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover ) { Abc_Obj_t * pNet; int i, nVars = Abc_ObjFaninNum(pNode); if ( nVars > 7 ) { printf( "Node \"%s\" has more than 7 inputs. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return; } fprintf( pFile, "\n" ); if ( nVars <= 4 ) { // write the .names line fprintf( pFile, ".names" ); Abc_ObjForEachFanin( pNode, pNet, i ) fprintf( pFile, " %s", Abc_ObjName(pNet) ); // get the output name fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); // write the cubes fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) ); } else { extern int If_Dec6PickBestMux( word t, word Cofs[2] ); extern int If_Dec7PickBestMux( word t[2], word c0r[2], word c1r[2] ); extern word If_Dec6MinimumBase( word uTruth, int * pSupp, int nVarsAll, int * pnVars ); extern void If_Dec7MinimumBase( word uTruth[2], int * pSupp, int nVarsAll, int * pnVars ); extern word If_Dec6Perform( word t, int fDerive ); extern word If_Dec7Perform( word t[2], int fDerive ); char * pSop; word z, uTruth6 = 0, uTruth7[2], Cofs6[2], Cofs7[2][2]; int c, iVar, nVarsMin[2], pVars[2][10]; // collect variables Abc_ObjForEachFanin( pNode, pNet, i ) pVars[0][i] = pVars[1][i] = i; // derive truth table if ( nVars == 7 ) { Abc_SopToTruth7( (char*)Abc_ObjData(pNode), nVars, uTruth7 ); iVar = If_Dec7PickBestMux( uTruth7, Cofs7[0], Cofs7[1] ); } else { uTruth6 = Abc_SopToTruth( (char*)Abc_ObjData(pNode), nVars ); iVar = If_Dec6PickBestMux( uTruth6, Cofs6 ); } // perform MUX decomposition if ( iVar >= 0 ) { if ( nVars == 7 ) { If_Dec7MinimumBase( Cofs7[0], pVars[0], nVars, &nVarsMin[0] ); If_Dec7MinimumBase( Cofs7[1], pVars[1], nVars, &nVarsMin[1] ); } else { Cofs6[0] = If_Dec6MinimumBase( Cofs6[0], pVars[0], nVars, &nVarsMin[0] ); Cofs6[1] = If_Dec6MinimumBase( Cofs6[1], pVars[1], nVars, &nVarsMin[1] ); } assert( nVarsMin[0] < 5 ); assert( nVarsMin[1] < 5 ); // write MUX fprintf( pFile, ".names" ); fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,iVar)) ); fprintf( pFile, " %s_cascade0", Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, " %s_cascade1", Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, "1-1 1\n01- 1\n" ); // write cofactors for ( c = 0; c < 2; c++ ) { pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, (word)(nVars == 7 ? Cofs7[c][0] : Cofs6[c]), nVarsMin[c], vCover ); fprintf( pFile, ".names" ); for ( i = 0; i < nVarsMin[c]; i++ ) fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pVars[c][i])) ); fprintf( pFile, " %s_cascade%d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), c ); fprintf( pFile, "%s", pSop ); } return; } assert( nVars == 6 || nVars == 7 ); // try cascade decomposition if ( nVars == 7 ) { z = If_Dec7Perform( uTruth7, 1 ); //If_Dec7Verify( uTruth7, z ); } else { z = If_Dec6Perform( uTruth6, 1 ); //If_Dec6Verify( uTruth6, z ); } if ( z == 0 ) { printf( "Node \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return; } // derive nodes for ( c = 1; c >= 0; c-- ) { // collect fanins uTruth7[c] = ((c ? z >> 32 : z) & 0xffff); uTruth7[c] |= (uTruth7[c] << 16); uTruth7[c] |= (uTruth7[c] << 32); for ( i = 0; i < 4; i++ ) pVars[c][i] = (z >> (c*32+16+4*i)) & 7; // minimize truth table Cofs6[c] = If_Dec6MinimumBase( uTruth7[c], pVars[c], 4, &nVarsMin[c] ); // write the nodes fprintf( pFile, ".names" ); for ( i = 0; i < nVarsMin[c]; i++ ) if ( pVars[c][i] == 7 ) fprintf( pFile, " %s_cascade", Abc_ObjName(Abc_ObjFanout0(pNode)) ); else fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pVars[c][i])) ); fprintf( pFile, " %s%s\n", Abc_ObjName(Abc_ObjFanout0(pNode)), c? "" : "_cascade" ); // write SOP pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, (word)Cofs6[c], nVarsMin[c], vCover ); fprintf( pFile, "%s", pSop ); } } } /**Function************************************************************* Synopsis [Write the node into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteNodeIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover, char * pStr ) { Abc_Obj_t * pNet; int nLeaves = Abc_ObjFaninNum(pNode); int i, nLutLeaf, nLutLeaf2, nLutRoot, Length; // quit if parameters are wrong Length = strlen(pStr); if ( Length != 2 && Length != 3 ) { printf( "Wrong LUT struct (%s)\n", pStr ); return; } 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; } 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; } // consider easy case fprintf( pFile, "\n" ); if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) ) { // write the .names line fprintf( pFile, ".names" ); Abc_ObjForEachFanin( pNode, pNet, i ) fprintf( pFile, " %s", Abc_ObjName(pNet) ); // get the output name fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); // write the cubes fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) ); return; } else { extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ); static word TruthStore[16][1<<10] = {{0}}, * pTruths[16]; word pCube[1<<10], pRes[1<<10], Func0, Func1, Func2; char pLut0[32], pLut1[32], pLut2[32] = {0}, * pSop; // int nVarsMin[3], pVars[3][20]; if ( TruthStore[0][0] == 0 ) { static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(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; } // collect variables // Abc_ObjForEachFanin( pNode, pNet, i ) // pVars[0][i] = pVars[1][i] = pVars[2][i] = i; // derive truth table Abc_SopToTruthBig( (char*)Abc_ObjData(pNode), nLeaves, pTruths, pCube, pRes ); if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ) { fprintf( pFile, ".names %s\n %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); return; } // Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); // Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); // perform decomposition if ( Length == 2 ) { 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 \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return; } } else { if ( !If_CluCheckExt3( NULL, 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 \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return; } } // write leaf node fprintf( pFile, ".names" ); for ( i = 0; i < pLut1[0]; i++ ) fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut1[2+i])) ); fprintf( pFile, " %s_lut1\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); // write SOP pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func1, pLut1[0], vCover ); fprintf( pFile, "%s", pSop ); if ( Length == 3 && pLut2[0] > 0 ) { // write leaf node fprintf( pFile, ".names" ); for ( i = 0; i < pLut2[0]; i++ ) if ( pLut2[2+i] == nLeaves ) fprintf( pFile, " %s_lut1", Abc_ObjName(Abc_ObjFanout0(pNode)) ); else fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut2[2+i])) ); fprintf( pFile, " %s_lut2\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); // write SOP pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func2, pLut2[0], vCover ); fprintf( pFile, "%s", pSop ); } // write root node fprintf( pFile, ".names" ); for ( i = 0; i < pLut0[0]; i++ ) if ( pLut0[2+i] == nLeaves ) fprintf( pFile, " %s_lut1", Abc_ObjName(Abc_ObjFanout0(pNode)) ); else if ( pLut0[2+i] == nLeaves+1 ) fprintf( pFile, " %s_lut2", Abc_ObjName(Abc_ObjFanout0(pNode)) ); else fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin(pNode,pLut0[2+i])) ); fprintf( pFile, " %s\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); // write SOP pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func0, pLut0[0], vCover ); fprintf( pFile, "%s", pSop ); } } /**Function************************************************************* Synopsis [Write the node into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteModelIntStruct( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vCover, char * pStr ) { Abc_Obj_t * pNet; int nLeaves = Abc_ObjFaninNum(pNode); int i, nLutLeaf, nLutLeaf2, nLutRoot, Length; // write the header fprintf( pFile, "\n" ); fprintf( pFile, ".model m%d\n", Abc_ObjId(pNode) ); fprintf( pFile, ".inputs" ); for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) fprintf( pFile, " %c", 'a' + i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs o\n" ); // quit if parameters are wrong Length = strlen(pStr); if ( Length != 2 && Length != 3 ) { printf( "Wrong LUT struct (%s)\n", pStr ); return; } 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; } 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; } // consider easy case if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) ) { // write the .names line fprintf( pFile, ".names" ); Abc_ObjForEachFanin( pNode, pNet, i ) fprintf( pFile, " %c", 'a' + i ); // get the output name fprintf( pFile, " %s\n", "o" ); // write the cubes fprintf( pFile, "%s", (char*)Abc_ObjData(pNode) ); fprintf( pFile, ".end\n" ); return; } else { extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ); static word TruthStore[16][1<<10] = {{0}}, * pTruths[16]; word pCube[1<<10], pRes[1<<10], Func0, Func1, Func2; char pLut0[32], pLut1[32], pLut2[32] = {0}, * pSop; // int nVarsMin[3], pVars[3][20]; if ( TruthStore[0][0] == 0 ) { static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(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; } // collect variables // Abc_ObjForEachFanin( pNode, pNet, i ) // pVars[0][i] = pVars[1][i] = pVars[2][i] = i; // derive truth table Abc_SopToTruthBig( (char*)Abc_ObjData(pNode), nLeaves, pTruths, pCube, pRes ); if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ) { fprintf( pFile, ".names %s\n %d\n", "o", Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); fprintf( pFile, ".end\n" ); return; } // Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); // Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); // perform decomposition if ( Length == 2 ) { 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 \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return; } } else { if ( !If_CluCheckExt3( NULL, 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 \"%s\" is not decomposable. Writing BLIF has failed.\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return; } } // write leaf node fprintf( pFile, ".names" ); for ( i = 0; i < pLut1[0]; i++ ) fprintf( pFile, " %c", 'a' + pLut1[2+i] ); fprintf( pFile, " lut1\n" ); // write SOP pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func1, pLut1[0], vCover ); fprintf( pFile, "%s", pSop ); if ( Length == 3 && pLut2[0] > 0 ) { // write leaf node fprintf( pFile, ".names" ); for ( i = 0; i < pLut2[0]; i++ ) if ( pLut2[2+i] == nLeaves ) fprintf( pFile, " lut1" ); else fprintf( pFile, " %c", 'a' + pLut2[2+i] ); fprintf( pFile, " lut2\n" ); // write SOP pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func2, pLut2[0], vCover ); fprintf( pFile, "%s", pSop ); } // write root node fprintf( pFile, ".names" ); for ( i = 0; i < pLut0[0]; i++ ) if ( pLut0[2+i] == nLeaves ) fprintf( pFile, " lut1" ); else if ( pLut0[2+i] == nLeaves+1 ) fprintf( pFile, " lut2" ); else fprintf( pFile, " %c", 'a' + pLut0[2+i] ); fprintf( pFile, " %s\n", "o" ); // write SOP pSop = Io_NtkDeriveSop( (Mem_Flex_t *)Abc_ObjNtk(pNode)->pManFunc, Func0, pLut0[0], vCover ); fprintf( pFile, "%s", pSop ); fprintf( pFile, ".end\n" ); } } /**Function************************************************************* Synopsis [Write the network into a BLIF file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBlifInt( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie ) { FILE * pFile; Vec_Int_t * vCover; Abc_Obj_t * pNode, * pLatch; int i; assert( Abc_NtkIsNetlist(pNtk) ); // start writing the file pFile = fopen( FileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteBlifInt(): Cannot open the output file.\n" ); return; } fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the model name fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); // write the PIs fprintf( pFile, ".inputs" ); Io_NtkWritePis( pFile, pNtk, 1 ); fprintf( pFile, "\n" ); // write the POs fprintf( pFile, ".outputs" ); Io_NtkWritePos( pFile, pNtk, 1 ); fprintf( pFile, "\n" ); // write the latches if ( Abc_NtkLatchNum(pNtk) ) fprintf( pFile, "\n" ); Abc_NtkForEachLatch( pNtk, pLatch, i ) Io_NtkWriteLatch( pFile, pLatch ); if ( Abc_NtkLatchNum(pNtk) ) fprintf( pFile, "\n" ); // write the hierarchy vCover = Vec_IntAlloc( (1<<16) ); if ( fUseHie ) { // write each internal node fprintf( pFile, "\n" ); Abc_NtkForEachNode( pNtk, pNode, i ) Io_NtkWriteNodeSubckt( pFile, pNode, 0 ); fprintf( pFile, ".end\n\n" ); // write models Abc_NtkForEachNode( pNtk, pNode, i ) Io_NtkWriteModelIntStruct( pFile, pNode, vCover, pLutStruct ); fprintf( pFile, "\n" ); } else { // write each internal node Abc_NtkForEachNode( pNtk, pNode, i ) { if ( pLutStruct ) Io_NtkWriteNodeIntStruct( pFile, pNode, vCover, pLutStruct ); else Io_NtkWriteNodeInt( pFile, pNode, vCover ); } fprintf( pFile, ".end\n\n" ); } Vec_IntFree( vCover ); fclose( pFile ); } /**Function************************************************************* Synopsis [Write the network into a BLIF file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, int fUseHie ) { Abc_Ntk_t * pNtkTemp; assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); // derive the netlist pNtkTemp = Abc_NtkToNetlist(pNtk); if ( pNtkTemp == NULL ) { fprintf( stdout, "Writing BLIF has failed.\n" ); return; } if ( pLutStruct && fUseHie ) Io_WriteBlifInt( pNtkTemp, FileName, pLutStruct, 1 ); else Io_WriteBlifInt( pNtkTemp, FileName, pLutStruct, 0 ); Abc_NtkDelete( pNtkTemp ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteBlifMv.c000066400000000000000000000334421300674244400242510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteBlifMv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write BLIF-MV files.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/main/main.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); static void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ); static void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ); static void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ); static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Write the network into a BLIF file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ) { FILE * pFile; Abc_Ntk_t * pNtkTemp; int i; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_NtkHasBlifMv(pNtk) ); // start writing the file pFile = fopen( FileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" ); return; } fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the master network Io_NtkWriteBlifMv( pFile, pNtk ); // write the remaining networks if ( pNtk->pDesign ) { Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNtkTemp, i ) { if ( pNtkTemp == pNtk ) continue; fprintf( pFile, "\n\n" ); Io_NtkWriteBlifMv( pFile, pNtkTemp ); } } fclose( pFile ); } /**Function************************************************************* Synopsis [Write the network into a BLIF file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ) { assert( Abc_NtkIsNetlist(pNtk) ); // write the model name fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); // write the network Io_NtkWriteBlifMvOne( pFile, pNtk ); // write EXDC network if it exists if ( Abc_NtkExdc(pNtk) ) printf( "Io_NtkWriteBlifMv(): EXDC is not written.\n" ); // finalize the file fprintf( pFile, ".end\n\n\n" ); } /**Function************************************************************* Synopsis [Write one network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Obj_t * pNode, * pTerm, * pLatch; int i; // write the PIs fprintf( pFile, ".inputs" ); Io_NtkWriteBlifMvPis( pFile, pNtk ); fprintf( pFile, "\n" ); // write the POs fprintf( pFile, ".outputs" ); Io_NtkWriteBlifMvPos( pFile, pNtk ); fprintf( pFile, "\n" ); // write the MV directives fprintf( pFile, "\n" ); Abc_NtkForEachCi( pNtk, pTerm, i ) if ( Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) > 2 ) fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) ); Abc_NtkForEachCo( pNtk, pTerm, i ) if ( Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) > 2 ) fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanin0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) ); // write the blackbox if ( Abc_NtkHasBlackbox( pNtk ) ) { fprintf( pFile, ".blackbox\n" ); return; } // write the timing info // Io_WriteTimingInfo( pFile, pNtk ); // write the latches if ( !Abc_NtkIsComb(pNtk) ) { fprintf( pFile, "\n" ); Abc_NtkForEachLatch( pNtk, pLatch, i ) Io_NtkWriteBlifMvLatch( pFile, pLatch ); fprintf( pFile, "\n" ); } /* // write the subcircuits assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); if ( Abc_NtkBlackboxNum(pNtk) > 0 ) { fprintf( pFile, "\n" ); Abc_NtkForEachBlackbox( pNtk, pNode, i ) Io_NtkWriteBlifMvSubckt( pFile, pNode ); fprintf( pFile, "\n" ); } */ if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) { fprintf( pFile, "\n" ); Abc_NtkForEachBox( pNtk, pNode, i ) { if ( Abc_ObjIsLatch(pNode) ) continue; Io_NtkWriteBlifMvSubckt( pFile, pNode ); } fprintf( pFile, "\n" ); } // write each internal node pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Io_NtkWriteBlifMvNode( pFile, pNode ); } Extra_ProgressBarStop( pProgress ); } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pTerm, * pNet; int LineLength; int AddedLength; int NameCounter; int i; LineLength = 7; NameCounter = 0; Abc_NtkForEachPi( pNtk, pTerm, i ) { pNet = Abc_ObjFanout0(pTerm); // get the line length after this name is written AddedLength = strlen(Abc_ObjName(pNet)) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", Abc_ObjName(pNet) ); LineLength += AddedLength; NameCounter++; } } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pTerm, * pNet; int LineLength; int AddedLength; int NameCounter; int i; LineLength = 8; NameCounter = 0; Abc_NtkForEachPo( pNtk, pTerm, i ) { pNet = Abc_ObjFanin0(pTerm); // get the line length after this name is written AddedLength = strlen(Abc_ObjName(pNet)) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", Abc_ObjName(pNet) ); LineLength += AddedLength; NameCounter++; } } /**Function************************************************************* Synopsis [Write the latch into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ) { Abc_Obj_t * pNetLi, * pNetLo; int Reset; pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); Reset = (int)(ABC_PTRUINT_T)Abc_ObjData( pLatch ); // write the latch line fprintf( pFile, ".latch" ); fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); fprintf( pFile, "\n" ); // write the reset node fprintf( pFile, ".reset %s\n", Abc_ObjName(pNetLo) ); fprintf( pFile, "%d\n", Reset-1 ); } /**Function************************************************************* Synopsis [Write the latch into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ) { Abc_Ntk_t * pModel = (Abc_Ntk_t *)pNode->pData; Abc_Obj_t * pTerm; int i; // write the MV directives fprintf( pFile, "\n" ); Abc_ObjForEachFanin( pNode, pTerm, i ) if ( Abc_ObjMvVarNum(pTerm) > 2 ) fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); Abc_ObjForEachFanout( pNode, pTerm, i ) if ( Abc_ObjMvVarNum(pTerm) > 2 ) fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); // write the subcircuit fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); // write pairs of the formal=actual names Abc_NtkForEachPi( pModel, pTerm, i ) { fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); pTerm = Abc_ObjFanin( pNode, i ); fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); } Abc_NtkForEachPo( pModel, pTerm, i ) { fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); pTerm = Abc_ObjFanout( pNode, i ); fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); } fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Write the node into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; char * pCur; int nValues, iFanin, i; // write .mv directives for the fanins fprintf( pFile, "\n" ); Abc_ObjForEachFanin( pNode, pFanin, i ) { // nValues = atoi(pCur); nValues = Abc_ObjMvVarNum( pFanin ); if ( nValues > 2 ) fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues ); // while ( *pCur++ != ' ' ); } // write .mv directives for the node // nValues = atoi(pCur); nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) ); if ( nValues > 2 ) fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues ); // while ( *pCur++ != '\n' ); // write the .names line fprintf( pFile, ".table" ); Io_NtkWriteBlifMvNodeFanins( pFile, pNode ); fprintf( pFile, "\n" ); // write the cubes pCur = (char *)Abc_ObjData(pNode); if ( *pCur == 'd' ) { fprintf( pFile, ".default " ); pCur++; } // write the literals for ( ; *pCur; pCur++ ) { fprintf( pFile, "%c", *pCur ); if ( *pCur != '=' ) continue; // get the number iFanin = atoi( pCur+1 ); fprintf( pFile, "%s", Abc_ObjName(Abc_ObjFanin(pNode,iFanin)) ); // scroll on to the next symbol while ( *pCur != ' ' && *pCur != '\n' ) pCur++; pCur--; } } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) { Abc_Obj_t * pNet; int LineLength; int AddedLength; int NameCounter; char * pName; int i; LineLength = 6; NameCounter = 0; Abc_ObjForEachFanin( pNode, pNet, i ) { // get the fanin name pName = Abc_ObjName(pNet); // get the line length after the fanin name is written AddedLength = strlen(pName) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", pName ); LineLength += AddedLength; NameCounter++; } // get the output name pName = Abc_ObjName(Abc_ObjFanout0(pNode)); // get the line length after the output name is written AddedLength = strlen(pName) + 1; if ( NameCounter && LineLength + AddedLength > 75 ) { // write the line extender fprintf( pFile, " \\\n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", pName ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteBook.c000066400000000000000000000752101300674244400237630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteBook.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write Bookshelf files.] Author [Myungchul Kim] Affiliation [U of Michigan] Date [Ver. 1.0. Started - October 25, 2008.] Revision [$Id: ioWriteBook.c,v 1.00 2005/11/10 00:00:00 mckima Exp $] ***********************************************************************/ #include #include "base/main/main.h" #include "map/mio/mio.h" #include "ioAbc.h" ABC_NAMESPACE_IMPL_START #define NODES 0 #define PL 1 #define coreHeight 1 #define termWidth 1 #define termHeight 1 //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static unsigned Io_NtkWriteNodes( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWritePiPoNodes( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteLatchNode( FILE * pFile, Abc_Obj_t * pLatch, int NodesOrPl ); static unsigned Io_NtkWriteIntNode( FILE * pFile, Abc_Obj_t * pNode, int NodesOrPl ); static unsigned Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode ); static void Io_NtkWriteNets( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteIntNet( FILE * pFile, Abc_Obj_t * pNode ); static void Io_NtkBuildLayout( FILE * pFile1, FILE *pFile2, Abc_Ntk_t * pNtk, double aspectRatio, double whiteSpace, unsigned coreCellArea ); static void Io_NtkWriteScl( FILE * pFile, unsigned numCoreRows, double layoutWidth ); static void Io_NtkWritePl( FILE * pFile, Abc_Ntk_t * pNtk, unsigned numTerms, double layoutHeight, double layoutWidth ); static Vec_Ptr_t * Io_NtkOrderingPads( Abc_Ntk_t * pNtk, Vec_Ptr_t * vTerms ); static Abc_Obj_t * Io_NtkBfsPads( Abc_Ntk_t * pNtk, Abc_Obj_t * pCurrEntry, unsigned numTerms, int * pOrdered ); static int Abc_NodeIsNand2( Abc_Obj_t * pNode ); static int Abc_NodeIsNor2( Abc_Obj_t * pNode ); static int Abc_NodeIsAnd2( Abc_Obj_t * pNode ); static int Abc_NodeIsOr2( Abc_Obj_t * pNode ); static int Abc_NodeIsXor2( Abc_Obj_t * pNode ); static int Abc_NodeIsXnor2( Abc_Obj_t * pNode ); static inline double Abc_Rint( double x ) { return (double)(int)x; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Write the network into a Bookshelf file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBookLogic( Abc_Ntk_t * pNtk, char * FileName ) { Abc_Ntk_t * pNtkTemp; // derive the netlist pNtkTemp = Abc_NtkToNetlist(pNtk); if ( pNtkTemp == NULL ) { fprintf( stdout, "Writing BOOK has failed.\n" ); return; } Io_WriteBook( pNtkTemp, FileName ); Abc_NtkDelete( pNtkTemp ); } /**Function************************************************************* Synopsis [Write the network into a BOOK file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteBook( Abc_Ntk_t * pNtk, char * FileName ) { FILE * pFileNodes, * pFileNets, * pFileAux; FILE * pFileScl, * pFilePl, * pFileWts; char * FileExt = ABC_CALLOC( char, strlen(FileName)+7 ); unsigned coreCellArea=0; Abc_Ntk_t * pExdc, * pNtkTemp; int i; assert( Abc_NtkIsNetlist(pNtk) ); // start writing the files strcpy(FileExt, FileName); pFileNodes = fopen( strcat(FileExt,".nodes"), "w" ); strcpy(FileExt, FileName); pFileNets = fopen( strcat(FileExt,".nets"), "w" ); strcpy(FileExt, FileName); pFileAux = fopen( strcat(FileExt,".aux"), "w" ); // write the aux file if ( (pFileNodes == NULL) || (pFileNets == NULL) || (pFileAux == NULL) ) { fclose( pFileAux ); fprintf( stdout, "Io_WriteBook(): Cannot open the output files.\n" ); return; } fprintf( pFileAux, "RowBasedPlacement : %s.nodes %s.nets %s.scl %s.pl %s.wts", FileName, FileName, FileName, FileName, FileName ); fclose( pFileAux ); // write the master network coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtk ); Io_NtkWriteNets( pFileNets, pNtk ); // write EXDC network if it exists pExdc = Abc_NtkExdc( pNtk ); if ( pExdc ) { coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtk ); Io_NtkWriteNets( pFileNets, pNtk ); } // make sure there is no logic hierarchy assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); // write the hierarchy if present if ( Abc_NtkBlackboxNum(pNtk) > 0 ) { Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNtkTemp, i ) { if ( pNtkTemp == pNtk ) continue; coreCellArea+=Io_NtkWriteNodes( pFileNodes, pNtkTemp ); Io_NtkWriteNets( pFileNets, pNtkTemp ); } } fclose( pFileNodes ); fclose( pFileNets ); strcpy(FileExt, FileName); pFileScl = fopen( strcat(FileExt,".scl"), "w" ); strcpy(FileExt, FileName); pFilePl = fopen( strcat(FileExt,".pl"), "w" ); strcpy(FileExt, FileName); pFileWts = fopen( strcat(FileExt,".wts"), "w" ); ABC_FREE(FileExt); Io_NtkBuildLayout( pFileScl, pFilePl, pNtk, 1.0, 10, coreCellArea ); fclose( pFileScl ); fclose( pFilePl ); fclose( pFileWts ); } /**Function************************************************************* Synopsis [Write the network into a BOOK file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Io_NtkWriteNodes( FILE * pFile, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Obj_t * pLatch, * pNode; unsigned numTerms, numNodes, coreCellArea=0; int i; assert( Abc_NtkIsNetlist(pNtk) ); // write the forehead numTerms=Abc_NtkPiNum(pNtk)+Abc_NtkPoNum(pNtk); numNodes=numTerms+Abc_NtkNodeNum(pNtk)+Abc_NtkLatchNum(pNtk); printf("NumNodes : %d\t", numNodes ); printf("NumTerminals : %d\n", numTerms ); fprintf( pFile, "UCLA nodes 1.0\n"); fprintf( pFile, "NumNodes : %d\n", numNodes ); fprintf( pFile, "NumTerminals : %d\n", numTerms ); // write the PI/POs Io_NtkWritePiPoNodes( pFile, pNtk ); // write the latches if ( !Abc_NtkIsComb(pNtk) ) { Abc_NtkForEachLatch( pNtk, pLatch, i ) { Io_NtkWriteLatchNode( pFile, pLatch, NODES ); coreCellArea+=6*coreHeight; } } // write each internal node pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); coreCellArea+=Io_NtkWriteIntNode( pFile, pNode, NODES ); } Extra_ProgressBarStop( pProgress ); return coreCellArea; } /**Function************************************************************* Synopsis [Writes the primary input nodes into a file] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWritePiPoNodes( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pTerm, * pNet; int i; Abc_NtkForEachPi( pNtk, pTerm, i ) { pNet = Abc_ObjFanout0(pTerm); fprintf( pFile, "i%s_input\t", Abc_ObjName(pNet) ); fprintf( pFile, "terminal "); fprintf( pFile, " %d %d\n", termWidth, termHeight ); } Abc_NtkForEachPo( pNtk, pTerm, i ) { pNet = Abc_ObjFanin0(pTerm); fprintf( pFile, "o%s_output\t", Abc_ObjName(pNet) ); fprintf( pFile, "terminal "); fprintf( pFile, " %d %d\n", termWidth, termHeight ); } } /**Function************************************************************* Synopsis [Write the latch nodes into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteLatchNode( FILE * pFile, Abc_Obj_t * pLatch, int NodesOrPl ) { Abc_Obj_t * pNetLi, * pNetLo; pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); /// write the latch line fprintf( pFile, "%s_%s_latch\t", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) ); if (NodesOrPl == NODES) fprintf( pFile, " %d %d\n", 6, 1 ); } /**Function************************************************************* Synopsis [Write the internal node into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Io_NtkWriteIntNode( FILE * pFile, Abc_Obj_t * pNode, int NodesOrPl ) { unsigned sizex=0, sizey=coreHeight, isize=0; //double nx, ny, xstep, ystep; Abc_Obj_t * pNeti, *pNeto; int i; // write the network after mapping if ( Abc_NtkHasMapping(pNode->pNtk) ) sizex=Io_NtkWriteNodeGate( pFile, pNode ); else { Abc_ObjForEachFanin( pNode, pNeti, i ) fprintf( pFile, "%s_", Abc_ObjName(pNeti) ); Abc_ObjForEachFanout( pNode, pNeto, i ) fprintf( pFile, "%s_", Abc_ObjName(pNeto) ); fprintf( pFile, "name\t" ); if(NodesOrPl == NODES) { isize=Abc_ObjFaninNum(pNode); if ( Abc_NodeIsConst0(pNode) || Abc_NodeIsConst1(pNode) ) sizex=0; else if ( Abc_NodeIsInv(pNode) ) sizex=1; else if ( Abc_NodeIsBuf(pNode) ) sizex=2; else { assert( Abc_NtkHasSop(pNode->pNtk) ); if ( Abc_NodeIsNand2(pNode) || Abc_NodeIsNor2(pNode) ) sizex=2; else if ( Abc_NodeIsAnd2(pNode) || Abc_NodeIsOr2(pNode) ) sizex=3; else if ( Abc_NodeIsXor2(pNode) || Abc_NodeIsXnor2(pNode) ) sizex=5; else { assert( isize > 2 ); sizex=isize+Abc_SopGetCubeNum((char *)pNode->pData); } } } } if(NodesOrPl == NODES) { fprintf( pFile, " %d %d\n", sizex, sizey ); // Equally place pins. Size pins needs / isize+#output+1 isize= isize + Abc_ObjFanoutNum(pNode) + 1; } return sizex*sizey; /* xstep = sizex / isize; ystep = sizey / isize; nx= -0.5 * sizex; ny= -0.5 * sizey; Abc_ObjForEachFanin( pNode, pFanin, i ) { nx+= xstep; ny+= ystep; if (fabs(nx) < 0.001) nx= 0; if (fabs(ny) < 0.001) ny= 0; } Abc_ObjForEachFanout( pNode, pFanout, i ) { nx+= xstep; ny+= ystep; if (fabs(nx) < 0.001) nx= 0; if (fabs(ny) < 0.001) ny= 0; } */ } /**Function************************************************************* Synopsis [Writes the internal node after tech mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode ) { Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData; Mio_Pin_t * pGatePin; int i; // write the node gate for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) fprintf( pFile, "%s_", Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); assert ( i == Abc_ObjFaninNum(pNode) ); fprintf( pFile, "%s_%s\t", Abc_ObjName( Abc_ObjFanout0(pNode) ), Mio_GateReadName(pGate) ); return Mio_GateReadArea(pGate); } /**Function************************************************************* Synopsis [Write the nets into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteNets( FILE * pFile, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Obj_t * pNet; unsigned numPin=0; int i; assert( Abc_NtkIsNetlist(pNtk) ); // write the head Abc_NtkForEachNet( pNtk, pNet, i ) numPin+=Abc_ObjFaninNum(pNet)+Abc_ObjFanoutNum(pNet); printf( "NumNets : %d\t", Abc_NtkNetNum(pNtk) ); printf( "NumPins : %d\n\n", numPin ); fprintf( pFile, "UCLA nets 1.0\n"); fprintf( pFile, "NumNets : %d\n", Abc_NtkNetNum(pNtk) ); fprintf( pFile, "NumPins : %d\n", numPin ); // write nets pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNetNum(pNtk) ); Abc_NtkForEachNet( pNtk, pNet, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Io_NtkWriteIntNet( pFile, pNet ); } Extra_ProgressBarStop( pProgress ); } /**Function************************************************************* Synopsis [Write the nets into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteIntNet( FILE * pFile, Abc_Obj_t * pNet ) { Abc_Obj_t * pFanin, * pFanout; Abc_Obj_t * pNeti, * pNeto; Abc_Obj_t * pNetLi, * pNetLo, * pLatch; int i, j; int NetDegree=Abc_ObjFaninNum(pNet)+Abc_ObjFanoutNum(pNet); fprintf( pFile, "NetDegree\t:\t\t%d\t\t%s\n", NetDegree, Abc_ObjName(Abc_ObjFanin0(pNet)) ); pFanin=Abc_ObjFanin0(pNet); if ( Abc_ObjIsPi(pFanin) ) fprintf( pFile, "i%s_input I\n", Abc_ObjName(pNet) ); else { if(!Abc_NtkIsComb(pNet->pNtk) && Abc_ObjFaninNum(pFanin) && Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) { pLatch=Abc_ObjFanin0(pFanin); pNetLi=Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); pNetLo=Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); fprintf( pFile, "%s_%s_latch I : ", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) ); } else { Abc_ObjForEachFanin( pFanin, pNeti, j ) fprintf( pFile, "%s_", Abc_ObjName(pNeti) ); Abc_ObjForEachFanout( pFanin, pNeto, j ) fprintf( pFile, "%s_", Abc_ObjName(pNeto) ); if ( Abc_NtkHasMapping(pNet->pNtk) ) fprintf( pFile, "%s : ", Mio_GateReadName((Mio_Gate_t *)pFanin->pData) ); else fprintf( pFile, "name I : " ); } // offsets are simlply 0.00 0.00 at the moment fprintf( pFile, "%.2f %.2f\n", .0, .0 ); } Abc_ObjForEachFanout( pNet, pFanout, i ) { if ( Abc_ObjIsPo(pFanout) ) fprintf( pFile, "o%s_output O\n", Abc_ObjName(pNet) ); else { if(!Abc_NtkIsComb(pNet->pNtk) && Abc_ObjFanoutNum(pFanout) && Abc_ObjIsLatch( Abc_ObjFanout0(pFanout) ) ) { pLatch=Abc_ObjFanout0(pFanout); pNetLi=Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); pNetLo=Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); fprintf( pFile, "%s_%s_latch O : ", Abc_ObjName(pNetLi), Abc_ObjName(pNetLo) ); } else { Abc_ObjForEachFanin( pFanout, pNeti, j ) fprintf( pFile, "%s_", Abc_ObjName(pNeti) ); Abc_ObjForEachFanout( pFanout, pNeto, j ) fprintf( pFile, "%s_", Abc_ObjName(pNeto) ); if ( Abc_NtkHasMapping(pNet->pNtk) ) fprintf( pFile, "%s : ", Mio_GateReadName((Mio_Gate_t *)pFanout->pData) ); else fprintf( pFile, "name O : " ); } // offsets are simlply 0.00 0.00 at the moment fprintf( pFile, "%.2f %.2f\n", .0, .0 ); } } } /**Function************************************************************* Synopsis [Write the network into a BOOK file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkBuildLayout( FILE * pFileScl, FILE * pFilePl, Abc_Ntk_t * pNtk, double aspectRatio, double whiteSpace, unsigned coreCellArea ) { unsigned numCoreCells=Abc_NtkNodeNum(pNtk)+Abc_NtkLatchNum(pNtk); double targetLayoutArea = coreCellArea/(1.0-(whiteSpace/100.0)); unsigned numCoreRows=(aspectRatio>0.0) ? (Abc_Rint(sqrt(targetLayoutArea/aspectRatio)/coreHeight)) : 0; unsigned numTerms=Abc_NtkPiNum(pNtk)+Abc_NtkPoNum(pNtk); unsigned totalWidth=coreCellArea/coreHeight; double layoutHeight = numCoreRows * coreHeight; double layoutWidth = Abc_Rint(targetLayoutArea/layoutHeight); double actualLayoutArea = layoutWidth * layoutHeight; printf( "Core cell height(==site height) is %d\n", coreHeight ); printf( "Total core cell width is %d giving an ave width of %f\n", totalWidth, (double)(totalWidth/numCoreCells)); printf( "Target Dimensions:\n" ); printf( " Area : %f\n", targetLayoutArea ); printf( " WS%% : %f\n", whiteSpace ); printf( " AR : %f\n", aspectRatio ); printf( "Actual Dimensions:\n" ); printf( " Width : %f\n", layoutWidth ); printf( " Height: %f (%d rows)\n", layoutHeight, numCoreRows); printf( " Area : %f\n", actualLayoutArea ); printf( " WS%% : %f\n", 100*(actualLayoutArea-coreCellArea)/actualLayoutArea ); printf( " AR : %f\n\n", layoutWidth/layoutHeight ); Io_NtkWriteScl( pFileScl, numCoreRows, layoutWidth ); Io_NtkWritePl( pFilePl, pNtk, numTerms, layoutHeight, layoutWidth ); } /**Function************************************************************* Synopsis [Write the network into a BOOK file with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteScl( FILE * pFile, unsigned numCoreRows, double layoutWidth ) { int origin_y=0; char * rowOrients[2] = {"N", "FS"}; char symmetry='Y'; double sitewidth=1.0; double spacing=1.0; unsigned rowId; // write the forehead fprintf( pFile, "UCLA scl 1.0\n\n" ); fprintf( pFile, "Numrows : %d\n\n", numCoreRows ); for( rowId=0 ; rowId0 ) { pNeighbor = (Abc_Obj_t *)Vec_PtrEntry( vNeighbors, 0 ); assert( Abc_ObjIsNode(pNeighbor) || Abc_ObjIsTerm(pNeighbor) ); Vec_PtrRemove( vNeighbors, pNeighbor ); if( Abc_NodeIsTravIdCurrent( pNeighbor ) ) continue; Abc_NodeSetTravIdCurrent( pNeighbor ); if( ((Abc_ObjIsPi(pNeighbor) || Abc_ObjIsPo(pNeighbor))) && !pOrdered[Abc_ObjId(pNeighbor)] ) { foundNeighbor=1; break; } if( Abc_ObjFanoutNum( pNeighbor ) ) { pNet=Abc_ObjFanout0( pNeighbor ); if( !Abc_NtkIsComb(pNtk) && Abc_ObjIsLatch(pNet) ) pNet=Abc_ObjFanout0( Abc_ObjFanout0(pNet) ); Abc_ObjForEachFanout( pNet, pNode, i ) if( !Abc_NodeIsTravIdCurrent(pNode) ) Vec_PtrPush( vNeighbors, pNode ); } if( Abc_ObjFaninNum( pNeighbor ) ) { if( !Abc_NtkIsComb(pNtk) && Abc_ObjIsLatch(Abc_ObjFanin0(pNeighbor)) ) pNeighbor=Abc_ObjFanin0( Abc_ObjFanin0(pNeighbor) ); Abc_ObjForEachFanin( pNeighbor, pNet, i ) if( !Abc_NodeIsTravIdCurrent(pNode=Abc_ObjFanin0(pNet)) ) Vec_PtrPush( vNeighbors, pNode ); } } return ( foundNeighbor ) ? pNeighbor : pTerm; } /**Function************************************************************* Synopsis [Test is the node is nand2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsNand2( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_ObjFaninNum(pNode) != 2 ) return 0; if ( Abc_NtkHasSop(pNtk) ) return ( !strcmp(((char *)pNode->pData), "-0 1\n0- 1\n") || !strcmp(((char *)pNode->pData), "0- 1\n-0 1\n") || !strcmp(((char *)pNode->pData), "11 0\n") ); if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == (void *)Mio_LibraryReadNand2((Mio_Library_t *)Abc_FrameReadLibGen()); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Test is the node is nand2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsNor2( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_ObjFaninNum(pNode) != 2 ) return 0; if ( Abc_NtkHasSop(pNtk) ) return ( !strcmp(((char *)pNode->pData), "00 1\n") ); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Test is the node is and2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsAnd2( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_ObjFaninNum(pNode) != 2 ) return 0; if ( Abc_NtkHasSop(pNtk) ) return Abc_SopIsAndType(((char *)pNode->pData)); if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == (void *)Mio_LibraryReadAnd2((Mio_Library_t *)Abc_FrameReadLibGen()); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Test is the node is or2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsOr2( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_ObjFaninNum(pNode) != 2 ) return 0; if ( Abc_NtkHasSop(pNtk) ) return ( Abc_SopIsOrType(((char *)pNode->pData)) || !strcmp(((char *)pNode->pData), "01 0\n") || !strcmp(((char *)pNode->pData), "10 0\n") || !strcmp(((char *)pNode->pData), "00 0\n") ); //off-sets, too assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Test is the node is xor2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsXor2( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_ObjFaninNum(pNode) != 2 ) return 0; if ( Abc_NtkHasSop(pNtk) ) return ( !strcmp(((char *)pNode->pData), "01 1\n10 1\n") || !strcmp(((char *)pNode->pData), "10 1\n01 1\n") ); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Test is the node is xnor2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsXnor2( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_ObjFaninNum(pNode) != 2 ) return 0; if ( Abc_NtkHasSop(pNtk) ) return ( !strcmp(((char *)pNode->pData), "11 1\n00 1\n") || !strcmp(((char *)pNode->pData), "00 1\n11 1\n") ); assert( 0 ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteCnf.c000066400000000000000000000073731300674244400236040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteCnf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to output CNF of the miter cone.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Ntk_t * s_pNtk = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Write the miter cone into a CNF file for the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName, int fAllPrimes ) { sat_solver * pSat; if ( Abc_NtkIsStrash(pNtk) ) printf( "Io_WriteCnf() warning: Generating CNF by applying heuristic AIG to CNF conversion.\n" ); else printf( "Io_WriteCnf() warning: Generating CNF by convering logic nodes into CNF clauses.\n" ); if ( Abc_NtkPoNum(pNtk) != 1 ) { fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" ); return 0; } if ( Abc_NtkLatchNum(pNtk) != 0 ) { fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" ); return 0; } if ( Abc_NtkNodeNum(pNtk) == 0 ) { fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" ); return 0; } // convert to logic BDD network if ( Abc_NtkIsLogic(pNtk) ) Abc_NtkToBdd( pNtk ); // create solver with clauses pSat = (sat_solver *)Abc_NtkMiterSatCreate( pNtk, fAllPrimes ); if ( pSat == NULL ) { fprintf( stdout, "The problem is trivially UNSAT. No CNF file is generated.\n" ); return 1; } // write the clauses s_pNtk = pNtk; Sat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 ); s_pNtk = NULL; // free the solver sat_solver_delete( pSat ); return 1; } /**Function************************************************************* Synopsis [Output the mapping of PIs into variable numbers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars ) { extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pNtk = s_pNtk; Vec_Int_t * vCiIds; Abc_Obj_t * pObj; int i; vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); fprintf( pFile, "c PI variable numbers: \n" ); Abc_NtkForEachCi( pNtk, pObj, i ) fprintf( pFile, "c %s %d\n", Abc_ObjName(pObj), Vec_IntEntry(vCiIds, i) + (int)(incrementVars > 0) ); Vec_IntFree( vCiIds ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteDot.c000066400000000000000000000703101300674244400236130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteDot.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write the graph structure of AIG in DOT.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteDot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/main/main.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static char * Abc_NtkPrintSop( char * pSop ); static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the graph structure of network for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ) { Vec_Ptr_t * vNodes; vNodes = Abc_NtkCollectObjects( pNtk ); Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0 ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Writes the graph structure of network for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) { FILE * pFile; Abc_Obj_t * pNode, * pFanin; char * pSopString; int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl, Prev; int Limit = 300; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); if ( vNodes->nSize < 1 ) { printf( "The set has no nodes. DOT file is not written.\n" ); return; } if ( vNodes->nSize > Limit ) { printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); return; } // start the stream if ( (pFile = fopen( pFileName, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } // transform logic functions from BDD to SOP if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) ) { if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) { printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); return; } } // mark the nodes from the set Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) pNode->fMarkC = 1; if ( vNodesShow ) Vec_PtrForEachEntry( Abc_Obj_t *, vNodesShow, pNode, i ) pNode->fMarkB = 1; // get the levels of nodes LevelMax = Abc_NtkLevel( pNtk ); if ( fUseReverse ) { LevelMin = Abc_NtkLevelReverse( pNtk ); assert( LevelMax == LevelMin ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) if ( Abc_ObjIsNode(pNode) ) pNode->Level = LevelMax - pNode->Level + 1; } // find the largest and the smallest levels LevelMin = 10000; LevelMax = -1; fHasCos = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsCo(pNode) ) { fHasCos = 1; continue; } if ( LevelMin > (int)pNode->Level ) LevelMin = pNode->Level; if ( LevelMax < (int)pNode->Level ) LevelMax = pNode->Level; } // set the level of the CO nodes if ( fHasCos ) { LevelMax++; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsCo(pNode) ) pNode->Level = LevelMax; } } // write the DOT header fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph network {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "size = \"10,8.5\";\n" ); // fprintf( pFile, "size = \"14,11\";\n" ); // fprintf( pFile, "page = \"8,11\";\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 >= LevelMin; 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 >= LevelMin; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != LevelMin ) 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", "Network structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); 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=\"" ); if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); else fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the POs if ( fHasCos ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the PO nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( !Abc_ObjIsCo(pNode) ) continue; fprintf( pFile, " Node%d [label = \"%s%s\"", pNode->Id, (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), (Abc_ObjIsBi(pNode)? "_in":"") ); fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); 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 - fHasCos; Level >= LevelMin && Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( (int)pNode->Level != Level ) continue; if ( Abc_ObjFaninNum(pNode) == 0 ) continue; /* int SuppSize; Vec_Ptr_t * vSupp; if ( (int)pNode->Level != Level ) continue; if ( Abc_ObjFaninNum(pNode) == 0 ) continue; vSupp = Abc_NtkNodeSupport( pNtk, &pNode, 1 ); SuppSize = Vec_PtrSize( vSupp ); Vec_PtrFree( vSupp ); */ // fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); if ( Abc_NtkIsStrash(pNtk) ) pSopString = ""; else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) pSopString = Mio_GateReadName((Mio_Gate_t *)pNode->pData); else if ( Abc_NtkHasMapping(pNtk) ) pSopString = Abc_NtkPrintSop(Mio_GateReadSop((Mio_Gate_t *)pNode->pData)); else pSopString = Abc_NtkPrintSop((char *)pNode->pData); fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); // fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, // SuppSize, // pSopString ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the PI nodes if any if ( LevelMin == 0 ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMin ); // generate the PO nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( !Abc_ObjIsCi(pNode) ) { // check if the costant node is present if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) { fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } continue; } fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) ); fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); 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" ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( (int)pNode->Level != LevelMax ) continue; fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); } // generate invisible edges among the COs Prev = -1; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( (int)pNode->Level != LevelMax ) continue; if ( !Abc_ObjIsPo(pNode) ) continue; if ( Prev >= 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, pNode->Id ); Prev = pNode->Id; } // generate edges Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsLatch(pNode) ) continue; Abc_ObjForEachFanin( pNode, pFanin, k ) { if ( Abc_ObjIsLatch(pFanin) ) continue; fCompl = 0; if ( Abc_NtkIsStrash(pNtk) ) fCompl = Abc_ObjFaninC(pNode, k); // generate the edge from this node to the next fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", pFanin->Id ); fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); // fprintf( pFile, ", label = \"%c\"", 'a' + k ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); fclose( pFile ); // unmark the nodes from the set Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) pNode->fMarkC = 0; if ( vNodesShow ) Vec_PtrForEachEntry( Abc_Obj_t *, vNodesShow, pNode, i ) pNode->fMarkB = 0; // convert the network back into BDDs if this is how it was if ( fHasBdds ) Abc_NtkSopToBdd(pNtk); } /**Function************************************************************* Synopsis [Writes the graph structure of network for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) { FILE * pFile; Abc_Obj_t * pNode, * pFanin; char * pSopString; int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl, Prev; int Limit = 300; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); if ( vNodes->nSize < 1 ) { printf( "The set has no nodes. DOT file is not written.\n" ); return; } if ( vNodes->nSize > Limit ) { printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); return; } // start the stream if ( (pFile = fopen( pFileName, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } // transform logic functions from BDD to SOP if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) ) { if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) { printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); return; } } // mark the nodes from the set Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) pNode->fMarkC = 1; if ( vNodesShow ) Vec_PtrForEachEntry( Abc_Obj_t *, vNodesShow, pNode, i ) pNode->fMarkB = 1; // get the levels of nodes LevelMax = Abc_NtkLevel( pNtk ); if ( fUseReverse ) { LevelMin = Abc_NtkLevelReverse( pNtk ); assert( LevelMax == LevelMin ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) if ( Abc_ObjIsNode(pNode) ) pNode->Level = LevelMax - pNode->Level + 1; } // find the largest and the smallest levels LevelMin = 10000; LevelMax = -1; fHasCos = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsCo(pNode) ) { fHasCos = 1; continue; } if ( LevelMin > (int)pNode->Level ) LevelMin = pNode->Level; if ( LevelMax < (int)pNode->Level ) LevelMax = pNode->Level; } // set the level of the CO nodes if ( fHasCos ) { LevelMax++; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsCo(pNode) ) pNode->Level = LevelMax; } } // write the DOT header fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph network {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "size = \"10,8.5\";\n" ); // fprintf( pFile, "size = \"14,11\";\n" ); // fprintf( pFile, "page = \"8,11\";\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 >= LevelMin; 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 >= LevelMin; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != LevelMin ) 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", "Network structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); 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=\"" ); if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); else fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the POs if ( fHasCos ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the PO nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( !Abc_ObjIsPo(pNode) ) continue; fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); fprintf( pFile, ", shape = %s", "invtriangle" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); 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 - fHasCos; Level >= LevelMin && Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( (int)pNode->Level != Level ) continue; // fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); if ( Abc_NtkIsStrash(pNtk) ) pSopString = ""; else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) pSopString = Mio_GateReadName((Mio_Gate_t *)pNode->pData); else if ( Abc_NtkHasMapping(pNtk) ) pSopString = Abc_NtkPrintSop(Mio_GateReadSop((Mio_Gate_t *)pNode->pData)); else pSopString = Abc_NtkPrintSop((char *)pNode->pData); fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the PI nodes if any if ( LevelMin == 0 ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMin ); // generate the PO nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( pNode->Level > 0 ) continue; if ( !Abc_ObjIsPi(pNode) ) { // check if the costant node is present if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) { fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } continue; } fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); fprintf( pFile, ", shape = %s", "triangle" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // fprintf( pFile, "{\n" ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( !Abc_ObjIsLatch(pNode) ) continue; fprintf( pFile, "Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); fprintf( pFile, ", shape = box" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); 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" ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( (int)pNode->Level != LevelMax ) continue; if ( !Abc_ObjIsPo(pNode) ) continue; fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); } // generate invisible edges among the COs Prev = -1; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( (int)pNode->Level != LevelMax ) continue; if ( !Abc_ObjIsPo(pNode) ) continue; if ( Prev >= 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, pNode->Id ); Prev = pNode->Id; } // generate edges Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsBi(pNode) || Abc_ObjIsBo(pNode) ) continue; Abc_ObjForEachFanin( pNode, pFanin, k ) { fCompl = 0; if ( Abc_NtkIsStrash(pNtk) ) { if ( Abc_ObjIsBi(pFanin) ) fCompl = Abc_ObjFaninC(pFanin, k); else fCompl = Abc_ObjFaninC(pNode, k); } if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) pFanin = Abc_ObjFanin0(pFanin); if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) pFanin = Abc_ObjFanin0(pFanin); if ( !pFanin->fMarkC ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", pFanin->Id ); fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); // fprintf( pFile, ", label = \"%c\"", 'a' + k ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); fclose( pFile ); // unmark the nodes from the set Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) pNode->fMarkC = 0; if ( vNodesShow ) Vec_PtrForEachEntry( Abc_Obj_t *, vNodesShow, pNode, i ) pNode->fMarkB = 0; // convert the network back into BDDs if this is how it was if ( fHasBdds ) Abc_NtkSopToBdd(pNtk); } /**Function************************************************************* Synopsis [Computes the printable SOP form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_NtkPrintSop( char * pSop ) { static char Buffer[1000]; char * pGet, * pSet; pSet = Buffer; for ( pGet = pSop; *pGet; pGet++ ) { if ( *pGet == '\n' ) { *pSet++ = '\\'; *pSet++ = 'n'; } else *pSet++ = *pGet; } *(pSet-2) = 0; return Buffer; } /**Function************************************************************* Synopsis [Computes the printable SOP form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ) { Abc_Obj_t * pObj; int i, Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { if ( !Abc_ObjIsNode(pObj) ) continue; if ( Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) continue; Counter ++; } return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteEqn.c000066400000000000000000000163551300674244400236210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteEqn.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write equation representation of the network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ); static int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the logic network in the equation format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; assert( Abc_NtkIsAigNetlist(pNtk) ); if ( Abc_NtkLatchNum(pNtk) > 0 ) printf( "Warning: only combinational portion is being written.\n" ); // check that the names are fine for the EQN format if ( !Io_NtkWriteEqnCheck(pNtk) ) return; // start the output stream pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteEqn(): Cannot open the output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# Equations for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the equations for the network Io_NtkWriteEqnOne( pFile, pNtk ); fprintf( pFile, "\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Write one network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) { Vec_Vec_t * vLevels; ProgressBar * pProgress; Abc_Obj_t * pNode, * pFanin; int i, k; // write the PIs fprintf( pFile, "INORDER =" ); Io_NtkWriteEqnCis( pFile, pNtk ); fprintf( pFile, ";\n" ); // write the POs fprintf( pFile, "OUTORDER =" ); Io_NtkWriteEqnCos( pFile, pNtk ); fprintf( pFile, ";\n" ); // write each internal node vLevels = Vec_VecAlloc( 10 ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); fprintf( pFile, "%s = ", Abc_ObjName(Abc_ObjFanout0(pNode)) ); // set the input names Abc_ObjForEachFanin( pNode, pFanin, k ) Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData = Abc_ObjName(pFanin); // write the formula Hop_ObjPrintEqn( pFile, (Hop_Obj_t *)pNode->pData, vLevels, 0 ); fprintf( pFile, ";\n" ); } Extra_ProgressBarStop( pProgress ); Vec_VecFree( vLevels ); } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pTerm, * pNet; int LineLength; int AddedLength; int NameCounter; int i; LineLength = 9; NameCounter = 0; Abc_NtkForEachCi( pNtk, pTerm, i ) { pNet = Abc_ObjFanout0(pTerm); // get the line length after this name is written AddedLength = strlen(Abc_ObjName(pNet)) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", Abc_ObjName(pNet) ); LineLength += AddedLength; NameCounter++; } } /**Function************************************************************* Synopsis [Writes the primary input list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pTerm, * pNet; int LineLength; int AddedLength; int NameCounter; int i; LineLength = 10; NameCounter = 0; Abc_NtkForEachCo( pNtk, pTerm, i ) { pNet = Abc_ObjFanin0(pTerm); // get the line length after this name is written AddedLength = strlen(Abc_ObjName(pNet)) + 1; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, " \n" ); // reset the line length LineLength = 0; NameCounter = 0; } fprintf( pFile, " %s", Abc_ObjName(pNet) ); LineLength += AddedLength; NameCounter++; } } /**Function************************************************************* Synopsis [Make sure the network does not have offending names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; char * pName = NULL; int i, k, Length; int RetValue = 1; // make sure the network does not have proper names, such as "0" or "1" or containing parentheses Abc_NtkForEachObj( pNtk, pObj, i ) { pName = Nm_ManFindNameById(pNtk->pManName, i); if ( pName == NULL ) continue; Length = strlen(pName); if ( pName[0] == '0' || pName[0] == '1' ) { RetValue = 0; break; } for ( k = 0; k < Length; k++ ) if ( pName[k] == '(' || pName[k] == ')' || pName[k] == '!' || pName[k] == '*' || pName[k] == '+' ) { RetValue = 0; break; } if ( k < Length ) break; } if ( RetValue == 0 ) { printf( "The network cannot be written in the EQN format because object %d has name \"%s\".\n", i, pName ); printf( "Consider renaming the objects using command \"short_names\" and trying again.\n" ); } return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteGml.c000066400000000000000000000075331300674244400236130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteGml.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write the graph structure of AIG in GML.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteGml.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the graph structure of AIG in GML.] Description [Useful for graph visualization using tools such as yEd: http://www.yworks.com/] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; Abc_Obj_t * pObj, * pFanin; int i, k; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); // start the output stream pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteGml(): Cannot open the output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# GML for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); fprintf( pFile, "graph [\n" ); // output the POs fprintf( pFile, "\n" ); Abc_NtkForEachPo( pNtk, pObj, i ) { fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FFFF\" ]\n" ); // blue fprintf( pFile, " ]\n" ); } // output the PIs fprintf( pFile, "\n" ); Abc_NtkForEachPi( pNtk, pObj, i ) { fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FF00\" ]\n" ); // green fprintf( pFile, " ]\n" ); } // output the latches fprintf( pFile, "\n" ); Abc_NtkForEachLatch( pNtk, pObj, i ) { fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); fprintf( pFile, " graphics [ type \"rectangle\" fill \"#FF0000\" ]\n" ); // red fprintf( pFile, " ]\n" ); } // output the nodes fprintf( pFile, "\n" ); Abc_NtkForEachNode( pNtk, pObj, i ) { fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); fprintf( pFile, " graphics [ type \"ellipse\" fill \"#CCCCFF\" ]\n" ); // grey fprintf( pFile, " ]\n" ); } // output the edges fprintf( pFile, "\n" ); Abc_NtkForEachObj( pNtk, pObj, i ) { Abc_ObjForEachFanin( pObj, pFanin, k ) { fprintf( pFile, " edge [ source %5d target %5d\n", pObj->Id, pFanin->Id ); fprintf( pFile, " graphics [ type \"line\" arrow \"first\" ]\n" ); fprintf( pFile, " ]\n" ); } } fprintf( pFile, "]\n" ); fprintf( pFile, "\n" ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteList.c000066400000000000000000000232421300674244400240020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteList.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write the graph structure of sequential AIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteList.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START /* -------- Original Message -------- Subject: Re: abc release and retiming Date: Sun, 13 Nov 2005 20:31:18 -0500 (EST) From: Luca Carloni To: Alan Mishchenko Alan, My graph-representation file format is based on an adjacency list representation and is indeed quite simple, in fact maybe too simple... I used it in order to reason on relatively small weighed direct graphs. I simply list all vertices, one per line and for each vertex "V_source" I list all vertices that are "sinks" with respect to it, i.e. such that there is a distinct arc between "V_source" and each of them (in parenthesis I list the name of the edge and its weight (number of latency on that path). For instance, if you look at the following graph, you have that vertex "v_5" is connected to vertex "v_6" through a directed arc called "v_5_to_v_6" whose latency is equal to 3, i.e. there are three flip-flops on this arc. Still, notice that I sometime interpret the graph also as the representation of a LIS where each node corresponds to a shell encapsulating a sequential core module (i.e. a module which does not contain any combinational path between its inputs and its outputs). With this representation an arc of latency 3 is interpreted as a wire where two relay stations have been inserted in addition to the flip-flop terminating the output of the core module. Finally, notice that the name of the arc does not necessarily have to be "v_5_to_v_6", but it could have been something like "arc_222" or "xyz" as long as it is a unique name in the graph. Thanks, Luca Example of graph representation ----------------------------------------------------------------------------- v_5 > v_6 ([v_5_to_v_6] = 3), v_12 ([v_5_to_v_12] = 2). v_2 > v_4 ([v_2_to_v_4] = 1), v_10_s0 ([v_2_to_v_10_s0] = 6), v_12 ([v_2_to_v_12] = 3). v_9 > v_10_s0 ([v_9_to_v_10_s0] = 5), v_12 ([v_9_to_v_12] = 2). v_12 > v_13 ([v_12_to_v_13] = 5). v_13 > v_14 ([v_13_to_v_14] = 1). v_6 > v_7 ([v_6_to_v_7] = 2). v_4 > v_5 ([v_4_to_v_5] = 2). v_1 > v_2 ([v_1_to_v_2] = 1). v_7 > v_8 ([v_7_to_v_8] = 2). t > . v_14 > t ([v_14_to_t] = 1), v_5 ([v_14_to_v_5] = 1). v_8 > v_9 ([v_8_to_v_9] = 2). s > v_1 ([s_to_v_1] = 1). v_10_s0 > v_10_s1 ([v_10_s0_to_v_10_s1] = 1). v_10_s1 > v_4 ([v_10_s1__v_4] = 1), v_8 ([v_10_s1__v_8] = 1). ----------------------------------------------------------------------------- */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ); static void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the adjacency list for a sequential AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ) { FILE * pFile; Abc_Obj_t * pObj; int i; // assert( Abc_NtkIsSeq(pNtk) ); // start the output stream pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteList(): Cannot open the output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# Adjacency list for sequential AIG \"%s\"\n", pNtk->pName ); fprintf( pFile, "# written by ABC on %s\n", Extra_TimeStamp() ); // write the constant node if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk) ) > 0 ) Io_WriteListEdge( pFile, Abc_AigConst1(pNtk) ); // write the PI edges Abc_NtkForEachPi( pNtk, pObj, i ) Io_WriteListEdge( pFile, pObj ); // write the internal nodes Abc_AigForEachAnd( pNtk, pObj, i ) Io_WriteListEdge( pFile, pObj ); // write the host node if ( fUseHost ) Io_WriteListHost( pFile, pNtk ); else Abc_NtkForEachPo( pNtk, pObj, i ) Io_WriteListEdge( pFile, pObj ); fprintf( pFile, "\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Writes the adjacency list for one edge in a sequential AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) { fprintf( pFile, " %s", Abc_ObjName(pFanout) ); fprintf( pFile, " ([%s_to_", Abc_ObjName(pObj) ); // fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) ); fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), 0 ); if ( i != Abc_ObjFanoutNum(pObj) - 1 ) fprintf( pFile, "," ); } fprintf( pFile, "." ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Writes the adjacency list for one edge in a sequential AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachPo( pNtk, pObj, i ) { fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); fprintf( pFile, " %s ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), "HOST", 0 ); fprintf( pFile, "." ); fprintf( pFile, "\n" ); } fprintf( pFile, "%-10s > ", "HOST" ); Abc_NtkForEachPi( pNtk, pObj, i ) { fprintf( pFile, " %s", Abc_ObjName(pObj) ); fprintf( pFile, " ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), 0 ); if ( i != Abc_NtkPiNum(pNtk) - 1 ) fprintf( pFile, "," ); } fprintf( pFile, "." ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Writes the adjacency list for a sequential AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; Abc_Obj_t * pObj, * pFanout; int i, k; assert( Abc_NtkIsLogic(pNtk) ); // start the output stream pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteCellNet(): Cannot open the output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# CellNet file for network \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // the only tricky part with writing is handling latches: // each latch comes with (a) single-input latch-input node, (b) latch proper, (c) single-input latch-output node // we arbitrarily decide to use the interger ID of the latch-input node to represent the latch in the file // (this ID is used for both the cell and the net driven by that cell) // write the PIs Abc_NtkForEachPi( pNtk, pObj, i ) fprintf( pFile, "cell %d is 0\n", pObj->Id ); // write the POs Abc_NtkForEachPo( pNtk, pObj, i ) fprintf( pFile, "cell %d is 1\n", pObj->Id ); // write the latches (use the ID of latch input) Abc_NtkForEachLatch( pNtk, pObj, i ) fprintf( pFile, "cell %d is 2\n", Abc_ObjFanin0(pObj)->Id ); // write the logic nodes Abc_NtkForEachNode( pNtk, pObj, i ) fprintf( pFile, "cell %d is %d\n", pObj->Id, 3+Abc_ObjFaninNum(pObj) ); // write the nets driven by PIs Abc_NtkForEachPi( pNtk, pObj, i ) { fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); Abc_ObjForEachFanout( pObj, pFanout, k ) fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); fprintf( pFile, "\n" ); } // write the nets driven by latches Abc_NtkForEachLatch( pNtk, pObj, i ) { fprintf( pFile, "net %d %d 0", Abc_ObjFanin0(pObj)->Id, Abc_ObjFanin0(pObj)->Id ); pObj = Abc_ObjFanout0(pObj); Abc_ObjForEachFanout( pObj, pFanout, k ) fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); fprintf( pFile, "\n" ); } // write the nets driven by nodes Abc_NtkForEachNode( pNtk, pObj, i ) { fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); Abc_ObjForEachFanout( pObj, pFanout, k ) fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); fprintf( pFile, "\n" ); } fprintf( pFile, "\n" ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWritePla.c000066400000000000000000000343321300674244400236050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWritePla.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write the network in BENCH format.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWritePla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the network in PLA format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Obj_t * pNode, * pFanin, * pDriver; char * pCubeIn, * pCubeOut, * pCube; int i, k, nProducts, nInputs, nOutputs, nFanins; nProducts = 0; Abc_NtkForEachCo( pNtk, pNode, i ) { pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); if ( !Abc_ObjIsNode(pDriver) ) { nProducts++; continue; } if ( Abc_NodeIsConst(pDriver) ) { if ( Abc_NodeIsConst1(pDriver) ) nProducts++; continue; } nProducts += Abc_SopGetCubeNum((char *)pDriver->pData); } // collect the parameters nInputs = Abc_NtkCiNum(pNtk); nOutputs = Abc_NtkCoNum(pNtk); pCubeIn = ABC_ALLOC( char, nInputs + 1 ); pCubeOut = ABC_ALLOC( char, nOutputs + 1 ); memset( pCubeIn, '-', nInputs ); pCubeIn[nInputs] = 0; memset( pCubeOut, '0', nOutputs ); pCubeOut[nOutputs] = 0; // write the header fprintf( pFile, ".i %d\n", nInputs ); fprintf( pFile, ".o %d\n", nOutputs ); fprintf( pFile, ".ilb" ); Abc_NtkForEachCi( pNtk, pNode, i ) fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); fprintf( pFile, "\n" ); fprintf( pFile, ".ob" ); Abc_NtkForEachCo( pNtk, pNode, i ) fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pNode)) ); fprintf( pFile, "\n" ); fprintf( pFile, ".p %d\n", nProducts ); // mark the CI nodes Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)i; // write the cubes pProgress = Extra_ProgressBarStart( stdout, nOutputs ); Abc_NtkForEachCo( pNtk, pNode, i ) { // prepare the output cube if ( i - 1 >= 0 ) pCubeOut[i-1] = '0'; pCubeOut[i] = '1'; // consider special cases of nodes pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); if ( !Abc_ObjIsNode(pDriver) ) { assert( Abc_ObjIsCi(pDriver) ); pCubeIn[(int)(ABC_PTRUINT_T)pDriver->pCopy] = '1' - Abc_ObjFaninC0(pNode); fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); pCubeIn[(int)(ABC_PTRUINT_T)pDriver->pCopy] = '-'; continue; } if ( Abc_NodeIsConst(pDriver) ) { if ( Abc_NodeIsConst1(pDriver) ) fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); continue; } // make sure the cover is not complemented assert( !Abc_SopIsComplement( (char *)pDriver->pData ) ); // write the cubes nFanins = Abc_ObjFaninNum(pDriver); Abc_SopForEachCube( (char *)pDriver->pData, nFanins, pCube ) { Abc_ObjForEachFanin( pDriver, pFanin, k ) { pFanin = Abc_ObjFanin0Ntk(pFanin); assert( (int)(ABC_PTRUINT_T)pFanin->pCopy < nInputs ); pCubeIn[(int)(ABC_PTRUINT_T)pFanin->pCopy] = pCube[k]; } fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); } // clean the cube for future writing Abc_ObjForEachFanin( pDriver, pFanin, k ) { pFanin = Abc_ObjFanin0Ntk(pFanin); assert( Abc_ObjIsCi(pFanin) ); pCubeIn[(int)(ABC_PTRUINT_T)pFanin->pCopy] = '-'; } Extra_ProgressBarUpdate( pProgress, i, NULL ); } Extra_ProgressBarStop( pProgress ); fprintf( pFile, ".e\n" ); // clean the CI nodes Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = NULL; ABC_FREE( pCubeIn ); ABC_FREE( pCubeOut ); return 1; } /**Function************************************************************* Synopsis [Writes the network in PLA format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName ) { Abc_Ntk_t * pExdc; FILE * pFile; assert( Abc_NtkIsSopNetlist(pNtk) ); assert( Abc_NtkLevel(pNtk) == 1 ); pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" ); return 0; } fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the network Io_WritePlaOne( pFile, pNtk ); // write EXDC network if it exists pExdc = Abc_NtkExdc( pNtk ); if ( pExdc ) printf( "Io_WritePla: EXDC is not written (warning).\n" ); // finalize the file fclose( pFile ); return 1; } #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Writes the network in PLA format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteMoPlaOneInt( FILE * pFile, Abc_Ntk_t * pNtk, DdManager * dd, Vec_Ptr_t * vFuncs ) { Abc_Obj_t * pNode; DdNode * bOnset, * bOffset, * bCube, * bFunc, * bTemp, * zCover; int i, k, nInputs, nOutputs; int nCubes, fPhase; assert( Vec_PtrSize(vFuncs) == Abc_NtkCoNum(pNtk) ); assert( dd->size == Abc_NtkCiNum(pNtk) ); assert( dd->size <= 1000 ); // collect the parameters nInputs = Abc_NtkCiNum(pNtk); nOutputs = Abc_NtkCoNum(pNtk); assert( nOutputs > 1 ); // create extra variables for ( i = 0; i < nOutputs; i++ ) Cudd_bddNewVarAtLevel( dd, i ); assert( dd->size == nInputs + nOutputs ); // create ON and OFF sets bOnset = Cudd_ReadLogicZero( dd ); Cudd_Ref(bOnset); bOffset = Cudd_ReadLogicZero( dd ); Cudd_Ref(bOffset); for ( i = 0; i < nOutputs; i++ ) { bFunc = (DdNode *)Vec_PtrEntry(vFuncs, i); // create onset bCube = Cudd_bddAnd( dd, Cudd_bddIthVar(dd, nInputs+i), bFunc ); Cudd_Ref(bCube); for ( k = 0; k < nOutputs; k++ ) if ( k != i ) { bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(Cudd_bddIthVar(dd, nInputs+k)) ); Cudd_Ref(bCube); Cudd_RecursiveDeref( dd, bTemp ); } bOnset = Cudd_bddOr( dd, bTemp = bOnset, bCube ); Cudd_Ref(bOnset); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); // create offset bCube = Cudd_bddAnd( dd, Cudd_bddIthVar(dd, nInputs+i), Cudd_Not(bFunc) ); Cudd_Ref(bCube); bOffset = Cudd_bddOr( dd, bTemp = bOffset, bCube ); Cudd_Ref(bOffset); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); printf( "Trying %d output.\n", i ); printf( "Onset = %d nodes.\n", Cudd_DagSize(bOnset) ); printf( "Offset = %d nodes.\n", Cudd_DagSize(bOffset) ); } Cudd_zddVarsFromBddVars( dd, 2 ); // derive ISOP { extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); DdNode * bCover, * zCover0, * zCover1; int nCubes0, nCubes1; // get the ZDD of the negative polarity bCover = Cudd_zddIsop( dd, bOffset, Cudd_Not(bOnset), &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, bOnset, Cudd_Not(bOffset), &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; } } Cudd_RecursiveDeref( dd, bOnset ); Cudd_RecursiveDeref( dd, bOffset ); Cudd_RecursiveDerefZdd( dd, zCover ); printf( "Cover = %d nodes.\n", Cudd_DagSize(zCover) ); printf( "ISOP = %d\n", nCubes ); // write the header fprintf( pFile, ".i %d\n", nInputs ); fprintf( pFile, ".o %d\n", nOutputs ); fprintf( pFile, ".ilb" ); Abc_NtkForEachCi( pNtk, pNode, i ) fprintf( pFile, " %s", Abc_ObjName(pNode) ); fprintf( pFile, "\n" ); fprintf( pFile, ".ob" ); Abc_NtkForEachCo( pNtk, pNode, i ) fprintf( pFile, " %s", Abc_ObjName(pNode) ); fprintf( pFile, "\n" ); fprintf( pFile, ".p %d\n", nCubes ); fprintf( pFile, ".e\n" ); return 1; } /**Function************************************************************* Synopsis [Writes the network in PLA format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteMoPlaOneIntMinterms( FILE * pFile, Abc_Ntk_t * pNtk, DdManager * dd, Vec_Ptr_t * vFuncs ) { int pValues[1000]; Abc_Obj_t * pNode; int i, k, nProducts, nInputs, nOutputs; assert( Vec_PtrSize(vFuncs) == Abc_NtkCoNum(pNtk) ); assert( dd->size == Abc_NtkCiNum(pNtk) ); assert( dd->size <= 1000 ); // collect the parameters nInputs = Abc_NtkCiNum(pNtk); nOutputs = Abc_NtkCoNum(pNtk); nProducts = (1 << nInputs); // write the header fprintf( pFile, ".i %d\n", nInputs ); fprintf( pFile, ".o %d\n", nOutputs ); fprintf( pFile, ".ilb" ); Abc_NtkForEachCi( pNtk, pNode, i ) fprintf( pFile, " %s", Abc_ObjName(pNode) ); fprintf( pFile, "\n" ); fprintf( pFile, ".ob" ); Abc_NtkForEachCo( pNtk, pNode, i ) fprintf( pFile, " %s", Abc_ObjName(pNode) ); fprintf( pFile, "\n" ); fprintf( pFile, ".p %d\n", nProducts ); // iterate through minterms for ( k = 0; k < nProducts; k++ ) { for ( i = 0; i < nInputs; i++ ) fprintf( pFile, "%c", '0' + (pValues[i] = ((k >> i) & 1)) ); fprintf( pFile, " " ); for ( i = 0; i < nOutputs; i++ ) fprintf( pFile, "%c", '0' + (Cudd_ReadOne(dd) == Cudd_Eval(dd, (DdNode *)Vec_PtrEntry(vFuncs, i), pValues)) ); fprintf( pFile, "\n" ); } fprintf( pFile, ".e\n" ); return 1; } /**Function************************************************************* Synopsis [Writes the network in PLA format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteMoPlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) { int fVerbose = 1; DdManager * dd; DdNode * bFunc; Vec_Ptr_t * vFuncsGlob; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsStrash(pNtk) ); dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); if ( dd == NULL ) return 0; if ( fVerbose ) 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) ); // consider minterms Io_WriteMoPlaOneIntMinterms( pFile, pNtk, dd, vFuncsGlob ); Abc_NtkFreeGlobalBdds( pNtk, 0 ); // cleanup Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) Cudd_RecursiveDeref( dd, bFunc ); Vec_PtrFree( vFuncsGlob ); Extra_StopManager( dd ); return 1; } /**Function************************************************************* Synopsis [Writes the network in PLA format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; assert( Abc_NtkIsStrash(pNtk) ); if ( Abc_NtkCiNum(pNtk) > 16 ) { printf( "Cannot write multi-output PLA for more than 16 inputs.\n" ); return 0; } pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" ); return 0; } fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); Io_WriteMoPlaOne( pFile, pNtk ); fclose( pFile ); return 1; } #else int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) { return 1; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteSmv.c000066400000000000000000000202641300674244400236350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteSmv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write the network in SMV format.] Author [Satrajit Chatterjee] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteSmv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Io_WriteSmvCheckNames( Abc_Ntk_t * pNtk ); static int Io_WriteSmvOne( FILE * pFile, Abc_Ntk_t * pNtk ); static int Io_WriteSmvOneNode( FILE * pFile, Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // This returns a pointer to a static area, so be careful in using results // of this function i.e. don't call this twice in the same printf call. // // This function replaces '|' with '_' I think abc introduces '|' when // flattening hierarchy. The '|' is interpreted as a or function by nusmv // which is unfortunate. This probably should be fixed elsewhere. static char *cleanUNSAFE( const char *s ) { char *t; static char buffer[1024]; assert (strlen(s) < 1024); strcpy(buffer, s); for (t = buffer; *t != 0; ++t) *t = (*t == '|') ? '_' : *t; return buffer; } static int hasPrefix(const char *needle, const char *haystack) { return (strncmp(haystack, needle, strlen(needle)) == 0); } /**Function************************************************************* Synopsis [Writes the network in SMV format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteSmv( Abc_Ntk_t * pNtk, char * pFileName ) { Abc_Ntk_t * pExdc; FILE * pFile; assert( Abc_NtkIsSopNetlist(pNtk) ); if ( !Io_WriteSmvCheckNames(pNtk) ) { fprintf( stdout, "Io_WriteSmv(): Signal names in this benchmark contain parentheses making them impossible to reproduce in the SMV format. Use \"short_names\".\n" ); return 0; } pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteSmv(): Cannot open the output file.\n" ); return 0; } fprintf( pFile, "-- benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); // write the network Io_WriteSmvOne( pFile, pNtk ); // write EXDC network if it exists pExdc = Abc_NtkExdc( pNtk ); if ( pExdc ) printf( "Io_WriteSmv: EXDC is not written (warning).\n" ); // finalize the file fclose( pFile ); return 1; } /**Function************************************************************* Synopsis [Writes the network in SMV format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteSmvOne( FILE * pFile, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Obj_t * pNode; int i; // write the PIs/POs/latches fprintf( pFile, "MODULE main\n"); // nusmv needs top module to be main fprintf ( pFile, "\n" ); fprintf( pFile, "VAR -- inputs\n"); Abc_NtkForEachPi( pNtk, pNode, i ) fprintf( pFile, " %s : boolean;\n", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode))) ); fprintf ( pFile, "\n" ); fprintf( pFile, "VAR -- state variables\n"); Abc_NtkForEachLatch( pNtk, pNode, i ) fprintf( pFile, " %s : boolean;\n", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode)))) ); fprintf ( pFile, "\n" ); // No outputs needed for NuSMV: // TODO: Add sepcs by recognizing assume_.* and assert_.* // // Abc_NtkForEachPo( pNtk, pNode, i ) // fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); // write internal nodes fprintf( pFile, "DEFINE\n"); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); Io_WriteSmvOneNode( pFile, pNode ); } Extra_ProgressBarStop( pProgress ); fprintf ( pFile, "\n" ); fprintf( pFile, "ASSIGN\n"); Abc_NtkForEachLatch( pNtk, pNode, i ) { int Reset = (int)(ABC_PTRUINT_T)Abc_ObjData( pNode ); assert (Reset >= 1); assert (Reset <= 3); if (Reset != 3) { fprintf( pFile, " init(%s) := %d;\n", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode)))), Reset - 1); } fprintf( pFile, " next(%s) := ", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode)))) ); fprintf( pFile, "%s;\n", cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode)))) ); } fprintf ( pFile, "\n" ); Abc_NtkForEachPo( pNtk, pNode, i ) { const char *n = cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(pNode))); // fprintf( pFile, "-- output %s;\n", n ); if (hasPrefix("assume_fair_", n)) { fprintf( pFile, "FAIRNESS %s;\n", n ); } else if (hasPrefix("Assert_", n) || hasPrefix("assert_safety_", n)) { fprintf( pFile, "INVARSPEC %s;\n", n ); } else if (hasPrefix("assert_fair_", n)) { fprintf( pFile, "LTLSPEC G F %s;\n", n ); } } return 1; } /**Function************************************************************* Synopsis [Writes the network in SMV format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteSmvOneNode( FILE * pFile, Abc_Obj_t * pNode ) { int nFanins; assert( Abc_ObjIsNode(pNode) ); nFanins = Abc_ObjFaninNum(pNode); if ( nFanins == 0 ) { // write the constant 1 node assert( Abc_NodeIsConst1(pNode) ); fprintf( pFile, " %s", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode)) ) ); fprintf( pFile, " := 1;\n" ); } else if ( nFanins == 1 ) { // write the interver/buffer if ( Abc_NodeIsBuf(pNode) ) { fprintf( pFile, " %s := ", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode))) ); fprintf( pFile, "%s;\n", cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(pNode))) ); } else { fprintf( pFile, " %s := !", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode))) ); fprintf( pFile, "%s;\n", cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(pNode))) ); } } else { // write the AND gate fprintf( pFile, " %s", cleanUNSAFE(Abc_ObjName(Abc_ObjFanout0(pNode))) ); fprintf( pFile, " := %s & ", cleanUNSAFE(Abc_ObjName(Abc_ObjFanin0(pNode))) ); fprintf( pFile, "%s;\n", cleanUNSAFE(Abc_ObjName(Abc_ObjFanin1(pNode))) ); } return 1; } /**Function************************************************************* Synopsis [Returns 1 if the names cannot be written into the bench file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteSmvCheckNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; char * pName; int i; Abc_NtkForEachObj( pNtk, pObj, i ) for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ ) if ( *pName == '(' || *pName == ')' ) return 0; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/ioWriteVerilog.c000066400000000000000000000537171300674244400245100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioWriteVerilog.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to output a special subset of Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ioWriteVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioAbc.h" #include "base/main/main.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ); static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ); static char * Io_WriteVerilogGetName( char * pName ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Write verilog.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName ) { Abc_Ntk_t * pNetlist; FILE * pFile; int i; // can only write nodes represented using local AIGs if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) ) { printf( "Io_WriteVerilog(): Can produce Verilog for mapped or AIG netlists only.\n" ); return; } // start the output stream pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName ); return; } // write the equations for the network fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); fprintf( pFile, "\n" ); // write modules if ( pNtk->pDesign ) { // write the network first Io_WriteVerilogInt( pFile, pNtk ); // write other things Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pNetlist, i ) { assert( Abc_NtkIsNetlist(pNetlist) ); if ( pNetlist == pNtk ) continue; fprintf( pFile, "\n" ); Io_WriteVerilogInt( pFile, pNetlist ); } } else { Io_WriteVerilogInt( pFile, pNtk ); } fprintf( pFile, "\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Writes verilog.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ) { // write inputs and outputs // fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); fprintf( pFile, "module %s ( ", Io_WriteVerilogGetName(Abc_NtkName(pNtk)) ); // add the clock signal if it does not exist if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) fprintf( pFile, "clock, " ); // write other primary inputs fprintf( pFile, "\n " ); if ( Abc_NtkPiNum(pNtk) > 0 ) { Io_WriteVerilogPis( pFile, pNtk, 3 ); fprintf( pFile, ",\n " ); } if ( Abc_NtkPoNum(pNtk) > 0 ) Io_WriteVerilogPos( pFile, pNtk, 3 ); fprintf( pFile, " );\n" ); // add the clock signal if it does not exist if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) fprintf( pFile, " input clock;\n" ); // write inputs, outputs, registers, and wires if ( Abc_NtkPiNum(pNtk) > 0 ) { // fprintf( pFile, " input gclk," ); fprintf( pFile, " input " ); Io_WriteVerilogPis( pFile, pNtk, 10 ); fprintf( pFile, ";\n" ); } if ( Abc_NtkPoNum(pNtk) > 0 ) { fprintf( pFile, " output" ); Io_WriteVerilogPos( pFile, pNtk, 5 ); fprintf( pFile, ";\n" ); } // if this is not a blackbox, write internal signals if ( !Abc_NtkHasBlackbox(pNtk) ) { if ( Abc_NtkLatchNum(pNtk) > 0 ) { fprintf( pFile, " reg" ); Io_WriteVerilogRegs( pFile, pNtk, 4 ); fprintf( pFile, ";\n" ); } if ( Io_WriteVerilogWiresCount(pNtk) > 0 ) { fprintf( pFile, " wire" ); Io_WriteVerilogWires( pFile, pNtk, 4 ); fprintf( pFile, ";\n" ); } // write nodes Io_WriteVerilogObjects( pFile, pNtk ); // write registers if ( Abc_NtkLatchNum(pNtk) > 0 ) Io_WriteVerilogLatches( pFile, pNtk ); } // finalize the file fprintf( pFile, "endmodule\n\n" ); } /**Function************************************************************* Synopsis [Writes the primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) { Abc_Obj_t * pTerm, * pNet; int LineLength; int AddedLength; int NameCounter; int i; LineLength = Start; NameCounter = 0; Abc_NtkForEachPi( pNtk, pTerm, i ) { pNet = Abc_ObjFanout0(pTerm); // get the line length after this name is written AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, "\n " ); // reset the line length LineLength = 3; NameCounter = 0; } fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," ); LineLength += AddedLength; NameCounter++; } } /**Function************************************************************* Synopsis [Writes the primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) { Abc_Obj_t * pTerm, * pNet, * pSkip; int LineLength; int AddedLength; int NameCounter; int i; int nskip; pSkip = 0; nskip = 0; LineLength = Start; NameCounter = 0; Abc_NtkForEachPo( pNtk, pTerm, i ) { pNet = Abc_ObjFanin0(pTerm); if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) ) { // Skip this output since it is a feedthrough -- the same // name will appear as an input and an output which other // tools reading verilog do not like. nskip++; pSkip = pNet; // save an example of skipped net continue; } // get the line length after this name is written AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, "\n " ); // reset the line length LineLength = 3; NameCounter = 0; } fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," ); LineLength += AddedLength; NameCounter++; } if (nskip != 0) { assert (pSkip); printf( "Io_WriteVerilogPos(): Omitted %d feedthrough nets from output list of module (e.g. %s).\n", nskip, Abc_ObjName(pSkip) ); return; } } /**Function************************************************************* Synopsis [Writes the wires.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) { Abc_Obj_t * pObj, * pNet, * pBox, * pTerm; int LineLength; int AddedLength; int NameCounter; int i, k, Counter, nNodes; // count the number of wires nNodes = Io_WriteVerilogWiresCount( pNtk ); // write the wires Counter = 0; LineLength = Start; NameCounter = 0; Abc_NtkForEachNode( pNtk, pObj, i ) { if ( i == 0 ) continue; pNet = Abc_ObjFanout0(pObj); if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) continue; Counter++; // get the line length after this name is written AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, "\n " ); // reset the line length LineLength = 3; NameCounter = 0; } fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); LineLength += AddedLength; NameCounter++; } Abc_NtkForEachLatch( pNtk, pObj, i ) { pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); Counter++; // get the line length after this name is written AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, "\n " ); // reset the line length LineLength = 3; NameCounter = 0; } fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); LineLength += AddedLength; NameCounter++; } Abc_NtkForEachBox( pNtk, pBox, i ) { if ( Abc_ObjIsLatch(pBox) ) continue; Abc_ObjForEachFanin( pBox, pTerm, k ) { pNet = Abc_ObjFanin0(pTerm); Counter++; // get the line length after this name is written AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, "\n " ); // reset the line length LineLength = 3; NameCounter = 0; } fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); LineLength += AddedLength; NameCounter++; } Abc_ObjForEachFanout( pBox, pTerm, k ) { pNet = Abc_ObjFanout0(pTerm); if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) continue; Counter++; // get the line length after this name is written AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, "\n " ); // reset the line length LineLength = 3; NameCounter = 0; } fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); LineLength += AddedLength; NameCounter++; } } assert( Counter == nNodes ); } /**Function************************************************************* Synopsis [Writes the regs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) { Abc_Obj_t * pLatch, * pNet; int LineLength; int AddedLength; int NameCounter; int i, Counter, nNodes; // count the number of latches nNodes = Abc_NtkLatchNum(pNtk); // write the wires Counter = 0; LineLength = Start; NameCounter = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { pNet = Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); Counter++; // get the line length after this name is written AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) { // write the line extender fprintf( pFile, "\n " ); // reset the line length LineLength = 3; NameCounter = 0; } fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); LineLength += AddedLength; NameCounter++; } } /**Function************************************************************* Synopsis [Writes the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pLatch; int i; if ( Abc_NtkLatchNum(pNtk) == 0 ) return; // write the latches // fprintf( pFile, " always @(posedge %s) begin\n", Io_WriteVerilogGetName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0))) ); // fprintf( pFile, " always begin\n" ); fprintf( pFile, " always @ (posedge clock) begin\n" ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { fprintf( pFile, " %s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); fprintf( pFile, " <= %s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pLatch)))) ); } fprintf( pFile, " end\n" ); // check if there are initial values Abc_NtkForEachLatch( pNtk, pLatch, i ) if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO || Abc_LatchInit(pLatch) == ABC_INIT_ONE ) break; if ( i == Abc_NtkLatchNum(pNtk) ) return; // write the initial values fprintf( pFile, " initial begin\n" ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO ) fprintf( pFile, " %s <= 1\'b0;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE ) fprintf( pFile, " %s <= 1\'b1;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); } fprintf( pFile, " end\n" ); } /**Function************************************************************* Synopsis [Writes the nodes and boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ) { int fUseSimpleGateNames = 0; Vec_Vec_t * vLevels; Abc_Ntk_t * pNtkBox; Abc_Obj_t * pObj, * pTerm, * pFanin; Hop_Obj_t * pFunc; int i, k, Counter, nDigits, Length; // write boxes nDigits = Abc_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); Counter = 0; Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; pNtkBox = (Abc_Ntk_t *)pObj->pData; fprintf( pFile, " %s box%0*d", pNtkBox->pName, nDigits, Counter++ ); fprintf( pFile, "(" ); Abc_NtkForEachPi( pNtkBox, pTerm, k ) { fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) ); fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) ); } Abc_NtkForEachPo( pNtkBox, pTerm, k ) { fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) ); fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " ); } fprintf( pFile, ");\n" ); } // write nodes if ( Abc_NtkHasMapping(pNtk) ) { Length = Mio_LibraryReadGateNameMax((Mio_Library_t *)pNtk->pManFunc); nDigits = Abc_Base10Log( Abc_NtkNodeNum(pNtk) ); Counter = 0; Abc_NtkForEachNode( pNtk, pObj, k ) { Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; Mio_Pin_t * pGatePin; if ( Abc_ObjFaninNum(pObj) == 0 && (!strcmp(Mio_GateReadName(pGate), "_const0_") || !strcmp(Mio_GateReadName(pGate), "_const1_")) ) { fprintf( pFile, " %-*s %s = 1\'b%d;\n", Length, "assign", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )), !strcmp(Mio_GateReadName(pGate), "_const1_") ); continue; } // write the node if ( fUseSimpleGateNames ) { fprintf( pFile, "%-*s ", Length, Mio_GateReadName(pGate) ); fprintf( pFile, "( %s", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) ); for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) fprintf( pFile, ", %s", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) ); assert ( i == Abc_ObjFaninNum(pObj) ); fprintf( pFile, " );\n" ); } else { fprintf( pFile, " %-*s g%0*d", Length, Mio_GateReadName(pGate), nDigits, Counter++ ); fprintf( pFile, "(" ); for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_PinReadName(pGatePin)) ); fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) ); } assert ( i == Abc_ObjFaninNum(pObj) ); fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) ); fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) ); fprintf( pFile, ");\n" ); } } } else { vLevels = Vec_VecAlloc( 10 ); Abc_NtkForEachNode( pNtk, pObj, i ) { pFunc = (Hop_Obj_t *)pObj->pData; fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); // set the input names Abc_ObjForEachFanin( pObj, pFanin, k ) Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin))); // write the formula Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 ); fprintf( pFile, ";\n" ); // clear the input names Abc_ObjForEachFanin( pObj, pFanin, k ) ABC_FREE( Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData ); } Vec_VecFree( vLevels ); } } /**Function************************************************************* Synopsis [Counts the number of wires.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pNet, * pBox; int i, k, nWires; nWires = Abc_NtkLatchNum(pNtk); Abc_NtkForEachNode( pNtk, pObj, i ) { if ( i == 0 ) continue; pNet = Abc_ObjFanout0(pObj); if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) continue; nWires++; } Abc_NtkForEachBox( pNtk, pBox, i ) { if ( Abc_ObjIsLatch(pBox) ) continue; nWires += Abc_ObjFaninNum(pBox); Abc_ObjForEachFanout( pBox, pObj, k ) { pNet = Abc_ObjFanout0(pObj); if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) continue; nWires++; } } return nWires; } /**Function************************************************************* Synopsis [Prepares the name for writing the Verilog file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Io_WriteVerilogGetName( char * pName ) { static char Buffer[500]; int Length, i; Length = strlen(pName); // consider the case of a signal having name "0" or "1" if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) ) { for ( i = 0; i < Length; i++ ) if ( !((pName[i] >= 'a' && pName[i] <= 'z') || (pName[i] >= 'A' && pName[i] <= 'Z') || (pName[i] >= '0' && pName[i] <= '9') || pName[i] == '_') ) break; if ( i == Length ) return pName; } // create Verilog style name Buffer[0] = '\\'; for ( i = 0; i < Length; i++ ) Buffer[i+1] = pName[i]; Buffer[Length+1] = ' '; Buffer[Length+2] = 0; return Buffer; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/io/module.make000066400000000000000000000015671300674244400235120ustar00rootroot00000000000000SRC += src/base/io/io.c \ src/base/io/ioReadAiger.c \ src/base/io/ioReadBaf.c \ src/base/io/ioReadBblif.c \ src/base/io/ioReadBench.c \ src/base/io/ioReadBlif.c \ src/base/io/ioReadBlifAig.c \ src/base/io/ioReadBlifMv.c \ src/base/io/ioReadDsd.c \ src/base/io/ioReadEdif.c \ src/base/io/ioReadEqn.c \ src/base/io/ioReadPla.c \ src/base/io/ioReadPlaMo.c \ src/base/io/ioReadVerilog.c \ src/base/io/ioUtil.c \ src/base/io/ioWriteAiger.c \ src/base/io/ioWriteBaf.c \ src/base/io/ioWriteBblif.c \ src/base/io/ioWriteBench.c \ src/base/io/ioWriteBlif.c \ src/base/io/ioWriteBlifMv.c \ src/base/io/ioWriteBook.c \ src/base/io/ioWriteCnf.c \ src/base/io/ioWriteDot.c \ src/base/io/ioWriteEqn.c \ src/base/io/ioWriteGml.c \ src/base/io/ioWriteList.c \ src/base/io/ioWritePla.c \ src/base/io/ioWriteVerilog.c \ src/base/io/ioWriteSmv.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/000077500000000000000000000000001300674244400216725ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/libSupport.c000066400000000000000000000145101300674244400242020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [libSupport.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [Support for external libaries.] Author [Mike Case] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: libSupport.c,v 1.1 2005/09/06 19:59:51 casem Exp $] ***********************************************************************/ #include #include #include "base/abc/abc.h" #include "mainInt.h" ABC_NAMESPACE_IMPL_START #if defined(ABC_NO_DYNAMIC_LINKING) #define WIN32 #endif #ifndef WIN32 # include # include # include #endif // fix by Paddy O'Brien on Sep 22, 2009 #ifdef __CYGWIN__ #ifndef RTLD_LOCAL #define RTLD_LOCAL 0 #endif #endif #define MAX_LIBS 256 static void* libHandles[MAX_LIBS+1]; // will be null terminated typedef void (*lib_init_end_func) (Abc_Frame_t * pAbc); //////////////////////////////////////////////////////////////////////////////////////////////////// // This will find all the ABC library extensions in the current directory and load them all. //////////////////////////////////////////////////////////////////////////////////////////////////// void open_libs() { int curr_lib = 0; #ifdef WIN32 // printf("Warning: open_libs WIN32 not implemented.\n"); #else DIR* dirp; struct dirent* dp; char *env, *init_p, *p; int done; env = getenv ("ABC_LIB_PATH"); if (env == NULL) { // printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n"); init_p = ABC_ALLOC( char, (2*sizeof(char)) ); init_p[0]='.'; init_p[1] = 0; } else { init_p = ABC_ALLOC( char, ((strlen(env)+1)*sizeof(char)) ); strcpy (init_p, env); } // Extract directories and read libraries done = 0; p = init_p; while (!done) { char *endp = strchr (p,':'); if (endp == NULL) done = 1; // last directory in the list else *endp = 0; // end of string dirp = opendir(p); if (dirp == NULL) { // printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p); continue; } while ((dp = readdir(dirp)) != NULL) { if ((strncmp("libabc_", dp->d_name, 7) == 0) && (strcmp(".so", dp->d_name + strlen(dp->d_name) - 3) == 0)) { // make sure we don't overflow the handle array if (curr_lib >= MAX_LIBS) { printf("Warning: maximum number of ABC libraries (%d) exceeded. Not loading %s.\n", MAX_LIBS, dp->d_name); } // attempt to load it else { char* szPrefixed = ABC_ALLOC( char, ((strlen(dp->d_name) + strlen(p) + 2) * sizeof(char)) ); sprintf(szPrefixed, "%s/", p); strcat(szPrefixed, dp->d_name); libHandles[curr_lib] = dlopen(szPrefixed, RTLD_NOW | RTLD_LOCAL); // did the load succeed? if (libHandles[curr_lib] != 0) { printf("Loaded ABC library: %s (Abc library extension #%d)\n", szPrefixed, curr_lib); curr_lib++; } else { printf("Warning: failed to load ABC library %s:\n\t%s\n", szPrefixed, dlerror()); } ABC_FREE(szPrefixed); } } } closedir(dirp); p = endp+1; } ABC_FREE(init_p); #endif // null terminate the list of handles libHandles[curr_lib] = 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// // This will close all open ABC library extensions //////////////////////////////////////////////////////////////////////////////////////////////////// void close_libs() { #ifdef WIN32 printf("Warning: close_libs WIN32 not implemented.\n"); #else int i; for (i = 0; libHandles[i] != 0; i++) { if (dlclose(libHandles[i]) != 0) { printf("Warning: failed to close library %d\n", i); } libHandles[i] = 0; } #endif } //////////////////////////////////////////////////////////////////////////////////////////////////// // This will get a pointer to a function inside of an open library //////////////////////////////////////////////////////////////////////////////////////////////////// void* get_fnct_ptr(int lib_num, char* sym_name) { #ifdef WIN32 printf("Warning: get_fnct_ptr WIN32 not implemented.\n"); return 0; #else return dlsym(libHandles[lib_num], sym_name); #endif } //////////////////////////////////////////////////////////////////////////////////////////////////// // This will call an initialization function in every open library. //////////////////////////////////////////////////////////////////////////////////////////////////// void call_inits(Abc_Frame_t* pAbc) { int i; lib_init_end_func init_func; for (i = 0; libHandles[i] != 0; i++) { init_func = (lib_init_end_func) get_fnct_ptr(i, "abc_init"); if (init_func == 0) { printf("Warning: Failed to initialize library %d.\n", i); } else { (*init_func)(pAbc); } } } //////////////////////////////////////////////////////////////////////////////////////////////////// // This will call a shutdown function in every open library. //////////////////////////////////////////////////////////////////////////////////////////////////// void call_ends(Abc_Frame_t* pAbc) { int i; lib_init_end_func end_func; for (i = 0; libHandles[i] != 0; i++) { end_func = (lib_init_end_func) get_fnct_ptr(i, "abc_end"); if (end_func == 0) { printf("Warning: Failed to end library %d.\n", i); } else { (*end_func)(pAbc); } } } void Libs_Init(Abc_Frame_t * pAbc) { open_libs(); call_inits(pAbc); } void Libs_End(Abc_Frame_t * pAbc) { call_ends(pAbc); // It's good practice to close our libraries at this point, but this can mess up any backtrace printed by Valgind. // close_libs(); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/main.c000066400000000000000000000003361300674244400227640ustar00rootroot00000000000000#include ABC_NAMESPACE_IMPL_START int Abc_RealMain(int argc, char *argv[]); ABC_NAMESPACE_IMPL_END int main(int argc, char *argv[]) { return ABC_NAMESPACE_PREFIX Abc_RealMain(argc, argv); } berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/main.h000066400000000000000000000205211300674244400227670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [main.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [External declarations of the main package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: main.h,v 1.1 2008/05/14 22:13:13 wudenni Exp $] ***********************************************************************/ #ifndef ABC__base__main__main_h #define ABC__base__main__main_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// // core packages #include "base/abc/abc.h" #include "aig/gia/gia.h" // data structure packages #include "misc/vec/vec.h" #include "misc/st/st.h" ABC_NAMESPACE_HEADER_START // the framework containing all data typedef struct Abc_Frame_t_ Abc_Frame_t; ABC_NAMESPACE_HEADER_END #include "base/cmd/cmd.h" #include "base/io/ioAbc.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// TYPEDEFS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== main.c ===========================================================*/ extern ABC_DLL void Abc_Start(); extern ABC_DLL void Abc_Stop(); /*=== mainFrame.c ===========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ); extern ABC_DLL Gia_Man_t * Abc_FrameReadGia( Abc_Frame_t * p ); extern ABC_DLL FILE * Abc_FrameReadOut( Abc_Frame_t * p ); extern ABC_DLL FILE * Abc_FrameReadErr( Abc_Frame_t * p ); extern ABC_DLL int Abc_FrameReadMode( Abc_Frame_t * p ); extern ABC_DLL int Abc_FrameSetMode( Abc_Frame_t * p, int fNameMode ); extern ABC_DLL void Abc_FrameRestart( Abc_Frame_t * p ); extern ABC_DLL int Abc_FrameShowProgress( Abc_Frame_t * p ); extern ABC_DLL void Abc_FrameClearVerifStatus( Abc_Frame_t * p ); extern ABC_DLL void Abc_FrameUpdateGia( Abc_Frame_t * p, Gia_Man_t * pNew ); extern ABC_DLL Gia_Man_t * Abc_FrameGetGia( Abc_Frame_t * p ); extern ABC_DLL void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); extern ABC_DLL void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ); extern ABC_DLL void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); extern ABC_DLL void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p ); extern ABC_DLL void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ); extern ABC_DLL void Abc_FrameSetGlobalFrame( Abc_Frame_t * p ); extern ABC_DLL Abc_Frame_t * Abc_FrameGetGlobalFrame(); extern ABC_DLL Abc_Frame_t * Abc_FrameReadGlobalFrame(); extern ABC_DLL Vec_Ptr_t * Abc_FrameReadStore(); extern ABC_DLL int Abc_FrameReadStoreSize(); extern ABC_DLL void * Abc_FrameReadLibLut(); extern ABC_DLL void * Abc_FrameReadLibBox(); extern ABC_DLL void * Abc_FrameReadLibGen(); extern ABC_DLL void * Abc_FrameReadLibGen2(); extern ABC_DLL void * Abc_FrameReadLibSuper(); extern ABC_DLL void * Abc_FrameReadLibScl(); extern ABC_DLL void * Abc_FrameReadManDd(); extern ABC_DLL void * Abc_FrameReadManDec(); extern ABC_DLL void * Abc_FrameReadManDsd(); extern ABC_DLL void * Abc_FrameReadManDsd2(); extern ABC_DLL char * Abc_FrameReadFlag( char * pFlag ); extern ABC_DLL int Abc_FrameIsFlagEnabled( char * pFlag ); extern ABC_DLL int Abc_FrameIsBatchMode(); extern ABC_DLL int Abc_FrameIsBridgeMode(); extern ABC_DLL void Abc_FrameSetBridgeMode(); extern ABC_DLL int Abc_FrameReadBmcFrames( Abc_Frame_t * p ); extern ABC_DLL int Abc_FrameReadProbStatus( Abc_Frame_t * p ); extern ABC_DLL Abc_Cex_t * Abc_FrameReadCex( Abc_Frame_t * p ); extern ABC_DLL Vec_Ptr_t * Abc_FrameReadCexVec( Abc_Frame_t * p ); extern ABC_DLL Vec_Int_t * Abc_FrameReadStatusVec( Abc_Frame_t * p ); extern ABC_DLL Vec_Ptr_t * Abc_FrameReadPoEquivs( Abc_Frame_t * p ); extern ABC_DLL Vec_Int_t * Abc_FrameReadPoStatuses( Abc_Frame_t * p ); extern ABC_DLL Vec_Int_t * Abc_FrameReadObjIds( Abc_Frame_t * p ); extern ABC_DLL int Abc_FrameReadCexPiNum( Abc_Frame_t * p ); extern ABC_DLL int Abc_FrameReadCexRegNum( Abc_Frame_t * p ); extern ABC_DLL int Abc_FrameReadCexPo( Abc_Frame_t * p ); extern ABC_DLL int Abc_FrameReadCexFrame( Abc_Frame_t * p ); extern ABC_DLL void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_FrameSetNtkStoreSize( int nStored ); extern ABC_DLL void Abc_FrameSetLibLut( void * pLib ); extern ABC_DLL void Abc_FrameSetLibBox( void * pLib ); extern ABC_DLL void Abc_FrameSetLibGen( void * pLib ); extern ABC_DLL void Abc_FrameSetLibGen2( void * pLib ); extern ABC_DLL void Abc_FrameSetLibSuper( void * pLib ); extern ABC_DLL void Abc_FrameSetLibVer( void * pLib ); extern ABC_DLL void Abc_FrameSetFlag( char * pFlag, char * pValue ); extern ABC_DLL void Abc_FrameSetCex( Abc_Cex_t * pCex ); extern ABC_DLL void Abc_FrameSetNFrames( int nFrames ); extern ABC_DLL void Abc_FrameSetStatus( int Status ); extern ABC_DLL void Abc_FrameSetManDsd( void * pMan ); extern ABC_DLL void Abc_FrameSetManDsd2( void * pMan ); extern ABC_DLL void Abc_FrameSetInv( Vec_Int_t * vInv ); extern ABC_DLL void Abc_FrameSetCnf( Vec_Int_t * vInv ); extern ABC_DLL void Abc_FrameSetStr( Vec_Str_t * vInv ); extern ABC_DLL int Abc_FrameCheckPoConst( Abc_Frame_t * p, int iPoNum ); extern ABC_DLL void Abc_FrameReplaceCex( Abc_Frame_t * pAbc, Abc_Cex_t ** ppCex ); extern ABC_DLL void Abc_FrameReplaceCexVec( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvCexVec ); extern ABC_DLL void Abc_FrameReplacePoEquivs( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvPoEquivs ); extern ABC_DLL void Abc_FrameReplacePoStatuses( Abc_Frame_t * pAbc, Vec_Int_t ** pvStatuses ); extern ABC_DLL char * Abc_FrameReadDrivingCell(); extern ABC_DLL float Abc_FrameReadMaxLoad(); extern ABC_DLL void Abc_FrameSetDrivingCell( char * pName ); extern ABC_DLL void Abc_FrameSetMaxLoad( float Load ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/mainFrame.c000066400000000000000000000552261300674244400237470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mainFrame.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [The global framework resides in this file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mainFrame.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "mainInt.h" #include "bool/dec/dec.h" #include "map/if/if.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Frame_t * s_GlobalFrame = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [APIs to access parameters in the flobal frame.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_FrameReadStore() { return s_GlobalFrame->vStore; } int Abc_FrameReadStoreSize() { return Vec_PtrSize(s_GlobalFrame->vStore); } void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; } void * Abc_FrameReadLibBox() { return s_GlobalFrame->pLibBox; } void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; } void * Abc_FrameReadLibGen2() { return s_GlobalFrame->pLibGen2; } void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; } void * Abc_FrameReadLibScl() { return s_GlobalFrame->pLibScl; } #ifdef ABC_USE_CUDD void * Abc_FrameReadManDd() { if ( s_GlobalFrame->dd == NULL ) s_GlobalFrame->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); return s_GlobalFrame->dd; } #endif void * Abc_FrameReadManDec() { if ( s_GlobalFrame->pManDec == NULL ) s_GlobalFrame->pManDec = Dec_ManStart(); return s_GlobalFrame->pManDec; } void * Abc_FrameReadManDsd() { return s_GlobalFrame->pManDsd; } void * Abc_FrameReadManDsd2() { return s_GlobalFrame->pManDsd2; } char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); } int Abc_FrameReadBmcFrames( Abc_Frame_t * p ) { return s_GlobalFrame->nFrames; } int Abc_FrameReadProbStatus( Abc_Frame_t * p ) { return s_GlobalFrame->Status; } Abc_Cex_t * Abc_FrameReadCex( Abc_Frame_t * p ) { return s_GlobalFrame->pCex; } Vec_Ptr_t * Abc_FrameReadCexVec( Abc_Frame_t * p ) { return s_GlobalFrame->vCexVec; } Vec_Int_t * Abc_FrameReadStatusVec( Abc_Frame_t * p ) { return s_GlobalFrame->vStatuses; } Vec_Ptr_t * Abc_FrameReadPoEquivs( Abc_Frame_t * p ) { return s_GlobalFrame->vPoEquivs; } Vec_Int_t * Abc_FrameReadPoStatuses( Abc_Frame_t * p ) { return s_GlobalFrame->vStatuses; } Vec_Int_t * Abc_FrameReadObjIds( Abc_Frame_t * p ) { return s_GlobalFrame->vAbcObjIds; } int Abc_FrameReadCexPiNum( Abc_Frame_t * p ) { return s_GlobalFrame->pCex->nPis; } int Abc_FrameReadCexRegNum( Abc_Frame_t * p ) { return s_GlobalFrame->pCex->nRegs; } int Abc_FrameReadCexPo( Abc_Frame_t * p ) { return s_GlobalFrame->pCex->iPo; } int Abc_FrameReadCexFrame( Abc_Frame_t * p ) { return s_GlobalFrame->pCex->iFrame; } void Abc_FrameSetLibLut( void * pLib ) { s_GlobalFrame->pLibLut = pLib; } void Abc_FrameSetLibBox( void * pLib ) { s_GlobalFrame->pLibBox = pLib; } void Abc_FrameSetLibGen( void * pLib ) { s_GlobalFrame->pLibGen = pLib; } void Abc_FrameSetLibGen2( void * pLib ) { s_GlobalFrame->pLibGen2 = pLib; } void Abc_FrameSetLibSuper( void * pLib ) { s_GlobalFrame->pLibSuper = pLib; } void Abc_FrameSetFlag( char * pFlag, char * pValue ) { Cmd_FlagUpdateValue( s_GlobalFrame, pFlag, pValue ); } void Abc_FrameSetCex( Abc_Cex_t * pCex ) { ABC_FREE( s_GlobalFrame->pCex ); s_GlobalFrame->pCex = pCex; } void Abc_FrameSetNFrames( int nFrames ) { ABC_FREE( s_GlobalFrame->pCex ); s_GlobalFrame->nFrames = nFrames; } void Abc_FrameSetStatus( int Status ) { ABC_FREE( s_GlobalFrame->pCex ); s_GlobalFrame->Status = Status; } void Abc_FrameSetManDsd( void * pMan ) { if (s_GlobalFrame->pManDsd && s_GlobalFrame->pManDsd != pMan) If_DsdManFree((If_DsdMan_t *)s_GlobalFrame->pManDsd, 0); s_GlobalFrame->pManDsd = pMan; } void Abc_FrameSetManDsd2( void * pMan ) { if (s_GlobalFrame->pManDsd2 && s_GlobalFrame->pManDsd2 != pMan) If_DsdManFree((If_DsdMan_t *)s_GlobalFrame->pManDsd2, 0); s_GlobalFrame->pManDsd2 = pMan; } void Abc_FrameSetInv( Vec_Int_t * vInv ) { Vec_IntFreeP(&s_GlobalFrame->pAbcWlcInv); s_GlobalFrame->pAbcWlcInv = vInv; } void Abc_FrameSetCnf( Vec_Int_t * vCnf ) { Vec_IntFreeP(&s_GlobalFrame->pAbcWlcCnf); s_GlobalFrame->pAbcWlcCnf = vCnf; } void Abc_FrameSetStr( Vec_Str_t * vStr ) { Vec_StrFreeP(&s_GlobalFrame->pAbcWlcStr); s_GlobalFrame->pAbcWlcStr = vStr; } int Abc_FrameIsBatchMode() { return s_GlobalFrame ? s_GlobalFrame->fBatchMode : 0; } int Abc_FrameIsBridgeMode() { return s_GlobalFrame ? s_GlobalFrame->fBridgeMode : 0; } void Abc_FrameSetBridgeMode() { if ( s_GlobalFrame ) s_GlobalFrame->fBridgeMode = 1; } char * Abc_FrameReadDrivingCell() { return s_GlobalFrame->pDrivingCell; } float Abc_FrameReadMaxLoad() { return s_GlobalFrame->MaxLoad; } void Abc_FrameSetDrivingCell( char * pName ) { ABC_FREE(s_GlobalFrame->pDrivingCell); s_GlobalFrame->pDrivingCell = pName; } void Abc_FrameSetMaxLoad( float Load ) { s_GlobalFrame->MaxLoad = Load; } /**Function************************************************************* Synopsis [Returns 1 if the flag is enabled without value or with value 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FrameIsFlagEnabled( char * pFlag ) { char * pValue; // if flag is not defined, it is not enabled pValue = Abc_FrameReadFlag( pFlag ); if ( pValue == NULL ) return 0; // if flag is defined but value is not empty (no parameter) or "1", it is not enabled if ( strcmp(pValue, "") && strcmp(pValue, "1") ) return 0; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Frame_t * Abc_FrameAllocate() { Abc_Frame_t * p; extern void define_cube_size( int n ); extern void set_espresso_flags(); // allocate and clean p = ABC_CALLOC( Abc_Frame_t, 1 ); // get version p->sVersion = Abc_UtilsGetVersion( p ); // set streams p->Err = stderr; p->Out = stdout; p->Hst = NULL; p->Status = -1; p->nFrames = -1; // set the starting step p->nSteps = 1; p->fBatchMode = 0; // networks to be used by choice p->vStore = Vec_PtrAlloc( 16 ); p->vAbcObjIds = Vec_IntAlloc( 0 ); // initialize decomposition manager // define_cube_size(20); // set_espresso_flags(); // initialize the trace manager // Abc_HManStart(); p->vPlugInComBinPairs = Vec_PtrAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameDeallocate( Abc_Frame_t * p ) { extern void Rwt_ManGlobalStop(); extern void undefine_cube_size(); // extern void Ivy_TruthManStop(); // Abc_HManStop(); // undefine_cube_size(); Rwt_ManGlobalStop(); // Ivy_TruthManStop(); if ( p->vAbcObjIds) Vec_IntFree( p->vAbcObjIds ); if ( p->vCexVec ) Vec_PtrFreeFree( p->vCexVec ); if ( p->vPoEquivs ) Vec_VecFree( (Vec_Vec_t *)p->vPoEquivs ); if ( p->vStatuses ) Vec_IntFree( p->vStatuses ); if ( p->pManDec ) Dec_ManStop( (Dec_Man_t *)p->pManDec ); #ifdef ABC_USE_CUDD if ( p->dd ) Extra_StopManager( p->dd ); #endif if ( p->vStore ) Vec_PtrFree( p->vStore ); if ( p->pSave1 ) Aig_ManStop( (Aig_Man_t *)p->pSave1 ); if ( p->pSave2 ) Aig_ManStop( (Aig_Man_t *)p->pSave2 ); if ( p->pSave3 ) Aig_ManStop( (Aig_Man_t *)p->pSave3 ); if ( p->pSave4 ) Aig_ManStop( (Aig_Man_t *)p->pSave4 ); if ( p->pManDsd ) If_DsdManFree( (If_DsdMan_t *)p->pManDsd, 0 ); if ( p->pManDsd2 ) If_DsdManFree( (If_DsdMan_t *)p->pManDsd2, 0 ); if ( p->pNtkBackup) Abc_NtkDelete( p->pNtkBackup ); if ( p->vPlugInComBinPairs ) { char * pTemp; int i; Vec_PtrForEachEntry( char *, p->vPlugInComBinPairs, pTemp, i ) ABC_FREE( pTemp ); Vec_PtrFree( p->vPlugInComBinPairs ); } Vec_IntFreeP( &p->vIndFlops ); Vec_PtrFreeP( &p->vLTLProperties_global ); Abc_FrameDeleteAllNetworks( p ); ABC_FREE( p->pDrivingCell ); ABC_FREE( p->pCex2 ); ABC_FREE( p->pCex ); Vec_IntFreeP( &p->pAbcWlcInv ); Vec_IntFreeP( &p->pAbcWlcCnf ); Vec_StrFreeP( &p->pAbcWlcStr ); ABC_FREE( p ); s_GlobalFrame = NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameRestart( Abc_Frame_t * p ) { } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameClearVerifStatus( Abc_Frame_t * p ) { p->nFrames = -1; p->Status = -1; ABC_FREE( p->pCex ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FrameShowProgress( Abc_Frame_t * p ) { return Abc_FrameIsFlagEnabled( "progressbar" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ) { return p->pNtkCur; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_FrameReadGia( Abc_Frame_t * p ) { return p->pGia; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ FILE * Abc_FrameReadOut( Abc_Frame_t * p ) { return p->Out; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ FILE * Abc_FrameReadErr( Abc_Frame_t * p ) { return p->Err; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FrameReadMode( Abc_Frame_t * p ) { int fShortNames; char * pValue; pValue = Cmd_FlagReadByName( p, "namemode" ); if ( pValue == NULL ) fShortNames = 0; else fShortNames = atoi(pValue); return fShortNames; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FrameSetMode( Abc_Frame_t * p, int fNameMode ) { char Buffer[2]; int fNameModeOld; fNameModeOld = Abc_FrameReadMode( p ); Buffer[0] = '0' + fNameMode; Buffer[1] = 0; Cmd_FlagUpdateValue( p, "namemode", (char *)Buffer ); return fNameModeOld; } /**Function************************************************************* Synopsis [Sets the given network to be the current one.] Description [Takes the network and makes it the current network. The previous current network is attached to the given network as a backup copy. In the stack of backup networks contains too many networks (defined by the paramater "savesteps"), the bottom most network is deleted.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtkNew ) { Abc_Ntk_t * pNtk, * pNtk2, * pNtk3; int nNetsPresent; int nNetsToSave; char * pValue; if ( p->pNtkCur == pNtkNew ) return; // link it to the previous network Abc_NtkSetBackup( pNtkNew, p->pNtkCur ); // set the step of this network Abc_NtkSetStep( pNtkNew, ++p->nSteps ); // set this network to be the current network p->pNtkCur = pNtkNew; // remove any extra network that may happen to be in the stack pValue = Cmd_FlagReadByName( p, "savesteps" ); // if the value of steps to save is not set, assume 1-level undo if ( pValue == NULL ) nNetsToSave = 1; else nNetsToSave = atoi(pValue); // count the network, remember the last one, and the one before the last one nNetsPresent = 0; pNtk2 = pNtk3 = NULL; for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk2) ) { nNetsPresent++; pNtk3 = pNtk2; pNtk2 = pNtk; } // remove the earliest backup network if it is more steps away than we store if ( nNetsPresent - 1 > nNetsToSave ) { // delete the last network Abc_NtkDelete( pNtk2 ); // clean the pointer of the network before the last one Abc_NtkSetBackup( pNtk3, NULL ); } } /**Function************************************************************* Synopsis [This procedure swaps the current and the backup network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ) { Abc_Ntk_t * pNtkCur, * pNtkBack, * pNtkBack2; int iStepCur, iStepBack; pNtkCur = p->pNtkCur; pNtkBack = Abc_NtkBackup( pNtkCur ); iStepCur = Abc_NtkStep ( pNtkCur ); // if there is no backup nothing to reset if ( pNtkBack == NULL ) return; // remember the backup of the backup pNtkBack2 = Abc_NtkBackup( pNtkBack ); iStepBack = Abc_NtkStep ( pNtkBack ); // set pNtkCur to be the next after the backup's backup Abc_NtkSetBackup( pNtkCur, pNtkBack2 ); Abc_NtkSetStep ( pNtkCur, iStepBack ); // set pNtkCur to be the next after the backup Abc_NtkSetBackup( pNtkBack, pNtkCur ); Abc_NtkSetStep ( pNtkBack, iStepCur ); // set the current network p->pNtkCur = pNtkBack; } /**Function************************************************************* Synopsis [Replaces the current network by the given one.] Description [This procedure does not modify the stack of saved networks.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtk ) { if ( pNtk == NULL ) return; if ( Abc_NtkPoNum(pNtk) == 0 ) Abc_Print( 0, "The current network has no primary outputs. Some commands may not work correctly.\n" ); // transfer the parameters to the new network if ( p->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) ) { Abc_NtkSetBackup( pNtk, Abc_NtkBackup(p->pNtkCur) ); Abc_NtkSetStep( pNtk, Abc_NtkStep(p->pNtkCur) ); // delete the current network Abc_NtkDelete( p->pNtkCur ); } else { Abc_NtkSetBackup( pNtk, NULL ); Abc_NtkSetStep( pNtk, ++p->nSteps ); // delete the current network if present but backup is disabled if ( p->pNtkCur ) Abc_NtkDelete( p->pNtkCur ); } // set the new current network p->pNtkCur = pNtk; } /**Function************************************************************* Synopsis [Removes library binding of all currently stored networks.] Description [This procedure is called when the library is freed.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p ) { Abc_Ntk_t * pNtk; for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) ) if ( Abc_NtkHasMapping(pNtk) ) Abc_NtkMapToSop( pNtk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ) { Abc_Ntk_t * pNtk, * pNtk2; // delete all the currently saved networks for ( pNtk = p->pNtkCur, pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL; pNtk; pNtk = pNtk2, pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL ) Abc_NtkDelete( pNtk ); // set the current network empty p->pNtkCur = NULL; // fprintf( p->Out, "All networks have been deleted.\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameSetGlobalFrame( Abc_Frame_t * p ) { s_GlobalFrame = p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Frame_t * Abc_FrameGetGlobalFrame() { if ( s_GlobalFrame == 0 ) { // start the framework s_GlobalFrame = Abc_FrameAllocate(); // perform initializations Abc_FrameInit( s_GlobalFrame ); } return s_GlobalFrame; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Frame_t * Abc_FrameReadGlobalFrame() { return s_GlobalFrame; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameSetSave1( void * pAig ) { Abc_Frame_t * pFrame = Abc_FrameGetGlobalFrame(); if ( pFrame->pSave1 ) Aig_ManStop( (Aig_Man_t *)pFrame->pSave1 ); pFrame->pSave1 = pAig; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameSetSave2( void * pAig ) { Abc_Frame_t * pFrame = Abc_FrameGetGlobalFrame(); if ( pFrame->pSave2 ) Aig_ManStop( (Aig_Man_t *)pFrame->pSave2 ); pFrame->pSave2 = pAig; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_FrameReadSave1() { void * pAig = Abc_FrameGetGlobalFrame()->pSave1; Abc_FrameGetGlobalFrame()->pSave1 = NULL; return pAig; } void * Abc_FrameReadSave2() { void * pAig = Abc_FrameGetGlobalFrame()->pSave2; Abc_FrameGetGlobalFrame()->pSave2 = NULL; return pAig; } /**Function************************************************************* Synopsis [Returns 0/1 if pNtkCur is an AIG and PO is 0/1; -1 otherwise.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FrameCheckPoConst( Abc_Frame_t * p, int iPoNum ) { Abc_Obj_t * pObj; if ( p->pNtkCur == NULL ) return -1; if ( !Abc_NtkIsStrash(p->pNtkCur) ) return -1; if ( iPoNum < 0 || iPoNum >= Abc_NtkPoNum(p->pNtkCur) ) return -1; pObj = Abc_NtkPo( p->pNtkCur, iPoNum ); if ( !Abc_AigNodeIsConst(Abc_ObjFanin0(pObj)) ) return -1; return !Abc_ObjFaninC0(pObj); } void Abc_FrameCheckPoConstTest( Abc_Frame_t * p ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachPo( p->pNtkCur, pObj, i ) printf( "%d = %d\n", i, Abc_FrameCheckPoConst(p, i) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/mainInit.c000066400000000000000000000111431300674244400236060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mainInit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [Initialization procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mainInit.c,v 1.3 2005/09/14 22:53:37 casem Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern void Abc_Init( Abc_Frame_t * pAbc ); extern void Abc_End ( Abc_Frame_t * pAbc ); extern void Io_Init( Abc_Frame_t * pAbc ); extern void Io_End ( Abc_Frame_t * pAbc ); extern void Cmd_Init( Abc_Frame_t * pAbc ); extern void Cmd_End ( Abc_Frame_t * pAbc ); extern void If_Init( Abc_Frame_t * pAbc ); extern void If_End ( Abc_Frame_t * pAbc ); extern void Map_Init( Abc_Frame_t * pAbc ); extern void Map_End ( Abc_Frame_t * pAbc ); extern void Mio_Init( Abc_Frame_t * pAbc ); extern void Mio_End ( Abc_Frame_t * pAbc ); extern void Super_Init( Abc_Frame_t * pAbc ); extern void Super_End ( Abc_Frame_t * pAbc ); extern void Libs_Init( Abc_Frame_t * pAbc ); extern void Libs_End( Abc_Frame_t * pAbc ); extern void Load_Init( Abc_Frame_t * pAbc ); extern void Load_End( Abc_Frame_t * pAbc ); extern void Scl_Init( Abc_Frame_t * pAbc ); extern void Scl_End( Abc_Frame_t * pAbc ); extern void Wlc_Init( Abc_Frame_t * pAbc ); extern void Wlc_End( Abc_Frame_t * pAbc ); extern void Bac_Init( Abc_Frame_t * pAbc ); extern void Bac_End( Abc_Frame_t * pAbc ); extern void Cba_Init( Abc_Frame_t * pAbc ); extern void Cba_End( Abc_Frame_t * pAbc ); extern void Pla_Init( Abc_Frame_t * pAbc ); extern void Pla_End( Abc_Frame_t * pAbc ); extern void Test_Init( Abc_Frame_t * pAbc ); extern void Test_End( Abc_Frame_t * pAbc ); extern void Abc2_Init( Abc_Frame_t * pAbc ); extern void Abc2_End ( Abc_Frame_t * pAbc ); extern void Abc85_Init( Abc_Frame_t * pAbc ); extern void Abc85_End( Abc_Frame_t * pAbc ); static Abc_FrameInitializer_t* s_InitializerStart = NULL; static Abc_FrameInitializer_t* s_InitializerEnd = NULL; void Abc_FrameAddInitializer( Abc_FrameInitializer_t* p ) { if( ! s_InitializerStart ) s_InitializerStart = p; p->next = NULL; p->prev = s_InitializerEnd; if ( s_InitializerEnd ) s_InitializerEnd->next = p; s_InitializerEnd = p; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts all the packages.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameInit( Abc_Frame_t * pAbc ) { Abc_FrameInitializer_t* p; Cmd_Init( pAbc ); Cmd_CommandExecute( pAbc, "set checkread" ); Io_Init( pAbc ); Abc_Init( pAbc ); If_Init( pAbc ); Map_Init( pAbc ); Mio_Init( pAbc ); Super_Init( pAbc ); Libs_Init( pAbc ); Load_Init( pAbc ); Scl_Init( pAbc ); Wlc_Init( pAbc ); Bac_Init( pAbc ); Cba_Init( pAbc ); Pla_Init( pAbc ); Test_Init( pAbc ); for( p = s_InitializerStart ; p ; p = p->next ) if(p->init) p->init(pAbc); } /**Function************************************************************* Synopsis [Stops all the packages.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameEnd( Abc_Frame_t * pAbc ) { Abc_FrameInitializer_t* p; for( p = s_InitializerEnd ; p ; p = p->prev ) if ( p->destroy ) p->destroy(pAbc); Abc_End( pAbc ); Io_End( pAbc ); Cmd_End( pAbc ); If_End( pAbc ); Map_End( pAbc ); Mio_End( pAbc ); Super_End( pAbc ); Libs_End( pAbc ); Load_End( pAbc ); Scl_End( pAbc ); Wlc_End( pAbc ); Bac_End( pAbc ); Cba_End( pAbc ); Pla_End( pAbc ); Test_End( pAbc ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/mainInt.h000066400000000000000000000175271300674244400234560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mainInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [Internal declarations of the main package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mainInt.h,v 1.1 2008/05/14 22:13:13 wudenni Exp $] ***********************************************************************/ #ifndef ABC__base__main__mainInt_h #define ABC__base__main__mainInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "main.h" #include "misc/tim/tim.h" #include "map/if/if.h" #include "aig/aig/aig.h" #include "aig/gia/gia.h" #include "proof/ssw/ssw.h" #include "proof/fra/fra.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // the current version #define ABC_VERSION "UC Berkeley, ABC 1.01" // the maximum length of an input line #define ABC_MAX_STR (1<<15) //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// struct Abc_Frame_t_ { // general info char * sVersion; // the name of the current version char * sBinary; // the name of the binary running // commands, aliases, etc st__table * tCommands; // the command table st__table * tAliases; // the alias table st__table * tFlags; // the flag table Vec_Ptr_t * aHistory; // the command history // the functionality Abc_Ntk_t * pNtkCur; // the current network Abc_Ntk_t * pNtkBestDelay; // the current network Abc_Ntk_t * pNtkBestArea; // the current network Abc_Ntk_t * pNtkBackup; // the current network int nSteps; // the counter of different network processed int fSource; // marks the source mode int fAutoexac; // marks the autoexec mode int fBatchMode; // batch mode flag int fBridgeMode; // bridge mode flag // output streams FILE * Out; FILE * Err; FILE * Hst; // used for runtime measurement double TimeCommand; // the runtime of the last command double TimeTotal; // the total runtime of all commands // temporary storage for structural choices Vec_Ptr_t * vStore; // networks to be used by choice // decomposition package void * pManDec; // decomposition manager void * pManDsd; // decomposition manager void * pManDsd2; // decomposition manager // libraries for mapping void * pLibLut; // the current LUT library void * pLibBox; // the current box library void * pLibGen; // the current genlib void * pLibGen2; // the current genlib void * pLibSuper; // the current supergate library void * pLibScl; // the current Liberty library void * pAbcCon; // constraint manager // timing constraints char * pDrivingCell; // name of the driving cell float MaxLoad; // maximum output load // inductive don't-cares Vec_Int_t * vIndFlops; int nIndFrames; // new code Gia_Man_t * pGia; // alternative current network as a light-weight AIG Gia_Man_t * pGia2; // copy of the above Gia_Man_t * pGiaBest; // copy of the above int nBestLuts; // best LUT count int nBestEdges; // best edge count int nBestLevels; // best level count Abc_Cex_t * pCex; // a counter-example to fail the current network Abc_Cex_t * pCex2; // copy of the above Vec_Ptr_t * vCexVec; // a vector of counter-examples if more than one PO fails Vec_Ptr_t * vPoEquivs; // equivalence classes of isomorphic primary outputs Vec_Int_t * vStatuses; // problem status for each output Vec_Int_t * vAbcObjIds; // object IDs int Status; // the status of verification problem (proved=1, disproved=0, undecided=-1) int nFrames; // the number of time frames completed by BMC Vec_Ptr_t * vPlugInComBinPairs; // pairs of command and its binary name Vec_Ptr_t * vLTLProperties_global; // related to LTL void * pSave1; void * pSave2; void * pSave3; void * pSave4; void * pAbc85Ntl; void * pAbc85Ntl2; void * pAbc85Best; void * pAbc85Delay; void * pAbcWlc; Vec_Int_t * pAbcWlcInv; Vec_Int_t * pAbcWlcCnf; Vec_Str_t * pAbcWlcStr; void * pAbcBac; void * pAbcCba; void * pAbcPla; #ifdef ABC_USE_CUDD DdManager * dd; // temporary BDD package #endif }; typedef void (*Abc_Frame_Initialization_Func)( Abc_Frame_t * pAbc ); struct Abc_FrameInitializer_t_; typedef struct Abc_FrameInitializer_t_ Abc_FrameInitializer_t; struct Abc_FrameInitializer_t_ { Abc_Frame_Initialization_Func init; Abc_Frame_Initialization_Func destroy; Abc_FrameInitializer_t* next; Abc_FrameInitializer_t* prev; }; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mvMain.c ===========================================================*/ extern ABC_DLL int main( int argc, char * argv[] ); /*=== mvInit.c ===================================================*/ extern ABC_DLL void Abc_FrameInit( Abc_Frame_t * pAbc ); extern ABC_DLL void Abc_FrameEnd( Abc_Frame_t * pAbc ); extern ABC_DLL void Abc_FrameAddInitializer( Abc_FrameInitializer_t* p ); /*=== mvFrame.c =====================================================*/ extern ABC_DLL Abc_Frame_t * Abc_FrameAllocate(); extern ABC_DLL void Abc_FrameDeallocate( Abc_Frame_t * p ); /*=== mvUtils.c =====================================================*/ extern ABC_DLL char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ); extern ABC_DLL char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ); extern ABC_DLL void Abc_UtilsPrintHello( Abc_Frame_t * pAbc ); extern ABC_DLL void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName ); extern ABC_DLL void Abc_UtilsSource( Abc_Frame_t * pAbc ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/mainLib.c000066400000000000000000000054051300674244400234150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [main.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [Here everything starts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Initialization procedure for the library project.] Description [Note that when Abc_Start() is run in a static library project, it does not load the resource file by default. As a result, ABC is not set up the same way, as when it is run on a command line. For example, some error messages while parsing files will not be produced, and intermediate networks will not be checked for consistancy. One possibility is to load the resource file after Abc_Start() as follows: Abc_UtilsSource( Abc_FrameGetGlobalFrame() );] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_Start() { Abc_Frame_t * pAbc; // added to detect memory leaks: #if defined(_DEBUG) && defined(_MSC_VER) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif // start the glocal frame pAbc = Abc_FrameGetGlobalFrame(); // source the resource file // Abc_UtilsSource( pAbc ); } /**Function************************************************************* Synopsis [Deallocation procedure for the library project.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_Stop() { Abc_Frame_t * pAbc; pAbc = Abc_FrameGetGlobalFrame(); // perform uninitializations Abc_FrameEnd( pAbc ); // stop the framework Abc_FrameDeallocate( pAbc ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/mainMC.c000066400000000000000000000126251300674244400232100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mainMC.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [The main file for the model checker.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mainInt.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include "aig/fra/fra.h" #include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [The main() procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int main( int argc, char * argv[] ) { int fEnableBmcOnly = 0; // enable to make it BMC-only int fEnableCounter = 1; // should be 1 in the final version int fEnableComment = 0; // should be 0 in the final version Fra_Sec_t SecPar, * pSecPar = &SecPar; FILE * pFile; Aig_Man_t * pAig; int RetValue = -1; int Depth = -1; // BMC parameters int nFrames = 50; int nSizeMax = 500000; int nBTLimit = 10000; int fRewrite = 0; int fNewAlgo = 1; int fVerbose = 0; clock_t clkTotal = clock(); if ( argc != 2 ) { printf( " Expecting one command-line argument (an input file in AIGER format).\n" ); printf( " usage: %s \n", argv[0] ); return 0; } pFile = fopen( argv[1], "r" ); if ( pFile == NULL ) { printf( " Cannot open input AIGER file \"%s\".\n", argv[1] ); printf( " usage: %s \n", argv[0] ); return 0; } fclose( pFile ); pAig = Ioa_ReadAiger( argv[1], 1 ); if ( pAig == NULL ) { printf( " Parsing the AIGER file \"%s\" has failed.\n", argv[1] ); printf( " usage: %s \n", argv[0] ); return 0; } Aig_ManSetRegNum( pAig, pAig->nRegs ); if ( !fEnableBmcOnly ) { // perform BMC if ( pAig->nRegs != 0 ) RetValue = Saig_ManBmcSimple( pAig, nFrames, nSizeMax, nBTLimit, fRewrite, fVerbose, NULL, 0 ); // perform full-blown SEC if ( RetValue != 0 ) { extern void Dar_LibStart(); extern void Dar_LibStop(); extern void Cnf_ManFree(); Fra_SecSetDefaultParams( pSecPar ); pSecPar->TimeLimit = 600; pSecPar->nFramesMax = 4; // the max number of frames used for induction pSecPar->fPhaseAbstract = 0; // disable phase-abstraction pSecPar->fSilent = 1; // disable phase-abstraction Dar_LibStart(); RetValue = Fra_FraigSec( pAig, pSecPar, NULL ); Dar_LibStop(); Cnf_ManFree(); } } // perform BMC again if ( RetValue == -1 && pAig->nRegs != 0 ) { int nFrames = 200; int nSizeMax = 500000; int nBTLimit = 10000000; int fRewrite = 0; RetValue = Saig_ManBmcSimple( pAig, nFrames, nSizeMax, nBTLimit, fRewrite, fVerbose, &Depth, 0 ); if ( RetValue != 0 ) RetValue = -1; } // decide how to report the output pFile = stdout; // report the result if ( RetValue == 0 ) { // fprintf(stdout, "s SATIFIABLE\n"); fprintf( pFile, "1" ); if ( fEnableCounter ) { printf( "\n" ); if ( pAig->pSeqModel ) Fra_SmlWriteCounterExample( pFile, pAig, pAig->pSeqModel ); } if ( fEnableComment ) { printf( " # File %10s. ", argv[1] ); PRT( "Time", clock() - clkTotal ); } if ( pFile != stdout ) fclose(pFile); Aig_ManStop( pAig ); exit(10); } else if ( RetValue == 1 ) { // fprintf(stdout, "s UNSATISFIABLE\n"); fprintf( pFile, "0" ); if ( fEnableComment ) { printf( " # File %10s. ", argv[1] ); PRT( "Time", clock() - clkTotal ); } printf( "\n" ); if ( pFile != stdout ) fclose(pFile); Aig_ManStop( pAig ); exit(20); } else // if ( RetValue == -1 ) { // fprintf(stdout, "s UNKNOWN\n"); fprintf( pFile, "2" ); if ( fEnableComment ) { printf( " # File %10s. ", argv[1] ); PRT( "Time", clock() - clkTotal ); } printf( "\n" ); if ( pFile != stdout ) fclose(pFile); Aig_ManStop( pAig ); exit(0); } return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/mainReal.c000066400000000000000000000267441300674244400236030ustar00rootroot00000000000000/*//////////////////////////////////////////////////////////////////////////// ABC: 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. ////////////////////////////////////////////////////////////////////////////*/ /**CFile**************************************************************** FileName [main.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [Here everything starts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "mainInt.h" #include "base/wlc/wlc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int TypeCheck( Abc_Frame_t * pAbc, const char * s); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [The main() procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_RealMain( int argc, char * argv[] ) { Abc_Frame_t * pAbc; Vec_Str_t* sCommandUsr = Vec_StrAlloc(1000); char sCommandTmp[ABC_MAX_STR], sReadCmd[1000], sWriteCmd[1000]; const char * sOutFile, * sInFile; char * sCommand; int fStatus = 0; int c, fInitSource, fInitRead, fFinalWrite; enum { INTERACTIVE, // interactive mode BATCH, // batch mode, run a command and quit BATCH_THEN_INTERACTIVE, // run a command, then back to interactive mode BATCH_QUIET, // as in batch mode, but don't echo the command BATCH_QUIET_THEN_INTERACTIVE, // as in batch then interactive mode, but don't echo the command BATCH_SMT // special batch mode, which expends SMTLIB problem via stdin } fBatch; // added to detect memory leaks // watch for {,,msvcrtd.dll}*__p__crtBreakAlloc() // (http://support.microsoft.com/kb/151585) #if defined(_DEBUG) && defined(_MSC_VER) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif // get global frame (singleton pattern) // will be initialized on first call pAbc = Abc_FrameGetGlobalFrame(); pAbc->sBinary = argv[0]; // default options fBatch = INTERACTIVE; fInitSource = 1; fInitRead = 0; fFinalWrite = 0; sInFile = sOutFile = NULL; sprintf( sReadCmd, "read" ); sprintf( sWriteCmd, "write" ); Extra_UtilGetoptReset(); while ((c = Extra_UtilGetopt(argc, argv, "c:q:C:Q:S:hf:F:o:st:T:xb")) != EOF) { switch(c) { case 'c': if( Vec_StrSize(sCommandUsr) > 0 ) { Vec_StrAppend(sCommandUsr, " ; "); } Vec_StrAppend(sCommandUsr, globalUtilOptarg ); fBatch = BATCH; break; case 'q': if( Vec_StrSize(sCommandUsr) > 0 ) { Vec_StrAppend(sCommandUsr, " ; "); } Vec_StrAppend(sCommandUsr, globalUtilOptarg ); fBatch = BATCH_QUIET; break; case 'Q': if( Vec_StrSize(sCommandUsr) > 0 ) { Vec_StrAppend(sCommandUsr, " ; "); } Vec_StrAppend(sCommandUsr, globalUtilOptarg ); fBatch = BATCH_QUIET_THEN_INTERACTIVE; break; case 'C': if( Vec_StrSize(sCommandUsr) > 0 ) { Vec_StrAppend(sCommandUsr, " ; "); } Vec_StrAppend(sCommandUsr, globalUtilOptarg ); fBatch = BATCH_THEN_INTERACTIVE; break; case 'S': if( Vec_StrSize(sCommandUsr) > 0 ) { Vec_StrAppend(sCommandUsr, " ; "); } Vec_StrAppend(sCommandUsr, globalUtilOptarg ); fBatch = BATCH_SMT; break; case 'f': if( Vec_StrSize(sCommandUsr) > 0 ) { Vec_StrAppend(sCommandUsr, " ; "); } Vec_StrPrintF(sCommandUsr, "source %s", globalUtilOptarg ); fBatch = BATCH; break; case 'F': if( Vec_StrSize(sCommandUsr) > 0 ) { Vec_StrAppend(sCommandUsr, " ; "); } Vec_StrPrintF(sCommandUsr, "source -x %s", globalUtilOptarg ); fBatch = BATCH; break; case 'h': goto usage; break; case 'o': sOutFile = globalUtilOptarg; fFinalWrite = 1; break; case 's': fInitSource = 0; break; case 't': if ( TypeCheck( pAbc, globalUtilOptarg ) ) { if ( !strcmp(globalUtilOptarg, "none") == 0 ) { fInitRead = 1; sprintf( sReadCmd, "read_%s", globalUtilOptarg ); } } else { goto usage; } fBatch = BATCH; break; case 'T': if ( TypeCheck( pAbc, globalUtilOptarg ) ) { if (!strcmp(globalUtilOptarg, "none") == 0) { fFinalWrite = 1; sprintf( sWriteCmd, "write_%s", globalUtilOptarg); } } else { goto usage; } fBatch = BATCH; break; case 'x': fFinalWrite = 0; fInitRead = 0; fBatch = BATCH; break; case 'b': Abc_FrameSetBridgeMode(); break; default: goto usage; } } Vec_StrPush(sCommandUsr, '\0'); if ( fBatch == BATCH_SMT ) { Wlc_StdinProcessSmt( pAbc, Vec_StrArray(sCommandUsr) ); Abc_Stop(); return 0; } if ( Abc_FrameIsBridgeMode() ) { extern Gia_Man_t * Gia_ManFromBridge( FILE * pFile, Vec_Int_t ** pvInit ); pAbc->pGia = Gia_ManFromBridge( stdin, NULL ); } else if ( fBatch!=INTERACTIVE && fBatch!=BATCH_QUIET && fBatch!=BATCH_QUIET_THEN_INTERACTIVE && Vec_StrSize(sCommandUsr)>0 ) Abc_Print( 1, "ABC command line: \"%s\".\n\n", Vec_StrArray(sCommandUsr) ); if ( fBatch!=INTERACTIVE ) { pAbc->fBatchMode = 1; if (argc - globalUtilOptind == 0) { sInFile = NULL; } else if (argc - globalUtilOptind == 1) { fInitRead = 1; sInFile = argv[globalUtilOptind]; } else { Abc_UtilsPrintUsage( pAbc, argv[0] ); } // source the resource file if ( fInitSource ) { Abc_UtilsSource( pAbc ); } fStatus = 0; if ( fInitRead && sInFile ) { sprintf( sCommandTmp, "%s %s", sReadCmd, sInFile ); fStatus = Cmd_CommandExecute( pAbc, sCommandTmp ); } if ( fStatus == 0 ) { /* cmd line contains `source ' */ fStatus = Cmd_CommandExecute( pAbc, Vec_StrArray(sCommandUsr) ); if ( (fStatus == 0 || fStatus == -1) && fFinalWrite && sOutFile ) { sprintf( sCommandTmp, "%s %s", sWriteCmd, sOutFile ); fStatus = Cmd_CommandExecute( pAbc, sCommandTmp ); } } if (fBatch == BATCH_THEN_INTERACTIVE || fBatch == BATCH_QUIET_THEN_INTERACTIVE){ fBatch = INTERACTIVE; pAbc->fBatchMode = 0; } } Vec_StrFreeP(&sCommandUsr); if ( fBatch==INTERACTIVE ) { // start interactive mode // print the hello line Abc_UtilsPrintHello( pAbc ); // print history of the recent commands Cmd_HistoryPrint( pAbc, 10 ); // source the resource file if ( fInitSource ) { Abc_UtilsSource( pAbc ); } // execute commands given by the user while ( !feof(stdin) ) { // print command line prompt and // get the command from the user sCommand = Abc_UtilsGetUsersInput( pAbc ); // execute the user's command fStatus = Cmd_CommandExecute( pAbc, sCommand ); // stop if the user quitted or an error occurred if ( fStatus == -1 || fStatus == -2 ) break; } } // if the memory should be freed, quit packages // if ( fStatus < 0 ) { Abc_Stop(); } return 0; usage: Abc_UtilsPrintHello( pAbc ); Abc_UtilsPrintUsage( pAbc, argv[0] ); return 1; } /**Function******************************************************************** Synopsis [Returns 1 if s is a file type recognized, else returns 0.] Description [Returns 1 if s is a file type recognized by ABC, else returns 0. Recognized types are "blif", "bench", "pla", and "none".] SideEffects [] ******************************************************************************/ static int TypeCheck( Abc_Frame_t * pAbc, const char * s ) { if (strcmp(s, "blif") == 0) return 1; else if (strcmp(s, "bench") == 0) return 1; else if (strcmp(s, "pla") == 0) return 1; else if (strcmp(s, "none") == 0) return 1; else { fprintf( pAbc->Err, "unknown type %s\n", s ); return 0; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/mainUtils.c000066400000000000000000000217341300674244400240120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mainUtils.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The main package.] Synopsis [Miscellaneous utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mainUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "mainInt.h" #ifdef ABC_USE_READLINE #include #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static char * DateReadFromDateString( char * datestr ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ) { static char Version[1000]; sprintf(Version, "%s (compiled %s %s)", ABC_VERSION, __DATE__, __TIME__); return Version; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ) { static char Prompt[5000]; sprintf( Prompt, "abc %02d> ", pAbc->nSteps ); #ifdef ABC_USE_READLINE { static char * line = NULL; if (line != NULL) ABC_FREE(line); line = readline(Prompt); if (line == NULL){ printf("***EOF***\n"); exit(0); } add_history(line); return line; } #else { char * pRetValue; fprintf( pAbc->Out, "%s", Prompt ); pRetValue = fgets( Prompt, 5000, stdin ); return Prompt; } #endif } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_UtilsPrintHello( Abc_Frame_t * pAbc ) { fprintf( pAbc->Out, "%s\n", pAbc->sVersion ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName ) { fprintf( pAbc->Err, "\n" ); fprintf( pAbc->Err, "usage: %s [-c cmd] [-q cmd] [-C cmd] [-Q cmd] [-f script] [-h] [-o file] [-s] [-t type] [-T type] [-x] [-b] [file]\n", ProgName); fprintf( pAbc->Err, " -c cmd\texecute commands `cmd'\n"); fprintf( pAbc->Err, " -q cmd\texecute commands `cmd' quietly\n"); fprintf( pAbc->Err, " -C cmd\texecute commands `cmd', then continue in interactive mode\n"); fprintf( pAbc->Err, " -Q cmd\texecute commands `cmd' quietly, then continue in interactive mode\n"); fprintf( pAbc->Err, " -F script\texecute commands from a script file and echo commands\n"); fprintf( pAbc->Err, " -f script\texecute commands from a script file\n"); fprintf( pAbc->Err, " -h\t\tprint the command usage\n"); fprintf( pAbc->Err, " -o file\tspecify output filename to store the result\n"); fprintf( pAbc->Err, " -s\t\tdo not read any initialization file\n"); fprintf( pAbc->Err, " -t type\tspecify input type (blif_mv (default), blif_mvs, blif, or none)\n"); fprintf( pAbc->Err, " -T type\tspecify output type (blif_mv (default), blif_mvs, blif, or none)\n"); fprintf( pAbc->Err, " -x\t\tequivalent to '-t none -T none'\n"); fprintf( pAbc->Err, " -b\t\trunning in bridge mode\n"); fprintf( pAbc->Err, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_UtilsSource( Abc_Frame_t * pAbc ) { #ifdef WIN32 if ( Cmd_CommandExecute(pAbc, "source abc.rc") ) { if ( Cmd_CommandExecute(pAbc, "source ..\\abc.rc") == 0 ) printf( "Loaded \"abc.rc\" from the parent directory.\n" ); else if ( Cmd_CommandExecute(pAbc, "source ..\\..\\abc.rc") == 0 ) printf( "Loaded \"abc.rc\" from the grandparent directory.\n" ); } #else #if 0 { char * sPath1, * sPath2; // If .rc is present in both the home and current directories, then read // it from the home directory. Otherwise, read it from wherever it's located. sPath1 = Extra_UtilFileSearch(".rc", "~/", "r"); sPath2 = Extra_UtilFileSearch(".rc", ".", "r"); if ( sPath1 && sPath2 ) { /* ~/.rc == .rc : Source the file only once */ (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); } else { if (sPath1) { (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); } if (sPath2) { (void) Cmd_CommandExecute(pAbc, "source -s .rc"); } } if ( sPath1 ) ABC_FREE(sPath1); if ( sPath2 ) ABC_FREE(sPath2); /* execute the abc script which can be open with the "open_path" */ Cmd_CommandExecute( pAbc, "source -s abc.rc" ); } #endif { char * sPath1, * sPath2; char * home; // If .rc is present in both the home and current directories, then read // it from the home directory. Otherwise, read it from wherever it's located. home = getenv("HOME"); if (home){ char * sPath3 = ABC_ALLOC(char, strlen(home) + 2); (void) sprintf(sPath3, "%s/", home); sPath1 = Extra_UtilFileSearch(".abc.rc", sPath3, "r"); ABC_FREE(sPath3); }else sPath1 = NULL; sPath2 = Extra_UtilFileSearch(".abc.rc", ".", "r"); if ( sPath1 && sPath2 ) { /* ~/.rc == .rc : Source the file only once */ char *tmp_cmd = ABC_ALLOC(char, strlen(sPath1)+12); (void) sprintf(tmp_cmd, "source -s %s", sPath1); // (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); (void) Cmd_CommandExecute(pAbc, tmp_cmd); ABC_FREE(tmp_cmd); } else { if (sPath1) { char *tmp_cmd = ABC_ALLOC(char, strlen(sPath1)+12); (void) sprintf(tmp_cmd, "source -s %s", sPath1); // (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); (void) Cmd_CommandExecute(pAbc, tmp_cmd); ABC_FREE(tmp_cmd); } if (sPath2) { char *tmp_cmd = ABC_ALLOC(char, strlen(sPath2)+12); (void) sprintf(tmp_cmd, "source -s %s", sPath2); // (void) Cmd_CommandExecute(pAbc, "source -s .abc.rc"); (void) Cmd_CommandExecute(pAbc, tmp_cmd); ABC_FREE(tmp_cmd); } } if ( sPath1 ) ABC_FREE(sPath1); if ( sPath2 ) ABC_FREE(sPath2); /* execute the abc script which can be open with the "open_path" */ Cmd_CommandExecute( pAbc, "source -s abc.rc" ); } #endif //WIN32 } /**Function******************************************************************** Synopsis [Returns the date in a brief format assuming its coming from the program `date'.] Description [optional] SideEffects [] ******************************************************************************/ char * DateReadFromDateString( char * datestr ) { static char result[25]; char day[10]; char month[10]; char zone[10]; char *at; int date; int hour; int minute; int second; int year; if (sscanf(datestr, "%s %s %2d %2d:%2d:%2d %s %4d", day, month, &date, &hour, &minute, &second, zone, &year) == 8) { if (hour >= 12) { if (hour >= 13) hour -= 12; at = "PM"; } else { if (hour == 0) hour = 12; at = "AM"; } (void) sprintf(result, "%d-%3s-%02d at %d:%02d %s", date, month, year % 100, hour, minute, at); return result; } else { return datestr; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/main/module.make000066400000000000000000000003171300674244400240170ustar00rootroot00000000000000SRC += src/base/main/main.c \ src/base/main/mainFrame.c \ src/base/main/mainInit.c \ src/base/main/mainLib.c \ src/base/main/mainReal.c \ src/base/main/libSupport.c \ src/base/main/mainUtils.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/000077500000000000000000000000001300674244400215225ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/module.make000066400000000000000000000003011300674244400236400ustar00rootroot00000000000000SRC += src/base/pla/plaCom.c \ src/base/pla/plaHash.c \ src/base/pla/plaMan.c \ src/base/pla/plaMerge.c \ src/base/pla/plaSimple.c \ src/base/pla/plaRead.c \ src/base/pla/plaWrite.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/pla.c000066400000000000000000000026701300674244400224470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pla.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: pla.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/pla.h000066400000000000000000000273201300674244400224530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pla.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: pla.h,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__wlc__wlc_h #define ABC__base__wlc__wlc_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "misc/extra/extra.h" #include "base/main/mainInt.h" //#include "misc/util/utilTruth.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define MASK55 ABC_CONST(0x5555555555555555) //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // file types typedef enum { PLA_FILE_FD = 0, PLA_FILE_F, PLA_FILE_FR, PLA_FILE_FDR, PLA_FILE_NONE } Pla_File_t; // literal types typedef enum { PLA_LIT_DASH = 0, PLA_LIT_ZERO, PLA_LIT_ONE, PLA_LIT_FULL } Pla_Lit_t; typedef struct Pla_Man_t_ Pla_Man_t; struct Pla_Man_t_ { char * pName; // model name char * pSpec; // input file Pla_File_t Type; // file type int nIns; // inputs int nOuts; // outputs int nInWords; // words of input data int nOutWords; // words of output data Vec_Int_t vCubes; // cubes Vec_Int_t vHashes; // hash values Vec_Wrd_t vInBits; // input bits Vec_Wrd_t vOutBits; // output bits Vec_Wec_t vCubeLits; // cubes as interger arrays Vec_Wec_t vOccurs; // occurence counters for the literals Vec_Int_t vDivs; // divisor definitions }; static inline char * Pla_ManName( Pla_Man_t * p ) { return p->pName; } static inline int Pla_ManInNum( Pla_Man_t * p ) { return p->nIns; } static inline int Pla_ManOutNum( Pla_Man_t * p ) { return p->nOuts; } static inline int Pla_ManCubeNum( Pla_Man_t * p ) { return Vec_IntSize( &p->vCubes ); } static inline int Pla_ManDivNum( Pla_Man_t * p ) { return Vec_IntSize( &p->vDivs ); } static inline word * Pla_CubeIn( Pla_Man_t * p, int i ) { return Vec_WrdEntryP(&p->vInBits, i * p->nInWords); } static inline word * Pla_CubeOut( Pla_Man_t * p, int i ) { return Vec_WrdEntryP(&p->vOutBits, i * p->nOutWords); } static inline int Pla_CubeNum( int hCube ) { return hCube >> 8; } static inline int Pla_CubeLit( int hCube ) { return hCube & 0xFF; } static inline int Pla_CubeHandle( int iCube, int iLit ) { assert( !(iCube >> 24) && !(iLit >> 8) ); return iCube << 8 | iLit; } // read/write/flip i-th bit of a bit string table static inline int Pla_TtGetBit( word * p, int i ) { return (int)(p[i>>6] >> (i & 63)) & 1; } static inline void Pla_TtSetBit( word * p, int i ) { p[i>>6] |= (((word)1)<<(i & 63)); } static inline void Pla_TtXorBit( word * p, int i ) { p[i>>6] ^= (((word)1)<<(i & 63)); } // read/write/flip i-th literal in a cube static inline int Pla_CubeGetLit( word * p, int i ) { return (int)(p[i>>5] >> ((i<<1) & 63)) & 3; } static inline void Pla_CubeSetLit( word * p, int i, Pla_Lit_t d ) { p[i>>5] |= (((word)d)<<((i<<1) & 63)); } static inline void Pla_CubeXorLit( word * p, int i, Pla_Lit_t d ) { p[i>>5] ^= (((word)d)<<((i<<1) & 63)); } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// #define Pla_ForEachCubeIn( p, pCube, i ) \ for ( i = 0; (i < Pla_ManCubeNum(p)) && (((pCube) = Pla_CubeIn(p, i)), 1); i++ ) #define Pla_ForEachCubeInStart( p, pCube, i, Start ) \ for ( i = Start; (i < Pla_ManCubeNum(p)) && (((pCube) = Pla_CubeIn(p, i)), 1); i++ ) #define Pla_ForEachCubeOut( p, pCube, i ) \ for ( i = 0; (i < Pla_ManCubeNum(p)) && (((pCube) = Pla_CubeOut(p, i)), 1); i++ ) #define Pla_ForEachCubeInOut( p, pCubeIn, pCubeOut, i ) \ for ( i = 0; (i < Pla_ManCubeNum(p)) && (((pCubeIn) = Pla_CubeIn(p, i)), 1) && (((pCubeOut) = Pla_CubeOut(p, i)), 1); i++ ) #define Pla_CubeForEachLit( nVars, pCube, Lit, i ) \ for ( i = 0; (i < nVars) && (((Lit) = Pla_CubeGetLit(pCube, i)), 1); i++ ) #define Pla_CubeForEachLitIn( p, pCube, Lit, i ) \ Pla_CubeForEachLit( Pla_ManInNum(p), pCube, Lit, i ) #define Pla_CubeForEachLitOut( p, pCube, Lit, i ) \ Pla_CubeForEachLit( Pla_ManOutNum(p), pCube, Lit, i ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if cubes are distance-1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pla_OnlyOneOne( word t ) { return t ? ((t & (t-1)) == 0) : 0; } static inline int Pla_CubesAreDistance1( word * p, word * q, int nWords ) { word Test; int c, fFound = 0; for ( c = 0; c < nWords; c++ ) { if ( p[c] == q[c] ) continue; if ( fFound ) return 0; // check if the number of 1s is one, which means exactly one different literal (0/1, -/1, -/0) Test = ((p[c] ^ q[c]) | ((p[c] ^ q[c]) >> 1)) & MASK55; if ( !Pla_OnlyOneOne(Test) ) return 0; fFound = 1; } return fFound; } static inline int Pla_CubesAreConsensus( word * p, word * q, int nWords, int * piVar ) { word Test; int c, fFound = 0; for ( c = 0; c < nWords; c++ ) { if ( p[c] == q[c] ) continue; if ( fFound ) return 0; // check if the number of 1s is one, which means exactly one opposite literal (0/1) but may have other diffs (-/0 or -/1) Test = ((p[c] ^ q[c]) & ((p[c] ^ q[c]) >> 1)) & MASK55; if ( !Pla_OnlyOneOne(Test) ) return 0; fFound = 1; if ( piVar ) *piVar = c * 32 + Abc_Tt6FirstBit(Test)/2; } return fFound; } static inline int Pla_TtCountOnesOne( word x ) { x = x - ((x >> 1) & ABC_CONST(0x5555555555555555)); x = (x & ABC_CONST(0x3333333333333333)) + ((x >> 2) & ABC_CONST(0x3333333333333333)); x = (x + (x >> 4)) & ABC_CONST(0x0F0F0F0F0F0F0F0F); x = x + (x >> 8); x = x + (x >> 16); x = x + (x >> 32); return (int)(x & 0xFF); } static inline int Pla_TtCountOnes( word * p, int nWords ) { int i, Count = 0; for ( i = 0; i < nWords; i++ ) Count += Pla_TtCountOnesOne( p[i] ); return Count; } /**Function************************************************************* Synopsis [Manager APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Pla_Man_t * Pla_ManAlloc( char * pFileName, int nIns, int nOuts, int nCubes ) { Pla_Man_t * p = ABC_CALLOC( Pla_Man_t, 1 ); p->pName = Extra_FileDesignName( pFileName ); p->pSpec = Abc_UtilStrsav( pFileName ); p->nIns = nIns; p->nOuts = nOuts; p->nInWords = Abc_Bit6WordNum( 2*nIns ); p->nOutWords = Abc_Bit6WordNum( 2*nOuts ); Vec_IntFillNatural( &p->vCubes, nCubes ); Vec_WrdFill( &p->vInBits, Pla_ManCubeNum(p) * p->nInWords, 0 ); Vec_WrdFill( &p->vOutBits, Pla_ManCubeNum(p) * p->nOutWords, 0 ); return p; } static inline void Pla_ManFree( Pla_Man_t * p ) { Vec_IntErase( &p->vCubes ); Vec_IntErase( &p->vHashes ); Vec_WrdErase( &p->vInBits ); Vec_WrdErase( &p->vOutBits ); Vec_WecErase( &p->vCubeLits ); Vec_WecErase( &p->vOccurs ); Vec_IntErase( &p->vDivs ); ABC_FREE( p->pName ); ABC_FREE( p->pSpec ); ABC_FREE( p ); } static inline int Pla_ManLitInNum( Pla_Man_t * p ) { word * pCube; int i, k, Lit, Count = 0; Pla_ForEachCubeIn( p, pCube, i ) Pla_CubeForEachLitIn( p, pCube, Lit, k ) Count += Lit != PLA_LIT_DASH; return Count; } static inline int Pla_ManLitOutNum( Pla_Man_t * p ) { word * pCube; int i, k, Lit, Count = 0; Pla_ForEachCubeOut( p, pCube, i ) Pla_CubeForEachLitOut( p, pCube, Lit, k ) Count += Lit == PLA_LIT_ONE; return Count; } static inline void Pla_ManPrintStats( Pla_Man_t * p, int fVerbose ) { printf( "%-16s : ", Pla_ManName(p) ); printf( "In =%4d ", Pla_ManInNum(p) ); printf( "Out =%4d ", Pla_ManOutNum(p) ); printf( "Cube =%8d ", Pla_ManCubeNum(p) ); printf( "LitIn =%8d ", Pla_ManLitInNum(p) ); printf( "LitOut =%8d ", Pla_ManLitOutNum(p) ); printf( "Div =%6d ", Pla_ManDivNum(p) ); printf( "\n" ); } /*=== plaHash.c ========================================================*/ extern int Pla_ManHashDist1NumTest( Pla_Man_t * p ); extern void Pla_ManComputeDist1Test( Pla_Man_t * p ); /*=== plaMan.c ========================================================*/ extern Vec_Bit_t * Pla_ManPrimesTable( int nVars ); extern Pla_Man_t * Pla_ManPrimesDetector( int nVars ); extern Pla_Man_t * Pla_ManGenerate( int nIns, int nOuts, int nCubes, int fVerbose ); extern void Pla_ManConvertFromBits( Pla_Man_t * p ); extern void Pla_ManConvertToBits( Pla_Man_t * p ); extern int Pla_ManDist1NumTest( Pla_Man_t * p ); /*=== plaMerge.c ========================================================*/ extern int Pla_ManDist1Merge( Pla_Man_t * p ); /*=== plaSimple.c ========================================================*/ extern int Pla_ManFxPerformSimple( int nVars ); /*=== plaRead.c ========================================================*/ extern Pla_Man_t * Pla_ReadPla( char * pFileName ); /*=== plaWrite.c ========================================================*/ extern void Pla_WritePla( Pla_Man_t * p, char * pFileName ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/plaCom.c000066400000000000000000000370321300674244400231060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [plaCom.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: plaCom.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_CommandReadPla ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandWritePla ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static inline Pla_Man_t * Pla_AbcGetMan( Abc_Frame_t * pAbc ) { return (Pla_Man_t *)pAbc->pAbcPla; } static inline void Pla_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcPla ) Pla_ManFree(Pla_AbcGetMan(pAbc)); } static inline void Pla_AbcUpdateMan( Abc_Frame_t * pAbc, Pla_Man_t * p ) { Pla_AbcFreeMan(pAbc); pAbc->pAbcPla = p; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Pla_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "Two-level", "|read", Abc_CommandReadPla, 0 ); Cmd_CommandAdd( pAbc, "Two-level", "|write", Abc_CommandWritePla, 0 ); Cmd_CommandAdd( pAbc, "Two-level", "|ps", Abc_CommandPs, 0 ); Cmd_CommandAdd( pAbc, "Two-level", "|gen", Abc_CommandGen, 0 ); Cmd_CommandAdd( pAbc, "Two-level", "|merge", Abc_CommandMerge, 0 ); Cmd_CommandAdd( pAbc, "Two-level", "|test", Abc_CommandTest, 0 ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Pla_End( Abc_Frame_t * pAbc ) { Pla_AbcFreeMan( pAbc ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Pla_SetMan( Abc_Frame_t * pAbc, Pla_Man_t * p ) { Pla_AbcUpdateMan( pAbc, p ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Abc_CommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Pla_Man_t * p = NULL; 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 ) { printf( "Abc_CommandReadPla(): Input file name should be given on the command line.\n" ); return 0; } // get the file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "r" )) == NULL ) { Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".pla", NULL, NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); Abc_Print( 1, "\n" ); return 0; } fclose( pFile ); // perform reading if ( !strcmp( Extra_FileNameExtension(pFileName), "pla" ) ) p = Pla_ReadPla( pFileName ); else { printf( "Abc_CommandReadPla(): Unknown file extension.\n" ); return 0; } Pla_AbcUpdateMan( pAbc, p ); return 0; usage: Abc_Print( -2, "usage: |read [-vh] \n" ); Abc_Print( -2, "\t reads the SOP from a PLA file\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Abc_CommandWritePla( Abc_Frame_t * pAbc, int argc, char ** argv ) { Pla_Man_t * p = Pla_AbcGetMan(pAbc); 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 ( p == NULL ) { Abc_Print( 1, "Abc_CommandWritePla(): There is no current design.\n" ); return 0; } if ( argc == globalUtilOptind ) pFileName = Extra_FileNameGenericAppend( p->pName, "_out.v" ); else if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; else { printf( "Output file name should be given on the command line.\n" ); return 0; } Pla_WritePla( p, pFileName ); return 0; usage: Abc_Print( -2, "usage: |write [-vh]\n" ); Abc_Print( -2, "\t writes the SOP into a PLA file\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Abc_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv ) { Pla_Man_t * p = Pla_AbcGetMan(pAbc); int fShowMulti = 0; int fShowAdder = 0; int fDistrib = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "madvh" ) ) != EOF ) { switch ( c ) { case 'm': fShowMulti ^= 1; break; case 'a': fShowAdder ^= 1; break; case 'd': fDistrib ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Abc_CommandPs(): There is no current design.\n" ); return 0; } Pla_ManPrintStats( p, fVerbose ); return 0; usage: Abc_Print( -2, "usage: |ps [-madvh]\n" ); Abc_Print( -2, "\t prints statistics\n" ); Abc_Print( -2, "\t-m : toggle printing multipliers [default = %s]\n", fShowMulti? "yes": "no" ); Abc_Print( -2, "\t-a : toggle printing adders [default = %s]\n", fShowAdder? "yes": "no" ); Abc_Print( -2, "\t-d : toggle printing distrubition [default = %s]\n", fDistrib? "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_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Pla_GenSorter( int nVars ); Pla_Man_t * p = NULL; int nInputs = 8; int nOutputs = 1; int nCubes = 20; int Seed = 0; int fSorter = 0; int fPrimes = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IOPSspvh" ) ) != 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++; if ( nInputs < 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; } nOutputs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nOutputs < 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; } nCubes = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCubes < 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 's': fSorter ^= 1; break; case 'p': fPrimes ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fSorter ) Pla_GenSorter( nInputs ); else if ( fPrimes ) p = Pla_ManPrimesDetector( nInputs ); else { Gia_ManRandom( 1 ); for ( c = 0; c < Seed; c++ ) Gia_ManRandom( 0 ); p = Pla_ManGenerate( nInputs, nOutputs, nCubes, fVerbose ); } Pla_AbcUpdateMan( pAbc, p ); return 0; usage: Abc_Print( -2, "usage: |gen [-IOPS num] [-spvh]\n" ); Abc_Print( -2, "\t generate random or specialized SOP\n" ); Abc_Print( -2, "\t-I num : the number of inputs [default = %d]\n", nInputs ); Abc_Print( -2, "\t-O num : the number of outputs [default = %d]\n", nOutputs ); Abc_Print( -2, "\t-P num : the number of products [default = %d]\n", nCubes ); Abc_Print( -2, "\t-S num : ramdom seed (0 <= num <= 1000) [default = %d]\n", Seed ); Abc_Print( -2, "\t-s : toggle generating sorter as a PLA file [default = %s]\n", fSorter? "yes": "no" ); Abc_Print( -2, "\t-p : toggle generating prime detector [default = %s]\n", fPrimes? "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_CommandMerge( Abc_Frame_t * pAbc, int argc, char ** argv ) { Pla_Man_t * p = Pla_AbcGetMan(pAbc); int c, fMulti = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF ) { switch ( c ) { case 'm': fMulti ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( p == NULL ) { Abc_Print( 1, "Abc_CommandMerge(): There is no current design.\n" ); return 0; } // transform Pla_ManDist1Merge( p ); return 0; usage: Abc_Print( -2, "usage: |merge [-mvh]\n" ); Abc_Print( -2, "\t performs distance-1 merge using cube hashing\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_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Pla_Man_t * p = Pla_AbcGetMan(pAbc); int c, nVars = 4, 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; } nVars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVars < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } /* if ( p == NULL ) { Abc_Print( 1, "Abc_CommandTest(): There is no current design.\n" ); return 0; } */ //Pla_ManFxPerformSimple( nVars ); //Pla_ManConvertFromBits( p ); //Pla_ManConvertToBits( p ); //Pla_ManPerformFxch( p ); return 0; usage: Abc_Print( -2, "usage: |test [-N num] [-vh]\n" ); Abc_Print( -2, "\t experiments with SOPs\n" ); Abc_Print( -2, "\t-N num : the number of variables [default = %d]\n", nVars ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/plaFxch.c000066400000000000000000000747411300674244400232700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [plaFxch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: plaFxch.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" #include "misc/vec/vecHash.h" #include "misc/vec/vecQue.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Fxch_Obj_t_ Fxch_Obj_t; struct Fxch_Obj_t_ { unsigned Table : 30; unsigned MarkN : 1; unsigned MarkP : 1; int Next; int Prev; int Cube; }; typedef struct Fxch_Man_t_ Fxch_Man_t; struct Fxch_Man_t_ { // user's data Vec_Wec_t vCubes; // cube -> lit // internal data Vec_Wec_t vLits; // lit -> cube Vec_Int_t vRands; // random numbers for each literal Vec_Int_t vCubeLinks; // first link for each cube Fxch_Obj_t * pBins; // hash table (lits -> cube + lit) Hash_IntMan_t * vHash; // divisor hash table Vec_Que_t * vPrio; // priority queue for divisors by weight Vec_Flt_t vWeights; // divisor weights Vec_Wec_t vPairs; // cube pairs for each div Vec_Wrd_t vDivs; // extracted divisors // temporary data Vec_Int_t vCubesS; // cube pairs for single Vec_Int_t vCubesD; // cube pairs for double Vec_Int_t vCube1; // first cube Vec_Int_t vCube2; // second cube // statistics abctime timeStart; // starting time int SizeMask; // hash table mask int nVars; // original problem variables int nLits; // the number of SOP literals int nCompls; // the number of complements int nPairsS; // number of lit pairs int nPairsD; // number of cube pairs }; #define Fxch_ManForEachCubeVec( vVec, vCubes, vCube, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((vCube) = Vec_WecEntry(vCubes, Vec_IntEntry(vVec, i))); i++ ) static inline Vec_Int_t * Fxch_ManCube( Fxch_Man_t * p, int hCube ) { return Vec_WecEntry(&p->vCubes, Pla_CubeNum(hCube)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the current state of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxch_ManWriteBlif( char * pFileName, Vec_Wec_t * vCubes, Vec_Wrd_t * vDivs ) { // find the number of original variables int nVarsInit = Vec_WrdCountZero(vDivs); FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { //char * pLits = "-01?"; Vec_Str_t * vStr; Vec_Int_t * vCube; int i, k, Lit; word Div; // comment fprintf( pFile, "# BLIF file written via PLA package in ABC on " ); fprintf( pFile, "%s", Extra_TimeStamp() ); fprintf( pFile, "\n\n" ); // header fprintf( pFile, ".model %s\n", pFileName ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nVarsInit; i++ ) fprintf( pFile, " i%d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs o" ); fprintf( pFile, "\n" ); // SOP header fprintf( pFile, ".names" ); for ( i = 0; i < Vec_WrdSize(vDivs); i++ ) fprintf( pFile, " i%d", i ); fprintf( pFile, " o\n" ); // SOP cubes vStr = Vec_StrStart( Vec_WrdSize(vDivs) + 1 ); Vec_WecForEachLevel( vCubes, vCube, i ) { if ( !Vec_IntSize(vCube) ) continue; for ( k = 0; k < Vec_WrdSize(vDivs); k++ ) Vec_StrWriteEntry( vStr, k, '-' ); Vec_IntForEachEntry( vCube, Lit, k ) Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit) ? '0' : '1') ); fprintf( pFile, "%s 1\n", Vec_StrArray(vStr) ); } Vec_StrFree( vStr ); // divisors Vec_WrdForEachEntryStart( vDivs, Div, i, nVarsInit ) { int pLits[2] = { (int)(Div & 0xFFFFFFFF), (int)(Div >> 32) }; fprintf( pFile, ".names" ); fprintf( pFile, " i%d", Abc_Lit2Var(pLits[0]) ); fprintf( pFile, " i%d", Abc_Lit2Var(pLits[1]) ); fprintf( pFile, " i%d\n", i ); fprintf( pFile, "%d%d 1\n", !Abc_LitIsCompl(pLits[0]), !Abc_LitIsCompl(pLits[1]) ); } fprintf( pFile, ".end\n\n" ); fclose( pFile ); printf( "Written BLIF file \"%s\".\n", pFileName ); } } /**Function************************************************************* Synopsis [Starting the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxch_Man_t * Fxch_ManStart( Vec_Wec_t * vCubes, Vec_Wec_t * vLits ) { Vec_Int_t * vCube; int i, LogSize; Fxch_Man_t * p = ABC_CALLOC( Fxch_Man_t, 1 ); p->vCubes = *vCubes; p->vLits = *vLits; p->nVars = Vec_WecSize(vLits)/2; p->nLits = 0; // random numbers Gia_ManRandom( 1 ); Vec_IntGrow( &p->vRands, 2*p->nVars ); for ( i = 0; i < 2*p->nVars; i++ ) Vec_IntPush( &p->vRands, Gia_ManRandom(0) & 0x3FFFFFF ); // assert( LogSize <= 26 ); // create cube links Vec_IntGrow( &p->vCubeLinks, Vec_WecSize(&p->vCubes) ); Vec_WecForEachLevel( vCubes, vCube, i ) { Vec_IntPush( &p->vCubeLinks, p->nLits+1 ); p->nLits += Vec_IntSize(vCube); } assert( Vec_IntSize(&p->vCubeLinks) == Vec_WecSize(&p->vCubes) ); // create table LogSize = Abc_Base2Log( p->nLits+1 ); assert( LogSize <= 26 ); p->SizeMask = (1 << LogSize) - 1; p->pBins = ABC_CALLOC( Fxch_Obj_t, p->SizeMask + 1 ); assert( p->nLits+1 < p->SizeMask+1 ); // divisor weights and cube pairs Vec_FltGrow( &p->vWeights, 1000 ); Vec_FltPush( &p->vWeights, -1 ); Vec_WecGrow( &p->vPairs, 1000 ); Vec_WecPushLevel( &p->vPairs ); // prepare divisors Vec_WrdGrow( &p->vDivs, p->nVars + 1000 ); Vec_WrdFill( &p->vDivs, p->nVars, 0 ); return p; } void Fxch_ManStop( Fxch_Man_t * p ) { Vec_WecErase( &p->vCubes ); Vec_WecErase( &p->vLits ); Vec_IntErase( &p->vRands ); Vec_IntErase( &p->vCubeLinks ); Hash_IntManStop( p->vHash ); Vec_QueFree( p->vPrio ); Vec_FltErase( &p->vWeights ); Vec_WecErase( &p->vPairs ); Vec_WrdErase( &p->vDivs ); Vec_IntErase( &p->vCubesS ); Vec_IntErase( &p->vCubesD ); Vec_IntErase( &p->vCube1 ); Vec_IntErase( &p->vCube2 ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fxch_TabCompare( Fxch_Man_t * p, int hCube1, int hCube2 ) { Vec_Int_t * vCube1 = Fxch_ManCube( p, hCube1 ); Vec_Int_t * vCube2 = Fxch_ManCube( p, hCube2 ); if ( !Vec_IntSize(vCube1) || !Vec_IntSize(vCube2) || Vec_IntSize(vCube1) != Vec_IntSize(vCube2) ) return 0; Vec_IntClear( &p->vCube1 ); Vec_IntClear( &p->vCube2 ); Vec_IntAppendSkip( &p->vCube1, vCube1, Pla_CubeLit(hCube1) ); Vec_IntAppendSkip( &p->vCube2, vCube2, Pla_CubeLit(hCube2) ); return Vec_IntEqual( &p->vCube1, &p->vCube2 ); } static inline void Fxch_CompressCubes( Fxch_Man_t * p, Vec_Int_t * vLit2Cube ) { int i, hCube, k = 0; Vec_IntForEachEntry( vLit2Cube, hCube, i ) if ( Vec_IntSize(Vec_WecEntry(&p->vCubes, hCube)) > 0 ) Vec_IntWriteEntry( vLit2Cube, k++, hCube ); Vec_IntShrink( vLit2Cube, k ); } static inline int Fxch_CollectSingles( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr ) { int * pBeg1 = vArr1->pArray; int * pBeg2 = vArr2->pArray; int * pEnd1 = vArr1->pArray + vArr1->nSize; int * pEnd2 = vArr2->pArray + vArr2->nSize; int * pBeg1New = vArr1->pArray; int * pBeg2New = vArr2->pArray; Vec_IntClear( vArr ); while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( Pla_CubeNum(*pBeg1) == Pla_CubeNum(*pBeg2) ) Vec_IntPushTwo( vArr, *pBeg1, *pBeg2 ), pBeg1++, pBeg2++; else if ( *pBeg1 < *pBeg2 ) *pBeg1New++ = *pBeg1++; else *pBeg2New++ = *pBeg2++; } while ( pBeg1 < pEnd1 ) *pBeg1New++ = *pBeg1++; while ( pBeg2 < pEnd2 ) *pBeg2New++ = *pBeg2++; Vec_IntShrink( vArr1, pBeg1New - vArr1->pArray ); Vec_IntShrink( vArr2, pBeg2New - vArr2->pArray ); return Vec_IntSize(vArr); } static inline void Fxch_CollectDoubles( Fxch_Man_t * p, Vec_Int_t * vPairs, Vec_Int_t * vRes, int Lit0, int Lit1 ) { int i, hCube1, hCube2; Vec_IntClear( vRes ); Vec_IntForEachEntryDouble( vPairs, hCube1, hCube2, i ) if ( Fxch_TabCompare(p, hCube1, hCube2) && Vec_IntEntry(Fxch_ManCube(p, hCube1), Pla_CubeLit(hCube1)) == Lit0 && Vec_IntEntry(Fxch_ManCube(p, hCube2), Pla_CubeLit(hCube2)) == Lit1 ) Vec_IntPushTwo( vRes, hCube1, hCube2 ); Vec_IntClear( vPairs ); // order pairs in the increasing order of the first cube //Vec_IntSortPairs( vRes ); } static inline void Fxch_CompressLiterals2( Vec_Int_t * p, int iInd1, int iInd2 ) { int i, Lit, k = 0; assert( iInd1 >= 0 && iInd1 < Vec_IntSize(p) ); if ( iInd2 != -1 ) assert( iInd1 >= 0 && iInd1 < Vec_IntSize(p) ); Vec_IntForEachEntry( p, Lit, i ) if ( i != iInd1 && i != iInd2 ) Vec_IntWriteEntry( p, k++, Lit ); Vec_IntShrink( p, k ); } static inline void Fxch_CompressLiterals( Vec_Int_t * p, int iLit1, int iLit2 ) { int i, Lit, k = 0; Vec_IntForEachEntry( p, Lit, i ) if ( Lit != iLit1 && Lit != iLit2 ) Vec_IntWriteEntry( p, k++, Lit ); assert( Vec_IntSize(p) == k + 2 ); Vec_IntShrink( p, k ); } static inline void Fxch_FilterCubes( Fxch_Man_t * p, Vec_Int_t * vCubesS, int Lit0, int Lit1 ) { Vec_Int_t * vCube; int i, k, Lit, iCube, n = 0; int fFound0, fFound1; Vec_IntForEachEntry( vCubesS, iCube, i ) { vCube = Vec_WecEntry( &p->vCubes, iCube ); fFound0 = fFound1 = 0; Vec_IntForEachEntry( vCube, Lit, k ) { if ( Lit == Lit0 ) fFound0 = 1; else if ( Lit == Lit1 ) fFound1 = 1; } if ( fFound0 && fFound1 ) Vec_IntWriteEntry( vCubesS, n++, Pla_CubeHandle(iCube, 255) ); } Vec_IntShrink( vCubesS, n ); } /**Function************************************************************* Synopsis [Divisor addition removal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxch_DivisorAdd( Fxch_Man_t * p, int Lit0, int Lit1, int Weight ) { int iDiv; assert( Lit0 != Lit1 ); if ( Lit0 < Lit1 ) iDiv = Hash_Int2ManInsert( p->vHash, Lit0, Lit1, 0 ); else iDiv = Hash_Int2ManInsert( p->vHash, Lit1, Lit0, 0 ); if ( iDiv == Vec_FltSize(&p->vWeights) ) { Vec_FltPush( &p->vWeights, -2 ); Vec_WecPushLevel( &p->vPairs ); assert( Vec_FltSize(&p->vWeights) == Vec_WecSize(&p->vPairs) ); } Vec_FltAddToEntry( &p->vWeights, iDiv, Weight ); if ( p->vPrio ) { if ( Vec_QueIsMember(p->vPrio, iDiv) ) Vec_QueUpdate( p->vPrio, iDiv ); else Vec_QuePush( p->vPrio, iDiv ); //assert( iDiv < Vec_QueSize(p->vPrio) ); } return iDiv; } void Fxch_DivisorRemove( Fxch_Man_t * p, int Lit0, int Lit1, int Weight ) { int iDiv; assert( Lit0 != Lit1 ); if ( Lit0 < Lit1 ) iDiv = *Hash_Int2ManLookup( p->vHash, Lit0, Lit1 ); else iDiv = *Hash_Int2ManLookup( p->vHash, Lit1, Lit0 ); assert( iDiv > 0 && iDiv < Vec_FltSize(&p->vWeights) ); Vec_FltAddToEntry( &p->vWeights, iDiv, -Weight ); if ( Vec_QueIsMember(p->vPrio, iDiv) ) Vec_QueUpdate( p->vPrio, iDiv ); } /**Function************************************************************* Synopsis [Starting the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Fxch_Obj_t * Fxch_TabBin( Fxch_Man_t * p, int Value ) { return p->pBins + (Value & p->SizeMask); } static inline Fxch_Obj_t * Fxch_TabEntry( Fxch_Man_t * p, int i ) { return i ? p->pBins + i : NULL; } static inline int Fxch_TabEntryId( Fxch_Man_t * p, Fxch_Obj_t * pEnt ) { assert(pEnt > p->pBins); return pEnt - p->pBins; } static inline void Fxch_TabMarkPair( Fxch_Man_t * p, int i, int j ) { Fxch_Obj_t * pI = Fxch_TabEntry(p, i); Fxch_Obj_t * pJ = Fxch_TabEntry(p, j); assert( pI->Next == j ); assert( pJ->Prev == i ); assert( pI->MarkN == 0 ); assert( pI->MarkP == 0 ); assert( pJ->MarkN == 0 ); assert( pJ->MarkP == 0 ); pI->MarkN = 1; pJ->MarkP = 1; } static inline void Fxch_TabUnmarkPair( Fxch_Man_t * p, int i, int j ) { Fxch_Obj_t * pI = Fxch_TabEntry(p, i); Fxch_Obj_t * pJ = Fxch_TabEntry(p, j); assert( pI->Next == j ); assert( pJ->Prev == i ); assert( pI->MarkN == 1 ); assert( pI->MarkP == 0 ); assert( pJ->MarkN == 0 ); assert( pJ->MarkP == 1 ); pI->MarkN = 0; pJ->MarkP = 0; } static inline void Fxch_TabInsertLink( Fxch_Man_t * p, int i, int j, int fSkipCheck ) { Fxch_Obj_t * pI = Fxch_TabEntry(p, i); Fxch_Obj_t * pN = Fxch_TabEntry(p, pI->Next); Fxch_Obj_t * pJ = Fxch_TabEntry(p, j); //assert( pJ->Cube != 0 ); assert( pN->Prev == i ); assert( fSkipCheck || pI->MarkN == 0 ); assert( fSkipCheck || pN->MarkP == 0 ); assert( fSkipCheck || pJ->MarkN == 0 ); assert( fSkipCheck || pJ->MarkP == 0 ); pJ->Next = pI->Next; pI->Next = j; pJ->Prev = i; pN->Prev = j; } static inline void Fxch_TabExtractLink( Fxch_Man_t * p, int i, int j ) { Fxch_Obj_t * pI = Fxch_TabEntry(p, i); Fxch_Obj_t * pJ = Fxch_TabEntry(p, j); Fxch_Obj_t * pN = Fxch_TabEntry(p, pJ->Next); //assert( pJ->Cube != 0 ); assert( pI->Next == j ); assert( pJ->Prev == i ); assert( pN->Prev == j ); assert( pI->MarkN == 0 ); assert( pJ->MarkP == 0 ); assert( pJ->MarkN == 0 ); assert( pN->MarkP == 0 ); pI->Next = pJ->Next; pJ->Next = 0; pN->Prev = pJ->Prev; pJ->Prev = 0; } static inline void Fxch_TabInsert( Fxch_Man_t * p, int iLink, int Value, int hCube ) { int iEnt, iDiv, Lit0, Lit1, fStart = 1; Fxch_Obj_t * pEnt; Fxch_Obj_t * pBin = Fxch_TabBin( p, Value ); Fxch_Obj_t * pCell = Fxch_TabEntry( p, iLink ); assert( pCell->MarkN == 0 ); assert( pCell->MarkP == 0 ); assert( pCell->Cube == 0 ); pCell->Cube = hCube; if ( pBin->Table == 0 ) { pBin->Table = pCell->Next = pCell->Prev = iLink; return; } // find equal cubes for ( iEnt = pBin->Table; iEnt != (int)pBin->Table || fStart; iEnt = pEnt->Next, fStart = 0 ) { pEnt = Fxch_TabBin( p, iEnt ); if ( pEnt->MarkN || pEnt->MarkP || !Fxch_TabCompare(p, pEnt->Cube, hCube) ) continue; Fxch_TabInsertLink( p, iEnt, iLink, 0 ); Fxch_TabMarkPair( p, iEnt, iLink ); // get literals Lit0 = Vec_IntEntry( Fxch_ManCube(p, hCube), Pla_CubeLit(hCube) ); Lit1 = Vec_IntEntry( Fxch_ManCube(p, pEnt->Cube), Pla_CubeLit(pEnt->Cube) ); // increment divisor weight iDiv = Fxch_DivisorAdd( p, Abc_LitNot(Lit0), Abc_LitNot(Lit1), Vec_IntSize(Fxch_ManCube(p, hCube)) ); // add divisor pair assert( iDiv < Vec_WecSize(&p->vPairs) ); if ( Lit0 < Lit1 ) { Vec_WecPush( &p->vPairs, iDiv, hCube ); Vec_WecPush( &p->vPairs, iDiv, pEnt->Cube ); } else { Vec_WecPush( &p->vPairs, iDiv, pEnt->Cube ); Vec_WecPush( &p->vPairs, iDiv, hCube ); } p->nPairsD++; return; } assert( iEnt == (int)pBin->Table ); pEnt = Fxch_TabBin( p, iEnt ); Fxch_TabInsertLink( p, pEnt->Prev, iLink, 1 ); } static inline void Fxch_TabExtract( Fxch_Man_t * p, int iLink, int Value, int hCube ) { int Lit0, Lit1; Fxch_Obj_t * pPair = NULL; Fxch_Obj_t * pBin = Fxch_TabBin( p, Value ); Fxch_Obj_t * pLink = Fxch_TabEntry( p, iLink ); assert( pLink->Cube == hCube ); if ( pLink->MarkN ) { pPair = Fxch_TabEntry( p, pLink->Next ); Fxch_TabUnmarkPair( p, iLink, pLink->Next ); } else if ( pLink->MarkP ) { pPair = Fxch_TabEntry( p, pLink->Prev ); Fxch_TabUnmarkPair( p, pLink->Prev, iLink ); } if ( (int)pBin->Table == iLink ) pBin->Table = pLink->Next != iLink ? pLink->Next : 0; if ( pLink->Next == iLink ) { assert( pLink->Prev == iLink ); pLink->Next = pLink->Prev = 0; } else Fxch_TabExtractLink( p, pLink->Prev, iLink ); pLink->Cube = 0; if ( pPair == NULL ) return; assert( Fxch_TabCompare(p, pPair->Cube, hCube) ); // get literals Lit0 = Vec_IntEntry( Fxch_ManCube(p, hCube), Pla_CubeLit(hCube) ); Lit1 = Vec_IntEntry( Fxch_ManCube(p, pPair->Cube), Pla_CubeLit(pPair->Cube) ); // decrement divisor weight Fxch_DivisorRemove( p, Abc_LitNot(Lit0), Abc_LitNot(Lit1), Vec_IntSize(Fxch_ManCube(p, hCube)) ); p->nPairsD--; } /**Function************************************************************* Synopsis [Starting the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxch_TabSingleDivisors( Fxch_Man_t * p, int iCube, int fAdd ) { Vec_Int_t * vCube = Vec_WecEntry( &p->vCubes, iCube ); int i, k, Lit, Lit2; if ( Vec_IntSize(vCube) < 2 ) return 0; Vec_IntForEachEntry( vCube, Lit, i ) Vec_IntForEachEntryStart( vCube, Lit2, k, i+1 ) { assert( Lit < Lit2 ); if ( fAdd ) Fxch_DivisorAdd( p, Lit, Lit2, 1 ), p->nPairsS++; else Fxch_DivisorRemove( p, Lit, Lit2, 1 ), p->nPairsS--; } return Vec_IntSize(vCube) * (Vec_IntSize(vCube) - 1) / 2; } int Fxch_TabDoubleDivisors( Fxch_Man_t * p, int iCube, int fAdd ) { Vec_Int_t * vCube = Vec_WecEntry( &p->vCubes, iCube ); int iLinkFirst = Vec_IntEntry( &p->vCubeLinks, iCube ); int k, Lit, Value = 0; Vec_IntForEachEntry( vCube, Lit, k ) Value += Vec_IntEntry(&p->vRands, Lit); Vec_IntForEachEntry( vCube, Lit, k ) { Value -= Vec_IntEntry(&p->vRands, Lit); if ( fAdd ) Fxch_TabInsert( p, iLinkFirst + k, Value, Pla_CubeHandle(iCube, k) ); else Fxch_TabExtract( p, iLinkFirst + k, Value, Pla_CubeHandle(iCube, k) ); Value += Vec_IntEntry(&p->vRands, Lit); } return 1; } void Fxch_ManCreateDivisors( Fxch_Man_t * p ) { float Weight; int i; // alloc hash table assert( p->vHash == NULL ); p->vHash = Hash_IntManStart( 1000 ); // create single-cube two-literal divisors for ( i = 0; i < Vec_WecSize(&p->vCubes); i++ ) Fxch_TabSingleDivisors( p, i, 1 ); // add - no update // create two-cube divisors for ( i = 0; i < Vec_WecSize(&p->vCubes); i++ ) Fxch_TabDoubleDivisors( p, i, 1 ); // add - no update // create queue with all divisors p->vPrio = Vec_QueAlloc( Vec_FltSize(&p->vWeights) ); Vec_QueSetPriority( p->vPrio, Vec_FltArrayP(&p->vWeights) ); Vec_FltForEachEntry( &p->vWeights, Weight, i ) if ( Weight > 0.0 ) Vec_QuePush( p->vPrio, i ); } /**Function************************************************************* Synopsis [Updates the data-structure when one divisor is selected.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxch_ManUpdate( Fxch_Man_t * p, int iDiv ) { Vec_Int_t * vCube1, * vCube2, * vLitP, * vLitN; //int nLitsNew = p->nLits - (int)Vec_FltEntry(&p->vWeights, iDiv); int i, Lit0, Lit1, hCube1, hCube2, iVarNew; //float Diff = Vec_FltEntry(&p->vWeights, iDiv) - (float)((int)Vec_FltEntry(&p->vWeights, iDiv)); //assert( Diff > 0.0 && Diff < 1.0 ); // get the divisor and select pivot variables Vec_IntPush( &p->vRands, Gia_ManRandom(0) & 0x3FFFFFF ); Vec_IntPush( &p->vRands, Gia_ManRandom(0) & 0x3FFFFFF ); Lit0 = Hash_IntObjData0( p->vHash, iDiv ); Lit1 = Hash_IntObjData1( p->vHash, iDiv ); assert( Lit0 >= 0 && Lit1 >= 0 && Lit0 < Lit1 ); Vec_WrdPush( &p->vDivs, ((word)Lit1 << 32) | (word)Lit0 ); // if the input cover is not prime, it may happen that we are extracting divisor (x + !x) // although it is not strictly correct, it seems to be fine to just skip such divisors // if ( Abc_Lit2Var(Lit0) == Abc_Lit2Var(Lit1) && Vec_IntSize(Hsh_VecReadEntry(p->vHash, iDiv)) == 2 ) // return; // collect single-cube-divisor cubes vLitP = Vec_WecEntry(&p->vLits, Lit0); vLitN = Vec_WecEntry(&p->vLits, Lit1); Fxch_CompressCubes( p, vLitP ); Fxch_CompressCubes( p, vLitN ); // Fxch_CollectSingles( vLitP, vLitN, &p->vCubesS ); // assert( Vec_IntSize(&p->vCubesS) % 2 == 0 ); Vec_IntTwoRemoveCommon( vLitP, vLitN, &p->vCubesS ); Fxch_FilterCubes( p, &p->vCubesS, Lit0, Lit1 ); // collect double-cube-divisor cube pairs Fxch_CollectDoubles( p, Vec_WecEntry(&p->vPairs, iDiv), &p->vCubesD, Abc_LitNot(Lit0), Abc_LitNot(Lit1) ); assert( Vec_IntSize(&p->vCubesD) % 2 == 0 ); Vec_IntUniqifyPairs( &p->vCubesD ); assert( Vec_IntSize(&p->vCubesD) % 2 == 0 ); // subtract cost of single-cube divisors // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube1), 0 ); // remove - update Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube1), 0 ), // remove - update Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube2), 0 ); // remove - update // subtract cost of double-cube divisors // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) { //printf( "%d ", Pla_CubeNum(hCube1) ); Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube1), 0 ); // remove - update } //printf( "\n" ); Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) { //printf( "%d ", Pla_CubeNum(hCube1) ); //printf( "%d ", Pla_CubeNum(hCube2) ); Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube1), 0 ), // remove - update Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube2), 0 ); // remove - update } //printf( "\n" ); // create new literals p->nLits += 2; iVarNew = Vec_WecSize( &p->vLits ) / 2; vLitP = Vec_WecPushLevel( &p->vLits ); vLitN = Vec_WecPushLevel( &p->vLits ); vLitP = Vec_WecEntry( &p->vLits, Vec_WecSize(&p->vLits) - 2 ); // update single-cube divisor cubes // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) { // int Lit0s, Lit1s; vCube1 = Fxch_ManCube( p, hCube1 ); // Lit0s = Vec_IntEntry(vCube1, Pla_CubeLit(hCube1)); // Lit1s = Vec_IntEntry(vCube1, Pla_CubeLit(hCube2)); // assert( Pla_CubeNum(hCube1) == Pla_CubeNum(hCube2) ); // assert( Vec_IntEntry(vCube1, Pla_CubeLit(hCube1)) == Lit0 ); // assert( Vec_IntEntry(vCube1, Pla_CubeLit(hCube2)) == Lit1 ); Fxch_CompressLiterals( vCube1, Lit0, Lit1 ); // Vec_IntPush( vLitP, Pla_CubeHandle(Pla_CubeNum(hCube1), Vec_IntSize(vCube1)) ); Vec_IntPush( vLitP, Pla_CubeNum(hCube1) ); Vec_IntPush( vCube1, Abc_Var2Lit(iVarNew, 0) ); //if ( Pla_CubeNum(hCube1) == 3 ) // printf( "VecSize = %d\n", Vec_IntSize(vCube1) ); p->nLits--; } // update double-cube divisor cube pairs Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) { vCube1 = Fxch_ManCube( p, hCube1 ); vCube2 = Fxch_ManCube( p, hCube2 ); assert( Vec_IntEntry(vCube1, Pla_CubeLit(hCube1)) == Abc_LitNot(Lit0) ); assert( Vec_IntEntry(vCube2, Pla_CubeLit(hCube2)) == Abc_LitNot(Lit1) ); Fxch_CompressLiterals2( vCube1, Pla_CubeLit(hCube1), -1 ); // Vec_IntPush( vLitN, Pla_CubeHandle(Pla_CubeNum(hCube1), Vec_IntSize(vCube1)) ); Vec_IntPush( vLitN, Pla_CubeNum(hCube1) ); Vec_IntPush( vCube1, Abc_Var2Lit(iVarNew, 1) ); p->nLits -= Vec_IntSize(vCube2); //if ( Pla_CubeNum(hCube1) == 3 ) // printf( "VecSize = %d\n", Vec_IntSize(vCube1) ); // remove second cube Vec_IntClear( vCube2 ); } Vec_IntSort( vLitN, 0 ); Vec_IntSort( vLitP, 0 ); // add cost of single-cube divisors // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube1), 1 ); // add - update Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) Fxch_TabSingleDivisors( p, Pla_CubeNum(hCube1), 1 ); // add - update // add cost of double-cube divisors // Vec_IntForEachEntryDouble( &p->vCubesS, hCube1, hCube2, i ) Vec_IntForEachEntry( &p->vCubesS, hCube1, i ) Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube1), 1 ); // add - update Vec_IntForEachEntryDouble( &p->vCubesD, hCube1, hCube2, i ) Fxch_TabDoubleDivisors( p, Pla_CubeNum(hCube1), 1 ); // add - update // check predicted improvement: (new SOP lits == old SOP lits - divisor weight) //assert( p->nLits == nLitsNew ); } /**Function************************************************************* Synopsis [Implements the improved fast_extract algorithm.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Fxch_PrintStats( Fxch_Man_t * p, abctime clk ) { printf( "Num =%6d ", Vec_WrdSize(&p->vDivs) - p->nVars ); printf( "Cubes =%8d ", Vec_WecSizeUsed(&p->vCubes) ); printf( "Lits =%8d ", p->nLits ); printf( "Divs =%8d ", Hash_IntManEntryNum(p->vHash) ); printf( "Divs+ =%8d ", Vec_QueSize(p->vPrio) ); printf( "PairS =%6d ", p->nPairsS ); printf( "PairD =%6d ", p->nPairsD ); Abc_PrintTime( 1, "Time", clk ); // printf( "\n" ); } static inline void Fxch_PrintDivOne( Fxch_Man_t * p, int iDiv ) { int i; int Lit0 = Hash_IntObjData0( p->vHash, iDiv ); int Lit1 = Hash_IntObjData1( p->vHash, iDiv ); assert( Lit0 >= 0 && Lit1 >= 0 && Lit0 < Lit1 ); printf( "Div %4d : ", iDiv ); printf( "Weight %12.5f ", Vec_FltEntry(&p->vWeights, iDiv) ); printf( "Pairs = %5d ", Vec_IntSize(Vec_WecEntry(&p->vPairs, iDiv))/2 ); for ( i = 0; i < Vec_WrdSize(&p->vDivs); i++ ) { if ( i == Abc_Lit2Var(Lit0) ) printf( "%d", !Abc_LitIsCompl(Lit0) ); else if ( i == Abc_Lit2Var(Lit1) ) printf( "%d", !Abc_LitIsCompl(Lit1) ); else printf( "-" ); } printf( "\n" ); } static void Fxch_PrintDivisors( Fxch_Man_t * p ) { int iDiv; for ( iDiv = 1; iDiv < Vec_FltSize(&p->vWeights); iDiv++ ) Fxch_PrintDivOne( p, iDiv ); printf( "\n" ); } int Fxch_ManFastExtract( Fxch_Man_t * p, int fVerbose, int fVeryVerbose ) { int nNewNodesMax = ABC_INFINITY; abctime clk = Abc_Clock(); int i, iDiv; Fxch_ManCreateDivisors( p ); // Fxch_PrintDivisors( p ); if ( fVerbose ) Fxch_PrintStats( p, Abc_Clock() - clk ); p->timeStart = Abc_Clock(); for ( i = 0; i < nNewNodesMax && Vec_QueTopPriority(p->vPrio) > 0.0; i++ ) { iDiv = Vec_QuePop(p->vPrio); //if ( fVerbose ) // Fxch_PrintStats( p, Abc_Clock() - clk ); if ( fVeryVerbose ) Fxch_PrintDivOne( p, iDiv ); Fxch_ManUpdate( p, iDiv ); } if ( fVerbose ) Fxch_PrintStats( p, Abc_Clock() - clk ); return 1; } /**Function************************************************************* Synopsis [Implements the improved fast_extract algorithm.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pla_ManPerformFxch( Pla_Man_t * p ) { char pFileName[1000]; Fxch_Man_t * pFxch; Pla_ManConvertFromBits( p ); pFxch = Fxch_ManStart( &p->vCubeLits, &p->vOccurs ); Vec_WecZero( &p->vCubeLits ); Vec_WecZero( &p->vOccurs ); Fxch_ManFastExtract( pFxch, 1, 0 ); sprintf( pFileName, "%s.blif", Pla_ManName(p) ); //Fxch_ManWriteBlif( pFileName, &pFxch->vCubes, &pFxch->vDivs ); Fxch_ManStop( pFxch ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/plaHash.c000066400000000000000000000316701300674244400232550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [plaHash.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: plaHash.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define PLA_HASH_VALUE_NUM 256 static unsigned s_PlaHashValues[PLA_HASH_VALUE_NUM] = { 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 inline int Pla_HashValue( int i ) { assert( i >= 0 && i < PLA_HASH_VALUE_NUM ); return s_PlaHashValues[i] & 0x3FFFFFF; } #define PLA_LIT_UNUSED 0xFFFF typedef struct Tab_Obj_t_ Tab_Obj_t; struct Tab_Obj_t_ { int Table; int Next; int Cube; unsigned VarA : 16; unsigned VarB : 16; }; typedef struct Tab_Man_t_ Tab_Man_t; struct Tab_Man_t_ { int SizeMask; // table size (2^Degree-1) int nBins; // number of entries Tab_Obj_t * pBins; // hash table (lits -> cube + lit + lit) Pla_Man_t * pMan; // manager }; static inline Tab_Obj_t * Tab_ManBin( Tab_Man_t * p, int Value ) { return p->pBins + (Value & p->SizeMask); } static inline Tab_Obj_t * Tab_ManEntry( Tab_Man_t * p, int i ) { return i ? p->pBins + i : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Tab_Man_t * Tab_ManAlloc( int LogSize, Pla_Man_t * pMan ) { Tab_Man_t * p = ABC_CALLOC( Tab_Man_t, 1 ); assert( LogSize >= 4 && LogSize <= 26 ); p->SizeMask = (1 << LogSize) - 1; p->pBins = ABC_CALLOC( Tab_Obj_t, p->SizeMask + 1 ); p->nBins = 1; p->pMan = pMan; return p; } static inline void Tab_ManFree( Tab_Man_t * p ) { ABC_FREE( p->pBins ); ABC_FREE( p ); } static inline void Tab_ManHashInsert( Tab_Man_t * p, int Value, int iCube, int iVar ) { Tab_Obj_t * pBin = Tab_ManBin( p, Value ); Tab_Obj_t * pCell = p->pBins + p->nBins; pCell->Cube = iCube; pCell->VarA = iVar; pCell->Next = pBin->Table; pBin->Table = p->nBins++; } static inline int Tab_ManHashLookup( Tab_Man_t * p, int Value, Vec_Int_t * vCube ) { Tab_Obj_t * pEnt, * pBin = Tab_ManBin( p, Value ); for ( pEnt = Tab_ManEntry(p, pBin->Table); pEnt; pEnt = Tab_ManEntry(p, pEnt->Next) ) if ( Vec_IntEqual( Vec_WecEntry(&p->pMan->vCubeLits, pEnt->Cube), vCube ) ) return 1; return 0; } static inline void Tab_ManHashCollect( Tab_Man_t * p, int iBin, Vec_Int_t * vEntries ) { Tab_Obj_t * pEnt, * pBin = Tab_ManBin( p, iBin ); Vec_IntClear( vEntries ); for ( pEnt = Tab_ManEntry(p, pBin->Table); pEnt; pEnt = Tab_ManEntry(p, pEnt->Next) ) Vec_IntPushTwo( vEntries, pEnt->Cube, pEnt->VarA ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pla_CubeHashValue( Vec_Int_t * vCube ) { int i, Lit, Value = 0; Vec_IntForEachEntry( vCube, Lit, i ) Value += Pla_HashValue(Lit); return Value; } void Pla_ManHashCubes( Pla_Man_t * p, Tab_Man_t * pTab ) { Vec_Int_t * vCube; int i, Value; Vec_IntClear( &p->vHashes ); Vec_IntGrow( &p->vHashes, Pla_ManCubeNum(p) ); Vec_WecForEachLevel( &p->vCubeLits, vCube, i ) { Value = Pla_CubeHashValue(vCube); Vec_IntPush( &p->vHashes, Value ); Tab_ManHashInsert( pTab, Value, i, PLA_LIT_UNUSED ); } } int Pla_ManHashDistance1( Pla_Man_t * p ) { Tab_Man_t * pTab; Vec_Int_t * vCube; Vec_Int_t * vCubeCopy = Vec_IntAlloc( p->nIns ); int nBits = Abc_Base2Log( Pla_ManCubeNum(p) ) + 2; int i, k, Lit, Value, ValueCopy, Count = 0; assert( nBits <= 26 ); pTab = Tab_ManAlloc( nBits, p ); Pla_ManConvertFromBits( p ); Pla_ManHashCubes( p, pTab ); Vec_WecForEachLevel( &p->vCubeLits, vCube, i ) { Vec_IntClear( vCubeCopy ); Vec_IntAppend( vCubeCopy, vCube ); Value = ValueCopy = Vec_IntEntry( &p->vHashes, i ); Vec_IntForEachEntry( vCubeCopy, Lit, k ) { // create new Value += Pla_HashValue(Abc_LitNot(Lit)) - Pla_HashValue(Lit); Vec_IntWriteEntry( vCubeCopy, k, Abc_LitNot(Lit) ); // check the cube Count += Tab_ManHashLookup( pTab, Value, vCubeCopy ); // create old Value -= Pla_HashValue(Abc_LitNot(Lit)) - Pla_HashValue(Lit); Vec_IntWriteEntry( vCubeCopy, k, Lit ); } assert( Value == ValueCopy ); } Vec_IntFree( vCubeCopy ); Tab_ManFree( pTab ); assert( !(Count & 1) ); return Count/2; } int Pla_ManHashDist1NumTest( Pla_Man_t * p ) { abctime clk = Abc_Clock(); int Count = Pla_ManHashDistance1( p ); printf( "Found %d pairs among %d cubes using cube hashing. ", Count, Pla_ManCubeNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pla_PrintCube( Vec_Int_t * vLits, int nVars, int iVar ) { int v, Lit; Vec_Str_t * vStr = Vec_StrStart( nVars + 1 ); Vec_StrFill( vStr, nVars, '-' ); Vec_IntForEachEntry( vLits, Lit, v ) Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit) ? '0' : '1') ); fprintf( stdout, "%s %d\n", Vec_StrArray(vStr), iVar ); Vec_StrFree( vStr ); } void Pla_ManHashCubes2( Pla_Man_t * p, Tab_Man_t * pTab ) { Vec_Int_t * vCube; int i, v, Lit, Value; Vec_WecForEachLevel( &p->vCubeLits, vCube, i ) { Value = Pla_CubeHashValue(vCube); Vec_IntForEachEntry( vCube, Lit, v ) { Value -= Pla_HashValue(Lit); Tab_ManHashInsert( pTab, Value, i, v ); Value += Pla_HashValue(Lit); } } } void Vec_IntCopySkip( Vec_Int_t * vCube, int iVar, Vec_Int_t * vRes ) { int i; Vec_IntClear( vRes ); for ( i = 0; i < Vec_IntSize(vCube); i++ ) if ( i != iVar ) Vec_IntPush( vRes, Vec_IntEntry(vCube, i) ); } Vec_Int_t * Pla_ManComputeDistance1Int( Pla_Man_t * p ) { Tab_Man_t * pTab; Vec_Int_t * vCube1, * vCube2; Vec_Int_t * vTemp1 = Vec_IntAlloc( 100 ); Vec_Int_t * vTemp2 = Vec_IntAlloc( 100 ); Vec_Int_t * vPairs = Vec_IntAlloc( 1000 ); Vec_Int_t * vCounts = Vec_IntStart( Vec_WecSize(&p->vCubeLits) ); Vec_Int_t * vEntries = Vec_IntAlloc( p->nIns ); int nBits = Abc_Base2Log( Vec_WecSizeSize(&p->vCubeLits) ) + 2; int v, i, k;//, Count = 0; int iCube1, iCube2, iVar1, iVar2; assert( nBits <= 26 ); pTab = Tab_ManAlloc( nBits, p ); //Pla_ManConvertFromBits( p ); Pla_ManHashCubes2( p, pTab ); // iterate through the hash bins for ( v = 0; v <= pTab->SizeMask; v++ ) { Tab_ManHashCollect( pTab, v, vEntries ); for ( i = 0; i < Vec_IntSize(vEntries)/2; i++ ) for ( k = i+1; k < Vec_IntSize(vEntries)/2; k++ ) { iCube1 = Vec_IntEntry(vEntries, 2*i); iCube2 = Vec_IntEntry(vEntries, 2*k); iVar1 = Vec_IntEntry(vEntries, 2*i+1); iVar2 = Vec_IntEntry(vEntries, 2*k+1); vCube1 = Vec_WecEntry(&p->vCubeLits, iCube1); vCube2 = Vec_WecEntry(&p->vCubeLits, iCube2); /* Pla_PrintCube( vCube1, p->nIns, iVar1 ); Pla_PrintCube( vCube2, p->nIns, iVar2 ); printf( "\n" ); */ if ( Vec_IntSize(vCube1) != Vec_IntSize(vCube2) ) continue; Vec_IntCopySkip( vCube1, iVar1, vTemp1 ); Vec_IntCopySkip( vCube2, iVar2, vTemp2 ); if ( !Vec_IntEqual( vTemp1, vTemp2 ) ) continue; printf( "%d %d ", iCube1, iCube2 ); Vec_IntPushTwo( vPairs, iCube1, iVar1 ); Vec_IntPushTwo( vPairs, iCube2, iVar2 ); Vec_IntAddToEntry( vCounts, iCube1, 1 ); Vec_IntAddToEntry( vCounts, iCube2, 1 ); } } Vec_IntPrint( vCounts ); Vec_IntFree( vCounts ); Vec_IntFree( vTemp1 ); Vec_IntFree( vTemp2 ); Vec_IntFree( vEntries ); Tab_ManFree( pTab ); return vPairs; } Vec_Int_t * Pla_ManComputeDistance1( Pla_Man_t * p ) { abctime clk = Abc_Clock(); Vec_Int_t * vPairs = Pla_ManComputeDistance1Int( p ); printf( "Found %d pairs among %d cubes using cube hashing. ", Vec_IntSize(vPairs)/4, Pla_ManCubeNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return vPairs; } void Pla_ManComputeDist1Test( Pla_Man_t * p ) { Vec_Int_t * vPairs; Pla_ManConvertFromBits( p ); vPairs = Pla_ManComputeDistance1( p ); Vec_IntFree( vPairs ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/plaMan.c000066400000000000000000000223701300674244400231020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [plaMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: plaMan.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Generates PLA description of a sorter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pla_GenSorter( int nVars ) { int i, k, Count, nMints = ( 1 << nVars ); char Buffer[20]; FILE * pFile; sprintf( Buffer, "sorter%02d.pla", nVars ); pFile = fopen( Buffer, "wb" ); fprintf( pFile, "# This file was generated by ABC on %s.\n", Extra_TimeStamp() ); fprintf( pFile, ".i %d\n", nVars ); fprintf( pFile, ".o %d\n", nVars ); fprintf( pFile, ".p %d\n", nMints-1 ); for ( i = 1; i < nMints; i++ ) { Count = 0; for ( k = nVars-1; k >= 0; k-- ) { Count += ((i >> k) & 1); fprintf( pFile, "%d", (i >> k) & 1 ); } fprintf( pFile, " " ); for ( k = 0; k < Count; k++ ) fprintf( pFile, "1" ); for ( ; k < nVars; k++ ) fprintf( pFile, "0" ); fprintf( pFile, "\n" ); } fprintf( pFile, ".end\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Generates prime detector for the given bit-widths.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Bit_t * Pla_ManPrimesTable( int nVars ) { int i, n, nBits = 1 << nVars; Vec_Bit_t * vMap = Vec_BitStartFull( Abc_MaxInt(64, nBits) ); for ( i = nBits; i < 64; i++ ) Vec_BitWriteEntry( vMap, i, 0 ); Vec_BitShrink( vMap, nBits ); Vec_BitWriteEntry( vMap, 0, 0 ); Vec_BitWriteEntry( vMap, 1, 0 ); for ( n = 2; n < nBits; n++ ) if ( Vec_BitEntry(vMap, n) ) for ( i = 2*n; i < nBits; i += n ) Vec_BitWriteEntry( vMap, i, 0 ); return vMap; } Vec_Int_t * Pla_GenPrimes( int nVars ) { int n, nBits = ( 1 << nVars ); Vec_Int_t * vPrimes = Vec_IntAlloc( 1000 ); Vec_Bit_t * vMap = Pla_ManPrimesTable( nVars ); for ( n = 2; n < nBits; n++ ) if ( Vec_BitEntry(vMap, n) ) Vec_IntPush( vPrimes, n ); printf( "Primes up to 2^%d = %d\n", nVars, Vec_IntSize(vPrimes) ); // Abc_GenCountHits1( vMap, vPrimes, nVars ); Vec_BitFree( vMap ); return vPrimes; } Pla_Man_t * Pla_GenFromMinterms( char * pName, Vec_Int_t * vMints, int nVars ) { Pla_Man_t * p = Pla_ManAlloc( pName, nVars, 1, Vec_IntSize(vMints) ); int i, k, Lit, Mint; word * pCube; Pla_ForEachCubeIn( p, pCube, i ) { Mint = Vec_IntEntry(vMints, i); Pla_CubeForEachLitIn( p, pCube, Lit, k ) Pla_CubeSetLit( pCube, k, ((Mint >> k) & 1) ? PLA_LIT_ONE : PLA_LIT_ZERO ); } Pla_ForEachCubeOut( p, pCube, i ) Pla_CubeSetLit( pCube, 0, PLA_LIT_ONE ); return p; } Pla_Man_t * Pla_ManPrimesDetector( int nVars ) { char pName[1000]; Pla_Man_t * p; Vec_Int_t * vMints = Pla_GenPrimes( nVars ); sprintf( pName, "primes%02d", nVars ); p = Pla_GenFromMinterms( pName, vMints, nVars ); Vec_IntFree( vMints ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Bit_t * Pla_GenRandom( int nVars, int nNums, int fNonZero ) { int Mint, Count = 0; Vec_Bit_t * vBits = Vec_BitStart( 1 << nVars ); assert( nVars > 0 && nVars <= 30 ); assert( nNums > 0 && nNums < (1 << (nVars - 1)) ); while ( Count < nNums ) { Mint = Gia_ManRandom(0) & ((1 << nVars) - 1); if ( fNonZero && Mint == 0 ) continue; if ( Vec_BitEntry(vBits, Mint) ) continue; Vec_BitWriteEntry( vBits, Mint, 1 ); Count++; } return vBits; } Pla_Man_t * Pla_ManGenerate( int nInputs, int nOutputs, int nCubes, int fVerbose ) { Pla_Man_t * p; Vec_Bit_t * vBits; int i, k, Count; word * pCube; char Buffer[1000]; sprintf( Buffer, "%s_%d_%d_%d", "rand", nInputs, nOutputs, nCubes ); p = Pla_ManAlloc( Buffer, nInputs, nOutputs, nCubes ); // generate nCube random input minterms vBits = Pla_GenRandom( nInputs, nCubes, 0 ); for ( i = Count = 0; i < Vec_BitSize(vBits); i++ ) if ( Vec_BitEntry(vBits, i) ) { pCube = Pla_CubeIn( p, Count++ ); for ( k = 0; k < nInputs; k++ ) Pla_CubeSetLit( pCube, k, ((i >> k) & 1) ? PLA_LIT_ONE : PLA_LIT_ZERO ); } assert( Count == nCubes ); Vec_BitFree( vBits ); // generate nCube random output minterms if ( nOutputs > 1 ) { vBits = Pla_GenRandom( nOutputs, nCubes, 1 ); for ( i = Count = 0; i < Vec_BitSize(vBits); i++ ) if ( Vec_BitEntry(vBits, i) ) { pCube = Pla_CubeOut( p, Count++ ); for ( k = 0; k < nOutputs; k++ ) Pla_CubeSetLit( pCube, k, ((i >> k) & 1) ? PLA_LIT_ONE : PLA_LIT_ZERO ); } assert( Count == nCubes ); Vec_BitFree( vBits ); } else { Pla_ForEachCubeOut( p, pCube, i ) Pla_CubeSetLit( pCube, 0, PLA_LIT_ONE ); } return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pla_ManConvertFromBits( Pla_Man_t * p ) { Vec_Int_t * vCube; word * pCube; int i, k, Lit, Count; Vec_WecClear( &p->vCubeLits ); Vec_WecClear( &p->vOccurs ); Vec_WecInit( &p->vCubeLits, Pla_ManCubeNum(p) ); Vec_WecInit( &p->vOccurs, 2*Pla_ManInNum(p) ); Pla_ForEachCubeIn( p, pCube, i ) { vCube = Vec_WecEntry( &p->vCubeLits, i ); Count = 0; Pla_CubeForEachLitIn( p, pCube, Lit, k ) if ( Lit != PLA_LIT_DASH ) Count++; Vec_IntGrow( vCube, Count ); Count = 0; Pla_CubeForEachLitIn( p, pCube, Lit, k ) if ( Lit != PLA_LIT_DASH ) { Lit = Abc_Var2Lit( k, Lit == PLA_LIT_ZERO ); Vec_WecPush( &p->vCubeLits, i, Lit ); // Vec_WecPush( &p->vOccurs, Lit, Pla_CubeHandle(i, Count++) ); Vec_WecPush( &p->vOccurs, Lit, i ); } assert( Vec_IntSize(vCube) == Vec_IntCap(vCube) ); } } void Pla_ManConvertToBits( Pla_Man_t * p ) { Vec_Int_t * vCube; int i, k, Lit; Vec_IntFillNatural( &p->vCubes, Vec_WecSize(&p->vCubeLits) ); Vec_WrdFill( &p->vInBits, Pla_ManCubeNum(p) * p->nInWords, 0 ); Vec_WecForEachLevel( &p->vCubeLits, vCube, i ) Vec_IntForEachEntry( vCube, Lit, k ) Pla_CubeSetLit( Pla_CubeIn(p, i), Abc_Lit2Var(Lit), Abc_LitIsCompl(Lit) ? PLA_LIT_ZERO : PLA_LIT_ONE ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pla_ManDist1Num( Pla_Man_t * p ) { word * pCube1, * pCube2; int i, k, Dist, Count = 0; Pla_ForEachCubeIn( p, pCube1, i ) Pla_ForEachCubeInStart( p, pCube2, k, i+1 ) { Dist = Pla_CubesAreDistance1( pCube1, pCube2, p->nInWords ); // Dist = Pla_CubesAreConsensus( pCube1, pCube2, p->nInWords, NULL ); Count += (Dist == 1); } return Count; } int Pla_ManDist1NumTest( Pla_Man_t * p ) { abctime clk = Abc_Clock(); int Count = Pla_ManDist1Num( p ); printf( "Found %d pairs among %d cubes using cube pair enumeration. ", Count, Pla_ManCubeNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/plaMerge.c000066400000000000000000000027731300674244400234330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [plaMerge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: plaMerge.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pla_ManDist1Merge( Pla_Man_t * p ) { return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/plaRead.c000066400000000000000000000167211300674244400232450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [plaRead.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: plaRead.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Pla_ReadFile( char * pFileName, char ** ppLimit ) { char * pBuffer; int nFileSize, RetValue; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file.\n" ); return NULL; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nFileSize + 16 ); pBuffer[0] = '\n'; RetValue = fread( pBuffer+1, nFileSize, 1, pFile ); fclose( pFile ); // terminate the string with '\0' pBuffer[nFileSize + 1] = '\n'; pBuffer[nFileSize + 2] = '\0'; *ppLimit = pBuffer + nFileSize + 3; return pBuffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pla_ReadPlaRemoveComments( char * pBuffer, char * pLimit ) { char * pTemp; for ( pTemp = pBuffer; pTemp < pLimit; pTemp++ ) if ( *pTemp == '#' ) while ( *pTemp && *pTemp != '\n' ) *pTemp++ = ' '; } int Pla_ReadPlaHeader( char * pBuffer, char * pLimit, int * pnIns, int * pnOuts, int * pnCubes, int * pType ) { char * pTemp; *pType = PLA_FILE_FD; *pnIns = *pnOuts = *pnCubes = -1; for ( pTemp = pBuffer; pTemp < pLimit; pTemp++ ) { if ( *pTemp != '.' ) continue; if ( !strncmp(pTemp, ".i ", 3) ) *pnIns = atoi( pTemp + 3 ); else if ( !strncmp(pTemp, ".o ", 3) ) *pnOuts = atoi( pTemp + 3 ); else if ( !strncmp(pTemp, ".p ", 3) ) *pnCubes = atoi( pTemp + 3 ); else if ( !strncmp(pTemp, ".e ", 3) ) break; else if ( !strncmp(pTemp, ".type ", 6) ) { char Buffer[100]; *pType = PLA_FILE_NONE; sscanf( pTemp+6, "%s", Buffer ); if ( !strcmp(Buffer, "f") ) *pType = PLA_FILE_F; else if ( !strcmp(Buffer, "fr") ) *pType = PLA_FILE_FR; else if ( !strcmp(Buffer, "fd") ) *pType = PLA_FILE_FD; else if ( !strcmp(Buffer, "fdr") ) *pType = PLA_FILE_FDR; } } if ( *pnIns <= 0 ) printf( "The number of inputs (.i) should be positive.\n" ); if ( *pnOuts <= 0 ) printf( "The number of outputs (.o) should be positive.\n" ); return *pnIns > 0 && *pnOuts > 0; } Vec_Str_t * Pla_ReadPlaBody( char * pBuffer, char * pLimit, Pla_File_t Type ) { char * pTemp; Vec_Str_t * vLits; vLits = Vec_StrAlloc( 10000 ); for ( pTemp = pBuffer; pTemp < pLimit; pTemp++ ) { if ( *pTemp == '.' ) while ( *pTemp && *pTemp != '\n' ) pTemp++; if ( *pTemp == '0' ) Vec_StrPush( vLits, (char)PLA_LIT_ZERO ); else if ( *pTemp == '1' ) Vec_StrPush( vLits, (char)PLA_LIT_ONE ); else if ( *pTemp == '-' || *pTemp == '2' ) Vec_StrPush( vLits, (char)PLA_LIT_DASH ); else if ( *pTemp == '~' ) // no meaning { if ( Type == PLA_FILE_F || Type == PLA_FILE_FD ) Vec_StrPush( vLits, (char)PLA_LIT_ZERO ); else if ( Type == PLA_FILE_FR ) Vec_StrPush( vLits, (char)PLA_LIT_DASH ); else if ( Type == PLA_FILE_FDR ) Vec_StrPush( vLits, (char)PLA_LIT_FULL ); else assert( 0 ); } } return vLits; } void Pla_ReadAddBody( Pla_Man_t * p, Vec_Str_t * vLits ) { word * pCubeIn, * pCubeOut; int i, k, Lit, Count = 0; int nCubesReal = Vec_StrSize(vLits) / (p->nIns + p->nOuts); assert( Vec_StrSize(vLits) % (p->nIns + p->nOuts) == 0 ); if ( nCubesReal != Pla_ManCubeNum(p) ) { printf( "Warning: Declared number of cubes (%d) differs from the actual (%d).\n", Pla_ManCubeNum(p), nCubesReal ); if ( nCubesReal < Pla_ManCubeNum(p) ) Vec_IntShrink( &p->vCubes, nCubesReal ); else { assert( nCubesReal > Pla_ManCubeNum(p) ); Vec_IntFillNatural( &p->vCubes, nCubesReal ); Vec_WrdFillExtra( &p->vInBits, nCubesReal * p->nInWords, 0 ); Vec_WrdFillExtra( &p->vOutBits, nCubesReal * p->nOutWords, 0 ); } } Pla_ForEachCubeInOut( p, pCubeIn, pCubeOut, i ) { Pla_CubeForEachLit( p->nIns, pCubeIn, Lit, k ) Pla_CubeSetLit( pCubeIn, k, (Pla_Lit_t)Vec_StrEntry(vLits, Count++) ); Pla_CubeForEachLit( p->nOuts, pCubeOut, Lit, k ) Pla_CubeSetLit( pCubeOut, k, (Pla_Lit_t)Vec_StrEntry(vLits, Count++) ); } assert( Count == Vec_StrSize(vLits) ); } Pla_Man_t * Pla_ReadPla( char * pFileName ) { Pla_Man_t * p; Vec_Str_t * vLits; int nIns, nOuts, nCubes, Type; char * pBuffer, * pLimit; pBuffer = Pla_ReadFile( pFileName, &pLimit ); if ( pBuffer == NULL ) return NULL; Pla_ReadPlaRemoveComments( pBuffer, pLimit ); if ( Pla_ReadPlaHeader( pBuffer, pLimit, &nIns, &nOuts, &nCubes, &Type ) ) { vLits = Pla_ReadPlaBody( pBuffer, pLimit, (Pla_File_t)Type ); if ( Vec_StrSize(vLits) % (nIns + nOuts) == 0 ) { if ( nCubes == -1 ) nCubes = Vec_StrSize(vLits) / (nIns + nOuts); p = Pla_ManAlloc( pFileName, nIns, nOuts, nCubes ); p->Type = (Pla_File_t)Type; Pla_ReadAddBody( p, vLits ); Vec_StrFree( vLits ); ABC_FREE( pBuffer ); return p; } printf( "Literal count is incorrect (in = %d; out = %d; lit = %d).\n", nIns, nOuts, Vec_StrSize(vLits) ); Vec_StrFree( vLits ); } ABC_FREE( pBuffer ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/plaSimple.c000066400000000000000000000267741300674244400236340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [plaSimple.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: plaSimple.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Dump PLA manager into a BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pla_ManDumpPla( Pla_Man_t * p, char * pFileName ) { // find the number of original variables //int nVarsInit = Pla_ManDivNum(p) ? Vec_IntCountZero(&p->vDivs) : Pla_ManInNum(p); FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { //char * pLits = "-01?"; Vec_Str_t * vStr; Vec_Int_t * vCube; int i, k, Lit; // comment fprintf( pFile, "# PLA file written via PLA package in ABC on " ); fprintf( pFile, "%s", Extra_TimeStamp() ); fprintf( pFile, "\n\n" ); // header fprintf( pFile, ".i %d\n", Pla_ManInNum(p) ); fprintf( pFile, ".o %d\n", 1 ); fprintf( pFile, ".p %d\n", Vec_WecSize(&p->vCubeLits) ); // SOP vStr = Vec_StrStart( Pla_ManInNum(p) + 1 ); Vec_WecForEachLevel( &p->vCubeLits, vCube, i ) { if ( !Vec_IntSize(vCube) ) continue; for ( k = 0; k < Pla_ManInNum(p); k++ ) Vec_StrWriteEntry( vStr, k, '-' ); Vec_IntForEachEntry( vCube, Lit, k ) Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit) ? '0' : '1') ); fprintf( pFile, "%s 1\n", Vec_StrArray(vStr) ); } Vec_StrFree( vStr ); fprintf( pFile, ".e\n\n" ); fclose( pFile ); printf( "Written file \"%s\".\n", pFileName ); } } void Pla_ManDumpBlif( Pla_Man_t * p, char * pFileName ) { // find the number of original variables int nVarsInit = Pla_ManDivNum(p) ? Vec_IntCountZero(&p->vDivs) : Pla_ManInNum(p); FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { //char * pLits = "-01?"; Vec_Str_t * vStr; Vec_Int_t * vCube; int i, k, Lit, Div; // comment fprintf( pFile, "# BLIF file written via PLA package in ABC on " ); fprintf( pFile, "%s", Extra_TimeStamp() ); fprintf( pFile, "\n\n" ); // header fprintf( pFile, ".model %s\n", Pla_ManName(p) ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nVarsInit; i++ ) fprintf( pFile, " i%d", i ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs o" ); fprintf( pFile, "\n" ); // SOP fprintf( pFile, ".names" ); for ( i = 0; i < Pla_ManInNum(p); i++ ) fprintf( pFile, " i%d", i ); fprintf( pFile, " o\n" ); vStr = Vec_StrStart( Pla_ManInNum(p) + 1 ); Vec_WecForEachLevel( &p->vCubeLits, vCube, i ) { for ( k = 0; k < Pla_ManInNum(p); k++ ) Vec_StrWriteEntry( vStr, k, '-' ); Vec_IntForEachEntry( vCube, Lit, k ) Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit) ? '0' : '1') ); fprintf( pFile, "%s 1\n", Vec_StrArray(vStr) ); } Vec_StrFree( vStr ); // divisors Vec_IntForEachEntryStart( &p->vDivs, Div, i, nVarsInit ) { int pLits[3] = { (Div >> 2) & 0x3FF, (Div >> 12) & 0x3FF, (Div >> 22) & 0x3FF }; fprintf( pFile, ".names" ); fprintf( pFile, " i%d", Abc_Lit2Var(pLits[0]) ); fprintf( pFile, " i%d", Abc_Lit2Var(pLits[1]) ); if ( (Div & 3) == 3 ) // MUX fprintf( pFile, " i%d", Abc_Lit2Var(pLits[2]) ); fprintf( pFile, " i%d\n", i ); if ( (Div & 3) == 1 ) // AND fprintf( pFile, "%d%d 1\n", !Abc_LitIsCompl(pLits[0]), !Abc_LitIsCompl(pLits[1]) ); else if ( (Div & 3) == 2 ) // XOR { assert( !Abc_LitIsCompl(pLits[0]) ); assert( !Abc_LitIsCompl(pLits[1]) ); fprintf( pFile, "10 1\n01 1\n" ); } else if ( (Div & 3) == 3 ) // MUX { assert( !Abc_LitIsCompl(pLits[1]) ); assert( !Abc_LitIsCompl(pLits[2]) ); fprintf( pFile, "%d-0 1\n-11 1\n", !Abc_LitIsCompl(pLits[0]) ); } else assert( 0 ); } fprintf( pFile, ".end\n\n" ); fclose( pFile ); printf( "Written file \"%s\".\n", pFileName ); } } /**Function************************************************************* Synopsis [Transforms truth table into an SOP manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pla_ManExpendDirNum( word * pOn, int nBits, int iMint, int * pVars ) { int v, nVars = 0; for ( v = 0; v < nBits; v++ ) if ( Pla_TtGetBit(pOn, iMint ^ (1 << v)) ) pVars[nVars++] = v; return nVars; } void Pla_PrintBinary( word * pT, int nBits ) { int v; for ( v = 0; v < nBits; v++ ) printf( "%d", Pla_TtGetBit(pT, v) ); printf( "\n" ); } Vec_Wrd_t * Pla_ManFxMinimize( word * pOn, int nVars ) { int i, v, iMint, iVar, nMints = (1 << nVars); int nWords = Abc_Bit6WordNum( nMints ); Vec_Wrd_t * vCubes = Vec_WrdAlloc( 1000 ); word * pDc = ABC_CALLOC( word, nWords ); int Count[32] = {0}; int Cubes[32] = {0}; Vec_Int_t * vStore = Vec_IntAlloc( 1000 ); // count the number of expansion directions for ( i = 0; i < nMints; i++ ) if ( Pla_TtGetBit(pOn, i) && !Pla_TtGetBit(pDc, i) ) { int pDirs[32], nDirs = Pla_ManExpendDirNum(pOn, nVars, i, pDirs); Count[nDirs]++; if ( nDirs == 0 ) { Pla_TtSetBit(pDc, i); Cubes[0]++; // save Vec_IntPushTwo( vStore, i, -1 ); continue; } if ( nDirs == 1 ) { //Pla_PrintBinary( (word *)&i, nVars ); //printf( " %d \n", pDirs[0] ); Pla_TtSetBit(pDc, i); Pla_TtSetBit(pDc, i ^ (1 << pDirs[0])); Cubes[1]++; // save Vec_IntPushTwo( vStore, i, pDirs[0] ); continue; } if ( nDirs == 2 && Pla_TtGetBit(pOn, i ^ (1 << pDirs[0]) ^ (1 << pDirs[1])) ) { assert( 0 ); Pla_TtSetBit(pDc, i); Pla_TtSetBit(pDc, i ^ (1 << pDirs[0])); Pla_TtSetBit(pDc, i ^ (1 << pDirs[1])); Pla_TtSetBit(pDc, i ^ (1 << pDirs[0]) ^ (1 << pDirs[1])); Cubes[2]++; continue; } } // go through the remaining cubes for ( i = 0; i < nMints; i++ ) if ( Pla_TtGetBit(pOn, i) && !Pla_TtGetBit(pDc, i) ) { int pDirs[32], nDirs = Pla_ManExpendDirNum(pOn, nVars, i, pDirs); // find direction, which is not taken for ( v = 0; v < nDirs; v++ ) if ( Pla_TtGetBit(pOn, i ^ (1 << pDirs[v])) && !Pla_TtGetBit(pDc, i ^ (1 << pDirs[v])) ) break; // if there is no open directions, use any one if ( v == nDirs ) v = 0; // mark this one Pla_TtSetBit(pDc, i); Pla_TtSetBit(pDc, i ^ (1 << pDirs[v])); Cubes[10]++; // save Vec_IntPushTwo( vStore, i, pDirs[v] ); continue; } printf( "\n" ); printf( "Truth = %d. ", Pla_TtCountOnes(pOn, nWords) ); printf( "Cover = %d. ", Pla_TtCountOnes(pDc, nWords) ); printf( "\n" ); printf( "Count: " ); for ( i = 0; i < 16; i++ ) if ( Count[i] ) printf( "%d=%d ", i, Count[i] ); printf( "\n" ); printf( "Cubes: " ); for ( i = 0; i < 16; i++ ) if ( Cubes[i] ) printf( "%d=%d ", i, Cubes[i] ); printf( "\n" ); /* // extract cubes one at a time for ( i = 0; i < nMints; i++ ) if ( Pla_TtGetBit(pOn, i) ) { word Cube = 0; for ( v = 0; v < nVars; v++ ) if ( (i >> v) & 1 ) Pla_CubeSetLit( &Cube, v, PLA_LIT_ONE ); else Pla_CubeSetLit( &Cube, v, PLA_LIT_ZERO ); Vec_WrdPush( vCubes, Cube ); } */ Vec_IntForEachEntryDouble( vStore, iMint, iVar, i ) { word Cube = 0; for ( v = 0; v < nVars; v++ ) { if ( v == iVar ) continue; if ( (iMint >> v) & 1 ) Pla_CubeSetLit( &Cube, v, PLA_LIT_ONE ); else Pla_CubeSetLit( &Cube, v, PLA_LIT_ZERO ); } Vec_WrdPush( vCubes, Cube ); } Vec_IntFree( vStore ); // collect the minterms ABC_FREE( pDc ); return vCubes; } Pla_Man_t * Pla_ManFxPrepare( int nVars ) { Pla_Man_t * p; char Buffer[1000]; Vec_Bit_t * vFunc = Pla_ManPrimesTable( nVars ); Vec_Wrd_t * vSop = Pla_ManFxMinimize( (word *)Vec_BitArray(vFunc), nVars ); word Cube, * pCube = &Cube; int i, k, Lit; sprintf( Buffer, "primes%02d", nVars ); p = Pla_ManAlloc( Buffer, nVars, 1, Vec_WrdSize(vSop) ); Vec_WecInit( &p->vCubeLits, Pla_ManCubeNum(p) ); Vec_WecInit( &p->vOccurs, 2*Pla_ManInNum(p) ); Vec_WrdForEachEntry( vSop, Cube, i ) Pla_CubeForEachLit( nVars, pCube, Lit, k ) if ( Lit != PLA_LIT_DASH ) { Lit = Abc_Var2Lit( k, Lit == PLA_LIT_ZERO ); Vec_WecPush( &p->vCubeLits, i, Lit ); Vec_WecPush( &p->vOccurs, Lit, i ); } Vec_BitFree( vFunc ); Vec_WrdFree( vSop ); return p; } int Pla_ManFxPerformSimple( int nVars ) { char Buffer[100]; Pla_Man_t * p = Pla_ManFxPrepare( nVars ); sprintf( Buffer, "primesmin%02d.pla", nVars ); Pla_ManDumpPla( p, Buffer ); Pla_ManFree( p ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/pla/plaWrite.c000066400000000000000000000067451300674244400234710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [plaWrite.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SOP manager.] Synopsis [Scalable SOP transformations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - March 18, 2015.] Revision [$Id: plaWrite.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pla.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Pla_WritePlaInt( Pla_Man_t * p ) { Vec_Str_t * vOut = Vec_StrAlloc( 10000 ); char * pLits = "-01?"; word * pCubeIn, * pCubeOut; int i, k, Lit; // write comments Vec_StrPrintStr( vOut, "# SOP \"" ); Vec_StrPrintStr( vOut, Pla_ManName(p) ); Vec_StrPrintStr( vOut, "\" written via PLA package in ABC on " ); Vec_StrPrintStr( vOut, Extra_TimeStamp() ); Vec_StrPrintStr( vOut, "\n\n" ); // write header if ( p->Type != PLA_FILE_FD ) { if ( p->Type == PLA_FILE_F ) Vec_StrPrintStr( vOut, ".type f\n" ); else if ( p->Type == PLA_FILE_FR ) Vec_StrPrintStr( vOut, ".type fr\n" ); else if ( p->Type == PLA_FILE_FDR ) Vec_StrPrintStr( vOut, ".type fdr\n" ); else if ( p->Type == PLA_FILE_NONE ) Vec_StrPrintStr( vOut, ".type ???\n" ); } Vec_StrPrintStr( vOut, ".i " ); Vec_StrPrintNum( vOut, p->nIns ); Vec_StrPrintStr( vOut, "\n.o " ); Vec_StrPrintNum( vOut, p->nOuts ); Vec_StrPrintStr( vOut, "\n.p " ); Vec_StrPrintNum( vOut, Pla_ManCubeNum(p) ); Vec_StrPrintStr( vOut, "\n" ); // write cube Pla_ForEachCubeInOut( p, pCubeIn, pCubeOut, i ) { Pla_CubeForEachLit( p->nIns, pCubeIn, Lit, k ) Vec_StrPush( vOut, pLits[Lit] ); Vec_StrPush( vOut, ' ' ); Pla_CubeForEachLit( p->nOuts, pCubeOut, Lit, k ) Vec_StrPush( vOut, pLits[Lit] ); Vec_StrPush( vOut, '\n' ); } Vec_StrPrintStr( vOut, ".e\n\n\0" ); return vOut; } void Pla_WritePla( Pla_Man_t * p, char * pFileName ) { Vec_Str_t * vOut = Pla_WritePlaInt( p ); if ( Vec_StrSize(vOut) > 0 ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); fclose( pFile ); } } Vec_StrFreeP( &vOut ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/test/000077500000000000000000000000001300674244400217255ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/test/module.make000066400000000000000000000000341300674244400240460ustar00rootroot00000000000000SRC += src/base/test/test.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/test/test.c000066400000000000000000000033131300674244400230500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [test.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Template package.] Synopsis [] Author [] Affiliation [] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: test.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Test_Init( Abc_Frame_t * pAbc ) { } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Test_End( Abc_Frame_t * pAbc ) { } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/000077500000000000000000000000001300674244400215425ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/module.make000066400000000000000000000001631300674244400236660ustar00rootroot00000000000000SRC += src/base/ver/verCore.c \ src/base/ver/verFormula.c \ src/base/ver/verParse.c \ src/base/ver/verStream.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/ver.h000066400000000000000000000112441300674244400225110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ver.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 19, 2006.] Revision [$Id: ver.h,v 1.00 2006/08/19 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__ver__ver_h #define ABC__base__ver__ver_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "base/abc/abc.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Ver_Man_t_ Ver_Man_t; typedef struct Ver_Stream_t_ Ver_Stream_t; struct Ver_Man_t_ { // internal parameters int fMapped; // mapped verilog int fUseMemMan; // allocate memory manager in the networks int fCheck; // checks network for currectness // input file stream char * pFileName; Ver_Stream_t * pReader; int fNameLast; ProgressBar * pProgress; // current design Abc_Des_t * pDesign; st__table * tName2Suffix; // error handling FILE * Output; int fTopLevel; int fError; char sError[2000]; // intermediate structures Vec_Ptr_t * vNames; Vec_Ptr_t * vStackFn; Vec_Int_t * vStackOp; Vec_Int_t * vPerm; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== verCore.c ========================================================*/ extern Abc_Des_t * Ver_ParseFile( char * pFileName, Abc_Des_t * pGateLib, int fCheck, int fUseMemMan ); extern void Ver_ParsePrintErrorMessage( Ver_Man_t * p ); /*=== verFormula.c ========================================================*/ extern void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ); extern void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ); /*=== verParse.c ========================================================*/ extern int Ver_ParseSkipComments( Ver_Man_t * p ); extern char * Ver_ParseGetName( Ver_Man_t * p ); /*=== verStream.c ========================================================*/ extern Ver_Stream_t * Ver_StreamAlloc( char * pFileName ); extern void Ver_StreamFree( Ver_Stream_t * p ); extern char * Ver_StreamGetFileName( Ver_Stream_t * p ); extern int Ver_StreamGetFileSize( Ver_Stream_t * p ); extern int Ver_StreamGetCurPosition( Ver_Stream_t * p ); extern int Ver_StreamGetLineNumber( Ver_Stream_t * p ); extern int Ver_StreamIsOkey( Ver_Stream_t * p ); extern char Ver_StreamScanChar( Ver_Stream_t * p ); extern char Ver_StreamPopChar( Ver_Stream_t * p ); extern void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ); extern void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ); extern char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/verCore.c000066400000000000000000003162411300674244400233220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [verCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Parses several flavors of structural Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 19, 2006.] Revision [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ver.h" #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // types of verilog signals typedef enum { VER_SIG_NONE = 0, VER_SIG_INPUT, VER_SIG_OUTPUT, VER_SIG_INOUT, VER_SIG_REG, VER_SIG_WIRE } Ver_SignalType_t; // types of verilog gates typedef enum { VER_GATE_AND = 0, VER_GATE_OR, VER_GATE_XOR, VER_GATE_BUF, VER_GATE_NAND, VER_GATE_NOR, VER_GATE_XNOR, VER_GATE_NOT } Ver_GateType_t; static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Des_t * pGateLib ); static void Ver_ParseStop( Ver_Man_t * p ); static void Ver_ParseFreeData( Ver_Man_t * p ); static void Ver_ParseInternal( Ver_Man_t * p ); static int Ver_ParseModule( Ver_Man_t * p ); static int Ver_ParseSignal( Ver_Man_t * p, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType ); static int Ver_ParseAlways( Ver_Man_t * p, Abc_Ntk_t * pNtk ); static int Ver_ParseInitial( Ver_Man_t * p, Abc_Ntk_t * pNtk ); static int Ver_ParseAssign( Ver_Man_t * p, Abc_Ntk_t * pNtk ); static int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType ); static int Ver_ParseFlopStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ); static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate ); static int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox ); static int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox ); static int Ver_ParseAttachBoxes( Ver_Man_t * pMan ); static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ); static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ); static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO ); static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); static void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan ); static inline int Ver_NtkIsDefined( Abc_Ntk_t * pNtkBox ) { assert( pNtkBox->pName ); return Abc_NtkPiNum(pNtkBox) || Abc_NtkPoNum(pNtkBox); } static inline int Ver_ObjIsConnected( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBox(pObj) ); return Abc_ObjFaninNum(pObj) || Abc_ObjFanoutNum(pObj); } int glo_fMapped = 0; // this is bad! typedef struct Ver_Bundle_t_ Ver_Bundle_t; struct Ver_Bundle_t_ { char * pNameFormal; // the name of the formal net Vec_Ptr_t * vNetsActual; // the vector of actual nets (MSB to LSB) }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Start parser.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Des_t * pGateLib ) { Ver_Man_t * p; p = ABC_ALLOC( Ver_Man_t, 1 ); memset( p, 0, sizeof(Ver_Man_t) ); p->pFileName = pFileName; p->pReader = Ver_StreamAlloc( pFileName ); if ( p->pReader == NULL ) { ABC_FREE( p ); return NULL; } p->Output = stdout; p->vNames = Vec_PtrAlloc( 100 ); p->vStackFn = Vec_PtrAlloc( 100 ); p->vStackOp = Vec_IntAlloc( 100 ); p->vPerm = Vec_IntAlloc( 100 ); // create the design library and assign the technology library p->pDesign = Abc_DesCreate( pFileName ); p->pDesign->pLibrary = pGateLib; // derive library from SCL // if ( Abc_FrameReadLibScl() ) // Abc_SclInstallGenlib( Abc_FrameReadLibScl(), 0, 0, 0 ); p->pDesign->pGenlib = Abc_FrameReadLibGen(); return p; } /**Function************************************************************* Synopsis [Stop parser.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_ParseStop( Ver_Man_t * p ) { if ( p->pProgress ) Extra_ProgressBarStop( p->pProgress ); Ver_StreamFree( p->pReader ); Vec_PtrFree( p->vNames ); Vec_PtrFree( p->vStackFn ); Vec_IntFree( p->vStackOp ); Vec_IntFree( p->vPerm ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [File parser.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Des_t * Ver_ParseFile( char * pFileName, Abc_Des_t * pGateLib, int fCheck, int fUseMemMan ) { Ver_Man_t * p; Abc_Des_t * pDesign; // start the parser p = Ver_ParseStart( pFileName, pGateLib ); p->fMapped = glo_fMapped; p->fCheck = fCheck; p->fUseMemMan = fUseMemMan; if ( glo_fMapped ) { Hop_ManStop((Hop_Man_t *)p->pDesign->pManFunc); p->pDesign->pManFunc = NULL; } // parse the file Ver_ParseInternal( p ); // save the result pDesign = p->pDesign; p->pDesign = NULL; // stop the parser Ver_ParseStop( p ); return pDesign; } /**Function************************************************************* Synopsis [File parser.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_ParseInternal( Ver_Man_t * pMan ) { Abc_Ntk_t * pNtk; char * pToken; int i; // preparse the modeles pMan->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(pMan->pReader) ); while ( 1 ) { // get the next token pToken = Ver_ParseGetName( pMan ); if ( pToken == NULL ) break; if ( strcmp( pToken, "module" ) ) { sprintf( pMan->sError, "Cannot read \"module\" directive." ); Ver_ParsePrintErrorMessage( pMan ); return; } // parse the module if ( !Ver_ParseModule(pMan) ) return; } Extra_ProgressBarStop( pMan->pProgress ); pMan->pProgress = NULL; // process defined and undefined boxes if ( !Ver_ParseAttachBoxes( pMan ) ) return; // connect the boxes and check Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) { // fix the dangling nets Abc_NtkFinalizeRead( pNtk ); // check the network for correctness if ( pMan->fCheck && !Abc_NtkCheckRead( pNtk ) ) { pMan->fTopLevel = 1; sprintf( pMan->sError, "The network check has failed for network %s.", pNtk->pName ); Ver_ParsePrintErrorMessage( pMan ); return; } } } /**Function************************************************************* Synopsis [File parser.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_ParseFreeData( Ver_Man_t * p ) { if ( p->pDesign ) { Abc_DesFree( p->pDesign, NULL ); p->pDesign = NULL; } } /**Function************************************************************* Synopsis [Prints the error message including the file name and line number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_ParsePrintErrorMessage( Ver_Man_t * p ) { p->fError = 1; if ( p->fTopLevel ) // the line number is not given fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); else // print the error message with the line number fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError ); // free the data Ver_ParseFreeData( p ); } /**Function************************************************************* Synopsis [Finds the network by name or create a new blackbox network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Ver_ParseFindOrCreateNetwork( Ver_Man_t * pMan, char * pName ) { Abc_Ntk_t * pNtkNew; // check if the network exists if ( (pNtkNew = Abc_DesFindModelByName( pMan->pDesign, pName )) ) return pNtkNew; //printf( "Creating network %s.\n", pName ); // create new network pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan ); pNtkNew->pName = Extra_UtilStrsav( pName ); pNtkNew->pSpec = NULL; // add module to the design Abc_DesAddModel( pMan->pDesign, pNtkNew ); return pNtkNew; } /**Function************************************************************* Synopsis [Finds the network by name or create a new blackbox network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Ver_ParseFindNet( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pObj; if ( (pObj = Abc_NtkFindNet(pNtk, pName)) ) return pObj; if ( !strcmp( pName, "1\'b0" ) || !strcmp( pName, "1\'bx" ) ) return Abc_NtkFindOrCreateNet( pNtk, "1\'b0" ); if ( !strcmp( pName, "1\'b1" ) ) return Abc_NtkFindOrCreateNet( pNtk, "1\'b1" ); return NULL; } /**Function************************************************************* Synopsis [Converts the network from the blackbox type into a different one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseConvertNetwork( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, int fMapped ) { if ( fMapped ) { // convert from the blackbox into the network with local functions representated by AIGs if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) { // change network type assert( pNtk->pManFunc == NULL ); pNtk->ntkFunc = ABC_FUNC_MAP; pNtk->pManFunc = pMan->pDesign->pGenlib; } else if ( pNtk->ntkFunc != ABC_FUNC_MAP ) { sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } else { // convert from the blackbox into the network with local functions representated by AIGs if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) { // change network type assert( pNtk->pManFunc == NULL ); pNtk->ntkFunc = ABC_FUNC_AIG; pNtk->pManFunc = pMan->pDesign->pManFunc; } else if ( pNtk->ntkFunc != ABC_FUNC_AIG ) { sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } return 1; } /**Function************************************************************* Synopsis [Parses one Verilog module.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseModule( Ver_Man_t * pMan ) { Mio_Gate_t * pGate; Ver_Stream_t * p = pMan->pReader; Abc_Ntk_t * pNtk, * pNtkTemp; char * pWord, Symbol; int RetValue; // get the network name pWord = Ver_ParseGetName( pMan ); // get the network with this name pNtk = Ver_ParseFindOrCreateNetwork( pMan, pWord ); // make sure we stopped at the opening parenthesis if ( Ver_StreamPopChar(p) != '(' ) { sprintf( pMan->sError, "Cannot find \"(\" after \"module\" in network %s.", pNtk->pName ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // skip to the end of parentheses do { if ( Ver_ParseGetName( pMan ) == NULL ) return 0; Symbol = Ver_StreamPopChar(p); } while ( Symbol == ',' ); assert( Symbol == ')' ); if ( !Ver_ParseSkipComments( pMan ) ) return 0; Symbol = Ver_StreamPopChar(p); if ( Symbol != ';' ) { sprintf( pMan->sError, "Expected closing parenthesis after \"module\"." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // parse the inputs/outputs/registers/wires/inouts while ( 1 ) { Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; if ( !strcmp( pWord, "input" ) ) RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INPUT ); else if ( !strcmp( pWord, "output" ) ) RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_OUTPUT ); else if ( !strcmp( pWord, "reg" ) ) RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_REG ); else if ( !strcmp( pWord, "wire" ) ) RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_WIRE ); else if ( !strcmp( pWord, "inout" ) ) RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INOUT ); else break; if ( RetValue == 0 ) return 0; } // parse the remaining statements while ( 1 ) { Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); if ( !strcmp( pWord, "and" ) ) RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_AND ); else if ( !strcmp( pWord, "or" ) ) RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_OR ); else if ( !strcmp( pWord, "xor" ) ) RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XOR ); else if ( !strcmp( pWord, "buf" ) ) RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_BUF ); else if ( !strcmp( pWord, "nand" ) ) RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NAND ); else if ( !strcmp( pWord, "nor" ) ) RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOR ); else if ( !strcmp( pWord, "xnor" ) ) RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XNOR ); else if ( !strcmp( pWord, "not" ) ) RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOT ); else if ( !strcmp( pWord, "dff" ) ) RetValue = Ver_ParseFlopStandard( pMan, pNtk ); else if ( !strcmp( pWord, "assign" ) ) RetValue = Ver_ParseAssign( pMan, pNtk ); else if ( !strcmp( pWord, "always" ) ) RetValue = Ver_ParseAlways( pMan, pNtk ); else if ( !strcmp( pWord, "initial" ) ) RetValue = Ver_ParseInitial( pMan, pNtk ); else if ( !strcmp( pWord, "endmodule" ) ) break; else if ( pMan->pDesign->pGenlib && (pGate = Mio_LibraryReadGateByName((Mio_Library_t *)pMan->pDesign->pGenlib, pWord, NULL)) ) // current design RetValue = Ver_ParseGate( pMan, pNtk, pGate ); // else if ( pMan->pDesign->pLibrary && st__lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library // RetValue = Ver_ParseGate( pMan, pNtkTemp ); else if ( !strcmp( pWord, "wire" ) ) RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_WIRE ); else // assume this is the box used in the current design { pNtkTemp = Ver_ParseFindOrCreateNetwork( pMan, pWord ); RetValue = Ver_ParseBox( pMan, pNtk, pNtkTemp ); } if ( RetValue == 0 ) return 0; // skip the comments if ( !Ver_ParseSkipComments( pMan ) ) return 0; // get new word pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; } // convert from the blackbox into the network with local functions representated by AIGs if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) { if ( Abc_NtkNodeNum(pNtk) > 0 || Abc_NtkBoxNum(pNtk) > 0 ) { if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) return 0; } else { Abc_Obj_t * pObj, * pBox, * pTerm; int i; 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 ); } } } // remove the table if needed Ver_ParseRemoveSuffixTable( pMan ); return 1; } /**Function************************************************************* Synopsis [Lookups the suffix of the signal of the form [m:n].] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseLookupSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb ) { unsigned Value; *pnMsb = *pnLsb = -1; if ( pMan->tName2Suffix == NULL ) return 1; if ( ! st__lookup( pMan->tName2Suffix, (char *)pWord, (char **)&Value ) ) return 1; *pnMsb = (Value >> 8) & 0xff; *pnLsb = Value & 0xff; return 1; } /**Function************************************************************* Synopsis [Lookups the suffix of the signal of the form [m:n].] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseInsertsSuffix( Ver_Man_t * pMan, char * pWord, int nMsb, int nLsb ) { unsigned Value; if ( pMan->tName2Suffix == NULL ) pMan->tName2Suffix = st__init_table( strcmp, st__strhash ); if ( st__is_member( pMan->tName2Suffix, pWord ) ) return 1; assert( nMsb >= 0 && nMsb < 128 ); assert( nLsb >= 0 && nLsb < 128 ); Value = (nMsb << 8) | nLsb; st__insert( pMan->tName2Suffix, Extra_UtilStrsav(pWord), (char *)(ABC_PTRUINT_T)Value ); return 1; } /**Function************************************************************* Synopsis [Lookups the suffic of the signal of the form [m:n].] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan ) { st__generator * gen; char * pKey, * pValue; if ( pMan->tName2Suffix == NULL ) return; st__foreach_item( pMan->tName2Suffix, gen, (const char **)&pKey, (char **)&pValue ) ABC_FREE( pKey ); st__free_table( pMan->tName2Suffix ); pMan->tName2Suffix = NULL; } /**Function************************************************************* Synopsis [Determine signal prefix of the form [Beg:End].] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseSignalPrefix( Ver_Man_t * pMan, char ** ppWord, int * pnMsb, int * pnLsb ) { char * pWord = *ppWord, * pTemp; int nMsb, nLsb; assert( pWord[0] == '[' ); // get the beginning nMsb = atoi( pWord + 1 ); // find the splitter while ( *pWord && *pWord != ':' && *pWord != ']' ) pWord++; if ( *pWord == 0 ) { sprintf( pMan->sError, "Cannot find closing bracket in this line." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } if ( *pWord == ']' ) nLsb = nMsb; else { assert( *pWord == ':' ); nLsb = atoi( pWord + 1 ); // find the closing parenthesis while ( *pWord && *pWord != ']' ) pWord++; if ( *pWord == 0 ) { sprintf( pMan->sError, "Cannot find closing bracket in this line." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } assert( *pWord == ']' ); pWord++; // fix the case when \ follows after [] without space if ( *pWord == '\\' ) { pWord++; pTemp = pWord; while ( *pTemp && *pTemp != ' ' ) pTemp++; if ( *pTemp == ' ' ) *pTemp = 0; } } assert( nMsb >= 0 && nLsb >= 0 ); // return *ppWord = pWord; *pnMsb = nMsb; *pnLsb = nLsb; return 1; } /**Function************************************************************* Synopsis [Determine signal suffix of the form [m:n].] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseSignalSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb ) { char * pCur; int Length; Length = strlen(pWord); assert( pWord[Length-1] == ']' ); // walk backward for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- ) if ( *pCur == ':' || *pCur == '[' ) break; if ( pCur == pWord ) { sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } if ( *pCur == '[' ) { *pnMsb = *pnLsb = atoi(pCur+1); *pCur = 0; return 1; } assert( *pCur == ':' ); // get the end of the interval *pnLsb = atoi(pCur+1); // find the beginning for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- ) if ( *pCur == '[' ) break; if ( pCur == pWord ) { sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } assert( *pCur == '[' ); // get the beginning of the interval *pnMsb = atoi(pCur+1); // cut the word *pCur = 0; return 1; } /**Function************************************************************* Synopsis [Returns the values of constant bits.] Description [The resulting bits are in MSB to LSB order.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseConstant( Ver_Man_t * pMan, char * pWord ) { int nBits, i; assert( pWord[0] >= '1' && pWord[1] <= '9' ); nBits = atoi(pWord); // find the next symbol \' while ( *pWord && *pWord != '\'' ) pWord++; if ( *pWord == 0 ) { sprintf( pMan->sError, "Cannot find symbol \' in the constant." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } assert( *pWord == '\'' ); pWord++; if ( *pWord != 'b' ) { sprintf( pMan->sError, "Currently can only handle binary constants." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } pWord++; // scan the bits Vec_PtrClear( pMan->vNames ); for ( i = 0; i < nBits; i++ ) { if ( pWord[i] != '0' && pWord[i] != '1' && pWord[i] != 'x' ) { sprintf( pMan->sError, "Having problem parsing the binary constant." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } if ( pWord[i] == 'x' ) Vec_PtrPush( pMan->vNames, (void *)0 ); else Vec_PtrPush( pMan->vNames, (void *)(ABC_PTRUINT_T)(pWord[i]-'0') ); } return 1; } /**Function************************************************************* Synopsis [Parses one directive.] Description [The signals are added in the order from LSB to MSB.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType ) { Ver_Stream_t * p = pMan->pReader; char Buffer[1000], Symbol, * pWord; int nMsb, nLsb, Bit, Limit, i; nMsb = nLsb = -1; while ( 1 ) { // get the next word pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; if ( !strcmp(pWord, "wire") ) continue; // check if the range is specified if ( pWord[0] == '[' && !pMan->fNameLast ) { assert( nMsb == -1 && nLsb == -1 ); Ver_ParseSignalPrefix( pMan, &pWord, &nMsb, &nLsb ); // check the case when there is space between bracket and the next word if ( *pWord == 0 ) { // get the signal name pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; } } // create signals if ( nMsb == -1 && nLsb == -1 ) { if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) Ver_ParseCreatePi( pNtk, pWord ); if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) Ver_ParseCreatePo( pNtk, pWord ); if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) Abc_NtkFindOrCreateNet( pNtk, pWord ); } else { assert( nMsb >= 0 && nLsb >= 0 ); // add to the hash table Ver_ParseInsertsSuffix( pMan, pWord, nMsb, nLsb ); // add signals from Lsb to Msb Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 ) { // sprintf( Buffer, "%s[%d]", pWord, Bit ); if ( Limit > 1 ) sprintf( Buffer, "%s[%d]", pWord, Bit ); else sprintf( Buffer, "%s", pWord ); if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) Ver_ParseCreatePi( pNtk, Buffer ); if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) Ver_ParseCreatePo( pNtk, Buffer ); if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) Abc_NtkFindOrCreateNet( pNtk, Buffer ); } } Symbol = Ver_StreamPopChar(p); if ( Symbol == ',' ) continue; if ( Symbol == ';' ) return 1; break; } sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } /**Function************************************************************* Synopsis [Parses one directive.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseAlways( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) { Ver_Stream_t * p = pMan->pReader; Abc_Obj_t * pNet, * pNet2; int fStopAfterOne; char * pWord, * pWord2; char Symbol; // parse the directive pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; if ( pWord[0] == '@' ) { Ver_StreamSkipToChars( p, ")" ); Ver_StreamPopChar(p); // parse the directive pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; } // decide how many statements to parse fStopAfterOne = 0; if ( strcmp( pWord, "begin" ) ) fStopAfterOne = 1; // iterate over the initial states while ( 1 ) { if ( !fStopAfterOne ) { // get the name of the output signal pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // look for the end of directive if ( !strcmp( pWord, "end" ) ) break; } // get the fanout net pNet = Ver_ParseFindNet( pNtk, pWord ); if ( pNet == NULL ) { sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // get the equality sign Symbol = Ver_StreamPopChar(p); if ( Symbol != '<' && Symbol != '=' ) { sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } if ( Symbol == '<' ) Ver_StreamPopChar(p); // skip the comments if ( !Ver_ParseSkipComments( pMan ) ) return 0; // get the second name pWord2 = Ver_ParseGetName( pMan ); if ( pWord2 == NULL ) return 0; // check if the name is complemented if ( pWord2[0] == '~' ) { pNet2 = Ver_ParseFindNet( pNtk, pWord2+1 ); pNet2 = Ver_ParseCreateInv( pNtk, pNet2 ); } else pNet2 = Ver_ParseFindNet( pNtk, pWord2 ); if ( pNet2 == NULL ) { sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // create the latch Ver_ParseCreateLatch( pNtk, pNet2, pNet ); // remove the last symbol Symbol = Ver_StreamPopChar(p); assert( Symbol == ';' ); // quit if only one directive if ( fStopAfterOne ) break; } return 1; } /**Function************************************************************* Synopsis [Parses one directive.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseInitial( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) { Ver_Stream_t * p = pMan->pReader; Abc_Obj_t * pNode, * pNet; int fStopAfterOne; char * pWord, * pEquation; char Symbol; // parse the directive pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // decide how many statements to parse fStopAfterOne = 0; if ( strcmp( pWord, "begin" ) ) fStopAfterOne = 1; // iterate over the initial states while ( 1 ) { if ( !fStopAfterOne ) { // get the name of the output signal pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // look for the end of directive if ( !strcmp( pWord, "end" ) ) break; } // get the fanout net pNet = Ver_ParseFindNet( pNtk, pWord ); if ( pNet == NULL ) { sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // get the equality sign Symbol = Ver_StreamPopChar(p); if ( Symbol != '<' && Symbol != '=' ) { sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } if ( Symbol == '<' ) Ver_StreamPopChar(p); // skip the comments if ( !Ver_ParseSkipComments( pMan ) ) return 0; // get the second name pEquation = Ver_StreamGetWord( p, ";" ); if ( pEquation == NULL ) return 0; // find the corresponding latch if ( Abc_ObjFaninNum(pNet) == 0 ) { sprintf( pMan->sError, "Cannot find the latch to assign the initial value." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNet)); assert( Abc_ObjIsLatch(pNode) ); // set the initial state if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") ) Abc_LatchSetInit0( pNode ); else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") ) Abc_LatchSetInit1( pNode ); // else if ( !strcmp(pEquation, "2") ) // Abc_LatchSetInitDc( pNode ); else { sprintf( pMan->sError, "Incorrect initial value of the latch %s.", Abc_ObjName(pNet) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // remove the last symbol Symbol = Ver_StreamPopChar(p); assert( Symbol == ';' ); // quit if only one directive if ( fStopAfterOne ) break; } return 1; } /**Function************************************************************* Synopsis [Parses one directive.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) { char Buffer[1000], Buffer2[1000]; Ver_Stream_t * p = pMan->pReader; Abc_Obj_t * pNode, * pNet; char * pWord, * pName, * pEquation; Hop_Obj_t * pFunc; char Symbol; int i, Bit, Limit, Length, fReduction; int nMsb, nLsb; // if ( Ver_StreamGetLineNumber(p) == 2756 ) // { // int x = 0; // } // convert from the blackbox into the network with local functions representated by AIGs if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) return 0; while ( 1 ) { // get the name of the output signal pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; if ( strcmp(pWord, "#1") == 0 ) continue; // check for vector-inputs if ( !Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ) ) return 0; // handle special case of constant assignment Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; if ( nMsb >= 0 && nLsb >= 0 && Limit > 1 ) { // save the fanout name if ( !strcmp(pWord, "1\'h0") ) strcpy( Buffer, "1\'b0" ); else if ( !strcmp(pWord, "1\'h1") ) strcpy( Buffer, "1\'b1" ); else strcpy( Buffer, pWord ); // get the equality sign if ( Ver_StreamPopChar(p) != '=' ) { sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // get the constant pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // check if it is indeed a constant if ( !(pWord[0] >= '0' && pWord[0] <= '9') ) { sprintf( pMan->sError, "Currently can only assign vector-signal \"%s\" to be a constant.", Buffer ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // get individual bits of the constant if ( !Ver_ParseConstant( pMan, pWord ) ) return 0; // check that the constant has the same size Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; if ( Limit != Vec_PtrSize(pMan->vNames) ) { sprintf( pMan->sError, "The constant size (%d) is different from the signal\"%s\" size (%d).", Vec_PtrSize(pMan->vNames), Buffer, Limit ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // iterate through the bits for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 ) { // get the fanin net if ( Vec_PtrEntry( pMan->vNames, Limit-1-i ) ) pNet = Ver_ParseFindNet( pNtk, "1\'b1" ); else pNet = Ver_ParseFindNet( pNtk, "1\'b0" ); assert( pNet != NULL ); // create the buffer pNode = Abc_NtkCreateNodeBuf( pNtk, pNet ); // get the fanout net sprintf( Buffer2, "%s[%d]", Buffer, Bit ); pNet = Ver_ParseFindNet( pNtk, Buffer2 ); if ( pNet == NULL ) { sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Abc_ObjAddFanin( pNet, pNode ); } // go to the end of the line Ver_ParseSkipComments( pMan ); } else { // consider the case of reduction operations fReduction = 0; if ( pWord[0] == '{' && !pMan->fNameLast ) fReduction = 1; if ( fReduction ) { pWord++; pWord[strlen(pWord)-1] = 0; assert( pWord[0] != '\\' ); } // get the fanout net pNet = Ver_ParseFindNet( pNtk, pWord ); if ( pNet == NULL ) { sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // get the equality sign if ( Ver_StreamPopChar(p) != '=' ) { sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // skip the comments if ( !Ver_ParseSkipComments( pMan ) ) return 0; // get the second name if ( fReduction ) pEquation = Ver_StreamGetWord( p, ";" ); else pEquation = Ver_StreamGetWord( p, ",;" ); if ( pEquation == NULL ) { sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // consider the case of mapped network Vec_PtrClear( pMan->vNames ); if ( pMan->fMapped ) { if ( !strcmp( pEquation, "1\'b0" ) ) pFunc = (Hop_Obj_t *)Mio_LibraryReadConst0((Mio_Library_t *)Abc_FrameReadLibGen()); else if ( !strcmp( pEquation, "1\'b1" ) ) pFunc = (Hop_Obj_t *)Mio_LibraryReadConst1((Mio_Library_t *)Abc_FrameReadLibGen()); else { // "assign foo = \bar ;" if ( *pEquation == '\\' ) { pEquation++; pEquation[strlen(pEquation) - 1] = 0; } if ( Ver_ParseFindNet(pNtk, pEquation) == NULL ) { sprintf( pMan->sError, "Cannot read Verilog with non-trivial assignments in the mapped netlist." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Vec_PtrPush( pMan->vNames, (void *)(ABC_PTRUINT_T)strlen(pEquation) ); Vec_PtrPush( pMan->vNames, pEquation ); // get the buffer pFunc = (Hop_Obj_t *)Mio_LibraryReadBuf((Mio_Library_t *)Abc_FrameReadLibGen()); if ( pFunc == NULL ) { sprintf( pMan->sError, "Reading assign statement for node %s has failed because the genlib library has no buffer.", Abc_ObjName(pNet) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } } else { if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") || !strcmp(pEquation, "1\'bx") ) pFunc = Hop_ManConst0((Hop_Man_t *)pNtk->pManFunc); else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") ) pFunc = Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc); else if ( fReduction ) pFunc = (Hop_Obj_t *)Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError ); else pFunc = (Hop_Obj_t *)Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError ); if ( pFunc == NULL ) { Ver_ParsePrintErrorMessage( pMan ); return 0; } } // create the node with the given inputs pNode = Abc_NtkCreateNode( pNtk ); pNode->pData = pFunc; Abc_ObjAddFanin( pNet, pNode ); // connect to fanin nets for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ ) { // get the name of this signal Length = (int)(ABC_PTRUINT_T)Vec_PtrEntry( pMan->vNames, 2*i ); pName = (char *)Vec_PtrEntry( pMan->vNames, 2*i + 1 ); pName[Length] = 0; // try name // pNet = Ver_ParseFindNet( pNtk, pName ); if ( !strcmp(pName, "1\'h0") ) pNet = Ver_ParseFindNet( pNtk, "1\'b0" ); else if ( !strcmp(pName, "1\'h1") ) pNet = Ver_ParseFindNet( pNtk, "1\'b1" ); else pNet = Ver_ParseFindNet( pNtk, pName ); // find the corresponding net if ( pNet == NULL ) { sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %s is not defined).", pWord, pName ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Abc_ObjAddFanin( pNode, pNet ); } } Symbol = Ver_StreamPopChar(p); if ( Symbol == ',' ) continue; if ( Symbol == ';' ) return 1; } return 1; } /**Function************************************************************* Synopsis [Parses one directive.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType ) { Ver_Stream_t * p = pMan->pReader; Abc_Obj_t * pNet, * pNode; char * pWord, Symbol; // convert from the blackbox into the network with local functions representated by AIGs if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) return 0; // this is gate name - throw it away if ( Ver_StreamPopChar(p) != '(' ) { sprintf( pMan->sError, "Cannot parse a standard gate (expected opening parenthesis)." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); // create the node pNode = Abc_NtkCreateNode( pNtk ); // parse pairs of formal/actural inputs while ( 1 ) { // parse the output name pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // get the net corresponding to this output pNet = Ver_ParseFindNet( pNtk, pWord ); if ( pNet == NULL ) { sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // if this is the first net, add it as an output if ( Abc_ObjFanoutNum(pNode) == 0 ) Abc_ObjAddFanin( pNet, pNode ); else Abc_ObjAddFanin( pNode, pNet ); // check if it is the end of gate Ver_ParseSkipComments( pMan ); Symbol = Ver_StreamPopChar(p); if ( Symbol == ')' ) break; // skip comma if ( Symbol != ',' ) { sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing parenthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); } if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 ) { sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // check if it is the end of gate Ver_ParseSkipComments( pMan ); if ( Ver_StreamPopChar(p) != ';' ) { sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // add logic function if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND ) pNode->pData = Hop_CreateAnd( (Hop_Man_t *)pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR ) pNode->pData = Hop_CreateOr( (Hop_Man_t *)pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR ) pNode->pData = Hop_CreateExor( (Hop_Man_t *)pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT ) pNode->pData = Hop_CreateAnd( (Hop_Man_t *)pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT ) pNode->pData = Hop_Not( (Hop_Obj_t *)pNode->pData ); return 1; } /**Function************************************************************* Synopsis [Parses one directive.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseFlopStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) { Ver_Stream_t * p = pMan->pReader; Abc_Obj_t * pNetLi, * pNetLo, * pLatch; char * pWord, Symbol; // convert from the blackbox into the network with local functions representated by AIGs if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) return 0; // this is gate name - throw it away if ( Ver_StreamPopChar(p) != '(' ) { sprintf( pMan->sError, "Cannot parse a standard gate (expected opening parenthesis)." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); // parse the output name pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // get the net corresponding to this output pNetLo = Ver_ParseFindNet( pNtk, pWord ); if ( pNetLo == NULL ) { sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // check if it is the end of gate Ver_ParseSkipComments( pMan ); Symbol = Ver_StreamPopChar(p); if ( Symbol == ')' ) { sprintf( pMan->sError, "Cannot parse the flop." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // skip comma if ( Symbol != ',' ) { sprintf( pMan->sError, "Cannot parse the flop." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); // parse the output name pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // get the net corresponding to this output pNetLi = Ver_ParseFindNet( pNtk, pWord ); if ( pNetLi == NULL ) { sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // check if it is the end of gate Ver_ParseSkipComments( pMan ); Symbol = Ver_StreamPopChar(p); if ( Symbol != ')' ) { sprintf( pMan->sError, "Cannot parse the flop." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // check if it is the end of gate Ver_ParseSkipComments( pMan ); if ( Ver_StreamPopChar(p) != ';' ) { sprintf( pMan->sError, "Cannot parse the flop." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // create the latch pLatch = Ver_ParseCreateLatch( pNtk, pNetLi, pNetLo ); Abc_LatchSetInit0( pLatch ); return 1; } /**Function************************************************************* Synopsis [Returns the index of the given pin the gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_FindGateInput( Mio_Gate_t * pGate, char * pName ) { Mio_Pin_t * pGatePin; int i; for ( i = 0, pGatePin = Mio_GateReadPins(pGate); pGatePin != NULL; pGatePin = Mio_PinReadNext(pGatePin), i++ ) if ( strcmp(pName, Mio_PinReadName(pGatePin)) == 0 ) return i; if ( strcmp(pName, Mio_GateReadOutName(pGate)) == 0 ) return i; if ( Mio_GateReadTwin(pGate) && strcmp(pName, Mio_GateReadOutName(Mio_GateReadTwin(pGate))) == 0 ) return i+1; return -1; } /**Function************************************************************* Synopsis [Parses one directive.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate ) { Ver_Stream_t * p = pMan->pReader; Abc_Obj_t * pNetActual, * pNode, * pNode2 = NULL; char * pWord, Symbol; int Input, i, nFanins = Mio_GateReadPinNum(pGate); // convert from the blackbox into the network with local functions representated by gates if ( 1 != pMan->fMapped ) { sprintf( pMan->sError, "The network appears to be mapped. Use \"r -m\" to read mapped Verilog." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // update the network type if needed if ( !Ver_ParseConvertNetwork( pMan, pNtk, 1 ) ) return 0; // parse the directive and set the pointers to the PIs/POs of the gate pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // this is gate name - throw it away if ( Ver_StreamPopChar(p) != '(' ) { sprintf( pMan->sError, "Cannot parse gate %s (expected opening parenthesis).", Mio_GateReadName(pGate) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); // start the node pNode = Abc_NtkCreateNode( pNtk ); pNode->pData = pGate; if ( Mio_GateReadTwin(pGate) ) { pNode2 = Abc_NtkCreateNode( pNtk ); pNode2->pData = Mio_GateReadTwin(pGate); } // parse pairs of formal/actural inputs Vec_IntClear( pMan->vPerm ); while ( 1 ) { // process one pair of formal/actual parameters if ( Ver_StreamPopChar(p) != '.' ) { sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Mio_GateReadName(pGate) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // parse the formal name pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // find the corresponding pin of the gate Input = Ver_FindGateInput( pGate, pWord ); if ( Input == -1 ) { sprintf( pMan->sError, "Formal input name %s cannot be found in the gate %s.", pWord, Mio_GateReadOutName(pGate) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // open the parenthesis if ( Ver_StreamPopChar(p) != '(' ) { sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening parenthesis).", pWord, Mio_GateReadName(pGate) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // parse the actual name pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // check if the name is complemented assert( pWord[0] != '~' ); /* fCompl = (pWord[0] == '~'); if ( fCompl ) { fComplUsed = 1; pWord++; if ( pNtk->pData == NULL ) pNtk->pData = Extra_MmFlexStart(); } */ // get the actual net pNetActual = Ver_ParseFindNet( pNtk, pWord ); if ( pNetActual == NULL ) { sprintf( pMan->sError, "Actual net %s is missing.", pWord ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // close the parenthesis if ( Ver_StreamPopChar(p) != ')' ) { sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing parenthesis).", pWord, Mio_GateReadName(pGate) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // add the fanin if ( Input < nFanins ) { Vec_IntPush( pMan->vPerm, Input ); Abc_ObjAddFanin( pNode, pNetActual ); // fanin if ( pNode2 ) Abc_ObjAddFanin( pNode2, pNetActual ); // fanin } else if ( Input == nFanins ) Abc_ObjAddFanin( pNetActual, pNode ); // fanout else if ( Input == nFanins + 1 ) Abc_ObjAddFanin( pNetActual, pNode2 ); // fanout else assert( 0 ); // check if it is the end of gate Ver_ParseSkipComments( pMan ); Symbol = Ver_StreamPopChar(p); if ( Symbol == ')' ) break; // skip comma if ( Symbol != ',' ) { sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing parenthesis).", pWord, Mio_GateReadName(pGate) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); } // check that the gate as the same number of input if ( !(Abc_ObjFaninNum(pNode) == nFanins && Abc_ObjFanoutNum(pNode) == 1) ) { sprintf( pMan->sError, "Parsing of gate %s has failed.", Mio_GateReadName(pGate) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // check if it is the end of gate Ver_ParseSkipComments( pMan ); if ( Ver_StreamPopChar(p) != ';' ) { sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", Mio_GateReadName(pGate) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // check if we need to permute the inputs Vec_IntForEachEntry( pMan->vPerm, Input, i ) if ( Input != i ) break; if ( i < Vec_IntSize(pMan->vPerm) ) { // add the fanin numnbers to the end of the permuation array for ( i = 0; i < nFanins; i++ ) Vec_IntPush( pMan->vPerm, Abc_ObjFaninId(pNode, i) ); // write the fanin numbers into their corresponding places (according to the gate) for ( i = 0; i < nFanins; i++ ) Vec_IntWriteEntry( &pNode->vFanins, Vec_IntEntry(pMan->vPerm, i), Vec_IntEntry(pMan->vPerm, i+nFanins) ); } return 1; } /**Function************************************************************* Synopsis [Parses one directive.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox ) { char Buffer[1000]; Ver_Stream_t * p = pMan->pReader; Ver_Bundle_t * pBundle; Vec_Ptr_t * vBundles; Abc_Obj_t * pNetActual; Abc_Obj_t * pNode; char * pWord, Symbol; int fCompl, fFormalIsGiven; int i, k, Bit, Limit, nMsb, nLsb, fQuit, flag; // gate the name of the box pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // create a box with this name pNode = Abc_NtkCreateBlackbox( pNtk ); pNode->pData = pNtkBox; Abc_ObjAssignName( pNode, pWord, NULL ); // continue parsing the box if ( Ver_StreamPopChar(p) != '(' ) { sprintf( pMan->sError, "Cannot parse box %s (expected opening parenthesis).", Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); // parse pairs of formal/actual inputs vBundles = Vec_PtrAlloc( 16 ); pNode->pCopy = (Abc_Obj_t *)vBundles; while ( 1 ) { // allocate the bundle (formal name + array of actual nets) pBundle = ABC_ALLOC( Ver_Bundle_t, 1 ); pBundle->pNameFormal = NULL; pBundle->vNetsActual = Vec_PtrAlloc( 4 ); Vec_PtrPush( vBundles, pBundle ); // process one pair of formal/actual parameters fFormalIsGiven = 0; if ( Ver_StreamScanChar(p) == '.' ) { fFormalIsGiven = 1; if ( Ver_StreamPopChar(p) != '.' ) { sprintf( pMan->sError, "Cannot parse box %s (expected .).", Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // parse the formal name pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // save the name pBundle->pNameFormal = Extra_UtilStrsav( pWord ); // open the parenthesis if ( Ver_StreamPopChar(p) != '(' ) { sprintf( pMan->sError, "Cannot formal parameter %s of box %s (expected opening parenthesis).", pWord, Abc_ObjName(pNode)); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); } // check if this is the beginning of {} expression Symbol = Ver_StreamScanChar(p); // consider the case of vector-inputs if ( Symbol == '{' ) { // skip this char Ver_StreamPopChar(p); // read actual names i = 0; fQuit = 0; while ( 1 ) { // parse the formal name Ver_ParseSkipComments( pMan ); pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // check if the last char is a closing brace if ( pWord[strlen(pWord)-1] == '}' ) { pWord[strlen(pWord)-1] = 0; fQuit = 1; } if ( pWord[0] == 0 ) break; // check for constant if ( pWord[0] >= '1' && pWord[0] <= '9' ) { if ( !Ver_ParseConstant( pMan, pWord ) ) return 0; // add constant MSB to LSB for ( k = 0; k < Vec_PtrSize(pMan->vNames); k++, i++ ) { // get the actual net sprintf( Buffer, "1\'b%d", (int)(Vec_PtrEntry(pMan->vNames,k) != NULL) ); pNetActual = Ver_ParseFindNet( pNtk, Buffer ); if ( pNetActual == NULL ) { sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Vec_PtrPush( pBundle->vNetsActual, pNetActual ); } } else { // get the suffix of the form [m:n] if ( pWord[strlen(pWord)-1] == ']' && !pMan->fNameLast ) Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb ); else Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ); // generate signals if ( nMsb == -1 && nLsb == -1 ) { // get the actual net pNetActual = Ver_ParseFindNet( pNtk, pWord ); if ( pNetActual == NULL ) { if ( !strncmp(pWord, "Open_", 5) || !strncmp(pWord, "dct_unconnected", 15) ) pNetActual = Abc_NtkCreateNet( pNtk ); else { sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } Vec_PtrPush( pBundle->vNetsActual, pNetActual ); i++; } else { // go from MSB to LSB assert( nMsb >= 0 && nLsb >= 0 ); Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1; for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--, i++ ) { // get the actual net sprintf( Buffer, "%s[%d]", pWord, Bit ); pNetActual = Ver_ParseFindNet( pNtk, Buffer ); if ( pNetActual == NULL ) { if ( !strncmp(pWord, "Open_", 5) || !strncmp(pWord, "dct_unconnected", 15) ) pNetActual = Abc_NtkCreateNet( pNtk ); else { sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } Vec_PtrPush( pBundle->vNetsActual, pNetActual ); } } } if ( fQuit ) break; // skip comma Ver_ParseSkipComments( pMan ); Symbol = Ver_StreamPopChar(p); if ( Symbol == '}' ) break; if ( Symbol != ',' ) { sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } } else { // get the next word pWord = Ver_ParseGetName( pMan ); if ( pWord == NULL ) return 0; // consider the case of empty name fCompl = 0; if ( pWord[0] == 0 ) { pNetActual = Abc_NtkCreateNet( pNtk ); Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) ); } else { // get the actual net flag=0; pNetActual = Ver_ParseFindNet( pNtk, pWord ); if ( pNetActual == NULL ) { Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ); if ( nMsb == -1 && nLsb == -1 ) { Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb ); if ( nMsb == -1 && nLsb == -1 ) { if ( !strncmp(pWord, "Open_", 5) || !strncmp(pWord, "dct_unconnected", 15) ) { pNetActual = Abc_NtkCreateNet( pNtk ); Vec_PtrPush( pBundle->vNetsActual, pNetActual ); } else { sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } else { flag=1; } } else { flag=1; } if (flag) { Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1; for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--) { // get the actual net sprintf( Buffer, "%s[%d]", pWord, Bit ); pNetActual = Ver_ParseFindNet( pNtk, Buffer ); if ( pNetActual == NULL ) { if ( !strncmp(pWord, "Open_", 5) || !strncmp(pWord, "dct_unconnected", 15)) pNetActual = Abc_NtkCreateNet( pNtk ); else { sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } Vec_PtrPush( pBundle->vNetsActual, pNetActual ); } } } else { Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) ); } } } if ( fFormalIsGiven ) { // close the parenthesis Ver_ParseSkipComments( pMan ); if ( Ver_StreamPopChar(p) != ')' ) { sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected closing parenthesis).", pWord, Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); } // check if it is the end of gate Symbol = Ver_StreamPopChar(p); if ( Symbol == ')' ) break; // skip comma if ( Symbol != ',' ) { sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected comma).", pWord, Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } Ver_ParseSkipComments( pMan ); } // check if it is the end of gate Ver_ParseSkipComments( pMan ); if ( Ver_StreamPopChar(p) != ';' ) { sprintf( pMan->sError, "Cannot read box %s (expected closing semicolumn).", Abc_ObjName(pNode) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } return 1; } /**Function************************************************************* Synopsis [Connects one box to the network] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_ParseFreeBundle( Ver_Bundle_t * pBundle ) { ABC_FREE( pBundle->pNameFormal ); Vec_PtrFree( pBundle->vNetsActual ); ABC_FREE( pBundle ); } /**Function************************************************************* Synopsis [Connects one box to the network] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox ) { Vec_Ptr_t * vBundles = (Vec_Ptr_t *)pBox->pCopy; Abc_Ntk_t * pNtk = pBox->pNtk; Abc_Ntk_t * pNtkBox = (Abc_Ntk_t *)pBox->pData; Abc_Obj_t * pTerm, * pTermNew, * pNetAct; Ver_Bundle_t * pBundle; char * pNameFormal; int i, k, j, iBundle, Length; assert( !Ver_ObjIsConnected(pBox) ); assert( Ver_NtkIsDefined(pNtkBox) ); assert( !Abc_NtkHasBlackbox(pNtkBox) || Abc_NtkBoxNum(pNtkBox) == 1 ); /* // clean the PI/PO nets Abc_NtkForEachPi( pNtkBox, pTerm, i ) Abc_ObjFanout0(pTerm)->pCopy = NULL; Abc_NtkForEachPo( pNtkBox, pTerm, i ) Abc_ObjFanin0(pTerm)->pCopy = NULL; */ // check the number of actual nets is the same as the number of formal nets if ( Vec_PtrSize(vBundles) > Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) { sprintf( pMan->sError, "The number of actual IOs (%d) is bigger than the number of formal IOs (%d) when instantiating network %s in box %s.", Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) ); // free the bundling Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k ) Ver_ParseFreeBundle( pBundle ); Vec_PtrFree( vBundles ); pBox->pCopy = NULL; Ver_ParsePrintErrorMessage( pMan ); return 0; } // check if some of them do not have formal names Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k ) if ( pBundle->pNameFormal == NULL ) break; if ( k < Vec_PtrSize(vBundles) ) { printf( "Warning: The instance %s of network %s will be connected without using formal names.\n", pNtkBox->pName, Abc_ObjName(pBox) ); // add all actual nets in the bundles iBundle = 0; Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j ) iBundle += Vec_PtrSize(pBundle->vNetsActual); // check the number of actual nets is the same as the number of formal nets if ( iBundle != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) { sprintf( pMan->sError, "The number of actual IOs (%d) is different from the number of formal IOs (%d) when instantiating network %s in box %s.", Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) ); // free the bundling Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k ) Ver_ParseFreeBundle( pBundle ); Vec_PtrFree( vBundles ); pBox->pCopy = NULL; Ver_ParsePrintErrorMessage( pMan ); return 0; } // connect bundles in the natural order iBundle = 0; Abc_NtkForEachPi( pNtkBox, pTerm, i ) { pBundle = (Ver_Bundle_t *)Vec_PtrEntry( vBundles, iBundle++ ); // the bundle is found - add the connections - using order LSB to MSB Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, k ) { pTermNew = Abc_NtkCreateBi( pNtk ); Abc_ObjAddFanin( pBox, pTermNew ); Abc_ObjAddFanin( pTermNew, pNetAct ); i++; } i--; } // create fanins of the box Abc_NtkForEachPo( pNtkBox, pTerm, i ) { pBundle = (Ver_Bundle_t *)Vec_PtrEntry( vBundles, iBundle++ ); // the bundle is found - add the connections - using order LSB to MSB Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, k ) { pTermNew = Abc_NtkCreateBo( pNtk ); Abc_ObjAddFanin( pTermNew, pBox ); Abc_ObjAddFanin( pNetAct, pTermNew ); i++; } i--; } // free the bundling Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k ) Ver_ParseFreeBundle( pBundle ); Vec_PtrFree( vBundles ); pBox->pCopy = NULL; return 1; } // bundles arrive in any order - but inside each bundle the order is MSB to LSB // make sure every formal PI has a corresponding net Abc_NtkForEachPi( pNtkBox, pTerm, i ) { // get the name of this formal net pNameFormal = Abc_ObjName( Abc_ObjFanout0(pTerm) ); // try to find the bundle with this formal net pBundle = NULL; Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k ) if ( !strcmp(pBundle->pNameFormal, pNameFormal) ) break; assert( pBundle != NULL ); // if the bundle is not found, try without parentheses if ( k == Vec_PtrSize(vBundles) ) { pBundle = NULL; Length = strlen(pNameFormal); if ( pNameFormal[Length-1] == ']' ) { // find the opening brace for ( Length--; Length >= 0; Length-- ) if ( pNameFormal[Length] == '[' ) break; // compare names before brace if ( Length > 0 ) { Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j ) if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) && (int)strlen(pBundle->pNameFormal) == Length ) break; if ( j == Vec_PtrSize(vBundles) ) pBundle = NULL; } } if ( pBundle == NULL ) { sprintf( pMan->sError, "Cannot find an actual net for the formal net %s when instantiating network %s in box %s.", pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } // the bundle is found - add the connections - using order LSB to MSB Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, k ) { pTermNew = Abc_NtkCreateBi( pNtk ); Abc_ObjAddFanin( pBox, pTermNew ); Abc_ObjAddFanin( pTermNew, pNetAct ); i++; } i--; } // connect those formal POs that do have nets Abc_NtkForEachPo( pNtkBox, pTerm, i ) { // get the name of this PI pNameFormal = Abc_ObjName( Abc_ObjFanin0(pTerm) ); // try to find this formal net in the bundle pBundle = NULL; Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k ) if ( !strcmp(pBundle->pNameFormal, pNameFormal) ) break; assert( pBundle != NULL ); // if the name is not found, try without parentheses if ( k == Vec_PtrSize(vBundles) ) { pBundle = NULL; Length = strlen(pNameFormal); if ( pNameFormal[Length-1] == ']' ) { // find the opening brace for ( Length--; Length >= 0; Length-- ) if ( pNameFormal[Length] == '[' ) break; // compare names before brace if ( Length > 0 ) { Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j ) if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) && (int)strlen(pBundle->pNameFormal) == Length ) break; if ( j == Vec_PtrSize(vBundles) ) pBundle = NULL; } } if ( pBundle == NULL ) { char Buffer[1000]; // printf( "Warning: The formal output %s is not driven when instantiating network %s in box %s.", // pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) ); pTermNew = Abc_NtkCreateBo( pNtk ); sprintf( Buffer, "_temp_net%d", Abc_ObjId(pTermNew) ); pNetAct = Abc_NtkFindOrCreateNet( pNtk, Buffer ); Abc_ObjAddFanin( pTermNew, pBox ); Abc_ObjAddFanin( pNetAct, pTermNew ); continue; } } // the bundle is found - add the connections Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, k ) { if ( !strcmp(Abc_ObjName(pNetAct), "1\'b0") || !strcmp(Abc_ObjName(pNetAct), "1\'b1") ) { sprintf( pMan->sError, "It looks like formal output %s is driving a constant net (%s) when instantiating network %s in box %s.", pBundle->pNameFormal, Abc_ObjName(pNetAct), pNtkBox->pName, Abc_ObjName(pBox) ); // free the bundling Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k ) Ver_ParseFreeBundle( pBundle ); Vec_PtrFree( vBundles ); pBox->pCopy = NULL; Ver_ParsePrintErrorMessage( pMan ); return 0; } pTermNew = Abc_NtkCreateBo( pNtk ); Abc_ObjAddFanin( pTermNew, pBox ); Abc_ObjAddFanin( pNetAct, pTermNew ); i++; } i--; } // free the bundling Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, k ) Ver_ParseFreeBundle( pBundle ); Vec_PtrFree( vBundles ); pBox->pCopy = NULL; return 1; } /**Function************************************************************* Synopsis [Connects the defined boxes.] Description [Returns 2 if there are any undef boxes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseConnectDefBoxes( Ver_Man_t * pMan ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pBox; int i, k, RetValue = 1; // go through all the modules Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) { // go through all the boxes of this module Abc_NtkForEachBox( pNtk, pBox, k ) { if ( Abc_ObjIsLatch(pBox) ) continue; // skip internal boxes of the blackboxes if ( pBox->pData == NULL ) continue; // if the network is undefined, it will be connected later if ( !Ver_NtkIsDefined((Abc_Ntk_t *)pBox->pData) ) { RetValue = 2; continue; } // connect the box if ( !Ver_ParseConnectBox( pMan, pBox ) ) return 0; // if the network is a true blackbox, skip if ( Abc_NtkHasBlackbox((Abc_Ntk_t *)pBox->pData) ) continue; // convert the box to the whitebox Abc_ObjBlackboxToWhitebox( pBox ); } } return RetValue; } /**Function************************************************************* Synopsis [Collects the undef boxes and maps them into their instances.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Ver_ParseCollectUndefBoxes( Ver_Man_t * pMan ) { Vec_Ptr_t * vUndefs; Abc_Ntk_t * pNtk, * pNtkBox; Abc_Obj_t * pBox; int i, k; // clear the module structures Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) pNtk->pData = NULL; // go through all the blackboxes vUndefs = Vec_PtrAlloc( 16 ); Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) { Abc_NtkForEachBlackbox( pNtk, pBox, k ) { pNtkBox = (Abc_Ntk_t *)pBox->pData; if ( pNtkBox == NULL ) continue; if ( Ver_NtkIsDefined(pNtkBox) ) continue; if ( pNtkBox->pData == NULL ) { // save the box Vec_PtrPush( vUndefs, pNtkBox ); pNtkBox->pData = Vec_PtrAlloc( 16 ); } // save the instance Vec_PtrPush( (Vec_Ptr_t *)pNtkBox->pData, pBox ); } } return vUndefs; } /**Function************************************************************* Synopsis [Reports how many times each type of undefined box occurs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_ParseReportUndefBoxes( Ver_Man_t * pMan ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pBox; int i, k, nBoxes; // clean nBoxes = 0; Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) { pNtk->fHiePath = 0; if ( !Ver_NtkIsDefined(pNtk) ) nBoxes++; } // count Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) Abc_NtkForEachBlackbox( pNtk, pBox, k ) if ( pBox->pData && !Ver_NtkIsDefined((Abc_Ntk_t *)pBox->pData) ) ((Abc_Ntk_t *)pBox->pData)->fHiePath++; // print the stats printf( "Warning: The design contains %d undefined object types interpreted as blackboxes:\n", nBoxes ); Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) if ( !Ver_NtkIsDefined(pNtk) ) printf( "%s (%d) ", Abc_NtkName(pNtk), pNtk->fHiePath ); printf( "\n" ); // clean Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) pNtk->fHiePath = 0; } /**Function************************************************************* Synopsis [Returns 1 if there are non-driven nets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseCheckNondrivenNets( Vec_Ptr_t * vUndefs ) { Abc_Ntk_t * pNtk; Ver_Bundle_t * pBundle; Abc_Obj_t * pBox, * pNet; int i, k, j, m; // go through undef box types Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i ) // go through instances of this type Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k ) // go through the bundles of this instance Vec_PtrForEachEntryReverse( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) // go through the actual nets of this bundle if ( pBundle ) Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNet, m ) { if ( Abc_ObjFaninNum(pNet) == 0 ) // non-driven if ( strcmp(Abc_ObjName(pNet), "1\'b0") && strcmp(Abc_ObjName(pNet), "1\'b1") ) // diff from a const return 1; } return 0; } /**Function************************************************************* Synopsis [Checks if formal nets with the given name are driven in any of the instances of undef boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseFormalNetsAreDriven( Abc_Ntk_t * pNtk, char * pNameFormal ) { Ver_Bundle_t * pBundle = NULL; Abc_Obj_t * pBox, * pNet; int k, j, m; // go through instances of this type Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k ) { // find a bundle with the given name in this instance Vec_PtrForEachEntryReverse( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) if ( pBundle && !strcmp( pBundle->pNameFormal, pNameFormal ) ) break; // skip non-driven bundles if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) continue; // check if all nets are driven in this bundle assert(pBundle); // Verify that pBundle was assigned to. Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNet, m ) if ( Abc_ObjFaninNum(pNet) > 0 ) return 1; } return 0; } /**Function************************************************************* Synopsis [Returns the non-driven bundle that is given distance from the end.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ver_Bundle_t * Ver_ParseGetNondrivenBundle( Abc_Ntk_t * pNtk, int Counter ) { Ver_Bundle_t * pBundle; Abc_Obj_t * pBox, * pNet; int k, m; // go through instances of this type Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k ) { if ( Counter >= Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) continue; // get the bundle given distance away pBundle = (Ver_Bundle_t *)Vec_PtrEntry( (Vec_Ptr_t *)pBox->pCopy, Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) - 1 - Counter ); if ( pBundle == NULL ) continue; // go through the actual nets of this bundle Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNet, m ) if ( !Abc_ObjFaninNum(pNet) && !Ver_ParseFormalNetsAreDriven(pNtk, pBundle->pNameFormal) ) // non-driven return pBundle; } return NULL; } /**Function************************************************************* Synopsis [Drives the bundle in the given undef box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseDriveFormal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_Bundle_t * pBundle0 ) { char Buffer[200]; char * pName; Ver_Bundle_t * pBundle = NULL; Abc_Obj_t * pBox, * pTerm, * pTermNew, * pNetAct, * pNetFormal; int k, j, m; // drive this net in the undef box Vec_PtrForEachEntry( Abc_Obj_t *, pBundle0->vNetsActual, pNetAct, m ) { // create the formal net if ( Vec_PtrSize(pBundle0->vNetsActual) == 1 ) sprintf( Buffer, "%s", pBundle0->pNameFormal ); else sprintf( Buffer, "%s[%d]", pBundle0->pNameFormal, m ); assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL ); pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer ); // connect it to the box pTerm = Abc_NtkCreateBo( pNtk ); assert( Abc_NtkBoxNum(pNtk) <= 1 ); pBox = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk); Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNetFormal ); Abc_ObjAddFanin( pNetFormal, pTerm ); Abc_ObjAddFanin( pTerm, pBox ); } // go through instances of this type pName = Extra_UtilStrsav(pBundle0->pNameFormal); Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k ) { // find a bundle with the given name in this instance Vec_PtrForEachEntryReverse( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) if ( pBundle && !strcmp( pBundle->pNameFormal, pName ) ) break; // skip non-driven bundles if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) continue; // check if any nets are driven in this bundle assert(pBundle); // Verify pBundle was assigned to. Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, m ) if ( Abc_ObjFaninNum(pNetAct) > 0 ) { sprintf( pMan->sError, "Missing specification of the I/Os of undefined box \"%s\".", Abc_NtkName(pNtk) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } // drive the nets by the undef box Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, m ) { pTermNew = Abc_NtkCreateBo( pNetAct->pNtk ); Abc_ObjAddFanin( pTermNew, pBox ); Abc_ObjAddFanin( pNetAct, pTermNew ); } // remove the bundle Ver_ParseFreeBundle( pBundle ); pBundle = NULL; Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL ); } ABC_FREE( pName ); return 1; } /**Function************************************************************* Synopsis [Drives the bundle in the given undef box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseDriveInputs( Ver_Man_t * pMan, Vec_Ptr_t * vUndefs ) { char Buffer[200]; Ver_Bundle_t * pBundle; Abc_Ntk_t * pNtk; Abc_Obj_t * pBox, * pBox2, * pTerm, * pTermNew, * pNetFormal, * pNetAct; int i, k, j, m, CountCur, CountTotal = -1; // iterate through the undef boxes Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i ) { // count the number of unconnected bundles for instances of this type of box CountTotal = -1; Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k ) { CountCur = 0; Vec_PtrForEachEntry( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) CountCur += (pBundle != NULL); if ( CountTotal == -1 ) CountTotal = CountCur; else if ( CountTotal != CountCur ) { sprintf( pMan->sError, "The number of formal inputs (%d) is different from the expected one (%d) when instantiating network %s in box %s.", CountCur, CountTotal, pNtk->pName, Abc_ObjName(pBox) ); Ver_ParsePrintErrorMessage( pMan ); return 0; } } // create formals pBox = (Abc_Obj_t *)Vec_PtrEntry( (Vec_Ptr_t *)pNtk->pData, 0 ); Vec_PtrForEachEntry( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) { if ( pBundle == NULL ) continue; Vec_PtrForEachEntry( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, m ) { // find create the formal net if ( Vec_PtrSize(pBundle->vNetsActual) == 1 ) sprintf( Buffer, "%s", pBundle->pNameFormal ); else sprintf( Buffer, "%s[%d]", pBundle->pNameFormal, m ); assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL ); pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer ); // connect pTerm = Abc_NtkCreateBi( pNtk ); assert( Abc_NtkBoxNum(pNtk) <= 1 ); pBox2 = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk); Abc_ObjAddFanin( pNetFormal, Abc_NtkCreatePi(pNtk) ); Abc_ObjAddFanin( pTerm, pNetFormal ); Abc_ObjAddFanin( pBox2, pTerm ); } } // go through all the boxes Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k ) { // go through all the bundles Vec_PtrForEachEntry( Ver_Bundle_t *, (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) { if ( pBundle == NULL ) continue; // drive the nets by the undef box Vec_PtrForEachEntryReverse( Abc_Obj_t *, pBundle->vNetsActual, pNetAct, m ) { pTermNew = Abc_NtkCreateBi( pNetAct->pNtk ); Abc_ObjAddFanin( pBox, pTermNew ); Abc_ObjAddFanin( pTermNew, pNetAct ); } // remove the bundle Ver_ParseFreeBundle( pBundle ); Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL ); } // free the bundles Vec_PtrFree( (Vec_Ptr_t *)pBox->pCopy ); pBox->pCopy = NULL; } } return 1; } /**Function************************************************************* Synopsis [Returns the max size of any undef box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseMaxBoxSize( Vec_Ptr_t * vUndefs ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pBox; int i, k, nMaxSize = 0; // go through undef box types Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i ) // go through instances of this type Vec_PtrForEachEntry( Abc_Obj_t *, (Vec_Ptr_t *)pNtk->pData, pBox, k ) // check the number of bundles of this instance if ( nMaxSize < Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) nMaxSize = Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy); return nMaxSize; } /**Function************************************************************* Synopsis [Prints the comprehensive report into a log file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_ParsePrintLog( Ver_Man_t * pMan ) { Abc_Ntk_t * pNtk, * pNtkBox; Abc_Obj_t * pBox; FILE * pFile; char * pNameGeneric; char Buffer[1000]; int i, k, Count1 = 0; // open the log file pNameGeneric = Extra_FileNameGeneric( pMan->pFileName ); sprintf( Buffer, "%s.log", pNameGeneric ); ABC_FREE( pNameGeneric ); pFile = fopen( Buffer, "w" ); // count the total number of instances and how many times they occur Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) pNtk->fHieVisited = 0; Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) Abc_NtkForEachBox( pNtk, pBox, k ) { if ( Abc_ObjIsLatch(pBox) ) continue; pNtkBox = (Abc_Ntk_t *)pBox->pData; if ( pNtkBox == NULL ) continue; pNtkBox->fHieVisited++; } // print each box and its stats fprintf( pFile, "The hierarhical design %s contains %d modules:\n", pMan->pFileName, Vec_PtrSize(pMan->pDesign->vModules) ); Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) { fprintf( pFile, "%-50s : ", Abc_NtkName(pNtk) ); if ( !Ver_NtkIsDefined(pNtk) ) fprintf( pFile, "undefbox" ); else if ( Abc_NtkHasBlackbox(pNtk) ) fprintf( pFile, "blackbox" ); else fprintf( pFile, "logicbox" ); fprintf( pFile, " instantiated %6d times ", pNtk->fHieVisited ); // fprintf( pFile, "\n " ); fprintf( pFile, " pi = %4d", Abc_NtkPiNum(pNtk) ); fprintf( pFile, " po = %4d", Abc_NtkPoNum(pNtk) ); fprintf( pFile, " nd = %8d", Abc_NtkNodeNum(pNtk) ); fprintf( pFile, " lat = %6d", Abc_NtkLatchNum(pNtk) ); fprintf( pFile, " box = %6d", Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); fprintf( pFile, "\n" ); Count1 += (Abc_NtkPoNum(pNtk) == 1); } Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) pNtk->fHieVisited = 0; fprintf( pFile, "The number of modules with one output = %d (%.2f %%).\n", Count1, 100.0 * Count1/Vec_PtrSize(pMan->pDesign->vModules) ); // report instances with dangling outputs if ( Vec_PtrSize(pMan->pDesign->vModules) > 1 ) { Vec_Ptr_t * vBundles; Ver_Bundle_t * pBundle; int j, nActNets, Counter = 0; // count the number of instances with dangling outputs Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) { Abc_NtkForEachBox( pNtk, pBox, k ) { if ( Abc_ObjIsLatch(pBox) ) continue; vBundles = (Vec_Ptr_t *)pBox->pCopy; pNtkBox = (Abc_Ntk_t *)pBox->pData; if ( pNtkBox == NULL ) continue; if ( !Ver_NtkIsDefined(pNtkBox) ) continue; // count the number of actual nets nActNets = 0; Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j ) nActNets += Vec_PtrSize(pBundle->vNetsActual); // the box is defined and will be connected if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) Counter++; } } if ( Counter == 0 ) fprintf( pFile, "The outputs of all box instances are connected.\n" ); else { fprintf( pFile, "\n" ); fprintf( pFile, "The outputs of %d box instances are not connected:\n", Counter ); // enumerate through the boxes Vec_PtrForEachEntry( Abc_Ntk_t *, pMan->pDesign->vModules, pNtk, i ) { Abc_NtkForEachBox( pNtk, pBox, k ) { if ( Abc_ObjIsLatch(pBox) ) continue; vBundles = (Vec_Ptr_t *)pBox->pCopy; pNtkBox = (Abc_Ntk_t *)pBox->pData; if ( pNtkBox == NULL ) continue; if ( !Ver_NtkIsDefined(pNtkBox) ) continue; // count the number of actual nets nActNets = 0; Vec_PtrForEachEntry( Ver_Bundle_t *, vBundles, pBundle, j ) nActNets += Vec_PtrSize(pBundle->vNetsActual); // the box is defined and will be connected if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) fprintf( pFile, "In module \"%s\" instance \"%s\" of box \"%s\" has different numbers of actual/formal nets (%d/%d).\n", Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pNtkBox), nActNets, Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ); } } } } fclose( pFile ); printf( "Hierarchy statistics can be found in log file \"%s\".\n", Buffer ); } /**Function************************************************************* Synopsis [Attaches the boxes to the network.] Description [This procedure is called after the design is parsed. At that point, all the defined models have their PIs present. They are connected first. Next undef boxes are processed (if present). Iteratively, one bundle is selected to be driven by the undef boxes in such a way that there is no conflict (if it is driven by an instance of the box, no other net will be driven twice by the same formal net of some other instance of the same box). In the end, all the remaining nets that cannot be driven by the undef boxes are connected to the undef boxes as inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseAttachBoxes( Ver_Man_t * pMan ) { int fPrintLog = 0; Abc_Ntk_t * pNtk = NULL; Ver_Bundle_t * pBundle; Vec_Ptr_t * vUndefs; int i, RetValue, Counter, nMaxBoxSize; // print the log file if ( fPrintLog && pMan->pDesign->vModules && Vec_PtrSize(pMan->pDesign->vModules) > 1 ) Ver_ParsePrintLog( pMan ); // connect defined boxes RetValue = Ver_ParseConnectDefBoxes( pMan ); if ( RetValue < 2 ) return RetValue; // report the boxes Ver_ParseReportUndefBoxes( pMan ); // collect undef box types and their actual instances vUndefs = Ver_ParseCollectUndefBoxes( pMan ); assert( Vec_PtrSize( vUndefs ) > 0 ); // go through all undef box types Counter = 0; nMaxBoxSize = Ver_ParseMaxBoxSize( vUndefs ); while ( Ver_ParseCheckNondrivenNets(vUndefs) && Counter < nMaxBoxSize ) { // go through undef box types pBundle = NULL; Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i ) if ( (pBundle = Ver_ParseGetNondrivenBundle( pNtk, Counter )) ) break; if ( pBundle == NULL ) { Counter++; continue; } // drive this bundle by this box if ( !Ver_ParseDriveFormal( pMan, pNtk, pBundle ) ) return 0; } // make all the remaining bundles the drivers of undefs if ( !Ver_ParseDriveInputs( pMan, vUndefs ) ) return 0; // cleanup Vec_PtrForEachEntry( Abc_Ntk_t *, vUndefs, pNtk, i ) { Vec_PtrFree( (Vec_Ptr_t *)pNtk->pData ); pNtk->pData = NULL; } Vec_PtrFree( vUndefs ); return 1; } /**Function************************************************************* Synopsis [Creates PI terminal and net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pNet, * pTerm; // get the PI net // pNet = Ver_ParseFindNet( pNtk, pName ); // if ( pNet ) // printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); // add the PI node pTerm = Abc_NtkCreatePi( pNtk ); Abc_ObjAddFanin( pNet, pTerm ); return pTerm; } /**Function************************************************************* Synopsis [Creates PO terminal and net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pNet, * pTerm; // get the PO net // pNet = Ver_ParseFindNet( pNtk, pName ); // if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) // printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); // add the PO node pTerm = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pTerm, pNet ); return pTerm; } /**Function************************************************************* Synopsis [Create a latch with the given input/output.] Description [By default, the latch value is a don't-care.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO ) { Abc_Obj_t * pLatch, * pTerm; // add the BO terminal pTerm = Abc_NtkCreateBi( pNtk ); Abc_ObjAddFanin( pTerm, pNetLI ); // add the latch box pLatch = Abc_NtkCreateLatch( pNtk ); Abc_ObjAddFanin( pLatch, pTerm ); // add the BI terminal pTerm = Abc_NtkCreateBo( pNtk ); Abc_ObjAddFanin( pTerm, pLatch ); // get the LO net Abc_ObjAddFanin( pNetLO, pTerm ); // set latch name Abc_ObjAssignName( pLatch, Abc_ObjName(pNetLO), "L" ); Abc_LatchSetInitDc( pLatch ); return pLatch; } /**Function************************************************************* Synopsis [Creates inverter and returns its net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) { Abc_Obj_t * pObj; pObj = Abc_NtkCreateNodeInv( pNtk, pNet ); pNet = Abc_NtkCreateNet( pNtk ); Abc_ObjAddFanin( pNet, pObj ); return pNet; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/verFormula.c000066400000000000000000000374411300674244400240410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [verFormula.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Formula parser to read Verilog assign statements.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 19, 2006.] Revision [$Id: verFormula.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the list of operation symbols to be used in expressions #define VER_PARSE_SYM_OPEN '(' // opening parenthesis #define VER_PARSE_SYM_CLOSE ')' // closing parenthesis #define VER_PARSE_SYM_CONST0 '0' // constant 0 #define VER_PARSE_SYM_CONST1 '1' // constant 1 #define VER_PARSE_SYM_NEGBEF1 '!' // negation before the variable #define VER_PARSE_SYM_NEGBEF2 '~' // negation before the variable #define VER_PARSE_SYM_AND '&' // logic AND #define VER_PARSE_SYM_OR '|' // logic OR #define VER_PARSE_SYM_XOR '^' // logic XOR #define VER_PARSE_SYM_MUX1 '?' // first symbol of MUX #define VER_PARSE_SYM_MUX2 ':' // second symbol of MUX // the list of opcodes (also specifying operation precedence) #define VER_PARSE_OPER_NEG 7 // negation (highest precedence) #define VER_PARSE_OPER_AND 6 // logic AND #define VER_PARSE_OPER_XOR 5 // logic EXOR (a'b | ab') #define VER_PARSE_OPER_OR 4 // logic OR #define VER_PARSE_OPER_EQU 3 // equvalence (a'b'| ab ) #define VER_PARSE_OPER_MUX 2 // MUX(a,b,c) (ab | a'c ) #define VER_PARSE_OPER_MARK 1 // OpStack token standing for an opening parenthesis // these are values of the internal Flag #define VER_PARSE_FLAG_START 1 // after the opening parenthesis #define VER_PARSE_FLAG_VAR 2 // after operation is received #define VER_PARSE_FLAG_OPER 3 // after operation symbol is received #define VER_PARSE_FLAG_ERROR 4 // when error is detected static Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ); static int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Parser of the formula encountered in assign statements.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ) { char * pTemp; Hop_Obj_t * bFunc, * bTemp; int nParans, Flag; int Oper, Oper1, Oper2; int v; // clear the stacks and the names Vec_PtrClear( vNames ); Vec_PtrClear( vStackFn ); Vec_IntClear( vStackOp ); if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1\'b0") ) return Hop_ManConst0((Hop_Man_t *)pMan); if ( !strcmp(pFormula, "1") || !strcmp(pFormula, "1\'b1") ) return Hop_ManConst1((Hop_Man_t *)pMan); // make sure that the number of opening and closing parentheses is the same nParans = 0; for ( pTemp = pFormula; *pTemp; pTemp++ ) if ( *pTemp == '(' ) nParans++; else if ( *pTemp == ')' ) nParans--; if ( nParans != 0 ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parentheses ()." ); return NULL; } // add parentheses pTemp = pFormula + strlen(pFormula) + 2; *pTemp-- = 0; *pTemp = ')'; while ( --pTemp != pFormula ) *pTemp = *(pTemp - 1); *pTemp = '('; // perform parsing Flag = VER_PARSE_FLAG_START; for ( pTemp = pFormula; *pTemp; pTemp++ ) { switch ( *pTemp ) { // skip all spaces, tabs, and end-of-lines case ' ': case '\t': case '\r': case '\n': continue; /* // treat Constant 0 as a variable case VER_PARSE_SYM_CONST0: Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( Hop_ManConst0(pMan) ); if ( Flag == VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." ); Flag = VER_PARSE_FLAG_ERROR; break; } Flag = VER_PARSE_FLAG_VAR; break; // the same for Constant 1 case VER_PARSE_SYM_CONST1: Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( Hop_ManConst1(pMan) ); if ( Flag == VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." ); Flag = VER_PARSE_FLAG_ERROR; break; } Flag = VER_PARSE_FLAG_VAR; break; */ case VER_PARSE_SYM_NEGBEF1: case VER_PARSE_SYM_NEGBEF2: if ( Flag == VER_PARSE_FLAG_VAR ) {// if NEGBEF follows a variable, AND is assumed sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." ); Flag = VER_PARSE_FLAG_ERROR; break; } Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG ); break; case VER_PARSE_SYM_AND: case VER_PARSE_SYM_OR: case VER_PARSE_SYM_XOR: case VER_PARSE_SYM_MUX1: case VER_PARSE_SYM_MUX2: if ( Flag != VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." ); Flag = VER_PARSE_FLAG_ERROR; break; } if ( *pTemp == VER_PARSE_SYM_AND ) Vec_IntPush( vStackOp, VER_PARSE_OPER_AND ); else if ( *pTemp == VER_PARSE_SYM_OR ) Vec_IntPush( vStackOp, VER_PARSE_OPER_OR ); else if ( *pTemp == VER_PARSE_SYM_XOR ) Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR ); else if ( *pTemp == VER_PARSE_SYM_MUX1 ) Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); // else if ( *pTemp == VER_PARSE_SYM_MUX2 ) // Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); Flag = VER_PARSE_FLAG_OPER; break; case VER_PARSE_SYM_OPEN: if ( Flag == VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a parenthesis." ); Flag = VER_PARSE_FLAG_ERROR; break; } Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK ); // after an opening bracket, it feels like starting over again Flag = VER_PARSE_FLAG_START; break; case VER_PARSE_SYM_CLOSE: if ( Vec_IntSize( vStackOp ) ) { while ( 1 ) { if ( !Vec_IntSize( vStackOp ) ) { sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening parenthesis\n" ); Flag = VER_PARSE_FLAG_ERROR; break; } Oper = Vec_IntPop( vStackOp ); if ( Oper == VER_PARSE_OPER_MARK ) break; // skip the second MUX operation // if ( Oper == VER_PARSE_OPER_MUX2 ) // { // Oper = Vec_IntPop( vStackOp ); // assert( Oper == VER_PARSE_OPER_MUX1 ); // } // perform the given operation if ( Ver_FormulaParserTopOper( (Hop_Man_t *)pMan, vStackFn, Oper ) == NULL ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); return NULL; } } } else { sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening parenthesis\n" ); Flag = VER_PARSE_FLAG_ERROR; break; } if ( Flag != VER_PARSE_FLAG_ERROR ) Flag = VER_PARSE_FLAG_VAR; break; default: // scan the next name v = Ver_FormulaParserFindVar( pTemp, vNames ); if ( *pTemp == '\\' ) pTemp++; pTemp += (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*v ) - 1; // assume operation AND, if vars follow one another if ( Flag == VER_PARSE_FLAG_VAR ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." ); return NULL; } bTemp = Hop_IthVar( (Hop_Man_t *)pMan, v ); Vec_PtrPush( vStackFn, bTemp ); // Cudd_Ref( bTemp ); Flag = VER_PARSE_FLAG_VAR; break; } if ( Flag == VER_PARSE_FLAG_ERROR ) break; // error exit else if ( Flag == VER_PARSE_FLAG_START ) continue; // go on parsing else if ( Flag == VER_PARSE_FLAG_VAR ) while ( 1 ) { // check if there are negations in the OpStack if ( !Vec_IntSize(vStackOp) ) break; Oper = Vec_IntPop( vStackOp ); if ( Oper != VER_PARSE_OPER_NEG ) { Vec_IntPush( vStackOp, Oper ); break; } else { // Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) ); Vec_PtrPush( vStackFn, Hop_Not((Hop_Obj_t *)Vec_PtrPop(vStackFn)) ); } } else // if ( Flag == VER_PARSE_FLAG_OPER ) while ( 1 ) { // execute all the operations in the OpStack // with precedence higher or equal than the last one Oper1 = Vec_IntPop( vStackOp ); // the last operation if ( !Vec_IntSize(vStackOp) ) { // if it is the only operation, push it back Vec_IntPush( vStackOp, Oper1 ); break; } Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) ) { // if Oper2 precedence is higher or equal, execute it if ( Ver_FormulaParserTopOper( (Hop_Man_t *)pMan, vStackFn, Oper2 ) == NULL ) { sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); return NULL; } Vec_IntPush( vStackOp, Oper1 ); // push the last operation back } else { // if Oper2 precedence is lower, push them back and done Vec_IntPush( vStackOp, Oper2 ); Vec_IntPush( vStackOp, Oper1 ); break; } } } if ( Flag != VER_PARSE_FLAG_ERROR ) { if ( Vec_PtrSize(vStackFn) ) { bFunc = (Hop_Obj_t *)Vec_PtrPop(vStackFn); if ( !Vec_PtrSize(vStackFn) ) if ( !Vec_IntSize(vStackOp) ) { // Cudd_Deref( bFunc ); return bFunc; } else sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" ); else sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" ); } else sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" ); } // Cudd_Ref( bFunc ); // Cudd_RecursiveDeref( dd, bFunc ); return NULL; } /**Function************************************************************* Synopsis [Performs the operation on the top entries in the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ) { Hop_Obj_t * bArg0, * bArg1, * bArg2, * bFunc; // perform the given operation bArg2 = (Hop_Obj_t *)Vec_PtrPop( vStackFn ); bArg1 = (Hop_Obj_t *)Vec_PtrPop( vStackFn ); if ( Oper == VER_PARSE_OPER_AND ) bFunc = Hop_And( pMan, bArg1, bArg2 ); else if ( Oper == VER_PARSE_OPER_XOR ) bFunc = Hop_Exor( pMan, bArg1, bArg2 ); else if ( Oper == VER_PARSE_OPER_OR ) bFunc = Hop_Or( pMan, bArg1, bArg2 ); else if ( Oper == VER_PARSE_OPER_EQU ) bFunc = Hop_Not( Hop_Exor( pMan, bArg1, bArg2 ) ); else if ( Oper == VER_PARSE_OPER_MUX ) { bArg0 = (Hop_Obj_t *)Vec_PtrPop( vStackFn ); // bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 ); Cudd_Ref( bFunc ); bFunc = Hop_Mux( pMan, bArg0, bArg1, bArg2 ); // Cudd_RecursiveDeref( dd, bArg0 ); // Cudd_Deref( bFunc ); } else return NULL; // Cudd_Ref( bFunc ); // Cudd_RecursiveDeref( dd, bArg1 ); // Cudd_RecursiveDeref( dd, bArg2 ); Vec_PtrPush( vStackFn, bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Returns the index of the new variable found.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ) { char * pTemp, * pTemp2; int nLength, nLength2, i; // start the string pTemp = pString; // find the end of the string delimited by other characters if ( *pTemp == '\\' ) { pString++; while ( *pTemp && *pTemp != ' ' ) pTemp++; } else { while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' && *pTemp != '\r' && *pTemp != '\n' && *pTemp != ',' && *pTemp != '}' && *pTemp != VER_PARSE_SYM_OPEN && *pTemp != VER_PARSE_SYM_CLOSE && *pTemp != VER_PARSE_SYM_NEGBEF1 && *pTemp != VER_PARSE_SYM_NEGBEF2 && *pTemp != VER_PARSE_SYM_AND && *pTemp != VER_PARSE_SYM_OR && *pTemp != VER_PARSE_SYM_XOR && *pTemp != VER_PARSE_SYM_MUX1 && *pTemp != VER_PARSE_SYM_MUX2 ) pTemp++; } // look for this string in the array nLength = pTemp - pString; for ( i = 0; i < Vec_PtrSize(vNames)/2; i++ ) { nLength2 = (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*i + 0 ); if ( nLength2 != nLength ) continue; pTemp2 = (char *)Vec_PtrEntry( vNames, 2*i + 1 ); if ( strncmp( pString, pTemp2, nLength ) ) continue; return i; } // could not find - add and return the number Vec_PtrPush( vNames, (void *)(ABC_PTRUINT_T)nLength ); Vec_PtrPush( vNames, pString ); return i; } /**Function************************************************************* Synopsis [Returns the AIG representation of the reduction formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ) { Hop_Obj_t * pRes = NULL; int v, fCompl; char Symbol; // get the operation Symbol = *pFormula++; fCompl = ( Symbol == '~' ); if ( fCompl ) Symbol = *pFormula++; // check the operation if ( Symbol != '&' && Symbol != '|' && Symbol != '^' ) { sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol ); return NULL; } // skip the brace while ( *pFormula++ != '{' ); // parse the names Vec_PtrClear( vNames ); while ( *pFormula != '}' ) { v = Ver_FormulaParserFindVar( pFormula, vNames ); pFormula += (int)(ABC_PTRUINT_T)Vec_PtrEntry( vNames, 2*v ); while ( *pFormula == ' ' || *pFormula == ',' ) pFormula++; } // compute the function if ( Symbol == '&' ) pRes = Hop_CreateAnd( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 ); else if ( Symbol == '|' ) pRes = Hop_CreateOr( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 ); else if ( Symbol == '^' ) pRes = Hop_CreateExor( (Hop_Man_t *)pMan, Vec_PtrSize(vNames)/2 ); return Hop_NotCond( pRes, fCompl ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/verParse.c000066400000000000000000000072721300674244400235050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [verParse.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Performs some Verilog parsing tasks.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 19, 2006.] Revision [$Id: verParse.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Skips the comments of they are present.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_ParseSkipComments( Ver_Man_t * pMan ) { Ver_Stream_t * p = pMan->pReader; char Symbol; // skip spaces Ver_StreamSkipChars( p, " \t\n\r" ); if ( !Ver_StreamIsOkey(pMan->pReader) ) return 1; // read the first symbol Symbol = Ver_StreamScanChar( p ); if ( Symbol != '/' ) return 1; Ver_StreamPopChar( p ); // read the second symbol Symbol = Ver_StreamScanChar( p ); if ( Symbol == '/' ) { // skip till the end of line Ver_StreamSkipToChars( p, "\n" ); return Ver_ParseSkipComments( pMan ); } if ( Symbol == '*' ) { // skip till the next occurrence of */ Ver_StreamPopChar( p ); do { Ver_StreamSkipToChars( p, "*" ); Ver_StreamPopChar( p ); } while ( Ver_StreamScanChar( p ) != '/' ); Ver_StreamPopChar( p ); return Ver_ParseSkipComments( pMan ); } sprintf( pMan->sError, "Cannot parse after symbol \"/\"." ); Ver_ParsePrintErrorMessage( pMan ); return 0; } /**Function************************************************************* Synopsis [Parses a Verilog name that can be being with a slash.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ver_ParseGetName( Ver_Man_t * pMan ) { Ver_Stream_t * p = pMan->pReader; char Symbol; char * pWord; pMan->fNameLast = 0; if ( !Ver_StreamIsOkey(p) ) return NULL; if ( !Ver_ParseSkipComments( pMan ) ) return NULL; Symbol = Ver_StreamScanChar( p ); if ( Symbol == '\\' ) { pMan->fNameLast = 1; Ver_StreamPopChar( p ); pWord = Ver_StreamGetWord( p, " \r\n" ); Ver_StreamSkipChars( p, " \r\n" ); if ( Ver_StreamScanChar(p) == '[' ) { char This, * pEnd = pWord + strlen( pWord ); while ( (This = Ver_StreamPopChar(p)) != ']' ) *pEnd++ = This; *pEnd++ = This; *pEnd = 0; } } else pWord = Ver_StreamGetWord( p, " \t\n\r(),;" ); if ( Ver_StreamIsOkey(p) && !Ver_ParseSkipComments( pMan ) ) return NULL; return pWord; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/verStream.c000066400000000000000000000326271300674244400236700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [verStream.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Input file stream, which knows nothing about Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 19, 2006.] Revision [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define VER_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory #define VER_OFFSET_SIZE 65536 // 64K - load new data when less than this is left #define VER_WORD_SIZE 65536 // 64K - the largest token that can be returned #define VER_MINIMUM(a,b) (((a) < (b))? (a) : (b)) struct Ver_Stream_t_ { // the input file char * pFileName; // the input file name FILE * pFile; // the input file pointer iword nFileSize; // the total number of bytes in the file iword nFileRead; // the number of bytes currently read from file iword nLineCounter; // the counter of lines processed // temporary storage for data iword nBufferSize; // the size of the buffer char * pBuffer; // the buffer char * pBufferCur; // the current reading position char * pBufferEnd; // the first position not used by currently loaded data char * pBufferStop; // the position where loading new data will be done // tokens given to the user char pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parentheses) int nChars; // the total number of characters in the word // status of the parser int fStop; // this flag goes high when the end of file is reached }; static void Ver_StreamReload( Ver_Stream_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the file reader for the given file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ver_Stream_t * Ver_StreamAlloc( char * pFileName ) { Ver_Stream_t * p; FILE * pFile; int nCharsToRead; int RetValue; // check if the file can be opened pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName ); return NULL; } // start the file reader p = ABC_ALLOC( Ver_Stream_t, 1 ); memset( p, 0, sizeof(Ver_Stream_t) ); p->pFileName = pFileName; p->pFile = pFile; // get the file size, in bytes fseek( pFile, 0, SEEK_END ); p->nFileSize = ftell( pFile ); rewind( pFile ); // allocate the buffer p->pBuffer = ABC_ALLOC( char, VER_BUFFER_SIZE+1 ); p->nBufferSize = VER_BUFFER_SIZE; p->pBufferCur = p->pBuffer; // determine how many chars to read nCharsToRead = VER_MINIMUM(p->nFileSize, VER_BUFFER_SIZE); // load the first part into the buffer RetValue = fread( p->pBuffer, nCharsToRead, 1, p->pFile ); p->nFileRead = nCharsToRead; // set the ponters to the end and the stopping point p->pBufferEnd = p->pBuffer + nCharsToRead; p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; // start the arrays p->nLineCounter = 1; // 1-based line counting return p; } /**Function************************************************************* Synopsis [Loads new data into the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_StreamReload( Ver_Stream_t * p ) { int nCharsUsed, nCharsToRead; int RetValue; assert( !p->fStop ); assert( p->pBufferCur > p->pBufferStop ); assert( p->pBufferCur < p->pBufferEnd ); // figure out how many chars are still not processed nCharsUsed = p->pBufferEnd - p->pBufferCur; // move the remaining data to the beginning of the buffer memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); p->pBufferCur = p->pBuffer; // determine how many chars we will read nCharsToRead = VER_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); // read the chars RetValue = fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); p->nFileRead += nCharsToRead; // set the ponters to the end and the stopping point p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; } /**Function************************************************************* Synopsis [Stops the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_StreamFree( Ver_Stream_t * p ) { if ( p->pFile ) fclose( p->pFile ); ABC_FREE( p->pBuffer ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the file size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ver_StreamGetFileName( Ver_Stream_t * p ) { return p->pFileName; } /**Function************************************************************* Synopsis [Returns the file size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_StreamGetFileSize( Ver_Stream_t * p ) { return p->nFileSize; } /**Function************************************************************* Synopsis [Returns the current reading position.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_StreamGetCurPosition( Ver_Stream_t * p ) { return p->nFileRead - (p->pBufferEnd - p->pBufferCur); } /**Function************************************************************* Synopsis [Returns the line number for the given token.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_StreamGetLineNumber( Ver_Stream_t * p ) { return p->nLineCounter; } /**Function************************************************************* Synopsis [Returns current symbol.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_StreamIsOkey( Ver_Stream_t * p ) { return !p->fStop; } /**Function************************************************************* Synopsis [Returns current symbol.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char Ver_StreamScanChar( Ver_Stream_t * p ) { assert( !p->fStop ); return *p->pBufferCur; } /**Function************************************************************* Synopsis [Returns current symbol and moves to the next.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char Ver_StreamPopChar( Ver_Stream_t * p ) { assert( !p->fStop ); // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Ver_StreamReload( p ); // check if there are symbols left if ( p->pBufferCur == p->pBufferEnd ) // end of file { p->fStop = 1; return -1; } // count the lines if ( *p->pBufferCur == '\n' ) p->nLineCounter++; return *p->pBufferCur++; } /**Function************************************************************* Synopsis [Skips the current symbol and all symbols from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ) { char * pChar, * pTemp; assert( !p->fStop ); assert( pCharsToSkip != NULL ); // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Ver_StreamReload( p ); // skip the symbols for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) { // skip symbols as long as they are in the list for ( pTemp = pCharsToSkip; *pTemp; pTemp++ ) if ( *pChar == *pTemp ) break; if ( *pTemp == 0 ) // pChar is not found in the list { p->pBufferCur = pChar; return; } // count the lines if ( *pChar == '\n' ) p->nLineCounter++; } // the file is finished or the last part continued // through VER_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { p->fStop = 1; return; } printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName ); } /**Function************************************************************* Synopsis [Skips all symbols until encountering one from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ) { char * pChar, * pTemp; assert( !p->fStop ); assert( pCharsToStop != NULL ); // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Ver_StreamReload( p ); // skip the symbols for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) { // skip symbols as long as they are NOT in the list for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) if ( *pChar == *pTemp ) break; if ( *pTemp == 0 ) // pChar is not found in the list { // count the lines if ( *pChar == '\n' ) p->nLineCounter++; continue; } // the symbol is found - move position and return p->pBufferCur = pChar; return; } // the file is finished or the last part continued // through VER_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { p->fStop = 1; return; } printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName ); } /**Function************************************************************* Synopsis [Returns current word delimited by the set of symbols.] Description [Modifies the stream by inserting 0 at the first encounter of one of the symbols in the list.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ) { char * pChar, * pTemp; if ( p->fStop ) return NULL; assert( pCharsToStop != NULL ); // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Ver_StreamReload( p ); // skip the symbols p->nChars = 0; for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) { // skip symbols as long as they are NOT in the list for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) if ( *pChar == *pTemp ) break; if ( *pTemp == 0 ) // pChar is not found in the list { p->pChars[p->nChars++] = *pChar; if ( p->nChars == VER_WORD_SIZE ) { printf( "Ver_StreamGetWord(): The buffer size is exceeded.\n" ); return NULL; } // count the lines if ( *pChar == '\n' ) p->nLineCounter++; continue; } // the symbol is found - move the position, set the word end, return the word p->pBufferCur = pChar; p->pChars[p->nChars] = 0; return p->pChars; } // the file is finished or the last part continued // through VER_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { p->fStop = 1; p->pChars[p->nChars] = 0; return p->pChars; } printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/verWords.c000066400000000000000000000027251300674244400235270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [verWords.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Handles keywords that are currently supported.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 19, 2006.] Revision [$Id: verWords.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/ver/ver_.c000066400000000000000000000027141300674244400226450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ver_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Parses several flavors of structural Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 19, 2006.] Revision [$Id: ver_.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/000077500000000000000000000000001300674244400215335ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/module.make000066400000000000000000000004201300674244400236530ustar00rootroot00000000000000SRC += src/base/wlc/wlcAbs.c \ src/base/wlc/wlcAbc.c \ src/base/wlc/wlcBlast.c \ src/base/wlc/wlcCom.c \ src/base/wlc/wlcNtk.c \ src/base/wlc/wlcReadSmt.c \ src/base/wlc/wlcReadVer.c \ src/base/wlc/wlcSim.c \ src/base/wlc/wlcStdin.c \ src/base/wlc/wlcWriteVer.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlc.c000066400000000000000000000232231300674244400224660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Parses several flavors of word-level Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlc.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_GenerateCodeMax4( int nBits ) { int nWidth, nSteps, i; FILE * pFile = fopen( "max4.v", "wb" ); if ( pFile == NULL ) return; for ( nSteps = 0, nWidth = 1; nWidth < nBits; nWidth *= 3, nSteps++ ); fprintf( pFile, "module max4 ( a, b, c, d, res, addr );\n\n" ); fprintf( pFile, " input [%d:0] a, b, c, d;\n", nBits-1 ); fprintf( pFile, " output [%d:0] res;\n", nBits-1 ); fprintf( pFile, " output [1:0] addr;\n\n" ); fprintf( pFile, " wire [%d:0] A = a;\n", nWidth-1 ); fprintf( pFile, " wire [%d:0] B = b;\n", nWidth-1 ); fprintf( pFile, " wire [%d:0] C = c;\n", nWidth-1 ); fprintf( pFile, " wire [%d:0] D = d;\n\n", nWidth-1 ); fprintf( pFile, " wire AB, AC, AD, BC, BD, CD;\n\n" ); fprintf( pFile, " comp( A, B, AB );\n" ); fprintf( pFile, " comp( A, C, AC );\n" ); fprintf( pFile, " comp( A, D, AD );\n" ); fprintf( pFile, " comp( B, C, BC );\n" ); fprintf( pFile, " comp( B, D, BD );\n" ); fprintf( pFile, " comp( C, D, CD );\n\n" ); fprintf( pFile, " assign addr = AB ? (CD ? (AC ? 2\'b00 : 2\'b10) : (AD ? 2\'b00 : 2\'b11)) : (CD ? (BC ? 2\'b01 : 2\'b10) : (BD ? 2\'b01 : 2\'b11));\n\n" ); fprintf( pFile, " assign res = addr[1] ? (addr[1] ? d : c) : (addr[0] ? b : a);\n\n" ); fprintf( pFile, "endmodule\n\n\n" ); fprintf( pFile, "module comp ( a, b, res );\n\n" ); fprintf( pFile, " input [%d:0] a, b;\n", nWidth-1 ); fprintf( pFile, " output res;\n" ); fprintf( pFile, " wire res2;\n\n" ); fprintf( pFile, " wire [%d:0] A = a & ~b;\n", nWidth-1 ); fprintf( pFile, " wire [%d:0] B = ~a & b;\n\n", nWidth-1 ); fprintf( pFile, " comp0( A, B, res, res2 );\n\n" ); fprintf( pFile, "endmodule\n\n\n" ); for ( i = 0; i < nSteps; i++ ) { fprintf( pFile, "module comp%d ( a, b, yes, no );\n\n", i ); fprintf( pFile, " input [%d:0] a, b;\n", nWidth-1 ); fprintf( pFile, " output yes, no;\n\n", nWidth/3-1 ); fprintf( pFile, " wire [2:0] y, n;\n\n" ); if ( i == nSteps - 1 ) { fprintf( pFile, " assign y = a;\n" ); fprintf( pFile, " assign n = b;\n\n" ); } else { fprintf( pFile, " wire [%d:0] A0 = a[%d:%d];\n", nWidth/3-1, nWidth/3-1, 0 ); fprintf( pFile, " wire [%d:0] A1 = a[%d:%d];\n", nWidth/3-1, 2*nWidth/3-1, nWidth/3 ); fprintf( pFile, " wire [%d:0] A2 = a[%d:%d];\n\n", nWidth/3-1, nWidth-1, 2*nWidth/3 ); fprintf( pFile, " wire [%d:0] B0 = b[%d:%d];\n", nWidth/3-1, nWidth/3-1, 0 ); fprintf( pFile, " wire [%d:0] B1 = b[%d:%d];\n", nWidth/3-1, 2*nWidth/3-1, nWidth/3 ); fprintf( pFile, " wire [%d:0] B2 = b[%d:%d];\n\n", nWidth/3-1, nWidth-1, 2*nWidth/3 ); fprintf( pFile, " comp%d( A0, B0, y[0], n[0] );\n", i+1 ); fprintf( pFile, " comp%d( A1, B1, y[1], n[1] );\n", i+1 ); fprintf( pFile, " comp%d( A2, B2, y[2], n[2] );\n\n", i+1 ); } fprintf( pFile, " assign yes = y[0] | (~y[0] & ~n[0] & y[1]) | (~y[0] & ~n[0] & ~y[1] & ~n[1] & y[2]);\n" ); fprintf( pFile, " assign no = n[0] | (~y[0] & ~n[0] & n[1]) | (~y[0] & ~n[0] & ~y[1] & ~n[1] & n[2]);\n\n" ); fprintf( pFile, "endmodule\n\n\n" ); nWidth /= 3; } fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_BlastFullAdderCtrlCnf( sat_solver * pSat, int a, int ac, int b, int c, int * pc, int * ps, int * piVars ) { int Cnf[12][6] = { // xabc cs // abc cs { -1, 0, 0, 0, 0, 0 }, // -000 00 // 000 00 { -1, 0, 0, 1, 0, 1 }, // -001 01 // 001 01 { -1, 0, 1, 0, 0, 1 }, // -010 01 // 010 01 { -1, 0, 1, 1, 1, 0 }, // -011 10 // 011 10 { 0,-1, 0, 0, 0, 0 }, // 0-00 00 { 0,-1, 0, 1, 0, 1 }, // 0-01 01 { 0,-1, 1, 0, 0, 1 }, // 0-10 01 { 0,-1, 1, 1, 1, 0 }, // 0-11 10 { 1, 1, 0, 0, 0, 1 }, // 1100 01 // 100 01 { 1, 1, 0, 1, 1, 0 }, // 1101 10 // 101 10 { 1, 1, 1, 0, 1, 0 }, // 1110 10 // 110 10 { 1, 1, 1, 1, 1, 1 } // 1111 11 // 111 11 }; int pVars[6] = {a, ac, b, c, *piVars, *piVars+1}; int i, v, nLits, pLits[6]; for ( i = 0; i < 12; i++ ) { nLits = 0; for ( v = 0; v < 6; v++ ) { if ( Cnf[i][v] == -1 ) continue; if ( pVars[v] == 0 ) // const 0 { if ( Cnf[i][v] == 0 ) continue; if ( Cnf[i][v] == 1 ) break; } if ( pVars[v] == -1 ) // const -1 { if ( Cnf[i][v] == 0 ) break; if ( Cnf[i][v] == 1 ) continue; } pLits[nLits++] = Abc_Var2Lit( pVars[v], Cnf[i][v] ); } if ( v < 6 ) continue; assert( nLits > 2 ); sat_solver_addclause( pSat, pLits, pLits + nLits ); } *pc = (*piVars)++; *ps = (*piVars)++; } void Wlc_BlastMultiplierCnf( sat_solver * pSat, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vTemp, Vec_Int_t * vRes, int * piVars ) { int * pRes, * pArgC, * pArgS, a, b, Carry = 0; assert( nArgA > 0 && nArgB > 0 ); // prepare result Vec_IntFill( vRes, nArgA + nArgB, 0 ); pRes = Vec_IntArray( vRes ); // prepare intermediate storage Vec_IntFill( vTemp, 2 * nArgA, 0 ); pArgC = Vec_IntArray( vTemp ); pArgS = pArgC + nArgA; // create matrix for ( b = 0; b < nArgB; b++ ) for ( a = 0; a < nArgA; a++ ) Wlc_BlastFullAdderCtrlCnf( pSat, pArgA[a], pArgB[b], pArgS[a], pArgC[a], &pArgC[a], a ? &pArgS[a-1] : &pRes[b], piVars ); // final addition pArgS[nArgA-1] = 0; for ( a = 0; a < nArgA; a++ ) Wlc_BlastFullAdderCtrlCnf( pSat, -1, pArgC[a], pArgS[a], Carry, &Carry, &pRes[nArgB+a], piVars ); } sat_solver * Wlc_BlastMultiplierCnfMain( int nBits ) { Vec_Int_t * vRes1 = Vec_IntAlloc( 2*nBits ); Vec_Int_t * vRes2 = Vec_IntAlloc( 2*nBits ); Vec_Int_t * vTemp = Vec_IntAlloc( 2*nBits ); int * pArgA = ABC_ALLOC( int, nBits ); int * pArgB = ABC_ALLOC( int, nBits ); int i, Ent1, Ent2, nVars = 1 + 2*nBits; int nVarsAll = 1 + 4*nBits + 4*nBits*(nBits + 1); sat_solver * pSat = sat_solver_new(); sat_solver_setnvars( pSat, nVarsAll ); for ( i = 0; i < nBits; i++ ) pArgA[i] = 1 + i, pArgB[i] = 1 + nBits + i; Wlc_BlastMultiplierCnf( pSat, pArgA, pArgB, nBits, nBits, vTemp, vRes1, &nVars ); for ( i = 0; i < nBits; i++ ) pArgA[i] = 1 + nBits + i, pArgB[i] = 1 + i; Wlc_BlastMultiplierCnf( pSat, pArgA, pArgB, nBits, nBits, vTemp, vRes2, &nVars ); Vec_IntClear( vTemp ); Vec_IntForEachEntryTwo( vRes1, vRes2, Ent1, Ent2, i ) { Vec_IntPush( vTemp, Abc_Var2Lit(nVars, 0) ); sat_solver_add_xor( pSat, Ent1, Ent2, nVars++, 0 ); } assert( nVars == nVarsAll ); sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp) ); ABC_FREE( pArgA ); ABC_FREE( pArgB ); Vec_IntFree( vRes1 ); Vec_IntFree( vRes2 ); Vec_IntFree( vTemp ); return pSat; } void Wlc_BlastMultiplierCnfTest( int nBits ) { abctime clk = Abc_Clock(); sat_solver * pSat = Wlc_BlastMultiplierCnfMain( nBits ); int i, status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); Sat_SolverWriteDimacs( pSat, "test_mult.cnf", NULL, NULL, 0 ); for ( i = 0; i < sat_solver_nvars(pSat); i++ ) printf( "%d=%d ", i, sat_solver_var_value(pSat, i) ); printf( "\n" ); printf( "Verifying for %d bits: %s ", nBits, status == l_True ? "SAT" : "UNSAT" ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); sat_solver_delete( pSat ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlc.h000066400000000000000000000510651300674244400225000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlc.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlc.h,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__wlc__wlc_h #define ABC__base__wlc__wlc_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "misc/extra/extra.h" #include "misc/util/utilNam.h" #include "misc/mem/mem.h" #include "misc/extra/extra.h" #include "misc/util/utilTruth.h" #include "base/main/mainInt.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START // object types typedef enum { WLC_OBJ_NONE = 0, // 00: unknown WLC_OBJ_PI, // 01: primary input WLC_OBJ_PO, // 02: primary output (unused) WLC_OBJ_FO, // 03: flop output WLC_OBJ_FI, // 04: flop input (unused) WLC_OBJ_FF, // 05: flop (unused) WLC_OBJ_CONST, // 06: constant WLC_OBJ_BUF, // 07: buffer WLC_OBJ_MUX, // 08: multiplexer WLC_OBJ_SHIFT_R, // 09: shift right WLC_OBJ_SHIFT_RA, // 10: shift right (arithmetic) WLC_OBJ_SHIFT_L, // 11: shift left WLC_OBJ_SHIFT_LA, // 12: shift left (arithmetic) WLC_OBJ_ROTATE_R, // 13: rotate right WLC_OBJ_ROTATE_L, // 14: rotate left WLC_OBJ_BIT_NOT, // 15: bitwise NOT WLC_OBJ_BIT_AND, // 16: bitwise AND WLC_OBJ_BIT_OR, // 17: bitwise OR WLC_OBJ_BIT_XOR, // 18: bitwise XOR WLC_OBJ_BIT_NAND, // 19: bitwise AND WLC_OBJ_BIT_NOR, // 20: bitwise OR WLC_OBJ_BIT_NXOR, // 21: bitwise NXOR WLC_OBJ_BIT_SELECT, // 22: bit selection WLC_OBJ_BIT_CONCAT, // 23: bit concatenation WLC_OBJ_BIT_ZEROPAD, // 24: zero padding WLC_OBJ_BIT_SIGNEXT, // 25: sign extension WLC_OBJ_LOGIC_NOT, // 26: logic NOT WLC_OBJ_LOGIC_IMPL, // 27: logic implication WLC_OBJ_LOGIC_AND, // 28: logic AND WLC_OBJ_LOGIC_OR, // 29: logic OR WLC_OBJ_LOGIC_XOR, // 30: logic XOR WLC_OBJ_COMP_EQU, // 31: compare equal WLC_OBJ_COMP_NOTEQU, // 32: compare not equal WLC_OBJ_COMP_LESS, // 33: compare less WLC_OBJ_COMP_MORE, // 34: compare more WLC_OBJ_COMP_LESSEQU, // 35: compare less or equal WLC_OBJ_COMP_MOREEQU, // 36: compare more or equal WLC_OBJ_REDUCT_AND, // 37: reduction AND WLC_OBJ_REDUCT_OR, // 38: reduction OR WLC_OBJ_REDUCT_XOR, // 39: reduction XOR WLC_OBJ_REDUCT_NAND, // 40: reduction NAND WLC_OBJ_REDUCT_NOR, // 41: reduction NOR WLC_OBJ_REDUCT_NXOR, // 42: reduction NXOR WLC_OBJ_ARI_ADD, // 43: arithmetic addition WLC_OBJ_ARI_SUB, // 44: arithmetic subtraction WLC_OBJ_ARI_MULTI, // 45: arithmetic multiplier WLC_OBJ_ARI_DIVIDE, // 46: arithmetic division WLC_OBJ_ARI_REM, // 47: arithmetic remainder WLC_OBJ_ARI_MODULUS, // 48: arithmetic modulus WLC_OBJ_ARI_POWER, // 49: arithmetic power WLC_OBJ_ARI_MINUS, // 50: arithmetic minus WLC_OBJ_ARI_SQRT, // 51: integer square root WLC_OBJ_ARI_SQUARE, // 52: integer square WLC_OBJ_TABLE, // 53: bit table WLC_OBJ_NUMBER // 54: unused } Wlc_ObjType_t; // when adding new types, remember to update table Wlc_Names in "wlcNtk.c" // Unlike AIG managers and logic networks in ABC, this network treats POs and FIs // as attributes of internal nodes and *not* as separate types of objects. //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Wlc_Obj_t_ Wlc_Obj_t; struct Wlc_Obj_t_ // 24 bytes { unsigned Type : 6; // node type unsigned Signed : 1; // signed unsigned Mark : 1; // user mark unsigned fIsPo : 1; // this is PO unsigned fIsFi : 1; // this is FI unsigned fXConst : 1; // this is X-valued constant unsigned nFanins; // fanin count int End; // range end int Beg; // range begin union { int Fanins[2]; // fanin IDs int * pFanins[1]; }; }; typedef struct Wlc_Ntk_t_ Wlc_Ntk_t; struct Wlc_Ntk_t_ { char * pName; // model name char * pSpec; // input file name Vec_Int_t vPis; // primary inputs Vec_Int_t vPos; // primary outputs Vec_Int_t vCis; // combinational inputs Vec_Int_t vCos; // combinational outputs Vec_Int_t vFfs; // flops Vec_Int_t * vInits; // initial values char * pInits; // initial values int nObjs[WLC_OBJ_NUMBER]; // counter of objects of each type int nAnds[WLC_OBJ_NUMBER]; // counter of AND gates after blasting int fSmtLib; // the network comes from an SMT-LIB file // memory for objects Wlc_Obj_t * pObjs; int iObj; int nObjsAlloc; Mem_Flex_t * pMemFanin; Mem_Flex_t * pMemTable; Vec_Ptr_t * vTables; // object names Abc_Nam_t * pManName; // object names Vec_Int_t vNameIds; // object name IDs Vec_Int_t vValues; // value objects // object attributes int nTravIds; // counter of traversal IDs Vec_Int_t vTravIds; // trav IDs of the objects Vec_Int_t vCopies; // object first bits Vec_Int_t vBits; // object mapping into AIG nodes }; static inline int Wlc_NtkObjNum( Wlc_Ntk_t * p ) { return p->iObj - 1; } static inline int Wlc_NtkObjNumMax( Wlc_Ntk_t * p ) { return p->iObj; } static inline int Wlc_NtkPiNum( Wlc_Ntk_t * p ) { return Vec_IntSize(&p->vPis); } static inline int Wlc_NtkPoNum( Wlc_Ntk_t * p ) { return Vec_IntSize(&p->vPos); } static inline int Wlc_NtkCiNum( Wlc_Ntk_t * p ) { return Vec_IntSize(&p->vCis); } static inline int Wlc_NtkCoNum( Wlc_Ntk_t * p ) { return Vec_IntSize(&p->vCos); } static inline int Wlc_NtkFfNum( Wlc_Ntk_t * p ) { return Vec_IntSize(&p->vCis) - Vec_IntSize(&p->vPis); } static inline Wlc_Obj_t * Wlc_NtkObj( Wlc_Ntk_t * p, int Id ) { assert(Id > 0 && Id < p->nObjsAlloc); return p->pObjs + Id; } static inline Wlc_Obj_t * Wlc_NtkPi( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vPis, i) ); } static inline Wlc_Obj_t * Wlc_NtkPo( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vPos, i) ); } static inline Wlc_Obj_t * Wlc_NtkCi( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vCis, i) ); } static inline Wlc_Obj_t * Wlc_NtkCo( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vCos, i) ); } static inline Wlc_Obj_t * Wlc_NtkFf( Wlc_Ntk_t * p, int i ) { return Wlc_NtkObj( p, Vec_IntEntry(&p->vFfs, i) ); } static inline int Wlc_ObjIsPi( Wlc_Obj_t * p ) { return p->Type == WLC_OBJ_PI; } static inline int Wlc_ObjIsPo( Wlc_Obj_t * p ) { return p->fIsPo; } static inline int Wlc_ObjIsCi( Wlc_Obj_t * p ) { return p->Type == WLC_OBJ_PI || p->Type == WLC_OBJ_FO; } static inline int Wlc_ObjIsCo( Wlc_Obj_t * p ) { return p->fIsPo || p->fIsFi; } static inline int Wlc_ObjId( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { return pObj - p->pObjs; } static inline int Wlc_ObjCiId( Wlc_Obj_t * p ) { assert( Wlc_ObjIsCi(p) ); return p->Fanins[1]; } static inline int Wlc_ObjFaninNum( Wlc_Obj_t * p ) { return p->nFanins; } static inline int Wlc_ObjHasArray( Wlc_Obj_t * p ) { return p->nFanins > 2 || p->Type == WLC_OBJ_CONST || p->Type == WLC_OBJ_BIT_SELECT; } static inline int * Wlc_ObjFanins( Wlc_Obj_t * p ) { return Wlc_ObjHasArray(p) ? p->pFanins[0] : p->Fanins; } static inline int Wlc_ObjFaninId( Wlc_Obj_t * p, int i ) { return Wlc_ObjFanins(p)[i]; } static inline int Wlc_ObjFaninId0( Wlc_Obj_t * p ) { return Wlc_ObjFanins(p)[0]; } static inline int Wlc_ObjFaninId1( Wlc_Obj_t * p ) { return Wlc_ObjFanins(p)[1]; } static inline int Wlc_ObjFaninId2( Wlc_Obj_t * p ) { return Wlc_ObjFanins(p)[2]; } static inline Wlc_Obj_t * Wlc_ObjFanin( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, int i ) { return Wlc_NtkObj( p, Wlc_ObjFaninId(pObj, i) ); } static inline Wlc_Obj_t * Wlc_ObjFanin0( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { return Wlc_NtkObj( p, Wlc_ObjFaninId(pObj, 0) ); } static inline Wlc_Obj_t * Wlc_ObjFanin1( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { return Wlc_NtkObj( p, Wlc_ObjFaninId(pObj, 1) ); } static inline Wlc_Obj_t * Wlc_ObjFanin2( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { return Wlc_NtkObj( p, Wlc_ObjFaninId(pObj, 2) ); } static inline int Wlc_ObjRange( Wlc_Obj_t * p ) { return 1 + (p->End >= p->Beg ? p->End - p->Beg : p->Beg - p->End); } static inline int Wlc_ObjRangeEnd( Wlc_Obj_t * p ) { assert(p->Type == WLC_OBJ_BIT_SELECT); return p->pFanins[0][1]; } static inline int Wlc_ObjRangeBeg( Wlc_Obj_t * p ) { assert(p->Type == WLC_OBJ_BIT_SELECT); return p->pFanins[0][2]; } static inline int Wlc_ObjRangeIsReversed( Wlc_Obj_t * p ) { return p->End < p->Beg; } static inline int Wlc_ObjIsSigned( Wlc_Obj_t * p ) { return p->Signed; } static inline int Wlc_ObjIsSignedFanin01( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ){ return p->fSmtLib ? Wlc_ObjIsSigned(pObj) : (Wlc_ObjFanin0(p, pObj)->Signed && Wlc_ObjFanin1(p, pObj)->Signed); } static inline int Wlc_ObjIsSignedFanin0( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { return p->fSmtLib ? Wlc_ObjIsSigned(pObj) : Wlc_ObjFanin0(p, pObj)->Signed; } static inline int Wlc_ObjIsSignedFanin1( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { return p->fSmtLib ? Wlc_ObjIsSigned(pObj) : Wlc_ObjFanin1(p, pObj)->Signed; } static inline int Wlc_ObjSign( Wlc_Obj_t * p ) { return Abc_Var2Lit( Wlc_ObjRange(p), Wlc_ObjIsSigned(p) ); } static inline int * Wlc_ObjConstValue( Wlc_Obj_t * p ) { assert(p->Type == WLC_OBJ_CONST); return Wlc_ObjFanins(p); } static inline int Wlc_ObjTableId( Wlc_Obj_t * p ) { assert(p->Type == WLC_OBJ_TABLE); return p->Fanins[1]; } static inline word * Wlc_ObjTable( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { return (word *)Vec_PtrEntry( p->vTables, Wlc_ObjTableId(pObj) ); } static inline void Wlc_NtkCleanCopy( Wlc_Ntk_t * p ) { Vec_IntFill( &p->vCopies, p->nObjsAlloc, 0 ); } static inline int Wlc_NtkHasCopy( Wlc_Ntk_t * p ) { return Vec_IntSize( &p->vCopies ) > 0; } static inline void Wlc_ObjSetCopy( Wlc_Ntk_t * p, int iObj, int i ) { Vec_IntWriteEntry( &p->vCopies, iObj, i ); } static inline int Wlc_ObjCopy( Wlc_Ntk_t * p, int iObj ) { return Vec_IntEntry( &p->vCopies, iObj ); } static inline Wlc_Obj_t * Wlc_ObjCopyObj(Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, Wlc_Obj_t * pObj) {return Wlc_NtkObj(pNew, Wlc_ObjCopy(p, Wlc_ObjId(p, pObj))); } static inline void Wlc_NtkCleanNameId( Wlc_Ntk_t * p ) { Vec_IntFill( &p->vNameIds, p->nObjsAlloc, 0 ); } static inline int Wlc_NtkHasNameId( Wlc_Ntk_t * p ) { return Vec_IntSize( &p->vNameIds ) > 0; } static inline void Wlc_ObjSetNameId( Wlc_Ntk_t * p, int iObj, int i ) { Vec_IntWriteEntry( &p->vNameIds, iObj, i ); } static inline int Wlc_ObjNameId( Wlc_Ntk_t * p, int iObj ) { return Vec_IntEntry( &p->vNameIds, iObj ); } static inline Wlc_Obj_t * Wlc_ObjFoToFi( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { assert( pObj->Type == WLC_OBJ_FO ); return Wlc_NtkCo(p, Wlc_NtkCoNum(p) - Wlc_NtkCiNum(p) + Wlc_ObjCiId(pObj)); } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// #define Wlc_NtkForEachObj( p, pObj, i ) \ for ( i = 1; (i < Wlc_NtkObjNumMax(p)) && (((pObj) = Wlc_NtkObj(p, i)), 1); i++ ) #define Wlc_NtkForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && (((pObj) = Wlc_NtkObj(p, Vec_IntEntry(vVec, i))), 1); i++ ) #define Wlc_NtkForEachPi( p, pPi, i ) \ for ( i = 0; (i < Wlc_NtkPiNum(p)) && (((pPi) = Wlc_NtkPi(p, i)), 1); i++ ) #define Wlc_NtkForEachPo( p, pPo, i ) \ for ( i = 0; (i < Wlc_NtkPoNum(p)) && (((pPo) = Wlc_NtkPo(p, i)), 1); i++ ) #define Wlc_NtkForEachCi( p, pCi, i ) \ for ( i = 0; (i < Wlc_NtkCiNum(p)) && (((pCi) = Wlc_NtkCi(p, i)), 1); i++ ) #define Wlc_NtkForEachCo( p, pCo, i ) \ for ( i = 0; (i < Wlc_NtkCoNum(p)) && (((pCo) = Wlc_NtkCo(p, i)), 1); i++ ) #define Wlc_NtkForEachFf( p, pFf, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vFfs)) && (((pFf) = Wlc_NtkFf(p, i)), 1); i++ ) #define Wlc_ObjForEachFanin( pObj, iFanin, i ) \ for ( i = 0; (i < Wlc_ObjFaninNum(pObj)) && (((iFanin) = Wlc_ObjFaninId(pObj, i)), 1); i++ ) #define Wlc_ObjForEachFaninReverse( pObj, iFanin, i ) \ for ( i = Wlc_ObjFaninNum(pObj) - 1; (i >= 0) && (((iFanin) = Wlc_ObjFaninId(pObj, i)), 1); i-- ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== wlcAbs.c ========================================================*/ extern int Wlc_NtkPairIsUifable( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Wlc_Obj_t * pObj2 ); extern Vec_Int_t * Wlc_NtkCollectMultipliers( Wlc_Ntk_t * p ); extern Vec_Int_t * Wlc_NtkFindUifableMultiplierPairs( Wlc_Ntk_t * p ); extern Wlc_Ntk_t * Wlc_NtkAbstractNodes( Wlc_Ntk_t * pNtk, Vec_Int_t * vNodes ); extern Wlc_Ntk_t * Wlc_NtkUifNodePairs( Wlc_Ntk_t * pNtk, Vec_Int_t * vPairs ); /*=== wlcBlast.c ========================================================*/ extern Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, int nRange, int fGiaSimple, int fAddOutputs, int fBooth ); /*=== wlcCom.c ========================================================*/ extern void Wlc_SetNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk ); /*=== wlcNtk.c ========================================================*/ extern Wlc_Ntk_t * Wlc_NtkAlloc( char * pName, int nObjsAlloc ); extern int Wlc_ObjAlloc( Wlc_Ntk_t * p, int Type, int Signed, int End, int Beg ); extern int Wlc_ObjCreate( Wlc_Ntk_t * p, int Type, int Signed, int End, int Beg, Vec_Int_t * vFanins ); extern void Wlc_ObjSetCi( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ); extern void Wlc_ObjSetCo( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, int fFlopInput ); extern char * Wlc_ObjName( Wlc_Ntk_t * p, int iObj ); extern void Wlc_ObjUpdateType( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, int Type ); extern void Wlc_ObjAddFanins( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Int_t * vFanins ); extern void Wlc_NtkFree( Wlc_Ntk_t * p ); extern void Wlc_NtkPrintNodes( Wlc_Ntk_t * p, int Type ); extern void Wlc_NtkPrintStats( Wlc_Ntk_t * p, int fDistrib, int fVerbose ); extern Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p ); extern void Wlc_NtkTransferNames( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p ); extern Wlc_Ntk_t * Wlc_NtkDupSingleNodes( Wlc_Ntk_t * p ); /*=== wlcReadSmt.c ========================================================*/ extern Wlc_Ntk_t * Wlc_ReadSmtBuffer( char * pFileName, char * pBuffer, char * pLimit, int fOldParser, int fPrintTree ); extern Wlc_Ntk_t * Wlc_ReadSmt( char * pFileName, int fOldParser, int fPrintTree ); /*=== wlcSim.c ========================================================*/ extern Vec_Ptr_t * Wlc_NtkSimulate( Wlc_Ntk_t * p, Vec_Int_t * vNodes, int nWords, int nFrames ); extern void Wlc_NtkDeleteSim( Vec_Ptr_t * p ); /*=== wlcStdin.c ========================================================*/ extern int Wlc_StdinProcessSmt( Abc_Frame_t * pAbc, char * pCmd ); /*=== wlcReadVer.c ========================================================*/ extern Wlc_Ntk_t * Wlc_ReadVer( char * pFileName ); /*=== wlcWriteVer.c ========================================================*/ extern void Wlc_WriteVer( Wlc_Ntk_t * p, char * pFileName, int fAddCos, int fNoFlops ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcAbc.c000066400000000000000000000113031300674244400230700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcAbc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Parses several flavors of word-level Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcAbc.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkPrintInvStats( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv, int fVerbose ) { Wlc_Obj_t * pObj; int i, k, nNum, nRange, nBits = 0; Wlc_NtkForEachCi( pNtk, pObj, i ) { if ( pObj->Type != WLC_OBJ_FO ) continue; nRange = Wlc_ObjRange(pObj); for ( k = 0; k < nRange; k++ ) { nNum = Vec_IntEntry(vInv, nBits + k); if ( nNum ) break; } if ( k == nRange ) { nBits += nRange; continue; } printf( "%s[%d:%d] : ", Wlc_ObjName(pNtk, Wlc_ObjId(pNtk, pObj)), pObj->End, pObj->Beg ); for ( k = 0; k < nRange; k++ ) { nNum = Vec_IntEntry( vInv, nBits + k ); if ( nNum == 0 ) continue; printf( " [%d] -> %d", k, nNum ); } printf( "\n"); nBits += nRange; } //printf( "%d %d\n", Vec_IntSize(vInv), nBits ); assert( Vec_IntSize(vInv) == nBits ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Wlc_NtkGetInv( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv, Vec_Str_t * vSop, int fVerbose ) { Wlc_Obj_t * pObj; int i, k, nNum, nRange, nBits = 0; Abc_Ntk_t * pMainNtk = NULL; Abc_Obj_t * pMainObj, * pMainTemp; char Buffer[5000]; // start the network pMainNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); // duplicate the name and the spec pMainNtk->pName = Extra_UtilStrsav(pNtk->pName); // create primary inputs Wlc_NtkForEachCi( pNtk, pObj, i ) { if ( pObj->Type != WLC_OBJ_FO ) continue; nRange = Wlc_ObjRange(pObj); for ( k = 0; k < nRange; k++ ) { nNum = Vec_IntEntry(vInv, nBits + k); if ( nNum ) break; } if ( k == nRange ) { nBits += nRange; continue; } //printf( "%s[%d:%d] : ", Wlc_ObjName(pNtk, Wlc_ObjId(pNtk, pObj)), pObj->End, pObj->Beg ); for ( k = 0; k < nRange; k++ ) { nNum = Vec_IntEntry( vInv, nBits + k ); if ( nNum == 0 ) continue; //printf( " [%d] -> %d", k, nNum ); pMainObj = Abc_NtkCreatePi( pMainNtk ); sprintf( Buffer, "%s[%d]", Wlc_ObjName(pNtk, Wlc_ObjId(pNtk, pObj)), k ); Abc_ObjAssignName( pMainObj, Buffer, NULL ); } //printf( "\n"); nBits += nRange; } //printf( "%d %d\n", Vec_IntSize(vInv), nBits ); assert( Vec_IntSize(vInv) == nBits ); // create node pMainObj = Abc_NtkCreateNode( pMainNtk ); Abc_NtkForEachPi( pMainNtk, pMainTemp, i ) Abc_ObjAddFanin( pMainObj, pMainTemp ); pMainObj->pData = Abc_SopRegister( (Mem_Flex_t *)pMainNtk->pManFunc, Vec_StrArray(vSop) ); // create PO pMainTemp = Abc_NtkCreatePo( pMainNtk ); Abc_ObjAddFanin( pMainTemp, pMainObj ); Abc_ObjAssignName( pMainTemp, "inv", NULL ); return pMainNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcAbs.c000066400000000000000000000235651300674244400231250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcAbs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Abstraction for word-level networks.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcAbs.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Check if two objects have the same input/output signatures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Wlc_NtkPairIsUifable( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Wlc_Obj_t * pObj2 ) { Wlc_Obj_t * pFanin, * pFanin2; int k; if ( Wlc_ObjRange(pObj) != Wlc_ObjRange(pObj2) ) return 0; if ( Wlc_ObjIsSigned(pObj) != Wlc_ObjIsSigned(pObj2) ) return 0; if ( Wlc_ObjFaninNum(pObj) != Wlc_ObjFaninNum(pObj2) ) return 0; for ( k = 0; k < Wlc_ObjFaninNum(pObj); k++ ) { pFanin = Wlc_ObjFanin(p, pObj, k); pFanin2 = Wlc_ObjFanin(p, pObj2, k); if ( Wlc_ObjRange(pFanin) != Wlc_ObjRange(pFanin2) ) return 0; if ( Wlc_ObjIsSigned(pFanin) != Wlc_ObjIsSigned(pFanin2) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Collect IDs of the multipliers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Wlc_NtkCollectMultipliers( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i; Vec_Int_t * vBoxIds = Vec_IntAlloc( 100 ); Wlc_NtkForEachObj( p, pObj, i ) if ( pObj->Type == WLC_OBJ_ARI_MULTI ) Vec_IntPush( vBoxIds, i ); if ( Vec_IntSize( vBoxIds ) > 0 ) return vBoxIds; Vec_IntFree( vBoxIds ); return NULL; } /**Function************************************************************* Synopsis [Returns all pairs of uifable multipliers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Wlc_NtkFindUifableMultiplierPairs( Wlc_Ntk_t * p ) { Vec_Int_t * vMultis = Wlc_NtkCollectMultipliers( p ); Vec_Int_t * vPairs = Vec_IntAlloc( 2 ); Wlc_Obj_t * pObj, * pObj2; int i, k; // iterate through unique pairs Wlc_NtkForEachObjVec( vMultis, p, pObj, i ) Wlc_NtkForEachObjVec( vMultis, p, pObj2, k ) { if ( k == i ) break; if ( Wlc_NtkPairIsUifable( p, pObj, pObj2 ) ) { Vec_IntPush( vPairs, Wlc_ObjId(p, pObj) ); Vec_IntPush( vPairs, Wlc_ObjId(p, pObj2) ); } } Vec_IntFree( vMultis ); if ( Vec_IntSize( vPairs ) > 0 ) return vPairs; Vec_IntFree( vPairs ); return NULL; } /**Function************************************************************* Synopsis [Abstracts nodes by replacing their outputs with new PIs.] Description [If array is NULL, abstract all multipliers.] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Ntk_t * Wlc_NtkAbstractNodes( Wlc_Ntk_t * p, Vec_Int_t * vNodesInit ) { Vec_Int_t * vNodes = vNodesInit; Wlc_Ntk_t * pNew; Wlc_Obj_t * pObj; int i, k, iObj, iFanin; // get multipliers if not given if ( vNodes == NULL ) vNodes = Wlc_NtkCollectMultipliers( p ); if ( vNodes == NULL ) return NULL; // mark nodes Wlc_NtkForEachObjVec( vNodes, p, pObj, i ) pObj->Mark = 1; // iterate through the nodes in the DFS order Wlc_NtkCleanCopy( p ); Wlc_NtkForEachObj( p, pObj, i ) { if ( i == Vec_IntSize(&p->vCopies) ) break; if ( pObj->Mark ) { // clean pObj->Mark = 0; // add fresh PI with the same number of bits iObj = Wlc_ObjAlloc( p, WLC_OBJ_PI, Wlc_ObjIsSigned(pObj), Wlc_ObjRange(pObj) - 1, 0 ); } else { // update fanins Wlc_ObjForEachFanin( pObj, iFanin, k ) Wlc_ObjFanins(pObj)[k] = Wlc_ObjCopy(p, iFanin); // node to remain iObj = i; } Wlc_ObjSetCopy( p, i, iObj ); } // POs do not change in this procedure if ( vNodes != vNodesInit ) Vec_IntFree( vNodes ); // reconstruct topological order pNew = Wlc_NtkDupDfs( p ); Wlc_NtkTransferNames( pNew, p ); return pNew; } /**Function************************************************************* Synopsis [Adds UIF constraints to node pairs and updates POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Ntk_t * Wlc_NtkUifNodePairs( Wlc_Ntk_t * p, Vec_Int_t * vPairsInit ) { Vec_Int_t * vPairs = vPairsInit; Wlc_Ntk_t * pNew; Wlc_Obj_t * pObj, * pObj2; Vec_Int_t * vUifConstrs, * vCompares, * vFanins; int i, k, iObj, iObj2, iObjNew, iObjNew2; int iFanin, iFanin2, iFaninNew; // get multiplier pairs if not given if ( vPairs == NULL ) vPairs = Wlc_NtkFindUifableMultiplierPairs( p ); if ( vPairs == NULL ) return NULL; // sanity checks assert( Vec_IntSize(vPairs) > 0 && Vec_IntSize(vPairs) % 2 == 0 ); // iterate through node pairs vFanins = Vec_IntAlloc( 100 ); vCompares = Vec_IntAlloc( 100 ); vUifConstrs = Vec_IntAlloc( 100 ); Vec_IntForEachEntryDouble( vPairs, iObj, iObj2, i ) { // get two nodes pObj = Wlc_NtkObj( p, iObj ); pObj2 = Wlc_NtkObj( p, iObj2 ); assert( Wlc_NtkPairIsUifable(p, pObj, pObj2) ); // create fanin comparator nodes Vec_IntClear( vCompares ); Wlc_ObjForEachFanin( pObj, iFanin, k ) { iFanin2 = Wlc_ObjFaninId( pObj2, k ); Vec_IntFillTwo( vFanins, 2, iFanin, iFanin2 ); iFaninNew = Wlc_ObjCreate( p, WLC_OBJ_COMP_NOTEQU, 0, 0, 0, vFanins ); Vec_IntPush( vCompares, iFaninNew ); // note that a pointer to Wlc_Obj_t (for example, pObj) can be invalidated after a call to // Wlc_ObjCreate() due to a possible realloc of the internal array of objects... pObj = Wlc_NtkObj( p, iObj ); } // concatenate fanin comparators iObjNew = Wlc_ObjCreate( p, WLC_OBJ_BIT_CONCAT, 0, Vec_IntSize(vCompares) - 1, 0, vCompares ); // create reduction-OR node Vec_IntFill( vFanins, 1, iObjNew ); iObjNew = Wlc_ObjCreate( p, WLC_OBJ_REDUCT_OR, 0, 0, 0, vFanins ); // craete output comparator node Vec_IntFillTwo( vFanins, 2, iObj, iObj2 ); iObjNew2 = Wlc_ObjCreate( p, WLC_OBJ_COMP_EQU, 0, 0, 0, vFanins ); // create implication node (iObjNew is already complemented above) Vec_IntFillTwo( vFanins, 2, iObjNew, iObjNew2 ); iObjNew = Wlc_ObjCreate( p, WLC_OBJ_LOGIC_OR, 0, 0, 0, vFanins ); // save the constraint Vec_IntPush( vUifConstrs, iObjNew ); } // derive the AND of the UIF contraints assert( Vec_IntSize(vUifConstrs) > 0 ); if ( Vec_IntSize(vUifConstrs) == 1 ) iObjNew = Vec_IntEntry( vUifConstrs, 0 ); else { // concatenate iObjNew = Wlc_ObjCreate( p, WLC_OBJ_BIT_CONCAT, 0, Vec_IntSize(vUifConstrs) - 1, 0, vUifConstrs ); // create reduction-AND node Vec_IntFill( vFanins, 1, iObjNew ); iObjNew = Wlc_ObjCreate( p, WLC_OBJ_REDUCT_AND, 0, 0, 0, vFanins ); } // update each PO to point to the new node Wlc_NtkForEachPo( p, pObj, i ) { iObj = Wlc_ObjId(p, pObj); Vec_IntFillTwo( vFanins, 2, iObj, iObjNew ); iObjNew = Wlc_ObjCreate( p, WLC_OBJ_LOGIC_AND, 0, 0, 0, vFanins ); // note that a pointer to Wlc_Obj_t (for example, pObj) can be invalidated after a call to // Wlc_ObjCreate() due to a possible realloc of the internal array of objects... pObj = Wlc_NtkObj( p, iObj ); // update PO/CO arrays assert( Vec_IntEntry(&p->vPos, i) == iObj ); assert( Vec_IntEntry(&p->vCos, i) == iObj ); Vec_IntWriteEntry( &p->vPos, i, iObjNew ); Vec_IntWriteEntry( &p->vCos, i, iObjNew ); // transfer the PO attribute Wlc_NtkObj(p, iObjNew)->fIsPo = 1; assert( pObj->fIsPo ); pObj->fIsPo = 0; } // cleanup Vec_IntFree( vUifConstrs ); Vec_IntFree( vCompares ); Vec_IntFree( vFanins ); if ( vPairs != vPairsInit ) Vec_IntFree( vPairs ); // reconstruct topological order pNew = Wlc_NtkDupDfs( p ); Wlc_NtkTransferNames( pNew, p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcBlast.c000066400000000000000000001764341300674244400234710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcBlast.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Bit-blasting.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcBlast.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" #include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Counts constant bits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Wlc_NtkCountConstBits( int * pArray, int nSize ) { int i, Counter = 0; for ( i = 0; i < nSize; i++ ) Counter += (pArray[i] == 0 || pArray[i] == 1); return Counter; } /**Function************************************************************* Synopsis [Helper functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Wlc_NtkPrepareBits( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, nBits = 0; Wlc_NtkCleanCopy( p ); Wlc_NtkForEachObj( p, pObj, i ) { Wlc_ObjSetCopy( p, i, nBits ); nBits += Wlc_ObjRange(pObj); } return nBits; } int * Wlc_VecCopy( Vec_Int_t * vOut, int * pArray, int nSize ) { int i; Vec_IntClear( vOut ); for( i = 0; i < nSize; i++) Vec_IntPush( vOut, pArray[i] ); return Vec_IntArray( vOut ); } int * Wlc_VecLoadFanins( Vec_Int_t * vOut, int * pFanins, int nFanins, int nTotal, int fSigned ) { int Fill = fSigned ? pFanins[nFanins-1] : 0; int i; Vec_IntClear( vOut ); assert( nFanins <= nTotal ); for( i = 0; i < nTotal; i++) Vec_IntPush( vOut, i < nFanins ? pFanins[i] : Fill ); return Vec_IntArray( vOut ); } int Wlc_BlastGetConst( int * pNum, int nNum ) { int i, Res = 0; for ( i = 0; i < nNum; i++ ) if ( pNum[i] == 1 ) Res |= (1 << i); else if ( pNum[i] != 0 ) return -1; return Res; } int Wlc_NtkMuxTree_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 = Wlc_NtkMuxTree_rec( pNew, pCtrl, nCtrl-1, vData, Shift ); iLit1 = Wlc_NtkMuxTree_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) ); return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); } /**Function************************************************************* Synopsis [Bit blasting for specific operations.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_BlastShiftRightInt( Gia_Man_t * pNew, int * pNum, int nNum, int * pShift, int nShift, int fSticky, Vec_Int_t * vRes ) { int * pRes = Wlc_VecCopy( vRes, pNum, nNum ); int Fill = fSticky ? pNum[nNum-1] : 0; int i, j, fShort = 0; assert( nShift <= 32 ); for( i = 0; i < nShift; i++ ) for( j = 0; j < nNum - fSticky; j++ ) { if( fShort || j + (1<= nNum ) { pRes[j] = Gia_ManHashMux( pNew, pShift[i], Fill, pRes[j] ); if ( (1< nNum ) fShort = 1; } else pRes[j] = Gia_ManHashMux( pNew, pShift[i], pRes[j+(1<= fSticky; j-- ) { if( fShort || (1< j ) { pRes[j] = Gia_ManHashMux( pNew, pShift[i], Fill, pRes[j] ); if ( (1< nNum ) fShort = 1; } else pRes[j] = Gia_ManHashMux( pNew, pShift[i], pRes[j-(1<= (1<= 0; k-- ) { iRes = Gia_ManHashMux( pNew, iKnown, iRes, Gia_ManHashAnd(pNew, Abc_LitNot(pArg0[k]), pArg1[k]) ); iKnown = Gia_ManHashOr( pNew, iKnown, Gia_ManHashXor(pNew, pArg0[k], pArg1[k]) ); if ( iKnown == 1 ) break; } return iRes; } void Wlc_BlastLess_rec( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits, int * pYes, int * pNo ) { if ( nBits > 1 ) { int Yes = Gia_ManHashAnd( pNew, Abc_LitNot(pArg0[nBits-1]), pArg1[nBits-1] ), YesR; int No = Gia_ManHashAnd( pNew, Abc_LitNot(pArg1[nBits-1]), pArg0[nBits-1] ), NoR; if ( Yes == 1 || No == 1 ) { *pYes = Yes; *pNo = No; return; } Wlc_BlastLess_rec( pNew, pArg0, pArg1, nBits-1, &YesR, &NoR ); *pYes = Gia_ManHashOr( pNew, Yes, Gia_ManHashAnd(pNew, Abc_LitNot(No), YesR) ); *pNo = Gia_ManHashOr( pNew, No, Gia_ManHashAnd(pNew, Abc_LitNot(Yes), NoR ) ); return; } assert( nBits == 1 ); *pYes = Gia_ManHashAnd( pNew, Abc_LitNot(pArg0[0]), pArg1[0] ); *pNo = Gia_ManHashAnd( pNew, Abc_LitNot(pArg1[0]), pArg0[0] ); } int Wlc_BlastLess( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits ) { int Yes, No; if ( nBits == 0 ) return 0; Wlc_BlastLess_rec( pNew, pArg0, pArg1, nBits, &Yes, &No ); return Yes; } int Wlc_BlastLessSigned( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits ) { int iDiffSign = Gia_ManHashXor( pNew, pArg0[nBits-1], pArg1[nBits-1] ); return Gia_ManHashMux( pNew, iDiffSign, pArg0[nBits-1], Wlc_BlastLess(pNew, pArg0, pArg1, nBits-1) ); } void Wlc_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps ) { int fUseXor = 0; if ( fUseXor ) { int Xor = Gia_ManHashXor(pNew, a, b); int And1 = Gia_ManHashAnd(pNew, a, b); int And2 = Gia_ManHashAnd(pNew, c, Xor); *ps = Gia_ManHashXor(pNew, c, Xor); *pc = Gia_ManHashOr (pNew, And1, And2); } else { int And1 = Gia_ManHashAnd(pNew, a, b); int And1_= Gia_ManHashAnd(pNew, Abc_LitNot(a), Abc_LitNot(b)); int Xor = Gia_ManHashAnd(pNew, Abc_LitNot(And1), Abc_LitNot(And1_)); int And2 = Gia_ManHashAnd(pNew, c, Xor); int And2_= Gia_ManHashAnd(pNew, Abc_LitNot(c), Abc_LitNot(Xor)); *ps = Gia_ManHashAnd(pNew, Abc_LitNot(And2), Abc_LitNot(And2_)); *pc = Gia_ManHashOr (pNew, And1, And2); } } void Wlc_BlastAdder( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0 { int b, Carry = 0; for ( b = 0; b < nBits; b++ ) Wlc_BlastFullAdder( pNew, pAdd0[b], pAdd1[b], Carry, &Carry, &pAdd0[b] ); } void Wlc_BlastSubtract( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0 { int b, Carry = 1; for ( b = 0; b < nBits; b++ ) Wlc_BlastFullAdder( pNew, pAdd0[b], Abc_LitNot(pAdd1[b]), Carry, &Carry, &pAdd0[b] ); } void Wlc_BlastAdderCLA_one( Gia_Man_t * pNew, int * pGen, int * pPro, int * pCar, int * pGen1, int * pPro1, int * pCar1 ) { int Temp = Gia_ManHashAnd( pNew, pGen[0], pPro[1] ); *pPro1 = Gia_ManHashAnd( pNew, pPro[0], pPro[1] ); *pGen1 = Gia_ManHashOr( pNew, Gia_ManHashOr(pNew, pGen[1], Temp), Gia_ManHashAnd(pNew, *pPro1, pCar[0]) ); *pCar1 = Gia_ManHashOr( pNew, pGen[0], Gia_ManHashAnd(pNew, pPro[0], pCar[0]) ); } void Wlc_BlastAdderCLA_rec( Gia_Man_t * pNew, int * pGen, int * pPro, int * pCar, int nBits, int * pGen1, int * pPro1 ) { if ( nBits == 2 ) Wlc_BlastAdderCLA_one( pNew, pGen, pPro, pCar, pGen1, pPro1, pCar+1 ); // returns *pGen1, *pPro1, pCar[1] else { int pGen2[2], pPro2[2]; assert( nBits % 2 == 0 ); // call recursively Wlc_BlastAdderCLA_rec( pNew, pGen, pPro, pCar, nBits/2, pGen2, pPro2 ); pCar[nBits/2] = *pGen2; Wlc_BlastAdderCLA_rec( pNew, pGen+nBits/2, pPro+nBits/2, pCar+nBits/2, nBits/2, pGen2+1, pPro2+1 ); // create structure Wlc_BlastAdderCLA_one( pNew, pGen2, pPro2, pCar, pGen1, pPro1, pCar+nBits/2 ); // returns *pGen1, *pPro1, pCar[nBits/2] } } void Wlc_BlastAdderCLA( Gia_Man_t * pNew, int * pAdd0, int * pAdd1, int nBits ) // result is in pAdd0 { int * pGen = ABC_CALLOC( int, nBits ); int * pPro = ABC_CALLOC( int, nBits ); int * pCar = ABC_CALLOC( int, nBits+1 ); int b, Gen, Pro; if ( nBits == 1 ) { int Carry = 0; Wlc_BlastFullAdder( pNew, pAdd0[0], pAdd1[0], Carry, &Carry, &pAdd0[0] ); return; } assert( nBits >= 2 ); pCar[0] = 0; for ( b = 0; b < nBits; b++ ) { pGen[b] = Gia_ManHashAnd(pNew, pAdd0[b], pAdd1[b]); pPro[b] = Gia_ManHashXor(pNew, pAdd0[b], pAdd1[b]); } Wlc_BlastAdderCLA_rec( pNew, pGen, pPro, pCar, nBits, &Gen, &Pro ); for ( b = 0; b < nBits; b++ ) pAdd0[b] = Gia_ManHashXor(pNew, pPro[b], pCar[b]); ABC_FREE(pGen); ABC_FREE(pPro); ABC_FREE(pCar); } void Wlc_BlastMinus( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vRes ) { int * pRes = Wlc_VecCopy( vRes, pNum, nNum ); int i, invert = 0; for ( i = 0; i < nNum; i++ ) { pRes[i] = Gia_ManHashMux( pNew, invert, Abc_LitNot(pRes[i]), pRes[i] ); invert = Gia_ManHashOr( pNew, invert, pNum[i] ); } } void Wlc_BlastMultiplier2( Gia_Man_t * pNew, int * pArg0, int * pArg1, int nBits, Vec_Int_t * vTemp, Vec_Int_t * vRes ) { int i, j; Vec_IntFill( vRes, nBits, 0 ); for ( i = 0; i < nBits; i++ ) { Vec_IntFill( vTemp, i, 0 ); for ( j = 0; Vec_IntSize(vTemp) < nBits; j++ ) Vec_IntPush( vTemp, Gia_ManHashAnd(pNew, pArg0[j], pArg1[i]) ); assert( Vec_IntSize(vTemp) == nBits ); Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vTemp), nBits ); } } void Wlc_BlastFullAdderCtrl( Gia_Man_t * pNew, int a, int ac, int b, int c, int * pc, int * ps, int fNeg ) { int And = Abc_LitNotCond( Gia_ManHashAnd(pNew, a, ac), fNeg ); Wlc_BlastFullAdder( pNew, And, b, c, pc, ps ); } void Wlc_BlastFullAdderSubtr( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps, int fSub ) { Wlc_BlastFullAdder( pNew, Gia_ManHashXor(pNew, a, fSub), b, c, pc, ps ); } void Wlc_BlastMultiplier( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vTemp, Vec_Int_t * vRes, int fSigned ) { int * pRes, * pArgC, * pArgS, a, b, Carry = fSigned; assert( nArgA > 0 && nArgB > 0 ); assert( fSigned == 0 || fSigned == 1 ); // prepare result Vec_IntFill( vRes, nArgA + nArgB, 0 ); pRes = Vec_IntArray( vRes ); // prepare intermediate storage Vec_IntFill( vTemp, 2 * nArgA, 0 ); pArgC = Vec_IntArray( vTemp ); pArgS = pArgC + nArgA; // create matrix for ( b = 0; b < nArgB; b++ ) for ( a = 0; a < nArgA; a++ ) Wlc_BlastFullAdderCtrl( pNew, pArgA[a], pArgB[b], pArgS[a], pArgC[a], &pArgC[a], a ? &pArgS[a-1] : &pRes[b], fSigned && ((a+1 == nArgA) ^ (b+1 == nArgB)) ); // final addition pArgS[nArgA-1] = fSigned; for ( a = 0; a < nArgA; a++ ) Wlc_BlastFullAdderCtrl( pNew, 1, pArgC[a], pArgS[a], Carry, &Carry, &pRes[nArgB+a], 0 ); } void Wlc_BlastDivider( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) { int * pRes = Wlc_VecCopy( vRes, pNum, nNum ); int * pQuo = ABC_ALLOC( int, nNum ); int * pTemp = ABC_ALLOC( int, nNum ); int i, j, known, borrow, y_bit, top_bit; assert( nNum == nDiv ); for ( j = nNum - 1; j >= 0; j-- ) { known = 0; for ( i = nNum - 1; i > nNum - 1 - j; i-- ) { known = Gia_ManHashOr( pNew, known, pDiv[i] ); if( known == 1 ) break; } pQuo[j] = known; for ( i = nNum - 1; i >= 0; i-- ) { if ( known == 1 ) break; y_bit = (i >= j) ? pDiv[i-j] : 0; pQuo[j] = Gia_ManHashMux( pNew, known, pQuo[j], Gia_ManHashAnd( pNew, y_bit, Abc_LitNot(pRes[i]) ) ); known = Gia_ManHashOr( pNew, known, Gia_ManHashXor(pNew, y_bit, pRes[i])); } pQuo[j] = Abc_LitNot(pQuo[j]); if ( pQuo[j] == 0 ) continue; borrow = 0; for ( i = 0; i < nNum; i++ ) { top_bit = Gia_ManHashMux( pNew, borrow, Abc_LitNot(pRes[i]), pRes[i] ); y_bit = (i >= j) ? pDiv[i-j] : 0; borrow = Gia_ManHashMux( pNew, pRes[i], Gia_ManHashAnd(pNew, borrow, y_bit), Gia_ManHashOr(pNew, borrow, y_bit) ); pTemp[i] = Gia_ManHashXor( pNew, top_bit, y_bit ); } if ( pQuo[j] == 1 ) Wlc_VecCopy( vRes, pTemp, nNum ); else for( i = 0; i < nNum; i++ ) pRes[i] = Gia_ManHashMux( pNew, pQuo[j], pTemp[i], pRes[i] ); } ABC_FREE( pTemp ); if ( fQuo ) Wlc_VecCopy( vRes, pQuo, nNum ); ABC_FREE( pQuo ); } // non-restoring divider void Wlc_BlastDivider2( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) { int i, * pRes = Vec_IntArray(vRes); int k, * pQuo = ABC_ALLOC( int, nNum ); assert( nNum > 0 && nDiv > 0 ); assert( Vec_IntSize(vRes) < nNum + nDiv ); for ( i = 0; i < nNum + nDiv; i++ ) pRes[i] = i < nNum ? pNum[i] : 0; for ( i = nNum-1; i >= 0; i-- ) { int Cntrl = i == nNum-1 ? 1 : pQuo[i+1]; int Carry = Cntrl; for ( k = 0; k <= nDiv; k++ ) Wlc_BlastFullAdderSubtr( pNew, k < nDiv ? pDiv[k] : 0, pRes[i+k], Carry, &Carry, &pRes[i+k], Cntrl ); pQuo[i] = Abc_LitNot(pRes[i+nDiv]); } if ( fQuo ) Wlc_VecCopy( vRes, pQuo, nNum ); else { int Carry = 0, Temp; for ( k = 0; k < nDiv; k++ ) { Wlc_BlastFullAdder( pNew, pDiv[k], pRes[k], Carry, &Carry, &Temp ); pRes[k] = Gia_ManHashMux( pNew, pQuo[0], pRes[k], Temp ); } Vec_IntShrink( vRes, nDiv ); } ABC_FREE( pQuo ); } void Wlc_BlastDividerSigned( Gia_Man_t * pNew, int * pNum, int nNum, int * pDiv, int nDiv, int fQuo, Vec_Int_t * vRes ) { Vec_Int_t * vNum = Vec_IntAlloc( nNum ); Vec_Int_t * vDiv = Vec_IntAlloc( nDiv ); Vec_Int_t * vRes00 = Vec_IntAlloc( nNum + nDiv ); Vec_Int_t * vRes01 = Vec_IntAlloc( nNum + nDiv ); Vec_Int_t * vRes10 = Vec_IntAlloc( nNum + nDiv ); Vec_Int_t * vRes11 = Vec_IntAlloc( nNum + nDiv ); Vec_Int_t * vRes2 = Vec_IntAlloc( nNum ); int k, iDiffSign = Gia_ManHashXor( pNew, pNum[nNum-1], pDiv[nDiv-1] ); Wlc_BlastMinus( pNew, pNum, nNum, vNum ); Wlc_BlastMinus( pNew, pDiv, nDiv, vDiv ); Wlc_BlastDivider( pNew, pNum, nNum, pDiv, nDiv, fQuo, vRes00 ); Wlc_BlastDivider( pNew, pNum, nNum, Vec_IntArray(vDiv), nDiv, fQuo, vRes01 ); Wlc_BlastDivider( pNew, Vec_IntArray(vNum), nNum, pDiv, nDiv, fQuo, vRes10 ); Wlc_BlastDivider( pNew, Vec_IntArray(vNum), nNum, Vec_IntArray(vDiv), nDiv, fQuo, vRes11 ); Vec_IntClear( vRes ); for ( k = 0; k < nNum; k++ ) { int Data0 = Gia_ManHashMux( pNew, pDiv[nDiv-1], Vec_IntEntry(vRes01,k), Vec_IntEntry(vRes00,k) ); int Data1 = Gia_ManHashMux( pNew, pDiv[nDiv-1], Vec_IntEntry(vRes11,k), Vec_IntEntry(vRes10,k) ); Vec_IntPush( vRes, Gia_ManHashMux(pNew, pNum[nNum-1], Data1, Data0) ); } Wlc_BlastMinus( pNew, Vec_IntArray(vRes), nNum, vRes2 ); for ( k = 0; k < nNum; k++ ) Vec_IntWriteEntry( vRes, k, Gia_ManHashMux(pNew, fQuo ? iDiffSign : pNum[nNum-1], Vec_IntEntry(vRes2,k), Vec_IntEntry(vRes,k)) ); Vec_IntFree( vNum ); Vec_IntFree( vDiv ); Vec_IntFree( vRes00 ); Vec_IntFree( vRes01 ); Vec_IntFree( vRes10 ); Vec_IntFree( vRes11 ); Vec_IntFree( vRes2 ); assert( Vec_IntSize(vRes) == nNum ); } void Wlc_BlastZeroCondition( Gia_Man_t * pNew, int * pDiv, int nDiv, Vec_Int_t * vRes ) { int i, Entry, iLit = Wlc_BlastReduction( pNew, pDiv, nDiv, WLC_OBJ_REDUCT_OR ); Vec_IntForEachEntry( vRes, Entry, i ) Vec_IntWriteEntry( vRes, i, Gia_ManHashAnd(pNew, iLit, Entry) ); } void Wlc_BlastTable( Gia_Man_t * pNew, word * pTable, int * pFans, int nFans, int nOuts, Vec_Int_t * vRes ) { extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); Vec_Int_t * vMemory = Vec_IntAlloc( 0 ); Vec_Int_t vLeaves = { nFans, nFans, pFans }; word * pTruth = ABC_ALLOC( word, Abc_TtWordNum(nFans) ); int o, i, m, iLit, nMints = (1 << nFans); Vec_IntClear( vRes ); for ( o = 0; o < nOuts; o++ ) { // derive truth table memset( pTruth, 0, sizeof(word) * Abc_TtWordNum(nFans) ); for ( m = 0; m < nMints; m++ ) for ( i = 0; i < nFans; i++ ) if ( Abc_TtGetBit( pTable, m * nFans + i ) ) Abc_TtSetBit( pTruth, m ); // implement truth table if ( nFans < 6 ) pTruth[0] = Abc_Tt6Stretch( pTruth[0], nFans ); iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, nFans, vMemory, &vLeaves, 1 ); Vec_IntPush( vRes, iLit ); } Vec_IntFree( vMemory ); ABC_FREE( pTruth ); } void Wlc_BlastPower( Gia_Man_t * pNew, int * pNum, int nNum, int * pExp, int nExp, Vec_Int_t * vTemp, Vec_Int_t * vRes ) { Vec_Int_t * vDegrees = Vec_IntAlloc( 2*nNum ); Vec_Int_t * vResTemp = Vec_IntAlloc( 2*nNum ); int i, * pDegrees = NULL, * pRes = Vec_IntArray(vRes); int k, * pResTemp = Vec_IntArray(vResTemp); Vec_IntFill( vRes, nNum, 0 ); Vec_IntWriteEntry( vRes, 0, 1 ); for ( i = 0; i < nExp; i++ ) { if ( i == 0 ) pDegrees = Wlc_VecCopy( vDegrees, pNum, nNum ); else { Wlc_BlastMultiplier2( pNew, pDegrees, pDegrees, nNum, vTemp, vResTemp ); pDegrees = Wlc_VecCopy( vDegrees, pResTemp, nNum ); } Wlc_BlastMultiplier2( pNew, pRes, pDegrees, nNum, vTemp, vResTemp ); for ( k = 0; k < nNum; k++ ) pRes[k] = Gia_ManHashMux( pNew, pExp[i], pResTemp[k], pRes[k] ); } Vec_IntFree( vResTemp ); Vec_IntFree( vDegrees ); } void Wlc_BlastSqrt( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_Int_t * vRes ) { int * pRes, * pSum, * pSumP; int i, k, Carry = -1; assert( nNum % 2 == 0 ); Vec_IntFill( vRes, nNum/2, 0 ); Vec_IntFill( vTmp, 2*nNum, 0 ); pRes = Vec_IntArray( vRes ); pSum = Vec_IntArray( vTmp ); pSumP = pSum + nNum; for ( i = 0; i < nNum/2; i++ ) { pSumP[0] = pNum[nNum-2*i-2]; pSumP[1] = pNum[nNum-2*i-1]; for ( k = 0; k < i+1; k++ ) pSumP[k+2] = pSum[k]; for ( k = 0; k < i + 3; k++ ) { if ( k >= 2 && k < i + 2 ) // middle ones Wlc_BlastFullAdder( pNew, pSumP[k], Abc_LitNot(pRes[i-k+1]), Carry, &Carry, &pSum[k] ); else Wlc_BlastFullAdder( pNew, pSumP[k], Abc_LitNot(k ? Carry:1), 1, &Carry, &pSum[k] ); if ( k == 0 || k > i ) Carry = Abc_LitNot(Carry); } pRes[i] = Abc_LitNot(Carry); for ( k = 0; k < i + 3; k++ ) pSum[k] = Gia_ManHashMux( pNew, pRes[i], pSum[k], pSumP[k] ); } Vec_IntReverseOrder( vRes ); } void Wlc_IntInsert( Vec_Int_t * vProd, Vec_Int_t * vLevel, int Node, int Level ) { int i; for ( i = Vec_IntSize(vLevel) - 1; i >= 0; i-- ) if ( Vec_IntEntry(vLevel, i) >= Level ) break; Vec_IntInsert( vProd, i + 1, Node ); Vec_IntInsert( vLevel, i + 1, Level ); } void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vLevels, Vec_Int_t * vRes ) { Vec_Int_t * vLevel, * vProd; int i, NodeS, NodeC, LevelS, LevelC, Node1, Node2, Node3, Level1, Level2, Level3; int nSize = Vec_WecSize(vProds); assert( nSize == Vec_WecSize(vLevels) ); for ( i = 0; i < nSize; i++ ) { while ( 1 ) { vProd = Vec_WecEntry( vProds, i ); if ( Vec_IntSize(vProd) < 3 ) break; Node1 = Vec_IntPop( vProd ); Node2 = Vec_IntPop( vProd ); Node3 = Vec_IntPop( vProd ); vLevel = Vec_WecEntry( vLevels, i ); Level1 = Vec_IntPop( vLevel ); Level2 = Vec_IntPop( vLevel ); Level3 = Vec_IntPop( vLevel ); Wlc_BlastFullAdder( pNew, Node1, Node2, Node3, &NodeC, &NodeS ); LevelS = Abc_MaxInt( Abc_MaxInt(Level1, Level2), Level3 ) + 2; LevelC = LevelS - 1; Wlc_IntInsert( vProd, vLevel, NodeS, LevelS ); vProd = Vec_WecEntry( vProds, i+1 ); vLevel = Vec_WecEntry( vLevels, i+1 ); Wlc_IntInsert( vProd, vLevel, NodeC, LevelC ); } } // make all ranks have two products for ( i = 0; i < nSize; i++ ) { vProd = Vec_WecEntry( vProds, i ); while ( Vec_IntSize(vProd) < 2 ) Vec_IntPush( vProd, 0 ); assert( Vec_IntSize(vProd) == 2 ); } // Vec_WecPrint( vProds, 0 ); vLevel = Vec_WecEntry( vLevels, 0 ); Vec_IntClear( vRes ); Vec_IntClear( vLevel ); for ( i = 0; i < nSize; i++ ) { vProd = Vec_WecEntry( vProds, i ); Vec_IntPush( vRes, Vec_IntEntry(vProd, 0) ); Vec_IntPush( vLevel, Vec_IntEntry(vProd, 1) ); } Vec_IntPush( vRes, 0 ); Vec_IntPush( vLevel, 0 ); Wlc_BlastAdder( pNew, Vec_IntArray(vRes), Vec_IntArray(vLevel), Vec_IntSize(vRes) ); } void Wlc_BlastMultiplier3( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB ); int i, k; for ( i = 0; i < nArgA; i++ ) for ( k = 0; k < nArgB; k++ ) { Vec_WecPush( vProds, i+k, Gia_ManHashAnd(pNew, pArgA[i], pArgB[k]) ); Vec_WecPush( vLevels, i+k, 0 ); } Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); Vec_WecFree( vProds ); Vec_WecFree( vLevels ); } void Wlc_BlastSquare( Gia_Man_t * pNew, int * pNum, int nNum, Vec_Int_t * vTmp, Vec_Int_t * vRes ) { Vec_Wec_t * vProds = Vec_WecStart( 2*nNum ); Vec_Wec_t * vLevels = Vec_WecStart( 2*nNum ); int i, k; for ( i = 0; i < nNum; i++ ) for ( k = 0; k < nNum; k++ ) { if ( i == k ) { Vec_WecPush( vProds, i+k, pNum[i] ); Vec_WecPush( vLevels, i+k, 0 ); } else if ( i < k ) { Vec_WecPush( vProds, i+k+1, Gia_ManHashAnd(pNew, pNum[i], pNum[k]) ); Vec_WecPush( vLevels, i+k+1, 0 ); } } Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); Vec_WecFree( vProds ); Vec_WecFree( vLevels ); } void Wlc_BlastBooth( Gia_Man_t * pNew, int * pArgA, int * pArgB, int nArgA, int nArgB, Vec_Int_t * vRes, int fSigned ) { Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB + 3 ); Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB + 3 ); int FillA = fSigned ? pArgA[nArgA-1] : 0; int FillB = fSigned ? pArgB[nArgB-1] : 0; int i, k, Sign; // create new arguments Vec_Int_t * vArgB = Vec_IntAlloc( nArgB + 3 ); Vec_IntPush( vArgB, 0 ); for ( i = 0; i < nArgB; i++ ) Vec_IntPush( vArgB, pArgB[i] ); Vec_IntPush( vArgB, FillB ); if ( Vec_IntSize(vArgB) % 2 == 0 ) Vec_IntPush( vArgB, FillB ); assert( Vec_IntSize(vArgB) % 2 == 1 ); // iterate through bit-pairs for ( k = 0; k+2 < Vec_IntSize(vArgB); k+=2 ) { int pp = -1; int Q2jM1 = Vec_IntEntry(vArgB, k); // q(2*j-1) int Q2j = Vec_IntEntry(vArgB, k+1); // q(2*j+0) int Q2jP1 = Vec_IntEntry(vArgB, k+2); // q(2*j+1) int Neg = Q2jP1; int One = Gia_ManHashXor( pNew, Q2j, Q2jM1 ); int Two = Gia_ManHashMux( pNew, Neg, Gia_ManHashAnd(pNew, Abc_LitNot(Q2j), Abc_LitNot(Q2jM1)), Gia_ManHashAnd(pNew, Q2j, Q2jM1) ); for ( i = 0; i <= nArgA; i++ ) { int This = i == nArgA ? FillA : pArgA[i]; int Prev = i ? pArgA[i-1] : 0; int Part = Gia_ManHashOr( pNew, Gia_ManHashAnd(pNew, One, This), Gia_ManHashAnd(pNew, Two, Prev) ); pp = Gia_ManHashXor( pNew, Part, Neg ); if ( pp == 0 ) continue; Vec_WecPush( vProds, k+i, pp ); Vec_WecPush( vLevels, k+i, 0 ); } // perform sign extension Sign = fSigned ? pp : Neg; if ( k == 0 ) { Vec_WecPush( vProds, k+i, Sign ); Vec_WecPush( vLevels, k+i, 0 ); Vec_WecPush( vProds, k+i+1, Sign ); Vec_WecPush( vLevels, k+i+1, 0 ); Vec_WecPush( vProds, k+i+2, Abc_LitNot(Sign) ); Vec_WecPush( vLevels, k+i+2, 0 ); } else { Vec_WecPush( vProds, k+i, Abc_LitNot(Sign) ); Vec_WecPush( vLevels, k+i, 0 ); Vec_WecPush( vProds, k+i+1, 1 ); Vec_WecPush( vLevels, k+i+1, 0 ); } // add neg to the first column if ( Neg == 0 ) continue; Vec_WecPush( vProds, k, Neg ); Vec_WecPush( vLevels, k, 0 ); } //Vec_WecPrint( vProds, 0 ); Wlc_BlastReduceMatrix( pNew, vProds, vLevels, vRes ); Vec_WecFree( vProds ); Vec_WecFree( vLevels ); Vec_IntFree( vArgB ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Vec_Int_t * vBoxIds, int iOutput, int nOutputRange, int fGiaSimple, int fAddOutputs, int fBooth ) { int fVerbose = 0; int fUseOldMultiplierBlasting = 0; Tim_Man_t * pManTime = NULL; Gia_Man_t * pTemp, * pNew, * pExtra = NULL; Wlc_Obj_t * pObj; Vec_Int_t * vBits = &p->vBits, * vTemp0, * vTemp1, * vTemp2, * vRes, * vAddOutputs = NULL, * vAddObjs = NULL; int nBits = Wlc_NtkPrepareBits( p ); int nRange, nRange0, nRange1, nRange2; int i, k, b, iFanin, iLit, nAndPrev, * pFans0, * pFans1, * pFans2; int nFFins = 0, nFFouts = 0, curPi = 0, curPo = 0; int nBitCis = 0, nBitCos = 0, fAdded = 0; Vec_IntClear( vBits ); Vec_IntGrow( vBits, nBits ); vTemp0 = Vec_IntAlloc( 1000 ); vTemp1 = Vec_IntAlloc( 1000 ); vTemp2 = Vec_IntAlloc( 1000 ); vRes = Vec_IntAlloc( 1000 ); // clean AND-gate counters memset( p->nAnds, 0, sizeof(int) * WLC_OBJ_NUMBER ); // create AIG manager pNew = Gia_ManStart( 5 * Wlc_NtkObjNum(p) + 1000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->fGiaSimple = fGiaSimple; if ( !fGiaSimple ) Gia_ManHashAlloc( pNew ); if ( fAddOutputs ) vAddOutputs = Vec_IntAlloc( 100 ); if ( fAddOutputs ) vAddObjs = Vec_IntAlloc( 100 ); // prepare for AIG with boxes if ( vBoxIds ) { int nNewCis = 0, nNewCos = 0; Wlc_NtkForEachObj( p, pObj, i ) pObj->Mark = 0; // count bit-width of regular CIs/COs Wlc_NtkForEachCi( p, pObj, i ) nBitCis += Wlc_ObjRange( pObj ); Wlc_NtkForEachCo( p, pObj, i ) nBitCos += Wlc_ObjRange( pObj ); // count bit-width of additional CIs/COs due to selected multipliers assert( Vec_IntSize(vBoxIds) > 0 ); Wlc_NtkForEachObjVec( vBoxIds, p, pObj, i ) { // currently works only for multipliers assert( pObj->Type == WLC_OBJ_ARI_MULTI ); nNewCis += Wlc_ObjRange( pObj ); nNewCos += Wlc_ObjRange( Wlc_ObjFanin0(p, pObj) ); nNewCos += Wlc_ObjRange( Wlc_ObjFanin1(p, pObj) ); pObj->Mark = 1; } // create hierarchy manager pManTime = Tim_ManStart( nBitCis + nNewCis, nBitCos + nNewCos ); curPi = nBitCis; curPo = 0; // create AIG manager for logic of the boxes pExtra = Gia_ManStart( Wlc_NtkObjNum(p) ); Gia_ManHashAlloc( pExtra ); assert( !fGiaSimple ); } // blast in the topological order Wlc_NtkForEachObj( p, pObj, i ) { // char * pName1 = Wlc_ObjName(p, i); // char * pName2 = Wlc_ObjFaninNum(pObj) ? Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) : NULL; nAndPrev = Gia_ManAndNum(pNew); nRange = Wlc_ObjRange( pObj ); nRange0 = Wlc_ObjFaninNum(pObj) > 0 ? Wlc_ObjRange( Wlc_ObjFanin0(p, pObj) ) : -1; nRange1 = Wlc_ObjFaninNum(pObj) > 1 ? Wlc_ObjRange( Wlc_ObjFanin1(p, pObj) ) : -1; nRange2 = Wlc_ObjFaninNum(pObj) > 2 ? Wlc_ObjRange( Wlc_ObjFanin2(p, pObj) ) : -1; pFans0 = Wlc_ObjFaninNum(pObj) > 0 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId0(pObj)) ) : NULL; pFans1 = Wlc_ObjFaninNum(pObj) > 1 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId1(pObj)) ) : NULL; pFans2 = Wlc_ObjFaninNum(pObj) > 2 ? Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjFaninId2(pObj)) ) : NULL; Vec_IntClear( vRes ); assert( nRange > 0 ); if ( vBoxIds && pObj->Mark ) { pObj->Mark = 0; // create new box Tim_ManCreateBox( pManTime, curPo, nRange0 + nRange1, curPi, nRange, -1, 0 ); curPi += nRange; curPo += nRange0 + nRange1; // create combinational outputs in the normal manager for ( k = 0; k < nRange0; k++ ) Gia_ManAppendCo( pNew, pFans0[k] ); for ( k = 0; k < nRange1; k++ ) Gia_ManAppendCo( pNew, pFans1[k] ); // make sure there is enough primary inputs in the manager for ( k = Gia_ManPiNum(pExtra); k < nRange0 + nRange1; k++ ) Gia_ManAppendCi( pExtra ); // create combinational inputs Vec_IntClear( vTemp0 ); for ( k = 0; k < nRange0; k++ ) Vec_IntPush( vTemp0, Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, k)) ); Vec_IntClear( vTemp1 ); for ( k = 0; k < nRange1; k++ ) Vec_IntPush( vTemp1, Gia_Obj2Lit(pExtra, Gia_ManPi(pExtra, nRange0+k)) ); // get new fanin arrays pFans0 = Vec_IntArray( vTemp0 ); pFans1 = Vec_IntArray( vTemp1 ); // bit-blast the multiplier in the external manager if ( fUseOldMultiplierBlasting ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); Wlc_BlastMultiplier2( pExtra, pArg0, pArg1, nRange, vTemp2, vRes ); Vec_IntShrink( vRes, nRange ); } else { int fSigned = Wlc_ObjIsSignedFanin01(p, pObj); int nRangeMax = Abc_MaxInt(nRange0, nRange1); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, fSigned ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned ); Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); if ( nRange > nRangeMax + nRangeMax ) Vec_IntFillExtra( vRes, nRange, fSigned ? Vec_IntEntryLast(vRes) : 0 ); else Vec_IntShrink( vRes, nRange ); assert( Vec_IntSize(vRes) == nRange ); } // create outputs in the external manager for ( k = 0; k < nRange; k++ ) Gia_ManAppendCo( pExtra, Vec_IntEntry(vRes, k) ); // create combinational inputs in the normal manager Vec_IntClear( vRes ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Gia_ManAppendCi(pNew) ); } else if ( Wlc_ObjIsCi(pObj) ) { if ( Wlc_ObjRangeIsReversed(pObj) ) { for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, -1 ); for ( k = 0; k < nRange; k++ ) Vec_IntWriteEntry( vRes, Vec_IntSize(vRes)-1-k, Gia_ManAppendCi(pNew) ); } else { for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Gia_ManAppendCi(pNew) ); } if ( pObj->Type == WLC_OBJ_FO ) nFFouts += Vec_IntSize(vRes); } else if ( pObj->Type == WLC_OBJ_BUF ) { int nRangeMax = Abc_MaxInt( nRange0, nRange ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin0(p, pObj) ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, pArg0[k] ); } else if ( pObj->Type == WLC_OBJ_CONST ) { word * pTruth = (word *)Wlc_ObjFanins(pObj); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Abc_TtGetBit(pTruth, k) ); } else if ( pObj->Type == WLC_OBJ_MUX ) { // It is strange and disturbing that Verilog standard treats these statements differently: // Statement 1: // assign o = i ? b : a; // Statement 2: // always @( i or a or b ) // begin // case ( i ) // 0 : o = a ; // 1 : o = b ; // endcase // end // If a is signed and b is unsigned, Statement 1 does not sign-extend a, while Statement 2 does. // The signedness of o does not matter. // // Below we (somewhat arbitrarily) distinguish these two by assuming that // Statement 1 has three fanins, while Statement 2 has more than three fanins. // int fSigned = 1; assert( nRange0 >= 1 && Wlc_ObjFaninNum(pObj) >= 3 ); assert( 1 + (1 << nRange0) == Wlc_ObjFaninNum(pObj) ); Wlc_ObjForEachFanin( pObj, iFanin, k ) if ( k > 0 ) fSigned &= Wlc_NtkObj(p, iFanin)->Signed; for ( b = 0; b < nRange; b++ ) { Vec_IntClear( vTemp0 ); Wlc_ObjForEachFanin( pObj, iFanin, k ) if ( k > 0 ) { nRange1 = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); pFans1 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, iFanin) ); if ( Wlc_ObjFaninNum(pObj) == 3 ) // Statement 1 Vec_IntPush( vTemp0, b < nRange1 ? pFans1[b] : (fSigned? pFans1[nRange1-1] : 0) ); else // Statement 2 Vec_IntPush( vTemp0, b < nRange1 ? pFans1[b] : (Wlc_NtkObj(p, iFanin)->Signed? pFans1[nRange1-1] : 0) ); } Vec_IntPush( vRes, Wlc_NtkMuxTree_rec(pNew, pFans0, nRange0, vTemp0, 0) ); } } else if ( pObj->Type == WLC_OBJ_SHIFT_R || pObj->Type == WLC_OBJ_SHIFT_RA || pObj->Type == WLC_OBJ_SHIFT_L || pObj->Type == WLC_OBJ_SHIFT_LA ) { int nRangeMax = Abc_MaxInt( nRange, nRange0 ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin0(p, pObj) ); if ( pObj->Type == WLC_OBJ_SHIFT_R || pObj->Type == WLC_OBJ_SHIFT_RA ) Wlc_BlastShiftRight( pNew, pArg0, nRangeMax, pFans1, nRange1, Wlc_ObjIsSignedFanin0(p, pObj) && pObj->Type == WLC_OBJ_SHIFT_RA, vRes ); else Wlc_BlastShiftLeft( pNew, pArg0, nRangeMax, pFans1, nRange1, 0, vRes ); Vec_IntShrink( vRes, nRange ); } else if ( pObj->Type == WLC_OBJ_ROTATE_R ) { assert( nRange0 == nRange ); Wlc_BlastRotateRight( pNew, pFans0, nRange0, pFans1, nRange1, vRes ); } else if ( pObj->Type == WLC_OBJ_ROTATE_L ) { assert( nRange0 == nRange ); Wlc_BlastRotateLeft( pNew, pFans0, nRange0, pFans1, nRange1, vRes ); } else if ( pObj->Type == WLC_OBJ_BIT_NOT ) { int nRangeMax = Abc_MaxInt( nRange, nRange0 ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin0(p, pObj) ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Abc_LitNot(pArg0[k]) ); } else if ( pObj->Type == WLC_OBJ_BIT_AND || pObj->Type == WLC_OBJ_BIT_NAND ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Abc_LitNotCond(Gia_ManHashAnd(pNew, pArg0[k], pArg1[k]), pObj->Type == WLC_OBJ_BIT_NAND) ); } else if ( pObj->Type == WLC_OBJ_BIT_OR || pObj->Type == WLC_OBJ_BIT_NOR ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Abc_LitNotCond(Gia_ManHashOr(pNew, pArg0[k], pArg1[k]), pObj->Type == WLC_OBJ_BIT_NOR) ); } else if ( pObj->Type == WLC_OBJ_BIT_XOR || pObj->Type == WLC_OBJ_BIT_NXOR ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); for ( k = 0; k < nRange; k++ ) Vec_IntPush( vRes, Abc_LitNotCond(Gia_ManHashXor(pNew, pArg0[k], pArg1[k]), pObj->Type == WLC_OBJ_BIT_NXOR) ); } else if ( pObj->Type == WLC_OBJ_BIT_SELECT ) { Wlc_Obj_t * pFanin = Wlc_ObjFanin0(p, pObj); int End = Wlc_ObjRangeEnd(pObj); int Beg = Wlc_ObjRangeBeg(pObj); if ( End >= Beg ) { assert( nRange == End - Beg + 1 ); assert( pFanin->Beg <= Beg && End <= pFanin->End ); for ( k = Beg; k <= End; k++ ) Vec_IntPush( vRes, pFans0[k - pFanin->Beg] ); } else { assert( nRange == Beg - End + 1 ); assert( pFanin->End <= End && Beg <= pFanin->Beg ); for ( k = End; k <= Beg; k++ ) Vec_IntPush( vRes, pFans0[k - pFanin->End] ); } } else if ( pObj->Type == WLC_OBJ_BIT_CONCAT ) { int iFanin, nTotal = 0; Wlc_ObjForEachFanin( pObj, iFanin, k ) nTotal += Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); assert( nRange == nTotal ); Wlc_ObjForEachFaninReverse( pObj, iFanin, k ) { nRange0 = Wlc_ObjRange( Wlc_NtkObj(p, iFanin) ); pFans0 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, iFanin) ); for ( b = 0; b < nRange0; b++ ) Vec_IntPush( vRes, pFans0[b] ); } } else if ( pObj->Type == WLC_OBJ_BIT_ZEROPAD || pObj->Type == WLC_OBJ_BIT_SIGNEXT ) { int Pad = pObj->Type == WLC_OBJ_BIT_ZEROPAD ? 0 : pFans0[nRange0-1]; assert( nRange0 <= nRange ); for ( k = 0; k < nRange0; k++ ) Vec_IntPush( vRes, pFans0[k] ); for ( ; k < nRange; k++ ) Vec_IntPush( vRes, Pad ); } else if ( pObj->Type == WLC_OBJ_LOGIC_NOT ) { iLit = Wlc_BlastReduction( pNew, pFans0, nRange0, WLC_OBJ_REDUCT_OR ); Vec_IntFill( vRes, 1, Abc_LitNot(iLit) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( pObj->Type == WLC_OBJ_LOGIC_IMPL ) { int iLit0 = Wlc_BlastReduction( pNew, pFans0, nRange0, WLC_OBJ_REDUCT_OR ); int iLit1 = Wlc_BlastReduction( pNew, pFans1, nRange1, WLC_OBJ_REDUCT_OR ); Vec_IntFill( vRes, 1, Gia_ManHashOr(pNew, Abc_LitNot(iLit0), iLit1) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( pObj->Type == WLC_OBJ_LOGIC_AND ) { int iLit0 = Wlc_BlastReduction( pNew, pFans0, nRange0, WLC_OBJ_REDUCT_OR ); int iLit1 = Wlc_BlastReduction( pNew, pFans1, nRange1, WLC_OBJ_REDUCT_OR ); Vec_IntFill( vRes, 1, Gia_ManHashAnd(pNew, iLit0, iLit1) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( pObj->Type == WLC_OBJ_LOGIC_OR ) { int iLit0 = Wlc_BlastReduction( pNew, pFans0, nRange0, WLC_OBJ_REDUCT_OR ); int iLit1 = Wlc_BlastReduction( pNew, pFans1, nRange1, WLC_OBJ_REDUCT_OR ); Vec_IntFill( vRes, 1, Gia_ManHashOr(pNew, iLit0, iLit1) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( pObj->Type == WLC_OBJ_LOGIC_XOR ) { int iLit0 = Wlc_BlastReduction( pNew, pFans0, nRange0, WLC_OBJ_REDUCT_OR ); int iLit1 = Wlc_BlastReduction( pNew, pFans1, nRange1, WLC_OBJ_REDUCT_OR ); Vec_IntFill( vRes, 1, Gia_ManHashXor(pNew, iLit0, iLit1) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( pObj->Type == WLC_OBJ_COMP_EQU || pObj->Type == WLC_OBJ_COMP_NOTEQU ) { int iLit = 0, nRangeMax = Abc_MaxInt( nRange0, nRange1 ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); for ( k = 0; k < nRangeMax; k++ ) iLit = Gia_ManHashOr( pNew, iLit, Gia_ManHashXor(pNew, pArg0[k], pArg1[k]) ); Vec_IntFill( vRes, 1, Abc_LitNotCond(iLit, pObj->Type == WLC_OBJ_COMP_EQU) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( pObj->Type == WLC_OBJ_COMP_LESS || pObj->Type == WLC_OBJ_COMP_MOREEQU || pObj->Type == WLC_OBJ_COMP_MORE || pObj->Type == WLC_OBJ_COMP_LESSEQU ) { int nRangeMax = Abc_MaxInt( nRange0, nRange1 ); int fSigned = Wlc_ObjIsSignedFanin01(p, pObj); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, fSigned ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned ); int fSwap = (pObj->Type == WLC_OBJ_COMP_MORE || pObj->Type == WLC_OBJ_COMP_LESSEQU); int fCompl = (pObj->Type == WLC_OBJ_COMP_MOREEQU || pObj->Type == WLC_OBJ_COMP_LESSEQU); if ( fSwap ) ABC_SWAP( int *, pArg0, pArg1 ); if ( fSigned ) iLit = Wlc_BlastLessSigned( pNew, pArg0, pArg1, nRangeMax ); else iLit = Wlc_BlastLess( pNew, pArg0, pArg1, nRangeMax ); iLit = Abc_LitNotCond( iLit, fCompl ); Vec_IntFill( vRes, 1, iLit ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( pObj->Type == WLC_OBJ_REDUCT_AND || pObj->Type == WLC_OBJ_REDUCT_OR || pObj->Type == WLC_OBJ_REDUCT_XOR || pObj->Type == WLC_OBJ_REDUCT_NAND || pObj->Type == WLC_OBJ_REDUCT_NOR || pObj->Type == WLC_OBJ_REDUCT_NXOR ) { Vec_IntPush( vRes, Wlc_BlastReduction( pNew, pFans0, nRange0, pObj->Type ) ); for ( k = 1; k < nRange; k++ ) Vec_IntPush( vRes, 0 ); } else if ( pObj->Type == WLC_OBJ_ARI_ADD || pObj->Type == WLC_OBJ_ARI_SUB ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Wlc_VecLoadFanins( vRes, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); if ( pObj->Type == WLC_OBJ_ARI_ADD ) Wlc_BlastAdder( pNew, pArg0, pArg1, nRange ); // result is in pFan0 (vRes) // Wlc_BlastAdderCLA( pNew, pArg0, pArg1, nRange ); // result is in pFan0 (vRes) else Wlc_BlastSubtract( pNew, pArg0, pArg1, nRange ); // result is in pFan0 (vRes) Vec_IntShrink( vRes, nRange ); } else if ( pObj->Type == WLC_OBJ_ARI_MULTI ) { if ( fUseOldMultiplierBlasting ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, Wlc_ObjIsSignedFanin01(p, pObj) ); Wlc_BlastMultiplier2( pNew, pArg0, pArg1, nRange, vTemp2, vRes ); Vec_IntShrink( vRes, nRange ); } else { int fSigned = Wlc_ObjIsSignedFanin01(p, pObj); int nRangeMax = Abc_MaxInt(nRange0, nRange1); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, fSigned ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned ); if ( Wlc_NtkCountConstBits(pArg0, nRangeMax) < Wlc_NtkCountConstBits(pArg1, nRangeMax) ) ABC_SWAP( int *, pArg0, pArg1 ); if ( fBooth ) Wlc_BlastBooth( pNew, pArg0, pArg1, nRange0, nRange1, vRes, fSigned ); else Wlc_BlastMultiplier( pNew, pArg0, pArg1, nRangeMax, nRangeMax, vTemp2, vRes, fSigned ); //Wlc_BlastMultiplier3( pNew, pArg0, pArg1, nRange0, nRange1, vRes ); if ( nRange > Vec_IntSize(vRes) ) Vec_IntFillExtra( vRes, nRange, fSigned ? Vec_IntEntryLast(vRes) : 0 ); else Vec_IntShrink( vRes, nRange ); assert( Vec_IntSize(vRes) == nRange ); } } else if ( pObj->Type == WLC_OBJ_ARI_DIVIDE || pObj->Type == WLC_OBJ_ARI_REM || pObj->Type == WLC_OBJ_ARI_MODULUS ) { int nRangeMax = Abc_MaxInt( nRange, Abc_MaxInt(nRange0, nRange1) ); int fSigned = Wlc_ObjIsSignedFanin01(p, pObj); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, fSigned ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRangeMax, fSigned ); if ( fSigned ) Wlc_BlastDividerSigned( pNew, pArg0, nRangeMax, pArg1, nRangeMax, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes ); else Wlc_BlastDivider( pNew, pArg0, nRangeMax, pArg1, nRangeMax, pObj->Type == WLC_OBJ_ARI_DIVIDE, vRes ); Vec_IntShrink( vRes, nRange ); //if ( pObj->Type == WLC_OBJ_ARI_DIVIDE ) Wlc_BlastZeroCondition( pNew, pFans1, nRange1, vRes ); } else if ( pObj->Type == WLC_OBJ_ARI_MINUS ) { int nRangeMax = Abc_MaxInt( nRange0, nRange ); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin0(p, pObj) ); Wlc_BlastMinus( pNew, pArg0, nRangeMax, vRes ); Vec_IntShrink( vRes, nRange ); } else if ( pObj->Type == WLC_OBJ_ARI_POWER ) { int nRangeMax = Abc_MaxInt(nRange0, nRange); int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRangeMax, Wlc_ObjIsSignedFanin0(p, pObj) ); int * pArg1 = Wlc_VecLoadFanins( vTemp1, pFans1, nRange1, nRange1, Wlc_ObjIsSignedFanin1(p, pObj) ); Wlc_BlastPower( pNew, pArg0, nRangeMax, pArg1, nRange1, vTemp2, vRes ); Vec_IntShrink( vRes, nRange ); } else if ( pObj->Type == WLC_OBJ_ARI_SQRT ) { int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRange0 + (nRange0 & 1), 0 ); nRange0 += (nRange0 & 1); Wlc_BlastSqrt( pNew, pArg0, nRange0, vTemp2, vRes ); if ( nRange > Vec_IntSize(vRes) ) Vec_IntFillExtra( vRes, nRange, 0 ); else Vec_IntShrink( vRes, nRange ); } else if ( pObj->Type == WLC_OBJ_ARI_SQUARE ) { int * pArg0 = Wlc_VecLoadFanins( vTemp0, pFans0, nRange0, nRange0, 0 ); Wlc_BlastSquare( pNew, pArg0, nRange0, vTemp2, vRes ); if ( nRange > Vec_IntSize(vRes) ) Vec_IntFillExtra( vRes, nRange, 0 ); else Vec_IntShrink( vRes, nRange ); } else if ( pObj->Type == WLC_OBJ_TABLE ) Wlc_BlastTable( pNew, Wlc_ObjTable(p, pObj), pFans0, nRange0, nRange, vRes ); else assert( 0 ); assert( Vec_IntSize(vBits) == Wlc_ObjCopy(p, i) ); Vec_IntAppend( vBits, vRes ); if ( vAddOutputs && !Wlc_ObjIsCo(pObj) && ( (pObj->Type >= WLC_OBJ_MUX && pObj->Type <= WLC_OBJ_ROTATE_L) || (pObj->Type >= WLC_OBJ_COMP_EQU && pObj->Type <= WLC_OBJ_COMP_MOREEQU) || (pObj->Type >= WLC_OBJ_ARI_ADD && pObj->Type <= WLC_OBJ_ARI_SQUARE) ) ) { Vec_IntAppend( vAddOutputs, vRes ); Vec_IntPush( vAddObjs, Wlc_ObjId(p, pObj) ); } p->nAnds[pObj->Type] += Gia_ManAndNum(pNew) - nAndPrev; } p->nAnds[0] = Gia_ManAndNum(pNew); assert( nBits == Vec_IntSize(vBits) ); Vec_IntFree( vTemp0 ); Vec_IntFree( vTemp1 ); Vec_IntFree( vTemp2 ); Vec_IntFree( vRes ); // create COs Wlc_NtkForEachCo( p, pObj, i ) { // skip all outputs except the given ones if ( iOutput >= 0 && (i < iOutput || i >= iOutput + nOutputRange) ) continue; // create additional PO literals if ( vAddOutputs && pObj->fIsFi ) { Vec_IntForEachEntry( vAddOutputs, iLit, k ) Gia_ManAppendCo( pNew, iLit ); printf( "Created %d additional POs for %d interesting internal word-level variables.\n", Vec_IntSize(vAddOutputs), Vec_IntSize(vAddObjs) ); Vec_IntFreeP( &vAddOutputs ); } nRange = Wlc_ObjRange( pObj ); pFans0 = Vec_IntEntryP( vBits, Wlc_ObjCopy(p, Wlc_ObjId(p, pObj)) ); if ( fVerbose ) printf( "%s(%d) ", Wlc_ObjName(p, Wlc_ObjId(p, pObj)), Gia_ManCoNum(pNew) ); if ( Wlc_ObjRangeIsReversed(pObj) ) { for ( k = 0; k < nRange; k++ ) Gia_ManAppendCo( pNew, pFans0[nRange-1-k] ); } else { for ( k = 0; k < nRange; k++ ) Gia_ManAppendCo( pNew, pFans0[k] ); } if ( pObj->fIsFi ) nFFins += nRange; } if ( fVerbose ) printf( "\n" ); //Vec_IntErase( vBits ); //Vec_IntErase( &p->vCopies ); // set the number of registers assert( nFFins == nFFouts ); Gia_ManSetRegNum( pNew, nFFins ); // finalize AIG if ( !fGiaSimple ) { pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManDupRemapLiterals( vBits, pTemp ); Gia_ManStop( pTemp ); } // transform AIG with init state if ( p->pInits ) { if ( (int)strlen(p->pInits) != Gia_ManRegNum(pNew) ) { printf( "The number of init values (%d) does not match the number of flops (%d).\n", (int)strlen(p->pInits), Gia_ManRegNum(pNew) ); printf( "It is assumed that the AIG has constant 0 initial state.\n" ); } else { pNew = Gia_ManDupZeroUndc( pTemp = pNew, p->pInits, fGiaSimple, 1 ); Gia_ManDupRemapLiterals( vBits, pTemp ); Gia_ManStop( pTemp ); } } // finalize AIG with boxes if ( vBoxIds ) { curPo += nBitCos; assert( curPi == Tim_ManCiNum(pManTime) ); assert( curPo == Tim_ManCoNum(pManTime) ); // finalize the extra AIG pExtra = Gia_ManCleanup( pTemp = pExtra ); Gia_ManStop( pTemp ); assert( Gia_ManPoNum(pExtra) == Gia_ManCiNum(pNew) - nBitCis ); // attach pNew->pAigExtra = pExtra; pNew->pManTime = pManTime; // normalize AIG pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); Gia_ManTransferTiming( pNew, pTemp ); Gia_ManStop( pTemp ); //Tim_ManPrint( pManTime ); } // create input names pNew->vNamesIn = Vec_PtrAlloc( Gia_ManCiNum(pNew) ); Wlc_NtkForEachCi( p, pObj, i ) if ( Wlc_ObjIsPi(pObj) ) { char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); nRange = Wlc_ObjRange( pObj ); if ( nRange == 1 ) Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(pName) ); else for ( k = 0; k < nRange; k++ ) { char Buffer[1000]; sprintf( Buffer, "%s[%d]", pName, k ); Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); } } if ( p->pInits ) { int Length = strlen(p->pInits); for ( i = 0; i < Length; i++ ) if ( p->pInits[i] == 'x' || p->pInits[i] == 'X' ) { char Buffer[100]; sprintf( Buffer, "%s%d", "init", i ); Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); fAdded = 1; } } Wlc_NtkForEachCi( p, pObj, i ) if ( !Wlc_ObjIsPi(pObj) ) { char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); nRange = Wlc_ObjRange( pObj ); if ( nRange == 1 ) Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(pName) ); else for ( k = 0; k < nRange; k++ ) { char Buffer[1000]; sprintf( Buffer, "%s[%d]", pName, k ); Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav(Buffer) ); } } if ( p->pInits && fAdded ) Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsav("abc_reset_flop") ); assert( Vec_PtrSize(pNew->vNamesIn) == Gia_ManCiNum(pNew) ); // create output names if ( vAddObjs ) { // add real primary outputs pNew->vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pNew) ); Wlc_NtkForEachCo( p, pObj, i ) if ( Wlc_ObjIsPo(pObj) ) { char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); nRange = Wlc_ObjRange( pObj ); if ( nRange == 1 ) Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(pName) ); else for ( k = 0; k < nRange; k++ ) { char Buffer[1000]; sprintf( Buffer, "%s[%d]", pName, k ); Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); } } // add internal primary outputs Wlc_NtkForEachObjVec( vAddObjs, p, pObj, i ) { char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); nRange = Wlc_ObjRange( pObj ); if ( nRange == 1 ) Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(pName) ); else for ( k = 0; k < nRange; k++ ) { char Buffer[1000]; sprintf( Buffer, "%s[%d]", pName, k ); Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); } } Vec_IntFreeP( &vAddObjs ); // add flop outputs if ( fAdded ) Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav("abc_reset_flop_in") ); Wlc_NtkForEachCo( p, pObj, i ) if ( !Wlc_ObjIsPo(pObj) ) { char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); nRange = Wlc_ObjRange( pObj ); if ( nRange == 1 ) Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(pName) ); else for ( k = 0; k < nRange; k++ ) { char Buffer[1000]; sprintf( Buffer, "%s[%d]", pName, k ); Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsav(Buffer) ); } } assert( Vec_PtrSize(pNew->vNamesOut) == Gia_ManCoNum(pNew) ); } pNew->pSpec = Abc_UtilStrsav( p->pSpec ? p->pSpec : p->pName ); // dump the miter parts if ( 0 ) { char pFileName0[1000], pFileName1[1000]; char * pNameGeneric = Extra_FileNameGeneric( p->pSpec ); Vec_Int_t * vOrder = Vec_IntStartNatural( Gia_ManPoNum(pNew) ); Gia_Man_t * pGia0 = Gia_ManDupCones( pNew, Vec_IntArray(vOrder), Vec_IntSize(vOrder)/2, 0 ); Gia_Man_t * pGia1 = Gia_ManDupCones( pNew, Vec_IntArray(vOrder) + Vec_IntSize(vOrder)/2, Vec_IntSize(vOrder)/2, 0 ); assert( Gia_ManPoNum(pNew) % 2 == 0 ); sprintf( pFileName0, "%s_lhs_.aig", pNameGeneric ); sprintf( pFileName1, "%s_rhs_.aig", pNameGeneric ); Gia_AigerWrite( pGia0, pFileName0, 0, 0 ); Gia_AigerWrite( pGia1, pFileName1, 0, 0 ); Gia_ManStop( pGia0 ); Gia_ManStop( pGia1 ); Vec_IntFree( vOrder ); ABC_FREE( pNameGeneric ); printf( "Dumped two parts of the miter into files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcCom.c000066400000000000000000000500701300674244400231250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcCom.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Command handlers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcCom.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_CommandReadWlc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandWriteWlc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPsInv ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGetInv ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static inline Wlc_Ntk_t * Wlc_AbcGetNtk( Abc_Frame_t * pAbc ) { return (Wlc_Ntk_t *)pAbc->pAbcWlc; } static inline void Wlc_AbcFreeNtk( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcWlc ) Wlc_NtkFree(Wlc_AbcGetNtk(pAbc)); } static inline void Wlc_AbcUpdateNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk ) { Wlc_AbcFreeNtk(pAbc); pAbc->pAbcWlc = pNtk; } static inline Vec_Int_t * Wlc_AbcGetInv( Abc_Frame_t * pAbc ) { return pAbc->pAbcWlcInv; } static inline Vec_Int_t * Wlc_AbcGetCnf( Abc_Frame_t * pAbc ) { return pAbc->pAbcWlcCnf; } static inline Vec_Str_t * Wlc_AbcGetStr( Abc_Frame_t * pAbc ) { return pAbc->pAbcWlcStr; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Wlc_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "Word level", "%read", Abc_CommandReadWlc, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%write", Abc_CommandWriteWlc, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%ps", Abc_CommandPs, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%blast", Abc_CommandBlast, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%psinv", Abc_CommandPsInv, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%getinv", Abc_CommandGetInv, 0 ); Cmd_CommandAdd( pAbc, "Word level", "%test", Abc_CommandTest, 0 ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Wlc_End( Abc_Frame_t * pAbc ) { Wlc_AbcFreeNtk( pAbc ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Wlc_SetNtk( Abc_Frame_t * pAbc, Wlc_Ntk_t * pNtk ) { Wlc_AbcUpdateNtk( pAbc, pNtk ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Abc_CommandReadWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Wlc_Ntk_t * pNtk = NULL; char * pFileName = NULL; int fOldParser = 0; int fPrintTree = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "opvh" ) ) != EOF ) { switch ( c ) { case 'o': fOldParser ^= 1; break; case 'p': fPrintTree ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { printf( "Abc_CommandReadWlc(): Input file name should be given on the command line.\n" ); return 0; } // get the file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "r" )) == NULL ) { Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".smt", ".smt2", NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", pFileName ); Abc_Print( 1, "\n" ); return 0; } fclose( pFile ); // perform reading if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) ) pNtk = Wlc_ReadVer( pFileName ); else if ( !strcmp( Extra_FileNameExtension(pFileName), "smt" ) || !strcmp( Extra_FileNameExtension(pFileName), "smt2" ) ) pNtk = Wlc_ReadSmt( pFileName, fOldParser, fPrintTree ); else { printf( "Abc_CommandReadWlc(): Unknown file extension.\n" ); return 0; } Wlc_AbcUpdateNtk( pAbc, pNtk ); return 0; usage: Abc_Print( -2, "usage: %%read [-opvh] \n" ); Abc_Print( -2, "\t reads word-level design from Verilog file\n" ); Abc_Print( -2, "\t-o : toggle using old SMT-LIB parser [default = %s]\n", fOldParser? "yes": "no" ); Abc_Print( -2, "\t-p : toggle printing parse SMT-LIB tree [default = %s]\n", fPrintTree? "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_CommandWriteWlc( Abc_Frame_t * pAbc, int argc, char ** argv ) { Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); char * pFileName = NULL; int fAddCos = 0; int fSplitNodes = 0; int fNoFlops = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "anfvh" ) ) != EOF ) { switch ( c ) { case 'a': fAddCos ^= 1; break; case 'n': fSplitNodes ^= 1; break; case 'f': fNoFlops ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( 1, "Abc_CommandWriteWlc(): There is no current design.\n" ); return 0; } if ( argc == globalUtilOptind ) pFileName = Extra_FileNameGenericAppend( pNtk->pName, "_out.v" ); else if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; else { printf( "Output file name should be given on the command line.\n" ); return 0; } if ( fSplitNodes ) { pNtk = Wlc_NtkDupSingleNodes( pNtk ); Wlc_WriteVer( pNtk, pFileName, fAddCos, fNoFlops ); Wlc_NtkFree( pNtk ); } else Wlc_WriteVer( pNtk, pFileName, fAddCos, fNoFlops ); return 0; usage: Abc_Print( -2, "usage: %%write [-anfvh]\n" ); Abc_Print( -2, "\t writes the design into a file\n" ); Abc_Print( -2, "\t-a : toggle adding a CO for each node [default = %s]\n", fAddCos? "yes": "no" ); Abc_Print( -2, "\t-n : toggle splitting into individual nodes [default = %s]\n", fSplitNodes? "yes": "no" ); Abc_Print( -2, "\t-f : toggle skipping flops when writing file [default = %s]\n",fNoFlops? "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_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv ) { Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); int fShowMulti = 0; int fShowAdder = 0; int fDistrib = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "madvh" ) ) != EOF ) { switch ( c ) { case 'm': fShowMulti ^= 1; break; case 'a': fShowAdder ^= 1; break; case 'd': fDistrib ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( 1, "Abc_CommandPs(): There is no current design.\n" ); return 0; } Wlc_NtkPrintStats( pNtk, fDistrib, fVerbose ); if ( fShowMulti ) Wlc_NtkPrintNodes( pNtk, WLC_OBJ_ARI_MULTI ); if ( fShowAdder ) Wlc_NtkPrintNodes( pNtk, WLC_OBJ_ARI_ADD ); return 0; usage: Abc_Print( -2, "usage: %%ps [-madvh]\n" ); Abc_Print( -2, "\t prints statistics\n" ); Abc_Print( -2, "\t-m : toggle printing multipliers [default = %s]\n", fShowMulti? "yes": "no" ); Abc_Print( -2, "\t-a : toggle printing adders [default = %s]\n", fShowAdder? "yes": "no" ); Abc_Print( -2, "\t-d : toggle printing distrubition [default = %s]\n", fDistrib? "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_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv ) { Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); Vec_Int_t * vBoxIds = NULL; Gia_Man_t * pNew = NULL; int c, iOutput = -1, nOutputRange = 2, fGiaSimple = 0, fAddOutputs = 0, fMulti = 0, fBooth = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ORcombvh" ) ) != EOF ) { switch ( c ) { case 'O': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } iOutput = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iOutput < 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; } nOutputRange = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nOutputRange < 0 ) goto usage; break; case 'c': fGiaSimple ^= 1; break; case 'o': fAddOutputs ^= 1; break; case 'm': fMulti ^= 1; break; case 'b': fBooth ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( 1, "Abc_CommandBlast(): There is no current design.\n" ); return 0; } if ( fMulti ) { vBoxIds = Wlc_NtkCollectMultipliers( pNtk ); if ( vBoxIds == NULL ) Abc_Print( 1, "Warning: There is no multipliers in the design.\n" ); } if ( iOutput >= 0 && iOutput + nOutputRange > Wlc_NtkPoNum(pNtk) ) { Abc_Print( 1, "Abc_CommandBlast(): The output range [%d:%d] is incorrect.\n", iOutput, iOutput + nOutputRange - 1 ); return 0; } // transform pNew = Wlc_NtkBitBlast( pNtk, vBoxIds, iOutput, nOutputRange, fGiaSimple, fAddOutputs, fBooth ); Vec_IntFreeP( &vBoxIds ); if ( pNew == NULL ) { Abc_Print( 1, "Abc_CommandBlast(): Bit-blasting has failed.\n" ); return 0; } Abc_FrameUpdateGia( pAbc, pNew ); return 0; usage: Abc_Print( -2, "usage: %%blast [-OR num] [-combvh]\n" ); Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" ); Abc_Print( -2, "\t-O num : zero-based index of the first word-level PO to bit-blast [default = %d]\n", iOutput ); Abc_Print( -2, "\t-R num : the total number of word-level POs to bit-blast [default = %d]\n", nOutputRange ); Abc_Print( -2, "\t-c : toggle using AIG w/o const propagation and strashing [default = %s]\n", fGiaSimple? "yes": "no" ); Abc_Print( -2, "\t-o : toggle using additional POs on the word-level boundaries [default = %s]\n", fAddOutputs? "yes": "no" ); Abc_Print( -2, "\t-m : toggle creating boxes for all multipliers in the design [default = %s]\n", fMulti? "yes": "no" ); Abc_Print( -2, "\t-b : toggle generating radix-4 Booth multipliers [default = %s]\n", fBooth? "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_CommandPsInv( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Wlc_NtkPrintInvStats( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv, int fVerbose ); Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); 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, "Abc_CommandPsInv(): There is no current design.\n" ); return 0; } if ( Wlc_AbcGetNtk(pAbc) == NULL ) { Abc_Print( 1, "Abc_CommandPsInv(): There is no saved invariant.\n" ); return 0; } if ( Wlc_AbcGetInv(pAbc) == NULL ) { Abc_Print( 1, "Abc_CommandPsInv(): Invariant is not available.\n" ); return 0; } Wlc_NtkPrintInvStats( pNtk, Wlc_AbcGetInv(pAbc), fVerbose ); return 0; usage: Abc_Print( -2, "usage: %%psinv [-vh]\n" ); Abc_Print( -2, "\t prints statistics for inductive invariant\n" ); Abc_Print( -2, "\t (in the case of \'sat\' or \'undecided\', inifity clauses are used)\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_CommandGetInv( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Wlc_NtkGetInv( Wlc_Ntk_t * pNtk, Vec_Int_t * vInv, Vec_Str_t * vSop, int fVerbose ); Abc_Ntk_t * pMainNtk; Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); 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, "Abc_CommandGetInv(): There is no current design.\n" ); return 0; } if ( Wlc_AbcGetNtk(pAbc) == NULL ) { Abc_Print( 1, "Abc_CommandGetInv(): There is no saved invariant.\n" ); return 0; } if ( Wlc_AbcGetInv(pAbc) == NULL ) { Abc_Print( 1, "Abc_CommandGetInv(): Invariant is not available.\n" ); return 0; } // derive the network pMainNtk = Wlc_NtkGetInv( pNtk, Wlc_AbcGetInv(pAbc), Wlc_AbcGetStr(pAbc), fVerbose ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pMainNtk ); return 0; usage: Abc_Print( -2, "usage: %%getinv [-vh]\n" ); Abc_Print( -2, "\t places invariant found by PDR as the current network in the main-space\n" ); Abc_Print( -2, "\t (in the case of \'sat\' or \'undecided\', inifity clauses are used)\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_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Wlc_NtkSimulateTest( Wlc_Ntk_t * p ); Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(pAbc); 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, "Abc_CommandBlast(): There is no current design.\n" ); return 0; } // transform //pNtk = Wlc_NtkUifNodePairs( pNtk, NULL ); //pNtk = Wlc_NtkAbstractNodes( pNtk, NULL ); //Wlc_AbcUpdateNtk( pAbc, pNtk ); //Wlc_GenerateSmtStdout( pAbc ); //Wlc_NtkSimulateTest( (Wlc_Ntk_t *)pAbc->pAbcWlc ); pNtk = Wlc_NtkDupSingleNodes( pNtk ); Wlc_AbcUpdateNtk( pAbc, pNtk ); return 0; usage: Abc_Print( -2, "usage: %%test [-vh]\n" ); Abc_Print( -2, "\t experiments with word-level networks\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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcNtk.c000066400000000000000000000740351300674244400231520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcNtk.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Network data-structure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcNtk.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "wlc.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // object types static char * Wlc_Names[WLC_OBJ_NUMBER+1] = { NULL, // 00: unknown "pi", // 01: primary input "po", // 02: primary output (unused) "ff", // 03: flop output "bi", // 04: flop input (unused) "ff", // 05: flop (unused) "const", // 06: constant "buf", // 07: buffer "mux", // 08: multiplexer ">>", // 09: shift right ">>>", // 10: shift right (arithmetic) "<<", // 11: shift left "<<<", // 12: shift left (arithmetic) "rotateR", // 13: rotate right "rotateL", // 14: rotate left "~", // 15: bitwise NOT "&", // 16: bitwise AND "|", // 17: bitwise OR "^", // 18: bitwise XOR "~&", // 19: bitwise NAND "~|", // 20: bitwise NOR "~^", // 21: bitwise NXOR "[:]", // 22: bit selection "{,}", // 23: bit concatenation "zeroPad", // 24: zero padding "signExt", // 25: sign extension "!", // 26: logic NOT "=>", // 27: logic implication "&&", // 28: logic AND "||", // 29: logic OR "^^", // 30: logic XOR "==", // 31: compare equal "!=", // 32: compare not equal "<", // 33: compare less ">", // 34: compare more "<=", // 35: compare less or equal ">=", // 36: compare more or equal "&", // 37: reduction AND "|", // 38: reduction OR "^", // 39: reduction XOR "~&", // 40: reduction NAND "~|", // 41: reduction NOR "~^", // 42: reduction NXOR "+", // 43: arithmetic addition "-", // 44: arithmetic subtraction "*", // 45: arithmetic multiplier "/", // 46: arithmetic division "%", // 47: arithmetic reminder "mod", // 48: arithmetic modulus "**", // 49: arithmetic power "-", // 50: arithmetic minus "sqrt", // 51: integer square root "square", // 52: integer square "table", // 53: bit table NULL // 54: unused }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Working with models.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Ntk_t * Wlc_NtkAlloc( char * pName, int nObjsAlloc ) { Wlc_Ntk_t * p; p = ABC_CALLOC( Wlc_Ntk_t, 1 ); p->pName = pName ? Extra_FileNameGeneric( pName ) : NULL; Vec_IntGrow( &p->vPis, 111 ); Vec_IntGrow( &p->vPos, 111 ); Vec_IntGrow( &p->vCis, 111 ); Vec_IntGrow( &p->vCos, 111 ); Vec_IntGrow( &p->vFfs, 111 ); p->pMemFanin = Mem_FlexStart(); p->nObjsAlloc = nObjsAlloc; p->pObjs = ABC_CALLOC( Wlc_Obj_t, p->nObjsAlloc ); p->iObj = 1; return p; } void Wlc_ObjSetCi( Wlc_Ntk_t * p, Wlc_Obj_t * pObj ) { assert( Wlc_ObjIsCi(pObj) ); assert( Wlc_ObjFaninNum(pObj) == 0 ); if ( Wlc_NtkPiNum(p) == Wlc_NtkCiNum(p) || pObj->Type != WLC_OBJ_PI ) { pObj->Fanins[1] = Vec_IntSize(&p->vCis); Vec_IntPush( &p->vCis, Wlc_ObjId(p, pObj) ); } else // insert in the array of CI at the end of PIs { Wlc_Obj_t * pTemp; int i; Vec_IntInsert( &p->vCis, Wlc_NtkPiNum(p), Wlc_ObjId(p, pObj) ); // other CI IDs are invalidated... naive fix! Wlc_NtkForEachCi( p, pTemp, i ) pTemp->Fanins[1] = i; } if ( pObj->Type == WLC_OBJ_PI ) Vec_IntPush( &p->vPis, Wlc_ObjId(p, pObj) ); } void Wlc_ObjSetCo( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, int fFlopInput ) { // pObj->Fanins[1] = Vec_IntSize(&p->vCos); Vec_IntPush( &p->vCos, Wlc_ObjId(p, pObj) ); if ( !fFlopInput ) Vec_IntPush( &p->vPos, Wlc_ObjId(p, pObj) ); if ( fFlopInput ) pObj->fIsFi = 1; else pObj->fIsPo = 1; } int Wlc_ObjAlloc( Wlc_Ntk_t * p, int Type, int Signed, int End, int Beg ) { Wlc_Obj_t * pObj; assert( Type != WLC_OBJ_PO && Type != WLC_OBJ_FI ); if ( p->iObj == p->nObjsAlloc ) { p->pObjs = ABC_REALLOC( Wlc_Obj_t, p->pObjs, 2 * p->nObjsAlloc ); memset( p->pObjs + p->nObjsAlloc, 0, sizeof(Wlc_Obj_t) * p->nObjsAlloc ); p->nObjsAlloc *= 2; } pObj = Wlc_NtkObj( p, p->iObj ); pObj->Type = Type; pObj->Signed = Signed; pObj->End = End; pObj->Beg = Beg; if ( Wlc_ObjIsCi(pObj) ) Wlc_ObjSetCi( p, pObj ); p->nObjs[Type]++; return p->iObj++; } int Wlc_ObjCreate( Wlc_Ntk_t * p, int Type, int Signed, int End, int Beg, Vec_Int_t * vFanins ) { int iFaninNew = Wlc_ObjAlloc( p, Type, Signed, End, Beg ); Wlc_ObjAddFanins( p, Wlc_NtkObj(p, iFaninNew), vFanins ); return iFaninNew; } char * Wlc_ObjName( Wlc_Ntk_t * p, int iObj ) { static char Buffer[100]; if ( Wlc_NtkHasNameId(p) && Wlc_ObjNameId(p, iObj) ) return Abc_NamStr( p->pManName, Wlc_ObjNameId(p, iObj) ); sprintf( Buffer, "n%d", iObj ); return Buffer; } void Wlc_ObjUpdateType( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, int Type ) { assert( pObj->Type == WLC_OBJ_NONE ); p->nObjs[pObj->Type]--; pObj->Type = Type; p->nObjs[pObj->Type]++; } void Wlc_ObjAddFanins( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Int_t * vFanins ) { assert( pObj->nFanins == 0 ); pObj->nFanins = Vec_IntSize(vFanins); if ( Wlc_ObjHasArray(pObj) ) pObj->pFanins[0] = (int *)Mem_FlexEntryFetch( p->pMemFanin, Vec_IntSize(vFanins) * sizeof(int) ); memcpy( Wlc_ObjFanins(pObj), Vec_IntArray(vFanins), sizeof(int) * Vec_IntSize(vFanins) ); // special treatment of CONST, SELECT and TABLE if ( pObj->Type == WLC_OBJ_CONST ) pObj->nFanins = 0; else if ( pObj->Type == WLC_OBJ_BIT_SELECT || pObj->Type == WLC_OBJ_TABLE ) pObj->nFanins = 1; } void Wlc_NtkFree( Wlc_Ntk_t * p ) { if ( p->pManName ) Abc_NamStop( p->pManName ); if ( p->pMemFanin ) Mem_FlexStop( p->pMemFanin, 0 ); if ( p->pMemTable ) Mem_FlexStop( p->pMemTable, 0 ); Vec_PtrFreeP( &p->vTables ); ABC_FREE( p->vPis.pArray ); ABC_FREE( p->vPos.pArray ); ABC_FREE( p->vCis.pArray ); ABC_FREE( p->vCos.pArray ); ABC_FREE( p->vFfs.pArray ); Vec_IntFreeP( &p->vInits ); ABC_FREE( p->vTravIds.pArray ); ABC_FREE( p->vNameIds.pArray ); ABC_FREE( p->vValues.pArray ); ABC_FREE( p->vCopies.pArray ); ABC_FREE( p->vBits.pArray ); ABC_FREE( p->pInits ); ABC_FREE( p->pObjs ); ABC_FREE( p->pName ); ABC_FREE( p->pSpec ); ABC_FREE( p ); } int Wlc_NtkMemUsage( Wlc_Ntk_t * p ) { int Mem = sizeof(Wlc_Ntk_t); Mem += 4 * p->vPis.nCap; Mem += 4 * p->vPos.nCap; Mem += 4 * p->vCis.nCap; Mem += 4 * p->vCos.nCap; Mem += 4 * p->vFfs.nCap; Mem += sizeof(Wlc_Obj_t) * p->nObjsAlloc; Mem += Abc_NamMemUsed(p->pManName); Mem += Mem_FlexReadMemUsage(p->pMemFanin); return Mem; } /**Function************************************************************* Synopsis [Prints distribution of operator types.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdSelectSortCost2( word * pArray, int nSize, word * pCosts ) { int i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pCosts[j] < pCosts[best_i] ) best_i = j; ABC_SWAP( word, pArray[i], pArray[best_i] ); ABC_SWAP( word, pCosts[i], pCosts[best_i] ); } } static inline word Wlc_NtkPrintDistribMakeSign( int s, int s0, int s1 ) { return ((word)s1 << 42) | ((word)s0 << 21) | (word)s; } static inline void Wlc_NtkPrintDistribFromSign( word sss, int * s, int * s0, int * s1 ) { *s1 = (int)(sss >> 42); *s0 = (int)(sss >> 21) & 0x1FFFFF; *s = (int)sss & 0x1FFFFF; } static inline void Wlc_NtkPrintDistribAddOne( Vec_Ptr_t * vTypes, Vec_Ptr_t * vOccurs, int Type, word Sign ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, Type ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, Type ); word Entry; int i; Vec_WrdForEachEntry( vType, Entry, i ) if ( Entry == Sign ) { Vec_WrdAddToEntry( vOccur, i, 1 ); return; } Vec_WrdPush( vType, Sign ); Vec_WrdPush( vOccur, 1 ); } void Wlc_NtkPrintDistribSortOne( Vec_Ptr_t * vTypes, Vec_Ptr_t * vOccurs, int Type ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, Type ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, Type ); Vec_WrdSelectSortCost2( Vec_WrdArray(vType), Vec_WrdSize(vType), Vec_WrdArray(vOccur) ); Vec_WrdReverseOrder( vType ); Vec_WrdReverseOrder( vOccur ); } void Wlc_NtkPrintDistrib( Wlc_Ntk_t * p, int fVerbose ) { Wlc_Obj_t * pObj, * pObjRange = NULL; int nCountRange = 0; Vec_Ptr_t * vTypes, * vOccurs; Vec_Int_t * vAnds = Vec_IntStart( WLC_OBJ_NUMBER ); word Sign; int i, k, s, s0, s1; // allocate statistics arrays vTypes = Vec_PtrStart( WLC_OBJ_NUMBER ); vOccurs = Vec_PtrStart( WLC_OBJ_NUMBER ); for ( i = 0; i < WLC_OBJ_NUMBER; i++ ) Vec_PtrWriteEntry( vTypes, i, Vec_WrdAlloc(16) ); for ( i = 0; i < WLC_OBJ_NUMBER; i++ ) Vec_PtrWriteEntry( vOccurs, i, Vec_WrdAlloc(16) ); // add nodes Wlc_NtkForEachObj( p, pObj, i ) { // char * pName = Wlc_ObjName(p, i); if ( Wlc_ObjSign(pObj) > 0x1FFFFF ) printf( "Object %6d has range %d, which is reduced to %d in the statistics.\n", i, Wlc_ObjRange(pObj), Wlc_ObjRange(pObj) & 0xFFFFF ); if ( pObj->Beg ) { if ( pObjRange == NULL ) pObjRange = pObj; nCountRange++; } // 0-input types if ( Wlc_ObjIsCi(pObj) || pObj->Type == WLC_OBJ_CONST || pObj->Type == WLC_OBJ_BIT_CONCAT ) Sign = Wlc_NtkPrintDistribMakeSign( Wlc_ObjSign(pObj), 0, 0 ); // 1-input types else if ( pObj->Type == WLC_OBJ_BUF || pObj->Type == WLC_OBJ_BIT_SELECT || pObj->Type == WLC_OBJ_TABLE || pObj->Type == WLC_OBJ_BIT_ZEROPAD || pObj->Type == WLC_OBJ_BIT_SIGNEXT || pObj->Type == WLC_OBJ_BIT_NOT || pObj->Type == WLC_OBJ_LOGIC_NOT || pObj->Type == WLC_OBJ_ARI_MINUS ) Sign = Wlc_NtkPrintDistribMakeSign( Wlc_ObjSign(pObj), Wlc_ObjSign(Wlc_ObjFanin0(p, pObj)), 0 ); // 2-input types (including MUX) else if ( Wlc_ObjFaninNum(pObj) == 1 ) Sign = Wlc_NtkPrintDistribMakeSign( Wlc_ObjSign(pObj), Wlc_ObjSign(Wlc_ObjFanin0(p, pObj)), 0 ); else { assert( Wlc_ObjFaninNum(pObj) >= 2 ); Sign = Wlc_NtkPrintDistribMakeSign( Wlc_ObjSign(pObj), Wlc_ObjSign(Wlc_ObjFanin0(p, pObj)), Wlc_ObjSign(Wlc_ObjFanin1(p, pObj)) ); } // add to storage Wlc_NtkPrintDistribAddOne( vTypes, vOccurs, pObj->Type, Sign ); // count the number of AIG nodes if ( pObj->Type == WLC_OBJ_MUX ) Vec_IntAddToEntry( vAnds, WLC_OBJ_MUX, 3 * Wlc_ObjRange(pObj) * (Wlc_ObjFaninNum(pObj) - 2) ); else if ( pObj->Type == WLC_OBJ_SHIFT_R ) Vec_IntAddToEntry( vAnds, WLC_OBJ_SHIFT_R, Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_SHIFT_RA ) Vec_IntAddToEntry( vAnds, WLC_OBJ_SHIFT_RA, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_SHIFT_L ) Vec_IntAddToEntry( vAnds, WLC_OBJ_SHIFT_L, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_SHIFT_LA ) Vec_IntAddToEntry( vAnds, WLC_OBJ_SHIFT_LA, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_ROTATE_R ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ROTATE_R, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_ROTATE_L ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ROTATE_L, Wlc_ObjRange(pObj) * Abc_MinInt(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Abc_Base2Log(Wlc_ObjRange(pObj))) * 3 ); else if ( pObj->Type == WLC_OBJ_BIT_NOT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_NOT, 0 ); else if ( pObj->Type == WLC_OBJ_BIT_AND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_AND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_OR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_OR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_XOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_XOR, 3 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_NAND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_NAND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_NOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_NOR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_NXOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_NXOR, 3 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_SELECT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_SELECT, 0 ); else if ( pObj->Type == WLC_OBJ_BIT_CONCAT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_CONCAT, 0 ); else if ( pObj->Type == WLC_OBJ_BIT_ZEROPAD ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_ZEROPAD, 0 ); else if ( pObj->Type == WLC_OBJ_BIT_SIGNEXT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_BIT_SIGNEXT, 0 ); else if ( pObj->Type == WLC_OBJ_LOGIC_NOT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_NOT, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_LOGIC_IMPL ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_IMPL, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_LOGIC_AND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_AND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_LOGIC_OR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_OR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_LOGIC_XOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_LOGIC_XOR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) + 1 ); else if ( pObj->Type == WLC_OBJ_COMP_EQU ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_EQU, 4 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_COMP_NOTEQU ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_NOTEQU, 4 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_COMP_LESS ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_LESS, 6 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 6 ); else if ( pObj->Type == WLC_OBJ_COMP_MORE ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_MORE, 6 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 6 ); else if ( pObj->Type == WLC_OBJ_COMP_LESSEQU ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_LESSEQU, 6 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 6 ); else if ( pObj->Type == WLC_OBJ_COMP_MOREEQU ) Vec_IntAddToEntry( vAnds, WLC_OBJ_COMP_MOREEQU, 6 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 6 ); else if ( pObj->Type == WLC_OBJ_REDUCT_AND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_AND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_REDUCT_OR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_OR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_REDUCT_XOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_XOR, 3 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 3 ); else if ( pObj->Type == WLC_OBJ_REDUCT_NAND ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_NAND, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_REDUCT_NOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_NOR, Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1 ); else if ( pObj->Type == WLC_OBJ_REDUCT_NXOR ) Vec_IntAddToEntry( vAnds, WLC_OBJ_REDUCT_NXOR, 3 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 3 ); else if ( pObj->Type == WLC_OBJ_ARI_ADD ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_ADD, 9 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_ARI_SUB ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_SUB, 9 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_ARI_MULTI ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_MULTI, 9 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_ARI_DIVIDE ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_DIVIDE, 13 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 19 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) + 10 ); else if ( pObj->Type == WLC_OBJ_ARI_REM ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_REM, 13 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 7 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 2 ); else if ( pObj->Type == WLC_OBJ_ARI_MODULUS ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_MODULUS, 13 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 7 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 2 ); else if ( pObj->Type == WLC_OBJ_ARI_POWER ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_POWER, 10 * (int)pow(Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)),Wlc_ObjRange(Wlc_ObjFanin0(p, pObj))) ); else if ( pObj->Type == WLC_OBJ_ARI_MINUS ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_MINUS, 4 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) ); else if ( pObj->Type == WLC_OBJ_ARI_SQRT ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_SQRT, 11 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) / 8 + 5 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) / 2 - 5 ); else if ( pObj->Type == WLC_OBJ_ARI_SQUARE ) Vec_IntAddToEntry( vAnds, WLC_OBJ_ARI_SQUARE, 5 * Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) * Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)) ); } if ( nCountRange ) { printf( "Warning: %d objects of the design have non-zero-based ranges.\n", nCountRange ); printf( "In particular, object %6d with name \"%s\" has range %d=[%d:%d]\n", Wlc_ObjId(p, pObjRange), Abc_NamStr(p->pManName, Wlc_ObjNameId(p, Wlc_ObjId(p, pObjRange))), Wlc_ObjRange(pObjRange), pObjRange->End, pObjRange->Beg ); } // print by occurrence printf( "ID : name occurrence and2 (occurrence)=. ...\n" ); for ( i = 0; i < WLC_OBJ_NUMBER; i++ ) { Vec_Wrd_t * vType = (Vec_Wrd_t *)Vec_PtrEntry( vTypes, i ); Vec_Wrd_t * vOccur = (Vec_Wrd_t *)Vec_PtrEntry( vOccurs, i ); if ( p->nObjs[i] == 0 ) continue; printf( "%2d : %-8s %6d%8d ", i, Wlc_Names[i], p->nObjs[i], Vec_IntEntry(vAnds, i) ); // sort by occurence Wlc_NtkPrintDistribSortOne( vTypes, vOccurs, i ); Vec_WrdForEachEntry( vType, Sign, k ) { Wlc_NtkPrintDistribFromSign( Sign, &s, &s0, &s1 ); if ( ((k % 6) == 5 && s1) || ((k % 8) == 7 && !s1) ) printf( "\n " ); printf( "(%d)", (int)Vec_WrdEntry( vOccur, k ) ); printf( "%s%d", Abc_LitIsCompl(s)?"-":"", Abc_Lit2Var(s) ); if ( s0 ) printf( "=%s%d", Abc_LitIsCompl(s0)?"-":"", Abc_Lit2Var(s0) ); if ( s1 ) printf( ".%s%d", Abc_LitIsCompl(s1)?"-":"", Abc_Lit2Var(s1) ); printf( " " ); } printf( "\n" ); } Vec_VecFree( (Vec_Vec_t *)vTypes ); Vec_VecFree( (Vec_Vec_t *)vOccurs ); Vec_IntFree( vAnds ); } void Wlc_NtkPrintNodes( Wlc_Ntk_t * p, int Type ) { Wlc_Obj_t * pObj; int i, Counter = 0; printf( "Operation %s\n", Wlc_Names[Type] ); Wlc_NtkForEachObj( p, pObj, i ) { if ( (int)pObj->Type != Type ) continue; printf( "%8d :", Counter++ ); printf( "%8d : ", i ); printf( "%3d%s = ", Wlc_ObjRange(pObj), Wlc_ObjIsSigned(pObj) ? "s" : " " ); printf( "%3d%s %s ", Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin0(p, pObj)) ? "s" : " ", Wlc_Names[Type] ); printf( "%3d%s ", Wlc_ObjRange(Wlc_ObjFanin1(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin1(p, pObj)) ? "s" : " " ); printf( " : " ); printf( "%-12s = ", Wlc_ObjName(p, i) ); printf( "%-12s %s ", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Wlc_Names[Type] ); printf( "%-12s ", Wlc_ObjName(p, Wlc_ObjFaninId1(pObj)) ); printf( "\n" ); } } void Wlc_NtkPrintStats( Wlc_Ntk_t * p, int fDistrib, int fVerbose ) { int i; printf( "%-20s : ", p->pName ); printf( "PI = %4d ", Wlc_NtkPiNum(p) ); printf( "PO = %4d ", Wlc_NtkPoNum(p) ); printf( "FF = %4d ", Wlc_NtkFfNum(p) ); printf( "Obj = %6d ", Wlc_NtkObjNum(p) ); printf( "Mem = %.3f MB", 1.0*Wlc_NtkMemUsage(p)/(1<<20) ); printf( "\n" ); if ( fDistrib ) { Wlc_NtkPrintDistrib( p, fVerbose ); return; } if ( !fVerbose ) return; printf( "Node type statistics:\n" ); for ( i = 1; i < WLC_OBJ_NUMBER; i++ ) { if ( !p->nObjs[i] ) continue; if ( p->nAnds[0] && p->nAnds[i] ) printf( "%2d : %-8s %6d %7.2f %%\n", i, Wlc_Names[i], p->nObjs[i], 100.0*p->nAnds[i]/p->nAnds[0] ); else printf( "%2d : %-8s %6d\n", i, Wlc_Names[i], p->nObjs[i] ); } } /**Function************************************************************* Synopsis [Duplicates the network in a topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_ObjCollectCopyFanins( Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) { int i, iFanin; Wlc_Obj_t * pObj = Wlc_NtkObj( p, iObj ); Vec_IntClear( vFanins ); Wlc_ObjForEachFanin( pObj, iFanin, i ) Vec_IntPush( vFanins, Wlc_ObjCopy(p, iFanin) ); // special treatment of CONST and SELECT if ( pObj->Type == WLC_OBJ_CONST ) { int * pInts = Wlc_ObjConstValue( pObj ); int nInts = Abc_BitWordNum( Wlc_ObjRange(pObj) ); for ( i = 0; i < nInts; i++ ) Vec_IntPush( vFanins, pInts[i] ); } else if ( pObj->Type == WLC_OBJ_BIT_SELECT ) { assert( Vec_IntSize(vFanins) == 1 ); Vec_IntPushTwo( vFanins, Wlc_ObjRangeEnd(pObj), Wlc_ObjRangeBeg(pObj) ); } else if ( pObj->Type == WLC_OBJ_TABLE ) { assert( Vec_IntSize(vFanins) == 1 ); Vec_IntPush( vFanins, pObj->Fanins[1] ); } } int Wlc_ObjDup( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) { Wlc_Obj_t * pObj = Wlc_NtkObj( p, iObj ); int iFaninNew = Wlc_ObjAlloc( pNew, pObj->Type, Wlc_ObjIsSigned(pObj), pObj->End, pObj->Beg ); Wlc_Obj_t * pObjNew = Wlc_NtkObj(pNew, iFaninNew); Wlc_ObjCollectCopyFanins( p, iObj, vFanins ); Wlc_ObjAddFanins( pNew, pObjNew, vFanins ); Wlc_ObjSetCopy( p, iObj, iFaninNew ); pObjNew->fXConst = pObj->fXConst; return iFaninNew; } void Wlc_NtkDupDfs_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins ) { Wlc_Obj_t * pObj; int i, iFanin; if ( Wlc_ObjCopy(p, iObj) ) return; pObj = Wlc_NtkObj( p, iObj ); Wlc_ObjForEachFanin( pObj, iFanin, i ) Wlc_NtkDupDfs_rec( pNew, p, iFanin, vFanins ); Wlc_ObjDup( pNew, p, iObj, vFanins ); } Wlc_Ntk_t * Wlc_NtkDupDfs( Wlc_Ntk_t * p ) { Wlc_Ntk_t * pNew; Wlc_Obj_t * pObj; Vec_Int_t * vFanins; int i; Wlc_NtkCleanCopy( p ); vFanins = Vec_IntAlloc( 100 ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew->fSmtLib = p->fSmtLib; Wlc_NtkForEachCi( p, pObj, i ) Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins ); Wlc_NtkForEachCo( p, pObj, i ) Wlc_NtkDupDfs_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins ); Wlc_NtkForEachCo( p, pObj, i ) Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), pObj->fIsFi ); if ( p->vInits ) pNew->vInits = Vec_IntDup( p->vInits ); if ( p->pInits ) pNew->pInits = Abc_UtilStrsav( p->pInits ); Vec_IntFree( vFanins ); if ( p->pSpec ) pNew->pSpec = Abc_UtilStrsav( p->pSpec ); return pNew; } void Wlc_NtkTransferNames( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p ) { int i; assert( !Wlc_NtkHasCopy(pNew) && Wlc_NtkHasCopy(p) ); assert( !Wlc_NtkHasNameId(pNew) && Wlc_NtkHasNameId(p) ); assert( pNew->pManName == NULL && p->pManName != NULL ); Wlc_NtkCleanNameId( pNew ); for ( i = 0; i < p->nObjsAlloc; i++ ) if ( Wlc_ObjCopy(p, i) && i < Vec_IntSize(&p->vNameIds) && Wlc_ObjNameId(p, i) ) Wlc_ObjSetNameId( pNew, Wlc_ObjCopy(p, i), Wlc_ObjNameId(p, i) ); pNew->pManName = p->pManName; p->pManName = NULL; Vec_IntErase( &p->vNameIds ); // transfer table pNew->pMemTable = p->pMemTable; p->pMemTable = NULL; pNew->vTables = p->vTables; p->vTables = NULL; } /**Function************************************************************* Synopsis [Duplicates the network by copying each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Ntk_t * Wlc_NtkDupSingleNodes( Wlc_Ntk_t * p ) { Wlc_Ntk_t * pNew; Vec_Int_t * vFanins; Wlc_Obj_t * pObj, * pObjNew; Wlc_Obj_t * pFanin, * pFaninNew; int i, k, iFanin, iFaninNew, iObjNew, Count = 0; // count objects Wlc_NtkForEachObj( p, pObj, i ) if ( !Wlc_ObjIsCi(pObj) ) Count += 1 + Wlc_ObjFaninNum(pObj); // copy objects Wlc_NtkCleanCopy( p ); vFanins = Vec_IntAlloc( 100 ); pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc ); pNew->fSmtLib = p->fSmtLib; Wlc_NtkForEachObj( p, pObj, i ) { if ( Wlc_ObjIsCi(pObj) ) continue; if ( pObj->Type == WLC_OBJ_ARI_MULTI ) continue; if ( pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3 ) continue; // create CIs for the fanins Wlc_ObjForEachFanin( pObj, iFanin, k ) { pFanin = Wlc_NtkObj(p, iFanin); iFaninNew = Wlc_ObjAlloc( pNew, WLC_OBJ_PI, pFanin->Signed, pFanin->End, pFanin->Beg ); pFaninNew = Wlc_NtkObj(pNew, iFaninNew); Wlc_ObjSetCopy( p, iFanin, iFaninNew ); //Wlc_ObjSetCi( pNew, pFaninNew ); } // create object iObjNew = Wlc_ObjDup( pNew, p, i, vFanins ); pObjNew = Wlc_NtkObj(pNew, iObjNew); pObjNew->fIsPo = 1; Vec_IntPush( &pNew->vPos, iObjNew ); } Vec_IntFree( vFanins ); Wlc_NtkTransferNames( pNew, p ); if ( p->pSpec ) pNew->pSpec = Abc_UtilStrsav( p->pSpec ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcReadSmt.c000066400000000000000000001671001300674244400237510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcParse.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Parses several flavors of word-level Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcParse.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // parser typedef struct Smt_Prs_t_ Smt_Prs_t; struct Smt_Prs_t_ { // input data char * pName; // file name char * pBuffer; // file contents char * pLimit; // end of file char * pCur; // current position Abc_Nam_t * pStrs; // string manager // network structure Vec_Int_t vStack; // current node on each level //Vec_Wec_t vDepth; // objects on each level Vec_Wec_t vObjs; // objects int NameCount; int nDigits; Vec_Int_t vTempFans; // error handling char ErrorStr[1000]; }; // parser name types typedef enum { SMT_PRS_NONE = 0, SMT_PRS_SET_OPTION, SMT_PRS_SET_LOGIC, SMT_PRS_SET_INFO, SMT_PRS_DEFINE_FUN, SMT_PRS_DECLARE_FUN, SMT_PRS_ASSERT, SMT_PRS_LET, SMT_PRS_CHECK_SAT, SMT_PRS_GET_VALUE, SMT_PRS_EXIT, SMT_PRS_END } Smt_LineType_t; typedef struct Smt_Pair_t_ Smt_Pair_t; struct Smt_Pair_t_ { Smt_LineType_t Type; char * pName; }; static Smt_Pair_t s_Types[SMT_PRS_END] = { { SMT_PRS_NONE, NULL }, { SMT_PRS_SET_OPTION, "set-option" }, { SMT_PRS_SET_LOGIC, "set-logic" }, { SMT_PRS_SET_INFO, "set-info" }, { SMT_PRS_DEFINE_FUN, "define-fun" }, { SMT_PRS_DECLARE_FUN, "declare-fun" }, { SMT_PRS_ASSERT, "assert" }, { SMT_PRS_LET, "let" }, { SMT_PRS_CHECK_SAT, "check-sat" }, { SMT_PRS_GET_VALUE, "get-value" }, { SMT_PRS_EXIT, "exit" } }; static inline char * Smt_GetTypeName( Smt_LineType_t Type ) { int i; for ( i = 1; i < SMT_PRS_END; i++ ) if ( s_Types[i].Type == Type ) return s_Types[i].pName; return NULL; } static inline void Smt_AddTypes( Abc_Nam_t * p ) { int Type; for ( Type = 1; Type < SMT_PRS_END; Type++ ) Abc_NamStrFindOrAdd( p, Smt_GetTypeName((Smt_LineType_t)Type), NULL ); assert( Abc_NamObjNumMax(p) == SMT_PRS_END ); } static inline int Smt_EntryIsName( int Fan ) { return Abc_LitIsCompl(Fan); } static inline int Smt_EntryIsType( int Fan, Smt_LineType_t Type ) { assert(Smt_EntryIsName(Fan)); return Abc_Lit2Var(Fan) == Type; } static inline char * Smt_EntryName( Smt_Prs_t * p, int Fan ) { assert(Smt_EntryIsName(Fan)); return Abc_NamStr( p->pStrs, Abc_Lit2Var(Fan) ); } static inline Vec_Int_t * Smt_EntryNode( Smt_Prs_t * p, int Fan ) { assert(!Smt_EntryIsName(Fan)); return Vec_WecEntry( &p->vObjs, Abc_Lit2Var(Fan) ); } static inline int Smt_VecEntryIsType( Vec_Int_t * vFans, int i, Smt_LineType_t Type ) { return i < Vec_IntSize(vFans) && Smt_EntryIsName(Vec_IntEntry(vFans, i)) && Smt_EntryIsType(Vec_IntEntry(vFans, i), Type); } static inline char * Smt_VecEntryName( Smt_Prs_t * p, Vec_Int_t * vFans, int i ) { return Smt_EntryIsName(Vec_IntEntry(vFans, i)) ? Smt_EntryName(p, Vec_IntEntry(vFans, i)) : NULL; } static inline Vec_Int_t * Smt_VecEntryNode( Smt_Prs_t * p, Vec_Int_t * vFans, int i ) { return Smt_EntryIsName(Vec_IntEntry(vFans, i)) ? NULL : Smt_EntryNode(p, Vec_IntEntry(vFans, i)); } #define Smt_ManForEachDir( p, Type, vVec, i ) \ for ( i = 0; (i < Vec_WecSize(&p->vObjs)) && (((vVec) = Vec_WecEntry(&p->vObjs, i)), 1); i++ ) \ if ( !Smt_VecEntryIsType(vVec, 0, Type) ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Smt_StrToType( char * pName, int * pfSigned ) { int Type = 0; *pfSigned = 0; if ( !strcmp(pName, "ite") ) Type = WLC_OBJ_MUX; // 08: multiplexer else if ( !strcmp(pName, "bvlshr") ) Type = WLC_OBJ_SHIFT_R; // 09: shift right else if ( !strcmp(pName, "bvashr") ) Type = WLC_OBJ_SHIFT_RA , *pfSigned = 1; // 10: shift right (arithmetic) else if ( !strcmp(pName, "bvshl") ) Type = WLC_OBJ_SHIFT_L; // 11: shift left // else if ( !strcmp(pName, "") ) // Type = WLC_OBJ_SHIFT_LA; // 12: shift left (arithmetic) else if ( !strcmp(pName, "rotate_right") ) Type = WLC_OBJ_ROTATE_R; // 13: rotate right else if ( !strcmp(pName, "rotate_left") ) Type = WLC_OBJ_ROTATE_L; // 14: rotate left else if ( !strcmp(pName, "bvnot") ) Type = WLC_OBJ_BIT_NOT; // 15: bitwise NOT else if ( !strcmp(pName, "bvand") ) Type = WLC_OBJ_BIT_AND; // 16: bitwise AND else if ( !strcmp(pName, "bvor") ) Type = WLC_OBJ_BIT_OR; // 17: bitwise OR else if ( !strcmp(pName, "bvxor") ) Type = WLC_OBJ_BIT_XOR; // 18: bitwise XOR else if ( !strcmp(pName, "bvnand") ) Type = WLC_OBJ_BIT_NAND; // 16: bitwise NAND else if ( !strcmp(pName, "bvnor") ) Type = WLC_OBJ_BIT_NOR; // 17: bitwise NOR else if ( !strcmp(pName, "bvxnor") ) Type = WLC_OBJ_BIT_NXOR; // 18: bitwise NXOR else if ( !strcmp(pName, "extract") ) Type = WLC_OBJ_BIT_SELECT; // 19: bit selection else if ( !strcmp(pName, "concat") ) Type = WLC_OBJ_BIT_CONCAT; // 20: bit concatenation else if ( !strcmp(pName, "zero_extend") ) Type = WLC_OBJ_BIT_ZEROPAD; // 21: zero padding else if ( !strcmp(pName, "sign_extend") ) Type = WLC_OBJ_BIT_SIGNEXT; // 22: sign extension else if ( !strcmp(pName, "not") ) Type = WLC_OBJ_LOGIC_NOT; // 23: logic NOT else if ( !strcmp(pName, "=>") ) Type = WLC_OBJ_LOGIC_IMPL; // 24: logic AND else if ( !strcmp(pName, "and") ) Type = WLC_OBJ_LOGIC_AND; // 24: logic AND else if ( !strcmp(pName, "or") ) Type = WLC_OBJ_LOGIC_OR; // 25: logic OR else if ( !strcmp(pName, "xor") ) Type = WLC_OBJ_LOGIC_XOR; // 26: logic OR else if ( !strcmp(pName, "bvcomp") || !strcmp(pName, "=") ) Type = WLC_OBJ_COMP_EQU; // 27: compare equal else if ( !strcmp(pName, "distinct") ) Type = WLC_OBJ_COMP_NOTEQU; // 28: compare not equal else if ( !strcmp(pName, "bvult") ) Type = WLC_OBJ_COMP_LESS; // 29: compare less else if ( !strcmp(pName, "bvugt") ) Type = WLC_OBJ_COMP_MORE; // 30: compare more else if ( !strcmp(pName, "bvule") ) Type = WLC_OBJ_COMP_LESSEQU; // 31: compare less or equal else if ( !strcmp(pName, "bvuge") ) Type = WLC_OBJ_COMP_MOREEQU; // 32: compare more or equal else if ( !strcmp(pName, "bvslt") ) Type = WLC_OBJ_COMP_LESS, *pfSigned = 1; // 29: compare less else if ( !strcmp(pName, "bvsgt") ) Type = WLC_OBJ_COMP_MORE, *pfSigned = 1; // 30: compare more else if ( !strcmp(pName, "bvsle") ) Type = WLC_OBJ_COMP_LESSEQU, *pfSigned = 1; // 31: compare less or equal else if ( !strcmp(pName, "bvsge") ) Type = WLC_OBJ_COMP_MOREEQU, *pfSigned = 1; // 32: compare more or equal else if ( !strcmp(pName, "bvredand") ) Type = WLC_OBJ_REDUCT_AND; // 33: reduction AND else if ( !strcmp(pName, "bvredor") ) Type = WLC_OBJ_REDUCT_OR; // 34: reduction OR else if ( !strcmp(pName, "bvredxor") ) Type = WLC_OBJ_REDUCT_XOR; // 35: reduction XOR else if ( !strcmp(pName, "bvadd") ) Type = WLC_OBJ_ARI_ADD; // 36: arithmetic addition else if ( !strcmp(pName, "bvsub") ) Type = WLC_OBJ_ARI_SUB; // 37: arithmetic subtraction else if ( !strcmp(pName, "bvmul") ) Type = WLC_OBJ_ARI_MULTI; // 38: arithmetic multiplier else if ( !strcmp(pName, "bvudiv") ) Type = WLC_OBJ_ARI_DIVIDE; // 39: arithmetic division else if ( !strcmp(pName, "bvurem") ) Type = WLC_OBJ_ARI_REM; // 40: arithmetic remainder else if ( !strcmp(pName, "bvsdiv") ) Type = WLC_OBJ_ARI_DIVIDE, *pfSigned = 1; // 39: arithmetic division else if ( !strcmp(pName, "bvsrem") ) Type = WLC_OBJ_ARI_REM, *pfSigned = 1; // 40: arithmetic remainder else if ( !strcmp(pName, "bvsmod") ) Type = WLC_OBJ_ARI_MODULUS, *pfSigned = 1; // 40: arithmetic modulus // else if ( !strcmp(pName, "") ) // Type = WLC_OBJ_ARI_POWER; // 41: arithmetic power else if ( !strcmp(pName, "bvneg") ) Type = WLC_OBJ_ARI_MINUS; // 42: arithmetic minus // else if ( !strcmp(pName, "") ) // Type = WLC_OBJ_TABLE; // 43: bit table else { printf( "The following operations is currently not supported (%s)\n", pName ); fflush( stdout ); } return Type; } static inline int Smt_PrsReadType( Smt_Prs_t * p, int iSig, int * pfSigned, int * Value1, int * Value2 ) { if ( Smt_EntryIsName(iSig) ) return Smt_StrToType( Smt_EntryName(p, iSig), pfSigned ); else { Vec_Int_t * vFans = Smt_EntryNode( p, iSig ); char * pStr = Smt_VecEntryName( p, vFans, 0 ); int Type; assert( Vec_IntSize(vFans) >= 3 ); assert( !strcmp(pStr, "_") ); // special op *Value1 = *Value2 = -1; assert( pStr[0] != 'b' || pStr[1] != 'v' ); // read type Type = Smt_StrToType( Smt_VecEntryName(p, vFans, 1), pfSigned ); if ( Type == 0 ) return 0; *Value1 = atoi( Smt_VecEntryName(p, vFans, 2) ); if ( Vec_IntSize(vFans) > 3 ) *Value2 = atoi( Smt_VecEntryName(p, vFans, 3) ); return Type; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Smt_PrsCreateNodeOld( Wlc_Ntk_t * pNtk, int Type, int fSigned, int Range, Vec_Int_t * vFanins, char * pName ) { char Buffer[100]; int NameId, fFound; int iObj = Wlc_ObjAlloc( pNtk, Type, fSigned, Range-1, 0 ); assert( Type > 0 ); assert( Range >= 0 ); assert( fSigned >= 0 ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins ); if ( fSigned ) Wlc_NtkObj(pNtk, iObj)->Signed = fSigned; if ( Type == WLC_OBJ_SHIFT_RA ) Wlc_NtkObj(pNtk, iObj)->Signed = 1; if ( pName == NULL ) { sprintf( Buffer, "_n%d_", iObj ); pName = Buffer; } // add node's name NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); assert( !fFound ); assert( iObj == NameId ); return iObj; } static inline int Smt_PrsCreateNode( Wlc_Ntk_t * pNtk, int Type, int fSigned, int Range, Vec_Int_t * vFanins, char * pName ) { char Buffer[100]; char * pNameFanin; int NameId, fFound, old_size, new_size; int iObj, iFanin0, iFanin1; Vec_Int_t * v2Fanins = Vec_IntStartFull(2); assert( Type > 0 ); assert( Range >= 0 ); assert( fSigned >= 0 ); // allow more than 2 fanins for specific operators // if (Vec_IntSize(vFanins)<=2 || Type == WLC_OBJ_BIT_CONCAT || Type == WLC_OBJ_MUX ) // explicitely secify allowed multi operators if (Vec_IntSize(vFanins)<=2 || !( Type == WLC_OBJ_BIT_AND || // 16:`` bitwise AND Type == WLC_OBJ_BIT_OR || // 17: bitwise OR Type == WLC_OBJ_BIT_XOR || // 18: bitwise XOR Type == WLC_OBJ_BIT_NAND || // 19: bitwise AND Type == WLC_OBJ_BIT_NOR || // 20: bitwise OR Type == WLC_OBJ_BIT_NXOR || // 21: bitwise NXOR Type == WLC_OBJ_LOGIC_IMPL || // 27: logic implication Type == WLC_OBJ_LOGIC_AND || // 28: logic AND Type == WLC_OBJ_LOGIC_OR || // 29: logic OR Type == WLC_OBJ_LOGIC_XOR || // 30: logic XOR Type == WLC_OBJ_COMP_EQU || // 31: compare equal Type == WLC_OBJ_COMP_NOTEQU || // 32: compare not equal Type == WLC_OBJ_COMP_LESS || // 33: compare less Type == WLC_OBJ_COMP_MORE || // 34: compare more Type == WLC_OBJ_COMP_LESSEQU || // 35: compare less or equal Type == WLC_OBJ_COMP_MOREEQU || // 36: compare more or equal Type == WLC_OBJ_ARI_ADD || // 43: arithmetic addition Type == WLC_OBJ_ARI_SUB || // 44: arithmetic subtraction Type == WLC_OBJ_ARI_MULTI || // 45: arithmetic multiplier Type == WLC_OBJ_ARI_DIVIDE // 46: arithmetic division )) goto FINISHED_WITH_FANINS; // we will be creating nodes backwards. this way we can pop from vFanins easier while (Vec_IntSize(vFanins)>2) { // getting 2 fanins at a time old_size = Vec_IntSize(vFanins); iFanin0 = Vec_IntPop(vFanins); iFanin1 = Vec_IntPop(vFanins); Vec_IntWriteEntry(v2Fanins,0,iFanin0); Vec_IntWriteEntry(v2Fanins,1,iFanin1); iObj = Wlc_ObjAlloc( pNtk, Type, fSigned, Range-1, 0 ); sprintf( Buffer, "_n%d_", iObj ); pNameFanin = Buffer; NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); assert( !fFound ); assert( iObj == NameId ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), v2Fanins ); // pushing the new node Vec_IntPush(vFanins, iObj); new_size = Vec_IntSize(vFanins); assert(new_size=2); if (range1>32) { Vec_Int_t * newFanins = Vec_IntAlloc(10); Vec_IntPush(newFanins,iFanin1); Vec_IntPushTwo( newFanins, 30, 0 ); iObj1 = Wlc_ObjAlloc( pNtk, WLC_OBJ_BIT_SELECT, 0, 30, 0 ); sprintf( Buffer, "_n%d_", iObj1 ); pNameFanin = Buffer; NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); assert( !fFound ); assert( iObj1 == NameId ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj1), newFanins ); // bit select of larger bits Vec_IntPop(newFanins); Vec_IntPop(newFanins); Vec_IntPushTwo( newFanins, range1-1, 31 ); iObj2 = Wlc_ObjAlloc( pNtk, WLC_OBJ_BIT_SELECT, 0, range1-1, 31 ); sprintf( Buffer, "_n%d_", iObj2 ); pNameFanin = Buffer; NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); assert( !fFound ); assert( iObj2 == NameId ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj2), newFanins ); // reduction or Vec_IntPop( newFanins ); Vec_IntPop( newFanins ); Vec_IntWriteEntry( newFanins, 0, iObj2 ); iObj3 = Wlc_ObjAlloc( pNtk, WLC_OBJ_REDUCT_OR, 0, 0, 0 ); sprintf( Buffer, "_n%d_", iObj3 ); pNameFanin = Buffer; NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); assert( !fFound ); assert( iObj3 == NameId ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj3), newFanins ); // concat all together Vec_IntWriteEntry( newFanins, 0, iObj3 ); Vec_IntPush( newFanins, iObj1 ); iObj = Wlc_ObjAlloc( pNtk, WLC_OBJ_BIT_CONCAT, 0, 31, 0 ); sprintf( Buffer, "_n%d_", iObj ); pNameFanin = Buffer; NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pNameFanin, &fFound ); assert( !fFound ); assert( iObj == NameId ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), newFanins ); // pushing the new node Vec_IntWriteEntry(vFanins, 1, iObj); Vec_IntFree(newFanins); } } iObj = Wlc_ObjAlloc( pNtk, Type, fSigned, Range-1, 0 ); // add node's name if ( pName == NULL ) { sprintf( Buffer, "_n%d_", iObj ); pName = Buffer; } NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); assert( !fFound ); assert( iObj == NameId ); Wlc_ObjAddFanins( pNtk, Wlc_NtkObj(pNtk, iObj), vFanins ); if ( fSigned ) { Wlc_NtkObj(pNtk, iObj)->Signed = fSigned; // if ( Vec_IntSize(vFanins) > 0 ) // Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 0))->Signed = fSigned; // if ( Vec_IntSize(vFanins) > 1 ) // Wlc_NtkObj(pNtk, Vec_IntEntry(vFanins, 1))->Signed = fSigned; } return iObj; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char * Smt_GetHexFromDecimalString(char * pStr) { int i,k=0, nDigits = strlen(pStr); int digit, carry = 0; int metNonZeroBit; int nBits; char * hex; Vec_Int_t * decimal = Vec_IntAlloc(nDigits); Vec_Int_t * rev; for (i=0;i=nDigits) { if (!metNonZeroBit) break; else { Vec_IntPush(rev,carry); carry = 0; k = 0; metNonZeroBit = 0; } } continue; } if (!metNonZeroBit) metNonZeroBit = 1; digit = carry*10 + digit; carry = digit%2; digit = digit / 2; Vec_IntWriteEntry(decimal,k,digit); k++; if (k>=nDigits) { Vec_IntPush(rev,carry); carry = 0; k = 0; metNonZeroBit = 0; } } Vec_IntFree(decimal); if (!Vec_IntSize(rev)) Vec_IntPush(rev,0); while (Vec_IntSize(rev)%4) Vec_IntPush(rev,0); nBits = Vec_IntSize(rev); hex = (char *)malloc((nBits/4+1)*sizeof(char)); for (k=0;k= '0' && pStr[0] <= '9' ) { /* int w, nWords, Number = atoi( pStr ); if ( nBits == -1 ) { nBits = Abc_Base2Log( Number+1 ); assert( nBits < 32 ); } nWords = Abc_BitWordNum( nBits ); for ( w = 0; w < nWords; w++ ) Vec_IntPush( vFanins, w ? 0 : Number ); */ // convert decimal to hex to parse large constants char * pHex = Smt_GetHexFromDecimalString(pStr); if ( nBits == -1 ) nBits = strlen(pHex)*4; Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 ); nDigits = Abc_TtReadHexNumber( (word *)Vec_IntArray(vFanins), pHex ); } else { int fFound, iObj = Abc_NamStrFindOrAdd( pNtk->pManName, pStr, &fFound ); assert( fFound ); Vec_IntFree( vFanins ); return iObj; } } else if ( pStr[1] == 'b' ) // binary { if ( nBits == -1 ) nBits = strlen(pStr+2); Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 ); for ( i = 0; i < nBits; i++ ) if ( pStr[2+i] == '1' ) Abc_InfoSetBit( (unsigned *)Vec_IntArray(vFanins), nBits-1-i ); else if ( pStr[2+i] != '0' ) return 0; } else if ( pStr[1] == 'x' ) // hexadecimal { if ( nBits == -1 ) nBits = strlen(pStr+2)*4; Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 ); nDigits = Abc_TtReadHexNumber( (word *)Vec_IntArray(vFanins), pStr+2 ); if ( nDigits != (nBits + 3)/4 ) return 0; } else return 0; // create constant node iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_CONST, 0, nBits, vFanins, pName ); Vec_IntFree( vFanins ); return iObj; } int Smt_PrsBuildNode( Wlc_Ntk_t * pNtk, Smt_Prs_t * p, int iNode, int RangeOut, char * pName ) { if ( Smt_EntryIsName(iNode) ) // name or constant { char * pStr = Abc_NamStr(p->pStrs, Abc_Lit2Var(iNode)); if ( (pStr[0] >= '0' && pStr[0] <= '9') || pStr[0] == '#' ) { // (_ BitVec 8) #x19 return Smt_PrsBuildConstant( pNtk, pStr, RangeOut, pName ); } else { // s3087 int fFound, iObj = Abc_NamStrFindOrAdd( pNtk->pManName, pStr, &fFound ); assert( fFound ); // create buffer if the name of the fanin has different name if ( pName && strcmp(pStr, pName) ) { Vec_IntFill( &p->vTempFans, 1, iObj ); iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, RangeOut, &p->vTempFans, pName ); } return iObj; } } else // node { Vec_Int_t * vFans = Smt_EntryNode( p, iNode ); char * pStr0 = Smt_VecEntryName( p, vFans, 0 ); char * pStr1 = Smt_VecEntryName( p, vFans, 1 ); if ( pStr0 && pStr1 && pStr0[0] == '_' && pStr1[0] == 'b' && pStr1[1] == 'v' ) { // (_ bv1 32) char * pStr2 = Smt_VecEntryName( p, vFans, 2 ); assert( Vec_IntSize(vFans) == 3 ); return Smt_PrsBuildConstant( pNtk, pStr1+2, atoi(pStr2), pName ); } else if ( pStr0 && pStr0[0] == '=' ) { assert( Vec_IntSize(vFans) == 3 ); iNode = Vec_IntEntry(vFans, 2); assert( Smt_EntryIsName(iNode) ); pStr0 = Smt_EntryName(p, iNode); // check the last one is "#b1" if ( !strcmp("#b1", pStr0) ) { iNode = Vec_IntEntry(vFans, 1); return Smt_PrsBuildNode( pNtk, p, iNode, -1, pName ); } else { Vec_Int_t * vFanins = Vec_IntAlloc( 2 ); // get the constant int iObj, iOper, iConst = Smt_PrsBuildConstant( pNtk, pStr0, -1, NULL ); // check the middle one is an operator iNode = Vec_IntEntry(vFans, 1); iOper = Smt_PrsBuildNode( pNtk, p, iNode, -1, pName ); // build comparator Vec_IntPushTwo( vFanins, iOper, iConst ); iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_COMP_EQU, 0, 1, vFanins, pName ); Vec_IntFree( vFanins ); return iObj; } } else { int i, Fan, NameId, iFanin, fSigned, Range, Value1 = -1, Value2 = -1; int Type = Smt_PrsReadType( p, Vec_IntEntry(vFans, 0), &fSigned, &Value1, &Value2 ); // collect fanins Vec_Int_t * vFanins = Vec_IntAlloc( 100 ); Vec_IntForEachEntryStart( vFans, Fan, i, 1 ) { iFanin = Smt_PrsBuildNode( pNtk, p, Fan, -1, NULL ); if ( iFanin == 0 ) { Vec_IntFree( vFanins ); return 0; } Vec_IntPush( vFanins, iFanin ); } // update specialized nodes assert( Type != WLC_OBJ_BIT_SIGNEXT && Type != WLC_OBJ_BIT_ZEROPAD ); if ( Type == WLC_OBJ_BIT_SELECT ) { assert( Value1 >= 0 && Value2 >= 0 && Value1 >= Value2 ); Vec_IntPushTwo( vFanins, Value1, Value2 ); } else if ( Type == WLC_OBJ_ROTATE_R || Type == WLC_OBJ_ROTATE_L ) { char Buffer[10]; assert( Value1 >= 0 ); sprintf( Buffer, "%d", Value1 ); NameId = Smt_PrsBuildConstant( pNtk, Buffer, -1, NULL ); Vec_IntPush( vFanins, NameId ); } // find range Range = 0; if ( Type >= WLC_OBJ_LOGIC_NOT && Type <= WLC_OBJ_REDUCT_XOR ) Range = 1; else if ( Type == WLC_OBJ_BIT_SELECT ) Range = Value1 - Value2 + 1; else if ( Type == WLC_OBJ_BIT_CONCAT ) { Vec_IntForEachEntry( vFanins, NameId, i ) Range += Wlc_ObjRange( Wlc_NtkObj(pNtk, NameId) ); } else if ( Type == WLC_OBJ_MUX ) { int * pArray = Vec_IntArray(vFanins); assert( Vec_IntSize(vFanins) == 3 ); ABC_SWAP( int, pArray[1], pArray[2] ); NameId = Vec_IntEntry(vFanins, 1); Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, NameId) ); } else // to determine range, look at the first argument { NameId = Vec_IntEntry(vFanins, 0); Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, NameId) ); } // create node assert( Range > 0 ); NameId = Smt_PrsCreateNode( pNtk, Type, fSigned, Range, vFanins, pName ); Vec_IntFree( vFanins ); return NameId; } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Ntk_t * Smt_PrsBuild( Smt_Prs_t * p ) { Wlc_Ntk_t * pNtk; Vec_Int_t * vFans, * vFans2, * vFans3; Vec_Int_t * vAsserts = Vec_IntAlloc(100); char * pName, * pRange, * pValue; int i, k, Fan, Fan3, iObj, Status, Range, NameId, nBits = 0; // issue warnings about unknown dirs vFans = Vec_WecEntry( &p->vObjs, 0 ); Vec_IntForEachEntry( vFans, Fan, i ) { assert( !Smt_EntryIsName(Fan) ); vFans2 = Smt_VecEntryNode( p, vFans, i ); Fan = Vec_IntEntry(vFans2, 0); assert( Smt_EntryIsName(Fan) ); if ( Abc_Lit2Var(Fan) >= SMT_PRS_END ) printf( "Ignoring directive \"%s\".\n", Smt_EntryName(p, Fan) ); } // start network and create primary inputs pNtk = Wlc_NtkAlloc( p->pName, 1000 ); pNtk->pManName = Abc_NamStart( 1000, 24 ); pNtk->fSmtLib = 1; Smt_ManForEachDir( p, SMT_PRS_DECLARE_FUN, vFans, i ) { assert( Vec_IntSize(vFans) == 4 ); assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DECLARE_FUN) ); // get name Fan = Vec_IntEntry(vFans, 1); assert( Smt_EntryIsName(Fan) ); pName = Smt_EntryName(p, Fan); // skip () Fan = Vec_IntEntry(vFans, 2); assert( !Smt_EntryIsName(Fan) ); vFans2 = Smt_VecEntryNode(p, vFans, 2); if ( Vec_IntSize(vFans2) > 0 ) { printf( "File parsing error: Uninterpreted functions are not supported.\n" ); Wlc_NtkFree( pNtk ); pNtk = NULL; goto finish; } // check type (Bool or BitVec) Fan = Vec_IntEntry(vFans, 3); if ( Smt_EntryIsName(Fan) ) { //(declare-fun s1 () Bool) assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); Range = 1; } else { // (declare-fun s1 () (_ BitVec 64)) // get range Fan = Vec_IntEntry(vFans, 3); assert( !Smt_EntryIsName(Fan) ); vFans2 = Smt_EntryNode(p, Fan); assert( Vec_IntSize(vFans2) == 3 ); assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); Fan = Vec_IntEntry(vFans2, 2); assert( Smt_EntryIsName(Fan) ); pRange = Smt_EntryName(p, Fan); Range = atoi(pRange); } // create node iObj = Wlc_ObjAlloc( pNtk, WLC_OBJ_PI, 0, Range-1, 0 ); NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, NULL ); assert( iObj == NameId ); // save values Vec_IntPush( &pNtk->vValues, NameId ); Vec_IntPush( &pNtk->vValues, nBits ); Vec_IntPush( &pNtk->vValues, Range ); nBits += Range; } // create constants Smt_ManForEachDir( p, SMT_PRS_DEFINE_FUN, vFans, i ) { assert( Vec_IntSize(vFans) == 5 ); assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DEFINE_FUN) ); // get name Fan = Vec_IntEntry(vFans, 1); assert( Smt_EntryIsName(Fan) ); pName = Smt_EntryName(p, Fan); // skip () Fan = Vec_IntEntry(vFans, 2); assert( !Smt_EntryIsName(Fan) ); // check type (Bool or BitVec) Fan = Vec_IntEntry(vFans, 3); if ( Smt_EntryIsName(Fan) ) { // (define-fun s_2 () Bool false) assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); Range = 1; pValue = Smt_VecEntryName(p, vFans, 4); if ( !strcmp("false", pValue) ) pValue = "#b0"; else if ( !strcmp("true", pValue) ) pValue = "#b1"; else assert( 0 ); Status = Smt_PrsBuildConstant( pNtk, pValue, Range, pName ); } else { // (define-fun s702 () (_ BitVec 4) #xe) // (define-fun s1 () (_ BitVec 8) (bvneg #x7f)) // get range Fan = Vec_IntEntry(vFans, 3); assert( !Smt_EntryIsName(Fan) ); vFans2 = Smt_VecEntryNode(p, vFans, 3); assert( Vec_IntSize(vFans2) == 3 ); assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); // get range Fan = Vec_IntEntry(vFans2, 2); assert( Smt_EntryIsName(Fan) ); pRange = Smt_EntryName(p, Fan); Range = atoi(pRange); // get constant Fan = Vec_IntEntry(vFans, 4); Status = Smt_PrsBuildNode( pNtk, p, Fan, Range, pName ); } if ( !Status ) { Wlc_NtkFree( pNtk ); pNtk = NULL; goto finish; } } // process let-statements Smt_ManForEachDir( p, SMT_PRS_LET, vFans, i ) { // let ((s35550 (bvor s48 s35549))) assert( Vec_IntSize(vFans) == 3 ); assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_LET) ); // get parts Fan = Vec_IntEntry(vFans, 1); assert( !Smt_EntryIsName(Fan) ); vFans2 = Smt_EntryNode(p, Fan); if ( Smt_VecEntryIsType(vFans2, 0, SMT_PRS_LET) ) continue; // iterate through the parts Vec_IntForEachEntry( vFans2, Fan, k ) { // s35550 (bvor s48 s35549) Fan = Vec_IntEntry(vFans2, 0); assert( !Smt_EntryIsName(Fan) ); vFans3 = Smt_EntryNode(p, Fan); // get the name Fan3 = Vec_IntEntry(vFans3, 0); assert( Smt_EntryIsName(Fan3) ); pName = Smt_EntryName(p, Fan3); // get function Fan3 = Vec_IntEntry(vFans3, 1); assert( !Smt_EntryIsName(Fan3) ); Status = Smt_PrsBuildNode( pNtk, p, Fan3, -1, pName ); if ( !Status ) { Wlc_NtkFree( pNtk ); pNtk = NULL; goto finish; } } } // process assert-statements Vec_IntClear( vAsserts ); Smt_ManForEachDir( p, SMT_PRS_ASSERT, vFans, i ) { //(assert ; no quantifiers // (let ((s2 (bvsge s0 s1))) // (not s2))) //(assert (not (= s0 #x00))) assert( Vec_IntSize(vFans) == 2 ); assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_ASSERT) ); // get second directive Fan = Vec_IntEntry(vFans, 1); if ( !Smt_EntryIsName(Fan) ) { // find the final let-statement vFans2 = Smt_VecEntryNode(p, vFans, 1); while ( Smt_VecEntryIsType(vFans2, 0, SMT_PRS_LET) ) { Fan = Vec_IntEntry(vFans2, 2); if ( Smt_EntryIsName(Fan) ) break; vFans2 = Smt_VecEntryNode(p, vFans2, 2); } } // find name or create node iObj = Smt_PrsBuildNode( pNtk, p, Fan, -1, NULL ); if ( !iObj ) { Wlc_NtkFree( pNtk ); pNtk = NULL; goto finish; } Vec_IntPush( vAsserts, iObj ); } // build AND of asserts if ( Vec_IntSize(vAsserts) == 1 ) iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, 1, vAsserts, "miter_output" ); else { iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BIT_CONCAT, 0, Vec_IntSize(vAsserts), vAsserts, NULL ); Vec_IntFill( vAsserts, 1, iObj ); iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_REDUCT_AND, 0, 1, vAsserts, "miter_output" ); } Wlc_ObjSetCo( pNtk, Wlc_NtkObj(pNtk, iObj), 0 ); // create nameIDs vFans = Vec_IntStartNatural( Wlc_NtkObjNumMax(pNtk) ); Vec_IntAppend( &pNtk->vNameIds, vFans ); Vec_IntFree( vFans ); //Wlc_NtkReport( pNtk, NULL ); finish: // cleanup Vec_IntFree(vAsserts); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Smt_PrsGenName( Smt_Prs_t * p ) { static char Buffer[16]; sprintf( Buffer, "_%0*X_", p->nDigits, ++p->NameCount ); return Buffer; } int Smt_PrsBuild2_rec( Wlc_Ntk_t * pNtk, Smt_Prs_t * p, int iNode, int iObjPrev, char * pName ) { if ( Smt_EntryIsName(iNode) ) { char * pStr = Abc_NamStr(p->pStrs, Abc_Lit2Var(iNode)); // handle built-in constants if ( !strcmp(pStr, "false") ) pStr = "#b0"; else if ( !strcmp(pStr, "true") ) pStr = "#b1"; if ( pStr[0] == '#' ) return Smt_PrsBuildConstant( pNtk, pStr, -1, pName ? pName : Smt_PrsGenName(p) ); else { int fFound, iObj = Abc_NamStrFindOrAdd( pNtk->pManName, pStr, &fFound ); assert( fFound ); // create buffer if the name of the fanin has different name if ( pName && strcmp(Wlc_ObjName(pNtk, iObj), pName) ) { Vec_IntFill( &p->vTempFans, 1, iObj ); iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, Wlc_ObjRange(Wlc_NtkObj(pNtk, iObj)), &p->vTempFans, pName ); } return iObj; } } else { Vec_Int_t * vRoots, * vRoots1, * vFans3; int iObj, iRoot0, iRoot1, iRoot2, Fan, Fan3, k; assert( !Smt_EntryIsName(iNode) ); vRoots = Smt_EntryNode( p, iNode ); iRoot0 = Vec_IntEntry( vRoots, 0 ); if ( Smt_EntryIsName(iRoot0) ) { char * pName2, * pStr0 = Abc_NamStr(p->pStrs, Abc_Lit2Var(iRoot0)); if ( Abc_Lit2Var(iRoot0) == SMT_PRS_LET ) { // let ((s35550 (bvor s48 s35549))) assert( Vec_IntSize(vRoots) == 3 ); assert( Smt_VecEntryIsType(vRoots, 0, SMT_PRS_LET) ); // get parts iRoot1 = Vec_IntEntry(vRoots, 1); assert( !Smt_EntryIsName(iRoot1) ); vRoots1 = Smt_EntryNode(p, iRoot1); // iterate through the parts Vec_IntForEachEntry( vRoots1, Fan, k ) { // s35550 (bvor s48 s35549) assert( !Smt_EntryIsName(Fan) ); vFans3 = Smt_EntryNode(p, Fan); assert( Vec_IntSize(vFans3) == 2 ); // get the name Fan3 = Vec_IntEntry(vFans3, 0); assert( Smt_EntryIsName(Fan3) ); pName2 = Smt_EntryName(p, Fan3); // get function Fan3 = Vec_IntEntry(vFans3, 1); //assert( !Smt_EntryIsName(Fan3) ); // solve the problem iObj = Smt_PrsBuild2_rec( pNtk, p, Fan3, -1, pName2 ); // NULL ); //pName2 ); if ( iObj == 0 ) return 0; // create buffer //Vec_IntFill( &p->vTempFans, 1, iObj ); //Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, Wlc_ObjRange(Wlc_NtkObj(pNtk, iObj)), &p->vTempFans, pName2 ); } // process the final part of let iRoot2 = Vec_IntEntry(vRoots, 2); return Smt_PrsBuild2_rec( pNtk, p, iRoot2, -1, pName ); } else if ( pStr0[0] == '_' ) { char * pStr1 = Smt_VecEntryName( p, vRoots, 1 ); if ( pStr1[0] == 'b' && pStr1[1] == 'v' ) { // (_ bv1 32) char * pStr2 = Smt_VecEntryName( p, vRoots, 2 ); assert( Vec_IntSize(vRoots) == 3 ); return Smt_PrsBuildConstant( pNtk, pStr1+2, atoi(pStr2), pName ? pName : Smt_PrsGenName(p) ); } else { int Type1, fSigned = 0, Range = -1; assert( iObjPrev != -1 ); Type1 = Smt_StrToType( pStr1, &fSigned ); if ( Type1 == 0 ) return 0; // find out this branch Vec_IntFill( &p->vTempFans, 1, iObjPrev ); if ( Type1 == WLC_OBJ_BIT_SIGNEXT || Type1 == WLC_OBJ_BIT_ZEROPAD || Type1 == WLC_OBJ_ROTATE_R || Type1 == WLC_OBJ_ROTATE_L ) { int iRoot2 = Vec_IntEntry(vRoots, 2); char * pStr2 = Abc_NamStr(p->pStrs, Abc_Lit2Var(iRoot2)); int Num = atoi( pStr2 ); //fSigned = (Type1 == WLC_OBJ_BIT_SIGNEXT); if ( Type1 == WLC_OBJ_ROTATE_R || Type1 == WLC_OBJ_ROTATE_L ) { int iConst = Smt_PrsBuildConstant( pNtk, pStr2, -1, Smt_PrsGenName(p) ); Vec_IntClear( &p->vTempFans ); Vec_IntPushTwo( &p->vTempFans, iObjPrev, iConst ); Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, iObjPrev) ); } else Range = Num + Wlc_ObjRange( Wlc_NtkObj(pNtk, iObjPrev) ); } else if ( Type1 == WLC_OBJ_BIT_SELECT ) { int iRoot2 = Vec_IntEntry( vRoots, 2 ); int iRoot3 = Vec_IntEntry( vRoots, 3 ); char * pStr2 = Abc_NamStr(p->pStrs, Abc_Lit2Var(iRoot2)); char * pStr3 = Abc_NamStr(p->pStrs, Abc_Lit2Var(iRoot3)); int Num1 = atoi( pStr2 ); int Num2 = atoi( pStr3 ); assert( Num1 >= Num2 ); Range = Num1 - Num2 + 1; Vec_IntPushTwo( &p->vTempFans, Num1, Num2 ); } else assert( 0 ); iObj = Smt_PrsCreateNode( pNtk, Type1, fSigned, Range, &p->vTempFans, pName ? pName : Smt_PrsGenName(p) ); return iObj; } } else { Vec_Int_t * vFanins; int i, Fan, fSigned = 0, Range, Type0; int iObj = Abc_NamStrFind( pNtk->pManName, pStr0 ); if ( iObj ) return iObj; Type0 = Smt_StrToType( pStr0, &fSigned ); if ( Type0 == 0 ) return 0; assert( Type0 != WLC_OBJ_BIT_SIGNEXT && Type0 != WLC_OBJ_BIT_ZEROPAD && Type0 != WLC_OBJ_BIT_SELECT && Type0 != WLC_OBJ_ROTATE_R && Type0 != WLC_OBJ_ROTATE_L ); // collect fanins vFanins = Vec_IntAlloc( 100 ); Vec_IntForEachEntryStart( vRoots, Fan, i, 1 ) { iObj = Smt_PrsBuild2_rec( pNtk, p, Fan, -1, NULL ); if ( iObj == 0 ) { Vec_IntFree( vFanins ); return 0; } Vec_IntPush( vFanins, iObj ); } // find range Range = 0; if ( Type0 >= WLC_OBJ_LOGIC_NOT && Type0 <= WLC_OBJ_REDUCT_XOR ) Range = 1; else if ( Type0 == WLC_OBJ_BIT_CONCAT ) { Vec_IntForEachEntry( vFanins, Fan, i ) Range += Wlc_ObjRange( Wlc_NtkObj(pNtk, Fan) ); } else if ( Type0 == WLC_OBJ_MUX ) { int * pArray = Vec_IntArray(vFanins); assert( Vec_IntSize(vFanins) == 3 ); ABC_SWAP( int, pArray[1], pArray[2] ); iObj = Vec_IntEntry(vFanins, 1); Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, iObj) ); } else // to determine range, look at the first argument { iObj = Vec_IntEntry(vFanins, 0); Range = Wlc_ObjRange( Wlc_NtkObj(pNtk, iObj) ); } // create node assert( Range > 0 ); iObj = Smt_PrsCreateNode( pNtk, Type0, fSigned, Range, vFanins, pName ? pName : Smt_PrsGenName(p) ); Vec_IntFree( vFanins ); return iObj; } } else if ( Vec_IntSize(vRoots) == 2 ) // could be ((_ extract 48 16) (bvmul ?v_5 ?v_12)) { int iObjPrev = Smt_PrsBuild2_rec( pNtk, p, Vec_IntEntry(vRoots, 1), -1, NULL ); if ( iObjPrev == 0 ) return 0; return Smt_PrsBuild2_rec( pNtk, p, Vec_IntEntry(vRoots, 0), iObjPrev, pName ); } else assert( 0 ); // return Smt_PrsBuild2_rec( pNtk, p, iRoot0 ); return 0; } } Wlc_Ntk_t * Smt_PrsBuild2( Smt_Prs_t * p ) { Wlc_Ntk_t * pNtk; Vec_Int_t * vFansRoot, * vFans, * vFans2; Vec_Int_t * vAsserts = Vec_IntAlloc(100); int i, Root, Fan, iObj, NameId, Range, Status, nBits = 0; char * pName, * pRange; // start network and create primary inputs pNtk = Wlc_NtkAlloc( p->pName, 1000 ); pNtk->pManName = Abc_NamStart( 1000, 24 ); pNtk->fSmtLib = 1; // collect top-level asserts vFansRoot = Vec_WecEntry( &p->vObjs, 0 ); Vec_IntForEachEntry( vFansRoot, Root, i ) { assert( !Smt_EntryIsName(Root) ); vFans = Smt_VecEntryNode( p, vFansRoot, i ); Fan = Vec_IntEntry(vFans, 0); assert( Smt_EntryIsName(Fan) ); // create variables if ( Abc_Lit2Var(Fan) == SMT_PRS_DECLARE_FUN ) { assert( Vec_IntSize(vFans) == 4 ); assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DECLARE_FUN) ); // get name Fan = Vec_IntEntry(vFans, 1); assert( Smt_EntryIsName(Fan) ); pName = Smt_EntryName(p, Fan); // skip () Fan = Vec_IntEntry(vFans, 2); assert( !Smt_EntryIsName(Fan) ); vFans2 = Smt_VecEntryNode(p, vFans, 2); if ( Vec_IntSize(vFans2) > 0 ) { printf( "File parsing error: Uninterpreted functions are not supported.\n" ); Wlc_NtkFree( pNtk ); pNtk = NULL; goto finish; } // check type (Bool or BitVec) Fan = Vec_IntEntry(vFans, 3); if ( Smt_EntryIsName(Fan) ) { //(declare-fun s1 () Bool) assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); Range = 1; } else { // (declare-fun s1 () (_ BitVec 64)) Fan = Vec_IntEntry(vFans, 3); assert( !Smt_EntryIsName(Fan) ); vFans2 = Smt_EntryNode(p, Fan); assert( Vec_IntSize(vFans2) == 3 ); assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); Fan = Vec_IntEntry(vFans2, 2); assert( Smt_EntryIsName(Fan) ); pRange = Smt_EntryName(p, Fan); Range = atoi(pRange); } // create node iObj = Wlc_ObjAlloc( pNtk, WLC_OBJ_PI, 0, Range-1, 0 ); NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, NULL ); assert( iObj == NameId ); // save values Vec_IntPush( &pNtk->vValues, NameId ); Vec_IntPush( &pNtk->vValues, nBits ); Vec_IntPush( &pNtk->vValues, Range ); nBits += Range; } // create constants else if ( Abc_Lit2Var(Fan) == SMT_PRS_DEFINE_FUN ) { assert( Vec_IntSize(vFans) == 5 ); assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_DEFINE_FUN) ); // get name Fan = Vec_IntEntry(vFans, 1); assert( Smt_EntryIsName(Fan) ); pName = Smt_EntryName(p, Fan); // skip () Fan = Vec_IntEntry(vFans, 2); assert( !Smt_EntryIsName(Fan) ); // check type (Bool or BitVec) Fan = Vec_IntEntry(vFans, 3); if ( Smt_EntryIsName(Fan) ) { // (define-fun s_2 () Bool false) assert( !strcmp("Bool", Smt_VecEntryName(p, vFans, 3)) ); iObj = Smt_PrsBuild2_rec( pNtk, p, Vec_IntEntry(vFans, 4), -1, pName ); if ( iObj == 0 ) { Wlc_NtkFree( pNtk ); pNtk = NULL; goto finish; } continue; } else { // (define-fun s702 () (_ BitVec 4) #xe) // (define-fun s1 () (_ BitVec 8) (bvneg #x7f)) // get range Fan = Vec_IntEntry(vFans, 3); assert( !Smt_EntryIsName(Fan) ); vFans2 = Smt_VecEntryNode(p, vFans, 3); assert( Vec_IntSize(vFans2) == 3 ); assert( !strcmp("_", Smt_VecEntryName(p, vFans2, 0)) ); assert( !strcmp("BitVec", Smt_VecEntryName(p, vFans2, 1)) ); // get range Fan = Vec_IntEntry(vFans2, 2); assert( Smt_EntryIsName(Fan) ); pRange = Smt_EntryName(p, Fan); Range = atoi(pRange); // get constant Fan = Vec_IntEntry(vFans, 4); Status = Smt_PrsBuildNode( pNtk, p, Fan, Range, pName ); } if ( !Status ) { Wlc_NtkFree( pNtk ); pNtk = NULL; goto finish; } } // collect assertion outputs else if ( Abc_Lit2Var(Fan) == SMT_PRS_ASSERT ) { //(assert ; no quantifiers // (let ((s2 (bvsge s0 s1))) // (not s2))) //(assert (not (= s0 #x00))) assert( Vec_IntSize(vFans) == 2 ); assert( Smt_VecEntryIsType(vFans, 0, SMT_PRS_ASSERT) ); iObj = Smt_PrsBuild2_rec( pNtk, p, Vec_IntEntry(vFans, 1), -1, NULL ); if ( iObj == 0 ) { Wlc_NtkFree( pNtk ); pNtk = NULL; goto finish; } Vec_IntPush( vAsserts, iObj ); } // issue warnings about unknown dirs else if ( Abc_Lit2Var(Fan) >= SMT_PRS_END ) printf( "Ignoring directive \"%s\".\n", Smt_EntryName(p, Fan) ); } // build AND of asserts if ( Vec_IntSize(vAsserts) == 1 ) iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BUF, 0, 1, vAsserts, "miter" ); else { iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_BIT_CONCAT, 0, Vec_IntSize(vAsserts), vAsserts, NULL ); Vec_IntFill( vAsserts, 1, iObj ); iObj = Smt_PrsCreateNode( pNtk, WLC_OBJ_REDUCT_AND, 0, 1, vAsserts, "miter" ); } Wlc_ObjSetCo( pNtk, Wlc_NtkObj(pNtk, iObj), 0 ); // create nameIDs vFans = Vec_IntStartNatural( Wlc_NtkObjNumMax(pNtk) ); Vec_IntAppend( &pNtk->vNameIds, vFans ); Vec_IntFree( vFans ); //Wlc_NtkReport( pNtk, NULL ); finish: // cleanup Vec_IntFree(vAsserts); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // create error message static inline int Smt_PrsErrorSet( Smt_Prs_t * p, char * pError, int Value ) { assert( !p->ErrorStr[0] ); sprintf( p->ErrorStr, "%s", pError ); return Value; } // print error message static inline int Smt_PrsErrorPrint( Smt_Prs_t * p ) { char * pThis; int iLine = 0; if ( !p->ErrorStr[0] ) return 1; for ( pThis = p->pBuffer; pThis < p->pCur; pThis++ ) iLine += (int)(*pThis == '\n'); printf( "Line %d: %s\n", iLine, p->ErrorStr ); return 0; } static inline char * Smt_PrsLoadFile( char * pFileName, char ** ppLimit ) { char * pBuffer; int nFileSize, RetValue; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file.\n" ); return NULL; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nFileSize + 16 ); pBuffer[0] = '\n'; RetValue = fread( pBuffer+1, nFileSize, 1, pFile ); fclose( pFile ); // terminate the string with '\0' pBuffer[nFileSize + 1] = '\n'; pBuffer[nFileSize + 2] = '\0'; *ppLimit = pBuffer + nFileSize + 2; return pBuffer; } static inline int Smt_PrsRemoveComments( char * pBuffer, char * pLimit ) { char * pTemp; int nCount1 = 0, nCount2 = 0, fHaveBar = 0; for ( pTemp = pBuffer; pTemp < pLimit; pTemp++ ) { if ( *pTemp == '(' ) nCount1++; else if ( *pTemp == ')' ) nCount2++; else if ( *pTemp == '|' ) fHaveBar ^= 1; else if ( *pTemp == ';' && !fHaveBar ) while ( *pTemp && *pTemp != '\n' ) *pTemp++ = ' '; } if ( nCount1 != nCount2 ) printf( "The input SMTLIB file has different number of opening and closing parentheses (%d and %d).\n", nCount1, nCount2 ); else if ( nCount1 == 0 ) printf( "The input SMTLIB file has no opening or closing parentheses.\n" ); return nCount1 == nCount2 ? nCount1 : 0; } static inline Smt_Prs_t * Smt_PrsAlloc( char * pFileName, char * pBuffer, char * pLimit, int nObjs ) { Smt_Prs_t * p; if ( nObjs == 0 ) return NULL; p = ABC_CALLOC( Smt_Prs_t, 1 ); p->pName = pFileName; p->pBuffer = pBuffer; p->pLimit = pLimit; p->pCur = pBuffer; p->pStrs = Abc_NamStart( 1000, 24 ); Smt_AddTypes( p->pStrs ); Vec_IntGrow( &p->vStack, 100 ); //Vec_WecGrow( &p->vDepth, 100 ); Vec_WecGrow( &p->vObjs, nObjs+1 ); return p; } static inline void Smt_PrsFree( Smt_Prs_t * p ) { if ( p->pStrs ) Abc_NamDeref( p->pStrs ); Vec_IntErase( &p->vStack ); Vec_IntErase( &p->vTempFans ); //Vec_WecErase( &p->vDepth ); Vec_WecErase( &p->vObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Smt_PrsIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; } static inline void Smt_PrsSkipSpaces( Smt_Prs_t * p ) { while ( Smt_PrsIsSpace(*p->pCur) ) p->pCur++; } static inline void Smt_PrsSkipNonSpaces( Smt_Prs_t * p ) { while ( p->pCur < p->pLimit && !Smt_PrsIsSpace(*p->pCur) && *p->pCur != '(' && *p->pCur != ')' ) p->pCur++; } void Smt_PrsReadLines( Smt_Prs_t * p ) { assert( Vec_IntSize(&p->vStack) == 0 ); //assert( Vec_WecSize(&p->vDepth) == 0 ); assert( Vec_WecSize(&p->vObjs) == 0 ); // add top node at level 0 //Vec_WecPushLevel( &p->vDepth ); //Vec_WecPush( &p->vDepth, Vec_IntSize(&p->vStack), Vec_WecSize(&p->vObjs) ); // add top node Vec_IntPush( &p->vStack, Vec_WecSize(&p->vObjs) ); Vec_WecPushLevel( &p->vObjs ); // add other nodes for ( p->pCur = p->pBuffer; p->pCur < p->pLimit; p->pCur++ ) { Smt_PrsSkipSpaces( p ); if ( *p->pCur == '(' ) { // add new node at this depth //assert( Vec_WecSize(&p->vDepth) >= Vec_IntSize(&p->vStack) ); //if ( Vec_WecSize(&p->vDepth) == Vec_IntSize(&p->vStack) ) // Vec_WecPushLevel(&p->vDepth); //Vec_WecPush( &p->vDepth, Vec_IntSize(&p->vStack), Vec_WecSize(&p->vObjs) ); // add fanin to node on the previous level Vec_IntPush( Vec_WecEntry(&p->vObjs, Vec_IntEntryLast(&p->vStack)), Abc_Var2Lit(Vec_WecSize(&p->vObjs), 0) ); // add node to the stack Vec_IntPush( &p->vStack, Vec_WecSize(&p->vObjs) ); Vec_WecPushLevel( &p->vObjs ); } else if ( *p->pCur == ')' ) { Vec_IntPop( &p->vStack ); } else // token { char * pStart = p->pCur; Smt_PrsSkipNonSpaces( p ); if ( p->pCur < p->pLimit ) { // remove strange characters (this can lead to name clashes) int iToken; char * pTemp; if ( *pStart == '?' ) *pStart = '_'; for ( pTemp = pStart; pTemp < p->pCur; pTemp++ ) if ( *pTemp == '.' ) *pTemp = '_'; // create and save token for this string iToken = Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur--, NULL ); Vec_IntPush( Vec_WecEntry(&p->vObjs, Vec_IntEntryLast(&p->vStack)), Abc_Var2Lit(iToken, 1) ); } } } assert( Vec_IntSize(&p->vStack) == 1 ); assert( Vec_WecSize(&p->vObjs) == Vec_WecCap(&p->vObjs) ); p->nDigits = Abc_Base16Log( Vec_WecSize(&p->vObjs) ); } void Smt_PrsPrintParser_rec( Smt_Prs_t * p, int iObj, int Depth ) { Vec_Int_t * vFans; int i, Fan; printf( "%*s(\n", Depth, "" ); vFans = Vec_WecEntry( &p->vObjs, iObj ); Vec_IntForEachEntry( vFans, Fan, i ) { if ( Abc_LitIsCompl(Fan) ) { printf( "%*s", Depth+2, "" ); printf( "%s\n", Abc_NamStr(p->pStrs, Abc_Lit2Var(Fan)) ); } else Smt_PrsPrintParser_rec( p, Abc_Lit2Var(Fan), Depth+4 ); } printf( "%*s)\n", Depth, "" ); } void Smt_PrsPrintParser( Smt_Prs_t * p ) { // Vec_WecPrint( &p->vDepth, 0 ); Smt_PrsPrintParser_rec( p, 0, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Ntk_t * Wlc_ReadSmtBuffer( char * pFileName, char * pBuffer, char * pLimit, int fOldParser, int fPrintTree ) { Wlc_Ntk_t * pNtk = NULL; int nCount = Smt_PrsRemoveComments( pBuffer, pLimit ); Smt_Prs_t * p = Smt_PrsAlloc( pFileName, pBuffer, pLimit, nCount ); if ( p == NULL ) return NULL; Smt_PrsReadLines( p ); if ( fPrintTree ) Smt_PrsPrintParser( p ); if ( Smt_PrsErrorPrint(p) ) pNtk = fOldParser ? Smt_PrsBuild(p) : Smt_PrsBuild2(p); Smt_PrsFree( p ); return pNtk; } Wlc_Ntk_t * Wlc_ReadSmt( char * pFileName, int fOldParser, int fPrintTree ) { Wlc_Ntk_t * pNtk = NULL; char * pBuffer, * pLimit; pBuffer = Smt_PrsLoadFile( pFileName, &pLimit ); if ( pBuffer == NULL ) return NULL; pNtk = Wlc_ReadSmtBuffer( pFileName, pBuffer, pLimit, fOldParser, fPrintTree ); ABC_FREE( pBuffer ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcReadVer.c000066400000000000000000001467221300674244400237510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcReadVer.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Parses several flavors of word-level Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcReadVer.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // Word-level Verilog file parser #define WLV_PRS_MAX_LINE 1000 typedef struct Wlc_Prs_t_ Wlc_Prs_t; struct Wlc_Prs_t_ { int nFileSize; char * pFileName; char * pBuffer; Vec_Int_t * vLines; Vec_Int_t * vStarts; Vec_Int_t * vFanins; Wlc_Ntk_t * pNtk; Mem_Flex_t * pMemTable; Vec_Ptr_t * vTables; int nConsts; int nNonZero[4]; int nNegative[4]; int nReverse[4]; char sError[WLV_PRS_MAX_LINE]; }; static inline int Wlc_PrsOffset( Wlc_Prs_t * p, char * pStr ) { return pStr - p->pBuffer; } static inline char * Wlc_PrsStr( Wlc_Prs_t * p, int iOffset ) { return p->pBuffer + iOffset; } static inline int Wlc_PrsStrCmp( char * pStr, char * pWhat ) { return !strncmp( pStr, pWhat, strlen(pWhat)); } #define Wlc_PrsForEachLine( p, pLine, i ) \ for ( i = 0; (i < Vec_IntSize((p)->vStarts)) && ((pLine) = Wlc_PrsStr(p, Vec_IntEntry((p)->vStarts, i))); i++ ) #define Wlc_PrsForEachLineStart( p, pLine, i, Start ) \ for ( i = Start; (i < Vec_IntSize((p)->vStarts)) && ((pLine) = Wlc_PrsStr(p, Vec_IntEntry((p)->vStarts, i))); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wlc_Prs_t * Wlc_PrsStart( char * pFileName ) { Wlc_Prs_t * p; if ( !Extra_FileCheck( pFileName ) ) return NULL; p = ABC_CALLOC( Wlc_Prs_t, 1 ); p->pFileName = pFileName; p->pBuffer = Extra_FileReadContents( pFileName ); p->nFileSize = strlen(p->pBuffer); assert( p->nFileSize > 0 ); p->vLines = Vec_IntAlloc( p->nFileSize / 50 ); p->vStarts = Vec_IntAlloc( p->nFileSize / 50 ); p->vFanins = Vec_IntAlloc( 100 ); p->vTables = Vec_PtrAlloc( 1000 ); p->pMemTable = Mem_FlexStart(); return p; } void Wlc_PrsStop( Wlc_Prs_t * p ) { if ( p->pNtk ) Wlc_NtkFree( p->pNtk ); if ( p->pMemTable ) Mem_FlexStop( p->pMemTable, 0 ); Vec_PtrFreeP( &p->vTables ); Vec_IntFree( p->vLines ); Vec_IntFree( p->vStarts ); Vec_IntFree( p->vFanins ); ABC_FREE( p->pBuffer ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the error message including the file name and line number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Wlc_PrsFindLine( Wlc_Prs_t * p, char * pCur ) { int Entry, iLine = 0; Vec_IntForEachEntry( p->vLines, Entry, iLine ) if ( Entry > pCur - p->pBuffer ) return iLine + 1; return -1; } int Wlc_PrsWriteErrorMessage( Wlc_Prs_t * p, char * pCur, const char * format, ... ) { char * pMessage; // derive message va_list args; va_start( args, format ); pMessage = vnsprintf( format, args ); va_end( args ); // print messsage assert( strlen(pMessage) < WLV_PRS_MAX_LINE - 100 ); assert( p->sError[0] == 0 ); if ( pCur == NULL ) // the line number is not given sprintf( p->sError, "%s: %s\n", p->pFileName, pMessage ); else // print the error message with the line number { int iLine = Wlc_PrsFindLine( p, pCur ); sprintf( p->sError, "%s (line %d): %s\n", p->pFileName, iLine, pMessage ); } ABC_FREE( pMessage ); return 0; } void Wlc_PrsPrintErrorMessage( Wlc_Prs_t * p ) { if ( p->sError[0] == 0 ) return; fprintf( stdout, "%s", p->sError ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Wlc_PrsIsDigit( char * pStr ) { return (pStr[0] >= '0' && pStr[0] <= '9'); } static inline int Wlc_PrsIsChar( char * pStr ) { return (pStr[0] >= 'a' && pStr[0] <= 'z') || (pStr[0] >= 'A' && pStr[0] <= 'Z') || (pStr[0] >= '0' && pStr[0] <= '9') || pStr[0] == '_' || pStr[0] == '$' || pStr[0] == '\\'; } static inline char * Wlc_PrsSkipSpaces( char * pStr ) { while ( *pStr && *pStr == ' ' ) pStr++; return pStr; } static inline char * Wlc_PrsFindSymbol( char * pStr, char Symb ) { int fNotName = 1; for ( ; *pStr; pStr++ ) { if ( fNotName && *pStr == Symb ) return pStr; if ( pStr[0] == '\\' ) fNotName = 0; else if ( !fNotName && *pStr == ' ' ) fNotName = 1; } return NULL; } static inline char * Wlc_PrsFindSymbolTwo( char * pStr, char Symb, char Symb2 ) { for ( ; pStr[1]; pStr++ ) if ( pStr[0] == Symb && pStr[1] == Symb2 ) return pStr; return NULL; } static inline char * Wlc_PrsFindClosingParenthesis( char * pStr, char Open, char Close ) { int Counter = 0; int fNotName = 1; assert( *pStr == Open ); for ( ; *pStr; pStr++ ) { if ( fNotName ) { if ( *pStr == Open ) Counter++; if ( *pStr == Close ) Counter--; if ( Counter == 0 ) return pStr; } if ( *pStr == '\\' ) fNotName = 0; else if ( !fNotName && *pStr == ' ' ) fNotName = 1; } return NULL; } int Wlc_PrsRemoveComments( Wlc_Prs_t * p ) { int fSpecifyFound = 0; char * pCur, * pNext, * pEnd = p->pBuffer + p->nFileSize; for ( pCur = p->pBuffer; pCur < pEnd; pCur++ ) { // regular comment (//) if ( *pCur == '/' && pCur[1] == '/' ) { if ( pCur + 5 < pEnd && pCur[2] == 'a' && pCur[3] == 'b' && pCur[4] == 'c' && pCur[5] == '2' ) pCur[0] = pCur[1] = pCur[2] = pCur[3] = pCur[4] = pCur[5] = ' '; else { pNext = Wlc_PrsFindSymbol( pCur, '\n' ); if ( pNext == NULL ) return Wlc_PrsWriteErrorMessage( p, pCur, "Cannot find end-of-line after symbols \"//\"." ); for ( ; pCur < pNext; pCur++ ) *pCur = ' '; } } // skip preprocessor directive (`timescale, `celldefine, etc) else if ( *pCur == '`' ) { pNext = Wlc_PrsFindSymbol( pCur, '\n' ); if ( pNext == NULL ) return Wlc_PrsWriteErrorMessage( p, pCur, "Cannot find end-of-line after symbols \"`\"." ); for ( ; pCur < pNext; pCur++ ) *pCur = ' '; } // regular comment (/* ... */) else if ( *pCur == '/' && pCur[1] == '*' ) { pNext = Wlc_PrsFindSymbolTwo( pCur, '*', '/' ); if ( pNext == NULL ) return Wlc_PrsWriteErrorMessage( p, pCur, "Cannot find symbols \"*/\" after symbols \"/*\"." ); // overwrite comment for ( ; pCur < pNext + 2; pCur++ ) *pCur = ' '; } // 'specify' treated as comments else if ( *pCur == 's' && pCur[1] == 'p' && pCur[2] == 'e' && !strncmp(pCur, "specify", 7) ) { for ( pNext = pCur; pNext < pEnd - 10; pNext++ ) if ( *pNext == 'e' && pNext[1] == 'n' && pNext[2] == 'd' && !strncmp(pNext, "endspecify", 10) ) { // overwrite comment for ( ; pCur < pNext + 10; pCur++ ) *pCur = ' '; if ( fSpecifyFound == 0 ) Abc_Print( 0, "Ignoring specify/endspecify directives.\n" ); fSpecifyFound = 1; break; } } // insert semicolons else if ( *pCur == 'e' && pCur[1] == 'n' && pCur[2] == 'd' && !strncmp(pCur, "endmodule", 9) ) pCur[strlen("endmodule")] = ';'; // overwrite end-of-lines with spaces (less checking to do later on) if ( *pCur == '\n' || *pCur == '\r' || *pCur == '\t' ) *pCur = ' '; } return 1; } int Wlc_PrsPrepare( Wlc_Prs_t * p ) { int fPrettyPrint = 0; int fNotName = 1; char * pTemp, * pPrev, * pThis; // collect info about lines assert( Vec_IntSize(p->vLines) == 0 ); for ( pTemp = p->pBuffer; *pTemp; pTemp++ ) if ( *pTemp == '\n' ) Vec_IntPush( p->vLines, pTemp - p->pBuffer ); // delete comments and insert breaks if ( !Wlc_PrsRemoveComments( p ) ) return 0; // collect info about breaks assert( Vec_IntSize(p->vStarts) == 0 ); for ( pPrev = pThis = p->pBuffer; *pThis; pThis++ ) { if ( fNotName && *pThis == ';' ) { *pThis = 0; Vec_IntPush( p->vStarts, Wlc_PrsOffset(p, Wlc_PrsSkipSpaces(pPrev)) ); pPrev = pThis + 1; } if ( *pThis == '\\' ) fNotName = 0; else if ( !fNotName && *pThis == ' ' ) fNotName = 1; } if ( fPrettyPrint ) { int i, k; // print the line types Wlc_PrsForEachLine( p, pTemp, i ) { if ( Wlc_PrsStrCmp( pTemp, "module" ) ) printf( "\n" ); if ( !Wlc_PrsStrCmp( pTemp, "module" ) && !Wlc_PrsStrCmp( pTemp, "endmodule" ) ) printf( " " ); printf( "%c", pTemp[0] ); for ( k = 1; pTemp[k]; k++ ) if ( pTemp[k] != ' ' || pTemp[k-1] != ' ' ) printf( "%c", pTemp[k] ); printf( ";\n" ); } /* // print the line types Wlc_PrsForEachLine( p, pTemp, i ) { int k; if ( !Wlc_PrsStrCmp( pTemp, "module" ) ) continue; printf( "%3d : ", i ); for ( k = 0; k < 40; k++ ) printf( "%c", pTemp[k] ? pTemp[k] : ' ' ); printf( "\n" ); } */ } return 1; } /**Function************************************************************* Synopsis [Modified version of strtok().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Wlc_PrsStrtok( char * s, const char * delim ) { const char *spanp; int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) return NULL; // skip leading delimiters cont: c = *s++; for (spanp = delim; (sc = *spanp++) != 0;) if (c == sc) goto cont; if (c == 0) // no non-delimiter characters return (last = NULL); // tok = s - 1; if ( c != '\\' ) tok = s - 1; else tok = s - 1; // go back to the first non-delimiter character s--; // find the token for (;;) { c = *s++; if ( c == '\\' ) // skip blind characters { while ( c != ' ' ) c = *s++; c = *s++; } spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; last = s; return (tok); } } while (sc != 0); } // not reached return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Wlc_PrsConvertInitValues( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i, k, Value, * pInits; char * pResult; Vec_Str_t * vStr = Vec_StrAlloc( 1000 ); Vec_IntForEachEntry( p->vInits, Value, i ) { if ( Value < 0 ) { for ( k = 0; k < -Value; k++ ) Vec_StrPush( vStr, '0' ); continue; } pObj = Wlc_NtkObj( p, Value ); Value = Wlc_ObjRange(pObj); while ( pObj->Type == WLC_OBJ_BUF ) pObj = Wlc_NtkObj( p, Wlc_ObjFaninId0(pObj) ); pInits = (pObj->Type == WLC_OBJ_CONST && !pObj->fXConst) ? Wlc_ObjConstValue(pObj) : NULL; for ( k = 0; k < Abc_MinInt(Value, Wlc_ObjRange(pObj)); k++ ) Vec_StrPush( vStr, (char)(pInits ? '0' + Abc_InfoHasBit((unsigned *)pInits, k) : 'X') ); // extend values with zero, in case the init value signal has different range compared to constant used for ( ; k < Value; k++ ) Vec_StrPush( vStr, '0' ); // update vInits to contain either number of values or PI index Vec_IntWriteEntry( p->vInits, i, (pInits || pObj->fXConst) ? -Value : Wlc_ObjCiId(pObj) ); } Vec_StrPush( vStr, '\0' ); pResult = Vec_StrReleaseArray( vStr ); Vec_StrFree( vStr ); return pResult; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char * Wlc_PrsFindRange( char * pStr, int * End, int * Beg ) { *End = *Beg = 0; pStr = Wlc_PrsSkipSpaces( pStr ); if ( pStr[0] != '[' ) return pStr; pStr = Wlc_PrsSkipSpaces( pStr+1 ); if ( !Wlc_PrsIsDigit(pStr) && pStr[0] != '-' ) return NULL; *End = *Beg = atoi( pStr ); if ( Wlc_PrsFindSymbol( pStr, ':' ) == NULL ) { pStr = Wlc_PrsFindSymbol( pStr, ']' ); if ( pStr == NULL ) return NULL; } else { pStr = Wlc_PrsFindSymbol( pStr, ':' ); pStr = Wlc_PrsSkipSpaces( pStr+1 ); if ( !Wlc_PrsIsDigit(pStr) && pStr[0] != '-' ) return NULL; *Beg = atoi( pStr ); pStr = Wlc_PrsFindSymbol( pStr, ']' ); if ( pStr == NULL ) return NULL; } return pStr + 1; } static inline char * Wlc_PrsFindWord( char * pStr, char * pWord, int * fFound ) { *fFound = 0; pStr = Wlc_PrsSkipSpaces( pStr ); if ( !Wlc_PrsStrCmp(pStr, pWord) ) return pStr; *fFound = 1; return pStr + strlen(pWord); } static inline char * Wlc_PrsFindName( char * pStr, char ** ppPlace ) { static char Buffer[WLV_PRS_MAX_LINE]; char * pThis = *ppPlace = Buffer; int fNotName = 1; pStr = Wlc_PrsSkipSpaces( pStr ); if ( !Wlc_PrsIsChar(pStr) ) return NULL; // while ( Wlc_PrsIsChar(pStr) ) // *pThis++ = *pStr++; while ( *pStr ) { if ( fNotName && !Wlc_PrsIsChar(pStr) ) break; if ( *pStr == '\\' ) fNotName = 0; else if ( !fNotName && *pStr == ' ' ) fNotName = 1; *pThis++ = *pStr++; } *pThis = 0; return pStr; } static inline char * Wlc_PrsReadConstant( Wlc_Prs_t * p, char * pStr, Vec_Int_t * vFanins, int * pRange, int * pSigned, int * pXValue ) { int i, nDigits, nBits = atoi( pStr ); *pRange = -1; *pSigned = 0; *pXValue = 0; pStr = Wlc_PrsSkipSpaces( pStr ); if ( Wlc_PrsFindSymbol( pStr, '\'' ) == NULL ) { // handle decimal number int Number = atoi( pStr ); *pRange = Abc_Base2Log( Number+1 ); assert( *pRange < 32 ); while ( Wlc_PrsIsDigit(pStr) ) pStr++; Vec_IntFill( vFanins, 1, Number ); return pStr; } pStr = Wlc_PrsFindSymbol( pStr, '\'' ); if ( pStr[1] == 's' ) { *pSigned = 1; pStr++; } if ( pStr[1] == 'b' ) { Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 ); for ( i = 0; i < nBits; i++ ) if ( pStr[2+i] == '1' ) Abc_InfoSetBit( (unsigned *)Vec_IntArray(vFanins), nBits-1-i ); else if ( pStr[2+i] != '0' ) return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Wrong digit in binary constant \"%c\".", pStr[2+i] ); *pRange = nBits; pStr += 2 + nBits; return pStr; } if ( pStr[1] != 'h' ) return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Expecting hexadecimal constant and not \"%c\".", pStr[1] ); *pXValue = (pStr[2] == 'x' || pStr[2] == 'X'); Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 ); nDigits = Abc_TtReadHexNumber( (word *)Vec_IntArray(vFanins), pStr+2 ); if ( nDigits != (nBits + 3)/4 ) { // return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "The length of a constant does not match." ); // printf( "Warning: The length of a constant (%d hex digits) does not match the number of bits (%d).\n", nDigits, nBits ); } *pRange = nBits; pStr += 2; while ( Wlc_PrsIsChar(pStr) ) pStr++; return pStr; } static inline char * Wlc_PrsReadName( Wlc_Prs_t * p, char * pStr, Vec_Int_t * vFanins ) { int NameId, fFound, iObj; pStr = Wlc_PrsSkipSpaces( pStr ); if ( Wlc_PrsIsDigit(pStr) ) { char Buffer[100]; int Range, Signed, XValue = 0; Vec_Int_t * vFanins = Vec_IntAlloc(0); pStr = Wlc_PrsReadConstant( p, pStr, vFanins, &Range, &Signed, &XValue ); if ( pStr == NULL ) { Vec_IntFree( vFanins ); return 0; } // create new node iObj = Wlc_ObjAlloc( p->pNtk, WLC_OBJ_CONST, Signed, Range-1, 0 ); Wlc_ObjAddFanins( p->pNtk, Wlc_NtkObj(p->pNtk, iObj), vFanins ); Wlc_NtkObj(p->pNtk, iObj)->fXConst = XValue; Vec_IntFree( vFanins ); // add node's name sprintf( Buffer, "_c%d_", p->nConsts++ ); NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, Buffer, &fFound ); if ( fFound ) return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Name %s is already used.", Buffer ); assert( iObj == NameId ); } else { char * pName; pStr = Wlc_PrsFindName( pStr, &pName ); if ( pStr == NULL ) return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in assign-statement." ); NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); if ( !fFound ) return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Name %s is used but not declared.", pName ); } Vec_IntPush( vFanins, NameId ); return Wlc_PrsSkipSpaces( pStr ); } static inline int Wlc_PrsFindDefinition( Wlc_Prs_t * p, char * pStr, Vec_Int_t * vFanins, int * pXValue ) { char * pName; int Type = WLC_OBJ_NONE; int fRotating = 0; Vec_IntClear( vFanins ); pStr = Wlc_PrsSkipSpaces( pStr ); if ( pStr[0] != '=' ) return 0; pStr = Wlc_PrsSkipSpaces( pStr+1 ); if ( pStr[0] == '(' ) { // consider rotating shifter if ( Wlc_PrsFindSymbolTwo(pStr, '>', '>') && Wlc_PrsFindSymbolTwo(pStr, '<', '<') ) { // THIS IS A HACK TO DETECT rotating shifters char * pClose = Wlc_PrsFindClosingParenthesis( pStr, '(', ')' ); if ( pClose == NULL ) return Wlc_PrsWriteErrorMessage( p, pStr, "Expecting closing parenthesis." ); *pStr = ' '; *pClose = 0; pStr = Wlc_PrsSkipSpaces( pStr ); fRotating = 1; } else { char * pClose = Wlc_PrsFindClosingParenthesis( pStr, '(', ')' ); if ( pClose == NULL ) return Wlc_PrsWriteErrorMessage( p, pStr, "Expecting closing parenthesis." ); *pStr = *pClose = ' '; pStr = Wlc_PrsSkipSpaces( pStr ); } } if ( Wlc_PrsIsDigit(pStr) ) { int Range, Signed; pStr = Wlc_PrsReadConstant( p, pStr, vFanins, &Range, &Signed, pXValue ); if ( pStr == NULL ) return 0; Type = WLC_OBJ_CONST; } else if ( pStr[0] == '!' || (pStr[0] == '~' && pStr[1] != '&' && pStr[1] != '|' && pStr[1] != '^') || pStr[0] == '@' || pStr[0] == '#' ) { if ( pStr[0] == '!' ) Type = WLC_OBJ_LOGIC_NOT; else if ( pStr[0] == '~' ) Type = WLC_OBJ_BIT_NOT; else if ( pStr[0] == '@' ) Type = WLC_OBJ_ARI_SQRT; else if ( pStr[0] == '#' ) Type = WLC_OBJ_ARI_SQUARE; else assert( 0 ); // skip parentheses pStr = Wlc_PrsSkipSpaces( pStr+1 ); if ( pStr[0] == '(' ) { char * pClose = Wlc_PrsFindClosingParenthesis( pStr, '(', ')' ); if ( pClose == NULL ) return Wlc_PrsWriteErrorMessage( p, pStr, "Expecting closing parenthesis." ); *pStr = *pClose = ' '; } if ( !(pStr = Wlc_PrsReadName(p, pStr, vFanins)) ) return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name after !." ); } else if ( pStr[0] == '-' || pStr[0] == '&' || pStr[0] == '|' || pStr[0] == '^' || (pStr[0] == '~' && pStr[1] == '&') || (pStr[0] == '~' && pStr[1] == '|') || (pStr[0] == '~' && pStr[1] == '^') ) { int shift = 1; if ( pStr[0] == '-' ) Type = WLC_OBJ_ARI_MINUS; else if ( pStr[0] == '&' ) Type = WLC_OBJ_REDUCT_AND; else if ( pStr[0] == '|' ) Type = WLC_OBJ_REDUCT_OR; else if ( pStr[0] == '^' ) Type = WLC_OBJ_REDUCT_XOR; else if ( pStr[0] == '~' && pStr[1] == '&' ) {Type = WLC_OBJ_REDUCT_NAND; shift = 2;} else if ( pStr[0] == '~' && pStr[1] == '|' ) {Type = WLC_OBJ_REDUCT_NOR; shift = 2;} else if ( pStr[0] == '~' && pStr[1] == '^' ) {Type = WLC_OBJ_REDUCT_NXOR; shift = 2;} else assert( 0 ); if ( !(pStr = Wlc_PrsReadName(p, pStr+shift, vFanins)) ) return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name after a unary operator." ); } else if ( pStr[0] == '{' ) { // THIS IS A HACK TO DETECT zero padding AND sign extension if ( Wlc_PrsFindSymbol(pStr+1, '{') ) { if ( Wlc_PrsFindSymbol(pStr+1, '\'') ) Type = WLC_OBJ_BIT_ZEROPAD; else Type = WLC_OBJ_BIT_SIGNEXT; pStr = Wlc_PrsFindSymbol(pStr+1, ','); if ( pStr == NULL ) return Wlc_PrsWriteErrorMessage( p, pStr, "Expecting one comma in this line." ); if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) ) return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in sign-extension." ); pStr = Wlc_PrsSkipSpaces( pStr ); if ( pStr[0] != '}' ) return Wlc_PrsWriteErrorMessage( p, pStr, "There is no closing brace (})." ); } else // concatenation { while ( 1 ) { pStr = Wlc_PrsSkipSpaces( pStr+1 ); if ( !(pStr = Wlc_PrsReadName(p, pStr, vFanins)) ) return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in concatenation." ); if ( pStr[0] == '}' ) break; if ( pStr[0] != ',' ) return Wlc_PrsWriteErrorMessage( p, pStr, "Expected comma (,) in this place." ); } Type = WLC_OBJ_BIT_CONCAT; } assert( pStr[0] == '}' ); pStr++; } else { if ( !(pStr = Wlc_PrsReadName(p, pStr, vFanins)) ) return 0; // get the next symbol if ( pStr[0] == 0 ) Type = WLC_OBJ_BUF; else if ( pStr[0] == '?' ) { if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) ) return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in MUX." ); if ( pStr[0] != ':' ) return Wlc_PrsWriteErrorMessage( p, pStr, "MUX lacks the colon symbol (:)." ); if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) ) return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in MUX." ); assert( Vec_IntSize(vFanins) == 3 ); ABC_SWAP( int, Vec_IntArray(vFanins)[1], Vec_IntArray(vFanins)[2] ); Type = WLC_OBJ_MUX; } else if ( pStr[0] == '[' ) { int End, Beg; char * pLine = pStr; pStr = Wlc_PrsFindRange( pStr, &End, &Beg ); if ( pStr == NULL ) return Wlc_PrsWriteErrorMessage( p, pLine, "Non-standard range." ); Vec_IntPushTwo( vFanins, End, Beg ); Type = WLC_OBJ_BIT_SELECT; } else { if ( pStr[0] == '>' && pStr[1] == '>' && pStr[2] != '>' ) pStr += 2, Type = fRotating ? WLC_OBJ_ROTATE_R : WLC_OBJ_SHIFT_R; else if ( pStr[0] == '>' && pStr[1] == '>' && pStr[2] == '>' ) pStr += 3, Type = WLC_OBJ_SHIFT_RA; else if ( pStr[0] == '<' && pStr[1] == '<' && pStr[2] != '<' ) pStr += 2, Type = fRotating ? WLC_OBJ_ROTATE_L : WLC_OBJ_SHIFT_L; else if ( pStr[0] == '<' && pStr[1] == '<' && pStr[2] == '<' ) pStr += 3, Type = WLC_OBJ_SHIFT_LA; else if ( pStr[0] == '&' && pStr[1] != '&' ) pStr += 1, Type = WLC_OBJ_BIT_AND; else if ( pStr[0] == '|' && pStr[1] != '|' ) pStr += 1, Type = WLC_OBJ_BIT_OR; else if ( pStr[0] == '^' && pStr[1] != '^' ) pStr += 1, Type = WLC_OBJ_BIT_XOR; else if ( pStr[0] == '~' && pStr[1] == '&' ) pStr += 2, Type = WLC_OBJ_BIT_NAND; else if ( pStr[0] == '~' && pStr[1] == '|' ) pStr += 2, Type = WLC_OBJ_BIT_NOR; else if ( pStr[0] == '~' && pStr[1] == '^' ) pStr += 2, Type = WLC_OBJ_BIT_NXOR; else if ( pStr[0] == '=' && pStr[1] == '>' ) pStr += 2, Type = WLC_OBJ_LOGIC_IMPL; else if ( pStr[0] == '&' && pStr[1] == '&' ) pStr += 2, Type = WLC_OBJ_LOGIC_AND; else if ( pStr[0] == '|' && pStr[1] == '|' ) pStr += 2, Type = WLC_OBJ_LOGIC_OR; else if ( pStr[0] == '^' && pStr[1] == '^' ) pStr += 2, Type = WLC_OBJ_LOGIC_XOR; else if ( pStr[0] == '=' && pStr[1] == '=' ) pStr += 2, Type = WLC_OBJ_COMP_EQU; else if ( pStr[0] == '!' && pStr[1] == '=' ) pStr += 2, Type = WLC_OBJ_COMP_NOTEQU; else if ( pStr[0] == '<' && pStr[1] != '=' ) pStr += 1, Type = WLC_OBJ_COMP_LESS; else if ( pStr[0] == '>' && pStr[1] != '=' ) pStr += 1, Type = WLC_OBJ_COMP_MORE; else if ( pStr[0] == '<' && pStr[1] == '=' ) pStr += 2, Type = WLC_OBJ_COMP_LESSEQU; else if ( pStr[0] == '>' && pStr[1] == '=' ) pStr += 2, Type = WLC_OBJ_COMP_MOREEQU; else if ( pStr[0] == '+' ) pStr += 1, Type = WLC_OBJ_ARI_ADD; else if ( pStr[0] == '-' ) pStr += 1, Type = WLC_OBJ_ARI_SUB; else if ( pStr[0] == '*' && pStr[1] != '*' ) pStr += 1, Type = WLC_OBJ_ARI_MULTI; else if ( pStr[0] == '/' ) pStr += 1, Type = WLC_OBJ_ARI_DIVIDE; else if ( pStr[0] == '%' ) pStr += 1, Type = WLC_OBJ_ARI_REM; else if ( pStr[0] == '*' && pStr[1] == '*' ) pStr += 2, Type = WLC_OBJ_ARI_POWER; else return Wlc_PrsWriteErrorMessage( p, pStr, "Unsupported operation (%c).", pStr[0] ); if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) ) return 0; pStr = Wlc_PrsSkipSpaces( pStr ); if ( pStr[0] ) printf( "Warning: Trailing symbols \"%s\" in line %d.\n", pStr, Wlc_PrsFindLine(p, pStr) ); } } // make sure there is nothing left there if ( pStr ) { pStr = Wlc_PrsFindName( pStr, &pName ); if ( pStr != NULL ) return Wlc_PrsWriteErrorMessage( p, pStr, "Name %s is left at the end of the line.", pName ); } return Type; } int Wlc_PrsReadDeclaration( Wlc_Prs_t * p, char * pStart ) { int fFound = 0, Type = WLC_OBJ_NONE, iObj; char * pLine; int Signed = 0, Beg = 0, End = 0, NameId, fIsPo = 0; if ( Wlc_PrsStrCmp( pStart, "input" ) ) pStart += strlen("input"), Type = WLC_OBJ_PI; else if ( Wlc_PrsStrCmp( pStart, "output" ) ) pStart += strlen("output"), fIsPo = 1; pStart = Wlc_PrsSkipSpaces( pStart ); if ( Wlc_PrsStrCmp( pStart, "wire" ) ) pStart += strlen("wire"); else if ( Wlc_PrsStrCmp( pStart, "reg" ) ) pStart += strlen("reg"); // read 'signed' pStart = Wlc_PrsFindWord( pStart, "signed", &Signed ); // read range pLine = pStart; pStart = Wlc_PrsFindRange( pStart, &End, &Beg ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pLine, "Non-standard range." ); if ( End != 0 && Beg != 0 ) { if ( p->nNonZero[0]++ == 0 ) { p->nNonZero[1] = End; p->nNonZero[2] = Beg; p->nNonZero[3] = Wlc_PrsFindLine(p, pStart); } } if ( End < 0 || Beg < 0 ) { if ( p->nNegative[0]++ == 0 ) { p->nNegative[1] = End; p->nNegative[2] = Beg; p->nNegative[3] = Wlc_PrsFindLine(p, pStart); } } if ( End < Beg ) { if ( p->nReverse[0]++ == 0 ) { p->nReverse[1] = End; p->nReverse[2] = Beg; p->nReverse[3] = Wlc_PrsFindLine(p, pStart); } } while ( 1 ) { char * pName; int XValue; // read name pStart = Wlc_PrsFindName( pStart, &pName ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name in declaration." ); NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); if ( fFound ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is declared more than once.", pName ); iObj = Wlc_ObjAlloc( p->pNtk, Type, Signed, End, Beg ); if ( fIsPo ) Wlc_ObjSetCo( p->pNtk, Wlc_NtkObj(p->pNtk, iObj), 0 ); assert( iObj == NameId ); // check next definition pStart = Wlc_PrsSkipSpaces( pStart ); if ( pStart[0] == ',' ) { pStart++; continue; } // check definition Type = Wlc_PrsFindDefinition( p, pStart, p->vFanins, &XValue ); if ( Type ) { Wlc_Obj_t * pObj = Wlc_NtkObj( p->pNtk, iObj ); Wlc_ObjUpdateType( p->pNtk, pObj, Type ); Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); pObj->fXConst = XValue; } break; } return 1; } int Wlc_PrsDerive( Wlc_Prs_t * p ) { Wlc_Obj_t * pObj; char * pStart, * pName; int i; // go through the directives Wlc_PrsForEachLine( p, pStart, i ) { startword: if ( Wlc_PrsStrCmp( pStart, "module" ) ) { // get module name pName = Wlc_PrsStrtok( pStart + strlen("module"), " \r\n\t(,)" ); if ( pName == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read model name." ); // THIS IS A HACK to skip definitions of modules beginning with "CPL_" if ( Wlc_PrsStrCmp( pName, "CPL_" ) ) { while ( ++i < Vec_IntSize(p->vStarts) ) { pStart = Wlc_PrsStr(p, Vec_IntEntry(p->vStarts, i)); pStart = strstr( pStart, "endmodule" ); if ( pStart != NULL ) break; } continue; } if ( Wlc_PrsStrCmp( pName, "table" ) ) { // THIS IS A HACK to detect table module descriptions int Width1 = -1, Width2 = -1; int v, b, Value, nBits, nInts; unsigned * pTable; Vec_Int_t * vValues = Vec_IntAlloc( 256 ); Wlc_PrsForEachLineStart( p, pStart, i, i+1 ) { if ( Wlc_PrsStrCmp( pStart, "endcase" ) ) break; pStart = Wlc_PrsFindSymbol( pStart, '\'' ); if ( pStart == NULL ) continue; Width1 = atoi(pStart-1); pStart = Wlc_PrsFindSymbol( pStart+2, '\'' ); if ( pStart == NULL ) continue; Width2 = atoi(pStart-1); Value = 0; Abc_TtReadHexNumber( (word *)&Value, pStart+2 ); Vec_IntPush( vValues, Value ); } //Vec_IntPrint( vValues ); nBits = Abc_Base2Log( Vec_IntSize(vValues) ); if ( Vec_IntSize(vValues) != (1 << nBits) ) { Vec_IntFree( vValues ); return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read module \"%s\".", pName ); } assert( Width1 == nBits ); // create bitmap nInts = Abc_BitWordNum( Width2 * Vec_IntSize(vValues) ); pTable = (unsigned *)Mem_FlexEntryFetch( p->pMemTable, nInts * sizeof(unsigned) ); memset( pTable, 0, nInts * sizeof(unsigned) ); Vec_IntForEachEntry( vValues, Value, v ) for ( b = 0; b < Width2; b++ ) if ( (Value >> b) & 1 ) Abc_InfoSetBit( pTable, v * Width2 + b ); Vec_PtrPush( p->vTables, pTable ); Vec_IntFree( vValues ); continue; } if ( p->pNtk != NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Network is already defined." ); p->pNtk = Wlc_NtkAlloc( pName, Vec_IntSize(p->vStarts) ); p->pNtk->pManName = Abc_NamStart( Vec_IntSize(p->vStarts), 20 ); p->pNtk->pMemTable = p->pMemTable; p->pMemTable = NULL; p->pNtk->vTables = p->vTables; p->vTables = NULL; // read the argument definitions while ( (pName = Wlc_PrsStrtok( NULL, "(,)" )) ) { pName = Wlc_PrsSkipSpaces( pName ); if ( Wlc_PrsStrCmp( pName, "input" ) || Wlc_PrsStrCmp( pName, "output" ) || Wlc_PrsStrCmp( pName, "wire" ) ) { if ( !Wlc_PrsReadDeclaration( p, pName ) ) return 0; } } } else if ( Wlc_PrsStrCmp( pStart, "endmodule" ) ) { Vec_Int_t * vTemp = Vec_IntStartNatural( Wlc_NtkObjNumMax(p->pNtk) ); Vec_IntAppend( &p->pNtk->vNameIds, vTemp ); Vec_IntFree( vTemp ); if ( p->pNtk->vInits ) { // move FO/FI to be part of CI/CO assert( (Vec_IntSize(&p->pNtk->vFfs) & 1) == 0 ); assert( Vec_IntSize(&p->pNtk->vFfs) == 2 * Vec_IntSize(p->pNtk->vInits) ); Wlc_NtkForEachFf( p->pNtk, pObj, i ) if ( i & 1 ) Wlc_ObjSetCo( p->pNtk, pObj, 1 ); else Wlc_ObjSetCi( p->pNtk, pObj ); Vec_IntClear( &p->pNtk->vFfs ); // convert init values into binary string //Vec_IntPrint( &p->pNtk->vInits ); p->pNtk->pInits = Wlc_PrsConvertInitValues( p->pNtk ); //printf( "%s", p->pNtk->pInits ); } break; } // these are read as part of the interface else if ( Wlc_PrsStrCmp( pStart, "input" ) || Wlc_PrsStrCmp( pStart, "output" ) || Wlc_PrsStrCmp( pStart, "wire" ) || Wlc_PrsStrCmp( pStart, "reg" ) ) { if ( !Wlc_PrsReadDeclaration( p, pStart ) ) return 0; } else if ( Wlc_PrsStrCmp( pStart, "assign" ) ) { int Type, NameId, fFound, XValue = 0; pStart += strlen("assign"); // read name pStart = Wlc_PrsFindName( pStart, &pName ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after assign." ); NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); if ( !fFound ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName ); // read definition Type = Wlc_PrsFindDefinition( p, pStart, p->vFanins, &XValue ); if ( Type ) { pObj = Wlc_NtkObj( p->pNtk, NameId ); Wlc_ObjUpdateType( p->pNtk, pObj, Type ); Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); pObj->fXConst = XValue; } else return 0; } else if ( Wlc_PrsStrCmp( pStart, "table" ) ) { // THIS IS A HACK to detect tables int NameId, fFound, iTable = atoi( pStart + strlen("table") ); // find opening pStart = Wlc_PrsFindSymbol( pStart, '(' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." ); // read input pStart = Wlc_PrsFindName( pStart+1, &pName ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after assign." ); NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); if ( !fFound ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName ); // save inputs Vec_IntClear( p->vFanins ); Vec_IntPush( p->vFanins, NameId ); Vec_IntPush( p->vFanins, iTable ); // find comma pStart = Wlc_PrsFindSymbol( pStart, ',' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." ); // read output pStart = Wlc_PrsFindName( pStart+1, &pName ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after assign." ); NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); if ( !fFound ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName ); pObj = Wlc_NtkObj( p->pNtk, NameId ); Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_TABLE ); Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); } else if ( Wlc_PrsStrCmp( pStart, "always" ) ) { // THIS IS A HACK to detect always statement representing combinational MUX int NameId, NameIdOut = -1, fFound, nValues, fDefaultFound = 0; // find control pStart = Wlc_PrsFindWord( pStart, "case", &fFound ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." ); // read the name pStart = Wlc_PrsFindSymbol( pStart, '(' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." ); pStart = Wlc_PrsFindSymbol( pStart+1, '(' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." ); pStart = Wlc_PrsFindName( pStart+1, &pName ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after case." ); NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); if ( !fFound ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName ); Vec_IntClear( p->vFanins ); Vec_IntPush( p->vFanins, NameId ); // read data inputs pObj = Wlc_NtkObj( p->pNtk, NameId ); if ( pObj == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot find the object in case statement." ); // remember the number of values nValues = (1 << Wlc_ObjRange(pObj)); while ( 1 ) { // find opening pStart = Wlc_PrsFindSymbol( pStart, ':' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot find colon in the case statement." ); // find output name pStart = Wlc_PrsFindName( pStart+1, &pName ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after case." ); NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); if ( !fFound ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName ); // find equality pStart = Wlc_PrsFindSymbol( pStart, '=' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot find equality in the case statement." ); // find input name pStart = Wlc_PrsSkipSpaces( pStart+1 ); pStart = Wlc_PrsReadName( p, pStart, p->vFanins ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside case statement." ); // consider default if ( fDefaultFound ) { int EntryLast = Vec_IntEntryLast( p->vFanins ); if (nValues != Vec_IntSize(p->vFanins)-2) Vec_IntFillExtra( p->vFanins, nValues + 1, EntryLast ); else Vec_IntPop(p->vFanins); // get next line and check its opening character pStart = Wlc_PrsStr(p, Vec_IntEntry(p->vStarts, ++i)); pStart = Wlc_PrsSkipSpaces( pStart ); } else { // get next line and check its opening character pStart = Wlc_PrsStr(p, Vec_IntEntry(p->vStarts, ++i)); pStart = Wlc_PrsSkipSpaces( pStart ); if ( Wlc_PrsIsDigit(pStart) ) continue; if ( Wlc_PrsStrCmp( pStart, "default" ) ) { fDefaultFound = 1; continue; } } // find closing pStart = Wlc_PrsFindWord( pStart, "endcase", &fFound ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." ); // find closing pStart = Wlc_PrsFindWord( pStart, "end", &fFound ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." ); pStart = Wlc_PrsSkipSpaces( pStart ); break; } // check range of the control if ( nValues != Vec_IntSize(p->vFanins) - 1 ) return Wlc_PrsWriteErrorMessage( p, pStart, "The number of values in the case statement is wrong.", pName ); if ( Wlc_ObjRange(pObj) == 1 ) { // return Wlc_PrsWriteErrorMessage( p, pStart, "Always-statement with 1-bit control is not bit-blasted correctly.", pName ); printf( "Warning: Case-statement with 1-bit control is treated as a 2:1 MUX (correct for unsigned signals only).\n" ); } pObj = Wlc_NtkObj( p->pNtk, NameIdOut ); Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_MUX ); Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins ); goto startword; } else if ( Wlc_PrsStrCmp( pStart, "CPL_FF" ) ) { int NameId = -1, NameIdIn = -1, NameIdOut = -1, fFound, nBits = 1, fFlopIn, fFlopOut; pStart += strlen("CPL_FF"); if ( pStart[0] == '#' ) nBits = atoi(pStart+1); // read names while ( 1 ) { pStart = Wlc_PrsFindSymbol( pStart, '.' ); if ( pStart == NULL ) break; pStart = Wlc_PrsSkipSpaces( pStart+1 ); if ( pStart[0] != 'd' && (pStart[0] != 'q' || pStart[1] == 'b') && strncmp(pStart, "arstval", 7) ) continue; fFlopIn = (pStart[0] == 'd'); fFlopOut = (pStart[0] == 'q'); pStart = Wlc_PrsFindSymbol( pStart, '(' ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." ); pStart = Wlc_PrsFindName( pStart+1, &pName ); if ( pStart == NULL ) return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." ); if ( fFlopIn ) NameIdIn = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else if ( fFlopOut ) NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); else NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound ); if ( !fFound ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName ); } if ( NameIdIn == -1 || NameIdOut == -1 ) return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." ); // create flop output pObj = Wlc_NtkObj( p->pNtk, NameIdOut ); Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FO ); Vec_IntPush( &p->pNtk->vFfs, NameIdOut ); if ( nBits != Wlc_ObjRange(pObj) ) printf( "Warning! Flop input has bit-width (%d) that differs from the flop declaration (%d)\n", Wlc_ObjRange(pObj), nBits ); // create flop input pObj = Wlc_NtkObj( p->pNtk, NameIdIn ); Vec_IntPush( &p->pNtk->vFfs, NameIdIn ); if ( nBits != Wlc_ObjRange(pObj) ) printf( "Warning! Flop output has bit-width (%d) that differs from the flop declaration (%d)\n", Wlc_ObjRange(pObj), nBits ); // save flop init value if ( NameId == -1 ) printf( "Initial value of flop \"%s\" is not specified. Zero is assumed.\n", Abc_NamStr(p->pNtk->pManName, NameIdOut) ); else { pObj = Wlc_NtkObj( p->pNtk, NameId ); if ( nBits != Wlc_ObjRange(pObj) ) printf( "Warning! Flop init signal bit-width (%d) is different from the flop declaration (%d)\n", Wlc_ObjRange(pObj), nBits ); } if ( p->pNtk->vInits == NULL ) p->pNtk->vInits = Vec_IntAlloc( 100 ); Vec_IntPush( p->pNtk->vInits, NameId > 0 ? NameId : -nBits ); } else if ( pStart[0] != '`' ) { pStart = Wlc_PrsFindName( pStart, &pName ); return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read line beginning with %s.", pName ); } } if ( p->nNonZero[0] ) { printf( "Warning: Input file contains %d objects with non-zero-based ranges.\n", p->nNonZero[0] ); printf( "For example, signal with range [%d:%d] is declared in line %d.\n", p->nNonZero[1], p->nNonZero[2], p->nNonZero[3] ); } if ( p->nNegative[0] ) { printf( "Warning: Input file contains %d objects with negative ranges.\n", p->nNegative[0] ); printf( "For example, signal with range [%d:%d] is declared in line %d.\n", p->nNegative[1], p->nNegative[2], p->nNegative[3] ); } if ( p->nReverse[0] ) { printf( "Warning: Input file contains %d objects with reversed ranges.\n", p->nReverse[0] ); printf( "For example, signal with range [%d:%d] is declared in line %d.\n", p->nReverse[1], p->nReverse[2], p->nReverse[3] ); } return 1; } Wlc_Ntk_t * Wlc_ReadVer( char * pFileName ) { Wlc_Prs_t * p; Wlc_Ntk_t * pNtk = NULL; // start the parser p = Wlc_PrsStart( pFileName ); if ( p == NULL ) return NULL; // detect lines if ( !Wlc_PrsPrepare( p ) ) goto finish; // parse models if ( !Wlc_PrsDerive( p ) ) goto finish; // derive topological order pNtk = Wlc_NtkDupDfs( p->pNtk ); Wlc_NtkTransferNames( pNtk, p->pNtk ); pNtk->pSpec = Abc_UtilStrsav( pFileName ); finish: Wlc_PrsPrintErrorMessage( p ); Wlc_PrsStop( p ); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadWordTest( char * pFileName ) { Gia_Man_t * pNew; Wlc_Ntk_t * pNtk = Wlc_ReadVer( pFileName ); if ( pNtk == NULL ) return; Wlc_WriteVer( pNtk, "test.v", 0, 0 ); pNew = Wlc_NtkBitBlast( pNtk, NULL, -1, 0, 0, 0, 0 ); Gia_AigerWrite( pNew, "test.aig", 0, 0 ); Gia_ManStop( pNew ); Wlc_NtkFree( pNtk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcSim.c000066400000000000000000000215471300674244400231460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Performs sequential simulation of word-level network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 04, 2015.] Revision [$Id: wlcSim.c,v 1.00 2015/06/04 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Internal simulation APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Wlc_ObjSim( Gia_Man_t * p, int iObj ) { return Vec_WrdEntryP( p->vSims, p->iPatsPi * iObj ); } static inline void Wlc_ObjSimPi( Gia_Man_t * p, int iObj ) { int w; word * pSim = Wlc_ObjSim( p, iObj ); for ( w = 0; w < p->iPatsPi; w++ ) pSim[w] = Gia_ManRandomW( 0 ); } static inline void Wlc_ObjSimRo( Gia_Man_t * p, int iObj ) { int w; word * pSimRo = Wlc_ObjSim( p, iObj ); word * pSimRi = Wlc_ObjSim( p, Gia_ObjRoToRiId(p, iObj) ); for ( w = 0; w < p->iPatsPi; w++ ) pSimRo[w] = pSimRi[w]; } static inline void Wlc_ObjSimCo( Gia_Man_t * p, int iObj ) { int w; Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); word * pSimCo = Wlc_ObjSim( p, iObj ); word * pSimDri = Wlc_ObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); if ( Gia_ObjFaninC0(pObj) ) for ( w = 0; w < p->iPatsPi; w++ ) pSimCo[w] = ~pSimDri[w]; else for ( w = 0; w < p->iPatsPi; w++ ) pSimCo[w] = pSimDri[w]; } static inline void Wlc_ObjSimAnd( Gia_Man_t * p, int iObj ) { int w; Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); word * pSim = Wlc_ObjSim( p, iObj ); word * pSim0 = Wlc_ObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); word * pSim1 = Wlc_ObjSim( p, Gia_ObjFaninId1(pObj, iObj) ); if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) for ( w = 0; w < p->iPatsPi; w++ ) pSim[w] = ~pSim0[w] & ~pSim1[w]; else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) for ( w = 0; w < p->iPatsPi; w++ ) pSim[w] = ~pSim0[w] & pSim1[w]; else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) for ( w = 0; w < p->iPatsPi; w++ ) pSim[w] = pSim0[w] & ~pSim1[w]; else for ( w = 0; w < p->iPatsPi; w++ ) pSim[w] = pSim0[w] & pSim1[w]; } /**Function************************************************************* Synopsis [Performs simulation of a word-level network.] Description [Returns vRes, a 2D array of simulation information for the output of each bit of each object listed in vNodes. In particular, Vec_Ptr_t * vSimObj = (Vec_Ptr_t *)Vec_PtrEntry(vRes, iObj) and Vec_Ptr_t * vSimObjBit = (Vec_Ptr_t *)Vec_PtrEntry(vSimObj, iBit) are arrays containing the simulation info for each object (vSimObj) and for each output bit of this object (vSimObjBit). Alternatively, Vec_Ptr_t * vSimObjBit = Vec_VecEntryEntry( (Vec_Vec_t *)vRes, iObj, iBit ). The output bitwidth of an object is Wlc_ObjRange( Wlc_NtkObj(pNtk, iObj) ). Simulation information is binary data constaining the given number (nWords) of 64-bit machine words for the given number (nFrames) of consecutive timeframes. The total number of timeframes is nWords * nFrames for each bit of each object.] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkDeleteSim( Vec_Ptr_t * p ) { word * pInfo; int i, k; Vec_Vec_t * vVec = (Vec_Vec_t *)p; Vec_VecForEachEntry( word *, vVec, pInfo, i, k ) ABC_FREE( pInfo ); Vec_VecFree( vVec ); } Vec_Ptr_t * Wlc_NtkSimulate( Wlc_Ntk_t * p, Vec_Int_t * vNodes, int nWords, int nFrames ) { Gia_Obj_t * pObj; Vec_Ptr_t * vOne, * vRes; Gia_Man_t * pGia = Wlc_NtkBitBlast( p, NULL, -1, 0, 0, 0, 0 ); Wlc_Obj_t * pWlcObj; int f, i, k, w, nBits, Counter = 0; // allocate simulation info for one timeframe Vec_WrdFreeP( &pGia->vSims ); pGia->vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords ); pGia->iPatsPi = nWords; // allocate resulting simulation info vRes = Vec_PtrAlloc( Vec_IntSize(vNodes) ); Wlc_NtkForEachObjVec( vNodes, p, pWlcObj, i ) { nBits = Wlc_ObjRange(pWlcObj); vOne = Vec_PtrAlloc( nBits ); for ( k = 0; k < nBits; k++ ) Vec_PtrPush( vOne, ABC_CALLOC(word, nWords * nFrames) ); Vec_PtrPush( vRes, vOne ); } // perform simulation (const0 and flop outputs are already initialized) Gia_ManRandomW( 1 ); for ( f = 0; f < nFrames; f++ ) { Gia_ManForEachObj1( pGia, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) Wlc_ObjSimAnd( pGia, i ); else if ( Gia_ObjIsCo(pObj) ) Wlc_ObjSimCo( pGia, i ); else if ( Gia_ObjIsPi(pGia, pObj) ) Wlc_ObjSimPi( pGia, i ); else if ( Gia_ObjIsRo(pGia, pObj) ) Wlc_ObjSimRo( pGia, i ); } // collect simulation data Wlc_NtkForEachObjVec( vNodes, p, pWlcObj, i ) { int nBits = Wlc_ObjRange(pWlcObj); int iFirst = Vec_IntEntry( &p->vCopies, Wlc_ObjId(p, pWlcObj) ); for ( k = 0; k < nBits; k++ ) { int iLit = Vec_IntEntry( &p->vBits, iFirst + k ); word * pInfo = (word*)Vec_VecEntryEntry( (Vec_Vec_t *)vRes, i, k ); if ( iLit == -1 ) { Counter++; for ( w = 0; w < nWords; w++ ) pInfo[f * nWords + w] = 0; } else { word * pInfoObj = Wlc_ObjSim( pGia, Abc_Lit2Var(iLit) ); for ( w = 0; w < nWords; w++ ) pInfo[f * nWords + w] = Abc_LitIsCompl(iLit) ? ~pInfoObj[w] : pInfoObj[w]; } } } if ( f == 0 && Counter ) printf( "Replaced %d dangling internal bits with constant 0.\n", Counter ); } Vec_WrdFreeP( &pGia->vSims ); pGia->iPatsPi = 0; Gia_ManStop( pGia ); return vRes; } /**Function************************************************************* Synopsis [Testing procedure.] Description [This testing procedure assumes that the WLC network has one node, which is a multiplier. It simulates the node and checks the word-level interpretation of the bit-level simulation info to make sure that it indeed represents multiplication.] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkSimulatePrint( Wlc_Ntk_t * p, Vec_Int_t * vNodes, Vec_Ptr_t * vRes, int nWords, int nFrames ) { Wlc_Obj_t * pWlcObj; int f, w, b, i, k, iPat = 0; for ( f = 0; f < nFrames; f++, printf("\n") ) for ( w = 0; w < nWords; w++ ) for ( b = 0; b < 64; b++, iPat++, printf("\n") ) { Wlc_NtkForEachObjVec( vNodes, p, pWlcObj, i ) { int nBits = Wlc_ObjRange(pWlcObj); for ( k = nBits-1; k >= 0; k-- ) { word * pInfo = (word*)Vec_VecEntryEntry( (Vec_Vec_t *)vRes, i, k ); printf( "%d", Abc_InfoHasBit((unsigned *)pInfo, iPat) ); } printf( " " ); } } } void Wlc_NtkSimulateTest( Wlc_Ntk_t * p ) { int nWords = 2; int nFrames = 2; Vec_Ptr_t * vRes; Vec_Int_t * vNodes = Vec_IntAlloc( 3 ); Vec_IntPush( vNodes, 1 ); Vec_IntPush( vNodes, 2 ); Vec_IntPush( vNodes, 3 ); vRes = Wlc_NtkSimulate( p, vNodes, nWords, nFrames ); Wlc_NtkSimulatePrint( p, vNodes, vRes, nWords, nFrames ); Wlc_NtkDeleteSim( vRes ); Vec_IntFree( vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcStdin.c000066400000000000000000000175371300674244400235030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcStdin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [stdin processing for STM interface.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcStdin.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converts a bit-string into a number in a given radix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_ComputeSum( char * pRes, char * pAdd, int nBits, int Radix ) { char Carry = 0; int i; for ( i = 0; i < nBits; i++ ) { char Sum = pRes[i] + pAdd[i] + Carry; if ( Sum >= Radix ) { Sum -= Radix; Carry = 1; } else Carry = 0; assert( Sum >= 0 && Sum < Radix ); pRes[i] = Sum; } assert( Carry == 0 ); } Vec_Str_t * Wlc_ConvertToRadix( unsigned * pBits, int Start, int nBits, int Radix ) { Vec_Str_t * vRes = Vec_StrStart( nBits ); Vec_Str_t * vSum = Vec_StrStart( nBits ); char * pRes = Vec_StrArray( vRes ); char * pSum = Vec_StrArray( vSum ); int i; assert( Radix >= 2 && Radix < 36 ); pSum[0] = 1; // compute number for ( i = 0; i < nBits; i++ ) { if ( Abc_InfoHasBit(pBits, Start + i) ) Wlc_ComputeSum( pRes, pSum, nBits, Radix ); if ( i < nBits - 1 ) Wlc_ComputeSum( pSum, pSum, nBits, Radix ); } Vec_StrFree( vSum ); // remove zeros for ( i = nBits - 1; i >= 0; i-- ) if ( pRes[i] ) break; Vec_StrShrink( vRes, i+1 ); // convert to chars for ( ; i >= 0; i-- ) { if ( pRes[i] < 10 ) pRes[i] += '0'; else pRes[i] += 'a' - 10; } Vec_StrReverseOrder( vRes ); if ( Vec_StrSize(vRes) == 0 ) Vec_StrPush( vRes, '0' ); Vec_StrPush( vRes, '\0' ); return vRes; } /**Function************************************************************* Synopsis [Report results.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_NtkReport( Wlc_Ntk_t * p, Abc_Cex_t * pCex, char * pName, int Radix ) { Vec_Str_t * vNum; int i, NameId, Name, Start = -1, nBits = -1; assert( pCex->nRegs == 0 ); // get the name ID NameId = Abc_NamStrFind( p->pManName, pName ); if ( NameId <= 0 ) { printf( "Cannot find \"%s\" among nodes of the network.\n", pName ); return; } // get the primary input Vec_IntForEachEntryTriple( &p->vValues, Name, Start, nBits, i ) if ( Name == NameId ) break; // find the PI if ( i == Vec_IntSize(&p->vValues) ) { printf( "Cannot find \"%s\" among primary inputs of the network.\n", pName ); return; } // print value assert( Radix == 2 || Radix == 10 || Radix == 16 ); vNum = Wlc_ConvertToRadix( pCex->pData, Start, nBits, Radix ); printf( "((%s %s%s))\n", pName, Radix == 16 ? "#x" : (Radix == 2 ? "#b" : ""), Vec_StrArray(vNum) ); Vec_StrFree( vNum ); } /**Function******************************************************************** Synopsis [Reads stdin and stops when "(check-sat)" is observed.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static inline int Wlc_StdinCollectStop( Vec_Str_t * vInput, char * pLine, int LineSize ) { char * pStr = Vec_StrArray(vInput) + Vec_StrSize(vInput) - LineSize; if ( Vec_StrSize(vInput) < LineSize ) return 0; return !strncmp( pStr, pLine, LineSize ); } Vec_Str_t * Wlc_StdinCollectProblem( char * pDir ) { int c, DirSize = strlen(pDir); Vec_Str_t * vInput = Vec_StrAlloc( 1000 ); while ( (c = fgetc(stdin)) != EOF ) { Vec_StrPush( vInput, (char)c ); if ( c == ')' && Wlc_StdinCollectStop(vInput, pDir, DirSize) ) break; } Vec_StrPush( vInput, '\0' ); return vInput; } Vec_Str_t * Wlc_StdinCollectQuery() { int c, Count = 0, fSomeInput = 0; Vec_Str_t * vInput = Vec_StrAlloc( 1000 ); while ( (c = fgetc(stdin)) != EOF ) { Vec_StrPush( vInput, (char)c ); if ( c == '(' ) Count++, fSomeInput = 1; else if ( c == ')' ) Count--; if ( Count == 0 && fSomeInput ) break; } if ( c == EOF ) Vec_StrFreeP( &vInput ); else Vec_StrPush( vInput, '\0' ); return vInput; } int Wlc_StdinProcessSmt( Abc_Frame_t * pAbc, char * pCmd ) { // collect stdin until (check-sat) Vec_Str_t * vInput = Wlc_StdinCollectProblem( "(check-sat)" ); // parse input Wlc_Ntk_t * pNtk = Wlc_ReadSmtBuffer( "top", Vec_StrArray(vInput), Vec_StrArray(vInput) + Vec_StrSize(vInput), 0, 0 ); Vec_StrFree( vInput ); // install current network Wlc_SetNtk( pAbc, pNtk ); // execute command if ( Cmd_CommandExecute(pAbc, pCmd) ) { Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pCmd ); return 0; } // solver finished if ( Abc_FrameReadProbStatus(pAbc) == -1 ) printf( "undecided\n" ); else if ( Abc_FrameReadProbStatus(pAbc) == 1 ) printf( "unsat\n" ); else if ( Abc_FrameReadProbStatus(pAbc) == 0 ) printf( "sat\n" ); else assert( 0 ); fflush( stdout ); // wait for stdin for give directions while ( (vInput = Wlc_StdinCollectQuery()) != NULL ) { char * pName = strtok( Vec_StrArray(vInput), " \n\t\r()" ); // check directive if ( strcmp(pName, "get-value") ) { Abc_Print( 1, "ABC is expecting \"get-value\" in a follow-up input of the satisfiable problem.\n" ); Vec_StrFree( vInput ); return 0; } // check status if ( Abc_FrameReadProbStatus(pAbc) != 0 ) { Abc_Print( 1, "ABC received a follow-up input for a problem that is not known to be satisfiable.\n" ); Vec_StrFree( vInput ); return 0; } // get the variable number pName = strtok( NULL, "() \n\t\r" ); // get the counter-example if ( Abc_FrameReadCex(pAbc) == NULL ) { Abc_Print( 1, "ABC does not have a counter-example available to process a \"get-value\" request.\n" ); Vec_StrFree( vInput ); return 0; } // report value of this variable Wlc_NtkReport( (Wlc_Ntk_t *)pAbc->pAbcWlc, Abc_FrameReadCex(pAbc), pName, 16 ); Vec_StrFree( vInput ); fflush( stdout ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/base/wlc/wlcWriteVer.c000066400000000000000000000466071300674244400241710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [wlcWriteVer.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Writes word-level Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: wlcWriteVer.c,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wlc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_WriteTableOne( FILE * pFile, int nFans, int nOuts, word * pTable, int Id ) { int m, nMints = (1< 0 && nOuts <= 64 && (64 % nOuts) == 0 ); fprintf( pFile, "module table%d(ind, val);\n", Id ); fprintf( pFile, " input [%d:0] ind;\n", nFans-1 ); fprintf( pFile, " output [%d:0] val;\n", nOuts-1 ); fprintf( pFile, " reg [%d:0] val;\n", nOuts-1 ); fprintf( pFile, " always @(ind)\n" ); fprintf( pFile, " begin\n" ); fprintf( pFile, " case (ind)\n" ); for ( m = 0; m < nMints; m++ ) fprintf( pFile, " %d\'h%x: val = %d\'h%x;\n", nFans, m, nOuts, (unsigned)((pTable[(nOuts * m) >> 6] >> ((nOuts * m) & 63)) & Abc_Tt6Mask(nOuts)) ); fprintf( pFile, " endcase\n" ); fprintf( pFile, " end\n" ); fprintf( pFile, "endmodule\n" ); fprintf( pFile, "\n" ); } void Wlc_WriteTables( FILE * pFile, Wlc_Ntk_t * p ) { Vec_Int_t * vNodes; Wlc_Obj_t * pObj, * pFanin; word * pTable; int i; if ( p->vTables == NULL || Vec_PtrSize(p->vTables) == 0 ) return; // map tables into their nodes vNodes = Vec_IntStart( Vec_PtrSize(p->vTables) ); Wlc_NtkForEachObj( p, pObj, i ) if ( pObj->Type == WLC_OBJ_TABLE ) Vec_IntWriteEntry( vNodes, Wlc_ObjTableId(pObj), i ); // write tables Vec_PtrForEachEntry( word *, p->vTables, pTable, i ) { pObj = Wlc_NtkObj( p, Vec_IntEntry(vNodes, i) ); assert( pObj->Type == WLC_OBJ_TABLE ); pFanin = Wlc_ObjFanin0( p, pObj ); Wlc_WriteTableOne( pFile, Wlc_ObjRange(pFanin), Wlc_ObjRange(pObj), pTable, i ); } Vec_IntFree( vNodes ); } /**Function************************************************************* Synopsis [This was used to add POs to each node except PIs and MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_WriteAddPos( Wlc_Ntk_t * p ) { Wlc_Obj_t * pObj; int i; Vec_IntClear( &p->vPos ); Wlc_NtkForEachObj( p, pObj, i ) if ( pObj->Type != WLC_OBJ_PI && pObj->Type != WLC_OBJ_MUX ) { pObj->fIsPo = 1; Vec_IntPush( &p->vPos, Wlc_ObjId(p, pObj) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Wlc_WriteVerIntVec( FILE * pFile, Wlc_Ntk_t * p, Vec_Int_t * vVec, int Start ) { char * pName; int LineLength = Start; int NameCounter = 0; int AddedLength, i, iObj; Vec_IntForEachEntry( vVec, iObj, i ) { pName = Wlc_ObjName( p, iObj ); // get the line length after this name is written AddedLength = strlen(pName) + 2; if ( NameCounter && LineLength + AddedLength + 3 > 70 ) { // write the line extender fprintf( pFile, "\n " ); // reset the line length LineLength = Start; NameCounter = 0; } fprintf( pFile, " %s%s", pName, (i==Vec_IntSize(vVec)-1)? "" : "," ); LineLength += AddedLength; NameCounter++; } } void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops ) { Wlc_Obj_t * pObj; int i, k, iFanin; char Range[100]; fprintf( pFile, "module %s ( ", p->pName ); fprintf( pFile, "\n " ); if ( Wlc_NtkPiNum(p) > 0 || (fNoFlops && Wlc_NtkCiNum(p)) ) { Wlc_WriteVerIntVec( pFile, p, fNoFlops ? &p->vCis : &p->vPis, 3 ); fprintf( pFile, ",\n " ); } if ( Wlc_NtkPoNum(p) > 0 || (fNoFlops && Wlc_NtkCoNum(p)) ) Wlc_WriteVerIntVec( pFile, p, fNoFlops ? &p->vCos : &p->vPos, 3 ); fprintf( pFile, " );\n" ); // mark fanins of rotation shifts Wlc_NtkForEachObj( p, pObj, i ) if ( pObj->Type == WLC_OBJ_ROTATE_R || pObj->Type == WLC_OBJ_ROTATE_L ) Wlc_ObjFanin1(p, pObj)->Mark = 1; Wlc_NtkForEachObj( p, pObj, i ) { int nDigits = Abc_Base10Log(Abc_AbsInt(pObj->End)+1) + Abc_Base10Log(Abc_AbsInt(pObj->Beg)+1) + (int)(pObj->End < 0) + (int)(pObj->Beg < 0); if ( pObj->Mark ) { pObj->Mark = 0; continue; } sprintf( Range, "%s[%d:%d]%*s", (!p->fSmtLib && Wlc_ObjIsSigned(pObj)) ? "signed ":" ", pObj->End, pObj->Beg, 8-nDigits, "" ); fprintf( pFile, " " ); if ( pObj->Type == WLC_OBJ_PI || (fNoFlops && pObj->Type == WLC_OBJ_FO) ) fprintf( pFile, "input " ); else if ( pObj->fIsPo || (fNoFlops && pObj->fIsFi) ) fprintf( pFile, "output " ); else fprintf( pFile, " " ); if ( Wlc_ObjIsCi(pObj) || pObj->fIsPo || (fNoFlops && pObj->fIsFi) ) { fprintf( pFile, "wire %s %s ;\n", Range, Wlc_ObjName(p, i) ); if ( Wlc_ObjIsCi(pObj) ) continue; Range[0] = 0; } if ( pObj->fIsPo || (fNoFlops && pObj->fIsFi) ) fprintf( pFile, " assign " ); else if ( pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3 ) fprintf( pFile, "reg %s ", Range ); else fprintf( pFile, "wire %s ", Range ); if ( pObj->Type == WLC_OBJ_TABLE ) { // wire [3:0] s4972; table0 s4972_Index(s4971, s4972); fprintf( pFile, "%s ; table%d", Wlc_ObjName(p, i), Wlc_ObjTableId(pObj) ); fprintf( pFile, " s%d_Index(%s, ", i, Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); fprintf( pFile, "%s)", Wlc_ObjName(p, i) ); } else if ( pObj->Type == WLC_OBJ_CONST ) { fprintf( pFile, "%-16s = %d\'%sh", Wlc_ObjName(p, i), Wlc_ObjRange(pObj), Wlc_ObjIsSigned(pObj) ? "s":"" ); if ( pObj->fXConst ) { for ( k = 0; k < (Wlc_ObjRange(pObj) + 3) / 4; k++ ) fprintf( pFile, "x" ); } else Abc_TtPrintHexArrayRev( pFile, (word *)Wlc_ObjConstValue(pObj), (Wlc_ObjRange(pObj) + 3) / 4 ); } else if ( pObj->Type == WLC_OBJ_ROTATE_R || pObj->Type == WLC_OBJ_ROTATE_L ) { // wire [27:0] s4960 = (s57 >> 17) | (s57 << 11); Wlc_Obj_t * pShift = Wlc_ObjFanin1(p, pObj); int Num0 = *Wlc_ObjConstValue(pShift); int Num1 = Wlc_ObjRange(pObj) - Num0; assert( pShift->Type == WLC_OBJ_CONST ); assert( Num0 > 0 && Num0 < Wlc_ObjRange(pObj) ); fprintf( pFile, "%-16s = ", Wlc_ObjName(p, i) ); if ( pObj->Type == WLC_OBJ_ROTATE_R ) fprintf( pFile, "(%s >> %d) | (%s << %d)", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Num0, Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Num1 ); else fprintf( pFile, "(%s << %d) | (%s >> %d)", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Num0, Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Num1 ); } else if ( pObj->Type == WLC_OBJ_MUX && Wlc_ObjFaninNum(pObj) > 3 ) { fprintf( pFile, "%s ;\n", Wlc_ObjName(p, i) ); fprintf( pFile, " " ); fprintf( pFile, "always @( " ); Wlc_ObjForEachFanin( pObj, iFanin, k ) fprintf( pFile, "%s%s", k ? " or ":"", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, k)) ); fprintf( pFile, " )\n" ); fprintf( pFile, " " ); fprintf( pFile, "begin\n" ); fprintf( pFile, " " ); fprintf( pFile, "case ( %s )\n", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, 0)) ); Wlc_ObjForEachFanin( pObj, iFanin, k ) { if ( !k ) continue; fprintf( pFile, " " ); fprintf( pFile, "%d : %s = ", k-1, Wlc_ObjName(p, i) ); fprintf( pFile, "%s ;\n", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, k)) ); } fprintf( pFile, " " ); fprintf( pFile, "endcase\n" ); fprintf( pFile, " " ); fprintf( pFile, "end\n" ); continue; } else { fprintf( pFile, "%-16s = ", Wlc_ObjName(p, i) ); if ( pObj->Type == WLC_OBJ_BUF ) fprintf( pFile, "%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_MUX ) { fprintf( pFile, "%s ? ", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); fprintf( pFile, "%s : ", Wlc_ObjName(p, Wlc_ObjFaninId2(pObj)) ); fprintf( pFile, "%s", Wlc_ObjName(p, Wlc_ObjFaninId1(pObj)) ); } else if ( pObj->Type == WLC_OBJ_ARI_MINUS ) fprintf( pFile, "-%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_NOT ) fprintf( pFile, "~%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_LOGIC_NOT ) fprintf( pFile, "!%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_REDUCT_AND ) fprintf( pFile, "&%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_REDUCT_OR ) fprintf( pFile, "|%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_REDUCT_XOR ) fprintf( pFile, "^%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_REDUCT_NAND ) fprintf( pFile, "~&%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_REDUCT_NOR ) fprintf( pFile, "~|%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_REDUCT_NXOR ) fprintf( pFile, "~^%s", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_SELECT ) fprintf( pFile, "%s [%d:%d]", Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Wlc_ObjRangeEnd(pObj), Wlc_ObjRangeBeg(pObj) ); else if ( pObj->Type == WLC_OBJ_BIT_SIGNEXT ) fprintf( pFile, "{ {%d{%s[%d]}}, %s }", Wlc_ObjRange(pObj) - Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)), Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)) - 1, Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_ZEROPAD ) fprintf( pFile, "{ {%d{1\'b0}}, %s }", Wlc_ObjRange(pObj) - Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjName(p, Wlc_ObjFaninId0(pObj)) ); else if ( pObj->Type == WLC_OBJ_BIT_CONCAT ) { fprintf( pFile, "{" ); Wlc_ObjForEachFanin( pObj, iFanin, k ) fprintf( pFile, " %s%s", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, k)), k == Wlc_ObjFaninNum(pObj)-1 ? "":"," ); fprintf( pFile, " }" ); } else { fprintf( pFile, "%s ", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, 0)) ); if ( pObj->Type == WLC_OBJ_SHIFT_R ) fprintf( pFile, ">>" ); else if ( pObj->Type == WLC_OBJ_SHIFT_RA ) fprintf( pFile, ">>>" ); else if ( pObj->Type == WLC_OBJ_SHIFT_L ) fprintf( pFile, "<<" ); else if ( pObj->Type == WLC_OBJ_SHIFT_LA ) fprintf( pFile, "<<<" ); else if ( pObj->Type == WLC_OBJ_BIT_AND ) fprintf( pFile, "&" ); else if ( pObj->Type == WLC_OBJ_BIT_OR ) fprintf( pFile, "|" ); else if ( pObj->Type == WLC_OBJ_BIT_XOR ) fprintf( pFile, "^" ); else if ( pObj->Type == WLC_OBJ_BIT_NAND ) fprintf( pFile, "~&" ); else if ( pObj->Type == WLC_OBJ_BIT_NOR ) fprintf( pFile, "~|" ); else if ( pObj->Type == WLC_OBJ_BIT_NXOR ) fprintf( pFile, "~^" ); else if ( pObj->Type == WLC_OBJ_LOGIC_IMPL ) fprintf( pFile, "=>" ); else if ( pObj->Type == WLC_OBJ_LOGIC_AND ) fprintf( pFile, "&&" ); else if ( pObj->Type == WLC_OBJ_LOGIC_OR ) fprintf( pFile, "||" ); else if ( pObj->Type == WLC_OBJ_LOGIC_XOR ) fprintf( pFile, "^^" ); else if ( pObj->Type == WLC_OBJ_COMP_EQU ) fprintf( pFile, "==" ); else if ( pObj->Type == WLC_OBJ_COMP_NOTEQU ) fprintf( pFile, "!=" ); else if ( pObj->Type == WLC_OBJ_COMP_LESS ) fprintf( pFile, "<" ); else if ( pObj->Type == WLC_OBJ_COMP_MORE ) fprintf( pFile, ">" ); else if ( pObj->Type == WLC_OBJ_COMP_LESSEQU ) fprintf( pFile, "<=" ); else if ( pObj->Type == WLC_OBJ_COMP_MOREEQU ) fprintf( pFile, ">=" ); else if ( pObj->Type == WLC_OBJ_ARI_ADD ) fprintf( pFile, "+" ); else if ( pObj->Type == WLC_OBJ_ARI_SUB ) fprintf( pFile, "-" ); else if ( pObj->Type == WLC_OBJ_ARI_MULTI ) fprintf( pFile, "*" ); else if ( pObj->Type == WLC_OBJ_ARI_DIVIDE ) fprintf( pFile, "/" ); else if ( pObj->Type == WLC_OBJ_ARI_REM ) fprintf( pFile, "%%" ); else if ( pObj->Type == WLC_OBJ_ARI_MODULUS ) fprintf( pFile, "%%" ); else if ( pObj->Type == WLC_OBJ_ARI_POWER ) fprintf( pFile, "**" ); else if ( pObj->Type == WLC_OBJ_ARI_SQRT ) fprintf( pFile, "@" ); else if ( pObj->Type == WLC_OBJ_ARI_SQUARE ) fprintf( pFile, "#" ); else assert( 0 ); //fprintf( pFile, "???" ); fprintf( pFile, " %s", Wlc_ObjName(p, Wlc_ObjFaninId(pObj, 1)) ); } } fprintf( pFile, " ;%s\n", (p->fSmtLib && Wlc_ObjIsSigned(pObj)) ? " // signed SMT-LIB operator" : "" ); } iFanin = 0; assert( !p->vInits || Wlc_NtkFfNum(p) == Vec_IntSize(p->vInits) ); if ( !fNoFlops ) { if ( p->vInits ) Wlc_NtkForEachCi( p, pObj, i ) { int nDigits = Abc_Base10Log(pObj->End+1) + 1; char * pName = Wlc_ObjName(p, Wlc_ObjId(p, pObj)); assert( i == Wlc_ObjCiId(pObj) ); if ( pObj->Type == WLC_OBJ_PI ) continue; sprintf( Range, " [%d:%d]%*s", Wlc_ObjRange(pObj) - 1, 0, 8-nDigits, "" ); fprintf( pFile, " " ); fprintf( pFile, "wire %s ", Range ); fprintf( pFile, "%s_init%*s = ", pName, 11 - (int)strlen(pName), "" ); if ( Vec_IntEntry(p->vInits, i-Wlc_NtkPiNum(p)) > 0 ) fprintf( pFile, "%s", Wlc_ObjName(p, Wlc_ObjId(p, Wlc_NtkPi(p, Vec_IntEntry(p->vInits, i-Wlc_NtkPiNum(p)))))); else { if ( p->pInits[iFanin] == 'x' || p->pInits[iFanin] == 'X' ) { fprintf( pFile, "%d\'h", Wlc_ObjRange(pObj) ); for ( k = 0; k < (Wlc_ObjRange(pObj) + 3) / 4; k++ ) fprintf( pFile, "x" ); } else { fprintf( pFile, "%d\'b", Wlc_ObjRange(pObj) ); for ( k = Wlc_ObjRange(pObj)-1; k >= 0; k-- ) fprintf( pFile, "%c", p->pInits[iFanin + k] ); } } fprintf( pFile, ";\n" ); iFanin += Wlc_ObjRange(pObj); } Wlc_NtkForEachCi( p, pObj, i ) { assert( i == Wlc_ObjCiId(pObj) ); if ( pObj->Type == WLC_OBJ_PI ) continue; fprintf( pFile, " " ); fprintf( pFile, "CPL_FF" ); if ( Wlc_ObjRange(pObj) > 1 ) fprintf( pFile, "#%d%*s", Wlc_ObjRange(pObj), 4 - Abc_Base10Log(Wlc_ObjRange(pObj)+1), "" ); else fprintf( pFile, " " ); fprintf( pFile, " reg%d (", i ); fprintf( pFile, " .q( %s ),", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); fprintf( pFile, " .qbar()," ); fprintf( pFile, " .d( %s ),", Wlc_ObjName(p, Wlc_ObjId(p, Wlc_ObjFoToFi(p, pObj))) ); fprintf( pFile, " .clk( %s ),", "1\'b0" ); fprintf( pFile, " .arst( %s ),", "1\'b0" ); if ( p->vInits ) fprintf( pFile, " .arstval( %s_init )", Wlc_ObjName(p, Wlc_ObjId(p, pObj)) ); else fprintf( pFile, " .arstval( %s )", "1\'b0" ); fprintf( pFile, " ) ;\n" ); } assert( !p->vInits || iFanin == (int)strlen(p->pInits) ); } fprintf( pFile, "endmodule\n\n" ); } void Wlc_WriteVer( Wlc_Ntk_t * p, char * pFileName, int fAddCos, int fNoFlops ) { FILE * pFile; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Wlc_WriteVer(): Cannot open the output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", p->pName, Extra_TimeStamp() ); fprintf( pFile, "\n" ); Wlc_WriteTables( pFile, p ); if ( fAddCos ) Wlc_WriteAddPos( p ); Wlc_WriteVerInt( pFile, p, fNoFlops ); fprintf( pFile, "\n" ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/000077500000000000000000000000001300674244400205655ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/bbr/000077500000000000000000000000001300674244400213325ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/bbr/bbr.h000066400000000000000000000071501300674244400222530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bbr.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD-based reachability analysis.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bbr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__bbr__bbr_h #define ABC__aig__bbr__bbr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include "bdd/cudd/cuddInt.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline DdNode * Aig_ObjGlobalBdd( Aig_Obj_t * pObj ) { return (DdNode *)pObj->pData; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== bbrImage.c ==========================================================*/ typedef struct Bbr_ImageTree_t_ Bbr_ImageTree_t; extern Bbr_ImageTree_t * Bbr_bddImageStart( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ); extern DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ); extern void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ); extern DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ); typedef struct Bbr_ImageTree2_t_ Bbr_ImageTree2_t; extern Bbr_ImageTree2_t * Bbr_bddImageStart2( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars, int fVerbose ); extern DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ); extern void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ); extern DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ); /*=== bbrNtbdd.c ==========================================================*/ extern void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ); extern int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ); extern DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); /*=== bbrReach.c ==========================================================*/ extern int Aig_ManVerifyUsingBdds( Aig_Man_t * p, Saig_ParBbr_t * pPars ); extern void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/bbr/bbrCex.c000066400000000000000000000133361300674244400227110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bbrCex.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD-based reachability analysis.] Synopsis [Procedures to derive a satisfiable counter-example.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bbrCex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bbr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the counter-example using the set of reached states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, int iOutput, int fVerbose, int fSilent ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; Bbr_ImageTree_t * pTree; DdNode * bCubeNs, * bState, * bImage; DdNode * bTemp, * bVar, * bRing; int i, v, RetValue, nPiOffset; char * pValues; abctime clk = Abc_Clock(); //printf( "\nDeriving counter-example.\n" ); // allocate room for the counter-example pCex = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), Vec_PtrSize(vOnionRings)+1 ); pCex->iFrame = Vec_PtrSize(vOnionRings); pCex->iPo = iOutput; nPiOffset = Saig_ManRegNum(p) + Saig_ManPiNum(p) * Vec_PtrSize(vOnionRings); // create the cube of NS variables bCubeNs = Bbr_bddComputeRangeCube( dd, Saig_ManCiNum(p), Saig_ManCiNum(p)+Saig_ManRegNum(p) ); Cudd_Ref( bCubeNs ); pTree = Bbr_bddImageStart( dd, bCubeNs, Saig_ManRegNum(p), pbParts, Saig_ManCiNum(p), dd->vars, 100000000, fVerbose ); Cudd_RecursiveDeref( dd, bCubeNs ); if ( pTree == NULL ) { if ( !fSilent ) printf( "BDDs blew up during qualitification scheduling. " ); return NULL; } // allocate room for the cube pValues = ABC_ALLOC( char, dd->size ); // get the last cube RetValue = Cudd_bddPickOneCube( dd, bCubeFirst, pValues ); assert( RetValue ); // write PIs of counter-example Saig_ManForEachPi( p, pObj, i ) if ( pValues[i] == 1 ) Abc_InfoSetBit( pCex->pData, nPiOffset + i ); nPiOffset -= Saig_ManPiNum(p); // write state in terms of NS variables bState = (dd)->one; Cudd_Ref( bState ); Saig_ManForEachLo( p, pObj, i ) { bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); Cudd_RecursiveDeref( dd, bTemp ); } // perform backward analysis Vec_PtrForEachEntryReverse( DdNode *, vOnionRings, bRing, v ) { // compute the next states bImage = Bbr_bddImageCompute( pTree, bState ); if ( bImage == NULL ) { Cudd_RecursiveDeref( dd, bState ); if ( !fSilent ) printf( "BDDs blew up during image computation. " ); Bbr_bddImageTreeDelete( pTree ); ABC_FREE( pValues ); return NULL; } Cudd_Ref( bImage ); Cudd_RecursiveDeref( dd, bState ); // intersect with the previous set bImage = Cudd_bddAnd( dd, bTemp = bImage, bRing ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( dd, bTemp ); // find any assignment of the BDD RetValue = Cudd_bddPickOneCube( dd, bImage, pValues ); assert( RetValue ); Cudd_RecursiveDeref( dd, bImage ); // write PIs of counter-example Saig_ManForEachPi( p, pObj, i ) if ( pValues[i] == 1 ) Abc_InfoSetBit( pCex->pData, nPiOffset + i ); nPiOffset -= Saig_ManPiNum(p); // check that we get the init state if ( v == 0 ) { Saig_ManForEachLo( p, pObj, i ) assert( pValues[Saig_ManPiNum(p)+i] == 0 ); break; } // write state in terms of NS variables bState = (dd)->one; Cudd_Ref( bState ); Saig_ManForEachLo( p, pObj, i ) { bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); Cudd_RecursiveDeref( dd, bTemp ); } } // cleanup Bbr_bddImageTreeDelete( pTree ); ABC_FREE( pValues ); // verify the counter example if ( Vec_PtrSize(vOnionRings) < 1000 ) { RetValue = Saig_ManVerifyCex( p, pCex ); if ( RetValue == 0 && !fSilent ) printf( "Aig_ManVerifyUsingBdds(): Counter-example verification has FAILED.\n" ); } if ( fVerbose && !fSilent ) { ABC_PRT( "Counter-example generation time", Abc_Clock() - clk ); } return pCex; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/bbr/bbrImage.c000066400000000000000000001203241300674244400232100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bbrImage.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD-based reachability analysis.] Synopsis [Performs image computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bbrImage.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bbr.h" #include "bdd/mtr/mtr.h" ABC_NAMESPACE_IMPL_START /* The ideas implemented in this file are inspired by the paper: Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in Image Computation. ICCAD, 2001. */ /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ typedef struct Bbr_ImageNode_t_ Bbr_ImageNode_t; typedef struct Bbr_ImagePart_t_ Bbr_ImagePart_t; typedef struct Bbr_ImageVar_t_ Bbr_ImageVar_t; struct Bbr_ImageTree_t_ { Bbr_ImageNode_t * pRoot; // the root of quantification tree Bbr_ImageNode_t * pCare; // the leaf node with the care set DdNode * bCareSupp; // the cube to quantify from the care int fVerbose; // the verbosity flag int nNodesMax; // the max number of nodes in one iter int nNodesMaxT; // the overall max number of nodes int nIter; // the number of iterations with this tree int nBddMax; // the number of node to stop }; struct Bbr_ImageNode_t_ { DdManager * dd; // the manager DdNode * bCube; // the cube to quantify DdNode * bImage; // the partial image Bbr_ImageNode_t * pNode1; // the first branch Bbr_ImageNode_t * pNode2; // the second branch Bbr_ImagePart_t * pPart; // the partition (temporary) }; struct Bbr_ImagePart_t_ { DdNode * bFunc; // the partition DdNode * bSupp; // the support of this partition int nNodes; // the number of BDD nodes short nSupp; // the number of support variables short iPart; // the number of this partition }; struct Bbr_ImageVar_t_ { int iNum; // the BDD index of this variable DdNode * bParts; // the partition numbers int nParts; // the number of partitions }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ #define b0 Cudd_Not((dd)->one) #define b1 (dd)->one #ifndef ABC_PRB #define ABC_PRB(dd,f) printf("%s = ", #f); Bbr_bddPrint(dd,f); printf("\n") #endif /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, int nParts, DdNode ** pbParts, DdNode * bCare ); static Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, int nParts, Bbr_ImagePart_t ** pParts, int nVars, DdNode ** pbVarsNs ); static Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, int nParts, Bbr_ImagePart_t ** pParts, int nVars, Bbr_ImageVar_t ** pVars ); static void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ); static int Bbr_BuildTreeNode( DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes, int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ); static Bbr_ImageNode_t * Bbr_MergeTopNodes( DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes ); static void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ); static int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ); static int Bbr_FindBestVariable( DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes, int nVars, Bbr_ImageVar_t ** pVars ); static void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, int nNodes, Bbr_ImageNode_t ** pNodes, int * piNode1, int * piNode2 ); static Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ); static void Bbr_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars ); static void Bbr_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, DdNode * bVarsCs, DdNode * bVarsNs, int iPart ); static void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ); static void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int nOffset ); static void Bbr_bddPrint( DdManager * dd, DdNode * F ); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Starts the image computation using tree-based scheduling.] Description [This procedure starts the image computation. It uses the given care set to test-run the image computation and creates the quantification tree by scheduling variable quantifications. The tree can be used to compute images for other care sets without rescheduling. In this case, Bbr_bddImageCompute() should be called.] SideEffects [] SeeAlso [] ***********************************************************************/ Bbr_ImageTree_t * Bbr_bddImageStart( DdManager * dd, DdNode * bCare, // the care set int nParts, DdNode ** pbParts, // the partitions for image computation int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ) // the NS and parameter variables (not quantified!) { Bbr_ImageTree_t * pTree; Bbr_ImagePart_t ** pParts; Bbr_ImageVar_t ** pVars; Bbr_ImageNode_t ** pNodes, * pCare; int fStop, v; if ( fVerbose && dd->size <= 80 ) Bbr_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars ); // create variables, partitions and leaf nodes pParts = Bbr_CreateParts( dd, nParts, pbParts, bCare ); pVars = Bbr_CreateVars( dd, nParts + 1, pParts, nVars, pbVars ); pNodes = Bbr_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars ); pCare = pNodes[nParts]; // process the nodes while ( Bbr_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars, &fStop, nBddMax ) ); // consider the case of BDD node blowup if ( fStop ) { for ( v = 0; v < dd->size; v++ ) if ( pVars[v] ) ABC_FREE( pVars[v] ); ABC_FREE( pVars ); for ( v = 0; v <= nParts; v++ ) if ( pNodes[v] ) { Bbr_DeleteParts_rec( pNodes[v] ); Bbr_bddImageTreeDelete_rec( pNodes[v] ); } ABC_FREE( pNodes ); ABC_FREE( pParts ); return NULL; } // make sure the variables are gone for ( v = 0; v < dd->size; v++ ) assert( pVars[v] == NULL ); ABC_FREE( pVars ); // create the tree pTree = ABC_ALLOC( Bbr_ImageTree_t, 1 ); memset( pTree, 0, sizeof(Bbr_ImageTree_t) ); pTree->pCare = pCare; pTree->nBddMax = nBddMax; pTree->fVerbose = fVerbose; // merge the topmost nodes while ( (pTree->pRoot = Bbr_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL ); // make sure the nodes are gone for ( v = 0; v < nParts + 1; v++ ) assert( pNodes[v] == NULL ); ABC_FREE( pNodes ); // if ( fVerbose ) // Bbr_bddImagePrintTree( pTree ); // set the support of the care set pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp ); // clean the partitions Bbr_DeleteParts_rec( pTree->pRoot ); ABC_FREE( pParts ); return pTree; } /**Function************************************************************* Synopsis [Compute the image.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ) { DdManager * dd = pTree->pCare->dd; DdNode * bSupp, * bRem; pTree->nIter++; // make sure the supports are okay bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); if ( bSupp != pTree->bCareSupp ) { bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); if ( bRem != b1 ) { printf( "Original care set support: " ); ABC_PRB( dd, pTree->bCareSupp ); printf( "Current care set support: " ); ABC_PRB( dd, bSupp ); Cudd_RecursiveDeref( dd, bSupp ); Cudd_RecursiveDeref( dd, bRem ); printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); return NULL; } Cudd_RecursiveDeref( dd, bRem ); } Cudd_RecursiveDeref( dd, bSupp ); // remove the previous image Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); // compute the image pTree->nNodesMax = 0; if ( !Bbr_bddImageCompute_rec( pTree, pTree->pRoot ) ) return NULL; if ( pTree->nNodesMaxT < pTree->nNodesMax ) pTree->nNodesMaxT = pTree->nNodesMax; // if ( pTree->fVerbose ) // printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); return pTree->pRoot->bImage; } /**Function************************************************************* Synopsis [Delete the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ) { if ( pTree->bCareSupp ) Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp ); Bbr_bddImageTreeDelete_rec( pTree->pRoot ); ABC_FREE( pTree ); } /**Function************************************************************* Synopsis [Reads the image from the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ) { return pTree->pRoot->bImage; } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Outputs the BDD in a readable format.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void Bbr_bddPrint( DdManager * dd, DdNode * F ) { DdGen * Gen; int * Cube; CUDD_VALUE_TYPE Value; int nVars = dd->size; int fFirstCube = 1; int i; if ( F == NULL ) { printf("NULL"); return; } if ( F == b0 ) { printf("Constant 0"); return; } if ( F == b1 ) { printf("Constant 1"); return; } Cudd_ForeachCube( dd, F, Gen, Cube, Value ) { if ( fFirstCube ) fFirstCube = 0; else // Output << " + "; printf( " + " ); for ( i = 0; i < nVars; i++ ) if ( Cube[i] == 0 ) printf( "[%d]'", i ); // printf( "%c'", (char)('a'+i) ); else if ( Cube[i] == 1 ) printf( "[%d]", i ); // printf( "%c", (char)('a'+i) ); } // printf("\n"); } /*---------------------------------------------------------------------------*/ /* Definition of static Functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Creates partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, int nParts, DdNode ** pbParts, DdNode * bCare ) { Bbr_ImagePart_t ** pParts; int i; // start the partitions pParts = ABC_ALLOC( Bbr_ImagePart_t *, nParts + 1 ); // create structures for each variable for ( i = 0; i < nParts; i++ ) { pParts[i] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc ); pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp ); pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); pParts[i]->iPart = i; } // add the care set as the last partition pParts[nParts] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc ); pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp ); pParts[nParts]->nSupp = Cudd_SupportSize( dd, pParts[nParts]->bSupp ); pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc ); pParts[nParts]->iPart = nParts; return pParts; } /**Function************************************************************* Synopsis [Creates variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, int nParts, Bbr_ImagePart_t ** pParts, int nVars, DdNode ** pbVars ) { Bbr_ImageVar_t ** pVars; DdNode ** pbFuncs; DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp; int nVarsTotal, iVar, p, Counter; // put all the functions into one array pbFuncs = ABC_ALLOC( DdNode *, nParts ); for ( p = 0; p < nParts; p++ ) pbFuncs[p] = pParts[p]->bSupp; bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp ); ABC_FREE( pbFuncs ); // remove the NS vars bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs ); bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCubeNs ); // get the number of I and CS variables to be quantified nVarsTotal = Cudd_SupportSize( dd, bSupp ); // start the variables pVars = ABC_ALLOC( Bbr_ImageVar_t *, dd->size ); memset( pVars, 0, sizeof(Bbr_ImageVar_t *) * dd->size ); // create structures for each variable for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) { iVar = bSuppTemp->index; pVars[iVar] = ABC_ALLOC( Bbr_ImageVar_t, 1 ); pVars[iVar]->iNum = iVar; // collect all the parts this var belongs to Counter = 0; bParts = b1; Cudd_Ref( bParts ); for ( p = 0; p < nParts; p++ ) if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) ) { bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts ); Cudd_RecursiveDeref( dd, bTemp ); Counter++; } pVars[iVar]->bParts = bParts; // takes ref pVars[iVar]->nParts = Counter; } Cudd_RecursiveDeref( dd, bSupp ); return pVars; } /**Function************************************************************* Synopsis [Creates variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, int nParts, Bbr_ImagePart_t ** pParts, int nVars, Bbr_ImageVar_t ** pVars ) { Bbr_ImageNode_t ** pNodes; Bbr_ImageNode_t * pNode; DdNode * bTemp; int i, v, iPart; /* DdManager * dd; // the manager DdNode * bCube; // the cube to quantify DdNode * bImage; // the partial image Bbr_ImageNode_t * pNode1; // the first branch Bbr_ImageNode_t * pNode2; // the second branch Bbr_ImagePart_t * pPart; // the partition (temporary) */ // start the partitions pNodes = ABC_ALLOC( Bbr_ImageNode_t *, nParts ); // create structures for each leaf nodes for ( i = 0; i < nParts; i++ ) { pNodes[i] = ABC_ALLOC( Bbr_ImageNode_t, 1 ); memset( pNodes[i], 0, sizeof(Bbr_ImageNode_t) ); pNodes[i]->dd = dd; pNodes[i]->pPart = pParts[i]; } // find the quantification cubes for each leaf node for ( v = 0; v < nVars; v++ ) { if ( pVars[v] == NULL ) continue; assert( pVars[v]->nParts > 0 ); if ( pVars[v]->nParts > 1 ) continue; iPart = pVars[v]->bParts->index; if ( pNodes[iPart]->bCube == NULL ) { pNodes[iPart]->bCube = dd->vars[v]; Cudd_Ref( dd->vars[v] ); } else { pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] ); Cudd_Ref( pNodes[iPart]->bCube ); Cudd_RecursiveDeref( dd, bTemp ); } // remove these variables Cudd_RecursiveDeref( dd, pVars[v]->bParts ); ABC_FREE( pVars[v] ); } // assign the leaf node images for ( i = 0; i < nParts; i++ ) { pNode = pNodes[i]; if ( pNode->bCube ) { // update the partition pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube ); Cudd_Ref( pParts[i]->bFunc ); Cudd_RecursiveDeref( dd, bTemp ); // update the support the partition pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); Cudd_Ref( pParts[i]->bSupp ); Cudd_RecursiveDeref( dd, bTemp ); // update the numbers pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); // get rid of the cube // save the last (care set) quantification cube if ( i < nParts - 1 ) { Cudd_RecursiveDeref( dd, pNode->bCube ); pNode->bCube = NULL; } } // copy the function pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage ); } /* for ( i = 0; i < nParts; i++ ) { pNode = pNodes[i]; ABC_PRB( dd, pNode->bCube ); ABC_PRB( dd, pNode->pPart->bFunc ); ABC_PRB( dd, pNode->pPart->bSupp ); printf( "\n" ); } */ return pNodes; } /**Function************************************************************* Synopsis [Delete the partitions from the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ) { Bbr_ImagePart_t * pPart; if ( pNode->pNode1 ) Bbr_DeleteParts_rec( pNode->pNode1 ); if ( pNode->pNode2 ) Bbr_DeleteParts_rec( pNode->pNode2 ); pPart = pNode->pPart; Cudd_RecursiveDeref( pNode->dd, pPart->bFunc ); Cudd_RecursiveDeref( pNode->dd, pPart->bSupp ); ABC_FREE( pNode->pPart ); } /**Function************************************************************* Synopsis [Delete the partitions from the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ) { if ( pNode->pNode1 ) Bbr_bddImageTreeDelete_rec( pNode->pNode1 ); if ( pNode->pNode2 ) Bbr_bddImageTreeDelete_rec( pNode->pNode2 ); if ( pNode->bCube ) Cudd_RecursiveDeref( pNode->dd, pNode->bCube ); if ( pNode->bImage ) Cudd_RecursiveDeref( pNode->dd, pNode->bImage ); assert( pNode->pPart == NULL ); ABC_FREE( pNode ); } /**Function************************************************************* Synopsis [Recompute the image.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ) { DdManager * dd = pNode->dd; DdNode * bTemp; int nNodes; // trivial case if ( pNode->pNode1 == NULL ) { if ( pNode->bCube ) { pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); Cudd_Ref( pNode->bImage ); Cudd_RecursiveDeref( dd, bTemp ); } return 1; } // compute the children if ( pNode->pNode1 ) if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode1 ) ) return 0; if ( pNode->pNode2 ) if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode2 ) ) return 0; // clean the old image if ( pNode->bImage ) Cudd_RecursiveDeref( dd, pNode->bImage ); pNode->bImage = NULL; // compute the new image if ( pNode->bCube ) pNode->bImage = Cudd_bddAndAbstract( dd, pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); else pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); Cudd_Ref( pNode->bImage ); if ( pTree->fVerbose ) { nNodes = Cudd_DagSize( pNode->bImage ); if ( pTree->nNodesMax < nNodes ) pTree->nNodesMax = nNodes; } if ( dd->keys-dd->dead > (unsigned)pTree->nBddMax ) return 0; return 1; } /**Function************************************************************* Synopsis [Builds the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbr_BuildTreeNode( DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes, int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ) { Bbr_ImageNode_t * pNode1, * pNode2; Bbr_ImageVar_t * pVar; Bbr_ImageNode_t * pNode; DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts; int iNode1, iNode2; int iVarBest, nSupp, v; // find the best variable iVarBest = Bbr_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); if ( iVarBest == -1 ) return 0; /* for ( v = 0; v < nVars; v++ ) { DdNode * bSupp; if ( pVars[v] == NULL ) continue; printf( "%3d :", v ); printf( "%3d ", pVars[v]->nParts ); bSupp = Cudd_Support( dd, pVars[v]->bParts ); Cudd_Ref( bSupp ); Bbr_bddPrint( dd, bSupp ); printf( "\n" ); Cudd_RecursiveDeref( dd, bSupp ); } */ pVar = pVars[iVarBest]; // this var cannot appear in one partition only nSupp = Cudd_SupportSize( dd, pVar->bParts ); assert( nSupp == pVar->nParts ); assert( nSupp != 1 ); //printf( "var = %d supp = %d\n\n", iVarBest, nSupp ); // if it appears in only two partitions, quantify it if ( pVar->nParts == 2 ) { // get the nodes iNode1 = pVar->bParts->index; iNode2 = cuddT(pVar->bParts)->index; pNode1 = pNodes[iNode1]; pNode2 = pNodes[iNode2]; // get the quantification cube bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); // add the variables that appear only in these partitions for ( v = 0; v < nVars; v++ ) if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) { // add this var bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); // clean this var Cudd_RecursiveDeref( dd, pVars[v]->bParts ); ABC_FREE( pVars[v] ); } // clean the best var Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); ABC_FREE( pVars[iVarBest] ); // combines two nodes pNode = Bbr_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); Cudd_RecursiveDeref( dd, bCube ); } else // if ( pVar->nParts > 2 ) { // find two smallest BDDs that have this var Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); pNode1 = pNodes[iNode1]; pNode2 = pNodes[iNode2]; //printf( "smallest bdds with this var: %d %d\n", iNode1, iNode2 ); /* // it is not possible that a var appears only in these two // otherwise, it would have a different cost bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); for ( v = 0; v < nVars; v++ ) if ( pVars[v] && pVars[v]->bParts == bParts ) assert( 0 ); Cudd_RecursiveDeref( dd, bParts ); */ // combines two nodes pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 ); } // clean the old nodes pNodes[iNode1] = pNode; pNodes[iNode2] = NULL; //printf( "Removing node %d (leaving node %d)\n", iNode2, iNode1 ); // update the variables that appear in pNode[iNode2] for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) { pVar = pVars[bSuppTemp->index]; if ( pVar == NULL ) // this variable is not be quantified continue; // quantify this var assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); Cudd_RecursiveDeref( dd, bTemp ); // add the new var pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); Cudd_RecursiveDeref( dd, bTemp ); // update the score pVar->nParts = Cudd_SupportSize( dd, pVar->bParts ); } *pfStop = 0; if ( dd->keys-dd->dead > (unsigned)nBddMax ) { *pfStop = 1; return 0; } return 1; } /**Function************************************************************* Synopsis [Merges the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbr_ImageNode_t * Bbr_MergeTopNodes( DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes ) { Bbr_ImageNode_t * pNode; int n1 = -1, n2 = -1, n; // find the first and the second non-empty spots for ( n = 0; n < nNodes; n++ ) if ( pNodes[n] ) { if ( n1 == -1 ) n1 = n; else if ( n2 == -1 ) { n2 = n; break; } } assert( n1 != -1 ); // check the situation when only one such node is detected if ( n2 == -1 ) { // save the node pNode = pNodes[n1]; // clean the node pNodes[n1] = NULL; return pNode; } // combines two nodes pNode = Bbr_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] ); // clean the old nodes pNodes[n1] = pNode; pNodes[n2] = NULL; return NULL; } /**Function************************************************************* Synopsis [Merges two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ) { Bbr_ImageNode_t * pNode; Bbr_ImagePart_t * pPart; // create a new partition pPart = ABC_ALLOC( Bbr_ImagePart_t, 1 ); memset( pPart, 0, sizeof(Bbr_ImagePart_t) ); // create the function pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); // update the support the partition pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube ); Cudd_Ref( pPart->bSupp ); // update the numbers pPart->nSupp = Cudd_SupportSize( dd, pPart->bSupp ); pPart->nNodes = Cudd_DagSize( pPart->bFunc ); pPart->iPart = -1; /* ABC_PRB( dd, pNode1->pPart->bSupp ); ABC_PRB( dd, pNode2->pPart->bSupp ); ABC_PRB( dd, pPart->bSupp ); */ // create a new node pNode = ABC_ALLOC( Bbr_ImageNode_t, 1 ); memset( pNode, 0, sizeof(Bbr_ImageNode_t) ); pNode->dd = dd; pNode->pPart = pPart; pNode->pNode1 = pNode1; pNode->pNode2 = pNode2; // compute the image pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); Cudd_Ref( pNode->bImage ); // save the cube if ( bCube != b1 ) { pNode->bCube = bCube; Cudd_Ref( bCube ); } return pNode; } /**Function************************************************************* Synopsis [Computes the best variable.] Description [The variables is the best if the sum of squares of the BDD sizes of the partitions, in which it participates, is the minimum.] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbr_FindBestVariable( DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes, int nVars, Bbr_ImageVar_t ** pVars ) { DdNode * bTemp; int iVarBest, v; double CostBest, CostCur; CostBest = 100000000000000.0; iVarBest = -1; // check if there are two-variable partitions for ( v = 0; v < nVars; v++ ) if ( pVars[v] && pVars[v]->nParts == 2 ) { CostCur = 0; for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) CostCur += pNodes[bTemp->index]->pPart->nNodes * pNodes[bTemp->index]->pPart->nNodes; if ( CostBest > CostCur ) { CostBest = CostCur; iVarBest = v; } } if ( iVarBest >= 0 ) return iVarBest; // find other partition for ( v = 0; v < nVars; v++ ) if ( pVars[v] ) { assert( pVars[v]->nParts > 1 ); CostCur = 0; for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) CostCur += pNodes[bTemp->index]->pPart->nNodes * pNodes[bTemp->index]->pPart->nNodes; if ( CostBest > CostCur ) { CostBest = CostCur; iVarBest = v; } } return iVarBest; } /**Function************************************************************* Synopsis [Computes two smallest partions that have this var.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, int nNodes, Bbr_ImageNode_t ** pNodes, int * piNode1, int * piNode2 ) { DdNode * bTemp; int iPart1, iPart2; int CostMin1, CostMin2, Cost; // go through the partitions iPart1 = iPart2 = -1; CostMin1 = CostMin2 = 1000000; for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) ) { Cost = pNodes[bTemp->index]->pPart->nNodes; if ( CostMin1 > Cost ) { CostMin2 = CostMin1; iPart2 = iPart1; CostMin1 = Cost; iPart1 = bTemp->index; } else if ( CostMin2 > Cost ) { CostMin2 = Cost; iPart2 = bTemp->index; } } *piNode1 = iPart1; *piNode2 = iPart2; } /**Function************************************************************* Synopsis [Prints the latch dependency matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, // the care set int nParts, DdNode ** pbParts, // the partitions for image computation int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!) { int i; DdNode * bVarsCs, * bVarsNs; bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs ); bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs ); printf( "The latch dependency matrix:\n" ); printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n", nParts, dd->size, nVars ); printf( " : " ); for ( i = 0; i < dd->size; i++ ) printf( "%d", i % 10 ); printf( "\n" ); for ( i = 0; i < nParts; i++ ) Bbr_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i ); Bbr_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts ); Cudd_RecursiveDeref( dd, bVarsCs ); Cudd_RecursiveDeref( dd, bVarsNs ); } /**Function************************************************************* Synopsis [Prints one row of the latch dependency matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, // the function DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars int iPart ) { DdNode * bSupport; int v; bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport ); printf( " %3d : ", iPart ); for ( v = 0; v < dd->size; v++ ) { if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) ) { if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) ) printf( "c" ); else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) printf( "n" ); else printf( "i" ); } else printf( "." ); } printf( "\n" ); Cudd_RecursiveDeref( dd, bSupport ); } /**Function************************************************************* Synopsis [Prints the tree for quenstification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ) { printf( "The quantification scheduling tree:\n" ); Bbr_bddImagePrintTree_rec( pTree->pRoot, 1 ); } /**Function************************************************************* Synopsis [Prints the tree for quenstification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int Offset ) { DdNode * Cube; int i; Cube = pNode->bCube; if ( pNode->pNode1 == NULL ) { printf( "<%d> ", pNode->pPart->iPart ); if ( Cube != NULL ) { ABC_PRB( pNode->dd, Cube ); } else printf( "\n" ); return; } printf( "<*> " ); if ( Cube != NULL ) { ABC_PRB( pNode->dd, Cube ); } else printf( "\n" ); for ( i = 0; i < Offset; i++ ) printf( " " ); Bbr_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 ); for ( i = 0; i < Offset; i++ ) printf( " " ); Bbr_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 ); } /**Function******************************************************************** Synopsis [Computes the positive polarty cube composed of the first vars in the array.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Bbr_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) { DdNode * bRes; DdNode * bTemp; int i; bRes = b1; Cudd_Ref( bRes ); for ( i = 0; i < nVars; i++ ) { bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); return bRes; } struct Bbr_ImageTree2_t_ { DdManager * dd; DdNode * bRel; DdNode * bCube; DdNode * bImage; }; /**Function************************************************************* Synopsis [Starts the monolithic image computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbr_ImageTree2_t * Bbr_bddImageStart2( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars, int fVerbose ) { Bbr_ImageTree2_t * pTree; DdNode * bCubeAll, * bCubeNot, * bTemp; int i; pTree = ABC_ALLOC( Bbr_ImageTree2_t, 1 ); pTree->dd = dd; pTree->bImage = NULL; bCubeAll = Bbr_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); bCubeNot = Bbr_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); Cudd_RecursiveDeref( dd, bCubeAll ); Cudd_RecursiveDeref( dd, bCubeNot ); // derive the monolithic relation pTree->bRel = b1; Cudd_Ref( pTree->bRel ); for ( i = 0; i < nParts; i++ ) { pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); Cudd_RecursiveDeref( dd, bTemp ); } Bbr_bddImageCompute2( pTree, bCare ); return pTree; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ) { if ( pTree->bImage ) Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); Cudd_Ref( pTree->bImage ); return pTree->bImage; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ) { if ( pTree->bRel ) Cudd_RecursiveDeref( pTree->dd, pTree->bRel ); if ( pTree->bCube ) Cudd_RecursiveDeref( pTree->dd, pTree->bCube ); if ( pTree->bImage ) Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); ABC_FREE( pTree ); } /**Function************************************************************* Synopsis [Returns the previously computed image.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ) { return pTree->bImage; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/bbr/bbrNtbdd.c000066400000000000000000000161431300674244400232240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bbrNtbdd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD-based reachability analysis.] Synopsis [Procedures to construct global BDDs for the network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bbrNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bbr.h" //#include "bar.h" ABC_NAMESPACE_IMPL_START typedef char ProgressBar; //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline void Aig_ObjSetGlobalBdd( Aig_Obj_t * pObj, DdNode * bFunc ) { pObj->pData = bFunc; } static inline void Aig_ObjCleanGlobalBdd( DdManager * dd, Aig_Obj_t * pObj ) { Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); pObj->pData = NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the global BDD for one AIG node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Bbr_NodeGlobalBdds_rec( DdManager * dd, Aig_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) { DdNode * bFunc, * bFunc0, * bFunc1; assert( !Aig_IsComplement(pNode) ); if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) { // Extra_ProgressBarStop( pProgress ); if ( fVerbose ) printf( "The number of live nodes reached %d.\n", nBddSizeMax ); fflush( stdout ); return NULL; } // if the result is available return if ( Aig_ObjGlobalBdd(pNode) == NULL ) { // compute the result for both branches bFunc0 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc0 == NULL ) return NULL; Cudd_Ref( bFunc0 ); bFunc1 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin1(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); if ( bFunc1 == NULL ) return NULL; Cudd_Ref( bFunc1 ); bFunc0 = Cudd_NotCond( bFunc0, Aig_ObjFaninC0(pNode) ); bFunc1 = Cudd_NotCond( bFunc1, Aig_ObjFaninC1(pNode) ); // get the final result bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bFunc0 ); Cudd_RecursiveDeref( dd, bFunc1 ); // add the number of used nodes (*pCounter)++; // set the result assert( Aig_ObjGlobalBdd(pNode) == NULL ); Aig_ObjSetGlobalBdd( pNode, bFunc ); // increment the progress bar // if ( pProgress ) // Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); } // prepare the return value bFunc = Aig_ObjGlobalBdd(pNode); // dereference BDD at the node if ( --pNode->nRefs == 0 && fDropInternal ) { Cudd_Deref( bFunc ); Aig_ObjSetGlobalBdd( pNode, NULL ); } return bFunc; } /**Function************************************************************* Synopsis [Frees the global BDDs of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjGlobalBdd(pObj) ) Aig_ObjCleanGlobalBdd( dd, pObj ); } /**Function************************************************************* Synopsis [Returns the shared size of global BDDs of the COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ) { Vec_Ptr_t * vFuncsGlob; Aig_Obj_t * pObj; int RetValue, i; // complement the global functions vFuncsGlob = Vec_PtrAlloc( Aig_ManCoNum(p) ); Aig_ManForEachCo( p, pObj, i ) Vec_PtrPush( vFuncsGlob, Aig_ObjGlobalBdd(pObj) ); RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); Vec_PtrFree( vFuncsGlob ); return RetValue; } /**Function************************************************************* Synopsis [Recursively computes global BDDs for the AIG in the manager.] Description [On exit, BDDs are stored in the pNode->pData fields.] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) { ProgressBar * pProgress = NULL; Aig_Obj_t * pObj; DdManager * dd; DdNode * bFunc; int i, Counter; // start the manager dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // set reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); // prepare to construct global BDDs Aig_ManCleanData( p ); // assign the constant node BDD Aig_ObjSetGlobalBdd( Aig_ManConst1(p), dd->one ); Cudd_Ref( dd->one ); // set the elementary variables Aig_ManForEachCi( p, pObj, i ) { Aig_ObjSetGlobalBdd( pObj, dd->vars[i] ); Cudd_Ref( dd->vars[i] ); } // collect the global functions of the COs Counter = 0; // construct the BDDs // pProgress = Extra_ProgressBarStart( stdout, Aig_ManNodeNum(p) ); Aig_ManForEachCo( p, pObj, i ) { bFunc = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); if ( bFunc == NULL ) { if ( fVerbose ) printf( "Constructing global BDDs is aborted.\n" ); Aig_ManFreeGlobalBdds( p, dd ); Cudd_Quit( dd ); // reset references Aig_ManResetRefs( p ); return NULL; } bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); Aig_ObjSetGlobalBdd( pObj, bFunc ); } // Extra_ProgressBarStop( pProgress ); // reset references Aig_ManResetRefs( p ); // reorder one more time if ( fReorder ) { Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); Cudd_AutodynDisable( dd ); } // Cudd_PrintInfo( dd, stdout ); return dd; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/bbr/bbrReach.c000066400000000000000000000507231300674244400232150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bbrReach.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD-based reachability analysis.] Synopsis [Procedures to perform reachability analysis.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bbrReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bbr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, int iOutput, int fVerbose, int fSilent ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default resynthesis parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ) { memset( p, 0, sizeof(Saig_ParBbr_t) ); p->TimeLimit = 0; p->nBddMax = 50000; p->nIterMax = 1000; p->fPartition = 1; p->fReorder = 1; p->fReorderImage = 1; p->fVerbose = 0; p->fSilent = 0; p->iFrame = -1; } /**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) { DdNode * bTemp, * bProd; int i; assert( iStart <= iStop ); assert( iStart >= 0 && iStart <= dd->size ); assert( iStop >= 0 && iStop <= dd->size ); bProd = (dd)->one; Cudd_Ref( bProd ); for ( i = iStart; i < iStop; i++ ) { bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bProd ); return bProd; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbr_StopManager( DdManager * dd ) { int RetValue; // check for remaining references in the package RetValue = Cudd_CheckZeroRef( dd ); if ( RetValue > 0 ) printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); // Cudd_PrintInfo( dd, stdout ); Cudd_Quit( dd ); } /**Function************************************************************* Synopsis [Computes the initial state and sets up the variable map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Aig_ManInitStateVarMap( DdManager * dd, Aig_Man_t * p, int fVerbose ) { DdNode ** pbVarsX, ** pbVarsY; DdNode * bTemp, * bProd; Aig_Obj_t * pLatch; int i; // set the variable mapping for Cudd_bddVarMap() pbVarsX = ABC_ALLOC( DdNode *, dd->size ); pbVarsY = ABC_ALLOC( DdNode *, dd->size ); bProd = (dd)->one; Cudd_Ref( bProd ); Saig_ManForEachLo( p, pLatch, i ) { pbVarsX[i] = dd->vars[ Saig_ManPiNum(p) + i ]; pbVarsY[i] = dd->vars[ Saig_ManCiNum(p) + i ]; // get the initial value of the latch bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_Not(pbVarsX[i]) ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Saig_ManRegNum(p) ); ABC_FREE( pbVarsX ); ABC_FREE( pbVarsY ); Cudd_Deref( bProd ); return bProd; } /**Function************************************************************* Synopsis [Collects the array of output BDDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode ** Aig_ManCreateOutputs( DdManager * dd, Aig_Man_t * p ) { DdNode ** pbOutputs; Aig_Obj_t * pNode; int i; // compute the transition relation pbOutputs = ABC_ALLOC( DdNode *, Saig_ManPoNum(p) ); Saig_ManForEachPo( p, pNode, i ) { pbOutputs[i] = Aig_ObjGlobalBdd(pNode); Cudd_Ref( pbOutputs[i] ); } return pbOutputs; } /**Function************************************************************* Synopsis [Collects the array of partition BDDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode ** Aig_ManCreatePartitions( DdManager * dd, Aig_Man_t * p, int fReorder, int fVerbose ) { DdNode ** pbParts; DdNode * bVar; Aig_Obj_t * pNode; int i; // extand the BDD manager to represent NS variables assert( dd->size == Saig_ManCiNum(p) ); Cudd_bddIthVar( dd, Saig_ManCiNum(p) + Saig_ManRegNum(p) - 1 ); // enable reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); else Cudd_AutodynDisable( dd ); // compute the transition relation pbParts = ABC_ALLOC( DdNode *, Saig_ManRegNum(p) ); Saig_ManForEachLi( p, pNode, i ) { bVar = Cudd_bddIthVar( dd, Saig_ManCiNum(p) + i ); pbParts[i] = Cudd_bddXnor( dd, bVar, Aig_ObjGlobalBdd(pNode) ); Cudd_Ref( pbParts[i] ); } // free global BDDs Aig_ManFreeGlobalBdds( p, dd ); // reorder and disable reordering if ( fReorder ) { if ( fVerbose ) fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); Cudd_AutodynDisable( dd ); if ( fVerbose ) fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); } return pbParts; } /**Function************************************************************* Synopsis [Computes the set of unreachable states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, DdNode * bInitial, DdNode ** pbOutputs, Saig_ParBbr_t * pPars, int fCheckOutputs ) { int fInternalReorder = 0; Bbr_ImageTree_t * pTree = NULL; // Suppress "might be used uninitialized" Bbr_ImageTree2_t * pTree2 = NULL; // Supprses "might be used uninitialized" DdNode * bReached, * bCubeCs; DdNode * bCurrent; DdNode * bNext = NULL; // Suppress "might be used uninitialized" DdNode * bTemp; Cudd_ReorderingType method; int i, nIters, nBddSize = 0, status; int nThreshold = 10000; abctime clk = Abc_Clock(); Vec_Ptr_t * vOnionRings; int fixedPoint = 0; status = Cudd_ReorderingStatus( dd, &method ); if ( status ) Cudd_AutodynDisable( dd ); // start the image computation bCubeCs = Bbr_bddComputeRangeCube( dd, Saig_ManPiNum(p), Saig_ManCiNum(p) ); Cudd_Ref( bCubeCs ); if ( pPars->fPartition ) pTree = Bbr_bddImageStart( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->nBddMax, pPars->fVerbose ); else pTree2 = Bbr_bddImageStart2( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->fVerbose ); Cudd_RecursiveDeref( dd, bCubeCs ); if ( pTree == NULL ) { if ( !pPars->fSilent ) printf( "BDDs blew up during qualitification scheduling. " ); return -1; } if ( status ) Cudd_AutodynEnable( dd, method ); // start the onion rings vOnionRings = Vec_PtrAlloc( 1000 ); // perform reachability analysis bCurrent = bInitial; Cudd_Ref( bCurrent ); bReached = bInitial; Cudd_Ref( bReached ); Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); for ( nIters = 0; nIters < pPars->nIterMax; nIters++ ) { // check the runtime limit if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC ) { printf( "Reached timeout after image computation (%d seconds).\n", pPars->TimeLimit ); Vec_PtrFree( vOnionRings ); // undo the image tree if ( pPars->fPartition ) Bbr_bddImageTreeDelete( pTree ); else Bbr_bddImageTreeDelete2( pTree2 ); pPars->iFrame = nIters - 1; return -1; } // compute the next states if ( pPars->fPartition ) bNext = Bbr_bddImageCompute( pTree, bCurrent ); else bNext = Bbr_bddImageCompute2( pTree2, bCurrent ); if ( bNext == NULL ) { if ( !pPars->fSilent ) printf( "BDDs blew up during image computation. " ); if ( pPars->fPartition ) Bbr_bddImageTreeDelete( pTree ); else Bbr_bddImageTreeDelete2( pTree2 ); Vec_PtrFree( vOnionRings ); pPars->iFrame = nIters - 1; return -1; } Cudd_Ref( bNext ); Cudd_RecursiveDeref( dd, bCurrent ); // remap these states into the current state vars bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); Cudd_RecursiveDeref( dd, bTemp ); // check if there are any new states if ( Cudd_bddLeq( dd, bNext, bReached ) ) { fixedPoint = 1; break; } // check the BDD size nBddSize = Cudd_DagSize(bNext); if ( nBddSize > pPars->nBddMax ) break; // check the result for ( i = 0; i < Saig_ManPoNum(p); i++ ) { if ( fCheckOutputs && !Cudd_bddLeq( dd, bNext, Cudd_Not(pbOutputs[i]) ) ) { DdNode * bIntersect; bIntersect = Cudd_bddIntersect( dd, bNext, pbOutputs[i] ); Cudd_Ref( bIntersect ); assert( p->pSeqModel == NULL ); p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); Cudd_RecursiveDeref( dd, bIntersect ); if ( !pPars->fSilent ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, Vec_PtrSize(vOnionRings) ); Cudd_RecursiveDeref( dd, bReached ); bReached = NULL; pPars->iFrame = nIters; break; } } if ( i < Saig_ManPoNum(p) ) break; // get the new states bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); // minimize the new states with the reached states // bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); // Cudd_RecursiveDeref( dd, bTemp ); // add to the reached states bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bNext ); if ( pPars->fVerbose ) fprintf( stdout, "Frame = %3d. BDD = %5d. ", nIters, nBddSize ); if ( fInternalReorder && pPars->fReorder && nBddSize > nThreshold ) { if ( pPars->fVerbose ) fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); Cudd_AutodynDisable( dd ); if ( pPars->fVerbose ) fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) ); nThreshold *= 2; } if ( pPars->fVerbose ) // fprintf( stdout, "\r" ); fprintf( stdout, "\n" ); if ( pPars->fVerbose ) { double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); // Extra_bddPrint( dd, bReached );printf( "\n" ); fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); fflush( stdout ); } } Cudd_RecursiveDeref( dd, bNext ); // free the onion rings Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) Cudd_RecursiveDeref( dd, bTemp ); Vec_PtrFree( vOnionRings ); // undo the image tree if ( pPars->fPartition ) Bbr_bddImageTreeDelete( pTree ); else Bbr_bddImageTreeDelete2( pTree2 ); if ( bReached == NULL ) return 0; // proved reachable // report the stats if ( pPars->fVerbose ) { double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax ) fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); else fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); fflush( stdout ); } //ABC_PRB( dd, bReached ); Cudd_RecursiveDeref( dd, bReached ); // SPG // if ( fixedPoint ) { if ( !pPars->fSilent ) { printf( "The miter is proved unreachable after %d iterations. ", nIters ); } pPars->iFrame = nIters - 1; return 1; } assert(nIters >= pPars->nIterMax || nBddSize >= pPars->nBddMax); if ( !pPars->fSilent ) printf( "Verified only for states reachable in %d frames. ", nIters ); pPars->iFrame = nIters - 1; return -1; // undecided } /**Function************************************************************* Synopsis [Performs reachability to see if any PO can be asserted.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManVerifyUsingBdds_int( Aig_Man_t * p, Saig_ParBbr_t * pPars ) { int fCheckOutputs = !pPars->fSkipOutCheck; DdManager * dd; DdNode ** pbParts, ** pbOutputs; DdNode * bInitial, * bTemp; int RetValue, i; abctime clk = Abc_Clock(); Vec_Ptr_t * vOnionRings; assert( Saig_ManRegNum(p) > 0 ); // compute the global BDDs of the latches dd = Aig_ManComputeGlobalBdds( p, pPars->nBddMax, 1, pPars->fReorder, pPars->fVerbose ); if ( dd == NULL ) { if ( !pPars->fSilent ) printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", pPars->nBddMax ); return -1; } if ( pPars->fVerbose ) printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); // check the runtime limit if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC ) { printf( "Reached timeout after constructing global BDDs (%d seconds).\n", pPars->TimeLimit ); Cudd_Quit( dd ); return -1; } // start the onion rings vOnionRings = Vec_PtrAlloc( 1000 ); // save outputs pbOutputs = Aig_ManCreateOutputs( dd, p ); // create partitions pbParts = Aig_ManCreatePartitions( dd, p, pPars->fReorder, pPars->fVerbose ); // create the initial state and the variable map bInitial = Aig_ManInitStateVarMap( dd, p, pPars->fVerbose ); Cudd_Ref( bInitial ); // set reordering if ( pPars->fReorderImage ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); // check the result RetValue = -1; for ( i = 0; i < Saig_ManPoNum(p); i++ ) { if ( fCheckOutputs && !Cudd_bddLeq( dd, bInitial, Cudd_Not(pbOutputs[i]) ) ) { DdNode * bIntersect; bIntersect = Cudd_bddIntersect( dd, bInitial, pbOutputs[i] ); Cudd_Ref( bIntersect ); assert( p->pSeqModel == NULL ); p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); Cudd_RecursiveDeref( dd, bIntersect ); if ( !pPars->fSilent ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, -1 ); RetValue = 0; break; } } // free the onion rings Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) Cudd_RecursiveDeref( dd, bTemp ); Vec_PtrFree( vOnionRings ); // explore reachable states if ( RetValue == -1 ) RetValue = Aig_ManComputeReachable( dd, p, pbParts, bInitial, pbOutputs, pPars, fCheckOutputs ); // cleanup Cudd_RecursiveDeref( dd, bInitial ); for ( i = 0; i < Saig_ManRegNum(p); i++ ) Cudd_RecursiveDeref( dd, pbParts[i] ); ABC_FREE( pbParts ); for ( i = 0; i < Saig_ManPoNum(p); i++ ) Cudd_RecursiveDeref( dd, pbOutputs[i] ); ABC_FREE( pbOutputs ); // if ( RetValue == -1 ) Cudd_Quit( dd ); // else // Bbr_StopManager( dd ); // report the runtime if ( !pPars->fSilent ) { ABC_PRT( "Time", Abc_Clock() - clk ); fflush( stdout ); } return RetValue; } /**Function************************************************************* Synopsis [Performs reachability to see if any PO can be asserted.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars ) { Abc_Cex_t * pCexOld, * pCexNew; Aig_Man_t * p; Aig_Obj_t * pObj; Vec_Int_t * vInputMap; int i, k, Entry, iBitOld, iBitNew, RetValue; // pPars->fVerbose = 1; // check if there are PIs without fanout Saig_ManForEachPi( pInit, pObj, i ) if ( Aig_ObjRefs(pObj) == 0 ) break; if ( i == Saig_ManPiNum(pInit) ) return Aig_ManVerifyUsingBdds_int( pInit, pPars ); // create new AIG p = Aig_ManDupTrim( pInit ); assert( Aig_ManCiNum(p) < Aig_ManCiNum(pInit) ); assert( Aig_ManRegNum(p) == Aig_ManRegNum(pInit) ); RetValue = Aig_ManVerifyUsingBdds_int( p, pPars ); if ( RetValue != 0 ) { Aig_ManStop( p ); return RetValue; } // the problem is satisfiable - remap the pattern pCexOld = p->pSeqModel; assert( pCexOld != NULL ); // create input map vInputMap = Vec_IntAlloc( Saig_ManPiNum(pInit) ); Saig_ManForEachPi( pInit, pObj, i ) if ( pObj->pData != NULL ) Vec_IntPush( vInputMap, Aig_ObjCioId((Aig_Obj_t *)pObj->pData) ); else Vec_IntPush( vInputMap, -1 ); // create new pattern pCexNew = Abc_CexAlloc( Saig_ManRegNum(pInit), Saig_ManPiNum(pInit), pCexOld->iFrame+1 ); pCexNew->iFrame = pCexOld->iFrame; pCexNew->iPo = pCexOld->iPo; // copy the bit-data for ( iBitOld = 0; iBitOld < pCexOld->nRegs; iBitOld++ ) if ( Abc_InfoHasBit( pCexOld->pData, iBitOld ) ) Abc_InfoSetBit( pCexNew->pData, iBitOld ); // copy the primary input data iBitNew = iBitOld; for ( i = 0; i <= pCexNew->iFrame; i++ ) { Vec_IntForEachEntry( vInputMap, Entry, k ) { if ( Entry == -1 ) continue; if ( Abc_InfoHasBit( pCexOld->pData, iBitOld + Entry ) ) Abc_InfoSetBit( pCexNew->pData, iBitNew + k ); } iBitOld += Saig_ManPiNum(p); iBitNew += Saig_ManPiNum(pInit); } assert( iBitOld < iBitNew ); assert( iBitOld == pCexOld->nBits ); assert( iBitNew == pCexNew->nBits ); Vec_IntFree( vInputMap ); pInit->pSeqModel = pCexNew; Aig_ManStop( p ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/bbr/bbr_.c000066400000000000000000000026071300674244400224070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "__Int.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/bbr/module.make000066400000000000000000000001521300674244400234540ustar00rootroot00000000000000SRC += src/bdd/bbr/bbrCex.c \ src/bdd/bbr/bbrImage.c \ src/bdd/bbr/bbrNtbdd.c \ src/bdd/bbr/bbrReach.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cas/000077500000000000000000000000001300674244400213335ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cas/cas.h000066400000000000000000000040751300674244400222600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cas.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cas.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__bdd__cas__cas_h #define ABC__bdd__cas__cas_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define MAXINPUTS 1024 #define MAXOUTPUTS 1024 //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== zzz.c ==========================================================*/ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cas/casCore.c000066400000000000000000001213611300674244400230620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [casCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] Synopsis [Entrance into the implementation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Spring 2002.] Revision [$Id: casCore.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include "base/main/main.h" #include "base/cmd/cmd.h" #include "bdd/extrab/extraBdd.h" #include "cas.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// static functions /// //////////////////////////////////////////////////////////////////////// DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose ); DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ); DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew ); extern int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose ); void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName ); DdNode * Cudd_bddTransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); //////////////////////////////////////////////////////////////////////// /// static varibles /// //////////////////////////////////////////////////////////////////////// //static FILE * pTable = NULL; //static long s_RemappingTime = 0; //////////////////////////////////////////////////////////////////////// /// debugging macros /// //////////////////////////////////////////////////////////////////////// #define PRD(p) printf( "\nDECOMPOSITION TREE:\n\n" ); PrintDecEntry( (p), 0 ) #define PRB_(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" ) #define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" ) #define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) //////////////////////////////////////////////////////////////////////// /// EXTERNAL FUNCTIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose ) { int i; int nVars = nInputs; int nOuts = nOutputs; abctime clk1; int nVarsEnc; // the number of additional variables to encode outputs DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars int nNames; // the total number of all inputs char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs char FileNameIni[100]; char FileNameFin[100]; char Buffer[100]; //pTable = fopen( "stats.txt", "a+" ); //fprintf( pTable, "%s ", pFileGeneric ); //fprintf( pTable, "%d ", nVars ); //fprintf( pTable, "%d ", nOuts ); // assign the file names strcpy( FileNameIni, pFileGeneric ); strcat( FileNameIni, "_ENC.blif" ); strcpy( FileNameFin, pFileGeneric ); strcat( FileNameFin, "_LUT.blif" ); // create the variables to encode the outputs nVarsEnc = Abc_Base2Log( nOuts ); for ( i = 0; i < nVarsEnc; i++ ) pbVarsEnc[i] = Cudd_bddNewVarAtLevel( dd, i ); // store the input names nNames = nVars + nVarsEnc; for ( i = 0; i < nVars; i++ ) { // pNames[i] = Extra_UtilStrsav( pFunc->pInputNames[i] ); sprintf( Buffer, "pi%03d", i ); pNames[i] = Extra_UtilStrsav( Buffer ); } // set the encoding variable name for ( ; i < nNames; i++ ) { sprintf( Buffer, "OutEnc_%02d", i-nVars ); pNames[i] = Extra_UtilStrsav( Buffer ); } // print the variable order // printf( "\n" ); // printf( "Variable order is: " ); // for ( i = 0; i < dd->size; i++ ) // printf( " %d", dd->invperm[i] ); // printf( "\n" ); // derive the single-output function clk1 = Abc_Clock(); aFunc = GetSingleOutputFunction( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc, fVerbose ); Cudd_Ref( aFunc ); // aFunc = GetSingleOutputFunctionRemapped( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc ); // if ( fVerbose ) // printf( "Single-output function computation time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); //fprintf( pTable, "%d ", Cudd_SharingSize( pOutputs, nOutputs ) ); //fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pOutputs, nOutputs) ); // dispose of the multiple-output function // Extra_Dissolve( pFunc ); // reorder the single output function // if ( fVerbose ) // printf( "Reordering variables...\n"); clk1 = Abc_Clock(); // if ( fVerbose ) // printf( "Node count before = %6d\n", Cudd_DagSize( aFunc ) ); // Cudd_ReduceHeap(dd, CUDD_REORDER_SIFT,1); Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); // Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); // Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); // Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); // Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); if ( fVerbose ) printf( "MTBDD reordered = %6d nodes\n", Cudd_DagSize( aFunc ) ); if ( fVerbose ) printf( "Variable reordering time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); // printf( "\n" ); // printf( "Variable order is: " ); // for ( i = 0; i < dd->size; i++ ) // printf( " %d", dd->invperm[i] ); // printf( "\n" ); //fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) ); //fprintf( pTable, "%d ", Extra_ProfileWidthMax(dd, aFunc) ); // write the single-output function into BLIF for verification clk1 = Abc_Clock(); if ( fCheck ) WriteSingleOutputFunctionBlif( dd, aFunc, pNames, nNames, FileNameIni ); // if ( fVerbose ) // printf( "Single-output function writing time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); /* /////////////////////////////////////////////////////////////////// // verification of single output function clk1 = Abc_Clock(); { BFunc g_Func; DdNode * aRes; g_Func.dd = dd; g_Func.FileInput = Extra_UtilStrsav(FileNameIni); if ( Extra_ReadFile( &g_Func ) == 0 ) { printf( "\nSomething did not work out while reading the input file for verification\n"); Extra_Dissolve( &g_Func ); return; } aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); if ( aRes != aFunc ) printf( "\nVerification FAILED!\n"); else printf( "\nVerification okay!\n"); Cudd_RecursiveDeref( dd, aRes ); // delocate Extra_Dissolve( &g_Func ); } printf( "Preliminary verification time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); /////////////////////////////////////////////////////////////////// */ if ( !CreateDecomposedNetwork( dd, aFunc, pNames, nNames, FileNameFin, nLutSize, fCheck, fVerbose ) ) return 0; /* /////////////////////////////////////////////////////////////////// // verification of the decomposed LUT network clk1 = Abc_Clock(); { BFunc g_Func; DdNode * aRes; g_Func.dd = dd; g_Func.FileInput = Extra_UtilStrsav(FileNameFin); if ( Extra_ReadFile( &g_Func ) == 0 ) { printf( "\nSomething did not work out while reading the input file for verification\n"); Extra_Dissolve( &g_Func ); return; } aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); if ( aRes != aFunc ) printf( "\nFinal verification FAILED!\n"); else printf( "\nFinal verification okay!\n"); Cudd_RecursiveDeref( dd, aRes ); // delocate Extra_Dissolve( &g_Func ); } printf( "Final verification time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); /////////////////////////////////////////////////////////////////// */ // verify the results if ( fCheck ) { char Command[200]; sprintf( Command, "cec %s %s", FileNameIni, FileNameFin ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); } Cudd_RecursiveDeref( dd, aFunc ); // release the names for ( i = 0; i < nNames; i++ ) ABC_FREE( pNames[i] ); //fprintf( pTable, "\n" ); //fclose( pTable ); return 1; } #if 0 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Experiment2( BFunc * pFunc ) { int i, x, RetValue; int nVars = pFunc->nInputs; int nOuts = pFunc->nOutputs; DdManager * dd = pFunc->dd; long clk1; // int nVarsEnc; // the number of additional variables to encode outputs // DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars int nNames; // the total number of all inputs char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs char FileNameIni[100]; char FileNameFin[100]; char Buffer[100]; DdManager * DdNew; //pTable = fopen( "stats.txt", "a+" ); //fprintf( pTable, "%s ", pFunc->FileGeneric ); //fprintf( pTable, "%d ", nVars ); //fprintf( pTable, "%d ", nOuts ); // assign the file names strcpy( FileNameIni, pFunc->FileGeneric ); strcat( FileNameIni, "_ENC.blif" ); strcpy( FileNameFin, pFunc->FileGeneric ); strcat( FileNameFin, "_LUT.blif" ); // derive the single-output function IN THE NEW MANAGER clk1 = Abc_Clock(); // aFunc = GetSingleOutputFunction( dd, pFunc->pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc ); aFunc = GetSingleOutputFunctionRemappedNewDD( dd, pFunc->pOutputs, nOuts, &DdNew ); Cudd_Ref( aFunc ); printf( "Single-output function derivation time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); // s_RemappingTime = Abc_Clock() - clk1; // dispose of the multiple-output function Extra_Dissolve( pFunc ); // reorder the single output function printf( "\nReordering variables in the new manager...\n"); clk1 = Abc_Clock(); printf( "Node count before = %d\n", Cudd_DagSize( aFunc ) ); // Cudd_ReduceHeap(DdNew, CUDD_REORDER_SIFT,1); Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1); // Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1); printf( "Node count after = %d\n", Cudd_DagSize( aFunc ) ); printf( "Variable reordering time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); printf( "\n" ); //fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) ); //fprintf( pTable, "%d ", Extra_ProfileWidthMax(DdNew, aFunc) ); // create the names to be used with the new manager nNames = DdNew->size; for ( x = 0; x < nNames; x++ ) { sprintf( Buffer, "v%02d", x ); pNames[x] = Extra_UtilStrsav( Buffer ); } // write the single-output function into BLIF for verification clk1 = Abc_Clock(); WriteSingleOutputFunctionBlif( DdNew, aFunc, pNames, nNames, FileNameIni ); printf( "Single-output function writing time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); /////////////////////////////////////////////////////////////////// // verification of single output function clk1 = Abc_Clock(); { BFunc g_Func; DdNode * aRes; g_Func.dd = DdNew; g_Func.FileInput = Extra_UtilStrsav(FileNameIni); if ( Extra_ReadFile( &g_Func ) == 0 ) { printf( "\nSomething did not work out while reading the input file for verification\n"); Extra_Dissolve( &g_Func ); return; } aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); if ( aRes != aFunc ) printf( "\nVerification FAILED!\n"); else printf( "\nVerification okay!\n"); Cudd_RecursiveDeref( DdNew, aRes ); // delocate Extra_Dissolve( &g_Func ); } printf( "Preliminary verification time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); /////////////////////////////////////////////////////////////////// CreateDecomposedNetwork( DdNew, aFunc, pNames, nNames, FileNameFin, nLutSize, 0 ); /* /////////////////////////////////////////////////////////////////// // verification of the decomposed LUT network clk1 = Abc_Clock(); { BFunc g_Func; DdNode * aRes; g_Func.dd = DdNew; g_Func.FileInput = Extra_UtilStrsav(FileNameFin); if ( Extra_ReadFile( &g_Func ) == 0 ) { printf( "\nSomething did not work out while reading the input file for verification\n"); Extra_Dissolve( &g_Func ); return; } aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); if ( aRes != aFunc ) printf( "\nFinal verification FAILED!\n"); else printf( "\nFinal verification okay!\n"); Cudd_RecursiveDeref( DdNew, aRes ); // delocate Extra_Dissolve( &g_Func ); } printf( "Final verification time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); /////////////////////////////////////////////////////////////////// */ Cudd_RecursiveDeref( DdNew, aFunc ); // release the names for ( i = 0; i < nNames; i++ ) ABC_FREE( pNames[i] ); ///////////////////////////////////////////////////////////////////// // check for remaining references in the package RetValue = Cudd_CheckZeroRef( DdNew ); printf( "\nThe number of referenced nodes in the new manager = %d\n", RetValue ); Cudd_Quit( DdNew ); //fprintf( pTable, "\n" ); //fclose( pTable ); } #endif //////////////////////////////////////////////////////////////////////// /// SINGLE OUTPUT FUNCTION /// //////////////////////////////////////////////////////////////////////// // the bit count for the first 256 integer numbers //static unsigned char BitCount8[256] = { // 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, // 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, // 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, // 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, // 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, // 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, // 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, // 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 //}; ///////////////////////////////////////////////////////////// static int s_SuppSize[MAXOUTPUTS]; int CompareSupports( int *ptrX, int *ptrY ) { return ( s_SuppSize[*ptrY] - s_SuppSize[*ptrX] ); } ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// static int s_MintOnes[MAXOUTPUTS]; int CompareMinterms( int *ptrX, int *ptrY ) { return ( s_MintOnes[*ptrY] - s_MintOnes[*ptrX] ); } ///////////////////////////////////////////////////////////// int GrayCode ( int BinCode ) { return BinCode ^ ( BinCode >> 1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose ) { int i; DdNode * bResult, * aResult; DdNode * bCube, * bTemp, * bProd; int Order[MAXOUTPUTS]; // int OrderMint[MAXOUTPUTS]; // sort the output according to their support size for ( i = 0; i < nOuts; i++ ) { s_SuppSize[i] = Cudd_SupportSize( dd, pbOuts[i] ); // s_MintOnes[i] = BitCount8[i]; Order[i] = i; // OrderMint[i] = i; } // order the outputs qsort( (void*)Order, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareSupports ); // order the outputs // qsort( (void*)OrderMint, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareMinterms ); bResult = b0; Cudd_Ref( bResult ); for ( i = 0; i < nOuts; i++ ) { // bCube = Cudd_bddBitsToCube( dd, OrderMint[i], nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); // bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[nOuts-1-i]] ); Cudd_Ref( bProd ); bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc, 1 ); Cudd_Ref( bCube ); bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[i]] ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bCube ); bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } // convert to the ADD if ( fVerbose ) printf( "Single BDD size = %6d nodes\n", Cudd_DagSize(bResult) ); aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult ); Cudd_RecursiveDeref( dd, bResult ); if ( fVerbose ) printf( "MTBDD = %6d nodes\n", Cudd_DagSize(aResult) ); Cudd_Deref( aResult ); return aResult; } /* DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ) { int i; DdNode * bResult, * aResult; DdNode * bCube, * bTemp, * bProd; bResult = b0; Cudd_Ref( bResult ); for ( i = 0; i < nOuts; i++ ) { // bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); bCube = Extra_bddBitsToCube( dd, nOuts-1-i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); bProd = Cudd_bddAnd( dd, bCube, pbOuts[i] ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bCube ); bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } // conver to the ADD aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult ); Cudd_RecursiveDeref( dd, bResult ); Cudd_Deref( aResult ); return aResult; } */ //////////////////////////////////////////////////////////////////////// /// INPUT REMAPPING /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ) // returns the ADD of the remapped function { static int Permute[MAXINPUTS]; static DdNode * pRemapped[MAXOUTPUTS]; DdNode * bSupp, * bTemp; int i, Counter; DdNode * bFunc; DdNode * aFunc; Cudd_AutodynDisable(dd); // perform the remapping for ( i = 0; i < nOuts; i++ ) { // get support bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp ); // create the variable map Counter = 0; for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) Permute[bTemp->index] = Counter++; // transfer the BDD and remap it pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] ); // remove support Cudd_RecursiveDeref( dd, bSupp ); } // perform the encoding bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc ); // convert to ADD aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); Cudd_RecursiveDeref( dd, bFunc ); // deref the intermediate results for ( i = 0; i < nOuts; i++ ) Cudd_RecursiveDeref( dd, pRemapped[i] ); Cudd_Deref( aFunc ); return aFunc; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew ) // returns the ADD of the remapped function { static int Permute[MAXINPUTS]; static DdNode * pRemapped[MAXOUTPUTS]; static DdNode * pbVarsEnc[MAXINPUTS]; int nVarsEnc; DdManager * ddnew; DdNode * bSupp, * bTemp; int i, v, Counter; DdNode * bFunc; // these are in the new manager DdNode * bFuncNew; DdNode * aFuncNew; int nVarsMax = 0; // perform the remapping and write the DDs into the new manager for ( i = 0; i < nOuts; i++ ) { // get support bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp ); // create the variable map // to remap the DD into the upper part of the manager Counter = 0; for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) Permute[bTemp->index] = dd->invperm[Counter++]; // transfer the BDD and remap it pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] ); // remove support Cudd_RecursiveDeref( dd, bSupp ); // determine the largest support size if ( nVarsMax < Counter ) nVarsMax = Counter; } // select the encoding variables to follow immediately after the original variables nVarsEnc = Abc_Base2Log(nOuts); /* for ( v = 0; v < nVarsEnc; v++ ) if ( nVarsMax + v < dd->size ) pbVarsEnc[v] = dd->var[ dd->invperm[nVarsMax+v] ]; else pbVarsEnc[v] = Cudd_bddNewVar( dd ); */ // create the new variables on top of the manager for ( v = 0; v < nVarsEnc; v++ ) pbVarsEnc[v] = Cudd_bddNewVarAtLevel( dd, v ); //fprintf( pTable, "%d ", Cudd_SharingSize( pRemapped, nOuts ) ); //fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pRemapped, nOuts) ); // perform the encoding bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc ); // find the cross-manager permutation // the variable from the level v in the old manager // should become a variable number v in the new manager for ( v = 0; v < nVarsMax + nVarsEnc; v++ ) Permute[dd->invperm[v]] = v; /////////////////////////////////////////////////////////////////////////////// // start the new manager ddnew = Cudd_Init( nVarsMax + nVarsEnc, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); // Cudd_AutodynDisable(ddnew); Cudd_AutodynEnable(dd, CUDD_REORDER_SYMM_SIFT); // transfer it to the new manager bFuncNew = Cudd_bddTransferPermute( dd, ddnew, bFunc, Permute ); Cudd_Ref( bFuncNew ); /////////////////////////////////////////////////////////////////////////////// // deref the intermediate results in the old manager Cudd_RecursiveDeref( dd, bFunc ); for ( i = 0; i < nOuts; i++ ) Cudd_RecursiveDeref( dd, pRemapped[i] ); /////////////////////////////////////////////////////////////////////////////// // convert to ADD in the new manager aFuncNew = Cudd_BddToAdd( ddnew, bFuncNew ); Cudd_Ref( aFuncNew ); Cudd_RecursiveDeref( ddnew, bFuncNew ); // return the manager *DdNew = ddnew; /////////////////////////////////////////////////////////////////////////////// Cudd_Deref( aFuncNew ); return aFuncNew; } //////////////////////////////////////////////////////////////////////// /// BLIF WRITING FUNCTIONS /// //////////////////////////////////////////////////////////////////////// void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName ) { int i; FILE * pFile; // start the file pFile = fopen( FileName, "w" ); fprintf( pFile, ".model %s\n", FileName ); fprintf( pFile, ".inputs" ); for ( i = 0; i < nNames; i++ ) fprintf( pFile, " %s", pNames[i] ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs F" ); fprintf( pFile, "\n" ); // write the DD into the file WriteDDintoBLIFfile( pFile, aFunc, "F", "", pNames ); fprintf( pFile, ".end\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ) // writes the main part of the BLIF file // Func is a BDD or a 0-1 ADD to be written // OutputName is the name of the output // Prefix is attached to each intermendiate signal to make it unique // InputNames are the names of the input signals // (some part of the code is borrowed from Cudd_DumpDot()) { int i; st__table * visited; st__generator * gen = NULL; long refAddr, diff, mask; DdNode * Node, * Else, * ElseR, * Then; /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash ); /* Collect all the nodes of this DD in the symbol table. */ cuddCollectNodes( Cudd_Regular(Func), visited ); /* Find how many most significant hex digits are identical ** in the addresses of all the nodes. Build a mask based ** on this knowledge, so that digits that carry no information ** will not be printed. This is done in two steps. ** 1. We scan the symbol table to find the bits that differ ** in at least 2 addresses. ** 2. We choose one of the possible masks. There are 8 possible ** masks for 32-bit integer, and 16 possible masks for 64-bit ** integers. */ /* Find the bits that are different. */ refAddr = ( long )Cudd_Regular(Func); diff = 0; gen = st__init_gen( visited ); while ( st__gen( gen, ( const char ** ) &Node, NULL ) ) { diff |= refAddr ^ ( long ) Node; } st__free_gen( gen ); gen = NULL; /* Choose the mask. */ for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 ) { mask = ( 1 << i ) - 1; if ( diff <= mask ) break; } // write the buffer for the output fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(Func) ) / sizeof(DdNode), OutputName ); fprintf( pFile, "%s 1\n", (Cudd_IsComplement(Func))? "0": "1" ); gen = st__init_gen( visited ); while ( st__gen( gen, ( const char ** ) &Node, NULL ) ) { if ( Node->index == CUDD_MAXINDEX ) { // write the terminal node fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" ); continue; } Else = cuddE(Node); ElseR = Cudd_Regular(Else); Then = cuddT(Node); assert( InputNames[Node->index] ); if ( Else == ElseR ) { // no inverter fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index], Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), Prefix, ( mask & (long)Then ) / sizeof(DdNode), Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); fprintf( pFile, "01- 1\n" ); fprintf( pFile, "1-1 1\n" ); } else { // inverter int * pSlot; fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index], Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), Prefix, ( mask & (long)Then ) / sizeof(DdNode), Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); fprintf( pFile, "01- 1\n" ); fprintf( pFile, "1-1 1\n" ); // if the inverter is written, skip if ( ! st__find( visited, (char *)ElseR, (char ***)&pSlot ) ) assert( 0 ); if ( *pSlot ) continue; *pSlot = 1; fprintf( pFile, ".names %s%lx %s%lx_i\n", Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) ); fprintf( pFile, "0 1\n" ); } } st__free_gen( gen ); gen = NULL; st__free_table( visited ); } static DdManager * s_ddmin; /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ) // writes the main part of the BLIF file // Func is a BDD or a 0-1 ADD to be written // OutputName is the name of the output // Prefix is attached to each intermendiate signal to make it unique // InputNames are the names of the input signals // (some part of the code is borrowed from Cudd_DumpDot()) { int i; st__table * visited; st__generator * gen = NULL; long refAddr, diff, mask; DdNode * Node, * Else, * ElseR, * Then; /////////////////////////////////////////////////////////////// DdNode * bFmin; abctime clk1; if ( s_ddmin == NULL ) s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); clk1 = Abc_Clock(); bFmin = Cudd_bddTransfer( dd, s_ddmin, Func ); Cudd_Ref( bFmin ); // reorder printf( "Nodes before = %d. ", Cudd_DagSize(bFmin) ); Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); // Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT_CONV,1); printf( "Nodes after = %d. \n", Cudd_DagSize(bFmin) ); /////////////////////////////////////////////////////////////// /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash ); /* Collect all the nodes of this DD in the symbol table. */ cuddCollectNodes( Cudd_Regular(bFmin), visited ); /* Find how many most significant hex digits are identical ** in the addresses of all the nodes. Build a mask based ** on this knowledge, so that digits that carry no information ** will not be printed. This is done in two steps. ** 1. We scan the symbol table to find the bits that differ ** in at least 2 addresses. ** 2. We choose one of the possible masks. There are 8 possible ** masks for 32-bit integer, and 16 possible masks for 64-bit ** integers. */ /* Find the bits that are different. */ refAddr = ( long )Cudd_Regular(bFmin); diff = 0; gen = st__init_gen( visited ); while ( st__gen( gen, ( const char ** ) &Node, NULL ) ) { diff |= refAddr ^ ( long ) Node; } st__free_gen( gen ); gen = NULL; /* Choose the mask. */ for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 ) { mask = ( 1 << i ) - 1; if ( diff <= mask ) break; } // write the buffer for the output fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(bFmin) ) / sizeof(DdNode), OutputName ); fprintf( pFile, "%s 1\n", (Cudd_IsComplement(bFmin))? "0": "1" ); gen = st__init_gen( visited ); while ( st__gen( gen, ( const char ** ) &Node, NULL ) ) { if ( Node->index == CUDD_MAXINDEX ) { // write the terminal node fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" ); continue; } Else = cuddE(Node); ElseR = Cudd_Regular(Else); Then = cuddT(Node); assert( InputNames[Node->index] ); if ( Else == ElseR ) { // no inverter fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index], Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), Prefix, ( mask & (long)Then ) / sizeof(DdNode), Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); fprintf( pFile, "01- 1\n" ); fprintf( pFile, "1-1 1\n" ); } else { // inverter fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index], Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), Prefix, ( mask & (long)Then ) / sizeof(DdNode), Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); fprintf( pFile, "01- 1\n" ); fprintf( pFile, "1-1 1\n" ); fprintf( pFile, ".names %s%lx %s%lx_i\n", Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) ); fprintf( pFile, "0 1\n" ); } } st__free_gen( gen ); gen = NULL; st__free_table( visited ); ////////////////////////////////////////////////// Cudd_RecursiveDeref( s_ddmin, bFmin ); ////////////////////////////////////////////////// } //////////////////////////////////////////////////////////////////////// /// TRANSFER WITH MAPPING /// //////////////////////////////////////////////////////////////////////// static DdNode * cuddBddTransferPermuteRecur ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute )); static DdNode * cuddBddTransferPermute ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute)); /**Function******************************************************************** Synopsis [Convert a BDD from a manager to another one.] Description [Convert a BDD from a manager to another one. The orders of the variables in the two managers may be different. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise. The i-th entry in the array Permute tells what is the index of the i-th variable from the old manager in the new manager.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_bddTransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ) { DdNode *res; do { ddDestination->reordered = 0; res = cuddBddTransferPermute( ddSource, ddDestination, f, Permute ); } while ( ddDestination->reordered == 1 ); return ( res ); } /* end of Cudd_bddTransferPermute */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Convert a BDD from a manager to another one.] Description [Convert a BDD from a manager to another one. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddTransferPermute] ******************************************************************************/ DdNode * cuddBddTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) { DdNode *res; st__table *table = NULL; st__generator *gen = NULL; DdNode *key, *value; table = st__init_table( st__ptrcmp, st__ptrhash ); if ( table == NULL ) goto failure; res = cuddBddTransferPermuteRecur( ddS, ddD, f, table, Permute ); if ( res != NULL ) cuddRef( res ); /* Dereference all elements in the table and dispose of the table. ** This must be done also if res is NULL to avoid leaks in case of ** reordering. */ gen = st__init_gen( table ); if ( gen == NULL ) goto failure; while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) ) { Cudd_RecursiveDeref( ddD, value ); } st__free_gen( gen ); gen = NULL; st__free_table( table ); table = NULL; if ( res != NULL ) cuddDeref( res ); return ( res ); failure: if ( table != NULL ) st__free_table( table ); if ( gen != NULL ) st__free_gen( gen ); return ( NULL ); } /* end of cuddBddTransferPermute */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddTransferPermute.] Description [Performs the recursive step of Cudd_bddTransferPermute. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddBddTransferPermute] ******************************************************************************/ static DdNode * cuddBddTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute ) { DdNode *ft, *fe, *t, *e, *var, *res; DdNode *one, *zero; int index; int comple = 0; statLine( ddD ); one = DD_ONE( ddD ); comple = Cudd_IsComplement( f ); /* Trivial cases. */ if ( Cudd_IsConstant( f ) ) return ( Cudd_NotCond( one, comple ) ); /* Make canonical to increase the utilization of the cache. */ f = Cudd_NotCond( f, comple ); /* Now f is a regular pointer to a non-constant node. */ /* Check the cache. */ if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) ) return ( Cudd_NotCond( res, comple ) ); /* Recursive step. */ index = Permute[f->index]; ft = cuddT( f ); fe = cuddE( f ); t = cuddBddTransferPermuteRecur( ddS, ddD, ft, table, Permute ); if ( t == NULL ) { return ( NULL ); } cuddRef( t ); e = cuddBddTransferPermuteRecur( ddS, ddD, fe, table, Permute ); if ( e == NULL ) { Cudd_RecursiveDeref( ddD, t ); return ( NULL ); } cuddRef( e ); zero = Cudd_Not( one ); var = cuddUniqueInter( ddD, index, one, zero ); if ( var == NULL ) { Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); return ( NULL ); } res = cuddBddIteRecur( ddD, var, t, e ); if ( res == NULL ) { Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); return ( NULL ); } cuddRef( res ); Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); if ( st__add_direct( table, ( char * ) f, ( char * ) res ) == st__OUT_OF_MEM ) { Cudd_RecursiveDeref( ddD, res ); return ( NULL ); } return ( Cudd_NotCond( res, comple ) ); } /* end of cuddBddTransferPermuteRecur */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cas/casDec.c000066400000000000000000000442231300674244400226660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [casDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] Synopsis [BDD-based decomposition with encoding.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Spring 2002.] Revision [$Id: casDec.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include "bdd/extrab/extraBdd.h" #include "cas.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// type definitions /// //////////////////////////////////////////////////////////////////////// typedef struct { int nIns; // the number of LUT variables int nInsP; // the number of inputs coming from the previous LUT int nCols; // the number of columns in this LUT int nMulti; // the column multiplicity, [log2(nCols)] int nSimple; // the number of outputs implemented as direct connections to inputs of the previous block int Level; // the starting level in the ADD in this LUT // DdNode ** pbVarsIn[32]; // the BDDs of the elementary input variables // DdNode ** pbVarsOut[32]; // the BDDs of the elementary output variables // char * pNamesIn[32]; // the names of input variables // char * pNamesOut[32]; // the names of output variables DdNode ** pbCols; // the array of columns represented by BDDs DdNode ** pbCodes; // the array of codes (in terms of pbVarsOut) DdNode ** paNodes; // the array of starting ADD nodes on the next level (also referenced) DdNode * bRelation; // the relation after encoding // the relation depends on the three groups of variables: // (1) variables on top represent the outputs of the previous cascade // (2) variables in the middle represent the primary inputs // (3) variables below (CVars) represent the codes // // the replacement is done after computing the relation } LUT; //////////////////////////////////////////////////////////////////////// /// static functions /// //////////////////////////////////////////////////////////////////////// // the LUT-2-BLIF writing function void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName ); // the function to write a DD (BDD or ADD) as a network of MUXES extern void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); extern void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); //////////////////////////////////////////////////////////////////////// /// static varibles /// //////////////////////////////////////////////////////////////////////// static int s_LutSize = 15; static int s_nFuncVars; long s_EncodingTime; long s_EncSearchTime; long s_EncComputeTime; //////////////////////////////////// // temporary output variables //FILE * pTable; //long s_ReadingTime; //long s_RemappingTime; //////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// debugging macros /// //////////////////////////////////////////////////////////////////////// #define PRB_(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" ) #define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" ) #define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) //////////////////////////////////////////////////////////////////////// /// EXTERNAL FUNCTIONS /// //////////////////////////////////////////////////////////////////////// int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose ) // aFunc is a 0-1 ADD for the given function // pNames (nNames) are the input variable names // FileName is the name of the output file for the LUT network // dynamic variable reordering should be disabled when this function is running { static LUT * pLuts[MAXINPUTS]; // the LUT cascade static int Profile[MAXINPUTS]; // the profile filled in with the info about the BDD width static int Permute[MAXINPUTS]; // the array to store a temporary permutation of variables LUT * p; // the current LUT int i, v; DdNode * bCVars[32]; // these are variables for the codes int nVarsRem; // the number of remaining variables int PrevMulti; // column multiplicity on the previous level int fLastLut; // flag to signal the last LUT int nLuts; int nLutsTotal = 0; int nLutOutputs = 0; int nLutOutputsOrig = 0; abctime clk1; s_LutSize = nLutSize; s_nFuncVars = nNames; // get the profile clk1 = Abc_Clock(); Extra_ProfileWidth( dd, aFunc, Profile, -1 ); // for ( v = 0; v < nNames; v++ ) // printf( "Level = %2d, Width = %2d\n", v+1, Profile[v] ); //printf( "\n" ); // mark-up the LUTs // assuming that the manager has exactly nNames vars (new vars have not been introduced yet) nVarsRem = nNames; // the number of remaining variables PrevMulti = 0; // column multiplicity on the previous level fLastLut = 0; nLuts = 0; do { p = (LUT*) ABC_ALLOC( char, sizeof(LUT) ); memset( p, 0, sizeof(LUT) ); if ( nVarsRem + PrevMulti <= s_LutSize ) // this is the last LUT { p->nIns = nVarsRem + PrevMulti; p->nInsP = PrevMulti; p->nCols = 2; p->nMulti = 1; p->Level = nNames-nVarsRem; nVarsRem = 0; PrevMulti = 1; fLastLut = 1; } else // this is not the last LUT { p->nIns = s_LutSize; p->nInsP = PrevMulti; p->nCols = Profile[nNames-(nVarsRem-(s_LutSize-PrevMulti))]; p->nMulti = Abc_Base2Log(p->nCols); p->Level = nNames-nVarsRem; nVarsRem = nVarsRem-(s_LutSize-PrevMulti); PrevMulti = p->nMulti; } if ( p->nMulti >= s_LutSize ) { printf( "The LUT size is too small\n" ); return 0; } nLutOutputsOrig += p->nMulti; //if ( fVerbose ) //printf( "Stage %2d: In = %3d, InP = %3d, Cols = %5d, Multi = %2d, Level = %2d\n", // nLuts+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->Level ); // there should be as many columns, codes, and nodes, as there are columns on this level p->pbCols = (DdNode **) ABC_ALLOC( char, p->nCols * sizeof(DdNode *) ); p->pbCodes = (DdNode **) ABC_ALLOC( char, p->nCols * sizeof(DdNode *) ); p->paNodes = (DdNode **) ABC_ALLOC( char, p->nCols * sizeof(DdNode *) ); pLuts[nLuts] = p; nLuts++; } while ( !fLastLut ); //if ( fVerbose ) //printf( "The number of cascades = %d\n", nLuts ); //fprintf( pTable, "%d ", nLuts ); // add the new variables at the bottom for ( i = 0; i < s_LutSize; i++ ) bCVars[i] = Cudd_bddNewVar(dd); // for each LUT - assign the LUT and encode the columns s_EncodingTime = 0; for ( i = 0; i < nLuts; i++ ) { int RetValue; DdNode * bVars[32]; int nVars; DdNode * bVarsInCube; DdNode * bVarsCCube; DdNode * bVarsCube; int CutLevel; p = pLuts[i]; // compute the columns of this LUT starting from the given set of nodes with the given codes // (these codes have been remapped to depend on the topmost variables in the manager) // for the first LUT, start with the constant 1 BDD CutLevel = p->Level + p->nIns - p->nInsP; if ( i == 0 ) RetValue = Extra_bddNodePathsUnderCutArray( dd, &aFunc, &(b1), 1, p->paNodes, p->pbCols, CutLevel ); else RetValue = Extra_bddNodePathsUnderCutArray( dd, pLuts[i-1]->paNodes, pLuts[i-1]->pbCodes, pLuts[i-1]->nCols, p->paNodes, p->pbCols, CutLevel ); assert( RetValue == p->nCols ); // at this point, we have filled out p->paNodes[] and p->pbCols[] of this LUT // pLuts[i-1]->paNodes depended on normal vars // pLuts[i-1]->pbCodes depended on the topmost variables // the resulting p->paNodes depend on normal ADD nodes // the resulting p->pbCols depend on normal vars and topmost variables in the manager // perform the encoding // create the cube of these variables // collect the topmost variables of the manager nVars = p->nInsP; for ( v = 0; v < nVars; v++ ) bVars[v] = dd->vars[ dd->invperm[v] ]; bVarsCCube = Extra_bddBitsToCube( dd, (1<nIns - p->nInsP; for ( v = 0; v < nVars; v++ ) bVars[v] = dd->vars[ dd->invperm[p->Level+v] ]; bVarsInCube = Extra_bddBitsToCube( dd, (1<nMulti == 1 ); assert( p->nCols == 2 ); assert( Cudd_IsConstant( p->paNodes[0] ) ); assert( Cudd_IsConstant( p->paNodes[1] ) ); bVar = ( p->paNodes[0] == a1 )? bCVars[0]: Cudd_Not( bCVars[0] ); p->bRelation = Cudd_bddIte( dd, bVar, p->pbCols[0], p->pbCols[1] ); Cudd_Ref( p->bRelation ); } else { abctime clk2 = Abc_Clock(); // p->bRelation = PerformTheEncoding( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation ); p->bRelation = Extra_bddEncodingNonStrict( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation ); s_EncodingTime += Abc_Clock() - clk2; } // update the number of LUT outputs nLutOutputs += (p->nMulti - p->nSimple); nLutsTotal += p->nMulti; //if ( fVerbose ) //printf( "Stage %2d: Simple = %d\n", i+1, p->nSimple ); if ( fVerbose ) printf( "Stage %3d: In = %3d InP = %3d Cols = %5d Multi = %2d Simple = %2d Level = %3d\n", i+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->nSimple, p->Level ); // get the codes from the relation (these are not necessarily cubes) { int c; for ( c = 0; c < p->nCols; c++ ) { p->pbCodes[c] = Cudd_bddAndAbstract( dd, p->bRelation, p->pbCols[c], bVarsCube ); Cudd_Ref( p->pbCodes[c] ); } } Cudd_RecursiveDeref( dd, bVarsCube ); // remap the codes to depend on the topmost varibles of the manager // useful as a preparation for the next step { DdNode ** pbTemp; int k, v; pbTemp = (DdNode **) ABC_ALLOC( char, p->nCols * sizeof(DdNode *) ); // create the identical permutation for ( v = 0; v < dd->size; v++ ) Permute[v] = v; // use the topmost variables of the manager // to represent the previous level codes for ( v = 0; v < p->nMulti; v++ ) Permute[bCVars[v]->index] = dd->invperm[v]; Extra_bddPermuteArray( dd, p->pbCodes, pbTemp, p->nCols, Permute ); // the array pbTemp comes already referenced // deref the old codes and assign the new ones for ( k = 0; k < p->nCols; k++ ) { Cudd_RecursiveDeref( dd, p->pbCodes[k] ); p->pbCodes[k] = pbTemp[k]; } ABC_FREE( pbTemp ); } } if ( fVerbose ) printf( "LUTs: Total = %5d. Final = %5d. Simple = %5d. (%6.2f %%) ", nLutsTotal, nLutOutputs, nLutsTotal-nLutOutputs, 100.0*(nLutsTotal-nLutOutputs)/nLutsTotal ); if ( fVerbose ) printf( "Memory = %6.2f MB\n", 1.0*nLutOutputs*(1<nCols; v++ ) { Cudd_RecursiveDeref( dd, p->pbCols[v] ); Cudd_RecursiveDeref( dd, p->pbCodes[v] ); Cudd_RecursiveDeref( dd, p->paNodes[v] ); } Cudd_RecursiveDeref( dd, p->bRelation ); ABC_FREE( p->pbCols ); ABC_FREE( p->pbCodes ); ABC_FREE( p->paNodes ); ABC_FREE( p ); } return 1; } void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName ) { int i, v, o; static char * pNamesLocalIn[MAXINPUTS]; static char * pNamesLocalOut[MAXINPUTS]; static char Buffer[100]; DdNode * bCube, * bCof, * bFunc; LUT * p; // go through all the LUTs for ( i = 0; i < nLuts; i++ ) { // get the pointer to the LUT p = pLuts[i]; if ( i == nLuts -1 ) { assert( p->nMulti == 1 ); } fprintf( pFile, "#----------------- LUT #%d ----------------------\n", i ); // fill in the names for the current LUT // write the outputs of the previous LUT if ( i != 0 ) for ( v = 0; v < p->nInsP; v++ ) { sprintf( Buffer, "LUT%02d_%02d", i-1, v ); pNamesLocalIn[dd->invperm[v]] = Extra_UtilStrsav( Buffer ); } // write the primary inputs of the current LUT for ( v = 0; v < p->nIns - p->nInsP; v++ ) pNamesLocalIn[dd->invperm[p->Level+v]] = Extra_UtilStrsav( pNames[dd->invperm[p->Level+v]] ); // write the outputs of the current LUT for ( v = 0; v < p->nMulti; v++ ) { sprintf( Buffer, "LUT%02d_%02d", i, v ); if ( i != nLuts - 1 ) pNamesLocalOut[v] = Extra_UtilStrsav( Buffer ); else pNamesLocalOut[v] = Extra_UtilStrsav( "F" ); } // write LUT outputs // get the prefix sprintf( Buffer, "L%02d_", i ); // get the cube of encoding variables bCube = Extra_bddBitsToCube( dd, (1<nMulti)-1, p->nMulti, bCVars, 1 ); Cudd_Ref( bCube ); // write each output of the LUT for ( o = 0; o < p->nMulti; o++ ) { // get the cofactor of this output bCof = Cudd_Cofactor( dd, p->bRelation, bCVars[o] ); Cudd_Ref( bCof ); // quantify the remaining variables to get the function bFunc = Cudd_bddExistAbstract( dd, bCof, bCube ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bCof ); // write BLIF sprintf( Buffer, "L%02d_%02d_", i, o ); // WriteDDintoBLIFfileReorder( dd, pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn ); // does not work well; the advantage is marginal (30%), the run time is huge... WriteDDintoBLIFfile( pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn ); Cudd_RecursiveDeref( dd, bFunc ); } Cudd_RecursiveDeref( dd, bCube ); // clean up the previous local names for ( v = 0; v < dd->size; v++ ) { if ( pNamesLocalIn[v] ) ABC_FREE( pNamesLocalIn[v] ); pNamesLocalIn[v] = NULL; } for ( v = 0; v < p->nMulti; v++ ) ABC_FREE( pNamesLocalOut[v] ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cas/module.make000066400000000000000000000000711300674244400234550ustar00rootroot00000000000000SRC += src/bdd/cas/casCore.c \ src/bdd/cas/casDec.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/000077500000000000000000000000001300674244400215045ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/Makefile000066400000000000000000000062771300674244400231600ustar00rootroot00000000000000# $Id$ # # Cudd - DD package #--------------------------- .SUFFIXES: .o .c .u CC = gcc RANLIB = ranlib PURE = # Define EXE as .exe for MS-DOS and derivatives. EXE = #EXE = .exe MFLAG = ICFLAGS = -g XCFLAGS = -DDD_STATS CFLAGS = $(ICFLAGS) $(MFLAG) $(XCFLAGS) #DDDEBUG = -DDD_DEBUG -DDD_CACHE_PROFILE -DDD_VERBOSE -DDD_UNIQUE_PROFILE DDDEBUG = LINTFLAGS = -u -n -DDD_STATS -DDD_CACHE_PROFILE -DDD_VERBOSE -DDD_DEBUG -DDD_UNIQUE_PROFILE # this is to create the lint library LINTSWITCH = -o WHERE = .. INCLUDE = $(WHERE)/include LIBS = ./libcudd.a $(WHERE)/mtr/libmtr.a \ $(WHERE)/st/libst.a $(WHERE)/util/libutil.a $(WHERE)/epd/libepd.a MNEMLIB = BLIBS = -kL. -klcudd -kL$(WHERE)/mtr -klmtr \ -kL$(WHERE)/st -klst -kL$(WHERE)/util -klutil -kL$(WHERE)/epd -klepd LINTLIBS = ./llib-lcudd.ln $(WHERE)/mtr/llib-lmtr.ln \ $(WHERE)/st/llib-lst.ln $(WHERE)/util/llib-lutil.ln \ $(WHERE)/epd/llib-lepd.ln LDFLAGS = # files for the package P = cudd PSRC = cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \ cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c \ cuddExact.c cuddExport.c cuddGenCof.c cuddGenetic.c \ cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ cuddLCache.c cuddLevelQ.c \ cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c \ cuddZddPort.c cuddZddReord.c cuddZddSetop.c cuddZddSymm.c \ cuddZddUtil.c PHDR = cudd.h cuddInt.h POBJ = $(PSRC:.c=.o) PUBJ = $(PSRC:.c=.u) TARGET = test$(P)$(EXE) TARGETu = test$(P)-u # files for the test program SRC = test$(P).c OBJ = $(SRC:.c=.o) UBJ = $(SRC:.c=.u) #------------------------------------------------------ lib$(P).a: $(POBJ) ar rv $@ $? $(RANLIB) $@ .c.o: $(PSRC) $(PHDR) $(CC) -c $< -I$(INCLUDE) $(CFLAGS) $(DDDEBUG) optimize_dec: lib$(P).b lib$(P).b: $(PUBJ) ar rv $@ $? $(RANLIB) $@ .c.u: $(PSRC) $(PHDR) cc -j $< -I$(INCLUDE) $(XCFLAGS) # if the header files change, recompile $(POBJ): $(PHDR) $(PUBJ): $(PHDR) $(OBJ): $(PHDR) $(UBJ): $(PHDR) $(TARGET): $(SRC) $(OBJ) $(HDR) $(LIBS) $(MNEMLIB) $(PURE) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(MNEMLIB) -lm # optimize (DECstations and Alphas only: uses u-code) $(TARGETu): $(SRC) $(UBJ) $(HDR) $(LIBS:.a=.b) $(CC) -O3 -Olimit 1000 $(XCFLAGS) $(LDFLAGS) -o $@ $(UBJ) $(BLIBS) -lm lint: llib-l$(P).ln llib-l$(P).ln: $(PSRC) $(PHDR) lint $(LINTFLAGS) $(LINTSWITCH)$(P) -I$(INCLUDE) $(PSRC) lintpgm: lint lint $(LINTFLAGS) -I$(INCLUDE) $(SRC) $(LINTLIBS) tags: $(PSRC) $(PHDR) ctags $(PSRC) $(PHDR) all: lib$(P).a lib$(P).b llib-l$(P).ln tags programs: $(TARGET) $(TARGETu) lintpgm clean: rm -f *.o *.u mon.out gmon.out *.pixie *.Addrs *.Counts mnem.* \ .pure core *.warnings distclean: clean rm -f $(TARGET) $(TARGETu) lib*.a lib$(P).b llib-l$(P).ln \ *.bak *~ tags .gdb_history *.qv *.qx berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuBdd.make000066400000000000000000000036361300674244400233740ustar00rootroot00000000000000CSRC_cu += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \ cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \ cuddExport.c cuddGenCof.c cuddGenetic.c \ cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ cuddLCache.c cuddLevelQ.c \ cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \ cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c HEADERS_cu += cudd.h cuddInt.h MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \ doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \ doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \ doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \ doc/node1.html doc/node2.html doc/node3.html doc/node4.html \ doc/node5.html doc/node6.html doc/node7.html doc/node8.html \ doc/icons/change_begin.gif \ doc/icons/change_delete.gif \ doc/icons/change_end.gif \ doc/icons/contents_motif.gif \ doc/icons/cross_ref_motif.gif \ doc/icons/foot_motif.gif \ doc/icons/image.gif \ doc/icons/index_motif.gif \ doc/icons/next_group_motif.gif \ doc/icons/next_group_motif_gr.gif \ doc/icons/next_motif.gif \ doc/icons/next_motif_gr.gif \ doc/icons/previous_group_motif.gif \ doc/icons/previous_group_motif_gr.gif \ doc/icons/previous_motif.gif \ doc/icons/previous_motif_gr.gif \ doc/icons/up_motif.gif \ doc/icons/up_motif_gr.gif DEPENDENCYFILES = $(CSRC_cu) berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cudd.h000066400000000000000000001554441300674244400226110ustar00rootroot00000000000000/**CHeaderFile***************************************************************** FileName [cudd.h] PackageName [cudd] Synopsis [The University of Colorado decision diagram package.] Description [External functions and data strucures of the CUDD package.
  • To turn on the gathering of statistics, define DD_STATS.
  • To link with mis, define DD_MIS.
Modified by Abelardo Pardo to interface it to VIS. ] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] Revision [$Id: cudd.h,v 1.174 2009/02/21 05:55:18 fabio Exp $] ******************************************************************************/ #ifndef ABC__bdd__cudd__cudd_h #define ABC__bdd__cudd__cudd_h /*---------------------------------------------------------------------------*/ /* Nested includes */ /*---------------------------------------------------------------------------*/ #include "bdd/mtr/mtr.h" #include "bdd/epd/epd.h" ABC_NAMESPACE_HEADER_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define CUDD_VERSION "2.4.2" #ifndef SIZEOF_VOID_P #define SIZEOF_VOID_P 4 #endif #ifndef SIZEOF_INT #define SIZEOF_INT 4 #endif #ifndef SIZEOF_LONG #define SIZEOF_LONG 4 #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define CUDD_VALUE_TYPE double #define CUDD_OUT_OF_MEM -1 /* The sizes of the subtables and the cache must be powers of two. */ #define CUDD_UNIQUE_SLOTS 256 /* initial size of subtables */ #define CUDD_CACHE_SLOTS 262144 /* default size of the cache */ /* Constants for residue functions. */ #define CUDD_RESIDUE_DEFAULT 0 #define CUDD_RESIDUE_MSB 1 #define CUDD_RESIDUE_TC 2 /* CUDD_MAXINDEX is defined in such a way that on 32-bit and 64-bit ** machines one can cast an index to (int) without generating a negative ** number. */ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define CUDD_MAXINDEX (((DdHalfWord) ~0) >> 1) #else #define CUDD_MAXINDEX ((DdHalfWord) ~0) #endif /* CUDD_CONST_INDEX is the index of constant nodes. Currently this ** is a synonim for CUDD_MAXINDEX. */ #define CUDD_CONST_INDEX CUDD_MAXINDEX /* These constants define the digits used in the representation of ** arbitrary precision integers. The configurations tested use 8, 16, ** and 32 bits for each digit. The typedefs should be in agreement ** with these definitions. */ #if SIZEOF_LONG == 8 #define DD_APA_BITS 32 #define DD_APA_BASE (1L << DD_APA_BITS) #define DD_APA_HEXPRINT "%08x" #else #define DD_APA_BITS 16 #define DD_APA_BASE (1 << DD_APA_BITS) #define DD_APA_HEXPRINT "%04x" #endif #define DD_APA_MASK (DD_APA_BASE - 1) /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /**Enum************************************************************************ Synopsis [Type of reordering algorithm.] Description [Type of reordering algorithm.] ******************************************************************************/ typedef enum { CUDD_REORDER_SAME, CUDD_REORDER_NONE, CUDD_REORDER_RANDOM, CUDD_REORDER_RANDOM_PIVOT, CUDD_REORDER_SIFT, CUDD_REORDER_SIFT_CONVERGE, CUDD_REORDER_SYMM_SIFT, CUDD_REORDER_SYMM_SIFT_CONV, CUDD_REORDER_WINDOW2, CUDD_REORDER_WINDOW3, CUDD_REORDER_WINDOW4, CUDD_REORDER_WINDOW2_CONV, CUDD_REORDER_WINDOW3_CONV, CUDD_REORDER_WINDOW4_CONV, CUDD_REORDER_GROUP_SIFT, CUDD_REORDER_GROUP_SIFT_CONV, CUDD_REORDER_ANNEALING, CUDD_REORDER_GENETIC, CUDD_REORDER_LINEAR, CUDD_REORDER_LINEAR_CONVERGE, CUDD_REORDER_LAZY_SIFT, CUDD_REORDER_EXACT } Cudd_ReorderingType; /**Enum************************************************************************ Synopsis [Type of aggregation methods.] Description [Type of aggregation methods.] ******************************************************************************/ typedef enum { CUDD_NO_CHECK, CUDD_GROUP_CHECK, CUDD_GROUP_CHECK2, CUDD_GROUP_CHECK3, CUDD_GROUP_CHECK4, CUDD_GROUP_CHECK5, CUDD_GROUP_CHECK6, CUDD_GROUP_CHECK7, CUDD_GROUP_CHECK8, CUDD_GROUP_CHECK9 } Cudd_AggregationType; /**Enum************************************************************************ Synopsis [Type of hooks.] Description [Type of hooks.] ******************************************************************************/ typedef enum { CUDD_PRE_GC_HOOK, CUDD_POST_GC_HOOK, CUDD_PRE_REORDERING_HOOK, CUDD_POST_REORDERING_HOOK } Cudd_HookType; /**Enum************************************************************************ Synopsis [Type of error codes.] Description [Type of error codes.] ******************************************************************************/ typedef enum { CUDD_NO_ERROR, CUDD_MEMORY_OUT, CUDD_TOO_MANY_NODES, CUDD_MAX_MEM_EXCEEDED, CUDD_INVALID_ARG, CUDD_INTERNAL_ERROR } Cudd_ErrorType; /**Enum************************************************************************ Synopsis [Group type for lazy sifting.] Description [Group type for lazy sifting.] ******************************************************************************/ typedef enum { CUDD_LAZY_NONE, CUDD_LAZY_SOFT_GROUP, CUDD_LAZY_HARD_GROUP, CUDD_LAZY_UNGROUP } Cudd_LazyGroupType; /**Enum************************************************************************ Synopsis [Variable type.] Description [Variable type. Currently used only in lazy sifting.] ******************************************************************************/ typedef enum { CUDD_VAR_PRIMARY_INPUT, CUDD_VAR_PRESENT_STATE, CUDD_VAR_NEXT_STATE } Cudd_VariableType; #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 typedef unsigned int DdHalfWord; #else typedef unsigned short DdHalfWord; #endif #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif typedef struct DdNode DdNode; typedef struct DdChildren { struct DdNode *T; struct DdNode *E; } DdChildren; /* The DdNode structure is the only one exported out of the package */ struct DdNode { DdHalfWord index; DdHalfWord ref; /* reference count */ DdNode *next; /* next pointer for unique table */ union { CUDD_VALUE_TYPE value; /* for constant nodes */ DdChildren kids; /* for internal nodes */ } type; ABC_INT64_T Id; }; #ifdef __osf__ #pragma pointer_size restore #endif typedef struct DdManager DdManager; typedef struct DdGen DdGen; /* These typedefs for arbitrary precision arithmetic should agree with ** the corresponding constant definitions above. */ #if SIZEOF_LONG == 8 typedef unsigned int DdApaDigit; typedef unsigned long int DdApaDoubleDigit; #else typedef unsigned short int DdApaDigit; typedef unsigned int DdApaDoubleDigit; #endif typedef DdApaDigit * DdApaNumber; /* Return type for function computing two-literal clauses. */ typedef struct DdTlcInfo DdTlcInfo; /* Type of hook function. */ typedef int (*DD_HFP)(DdManager *, const char *, void *); /* Type of priority function */ typedef DdNode * (*DD_PRFP)(DdManager * , int, DdNode **, DdNode **, DdNode **); /* Type of apply operator. */ typedef DdNode * (*DD_AOP)(DdManager *, DdNode **, DdNode **); /* Type of monadic apply operator. */ typedef DdNode * (*DD_MAOP)(DdManager *, DdNode *); /* Types of cache tag functions. */ typedef DdNode * (*DD_CTFP)(DdManager *, DdNode *, DdNode *); typedef DdNode * (*DD_CTFP1)(DdManager *, DdNode *); /* Type of memory-out function. */ typedef void (*DD_OOMFP)(long); /* Type of comparison function for qsort. */ typedef int (*DD_QSFP)(const void *, const void *); /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**Macro*********************************************************************** Synopsis [Returns 1 if the node is a constant node.] Description [Returns 1 if the node is a constant node (rather than an internal node). All constant nodes have the same index (CUDD_CONST_INDEX). The pointer passed to Cudd_IsConstant may be either regular or complemented.] SideEffects [none] SeeAlso [] ******************************************************************************/ #define Cudd_IsConstant(node) ((Cudd_Regular(node))->index == CUDD_CONST_INDEX) /**Macro*********************************************************************** Synopsis [Complements a DD.] Description [Complements a DD by flipping the complement attribute of the pointer (the least significant bit).] SideEffects [none] SeeAlso [Cudd_NotCond] ******************************************************************************/ #define Cudd_Not(node) ((DdNode *)((ptrint)(node) ^ 01)) /**Macro*********************************************************************** Synopsis [Complements a DD if a condition is true.] Description [Complements a DD if condition c is true; c should be either 0 or 1, because it is used directly (for efficiency). If in doubt on the values c may take, use "(c) ? Cudd_Not(node) : node".] SideEffects [none] SeeAlso [Cudd_Not] ******************************************************************************/ #define Cudd_NotCond(node,c) ((DdNode *)((ptrint)(node) ^ (c))) /**Macro*********************************************************************** Synopsis [Returns the regular version of a pointer.] Description [] SideEffects [none] SeeAlso [Cudd_Complement Cudd_IsComplement] ******************************************************************************/ #define Cudd_Regular(node) ((DdNode *)((ptruint)(node) & ~01)) /**Macro*********************************************************************** Synopsis [Returns the complemented version of a pointer.] Description [] SideEffects [none] SeeAlso [Cudd_Regular Cudd_IsComplement] ******************************************************************************/ #define Cudd_Complement(node) ((DdNode *)((ptruint)(node) | 01)) /**Macro*********************************************************************** Synopsis [Returns 1 if a pointer is complemented.] Description [] SideEffects [none] SeeAlso [Cudd_Regular Cudd_Complement] ******************************************************************************/ #define Cudd_IsComplement(node) ((int) ((ptrint) (node) & 01)) /**Macro*********************************************************************** Synopsis [Returns the then child of an internal node.] Description [Returns the then child of an internal node. If node is a constant node, the result is unpredictable.] SideEffects [none] SeeAlso [Cudd_E Cudd_V] ******************************************************************************/ #define Cudd_T(node) ((Cudd_Regular(node))->type.kids.T) /**Macro*********************************************************************** Synopsis [Returns the else child of an internal node.] Description [Returns the else child of an internal node. If node is a constant node, the result is unpredictable.] SideEffects [none] SeeAlso [Cudd_T Cudd_V] ******************************************************************************/ #define Cudd_E(node) ((Cudd_Regular(node))->type.kids.E) /**Macro*********************************************************************** Synopsis [Returns the value of a constant node.] Description [Returns the value of a constant node. If node is an internal node, the result is unpredictable.] SideEffects [none] SeeAlso [Cudd_T Cudd_E] ******************************************************************************/ #define Cudd_V(node) ((Cudd_Regular(node))->type.value) /**Macro*********************************************************************** Synopsis [Returns the current position in the order of variable index.] Description [Returns the current position in the order of variable index. This macro is obsolete and is kept for compatibility. New applications should use Cudd_ReadPerm instead.] SideEffects [none] SeeAlso [Cudd_ReadPerm] ******************************************************************************/ #define Cudd_ReadIndex(dd,index) (Cudd_ReadPerm(dd,index)) /**Macro*********************************************************************** Synopsis [Iterates over the cubes of a decision diagram.] Description [Iterates over the cubes of a decision diagram f.
  • DdManager *manager;
  • DdNode *f;
  • DdGen *gen;
  • int *cube;
  • CUDD_VALUE_TYPE value;
Cudd_ForeachCube allocates and frees the generator. Therefore the application should not try to do that. Also, the cube is freed at the end of Cudd_ForeachCube and hence is not available outside of the loop.

CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.] SideEffects [none] SeeAlso [Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty Cudd_AutodynDisable] ******************************************************************************/ #define Cudd_ForeachCube(manager, f, gen, cube, value)\ for((gen) = Cudd_FirstCube(manager, f, &cube, &value);\ Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ (void) Cudd_NextCube(gen, &cube, &value)) /**Macro*********************************************************************** Synopsis [Iterates over the primes of a Boolean function.] Description [Iterates over the primes of a Boolean function producing a prime and irredundant cover.

  • DdManager *manager;
  • DdNode *l;
  • DdNode *u;
  • DdGen *gen;
  • int *cube;
The Boolean function is described by an upper bound and a lower bound. If the function is completely specified, the two bounds coincide. Cudd_ForeachPrime allocates and frees the generator. Therefore the application should not try to do that. Also, the cube is freed at the end of Cudd_ForeachPrime and hence is not available outside of the loop.

CAUTION: It is a mistake to change a diagram on which generation is ongoing.] SideEffects [none] SeeAlso [Cudd_ForeachCube Cudd_FirstPrime Cudd_NextPrime Cudd_GenFree Cudd_IsGenEmpty] ******************************************************************************/ #define Cudd_ForeachPrime(manager, l, u, gen, cube)\ for((gen) = Cudd_FirstPrime(manager, l, u, &cube);\ Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ (void) Cudd_NextPrime(gen, &cube)) /**Macro*********************************************************************** Synopsis [Iterates over the nodes of a decision diagram.] Description [Iterates over the nodes of a decision diagram f.

  • DdManager *manager;
  • DdNode *f;
  • DdGen *gen;
  • DdNode *node;
The nodes are returned in a seemingly random order. Cudd_ForeachNode allocates and frees the generator. Therefore the application should not try to do that.

CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.] SideEffects [none] SeeAlso [Cudd_ForeachCube Cudd_FirstNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty Cudd_AutodynDisable] ******************************************************************************/ #define Cudd_ForeachNode(manager, f, gen, node)\ for((gen) = Cudd_FirstNode(manager, f, &node);\ Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ (void) Cudd_NextNode(gen, &node)) /**Macro*********************************************************************** Synopsis [Iterates over the paths of a ZDD.] Description [Iterates over the paths of a ZDD f.

  • DdManager *manager;
  • DdNode *f;
  • DdGen *gen;
  • int *path;
Cudd_zddForeachPath allocates and frees the generator. Therefore the application should not try to do that. Also, the path is freed at the end of Cudd_zddForeachPath and hence is not available outside of the loop.

CAUTION: It is assumed that dynamic reordering will not occur while there are open generators. It is the user's responsibility to make sure that dynamic reordering does not occur. As long as new nodes are not created during generation, and dynamic reordering is not called explicitly, dynamic reordering will not occur. Alternatively, it is sufficient to disable dynamic reordering. It is a mistake to dispose of a diagram on which generation is ongoing.] SideEffects [none] SeeAlso [Cudd_zddFirstPath Cudd_zddNextPath Cudd_GenFree Cudd_IsGenEmpty Cudd_AutodynDisable] ******************************************************************************/ #define Cudd_zddForeachPath(manager, f, gen, path)\ for((gen) = Cudd_zddFirstPath(manager, f, &path);\ Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ (void) Cudd_zddNextPath(gen, &path)) /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Function prototypes */ /*---------------------------------------------------------------------------*/ extern DdNode * Cudd_addNewVar( DdManager * dd ); extern DdNode * Cudd_addNewVarAtLevel( DdManager * dd, int level ); extern DdNode * Cudd_bddNewVar( DdManager * dd ); extern DdNode * Cudd_bddNewVarAtLevel( DdManager * dd, int level ); extern DdNode * Cudd_addIthVar( DdManager * dd, int i ); extern DdNode * Cudd_bddIthVar( DdManager * dd, int i ); extern DdNode * Cudd_zddIthVar( DdManager * dd, int i ); extern int Cudd_zddVarsFromBddVars( DdManager * dd, int multiplicity ); extern DdNode * Cudd_addConst( DdManager * dd, CUDD_VALUE_TYPE c ); extern int Cudd_IsNonConstant( DdNode * f ); extern void Cudd_AutodynEnable( DdManager * unique, Cudd_ReorderingType method ); extern void Cudd_AutodynDisable( DdManager * unique ); extern int Cudd_ReorderingStatus( DdManager * unique, Cudd_ReorderingType * method ); extern void Cudd_AutodynEnableZdd( DdManager * unique, Cudd_ReorderingType method ); extern void Cudd_AutodynDisableZdd( DdManager * unique ); extern int Cudd_ReorderingStatusZdd( DdManager * unique, Cudd_ReorderingType * method ); extern int Cudd_zddRealignmentEnabled( DdManager * unique ); extern void Cudd_zddRealignEnable( DdManager * unique ); extern void Cudd_zddRealignDisable( DdManager * unique ); extern int Cudd_bddRealignmentEnabled( DdManager * unique ); extern void Cudd_bddRealignEnable( DdManager * unique ); extern void Cudd_bddRealignDisable( DdManager * unique ); extern DdNode * Cudd_ReadOne( DdManager * dd ); extern DdNode * Cudd_ReadZddOne( DdManager * dd, int i ); extern DdNode * Cudd_ReadZero( DdManager * dd ); extern DdNode * Cudd_ReadLogicZero( DdManager * dd ); extern DdNode * Cudd_ReadPlusInfinity( DdManager * dd ); extern DdNode * Cudd_ReadMinusInfinity( DdManager * dd ); extern DdNode * Cudd_ReadBackground( DdManager * dd ); extern void Cudd_SetBackground( DdManager * dd, DdNode * bck ); extern unsigned int Cudd_ReadCacheSlots( DdManager * dd ); extern double Cudd_ReadCacheUsedSlots( DdManager * dd ); extern double Cudd_ReadCacheLookUps( DdManager * dd ); extern double Cudd_ReadCacheHits( DdManager * dd ); extern double Cudd_ReadRecursiveCalls( DdManager * dd ); extern unsigned int Cudd_ReadMinHit( DdManager * dd ); extern void Cudd_SetMinHit( DdManager * dd, unsigned int hr ); extern unsigned int Cudd_ReadLooseUpTo( DdManager * dd ); extern void Cudd_SetLooseUpTo( DdManager * dd, unsigned int lut ); extern unsigned int Cudd_ReadMaxCache( DdManager * dd ); extern unsigned int Cudd_ReadMaxCacheHard( DdManager * dd ); extern void Cudd_SetMaxCacheHard( DdManager * dd, unsigned int mc ); extern int Cudd_ReadSize( DdManager * dd ); extern int Cudd_ReadZddSize( DdManager * dd ); extern unsigned int Cudd_ReadSlots( DdManager * dd ); extern double Cudd_ReadUsedSlots( DdManager * dd ); extern double Cudd_ExpectedUsedSlots( DdManager * dd ); extern unsigned int Cudd_ReadKeys( DdManager * dd ); extern unsigned int Cudd_ReadDead( DdManager * dd ); extern unsigned int Cudd_ReadMinDead( DdManager * dd ); extern int Cudd_ReadReorderings( DdManager * dd ); extern long Cudd_ReadReorderingTime( DdManager * dd ); extern int Cudd_ReadGarbageCollections( DdManager * dd ); extern long Cudd_ReadGarbageCollectionTime( DdManager * dd ); extern double Cudd_ReadNodesFreed( DdManager * dd ); extern double Cudd_ReadNodesDropped( DdManager * dd ); extern double Cudd_ReadUniqueLookUps( DdManager * dd ); extern double Cudd_ReadUniqueLinks( DdManager * dd ); extern int Cudd_ReadSiftMaxVar( DdManager * dd ); extern void Cudd_SetSiftMaxVar( DdManager * dd, int smv ); extern int Cudd_ReadSiftMaxSwap( DdManager * dd ); extern void Cudd_SetSiftMaxSwap( DdManager * dd, int sms ); extern double Cudd_ReadMaxGrowth( DdManager * dd ); extern void Cudd_SetMaxGrowth( DdManager * dd, double mg ); extern double Cudd_ReadMaxGrowthAlternate( DdManager * dd ); extern void Cudd_SetMaxGrowthAlternate( DdManager * dd, double mg ); extern int Cudd_ReadReorderingCycle( DdManager * dd ); extern void Cudd_SetReorderingCycle( DdManager * dd, int cycle ); extern MtrNode * Cudd_ReadTree( DdManager * dd ); extern void Cudd_SetTree( DdManager * dd, MtrNode * tree ); extern void Cudd_FreeTree( DdManager * dd ); extern MtrNode * Cudd_ReadZddTree( DdManager * dd ); extern void Cudd_SetZddTree( DdManager * dd, MtrNode * tree ); extern void Cudd_FreeZddTree( DdManager * dd ); extern unsigned int Cudd_NodeReadIndex( DdNode * node ); extern int Cudd_ReadPerm( DdManager * dd, int i ); extern int Cudd_ReadPermZdd( DdManager * dd, int i ); extern int Cudd_ReadInvPerm( DdManager * dd, int i ); extern int Cudd_ReadInvPermZdd( DdManager * dd, int i ); extern DdNode * Cudd_ReadVars( DdManager * dd, int i ); extern CUDD_VALUE_TYPE Cudd_ReadEpsilon( DdManager * dd ); extern void Cudd_SetEpsilon( DdManager * dd, CUDD_VALUE_TYPE ep ); extern Cudd_AggregationType Cudd_ReadGroupcheck( DdManager * dd ); extern void Cudd_SetGroupcheck( DdManager * dd, Cudd_AggregationType gc ); extern int Cudd_GarbageCollectionEnabled( DdManager * dd ); extern void Cudd_EnableGarbageCollection( DdManager * dd ); extern void Cudd_DisableGarbageCollection( DdManager * dd ); extern int Cudd_DeadAreCounted( DdManager * dd ); extern void Cudd_TurnOnCountDead( DdManager * dd ); extern void Cudd_TurnOffCountDead( DdManager * dd ); extern int Cudd_ReadRecomb( DdManager * dd ); extern void Cudd_SetRecomb( DdManager * dd, int recomb ); extern int Cudd_ReadSymmviolation( DdManager * dd ); extern void Cudd_SetSymmviolation( DdManager * dd, int symmviolation ); extern int Cudd_ReadArcviolation( DdManager * dd ); extern void Cudd_SetArcviolation( DdManager * dd, int arcviolation ); extern int Cudd_ReadPopulationSize( DdManager * dd ); extern void Cudd_SetPopulationSize( DdManager * dd, int populationSize ); extern int Cudd_ReadNumberXovers( DdManager * dd ); extern void Cudd_SetNumberXovers( DdManager * dd, int numberXovers ); extern unsigned long Cudd_ReadMemoryInUse( DdManager * dd ); extern int Cudd_PrintInfo( DdManager * dd, FILE * fp ); extern long Cudd_ReadPeakNodeCount( DdManager * dd ); extern int Cudd_ReadPeakLiveNodeCount( DdManager * dd ); extern long Cudd_ReadNodeCount( DdManager * dd ); extern long Cudd_zddReadNodeCount( DdManager * dd ); extern int Cudd_AddHook( DdManager * dd, DD_HFP f, Cudd_HookType where ); extern int Cudd_RemoveHook( DdManager * dd, DD_HFP f, Cudd_HookType where ); extern int Cudd_IsInHook( DdManager * dd, DD_HFP f, Cudd_HookType where ); extern int Cudd_StdPreReordHook( DdManager * dd, const char * str, void * data ); extern int Cudd_StdPostReordHook( DdManager * dd, const char * str, void * data ); extern int Cudd_EnableReorderingReporting( DdManager * dd ); extern int Cudd_DisableReorderingReporting( DdManager * dd ); extern int Cudd_ReorderingReporting( DdManager * dd ); extern Cudd_ErrorType Cudd_ReadErrorCode( DdManager * dd ); extern void Cudd_ClearErrorCode( DdManager * dd ); extern FILE * Cudd_ReadStdout( DdManager * dd ); extern void Cudd_SetStdout( DdManager * dd, FILE * fp ); extern FILE * Cudd_ReadStderr( DdManager * dd ); extern void Cudd_SetStderr( DdManager * dd, FILE * fp ); extern unsigned int Cudd_ReadNextReordering( DdManager * dd ); extern void Cudd_SetNextReordering( DdManager * dd, unsigned int next ); extern double Cudd_ReadSwapSteps( DdManager * dd ); extern unsigned int Cudd_ReadMaxLive( DdManager * dd ); extern void Cudd_SetMaxLive( DdManager * dd, unsigned int maxLive ); extern unsigned long Cudd_ReadMaxMemory( DdManager * dd ); extern void Cudd_SetMaxMemory( DdManager * dd, unsigned long maxMemory ); extern int Cudd_bddBindVar( DdManager * dd, int index ); extern int Cudd_bddUnbindVar( DdManager * dd, int index ); extern int Cudd_bddVarIsBound( DdManager * dd, int index ); extern DdNode * Cudd_addExistAbstract( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * Cudd_addUnivAbstract( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * Cudd_addOrAbstract( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * Cudd_addApply( DdManager * dd, DdNode * ( * )(DdManager * , DdNode ** , DdNode ** ), DdNode * f, DdNode * g ); extern DdNode * Cudd_addPlus( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addTimes( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addThreshold( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addSetNZ( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addDivide( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addMinus( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addMinimum( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addMaximum( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addOneZeroMaximum( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addDiff( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addAgreement( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addOr( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addNand( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addNor( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addXor( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addXnor( DdManager * dd, DdNode ** f, DdNode ** g ); extern DdNode * Cudd_addMonadicApply( DdManager * dd, DdNode * ( * op)(DdManager * , DdNode * ), DdNode * f ); extern DdNode * Cudd_addLog( DdManager * dd, DdNode * f ); extern DdNode * Cudd_addFindMax( DdManager * dd, DdNode * f ); extern DdNode * Cudd_addFindMin( DdManager * dd, DdNode * f ); extern DdNode * Cudd_addIthBit( DdManager * dd, DdNode * f, int bit ); extern DdNode * Cudd_addScalarInverse( DdManager * dd, DdNode * f, DdNode * epsilon ); extern DdNode * Cudd_addIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * Cudd_addIteConstant( DdManager * dd, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * Cudd_addEvalConst( DdManager * dd, DdNode * f, DdNode * g ); extern int Cudd_addLeq( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_addCmpl( DdManager * dd, DdNode * f ); extern DdNode * Cudd_addNegate( DdManager * dd, DdNode * f ); extern DdNode * Cudd_addRoundOff( DdManager * dd, DdNode * f, int N ); extern DdNode * Cudd_addWalsh( DdManager * dd, DdNode ** x, DdNode ** y, int n ); extern DdNode * Cudd_addResidue( DdManager * dd, int n, int m, int options, int top ); extern DdNode * Cudd_bddAndAbstract( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube ); extern DdNode * Cudd_bddAndAbstractLimit( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, unsigned int limit ); extern int Cudd_ApaNumberOfDigits( int binaryDigits ); extern DdApaNumber Cudd_NewApaNumber( int digits ); extern void Cudd_ApaCopy( int digits, DdApaNumber source, DdApaNumber dest ); extern DdApaDigit Cudd_ApaAdd( int digits, DdApaNumber a, DdApaNumber b, DdApaNumber sum ); extern DdApaDigit Cudd_ApaSubtract( int digits, DdApaNumber a, DdApaNumber b, DdApaNumber diff ); extern DdApaDigit Cudd_ApaShortDivision( int digits, DdApaNumber dividend, DdApaDigit divisor, DdApaNumber quotient ); extern unsigned int Cudd_ApaIntDivision( int digits, DdApaNumber dividend, unsigned int divisor, DdApaNumber quotient ); extern void Cudd_ApaShiftRight( int digits, DdApaDigit in, DdApaNumber a, DdApaNumber b ); extern void Cudd_ApaSetToLiteral( int digits, DdApaNumber number, DdApaDigit literal ); extern void Cudd_ApaPowerOfTwo( int digits, DdApaNumber number, int power ); extern int Cudd_ApaCompare( int digitsFirst, DdApaNumber first, int digitsSecond, DdApaNumber second ); extern int Cudd_ApaCompareRatios( int digitsFirst, DdApaNumber firstNum, unsigned int firstDen, int digitsSecond, DdApaNumber secondNum, unsigned int secondDen ); extern int Cudd_ApaPrintHex( FILE * fp, int digits, DdApaNumber number ); extern int Cudd_ApaPrintDecimal( FILE * fp, int digits, DdApaNumber number ); extern int Cudd_ApaPrintExponential( FILE * fp, int digits, DdApaNumber number, int precision ); extern DdApaNumber Cudd_ApaCountMinterm( DdManager * manager, DdNode * node, int nvars, int * digits ); extern int Cudd_ApaPrintMinterm( FILE * fp, DdManager * dd, DdNode * node, int nvars ); extern int Cudd_ApaPrintMintermExp( FILE * fp, DdManager * dd, DdNode * node, int nvars, int precision ); extern int Cudd_ApaPrintDensity( FILE * fp, DdManager * dd, DdNode * node, int nvars ); extern DdNode * Cudd_UnderApprox( DdManager * dd, DdNode * f, int numVars, int threshold, int safe, double quality ); extern DdNode * Cudd_OverApprox( DdManager * dd, DdNode * f, int numVars, int threshold, int safe, double quality ); extern DdNode * Cudd_RemapUnderApprox( DdManager * dd, DdNode * f, int numVars, int threshold, double quality ); extern DdNode * Cudd_RemapOverApprox( DdManager * dd, DdNode * f, int numVars, int threshold, double quality ); extern DdNode * Cudd_BiasedUnderApprox( DdManager * dd, DdNode * f, DdNode * b, int numVars, int threshold, double quality1, double quality0 ); extern DdNode * Cudd_BiasedOverApprox( DdManager * dd, DdNode * f, DdNode * b, int numVars, int threshold, double quality1, double quality0 ); extern DdNode * Cudd_bddExistAbstract( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * Cudd_bddXorExistAbstract( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube ); extern DdNode * Cudd_bddUnivAbstract( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * Cudd_bddBooleanDiff( DdManager * manager, DdNode * f, int x ); extern int Cudd_bddVarIsDependent( DdManager * dd, DdNode * f, DdNode * var ); extern double Cudd_bddCorrelation( DdManager * manager, DdNode * f, DdNode * g ); extern double Cudd_bddCorrelationWeights( DdManager * manager, DdNode * f, DdNode * g, double * prob ); extern DdNode * Cudd_bddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * Cudd_bddIteConstant( DdManager * dd, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * Cudd_bddIntersect( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_bddAnd( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_bddAndLimit( DdManager * dd, DdNode * f, DdNode * g, unsigned int limit ); extern DdNode * Cudd_bddOr( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_bddNand( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_bddNor( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_bddXor( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_bddXnor( DdManager * dd, DdNode * f, DdNode * g ); extern int Cudd_bddLeq( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_addBddThreshold( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE value ); extern DdNode * Cudd_addBddStrictThreshold( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE value ); extern DdNode * Cudd_addBddInterval( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE lower, CUDD_VALUE_TYPE upper ); extern DdNode * Cudd_addBddIthBit( DdManager * dd, DdNode * f, int bit ); extern DdNode * Cudd_BddToAdd( DdManager * dd, DdNode * B ); extern DdNode * Cudd_addBddPattern( DdManager * dd, DdNode * f ); extern DdNode * Cudd_bddTransfer( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); extern int Cudd_DebugCheck( DdManager * table ); extern int Cudd_CheckKeys( DdManager * table ); extern DdNode * Cudd_bddClippingAnd( DdManager * dd, DdNode * f, DdNode * g, int maxDepth, int direction ); extern DdNode * Cudd_bddClippingAndAbstract( DdManager * dd, DdNode * f, DdNode * g, DdNode * cube, int maxDepth, int direction ); extern DdNode * Cudd_Cofactor( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_bddCompose( DdManager * dd, DdNode * f, DdNode * g, int v ); extern DdNode * Cudd_addCompose( DdManager * dd, DdNode * f, DdNode * g, int v ); extern DdNode * Cudd_addPermute( DdManager * manager, DdNode * node, int * permut ); extern DdNode * Cudd_addSwapVariables( DdManager * dd, DdNode * f, DdNode ** x, DdNode ** y, int n ); extern DdNode * Cudd_bddPermute( DdManager * manager, DdNode * node, int * permut ); extern DdNode * Cudd_bddVarMap( DdManager * manager, DdNode * f ); extern int Cudd_SetVarMap( DdManager * manager, DdNode ** x, DdNode ** y, int n ); extern DdNode * Cudd_bddSwapVariables( DdManager * dd, DdNode * f, DdNode ** x, DdNode ** y, int n ); extern DdNode * Cudd_bddAdjPermuteX( DdManager * dd, DdNode * B, DdNode ** x, int n ); extern DdNode * Cudd_addVectorCompose( DdManager * dd, DdNode * f, DdNode ** vector ); extern DdNode * Cudd_addGeneralVectorCompose( DdManager * dd, DdNode * f, DdNode ** vectorOn, DdNode ** vectorOff ); extern DdNode * Cudd_addNonSimCompose( DdManager * dd, DdNode * f, DdNode ** vector ); extern DdNode * Cudd_bddVectorCompose( DdManager * dd, DdNode * f, DdNode ** vector ); extern int Cudd_bddApproxConjDecomp( DdManager * dd, DdNode * f, DdNode ** * conjuncts ); extern int Cudd_bddApproxDisjDecomp( DdManager * dd, DdNode * f, DdNode ** * disjuncts ); extern int Cudd_bddIterConjDecomp( DdManager * dd, DdNode * f, DdNode ** * conjuncts ); extern int Cudd_bddIterDisjDecomp( DdManager * dd, DdNode * f, DdNode ** * disjuncts ); extern int Cudd_bddGenConjDecomp( DdManager * dd, DdNode * f, DdNode ** * conjuncts ); extern int Cudd_bddGenDisjDecomp( DdManager * dd, DdNode * f, DdNode ** * disjuncts ); extern int Cudd_bddVarConjDecomp( DdManager * dd, DdNode * f, DdNode ** * conjuncts ); extern int Cudd_bddVarDisjDecomp( DdManager * dd, DdNode * f, DdNode ** * disjuncts ); extern DdNode * Cudd_FindEssential( DdManager * dd, DdNode * f ); extern int Cudd_bddIsVarEssential( DdManager * manager, DdNode * f, int id, int phase ); extern DdTlcInfo * Cudd_FindTwoLiteralClauses( DdManager * dd, DdNode * f ); extern int Cudd_PrintTwoLiteralClauses( DdManager * dd, DdNode * f, char ** names, FILE * fp ); extern int Cudd_ReadIthClause( DdTlcInfo * tlc, int i, DdHalfWord * var1, DdHalfWord * var2, int * phase1, int * phase2 ); extern void Cudd_tlcInfoFree( DdTlcInfo * t ); extern int Cudd_DumpBlif( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, char * mname, FILE * fp, int mv ); extern int Cudd_DumpBlifBody( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp, int mv ); extern int Cudd_DumpDot( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp ); extern int Cudd_DumpDaVinci( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp ); extern int Cudd_DumpDDcal( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp ); extern int Cudd_DumpFactoredForm( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp ); extern DdNode * Cudd_bddConstrain( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * Cudd_bddRestrict( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * Cudd_bddNPAnd( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * Cudd_addConstrain( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode ** Cudd_bddConstrainDecomp( DdManager * dd, DdNode * f ); extern DdNode * Cudd_addRestrict( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode ** Cudd_bddCharToVect( DdManager * dd, DdNode * f ); extern DdNode * Cudd_bddLICompaction( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * Cudd_bddSqueeze( DdManager * dd, DdNode * l, DdNode * u ); extern DdNode * Cudd_bddMinimize( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * Cudd_SubsetCompress( DdManager * dd, DdNode * f, int nvars, int threshold ); extern DdNode * Cudd_SupersetCompress( DdManager * dd, DdNode * f, int nvars, int threshold ); extern MtrNode * Cudd_MakeTreeNode( DdManager * dd, unsigned int low, unsigned int size, unsigned int type ); extern int Cudd_addHarwell( FILE * fp, DdManager * dd, DdNode ** E, DdNode ** * x, DdNode ** * y, DdNode ** * xn, DdNode ** * yn_, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy, int pr ); extern DdManager * Cudd_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory ); extern void Cudd_Quit( DdManager * unique ); extern int Cudd_PrintLinear( DdManager * table ); extern int Cudd_ReadLinear( DdManager * table, int x, int y ); extern DdNode * Cudd_bddLiteralSetIntersection( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_addMatrixMultiply( DdManager * dd, DdNode * A, DdNode * B, DdNode ** z, int nz ); extern DdNode * Cudd_addTimesPlus( DdManager * dd, DdNode * A, DdNode * B, DdNode ** z, int nz ); extern DdNode * Cudd_addTriangle( DdManager * dd, DdNode * f, DdNode * g, DdNode ** z, int nz ); extern DdNode * Cudd_addOuterSum( DdManager * dd, DdNode * M, DdNode * r, DdNode * c ); extern DdNode * Cudd_PrioritySelect( DdManager * dd, DdNode * R, DdNode ** x, DdNode ** y, DdNode ** z, DdNode * Pi, int n, DdNode * ( * )(DdManager * , int, DdNode ** , DdNode ** , DdNode ** ) ); extern DdNode * Cudd_Xgty( DdManager * dd, int N, DdNode ** z, DdNode ** x, DdNode ** y ); extern DdNode * Cudd_Xeqy( DdManager * dd, int N, DdNode ** x, DdNode ** y ); extern DdNode * Cudd_addXeqy( DdManager * dd, int N, DdNode ** x, DdNode ** y ); extern DdNode * Cudd_Dxygtdxz( DdManager * dd, int N, DdNode ** x, DdNode ** y, DdNode ** z ); extern DdNode * Cudd_Dxygtdyz( DdManager * dd, int N, DdNode ** x, DdNode ** y, DdNode ** z ); extern DdNode * Cudd_Inequality( DdManager * dd, int N, int c, DdNode ** x, DdNode ** y ); extern DdNode * Cudd_Disequality( DdManager * dd, int N, int c, DdNode ** x, DdNode ** y ); extern DdNode * Cudd_bddInterval( DdManager * dd, int N, DdNode ** x, unsigned int lowerB, unsigned int upperB ); extern DdNode * Cudd_CProjection( DdManager * dd, DdNode * R, DdNode * Y ); extern DdNode * Cudd_addHamming( DdManager * dd, DdNode ** xVars, DdNode ** yVars, int nVars ); extern int Cudd_MinHammingDist( DdManager * dd, DdNode * f, int * minterm, int upperBound ); extern DdNode * Cudd_bddClosestCube( DdManager * dd, DdNode * f, DdNode * g, int * distance ); extern int Cudd_addRead( FILE * fp, DdManager * dd, DdNode ** E, DdNode ** * x, DdNode ** * y, DdNode ** * xn, DdNode ** * yn_, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy ); extern int Cudd_bddRead( FILE * fp, DdManager * dd, DdNode ** E, DdNode ** * x, DdNode ** * y, int * nx, int * ny, int * m, int * n, int bx, int sx, int by, int sy ); extern void Cudd_Ref( DdNode * n ); extern void Cudd_RecursiveDeref( DdManager * table, DdNode * n ); extern void Cudd_IterDerefBdd( DdManager * table, DdNode * n ); extern void Cudd_DelayedDerefBdd( DdManager * table, DdNode * n ); extern void Cudd_RecursiveDerefZdd( DdManager * table, DdNode * n ); extern void Cudd_Deref( DdNode * node ); extern int Cudd_CheckZeroRef( DdManager * manager ); extern int Cudd_ReduceHeap( DdManager * table, Cudd_ReorderingType heuristic, int minsize ); extern int Cudd_ShuffleHeap( DdManager * table, int * permutation ); extern DdNode * Cudd_Eval( DdManager * dd, DdNode * f, int * inputs ); extern DdNode * Cudd_ShortestPath( DdManager * manager, DdNode * f, int * weight, int * support, int * length ); extern DdNode * Cudd_LargestCube( DdManager * manager, DdNode * f, int * length ); extern int Cudd_ShortestLength( DdManager * manager, DdNode * f, int * weight ); extern DdNode * Cudd_Decreasing( DdManager * dd, DdNode * f, int i ); extern DdNode * Cudd_Increasing( DdManager * dd, DdNode * f, int i ); extern int Cudd_EquivDC( DdManager * dd, DdNode * F, DdNode * G, DdNode * D ); extern int Cudd_bddLeqUnless( DdManager * dd, DdNode * f, DdNode * g, DdNode * D ); extern int Cudd_EqualSupNorm( DdManager * dd, DdNode * f, DdNode * g, CUDD_VALUE_TYPE tolerance, int pr ); extern DdNode * Cudd_bddMakePrime( DdManager * dd, DdNode * cube, DdNode * f ); extern double * Cudd_CofMinterm( DdManager * dd, DdNode * node ); extern DdNode * Cudd_SolveEqn( DdManager * bdd, DdNode * F, DdNode * Y, DdNode ** G, int ** yIndex, int n ); extern DdNode * Cudd_VerifySol( DdManager * bdd, DdNode * F, DdNode ** G, int * yIndex, int n ); extern DdNode * Cudd_SplitSet( DdManager * manager, DdNode * S, DdNode ** xVars, int n, double m ); extern DdNode * Cudd_SubsetHeavyBranch( DdManager * dd, DdNode * f, int numVars, int threshold ); extern DdNode * Cudd_SupersetHeavyBranch( DdManager * dd, DdNode * f, int numVars, int threshold ); extern DdNode * Cudd_SubsetShortPaths( DdManager * dd, DdNode * f, int numVars, int threshold, int hardlimit ); extern DdNode * Cudd_SupersetShortPaths( DdManager * dd, DdNode * f, int numVars, int threshold, int hardlimit ); extern void Cudd_SymmProfile( DdManager * table, int lower, int upper ); extern unsigned int Cudd_Prime( unsigned int p ); extern int Cudd_PrintMinterm( DdManager * manager, DdNode * node ); extern int Cudd_bddPrintCover( DdManager * dd, DdNode * l, DdNode * u ); extern int Cudd_PrintDebug( DdManager * dd, DdNode * f, int n, int pr ); extern int Cudd_DagSize( DdNode * node ); extern int Cudd_EstimateCofactor( DdManager * dd, DdNode * node, int i, int phase ); extern int Cudd_EstimateCofactorSimple( DdNode * node, int i ); extern int Cudd_SharingSize( DdNode ** nodeArray, int n ); extern double Cudd_CountMinterm( DdManager * manager, DdNode * node, int nvars ); extern int Cudd_EpdCountMinterm( DdManager * manager, DdNode * node, int nvars, EpDouble * epd ); extern double Cudd_CountPath( DdNode * node ); extern double Cudd_CountPathsToNonZero( DdNode * node ); extern DdNode * Cudd_Support( DdManager * dd, DdNode * f ); extern int * Cudd_SupportIndex( DdManager * dd, DdNode * f ); extern int Cudd_SupportSize( DdManager * dd, DdNode * f ); extern DdNode * Cudd_VectorSupport( DdManager * dd, DdNode ** F, int n ); extern int * Cudd_VectorSupportIndex( DdManager * dd, DdNode ** F, int n ); extern int Cudd_VectorSupportSize( DdManager * dd, DdNode ** F, int n ); extern int Cudd_ClassifySupport( DdManager * dd, DdNode * f, DdNode * g, DdNode ** common, DdNode ** onlyF, DdNode ** onlyG ); extern int Cudd_CountLeaves( DdNode * node ); extern int Cudd_bddPickOneCube( DdManager * ddm, DdNode * node, char * string ); extern DdNode * Cudd_bddPickOneMinterm( DdManager * dd, DdNode * f, DdNode ** vars, int n ); extern DdNode ** Cudd_bddPickArbitraryMinterms( DdManager * dd, DdNode * f, DdNode ** vars, int n, int k ); extern DdNode * Cudd_SubsetWithMaskVars( DdManager * dd, DdNode * f, DdNode ** vars, int nvars, DdNode ** maskVars, int mvars ); extern DdGen * Cudd_FirstCube( DdManager * dd, DdNode * f, int ** cube, CUDD_VALUE_TYPE * value ); extern int Cudd_NextCube( DdGen * gen, int ** cube, CUDD_VALUE_TYPE * value ); extern DdGen * Cudd_FirstPrime(DdManager * dd, DdNode * l, DdNode * u, int ** cube ); extern int Cudd_NextPrime(DdGen * gen, int ** cube ); extern DdNode * Cudd_bddComputeCube( DdManager * dd, DdNode ** vars, int * phase, int n ); extern DdNode * Cudd_addComputeCube( DdManager * dd, DdNode ** vars, int * phase, int n ); extern DdNode * Cudd_CubeArrayToBdd( DdManager * dd, int * array ); extern int Cudd_BddToCubeArray( DdManager * dd, DdNode * cube, int * array ); extern DdGen * Cudd_FirstNode( DdManager * dd, DdNode * f, DdNode ** node ); extern int Cudd_NextNode( DdGen * gen, DdNode ** node ); extern int Cudd_GenFree( DdGen * gen ); extern int Cudd_IsGenEmpty( DdGen * gen ); extern DdNode * Cudd_IndicesToCube( DdManager * dd, int * array, int n ); extern void Cudd_PrintVersion( FILE * fp ); extern double Cudd_AverageDistance( DdManager * dd ); extern long Cudd_Random( void ); extern void Cudd_Srandom( long seed ); extern double Cudd_Density( DdManager * dd, DdNode * f, int nvars ); extern void Cudd_OutOfMem( long size ); extern int Cudd_zddCount( DdManager * zdd, DdNode * P ); extern double Cudd_zddCountDouble( DdManager * zdd, DdNode * P ); extern DdNode * Cudd_zddProduct( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_zddUnateProduct( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_zddWeakDiv( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_zddDivide( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_zddWeakDivF( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_zddDivideF( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * Cudd_zddComplement( DdManager * dd, DdNode * node ); extern MtrNode * Cudd_MakeZddTreeNode( DdManager * dd, unsigned int low, unsigned int size, unsigned int type ); extern DdNode * Cudd_zddIsop( DdManager * dd, DdNode * L, DdNode * U, DdNode ** zdd_I ); extern DdNode * Cudd_bddIsop( DdManager * dd, DdNode * L, DdNode * U ); extern DdNode * Cudd_MakeBddFromZddCover( DdManager * dd, DdNode * node ); extern int Cudd_zddDagSize( DdNode * p_node ); extern double Cudd_zddCountMinterm( DdManager * zdd, DdNode * node, int path ); extern void Cudd_zddPrintSubtable( DdManager * table ); extern DdNode * Cudd_zddPortFromBdd( DdManager * dd, DdNode * B ); extern DdNode * Cudd_zddPortToBdd( DdManager * dd, DdNode * f ); extern int Cudd_zddReduceHeap( DdManager * table, Cudd_ReorderingType heuristic, int minsize ); extern int Cudd_zddShuffleHeap( DdManager * table, int * permutation ); extern DdNode * Cudd_zddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * Cudd_zddUnion( DdManager * dd, DdNode * P, DdNode * Q ); extern DdNode * Cudd_zddIntersect( DdManager * dd, DdNode * P, DdNode * Q ); extern DdNode * Cudd_zddDiff( DdManager * dd, DdNode * P, DdNode * Q ); extern DdNode * Cudd_zddDiffConst( DdManager * zdd, DdNode * P, DdNode * Q ); extern DdNode * Cudd_zddSubset1( DdManager * dd, DdNode * P, int var ); extern DdNode * Cudd_zddSubset0( DdManager * dd, DdNode * P, int var ); extern DdNode * Cudd_zddChange( DdManager * dd, DdNode * P, int var ); extern void Cudd_zddSymmProfile( DdManager * table, int lower, int upper ); extern int Cudd_zddPrintMinterm( DdManager * zdd, DdNode * node ); extern int Cudd_zddPrintCover( DdManager * zdd, DdNode * node ); extern int Cudd_zddPrintDebug( DdManager * zdd, DdNode * f, int n, int pr ); extern DdGen * Cudd_zddFirstPath( DdManager * zdd, DdNode * f, int ** path ); extern int Cudd_zddNextPath( DdGen * gen, int ** path ); extern char * Cudd_zddCoverPathToString( DdManager * zdd, int * path, char * str ); extern int Cudd_zddDumpDot( DdManager * dd, int n, DdNode ** f, char ** inames, char ** onames, FILE * fp ); extern int Cudd_bddSetPiVar( DdManager * dd, int index ); extern int Cudd_bddSetPsVar( DdManager * dd, int index ); extern int Cudd_bddSetNsVar( DdManager * dd, int index ); extern int Cudd_bddIsPiVar( DdManager * dd, int index ); extern int Cudd_bddIsPsVar( DdManager * dd, int index ); extern int Cudd_bddIsNsVar( DdManager * dd, int index ); extern int Cudd_bddSetPairIndex( DdManager * dd, int index, int pairIndex ); extern int Cudd_bddReadPairIndex( DdManager * dd, int index ); extern int Cudd_bddSetVarToBeGrouped( DdManager * dd, int index ); extern int Cudd_bddSetVarHardGroup( DdManager * dd, int index ); extern int Cudd_bddResetVarToBeGrouped( DdManager * dd, int index ); extern int Cudd_bddIsVarToBeGrouped( DdManager * dd, int index ); extern int Cudd_bddSetVarToBeUngrouped( DdManager * dd, int index ); extern int Cudd_bddIsVarToBeUngrouped( DdManager * dd, int index ); extern int Cudd_bddIsVarHardGroup( DdManager * dd, int index ); /**AutomaticEnd***************************************************************/ ABC_NAMESPACE_HEADER_END #endif /* _CUDD */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cudd.make000066400000000000000000000035541300674244400232710ustar00rootroot00000000000000CSRC += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c\ cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \ cuddExport.c cuddGenCof.c cuddGenetic.c \ cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ cuddLCache.c cuddLevelQ.c \ cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \ cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c HEADERS += cudd.h cuddInt.h MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \ doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \ doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \ doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \ doc/node1.html doc/node2.html doc/node3.html doc/node4.html \ doc/node5.html doc/node6.html doc/node7.html doc/node8.html \ doc/icons/change_begin.gif \ doc/icons/change_delete.gif \ doc/icons/change_end.gif \ doc/icons/contents_motif.gif \ doc/icons/cross_ref_motif.gif \ doc/icons/foot_motif.gif \ doc/icons/image.gif \ doc/icons/index_motif.gif \ doc/icons/next_group_motif.gif \ doc/icons/next_group_motif_gr.gif \ doc/icons/next_motif.gif \ doc/icons/next_motif_gr.gif \ doc/icons/previous_group_motif.gif \ doc/icons/previous_group_motif_gr.gif \ doc/icons/previous_motif.gif \ doc/icons/previous_motif_gr.gif \ doc/icons/up_motif.gif \ doc/icons/up_motif_gr.gif DEPENDENCYFILES = $(CSRC) berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAPI.c000066400000000000000000003773621300674244400231430ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAPI.c] PackageName [cudd] Synopsis [Application interface functions.] Description [External procedures included in this module:

  • Cudd_addNewVar()
  • Cudd_addNewVarAtLevel()
  • Cudd_bddNewVar()
  • Cudd_bddNewVarAtLevel()
  • Cudd_addIthVar()
  • Cudd_bddIthVar()
  • Cudd_zddIthVar()
  • Cudd_zddVarsFromBddVars()
  • Cudd_addConst()
  • Cudd_IsNonConstant()
  • Cudd_AutodynEnable()
  • Cudd_AutodynDisable()
  • Cudd_ReorderingStatus()
  • Cudd_AutodynEnableZdd()
  • Cudd_AutodynDisableZdd()
  • Cudd_ReorderingStatusZdd()
  • Cudd_zddRealignmentEnabled()
  • Cudd_zddRealignEnable()
  • Cudd_zddRealignDisable()
  • Cudd_bddRealignmentEnabled()
  • Cudd_bddRealignEnable()
  • Cudd_bddRealignDisable()
  • Cudd_ReadOne()
  • Cudd_ReadZddOne()
  • Cudd_ReadZero()
  • Cudd_ReadLogicZero()
  • Cudd_ReadPlusInfinity()
  • Cudd_ReadMinusInfinity()
  • Cudd_ReadBackground()
  • Cudd_SetBackground()
  • Cudd_ReadCacheSlots()
  • Cudd_ReadCacheUsedSlots()
  • Cudd_ReadCacheLookUps()
  • Cudd_ReadCacheHits()
  • Cudd_ReadMinHit()
  • Cudd_SetMinHit()
  • Cudd_ReadLooseUpTo()
  • Cudd_SetLooseUpTo()
  • Cudd_ReadMaxCache()
  • Cudd_ReadMaxCacheHard()
  • Cudd_SetMaxCacheHard()
  • Cudd_ReadSize()
  • Cudd_ReadSlots()
  • Cudd_ReadUsedSlots()
  • Cudd_ExpectedUsedSlots()
  • Cudd_ReadKeys()
  • Cudd_ReadDead()
  • Cudd_ReadMinDead()
  • Cudd_ReadReorderings()
  • Cudd_ReadReorderingTime()
  • Cudd_ReadGarbageCollections()
  • Cudd_ReadGarbageCollectionTime()
  • Cudd_ReadNodesFreed()
  • Cudd_ReadNodesDropped()
  • Cudd_ReadUniqueLookUps()
  • Cudd_ReadUniqueLinks()
  • Cudd_ReadSiftMaxVar()
  • Cudd_SetSiftMaxVar()
  • Cudd_ReadMaxGrowth()
  • Cudd_SetMaxGrowth()
  • Cudd_ReadMaxGrowthAlternate()
  • Cudd_SetMaxGrowthAlternate()
  • Cudd_ReadReorderingCycle()
  • Cudd_SetReorderingCycle()
  • Cudd_ReadTree()
  • Cudd_SetTree()
  • Cudd_FreeTree()
  • Cudd_ReadZddTree()
  • Cudd_SetZddTree()
  • Cudd_FreeZddTree()
  • Cudd_NodeReadIndex()
  • Cudd_ReadPerm()
  • Cudd_ReadInvPerm()
  • Cudd_ReadVars()
  • Cudd_ReadEpsilon()
  • Cudd_SetEpsilon()
  • Cudd_ReadGroupCheck()
  • Cudd_SetGroupcheck()
  • Cudd_GarbageCollectionEnabled()
  • Cudd_EnableGarbageCollection()
  • Cudd_DisableGarbageCollection()
  • Cudd_DeadAreCounted()
  • Cudd_TurnOnCountDead()
  • Cudd_TurnOffCountDead()
  • Cudd_ReadRecomb()
  • Cudd_SetRecomb()
  • Cudd_ReadSymmviolation()
  • Cudd_SetSymmviolation()
  • Cudd_ReadArcviolation()
  • Cudd_SetArcviolation()
  • Cudd_ReadPopulationSize()
  • Cudd_SetPopulationSize()
  • Cudd_ReadNumberXovers()
  • Cudd_SetNumberXovers()
  • Cudd_ReadMemoryInUse()
  • Cudd_PrintInfo()
  • Cudd_ReadPeakNodeCount()
  • Cudd_ReadPeakLiveNodeCount()
  • Cudd_ReadNodeCount()
  • Cudd_zddReadNodeCount()
  • Cudd_AddHook()
  • Cudd_RemoveHook()
  • Cudd_IsInHook()
  • Cudd_StdPreReordHook()
  • Cudd_StdPostReordHook()
  • Cudd_EnableReorderingReporting()
  • Cudd_DisableReorderingReporting()
  • Cudd_ReorderingReporting()
  • Cudd_ReadErrorCode()
  • Cudd_ClearErrorCode()
  • Cudd_ReadStdout()
  • Cudd_SetStdout()
  • Cudd_ReadStderr()
  • Cudd_SetStderr()
  • Cudd_ReadNextReordering()
  • Cudd_SetNextReordering()
  • Cudd_ReadSwapSteps()
  • Cudd_ReadMaxLive()
  • Cudd_SetMaxLive()
  • Cudd_ReadMaxMemory()
  • Cudd_SetMaxMemory()
  • Cudd_bddBindVar()
  • Cudd_bddUnbindVar()
  • Cudd_bddVarIsBound()
  • Cudd_bddSetPiVar()
  • Cudd_bddSetPsVar()
  • Cudd_bddSetNsVar()
  • Cudd_bddIsPiVar()
  • Cudd_bddIsPsVar()
  • Cudd_bddIsNsVar()
  • Cudd_bddSetPairIndex()
  • Cudd_bddReadPairIndex()
  • Cudd_bddSetVarToBeGrouped()
  • Cudd_bddSetVarHardGroup()
  • Cudd_bddResetVarToBeGrouped()
  • Cudd_bddIsVarToBeGrouped()
  • Cudd_bddSetVarToBeUngrouped()
  • Cudd_bddIsVarToBeUngrouped()
  • Cudd_bddIsVarHardGroup()
Static procedures included in this module:
  • fixVarTree()
] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAPI.c,v 1.59 2009/02/19 16:14:14 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void fixVarTree (MtrNode *treenode, int *perm, int size); static int addMultiplicityGroups (DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Returns a new ADD variable.] Description [Creates a new ADD variable. The new variable has an index equal to the largest previous index plus 1. Returns a pointer to the new variable if successful; NULL otherwise. An ADD variable differs from a BDD variable because it points to the arithmetic zero, instead of having a complement pointer to 1. ] SideEffects [None] SeeAlso [Cudd_bddNewVar Cudd_addIthVar Cudd_addConst Cudd_addNewVarAtLevel] ******************************************************************************/ DdNode * Cudd_addNewVar( DdManager * dd) { DdNode *res; if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); do { dd->reordered = 0; res = cuddUniqueInter(dd,dd->size,DD_ONE(dd),DD_ZERO(dd)); } while (dd->reordered == 1); return(res); } /* end of Cudd_addNewVar */ /**Function******************************************************************** Synopsis [Returns a new ADD variable at a specified level.] Description [Creates a new ADD variable. The new variable has an index equal to the largest previous index plus 1 and is positioned at the specified level in the order. Returns a pointer to the new variable if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel] ******************************************************************************/ DdNode * Cudd_addNewVarAtLevel( DdManager * dd, int level) { DdNode *res; if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); if (level >= dd->size) return(Cudd_addIthVar(dd,level)); if (!cuddInsertSubtables(dd,1,level)) return(NULL); do { dd->reordered = 0; res = cuddUniqueInter(dd,dd->size - 1,DD_ONE(dd),DD_ZERO(dd)); } while (dd->reordered == 1); return(res); } /* end of Cudd_addNewVarAtLevel */ /**Function******************************************************************** Synopsis [Returns a new BDD variable.] Description [Creates a new BDD variable. The new variable has an index equal to the largest previous index plus 1. Returns a pointer to the new variable if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel] ******************************************************************************/ DdNode * Cudd_bddNewVar( DdManager * dd) { DdNode *res; if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); res = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one)); return(res); } /* end of Cudd_bddNewVar */ /**Function******************************************************************** Synopsis [Returns a new BDD variable at a specified level.] Description [Creates a new BDD variable. The new variable has an index equal to the largest previous index plus 1 and is positioned at the specified level in the order. Returns a pointer to the new variable if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddNewVar Cudd_bddIthVar Cudd_addNewVarAtLevel] ******************************************************************************/ DdNode * Cudd_bddNewVarAtLevel( DdManager * dd, int level) { DdNode *res; if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); if (level >= dd->size) return(Cudd_bddIthVar(dd,level)); if (!cuddInsertSubtables(dd,1,level)) return(NULL); res = dd->vars[dd->size - 1]; return(res); } /* end of Cudd_bddNewVarAtLevel */ /**Function******************************************************************** Synopsis [Returns the ADD variable with index i.] Description [Retrieves the ADD variable with index i if it already exists, or creates a new ADD variable. Returns a pointer to the variable if successful; NULL otherwise. An ADD variable differs from a BDD variable because it points to the arithmetic zero, instead of having a complement pointer to 1. ] SideEffects [None] SeeAlso [Cudd_addNewVar Cudd_bddIthVar Cudd_addConst Cudd_addNewVarAtLevel] ******************************************************************************/ DdNode * Cudd_addIthVar( DdManager * dd, int i) { DdNode *res; if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); do { dd->reordered = 0; res = cuddUniqueInter(dd,i,DD_ONE(dd),DD_ZERO(dd)); } while (dd->reordered == 1); return(res); } /* end of Cudd_addIthVar */ /**Function******************************************************************** Synopsis [Returns the BDD variable with index i.] Description [Retrieves the BDD variable with index i if it already exists, or creates a new BDD variable. Returns a pointer to the variable if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel Cudd_ReadVars] ******************************************************************************/ DdNode * Cudd_bddIthVar( DdManager * dd, int i) { DdNode *res; if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); if (i < dd->size) { res = dd->vars[i]; } else { res = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); } return(res); } /* end of Cudd_bddIthVar */ /**Function******************************************************************** Synopsis [Returns the ZDD variable with index i.] Description [Retrieves the ZDD variable with index i if it already exists, or creates a new ZDD variable. Returns a pointer to the variable if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddIthVar Cudd_addIthVar] ******************************************************************************/ DdNode * Cudd_zddIthVar( DdManager * dd, int i) { DdNode *res; DdNode *zvar; DdNode *lower; int j; if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); /* The i-th variable function has the following structure: ** at the level corresponding to index i there is a node whose "then" ** child points to the universe, and whose "else" child points to zero. ** Above that level there are nodes with identical children. */ /* First we build the node at the level of index i. */ lower = (i < dd->sizeZ - 1) ? dd->univ[dd->permZ[i]+1] : DD_ONE(dd); do { dd->reordered = 0; zvar = cuddUniqueInterZdd(dd, i, lower, DD_ZERO(dd)); } while (dd->reordered == 1); if (zvar == NULL) return(NULL); cuddRef(zvar); /* Now we add the "filler" nodes above the level of index i. */ for (j = dd->permZ[i] - 1; j >= 0; j--) { do { dd->reordered = 0; res = cuddUniqueInterZdd(dd, dd->invpermZ[j], zvar, zvar); } while (dd->reordered == 1); if (res == NULL) { Cudd_RecursiveDerefZdd(dd,zvar); return(NULL); } cuddRef(res); Cudd_RecursiveDerefZdd(dd,zvar); zvar = res; } cuddDeref(zvar); return(zvar); } /* end of Cudd_zddIthVar */ /**Function******************************************************************** Synopsis [Creates one or more ZDD variables for each BDD variable.] Description [Creates one or more ZDD variables for each BDD variable. If some ZDD variables already exist, only the missing variables are created. Parameter multiplicity allows the caller to control how many variables are created for each BDD variable in existence. For instance, if ZDDs are used to represent covers, two ZDD variables are required for each BDD variable. The order of the BDD variables is transferred to the ZDD variables. If a variable group tree exists for the BDD variables, a corresponding ZDD variable group tree is created by expanding the BDD variable tree. In any case, the ZDD variables derived from the same BDD variable are merged in a ZDD variable group. If a ZDD variable group tree exists, it is freed. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_bddNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel] ******************************************************************************/ int Cudd_zddVarsFromBddVars( DdManager * dd /* DD manager */, int multiplicity /* how many ZDD variables are created for each BDD variable */) { int res; int i, j; int allnew; int *permutation; if (multiplicity < 1) return(0); allnew = dd->sizeZ == 0; if (dd->size * multiplicity > dd->sizeZ) { res = cuddResizeTableZdd(dd,dd->size * multiplicity - 1); if (res == 0) return(0); } /* Impose the order of the BDD variables to the ZDD variables. */ if (allnew) { for (i = 0; i < dd->size; i++) { for (j = 0; j < multiplicity; j++) { dd->permZ[i * multiplicity + j] = dd->perm[i] * multiplicity + j; dd->invpermZ[dd->permZ[i * multiplicity + j]] = i * multiplicity + j; } } for (i = 0; i < dd->sizeZ; i++) { dd->univ[i]->index = dd->invpermZ[i]; } } else { permutation = ABC_ALLOC(int,dd->sizeZ); if (permutation == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < dd->size; i++) { for (j = 0; j < multiplicity; j++) { permutation[i * multiplicity + j] = dd->invperm[i] * multiplicity + j; } } for (i = dd->size * multiplicity; i < dd->sizeZ; i++) { permutation[i] = i; } res = Cudd_zddShuffleHeap(dd, permutation); ABC_FREE(permutation); if (res == 0) return(0); } /* Copy and expand the variable group tree if it exists. */ if (dd->treeZ != NULL) { Cudd_FreeZddTree(dd); } if (dd->tree != NULL) { dd->treeZ = Mtr_CopyTree(dd->tree, multiplicity); if (dd->treeZ == NULL) return(0); } else if (multiplicity > 1) { dd->treeZ = Mtr_InitGroupTree(0, dd->sizeZ); if (dd->treeZ == NULL) return(0); dd->treeZ->index = dd->invpermZ[0]; } /* Create groups for the ZDD variables derived from the same BDD variable. */ if (multiplicity > 1) { char *vmask, *lmask; vmask = ABC_ALLOC(char, dd->size); if (vmask == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } lmask = ABC_ALLOC(char, dd->size); if (lmask == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < dd->size; i++) { vmask[i] = lmask[i] = 0; } res = addMultiplicityGroups(dd,dd->treeZ,multiplicity,vmask,lmask); ABC_FREE(vmask); ABC_FREE(lmask); if (res == 0) return(0); } return(1); } /* end of Cudd_zddVarsFromBddVars */ /**Function******************************************************************** Synopsis [Returns the ADD for constant c.] Description [Retrieves the ADD for constant c if it already exists, or creates a new ADD. Returns a pointer to the ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addNewVar Cudd_addIthVar] ******************************************************************************/ DdNode * Cudd_addConst( DdManager * dd, CUDD_VALUE_TYPE c) { return(cuddUniqueConst(dd,c)); } /* end of Cudd_addConst */ /**Function******************************************************************** Synopsis [Returns 1 if a DD node is not constant.] Description [Returns 1 if a DD node is not constant. This function is useful to test the results of Cudd_bddIteConstant, Cudd_addIteConstant, Cudd_addEvalConst. These results may be a special value signifying non-constant. In the other cases the macro Cudd_IsConstant can be used.] SideEffects [None] SeeAlso [Cudd_IsConstant Cudd_bddIteConstant Cudd_addIteConstant Cudd_addEvalConst] ******************************************************************************/ int Cudd_IsNonConstant( DdNode *f) { return(f == DD_NON_CONSTANT || !Cudd_IsConstant(f)); } /* end of Cudd_IsNonConstant */ /**Function******************************************************************** Synopsis [Enables automatic dynamic reordering of BDDs and ADDs.] Description [Enables automatic dynamic reordering of BDDs and ADDs. Parameter method is used to determine the method used for reordering. If CUDD_REORDER_SAME is passed, the method is unchanged.] SideEffects [None] SeeAlso [Cudd_AutodynDisable Cudd_ReorderingStatus Cudd_AutodynEnableZdd] ******************************************************************************/ void Cudd_AutodynEnable( DdManager * unique, Cudd_ReorderingType method) { unique->autoDyn = 1; if (method != CUDD_REORDER_SAME) { unique->autoMethod = method; } #ifndef DD_NO_DEATH_ROW /* If reordering is enabled, using the death row causes too many ** invocations. Hence, we shrink the death row to just one entry. */ cuddClearDeathRow(unique); unique->deathRowDepth = 1; unique->deadMask = unique->deathRowDepth - 1; if ((unsigned) unique->nextDead > unique->deadMask) { unique->nextDead = 0; } unique->deathRow = ABC_REALLOC(DdNodePtr, unique->deathRow, unique->deathRowDepth); #endif return; } /* end of Cudd_AutodynEnable */ /**Function******************************************************************** Synopsis [Disables automatic dynamic reordering.] Description [] SideEffects [None] SeeAlso [Cudd_AutodynEnable Cudd_ReorderingStatus Cudd_AutodynDisableZdd] ******************************************************************************/ void Cudd_AutodynDisable( DdManager * unique) { unique->autoDyn = 0; return; } /* end of Cudd_AutodynDisable */ /**Function******************************************************************** Synopsis [Reports the status of automatic dynamic reordering of BDDs and ADDs.] Description [Reports the status of automatic dynamic reordering of BDDs and ADDs. Parameter method is set to the reordering method currently selected. Returns 1 if automatic reordering is enabled; 0 otherwise.] SideEffects [Parameter method is set to the reordering method currently selected.] SeeAlso [Cudd_AutodynEnable Cudd_AutodynDisable Cudd_ReorderingStatusZdd] ******************************************************************************/ int Cudd_ReorderingStatus( DdManager * unique, Cudd_ReorderingType * method) { *method = unique->autoMethod; return(unique->autoDyn); } /* end of Cudd_ReorderingStatus */ /**Function******************************************************************** Synopsis [Enables automatic dynamic reordering of ZDDs.] Description [Enables automatic dynamic reordering of ZDDs. Parameter method is used to determine the method used for reordering ZDDs. If CUDD_REORDER_SAME is passed, the method is unchanged.] SideEffects [None] SeeAlso [Cudd_AutodynDisableZdd Cudd_ReorderingStatusZdd Cudd_AutodynEnable] ******************************************************************************/ void Cudd_AutodynEnableZdd( DdManager * unique, Cudd_ReorderingType method) { unique->autoDynZ = 1; if (method != CUDD_REORDER_SAME) { unique->autoMethodZ = method; } return; } /* end of Cudd_AutodynEnableZdd */ /**Function******************************************************************** Synopsis [Disables automatic dynamic reordering of ZDDs.] Description [] SideEffects [None] SeeAlso [Cudd_AutodynEnableZdd Cudd_ReorderingStatusZdd Cudd_AutodynDisable] ******************************************************************************/ void Cudd_AutodynDisableZdd( DdManager * unique) { unique->autoDynZ = 0; return; } /* end of Cudd_AutodynDisableZdd */ /**Function******************************************************************** Synopsis [Reports the status of automatic dynamic reordering of ZDDs.] Description [Reports the status of automatic dynamic reordering of ZDDs. Parameter method is set to the ZDD reordering method currently selected. Returns 1 if automatic reordering is enabled; 0 otherwise.] SideEffects [Parameter method is set to the ZDD reordering method currently selected.] SeeAlso [Cudd_AutodynEnableZdd Cudd_AutodynDisableZdd Cudd_ReorderingStatus] ******************************************************************************/ int Cudd_ReorderingStatusZdd( DdManager * unique, Cudd_ReorderingType * method) { *method = unique->autoMethodZ; return(unique->autoDynZ); } /* end of Cudd_ReorderingStatusZdd */ /**Function******************************************************************** Synopsis [Tells whether the realignment of ZDD order to BDD order is enabled.] Description [Returns 1 if the realignment of ZDD order to BDD order is enabled; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_zddRealignEnable Cudd_zddRealignDisable Cudd_bddRealignEnable Cudd_bddRealignDisable] ******************************************************************************/ int Cudd_zddRealignmentEnabled( DdManager * unique) { return(unique->realign); } /* end of Cudd_zddRealignmentEnabled */ /**Function******************************************************************** Synopsis [Enables realignment of ZDD order to BDD order.] Description [Enables realignment of the ZDD variable order to the BDD variable order after the BDDs and ADDs have been reordered. The number of ZDD variables must be a multiple of the number of BDD variables for realignment to make sense. If this condition is not met, Cudd_ReduceHeap will return 0. Let M be the ratio of the two numbers. For the purpose of realignment, the ZDD variables from M*i to (M+1)*i-1 are reagarded as corresponding to BDD variable i. Realignment is initially disabled.] SideEffects [None] SeeAlso [Cudd_ReduceHeap Cudd_zddRealignDisable Cudd_zddRealignmentEnabled Cudd_bddRealignDisable Cudd_bddRealignmentEnabled] ******************************************************************************/ void Cudd_zddRealignEnable( DdManager * unique) { unique->realign = 1; return; } /* end of Cudd_zddRealignEnable */ /**Function******************************************************************** Synopsis [Disables realignment of ZDD order to BDD order.] Description [] SideEffects [None] SeeAlso [Cudd_zddRealignEnable Cudd_zddRealignmentEnabled Cudd_bddRealignEnable Cudd_bddRealignmentEnabled] ******************************************************************************/ void Cudd_zddRealignDisable( DdManager * unique) { unique->realign = 0; return; } /* end of Cudd_zddRealignDisable */ /**Function******************************************************************** Synopsis [Tells whether the realignment of BDD order to ZDD order is enabled.] Description [Returns 1 if the realignment of BDD order to ZDD order is enabled; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_bddRealignEnable Cudd_bddRealignDisable Cudd_zddRealignEnable Cudd_zddRealignDisable] ******************************************************************************/ int Cudd_bddRealignmentEnabled( DdManager * unique) { return(unique->realignZ); } /* end of Cudd_bddRealignmentEnabled */ /**Function******************************************************************** Synopsis [Enables realignment of BDD order to ZDD order.] Description [Enables realignment of the BDD variable order to the ZDD variable order after the ZDDs have been reordered. The number of ZDD variables must be a multiple of the number of BDD variables for realignment to make sense. If this condition is not met, Cudd_zddReduceHeap will return 0. Let M be the ratio of the two numbers. For the purpose of realignment, the ZDD variables from M*i to (M+1)*i-1 are reagarded as corresponding to BDD variable i. Realignment is initially disabled.] SideEffects [None] SeeAlso [Cudd_zddReduceHeap Cudd_bddRealignDisable Cudd_bddRealignmentEnabled Cudd_zddRealignDisable Cudd_zddRealignmentEnabled] ******************************************************************************/ void Cudd_bddRealignEnable( DdManager * unique) { unique->realignZ = 1; return; } /* end of Cudd_bddRealignEnable */ /**Function******************************************************************** Synopsis [Disables realignment of ZDD order to BDD order.] Description [] SideEffects [None] SeeAlso [Cudd_bddRealignEnable Cudd_bddRealignmentEnabled Cudd_zddRealignEnable Cudd_zddRealignmentEnabled] ******************************************************************************/ void Cudd_bddRealignDisable( DdManager * unique) { unique->realignZ = 0; return; } /* end of Cudd_bddRealignDisable */ /**Function******************************************************************** Synopsis [Returns the one constant of the manager.] Description [Returns the one constant of the manager. The one constant is common to ADDs and BDDs.] SideEffects [None] SeeAlso [Cudd_ReadZero Cudd_ReadLogicZero Cudd_ReadZddOne] ******************************************************************************/ DdNode * Cudd_ReadOne( DdManager * dd) { return(dd->one); } /* end of Cudd_ReadOne */ /**Function******************************************************************** Synopsis [Returns the ZDD for the constant 1 function.] Description [Returns the ZDD for the constant 1 function. The representation of the constant 1 function as a ZDD depends on how many variables it (nominally) depends on. The index of the topmost variable in the support is given as argument i.] SideEffects [None] SeeAlso [Cudd_ReadOne] ******************************************************************************/ DdNode * Cudd_ReadZddOne( DdManager * dd, int i) { if (i < 0) return(NULL); return(i < dd->sizeZ ? dd->univ[i] : DD_ONE(dd)); } /* end of Cudd_ReadZddOne */ /**Function******************************************************************** Synopsis [Returns the zero constant of the manager.] Description [Returns the zero constant of the manager. The zero constant is the arithmetic zero, rather than the logic zero. The latter is the complement of the one constant.] SideEffects [None] SeeAlso [Cudd_ReadOne Cudd_ReadLogicZero] ******************************************************************************/ DdNode * Cudd_ReadZero( DdManager * dd) { return(DD_ZERO(dd)); } /* end of Cudd_ReadZero */ /**Function******************************************************************** Synopsis [Returns the logic zero constant of the manager.] Description [Returns the zero constant of the manager. The logic zero constant is the complement of the one constant, and is distinct from the arithmetic zero.] SideEffects [None] SeeAlso [Cudd_ReadOne Cudd_ReadZero] ******************************************************************************/ DdNode * Cudd_ReadLogicZero( DdManager * dd) { return(Cudd_Not(DD_ONE(dd))); } /* end of Cudd_ReadLogicZero */ /**Function******************************************************************** Synopsis [Reads the plus-infinity constant from the manager.] Description [] SideEffects [None] ******************************************************************************/ DdNode * Cudd_ReadPlusInfinity( DdManager * dd) { return(dd->plusinfinity); } /* end of Cudd_ReadPlusInfinity */ /**Function******************************************************************** Synopsis [Reads the minus-infinity constant from the manager.] Description [] SideEffects [None] ******************************************************************************/ DdNode * Cudd_ReadMinusInfinity( DdManager * dd) { return(dd->minusinfinity); } /* end of Cudd_ReadMinusInfinity */ /**Function******************************************************************** Synopsis [Reads the background constant of the manager.] Description [] SideEffects [None] ******************************************************************************/ DdNode * Cudd_ReadBackground( DdManager * dd) { return(dd->background); } /* end of Cudd_ReadBackground */ /**Function******************************************************************** Synopsis [Sets the background constant of the manager.] Description [Sets the background constant of the manager. It assumes that the DdNode pointer bck is already referenced.] SideEffects [None] ******************************************************************************/ void Cudd_SetBackground( DdManager * dd, DdNode * bck) { dd->background = bck; } /* end of Cudd_SetBackground */ /**Function******************************************************************** Synopsis [Reads the number of slots in the cache.] Description [] SideEffects [None] SeeAlso [Cudd_ReadCacheUsedSlots] ******************************************************************************/ unsigned int Cudd_ReadCacheSlots( DdManager * dd) { return(dd->cacheSlots); } /* end of Cudd_ReadCacheSlots */ /**Function******************************************************************** Synopsis [Reads the fraction of used slots in the cache.] Description [Reads the fraction of used slots in the cache. The unused slots are those in which no valid data is stored. Garbage collection, variable reordering, and cache resizing may cause used slots to become unused.] SideEffects [None] SeeAlso [Cudd_ReadCacheSlots] ******************************************************************************/ double Cudd_ReadCacheUsedSlots( DdManager * dd) { unsigned long used = 0; int slots = dd->cacheSlots; DdCache *cache = dd->cache; int i; for (i = 0; i < slots; i++) { used += cache[i].h != 0; } return((double)used / (double) dd->cacheSlots); } /* end of Cudd_ReadCacheUsedSlots */ /**Function******************************************************************** Synopsis [Returns the number of cache look-ups.] Description [Returns the number of cache look-ups.] SideEffects [None] SeeAlso [Cudd_ReadCacheHits] ******************************************************************************/ double Cudd_ReadCacheLookUps( DdManager * dd) { return(dd->cacheHits + dd->cacheMisses + dd->totCachehits + dd->totCacheMisses); } /* end of Cudd_ReadCacheLookUps */ /**Function******************************************************************** Synopsis [Returns the number of cache hits.] Description [] SideEffects [None] SeeAlso [Cudd_ReadCacheLookUps] ******************************************************************************/ double Cudd_ReadCacheHits( DdManager * dd) { return(dd->cacheHits + dd->totCachehits); } /* end of Cudd_ReadCacheHits */ /**Function******************************************************************** Synopsis [Returns the number of recursive calls.] Description [Returns the number of recursive calls if the package is compiled with DD_COUNT defined.] SideEffects [None] SeeAlso [] ******************************************************************************/ double Cudd_ReadRecursiveCalls( DdManager * dd) { #ifdef DD_COUNT return(dd->recursiveCalls); #else return(-1.0); #endif } /* end of Cudd_ReadRecursiveCalls */ /**Function******************************************************************** Synopsis [Reads the hit rate that causes resizinig of the computed table.] Description [] SideEffects [None] SeeAlso [Cudd_SetMinHit] ******************************************************************************/ unsigned int Cudd_ReadMinHit( DdManager * dd) { /* Internally, the package manipulates the ratio of hits to ** misses instead of the ratio of hits to accesses. */ return((unsigned int) (0.5 + 100 * dd->minHit / (1 + dd->minHit))); } /* end of Cudd_ReadMinHit */ /**Function******************************************************************** Synopsis [Sets the hit rate that causes resizinig of the computed table.] Description [Sets the minHit parameter of the manager. This parameter controls the resizing of the computed table. If the hit rate is larger than the specified value, and the cache is not already too large, then its size is doubled.] SideEffects [None] SeeAlso [Cudd_ReadMinHit] ******************************************************************************/ void Cudd_SetMinHit( DdManager * dd, unsigned int hr) { /* Internally, the package manipulates the ratio of hits to ** misses instead of the ratio of hits to accesses. */ dd->minHit = (double) hr / (100.0 - (double) hr); } /* end of Cudd_SetMinHit */ /**Function******************************************************************** Synopsis [Reads the looseUpTo parameter of the manager.] Description [] SideEffects [None] SeeAlso [Cudd_SetLooseUpTo Cudd_ReadMinHit Cudd_ReadMinDead] ******************************************************************************/ unsigned int Cudd_ReadLooseUpTo( DdManager * dd) { return(dd->looseUpTo); } /* end of Cudd_ReadLooseUpTo */ /**Function******************************************************************** Synopsis [Sets the looseUpTo parameter of the manager.] Description [Sets the looseUpTo parameter of the manager. This parameter of the manager controls the threshold beyond which no fast growth of the unique table is allowed. The threshold is given as a number of slots. If the value passed to this function is 0, the function determines a suitable value based on the available memory.] SideEffects [None] SeeAlso [Cudd_ReadLooseUpTo Cudd_SetMinHit] ******************************************************************************/ void Cudd_SetLooseUpTo( DdManager * dd, unsigned int lut) { if (lut == 0) { unsigned long datalimit = getSoftDataLimit(); lut = (unsigned int) (datalimit / (sizeof(DdNode) * DD_MAX_LOOSE_FRACTION)); } dd->looseUpTo = lut; } /* end of Cudd_SetLooseUpTo */ /**Function******************************************************************** Synopsis [Returns the soft limit for the cache size.] Description [Returns the soft limit for the cache size. The soft limit] SideEffects [None] SeeAlso [Cudd_ReadMaxCache] ******************************************************************************/ unsigned int Cudd_ReadMaxCache( DdManager * dd) { return(2 * dd->cacheSlots + dd->cacheSlack); } /* end of Cudd_ReadMaxCache */ /**Function******************************************************************** Synopsis [Reads the maxCacheHard parameter of the manager.] Description [] SideEffects [None] SeeAlso [Cudd_SetMaxCacheHard Cudd_ReadMaxCache] ******************************************************************************/ unsigned int Cudd_ReadMaxCacheHard( DdManager * dd) { return(dd->maxCacheHard); } /* end of Cudd_ReadMaxCache */ /**Function******************************************************************** Synopsis [Sets the maxCacheHard parameter of the manager.] Description [Sets the maxCacheHard parameter of the manager. The cache cannot grow larger than maxCacheHard entries. This parameter allows an application to control the trade-off of memory versus speed. If the value passed to this function is 0, the function determines a suitable maximum cache size based on the available memory.] SideEffects [None] SeeAlso [Cudd_ReadMaxCacheHard Cudd_SetMaxCache] ******************************************************************************/ void Cudd_SetMaxCacheHard( DdManager * dd, unsigned int mc) { if (mc == 0) { unsigned long datalimit = getSoftDataLimit(); mc = (unsigned int) (datalimit / (sizeof(DdCache) * DD_MAX_CACHE_FRACTION)); } dd->maxCacheHard = mc; } /* end of Cudd_SetMaxCacheHard */ /**Function******************************************************************** Synopsis [Returns the number of BDD variables in existance.] Description [] SideEffects [None] SeeAlso [Cudd_ReadZddSize] ******************************************************************************/ int Cudd_ReadSize( DdManager * dd) { return(dd->size); } /* end of Cudd_ReadSize */ /**Function******************************************************************** Synopsis [Returns the number of ZDD variables in existance.] Description [] SideEffects [None] SeeAlso [Cudd_ReadSize] ******************************************************************************/ int Cudd_ReadZddSize( DdManager * dd) { return(dd->sizeZ); } /* end of Cudd_ReadZddSize */ /**Function******************************************************************** Synopsis [Returns the total number of slots of the unique table.] Description [Returns the total number of slots of the unique table. This number ismainly for diagnostic purposes.] SideEffects [None] ******************************************************************************/ unsigned int Cudd_ReadSlots( DdManager * dd) { return(dd->slots); } /* end of Cudd_ReadSlots */ /**Function******************************************************************** Synopsis [Reads the fraction of used slots in the unique table.] Description [Reads the fraction of used slots in the unique table. The unused slots are those in which no valid data is stored. Garbage collection, variable reordering, and subtable resizing may cause used slots to become unused.] SideEffects [None] SeeAlso [Cudd_ReadSlots] ******************************************************************************/ double Cudd_ReadUsedSlots( DdManager * dd) { unsigned long used = 0; int i, j; int size = dd->size; DdNodePtr *nodelist; DdSubtable *subtable; DdNode *node; DdNode *sentinel = &(dd->sentinel); /* Scan each BDD/ADD subtable. */ for (i = 0; i < size; i++) { subtable = &(dd->subtables[i]); nodelist = subtable->nodelist; for (j = 0; (unsigned) j < subtable->slots; j++) { node = nodelist[j]; if (node != sentinel) { used++; } } } /* Scan the ZDD subtables. */ size = dd->sizeZ; for (i = 0; i < size; i++) { subtable = &(dd->subtableZ[i]); nodelist = subtable->nodelist; for (j = 0; (unsigned) j < subtable->slots; j++) { node = nodelist[j]; if (node != NULL) { used++; } } } /* Constant table. */ subtable = &(dd->constants); nodelist = subtable->nodelist; for (j = 0; (unsigned) j < subtable->slots; j++) { node = nodelist[j]; if (node != NULL) { used++; } } return((double)used / (double) dd->slots); } /* end of Cudd_ReadUsedSlots */ /**Function******************************************************************** Synopsis [Computes the expected fraction of used slots in the unique table.] Description [Computes the fraction of slots in the unique table that should be in use. This expected value is based on the assumption that the hash function distributes the keys randomly; it can be compared with the result of Cudd_ReadUsedSlots to monitor the performance of the unique table hash function.] SideEffects [None] SeeAlso [Cudd_ReadSlots Cudd_ReadUsedSlots] ******************************************************************************/ double Cudd_ExpectedUsedSlots( DdManager * dd) { int i; int size = dd->size; DdSubtable *subtable; double empty = 0.0; /* To each subtable we apply the corollary to Theorem 8.5 (occupancy ** distribution) from Sedgewick and Flajolet's Analysis of Algorithms. ** The corollary says that for a table with M buckets and a load ratio ** of r, the expected number of empty buckets is asymptotically given ** by M * exp(-r). */ /* Scan each BDD/ADD subtable. */ for (i = 0; i < size; i++) { subtable = &(dd->subtables[i]); empty += (double) subtable->slots * exp(-(double) subtable->keys / (double) subtable->slots); } /* Scan the ZDD subtables. */ size = dd->sizeZ; for (i = 0; i < size; i++) { subtable = &(dd->subtableZ[i]); empty += (double) subtable->slots * exp(-(double) subtable->keys / (double) subtable->slots); } /* Constant table. */ subtable = &(dd->constants); empty += (double) subtable->slots * exp(-(double) subtable->keys / (double) subtable->slots); return(1.0 - empty / (double) dd->slots); } /* end of Cudd_ExpectedUsedSlots */ /**Function******************************************************************** Synopsis [Returns the number of nodes in the unique table.] Description [Returns the total number of nodes currently in the unique table, including the dead nodes.] SideEffects [None] SeeAlso [Cudd_ReadDead] ******************************************************************************/ unsigned int Cudd_ReadKeys( DdManager * dd) { return(dd->keys); } /* end of Cudd_ReadKeys */ /**Function******************************************************************** Synopsis [Returns the number of dead nodes in the unique table.] Description [] SideEffects [None] SeeAlso [Cudd_ReadKeys] ******************************************************************************/ unsigned int Cudd_ReadDead( DdManager * dd) { return(dd->dead); } /* end of Cudd_ReadDead */ /**Function******************************************************************** Synopsis [Reads the minDead parameter of the manager.] Description [Reads the minDead parameter of the manager. The minDead parameter is used by the package to decide whether to collect garbage or resize a subtable of the unique table when the subtable becomes too full. The application can indirectly control the value of minDead by setting the looseUpTo parameter.] SideEffects [None] SeeAlso [Cudd_ReadDead Cudd_ReadLooseUpTo Cudd_SetLooseUpTo] ******************************************************************************/ unsigned int Cudd_ReadMinDead( DdManager * dd) { return(dd->minDead); } /* end of Cudd_ReadMinDead */ /**Function******************************************************************** Synopsis [Returns the number of times reordering has occurred.] Description [Returns the number of times reordering has occurred in the manager. The number includes both the calls to Cudd_ReduceHeap from the application program and those automatically performed by the package. However, calls that do not even initiate reordering are not counted. A call may not initiate reordering if there are fewer than minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified as reordering method. The calls to Cudd_ShuffleHeap are not counted.] SideEffects [None] SeeAlso [Cudd_ReduceHeap Cudd_ReadReorderingTime] ******************************************************************************/ int Cudd_ReadReorderings( DdManager * dd) { return(dd->reorderings); } /* end of Cudd_ReadReorderings */ /**Function******************************************************************** Synopsis [Returns the time spent in reordering.] Description [Returns the number of milliseconds spent reordering variables since the manager was initialized. The time spent in collecting garbage before reordering is included.] SideEffects [None] SeeAlso [Cudd_ReadReorderings] ******************************************************************************/ long Cudd_ReadReorderingTime( DdManager * dd) { return(dd->reordTime); } /* end of Cudd_ReadReorderingTime */ /**Function******************************************************************** Synopsis [Returns the number of times garbage collection has occurred.] Description [Returns the number of times garbage collection has occurred in the manager. The number includes both the calls from reordering procedures and those caused by requests to create new nodes.] SideEffects [None] SeeAlso [Cudd_ReadGarbageCollectionTime] ******************************************************************************/ int Cudd_ReadGarbageCollections( DdManager * dd) { return(dd->garbageCollections); } /* end of Cudd_ReadGarbageCollections */ /**Function******************************************************************** Synopsis [Returns the time spent in garbage collection.] Description [Returns the number of milliseconds spent doing garbage collection since the manager was initialized.] SideEffects [None] SeeAlso [Cudd_ReadGarbageCollections] ******************************************************************************/ long Cudd_ReadGarbageCollectionTime( DdManager * dd) { return(dd->GCTime); } /* end of Cudd_ReadGarbageCollectionTime */ /**Function******************************************************************** Synopsis [Returns the number of nodes freed.] Description [Returns the number of nodes returned to the free list if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_STATS defined.] SideEffects [None] SeeAlso [Cudd_ReadNodesDropped] ******************************************************************************/ double Cudd_ReadNodesFreed( DdManager * dd) { #ifdef DD_STATS return(dd->nodesFreed); #else return(-1.0); #endif } /* end of Cudd_ReadNodesFreed */ /**Function******************************************************************** Synopsis [Returns the number of nodes dropped.] Description [Returns the number of nodes killed by dereferencing if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_STATS defined.] SideEffects [None] SeeAlso [Cudd_ReadNodesFreed] ******************************************************************************/ double Cudd_ReadNodesDropped( DdManager * dd) { #ifdef DD_STATS return(dd->nodesDropped); #else return(-1.0); #endif } /* end of Cudd_ReadNodesDropped */ /**Function******************************************************************** Synopsis [Returns the number of look-ups in the unique table.] Description [Returns the number of look-ups in the unique table if the keeping of this statistic is enabled; -1 otherwise. This statistic is enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.] SideEffects [None] SeeAlso [Cudd_ReadUniqueLinks] ******************************************************************************/ double Cudd_ReadUniqueLookUps( DdManager * dd) { #ifdef DD_UNIQUE_PROFILE return(dd->uniqueLookUps); #else return(-1.0); #endif } /* end of Cudd_ReadUniqueLookUps */ /**Function******************************************************************** Synopsis [Returns the number of links followed in the unique table.] Description [Returns the number of links followed during look-ups in the unique table if the keeping of this statistic is enabled; -1 otherwise. If an item is found in the first position of its collision list, the number of links followed is taken to be 0. If it is in second position, the number of links is 1, and so on. This statistic is enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.] SideEffects [None] SeeAlso [Cudd_ReadUniqueLookUps] ******************************************************************************/ double Cudd_ReadUniqueLinks( DdManager * dd) { #ifdef DD_UNIQUE_PROFILE return(dd->uniqueLinks); #else return(-1.0); #endif } /* end of Cudd_ReadUniqueLinks */ /**Function******************************************************************** Synopsis [Reads the siftMaxVar parameter of the manager.] Description [Reads the siftMaxVar parameter of the manager. This parameter gives the maximum number of variables that will be sifted for each invocation of sifting.] SideEffects [None] SeeAlso [Cudd_ReadSiftMaxSwap Cudd_SetSiftMaxVar] ******************************************************************************/ int Cudd_ReadSiftMaxVar( DdManager * dd) { return(dd->siftMaxVar); } /* end of Cudd_ReadSiftMaxVar */ /**Function******************************************************************** Synopsis [Sets the siftMaxVar parameter of the manager.] Description [Sets the siftMaxVar parameter of the manager. This parameter gives the maximum number of variables that will be sifted for each invocation of sifting.] SideEffects [None] SeeAlso [Cudd_SetSiftMaxSwap Cudd_ReadSiftMaxVar] ******************************************************************************/ void Cudd_SetSiftMaxVar( DdManager * dd, int smv) { dd->siftMaxVar = smv; } /* end of Cudd_SetSiftMaxVar */ /**Function******************************************************************** Synopsis [Reads the siftMaxSwap parameter of the manager.] Description [Reads the siftMaxSwap parameter of the manager. This parameter gives the maximum number of swaps that will be attempted for each invocation of sifting. The real number of swaps may exceed the set limit because the package will always complete the sifting of the variable that causes the limit to be reached.] SideEffects [None] SeeAlso [Cudd_ReadSiftMaxVar Cudd_SetSiftMaxSwap] ******************************************************************************/ int Cudd_ReadSiftMaxSwap( DdManager * dd) { return(dd->siftMaxSwap); } /* end of Cudd_ReadSiftMaxSwap */ /**Function******************************************************************** Synopsis [Sets the siftMaxSwap parameter of the manager.] Description [Sets the siftMaxSwap parameter of the manager. This parameter gives the maximum number of swaps that will be attempted for each invocation of sifting. The real number of swaps may exceed the set limit because the package will always complete the sifting of the variable that causes the limit to be reached.] SideEffects [None] SeeAlso [Cudd_SetSiftMaxVar Cudd_ReadSiftMaxSwap] ******************************************************************************/ void Cudd_SetSiftMaxSwap( DdManager * dd, int sms) { dd->siftMaxSwap = sms; } /* end of Cudd_SetSiftMaxSwap */ /**Function******************************************************************** Synopsis [Reads the maxGrowth parameter of the manager.] Description [Reads the maxGrowth parameter of the manager. This parameter determines how much the number of nodes can grow during sifting of a variable. Overall, sifting never increases the size of the decision diagrams. This parameter only refers to intermediate results. A lower value will speed up sifting, possibly at the expense of quality.] SideEffects [None] SeeAlso [Cudd_SetMaxGrowth Cudd_ReadMaxGrowthAlternate] ******************************************************************************/ double Cudd_ReadMaxGrowth( DdManager * dd) { return(dd->maxGrowth); } /* end of Cudd_ReadMaxGrowth */ /**Function******************************************************************** Synopsis [Sets the maxGrowth parameter of the manager.] Description [Sets the maxGrowth parameter of the manager. This parameter determines how much the number of nodes can grow during sifting of a variable. Overall, sifting never increases the size of the decision diagrams. This parameter only refers to intermediate results. A lower value will speed up sifting, possibly at the expense of quality.] SideEffects [None] SeeAlso [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate] ******************************************************************************/ void Cudd_SetMaxGrowth( DdManager * dd, double mg) { dd->maxGrowth = mg; } /* end of Cudd_SetMaxGrowth */ /**Function******************************************************************** Synopsis [Reads the maxGrowthAlt parameter of the manager.] Description [Reads the maxGrowthAlt parameter of the manager. This parameter is analogous to the maxGrowth paramter, and is used every given number of reorderings instead of maxGrowth. The number of reorderings is set with Cudd_SetReorderingCycle. If the number of reorderings is 0 (default) maxGrowthAlt is never used.] SideEffects [None] SeeAlso [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate Cudd_SetReorderingCycle Cudd_ReadReorderingCycle] ******************************************************************************/ double Cudd_ReadMaxGrowthAlternate( DdManager * dd) { return(dd->maxGrowthAlt); } /* end of Cudd_ReadMaxGrowthAlternate */ /**Function******************************************************************** Synopsis [Sets the maxGrowthAlt parameter of the manager.] Description [Sets the maxGrowthAlt parameter of the manager. This parameter is analogous to the maxGrowth paramter, and is used every given number of reorderings instead of maxGrowth. The number of reorderings is set with Cudd_SetReorderingCycle. If the number of reorderings is 0 (default) maxGrowthAlt is never used.] SideEffects [None] SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowth Cudd_SetReorderingCycle Cudd_ReadReorderingCycle] ******************************************************************************/ void Cudd_SetMaxGrowthAlternate( DdManager * dd, double mg) { dd->maxGrowthAlt = mg; } /* end of Cudd_SetMaxGrowthAlternate */ /**Function******************************************************************** Synopsis [Reads the reordCycle parameter of the manager.] Description [Reads the reordCycle parameter of the manager. This parameter determines how often the alternate threshold on maximum growth is used in reordering.] SideEffects [None] SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate Cudd_SetReorderingCycle] ******************************************************************************/ int Cudd_ReadReorderingCycle( DdManager * dd) { return(dd->reordCycle); } /* end of Cudd_ReadReorderingCycle */ /**Function******************************************************************** Synopsis [Sets the reordCycle parameter of the manager.] Description [Sets the reordCycle parameter of the manager. This parameter determines how often the alternate threshold on maximum growth is used in reordering.] SideEffects [None] SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate Cudd_ReadReorderingCycle] ******************************************************************************/ void Cudd_SetReorderingCycle( DdManager * dd, int cycle) { dd->reordCycle = cycle; } /* end of Cudd_SetReorderingCycle */ /**Function******************************************************************** Synopsis [Returns the variable group tree of the manager.] Description [] SideEffects [None] SeeAlso [Cudd_SetTree Cudd_FreeTree Cudd_ReadZddTree] ******************************************************************************/ MtrNode * Cudd_ReadTree( DdManager * dd) { return(dd->tree); } /* end of Cudd_ReadTree */ /**Function******************************************************************** Synopsis [Sets the variable group tree of the manager.] Description [] SideEffects [None] SeeAlso [Cudd_FreeTree Cudd_ReadTree Cudd_SetZddTree] ******************************************************************************/ void Cudd_SetTree( DdManager * dd, MtrNode * tree) { if (dd->tree != NULL) { Mtr_FreeTree(dd->tree); } dd->tree = tree; if (tree == NULL) return; fixVarTree(tree, dd->perm, dd->size); return; } /* end of Cudd_SetTree */ /**Function******************************************************************** Synopsis [Frees the variable group tree of the manager.] Description [] SideEffects [None] SeeAlso [Cudd_SetTree Cudd_ReadTree Cudd_FreeZddTree] ******************************************************************************/ void Cudd_FreeTree( DdManager * dd) { if (dd->tree != NULL) { Mtr_FreeTree(dd->tree); dd->tree = NULL; } return; } /* end of Cudd_FreeTree */ /**Function******************************************************************** Synopsis [Returns the variable group tree of the manager.] Description [] SideEffects [None] SeeAlso [Cudd_SetZddTree Cudd_FreeZddTree Cudd_ReadTree] ******************************************************************************/ MtrNode * Cudd_ReadZddTree( DdManager * dd) { return(dd->treeZ); } /* end of Cudd_ReadZddTree */ /**Function******************************************************************** Synopsis [Sets the ZDD variable group tree of the manager.] Description [] SideEffects [None] SeeAlso [Cudd_FreeZddTree Cudd_ReadZddTree Cudd_SetTree] ******************************************************************************/ void Cudd_SetZddTree( DdManager * dd, MtrNode * tree) { if (dd->treeZ != NULL) { Mtr_FreeTree(dd->treeZ); } dd->treeZ = tree; if (tree == NULL) return; fixVarTree(tree, dd->permZ, dd->sizeZ); return; } /* end of Cudd_SetZddTree */ /**Function******************************************************************** Synopsis [Frees the variable group tree of the manager.] Description [] SideEffects [None] SeeAlso [Cudd_SetZddTree Cudd_ReadZddTree Cudd_FreeTree] ******************************************************************************/ void Cudd_FreeZddTree( DdManager * dd) { if (dd->treeZ != NULL) { Mtr_FreeTree(dd->treeZ); dd->treeZ = NULL; } return; } /* end of Cudd_FreeZddTree */ /**Function******************************************************************** Synopsis [Returns the index of the node.] Description [Returns the index of the node. The node pointer can be either regular or complemented.] SideEffects [None] SeeAlso [Cudd_ReadIndex] ******************************************************************************/ unsigned int Cudd_NodeReadIndex( DdNode * node) { return((unsigned int) Cudd_Regular(node)->index); } /* end of Cudd_NodeReadIndex */ /**Function******************************************************************** Synopsis [Returns the current position of the i-th variable in the order.] Description [Returns the current position of the i-th variable in the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] SideEffects [None] SeeAlso [Cudd_ReadInvPerm Cudd_ReadPermZdd] ******************************************************************************/ int Cudd_ReadPerm( DdManager * dd, int i) { if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); if (i < 0 || i >= dd->size) return(-1); return(dd->perm[i]); } /* end of Cudd_ReadPerm */ /**Function******************************************************************** Synopsis [Returns the current position of the i-th ZDD variable in the order.] Description [Returns the current position of the i-th ZDD variable in the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] SideEffects [None] SeeAlso [Cudd_ReadInvPermZdd Cudd_ReadPerm] ******************************************************************************/ int Cudd_ReadPermZdd( DdManager * dd, int i) { if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); if (i < 0 || i >= dd->sizeZ) return(-1); return(dd->permZ[i]); } /* end of Cudd_ReadPermZdd */ /**Function******************************************************************** Synopsis [Returns the index of the variable currently in the i-th position of the order.] Description [Returns the index of the variable currently in the i-th position of the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] SideEffects [None] SeeAlso [Cudd_ReadPerm Cudd_ReadInvPermZdd] ******************************************************************************/ int Cudd_ReadInvPerm( DdManager * dd, int i) { if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); if (i < 0 || i >= dd->size) return(-1); return(dd->invperm[i]); } /* end of Cudd_ReadInvPerm */ /**Function******************************************************************** Synopsis [Returns the index of the ZDD variable currently in the i-th position of the order.] Description [Returns the index of the ZDD variable currently in the i-th position of the order. If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] SideEffects [None] SeeAlso [Cudd_ReadPerm Cudd_ReadInvPermZdd] ******************************************************************************/ int Cudd_ReadInvPermZdd( DdManager * dd, int i) { if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); if (i < 0 || i >= dd->sizeZ) return(-1); return(dd->invpermZ[i]); } /* end of Cudd_ReadInvPermZdd */ /**Function******************************************************************** Synopsis [Returns the i-th element of the vars array.] Description [Returns the i-th element of the vars array if it falls within the array bounds; NULL otherwise. If i is the index of an existing variable, this function produces the same result as Cudd_bddIthVar. However, if the i-th var does not exist yet, Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.] SideEffects [None] SeeAlso [Cudd_bddIthVar] ******************************************************************************/ DdNode * Cudd_ReadVars( DdManager * dd, int i) { if (i < 0 || i > dd->size) return(NULL); return(dd->vars[i]); } /* end of Cudd_ReadVars */ /**Function******************************************************************** Synopsis [Reads the epsilon parameter of the manager.] Description [Reads the epsilon parameter of the manager. The epsilon parameter control the comparison between floating point numbers.] SideEffects [None] SeeAlso [Cudd_SetEpsilon] ******************************************************************************/ CUDD_VALUE_TYPE Cudd_ReadEpsilon( DdManager * dd) { return(dd->epsilon); } /* end of Cudd_ReadEpsilon */ /**Function******************************************************************** Synopsis [Sets the epsilon parameter of the manager to ep.] Description [Sets the epsilon parameter of the manager to ep. The epsilon parameter control the comparison between floating point numbers.] SideEffects [None] SeeAlso [Cudd_ReadEpsilon] ******************************************************************************/ void Cudd_SetEpsilon( DdManager * dd, CUDD_VALUE_TYPE ep) { dd->epsilon = ep; } /* end of Cudd_SetEpsilon */ /**Function******************************************************************** Synopsis [Reads the groupcheck parameter of the manager.] Description [Reads the groupcheck parameter of the manager. The groupcheck parameter determines the aggregation criterion in group sifting.] SideEffects [None] SeeAlso [Cudd_SetGroupcheck] ******************************************************************************/ Cudd_AggregationType Cudd_ReadGroupcheck( DdManager * dd) { return(dd->groupcheck); } /* end of Cudd_ReadGroupCheck */ /**Function******************************************************************** Synopsis [Sets the parameter groupcheck of the manager to gc.] Description [Sets the parameter groupcheck of the manager to gc. The groupcheck parameter determines the aggregation criterion in group sifting.] SideEffects [None] SeeAlso [Cudd_ReadGroupCheck] ******************************************************************************/ void Cudd_SetGroupcheck( DdManager * dd, Cudd_AggregationType gc) { dd->groupcheck = gc; } /* end of Cudd_SetGroupcheck */ /**Function******************************************************************** Synopsis [Tells whether garbage collection is enabled.] Description [Returns 1 if garbage collection is enabled; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_EnableGarbageCollection Cudd_DisableGarbageCollection] ******************************************************************************/ int Cudd_GarbageCollectionEnabled( DdManager * dd) { return(dd->gcEnabled); } /* end of Cudd_GarbageCollectionEnabled */ /**Function******************************************************************** Synopsis [Enables garbage collection.] Description [Enables garbage collection. Garbage collection is initially enabled. Therefore it is necessary to call this function only if garbage collection has been explicitly disabled.] SideEffects [None] SeeAlso [Cudd_DisableGarbageCollection Cudd_GarbageCollectionEnabled] ******************************************************************************/ void Cudd_EnableGarbageCollection( DdManager * dd) { dd->gcEnabled = 1; } /* end of Cudd_EnableGarbageCollection */ /**Function******************************************************************** Synopsis [Disables garbage collection.] Description [Disables garbage collection. Garbage collection is initially enabled. This function may be called to disable it. However, garbage collection will still occur when a new node must be created and no memory is left, or when garbage collection is required for correctness. (E.g., before reordering.)] SideEffects [None] SeeAlso [Cudd_EnableGarbageCollection Cudd_GarbageCollectionEnabled] ******************************************************************************/ void Cudd_DisableGarbageCollection( DdManager * dd) { dd->gcEnabled = 0; } /* end of Cudd_DisableGarbageCollection */ /**Function******************************************************************** Synopsis [Tells whether dead nodes are counted towards triggering reordering.] Description [Tells whether dead nodes are counted towards triggering reordering. Returns 1 if dead nodes are counted; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_TurnOnCountDead Cudd_TurnOffCountDead] ******************************************************************************/ int Cudd_DeadAreCounted( DdManager * dd) { return(dd->countDead == 0 ? 1 : 0); } /* end of Cudd_DeadAreCounted */ /**Function******************************************************************** Synopsis [Causes the dead nodes to be counted towards triggering reordering.] Description [Causes the dead nodes to be counted towards triggering reordering. This causes more frequent reorderings. By default dead nodes are not counted.] SideEffects [Changes the manager.] SeeAlso [Cudd_TurnOffCountDead Cudd_DeadAreCounted] ******************************************************************************/ void Cudd_TurnOnCountDead( DdManager * dd) { dd->countDead = 0; } /* end of Cudd_TurnOnCountDead */ /**Function******************************************************************** Synopsis [Causes the dead nodes not to be counted towards triggering reordering.] Description [Causes the dead nodes not to be counted towards triggering reordering. This causes less frequent reorderings. By default dead nodes are not counted. Therefore there is no need to call this function unless Cudd_TurnOnCountDead has been previously called.] SideEffects [Changes the manager.] SeeAlso [Cudd_TurnOnCountDead Cudd_DeadAreCounted] ******************************************************************************/ void Cudd_TurnOffCountDead( DdManager * dd) { dd->countDead = ~0; } /* end of Cudd_TurnOffCountDead */ /**Function******************************************************************** Synopsis [Returns the current value of the recombination parameter used in group sifting.] Description [Returns the current value of the recombination parameter used in group sifting. A larger (positive) value makes the aggregation of variables due to the second difference criterion more likely. A smaller (negative) value makes aggregation less likely.] SideEffects [None] SeeAlso [Cudd_SetRecomb] ******************************************************************************/ int Cudd_ReadRecomb( DdManager * dd) { return(dd->recomb); } /* end of Cudd_ReadRecomb */ /**Function******************************************************************** Synopsis [Sets the value of the recombination parameter used in group sifting.] Description [Sets the value of the recombination parameter used in group sifting. A larger (positive) value makes the aggregation of variables due to the second difference criterion more likely. A smaller (negative) value makes aggregation less likely. The default value is 0.] SideEffects [Changes the manager.] SeeAlso [Cudd_ReadRecomb] ******************************************************************************/ void Cudd_SetRecomb( DdManager * dd, int recomb) { dd->recomb = recomb; } /* end of Cudd_SetRecomb */ /**Function******************************************************************** Synopsis [Returns the current value of the symmviolation parameter used in group sifting.] Description [Returns the current value of the symmviolation parameter. This parameter is used in group sifting to decide how many violations to the symmetry conditions f10 = f01 or f11 = f00 are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.] SideEffects [None] SeeAlso [Cudd_SetSymmviolation] ******************************************************************************/ int Cudd_ReadSymmviolation( DdManager * dd) { return(dd->symmviolation); } /* end of Cudd_ReadSymmviolation */ /**Function******************************************************************** Synopsis [Sets the value of the symmviolation parameter used in group sifting.] Description [Sets the value of the symmviolation parameter. This parameter is used in group sifting to decide how many violations to the symmetry conditions f10 = f01 or f11 = f00 are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.] SideEffects [Changes the manager.] SeeAlso [Cudd_ReadSymmviolation] ******************************************************************************/ void Cudd_SetSymmviolation( DdManager * dd, int symmviolation) { dd->symmviolation = symmviolation; } /* end of Cudd_SetSymmviolation */ /**Function******************************************************************** Synopsis [Returns the current value of the arcviolation parameter used in group sifting.] Description [Returns the current value of the arcviolation parameter. This parameter is used in group sifting to decide how many arcs into y not coming from x are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.] SideEffects [None] SeeAlso [Cudd_SetArcviolation] ******************************************************************************/ int Cudd_ReadArcviolation( DdManager * dd) { return(dd->arcviolation); } /* end of Cudd_ReadArcviolation */ /**Function******************************************************************** Synopsis [Sets the value of the arcviolation parameter used in group sifting.] Description [Sets the value of the arcviolation parameter. This parameter is used in group sifting to decide how many arcs into y not coming from x are tolerable when checking for aggregation due to extended symmetry. The value should be between 0 and 100. A small value causes fewer variables to be aggregated. The default value is 0.] SideEffects [None] SeeAlso [Cudd_ReadArcviolation] ******************************************************************************/ void Cudd_SetArcviolation( DdManager * dd, int arcviolation) { dd->arcviolation = arcviolation; } /* end of Cudd_SetArcviolation */ /**Function******************************************************************** Synopsis [Reads the current size of the population used by the genetic algorithm for reordering.] Description [Reads the current size of the population used by the genetic algorithm for variable reordering. A larger population size will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as population size, with a maximum of 120.] SideEffects [None] SeeAlso [Cudd_SetPopulationSize] ******************************************************************************/ int Cudd_ReadPopulationSize( DdManager * dd) { return(dd->populationSize); } /* end of Cudd_ReadPopulationSize */ /**Function******************************************************************** Synopsis [Sets the size of the population used by the genetic algorithm for reordering.] Description [Sets the size of the population used by the genetic algorithm for variable reordering. A larger population size will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as population size, with a maximum of 120.] SideEffects [Changes the manager.] SeeAlso [Cudd_ReadPopulationSize] ******************************************************************************/ void Cudd_SetPopulationSize( DdManager * dd, int populationSize) { dd->populationSize = populationSize; } /* end of Cudd_SetPopulationSize */ /**Function******************************************************************** Synopsis [Reads the current number of crossovers used by the genetic algorithm for reordering.] Description [Reads the current number of crossovers used by the genetic algorithm for variable reordering. A larger number of crossovers will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as number of crossovers, with a maximum of 60.] SideEffects [None] SeeAlso [Cudd_SetNumberXovers] ******************************************************************************/ int Cudd_ReadNumberXovers( DdManager * dd) { return(dd->numberXovers); } /* end of Cudd_ReadNumberXovers */ /**Function******************************************************************** Synopsis [Sets the number of crossovers used by the genetic algorithm for reordering.] Description [Sets the number of crossovers used by the genetic algorithm for variable reordering. A larger number of crossovers will cause the genetic algorithm to take more time, but will generally produce better results. The default value is 0, in which case the package uses three times the number of variables as number of crossovers, with a maximum of 60.] SideEffects [None] SeeAlso [Cudd_ReadNumberXovers] ******************************************************************************/ void Cudd_SetNumberXovers( DdManager * dd, int numberXovers) { dd->numberXovers = numberXovers; } /* end of Cudd_SetNumberXovers */ /**Function******************************************************************** Synopsis [Returns the memory in use by the manager measured in bytes.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ unsigned long Cudd_ReadMemoryInUse( DdManager * dd) { return(dd->memused); } /* end of Cudd_ReadMemoryInUse */ /**Function******************************************************************** Synopsis [Prints out statistics and settings for a CUDD manager.] Description [Prints out statistics and settings for a CUDD manager. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_PrintInfo( DdManager * dd, FILE * fp) { int retval; Cudd_ReorderingType autoMethod, autoMethodZ; /* Modifiable parameters. */ retval = fprintf(fp,"**** CUDD modifiable parameters ****\n"); if (retval == EOF) return(0); retval = fprintf(fp,"Hard limit for cache size: %u\n", Cudd_ReadMaxCacheHard(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Cache hit threshold for resizing: %u%%\n", Cudd_ReadMinHit(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Garbage collection enabled: %s\n", Cudd_GarbageCollectionEnabled(dd) ? "yes" : "no"); if (retval == EOF) return(0); retval = fprintf(fp,"Limit for fast unique table growth: %u\n", Cudd_ReadLooseUpTo(dd)); if (retval == EOF) return(0); retval = fprintf(fp, "Maximum number of variables sifted per reordering: %d\n", Cudd_ReadSiftMaxVar(dd)); if (retval == EOF) return(0); retval = fprintf(fp, "Maximum number of variable swaps per reordering: %d\n", Cudd_ReadSiftMaxSwap(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Maximum growth while sifting a variable: %g\n", Cudd_ReadMaxGrowth(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Dynamic reordering of BDDs enabled: %s\n", Cudd_ReorderingStatus(dd,&autoMethod) ? "yes" : "no"); if (retval == EOF) return(0); retval = fprintf(fp,"Default BDD reordering method: %d\n", (int) autoMethod); if (retval == EOF) return(0); retval = fprintf(fp,"Dynamic reordering of ZDDs enabled: %s\n", Cudd_ReorderingStatusZdd(dd,&autoMethodZ) ? "yes" : "no"); if (retval == EOF) return(0); retval = fprintf(fp,"Default ZDD reordering method: %d\n", (int) autoMethodZ); if (retval == EOF) return(0); retval = fprintf(fp,"Realignment of ZDDs to BDDs enabled: %s\n", Cudd_zddRealignmentEnabled(dd) ? "yes" : "no"); if (retval == EOF) return(0); retval = fprintf(fp,"Realignment of BDDs to ZDDs enabled: %s\n", Cudd_bddRealignmentEnabled(dd) ? "yes" : "no"); if (retval == EOF) return(0); retval = fprintf(fp,"Dead nodes counted in triggering reordering: %s\n", Cudd_DeadAreCounted(dd) ? "yes" : "no"); if (retval == EOF) return(0); retval = fprintf(fp,"Group checking criterion: %d\n", (int) Cudd_ReadGroupcheck(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Recombination threshold: %d\n", Cudd_ReadRecomb(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Symmetry violation threshold: %d\n", Cudd_ReadSymmviolation(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Arc violation threshold: %d\n", Cudd_ReadArcviolation(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"GA population size: %d\n", Cudd_ReadPopulationSize(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Number of crossovers for GA: %d\n", Cudd_ReadNumberXovers(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Next reordering threshold: %u\n", Cudd_ReadNextReordering(dd)); if (retval == EOF) return(0); /* Non-modifiable parameters. */ retval = fprintf(fp,"**** CUDD non-modifiable parameters ****\n"); if (retval == EOF) return(0); retval = fprintf(fp,"Memory in use: %lu\n", Cudd_ReadMemoryInUse(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Peak number of nodes: %ld\n", Cudd_ReadPeakNodeCount(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Peak number of live nodes: %d\n", Cudd_ReadPeakLiveNodeCount(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Number of BDD variables: %d\n", dd->size); if (retval == EOF) return(0); retval = fprintf(fp,"Number of ZDD variables: %d\n", dd->sizeZ); if (retval == EOF) return(0); retval = fprintf(fp,"Number of cache entries: %u\n", dd->cacheSlots); if (retval == EOF) return(0); retval = fprintf(fp,"Number of cache look-ups: %.0f\n", Cudd_ReadCacheLookUps(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Number of cache hits: %.0f\n", Cudd_ReadCacheHits(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Number of cache insertions: %.0f\n", dd->cacheinserts); if (retval == EOF) return(0); retval = fprintf(fp,"Number of cache collisions: %.0f\n", dd->cachecollisions); if (retval == EOF) return(0); retval = fprintf(fp,"Number of cache deletions: %.0f\n", dd->cachedeletions); if (retval == EOF) return(0); retval = cuddCacheProfile(dd,fp); if (retval == 0) return(0); retval = fprintf(fp,"Soft limit for cache size: %u\n", Cudd_ReadMaxCache(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Number of buckets in unique table: %u\n", dd->slots); if (retval == EOF) return(0); retval = fprintf(fp,"Used buckets in unique table: %.2f%% (expected %.2f%%)\n", 100.0 * Cudd_ReadUsedSlots(dd), 100.0 * Cudd_ExpectedUsedSlots(dd)); if (retval == EOF) return(0); #ifdef DD_UNIQUE_PROFILE retval = fprintf(fp,"Unique lookups: %.0f\n", dd->uniqueLookUps); if (retval == EOF) return(0); retval = fprintf(fp,"Unique links: %.0f (%g per lookup)\n", dd->uniqueLinks, dd->uniqueLinks / dd->uniqueLookUps); if (retval == EOF) return(0); #endif retval = fprintf(fp,"Number of BDD and ADD nodes: %u\n", dd->keys); if (retval == EOF) return(0); retval = fprintf(fp,"Number of ZDD nodes: %u\n", dd->keysZ); if (retval == EOF) return(0); retval = fprintf(fp,"Number of dead BDD and ADD nodes: %u\n", dd->dead); if (retval == EOF) return(0); retval = fprintf(fp,"Number of dead ZDD nodes: %u\n", dd->deadZ); if (retval == EOF) return(0); retval = fprintf(fp,"Total number of nodes allocated: %d\n", (int)dd->allocated); if (retval == EOF) return(0); retval = fprintf(fp,"Total number of nodes reclaimed: %.0f\n", dd->reclaimed); if (retval == EOF) return(0); #ifdef DD_STATS retval = fprintf(fp,"Nodes freed: %.0f\n", dd->nodesFreed); if (retval == EOF) return(0); retval = fprintf(fp,"Nodes dropped: %.0f\n", dd->nodesDropped); if (retval == EOF) return(0); #endif #ifdef DD_COUNT retval = fprintf(fp,"Number of recursive calls: %.0f\n", Cudd_ReadRecursiveCalls(dd)); if (retval == EOF) return(0); #endif retval = fprintf(fp,"Garbage collections so far: %d\n", Cudd_ReadGarbageCollections(dd)); if (retval == EOF) return(0); retval = fprintf(fp,"Time for garbage collection: %.2f sec\n", ((double)Cudd_ReadGarbageCollectionTime(dd)/1000.0)); if (retval == EOF) return(0); retval = fprintf(fp,"Reorderings so far: %d\n", dd->reorderings); if (retval == EOF) return(0); retval = fprintf(fp,"Time for reordering: %.2f sec\n", ((double)Cudd_ReadReorderingTime(dd)/1000.0)); if (retval == EOF) return(0); #ifdef DD_COUNT retval = fprintf(fp,"Node swaps in reordering: %.0f\n", Cudd_ReadSwapSteps(dd)); if (retval == EOF) return(0); #endif return(1); } /* end of Cudd_PrintInfo */ /**Function******************************************************************** Synopsis [Reports the peak number of nodes.] Description [Reports the peak number of nodes. This number includes node on the free list. At the peak, the number of nodes on the free list is guaranteed to be less than DD_MEM_CHUNK.] SideEffects [None] SeeAlso [Cudd_ReadNodeCount Cudd_PrintInfo] ******************************************************************************/ long Cudd_ReadPeakNodeCount( DdManager * dd) { long count = 0; DdNodePtr *scan = dd->memoryList; while (scan != NULL) { count += DD_MEM_CHUNK; scan = (DdNodePtr *) *scan; } return(count); } /* end of Cudd_ReadPeakNodeCount */ /**Function******************************************************************** Synopsis [Reports the peak number of live nodes.] Description [Reports the peak number of live nodes. This count is kept only if CUDD is compiled with DD_STATS defined. If DD_STATS is not defined, this function returns -1.] SideEffects [None] SeeAlso [Cudd_ReadNodeCount Cudd_PrintInfo Cudd_ReadPeakNodeCount] ******************************************************************************/ int Cudd_ReadPeakLiveNodeCount( DdManager * dd) { unsigned int live = dd->keys - dd->dead; if (live > dd->peakLiveNodes) { dd->peakLiveNodes = live; } return((int)dd->peakLiveNodes); } /* end of Cudd_ReadPeakLiveNodeCount */ /**Function******************************************************************** Synopsis [Reports the number of nodes in BDDs and ADDs.] Description [Reports the number of live nodes in BDDs and ADDs. This number does not include the isolated projection functions and the unused constants. These nodes that are not counted are not part of the DDs manipulated by the application.] SideEffects [None] SeeAlso [Cudd_ReadPeakNodeCount Cudd_zddReadNodeCount] ******************************************************************************/ long Cudd_ReadNodeCount( DdManager * dd) { long count; int i; #ifndef DD_NO_DEATH_ROW cuddClearDeathRow(dd); #endif count = (long) (dd->keys - dd->dead); /* Count isolated projection functions. Their number is subtracted ** from the node count because they are not part of the BDDs. */ for (i=0; i < dd->size; i++) { if (dd->vars[i]->ref == 1) count--; } /* Subtract from the count the unused constants. */ if (DD_ZERO(dd)->ref == 1) count--; if (DD_PLUS_INFINITY(dd)->ref == 1) count--; if (DD_MINUS_INFINITY(dd)->ref == 1) count--; return(count); } /* end of Cudd_ReadNodeCount */ /**Function******************************************************************** Synopsis [Reports the number of nodes in ZDDs.] Description [Reports the number of nodes in ZDDs. This number always includes the two constants 1 and 0.] SideEffects [None] SeeAlso [Cudd_ReadPeakNodeCount Cudd_ReadNodeCount] ******************************************************************************/ long Cudd_zddReadNodeCount( DdManager * dd) { return((long)(dd->keysZ - dd->deadZ + 2)); } /* end of Cudd_zddReadNodeCount */ /**Function******************************************************************** Synopsis [Adds a function to a hook.] Description [Adds a function to a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if the function is successfully added; 2 if the function was already in the list; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_RemoveHook] ******************************************************************************/ int Cudd_AddHook( DdManager * dd, DD_HFP f, Cudd_HookType where) { DdHook **hook, *nextHook, *newHook; switch (where) { case CUDD_PRE_GC_HOOK: hook = &(dd->preGCHook); break; case CUDD_POST_GC_HOOK: hook = &(dd->postGCHook); break; case CUDD_PRE_REORDERING_HOOK: hook = &(dd->preReorderingHook); break; case CUDD_POST_REORDERING_HOOK: hook = &(dd->postReorderingHook); break; default: return(0); } /* Scan the list and find whether the function is already there. ** If so, just return. */ nextHook = *hook; while (nextHook != NULL) { if (nextHook->f == f) { return(2); } hook = &(nextHook->next); nextHook = nextHook->next; } /* The function was not in the list. Create a new item and append it ** to the end of the list. */ newHook = ABC_ALLOC(DdHook,1); if (newHook == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } newHook->next = NULL; newHook->f = f; *hook = newHook; return(1); } /* end of Cudd_AddHook */ /**Function******************************************************************** Synopsis [Removes a function from a hook.] Description [Removes a function from a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if successful; 0 the function was not in the list.] SideEffects [None] SeeAlso [Cudd_AddHook] ******************************************************************************/ int Cudd_RemoveHook( DdManager * dd, DD_HFP f, Cudd_HookType where) { DdHook **hook, *nextHook; switch (where) { case CUDD_PRE_GC_HOOK: hook = &(dd->preGCHook); break; case CUDD_POST_GC_HOOK: hook = &(dd->postGCHook); break; case CUDD_PRE_REORDERING_HOOK: hook = &(dd->preReorderingHook); break; case CUDD_POST_REORDERING_HOOK: hook = &(dd->postReorderingHook); break; default: return(0); } nextHook = *hook; while (nextHook != NULL) { if (nextHook->f == f) { *hook = nextHook->next; ABC_FREE(nextHook); return(1); } hook = &(nextHook->next); nextHook = nextHook->next; } return(0); } /* end of Cudd_RemoveHook */ /**Function******************************************************************** Synopsis [Checks whether a function is in a hook.] Description [Checks whether a function is in a hook. A hook is a list of application-provided functions called on certain occasions by the package. Returns 1 if the function is found; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_AddHook Cudd_RemoveHook] ******************************************************************************/ int Cudd_IsInHook( DdManager * dd, DD_HFP f, Cudd_HookType where) { DdHook *hook; switch (where) { case CUDD_PRE_GC_HOOK: hook = dd->preGCHook; break; case CUDD_POST_GC_HOOK: hook = dd->postGCHook; break; case CUDD_PRE_REORDERING_HOOK: hook = dd->preReorderingHook; break; case CUDD_POST_REORDERING_HOOK: hook = dd->postReorderingHook; break; default: return(0); } /* Scan the list and find whether the function is already there. */ while (hook != NULL) { if (hook->f == f) { return(1); } hook = hook->next; } return(0); } /* end of Cudd_IsInHook */ /**Function******************************************************************** Synopsis [Sample hook function to call before reordering.] Description [Sample hook function to call before reordering. Prints on the manager's stdout reordering method and initial size. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_StdPostReordHook] ******************************************************************************/ int Cudd_StdPreReordHook( DdManager *dd, const char *str, void *data) { Cudd_ReorderingType method = (Cudd_ReorderingType) (ptruint) data; int retval; retval = fprintf(dd->out,"%s reordering with ", str); if (retval == EOF) return(0); switch (method) { case CUDD_REORDER_SIFT_CONVERGE: case CUDD_REORDER_SYMM_SIFT_CONV: case CUDD_REORDER_GROUP_SIFT_CONV: case CUDD_REORDER_WINDOW2_CONV: case CUDD_REORDER_WINDOW3_CONV: case CUDD_REORDER_WINDOW4_CONV: case CUDD_REORDER_LINEAR_CONVERGE: retval = fprintf(dd->out,"converging "); if (retval == EOF) return(0); break; default: break; } switch (method) { case CUDD_REORDER_RANDOM: case CUDD_REORDER_RANDOM_PIVOT: retval = fprintf(dd->out,"random"); break; case CUDD_REORDER_SIFT: case CUDD_REORDER_SIFT_CONVERGE: retval = fprintf(dd->out,"sifting"); break; case CUDD_REORDER_SYMM_SIFT: case CUDD_REORDER_SYMM_SIFT_CONV: retval = fprintf(dd->out,"symmetric sifting"); break; case CUDD_REORDER_LAZY_SIFT: retval = fprintf(dd->out,"lazy sifting"); break; case CUDD_REORDER_GROUP_SIFT: case CUDD_REORDER_GROUP_SIFT_CONV: retval = fprintf(dd->out,"group sifting"); break; case CUDD_REORDER_WINDOW2: case CUDD_REORDER_WINDOW3: case CUDD_REORDER_WINDOW4: case CUDD_REORDER_WINDOW2_CONV: case CUDD_REORDER_WINDOW3_CONV: case CUDD_REORDER_WINDOW4_CONV: retval = fprintf(dd->out,"window"); break; case CUDD_REORDER_ANNEALING: retval = fprintf(dd->out,"annealing"); break; case CUDD_REORDER_GENETIC: retval = fprintf(dd->out,"genetic"); break; case CUDD_REORDER_LINEAR: case CUDD_REORDER_LINEAR_CONVERGE: retval = fprintf(dd->out,"linear sifting"); break; case CUDD_REORDER_EXACT: retval = fprintf(dd->out,"exact"); break; default: return(0); } if (retval == EOF) return(0); retval = fprintf(dd->out,": from %ld to ... ", strcmp(str, "BDD") == 0 ? Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd)); if (retval == EOF) return(0); fflush(dd->out); return(1); } /* end of Cudd_StdPreReordHook */ /**Function******************************************************************** Synopsis [Sample hook function to call after reordering.] Description [Sample hook function to call after reordering. Prints on the manager's stdout final size and reordering time. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_StdPreReordHook] ******************************************************************************/ int Cudd_StdPostReordHook( DdManager *dd, const char *str, void *data) { long initialTime = (long) data; int retval; long finalTime = util_cpu_time(); double totalTimeSec = (double)(finalTime - initialTime) / 1000.0; retval = fprintf(dd->out,"%ld nodes in %g sec\n", strcmp(str, "BDD") == 0 ? Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd), totalTimeSec); if (retval == EOF) return(0); retval = fflush(dd->out); if (retval == EOF) return(0); return(1); } /* end of Cudd_StdPostReordHook */ /**Function******************************************************************** Synopsis [Enables reporting of reordering stats.] Description [Enables reporting of reordering stats. Returns 1 if successful; 0 otherwise.] SideEffects [Installs functions in the pre-reordering and post-reordering hooks.] SeeAlso [Cudd_DisableReorderingReporting Cudd_ReorderingReporting] ******************************************************************************/ int Cudd_EnableReorderingReporting( DdManager *dd) { if (!Cudd_AddHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) { return(0); } if (!Cudd_AddHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) { return(0); } return(1); } /* end of Cudd_EnableReorderingReporting */ /**Function******************************************************************** Synopsis [Disables reporting of reordering stats.] Description [Disables reporting of reordering stats. Returns 1 if successful; 0 otherwise.] SideEffects [Removes functions from the pre-reordering and post-reordering hooks.] SeeAlso [Cudd_EnableReorderingReporting Cudd_ReorderingReporting] ******************************************************************************/ int Cudd_DisableReorderingReporting( DdManager *dd) { if (!Cudd_RemoveHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) { return(0); } if (!Cudd_RemoveHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) { return(0); } return(1); } /* end of Cudd_DisableReorderingReporting */ /**Function******************************************************************** Synopsis [Returns 1 if reporting of reordering stats is enabled.] Description [Returns 1 if reporting of reordering stats is enabled; 0 otherwise.] SideEffects [none] SeeAlso [Cudd_EnableReorderingReporting Cudd_DisableReorderingReporting] ******************************************************************************/ int Cudd_ReorderingReporting( DdManager *dd) { return(Cudd_IsInHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)); } /* end of Cudd_ReorderingReporting */ /**Function******************************************************************** Synopsis [Returns the code of the last error.] Description [Returns the code of the last error. The error codes are defined in cudd.h.] SideEffects [None] SeeAlso [Cudd_ClearErrorCode] ******************************************************************************/ Cudd_ErrorType Cudd_ReadErrorCode( DdManager *dd) { return(dd->errorCode); } /* end of Cudd_ReadErrorCode */ /**Function******************************************************************** Synopsis [Clear the error code of a manager.] Description [] SideEffects [None] SeeAlso [Cudd_ReadErrorCode] ******************************************************************************/ void Cudd_ClearErrorCode( DdManager *dd) { dd->errorCode = CUDD_NO_ERROR; } /* end of Cudd_ClearErrorCode */ /**Function******************************************************************** Synopsis [Reads the stdout of a manager.] Description [Reads the stdout of a manager. This is the file pointer to which messages normally going to stdout are written. It is initialized to stdout. Cudd_SetStdout allows the application to redirect it.] SideEffects [None] SeeAlso [Cudd_SetStdout Cudd_ReadStderr] ******************************************************************************/ FILE * Cudd_ReadStdout( DdManager *dd) { return(dd->out); } /* end of Cudd_ReadStdout */ /**Function******************************************************************** Synopsis [Sets the stdout of a manager.] Description [] SideEffects [None] SeeAlso [Cudd_ReadStdout Cudd_SetStderr] ******************************************************************************/ void Cudd_SetStdout( DdManager *dd, FILE *fp) { dd->out = fp; } /* end of Cudd_SetStdout */ /**Function******************************************************************** Synopsis [Reads the stderr of a manager.] Description [Reads the stderr of a manager. This is the file pointer to which messages normally going to stderr are written. It is initialized to stderr. Cudd_SetStderr allows the application to redirect it.] SideEffects [None] SeeAlso [Cudd_SetStderr Cudd_ReadStdout] ******************************************************************************/ FILE * Cudd_ReadStderr( DdManager *dd) { return(dd->err); } /* end of Cudd_ReadStderr */ /**Function******************************************************************** Synopsis [Sets the stderr of a manager.] Description [] SideEffects [None] SeeAlso [Cudd_ReadStderr Cudd_SetStdout] ******************************************************************************/ void Cudd_SetStderr( DdManager *dd, FILE *fp) { dd->err = fp; } /* end of Cudd_SetStderr */ /**Function******************************************************************** Synopsis [Returns the threshold for the next dynamic reordering.] Description [Returns the threshold for the next dynamic reordering. The threshold is in terms of number of nodes and is in effect only if reordering is enabled. The count does not include the dead nodes, unless the countDead parameter of the manager has been changed from its default setting.] SideEffects [None] SeeAlso [Cudd_SetNextReordering] ******************************************************************************/ unsigned int Cudd_ReadNextReordering( DdManager *dd) { return(dd->nextDyn); } /* end of Cudd_ReadNextReordering */ /**Function******************************************************************** Synopsis [Sets the threshold for the next dynamic reordering.] Description [Sets the threshold for the next dynamic reordering. The threshold is in terms of number of nodes and is in effect only if reordering is enabled. The count does not include the dead nodes, unless the countDead parameter of the manager has been changed from its default setting.] SideEffects [None] SeeAlso [Cudd_ReadNextReordering] ******************************************************************************/ void Cudd_SetNextReordering( DdManager *dd, unsigned int next) { dd->nextDyn = next; } /* end of Cudd_SetNextReordering */ /**Function******************************************************************** Synopsis [Reads the number of elementary reordering steps.] Description [] SideEffects [none] SeeAlso [] ******************************************************************************/ double Cudd_ReadSwapSteps( DdManager *dd) { #ifdef DD_COUNT return(dd->swapSteps); #else return(-1); #endif } /* end of Cudd_ReadSwapSteps */ /**Function******************************************************************** Synopsis [Reads the maximum allowed number of live nodes.] Description [Reads the maximum allowed number of live nodes. When this number is exceeded, the package returns NULL.] SideEffects [none] SeeAlso [Cudd_SetMaxLive] ******************************************************************************/ unsigned int Cudd_ReadMaxLive( DdManager *dd) { return(dd->maxLive); } /* end of Cudd_ReadMaxLive */ /**Function******************************************************************** Synopsis [Sets the maximum allowed number of live nodes.] Description [Sets the maximum allowed number of live nodes. When this number is exceeded, the package returns NULL.] SideEffects [none] SeeAlso [Cudd_ReadMaxLive] ******************************************************************************/ void Cudd_SetMaxLive( DdManager *dd, unsigned int maxLive) { dd->maxLive = maxLive; } /* end of Cudd_SetMaxLive */ /**Function******************************************************************** Synopsis [Reads the maximum allowed memory.] Description [Reads the maximum allowed memory. When this number is exceeded, the package returns NULL.] SideEffects [none] SeeAlso [Cudd_SetMaxMemory] ******************************************************************************/ unsigned long Cudd_ReadMaxMemory( DdManager *dd) { return(dd->maxmemhard); } /* end of Cudd_ReadMaxMemory */ /**Function******************************************************************** Synopsis [Sets the maximum allowed memory.] Description [Sets the maximum allowed memory. When this number is exceeded, the package returns NULL.] SideEffects [none] SeeAlso [Cudd_ReadMaxMemory] ******************************************************************************/ void Cudd_SetMaxMemory( DdManager *dd, unsigned long maxMemory) { dd->maxmemhard = maxMemory; } /* end of Cudd_SetMaxMemory */ /**Function******************************************************************** Synopsis [Prevents sifting of a variable.] Description [This function sets a flag to prevent sifting of a variable. Returns 1 if successful; 0 otherwise (i.e., invalid variable index).] SideEffects [Changes the "bindVar" flag in DdSubtable.] SeeAlso [Cudd_bddUnbindVar] ******************************************************************************/ int Cudd_bddBindVar( DdManager *dd /* manager */, int index /* variable index */) { if (index >= dd->size || index < 0) return(0); dd->subtables[dd->perm[index]].bindVar = 1; return(1); } /* end of Cudd_bddBindVar */ /**Function******************************************************************** Synopsis [Allows the sifting of a variable.] Description [This function resets the flag that prevents the sifting of a variable. In successive variable reorderings, the variable will NOT be skipped, that is, sifted. Initially all variables can be sifted. It is necessary to call this function only to re-enable sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0 otherwise (i.e., invalid variable index).] SideEffects [Changes the "bindVar" flag in DdSubtable.] SeeAlso [Cudd_bddBindVar] ******************************************************************************/ int Cudd_bddUnbindVar( DdManager *dd /* manager */, int index /* variable index */) { if (index >= dd->size || index < 0) return(0); dd->subtables[dd->perm[index]].bindVar = 0; return(1); } /* end of Cudd_bddUnbindVar */ /**Function******************************************************************** Synopsis [Tells whether a variable can be sifted.] Description [This function returns 1 if a variable is enabled for sifting. Initially all variables can be sifted. This function returns 0 only if there has been a previous call to Cudd_bddBindVar for that variable not followed by a call to Cudd_bddUnbindVar. The function returns 0 also in the case in which the index of the variable is out of bounds.] SideEffects [none] SeeAlso [Cudd_bddBindVar Cudd_bddUnbindVar] ******************************************************************************/ int Cudd_bddVarIsBound( DdManager *dd /* manager */, int index /* variable index */) { if (index >= dd->size || index < 0) return(0); return(dd->subtables[dd->perm[index]].bindVar); } /* end of Cudd_bddVarIsBound */ /**Function******************************************************************** Synopsis [Sets a variable type to primary input.] Description [Sets a variable type to primary input. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddSetPsVar Cudd_bddSetNsVar Cudd_bddIsPiVar] ******************************************************************************/ int Cudd_bddSetPiVar( DdManager *dd /* manager */, int index /* variable index */) { if (index >= dd->size || index < 0) return (0); dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRIMARY_INPUT; return(1); } /* end of Cudd_bddSetPiVar */ /**Function******************************************************************** Synopsis [Sets a variable type to present state.] Description [Sets a variable type to present state. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddSetPiVar Cudd_bddSetNsVar Cudd_bddIsPsVar] ******************************************************************************/ int Cudd_bddSetPsVar( DdManager *dd /* manager */, int index /* variable index */) { if (index >= dd->size || index < 0) return (0); dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRESENT_STATE; return(1); } /* end of Cudd_bddSetPsVar */ /**Function******************************************************************** Synopsis [Sets a variable type to next state.] Description [Sets a variable type to next state. The variable type is used by lazy sifting. Returns 1 if successful; 0 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddSetPiVar Cudd_bddSetPsVar Cudd_bddIsNsVar] ******************************************************************************/ int Cudd_bddSetNsVar( DdManager *dd /* manager */, int index /* variable index */) { if (index >= dd->size || index < 0) return (0); dd->subtables[dd->perm[index]].varType = CUDD_VAR_NEXT_STATE; return(1); } /* end of Cudd_bddSetNsVar */ /**Function******************************************************************** Synopsis [Checks whether a variable is primary input.] Description [Checks whether a variable is primary input. Returns 1 if the variable's type is primary input; 0 if the variable exists but is not a primary input; -1 if the variable does not exist.] SideEffects [none] SeeAlso [Cudd_bddSetPiVar Cudd_bddIsPsVar Cudd_bddIsNsVar] ******************************************************************************/ int Cudd_bddIsPiVar( DdManager *dd /* manager */, int index /* variable index */) { if (index >= dd->size || index < 0) return -1; return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRIMARY_INPUT); } /* end of Cudd_bddIsPiVar */ /**Function******************************************************************** Synopsis [Checks whether a variable is present state.] Description [Checks whether a variable is present state. Returns 1 if the variable's type is present state; 0 if the variable exists but is not a present state; -1 if the variable does not exist.] SideEffects [none] SeeAlso [Cudd_bddSetPsVar Cudd_bddIsPiVar Cudd_bddIsNsVar] ******************************************************************************/ int Cudd_bddIsPsVar( DdManager *dd, int index) { if (index >= dd->size || index < 0) return -1; return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRESENT_STATE); } /* end of Cudd_bddIsPsVar */ /**Function******************************************************************** Synopsis [Checks whether a variable is next state.] Description [Checks whether a variable is next state. Returns 1 if the variable's type is present state; 0 if the variable exists but is not a present state; -1 if the variable does not exist.] SideEffects [none] SeeAlso [Cudd_bddSetNsVar Cudd_bddIsPiVar Cudd_bddIsPsVar] ******************************************************************************/ int Cudd_bddIsNsVar( DdManager *dd, int index) { if (index >= dd->size || index < 0) return -1; return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_NEXT_STATE); } /* end of Cudd_bddIsNsVar */ /**Function******************************************************************** Synopsis [Sets a corresponding pair index for a given index.] Description [Sets a corresponding pair index for a given index. These pair indices are present and next state variable. Returns 1 if successful; 0 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddReadPairIndex] ******************************************************************************/ int Cudd_bddSetPairIndex( DdManager *dd /* manager */, int index /* variable index */, int pairIndex /* corresponding variable index */) { if (index >= dd->size || index < 0) return(0); dd->subtables[dd->perm[index]].pairIndex = pairIndex; return(1); } /* end of Cudd_bddSetPairIndex */ /**Function******************************************************************** Synopsis [Reads a corresponding pair index for a given index.] Description [Reads a corresponding pair index for a given index. These pair indices are present and next state variable. Returns the corresponding variable index if the variable exists; -1 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddSetPairIndex] ******************************************************************************/ int Cudd_bddReadPairIndex( DdManager *dd, int index) { if (index >= dd->size || index < 0) return -1; return dd->subtables[dd->perm[index]].pairIndex; } /* end of Cudd_bddReadPairIndex */ /**Function******************************************************************** Synopsis [Sets a variable to be grouped.] Description [Sets a variable to be grouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddSetVarHardGroup Cudd_bddResetVarToBeGrouped] ******************************************************************************/ int Cudd_bddSetVarToBeGrouped( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(0); if (dd->subtables[dd->perm[index]].varToBeGrouped <= CUDD_LAZY_SOFT_GROUP) { dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_SOFT_GROUP; } return(1); } /* end of Cudd_bddSetVarToBeGrouped */ /**Function******************************************************************** Synopsis [Sets a variable to be a hard group.] Description [Sets a variable to be a hard group. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddSetVarToBeGrouped Cudd_bddResetVarToBeGrouped Cudd_bddIsVarHardGroup] ******************************************************************************/ int Cudd_bddSetVarHardGroup( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(0); dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_HARD_GROUP; return(1); } /* end of Cudd_bddSetVarHardGrouped */ /**Function******************************************************************** Synopsis [Resets a variable not to be grouped.] Description [Resets a variable not to be grouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddSetVarToBeGrouped Cudd_bddSetVarHardGroup] ******************************************************************************/ int Cudd_bddResetVarToBeGrouped( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(0); if (dd->subtables[dd->perm[index]].varToBeGrouped <= CUDD_LAZY_SOFT_GROUP) { dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_NONE; } return(1); } /* end of Cudd_bddResetVarToBeGrouped */ /**Function******************************************************************** Synopsis [Checks whether a variable is set to be grouped.] Description [Checks whether a variable is set to be grouped. This function is used for lazy sifting.] SideEffects [none] SeeAlso [] ******************************************************************************/ int Cudd_bddIsVarToBeGrouped( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(-1); if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP) return(0); else return(dd->subtables[dd->perm[index]].varToBeGrouped); } /* end of Cudd_bddIsVarToBeGrouped */ /**Function******************************************************************** Synopsis [Sets a variable to be ungrouped.] Description [Sets a variable to be ungrouped. This function is used for lazy sifting. Returns 1 if successful; 0 otherwise.] SideEffects [modifies the manager] SeeAlso [Cudd_bddIsVarToBeUngrouped] ******************************************************************************/ int Cudd_bddSetVarToBeUngrouped( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(0); dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_UNGROUP; return(1); } /* end of Cudd_bddSetVarToBeGrouped */ /**Function******************************************************************** Synopsis [Checks whether a variable is set to be ungrouped.] Description [Checks whether a variable is set to be ungrouped. This function is used for lazy sifting. Returns 1 if the variable is marked to be ungrouped; 0 if the variable exists, but it is not marked to be ungrouped; -1 if the variable does not exist.] SideEffects [none] SeeAlso [Cudd_bddSetVarToBeUngrouped] ******************************************************************************/ int Cudd_bddIsVarToBeUngrouped( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(-1); return dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP; } /* end of Cudd_bddIsVarToBeGrouped */ /**Function******************************************************************** Synopsis [Checks whether a variable is set to be in a hard group.] Description [Checks whether a variable is set to be in a hard group. This function is used for lazy sifting. Returns 1 if the variable is marked to be in a hard group; 0 if the variable exists, but it is not marked to be in a hard group; -1 if the variable does not exist.] SideEffects [none] SeeAlso [Cudd_bddSetVarHardGroup] ******************************************************************************/ int Cudd_bddIsVarHardGroup( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(-1); if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_HARD_GROUP) return(1); return(0); } /* end of Cudd_bddIsVarToBeGrouped */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Fixes a variable group tree.] Description [] SideEffects [Changes the variable group tree.] SeeAlso [] ******************************************************************************/ static void fixVarTree( MtrNode * treenode, int * perm, int size) { treenode->index = treenode->low; treenode->low = ((int) treenode->index < size) ? perm[treenode->index] : treenode->index; if (treenode->child != NULL) fixVarTree(treenode->child, perm, size); if (treenode->younger != NULL) fixVarTree(treenode->younger, perm, size); return; } /* end of fixVarTree */ /**Function******************************************************************** Synopsis [Adds multiplicity groups to a ZDD variable group tree.] Description [Adds multiplicity groups to a ZDD variable group tree. Returns 1 if successful; 0 otherwise. This function creates the groups for set of ZDD variables (whose cardinality is given by parameter multiplicity) that are created for each BDD variable in Cudd_zddVarsFromBddVars. The crux of the matter is to determine the index each new group. (The index of the first variable in the group.) We first build all the groups for the children of a node, and then deal with the ZDD variables that are directly attached to the node. The problem for these is that the tree itself does not provide information on their position inside the group. While we deal with the children of the node, therefore, we keep track of all the positions they occupy. The remaining positions in the tree can be freely used. Also, we keep track of all the variables placed in the children. All the remaining variables are directly attached to the group. We can then place any pair of variables not yet grouped in any pair of available positions in the node.] SideEffects [Changes the variable group tree.] SeeAlso [Cudd_zddVarsFromBddVars] ******************************************************************************/ static int addMultiplicityGroups( DdManager *dd /* manager */, MtrNode *treenode /* current tree node */, int multiplicity /* how many ZDD vars per BDD var */, char *vmask /* variable pairs for which a group has been already built */, char *lmask /* levels for which a group has already been built*/) { int startV, stopV, startL; int i, j; MtrNode *auxnode = treenode; while (auxnode != NULL) { if (auxnode->child != NULL) { addMultiplicityGroups(dd,auxnode->child,multiplicity,vmask,lmask); } /* Build remaining groups. */ startV = dd->permZ[auxnode->index] / multiplicity; startL = auxnode->low / multiplicity; stopV = startV + auxnode->size / multiplicity; /* Walk down vmask starting at startV and build missing groups. */ for (i = startV, j = startL; i < stopV; i++) { if (vmask[i] == 0) { MtrNode *node; while (lmask[j] == 1) j++; node = Mtr_MakeGroup(auxnode, j * multiplicity, multiplicity, MTR_FIXED); if (node == NULL) { return(0); } node->index = dd->invpermZ[i * multiplicity]; vmask[i] = 1; lmask[j] = 1; } } auxnode = auxnode->younger; } return(1); } /* end of addMultiplicityGroups */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAddAbs.c000066400000000000000000000451051300674244400236330ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAddAbs.c] PackageName [cudd] Synopsis [Quantification functions for ADDs.] Description [External procedures included in this module:
  • Cudd_addExistAbstract()
  • Cudd_addUnivAbstract()
  • Cudd_addOrAbstract()
Internal procedures included in this module:
  • cuddAddExistAbstractRecur()
  • cuddAddUnivAbstractRecur()
  • cuddAddOrAbstractRecur()
Static procedures included in this module:
  • addCheckPositiveCube()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAddAbs.c,v 1.15 2004/08/13 18:04:45 fabio Exp $"; #endif static DdNode *two; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int addCheckPositiveCube (DdManager *manager, DdNode *cube); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Existentially Abstracts all the variables in cube from f.] Description [Abstracts all the variables in cube from f by summing over all possible values taken by the variables. Returns the abstracted ADD.] SideEffects [None] SeeAlso [Cudd_addUnivAbstract Cudd_bddExistAbstract Cudd_addOrAbstract] ******************************************************************************/ DdNode * Cudd_addExistAbstract( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *res; two = cuddUniqueConst(manager,(CUDD_VALUE_TYPE) 2); if (two == NULL) return(NULL); cuddRef(two); if (addCheckPositiveCube(manager, cube) == 0) { (void) fprintf(manager->err,"Error: Can only abstract cubes"); return(NULL); } do { manager->reordered = 0; res = cuddAddExistAbstractRecur(manager, f, cube); } while (manager->reordered == 1); if (res == NULL) { Cudd_RecursiveDeref(manager,two); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,two); cuddDeref(res); return(res); } /* end of Cudd_addExistAbstract */ /**Function******************************************************************** Synopsis [Universally Abstracts all the variables in cube from f.] Description [Abstracts all the variables in cube from f by taking the product over all possible values taken by the variable. Returns the abstracted ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addExistAbstract Cudd_bddUnivAbstract Cudd_addOrAbstract] ******************************************************************************/ DdNode * Cudd_addUnivAbstract( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *res; if (addCheckPositiveCube(manager, cube) == 0) { (void) fprintf(manager->err,"Error: Can only abstract cubes"); return(NULL); } do { manager->reordered = 0; res = cuddAddUnivAbstractRecur(manager, f, cube); } while (manager->reordered == 1); return(res); } /* end of Cudd_addUnivAbstract */ /**Function******************************************************************** Synopsis [Disjunctively abstracts all the variables in cube from the 0-1 ADD f.] Description [Abstracts all the variables in cube from the 0-1 ADD f by taking the disjunction over all possible values taken by the variables. Returns the abstracted ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addUnivAbstract Cudd_addExistAbstract] ******************************************************************************/ DdNode * Cudd_addOrAbstract( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *res; if (addCheckPositiveCube(manager, cube) == 0) { (void) fprintf(manager->err,"Error: Can only abstract cubes"); return(NULL); } do { manager->reordered = 0; res = cuddAddOrAbstractRecur(manager, f, cube); } while (manager->reordered == 1); return(res); } /* end of Cudd_addOrAbstract */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addExistAbstract.] Description [Performs the recursive step of Cudd_addExistAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddAddExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *T, *E, *res, *res1, *res2, *zero; statLine(manager); zero = DD_ZERO(manager); /* Cube is guaranteed to be a cube at this point. */ if (f == zero || cuddIsConstant(cube)) { return(f); } /* Abstract a variable that does not appear in f => multiply by 2. */ if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); /* Use the "internal" procedure to be alerted in case of ** dynamic reordering. If dynamic reordering occurs, we ** have to abort the entire abstraction. */ res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); cuddDeref(res); return(res); } if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) { return(res); } T = cuddT(f); E = cuddE(f); /* If the two indices are the same, so are their levels. */ if (f->index == cube->index) { res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ res1 = cuddAddExistAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddExistAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = (res1 == res2) ? res1 : cuddUniqueInter(manager, (int) f->index, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); return(res); } } /* end of cuddAddExistAbstractRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addUnivAbstract.] Description [Performs the recursive step of Cudd_addUnivAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddAddUnivAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *T, *E, *res, *res1, *res2, *one, *zero; statLine(manager); one = DD_ONE(manager); zero = DD_ZERO(manager); /* Cube is guaranteed to be a cube at this point. ** zero and one are the only constatnts c such that c*c=c. */ if (f == zero || f == one || cube == one) { return(f); } /* Abstract a variable that does not appear in f. */ if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); /* Use the "internal" procedure to be alerted in case of ** dynamic reordering. If dynamic reordering occurs, we ** have to abort the entire abstraction. */ res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); cuddDeref(res); return(res); } if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) { return(res); } T = cuddT(f); E = cuddE(f); /* If the two indices are the same, so are their levels. */ if (f->index == cube->index) { res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ res1 = cuddAddUnivAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddUnivAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = (res1 == res2) ? res1 : cuddUniqueInter(manager, (int) f->index, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); return(res); } } /* end of cuddAddUnivAbstractRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addOrAbstract.] Description [Performs the recursive step of Cudd_addOrAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddAddOrAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *T, *E, *res, *res1, *res2, *one; statLine(manager); one = DD_ONE(manager); /* Cube is guaranteed to be a cube at this point. */ if (cuddIsConstant(f) || cube == one) { return(f); } /* Abstract a variable that does not appear in f. */ if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { res = cuddAddOrAbstractRecur(manager, f, cuddT(cube)); return(res); } if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) { return(res); } T = cuddT(f); E = cuddE(f); /* If the two indices are the same, so are their levels. */ if (f->index == cube->index) { res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); if (res1 != one) { res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); } else { res = res1; } cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ res1 = cuddAddOrAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddOrAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = (res1 == res2) ? res1 : cuddUniqueInter(manager, (int) f->index, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); return(res); } } /* end of cuddAddOrAbstractRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Checks whether cube is an ADD representing the product of positive literals.] Description [Checks whether cube is an ADD representing the product of positive literals. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int addCheckPositiveCube( DdManager * manager, DdNode * cube) { if (Cudd_IsComplement(cube)) return(0); if (cube == DD_ONE(manager)) return(1); if (cuddIsConstant(cube)) return(0); if (cuddE(cube) == DD_ZERO(manager)) { return(addCheckPositiveCube(manager, cuddT(cube))); } return(0); } /* end of addCheckPositiveCube */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAddApply.c000066400000000000000000000604121300674244400242110ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAddApply.c] PackageName [cudd] Synopsis [Apply functions for ADDs and their operators.] Description [External procedures included in this module:
  • Cudd_addApply()
  • Cudd_addMonadicApply()
  • Cudd_addPlus()
  • Cudd_addTimes()
  • Cudd_addThreshold()
  • Cudd_addSetNZ()
  • Cudd_addDivide()
  • Cudd_addMinus()
  • Cudd_addMinimum()
  • Cudd_addMaximum()
  • Cudd_addOneZeroMaximum()
  • Cudd_addDiff()
  • Cudd_addAgreement()
  • Cudd_addOr()
  • Cudd_addNand()
  • Cudd_addNor()
  • Cudd_addXor()
  • Cudd_addXnor()
Internal procedures included in this module:
  • cuddAddApplyRecur()
  • cuddAddMonadicApplyRecur()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.18 2009/02/19 16:15:26 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Applies op to the corresponding discriminants of f and g.] Description [Applies op to the corresponding discriminants of f and g. Returns a pointer to the result if succssful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor] ******************************************************************************/ DdNode * Cudd_addApply( DdManager * dd, DD_AOP op, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddAddApplyRecur(dd,op,f,g); } while (dd->reordered == 1); return(res); } /* end of Cudd_addApply */ /**Function******************************************************************** Synopsis [Integer and floating point addition.] Description [Integer and floating point addition. Returns NULL if not a terminal case; f+g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addPlus( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *res; DdNode *F, *G; CUDD_VALUE_TYPE value; F = *f; G = *g; if (F == DD_ZERO(dd)) return(G); if (G == DD_ZERO(dd)) return(F); if (cuddIsConstant(F) && cuddIsConstant(G)) { value = cuddV(F)+cuddV(G); res = cuddUniqueConst(dd,value); return(res); } if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addPlus */ /**Function******************************************************************** Synopsis [Integer and floating point multiplication.] Description [Integer and floating point multiplication. Returns NULL if not a terminal case; f * g otherwise. This function can be used also to take the AND of two 0-1 ADDs.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addTimes( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *res; DdNode *F, *G; CUDD_VALUE_TYPE value; F = *f; G = *g; if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd)); if (F == DD_ONE(dd)) return(G); if (G == DD_ONE(dd)) return(F); if (cuddIsConstant(F) && cuddIsConstant(G)) { value = cuddV(F)*cuddV(G); res = cuddUniqueConst(dd,value); return(res); } if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addTimes */ /**Function******************************************************************** Synopsis [f if f>=g; 0 if f<g.] Description [Threshold operator for Apply (f if f >=g; 0 if f<g). Returns NULL if not a terminal case; f op g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addThreshold( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G || F == DD_PLUS_INFINITY(dd)) return(F); if (cuddIsConstant(F) && cuddIsConstant(G)) { if (cuddV(F) >= cuddV(G)) { return(F); } else { return(DD_ZERO(dd)); } } return(NULL); } /* end of Cudd_addThreshold */ /**Function******************************************************************** Synopsis [This operator sets f to the value of g wherever g != 0.] Description [This operator sets f to the value of g wherever g != 0. Returns NULL if not a terminal case; f op g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addSetNZ( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G) return(F); if (F == DD_ZERO(dd)) return(G); if (G == DD_ZERO(dd)) return(F); if (cuddIsConstant(G)) return(G); return(NULL); } /* end of Cudd_addSetNZ */ /**Function******************************************************************** Synopsis [Integer and floating point division.] Description [Integer and floating point division. Returns NULL if not a terminal case; f / g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addDivide( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *res; DdNode *F, *G; CUDD_VALUE_TYPE value; F = *f; G = *g; /* We would like to use F == G -> F/G == 1, but F and G may ** contain zeroes. */ if (F == DD_ZERO(dd)) return(DD_ZERO(dd)); if (G == DD_ONE(dd)) return(F); if (cuddIsConstant(F) && cuddIsConstant(G)) { value = cuddV(F)/cuddV(G); res = cuddUniqueConst(dd,value); return(res); } return(NULL); } /* end of Cudd_addDivide */ /**Function******************************************************************** Synopsis [Integer and floating point subtraction.] Description [Integer and floating point subtraction. Returns NULL if not a terminal case; f - g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addMinus( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *res; DdNode *F, *G; CUDD_VALUE_TYPE value; F = *f; G = *g; if (F == G) return(DD_ZERO(dd)); if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G)); if (G == DD_ZERO(dd)) return(F); if (cuddIsConstant(F) && cuddIsConstant(G)) { value = cuddV(F)-cuddV(G); res = cuddUniqueConst(dd,value); return(res); } return(NULL); } /* end of Cudd_addMinus */ /**Function******************************************************************** Synopsis [Integer and floating point min.] Description [Integer and floating point min for Cudd_addApply. Returns NULL if not a terminal case; min(f,g) otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addMinimum( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == DD_PLUS_INFINITY(dd)) return(G); if (G == DD_PLUS_INFINITY(dd)) return(F); if (F == G) return(F); #if 0 /* These special cases probably do not pay off. */ if (F == DD_MINUS_INFINITY(dd)) return(F); if (G == DD_MINUS_INFINITY(dd)) return(G); #endif if (cuddIsConstant(F) && cuddIsConstant(G)) { if (cuddV(F) <= cuddV(G)) { return(F); } else { return(G); } } if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addMinimum */ /**Function******************************************************************** Synopsis [Integer and floating point max.] Description [Integer and floating point max for Cudd_addApply. Returns NULL if not a terminal case; max(f,g) otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addMaximum( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G) return(F); if (F == DD_MINUS_INFINITY(dd)) return(G); if (G == DD_MINUS_INFINITY(dd)) return(F); #if 0 /* These special cases probably do not pay off. */ if (F == DD_PLUS_INFINITY(dd)) return(F); if (G == DD_PLUS_INFINITY(dd)) return(G); #endif if (cuddIsConstant(F) && cuddIsConstant(G)) { if (cuddV(F) >= cuddV(G)) { return(F); } else { return(G); } } if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addMaximum */ /**Function******************************************************************** Synopsis [Returns 1 if f > g and 0 otherwise.] Description [Returns 1 if f > g and 0 otherwise. Used in conjunction with Cudd_addApply. Returns NULL if not a terminal case.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addOneZeroMaximum( DdManager * dd, DdNode ** f, DdNode ** g) { if (*f == *g) return(DD_ZERO(dd)); if (*g == DD_PLUS_INFINITY(dd)) return DD_ZERO(dd); if (cuddIsConstant(*f) && cuddIsConstant(*g)) { if (cuddV(*f) > cuddV(*g)) { return(DD_ONE(dd)); } else { return(DD_ZERO(dd)); } } return(NULL); } /* end of Cudd_addOneZeroMaximum */ /**Function******************************************************************** Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.] Description [Returns NULL if not a terminal case; f op g otherwise, where f op g is plusinfinity if f=g; min(f,g) if f!=g.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addDiff( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G) return(DD_PLUS_INFINITY(dd)); if (F == DD_PLUS_INFINITY(dd)) return(G); if (G == DD_PLUS_INFINITY(dd)) return(F); if (cuddIsConstant(F) && cuddIsConstant(G)) { if (cuddV(F) != cuddV(G)) { if (cuddV(F) < cuddV(G)) { return(F); } else { return(G); } } else { return(DD_PLUS_INFINITY(dd)); } } return(NULL); } /* end of Cudd_addDiff */ /**Function******************************************************************** Synopsis [f if f==g; background if f!=g.] Description [Returns NULL if not a terminal case; f op g otherwise, where f op g is f if f==g; background if f!=g.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addAgreement( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G) return(F); if (F == dd->background) return(F); if (G == dd->background) return(G); if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background); return(NULL); } /* end of Cudd_addAgreement */ /**Function******************************************************************** Synopsis [Disjunction of two 0-1 ADDs.] Description [Disjunction of two 0-1 ADDs. Returns NULL if not a terminal case; f OR g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addOr( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd)); if (cuddIsConstant(F)) return(G); if (cuddIsConstant(G)) return(F); if (F == G) return(F); if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addOr */ /**Function******************************************************************** Synopsis [NAND of two 0-1 ADDs.] Description [NAND of two 0-1 ADDs. Returns NULL if not a terminal case; f NAND g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addNand( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd)); if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addNand */ /**Function******************************************************************** Synopsis [NOR of two 0-1 ADDs.] Description [NOR of two 0-1 ADDs. Returns NULL if not a terminal case; f NOR g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addNor( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd)); if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd)); if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addNor */ /**Function******************************************************************** Synopsis [XOR of two 0-1 ADDs.] Description [XOR of two 0-1 ADDs. Returns NULL if not a terminal case; f XOR g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addXor( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G) return(DD_ZERO(dd)); if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd)); if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addXor */ /**Function******************************************************************** Synopsis [XNOR of two 0-1 ADDs.] Description [XNOR of two 0-1 ADDs. Returns NULL if not a terminal case; f XNOR g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addXnor( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G) return(DD_ONE(dd)); if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd)); if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addXnor */ /**Function******************************************************************** Synopsis [Applies op to the discriminants of f.] Description [Applies op to the discriminants of f. Returns a pointer to the result if succssful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addApply Cudd_addLog] ******************************************************************************/ DdNode * Cudd_addMonadicApply( DdManager * dd, DD_MAOP op, DdNode * f) { DdNode *res; do { dd->reordered = 0; res = cuddAddMonadicApplyRecur(dd,op,f); } while (dd->reordered == 1); return(res); } /* end of Cudd_addMonadicApply */ /**Function******************************************************************** Synopsis [Natural logarithm of an ADD.] Description [Natural logarithm of an ADDs. Returns NULL if not a terminal case; log(f) otherwise. The discriminants of f must be positive double's.] SideEffects [None] SeeAlso [Cudd_addMonadicApply] ******************************************************************************/ DdNode * Cudd_addLog( DdManager * dd, DdNode * f) { if (cuddIsConstant(f)) { CUDD_VALUE_TYPE value = log(cuddV(f)); DdNode *res = cuddUniqueConst(dd,value); return(res); } return(NULL); } /* end of Cudd_addLog */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addApply.] Description [Performs the recursive step of Cudd_addApply. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddAddMonadicApplyRecur] ******************************************************************************/ DdNode * cuddAddApplyRecur( DdManager * dd, DD_AOP op, DdNode * f, DdNode * g) { DdNode *res, *fv, *fvn, *gv, *gvn, *T, *E; unsigned int ford, gord; unsigned int index; DD_CTFP cacheOp; /* Check terminal cases. Op may swap f and g to increase the * cache hit rate. */ statLine(dd); res = (*op)(dd,&f,&g); if (res != NULL) return(res); /* Check cache. */ cacheOp = (DD_CTFP) op; res = cuddCacheLookup2(dd,cacheOp,f,g); if (res != NULL) return(res); /* Recursive step. */ ford = cuddI(dd,f->index); gord = cuddI(dd,g->index); if (ford <= gord) { index = f->index; fv = cuddT(f); fvn = cuddE(f); } else { index = g->index; fv = fvn = f; } if (gord <= ford) { gv = cuddT(g); gvn = cuddE(g); } else { gv = gvn = g; } T = cuddAddApplyRecur(dd,op,fv,gv); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddApplyRecur(dd,op,fvn,gvn); if (E == NULL) { Cudd_RecursiveDeref(dd,T); return(NULL); } cuddRef(E); res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,cacheOp,f,g,res); return(res); } /* end of cuddAddApplyRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addMonadicApply.] Description [Performs the recursive step of Cudd_addMonadicApply. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddAddApplyRecur] ******************************************************************************/ DdNode * cuddAddMonadicApplyRecur( DdManager * dd, DD_MAOP op, DdNode * f) { DdNode *res, *ft, *fe, *T, *E; unsigned int index; /* Check terminal cases. */ statLine(dd); res = (*op)(dd,f); if (res != NULL) return(res); /* Check cache. */ res = cuddCacheLookup1(dd,op,f); if (res != NULL) return(res); /* Recursive step. */ index = f->index; ft = cuddT(f); fe = cuddE(f); T = cuddAddMonadicApplyRecur(dd,op,ft); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddMonadicApplyRecur(dd,op,fe); if (E == NULL) { Cudd_RecursiveDeref(dd,T); return(NULL); } cuddRef(E); res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert1(dd,op,f,res); return(res); } /* end of cuddAddMonadicApplyRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAddFind.c000066400000000000000000000224161300674244400240060ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAddFind.c] PackageName [cudd] Synopsis [Functions to find maximum and minimum in an ADD and to extract the i-th bit.] Description [External procedures included in this module:
  • Cudd_addFindMax()
  • Cudd_addFindMin()
  • Cudd_addIthBit()
Static functions included in this module:
  • addDoIthBit()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAddFind.c,v 1.8 2004/08/13 18:04:45 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * addDoIthBit (DdManager *dd, DdNode *f, DdNode *index); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Finds the maximum discriminant of f.] Description [Returns a pointer to a constant ADD.] SideEffects [None] ******************************************************************************/ DdNode * Cudd_addFindMax( DdManager * dd, DdNode * f) { DdNode *t, *e, *res; statLine(dd); if (cuddIsConstant(f)) { return(f); } res = cuddCacheLookup1(dd,Cudd_addFindMax,f); if (res != NULL) { return(res); } t = Cudd_addFindMax(dd,cuddT(f)); if (t == DD_PLUS_INFINITY(dd)) return(t); e = Cudd_addFindMax(dd,cuddE(f)); res = (cuddV(t) >= cuddV(e)) ? t : e; cuddCacheInsert1(dd,Cudd_addFindMax,f,res); return(res); } /* end of Cudd_addFindMax */ /**Function******************************************************************** Synopsis [Finds the minimum discriminant of f.] Description [Returns a pointer to a constant ADD.] SideEffects [None] ******************************************************************************/ DdNode * Cudd_addFindMin( DdManager * dd, DdNode * f) { DdNode *t, *e, *res; statLine(dd); if (cuddIsConstant(f)) { return(f); } res = cuddCacheLookup1(dd,Cudd_addFindMin,f); if (res != NULL) { return(res); } t = Cudd_addFindMin(dd,cuddT(f)); if (t == DD_MINUS_INFINITY(dd)) return(t); e = Cudd_addFindMin(dd,cuddE(f)); res = (cuddV(t) <= cuddV(e)) ? t : e; cuddCacheInsert1(dd,Cudd_addFindMin,f,res); return(res); } /* end of Cudd_addFindMin */ /**Function******************************************************************** Synopsis [Extracts the i-th bit from an ADD.] Description [Produces an ADD from another ADD by replacing all discriminants whose i-th bit is equal to 1 with 1, and all other discriminants with 0. The i-th bit refers to the integer representation of the leaf value. If the value is has a fractional part, it is ignored. Repeated calls to this procedure allow one to transform an integer-valued ADD into an array of ADDs, one for each bit of the leaf values. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addBddIthBit] ******************************************************************************/ DdNode * Cudd_addIthBit( DdManager * dd, DdNode * f, int bit) { DdNode *res; DdNode *index; /* Use a constant node to remember the bit, so that we can use the ** global cache. */ index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit); if (index == NULL) return(NULL); cuddRef(index); do { dd->reordered = 0; res = addDoIthBit(dd, f, index); } while (dd->reordered == 1); if (res == NULL) { Cudd_RecursiveDeref(dd, index); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, index); cuddDeref(res); return(res); } /* end of Cudd_addIthBit */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addIthBit.] Description [Performs the recursive step for Cudd_addIthBit. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * addDoIthBit( DdManager * dd, DdNode * f, DdNode * index) { DdNode *res, *T, *E; DdNode *fv, *fvn; int mask, value; int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { mask = 1 << ((int) cuddV(index)); value = (int) cuddV(f); return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd)); } /* Check cache. */ res = cuddCacheLookup2(dd,addDoIthBit,f,index); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = addDoIthBit(dd,fv,index); if (T == NULL) return(NULL); cuddRef(T); E = addDoIthBit(dd,fvn,index); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,addDoIthBit,f,index,res); return(res); } /* end of addDoIthBit */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAddInv.c000066400000000000000000000157441300674244400236700ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAddInv.c] PackageName [cudd] Synopsis [Function to compute the scalar inverse of an ADD.] Description [External procedures included in this module:
  • Cudd_addScalarInverse()
Internal procedures included in this module:
  • cuddAddScalarInverseRecur()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAddInv.c,v 1.9 2004/08/13 18:04:45 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the scalar inverse of an ADD.] Description [Computes an n ADD where the discriminants are the multiplicative inverses of the corresponding discriminants of the argument ADD. Returns a pointer to the resulting ADD in case of success. Returns NULL if any discriminants smaller than epsilon is encountered.] SideEffects [None] ******************************************************************************/ DdNode * Cudd_addScalarInverse( DdManager * dd, DdNode * f, DdNode * epsilon) { DdNode *res; if (!cuddIsConstant(epsilon)) { (void) fprintf(dd->err,"Invalid epsilon\n"); return(NULL); } do { dd->reordered = 0; res = cuddAddScalarInverseRecur(dd,f,epsilon); } while (dd->reordered == 1); return(res); } /* end of Cudd_addScalarInverse */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of addScalarInverse.] Description [Returns a pointer to the resulting ADD in case of success. Returns NULL if any discriminants smaller than epsilon is encountered.] SideEffects [None] ******************************************************************************/ DdNode * cuddAddScalarInverseRecur( DdManager * dd, DdNode * f, DdNode * epsilon) { DdNode *t, *e, *res; CUDD_VALUE_TYPE value; statLine(dd); if (cuddIsConstant(f)) { if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL); value = 1.0 / cuddV(f); res = cuddUniqueConst(dd,value); return(res); } res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon); if (res != NULL) return(res); t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon); if (t == NULL) return(NULL); cuddRef(t); e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res); return(res); } /* end of cuddAddScalarInverseRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAddIte.c000066400000000000000000000440371300674244400236520ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAddIte.c] PackageName [cudd] Synopsis [ADD ITE function and satellites.] Description [External procedures included in this module:
  • Cudd_addIte()
  • Cudd_addIteConstant()
  • Cudd_addEvalConst()
  • Cudd_addCmpl()
  • Cudd_addLeq()
Internal procedures included in this module:
  • cuddAddIteRecur()
  • cuddAddCmplRecur()
Static procedures included in this module:
  • addVarToConst()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.15 2004/08/13 18:04:45 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void addVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements ITE(f,g,h).] Description [Implements ITE(f,g,h). This procedure assumes that f is a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addIteConstant Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *res; do { dd->reordered = 0; res = cuddAddIteRecur(dd,f,g,h); } while (dd->reordered == 1); return(res); } /* end of Cudd_addIte */ /**Function******************************************************************** Synopsis [Implements ITEconstant for ADDs.] Description [Implements ITEconstant for ADDs. f must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may or may not be constant) or DD_NON_CONSTANT. No new nodes are created. This function can be used, for instance, to check that g has a constant value (specified by h) whenever f is 1. If the constant value is unknown, then one should use Cudd_addEvalConst.] SideEffects [None] SeeAlso [Cudd_addIte Cudd_addEvalConst Cudd_bddIteConstant] ******************************************************************************/ DdNode * Cudd_addIteConstant( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *one,*zero; DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e; unsigned int topf,topg,toph,v; statLine(dd); /* Trivial cases. */ if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ return(g); } if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ return(h); } /* From now on, f is known not to be a constant. */ addVarToConst(f,&g,&h,one,zero); /* Check remaining one variable cases. */ if (g == h) { /* ITE(F,G,G) = G */ return(g); } if (cuddIsConstant(g) && cuddIsConstant(h)) { return(DD_NON_CONSTANT); } topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); toph = cuddI(dd,h->index); v = ddMin(topg,toph); /* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */ if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) { return(DD_NON_CONSTANT); } /* Check cache. */ r = cuddConstantLookup(dd,DD_ADD_ITE_CONSTANT_TAG,f,g,h); if (r != NULL) { return(r); } /* Compute cofactors. */ if (topf <= v) { v = ddMin(topf,v); /* v = top_var(F,G,H) */ Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } if (topg == v) { Gv = cuddT(g); Gnv = cuddE(g); } else { Gv = Gnv = g; } if (toph == v) { Hv = cuddT(h); Hnv = cuddE(h); } else { Hv = Hnv = h; } /* Recursive step. */ t = Cudd_addIteConstant(dd,Fv,Gv,Hv); if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) { cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); return(DD_NON_CONSTANT); } e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv); if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) { cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); return(DD_NON_CONSTANT); } cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t); return(t); } /* end of Cudd_addIteConstant */ /**Function******************************************************************** Synopsis [Checks whether ADD g is constant whenever ADD f is 1.] Description [Checks whether ADD g is constant whenever ADD f is 1. f must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may or may not be constant) or DD_NON_CONSTANT. If f is identically 0, the check is assumed to be successful, and the background value is returned. No new nodes are created.] SideEffects [None] SeeAlso [Cudd_addIteConstant Cudd_addLeq] ******************************************************************************/ DdNode * Cudd_addEvalConst( DdManager * dd, DdNode * f, DdNode * g) { DdNode *zero; DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e; unsigned int topf,topg; #ifdef DD_DEBUG assert(!Cudd_IsComplement(f)); #endif statLine(dd); /* Terminal cases. */ if (f == DD_ONE(dd) || cuddIsConstant(g)) { return(g); } if (f == (zero = DD_ZERO(dd))) { return(dd->background); } #ifdef DD_DEBUG assert(!cuddIsConstant(f)); #endif /* From now on, f and g are known not to be constants. */ topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); /* Check cache. */ r = cuddConstantLookup(dd,DD_ADD_EVAL_CONST_TAG,f,g,g); if (r != NULL) { return(r); } /* Compute cofactors. */ if (topf <= topg) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } if (topg <= topf) { Gv = cuddT(g); Gnv = cuddE(g); } else { Gv = Gnv = g; } /* Recursive step. */ if (Fv != zero) { t = Cudd_addEvalConst(dd,Fv,Gv); if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) { cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT); return(DD_NON_CONSTANT); } if (Fnv != zero) { e = Cudd_addEvalConst(dd,Fnv,Gnv); if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) { cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT); return(DD_NON_CONSTANT); } } cuddCacheInsert2(dd,Cudd_addEvalConst,f,g,t); return(t); } else { /* Fnv must be != zero */ e = Cudd_addEvalConst(dd,Fnv,Gnv); cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e); return(e); } } /* end of Cudd_addEvalConst */ /**Function******************************************************************** Synopsis [Computes the complement of an ADD a la C language.] Description [Computes the complement of an ADD a la C language: The complement of 0 is 1 and the complement of everything else is 0. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addNegate] ******************************************************************************/ DdNode * Cudd_addCmpl( DdManager * dd, DdNode * f) { DdNode *res; do { dd->reordered = 0; res = cuddAddCmplRecur(dd,f); } while (dd->reordered == 1); return(res); } /* end of Cudd_addCmpl */ /**Function******************************************************************** Synopsis [Determines whether f is less than or equal to g.] Description [Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created. This procedure works for arbitrary ADDs. For 0-1 ADDs Cudd_addEvalConst is more efficient.] SideEffects [None] SeeAlso [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq] ******************************************************************************/ int Cudd_addLeq( DdManager * dd, DdNode * f, DdNode * g) { DdNode *tmp, *fv, *fvn, *gv, *gvn; unsigned int topf, topg, res; /* Terminal cases. */ if (f == g) return(1); statLine(dd); if (cuddIsConstant(f)) { if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g)); if (f == DD_MINUS_INFINITY(dd)) return(1); if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */ } if (g == DD_PLUS_INFINITY(dd)) return(1); if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */ /* Check cache. */ tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_addLeq,f,g); if (tmp != NULL) { return(tmp == DD_ONE(dd)); } /* Compute cofactors. One of f and g is not constant. */ topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); if (topf <= topg) { fv = cuddT(f); fvn = cuddE(f); } else { fv = fvn = f; } if (topg <= topf) { gv = cuddT(g); gvn = cuddE(g); } else { gv = gvn = g; } res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv); /* Store result in cache and return. */ cuddCacheInsert2(dd,(DD_CTFP) Cudd_addLeq,f,g, Cudd_NotCond(DD_ONE(dd),res==0)); return(res); } /* end of Cudd_addLeq */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_addIte(f,g,h).] Description [Implements the recursive step of Cudd_addIte(f,g,h). Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addIte] ******************************************************************************/ DdNode * cuddAddIteRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *one,*zero; DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e; unsigned int topf,topg,toph,v; int index = -1; statLine(dd); /* Trivial cases. */ /* One variable cases. */ if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ return(g); } if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ return(h); } /* From now on, f is known to not be a constant. */ addVarToConst(f,&g,&h,one,zero); /* Check remaining one variable cases. */ if (g == h) { /* ITE(F,G,G) = G */ return(g); } if (g == one) { /* ITE(F,1,0) = F */ if (h == zero) return(f); } topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); toph = cuddI(dd,h->index); v = ddMin(topg,toph); /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */ if (topf < v && cuddT(f) == one && cuddE(f) == zero) { r = cuddUniqueInter(dd,(int)f->index,g,h); return(r); } if (topf < v && cuddT(f) == zero && cuddE(f) == one) { r = cuddUniqueInter(dd,(int)f->index,h,g); return(r); } /* Check cache. */ r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h); if (r != NULL) { return(r); } /* Compute cofactors. */ if (topf <= v) { v = ddMin(topf,v); /* v = top_var(F,G,H) */ index = f->index; Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } if (topg == v) { index = g->index; Gv = cuddT(g); Gnv = cuddE(g); } else { Gv = Gnv = g; } if (toph == v) { index = h->index; Hv = cuddT(h); Hnv = cuddE(h); } else { Hv = Hnv = h; } /* Recursive step. */ t = cuddAddIteRecur(dd,Fv,Gv,Hv); if (t == NULL) return(NULL); cuddRef(t); e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv); if (e == NULL) { Cudd_RecursiveDeref(dd,t); return(NULL); } cuddRef(e); r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); if (r == NULL) { Cudd_RecursiveDeref(dd,t); Cudd_RecursiveDeref(dd,e); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r); return(r); } /* end of cuddAddIteRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addCmpl.] Description [Performs the recursive step of Cudd_addCmpl. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addCmpl] ******************************************************************************/ DdNode * cuddAddCmplRecur( DdManager * dd, DdNode * f) { DdNode *one,*zero; DdNode *r,*Fv,*Fnv,*t,*e; statLine(dd); one = DD_ONE(dd); zero = DD_ZERO(dd); if (cuddIsConstant(f)) { if (f == zero) { return(one); } else { return(zero); } } r = cuddCacheLookup1(dd,Cudd_addCmpl,f); if (r != NULL) { return(r); } Fv = cuddT(f); Fnv = cuddE(f); t = cuddAddCmplRecur(dd,Fv); if (t == NULL) return(NULL); cuddRef(t); e = cuddAddCmplRecur(dd,Fnv); if (e == NULL) { Cudd_RecursiveDeref(dd,t); return(NULL); } cuddRef(e); r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); if (r == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert1(dd,Cudd_addCmpl,f,r); return(r); } /* end of cuddAddCmplRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Replaces variables with constants if possible (part of canonical form).] Description [] SideEffects [None] ******************************************************************************/ static void addVarToConst( DdNode * f, DdNode ** gp, DdNode ** hp, DdNode * one, DdNode * zero) { DdNode *g = *gp; DdNode *h = *hp; if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ *gp = one; } if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ *hp = zero; } } /* end of addVarToConst */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAddNeg.c000066400000000000000000000214211300674244400236320ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAddNeg.c] PackageName [cudd] Synopsis [Function to compute the negation of an ADD.] Description [External procedures included in this module:
  • Cudd_addNegate()
  • Cudd_addRoundOff()
Internal procedures included in this module:
  • cuddAddNegateRecur()
  • cuddAddRoundOffRecur()
] Author [Fabio Somenzi, Balakrishna Kumthekar] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAddNeg.c,v 1.12 2009/02/20 02:14:58 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the additive inverse of an ADD.] Description [Computes the additive inverse of an ADD. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addCmpl] ******************************************************************************/ DdNode * Cudd_addNegate( DdManager * dd, DdNode * f) { DdNode *res; do { res = cuddAddNegateRecur(dd,f); } while (dd->reordered == 1); return(res); } /* end of Cudd_addNegate */ /**Function******************************************************************** Synopsis [Rounds off the discriminants of an ADD.] Description [Rounds off the discriminants of an ADD. The discriminants are rounded off to N digits after the decimal. Returns a pointer to the result ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_addRoundOff( DdManager * dd, DdNode * f, int N) { DdNode *res; double trunc = pow(10.0,(double)N); do { res = cuddAddRoundOffRecur(dd,f,trunc); } while (dd->reordered == 1); return(res); } /* end of Cudd_addRoundOff */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_addNegate.] Description [Implements the recursive step of Cudd_addNegate. Returns a pointer to the result.] SideEffects [None] ******************************************************************************/ DdNode * cuddAddNegateRecur( DdManager * dd, DdNode * f) { DdNode *res, *fv, *fvn, *T, *E; statLine(dd); /* Check terminal cases. */ if (cuddIsConstant(f)) { res = cuddUniqueConst(dd,-cuddV(f)); return(res); } /* Check cache */ res = cuddCacheLookup1(dd,Cudd_addNegate,f); if (res != NULL) return(res); /* Recursive Step */ fv = cuddT(f); fvn = cuddE(f); T = cuddAddNegateRecur(dd,fv); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddNegateRecur(dd,fvn); if (E == NULL) { Cudd_RecursiveDeref(dd,T); return(NULL); } cuddRef(E); res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert1(dd,Cudd_addNegate,f,res); return(res); } /* end of cuddAddNegateRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_addRoundOff.] Description [Implements the recursive step of Cudd_addRoundOff. Returns a pointer to the result.] SideEffects [None] ******************************************************************************/ DdNode * cuddAddRoundOffRecur( DdManager * dd, DdNode * f, double trunc) { DdNode *res, *fv, *fvn, *T, *E; double n; DD_CTFP1 cacheOp; statLine(dd); if (cuddIsConstant(f)) { n = ceil(cuddV(f)*trunc)/trunc; res = cuddUniqueConst(dd,n); return(res); } cacheOp = (DD_CTFP1) Cudd_addRoundOff; res = cuddCacheLookup1(dd,cacheOp,f); if (res != NULL) { return(res); } /* Recursive Step */ fv = cuddT(f); fvn = cuddE(f); T = cuddAddRoundOffRecur(dd,fv,trunc); if (T == NULL) { return(NULL); } cuddRef(T); E = cuddAddRoundOffRecur(dd,fvn,trunc); if (E == NULL) { Cudd_RecursiveDeref(dd,T); return(NULL); } cuddRef(E); res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); return(NULL); } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert1(dd,cacheOp,f,res); return(res); } /* end of cuddAddRoundOffRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAddWalsh.c000066400000000000000000000314101300674244400241760ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAddWalsh.c] PackageName [cudd] Synopsis [Functions that generate Walsh matrices and residue functions in ADD form.] Description [External procedures included in this module:
  • Cudd_addWalsh()
  • Cudd_addResidue()
Static procedures included in this module:
  • addWalshInt()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAddWalsh.c,v 1.10 2008/04/17 21:17:11 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * addWalshInt (DdManager *dd, DdNode **x, DdNode **y, int n); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Generates a Walsh matrix in ADD form.] Description [Generates a Walsh matrix in ADD form. Returns a pointer to the matrixi if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ DdNode * Cudd_addWalsh( DdManager * dd, DdNode ** x, DdNode ** y, int n) { DdNode *res; do { dd->reordered = 0; res = addWalshInt(dd, x, y, n); } while (dd->reordered == 1); return(res); } /* end of Cudd_addWalsh */ /**Function******************************************************************** Synopsis [Builds an ADD for the residue modulo m of an n-bit number.] Description [Builds an ADD for the residue modulo m of an n-bit number. The modulus must be at least 2, and the number of bits at least 1. Parameter options specifies whether the MSB should be on top or the LSB; and whther the number whose residue is computed is in two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's complement residue. To request MSB on top and two's complement residue simultaneously, one can OR the two macros: CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC. Cudd_addResidue returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_addResidue( DdManager * dd /* manager */, int n /* number of bits */, int m /* modulus */, int options /* options */, int top /* index of top variable */) { int msbLsb; /* MSB on top (1) or LSB on top (0) */ int tc; /* two's complement (1) or unsigned (0) */ int i, j, k, t, residue, thisOne, previous, index; DdNode **array[2], *var, *tmp, *res; /* Sanity check. */ if (n < 1 && m < 2) return(NULL); msbLsb = options & CUDD_RESIDUE_MSB; tc = options & CUDD_RESIDUE_TC; /* Allocate and initialize working arrays. */ array[0] = ABC_ALLOC(DdNode *,m); if (array[0] == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } array[1] = ABC_ALLOC(DdNode *,m); if (array[1] == NULL) { ABC_FREE(array[0]); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < m; i++) { array[0][i] = array[1][i] = NULL; } /* Initialize residues. */ for (i = 0; i < m; i++) { tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i); if (tmp == NULL) { for (j = 0; j < i; j++) { Cudd_RecursiveDeref(dd,array[1][j]); } ABC_FREE(array[0]); ABC_FREE(array[1]); return(NULL); } cuddRef(tmp); array[1][i] = tmp; } /* Main iteration. */ residue = 1; /* residue of 2**0 */ for (k = 0; k < n; k++) { /* Choose current and previous arrays. */ thisOne = k & 1; previous = thisOne ^ 1; /* Build an ADD projection function. */ if (msbLsb) { index = top+n-k-1; } else { index = top+k; } var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd)); if (var == NULL) { for (j = 0; j < m; j++) { Cudd_RecursiveDeref(dd,array[previous][j]); } ABC_FREE(array[0]); ABC_FREE(array[1]); return(NULL); } cuddRef(var); for (i = 0; i < m; i ++) { t = (i + residue) % m; tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]); if (tmp == NULL) { for (j = 0; j < i; j++) { Cudd_RecursiveDeref(dd,array[thisOne][j]); } for (j = 0; j < m; j++) { Cudd_RecursiveDeref(dd,array[previous][j]); } ABC_FREE(array[0]); ABC_FREE(array[1]); return(NULL); } cuddRef(tmp); array[thisOne][i] = tmp; } /* One layer completed. Free the other array for the next iteration. */ for (i = 0; i < m; i++) { Cudd_RecursiveDeref(dd,array[previous][i]); } Cudd_RecursiveDeref(dd,var); /* Update residue of 2**k. */ residue = (2 * residue) % m; /* Adjust residue for MSB, if this is a two's complement number. */ if (tc && (k == n - 1)) { residue = (m - residue) % m; } } /* We are only interested in the 0-residue node of the top layer. */ for (i = 1; i < m; i++) { Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]); } res = array[(n - 1) & 1][0]; ABC_FREE(array[0]); ABC_FREE(array[1]); cuddDeref(res); return(res); } /* end of Cudd_addResidue */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_addWalsh.] Description [Generates a Walsh matrix in ADD form. Returns a pointer to the matrixi if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ static DdNode * addWalshInt( DdManager * dd, DdNode ** x, DdNode ** y, int n) { DdNode *one, *minusone; DdNode *t = NULL, *u = NULL, *t1, *u1, *v, *w; int i; one = DD_ONE(dd); if (n == 0) return(one); /* Build bottom part of ADD outside loop */ minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1); if (minusone == NULL) return(NULL); cuddRef(minusone); v = Cudd_addIte(dd, y[n-1], minusone, one); if (v == NULL) { Cudd_RecursiveDeref(dd, minusone); return(NULL); } cuddRef(v); u = Cudd_addIte(dd, x[n-1], v, one); if (u == NULL) { Cudd_RecursiveDeref(dd, minusone); Cudd_RecursiveDeref(dd, v); return(NULL); } cuddRef(u); Cudd_RecursiveDeref(dd, v); if (n>1) { w = Cudd_addIte(dd, y[n-1], one, minusone); if (w == NULL) { Cudd_RecursiveDeref(dd, minusone); Cudd_RecursiveDeref(dd, u); return(NULL); } cuddRef(w); t = Cudd_addIte(dd, x[n-1], w, minusone); if (t == NULL) { Cudd_RecursiveDeref(dd, minusone); Cudd_RecursiveDeref(dd, u); Cudd_RecursiveDeref(dd, w); return(NULL); } cuddRef(t); Cudd_RecursiveDeref(dd, w); } cuddDeref(minusone); /* minusone is in the result; it won't die */ /* Loop to build the rest of the ADD */ for (i=n-2; i>=0; i--) { t1 = t; u1 = u; v = Cudd_addIte(dd, y[i], t1, u1); if (v == NULL) { Cudd_RecursiveDeref(dd, u1); Cudd_RecursiveDeref(dd, t1); return(NULL); } cuddRef(v); u = Cudd_addIte(dd, x[i], v, u1); if (u == NULL) { Cudd_RecursiveDeref(dd, u1); Cudd_RecursiveDeref(dd, t1); Cudd_RecursiveDeref(dd, v); return(NULL); } cuddRef(u); Cudd_RecursiveDeref(dd, v); if (i>0) { w = Cudd_addIte(dd, y[i], u1, t1); if (w == NULL) { Cudd_RecursiveDeref(dd, u1); Cudd_RecursiveDeref(dd, t1); Cudd_RecursiveDeref(dd, u); return(NULL); } cuddRef(w); t = Cudd_addIte(dd, x[i], w, t1); if (u == NULL) { Cudd_RecursiveDeref(dd, u1); Cudd_RecursiveDeref(dd, t1); Cudd_RecursiveDeref(dd, u); Cudd_RecursiveDeref(dd, w); return(NULL); } cuddRef(t); Cudd_RecursiveDeref(dd, w); } Cudd_RecursiveDeref(dd, u1); Cudd_RecursiveDeref(dd, t1); } cuddDeref(u); return(u); } /* end of addWalshInt */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAndAbs.c000066400000000000000000000306021300674244400236410ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAndAbs.c] PackageName [cudd] Synopsis [Combined AND and existential abstraction for BDDs] Description [External procedures included in this module:
  • Cudd_bddAndAbstract()
  • Cudd_bddAndAbstractLimit()
Internal procedures included in this module:
  • cuddBddAndAbstractRecur()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAndAbs.c,v 1.19 2004/08/13 18:04:46 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Takes the AND of two BDDs and simultaneously abstracts the variables in cube.] Description [Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise. Cudd_bddAndAbstract implements the semiring matrix multiplication algorithm for the boolean semiring.] SideEffects [None] SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd] ******************************************************************************/ DdNode * Cudd_bddAndAbstract( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube) { DdNode *res; do { manager->reordered = 0; res = cuddBddAndAbstractRecur(manager, f, g, cube); } while (manager->reordered == 1); return(res); } /* end of Cudd_bddAndAbstract */ /**Function******************************************************************** Synopsis [Takes the AND of two BDDs and simultaneously abstracts the variables in cube. Returns NULL if too many nodes are required.] Description [Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise. In particular, if the number of new nodes created exceeds limit, this function returns NULL.] SideEffects [None] SeeAlso [Cudd_bddAndAbstract] ******************************************************************************/ DdNode * Cudd_bddAndAbstractLimit( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, unsigned int limit) { DdNode *res; unsigned int saveLimit = manager->maxLive; manager->maxLive = (manager->keys - manager->dead) + (manager->keysZ - manager->deadZ) + limit; do { manager->reordered = 0; res = cuddBddAndAbstractRecur(manager, f, g, cube); } while (manager->reordered == 1); manager->maxLive = saveLimit; return(res); } /* end of Cudd_bddAndAbstractLimit */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Takes the AND of two BDDs and simultaneously abstracts the variables in cube.] Description [Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddAndAbstract] ******************************************************************************/ DdNode * cuddBddAndAbstractRecur( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube) { DdNode *F, *ft, *fe, *G, *gt, *ge; DdNode *one, *zero, *r, *t, *e; unsigned int topf, topg, topcube, top, index; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* Terminal cases. */ if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); if (f == one && g == one) return(one); if (cube == one) { return(cuddBddAndRecur(manager, f, g)); } if (f == one || f == g) { return(cuddBddExistAbstractRecur(manager, g, cube)); } if (g == one) { return(cuddBddExistAbstractRecur(manager, f, cube)); } /* At this point f, g, and cube are not constant. */ if (f > g) { /* Try to increase cache efficiency. */ DdNode *tmp = f; f = g; g = tmp; } /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ F = Cudd_Regular(f); G = Cudd_Regular(g); topf = manager->perm[F->index]; topg = manager->perm[G->index]; top = ddMin(topf, topg); topcube = manager->perm[cube->index]; while (topcube < top) { cube = cuddT(cube); if (cube == one) { return(cuddBddAndRecur(manager, f, g)); } topcube = manager->perm[cube->index]; } /* Now, topcube >= top. */ /* Check cache. */ if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); if (r != NULL) { return(r); } } if ( manager->TimeStop && Abc_Clock() > manager->TimeStop ) return NULL; if (topf == top) { index = F->index; ft = cuddT(F); fe = cuddE(F); if (Cudd_IsComplement(f)) { ft = Cudd_Not(ft); fe = Cudd_Not(fe); } } else { index = G->index; ft = fe = f; } if (topg == top) { gt = cuddT(G); ge = cuddE(G); if (Cudd_IsComplement(g)) { gt = Cudd_Not(gt); ge = Cudd_Not(ge); } } else { gt = ge = g; } if (topcube == top) { /* quantify */ DdNode *Cube = cuddT(cube); t = cuddBddAndAbstractRecur(manager, ft, gt, Cube); if (t == NULL) return(NULL); /* Special case: 1 OR anything = 1. Hence, no need to compute ** the else branch if t is 1. Likewise t + t * anything == t. ** Notice that t == fe implies that fe does not depend on the ** variables in Cube. Likewise for t == ge. */ if (t == one || t == fe || t == ge) { if (F->ref != 1 || G->ref != 1) cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, t); return(t); } cuddRef(t); /* Special case: t + !t * anything == t + anything. */ if (t == Cudd_Not(fe)) { e = cuddBddExistAbstractRecur(manager, ge, Cube); } else if (t == Cudd_Not(ge)) { e = cuddBddExistAbstractRecur(manager, fe, Cube); } else { e = cuddBddAndAbstractRecur(manager, fe, ge, Cube); } if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } if (t == e) { r = t; cuddDeref(t); } else { cuddRef(e); r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); cuddRef(r); Cudd_DelayedDerefBdd(manager, t); Cudd_DelayedDerefBdd(manager, e); cuddDeref(r); } } else { t = cuddBddAndAbstractRecur(manager, ft, gt, cube); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddAndAbstractRecur(manager, fe, ge, cube); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } if (t == e) { r = t; cuddDeref(t); } else { cuddRef(e); if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager, (int) index, Cudd_Not(t), Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } cuddDeref(e); cuddDeref(t); } } if (F->ref != 1 || G->ref != 1) cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); return (r); } /* end of cuddBddAndAbstractRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddAnneal.c000066400000000000000000000600511300674244400237100ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddAnneal.c] PackageName [cudd] Synopsis [Reordering of DDs based on simulated annealing] Description [Internal procedures included in this file:
  • cuddAnnealing()
Static procedures included in this file:
  • stopping_criterion()
  • random_generator()
  • ddExchange()
  • ddJumpingAux()
  • ddJumpingUp()
  • ddJumpingDown()
  • siftBackwardProb()
  • copyOrder()
  • restoreOrder()
] SeeAlso [] Author [Jae-Young Jang, Jorgen Sivesind] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /* Annealing parameters */ #define BETA 0.6 #define ALPHA 0.90 #define EXC_PROB 0.4 #define JUMP_UP_PROB 0.36 #define MAXGEN_RATIO 15.0 #define STOP_TEMP 1.0 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.14 2004/08/13 18:04:46 fabio Exp $"; #endif #ifdef DD_STATS extern int ddTotalNumberSwapping; extern int ddTotalNISwaps; static int tosses; static int acceptances; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int stopping_criterion (int c1, int c2, int c3, int c4, double temp); static double random_generator (void); static int ddExchange (DdManager *table, int x, int y, double temp); static int ddJumpingAux (DdManager *table, int x, int x_low, int x_high, double temp); static Move * ddJumpingUp (DdManager *table, int x, int x_low, int initial_size); static Move * ddJumpingDown (DdManager *table, int x, int x_high, int initial_size); static int siftBackwardProb (DdManager *table, Move *moves, int size, double temp); static void copyOrder (DdManager *table, int *array, int lower, int upper); static int restoreOrder (DdManager *table, int *array, int lower, int upper); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Get new variable-order by simulated annealing algorithm.] Description [Get x, y by random selection. Choose either exchange or jump randomly. In case of jump, choose between jump_up and jump_down randomly. Do exchange or jump and get optimal case. Loop until there is no improvement or temperature reaches minimum. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddAnnealing( DdManager * table, int lower, int upper) { int nvars; int size; int x,y; int result; int c1, c2, c3, c4; int BestCost; int *BestOrder; double NewTemp, temp; double rand1; int innerloop, maxGen; int ecount, ucount, dcount; nvars = upper - lower + 1; result = cuddSifting(table,lower,upper); #ifdef DD_STATS (void) fprintf(table->out,"\n"); #endif if (result == 0) return(0); size = table->keys - table->isolated; /* Keep track of the best order. */ BestCost = size; BestOrder = ABC_ALLOC(int,nvars); if (BestOrder == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } copyOrder(table,BestOrder,lower,upper); temp = BETA * size; maxGen = (int) (MAXGEN_RATIO * nvars); c1 = size + 10; c2 = c1 + 10; c3 = size; c4 = c2 + 10; ecount = ucount = dcount = 0; while (!stopping_criterion(c1, c2, c3, c4, temp)) { #ifdef DD_STATS (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t", temp,size,maxGen); tosses = acceptances = 0; #endif for (innerloop = 0; innerloop < maxGen; innerloop++) { /* Choose x, y randomly. */ x = (int) Cudd_Random() % nvars; do { y = (int) Cudd_Random() % nvars; } while (x == y); x += lower; y += lower; if (x > y) { int tmp = x; x = y; y = tmp; } /* Choose move with roulette wheel. */ rand1 = random_generator(); if (rand1 < EXC_PROB) { result = ddExchange(table,x,y,temp); /* exchange */ ecount++; #if 0 (void) fprintf(table->out, "Exchange of %d and %d: size = %d\n", x,y,table->keys - table->isolated); #endif } else if (rand1 < EXC_PROB + JUMP_UP_PROB) { result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */ ucount++; #if 0 (void) fprintf(table->out, "Jump up of %d to %d: size = %d\n", y,x,table->keys - table->isolated); #endif } else { result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */ dcount++; #if 0 (void) fprintf(table->out, "Jump down of %d to %d: size = %d\n", x,y,table->keys - table->isolated); #endif } if (!result) { ABC_FREE(BestOrder); return(0); } size = table->keys - table->isolated; /* keep current size */ if (size < BestCost) { /* update best order */ BestCost = size; copyOrder(table,BestOrder,lower,upper); } } c1 = c2; c2 = c3; c3 = c4; c4 = size; NewTemp = ALPHA * temp; if (NewTemp >= 1.0) { maxGen = (int)(log(NewTemp) / log(temp) * maxGen); } temp = NewTemp; /* control variable */ #ifdef DD_STATS (void) fprintf(table->out,"uphill = %d\taccepted = %d\n", tosses,acceptances); fflush(table->out); #endif } result = restoreOrder(table,BestOrder,lower,upper); ABC_FREE(BestOrder); if (!result) return(0); #ifdef DD_STATS fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount); fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount); fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount); #endif return(1); } /* end of cuddAnnealing */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Checks termination condition.] Description [If temperature is STOP_TEMP or there is no improvement then terminates. Returns 1 if the termination criterion is met; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int stopping_criterion( int c1, int c2, int c3, int c4, double temp) { if (STOP_TEMP < temp) { return(0); } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) { return(1); } else { return(0); } } /* end of stopping_criterion */ /**Function******************************************************************** Synopsis [Random number generator.] Description [Returns a double precision value between 0.0 and 1.0.] SideEffects [None] SeeAlso [] ******************************************************************************/ static double random_generator(void) { return((double)(Cudd_Random() / 2147483561.0)); } /* end of random_generator */ /**Function******************************************************************** Synopsis [This function is for exchanging two variables, x and y.] Description [This is the same funcion as ddSwapping except for comparison expression. Use probability function, exp(-size_change/temp).] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddExchange( DdManager * table, int x, int y, double temp) { Move *move,*moves; int tmp; int x_ref,y_ref; int x_next,y_next; int size, result; int initial_size, limit_size; x_ref = x; y_ref = y; x_next = cuddNextHigh(table,x); y_next = cuddNextLow(table,y); moves = NULL; initial_size = limit_size = table->keys - table->isolated; for (;;) { if (x_next == y_next) { size = cuddSwapInPlace(table,x,x_next); if (size == 0) goto ddExchangeOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddExchangeOutOfMem; move->x = x; move->y = x_next; move->size = size; move->next = moves; moves = move; size = cuddSwapInPlace(table,y_next,y); if (size == 0) goto ddExchangeOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddExchangeOutOfMem; move->x = y_next; move->y = y; move->size = size; move->next = moves; moves = move; size = cuddSwapInPlace(table,x,x_next); if (size == 0) goto ddExchangeOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddExchangeOutOfMem; move->x = x; move->y = x_next; move->size = size; move->next = moves; moves = move; tmp = x; x = y; y = tmp; } else if (x == y_next) { size = cuddSwapInPlace(table,x,x_next); if (size == 0) goto ddExchangeOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddExchangeOutOfMem; move->x = x; move->y = x_next; move->size = size; move->next = moves; moves = move; tmp = x; x = y; y = tmp; } else { size = cuddSwapInPlace(table,x,x_next); if (size == 0) goto ddExchangeOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddExchangeOutOfMem; move->x = x; move->y = x_next; move->size = size; move->next = moves; moves = move; size = cuddSwapInPlace(table,y_next,y); if (size == 0) goto ddExchangeOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddExchangeOutOfMem; move->x = y_next; move->y = y; move->size = size; move->next = moves; moves = move; x = x_next; y = y_next; } x_next = cuddNextHigh(table,x); y_next = cuddNextLow(table,y); if (x_next > y_ref) break; if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) { break; } else if (size < limit_size) { limit_size = size; } } if (y_next>=x_ref) { size = cuddSwapInPlace(table,y_next,y); if (size == 0) goto ddExchangeOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddExchangeOutOfMem; move->x = y_next; move->y = y; move->size = size; move->next = moves; moves = move; } /* move backward and stop at best position or accept uphill move */ result = siftBackwardProb(table,moves,initial_size,temp); if (!result) goto ddExchangeOutOfMem; while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(1); ddExchangeOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(0); } /* end of ddExchange */ /**Function******************************************************************** Synopsis [Moves a variable to a specified position.] Description [If x==x_low, it executes jumping_down. If x==x_high, it executes jumping_up. This funcion is similar to ddSiftingAux. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddJumpingAux( DdManager * table, int x, int x_low, int x_high, double temp) { Move *move; Move *moves; /* list of moves */ int initial_size; int result; initial_size = table->keys - table->isolated; #ifdef DD_DEBUG assert(table->subtables[x].keys > 0); #endif moves = NULL; if (cuddNextLow(table,x) < x_low) { if (cuddNextHigh(table,x) > x_high) return(1); moves = ddJumpingDown(table,x,x_high,initial_size); /* after that point x --> x_high unless early termination */ if (moves == NULL) goto ddJumpingAuxOutOfMem; /* move backward and stop at best position or accept uphill move */ result = siftBackwardProb(table,moves,initial_size,temp); if (!result) goto ddJumpingAuxOutOfMem; } else if (cuddNextHigh(table,x) > x_high) { moves = ddJumpingUp(table,x,x_low,initial_size); /* after that point x --> x_low unless early termination */ if (moves == NULL) goto ddJumpingAuxOutOfMem; /* move backward and stop at best position or accept uphill move */ result = siftBackwardProb(table,moves,initial_size,temp); if (!result) goto ddJumpingAuxOutOfMem; } else { (void) fprintf(table->err,"Unexpected condition in ddJumping\n"); goto ddJumpingAuxOutOfMem; } while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(1); ddJumpingAuxOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(0); } /* end of ddJumpingAux */ /**Function******************************************************************** Synopsis [This function is for jumping up.] Description [This is a simplified version of ddSiftingUp. It does not use lower bounding. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * ddJumpingUp( DdManager * table, int x, int x_low, int initial_size) { Move *moves; Move *move; int y; int size; int limit_size = initial_size; moves = NULL; y = cuddNextLow(table,x); while (y >= x_low) { size = cuddSwapInPlace(table,y,x); if (size == 0) goto ddJumpingUpOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddJumpingUpOutOfMem; move->x = y; move->y = x; move->size = size; move->next = moves; moves = move; if ((double) size > table->maxGrowth * (double) limit_size) { break; } else if (size < limit_size) { limit_size = size; } x = y; y = cuddNextLow(table,x); } return(moves); ddJumpingUpOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(NULL); } /* end of ddJumpingUp */ /**Function******************************************************************** Synopsis [This function is for jumping down.] Description [This is a simplified version of ddSiftingDown. It does not use lower bounding. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * ddJumpingDown( DdManager * table, int x, int x_high, int initial_size) { Move *moves; Move *move; int y; int size; int limit_size = initial_size; moves = NULL; y = cuddNextHigh(table,x); while (y <= x_high) { size = cuddSwapInPlace(table,x,y); if (size == 0) goto ddJumpingDownOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddJumpingDownOutOfMem; move->x = x; move->y = y; move->size = size; move->next = moves; moves = move; if ((double) size > table->maxGrowth * (double) limit_size) { break; } else if (size < limit_size) { limit_size = size; } x = y; y = cuddNextHigh(table,x); } return(moves); ddJumpingDownOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(NULL); } /* end of ddJumpingDown */ /**Function******************************************************************** Synopsis [Returns the DD to the best position encountered during sifting if there was improvement.] Description [Otherwise, "tosses a coin" to decide whether to keep the current configuration or return the DD to the original one. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int siftBackwardProb( DdManager * table, Move * moves, int size, double temp) { Move *move; int res; int best_size = size; double coin, threshold; /* Look for best size during the last sifting */ for (move = moves; move != NULL; move = move->next) { if (move->size < best_size) { best_size = move->size; } } /* If best_size equals size, the last sifting did not produce any ** improvement. We now toss a coin to decide whether to retain ** this change or not. */ if (best_size == size) { coin = random_generator(); #ifdef DD_STATS tosses++; #endif threshold = exp(-((double)(table->keys - table->isolated - size))/temp); if (coin < threshold) { #ifdef DD_STATS acceptances++; #endif return(1); } } /* Either there was improvement, or we have decided not to ** accept the uphill move. Go to best position. */ res = table->keys - table->isolated; for (move = moves; move != NULL; move = move->next) { if (res == best_size) return(1); res = cuddSwapInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); } return(1); } /* end of sift_backward_prob */ /**Function******************************************************************** Synopsis [Copies the current variable order to array.] Description [Copies the current variable order to array. At the same time inverts the permutation.] SideEffects [None] SeeAlso [] ******************************************************************************/ static void copyOrder( DdManager * table, int * array, int lower, int upper) { int i; int nvars; nvars = upper - lower + 1; for (i = 0; i < nvars; i++) { array[i] = table->invperm[i+lower]; } } /* end of copyOrder */ /**Function******************************************************************** Synopsis [Restores the variable order in array by a series of sifts up.] Description [Restores the variable order in array by a series of sifts up. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int restoreOrder( DdManager * table, int * array, int lower, int upper) { int i, x, y, size; int nvars = upper - lower + 1; for (i = 0; i < nvars; i++) { x = table->perm[array[i]]; #ifdef DD_DEBUG assert(x >= lower && x <= upper); #endif y = cuddNextLow(table,x); while (y >= i + lower) { size = cuddSwapInPlace(table,y,x); if (size == 0) return(0); x = y; y = cuddNextLow(table,x); } } return(1); } /* end of restoreOrder */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddApa.c000066400000000000000000000707731300674244400232270ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddApa.c] PackageName [cudd] Synopsis [Arbitrary precision arithmetic functions.] Description [External procedures included in this module:
  • Cudd_ApaNumberOfDigits()
  • Cudd_NewApaNumber()
  • Cudd_ApaCopy()
  • Cudd_ApaAdd()
  • Cudd_ApaSubtract()
  • Cudd_ApaShortDivision()
  • Cudd_ApaIntDivision()
  • Cudd_ApaShiftRight()
  • Cudd_ApaSetToLiteral()
  • Cudd_ApaPowerOfTwo()
  • Cudd_ApaCompare()
  • Cudd_ApaCompareRatios()
  • Cudd_ApaPrintHex()
  • Cudd_ApaPrintDecimal()
  • Cudd_ApaPrintExponential()
  • Cudd_ApaCountMinterm()
  • Cudd_ApaPrintMinterm()
  • Cudd_ApaPrintMintermExp()
  • Cudd_ApaPrintDensity()
Static procedures included in this module:
  • cuddApaCountMintermAux()
  • cuddApaStCountfree()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddApa.c,v 1.19 2009/03/08 01:27:50 fabio Exp $"; #endif static DdNode *background, *zero; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdApaNumber cuddApaCountMintermAux (DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st__table * table); static enum st__retval cuddApaStCountfree (char * key, char * value, char * arg); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Finds the number of digits for an arbitrary precision integer.] Description [Finds the number of digits for an arbitrary precision integer given the maximum number of binary digits. The number of binary digits should be positive. Returns the number of digits if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_ApaNumberOfDigits( int binaryDigits) { int digits; digits = binaryDigits / DD_APA_BITS; if ((digits * DD_APA_BITS) != binaryDigits) digits++; return(digits); } /* end of Cudd_ApaNumberOfDigits */ /**Function******************************************************************** Synopsis [Allocates memory for an arbitrary precision integer.] Description [Allocates memory for an arbitrary precision integer. Returns a pointer to the allocated memory if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdApaNumber Cudd_NewApaNumber( int digits) { return(ABC_ALLOC(DdApaDigit, digits)); } /* end of Cudd_NewApaNumber */ /**Function******************************************************************** Synopsis [Makes a copy of an arbitrary precision integer.] Description [Makes a copy of an arbitrary precision integer.] SideEffects [Changes parameter dest.] SeeAlso [] ******************************************************************************/ void Cudd_ApaCopy( int digits, DdApaNumber source, DdApaNumber dest) { int i; for (i = 0; i < digits; i++) { dest[i] = source[i]; } } /* end of Cudd_ApaCopy */ /**Function******************************************************************** Synopsis [Adds two arbitrary precision integers.] Description [Adds two arbitrary precision integers. Returns the carry out of the most significant digit.] SideEffects [The result of the sum is stored in parameter sum.] SeeAlso [] ******************************************************************************/ DdApaDigit Cudd_ApaAdd( int digits, DdApaNumber a, DdApaNumber b, DdApaNumber sum) { int i; DdApaDoubleDigit partial = 0; for (i = digits - 1; i >= 0; i--) { partial = a[i] + b[i] + DD_MSDIGIT(partial); sum[i] = (DdApaDigit) DD_LSDIGIT(partial); } return((DdApaDigit) DD_MSDIGIT(partial)); } /* end of Cudd_ApaAdd */ /**Function******************************************************************** Synopsis [Subtracts two arbitrary precision integers.] Description [Subtracts two arbitrary precision integers. Returns the borrow out of the most significant digit.] SideEffects [The result of the subtraction is stored in parameter diff.] SeeAlso [] ******************************************************************************/ DdApaDigit Cudd_ApaSubtract( int digits, DdApaNumber a, DdApaNumber b, DdApaNumber diff) { int i; DdApaDoubleDigit partial = DD_APA_BASE; for (i = digits - 1; i >= 0; i--) { partial = DD_MSDIGIT(partial) + DD_APA_MASK + a[i] - b[i]; diff[i] = (DdApaDigit) DD_LSDIGIT(partial); } return((DdApaDigit) DD_MSDIGIT(partial) - 1); } /* end of Cudd_ApaSubtract */ /**Function******************************************************************** Synopsis [Divides an arbitrary precision integer by a digit.] Description [Divides an arbitrary precision integer by a digit.] SideEffects [The quotient is returned in parameter quotient.] SeeAlso [] ******************************************************************************/ DdApaDigit Cudd_ApaShortDivision( int digits, DdApaNumber dividend, DdApaDigit divisor, DdApaNumber quotient) { int i; DdApaDigit remainder; DdApaDoubleDigit partial; remainder = 0; for (i = 0; i < digits; i++) { partial = remainder * DD_APA_BASE + dividend[i]; quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor); remainder = (DdApaDigit) (partial % divisor); } return(remainder); } /* end of Cudd_ApaShortDivision */ /**Function******************************************************************** Synopsis [Divides an arbitrary precision integer by an integer.] Description [Divides an arbitrary precision integer by a 32-bit unsigned integer. Returns the remainder of the division. This procedure relies on the assumption that the number of bits of a DdApaDigit plus the number of bits of an unsigned int is less the number of bits of the mantissa of a double. This guarantees that the product of a DdApaDigit and an unsigned int can be represented without loss of precision by a double. On machines where this assumption is not satisfied, this procedure will malfunction.] SideEffects [The quotient is returned in parameter quotient.] SeeAlso [Cudd_ApaShortDivision] ******************************************************************************/ unsigned int Cudd_ApaIntDivision( int digits, DdApaNumber dividend, unsigned int divisor, DdApaNumber quotient) { int i; double partial; unsigned int remainder = 0; double ddiv = (double) divisor; for (i = 0; i < digits; i++) { partial = (double) remainder * DD_APA_BASE + dividend[i]; quotient[i] = (DdApaDigit) (partial / ddiv); remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv)); } return(remainder); } /* end of Cudd_ApaIntDivision */ /**Function******************************************************************** Synopsis [Shifts right an arbitrary precision integer by one binary place.] Description [Shifts right an arbitrary precision integer by one binary place. The most significant binary digit of the result is taken from parameter in.] SideEffects [The result is returned in parameter b.] SeeAlso [] ******************************************************************************/ void Cudd_ApaShiftRight( int digits, DdApaDigit in, DdApaNumber a, DdApaNumber b) { int i; for (i = digits - 1; i > 0; i--) { b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1)); } b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1)); } /* end of Cudd_ApaShiftRight */ /**Function******************************************************************** Synopsis [Sets an arbitrary precision integer to a one-digit literal.] Description [Sets an arbitrary precision integer to a one-digit literal.] SideEffects [The result is returned in parameter number.] SeeAlso [] ******************************************************************************/ void Cudd_ApaSetToLiteral( int digits, DdApaNumber number, DdApaDigit literal) { int i; for (i = 0; i < digits - 1; i++) number[i] = 0; number[digits - 1] = literal; } /* end of Cudd_ApaSetToLiteral */ /**Function******************************************************************** Synopsis [Sets an arbitrary precision integer to a power of two.] Description [Sets an arbitrary precision integer to a power of two. If the power of two is too large to be represented, the number is set to 0.] SideEffects [The result is returned in parameter number.] SeeAlso [] ******************************************************************************/ void Cudd_ApaPowerOfTwo( int digits, DdApaNumber number, int power) { int i; int index; for (i = 0; i < digits; i++) number[i] = 0; i = digits - 1 - power / DD_APA_BITS; if (i < 0) return; index = power & (DD_APA_BITS - 1); number[i] = 1 << index; } /* end of Cudd_ApaPowerOfTwo */ /**Function******************************************************************** Synopsis [Compares two arbitrary precision integers.] Description [Compares two arbitrary precision integers. Returns 1 if the first number is larger; 0 if they are equal; -1 if the second number is larger.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_ApaCompare( int digitsFirst, DdApaNumber first, int digitsSecond, DdApaNumber second) { int i; int firstNZ, secondNZ; /* Find first non-zero in both numbers. */ for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++) if (first[firstNZ] != 0) break; for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++) if (second[secondNZ] != 0) break; if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1); else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1); for (i = 0; i < digitsFirst - firstNZ; i++) { if (first[firstNZ + i] > second[secondNZ + i]) return(1); else if (first[firstNZ + i] < second[secondNZ + i]) return(-1); } return(0); } /* end of Cudd_ApaCompare */ /**Function******************************************************************** Synopsis [Compares the ratios of two arbitrary precision integers to two unsigned ints.] Description [Compares the ratios of two arbitrary precision integers to two unsigned ints. Returns 1 if the first number is larger; 0 if they are equal; -1 if the second number is larger.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_ApaCompareRatios( int digitsFirst, DdApaNumber firstNum, unsigned int firstDen, int digitsSecond, DdApaNumber secondNum, unsigned int secondDen) { int result; DdApaNumber first, second; unsigned int firstRem, secondRem; first = Cudd_NewApaNumber(digitsFirst); firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first); second = Cudd_NewApaNumber(digitsSecond); secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second); result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second); ABC_FREE(first); ABC_FREE(second); if (result == 0) { if ((double)firstRem/firstDen > (double)secondRem/secondDen) return(1); else if ((double)firstRem/firstDen < (double)secondRem/secondDen) return(-1); } return(result); } /* end of Cudd_ApaCompareRatios */ /**Function******************************************************************** Synopsis [Prints an arbitrary precision integer in hexadecimal format.] Description [Prints an arbitrary precision integer in hexadecimal format. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential] ******************************************************************************/ int Cudd_ApaPrintHex( FILE * fp, int digits, DdApaNumber number) { int i, result; for (i = 0; i < digits; i++) { result = fprintf(fp,DD_APA_HEXPRINT,number[i]); if (result == EOF) return(0); } return(1); } /* end of Cudd_ApaPrintHex */ /**Function******************************************************************** Synopsis [Prints an arbitrary precision integer in decimal format.] Description [Prints an arbitrary precision integer in decimal format. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintExponential] ******************************************************************************/ int Cudd_ApaPrintDecimal( FILE * fp, int digits, DdApaNumber number) { int i, result; DdApaDigit remainder; DdApaNumber work; unsigned char *decimal; int leadingzero; int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; work = Cudd_NewApaNumber(digits); if (work == NULL) return(0); decimal = ABC_ALLOC(unsigned char, decimalDigits); if (decimal == NULL) { ABC_FREE(work); return(0); } Cudd_ApaCopy(digits,number,work); for (i = decimalDigits - 1; i >= 0; i--) { remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); decimal[i] = (unsigned char) remainder; } ABC_FREE(work); leadingzero = 1; for (i = 0; i < decimalDigits; i++) { leadingzero = leadingzero && (decimal[i] == 0); if ((!leadingzero) || (i == (decimalDigits - 1))) { result = fprintf(fp,"%1d",decimal[i]); if (result == EOF) { ABC_FREE(decimal); return(0); } } } ABC_FREE(decimal); return(1); } /* end of Cudd_ApaPrintDecimal */ /**Function******************************************************************** Synopsis [Prints an arbitrary precision integer in exponential format.] Description [Prints an arbitrary precision integer in exponential format. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintDecimal] ******************************************************************************/ int Cudd_ApaPrintExponential( FILE * fp, int digits, DdApaNumber number, int precision) { int i, first, last, result; DdApaDigit remainder; DdApaNumber work; unsigned char *decimal; int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; work = Cudd_NewApaNumber(digits); if (work == NULL) return(0); decimal = ABC_ALLOC(unsigned char, decimalDigits); if (decimal == NULL) { ABC_FREE(work); return(0); } Cudd_ApaCopy(digits,number,work); first = decimalDigits - 1; for (i = decimalDigits - 1; i >= 0; i--) { remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); decimal[i] = (unsigned char) remainder; if (remainder != 0) first = i; /* keep track of MS non-zero */ } ABC_FREE(work); last = ddMin(first + precision, decimalDigits); for (i = first; i < last; i++) { result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]); if (result == EOF) { ABC_FREE(decimal); return(0); } } ABC_FREE(decimal); result = fprintf(fp,"e+%d",decimalDigits - first - 1); if (result == EOF) { return(0); } return(1); } /* end of Cudd_ApaPrintExponential */ /**Function******************************************************************** Synopsis [Counts the number of minterms of a DD.] Description [Counts the number of minterms of a DD. The function is assumed to depend on nvars variables. The minterm count is represented as an arbitrary precision unsigned integer, to allow for any number of variables CUDD supports. Returns a pointer to the array representing the number of minterms of the function rooted at node if successful; NULL otherwise.] SideEffects [The number of digits of the result is returned in parameter digits.] SeeAlso [Cudd_CountMinterm] ******************************************************************************/ DdApaNumber Cudd_ApaCountMinterm( DdManager * manager, DdNode * node, int nvars, int * digits) { DdApaNumber max, min; st__table *table; DdApaNumber i,count; background = manager->background; zero = Cudd_Not(manager->one); *digits = Cudd_ApaNumberOfDigits(nvars+1); max = Cudd_NewApaNumber(*digits); if (max == NULL) { return(NULL); } Cudd_ApaPowerOfTwo(*digits,max,nvars); min = Cudd_NewApaNumber(*digits); if (min == NULL) { ABC_FREE(max); return(NULL); } Cudd_ApaSetToLiteral(*digits,min,0); table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) { ABC_FREE(max); ABC_FREE(min); return(NULL); } i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table); if (i == NULL) { ABC_FREE(max); ABC_FREE(min); st__foreach(table, cuddApaStCountfree, NULL); st__free_table(table); return(NULL); } count = Cudd_NewApaNumber(*digits); if (count == NULL) { ABC_FREE(max); ABC_FREE(min); st__foreach(table, cuddApaStCountfree, NULL); st__free_table(table); if (Cudd_Regular(node)->ref == 1) ABC_FREE(i); return(NULL); } if (Cudd_IsComplement(node)) { (void) Cudd_ApaSubtract(*digits,max,i,count); } else { Cudd_ApaCopy(*digits,i,count); } ABC_FREE(max); ABC_FREE(min); st__foreach(table, cuddApaStCountfree, NULL); st__free_table(table); if (Cudd_Regular(node)->ref == 1) ABC_FREE(i); return(count); } /* end of Cudd_ApaCountMinterm */ /**Function******************************************************************** Synopsis [Prints the number of minterms of a BDD or ADD using arbitrary precision arithmetic.] Description [Prints the number of minterms of a BDD or ADD using arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_ApaPrintMintermExp] ******************************************************************************/ int Cudd_ApaPrintMinterm( FILE * fp, DdManager * dd, DdNode * node, int nvars) { int digits; int result; DdApaNumber count; count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); if (count == NULL) return(0); result = Cudd_ApaPrintDecimal(fp,digits,count); ABC_FREE(count); if (fprintf(fp,"\n") == EOF) { return(0); } return(result); } /* end of Cudd_ApaPrintMinterm */ /**Function******************************************************************** Synopsis [Prints the number of minterms of a BDD or ADD in exponential format using arbitrary precision arithmetic.] Description [Prints the number of minterms of a BDD or ADD in exponential format using arbitrary precision arithmetic. Parameter precision controls the number of signficant digits printed. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_ApaPrintMinterm] ******************************************************************************/ int Cudd_ApaPrintMintermExp( FILE * fp, DdManager * dd, DdNode * node, int nvars, int precision) { int digits; int result; DdApaNumber count; count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); if (count == NULL) return(0); result = Cudd_ApaPrintExponential(fp,digits,count,precision); ABC_FREE(count); if (fprintf(fp,"\n") == EOF) { return(0); } return(result); } /* end of Cudd_ApaPrintMintermExp */ /**Function******************************************************************** Synopsis [Prints the density of a BDD or ADD using arbitrary precision arithmetic.] Description [Prints the density of a BDD or ADD using arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_ApaPrintDensity( FILE * fp, DdManager * dd, DdNode * node, int nvars) { int digits; int result; DdApaNumber count,density; unsigned int size, remainder, fractional; count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); if (count == NULL) return(0); size = Cudd_DagSize(node); density = Cudd_NewApaNumber(digits); remainder = Cudd_ApaIntDivision(digits,count,size,density); result = Cudd_ApaPrintDecimal(fp,digits,density); ABC_FREE(count); ABC_FREE(density); fractional = (unsigned int)((double)remainder / size * 1000000); if (fprintf(fp,".%u\n", fractional) == EOF) { return(0); } return(result); } /* end of Cudd_ApaPrintDensity */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_ApaCountMinterm.] Description [Performs the recursive step of Cudd_ApaCountMinterm. It is based on the following identity. Let |f| be the number of minterms of f. Then: |f| = (|f0|+|f1|)/2 where f0 and f1 are the two cofactors of f. Uses the identity |f'| = max - |f|. The procedure expects the argument "node" to be a regular pointer, and guarantees this condition is met in the recursive calls. For efficiency, the result of a call is cached only if the node has a reference count greater than 1. Returns the number of minterms of the function rooted at node.] SideEffects [None] ******************************************************************************/ static DdApaNumber cuddApaCountMintermAux( DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st__table * table) { DdNode *Nt, *Ne; DdApaNumber mint, mint1, mint2; DdApaDigit carryout; if (cuddIsConstant(node)) { if (node == background || node == zero) { return(min); } else { return(max); } } if (node->ref > 1 && st__lookup(table, (const char *)node, (char **)&mint)) { return(mint); } Nt = cuddT(node); Ne = cuddE(node); mint1 = cuddApaCountMintermAux(Nt, digits, max, min, table); if (mint1 == NULL) return(NULL); mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table); if (mint2 == NULL) { if (Nt->ref == 1) ABC_FREE(mint1); return(NULL); } mint = Cudd_NewApaNumber(digits); if (mint == NULL) { if (Nt->ref == 1) ABC_FREE(mint1); if (Cudd_Regular(Ne)->ref == 1) ABC_FREE(mint2); return(NULL); } if (Cudd_IsComplement(Ne)) { (void) Cudd_ApaSubtract(digits,max,mint2,mint); carryout = Cudd_ApaAdd(digits,mint1,mint,mint); } else { carryout = Cudd_ApaAdd(digits,mint1,mint2,mint); } Cudd_ApaShiftRight(digits,carryout,mint,mint); /* If the refernce count of a child is 1, its minterm count ** hasn't been stored in table. Therefore, it must be explicitly ** freed here. */ if (Nt->ref == 1) ABC_FREE(mint1); if (Cudd_Regular(Ne)->ref == 1) ABC_FREE(mint2); if (node->ref > 1) { if ( st__insert(table, (char *)node, (char *)mint) == st__OUT_OF_MEM) { ABC_FREE(mint); return(NULL); } } return(mint); } /* end of cuddApaCountMintermAux */ /**Function******************************************************************** Synopsis [Frees the memory used to store the minterm counts recorded in the visited table.] Description [Frees the memory used to store the minterm counts recorded in the visited table. Returns st__CONTINUE.] SideEffects [None] ******************************************************************************/ static enum st__retval cuddApaStCountfree( char * key, char * value, char * arg) { DdApaNumber d; d = (DdApaNumber) value; ABC_FREE(d); return( st__CONTINUE); } /* end of cuddApaStCountfree */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddApprox.c000066400000000000000000002302331300674244400237640ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddApprox.c] PackageName [cudd] Synopsis [Procedures to approximate a given BDD.] Description [External procedures provided by this module:
  • Cudd_UnderApprox()
  • Cudd_OverApprox()
  • Cudd_RemapUnderApprox()
  • Cudd_RemapOverApprox()
  • Cudd_BiasedUnderApprox()
  • Cudd_BiasedOverApprox()
Internal procedures included in this module:
  • cuddUnderApprox()
  • cuddRemapUnderApprox()
  • cuddBiasedUnderApprox()
Static procedures included in this module:
  • gatherInfoAux()
  • gatherInfo()
  • computeSavings()
  • UAmarkNodes()
  • UAbuildSubset()
  • updateRefs()
  • RAmarkNodes()
  • BAmarkNodes()
  • RAbuildSubset()
] SeeAlso [cuddSubsetHB.c cuddSubsetSP.c cuddGenCof.c] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #ifdef __STDC__ #include #else #define DBL_MAX_EXP 1024 #endif #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define NOTHING 0 #define REPLACE_T 1 #define REPLACE_E 2 #define REPLACE_N 3 #define REPLACE_TT 4 #define REPLACE_TE 5 #define DONT_CARE 0 #define CARE 1 #define TOTAL_CARE 2 #define CARE_ERROR 3 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /* Data structure to store the information on each node. It keeps the ** number of minterms of the function rooted at this node in terms of ** the number of variables specified by the user; the number of ** minterms of the complement; the impact of the number of minterms of ** this function on the number of minterms of the root function; the ** reference count of the node from within the root function; the ** reference count of the node from an internal node; and the flag ** that says whether the node should be replaced and how. */ typedef struct NodeData { double mintermsP; /* minterms for the regular node */ double mintermsN; /* minterms for the complemented node */ int functionRef; /* references from within this function */ char care; /* node intersects care set */ char replace; /* replacement decision */ short int parity; /* 1: even; 2: odd; 3: both */ DdNode *resultP; /* result for even parity */ DdNode *resultN; /* result for odd parity */ } NodeData; typedef struct ApproxInfo { DdNode *one; /* one constant */ DdNode *zero; /* BDD zero constant */ NodeData *page; /* per-node information */ st__table *table; /* hash table to access the per-node info */ int index; /* index of the current node */ double max; /* max number of minterms */ int size; /* how many nodes are left */ double minterms; /* how many minterms are left */ } ApproxInfo; /* Item of the queue used in the levelized traversal of the BDD. */ #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif typedef struct GlobalQueueItem { struct GlobalQueueItem *next; struct GlobalQueueItem *cnext; DdNode *node; double impactP; double impactN; } GlobalQueueItem; typedef struct LocalQueueItem { struct LocalQueueItem *next; struct LocalQueueItem *cnext; DdNode *node; int localRef; } LocalQueueItem; #ifdef __osf__ #pragma pointer_size restore #endif /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.27 2009/02/19 16:16:51 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void updateParity (DdNode *node, ApproxInfo *info, int newparity); static NodeData * gatherInfoAux (DdNode *node, ApproxInfo *info, int parity); static ApproxInfo * gatherInfo (DdManager *dd, DdNode *node, int numVars, int parity); static int computeSavings (DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue); static int updateRefs (DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue); static int UAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality); static DdNode * UAbuildSubset (DdManager *dd, DdNode *node, ApproxInfo *info); static int RAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality); static int BAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0); static DdNode * RAbuildSubset (DdManager *dd, DdNode *node, ApproxInfo *info); static int BAapplyBias (DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Extracts a dense subset from a BDD with Shiple's underapproximation method.] Description [Extracts a dense subset from a BDD. This procedure uses a variant of Tom Shiple's underapproximation method. The main difference from the original method is that density is used as cost function. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.] SideEffects [None] SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_UnderApprox( DdManager * dd /* manager */, DdNode * f /* function to be subset */, int numVars /* number of variables in the support of f */, int threshold /* when to stop approximation */, int safe /* enforce safe approximation */, double quality /* minimum improvement for accepted changes */) { DdNode *subset; do { dd->reordered = 0; subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality); } while (dd->reordered == 1); return(subset); } /* end of Cudd_UnderApprox */ /**Function******************************************************************** Synopsis [Extracts a dense superset from a BDD with Shiple's underapproximation method.] Description [Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.] SideEffects [None] SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_OverApprox( DdManager * dd /* manager */, DdNode * f /* function to be superset */, int numVars /* number of variables in the support of f */, int threshold /* when to stop approximation */, int safe /* enforce safe approximation */, double quality /* minimum improvement for accepted changes */) { DdNode *subset, *g; g = Cudd_Not(f); do { dd->reordered = 0; subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality); } while (dd->reordered == 1); return(Cudd_NotCond(subset, (subset != NULL))); } /* end of Cudd_OverApprox */ /**Function******************************************************************** Synopsis [Extracts a dense subset from a BDD with the remapping underapproximation method.] Description [Extracts a dense subset from a BDD. This procedure uses a remapping technique and density as the cost function. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.] SideEffects [None] SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_RemapUnderApprox( DdManager * dd /* manager */, DdNode * f /* function to be subset */, int numVars /* number of variables in the support of f */, int threshold /* when to stop approximation */, double quality /* minimum improvement for accepted changes */) { DdNode *subset; do { dd->reordered = 0; subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality); } while (dd->reordered == 1); return(subset); } /* end of Cudd_RemapUnderApprox */ /**Function******************************************************************** Synopsis [Extracts a dense superset from a BDD with the remapping underapproximation method.] Description [Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.] SideEffects [None] SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_RemapOverApprox( DdManager * dd /* manager */, DdNode * f /* function to be superset */, int numVars /* number of variables in the support of f */, int threshold /* when to stop approximation */, double quality /* minimum improvement for accepted changes */) { DdNode *subset, *g; g = Cudd_Not(f); do { dd->reordered = 0; subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality); } while (dd->reordered == 1); return(Cudd_NotCond(subset, (subset != NULL))); } /* end of Cudd_RemapOverApprox */ /**Function******************************************************************** Synopsis [Extracts a dense subset from a BDD with the biased underapproximation method.] Description [Extracts a dense subset from a BDD. This procedure uses a biased remapping technique and density as the cost function. The bias is a function. This procedure tries to approximate where the bias is 0 and preserve the given function where the bias is 1. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will cause overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.] SideEffects [None] SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox Cudd_RemapUnderApprox Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_BiasedUnderApprox( DdManager *dd /* manager */, DdNode *f /* function to be subset */, DdNode *b /* bias function */, int numVars /* number of variables in the support of f */, int threshold /* when to stop approximation */, double quality1 /* minimum improvement for accepted changes when b=1 */, double quality0 /* minimum improvement for accepted changes when b=0 */) { DdNode *subset; do { dd->reordered = 0; subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1, quality0); } while (dd->reordered == 1); return(subset); } /* end of Cudd_BiasedUnderApprox */ /**Function******************************************************************** Synopsis [Extracts a dense superset from a BDD with the biased underapproximation method.] Description [Extracts a dense superset from a BDD. The procedure is identical to the underapproximation procedure except for the fact that it works on the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.] SideEffects [None] SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_RemapOverApprox Cudd_BiasedUnderApprox Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_BiasedOverApprox( DdManager *dd /* manager */, DdNode *f /* function to be superset */, DdNode *b /* bias function */, int numVars /* number of variables in the support of f */, int threshold /* when to stop approximation */, double quality1 /* minimum improvement for accepted changes when b=1*/, double quality0 /* minimum improvement for accepted changes when b=0 */) { DdNode *subset, *g; g = Cudd_Not(f); do { dd->reordered = 0; subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1, quality0); } while (dd->reordered == 1); return(Cudd_NotCond(subset, (subset != NULL))); } /* end of Cudd_BiasedOverApprox */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Applies Tom Shiple's underappoximation algorithm.] Description [Applies Tom Shiple's underappoximation algorithm. Proceeds in three phases:
  • collect information on each node in the BDD; this is done via DFS.
  • traverse the BDD in top-down fashion and compute for each node whether its elimination increases density.
  • traverse the BDD via DFS and actually perform the elimination.
Returns the approximated BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_UnderApprox] ******************************************************************************/ DdNode * cuddUnderApprox( DdManager * dd /* DD manager */, DdNode * f /* current DD */, int numVars /* maximum number of variables */, int threshold /* threshold under which approximation stops */, int safe /* enforce safe approximation */, double quality /* minimum improvement for accepted changes */) { ApproxInfo *info; DdNode *subset; int result; if (f == NULL) { fprintf(dd->err, "Cannot subset, nil object\n"); return(NULL); } if (Cudd_IsConstant(f)) { return(f); } /* Create table where node data are accessible via a hash table. */ info = gatherInfo(dd, f, numVars, safe); if (info == NULL) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } /* Mark nodes that should be replaced by zero. */ result = UAmarkNodes(dd, f, info, threshold, safe, quality); if (result == 0) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); ABC_FREE(info->page); st__free_table(info->table); ABC_FREE(info); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } /* Build the result. */ subset = UAbuildSubset(dd, f, info); #if 1 if (subset && info->size < Cudd_DagSize(subset)) (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", info->size, Cudd_DagSize(subset)); #endif ABC_FREE(info->page); st__free_table(info->table); ABC_FREE(info); #ifdef DD_DEBUG if (subset != NULL) { cuddRef(subset); #if 0 (void) Cudd_DebugCheck(dd); (void) Cudd_CheckKeys(dd); #endif if (!Cudd_bddLeq(dd, subset, f)) { (void) fprintf(dd->err, "Wrong subset\n"); dd->errorCode = CUDD_INTERNAL_ERROR; } cuddDeref(subset); } #endif return(subset); } /* end of cuddUnderApprox */ /**Function******************************************************************** Synopsis [Applies the remapping underappoximation algorithm.] Description [Applies the remapping underappoximation algorithm. Proceeds in three phases:
  • collect information on each node in the BDD; this is done via DFS.
  • traverse the BDD in top-down fashion and compute for each node whether remapping increases density.
  • traverse the BDD via DFS and actually perform the elimination.
Returns the approximated BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_RemapUnderApprox] ******************************************************************************/ DdNode * cuddRemapUnderApprox( DdManager * dd /* DD manager */, DdNode * f /* current DD */, int numVars /* maximum number of variables */, int threshold /* threshold under which approximation stops */, double quality /* minimum improvement for accepted changes */) { ApproxInfo *info; DdNode *subset; int result; if (f == NULL) { fprintf(dd->err, "Cannot subset, nil object\n"); dd->errorCode = CUDD_INVALID_ARG; return(NULL); } if (Cudd_IsConstant(f)) { return(f); } /* Create table where node data are accessible via a hash table. */ info = gatherInfo(dd, f, numVars, TRUE); if (info == NULL) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } /* Mark nodes that should be replaced by zero. */ result = RAmarkNodes(dd, f, info, threshold, quality); if (result == 0) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); ABC_FREE(info->page); st__free_table(info->table); ABC_FREE(info); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } /* Build the result. */ subset = RAbuildSubset(dd, f, info); #if 1 if (subset && info->size < Cudd_DagSize(subset)) (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", info->size, Cudd_DagSize(subset)); #endif ABC_FREE(info->page); st__free_table(info->table); ABC_FREE(info); #ifdef DD_DEBUG if (subset != NULL) { cuddRef(subset); #if 0 (void) Cudd_DebugCheck(dd); (void) Cudd_CheckKeys(dd); #endif if (!Cudd_bddLeq(dd, subset, f)) { (void) fprintf(dd->err, "Wrong subset\n"); } cuddDeref(subset); dd->errorCode = CUDD_INTERNAL_ERROR; } #endif return(subset); } /* end of cuddRemapUnderApprox */ /**Function******************************************************************** Synopsis [Applies the biased remapping underappoximation algorithm.] Description [Applies the biased remapping underappoximation algorithm. Proceeds in three phases:
  • collect information on each node in the BDD; this is done via DFS.
  • traverse the BDD in top-down fashion and compute for each node whether remapping increases density.
  • traverse the BDD via DFS and actually perform the elimination.
Returns the approximated BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_BiasedUnderApprox] ******************************************************************************/ DdNode * cuddBiasedUnderApprox( DdManager *dd /* DD manager */, DdNode *f /* current DD */, DdNode *b /* bias function */, int numVars /* maximum number of variables */, int threshold /* threshold under which approximation stops */, double quality1 /* minimum improvement for accepted changes when b=1 */, double quality0 /* minimum improvement for accepted changes when b=0 */) { ApproxInfo *info; DdNode *subset; int result; DdHashTable *cache; if (f == NULL) { fprintf(dd->err, "Cannot subset, nil object\n"); dd->errorCode = CUDD_INVALID_ARG; return(NULL); } if (Cudd_IsConstant(f)) { return(f); } /* Create table where node data are accessible via a hash table. */ info = gatherInfo(dd, f, numVars, TRUE); if (info == NULL) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } cache = cuddHashTableInit(dd,2,2); result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache); if (result == CARE_ERROR) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); cuddHashTableQuit(cache); ABC_FREE(info->page); st__free_table(info->table); ABC_FREE(info); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } cuddHashTableQuit(cache); /* Mark nodes that should be replaced by zero. */ result = BAmarkNodes(dd, f, info, threshold, quality1, quality0); if (result == 0) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); ABC_FREE(info->page); st__free_table(info->table); ABC_FREE(info); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } /* Build the result. */ subset = RAbuildSubset(dd, f, info); #if 1 if (subset && info->size < Cudd_DagSize(subset)) (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", info->size, Cudd_DagSize(subset)); #endif ABC_FREE(info->page); st__free_table(info->table); ABC_FREE(info); #ifdef DD_DEBUG if (subset != NULL) { cuddRef(subset); #if 0 (void) Cudd_DebugCheck(dd); (void) Cudd_CheckKeys(dd); #endif if (!Cudd_bddLeq(dd, subset, f)) { (void) fprintf(dd->err, "Wrong subset\n"); } cuddDeref(subset); dd->errorCode = CUDD_INTERNAL_ERROR; } #endif return(subset); } /* end of cuddBiasedUnderApprox */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Recursively update the parity of the paths reaching a node.] Description [Recursively update the parity of the paths reaching a node. Assumes that node is regular and propagates the invariant.] SideEffects [None] SeeAlso [gatherInfoAux] ******************************************************************************/ static void updateParity( DdNode * node /* function to analyze */, ApproxInfo * info /* info on BDD */, int newparity /* new parity for node */) { NodeData *infoN; DdNode *E; if (! st__lookup(info->table, (const char *)node, (char **)&infoN)) return; if ((infoN->parity & newparity) != 0) return; infoN->parity |= (short) newparity; if (Cudd_IsConstant(node)) return; updateParity(cuddT(node),info,newparity); E = cuddE(node); if (Cudd_IsComplement(E)) { updateParity(Cudd_Not(E),info,3-newparity); } else { updateParity(E,info,newparity); } return; } /* end of updateParity */ /**Function******************************************************************** Synopsis [Recursively counts minterms and computes reference counts of each node in the BDD.] Description [Recursively counts minterms and computes reference counts of each node in the BDD. Similar to the cuddCountMintermAux which recursively counts the number of minterms for the dag rooted at each node in terms of the total number of variables (max). It assumes that the node pointer passed to it is regular and it maintains the invariant.] SideEffects [None] SeeAlso [gatherInfo] ******************************************************************************/ static NodeData * gatherInfoAux( DdNode * node /* function to analyze */, ApproxInfo * info /* info on BDD */, int parity /* gather parity information */) { DdNode *N, *Nt, *Ne; NodeData *infoN, *infoT, *infoE; N = Cudd_Regular(node); /* Check whether entry for this node exists. */ if ( st__lookup(info->table, (const char *)N, (char **)&infoN)) { if (parity) { /* Update parity and propagate. */ updateParity(N, info, 1 + (int) Cudd_IsComplement(node)); } return(infoN); } /* Compute the cofactors. */ Nt = Cudd_NotCond(cuddT(N), N != node); Ne = Cudd_NotCond(cuddE(N), N != node); infoT = gatherInfoAux(Nt, info, parity); if (infoT == NULL) return(NULL); infoE = gatherInfoAux(Ne, info, parity); if (infoE == NULL) return(NULL); infoT->functionRef++; infoE->functionRef++; /* Point to the correct location in the page. */ infoN = &(info->page[info->index++]); infoN->parity |= (short) (1 + Cudd_IsComplement(node)); infoN->mintermsP = infoT->mintermsP/2; infoN->mintermsN = infoT->mintermsN/2; if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) { infoN->mintermsP += infoE->mintermsN/2; infoN->mintermsN += infoE->mintermsP/2; } else { infoN->mintermsP += infoE->mintermsP/2; infoN->mintermsN += infoE->mintermsN/2; } /* Insert entry for the node in the table. */ if ( st__insert(info->table,(char *)N, (char *)infoN) == st__OUT_OF_MEM) { return(NULL); } return(infoN); } /* end of gatherInfoAux */ /**Function******************************************************************** Synopsis [Gathers information about each node.] Description [Counts minterms and computes reference counts of each node in the BDD . The minterm count is separately computed for the node and its complement. This is to avoid cancellation errors. Returns a pointer to the data structure holding the information gathered if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddUnderApprox gatherInfoAux] ******************************************************************************/ static ApproxInfo * gatherInfo( DdManager * dd /* manager */, DdNode * node /* function to be analyzed */, int numVars /* number of variables node depends on */, int parity /* gather parity information */) { ApproxInfo *info; NodeData *infoTop; /* If user did not give numVars value, set it to the maximum ** exponent that the pow function can take. The -1 is due to the ** discrepancy in the value that pow takes and the value that ** log gives. */ if (numVars == 0) { numVars = DBL_MAX_EXP - 1; } info = ABC_ALLOC(ApproxInfo,1); if (info == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } info->max = pow(2.0,(double) numVars); info->one = DD_ONE(dd); info->zero = Cudd_Not(info->one); info->size = Cudd_DagSize(node); /* All the information gathered will be stored in a contiguous ** piece of memory, which is allocated here. This can be done ** efficiently because we have counted the number of nodes of the ** BDD. info->index points to the next available entry in the array ** that stores the per-node information. */ info->page = ABC_ALLOC(NodeData,info->size); if (info->page == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(info); return(NULL); } memset(info->page, 0, info->size * sizeof(NodeData)); /* clear all page */ info->table = st__init_table( st__ptrcmp, st__ptrhash); if (info->table == NULL) { ABC_FREE(info->page); ABC_FREE(info); return(NULL); } /* We visit the DAG in post-order DFS. Hence, the constant node is ** in first position, and the root of the DAG is in last position. */ /* Info for the constant node: Initialize only fields different from 0. */ if ( st__insert(info->table, (char *)info->one, (char *)info->page) == st__OUT_OF_MEM) { ABC_FREE(info->page); ABC_FREE(info); st__free_table(info->table); return(NULL); } info->page[0].mintermsP = info->max; info->index = 1; infoTop = gatherInfoAux(node,info,parity); if (infoTop == NULL) { ABC_FREE(info->page); st__free_table(info->table); ABC_FREE(info); return(NULL); } if (Cudd_IsComplement(node)) { info->minterms = infoTop->mintermsN; } else { info->minterms = infoTop->mintermsP; } infoTop->functionRef = 1; return(info); } /* end of gatherInfo */ /**Function******************************************************************** Synopsis [Counts the nodes that would be eliminated if a given node were replaced by zero.] Description [Counts the nodes that would be eliminated if a given node were replaced by zero. This procedure uses a queue passed by the caller for efficiency: since the queue is left empty at the endof the search, it can be reused as is by the next search. Returns the count (always striclty positive) if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddUnderApprox] ******************************************************************************/ static int computeSavings( DdManager * dd, DdNode * f, DdNode * skip, ApproxInfo * info, DdLevelQueue * queue) { NodeData *infoN; LocalQueueItem *item; DdNode *node; int savings = 0; node = Cudd_Regular(f); skip = Cudd_Regular(skip); /* Insert the given node in the level queue. Its local reference ** count is set equal to the function reference count so that the ** search will continue from it when it is retrieved. */ item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); if (item == NULL) return(0); (void) st__lookup(info->table, (const char *)node, (char **)&infoN); item->localRef = infoN->functionRef; /* Process the queue. */ while (queue->first != NULL) { item = (LocalQueueItem *) queue->first; node = item->node; cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); if (node == skip) continue; (void) st__lookup(info->table, (const char *)node, (char **)&infoN); if (item->localRef != infoN->functionRef) { /* This node is shared. */ continue; } savings++; if (!cuddIsConstant(cuddT(node))) { item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), cuddI(dd,cuddT(node)->index)); if (item == NULL) return(0); item->localRef++; } if (!Cudd_IsConstant(cuddE(node))) { item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), cuddI(dd,Cudd_Regular(cuddE(node))->index)); if (item == NULL) return(0); item->localRef++; } } #ifdef DD_DEBUG /* At the end of a local search the queue should be empty. */ assert(queue->size == 0); #endif return(savings); } /* end of computeSavings */ /**Function******************************************************************** Synopsis [Update function reference counts.] Description [Update function reference counts to account for replacement. Returns the number of nodes saved if successful; 0 otherwise.] SideEffects [None] SeeAlso [UAmarkNodes RAmarkNodes] ******************************************************************************/ static int updateRefs( DdManager * dd, DdNode * f, DdNode * skip, ApproxInfo * info, DdLevelQueue * queue) { NodeData *infoN; LocalQueueItem *item; DdNode *node; int savings = 0; node = Cudd_Regular(f); /* Insert the given node in the level queue. Its function reference ** count is set equal to 0 so that the search will continue from it ** when it is retrieved. */ item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); if (item == NULL) return(0); (void) st__lookup(info->table, (const char *)node, (char **)&infoN); infoN->functionRef = 0; if (skip != NULL) { /* Increase the function reference count of the node to be skipped ** by 1 to account for the node pointing to it that will be created. */ skip = Cudd_Regular(skip); (void) st__lookup(info->table, (const char *)skip, (char **)&infoN); infoN->functionRef++; } /* Process the queue. */ while (queue->first != NULL) { item = (LocalQueueItem *) queue->first; node = item->node; cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); (void) st__lookup(info->table, (const char *)node, (char **)&infoN); if (infoN->functionRef != 0) { /* This node is shared or must be skipped. */ continue; } savings++; if (!cuddIsConstant(cuddT(node))) { item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), cuddI(dd,cuddT(node)->index)); if (item == NULL) return(0); (void) st__lookup(info->table, (const char *)cuddT(node), (char **)&infoN); infoN->functionRef--; } if (!Cudd_IsConstant(cuddE(node))) { item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), cuddI(dd,Cudd_Regular(cuddE(node))->index)); if (item == NULL) return(0); (void) st__lookup(info->table, (const char *)Cudd_Regular(cuddE(node)), (char **)&infoN); infoN->functionRef--; } } #ifdef DD_DEBUG /* At the end of a local search the queue should be empty. */ assert(queue->size == 0); #endif return(savings); } /* end of updateRefs */ /**Function******************************************************************** Synopsis [Marks nodes for replacement by zero.] Description [Marks nodes for replacement by zero. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddUnderApprox] ******************************************************************************/ static int UAmarkNodes( DdManager * dd /* manager */, DdNode * f /* function to be analyzed */, ApproxInfo * info /* info on BDD */, int threshold /* when to stop approximating */, int safe /* enforce safe approximation */, double quality /* minimum improvement for accepted changes */) { DdLevelQueue *queue; DdLevelQueue *localQueue; NodeData *infoN; GlobalQueueItem *item; DdNode *node; double numOnset; double impactP, impactN; int savings; #if 0 (void) printf("initial size = %d initial minterms = %g\n", info->size, info->minterms); #endif queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); if (queue == NULL) { return(0); } localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), dd->initSlots); if (localQueue == NULL) { cuddLevelQueueQuit(queue); return(0); } node = Cudd_Regular(f); item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); if (item == NULL) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } if (Cudd_IsComplement(f)) { item->impactP = 0.0; item->impactN = 1.0; } else { item->impactP = 1.0; item->impactN = 0.0; } while (queue->first != NULL) { /* If the size of the subset is below the threshold, quit. */ if (info->size <= threshold) break; item = (GlobalQueueItem *) queue->first; node = item->node; node = Cudd_Regular(node); (void) st__lookup(info->table, (const char *)node, (char **)&infoN); if (safe && infoN->parity == 3) { cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); continue; } impactP = item->impactP; impactN = item->impactN; numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; savings = computeSavings(dd,node,NULL,info,localQueue); if (savings == 0) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); #if 0 (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", node, impactP, impactN, numOnset, savings); #endif if ((1 - numOnset / info->minterms) > quality * (1 - (double) savings / info->size)) { infoN->replace = TRUE; info->size -= savings; info->minterms -=numOnset; #if 0 (void) printf("replace: new size = %d new minterms = %g\n", info->size, info->minterms); #endif savings -= updateRefs(dd,node,NULL,info,localQueue); assert(savings == 0); continue; } if (!cuddIsConstant(cuddT(node))) { item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), cuddI(dd,cuddT(node)->index)); item->impactP += impactP/2.0; item->impactN += impactN/2.0; } if (!Cudd_IsConstant(cuddE(node))) { item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), cuddI(dd,Cudd_Regular(cuddE(node))->index)); if (Cudd_IsComplement(cuddE(node))) { item->impactP += impactN/2.0; item->impactN += impactP/2.0; } else { item->impactP += impactP/2.0; item->impactN += impactN/2.0; } } } cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(1); } /* end of UAmarkNodes */ /**Function******************************************************************** Synopsis [Builds the subset BDD.] Description [Builds the subset BDD. Based on the info table, replaces selected nodes by zero. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddUnderApprox] ******************************************************************************/ static DdNode * UAbuildSubset( DdManager * dd /* DD manager */, DdNode * node /* current node */, ApproxInfo * info /* node info */) { DdNode *Nt, *Ne, *N, *t, *e, *r; NodeData *infoN; if (Cudd_IsConstant(node)) return(node); N = Cudd_Regular(node); if ( st__lookup(info->table, (const char *)N, (char **)&infoN)) { if (infoN->replace == TRUE) { return(info->zero); } if (N == node ) { if (infoN->resultP != NULL) { return(infoN->resultP); } } else { if (infoN->resultN != NULL) { return(infoN->resultN); } } } else { (void) fprintf(dd->err, "Something is wrong, ought to be in info table\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node)); Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node)); t = UAbuildSubset(dd, Nt, info); if (t == NULL) { return(NULL); } cuddRef(t); e = UAbuildSubset(dd, Ne, info); if (e == NULL) { Cudd_RecursiveDeref(dd,t); return(NULL); } cuddRef(e); if (Cudd_IsComplement(t)) { t = Cudd_Not(t); e = Cudd_Not(e); r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } r = Cudd_Not(r); } else { r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } } cuddDeref(t); cuddDeref(e); if (N == node) { infoN->resultP = r; } else { infoN->resultN = r; } return(r); } /* end of UAbuildSubset */ /**Function******************************************************************** Synopsis [Marks nodes for remapping.] Description [Marks nodes for remapping. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddRemapUnderApprox] ******************************************************************************/ static int RAmarkNodes( DdManager * dd /* manager */, DdNode * f /* function to be analyzed */, ApproxInfo * info /* info on BDD */, int threshold /* when to stop approximating */, double quality /* minimum improvement for accepted changes */) { DdLevelQueue *queue; DdLevelQueue *localQueue; NodeData *infoN, *infoT, *infoE; GlobalQueueItem *item; DdNode *node, *T, *E; DdNode *shared; /* grandchild shared by the two children of node */ double numOnset; double impact, impactP, impactN; double minterms; int savings; int replace; #if 0 (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n", info->size, info->minterms); #endif queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); if (queue == NULL) { return(0); } localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), dd->initSlots); if (localQueue == NULL) { cuddLevelQueueQuit(queue); return(0); } /* Enqueue regular pointer to root and initialize impact. */ node = Cudd_Regular(f); item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); if (item == NULL) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } if (Cudd_IsComplement(f)) { item->impactP = 0.0; item->impactN = 1.0; } else { item->impactP = 1.0; item->impactN = 0.0; } /* The nodes retrieved here are guaranteed to be non-terminal. ** The initial node is not terminal because constant nodes are ** dealt with in the calling procedure. Subsequent nodes are inserted ** only if they are not terminal. */ while (queue->first != NULL) { /* If the size of the subset is below the threshold, quit. */ if (info->size <= threshold) break; item = (GlobalQueueItem *) queue->first; node = item->node; #ifdef DD_DEBUG assert(item->impactP >= 0 && item->impactP <= 1.0); assert(item->impactN >= 0 && item->impactN <= 1.0); assert(!Cudd_IsComplement(node)); assert(!Cudd_IsConstant(node)); #endif if (! st__lookup(info->table, (const char *)node, (char **)&infoN)) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } #ifdef DD_DEBUG assert(infoN->parity >= 1 && infoN->parity <= 3); #endif if (infoN->parity == 3) { /* This node can be reached through paths of different parity. ** It is not safe to replace it, because remapping will give ** an incorrect result, while replacement by 0 may cause node ** splitting. */ cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); continue; } T = cuddT(node); E = cuddE(node); shared = NULL; impactP = item->impactP; impactN = item->impactN; if (Cudd_bddLeq(dd,T,E)) { /* Here we know that E is regular. */ #ifdef DD_DEBUG assert(!Cudd_IsComplement(E)); #endif (void) st__lookup(info->table, (const char *)T, (char **)&infoT); (void) st__lookup(info->table, (const char *)E, (char **)&infoE); if (infoN->parity == 1) { impact = impactP; minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0; if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { savings = 1 + computeSavings(dd,E,NULL,info,localQueue); if (savings == 1) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } } else { savings = 1; } replace = REPLACE_E; } else { #ifdef DD_DEBUG assert(infoN->parity == 2); #endif impact = impactN; minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0; if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { savings = 1 + computeSavings(dd,T,NULL,info,localQueue); if (savings == 1) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } } else { savings = 1; } replace = REPLACE_T; } numOnset = impact * minterms; } else if (Cudd_bddLeq(dd,E,T)) { /* Here E may be complemented. */ DdNode *Ereg = Cudd_Regular(E); (void) st__lookup(info->table, (const char *)T, (char **)&infoT); (void) st__lookup(info->table, (const char *)Ereg, (char **)&infoE); if (infoN->parity == 1) { impact = impactP; minterms = infoT->mintermsP/2.0 - ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0; if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { savings = 1 + computeSavings(dd,T,NULL,info,localQueue); if (savings == 1) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } } else { savings = 1; } replace = REPLACE_T; } else { #ifdef DD_DEBUG assert(infoN->parity == 2); #endif impact = impactN; minterms = ((E == Ereg) ? infoE->mintermsN : infoE->mintermsP)/2.0 - infoT->mintermsN/2.0; if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { savings = 1 + computeSavings(dd,E,NULL,info,localQueue); if (savings == 1) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } } else { savings = 1; } replace = REPLACE_E; } numOnset = impact * minterms; } else { DdNode *Ereg = Cudd_Regular(E); DdNode *TT = cuddT(T); DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E)); if (T->index == Ereg->index && TT == ET) { shared = TT; replace = REPLACE_TT; } else { DdNode *TE = cuddE(T); DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E)); if (T->index == Ereg->index && TE == EE) { shared = TE; replace = REPLACE_TE; } else { replace = REPLACE_N; } } numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; savings = computeSavings(dd,node,shared,info,localQueue); if (shared != NULL) { NodeData *infoS; (void) st__lookup(info->table, (const char *)Cudd_Regular(shared), (char **)&infoS); if (Cudd_IsComplement(shared)) { numOnset -= (infoS->mintermsN * impactP + infoS->mintermsP * impactN)/2.0; } else { numOnset -= (infoS->mintermsP * impactP + infoS->mintermsN * impactN)/2.0; } savings--; } } cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); #if 0 if (replace == REPLACE_T || replace == REPLACE_E) (void) printf("node %p: impact = %g numOnset = %g savings %d\n", node, impact, numOnset, savings); else (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", node, impactP, impactN, numOnset, savings); #endif if ((1 - numOnset / info->minterms) > quality * (1 - (double) savings / info->size)) { infoN->replace = (char) replace; info->size -= savings; info->minterms -=numOnset; #if 0 (void) printf("remap(%d): new size = %d new minterms = %g\n", replace, info->size, info->minterms); #endif if (replace == REPLACE_N) { savings -= updateRefs(dd,node,NULL,info,localQueue); } else if (replace == REPLACE_T) { savings -= updateRefs(dd,node,E,info,localQueue); } else if (replace == REPLACE_E) { savings -= updateRefs(dd,node,T,info,localQueue); } else { #ifdef DD_DEBUG assert(replace == REPLACE_TT || replace == REPLACE_TE); #endif savings -= updateRefs(dd,node,shared,info,localQueue) - 1; } assert(savings == 0); } else { replace = NOTHING; } if (replace == REPLACE_N) continue; if ((replace == REPLACE_E || replace == NOTHING) && !cuddIsConstant(cuddT(node))) { item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), cuddI(dd,cuddT(node)->index)); if (replace == REPLACE_E) { item->impactP += impactP; item->impactN += impactN; } else { item->impactP += impactP/2.0; item->impactN += impactN/2.0; } } if ((replace == REPLACE_T || replace == NOTHING) && !Cudd_IsConstant(cuddE(node))) { item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), cuddI(dd,Cudd_Regular(cuddE(node))->index)); if (Cudd_IsComplement(cuddE(node))) { if (replace == REPLACE_T) { item->impactP += impactN; item->impactN += impactP; } else { item->impactP += impactN/2.0; item->impactN += impactP/2.0; } } else { if (replace == REPLACE_T) { item->impactP += impactP; item->impactN += impactN; } else { item->impactP += impactP/2.0; item->impactN += impactN/2.0; } } } if ((replace == REPLACE_TT || replace == REPLACE_TE) && !Cudd_IsConstant(shared)) { item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared), cuddI(dd,Cudd_Regular(shared)->index)); if (Cudd_IsComplement(shared)) { item->impactP += impactN; item->impactN += impactP; } else { item->impactP += impactP; item->impactN += impactN; } } } cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(1); } /* end of RAmarkNodes */ /**Function******************************************************************** Synopsis [Marks nodes for remapping.] Description [Marks nodes for remapping. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddRemapUnderApprox] ******************************************************************************/ static int BAmarkNodes( DdManager *dd /* manager */, DdNode *f /* function to be analyzed */, ApproxInfo *info /* info on BDD */, int threshold /* when to stop approximating */, double quality1 /* minimum improvement for accepted changes when b=1 */, double quality0 /* minimum improvement for accepted changes when b=0 */) { DdLevelQueue *queue; DdLevelQueue *localQueue; NodeData *infoN, *infoT, *infoE; GlobalQueueItem *item; DdNode *node, *T, *E; DdNode *shared; /* grandchild shared by the two children of node */ double numOnset; double impact, impactP, impactN; double minterms; double quality; int savings; int replace; #if 0 (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n", info->size, info->minterms); #endif queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); if (queue == NULL) { return(0); } localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), dd->initSlots); if (localQueue == NULL) { cuddLevelQueueQuit(queue); return(0); } /* Enqueue regular pointer to root and initialize impact. */ node = Cudd_Regular(f); item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); if (item == NULL) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } if (Cudd_IsComplement(f)) { item->impactP = 0.0; item->impactN = 1.0; } else { item->impactP = 1.0; item->impactN = 0.0; } /* The nodes retrieved here are guaranteed to be non-terminal. ** The initial node is not terminal because constant nodes are ** dealt with in the calling procedure. Subsequent nodes are inserted ** only if they are not terminal. */ while (queue->first != NULL) { /* If the size of the subset is below the threshold, quit. */ if (info->size <= threshold) break; item = (GlobalQueueItem *) queue->first; node = item->node; #ifdef DD_DEBUG assert(item->impactP >= 0 && item->impactP <= 1.0); assert(item->impactN >= 0 && item->impactN <= 1.0); assert(!Cudd_IsComplement(node)); assert(!Cudd_IsConstant(node)); #endif if (! st__lookup(info->table, (const char *)node, (char **)&infoN)) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } quality = infoN->care ? quality1 : quality0; #ifdef DD_DEBUG assert(infoN->parity >= 1 && infoN->parity <= 3); #endif if (infoN->parity == 3) { /* This node can be reached through paths of different parity. ** It is not safe to replace it, because remapping will give ** an incorrect result, while replacement by 0 may cause node ** splitting. */ cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); continue; } T = cuddT(node); E = cuddE(node); shared = NULL; impactP = item->impactP; impactN = item->impactN; if (Cudd_bddLeq(dd,T,E)) { /* Here we know that E is regular. */ #ifdef DD_DEBUG assert(!Cudd_IsComplement(E)); #endif (void) st__lookup(info->table, (const char *)T, (char **)&infoT); (void) st__lookup(info->table, (const char *)E, (char **)&infoE); if (infoN->parity == 1) { impact = impactP; minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0; if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { savings = 1 + computeSavings(dd,E,NULL,info,localQueue); if (savings == 1) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } } else { savings = 1; } replace = REPLACE_E; } else { #ifdef DD_DEBUG assert(infoN->parity == 2); #endif impact = impactN; minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0; if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { savings = 1 + computeSavings(dd,T,NULL,info,localQueue); if (savings == 1) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } } else { savings = 1; } replace = REPLACE_T; } numOnset = impact * minterms; } else if (Cudd_bddLeq(dd,E,T)) { /* Here E may be complemented. */ DdNode *Ereg = Cudd_Regular(E); (void) st__lookup(info->table, (const char *)T, (char **)&infoT); (void) st__lookup(info->table, (const char *)Ereg, (char **)&infoE); if (infoN->parity == 1) { impact = impactP; minterms = infoT->mintermsP/2.0 - ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0; if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { savings = 1 + computeSavings(dd,T,NULL,info,localQueue); if (savings == 1) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } } else { savings = 1; } replace = REPLACE_T; } else { #ifdef DD_DEBUG assert(infoN->parity == 2); #endif impact = impactN; minterms = ((E == Ereg) ? infoE->mintermsN : infoE->mintermsP)/2.0 - infoT->mintermsN/2.0; if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { savings = 1 + computeSavings(dd,E,NULL,info,localQueue); if (savings == 1) { cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(0); } } else { savings = 1; } replace = REPLACE_E; } numOnset = impact * minterms; } else { DdNode *Ereg = Cudd_Regular(E); DdNode *TT = cuddT(T); DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E)); if (T->index == Ereg->index && TT == ET) { shared = TT; replace = REPLACE_TT; } else { DdNode *TE = cuddE(T); DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E)); if (T->index == Ereg->index && TE == EE) { shared = TE; replace = REPLACE_TE; } else { replace = REPLACE_N; } } numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; savings = computeSavings(dd,node,shared,info,localQueue); if (shared != NULL) { NodeData *infoS; (void) st__lookup(info->table, (const char *)Cudd_Regular(shared), (char **)&infoS); if (Cudd_IsComplement(shared)) { numOnset -= (infoS->mintermsN * impactP + infoS->mintermsP * impactN)/2.0; } else { numOnset -= (infoS->mintermsP * impactP + infoS->mintermsN * impactN)/2.0; } savings--; } } cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); #if 0 if (replace == REPLACE_T || replace == REPLACE_E) (void) printf("node %p: impact = %g numOnset = %g savings %d\n", node, impact, numOnset, savings); else (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", node, impactP, impactN, numOnset, savings); #endif if ((1 - numOnset / info->minterms) > quality * (1 - (double) savings / info->size)) { infoN->replace = (char) replace; info->size -= savings; info->minterms -=numOnset; #if 0 (void) printf("remap(%d): new size = %d new minterms = %g\n", replace, info->size, info->minterms); #endif if (replace == REPLACE_N) { savings -= updateRefs(dd,node,NULL,info,localQueue); } else if (replace == REPLACE_T) { savings -= updateRefs(dd,node,E,info,localQueue); } else if (replace == REPLACE_E) { savings -= updateRefs(dd,node,T,info,localQueue); } else { #ifdef DD_DEBUG assert(replace == REPLACE_TT || replace == REPLACE_TE); #endif savings -= updateRefs(dd,node,shared,info,localQueue) - 1; } assert(savings == 0); } else { replace = NOTHING; } if (replace == REPLACE_N) continue; if ((replace == REPLACE_E || replace == NOTHING) && !cuddIsConstant(cuddT(node))) { item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), cuddI(dd,cuddT(node)->index)); if (replace == REPLACE_E) { item->impactP += impactP; item->impactN += impactN; } else { item->impactP += impactP/2.0; item->impactN += impactN/2.0; } } if ((replace == REPLACE_T || replace == NOTHING) && !Cudd_IsConstant(cuddE(node))) { item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), cuddI(dd,Cudd_Regular(cuddE(node))->index)); if (Cudd_IsComplement(cuddE(node))) { if (replace == REPLACE_T) { item->impactP += impactN; item->impactN += impactP; } else { item->impactP += impactN/2.0; item->impactN += impactP/2.0; } } else { if (replace == REPLACE_T) { item->impactP += impactP; item->impactN += impactN; } else { item->impactP += impactP/2.0; item->impactN += impactN/2.0; } } } if ((replace == REPLACE_TT || replace == REPLACE_TE) && !Cudd_IsConstant(shared)) { item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared), cuddI(dd,Cudd_Regular(shared)->index)); if (Cudd_IsComplement(shared)) { if (replace == REPLACE_T) { item->impactP += impactN; item->impactN += impactP; } else { item->impactP += impactN/2.0; item->impactN += impactP/2.0; } } else { if (replace == REPLACE_T) { item->impactP += impactP; item->impactN += impactN; } else { item->impactP += impactP/2.0; item->impactN += impactN/2.0; } } } } cuddLevelQueueQuit(queue); cuddLevelQueueQuit(localQueue); return(1); } /* end of BAmarkNodes */ /**Function******************************************************************** Synopsis [Builds the subset BDD for cuddRemapUnderApprox.] Description [Builds the subset BDDfor cuddRemapUnderApprox. Based on the info table, performs remapping or replacement at selected nodes. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddRemapUnderApprox] ******************************************************************************/ static DdNode * RAbuildSubset( DdManager * dd /* DD manager */, DdNode * node /* current node */, ApproxInfo * info /* node info */) { DdNode *Nt, *Ne, *N, *t, *e, *r; NodeData *infoN; if (Cudd_IsConstant(node)) return(node); N = Cudd_Regular(node); Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node)); Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node)); if ( st__lookup(info->table, (const char *)N, (char **)&infoN)) { if (N == node ) { if (infoN->resultP != NULL) { return(infoN->resultP); } } else { if (infoN->resultN != NULL) { return(infoN->resultN); } } if (infoN->replace == REPLACE_T) { r = RAbuildSubset(dd, Ne, info); return(r); } else if (infoN->replace == REPLACE_E) { r = RAbuildSubset(dd, Nt, info); return(r); } else if (infoN->replace == REPLACE_N) { return(info->zero); } else if (infoN->replace == REPLACE_TT) { DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)), Cudd_IsComplement(node)); int index = cuddT(N)->index; e = info->zero; t = RAbuildSubset(dd, Ntt, info); if (t == NULL) { return(NULL); } cuddRef(t); if (Cudd_IsComplement(t)) { t = Cudd_Not(t); e = Cudd_Not(e); r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } r = Cudd_Not(r); } else { r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } } cuddDeref(t); return(r); } else if (infoN->replace == REPLACE_TE) { DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)), Cudd_IsComplement(node)); int index = cuddT(N)->index; t = info->one; e = RAbuildSubset(dd, Nte, info); if (e == NULL) { return(NULL); } cuddRef(e); e = Cudd_Not(e); r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, e); return(NULL); } r =Cudd_Not(r); cuddDeref(e); return(r); } } else { (void) fprintf(dd->err, "Something is wrong, ought to be in info table\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } t = RAbuildSubset(dd, Nt, info); if (t == NULL) { return(NULL); } cuddRef(t); e = RAbuildSubset(dd, Ne, info); if (e == NULL) { Cudd_RecursiveDeref(dd,t); return(NULL); } cuddRef(e); if (Cudd_IsComplement(t)) { t = Cudd_Not(t); e = Cudd_Not(e); r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } r = Cudd_Not(r); } else { r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } } cuddDeref(t); cuddDeref(e); if (N == node) { infoN->resultP = r; } else { infoN->resultN = r; } return(r); } /* end of RAbuildSubset */ /**Function******************************************************************** Synopsis [Finds don't care nodes.] Description [Finds don't care nodes by traversing f and b in parallel. Returns the care status of the visited f node if successful; CARE_ERROR otherwise.] SideEffects [None] SeeAlso [cuddBiasedUnderApprox] ******************************************************************************/ static int BAapplyBias( DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache) { DdNode *one, *zero, *res; DdNode *Ft, *Fe, *B, *Bt, *Be; unsigned int topf, topb; NodeData *infoF; int careT, careE; one = DD_ONE(dd); zero = Cudd_Not(one); if (! st__lookup(info->table, (const char *)f, (char **)&infoF)) return(CARE_ERROR); if (f == one) return(TOTAL_CARE); if (b == zero) return(infoF->care); if (infoF->care == TOTAL_CARE) return(TOTAL_CARE); if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) && (res = cuddHashTableLookup2(cache,f,b)) != NULL) { if (res->ref == 0) { cache->manager->dead++; cache->manager->constants.dead++; } return(infoF->care); } topf = dd->perm[f->index]; B = Cudd_Regular(b); topb = cuddI(dd,B->index); if (topf <= topb) { Ft = cuddT(f); Fe = cuddE(f); } else { Ft = Fe = f; } if (topb <= topf) { /* We know that b is not constant because f is not. */ Bt = cuddT(B); Be = cuddE(B); if (Cudd_IsComplement(b)) { Bt = Cudd_Not(Bt); Be = Cudd_Not(Be); } } else { Bt = Be = b; } careT = BAapplyBias(dd, Ft, Bt, info, cache); if (careT == CARE_ERROR) return(CARE_ERROR); careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache); if (careE == CARE_ERROR) return(CARE_ERROR); if (careT == TOTAL_CARE && careE == TOTAL_CARE) { infoF->care = TOTAL_CARE; } else { infoF->care = CARE; } if (f->ref != 1 || Cudd_Regular(b)->ref != 1) { ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref; cuddSatDec(fanout); if (!cuddHashTableInsert2(cache,f,b,one,fanout)) { return(CARE_ERROR); } } return(infoF->care); } /* end of BAapplyBias */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddBddAbs.c000066400000000000000000000532471300674244400236420ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddBddAbs.c] PackageName [cudd] Synopsis [Quantification functions for BDDs.] Description [External procedures included in this module:
  • Cudd_bddExistAbstract()
  • Cudd_bddXorExistAbstract()
  • Cudd_bddUnivAbstract()
  • Cudd_bddBooleanDiff()
  • Cudd_bddVarIsDependent()
Internal procedures included in this module:
  • cuddBddExistAbstractRecur()
  • cuddBddXorExistAbstractRecur()
  • cuddBddBooleanDiffRecur()
Static procedures included in this module:
  • bddCheckPositiveCube()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddBddAbs.c,v 1.26 2004/08/13 18:04:46 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int bddCheckPositiveCube (DdManager *manager, DdNode *cube); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Existentially abstracts all the variables in cube from f.] Description [Existentially abstracts all the variables in cube from f. Returns the abstracted BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddUnivAbstract Cudd_addExistAbstract] ******************************************************************************/ DdNode * Cudd_bddExistAbstract( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *res; if (bddCheckPositiveCube(manager, cube) == 0) { (void) fprintf(manager->err, "Error: Can only abstract positive cubes\n"); manager->errorCode = CUDD_INVALID_ARG; return(NULL); } do { manager->reordered = 0; res = cuddBddExistAbstractRecur(manager, f, cube); } while (manager->reordered == 1); return(res); } /* end of Cudd_bddExistAbstract */ /**Function******************************************************************** Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube.] Description [Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddUnivAbstract Cudd_bddExistAbstract Cudd_bddAndAbstract] ******************************************************************************/ DdNode * Cudd_bddXorExistAbstract( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube) { DdNode *res; if (bddCheckPositiveCube(manager, cube) == 0) { (void) fprintf(manager->err, "Error: Can only abstract positive cubes\n"); manager->errorCode = CUDD_INVALID_ARG; return(NULL); } do { manager->reordered = 0; res = cuddBddXorExistAbstractRecur(manager, f, g, cube); } while (manager->reordered == 1); return(res); } /* end of Cudd_bddXorExistAbstract */ /**Function******************************************************************** Synopsis [Universally abstracts all the variables in cube from f.] Description [Universally abstracts all the variables in cube from f. Returns the abstracted BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddExistAbstract Cudd_addUnivAbstract] ******************************************************************************/ DdNode * Cudd_bddUnivAbstract( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *res; if (bddCheckPositiveCube(manager, cube) == 0) { (void) fprintf(manager->err, "Error: Can only abstract positive cubes\n"); manager->errorCode = CUDD_INVALID_ARG; return(NULL); } do { manager->reordered = 0; res = cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube); } while (manager->reordered == 1); if (res != NULL) res = Cudd_Not(res); return(res); } /* end of Cudd_bddUnivAbstract */ /**Function******************************************************************** Synopsis [Computes the boolean difference of f with respect to x.] Description [Computes the boolean difference of f with respect to the variable with index x. Returns the BDD of the boolean difference if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_bddBooleanDiff( DdManager * manager, DdNode * f, int x) { DdNode *res, *var; /* If the variable is not currently in the manager, f cannot ** depend on it. */ if (x >= manager->size) return(Cudd_Not(DD_ONE(manager))); var = manager->vars[x]; do { manager->reordered = 0; res = cuddBddBooleanDiffRecur(manager, Cudd_Regular(f), var); } while (manager->reordered == 1); return(res); } /* end of Cudd_bddBooleanDiff */ /**Function******************************************************************** Synopsis [Checks whether a variable is dependent on others in a function.] Description [Checks whether a variable is dependent on others in a function. Returns 1 if the variable is dependent; 0 otherwise. No new nodes are created.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_bddVarIsDependent( DdManager *dd, /* manager */ DdNode *f, /* function */ DdNode *var /* variable */) { DdNode *F, *res, *zero, *ft, *fe; unsigned topf, level; DD_CTFP cacheOp; int retval; zero = Cudd_Not(DD_ONE(dd)); if (Cudd_IsConstant(f)) return(f == zero); /* From now on f is not constant. */ F = Cudd_Regular(f); topf = (unsigned) dd->perm[F->index]; level = (unsigned) dd->perm[var->index]; /* Check terminal case. If topf > index of var, f does not depend on var. ** Therefore, var is not dependent in f. */ if (topf > level) { return(0); } cacheOp = (DD_CTFP) Cudd_bddVarIsDependent; res = cuddCacheLookup2(dd,cacheOp,f,var); if (res != NULL) { return(res != zero); } /* Compute cofactors. */ ft = Cudd_NotCond(cuddT(F), f != F); fe = Cudd_NotCond(cuddE(F), f != F); if (topf == level) { retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe)); } else { retval = Cudd_bddVarIsDependent(dd,ft,var) && Cudd_bddVarIsDependent(dd,fe,var); } cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval)); return(retval); } /* Cudd_bddVarIsDependent */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive steps of Cudd_bddExistAbstract.] Description [Performs the recursive steps of Cudd_bddExistAbstract. Returns the BDD obtained by abstracting the variables of cube from f if successful; NULL otherwise. It is also used by Cudd_bddUnivAbstract.] SideEffects [None] SeeAlso [Cudd_bddExistAbstract Cudd_bddUnivAbstract] ******************************************************************************/ DdNode * cuddBddExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *F, *T, *E, *res, *res1, *res2, *one; statLine(manager); one = DD_ONE(manager); F = Cudd_Regular(f); /* Cube is guaranteed to be a cube at this point. */ if (cube == one || F == one) { return(f); } /* From now on, f and cube are non-constant. */ /* Abstract a variable that does not appear in f. */ while (manager->perm[F->index] > manager->perm[cube->index]) { cube = cuddT(cube); if (cube == one) return(f); } /* Check the cache. */ if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) { return(res); } /* Compute the cofactors of f. */ T = cuddT(F); E = cuddE(F); if (f != F) { T = Cudd_Not(T); E = Cudd_Not(E); } /* If the two indices are the same, so are their levels. */ if (F->index == cube->index) { if (T == one || E == one || T == Cudd_Not(E)) { return(one); } res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); if (res1 == one) { if (F->ref != 1) cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one); return(one); } cuddRef(res1); res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_IterDerefBdd(manager,res1); return(NULL); } cuddRef(res2); res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2)); if (res == NULL) { Cudd_IterDerefBdd(manager, res1); Cudd_IterDerefBdd(manager, res2); return(NULL); } res = Cudd_Not(res); cuddRef(res); Cudd_IterDerefBdd(manager, res1); Cudd_IterDerefBdd(manager, res2); if (F->ref != 1) cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */ res1 = cuddBddExistAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddBddExistAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_IterDerefBdd(manager, res1); return(NULL); } cuddRef(res2); /* ITE takes care of possible complementation of res1 and of the ** case in which res1 == res2. */ res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2); if (res == NULL) { Cudd_IterDerefBdd(manager, res1); Cudd_IterDerefBdd(manager, res2); return(NULL); } cuddRef(res); //Added Cudd_IterDerefBdd(manager, res1); //cuddDeref(res1); Cudd_IterDerefBdd(manager, res2); //cuddDeref(res2); cuddDeref(res); //Added if (F->ref != 1) cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); return(res); } } /* end of cuddBddExistAbstractRecur */ /**Function******************************************************************** Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube.] Description [Takes the exclusive OR of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddAndAbstract] ******************************************************************************/ DdNode * cuddBddXorExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube) { DdNode *F, *fv, *fnv, *G, *gv, *gnv; DdNode *one, *zero, *r, *t, *e, *Cube; unsigned int topf, topg, topcube, top, index; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* Terminal cases. */ if (f == g) { return(zero); } if (f == Cudd_Not(g)) { return(one); } if (cube == one) { return(cuddBddXorRecur(manager, f, g)); } if (f == one) { return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube)); } if (g == one) { return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube)); } if (f == zero) { return(cuddBddExistAbstractRecur(manager, g, cube)); } if (g == zero) { return(cuddBddExistAbstractRecur(manager, f, cube)); } /* At this point f, g, and cube are not constant. */ if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */ DdNode *tmp = f; f = g; g = tmp; } /* Check cache. */ r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube); if (r != NULL) { return(r); } /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ F = Cudd_Regular(f); topf = manager->perm[F->index]; G = Cudd_Regular(g); topg = manager->perm[G->index]; top = ddMin(topf, topg); topcube = manager->perm[cube->index]; if (topcube < top) { return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube))); } /* Now, topcube >= top. */ if (topf == top) { index = F->index; fv = cuddT(F); fnv = cuddE(F); if (Cudd_IsComplement(f)) { fv = Cudd_Not(fv); fnv = Cudd_Not(fnv); } } else { index = G->index; fv = fnv = f; } if (topg == top) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } if (topcube == top) { Cube = cuddT(cube); } else { Cube = cube; } t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube); if (t == NULL) return(NULL); /* Special case: 1 OR anything = 1. Hence, no need to compute ** the else branch if t is 1. */ if (t == one && topcube == top) { cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one); return(one); } cuddRef(t); e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } cuddRef(e); if (topcube == top) { /* abstract */ r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); cuddRef(r); Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); cuddDeref(r); } else if (t == e) { r = t; cuddDeref(t); cuddDeref(e); } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } cuddDeref(e); cuddDeref(t); } cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r); return (r); } /* end of cuddBddXorExistAbstractRecur */ /**Function******************************************************************** Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.] Description [Performs the recursive steps of Cudd_bddBoleanDiff. Returns the BDD obtained by XORing the cofactors of f with respect to var if successful; NULL otherwise. Exploits the fact that dF/dx = dF'/dx.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddBddBooleanDiffRecur( DdManager * manager, DdNode * f, DdNode * var) { DdNode *T, *E, *res, *res1, *res2; statLine(manager); if (cuddI(manager,f->index) > manager->perm[var->index]) { /* f does not depend on var. */ return(Cudd_Not(DD_ONE(manager))); } /* From now on, f is non-constant. */ /* If the two indices are the same, so are their levels. */ if (f->index == var->index) { res = cuddBddXorRecur(manager, cuddT(f), cuddE(f)); return(res); } /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */ /* Check the cache. */ res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var); if (res != NULL) { return(res); } /* Compute the cofactors of f. */ T = cuddT(f); E = cuddE(f); res1 = cuddBddBooleanDiffRecur(manager, T, var); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var); if (res2 == NULL) { Cudd_IterDerefBdd(manager, res1); return(NULL); } cuddRef(res2); /* ITE takes care of possible complementation of res1 and of the ** case in which res1 == res2. */ res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2); if (res == NULL) { Cudd_IterDerefBdd(manager, res1); Cudd_IterDerefBdd(manager, res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res); return(res); } /* end of cuddBddBooleanDiffRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Checks whether cube is an BDD representing the product of positive literals.] Description [Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int bddCheckPositiveCube( DdManager * manager, DdNode * cube) { if (Cudd_IsComplement(cube)) return(0); if (cube == DD_ONE(manager)) return(1); if (cuddIsConstant(cube)) return(0); if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) { return(bddCheckPositiveCube(manager, cuddT(cube))); } return(0); } /* end of bddCheckPositiveCube */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddBddCorr.c000066400000000000000000000356651300674244400240460ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddBddCorr.c] PackageName [cudd] Synopsis [Correlation between BDDs.] Description [External procedures included in this module:
  • Cudd_bddCorrelation()
  • Cudd_bddCorrelationWeights()
Static procedures included in this module:
  • bddCorrelationAux()
  • bddCorrelationWeightsAux()
  • CorrelCompare()
  • CorrelHash()
  • CorrelCleanUp()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ typedef struct hashEntry { DdNode *f; DdNode *g; } HashEntry; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.14 2004/08/13 18:04:46 fabio Exp $"; #endif #ifdef CORREL_STATS static int num_calls; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static double bddCorrelationAux (DdManager *dd, DdNode *f, DdNode *g, st__table *table); static double bddCorrelationWeightsAux (DdManager *dd, DdNode *f, DdNode *g, double *prob, st__table *table); static int CorrelCompare (const char *key1, const char *key2); static int CorrelHash (const char *key, int modulus); static enum st__retval CorrelCleanUp (char *key, char *value, char *arg); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the correlation of f and g.] Description [Computes the correlation of f and g. If f == g, their correlation is 1. If f == g', their correlation is 0. Returns the fraction of minterms in the ON-set of the EXNOR of f and g. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM.] SideEffects [None] SeeAlso [Cudd_bddCorrelationWeights] ******************************************************************************/ double Cudd_bddCorrelation( DdManager * manager, DdNode * f, DdNode * g) { st__table *table; double correlation; #ifdef CORREL_STATS num_calls = 0; #endif table = st__init_table(CorrelCompare,CorrelHash); if (table == NULL) return((double)CUDD_OUT_OF_MEM); correlation = bddCorrelationAux(manager,f,g,table); st__foreach(table, CorrelCleanUp, NIL(char)); st__free_table(table); return(correlation); } /* end of Cudd_bddCorrelation */ /**Function******************************************************************** Synopsis [Computes the correlation of f and g for given input probabilities.] Description [Computes the correlation of f and g for given input probabilities. On input, prob\[i\] is supposed to contain the probability of the i-th input variable to be 1. If f == g, their correlation is 1. If f == g', their correlation is 0. Returns the probability that f and g have the same value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The correlation of f and the constant one gives the probability of f.] SideEffects [None] SeeAlso [Cudd_bddCorrelation] ******************************************************************************/ double Cudd_bddCorrelationWeights( DdManager * manager, DdNode * f, DdNode * g, double * prob) { st__table *table; double correlation; #ifdef CORREL_STATS num_calls = 0; #endif table = st__init_table(CorrelCompare,CorrelHash); if (table == NULL) return((double)CUDD_OUT_OF_MEM); correlation = bddCorrelationWeightsAux(manager,f,g,prob,table); st__foreach(table, CorrelCleanUp, NIL(char)); st__free_table(table); return(correlation); } /* end of Cudd_bddCorrelationWeights */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddCorrelation.] Description [Performs the recursive step of Cudd_bddCorrelation. Returns the fraction of minterms in the ON-set of the EXNOR of f and g.] SideEffects [None] SeeAlso [bddCorrelationWeightsAux] ******************************************************************************/ static double bddCorrelationAux( DdManager * dd, DdNode * f, DdNode * g, st__table * table) { DdNode *Fv, *Fnv, *G, *Gv, *Gnv; double min, *pmin, min1, min2, *dummy; HashEntry *entry; unsigned int topF, topG; statLine(dd); #ifdef CORREL_STATS num_calls++; #endif /* Terminal cases: only work for BDDs. */ if (f == g) return(1.0); if (f == Cudd_Not(g)) return(0.0); /* Standardize call using the following properties: ** (f EXNOR g) = (g EXNOR f) ** (f' EXNOR g') = (f EXNOR g). */ if (cuddF2L(f) > cuddF2L(g)) { DdNode *tmp = f; f = g; g = tmp; } if (Cudd_IsComplement(f)) { f = Cudd_Not(f); g = Cudd_Not(g); } /* From now on, f is regular. */ entry = ABC_ALLOC(HashEntry,1); if (entry == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(CUDD_OUT_OF_MEM); } entry->f = f; entry->g = g; /* We do not use the fact that ** correlation(f,g') = 1 - correlation(f,g) ** to minimize the risk of cancellation. */ if ( st__lookup(table, (const char *)entry, (char **)&dummy)) { min = *dummy; ABC_FREE(entry); return(min); } G = Cudd_Regular(g); topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } if (g != G) { Gv = Cudd_Not(Gv); Gnv = Cudd_Not(Gnv); } min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0; if (min1 == (double)CUDD_OUT_OF_MEM) { ABC_FREE(entry); return(CUDD_OUT_OF_MEM); } min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0; if (min2 == (double)CUDD_OUT_OF_MEM) { ABC_FREE(entry); return(CUDD_OUT_OF_MEM); } min = (min1+min2); pmin = ABC_ALLOC(double,1); if (pmin == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return((double)CUDD_OUT_OF_MEM); } *pmin = min; if ( st__insert(table,(char *)entry, (char *)pmin) == st__OUT_OF_MEM) { ABC_FREE(entry); ABC_FREE(pmin); return((double)CUDD_OUT_OF_MEM); } return(min); } /* end of bddCorrelationAux */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddCorrelationWeigths.] Description [] SideEffects [None] SeeAlso [bddCorrelationAux] ******************************************************************************/ static double bddCorrelationWeightsAux( DdManager * dd, DdNode * f, DdNode * g, double * prob, st__table * table) { DdNode *Fv, *Fnv, *G, *Gv, *Gnv; double min, *pmin, min1, min2, *dummy; HashEntry *entry; int topF, topG, index; statLine(dd); #ifdef CORREL_STATS num_calls++; #endif /* Terminal cases: only work for BDDs. */ if (f == g) return(1.0); if (f == Cudd_Not(g)) return(0.0); /* Standardize call using the following properties: ** (f EXNOR g) = (g EXNOR f) ** (f' EXNOR g') = (f EXNOR g). */ if (cuddF2L(f) > cuddF2L(g)) { DdNode *tmp = f; f = g; g = tmp; } if (Cudd_IsComplement(f)) { f = Cudd_Not(f); g = Cudd_Not(g); } /* From now on, f is regular. */ entry = ABC_ALLOC(HashEntry,1); if (entry == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return((double)CUDD_OUT_OF_MEM); } entry->f = f; entry->g = g; /* We do not use the fact that ** correlation(f,g') = 1 - correlation(f,g) ** to minimize the risk of cancellation. */ if ( st__lookup(table, (const char *)entry, (char **)&dummy)) { min = *dummy; ABC_FREE(entry); return(min); } G = Cudd_Regular(g); topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); index = f->index; } else { Fv = Fnv = f; index = G->index; } if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } if (g != G) { Gv = Cudd_Not(Gv); Gnv = Cudd_Not(Gnv); } min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index]; if (min1 == (double)CUDD_OUT_OF_MEM) { ABC_FREE(entry); return((double)CUDD_OUT_OF_MEM); } min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]); if (min2 == (double)CUDD_OUT_OF_MEM) { ABC_FREE(entry); return((double)CUDD_OUT_OF_MEM); } min = (min1+min2); pmin = ABC_ALLOC(double,1); if (pmin == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return((double)CUDD_OUT_OF_MEM); } *pmin = min; if ( st__insert(table,(char *)entry, (char *)pmin) == st__OUT_OF_MEM) { ABC_FREE(entry); ABC_FREE(pmin); return((double)CUDD_OUT_OF_MEM); } return(min); } /* end of bddCorrelationWeightsAux */ /**Function******************************************************************** Synopsis [Compares two hash table entries.] Description [Compares two hash table entries. Returns 0 if they are identical; 1 otherwise.] SideEffects [None] ******************************************************************************/ static int CorrelCompare( const char * key1, const char * key2) { HashEntry *entry1; HashEntry *entry2; entry1 = (HashEntry *) key1; entry2 = (HashEntry *) key2; if (entry1->f != entry2->f || entry1->g != entry2->g) return(1); return(0); } /* end of CorrelCompare */ /**Function******************************************************************** Synopsis [Hashes a hash table entry.] Description [Hashes a hash table entry. It is patterned after st__strhash. Returns a value between 0 and modulus.] SideEffects [None] ******************************************************************************/ static int CorrelHash( const char * key, int modulus) { HashEntry *entry; int val = 0; entry = (HashEntry *) key; #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g)); #else val = ((int) entry->f)*997 + ((int) entry->g); #endif return ((val < 0) ? -val : val) % modulus; } /* end of CorrelHash */ /**Function******************************************************************** Synopsis [Frees memory associated with hash table.] Description [Frees memory associated with hash table. Returns st__CONTINUE.] SideEffects [None] ******************************************************************************/ static enum st__retval CorrelCleanUp( char * key, char * value, char * arg) { double *d; HashEntry *entry; entry = (HashEntry *) key; ABC_FREE(entry); d = (double *)value; ABC_FREE(d); return st__CONTINUE; } /* end of CorrelCleanUp */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddBddIte.c000066400000000000000000001110211300674244400236370ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddBddIte.c] PackageName [cudd] Synopsis [BDD ITE function and satellites.] Description [External procedures included in this module:
  • Cudd_bddIte()
  • Cudd_bddIteConstant()
  • Cudd_bddIntersect()
  • Cudd_bddAnd()
  • Cudd_bddAndLimit()
  • Cudd_bddOr()
  • Cudd_bddNand()
  • Cudd_bddNor()
  • Cudd_bddXor()
  • Cudd_bddXnor()
  • Cudd_bddLeq()
Internal procedures included in this module:
  • cuddBddIteRecur()
  • cuddBddIntersectRecur()
  • cuddBddAndRecur()
  • cuddBddXorRecur()
Static procedures included in this module:
  • bddVarToConst()
  • bddVarToCanonical()
  • bddVarToCanonicalSimple()
] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.24 2004/08/13 18:04:46 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void bddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one); static int bddVarToCanonical (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp); static int bddVarToCanonicalSimple (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements ITE(f,g,h).] Description [Implements ITE(f,g,h). Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_addIte Cudd_bddIteConstant Cudd_bddIntersect] ******************************************************************************/ DdNode * Cudd_bddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *res; do { dd->reordered = 0; res = cuddBddIteRecur(dd,f,g,h); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddIte */ /**Function******************************************************************** Synopsis [Implements ITEconstant(f,g,h).] Description [Implements ITEconstant(f,g,h). Returns a pointer to the resulting BDD (which may or may not be constant) or DD_NON_CONSTANT. No new nodes are created.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_bddIntersect Cudd_bddLeq Cudd_addIteConstant] ******************************************************************************/ DdNode * Cudd_bddIteConstant( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); int comple; unsigned int topf, topg, toph, v; statLine(dd); /* Trivial cases. */ if (f == one) /* ITE(1,G,H) => G */ return(g); if (f == zero) /* ITE(0,G,H) => H */ return(h); /* f now not a constant. */ bddVarToConst(f, &g, &h, one); /* possibly convert g or h */ /* to constants */ if (g == h) /* ITE(F,G,G) => G */ return(g); if (Cudd_IsConstant(g) && Cudd_IsConstant(h)) return(DD_NON_CONSTANT); /* ITE(F,1,0) or ITE(F,0,1) */ /* => DD_NON_CONSTANT */ if (g == Cudd_Not(h)) return(DD_NON_CONSTANT); /* ITE(F,G,G') => DD_NON_CONSTANT */ /* if F != G and F != G' */ comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph); /* Cache lookup. */ r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h); if (r != NULL) { return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT)); } v = ddMin(topg, toph); /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */ if (topf < v && cuddT(f) == one && cuddE(f) == zero) { return(DD_NON_CONSTANT); } /* Compute cofactors. */ if (topf <= v) { v = ddMin(topf, v); /* v = top_var(F,G,H) */ Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } if (topg == v) { Gv = cuddT(g); Gnv = cuddE(g); } else { Gv = Gnv = g; } if (toph == v) { H = Cudd_Regular(h); Hv = cuddT(H); Hnv = cuddE(H); if (Cudd_IsComplement(h)) { Hv = Cudd_Not(Hv); Hnv = Cudd_Not(Hnv); } } else { Hv = Hnv = h; } /* Recursion. */ t = Cudd_bddIteConstant(dd, Fv, Gv, Hv); if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) { cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); return(DD_NON_CONSTANT); } e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv); if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) { cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); return(DD_NON_CONSTANT); } cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t); return(Cudd_NotCond(t,comple)); } /* end of Cudd_bddIteConstant */ /**Function******************************************************************** Synopsis [Returns a function included in the intersection of f and g.] Description [Computes a function included in the intersection of f and g. (That is, a witness that the intersection is not empty.) Cudd_bddIntersect tries to build as few new nodes as possible. If the only result of interest is whether f and g intersect, Cudd_bddLeq should be used instead.] SideEffects [None] SeeAlso [Cudd_bddLeq Cudd_bddIteConstant] ******************************************************************************/ DdNode * Cudd_bddIntersect( DdManager * dd /* manager */, DdNode * f /* first operand */, DdNode * g /* second operand */) { DdNode *res; do { dd->reordered = 0; res = cuddBddIntersectRecur(dd,f,g); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddIntersect */ /**Function******************************************************************** Synopsis [Computes the conjunction of two BDDs f and g.] Description [Computes the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor] ******************************************************************************/ DdNode * Cudd_bddAnd( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddBddAndRecur(dd,f,g); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddAnd */ /**Function******************************************************************** Synopsis [Computes the conjunction of two BDDs f and g. Returns NULL if too many nodes are required.] Description [Computes the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up or more new nodes than limit are required.] SideEffects [None] SeeAlso [Cudd_bddAnd] ******************************************************************************/ DdNode * Cudd_bddAndLimit( DdManager * dd, DdNode * f, DdNode * g, unsigned int limit) { DdNode *res; unsigned int saveLimit = dd->maxLive; dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit; do { dd->reordered = 0; res = cuddBddAndRecur(dd,f,g); } while (dd->reordered == 1); dd->maxLive = saveLimit; return(res); } /* end of Cudd_bddAndLimit */ /**Function******************************************************************** Synopsis [Computes the disjunction of two BDDs f and g.] Description [Computes the disjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor] ******************************************************************************/ DdNode * Cudd_bddOr( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g)); } while (dd->reordered == 1); res = Cudd_NotCond(res,res != NULL); return(res); } /* end of Cudd_bddOr */ /**Function******************************************************************** Synopsis [Computes the NAND of two BDDs f and g.] Description [Computes the NAND of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNor Cudd_bddXor Cudd_bddXnor] ******************************************************************************/ DdNode * Cudd_bddNand( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddBddAndRecur(dd,f,g); } while (dd->reordered == 1); res = Cudd_NotCond(res,res != NULL); return(res); } /* end of Cudd_bddNand */ /**Function******************************************************************** Synopsis [Computes the NOR of two BDDs f and g.] Description [Computes the NOR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand Cudd_bddXor Cudd_bddXnor] ******************************************************************************/ DdNode * Cudd_bddNor( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g)); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddNor */ /**Function******************************************************************** Synopsis [Computes the exclusive OR of two BDDs f and g.] Description [Computes the exclusive OR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXnor] ******************************************************************************/ DdNode * Cudd_bddXor( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddBddXorRecur(dd,f,g); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddXor */ /**Function******************************************************************** Synopsis [Computes the exclusive NOR of two BDDs f and g.] Description [Computes the exclusive NOR of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor] ******************************************************************************/ DdNode * Cudd_bddXnor( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddBddXorRecur(dd,f,Cudd_Not(g)); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddXnor */ /**Function******************************************************************** Synopsis [Determines whether f is less than or equal to g.] Description [Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created.] SideEffects [None] SeeAlso [Cudd_bddIteConstant Cudd_addEvalConst] ******************************************************************************/ int Cudd_bddLeq( DdManager * dd, DdNode * f, DdNode * g) { DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn; unsigned int topf, topg, res; statLine(dd); /* Terminal cases and normalization. */ if (f == g) return(1); if (Cudd_IsComplement(g)) { /* Special case: if f is regular and g is complemented, ** f(1,...,1) = 1 > 0 = g(1,...,1). */ if (!Cudd_IsComplement(f)) return(0); /* Both are complemented: Swap and complement because ** f <= g <=> g' <= f' and we want the second argument to be regular. */ tmp = g; g = Cudd_Not(f); f = Cudd_Not(tmp); } else if (Cudd_IsComplement(f) && cuddF2L(g) < cuddF2L(f)) { tmp = g; g = Cudd_Not(f); f = Cudd_Not(tmp); } /* Now g is regular and, if f is not regular, f < g. */ one = DD_ONE(dd); if (g == one) return(1); /* no need to test against zero */ if (f == one) return(0); /* since at this point g != one */ if (Cudd_Not(f) == g) return(0); /* because neither is constant */ zero = Cudd_Not(one); if (f == zero) return(1); /* Here neither f nor g is constant. */ /* Check cache. */ tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_bddLeq,f,g); if (tmp != NULL) { return(tmp == one); } /* Compute cofactors. */ F = Cudd_Regular(f); topf = dd->perm[F->index]; topg = dd->perm[g->index]; if (topf <= topg) { fv = cuddT(F); fvn = cuddE(F); if (f != F) { fv = Cudd_Not(fv); fvn = Cudd_Not(fvn); } } else { fv = fvn = f; } if (topg <= topf) { gv = cuddT(g); gvn = cuddE(g); } else { gv = gvn = g; } /* Recursive calls. Since we want to maximize the probability of ** the special case f(1,...,1) > g(1,...,1), we consider the negative ** cofactors first. Indeed, the complementation parity of the positive ** cofactors is the same as the one of the parent functions. */ res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv); /* Store result in cache and return. */ cuddCacheInsert2(dd,(DD_CTFP)Cudd_bddLeq,f,g,(res ? one : zero)); return(res); } /* end of Cudd_bddLeq */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddIte.] Description [Implements the recursive step of Cudd_bddIte. Returns a pointer to the resulting BDD. NULL if the intermediate result blows up or if reordering occurs.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddBddIteRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *one, *zero, *res; DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; unsigned int topf, topg, toph, v; int index = -1; int comple; statLine(dd); /* Terminal cases. */ /* One variable cases. */ if (f == (one = DD_ONE(dd))) /* ITE(1,G,H) = G */ return(g); if (f == (zero = Cudd_Not(one))) /* ITE(0,G,H) = H */ return(h); /* From now on, f is known not to be a constant. */ if (g == one || f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ if (h == zero) { /* ITE(F,1,0) = F */ return(f); } else { res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h)); return(Cudd_NotCond(res,res != NULL)); } } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ if (h == one) { /* ITE(F,0,1) = !F */ return(Cudd_Not(f)); } else { res = cuddBddAndRecur(dd,Cudd_Not(f),h); return(res); } } if (h == zero || f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ res = cuddBddAndRecur(dd,f,g); return(res); } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ res = cuddBddAndRecur(dd,f,Cudd_Not(g)); return(Cudd_NotCond(res,res != NULL)); } /* Check remaining one variable case. */ if (g == h) { /* ITE(F,G,G) = G */ return(g); } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */ res = cuddBddXorRecur(dd,f,h); return(res); } /* From here, there are no constants. */ comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph); /* f & g are now regular pointers */ v = ddMin(topg, toph); /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */ if (topf < v && cuddT(f) == one && cuddE(f) == zero) { r = cuddUniqueInter(dd, (int) f->index, g, h); return(Cudd_NotCond(r,comple && r != NULL)); } /* Check cache. */ r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h); if (r != NULL) { return(Cudd_NotCond(r,comple)); } /* Compute cofactors. */ if (topf <= v) { v = ddMin(topf, v); /* v = top_var(F,G,H) */ index = f->index; Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } if (topg == v) { index = g->index; Gv = cuddT(g); Gnv = cuddE(g); } else { Gv = Gnv = g; } if (toph == v) { H = Cudd_Regular(h); index = H->index; Hv = cuddT(H); Hnv = cuddE(H); if (Cudd_IsComplement(h)) { Hv = Cudd_Not(Hv); Hnv = Cudd_Not(Hnv); } } else { Hv = Hnv = h; } /* Recursive step. */ t = cuddBddIteRecur(dd,Fv,Gv,Hv); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv); if (e == NULL) { Cudd_IterDerefBdd(dd,t); return(NULL); } cuddRef(e); r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); if (r == NULL) { Cudd_IterDerefBdd(dd,t); Cudd_IterDerefBdd(dd,e); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r); return(Cudd_NotCond(r,comple)); } /* end of cuddBddIteRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddIntersect.] Description [] SideEffects [None] SeeAlso [Cudd_bddIntersect] ******************************************************************************/ DdNode * cuddBddIntersectRecur( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; DdNode *F, *G, *t, *e; DdNode *fv, *fnv, *gv, *gnv; DdNode *one, *zero; unsigned int index, topf, topg; statLine(dd); one = DD_ONE(dd); zero = Cudd_Not(one); /* Terminal cases. */ if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); if (f == g || g == one) return(f); if (f == one) return(g); /* At this point f and g are not constant. */ if (cuddF2L(f) > cuddF2L(g)) { DdNode *tmp = f; f = g; g = tmp; } res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g); if (res != NULL) return(res); /* Find splitting variable. Here we can skip the use of cuddI, ** because the operands are known to be non-constant. */ F = Cudd_Regular(f); topf = dd->perm[F->index]; G = Cudd_Regular(g); topg = dd->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = F->index; fv = cuddT(F); fnv = cuddE(F); if (Cudd_IsComplement(f)) { fv = Cudd_Not(fv); fnv = Cudd_Not(fnv); } } else { index = G->index; fv = fnv = f; } if (topg <= topf) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } /* Compute partial results. */ t = cuddBddIntersectRecur(dd,fv,gv); if (t == NULL) return(NULL); cuddRef(t); if (t != zero) { e = zero; } else { e = cuddBddIntersectRecur(dd,fnv,gnv); if (e == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } } cuddRef(e); if (t == e) { /* both equal zero */ res = t; } else if (Cudd_IsComplement(t)) { res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e)); if (res == NULL) { Cudd_IterDerefBdd(dd, t); Cudd_IterDerefBdd(dd, e); return(NULL); } res = Cudd_Not(res); } else { res = cuddUniqueInter(dd,(int)index,t,e); if (res == NULL) { Cudd_IterDerefBdd(dd, t); Cudd_IterDerefBdd(dd, e); return(NULL); } } cuddDeref(e); cuddDeref(t); cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res); return(res); } /* end of cuddBddIntersectRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddAnd.] Description [Implements the recursive step of Cudd_bddAnd by taking the conjunction of two BDDs. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddAnd] ******************************************************************************/ DdNode * cuddBddAndRecur( DdManager * manager, DdNode * f, DdNode * g) { DdNode *F, *fv, *fnv, *G, *gv, *gnv; DdNode *one, *r, *t, *e; unsigned int topf, topg, index; statLine(manager); one = DD_ONE(manager); /* Terminal cases. */ F = Cudd_Regular(f); G = Cudd_Regular(g); if (F == G) { if (f == g) return(f); else return(Cudd_Not(one)); } if (F == one) { if (f == one) return(g); else return(f); } if (G == one) { if (g == one) return(f); else return(g); } /* At this point f and g are not constant. */ if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */ DdNode *tmp = f; f = g; g = tmp; F = Cudd_Regular(f); G = Cudd_Regular(g); } /* Check cache. */ if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); if (r != NULL) return(r); } if ( manager->TimeStop && Abc_Clock() > manager->TimeStop ) return NULL; /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[F->index]; topg = manager->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = F->index; fv = cuddT(F); fnv = cuddE(F); if (Cudd_IsComplement(f)) { fv = Cudd_Not(fv); fnv = Cudd_Not(fnv); } } else { index = G->index; fv = fnv = f; } if (topg <= topf) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } t = cuddBddAndRecur(manager, fv, gv); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddAndRecur(manager, fnv, gnv); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } } cuddDeref(e); cuddDeref(t); if (F->ref != 1 || G->ref != 1) cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); return(r); } /* end of cuddBddAndRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddXor.] Description [Implements the recursive step of Cudd_bddXor by taking the exclusive OR of two BDDs. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddXor] ******************************************************************************/ DdNode * cuddBddXorRecur( DdManager * manager, DdNode * f, DdNode * g) { DdNode *fv, *fnv, *G, *gv, *gnv; DdNode *one, *zero, *r, *t, *e; unsigned int topf, topg, index; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* Terminal cases. */ if (f == g) return(zero); if (f == Cudd_Not(g)) return(one); if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency and simplify tests. */ DdNode *tmp = f; f = g; g = tmp; } if (g == zero) return(f); if (g == one) return(Cudd_Not(f)); if (Cudd_IsComplement(f)) { f = Cudd_Not(f); g = Cudd_Not(g); } /* Now the first argument is regular. */ if (f == one) return(Cudd_Not(g)); /* At this point f and g are not constant. */ /* Check cache. */ r = cuddCacheLookup2(manager, Cudd_bddXor, f, g); if (r != NULL) return(r); /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[f->index]; G = Cudd_Regular(g); topg = manager->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = f->index; fv = cuddT(f); fnv = cuddE(f); } else { index = G->index; fv = fnv = f; } if (topg <= topf) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } t = cuddBddXorRecur(manager, fv, gv); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddXorRecur(manager, fnv, gnv); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } } cuddDeref(e); cuddDeref(t); cuddCacheInsert2(manager, Cudd_bddXor, f, g, r); return(r); } /* end of cuddBddXorRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Replaces variables with constants if possible.] Description [This function performs part of the transformation to standard form by replacing variables with constants if possible.] SideEffects [None] SeeAlso [bddVarToCanonical bddVarToCanonicalSimple] ******************************************************************************/ static void bddVarToConst( DdNode * f, DdNode ** gp, DdNode ** hp, DdNode * one) { DdNode *g = *gp; DdNode *h = *hp; if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ *gp = one; } else if (f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ *gp = Cudd_Not(one); } if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ *hp = Cudd_Not(one); } else if (f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ *hp = one; } } /* end of bddVarToConst */ /**Function******************************************************************** Synopsis [Picks unique member from equiv expressions.] Description [Reduces 2 variable expressions to canonical form.] SideEffects [None] SeeAlso [bddVarToConst bddVarToCanonicalSimple] ******************************************************************************/ static int bddVarToCanonical( DdManager * dd, DdNode ** fp, DdNode ** gp, DdNode ** hp, unsigned int * topfp, unsigned int * topgp, unsigned int * tophp) { register DdNode *F, *G, *H, *r, *f, *g, *h; register unsigned int topf, topg, toph; DdNode *one = dd->one; int comple, change; f = *fp; g = *gp; h = *hp; F = Cudd_Regular(f); G = Cudd_Regular(g); H = Cudd_Regular(h); topf = cuddI(dd,F->index); topg = cuddI(dd,G->index); toph = cuddI(dd,H->index); change = 0; if (G == one) { /* ITE(F,c,H) */ if ((topf > toph) || (topf == toph && cuddF2L(f) > cuddF2L(h))) { r = h; h = f; f = r; /* ITE(F,1,H) = ITE(H,1,F) */ if (g != one) { /* g == zero */ f = Cudd_Not(f); /* ITE(F,0,H) = ITE(!H,0,!F) */ h = Cudd_Not(h); } change = 1; } } else if (H == one) { /* ITE(F,G,c) */ if ((topf > topg) || (topf == topg && cuddF2L(f) > cuddF2L(g))) { r = g; g = f; f = r; /* ITE(F,G,0) = ITE(G,F,0) */ if (h == one) { f = Cudd_Not(f); /* ITE(F,G,1) = ITE(!G,!F,1) */ g = Cudd_Not(g); } change = 1; } } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = ITE(G,F,!F) */ if ((topf > topg) || (topf == topg && cuddF2L(f) > cuddF2L(g))) { r = f; f = g; g = r; h = Cudd_Not(r); change = 1; } } /* adjust pointers so that the first 2 arguments to ITE are regular */ if (Cudd_IsComplement(f) != 0) { /* ITE(!F,G,H) = ITE(F,H,G) */ f = Cudd_Not(f); r = g; g = h; h = r; change = 1; } comple = 0; if (Cudd_IsComplement(g) != 0) { /* ITE(F,!G,H) = !ITE(F,G,!H) */ g = Cudd_Not(g); h = Cudd_Not(h); change = 1; comple = 1; } if (change != 0) { *fp = f; *gp = g; *hp = h; } *topfp = cuddI(dd,f->index); *topgp = cuddI(dd,g->index); *tophp = cuddI(dd,Cudd_Regular(h)->index); return(comple); } /* end of bddVarToCanonical */ /**Function******************************************************************** Synopsis [Picks unique member from equiv expressions.] Description [Makes sure the first two pointers are regular. This mat require the complementation of the result, which is signaled by returning 1 instead of 0. This function is simpler than the general case because it assumes that no two arguments are the same or complementary, and no argument is constant.] SideEffects [None] SeeAlso [bddVarToConst bddVarToCanonical] ******************************************************************************/ static int bddVarToCanonicalSimple( DdManager * dd, DdNode ** fp, DdNode ** gp, DdNode ** hp, unsigned int * topfp, unsigned int * topgp, unsigned int * tophp) { register DdNode *r, *f, *g, *h; int comple, change; f = *fp; g = *gp; h = *hp; change = 0; /* adjust pointers so that the first 2 arguments to ITE are regular */ if (Cudd_IsComplement(f)) { /* ITE(!F,G,H) = ITE(F,H,G) */ f = Cudd_Not(f); r = g; g = h; h = r; change = 1; } comple = 0; if (Cudd_IsComplement(g)) { /* ITE(F,!G,H) = !ITE(F,G,!H) */ g = Cudd_Not(g); h = Cudd_Not(h); change = 1; comple = 1; } if (change) { *fp = f; *gp = g; *hp = h; } /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ *topfp = dd->perm[f->index]; *topgp = dd->perm[g->index]; *tophp = dd->perm[Cudd_Regular(h)->index]; return(comple); } /* end of bddVarToCanonicalSimple */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddBridge.c000066400000000000000000000666541300674244400237250ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddBridge.c] PackageName [cudd] Synopsis [Translation from BDD to ADD and vice versa and transfer between different managers.] Description [External procedures included in this file:
  • Cudd_addBddThreshold()
  • Cudd_addBddStrictThreshold()
  • Cudd_addBddInterval()
  • Cudd_addBddIthBit()
  • Cudd_BddToAdd()
  • Cudd_addBddPattern()
  • Cudd_bddTransfer()
Internal procedures included in this file:
  • cuddBddTransfer()
  • cuddAddBddDoPattern()
Static procedures included in this file:
  • addBddDoThreshold()
  • addBddDoStrictThreshold()
  • addBddDoInterval()
  • addBddDoIthBit()
  • ddBddToAddRecur()
  • cuddBddTransferRecur()
] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddBridge.c,v 1.19 2008/04/25 06:42:55 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * addBddDoThreshold (DdManager *dd, DdNode *f, DdNode *val); static DdNode * addBddDoStrictThreshold (DdManager *dd, DdNode *f, DdNode *val); static DdNode * addBddDoInterval (DdManager *dd, DdNode *f, DdNode *l, DdNode *u); static DdNode * addBddDoIthBit (DdManager *dd, DdNode *f, DdNode *index); static DdNode * ddBddToAddRecur (DdManager *dd, DdNode *B); static DdNode * cuddBddTransferRecur (DdManager *ddS, DdManager *ddD, DdNode *f, st__table *table); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Converts an ADD to a BDD.] Description [Converts an ADD to a BDD by replacing all discriminants greater than or equal to value with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd Cudd_addBddStrictThreshold] ******************************************************************************/ DdNode * Cudd_addBddThreshold( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE value) { DdNode *res; DdNode *val; val = cuddUniqueConst(dd,value); if (val == NULL) return(NULL); cuddRef(val); do { dd->reordered = 0; res = addBddDoThreshold(dd, f, val); } while (dd->reordered == 1); if (res == NULL) { Cudd_RecursiveDeref(dd, val); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, val); cuddDeref(res); return(res); } /* end of Cudd_addBddThreshold */ /**Function******************************************************************** Synopsis [Converts an ADD to a BDD.] Description [Converts an ADD to a BDD by replacing all discriminants STRICTLY greater than value with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd Cudd_addBddThreshold] ******************************************************************************/ DdNode * Cudd_addBddStrictThreshold( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE value) { DdNode *res; DdNode *val; val = cuddUniqueConst(dd,value); if (val == NULL) return(NULL); cuddRef(val); do { dd->reordered = 0; res = addBddDoStrictThreshold(dd, f, val); } while (dd->reordered == 1); if (res == NULL) { Cudd_RecursiveDeref(dd, val); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, val); cuddDeref(res); return(res); } /* end of Cudd_addBddStrictThreshold */ /**Function******************************************************************** Synopsis [Converts an ADD to a BDD.] Description [Converts an ADD to a BDD by replacing all discriminants greater than or equal to lower and less than or equal to upper with 1, and all other discriminants with 0. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addBddThreshold Cudd_addBddStrictThreshold Cudd_addBddPattern Cudd_BddToAdd] ******************************************************************************/ DdNode * Cudd_addBddInterval( DdManager * dd, DdNode * f, CUDD_VALUE_TYPE lower, CUDD_VALUE_TYPE upper) { DdNode *res; DdNode *l; DdNode *u; /* Create constant nodes for the interval bounds, so that we can use ** the global cache. */ l = cuddUniqueConst(dd,lower); if (l == NULL) return(NULL); cuddRef(l); u = cuddUniqueConst(dd,upper); if (u == NULL) { Cudd_RecursiveDeref(dd,l); return(NULL); } cuddRef(u); do { dd->reordered = 0; res = addBddDoInterval(dd, f, l, u); } while (dd->reordered == 1); if (res == NULL) { Cudd_RecursiveDeref(dd, l); Cudd_RecursiveDeref(dd, u); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, l); Cudd_RecursiveDeref(dd, u); cuddDeref(res); return(res); } /* end of Cudd_addBddInterval */ /**Function******************************************************************** Synopsis [Converts an ADD to a BDD by extracting the i-th bit from the leaves.] Description [Converts an ADD to a BDD by replacing all discriminants whose i-th bit is equal to 1 with 1, and all other discriminants with 0. The i-th bit refers to the integer representation of the leaf value. If the value is has a fractional part, it is ignored. Repeated calls to this procedure allow one to transform an integer-valued ADD into an array of BDDs, one for each bit of the leaf values. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd] ******************************************************************************/ DdNode * Cudd_addBddIthBit( DdManager * dd, DdNode * f, int bit) { DdNode *res; DdNode *index; index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit); if (index == NULL) return(NULL); cuddRef(index); do { dd->reordered = 0; res = addBddDoIthBit(dd, f, index); } while (dd->reordered == 1); if (res == NULL) { Cudd_RecursiveDeref(dd, index); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, index); cuddDeref(res); return(res); } /* end of Cudd_addBddIthBit */ /**Function******************************************************************** Synopsis [Converts a BDD to a 0-1 ADD.] Description [Converts a BDD to a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addBddPattern Cudd_addBddThreshold Cudd_addBddInterval Cudd_addBddStrictThreshold] ******************************************************************************/ DdNode * Cudd_BddToAdd( DdManager * dd, DdNode * B) { DdNode *res; do { dd->reordered = 0; res = ddBddToAddRecur(dd, B); } while (dd->reordered ==1); return(res); } /* end of Cudd_BddToAdd */ /**Function******************************************************************** Synopsis [Converts an ADD to a BDD.] Description [Converts an ADD to a BDD by replacing all discriminants different from 0 with 1. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_BddToAdd Cudd_addBddThreshold Cudd_addBddInterval Cudd_addBddStrictThreshold] ******************************************************************************/ DdNode * Cudd_addBddPattern( DdManager * dd, DdNode * f) { DdNode *res; do { dd->reordered = 0; res = cuddAddBddDoPattern(dd, f); } while (dd->reordered == 1); return(res); } /* end of Cudd_addBddPattern */ /**Function******************************************************************** Synopsis [Convert a BDD from a manager to another one.] Description [Convert a BDD from a manager to another one. The orders of the variables in the two managers may be different. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_bddTransfer( DdManager * ddSource, DdManager * ddDestination, DdNode * f) { DdNode *res; do { ddDestination->reordered = 0; res = cuddBddTransfer(ddSource, ddDestination, f); } while (ddDestination->reordered == 1); return(res); } /* end of Cudd_bddTransfer */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Convert a BDD from a manager to another one.] Description [Convert a BDD from a manager to another one. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddTransfer] ******************************************************************************/ DdNode * cuddBddTransfer( DdManager * ddS, DdManager * ddD, DdNode * f) { DdNode *res; st__table *table = NULL; st__generator *gen = NULL; DdNode *key, *value; table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) goto failure; res = cuddBddTransferRecur(ddS, ddD, f, table); if (res != NULL) cuddRef(res); /* Dereference all elements in the table and dispose of the table. ** This must be done also if res is NULL to avoid leaks in case of ** reordering. */ gen = st__init_gen(table); if (gen == NULL) goto failure; while ( st__gen(gen, (const char **)&key, (char **)&value)) { Cudd_RecursiveDeref(ddD, value); } st__free_gen(gen); gen = NULL; st__free_table(table); table = NULL; if (res != NULL) cuddDeref(res); return(res); failure: /* No need to free gen because it is always NULL here. */ if (table != NULL) st__free_table(table); return(NULL); } /* end of cuddBddTransfer */ /**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addBddPattern.] Description [Performs the recursive step for Cudd_addBddPattern. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddAddBddDoPattern( DdManager * dd, DdNode * f) { DdNode *res, *T, *E; DdNode *fv, *fvn; int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { return(Cudd_NotCond(DD_ONE(dd),f == DD_ZERO(dd))); } /* Check cache. */ res = cuddCacheLookup1(dd,Cudd_addBddPattern,f); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = cuddAddBddDoPattern(dd,fv); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddBddDoPattern(dd,fvn); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); if (Cudd_IsComplement(T)) { res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } res = Cudd_Not(res); } else { res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert1(dd,Cudd_addBddPattern,f,res); return(res); } /* end of cuddAddBddDoPattern */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addBddThreshold.] Description [Performs the recursive step for Cudd_addBddThreshold. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [addBddDoStrictThreshold] ******************************************************************************/ static DdNode * addBddDoThreshold( DdManager * dd, DdNode * f, DdNode * val) { DdNode *res, *T, *E; DdNode *fv, *fvn; int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(val))); } /* Check cache. */ res = cuddCacheLookup2(dd,addBddDoThreshold,f,val); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = addBddDoThreshold(dd,fv,val); if (T == NULL) return(NULL); cuddRef(T); E = addBddDoThreshold(dd,fvn,val); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); if (Cudd_IsComplement(T)) { res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } res = Cudd_Not(res); } else { res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,addBddDoThreshold,f,val,res); return(res); } /* end of addBddDoThreshold */ /**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addBddStrictThreshold.] Description [Performs the recursive step for Cudd_addBddStrictThreshold. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [addBddDoThreshold] ******************************************************************************/ static DdNode * addBddDoStrictThreshold( DdManager * dd, DdNode * f, DdNode * val) { DdNode *res, *T, *E; DdNode *fv, *fvn; int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { return(Cudd_NotCond(DD_ONE(dd),cuddV(f) <= cuddV(val))); } /* Check cache. */ res = cuddCacheLookup2(dd,addBddDoStrictThreshold,f,val); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = addBddDoStrictThreshold(dd,fv,val); if (T == NULL) return(NULL); cuddRef(T); E = addBddDoStrictThreshold(dd,fvn,val); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); if (Cudd_IsComplement(T)) { res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } res = Cudd_Not(res); } else { res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,addBddDoStrictThreshold,f,val,res); return(res); } /* end of addBddDoStrictThreshold */ /**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addBddInterval.] Description [Performs the recursive step for Cudd_addBddInterval. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [addBddDoThreshold addBddDoStrictThreshold] ******************************************************************************/ static DdNode * addBddDoInterval( DdManager * dd, DdNode * f, DdNode * l, DdNode * u) { DdNode *res, *T, *E; DdNode *fv, *fvn; int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(l) || cuddV(f) > cuddV(u))); } /* Check cache. */ res = cuddCacheLookup(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = addBddDoInterval(dd,fv,l,u); if (T == NULL) return(NULL); cuddRef(T); E = addBddDoInterval(dd,fvn,l,u); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); if (Cudd_IsComplement(T)) { res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } res = Cudd_Not(res); } else { res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u,res); return(res); } /* end of addBddDoInterval */ /**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addBddIthBit.] Description [Performs the recursive step for Cudd_addBddIthBit. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * addBddDoIthBit( DdManager * dd, DdNode * f, DdNode * index) { DdNode *res, *T, *E; DdNode *fv, *fvn; int mask, value; int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { mask = 1 << ((int) cuddV(index)); value = (int) cuddV(f); return(Cudd_NotCond(DD_ONE(dd),(value & mask) == 0)); } /* Check cache. */ res = cuddCacheLookup2(dd,addBddDoIthBit,f,index); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = addBddDoIthBit(dd,fv,index); if (T == NULL) return(NULL); cuddRef(T); E = addBddDoIthBit(dd,fvn,index); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); if (Cudd_IsComplement(T)) { res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } res = Cudd_Not(res); } else { res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,addBddDoIthBit,f,index,res); return(res); } /* end of addBddDoIthBit */ /**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_BddToAdd.] Description [Performs the recursive step for Cudd_BddToAdd. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * ddBddToAddRecur( DdManager * dd, DdNode * B) { DdNode *one; DdNode *res, *res1, *T, *E, *Bt, *Be; int complement = 0; statLine(dd); one = DD_ONE(dd); if (Cudd_IsConstant(B)) { if (B == one) { res = one; } else { res = DD_ZERO(dd); } return(res); } /* Check visited table */ res = cuddCacheLookup1(dd,ddBddToAddRecur,B); if (res != NULL) return(res); if (Cudd_IsComplement(B)) { complement = 1; Bt = cuddT(Cudd_Regular(B)); Be = cuddE(Cudd_Regular(B)); } else { Bt = cuddT(B); Be = cuddE(B); } T = ddBddToAddRecur(dd, Bt); if (T == NULL) return(NULL); cuddRef(T); E = ddBddToAddRecur(dd, Be); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); /* No need to check for T == E, because it is guaranteed not to happen. */ res = cuddUniqueInter(dd, (int) Cudd_Regular(B)->index, T, E); if (res == NULL) { Cudd_RecursiveDeref(dd ,T); Cudd_RecursiveDeref(dd ,E); return(NULL); } cuddDeref(T); cuddDeref(E); if (complement) { cuddRef(res); res1 = cuddAddCmplRecur(dd, res); if (res1 == NULL) { Cudd_RecursiveDeref(dd, res); return(NULL); } cuddRef(res1); Cudd_RecursiveDeref(dd, res); res = res1; cuddDeref(res); } /* Store result. */ cuddCacheInsert1(dd,ddBddToAddRecur,B,res); return(res); } /* end of ddBddToAddRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddTransfer.] Description [Performs the recursive step of Cudd_bddTransfer. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddBddTransfer] ******************************************************************************/ static DdNode * cuddBddTransferRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table) { DdNode *ft, *fe, *t, *e, *var, *res; DdNode *one, *zero; int index; int comple = 0; statLine(ddD); one = DD_ONE(ddD); comple = Cudd_IsComplement(f); /* Trivial cases. */ if (Cudd_IsConstant(f)) return(Cudd_NotCond(one, comple)); /* Make canonical to increase the utilization of the cache. */ f = Cudd_NotCond(f,comple); /* Now f is a regular pointer to a non-constant node. */ /* Check the cache. */ if ( st__lookup(table, (const char *)f, (char **)&res)) return(Cudd_NotCond(res,comple)); if ( ddS->TimeStop && Abc_Clock() > ddS->TimeStop ) return NULL; if ( ddD->TimeStop && Abc_Clock() > ddD->TimeStop ) return NULL; /* Recursive step. */ index = f->index; ft = cuddT(f); fe = cuddE(f); t = cuddBddTransferRecur(ddS, ddD, ft, table); if (t == NULL) { return(NULL); } cuddRef(t); e = cuddBddTransferRecur(ddS, ddD, fe, table); if (e == NULL) { Cudd_RecursiveDeref(ddD, t); return(NULL); } cuddRef(e); zero = Cudd_Not(one); var = cuddUniqueInter(ddD,index,one,zero); if (var == NULL) { Cudd_RecursiveDeref(ddD, t); Cudd_RecursiveDeref(ddD, e); return(NULL); } res = cuddBddIteRecur(ddD,var,t,e); if (res == NULL) { Cudd_RecursiveDeref(ddD, t); Cudd_RecursiveDeref(ddD, e); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(ddD, t); Cudd_RecursiveDeref(ddD, e); if ( st__add_direct(table, (char *) f, (char *) res) == st__OUT_OF_MEM) { Cudd_RecursiveDeref(ddD, res); return(NULL); } return(Cudd_NotCond(res,comple)); } /* end of cuddBddTransferRecur */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddCache.c000066400000000000000000000741001300674244400235150ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddCache.c] PackageName [cudd] Synopsis [Functions for cache insertion and lookup.] Description [Internal procedures included in this module:
  • cuddInitCache()
  • cuddCacheInsert()
  • cuddCacheInsert2()
  • cuddCacheLookup()
  • cuddCacheLookupZdd()
  • cuddCacheLookup2()
  • cuddCacheLookup2Zdd()
  • cuddConstantLookup()
  • cuddCacheProfile()
  • cuddCacheResize()
  • cuddCacheFlush()
  • cuddComputeFloorLog2()
Static procedures included in this module:
] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #ifdef DD_CACHE_PROFILE #define DD_HYSTO_BINS 8 #endif /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddCache.c,v 1.34 2009/02/19 16:17:50 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Initializes the computed table.] Description [Initializes the computed table. It is called by Cudd_Init. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_Init] ******************************************************************************/ int cuddInitCache( DdManager * unique /* unique table */, unsigned int cacheSize /* initial size of the cache */, unsigned int maxCacheSize /* cache size beyond which no resizing occurs */) { int i; unsigned int logSize; #ifndef DD_CACHE_PROFILE DdNodePtr *mem; ptruint offset; #endif /* Round cacheSize to largest power of 2 not greater than the requested ** initial cache size. */ logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2)); cacheSize = 1 << logSize; // unique->acache = ABC_ALLOC(DdCache,cacheSize+1); unique->acache = ABC_ALLOC(DdCache,cacheSize+2); if (unique->acache == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } /* If the size of the cache entry is a power of 2, we want to ** enforce alignment to that power of two. This happens when ** DD_CACHE_PROFILE is not defined. */ #ifdef DD_CACHE_PROFILE unique->cache = unique->acache; unique->memused += (cacheSize) * sizeof(DdCache); #else mem = (DdNodePtr *) unique->acache; // offset = (ptruint) mem & (sizeof(DdCache) - 1); // mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr); offset = (ptruint) mem & (32 - 1); mem += (32 - offset) / sizeof(DdNodePtr); unique->cache = (DdCache *) mem; // assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0); assert(((ptruint) unique->cache & (32 - 1)) == 0); unique->memused += (cacheSize+1) * sizeof(DdCache); #endif unique->cacheSlots = cacheSize; unique->cacheShift = sizeof(int) * 8 - logSize; unique->maxCacheHard = maxCacheSize; /* If cacheSlack is non-negative, we can resize. */ unique->cacheSlack = (int) ddMin(maxCacheSize, DD_MAX_CACHE_TO_SLOTS_RATIO*unique->slots) - 2 * (int) cacheSize; Cudd_SetMinHit(unique,DD_MIN_HIT); /* Initialize to avoid division by 0 and immediate resizing. */ unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1); unique->cacheHits = 0; unique->totCachehits = 0; /* The sum of cacheMisses and totCacheMisses is always correct, ** even though cacheMisses is larger than it should for the reasons ** explained above. */ unique->totCacheMisses = -unique->cacheMisses; unique->cachecollisions = 0; unique->cacheinserts = 0; unique->cacheLastInserts = 0; unique->cachedeletions = 0; /* Initialize the cache */ for (i = 0; (unsigned) i < cacheSize; i++) { unique->cache[i].h = 0; /* unused slots */ unique->cache[i].data = NULL; /* invalid entry */ #ifdef DD_CACHE_PROFILE unique->cache[i].count = 0; #endif } return(1); } /* end of cuddInitCache */ /**Function******************************************************************** Synopsis [Inserts a result in the cache.] Description [] SideEffects [None] SeeAlso [cuddCacheInsert2 cuddCacheInsert1] ******************************************************************************/ void cuddCacheInsert( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h, DdNode * data) { int posn; unsigned hash; register DdCache *entry; ptruint uf, ug, uh; ptruint ufc, ugc, uhc; uf = (ptruint) f | (op & 0xe); ug = (ptruint) g | (op >> 4); uh = (ptruint) h; ufc = (ptruint) cuddF2L(f) | (op & 0xe); ugc = (ptruint) cuddF2L(g) | (op >> 4); uhc = (ptruint) cuddF2L(h); hash = ddCHash2_(uhc,ufc,ugc); // posn = ddCHash2(uhc,ufc,ugc,table->cacheShift); posn = hash >> table->cacheShift; entry = &table->cache[posn]; table->cachecollisions += entry->data != NULL; table->cacheinserts++; entry->f = (DdNode *) uf; entry->g = (DdNode *) ug; entry->h = uh; entry->data = data; #ifdef DD_CACHE_PROFILE entry->count++; #endif entry->hash = hash; } /* end of cuddCacheInsert */ /**Function******************************************************************** Synopsis [Inserts a result in the cache for a function with two operands.] Description [] SideEffects [None] SeeAlso [cuddCacheInsert cuddCacheInsert1] ******************************************************************************/ void cuddCacheInsert2( DdManager * table, DD_CTFP op, DdNode * f, DdNode * g, DdNode * data) { int posn; unsigned hash; register DdCache *entry; hash = ddCHash2_(op,cuddF2L(f),cuddF2L(g)); // posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift); posn = hash >> table->cacheShift; entry = &table->cache[posn]; if (entry->data != NULL) { table->cachecollisions++; } table->cacheinserts++; entry->f = f; entry->g = g; entry->h = (ptruint) op; entry->data = data; #ifdef DD_CACHE_PROFILE entry->count++; #endif entry->hash = hash; } /* end of cuddCacheInsert2 */ /**Function******************************************************************** Synopsis [Inserts a result in the cache for a function with two operands.] Description [] SideEffects [None] SeeAlso [cuddCacheInsert cuddCacheInsert2] ******************************************************************************/ void cuddCacheInsert1( DdManager * table, DD_CTFP1 op, DdNode * f, DdNode * data) { int posn; unsigned hash; register DdCache *entry; hash = ddCHash2_(op,cuddF2L(f),cuddF2L(f)); // posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift); posn = hash >> table->cacheShift; entry = &table->cache[posn]; if (entry->data != NULL) { table->cachecollisions++; } table->cacheinserts++; entry->f = f; entry->g = f; entry->h = (ptruint) op; entry->data = data; #ifdef DD_CACHE_PROFILE entry->count++; #endif entry->hash = hash; } /* end of cuddCacheInsert1 */ /**Function******************************************************************** Synopsis [Looks up in the cache for the result of op applied to f, g, and h.] Description [Returns the result if found; it returns NULL if no result is found.] SideEffects [None] SeeAlso [cuddCacheLookup2 cuddCacheLookup1] ******************************************************************************/ DdNode * cuddCacheLookup( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h) { int posn; DdCache *en,*cache; DdNode *data; ptruint uf, ug, uh; ptruint ufc, ugc, uhc; uf = (ptruint) f | (op & 0xe); ug = (ptruint) g | (op >> 4); uh = (ptruint) h; ufc = (ptruint) cuddF2L(f) | (op & 0xe); ugc = (ptruint) cuddF2L(g) | (op >> 4); uhc = (ptruint) cuddF2L(h); cache = table->cache; #ifdef DD_DEBUG if (cache == NULL) { return(NULL); } #endif posn = ddCHash2(uhc,ufc,ugc,table->cacheShift); en = &cache[posn]; if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && en->h==uh) { data = Cudd_Regular(en->data); table->cacheHits++; if (data->ref == 0) { cuddReclaim(table,data); } return(en->data); } /* Cache miss: decide whether to resize. */ table->cacheMisses++; if (table->cacheSlack >= 0 && table->cacheHits > table->cacheMisses * table->minHit) { cuddCacheResize(table); } return(NULL); } /* end of cuddCacheLookup */ /**Function******************************************************************** Synopsis [Looks up in the cache for the result of op applied to f, g, and h.] Description [Returns the result if found; it returns NULL if no result is found.] SideEffects [None] SeeAlso [cuddCacheLookup2Zdd cuddCacheLookup1Zdd] ******************************************************************************/ DdNode * cuddCacheLookupZdd( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h) { int posn; DdCache *en,*cache; DdNode *data; ptruint uf, ug, uh; ptruint ufc, ugc, uhc; uf = (ptruint) f | (op & 0xe); ug = (ptruint) g | (op >> 4); uh = (ptruint) h; ufc = (ptruint) cuddF2L(f) | (op & 0xe); ugc = (ptruint) cuddF2L(g) | (op >> 4); uhc = (ptruint) cuddF2L(h); cache = table->cache; #ifdef DD_DEBUG if (cache == NULL) { return(NULL); } #endif posn = ddCHash2(uhc,ufc,ugc,table->cacheShift); en = &cache[posn]; if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && en->h==uh) { data = Cudd_Regular(en->data); table->cacheHits++; if (data->ref == 0) { cuddReclaimZdd(table,data); } return(en->data); } /* Cache miss: decide whether to resize. */ table->cacheMisses++; if (table->cacheSlack >= 0 && table->cacheHits > table->cacheMisses * table->minHit) { cuddCacheResize(table); } return(NULL); } /* end of cuddCacheLookupZdd */ /**Function******************************************************************** Synopsis [Looks up in the cache for the result of op applied to f and g.] Description [Returns the result if found; it returns NULL if no result is found.] SideEffects [None] SeeAlso [cuddCacheLookup cuddCacheLookup1] ******************************************************************************/ DdNode * cuddCacheLookup2( DdManager * table, DD_CTFP op, DdNode * f, DdNode * g) { int posn; DdCache *en,*cache; DdNode *data; cache = table->cache; #ifdef DD_DEBUG if (cache == NULL) { return(NULL); } #endif posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift); en = &cache[posn]; if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) { data = Cudd_Regular(en->data); table->cacheHits++; if (data->ref == 0) { cuddReclaim(table,data); } return(en->data); } /* Cache miss: decide whether to resize. */ table->cacheMisses++; if (table->cacheSlack >= 0 && table->cacheHits > table->cacheMisses * table->minHit) { cuddCacheResize(table); } return(NULL); } /* end of cuddCacheLookup2 */ /**Function******************************************************************** Synopsis [Looks up in the cache for the result of op applied to f.] Description [Returns the result if found; it returns NULL if no result is found.] SideEffects [None] SeeAlso [cuddCacheLookup cuddCacheLookup2] ******************************************************************************/ DdNode * cuddCacheLookup1( DdManager * table, DD_CTFP1 op, DdNode * f) { int posn; DdCache *en,*cache; DdNode *data; cache = table->cache; #ifdef DD_DEBUG if (cache == NULL) { return(NULL); } #endif posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift); en = &cache[posn]; if (en->data != NULL && en->f==f && en->h==(ptruint)op) { data = Cudd_Regular(en->data); table->cacheHits++; if (data->ref == 0) { cuddReclaim(table,data); } return(en->data); } /* Cache miss: decide whether to resize. */ table->cacheMisses++; if (table->cacheSlack >= 0 && table->cacheHits > table->cacheMisses * table->minHit) { cuddCacheResize(table); } return(NULL); } /* end of cuddCacheLookup1 */ /**Function******************************************************************** Synopsis [Looks up in the cache for the result of op applied to f and g.] Description [Returns the result if found; it returns NULL if no result is found.] SideEffects [None] SeeAlso [cuddCacheLookupZdd cuddCacheLookup1Zdd] ******************************************************************************/ DdNode * cuddCacheLookup2Zdd( DdManager * table, DD_CTFP op, DdNode * f, DdNode * g) { int posn; DdCache *en,*cache; DdNode *data; cache = table->cache; #ifdef DD_DEBUG if (cache == NULL) { return(NULL); } #endif posn = ddCHash2(op,cuddF2L(f),cuddF2L(g),table->cacheShift); en = &cache[posn]; if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) { data = Cudd_Regular(en->data); table->cacheHits++; if (data->ref == 0) { cuddReclaimZdd(table,data); } return(en->data); } /* Cache miss: decide whether to resize. */ table->cacheMisses++; if (table->cacheSlack >= 0 && table->cacheHits > table->cacheMisses * table->minHit) { cuddCacheResize(table); } return(NULL); } /* end of cuddCacheLookup2Zdd */ /**Function******************************************************************** Synopsis [Looks up in the cache for the result of op applied to f.] Description [Returns the result if found; it returns NULL if no result is found.] SideEffects [None] SeeAlso [cuddCacheLookupZdd cuddCacheLookup2Zdd] ******************************************************************************/ DdNode * cuddCacheLookup1Zdd( DdManager * table, DD_CTFP1 op, DdNode * f) { int posn; DdCache *en,*cache; DdNode *data; cache = table->cache; #ifdef DD_DEBUG if (cache == NULL) { return(NULL); } #endif posn = ddCHash2(op,cuddF2L(f),cuddF2L(f),table->cacheShift); en = &cache[posn]; if (en->data != NULL && en->f==f && en->h==(ptruint)op) { data = Cudd_Regular(en->data); table->cacheHits++; if (data->ref == 0) { cuddReclaimZdd(table,data); } return(en->data); } /* Cache miss: decide whether to resize. */ table->cacheMisses++; if (table->cacheSlack >= 0 && table->cacheHits > table->cacheMisses * table->minHit) { cuddCacheResize(table); } return(NULL); } /* end of cuddCacheLookup1Zdd */ /**Function******************************************************************** Synopsis [Looks up in the cache for the result of op applied to f, g, and h.] Description [Looks up in the cache for the result of op applied to f, g, and h. Assumes that the calling procedure (e.g., Cudd_bddIteConstant) is only interested in whether the result is constant or not. Returns the result if found (possibly DD_NON_CONSTANT); otherwise it returns NULL.] SideEffects [None] SeeAlso [cuddCacheLookup] ******************************************************************************/ DdNode * cuddConstantLookup( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h) { int posn; DdCache *en,*cache; ptruint uf, ug, uh; ptruint ufc, ugc, uhc; uf = (ptruint) f | (op & 0xe); ug = (ptruint) g | (op >> 4); uh = (ptruint) h; ufc = (ptruint) cuddF2L(f) | (op & 0xe); ugc = (ptruint) cuddF2L(g) | (op >> 4); uhc = (ptruint) cuddF2L(h); cache = table->cache; #ifdef DD_DEBUG if (cache == NULL) { return(NULL); } #endif posn = ddCHash2(uhc,ufc,ugc,table->cacheShift); en = &cache[posn]; /* We do not reclaim here because the result should not be * referenced, but only tested for being a constant. */ if (en->data != NULL && en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) { table->cacheHits++; return(en->data); } /* Cache miss: decide whether to resize. */ table->cacheMisses++; if (table->cacheSlack >= 0 && table->cacheHits > table->cacheMisses * table->minHit) { cuddCacheResize(table); } return(NULL); } /* end of cuddConstantLookup */ /**Function******************************************************************** Synopsis [Computes and prints a profile of the cache usage.] Description [Computes and prints a profile of the cache usage. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddCacheProfile( DdManager * table, FILE * fp) { DdCache *cache = table->cache; int slots = table->cacheSlots; int nzeroes = 0; int i, retval; double exUsed; #ifdef DD_CACHE_PROFILE double count, mean, meansq, stddev, expected; long max, min; int imax, imin; double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */ int nbins = DD_HYSTO_BINS; int bin; long thiscount; double totalcount, exStddev; meansq = mean = expected = 0.0; max = min = (long) cache[0].count; imax = imin = 0; totalcount = 0.0; hystogramQ = ABC_ALLOC(double, nbins); if (hystogramQ == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } hystogramR = ABC_ALLOC(double, nbins); if (hystogramR == NULL) { ABC_FREE(hystogramQ); table->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < nbins; i++) { hystogramQ[i] = 0; hystogramR[i] = 0; } for (i = 0; i < slots; i++) { thiscount = (long) cache[i].count; if (thiscount > max) { max = thiscount; imax = i; } if (thiscount < min) { min = thiscount; imin = i; } if (thiscount == 0) { nzeroes++; } count = (double) thiscount; mean += count; meansq += count * count; totalcount += count; expected += count * (double) i; bin = (i * nbins) / slots; hystogramQ[bin] += (double) thiscount; bin = i % nbins; hystogramR[bin] += (double) thiscount; } mean /= (double) slots; meansq /= (double) slots; /* Compute the standard deviation from both the data and the ** theoretical model for a random distribution. */ stddev = sqrt(meansq - mean*mean); exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots); retval = fprintf(fp,"Cache average accesses = %g\n", mean); if (retval == EOF) return(0); retval = fprintf(fp,"Cache access standard deviation = %g ", stddev); if (retval == EOF) return(0); retval = fprintf(fp,"(expected = %g)\n", exStddev); if (retval == EOF) return(0); retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); if (retval == EOF) return(0); retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); if (retval == EOF) return(0); exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots)); retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", 100.0 - (double) nzeroes * 100.0 / (double) slots, exUsed); if (retval == EOF) return(0); if (totalcount > 0) { expected /= totalcount; retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); if (retval == EOF) return(0); retval = fprintf(fp," (expected bin value = %g)\nBy quotient:", expected); if (retval == EOF) return(0); for (i = nbins - 1; i>=0; i--) { retval = fprintf(fp," %.0f", hystogramQ[i]); if (retval == EOF) return(0); } retval = fprintf(fp,"\nBy residue: "); if (retval == EOF) return(0); for (i = nbins - 1; i>=0; i--) { retval = fprintf(fp," %.0f", hystogramR[i]); if (retval == EOF) return(0); } retval = fprintf(fp,"\n"); if (retval == EOF) return(0); } ABC_FREE(hystogramQ); ABC_FREE(hystogramR); #else for (i = 0; i < slots; i++) { nzeroes += cache[i].h == 0; } exUsed = 100.0 * (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) / (double) slots)); retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", 100.0 - (double) nzeroes * 100.0 / (double) slots, exUsed); if (retval == EOF) return(0); #endif return(1); } /* end of cuddCacheProfile */ /**Function******************************************************************** Synopsis [Resizes the cache.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddCacheResize( DdManager * table) { DdCache *cache, *oldcache, *oldacache, *entry, *old; int i; int posn, shift; unsigned int slots, oldslots; double offset; int moved = 0; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; #ifndef DD_CACHE_PROFILE ptruint misalignment; DdNodePtr *mem; #endif oldcache = table->cache; oldacache = table->acache; oldslots = table->cacheSlots; slots = table->cacheSlots = oldslots << 1; #ifdef DD_VERBOSE (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n", oldslots, slots); (void) fprintf(table->err, "\thits = %g\tmisses = %g\thit ratio = %5.3f\n", table->cacheHits, table->cacheMisses, table->cacheHits / (table->cacheHits + table->cacheMisses)); #endif saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; // table->acache = cache = ABC_ALLOC(DdCache,slots+1); table->acache = cache = ABC_ALLOC(DdCache,slots+2); MMoutOfMemory = saveHandler; /* If we fail to allocate the new table we just give up. */ if (cache == NULL) { #ifdef DD_VERBOSE (void) fprintf(table->err,"Resizing failed. Giving up.\n"); #endif table->cacheSlots = oldslots; table->acache = oldacache; /* Do not try to resize again. */ table->maxCacheHard = oldslots - 1; table->cacheSlack = - (int) (oldslots + 1); return; } /* If the size of the cache entry is a power of 2, we want to ** enforce alignment to that power of two. This happens when ** DD_CACHE_PROFILE is not defined. */ #ifdef DD_CACHE_PROFILE table->cache = cache; #else mem = (DdNodePtr *) cache; // misalignment = (ptruint) mem & (sizeof(DdCache) - 1); // mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr); // table->cache = cache = (DdCache *) mem; // assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0); misalignment = (ptruint) mem & (32 - 1); mem += (32 - misalignment) / sizeof(DdNodePtr); table->cache = cache = (DdCache *) mem; assert(((ptruint) table->cache & (32 - 1)) == 0); #endif shift = --(table->cacheShift); table->memused += (slots - oldslots) * sizeof(DdCache); table->cacheSlack -= slots; /* need these many slots to double again */ /* Clear new cache. */ for (i = 0; (unsigned) i < slots; i++) { cache[i].data = NULL; cache[i].h = 0; #ifdef DD_CACHE_PROFILE cache[i].count = 0; #endif } /* Copy from old cache to new one. */ for (i = 0; (unsigned) i < oldslots; i++) { old = &oldcache[i]; if (old->data != NULL) { // posn = ddCHash2(old->h,old->f,old->g,shift); posn = old->hash >> shift; entry = &cache[posn]; entry->f = old->f; entry->g = old->g; entry->h = old->h; entry->data = old->data; #ifdef DD_CACHE_PROFILE entry->count = 1; #endif entry->hash = old->hash; moved++; } } ABC_FREE(oldacache); /* Reinitialize measurements so as to avoid division by 0 and ** immediate resizing. */ offset = (double) (int) (slots * table->minHit + 1); table->totCacheMisses += table->cacheMisses - offset; table->cacheMisses = offset; table->totCachehits += table->cacheHits; table->cacheHits = 0; table->cacheLastInserts = table->cacheinserts - (double) moved; } /* end of cuddCacheResize */ /**Function******************************************************************** Synopsis [Flushes the cache.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddCacheFlush( DdManager * table) { int i, slots; DdCache *cache; slots = table->cacheSlots; cache = table->cache; for (i = 0; i < slots; i++) { table->cachedeletions += cache[i].data != NULL; cache[i].data = NULL; } table->cacheLastInserts = table->cacheinserts; return; } /* end of cuddCacheFlush */ /**Function******************************************************************** Synopsis [Returns the floor of the logarithm to the base 2.] Description [Returns the floor of the logarithm to the base 2. The input value is assumed to be greater than 0.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddComputeFloorLog2( unsigned int value) { int floorLog = 0; #ifdef DD_DEBUG assert(value > 0); #endif while (value > 1) { floorLog++; value >>= 1; } return(floorLog); } /* end of cuddComputeFloorLog2 */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddCheck.c000066400000000000000000000761041300674244400235350ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddCheck.c] PackageName [cudd] Synopsis [Functions to check consistency of data structures.] Description [External procedures included in this module:
  • Cudd_DebugCheck()
  • Cudd_CheckKeys()
Internal procedures included in this module:
  • cuddHeapProfile()
  • cuddPrintNode()
  • cuddPrintVarGroups()
Static procedures included in this module:
  • debugFindParent()
] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.35 2009/03/08 02:49:01 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void debugFindParent (DdManager *table, DdNode *node); #if 0 static void debugCheckParent (DdManager *table, DdNode *node); #endif /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Checks for inconsistencies in the DD heap.] Description [Checks for inconsistencies in the DD heap:
  • node has illegal index
  • live node has dead children
  • node has illegal Then or Else pointers
  • BDD/ADD node has identical children
  • ZDD node has zero then child
  • wrong number of total nodes
  • wrong number of dead nodes
  • ref count error at node
Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is not enough memory; 1 otherwise.] SideEffects [None] SeeAlso [Cudd_CheckKeys] ******************************************************************************/ int Cudd_DebugCheck( DdManager * table) { unsigned int i; int j,count; int slots; DdNodePtr *nodelist; DdNode *f; DdNode *sentinel = &(table->sentinel); st__table *edgeTable; /* stores internal ref count for each node */ st__generator *gen; int flag = 0; int totalNode; int deadNode; int index; edgeTable = st__init_table( st__ptrcmp, st__ptrhash); if (edgeTable == NULL) return(CUDD_OUT_OF_MEM); /* Check the BDD/ADD subtables. */ for (i = 0; i < (unsigned) table->size; i++) { index = table->invperm[i]; if (i != (unsigned) table->perm[index]) { (void) fprintf(table->err, "Permutation corrupted: invperm[%u] = %d\t perm[%d] = %d\n", i, index, index, table->perm[index]); } nodelist = table->subtables[i].nodelist; slots = table->subtables[i].slots; totalNode = 0; deadNode = 0; for (j = 0; j < slots; j++) { /* for each subtable slot */ f = nodelist[j]; while (f != sentinel) { totalNode++; if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { if ((int) f->index != index) { (void) fprintf(table->err, "Error: node has illegal index\n"); cuddPrintNode(f,table->err); flag = 1; } if ((unsigned) cuddI(table,cuddT(f)->index) <= i || (unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index) <= i) { (void) fprintf(table->err, "Error: node has illegal children\n"); cuddPrintNode(f,table->err); flag = 1; } if (Cudd_Regular(cuddT(f)) != cuddT(f)) { (void) fprintf(table->err, "Error: node has illegal form\n"); cuddPrintNode(f,table->err); flag = 1; } if (cuddT(f) == cuddE(f)) { (void) fprintf(table->err, "Error: node has identical children\n"); cuddPrintNode(f,table->err); flag = 1; } if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) { (void) fprintf(table->err, "Error: live node has dead children\n"); cuddPrintNode(f,table->err); flag =1; } /* Increment the internal reference count for the ** then child of the current node. */ if ( st__lookup_int(edgeTable,(char *)cuddT(f),&count)) { count++; } else { count = 1; } if ( st__insert(edgeTable,(char *)cuddT(f), (char *)(long)count) == st__OUT_OF_MEM) { st__free_table(edgeTable); return(CUDD_OUT_OF_MEM); } /* Increment the internal reference count for the ** else child of the current node. */ if ( st__lookup_int(edgeTable,(char *)Cudd_Regular(cuddE(f)), &count)) { count++; } else { count = 1; } if ( st__insert(edgeTable,(char *)Cudd_Regular(cuddE(f)), (char *)(long)count) == st__OUT_OF_MEM) { st__free_table(edgeTable); return(CUDD_OUT_OF_MEM); } } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) { deadNode++; #if 0 debugCheckParent(table,f); #endif } else { fprintf(table->err, "Error: node has illegal Then or Else pointers\n"); cuddPrintNode(f,table->err); flag = 1; } f = f->next; } /* for each element of the collision list */ } /* for each subtable slot */ if ((unsigned) totalNode != table->subtables[i].keys) { fprintf(table->err,"Error: wrong number of total nodes\n"); flag = 1; } if ((unsigned) deadNode != table->subtables[i].dead) { fprintf(table->err,"Error: wrong number of dead nodes\n"); flag = 1; } } /* for each BDD/ADD subtable */ /* Check the ZDD subtables. */ for (i = 0; i < (unsigned) table->sizeZ; i++) { index = table->invpermZ[i]; if (i != (unsigned) table->permZ[index]) { (void) fprintf(table->err, "Permutation corrupted: invpermZ[%u] = %d\t permZ[%d] = %d in ZDD\n", i, index, index, table->permZ[index]); } nodelist = table->subtableZ[i].nodelist; slots = table->subtableZ[i].slots; totalNode = 0; deadNode = 0; for (j = 0; j < slots; j++) { /* for each subtable slot */ f = nodelist[j]; while (f != NULL) { totalNode++; if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { if ((int) f->index != index) { (void) fprintf(table->err, "Error: ZDD node has illegal index\n"); cuddPrintNode(f,table->err); flag = 1; } if (Cudd_IsComplement(cuddT(f)) || Cudd_IsComplement(cuddE(f))) { (void) fprintf(table->err, "Error: ZDD node has complemented children\n"); cuddPrintNode(f,table->err); flag = 1; } if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i || (unsigned) cuddIZ(table,cuddE(f)->index) <= i) { (void) fprintf(table->err, "Error: ZDD node has illegal children\n"); cuddPrintNode(f,table->err); cuddPrintNode(cuddT(f),table->err); cuddPrintNode(cuddE(f),table->err); flag = 1; } if (cuddT(f) == DD_ZERO(table)) { (void) fprintf(table->err, "Error: ZDD node has zero then child\n"); cuddPrintNode(f,table->err); flag = 1; } if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) { (void) fprintf(table->err, "Error: ZDD live node has dead children\n"); cuddPrintNode(f,table->err); flag =1; } /* Increment the internal reference count for the ** then child of the current node. */ if ( st__lookup_int(edgeTable,(char *)cuddT(f),&count)) { count++; } else { count = 1; } if ( st__insert(edgeTable,(char *)cuddT(f), (char *)(long)count) == st__OUT_OF_MEM) { st__free_table(edgeTable); return(CUDD_OUT_OF_MEM); } /* Increment the internal reference count for the ** else child of the current node. */ if ( st__lookup_int(edgeTable,(char *)cuddE(f),&count)) { count++; } else { count = 1; } if ( st__insert(edgeTable,(char *)cuddE(f), (char *)(long)count) == st__OUT_OF_MEM) { st__free_table(edgeTable); table->errorCode = CUDD_MEMORY_OUT; return(CUDD_OUT_OF_MEM); } } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) { deadNode++; #if 0 debugCheckParent(table,f); #endif } else { fprintf(table->err, "Error: ZDD node has illegal Then or Else pointers\n"); cuddPrintNode(f,table->err); flag = 1; } f = f->next; } /* for each element of the collision list */ } /* for each subtable slot */ if ((unsigned) totalNode != table->subtableZ[i].keys) { fprintf(table->err, "Error: wrong number of total nodes in ZDD\n"); flag = 1; } if ((unsigned) deadNode != table->subtableZ[i].dead) { fprintf(table->err, "Error: wrong number of dead nodes in ZDD\n"); flag = 1; } } /* for each ZDD subtable */ /* Check the constant table. */ nodelist = table->constants.nodelist; slots = table->constants.slots; totalNode = 0; deadNode = 0; for (j = 0; j < slots; j++) { f = nodelist[j]; while (f != NULL) { totalNode++; if (f->ref != 0) { if (f->index != CUDD_CONST_INDEX) { fprintf(table->err,"Error: node has illegal index\n"); #if SIZEOF_VOID_P == 8 fprintf(table->err, " node 0x%lx, id = %u, ref = %u, value = %g\n", (ptruint)f,f->index,f->ref,cuddV(f)); #else fprintf(table->err, " node 0x%x, id = %hu, ref = %hu, value = %g\n", (ptruint)f,f->index,f->ref,cuddV(f)); #endif flag = 1; } } else { deadNode++; } f = f->next; } } if ((unsigned) totalNode != table->constants.keys) { (void) fprintf(table->err, "Error: wrong number of total nodes in constants\n"); flag = 1; } if ((unsigned) deadNode != table->constants.dead) { (void) fprintf(table->err, "Error: wrong number of dead nodes in constants\n"); flag = 1; } gen = st__init_gen(edgeTable); while ( st__gen(gen, (const char **)&f, (char **)&count)) { if (count > (int)(f->ref) && f->ref != DD_MAXREF) { #if SIZEOF_VOID_P == 8 fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); #else fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,count,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); #endif debugFindParent(table,f); flag = 1; } } st__free_gen(gen); st__free_table(edgeTable); return (flag); } /* end of Cudd_DebugCheck */ /**Function******************************************************************** Synopsis [Checks for several conditions that should not occur.] Description [Checks for the following conditions:
  • Wrong sizes of subtables.
  • Wrong number of keys found in unique subtable.
  • Wrong number of dead found in unique subtable.
  • Wrong number of keys found in the constant table
  • Wrong number of dead found in the constant table
  • Wrong number of total slots found
  • Wrong number of maximum keys found
  • Wrong number of total dead found
Reports the average length of non-empty lists. Returns the number of subtables for which the number of keys is wrong.] SideEffects [None] SeeAlso [Cudd_DebugCheck] ******************************************************************************/ int Cudd_CheckKeys( DdManager * table) { int size; int i,j; DdNodePtr *nodelist; DdNode *node; DdNode *sentinel = &(table->sentinel); DdSubtable *subtable; int keys; int dead; int count = 0; int totalKeys = 0; int totalSlots = 0; int totalDead = 0; int nonEmpty = 0; unsigned int slots; int logSlots; int shift; size = table->size; for (i = 0; i < size; i++) { subtable = &(table->subtables[i]); nodelist = subtable->nodelist; keys = subtable->keys; dead = subtable->dead; totalKeys += keys; slots = subtable->slots; shift = subtable->shift; logSlots = sizeof(int) * 8 - shift; if (((slots >> logSlots) << logSlots) != slots) { (void) fprintf(table->err, "Unique table %d is not the right power of 2\n", i); (void) fprintf(table->err, " slots = %u shift = %d\n", slots, shift); } totalSlots += slots; totalDead += dead; for (j = 0; (unsigned) j < slots; j++) { node = nodelist[j]; if (node != sentinel) { nonEmpty++; } while (node != sentinel) { keys--; if (node->ref == 0) { dead--; } node = node->next; } } if (keys != 0) { (void) fprintf(table->err, "Wrong number of keys found \ in unique table %d (difference=%d)\n", i, keys); count++; } if (dead != 0) { (void) fprintf(table->err, "Wrong number of dead found \ in unique table no. %d (difference=%d)\n", i, dead); } } /* for each BDD/ADD subtable */ /* Check the ZDD subtables. */ size = table->sizeZ; for (i = 0; i < size; i++) { subtable = &(table->subtableZ[i]); nodelist = subtable->nodelist; keys = subtable->keys; dead = subtable->dead; totalKeys += keys; totalSlots += subtable->slots; totalDead += dead; for (j = 0; (unsigned) j < subtable->slots; j++) { node = nodelist[j]; if (node != NULL) { nonEmpty++; } while (node != NULL) { keys--; if (node->ref == 0) { dead--; } node = node->next; } } if (keys != 0) { (void) fprintf(table->err, "Wrong number of keys found \ in ZDD unique table no. %d (difference=%d)\n", i, keys); count++; } if (dead != 0) { (void) fprintf(table->err, "Wrong number of dead found \ in ZDD unique table no. %d (difference=%d)\n", i, dead); } } /* for each ZDD subtable */ /* Check the constant table. */ subtable = &(table->constants); nodelist = subtable->nodelist; keys = subtable->keys; dead = subtable->dead; totalKeys += keys; totalSlots += subtable->slots; totalDead += dead; for (j = 0; (unsigned) j < subtable->slots; j++) { node = nodelist[j]; if (node != NULL) { nonEmpty++; } while (node != NULL) { keys--; if (node->ref == 0) { dead--; } node = node->next; } } if (keys != 0) { (void) fprintf(table->err, "Wrong number of keys found \ in the constant table (difference=%d)\n", keys); count++; } if (dead != 0) { (void) fprintf(table->err, "Wrong number of dead found \ in the constant table (difference=%d)\n", dead); } if ((unsigned) totalKeys != table->keys + table->keysZ) { (void) fprintf(table->err, "Wrong number of total keys found \ (difference=%d)\n", (int) (totalKeys-table->keys)); } if ((unsigned) totalSlots != table->slots) { (void) fprintf(table->err, "Wrong number of total slots found \ (difference=%d)\n", (int) (totalSlots-table->slots)); } if (table->minDead != (unsigned) (table->gcFrac * table->slots)) { (void) fprintf(table->err, "Wrong number of minimum dead found \ (%u vs. %u)\n", table->minDead, (unsigned) (table->gcFrac * (double) table->slots)); } if ((unsigned) totalDead != table->dead + table->deadZ) { (void) fprintf(table->err, "Wrong number of total dead found \ (difference=%d)\n", (int) (totalDead-table->dead)); } (void)printf("Average length of non-empty lists = %g\n", (double) table->keys / (double) nonEmpty); return(count); } /* end of Cudd_CheckKeys */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints information about the heap.] Description [Prints to the manager's stdout the number of live nodes for each level of the DD heap that contains at least one live node. It also prints a summary containing:
  • total number of tables;
  • number of tables with live nodes;
  • table with the largest number of live nodes;
  • number of nodes in that table.
If more than one table contains the maximum number of live nodes, only the one of lowest index is reported. Returns 1 in case of success and 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddHeapProfile( DdManager * dd) { int ntables = dd->size; DdSubtable *subtables = dd->subtables; int i, /* loop index */ nodes, /* live nodes in i-th layer */ retval, /* return value of fprintf */ largest = -1, /* index of the table with most live nodes */ maxnodes = -1, /* maximum number of live nodes in a table */ nonempty = 0; /* number of tables with live nodes */ /* Print header. */ #if SIZEOF_VOID_P == 8 retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n", (ptruint) dd); #else retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n", (ptruint) dd); #endif if (retval == EOF) return 0; /* Print number of live nodes for each nonempty table. */ for (i=0; iout,"%5d: %5d nodes\n", i, nodes); if (retval == EOF) return 0; if (nodes > maxnodes) { maxnodes = nodes; largest = i; } } } nodes = dd->constants.keys - dd->constants.dead; if (nodes) { nonempty++; retval = fprintf(dd->out,"const: %5d nodes\n", nodes); if (retval == EOF) return 0; if (nodes > maxnodes) { maxnodes = nodes; largest = CUDD_CONST_INDEX; } } /* Print summary. */ retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ", ntables+1, nonempty, largest); if (retval == EOF) return 0; retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes); if (retval == EOF) return 0; return(1); } /* end of cuddHeapProfile */ /**Function******************************************************************** Synopsis [Prints out information on a node.] Description [Prints out information on a node.] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddPrintNode( DdNode * f, FILE *fp) { f = Cudd_Regular(f); #if SIZEOF_VOID_P == 8 (void) fprintf(fp," node 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); #else (void) fprintf(fp," node 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n",(ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); #endif } /* end of cuddPrintNode */ /**Function******************************************************************** Synopsis [Prints the variable groups as a parenthesized list.] Description [Prints the variable groups as a parenthesized list. For each group the level range that it represents is printed. After each group, the group's flags are printed, preceded by a `|'. For each flag (except MTR_TERMINAL) a character is printed.
  • F: MTR_FIXED
  • N: MTR_NEWNODE
  • S: MTR_SOFT
The second argument, silent, if different from 0, causes Cudd_PrintVarGroups to only check the syntax of the group tree.] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddPrintVarGroups( DdManager * dd /* manager */, MtrNode * root /* root of the group tree */, int zdd /* 0: BDD; 1: ZDD */, int silent /* flag to check tree syntax only */) { MtrNode *node; int level; assert(root != NULL); assert(root->younger == NULL || root->younger->elder == root); assert(root->elder == NULL || root->elder->younger == root); if (zdd) { level = dd->permZ[root->index]; } else { level = dd->perm[root->index]; } if (!silent) (void) printf("(%d",level); if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { if (!silent) (void) printf(","); } else { node = root->child; while (node != NULL) { assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); assert(node->parent == root); cuddPrintVarGroups(dd,node,zdd,silent); node = node->younger; } } if (!silent) { (void) printf("%d", (int) (level + root->size - 1)); if (root->flags != MTR_DEFAULT) { (void) printf("|"); if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); } (void) printf(")"); if (root->parent == NULL) (void) printf("\n"); } assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); return; } /* end of cuddPrintVarGroups */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Searches the subtables above node for its parents.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void debugFindParent( DdManager * table, DdNode * node) { int i,j; int slots; DdNodePtr *nodelist; DdNode *f; for (i = 0; i < cuddI(table,node->index); i++) { nodelist = table->subtables[i].nodelist; slots = table->subtables[i].slots; for (j=0;jout,"parent is at 0x%lx, id = %u, ref = %u, then = 0x%lx, else = 0x%lx\n", (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); #else (void) fprintf(table->out,"parent is at 0x%x, id = %hu, ref = %hu, then = 0x%x, else = 0x%x\n", (ptruint)f,f->index,f->ref,(ptruint)cuddT(f),(ptruint)cuddE(f)); #endif } f = f->next; } } } } /* end of debugFindParent */ #if 0 /**Function******************************************************************** Synopsis [Reports an error if a (dead) node has a non-dead parent.] Description [Searches all the subtables above node. Very expensive. The same check is now implemented more efficiently in ddDebugCheck.] SideEffects [None] SeeAlso [debugFindParent] ******************************************************************************/ static void debugCheckParent( DdManager * table, DdNode * node) { int i,j; int slots; DdNode **nodelist,*f; for (i = 0; i < cuddI(table,node->index); i++) { nodelist = table->subtables[i].nodelist; slots = table->subtables[i].slots; for (j=0;jref != 0) { (void) fprintf(table->err, "error with zero ref count\n"); (void) fprintf(table->err,"parent is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f)); (void) fprintf(table->err,"child is 0x%x, id = %u, ref = %u, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node)); } f = f->next; } } } } #endif ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddClip.c000066400000000000000000000426101300674244400234020ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddClip.c] PackageName [cudd] Synopsis [Clipping functions.] Description [External procedures included in this module:
  • Cudd_bddClippingAnd()
  • Cudd_bddClippingAndAbstract()
Internal procedures included in this module:
  • cuddBddClippingAnd()
  • cuddBddClippingAndAbstract()
Static procedures included in this module:
  • cuddBddClippingAndRecur()
  • cuddBddClipAndAbsRecur()
SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddClip.c,v 1.8 2004/08/13 18:04:47 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * cuddBddClippingAndRecur (DdManager *manager, DdNode *f, DdNode *g, int distance, int direction); static DdNode * cuddBddClipAndAbsRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, int distance, int direction); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Approximates the conjunction of two BDDs f and g.] Description [Approximates the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddAnd] ******************************************************************************/ DdNode * Cudd_bddClippingAnd( DdManager * dd /* manager */, DdNode * f /* first conjunct */, DdNode * g /* second conjunct */, int maxDepth /* maximum recursion depth */, int direction /* under (0) or over (1) approximation */) { DdNode *res; do { dd->reordered = 0; res = cuddBddClippingAnd(dd,f,g,maxDepth,direction); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddClippingAnd */ /**Function******************************************************************** Synopsis [Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube.] Description [Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddAndAbstract Cudd_bddClippingAnd] ******************************************************************************/ DdNode * Cudd_bddClippingAndAbstract( DdManager * dd /* manager */, DdNode * f /* first conjunct */, DdNode * g /* second conjunct */, DdNode * cube /* cube of variables to be abstracted */, int maxDepth /* maximum recursion depth */, int direction /* under (0) or over (1) approximation */) { DdNode *res; do { dd->reordered = 0; res = cuddBddClippingAndAbstract(dd,f,g,cube,maxDepth,direction); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddClippingAndAbstract */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Approximates the conjunction of two BDDs f and g.] Description [Approximates the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddClippingAnd] ******************************************************************************/ DdNode * cuddBddClippingAnd( DdManager * dd /* manager */, DdNode * f /* first conjunct */, DdNode * g /* second conjunct */, int maxDepth /* maximum recursion depth */, int direction /* under (0) or over (1) approximation */) { DdNode *res; res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction); return(res); } /* end of cuddBddClippingAnd */ /**Function******************************************************************** Synopsis [Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube.] Description [Approximates the conjunction of two BDDs f and g and simultaneously abstracts the variables in cube. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddClippingAndAbstract] ******************************************************************************/ DdNode * cuddBddClippingAndAbstract( DdManager * dd /* manager */, DdNode * f /* first conjunct */, DdNode * g /* second conjunct */, DdNode * cube /* cube of variables to be abstracted */, int maxDepth /* maximum recursion depth */, int direction /* under (0) or over (1) approximation */) { DdNode *res; res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction); return(res); } /* end of cuddBddClippingAndAbstract */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddClippingAnd.] Description [Implements the recursive step of Cudd_bddClippingAnd by taking the conjunction of two BDDs. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddBddClippingAnd] ******************************************************************************/ static DdNode * cuddBddClippingAndRecur( DdManager * manager, DdNode * f, DdNode * g, int distance, int direction) { DdNode *F, *ft, *fe, *G, *gt, *ge; DdNode *one, *zero, *r, *t, *e; unsigned int topf, topg, index; DD_CTFP cacheOp; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* Terminal cases. */ if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); if (f == g || g == one) return(f); if (f == one) return(g); if (distance == 0) { /* One last attempt at returning the right result. We sort of ** cheat by calling Cudd_bddLeq. */ if (Cudd_bddLeq(manager,f,g)) return(f); if (Cudd_bddLeq(manager,g,f)) return(g); if (direction == 1) { if (Cudd_bddLeq(manager,f,Cudd_Not(g)) || Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero); } return(Cudd_NotCond(one,(direction == 0))); } /* At this point f and g are not constant. */ distance--; /* Check cache. Try to increase cache efficiency by sorting the ** pointers. */ if (f > g) { DdNode *tmp = f; f = g; g = tmp; } F = Cudd_Regular(f); G = Cudd_Regular(g); cacheOp = (DD_CTFP) (direction ? Cudd_bddClippingAnd : cuddBddClippingAnd); if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup2(manager, cacheOp, f, g); if (r != NULL) return(r); } /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[F->index]; topg = manager->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = F->index; ft = cuddT(F); fe = cuddE(F); if (Cudd_IsComplement(f)) { ft = Cudd_Not(ft); fe = Cudd_Not(fe); } } else { index = G->index; ft = fe = f; } if (topg <= topf) { gt = cuddT(G); ge = cuddE(G); if (Cudd_IsComplement(g)) { gt = Cudd_Not(gt); ge = Cudd_Not(ge); } } else { gt = ge = g; } t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction); if (e == NULL) { Cudd_RecursiveDeref(manager, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_RecursiveDeref(manager, t); Cudd_RecursiveDeref(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_RecursiveDeref(manager, t); Cudd_RecursiveDeref(manager, e); return(NULL); } } } cuddDeref(e); cuddDeref(t); if (F->ref != 1 || G->ref != 1) cuddCacheInsert2(manager, cacheOp, f, g, r); return(r); } /* end of cuddBddClippingAndRecur */ /**Function******************************************************************** Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the variables in cube.] Description [Approximates the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddClippingAndAbstract] ******************************************************************************/ static DdNode * cuddBddClipAndAbsRecur( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int distance, int direction) { DdNode *F, *ft, *fe, *G, *gt, *ge; DdNode *one, *zero, *r, *t, *e, *Cube; unsigned int topf, topg, topcube, top, index; ptruint cacheTag; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* Terminal cases. */ if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); if (f == one && g == one) return(one); if (cube == one) { return(cuddBddClippingAndRecur(manager, f, g, distance, direction)); } if (f == one || f == g) { return (cuddBddExistAbstractRecur(manager, g, cube)); } if (g == one) { return (cuddBddExistAbstractRecur(manager, f, cube)); } if (distance == 0) return(Cudd_NotCond(one,(direction == 0))); /* At this point f, g, and cube are not constant. */ distance--; /* Check cache. */ if (f > g) { /* Try to increase cache efficiency. */ DdNode *tmp = f; f = g; g = tmp; } F = Cudd_Regular(f); G = Cudd_Regular(g); cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG : DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG; if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup(manager, cacheTag, f, g, cube); if (r != NULL) { return(r); } } /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[F->index]; topg = manager->perm[G->index]; top = ddMin(topf, topg); topcube = manager->perm[cube->index]; if (topcube < top) { return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube), distance, direction)); } /* Now, topcube >= top. */ if (topf == top) { index = F->index; ft = cuddT(F); fe = cuddE(F); if (Cudd_IsComplement(f)) { ft = Cudd_Not(ft); fe = Cudd_Not(fe); } } else { index = G->index; ft = fe = f; } if (topg == top) { gt = cuddT(G); ge = cuddE(G); if (Cudd_IsComplement(g)) { gt = Cudd_Not(gt); ge = Cudd_Not(ge); } } else { gt = ge = g; } if (topcube == top) { Cube = cuddT(cube); } else { Cube = cube; } t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction); if (t == NULL) return(NULL); /* Special case: 1 OR anything = 1. Hence, no need to compute ** the else branch if t is 1. */ if (t == one && topcube == top) { if (F->ref != 1 || G->ref != 1) cuddCacheInsert(manager, cacheTag, f, g, cube, one); return(one); } cuddRef(t); e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction); if (e == NULL) { Cudd_RecursiveDeref(manager, t); return(NULL); } cuddRef(e); if (topcube == top) { /* abstract */ r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e), distance, (direction == 0)); if (r == NULL) { Cudd_RecursiveDeref(manager, t); Cudd_RecursiveDeref(manager, e); return(NULL); } r = Cudd_Not(r); cuddRef(r); Cudd_RecursiveDeref(manager, t); Cudd_RecursiveDeref(manager, e); cuddDeref(r); } else if (t == e) { r = t; cuddDeref(t); cuddDeref(e); } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_RecursiveDeref(manager, t); Cudd_RecursiveDeref(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_RecursiveDeref(manager, t); Cudd_RecursiveDeref(manager, e); return(NULL); } } cuddDeref(e); cuddDeref(t); } if (F->ref != 1 || G->ref != 1) cuddCacheInsert(manager, cacheTag, f, g, cube, r); return (r); } /* end of cuddBddClipAndAbsRecur */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddCof.c000066400000000000000000000241221300674244400232200ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddCof.c] PackageName [cudd] Synopsis [Cofactoring functions.] Description [External procedures included in this module:
  • Cudd_Cofactor()
Internal procedures included in this module:
  • cuddGetBranches()
  • cuddCheckCube()
  • cuddCofactorRecur()
] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddCof.c,v 1.9 2004/08/13 18:04:47 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the cofactor of f with respect to g.] Description [Computes the cofactor of f with respect to g; g must be the BDD or the ADD of a cube. Returns a pointer to the cofactor if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddConstrain Cudd_bddRestrict] ******************************************************************************/ DdNode * Cudd_Cofactor( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res,*zero; zero = Cudd_Not(DD_ONE(dd)); if (g == zero || g == DD_ZERO(dd)) { (void) fprintf(dd->err,"Cudd_Cofactor: Invalid restriction 1\n"); dd->errorCode = CUDD_INVALID_ARG; return(NULL); } do { dd->reordered = 0; res = cuddCofactorRecur(dd,f,g); } while (dd->reordered == 1); return(res); } /* end of Cudd_Cofactor */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the children of g.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddGetBranches( DdNode * g, DdNode ** g1, DdNode ** g0) { DdNode *G = Cudd_Regular(g); *g1 = cuddT(G); *g0 = cuddE(G); if (Cudd_IsComplement(g)) { *g1 = Cudd_Not(*g1); *g0 = Cudd_Not(*g0); } } /* end of cuddGetBranches */ /**Function******************************************************************** Synopsis [Checks whether g is the BDD of a cube.] Description [Checks whether g is the BDD of a cube. Returns 1 in case of success; 0 otherwise. The constant 1 is a valid cube, but all other constant functions cause cuddCheckCube to return 0.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddCheckCube( DdManager * dd, DdNode * g) { DdNode *g1,*g0,*one,*zero; one = DD_ONE(dd); if (g == one) return(1); if (Cudd_IsConstant(g)) return(0); zero = Cudd_Not(one); cuddGetBranches(g,&g1,&g0); if (g0 == zero) { return(cuddCheckCube(dd, g1)); } if (g1 == zero) { return(cuddCheckCube(dd, g0)); } return(0); } /* end of cuddCheckCube */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_Cofactor.] Description [Performs the recursive step of Cudd_Cofactor. Returns a pointer to the cofactor if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_Cofactor] ******************************************************************************/ DdNode * cuddCofactorRecur( DdManager * dd, DdNode * f, DdNode * g) { DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r; unsigned int topf,topg; int comple; statLine(dd); F = Cudd_Regular(f); if (cuddIsConstant(F)) return(f); one = DD_ONE(dd); /* The invariant g != 0 is true on entry to this procedure and is ** recursively maintained by it. Therefore it suffices to test g ** against one to make sure it is not constant. */ if (g == one) return(f); /* From now on, f and g are known not to be constants. */ comple = f != F; r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g); if (r != NULL) { return(Cudd_NotCond(r,comple)); } topf = dd->perm[F->index]; G = Cudd_Regular(g); topg = dd->perm[G->index]; /* We take the cofactors of F because we are going to rely on ** the fact that the cofactors of the complement are the complements ** of the cofactors to better utilize the cache. Variable comple ** remembers whether we have to complement the result or not. */ if (topf <= topg) { f1 = cuddT(F); f0 = cuddE(F); } else { f1 = f0 = F; } if (topg <= topf) { g1 = cuddT(G); g0 = cuddE(G); if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); } } else { g1 = g0 = g; } zero = Cudd_Not(one); if (topf >= topg) { if (g0 == zero || g0 == DD_ZERO(dd)) { r = cuddCofactorRecur(dd, f1, g1); } else if (g1 == zero || g1 == DD_ZERO(dd)) { r = cuddCofactorRecur(dd, f0, g0); } else { (void) fprintf(dd->out, "Cudd_Cofactor: Invalid restriction 2\n"); dd->errorCode = CUDD_INVALID_ARG; return(NULL); } if (r == NULL) return(NULL); } else /* if (topf < topg) */ { t = cuddCofactorRecur(dd, f1, g); if (t == NULL) return(NULL); cuddRef(t); e = cuddCofactorRecur(dd, f0, g); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else if (Cudd_IsComplement(t)) { r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e)); if (r != NULL) r = Cudd_Not(r); } else { r = cuddUniqueInter(dd,(int)F->index,t,e); } if (r == NULL) { Cudd_RecursiveDeref(dd ,e); Cudd_RecursiveDeref(dd ,t); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r); return(Cudd_NotCond(r,comple)); } /* end of cuddCofactorRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddCompose.c000066400000000000000000001506261300674244400241270ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddCompose.c] PackageName [cudd] Synopsis [Functional composition and variable permutation of DDs.] Description [External procedures included in this module:
  • Cudd_bddCompose()
  • Cudd_addCompose()
  • Cudd_addPermute()
  • Cudd_addSwapVariables()
  • Cudd_bddPermute()
  • Cudd_bddVarMap()
  • Cudd_SetVarMap()
  • Cudd_bddSwapVariables()
  • Cudd_bddAdjPermuteX()
  • Cudd_addVectorCompose()
  • Cudd_addGeneralVectorCompose()
  • Cudd_addNonSimCompose()
  • Cudd_bddVectorCompose()
Internal procedures included in this module:
  • cuddBddComposeRecur()
  • cuddAddComposeRecur()
Static procedures included in this module:
  • cuddAddPermuteRecur()
  • cuddBddPermuteRecur()
  • cuddBddVarMapRecur()
  • cuddAddVectorComposeRecur()
  • cuddAddGeneralVectorComposeRecur()
  • cuddAddNonSimComposeRecur()
  • cuddBddVectorComposeRecur()
  • ddIsIthAddVar()
  • ddIsIthAddVarPair()
The permutation functions use a local cache because the results to be remembered depend on the permutation being applied. Since the permutation is just an array, it cannot be stored in the global cache. There are different procedured for BDDs and ADDs. This is because bddPermuteRecur uses cuddBddIteRecur. If this were changed, the procedures could be merged.] Author [Fabio Somenzi and Kavita Ravi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddCompose.c,v 1.45 2004/08/13 18:04:47 fabio Exp $"; #endif #ifdef DD_DEBUG static int addPermuteRecurHits; static int bddPermuteRecurHits; static int bddVectorComposeHits; static int addVectorComposeHits; static int addGeneralVectorComposeHits; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * cuddAddPermuteRecur (DdManager *manager, DdHashTable *table, DdNode *node, int *permut); static DdNode * cuddBddPermuteRecur (DdManager *manager, DdHashTable *table, DdNode *node, int *permut); static DdNode * cuddBddVarMapRecur (DdManager *manager, DdNode *f); static DdNode * cuddAddVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest); static DdNode * cuddAddNonSimComposeRecur (DdManager *dd, DdNode *f, DdNode **vector, DdNode *key, DdNode *cube, int lastsub); static DdNode * cuddBddVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest); DD_INLINE static int ddIsIthAddVar (DdManager *dd, DdNode *f, unsigned int i); static DdNode * cuddAddGeneralVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vectorOn, DdNode **vectorOff, int deepest); DD_INLINE static int ddIsIthAddVarPair (DdManager *dd, DdNode *f, DdNode *g, unsigned int i); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Substitutes g for x_v in the BDD for f.] Description [Substitutes g for x_v in the BDD for f. v is the index of the variable to be substituted. Cudd_bddCompose passes the corresponding projection function to the recursive procedure, so that the cache may be used. Returns the composed BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addCompose] ******************************************************************************/ DdNode * Cudd_bddCompose( DdManager * dd, DdNode * f, DdNode * g, int v) { DdNode *proj, *res; /* Sanity check. */ if (v < 0 || v >= dd->size) return(NULL); proj = dd->vars[v]; do { dd->reordered = 0; res = cuddBddComposeRecur(dd,f,g,proj); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddCompose */ /**Function******************************************************************** Synopsis [Substitutes g for x_v in the ADD for f.] Description [Substitutes g for x_v in the ADD for f. v is the index of the variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes the corresponding projection function to the recursive procedure, so that the cache may be used. Returns the composed ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddCompose] ******************************************************************************/ DdNode * Cudd_addCompose( DdManager * dd, DdNode * f, DdNode * g, int v) { DdNode *proj, *res; /* Sanity check. */ if (v < 0 || v >= dd->size) return(NULL); proj = dd->vars[v]; do { dd->reordered = 0; res = cuddAddComposeRecur(dd,f,g,proj); } while (dd->reordered == 1); return(res); } /* end of Cudd_addCompose */ /**Function******************************************************************** Synopsis [Permutes the variables of an ADD.] Description [Given a permutation in array permut, creates a new ADD with permuted variables. There should be an entry in array permut for each variable in the manager. The i-th entry of permut holds the index of the variable that is to substitute the i-th variable. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] ******************************************************************************/ DdNode * Cudd_addPermute( DdManager * manager, DdNode * node, int * permut) { DdHashTable *table; DdNode *res; do { manager->reordered = 0; table = cuddHashTableInit(manager,1,2); if (table == NULL) return(NULL); /* Recursively solve the problem. */ res = cuddAddPermuteRecur(manager,table,node,permut); if (res != NULL) cuddRef(res); /* Dispose of local cache. */ cuddHashTableQuit(table); } while (manager->reordered == 1); if (res != NULL) cuddDeref(res); return(res); } /* end of Cudd_addPermute */ /**Function******************************************************************** Synopsis [Swaps two sets of variables of the same size (x and y) in the ADD f.] Description [Swaps two sets of variables of the same size (x and y) in the ADD f. The size is given by n. The two sets of variables are assumed to be disjoint. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] ******************************************************************************/ DdNode * Cudd_addSwapVariables( DdManager * dd, DdNode * f, DdNode ** x, DdNode ** y, int n) { DdNode *swapped; int i, j, k; int *permut; permut = ABC_ALLOC(int,dd->size); if (permut == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < dd->size; i++) permut[i] = i; for (i = 0; i < n; i++) { j = x[i]->index; k = y[i]->index; permut[j] = k; permut[k] = j; } swapped = Cudd_addPermute(dd,f,permut); ABC_FREE(permut); return(swapped); } /* end of Cudd_addSwapVariables */ /**Function******************************************************************** Synopsis [Permutes the variables of a BDD.] Description [Given a permutation in array permut, creates a new BDD with permuted variables. There should be an entry in array permut for each variable in the manager. The i-th entry of permut holds the index of the variable that is to substitute the i-th variable. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] ******************************************************************************/ DdNode * Cudd_bddPermute( DdManager * manager, DdNode * node, int * permut) { DdHashTable *table; DdNode *res; do { manager->reordered = 0; table = cuddHashTableInit(manager,1,2); if (table == NULL) return(NULL); res = cuddBddPermuteRecur(manager,table,node,permut); if (res != NULL) cuddRef(res); /* Dispose of local cache. */ cuddHashTableQuit(table); } while (manager->reordered == 1); if (res != NULL) cuddDeref(res); return(res); } /* end of Cudd_bddPermute */ /**Function******************************************************************** Synopsis [Remaps the variables of a BDD using the default variable map.] Description [Remaps the variables of a BDD using the default variable map. A typical use of this function is to swap two sets of variables. The variable map must be registered with Cudd_SetVarMap. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables Cudd_SetVarMap] ******************************************************************************/ DdNode * Cudd_bddVarMap( DdManager * manager /* DD manager */, DdNode * f /* function in which to remap variables */) { DdNode *res; if (manager->map == NULL) return(NULL); do { manager->reordered = 0; res = cuddBddVarMapRecur(manager, f); } while (manager->reordered == 1); return(res); } /* end of Cudd_bddVarMap */ /**Function******************************************************************** Synopsis [Registers a variable mapping with the manager.] Description [Registers with the manager a variable mapping described by two sets of variables. This variable mapping is then used by functions like Cudd_bddVarMap. This function is convenient for those applications that perform the same mapping several times. However, if several different permutations are used, it may be more efficient not to rely on the registered mapping, because changing mapping causes the cache to be cleared. (The initial setting, however, does not clear the cache.) The two sets of variables (x and y) must have the same size (x and y). The size is given by n. The two sets of variables are normally disjoint, but this restriction is not imposeded by the function. When new variables are created, the map is automatically extended (each new variable maps to itself). The typical use, however, is to wait until all variables are created, and then create the map. Returns 1 if the mapping is successfully registered with the manager; 0 otherwise.] SideEffects [Modifies the manager. May clear the cache.] SeeAlso [Cudd_bddVarMap Cudd_bddPermute Cudd_bddSwapVariables] ******************************************************************************/ int Cudd_SetVarMap ( DdManager *manager /* DD manager */, DdNode **x /* first array of variables */, DdNode **y /* second array of variables */, int n /* length of both arrays */) { int i; if (manager->map != NULL) { cuddCacheFlush(manager); } else { manager->map = ABC_ALLOC(int,manager->maxSize); if (manager->map == NULL) { manager->errorCode = CUDD_MEMORY_OUT; return(0); } manager->memused += sizeof(int) * manager->maxSize; } /* Initialize the map to the identity. */ for (i = 0; i < manager->size; i++) { manager->map[i] = i; } /* Create the map. */ for (i = 0; i < n; i++) { manager->map[x[i]->index] = y[i]->index; manager->map[y[i]->index] = x[i]->index; } return(1); } /* end of Cudd_SetVarMap */ /**Function******************************************************************** Synopsis [Swaps two sets of variables of the same size (x and y) in the BDD f.] Description [Swaps two sets of variables of the same size (x and y) in the BDD f. The size is given by n. The two sets of variables are assumed to be disjoint. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] ******************************************************************************/ DdNode * Cudd_bddSwapVariables( DdManager * dd, DdNode * f, DdNode ** x, DdNode ** y, int n) { DdNode *swapped; int i, j, k; int *permut; permut = ABC_ALLOC(int,dd->size); if (permut == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < dd->size; i++) permut[i] = i; for (i = 0; i < n; i++) { j = x[i]->index; k = y[i]->index; permut[j] = k; permut[k] = j; } swapped = Cudd_bddPermute(dd,f,permut); ABC_FREE(permut); return(swapped); } /* end of Cudd_bddSwapVariables */ /**Function******************************************************************** Synopsis [Rearranges a set of variables in the BDD B.] Description [Rearranges a set of variables in the BDD B. The size of the set is given by n. This procedure is intended for the `randomization' of the priority functions. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_PrioritySelect] ******************************************************************************/ DdNode * Cudd_bddAdjPermuteX( DdManager * dd, DdNode * B, DdNode ** x, int n) { DdNode *swapped; int i, j, k; int *permut; permut = ABC_ALLOC(int,dd->size); if (permut == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < dd->size; i++) permut[i] = i; for (i = 0; i < n-2; i += 3) { j = x[i]->index; k = x[i+1]->index; permut[j] = k; permut[k] = j; } swapped = Cudd_bddPermute(dd,B,permut); ABC_FREE(permut); return(swapped); } /* end of Cudd_bddAdjPermuteX */ /**Function******************************************************************** Synopsis [Composes an ADD with a vector of 0-1 ADDs.] Description [Given a vector of 0-1 ADDs, creates a new ADD by substituting the 0-1 ADDs for the variables of the ADD f. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addNonSimCompose Cudd_addPermute Cudd_addCompose Cudd_bddVectorCompose] ******************************************************************************/ DdNode * Cudd_addVectorCompose( DdManager * dd, DdNode * f, DdNode ** vector) { DdHashTable *table; DdNode *res; int deepest; int i; do { dd->reordered = 0; /* Initialize local cache. */ table = cuddHashTableInit(dd,1,2); if (table == NULL) return(NULL); /* Find deepest real substitution. */ for (deepest = dd->size - 1; deepest >= 0; deepest--) { i = dd->invperm[deepest]; if (!ddIsIthAddVar(dd,vector[i],i)) { break; } } /* Recursively solve the problem. */ res = cuddAddVectorComposeRecur(dd,table,f,vector,deepest); if (res != NULL) cuddRef(res); /* Dispose of local cache. */ cuddHashTableQuit(table); } while (dd->reordered == 1); if (res != NULL) cuddDeref(res); return(res); } /* end of Cudd_addVectorCompose */ /**Function******************************************************************** Synopsis [Composes an ADD with a vector of ADDs.] Description [Given a vector of ADDs, creates a new ADD by substituting the ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted for the x_v and vectorOff the ADDs to be substituted for x_v'. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addVectorCompose Cudd_addNonSimCompose Cudd_addPermute Cudd_addCompose Cudd_bddVectorCompose] ******************************************************************************/ DdNode * Cudd_addGeneralVectorCompose( DdManager * dd, DdNode * f, DdNode ** vectorOn, DdNode ** vectorOff) { DdHashTable *table; DdNode *res; int deepest; int i; do { dd->reordered = 0; /* Initialize local cache. */ table = cuddHashTableInit(dd,1,2); if (table == NULL) return(NULL); /* Find deepest real substitution. */ for (deepest = dd->size - 1; deepest >= 0; deepest--) { i = dd->invperm[deepest]; if (!ddIsIthAddVarPair(dd,vectorOn[i],vectorOff[i],i)) { break; } } /* Recursively solve the problem. */ res = cuddAddGeneralVectorComposeRecur(dd,table,f,vectorOn, vectorOff,deepest); if (res != NULL) cuddRef(res); /* Dispose of local cache. */ cuddHashTableQuit(table); } while (dd->reordered == 1); if (res != NULL) cuddDeref(res); return(res); } /* end of Cudd_addGeneralVectorCompose */ /**Function******************************************************************** Synopsis [Composes an ADD with a vector of 0-1 ADDs.] Description [Given a vector of 0-1 ADDs, creates a new ADD by substituting the 0-1 ADDs for the variables of the ADD f. There should be an entry in vector for each variable in the manager. This function implements non-simultaneous composition. If any of the functions being composed depends on any of the variables being substituted, then the result depends on the order of composition, which in turn depends on the variable order: The variables farther from the roots in the order are substituted first. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addVectorCompose Cudd_addPermute Cudd_addCompose] ******************************************************************************/ DdNode * Cudd_addNonSimCompose( DdManager * dd, DdNode * f, DdNode ** vector) { DdNode *cube, *key, *var, *tmp, *piece; DdNode *res; int i, lastsub; /* The cache entry for this function is composed of three parts: ** f itself, the replacement relation, and the cube of the ** variables being substituted. ** The replacement relation is the product of the terms (yi EXNOR gi). ** This apporach allows us to use the global cache for this function, ** with great savings in memory with respect to using arrays for the ** cache entries. ** First we build replacement relation and cube of substituted ** variables from the vector specifying the desired composition. */ key = DD_ONE(dd); cuddRef(key); cube = DD_ONE(dd); cuddRef(cube); for (i = (int) dd->size - 1; i >= 0; i--) { if (ddIsIthAddVar(dd,vector[i],(unsigned int)i)) { continue; } var = Cudd_addIthVar(dd,i); if (var == NULL) { Cudd_RecursiveDeref(dd,key); Cudd_RecursiveDeref(dd,cube); return(NULL); } cuddRef(var); /* Update cube. */ tmp = Cudd_addApply(dd,Cudd_addTimes,var,cube); if (tmp == NULL) { Cudd_RecursiveDeref(dd,key); Cudd_RecursiveDeref(dd,cube); Cudd_RecursiveDeref(dd,var); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(dd,cube); cube = tmp; /* Update replacement relation. */ piece = Cudd_addApply(dd,Cudd_addXnor,var,vector[i]); if (piece == NULL) { Cudd_RecursiveDeref(dd,key); Cudd_RecursiveDeref(dd,var); return(NULL); } cuddRef(piece); Cudd_RecursiveDeref(dd,var); tmp = Cudd_addApply(dd,Cudd_addTimes,key,piece); if (tmp == NULL) { Cudd_RecursiveDeref(dd,key); Cudd_RecursiveDeref(dd,piece); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(dd,key); Cudd_RecursiveDeref(dd,piece); key = tmp; } /* Now try composition, until no reordering occurs. */ do { /* Find real substitution with largest index. */ for (lastsub = dd->size - 1; lastsub >= 0; lastsub--) { if (!ddIsIthAddVar(dd,vector[lastsub],(unsigned int)lastsub)) { break; } } /* Recursively solve the problem. */ dd->reordered = 0; res = cuddAddNonSimComposeRecur(dd,f,vector,key,cube,lastsub+1); if (res != NULL) cuddRef(res); } while (dd->reordered == 1); Cudd_RecursiveDeref(dd,key); Cudd_RecursiveDeref(dd,cube); if (res != NULL) cuddDeref(res); return(res); } /* end of Cudd_addNonSimCompose */ /**Function******************************************************************** Synopsis [Composes a BDD with a vector of BDDs.] Description [Given a vector of BDDs, creates a new BDD by substituting the BDDs for the variables of the BDD f. There should be an entry in vector for each variable in the manager. If no substitution is sought for a given variable, the corresponding projection function should be specified in the vector. This function implements simultaneous composition. Returns a pointer to the resulting BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddPermute Cudd_bddCompose Cudd_addVectorCompose] ******************************************************************************/ DdNode * Cudd_bddVectorCompose( DdManager * dd, DdNode * f, DdNode ** vector) { DdHashTable *table; DdNode *res; int deepest; int i; do { dd->reordered = 0; /* Initialize local cache. */ table = cuddHashTableInit(dd,1,2); if (table == NULL) return(NULL); /* Find deepest real substitution. */ for (deepest = dd->size - 1; deepest >= 0; deepest--) { i = dd->invperm[deepest]; if (vector[i] != dd->vars[i]) { break; } } /* Recursively solve the problem. */ res = cuddBddVectorComposeRecur(dd,table,f,vector, deepest); if (res != NULL) cuddRef(res); /* Dispose of local cache. */ cuddHashTableQuit(table); } while (dd->reordered == 1); if (res != NULL) cuddDeref(res); return(res); } /* end of Cudd_bddVectorCompose */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddCompose.] Description [Performs the recursive step of Cudd_bddCompose. Exploits the fact that the composition of f' with g produces the complement of the composition of f with g to better utilize the cache. Returns the composed BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddCompose] ******************************************************************************/ DdNode * cuddBddComposeRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * proj) { DdNode *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e; unsigned int v, topf, topg, topindex; int comple; statLine(dd); v = dd->perm[proj->index]; F = Cudd_Regular(f); topf = cuddI(dd,F->index); /* Terminal case. Subsumes the test for constant f. */ if (topf > v) return(f); /* We solve the problem for a regular pointer, and then complement ** the result if the pointer was originally complemented. */ comple = Cudd_IsComplement(f); /* Check cache. */ r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj); if (r != NULL) { return(Cudd_NotCond(r,comple)); } if (topf == v) { /* Compose. */ f1 = cuddT(F); f0 = cuddE(F); r = cuddBddIteRecur(dd, g, f1, f0); if (r == NULL) return(NULL); } else { /* Compute cofactors of f and g. Remember the index of the top ** variable. */ G = Cudd_Regular(g); topg = cuddI(dd,G->index); if (topf > topg) { topindex = G->index; f1 = f0 = F; } else { topindex = F->index; f1 = cuddT(F); f0 = cuddE(F); } if (topg > topf) { g1 = g0 = g; } else { g1 = cuddT(G); g0 = cuddE(G); if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); } } /* Recursive step. */ t = cuddBddComposeRecur(dd, f1, g1, proj); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddComposeRecur(dd, f0, g0, proj); if (e == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } cuddRef(e); r = cuddBddIteRecur(dd, dd->vars[topindex], t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, t); Cudd_IterDerefBdd(dd, e); return(NULL); } cuddRef(r); Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */ Cudd_IterDerefBdd(dd, e); cuddDeref(r); } cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r); return(Cudd_NotCond(r,comple)); } /* end of cuddBddComposeRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addCompose.] Description [Performs the recursive step of Cudd_addCompose. Returns the composed BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addCompose] ******************************************************************************/ DdNode * cuddAddComposeRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * proj) { DdNode *f1, *f0, *g1, *g0, *r, *t, *e; unsigned int v, topf, topg, topindex; statLine(dd); v = dd->perm[proj->index]; topf = cuddI(dd,f->index); /* Terminal case. Subsumes the test for constant f. */ if (topf > v) return(f); /* Check cache. */ r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj); if (r != NULL) { return(r); } if (topf == v) { /* Compose. */ f1 = cuddT(f); f0 = cuddE(f); r = cuddAddIteRecur(dd, g, f1, f0); if (r == NULL) return(NULL); } else { /* Compute cofactors of f and g. Remember the index of the top ** variable. */ topg = cuddI(dd,g->index); if (topf > topg) { topindex = g->index; f1 = f0 = f; } else { topindex = f->index; f1 = cuddT(f); f0 = cuddE(f); } if (topg > topf) { g1 = g0 = g; } else { g1 = cuddT(g); g0 = cuddE(g); } /* Recursive step. */ t = cuddAddComposeRecur(dd, f1, g1, proj); if (t == NULL) return(NULL); cuddRef(t); e = cuddAddComposeRecur(dd, f0, g0, proj); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { r = cuddUniqueInter(dd, (int) topindex, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } } cuddDeref(t); cuddDeref(e); } cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r); return(r); } /* end of cuddAddComposeRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_addPermute.] Description [ Recursively puts the ADD in the order given in the array permut. Checks for trivial cases to terminate recursion, then splits on the children of this node. Once the solutions for the children are obtained, it puts into the current position the node from the rest of the ADD that should be here. Then returns this ADD. The key here is that the node being visited is NOT put in its proper place by this instance, but rather is switched when its proper position is reached in the recursion tree.

The DdNode * that is returned is the same ADD as passed in as node, but in the new order.] SideEffects [None] SeeAlso [Cudd_addPermute cuddBddPermuteRecur] ******************************************************************************/ static DdNode * cuddAddPermuteRecur( DdManager * manager /* DD manager */, DdHashTable * table /* computed table */, DdNode * node /* ADD to be reordered */, int * permut /* permutation array */) { DdNode *T,*E; DdNode *res,*var; int index; statLine(manager); /* Check for terminal case of constant node. */ if (cuddIsConstant(node)) { return(node); } /* If problem already solved, look up answer and return. */ if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { #ifdef DD_DEBUG addPermuteRecurHits++; #endif return(res); } /* Split and recur on children of this node. */ T = cuddAddPermuteRecur(manager,table,cuddT(node),permut); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddPermuteRecur(manager,table,cuddE(node),permut); if (E == NULL) { Cudd_RecursiveDeref(manager, T); return(NULL); } cuddRef(E); /* Move variable that should be in this position to this position ** by creating a single var ADD for that variable, and calling ** cuddAddIteRecur with the T and E we just created. */ index = permut[node->index]; var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager)); if (var == NULL) return(NULL); cuddRef(var); res = cuddAddIteRecur(manager,var,T,E); if (res == NULL) { Cudd_RecursiveDeref(manager,var); Cudd_RecursiveDeref(manager, T); Cudd_RecursiveDeref(manager, E); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,var); Cudd_RecursiveDeref(manager, T); Cudd_RecursiveDeref(manager, E); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again. */ if (node->ref != 1) { ptrint fanout = (ptrint) node->ref; cuddSatDec(fanout); if (!cuddHashTableInsert1(table,node,res,fanout)) { Cudd_RecursiveDeref(manager, res); return(NULL); } } cuddDeref(res); return(res); } /* end of cuddAddPermuteRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddPermute.] Description [ Recursively puts the BDD in the order given in the array permut. Checks for trivial cases to terminate recursion, then splits on the children of this node. Once the solutions for the children are obtained, it puts into the current position the node from the rest of the BDD that should be here. Then returns this BDD. The key here is that the node being visited is NOT put in its proper place by this instance, but rather is switched when its proper position is reached in the recursion tree.

The DdNode * that is returned is the same BDD as passed in as node, but in the new order.] SideEffects [None] SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] ******************************************************************************/ static DdNode * cuddBddPermuteRecur( DdManager * manager /* DD manager */, DdHashTable * table /* computed table */, DdNode * node /* BDD to be reordered */, int * permut /* permutation array */) { DdNode *N,*T,*E; DdNode *res; int index; statLine(manager); N = Cudd_Regular(node); /* Check for terminal case of constant node. */ if (cuddIsConstant(N)) { return(node); } /* If problem already solved, look up answer and return. */ if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) { #ifdef DD_DEBUG bddPermuteRecurHits++; #endif return(Cudd_NotCond(res,N != node)); } /* Split and recur on children of this node. */ T = cuddBddPermuteRecur(manager,table,cuddT(N),permut); if (T == NULL) return(NULL); cuddRef(T); E = cuddBddPermuteRecur(manager,table,cuddE(N),permut); if (E == NULL) { Cudd_IterDerefBdd(manager, T); return(NULL); } cuddRef(E); /* Move variable that should be in this position to this position ** by retrieving the single var BDD for that variable, and calling ** cuddBddIteRecur with the T and E we just created. */ index = permut[N->index]; res = cuddBddIteRecur(manager,manager->vars[index],T,E); if (res == NULL) { Cudd_IterDerefBdd(manager, T); Cudd_IterDerefBdd(manager, E); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(manager, T); Cudd_IterDerefBdd(manager, E); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again. */ if (N->ref != 1) { ptrint fanout = (ptrint) N->ref; cuddSatDec(fanout); if (!cuddHashTableInsert1(table,N,res,fanout)) { Cudd_IterDerefBdd(manager, res); return(NULL); } } cuddDeref(res); return(Cudd_NotCond(res,N != node)); } /* end of cuddBddPermuteRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddVarMap.] Description [Implements the recursive step of Cudd_bddVarMap. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddVarMap] ******************************************************************************/ static DdNode * cuddBddVarMapRecur( DdManager *manager /* DD manager */, DdNode *f /* BDD to be remapped */) { DdNode *F, *T, *E; DdNode *res; int index; statLine(manager); F = Cudd_Regular(f); /* Check for terminal case of constant node. */ if (cuddIsConstant(F)) { return(f); } /* If problem already solved, look up answer and return. */ if (F->ref != 1 && (res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) { return(Cudd_NotCond(res,F != f)); } if ( manager->TimeStop && Abc_Clock() > manager->TimeStop ) return NULL; /* Split and recur on children of this node. */ T = cuddBddVarMapRecur(manager,cuddT(F)); if (T == NULL) return(NULL); cuddRef(T); E = cuddBddVarMapRecur(manager,cuddE(F)); if (E == NULL) { Cudd_IterDerefBdd(manager, T); return(NULL); } cuddRef(E); /* Move variable that should be in this position to this position ** by retrieving the single var BDD for that variable, and calling ** cuddBddIteRecur with the T and E we just created. */ index = manager->map[F->index]; res = cuddBddIteRecur(manager,manager->vars[index],T,E); if (res == NULL) { Cudd_IterDerefBdd(manager, T); Cudd_IterDerefBdd(manager, E); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(manager, T); Cudd_IterDerefBdd(manager, E); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again. */ if (F->ref != 1) { cuddCacheInsert1(manager,Cudd_bddVarMap,F,res); } cuddDeref(res); return(Cudd_NotCond(res,F != f)); } /* end of cuddBddVarMapRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addVectorCompose.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddAddVectorComposeRecur( DdManager * dd /* DD manager */, DdHashTable * table /* computed table */, DdNode * f /* ADD in which to compose */, DdNode ** vector /* functions to substitute */, int deepest /* depth of deepest substitution */) { DdNode *T,*E; DdNode *res; statLine(dd); /* If we are past the deepest substitution, return f. */ if (cuddI(dd,f->index) > deepest) { return(f); } if ((res = cuddHashTableLookup1(table,f)) != NULL) { #ifdef DD_DEBUG addVectorComposeHits++; #endif return(res); } /* Split and recur on children of this node. */ T = cuddAddVectorComposeRecur(dd,table,cuddT(f),vector,deepest); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddVectorComposeRecur(dd,table,cuddE(f),vector,deepest); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); /* Retrieve the 0-1 ADD for the current top variable and call ** cuddAddIteRecur with the T and E we just created. */ res = cuddAddIteRecur(dd,vector[f->index],T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again */ if (f->ref != 1) { ptrint fanout = (ptrint) f->ref; cuddSatDec(fanout); if (!cuddHashTableInsert1(table,f,res,fanout)) { Cudd_RecursiveDeref(dd, res); return(NULL); } } cuddDeref(res); return(res); } /* end of cuddAddVectorComposeRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addGeneralVectorCompose.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddAddGeneralVectorComposeRecur( DdManager * dd /* DD manager */, DdHashTable * table /* computed table */, DdNode * f /* ADD in which to compose */, DdNode ** vectorOn /* functions to substitute for x_i */, DdNode ** vectorOff /* functions to substitute for x_i' */, int deepest /* depth of deepest substitution */) { DdNode *T,*E,*t,*e; DdNode *res; /* If we are past the deepest substitution, return f. */ if (cuddI(dd,f->index) > deepest) { return(f); } if ((res = cuddHashTableLookup1(table,f)) != NULL) { #ifdef DD_DEBUG addGeneralVectorComposeHits++; #endif return(res); } /* Split and recur on children of this node. */ T = cuddAddGeneralVectorComposeRecur(dd,table,cuddT(f), vectorOn,vectorOff,deepest); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddGeneralVectorComposeRecur(dd,table,cuddE(f), vectorOn,vectorOff,deepest); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); /* Retrieve the compose ADDs for the current top variable and call ** cuddAddApplyRecur with the T and E we just created. */ t = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOn[f->index],T); if (t == NULL) { Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); return(NULL); } cuddRef(t); e = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOff[f->index],E); if (e == NULL) { Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); Cudd_RecursiveDeref(dd,t); return(NULL); } cuddRef(e); res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); Cudd_RecursiveDeref(dd,t); Cudd_RecursiveDeref(dd,e); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); Cudd_RecursiveDeref(dd,t); Cudd_RecursiveDeref(dd,e); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again */ if (f->ref != 1) { ptrint fanout = (ptrint) f->ref; cuddSatDec(fanout); if (!cuddHashTableInsert1(table,f,res,fanout)) { Cudd_RecursiveDeref(dd, res); return(NULL); } } cuddDeref(res); return(res); } /* end of cuddAddGeneralVectorComposeRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addNonSimCompose.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddAddNonSimComposeRecur( DdManager * dd, DdNode * f, DdNode ** vector, DdNode * key, DdNode * cube, int lastsub) { DdNode *f1, *f0, *key1, *key0, *cube1, *var; DdNode *T,*E; DdNode *r; unsigned int top, topf, topk, topc; unsigned int index; int i; DdNode **vect1; DdNode **vect0; statLine(dd); /* If we are past the deepest substitution, return f. */ if (cube == DD_ONE(dd) || cuddIsConstant(f)) { return(f); } /* If problem already solved, look up answer and return. */ r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube); if (r != NULL) { return(r); } /* Find top variable. we just need to look at f, key, and cube, ** because all the varibles in the gi are in key. */ topf = cuddI(dd,f->index); topk = cuddI(dd,key->index); top = ddMin(topf,topk); topc = cuddI(dd,cube->index); top = ddMin(top,topc); index = dd->invperm[top]; /* Compute the cofactors. */ if (topf == top) { f1 = cuddT(f); f0 = cuddE(f); } else { f1 = f0 = f; } if (topc == top) { cube1 = cuddT(cube); /* We want to eliminate vector[index] from key. Otherwise ** cache performance is severely affected. Hence we ** existentially quantify the variable with index "index" from key. */ var = Cudd_addIthVar(dd, (int) index); if (var == NULL) { return(NULL); } cuddRef(var); key1 = cuddAddExistAbstractRecur(dd, key, var); if (key1 == NULL) { Cudd_RecursiveDeref(dd,var); return(NULL); } cuddRef(key1); Cudd_RecursiveDeref(dd,var); key0 = key1; } else { cube1 = cube; if (topk == top) { key1 = cuddT(key); key0 = cuddE(key); } else { key1 = key0 = key; } cuddRef(key1); } /* Allocate two new vectors for the cofactors of vector. */ vect1 = ABC_ALLOC(DdNode *,lastsub); if (vect1 == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd,key1); return(NULL); } vect0 = ABC_ALLOC(DdNode *,lastsub); if (vect0 == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd,key1); ABC_FREE(vect1); return(NULL); } /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because ** we do not need them. */ for (i = 0; i < lastsub; i++) { DdNode *gi = vector[i]; if (gi == NULL) { vect1[i] = vect0[i] = NULL; } else if (gi->index == index) { vect1[i] = cuddT(gi); vect0[i] = cuddE(gi); } else { vect1[i] = vect0[i] = gi; } } vect1[index] = vect0[index] = NULL; /* Recur on children. */ T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub); ABC_FREE(vect1); if (T == NULL) { Cudd_RecursiveDeref(dd,key1); ABC_FREE(vect0); return(NULL); } cuddRef(T); E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub); ABC_FREE(vect0); if (E == NULL) { Cudd_RecursiveDeref(dd,key1); Cudd_RecursiveDeref(dd,T); return(NULL); } cuddRef(E); Cudd_RecursiveDeref(dd,key1); /* Retrieve the 0-1 ADD for the current top variable from vector, ** and call cuddAddIteRecur with the T and E we just created. */ r = cuddAddIteRecur(dd,vector[index],T,E); if (r == NULL) { Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); return(NULL); } cuddRef(r); Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); cuddDeref(r); /* Store answer to trim recursion. */ cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r); return(r); } /* end of cuddAddNonSimComposeRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddVectorCompose.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddBddVectorComposeRecur( DdManager * dd /* DD manager */, DdHashTable * table /* computed table */, DdNode * f /* BDD in which to compose */, DdNode ** vector /* functions to be composed */, int deepest /* depth of the deepest substitution */) { DdNode *F,*T,*E; DdNode *res; statLine(dd); F = Cudd_Regular(f); /* If we are past the deepest substitution, return f. */ if (cuddI(dd,F->index) > deepest) { return(f); } /* If problem already solved, look up answer and return. */ if ((res = cuddHashTableLookup1(table,F)) != NULL) { #ifdef DD_DEBUG bddVectorComposeHits++; #endif return(Cudd_NotCond(res,F != f)); } /* Split and recur on children of this node. */ T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest); if (T == NULL) return(NULL); cuddRef(T); E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest); if (E == NULL) { Cudd_IterDerefBdd(dd, T); return(NULL); } cuddRef(E); /* Call cuddBddIteRecur with the BDD that replaces the current top ** variable and the T and E we just created. */ res = cuddBddIteRecur(dd,vector[F->index],T,E); if (res == NULL) { Cudd_IterDerefBdd(dd, T); Cudd_IterDerefBdd(dd, E); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(dd, T); Cudd_IterDerefBdd(dd, E); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again. */ if (F->ref != 1) { ptrint fanout = (ptrint) F->ref; cuddSatDec(fanout); if (!cuddHashTableInsert1(table,F,res,fanout)) { Cudd_IterDerefBdd(dd, res); return(NULL); } } cuddDeref(res); return(Cudd_NotCond(res,F != f)); } /* end of cuddBddVectorComposeRecur */ /**Function******************************************************************** Synopsis [Comparison of a function to the i-th ADD variable.] Description [Comparison of a function to the i-th ADD variable. Returns 1 if the function is the i-th ADD variable; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DD_INLINE static int ddIsIthAddVar( DdManager * dd, DdNode * f, unsigned int i) { return(f->index == i && cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd)); } /* end of ddIsIthAddVar */ /**Function******************************************************************** Synopsis [Comparison of a pair of functions to the i-th ADD variable.] Description [Comparison of a pair of functions to the i-th ADD variable. Returns 1 if the functions are the i-th ADD variable and its complement; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DD_INLINE static int ddIsIthAddVarPair( DdManager * dd, DdNode * f, DdNode * g, unsigned int i) { return(f->index == i && g->index == i && cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd) && cuddT(g) == DD_ZERO(dd) && cuddE(g) == DD_ONE(dd)); } /* end of ddIsIthAddVarPair */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddDecomp.c000066400000000000000000002154421300674244400237270ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddDecomp.c] PackageName [cudd] Synopsis [Functions for BDD decomposition.] Description [External procedures included in this file:

  • Cudd_bddApproxConjDecomp()
  • Cudd_bddApproxDisjDecomp()
  • Cudd_bddIterConjDecomp()
  • Cudd_bddIterDisjDecomp()
  • Cudd_bddGenConjDecomp()
  • Cudd_bddGenDisjDecomp()
  • Cudd_bddVarConjDecomp()
  • Cudd_bddVarDisjDecomp()
Static procedures included in this module:
  • cuddConjunctsAux()
  • CreateBotDist()
  • BuildConjuncts()
  • ConjunctsFree()
] Author [Kavita Ravi, Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DEPTH 5 #define THRESHOLD 10 #define NONE 0 #define PAIR_ST 1 #define PAIR_CR 2 #define G_ST 3 #define G_CR 4 #define H_ST 5 #define H_CR 6 #define BOTH_G 7 #define BOTH_H 8 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ typedef struct Conjuncts { DdNode *g; DdNode *h; } Conjuncts; typedef struct NodeStat { int distance; int localRef; } NodeStat; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddDecomp.c,v 1.44 2004/08/13 18:04:47 fabio Exp $"; #endif static DdNode *one, *zero; long lastTimeG; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ #define FactorsNotStored(factors) ((int)((long)(factors) & 01)) #define FactorsComplement(factors) ((Conjuncts *)((long)(factors) | 01)) #define FactorsUncomplement(factors) ((Conjuncts *)((long)(factors) ^ 01)) /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static NodeStat * CreateBotDist (DdNode * node, st__table * distanceTable); static double CountMinterms (DdNode * node, double max, st__table * mintermTable, FILE *fp); static void ConjunctsFree (DdManager * dd, Conjuncts * factors); static int PairInTables (DdNode * g, DdNode * h, st__table * ghTable); static Conjuncts * CheckTablesCacheAndReturn (DdNode * node, DdNode * g, DdNode * h, st__table * ghTable, st__table * cacheTable); static Conjuncts * PickOnePair (DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st__table * ghTable, st__table * cacheTable); static Conjuncts * CheckInTables (DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st__table * ghTable, st__table * cacheTable, int * outOfMem); static Conjuncts * ZeroCase (DdManager * dd, DdNode * node, Conjuncts * factorsNv, st__table * ghTable, st__table * cacheTable, int switched); static Conjuncts * BuildConjuncts (DdManager * dd, DdNode * node, st__table * distanceTable, st__table * cacheTable, int approxDistance, int maxLocalRef, st__table * ghTable, st__table * mintermTable); static int cuddConjunctsAux (DdManager * dd, DdNode * f, DdNode ** c1, DdNode ** c2); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs two-way conjunctive decomposition of a BDD.] Description [Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the use of supersetting to obtain an initial factor of the given function. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be imbalanced.] SideEffects [The factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.] SeeAlso [Cudd_bddApproxDisjDecomp Cudd_bddIterConjDecomp Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox Cudd_bddSqueeze Cudd_bddLICompaction] ******************************************************************************/ int Cudd_bddApproxConjDecomp( DdManager * dd /* manager */, DdNode * f /* function to be decomposed */, DdNode *** conjuncts /* address of the first factor */) { DdNode *superset1, *superset2, *glocal, *hlocal; int nvars = Cudd_SupportSize(dd,f); /* Find a tentative first factor by overapproximation and minimization. */ superset1 = Cudd_RemapOverApprox(dd,f,nvars,0,1.0); if (superset1 == NULL) return(0); cuddRef(superset1); superset2 = Cudd_bddSqueeze(dd,f,superset1); if (superset2 == NULL) { Cudd_RecursiveDeref(dd,superset1); return(0); } cuddRef(superset2); Cudd_RecursiveDeref(dd,superset1); /* Compute the second factor by minimization. */ hlocal = Cudd_bddLICompaction(dd,f,superset2); if (hlocal == NULL) { Cudd_RecursiveDeref(dd,superset2); return(0); } cuddRef(hlocal); /* Refine the first factor by minimization. If h turns out to be f, this ** step guarantees that g will be 1. */ glocal = Cudd_bddLICompaction(dd,superset2,hlocal); if (glocal == NULL) { Cudd_RecursiveDeref(dd,superset2); Cudd_RecursiveDeref(dd,hlocal); return(0); } cuddRef(glocal); Cudd_RecursiveDeref(dd,superset2); if (glocal != DD_ONE(dd)) { if (hlocal != DD_ONE(dd)) { *conjuncts = ABC_ALLOC(DdNode *,2); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,glocal); Cudd_RecursiveDeref(dd,hlocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = glocal; (*conjuncts)[1] = hlocal; return(2); } else { Cudd_RecursiveDeref(dd,hlocal); *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,glocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = glocal; return(1); } } else { Cudd_RecursiveDeref(dd,glocal); *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,hlocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = hlocal; return(1); } } /* end of Cudd_bddApproxConjDecomp */ /**Function******************************************************************** Synopsis [Performs two-way disjunctive decomposition of a BDD.] Description [Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be imbalanced.] SideEffects [The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.] SeeAlso [Cudd_bddApproxConjDecomp Cudd_bddIterDisjDecomp Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp] ******************************************************************************/ int Cudd_bddApproxDisjDecomp( DdManager * dd /* manager */, DdNode * f /* function to be decomposed */, DdNode *** disjuncts /* address of the array of the disjuncts */) { int result, i; result = Cudd_bddApproxConjDecomp(dd,Cudd_Not(f),disjuncts); for (i = 0; i < result; i++) { (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); } return(result); } /* end of Cudd_bddApproxDisjDecomp */ /**Function******************************************************************** Synopsis [Performs two-way conjunctive decomposition of a BDD.] Description [Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the iterated use of supersetting to obtain a factor of the given function. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be imbalanced.] SideEffects [The factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.] SeeAlso [Cudd_bddIterDisjDecomp Cudd_bddApproxConjDecomp Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox Cudd_bddSqueeze Cudd_bddLICompaction] ******************************************************************************/ int Cudd_bddIterConjDecomp( DdManager * dd /* manager */, DdNode * f /* function to be decomposed */, DdNode *** conjuncts /* address of the array of conjuncts */) { DdNode *superset1, *superset2, *old[2], *res[2]; int sizeOld, sizeNew; int nvars = Cudd_SupportSize(dd,f); old[0] = DD_ONE(dd); cuddRef(old[0]); old[1] = f; cuddRef(old[1]); sizeOld = Cudd_SharingSize(old,2); do { /* Find a tentative first factor by overapproximation and ** minimization. */ superset1 = Cudd_RemapOverApprox(dd,old[1],nvars,0,1.0); if (superset1 == NULL) { Cudd_RecursiveDeref(dd,old[0]); Cudd_RecursiveDeref(dd,old[1]); return(0); } cuddRef(superset1); superset2 = Cudd_bddSqueeze(dd,old[1],superset1); if (superset2 == NULL) { Cudd_RecursiveDeref(dd,old[0]); Cudd_RecursiveDeref(dd,old[1]); Cudd_RecursiveDeref(dd,superset1); return(0); } cuddRef(superset2); Cudd_RecursiveDeref(dd,superset1); res[0] = Cudd_bddAnd(dd,old[0],superset2); if (res[0] == NULL) { Cudd_RecursiveDeref(dd,superset2); Cudd_RecursiveDeref(dd,old[0]); Cudd_RecursiveDeref(dd,old[1]); return(0); } cuddRef(res[0]); Cudd_RecursiveDeref(dd,superset2); if (res[0] == old[0]) { Cudd_RecursiveDeref(dd,res[0]); break; /* avoid infinite loop */ } /* Compute the second factor by minimization. */ res[1] = Cudd_bddLICompaction(dd,old[1],res[0]); if (res[1] == NULL) { Cudd_RecursiveDeref(dd,old[0]); Cudd_RecursiveDeref(dd,old[1]); return(0); } cuddRef(res[1]); sizeNew = Cudd_SharingSize(res,2); if (sizeNew <= sizeOld) { Cudd_RecursiveDeref(dd,old[0]); old[0] = res[0]; Cudd_RecursiveDeref(dd,old[1]); old[1] = res[1]; sizeOld = sizeNew; } else { Cudd_RecursiveDeref(dd,res[0]); Cudd_RecursiveDeref(dd,res[1]); break; } } while (1); /* Refine the first factor by minimization. If h turns out to ** be f, this step guarantees that g will be 1. */ superset1 = Cudd_bddLICompaction(dd,old[0],old[1]); if (superset1 == NULL) { Cudd_RecursiveDeref(dd,old[0]); Cudd_RecursiveDeref(dd,old[1]); return(0); } cuddRef(superset1); Cudd_RecursiveDeref(dd,old[0]); old[0] = superset1; if (old[0] != DD_ONE(dd)) { if (old[1] != DD_ONE(dd)) { *conjuncts = ABC_ALLOC(DdNode *,2); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,old[0]); Cudd_RecursiveDeref(dd,old[1]); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = old[0]; (*conjuncts)[1] = old[1]; return(2); } else { Cudd_RecursiveDeref(dd,old[1]); *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,old[0]); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = old[0]; return(1); } } else { Cudd_RecursiveDeref(dd,old[0]); *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,old[1]); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = old[1]; return(1); } } /* end of Cudd_bddIterConjDecomp */ /**Function******************************************************************** Synopsis [Performs two-way disjunctive decomposition of a BDD.] Description [Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be imbalanced.] SideEffects [The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.] SeeAlso [Cudd_bddIterConjDecomp Cudd_bddApproxDisjDecomp Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp] ******************************************************************************/ int Cudd_bddIterDisjDecomp( DdManager * dd /* manager */, DdNode * f /* function to be decomposed */, DdNode *** disjuncts /* address of the array of the disjuncts */) { int result, i; result = Cudd_bddIterConjDecomp(dd,Cudd_Not(f),disjuncts); for (i = 0; i < result; i++) { (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); } return(result); } /* end of Cudd_bddIterDisjDecomp */ /**Function******************************************************************** Synopsis [Performs two-way conjunctive decomposition of a BDD.] Description [Performs two-way conjunctive decomposition of a BDD. This procedure owes its name to the fact tht it generalizes the decomposition based on the cofactors with respect to one variable. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The conjuncts produced by this procedure tend to be balanced.] SideEffects [The two factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.] SeeAlso [Cudd_bddGenDisjDecomp Cudd_bddApproxConjDecomp Cudd_bddIterConjDecomp Cudd_bddVarConjDecomp] ******************************************************************************/ int Cudd_bddGenConjDecomp( DdManager * dd /* manager */, DdNode * f /* function to be decomposed */, DdNode *** conjuncts /* address of the array of conjuncts */) { int result; DdNode *glocal, *hlocal; one = DD_ONE(dd); zero = Cudd_Not(one); do { dd->reordered = 0; result = cuddConjunctsAux(dd, f, &glocal, &hlocal); } while (dd->reordered == 1); if (result == 0) { return(0); } if (glocal != one) { if (hlocal != one) { *conjuncts = ABC_ALLOC(DdNode *,2); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,glocal); Cudd_RecursiveDeref(dd,hlocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = glocal; (*conjuncts)[1] = hlocal; return(2); } else { Cudd_RecursiveDeref(dd,hlocal); *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,glocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = glocal; return(1); } } else { Cudd_RecursiveDeref(dd,glocal); *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,hlocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = hlocal; return(1); } } /* end of Cudd_bddGenConjDecomp */ /**Function******************************************************************** Synopsis [Performs two-way disjunctive decomposition of a BDD.] Description [Performs two-way disjunctive decomposition of a BDD. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise. The disjuncts produced by this procedure tend to be balanced.] SideEffects [The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.] SeeAlso [Cudd_bddGenConjDecomp Cudd_bddApproxDisjDecomp Cudd_bddIterDisjDecomp Cudd_bddVarDisjDecomp] ******************************************************************************/ int Cudd_bddGenDisjDecomp( DdManager * dd /* manager */, DdNode * f /* function to be decomposed */, DdNode *** disjuncts /* address of the array of the disjuncts */) { int result, i; result = Cudd_bddGenConjDecomp(dd,Cudd_Not(f),disjuncts); for (i = 0; i < result; i++) { (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); } return(result); } /* end of Cudd_bddGenDisjDecomp */ /**Function******************************************************************** Synopsis [Performs two-way conjunctive decomposition of a BDD.] Description [Conjunctively decomposes one BDD according to a variable. If f is the function of the BDD and x is the variable, the decomposition is (f+x)(f+x'). The variable is chosen so as to balance the sizes of the two conjuncts and to keep them small. Returns the number of conjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise.] SideEffects [The two factors are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the conjuncts are already referenced. If the function returns 0, the array for the conjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.] SeeAlso [Cudd_bddVarDisjDecomp Cudd_bddGenConjDecomp Cudd_bddApproxConjDecomp Cudd_bddIterConjDecomp] *****************************************************************************/ int Cudd_bddVarConjDecomp( DdManager * dd /* manager */, DdNode * f /* function to be decomposed */, DdNode *** conjuncts /* address of the array of conjuncts */) { int best; int min; DdNode *support, *scan, *var, *glocal, *hlocal; /* Find best cofactoring variable. */ support = Cudd_Support(dd,f); if (support == NULL) return(0); if (Cudd_IsConstant(support)) { *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = f; cuddRef((*conjuncts)[0]); return(1); } cuddRef(support); min = 1000000000; best = -1; scan = support; while (!Cudd_IsConstant(scan)) { int i = scan->index; int est1 = Cudd_EstimateCofactor(dd,f,i,1); int est0 = Cudd_EstimateCofactor(dd,f,i,0); /* Minimize the size of the larger of the two cofactors. */ int est = (est1 > est0) ? est1 : est0; if (est < min) { min = est; best = i; } scan = cuddT(scan); } #ifdef DD_DEBUG assert(best >= 0 && best < dd->size); #endif Cudd_RecursiveDeref(dd,support); var = Cudd_bddIthVar(dd,best); glocal = Cudd_bddOr(dd,f,var); if (glocal == NULL) { return(0); } cuddRef(glocal); hlocal = Cudd_bddOr(dd,f,Cudd_Not(var)); if (hlocal == NULL) { Cudd_RecursiveDeref(dd,glocal); return(0); } cuddRef(hlocal); if (glocal != DD_ONE(dd)) { if (hlocal != DD_ONE(dd)) { *conjuncts = ABC_ALLOC(DdNode *,2); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,glocal); Cudd_RecursiveDeref(dd,hlocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = glocal; (*conjuncts)[1] = hlocal; return(2); } else { Cudd_RecursiveDeref(dd,hlocal); *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,glocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = glocal; return(1); } } else { Cudd_RecursiveDeref(dd,glocal); *conjuncts = ABC_ALLOC(DdNode *,1); if (*conjuncts == NULL) { Cudd_RecursiveDeref(dd,hlocal); dd->errorCode = CUDD_MEMORY_OUT; return(0); } (*conjuncts)[0] = hlocal; return(1); } } /* end of Cudd_bddVarConjDecomp */ /**Function******************************************************************** Synopsis [Performs two-way disjunctive decomposition of a BDD.] Description [Performs two-way disjunctive decomposition of a BDD according to a variable. If f is the function of the BDD and x is the variable, the decomposition is f*x + f*x'. The variable is chosen so as to balance the sizes of the two disjuncts and to keep them small. Returns the number of disjuncts produced, that is, 2 if successful; 1 if no meaningful decomposition was found; 0 otherwise.] SideEffects [The two disjuncts are returned in an array as side effects. The array is allocated by this function. It is the caller's responsibility to free it. On successful completion, the disjuncts are already referenced. If the function returns 0, the array for the disjuncts is not allocated. If the function returns 1, the only factor equals the function to be decomposed.] SeeAlso [Cudd_bddVarConjDecomp Cudd_bddApproxDisjDecomp Cudd_bddIterDisjDecomp Cudd_bddGenDisjDecomp] ******************************************************************************/ int Cudd_bddVarDisjDecomp( DdManager * dd /* manager */, DdNode * f /* function to be decomposed */, DdNode *** disjuncts /* address of the array of the disjuncts */) { int result, i; result = Cudd_bddVarConjDecomp(dd,Cudd_Not(f),disjuncts); for (i = 0; i < result; i++) { (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); } return(result); } /* end of Cudd_bddVarDisjDecomp */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Get longest distance of node from constant.] Description [Get longest distance of node from constant. Returns the distance of the root from the constant if successful; CUDD_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static NodeStat * CreateBotDist( DdNode * node, st__table * distanceTable) { DdNode *N, *Nv, *Nnv; int distance, distanceNv, distanceNnv; NodeStat *nodeStat, *nodeStatNv, *nodeStatNnv; #if 0 if (Cudd_IsConstant(node)) { return(0); } #endif /* Return the entry in the table if found. */ N = Cudd_Regular(node); if ( st__lookup(distanceTable, (const char *)N, (char **)&nodeStat)) { nodeStat->localRef++; return(nodeStat); } Nv = cuddT(N); Nnv = cuddE(N); Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); /* Recur on the children. */ nodeStatNv = CreateBotDist(Nv, distanceTable); if (nodeStatNv == NULL) return(NULL); distanceNv = nodeStatNv->distance; nodeStatNnv = CreateBotDist(Nnv, distanceTable); if (nodeStatNnv == NULL) return(NULL); distanceNnv = nodeStatNnv->distance; /* Store max distance from constant; note sometimes this distance ** may be to 0. */ distance = (distanceNv > distanceNnv) ? (distanceNv+1) : (distanceNnv + 1); nodeStat = ABC_ALLOC(NodeStat, 1); if (nodeStat == NULL) { return(0); } nodeStat->distance = distance; nodeStat->localRef = 1; if ( st__insert(distanceTable, (char *)N, (char *)nodeStat) == st__OUT_OF_MEM) { return(0); } return(nodeStat); } /* end of CreateBotDist */ /**Function******************************************************************** Synopsis [Count the number of minterms of each node ina a BDD and store it in a hash table.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static double CountMinterms( DdNode * node, double max, st__table * mintermTable, FILE *fp) { DdNode *N, *Nv, *Nnv; double min, minNv, minNnv; double *dummy; N = Cudd_Regular(node); if (cuddIsConstant(N)) { if (node == zero) { return(0); } else { return(max); } } /* Return the entry in the table if found. */ if ( st__lookup(mintermTable, (const char *)node, (char **)&dummy)) { min = *dummy; return(min); } Nv = cuddT(N); Nnv = cuddE(N); Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); /* Recur on the children. */ minNv = CountMinterms(Nv, max, mintermTable, fp); if (minNv == -1.0) return(-1.0); minNnv = CountMinterms(Nnv, max, mintermTable, fp); if (minNnv == -1.0) return(-1.0); min = minNv / 2.0 + minNnv / 2.0; /* store */ dummy = ABC_ALLOC(double, 1); if (dummy == NULL) return(-1.0); *dummy = min; if ( st__insert(mintermTable, (char *)node, (char *)dummy) == st__OUT_OF_MEM) { (void) fprintf(fp, "st table insert failed\n"); } return(min); } /* end of CountMinterms */ /**Function******************************************************************** Synopsis [Free factors structure] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void ConjunctsFree( DdManager * dd, Conjuncts * factors) { Cudd_RecursiveDeref(dd, factors->g); Cudd_RecursiveDeref(dd, factors->h); ABC_FREE(factors); return; } /* end of ConjunctsFree */ /**Function******************************************************************** Synopsis [Check whether the given pair is in the tables.] Description [.Check whether the given pair is in the tables. gTable and hTable are combined. absence in both is indicated by 0, presence in gTable is indicated by 1, presence in hTable by 2 and presence in both by 3. The values returned by this function are PAIR_ST, PAIR_CR, G_ST, G_CR, H_ST, H_CR, BOTH_G, BOTH_H, NONE. PAIR_ST implies g in gTable and h in hTable PAIR_CR implies g in hTable and h in gTable G_ST implies g in gTable and h not in any table G_CR implies g in hTable and h not in any table H_ST implies h in hTable and g not in any table H_CR implies h in gTable and g not in any table BOTH_G implies both in gTable BOTH_H implies both in hTable NONE implies none in table; ] SideEffects [] SeeAlso [CheckTablesCacheAndReturn CheckInTables] ******************************************************************************/ static int PairInTables( DdNode * g, DdNode * h, st__table * ghTable) { int valueG, valueH, gPresent, hPresent; valueG = valueH = gPresent = hPresent = 0; gPresent = st__lookup_int(ghTable, (char *)Cudd_Regular(g), &valueG); hPresent = st__lookup_int(ghTable, (char *)Cudd_Regular(h), &valueH); if (!gPresent && !hPresent) return(NONE); if (!hPresent) { if (valueG & 1) return(G_ST); if (valueG & 2) return(G_CR); } if (!gPresent) { if (valueH & 1) return(H_CR); if (valueH & 2) return(H_ST); } /* both in tables */ if ((valueG & 1) && (valueH & 2)) return(PAIR_ST); if ((valueG & 2) && (valueH & 1)) return(PAIR_CR); if (valueG & 1) { return(BOTH_G); } else { return(BOTH_H); } } /* end of PairInTables */ /**Function******************************************************************** Synopsis [Check the tables for the existence of pair and return one combination, cache the result.] Description [Check the tables for the existence of pair and return one combination, cache the result. The assumption is that one of the conjuncts is already in the tables.] SideEffects [g and h referenced for the cache] SeeAlso [ZeroCase] ******************************************************************************/ static Conjuncts * CheckTablesCacheAndReturn( DdNode * node, DdNode * g, DdNode * h, st__table * ghTable, st__table * cacheTable) { int pairValue; int value; Conjuncts *factors; value = 0; /* check tables */ pairValue = PairInTables(g, h, ghTable); assert(pairValue != NONE); /* if both dont exist in table, we know one exists(either g or h). * Therefore store the other and proceed */ factors = ABC_ALLOC(Conjuncts, 1); if (factors == NULL) return(NULL); if ((pairValue == BOTH_H) || (pairValue == H_ST)) { if (g != one) { value = 0; if ( st__lookup_int(ghTable, (char *)Cudd_Regular(g), &value)) { value |= 1; } else { value = 1; } if ( st__insert(ghTable, (char *)Cudd_Regular(g), (char *)(long)value) == st__OUT_OF_MEM) { return(NULL); } } factors->g = g; factors->h = h; } else if ((pairValue == BOTH_G) || (pairValue == G_ST)) { if (h != one) { value = 0; if ( st__lookup_int(ghTable, (char *)Cudd_Regular(h), &value)) { value |= 2; } else { value = 2; } if ( st__insert(ghTable, (char *)Cudd_Regular(h), (char *)(long)value) == st__OUT_OF_MEM) { return(NULL); } } factors->g = g; factors->h = h; } else if (pairValue == H_CR) { if (g != one) { value = 2; if ( st__insert(ghTable, (char *)Cudd_Regular(g), (char *)(long)value) == st__OUT_OF_MEM) { return(NULL); } } factors->g = h; factors->h = g; } else if (pairValue == G_CR) { if (h != one) { value = 1; if ( st__insert(ghTable, (char *)Cudd_Regular(h), (char *)(long)value) == st__OUT_OF_MEM) { return(NULL); } } factors->g = h; factors->h = g; } else if (pairValue == PAIR_CR) { /* pair exists in table */ factors->g = h; factors->h = g; } else if (pairValue == PAIR_ST) { factors->g = g; factors->h = h; } /* cache the result for this node */ if ( st__insert(cacheTable, (char *)node, (char *)factors) == st__OUT_OF_MEM) { ABC_FREE(factors); return(NULL); } return(factors); } /* end of CheckTablesCacheAndReturn */ /**Function******************************************************************** Synopsis [Check the tables for the existence of pair and return one combination, store in cache.] Description [Check the tables for the existence of pair and return one combination, store in cache. The pair that has more pointers to it is picked. An approximation of the number of local pointers is made by taking the reference count of the pairs sent. ] SideEffects [] SeeAlso [ZeroCase BuildConjuncts] ******************************************************************************/ static Conjuncts * PickOnePair( DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st__table * ghTable, st__table * cacheTable) { int value; Conjuncts *factors; int oneRef, twoRef; factors = ABC_ALLOC(Conjuncts, 1); if (factors == NULL) return(NULL); /* count the number of pointers to pair 2 */ if (h2 == one) { twoRef = (Cudd_Regular(g2))->ref; } else if (g2 == one) { twoRef = (Cudd_Regular(h2))->ref; } else { twoRef = ((Cudd_Regular(g2))->ref + (Cudd_Regular(h2))->ref)/2; } /* count the number of pointers to pair 1 */ if (h1 == one) { oneRef = (Cudd_Regular(g1))->ref; } else if (g1 == one) { oneRef = (Cudd_Regular(h1))->ref; } else { oneRef = ((Cudd_Regular(g1))->ref + (Cudd_Regular(h1))->ref)/2; } /* pick the pair with higher reference count */ if (oneRef >= twoRef) { factors->g = g1; factors->h = h1; } else { factors->g = g2; factors->h = h2; } /* * Store computed factors in respective tables to encourage * recombination. */ if (factors->g != one) { /* insert g in htable */ value = 0; if ( st__lookup_int(ghTable, (char *)Cudd_Regular(factors->g), &value)) { if (value == 2) { value |= 1; if ( st__insert(ghTable, (char *)Cudd_Regular(factors->g), (char *)(long)value) == st__OUT_OF_MEM) { ABC_FREE(factors); return(NULL); } } } else { value = 1; if ( st__insert(ghTable, (char *)Cudd_Regular(factors->g), (char *)(long)value) == st__OUT_OF_MEM) { ABC_FREE(factors); return(NULL); } } } if (factors->h != one) { /* insert h in htable */ value = 0; if ( st__lookup_int(ghTable, (char *)Cudd_Regular(factors->h), &value)) { if (value == 1) { value |= 2; if ( st__insert(ghTable, (char *)Cudd_Regular(factors->h), (char *)(long)value) == st__OUT_OF_MEM) { ABC_FREE(factors); return(NULL); } } } else { value = 2; if ( st__insert(ghTable, (char *)Cudd_Regular(factors->h), (char *)(long)value) == st__OUT_OF_MEM) { ABC_FREE(factors); return(NULL); } } } /* Store factors in cache table for later use. */ if ( st__insert(cacheTable, (char *)node, (char *)factors) == st__OUT_OF_MEM) { ABC_FREE(factors); return(NULL); } return(factors); } /* end of PickOnePair */ /**Function******************************************************************** Synopsis [Check if the two pairs exist in the table, If any of the conjuncts do exist, store in the cache and return the corresponding pair.] Description [Check if the two pairs exist in the table. If any of the conjuncts do exist, store in the cache and return the corresponding pair.] SideEffects [] SeeAlso [ZeroCase BuildConjuncts] ******************************************************************************/ static Conjuncts * CheckInTables( DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st__table * ghTable, st__table * cacheTable, int * outOfMem) { int pairValue1, pairValue2; Conjuncts *factors; int value; *outOfMem = 0; /* check existence of pair in table */ pairValue1 = PairInTables(g1, h1, ghTable); pairValue2 = PairInTables(g2, h2, ghTable); /* if none of the 4 exist in the gh tables, return NULL */ if ((pairValue1 == NONE) && (pairValue2 == NONE)) { return NULL; } factors = ABC_ALLOC(Conjuncts, 1); if (factors == NULL) { *outOfMem = 1; return NULL; } /* pairs that already exist in the table get preference. */ if (pairValue1 == PAIR_ST) { factors->g = g1; factors->h = h1; } else if (pairValue2 == PAIR_ST) { factors->g = g2; factors->h = h2; } else if (pairValue1 == PAIR_CR) { factors->g = h1; factors->h = g1; } else if (pairValue2 == PAIR_CR) { factors->g = h2; factors->h = g2; } else if (pairValue1 == G_ST) { /* g exists in the table, h is not found in either table */ factors->g = g1; factors->h = h1; if (h1 != one) { value = 2; if ( st__insert(ghTable, (char *)Cudd_Regular(h1), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue1 == BOTH_G) { /* g and h are found in the g table */ factors->g = g1; factors->h = h1; if (h1 != one) { value = 3; if ( st__insert(ghTable, (char *)Cudd_Regular(h1), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue1 == H_ST) { /* h exists in the table, g is not found in either table */ factors->g = g1; factors->h = h1; if (g1 != one) { value = 1; if ( st__insert(ghTable, (char *)Cudd_Regular(g1), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue1 == BOTH_H) { /* g and h are found in the h table */ factors->g = g1; factors->h = h1; if (g1 != one) { value = 3; if ( st__insert(ghTable, (char *)Cudd_Regular(g1), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue2 == G_ST) { /* g exists in the table, h is not found in either table */ factors->g = g2; factors->h = h2; if (h2 != one) { value = 2; if ( st__insert(ghTable, (char *)Cudd_Regular(h2), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue2 == BOTH_G) { /* g and h are found in the g table */ factors->g = g2; factors->h = h2; if (h2 != one) { value = 3; if ( st__insert(ghTable, (char *)Cudd_Regular(h2), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue2 == H_ST) { /* h exists in the table, g is not found in either table */ factors->g = g2; factors->h = h2; if (g2 != one) { value = 1; if ( st__insert(ghTable, (char *)Cudd_Regular(g2), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue2 == BOTH_H) { /* g and h are found in the h table */ factors->g = g2; factors->h = h2; if (g2 != one) { value = 3; if ( st__insert(ghTable, (char *)Cudd_Regular(g2), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue1 == G_CR) { /* g found in h table and h in none */ factors->g = h1; factors->h = g1; if (h1 != one) { value = 1; if ( st__insert(ghTable, (char *)Cudd_Regular(h1), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue1 == H_CR) { /* h found in g table and g in none */ factors->g = h1; factors->h = g1; if (g1 != one) { value = 2; if ( st__insert(ghTable, (char *)Cudd_Regular(g1), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue2 == G_CR) { /* g found in h table and h in none */ factors->g = h2; factors->h = g2; if (h2 != one) { value = 1; if ( st__insert(ghTable, (char *)Cudd_Regular(h2), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } else if (pairValue2 == H_CR) { /* h found in g table and g in none */ factors->g = h2; factors->h = g2; if (g2 != one) { value = 2; if ( st__insert(ghTable, (char *)Cudd_Regular(g2), (char *)(long)value) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } } } /* Store factors in cache table for later use. */ if ( st__insert(cacheTable, (char *)node, (char *)factors) == st__OUT_OF_MEM) { *outOfMem = 1; ABC_FREE(factors); return(NULL); } return factors; } /* end of CheckInTables */ /**Function******************************************************************** Synopsis [If one child is zero, do explicitly what Restrict does or better] Description [If one child is zero, do explicitly what Restrict does or better. First separate a variable and its child in the base case. In case of a cube times a function, separate the cube and function. As a last resort, look in tables.] SideEffects [Frees the BDDs in factorsNv. factorsNv itself is not freed because it is freed above.] SeeAlso [BuildConjuncts] ******************************************************************************/ static Conjuncts * ZeroCase( DdManager * dd, DdNode * node, Conjuncts * factorsNv, st__table * ghTable, st__table * cacheTable, int switched) { int topid; DdNode *g, *h, *g1, *g2, *h1, *h2, *x, *N, *G, *H, *Gv, *Gnv; DdNode *Hv, *Hnv; int value; int outOfMem; Conjuncts *factors; /* get var at this node */ N = Cudd_Regular(node); topid = N->index; x = dd->vars[topid]; x = (switched) ? Cudd_Not(x): x; cuddRef(x); /* Seprate variable and child */ if (factorsNv->g == one) { Cudd_RecursiveDeref(dd, factorsNv->g); factors = ABC_ALLOC(Conjuncts, 1); if (factors == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, x); return(NULL); } factors->g = x; factors->h = factorsNv->h; /* cache the result*/ if ( st__insert(cacheTable, (char *)node, (char *)factors) == st__OUT_OF_MEM) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, x); ABC_FREE(factors); return NULL; } /* store x in g table, the other node is already in the table */ if ( st__lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) { value |= 1; } else { value = 1; } if ( st__insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == st__OUT_OF_MEM) { dd->errorCode = CUDD_MEMORY_OUT; return NULL; } return(factors); } /* Seprate variable and child */ if (factorsNv->h == one) { Cudd_RecursiveDeref(dd, factorsNv->h); factors = ABC_ALLOC(Conjuncts, 1); if (factors == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, x); return(NULL); } factors->g = factorsNv->g; factors->h = x; /* cache the result. */ if ( st__insert(cacheTable, (char *)node, (char *)factors) == st__OUT_OF_MEM) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, x); ABC_FREE(factors); return(NULL); } /* store x in h table, the other node is already in the table */ if ( st__lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) { value |= 2; } else { value = 2; } if ( st__insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == st__OUT_OF_MEM) { dd->errorCode = CUDD_MEMORY_OUT; return NULL; } return(factors); } G = Cudd_Regular(factorsNv->g); Gv = cuddT(G); Gnv = cuddE(G); Gv = Cudd_NotCond(Gv, Cudd_IsComplement(node)); Gnv = Cudd_NotCond(Gnv, Cudd_IsComplement(node)); /* if the child below is a variable */ if ((Gv == zero) || (Gnv == zero)) { h = factorsNv->h; g = cuddBddAndRecur(dd, x, factorsNv->g); if (g != NULL) cuddRef(g); Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, x); if (g == NULL) { Cudd_RecursiveDeref(dd, factorsNv->h); return NULL; } /* CheckTablesCacheAndReturn responsible for allocating * factors structure., g,h referenced for cache store the */ factors = CheckTablesCacheAndReturn(node, g, h, ghTable, cacheTable); if (factors == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, g); Cudd_RecursiveDeref(dd, h); } return(factors); } H = Cudd_Regular(factorsNv->h); Hv = cuddT(H); Hnv = cuddE(H); Hv = Cudd_NotCond(Hv, Cudd_IsComplement(node)); Hnv = Cudd_NotCond(Hnv, Cudd_IsComplement(node)); /* if the child below is a variable */ if ((Hv == zero) || (Hnv == zero)) { g = factorsNv->g; h = cuddBddAndRecur(dd, x, factorsNv->h); if (h!= NULL) cuddRef(h); Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, x); if (h == NULL) { Cudd_RecursiveDeref(dd, factorsNv->g); return NULL; } /* CheckTablesCacheAndReturn responsible for allocating * factors structure.g,h referenced for table store */ factors = CheckTablesCacheAndReturn(node, g, h, ghTable, cacheTable); if (factors == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, g); Cudd_RecursiveDeref(dd, h); } return(factors); } /* build g1 = x*g; h1 = h */ /* build g2 = g; h2 = x*h */ Cudd_RecursiveDeref(dd, x); h1 = factorsNv->h; g1 = cuddBddAndRecur(dd, x, factorsNv->g); if (g1 != NULL) cuddRef(g1); if (g1 == NULL) { Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, factorsNv->h); return NULL; } g2 = factorsNv->g; h2 = cuddBddAndRecur(dd, x, factorsNv->h); if (h2 != NULL) cuddRef(h2); if (h2 == NULL) { Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, factorsNv->g); return NULL; } /* check whether any pair is in tables */ factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem); if (outOfMem) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); Cudd_RecursiveDeref(dd, g2); Cudd_RecursiveDeref(dd, h2); return NULL; } if (factors != NULL) { if ((factors->g == g1) || (factors->g == h1)) { Cudd_RecursiveDeref(dd, g2); Cudd_RecursiveDeref(dd, h2); } else { Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); } return factors; } /* check for each pair in tables and choose one */ factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable); if (factors == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); Cudd_RecursiveDeref(dd, g2); Cudd_RecursiveDeref(dd, h2); } else { /* now free what was created and not used */ if ((factors->g == g1) || (factors->g == h1)) { Cudd_RecursiveDeref(dd, g2); Cudd_RecursiveDeref(dd, h2); } else { Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); } } return(factors); } /* end of ZeroCase */ /**Function******************************************************************** Synopsis [Builds the conjuncts recursively, bottom up.] Description [Builds the conjuncts recursively, bottom up. Constants are returned as (f, f). The cache is checked for previously computed result. The decomposition points are determined by the local reference count of this node and the longest distance from the constant. At the decomposition point, the factors returned are (f, 1). Recur on the two children. The order is determined by the heavier branch. Combine the factors of the two children and pick the one that already occurs in the gh table. Occurence in g is indicated by value 1, occurence in h by 2, occurence in both 3.] SideEffects [] SeeAlso [cuddConjunctsAux] ******************************************************************************/ static Conjuncts * BuildConjuncts( DdManager * dd, DdNode * node, st__table * distanceTable, st__table * cacheTable, int approxDistance, int maxLocalRef, st__table * ghTable, st__table * mintermTable) { int topid, distance; Conjuncts *factorsNv = NULL, *factorsNnv = NULL, *factors; Conjuncts *dummy; DdNode *N, *Nv, *Nnv, *temp, *g1, *g2, *h1, *h2, *topv; double minNv = 0.0, minNnv = 0.0; double *doubleDummy; int switched =0; int outOfMem; int freeNv = 0, freeNnv = 0, freeTemp; NodeStat *nodeStat; int value; /* if f is constant, return (f,f) */ if (Cudd_IsConstant(node)) { factors = ABC_ALLOC(Conjuncts, 1); if (factors == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } factors->g = node; factors->h = node; return(FactorsComplement(factors)); } /* If result (a pair of conjuncts) in cache, return the factors. */ if ( st__lookup(cacheTable, (const char *)node, (char **)&dummy)) { factors = dummy; return(factors); } /* check distance and local reference count of this node */ N = Cudd_Regular(node); if (! st__lookup(distanceTable, (const char *)N, (char **)&nodeStat)) { (void) fprintf(dd->err, "Not in table, Something wrong\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } distance = nodeStat->distance; /* at or below decomposition point, return (f, 1) */ if (((nodeStat->localRef > maxLocalRef*2/3) && (distance < approxDistance*2/3)) || (distance <= approxDistance/4)) { factors = ABC_ALLOC(Conjuncts, 1); if (factors == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } /* alternate assigning (f,1) */ value = 0; if ( st__lookup_int(ghTable, (char *)Cudd_Regular(node), &value)) { if (value == 3) { if (!lastTimeG) { factors->g = node; factors->h = one; lastTimeG = 1; } else { factors->g = one; factors->h = node; lastTimeG = 0; } } else if (value == 1) { factors->g = node; factors->h = one; } else { factors->g = one; factors->h = node; } } else if (!lastTimeG) { factors->g = node; factors->h = one; lastTimeG = 1; value = 1; if ( st__insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == st__OUT_OF_MEM) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(factors); return NULL; } } else { factors->g = one; factors->h = node; lastTimeG = 0; value = 2; if ( st__insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == st__OUT_OF_MEM) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(factors); return NULL; } } return(FactorsComplement(factors)); } /* get the children and recur */ Nv = cuddT(N); Nnv = cuddE(N); Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); /* Choose which subproblem to solve first based on the number of * minterms. We go first where there are more minterms. */ if (!Cudd_IsConstant(Nv)) { if (! st__lookup(mintermTable, (const char *)Nv, (char **)&doubleDummy)) { (void) fprintf(dd->err, "Not in table: Something wrong\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } minNv = *doubleDummy; } if (!Cudd_IsConstant(Nnv)) { if (! st__lookup(mintermTable, (const char *)Nnv, (char **)&doubleDummy)) { (void) fprintf(dd->err, "Not in table: Something wrong\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } minNnv = *doubleDummy; } if (minNv < minNnv) { temp = Nv; Nv = Nnv; Nnv = temp; switched = 1; } /* build gt, ht recursively */ if (Nv != zero) { factorsNv = BuildConjuncts(dd, Nv, distanceTable, cacheTable, approxDistance, maxLocalRef, ghTable, mintermTable); if (factorsNv == NULL) return(NULL); freeNv = FactorsNotStored(factorsNv); factorsNv = (freeNv) ? FactorsUncomplement(factorsNv) : factorsNv; cuddRef(factorsNv->g); cuddRef(factorsNv->h); /* Deal with the zero case */ if (Nnv == zero) { /* is responsible for freeing factorsNv */ factors = ZeroCase(dd, node, factorsNv, ghTable, cacheTable, switched); if (freeNv) ABC_FREE(factorsNv); return(factors); } } /* build ge, he recursively */ if (Nnv != zero) { factorsNnv = BuildConjuncts(dd, Nnv, distanceTable, cacheTable, approxDistance, maxLocalRef, ghTable, mintermTable); if (factorsNnv == NULL) { Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, factorsNv->h); if (freeNv) ABC_FREE(factorsNv); return(NULL); } freeNnv = FactorsNotStored(factorsNnv); factorsNnv = (freeNnv) ? FactorsUncomplement(factorsNnv) : factorsNnv; cuddRef(factorsNnv->g); cuddRef(factorsNnv->h); /* Deal with the zero case */ if (Nv == zero) { /* is responsible for freeing factorsNv */ factors = ZeroCase(dd, node, factorsNnv, ghTable, cacheTable, switched); if (freeNnv) ABC_FREE(factorsNnv); return(factors); } } /* construct the 2 pairs */ /* g1 = x*gt + x'*ge; h1 = x*ht + x'*he; */ /* g2 = x*gt + x'*he; h2 = x*ht + x'*ge */ if (switched) { factors = factorsNnv; factorsNnv = factorsNv; factorsNv = factors; freeTemp = freeNv; freeNv = freeNnv; freeNnv = freeTemp; } /* Build the factors for this node. */ topid = N->index; topv = dd->vars[topid]; g1 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->g); if (g1 == NULL) { Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, factorsNnv->g); Cudd_RecursiveDeref(dd, factorsNnv->h); if (freeNv) ABC_FREE(factorsNv); if (freeNnv) ABC_FREE(factorsNnv); return(NULL); } cuddRef(g1); h1 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->h); if (h1 == NULL) { Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, factorsNnv->g); Cudd_RecursiveDeref(dd, factorsNnv->h); Cudd_RecursiveDeref(dd, g1); if (freeNv) ABC_FREE(factorsNv); if (freeNnv) ABC_FREE(factorsNnv); return(NULL); } cuddRef(h1); g2 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->h); if (g2 == NULL) { Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, factorsNnv->g); Cudd_RecursiveDeref(dd, factorsNnv->h); Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); if (freeNv) ABC_FREE(factorsNv); if (freeNnv) ABC_FREE(factorsNnv); return(NULL); } cuddRef(g2); Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, factorsNnv->h); h2 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->g); if (h2 == NULL) { Cudd_RecursiveDeref(dd, factorsNv->g); Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, factorsNnv->g); Cudd_RecursiveDeref(dd, factorsNnv->h); Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); Cudd_RecursiveDeref(dd, g2); if (freeNv) ABC_FREE(factorsNv); if (freeNnv) ABC_FREE(factorsNnv); return(NULL); } cuddRef(h2); Cudd_RecursiveDeref(dd, factorsNv->h); Cudd_RecursiveDeref(dd, factorsNnv->g); if (freeNv) ABC_FREE(factorsNv); if (freeNnv) ABC_FREE(factorsNnv); /* check for each pair in tables and choose one */ factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem); if (outOfMem) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); Cudd_RecursiveDeref(dd, g2); Cudd_RecursiveDeref(dd, h2); return(NULL); } if (factors != NULL) { if ((factors->g == g1) || (factors->g == h1)) { Cudd_RecursiveDeref(dd, g2); Cudd_RecursiveDeref(dd, h2); } else { Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); } return(factors); } /* if not in tables, pick one pair */ factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable); if (factors == NULL) { dd->errorCode = CUDD_MEMORY_OUT; Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); Cudd_RecursiveDeref(dd, g2); Cudd_RecursiveDeref(dd, h2); } else { /* now free what was created and not used */ if ((factors->g == g1) || (factors->g == h1)) { Cudd_RecursiveDeref(dd, g2); Cudd_RecursiveDeref(dd, h2); } else { Cudd_RecursiveDeref(dd, g1); Cudd_RecursiveDeref(dd, h1); } } return(factors); } /* end of BuildConjuncts */ /**Function******************************************************************** Synopsis [Procedure to compute two conjunctive factors of f and place in *c1 and *c2.] Description [Procedure to compute two conjunctive factors of f and place in *c1 and *c2. Sets up the required data - table of distances from the constant and local reference count. Also minterm table. ] SideEffects [] SeeAlso [] ******************************************************************************/ static int cuddConjunctsAux( DdManager * dd, DdNode * f, DdNode ** c1, DdNode ** c2) { st__table *distanceTable = NULL; st__table *cacheTable = NULL; st__table *mintermTable = NULL; st__table *ghTable = NULL; st__generator *stGen; char *key, *value; Conjuncts *factors; int distance, approxDistance; double max, minterms; int freeFactors; NodeStat *nodeStat; int maxLocalRef; /* initialize */ *c1 = NULL; *c2 = NULL; /* initialize distances table */ distanceTable = st__init_table( st__ptrcmp, st__ptrhash); if (distanceTable == NULL) goto outOfMem; /* make the entry for the constant */ nodeStat = ABC_ALLOC(NodeStat, 1); if (nodeStat == NULL) goto outOfMem; nodeStat->distance = 0; nodeStat->localRef = 1; if ( st__insert(distanceTable, (char *)one, (char *)nodeStat) == st__OUT_OF_MEM) { goto outOfMem; } /* Count node distances from constant. */ nodeStat = CreateBotDist(f, distanceTable); if (nodeStat == NULL) goto outOfMem; /* set the distance for the decomposition points */ approxDistance = (DEPTH < nodeStat->distance) ? nodeStat->distance : DEPTH; distance = nodeStat->distance; if (distance < approxDistance) { /* Too small to bother. */ *c1 = f; *c2 = DD_ONE(dd); cuddRef(*c1); cuddRef(*c2); stGen = st__init_gen(distanceTable); if (stGen == NULL) goto outOfMem; while( st__gen(stGen, (const char **)&key, (char **)&value)) { ABC_FREE(value); } st__free_gen(stGen); stGen = NULL; st__free_table(distanceTable); return(1); } /* record the maximum local reference count */ maxLocalRef = 0; stGen = st__init_gen(distanceTable); if (stGen == NULL) goto outOfMem; while( st__gen(stGen, (const char **)&key, (char **)&value)) { nodeStat = (NodeStat *)value; maxLocalRef = (nodeStat->localRef > maxLocalRef) ? nodeStat->localRef : maxLocalRef; } st__free_gen(stGen); stGen = NULL; /* Count minterms for each node. */ max = pow(2.0, (double)Cudd_SupportSize(dd,f)); /* potential overflow */ mintermTable = st__init_table( st__ptrcmp, st__ptrhash); if (mintermTable == NULL) goto outOfMem; minterms = CountMinterms(f, max, mintermTable, dd->err); if (minterms == -1.0) goto outOfMem; lastTimeG = Cudd_Random() & 1; cacheTable = st__init_table( st__ptrcmp, st__ptrhash); if (cacheTable == NULL) goto outOfMem; ghTable = st__init_table( st__ptrcmp, st__ptrhash); if (ghTable == NULL) goto outOfMem; /* Build conjuncts. */ factors = BuildConjuncts(dd, f, distanceTable, cacheTable, approxDistance, maxLocalRef, ghTable, mintermTable); if (factors == NULL) goto outOfMem; /* free up tables */ stGen = st__init_gen(distanceTable); if (stGen == NULL) goto outOfMem; while( st__gen(stGen, (const char **)&key, (char **)&value)) { ABC_FREE(value); } st__free_gen(stGen); stGen = NULL; st__free_table(distanceTable); distanceTable = NULL; st__free_table(ghTable); ghTable = NULL; stGen = st__init_gen(mintermTable); if (stGen == NULL) goto outOfMem; while( st__gen(stGen, (const char **)&key, (char **)&value)) { ABC_FREE(value); } st__free_gen(stGen); stGen = NULL; st__free_table(mintermTable); mintermTable = NULL; freeFactors = FactorsNotStored(factors); factors = (freeFactors) ? FactorsUncomplement(factors) : factors; if (factors != NULL) { *c1 = factors->g; *c2 = factors->h; cuddRef(*c1); cuddRef(*c2); if (freeFactors) ABC_FREE(factors); #if 0 if ((*c1 == f) && (!Cudd_IsConstant(f))) { assert(*c2 == one); } if ((*c2 == f) && (!Cudd_IsConstant(f))) { assert(*c1 == one); } if ((*c1 != one) && (!Cudd_IsConstant(f))) { assert(!Cudd_bddLeq(dd, *c2, *c1)); } if ((*c2 != one) && (!Cudd_IsConstant(f))) { assert(!Cudd_bddLeq(dd, *c1, *c2)); } #endif } stGen = st__init_gen(cacheTable); if (stGen == NULL) goto outOfMem; while( st__gen(stGen, (const char **)&key, (char **)&value)) { ConjunctsFree(dd, (Conjuncts *)value); } st__free_gen(stGen); stGen = NULL; st__free_table(cacheTable); cacheTable = NULL; return(1); outOfMem: if (distanceTable != NULL) { stGen = st__init_gen(distanceTable); if (stGen == NULL) goto outOfMem; while( st__gen(stGen, (const char **)&key, (char **)&value)) { ABC_FREE(value); } st__free_gen(stGen); stGen = NULL; st__free_table(distanceTable); distanceTable = NULL; } if (mintermTable != NULL) { stGen = st__init_gen(mintermTable); if (stGen == NULL) goto outOfMem; while( st__gen(stGen, (const char **)&key, (char **)&value)) { ABC_FREE(value); } st__free_gen(stGen); stGen = NULL; st__free_table(mintermTable); mintermTable = NULL; } if (ghTable != NULL) st__free_table(ghTable); if (cacheTable != NULL) { stGen = st__init_gen(cacheTable); if (stGen == NULL) goto outOfMem; while( st__gen(stGen, (const char **)&key, (char **)&value)) { ConjunctsFree(dd, (Conjuncts *)value); } st__free_gen(stGen); stGen = NULL; st__free_table(cacheTable); cacheTable = NULL; } dd->errorCode = CUDD_MEMORY_OUT; return(0); } /* end of cuddConjunctsAux */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddEssent.c000066400000000000000000001404621300674244400237600ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddEssent.c] PackageName [cudd] Synopsis [Functions for the detection of essential variables.] Description [External procedures included in this file:
  • Cudd_FindEssential()
  • Cudd_bddIsVarEssential()
  • Cudd_FindTwoLiteralClauses()
  • Cudd_ReadIthClause()
  • Cudd_PrintTwoLiteralClauses()
  • Cudd_tlcInfoFree()
Static procedures included in this module:
  • ddFindEssentialRecur()
  • ddFindTwoLiteralClausesRecur()
  • computeClauses()
  • computeClausesWithUniverse()
  • emptyClauseSet()
  • sentinelp()
  • equalp()
  • beforep()
  • oneliteralp()
  • impliedp()
  • bitVectorAlloc()
  • bitVectorClear()
  • bitVectorFree()
  • bitVectorRead()
  • bitVectorSet()
  • tlcInfoAlloc()
] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /* These definitions are for the bit vectors. */ #if SIZEOF_LONG == 8 #define BPL 64 #define LOGBPL 6 #else #define BPL 32 #define LOGBPL 5 #endif /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /* This structure holds the set of clauses for a node. Each clause consists ** of two literals. For one-literal clauses, the second lietral is FALSE. ** Each literal is composed of a variable and a phase. A variable is a node ** index, and requires sizeof(DdHalfWord) bytes. The constant literals use ** CUDD_MAXINDEX as variable indicator. Each phase is a bit: 0 for positive ** phase, and 1 for negative phase. ** Variables and phases are stored separately for the sake of compactness. ** The variables are stored in an array of DdHalfWord's terminated by a ** sentinel (a pair of zeroes). The phases are stored in a bit vector. ** The cnt field holds, at the end, the number of clauses. ** The clauses of the set are kept sorted. For each clause, the first literal ** is the one of least index. So, the clause with literals +2 and -4 is stored ** as (+2,-4). A one-literal clause with literal +3 is stored as ** (+3,-CUDD_MAXINDEX). Clauses are sorted in decreasing order as follows: ** (+5,-7) ** (+5,+6) ** (-5,+7) ** (-4,FALSE) ** (-4,+8) ** ... ** That is, one first looks at the variable of the first literal, then at the ** phase of the first litral, then at the variable of the second literal, ** and finally at the phase of the second literal. */ struct DdTlcInfo { DdHalfWord *vars; long *phases; DdHalfWord cnt; }; /* This structure is for temporary representation of sets of clauses. It is ** meant to be used in link lists, when the number of clauses is not yet ** known. The encoding of a clause is the same as in DdTlcInfo, though ** the phase information is not stored in a bit array. */ struct TlClause { DdHalfWord v1, v2; short p1, p2; struct TlClause *next; }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ typedef long BitVector; typedef struct TlClause TlClause; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddEssent.c,v 1.24 2009/02/21 18:24:10 fabio Exp $"; #endif static BitVector *Tolv; static BitVector *Tolp; static BitVector *Eolv; static BitVector *Eolp; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * ddFindEssentialRecur (DdManager *dd, DdNode *f); static DdTlcInfo * ddFindTwoLiteralClausesRecur (DdManager * dd, DdNode * f, st__table *table); static DdTlcInfo * computeClauses (DdTlcInfo *Tres, DdTlcInfo *Eres, DdHalfWord label, int size); static DdTlcInfo * computeClausesWithUniverse (DdTlcInfo *Cres, DdHalfWord label, short phase); static DdTlcInfo * emptyClauseSet (void); static int sentinelp (DdHalfWord var1, DdHalfWord var2); static int equalp (DdHalfWord var1a, short phase1a, DdHalfWord var1b, short phase1b, DdHalfWord var2a, short phase2a, DdHalfWord var2b, short phase2b); static int beforep (DdHalfWord var1a, short phase1a, DdHalfWord var1b, short phase1b, DdHalfWord var2a, short phase2a, DdHalfWord var2b, short phase2b); static int oneliteralp (DdHalfWord var); static int impliedp (DdHalfWord var1, short phase1, DdHalfWord var2, short phase2, BitVector *olv, BitVector *olp); static BitVector * bitVectorAlloc (int size); DD_INLINE static void bitVectorClear (BitVector *vector, int size); static void bitVectorFree (BitVector *vector); DD_INLINE static short bitVectorRead (BitVector *vector, int i); DD_INLINE static void bitVectorSet (BitVector * vector, int i, short val); static DdTlcInfo * tlcInfoAlloc (void); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Finds the essential variables of a DD.] Description [Returns the cube of the essential variables. A positive literal means that the variable must be set to 1 for the function to be 1. A negative literal means that the variable must be set to 0 for the function to be 1. Returns a pointer to the cube BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddIsVarEssential] ******************************************************************************/ DdNode * Cudd_FindEssential( DdManager * dd, DdNode * f) { DdNode *res; do { dd->reordered = 0; res = ddFindEssentialRecur(dd,f); } while (dd->reordered == 1); return(res); } /* end of Cudd_FindEssential */ /**Function******************************************************************** Synopsis [Determines whether a given variable is essential with a given phase in a BDD.] Description [Determines whether a given variable is essential with a given phase in a BDD. Uses Cudd_bddIteConstant. Returns 1 if phase == 1 and f-->x_id, or if phase == 0 and f-->x_id'.] SideEffects [None] SeeAlso [Cudd_FindEssential] ******************************************************************************/ int Cudd_bddIsVarEssential( DdManager * manager, DdNode * f, int id, int phase) { DdNode *var; int res; var = Cudd_bddIthVar(manager, id); var = Cudd_NotCond(var,phase == 0); res = Cudd_bddLeq(manager, f, var); return(res); } /* end of Cudd_bddIsVarEssential */ /**Function******************************************************************** Synopsis [Finds the two literal clauses of a DD.] Description [Returns the one- and two-literal clauses of a DD. Returns a pointer to the structure holding the clauses if successful; NULL otherwise. For a constant DD, the empty set of clauses is returned. This is obviously correct for a non-zero constant. For the constant zero, it is based on the assumption that only those clauses containing variables in the support of the function are considered. Since the support of a constant function is empty, no clauses are returned.] SideEffects [None] SeeAlso [Cudd_FindEssential] ******************************************************************************/ DdTlcInfo * Cudd_FindTwoLiteralClauses( DdManager * dd, DdNode * f) { DdTlcInfo *res; st__table *table; st__generator *gen; DdTlcInfo *tlc; DdNode *node; int size = dd->size; if (Cudd_IsConstant(f)) { res = emptyClauseSet(); return(res); } table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) return(NULL); Tolv = bitVectorAlloc(size); if (Tolv == NULL) { st__free_table(table); return(NULL); } Tolp = bitVectorAlloc(size); if (Tolp == NULL) { st__free_table(table); bitVectorFree(Tolv); return(NULL); } Eolv = bitVectorAlloc(size); if (Eolv == NULL) { st__free_table(table); bitVectorFree(Tolv); bitVectorFree(Tolp); return(NULL); } Eolp = bitVectorAlloc(size); if (Eolp == NULL) { st__free_table(table); bitVectorFree(Tolv); bitVectorFree(Tolp); bitVectorFree(Eolv); return(NULL); } res = ddFindTwoLiteralClausesRecur(dd,f,table); /* Dispose of table contents and free table. */ st__foreach_item(table, gen, (const char **)&node, (char **)&tlc) { if (node != f) { Cudd_tlcInfoFree(tlc); } } st__free_table(table); bitVectorFree(Tolv); bitVectorFree(Tolp); bitVectorFree(Eolv); bitVectorFree(Eolp); if (res != NULL) { int i; for (i = 0; !sentinelp(res->vars[i], res->vars[i+1]); i += 2); res->cnt = i >> 1; } return(res); } /* end of Cudd_FindTwoLiteralClauses */ /**Function******************************************************************** Synopsis [Accesses the i-th clause of a DD.] Description [Accesses the i-th clause of a DD given the clause set which must be already computed. Returns 1 if successful; 0 if i is out of range, or in case of error.] SideEffects [the four components of a clause are returned as side effects.] SeeAlso [Cudd_FindTwoLiteralClauses] ******************************************************************************/ int Cudd_ReadIthClause( DdTlcInfo * tlc, int i, DdHalfWord *var1, DdHalfWord *var2, int *phase1, int *phase2) { if (tlc == NULL) return(0); if (tlc->vars == NULL || tlc->phases == NULL) return(0); if (i < 0 || (unsigned) i >= tlc->cnt) return(0); *var1 = tlc->vars[2*i]; *var2 = tlc->vars[2*i+1]; *phase1 = (int) bitVectorRead(tlc->phases, 2*i); *phase2 = (int) bitVectorRead(tlc->phases, 2*i+1); return(1); } /* end of Cudd_ReadIthClause */ /**Function******************************************************************** Synopsis [Prints the two literal clauses of a DD.] Description [Prints the one- and two-literal clauses. Returns 1 if successful; 0 otherwise. The argument "names" can be NULL, in which case the variable indices are printed.] SideEffects [None] SeeAlso [Cudd_FindTwoLiteralClauses] ******************************************************************************/ int Cudd_PrintTwoLiteralClauses( DdManager * dd, DdNode * f, char **names, FILE *fp) { DdHalfWord *vars; BitVector *phases; int i; DdTlcInfo *res = Cudd_FindTwoLiteralClauses(dd, f); FILE *ifp = fp == NULL ? dd->out : fp; if (res == NULL) return(0); vars = res->vars; phases = res->phases; for (i = 0; !sentinelp(vars[i], vars[i+1]); i += 2) { if (names != NULL) { if (vars[i+1] == CUDD_MAXINDEX) { (void) fprintf(ifp, "%s%s\n", bitVectorRead(phases, i) ? "~" : " ", names[vars[i]]); } else { (void) fprintf(ifp, "%s%s | %s%s\n", bitVectorRead(phases, i) ? "~" : " ", names[vars[i]], bitVectorRead(phases, i+1) ? "~" : " ", names[vars[i+1]]); } } else { if (vars[i+1] == CUDD_MAXINDEX) { (void) fprintf(ifp, "%s%d\n", bitVectorRead(phases, i) ? "~" : " ", (int) vars[i]); } else { (void) fprintf(ifp, "%s%d | %s%d\n", bitVectorRead(phases, i) ? "~" : " ", (int) vars[i], bitVectorRead(phases, i+1) ? "~" : " ", (int) vars[i+1]); } } } Cudd_tlcInfoFree(res); return(1); } /* end of Cudd_PrintTwoLiteralClauses */ /**Function******************************************************************** Synopsis [Frees a DdTlcInfo Structure.] Description [Frees a DdTlcInfo Structure as well as the memory pointed by it.] SideEffects [None] SeeAlso [] ******************************************************************************/ void Cudd_tlcInfoFree( DdTlcInfo * t) { if (t->vars != NULL) ABC_FREE(t->vars); if (t->phases != NULL) ABC_FREE(t->phases); ABC_FREE(t); } /* end of Cudd_tlcInfoFree */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_FindEssential.] Description [Implements the recursive step of Cudd_FindEssential. Returns a pointer to the cube BDD if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ static DdNode * ddFindEssentialRecur( DdManager * dd, DdNode * f) { DdNode *T, *E, *F; DdNode *essT, *essE, *res; int index; DdNode *one, *lzero, *azero; one = DD_ONE(dd); F = Cudd_Regular(f); /* If f is constant the set of essential variables is empty. */ if (cuddIsConstant(F)) return(one); res = cuddCacheLookup1(dd,Cudd_FindEssential,f); if (res != NULL) { return(res); } lzero = Cudd_Not(one); azero = DD_ZERO(dd); /* Find cofactors: here f is non-constant. */ T = cuddT(F); E = cuddE(F); if (Cudd_IsComplement(f)) { T = Cudd_Not(T); E = Cudd_Not(E); } index = F->index; if (Cudd_IsConstant(T) && T != lzero && T != azero) { /* if E is zero, index is essential, otherwise there are no ** essentials, because index is not essential and no other variable ** can be, since setting index = 1 makes the function constant and ** different from 0. */ if (E == lzero || E == azero) { res = dd->vars[index]; } else { res = one; } } else if (T == lzero || T == azero) { if (Cudd_IsConstant(E)) { /* E cannot be zero here */ res = Cudd_Not(dd->vars[index]); } else { /* E == non-constant */ /* find essentials in the else branch */ essE = ddFindEssentialRecur(dd,E); if (essE == NULL) { return(NULL); } cuddRef(essE); /* add index to the set with negative phase */ res = cuddUniqueInter(dd,index,one,Cudd_Not(essE)); if (res == NULL) { Cudd_RecursiveDeref(dd,essE); return(NULL); } res = Cudd_Not(res); cuddDeref(essE); } } else { /* T == non-const */ if (E == lzero || E == azero) { /* find essentials in the then branch */ essT = ddFindEssentialRecur(dd,T); if (essT == NULL) { return(NULL); } cuddRef(essT); /* add index to the set with positive phase */ /* use And because essT may be complemented */ res = cuddBddAndRecur(dd,dd->vars[index],essT); if (res == NULL) { Cudd_RecursiveDeref(dd,essT); return(NULL); } cuddDeref(essT); } else if (!Cudd_IsConstant(E)) { /* if E is a non-zero constant there are no essentials ** because T is non-constant. */ essT = ddFindEssentialRecur(dd,T); if (essT == NULL) { return(NULL); } if (essT == one) { res = one; } else { cuddRef(essT); essE = ddFindEssentialRecur(dd,E); if (essE == NULL) { Cudd_RecursiveDeref(dd,essT); return(NULL); } cuddRef(essE); /* res = intersection(essT, essE) */ res = cuddBddLiteralSetIntersectionRecur(dd,essT,essE); if (res == NULL) { Cudd_RecursiveDeref(dd,essT); Cudd_RecursiveDeref(dd,essE); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd,essT); Cudd_RecursiveDeref(dd,essE); cuddDeref(res); } } else { /* E is a non-zero constant */ res = one; } } cuddCacheInsert1(dd,Cudd_FindEssential, f, res); return(res); } /* end of ddFindEssentialRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_FindTwoLiteralClauses.] Description [Implements the recursive step of Cudd_FindTwoLiteralClauses. The DD node is assumed to be not constant. Returns a pointer to a set of clauses if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_FindTwoLiteralClauses] ******************************************************************************/ static DdTlcInfo * ddFindTwoLiteralClausesRecur( DdManager * dd, DdNode * f, st__table *table) { DdNode *T, *E, *F; DdNode *one, *lzero, *azero; DdTlcInfo *res, *Tres, *Eres; DdHalfWord index; F = Cudd_Regular(f); assert(!cuddIsConstant(F)); /* Check computed table. Separate entries are necessary for ** a node and its complement. We should update the counter here. */ if ( st__lookup(table, (const char *)f, (char **)&res)) { return(res); } /* Easy access to the constants for BDDs and ADDs. */ one = DD_ONE(dd); lzero = Cudd_Not(one); azero = DD_ZERO(dd); /* Find cofactors and variable labeling the top node. */ T = cuddT(F); E = cuddE(F); if (Cudd_IsComplement(f)) { T = Cudd_Not(T); E = Cudd_Not(E); } index = F->index; if (Cudd_IsConstant(T) && T != lzero && T != azero) { /* T is a non-zero constant. If E is zero, then this node's index ** is a one-literal clause. Otherwise, if E is a non-zero ** constant, there are no clauses for this node. Finally, ** if E is not constant, we recursively compute its clauses, and then ** merge using the empty set for T. */ if (E == lzero || E == azero) { /* Create the clause (index + 0). */ res = tlcInfoAlloc(); if (res == NULL) return(NULL); res->vars = ABC_ALLOC(DdHalfWord,4); if (res->vars == NULL) { ABC_FREE(res); return(NULL); } res->phases = bitVectorAlloc(2); if (res->phases == NULL) { ABC_FREE(res->vars); ABC_FREE(res); return(NULL); } res->vars[0] = index; res->vars[1] = CUDD_MAXINDEX; res->vars[2] = 0; res->vars[3] = 0; bitVectorSet(res->phases, 0, 0); /* positive phase */ bitVectorSet(res->phases, 1, 1); /* negative phase */ } else if (Cudd_IsConstant(E)) { /* If E is a non-zero constant, no clauses. */ res = emptyClauseSet(); } else { /* E is non-constant */ Tres = emptyClauseSet(); if (Tres == NULL) return(NULL); Eres = ddFindTwoLiteralClausesRecur(dd, E, table); if (Eres == NULL) { Cudd_tlcInfoFree(Tres); return(NULL); } res = computeClauses(Tres, Eres, index, dd->size); Cudd_tlcInfoFree(Tres); } } else if (T == lzero || T == azero) { /* T is zero. If E is a non-zero constant, then the ** complement of this node's index is a one-literal clause. ** Otherwise, if E is not constant, we recursively compute its ** clauses, and then merge using the universal set for T. */ if (Cudd_IsConstant(E)) { /* E cannot be zero here */ /* Create the clause (!index + 0). */ res = tlcInfoAlloc(); if (res == NULL) return(NULL); res->vars = ABC_ALLOC(DdHalfWord,4); if (res->vars == NULL) { ABC_FREE(res); return(NULL); } res->phases = bitVectorAlloc(2); if (res->phases == NULL) { ABC_FREE(res->vars); ABC_FREE(res); return(NULL); } res->vars[0] = index; res->vars[1] = CUDD_MAXINDEX; res->vars[2] = 0; res->vars[3] = 0; bitVectorSet(res->phases, 0, 1); /* negative phase */ bitVectorSet(res->phases, 1, 1); /* negative phase */ } else { /* E == non-constant */ Eres = ddFindTwoLiteralClausesRecur(dd, E, table); if (Eres == NULL) return(NULL); res = computeClausesWithUniverse(Eres, index, 1); } } else { /* T == non-const */ Tres = ddFindTwoLiteralClausesRecur(dd, T, table); if (Tres == NULL) return(NULL); if (Cudd_IsConstant(E)) { if (E == lzero || E == azero) { res = computeClausesWithUniverse(Tres, index, 0); } else { Eres = emptyClauseSet(); if (Eres == NULL) return(NULL); res = computeClauses(Tres, Eres, index, dd->size); Cudd_tlcInfoFree(Eres); } } else { Eres = ddFindTwoLiteralClausesRecur(dd, E, table); if (Eres == NULL) return(NULL); res = computeClauses(Tres, Eres, index, dd->size); } } /* Cache results. */ if ( st__add_direct(table, (char *)f, (char *)res) == st__OUT_OF_MEM) { ABC_FREE(res); return(NULL); } return(res); } /* end of ddFindTwoLiteralClausesRecur */ /**Function******************************************************************** Synopsis [Computes the two-literal clauses for a node.] Description [Computes the two-literal clauses for a node given the clauses for its children and the label of the node. Returns a pointer to a TclInfo structure if successful; NULL otherwise.] SideEffects [None] SeeAlso [computeClausesWithUniverse] ******************************************************************************/ static DdTlcInfo * computeClauses( DdTlcInfo *Tres /* list of clauses for T child */, DdTlcInfo *Eres /* list of clauses for E child */, DdHalfWord label /* variable labeling the current node */, int size /* number of variables in the manager */) { DdHalfWord *Tcv = Tres->vars; /* variables of clauses for the T child */ BitVector *Tcp = Tres->phases; /* phases of clauses for the T child */ DdHalfWord *Ecv = Eres->vars; /* variables of clauses for the E child */ BitVector *Ecp = Eres->phases; /* phases of clauses for the E child */ DdHalfWord *Vcv = NULL; /* pointer to variables of the clauses for v */ BitVector *Vcp = NULL; /* pointer to phases of the clauses for v */ DdTlcInfo *res = NULL; /* the set of clauses to be returned */ int pt = 0; /* index in the list of clauses of T */ int pe = 0; /* index in the list of clauses of E */ int cv = 0; /* counter of the clauses for this node */ TlClause *iclauses = NULL; /* list of inherited clauses */ TlClause *tclauses = NULL; /* list of 1-literal clauses of T */ TlClause *eclauses = NULL; /* list of 1-literal clauses of E */ TlClause *nclauses = NULL; /* list of new (non-inherited) clauses */ TlClause *lnclause = NULL; /* pointer to last new clause */ TlClause *newclause; /* temporary pointer to new clauses */ /* Initialize sets of one-literal clauses. The one-literal clauses ** are stored redundantly. These sets allow constant-time lookup, which ** we need when we check for implication of a two-literal clause by a ** one-literal clause. The linked lists allow fast sequential ** processing. */ bitVectorClear(Tolv, size); bitVectorClear(Tolp, size); bitVectorClear(Eolv, size); bitVectorClear(Eolp, size); /* Initialize result structure. */ res = tlcInfoAlloc(); if (res == NULL) goto cleanup; /* Scan the two input list. Extract inherited two-literal clauses ** and set aside one-literal clauses from each list. The incoming lists ** are sorted in the order defined by beforep. The three linked list ** produced by this loop are sorted in the reverse order because we ** always append to the front of the lists. ** The inherited clauses are those clauses (both one- and two-literal) ** that are common to both children; and the two-literal clauses of ** one child that are implied by a one-literal clause of the other ** child. */ while (!sentinelp(Tcv[pt], Tcv[pt+1]) || !sentinelp(Ecv[pe], Ecv[pe+1])) { if (equalp(Tcv[pt], bitVectorRead(Tcp, pt), Tcv[pt+1], bitVectorRead(Tcp, pt+1), Ecv[pe], bitVectorRead(Ecp, pe), Ecv[pe+1], bitVectorRead(Ecp, pe+1))) { /* Add clause to inherited list. */ newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = Tcv[pt]; newclause->v2 = Tcv[pt+1]; newclause->p1 = bitVectorRead(Tcp, pt); newclause->p2 = bitVectorRead(Tcp, pt+1); newclause->next = iclauses; iclauses = newclause; pt += 2; pe += 2; cv++; } else if (beforep(Tcv[pt], bitVectorRead(Tcp, pt), Tcv[pt+1], bitVectorRead(Tcp, pt+1), Ecv[pe], bitVectorRead(Ecp, pe), Ecv[pe+1], bitVectorRead(Ecp, pe+1))) { if (oneliteralp(Tcv[pt+1])) { /* Add this one-literal clause to the T set. */ newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = Tcv[pt]; newclause->v2 = CUDD_MAXINDEX; newclause->p1 = bitVectorRead(Tcp, pt); newclause->p2 = 1; newclause->next = tclauses; tclauses = newclause; bitVectorSet(Tolv, Tcv[pt], 1); bitVectorSet(Tolp, Tcv[pt], bitVectorRead(Tcp, pt)); } else { if (impliedp(Tcv[pt], bitVectorRead(Tcp, pt), Tcv[pt+1], bitVectorRead(Tcp, pt+1), Eolv, Eolp)) { /* Add clause to inherited list. */ newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = Tcv[pt]; newclause->v2 = Tcv[pt+1]; newclause->p1 = bitVectorRead(Tcp, pt); newclause->p2 = bitVectorRead(Tcp, pt+1); newclause->next = iclauses; iclauses = newclause; cv++; } } pt += 2; } else { /* !beforep() */ if (oneliteralp(Ecv[pe+1])) { /* Add this one-literal clause to the E set. */ newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = Ecv[pe]; newclause->v2 = CUDD_MAXINDEX; newclause->p1 = bitVectorRead(Ecp, pe); newclause->p2 = 1; newclause->next = eclauses; eclauses = newclause; bitVectorSet(Eolv, Ecv[pe], 1); bitVectorSet(Eolp, Ecv[pe], bitVectorRead(Ecp, pe)); } else { if (impliedp(Ecv[pe], bitVectorRead(Ecp, pe), Ecv[pe+1], bitVectorRead(Ecp, pe+1), Tolv, Tolp)) { /* Add clause to inherited list. */ newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = Ecv[pe]; newclause->v2 = Ecv[pe+1]; newclause->p1 = bitVectorRead(Ecp, pe); newclause->p2 = bitVectorRead(Ecp, pe+1); newclause->next = iclauses; iclauses = newclause; cv++; } } pe += 2; } } /* Add one-literal clauses for the label variable to the front of ** the two lists. */ newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = label; newclause->v2 = CUDD_MAXINDEX; newclause->p1 = 0; newclause->p2 = 1; newclause->next = tclauses; tclauses = newclause; newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = label; newclause->v2 = CUDD_MAXINDEX; newclause->p1 = 1; newclause->p2 = 1; newclause->next = eclauses; eclauses = newclause; /* Produce the non-inherited clauses. We preserve the "reverse" ** order of the two input lists by appending to the end of the ** list. In this way, iclauses and nclauses are consistent. */ while (tclauses != NULL && eclauses != NULL) { if (beforep(eclauses->v1, eclauses->p1, eclauses->v2, eclauses->p2, tclauses->v1, tclauses->p1, tclauses->v2, tclauses->p2)) { TlClause *nextclause = tclauses->next; TlClause *otherclauses = eclauses; while (otherclauses != NULL) { if (tclauses->v1 != otherclauses->v1) { newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = tclauses->v1; newclause->v2 = otherclauses->v1; newclause->p1 = tclauses->p1; newclause->p2 = otherclauses->p1; newclause->next = NULL; if (nclauses == NULL) { nclauses = newclause; lnclause = newclause; } else { lnclause->next = newclause; lnclause = newclause; } cv++; } otherclauses = otherclauses->next; } ABC_FREE(tclauses); tclauses = nextclause; } else { TlClause *nextclause = eclauses->next; TlClause *otherclauses = tclauses; while (otherclauses != NULL) { if (eclauses->v1 != otherclauses->v1) { newclause = ABC_ALLOC(TlClause,1); if (newclause == NULL) goto cleanup; newclause->v1 = eclauses->v1; newclause->v2 = otherclauses->v1; newclause->p1 = eclauses->p1; newclause->p2 = otherclauses->p1; newclause->next = NULL; if (nclauses == NULL) { nclauses = newclause; lnclause = newclause; } else { lnclause->next = newclause; lnclause = newclause; } cv++; } otherclauses = otherclauses->next; } ABC_FREE(eclauses); eclauses = nextclause; } } while (tclauses != NULL) { TlClause *nextclause = tclauses->next; ABC_FREE(tclauses); tclauses = nextclause; } while (eclauses != NULL) { TlClause *nextclause = eclauses->next; ABC_FREE(eclauses); eclauses = nextclause; } /* Merge inherited and non-inherited clauses. Now that we know the ** total number, we allocate the arrays, and we fill them bottom-up ** to restore the proper ordering. */ Vcv = ABC_ALLOC(DdHalfWord, 2*(cv+1)); if (Vcv == NULL) goto cleanup; if (cv > 0) { Vcp = bitVectorAlloc(2*cv); if (Vcp == NULL) goto cleanup; } else { Vcp = NULL; } res->vars = Vcv; res->phases = Vcp; /* Add sentinel. */ Vcv[2*cv] = 0; Vcv[2*cv+1] = 0; while (iclauses != NULL || nclauses != NULL) { TlClause *nextclause; cv--; if (nclauses == NULL || (iclauses != NULL && beforep(nclauses->v1, nclauses->p1, nclauses->v2, nclauses->p2, iclauses->v1, iclauses->p1, iclauses->v2, iclauses->p2))) { Vcv[2*cv] = iclauses->v1; Vcv[2*cv+1] = iclauses->v2; bitVectorSet(Vcp, 2*cv, iclauses->p1); bitVectorSet(Vcp, 2*cv+1, iclauses->p2); nextclause = iclauses->next; ABC_FREE(iclauses); iclauses = nextclause; } else { Vcv[2*cv] = nclauses->v1; Vcv[2*cv+1] = nclauses->v2; bitVectorSet(Vcp, 2*cv, nclauses->p1); bitVectorSet(Vcp, 2*cv+1, nclauses->p2); nextclause = nclauses->next; ABC_FREE(nclauses); nclauses = nextclause; } } assert(cv == 0); return(res); cleanup: if (res != NULL) Cudd_tlcInfoFree(res); while (iclauses != NULL) { TlClause *nextclause = iclauses->next; ABC_FREE(iclauses); iclauses = nextclause; } while (nclauses != NULL) { TlClause *nextclause = nclauses->next; ABC_FREE(nclauses); nclauses = nextclause; } while (tclauses != NULL) { TlClause *nextclause = tclauses->next; ABC_FREE(tclauses); tclauses = nextclause; } while (eclauses != NULL) { TlClause *nextclause = eclauses->next; ABC_FREE(eclauses); eclauses = nextclause; } return(NULL); } /* end of computeClauses */ /**Function******************************************************************** Synopsis [Computes the two-literal clauses for a node.] Description [Computes the two-literal clauses for a node with a zero child, given the clauses for its other child and the label of the node. Returns a pointer to a TclInfo structure if successful; NULL otherwise.] SideEffects [None] SeeAlso [computeClauses] ******************************************************************************/ static DdTlcInfo * computeClausesWithUniverse( DdTlcInfo *Cres /* list of clauses for child */, DdHalfWord label /* variable labeling the current node */, short phase /* 0 if E child is zero; 1 if T child is zero */) { DdHalfWord *Ccv = Cres->vars; /* variables of clauses for child */ BitVector *Ccp = Cres->phases; /* phases of clauses for child */ DdHalfWord *Vcv = NULL; /* pointer to the variables of the clauses for v */ BitVector *Vcp = NULL; /* pointer to the phases of the clauses for v */ DdTlcInfo *res = NULL; /* the set of clauses to be returned */ int i; /* Initialize result. */ res = tlcInfoAlloc(); if (res == NULL) goto cleanup; /* Count entries for new list and allocate accordingly. */ for (i = 0; !sentinelp(Ccv[i], Ccv[i+1]); i += 2); /* At this point, i is twice the number of clauses in the child's ** list. We need four more entries for this node: 2 for the one-literal ** clause for the label, and 2 for the sentinel. */ Vcv = ABC_ALLOC(DdHalfWord,i+4); if (Vcv == NULL) goto cleanup; Vcp = bitVectorAlloc(i+4); if (Vcp == NULL) goto cleanup; res->vars = Vcv; res->phases = Vcp; /* Copy old list into new. */ for (i = 0; !sentinelp(Ccv[i], Ccv[i+1]); i += 2) { Vcv[i] = Ccv[i]; Vcv[i+1] = Ccv[i+1]; bitVectorSet(Vcp, i, bitVectorRead(Ccp, i)); bitVectorSet(Vcp, i+1, bitVectorRead(Ccp, i+1)); } /* Add clause corresponding to label. */ Vcv[i] = label; bitVectorSet(Vcp, i, phase); i++; Vcv[i] = CUDD_MAXINDEX; bitVectorSet(Vcp, i, 1); i++; /* Add sentinel. */ Vcv[i] = 0; Vcv[i+1] = 0; bitVectorSet(Vcp, i, 0); bitVectorSet(Vcp, i+1, 0); return(res); cleanup: /* Vcp is guaranteed to be NULL here. Hence, we do not try to free it. */ if (Vcv != NULL) ABC_FREE(Vcv); if (res != NULL) Cudd_tlcInfoFree(res); return(NULL); } /* end of computeClausesWithUniverse */ /**Function******************************************************************** Synopsis [Returns an enpty set of clauses.] Description [Returns a pointer to an empty set of clauses if successful; NULL otherwise. No bit vector for the phases is allocated.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdTlcInfo * emptyClauseSet(void) { DdTlcInfo *eset; eset = ABC_ALLOC(DdTlcInfo,1); if (eset == NULL) return(NULL); eset->vars = ABC_ALLOC(DdHalfWord,2); if (eset->vars == NULL) { ABC_FREE(eset); return(NULL); } /* Sentinel */ eset->vars[0] = 0; eset->vars[1] = 0; eset->phases = NULL; /* does not matter */ eset->cnt = 0; return(eset); } /* end of emptyClauseSet */ /**Function******************************************************************** Synopsis [Returns true iff the argument is the sentinel clause.] Description [Returns true iff the argument is the sentinel clause. A sentinel clause has both variables equal to 0.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int sentinelp( DdHalfWord var1, DdHalfWord var2) { return(var1 == 0 && var2 == 0); } /* end of sentinelp */ /**Function******************************************************************** Synopsis [Returns true iff the two arguments are identical clauses.] Description [Returns true iff the two arguments are identical clauses. Since literals are sorted, we only need to compare literals in the same position.] SideEffects [None] SeeAlso [beforep] ******************************************************************************/ static int equalp( DdHalfWord var1a, short phase1a, DdHalfWord var1b, short phase1b, DdHalfWord var2a, short phase2a, DdHalfWord var2b, short phase2b) { return(var1a == var2a && phase1a == phase2a && var1b == var2b && phase1b == phase2b); } /* end of equalp */ /**Function******************************************************************** Synopsis [Returns true iff the first argument precedes the second in the clause order.] Description [Returns true iff the first argument precedes the second in the clause order. A clause precedes another if its first lieral precedes the first literal of the other, or if the first literals are the same, and its second literal precedes the second literal of the other clause. A literal precedes another if it has a higher index, of if it has the same index, but it has lower phase. Phase 0 is the positive phase, and it is lower than Phase 1 (negative phase).] SideEffects [None] SeeAlso [equalp] ******************************************************************************/ static int beforep( DdHalfWord var1a, short phase1a, DdHalfWord var1b, short phase1b, DdHalfWord var2a, short phase2a, DdHalfWord var2b, short phase2b) { return(var1a > var2a || (var1a == var2a && (phase1a < phase2a || (phase1a == phase2a && (var1b > var2b || (var1b == var2b && phase1b < phase2b)))))); } /* end of beforep */ /**Function******************************************************************** Synopsis [Returns true iff the argument is a one-literal clause.] Description [Returns true iff the argument is a one-literal clause. A one-litaral clause has the constant FALSE as second literal. Since the constant TRUE is never used, it is sufficient to test for a constant.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int oneliteralp( DdHalfWord var) { return(var == CUDD_MAXINDEX); } /* end of oneliteralp */ /**Function******************************************************************** Synopsis [Returns true iff either literal of a clause is in a set of literals.] Description [Returns true iff either literal of a clause is in a set of literals. The first four arguments specify the clause. The remaining two arguments specify the literal set.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int impliedp( DdHalfWord var1, short phase1, DdHalfWord var2, short phase2, BitVector *olv, BitVector *olp) { return((bitVectorRead(olv, var1) && bitVectorRead(olp, var1) == phase1) || (bitVectorRead(olv, var2) && bitVectorRead(olp, var2) == phase2)); } /* end of impliedp */ /**Function******************************************************************** Synopsis [Allocates a bit vector.] Description [Allocates a bit vector. The parameter size gives the number of bits. This procedure allocates enough long's to hold the specified number of bits. Returns a pointer to the allocated vector if successful; NULL otherwise.] SideEffects [None] SeeAlso [bitVectorClear bitVectorFree] ******************************************************************************/ static BitVector * bitVectorAlloc( int size) { int allocSize; BitVector *vector; /* Find out how many long's we need. ** There are sizeof(long) * 8 bits in a long. ** The ceiling of the ratio of two integers m and n is given ** by ((n-1)/m)+1. Putting all this together, we get... */ allocSize = ((size - 1) / (sizeof(BitVector) * 8)) + 1; vector = ABC_ALLOC(BitVector, allocSize); if (vector == NULL) return(NULL); /* Clear the whole array. */ (void) memset(vector, 0, allocSize * sizeof(BitVector)); return(vector); } /* end of bitVectorAlloc */ /**Function******************************************************************** Synopsis [Clears a bit vector.] Description [Clears a bit vector. The parameter size gives the number of bits.] SideEffects [None] SeeAlso [bitVectorAlloc] ******************************************************************************/ DD_INLINE static void bitVectorClear( BitVector *vector, int size) { int allocSize; /* Find out how many long's we need. ** There are sizeof(long) * 8 bits in a long. ** The ceiling of the ratio of two integers m and n is given ** by ((n-1)/m)+1. Putting all this together, we get... */ allocSize = ((size - 1) / (sizeof(BitVector) * 8)) + 1; /* Clear the whole array. */ (void) memset(vector, 0, allocSize * sizeof(BitVector)); return; } /* end of bitVectorClear */ /**Function******************************************************************** Synopsis [Frees a bit vector.] Description [Frees a bit vector.] SideEffects [None] SeeAlso [bitVectorAlloc] ******************************************************************************/ static void bitVectorFree( BitVector *vector) { ABC_FREE(vector); } /* end of bitVectorFree */ /**Function******************************************************************** Synopsis [Returns the i-th entry of a bit vector.] Description [Returns the i-th entry of a bit vector.] SideEffects [None] SeeAlso [bitVectorSet] ******************************************************************************/ DD_INLINE static short bitVectorRead( BitVector *vector, int i) { int word, bit; short result; if (vector == NULL) return((short) 0); word = i >> LOGBPL; bit = i & (BPL - 1); result = (short) ((vector[word] >> bit) & 1L); return(result); } /* end of bitVectorRead */ /**Function******************************************************************** Synopsis [Sets the i-th entry of a bit vector to a value.] Description [Sets the i-th entry of a bit vector to a value.] SideEffects [None] SeeAlso [bitVectorRead] ******************************************************************************/ DD_INLINE static void bitVectorSet( BitVector * vector, int i, short val) { int word, bit; word = i >> LOGBPL; bit = i & (BPL - 1); vector[word] &= ~(1L << bit); vector[word] |= (((long) val) << bit); } /* end of bitVectorSet */ /**Function******************************************************************** Synopsis [Allocates a DdTlcInfo Structure.] Description [Returns a pointer to a DdTlcInfo Structure if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_tlcInfoFree] ******************************************************************************/ static DdTlcInfo * tlcInfoAlloc(void) { DdTlcInfo *res = ABC_ALLOC(DdTlcInfo,1); if (res == NULL) return(NULL); res->vars = NULL; res->phases = NULL; res->cnt = 0; return(res); } /* end of tlcInfoAlloc */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddExact.c000066400000000000000000000753561300674244400235740ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddExact.c] PackageName [cudd] Synopsis [Functions for exact variable reordering.] Description [External procedures included in this file:
Internal procedures included in this module:
  • cuddExact()
Static procedures included in this module:
  • getMaxBinomial()
  • gcd()
  • getMatrix()
  • freeMatrix()
  • getLevelKeys()
  • ddShuffle()
  • ddSiftUp()
  • updateUB()
  • ddCountRoots()
  • ddClearGlobal()
  • computeLB()
  • updateEntry()
  • pushDown()
  • initSymmInfo()
] Author [Cheng Hua, Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.28 2009/02/19 16:19:19 fabio Exp $"; #endif #ifdef DD_STATS static int ddTotalShuffles; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int getMaxBinomial (int n); static DdHalfWord ** getMatrix (int rows, int cols); static void freeMatrix (DdHalfWord **matrix); static int getLevelKeys (DdManager *table, int l); static int ddShuffle (DdManager *table, DdHalfWord *permutation, int lower, int upper); static int ddSiftUp (DdManager *table, int x, int xLow); static int updateUB (DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper); static int ddCountRoots (DdManager *table, int lower, int upper); static void ddClearGlobal (DdManager *table, int lower, int maxlevel); static int computeLB (DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level); static int updateEntry (DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper); static void pushDown (DdHalfWord *order, int j, int level); static DdHalfWord * initSymmInfo (DdManager *table, int lower, int upper); static int checkSymmInfo (DdManager *table, DdHalfWord *symmInfo, int index, int level); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Exact variable ordering algorithm.] Description [Exact variable ordering algorithm. Finds an optimum order for the variables between lower and upper. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddExact( DdManager * table, int lower, int upper) { int k, i, j; int maxBinomial, oldSubsets, newSubsets; int subsetCost; int size; /* number of variables to be reordered */ int unused, nvars, level, result; int upperBound, lowerBound, cost; int roots; char *mask = NULL; DdHalfWord *symmInfo = NULL; DdHalfWord **newOrder = NULL; DdHalfWord **oldOrder = NULL; int *newCost = NULL; int *oldCost = NULL; DdHalfWord **tmpOrder; int *tmpCost; DdHalfWord *bestOrder = NULL; DdHalfWord *order; #ifdef DD_STATS int ddTotalSubsets; #endif /* Restrict the range to be reordered by excluding unused variables ** at the two ends. */ while (table->subtables[lower].keys == 1 && table->vars[table->invperm[lower]]->ref == 1 && lower < upper) lower++; while (table->subtables[upper].keys == 1 && table->vars[table->invperm[upper]]->ref == 1 && lower < upper) upper--; if (lower == upper) return(1); /* trivial problem */ /* Apply symmetric sifting to get a good upper bound and to extract ** symmetry information. */ result = cuddSymmSiftingConv(table,lower,upper); if (result == 0) goto cuddExactOutOfMem; #ifdef DD_STATS (void) fprintf(table->out,"\n"); ddTotalShuffles = 0; ddTotalSubsets = 0; #endif /* Initialization. */ nvars = table->size; size = upper - lower + 1; /* Count unused variable among those to be reordered. This is only ** used to compute maxBinomial. */ unused = 0; for (i = lower + 1; i < upper; i++) { if (table->subtables[i].keys == 1 && table->vars[table->invperm[i]]->ref == 1) unused++; } /* Find the maximum number of subsets we may have to store. */ maxBinomial = getMaxBinomial(size - unused); if (maxBinomial == -1) goto cuddExactOutOfMem; newOrder = getMatrix(maxBinomial, size); if (newOrder == NULL) goto cuddExactOutOfMem; newCost = ABC_ALLOC(int, maxBinomial); if (newCost == NULL) goto cuddExactOutOfMem; oldOrder = getMatrix(maxBinomial, size); if (oldOrder == NULL) goto cuddExactOutOfMem; oldCost = ABC_ALLOC(int, maxBinomial); if (oldCost == NULL) goto cuddExactOutOfMem; bestOrder = ABC_ALLOC(DdHalfWord, size); if (bestOrder == NULL) goto cuddExactOutOfMem; mask = ABC_ALLOC(char, nvars); if (mask == NULL) goto cuddExactOutOfMem; symmInfo = initSymmInfo(table, lower, upper); if (symmInfo == NULL) goto cuddExactOutOfMem; roots = ddCountRoots(table, lower, upper); /* Initialize the old order matrix for the empty subset and the best ** order to the current order. The cost for the empty subset includes ** the cost of the levels between upper and the constants. These levels ** are not going to change. Hence, we count them only once. */ oldSubsets = 1; for (i = 0; i < size; i++) { oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower]; } subsetCost = table->constants.keys; for (i = upper + 1; i < nvars; i++) subsetCost += getLevelKeys(table,i); oldCost[0] = subsetCost; /* The upper bound is initialized to the current size of the BDDs. */ upperBound = table->keys - table->isolated; /* Now consider subsets of increasing size. */ for (k = 1; k <= size; k++) { #ifdef DD_STATS (void) fprintf(table->out,"Processing subsets of size %d\n", k); fflush(table->out); #endif newSubsets = 0; level = size - k; /* offset of first bottom variable */ for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */ order = oldOrder[i]; cost = oldCost[i]; lowerBound = computeLB(table, order, roots, cost, lower, upper, level); if (lowerBound >= upperBound) continue; /* Impose new order. */ result = ddShuffle(table, order, lower, upper); if (result == 0) goto cuddExactOutOfMem; upperBound = updateUB(table,upperBound,bestOrder,lower,upper); /* For each top bottom variable. */ for (j = level; j >= 0; j--) { /* Skip unused variables. */ if (table->subtables[j+lower-1].keys == 1 && table->vars[table->invperm[j+lower-1]]->ref == 1) continue; /* Find cost under this order. */ subsetCost = cost + getLevelKeys(table, lower + level); newSubsets = updateEntry(table, order, level, subsetCost, newOrder, newCost, newSubsets, mask, lower, upper); if (j == 0) break; if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0) continue; pushDown(order,j-1,level); /* Impose new order. */ result = ddShuffle(table, order, lower, upper); if (result == 0) goto cuddExactOutOfMem; upperBound = updateUB(table,upperBound,bestOrder,lower,upper); } /* for each bottom variable */ } /* for each subset of size k */ /* New orders become old orders in preparation for next iteration. */ tmpOrder = oldOrder; tmpCost = oldCost; oldOrder = newOrder; oldCost = newCost; newOrder = tmpOrder; newCost = tmpCost; #ifdef DD_STATS ddTotalSubsets += newSubsets; #endif oldSubsets = newSubsets; } result = ddShuffle(table, bestOrder, lower, upper); if (result == 0) goto cuddExactOutOfMem; #ifdef DD_STATS #ifdef DD_VERBOSE (void) fprintf(table->out,"\n"); #endif (void) fprintf(table->out,"#:S_EXACT %8d: total subsets\n", ddTotalSubsets); (void) fprintf(table->out,"#:H_EXACT %8d: total shuffles", ddTotalShuffles); #endif freeMatrix(newOrder); freeMatrix(oldOrder); ABC_FREE(bestOrder); ABC_FREE(oldCost); ABC_FREE(newCost); ABC_FREE(symmInfo); ABC_FREE(mask); return(1); cuddExactOutOfMem: if (newOrder != NULL) freeMatrix(newOrder); if (oldOrder != NULL) freeMatrix(oldOrder); if (bestOrder != NULL) ABC_FREE(bestOrder); if (oldCost != NULL) ABC_FREE(oldCost); if (newCost != NULL) ABC_FREE(newCost); if (symmInfo != NULL) ABC_FREE(symmInfo); if (mask != NULL) ABC_FREE(mask); table->errorCode = CUDD_MEMORY_OUT; return(0); } /* end of cuddExact */ /**Function******************************************************************** Synopsis [Returns the maximum value of (n choose k) for a given n.] Description [Computes the maximum value of (n choose k) for a given n. The maximum value occurs for k = n/2 when n is even, or k = (n-1)/2 when n is odd. The algorithm used in this procedure avoids intermediate overflow problems. It is based on the identity
    binomial(n,k) = n/k * binomial(n-1,k-1).
  
Returns the computed value if successful; -1 if out of range.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int getMaxBinomial( int n) { double i, j, result; if (n < 0 || n > 33) return(-1); /* error */ if (n < 2) return(1); for (result = (double)((n+3)/2), i = result+1, j=2; i <= n; i++, j++) { result *= i; result /= j; } return((int)result); } /* end of getMaxBinomial */ #if 0 /**Function******************************************************************** Synopsis [Returns the gcd of two integers.] Description [Returns the gcd of two integers. Uses the binary GCD algorithm described in Cormen, Leiserson, and Rivest.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int gcd( int x, int y) { int a; int b; int lsbMask; /* GCD(n,0) = n. */ if (x == 0) return(y); if (y == 0) return(x); a = x; b = y; lsbMask = 1; /* Here both a and b are != 0. The iteration maintains this invariant. ** Hence, we only need to check for when they become equal. */ while (a != b) { if (a & lsbMask) { if (b & lsbMask) { /* both odd */ if (a < b) { b = (b - a) >> 1; } else { a = (a - b) >> 1; } } else { /* a odd, b even */ b >>= 1; } } else { if (b & lsbMask) { /* a even, b odd */ a >>= 1; } else { /* both even */ lsbMask <<= 1; } } } return(a); } /* end of gcd */ #endif /**Function******************************************************************** Synopsis [Allocates a two-dimensional matrix of ints.] Description [Allocates a two-dimensional matrix of ints. Returns the pointer to the matrix if successful; NULL otherwise.] SideEffects [None] SeeAlso [freeMatrix] ******************************************************************************/ static DdHalfWord ** getMatrix( int rows /* number of rows */, int cols /* number of columns */) { DdHalfWord **matrix; int i; if (cols*rows == 0) return(NULL); matrix = ABC_ALLOC(DdHalfWord *, rows); if (matrix == NULL) return(NULL); matrix[0] = ABC_ALLOC(DdHalfWord, cols*rows); if (matrix[0] == NULL) { ABC_FREE(matrix); return(NULL); } for (i = 1; i < rows; i++) { matrix[i] = matrix[i-1] + cols; } return(matrix); } /* end of getMatrix */ /**Function******************************************************************** Synopsis [Frees a two-dimensional matrix allocated by getMatrix.] Description [] SideEffects [None] SeeAlso [getMatrix] ******************************************************************************/ static void freeMatrix( DdHalfWord ** matrix) { ABC_FREE(matrix[0]); ABC_FREE(matrix); return; } /* end of freeMatrix */ /**Function******************************************************************** Synopsis [Returns the number of nodes at one level of a unique table.] Description [Returns the number of nodes at one level of a unique table. The projection function, if isolated, is not counted.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int getLevelKeys( DdManager * table, int l) { int isolated; int x; /* x is an index */ x = table->invperm[l]; isolated = table->vars[x]->ref == 1; return(table->subtables[l].keys - isolated); } /* end of getLevelKeys */ /**Function******************************************************************** Synopsis [Reorders variables according to a given permutation.] Description [Reorders variables according to a given permutation. The i-th permutation array contains the index of the variable that should be brought to the i-th level. ddShuffle assumes that no dead nodes are present and that the interaction matrix is properly initialized. The reordering is achieved by a series of upward sifts. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddShuffle( DdManager * table, DdHalfWord * permutation, int lower, int upper) { DdHalfWord index; int level; int position; #if 0 int numvars; #endif int result; #ifdef DD_STATS long localTime; int initialSize; #ifdef DD_VERBOSE int finalSize; #endif int previousSize; #endif #ifdef DD_STATS localTime = util_cpu_time(); initialSize = table->keys - table->isolated; #endif #if 0 numvars = table->size; (void) fprintf(table->out,"%d:", ddTotalShuffles); for (level = 0; level < numvars; level++) { (void) fprintf(table->out," %d", table->invperm[level]); } (void) fprintf(table->out,"\n"); #endif for (level = 0; level <= upper - lower; level++) { index = permutation[level]; position = table->perm[index]; #ifdef DD_STATS previousSize = table->keys - table->isolated; #endif result = ddSiftUp(table,position,level+lower); if (!result) return(0); } #ifdef DD_STATS ddTotalShuffles++; #ifdef DD_VERBOSE finalSize = table->keys - table->isolated; if (finalSize < initialSize) { (void) fprintf(table->out,"-"); } else if (finalSize > initialSize) { (void) fprintf(table->out,"+"); } else { (void) fprintf(table->out,"="); } if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n"); fflush(table->out); #endif #endif return(1); } /* end of ddShuffle */ /**Function******************************************************************** Synopsis [Moves one variable up.] Description [Takes a variable from position x and sifts it up to position xLow; xLow should be less than or equal to x. Returns 1 if successful; 0 otherwise] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddSiftUp( DdManager * table, int x, int xLow) { int y; int size; y = cuddNextLow(table,x); while (y >= xLow) { size = cuddSwapInPlace(table,y,x); if (size == 0) { return(0); } x = y; y = cuddNextLow(table,x); } return(1); } /* end of ddSiftUp */ /**Function******************************************************************** Synopsis [Updates the upper bound and saves the best order seen so far.] Description [Updates the upper bound and saves the best order seen so far. Returns the current value of the upper bound.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int updateUB( DdManager * table, int oldBound, DdHalfWord * bestOrder, int lower, int upper) { int i; int newBound = table->keys - table->isolated; if (newBound < oldBound) { #ifdef DD_STATS (void) fprintf(table->out,"New upper bound = %d\n", newBound); fflush(table->out); #endif for (i = lower; i <= upper; i++) bestOrder[i-lower] = (DdHalfWord) table->invperm[i]; return(newBound); } else { return(oldBound); } } /* end of updateUB */ /**Function******************************************************************** Synopsis [Counts the number of roots.] Description [Counts the number of roots at the levels between lower and upper. The computation is based on breadth-first search. A node is a root if it is not reachable from any previously visited node. (All the nodes at level lower are therefore considered roots.) The visited flag uses the LSB of the next pointer. Returns the root count. The roots that are constant nodes are always ignored.] SideEffects [None] SeeAlso [ddClearGlobal] ******************************************************************************/ static int ddCountRoots( DdManager * table, int lower, int upper) { int i,j; DdNode *f; DdNodePtr *nodelist; DdNode *sentinel = &(table->sentinel); int slots; int roots = 0; int maxlevel = lower; for (i = lower; i <= upper; i++) { nodelist = table->subtables[i].nodelist; slots = table->subtables[i].slots; for (j = 0; j < slots; j++) { f = nodelist[j]; while (f != sentinel) { /* A node is a root of the DAG if it cannot be ** reached by nodes above it. If a node was never ** reached during the previous depth-first searches, ** then it is a root, and we start a new depth-first ** search from it. */ if (!Cudd_IsComplement(f->next)) { if (f != table->vars[f->index]) { roots++; } } if (!Cudd_IsConstant(cuddT(f))) { cuddT(f)->next = Cudd_Complement(cuddT(f)->next); if (table->perm[cuddT(f)->index] > maxlevel) maxlevel = table->perm[cuddT(f)->index]; } if (!Cudd_IsConstant(cuddE(f))) { Cudd_Regular(cuddE(f))->next = Cudd_Complement(Cudd_Regular(cuddE(f))->next); if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel) maxlevel = table->perm[Cudd_Regular(cuddE(f))->index]; } f = Cudd_Regular(f->next); } } } ddClearGlobal(table, lower, maxlevel); return(roots); } /* end of ddCountRoots */ /**Function******************************************************************** Synopsis [Scans the DD and clears the LSB of the next pointers.] Description [Scans the DD and clears the LSB of the next pointers. The LSB of the next pointers are used as markers to tell whether a node was reached. Once the roots are counted, these flags are reset.] SideEffects [None] SeeAlso [ddCountRoots] ******************************************************************************/ static void ddClearGlobal( DdManager * table, int lower, int maxlevel) { int i,j; DdNode *f; DdNodePtr *nodelist; DdNode *sentinel = &(table->sentinel); int slots; for (i = lower; i <= maxlevel; i++) { nodelist = table->subtables[i].nodelist; slots = table->subtables[i].slots; for (j = 0; j < slots; j++) { f = nodelist[j]; while (f != sentinel) { f->next = Cudd_Regular(f->next); f = f->next; } } } } /* end of ddClearGlobal */ /**Function******************************************************************** Synopsis [Computes a lower bound on the size of a BDD.] Description [Computes a lower bound on the size of a BDD from the following factors:
  • size of the lower part of it;
  • size of the part of the upper part not subjected to reordering;
  • number of roots in the part of the BDD subjected to reordering;
  • variable in the support of the roots in the upper part of the BDD subjected to reordering.
      ] SideEffects [None] SeeAlso [] ******************************************************************************/ static int computeLB( DdManager * table /* manager */, DdHalfWord * order /* optimal order for the subset */, int roots /* roots between lower and upper */, int cost /* minimum cost for the subset */, int lower /* lower level to be reordered */, int upper /* upper level to be reordered */, int level /* offset for the current top bottom var */ ) { int i; int lb = cost; int lb1 = 0; int lb2; int support; DdHalfWord ref; /* The levels not involved in reordering are not going to change. ** Add their sizes to the lower bound. */ for (i = 0; i < lower; i++) { lb += getLevelKeys(table,i); } /* If a variable is in the support, then there is going ** to be at least one node labeled by that variable. */ for (i = lower; i <= lower+level; i++) { support = table->subtables[i].keys > 1 || table->vars[order[i-lower]]->ref > 1; lb1 += support; } /* Estimate the number of nodes required to connect the roots to ** the nodes in the bottom part. */ if (lower+level+1 < table->size) { if (lower+level < upper) ref = table->vars[order[level+1]]->ref; else ref = table->vars[table->invperm[upper+1]]->ref; lb2 = table->subtables[lower+level+1].keys - (ref > (DdHalfWord) 1) - roots; } else { lb2 = 0; } lb += lb1 > lb2 ? lb1 : lb2; return(lb); } /* end of computeLB */ /**Function******************************************************************** Synopsis [Updates entry for a subset.] Description [Updates entry for a subset. Finds the subset, if it exists. If the new order for the subset has lower cost, or if the subset did not exist, it stores the new order and cost. Returns the number of subsets currently in the table.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int updateEntry( DdManager * table, DdHalfWord * order, int level, int cost, DdHalfWord ** orders, int * costs, int subsets, char * mask, int lower, int upper) { int i, j; int size = upper - lower + 1; /* Build a mask that says what variables are in this subset. */ for (i = lower; i <= upper; i++) mask[table->invperm[i]] = 0; for (i = level; i < size; i++) mask[order[i]] = 1; /* Check each subset until a match is found or all subsets are examined. */ for (i = 0; i < subsets; i++) { DdHalfWord *subset = orders[i]; for (j = level; j < size; j++) { if (mask[subset[j]] == 0) break; } if (j == size) /* no mismatches: success */ break; } if (i == subsets || cost < costs[i]) { /* add or replace */ for (j = 0; j < size; j++) orders[i][j] = order[j]; costs[i] = cost; subsets += (i == subsets); } return(subsets); } /* end of updateEntry */ /**Function******************************************************************** Synopsis [Pushes a variable in the order down to position "level."] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void pushDown( DdHalfWord * order, int j, int level) { int i; DdHalfWord tmp; tmp = order[j]; for (i = j; i < level; i++) { order[i] = order[i+1]; } order[level] = tmp; return; } /* end of pushDown */ /**Function******************************************************************** Synopsis [Gathers symmetry information.] Description [Translates the symmetry information stored in the next field of each subtable from level to indices. This procedure is called immediately after symmetric sifting, so that the next fields are correct. By translating this informaton in terms of indices, we make it independent of subsequent reorderings. The format used is that of the next fields: a circular list where each variable points to the next variable in the same symmetry group. Only the entries between lower and upper are considered. The procedure returns a pointer to an array holding the symmetry information if successful; NULL otherwise.] SideEffects [None] SeeAlso [checkSymmInfo] ******************************************************************************/ static DdHalfWord * initSymmInfo( DdManager * table, int lower, int upper) { int level, index, next, nextindex; DdHalfWord *symmInfo; symmInfo = ABC_ALLOC(DdHalfWord, table->size); if (symmInfo == NULL) return(NULL); for (level = lower; level <= upper; level++) { index = table->invperm[level]; next = table->subtables[level].next; nextindex = table->invperm[next]; symmInfo[index] = nextindex; } return(symmInfo); } /* end of initSymmInfo */ /**Function******************************************************************** Synopsis [Check symmetry condition.] Description [Returns 1 if a variable is the one with the highest index among those belonging to a symmetry group that are in the top part of the BDD. The top part is given by level.] SideEffects [None] SeeAlso [initSymmInfo] ******************************************************************************/ static int checkSymmInfo( DdManager * table, DdHalfWord * symmInfo, int index, int level) { int i; i = symmInfo[index]; while (i != index) { if (index < i && table->perm[i] <= level) return(0); i = symmInfo[i]; } return(1); } /* end of checkSymmInfo */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddExport.c000066400000000000000000001357541300674244400240100ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddExport.c] PackageName [cudd] Synopsis [Export functions.] Description [External procedures included in this module:
      • Cudd_DumpBlif()
      • Cudd_DumpBlifBody()
      • Cudd_DumpDot()
      • Cudd_DumpDaVinci()
      • Cudd_DumpDDcal()
      • Cudd_DumpFactoredForm()
      Internal procedures included in this module:
      Static procedures included in this module:
      • ddDoDumpBlif()
      • ddDoDumpDaVinci()
      • ddDoDumpDDcal()
      • ddDoDumpFactoredForm()
      ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddExport.c,v 1.22 2009/03/08 02:49:02 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int ddDoDumpBlif (DdManager *dd, DdNode *f, FILE *fp, st__table *visited, char **names, int mv); static int ddDoDumpDaVinci (DdManager *dd, DdNode *f, FILE *fp, st__table *visited, char **names, ptruint mask); static int ddDoDumpDDcal (DdManager *dd, DdNode *f, FILE *fp, st__table *visited, char **names, ptruint mask); static int ddDoDumpFactoredForm (DdManager *dd, DdNode *f, FILE *fp, char **names); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Writes a blif file representing the argument BDDs.] Description [Writes a blif file representing the argument BDDs as a network of multiplexers. One multiplexer is written for each BDD node. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full, or an ADD with constants different from 0 and 1). Cudd_DumpBlif does not close the file: This is the caller responsibility. Cudd_DumpBlif uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.] SideEffects [None] SeeAlso [Cudd_DumpBlifBody Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal Cudd_DumpDaVinci Cudd_DumpFactoredForm] ******************************************************************************/ int Cudd_DumpBlif( DdManager * dd /* manager */, int n /* number of output nodes to be dumped */, DdNode ** f /* array of output nodes to be dumped */, char ** inames /* array of input names (or NULL) */, char ** onames /* array of output names (or NULL) */, char * mname /* model name (or NULL) */, FILE * fp /* pointer to the dump file */, int mv /* 0: blif, 1: blif-MV */) { DdNode *support = NULL; DdNode *scan; int *sorted = NULL; int nvars = dd->size; int retval; int i; /* Build a bit array with the support of f. */ sorted = ABC_ALLOC(int,nvars); if (sorted == NULL) { dd->errorCode = CUDD_MEMORY_OUT; goto failure; } for (i = 0; i < nvars; i++) sorted[i] = 0; /* Take the union of the supports of each output function. */ support = Cudd_VectorSupport(dd,f,n); if (support == NULL) goto failure; cuddRef(support); scan = support; while (!cuddIsConstant(scan)) { sorted[scan->index] = 1; scan = cuddT(scan); } Cudd_RecursiveDeref(dd,support); support = NULL; /* so that we do not try to free it in case of failure */ /* Write the header (.model .inputs .outputs). */ if (mname == NULL) { retval = fprintf(fp,".model DD\n.inputs"); } else { retval = fprintf(fp,".model %s\n.inputs",mname); } if (retval == EOF) { ABC_FREE(sorted); return(0); } /* Write the input list by scanning the support array. */ for (i = 0; i < nvars; i++) { if (sorted[i]) { if (inames == NULL) { retval = fprintf(fp," %d", i); } else { retval = fprintf(fp," %s", inames[i]); } if (retval == EOF) goto failure; } } ABC_FREE(sorted); sorted = NULL; /* Write the .output line. */ retval = fprintf(fp,"\n.outputs"); if (retval == EOF) goto failure; for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp," f%d", i); } else { retval = fprintf(fp," %s", onames[i]); } if (retval == EOF) goto failure; } retval = fprintf(fp,"\n"); if (retval == EOF) goto failure; retval = Cudd_DumpBlifBody(dd, n, f, inames, onames, fp, mv); if (retval == 0) goto failure; /* Write trailer and return. */ retval = fprintf(fp,".end\n"); if (retval == EOF) goto failure; return(1); failure: if (sorted != NULL) ABC_FREE(sorted); if (support != NULL) Cudd_RecursiveDeref(dd,support); return(0); } /* end of Cudd_DumpBlif */ /**Function******************************************************************** Synopsis [Writes a blif body representing the argument BDDs.] Description [Writes a blif body representing the argument BDDs as a network of multiplexers. No header (.model, .inputs, and .outputs) and footer (.end) are produced by this function. One multiplexer is written for each BDD node. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full, or an ADD with constants different from 0 and 1). Cudd_DumpBlifBody does not close the file: This is the caller responsibility. Cudd_DumpBlifBody uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. This function prints out only .names part.] SideEffects [None] SeeAlso [Cudd_DumpBlif Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal Cudd_DumpDaVinci Cudd_DumpFactoredForm] ******************************************************************************/ int Cudd_DumpBlifBody( DdManager * dd /* manager */, int n /* number of output nodes to be dumped */, DdNode ** f /* array of output nodes to be dumped */, char ** inames /* array of input names (or NULL) */, char ** onames /* array of output names (or NULL) */, FILE * fp /* pointer to the dump file */, int mv /* 0: blif, 1: blif-MV */) { st__table *visited = NULL; int retval; int i; /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash); if (visited == NULL) goto failure; /* Call the function that really gets the job done. */ for (i = 0; i < n; i++) { retval = ddDoDumpBlif(dd,Cudd_Regular(f[i]),fp,visited,inames,mv); if (retval == 0) goto failure; } /* To account for the possible complement on the root, ** we put either a buffer or an inverter at the output of ** the multiplexer representing the top node. */ for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp, #if SIZEOF_VOID_P == 8 ".names %lx f%d\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), i); #else ".names %x f%d\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), i); #endif } else { retval = fprintf(fp, #if SIZEOF_VOID_P == 8 ".names %lx %s\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), onames[i]); #else ".names %x %s\n", (ptruint) f[i] / (ptruint) sizeof(DdNode), onames[i]); #endif } if (retval == EOF) goto failure; if (Cudd_IsComplement(f[i])) { retval = fprintf(fp,"%s0 1\n", mv ? ".def 0\n" : ""); } else { retval = fprintf(fp,"%s1 1\n", mv ? ".def 0\n" : ""); } if (retval == EOF) goto failure; } st__free_table(visited); return(1); failure: if (visited != NULL) st__free_table(visited); return(0); } /* end of Cudd_DumpBlifBody */ /**Function******************************************************************** Synopsis [Writes a dot file representing the argument DDs.] Description [Writes a file representing the argument DDs in a format suitable for the graph drawing program dot. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full). Cudd_DumpDot does not close the file: This is the caller responsibility. Cudd_DumpDot uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. Cudd_DumpDot uses the following convention to draw arcs:
      • solid line: THEN arcs;
      • dotted line: complement arcs;
      • dashed line: regular ELSE arcs.
      The dot options are chosen so that the drawing fits on a letter-size sheet. ] SideEffects [None] SeeAlso [Cudd_DumpBlif Cudd_PrintDebug Cudd_DumpDDcal Cudd_DumpDaVinci Cudd_DumpFactoredForm] ******************************************************************************/ int Cudd_DumpDot( DdManager * dd /* manager */, int n /* number of output nodes to be dumped */, DdNode ** f /* array of output nodes to be dumped */, char ** inames /* array of input names (or NULL) */, char ** onames /* array of output names (or NULL) */, FILE * fp /* pointer to the dump file */) { DdNode *support = NULL; DdNode *scan; int *sorted = NULL; int nvars = dd->size; st__table *visited = NULL; st__generator *gen = NULL; int retval; int i, j; int slots; DdNodePtr *nodelist; long refAddr, diff, mask; /* Build a bit array with the support of f. */ sorted = ABC_ALLOC(int,nvars); if (sorted == NULL) { dd->errorCode = CUDD_MEMORY_OUT; goto failure; } for (i = 0; i < nvars; i++) sorted[i] = 0; /* Take the union of the supports of each output function. */ support = Cudd_VectorSupport(dd,f,n); if (support == NULL) goto failure; cuddRef(support); scan = support; while (!cuddIsConstant(scan)) { sorted[scan->index] = 1; scan = cuddT(scan); } Cudd_RecursiveDeref(dd,support); support = NULL; /* so that we do not try to free it in case of failure */ /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash); if (visited == NULL) goto failure; /* Collect all the nodes of this DD in the symbol table. */ for (i = 0; i < n; i++) { retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); if (retval == 0) goto failure; } /* Find how many most significant hex digits are identical ** in the addresses of all the nodes. Build a mask based ** on this knowledge, so that digits that carry no information ** will not be printed. This is done in two steps. ** 1. We scan the symbol table to find the bits that differ ** in at least 2 addresses. ** 2. We choose one of the possible masks. There are 8 possible ** masks for 32-bit integer, and 16 possible masks for 64-bit ** integers. */ /* Find the bits that are different. */ refAddr = (long) Cudd_Regular(f[0]); diff = 0; gen = st__init_gen(visited); if (gen == NULL) goto failure; while ( st__gen(gen, (const char **)&scan, NULL)) { diff |= refAddr ^ (long) scan; } st__free_gen(gen); gen = NULL; /* Choose the mask. */ for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { mask = (1 << i) - 1; if (diff <= mask) break; } /* Write the header and the global attributes. */ retval = fprintf(fp,"digraph \"DD\" {\n"); if (retval == EOF) return(0); retval = fprintf(fp, "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n"); if (retval == EOF) return(0); /* Write the input name subgraph by scanning the support array. */ retval = fprintf(fp,"{ node [shape = plaintext];\n"); if (retval == EOF) goto failure; retval = fprintf(fp," edge [style = invis];\n"); if (retval == EOF) goto failure; /* We use a name ("CONST NODES") with an embedded blank, because ** it is unlikely to appear as an input name. */ retval = fprintf(fp," \"CONST NODES\" [style = invis];\n"); if (retval == EOF) goto failure; for (i = 0; i < nvars; i++) { if (sorted[dd->invperm[i]]) { if (inames == NULL || inames[dd->invperm[i]] == NULL) { retval = fprintf(fp,"\" %d \" -> ", dd->invperm[i]); } else { retval = fprintf(fp,"\" %s \" -> ", inames[dd->invperm[i]]); } if (retval == EOF) goto failure; } } retval = fprintf(fp,"\"CONST NODES\"; \n}\n"); if (retval == EOF) goto failure; /* Write the output node subgraph. */ retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n"); if (retval == EOF) goto failure; for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp,"\"F%d\"", i); } else { retval = fprintf(fp,"\" %s \"", onames[i]); } if (retval == EOF) goto failure; if (i == n - 1) { retval = fprintf(fp,"; }\n"); } else { retval = fprintf(fp," -> "); } if (retval == EOF) goto failure; } /* Write rank info: All nodes with the same index have the same rank. */ for (i = 0; i < nvars; i++) { if (sorted[dd->invperm[i]]) { retval = fprintf(fp,"{ rank = same; "); if (retval == EOF) goto failure; if (inames == NULL || inames[dd->invperm[i]] == NULL) { retval = fprintf(fp,"\" %d \";\n", dd->invperm[i]); } else { retval = fprintf(fp,"\" %s \";\n", inames[dd->invperm[i]]); } if (retval == EOF) goto failure; nodelist = dd->subtables[i].nodelist; slots = dd->subtables[i].slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if ( st__is_member(visited,(char *) scan)) { retval = fprintf(fp,"\"%lx\";\n", ((mask & (ptrint) scan) / sizeof(DdNode))); if (retval == EOF) goto failure; } scan = scan->next; } } retval = fprintf(fp,"}\n"); if (retval == EOF) goto failure; } } /* All constants have the same rank. */ retval = fprintf(fp, "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; "); if (retval == EOF) goto failure; nodelist = dd->constants.nodelist; slots = dd->constants.slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if ( st__is_member(visited,(char *) scan)) { retval = fprintf(fp,"\"%lx\";\n", ((mask & (ptrint) scan) / sizeof(DdNode))); if (retval == EOF) goto failure; } scan = scan->next; } } retval = fprintf(fp,"}\n}\n"); if (retval == EOF) goto failure; /* Write edge info. */ /* Edges from the output nodes. */ for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp,"\"F%d\"", i); } else { retval = fprintf(fp,"\" %s \"", onames[i]); } if (retval == EOF) goto failure; /* Account for the possible complement on the root. */ if (Cudd_IsComplement(f[i])) { retval = fprintf(fp," -> \"%lx\" [style = dotted];\n", ((mask & (ptrint) f[i]) / sizeof(DdNode))); } else { retval = fprintf(fp," -> \"%lx\" [style = solid];\n", ((mask & (ptrint) f[i]) / sizeof(DdNode))); } if (retval == EOF) goto failure; } /* Edges from internal nodes. */ for (i = 0; i < nvars; i++) { if (sorted[dd->invperm[i]]) { nodelist = dd->subtables[i].nodelist; slots = dd->subtables[i].slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if ( st__is_member(visited,(char *) scan)) { retval = fprintf(fp, "\"%lx\" -> \"%lx\";\n", ((mask & (ptrint) scan) / sizeof(DdNode)), ((mask & (ptrint) cuddT(scan)) / sizeof(DdNode))); if (retval == EOF) goto failure; if (Cudd_IsComplement(cuddE(scan))) { retval = fprintf(fp,"\"%lx\" -> \"%lx\" [style = dotted];\n", ((mask & (ptrint) scan) / sizeof(DdNode)), ((mask & (ptrint) cuddE(scan)) / sizeof(DdNode))); } else { retval = fprintf(fp, "\"%lx\" -> \"%lx\" [style = dashed];\n", ((mask & (ptrint) scan) / sizeof(DdNode)), ((mask & (ptrint) cuddE(scan)) / sizeof(DdNode))); } if (retval == EOF) goto failure; } scan = scan->next; } } } } /* Write constant labels. */ nodelist = dd->constants.nodelist; slots = dd->constants.slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if ( st__is_member(visited,(char *) scan)) { retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n", ((mask & (ptrint) scan) / sizeof(DdNode)), cuddV(scan)); if (retval == EOF) goto failure; } scan = scan->next; } } /* Write trailer and return. */ retval = fprintf(fp,"}\n"); if (retval == EOF) goto failure; st__free_table(visited); ABC_FREE(sorted); return(1); failure: if (sorted != NULL) ABC_FREE(sorted); if (support != NULL) Cudd_RecursiveDeref(dd,support); if (visited != NULL) st__free_table(visited); return(0); } /* end of Cudd_DumpDot */ /**Function******************************************************************** Synopsis [Writes a daVinci file representing the argument BDDs.] Description [Writes a daVinci file representing the argument BDDs. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or file system full). Cudd_DumpDaVinci does not close the file: This is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.] SideEffects [None] SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDDcal Cudd_DumpFactoredForm] ******************************************************************************/ int Cudd_DumpDaVinci( DdManager * dd /* manager */, int n /* number of output nodes to be dumped */, DdNode ** f /* array of output nodes to be dumped */, char ** inames /* array of input names (or NULL) */, char ** onames /* array of output names (or NULL) */, FILE * fp /* pointer to the dump file */) { DdNode *support = NULL; DdNode *scan; st__table *visited = NULL; int retval; int i; st__generator *gen; ptruint refAddr, diff, mask; /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash); if (visited == NULL) goto failure; /* Collect all the nodes of this DD in the symbol table. */ for (i = 0; i < n; i++) { retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); if (retval == 0) goto failure; } /* Find how many most significant hex digits are identical ** in the addresses of all the nodes. Build a mask based ** on this knowledge, so that digits that carry no information ** will not be printed. This is done in two steps. ** 1. We scan the symbol table to find the bits that differ ** in at least 2 addresses. ** 2. We choose one of the possible masks. There are 8 possible ** masks for 32-bit integer, and 16 possible masks for 64-bit ** integers. */ /* Find the bits that are different. */ refAddr = (ptruint) Cudd_Regular(f[0]); diff = 0; gen = st__init_gen(visited); while ( st__gen(gen, (const char **)&scan, NULL)) { diff |= refAddr ^ (ptruint) scan; } st__free_gen(gen); /* Choose the mask. */ for (i = 0; (unsigned) i < 8 * sizeof(ptruint); i += 4) { mask = (1 << i) - 1; if (diff <= mask) break; } st__free_table(visited); /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash); if (visited == NULL) goto failure; retval = fprintf(fp, "["); if (retval == EOF) goto failure; /* Call the function that really gets the job done. */ for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp, "l(\"f%d\",n(\"root\",[a(\"OBJECT\",\"f%d\")],", i,i); } else { retval = fprintf(fp, "l(\"%s\",n(\"root\",[a(\"OBJECT\",\"%s\")],", onames[i], onames[i]); } if (retval == EOF) goto failure; retval = fprintf(fp, "[e(\"edge\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", Cudd_IsComplement(f[i]) ? "red" : "blue"); if (retval == EOF) goto failure; retval = ddDoDumpDaVinci(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); if (retval == 0) goto failure; retval = fprintf(fp, ")]))%s", i == n-1 ? "" : ","); if (retval == EOF) goto failure; } /* Write trailer and return. */ retval = fprintf(fp, "]\n"); if (retval == EOF) goto failure; st__free_table(visited); return(1); failure: if (support != NULL) Cudd_RecursiveDeref(dd,support); if (visited != NULL) st__free_table(visited); return(0); } /* end of Cudd_DumpDaVinci */ /**Function******************************************************************** Synopsis [Writes a DDcal file representing the argument BDDs.] Description [Writes a DDcal file representing the argument BDDs. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or file system full). Cudd_DumpDDcal does not close the file: This is the caller responsibility. Cudd_DumpDDcal uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.] SideEffects [None] SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci Cudd_DumpFactoredForm] ******************************************************************************/ int Cudd_DumpDDcal( DdManager * dd /* manager */, int n /* number of output nodes to be dumped */, DdNode ** f /* array of output nodes to be dumped */, char ** inames /* array of input names (or NULL) */, char ** onames /* array of output names (or NULL) */, FILE * fp /* pointer to the dump file */) { DdNode *support = NULL; DdNode *scan; int *sorted = NULL; int nvars = dd->size; st__table *visited = NULL; int retval; int i; st__generator *gen; ptruint refAddr, diff, mask; /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash); if (visited == NULL) goto failure; /* Collect all the nodes of this DD in the symbol table. */ for (i = 0; i < n; i++) { retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); if (retval == 0) goto failure; } /* Find how many most significant hex digits are identical ** in the addresses of all the nodes. Build a mask based ** on this knowledge, so that digits that carry no information ** will not be printed. This is done in two steps. ** 1. We scan the symbol table to find the bits that differ ** in at least 2 addresses. ** 2. We choose one of the possible masks. There are 8 possible ** masks for 32-bit integer, and 16 possible masks for 64-bit ** integers. */ /* Find the bits that are different. */ refAddr = (ptruint) Cudd_Regular(f[0]); diff = 0; gen = st__init_gen(visited); while ( st__gen(gen, (const char **)&scan, NULL)) { diff |= refAddr ^ (ptruint) scan; } st__free_gen(gen); /* Choose the mask. */ for (i = 0; (unsigned) i < 8 * sizeof(ptruint); i += 4) { mask = (1 << i) - 1; if (diff <= mask) break; } st__free_table(visited); visited = NULL; /* Build a bit array with the support of f. */ sorted = ABC_ALLOC(int,nvars); if (sorted == NULL) { dd->errorCode = CUDD_MEMORY_OUT; goto failure; } for (i = 0; i < nvars; i++) sorted[i] = 0; /* Take the union of the supports of each output function. */ support = Cudd_VectorSupport(dd,f,n); if (support == NULL) goto failure; cuddRef(support); scan = support; while (!cuddIsConstant(scan)) { sorted[scan->index] = 1; scan = cuddT(scan); } Cudd_RecursiveDeref(dd,support); support = NULL; /* so that we do not try to free it in case of failure */ for (i = 0; i < nvars; i++) { if (sorted[dd->invperm[i]]) { if (inames == NULL || inames[dd->invperm[i]] == NULL) { retval = fprintf(fp,"v%d", dd->invperm[i]); } else { retval = fprintf(fp,"%s", inames[dd->invperm[i]]); } if (retval == EOF) goto failure; } retval = fprintf(fp,"%s", i == nvars - 1 ? "\n" : " * "); if (retval == EOF) goto failure; } ABC_FREE(sorted); sorted = NULL; /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash); if (visited == NULL) goto failure; /* Call the function that really gets the job done. */ for (i = 0; i < n; i++) { retval = ddDoDumpDDcal(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); if (retval == 0) goto failure; if (onames == NULL) { retval = fprintf(fp, "f%d = ", i); } else { retval = fprintf(fp, "%s = ", onames[i]); } if (retval == EOF) goto failure; retval = fprintf(fp, "n%p%s\n", (void *) (((ptruint) f[i] & mask) / (ptruint) sizeof(DdNode)), Cudd_IsComplement(f[i]) ? "'" : ""); if (retval == EOF) goto failure; } /* Write trailer and return. */ retval = fprintf(fp, "["); if (retval == EOF) goto failure; for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp, "f%d", i); } else { retval = fprintf(fp, "%s", onames[i]); } retval = fprintf(fp, "%s", i == n-1 ? "" : " "); if (retval == EOF) goto failure; } retval = fprintf(fp, "]\n"); if (retval == EOF) goto failure; if ( visited ) st__free_table(visited); return(1); failure: if (sorted != NULL) ABC_FREE(sorted); if (support != NULL) Cudd_RecursiveDeref(dd,support); if (visited != NULL) st__free_table(visited); return(0); } /* end of Cudd_DumpDDcal */ /**Function******************************************************************** Synopsis [Writes factored forms representing the argument BDDs.] Description [Writes factored forms representing the argument BDDs. The format of the factored form is the one used in the genlib files for technology mapping in sis. It returns 1 in case of success; 0 otherwise (e.g., file system full). Cudd_DumpFactoredForm does not close the file: This is the caller responsibility. Caution must be exercised because a factored form may be exponentially larger than the argument BDD. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames.] SideEffects [None] SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci Cudd_DumpDDcal] ******************************************************************************/ int Cudd_DumpFactoredForm( DdManager * dd /* manager */, int n /* number of output nodes to be dumped */, DdNode ** f /* array of output nodes to be dumped */, char ** inames /* array of input names (or NULL) */, char ** onames /* array of output names (or NULL) */, FILE * fp /* pointer to the dump file */) { int retval; int i; /* Call the function that really gets the job done. */ for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp, "f%d = ", i); } else { retval = fprintf(fp, "%s = ", onames[i]); } if (retval == EOF) return(0); if (f[i] == DD_ONE(dd)) { retval = fprintf(fp, "CONST1"); if (retval == EOF) return(0); } else if (f[i] == Cudd_Not(DD_ONE(dd)) || f[i] == DD_ZERO(dd)) { retval = fprintf(fp, "CONST0"); if (retval == EOF) return(0); } else { retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? "!(" : ""); if (retval == EOF) return(0); retval = ddDoDumpFactoredForm(dd,Cudd_Regular(f[i]),fp,inames); if (retval == 0) return(0); retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? ")" : ""); if (retval == EOF) return(0); } retval = fprintf(fp, "%s", i == n-1 ? "" : "\n"); if (retval == EOF) return(0); } return(1); } /* end of Cudd_DumpFactoredForm */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_DumpBlif.] Description [Performs the recursive step of Cudd_DumpBlif. Traverses the BDD f and writes a multiplexer-network description to the file pointed by fp in blif format. f is assumed to be a regular pointer and ddDoDumpBlif guarantees this assumption in the recursive calls.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddDoDumpBlif( DdManager * dd, DdNode * f, FILE * fp, st__table * visited, char ** names, int mv) { DdNode *T, *E; int retval; #ifdef DD_DEBUG assert(!Cudd_IsComplement(f)); #endif /* If already visited, nothing to do. */ if ( st__is_member(visited, (char *) f) == 1) return(1); /* Check for abnormal condition that should never happen. */ if (f == NULL) return(0); /* Mark node as visited. */ if ( st__insert(visited, (char *) f, NULL) == st__OUT_OF_MEM) return(0); /* Check for special case: If constant node, generate constant 1. */ if (f == DD_ONE(dd)) { #if SIZEOF_VOID_P == 8 retval = fprintf(fp, ".names %lx\n1\n",(ptruint) f / (ptruint) sizeof(DdNode)); #else retval = fprintf(fp, ".names %x\n1\n",(ptruint) f / (ptruint) sizeof(DdNode)); #endif if (retval == EOF) { return(0); } else { return(1); } } /* Check whether this is an ADD. We deal with 0-1 ADDs, but not ** with the general case. */ if (f == DD_ZERO(dd)) { #if SIZEOF_VOID_P == 8 retval = fprintf(fp, ".names %lx\n%s", (ptruint) f / (ptruint) sizeof(DdNode), mv ? "0\n" : ""); #else retval = fprintf(fp, ".names %x\n%s", (ptruint) f / (ptruint) sizeof(DdNode), mv ? "0\n" : ""); #endif if (retval == EOF) { return(0); } else { return(1); } } if (cuddIsConstant(f)) return(0); /* Recursive calls. */ T = cuddT(f); retval = ddDoDumpBlif(dd,T,fp,visited,names,mv); if (retval != 1) return(retval); E = Cudd_Regular(cuddE(f)); retval = ddDoDumpBlif(dd,E,fp,visited,names,mv); if (retval != 1) return(retval); /* Write multiplexer taking complement arc into account. */ if (names != NULL) { retval = fprintf(fp,".names %s", names[f->index]); } else { #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 retval = fprintf(fp,".names %u", f->index); #else retval = fprintf(fp,".names %hu", f->index); #endif } if (retval == EOF) return(0); #if SIZEOF_VOID_P == 8 if (mv) { if (Cudd_IsComplement(cuddE(f))) { retval = fprintf(fp," %lx %lx %lx\n.def 0\n1 1 - 1\n0 - 0 1\n", (ptruint) T / (ptruint) sizeof(DdNode), (ptruint) E / (ptruint) sizeof(DdNode), (ptruint) f / (ptruint) sizeof(DdNode)); } else { retval = fprintf(fp," %lx %lx %lx\n.def 0\n1 1 - 1\n0 - 1 1\n", (ptruint) T / (ptruint) sizeof(DdNode), (ptruint) E / (ptruint) sizeof(DdNode), (ptruint) f / (ptruint) sizeof(DdNode)); } } else { if (Cudd_IsComplement(cuddE(f))) { retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-0 1\n", (ptruint) T / (ptruint) sizeof(DdNode), (ptruint) E / (ptruint) sizeof(DdNode), (ptruint) f / (ptruint) sizeof(DdNode)); } else { retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-1 1\n", (ptruint) T / (ptruint) sizeof(DdNode), (ptruint) E / (ptruint) sizeof(DdNode), (ptruint) f / (ptruint) sizeof(DdNode)); } } #else if (mv) { if (Cudd_IsComplement(cuddE(f))) { retval = fprintf(fp," %x %x %x\n.def 0\n1 1 - 1\n0 - 0 1\n", (ptruint) T / (ptruint) sizeof(DdNode), (ptruint) E / (ptruint) sizeof(DdNode), (ptruint) f / (ptruint) sizeof(DdNode)); } else { retval = fprintf(fp," %x %x %x\n.def 0\n1 1 - 1\n0 - 1 1\n", (ptruint) T / (ptruint) sizeof(DdNode), (ptruint) E / (ptruint) sizeof(DdNode), (ptruint) f / (ptruint) sizeof(DdNode)); } } else { if (Cudd_IsComplement(cuddE(f))) { retval = fprintf(fp," %x %x %x\n11- 1\n0-0 1\n", (ptruint) T / (ptruint) sizeof(DdNode), (ptruint) E / (ptruint) sizeof(DdNode), (ptruint) f / (ptruint) sizeof(DdNode)); } else { retval = fprintf(fp," %x %x %x\n11- 1\n0-1 1\n", (ptruint) T / (ptruint) sizeof(DdNode), (ptruint) E / (ptruint) sizeof(DdNode), (ptruint) f / (ptruint) sizeof(DdNode)); } } #endif if (retval == EOF) { return(0); } else { return(1); } } /* end of ddDoDumpBlif */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_DumpDaVinci.] Description [Performs the recursive step of Cudd_DumpDaVinci. Traverses the BDD f and writes a term expression to the file pointed by fp in daVinci format. f is assumed to be a regular pointer and ddDoDumpDaVinci guarantees this assumption in the recursive calls.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddDoDumpDaVinci( DdManager * dd, DdNode * f, FILE * fp, st__table * visited, char ** names, ptruint mask) { DdNode *T, *E; int retval; ptruint id; #ifdef DD_DEBUG assert(!Cudd_IsComplement(f)); #endif id = ((ptruint) f & mask) / sizeof(DdNode); /* If already visited, insert a reference. */ if ( st__is_member(visited, (char *) f) == 1) { retval = fprintf(fp,"r(\"%p\")", (void *) id); if (retval == EOF) { return(0); } else { return(1); } } /* Check for abnormal condition that should never happen. */ if (f == NULL) return(0); /* Mark node as visited. */ if ( st__insert(visited, (char *) f, NULL) == st__OUT_OF_MEM) return(0); /* Check for special case: If constant node, generate constant 1. */ if (Cudd_IsConstant(f)) { retval = fprintf(fp, "l(\"%p\",n(\"constant\",[a(\"OBJECT\",\"%g\")],[]))", (void *) id, cuddV(f)); if (retval == EOF) { return(0); } else { return(1); } } /* Recursive calls. */ if (names != NULL) { retval = fprintf(fp, "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%s\"),", (void *) id, names[f->index]); } else { retval = fprintf(fp, #if SIZEOF_VOID_P == 8 "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%u\"),", #else "l(\"%p\",n(\"internal\",[a(\"OBJECT\",\"%hu\"),", #endif (void *) id, f->index); } retval = fprintf(fp, "a(\"_GO\",\"ellipse\")],[e(\"then\",[a(\"EDGECOLOR\",\"blue\"),a(\"_DIR\",\"none\")],"); if (retval == EOF) return(0); T = cuddT(f); retval = ddDoDumpDaVinci(dd,T,fp,visited,names,mask); if (retval != 1) return(retval); retval = fprintf(fp, "),e(\"else\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", Cudd_IsComplement(cuddE(f)) ? "red" : "green"); if (retval == EOF) return(0); E = Cudd_Regular(cuddE(f)); retval = ddDoDumpDaVinci(dd,E,fp,visited,names,mask); if (retval != 1) return(retval); retval = fprintf(fp,")]))"); if (retval == EOF) { return(0); } else { return(1); } } /* end of ddDoDumpDaVinci */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_DumpDDcal.] Description [Performs the recursive step of Cudd_DumpDDcal. Traverses the BDD f and writes a line for each node to the file pointed by fp in DDcal format. f is assumed to be a regular pointer and ddDoDumpDDcal guarantees this assumption in the recursive calls.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddDoDumpDDcal( DdManager * dd, DdNode * f, FILE * fp, st__table * visited, char ** names, ptruint mask) { DdNode *T, *E; int retval; ptruint id, idT, idE; #ifdef DD_DEBUG assert(!Cudd_IsComplement(f)); #endif id = ((ptruint) f & mask) / sizeof(DdNode); /* If already visited, do nothing. */ if ( st__is_member(visited, (char *) f) == 1) { return(1); } /* Check for abnormal condition that should never happen. */ if (f == NULL) return(0); /* Mark node as visited. */ if ( st__insert(visited, (char *) f, NULL) == st__OUT_OF_MEM) return(0); /* Check for special case: If constant node, assign constant. */ if (Cudd_IsConstant(f)) { if (f != DD_ONE(dd) && f != DD_ZERO(dd)) return(0); retval = fprintf(fp, "n%p = %g\n", (void *) id, cuddV(f)); if (retval == EOF) { return(0); } else { return(1); } } /* Recursive calls. */ T = cuddT(f); retval = ddDoDumpDDcal(dd,T,fp,visited,names,mask); if (retval != 1) return(retval); E = Cudd_Regular(cuddE(f)); retval = ddDoDumpDDcal(dd,E,fp,visited,names,mask); if (retval != 1) return(retval); idT = ((ptruint) T & mask) / sizeof(DdNode); idE = ((ptruint) E & mask) / sizeof(DdNode); if (names != NULL) { retval = fprintf(fp, "n%p = %s * n%p + %s' * n%p%s\n", (void *) id, names[f->index], (void *) idT, names[f->index], (void *) idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); } else { #if SIZEOF_VOID_P == 8 retval = fprintf(fp, "n%p = v%u * n%p + v%u' * n%p%s\n", #else retval = fprintf(fp, "n%p = v%hu * n%p + v%hu' * n%p%s\n", #endif (void *) id, f->index, (void *) idT, f->index, (void *) idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); } if (retval == EOF) { return(0); } else { return(1); } } /* end of ddDoDumpDDcal */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_DumpFactoredForm.] Description [Performs the recursive step of Cudd_DumpFactoredForm. Traverses the BDD f and writes a factored form for each node to the file pointed by fp in terms of the factored forms of the children. Constants are propagated, and absorption is applied. f is assumed to be a regular pointer and ddDoDumpFActoredForm guarantees this assumption in the recursive calls.] SideEffects [None] SeeAlso [Cudd_DumpFactoredForm] ******************************************************************************/ static int ddDoDumpFactoredForm( DdManager * dd, DdNode * f, FILE * fp, char ** names) { DdNode *T, *E; int retval; #ifdef DD_DEBUG assert(!Cudd_IsComplement(f)); assert(!Cudd_IsConstant(f)); #endif /* Check for abnormal condition that should never happen. */ if (f == NULL) return(0); /* Recursive calls. */ T = cuddT(f); E = cuddE(f); if (T != DD_ZERO(dd)) { if (E != DD_ONE(dd)) { if (names != NULL) { retval = fprintf(fp, "%s", names[f->index]); } else { #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 retval = fprintf(fp, "x%u", f->index); #else retval = fprintf(fp, "x%hu", f->index); #endif } if (retval == EOF) return(0); } if (T != DD_ONE(dd)) { retval = fprintf(fp, "%s(", E != DD_ONE(dd) ? " * " : ""); if (retval == EOF) return(0); retval = ddDoDumpFactoredForm(dd,T,fp,names); if (retval != 1) return(retval); retval = fprintf(fp, ")"); if (retval == EOF) return(0); } if (E == Cudd_Not(DD_ONE(dd)) || E == DD_ZERO(dd)) return(1); retval = fprintf(fp, " + "); if (retval == EOF) return(0); } E = Cudd_Regular(E); if (T != DD_ONE(dd)) { if (names != NULL) { retval = fprintf(fp, "!%s", names[f->index]); } else { #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 retval = fprintf(fp, "!x%u", f->index); #else retval = fprintf(fp, "!x%hu", f->index); #endif } if (retval == EOF) return(0); } if (E != DD_ONE(dd)) { retval = fprintf(fp, "%s%s(", T != DD_ONE(dd) ? " * " : "", E != cuddE(f) ? "!" : ""); if (retval == EOF) return(0); retval = ddDoDumpFactoredForm(dd,E,fp,names); if (retval != 1) return(retval); retval = fprintf(fp, ")"); if (retval == EOF) return(0); } return(1); } /* end of ddDoDumpFactoredForm */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddGenCof.c000066400000000000000000001726671300674244400236740ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddGenCof.c] PackageName [cudd] Synopsis [Generalized cofactors for BDDs and ADDs.] Description [External procedures included in this module:
      • Cudd_bddConstrain()
      • Cudd_bddRestrict()
      • Cudd_bddNPAnd()
      • Cudd_addConstrain()
      • Cudd_bddConstrainDecomp()
      • Cudd_addRestrict()
      • Cudd_bddCharToVect()
      • Cudd_bddLICompaction()
      • Cudd_bddSqueeze()
      • Cudd_SubsetCompress()
      • Cudd_SupersetCompress()
      Internal procedures included in this module:
      • cuddBddConstrainRecur()
      • cuddBddRestrictRecur()
      • cuddBddNPAndRecur()
      • cuddAddConstrainRecur()
      • cuddAddRestrictRecur()
      • cuddBddLICompaction()
      Static procedures included in this module:
      • cuddBddConstrainDecomp()
      • cuddBddCharToVect()
      • cuddBddLICMarkEdges()
      • cuddBddLICBuildResult()
      • cuddBddSqueeze()
      ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /* Codes for edge markings in Cudd_bddLICompaction. The codes are defined ** so that they can be bitwise ORed to implement the code priority scheme. */ #define DD_LIC_DC 0 #define DD_LIC_1 1 #define DD_LIC_0 2 #define DD_LIC_NL 3 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /* Key for the cache used in the edge marking phase. */ typedef struct MarkCacheKey { DdNode *f; DdNode *c; } MarkCacheKey; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddGenCof.c,v 1.38 2005/05/14 17:27:11 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int cuddBddConstrainDecomp (DdManager *dd, DdNode *f, DdNode **decomp); static DdNode * cuddBddCharToVect (DdManager *dd, DdNode *f, DdNode *x); static int cuddBddLICMarkEdges (DdManager *dd, DdNode *f, DdNode *c, st__table *table, st__table *cache); static DdNode * cuddBddLICBuildResult (DdManager *dd, DdNode *f, st__table *cache, st__table *table); static int MarkCacheHash (const char *ptr, int modulus); static int MarkCacheCompare (const char *ptr1, const char *ptr2); static enum st__retval MarkCacheCleanUp (char *key, char *value, char *arg); static DdNode * cuddBddSqueeze (DdManager *dd, DdNode *l, DdNode *u); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes f constrain c.] Description [Computes f constrain c (f @ c). Uses a canonical form: (f' @ c) = ( f @ c)'. (Note: this is not true for c.) List of special cases:
      • f @ 0 = 0
      • f @ 1 = f
      • 0 @ c = 0
      • 1 @ c = 1
      • f @ f = 1
      • f @ f'= 0
      Returns a pointer to the result if successful; NULL otherwise. Note that if F=(f1,...,fn) and reordering takes place while computing F @ c, then the image restriction property (Img(F,c) = Img(F @ c)) is lost.] SideEffects [None] SeeAlso [Cudd_bddRestrict Cudd_addConstrain] ******************************************************************************/ DdNode * Cudd_bddConstrain( DdManager * dd, DdNode * f, DdNode * c) { DdNode *res; do { dd->reordered = 0; res = cuddBddConstrainRecur(dd,f,c); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddConstrain */ /**Function******************************************************************** Synopsis [BDD restrict according to Coudert and Madre's algorithm (ICCAD90).] Description [BDD restrict according to Coudert and Madre's algorithm (ICCAD90). Returns the restricted BDD if successful; otherwise NULL. If application of restrict results in a BDD larger than the input BDD, the input BDD is returned.] SideEffects [None] SeeAlso [Cudd_bddConstrain Cudd_addRestrict] ******************************************************************************/ DdNode * Cudd_bddRestrict( DdManager * dd, DdNode * f, DdNode * c) { DdNode *suppF, *suppC, *commonSupport; DdNode *cplus, *res; int retval; int sizeF, sizeRes; /* Check terminal cases here to avoid computing supports in trivial cases. ** This also allows us notto check later for the case c == 0, in which ** there is no common support. */ if (c == Cudd_Not(DD_ONE(dd))) return(Cudd_Not(DD_ONE(dd))); if (Cudd_IsConstant(f)) return(f); if (f == c) return(DD_ONE(dd)); if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd))); /* Check if supports intersect. */ retval = Cudd_ClassifySupport(dd,f,c,&commonSupport,&suppF,&suppC); if (retval == 0) { return(NULL); } cuddRef(commonSupport); cuddRef(suppF); cuddRef(suppC); Cudd_IterDerefBdd(dd,suppF); if (commonSupport == DD_ONE(dd)) { Cudd_IterDerefBdd(dd,commonSupport); Cudd_IterDerefBdd(dd,suppC); return(f); } Cudd_IterDerefBdd(dd,commonSupport); /* Abstract from c the variables that do not appear in f. */ cplus = Cudd_bddExistAbstract(dd, c, suppC); if (cplus == NULL) { Cudd_IterDerefBdd(dd,suppC); return(NULL); } cuddRef(cplus); Cudd_IterDerefBdd(dd,suppC); do { dd->reordered = 0; res = cuddBddRestrictRecur(dd, f, cplus); } while (dd->reordered == 1); if (res == NULL) { Cudd_IterDerefBdd(dd,cplus); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(dd,cplus); /* Make restric safe by returning the smaller of the input and the ** result. */ sizeF = Cudd_DagSize(f); sizeRes = Cudd_DagSize(res); if (sizeF <= sizeRes) { Cudd_IterDerefBdd(dd, res); return(f); } else { cuddDeref(res); return(res); } } /* end of Cudd_bddRestrict */ /**Function******************************************************************** Synopsis [Computes f non-polluting-and g.] Description [Computes f non-polluting-and g. The non-polluting AND of f and g is a hybrid of AND and Restrict. From Restrict, this operation takes the idea of existentially quantifying the top variable of the second operand if it does not appear in the first. Therefore, the variables that appear in the result also appear in f. For the rest, the function behaves like AND. Since the two operands play different roles, non-polluting AND is not commutative. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddConstrain Cudd_bddRestrict] ******************************************************************************/ DdNode * Cudd_bddNPAnd( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddBddNPAndRecur(dd,f,g); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddNPAnd */ /**Function******************************************************************** Synopsis [Computes f constrain c for ADDs.] Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1 ADD. List of special cases:
      • F @ 0 = 0
      • F @ 1 = F
      • 0 @ c = 0
      • 1 @ c = 1
      • F @ F = 1
      Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddConstrain] ******************************************************************************/ DdNode * Cudd_addConstrain( DdManager * dd, DdNode * f, DdNode * c) { DdNode *res; do { dd->reordered = 0; res = cuddAddConstrainRecur(dd,f,c); } while (dd->reordered == 1); return(res); } /* end of Cudd_addConstrain */ /**Function******************************************************************** Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.] Description [BDD conjunctive decomposition as in McMillan's CAV96 paper. The decomposition is canonical only for a given variable order. If canonicity is required, variable ordering must be disabled after the decomposition has been computed. Returns an array with one entry for each BDD variable in the manager if successful; otherwise NULL. The components of the solution have their reference counts already incremented (unlike the results of most other functions in the package.] SideEffects [None] SeeAlso [Cudd_bddConstrain Cudd_bddExistAbstract] ******************************************************************************/ DdNode ** Cudd_bddConstrainDecomp( DdManager * dd, DdNode * f) { DdNode **decomp; int res; int i; /* Create an initialize decomposition array. */ decomp = ABC_ALLOC(DdNode *,dd->size); if (decomp == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < dd->size; i++) { decomp[i] = NULL; } do { dd->reordered = 0; /* Clean up the decomposition array in case reordering took place. */ for (i = 0; i < dd->size; i++) { if (decomp[i] != NULL) { Cudd_IterDerefBdd(dd, decomp[i]); decomp[i] = NULL; } } res = cuddBddConstrainDecomp(dd,f,decomp); } while (dd->reordered == 1); if (res == 0) { ABC_FREE(decomp); return(NULL); } /* Missing components are constant ones. */ for (i = 0; i < dd->size; i++) { if (decomp[i] == NULL) { decomp[i] = DD_ONE(dd); cuddRef(decomp[i]); } } return(decomp); } /* end of Cudd_bddConstrainDecomp */ /**Function******************************************************************** Synopsis [ADD restrict according to Coudert and Madre's algorithm (ICCAD90).] Description [ADD restrict according to Coudert and Madre's algorithm (ICCAD90). Returns the restricted ADD if successful; otherwise NULL. If application of restrict results in an ADD larger than the input ADD, the input ADD is returned.] SideEffects [None] SeeAlso [Cudd_addConstrain Cudd_bddRestrict] ******************************************************************************/ DdNode * Cudd_addRestrict( DdManager * dd, DdNode * f, DdNode * c) { DdNode *supp_f, *supp_c; DdNode *res, *commonSupport; int intersection; int sizeF, sizeRes; /* Check if supports intersect. */ supp_f = Cudd_Support(dd, f); if (supp_f == NULL) { return(NULL); } cuddRef(supp_f); supp_c = Cudd_Support(dd, c); if (supp_c == NULL) { Cudd_RecursiveDeref(dd,supp_f); return(NULL); } cuddRef(supp_c); commonSupport = Cudd_bddLiteralSetIntersection(dd, supp_f, supp_c); if (commonSupport == NULL) { Cudd_RecursiveDeref(dd,supp_f); Cudd_RecursiveDeref(dd,supp_c); return(NULL); } cuddRef(commonSupport); Cudd_RecursiveDeref(dd,supp_f); Cudd_RecursiveDeref(dd,supp_c); intersection = commonSupport != DD_ONE(dd); Cudd_RecursiveDeref(dd,commonSupport); if (intersection) { do { dd->reordered = 0; res = cuddAddRestrictRecur(dd, f, c); } while (dd->reordered == 1); sizeF = Cudd_DagSize(f); sizeRes = Cudd_DagSize(res); if (sizeF <= sizeRes) { cuddRef(res); Cudd_RecursiveDeref(dd, res); return(f); } else { return(res); } } else { return(f); } } /* end of Cudd_addRestrict */ /**Function******************************************************************** Synopsis [Computes a vector whose image equals a non-zero function.] Description [Computes a vector of BDDs whose image equals a non-zero function. The result depends on the variable order. The i-th component of the vector depends only on the first i variables in the order. Each BDD in the vector is not larger than the BDD of the given characteristic function. This function is based on the description of char-to-vect in "Verification of Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C. Berthet and J. C. Madre. Returns a pointer to an array containing the result if successful; NULL otherwise. The size of the array equals the number of variables in the manager. The components of the solution have their reference counts already incremented (unlike the results of most other functions in the package).] SideEffects [None] SeeAlso [Cudd_bddConstrain] ******************************************************************************/ DdNode ** Cudd_bddCharToVect( DdManager * dd, DdNode * f) { int i, j; DdNode **vect; DdNode *res = NULL; if (f == Cudd_Not(DD_ONE(dd))) return(NULL); vect = ABC_ALLOC(DdNode *, dd->size); if (vect == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } do { dd->reordered = 0; for (i = 0; i < dd->size; i++) { res = cuddBddCharToVect(dd,f,dd->vars[dd->invperm[i]]); if (res == NULL) { /* Clean up the vector array in case reordering took place. */ for (j = 0; j < i; j++) { Cudd_IterDerefBdd(dd, vect[dd->invperm[j]]); } break; } cuddRef(res); vect[dd->invperm[i]] = res; } } while (dd->reordered == 1); if (res == NULL) { ABC_FREE(vect); return(NULL); } return(vect); } /* end of Cudd_bddCharToVect */ /**Function******************************************************************** Synopsis [Performs safe minimization of a BDD.] Description [Performs safe minimization of a BDD. Given the BDD f of a function to be minimized and a BDD c representing the care set, Cudd_bddLICompaction produces the BDD of a function that agrees with f wherever c is 1. Safe minimization means that the size of the result is guaranteed not to exceed the size of f. This function is based on the DAC97 paper by Hong et al.. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddRestrict] ******************************************************************************/ DdNode * Cudd_bddLICompaction( DdManager * dd /* manager */, DdNode * f /* function to be minimized */, DdNode * c /* constraint (care set) */) { DdNode *res; do { dd->reordered = 0; res = cuddBddLICompaction(dd,f,c); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddLICompaction */ /**Function******************************************************************** Synopsis [Finds a small BDD in a function interval.] Description [Finds a small BDD in a function interval. Given BDDs l and u, representing the lower bound and upper bound of a function interval, Cudd_bddSqueeze produces the BDD of a function within the interval with a small BDD. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction] ******************************************************************************/ DdNode * Cudd_bddSqueeze( DdManager * dd /* manager */, DdNode * l /* lower bound */, DdNode * u /* upper bound */) { DdNode *res; int sizeRes, sizeL, sizeU; do { dd->reordered = 0; res = cuddBddSqueeze(dd,l,u); } while (dd->reordered == 1); if (res == NULL) return(NULL); /* We now compare the result with the bounds and return the smallest. ** We first compare to u, so that in case l == 0 and u == 1, we return ** 0 as in other minimization algorithms. */ sizeRes = Cudd_DagSize(res); sizeU = Cudd_DagSize(u); if (sizeU <= sizeRes) { cuddRef(res); Cudd_IterDerefBdd(dd,res); res = u; sizeRes = sizeU; } sizeL = Cudd_DagSize(l); if (sizeL <= sizeRes) { cuddRef(res); Cudd_IterDerefBdd(dd,res); res = l; sizeRes = sizeL; } return(res); } /* end of Cudd_bddSqueeze */ /**Function******************************************************************** Synopsis [Finds a small BDD that agrees with f over c.] Description [Finds a small BDD that agrees with f over c. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze] ******************************************************************************/ DdNode * Cudd_bddMinimize( DdManager * dd, DdNode * f, DdNode * c) { DdNode *cplus, *res; if (c == Cudd_Not(DD_ONE(dd))) return(c); if (Cudd_IsConstant(f)) return(f); if (f == c) return(DD_ONE(dd)); if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd))); cplus = Cudd_RemapOverApprox(dd,c,0,0,1.0); if (cplus == NULL) return(NULL); cuddRef(cplus); res = Cudd_bddLICompaction(dd,f,cplus); if (res == NULL) { Cudd_IterDerefBdd(dd,cplus); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(dd,cplus); cuddDeref(res); return(res); } /* end of Cudd_bddMinimize */ /**Function******************************************************************** Synopsis [Find a dense subset of BDD f.] Description [Finds a dense subset of BDD f. Density is the ratio of number of minterms to number of nodes. Uses several techniques in series. It is more expensive than other subsetting procedures, but often produces better results. See Cudd_SubsetShortPaths for a description of the threshold and nvars parameters. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_SubsetRemap Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_bddSqueeze] ******************************************************************************/ DdNode * Cudd_SubsetCompress( DdManager * dd /* manager */, DdNode * f /* BDD whose subset is sought */, int nvars /* number of variables in the support of f */, int threshold /* maximum number of nodes in the subset */) { DdNode *res, *tmp1, *tmp2; tmp1 = Cudd_SubsetShortPaths(dd, f, nvars, threshold, 0); if (tmp1 == NULL) return(NULL); cuddRef(tmp1); tmp2 = Cudd_RemapUnderApprox(dd,tmp1,nvars,0,1.0); if (tmp2 == NULL) { Cudd_IterDerefBdd(dd,tmp1); return(NULL); } cuddRef(tmp2); Cudd_IterDerefBdd(dd,tmp1); res = Cudd_bddSqueeze(dd,tmp2,f); if (res == NULL) { Cudd_IterDerefBdd(dd,tmp2); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(dd,tmp2); cuddDeref(res); return(res); } /* end of Cudd_SubsetCompress */ /**Function******************************************************************** Synopsis [Find a dense superset of BDD f.] Description [Finds a dense superset of BDD f. Density is the ratio of number of minterms to number of nodes. Uses several techniques in series. It is more expensive than other supersetting procedures, but often produces better results. See Cudd_SupersetShortPaths for a description of the threshold and nvars parameters. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths Cudd_SupersetHeavyBranch Cudd_bddSqueeze] ******************************************************************************/ DdNode * Cudd_SupersetCompress( DdManager * dd /* manager */, DdNode * f /* BDD whose superset is sought */, int nvars /* number of variables in the support of f */, int threshold /* maximum number of nodes in the superset */) { DdNode *subset; subset = Cudd_SubsetCompress(dd, Cudd_Not(f),nvars,threshold); return(Cudd_NotCond(subset, (subset != NULL))); } /* end of Cudd_SupersetCompress */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddConstrain.] Description [Performs the recursive step of Cudd_bddConstrain. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddConstrain] ******************************************************************************/ DdNode * cuddBddConstrainRecur( DdManager * dd, DdNode * f, DdNode * c) { DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; DdNode *one, *zero; unsigned int topf, topc; int index; int comple = 0; statLine(dd); one = DD_ONE(dd); zero = Cudd_Not(one); /* Trivial cases. */ if (c == one) return(f); if (c == zero) return(zero); if (Cudd_IsConstant(f)) return(f); if (f == c) return(one); if (f == Cudd_Not(c)) return(zero); /* Make canonical to increase the utilization of the cache. */ if (Cudd_IsComplement(f)) { f = Cudd_Not(f); comple = 1; } /* Now f is a regular pointer to a non-constant node; c is also ** non-constant, but may be complemented. */ /* Check the cache. */ r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c); if (r != NULL) { return(Cudd_NotCond(r,comple)); } /* Recursive step. */ topf = dd->perm[f->index]; topc = dd->perm[Cudd_Regular(c)->index]; if (topf <= topc) { index = f->index; Fv = cuddT(f); Fnv = cuddE(f); } else { index = Cudd_Regular(c)->index; Fv = Fnv = f; } if (topc <= topf) { Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); if (Cudd_IsComplement(c)) { Cv = Cudd_Not(Cv); Cnv = Cudd_Not(Cnv); } } else { Cv = Cnv = c; } if (!Cudd_IsConstant(Cv)) { t = cuddBddConstrainRecur(dd, Fv, Cv); if (t == NULL) return(NULL); } else if (Cv == one) { t = Fv; } else { /* Cv == zero: return Fnv @ Cnv */ if (Cnv == one) { r = Fnv; } else { r = cuddBddConstrainRecur(dd, Fnv, Cnv); if (r == NULL) return(NULL); } return(Cudd_NotCond(r,comple)); } cuddRef(t); if (!Cudd_IsConstant(Cnv)) { e = cuddBddConstrainRecur(dd, Fnv, Cnv); if (e == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } } else if (Cnv == one) { e = Fnv; } else { /* Cnv == zero: return Fv @ Cv previously computed */ cuddDeref(t); return(Cudd_NotCond(t,comple)); } cuddRef(e); if (Cudd_IsComplement(t)) { t = Cudd_Not(t); e = Cudd_Not(e); r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); Cudd_IterDerefBdd(dd, t); return(NULL); } r = Cudd_Not(r); } else { r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); Cudd_IterDerefBdd(dd, t); return(NULL); } } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r); return(Cudd_NotCond(r,comple)); } /* end of cuddBddConstrainRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddRestrict.] Description [Performs the recursive step of Cudd_bddRestrict. Returns the restricted BDD if successful; otherwise NULL.] SideEffects [None] SeeAlso [Cudd_bddRestrict] ******************************************************************************/ DdNode * cuddBddRestrictRecur( DdManager * dd, DdNode * f, DdNode * c) { DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; unsigned int topf, topc; int index; int comple = 0; statLine(dd); one = DD_ONE(dd); zero = Cudd_Not(one); /* Trivial cases */ if (c == one) return(f); if (c == zero) return(zero); if (Cudd_IsConstant(f)) return(f); if (f == c) return(one); if (f == Cudd_Not(c)) return(zero); /* Make canonical to increase the utilization of the cache. */ if (Cudd_IsComplement(f)) { f = Cudd_Not(f); comple = 1; } /* Now f is a regular pointer to a non-constant node; c is also ** non-constant, but may be complemented. */ /* Check the cache. */ r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c); if (r != NULL) { return(Cudd_NotCond(r,comple)); } topf = dd->perm[f->index]; topc = dd->perm[Cudd_Regular(c)->index]; if (topc < topf) { /* abstract top variable from c */ DdNode *d, *s1, *s2; /* Find complements of cofactors of c. */ if (Cudd_IsComplement(c)) { s1 = cuddT(Cudd_Regular(c)); s2 = cuddE(Cudd_Regular(c)); } else { s1 = Cudd_Not(cuddT(c)); s2 = Cudd_Not(cuddE(c)); } /* Take the OR by applying DeMorgan. */ d = cuddBddAndRecur(dd, s1, s2); if (d == NULL) return(NULL); d = Cudd_Not(d); cuddRef(d); r = cuddBddRestrictRecur(dd, f, d); if (r == NULL) { Cudd_IterDerefBdd(dd, d); return(NULL); } cuddRef(r); Cudd_IterDerefBdd(dd, d); cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); cuddDeref(r); return(Cudd_NotCond(r,comple)); } /* Recursive step. Here topf <= topc. */ index = f->index; Fv = cuddT(f); Fnv = cuddE(f); if (topc == topf) { Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); if (Cudd_IsComplement(c)) { Cv = Cudd_Not(Cv); Cnv = Cudd_Not(Cnv); } } else { Cv = Cnv = c; } if (!Cudd_IsConstant(Cv)) { t = cuddBddRestrictRecur(dd, Fv, Cv); if (t == NULL) return(NULL); } else if (Cv == one) { t = Fv; } else { /* Cv == zero: return(Fnv @ Cnv) */ if (Cnv == one) { r = Fnv; } else { r = cuddBddRestrictRecur(dd, Fnv, Cnv); if (r == NULL) return(NULL); } return(Cudd_NotCond(r,comple)); } cuddRef(t); if (!Cudd_IsConstant(Cnv)) { e = cuddBddRestrictRecur(dd, Fnv, Cnv); if (e == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } } else if (Cnv == one) { e = Fnv; } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ cuddDeref(t); return(Cudd_NotCond(t,comple)); } cuddRef(e); if (Cudd_IsComplement(t)) { t = Cudd_Not(t); e = Cudd_Not(e); r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); Cudd_IterDerefBdd(dd, t); return(NULL); } r = Cudd_Not(r); } else { r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); Cudd_IterDerefBdd(dd, t); return(NULL); } } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); return(Cudd_NotCond(r,comple)); } /* end of cuddBddRestrictRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddAnd.] Description [Implements the recursive step of Cudd_bddNPAnd. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddNPAnd] ******************************************************************************/ DdNode * cuddBddNPAndRecur( DdManager * manager, DdNode * f, DdNode * g) { DdNode *F, *ft, *fe, *G, *gt, *ge; DdNode *one, *r, *t, *e; unsigned int topf, topg, index; statLine(manager); one = DD_ONE(manager); /* Terminal cases. */ F = Cudd_Regular(f); G = Cudd_Regular(g); if (F == G) { if (f == g) return(one); else return(Cudd_Not(one)); } if (G == one) { if (g == one) return(f); else return(g); } if (F == one) { return(f); } /* At this point f and g are not constant. */ /* Check cache. */ if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup2(manager, Cudd_bddNPAnd, f, g); if (r != NULL) return(r); } /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[F->index]; topg = manager->perm[G->index]; if (topg < topf) { /* abstract top variable from g */ DdNode *d; /* Find complements of cofactors of g. */ if (Cudd_IsComplement(g)) { gt = cuddT(G); ge = cuddE(G); } else { gt = Cudd_Not(cuddT(g)); ge = Cudd_Not(cuddE(g)); } /* Take the OR by applying DeMorgan. */ d = cuddBddAndRecur(manager, gt, ge); if (d == NULL) return(NULL); d = Cudd_Not(d); cuddRef(d); r = cuddBddNPAndRecur(manager, f, d); if (r == NULL) { Cudd_IterDerefBdd(manager, d); return(NULL); } cuddRef(r); Cudd_IterDerefBdd(manager, d); cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r); cuddDeref(r); return(r); } /* Compute cofactors. */ index = F->index; ft = cuddT(F); fe = cuddE(F); if (Cudd_IsComplement(f)) { ft = Cudd_Not(ft); fe = Cudd_Not(fe); } if (topg == topf) { gt = cuddT(G); ge = cuddE(G); if (Cudd_IsComplement(g)) { gt = Cudd_Not(gt); ge = Cudd_Not(ge); } } else { gt = ge = g; } t = cuddBddAndRecur(manager, ft, gt); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddAndRecur(manager, fe, ge); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } } cuddDeref(e); cuddDeref(t); if (F->ref != 1 || G->ref != 1) cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r); return(r); } /* end of cuddBddNPAndRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addConstrain.] Description [Performs the recursive step of Cudd_addConstrain. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addConstrain] ******************************************************************************/ DdNode * cuddAddConstrainRecur( DdManager * dd, DdNode * f, DdNode * c) { DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; DdNode *one, *zero; unsigned int topf, topc; int index; statLine(dd); one = DD_ONE(dd); zero = DD_ZERO(dd); /* Trivial cases. */ if (c == one) return(f); if (c == zero) return(zero); if (Cudd_IsConstant(f)) return(f); if (f == c) return(one); /* Now f and c are non-constant. */ /* Check the cache. */ r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c); if (r != NULL) { return(r); } /* Recursive step. */ topf = dd->perm[f->index]; topc = dd->perm[c->index]; if (topf <= topc) { index = f->index; Fv = cuddT(f); Fnv = cuddE(f); } else { index = c->index; Fv = Fnv = f; } if (topc <= topf) { Cv = cuddT(c); Cnv = cuddE(c); } else { Cv = Cnv = c; } if (!Cudd_IsConstant(Cv)) { t = cuddAddConstrainRecur(dd, Fv, Cv); if (t == NULL) return(NULL); } else if (Cv == one) { t = Fv; } else { /* Cv == zero: return Fnv @ Cnv */ if (Cnv == one) { r = Fnv; } else { r = cuddAddConstrainRecur(dd, Fnv, Cnv); if (r == NULL) return(NULL); } return(r); } cuddRef(t); if (!Cudd_IsConstant(Cnv)) { e = cuddAddConstrainRecur(dd, Fnv, Cnv); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } } else if (Cnv == one) { e = Fnv; } else { /* Cnv == zero: return Fv @ Cv previously computed */ cuddDeref(t); return(t); } cuddRef(e); r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r); return(r); } /* end of cuddAddConstrainRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addRestrict.] Description [Performs the recursive step of Cudd_addRestrict. Returns the restricted ADD if successful; otherwise NULL.] SideEffects [None] SeeAlso [Cudd_addRestrict] ******************************************************************************/ DdNode * cuddAddRestrictRecur( DdManager * dd, DdNode * f, DdNode * c) { DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; unsigned int topf, topc; int index; statLine(dd); one = DD_ONE(dd); zero = DD_ZERO(dd); /* Trivial cases */ if (c == one) return(f); if (c == zero) return(zero); if (Cudd_IsConstant(f)) return(f); if (f == c) return(one); /* Now f and c are non-constant. */ /* Check the cache. */ r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c); if (r != NULL) { return(r); } topf = dd->perm[f->index]; topc = dd->perm[c->index]; if (topc < topf) { /* abstract top variable from c */ DdNode *d, *s1, *s2; /* Find cofactors of c. */ s1 = cuddT(c); s2 = cuddE(c); /* Take the OR by applying DeMorgan. */ d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2); if (d == NULL) return(NULL); cuddRef(d); r = cuddAddRestrictRecur(dd, f, d); if (r == NULL) { Cudd_RecursiveDeref(dd, d); return(NULL); } cuddRef(r); Cudd_RecursiveDeref(dd, d); cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); cuddDeref(r); return(r); } /* Recursive step. Here topf <= topc. */ index = f->index; Fv = cuddT(f); Fnv = cuddE(f); if (topc == topf) { Cv = cuddT(c); Cnv = cuddE(c); } else { Cv = Cnv = c; } if (!Cudd_IsConstant(Cv)) { t = cuddAddRestrictRecur(dd, Fv, Cv); if (t == NULL) return(NULL); } else if (Cv == one) { t = Fv; } else { /* Cv == zero: return(Fnv @ Cnv) */ if (Cnv == one) { r = Fnv; } else { r = cuddAddRestrictRecur(dd, Fnv, Cnv); if (r == NULL) return(NULL); } return(r); } cuddRef(t); if (!Cudd_IsConstant(Cnv)) { e = cuddAddRestrictRecur(dd, Fnv, Cnv); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } } else if (Cnv == one) { e = Fnv; } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ cuddDeref(t); return(t); } cuddRef(e); r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); return(r); } /* end of cuddAddRestrictRecur */ /**Function******************************************************************** Synopsis [Performs safe minimization of a BDD.] Description [Performs safe minimization of a BDD. Given the BDD f of a function to be minimized and a BDD c representing the care set, Cudd_bddLICompaction produces the BDD of a function that agrees with f wherever c is 1. Safe minimization means that the size of the result is guaranteed not to exceed the size of f. This function is based on the DAC97 paper by Hong et al.. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddLICompaction] ******************************************************************************/ DdNode * cuddBddLICompaction( DdManager * dd /* manager */, DdNode * f /* function to be minimized */, DdNode * c /* constraint (care set) */) { st__table *marktable, *markcache, *buildcache; DdNode *res, *zero; zero = Cudd_Not(DD_ONE(dd)); if (c == zero) return(zero); /* We need to use local caches for both steps of this operation. ** The results of the edge marking step are only valid as long as the ** edge markings themselves are available. However, the edge markings ** are lost at the end of one invocation of Cudd_bddLICompaction. ** Hence, the cache entries for the edge marking step must be ** invalidated at the end of this function. ** For the result of the building step we argue as follows. The result ** for a node and a given constrain depends on the BDD in which the node ** appears. Hence, the same node and constrain may give different results ** in successive invocations. */ marktable = st__init_table( st__ptrcmp, st__ptrhash); if (marktable == NULL) { return(NULL); } markcache = st__init_table(MarkCacheCompare,MarkCacheHash); if (markcache == NULL) { st__free_table(marktable); return(NULL); } if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) { st__foreach(markcache, MarkCacheCleanUp, NULL); st__free_table(marktable); st__free_table(markcache); return(NULL); } st__foreach(markcache, MarkCacheCleanUp, NULL); st__free_table(markcache); buildcache = st__init_table( st__ptrcmp, st__ptrhash); if (buildcache == NULL) { st__free_table(marktable); return(NULL); } res = cuddBddLICBuildResult(dd,f,buildcache,marktable); st__free_table(buildcache); st__free_table(marktable); return(res); } /* end of cuddBddLICompaction */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddConstrainDecomp.] Description [Performs the recursive step of Cudd_bddConstrainDecomp. Returns f super (i) if successful; otherwise NULL.] SideEffects [None] SeeAlso [Cudd_bddConstrainDecomp] ******************************************************************************/ static int cuddBddConstrainDecomp( DdManager * dd, DdNode * f, DdNode ** decomp) { DdNode *F, *fv, *fvn; DdNode *fAbs; DdNode *result; int ok; if (Cudd_IsConstant(f)) return(1); /* Compute complements of cofactors. */ F = Cudd_Regular(f); fv = cuddT(F); fvn = cuddE(F); if (F == f) { fv = Cudd_Not(fv); fvn = Cudd_Not(fvn); } /* Compute abstraction of top variable. */ fAbs = cuddBddAndRecur(dd, fv, fvn); if (fAbs == NULL) { return(0); } cuddRef(fAbs); fAbs = Cudd_Not(fAbs); /* Recursively find the next abstraction and the components of the ** decomposition. */ ok = cuddBddConstrainDecomp(dd, fAbs, decomp); if (ok == 0) { Cudd_IterDerefBdd(dd,fAbs); return(0); } /* Compute the component of the decomposition corresponding to the ** top variable and store it in the decomposition array. */ result = cuddBddConstrainRecur(dd, f, fAbs); if (result == NULL) { Cudd_IterDerefBdd(dd,fAbs); return(0); } cuddRef(result); decomp[F->index] = result; Cudd_IterDerefBdd(dd, fAbs); return(1); } /* end of cuddBddConstrainDecomp */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddCharToVect.] Description [Performs the recursive step of Cudd_bddCharToVect. This function maintains the invariant that f is non-zero. Returns the i-th component of the vector if successful; otherwise NULL.] SideEffects [None] SeeAlso [Cudd_bddCharToVect] ******************************************************************************/ static DdNode * cuddBddCharToVect( DdManager * dd, DdNode * f, DdNode * x) { unsigned int topf; unsigned int level; int comple; DdNode *one, *zero, *res, *F, *fT, *fE, *T, *E; statLine(dd); /* Check the cache. */ res = cuddCacheLookup2(dd, cuddBddCharToVect, f, x); if (res != NULL) { return(res); } F = Cudd_Regular(f); topf = cuddI(dd,F->index); level = dd->perm[x->index]; if (topf > level) return(x); one = DD_ONE(dd); zero = Cudd_Not(one); comple = F != f; fT = Cudd_NotCond(cuddT(F),comple); fE = Cudd_NotCond(cuddE(F),comple); if (topf == level) { if (fT == zero) return(zero); if (fE == zero) return(one); return(x); } /* Here topf < level. */ if (fT == zero) return(cuddBddCharToVect(dd, fE, x)); if (fE == zero) return(cuddBddCharToVect(dd, fT, x)); T = cuddBddCharToVect(dd, fT, x); if (T == NULL) { return(NULL); } cuddRef(T); E = cuddBddCharToVect(dd, fE, x); if (E == NULL) { Cudd_IterDerefBdd(dd,T); return(NULL); } cuddRef(E); res = cuddBddIteRecur(dd, dd->vars[F->index], T, E); if (res == NULL) { Cudd_IterDerefBdd(dd,T); Cudd_IterDerefBdd(dd,E); return(NULL); } cuddDeref(T); cuddDeref(E); cuddCacheInsert2(dd, cuddBddCharToVect, f, x, res); return(res); } /* end of cuddBddCharToVect */ /**Function******************************************************************** Synopsis [Performs the edge marking step of Cudd_bddLICompaction.] Description [Performs the edge marking step of Cudd_bddLICompaction. Returns the LUB of the markings of the two outgoing edges of f if successful; otherwise CUDD_OUT_OF_MEM.] SideEffects [None] SeeAlso [Cudd_bddLICompaction cuddBddLICBuildResult] ******************************************************************************/ static int cuddBddLICMarkEdges( DdManager * dd, DdNode * f, DdNode * c, st__table * table, st__table * cache) { DdNode *Fv, *Fnv, *Cv, *Cnv; DdNode *one, *zero; unsigned int topf, topc; int comple; int resT, resE, res, retval; char **slot; MarkCacheKey *key; one = DD_ONE(dd); zero = Cudd_Not(one); /* Terminal cases. */ if (c == zero) return(DD_LIC_DC); if (f == one) return(DD_LIC_1); if (f == zero) return(DD_LIC_0); /* Make canonical to increase the utilization of the cache. */ comple = Cudd_IsComplement(f); f = Cudd_Regular(f); /* Now f is a regular pointer to a non-constant node; c may be ** constant, or it may be complemented. */ /* Check the cache. */ key = ABC_ALLOC(MarkCacheKey, 1); if (key == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(CUDD_OUT_OF_MEM); } key->f = f; key->c = c; if ( st__lookup_int(cache, (char *)key, &res)) { ABC_FREE(key); if (comple) { if (res == DD_LIC_0) res = DD_LIC_1; else if (res == DD_LIC_1) res = DD_LIC_0; } return(res); } /* Recursive step. */ topf = dd->perm[f->index]; topc = cuddI(dd,Cudd_Regular(c)->index); if (topf <= topc) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } if (topc <= topf) { /* We know that c is not constant because f is not. */ Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); if (Cudd_IsComplement(c)) { Cv = Cudd_Not(Cv); Cnv = Cudd_Not(Cnv); } } else { Cv = Cnv = c; } resT = cuddBddLICMarkEdges(dd, Fv, Cv, table, cache); if (resT == CUDD_OUT_OF_MEM) { ABC_FREE(key); return(CUDD_OUT_OF_MEM); } resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache); if (resE == CUDD_OUT_OF_MEM) { ABC_FREE(key); return(CUDD_OUT_OF_MEM); } /* Update edge markings. */ if (topf <= topc) { retval = st__find_or_add(table, (char *)f, (char ***)&slot); if (retval == 0) { *slot = (char *) (ptrint)((resT << 2) | resE); } else if (retval == 1) { *slot = (char *) (ptrint)((int)((ptrint) *slot) | (resT << 2) | resE); } else { ABC_FREE(key); return(CUDD_OUT_OF_MEM); } } /* Cache result. */ res = resT | resE; if ( st__insert(cache, (char *)key, (char *)(ptrint)res) == st__OUT_OF_MEM) { ABC_FREE(key); return(CUDD_OUT_OF_MEM); } /* Take into account possible complementation. */ if (comple) { if (res == DD_LIC_0) res = DD_LIC_1; else if (res == DD_LIC_1) res = DD_LIC_0; } return(res); } /* end of cuddBddLICMarkEdges */ /**Function******************************************************************** Synopsis [Builds the result of Cudd_bddLICompaction.] Description [Builds the results of Cudd_bddLICompaction. Returns a pointer to the minimized BDD if successful; otherwise NULL.] SideEffects [None] SeeAlso [Cudd_bddLICompaction cuddBddLICMarkEdges] ******************************************************************************/ static DdNode * cuddBddLICBuildResult( DdManager * dd, DdNode * f, st__table * cache, st__table * table) { DdNode *Fv, *Fnv, *r, *t, *e; DdNode *one, *zero; int index; int comple; int markT, markE, markings; one = DD_ONE(dd); zero = Cudd_Not(one); if (Cudd_IsConstant(f)) return(f); /* Make canonical to increase the utilization of the cache. */ comple = Cudd_IsComplement(f); f = Cudd_Regular(f); /* Check the cache. */ if ( st__lookup(cache, (const char *)f, (char **)&r)) { return(Cudd_NotCond(r,comple)); } /* Retrieve the edge markings. */ if ( st__lookup_int(table, (char *)f, &markings) == 0) return(NULL); markT = markings >> 2; markE = markings & 3; index = f->index; Fv = cuddT(f); Fnv = cuddE(f); if (markT == DD_LIC_NL) { t = cuddBddLICBuildResult(dd,Fv,cache,table); if (t == NULL) { return(NULL); } } else if (markT == DD_LIC_1) { t = one; } else { t = zero; } cuddRef(t); if (markE == DD_LIC_NL) { e = cuddBddLICBuildResult(dd,Fnv,cache,table); if (e == NULL) { Cudd_IterDerefBdd(dd,t); return(NULL); } } else if (markE == DD_LIC_1) { e = one; } else { e = zero; } cuddRef(e); if (markT == DD_LIC_DC && markE != DD_LIC_DC) { r = e; } else if (markT != DD_LIC_DC && markE == DD_LIC_DC) { r = t; } else { if (Cudd_IsComplement(t)) { t = Cudd_Not(t); e = Cudd_Not(e); r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); Cudd_IterDerefBdd(dd, t); return(NULL); } r = Cudd_Not(r); } else { r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); Cudd_IterDerefBdd(dd, t); return(NULL); } } } cuddDeref(t); cuddDeref(e); if ( st__insert(cache, (char *)f, (char *)r) == st__OUT_OF_MEM) { cuddRef(r); Cudd_IterDerefBdd(dd,r); return(NULL); } return(Cudd_NotCond(r,comple)); } /* end of cuddBddLICBuildResult */ /**Function******************************************************************** Synopsis [Hash function for the computed table of cuddBddLICMarkEdges.] Description [Hash function for the computed table of cuddBddLICMarkEdges. Returns the bucket number.] SideEffects [None] SeeAlso [Cudd_bddLICompaction] ******************************************************************************/ static int MarkCacheHash( const char * ptr, int modulus) { int val = 0; MarkCacheKey *entry; entry = (MarkCacheKey *) ptr; val = (int) (ptrint) entry->f; val = val * 997 + (int) (ptrint) entry->c; return ((val < 0) ? -val : val) % modulus; } /* end of MarkCacheHash */ /**Function******************************************************************** Synopsis [Comparison function for the computed table of cuddBddLICMarkEdges.] Description [Comparison function for the computed table of cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1 otherwise.] SideEffects [None] SeeAlso [Cudd_bddLICompaction] ******************************************************************************/ static int MarkCacheCompare( const char * ptr1, const char * ptr2) { MarkCacheKey *entry1, *entry2; entry1 = (MarkCacheKey *) ptr1; entry2 = (MarkCacheKey *) ptr2; return((entry1->f != entry2->f) || (entry1->c != entry2->c)); } /* end of MarkCacheCompare */ /**Function******************************************************************** Synopsis [Frees memory associated with computed table of cuddBddLICMarkEdges.] Description [Frees memory associated with computed table of cuddBddLICMarkEdges. Returns st__CONTINUE.] SideEffects [None] SeeAlso [Cudd_bddLICompaction] ******************************************************************************/ static enum st__retval MarkCacheCleanUp( char * key, char * value, char * arg) { MarkCacheKey *entry; entry = (MarkCacheKey *) key; ABC_FREE(entry); return st__CONTINUE; } /* end of MarkCacheCleanUp */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddSqueeze.] Description [Performs the recursive step of Cudd_bddSqueeze. This procedure exploits the fact that if we complement and swap the bounds of the interval we obtain a valid solution by taking the complement of the solution to the original problem. Therefore, we can enforce the condition that the upper bound is always regular. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddSqueeze] ******************************************************************************/ static DdNode * cuddBddSqueeze( DdManager * dd, DdNode * l, DdNode * u) { DdNode *one, *zero, *r, *lt, *le, *ut, *ue, *t, *e; #if 0 DdNode *ar; #endif int comple = 0; unsigned int topu, topl; int index; statLine(dd); if (l == u) { return(l); } one = DD_ONE(dd); zero = Cudd_Not(one); /* The only case when l == zero && u == one is at the top level, ** where returning either one or zero is OK. In all other cases ** the procedure will detect such a case and will perform ** remapping. Therefore the order in which we test l and u at this ** point is immaterial. */ if (l == zero) return(l); if (u == one) return(u); /* Make canonical to increase the utilization of the cache. */ if (Cudd_IsComplement(u)) { DdNode *temp; temp = Cudd_Not(l); l = Cudd_Not(u); u = temp; comple = 1; } /* At this point u is regular and non-constant; l is non-constant, but ** may be complemented. */ /* Here we could check the relative sizes. */ /* Check the cache. */ r = cuddCacheLookup2(dd, Cudd_bddSqueeze, l, u); if (r != NULL) { return(Cudd_NotCond(r,comple)); } /* Recursive step. */ topu = dd->perm[u->index]; topl = dd->perm[Cudd_Regular(l)->index]; if (topu <= topl) { index = u->index; ut = cuddT(u); ue = cuddE(u); } else { index = Cudd_Regular(l)->index; ut = ue = u; } if (topl <= topu) { lt = cuddT(Cudd_Regular(l)); le = cuddE(Cudd_Regular(l)); if (Cudd_IsComplement(l)) { lt = Cudd_Not(lt); le = Cudd_Not(le); } } else { lt = le = l; } /* If one interval is contained in the other, use the smaller ** interval. This corresponds to one-sided matching. */ if ((lt == zero || Cudd_bddLeq(dd,lt,le)) && (ut == one || Cudd_bddLeq(dd,ue,ut))) { /* remap */ r = cuddBddSqueeze(dd, le, ue); if (r == NULL) return(NULL); return(Cudd_NotCond(r,comple)); } else if ((le == zero || Cudd_bddLeq(dd,le,lt)) && (ue == one || Cudd_bddLeq(dd,ut,ue))) { /* remap */ r = cuddBddSqueeze(dd, lt, ut); if (r == NULL) return(NULL); return(Cudd_NotCond(r,comple)); } else if ((le == zero || Cudd_bddLeq(dd,le,Cudd_Not(ut))) && (ue == one || Cudd_bddLeq(dd,Cudd_Not(lt),ue))) { /* c-remap */ t = cuddBddSqueeze(dd, lt, ut); cuddRef(t); if (Cudd_IsComplement(t)) { r = cuddUniqueInter(dd, index, Cudd_Not(t), t); if (r == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(dd, index, t, Cudd_Not(t)); if (r == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } } cuddDeref(t); if (r == NULL) return(NULL); cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); return(Cudd_NotCond(r,comple)); } else if ((lt == zero || Cudd_bddLeq(dd,lt,Cudd_Not(ue))) && (ut == one || Cudd_bddLeq(dd,Cudd_Not(le),ut))) { /* c-remap */ e = cuddBddSqueeze(dd, le, ue); cuddRef(e); if (Cudd_IsComplement(e)) { r = cuddUniqueInter(dd, index, Cudd_Not(e), e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); return(NULL); } } else { r = cuddUniqueInter(dd, index, e, Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(dd, e); return(NULL); } r = Cudd_Not(r); } cuddDeref(e); if (r == NULL) return(NULL); cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); return(Cudd_NotCond(r,comple)); } #if 0 /* If the two intervals intersect, take a solution from ** the intersection of the intervals. This guarantees that the ** splitting variable will not appear in the result. ** This approach corresponds to two-sided matching, and is very ** expensive. */ if (Cudd_bddLeq(dd,lt,ue) && Cudd_bddLeq(dd,le,ut)) { DdNode *au, *al; au = cuddBddAndRecur(dd,ut,ue); if (au == NULL) return(NULL); cuddRef(au); al = cuddBddAndRecur(dd,Cudd_Not(lt),Cudd_Not(le)); if (al == NULL) { Cudd_IterDerefBdd(dd,au); return(NULL); } cuddRef(al); al = Cudd_Not(al); ar = cuddBddSqueeze(dd, al, au); if (ar == NULL) { Cudd_IterDerefBdd(dd,au); Cudd_IterDerefBdd(dd,al); return(NULL); } cuddRef(ar); Cudd_IterDerefBdd(dd,au); Cudd_IterDerefBdd(dd,al); } else { ar = NULL; } #endif t = cuddBddSqueeze(dd, lt, ut); if (t == NULL) { return(NULL); } cuddRef(t); e = cuddBddSqueeze(dd, le, ue); if (e == NULL) { Cudd_IterDerefBdd(dd,t); return(NULL); } cuddRef(e); if (Cudd_IsComplement(t)) { t = Cudd_Not(t); e = Cudd_Not(e); r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); Cudd_IterDerefBdd(dd, t); return(NULL); } r = Cudd_Not(r); } else { r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (r == NULL) { Cudd_IterDerefBdd(dd, e); Cudd_IterDerefBdd(dd, t); return(NULL); } } cuddDeref(t); cuddDeref(e); #if 0 /* Check whether there is a result obtained by abstraction and whether ** it is better than the one obtained by recursion. */ cuddRef(r); if (ar != NULL) { if (Cudd_DagSize(ar) <= Cudd_DagSize(r)) { Cudd_IterDerefBdd(dd, r); r = ar; } else { Cudd_IterDerefBdd(dd, ar); } } cuddDeref(r); #endif cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); return(Cudd_NotCond(r,comple)); } /* end of cuddBddSqueeze */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddGenetic.c000066400000000000000000000737751300674244400241110ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddGenetic.c] PackageName [cudd] Synopsis [Genetic algorithm for variable reordering.] Description [Internal procedures included in this file:
      • cuddGa()
      Static procedures included in this module:
      • make_random()
      • sift_up()
      • build_dd()
      • largest()
      • rand_int()
      • array_hash()
      • array_compare()
      • find_best()
      • find_average_fitness()
      • PMX()
      • roulette()
      The genetic algorithm implemented here is as follows. We start with the current DD order. We sift this order and use this as the reference DD. We only keep 1 DD around for the entire process and simply rearrange the order of this DD, storing the various orders and their corresponding DD sizes. We generate more random orders to build an initial population. This initial population is 3 times the number of variables, with a maximum of 120. Each random order is built (from the reference DD) and its size stored. Each random order is also sifted to keep the DD sizes fairly small. Then a crossover is performed between two orders (picked randomly) and the two resulting DDs are built and sifted. For each new order, if its size is smaller than any DD in the population, it is inserted into the population and the DD with the largest number of nodes is thrown out. The crossover process happens up to 50 times, and at this point the DD in the population with the smallest size is chosen as the result. This DD must then be built from the reference DD.] SeeAlso [] Author [Curt Musfeldt, Alan Shuler, Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.28 2004/08/13 18:04:48 fabio Exp $"; #endif static int popsize; /* the size of the population */ static int numvars; /* the number of input variables in the ckt. */ /* storedd stores the population orders and sizes. This table has two ** extra rows and one extras column. The two extra rows are used for the ** offspring produced by a crossover. Each row stores one order and its ** size. The order is stored by storing the indices of variables in the ** order in which they appear in the order. The table is in reality a ** one-dimensional array which is accessed via a macro to give the illusion ** it is a two-dimensional structure. */ static int *storedd; static st__table *computed; /* hash table to identify existing orders */ static int *repeat; /* how many times an order is present */ static int large; /* stores the index of the population with ** the largest number of nodes in the DD */ static int result; static int cross; /* the number of crossovers to perform */ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /* macro used to access the population table as if it were a ** two-dimensional structure. */ #define STOREDD(i,j) storedd[(i)*(numvars+1)+(j)] /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int make_random (DdManager *table, int lower); static int sift_up (DdManager *table, int x, int x_low); static int build_dd (DdManager *table, int num, int lower, int upper); static int largest (void); static int rand_int (int a); static int array_hash (const char *array, int modulus); static int array_compare (const char *array1, const char *array2); static int find_best (void); #ifdef DD_STATS static double find_average_fitness (void); #endif static int PMX (int maxvar); static int roulette (int *p1, int *p2); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Genetic algorithm for DD reordering.] Description [Genetic algorithm for DD reordering. The two children of a crossover will be stored in storedd[popsize] and storedd[popsize+1] --- the last two slots in the storedd array. (This will make comparisons and replacement easy.) Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddGa( DdManager * table /* manager */, int lower /* lowest level to be reordered */, int upper /* highest level to be reorderded */) { int i,n,m; /* dummy/loop vars */ int index; #ifdef DD_STATS double average_fitness; #endif int small; /* index of smallest DD in population */ /* Do an initial sifting to produce at least one reasonable individual. */ if (!cuddSifting(table,lower,upper)) return(0); /* Get the initial values. */ numvars = upper - lower + 1; /* number of variables to be reordered */ if (table->populationSize == 0) { popsize = 3 * numvars; /* population size is 3 times # of vars */ if (popsize > 120) { popsize = 120; /* Maximum population size is 120 */ } } else { popsize = table->populationSize; /* user specified value */ } if (popsize < 4) popsize = 4; /* enforce minimum population size */ /* Allocate population table. */ storedd = ABC_ALLOC(int,(popsize+2)*(numvars+1)); if (storedd == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } /* Initialize the computed table. This table is made up of two data ** structures: A hash table with the key given by the order, which says ** if a given order is present in the population; and the repeat ** vector, which says how many copies of a given order are stored in ** the population table. If there are multiple copies of an order, only ** one has a repeat count greater than 1. This copy is the one pointed ** by the computed table. */ repeat = ABC_ALLOC(int,popsize); if (repeat == NULL) { table->errorCode = CUDD_MEMORY_OUT; ABC_FREE(storedd); return(0); } for (i = 0; i < popsize; i++) { repeat[i] = 0; } computed = st__init_table(array_compare,array_hash); if (computed == NULL) { table->errorCode = CUDD_MEMORY_OUT; ABC_FREE(storedd); ABC_FREE(repeat); return(0); } /* Copy the current DD and its size to the population table. */ for (i = 0; i < numvars; i++) { STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */ } STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */ /* Store the initial order in the computed table. */ if ( st__insert(computed,(char *)storedd,(char *) 0) == st__OUT_OF_MEM) { ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } repeat[0]++; /* Insert the reverse order as second element of the population. */ for (i = 0; i < numvars; i++) { STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */ } /* Now create the random orders. make_random fills the population ** table with random permutations. The successive loop builds and sifts ** the DDs for the reverse order and each random permutation, and stores ** the results in the computed table. */ if (!make_random(table,lower)) { table->errorCode = CUDD_MEMORY_OUT; ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } for (i = 1; i < popsize; i++) { result = build_dd(table,i,lower,upper); /* build and sift order */ if (!result) { ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } if ( st__lookup_int(computed,(char *)&STOREDD(i,0),&index)) { repeat[index]++; } else { if ( st__insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) == st__OUT_OF_MEM) { ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } repeat[i]++; } } #if 0 #ifdef DD_STATS /* Print the initial population. */ (void) fprintf(table->out,"Initial population after sifting\n"); for (m = 0; m < popsize; m++) { for (i = 0; i < numvars; i++) { (void) fprintf(table->out," %2d",STOREDD(m,i)); } (void) fprintf(table->out," : %3d (%d)\n", STOREDD(m,numvars),repeat[m]); } #endif #endif small = find_best(); #ifdef DD_STATS average_fitness = find_average_fitness(); (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); #endif /* Decide how many crossovers should be tried. */ if (table->numberXovers == 0) { cross = 3*numvars; if (cross > 60) { /* do a maximum of 50 crossovers */ cross = 60; } } else { cross = table->numberXovers; /* use user specified value */ } /* Perform the crossovers to get the best order. */ for (m = 0; m < cross; m++) { if (!PMX(table->size)) { /* perform one crossover */ table->errorCode = CUDD_MEMORY_OUT; ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } /* The offsprings are left in the last two entries of the ** population table. These are now considered in turn. */ for (i = popsize; i <= popsize+1; i++) { result = build_dd(table,i,lower,upper); /* build and sift child */ if (!result) { ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } large = largest(); /* find the largest DD in population */ /* If the new child is smaller than the largest DD in the current ** population, enter it into the population in place of the ** largest DD. */ if (STOREDD(i,numvars) < STOREDD(large,numvars)) { /* Look up the largest DD in the computed table. ** Decrease its repetition count. If the repetition count ** goes to 0, remove the largest DD from the computed table. */ result = st__lookup_int(computed,(char *)&STOREDD(large,0), &index); if (!result) { ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } repeat[index]--; if (repeat[index] == 0) { int *pointer = &STOREDD(index,0); result = st__delete(computed, (const char **)&pointer, NULL); if (!result) { ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } } /* Copy the new individual to the entry of the ** population table just made available and update the ** computed table. */ for (n = 0; n <= numvars; n++) { STOREDD(large,n) = STOREDD(i,n); } if ( st__lookup_int(computed,(char *)&STOREDD(large,0), &index)) { repeat[index]++; } else { if ( st__insert(computed,(char *)&STOREDD(large,0), (char *)(long)large) == st__OUT_OF_MEM) { ABC_FREE(storedd); ABC_FREE(repeat); st__free_table(computed); return(0); } repeat[large]++; } } } } /* Find the smallest DD in the population and build it; ** that will be the result. */ small = find_best(); /* Print stats on the final population. */ #ifdef DD_STATS average_fitness = find_average_fitness(); (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); #endif /* Clean up, build the result DD, and return. */ st__free_table(computed); computed = NULL; result = build_dd(table,small,lower,upper); ABC_FREE(storedd); ABC_FREE(repeat); return(result); } /* end of cuddGa */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Generates the random sequences for the initial population.] Description [Generates the random sequences for the initial population. The sequences are permutations of the indices between lower and upper in the current order.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int make_random( DdManager * table, int lower) { int i,j; /* loop variables */ int *used; /* is a number already in a permutation */ int next; /* next random number without repetitions */ used = ABC_ALLOC(int,numvars); if (used == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } #if 0 #ifdef DD_STATS (void) fprintf(table->out,"Initial population before sifting\n"); for (i = 0; i < 2; i++) { for (j = 0; j < numvars; j++) { (void) fprintf(table->out," %2d",STOREDD(i,j)); } (void) fprintf(table->out,"\n"); } #endif #endif for (i = 2; i < popsize; i++) { for (j = 0; j < numvars; j++) { used[j] = 0; } /* Generate a permutation of {0...numvars-1} and use it to ** permute the variables in the layesr from lower to upper. */ for (j = 0; j < numvars; j++) { do { next = rand_int(numvars-1); } while (used[next] != 0); used[next] = 1; STOREDD(i,j) = table->invperm[next+lower]; } #if 0 #ifdef DD_STATS /* Print the order just generated. */ for (j = 0; j < numvars; j++) { (void) fprintf(table->out," %2d",STOREDD(i,j)); } (void) fprintf(table->out,"\n"); #endif #endif } ABC_FREE(used); return(1); } /* end of make_random */ /**Function******************************************************************** Synopsis [Moves one variable up.] Description [Takes a variable from position x and sifts it up to position x_low; x_low should be less than x. Returns 1 if successful; 0 otherwise] SideEffects [None] SeeAlso [] ******************************************************************************/ static int sift_up( DdManager * table, int x, int x_low) { int y; int size; y = cuddNextLow(table,x); while (y >= x_low) { size = cuddSwapInPlace(table,y,x); if (size == 0) { return(0); } x = y; y = cuddNextLow(table,x); } return(1); } /* end of sift_up */ /**Function******************************************************************** Synopsis [Builds a DD from a given order.] Description [Builds a DD from a given order. This procedure also sifts the final order and inserts into the array the size in nodes of the result. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int build_dd( DdManager * table, int num /* the index of the individual to be built */, int lower, int upper) { int i,j; /* loop vars */ int position; int index; int limit; /* how large the DD for this order can grow */ int size; /* Check the computed table. If the order already exists, it ** suffices to copy the size from the existing entry. */ if (computed && st__lookup_int(computed,(char *)&STOREDD(num,0),&index)) { STOREDD(num,numvars) = STOREDD(index,numvars); #ifdef DD_STATS (void) fprintf(table->out,"\nCache hit for index %d", index); #endif return(1); } /* Stop if the DD grows 20 times larges than the reference size. */ limit = 20 * STOREDD(0,numvars); /* Sift up the variables so as to build the desired permutation. ** First the variable that has to be on top is sifted to the top. ** Then the variable that has to occupy the secon position is sifted ** up to the second position, and so on. */ for (j = 0; j < numvars; j++) { i = STOREDD(num,j); position = table->perm[i]; result = sift_up(table,position,j+lower); if (!result) return(0); size = table->keys - table->isolated; if (size > limit) break; } /* Sift the DD just built. */ #ifdef DD_STATS (void) fprintf(table->out,"\n"); #endif result = cuddSifting(table,lower,upper); if (!result) return(0); /* Copy order and size to table. */ for (j = 0; j < numvars; j++) { STOREDD(num,j) = table->invperm[lower+j]; } STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */ return(1); } /* end of build_dd */ /**Function******************************************************************** Synopsis [Finds the largest DD in the population.] Description [Finds the largest DD in the population. If an order is repeated, it avoids choosing the copy that is in the computed table (it has repeat[i] > 1).] SideEffects [None] SeeAlso [] ******************************************************************************/ static int largest(void) { int i; /* loop var */ int big; /* temporary holder to return result */ big = 0; while (repeat[big] > 1) big++; for (i = big + 1; i < popsize; i++) { if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) { big = i; } } return(big); } /* end of largest */ /**Function******************************************************************** Synopsis [Generates a random number between 0 and the integer a.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static int rand_int( int a) { return(Cudd_Random() % (a+1)); } /* end of rand_int */ /**Function******************************************************************** Synopsis [Hash function for the computed table.] Description [Hash function for the computed table. Returns the bucket number.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int array_hash( const char * array, int modulus) { int val = 0; int i; int *intarray; intarray = (int *) array; for (i = 0; i < numvars; i++) { val = val * 997 + intarray[i]; } return ((val < 0) ? -val : val) % modulus; } /* end of array_hash */ /**Function******************************************************************** Synopsis [Comparison function for the computed table.] Description [Comparison function for the computed table. Returns 0 if the two arrays are equal; 1 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int array_compare( const char * array1, const char * array2) { int i; int *intarray1, *intarray2; intarray1 = (int *) array1; intarray2 = (int *) array2; for (i = 0; i < numvars; i++) { if (intarray1[i] != intarray2[i]) return(1); } return(0); } /* end of array_compare */ /**Function******************************************************************** Synopsis [Returns the index of the fittest individual.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static int find_best(void) { int i,small; small = 0; for (i = 1; i < popsize; i++) { if (STOREDD(i,numvars) < STOREDD(small,numvars)) { small = i; } } return(small); } /* end of find_best */ /**Function******************************************************************** Synopsis [Returns the average fitness of the population.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ #ifdef DD_STATS static double find_average_fitness(void) { int i; int total_fitness = 0; double average_fitness; for (i = 0; i < popsize; i++) { total_fitness += STOREDD(i,numvars); } average_fitness = (double) total_fitness / (double) popsize; return(average_fitness); } /* end of find_average_fitness */ #endif /**Function******************************************************************** Synopsis [Performs the crossover between two parents.] Description [Performs the crossover between two randomly chosen parents, and creates two children, x1 and x2. Uses the Partially Matched Crossover operator.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int PMX( int maxvar) { int cut1,cut2; /* the two cut positions (random) */ int mom,dad; /* the two randomly chosen parents */ int *inv1; /* inverse permutations for repair algo */ int *inv2; int i; /* loop vars */ int u,v; /* aux vars */ inv1 = ABC_ALLOC(int,maxvar); if (inv1 == NULL) { return(0); } inv2 = ABC_ALLOC(int,maxvar); if (inv2 == NULL) { ABC_FREE(inv1); return(0); } /* Choose two orders from the population using roulette wheel. */ if (!roulette(&mom,&dad)) { ABC_FREE(inv1); ABC_FREE(inv2); return(0); } /* Choose two random cut positions. A cut in position i means that ** the cut immediately precedes position i. If cut1 < cut2, we ** exchange the middle of the two orderings; otherwise, we ** exchange the beginnings and the ends. */ cut1 = rand_int(numvars-1); do { cut2 = rand_int(numvars-1); } while (cut1 == cut2); #if 0 /* Print out the parents. */ (void) fprintf(table->out, "Crossover of %d (mom) and %d (dad) between %d and %d\n", mom,dad,cut1,cut2); for (i = 0; i < numvars; i++) { if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); (void) fprintf(table->out,"%2d ",STOREDD(mom,i)); } (void) fprintf(table->out,"\n"); for (i = 0; i < numvars; i++) { if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); (void) fprintf(table->out,"%2d ",STOREDD(dad,i)); } (void) fprintf(table->out,"\n"); #endif /* Initialize the inverse permutations: -1 means yet undetermined. */ for (i = 0; i < maxvar; i++) { inv1[i] = -1; inv2[i] = -1; } /* Copy the portions whithin the cuts. */ for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) { STOREDD(popsize,i) = STOREDD(dad,i); inv1[STOREDD(popsize,i)] = i; STOREDD(popsize+1,i) = STOREDD(mom,i); inv2[STOREDD(popsize+1,i)] = i; } /* Now apply the repair algorithm outside the cuts. */ for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) { v = i; do { u = STOREDD(mom,v); v = inv1[u]; } while (v != -1); STOREDD(popsize,i) = u; inv1[u] = i; v = i; do { u = STOREDD(dad,v); v = inv2[u]; } while (v != -1); STOREDD(popsize+1,i) = u; inv2[u] = i; } #if 0 /* Print the results of crossover. */ for (i = 0; i < numvars; i++) { if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); (void) fprintf(table->out,"%2d ",STOREDD(popsize,i)); } (void) fprintf(table->out,"\n"); for (i = 0; i < numvars; i++) { if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); (void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i)); } (void) fprintf(table->out,"\n"); #endif ABC_FREE(inv1); ABC_FREE(inv2); return(1); } /* end of PMX */ /**Function******************************************************************** Synopsis [Selects two parents with the roulette wheel method.] Description [Selects two distinct parents with the roulette wheel method.] SideEffects [The indices of the selected parents are returned as side effects.] SeeAlso [] ******************************************************************************/ static int roulette( int * p1, int * p2) { double *wheel; double spin; int i; wheel = ABC_ALLOC(double,popsize); if (wheel == NULL) { return(0); } /* The fitness of an individual is the reciprocal of its size. */ wheel[0] = 1.0 / (double) STOREDD(0,numvars); for (i = 1; i < popsize; i++) { wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars); } /* Get a random number between 0 and wheel[popsize-1] (that is, ** the sum of all fitness values. 2147483561 is the largest number ** returned by Cudd_Random. */ spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0; /* Find the lucky element by scanning the wheel. */ for (i = 0; i < popsize; i++) { if (spin <= wheel[i]) break; } *p1 = i; /* Repeat the process for the second parent, making sure it is ** distinct from the first. */ do { spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0; for (i = 0; i < popsize; i++) { if (spin <= wheel[i]) break; } } while (i == *p1); *p2 = i; ABC_FREE(wheel); return(1); } /* end of roulette */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddGroup.c000066400000000000000000002117161300674244400236140ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddGroup.c] PackageName [cudd] Synopsis [Functions for group sifting.] Description [External procedures included in this file:
      • Cudd_MakeTreeNode()
      Internal procedures included in this file:
      • cuddTreeSifting()
      Static procedures included in this module:
      • ddTreeSiftingAux()
      • ddCountInternalMtrNodes()
      • ddReorderChildren()
      • ddFindNodeHiLo()
      • ddUniqueCompareGroup()
      • ddGroupSifting()
      • ddCreateGroup()
      • ddGroupSiftingAux()
      • ddGroupSiftingUp()
      • ddGroupSiftingDown()
      • ddGroupMove()
      • ddGroupMoveBackward()
      • ddGroupSiftingBackward()
      • ddMergeGroups()
      • ddDissolveGroup()
      • ddNoCheck()
      • ddSecDiffCheck()
      • ddExtSymmCheck()
      • ddVarGroupCheck()
      • ddSetVarHandled()
      • ddResetVarHandled()
      • ddIsVarHandled()
      ] Author [Shipra Panda, Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /* Constants for lazy sifting */ #define DD_NORMAL_SIFT 0 #define DD_LAZY_SIFT 1 /* Constants for sifting up and down */ #define DD_SIFT_DOWN 0 #define DD_SIFT_UP 1 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ typedef int (*DD_CHKFP)(DdManager *, int, int); /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.44 2009/02/21 18:24:10 fabio Exp $"; #endif static int *entry; extern int ddTotalNumberSwapping; #ifdef DD_STATS extern int ddTotalNISwaps; static int extsymmcalls; static int extsymm; static int secdiffcalls; static int secdiff; static int secdiffmisfire; #endif #ifdef DD_DEBUG static int pr = 0; /* flag to enable printing while debugging */ /* by depositing a 1 into it */ #endif static unsigned int originalSize; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int ddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method); #ifdef DD_STATS static int ddCountInternalMtrNodes (DdManager *table, MtrNode *treenode); #endif static int ddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method); static void ddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper); static int ddUniqueCompareGroup (int *ptrX, int *ptrY); static int ddGroupSifting (DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag); static void ddCreateGroup (DdManager *table, int x, int y); static int ddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag); static int ddGroupSiftingUp (DdManager *table, int y, int xLow, DD_CHKFP checkFunction, Move **moves); static int ddGroupSiftingDown (DdManager *table, int x, int xHigh, DD_CHKFP checkFunction, Move **moves); static int ddGroupMove (DdManager *table, int x, int y, Move **moves); static int ddGroupMoveBackward (DdManager *table, int x, int y); static int ddGroupSiftingBackward (DdManager *table, Move *moves, int size, int upFlag, int lazyFlag); static void ddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high); static void ddDissolveGroup (DdManager *table, int x, int y); static int ddNoCheck (DdManager *table, int x, int y); static int ddSecDiffCheck (DdManager *table, int x, int y); static int ddExtSymmCheck (DdManager *table, int x, int y); static int ddVarGroupCheck (DdManager * table, int x, int y); static int ddSetVarHandled (DdManager *dd, int index); static int ddResetVarHandled (DdManager *dd, int index); static int ddIsVarHandled (DdManager *dd, int index); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Creates a new variable group.] Description [Creates a new variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.] SideEffects [The variable tree is changed.] SeeAlso [Cudd_MakeZddTreeNode] ******************************************************************************/ MtrNode * Cudd_MakeTreeNode( DdManager * dd /* manager */, unsigned int low /* index of the first group variable */, unsigned int size /* number of variables in the group */, unsigned int type /* MTR_DEFAULT or MTR_FIXED */) { MtrNode *group; MtrNode *tree; unsigned int level; /* If the variable does not exist yet, the position is assumed to be ** the same as the index. Therefore, applications that rely on ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new ** variables have to create the variables before they group them. */ level = (low < (unsigned int) dd->size) ? dd->perm[low] : low; if (level + size - 1> (int) MTR_MAXHIGH) return(NULL); /* If the tree does not exist yet, create it. */ tree = dd->tree; if (tree == NULL) { dd->tree = tree = Mtr_InitGroupTree(0, dd->size); if (tree == NULL) return(NULL); tree->index = dd->invperm[0]; } /* Extend the upper bound of the tree if necessary. This allows the ** application to create groups even before the variables are created. */ tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size)); /* Create the group. */ group = Mtr_MakeGroup(tree, level, size, type); if (group == NULL) return(NULL); /* Initialize the index field to the index of the variable currently ** in position low. This field will be updated by the reordering ** procedure to provide a handle to the group once it has been moved. */ group->index = (MtrHalfWord) low; return(group); } /* end of Cudd_MakeTreeNode */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Tree sifting algorithm.] Description [Tree sifting algorithm. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling ddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ int cuddTreeSifting( DdManager * table /* DD table */, Cudd_ReorderingType method /* reordering method for the groups of leaves */) { int i; int nvars; int result; int tempTree; /* If no tree is provided we create a temporary one in which all ** variables are in a single group. After reordering this tree is ** destroyed. */ tempTree = table->tree == NULL; if (tempTree) { table->tree = Mtr_InitGroupTree(0,table->size); table->tree->index = table->invperm[0]; } nvars = table->size; #ifdef DD_DEBUG if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:"); Mtr_PrintGroups(table->tree,pr <= 0); #endif #ifdef DD_STATS extsymmcalls = 0; extsymm = 0; secdiffcalls = 0; secdiff = 0; secdiffmisfire = 0; (void) fprintf(table->out,"\n"); if (!tempTree) (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", ddCountInternalMtrNodes(table,table->tree)); #endif /* Initialize the group of each subtable to itself. Initially ** there are no groups. Groups are created according to the tree ** structure in postorder fashion. */ for (i = 0; i < nvars; i++) table->subtables[i].next = i; /* Reorder. */ result = ddTreeSiftingAux(table, table->tree, method); #ifdef DD_STATS /* print stats */ if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && (table->groupcheck == CUDD_GROUP_CHECK7 || table->groupcheck == CUDD_GROUP_CHECK5)) { (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); (void) fprintf(table->out,"extsymm = %d",extsymm); } if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && table->groupcheck == CUDD_GROUP_CHECK7) { (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); (void) fprintf(table->out,"secdiff = %d\n",secdiff); (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); } #endif if (tempTree) Cudd_FreeTree(table); return(result); } /* end of cuddTreeSifting */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Visits the group tree and reorders each group.] Description [Recursively visits the group tree and reorders each group in postorder fashion. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddTreeSiftingAux( DdManager * table, MtrNode * treenode, Cudd_ReorderingType method) { MtrNode *auxnode; int res; Cudd_AggregationType saveCheck; #ifdef DD_DEBUG Mtr_PrintGroups(treenode,1); #endif auxnode = treenode; while (auxnode != NULL) { if (auxnode->child != NULL) { if (!ddTreeSiftingAux(table, auxnode->child, method)) return(0); saveCheck = table->groupcheck; table->groupcheck = CUDD_NO_CHECK; if (method != CUDD_REORDER_LAZY_SIFT) res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); else res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT); table->groupcheck = saveCheck; if (res == 0) return(0); } else if (auxnode->size > 1) { if (!ddReorderChildren(table, auxnode, method)) return(0); } auxnode = auxnode->younger; } return(1); } /* end of ddTreeSiftingAux */ #ifdef DD_STATS /**Function******************************************************************** Synopsis [Counts the number of internal nodes of the group tree.] Description [Counts the number of internal nodes of the group tree. Returns the count.] SideEffects [None] ******************************************************************************/ static int ddCountInternalMtrNodes( DdManager * table, MtrNode * treenode) { MtrNode *auxnode; int count,nodeCount; nodeCount = 0; auxnode = treenode; while (auxnode != NULL) { if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { nodeCount++; count = ddCountInternalMtrNodes(table,auxnode->child); nodeCount += count; } auxnode = auxnode->younger; } return(nodeCount); } /* end of ddCountInternalMtrNodes */ #endif /**Function******************************************************************** Synopsis [Reorders the children of a group tree node according to the options.] Description [Reorders the children of a group tree node according to the options. After reordering puts all the variables in the group and/or its descendents in a single group. This allows hierarchical reordering. If the variables in the group do not exist yet, simply does nothing. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddReorderChildren( DdManager * table, MtrNode * treenode, Cudd_ReorderingType method) { int lower; int upper = -1; int result; unsigned int initialSize; ddFindNodeHiLo(table,treenode,&lower,&upper); /* If upper == -1 these variables do not exist yet. */ if (upper == -1) return(1); if (treenode->flags == MTR_FIXED) { result = 1; } else { #ifdef DD_STATS (void) fprintf(table->out," "); #endif switch (method) { case CUDD_REORDER_RANDOM: case CUDD_REORDER_RANDOM_PIVOT: result = cuddSwapping(table,lower,upper,method); break; case CUDD_REORDER_SIFT: result = cuddSifting(table,lower,upper); break; case CUDD_REORDER_SIFT_CONVERGE: do { initialSize = table->keys - table->isolated; result = cuddSifting(table,lower,upper); if (initialSize <= table->keys - table->isolated) break; #ifdef DD_STATS else (void) fprintf(table->out,"\n"); #endif } while (result != 0); break; case CUDD_REORDER_SYMM_SIFT: result = cuddSymmSifting(table,lower,upper); break; case CUDD_REORDER_SYMM_SIFT_CONV: result = cuddSymmSiftingConv(table,lower,upper); break; case CUDD_REORDER_GROUP_SIFT: if (table->groupcheck == CUDD_NO_CHECK) { result = ddGroupSifting(table,lower,upper,ddNoCheck, DD_NORMAL_SIFT); } else if (table->groupcheck == CUDD_GROUP_CHECK5) { result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, DD_NORMAL_SIFT); } else if (table->groupcheck == CUDD_GROUP_CHECK7) { result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, DD_NORMAL_SIFT); } else { (void) fprintf(table->err, "Unknown group ckecking method\n"); result = 0; } break; case CUDD_REORDER_GROUP_SIFT_CONV: do { initialSize = table->keys - table->isolated; if (table->groupcheck == CUDD_NO_CHECK) { result = ddGroupSifting(table,lower,upper,ddNoCheck, DD_NORMAL_SIFT); } else if (table->groupcheck == CUDD_GROUP_CHECK5) { result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, DD_NORMAL_SIFT); } else if (table->groupcheck == CUDD_GROUP_CHECK7) { result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, DD_NORMAL_SIFT); } else { (void) fprintf(table->err, "Unknown group ckecking method\n"); result = 0; } #ifdef DD_STATS (void) fprintf(table->out,"\n"); #endif result = cuddWindowReorder(table,lower,upper, CUDD_REORDER_WINDOW4); if (initialSize <= table->keys - table->isolated) break; #ifdef DD_STATS else (void) fprintf(table->out,"\n"); #endif } while (result != 0); break; case CUDD_REORDER_WINDOW2: case CUDD_REORDER_WINDOW3: case CUDD_REORDER_WINDOW4: case CUDD_REORDER_WINDOW2_CONV: case CUDD_REORDER_WINDOW3_CONV: case CUDD_REORDER_WINDOW4_CONV: result = cuddWindowReorder(table,lower,upper,method); break; case CUDD_REORDER_ANNEALING: result = cuddAnnealing(table,lower,upper); break; case CUDD_REORDER_GENETIC: result = cuddGa(table,lower,upper); break; case CUDD_REORDER_LINEAR: result = cuddLinearAndSifting(table,lower,upper); break; case CUDD_REORDER_LINEAR_CONVERGE: do { initialSize = table->keys - table->isolated; result = cuddLinearAndSifting(table,lower,upper); if (initialSize <= table->keys - table->isolated) break; #ifdef DD_STATS else (void) fprintf(table->out,"\n"); #endif } while (result != 0); break; case CUDD_REORDER_EXACT: result = cuddExact(table,lower,upper); break; case CUDD_REORDER_LAZY_SIFT: result = ddGroupSifting(table,lower,upper,ddVarGroupCheck, DD_LAZY_SIFT); break; default: return(0); } } /* Create a single group for all the variables that were sifted, ** so that they will be treated as a single block by successive ** invocations of ddGroupSifting. */ ddMergeGroups(table,treenode,lower,upper); #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:"); #endif return(result); } /* end of ddReorderChildren */ /**Function******************************************************************** Synopsis [Finds the lower and upper bounds of the group represented by treenode.] Description [Finds the lower and upper bounds of the group represented by treenode. From the index and size fields we need to derive the current positions, and find maximum and minimum.] SideEffects [The bounds are returned as side effects.] SeeAlso [] ******************************************************************************/ static void ddFindNodeHiLo( DdManager * table, MtrNode * treenode, int * lower, int * upper) { int low; int high; /* Check whether no variables in this group already exist. ** If so, return immediately. The calling procedure will know from ** the values of upper that no reordering is needed. */ if ((int) treenode->low >= table->size) { *lower = table->size; *upper = -1; return; } *lower = low = (unsigned int) table->perm[treenode->index]; high = (int) (low + treenode->size - 1); if (high >= table->size) { /* This is the case of a partially existing group. The aim is to ** reorder as many variables as safely possible. If the tree ** node is terminal, we just reorder the subset of the group ** that is currently in existence. If the group has ** subgroups, then we only reorder those subgroups that are ** fully instantiated. This way we avoid breaking up a group. */ MtrNode *auxnode = treenode->child; if (auxnode == NULL) { *upper = (unsigned int) table->size - 1; } else { /* Search the subgroup that strands the table->size line. ** If the first group starts at 0 and goes past table->size ** upper will get -1, thus correctly signaling that no reordering ** should take place. */ while (auxnode != NULL) { int thisLower = table->perm[auxnode->low]; int thisUpper = thisLower + auxnode->size - 1; if (thisUpper >= table->size && thisLower < table->size) *upper = (unsigned int) thisLower - 1; auxnode = auxnode->younger; } } } else { /* Normal case: All the variables of the group exist. */ *upper = (unsigned int) high; } #ifdef DD_DEBUG /* Make sure that all variables in group are contiguous. */ assert(treenode->size >= *upper - *lower + 1); #endif return; } /* end of ddFindNodeHiLo */ /**Function******************************************************************** Synopsis [Comparison function used by qsort.] Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.] SideEffects [None] ******************************************************************************/ static int ddUniqueCompareGroup( int * ptrX, int * ptrY) { #if 0 if (entry[*ptrY] == entry[*ptrX]) { return((*ptrX) - (*ptrY)); } #endif return(entry[*ptrY] - entry[*ptrX]); } /* end of ddUniqueCompareGroup */ /**Function******************************************************************** Synopsis [Sifts from treenode->low to treenode->high.] Description [Sifts from treenode->low to treenode->high. If croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the end of the initial sifting. If a group is created, it is then sifted again. After sifting one variable, the group that contains it is dissolved. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddGroupSifting( DdManager * table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag) { int *var; int i,j,x,xInit; int nvars; int classes; int result; int *sifted; int merged; int dissolve; #ifdef DD_STATS unsigned previousSize; #endif int xindex; nvars = table->size; /* Order variables to sift. */ entry = NULL; sifted = NULL; var = ABC_ALLOC(int,nvars); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto ddGroupSiftingOutOfMem; } entry = ABC_ALLOC(int,nvars); if (entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto ddGroupSiftingOutOfMem; } sifted = ABC_ALLOC(int,nvars); if (sifted == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto ddGroupSiftingOutOfMem; } /* Here we consider only one representative for each group. */ for (i = 0, classes = 0; i < nvars; i++) { sifted[i] = 0; x = table->perm[i]; if ((unsigned) x >= table->subtables[x].next) { entry[i] = table->subtables[x].keys; var[classes] = i; classes++; } } qsort((void *)var,classes,sizeof(int), (DD_QSFP) ddUniqueCompareGroup); if (lazyFlag) { for (i = 0; i < nvars; i ++) { ddResetVarHandled(table, i); } } /* Now sift. */ for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { if (ddTotalNumberSwapping >= table->siftMaxSwap) break; xindex = var[i]; if (sifted[xindex] == 1) /* variable already sifted as part of group */ continue; x = table->perm[xindex]; /* find current level of this variable */ if (x < lower || x > upper || table->subtables[x].bindVar == 1) continue; #ifdef DD_STATS previousSize = table->keys - table->isolated; #endif #ifdef DD_DEBUG /* x is bottom of group */ assert((unsigned) x >= table->subtables[x].next); #endif if ((unsigned) x == table->subtables[x].next) { dissolve = 1; result = ddGroupSiftingAux(table,x,lower,upper,checkFunction, lazyFlag); } else { dissolve = 0; result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); } if (!result) goto ddGroupSiftingOutOfMem; /* check for aggregation */ merged = 0; if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) { x = table->perm[xindex]; /* find current level */ if ((unsigned) x == table->subtables[x].next) { /* not part of a group */ if (x != upper && sifted[table->invperm[x+1]] == 0 && (unsigned) x+1 == table->subtables[x+1].next) { if (ddSecDiffCheck(table,x,x+1)) { merged =1; ddCreateGroup(table,x,x+1); } } if (x != lower && sifted[table->invperm[x-1]] == 0 && (unsigned) x-1 == table->subtables[x-1].next) { if (ddSecDiffCheck(table,x-1,x)) { merged =1; ddCreateGroup(table,x-1,x); } } } } if (merged) { /* a group was created */ /* move x to bottom of group */ while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; /* sift */ result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); if (!result) goto ddGroupSiftingOutOfMem; #ifdef DD_STATS if (table->keys < previousSize + table->isolated) { (void) fprintf(table->out,"_"); } else if (table->keys > previousSize + table->isolated) { (void) fprintf(table->out,"^"); } else { (void) fprintf(table->out,"*"); } fflush(table->out); } else { if (table->keys < previousSize + table->isolated) { (void) fprintf(table->out,"-"); } else if (table->keys > previousSize + table->isolated) { (void) fprintf(table->out,"+"); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } /* Mark variables in the group just sifted. */ x = table->perm[xindex]; if ((unsigned) x != table->subtables[x].next) { xInit = x; do { j = table->invperm[x]; sifted[j] = 1; x = table->subtables[x].next; } while (x != xInit); /* Dissolve the group if it was created. */ if (lazyFlag == 0 && dissolve) { do { j = table->subtables[x].next; table->subtables[x].next = x; x = j; } while (x != xInit); } } #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:"); #endif if (lazyFlag) ddSetVarHandled(table, xindex); } /* for */ ABC_FREE(sifted); ABC_FREE(var); ABC_FREE(entry); return(1); ddGroupSiftingOutOfMem: if (entry != NULL) ABC_FREE(entry); if (var != NULL) ABC_FREE(var); if (sifted != NULL) ABC_FREE(sifted); return(0); } /* end of ddGroupSifting */ /**Function******************************************************************** Synopsis [Creates a group encompassing variables from x to y in the DD table.] Description [Creates a group encompassing variables from x to y in the DD table. In the current implementation it must be y == x+1. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static void ddCreateGroup( DdManager * table, int x, int y) { int gybot; #ifdef DD_DEBUG assert(y == x+1); #endif /* Find bottom of second group. */ gybot = y; while ((unsigned) gybot < table->subtables[gybot].next) gybot = table->subtables[gybot].next; /* Link groups. */ table->subtables[x].next = y; table->subtables[gybot].next = x; return; } /* ddCreateGroup */ /**Function******************************************************************** Synopsis [Sifts one variable up and down until it has taken all positions. Checks for aggregation.] Description [Sifts one variable up and down until it has taken all positions. Checks for aggregation. There may be at most two sweeps, even if the group grows. Assumes that x is either an isolated variable, or it is the bottom of a group. All groups may not have been found. The variable being moved is returned to the best position seen during sifting. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddGroupSiftingAux( DdManager * table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag) { Move *move; Move *moves; /* list of moves */ int initialSize; int result; int y; int topbot; #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out, "ddGroupSiftingAux from %d to %d\n",xLow,xHigh); assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */ #endif initialSize = table->keys - table->isolated; moves = NULL; originalSize = initialSize; /* for lazy sifting */ /* If we have a singleton, we check for aggregation in both ** directions before we sift. */ if ((unsigned) x == table->subtables[x].next) { /* Will go down first, unless x == xHigh: ** Look for aggregation above x. */ for (y = x; y > xLow; y--) { if (!checkFunction(table,y-1,y)) break; topbot = table->subtables[y-1].next; /* find top of y-1's group */ table->subtables[y-1].next = y; table->subtables[x].next = topbot; /* x is bottom of group so its */ /* next is top of y-1's group */ y = topbot + 1; /* add 1 for y--; new y is top of group */ } /* Will go up first unless x == xlow: ** Look for aggregation below x. */ for (y = x; y < xHigh; y++) { if (!checkFunction(table,y,y+1)) break; /* find bottom of y+1's group */ topbot = y + 1; while ((unsigned) topbot < table->subtables[topbot].next) { topbot = table->subtables[topbot].next; } table->subtables[topbot].next = table->subtables[y].next; table->subtables[y].next = y + 1; y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */ } } /* Now x may be in the middle of a group. ** Find bottom of x's group. */ while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; if (x == xLow) { /* Sift down */ #ifdef DD_DEBUG /* x must be a singleton */ assert((unsigned) x == table->subtables[x].next); #endif if (x == xHigh) return(1); /* just one variable */ if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) goto ddGroupSiftingAuxOutOfMem; /* at this point x == xHigh, unless early term */ /* move backward and stop at best position */ result = ddGroupSiftingBackward(table,moves,initialSize, DD_SIFT_DOWN,lazyFlag); #ifdef DD_DEBUG assert(table->keys - table->isolated <= (unsigned) initialSize); #endif if (!result) goto ddGroupSiftingAuxOutOfMem; } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ #ifdef DD_DEBUG /* x is bottom of group */ assert((unsigned) x >= table->subtables[x].next); #endif /* Find top of x's group */ x = table->subtables[x].next; if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) goto ddGroupSiftingAuxOutOfMem; /* at this point x == xLow, unless early term */ /* move backward and stop at best position */ result = ddGroupSiftingBackward(table,moves,initialSize, DD_SIFT_UP,lazyFlag); #ifdef DD_DEBUG assert(table->keys - table->isolated <= (unsigned) initialSize); #endif if (!result) goto ddGroupSiftingAuxOutOfMem; } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) goto ddGroupSiftingAuxOutOfMem; /* at this point x == xHigh, unless early term */ /* Find top of group */ if (moves) { x = moves->y; } while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; x = table->subtables[x].next; #ifdef DD_DEBUG /* x should be the top of a group */ assert((unsigned) x <= table->subtables[x].next); #endif if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) goto ddGroupSiftingAuxOutOfMem; /* move backward and stop at best position */ result = ddGroupSiftingBackward(table,moves,initialSize, DD_SIFT_UP,lazyFlag); #ifdef DD_DEBUG assert(table->keys - table->isolated <= (unsigned) initialSize); #endif if (!result) goto ddGroupSiftingAuxOutOfMem; } else { /* moving up first: shorter */ /* Find top of x's group */ x = table->subtables[x].next; if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) goto ddGroupSiftingAuxOutOfMem; /* at this point x == xHigh, unless early term */ if (moves) { x = moves->x; } while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; #ifdef DD_DEBUG /* x is bottom of a group */ assert((unsigned) x >= table->subtables[x].next); #endif if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) goto ddGroupSiftingAuxOutOfMem; /* move backward and stop at best position */ result = ddGroupSiftingBackward(table,moves,initialSize, DD_SIFT_DOWN,lazyFlag); #ifdef DD_DEBUG assert(table->keys - table->isolated <= (unsigned) initialSize); #endif if (!result) goto ddGroupSiftingAuxOutOfMem; } while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(1); ddGroupSiftingAuxOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(0); } /* end of ddGroupSiftingAux */ /**Function******************************************************************** Synopsis [Sifts up a variable until either it reaches position xLow or the size of the DD heap increases too much.] Description [Sifts up a variable until either it reaches position xLow or the size of the DD heap increases too much. Assumes that y is the top of a group (or a singleton). Checks y for aggregation to the adjacent variables. Records all the moves that are appended to the list of moves received as input and returned as a side effect. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddGroupSiftingUp( DdManager * table, int y, int xLow, DD_CHKFP checkFunction, Move ** moves) { Move *move; int x; int size; int i; int gxtop,gybot; int limitSize; int xindex, yindex; int zindex; int z; int isolated; int L; /* lower bound on DD size */ #ifdef DD_DEBUG int checkL; #endif yindex = table->invperm[y]; /* Initialize the lower bound. ** The part of the DD below the bottom of y's group will not change. ** The part of the DD above y that does not interact with any ** variable of y's group will not change. ** The rest may vanish in the best case, except for ** the nodes at level xLow, which will not vanish, regardless. ** What we use here is not really a lower bound, because we ignore ** the interactions with all variables except y. */ limitSize = L = table->keys - table->isolated; gybot = y; while ((unsigned) gybot < table->subtables[gybot].next) gybot = table->subtables[gybot].next; for (z = xLow + 1; z <= gybot; z++) { zindex = table->invperm[z]; if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { isolated = table->vars[zindex]->ref == 1; L -= table->subtables[z].keys - isolated; } } x = cuddNextLow(table,y); while (x >= xLow && L <= limitSize) { #ifdef DD_DEBUG gybot = y; while ((unsigned) gybot < table->subtables[gybot].next) gybot = table->subtables[gybot].next; checkL = table->keys - table->isolated; for (z = xLow + 1; z <= gybot; z++) { zindex = table->invperm[z]; if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { isolated = table->vars[zindex]->ref == 1; checkL -= table->subtables[z].keys - isolated; } } if (pr > 0 && L != checkL) { (void) fprintf(table->out, "Inaccurate lower bound: L = %d checkL = %d\n", L, checkL); } #endif gxtop = table->subtables[x].next; if (checkFunction(table,x,y)) { /* Group found, attach groups */ table->subtables[x].next = y; i = table->subtables[y].next; while (table->subtables[i].next != (unsigned) y) i = table->subtables[i].next; table->subtables[i].next = gxtop; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddGroupSiftingUpOutOfMem; move->x = x; move->y = y; move->flags = MTR_NEWNODE; move->size = table->keys - table->isolated; move->next = *moves; *moves = move; } else if (table->subtables[x].next == (unsigned) x && table->subtables[y].next == (unsigned) y) { /* x and y are self groups */ xindex = table->invperm[x]; size = cuddSwapInPlace(table,x,y); #ifdef DD_DEBUG assert(table->subtables[x].next == (unsigned) x); assert(table->subtables[y].next == (unsigned) y); #endif if (size == 0) goto ddGroupSiftingUpOutOfMem; /* Update the lower bound. */ if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[xindex]->ref == 1; L += table->subtables[y].keys - isolated; } move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddGroupSiftingUpOutOfMem; move->x = x; move->y = y; move->flags = MTR_DEFAULT; move->size = size; move->next = *moves; *moves = move; #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out, "ddGroupSiftingUp (2 single groups):\n"); #endif if ((double) size > (double) limitSize * table->maxGrowth) return(1); if (size < limitSize) limitSize = size; } else { /* Group move */ size = ddGroupMove(table,x,y,moves); if (size == 0) goto ddGroupSiftingUpOutOfMem; /* Update the lower bound. */ z = (*moves)->y; do { zindex = table->invperm[z]; if (cuddTestInteract(table,zindex,yindex)) { isolated = table->vars[zindex]->ref == 1; L += table->subtables[z].keys - isolated; } z = table->subtables[z].next; } while (z != (int) (*moves)->y); if ((double) size > (double) limitSize * table->maxGrowth) return(1); if (size < limitSize) limitSize = size; } y = gxtop; x = cuddNextLow(table,y); } return(1); ddGroupSiftingUpOutOfMem: while (*moves != NULL) { move = (*moves)->next; cuddDeallocMove(table, *moves); *moves = move; } return(0); } /* end of ddGroupSiftingUp */ /**Function******************************************************************** Synopsis [Sifts down a variable until it reaches position xHigh.] Description [Sifts down a variable until it reaches position xHigh. Assumes that x is the bottom of a group (or a singleton). Records all the moves. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddGroupSiftingDown( DdManager * table, int x, int xHigh, DD_CHKFP checkFunction, Move ** moves) { Move *move; int y; int size; int limitSize; int gxtop,gybot; int R; /* upper bound on node decrease */ int xindex, yindex; int isolated, allVars; int z; int zindex; #ifdef DD_DEBUG int checkR; #endif /* If the group consists of simple variables, there is no point in ** sifting it down. This check is redundant if the projection functions ** do not have external references, because the computation of the ** lower bound takes care of the problem. It is necessary otherwise to ** prevent the sifting down of simple variables. */ y = x; allVars = 1; do { if (table->subtables[y].keys != 1) { allVars = 0; break; } y = table->subtables[y].next; } while (table->subtables[y].next != (unsigned) x); if (allVars) return(1); /* Initialize R. */ xindex = table->invperm[x]; gxtop = table->subtables[x].next; limitSize = size = table->keys - table->isolated; R = 0; for (z = xHigh; z > gxtop; z--) { zindex = table->invperm[z]; if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; R += table->subtables[z].keys - isolated; } } y = cuddNextHigh(table,x); while (y <= xHigh && size - R < limitSize) { #ifdef DD_DEBUG gxtop = table->subtables[x].next; checkR = 0; for (z = xHigh; z > gxtop; z--) { zindex = table->invperm[z]; if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; checkR += table->subtables[z].keys - isolated; } } assert(R >= checkR); #endif /* Find bottom of y group. */ gybot = table->subtables[y].next; while (table->subtables[gybot].next != (unsigned) y) gybot = table->subtables[gybot].next; if (checkFunction(table,x,y)) { /* Group found: attach groups and record move. */ gxtop = table->subtables[x].next; table->subtables[x].next = y; table->subtables[gybot].next = gxtop; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto ddGroupSiftingDownOutOfMem; move->x = x; move->y = y; move->flags = MTR_NEWNODE; move->size = table->keys - table->isolated; move->next = *moves; *moves = move; } else if (table->subtables[x].next == (unsigned) x && table->subtables[y].next == (unsigned) y) { /* x and y are self groups */ /* Update upper bound on node decrease. */ yindex = table->invperm[y]; if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[yindex]->ref == 1; R -= table->subtables[y].keys - isolated; } size = cuddSwapInPlace(table,x,y); #ifdef DD_DEBUG assert(table->subtables[x].next == (unsigned) x); assert(table->subtables[y].next == (unsigned) y); #endif if (size == 0) goto ddGroupSiftingDownOutOfMem; /* Record move. */ move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddGroupSiftingDownOutOfMem; move->x = x; move->y = y; move->flags = MTR_DEFAULT; move->size = size; move->next = *moves; *moves = move; #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out, "ddGroupSiftingDown (2 single groups):\n"); #endif if ((double) size > (double) limitSize * table->maxGrowth) return(1); if (size < limitSize) limitSize = size; x = y; y = cuddNextHigh(table,x); } else { /* Group move */ /* Update upper bound on node decrease: first phase. */ gxtop = table->subtables[x].next; z = gxtop + 1; do { zindex = table->invperm[z]; if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; R -= table->subtables[z].keys - isolated; } z++; } while (z <= gybot); size = ddGroupMove(table,x,y,moves); if (size == 0) goto ddGroupSiftingDownOutOfMem; if ((double) size > (double) limitSize * table->maxGrowth) return(1); if (size < limitSize) limitSize = size; /* Update upper bound on node decrease: second phase. */ gxtop = table->subtables[gybot].next; for (z = gxtop + 1; z <= gybot; z++) { zindex = table->invperm[z]; if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; R += table->subtables[z].keys - isolated; } } } x = gybot; y = cuddNextHigh(table,x); } return(1); ddGroupSiftingDownOutOfMem: while (*moves != NULL) { move = (*moves)->next; cuddDeallocMove(table, *moves); *moves = move; } return(0); } /* end of ddGroupSiftingDown */ /**Function******************************************************************** Synopsis [Swaps two groups and records the move.] Description [Swaps two groups and records the move. Returns the number of keys in the DD table in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddGroupMove( DdManager * table, int x, int y, Move ** moves) { Move *move; int size; int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; int swapx = -1,swapy = -1; #if defined(DD_DEBUG) && defined(DD_VERBOSE) int initialSize,bestSize; #endif #ifdef DD_DEBUG /* We assume that x < y */ assert(x < y); #endif /* Find top, bottom, and size for the two groups. */ xbot = x; xtop = table->subtables[x].next; xsize = xbot - xtop + 1; ybot = y; while ((unsigned) ybot < table->subtables[ybot].next) ybot = table->subtables[ybot].next; ytop = y; ysize = ybot - ytop + 1; #if defined(DD_DEBUG) && defined(DD_VERBOSE) initialSize = bestSize = table->keys - table->isolated; #endif /* Sift the variables of the second group up through the first group */ for (i = 1; i <= ysize; i++) { for (j = 1; j <= xsize; j++) { size = cuddSwapInPlace(table,x,y); if (size == 0) goto ddGroupMoveOutOfMem; #if defined(DD_DEBUG) && defined(DD_VERBOSE) if (size < bestSize) bestSize = size; #endif swapx = x; swapy = y; y = x; x = cuddNextLow(table,y); } y = ytop + i; x = cuddNextLow(table,y); } #if defined(DD_DEBUG) && defined(DD_VERBOSE) if ((bestSize < initialSize) && (bestSize < size)) (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); #endif /* fix groups */ y = xtop; /* ytop is now where xtop used to be */ for (i = 0; i < ysize - 1; i++) { table->subtables[y].next = cuddNextHigh(table,y); y = cuddNextHigh(table,y); } table->subtables[y].next = xtop; /* y is bottom of its group, join */ /* it to top of its group */ x = cuddNextHigh(table,y); newxtop = x; for (i = 0; i < xsize - 1; i++) { table->subtables[x].next = cuddNextHigh(table,x); x = cuddNextHigh(table,x); } table->subtables[x].next = newxtop; /* x is bottom of its group, join */ /* it to top of its group */ #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n"); #endif /* Store group move */ move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddGroupMoveOutOfMem; move->x = swapx; move->y = swapy; move->flags = MTR_DEFAULT; move->size = table->keys - table->isolated; move->next = *moves; *moves = move; return(table->keys - table->isolated); ddGroupMoveOutOfMem: while (*moves != NULL) { move = (*moves)->next; cuddDeallocMove(table, *moves); *moves = move; } return(0); } /* end of ddGroupMove */ /**Function******************************************************************** Synopsis [Undoes the swap two groups.] Description [Undoes the swap two groups. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddGroupMoveBackward( DdManager * table, int x, int y) { int size; int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; #ifdef DD_DEBUG /* We assume that x < y */ assert(x < y); #endif /* Find top, bottom, and size for the two groups. */ xbot = x; xtop = table->subtables[x].next; xsize = xbot - xtop + 1; ybot = y; while ((unsigned) ybot < table->subtables[ybot].next) ybot = table->subtables[ybot].next; ytop = y; ysize = ybot - ytop + 1; /* Sift the variables of the second group up through the first group */ for (i = 1; i <= ysize; i++) { for (j = 1; j <= xsize; j++) { size = cuddSwapInPlace(table,x,y); if (size == 0) return(0); y = x; x = cuddNextLow(table,y); } y = ytop + i; x = cuddNextLow(table,y); } /* fix groups */ y = xtop; for (i = 0; i < ysize - 1; i++) { table->subtables[y].next = cuddNextHigh(table,y); y = cuddNextHigh(table,y); } table->subtables[y].next = xtop; /* y is bottom of its group, join */ /* to its top */ x = cuddNextHigh(table,y); newxtop = x; for (i = 0; i < xsize - 1; i++) { table->subtables[x].next = cuddNextHigh(table,x); x = cuddNextHigh(table,x); } table->subtables[x].next = newxtop; /* x is bottom of its group, join */ /* to its top */ #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n"); #endif return(1); } /* end of ddGroupMoveBackward */ /**Function******************************************************************** Synopsis [Determines the best position for a variables and returns it there.] Description [Determines the best position for a variables and returns it there. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddGroupSiftingBackward( DdManager * table, Move * moves, int size, int upFlag, int lazyFlag) { Move *move; int res; Move *end_move = NULL; int diff, tmp_diff; int index; unsigned int pairlev; if (lazyFlag) { end_move = NULL; /* Find the minimum size, and the earliest position at which it ** was achieved. */ for (move = moves; move != NULL; move = move->next) { if (move->size < size) { size = move->size; end_move = move; } else if (move->size == size) { if (end_move == NULL) end_move = move; } } /* Find among the moves that give minimum size the one that ** minimizes the distance from the corresponding variable. */ if (moves != NULL) { diff = Cudd_ReadSize(table) + 1; index = (upFlag == 1) ? table->invperm[moves->x] : table->invperm[moves->y]; pairlev = (unsigned) table->perm[Cudd_bddReadPairIndex(table, index)]; for (move = moves; move != NULL; move = move->next) { if (move->size == size) { if (upFlag == 1) { tmp_diff = (move->x > pairlev) ? move->x - pairlev : pairlev - move->x; } else { tmp_diff = (move->y > pairlev) ? move->y - pairlev : pairlev - move->y; } if (tmp_diff < diff) { diff = tmp_diff; end_move = move; } } } } } else { /* Find the minimum size. */ for (move = moves; move != NULL; move = move->next) { if (move->size < size) { size = move->size; } } } /* In case of lazy sifting, end_move identifies the position at ** which we want to stop. Otherwise, we stop as soon as we meet ** the minimum size. */ for (move = moves; move != NULL; move = move->next) { if (lazyFlag) { if (move == end_move) return(1); } else { if (move->size == size) return(1); } if ((table->subtables[move->x].next == move->x) && (table->subtables[move->y].next == move->y)) { res = cuddSwapInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n"); assert(table->subtables[move->x].next == move->x); assert(table->subtables[move->y].next == move->y); #endif } else { /* Group move necessary */ if (move->flags == MTR_NEWNODE) { ddDissolveGroup(table,(int)move->x,(int)move->y); } else { res = ddGroupMoveBackward(table,(int)move->x,(int)move->y); if (!res) return(0); } } } return(1); } /* end of ddGroupSiftingBackward */ /**Function******************************************************************** Synopsis [Merges groups in the DD table.] Description [Creates a single group from low to high and adjusts the index field of the tree node.] SideEffects [None] ******************************************************************************/ static void ddMergeGroups( DdManager * table, MtrNode * treenode, int low, int high) { int i; MtrNode *auxnode; int saveindex; int newindex; /* Merge all variables from low to high in one group, unless ** this is the topmost group. In such a case we do not merge lest ** we lose the symmetry information. */ if (treenode != table->tree) { for (i = low; i < high; i++) table->subtables[i].next = i+1; table->subtables[high].next = low; } /* Adjust the index fields of the tree nodes. If a node is the ** first child of its parent, then the parent may also need adjustment. */ saveindex = treenode->index; newindex = table->invperm[low]; auxnode = treenode; do { auxnode->index = newindex; if (auxnode->parent == NULL || (int) auxnode->parent->index != saveindex) break; auxnode = auxnode->parent; } while (1); return; } /* end of ddMergeGroups */ /**Function******************************************************************** Synopsis [Dissolves a group in the DD table.] Description [x and y are variables in a group to be cut in two. The cut is to pass between x and y.] SideEffects [None] ******************************************************************************/ static void ddDissolveGroup( DdManager * table, int x, int y) { int topx; int boty; /* find top and bottom of the two groups */ boty = y; while ((unsigned) boty < table->subtables[boty].next) boty = table->subtables[boty].next; topx = table->subtables[boty].next; table->subtables[boty].next = y; table->subtables[x].next = topx; return; } /* end of ddDissolveGroup */ /**Function******************************************************************** Synopsis [Pretends to check two variables for aggregation.] Description [Pretends to check two variables for aggregation. Always returns 0.] SideEffects [None] ******************************************************************************/ static int ddNoCheck( DdManager * table, int x, int y) { return(0); } /* end of ddNoCheck */ /**Function******************************************************************** Synopsis [Checks two variables for aggregation.] Description [Checks two variables for aggregation. The check is based on the second difference of the number of nodes as a function of the layer. If the second difference is lower than a given threshold (typically negative) then the two variables should be aggregated. Returns 1 if the two variables pass the test; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddSecDiffCheck( DdManager * table, int x, int y) { double Nx,Nx_1; double Sx; double threshold; int xindex,yindex; if (x==0) return(0); #ifdef DD_STATS secdiffcalls++; #endif Nx = (double) table->subtables[x].keys; Nx_1 = (double) table->subtables[x-1].keys; Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1); threshold = table->recomb / 100.0; if (Sx < threshold) { xindex = table->invperm[x]; yindex = table->invperm[y]; if (cuddTestInteract(table,xindex,yindex)) { #if defined(DD_DEBUG) && defined(DD_VERBOSE) (void) fprintf(table->out, "Second difference for %d = %g Pos(%d)\n", table->invperm[x],Sx,x); #endif #ifdef DD_STATS secdiff++; #endif return(1); } else { #ifdef DD_STATS secdiffmisfire++; #endif return(0); } } return(0); } /* end of ddSecDiffCheck */ /**Function******************************************************************** Synopsis [Checks for extended symmetry of x and y.] Description [Checks for extended symmetry of x and y. Returns 1 in case of extended symmetry; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddExtSymmCheck( DdManager * table, int x, int y) { DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; DdNode *one; unsigned comple; /* f0 is complemented */ int notproj; /* f is not a projection function */ int arccount; /* number of arcs from layer x to layer y */ int TotalRefCount; /* total reference count of layer y minus 1 */ int counter; /* number of nodes of layer x that are allowed */ /* to violate extended symmetry conditions */ int arccounter; /* number of arcs into layer y that are allowed */ /* to come from layers other than x */ int i; int xindex; int yindex; int res; int slots; DdNodePtr *list; DdNode *sentinel = &(table->sentinel); xindex = table->invperm[x]; yindex = table->invperm[y]; /* If the two variables do not interact, we do not want to merge them. */ if (!cuddTestInteract(table,xindex,yindex)) return(0); #ifdef DD_DEBUG /* Checks that x and y do not contain just the projection functions. ** With the test on interaction, these test become redundant, ** because an isolated projection function does not interact with ** any other variable. */ if (table->subtables[x].keys == 1) { assert(table->vars[xindex]->ref != 1); } if (table->subtables[y].keys == 1) { assert(table->vars[yindex]->ref != 1); } #endif #ifdef DD_STATS extsymmcalls++; #endif arccount = 0; counter = (int) (table->subtables[x].keys * (table->symmviolation/100.0) + 0.5); one = DD_ONE(table); slots = table->subtables[x].slots; list = table->subtables[x].nodelist; for (i = 0; i < slots; i++) { f = list[i]; while (f != sentinel) { /* Find f1, f0, f11, f10, f01, f00. */ f1 = cuddT(f); f0 = Cudd_Regular(cuddE(f)); comple = Cudd_IsComplement(cuddE(f)); notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1; if (f1->index == (unsigned) yindex) { arccount++; f11 = cuddT(f1); f10 = cuddE(f1); } else { if ((int) f0->index != yindex) { /* If f is an isolated projection function it is ** allowed to bypass layer y. */ if (notproj) { if (counter == 0) return(0); counter--; /* f bypasses layer y */ } } f11 = f10 = f1; } if ((int) f0->index == yindex) { arccount++; f01 = cuddT(f0); f00 = cuddE(f0); } else { f01 = f00 = f0; } if (comple) { f01 = Cudd_Not(f01); f00 = Cudd_Not(f00); } /* Unless we are looking at a projection function ** without external references except the one from the ** table, we insist that f01 == f10 or f11 == f00 */ if (notproj) { if (f01 != f10 && f11 != f00) { if (counter == 0) return(0); counter--; } } f = f->next; } /* while */ } /* for */ /* Calculate the total reference counts of y */ TotalRefCount = -1; /* -1 for projection function */ slots = table->subtables[y].slots; list = table->subtables[y].nodelist; for (i = 0; i < slots; i++) { f = list[i]; while (f != sentinel) { TotalRefCount += f->ref; f = f->next; } } arccounter = (int) (table->subtables[y].keys * (table->arcviolation/100.0) + 0.5); res = arccount >= TotalRefCount - arccounter; #if defined(DD_DEBUG) && defined(DD_VERBOSE) if (res) { (void) fprintf(table->out, "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n", xindex,yindex,x,y); } #endif #ifdef DD_STATS if (res) extsymm++; #endif return(res); } /* end ddExtSymmCheck */ /**Function******************************************************************** Synopsis [Checks for grouping of x and y.] Description [Checks for grouping of x and y. Returns 1 in case of grouping; 0 otherwise. This function is used for lazy sifting.] SideEffects [None] ******************************************************************************/ static int ddVarGroupCheck( DdManager * table, int x, int y) { int xindex = table->invperm[x]; int yindex = table->invperm[y]; if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0); if (Cudd_bddReadPairIndex(table, xindex) == yindex) { if (ddIsVarHandled(table, xindex) || ddIsVarHandled(table, yindex)) { if (Cudd_bddIsVarToBeGrouped(table, xindex) || Cudd_bddIsVarToBeGrouped(table, yindex) ) { if (table->keys - table->isolated <= originalSize) { return(1); } } } } return(0); } /* end of ddVarGroupCheck */ /**Function******************************************************************** Synopsis [Sets a variable to already handled.] Description [Sets a variable to already handled. This function is used for lazy sifting.] SideEffects [none] SeeAlso [] ******************************************************************************/ static int ddSetVarHandled( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(0); dd->subtables[dd->perm[index]].varHandled = 1; return(1); } /* end of ddSetVarHandled */ /**Function******************************************************************** Synopsis [Resets a variable to be processed.] Description [Resets a variable to be processed. This function is used for lazy sifting.] SideEffects [none] SeeAlso [] ******************************************************************************/ static int ddResetVarHandled( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(0); dd->subtables[dd->perm[index]].varHandled = 0; return(1); } /* end of ddResetVarHandled */ /**Function******************************************************************** Synopsis [Checks whether a variables is already handled.] Description [Checks whether a variables is already handled. This function is used for lazy sifting.] SideEffects [none] SeeAlso [] ******************************************************************************/ static int ddIsVarHandled( DdManager *dd, int index) { if (index >= dd->size || index < 0) return(-1); return dd->subtables[dd->perm[index]].varHandled; } /* end of ddIsVarHandled */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddHarwell.c000066400000000000000000000441661300674244400241210ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddHarwell.c] PackageName [cudd] Synopsis [Function to read a matrix in Harwell format.] Description [External procedures included in this module:
      • Cudd_addHarwell()
      ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddHarwell.c,v 1.9 2004/08/13 18:04:49 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Reads in a matrix in the format of the Harwell-Boeing benchmark suite.] Description [Reads in a matrix in the format of the Harwell-Boeing benchmark suite. The variables are ordered as follows:
      x\[0\] y\[0\] x\[1\] y\[1\] ...
      0 is the most significant bit. On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. Returns 1 on success; 0 otherwise. The ADD for the sparse matrix is returned in E, and its reference count is > 0.] SideEffects [None] SeeAlso [Cudd_addRead Cudd_bddRead] ******************************************************************************/ int Cudd_addHarwell( FILE * fp /* pointer to the input file */, DdManager * dd /* DD manager */, DdNode ** E /* characteristic function of the graph */, DdNode *** x /* array of row variables */, DdNode *** y /* array of column variables */, DdNode *** xn /* array of complemented row variables */, DdNode *** yn_ /* array of complemented column variables */, int * nx /* number or row variables */, int * ny /* number or column variables */, int * m /* number of rows */, int * n /* number of columns */, int bx /* first index of row variables */, int sx /* step of row variables */, int by /* first index of column variables */, int sy /* step of column variables */, int pr /* verbosity level */) { DdNode *one, *zero; DdNode *w; DdNode *cubex, *cubey, *minterm1; int u, v, err, i, j, nv; double val; DdNode **lx = NULL, **ly = NULL, **lxn = NULL, **lyn = NULL; /* local copies of x, y, xn, yn_ */ int lnx, lny; /* local copies of nx and ny */ char title[73], key[9], mxtype[4], rhstyp[4]; int totcrd, ptrcrd, indcrd, valcrd, rhscrd, nrow, ncol, nnzero, neltvl, nrhs, nrhsix; int *colptr, *rowind; #if 0 int nguess, nexact; int *rhsptr, *rhsind; #endif if (*nx < 0 || *ny < 0) return(0); one = DD_ONE(dd); zero = DD_ZERO(dd); /* Read the header */ err = fscanf(fp, "%72c %8c", title, key); if (err == EOF) { return(0); } else if (err != 2) { return(0); } title[72] = (char) 0; key[8] = (char) 0; err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd, &valcrd, &rhscrd); if (err == EOF) { return(0); } else if (err != 5) { return(0); } err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol, &nnzero, &neltvl); if (err == EOF) { return(0); } else if (err != 5) { return(0); } /* Skip FORTRAN formats */ if (rhscrd == 0) { err = fscanf(fp, "%*s %*s %*s \n"); } else { err = fscanf(fp, "%*s %*s %*s %*s \n"); } if (err == EOF) { return(0); } else if (err != 0) { return(0); } /* Print out some stuff if requested to be verbose */ if (pr>0) { (void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key, mxtype, nrow, ncol, nnzero); if (pr>1) (void) fprintf(dd->out,"%s\n", title); } /* Check matrix type */ if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') { (void) fprintf(dd->err,"%s: Illegal matrix type: %s\n", key, mxtype); return(0); } if (neltvl != 0) return(0); /* Read optional 5-th line */ if (rhscrd != 0) { err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix); if (err == EOF) { return(0); } else if (err != 3) { return(0); } rhstyp[3] = (char) 0; if (rhstyp[0] != 'F') { (void) fprintf(dd->err, "%s: Sparse right-hand side not yet supported\n", key); return(0); } if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs); } else { nrhs = 0; } /* Compute the number of variables */ /* row and column numbers start from 0 */ u = nrow - 1; for (i=0; u > 0; i++) { u >>= 1; } lnx = i; if (nrhs == 0) { v = ncol - 1; } else { v = 2* (ddMax(ncol, nrhs) - 1); } for (i=0; v > 0; i++) { v >>= 1; } lny = i; /* Allocate or reallocate arrays for variables as needed */ if (*nx == 0) { if (lnx > 0) { *x = lx = ABC_ALLOC(DdNode *,lnx); if (lx == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } *xn = lxn = ABC_ALLOC(DdNode *,lnx); if (lxn == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } else { *x = *xn = NULL; } } else if (lnx > *nx) { *x = lx = ABC_REALLOC(DdNode *, *x, lnx); if (lx == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } *xn = lxn = ABC_REALLOC(DdNode *, *xn, lnx); if (lxn == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } else { lx = *x; lxn = *xn; } if (*ny == 0) { if (lny >0) { *y = ly = ABC_ALLOC(DdNode *,lny); if (ly == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } *yn_ = lyn = ABC_ALLOC(DdNode *,lny); if (lyn == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } else { *y = *yn_ = NULL; } } else if (lny > *ny) { *y = ly = ABC_REALLOC(DdNode *, *y, lny); if (ly == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } *yn_ = lyn = ABC_REALLOC(DdNode *, *yn_, lny); if (lyn == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } else { ly = *y; lyn = *yn_; } /* Create new variables as needed */ for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) { do { dd->reordered = 0; lx[i] = cuddUniqueInter(dd, nv, one, zero); } while (dd->reordered == 1); if (lx[i] == NULL) return(0); cuddRef(lx[i]); do { dd->reordered = 0; lxn[i] = cuddUniqueInter(dd, nv, zero, one); } while (dd->reordered == 1); if (lxn[i] == NULL) return(0); cuddRef(lxn[i]); } for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) { do { dd->reordered = 0; ly[i] = cuddUniqueInter(dd, nv, one, zero); } while (dd->reordered == 1); if (ly[i] == NULL) return(0); cuddRef(ly[i]); do { dd->reordered = 0; lyn[i] = cuddUniqueInter(dd, nv, zero, one); } while (dd->reordered == 1); if (lyn[i] == NULL) return(0); cuddRef(lyn[i]); } /* Update matrix parameters */ *nx = lnx; *ny = lny; *m = nrow; if (nrhs == 0) { *n = ncol; } else { *n = (1 << (lny - 1)) + nrhs; } /* Read structure data */ colptr = ABC_ALLOC(int, ncol+1); if (colptr == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } rowind = ABC_ALLOC(int, nnzero); if (rowind == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } for (i=0; ierr,"%s: Unexpected colptr[0] (%d)\n", key,colptr[0]); ABC_FREE(colptr); ABC_FREE(rowind); return(0); } for (i=0; i=0; nv--) { if (v & 1) { w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); } else { w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); } if (w == NULL) { Cudd_RecursiveDeref(dd, cubey); ABC_FREE(colptr); ABC_FREE(rowind); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, cubey); cubey = w; v >>= 1; } for (i=colptr[j]; i=0; nv--) { if (u & 1) { w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); } else { w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); } if (w == NULL) { Cudd_RecursiveDeref(dd, cubey); Cudd_RecursiveDeref(dd, cubex); ABC_FREE(colptr); ABC_FREE(rowind); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, cubex); cubex = w; u >>= 1; } minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); if (minterm1 == NULL) { Cudd_RecursiveDeref(dd, cubey); Cudd_RecursiveDeref(dd, cubex); ABC_FREE(colptr); ABC_FREE(rowind); return(0); } cuddRef(minterm1); Cudd_RecursiveDeref(dd, cubex); w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); if (w == NULL) { Cudd_RecursiveDeref(dd, cubey); ABC_FREE(colptr); ABC_FREE(rowind); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, minterm1); Cudd_RecursiveDeref(dd, *E); *E = w; } Cudd_RecursiveDeref(dd, cubey); } ABC_FREE(colptr); ABC_FREE(rowind); /* Read right-hand sides */ for (j=0; j=0; nv--) { if (v & 1) { w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); } else { w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); } if (w == NULL) { Cudd_RecursiveDeref(dd, cubey); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, cubey); cubey = w; v >>= 1; } for (i=0; i=0; nv--) { if (u & 1) { w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); } else { w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); } if (w == NULL) { Cudd_RecursiveDeref(dd, cubey); Cudd_RecursiveDeref(dd, cubex); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, cubex); cubex = w; u >>= 1; } minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); if (minterm1 == NULL) { Cudd_RecursiveDeref(dd, cubey); Cudd_RecursiveDeref(dd, cubex); return(0); } cuddRef(minterm1); Cudd_RecursiveDeref(dd, cubex); w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); if (w == NULL) { Cudd_RecursiveDeref(dd, cubey); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, minterm1); Cudd_RecursiveDeref(dd, *E); *E = w; } Cudd_RecursiveDeref(dd, cubey); } return(1); } /* end of Cudd_addHarwell */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddInit.c000066400000000000000000000247461300674244400234300ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddInit.c] PackageName [cudd] Synopsis [Functions to initialize and shut down the DD manager.] Description [External procedures included in this module:
      • Cudd_Init()
      • Cudd_Quit()
      Internal procedures included in this module:
      • cuddZddInitUniv()
      • cuddZddFreeUniv()
      ] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddInit.c,v 1.33 2007/07/01 05:10:50 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Creates a new DD manager.] Description [Creates a new DD manager, initializes the table, the basic constants and the projection functions. If maxMemory is 0, Cudd_Init decides suitable values for the maximum size of the cache and for the limit for fast unique table growth based on the available memory. Returns a pointer to the manager if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_Quit] ******************************************************************************/ DdManager * Cudd_Init( unsigned int numVars /* initial number of BDD variables (i.e., subtables) */, unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */, unsigned int numSlots /* initial size of the unique tables */, unsigned int cacheSize /* initial size of the cache */, unsigned long maxMemory /* target maximum memory occupation */) { DdManager *unique; int i,result; DdNode *one, *zero; unsigned int maxCacheSize; unsigned int looseUpTo; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; if (maxMemory == 0) { maxMemory = getSoftDataLimit(); } looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) / DD_MAX_LOOSE_FRACTION); unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo); if (unique == NULL) return(NULL); unique->maxmem = (unsigned long) maxMemory / 10 * 9; maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) / DD_MAX_CACHE_FRACTION); result = cuddInitCache(unique,cacheSize,maxCacheSize); if (result == 0) return(NULL); saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; unique->stash = ABC_ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4); MMoutOfMemory = saveHandler; if (unique->stash == NULL) { (void) fprintf(unique->err,"Unable to set aside memory\n"); } /* Initialize constants. */ unique->one = cuddUniqueConst(unique,1.0); if (unique->one == NULL) return(0); cuddRef(unique->one); unique->zero = cuddUniqueConst(unique,0.0); if (unique->zero == NULL) return(0); cuddRef(unique->zero); #ifdef HAVE_IEEE_754 if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 || DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) { (void) fprintf(unique->err,"Warning: Crippled infinite values\n"); (void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n"); } #endif unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL); if (unique->plusinfinity == NULL) return(0); cuddRef(unique->plusinfinity); unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL); if (unique->minusinfinity == NULL) return(0); cuddRef(unique->minusinfinity); unique->background = unique->zero; /* The logical zero is different from the CUDD_VALUE_TYPE zero! */ one = unique->one; zero = Cudd_Not(one); /* Create the projection functions. */ unique->vars = ABC_ALLOC(DdNodePtr,unique->maxSize); if (unique->vars == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < unique->size; i++) { unique->vars[i] = cuddUniqueInter(unique,i,one,zero); if (unique->vars[i] == NULL) return(0); cuddRef(unique->vars[i]); } if (unique->sizeZ) cuddZddInitUniv(unique); unique->memused += sizeof(DdNode *) * unique->maxSize; unique->bFunc = NULL; unique->bFunc2 = NULL; unique->TimeStop = 0; return(unique); } /* end of Cudd_Init */ /**Function******************************************************************** Synopsis [Deletes resources associated with a DD manager.] Description [Deletes resources associated with a DD manager and resets the global statistical counters. (Otherwise, another manaqger subsequently created would inherit the stats of this one.)] SideEffects [None] SeeAlso [Cudd_Init] ******************************************************************************/ void Cudd_Quit( DdManager * unique) { if (unique->stash != NULL) ABC_FREE(unique->stash); cuddFreeTable(unique); } /* end of Cudd_Quit */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Initializes the ZDD universe.] Description [Initializes the ZDD universe. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddZddFreeUniv] ******************************************************************************/ int cuddZddInitUniv( DdManager * zdd) { DdNode *p, *res; int i; zdd->univ = ABC_ALLOC(DdNodePtr, zdd->sizeZ); if (zdd->univ == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; return(0); } res = DD_ONE(zdd); cuddRef(res); for (i = zdd->sizeZ - 1; i >= 0; i--) { unsigned int index = zdd->invpermZ[i]; p = res; res = cuddUniqueInterZdd(zdd, index, p, p); if (res == NULL) { Cudd_RecursiveDerefZdd(zdd,p); ABC_FREE(zdd->univ); return(0); } cuddRef(res); cuddDeref(p); zdd->univ[i] = res; } #ifdef DD_VERBOSE cuddZddP(zdd, zdd->univ[0]); #endif return(1); } /* end of cuddZddInitUniv */ /**Function******************************************************************** Synopsis [Frees the ZDD universe.] Description [Frees the ZDD universe.] SideEffects [None] SeeAlso [cuddZddInitUniv] ******************************************************************************/ void cuddZddFreeUniv( DdManager * zdd) { if (zdd->univ) { Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]); ABC_FREE(zdd->univ); } } /* end of cuddZddFreeUniv */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddInt.h000066400000000000000000001456511300674244400232630ustar00rootroot00000000000000/**CHeaderFile***************************************************************** FileName [cuddInt.h] PackageName [cudd] Synopsis [Internal data structures of the CUDD package.] Description [] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] Revision [$Id: cuddInt.h,v 1.139 2009/03/08 02:49:02 fabio Exp $] ******************************************************************************/ #ifndef ABC__bdd__cudd__cuddInt_h #define ABC__bdd__cudd__cuddInt_h /*---------------------------------------------------------------------------*/ /* Nested includes */ /*---------------------------------------------------------------------------*/ #ifdef DD_MIS #include "array.h" #include "list.h" #include "misc/st/st.h" #include "misc/espresso/espresso.h" #include "node.h" #ifdef SIS #include "graph.h" #include "astg.h" #endif #include "network.h" #endif #include #include "cudd.h" #include "misc/st/st.h" ABC_NAMESPACE_HEADER_START #if defined(__GNUC__) # define DD_INLINE __inline__ # if (__GNUC__ >2 || __GNUC_MINOR__ >=7) # define DD_UNUSED __attribute__ ((__unused__)) # else # define DD_UNUSED # endif #else # if defined(__cplusplus) # define DD_INLINE inline # else # define DD_INLINE # endif # define DD_UNUSED #endif /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DD_MAXREF ((DdHalfWord) ~0) #define DD_DEFAULT_RESIZE 10 /* how many extra variables */ /* should be added when resizing */ #define DD_MEM_CHUNK 1022 /* These definitions work for CUDD_VALUE_TYPE == double */ #define DD_ONE_VAL (1.0) #define DD_ZERO_VAL (0.0) #define DD_EPSILON (1.0e-12) /* The definitions of +/- infinity in terms of HUGE_VAL work on ** the DECstations and on many other combinations of OS/compiler. */ #ifdef HAVE_IEEE_754 # define DD_PLUS_INF_VAL (HUGE_VAL) #else # define DD_PLUS_INF_VAL (10e301) # define DD_CRI_HI_MARK (10e150) # define DD_CRI_LO_MARK (-(DD_CRI_HI_MARK)) #endif #define DD_MINUS_INF_VAL (-(DD_PLUS_INF_VAL)) #define DD_NON_CONSTANT ((DdNode *) 1) /* for Cudd_bddIteConstant */ /* Unique table and cache management constants. */ #define DD_MAX_SUBTABLE_DENSITY 4 /* tells when to resize a subtable */ /* gc when this percent are dead (measured w.r.t. slots, not keys) ** The first limit (LO) applies normally. The second limit applies when ** the package believes more space for the unique table (i.e., more dead ** nodes) would improve performance, and the unique table is not already ** too large. The third limit applies when memory is low. */ #define DD_GC_FRAC_LO DD_MAX_SUBTABLE_DENSITY * 0.25 #define DD_GC_FRAC_HI DD_MAX_SUBTABLE_DENSITY * 1.0 #define DD_GC_FRAC_MIN 0.2 #define DD_MIN_HIT 30 /* resize cache when hit ratio above this percentage (default) */ #define DD_MAX_LOOSE_FRACTION 5 /* 1 / (max fraction of memory used for unique table in fast growth mode) */ #define DD_MAX_CACHE_FRACTION 3 /* 1 / (max fraction of memory used for computed table if resizing enabled) */ #define DD_STASH_FRACTION 64 /* 1 / (fraction of memory set aside for emergencies) */ #define DD_MAX_CACHE_TO_SLOTS_RATIO 4 /* used to limit the cache size */ /* Variable ordering default parameter values. */ #define DD_SIFT_MAX_VAR 1000 #define DD_SIFT_MAX_SWAPS 2000000 #define DD_DEFAULT_RECOMB 0 #define DD_MAX_REORDER_GROWTH 1.1 #define DD_FIRST_REORDER 4004 /* 4 for the constants */ #define DD_DYN_RATIO 2 /* when to dynamically reorder */ /* Primes for cache hash functions. */ #define DD_P1 12582917 #define DD_P2 4256249 #define DD_P3 741457 #define DD_P4 1618033999 /* Cache tags for 3-operand operators. These tags are stored in the ** least significant bits of the cache operand pointers according to ** the following scheme. The tag consists of two hex digits. Both digits ** must be even, so that they do not interfere with complementation bits. ** The least significant one is stored in Bits 3:1 of the f operand in the ** cache entry. Bit 1 is always 1, so that we can differentiate ** three-operand operations from one- and two-operand operations. ** Therefore, the least significant digit is one of {2,6,a,e}. The most ** significant digit occupies Bits 3:1 of the g operand in the cache ** entry. It can by any even digit between 0 and e. This gives a total ** of 5 bits for the tag proper, which means a maximum of 32 three-operand ** operations. */ #define DD_ADD_ITE_TAG 0x02 #define DD_BDD_AND_ABSTRACT_TAG 0x06 #define DD_BDD_XOR_EXIST_ABSTRACT_TAG 0x0a #define DD_BDD_ITE_TAG 0x0e #define DD_ADD_BDD_DO_INTERVAL_TAG 0x22 #define DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG 0x26 #define DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG 0x2a #define DD_BDD_COMPOSE_RECUR_TAG 0x2e #define DD_ADD_COMPOSE_RECUR_TAG 0x42 #define DD_ADD_NON_SIM_COMPOSE_TAG 0x46 #define DD_EQUIV_DC_TAG 0x4a #define DD_ZDD_ITE_TAG 0x4e #define DD_ADD_ITE_CONSTANT_TAG 0x62 #define DD_ADD_EVAL_CONST_TAG 0x66 #define DD_BDD_ITE_CONSTANT_TAG 0x6a #define DD_ADD_OUT_SUM_TAG 0x6e #define DD_BDD_LEQ_UNLESS_TAG 0x82 #define DD_ADD_TRIANGLE_TAG 0x86 /* Generator constants. */ #define CUDD_GEN_CUBES 0 #define CUDD_GEN_PRIMES 1 #define CUDD_GEN_NODES 2 #define CUDD_GEN_ZDD_PATHS 3 #define CUDD_GEN_EMPTY 0 #define CUDD_GEN_NONEMPTY 1 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ struct DdGen { DdManager *manager; int type; int status; union { struct { int *cube; CUDD_VALUE_TYPE value; } cubes; struct { int *cube; DdNode *ub; } primes; struct { int size; } nodes; } gen; struct { int sp; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif DdNode **stack; #ifdef __osf__ #pragma pointer_size restore #endif } stack; DdNode *node; }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /* Hooks in CUDD are functions that the application registers with the ** manager so that they are called at appropriate times. The functions ** are passed the manager as argument; they should return 1 if ** successful and 0 otherwise. */ typedef struct DdHook { /* hook list element */ DD_HFP f; /* function to be called */ struct DdHook *next; /* next element in the list */ } DdHook; /* #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 typedef long ptrint; typedef unsigned long ptruint; #else typedef int ptrint; typedef unsigned int ptruint; #endif */ typedef ABC_PTRINT_T ptrint; typedef ABC_PTRUINT_T ptruint; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif typedef DdNode *DdNodePtr; /* Generic local cache item. */ typedef struct DdLocalCacheItem { DdNode *value; #ifdef DD_CACHE_PROFILE ptrint count; #endif DdNode *key[1]; } DdLocalCacheItem; /* Local cache. */ typedef struct DdLocalCache { DdLocalCacheItem *item; unsigned int itemsize; unsigned int keysize; unsigned int slots; int shift; double lookUps; double minHit; double hits; unsigned int maxslots; DdManager *manager; struct DdLocalCache *next; } DdLocalCache; /* Generic hash item. */ typedef struct DdHashItem { struct DdHashItem *next; ptrint count; DdNode *value; DdNode *key[1]; } DdHashItem; /* Local hash table */ typedef struct DdHashTable { unsigned int keysize; unsigned int itemsize; DdHashItem **bucket; DdHashItem *nextFree; DdHashItem **memoryList; unsigned int numBuckets; int shift; unsigned int size; unsigned int maxsize; DdManager *manager; } DdHashTable; typedef struct DdCache { DdNode *f,*g; /* DDs */ ptruint h; /* either operator or DD */ DdNode *data; /* already constructed DD */ #ifdef DD_CACHE_PROFILE ptrint count; #endif unsigned hash; } DdCache; typedef struct DdSubtable { /* subtable for one index */ DdNode **nodelist; /* hash table */ int shift; /* shift for hash function */ unsigned int slots; /* size of the hash table */ unsigned int keys; /* number of nodes stored in this table */ unsigned int maxKeys; /* slots * DD_MAX_SUBTABLE_DENSITY */ unsigned int dead; /* number of dead nodes in this table */ unsigned int next; /* index of next variable in group */ int bindVar; /* flag to bind this variable to its level */ /* Fields for lazy sifting. */ Cudd_VariableType varType; /* variable type (ps, ns, pi) */ int pairIndex; /* corresponding variable index (ps <-> ns) */ int varHandled; /* flag: 1 means variable is already handled */ Cudd_LazyGroupType varToBeGrouped; /* tells what grouping to apply */ } DdSubtable; struct DdManager { /* specialized DD symbol table */ /* Constants */ DdNode sentinel; /* for collision lists */ DdNode *one; /* constant 1 */ DdNode *zero; /* constant 0 */ DdNode *plusinfinity; /* plus infinity */ DdNode *minusinfinity; /* minus infinity */ DdNode *background; /* background value */ /* Computed Table */ DdCache *acache; /* address of allocated memory for cache */ DdCache *cache; /* the cache-based computed table */ unsigned int cacheSlots; /* total number of cache entries */ int cacheShift; /* shift value for cache hash function */ double cacheMisses; /* number of cache misses (since resizing) */ double cacheHits; /* number of cache hits (since resizing) */ double minHit; /* hit percentage above which to resize */ int cacheSlack; /* slots still available for resizing */ unsigned int maxCacheHard; /* hard limit for cache size */ /* Unique Table */ int size; /* number of unique subtables */ int sizeZ; /* for ZDD */ int maxSize; /* max number of subtables before resizing */ int maxSizeZ; /* for ZDD */ DdSubtable *subtables; /* array of unique subtables */ DdSubtable *subtableZ; /* for ZDD */ DdSubtable constants; /* unique subtable for the constants */ unsigned int slots; /* total number of hash buckets */ unsigned int keys; /* total number of BDD and ADD nodes */ unsigned int keysZ; /* total number of ZDD nodes */ unsigned int dead; /* total number of dead BDD and ADD nodes */ unsigned int deadZ; /* total number of dead ZDD nodes */ unsigned int maxLive; /* maximum number of live nodes */ unsigned int minDead; /* do not GC if fewer than these dead */ double gcFrac; /* gc when this fraction is dead */ int gcEnabled; /* gc is enabled */ unsigned int looseUpTo; /* slow growth beyond this limit */ /* (measured w.r.t. slots, not keys) */ unsigned int initSlots; /* initial size of a subtable */ DdNode **stack; /* stack for iterative procedures */ // double allocated; /* number of nodes allocated */ ABC_INT64_T allocated; /* number of nodes allocated */ /* (not during reordering) */ double reclaimed; /* number of nodes brought back from the dead */ int isolated; /* isolated projection functions */ int *perm; /* current variable perm. (index to level) */ int *permZ; /* for ZDD */ int *invperm; /* current inv. var. perm. (level to index) */ int *invpermZ; /* for ZDD */ DdNode **vars; /* projection functions */ int *map; /* variable map for fast swap */ DdNode **univ; /* ZDD 1 for each variable */ int linearSize; /* number of rows and columns of linear */ long *interact; /* interacting variable matrix */ long *linear; /* linear transform matrix */ /* Memory Management */ DdNode **memoryList; /* memory manager for symbol table */ DdNode *nextFree; /* list of free nodes */ char *stash; /* memory reserve */ #ifndef DD_NO_DEATH_ROW DdNode **deathRow; /* queue for dereferencing */ int deathRowDepth; /* number of slots in the queue */ int nextDead; /* index in the queue */ unsigned deadMask; /* mask for circular index update */ #endif /* General Parameters */ CUDD_VALUE_TYPE epsilon; /* tolerance on comparisons */ /* Dynamic Reordering Parameters */ int reordered; /* flag set at the end of reordering */ int reorderings; /* number of calls to Cudd_ReduceHeap */ int siftMaxVar; /* maximum number of vars sifted */ int siftMaxSwap; /* maximum number of swaps per sifting */ double maxGrowth; /* maximum growth during reordering */ double maxGrowthAlt; /* alternate maximum growth for reordering */ int reordCycle; /* how often to apply alternate threshold */ int autoDyn; /* automatic dynamic reordering flag (BDD) */ int autoDynZ; /* automatic dynamic reordering flag (ZDD) */ Cudd_ReorderingType autoMethod; /* default reordering method */ Cudd_ReorderingType autoMethodZ; /* default reordering method (ZDD) */ int realign; /* realign ZDD order after BDD reordering */ int realignZ; /* realign BDD order after ZDD reordering */ unsigned int nextDyn; /* reorder if this size is reached */ unsigned int countDead; /* if 0, count deads to trigger reordering */ MtrNode *tree; /* Variable group tree (BDD) */ MtrNode *treeZ; /* Variable group tree (ZDD) */ Cudd_AggregationType groupcheck; /* Used during group sifting */ int recomb; /* Used during group sifting */ int symmviolation; /* Used during group sifting */ int arcviolation; /* Used during group sifting */ int populationSize; /* population size for GA */ int numberXovers; /* number of crossovers for GA */ DdLocalCache *localCaches; /* local caches currently in existence */ #ifdef __osf__ #pragma pointer_size restore #endif char *hooks; /* application-specific field (used by vis) */ DdHook *preGCHook; /* hooks to be called before GC */ DdHook *postGCHook; /* hooks to be called after GC */ DdHook *preReorderingHook; /* hooks to be called before reordering */ DdHook *postReorderingHook; /* hooks to be called after reordering */ FILE *out; /* stdout for this manager */ FILE *err; /* stderr for this manager */ #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif Cudd_ErrorType errorCode; /* info on last error */ /* Statistical counters. */ unsigned long memused; /* total memory allocated for the manager */ unsigned long maxmem; /* target maximum memory */ unsigned long maxmemhard; /* hard limit for maximum memory */ int garbageCollections; /* number of garbage collections */ long GCTime; /* total time spent in garbage collection */ long reordTime; /* total time spent in reordering */ double totCachehits; /* total number of cache hits */ double totCacheMisses; /* total number of cache misses */ double cachecollisions; /* number of cache collisions */ double cacheinserts; /* number of cache insertions */ double cacheLastInserts; /* insertions at the last cache resizing */ double cachedeletions; /* number of deletions during garbage coll. */ #ifdef DD_STATS double nodesFreed; /* number of nodes returned to the free list */ double nodesDropped; /* number of nodes killed by dereferencing */ #endif unsigned int peakLiveNodes; /* maximum number of live nodes */ #ifdef DD_UNIQUE_PROFILE double uniqueLookUps; /* number of unique table lookups */ double uniqueLinks; /* total distance traveled in coll. chains */ #endif #ifdef DD_COUNT double recursiveCalls; /* number of recursive calls */ #ifdef DD_STATS double nextSample; /* when to write next line of stats */ #endif double swapSteps; /* number of elementary reordering steps */ #endif #ifdef DD_MIS /* mis/verif compatibility fields */ array_t *iton; /* maps ids in ddNode to node_t */ array_t *order; /* copy of order_list */ lsHandle handle; /* where it is in network BDD list */ network_t *network; st__table *local_order; /* for local BDDs */ int nvars; /* variables used so far */ int threshold; /* for pseudo var threshold value*/ #endif DdNode * bFunc; DdNode * bFunc2; abctime TimeStop; /* timeout for reordering */ }; typedef struct Move { DdHalfWord x; DdHalfWord y; unsigned int flags; int size; struct Move *next; } Move; /* Generic level queue item. */ typedef struct DdQueueItem { struct DdQueueItem *next; struct DdQueueItem *cnext; void *key; } DdQueueItem; /* Level queue. */ typedef struct DdLevelQueue { void *first; DdQueueItem **last; DdQueueItem *freelist; DdQueueItem **buckets; int levels; int itemsize; int size; int maxsize; int numBuckets; int shift; } DdLevelQueue; #ifdef __osf__ #pragma pointer_size restore #endif /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**Macro*********************************************************************** Synopsis [Adds node to the head of the free list.] Description [Adds node to the head of the free list. Does not deallocate memory chunks that become free. This function is also used by the dynamic reordering functions.] SideEffects [None] SeeAlso [cuddAllocNode cuddDynamicAllocNode cuddDeallocMove] ******************************************************************************/ #define cuddDeallocNode(unique,node) \ (node)->next = (unique)->nextFree; \ (unique)->nextFree = node; /**Macro*********************************************************************** Synopsis [Adds node to the head of the free list.] Description [Adds node to the head of the free list. Does not deallocate memory chunks that become free. This function is also used by the dynamic reordering functions.] SideEffects [None] SeeAlso [cuddDeallocNode cuddDynamicAllocNode] ******************************************************************************/ #define cuddDeallocMove(unique,node) \ ((DdNode *)(node))->ref = 0; \ ((DdNode *)(node))->next = (unique)->nextFree; \ (unique)->nextFree = (DdNode *)(node); /**Macro*********************************************************************** Synopsis [Increases the reference count of a node, if it is not saturated.] Description [Increases the reference count of a node, if it is not saturated. This being a macro, it is faster than Cudd_Ref, but it cannot be used in constructs like cuddRef(a = b()).] SideEffects [none] SeeAlso [Cudd_Ref] ******************************************************************************/ #define cuddRef(n) cuddSatInc(Cudd_Regular(n)->ref) /**Macro*********************************************************************** Synopsis [Decreases the reference count of a node, if it is not saturated.] Description [Decreases the reference count of node. It is primarily used in recursive procedures to decrease the ref count of a result node before returning it. This accomplishes the goal of removing the protection applied by a previous cuddRef. This being a macro, it is faster than Cudd_Deref, but it cannot be used in constructs like cuddDeref(a = b()).] SideEffects [none] SeeAlso [Cudd_Deref] ******************************************************************************/ #define cuddDeref(n) cuddSatDec(Cudd_Regular(n)->ref) /**Macro*********************************************************************** Synopsis [Returns 1 if the node is a constant node.] Description [Returns 1 if the node is a constant node (rather than an internal node). All constant nodes have the same index (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.] SideEffects [none] SeeAlso [Cudd_IsConstant] ******************************************************************************/ #define cuddIsConstant(node) ((node)->index == CUDD_CONST_INDEX) /**Macro*********************************************************************** Synopsis [Returns the then child of an internal node.] Description [Returns the then child of an internal node. If node is a constant node, the result is unpredictable. The pointer passed to cuddT must be regular.] SideEffects [none] SeeAlso [Cudd_T] ******************************************************************************/ #define cuddT(node) ((node)->type.kids.T) /**Macro*********************************************************************** Synopsis [Returns the else child of an internal node.] Description [Returns the else child of an internal node. If node is a constant node, the result is unpredictable. The pointer passed to cuddE must be regular.] SideEffects [none] SeeAlso [Cudd_E] ******************************************************************************/ #define cuddE(node) ((node)->type.kids.E) /**Macro*********************************************************************** Synopsis [Returns the value of a constant node.] Description [Returns the value of a constant node. If node is an internal node, the result is unpredictable. The pointer passed to cuddV must be regular.] SideEffects [none] SeeAlso [Cudd_V] ******************************************************************************/ #define cuddV(node) ((node)->type.value) /**Macro*********************************************************************** Synopsis [Finds the current position of variable index in the order.] Description [Finds the current position of variable index in the order. This macro duplicates the functionality of Cudd_ReadPerm, but it does not check for out-of-bounds indices and it is more efficient.] SideEffects [none] SeeAlso [Cudd_ReadPerm] ******************************************************************************/ #define cuddI(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)]) /**Macro*********************************************************************** Synopsis [Finds the current position of ZDD variable index in the order.] Description [Finds the current position of ZDD variable index in the order. This macro duplicates the functionality of Cudd_ReadPermZdd, but it does not check for out-of-bounds indices and it is more efficient.] SideEffects [none] SeeAlso [Cudd_ReadPermZdd] ******************************************************************************/ #define cuddIZ(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)]) /**Macro*********************************************************************** Synopsis [Converts pointer into a literal.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ #define cuddF2L(f) ((Cudd_Regular(f)->Id << 1) | Cudd_IsComplement(f)) /**Macro*********************************************************************** Synopsis [Hash function for the unique table.] Description [] SideEffects [none] SeeAlso [ddCHash ddCHash2] ******************************************************************************/ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define ddHash(f,g,s) \ ((((unsigned)(ptruint)(f) * DD_P1 + \ (unsigned)(ptruint)(g)) * DD_P2) >> (s)) #else #define ddHash(f,g,s) \ ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) #endif /**Macro*********************************************************************** Synopsis [Hash function for the cache.] Description [] SideEffects [none] SeeAlso [ddHash ddCHash2] ******************************************************************************/ /* #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define ddCHash(o,f,g,h,s) \ ((((((unsigned)(ptruint)(f) + (unsigned)(ptruint)(o)) * DD_P1 + \ (unsigned)(ptruint)(g)) * DD_P2 + \ (unsigned)(ptruint)(h)) * DD_P3) >> (s)) #else #define ddCHash(o,f,g,h,s) \ ((((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2 + \ (unsigned)(h)) * DD_P3) >> (s)) #endif */ /**Macro*********************************************************************** Synopsis [Hash function for the cache for functions with two operands.] Description [] SideEffects [none] SeeAlso [ddHash ddCHash] ******************************************************************************/ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define ddCHash2(o,f,g,s) \ (((((unsigned)(ptruint)(f) + (unsigned)(ptruint)(o)) * DD_P1 + \ (unsigned)(ptruint)(g)) * DD_P2) >> (s)) #define ddCHash2_(o,f,g) \ (((((unsigned)(ptruint)(f) + (unsigned)(ptruint)(o)) * DD_P1 + \ (unsigned)(ptruint)(g)) * DD_P2)) #else #define ddCHash2(o,f,g,s) \ (((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) #define ddCHash2_(o,f,g) \ (((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2)) #endif /**Macro*********************************************************************** Synopsis [Clears the 4 least significant bits of a pointer.] Description [] SideEffects [none] SeeAlso [] ******************************************************************************/ #define cuddClean(p) ((DdNode *)((ptruint)(p) & ~0xf)) /**Macro*********************************************************************** Synopsis [Computes the minimum of two numbers.] Description [] SideEffects [none] SeeAlso [ddMax] ******************************************************************************/ #define ddMin(x,y) (((y) < (x)) ? (y) : (x)) /**Macro*********************************************************************** Synopsis [Computes the maximum of two numbers.] Description [] SideEffects [none] SeeAlso [ddMin] ******************************************************************************/ #define ddMax(x,y) (((y) > (x)) ? (y) : (x)) /**Macro*********************************************************************** Synopsis [Computes the absolute value of a number.] Description [] SideEffects [none] SeeAlso [] ******************************************************************************/ #define ddAbs(x) (((x)<0) ? -(x) : (x)) /**Macro*********************************************************************** Synopsis [Returns 1 if the absolute value of the difference of the two arguments x and y is less than e.] Description [] SideEffects [none] SeeAlso [] ******************************************************************************/ #define ddEqualVal(x,y,e) (ddAbs((x)-(y))<(e)) /**Macro*********************************************************************** Synopsis [Saturating increment operator.] Description [] SideEffects [none] SeeAlso [cuddSatDec] ******************************************************************************/ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define cuddSatInc(x) ((x)++) #else #define cuddSatInc(x) ((x) += (x) != (DdHalfWord)DD_MAXREF) #endif /**Macro*********************************************************************** Synopsis [Saturating decrement operator.] Description [] SideEffects [none] SeeAlso [cuddSatInc] ******************************************************************************/ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define cuddSatDec(x) ((x)--) #else #define cuddSatDec(x) ((x) -= (x) != (DdHalfWord)DD_MAXREF) #endif /**Macro*********************************************************************** Synopsis [Returns the constant 1 node.] Description [] SideEffects [none] SeeAlso [DD_ZERO DD_PLUS_INFINITY DD_MINUS_INFINITY] ******************************************************************************/ #define DD_ONE(dd) ((dd)->one) /**Macro*********************************************************************** Synopsis [Returns the arithmetic 0 constant node.] Description [Returns the arithmetic 0 constant node. This is different from the logical zero. The latter is obtained by Cudd_Not(DD_ONE(dd)).] SideEffects [none] SeeAlso [DD_ONE Cudd_Not DD_PLUS_INFINITY DD_MINUS_INFINITY] ******************************************************************************/ #define DD_ZERO(dd) ((dd)->zero) /**Macro*********************************************************************** Synopsis [Returns the plus infinity constant node.] Description [] SideEffects [none] SeeAlso [DD_ONE DD_ZERO DD_MINUS_INFINITY] ******************************************************************************/ #define DD_PLUS_INFINITY(dd) ((dd)->plusinfinity) /**Macro*********************************************************************** Synopsis [Returns the minus infinity constant node.] Description [] SideEffects [none] SeeAlso [DD_ONE DD_ZERO DD_PLUS_INFINITY] ******************************************************************************/ #define DD_MINUS_INFINITY(dd) ((dd)->minusinfinity) /**Macro*********************************************************************** Synopsis [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.] Description [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL. Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to DD_PLUS_INF_VAL. Normally this macro is a NOOP. However, if HAVE_IEEE_754 is not defined, it makes sure that a value does not get larger than infinity in absolute value, and once it gets to infinity, stays there. If the value overflows before this macro is applied, no recovery is possible.] SideEffects [none] SeeAlso [] ******************************************************************************/ #ifdef HAVE_IEEE_754 #define cuddAdjust(x) #else #define cuddAdjust(x) ((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x))) #endif /**Macro*********************************************************************** Synopsis [Extract the least significant digit of a double digit.] Description [Extract the least significant digit of a double digit. Used in the manipulation of arbitrary precision integers.] SideEffects [None] SeeAlso [DD_MSDIGIT] ******************************************************************************/ #define DD_LSDIGIT(x) ((x) & DD_APA_MASK) /**Macro*********************************************************************** Synopsis [Extract the most significant digit of a double digit.] Description [Extract the most significant digit of a double digit. Used in the manipulation of arbitrary precision integers.] SideEffects [None] SeeAlso [DD_LSDIGIT] ******************************************************************************/ #define DD_MSDIGIT(x) ((x) >> DD_APA_BITS) /**Macro*********************************************************************** Synopsis [Outputs a line of stats.] Description [Outputs a line of stats if DD_COUNT and DD_STATS are defined. Increments the number of recursive calls if DD_COUNT is defined.] SideEffects [None] SeeAlso [] ******************************************************************************/ #ifdef DD_COUNT #ifdef DD_STATS #define statLine(dd) dd->recursiveCalls++; \ if (dd->recursiveCalls == dd->nextSample) {(void) fprintf(dd->err, \ "@%.0f: %u nodes %u live %.0f dropped %.0f reclaimed\n", dd->recursiveCalls, \ dd->keys, dd->keys - dd->dead, dd->nodesDropped, dd->reclaimed); \ dd->nextSample += 250000;} #else #define statLine(dd) dd->recursiveCalls++; #endif #else #define statLine(dd) #endif /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Function prototypes */ /*---------------------------------------------------------------------------*/ extern DdNode * cuddAddExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * cuddAddUnivAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * cuddAddOrAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * cuddAddApplyRecur( DdManager * dd, DdNode * (*)(DdManager * , DdNode ** , DdNode **), DdNode * f, DdNode * g ); extern DdNode * cuddAddMonadicApplyRecur( DdManager * dd, DdNode * (*)(DdManager * , DdNode *), DdNode * f ); extern DdNode * cuddAddScalarInverseRecur( DdManager * dd, DdNode * f, DdNode * epsilon ); extern DdNode * cuddAddIteRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * cuddAddCmplRecur( DdManager * dd, DdNode * f ); extern DdNode * cuddAddNegateRecur( DdManager * dd, DdNode * f ); extern DdNode * cuddAddRoundOffRecur( DdManager * dd, DdNode * f, double trunc ); extern DdNode * cuddUnderApprox( DdManager * dd, DdNode * f, int numVars, int threshold, int safe, double quality ); extern DdNode * cuddRemapUnderApprox( DdManager * dd, DdNode * f, int numVars, int threshold, double quality ); extern DdNode * cuddBiasedUnderApprox( DdManager * dd, DdNode * f, DdNode * b, int numVars, int threshold, double quality1, double quality0 ); extern DdNode * cuddBddAndAbstractRecur( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube ); extern int cuddAnnealing( DdManager * table, int lower, int upper ); extern DdNode * cuddBddExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube ); extern DdNode * cuddBddXorExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube ); extern DdNode * cuddBddBooleanDiffRecur( DdManager * manager, DdNode * f, DdNode * var ); extern DdNode * cuddBddIteRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * cuddBddIntersectRecur( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * cuddBddAndRecur( DdManager * manager, DdNode * f, DdNode * g ); extern DdNode * cuddBddXorRecur( DdManager * manager, DdNode * f, DdNode * g ); extern DdNode * cuddBddTransfer( DdManager * ddS, DdManager * ddD, DdNode * f ); extern DdNode * cuddAddBddDoPattern( DdManager * dd, DdNode * f ); extern int cuddInitCache( DdManager * unique, unsigned int cacheSize, unsigned int maxCacheSize ); extern void cuddCacheInsert( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h, DdNode * data ); extern void cuddCacheInsert2( DdManager * table, DdNode * (*)(DdManager * , DdNode * , DdNode *), DdNode * f, DdNode * g, DdNode * data ); extern void cuddCacheInsert1( DdManager * table, DdNode * (*)(DdManager * , DdNode *), DdNode * f, DdNode * data ); extern DdNode * cuddCacheLookup( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * cuddCacheLookupZdd( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * cuddCacheLookup2( DdManager * table, DdNode * (*)(DdManager * , DdNode * , DdNode *), DdNode * f, DdNode * g ); extern DdNode * cuddCacheLookup1( DdManager * table, DdNode * (*)(DdManager * , DdNode *), DdNode * f ); extern DdNode * cuddCacheLookup2Zdd( DdManager * table, DdNode * (*)(DdManager * , DdNode * , DdNode *), DdNode * f, DdNode * g ); extern DdNode * cuddCacheLookup1Zdd( DdManager * table, DdNode * (*)(DdManager * , DdNode *), DdNode * f ); extern DdNode * cuddConstantLookup( DdManager * table, ptruint op, DdNode * f, DdNode * g, DdNode * h ); extern int cuddCacheProfile( DdManager * table, FILE * fp ); extern void cuddCacheResize( DdManager * table ); extern void cuddCacheFlush( DdManager * table ); extern int cuddComputeFloorLog2( unsigned int value ); extern int cuddHeapProfile( DdManager * dd ); extern void cuddPrintNode( DdNode * f, FILE * fp ); extern void cuddPrintVarGroups( DdManager * dd, MtrNode * root, int zdd, int silent ); extern DdNode * cuddBddClippingAnd( DdManager * dd, DdNode * f, DdNode * g, int maxDepth, int direction ); extern DdNode * cuddBddClippingAndAbstract( DdManager * dd, DdNode * f, DdNode * g, DdNode * cube, int maxDepth, int direction ); extern void cuddGetBranches( DdNode * g, DdNode ** g1, DdNode ** g0 ); extern int cuddCheckCube( DdManager * dd, DdNode * g ); extern DdNode * cuddCofactorRecur( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * cuddBddComposeRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * proj ); extern DdNode * cuddAddComposeRecur( DdManager * dd, DdNode * f, DdNode * g, DdNode * proj ); extern int cuddExact( DdManager * table, int lower, int upper ); extern DdNode * cuddBddConstrainRecur( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * cuddBddRestrictRecur( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * cuddBddNPAndRecur( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * cuddAddConstrainRecur( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * cuddAddRestrictRecur( DdManager * dd, DdNode * f, DdNode * c ); extern DdNode * cuddBddLICompaction( DdManager * dd, DdNode * f, DdNode * c ); extern int cuddGa( DdManager * table, int lower, int upper ); extern int cuddTreeSifting( DdManager * table, Cudd_ReorderingType method ); extern int cuddZddInitUniv( DdManager * zdd ); extern void cuddZddFreeUniv( DdManager * zdd ); extern void cuddSetInteract( DdManager * table, int x, int y ); extern int cuddTestInteract( DdManager * table, int x, int y ); extern int cuddInitInteract( DdManager * table ); extern DdLocalCache * cuddLocalCacheInit( DdManager * manager, unsigned int keySize, unsigned int cacheSize, unsigned int maxCacheSize ); extern void cuddLocalCacheQuit( DdLocalCache * cache ); extern void cuddLocalCacheInsert( DdLocalCache * cache, DdNodePtr * key, DdNode * value ); extern DdNode * cuddLocalCacheLookup( DdLocalCache * cache, DdNodePtr * key ); extern void cuddLocalCacheClearDead( DdManager * manager ); extern int cuddIsInDeathRow( DdManager * dd, DdNode * f ); extern int cuddTimesInDeathRow( DdManager * dd, DdNode * f ); extern void cuddLocalCacheClearAll( DdManager * manager ); #ifdef DD_CACHE_PROFILE extern int cuddLocalCacheProfile( DdLocalCache * cache ); #endif extern DdHashTable * cuddHashTableInit( DdManager * manager, unsigned int keySize, unsigned int initSize ); extern void cuddHashTableQuit( DdHashTable * hash ); extern int cuddHashTableInsert( DdHashTable * hash, DdNodePtr * key, DdNode * value, ptrint count ); extern DdNode * cuddHashTableLookup( DdHashTable * hash, DdNodePtr * key ); extern int cuddHashTableInsert1( DdHashTable * hash, DdNode * f, DdNode * value, ptrint count ); extern DdNode * cuddHashTableLookup1( DdHashTable * hash, DdNode * f ); extern int cuddHashTableInsert2( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * value, ptrint count ); extern DdNode * cuddHashTableLookup2( DdHashTable * hash, DdNode * f, DdNode * g ); extern int cuddHashTableInsert3( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * h, DdNode * value, ptrint count ); extern DdNode * cuddHashTableLookup3( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * h ); extern DdLevelQueue * cuddLevelQueueInit( int levels, int itemSize, int numBuckets ); extern void cuddLevelQueueQuit( DdLevelQueue * queue ); extern void * cuddLevelQueueEnqueue( DdLevelQueue * queue, void * key, int level ); extern void cuddLevelQueueDequeue( DdLevelQueue * queue, int level ); extern int cuddLinearAndSifting( DdManager * table, int lower, int upper ); extern int cuddLinearInPlace( DdManager * table, int x, int y ); extern void cuddUpdateInteractionMatrix( DdManager * table, int xindex, int yindex ); extern int cuddInitLinear( DdManager * table ); extern int cuddResizeLinear( DdManager * table ); extern DdNode * cuddBddLiteralSetIntersectionRecur( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * cuddCProjectionRecur( DdManager * dd, DdNode * R, DdNode * Y, DdNode * Ysupp ); extern DdNode * cuddBddClosestCube( DdManager * dd, DdNode * f, DdNode * g, CUDD_VALUE_TYPE bound ); extern void cuddReclaim( DdManager * table, DdNode * n ); extern void cuddReclaimZdd( DdManager * table, DdNode * n ); extern void cuddClearDeathRow( DdManager * table ); extern void cuddShrinkDeathRow( DdManager * table ); extern DdNode * cuddDynamicAllocNode( DdManager * table ); extern int cuddSifting( DdManager * table, int lower, int upper ); extern int cuddSwapping( DdManager * table, int lower, int upper, Cudd_ReorderingType heuristic ); extern int cuddNextHigh( DdManager * table, int x ); extern int cuddNextLow( DdManager * table, int x ); extern int cuddSwapInPlace( DdManager * table, int x, int y ); extern int cuddBddAlignToZdd( DdManager * table ); extern DdNode * cuddBddMakePrime( DdManager * dd, DdNode * cube, DdNode * f ); extern DdNode * cuddSolveEqnRecur( DdManager * bdd, DdNode * F, DdNode * Y, DdNode ** G, int n, int * yIndex, int i ); extern DdNode * cuddVerifySol( DdManager * bdd, DdNode * F, DdNode ** G, int * yIndex, int n ); #ifdef st__INCLUDED extern DdNode * cuddSplitSetRecur( DdManager * manager, st__table * mtable, int * varSeen, DdNode * p, double n, double max, int index ); #endif extern DdNode * cuddSubsetHeavyBranch( DdManager * dd, DdNode * f, int numVars, int threshold ); extern DdNode * cuddSubsetShortPaths( DdManager * dd, DdNode * f, int numVars, int threshold, int hardlimit ); extern int cuddSymmCheck( DdManager * table, int x, int y ); extern int cuddSymmSifting( DdManager * table, int lower, int upper ); extern int cuddSymmSiftingConv( DdManager * table, int lower, int upper ); extern DdNode * cuddAllocNode( DdManager * unique ); extern DdManager * cuddInitTable( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo ); extern void cuddFreeTable( DdManager * unique ); extern int cuddGarbageCollect( DdManager * unique, int clearCache ); extern DdNode * cuddZddGetNode( DdManager * zdd, int id, DdNode * T, DdNode * E ); extern DdNode * cuddZddGetNodeIVO( DdManager * dd, int index, DdNode * g, DdNode * h ); extern DdNode * cuddUniqueInter( DdManager * unique, int index, DdNode * T, DdNode * E ); extern DdNode * cuddUniqueInterIVO( DdManager * unique, int index, DdNode * T, DdNode * E ); extern DdNode * cuddUniqueInterZdd( DdManager * unique, int index, DdNode * T, DdNode * E ); extern DdNode * cuddUniqueConst( DdManager * unique, CUDD_VALUE_TYPE value ); extern void cuddRehash( DdManager * unique, int i ); extern void cuddShrinkSubtable( DdManager * unique, int i ); extern int cuddInsertSubtables( DdManager * unique, int n, int level ); extern int cuddDestroySubtables( DdManager * unique, int n ); extern int cuddResizeTableZdd( DdManager * unique, int index ); extern void cuddSlowTableGrowth( DdManager * unique ); extern int cuddP( DdManager * dd, DdNode * f ); #ifdef st__INCLUDED extern enum st__retval cuddStCountfree( char * key, char * value, char * arg ); extern int cuddCollectNodes( DdNode * f, st__table * visited ); #endif extern DdNodePtr * cuddNodeArray( DdNode * f, int * n ); extern int cuddWindowReorder( DdManager * table, int low, int high, Cudd_ReorderingType submethod ); extern DdNode * cuddZddProduct( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * cuddZddUnateProduct( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * cuddZddWeakDiv( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * cuddZddWeakDivF( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * cuddZddDivide( DdManager * dd, DdNode * f, DdNode * g ); extern DdNode * cuddZddDivideF( DdManager * dd, DdNode * f, DdNode * g ); extern int cuddZddGetCofactors3( DdManager * dd, DdNode * f, int v, DdNode ** f1, DdNode ** f0, DdNode ** fd ); extern int cuddZddGetCofactors2( DdManager * dd, DdNode * f, int v, DdNode ** f1, DdNode ** f0 ); extern DdNode * cuddZddComplement( DdManager * dd, DdNode * node ); extern int cuddZddGetPosVarIndex(DdManager * dd, int index ); extern int cuddZddGetNegVarIndex(DdManager * dd, int index ); extern int cuddZddGetPosVarLevel(DdManager * dd, int index ); extern int cuddZddGetNegVarLevel(DdManager * dd, int index ); extern int cuddZddTreeSifting( DdManager * table, Cudd_ReorderingType method ); extern DdNode * cuddZddIsop( DdManager * dd, DdNode * L, DdNode * U, DdNode ** zdd_I ); extern DdNode * cuddBddIsop( DdManager * dd, DdNode * L, DdNode * U ); extern DdNode * cuddMakeBddFromZddCover( DdManager * dd, DdNode * node ); extern int cuddZddLinearSifting( DdManager * table, int lower, int upper ); extern int cuddZddAlignToBdd( DdManager * table ); extern int cuddZddNextHigh( DdManager * table, int x ); extern int cuddZddNextLow( DdManager * table, int x ); extern int cuddZddUniqueCompare( int * ptr_x, int * ptr_y ); extern int cuddZddSwapInPlace( DdManager * table, int x, int y ); extern int cuddZddSwapping( DdManager * table, int lower, int upper, Cudd_ReorderingType heuristic ); extern int cuddZddSifting( DdManager * table, int lower, int upper ); extern DdNode * cuddZddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h ); extern DdNode * cuddZddUnion( DdManager * zdd, DdNode * P, DdNode * Q ); extern DdNode * cuddZddIntersect( DdManager * zdd, DdNode * P, DdNode * Q ); extern DdNode * cuddZddDiff( DdManager * zdd, DdNode * P, DdNode * Q ); extern DdNode * cuddZddChangeAux( DdManager * zdd, DdNode * P, DdNode * zvar ); extern DdNode * cuddZddSubset1( DdManager * dd, DdNode * P, int var ); extern DdNode * cuddZddSubset0( DdManager * dd, DdNode * P, int var ); extern DdNode * cuddZddChange( DdManager * dd, DdNode * P, int var ); extern int cuddZddSymmCheck( DdManager * table, int x, int y ); extern int cuddZddSymmSifting( DdManager * table, int lower, int upper ); extern int cuddZddSymmSiftingConv( DdManager * table, int lower, int upper ); extern int cuddZddP( DdManager * zdd, DdNode * f ); /**AutomaticEnd***************************************************************/ ABC_NAMESPACE_HEADER_END #endif /* _CUDDINT */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddInteract.c000066400000000000000000000322411300674244400242630ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddInteract.c] PackageName [cudd] Synopsis [Functions to manipulate the variable interaction matrix.] Description [Internal procedures included in this file:
      • cuddSetInteract()
      • cuddTestInteract()
      • cuddInitInteract()
      Static procedures included in this file:
      • ddSuppInteract()
      • ddClearLocal()
      • ddUpdateInteract()
      • ddClearGlobal()
      The interaction matrix tells whether two variables are both in the support of some function of the DD. The main use of the interaction matrix is in the in-place swapping. Indeed, if two variables do not interact, there is no arc connecting the two layers; therefore, the swap can be performed in constant time, without scanning the subtables. Another use of the interaction matrix is in the computation of the lower bounds for sifting. Finally, the interaction matrix can be used to speed up aggregation checks in symmetric and group sifting.

      The computation of the interaction matrix is done with a series of depth-first searches. The searches start from those nodes that have only external references. The matrix is stored as a packed array of bits; since it is symmetric, only the upper triangle is kept in memory. As a final remark, we note that there may be variables that do intercat, but that for a given variable order have no arc connecting their layers when they are adjacent.] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #if SIZEOF_LONG == 8 #define BPL 64 #define LOGBPL 6 #else #define BPL 32 #define LOGBPL 5 #endif /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.12 2004/08/13 18:04:49 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void ddSuppInteract (DdNode *f, int *support); static void ddClearLocal (DdNode *f); static void ddUpdateInteract (DdManager *table, int *support); static void ddClearGlobal (DdManager *table); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Set interaction matrix entries.] Description [Given a pair of variables 0 <= x < y < table->size, sets the corresponding bit of the interaction matrix to 1.] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddSetInteract( DdManager * table, int x, int y) { int posn, word, bit; #ifdef DD_DEBUG assert(x < y); assert(y < table->size); assert(x >= 0); #endif posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; word = posn >> LOGBPL; bit = posn & (BPL-1); table->interact[word] |= 1L << bit; } /* end of cuddSetInteract */ /**Function******************************************************************** Synopsis [Test interaction matrix entries.] Description [Given a pair of variables 0 <= x < y < table->size, tests whether the corresponding bit of the interaction matrix is 1. Returns the value of the bit.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddTestInteract( DdManager * table, int x, int y) { int posn, word, bit, result; if (x > y) { int tmp = x; x = y; y = tmp; } #ifdef DD_DEBUG assert(x < y); assert(y < table->size); assert(x >= 0); #endif posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; word = posn >> LOGBPL; bit = posn & (BPL-1); result = (table->interact[word] >> bit) & 1L; return(result); } /* end of cuddTestInteract */ /**Function******************************************************************** Synopsis [Initializes the interaction matrix.] Description [Initializes the interaction matrix. The interaction matrix is implemented as a bit vector storing the upper triangle of the symmetric interaction matrix. The bit vector is kept in an array of long integers. The computation is based on a series of depth-first searches, one for each root of the DAG. Two flags are needed: The local visited flag uses the LSB of the then pointer. The global visited flag uses the LSB of the next pointer. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddInitInteract( DdManager * table) { int i,j,k; ABC_UINT64_T words; long *interact; int *support; DdNode *f; DdNode *sentinel = &(table->sentinel); DdNodePtr *nodelist; int slots; int n = table->size; words = ((n * (n-1)) >> (1 + LOGBPL)) + 1; table->interact = interact = ABC_ALLOC(long,(unsigned)words); if (interact == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < words; i++) { interact[i] = 0; } support = ABC_ALLOC(int,n); if (support == NULL) { table->errorCode = CUDD_MEMORY_OUT; ABC_FREE(interact); return(0); } for (i = 0; i < n; i++) { nodelist = table->subtables[i].nodelist; slots = table->subtables[i].slots; for (j = 0; j < slots; j++) { f = nodelist[j]; while (f != sentinel) { /* A node is a root of the DAG if it cannot be ** reached by nodes above it. If a node was never ** reached during the previous depth-first searches, ** then it is a root, and we start a new depth-first ** search from it. */ if (!Cudd_IsComplement(f->next)) { for (k = 0; k < n; k++) { support[k] = 0; } ddSuppInteract(f,support); ddClearLocal(f); ddUpdateInteract(table,support); } f = Cudd_Regular(f->next); } } } ddClearGlobal(table); ABC_FREE(support); return(1); } /* end of cuddInitInteract */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Find the support of f.] Description [Performs a DFS from f. Uses the LSB of the then pointer as visited flag.] SideEffects [Accumulates in support the variables on which f depends.] SeeAlso [] ******************************************************************************/ static void ddSuppInteract( DdNode * f, int * support) { if (cuddIsConstant(f) || Cudd_IsComplement(cuddT(f))) { return; } support[f->index] = 1; ddSuppInteract(cuddT(f),support); ddSuppInteract(Cudd_Regular(cuddE(f)),support); /* mark as visited */ cuddT(f) = Cudd_Complement(cuddT(f)); f->next = Cudd_Complement(f->next); return; } /* end of ddSuppInteract */ /**Function******************************************************************** Synopsis [Performs a DFS from f, clearing the LSB of the then pointers.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void ddClearLocal( DdNode * f) { if (cuddIsConstant(f) || !Cudd_IsComplement(cuddT(f))) { return; } /* clear visited flag */ cuddT(f) = Cudd_Regular(cuddT(f)); ddClearLocal(cuddT(f)); ddClearLocal(Cudd_Regular(cuddE(f))); return; } /* end of ddClearLocal */ /**Function******************************************************************** Synopsis [Marks as interacting all pairs of variables that appear in support.] Description [If support[i] == support[j] == 1, sets the (i,j) entry of the interaction matrix to 1.] SideEffects [None] SeeAlso [] ******************************************************************************/ static void ddUpdateInteract( DdManager * table, int * support) { int i,j; int n = table->size; for (i = 0; i < n-1; i++) { if (support[i] == 1) { for (j = i+1; j < n; j++) { if (support[j] == 1) { cuddSetInteract(table,i,j); } } } } } /* end of ddUpdateInteract */ /**Function******************************************************************** Synopsis [Scans the DD and clears the LSB of the next pointers.] Description [The LSB of the next pointers are used as markers to tell whether a node was reached by at least one DFS. Once the interaction matrix is built, these flags are reset.] SideEffects [None] SeeAlso [] ******************************************************************************/ static void ddClearGlobal( DdManager * table) { int i,j; DdNode *f; DdNode *sentinel = &(table->sentinel); DdNodePtr *nodelist; int slots; for (i = 0; i < table->size; i++) { nodelist = table->subtables[i].nodelist; slots = table->subtables[i].slots; for (j = 0; j < slots; j++) { f = nodelist[j]; while (f != sentinel) { f->next = Cudd_Regular(f->next); f = f->next; } } } } /* end of ddClearGlobal */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddLCache.c000066400000000000000000001223771300674244400236430ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddLCache.c] PackageName [cudd] Synopsis [Functions for local caches.] Description [Internal procedures included in this module:

      • cuddLocalCacheInit()
      • cuddLocalCacheQuit()
      • cuddLocalCacheInsert()
      • cuddLocalCacheLookup()
      • cuddLocalCacheClearDead()
      • cuddLocalCacheClearAll()
      • cuddLocalCacheProfile()
      • cuddHashTableInit()
      • cuddHashTableQuit()
      • cuddHashTableInsert()
      • cuddHashTableLookup()
      • cuddHashTableInsert2()
      • cuddHashTableLookup2()
      • cuddHashTableInsert3()
      • cuddHashTableLookup3()
      Static procedures included in this module:
      • cuddLocalCacheResize()
      • ddLCHash()
      • cuddLocalCacheAddToList()
      • cuddLocalCacheRemoveFromList()
      • cuddHashTableResize()
      • cuddHashTableAlloc()
      ] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DD_MAX_HASHTABLE_DENSITY 2 /* tells when to resize a table */ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.24 2009/03/08 02:49:02 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**Macro*********************************************************************** Synopsis [Computes hash function for keys of two operands.] Description [] SideEffects [None] SeeAlso [ddLCHash3 ddLCHash] ******************************************************************************/ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define ddLCHash2(f,g,shift) \ ((((unsigned)(ptruint)(f) * DD_P1 + \ (unsigned)(ptruint)(g)) * DD_P2) >> (shift)) #else #define ddLCHash2(f,g,shift) \ ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift)) #endif /**Macro*********************************************************************** Synopsis [Computes hash function for keys of three operands.] Description [] SideEffects [None] SeeAlso [ddLCHash2 ddLCHash] ******************************************************************************/ #define ddLCHash3(f,g,h,shift) ddCHash2(f,g,h,shift) /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void cuddLocalCacheResize (DdLocalCache *cache); DD_INLINE static unsigned int ddLCHash (DdNodePtr *key, unsigned int keysize, int shift); static void cuddLocalCacheAddToList (DdLocalCache *cache); static void cuddLocalCacheRemoveFromList (DdLocalCache *cache); static int cuddHashTableResize (DdHashTable *hash); DD_INLINE static DdHashItem * cuddHashTableAlloc (DdHashTable *hash); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Initializes a local computed table.] Description [Initializes a computed table. Returns a pointer the the new local cache in case of success; NULL otherwise.] SideEffects [None] SeeAlso [cuddInitCache] ******************************************************************************/ DdLocalCache * cuddLocalCacheInit( DdManager * manager /* manager */, unsigned int keySize /* size of the key (number of operands) */, unsigned int cacheSize /* Initial size of the cache */, unsigned int maxCacheSize /* Size of the cache beyond which no resizing occurs */) { DdLocalCache *cache; int logSize; cache = ABC_ALLOC(DdLocalCache,1); if (cache == NULL) { manager->errorCode = CUDD_MEMORY_OUT; return(NULL); } cache->manager = manager; cache->keysize = keySize; cache->itemsize = (keySize + 1) * sizeof(DdNode *); #ifdef DD_CACHE_PROFILE cache->itemsize += sizeof(ptrint); #endif logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2)); cacheSize = 1 << logSize; cache->item = (DdLocalCacheItem *) ABC_ALLOC(char, cacheSize * cache->itemsize); if (cache->item == NULL) { manager->errorCode = CUDD_MEMORY_OUT; ABC_FREE(cache); return(NULL); } cache->slots = cacheSize; cache->shift = sizeof(int) * 8 - logSize; cache->maxslots = ddMin(maxCacheSize,manager->slots); cache->minHit = manager->minHit; /* Initialize to avoid division by 0 and immediate resizing. */ cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1); cache->hits = 0; manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache); /* Initialize the cache. */ memset(cache->item, 0, cacheSize * cache->itemsize); /* Add to manager's list of local caches for GC. */ cuddLocalCacheAddToList(cache); return(cache); } /* end of cuddLocalCacheInit */ /**Function******************************************************************** Synopsis [Shuts down a local computed table.] Description [Initializes the computed table. It is called by Cudd_Init. Returns a pointer the the new local cache in case of success; NULL otherwise.] SideEffects [None] SeeAlso [cuddLocalCacheInit] ******************************************************************************/ void cuddLocalCacheQuit( DdLocalCache * cache /* cache to be shut down */) { cache->manager->memused -= cache->slots * cache->itemsize + sizeof(DdLocalCache); cuddLocalCacheRemoveFromList(cache); ABC_FREE(cache->item); ABC_FREE(cache); return; } /* end of cuddLocalCacheQuit */ /**Function******************************************************************** Synopsis [Inserts a result in a local cache.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddLocalCacheInsert( DdLocalCache * cache, DdNodePtr * key, DdNode * value) { unsigned int posn; DdLocalCacheItem *entry; posn = ddLCHash(key,cache->keysize,cache->shift); entry = (DdLocalCacheItem *) ((char *) cache->item + posn * cache->itemsize); memcpy(entry->key,key,cache->keysize * sizeof(DdNode *)); entry->value = value; #ifdef DD_CACHE_PROFILE entry->count++; #endif } /* end of cuddLocalCacheInsert */ /**Function******************************************************************** Synopsis [Looks up in a local cache.] Description [Looks up in a local cache. Returns the result if found; it returns NULL if no result is found.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddLocalCacheLookup( DdLocalCache * cache, DdNodePtr * key) { unsigned int posn; DdLocalCacheItem *entry; DdNode *value; cache->lookUps++; posn = ddLCHash(key,cache->keysize,cache->shift); entry = (DdLocalCacheItem *) ((char *) cache->item + posn * cache->itemsize); if (entry->value != NULL && memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) { cache->hits++; value = Cudd_Regular(entry->value); if (value->ref == 0) { cuddReclaim(cache->manager,value); } return(entry->value); } /* Cache miss: decide whether to resize */ if (cache->slots < cache->maxslots && cache->hits > cache->lookUps * cache->minHit) { cuddLocalCacheResize(cache); } return(NULL); } /* end of cuddLocalCacheLookup */ /**Function******************************************************************** Synopsis [Clears the dead entries of the local caches of a manager.] Description [Clears the dead entries of the local caches of a manager. Used during garbage collection.] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddLocalCacheClearDead( DdManager * manager) { DdLocalCache *cache = manager->localCaches; unsigned int keysize; unsigned int itemsize; unsigned int slots; DdLocalCacheItem *item; DdNodePtr *key; unsigned int i, j; while (cache != NULL) { keysize = cache->keysize; itemsize = cache->itemsize; slots = cache->slots; item = cache->item; for (i = 0; i < slots; i++) { if (item->value != NULL) { if (Cudd_Regular(item->value)->ref == 0) { item->value = NULL; } else { key = item->key; for (j = 0; j < keysize; j++) { if (Cudd_Regular(key[j])->ref == 0) { item->value = NULL; break; } } } } item = (DdLocalCacheItem *) ((char *) item + itemsize); } cache = cache->next; } return; } /* end of cuddLocalCacheClearDead */ /**Function******************************************************************** Synopsis [Clears the local caches of a manager.] Description [Clears the local caches of a manager. Used before reordering.] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddLocalCacheClearAll( DdManager * manager) { DdLocalCache *cache = manager->localCaches; while (cache != NULL) { memset(cache->item, 0, cache->slots * cache->itemsize); cache = cache->next; } return; } /* end of cuddLocalCacheClearAll */ #ifdef DD_CACHE_PROFILE #define DD_HYSTO_BINS 8 /**Function******************************************************************** Synopsis [Computes and prints a profile of a local cache usage.] Description [Computes and prints a profile of a local cache usage. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddLocalCacheProfile( DdLocalCache * cache) { double count, mean, meansq, stddev, expected; long max, min; int imax, imin; int i, retval, slots; long *hystogram; int nbins = DD_HYSTO_BINS; int bin; long thiscount; double totalcount; int nzeroes; DdLocalCacheItem *entry; FILE *fp = cache->manager->out; slots = cache->slots; meansq = mean = expected = 0.0; max = min = (long) cache->item[0].count; imax = imin = nzeroes = 0; totalcount = 0.0; hystogram = ABC_ALLOC(long, nbins); if (hystogram == NULL) { return(0); } for (i = 0; i < nbins; i++) { hystogram[i] = 0; } for (i = 0; i < slots; i++) { entry = (DdLocalCacheItem *) ((char *) cache->item + i * cache->itemsize); thiscount = (long) entry->count; if (thiscount > max) { max = thiscount; imax = i; } if (thiscount < min) { min = thiscount; imin = i; } if (thiscount == 0) { nzeroes++; } count = (double) thiscount; mean += count; meansq += count * count; totalcount += count; expected += count * (double) i; bin = (i * nbins) / slots; hystogram[bin] += thiscount; } mean /= (double) slots; meansq /= (double) slots; stddev = sqrt(meansq - mean*mean); retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean); if (retval == EOF) return(0); retval = fprintf(fp,"standard deviation = %g\n", stddev); if (retval == EOF) return(0); retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); if (retval == EOF) return(0); retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); if (retval == EOF) return(0); retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes); if (retval == EOF) return(0); if (totalcount) { expected /= totalcount; retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); if (retval == EOF) return(0); retval = fprintf(fp," (expected bin value = %g)\n# ", expected); if (retval == EOF) return(0); for (i = nbins - 1; i>=0; i--) { retval = fprintf(fp,"%ld ", hystogram[i]); if (retval == EOF) return(0); } retval = fprintf(fp,"\n"); if (retval == EOF) return(0); } ABC_FREE(hystogram); return(1); } /* end of cuddLocalCacheProfile */ #endif /**Function******************************************************************** Synopsis [Initializes a hash table.] Description [Initializes a hash table. Returns a pointer to the new table if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddHashTableQuit] ******************************************************************************/ DdHashTable * cuddHashTableInit( DdManager * manager, unsigned int keySize, unsigned int initSize) { DdHashTable *hash; int logSize; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif hash = ABC_ALLOC(DdHashTable, 1); if (hash == NULL) { manager->errorCode = CUDD_MEMORY_OUT; return(NULL); } hash->keysize = keySize; hash->manager = manager; hash->memoryList = NULL; hash->nextFree = NULL; hash->itemsize = (keySize + 1) * sizeof(DdNode *) + sizeof(ptrint) + sizeof(DdHashItem *); /* We have to guarantee that the shift be < 32. */ if (initSize < 2) initSize = 2; logSize = cuddComputeFloorLog2(initSize); hash->numBuckets = 1 << logSize; hash->shift = sizeof(int) * 8 - logSize; hash->bucket = ABC_ALLOC(DdHashItem *, hash->numBuckets); if (hash->bucket == NULL) { manager->errorCode = CUDD_MEMORY_OUT; ABC_FREE(hash); return(NULL); } memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *)); hash->size = 0; hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY; #ifdef __osf__ #pragma pointer_size restore #endif return(hash); } /* end of cuddHashTableInit */ /**Function******************************************************************** Synopsis [Shuts down a hash table.] Description [Shuts down a hash table, dereferencing all the values.] SideEffects [None] SeeAlso [cuddHashTableInit] ******************************************************************************/ void cuddHashTableQuit( DdHashTable * hash) { #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif unsigned int i; DdManager *dd = hash->manager; DdHashItem *bucket; DdHashItem **memlist, **nextmem; unsigned int numBuckets = hash->numBuckets; for (i = 0; i < numBuckets; i++) { bucket = hash->bucket[i]; while (bucket != NULL) { Cudd_RecursiveDeref(dd, bucket->value); bucket = bucket->next; } } memlist = hash->memoryList; while (memlist != NULL) { nextmem = (DdHashItem **) memlist[0]; ABC_FREE(memlist); memlist = nextmem; } ABC_FREE(hash->bucket); ABC_FREE(hash); #ifdef __osf__ #pragma pointer_size restore #endif return; } /* end of cuddHashTableQuit */ /**Function******************************************************************** Synopsis [Inserts an item in a hash table.] Description [Inserts an item in a hash table when the key has more than three pointers. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3 cuddHashTableLookup] ******************************************************************************/ int cuddHashTableInsert( DdHashTable * hash, DdNodePtr * key, DdNode * value, ptrint count) { int result; unsigned int posn; DdHashItem *item; unsigned int i; #ifdef DD_DEBUG assert(hash->keysize > 3); #endif if (hash->size > hash->maxsize) { result = cuddHashTableResize(hash); if (result == 0) return(0); } item = cuddHashTableAlloc(hash); if (item == NULL) return(0); hash->size++; item->value = value; cuddRef(value); item->count = count; for (i = 0; i < hash->keysize; i++) { item->key[i] = key[i]; } posn = ddLCHash(key,hash->keysize,hash->shift); item->next = hash->bucket[posn]; hash->bucket[posn] = item; return(1); } /* end of cuddHashTableInsert */ /**Function******************************************************************** Synopsis [Looks up a key in a hash table.] Description [Looks up a key consisting of more than three pointers in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.] SideEffects [None] SeeAlso [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3 cuddHashTableInsert] ******************************************************************************/ DdNode * cuddHashTableLookup( DdHashTable * hash, DdNodePtr * key) { unsigned int posn; DdHashItem *item, *prev; unsigned int i, keysize; #ifdef DD_DEBUG assert(hash->keysize > 3); #endif posn = ddLCHash(key,hash->keysize,hash->shift); item = hash->bucket[posn]; prev = NULL; keysize = hash->keysize; while (item != NULL) { DdNodePtr *key2 = item->key; int equal = 1; for (i = 0; i < keysize; i++) { if (key[i] != key2[i]) { equal = 0; break; } } if (equal) { DdNode *value = item->value; cuddSatDec(item->count); if (item->count == 0) { cuddDeref(value); if (prev == NULL) { hash->bucket[posn] = item->next; } else { prev->next = item->next; } item->next = hash->nextFree; hash->nextFree = item; hash->size--; } return(value); } prev = item; item = item->next; } return(NULL); } /* end of cuddHashTableLookup */ /**Function******************************************************************** Synopsis [Inserts an item in a hash table.] Description [Inserts an item in a hash table when the key is one pointer. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3 cuddHashTableLookup1] ******************************************************************************/ int cuddHashTableInsert1( DdHashTable * hash, DdNode * f, DdNode * value, ptrint count) { int result; unsigned int posn; DdHashItem *item; #ifdef DD_DEBUG assert(hash->keysize == 1); #endif if (hash->size > hash->maxsize) { result = cuddHashTableResize(hash); if (result == 0) return(0); } item = cuddHashTableAlloc(hash); if (item == NULL) return(0); hash->size++; item->value = value; cuddRef(value); item->count = count; item->key[0] = f; posn = ddLCHash2(cuddF2L(f),cuddF2L(f),hash->shift); item->next = hash->bucket[posn]; hash->bucket[posn] = item; return(1); } /* end of cuddHashTableInsert1 */ /**Function******************************************************************** Synopsis [Looks up a key consisting of one pointer in a hash table.] Description [Looks up a key consisting of one pointer in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.] SideEffects [None] SeeAlso [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3 cuddHashTableInsert1] ******************************************************************************/ DdNode * cuddHashTableLookup1( DdHashTable * hash, DdNode * f) { unsigned int posn; DdHashItem *item, *prev; #ifdef DD_DEBUG assert(hash->keysize == 1); #endif posn = ddLCHash2(cuddF2L(f),cuddF2L(f),hash->shift); item = hash->bucket[posn]; prev = NULL; while (item != NULL) { DdNodePtr *key = item->key; if (f == key[0]) { DdNode *value = item->value; cuddSatDec(item->count); if (item->count == 0) { cuddDeref(value); if (prev == NULL) { hash->bucket[posn] = item->next; } else { prev->next = item->next; } item->next = hash->nextFree; hash->nextFree = item; hash->size--; } return(value); } prev = item; item = item->next; } return(NULL); } /* end of cuddHashTableLookup1 */ /**Function******************************************************************** Synopsis [Inserts an item in a hash table.] Description [Inserts an item in a hash table when the key is composed of two pointers. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3 cuddHashTableLookup2] ******************************************************************************/ int cuddHashTableInsert2( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * value, ptrint count) { int result; unsigned int posn; DdHashItem *item; #ifdef DD_DEBUG assert(hash->keysize == 2); #endif if (hash->size > hash->maxsize) { result = cuddHashTableResize(hash); if (result == 0) return(0); } item = cuddHashTableAlloc(hash); if (item == NULL) return(0); hash->size++; item->value = value; cuddRef(value); item->count = count; item->key[0] = f; item->key[1] = g; posn = ddLCHash2(cuddF2L(f),cuddF2L(g),hash->shift); item->next = hash->bucket[posn]; hash->bucket[posn] = item; return(1); } /* end of cuddHashTableInsert2 */ /**Function******************************************************************** Synopsis [Looks up a key consisting of two pointers in a hash table.] Description [Looks up a key consisting of two pointer in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.] SideEffects [None] SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3 cuddHashTableInsert2] ******************************************************************************/ DdNode * cuddHashTableLookup2( DdHashTable * hash, DdNode * f, DdNode * g) { unsigned int posn; DdHashItem *item, *prev; #ifdef DD_DEBUG assert(hash->keysize == 2); #endif posn = ddLCHash2(cuddF2L(f),cuddF2L(g),hash->shift); item = hash->bucket[posn]; prev = NULL; while (item != NULL) { DdNodePtr *key = item->key; if ((f == key[0]) && (g == key[1])) { DdNode *value = item->value; cuddSatDec(item->count); if (item->count == 0) { cuddDeref(value); if (prev == NULL) { hash->bucket[posn] = item->next; } else { prev->next = item->next; } item->next = hash->nextFree; hash->nextFree = item; hash->size--; } return(value); } prev = item; item = item->next; } return(NULL); } /* end of cuddHashTableLookup2 */ /**Function******************************************************************** Synopsis [Inserts an item in a hash table.] Description [Inserts an item in a hash table when the key is composed of three pointers. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableLookup3] ******************************************************************************/ int cuddHashTableInsert3( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * h, DdNode * value, ptrint count) { int result; unsigned int posn; DdHashItem *item; #ifdef DD_DEBUG assert(hash->keysize == 3); #endif if (hash->size > hash->maxsize) { result = cuddHashTableResize(hash); if (result == 0) return(0); } item = cuddHashTableAlloc(hash); if (item == NULL) return(0); hash->size++; item->value = value; cuddRef(value); item->count = count; item->key[0] = f; item->key[1] = g; item->key[2] = h; posn = ddLCHash3(cuddF2L(f),cuddF2L(g),cuddF2L(h),hash->shift); item->next = hash->bucket[posn]; hash->bucket[posn] = item; return(1); } /* end of cuddHashTableInsert3 */ /**Function******************************************************************** Synopsis [Looks up a key consisting of three pointers in a hash table.] Description [Looks up a key consisting of three pointers in a hash table. Returns the value associated to the key if there is an entry for the given key in the table; NULL otherwise. If the entry is present, its reference counter is decremented if not saturated. If the counter reaches 0, the value of the entry is dereferenced, and the entry is returned to the free list.] SideEffects [None] SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableInsert3] ******************************************************************************/ DdNode * cuddHashTableLookup3( DdHashTable * hash, DdNode * f, DdNode * g, DdNode * h) { unsigned int posn; DdHashItem *item, *prev; #ifdef DD_DEBUG assert(hash->keysize == 3); #endif posn = ddLCHash3(cuddF2L(f),cuddF2L(g),cuddF2L(h),hash->shift); item = hash->bucket[posn]; prev = NULL; while (item != NULL) { DdNodePtr *key = item->key; if ((f == key[0]) && (g == key[1]) && (h == key[2])) { DdNode *value = item->value; cuddSatDec(item->count); if (item->count == 0) { cuddDeref(value); if (prev == NULL) { hash->bucket[posn] = item->next; } else { prev->next = item->next; } item->next = hash->nextFree; hash->nextFree = item; hash->size--; } return(value); } prev = item; item = item->next; } return(NULL); } /* end of cuddHashTableLookup3 */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Resizes a local cache.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void cuddLocalCacheResize( DdLocalCache * cache) { DdLocalCacheItem *item, *olditem, *entry, *old; int i, shift; unsigned int posn; unsigned int slots, oldslots; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; olditem = cache->item; oldslots = cache->slots; slots = cache->slots = oldslots << 1; #ifdef DD_VERBOSE (void) fprintf(cache->manager->err, "Resizing local cache from %d to %d entries\n", oldslots, slots); (void) fprintf(cache->manager->err, "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n", cache->hits, cache->lookUps, cache->hits / cache->lookUps); #endif saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; cache->item = item = (DdLocalCacheItem *) ABC_ALLOC(char, slots * cache->itemsize); MMoutOfMemory = saveHandler; /* If we fail to allocate the new table we just give up. */ if (item == NULL) { #ifdef DD_VERBOSE (void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n"); #endif cache->slots = oldslots; cache->item = olditem; /* Do not try to resize again. */ cache->maxslots = oldslots - 1; return; } shift = --(cache->shift); cache->manager->memused += (slots - oldslots) * cache->itemsize; /* Clear new cache. */ memset(item, 0, slots * cache->itemsize); /* Copy from old cache to new one. */ for (i = 0; (unsigned) i < oldslots; i++) { old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize); if (old->value != NULL) { posn = ddLCHash(old->key,cache->keysize,shift); entry = (DdLocalCacheItem *) ((char *) item + posn * cache->itemsize); memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *)); entry->value = old->value; } } ABC_FREE(olditem); /* Reinitialize measurements so as to avoid division by 0 and ** immediate resizing. */ cache->lookUps = (double) (int) (slots * cache->minHit + 1); cache->hits = 0; } /* end of cuddLocalCacheResize */ /**Function******************************************************************** Synopsis [Computes the hash value for a local cache.] Description [Computes the hash value for a local cache. Returns the bucket index.] SideEffects [None] SeeAlso [] ******************************************************************************/ DD_INLINE static unsigned int ddLCHash( DdNodePtr * key, unsigned int keysize, int shift) { unsigned int val = (unsigned int) (ptrint) key[0] * DD_P2; unsigned int i; for (i = 1; i < keysize; i++) { val = val * DD_P1 + (int) (ptrint) key[i]; } return(val >> shift); } /* end of ddLCHash */ /**Function******************************************************************** Synopsis [Inserts a local cache in the manager list.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void cuddLocalCacheAddToList( DdLocalCache * cache) { DdManager *manager = cache->manager; cache->next = manager->localCaches; manager->localCaches = cache; return; } /* end of cuddLocalCacheAddToList */ /**Function******************************************************************** Synopsis [Removes a local cache from the manager list.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void cuddLocalCacheRemoveFromList( DdLocalCache * cache) { DdManager *manager = cache->manager; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif DdLocalCache **prevCache, *nextCache; #ifdef __osf__ #pragma pointer_size restore #endif prevCache = &(manager->localCaches); nextCache = manager->localCaches; while (nextCache != NULL) { if (nextCache == cache) { *prevCache = nextCache->next; return; } prevCache = &(nextCache->next); nextCache = nextCache->next; } return; /* should never get here */ } /* end of cuddLocalCacheRemoveFromList */ /**Function******************************************************************** Synopsis [Resizes a hash table.] Description [Resizes a hash table. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddHashTableInsert] ******************************************************************************/ static int cuddHashTableResize( DdHashTable * hash) { int j; unsigned int posn; DdHashItem *item; DdHashItem *next; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif DdNode **key; int numBuckets; DdHashItem **buckets; DdHashItem **oldBuckets = hash->bucket; #ifdef __osf__ #pragma pointer_size restore #endif int shift; int oldNumBuckets = hash->numBuckets; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; /* Compute the new size of the table. */ numBuckets = oldNumBuckets << 1; saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif buckets = ABC_ALLOC(DdHashItem *, numBuckets); MMoutOfMemory = saveHandler; if (buckets == NULL) { hash->maxsize <<= 1; return(1); } hash->bucket = buckets; hash->numBuckets = numBuckets; shift = --(hash->shift); hash->maxsize <<= 1; memset(buckets, 0, numBuckets * sizeof(DdHashItem *)); #ifdef __osf__ #pragma pointer_size restore #endif if (hash->keysize == 1) { for (j = 0; j < oldNumBuckets; j++) { item = oldBuckets[j]; while (item != NULL) { next = item->next; key = item->key; posn = ddLCHash2(cuddF2L(key[0]), cuddF2L(key[0]), shift); item->next = buckets[posn]; buckets[posn] = item; item = next; } } } else if (hash->keysize == 2) { for (j = 0; j < oldNumBuckets; j++) { item = oldBuckets[j]; while (item != NULL) { next = item->next; key = item->key; posn = ddLCHash2(cuddF2L(key[0]), cuddF2L(key[1]), shift); item->next = buckets[posn]; buckets[posn] = item; item = next; } } } else if (hash->keysize == 3) { for (j = 0; j < oldNumBuckets; j++) { item = oldBuckets[j]; while (item != NULL) { next = item->next; key = item->key; posn = ddLCHash3(cuddF2L(key[0]), cuddF2L(key[1]), cuddF2L(key[2]), shift); item->next = buckets[posn]; buckets[posn] = item; item = next; } } } else { for (j = 0; j < oldNumBuckets; j++) { item = oldBuckets[j]; while (item != NULL) { next = item->next; posn = ddLCHash(item->key, hash->keysize, shift); item->next = buckets[posn]; buckets[posn] = item; item = next; } } } ABC_FREE(oldBuckets); return(1); } /* end of cuddHashTableResize */ /**Function******************************************************************** Synopsis [Fast storage allocation for items in a hash table.] Description [Fast storage allocation for items in a hash table. The first 4 bytes of a chunk contain a pointer to the next block; the rest contains DD_MEM_CHUNK spaces for hash items. Returns a pointer to a new item if successful; NULL is memory is full.] SideEffects [None] SeeAlso [cuddAllocNode cuddDynamicAllocNode] ******************************************************************************/ DD_INLINE static DdHashItem * cuddHashTableAlloc( DdHashTable * hash) { int i; unsigned int itemsize = hash->itemsize; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif DdHashItem **mem, *thisOne, *next, *item; if (hash->nextFree == NULL) { saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; mem = (DdHashItem **) ABC_ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); MMoutOfMemory = saveHandler; #ifdef __osf__ #pragma pointer_size restore #endif if (mem == NULL) { if (hash->manager->stash != NULL) { ABC_FREE(hash->manager->stash); hash->manager->stash = NULL; /* Inhibit resizing of tables. */ hash->manager->maxCacheHard = hash->manager->cacheSlots - 1; hash->manager->cacheSlack = - (int) (hash->manager->cacheSlots + 1); for (i = 0; i < hash->manager->size; i++) { hash->manager->subtables[i].maxKeys <<= 2; } hash->manager->gcFrac = 0.2; hash->manager->minDead = (unsigned) (0.2 * (double) hash->manager->slots); #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif mem = (DdHashItem **) ABC_ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); #ifdef __osf__ #pragma pointer_size restore #endif } if (mem == NULL) { (*MMoutOfMemory)((long)((DD_MEM_CHUNK + 1) * itemsize)); hash->manager->errorCode = CUDD_MEMORY_OUT; return(NULL); } } mem[0] = (DdHashItem *) hash->memoryList; hash->memoryList = mem; thisOne = (DdHashItem *) ((char *) mem + itemsize); hash->nextFree = thisOne; for (i = 1; i < DD_MEM_CHUNK; i++) { next = (DdHashItem *) ((char *) thisOne + itemsize); thisOne->next = next; thisOne = next; } thisOne->next = NULL; } item = hash->nextFree; hash->nextFree = item->next; return(item); } /* end of cuddHashTableAlloc */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddLevelQ.c000066400000000000000000000420451300674244400237050ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddLevelQ.c] PackageName [cudd] Synopsis [Procedure to manage level queues.] Description [The functions in this file allow an application to easily manipulate a queue where nodes are prioritized by level. The emphasis is on efficiency. Therefore, the queue items can have variable size. If the application does not need to attach information to the nodes, it can declare the queue items to be of type DdQueueItem. Otherwise, it can declare them to be of a structure type such that the first three fields are data pointers. The third pointer points to the node. The first two pointers are used by the level queue functions. The remaining fields are initialized to 0 when a new item is created, and are then left to the exclusive use of the application. On the DEC Alphas the three pointers must be 32-bit pointers when CUDD is compiled with 32-bit pointers. The level queue functions make sure that each node appears at most once in the queue. They do so by keeping a hash table where the node is used as key. Queue items are recycled via a free list for efficiency. Internal procedures provided by this module:
      • cuddLevelQueueInit()
      • cuddLevelQueueQuit()
      • cuddLevelQueueEnqueue()
      • cuddLevelQueueDequeue()
      Static procedures included in this module:
      • hashLookup()
      • hashInsert()
      • hashDelete()
      • hashResize()
      ] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.13 2009/03/08 02:49:02 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**Macro*********************************************************************** Synopsis [Hash function for the table of a level queue.] Description [Hash function for the table of a level queue.] SideEffects [None] SeeAlso [hashInsert hashLookup hashDelete] ******************************************************************************/ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define lqHash(key,shift) \ (((unsigned)(ptruint)(key) * DD_P1) >> (shift)) #else #define lqHash(key,shift) \ (((unsigned)(key) * DD_P1) >> (shift)) #endif /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdQueueItem * hashLookup (DdLevelQueue *queue, void *key); static int hashInsert (DdLevelQueue *queue, DdQueueItem *item); static void hashDelete (DdLevelQueue *queue, DdQueueItem *item); static int hashResize (DdLevelQueue *queue); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Initializes a level queue.] Description [Initializes a level queue. A level queue is a queue where inserts are based on the levels of the nodes. Within each level the policy is FIFO. Level queues are useful in traversing a BDD top-down. Queue items are kept in a free list when dequeued for efficiency. Returns a pointer to the new queue if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue] ******************************************************************************/ DdLevelQueue * cuddLevelQueueInit( int levels /* number of levels */, int itemSize /* size of the item */, int numBuckets /* initial number of hash buckets */) { DdLevelQueue *queue; int logSize; queue = ABC_ALLOC(DdLevelQueue,1); if (queue == NULL) return(NULL); #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif /* Keep pointers to the insertion points for all levels. */ queue->last = ABC_ALLOC(DdQueueItem *, levels); #ifdef __osf__ #pragma pointer_size restore #endif if (queue->last == NULL) { ABC_FREE(queue); return(NULL); } /* Use a hash table to test for uniqueness. */ if (numBuckets < 2) numBuckets = 2; logSize = cuddComputeFloorLog2(numBuckets); queue->numBuckets = 1 << logSize; queue->shift = sizeof(int) * 8 - logSize; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif queue->buckets = ABC_ALLOC(DdQueueItem *, queue->numBuckets); #ifdef __osf__ #pragma pointer_size restore #endif if (queue->buckets == NULL) { ABC_FREE(queue->last); ABC_FREE(queue); return(NULL); } #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif memset(queue->last, 0, levels * sizeof(DdQueueItem *)); memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *)); #ifdef __osf__ #pragma pointer_size restore #endif queue->first = NULL; queue->freelist = NULL; queue->levels = levels; queue->itemsize = itemSize; queue->size = 0; queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY; return(queue); } /* end of cuddLevelQueueInit */ /**Function******************************************************************** Synopsis [Shuts down a level queue.] Description [Shuts down a level queue and releases all the associated memory.] SideEffects [None] SeeAlso [cuddLevelQueueInit] ******************************************************************************/ void cuddLevelQueueQuit( DdLevelQueue * queue) { DdQueueItem *item; while (queue->freelist != NULL) { item = queue->freelist; queue->freelist = item->next; ABC_FREE(item); } while (queue->first != NULL) { item = (DdQueueItem *) queue->first; queue->first = item->next; ABC_FREE(item); } ABC_FREE(queue->buckets); ABC_FREE(queue->last); ABC_FREE(queue); return; } /* end of cuddLevelQueueQuit */ /**Function******************************************************************** Synopsis [Inserts a new key in a level queue.] Description [Inserts a new key in a level queue. A new entry is created in the queue only if the node is not already enqueued. Returns a pointer to the queue item if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue] ******************************************************************************/ void * cuddLevelQueueEnqueue( DdLevelQueue * queue /* level queue */, void * key /* key to be enqueued */, int level /* level at which to insert */) { int plevel; DdQueueItem *item; #ifdef DD_DEBUG assert(level < queue->levels); #endif /* Check whether entry for this node exists. */ item = hashLookup(queue,key); if (item != NULL) return(item); /* Get a free item from either the free list or the memory manager. */ if (queue->freelist == NULL) { item = (DdQueueItem *) ABC_ALLOC(char, queue->itemsize); if (item == NULL) return(NULL); } else { item = queue->freelist; queue->freelist = item->next; } /* Initialize. */ memset(item, 0, queue->itemsize); item->key = key; /* Update stats. */ queue->size++; if (queue->last[level]) { /* There are already items for this level in the queue. */ item->next = queue->last[level]->next; queue->last[level]->next = item; } else { /* There are no items at the current level. Look for the first ** non-empty level preceeding this one. */ plevel = level; while (plevel != 0 && queue->last[plevel] == NULL) plevel--; if (queue->last[plevel] == NULL) { /* No element precedes this one in the queue. */ item->next = (DdQueueItem *) queue->first; queue->first = item; } else { item->next = queue->last[plevel]->next; queue->last[plevel]->next = item; } } queue->last[level] = item; /* Insert entry for the key in the hash table. */ if (hashInsert(queue,item) == 0) { return(NULL); } return(item); } /* end of cuddLevelQueueEnqueue */ /**Function******************************************************************** Synopsis [Remove an item from the front of a level queue.] Description [Remove an item from the front of a level queue.] SideEffects [None] SeeAlso [cuddLevelQueueEnqueue] ******************************************************************************/ void cuddLevelQueueDequeue( DdLevelQueue * queue, int level) { DdQueueItem *item = (DdQueueItem *) queue->first; /* Delete from the hash table. */ hashDelete(queue,item); /* Since we delete from the front, if this is the last item for ** its level, there are no other items for the same level. */ if (queue->last[level] == item) queue->last[level] = NULL; queue->first = item->next; /* Put item on the free list. */ item->next = queue->freelist; queue->freelist = item; /* Update stats. */ queue->size--; return; } /* end of cuddLevelQueueDequeue */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Looks up a key in the hash table of a level queue.] Description [Looks up a key in the hash table of a level queue. Returns a pointer to the item with the given key if the key is found; NULL otherwise.] SideEffects [None] SeeAlso [cuddLevelQueueEnqueue hashInsert] ******************************************************************************/ static DdQueueItem * hashLookup( DdLevelQueue * queue, void * key) { int posn; DdQueueItem *item; posn = lqHash(key,queue->shift); item = queue->buckets[posn]; while (item != NULL) { if (item->key == key) { return(item); } item = item->cnext; } return(NULL); } /* end of hashLookup */ /**Function******************************************************************** Synopsis [Inserts an item in the hash table of a level queue.] Description [Inserts an item in the hash table of a level queue. Returns 1 if successful; 0 otherwise. No check is performed to see if an item with the same key is already in the hash table.] SideEffects [None] SeeAlso [cuddLevelQueueEnqueue] ******************************************************************************/ static int hashInsert( DdLevelQueue * queue, DdQueueItem * item) { int result; int posn; if (queue->size > queue->maxsize) { result = hashResize(queue); if (result == 0) return(0); } posn = lqHash(item->key,queue->shift); item->cnext = queue->buckets[posn]; queue->buckets[posn] = item; return(1); } /* end of hashInsert */ /**Function******************************************************************** Synopsis [Removes an item from the hash table of a level queue.] Description [Removes an item from the hash table of a level queue. Nothing is done if the item is not in the table.] SideEffects [None] SeeAlso [cuddLevelQueueDequeue hashInsert] ******************************************************************************/ static void hashDelete( DdLevelQueue * queue, DdQueueItem * item) { int posn; DdQueueItem *prevItem; posn = lqHash(item->key,queue->shift); prevItem = queue->buckets[posn]; if (prevItem == NULL) return; if (prevItem == item) { queue->buckets[posn] = prevItem->cnext; return; } while (prevItem->cnext != NULL) { if (prevItem->cnext == item) { prevItem->cnext = item->cnext; return; } prevItem = prevItem->cnext; } return; } /* end of hashDelete */ /**Function******************************************************************** Synopsis [Resizes the hash table of a level queue.] Description [Resizes the hash table of a level queue. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [hashInsert] ******************************************************************************/ static int hashResize( DdLevelQueue * queue) { int j; int posn; DdQueueItem *item; DdQueueItem *next; int numBuckets; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif DdQueueItem **buckets; DdQueueItem **oldBuckets = queue->buckets; #ifdef __osf__ #pragma pointer_size restore #endif int shift; int oldNumBuckets = queue->numBuckets; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; /* Compute the new size of the subtable. */ numBuckets = oldNumBuckets << 1; saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif buckets = queue->buckets = ABC_ALLOC(DdQueueItem *, numBuckets); MMoutOfMemory = saveHandler; if (buckets == NULL) { queue->maxsize <<= 1; return(1); } queue->numBuckets = numBuckets; shift = --(queue->shift); queue->maxsize <<= 1; memset(buckets, 0, numBuckets * sizeof(DdQueueItem *)); #ifdef __osf__ #pragma pointer_size restore #endif for (j = 0; j < oldNumBuckets; j++) { item = oldBuckets[j]; while (item != NULL) { next = item->cnext; posn = lqHash(item->key, shift); item->cnext = buckets[posn]; buckets[posn] = item; item = next; } } ABC_FREE(oldBuckets); return(1); } /* end of hashResize */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddLinear.c000066400000000000000000001266461300674244400237410ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddLinear.c] PackageName [cudd] Synopsis [Functions for DD reduction by linear transformations.] Description [ Internal procedures included in this module:
      • cuddLinearAndSifting()
      • cuddLinearInPlace()
      • cuddUpdateInteractionMatrix()
      • cuddInitLinear()
      • cuddResizeLinear()
      Static procedures included in this module:
      • ddLinearUniqueCompare()
      • ddLinearAndSiftingAux()
      • ddLinearAndSiftingUp()
      • ddLinearAndSiftingDown()
      • ddLinearAndSiftingBackward()
      • ddUndoMoves()
      • cuddXorLinear()
      ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define CUDD_SWAP_MOVE 0 #define CUDD_LINEAR_TRANSFORM_MOVE 1 #define CUDD_INVERSE_TRANSFORM_MOVE 2 #if SIZEOF_LONG == 8 #define BPL 64 #define LOGBPL 6 #else #define BPL 32 #define LOGBPL 5 #endif /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.28 2009/02/19 16:21:03 fabio Exp $"; #endif static int *entry; #ifdef DD_STATS extern int ddTotalNumberSwapping; extern int ddTotalNISwaps; static int ddTotalNumberLinearTr; #endif #ifdef DD_DEBUG static int zero = 0; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int ddLinearUniqueCompare (int *ptrX, int *ptrY); static int ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh); static Move * ddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves); static Move * ddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves); static int ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves); static Move* ddUndoMoves (DdManager *table, Move *moves); static void cuddXorLinear (DdManager *table, int x, int y); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints the linear transform matrix.] Description [Prints the linear transform matrix. Returns 1 in case of success; 0 otherwise.] SideEffects [none] SeeAlso [] ******************************************************************************/ int Cudd_PrintLinear( DdManager * table) { int i,j,k; int retval; int nvars = table->linearSize; int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; long word; for (i = 0; i < nvars; i++) { for (j = 0; j < wordsPerRow; j++) { word = table->linear[i*wordsPerRow + j]; for (k = 0; k < BPL; k++) { retval = fprintf(table->out,"%ld",word & 1); if (retval == 0) return(0); word >>= 1; } } retval = fprintf(table->out,"\n"); if (retval == 0) return(0); } return(1); } /* end of Cudd_PrintLinear */ /**Function******************************************************************** Synopsis [Reads an entry of the linear transform matrix.] Description [Reads an entry of the linear transform matrix.] SideEffects [none] SeeAlso [] ******************************************************************************/ int Cudd_ReadLinear( DdManager * table /* CUDD manager */, int x /* row index */, int y /* column index */) { int nvars = table->size; int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; long word; int bit; int result; assert(table->size == table->linearSize); word = wordsPerRow * x + (y >> LOGBPL); bit = y & (BPL-1); result = (int) ((table->linear[word] >> bit) & 1); return(result); } /* end of Cudd_ReadLinear */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [BDD reduction based on combination of sifting and linear transformations.] Description [BDD reduction based on combination of sifting and linear transformations. Assumes that no dead nodes are present.
      1. Order all the variables according to the number of entries in each unique table.
      2. Sift the variable up and down, remembering each time the total size of the DD heap. At each position, linear transformation of the two adjacent variables is tried and is accepted if it reduces the size of the DD.
      3. Select the best permutation.
      4. Repeat 3 and 4 for all variables.
      Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ int cuddLinearAndSifting( DdManager * table, int lower, int upper) { int i; int *var; int size; int x; int result; #ifdef DD_STATS int previousSize; #endif #ifdef DD_STATS ddTotalNumberLinearTr = 0; #endif size = table->size; var = NULL; entry = NULL; if (table->linear == NULL) { result = cuddInitLinear(table); if (result == 0) goto cuddLinearAndSiftingOutOfMem; #if 0 (void) fprintf(table->out,"\n"); result = Cudd_PrintLinear(table); if (result == 0) goto cuddLinearAndSiftingOutOfMem; #endif } else if (table->size != table->linearSize) { result = cuddResizeLinear(table); if (result == 0) goto cuddLinearAndSiftingOutOfMem; #if 0 (void) fprintf(table->out,"\n"); result = Cudd_PrintLinear(table); if (result == 0) goto cuddLinearAndSiftingOutOfMem; #endif } /* Find order in which to sift variables. */ entry = ABC_ALLOC(int,size); if (entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddLinearAndSiftingOutOfMem; } var = ABC_ALLOC(int,size); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddLinearAndSiftingOutOfMem; } for (i = 0; i < size; i++) { x = table->perm[i]; entry[i] = table->subtables[x].keys; var[i] = i; } qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare); /* Now sift. */ for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { x = table->perm[var[i]]; if (x < lower || x > upper) continue; #ifdef DD_STATS previousSize = table->keys - table->isolated; #endif result = ddLinearAndSiftingAux(table,x,lower,upper); if (!result) goto cuddLinearAndSiftingOutOfMem; #ifdef DD_STATS if (table->keys < (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"-"); } else if (table->keys > (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"+"); /* should never happen */ (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif #ifdef DD_DEBUG (void) Cudd_DebugCheck(table); #endif } ABC_FREE(var); ABC_FREE(entry); #ifdef DD_STATS (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.", ddTotalNumberLinearTr); #endif return(1); cuddLinearAndSiftingOutOfMem: if (entry != NULL) ABC_FREE(entry); if (var != NULL) ABC_FREE(var); return(0); } /* end of cuddLinearAndSifting */ /**Function******************************************************************** Synopsis [Linearly combines two adjacent variables.] Description [Linearly combines two adjacent variables. Specifically, replaces the top variable with the exclusive nor of the two variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddLinearInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.] SideEffects [The two subtables corrresponding to variables x and y are modified. The global counters of the unique table are also affected.] SeeAlso [cuddSwapInPlace] ******************************************************************************/ int cuddLinearInPlace( DdManager * table, int x, int y) { DdNodePtr *xlist, *ylist; int xindex, yindex; int xslots, yslots; int xshift, yshift; int oldxkeys, oldykeys; int newxkeys, newykeys; int comple, newcomplement; int i; int posn; int isolated; DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; DdNode *g,*next,*last=NULL; DdNodePtr *previousP; DdNode *tmp; DdNode *sentinel = &(table->sentinel); #ifdef DD_DEBUG int count, idcheck; #endif #ifdef DD_DEBUG assert(x < y); assert(cuddNextHigh(table,x) == y); assert(table->subtables[x].keys != 0); assert(table->subtables[y].keys != 0); assert(table->subtables[x].dead == 0); assert(table->subtables[y].dead == 0); #endif xindex = table->invperm[x]; yindex = table->invperm[y]; if (cuddTestInteract(table,xindex,yindex)) { #ifdef DD_STATS ddTotalNumberLinearTr++; #endif /* Get parameters of x subtable. */ xlist = table->subtables[x].nodelist; oldxkeys = table->subtables[x].keys; xslots = table->subtables[x].slots; xshift = table->subtables[x].shift; /* Get parameters of y subtable. */ ylist = table->subtables[y].nodelist; oldykeys = table->subtables[y].keys; yslots = table->subtables[y].slots; yshift = table->subtables[y].shift; newxkeys = 0; newykeys = oldykeys; /* Check whether the two projection functions involved in this ** swap are isolated. At the end, we'll be able to tell how many ** isolated projection functions are there by checking only these ** two functions again. This is done to eliminate the isolated ** projection functions from the node count. */ isolated = - ((table->vars[xindex]->ref == 1) + (table->vars[yindex]->ref == 1)); /* The nodes in the x layer are put in a chain. ** The chain is handled as a FIFO; g points to the beginning and ** last points to the end. */ g = NULL; #ifdef DD_DEBUG last = NULL; #endif for (i = 0; i < xslots; i++) { f = xlist[i]; if (f == sentinel) continue; xlist[i] = sentinel; if (g == NULL) { g = f; } else { last->next = f; } while ((next = f->next) != sentinel) { f = next; } /* while there are elements in the collision chain */ last = f; } /* for each slot of the x subtable */ #ifdef DD_DEBUG /* last is always assigned in the for loop because there is at ** least one key */ assert(last != NULL); #endif last->next = NULL; #ifdef DD_COUNT table->swapSteps += oldxkeys; #endif /* Take care of the x nodes that must be re-expressed. ** They form a linked list pointed by g. */ f = g; while (f != NULL) { next = f->next; /* Find f1, f0, f11, f10, f01, f00. */ f1 = cuddT(f); #ifdef DD_DEBUG assert(!(Cudd_IsComplement(f1))); #endif if ((int) f1->index == yindex) { f11 = cuddT(f1); f10 = cuddE(f1); } else { f11 = f10 = f1; } #ifdef DD_DEBUG assert(!(Cudd_IsComplement(f11))); #endif f0 = cuddE(f); comple = Cudd_IsComplement(f0); f0 = Cudd_Regular(f0); if ((int) f0->index == yindex) { f01 = cuddT(f0); f00 = cuddE(f0); } else { f01 = f00 = f0; } if (comple) { f01 = Cudd_Not(f01); f00 = Cudd_Not(f00); } /* Decrease ref count of f1. */ cuddSatDec(f1->ref); /* Create the new T child. */ if (f11 == f00) { newf1 = f11; cuddSatInc(newf1->ref); } else { /* Check ylist for triple (yindex,f11,f00). */ posn = ddHash(cuddF2L(f11), cuddF2L(f00), yshift); /* For each element newf1 in collision list ylist[posn]. */ previousP = &(ylist[posn]); newf1 = *previousP; while (f11 < cuddT(newf1)) { previousP = &(newf1->next); newf1 = *previousP; } while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) { previousP = &(newf1->next); newf1 = *previousP; } if (cuddT(newf1) == f11 && cuddE(newf1) == f00) { cuddSatInc(newf1->ref); } else { /* no match */ newf1 = cuddDynamicAllocNode(table); if (newf1 == NULL) goto cuddLinearOutOfMem; newf1->index = yindex; newf1->ref = 1; cuddT(newf1) = f11; cuddE(newf1) = f00; /* Insert newf1 in the collision list ylist[posn]; ** increase the ref counts of f11 and f00. */ newykeys++; newf1->next = *previousP; *previousP = newf1; cuddSatInc(f11->ref); tmp = Cudd_Regular(f00); cuddSatInc(tmp->ref); } } cuddT(f) = newf1; #ifdef DD_DEBUG assert(!(Cudd_IsComplement(newf1))); #endif /* Do the same for f0, keeping complement dots into account. */ /* decrease ref count of f0 */ tmp = Cudd_Regular(f0); cuddSatDec(tmp->ref); /* create the new E child */ if (f01 == f10) { newf0 = f01; tmp = Cudd_Regular(newf0); cuddSatInc(tmp->ref); } else { /* make sure f01 is regular */ newcomplement = Cudd_IsComplement(f01); if (newcomplement) { f01 = Cudd_Not(f01); f10 = Cudd_Not(f10); } /* Check ylist for triple (yindex,f01,f10). */ posn = ddHash(cuddF2L(f01), cuddF2L(f10), yshift); /* For each element newf0 in collision list ylist[posn]. */ previousP = &(ylist[posn]); newf0 = *previousP; while (f01 < cuddT(newf0)) { previousP = &(newf0->next); newf0 = *previousP; } while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) { previousP = &(newf0->next); newf0 = *previousP; } if (cuddT(newf0) == f01 && cuddE(newf0) == f10) { cuddSatInc(newf0->ref); } else { /* no match */ newf0 = cuddDynamicAllocNode(table); if (newf0 == NULL) goto cuddLinearOutOfMem; newf0->index = yindex; newf0->ref = 1; cuddT(newf0) = f01; cuddE(newf0) = f10; /* Insert newf0 in the collision list ylist[posn]; ** increase the ref counts of f01 and f10. */ newykeys++; newf0->next = *previousP; *previousP = newf0; cuddSatInc(f01->ref); tmp = Cudd_Regular(f10); cuddSatInc(tmp->ref); } if (newcomplement) { newf0 = Cudd_Not(newf0); } } cuddE(f) = newf0; /* Re-insert the modified f in xlist. ** The modified f does not already exists in xlist. ** (Because of the uniqueness of the cofactors.) */ posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), xshift); newxkeys++; previousP = &(xlist[posn]); tmp = *previousP; while (newf1 < cuddT(tmp)) { previousP = &(tmp->next); tmp = *previousP; } while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { previousP = &(tmp->next); tmp = *previousP; } f->next = *previousP; *previousP = f; f = next; } /* while f != NULL */ /* GC the y layer. */ /* For each node f in ylist. */ for (i = 0; i < yslots; i++) { previousP = &(ylist[i]); f = *previousP; while (f != sentinel) { next = f->next; if (f->ref == 0) { tmp = cuddT(f); cuddSatDec(tmp->ref); tmp = Cudd_Regular(cuddE(f)); cuddSatDec(tmp->ref); cuddDeallocNode(table,f); newykeys--; } else { *previousP = f; previousP = &(f->next); } f = next; } /* while f */ *previousP = sentinel; } /* for every collision list */ #ifdef DD_DEBUG #if 0 (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y); #endif count = 0; idcheck = 0; for (i = 0; i < yslots; i++) { f = ylist[i]; while (f != sentinel) { count++; if (f->index != (DdHalfWord) yindex) idcheck++; f = f->next; } } if (count != newykeys) { fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count); } if (idcheck != 0) fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck); count = 0; idcheck = 0; for (i = 0; i < xslots; i++) { f = xlist[i]; while (f != sentinel) { count++; if (f->index != (DdHalfWord) xindex) idcheck++; f = f->next; } } if (count != newxkeys || newxkeys != oldxkeys) { fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count); } if (idcheck != 0) fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck); #endif isolated += (table->vars[xindex]->ref == 1) + (table->vars[yindex]->ref == 1); table->isolated += isolated; /* Set the appropriate fields in table. */ table->subtables[y].keys = newykeys; /* Here we should update the linear combination table ** to record that x <- x EXNOR y. This is done by complementing ** the (x,y) entry of the table. */ table->keys += newykeys - oldykeys; cuddXorLinear(table,xindex,yindex); } #ifdef DD_DEBUG if (zero) { (void) Cudd_DebugCheck(table); } #endif return(table->keys - table->isolated); cuddLinearOutOfMem: (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n"); return (0); } /* end of cuddLinearInPlace */ /**Function******************************************************************** Synopsis [Updates the interaction matrix.] Description [] SideEffects [none] SeeAlso [] ******************************************************************************/ void cuddUpdateInteractionMatrix( DdManager * table, int xindex, int yindex) { int i; for (i = 0; i < yindex; i++) { if (i != xindex && cuddTestInteract(table,i,yindex)) { if (i < xindex) { cuddSetInteract(table,i,xindex); } else { cuddSetInteract(table,xindex,i); } } } for (i = yindex+1; i < table->size; i++) { if (i != xindex && cuddTestInteract(table,yindex,i)) { if (i < xindex) { cuddSetInteract(table,i,xindex); } else { cuddSetInteract(table,xindex,i); } } } } /* end of cuddUpdateInteractionMatrix */ /**Function******************************************************************** Synopsis [Initializes the linear transform matrix.] Description [Initializes the linear transform matrix. Returns 1 if successful; 0 otherwise.] SideEffects [none] SeeAlso [] ******************************************************************************/ int cuddInitLinear( DdManager * table) { int words; int wordsPerRow; int nvars; int word; int bit; int i; long *linear; nvars = table->size; wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; words = wordsPerRow * nvars; table->linear = linear = ABC_ALLOC(long,words); if (linear == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } table->memused += words * sizeof(long); table->linearSize = nvars; for (i = 0; i < words; i++) linear[i] = 0; for (i = 0; i < nvars; i++) { word = wordsPerRow * i + (i >> LOGBPL); bit = i & (BPL-1); linear[word] = 1 << bit; } return(1); } /* end of cuddInitLinear */ /**Function******************************************************************** Synopsis [Resizes the linear transform matrix.] Description [Resizes the linear transform matrix. Returns 1 if successful; 0 otherwise.] SideEffects [none] SeeAlso [] ******************************************************************************/ int cuddResizeLinear( DdManager * table) { int words,oldWords; int wordsPerRow,oldWordsPerRow; int nvars,oldNvars; int word,oldWord; int bit; int i,j; long *linear,*oldLinear; oldNvars = table->linearSize; oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1; oldWords = oldWordsPerRow * oldNvars; oldLinear = table->linear; nvars = table->size; wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; words = wordsPerRow * nvars; table->linear = linear = ABC_ALLOC(long,words); if (linear == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } table->memused += (words - oldWords) * sizeof(long); for (i = 0; i < words; i++) linear[i] = 0; /* Copy old matrix. */ for (i = 0; i < oldNvars; i++) { for (j = 0; j < oldWordsPerRow; j++) { oldWord = oldWordsPerRow * i + j; word = wordsPerRow * i + j; linear[word] = oldLinear[oldWord]; } } ABC_FREE(oldLinear); /* Add elements to the diagonal. */ for (i = oldNvars; i < nvars; i++) { word = wordsPerRow * i + (i >> LOGBPL); bit = i & (BPL-1); linear[word] = 1 << bit; } table->linearSize = nvars; return(1); } /* end of cuddResizeLinear */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Comparison function used by qsort.] Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.] SideEffects [None] ******************************************************************************/ static int ddLinearUniqueCompare( int * ptrX, int * ptrY) { #if 0 if (entry[*ptrY] == entry[*ptrX]) { return((*ptrX) - (*ptrY)); } #endif return(entry[*ptrY] - entry[*ptrX]); } /* end of ddLinearUniqueCompare */ /**Function******************************************************************** Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.] Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. At each step a linear transformation is tried, and, if it decreases the size of the DD, it is accepted. Finds the best position and does the required changes. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddLinearAndSiftingAux( DdManager * table, int x, int xLow, int xHigh) { Move *move; Move *moveUp; /* list of up moves */ Move *moveDown; /* list of down moves */ int initialSize; int result; initialSize = table->keys - table->isolated; moveDown = NULL; moveUp = NULL; if (x == xLow) { moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); /* At this point x --> xHigh unless bounding occurred. */ if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; /* Move backward and stop at best position. */ result = ddLinearAndSiftingBackward(table,initialSize,moveDown); if (!result) goto ddLinearAndSiftingAuxOutOfMem; } else if (x == xHigh) { moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); /* At this point x --> xLow unless bounding occurred. */ if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; /* Move backward and stop at best position. */ result = ddLinearAndSiftingBackward(table,initialSize,moveUp); if (!result) goto ddLinearAndSiftingAuxOutOfMem; } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); /* At this point x --> xHigh unless bounding occurred. */ if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; moveUp = ddUndoMoves(table,moveDown); #ifdef DD_DEBUG assert(moveUp == NULL || moveUp->x == x); #endif moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp); if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; /* Move backward and stop at best position. */ result = ddLinearAndSiftingBackward(table,initialSize,moveUp); if (!result) goto ddLinearAndSiftingAuxOutOfMem; } else { /* must go up first: shorter */ moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); /* At this point x --> xLow unless bounding occurred. */ if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; moveDown = ddUndoMoves(table,moveUp); #ifdef DD_DEBUG assert(moveDown == NULL || moveDown->y == x); #endif moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown); if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; /* Move backward and stop at best position. */ result = ddLinearAndSiftingBackward(table,initialSize,moveDown); if (!result) goto ddLinearAndSiftingAuxOutOfMem; } while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } return(1); ddLinearAndSiftingAuxOutOfMem: while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } return(0); } /* end of ddLinearAndSiftingAux */ /**Function******************************************************************** Synopsis [Sifts a variable up and applies linear transformations.] Description [Sifts a variable up and applies linear transformations. Moves y up until either it reaches the bound (xLow) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] ******************************************************************************/ static Move * ddLinearAndSiftingUp( DdManager * table, int y, int xLow, Move * prevMoves) { Move *moves; Move *move; int x; int size, newsize; int limitSize; int xindex, yindex; int isolated; int L; /* lower bound on DD size */ #ifdef DD_DEBUG int checkL; int z; int zindex; #endif moves = prevMoves; yindex = table->invperm[y]; /* Initialize the lower bound. ** The part of the DD below y will not change. ** The part of the DD above y that does not interact with y will not ** change. The rest may vanish in the best case, except for ** the nodes at level xLow, which will not vanish, regardless. */ limitSize = L = table->keys - table->isolated; for (x = xLow + 1; x < y; x++) { xindex = table->invperm[x]; if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[xindex]->ref == 1; L -= table->subtables[x].keys - isolated; } } isolated = table->vars[yindex]->ref == 1; L -= table->subtables[y].keys - isolated; x = cuddNextLow(table,y); while (x >= xLow && L <= limitSize) { xindex = table->invperm[x]; #ifdef DD_DEBUG checkL = table->keys - table->isolated; for (z = xLow + 1; z < y; z++) { zindex = table->invperm[z]; if (cuddTestInteract(table,zindex,yindex)) { isolated = table->vars[zindex]->ref == 1; checkL -= table->subtables[z].keys - isolated; } } isolated = table->vars[yindex]->ref == 1; checkL -= table->subtables[y].keys - isolated; if (L != checkL) { (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L); } #endif size = cuddSwapInPlace(table,x,y); if (size == 0) goto ddLinearAndSiftingUpOutOfMem; newsize = cuddLinearInPlace(table,x,y); if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddLinearAndSiftingUpOutOfMem; move->x = x; move->y = y; move->next = moves; moves = move; move->flags = CUDD_SWAP_MOVE; if (newsize >= size) { /* Undo transformation. The transformation we apply is ** its own inverse. Hence, we just apply the transformation ** again. */ newsize = cuddLinearInPlace(table,x,y); if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; #ifdef DD_DEBUG if (newsize != size) { (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); } #endif } else if (cuddTestInteract(table,xindex,yindex)) { size = newsize; move->flags = CUDD_LINEAR_TRANSFORM_MOVE; cuddUpdateInteractionMatrix(table,xindex,yindex); } move->size = size; /* Update the lower bound. */ if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[xindex]->ref == 1; L += table->subtables[y].keys - isolated; } if ((double) size > (double) limitSize * table->maxGrowth) break; if (size < limitSize) limitSize = size; y = x; x = cuddNextLow(table,y); } return(moves); ddLinearAndSiftingUpOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return((Move *) CUDD_OUT_OF_MEM); } /* end of ddLinearAndSiftingUp */ /**Function******************************************************************** Synopsis [Sifts a variable down and applies linear transformations.] Description [Sifts a variable down and applies linear transformations. Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] ******************************************************************************/ static Move * ddLinearAndSiftingDown( DdManager * table, int x, int xHigh, Move * prevMoves) { Move *moves; Move *move; int y; int size, newsize; int R; /* upper bound on node decrease */ int limitSize; int xindex, yindex; int isolated; #ifdef DD_DEBUG int checkR; int z; int zindex; #endif moves = prevMoves; /* Initialize R */ xindex = table->invperm[x]; limitSize = size = table->keys - table->isolated; R = 0; for (y = xHigh; y > x; y--) { yindex = table->invperm[y]; if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[yindex]->ref == 1; R += table->subtables[y].keys - isolated; } } y = cuddNextHigh(table,x); while (y <= xHigh && size - R < limitSize) { #ifdef DD_DEBUG checkR = 0; for (z = xHigh; z > x; z--) { zindex = table->invperm[z]; if (cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; checkR += table->subtables[z].keys - isolated; } } if (R != checkR) { (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R); } #endif /* Update upper bound on node decrease. */ yindex = table->invperm[y]; if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[yindex]->ref == 1; R -= table->subtables[y].keys - isolated; } size = cuddSwapInPlace(table,x,y); if (size == 0) goto ddLinearAndSiftingDownOutOfMem; newsize = cuddLinearInPlace(table,x,y); if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddLinearAndSiftingDownOutOfMem; move->x = x; move->y = y; move->next = moves; moves = move; move->flags = CUDD_SWAP_MOVE; if (newsize >= size) { /* Undo transformation. The transformation we apply is ** its own inverse. Hence, we just apply the transformation ** again. */ newsize = cuddLinearInPlace(table,x,y); if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; if (newsize != size) { (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); } } else if (cuddTestInteract(table,xindex,yindex)) { size = newsize; move->flags = CUDD_LINEAR_TRANSFORM_MOVE; cuddUpdateInteractionMatrix(table,xindex,yindex); } move->size = size; if ((double) size > (double) limitSize * table->maxGrowth) break; if (size < limitSize) limitSize = size; x = y; y = cuddNextHigh(table,x); } return(moves); ddLinearAndSiftingDownOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return((Move *) CUDD_OUT_OF_MEM); } /* end of ddLinearAndSiftingDown */ /**Function******************************************************************** Synopsis [Given a set of moves, returns the DD heap to the order giving the minimum size.] Description [Given a set of moves, returns the DD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddLinearAndSiftingBackward( DdManager * table, int size, Move * moves) { Move *move; int res; for (move = moves; move != NULL; move = move->next) { if (move->size < size) { size = move->size; } } for (move = moves; move != NULL; move = move->next) { if (move->size == size) return(1); if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { res = cuddLinearInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); } res = cuddSwapInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { res = cuddLinearInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); } } return(1); } /* end of ddLinearAndSiftingBackward */ /**Function******************************************************************** Synopsis [Given a set of moves, returns the DD heap to the order in effect before the moves.] Description [Given a set of moves, returns the DD heap to the order in effect before the moves. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static Move* ddUndoMoves( DdManager * table, Move * moves) { Move *invmoves = NULL; Move *move; Move *invmove; int size; for (move = moves; move != NULL; move = move->next) { invmove = (Move *) cuddDynamicAllocNode(table); if (invmove == NULL) goto ddUndoMovesOutOfMem; invmove->x = move->x; invmove->y = move->y; invmove->next = invmoves; invmoves = invmove; if (move->flags == CUDD_SWAP_MOVE) { invmove->flags = CUDD_SWAP_MOVE; size = cuddSwapInPlace(table,(int)move->x,(int)move->y); if (!size) goto ddUndoMovesOutOfMem; } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; size = cuddLinearInPlace(table,(int)move->x,(int)move->y); if (!size) goto ddUndoMovesOutOfMem; size = cuddSwapInPlace(table,(int)move->x,(int)move->y); if (!size) goto ddUndoMovesOutOfMem; } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ #ifdef DD_DEBUG (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); #endif invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; size = cuddSwapInPlace(table,(int)move->x,(int)move->y); if (!size) goto ddUndoMovesOutOfMem; size = cuddLinearInPlace(table,(int)move->x,(int)move->y); if (!size) goto ddUndoMovesOutOfMem; } invmove->size = size; } return(invmoves); ddUndoMovesOutOfMem: while (invmoves != NULL) { move = invmoves->next; cuddDeallocMove(table, invmoves); invmoves = move; } return((Move *) CUDD_OUT_OF_MEM); } /* end of ddUndoMoves */ /**Function******************************************************************** Synopsis [XORs two rows of the linear transform matrix.] Description [XORs two rows of the linear transform matrix and replaces the first row with the result.] SideEffects [none] SeeAlso [] ******************************************************************************/ static void cuddXorLinear( DdManager * table, int x, int y) { int i; int nvars = table->size; int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; int xstart = wordsPerRow * x; int ystart = wordsPerRow * y; long *linear = table->linear; for (i = 0; i < wordsPerRow; i++) { linear[xstart+i] ^= linear[ystart+i]; } } /* end of cuddXorLinear */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddLiteral.c000066400000000000000000000217201300674244400241060ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddLiteral.c] PackageName [cudd] Synopsis [Functions for manipulation of literal sets represented by BDDs.] Description [External procedures included in this file:
      • Cudd_bddLiteralSetIntersection()
      Internal procedures included in this file:
      • cuddBddLiteralSetIntersectionRecur()
      ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddLiteral.c,v 1.8 2004/08/13 18:04:50 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the intesection of two sets of literals represented as BDDs.] Description [Computes the intesection of two sets of literals represented as BDDs. Each set is represented as a cube of the literals in the set. The empty set is represented by the constant 1. No variable can be simultaneously present in both phases in a set. Returns a pointer to the BDD representing the intersected sets, if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ DdNode * Cudd_bddLiteralSetIntersection( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddBddLiteralSetIntersectionRecur(dd,f,g); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddLiteralSetIntersection */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddLiteralSetIntersection.] Description [Performs the recursive step of Cudd_bddLiteralSetIntersection. Scans the cubes for common variables, and checks whether they agree in phase. Returns a pointer to the resulting cube if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ DdNode * cuddBddLiteralSetIntersectionRecur( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res, *tmp; DdNode *F, *G; DdNode *fc, *gc; DdNode *one; DdNode *zero; unsigned int topf, topg, comple; int phasef, phaseg; statLine(dd); if (f == g) return(f); F = Cudd_Regular(f); G = Cudd_Regular(g); one = DD_ONE(dd); /* Here f != g. If F == G, then f and g are complementary. ** Since they are two cubes, this case only occurs when f == v, ** g == v', and v is a variable or its complement. */ if (F == G) return(one); zero = Cudd_Not(one); topf = cuddI(dd,F->index); topg = cuddI(dd,G->index); /* Look for a variable common to both cubes. If there are none, this ** loop will stop when the constant node is reached in both cubes. */ while (topf != topg) { if (topf < topg) { /* move down on f */ comple = f != F; f = cuddT(F); if (comple) f = Cudd_Not(f); if (f == zero) { f = cuddE(F); if (comple) f = Cudd_Not(f); } F = Cudd_Regular(f); topf = cuddI(dd,F->index); } else if (topg < topf) { comple = g != G; g = cuddT(G); if (comple) g = Cudd_Not(g); if (g == zero) { g = cuddE(G); if (comple) g = Cudd_Not(g); } G = Cudd_Regular(g); topg = cuddI(dd,G->index); } } /* At this point, f == one <=> g == 1. It suffices to test one of them. */ if (f == one) return(one); res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g); if (res != NULL) { return(res); } /* Here f and g are both non constant and have the same top variable. */ comple = f != F; fc = cuddT(F); phasef = 1; if (comple) fc = Cudd_Not(fc); if (fc == zero) { fc = cuddE(F); phasef = 0; if (comple) fc = Cudd_Not(fc); } comple = g != G; gc = cuddT(G); phaseg = 1; if (comple) gc = Cudd_Not(gc); if (gc == zero) { gc = cuddE(G); phaseg = 0; if (comple) gc = Cudd_Not(gc); } tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc); if (tmp == NULL) { return(NULL); } if (phasef != phaseg) { res = tmp; } else { cuddRef(tmp); if (phasef == 0) { res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp); } else { res = cuddBddAndRecur(dd,dd->vars[F->index],tmp); } if (res == NULL) { Cudd_RecursiveDeref(dd,tmp); return(NULL); } cuddDeref(tmp); /* Just cuddDeref, because it is included in result */ } cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res); return(res); } /* end of cuddBddLiteralSetIntersectionRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddMatMult.c000066400000000000000000000534761300674244400241120ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddMatMult.c] PackageName [cudd] Synopsis [Matrix multiplication functions.] Description [External procedures included in this module:
      • Cudd_addMatrixMultiply()
      • Cudd_addTimesPlus()
      • Cudd_addTriangle()
      • Cudd_addOuterSum()
      Static procedures included in this module:
      • addMMRecur()
      • addTriangleRecur()
      • cuddAddOuterSumRecur()
      ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddMatMult.c,v 1.17 2004/08/13 18:04:50 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * addMMRecur (DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars); static DdNode * addTriangleRecur (DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube); static DdNode * cuddAddOuterSumRecur (DdManager *dd, DdNode *M, DdNode *r, DdNode *c); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Calculates the product of two matrices represented as ADDs.] Description [Calculates the product of two matrices, A and B, represented as ADDs. This procedure implements the quasiring multiplication algorithm. A is assumed to depend on variables x (rows) and z (columns). B is assumed to depend on variables z (rows) and y (columns). The product of A and B then depends on x (rows) and y (columns). Only the z variables have to be explicitly identified; they are the "summation" variables. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addTimesPlus Cudd_addTriangle Cudd_bddAndAbstract] ******************************************************************************/ DdNode * Cudd_addMatrixMultiply( DdManager * dd, DdNode * A, DdNode * B, DdNode ** z, int nz) { int i, nvars, *vars; DdNode *res; /* Array vars says what variables are "summation" variables. */ nvars = dd->size; vars = ABC_ALLOC(int,nvars); if (vars == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < nvars; i++) { vars[i] = 0; } for (i = 0; i < nz; i++) { vars[z[i]->index] = 1; } do { dd->reordered = 0; res = addMMRecur(dd,A,B,-1,vars); } while (dd->reordered == 1); ABC_FREE(vars); return(res); } /* end of Cudd_addMatrixMultiply */ /**Function******************************************************************** Synopsis [Calculates the product of two matrices represented as ADDs.] Description [Calculates the product of two matrices, A and B, represented as ADDs, using the CMU matrix by matrix multiplication procedure by Clarke et al.. Matrix A has x's as row variables and z's as column variables, while matrix B has z's as row variables and y's as column variables. Returns the pointer to the result if successful; NULL otherwise. The resulting matrix has x's as row variables and y's as column variables.] SideEffects [None] SeeAlso [Cudd_addMatrixMultiply] ******************************************************************************/ DdNode * Cudd_addTimesPlus( DdManager * dd, DdNode * A, DdNode * B, DdNode ** z, int nz) { DdNode *w, *cube, *tmp, *res; int i; tmp = Cudd_addApply(dd,Cudd_addTimes,A,B); if (tmp == NULL) return(NULL); Cudd_Ref(tmp); Cudd_Ref(cube = DD_ONE(dd)); for (i = nz-1; i >= 0; i--) { w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd)); if (w == NULL) { Cudd_RecursiveDeref(dd,tmp); return(NULL); } Cudd_Ref(w); Cudd_RecursiveDeref(dd,cube); cube = w; } res = Cudd_addExistAbstract(dd,tmp,cube); if (res == NULL) { Cudd_RecursiveDeref(dd,tmp); Cudd_RecursiveDeref(dd,cube); return(NULL); } Cudd_Ref(res); Cudd_RecursiveDeref(dd,cube); Cudd_RecursiveDeref(dd,tmp); Cudd_Deref(res); return(res); } /* end of Cudd_addTimesPlus */ /**Function******************************************************************** Synopsis [Performs the triangulation step for the shortest path computation.] Description [Implements the semiring multiplication algorithm used in the triangulation step for the shortest path computation. f is assumed to depend on variables x (rows) and z (columns). g is assumed to depend on variables z (rows) and y (columns). The product of f and g then depends on x (rows) and y (columns). Only the z variables have to be explicitly identified; they are the "abstraction" variables. Returns a pointer to the result if successful; NULL otherwise. ] SideEffects [None] SeeAlso [Cudd_addMatrixMultiply Cudd_bddAndAbstract] ******************************************************************************/ DdNode * Cudd_addTriangle( DdManager * dd, DdNode * f, DdNode * g, DdNode ** z, int nz) { int i, nvars, *vars; DdNode *res, *cube; nvars = dd->size; vars = ABC_ALLOC(int, nvars); if (vars == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < nvars; i++) vars[i] = -1; for (i = 0; i < nz; i++) vars[z[i]->index] = i; cube = Cudd_addComputeCube(dd, z, NULL, nz); if (cube == NULL) { ABC_FREE(vars); return(NULL); } cuddRef(cube); do { dd->reordered = 0; res = addTriangleRecur(dd, f, g, vars, cube); } while (dd->reordered == 1); if (res != NULL) cuddRef(res); Cudd_RecursiveDeref(dd,cube); if (res != NULL) cuddDeref(res); ABC_FREE(vars); return(res); } /* end of Cudd_addTriangle */ /**Function******************************************************************** Synopsis [Takes the minimum of a matrix and the outer sum of two vectors.] Description [Takes the pointwise minimum of a matrix and the outer sum of two vectors. This procedure is used in the Floyd-Warshall all-pair shortest path algorithm. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_addOuterSum( DdManager *dd, DdNode *M, DdNode *r, DdNode *c) { DdNode *res; do { dd->reordered = 0; res = cuddAddOuterSumRecur(dd, M, r, c); } while (dd->reordered == 1); return(res); } /* end of Cudd_addOuterSum */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addMatrixMultiply.] Description [Performs the recursive step of Cudd_addMatrixMultiply. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ static DdNode * addMMRecur( DdManager * dd, DdNode * A, DdNode * B, int topP, int * vars) { DdNode *zero, *At, /* positive cofactor of first operand */ *Ae, /* negative cofactor of first operand */ *Bt, /* positive cofactor of second operand */ *Be, /* negative cofactor of second operand */ *t, /* positive cofactor of result */ *e, /* negative cofactor of result */ *scaled, /* scaled result */ *add_scale, /* ADD representing the scaling factor */ *res; int i; /* loop index */ double scale; /* scaling factor */ int index; /* index of the top variable */ CUDD_VALUE_TYPE value; unsigned int topA, topB, topV; DD_CTFP cacheOp; statLine(dd); zero = DD_ZERO(dd); if (A == zero || B == zero) { return(zero); } if (cuddIsConstant(A) && cuddIsConstant(B)) { /* Compute the scaling factor. It is 2^k, where k is the ** number of summation variables below the current variable. ** Indeed, these constants represent blocks of 2^k identical ** constant values in both A and B. */ value = cuddV(A) * cuddV(B); for (i = 0; i < dd->size; i++) { if (vars[i]) { if (dd->perm[i] > topP) { value *= (CUDD_VALUE_TYPE) 2; } } } res = cuddUniqueConst(dd, value); return(res); } /* Standardize to increase cache efficiency. Clearly, A*B != B*A ** in matrix multiplication. However, which matrix is which is ** determined by the variables appearing in the ADDs and not by ** which one is passed as first argument. */ if (A > B) { DdNode *tmp = A; A = B; B = tmp; } topA = cuddI(dd,A->index); topB = cuddI(dd,B->index); topV = ddMin(topA,topB); cacheOp = (DD_CTFP) addMMRecur; res = cuddCacheLookup2(dd,cacheOp,A,B); if (res != NULL) { /* If the result is 0, there is no need to normalize. ** Otherwise we count the number of z variables between ** the current depth and the top of the ADDs. These are ** the missing variables that determine the size of the ** constant blocks. */ if (res == zero) return(res); scale = 1.0; for (i = 0; i < dd->size; i++) { if (vars[i]) { if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { scale *= 2; } } } if (scale > 1.0) { cuddRef(res); add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); if (add_scale == NULL) { Cudd_RecursiveDeref(dd, res); return(NULL); } cuddRef(add_scale); scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); if (scaled == NULL) { Cudd_RecursiveDeref(dd, add_scale); Cudd_RecursiveDeref(dd, res); return(NULL); } cuddRef(scaled); Cudd_RecursiveDeref(dd, add_scale); Cudd_RecursiveDeref(dd, res); res = scaled; cuddDeref(res); } return(res); } /* compute the cofactors */ if (topV == topA) { At = cuddT(A); Ae = cuddE(A); } else { At = Ae = A; } if (topV == topB) { Bt = cuddT(B); Be = cuddE(B); } else { Bt = Be = B; } t = addMMRecur(dd, At, Bt, (int)topV, vars); if (t == NULL) return(NULL); cuddRef(t); e = addMMRecur(dd, Ae, Be, (int)topV, vars); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); index = dd->invperm[topV]; if (vars[index] == 0) { /* We have split on either the rows of A or the columns ** of B. We just need to connect the two subresults, ** which correspond to two submatrices of the result. */ res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddRef(res); cuddDeref(t); cuddDeref(e); } else { /* we have simultaneously split on the columns of A and ** the rows of B. The two subresults must be added. */ res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); } cuddCacheInsert2(dd,cacheOp,A,B,res); /* We have computed (and stored in the computed table) a minimal ** result; that is, a result that assumes no summation variables ** between the current depth of the recursion and its top ** variable. We now take into account the z variables by properly ** scaling the result. */ if (res != zero) { scale = 1.0; for (i = 0; i < dd->size; i++) { if (vars[i]) { if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { scale *= 2; } } } if (scale > 1.0) { add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); if (add_scale == NULL) { Cudd_RecursiveDeref(dd, res); return(NULL); } cuddRef(add_scale); scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); if (scaled == NULL) { Cudd_RecursiveDeref(dd, res); Cudd_RecursiveDeref(dd, add_scale); return(NULL); } cuddRef(scaled); Cudd_RecursiveDeref(dd, add_scale); Cudd_RecursiveDeref(dd, res); res = scaled; } } cuddDeref(res); return(res); } /* end of addMMRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addTriangle.] Description [Performs the recursive step of Cudd_addTriangle. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ static DdNode * addTriangleRecur( DdManager * dd, DdNode * f, DdNode * g, int * vars, DdNode *cube) { DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res; CUDD_VALUE_TYPE value; int top, topf, topg, index; statLine(dd); if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) { return(DD_PLUS_INFINITY(dd)); } if (cuddIsConstant(f) && cuddIsConstant(g)) { value = cuddV(f) + cuddV(g); res = cuddUniqueConst(dd, value); return(res); } if (f < g) { DdNode *tmp = f; f = g; g = tmp; } if (f->ref != 1 || g->ref != 1) { res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube); if (res != NULL) { return(res); } } topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); top = ddMin(topf,topg); if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} t = addTriangleRecur(dd, fv, gv, vars, cube); if (t == NULL) return(NULL); cuddRef(t); e = addTriangleRecur(dd, fvn, gvn, vars, cube); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); index = dd->invperm[top]; if (vars[index] < 0) { res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddDeref(t); cuddDeref(e); } else { res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); cuddDeref(res); } if (f->ref != 1 || g->ref != 1) { cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res); } return(res); } /* end of addTriangleRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addOuterSum.] Description [Performs the recursive step of Cudd_addOuterSum. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddAddOuterSumRecur( DdManager *dd, DdNode *M, DdNode *r, DdNode *c) { DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re; int topM, topc, topr; int v, index; statLine(dd); /* Check special cases. */ if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); if (cuddIsConstant(c) && cuddIsConstant(r)) { R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r)); cuddRef(R); if (cuddIsConstant(M)) { if (cuddV(R) <= cuddV(M)) { cuddDeref(R); return(R); } else { Cudd_RecursiveDeref(dd,R); return(M); } } else { P = Cudd_addApply(dd,Cudd_addMinimum,R,M); cuddRef(P); Cudd_RecursiveDeref(dd,R); cuddDeref(P); return(P); } } /* Check the cache. */ R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c); if (R != NULL) return(R); topM = cuddI(dd,M->index); topr = cuddI(dd,r->index); topc = cuddI(dd,c->index); v = ddMin(topM,ddMin(topr,topc)); /* Compute cofactors. */ if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; } if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; } if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; } /* Recursively solve. */ Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct); if (Rt == NULL) return(NULL); cuddRef(Rt); Re = cuddAddOuterSumRecur(dd,Me,re,ce); if (Re == NULL) { Cudd_RecursiveDeref(dd, Rt); return(NULL); } cuddRef(Re); index = dd->invperm[v]; R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re); if (R == NULL) { Cudd_RecursiveDeref(dd, Rt); Cudd_RecursiveDeref(dd, Re); return(NULL); } cuddDeref(Rt); cuddDeref(Re); /* Store the result in the cache. */ cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R); return(R); } /* end of cuddAddOuterSumRecur */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddPriority.c000066400000000000000000001776521300674244400243530ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddPriority.c] PackageName [cudd] Synopsis [Priority functions.] Description [External procedures included in this file:
      • Cudd_PrioritySelect()
      • Cudd_Xgty()
      • Cudd_Xeqy()
      • Cudd_addXeqy()
      • Cudd_Dxygtdxz()
      • Cudd_Dxygtdyz()
      • Cudd_Inequality()
      • Cudd_Disequality()
      • Cudd_bddInterval()
      • Cudd_CProjection()
      • Cudd_addHamming()
      • Cudd_MinHammingDist()
      • Cudd_bddClosestCube()
      Internal procedures included in this module:
      • cuddCProjectionRecur()
      • cuddBddClosestCube()
      Static procedures included in this module:
      • cuddMinHammingDistRecur()
      • separateCube()
      • createResult()
      ] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DD_DEBUG 1 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddPriority.c,v 1.33 2009/02/20 02:14:58 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int cuddMinHammingDistRecur (DdNode * f, int *minterm, DdHashTable * table, int upperBound); static DdNode * separateCube (DdManager *dd, DdNode *f, CUDD_VALUE_TYPE *distance); static DdNode * createResult (DdManager *dd, unsigned int index, unsigned int phase, DdNode *cube, CUDD_VALUE_TYPE distance); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Selects pairs from R using a priority function.] Description [Selects pairs from a relation R(x,y) (given as a BDD) in such a way that a given x appears in one pair only. Uses a priority function to determine which y should be paired to a given x. Cudd_PrioritySelect returns a pointer to the selected function if successful; NULL otherwise. Three of the arguments--x, y, and z--are vectors of BDD variables. The first two are the variables on which R depends. The third vectore is a vector of auxiliary variables, used during the computation. This vector is optional. If a NULL value is passed instead, Cudd_PrioritySelect will create the working variables on the fly. The sizes of x and y (and z if it is not NULL) should equal n. The priority function Pi can be passed as a BDD, or can be built by Cudd_PrioritySelect. If NULL is passed instead of a DdNode *, parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the priority function. (Pifunc is a pointer to a C function.) If Pi is not NULL, then Pifunc is ignored. Pifunc should have the same interface as the standard priority functions (e.g., Cudd_Dxygtdxz). Cudd_PrioritySelect and Cudd_CProjection can sometimes be used interchangeably. Specifically, calling Cudd_PrioritySelect with Cudd_Xgty as Pifunc produces the same result as calling Cudd_CProjection with the all-zero minterm as reference minterm. However, depending on the application, one or the other may be preferable:
      • When extracting representatives from an equivalence relation, Cudd_CProjection has the advantage of nor requiring the auxiliary variables.
      • When computing matchings in general bipartite graphs, Cudd_PrioritySelect normally obtains better results because it can use more powerful matching schemes (e.g., Cudd_Dxygtdxz).
      ] SideEffects [If called with z == NULL, will create new variables in the manager.] SeeAlso [Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_Xgty Cudd_bddAdjPermuteX Cudd_CProjection] ******************************************************************************/ DdNode * Cudd_PrioritySelect( DdManager * dd /* manager */, DdNode * R /* BDD of the relation */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */, DdNode ** z /* array of z variables (optional: may be NULL) */, DdNode * Pi /* BDD of the priority function (optional: may be NULL) */, int n /* size of x, y, and z */, DD_PRFP Pifunc /* function used to build Pi if it is NULL */) { DdNode *res = NULL; DdNode *zcube = NULL; DdNode *Rxz, *Q; int createdZ = 0; int createdPi = 0; int i; /* Create z variables if needed. */ if (z == NULL) { if (Pi != NULL) return(NULL); z = ABC_ALLOC(DdNode *,n); if (z == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } createdZ = 1; for (i = 0; i < n; i++) { if (dd->size >= (int) CUDD_MAXINDEX - 1) goto endgame; z[i] = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one)); if (z[i] == NULL) goto endgame; } } /* Create priority function BDD if needed. */ if (Pi == NULL) { Pi = Pifunc(dd,n,x,y,z); if (Pi == NULL) goto endgame; createdPi = 1; cuddRef(Pi); } /* Initialize abstraction cube. */ zcube = DD_ONE(dd); cuddRef(zcube); for (i = n - 1; i >= 0; i--) { DdNode *tmpp; tmpp = Cudd_bddAnd(dd,z[i],zcube); if (tmpp == NULL) goto endgame; cuddRef(tmpp); Cudd_RecursiveDeref(dd,zcube); zcube = tmpp; } /* Compute subset of (x,y) pairs. */ Rxz = Cudd_bddSwapVariables(dd,R,y,z,n); if (Rxz == NULL) goto endgame; cuddRef(Rxz); Q = Cudd_bddAndAbstract(dd,Rxz,Pi,zcube); if (Q == NULL) { Cudd_RecursiveDeref(dd,Rxz); goto endgame; } cuddRef(Q); Cudd_RecursiveDeref(dd,Rxz); res = Cudd_bddAnd(dd,R,Cudd_Not(Q)); if (res == NULL) { Cudd_RecursiveDeref(dd,Q); goto endgame; } cuddRef(res); Cudd_RecursiveDeref(dd,Q); endgame: if (zcube != NULL) Cudd_RecursiveDeref(dd,zcube); if (createdZ) { ABC_FREE(z); } if (createdPi) { Cudd_RecursiveDeref(dd,Pi); } if (res != NULL) cuddDeref(res); return(res); } /* Cudd_PrioritySelect */ /**Function******************************************************************** Synopsis [Generates a BDD for the function x > y.] Description [This function generates a BDD for the function x > y. Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. The BDD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. Argument z is not used by Cudd_Xgty: it is included to make it call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.] SideEffects [None] SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Dxygtdyz] ******************************************************************************/ DdNode * Cudd_Xgty( DdManager * dd /* DD manager */, int N /* number of x and y variables */, DdNode ** z /* array of z variables: unused */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */) { DdNode *u, *v, *w; int i; /* Build bottom part of BDD outside loop. */ u = Cudd_bddAnd(dd, x[N-1], Cudd_Not(y[N-1])); if (u == NULL) return(NULL); cuddRef(u); /* Loop to build the rest of the BDD. */ for (i = N-2; i >= 0; i--) { v = Cudd_bddAnd(dd, y[i], Cudd_Not(u)); if (v == NULL) { Cudd_RecursiveDeref(dd, u); return(NULL); } cuddRef(v); w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); if (w == NULL) { Cudd_RecursiveDeref(dd, u); Cudd_RecursiveDeref(dd, v); return(NULL); } cuddRef(w); Cudd_RecursiveDeref(dd, u); u = Cudd_bddIte(dd, x[i], Cudd_Not(v), w); if (u == NULL) { Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); return(NULL); } cuddRef(u); Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); } cuddDeref(u); return(u); } /* end of Cudd_Xgty */ /**Function******************************************************************** Synopsis [Generates a BDD for the function x==y.] Description [This function generates a BDD for the function x==y. Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. The BDD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] SideEffects [None] SeeAlso [Cudd_addXeqy] ******************************************************************************/ DdNode * Cudd_Xeqy( DdManager * dd /* DD manager */, int N /* number of x and y variables */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */) { DdNode *u, *v, *w; int i; /* Build bottom part of BDD outside loop. */ u = Cudd_bddIte(dd, x[N-1], y[N-1], Cudd_Not(y[N-1])); if (u == NULL) return(NULL); cuddRef(u); /* Loop to build the rest of the BDD. */ for (i = N-2; i >= 0; i--) { v = Cudd_bddAnd(dd, y[i], u); if (v == NULL) { Cudd_RecursiveDeref(dd, u); return(NULL); } cuddRef(v); w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); if (w == NULL) { Cudd_RecursiveDeref(dd, u); Cudd_RecursiveDeref(dd, v); return(NULL); } cuddRef(w); Cudd_RecursiveDeref(dd, u); u = Cudd_bddIte(dd, x[i], v, w); if (u == NULL) { Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); return(NULL); } cuddRef(u); Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); } cuddDeref(u); return(u); } /* end of Cudd_Xeqy */ /**Function******************************************************************** Synopsis [Generates an ADD for the function x==y.] Description [This function generates an ADD for the function x==y. Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. The ADD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] SideEffects [None] SeeAlso [Cudd_Xeqy] ******************************************************************************/ DdNode * Cudd_addXeqy( DdManager * dd /* DD manager */, int N /* number of x and y variables */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */) { DdNode *one, *zero; DdNode *u, *v, *w; int i; one = DD_ONE(dd); zero = DD_ZERO(dd); /* Build bottom part of ADD outside loop. */ v = Cudd_addIte(dd, y[N-1], one, zero); if (v == NULL) return(NULL); cuddRef(v); w = Cudd_addIte(dd, y[N-1], zero, one); if (w == NULL) { Cudd_RecursiveDeref(dd, v); return(NULL); } cuddRef(w); u = Cudd_addIte(dd, x[N-1], v, w); if (u == NULL) { Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); return(NULL); } cuddRef(u); Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); /* Loop to build the rest of the ADD. */ for (i = N-2; i >= 0; i--) { v = Cudd_addIte(dd, y[i], u, zero); if (v == NULL) { Cudd_RecursiveDeref(dd, u); return(NULL); } cuddRef(v); w = Cudd_addIte(dd, y[i], zero, u); if (w == NULL) { Cudd_RecursiveDeref(dd, u); Cudd_RecursiveDeref(dd, v); return(NULL); } cuddRef(w); Cudd_RecursiveDeref(dd, u); u = Cudd_addIte(dd, x[i], v, w); if (w == NULL) { Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); return(NULL); } cuddRef(u); Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); } cuddDeref(u); return(u); } /* end of Cudd_addXeqy */ /**Function******************************************************************** Synopsis [Generates a BDD for the function d(x,y) > d(x,z).] Description [This function generates a BDD for the function d(x,y) > d(x,z); x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], with 0 the most significant bit. The distance d(x,y) is defined as: \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). The BDD is built bottom-up. It has 7*N-3 internal nodes, if the variables are ordered as follows: x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] SideEffects [None] SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdyz Cudd_Xgty Cudd_bddAdjPermuteX] ******************************************************************************/ DdNode * Cudd_Dxygtdxz( DdManager * dd /* DD manager */, int N /* number of x, y, and z variables */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */, DdNode ** z /* array of z variables */) { DdNode *one, *zero; DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; int i; one = DD_ONE(dd); zero = Cudd_Not(one); /* Build bottom part of BDD outside loop. */ y1_ = Cudd_bddIte(dd, y[N-1], one, Cudd_Not(z[N-1])); if (y1_ == NULL) return(NULL); cuddRef(y1_); y2 = Cudd_bddIte(dd, y[N-1], z[N-1], one); if (y2 == NULL) { Cudd_RecursiveDeref(dd, y1_); return(NULL); } cuddRef(y2); x1 = Cudd_bddIte(dd, x[N-1], y1_, y2); if (x1 == NULL) { Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); return(NULL); } cuddRef(x1); Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); /* Loop to build the rest of the BDD. */ for (i = N-2; i >= 0; i--) { z1 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); if (z1 == NULL) { Cudd_RecursiveDeref(dd, x1); return(NULL); } cuddRef(z1); z2 = Cudd_bddIte(dd, z[i], x1, one); if (z2 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); return(NULL); } cuddRef(z2); z3 = Cudd_bddIte(dd, z[i], one, x1); if (z3 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); return(NULL); } cuddRef(z3); z4 = Cudd_bddIte(dd, z[i], x1, zero); if (z4 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); return(NULL); } cuddRef(z4); Cudd_RecursiveDeref(dd, x1); y1_ = Cudd_bddIte(dd, y[i], z2, Cudd_Not(z1)); if (y1_ == NULL) { Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); return(NULL); } cuddRef(y1_); y2 = Cudd_bddIte(dd, y[i], z4, z3); if (y2 == NULL) { Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); Cudd_RecursiveDeref(dd, y1_); return(NULL); } cuddRef(y2); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); x1 = Cudd_bddIte(dd, x[i], y1_, y2); if (x1 == NULL) { Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); return(NULL); } cuddRef(x1); Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); } cuddDeref(x1); return(Cudd_Not(x1)); } /* end of Cudd_Dxygtdxz */ /**Function******************************************************************** Synopsis [Generates a BDD for the function d(x,y) > d(y,z).] Description [This function generates a BDD for the function d(x,y) > d(y,z); x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], with 0 the most significant bit. The distance d(x,y) is defined as: \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). The BDD is built bottom-up. It has 7*N-3 internal nodes, if the variables are ordered as follows: x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] SideEffects [None] SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Xgty Cudd_bddAdjPermuteX] ******************************************************************************/ DdNode * Cudd_Dxygtdyz( DdManager * dd /* DD manager */, int N /* number of x, y, and z variables */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */, DdNode ** z /* array of z variables */) { DdNode *one, *zero; DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; int i; one = DD_ONE(dd); zero = Cudd_Not(one); /* Build bottom part of BDD outside loop. */ y1_ = Cudd_bddIte(dd, y[N-1], one, z[N-1]); if (y1_ == NULL) return(NULL); cuddRef(y1_); y2 = Cudd_bddIte(dd, y[N-1], z[N-1], zero); if (y2 == NULL) { Cudd_RecursiveDeref(dd, y1_); return(NULL); } cuddRef(y2); x1 = Cudd_bddIte(dd, x[N-1], y1_, Cudd_Not(y2)); if (x1 == NULL) { Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); return(NULL); } cuddRef(x1); Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); /* Loop to build the rest of the BDD. */ for (i = N-2; i >= 0; i--) { z1 = Cudd_bddIte(dd, z[i], x1, zero); if (z1 == NULL) { Cudd_RecursiveDeref(dd, x1); return(NULL); } cuddRef(z1); z2 = Cudd_bddIte(dd, z[i], x1, one); if (z2 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); return(NULL); } cuddRef(z2); z3 = Cudd_bddIte(dd, z[i], one, x1); if (z3 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); return(NULL); } cuddRef(z3); z4 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); if (z4 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); return(NULL); } cuddRef(z4); Cudd_RecursiveDeref(dd, x1); y1_ = Cudd_bddIte(dd, y[i], z2, z1); if (y1_ == NULL) { Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); return(NULL); } cuddRef(y1_); y2 = Cudd_bddIte(dd, y[i], z4, Cudd_Not(z3)); if (y2 == NULL) { Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); Cudd_RecursiveDeref(dd, y1_); return(NULL); } cuddRef(y2); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); x1 = Cudd_bddIte(dd, x[i], y1_, Cudd_Not(y2)); if (x1 == NULL) { Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); return(NULL); } cuddRef(x1); Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); } cuddDeref(x1); return(Cudd_Not(x1)); } /* end of Cudd_Dxygtdyz */ /**Function******************************************************************** Synopsis [Generates a BDD for the function x - y ≥ c.] Description [This function generates a BDD for the function x -y ≥ c. Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. The BDD is built bottom-up. It has a linear number of nodes if the variables are ordered as follows: x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].] SideEffects [None] SeeAlso [Cudd_Xgty] ******************************************************************************/ DdNode * Cudd_Inequality( DdManager * dd /* DD manager */, int N /* number of x and y variables */, int c /* right-hand side constant */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */) { /* The nodes at level i represent values of the difference that are ** multiples of 2^i. We use variables with names starting with k ** to denote the multipliers of 2^i in such multiples. */ int kTrue = c; int kFalse = c - 1; /* Mask used to compute the ceiling function. Since we divide by 2^i, ** we want to know whether the dividend is a multiple of 2^i. If it is, ** then ceiling and floor coincide; otherwise, they differ by one. */ int mask = 1; int i; DdNode *f = NULL; /* the eventual result */ DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); /* Two x-labeled nodes are created at most at each iteration. They are ** stored, along with their k values, in these variables. At each level, ** the old nodes are freed and the new nodes are copied into the old map. */ DdNode *map[2] = {0}; int invalidIndex = 1 << (N-1); int index[2] = {invalidIndex, invalidIndex}; /* This should never happen. */ if (N < 0) return(NULL); /* If there are no bits, both operands are 0. The result depends on c. */ if (N == 0) { if (c >= 0) return(one); else return(zero); } /* The maximum or the minimum difference comparing to c can generate the terminal case */ if ((1 << N) - 1 < c) return(zero); else if ((-(1 << N) + 1) >= c) return(one); /* Build the result bottom up. */ for (i = 1; i <= N; i++) { int kTrueLower, kFalseLower; int leftChild, middleChild, rightChild; DdNode *g0, *g1, *fplus, *fequal, *fminus; int j; DdNode *newMap[2] = {NULL}; int newIndex[2]; kTrueLower = kTrue; kFalseLower = kFalse; /* kTrue = ceiling((c-1)/2^i) + 1 */ kTrue = ((c-1) >> i) + ((c & mask) != 1) + 1; mask = (mask << 1) | 1; /* kFalse = floor(c/2^i) - 1 */ kFalse = (c >> i) - 1; newIndex[0] = invalidIndex; newIndex[1] = invalidIndex; for (j = kFalse + 1; j < kTrue; j++) { /* Skip if node is not reachable from top of BDD. */ if ((j >= (1 << (N - i))) || (j <= -(1 << (N -i)))) continue; /* Find f- */ leftChild = (j << 1) - 1; if (leftChild >= kTrueLower) { fminus = one; } else if (leftChild <= kFalseLower) { fminus = zero; } else { assert(leftChild == index[0] || leftChild == index[1]); if (leftChild == index[0]) { fminus = map[0]; } else { fminus = map[1]; } } /* Find f= */ middleChild = j << 1; if (middleChild >= kTrueLower) { fequal = one; } else if (middleChild <= kFalseLower) { fequal = zero; } else { assert(middleChild == index[0] || middleChild == index[1]); if (middleChild == index[0]) { fequal = map[0]; } else { fequal = map[1]; } } /* Find f+ */ rightChild = (j << 1) + 1; if (rightChild >= kTrueLower) { fplus = one; } else if (rightChild <= kFalseLower) { fplus = zero; } else { assert(rightChild == index[0] || rightChild == index[1]); if (rightChild == index[0]) { fplus = map[0]; } else { fplus = map[1]; } } /* Build new nodes. */ g1 = Cudd_bddIte(dd, y[N - i], fequal, fplus); if (g1 == NULL) { if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]); if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]); if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]); if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]); return(NULL); } cuddRef(g1); g0 = Cudd_bddIte(dd, y[N - i], fminus, fequal); if (g0 == NULL) { Cudd_IterDerefBdd(dd, g1); if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]); if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]); if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]); if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]); return(NULL); } cuddRef(g0); f = Cudd_bddIte(dd, x[N - i], g1, g0); if (f == NULL) { Cudd_IterDerefBdd(dd, g1); Cudd_IterDerefBdd(dd, g0); if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]); if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]); if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]); if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]); return(NULL); } cuddRef(f); Cudd_IterDerefBdd(dd, g1); Cudd_IterDerefBdd(dd, g0); /* Save newly computed node in map. */ assert(newIndex[0] == invalidIndex || newIndex[1] == invalidIndex); if (newIndex[0] == invalidIndex) { newIndex[0] = j; newMap[0] = f; } else { newIndex[1] = j; newMap[1] = f; } } /* Copy new map to map. */ if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]); if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]); map[0] = newMap[0]; map[1] = newMap[1]; index[0] = newIndex[0]; index[1] = newIndex[1]; } cuddDeref(f); return(f); } /* end of Cudd_Inequality */ /**Function******************************************************************** Synopsis [Generates a BDD for the function x - y != c.] Description [This function generates a BDD for the function x -y != c. Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. The BDD is built bottom-up. It has a linear number of nodes if the variables are ordered as follows: x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].] SideEffects [None] SeeAlso [Cudd_Xgty] ******************************************************************************/ DdNode * Cudd_Disequality( DdManager * dd /* DD manager */, int N /* number of x and y variables */, int c /* right-hand side constant */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */) { /* The nodes at level i represent values of the difference that are ** multiples of 2^i. We use variables with names starting with k ** to denote the multipliers of 2^i in such multiples. */ int kTrueLb = c + 1; int kTrueUb = c - 1; int kFalse = c; /* Mask used to compute the ceiling function. Since we divide by 2^i, ** we want to know whether the dividend is a multiple of 2^i. If it is, ** then ceiling and floor coincide; otherwise, they differ by one. */ int mask = 1; int i; DdNode *f = NULL; /* the eventual result */ DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); /* Two x-labeled nodes are created at most at each iteration. They are ** stored, along with their k values, in these variables. At each level, ** the old nodes are freed and the new nodes are copied into the old map. */ DdNode *map[2] = {0}; int invalidIndex = 1 << (N-1); int index[2] = {invalidIndex, invalidIndex}; /* This should never happen. */ if (N < 0) return(NULL); /* If there are no bits, both operands are 0. The result depends on c. */ if (N == 0) { if (c != 0) return(one); else return(zero); } /* The maximum or the minimum difference comparing to c can generate the terminal case */ if ((1 << N) - 1 < c || (-(1 << N) + 1) > c) return(one); /* Build the result bottom up. */ for (i = 1; i <= N; i++) { int kTrueLbLower, kTrueUbLower; int leftChild, middleChild, rightChild; DdNode *g0, *g1, *fplus, *fequal, *fminus; int j; DdNode *newMap[2] = {NULL}; int newIndex[2]; kTrueLbLower = kTrueLb; kTrueUbLower = kTrueUb; /* kTrueLb = floor((c-1)/2^i) + 2 */ kTrueLb = ((c-1) >> i) + 2; /* kTrueUb = ceiling((c+1)/2^i) - 2 */ kTrueUb = ((c+1) >> i) + (((c+2) & mask) != 1) - 2; mask = (mask << 1) | 1; newIndex[0] = invalidIndex; newIndex[1] = invalidIndex; for (j = kTrueUb + 1; j < kTrueLb; j++) { /* Skip if node is not reachable from top of BDD. */ if ((j >= (1 << (N - i))) || (j <= -(1 << (N -i)))) continue; /* Find f- */ leftChild = (j << 1) - 1; if (leftChild >= kTrueLbLower || leftChild <= kTrueUbLower) { fminus = one; } else if (i == 1 && leftChild == kFalse) { fminus = zero; } else { assert(leftChild == index[0] || leftChild == index[1]); if (leftChild == index[0]) { fminus = map[0]; } else { fminus = map[1]; } } /* Find f= */ middleChild = j << 1; if (middleChild >= kTrueLbLower || middleChild <= kTrueUbLower) { fequal = one; } else if (i == 1 && middleChild == kFalse) { fequal = zero; } else { assert(middleChild == index[0] || middleChild == index[1]); if (middleChild == index[0]) { fequal = map[0]; } else { fequal = map[1]; } } /* Find f+ */ rightChild = (j << 1) + 1; if (rightChild >= kTrueLbLower || rightChild <= kTrueUbLower) { fplus = one; } else if (i == 1 && rightChild == kFalse) { fplus = zero; } else { assert(rightChild == index[0] || rightChild == index[1]); if (rightChild == index[0]) { fplus = map[0]; } else { fplus = map[1]; } } /* Build new nodes. */ g1 = Cudd_bddIte(dd, y[N - i], fequal, fplus); if (g1 == NULL) { if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]); if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]); if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]); if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]); return(NULL); } cuddRef(g1); g0 = Cudd_bddIte(dd, y[N - i], fminus, fequal); if (g0 == NULL) { Cudd_IterDerefBdd(dd, g1); if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]); if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]); if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]); if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]); return(NULL); } cuddRef(g0); f = Cudd_bddIte(dd, x[N - i], g1, g0); if (f == NULL) { Cudd_IterDerefBdd(dd, g1); Cudd_IterDerefBdd(dd, g0); if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]); if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]); if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]); if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]); return(NULL); } cuddRef(f); Cudd_IterDerefBdd(dd, g1); Cudd_IterDerefBdd(dd, g0); /* Save newly computed node in map. */ assert(newIndex[0] == invalidIndex || newIndex[1] == invalidIndex); if (newIndex[0] == invalidIndex) { newIndex[0] = j; newMap[0] = f; } else { newIndex[1] = j; newMap[1] = f; } } /* Copy new map to map. */ if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]); if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]); map[0] = newMap[0]; map[1] = newMap[1]; index[0] = newIndex[0]; index[1] = newIndex[1]; } cuddDeref(f); return(f); } /* end of Cudd_Disequality */ /**Function******************************************************************** Synopsis [Generates a BDD for the function lowerB ≤ x ≤ upperB.] Description [This function generates a BDD for the function lowerB ≤ x ≤ upperB, where x is an N-bit number, x\[0\] x\[1\] ... x\[N-1\], with 0 the most significant bit (important!). The number of variables N should be sufficient to represent the bounds; otherwise, the bounds are truncated to their N least significant bits. Two BDDs are built bottom-up for lowerB ≤ x and x ≤ upperB, and they are finally conjoined.] SideEffects [None] SeeAlso [Cudd_Xgty] ******************************************************************************/ DdNode * Cudd_bddInterval( DdManager * dd /* DD manager */, int N /* number of x variables */, DdNode ** x /* array of x variables */, unsigned int lowerB /* lower bound */, unsigned int upperB /* upper bound */) { DdNode *one, *zero; DdNode *r, *rl, *ru; int i; one = DD_ONE(dd); zero = Cudd_Not(one); rl = one; cuddRef(rl); ru = one; cuddRef(ru); /* Loop to build the rest of the BDDs. */ for (i = N-1; i >= 0; i--) { DdNode *vl, *vu; vl = Cudd_bddIte(dd, x[i], lowerB&1 ? rl : one, lowerB&1 ? zero : rl); if (vl == NULL) { Cudd_IterDerefBdd(dd, rl); Cudd_IterDerefBdd(dd, ru); return(NULL); } cuddRef(vl); Cudd_IterDerefBdd(dd, rl); rl = vl; lowerB >>= 1; vu = Cudd_bddIte(dd, x[i], upperB&1 ? ru : zero, upperB&1 ? one : ru); if (vu == NULL) { Cudd_IterDerefBdd(dd, rl); Cudd_IterDerefBdd(dd, ru); return(NULL); } cuddRef(vu); Cudd_IterDerefBdd(dd, ru); ru = vu; upperB >>= 1; } /* Conjoin the two bounds. */ r = Cudd_bddAnd(dd, rl, ru); if (r == NULL) { Cudd_IterDerefBdd(dd, rl); Cudd_IterDerefBdd(dd, ru); return(NULL); } cuddRef(r); Cudd_IterDerefBdd(dd, rl); Cudd_IterDerefBdd(dd, ru); cuddDeref(r); return(r); } /* end of Cudd_bddInterval */ /**Function******************************************************************** Synopsis [Computes the compatible projection of R w.r.t. cube Y.] Description [Computes the compatible projection of relation R with respect to cube Y. Returns a pointer to the c-projection if successful; NULL otherwise. For a comparison between Cudd_CProjection and Cudd_PrioritySelect, see the documentation of the latter.] SideEffects [None] SeeAlso [Cudd_PrioritySelect] ******************************************************************************/ DdNode * Cudd_CProjection( DdManager * dd, DdNode * R, DdNode * Y) { DdNode *res; DdNode *support; if (cuddCheckCube(dd,Y) == 0) { (void) fprintf(dd->err, "Error: The third argument of Cudd_CProjection should be a cube\n"); dd->errorCode = CUDD_INVALID_ARG; return(NULL); } /* Compute the support of Y, which is used by the abstraction step ** in cuddCProjectionRecur. */ support = Cudd_Support(dd,Y); if (support == NULL) return(NULL); cuddRef(support); do { dd->reordered = 0; res = cuddCProjectionRecur(dd,R,Y,support); } while (dd->reordered == 1); if (res == NULL) { Cudd_RecursiveDeref(dd,support); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd,support); cuddDeref(res); return(res); } /* end of Cudd_CProjection */ /**Function******************************************************************** Synopsis [Computes the Hamming distance ADD.] Description [Computes the Hamming distance ADD. Returns an ADD that gives the Hamming distance between its two arguments if successful; NULL otherwise. The two vectors xVars and yVars identify the variables that form the two arguments.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_addHamming( DdManager * dd, DdNode ** xVars, DdNode ** yVars, int nVars) { DdNode *result,*tempBdd; DdNode *tempAdd,*temp; int i; result = DD_ZERO(dd); cuddRef(result); for (i = 0; i < nVars; i++) { tempBdd = Cudd_bddIte(dd,xVars[i],Cudd_Not(yVars[i]),yVars[i]); if (tempBdd == NULL) { Cudd_RecursiveDeref(dd,result); return(NULL); } cuddRef(tempBdd); tempAdd = Cudd_BddToAdd(dd,tempBdd); if (tempAdd == NULL) { Cudd_RecursiveDeref(dd,tempBdd); Cudd_RecursiveDeref(dd,result); return(NULL); } cuddRef(tempAdd); Cudd_RecursiveDeref(dd,tempBdd); temp = Cudd_addApply(dd,Cudd_addPlus,tempAdd,result); if (temp == NULL) { Cudd_RecursiveDeref(dd,tempAdd); Cudd_RecursiveDeref(dd,result); return(NULL); } cuddRef(temp); Cudd_RecursiveDeref(dd,tempAdd); Cudd_RecursiveDeref(dd,result); result = temp; } cuddDeref(result); return(result); } /* end of Cudd_addHamming */ /**Function******************************************************************** Synopsis [Returns the minimum Hamming distance between f and minterm.] Description [Returns the minimum Hamming distance between the minterms of a function f and a reference minterm. The function is given as a BDD; the minterm is given as an array of integers, one for each variable in the manager. Returns the minimum distance if it is less than the upper bound; the upper bound if the minimum distance is at least as large; CUDD_OUT_OF_MEM in case of failure.] SideEffects [None] SeeAlso [Cudd_addHamming Cudd_bddClosestCube] ******************************************************************************/ int Cudd_MinHammingDist( DdManager *dd /* DD manager */, DdNode *f /* function to examine */, int *minterm /* reference minterm */, int upperBound /* distance above which an approximate answer is OK */) { DdHashTable *table; CUDD_VALUE_TYPE epsilon; int res; table = cuddHashTableInit(dd,1,2); if (table == NULL) { return(CUDD_OUT_OF_MEM); } epsilon = Cudd_ReadEpsilon(dd); Cudd_SetEpsilon(dd,(CUDD_VALUE_TYPE)0.0); res = cuddMinHammingDistRecur(f,minterm,table,upperBound); cuddHashTableQuit(table); Cudd_SetEpsilon(dd,epsilon); return(res); } /* end of Cudd_MinHammingDist */ /**Function******************************************************************** Synopsis [Finds a cube of f at minimum Hamming distance from g.] Description [Finds a cube of f at minimum Hamming distance from the minterms of g. All the minterms of the cube are at the minimum distance. If the distance is 0, the cube belongs to the intersection of f and g. Returns the cube if successful; NULL otherwise.] SideEffects [The distance is returned as a side effect.] SeeAlso [Cudd_MinHammingDist] ******************************************************************************/ DdNode * Cudd_bddClosestCube( DdManager *dd, DdNode * f, DdNode *g, int *distance) { DdNode *res, *acube; CUDD_VALUE_TYPE rdist; /* Compute the cube and distance as a single ADD. */ do { dd->reordered = 0; res = cuddBddClosestCube(dd,f,g,CUDD_CONST_INDEX + 1.0); } while (dd->reordered == 1); if (res == NULL) return(NULL); cuddRef(res); /* Unpack distance and cube. */ do { dd->reordered = 0; acube = separateCube(dd, res, &rdist); } while (dd->reordered == 1); if (acube == NULL) { Cudd_RecursiveDeref(dd, res); return(NULL); } cuddRef(acube); Cudd_RecursiveDeref(dd, res); /* Convert cube from ADD to BDD. */ do { dd->reordered = 0; res = cuddAddBddDoPattern(dd, acube); } while (dd->reordered == 1); if (res == NULL) { Cudd_RecursiveDeref(dd, acube); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, acube); *distance = (int) rdist; cuddDeref(res); return(res); } /* end of Cudd_bddClosestCube */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_CProjection.] Description [Performs the recursive step of Cudd_CProjection. Returns the projection if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_CProjection] ******************************************************************************/ DdNode * cuddCProjectionRecur( DdManager * dd, DdNode * R, DdNode * Y, DdNode * Ysupp) { DdNode *res, *res1, *res2, *resA; DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha; unsigned int topR, topY, top, index = 0; DdNode *one = DD_ONE(dd); statLine(dd); if (Y == one) return(R); #ifdef DD_DEBUG assert(!Cudd_IsConstant(Y)); #endif if (R == Cudd_Not(one)) return(R); res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y); if (res != NULL) return(res); r = Cudd_Regular(R); topR = cuddI(dd,r->index); y = Cudd_Regular(Y); topY = cuddI(dd,y->index); top = ddMin(topR, topY); /* Compute the cofactors of R */ if (topR == top) { index = r->index; RT = cuddT(r); RE = cuddE(r); if (r != R) { RT = Cudd_Not(RT); RE = Cudd_Not(RE); } } else { RT = RE = R; } if (topY > top) { /* Y does not depend on the current top variable. ** We just need to compute the results on the two cofactors of R ** and make them the children of a node labeled r->index. */ res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp); if (res2 == NULL) { Cudd_RecursiveDeref(dd,res1); return(NULL); } cuddRef(res2); res = cuddBddIteRecur(dd, dd->vars[index], res1, res2); if (res == NULL) { Cudd_RecursiveDeref(dd,res1); Cudd_RecursiveDeref(dd,res2); return(NULL); } /* If we have reached this point, res1 and res2 are now ** incorporated in res. cuddDeref is therefore sufficient. */ cuddDeref(res1); cuddDeref(res2); } else { /* Compute the cofactors of Y */ index = y->index; YT = cuddT(y); YE = cuddE(y); if (y != Y) { YT = Cudd_Not(YT); YE = Cudd_Not(YE); } if (YT == Cudd_Not(one)) { Alpha = Cudd_Not(dd->vars[index]); Yrest = YE; Ra = RE; Ran = RT; } else { Alpha = dd->vars[index]; Yrest = YT; Ra = RT; Ran = RE; } Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp)); if (Gamma == NULL) return(NULL); if (Gamma == one) { res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); if (res1 == NULL) return(NULL); cuddRef(res1); res = cuddBddAndRecur(dd, Alpha, res1); if (res == NULL) { Cudd_RecursiveDeref(dd,res1); return(NULL); } cuddDeref(res1); } else if (Gamma == Cudd_Not(one)) { res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); if (res1 == NULL) return(NULL); cuddRef(res1); res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1); if (res == NULL) { Cudd_RecursiveDeref(dd,res1); return(NULL); } cuddDeref(res1); } else { cuddRef(Gamma); resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); if (resA == NULL) { Cudd_RecursiveDeref(dd,Gamma); return(NULL); } cuddRef(resA); res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA); if (res2 == NULL) { Cudd_RecursiveDeref(dd,Gamma); Cudd_RecursiveDeref(dd,resA); return(NULL); } cuddRef(res2); Cudd_RecursiveDeref(dd,Gamma); Cudd_RecursiveDeref(dd,resA); res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); if (res1 == NULL) { Cudd_RecursiveDeref(dd,res2); return(NULL); } cuddRef(res1); res = cuddBddIteRecur(dd, Alpha, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(dd,res1); Cudd_RecursiveDeref(dd,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); } } cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res); return(res); } /* end of cuddCProjectionRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddClosestCube.] Description [Performs the recursive step of Cudd_bddClosestCube. Returns the cube if succesful; NULL otherwise. The procedure uses a four-way recursion to examine all four combinations of cofactors of f and g according to the following formula.
          H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1)
        
      Bounding is based on the following observations.
      • If we already found two points at distance 0, there is no point in continuing. Furthermore,
      • If F == not(G) then the best we can hope for is a minimum distance of 1. If we have already found two points at distance 1, there is no point in continuing. (Indeed, H(F,G) == 1 in this case. We have to continue, though, to find the cube.)
      The variable bound is set at the largest value of the distance that we are still interested in. Therefore, we desist when
          (bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)).
        
      If we were maximally aggressive in using the bound, we would always set the bound to the minimum distance seen thus far minus one. That is, we would maintain the invariant
          bound < minD,
        
      except at the very beginning, when we have no value for minD.

      However, we do not use bound < minD when examining the two negative cofactors, because we try to find a large cube at minimum distance. To do so, we try to find a cube in the negative cofactors at the same or smaller distance from the cube found in the positive cofactors.

      When we compute H(ft,ge) and H(fe,gt) we know that we are going to add 1 to the result of the recursive call to account for the difference in the splitting variable. Therefore, we decrease the bound correspondingly.

      Another important observation concerns the need of examining all four pairs of cofators only when both f and g depend on the top variable.

      Suppose gt == ge == g. (That is, g does not depend on the top variable.) Then

          H(f,g) = min(H(ft,g), H(fe,g), H(ft,g)+1, H(fe,g)+1)
                 = min(H(ft,g), H(fe,g)) .
        
      Therefore, under these circumstances, we skip the two "cross" cases.

      An interesting feature of this function is the scheme used for caching the results in the global computed table. Since we have a cube and a distance, we combine them to form an ADD. The combination replaces the zero child of the top node of the cube with the negative of the distance. (The use of the negative is to avoid ambiguity with 1.) The degenerate cases (zero and one) are treated specially because the distance is known (0 for one, and infinity for zero).] SideEffects [None] SeeAlso [Cudd_bddClosestCube] ******************************************************************************/ DdNode * cuddBddClosestCube( DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE bound) { DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee; DdNode *ctt, *cee, *cte, *cet; CUDD_VALUE_TYPE minD, dtt, dee, dte, det; DdNode *one = DD_ONE(dd); DdNode *lzero = Cudd_Not(one); DdNode *azero = DD_ZERO(dd); unsigned int topf, topg, index; statLine(dd); if (bound < (int)(f == Cudd_Not(g))) return(azero); /* Terminal cases. */ if (g == lzero || f == lzero) return(azero); if (f == one && g == one) return(one); /* Check cache. */ F = Cudd_Regular(f); G = Cudd_Regular(g); if (F->ref != 1 || G->ref != 1) { res = cuddCacheLookup2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g); if (res != NULL) return(res); } topf = cuddI(dd,F->index); topg = cuddI(dd,G->index); /* Compute cofactors. */ if (topf <= topg) { index = F->index; ft = cuddT(F); fe = cuddE(F); if (Cudd_IsComplement(f)) { ft = Cudd_Not(ft); fe = Cudd_Not(fe); } } else { index = G->index; ft = fe = f; } if (topg <= topf) { gt = cuddT(G); ge = cuddE(G); if (Cudd_IsComplement(g)) { gt = Cudd_Not(gt); ge = Cudd_Not(ge); } } else { gt = ge = g; } tt = cuddBddClosestCube(dd,ft,gt,bound); if (tt == NULL) return(NULL); cuddRef(tt); ctt = separateCube(dd,tt,&dtt); if (ctt == NULL) { Cudd_RecursiveDeref(dd, tt); return(NULL); } cuddRef(ctt); Cudd_RecursiveDeref(dd, tt); minD = dtt; bound = ddMin(bound,minD); ee = cuddBddClosestCube(dd,fe,ge,bound); if (ee == NULL) { Cudd_RecursiveDeref(dd, ctt); return(NULL); } cuddRef(ee); cee = separateCube(dd,ee,&dee); if (cee == NULL) { Cudd_RecursiveDeref(dd, ctt); Cudd_RecursiveDeref(dd, ee); return(NULL); } cuddRef(cee); Cudd_RecursiveDeref(dd, ee); minD = ddMin(dtt, dee); if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1); if (minD > 0 && topf == topg) { DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1); if (te == NULL) { Cudd_RecursiveDeref(dd, ctt); Cudd_RecursiveDeref(dd, cee); return(NULL); } cuddRef(te); cte = separateCube(dd,te,&dte); if (cte == NULL) { Cudd_RecursiveDeref(dd, ctt); Cudd_RecursiveDeref(dd, cee); Cudd_RecursiveDeref(dd, te); return(NULL); } cuddRef(cte); Cudd_RecursiveDeref(dd, te); dte += 1.0; minD = ddMin(minD, dte); } else { cte = azero; cuddRef(cte); dte = CUDD_CONST_INDEX + 1.0; } if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1); if (minD > 0 && topf == topg) { DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1); if (et == NULL) { Cudd_RecursiveDeref(dd, ctt); Cudd_RecursiveDeref(dd, cee); Cudd_RecursiveDeref(dd, cte); return(NULL); } cuddRef(et); cet = separateCube(dd,et,&det); if (cet == NULL) { Cudd_RecursiveDeref(dd, ctt); Cudd_RecursiveDeref(dd, cee); Cudd_RecursiveDeref(dd, cte); Cudd_RecursiveDeref(dd, et); return(NULL); } cuddRef(cet); Cudd_RecursiveDeref(dd, et); det += 1.0; minD = ddMin(minD, det); } else { cet = azero; cuddRef(cet); det = CUDD_CONST_INDEX + 1.0; } if (minD == dtt) { if (dtt == dee && ctt == cee) { res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt); } else { res = createResult(dd,index,1,ctt,dtt); } } else if (minD == dee) { res = createResult(dd,index,0,cee,dee); } else if (minD == dte) { #ifdef DD_DEBUG assert(topf == topg); #endif res = createResult(dd,index,1,cte,dte); } else { #ifdef DD_DEBUG assert(topf == topg); #endif res = createResult(dd,index,0,cet,det); } if (res == NULL) { Cudd_RecursiveDeref(dd, ctt); Cudd_RecursiveDeref(dd, cee); Cudd_RecursiveDeref(dd, cte); Cudd_RecursiveDeref(dd, cet); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, ctt); Cudd_RecursiveDeref(dd, cee); Cudd_RecursiveDeref(dd, cte); Cudd_RecursiveDeref(dd, cet); /* Only cache results that are different from azero to avoid ** storing results that depend on the value of the bound. */ if ((F->ref != 1 || G->ref != 1) && res != azero) cuddCacheInsert2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g, res); cuddDeref(res); return(res); } /* end of cuddBddClosestCube */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_MinHammingDist.] Description [Performs the recursive step of Cudd_MinHammingDist. It is based on the following identity. Let H(f) be the minimum Hamming distance of the minterms of f from the reference minterm. Then:

      H(f) = min(H(f0)+h0,H(f1)+h1) where f0 and f1 are the two cofactors of f with respect to its top variable; h0 is 1 if the minterm assigns 1 to the top variable of f; h1 is 1 if the minterm assigns 0 to the top variable of f. The upper bound on the distance is used to bound the depth of the recursion. Returns the minimum distance unless it exceeds the upper bound or computation fails.] SideEffects [None] SeeAlso [Cudd_MinHammingDist] ******************************************************************************/ static int cuddMinHammingDistRecur( DdNode * f, int *minterm, DdHashTable * table, int upperBound) { DdNode *F, *Ft, *Fe; double h, hT, hE; DdNode *zero, *res; DdManager *dd = table->manager; statLine(dd); if (upperBound == 0) return(0); F = Cudd_Regular(f); if (cuddIsConstant(F)) { zero = Cudd_Not(DD_ONE(dd)); if (f == dd->background || f == zero) { return(upperBound); } else { return(0); } } if ((res = cuddHashTableLookup1(table,f)) != NULL) { h = cuddV(res); if (res->ref == 0) { dd->dead++; dd->constants.dead++; } return((int) h); } Ft = cuddT(F); Fe = cuddE(F); if (Cudd_IsComplement(f)) { Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe); } if (minterm[F->index] == 0) { DdNode *temp = Ft; Ft = Fe; Fe = temp; } hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound); if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); if (hT == 0) { hE = upperBound; } else { hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1); if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); } h = ddMin(hT, hE + 1); if (F->ref != 1) { ptrint fanout = (ptrint) F->ref; cuddSatDec(fanout); res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h); if (!cuddHashTableInsert1(table,f,res,fanout)) { cuddRef(res); Cudd_RecursiveDeref(dd, res); return(CUDD_OUT_OF_MEM); } } return((int) h); } /* end of cuddMinHammingDistRecur */ /**Function******************************************************************** Synopsis [Separates cube from distance.] Description [Separates cube from distance. Returns the cube if successful; NULL otherwise.] SideEffects [The distance is returned as a side effect.] SeeAlso [cuddBddClosestCube createResult] ******************************************************************************/ static DdNode * separateCube( DdManager *dd, DdNode *f, CUDD_VALUE_TYPE *distance) { DdNode *cube, *t; /* One and zero are special cases because the distance is implied. */ if (Cudd_IsConstant(f)) { *distance = (f == DD_ONE(dd)) ? 0.0 : (1.0 + (CUDD_VALUE_TYPE) CUDD_CONST_INDEX); return(f); } /* Find out which branch points to the distance and replace the top ** node with one pointing to zero instead. */ t = cuddT(f); if (Cudd_IsConstant(t) && cuddV(t) <= 0) { #ifdef DD_DEBUG assert(!Cudd_IsConstant(cuddE(f)) || cuddE(f) == DD_ONE(dd)); #endif *distance = -cuddV(t); cube = cuddUniqueInter(dd, f->index, DD_ZERO(dd), cuddE(f)); } else { #ifdef DD_DEBUG assert(!Cudd_IsConstant(t) || t == DD_ONE(dd)); #endif *distance = -cuddV(cuddE(f)); cube = cuddUniqueInter(dd, f->index, t, DD_ZERO(dd)); } return(cube); } /* end of separateCube */ /**Function******************************************************************** Synopsis [Builds a result for cache storage.] Description [Builds a result for cache storage. Returns a pointer to the resulting ADD if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddBddClosestCube separateCube] ******************************************************************************/ static DdNode * createResult( DdManager *dd, unsigned int index, unsigned int phase, DdNode *cube, CUDD_VALUE_TYPE distance) { DdNode *res, *constant; /* Special case. The cube is either one or zero, and we do not ** add any variables. Hence, the result is also one or zero, ** and the distance remains implied by the value of the constant. */ if (index == CUDD_CONST_INDEX && Cudd_IsConstant(cube)) return(cube); constant = cuddUniqueConst(dd,-distance); if (constant == NULL) return(NULL); cuddRef(constant); if (index == CUDD_CONST_INDEX) { /* Replace the top node. */ if (cuddT(cube) == DD_ZERO(dd)) { res = cuddUniqueInter(dd,cube->index,constant,cuddE(cube)); } else { res = cuddUniqueInter(dd,cube->index,cuddT(cube),constant); } } else { /* Add a new top node. */ #ifdef DD_DEBUG assert(cuddI(dd,index) < cuddI(dd,cube->index)); #endif if (phase) { res = cuddUniqueInter(dd,index,cube,constant); } else { res = cuddUniqueInter(dd,index,constant,cube); } } if (res == NULL) { Cudd_RecursiveDeref(dd, constant); return(NULL); } cuddDeref(constant); /* safe because constant is part of res */ return(res); } /* end of createResult */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddRead.c000066400000000000000000000435561300674244400234000ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddRead.c] PackageName [cudd] Synopsis [Functions to read in a matrix] Description [External procedures included in this module:
      • Cudd_addRead()
      • Cudd_bddRead()
      ] SeeAlso [cudd_addHarwell.c] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddRead.c,v 1.6 2004/08/13 18:04:50 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Reads in a sparse matrix.] Description [Reads in a sparse matrix specified in a simple format. The first line of the input contains the numbers of rows and columns. The remaining lines contain the elements of the matrix, one per line. Given a background value (specified by the background field of the manager), only the values different from it are explicitly listed. Each foreground element is described by two integers, i.e., the row and column number, and a real number, i.e., the value.

      Cudd_addRead produces an ADD that depends on two sets of variables: x and y. The x variables (x\[0\] ... x\[nx-1\]) encode the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the column index. x\[0\] and y\[0\] are the most significant bits in the indices. The variables may already exist or may be created by the function. The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.

      On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. When Cudd_addRead creates the variable arrays, the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy. When some variables already exist Cudd_addRead expects the indices of the existing x variables to be bx+i*sx, and the indices of the existing y variables to be by+i*sy.

      m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. The ADD for the sparse matrix is returned in E, and its reference count is > 0. Cudd_addRead returns 1 in case of success; 0 otherwise.] SideEffects [nx and ny are set to the numbers of row and column variables. m and n are set to the numbers of rows and columns. x and y are possibly extended to represent the array of row and column variables. Similarly for xn and yn_, which hold on return from Cudd_addRead the complements of the row and column variables.] SeeAlso [Cudd_addHarwell Cudd_bddRead] ******************************************************************************/ int Cudd_addRead( FILE * fp /* input file pointer */, DdManager * dd /* DD manager */, DdNode ** E /* characteristic function of the graph */, DdNode *** x /* array of row variables */, DdNode *** y /* array of column variables */, DdNode *** xn /* array of complemented row variables */, DdNode *** yn_ /* array of complemented column variables */, int * nx /* number or row variables */, int * ny /* number or column variables */, int * m /* number of rows */, int * n /* number of columns */, int bx /* first index of row variables */, int sx /* step of row variables */, int by /* first index of column variables */, int sy /* step of column variables */) { DdNode *one, *zero; DdNode *w, *neW; DdNode *minterm1; int u, v, err, i, nv; int lnx, lny; CUDD_VALUE_TYPE val; DdNode **lx, **ly, **lxn, **lyn; one = DD_ONE(dd); zero = DD_ZERO(dd); err = fscanf(fp, "%d %d", &u, &v); if (err == EOF) { return(0); } else if (err != 2) { return(0); } *m = u; /* Compute the number of x variables. */ lx = *x; lxn = *xn; u--; /* row and column numbers start from 0 */ for (lnx=0; u > 0; lnx++) { u >>= 1; } /* Here we rely on the fact that REALLOC of a null pointer is ** translates to an ALLOC. */ if (lnx > *nx) { *x = lx = ABC_REALLOC(DdNode *, *x, lnx); if (lx == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } *xn = lxn = ABC_REALLOC(DdNode *, *xn, lnx); if (lxn == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } *n = v; /* Compute the number of y variables. */ ly = *y; lyn = *yn_; v--; /* row and column numbers start from 0 */ for (lny=0; v > 0; lny++) { v >>= 1; } /* Here we rely on the fact that REALLOC of a null pointer is ** translates to an ALLOC. */ if (lny > *ny) { *y = ly = ABC_REALLOC(DdNode *, *y, lny); if (ly == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } *yn_ = lyn = ABC_REALLOC(DdNode *, *yn_, lny); if (lyn == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } /* Create all new variables. */ for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { do { dd->reordered = 0; lx[i] = cuddUniqueInter(dd, nv, one, zero); } while (dd->reordered == 1); if (lx[i] == NULL) return(0); cuddRef(lx[i]); do { dd->reordered = 0; lxn[i] = cuddUniqueInter(dd, nv, zero, one); } while (dd->reordered == 1); if (lxn[i] == NULL) return(0); cuddRef(lxn[i]); } for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { do { dd->reordered = 0; ly[i] = cuddUniqueInter(dd, nv, one, zero); } while (dd->reordered == 1); if (ly[i] == NULL) return(0); cuddRef(ly[i]); do { dd->reordered = 0; lyn[i] = cuddUniqueInter(dd, nv, zero, one); } while (dd->reordered == 1); if (lyn[i] == NULL) return(0); cuddRef(lyn[i]); } *nx = lnx; *ny = lny; *E = dd->background; /* this call will never cause reordering */ cuddRef(*E); while (! feof(fp)) { err = fscanf(fp, "%d %d %lf", &u, &v, &val); if (err == EOF) { break; } else if (err != 3) { return(0); } else if (u >= *m || v >= *n || u < 0 || v < 0) { return(0); } minterm1 = one; cuddRef(minterm1); /* Build minterm1 corresponding to this arc */ for (i = lnx - 1; i>=0; i--) { if (u & 1) { w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]); } else { w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]); } if (w == NULL) { Cudd_RecursiveDeref(dd, minterm1); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, minterm1); minterm1 = w; u >>= 1; } for (i = lny - 1; i>=0; i--) { if (v & 1) { w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]); } else { w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]); } if (w == NULL) { Cudd_RecursiveDeref(dd, minterm1); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, minterm1); minterm1 = w; v >>= 1; } /* Create new constant node if necessary. ** This call will never cause reordering. */ neW = cuddUniqueConst(dd, val); if (neW == NULL) { Cudd_RecursiveDeref(dd, minterm1); return(0); } cuddRef(neW); w = Cudd_addIte(dd, minterm1, neW, *E); if (w == NULL) { Cudd_RecursiveDeref(dd, minterm1); Cudd_RecursiveDeref(dd, neW); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, minterm1); Cudd_RecursiveDeref(dd, neW); Cudd_RecursiveDeref(dd, *E); *E = w; } return(1); } /* end of Cudd_addRead */ /**Function******************************************************************** Synopsis [Reads in a graph (without labels) given as a list of arcs.] Description [Reads in a graph (without labels) given as an adjacency matrix. The first line of the input contains the numbers of rows and columns of the adjacency matrix. The remaining lines contain the arcs of the graph, one per line. Each arc is described by two integers, i.e., the row and column number, or the indices of the two endpoints. Cudd_bddRead produces a BDD that depends on two sets of variables: x and y. The x variables (x\[0\] ... x\[nx-1\]) encode the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the column index. x\[0\] and y\[0\] are the most significant bits in the indices. The variables may already exist or may be created by the function. The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.

      On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. When Cudd_bddRead creates the variable arrays, the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy. When some variables already exist, Cudd_bddRead expects the indices of the existing x variables to be bx+i*sx, and the indices of the existing y variables to be by+i*sy.

      m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. The BDD for the graph is returned in E, and its reference count is > 0. Cudd_bddRead returns 1 in case of success; 0 otherwise.] SideEffects [nx and ny are set to the numbers of row and column variables. m and n are set to the numbers of rows and columns. x and y are possibly extended to represent the array of row and column variables.] SeeAlso [Cudd_addHarwell Cudd_addRead] ******************************************************************************/ int Cudd_bddRead( FILE * fp /* input file pointer */, DdManager * dd /* DD manager */, DdNode ** E /* characteristic function of the graph */, DdNode *** x /* array of row variables */, DdNode *** y /* array of column variables */, int * nx /* number or row variables */, int * ny /* number or column variables */, int * m /* number of rows */, int * n /* number of columns */, int bx /* first index of row variables */, int sx /* step of row variables */, int by /* first index of column variables */, int sy /* step of column variables */) { DdNode *one, *zero; DdNode *w; DdNode *minterm1; int u, v, err, i, nv; int lnx, lny; DdNode **lx, **ly; one = DD_ONE(dd); zero = Cudd_Not(one); err = fscanf(fp, "%d %d", &u, &v); if (err == EOF) { return(0); } else if (err != 2) { return(0); } *m = u; /* Compute the number of x variables. */ lx = *x; u--; /* row and column numbers start from 0 */ for (lnx=0; u > 0; lnx++) { u >>= 1; } if (lnx > *nx) { *x = lx = ABC_REALLOC(DdNode *, *x, lnx); if (lx == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } *n = v; /* Compute the number of y variables. */ ly = *y; v--; /* row and column numbers start from 0 */ for (lny=0; v > 0; lny++) { v >>= 1; } if (lny > *ny) { *y = ly = ABC_REALLOC(DdNode *, *y, lny); if (ly == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } /* Create all new variables. */ for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { do { dd->reordered = 0; lx[i] = cuddUniqueInter(dd, nv, one, zero); } while (dd->reordered == 1); if (lx[i] == NULL) return(0); cuddRef(lx[i]); } for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { do { dd->reordered = 0; ly[i] = cuddUniqueInter(dd, nv, one, zero); } while (dd->reordered == 1); if (ly[i] == NULL) return(0); cuddRef(ly[i]); } *nx = lnx; *ny = lny; *E = zero; /* this call will never cause reordering */ cuddRef(*E); while (! feof(fp)) { err = fscanf(fp, "%d %d", &u, &v); if (err == EOF) { break; } else if (err != 2) { return(0); } else if (u >= *m || v >= *n || u < 0 || v < 0) { return(0); } minterm1 = one; cuddRef(minterm1); /* Build minterm1 corresponding to this arc. */ for (i = lnx - 1; i>=0; i--) { if (u & 1) { w = Cudd_bddAnd(dd, minterm1, lx[i]); } else { w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i])); } if (w == NULL) { Cudd_RecursiveDeref(dd, minterm1); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd,minterm1); minterm1 = w; u >>= 1; } for (i = lny - 1; i>=0; i--) { if (v & 1) { w = Cudd_bddAnd(dd, minterm1, ly[i]); } else { w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i])); } if (w == NULL) { Cudd_RecursiveDeref(dd, minterm1); return(0); } cuddRef(w); Cudd_RecursiveDeref(dd, minterm1); minterm1 = w; v >>= 1; } w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E)); if (w == NULL) { Cudd_RecursiveDeref(dd, minterm1); return(0); } w = Cudd_Not(w); cuddRef(w); Cudd_RecursiveDeref(dd, minterm1); Cudd_RecursiveDeref(dd, *E); *E = w; } return(1); } /* end of Cudd_bddRead */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddRef.c000066400000000000000000000546341300674244400232400ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddRef.c] PackageName [cudd] Synopsis [Functions that manipulate the reference counts.] Description [External procedures included in this module:

      • Cudd_Ref()
      • Cudd_RecursiveDeref()
      • Cudd_IterDerefBdd()
      • Cudd_DelayedDerefBdd()
      • Cudd_RecursiveDerefZdd()
      • Cudd_Deref()
      • Cudd_CheckZeroRef()
      Internal procedures included in this module:
      • cuddReclaim()
      • cuddReclaimZdd()
      • cuddClearDeathRow()
      • cuddShrinkDeathRow()
      • cuddIsInDeathRow()
      • cuddTimesInDeathRow()
      ] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.28 2004/08/13 18:04:50 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Increases the reference count of a node, if it is not saturated.] Description [] SideEffects [None] SeeAlso [Cudd_RecursiveDeref Cudd_Deref] ******************************************************************************/ void Cudd_Ref( DdNode * n) { n = Cudd_Regular(n); cuddSatInc(n->ref); } /* end of Cudd_Ref */ /**Function******************************************************************** Synopsis [Decreases the reference count of node n.] Description [Decreases the reference count of node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a DD that is no longer needed.] SideEffects [None] SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd] ******************************************************************************/ void Cudd_RecursiveDeref( DdManager * table, DdNode * n) { DdNode *N; int ord; DdNodePtr *stack = table->stack; int SP = 1; unsigned int live = table->keys - table->dead; if (live > table->peakLiveNodes) { table->peakLiveNodes = live; } N = Cudd_Regular(n); do { #ifdef DD_DEBUG assert(N->ref != 0); #endif if (N->ref == 1) { N->ref = 0; table->dead++; #ifdef DD_STATS table->nodesDropped++; #endif if (cuddIsConstant(N)) { table->constants.dead++; N = stack[--SP]; } else { ord = table->perm[N->index]; stack[SP++] = Cudd_Regular(cuddE(N)); table->subtables[ord].dead++; N = cuddT(N); } } else { cuddSatDec(N->ref); N = stack[--SP]; } } while (SP != 0); } /* end of Cudd_RecursiveDeref */ /**Function******************************************************************** Synopsis [Decreases the reference count of BDD node n.] Description [Decreases the reference count of node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a BDD that is no longer needed. It is more efficient than Cudd_RecursiveDeref, but it cannot be used on ADDs. The greater efficiency comes from being able to assume that no constant node will ever die as a result of a call to this procedure.] SideEffects [None] SeeAlso [Cudd_RecursiveDeref Cudd_DelayedDerefBdd] ******************************************************************************/ void Cudd_IterDerefBdd( DdManager * table, DdNode * n) { DdNode *N; int ord; DdNodePtr *stack = table->stack; int SP = 1; unsigned int live = table->keys - table->dead; if (live > table->peakLiveNodes) { table->peakLiveNodes = live; } N = Cudd_Regular(n); do { #ifdef DD_DEBUG assert(N->ref != 0); #endif if (N->ref == 1) { N->ref = 0; table->dead++; #ifdef DD_STATS table->nodesDropped++; #endif ord = table->perm[N->index]; stack[SP++] = Cudd_Regular(cuddE(N)); table->subtables[ord].dead++; N = cuddT(N); } else { cuddSatDec(N->ref); N = stack[--SP]; } } while (SP != 0); } /* end of Cudd_IterDerefBdd */ /**Function******************************************************************** Synopsis [Decreases the reference count of BDD node n.] Description [Enqueues node n for later dereferencing. If the queue is full decreases the reference count of the oldest node N to make room for n. If N dies, recursively decreases the reference counts of its children. It is used to dispose of a BDD that is currently not needed, but may be useful again in the near future. The dereferencing proper is done as in Cudd_IterDerefBdd.] SideEffects [None] SeeAlso [Cudd_RecursiveDeref Cudd_IterDerefBdd] ******************************************************************************/ void Cudd_DelayedDerefBdd( DdManager * table, DdNode * n) { DdNode *N; int ord; DdNodePtr *stack; int SP; unsigned int live = table->keys - table->dead; if (live > table->peakLiveNodes) { table->peakLiveNodes = live; } n = Cudd_Regular(n); #ifdef DD_DEBUG assert(n->ref != 0); #endif #ifdef DD_NO_DEATH_ROW N = n; #else if (cuddIsConstant(n) || n->ref > 1) { #ifdef DD_DEBUG assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table))); #endif cuddSatDec(n->ref); return; } N = table->deathRow[table->nextDead]; if (N != NULL) { #endif #ifdef DD_DEBUG assert(!Cudd_IsComplement(N)); #endif stack = table->stack; SP = 1; do { #ifdef DD_DEBUG assert(N->ref != 0); #endif if (N->ref == 1) { N->ref = 0; table->dead++; #ifdef DD_STATS table->nodesDropped++; #endif ord = table->perm[N->index]; stack[SP++] = Cudd_Regular(cuddE(N)); table->subtables[ord].dead++; N = cuddT(N); } else { cuddSatDec(N->ref); N = stack[--SP]; } } while (SP != 0); #ifndef DD_NO_DEATH_ROW } table->deathRow[table->nextDead] = n; /* Udate insertion point. */ table->nextDead++; table->nextDead &= table->deadMask; #if 0 if (table->nextDead == table->deathRowDepth) { if (table->deathRowDepth < table->looseUpTo / 2) { extern void (*MMoutOfMemory)(long); void (*saveHandler)(long) = MMoutOfMemory; DdNodePtr *newRow; MMoutOfMemory = Cudd_OutOfMem; newRow = ABC_REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth); MMoutOfMemory = saveHandler; if (newRow == NULL) { table->nextDead = 0; } else { int i; table->memused += table->deathRowDepth; i = table->deathRowDepth; table->deathRowDepth <<= 1; for (; i < table->deathRowDepth; i++) { newRow[i] = NULL; } table->deadMask = table->deathRowDepth - 1; table->deathRow = newRow; } } else { table->nextDead = 0; } } #endif #endif } /* end of Cudd_DelayedDerefBdd */ /**Function******************************************************************** Synopsis [Decreases the reference count of ZDD node n.] Description [Decreases the reference count of ZDD node n. If n dies, recursively decreases the reference counts of its children. It is used to dispose of a ZDD that is no longer needed.] SideEffects [None] SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref] ******************************************************************************/ void Cudd_RecursiveDerefZdd( DdManager * table, DdNode * n) { DdNode *N; int ord; DdNodePtr *stack = table->stack; int SP = 1; N = n; do { #ifdef DD_DEBUG assert(N->ref != 0); #endif cuddSatDec(N->ref); if (N->ref == 0) { table->deadZ++; #ifdef DD_STATS table->nodesDropped++; #endif #ifdef DD_DEBUG assert(!cuddIsConstant(N)); #endif ord = table->permZ[N->index]; stack[SP++] = cuddE(N); table->subtableZ[ord].dead++; N = cuddT(N); } else { N = stack[--SP]; } } while (SP != 0); } /* end of Cudd_RecursiveDerefZdd */ /**Function******************************************************************** Synopsis [Decreases the reference count of node.] Description [Decreases the reference count of node. It is primarily used in recursive procedures to decrease the ref count of a result node before returning it. This accomplishes the goal of removing the protection applied by a previous Cudd_Ref.] SideEffects [None] SeeAlso [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref] ******************************************************************************/ void Cudd_Deref( DdNode * node) { node = Cudd_Regular(node); cuddSatDec(node->ref); } /* end of Cudd_Deref */ /**Function******************************************************************** Synopsis [Checks the unique table for nodes with non-zero reference counts.] Description [Checks the unique table for nodes with non-zero reference counts. It is normally called before Cudd_Quit to make sure that there are no memory leaks due to missing Cudd_RecursiveDeref's. Takes into account that reference counts may saturate and that the basic constants and the projection functions are referenced by the manager. Returns the number of nodes with non-zero reference count. (Except for the cases mentioned above.)] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_CheckZeroRef( DdManager * manager) { int size; int i, j; int remain; /* the expected number of remaining references to one */ DdNodePtr *nodelist; DdNode *node; DdNode *sentinel = &(manager->sentinel); DdSubtable *subtable; int count = 0; int index; #ifndef DD_NO_DEATH_ROW cuddClearDeathRow(manager); #endif /* First look at the BDD/ADD subtables. */ remain = 1; /* reference from the manager */ size = manager->size; remain += 2 * size; /* reference from the BDD projection functions */ for (i = 0; i < size; i++) { subtable = &(manager->subtables[i]); nodelist = subtable->nodelist; for (j = 0; (unsigned) j < subtable->slots; j++) { node = nodelist[j]; while (node != sentinel) { if (node->ref != 0 && node->ref != DD_MAXREF) { index = (int) node->index; if (node != manager->vars[index]) { count++; } else { if (node->ref != 1) { count++; } } } node = node->next; } } } /* Then look at the ZDD subtables. */ size = manager->sizeZ; if (size) /* references from ZDD universe */ remain += 2; for (i = 0; i < size; i++) { subtable = &(manager->subtableZ[i]); nodelist = subtable->nodelist; for (j = 0; (unsigned) j < subtable->slots; j++) { node = nodelist[j]; while (node != NULL) { if (node->ref != 0 && node->ref != DD_MAXREF) { index = (int) node->index; if (node == manager->univ[manager->permZ[index]]) { if (node->ref > 2) { count++; } } else { count++; } } node = node->next; } } } /* Now examine the constant table. Plusinfinity, minusinfinity, and ** zero are referenced by the manager. One is referenced by the ** manager, by the ZDD universe, and by all projection functions. ** All other nodes should have no references. */ nodelist = manager->constants.nodelist; for (j = 0; (unsigned) j < manager->constants.slots; j++) { node = nodelist[j]; while (node != NULL) { if (node->ref != 0 && node->ref != DD_MAXREF) { if (node == manager->one) { if ((int) node->ref != remain) { count++; } } else if (node == manager->zero || node == manager->plusinfinity || node == manager->minusinfinity) { if (node->ref != 1) { count++; } } else { count++; } } node = node->next; } } return(count); } /* end of Cudd_CheckZeroRef */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Brings children of a dead node back.] Description [] SideEffects [None] SeeAlso [cuddReclaimZdd] ******************************************************************************/ void cuddReclaim( DdManager * table, DdNode * n) { DdNode *N; int ord; DdNodePtr *stack = table->stack; int SP = 1; double initialDead = table->dead; N = Cudd_Regular(n); #ifdef DD_DEBUG assert(N->ref == 0); #endif do { if (N->ref == 0) { N->ref = 1; table->dead--; if (cuddIsConstant(N)) { table->constants.dead--; N = stack[--SP]; } else { ord = table->perm[N->index]; stack[SP++] = Cudd_Regular(cuddE(N)); table->subtables[ord].dead--; N = cuddT(N); } } else { cuddSatInc(N->ref); N = stack[--SP]; } } while (SP != 0); N = Cudd_Regular(n); cuddSatDec(N->ref); table->reclaimed += initialDead - table->dead; } /* end of cuddReclaim */ /**Function******************************************************************** Synopsis [Brings children of a dead ZDD node back.] Description [] SideEffects [None] SeeAlso [cuddReclaim] ******************************************************************************/ void cuddReclaimZdd( DdManager * table, DdNode * n) { DdNode *N; int ord; DdNodePtr *stack = table->stack; int SP = 1; N = n; #ifdef DD_DEBUG assert(N->ref == 0); #endif do { cuddSatInc(N->ref); if (N->ref == 1) { table->deadZ--; table->reclaimed++; #ifdef DD_DEBUG assert(!cuddIsConstant(N)); #endif ord = table->permZ[N->index]; stack[SP++] = cuddE(N); table->subtableZ[ord].dead--; N = cuddT(N); } else { N = stack[--SP]; } } while (SP != 0); cuddSatDec(n->ref); } /* end of cuddReclaimZdd */ /**Function******************************************************************** Synopsis [Shrinks the death row.] Description [Shrinks the death row by a factor of four.] SideEffects [None] SeeAlso [cuddClearDeathRow] ******************************************************************************/ void cuddShrinkDeathRow( DdManager *table) { #ifndef DD_NO_DEATH_ROW int i; if (table->deathRowDepth > 3) { for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) { if (table->deathRow[i] == NULL) break; Cudd_IterDerefBdd(table,table->deathRow[i]); table->deathRow[i] = NULL; } table->deathRowDepth /= 4; table->deadMask = table->deathRowDepth - 1; if ((unsigned) table->nextDead > table->deadMask) { table->nextDead = 0; } table->deathRow = ABC_REALLOC(DdNodePtr, table->deathRow, table->deathRowDepth); } #endif } /* end of cuddShrinkDeathRow */ /**Function******************************************************************** Synopsis [Clears the death row.] Description [] SideEffects [None] SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef cuddGarbageCollect] ******************************************************************************/ void cuddClearDeathRow( DdManager *table) { #ifndef DD_NO_DEATH_ROW int i; for (i = 0; i < table->deathRowDepth; i++) { if (table->deathRow[i] == NULL) break; Cudd_IterDerefBdd(table,table->deathRow[i]); table->deathRow[i] = NULL; } #ifdef DD_DEBUG for (; i < table->deathRowDepth; i++) { assert(table->deathRow[i] == NULL); } #endif table->nextDead = 0; #endif } /* end of cuddClearDeathRow */ /**Function******************************************************************** Synopsis [Checks whether a node is in the death row.] Description [Checks whether a node is in the death row. Returns the position of the first occurrence if the node is present; -1 otherwise.] SideEffects [None] SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow] ******************************************************************************/ int cuddIsInDeathRow( DdManager *dd, DdNode *f) { #ifndef DD_NO_DEATH_ROW int i; for (i = 0; i < dd->deathRowDepth; i++) { if (f == dd->deathRow[i]) { return(i); } } #endif return(-1); } /* end of cuddIsInDeathRow */ /**Function******************************************************************** Synopsis [Counts how many times a node is in the death row.] Description [] SideEffects [None] SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow] ******************************************************************************/ int cuddTimesInDeathRow( DdManager *dd, DdNode *f) { int count = 0; #ifndef DD_NO_DEATH_ROW int i; for (i = 0; i < dd->deathRowDepth; i++) { count += f == dd->deathRow[i]; } #endif return(count); } /* end of cuddTimesInDeathRow */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddReorder.c000066400000000000000000002051451300674244400241210ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddReorder.c] PackageName [cudd] Synopsis [Functions for dynamic variable reordering.] Description [External procedures included in this file:
      • Cudd_ReduceHeap()
      • Cudd_ShuffleHeap()
      Internal procedures included in this module:
      • cuddDynamicAllocNode()
      • cuddSifting()
      • cuddSwapping()
      • cuddNextHigh()
      • cuddNextLow()
      • cuddSwapInPlace()
      • cuddBddAlignToZdd()
      Static procedures included in this module:
      • ddUniqueCompare()
      • ddSwapAny()
      • ddSiftingAux()
      • ddSiftingUp()
      • ddSiftingDown()
      • ddSiftingBackward()
      • ddReorderPreprocess()
      • ddReorderPostprocess()
      • ddShuffle()
      • ddSiftUp()
      • bddFixTree()
      ] Author [Shipra Panda, Bernard Plessier, Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DD_MAX_SUBTABLE_SPARSITY 8 #define DD_SHRINK_FACTOR 2 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.69 2009/02/21 18:24:10 fabio Exp $"; #endif static int *entry; int ddTotalNumberSwapping; #ifdef DD_STATS int ddTotalNISwaps; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int ddUniqueCompare (int *ptrX, int *ptrY); static Move * ddSwapAny (DdManager *table, int x, int y); static int ddSiftingAux (DdManager *table, int x, int xLow, int xHigh); static Move * ddSiftingUp (DdManager *table, int y, int xLow); static Move * ddSiftingDown (DdManager *table, int x, int xHigh); static int ddSiftingBackward (DdManager *table, int size, Move *moves); static int ddReorderPreprocess (DdManager *table); static int ddReorderPostprocess (DdManager *table); static int ddShuffle (DdManager *table, int *permutation); static int ddSiftUp (DdManager *table, int x, int xLow); static void bddFixTree (DdManager *table, MtrNode *treenode); static int ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm); static int ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Main dynamic reordering routine.] Description [Main dynamic reordering routine. Calls one of the possible reordering procedures:
      • Swapping
      • Sifting
      • Symmetric Sifting
      • Group Sifting
      • Window Permutation
      • Simulated Annealing
      • Genetic Algorithm
      • Dynamic Programming (exact)
      For sifting, symmetric sifting, group sifting, and window permutation it is possible to request reordering to convergence.

      The core of all methods is the reordering procedure cuddSwapInPlace() which swaps two adjacent variables and is based on Rudell's paper. Returns 1 in case of success; 0 otherwise. In the case of symmetric sifting (with and without convergence) returns 1 plus the number of symmetric variables, in case of success.] SideEffects [Changes the variable order for all diagrams and clears the cache.] ******************************************************************************/ int Cudd_ReduceHeap( DdManager * table /* DD manager */, Cudd_ReorderingType heuristic /* method used for reordering */, int minsize /* bound below which no reordering occurs */) { DdHook *hook; int result; unsigned int nextDyn; #ifdef DD_STATS unsigned int initialSize; unsigned int finalSize; #endif long localTime; /* Don't reorder if there are too many dead nodes. */ if (table->keys - table->dead < (unsigned) minsize) return(1); if (heuristic == CUDD_REORDER_SAME) { heuristic = table->autoMethod; } if (heuristic == CUDD_REORDER_NONE) { return(1); } /* This call to Cudd_ReduceHeap does initiate reordering. Therefore ** we count it. */ table->reorderings++; localTime = util_cpu_time(); /* Run the hook functions. */ hook = table->preReorderingHook; while (hook != NULL) { int res = (hook->f)(table, "BDD", (void *)heuristic); if (res == 0) return(0); hook = hook->next; } if (!ddReorderPreprocess(table)) return(0); ddTotalNumberSwapping = 0; if (table->keys > table->peakLiveNodes) { table->peakLiveNodes = table->keys; } #ifdef DD_STATS initialSize = table->keys - table->isolated; ddTotalNISwaps = 0; switch(heuristic) { case CUDD_REORDER_RANDOM: case CUDD_REORDER_RANDOM_PIVOT: (void) fprintf(table->out,"#:I_RANDOM "); break; case CUDD_REORDER_SIFT: case CUDD_REORDER_SIFT_CONVERGE: case CUDD_REORDER_SYMM_SIFT: case CUDD_REORDER_SYMM_SIFT_CONV: case CUDD_REORDER_GROUP_SIFT: case CUDD_REORDER_GROUP_SIFT_CONV: (void) fprintf(table->out,"#:I_SIFTING "); break; case CUDD_REORDER_WINDOW2: case CUDD_REORDER_WINDOW3: case CUDD_REORDER_WINDOW4: case CUDD_REORDER_WINDOW2_CONV: case CUDD_REORDER_WINDOW3_CONV: case CUDD_REORDER_WINDOW4_CONV: (void) fprintf(table->out,"#:I_WINDOW "); break; case CUDD_REORDER_ANNEALING: (void) fprintf(table->out,"#:I_ANNEAL "); break; case CUDD_REORDER_GENETIC: (void) fprintf(table->out,"#:I_GENETIC "); break; case CUDD_REORDER_LINEAR: case CUDD_REORDER_LINEAR_CONVERGE: (void) fprintf(table->out,"#:I_LINSIFT "); break; case CUDD_REORDER_EXACT: (void) fprintf(table->out,"#:I_EXACT "); break; default: return(0); } (void) fprintf(table->out,"%8d: initial size",initialSize); #endif /* See if we should use alternate threshold for maximum growth. */ if (table->reordCycle && table->reorderings % table->reordCycle == 0) { double saveGrowth = table->maxGrowth; table->maxGrowth = table->maxGrowthAlt; result = cuddTreeSifting(table,heuristic); table->maxGrowth = saveGrowth; } else { result = cuddTreeSifting(table,heuristic); } #ifdef DD_STATS (void) fprintf(table->out,"\n"); finalSize = table->keys - table->isolated; (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", ((double)(util_cpu_time() - localTime)/1000.0)); (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", ddTotalNumberSwapping); (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps); #endif if (result == 0) return(0); if (!ddReorderPostprocess(table)) return(0); if (table->realign) { if (!cuddZddAlignToBdd(table)) return(0); } nextDyn = (table->keys - table->constants.keys + 1) * DD_DYN_RATIO + table->constants.keys; if (table->reorderings < 20 || nextDyn > table->nextDyn) table->nextDyn = nextDyn; else table->nextDyn += 20; table->reordered = 1; /* Run hook functions. */ hook = table->postReorderingHook; while (hook != NULL) { int res = (hook->f)(table, "BDD", (void *)localTime); if (res == 0) return(0); hook = hook->next; } /* Update cumulative reordering time. */ table->reordTime += util_cpu_time() - localTime; return(result); } /* end of Cudd_ReduceHeap */ /**Function******************************************************************** Synopsis [Reorders variables according to given permutation.] Description [Reorders variables according to given permutation. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use. Returns 1 in case of success; 0 otherwise.] SideEffects [Changes the variable order for all diagrams and clears the cache.] SeeAlso [Cudd_ReduceHeap] ******************************************************************************/ int Cudd_ShuffleHeap( DdManager * table /* DD manager */, int * permutation /* required variable permutation */) { int result; int i; int identity = 1; int *perm; /* Don't waste time in case of identity permutation. */ for (i = 0; i < table->size; i++) { if (permutation[i] != table->invperm[i]) { identity = 0; break; } } if (identity == 1) { return(1); } if (!ddReorderPreprocess(table)) return(0); if (table->keys > table->peakLiveNodes) { table->peakLiveNodes = table->keys; } perm = ABC_ALLOC(int, table->size); for (i = 0; i < table->size; i++) perm[permutation[i]] = i; if (!ddCheckPermuation(table,table->tree,perm,permutation)) { ABC_FREE(perm); return(0); } if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) { ABC_FREE(perm); return(0); } ABC_FREE(perm); result = ddShuffle(table,permutation); if (!ddReorderPostprocess(table)) return(0); return(result); } /* end of Cudd_ShuffleHeap */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Dynamically allocates a Node.] Description [Dynamically allocates a Node. This procedure is similar to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage collection, because during reordering there are no dead nodes. Returns a pointer to a new node if successful; NULL is memory is full.] SideEffects [None] SeeAlso [cuddAllocNode] ******************************************************************************/ DdNode * cuddDynamicAllocNode( DdManager * table) { int i; DdNodePtr *mem; DdNode *list, *node; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; if (table->nextFree == NULL) { /* free list is empty */ /* Try to allocate a new block. */ saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; // mem = (DdNodePtr *) ABC_ALLOC(DdNode, DD_MEM_CHUNK + 1); mem = (DdNodePtr *) ABC_ALLOC(DdNode, DD_MEM_CHUNK + 2); MMoutOfMemory = saveHandler; if (mem == NULL && table->stash != NULL) { ABC_FREE(table->stash); table->stash = NULL; /* Inhibit resizing of tables. */ table->maxCacheHard = table->cacheSlots - 1; table->cacheSlack = - (int) (table->cacheSlots + 1); for (i = 0; i < table->size; i++) { table->subtables[i].maxKeys <<= 2; } // mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 1); mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 2); } if (mem == NULL) { /* Out of luck. Call the default handler to do ** whatever it specifies for a failed malloc. If this ** handler returns, then set error code, print ** warning, and return. */ (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); table->errorCode = CUDD_MEMORY_OUT; #ifdef DD_VERBOSE (void) fprintf(table->err, "cuddDynamicAllocNode: out of memory"); (void) fprintf(table->err,"Memory in use = %lu\n", table->memused); #endif return(NULL); } else { /* successful allocation; slice memory */ unsigned long offset; table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); mem[0] = (DdNode *) table->memoryList; table->memoryList = mem; /* Here we rely on the fact that the size of a DdNode is a ** power of 2 and a multiple of the size of a pointer. ** If we align one node, all the others will be aligned ** as well. */ // offset = (unsigned long) mem & (sizeof(DdNode) - 1); // mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); offset = (unsigned long) mem & (32 - 1); mem += (32 - offset) / sizeof(DdNodePtr); #ifdef DD_DEBUG // assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0); assert(((unsigned long) mem & (32 - 1)) == 0); #endif list = (DdNode *) mem; i = 1; do { list[i - 1].ref = 0; list[i - 1].next = &list[i]; } while (++i < DD_MEM_CHUNK); list[DD_MEM_CHUNK-1].ref = 0; list[DD_MEM_CHUNK - 1].next = NULL; table->nextFree = &list[0]; } } /* if free list empty */ node = table->nextFree; table->nextFree = node->next; return (node); } /* end of cuddDynamicAllocNode */ /**Function******************************************************************** Synopsis [Implementation of Rudell's sifting algorithm.] Description [Implementation of Rudell's sifting algorithm. Assumes that no dead nodes are present.

      1. Order all the variables according to the number of entries in each unique table.
      2. Sift the variable up and down, remembering each time the total size of the DD heap.
      3. Select the best permutation.
      4. Repeat 3 and 4 for all variables.
      Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ int cuddSifting( DdManager * table, int lower, int upper) { int i; int *var; int size; int x; int result; #ifdef DD_STATS int previousSize; #endif size = table->size; /* Find order in which to sift variables. */ var = NULL; entry = ABC_ALLOC(int,size); if (entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddSiftingOutOfMem; } var = ABC_ALLOC(int,size); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddSiftingOutOfMem; } for (i = 0; i < size; i++) { x = table->perm[i]; entry[i] = table->subtables[x].keys; var[i] = i; } qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare); /* Now sift. */ for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { if (ddTotalNumberSwapping >= table->siftMaxSwap) break; x = table->perm[var[i]]; if (x < lower || x > upper || table->subtables[x].bindVar == 1) continue; #ifdef DD_STATS previousSize = table->keys - table->isolated; #endif result = ddSiftingAux(table, x, lower, upper); if (!result) goto cuddSiftingOutOfMem; #ifdef DD_STATS if (table->keys < (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"-"); } else if (table->keys > (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"+"); /* should never happen */ (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } ABC_FREE(var); ABC_FREE(entry); return(1); cuddSiftingOutOfMem: if (entry != NULL) ABC_FREE(entry); if (var != NULL) ABC_FREE(var); return(0); } /* end of cuddSifting */ /**Function******************************************************************** Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] Description [Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps.
      1. Select two variables (RANDOM or HEURISTIC).
      2. Permute these variables.
      3. If the nodes have decreased accept the permutation.
      4. Otherwise reconstruct the original heap.
      5. Loop.
      Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ int cuddSwapping( DdManager * table, int lower, int upper, Cudd_ReorderingType heuristic) { int i, j; int max, keys; int nvars; int x, y; int iterate; int previousSize; Move *moves, *move; int pivot = -1; int modulo; int result; #ifdef DD_DEBUG /* Sanity check */ assert(lower >= 0 && upper < table->size && lower <= upper); #endif nvars = upper - lower + 1; iterate = nvars; for (i = 0; i < iterate; i++) { if (ddTotalNumberSwapping >= table->siftMaxSwap) break; if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { max = -1; for (j = lower; j <= upper; j++) { if ((keys = table->subtables[j].keys) > max) { max = keys; pivot = j; } } modulo = upper - pivot; if (modulo == 0) { y = pivot; } else{ y = pivot + 1 + ((int) Cudd_Random() % modulo); } modulo = pivot - lower - 1; if (modulo < 1) { x = lower; } else{ do { x = (int) Cudd_Random() % modulo; } while (x == y); } } else { x = ((int) Cudd_Random() % nvars) + lower; do { y = ((int) Cudd_Random() % nvars) + lower; } while (x == y); } previousSize = table->keys - table->isolated; moves = ddSwapAny(table,x,y); if (moves == NULL) goto cuddSwappingOutOfMem; result = ddSiftingBackward(table,previousSize,moves); if (!result) goto cuddSwappingOutOfMem; while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } #ifdef DD_STATS if (table->keys < (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"-"); } else if (table->keys > (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"+"); /* should never happen */ } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif #if 0 (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n", table->keys - table->isolated); #endif } return(1); cuddSwappingOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(0); } /* end of cuddSwapping */ /**Function******************************************************************** Synopsis [Finds the next subtable with a larger index.] Description [Finds the next subtable with a larger index. Returns the index.] SideEffects [None] SeeAlso [cuddNextLow] ******************************************************************************/ int cuddNextHigh( DdManager * table, int x) { return(x+1); } /* end of cuddNextHigh */ /**Function******************************************************************** Synopsis [Finds the next subtable with a smaller index.] Description [Finds the next subtable with a smaller index. Returns the index.] SideEffects [None] SeeAlso [cuddNextHigh] ******************************************************************************/ int cuddNextLow( DdManager * table, int x) { return(x-1); } /* end of cuddNextLow */ /**Function******************************************************************** Synopsis [Swaps two adjacent variables.] Description [Swaps two adjacent variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddSwapInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ int cuddSwapInPlace( DdManager * table, int x, int y) { DdNodePtr *xlist, *ylist; int xindex, yindex; int xslots, yslots; int xshift, yshift; int oldxkeys, oldykeys; int newxkeys, newykeys; int comple, newcomplement; int i; Cudd_VariableType varType; Cudd_LazyGroupType groupType; int posn; int isolated; DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; DdNode *g,*next; DdNodePtr *previousP; DdNode *tmp; DdNode *sentinel = &(table->sentinel); extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; #ifdef DD_DEBUG int count,idcheck; #endif #ifdef DD_DEBUG assert(x < y); assert(cuddNextHigh(table,x) == y); assert(table->subtables[x].keys != 0); assert(table->subtables[y].keys != 0); assert(table->subtables[x].dead == 0); assert(table->subtables[y].dead == 0); #endif ddTotalNumberSwapping++; /* Get parameters of x subtable. */ xindex = table->invperm[x]; xlist = table->subtables[x].nodelist; oldxkeys = table->subtables[x].keys; xslots = table->subtables[x].slots; xshift = table->subtables[x].shift; /* Get parameters of y subtable. */ yindex = table->invperm[y]; ylist = table->subtables[y].nodelist; oldykeys = table->subtables[y].keys; yslots = table->subtables[y].slots; yshift = table->subtables[y].shift; if (!cuddTestInteract(table,xindex,yindex)) { #ifdef DD_STATS ddTotalNISwaps++; #endif newxkeys = oldxkeys; newykeys = oldykeys; } else { newxkeys = 0; newykeys = oldykeys; /* Check whether the two projection functions involved in this ** swap are isolated. At the end, we'll be able to tell how many ** isolated projection functions are there by checking only these ** two functions again. This is done to eliminate the isolated ** projection functions from the node count. */ isolated = - ((table->vars[xindex]->ref == 1) + (table->vars[yindex]->ref == 1)); /* The nodes in the x layer that do not depend on ** y will stay there; the others are put in a chain. ** The chain is handled as a LIFO; g points to the beginning. */ g = NULL; if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) && oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) { for (i = 0; i < xslots; i++) { previousP = &(xlist[i]); f = *previousP; while (f != sentinel) { next = f->next; f1 = cuddT(f); f0 = cuddE(f); if (f1->index != (DdHalfWord) yindex && Cudd_Regular(f0)->index != (DdHalfWord) yindex) { /* stays */ newxkeys++; *previousP = f; previousP = &(f->next); } else { f->index = yindex; f->next = g; g = f; } f = next; } /* while there are elements in the collision chain */ *previousP = sentinel; } /* for each slot of the x subtable */ } else { /* resize xlist */ DdNode *h = NULL; DdNodePtr *newxlist; unsigned int newxslots; int newxshift; /* Empty current xlist. Nodes that stay go to list h; ** nodes that move go to list g. */ for (i = 0; i < xslots; i++) { f = xlist[i]; while (f != sentinel) { next = f->next; f1 = cuddT(f); f0 = cuddE(f); if (f1->index != (DdHalfWord) yindex && Cudd_Regular(f0)->index != (DdHalfWord) yindex) { /* stays */ f->next = h; h = f; newxkeys++; } else { f->index = yindex; f->next = g; g = f; } f = next; } /* while there are elements in the collision chain */ } /* for each slot of the x subtable */ /* Decide size of new subtable. */ newxshift = xshift; newxslots = xslots; while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) { newxshift--; newxslots <<= 1; } while ((unsigned) oldxkeys < newxslots && newxslots > table->initSlots) { newxshift++; newxslots >>= 1; } /* Try to allocate new table. Be ready to back off. */ saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; newxlist = ABC_ALLOC(DdNodePtr, newxslots); MMoutOfMemory = saveHandler; if (newxlist == NULL) { (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i); newxlist = xlist; newxslots = xslots; newxshift = xshift; } else { table->slots += ((int) newxslots - xslots); table->minDead = (unsigned) (table->gcFrac * (double) table->slots); table->cacheSlack = (int) ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO * table->slots) - 2 * (int) table->cacheSlots; table->memused += ((int) newxslots - xslots) * sizeof(DdNodePtr); ABC_FREE(xlist); xslots = newxslots; xshift = newxshift; xlist = newxlist; } /* Initialize new subtable. */ for (i = 0; i < xslots; i++) { xlist[i] = sentinel; } /* Move nodes that were parked in list h to their new home. */ f = h; while (f != NULL) { next = f->next; f1 = cuddT(f); f0 = cuddE(f); /* Check xlist for pair (f11,f01). */ posn = ddHash(cuddF2L(f1), cuddF2L(f0), xshift); /* For each element tmp in collision list xlist[posn]. */ previousP = &(xlist[posn]); tmp = *previousP; while (f1 < cuddT(tmp)) { previousP = &(tmp->next); tmp = *previousP; } while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) { previousP = &(tmp->next); tmp = *previousP; } f->next = *previousP; *previousP = f; f = next; } } #ifdef DD_COUNT table->swapSteps += oldxkeys - newxkeys; #endif /* Take care of the x nodes that must be re-expressed. ** They form a linked list pointed by g. Their index has been ** already changed to yindex. */ f = g; while (f != NULL) { next = f->next; /* Find f1, f0, f11, f10, f01, f00. */ f1 = cuddT(f); #ifdef DD_DEBUG assert(!(Cudd_IsComplement(f1))); #endif if ((int) f1->index == yindex) { f11 = cuddT(f1); f10 = cuddE(f1); } else { f11 = f10 = f1; } #ifdef DD_DEBUG assert(!(Cudd_IsComplement(f11))); #endif f0 = cuddE(f); comple = Cudd_IsComplement(f0); f0 = Cudd_Regular(f0); if ((int) f0->index == yindex) { f01 = cuddT(f0); f00 = cuddE(f0); } else { f01 = f00 = f0; } if (comple) { f01 = Cudd_Not(f01); f00 = Cudd_Not(f00); } /* Decrease ref count of f1. */ cuddSatDec(f1->ref); /* Create the new T child. */ if (f11 == f01) { newf1 = f11; cuddSatInc(newf1->ref); } else { /* Check xlist for triple (xindex,f11,f01). */ posn = ddHash(cuddF2L(f11), cuddF2L(f01), xshift); /* For each element newf1 in collision list xlist[posn]. */ previousP = &(xlist[posn]); newf1 = *previousP; while (f11 < cuddT(newf1)) { previousP = &(newf1->next); newf1 = *previousP; } while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) { previousP = &(newf1->next); newf1 = *previousP; } if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { cuddSatInc(newf1->ref); } else { /* no match */ newf1 = cuddDynamicAllocNode(table); if (newf1 == NULL) goto cuddSwapOutOfMem; newf1->index = xindex; newf1->ref = 1; cuddT(newf1) = f11; cuddE(newf1) = f01; /* Insert newf1 in the collision list xlist[posn]; ** increase the ref counts of f11 and f01. */ newxkeys++; newf1->next = *previousP; *previousP = newf1; cuddSatInc(f11->ref); tmp = Cudd_Regular(f01); cuddSatInc(tmp->ref); } } cuddT(f) = newf1; #ifdef DD_DEBUG assert(!(Cudd_IsComplement(newf1))); #endif /* Do the same for f0, keeping complement dots into account. */ /* Decrease ref count of f0. */ tmp = Cudd_Regular(f0); cuddSatDec(tmp->ref); /* Create the new E child. */ if (f10 == f00) { newf0 = f00; tmp = Cudd_Regular(newf0); cuddSatInc(tmp->ref); } else { /* make sure f10 is regular */ newcomplement = Cudd_IsComplement(f10); if (newcomplement) { f10 = Cudd_Not(f10); f00 = Cudd_Not(f00); } /* Check xlist for triple (xindex,f10,f00). */ posn = ddHash(cuddF2L(f10), cuddF2L(f00), xshift); /* For each element newf0 in collision list xlist[posn]. */ previousP = &(xlist[posn]); newf0 = *previousP; while (f10 < cuddT(newf0)) { previousP = &(newf0->next); newf0 = *previousP; } while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) { previousP = &(newf0->next); newf0 = *previousP; } if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { cuddSatInc(newf0->ref); } else { /* no match */ newf0 = cuddDynamicAllocNode(table); if (newf0 == NULL) goto cuddSwapOutOfMem; newf0->index = xindex; newf0->ref = 1; cuddT(newf0) = f10; cuddE(newf0) = f00; /* Insert newf0 in the collision list xlist[posn]; ** increase the ref counts of f10 and f00. */ newxkeys++; newf0->next = *previousP; *previousP = newf0; cuddSatInc(f10->ref); tmp = Cudd_Regular(f00); cuddSatInc(tmp->ref); } if (newcomplement) { newf0 = Cudd_Not(newf0); } } cuddE(f) = newf0; /* Insert the modified f in ylist. ** The modified f does not already exists in ylist. ** (Because of the uniqueness of the cofactors.) */ posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), yshift); newykeys++; previousP = &(ylist[posn]); tmp = *previousP; while (newf1 < cuddT(tmp)) { previousP = &(tmp->next); tmp = *previousP; } while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { previousP = &(tmp->next); tmp = *previousP; } f->next = *previousP; *previousP = f; f = next; } /* while f != NULL */ /* GC the y layer. */ /* For each node f in ylist. */ for (i = 0; i < yslots; i++) { previousP = &(ylist[i]); f = *previousP; while (f != sentinel) { next = f->next; if (f->ref == 0) { tmp = cuddT(f); cuddSatDec(tmp->ref); tmp = Cudd_Regular(cuddE(f)); cuddSatDec(tmp->ref); cuddDeallocNode(table,f); newykeys--; } else { *previousP = f; previousP = &(f->next); } f = next; } /* while f */ *previousP = sentinel; } /* for i */ #ifdef DD_DEBUG #if 0 (void) fprintf(table->out,"Swapping %d and %d\n",x,y); #endif count = 0; idcheck = 0; for (i = 0; i < yslots; i++) { f = ylist[i]; while (f != sentinel) { count++; if (f->index != (DdHalfWord) yindex) idcheck++; f = f->next; } } if (count != newykeys) { (void) fprintf(table->out, "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n", oldykeys,newykeys,count); } if (idcheck != 0) (void) fprintf(table->out, "Error in id's of ylist\twrong id's = %d\n", idcheck); count = 0; idcheck = 0; for (i = 0; i < xslots; i++) { f = xlist[i]; while (f != sentinel) { count++; if (f->index != (DdHalfWord) xindex) idcheck++; f = f->next; } } if (count != newxkeys) { (void) fprintf(table->out, "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n", oldxkeys,newxkeys,count); } if (idcheck != 0) (void) fprintf(table->out, "Error in id's of xlist\twrong id's = %d\n", idcheck); #endif isolated += (table->vars[xindex]->ref == 1) + (table->vars[yindex]->ref == 1); table->isolated += isolated; } /* Set the appropriate fields in table. */ table->subtables[x].nodelist = ylist; table->subtables[x].slots = yslots; table->subtables[x].shift = yshift; table->subtables[x].keys = newykeys; table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; i = table->subtables[x].bindVar; table->subtables[x].bindVar = table->subtables[y].bindVar; table->subtables[y].bindVar = i; /* Adjust filds for lazy sifting. */ varType = table->subtables[x].varType; table->subtables[x].varType = table->subtables[y].varType; table->subtables[y].varType = varType; i = table->subtables[x].pairIndex; table->subtables[x].pairIndex = table->subtables[y].pairIndex; table->subtables[y].pairIndex = i; i = table->subtables[x].varHandled; table->subtables[x].varHandled = table->subtables[y].varHandled; table->subtables[y].varHandled = i; groupType = table->subtables[x].varToBeGrouped; table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped; table->subtables[y].varToBeGrouped = groupType; table->subtables[y].nodelist = xlist; table->subtables[y].slots = xslots; table->subtables[y].shift = xshift; table->subtables[y].keys = newxkeys; table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; table->perm[xindex] = y; table->perm[yindex] = x; table->invperm[x] = yindex; table->invperm[y] = xindex; table->keys += newxkeys + newykeys - oldxkeys - oldykeys; return(table->keys - table->isolated); cuddSwapOutOfMem: (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n"); return (0); } /* end of cuddSwapInPlace */ /**Function******************************************************************** Synopsis [Reorders BDD variables according to the order of the ZDD variables.] Description [Reorders BDD variables according to the order of the ZDD variables. This function can be called at the end of ZDD reordering to insure that the order of the BDD variables is consistent with the order of the ZDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M be the ratio of the two numbers. cuddBddAlignToZdd then considers the ZDD variables from M*i to (M+1)*i-1 as corresponding to BDD variable i. This function should be normally called from Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.] SideEffects [Changes the BDD variable order for all diagrams and performs garbage collection of the BDD unique table.] SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap] ******************************************************************************/ int cuddBddAlignToZdd( DdManager * table /* DD manager */) { int *invperm; /* permutation array */ int M; /* ratio of ZDD variables to BDD variables */ int i; /* loop index */ int result; /* return value */ /* We assume that a ratio of 0 is OK. */ if (table->size == 0) return(1); M = table->sizeZ / table->size; /* Check whether the number of ZDD variables is a multiple of the ** number of BDD variables. */ if (M * table->size != table->sizeZ) return(0); /* Create and initialize the inverse permutation array. */ invperm = ABC_ALLOC(int,table->size); if (invperm == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < table->sizeZ; i += M) { int indexZ = table->invpermZ[i]; int index = indexZ / M; invperm[i / M] = index; } /* Eliminate dead nodes. Do not scan the cache again, because we ** assume that Cudd_zddReduceHeap has already cleared it. */ cuddGarbageCollect(table,0); /* Initialize number of isolated projection functions. */ table->isolated = 0; for (i = 0; i < table->size; i++) { if (table->vars[i]->ref == 1) table->isolated++; } /* Initialize the interaction matrix. */ result = cuddInitInteract(table); if (result == 0) return(0); result = ddShuffle(table, invperm); ABC_FREE(invperm); /* Free interaction matrix. */ ABC_FREE(table->interact); /* Fix the BDD variable group tree. */ bddFixTree(table,table->tree); return(result); } /* end of cuddBddAlignToZdd */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Comparison function used by qsort.] Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.] SideEffects [None] ******************************************************************************/ static int ddUniqueCompare( int * ptrX, int * ptrY) { #if 0 if (entry[*ptrY] == entry[*ptrX]) { return((*ptrX) - (*ptrY)); } #endif return(entry[*ptrY] - entry[*ptrX]); } /* end of ddUniqueCompare */ /**Function******************************************************************** Synopsis [Swaps any two variables.] Description [Swaps any two variables. Returns the set of moves.] SideEffects [None] ******************************************************************************/ static Move * ddSwapAny( DdManager * table, int x, int y) { Move *move, *moves; int xRef,yRef; int xNext,yNext; int size; int limitSize; int tmp; if (x >y) { tmp = x; x = y; y = tmp; } xRef = x; yRef = y; xNext = cuddNextHigh(table,x); yNext = cuddNextLow(table,y); moves = NULL; limitSize = table->keys - table->isolated; for (;;) { if ( xNext == yNext) { size = cuddSwapInPlace(table,x,xNext); if (size == 0) goto ddSwapAnyOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSwapAnyOutOfMem; move->x = x; move->y = xNext; move->size = size; move->next = moves; moves = move; size = cuddSwapInPlace(table,yNext,y); if (size == 0) goto ddSwapAnyOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSwapAnyOutOfMem; move->x = yNext; move->y = y; move->size = size; move->next = moves; moves = move; size = cuddSwapInPlace(table,x,xNext); if (size == 0) goto ddSwapAnyOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSwapAnyOutOfMem; move->x = x; move->y = xNext; move->size = size; move->next = moves; moves = move; tmp = x; x = y; y = tmp; } else if (x == yNext) { size = cuddSwapInPlace(table,x,xNext); if (size == 0) goto ddSwapAnyOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSwapAnyOutOfMem; move->x = x; move->y = xNext; move->size = size; move->next = moves; moves = move; tmp = x; x = y; y = tmp; } else { size = cuddSwapInPlace(table,x,xNext); if (size == 0) goto ddSwapAnyOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSwapAnyOutOfMem; move->x = x; move->y = xNext; move->size = size; move->next = moves; moves = move; size = cuddSwapInPlace(table,yNext,y); if (size == 0) goto ddSwapAnyOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSwapAnyOutOfMem; move->x = yNext; move->y = y; move->size = size; move->next = moves; moves = move; x = xNext; y = yNext; } xNext = cuddNextHigh(table,x); yNext = cuddNextLow(table,y); if (xNext > yRef) break; if ((double) size > table->maxGrowth * (double) limitSize) break; if (size < limitSize) limitSize = size; } if (yNext>=xRef) { size = cuddSwapInPlace(table,yNext,y); if (size == 0) goto ddSwapAnyOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSwapAnyOutOfMem; move->x = yNext; move->y = y; move->size = size; move->next = moves; moves = move; } return(moves); ddSwapAnyOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(NULL); } /* end of ddSwapAny */ /**Function******************************************************************** Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.] Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddSiftingAux( DdManager * table, int x, int xLow, int xHigh) { Move *move; Move *moveUp; /* list of up moves */ Move *moveDown; /* list of down moves */ int initialSize; int result; initialSize = table->keys - table->isolated; moveDown = NULL; moveUp = NULL; if (x == xLow) { moveDown = ddSiftingDown(table,x,xHigh); /* At this point x --> xHigh unless bounding occurred. */ if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; /* Move backward and stop at best position. */ result = ddSiftingBackward(table,initialSize,moveDown); if (!result) goto ddSiftingAuxOutOfMem; } else if (x == xHigh) { moveUp = ddSiftingUp(table,x,xLow); /* At this point x --> xLow unless bounding occurred. */ if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; /* Move backward and stop at best position. */ result = ddSiftingBackward(table,initialSize,moveUp); if (!result) goto ddSiftingAuxOutOfMem; } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ moveDown = ddSiftingDown(table,x,xHigh); /* At this point x --> xHigh unless bounding occurred. */ if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; if (moveDown != NULL) { x = moveDown->y; } moveUp = ddSiftingUp(table,x,xLow); if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; /* Move backward and stop at best position */ result = ddSiftingBackward(table,initialSize,moveUp); if (!result) goto ddSiftingAuxOutOfMem; } else { /* must go up first: shorter */ moveUp = ddSiftingUp(table,x,xLow); /* At this point x --> xLow unless bounding occurred. */ if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; if (moveUp != NULL) { x = moveUp->x; } moveDown = ddSiftingDown(table,x,xHigh); if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; /* Move backward and stop at best position. */ result = ddSiftingBackward(table,initialSize,moveDown); if (!result) goto ddSiftingAuxOutOfMem; } while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } return(1); ddSiftingAuxOutOfMem: if (moveDown != (Move *) CUDD_OUT_OF_MEM) { while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } } if (moveUp != (Move *) CUDD_OUT_OF_MEM) { while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } } return(0); } /* end of ddSiftingAux */ /**Function******************************************************************** Synopsis [Sifts a variable up.] Description [Sifts a variable up. Moves y up until either it reaches the bound (xLow) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] ******************************************************************************/ static Move * ddSiftingUp( DdManager * table, int y, int xLow) { Move *moves; Move *move; int x; int size; int limitSize; int xindex, yindex; int isolated; int L; /* lower bound on DD size */ #ifdef DD_DEBUG int checkL; int z; int zindex; #endif moves = NULL; yindex = table->invperm[y]; /* Initialize the lower bound. ** The part of the DD below y will not change. ** The part of the DD above y that does not interact with y will not ** change. The rest may vanish in the best case, except for ** the nodes at level xLow, which will not vanish, regardless. */ limitSize = L = table->keys - table->isolated; for (x = xLow + 1; x < y; x++) { xindex = table->invperm[x]; if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[xindex]->ref == 1; L -= table->subtables[x].keys - isolated; } } isolated = table->vars[yindex]->ref == 1; L -= table->subtables[y].keys - isolated; x = cuddNextLow(table,y); while (x >= xLow && L <= limitSize) { xindex = table->invperm[x]; #ifdef DD_DEBUG checkL = table->keys - table->isolated; for (z = xLow + 1; z < y; z++) { zindex = table->invperm[z]; if (cuddTestInteract(table,zindex,yindex)) { isolated = table->vars[zindex]->ref == 1; checkL -= table->subtables[z].keys - isolated; } } isolated = table->vars[yindex]->ref == 1; checkL -= table->subtables[y].keys - isolated; assert(L == checkL); #endif size = cuddSwapInPlace(table,x,y); if (size == 0) goto ddSiftingUpOutOfMem; /* Update the lower bound. */ if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[xindex]->ref == 1; L += table->subtables[y].keys - isolated; } move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSiftingUpOutOfMem; move->x = x; move->y = y; move->size = size; move->next = moves; moves = move; if ((double) size > (double) limitSize * table->maxGrowth) break; if (size < limitSize) limitSize = size; y = x; x = cuddNextLow(table,y); } return(moves); ddSiftingUpOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return((Move *) CUDD_OUT_OF_MEM); } /* end of ddSiftingUp */ /**Function******************************************************************** Synopsis [Sifts a variable down.] Description [Sifts a variable down. Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] ******************************************************************************/ static Move * ddSiftingDown( DdManager * table, int x, int xHigh) { Move *moves; Move *move; int y; int size; int R; /* upper bound on node decrease */ int limitSize; int xindex, yindex; int isolated; #ifdef DD_DEBUG int checkR; int z; int zindex; #endif moves = NULL; /* Initialize R */ xindex = table->invperm[x]; limitSize = size = table->keys - table->isolated; R = 0; for (y = xHigh; y > x; y--) { yindex = table->invperm[y]; if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[yindex]->ref == 1; R += table->subtables[y].keys - isolated; } } y = cuddNextHigh(table,x); while (y <= xHigh && size - R < limitSize) { #ifdef DD_DEBUG checkR = 0; for (z = xHigh; z > x; z--) { zindex = table->invperm[z]; if (cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; checkR += table->subtables[z].keys - isolated; } } assert(R == checkR); #endif /* Update upper bound on node decrease. */ yindex = table->invperm[y]; if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[yindex]->ref == 1; R -= table->subtables[y].keys - isolated; } size = cuddSwapInPlace(table,x,y); if (size == 0) goto ddSiftingDownOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSiftingDownOutOfMem; move->x = x; move->y = y; move->size = size; move->next = moves; moves = move; if ((double) size > (double) limitSize * table->maxGrowth) break; if (size < limitSize) limitSize = size; x = y; y = cuddNextHigh(table,x); } return(moves); ddSiftingDownOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return((Move *) CUDD_OUT_OF_MEM); } /* end of ddSiftingDown */ /**Function******************************************************************** Synopsis [Given a set of moves, returns the DD heap to the position giving the minimum size.] Description [Given a set of moves, returns the DD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddSiftingBackward( DdManager * table, int size, Move * moves) { Move *move; int res; for (move = moves; move != NULL; move = move->next) { if (move->size < size) { size = move->size; } } for (move = moves; move != NULL; move = move->next) { if (move->size == size) return(1); res = cuddSwapInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); } return(1); } /* end of ddSiftingBackward */ /**Function******************************************************************** Synopsis [Prepares the DD heap for dynamic reordering.] Description [Prepares the DD heap for dynamic reordering. Does garbage collection, to guarantee that there are no dead nodes; clears the cache, which is invalidated by dynamic reordering; initializes the number of isolated projection functions; and initializes the interaction matrix. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddReorderPreprocess( DdManager * table) { int i; int res; /* Clear the cache. */ cuddCacheFlush(table); cuddLocalCacheClearAll(table); /* Eliminate dead nodes. Do not scan the cache again. */ cuddGarbageCollect(table,0); /* Initialize number of isolated projection functions. */ table->isolated = 0; for (i = 0; i < table->size; i++) { if (table->vars[i]->ref == 1) table->isolated++; } /* Initialize the interaction matrix. */ res = cuddInitInteract(table); if (res == 0) return(0); return(1); } /* end of ddReorderPreprocess */ /**Function******************************************************************** Synopsis [Cleans up at the end of reordering.] Description [] SideEffects [None] ******************************************************************************/ static int ddReorderPostprocess( DdManager * table) { #ifdef DD_VERBOSE (void) fflush(table->out); #endif /* Free interaction matrix. */ ABC_FREE(table->interact); return(1); } /* end of ddReorderPostprocess */ /**Function******************************************************************** Synopsis [Reorders variables according to a given permutation.] Description [Reorders variables according to a given permutation. The i-th permutation array contains the index of the variable that should be brought to the i-th level. ddShuffle assumes that no dead nodes are present and that the interaction matrix is properly initialized. The reordering is achieved by a series of upward sifts. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddShuffle( DdManager * table, int * permutation) { int index; int level; int position; int numvars; int result; #ifdef DD_STATS long localTime; int initialSize; int finalSize; int previousSize; #endif ddTotalNumberSwapping = 0; #ifdef DD_STATS localTime = util_cpu_time(); initialSize = table->keys - table->isolated; (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", initialSize); ddTotalNISwaps = 0; #endif numvars = table->size; for (level = 0; level < numvars; level++) { index = permutation[level]; position = table->perm[index]; #ifdef DD_STATS previousSize = table->keys - table->isolated; #endif result = ddSiftUp(table,position,level); if (!result) return(0); #ifdef DD_STATS if (table->keys < (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"-"); } else if (table->keys > (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"+"); /* should never happen */ } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } #ifdef DD_STATS (void) fprintf(table->out,"\n"); finalSize = table->keys - table->isolated; (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", ((double)(util_cpu_time() - localTime)/1000.0)); (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", ddTotalNumberSwapping); (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps); #endif return(1); } /* end of ddShuffle */ /**Function******************************************************************** Synopsis [Moves one variable up.] Description [Takes a variable from position x and sifts it up to position xLow; xLow should be less than or equal to x. Returns 1 if successful; 0 otherwise] SideEffects [None] SeeAlso [] ******************************************************************************/ static int ddSiftUp( DdManager * table, int x, int xLow) { int y; int size; y = cuddNextLow(table,x); while (y >= xLow) { size = cuddSwapInPlace(table,y,x); if (size == 0) { return(0); } x = y; y = cuddNextLow(table,x); } return(1); } /* end of ddSiftUp */ /**Function******************************************************************** Synopsis [Fixes the BDD variable group tree after a shuffle.] Description [Fixes the BDD variable group tree after a shuffle. Assumes that the order of the variables in a terminal node has not been changed.] SideEffects [Changes the BDD variable group tree.] SeeAlso [] ******************************************************************************/ static void bddFixTree( DdManager * table, MtrNode * treenode) { if (treenode == NULL) return; treenode->low = ((int) treenode->index < table->size) ? table->perm[treenode->index] : treenode->index; if (treenode->child != NULL) { bddFixTree(table, treenode->child); } if (treenode->younger != NULL) bddFixTree(table, treenode->younger); if (treenode->parent != NULL && treenode->low < treenode->parent->low) { treenode->parent->low = treenode->low; treenode->parent->index = treenode->index; } return; } /* end of bddFixTree */ /**Function******************************************************************** Synopsis [Updates the BDD variable group tree before a shuffle.] Description [Updates the BDD variable group tree before a shuffle. Returns 1 if successful; 0 otherwise.] SideEffects [Changes the BDD variable group tree.] SeeAlso [] ******************************************************************************/ static int ddUpdateMtrTree( DdManager * table, MtrNode * treenode, int * perm, int * invperm) { int i, size; int index, level, minLevel, maxLevel, minIndex; if (treenode == NULL) return(1); minLevel = CUDD_MAXINDEX; maxLevel = 0; minIndex = -1; /* i : level */ for (i = treenode->low; i < treenode->low + treenode->size; i++) { index = table->invperm[i]; level = perm[index]; if (level < minLevel) { minLevel = level; minIndex = index; } if (level > maxLevel) maxLevel = level; } size = maxLevel - minLevel + 1; if (minIndex == -1) return(0); if (size == treenode->size) { treenode->low = minLevel; treenode->index = minIndex; } else { return(0); } if (treenode->child != NULL) { if (!ddUpdateMtrTree(table, treenode->child, perm, invperm)) return(0); } if (treenode->younger != NULL) { if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm)) return(0); } return(1); } /**Function******************************************************************** Synopsis [Checks the BDD variable group tree before a shuffle.] Description [Checks the BDD variable group tree before a shuffle. Returns 1 if successful; 0 otherwise.] SideEffects [Changes the BDD variable group tree.] SeeAlso [] ******************************************************************************/ static int ddCheckPermuation( DdManager * table, MtrNode * treenode, int * perm, int * invperm) { int i, size; int index, level, minLevel, maxLevel; if (treenode == NULL) return(1); minLevel = table->size; maxLevel = 0; /* i : level */ for (i = treenode->low; i < treenode->low + treenode->size; i++) { index = table->invperm[i]; level = perm[index]; if (level < minLevel) minLevel = level; if (level > maxLevel) maxLevel = level; } size = maxLevel - minLevel + 1; if (size != treenode->size) return(0); if (treenode->child != NULL) { if (!ddCheckPermuation(table, treenode->child, perm, invperm)) return(0); } if (treenode->younger != NULL) { if (!ddCheckPermuation(table, treenode->younger, perm, invperm)) return(0); } return(1); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddSat.c000066400000000000000000001164461300674244400232530ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddSat.c] PackageName [cudd] Synopsis [Functions for the solution of satisfiability related problems.] Description [External procedures included in this file:
      • Cudd_Eval()
      • Cudd_ShortestPath()
      • Cudd_LargestCube()
      • Cudd_ShortestLength()
      • Cudd_Decreasing()
      • Cudd_Increasing()
      • Cudd_EquivDC()
      • Cudd_bddLeqUnless()
      • Cudd_EqualSupNorm()
      • Cudd_bddMakePrime()
      Internal procedures included in this module:
      • cuddBddMakePrime()
      Static procedures included in this module:
      • freePathPair()
      • getShortest()
      • getPath()
      • getLargest()
      • getCube()
      ] Author [Seh-Woong Jeong, Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DD_BIGGY 1000000 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ typedef struct cuddPathPair { int pos; int neg; } cuddPathPair; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.36 2009/03/08 02:49:02 fabio Exp $"; #endif static DdNode *one, *zero; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ #define WEIGHT(weight, col) ((weight) == NULL ? 1 : weight[col]) /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static enum st__retval freePathPair (char *key, char *value, char *arg); static cuddPathPair getShortest (DdNode *root, int *cost, int *support, st__table *visited); static DdNode * getPath (DdManager *manager, st__table *visited, DdNode *f, int *weight, int cost); static cuddPathPair getLargest (DdNode *root, st__table *visited); static DdNode * getCube (DdManager *manager, st__table *visited, DdNode *f, int cost); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Returns the value of a DD for a given variable assignment.] Description [Finds the value of a DD for a given variable assignment. The variable assignment is passed in an array of int's, that should specify a zero or a one for each variable in the support of the function. Returns a pointer to a constant node. No new nodes are produced.] SideEffects [None] SeeAlso [Cudd_bddLeq Cudd_addEvalConst] ******************************************************************************/ DdNode * Cudd_Eval( DdManager * dd, DdNode * f, int * inputs) { int comple; DdNode *ptr; comple = Cudd_IsComplement(f); ptr = Cudd_Regular(f); while (!cuddIsConstant(ptr)) { if (inputs[ptr->index] == 1) { ptr = cuddT(ptr); } else { comple ^= Cudd_IsComplement(cuddE(ptr)); ptr = Cudd_Regular(cuddE(ptr)); } } return(Cudd_NotCond(ptr,comple)); } /* end of Cudd_Eval */ /**Function******************************************************************** Synopsis [Finds a shortest path in a DD.] Description [Finds a shortest path in a DD. f is the DD we want to get the shortest path for; weight\[i\] is the weight of the THEN arc coming from the node whose index is i. If weight is NULL, then unit weights are assumed for all THEN arcs. All ELSE arcs have 0 weight. If non-NULL, both weight and support should point to arrays with at least as many entries as there are variables in the manager. Returns the shortest path as the BDD of a cube.] SideEffects [support contains on return the true support of f. If support is NULL on entry, then Cudd_ShortestPath does not compute the true support info. length contains the length of the path.] SeeAlso [Cudd_ShortestLength Cudd_LargestCube] ******************************************************************************/ DdNode * Cudd_ShortestPath( DdManager * manager, DdNode * f, int * weight, int * support, int * length) { DdNode *F; st__table *visited; DdNode *sol; cuddPathPair *rootPair; int complement, cost; int i; one = DD_ONE(manager); zero = DD_ZERO(manager); /* Initialize support. Support does not depend on variable order. ** Hence, it does not need to be reinitialized if reordering occurs. */ if (support) { for (i = 0; i < manager->size; i++) { support[i] = 0; } } if (f == Cudd_Not(one) || f == zero) { *length = DD_BIGGY; return(Cudd_Not(one)); } /* From this point on, a path exists. */ do { manager->reordered = 0; /* Initialize visited table. */ visited = st__init_table( st__ptrcmp, st__ptrhash); /* Now get the length of the shortest path(s) from f to 1. */ (void) getShortest(f, weight, support, visited); complement = Cudd_IsComplement(f); F = Cudd_Regular(f); if (! st__lookup(visited, (const char *)F, (char **)&rootPair)) return(NULL); if (complement) { cost = rootPair->neg; } else { cost = rootPair->pos; } /* Recover an actual shortest path. */ sol = getPath(manager,visited,f,weight,cost); st__foreach(visited, freePathPair, NULL); st__free_table(visited); } while (manager->reordered == 1); *length = cost; return(sol); } /* end of Cudd_ShortestPath */ /**Function******************************************************************** Synopsis [Finds a largest cube in a DD.] Description [Finds a largest cube in a DD. f is the DD we want to get the largest cube for. The problem is translated into the one of finding a shortest path in f, when both THEN and ELSE arcs are assumed to have unit length. This yields a largest cube in the disjoint cover corresponding to the DD. Therefore, it is not necessarily the largest implicant of f. Returns the largest cube as a BDD.] SideEffects [The number of literals of the cube is returned in length.] SeeAlso [Cudd_ShortestPath] ******************************************************************************/ DdNode * Cudd_LargestCube( DdManager * manager, DdNode * f, int * length) { register DdNode *F; st__table *visited; DdNode *sol; cuddPathPair *rootPair; int complement, cost; one = DD_ONE(manager); zero = DD_ZERO(manager); if (f == Cudd_Not(one) || f == zero) { *length = DD_BIGGY; return(Cudd_Not(one)); } /* From this point on, a path exists. */ do { manager->reordered = 0; /* Initialize visited table. */ visited = st__init_table( st__ptrcmp, st__ptrhash); /* Now get the length of the shortest path(s) from f to 1. */ (void) getLargest(f, visited); complement = Cudd_IsComplement(f); F = Cudd_Regular(f); if (! st__lookup(visited, (const char *)F, (char **)&rootPair)) return(NULL); if (complement) { cost = rootPair->neg; } else { cost = rootPair->pos; } /* Recover an actual shortest path. */ sol = getCube(manager,visited,f,cost); st__foreach(visited, freePathPair, NULL); st__free_table(visited); } while (manager->reordered == 1); *length = cost; return(sol); } /* end of Cudd_LargestCube */ /**Function******************************************************************** Synopsis [Find the length of the shortest path(s) in a DD.] Description [Find the length of the shortest path(s) in a DD. f is the DD we want to get the shortest path for; weight\[i\] is the weight of the THEN edge coming from the node whose index is i. All ELSE edges have 0 weight. Returns the length of the shortest path(s) if such a path is found; a large number if the function is identically 0, and CUDD_OUT_OF_MEM in case of failure.] SideEffects [None] SeeAlso [Cudd_ShortestPath] ******************************************************************************/ int Cudd_ShortestLength( DdManager * manager, DdNode * f, int * weight) { register DdNode *F; st__table *visited; cuddPathPair *my_pair; int complement, cost; one = DD_ONE(manager); zero = DD_ZERO(manager); if (f == Cudd_Not(one) || f == zero) { return(DD_BIGGY); } /* From this point on, a path exists. */ /* Initialize visited table and support. */ visited = st__init_table( st__ptrcmp, st__ptrhash); /* Now get the length of the shortest path(s) from f to 1. */ (void) getShortest(f, weight, NULL, visited); complement = Cudd_IsComplement(f); F = Cudd_Regular(f); if (! st__lookup(visited, (const char *)F, (char **)&my_pair)) return(CUDD_OUT_OF_MEM); if (complement) { cost = my_pair->neg; } else { cost = my_pair->pos; } st__foreach(visited, freePathPair, NULL); st__free_table(visited); return(cost); } /* end of Cudd_ShortestLength */ /**Function******************************************************************** Synopsis [Determines whether a BDD is negative unate in a variable.] Description [Determines whether the function represented by BDD f is negative unate (monotonic decreasing) in variable i. Returns the constant one is f is unate and the (logical) constant zero if it is not. This function does not generate any new nodes.] SideEffects [None] SeeAlso [Cudd_Increasing] ******************************************************************************/ DdNode * Cudd_Decreasing( DdManager * dd, DdNode * f, int i) { unsigned int topf, level; DdNode *F, *fv, *fvn, *res; DD_CTFP cacheOp; statLine(dd); #ifdef DD_DEBUG assert(0 <= i && i < dd->size); #endif F = Cudd_Regular(f); topf = cuddI(dd,F->index); /* Check terminal case. If topf > i, f does not depend on var. ** Therefore, f is unate in i. */ level = (unsigned) dd->perm[i]; if (topf > level) { return(DD_ONE(dd)); } /* From now on, f is not constant. */ /* Check cache. */ cacheOp = (DD_CTFP) Cudd_Decreasing; res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]); if (res != NULL) { return(res); } /* Compute cofactors. */ fv = cuddT(F); fvn = cuddE(F); if (F != f) { fv = Cudd_Not(fv); fvn = Cudd_Not(fvn); } if (topf == (unsigned) level) { /* Special case: if fv is regular, fv(1,...,1) = 1; ** If in addition fvn is complemented, fvn(1,...,1) = 0. ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not ** monotonic decreasing in i. */ if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) { return(Cudd_Not(DD_ONE(dd))); } res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd)); } else { res = Cudd_Decreasing(dd,fv,i); if (res == DD_ONE(dd)) { res = Cudd_Decreasing(dd,fvn,i); } } cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res); return(res); } /* end of Cudd_Decreasing */ /**Function******************************************************************** Synopsis [Determines whether a BDD is positive unate in a variable.] Description [Determines whether the function represented by BDD f is positive unate (monotonic increasing) in variable i. It is based on Cudd_Decreasing and the fact that f is monotonic increasing in i if and only if its complement is monotonic decreasing in i.] SideEffects [None] SeeAlso [Cudd_Decreasing] ******************************************************************************/ DdNode * Cudd_Increasing( DdManager * dd, DdNode * f, int i) { return(Cudd_Decreasing(dd,Cudd_Not(f),i)); } /* end of Cudd_Increasing */ /**Function******************************************************************** Synopsis [Tells whether F and G are identical wherever D is 0.] Description [Tells whether F and G are identical wherever D is 0. F and G are either two ADDs or two BDDs. D is either a 0-1 ADD or a BDD. The function returns 1 if F and G are equivalent, and 0 otherwise. No new nodes are created.] SideEffects [None] SeeAlso [Cudd_bddLeqUnless] ******************************************************************************/ int Cudd_EquivDC( DdManager * dd, DdNode * F, DdNode * G, DdNode * D) { DdNode *tmp, *One, *Gr, *Dr; DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn; int res; unsigned int flevel, glevel, dlevel, top; One = DD_ONE(dd); statLine(dd); /* Check terminal cases. */ if (D == One || F == G) return(1); if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0); /* From now on, D is non-constant. */ /* Normalize call to increase cache efficiency. */ if (F > G) { tmp = F; F = G; G = tmp; } if (Cudd_IsComplement(F)) { F = Cudd_Not(F); G = Cudd_Not(G); } /* From now on, F is regular. */ /* Check cache. */ tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D); if (tmp != NULL) return(tmp == One); /* Find splitting variable. */ flevel = cuddI(dd,F->index); Gr = Cudd_Regular(G); glevel = cuddI(dd,Gr->index); top = ddMin(flevel,glevel); Dr = Cudd_Regular(D); dlevel = dd->perm[Dr->index]; top = ddMin(top,dlevel); /* Compute cofactors. */ if (top == flevel) { Fv = cuddT(F); Fvn = cuddE(F); } else { Fv = Fvn = F; } if (top == glevel) { Gv = cuddT(Gr); Gvn = cuddE(Gr); if (G != Gr) { Gv = Cudd_Not(Gv); Gvn = Cudd_Not(Gvn); } } else { Gv = Gvn = G; } if (top == dlevel) { Dv = cuddT(Dr); Dvn = cuddE(Dr); if (D != Dr) { Dv = Cudd_Not(Dv); Dvn = Cudd_Not(Dvn); } } else { Dv = Dvn = D; } /* Solve recursively. */ res = Cudd_EquivDC(dd,Fv,Gv,Dv); if (res != 0) { res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn); } cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One)); return(res); } /* end of Cudd_EquivDC */ /**Function******************************************************************** Synopsis [Tells whether f is less than of equal to G unless D is 1.] Description [Tells whether f is less than of equal to G unless D is 1. f, g, and D are BDDs. The function returns 1 if f is less than of equal to G, and 0 otherwise. No new nodes are created.] SideEffects [None] SeeAlso [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant] ******************************************************************************/ int Cudd_bddLeqUnless( DdManager *dd, DdNode *f, DdNode *g, DdNode *D) { DdNode *tmp, *One, *F, *G; DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De; int res; unsigned int flevel, glevel, dlevel, top; statLine(dd); One = DD_ONE(dd); /* Check terminal cases. */ if (f == g || g == One || f == Cudd_Not(One) || D == One || D == f || D == Cudd_Not(g)) return(1); /* Check for two-operand cases. */ if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,g)); if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D)); if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D)); /* From now on, f, g, and D are non-constant, distinct, and ** non-complementary. */ /* Normalize call to increase cache efficiency. We rely on the ** fact that f <= g unless D is equivalent to not(g) <= not(f) ** unless D and to f <= D unless g. We make sure that D is ** regular, and that at most one of f and g is complemented. We also ** ensure that when two operands can be swapped, the one with the ** lowest address comes first. */ if (Cudd_IsComplement(D)) { if (Cudd_IsComplement(g)) { /* Special case: if f is regular and g is complemented, ** f(1,...,1) = 1 > 0 = g(1,...,1). If D(1,...,1) = 0, return 0. */ if (!Cudd_IsComplement(f)) return(0); /* !g <= D unless !f or !D <= g unless !f */ tmp = D; D = Cudd_Not(f); if (g < tmp) { f = Cudd_Not(g); g = tmp; } else { f = Cudd_Not(tmp); } } else { if (Cudd_IsComplement(f)) { /* !D <= !f unless g or !D <= g unless !f */ tmp = f; f = Cudd_Not(D); if (tmp < g) { D = g; g = Cudd_Not(tmp); } else { D = Cudd_Not(tmp); } } else { /* f <= D unless g or !D <= !f unless g */ tmp = D; D = g; if (tmp < f) { g = Cudd_Not(f); f = Cudd_Not(tmp); } else { g = tmp; } } } } else { if (Cudd_IsComplement(g)) { if (Cudd_IsComplement(f)) { /* !g <= !f unless D or !g <= D unless !f */ tmp = f; f = Cudd_Not(g); if (D < tmp) { g = D; D = Cudd_Not(tmp); } else { g = Cudd_Not(tmp); } } else { /* f <= g unless D or !g <= !f unless D */ if (g < f) { tmp = g; g = Cudd_Not(f); f = Cudd_Not(tmp); } } } else { /* f <= g unless D or f <= D unless g */ if (D < g) { tmp = D; D = g; g = tmp; } } } /* From now on, D is regular. */ /* Check cache. */ tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D); if (tmp != NULL) return(tmp == One); /* Find splitting variable. */ F = Cudd_Regular(f); flevel = dd->perm[F->index]; G = Cudd_Regular(g); glevel = dd->perm[G->index]; top = ddMin(flevel,glevel); dlevel = dd->perm[D->index]; top = ddMin(top,dlevel); /* Compute cofactors. */ if (top == flevel) { Ft = cuddT(F); Fe = cuddE(F); if (F != f) { Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe); } } else { Ft = Fe = f; } if (top == glevel) { Gt = cuddT(G); Ge = cuddE(G); if (G != g) { Gt = Cudd_Not(Gt); Ge = Cudd_Not(Ge); } } else { Gt = Ge = g; } if (top == dlevel) { Dt = cuddT(D); De = cuddE(D); } else { Dt = De = D; } /* Solve recursively. */ res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt); if (res != 0) { res = Cudd_bddLeqUnless(dd,Fe,Ge,De); } cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res)); return(res); } /* end of Cudd_bddLeqUnless */ /**Function******************************************************************** Synopsis [Compares two ADDs for equality within tolerance.] Description [Compares two ADDs for equality within tolerance. Two ADDs are reported to be equal if the maximum difference between them (the sup norm of their difference) is less than or equal to the tolerance parameter. Returns 1 if the two ADDs are equal (within tolerance); 0 otherwise. If parameter pr is positive the first failure is reported to the standard output.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_EqualSupNorm( DdManager * dd /* manager */, DdNode * f /* first ADD */, DdNode * g /* second ADD */, CUDD_VALUE_TYPE tolerance /* maximum allowed difference */, int pr /* verbosity level */) { DdNode *fv, *fvn, *gv, *gvn, *r; unsigned int topf, topg; statLine(dd); /* Check terminal cases. */ if (f == g) return(1); if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) { if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) { return(1); } else { if (pr>0) { (void) fprintf(dd->out,"Offending nodes:\n"); (void) fprintf(dd->out, "f: address = %p\t value = %40.30f\n", (void *) f, cuddV(f)); (void) fprintf(dd->out, "g: address = %p\t value = %40.30f\n", (void *) g, cuddV(g)); } return(0); } } /* We only insert the result in the cache if the comparison is ** successful. Therefore, if we hit we return 1. */ r = cuddCacheLookup2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g); if (r != NULL) { return(1); } /* Compute the cofactors and solve the recursive subproblems. */ topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0); if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0); cuddCacheInsert2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g,DD_ONE(dd)); return(1); } /* end of Cudd_EqualSupNorm */ /**Function******************************************************************** Synopsis [Expands cube to a prime implicant of f.] Description [Expands cube to a prime implicant of f. Returns the prime if successful; NULL otherwise. In particular, NULL is returned if cube is not a real cube or is not an implicant of f.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_bddMakePrime( DdManager *dd /* manager */, DdNode *cube /* cube to be expanded */, DdNode *f /* function of which the cube is to be made a prime */) { DdNode *res; if (!Cudd_bddLeq(dd,cube,f)) return(NULL); do { dd->reordered = 0; res = cuddBddMakePrime(dd,cube,f); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddMakePrime */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddMakePrime.] Description [Performs the recursive step of Cudd_bddMakePrime. Returns the prime if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddBddMakePrime( DdManager *dd /* manager */, DdNode *cube /* cube to be expanded */, DdNode *f /* function of which the cube is to be made a prime */) { DdNode *scan; DdNode *t, *e; DdNode *res = cube; DdNode *zero = Cudd_Not(DD_ONE(dd)); Cudd_Ref(res); scan = cube; while (!Cudd_IsConstant(scan)) { DdNode *reg = Cudd_Regular(scan); DdNode *var = dd->vars[reg->index]; DdNode *expanded = Cudd_bddExistAbstract(dd,res,var); if (expanded == NULL) { return(NULL); } Cudd_Ref(expanded); if (Cudd_bddLeq(dd,expanded,f)) { Cudd_RecursiveDeref(dd,res); res = expanded; } else { Cudd_RecursiveDeref(dd,expanded); } cuddGetBranches(scan,&t,&e); if (t == zero) { scan = e; } else if (e == zero) { scan = t; } else { Cudd_RecursiveDeref(dd,res); return(NULL); /* cube is not a cube */ } } if (scan == DD_ONE(dd)) { Cudd_Deref(res); return(res); } else { Cudd_RecursiveDeref(dd,res); return(NULL); } } /* end of cuddBddMakePrime */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Frees the entries of the visited symbol table.] Description [Frees the entries of the visited symbol table. Returns st__CONTINUE.] SideEffects [None] ******************************************************************************/ static enum st__retval freePathPair( char * key, char * value, char * arg) { cuddPathPair *pair; pair = (cuddPathPair *) value; ABC_FREE(pair); return( st__CONTINUE); } /* end of freePathPair */ /**Function******************************************************************** Synopsis [Finds the length of the shortest path(s) in a DD.] Description [Finds the length of the shortest path(s) in a DD. Uses a local symbol table to store the lengths for each node. Only the lengths for the regular nodes are entered in the table, because those for the complement nodes are simply obtained by swapping the two lenghts. Returns a pair of lengths: the length of the shortest path to 1; and the length of the shortest path to 0. This is done so as to take complement arcs into account.] SideEffects [Accumulates the support of the DD in support.] SeeAlso [] ******************************************************************************/ static cuddPathPair getShortest( DdNode * root, int * cost, int * support, st__table * visited) { cuddPathPair *my_pair, res_pair, pair_T, pair_E; DdNode *my_root, *T, *E; int weight; my_root = Cudd_Regular(root); if ( st__lookup(visited, (const char *)my_root, (char **)&my_pair)) { if (Cudd_IsComplement(root)) { res_pair.pos = my_pair->neg; res_pair.neg = my_pair->pos; } else { res_pair.pos = my_pair->pos; res_pair.neg = my_pair->neg; } return(res_pair); } /* In the case of a BDD the following test is equivalent to ** testing whether the BDD is the constant 1. This formulation, ** however, works for ADDs as well, by assuming the usual ** dichotomy of 0 and != 0. */ if (cuddIsConstant(my_root)) { if (my_root != zero) { res_pair.pos = 0; res_pair.neg = DD_BIGGY; } else { res_pair.pos = DD_BIGGY; res_pair.neg = 0; } } else { T = cuddT(my_root); E = cuddE(my_root); pair_T = getShortest(T, cost, support, visited); pair_E = getShortest(E, cost, support, visited); weight = WEIGHT(cost, my_root->index); res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos); res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg); /* Update support. */ if (support != NULL) { support[my_root->index] = 1; } } my_pair = ABC_ALLOC(cuddPathPair, 1); if (my_pair == NULL) { if (Cudd_IsComplement(root)) { int tmp = res_pair.pos; res_pair.pos = res_pair.neg; res_pair.neg = tmp; } return(res_pair); } my_pair->pos = res_pair.pos; my_pair->neg = res_pair.neg; st__insert(visited, (char *)my_root, (char *)my_pair); if (Cudd_IsComplement(root)) { res_pair.pos = my_pair->neg; res_pair.neg = my_pair->pos; } else { res_pair.pos = my_pair->pos; res_pair.neg = my_pair->neg; } return(res_pair); } /* end of getShortest */ /**Function******************************************************************** Synopsis [Build a BDD for a shortest path of f.] Description [Build a BDD for a shortest path of f. Given the minimum length from the root, and the minimum lengths for each node (in visited), apply triangulation at each node. Of the two children of each node on a shortest path, at least one is on a shortest path. In case of ties the procedure chooses the THEN children. Returns a pointer to the cube BDD representing the path if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * getPath( DdManager * manager, st__table * visited, DdNode * f, int * weight, int cost) { DdNode *sol, *tmp; DdNode *my_dd, *T, *E; cuddPathPair *T_pair, *E_pair; int Tcost, Ecost; int complement; my_dd = Cudd_Regular(f); complement = Cudd_IsComplement(f); sol = one; cuddRef(sol); while (!cuddIsConstant(my_dd)) { Tcost = cost - WEIGHT(weight, my_dd->index); Ecost = cost; T = cuddT(my_dd); E = cuddE(my_dd); if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} st__lookup(visited, (const char *)Cudd_Regular(T), (char **)&T_pair); if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); if (tmp == NULL) { Cudd_RecursiveDeref(manager,sol); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(manager,sol); sol = tmp; complement = Cudd_IsComplement(T); my_dd = Cudd_Regular(T); cost = Tcost; continue; } st__lookup(visited, (const char *)Cudd_Regular(E), (char **)&E_pair); if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); if (tmp == NULL) { Cudd_RecursiveDeref(manager,sol); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(manager,sol); sol = tmp; complement = Cudd_IsComplement(E); my_dd = Cudd_Regular(E); cost = Ecost; continue; } (void) fprintf(manager->err,"We shouldn't be here!!\n"); manager->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } cuddDeref(sol); return(sol); } /* end of getPath */ /**Function******************************************************************** Synopsis [Finds the size of the largest cube(s) in a DD.] Description [Finds the size of the largest cube(s) in a DD. This problem is translated into finding the shortest paths from a node when both THEN and ELSE arcs have unit lengths. Uses a local symbol table to store the lengths for each node. Only the lengths for the regular nodes are entered in the table, because those for the complement nodes are simply obtained by swapping the two lenghts. Returns a pair of lengths: the length of the shortest path to 1; and the length of the shortest path to 0. This is done so as to take complement arcs into account.] SideEffects [none] SeeAlso [] ******************************************************************************/ static cuddPathPair getLargest( DdNode * root, st__table * visited) { cuddPathPair *my_pair, res_pair, pair_T, pair_E; DdNode *my_root, *T, *E; my_root = Cudd_Regular(root); if ( st__lookup(visited, (const char *)my_root, (char **)&my_pair)) { if (Cudd_IsComplement(root)) { res_pair.pos = my_pair->neg; res_pair.neg = my_pair->pos; } else { res_pair.pos = my_pair->pos; res_pair.neg = my_pair->neg; } return(res_pair); } /* In the case of a BDD the following test is equivalent to ** testing whether the BDD is the constant 1. This formulation, ** however, works for ADDs as well, by assuming the usual ** dichotomy of 0 and != 0. */ if (cuddIsConstant(my_root)) { if (my_root != zero) { res_pair.pos = 0; res_pair.neg = DD_BIGGY; } else { res_pair.pos = DD_BIGGY; res_pair.neg = 0; } } else { T = cuddT(my_root); E = cuddE(my_root); pair_T = getLargest(T, visited); pair_E = getLargest(E, visited); res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1; res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1; } my_pair = ABC_ALLOC(cuddPathPair, 1); if (my_pair == NULL) { /* simply do not cache this result */ if (Cudd_IsComplement(root)) { int tmp = res_pair.pos; res_pair.pos = res_pair.neg; res_pair.neg = tmp; } return(res_pair); } my_pair->pos = res_pair.pos; my_pair->neg = res_pair.neg; /* Caching may fail without affecting correctness. */ st__insert(visited, (char *)my_root, (char *)my_pair); if (Cudd_IsComplement(root)) { res_pair.pos = my_pair->neg; res_pair.neg = my_pair->pos; } else { res_pair.pos = my_pair->pos; res_pair.neg = my_pair->neg; } return(res_pair); } /* end of getLargest */ /**Function******************************************************************** Synopsis [Build a BDD for a largest cube of f.] Description [Build a BDD for a largest cube of f. Given the minimum length from the root, and the minimum lengths for each node (in visited), apply triangulation at each node. Of the two children of each node on a shortest path, at least one is on a shortest path. In case of ties the procedure chooses the THEN children. Returns a pointer to the cube BDD representing the path if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * getCube( DdManager * manager, st__table * visited, DdNode * f, int cost) { DdNode *sol, *tmp; DdNode *my_dd, *T, *E; cuddPathPair *T_pair, *E_pair; int Tcost, Ecost; int complement; my_dd = Cudd_Regular(f); complement = Cudd_IsComplement(f); sol = one; cuddRef(sol); while (!cuddIsConstant(my_dd)) { Tcost = cost - 1; Ecost = cost - 1; T = cuddT(my_dd); E = cuddE(my_dd); if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} if (! st__lookup(visited, (const char *)Cudd_Regular(T), (char **)&T_pair)) return(NULL); if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); if (tmp == NULL) { Cudd_RecursiveDeref(manager,sol); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(manager,sol); sol = tmp; complement = Cudd_IsComplement(T); my_dd = Cudd_Regular(T); cost = Tcost; continue; } if (! st__lookup(visited, (const char *)Cudd_Regular(E), (char **)&E_pair)) return(NULL); if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); if (tmp == NULL) { Cudd_RecursiveDeref(manager,sol); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(manager,sol); sol = tmp; complement = Cudd_IsComplement(E); my_dd = Cudd_Regular(E); cost = Ecost; continue; } (void) fprintf(manager->err,"We shouldn't be here!\n"); manager->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } cuddDeref(sol); return(sol); } /* end of getCube */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddSign.c000066400000000000000000000264111300674244400234140ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddSign.c] PackageName [cudd] Synopsis [Computation of signatures.] Description [External procedures included in this module:
      • Cudd_CofMinterm();
      Static procedures included in this module:
      • ddCofMintermAux()
      ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddSign.c,v 1.22 2009/02/20 02:14:58 fabio Exp $"; #endif static int size; #ifdef DD_STATS static int num_calls; /* should equal 2n-1 (n is the # of nodes) */ static int table_mem; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static double * ddCofMintermAux (DdManager *dd, DdNode *node, st__table *table); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the fraction of minterms in the on-set of all the positive cofactors of a BDD or ADD.] Description [Computes the fraction of minterms in the on-set of all the positive cofactors of DD. Returns the pointer to an array of doubles if successful; NULL otherwise. The array has as many positions as there are BDD variables in the manager plus one. The last position of the array contains the fraction of the minterms in the ON-set of the function represented by the BDD or ADD. The other positions of the array hold the variable signatures.] SideEffects [None] ******************************************************************************/ double * Cudd_CofMinterm( DdManager * dd, DdNode * node) { st__table *table; double *values; double *result = NULL; int i, firstLevel; #ifdef DD_STATS long startTime; startTime = util_cpu_time(); num_calls = 0; table_mem = sizeof( st__table); #endif table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) { (void) fprintf(dd->err, "out-of-memory, couldn't measure DD cofactors.\n"); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } size = dd->size; values = ddCofMintermAux(dd, node, table); if (values != NULL) { result = ABC_ALLOC(double,size + 1); if (result != NULL) { #ifdef DD_STATS table_mem += (size + 1) * sizeof(double); #endif if (Cudd_IsConstant(node)) firstLevel = 1; else firstLevel = cuddI(dd,Cudd_Regular(node)->index); for (i = 0; i < size; i++) { if (i >= cuddI(dd,Cudd_Regular(node)->index)) { result[dd->invperm[i]] = values[i - firstLevel]; } else { result[dd->invperm[i]] = values[size - firstLevel]; } } result[size] = values[size - firstLevel]; } else { dd->errorCode = CUDD_MEMORY_OUT; } } #ifdef DD_STATS table_mem += table->num_bins * sizeof( st__table_entry *); #endif if (Cudd_Regular(node)->ref == 1) ABC_FREE(values); st__foreach(table, cuddStCountfree, NULL); st__free_table(table); #ifdef DD_STATS (void) fprintf(dd->out,"Number of calls: %d\tTable memory: %d bytes\n", num_calls, table_mem); (void) fprintf(dd->out,"Time to compute measures: %s\n", util_print_time(util_cpu_time() - startTime)); #endif if (result == NULL) { (void) fprintf(dd->out, "out-of-memory, couldn't measure DD cofactors.\n"); dd->errorCode = CUDD_MEMORY_OUT; } return(result); } /* end of Cudd_CofMinterm */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Recursive Step for Cudd_CofMinterm function.] Description [Traverses the DD node and computes the fraction of minterms in the on-set of all positive cofactors simultaneously. It allocates an array with two more entries than there are variables below the one labeling the node. One extra entry (the first in the array) is for the variable labeling the node. The other entry (the last one in the array) holds the fraction of minterms of the function rooted at node. Each other entry holds the value for one cofactor. The array is put in a symbol table, to avoid repeated computation, and its address is returned by the procedure, for use by the caller. Returns a pointer to the array of cofactor measures.] SideEffects [None] SeeAlso [] ******************************************************************************/ static double * ddCofMintermAux( DdManager * dd, DdNode * node, st__table * table) { DdNode *N; /* regular version of node */ DdNode *Nv, *Nnv; double *values; double *valuesT, *valuesE; int i; int localSize, localSizeT, localSizeE; double vT, vE; statLine(dd); #ifdef DD_STATS num_calls++; #endif if ( st__lookup(table, (const char *)node, (char **)&values)) { return(values); } N = Cudd_Regular(node); if (cuddIsConstant(N)) { localSize = 1; } else { localSize = size - cuddI(dd,N->index) + 1; } values = ABC_ALLOC(double, localSize); if (values == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } if (cuddIsConstant(N)) { if (node == DD_ZERO(dd) || node == Cudd_Not(DD_ONE(dd))) { values[0] = 0.0; } else { values[0] = 1.0; } } else { Nv = Cudd_NotCond(cuddT(N),N!=node); Nnv = Cudd_NotCond(cuddE(N),N!=node); valuesT = ddCofMintermAux(dd, Nv, table); if (valuesT == NULL) return(NULL); valuesE = ddCofMintermAux(dd, Nnv, table); if (valuesE == NULL) return(NULL); if (Cudd_IsConstant(Nv)) { localSizeT = 1; } else { localSizeT = size - cuddI(dd,Cudd_Regular(Nv)->index) + 1; } if (Cudd_IsConstant(Nnv)) { localSizeE = 1; } else { localSizeE = size - cuddI(dd,Cudd_Regular(Nnv)->index) + 1; } values[0] = valuesT[localSizeT - 1]; for (i = 1; i < localSize; i++) { if (i >= cuddI(dd,Cudd_Regular(Nv)->index) - cuddI(dd,N->index)) { vT = valuesT[i - cuddI(dd,Cudd_Regular(Nv)->index) + cuddI(dd,N->index)]; } else { vT = valuesT[localSizeT - 1]; } if (i >= cuddI(dd,Cudd_Regular(Nnv)->index) - cuddI(dd,N->index)) { vE = valuesE[i - cuddI(dd,Cudd_Regular(Nnv)->index) + cuddI(dd,N->index)]; } else { vE = valuesE[localSizeE - 1]; } values[i] = (vT + vE) / 2.0; } if (Cudd_Regular(Nv)->ref == 1) ABC_FREE(valuesT); if (Cudd_Regular(Nnv)->ref == 1) ABC_FREE(valuesE); } if (N->ref > 1) { if ( st__add_direct(table, (char *) node, (char *) values) == st__OUT_OF_MEM) { ABC_FREE(values); return(NULL); } #ifdef DD_STATS table_mem += localSize * sizeof(double) + sizeof( st__table_entry); #endif } return(values); } /* end of ddCofMintermAux */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddSolve.c000066400000000000000000000263161300674244400236100ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddSolve.c] PackageName [cudd] Synopsis [Boolean equation solver and related functions.] Description [External functions included in this modoule:
      • Cudd_SolveEqn()
      • Cudd_VerifySol()
      Internal functions included in this module:
      • cuddSolveEqnRecur()
      • cuddVerifySol()
      ] SeeAlso [] Author [Balakrishna Kumthekar] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Structure declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddSolve.c,v 1.12 2004/08/13 18:04:51 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the solution of F(x,y) = 0.] Description [Implements the solution for F(x,y) = 0. The return value is the consistency condition. The y variables are the unknowns and the remaining variables are the parameters. Returns the consistency condition if successful; NULL otherwise. Cudd_SolveEqn allocates an array and fills it with the indices of the unknowns. This array is used by Cudd_VerifySol.] SideEffects [The solution is returned in G; the indices of the y variables are returned in yIndex.] SeeAlso [Cudd_VerifySol] ******************************************************************************/ DdNode * Cudd_SolveEqn( DdManager * bdd, DdNode * F /* the left-hand side of the equation */, DdNode * Y /* the cube of the y variables */, DdNode ** G /* the array of solutions (return parameter) */, int ** yIndex /* index of y variables */, int n /* numbers of unknowns */) { DdNode *res; int *temp; *yIndex = temp = ABC_ALLOC(int, n); if (temp == NULL) { bdd->errorCode = CUDD_MEMORY_OUT; (void) fprintf(bdd->out, "Cudd_SolveEqn: Out of memory for yIndex\n"); return(NULL); } do { bdd->reordered = 0; res = cuddSolveEqnRecur(bdd, F, Y, G, n, temp, 0); } while (bdd->reordered == 1); return(res); } /* end of Cudd_SolveEqn */ /**Function******************************************************************** Synopsis [Checks the solution of F(x,y) = 0.] Description [Checks the solution of F(x,y) = 0. This procedure substitutes the solution components for the unknowns of F and returns the resulting BDD for F.] SideEffects [Frees the memory pointed by yIndex.] SeeAlso [Cudd_SolveEqn] ******************************************************************************/ DdNode * Cudd_VerifySol( DdManager * bdd, DdNode * F /* the left-hand side of the equation */, DdNode ** G /* the array of solutions */, int * yIndex /* index of y variables */, int n /* numbers of unknowns */) { DdNode *res; do { bdd->reordered = 0; res = cuddVerifySol(bdd, F, G, yIndex, n); } while (bdd->reordered == 1); ABC_FREE(yIndex); return(res); } /* end of Cudd_VerifySol */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_SolveEqn.] Description [Implements the recursive step of Cudd_SolveEqn. Returns NULL if the intermediate solution blows up or reordering occurs. The parametric solutions are stored in the array G.] SideEffects [none] SeeAlso [Cudd_SolveEqn, Cudd_VerifySol] ******************************************************************************/ DdNode * cuddSolveEqnRecur( DdManager * bdd, DdNode * F /* the left-hand side of the equation */, DdNode * Y /* the cube of remaining y variables */, DdNode ** G /* the array of solutions */, int n /* number of unknowns */, int * yIndex /* array holding the y variable indices */, int i /* level of recursion */) { DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one; DdNodePtr *variables; int j; statLine(bdd); variables = bdd->vars; one = DD_ONE(bdd); /* Base condition. */ if (Y == one) { return F; } /* Cofactor of Y. */ yIndex[i] = Y->index; nextY = Cudd_T(Y); /* Universal abstraction of F with respect to the top variable index. */ Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]); if (Fm1) { Fm1 = Cudd_Not(Fm1); cuddRef(Fm1); } else { return(NULL); } Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1); if (Fn) { cuddRef(Fn); } else { Cudd_RecursiveDeref(bdd, Fm1); return(NULL); } Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]); if (Fv) { cuddRef(Fv); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); return(NULL); } Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]])); if (Fvbar) { cuddRef(Fvbar); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); return(NULL); } /* Build i-th component of the solution. */ w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar); if (w) { cuddRef(w); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); Cudd_RecursiveDeref(bdd, Fvbar); return(NULL); } T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1)); if(T) { cuddRef(T); } else { Cudd_RecursiveDeref(bdd, Fm1); Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, Fv); Cudd_RecursiveDeref(bdd, Fvbar); Cudd_RecursiveDeref(bdd, w); return(NULL); } Cudd_RecursiveDeref(bdd,Fm1); Cudd_RecursiveDeref(bdd,w); Cudd_RecursiveDeref(bdd,Fv); Cudd_RecursiveDeref(bdd,Fvbar); /* Substitute components of solution already found into solution. */ for (j = n-1; j > i; j--) { w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]); if(w) { cuddRef(w); } else { Cudd_RecursiveDeref(bdd, Fn); Cudd_RecursiveDeref(bdd, T); return(NULL); } Cudd_RecursiveDeref(bdd,T); T = w; } G[i] = T; Cudd_Deref(Fn); return(Fn); } /* end of cuddSolveEqnRecur */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_VerifySol. ] Description [] SideEffects [none] SeeAlso [Cudd_VerifySol] ******************************************************************************/ DdNode * cuddVerifySol( DdManager * bdd, DdNode * F /* the left-hand side of the equation */, DdNode ** G /* the array of solutions */, int * yIndex /* array holding the y variable indices */, int n /* number of unknowns */) { DdNode *w, *R; int j; R = F; cuddRef(R); for(j = n - 1; j >= 0; j--) { w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]); if (w) { cuddRef(w); } else { return(NULL); } Cudd_RecursiveDeref(bdd,R); R = w; } cuddDeref(R); return(R); } /* end of cuddVerifySol */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddSplit.c000066400000000000000000000522371300674244400236140ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddSplit.c] PackageName [cudd] Synopsis [Returns a subset of minterms from a boolean function.] Description [External functions included in this modoule:
      • Cudd_SplitSet()
      Internal functions included in this module:
      • cuddSplitSetRecur() Static functions included in this module:
        • selectMintermsFromUniverse()
        • mintermsFromUniverse()
        • bddAnnotateMintermCount()
        ] SeeAlso [] Author [Balakrishna Kumthekar] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Structure declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * selectMintermsFromUniverse (DdManager *manager, int *varSeen, double n); static DdNode * mintermsFromUniverse (DdManager *manager, DdNode **vars, int numVars, double n, int index); static double bddAnnotateMintermCount (DdManager *manager, DdNode *node, double max, st__table *table); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Returns m minterms from a BDD.] Description [Returns m minterms from a BDD whose support has n variables at most. The procedure tries to create as few extra nodes as possible. The function represented by S depends on at most n of the variables in xVars. Returns a BDD with m minterms of the on-set of S if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_SplitSet( DdManager * manager, DdNode * S, DdNode ** xVars, int n, double m) { DdNode *result; DdNode *zero, *one; double max, num; st__table *mtable; int *varSeen; int i,index, size; size = manager->size; one = DD_ONE(manager); zero = Cudd_Not(one); /* Trivial cases. */ if (m == 0.0) { return(zero); } if (S == zero) { return(NULL); } max = pow(2.0,(double)n); if (m > max) return(NULL); do { manager->reordered = 0; /* varSeen is used to mark the variables that are encountered ** while traversing the BDD S. */ varSeen = ABC_ALLOC(int, size); if (varSeen == NULL) { manager->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < size; i++) { varSeen[i] = -1; } for (i = 0; i < n; i++) { index = (xVars[i])->index; varSeen[manager->invperm[index]] = 0; } if (S == one) { if (m == max) { ABC_FREE(varSeen); return(S); } result = selectMintermsFromUniverse(manager,varSeen,m); if (result) cuddRef(result); ABC_FREE(varSeen); } else { mtable = st__init_table( st__ptrcmp, st__ptrhash); if (mtable == NULL) { (void) fprintf(manager->out, "Cudd_SplitSet: out-of-memory.\n"); ABC_FREE(varSeen); manager->errorCode = CUDD_MEMORY_OUT; return(NULL); } /* The nodes of BDD S are annotated by the number of minterms ** in their onset. The node and the number of minterms in its ** onset are stored in mtable. */ num = bddAnnotateMintermCount(manager,S,max,mtable); if (m == num) { st__foreach(mtable,cuddStCountfree,NIL(char)); st__free_table(mtable); ABC_FREE(varSeen); return(S); } result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0); if (result) cuddRef(result); st__foreach(mtable,cuddStCountfree,NULL); st__free_table(mtable); ABC_FREE(varSeen); } } while (manager->reordered == 1); cuddDeref(result); return(result); } /* end of Cudd_SplitSet */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_SplitSet.] Description [Implements the recursive step of Cudd_SplitSet. The procedure recursively traverses the BDD and checks to see if any node satisfies the minterm requirements as specified by 'n'. At any node X, n is compared to the number of minterms in the onset of X's children. If either of the child nodes have exactly n minterms, then that node is returned; else, if n is greater than the onset of one of the child nodes, that node is retained and the difference in the number of minterms is extracted from the other child. In case n minterms can be extracted from constant 1, the algorithm returns the result with at most log(n) nodes.] SideEffects [The array 'varSeen' is updated at every recursive call to set the variables traversed by the procedure.] SeeAlso [] ******************************************************************************/ DdNode* cuddSplitSetRecur( DdManager * manager, st__table * mtable, int * varSeen, DdNode * p, double n, double max, int index) { DdNode *one, *zero, *N, *Nv; DdNode *Nnv, *q, *r, *v; DdNode *result; double *dummy, numT, numE; int variable, positive; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* If p is constant, extract n minterms from constant 1. The procedure by ** construction guarantees that minterms will not be extracted from ** constant 0. */ if (Cudd_IsConstant(p)) { q = selectMintermsFromUniverse(manager,varSeen,n); return(q); } N = Cudd_Regular(p); /* Set variable as seen. */ variable = N->index; varSeen[manager->invperm[variable]] = -1; Nv = cuddT(N); Nnv = cuddE(N); if (Cudd_IsComplement(p)) { Nv = Cudd_Not(Nv); Nnv = Cudd_Not(Nnv); } /* If both the children of 'p' are constants, extract n minterms from a ** constant node. */ if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) { q = selectMintermsFromUniverse(manager,varSeen,n); if (q == NULL) { return(NULL); } cuddRef(q); r = cuddBddAndRecur(manager,p,q); if (r == NULL) { Cudd_RecursiveDeref(manager,q); return(NULL); } cuddRef(r); Cudd_RecursiveDeref(manager,q); cuddDeref(r); return(r); } /* Lookup the # of minterms in the onset of the node from the table. */ if (!Cudd_IsConstant(Nv)) { if (! st__lookup(mtable, (const char *)Nv, (char **)&dummy)) return(NULL); numT = *dummy/(2*(1<size; one = DD_ONE(manager); zero = Cudd_Not(one); /* Count the number of variables not encountered so far in procedure ** cuddSplitSetRecur. */ for (i = size-1; i >= 0; i--) { if(varSeen[i] == 0) numVars++; } vars = ABC_ALLOC(DdNode *, numVars); if (!vars) { manager->errorCode = CUDD_MEMORY_OUT; return(NULL); } j = 0; for (i = size-1; i >= 0; i--) { if(varSeen[i] == 0) { vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero); cuddRef(vars[j]); j++; } } /* Compute a function which has n minterms and depends on at most ** numVars variables. */ result = mintermsFromUniverse(manager,vars,numVars,n, 0); if (result) cuddRef(result); for (i = 0; i < numVars; i++) Cudd_RecursiveDeref(manager,vars[i]); ABC_FREE(vars); return(result); } /* end of selectMintermsFromUniverse */ /**Function******************************************************************** Synopsis [Recursive procedure to extract n mintems from constant 1.] Description [Recursive procedure to extract n mintems from constant 1.] SideEffects [None] ******************************************************************************/ static DdNode * mintermsFromUniverse( DdManager * manager, DdNode ** vars, int numVars, double n, int index) { DdNode *one, *zero; DdNode *q, *result; double max, max2; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); max = pow(2.0, (double)numVars); max2 = max / 2.0; if (n == max) return(one); if (n == 0.0) return(zero); /* if n == 2^(numVars-1), return a single variable */ if (n == max2) return vars[index]; else if (n > max2) { /* When n > 2^(numVars-1), a single variable vars[index] ** contains 2^(numVars-1) minterms. The rest are extracted ** from a constant with 1 less variable. */ q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1); if (q == NULL) return(NULL); cuddRef(q); result = cuddBddIteRecur(manager,vars[index],one,q); } else { /* When n < 2^(numVars-1), a literal of variable vars[index] ** is selected. The required n minterms are extracted from a ** constant with 1 less variable. */ q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1); if (q == NULL) return(NULL); cuddRef(q); result = cuddBddAndRecur(manager,vars[index],q); } if (result == NULL) { Cudd_RecursiveDeref(manager,q); return(NULL); } cuddRef(result); Cudd_RecursiveDeref(manager,q); cuddDeref(result); return(result); } /* end of mintermsFromUniverse */ /**Function******************************************************************** Synopsis [Annotates every node in the BDD node with its minterm count.] Description [Annotates every node in the BDD node with its minterm count. In this function, every node and the minterm count represented by it are stored in a hash table.] SideEffects [Fills up 'table' with the pair .] ******************************************************************************/ static double bddAnnotateMintermCount( DdManager * manager, DdNode * node, double max, st__table * table) { DdNode *N,*Nv,*Nnv; register double min_v,min_nv; register double min_N; double *pmin; double *dummy; statLine(manager); N = Cudd_Regular(node); if (cuddIsConstant(N)) { if (node == DD_ONE(manager)) { return(max); } else { return(0.0); } } if ( st__lookup(table, (const char *)node, (char **)&dummy)) { return(*dummy); } Nv = cuddT(N); Nnv = cuddE(N); if (N != node) { Nv = Cudd_Not(Nv); Nnv = Cudd_Not(Nnv); } /* Recur on the two branches. */ min_v = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0; if (min_v == (double)CUDD_OUT_OF_MEM) return ((double)CUDD_OUT_OF_MEM); min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0; if (min_nv == (double)CUDD_OUT_OF_MEM) return ((double)CUDD_OUT_OF_MEM); min_N = min_v + min_nv; pmin = ABC_ALLOC(double,1); if (pmin == NULL) { manager->errorCode = CUDD_MEMORY_OUT; return((double)CUDD_OUT_OF_MEM); } *pmin = min_N; if ( st__insert(table,(char *)node, (char *)pmin) == st__OUT_OF_MEM) { ABC_FREE(pmin); return((double)CUDD_OUT_OF_MEM); } return(min_N); } /* end of bddAnnotateMintermCount */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddSubsetHB.c000066400000000000000000001304641300674244400241770ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddSubsetHB.c] PackageName [cudd] Synopsis [Procedure to subset the given BDD by choosing the heavier branches.] Description [External procedures provided by this module:
        • Cudd_SubsetHeavyBranch()
        • Cudd_SupersetHeavyBranch()
        Internal procedures included in this module:
        • cuddSubsetHeavyBranch()
        Static procedures included in this module:
        • ResizeCountMintermPages();
        • ResizeNodeDataPages()
        • ResizeCountNodePages()
        • SubsetCountMintermAux()
        • SubsetCountMinterm()
        • SubsetCountNodesAux()
        • SubsetCountNodes()
        • BuildSubsetBdd()
        ] SeeAlso [cuddSubsetSP.c] Author [Kavita Ravi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #ifdef __STDC__ #include #else #define DBL_MAX_EXP 1024 #endif #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DEFAULT_PAGE_SIZE 2048 #define DEFAULT_NODE_DATA_PAGE_SIZE 1024 #define INITIAL_PAGES 128 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /* data structure to store the information on each node. It keeps * the number of minterms represented by the DAG rooted at this node * in terms of the number of variables specified by the user, number * of nodes in this DAG and the number of nodes of its child with * lesser number of minterms that are not shared by the child with * more minterms */ struct NodeData { double *mintermPointer; int *nodesPointer; int *lightChildNodesPointer; }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ typedef struct NodeData NodeData_t; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.37 2009/02/20 02:14:58 fabio Exp $"; #endif static int memOut; #ifdef DEBUG static int num_calls; #endif static DdNode *zero, *one; /* constant functions */ static double **mintermPages; /* pointers to the pages */ static int **nodePages; /* pointers to the pages */ static int **lightNodePages; /* pointers to the pages */ static double *currentMintermPage; /* pointer to the current page */ static double max; /* to store the 2^n value of the number * of variables */ static int *currentNodePage; /* pointer to the current page */ static int *currentLightNodePage; /* pointer to the * current page */ static int pageIndex; /* index to next element */ static int page; /* index to current page */ static int pageSize = DEFAULT_PAGE_SIZE; /* page size */ static int maxPages; /* number of page pointers */ static NodeData_t *currentNodeDataPage; /* pointer to the current page */ static int nodeDataPage; /* index to next element */ static int nodeDataPageIndex; /* index to next element */ static NodeData_t **nodeDataPages; /* index to current page */ static int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE; /* page size */ static int maxNodeDataPages; /* number of page pointers */ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void ResizeNodeDataPages (void); static void ResizeCountMintermPages (void); static void ResizeCountNodePages (void); static double SubsetCountMintermAux (DdNode *node, double max, st__table *table); static st__table * SubsetCountMinterm (DdNode *node, int nvars); static int SubsetCountNodesAux (DdNode *node, st__table *table, double max); static int SubsetCountNodes (DdNode *node, st__table *table, int nvars); static void StoreNodes ( st__table *storeTable, DdManager *dd, DdNode *node); static DdNode * BuildSubsetBdd (DdManager *dd, DdNode *node, int *size, st__table *visitedTable, int threshold, st__table *storeTable, st__table *approxTable); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Extracts a dense subset from a BDD with the heavy branch heuristic.] Description [Extracts a dense subset from a BDD. This procedure builds a subset by throwing away one of the children of each node, starting from the root, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.] SideEffects [None] SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_SubsetHeavyBranch( DdManager * dd /* manager */, DdNode * f /* function to be subset */, int numVars /* number of variables in the support of f */, int threshold /* maximum number of nodes in the subset */) { DdNode *subset; memOut = 0; do { dd->reordered = 0; subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold); } while ((dd->reordered == 1) && (!memOut)); return(subset); } /* end of Cudd_SubsetHeavyBranch */ /**Function******************************************************************** Synopsis [Extracts a dense superset from a BDD with the heavy branch heuristic.] Description [Extracts a dense superset from a BDD. The procedure is identical to the subset procedure except for the fact that it receives the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. This procedure builds a superset by throwing away one of the children of each node starting from the root of the complement function, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.] SideEffects [None] SeeAlso [Cudd_SubsetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_SupersetHeavyBranch( DdManager * dd /* manager */, DdNode * f /* function to be superset */, int numVars /* number of variables in the support of f */, int threshold /* maximum number of nodes in the superset */) { DdNode *subset, *g; g = Cudd_Not(f); memOut = 0; do { dd->reordered = 0; subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold); } while ((dd->reordered == 1) && (!memOut)); return(Cudd_NotCond(subset, (subset != NULL))); } /* end of Cudd_SupersetHeavyBranch */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [The main procedure that returns a subset by choosing the heavier branch in the BDD.] Description [Here a subset BDD is built by throwing away one of the children. Starting at root, annotate each node with the number of minterms (in terms of the total number of variables specified - numVars), number of nodes taken by the DAG rooted at this node and number of additional nodes taken by the child that has the lesser minterms. The child with the lower number of minterms is thrown away and a dyanmic count of the nodes of the subset is kept. Once the threshold is reached the subset is returned to the calling procedure.] SideEffects [None] SeeAlso [Cudd_SubsetHeavyBranch] ******************************************************************************/ DdNode * cuddSubsetHeavyBranch( DdManager * dd /* DD manager */, DdNode * f /* current DD */, int numVars /* maximum number of variables */, int threshold /* threshold size for the subset */) { int i, *size; st__table *visitedTable; int numNodes; NodeData_t *currNodeQual; DdNode *subset; st__table *storeTable, *approxTable; char *key, *value; st__generator *stGen; if (f == NULL) { fprintf(dd->err, "Cannot subset, nil object\n"); dd->errorCode = CUDD_INVALID_ARG; return(NULL); } one = Cudd_ReadOne(dd); zero = Cudd_Not(one); /* If user does not know numVars value, set it to the maximum * exponent that the pow function can take. The -1 is due to the * discrepancy in the value that pow takes and the value that * log gives. */ if (numVars == 0) { /* set default value */ numVars = DBL_MAX_EXP - 1; } if (Cudd_IsConstant(f)) { return(f); } max = pow(2.0, (double)numVars); /* Create visited table where structures for node data are allocated and stored in a st__table */ visitedTable = SubsetCountMinterm(f, numVars); if ((visitedTable == NULL) || memOut) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); dd->errorCode = CUDD_MEMORY_OUT; return(0); } numNodes = SubsetCountNodes(f, visitedTable, numVars); if (memOut) { (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); dd->errorCode = CUDD_MEMORY_OUT; return(0); } if ( st__lookup(visitedTable, (const char *)f, (char **)&currNodeQual) == 0) { fprintf(dd->err, "Something is wrong, ought to be node quality table\n"); dd->errorCode = CUDD_INTERNAL_ERROR; } size = ABC_ALLOC(int, 1); if (size == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } *size = numNodes; #ifdef DEBUG num_calls = 0; #endif /* table to store nodes being created. */ storeTable = st__init_table( st__ptrcmp, st__ptrhash); /* insert the constant */ cuddRef(one); if ( st__insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) == st__OUT_OF_MEM) { fprintf(dd->out, "Something wrong, st__table insert failed\n"); } /* table to store approximations of nodes */ approxTable = st__init_table( st__ptrcmp, st__ptrhash); subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold, storeTable, approxTable); if (subset != NULL) { cuddRef(subset); } stGen = st__init_gen(approxTable); if (stGen == NULL) { st__free_table(approxTable); return(NULL); } while( st__gen(stGen, (const char **)&key, (char **)&value)) { Cudd_RecursiveDeref(dd, (DdNode *)value); } st__free_gen(stGen); stGen = NULL; st__free_table(approxTable); stGen = st__init_gen(storeTable); if (stGen == NULL) { st__free_table(storeTable); return(NULL); } while( st__gen(stGen, (const char **)&key, (char **)&value)) { Cudd_RecursiveDeref(dd, (DdNode *)key); } st__free_gen(stGen); stGen = NULL; st__free_table(storeTable); for (i = 0; i <= page; i++) { ABC_FREE(mintermPages[i]); } ABC_FREE(mintermPages); for (i = 0; i <= page; i++) { ABC_FREE(nodePages[i]); } ABC_FREE(nodePages); for (i = 0; i <= page; i++) { ABC_FREE(lightNodePages[i]); } ABC_FREE(lightNodePages); for (i = 0; i <= nodeDataPage; i++) { ABC_FREE(nodeDataPages[i]); } ABC_FREE(nodeDataPages); st__free_table(visitedTable); ABC_FREE(size); #if 0 (void) Cudd_DebugCheck(dd); (void) Cudd_CheckKeys(dd); #endif if (subset != NULL) { #ifdef DD_DEBUG if (!Cudd_bddLeq(dd, subset, f)) { fprintf(dd->err, "Wrong subset\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } #endif cuddDeref(subset); return(subset); } else { return(NULL); } } /* end of cuddSubsetHeavyBranch */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Resize the number of pages allocated to store the node data.] Description [Resize the number of pages allocated to store the node data The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.] SideEffects [Changes the size of pages, page, page index, maximum number of pages freeing stuff in case of memory out. ] SeeAlso [] ******************************************************************************/ static void ResizeNodeDataPages(void) { int i; NodeData_t **newNodeDataPages; nodeDataPage++; /* If the current page index is larger than the number of pages * allocated, allocate a new page array. Page numbers are incremented by * INITIAL_PAGES */ if (nodeDataPage == maxNodeDataPages) { newNodeDataPages = ABC_ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES); if (newNodeDataPages == NULL) { for (i = 0; i < nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); memOut = 1; return; } else { for (i = 0; i < maxNodeDataPages; i++) { newNodeDataPages[i] = nodeDataPages[i]; } /* Increase total page count */ maxNodeDataPages += INITIAL_PAGES; ABC_FREE(nodeDataPages); nodeDataPages = newNodeDataPages; } } /* Allocate a new page */ currentNodeDataPage = nodeDataPages[nodeDataPage] = ABC_ALLOC(NodeData_t ,nodeDataPageSize); if (currentNodeDataPage == NULL) { for (i = 0; i < nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); memOut = 1; return; } /* reset page index */ nodeDataPageIndex = 0; return; } /* end of ResizeNodeDataPages */ /**Function******************************************************************** Synopsis [Resize the number of pages allocated to store the minterm counts. ] Description [Resize the number of pages allocated to store the minterm counts. The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.] SideEffects [Changes the size of minterm pages, page, page index, maximum number of pages freeing stuff in case of memory out. ] SeeAlso [] ******************************************************************************/ static void ResizeCountMintermPages(void) { int i; double **newMintermPages; page++; /* If the current page index is larger than the number of pages * allocated, allocate a new page array. Page numbers are incremented by * INITIAL_PAGES */ if (page == maxPages) { newMintermPages = ABC_ALLOC(double *,maxPages + INITIAL_PAGES); if (newMintermPages == NULL) { for (i = 0; i < page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); memOut = 1; return; } else { for (i = 0; i < maxPages; i++) { newMintermPages[i] = mintermPages[i]; } /* Increase total page count */ maxPages += INITIAL_PAGES; ABC_FREE(mintermPages); mintermPages = newMintermPages; } } /* Allocate a new page */ currentMintermPage = mintermPages[page] = ABC_ALLOC(double,pageSize); if (currentMintermPage == NULL) { for (i = 0; i < page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); memOut = 1; return; } /* reset page index */ pageIndex = 0; return; } /* end of ResizeCountMintermPages */ /**Function******************************************************************** Synopsis [Resize the number of pages allocated to store the node counts.] Description [Resize the number of pages allocated to store the node counts. The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.] SideEffects [Changes the size of pages, page, page index, maximum number of pages freeing stuff in case of memory out.] SeeAlso [] ******************************************************************************/ static void ResizeCountNodePages(void) { int i; int **newNodePages; page++; /* If the current page index is larger than the number of pages * allocated, allocate a new page array. The number of pages is incremented * by INITIAL_PAGES. */ if (page == maxPages) { newNodePages = ABC_ALLOC(int *,maxPages + INITIAL_PAGES); if (newNodePages == NULL) { for (i = 0; i < page; i++) ABC_FREE(nodePages[i]); ABC_FREE(nodePages); for (i = 0; i < page; i++) ABC_FREE(lightNodePages[i]); ABC_FREE(lightNodePages); memOut = 1; return; } else { for (i = 0; i < maxPages; i++) { newNodePages[i] = nodePages[i]; } ABC_FREE(nodePages); nodePages = newNodePages; } newNodePages = ABC_ALLOC(int *,maxPages + INITIAL_PAGES); if (newNodePages == NULL) { for (i = 0; i < page; i++) ABC_FREE(nodePages[i]); ABC_FREE(nodePages); for (i = 0; i < page; i++) ABC_FREE(lightNodePages[i]); ABC_FREE(lightNodePages); memOut = 1; return; } else { for (i = 0; i < maxPages; i++) { newNodePages[i] = lightNodePages[i]; } ABC_FREE(lightNodePages); lightNodePages = newNodePages; } /* Increase total page count */ maxPages += INITIAL_PAGES; } /* Allocate a new page */ currentNodePage = nodePages[page] = ABC_ALLOC(int,pageSize); if (currentNodePage == NULL) { for (i = 0; i < page; i++) ABC_FREE(nodePages[i]); ABC_FREE(nodePages); for (i = 0; i < page; i++) ABC_FREE(lightNodePages[i]); ABC_FREE(lightNodePages); memOut = 1; return; } /* Allocate a new page */ currentLightNodePage = lightNodePages[page] = ABC_ALLOC(int,pageSize); if (currentLightNodePage == NULL) { for (i = 0; i <= page; i++) ABC_FREE(nodePages[i]); ABC_FREE(nodePages); for (i = 0; i < page; i++) ABC_FREE(lightNodePages[i]); ABC_FREE(lightNodePages); memOut = 1; return; } /* reset page index */ pageIndex = 0; return; } /* end of ResizeCountNodePages */ /**Function******************************************************************** Synopsis [Recursively counts minterms of each node in the DAG.] Description [Recursively counts minterms of each node in the DAG. Similar to the cuddCountMintermAux which recursively counts the number of minterms for the dag rooted at each node in terms of the total number of variables (max). This procedure creates the node data structure and stores the minterm count as part of the node data structure. ] SideEffects [Creates structures of type node quality and fills the st__table] SeeAlso [SubsetCountMinterm] ******************************************************************************/ static double SubsetCountMintermAux( DdNode * node /* function to analyze */, double max /* number of minterms of constant 1 */, st__table * table /* visitedTable table */) { DdNode *N,*Nv,*Nnv; /* nodes to store cofactors */ double min,*pmin; /* minterm count */ double min1, min2; /* minterm count */ NodeData_t *dummy; NodeData_t *newEntry; int i; #ifdef DEBUG num_calls++; #endif /* Constant case */ if (Cudd_IsConstant(node)) { if (node == zero) { return(0.0); } else { return(max); } } else { /* check if entry for this node exists */ if ( st__lookup(table, (const char *)node, (char **)&dummy)) { min = *(dummy->mintermPointer); return(min); } /* Make the node regular to extract cofactors */ N = Cudd_Regular(node); /* store the cofactors */ Nv = Cudd_T(N); Nnv = Cudd_E(N); Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); min1 = SubsetCountMintermAux(Nv, max,table)/2.0; if (memOut) return(0.0); min2 = SubsetCountMintermAux(Nnv,max,table)/2.0; if (memOut) return(0.0); min = (min1+min2); /* if page index is at the bottom, then create a new page */ if (pageIndex == pageSize) ResizeCountMintermPages(); if (memOut) { for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); st__free_table(table); return(0.0); } /* point to the correct location in the page */ pmin = currentMintermPage+pageIndex; pageIndex++; /* store the minterm count of this node in the page */ *pmin = min; /* Note I allocate the struct here. Freeing taken care of later */ if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages(); if (memOut) { for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); st__free_table(table); return(0.0); } newEntry = currentNodeDataPage + nodeDataPageIndex; nodeDataPageIndex++; /* points to the correct location in the page */ newEntry->mintermPointer = pmin; /* initialize this field of the Node Quality structure */ newEntry->nodesPointer = NULL; /* insert entry for the node in the table */ if ( st__insert(table,(char *)node, (char *)newEntry) == st__OUT_OF_MEM) { memOut = 1; for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); st__free_table(table); return(0.0); } return(min); } } /* end of SubsetCountMintermAux */ /**Function******************************************************************** Synopsis [Counts minterms of each node in the DAG] Description [Counts minterms of each node in the DAG. Similar to the Cudd_CountMinterm procedure except this returns the minterm count for all the nodes in the bdd in an st__table.] SideEffects [none] SeeAlso [SubsetCountMintermAux] ******************************************************************************/ static st__table * SubsetCountMinterm( DdNode * node /* function to be analyzed */, int nvars /* number of variables node depends on */) { st__table *table; int i; #ifdef DEBUG num_calls = 0; #endif max = pow(2.0,(double) nvars); table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) goto OUT_OF_MEM; maxPages = INITIAL_PAGES; mintermPages = ABC_ALLOC(double *,maxPages); if (mintermPages == NULL) { st__free_table(table); goto OUT_OF_MEM; } page = 0; currentMintermPage = ABC_ALLOC(double,pageSize); mintermPages[page] = currentMintermPage; if (currentMintermPage == NULL) { ABC_FREE(mintermPages); st__free_table(table); goto OUT_OF_MEM; } pageIndex = 0; maxNodeDataPages = INITIAL_PAGES; nodeDataPages = ABC_ALLOC(NodeData_t *, maxNodeDataPages); if (nodeDataPages == NULL) { for (i = 0; i <= page ; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); st__free_table(table); goto OUT_OF_MEM; } nodeDataPage = 0; currentNodeDataPage = ABC_ALLOC(NodeData_t ,nodeDataPageSize); nodeDataPages[nodeDataPage] = currentNodeDataPage; if (currentNodeDataPage == NULL) { for (i = 0; i <= page ; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); ABC_FREE(nodeDataPages); st__free_table(table); goto OUT_OF_MEM; } nodeDataPageIndex = 0; (void) SubsetCountMintermAux(node,max,table); if (memOut) goto OUT_OF_MEM; return(table); OUT_OF_MEM: memOut = 1; return(NULL); } /* end of SubsetCountMinterm */ /**Function******************************************************************** Synopsis [Recursively counts the number of nodes under the dag. Also counts the number of nodes under the lighter child of this node.] Description [Recursively counts the number of nodes under the dag. Also counts the number of nodes under the lighter child of this node. . Note that the same dag may be the lighter child of two different nodes and have different counts. As with the minterm counts, the node counts are stored in pages to be space efficient and the address for these node counts are stored in an st__table associated to each node. ] SideEffects [Updates the node data table with node counts] SeeAlso [SubsetCountNodes] ******************************************************************************/ static int SubsetCountNodesAux( DdNode * node /* current node */, st__table * table /* table to update node count, also serves as visited table. */, double max /* maximum number of variables */) { int tval, eval, i; DdNode *N, *Nv, *Nnv; double minNv, minNnv; NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar; int *pmin, *pminBar, *val; if ((node == NULL) || Cudd_IsConstant(node)) return(0); /* if this node has been processed do nothing */ if ( st__lookup(table, (const char *)node, (char **)&dummyN) == 1) { val = dummyN->nodesPointer; if (val != NULL) return(0); } else { return(0); } N = Cudd_Regular(node); Nv = Cudd_T(N); Nnv = Cudd_E(N); Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); /* find the minterm counts for the THEN and ELSE branches */ if (Cudd_IsConstant(Nv)) { if (Nv == zero) { minNv = 0.0; } else { minNv = max; } } else { if ( st__lookup(table, (const char *)Nv, (char **)&dummyNv) == 1) minNv = *(dummyNv->mintermPointer); else { return(0); } } if (Cudd_IsConstant(Nnv)) { if (Nnv == zero) { minNnv = 0.0; } else { minNnv = max; } } else { if ( st__lookup(table, (const char *)Nnv, (char **)&dummyNnv) == 1) { minNnv = *(dummyNnv->mintermPointer); } else { return(0); } } /* recur based on which has larger minterm, */ if (minNv >= minNnv) { tval = SubsetCountNodesAux(Nv, table, max); if (memOut) return(0); eval = SubsetCountNodesAux(Nnv, table, max); if (memOut) return(0); /* store the node count of the lighter child. */ if (pageIndex == pageSize) ResizeCountNodePages(); if (memOut) { for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); st__free_table(table); return(0); } pmin = currentLightNodePage + pageIndex; *pmin = eval; /* Here the ELSE child is lighter */ dummyN->lightChildNodesPointer = pmin; } else { eval = SubsetCountNodesAux(Nnv, table, max); if (memOut) return(0); tval = SubsetCountNodesAux(Nv, table, max); if (memOut) return(0); /* store the node count of the lighter child. */ if (pageIndex == pageSize) ResizeCountNodePages(); if (memOut) { for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); st__free_table(table); return(0); } pmin = currentLightNodePage + pageIndex; *pmin = tval; /* Here the THEN child is lighter */ dummyN->lightChildNodesPointer = pmin; } /* updating the page index for node count storage. */ pmin = currentNodePage + pageIndex; *pmin = tval + eval + 1; dummyN->nodesPointer = pmin; /* pageIndex is parallel page index for count_nodes and count_lightNodes */ pageIndex++; /* if this node has been reached first, it belongs to a heavier branch. Its complement will be reached later on a lighter branch. Hence the complement has zero node count. */ if ( st__lookup(table, (const char *)Cudd_Not(node), (char **)&dummyNBar) == 1) { if (pageIndex == pageSize) ResizeCountNodePages(); if (memOut) { for (i = 0; i < page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); for (i = 0; i < nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); st__free_table(table); return(0); } pminBar = currentLightNodePage + pageIndex; *pminBar = 0; dummyNBar->lightChildNodesPointer = pminBar; /* The lighter child has less nodes than the parent. * So if parent 0 then lighter child zero */ if (pageIndex == pageSize) ResizeCountNodePages(); if (memOut) { for (i = 0; i < page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); for (i = 0; i < nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); st__free_table(table); return(0); } pminBar = currentNodePage + pageIndex; *pminBar = 0; dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */ pageIndex++; } return(*pmin); } /*end of SubsetCountNodesAux */ /**Function******************************************************************** Synopsis [Counts the nodes under the current node and its lighter child] Description [Counts the nodes under the current node and its lighter child. Calls a recursive procedure to count the number of nodes of a DAG rooted at a particular node and the number of nodes taken by its lighter child.] SideEffects [None] SeeAlso [SubsetCountNodesAux] ******************************************************************************/ static int SubsetCountNodes( DdNode * node /* function to be analyzed */, st__table * table /* node quality table */, int nvars /* number of variables node depends on */) { int num; int i; #ifdef DEBUG num_calls = 0; #endif max = pow(2.0,(double) nvars); maxPages = INITIAL_PAGES; nodePages = ABC_ALLOC(int *,maxPages); if (nodePages == NULL) { goto OUT_OF_MEM; } lightNodePages = ABC_ALLOC(int *,maxPages); if (lightNodePages == NULL) { for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); ABC_FREE(nodePages); goto OUT_OF_MEM; } page = 0; currentNodePage = nodePages[page] = ABC_ALLOC(int,pageSize); if (currentNodePage == NULL) { for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); ABC_FREE(lightNodePages); ABC_FREE(nodePages); goto OUT_OF_MEM; } currentLightNodePage = lightNodePages[page] = ABC_ALLOC(int,pageSize); if (currentLightNodePage == NULL) { for (i = 0; i <= page; i++) ABC_FREE(mintermPages[i]); ABC_FREE(mintermPages); for (i = 0; i <= nodeDataPage; i++) ABC_FREE(nodeDataPages[i]); ABC_FREE(nodeDataPages); ABC_FREE(currentNodePage); ABC_FREE(lightNodePages); ABC_FREE(nodePages); goto OUT_OF_MEM; } pageIndex = 0; num = SubsetCountNodesAux(node,table,max); if (memOut) goto OUT_OF_MEM; return(num); OUT_OF_MEM: memOut = 1; return(0); } /* end of SubsetCountNodes */ /**Function******************************************************************** Synopsis [Procedure to recursively store nodes that are retained in the subset.] Description [rocedure to recursively store nodes that are retained in the subset.] SideEffects [None] SeeAlso [StoreNodes] ******************************************************************************/ static void StoreNodes( st__table * storeTable, DdManager * dd, DdNode * node) { DdNode *N, *Nt, *Ne; if (Cudd_IsConstant(dd)) { return; } N = Cudd_Regular(node); if ( st__lookup(storeTable, (char *)N, NIL(char *))) { return; } cuddRef(N); if ( st__insert(storeTable, (char *)N, NIL(char)) == st__OUT_OF_MEM) { fprintf(dd->err,"Something wrong, st__table insert failed\n"); } Nt = Cudd_T(N); Ne = Cudd_E(N); StoreNodes(storeTable, dd, Nt); StoreNodes(storeTable, dd, Ne); return; } /**Function******************************************************************** Synopsis [Builds the subset BDD using the heavy branch method.] Description [The procedure carries out the building of the subset BDD starting at the root. Using the three different counts labelling each node, the procedure chooses the heavier branch starting from the root and keeps track of the number of nodes it discards at each step, thus keeping count of the size of the subset BDD dynamically. Once the threshold is satisfied, the procedure then calls ITE to build the BDD.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * BuildSubsetBdd( DdManager * dd /* DD manager */, DdNode * node /* current node */, int * size /* current size of the subset */, st__table * visitedTable /* visited table storing all node data */, int threshold, st__table * storeTable, st__table * approxTable) { DdNode *Nv, *Nnv, *N, *topv, *neW; double minNv, minNnv; NodeData_t *currNodeQual; NodeData_t *currNodeQualT; NodeData_t *currNodeQualE; DdNode *ThenBranch, *ElseBranch; unsigned int topid; char *dummy; #ifdef DEBUG num_calls++; #endif /*If the size of the subset is below the threshold, dont do anything. */ if ((*size) <= threshold) { /* store nodes below this, so we can recombine if possible */ StoreNodes(storeTable, dd, node); return(node); } if (Cudd_IsConstant(node)) return(node); /* Look up minterm count for this node. */ if (! st__lookup(visitedTable, (const char *)node, (char **)&currNodeQual)) { fprintf(dd->err, "Something is wrong, ought to be in node quality table\n"); } /* Get children. */ N = Cudd_Regular(node); Nv = Cudd_T(N); Nnv = Cudd_E(N); /* complement if necessary */ Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); if (!Cudd_IsConstant(Nv)) { /* find out minterms and nodes contributed by then child */ if (! st__lookup(visitedTable, (const char *)Nv, (char **)&currNodeQualT)) { fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } else { minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer); } } else { if (Nv == zero) { minNv = 0; } else { minNv = max; } } if (!Cudd_IsConstant(Nnv)) { /* find out minterms and nodes contributed by else child */ if (! st__lookup(visitedTable, (const char *)Nnv, (char **)&currNodeQualE)) { fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } else { minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer); } } else { if (Nnv == zero) { minNnv = 0; } else { minNnv = max; } } /* keep track of size of subset by subtracting the number of * differential nodes contributed by lighter child */ *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer); if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes the Then branch in case of a tie */ /* recur with the Then branch */ ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size, visitedTable, threshold, storeTable, approxTable); if (ThenBranch == NULL) { return(NULL); } cuddRef(ThenBranch); /* The Else branch is either a node that already exists in the * subset, or one whose approximation has been computed, or * Zero. */ if ( st__lookup(storeTable, (char *)Cudd_Regular(Nnv), &dummy)) { ElseBranch = Nnv; cuddRef(ElseBranch); } else { if ( st__lookup(approxTable, (char *)Nnv, &dummy)) { ElseBranch = (DdNode *)dummy; cuddRef(ElseBranch); } else { ElseBranch = zero; cuddRef(ElseBranch); } } } else { /* recur with the Else branch */ ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size, visitedTable, threshold, storeTable, approxTable); if (ElseBranch == NULL) { return(NULL); } cuddRef(ElseBranch); /* The Then branch is either a node that already exists in the * subset, or one whose approximation has been computed, or * Zero. */ if ( st__lookup(storeTable, (char *)Cudd_Regular(Nv), &dummy)) { ThenBranch = Nv; cuddRef(ThenBranch); } else { if ( st__lookup(approxTable, (char *)Nv, &dummy)) { ThenBranch = (DdNode *)dummy; cuddRef(ThenBranch); } else { ThenBranch = zero; cuddRef(ThenBranch); } } } /* construct the Bdd with the top variable and the two children */ topid = Cudd_NodeReadIndex(N); topv = Cudd_ReadVars(dd, topid); cuddRef(topv); neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); if (neW != NULL) { cuddRef(neW); } Cudd_RecursiveDeref(dd, topv); Cudd_RecursiveDeref(dd, ThenBranch); Cudd_RecursiveDeref(dd, ElseBranch); if (neW == NULL) return(NULL); else { /* store this node in the store table */ if (! st__lookup(storeTable, (char *)Cudd_Regular(neW), &dummy)) { cuddRef(neW); if (! st__insert(storeTable, (char *)Cudd_Regular(neW), NIL(char))) return (NULL); } /* store the approximation for this node */ if (N != Cudd_Regular(neW)) { if ( st__lookup(approxTable, (char *)node, &dummy)) { fprintf(dd->err, "This node should not be in the approximated table\n"); } else { cuddRef(neW); if (! st__insert(approxTable, (char *)node, (char *)neW)) return(NULL); } } cuddDeref(neW); return(neW); } } /* end of BuildSubsetBdd */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddSubsetSP.c000066400000000000000000001725071300674244400242340ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddSubsetSP.c] PackageName [cudd] Synopsis [Procedure to subset the given BDD choosing the shortest paths (largest cubes) in the BDD.] Description [External procedures included in this module:
        • Cudd_SubsetShortPaths()
        • Cudd_SupersetShortPaths()
        Internal procedures included in this module:
        • cuddSubsetShortPaths()
        Static procedures included in this module:
        • BuildSubsetBdd()
        • CreatePathTable()
        • AssessPathLength()
        • CreateTopDist()
        • CreateBotDist()
        • ResizeNodeDistPages()
        • ResizeQueuePages()
        • stPathTableDdFree()
        ] SeeAlso [cuddSubsetHB.c] Author [Kavita Ravi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DEFAULT_PAGE_SIZE 2048 /* page size to store the BFS queue element type */ #define DEFAULT_NODE_DIST_PAGE_SIZE 2048 /* page sizesto store NodeDist_t type */ #define MAXSHORTINT ((DdHalfWord) ~0) /* constant defined to store * maximum distance of a node * from the root or the * constant */ #define INITIAL_PAGES 128 /* number of initial pages for the * queue/NodeDist_t type */ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /* structure created to store subset results for each node and distances with * odd and even parity of the node from the root and sink. Main data structure * in this procedure. */ struct NodeDist{ DdHalfWord oddTopDist; DdHalfWord evenTopDist; DdHalfWord oddBotDist; DdHalfWord evenBotDist; DdNode *regResult; DdNode *compResult; }; /* assorted information needed by the BuildSubsetBdd procedure. */ struct AssortedInfo { unsigned int maxpath; int findShortestPath; int thresholdReached; st__table *maxpathTable; int threshold; }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ typedef struct NodeDist NodeDist_t; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.34 2009/02/19 16:23:19 fabio Exp $"; #endif #ifdef DD_DEBUG static int numCalls; static int hits; static int thishit; #endif static int memOut; /* flag to indicate out of memory */ static DdNode *zero, *one; /* constant functions */ static NodeDist_t **nodeDistPages; /* pointers to the pages */ static int nodeDistPageIndex; /* index to next element */ static int nodeDistPage; /* index to current page */ static int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE; /* page size */ static int maxNodeDistPages; /* number of page pointers */ static NodeDist_t *currentNodeDistPage; /* current page */ static DdNode ***queuePages; /* pointers to the pages */ static int queuePageIndex; /* index to next element */ static int queuePage; /* index to current page */ static int queuePageSize = DEFAULT_PAGE_SIZE; /* page size */ static int maxQueuePages; /* number of page pointers */ static DdNode **currentQueuePage; /* current page */ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void ResizeNodeDistPages (void); static void ResizeQueuePages (void); static void CreateTopDist ( st__table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp); static int CreateBotDist (DdNode *node, st__table *pathTable, unsigned int *pathLengthArray, FILE *fp); static st__table * CreatePathTable (DdNode *node, unsigned int *pathLengthArray, FILE *fp); static unsigned int AssessPathLength (unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp); static DdNode * BuildSubsetBdd (DdManager *dd, st__table *pathTable, DdNode *node, struct AssortedInfo *info, st__table *subsetNodeTable); static enum st__retval stPathTableDdFree (char *key, char *value, char *arg); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of Exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Extracts a dense subset from a BDD with the shortest paths heuristic.] Description [Extracts a dense subset from a BDD. This procedure tries to preserve the shortest paths of the input BDD, because they give many minterms and contribute few nodes. This procedure may increase the number of nodes in trying to create the subset or reduce the number of nodes due to recombination as compared to the original BDD. Hence the threshold may not be strictly adhered to. In practice, recombination overshadows the increase in the number of nodes and results in small BDDs as compared to the threshold. The hardlimit specifies whether threshold needs to be strictly adhered to. If it is set to 1, the procedure ensures that result is never larger than the specified limit but may be considerably less than the threshold. Returns a pointer to the BDD for the subset if successful; NULL otherwise. The value for numVars should be as close as possible to the size of the support of f for better efficiency. However, it is safe to pass the value returned by Cudd_ReadSize for numVars. If 0 is passed, then the value returned by Cudd_ReadSize is used.] SideEffects [None] SeeAlso [Cudd_SupersetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_SubsetShortPaths( DdManager * dd /* manager */, DdNode * f /* function to be subset */, int numVars /* number of variables in the support of f */, int threshold /* maximum number of nodes in the subset */, int hardlimit /* flag: 1 if threshold is a hard limit */) { DdNode *subset; memOut = 0; do { dd->reordered = 0; subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit); } while((dd->reordered ==1) && (!memOut)); return(subset); } /* end of Cudd_SubsetShortPaths */ /**Function******************************************************************** Synopsis [Extracts a dense superset from a BDD with the shortest paths heuristic.] Description [Extracts a dense superset from a BDD. The procedure is identical to the subset procedure except for the fact that it receives the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. This procedure tries to preserve the shortest paths of the complement BDD, because they give many minterms and contribute few nodes. This procedure may increase the number of nodes in trying to create the superset or reduce the number of nodes due to recombination as compared to the original BDD. Hence the threshold may not be strictly adhered to. In practice, recombination overshadows the increase in the number of nodes and results in small BDDs as compared to the threshold. The hardlimit specifies whether threshold needs to be strictly adhered to. If it is set to 1, the procedure ensures that result is never larger than the specified limit but may be considerably less than the threshold. Returns a pointer to the BDD for the superset if successful; NULL otherwise. The value for numVars should be as close as possible to the size of the support of f for better efficiency. However, it is safe to pass the value returned by Cudd_ReadSize for numVar. If 0 is passed, then the value returned by Cudd_ReadSize is used.] SideEffects [None] SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize] ******************************************************************************/ DdNode * Cudd_SupersetShortPaths( DdManager * dd /* manager */, DdNode * f /* function to be superset */, int numVars /* number of variables in the support of f */, int threshold /* maximum number of nodes in the subset */, int hardlimit /* flag: 1 if threshold is a hard limit */) { DdNode *subset, *g; g = Cudd_Not(f); memOut = 0; do { dd->reordered = 0; subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit); } while((dd->reordered ==1) && (!memOut)); return(Cudd_NotCond(subset, (subset != NULL))); } /* end of Cudd_SupersetShortPaths */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [The outermost procedure to return a subset of the given BDD with the shortest path lengths.] Description [The outermost procedure to return a subset of the given BDD with the largest cubes. The path lengths are calculated, the maximum allowable path length is determined and the number of nodes of this path length that can be used to build a subset. If the threshold is larger than the size of the original BDD, the original BDD is returned. ] SideEffects [None] SeeAlso [Cudd_SubsetShortPaths] ******************************************************************************/ DdNode * cuddSubsetShortPaths( DdManager * dd /* DD manager */, DdNode * f /* function to be subset */, int numVars /* total number of variables in consideration */, int threshold /* maximum number of nodes allowed in the subset */, int hardlimit /* flag determining whether thershold should be respected strictly */) { st__table *pathTable; DdNode *N, *subset; unsigned int *pathLengthArray; unsigned int maxpath, oddLen, evenLen, pathLength, *excess; int i; NodeDist_t *nodeStat; struct AssortedInfo *info; st__table *subsetNodeTable; one = DD_ONE(dd); zero = Cudd_Not(one); if (numVars == 0) { /* set default value */ numVars = Cudd_ReadSize(dd); } if (threshold > numVars) { threshold = threshold - numVars; } if (f == NULL) { fprintf(dd->err, "Cannot partition, nil object\n"); dd->errorCode = CUDD_INVALID_ARG; return(NULL); } if (Cudd_IsConstant(f)) return (f); pathLengthArray = ABC_ALLOC(unsigned int, numVars+1); for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0; #ifdef DD_DEBUG numCalls = 0; #endif pathTable = CreatePathTable(f, pathLengthArray, dd->err); if ((pathTable == NULL) || (memOut)) { if (pathTable != NULL) st__free_table(pathTable); ABC_FREE(pathLengthArray); return (NIL(DdNode)); } excess = ABC_ALLOC(unsigned int, 1); *excess = 0; maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess, dd->err); if (maxpath != (unsigned) (numVars + 1)) { info = ABC_ALLOC(struct AssortedInfo, 1); info->maxpath = maxpath; info->findShortestPath = 0; info->thresholdReached = *excess; info->maxpathTable = st__init_table( st__ptrcmp, st__ptrhash); info->threshold = threshold; #ifdef DD_DEBUG (void) fprintf(dd->out, "Path length array\n"); for (i = 0; i < (numVars+1); i++) { if (pathLengthArray[i]) (void) fprintf(dd->out, "%d ",i); } (void) fprintf(dd->out, "\n"); for (i = 0; i < (numVars+1); i++) { if (pathLengthArray[i]) (void) fprintf(dd->out, "%d ",pathLengthArray[i]); } (void) fprintf(dd->out, "\n"); (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n", maxpath, info->thresholdReached); #endif N = Cudd_Regular(f); if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) { fprintf(dd->err, "Something wrong, root node must be in table\n"); dd->errorCode = CUDD_INTERNAL_ERROR; ABC_FREE(excess); ABC_FREE(info); return(NULL); } else { if ((nodeStat->oddTopDist != MAXSHORTINT) && (nodeStat->oddBotDist != MAXSHORTINT)) oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); else oddLen = MAXSHORTINT; if ((nodeStat->evenTopDist != MAXSHORTINT) && (nodeStat->evenBotDist != MAXSHORTINT)) evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); else evenLen = MAXSHORTINT; pathLength = (oddLen <= evenLen) ? oddLen : evenLen; if (pathLength > maxpath) { (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %u, %u\n", maxpath, pathLength); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } } #ifdef DD_DEBUG numCalls = 0; hits = 0; thishit = 0; #endif /* initialize a table to store computed nodes */ if (hardlimit) { subsetNodeTable = st__init_table( st__ptrcmp, st__ptrhash); } else { subsetNodeTable = NIL( st__table); } subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable); if (subset != NULL) { cuddRef(subset); } /* record the number of times a computed result for a node is hit */ #ifdef DD_DEBUG (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n", hits, thishit, numCalls); #endif if (subsetNodeTable != NIL( st__table)) { st__free_table(subsetNodeTable); } st__free_table(info->maxpathTable); st__foreach(pathTable, stPathTableDdFree, (char *)dd); ABC_FREE(info); } else {/* if threshold larger than size of dd */ subset = f; cuddRef(subset); } ABC_FREE(excess); st__free_table(pathTable); ABC_FREE(pathLengthArray); for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); #ifdef DD_DEBUG /* check containment of subset in f */ if (subset != NULL) { DdNode *check; check = Cudd_bddIteConstant(dd, subset, f, one); if (check != one) { (void) fprintf(dd->err, "Wrong partition\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } } #endif if (subset != NULL) { cuddDeref(subset); return(subset); } else { return(NULL); } } /* end of cuddSubsetShortPaths */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Resize the number of pages allocated to store the distances related to each node.] Description [Resize the number of pages allocated to store the distances related to each node. The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary. ] SideEffects [Changes the size of pages, page, page index, maximum number of pages freeing stuff in case of memory out. ] SeeAlso [] ******************************************************************************/ static void ResizeNodeDistPages(void) { int i; NodeDist_t **newNodeDistPages; /* move to next page */ nodeDistPage++; /* If the current page index is larger than the number of pages * allocated, allocate a new page array. Page numbers are incremented by * INITIAL_PAGES */ if (nodeDistPage == maxNodeDistPages) { newNodeDistPages = ABC_ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES); if (newNodeDistPages == NULL) { for (i = 0; i < nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); memOut = 1; return; } else { for (i = 0; i < maxNodeDistPages; i++) { newNodeDistPages[i] = nodeDistPages[i]; } /* Increase total page count */ maxNodeDistPages += INITIAL_PAGES; ABC_FREE(nodeDistPages); nodeDistPages = newNodeDistPages; } } /* Allocate a new page */ currentNodeDistPage = nodeDistPages[nodeDistPage] = ABC_ALLOC(NodeDist_t, nodeDistPageSize); if (currentNodeDistPage == NULL) { for (i = 0; i < nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); memOut = 1; return; } /* reset page index */ nodeDistPageIndex = 0; return; } /* end of ResizeNodeDistPages */ /**Function******************************************************************** Synopsis [Resize the number of pages allocated to store nodes in the BFS traversal of the Bdd .] Description [Resize the number of pages allocated to store nodes in the BFS traversal of the Bdd. The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.] SideEffects [Changes the size of pages, page, page index, maximum number of pages freeing stuff in case of memory out. ] SeeAlso [] ******************************************************************************/ static void ResizeQueuePages(void) { int i; DdNode ***newQueuePages; queuePage++; /* If the current page index is larger than the number of pages * allocated, allocate a new page array. Page numbers are incremented by * INITIAL_PAGES */ if (queuePage == maxQueuePages) { newQueuePages = ABC_ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES); if (newQueuePages == NULL) { for (i = 0; i < queuePage; i++) ABC_FREE(queuePages[i]); ABC_FREE(queuePages); memOut = 1; return; } else { for (i = 0; i < maxQueuePages; i++) { newQueuePages[i] = queuePages[i]; } /* Increase total page count */ maxQueuePages += INITIAL_PAGES; ABC_FREE(queuePages); queuePages = newQueuePages; } } /* Allocate a new page */ currentQueuePage = queuePages[queuePage] = ABC_ALLOC(DdNode *,queuePageSize); if (currentQueuePage == NULL) { for (i = 0; i < queuePage; i++) ABC_FREE(queuePages[i]); ABC_FREE(queuePages); memOut = 1; return; } /* reset page index */ queuePageIndex = 0; return; } /* end of ResizeQueuePages */ /**Function******************************************************************** Synopsis [ Labels each node with its shortest distance from the root] Description [ Labels each node with its shortest distance from the root. This is done in a BFS search of the BDD. The nodes are processed in a queue implemented as pages(array) to reduce memory fragmentation. An entry is created for each node visited. The distance from the root to the node with the corresponding parity is updated. The procedure is called recursively each recusion level handling nodes at a given level from the root.] SideEffects [Creates entries in the pathTable] SeeAlso [CreatePathTable CreateBotDist] ******************************************************************************/ static void CreateTopDist( st__table * pathTable /* hast table to store path lengths */, int parentPage /* the pointer to the page on which the first parent in the queue is to be found. */, int parentQueueIndex /* pointer to the first parent on the page */, int topLen /* current distance from the root */, DdNode ** childPage /* pointer to the page on which the first child is to be added. */, int childQueueIndex /* pointer to the first child */, int numParents /* number of parents to process in this recursive call */, FILE *fp /* where to write messages */) { NodeDist_t *nodeStat; DdNode *N, *Nv, *Nnv, *node, *child, *regChild; int i; int processingDone, childrenCount; #ifdef DD_DEBUG numCalls++; /* assume this procedure comes in with only the root node*/ /* set queue index to the next available entry for addition */ /* set queue page to page of addition */ if ((queuePages[parentPage] == childPage) && (parentQueueIndex == childQueueIndex)) { fprintf(fp, "Should not happen that they are equal\n"); } assert(queuePageIndex == childQueueIndex); assert(currentQueuePage == childPage); #endif /* number children added to queue is initialized , needed for * numParents in the next call */ childrenCount = 0; /* process all the nodes in this level */ while (numParents) { numParents--; if (parentQueueIndex == queuePageSize) { parentPage++; parentQueueIndex = 0; } /* a parent to process */ node = *(queuePages[parentPage] + parentQueueIndex); parentQueueIndex++; /* get its children */ N = Cudd_Regular(node); Nv = Cudd_T(N); Nnv = Cudd_E(N); Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); processingDone = 2; while (processingDone) { /* processing the THEN and the ELSE children, the THEN * child first */ if (processingDone == 2) { child = Nv; } else { child = Nnv; } regChild = Cudd_Regular(child); /* dont process if the child is a constant */ if (!Cudd_IsConstant(child)) { /* check is already visited, if not add a new entry in * the path Table */ if (! st__lookup(pathTable, (const char *)regChild, (char **)&nodeStat)) { /* if not in table, has never been visited */ /* create entry for table */ if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages(); if (memOut) { for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]); ABC_FREE(queuePages); st__free_table(pathTable); return; } /* New entry for child in path Table is created here */ nodeStat = currentNodeDistPage + nodeDistPageIndex; nodeDistPageIndex++; /* Initialize fields of the node data */ nodeStat->oddTopDist = MAXSHORTINT; nodeStat->evenTopDist = MAXSHORTINT; nodeStat->evenBotDist = MAXSHORTINT; nodeStat->oddBotDist = MAXSHORTINT; nodeStat->regResult = NULL; nodeStat->compResult = NULL; /* update the table entry element, the distance keeps * track of the parity of the path from the root */ if (Cudd_IsComplement(child)) { nodeStat->oddTopDist = (DdHalfWord) topLen + 1; } else { nodeStat->evenTopDist = (DdHalfWord) topLen + 1; } /* insert entry element for child in the table */ if ( st__insert(pathTable, (char *)regChild, (char *)nodeStat) == st__OUT_OF_MEM) { memOut = 1; for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]); ABC_FREE(queuePages); st__free_table(pathTable); return; } /* Create list element for this child to process its children. * If this node has been processed already, then it appears * in the path table and hence is never added to the list * again. */ if (queuePageIndex == queuePageSize) ResizeQueuePages(); if (memOut) { for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); st__free_table(pathTable); return; } *(currentQueuePage + queuePageIndex) = child; queuePageIndex++; childrenCount++; } else { /* if not been met in a path with this parity before */ /* put in list */ if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist == MAXSHORTINT)) || ((!Cudd_IsComplement(child)) && (nodeStat->evenTopDist == MAXSHORTINT))) { if (queuePageIndex == queuePageSize) ResizeQueuePages(); if (memOut) { for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); st__free_table(pathTable); return; } *(currentQueuePage + queuePageIndex) = child; queuePageIndex++; /* update the distance with the appropriate parity */ if (Cudd_IsComplement(child)) { nodeStat->oddTopDist = (DdHalfWord) topLen + 1; } else { nodeStat->evenTopDist = (DdHalfWord) topLen + 1; } childrenCount++; } } /* end of else (not found in st__table) */ } /*end of if Not constant child */ processingDone--; } /*end of while processing Nv, Nnv */ } /*end of while numParents */ #ifdef DD_DEBUG assert(queuePages[parentPage] == childPage); assert(parentQueueIndex == childQueueIndex); #endif if (childrenCount != 0) { topLen++; childPage = currentQueuePage; childQueueIndex = queuePageIndex; CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen, childPage, childQueueIndex, childrenCount, fp); } return; } /* end of CreateTopDist */ /**Function******************************************************************** Synopsis [ Labels each node with the shortest distance from the constant.] Description [Labels each node with the shortest distance from the constant. This is done in a DFS search of the BDD. Each node has an odd and even parity distance from the sink (since there exists paths to both zero and one) which is less than MAXSHORTINT. At each node these distances are updated using the minimum distance of its children from the constant. SInce now both the length from the root and child is known, the minimum path length(length of the shortest path between the root and the constant that this node lies on) of this node can be calculated and used to update the pathLengthArray] SideEffects [Updates Path Table and path length array] SeeAlso [CreatePathTable CreateTopDist AssessPathLength] ******************************************************************************/ static int CreateBotDist( DdNode * node /* current node */, st__table * pathTable /* path table with path lengths */, unsigned int * pathLengthArray /* array that stores number of nodes belonging to a particular path length. */, FILE *fp /* where to write messages */) { DdNode *N, *Nv, *Nnv; DdNode *realChild; DdNode *child, *regChild; NodeDist_t *nodeStat, *nodeStatChild; unsigned int oddLen, evenLen, pathLength; DdHalfWord botDist; int processingDone; if (Cudd_IsConstant(node)) return(1); N = Cudd_Regular(node); /* each node has one table entry */ /* update as you go down the min dist of each node from the root in each (odd and even) parity */ if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) { fprintf(fp, "Something wrong, the entry doesn't exist\n"); return(0); } /* compute length of odd parity distances */ if ((nodeStat->oddTopDist != MAXSHORTINT) && (nodeStat->oddBotDist != MAXSHORTINT)) oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); else oddLen = MAXSHORTINT; /* compute length of even parity distances */ if (!((nodeStat->evenTopDist == MAXSHORTINT) || (nodeStat->evenBotDist == MAXSHORTINT))) evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); else evenLen = MAXSHORTINT; /* assign pathlength to minimum of the two */ pathLength = (oddLen <= evenLen) ? oddLen : evenLen; Nv = Cudd_T(N); Nnv = Cudd_E(N); /* process each child */ processingDone = 0; while (processingDone != 2) { if (!processingDone) { child = Nv; } else { child = Nnv; } realChild = Cudd_NotCond(child, Cudd_IsComplement(node)); regChild = Cudd_Regular(child); if (Cudd_IsConstant(realChild)) { /* Found a minterm; count parity and shortest distance ** from the constant. */ if (Cudd_IsComplement(child)) nodeStat->oddBotDist = 1; else nodeStat->evenBotDist = 1; } else { /* If node not in table, recur. */ if (! st__lookup(pathTable, (const char *)regChild, (char **)&nodeStatChild)) { fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n"); return(0); } if (nodeStatChild->oddBotDist == MAXSHORTINT) { if (nodeStatChild->evenBotDist == MAXSHORTINT) { if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp)) return(0); } else { fprintf(fp, "Something wrong, both bot nodeStats should be there\n"); return(0); } } /* Update shortest distance from the constant depending on ** parity. */ if (Cudd_IsComplement(child)) { /* If parity on the edge then add 1 to even distance ** of child to get odd parity distance and add 1 to ** odd distance of child to get even parity ** distance. Change distance of current node only if ** the calculated distance is less than existing ** distance. */ if (nodeStatChild->oddBotDist != MAXSHORTINT) botDist = nodeStatChild->oddBotDist + 1; else botDist = MAXSHORTINT; if (nodeStat->evenBotDist > botDist ) nodeStat->evenBotDist = botDist; if (nodeStatChild->evenBotDist != MAXSHORTINT) botDist = nodeStatChild->evenBotDist + 1; else botDist = MAXSHORTINT; if (nodeStat->oddBotDist > botDist) nodeStat->oddBotDist = botDist; } else { /* If parity on the edge then add 1 to even distance ** of child to get even parity distance and add 1 to ** odd distance of child to get odd parity distance. ** Change distance of current node only if the ** calculated distance is lesser than existing ** distance. */ if (nodeStatChild->evenBotDist != MAXSHORTINT) botDist = nodeStatChild->evenBotDist + 1; else botDist = MAXSHORTINT; if (nodeStat->evenBotDist > botDist) nodeStat->evenBotDist = botDist; if (nodeStatChild->oddBotDist != MAXSHORTINT) botDist = nodeStatChild->oddBotDist + 1; else botDist = MAXSHORTINT; if (nodeStat->oddBotDist > botDist) nodeStat->oddBotDist = botDist; } } /* end of else (if not constant child ) */ processingDone++; } /* end of while processing Nv, Nnv */ /* Compute shortest path length on the fly. */ if ((nodeStat->oddTopDist != MAXSHORTINT) && (nodeStat->oddBotDist != MAXSHORTINT)) oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); else oddLen = MAXSHORTINT; if ((nodeStat->evenTopDist != MAXSHORTINT) && (nodeStat->evenBotDist != MAXSHORTINT)) evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); else evenLen = MAXSHORTINT; /* Update path length array that has number of nodes of a particular ** path length. */ if (oddLen < pathLength ) { if (pathLength != MAXSHORTINT) pathLengthArray[pathLength]--; if (oddLen != MAXSHORTINT) pathLengthArray[oddLen]++; pathLength = oddLen; } if (evenLen < pathLength ) { if (pathLength != MAXSHORTINT) pathLengthArray[pathLength]--; if (evenLen != MAXSHORTINT) pathLengthArray[evenLen]++; } return(1); } /*end of CreateBotDist */ /**Function******************************************************************** Synopsis [ The outer procedure to label each node with its shortest distance from the root and constant] Description [ The outer procedure to label each node with its shortest distance from the root and constant. Calls CreateTopDist and CreateBotDist. The basis for computing the distance between root and constant is that the distance may be the sum of even distances from the node to the root and constant or the sum of odd distances from the node to the root and constant. Both CreateTopDist and CreateBotDist create the odd and even parity distances from the root and constant respectively.] SideEffects [None] SeeAlso [CreateTopDist CreateBotDist] ******************************************************************************/ static st__table * CreatePathTable( DdNode * node /* root of function */, unsigned int * pathLengthArray /* array of path lengths to store nodes labeled with the various path lengths */, FILE *fp /* where to write messages */) { st__table *pathTable; NodeDist_t *nodeStat; DdHalfWord topLen; DdNode *N; int i, numParents; int insertValue; DdNode **childPage; int parentPage; int childQueueIndex, parentQueueIndex; /* Creating path Table for storing data about nodes */ pathTable = st__init_table( st__ptrcmp, st__ptrhash); /* initializing pages for info about each node */ maxNodeDistPages = INITIAL_PAGES; nodeDistPages = ABC_ALLOC(NodeDist_t *, maxNodeDistPages); if (nodeDistPages == NULL) { goto OUT_OF_MEM; } nodeDistPage = 0; currentNodeDistPage = nodeDistPages[nodeDistPage] = ABC_ALLOC(NodeDist_t, nodeDistPageSize); if (currentNodeDistPage == NULL) { for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); goto OUT_OF_MEM; } nodeDistPageIndex = 0; /* Initializing pages for the BFS search queue, implemented as an array. */ maxQueuePages = INITIAL_PAGES; queuePages = ABC_ALLOC(DdNode **, maxQueuePages); if (queuePages == NULL) { goto OUT_OF_MEM; } queuePage = 0; currentQueuePage = queuePages[queuePage] = ABC_ALLOC(DdNode *, queuePageSize); if (currentQueuePage == NULL) { for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]); ABC_FREE(queuePages); goto OUT_OF_MEM; } queuePageIndex = 0; /* Enter the root node into the queue to start with. */ parentPage = queuePage; parentQueueIndex = queuePageIndex; topLen = 0; *(currentQueuePage + queuePageIndex) = node; queuePageIndex++; childPage = currentQueuePage; childQueueIndex = queuePageIndex; N = Cudd_Regular(node); if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages(); if (memOut) { for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]); ABC_FREE(queuePages); st__free_table(pathTable); goto OUT_OF_MEM; } nodeStat = currentNodeDistPage + nodeDistPageIndex; nodeDistPageIndex++; nodeStat->oddTopDist = MAXSHORTINT; nodeStat->evenTopDist = MAXSHORTINT; nodeStat->evenBotDist = MAXSHORTINT; nodeStat->oddBotDist = MAXSHORTINT; nodeStat->regResult = NULL; nodeStat->compResult = NULL; insertValue = st__insert(pathTable, (char *)N, (char *)nodeStat); if (insertValue == st__OUT_OF_MEM) { memOut = 1; for (i = 0; i <= nodeDistPage; i++) ABC_FREE(nodeDistPages[i]); ABC_FREE(nodeDistPages); for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]); ABC_FREE(queuePages); st__free_table(pathTable); goto OUT_OF_MEM; } else if (insertValue == 1) { fprintf(fp, "Something wrong, the entry exists but didnt show up in st__lookup\n"); return(NULL); } if (Cudd_IsComplement(node)) { nodeStat->oddTopDist = 0; } else { nodeStat->evenTopDist = 0; } numParents = 1; /* call the function that counts the distance of each node from the * root */ #ifdef DD_DEBUG numCalls = 0; #endif CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen, childPage, childQueueIndex, numParents, fp); if (memOut) { fprintf(fp, "Out of Memory and cant count path lengths\n"); goto OUT_OF_MEM; } #ifdef DD_DEBUG numCalls = 0; #endif /* call the function that counts the distance of each node from the * constant */ if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL); /* free BFS queue pages as no longer required */ for (i = 0; i <= queuePage; i++) ABC_FREE(queuePages[i]); ABC_FREE(queuePages); return(pathTable); OUT_OF_MEM: (void) fprintf(fp, "Out of Memory, cannot allocate pages\n"); memOut = 1; return(NULL); } /*end of CreatePathTable */ /**Function******************************************************************** Synopsis [Chooses the maximum allowable path length of nodes under the threshold.] Description [Chooses the maximum allowable path length under each node. The corner cases are when the threshold is larger than the number of nodes in the BDD iself, in which case 'numVars + 1' is returned. If all nodes of a particular path length are needed, then the maxpath returned is the next one with excess nodes = 0;] SideEffects [None] SeeAlso [] ******************************************************************************/ static unsigned int AssessPathLength( unsigned int * pathLengthArray /* array determining number of nodes belonging to the different path lengths */, int threshold /* threshold to determine maximum allowable nodes in the subset */, int numVars /* maximum number of variables */, unsigned int * excess /* number of nodes labeled maxpath required in the subset */, FILE *fp /* where to write messages */) { unsigned int i, maxpath; int temp; temp = threshold; i = 0; maxpath = 0; /* quit loop if i reaches max number of variables or if temp reaches * below zero */ while ((i < (unsigned) numVars+1) && (temp > 0)) { if (pathLengthArray[i] > 0) { maxpath = i; temp = temp - pathLengthArray[i]; } i++; } /* if all nodes of max path are needed */ if (temp >= 0) { maxpath++; /* now maxpath becomes the next maxppath or max number of variables */ *excess = 0; } else { /* normal case when subset required is less than size of original BDD */ *excess = temp + pathLengthArray[maxpath]; } if (maxpath == 0) { fprintf(fp, "Path Length array seems to be all zeroes, check\n"); } return(maxpath); } /* end of AssessPathLength */ /**Function******************************************************************** Synopsis [Builds the BDD with nodes labeled with path length less than or equal to maxpath] Description [Builds the BDD with nodes labeled with path length under maxpath and as many nodes labeled maxpath as determined by the threshold. The procedure uses the path table to determine which nodes in the original bdd need to be retained. This procedure picks a shortest path (tie break decided by taking the child with the shortest distance to the constant) and recurs down the path till it reaches the constant. the procedure then starts building the subset upward from the constant. All nodes labeled by path lengths less than the given maxpath are used to build the subset. However, in the case of nodes that have label equal to maxpath, as many are chosen as required by the threshold. This number is stored in the info structure in the field thresholdReached. This field is decremented whenever a node labeled maxpath is encountered and the nodes labeled maxpath are aggregated in a maxpath table. As soon as the thresholdReached count goes to 0, the shortest path from this node to the constant is found. The extraction of nodes with the above labeling is based on the fact that each node, labeled with a path length, P, has at least one child labeled P or less. So extracting all nodes labeled a given path length P ensures complete paths between the root and the constant. Extraction of a partial number of nodes with a given path length may result in incomplete paths and hence the additional number of nodes are grabbed to complete the path. Since the Bdd is built bottom-up, other nodes labeled maxpath do lie on complete paths. The procedure may cause the subset to have a larger or smaller number of nodes than the specified threshold. The increase in the number of nodes is caused by the building of a subset and the reduction by recombination. However in most cases, the recombination overshadows the increase and the procedure returns a result with lower number of nodes than specified. The subsetNodeTable is NIL when there is no hard limit on the number of nodes. Further efforts towards keeping the subset closer to the threshold number were abandoned in favour of keeping the procedure simple and fast.] SideEffects [SubsetNodeTable is changed if it is not NIL.] SeeAlso [] ******************************************************************************/ static DdNode * BuildSubsetBdd( DdManager * dd /* DD manager */, st__table * pathTable /* path table with path lengths and computed results */, DdNode * node /* current node */, struct AssortedInfo * info /* assorted information structure */, st__table * subsetNodeTable /* table storing computed results */) { DdNode *N, *Nv, *Nnv; DdNode *ThenBranch, *ElseBranch, *childBranch; DdNode *child, *regChild, *regNnv = NULL, *regNv = NULL; NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv; DdNode *neW, *topv, *regNew; char *entry; unsigned int topid; unsigned int childPathLength, oddLen, evenLen, NnvPathLength = 0, NvPathLength = 0; unsigned int NvBotDist, NnvBotDist; int tiebreakChild; int processingDone, thenDone, elseDone; #ifdef DD_DEBUG numCalls++; #endif if (Cudd_IsConstant(node)) return(node); N = Cudd_Regular(node); /* Find node in table. */ if (! st__lookup(pathTable, (const char *)N, (char **)&nodeStat)) { (void) fprintf(dd->err, "Something wrong, node must be in table \n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } /* If the node in the table has been visited, then return the corresponding ** Dd. Since a node can become a subset of itself, its ** complement (that is te same node reached by a different parity) will ** become a superset of the original node and result in some minterms ** that were not in the original set. Hence two different results are ** maintained, corresponding to the odd and even parities. */ /* If this node is reached with an odd parity, get odd parity results. */ if (Cudd_IsComplement(node)) { if (nodeStat->compResult != NULL) { #ifdef DD_DEBUG hits++; #endif return(nodeStat->compResult); } } else { /* if this node is reached with an even parity, get even parity * results */ if (nodeStat->regResult != NULL) { #ifdef DD_DEBUG hits++; #endif return(nodeStat->regResult); } } /* get children */ Nv = Cudd_T(N); Nnv = Cudd_E(N); Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); /* no child processed */ processingDone = 0; /* then child not processed */ thenDone = 0; ThenBranch = NULL; /* else child not processed */ elseDone = 0; ElseBranch = NULL; /* if then child constant, branch is the child */ if (Cudd_IsConstant(Nv)) { /*shortest path found */ if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) { info->findShortestPath = 0; } ThenBranch = Nv; cuddRef(ThenBranch); if (ThenBranch == NULL) { return(NULL); } thenDone++; processingDone++; NvBotDist = MAXSHORTINT; } else { /* Derive regular child for table lookup. */ regNv = Cudd_Regular(Nv); /* Get node data for shortest path length. */ if (! st__lookup(pathTable, (const char *)regNv, (char **)&nodeStatNv) ) { (void) fprintf(dd->err, "Something wrong, node must be in table\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } /* Derive shortest path length for child. */ if ((nodeStatNv->oddTopDist != MAXSHORTINT) && (nodeStatNv->oddBotDist != MAXSHORTINT)) { oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist); } else { oddLen = MAXSHORTINT; } if ((nodeStatNv->evenTopDist != MAXSHORTINT) && (nodeStatNv->evenBotDist != MAXSHORTINT)) { evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist); } else { evenLen = MAXSHORTINT; } NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist: nodeStatNv->evenBotDist; } /* if else child constant, branch is the child */ if (Cudd_IsConstant(Nnv)) { /*shortest path found */ if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) { info->findShortestPath = 0; } ElseBranch = Nnv; cuddRef(ElseBranch); if (ElseBranch == NULL) { return(NULL); } elseDone++; processingDone++; NnvBotDist = MAXSHORTINT; } else { /* Derive regular child for table lookup. */ regNnv = Cudd_Regular(Nnv); /* Get node data for shortest path length. */ if (! st__lookup(pathTable, (const char *)regNnv, (char **)&nodeStatNnv) ) { (void) fprintf(dd->err, "Something wrong, node must be in table\n"); dd->errorCode = CUDD_INTERNAL_ERROR; return(NULL); } /* Derive shortest path length for child. */ if ((nodeStatNnv->oddTopDist != MAXSHORTINT) && (nodeStatNnv->oddBotDist != MAXSHORTINT)) { oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist); } else { oddLen = MAXSHORTINT; } if ((nodeStatNnv->evenTopDist != MAXSHORTINT) && (nodeStatNnv->evenBotDist != MAXSHORTINT)) { evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist); } else { evenLen = MAXSHORTINT; } NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist : nodeStatNnv->evenBotDist; } tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0; /* while both children not processed */ while (processingDone != 2) { if (!processingDone) { /* if no child processed */ /* pick the child with shortest path length and record which one * picked */ if ((NvPathLength < NnvPathLength) || ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) { child = Nv; regChild = regNv; thenDone = 1; childPathLength = NvPathLength; } else { child = Nnv; regChild = regNnv; elseDone = 1; childPathLength = NnvPathLength; } /* then path length less than else path length */ } else { /* if one child processed, process the other */ if (thenDone) { child = Nnv; regChild = regNnv; elseDone = 1; childPathLength = NnvPathLength; } else { child = Nv; regChild = regNv; thenDone = 1; childPathLength = NvPathLength; } /* end of else pick the Then child if ELSE child processed */ } /* end of else one child has been processed */ /* ignore (replace with constant 0) all nodes which lie on paths larger * than the maximum length of the path required */ if (childPathLength > info->maxpath) { /* record nodes visited */ childBranch = zero; } else { if (childPathLength < info->maxpath) { if (info->findShortestPath) { info->findShortestPath = 0; } childBranch = BuildSubsetBdd(dd, pathTable, child, info, subsetNodeTable); } else { /* Case: path length of node = maxpath */ /* If the node labeled with maxpath is found in the ** maxpathTable, use it to build the subset BDD. */ if ( st__lookup(info->maxpathTable, (char *)regChild, (char **)&entry)) { /* When a node that is already been chosen is hit, ** the quest for a complete path is over. */ if (info->findShortestPath) { info->findShortestPath = 0; } childBranch = BuildSubsetBdd(dd, pathTable, child, info, subsetNodeTable); } else { /* If node is not found in the maxpathTable and ** the threshold has been reached, then if the ** path needs to be completed, continue. Else ** replace the node with a zero. */ if (info->thresholdReached <= 0) { if (info->findShortestPath) { if ( st__insert(info->maxpathTable, (char *)regChild, (char *)NIL(char)) == st__OUT_OF_MEM) { memOut = 1; (void) fprintf(dd->err, "OUT of memory\n"); info->thresholdReached = 0; childBranch = zero; } else { info->thresholdReached--; childBranch = BuildSubsetBdd(dd, pathTable, child, info,subsetNodeTable); } } else { /* not find shortest path, we dont need this node */ childBranch = zero; } } else { /* Threshold hasn't been reached, ** need the node. */ if ( st__insert(info->maxpathTable, (char *)regChild, (char *)NIL(char)) == st__OUT_OF_MEM) { memOut = 1; (void) fprintf(dd->err, "OUT of memory\n"); info->thresholdReached = 0; childBranch = zero; } else { info->thresholdReached--; if (info->thresholdReached <= 0) { info->findShortestPath = 1; } childBranch = BuildSubsetBdd(dd, pathTable, child, info, subsetNodeTable); } /* end of st__insert successful */ } /* end of threshold hasnt been reached yet */ } /* end of else node not found in maxpath table */ } /* end of if (path length of node = maxpath) */ } /* end if !(childPathLength > maxpath) */ if (childBranch == NULL) { /* deref other stuff incase reordering has taken place */ if (ThenBranch != NULL) { Cudd_RecursiveDeref(dd, ThenBranch); ThenBranch = NULL; } if (ElseBranch != NULL) { Cudd_RecursiveDeref(dd, ElseBranch); ElseBranch = NULL; } return(NULL); } cuddRef(childBranch); if (child == Nv) { ThenBranch = childBranch; } else { ElseBranch = childBranch; } processingDone++; } /*end of while processing Nv, Nnv */ info->findShortestPath = 0; topid = Cudd_NodeReadIndex(N); topv = Cudd_ReadVars(dd, topid); cuddRef(topv); neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); if (neW != NULL) { cuddRef(neW); } Cudd_RecursiveDeref(dd, topv); Cudd_RecursiveDeref(dd, ThenBranch); Cudd_RecursiveDeref(dd, ElseBranch); /* Hard Limit of threshold has been imposed */ if (subsetNodeTable != NIL( st__table)) { /* check if a new node is created */ regNew = Cudd_Regular(neW); /* subset node table keeps all new nodes that have been created to keep * a running count of how many nodes have been built in the subset. */ if (! st__lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) { if (!Cudd_IsConstant(regNew)) { if ( st__insert(subsetNodeTable, (char *)regNew, (char *)NULL) == st__OUT_OF_MEM) { (void) fprintf(dd->err, "Out of memory\n"); return (NULL); } if ( st__count(subsetNodeTable) > info->threshold) { info->thresholdReached = 0; } } } } if (neW == NULL) { return(NULL); } else { /*store computed result in regular form*/ if (Cudd_IsComplement(node)) { nodeStat->compResult = neW; cuddRef(nodeStat->compResult); /* if the new node is the same as the corresponding node in the * original bdd then its complement need not be computed as it * cannot be larger than the node itself */ if (neW == node) { #ifdef DD_DEBUG thishit++; #endif /* if a result for the node has already been computed, then * it can only be smaller than teh node itself. hence store * the node result in order not to break recombination */ if (nodeStat->regResult != NULL) { Cudd_RecursiveDeref(dd, nodeStat->regResult); } nodeStat->regResult = Cudd_Not(neW); cuddRef(nodeStat->regResult); } } else { nodeStat->regResult = neW; cuddRef(nodeStat->regResult); if (neW == node) { #ifdef DD_DEBUG thishit++; #endif if (nodeStat->compResult != NULL) { Cudd_RecursiveDeref(dd, nodeStat->compResult); } nodeStat->compResult = Cudd_Not(neW); cuddRef(nodeStat->compResult); } } cuddDeref(neW); return(neW); } /* end of else i.e. Subset != NULL */ } /* end of BuildSubsetBdd */ /**Function******************************************************************** Synopsis [Procedure to free te result dds stored in the NodeDist pages.] Description [None] SideEffects [None] SeeAlso [] ******************************************************************************/ static enum st__retval stPathTableDdFree( char * key, char * value, char * arg) { NodeDist_t *nodeStat; DdManager *dd; nodeStat = (NodeDist_t *)value; dd = (DdManager *)arg; if (nodeStat->regResult != NULL) { Cudd_RecursiveDeref(dd, nodeStat->regResult); } if (nodeStat->compResult != NULL) { Cudd_RecursiveDeref(dd, nodeStat->compResult); } return( st__CONTINUE); } /* end of stPathTableFree */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddSymmetry.c000066400000000000000000001553741300674244400243600ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddSymmetry.c] PackageName [cudd] Synopsis [Functions for symmetry-based variable reordering.] Description [External procedures included in this file:
        • Cudd_SymmProfile()
        Internal procedures included in this module:
        • cuddSymmCheck()
        • cuddSymmSifting()
        • cuddSymmSiftingConv()
        Static procedures included in this module:
        • ddSymmUniqueCompare()
        • ddSymmSiftingAux()
        • ddSymmSiftingConvAux()
        • ddSymmSiftingUp()
        • ddSymmSiftingDown()
        • ddSymmGroupMove()
        • ddSymmGroupMoveBackward()
        • ddSymmSiftingBackward()
        • ddSymmSummary()
        ] Author [Shipra Panda, Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define MV_OOM (Move *)1 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.26 2009/02/19 16:23:54 fabio Exp $"; #endif static int *entry; extern int ddTotalNumberSwapping; #ifdef DD_STATS extern int ddTotalNISwaps; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int ddSymmUniqueCompare (int *ptrX, int *ptrY); static int ddSymmSiftingAux (DdManager *table, int x, int xLow, int xHigh); static int ddSymmSiftingConvAux (DdManager *table, int x, int xLow, int xHigh); static Move * ddSymmSiftingUp (DdManager *table, int y, int xLow); static Move * ddSymmSiftingDown (DdManager *table, int x, int xHigh); static int ddSymmGroupMove (DdManager *table, int x, int y, Move **moves); static int ddSymmGroupMoveBackward (DdManager *table, int x, int y); static int ddSymmSiftingBackward (DdManager *table, Move *moves, int size); static void ddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints statistics on symmetric variables.] Description [] SideEffects [None] ******************************************************************************/ void Cudd_SymmProfile( DdManager * table, int lower, int upper) { int i,x,gbot; int TotalSymm = 0; int TotalSymmGroups = 0; for (i = lower; i <= upper; i++) { if (table->subtables[i].next != (unsigned) i) { x = i; (void) fprintf(table->out,"Group:"); do { (void) fprintf(table->out," %d",table->invperm[x]); TotalSymm++; gbot = x; x = table->subtables[x].next; } while (x != i); TotalSymmGroups++; #ifdef DD_DEBUG assert(table->subtables[gbot].next == (unsigned) i); #endif i = gbot; (void) fprintf(table->out,"\n"); } } (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm); (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups); } /* end of Cudd_SymmProfile */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Checks for symmetry of x and y.] Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.] SideEffects [None] ******************************************************************************/ int cuddSymmCheck( DdManager * table, int x, int y) { DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; int comple; /* f0 is complemented */ int xsymmy; /* x and y may be positively symmetric */ int xsymmyp; /* x and y may be negatively symmetric */ int arccount; /* number of arcs from layer x to layer y */ int TotalRefCount; /* total reference count of layer y minus 1 */ int yindex; int i; DdNodePtr *list; int slots; DdNode *sentinel = &(table->sentinel); #ifdef DD_DEBUG int xindex; #endif /* Checks that x and y are not the projection functions. ** For x it is sufficient to check whether there is only one ** node; indeed, if there is one node, it is the projection function ** and it cannot point to y. Hence, if y isn't just the projection ** function, it has one arc coming from a layer different from x. */ if (table->subtables[x].keys == 1) { return(0); } yindex = table->invperm[y]; if (table->subtables[y].keys == 1) { if (table->vars[yindex]->ref == 1) return(0); } xsymmy = xsymmyp = 1; arccount = 0; slots = table->subtables[x].slots; list = table->subtables[x].nodelist; for (i = 0; i < slots; i++) { f = list[i]; while (f != sentinel) { /* Find f1, f0, f11, f10, f01, f00. */ f1 = cuddT(f); f0 = Cudd_Regular(cuddE(f)); comple = Cudd_IsComplement(cuddE(f)); if ((int) f1->index == yindex) { arccount++; f11 = cuddT(f1); f10 = cuddE(f1); } else { if ((int) f0->index != yindex) { /* If f is an isolated projection function it is ** allowed to bypass layer y. */ if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) return(0); /* f bypasses layer y */ } f11 = f10 = f1; } if ((int) f0->index == yindex) { arccount++; f01 = cuddT(f0); f00 = cuddE(f0); } else { f01 = f00 = f0; } if (comple) { f01 = Cudd_Not(f01); f00 = Cudd_Not(f00); } if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) { xsymmy &= f01 == f10; xsymmyp &= f11 == f00; if ((xsymmy == 0) && (xsymmyp == 0)) return(0); } f = f->next; } /* while */ } /* for */ /* Calculate the total reference counts of y */ TotalRefCount = -1; /* -1 for projection function */ slots = table->subtables[y].slots; list = table->subtables[y].nodelist; for (i = 0; i < slots; i++) { f = list[i]; while (f != sentinel) { TotalRefCount += f->ref; f = f->next; } } #if defined(DD_DEBUG) && defined(DD_VERBOSE) if (arccount == TotalRefCount) { xindex = table->invperm[x]; (void) fprintf(table->out, "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", xindex,yindex,x,y); } #endif return(arccount == TotalRefCount); } /* end of cuddSymmCheck */ /**Function******************************************************************** Synopsis [Symmetric sifting algorithm.] Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.
        1. Order all the variables according to the number of entries in each unique subtable.
        2. Sift the variable up and down, remembering each time the total size of the DD heap and grouping variables that are symmetric.
        3. Select the best permutation.
        4. Repeat 3 and 4 for all variables.
        Returns 1 plus the number of symmetric variables if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddSymmSiftingConv] ******************************************************************************/ int cuddSymmSifting( DdManager * table, int lower, int upper) { int i; int *var; int size; int x; int result; int symvars; int symgroups; #ifdef DD_STATS int previousSize; #endif size = table->size; /* Find order in which to sift variables. */ var = NULL; entry = ABC_ALLOC(int,size); if (entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto ddSymmSiftingOutOfMem; } var = ABC_ALLOC(int,size); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto ddSymmSiftingOutOfMem; } for (i = 0; i < size; i++) { x = table->perm[i]; entry[i] = table->subtables[x].keys; var[i] = i; } qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); /* Initialize the symmetry of each subtable to itself. */ for (i = lower; i <= upper; i++) { table->subtables[i].next = i; } for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { if (ddTotalNumberSwapping >= table->siftMaxSwap) break; // enable timeout during variable reodering - alanmi 2/13/11 if ( table->TimeStop && Abc_Clock() > table->TimeStop ) break; x = table->perm[var[i]]; #ifdef DD_STATS previousSize = table->keys - table->isolated; #endif if (x < lower || x > upper) continue; if (table->subtables[x].next == (unsigned) x) { result = ddSymmSiftingAux(table,x,lower,upper); if (!result) goto ddSymmSiftingOutOfMem; #ifdef DD_STATS if (table->keys < (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"-"); } else if (table->keys > (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"+"); /* should never happen */ } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } } ABC_FREE(var); ABC_FREE(entry); ddSymmSummary(table, lower, upper, &symvars, &symgroups); #ifdef DD_STATS (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", symvars); (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", symgroups); #endif return(1+symvars); ddSymmSiftingOutOfMem: if (entry != NULL) ABC_FREE(entry); if (var != NULL) ABC_FREE(var); return(0); } /* end of cuddSymmSifting */ /**Function******************************************************************** Synopsis [Symmetric sifting to convergence algorithm.] Description [Symmetric sifting to convergence algorithm. Assumes that no dead nodes are present.
        1. Order all the variables according to the number of entries in each unique subtable.
        2. Sift the variable up and down, remembering each time the total size of the DD heap and grouping variables that are symmetric.
        3. Select the best permutation.
        4. Repeat 3 and 4 for all variables.
        5. Repeat 1-4 until no further improvement.
        Returns 1 plus the number of symmetric variables if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddSymmSifting] ******************************************************************************/ int cuddSymmSiftingConv( DdManager * table, int lower, int upper) { int i; int *var; int size; int x; int result; int symvars; int symgroups; int classes; int initialSize; #ifdef DD_STATS int previousSize; #endif initialSize = table->keys - table->isolated; size = table->size; /* Find order in which to sift variables. */ var = NULL; entry = ABC_ALLOC(int,size); if (entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto ddSymmSiftingConvOutOfMem; } var = ABC_ALLOC(int,size); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto ddSymmSiftingConvOutOfMem; } for (i = 0; i < size; i++) { x = table->perm[i]; entry[i] = table->subtables[x].keys; var[i] = i; } qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); /* Initialize the symmetry of each subtable to itself ** for first pass of converging symmetric sifting. */ for (i = lower; i <= upper; i++) { table->subtables[i].next = i; } for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) { if (ddTotalNumberSwapping >= table->siftMaxSwap) break; x = table->perm[var[i]]; if (x < lower || x > upper) continue; /* Only sift if not in symmetry group already. */ if (table->subtables[x].next == (unsigned) x) { #ifdef DD_STATS previousSize = table->keys - table->isolated; #endif result = ddSymmSiftingAux(table,x,lower,upper); if (!result) goto ddSymmSiftingConvOutOfMem; #ifdef DD_STATS if (table->keys < (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"-"); } else if (table->keys > (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"+"); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } } /* Sifting now until convergence. */ while ((unsigned) initialSize > table->keys - table->isolated) { initialSize = table->keys - table->isolated; #ifdef DD_STATS (void) fprintf(table->out,"\n"); #endif /* Here we consider only one representative for each symmetry class. */ for (x = lower, classes = 0; x <= upper; x++, classes++) { while ((unsigned) x < table->subtables[x].next) { x = table->subtables[x].next; } /* Here x is the largest index in a group. ** Groups consist of adjacent variables. ** Hence, the next increment of x will move it to a new group. */ i = table->invperm[x]; entry[i] = table->subtables[x].keys; var[classes] = i; } qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare); /* Now sift. */ for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { if (ddTotalNumberSwapping >= table->siftMaxSwap) break; x = table->perm[var[i]]; if ((unsigned) x >= table->subtables[x].next) { #ifdef DD_STATS previousSize = table->keys - table->isolated; #endif result = ddSymmSiftingConvAux(table,x,lower,upper); if (!result ) goto ddSymmSiftingConvOutOfMem; #ifdef DD_STATS if (table->keys < (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"-"); } else if (table->keys > (unsigned) previousSize + table->isolated) { (void) fprintf(table->out,"+"); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } } /* for */ } ddSymmSummary(table, lower, upper, &symvars, &symgroups); #ifdef DD_STATS (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", symvars); (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", symgroups); #endif ABC_FREE(var); ABC_FREE(entry); return(1+symvars); ddSymmSiftingConvOutOfMem: if (entry != NULL) ABC_FREE(entry); if (var != NULL) ABC_FREE(var); return(0); } /* end of cuddSymmSiftingConv */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Comparison function used by qsort.] Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.] SideEffects [None] ******************************************************************************/ static int ddSymmUniqueCompare( int * ptrX, int * ptrY) { #if 0 if (entry[*ptrY] == entry[*ptrX]) { return((*ptrX) - (*ptrY)); } #endif return(entry[*ptrY] - entry[*ptrX]); } /* end of ddSymmUniqueCompare */ /**Function******************************************************************** Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.] Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is not part of a symmetry group. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddSymmSiftingAux( DdManager * table, int x, int xLow, int xHigh) { Move *move; Move *moveUp; /* list of up moves */ Move *moveDown; /* list of down moves */ int initialSize; int result; int i; int topbot; /* index to either top or bottom of symmetry group */ int initGroupSize, finalGroupSize; #ifdef DD_DEBUG /* check for previously detected symmetry */ assert(table->subtables[x].next == (unsigned) x); #endif initialSize = table->keys - table->isolated; moveDown = NULL; moveUp = NULL; if ((x - xLow) > (xHigh - x)) { /* Will go down first, unless x == xHigh: ** Look for consecutive symmetries above x. */ for (i = x; i > xLow; i--) { if (!cuddSymmCheck(table,i-1,i)) break; topbot = table->subtables[i-1].next; /* find top of i-1's group */ table->subtables[i-1].next = i; table->subtables[x].next = topbot; /* x is bottom of group so its */ /* next is top of i-1's group */ i = topbot + 1; /* add 1 for i--; new i is top of symm group */ } } else { /* Will go up first unless x == xlow: ** Look for consecutive symmetries below x. */ for (i = x; i < xHigh; i++) { if (!cuddSymmCheck(table,i,i+1)) break; /* find bottom of i+1's symm group */ topbot = i + 1; while ((unsigned) topbot < table->subtables[topbot].next) { topbot = table->subtables[topbot].next; } table->subtables[topbot].next = table->subtables[i].next; table->subtables[i].next = i + 1; i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */ } } /* Now x may be in the middle of a symmetry group. ** Find bottom of x's symm group. */ while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; if (x == xLow) { /* Sift down */ #ifdef DD_DEBUG /* x must be a singleton */ assert((unsigned) x == table->subtables[x].next); #endif if (x == xHigh) return(1); /* just one variable */ initGroupSize = 1; moveDown = ddSymmSiftingDown(table,x,xHigh); /* after this point x --> xHigh, unless early term */ if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; if (moveDown == NULL) return(1); x = moveDown->y; /* Find bottom of x's group */ i = x; while ((unsigned) i < table->subtables[i].next) { i = table->subtables[i].next; } #ifdef DD_DEBUG /* x should be the top of the symmetry group and i the bottom */ assert((unsigned) i >= table->subtables[i].next); assert((unsigned) x == table->subtables[i].next); #endif finalGroupSize = i - x + 1; if (initGroupSize == finalGroupSize) { /* No new symmetry groups detected, return to best position */ result = ddSymmSiftingBackward(table,moveDown,initialSize); } else { initialSize = table->keys - table->isolated; moveUp = ddSymmSiftingUp(table,x,xLow); result = ddSymmSiftingBackward(table,moveUp,initialSize); } if (!result) goto ddSymmSiftingAuxOutOfMem; } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ /* Find top of x's symm group */ i = x; /* bottom */ x = table->subtables[x].next; /* top */ if (x == xLow) return(1); /* just one big group */ initGroupSize = i - x + 1; moveUp = ddSymmSiftingUp(table,x,xLow); /* after this point x --> xLow, unless early term */ if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; if (moveUp == NULL) return(1); x = moveUp->x; /* Find top of x's group */ i = table->subtables[x].next; #ifdef DD_DEBUG /* x should be the bottom of the symmetry group and i the top */ assert((unsigned) x >= table->subtables[x].next); assert((unsigned) i == table->subtables[x].next); #endif finalGroupSize = x - i + 1; if (initGroupSize == finalGroupSize) { /* No new symmetry groups detected, return to best position */ result = ddSymmSiftingBackward(table,moveUp,initialSize); } else { initialSize = table->keys - table->isolated; moveDown = ddSymmSiftingDown(table,x,xHigh); result = ddSymmSiftingBackward(table,moveDown,initialSize); } if (!result) goto ddSymmSiftingAuxOutOfMem; } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ moveDown = ddSymmSiftingDown(table,x,xHigh); /* at this point x == xHigh, unless early term */ if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; if (moveDown != NULL) { x = moveDown->y; /* x is top here */ i = x; while ((unsigned) i < table->subtables[i].next) { i = table->subtables[i].next; } } else { i = x; while ((unsigned) i < table->subtables[i].next) { i = table->subtables[i].next; } x = table->subtables[i].next; } #ifdef DD_DEBUG /* x should be the top of the symmetry group and i the bottom */ assert((unsigned) i >= table->subtables[i].next); assert((unsigned) x == table->subtables[i].next); #endif initGroupSize = i - x + 1; moveUp = ddSymmSiftingUp(table,x,xLow); if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; if (moveUp != NULL) { x = moveUp->x; i = table->subtables[x].next; } else { i = x; while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; } #ifdef DD_DEBUG /* x should be the bottom of the symmetry group and i the top */ assert((unsigned) x >= table->subtables[x].next); assert((unsigned) i == table->subtables[x].next); #endif finalGroupSize = x - i + 1; if (initGroupSize == finalGroupSize) { /* No new symmetry groups detected, return to best position */ result = ddSymmSiftingBackward(table,moveUp,initialSize); } else { while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } initialSize = table->keys - table->isolated; moveDown = ddSymmSiftingDown(table,x,xHigh); result = ddSymmSiftingBackward(table,moveDown,initialSize); } if (!result) goto ddSymmSiftingAuxOutOfMem; } else { /* moving up first: shorter */ /* Find top of x's symmetry group */ x = table->subtables[x].next; moveUp = ddSymmSiftingUp(table,x,xLow); /* at this point x == xHigh, unless early term */ if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; if (moveUp != NULL) { x = moveUp->x; i = table->subtables[x].next; } else { while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; i = table->subtables[x].next; } #ifdef DD_DEBUG /* x is bottom of the symmetry group and i is top */ assert((unsigned) x >= table->subtables[x].next); assert((unsigned) i == table->subtables[x].next); #endif initGroupSize = x - i + 1; moveDown = ddSymmSiftingDown(table,x,xHigh); if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; if (moveDown != NULL) { x = moveDown->y; i = x; while ((unsigned) i < table->subtables[i].next) { i = table->subtables[i].next; } } else { i = x; x = table->subtables[x].next; } #ifdef DD_DEBUG /* x should be the top of the symmetry group and i the bottom */ assert((unsigned) i >= table->subtables[i].next); assert((unsigned) x == table->subtables[i].next); #endif finalGroupSize = i - x + 1; if (initGroupSize == finalGroupSize) { /* No new symmetries detected, go back to best position */ result = ddSymmSiftingBackward(table,moveDown,initialSize); } else { while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } initialSize = table->keys - table->isolated; moveUp = ddSymmSiftingUp(table,x,xLow); result = ddSymmSiftingBackward(table,moveUp,initialSize); } if (!result) goto ddSymmSiftingAuxOutOfMem; } while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } return(1); ddSymmSiftingAuxOutOfMem: if (moveDown != MV_OOM) { while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } } if (moveUp != MV_OOM) { while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } } return(0); } /* end of ddSymmSiftingAux */ /**Function******************************************************************** Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.] Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is either an isolated variable, or it is the bottom of a symmetry group. All symmetries may not have been found, because of exceeded growth limit. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddSymmSiftingConvAux( DdManager * table, int x, int xLow, int xHigh) { Move *move; Move *moveUp; /* list of up moves */ Move *moveDown; /* list of down moves */ int initialSize; int result; int i; int initGroupSize, finalGroupSize; initialSize = table->keys - table->isolated; moveDown = NULL; moveUp = NULL; if (x == xLow) { /* Sift down */ #ifdef DD_DEBUG /* x is bottom of symmetry group */ assert((unsigned) x >= table->subtables[x].next); #endif i = table->subtables[x].next; initGroupSize = x - i + 1; moveDown = ddSymmSiftingDown(table,x,xHigh); /* at this point x == xHigh, unless early term */ if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; if (moveDown == NULL) return(1); x = moveDown->y; i = x; while ((unsigned) i < table->subtables[i].next) { i = table->subtables[i].next; } #ifdef DD_DEBUG /* x should be the top of the symmetric group and i the bottom */ assert((unsigned) i >= table->subtables[i].next); assert((unsigned) x == table->subtables[i].next); #endif finalGroupSize = i - x + 1; if (initGroupSize == finalGroupSize) { /* No new symmetries detected, go back to best position */ result = ddSymmSiftingBackward(table,moveDown,initialSize); } else { initialSize = table->keys - table->isolated; moveUp = ddSymmSiftingUp(table,x,xLow); result = ddSymmSiftingBackward(table,moveUp,initialSize); } if (!result) goto ddSymmSiftingConvAuxOutOfMem; } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ /* Find top of x's symm group */ while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; i = x; /* bottom */ x = table->subtables[x].next; /* top */ if (x == xLow) return(1); initGroupSize = i - x + 1; moveUp = ddSymmSiftingUp(table,x,xLow); /* at this point x == xLow, unless early term */ if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; if (moveUp == NULL) return(1); x = moveUp->x; i = table->subtables[x].next; #ifdef DD_DEBUG /* x should be the bottom of the symmetry group and i the top */ assert((unsigned) x >= table->subtables[x].next); assert((unsigned) i == table->subtables[x].next); #endif finalGroupSize = x - i + 1; if (initGroupSize == finalGroupSize) { /* No new symmetry groups detected, return to best position */ result = ddSymmSiftingBackward(table,moveUp,initialSize); } else { initialSize = table->keys - table->isolated; moveDown = ddSymmSiftingDown(table,x,xHigh); result = ddSymmSiftingBackward(table,moveDown,initialSize); } if (!result) goto ddSymmSiftingConvAuxOutOfMem; } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ moveDown = ddSymmSiftingDown(table,x,xHigh); /* at this point x == xHigh, unless early term */ if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; if (moveDown != NULL) { x = moveDown->y; i = x; while ((unsigned) i < table->subtables[i].next) { i = table->subtables[i].next; } } else { while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; i = x; x = table->subtables[x].next; } #ifdef DD_DEBUG /* x should be the top of the symmetry group and i the bottom */ assert((unsigned) i >= table->subtables[i].next); assert((unsigned) x == table->subtables[i].next); #endif initGroupSize = i - x + 1; moveUp = ddSymmSiftingUp(table,x,xLow); if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; if (moveUp != NULL) { x = moveUp->x; i = table->subtables[x].next; } else { i = x; while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; } #ifdef DD_DEBUG /* x should be the bottom of the symmetry group and i the top */ assert((unsigned) x >= table->subtables[x].next); assert((unsigned) i == table->subtables[x].next); #endif finalGroupSize = x - i + 1; if (initGroupSize == finalGroupSize) { /* No new symmetry groups detected, return to best position */ result = ddSymmSiftingBackward(table,moveUp,initialSize); } else { while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } initialSize = table->keys - table->isolated; moveDown = ddSymmSiftingDown(table,x,xHigh); result = ddSymmSiftingBackward(table,moveDown,initialSize); } if (!result) goto ddSymmSiftingConvAuxOutOfMem; } else { /* moving up first: shorter */ /* Find top of x's symmetry group */ x = table->subtables[x].next; moveUp = ddSymmSiftingUp(table,x,xLow); /* at this point x == xHigh, unless early term */ if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; if (moveUp != NULL) { x = moveUp->x; i = table->subtables[x].next; } else { i = x; while ((unsigned) x < table->subtables[x].next) x = table->subtables[x].next; } #ifdef DD_DEBUG /* x is bottom of the symmetry group and i is top */ assert((unsigned) x >= table->subtables[x].next); assert((unsigned) i == table->subtables[x].next); #endif initGroupSize = x - i + 1; moveDown = ddSymmSiftingDown(table,x,xHigh); if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; if (moveDown != NULL) { x = moveDown->y; i = x; while ((unsigned) i < table->subtables[i].next) { i = table->subtables[i].next; } } else { i = x; x = table->subtables[x].next; } #ifdef DD_DEBUG /* x should be the top of the symmetry group and i the bottom */ assert((unsigned) i >= table->subtables[i].next); assert((unsigned) x == table->subtables[i].next); #endif finalGroupSize = i - x + 1; if (initGroupSize == finalGroupSize) { /* No new symmetries detected, go back to best position */ result = ddSymmSiftingBackward(table,moveDown,initialSize); } else { while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } initialSize = table->keys - table->isolated; moveUp = ddSymmSiftingUp(table,x,xLow); result = ddSymmSiftingBackward(table,moveUp,initialSize); } if (!result) goto ddSymmSiftingConvAuxOutOfMem; } while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } return(1); ddSymmSiftingConvAuxOutOfMem: if (moveDown != MV_OOM) { while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } } if (moveUp != MV_OOM) { while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } } return(0); } /* end of ddSymmSiftingConvAux */ /**Function******************************************************************** Synopsis [Moves x up until either it reaches the bound (xLow) or the size of the DD heap increases too much.] Description [Moves x up until either it reaches the bound (xLow) or the size of the DD heap increases too much. Assumes that x is the top of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; MV_OOM if memory is full.] SideEffects [None] ******************************************************************************/ static Move * ddSymmSiftingUp( DdManager * table, int y, int xLow) { Move *moves; Move *move; int x; int size; int i; int gxtop,gybot; int limitSize; int xindex, yindex; int zindex; int z; int isolated; int L; /* lower bound on DD size */ #ifdef DD_DEBUG int checkL; #endif moves = NULL; yindex = table->invperm[y]; /* Initialize the lower bound. ** The part of the DD below the bottom of y' group will not change. ** The part of the DD above y that does not interact with y will not ** change. The rest may vanish in the best case, except for ** the nodes at level xLow, which will not vanish, regardless. */ limitSize = L = table->keys - table->isolated; gybot = y; while ((unsigned) gybot < table->subtables[gybot].next) gybot = table->subtables[gybot].next; for (z = xLow + 1; z <= gybot; z++) { zindex = table->invperm[z]; if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { isolated = table->vars[zindex]->ref == 1; L -= table->subtables[z].keys - isolated; } } x = cuddNextLow(table,y); while (x >= xLow && L <= limitSize) { #ifdef DD_DEBUG gybot = y; while ((unsigned) gybot < table->subtables[gybot].next) gybot = table->subtables[gybot].next; checkL = table->keys - table->isolated; for (z = xLow + 1; z <= gybot; z++) { zindex = table->invperm[z]; if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { isolated = table->vars[zindex]->ref == 1; checkL -= table->subtables[z].keys - isolated; } } assert(L == checkL); #endif gxtop = table->subtables[x].next; if (cuddSymmCheck(table,x,y)) { /* Symmetry found, attach symm groups */ table->subtables[x].next = y; i = table->subtables[y].next; while (table->subtables[i].next != (unsigned) y) i = table->subtables[i].next; table->subtables[i].next = gxtop; } else if (table->subtables[x].next == (unsigned) x && table->subtables[y].next == (unsigned) y) { /* x and y have self symmetry */ xindex = table->invperm[x]; size = cuddSwapInPlace(table,x,y); #ifdef DD_DEBUG assert(table->subtables[x].next == (unsigned) x); assert(table->subtables[y].next == (unsigned) y); #endif if (size == 0) goto ddSymmSiftingUpOutOfMem; /* Update the lower bound. */ if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[xindex]->ref == 1; L += table->subtables[y].keys - isolated; } move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSymmSiftingUpOutOfMem; move->x = x; move->y = y; move->size = size; move->next = moves; moves = move; if ((double) size > (double) limitSize * table->maxGrowth) return(moves); if (size < limitSize) limitSize = size; } else { /* Group move */ size = ddSymmGroupMove(table,x,y,&moves); if (size == 0) goto ddSymmSiftingUpOutOfMem; /* Update the lower bound. */ z = moves->y; do { zindex = table->invperm[z]; if (cuddTestInteract(table,zindex,yindex)) { isolated = table->vars[zindex]->ref == 1; L += table->subtables[z].keys - isolated; } z = table->subtables[z].next; } while (z != (int) moves->y); if ((double) size > (double) limitSize * table->maxGrowth) return(moves); if (size < limitSize) limitSize = size; } y = gxtop; x = cuddNextLow(table,y); } return(moves); ddSymmSiftingUpOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(MV_OOM); } /* end of ddSymmSiftingUp */ /**Function******************************************************************** Synopsis [Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much.] Description [Moves x down until either it reaches the bound (xHigh) or the size of the DD heap increases too much. Assumes that x is the bottom of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; MV_OOM if memory is full.] SideEffects [None] ******************************************************************************/ static Move * ddSymmSiftingDown( DdManager * table, int x, int xHigh) { Move *moves; Move *move; int y; int size; int limitSize; int gxtop,gybot; int R; /* upper bound on node decrease */ int xindex, yindex; int isolated; int z; int zindex; #ifdef DD_DEBUG int checkR; #endif moves = NULL; /* Initialize R */ xindex = table->invperm[x]; gxtop = table->subtables[x].next; limitSize = size = table->keys - table->isolated; R = 0; for (z = xHigh; z > gxtop; z--) { zindex = table->invperm[z]; if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; R += table->subtables[z].keys - isolated; } } y = cuddNextHigh(table,x); while (y <= xHigh && size - R < limitSize) { #ifdef DD_DEBUG gxtop = table->subtables[x].next; checkR = 0; for (z = xHigh; z > gxtop; z--) { zindex = table->invperm[z]; if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; checkR += table->subtables[z].keys - isolated; } } assert(R == checkR); #endif gybot = table->subtables[y].next; while (table->subtables[gybot].next != (unsigned) y) gybot = table->subtables[gybot].next; if (cuddSymmCheck(table,x,y)) { /* Symmetry found, attach symm groups */ gxtop = table->subtables[x].next; table->subtables[x].next = y; table->subtables[gybot].next = gxtop; } else if (table->subtables[x].next == (unsigned) x && table->subtables[y].next == (unsigned) y) { /* x and y have self symmetry */ /* Update upper bound on node decrease. */ yindex = table->invperm[y]; if (cuddTestInteract(table,xindex,yindex)) { isolated = table->vars[yindex]->ref == 1; R -= table->subtables[y].keys - isolated; } size = cuddSwapInPlace(table,x,y); #ifdef DD_DEBUG assert(table->subtables[x].next == (unsigned) x); assert(table->subtables[y].next == (unsigned) y); #endif if (size == 0) goto ddSymmSiftingDownOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto ddSymmSiftingDownOutOfMem; move->x = x; move->y = y; move->size = size; move->next = moves; moves = move; if ((double) size > (double) limitSize * table->maxGrowth) return(moves); if (size < limitSize) limitSize = size; } else { /* Group move */ /* Update upper bound on node decrease: first phase. */ gxtop = table->subtables[x].next; z = gxtop + 1; do { zindex = table->invperm[z]; if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; R -= table->subtables[z].keys - isolated; } z++; } while (z <= gybot); size = ddSymmGroupMove(table,x,y,&moves); if (size == 0) goto ddSymmSiftingDownOutOfMem; if ((double) size > (double) limitSize * table->maxGrowth) return(moves); if (size < limitSize) limitSize = size; /* Update upper bound on node decrease: second phase. */ gxtop = table->subtables[gybot].next; for (z = gxtop + 1; z <= gybot; z++) { zindex = table->invperm[z]; if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { isolated = table->vars[zindex]->ref == 1; R += table->subtables[z].keys - isolated; } } } x = gybot; y = cuddNextHigh(table,x); } return(moves); ddSymmSiftingDownOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(MV_OOM); } /* end of ddSymmSiftingDown */ /**Function******************************************************************** Synopsis [Swaps two groups.] Description [Swaps two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Updates the list of moves. Returns the number of keys in the table if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddSymmGroupMove( DdManager * table, int x, int y, Move ** moves) { Move *move; int size = -1; int i,j; int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; int swapx = -1,swapy = -1; #ifdef DD_DEBUG assert(x < y); /* we assume that x < y */ #endif /* Find top, bottom, and size for the two groups. */ xbot = x; xtop = table->subtables[x].next; xsize = xbot - xtop + 1; ybot = y; while ((unsigned) ybot < table->subtables[ybot].next) ybot = table->subtables[ybot].next; ytop = y; ysize = ybot - ytop + 1; /* Sift the variables of the second group up through the first group. */ for (i = 1; i <= ysize; i++) { for (j = 1; j <= xsize; j++) { size = cuddSwapInPlace(table,x,y); if (size == 0) return(0); swapx = x; swapy = y; y = x; x = y - 1; } y = ytop + i; x = y - 1; } /* fix symmetries */ y = xtop; /* ytop is now where xtop used to be */ for (i = 0; i < ysize-1 ; i++) { table->subtables[y].next = y + 1; y = y + 1; } table->subtables[y].next = xtop; /* y is bottom of its group, join */ /* its symmetry to top of its group */ x = y + 1; newxtop = x; for (i = 0; i < xsize - 1 ; i++) { table->subtables[x].next = x + 1; x = x + 1; } table->subtables[x].next = newxtop; /* x is bottom of its group, join */ /* its symmetry to top of its group */ /* Store group move */ move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) return(0); move->x = swapx; move->y = swapy; move->size = size; move->next = *moves; *moves = move; return(size); } /* end of ddSymmGroupMove */ /**Function******************************************************************** Synopsis [Undoes the swap of two groups.] Description [Undoes the swap of two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Returns the number of keys in the table if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddSymmGroupMoveBackward( DdManager * table, int x, int y) { int size = -1; int i,j; int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; #ifdef DD_DEBUG assert(x < y); /* We assume that x < y */ #endif /* Find top, bottom, and size for the two groups. */ xbot = x; xtop = table->subtables[x].next; xsize = xbot - xtop + 1; ybot = y; while ((unsigned) ybot < table->subtables[ybot].next) ybot = table->subtables[ybot].next; ytop = y; ysize = ybot - ytop + 1; /* Sift the variables of the second group up through the first group. */ for (i = 1; i <= ysize; i++) { for (j = 1; j <= xsize; j++) { size = cuddSwapInPlace(table,x,y); if (size == 0) return(0); y = x; x = cuddNextLow(table,y); } y = ytop + i; x = y - 1; } /* Fix symmetries. */ y = xtop; for (i = 0; i < ysize-1 ; i++) { table->subtables[y].next = y + 1; y = y + 1; } table->subtables[y].next = xtop; /* y is bottom of its group, join */ /* its symmetry to top of its group */ x = y + 1; newxtop = x; for (i = 0; i < xsize-1 ; i++) { table->subtables[x].next = x + 1; x = x + 1; } table->subtables[x].next = newxtop; /* x is bottom of its group, join */ /* its symmetry to top of its group */ return(size); } /* end of ddSymmGroupMoveBackward */ /**Function******************************************************************** Synopsis [Given a set of moves, returns the DD heap to the position giving the minimum size.] Description [Given a set of moves, returns the DD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddSymmSiftingBackward( DdManager * table, Move * moves, int size) { Move *move; int res = -1; for (move = moves; move != NULL; move = move->next) { if (move->size < size) { size = move->size; } } for (move = moves; move != NULL; move = move->next) { if (move->size == size) return(1); if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) { res = cuddSwapInPlace(table,(int)move->x,(int)move->y); #ifdef DD_DEBUG assert(table->subtables[move->x].next == move->x); assert(table->subtables[move->y].next == move->y); #endif } else { /* Group move necessary */ res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y); } if (!res) return(0); } return(1); } /* end of ddSymmSiftingBackward */ /**Function******************************************************************** Synopsis [Counts numbers of symmetric variables and symmetry groups.] Description [] SideEffects [None] ******************************************************************************/ static void ddSymmSummary( DdManager * table, int lower, int upper, int * symvars, int * symgroups) { int i,x,gbot; int TotalSymm = 0; int TotalSymmGroups = 0; for (i = lower; i <= upper; i++) { if (table->subtables[i].next != (unsigned) i) { TotalSymmGroups++; x = i; do { TotalSymm++; gbot = x; x = table->subtables[x].next; } while (x != i); #ifdef DD_DEBUG assert(table->subtables[gbot].next == (unsigned) i); #endif i = gbot; } } *symvars = TotalSymm; *symgroups = TotalSymmGroups; return; } /* end of ddSymmSummary */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddTable.c000066400000000000000000003202401300674244400235400ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddTable.c] PackageName [cudd] Synopsis [Unique table management functions.] Description [External procedures included in this module:
        • Cudd_Prime()
        Internal procedures included in this module:
        • cuddAllocNode()
        • cuddInitTable()
        • cuddFreeTable()
        • cuddGarbageCollect()
        • cuddZddGetNode()
        • cuddZddGetNodeIVO()
        • cuddUniqueInter()
        • cuddUniqueInterIVO()
        • cuddUniqueInterZdd()
        • cuddUniqueConst()
        • cuddRehash()
        • cuddShrinkSubtable()
        • cuddInsertSubtables()
        • cuddDestroySubtables()
        • cuddResizeTableZdd()
        • cuddSlowTableGrowth()
        Static procedures included in this module:
        • ddRehashZdd()
        • ddResizeTable()
        • cuddFindParent()
        • cuddOrderedInsert()
        • cuddOrderedThread()
        • cuddRotateLeft()
        • cuddRotateRight()
        • cuddDoRebalance()
        • cuddCheckCollisionOrdering()
        ] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST /* Constants for red/black trees. */ #define DD_STACK_SIZE 128 #define DD_RED 0 #define DD_BLACK 1 #define DD_PAGE_SIZE 8192 #define DD_PAGE_MASK ~(DD_PAGE_SIZE - 1) #endif #endif /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /* This is a hack for when CUDD_VALUE_TYPE is double */ typedef union hack { CUDD_VALUE_TYPE value; unsigned int bits[2]; } hack; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddTable.c,v 1.122 2009/02/19 16:24:28 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST /* Macros for red/black trees. */ #define DD_INSERT_COMPARE(x,y) \ (((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK)) #define DD_COLOR(p) ((p)->index) #define DD_IS_BLACK(p) ((p)->index == DD_BLACK) #define DD_IS_RED(p) ((p)->index == DD_RED) #define DD_LEFT(p) cuddT(p) #define DD_RIGHT(p) cuddE(p) #define DD_NEXT(p) ((p)->next) #endif #endif /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void ddRehashZdd (DdManager *unique, int i); static int ddResizeTable (DdManager *unique, int index); static int cuddFindParent (DdManager *table, DdNode *node); DD_INLINE static void ddFixLimits (DdManager *unique); #ifdef DD_RED_BLACK_FREE_LIST static void cuddOrderedInsert (DdNodePtr *root, DdNodePtr node); static DdNode * cuddOrderedThread (DdNode *root, DdNode *list); static void cuddRotateLeft (DdNodePtr *nodeP); static void cuddRotateRight (DdNodePtr *nodeP); static void cuddDoRebalance (DdNodePtr **stack, int stackN); #endif static void ddPatchTree (DdManager *dd, MtrNode *treenode); #ifdef DD_DEBUG static int cuddCheckCollisionOrdering (DdManager *unique, int i, int j); #endif static void ddReportRefMess (DdManager *unique, int i, const char *caller); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Returns the next prime >= p.] Description [] SideEffects [None] ******************************************************************************/ unsigned int Cudd_Prime( unsigned int p) { int i,pn; p--; do { p++; if (p&1) { pn = 1; i = 3; while ((unsigned) (i * i) <= p) { if (p % i == 0) { pn = 0; break; } i += 2; } } else { pn = 0; } } while (!pn); return(p); } /* end of Cudd_Prime */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Fast storage allocation for DdNodes in the table.] Description [Fast storage allocation for DdNodes in the table. The first 4 bytes of a chunk contain a pointer to the next block; the rest contains DD_MEM_CHUNK spaces for DdNodes. Returns a pointer to a new node if successful; NULL is memory is full.] SideEffects [None] SeeAlso [cuddDynamicAllocNode] ******************************************************************************/ DdNode * cuddAllocNode( DdManager * unique) { int i; DdNodePtr *mem; DdNode *list, *node; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; if (unique->nextFree == NULL) { /* free list is empty */ /* Check for exceeded limits. */ if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) > unique->maxLive) { unique->errorCode = CUDD_TOO_MANY_NODES; return(NULL); } if (unique->stash == NULL || unique->memused > unique->maxmemhard) { (void) cuddGarbageCollect(unique,1); mem = NULL; } if (unique->nextFree == NULL) { if (unique->memused > unique->maxmemhard) { unique->errorCode = CUDD_MAX_MEM_EXCEEDED; return(NULL); } /* Try to allocate a new block. */ saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; // mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 1); mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 2); MMoutOfMemory = saveHandler; if (mem == NULL) { /* No more memory: Try collecting garbage. If this succeeds, ** we end up with mem still NULL, but unique->nextFree != ** NULL. */ if (cuddGarbageCollect(unique,1) == 0) { /* Last resort: Free the memory stashed away, if there ** any. If this succeeeds, mem != NULL and ** unique->nextFree still NULL. */ if (unique->stash != NULL) { ABC_FREE(unique->stash); unique->stash = NULL; /* Inhibit resizing of tables. */ cuddSlowTableGrowth(unique); /* Now try again. */ // mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 1); mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 2); } if (mem == NULL) { /* Out of luck. Call the default handler to do ** whatever it specifies for a failed malloc. ** If this handler returns, then set error code, ** print warning, and return. */ (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); unique->errorCode = CUDD_MEMORY_OUT; #ifdef DD_VERBOSE (void) fprintf(unique->err, "cuddAllocNode: out of memory"); (void) fprintf(unique->err, "Memory in use = %lu\n", unique->memused); #endif return(NULL); } } } if (mem != NULL) { /* successful allocation; slice memory */ ptruint offset; unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); mem[0] = (DdNodePtr) unique->memoryList; unique->memoryList = mem; /* Here we rely on the fact that a DdNode is as large as 4 pointers. */ // offset = (ptruint) mem & (sizeof(DdNode) - 1); // mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); // assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0); // list = (DdNode *) mem; offset = (ptruint) mem & (32 - 1); mem += (32 - offset) / sizeof(DdNodePtr); assert(((ptruint) mem & (32 - 1)) == 0); list = (DdNode *) mem; i = 1; do { list[i - 1].ref = 0; list[i - 1].next = &list[i]; } while (++i < DD_MEM_CHUNK); list[DD_MEM_CHUNK-1].ref = 0; list[DD_MEM_CHUNK-1].next = NULL; unique->nextFree = &list[0]; } } } unique->allocated++; node = unique->nextFree; unique->nextFree = node->next; node->Id = (unique->allocated<<4); return(node); } /* end of cuddAllocNode */ /**Function******************************************************************** Synopsis [Creates and initializes the unique table.] Description [Creates and initializes the unique table. Returns a pointer to the table if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_Init cuddFreeTable] ******************************************************************************/ DdManager * cuddInitTable( unsigned int numVars /* Initial number of BDD variables (and subtables) */, unsigned int numVarsZ /* Initial number of ZDD variables (and subtables) */, unsigned int numSlots /* Initial size of the BDD subtables */, unsigned int looseUpTo /* Limit for fast table growth */) { DdManager *unique = ABC_ALLOC(DdManager,1); int i, j; DdNodePtr *nodelist; DdNode *sentinel; unsigned int slots; int shift; if (unique == NULL) { return(NULL); } sentinel = &(unique->sentinel); sentinel->ref = 0; sentinel->index = 0; cuddT(sentinel) = NULL; cuddE(sentinel) = NULL; sentinel->next = NULL; unique->epsilon = DD_EPSILON; unique->maxGrowth = DD_MAX_REORDER_GROWTH; unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH; unique->reordCycle = 0; /* do not use alternate threshold */ unique->size = numVars; unique->sizeZ = numVarsZ; unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars); unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ); /* Adjust the requested number of slots to a power of 2. */ slots = 8; while (slots < numSlots) { slots <<= 1; } unique->initSlots = slots; shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots); unique->slots = (numVars + numVarsZ + 1) * slots; unique->keys = 0; unique->maxLive = ~0; /* very large number */ unique->keysZ = 0; unique->dead = 0; unique->deadZ = 0; unique->gcFrac = DD_GC_FRAC_HI; unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); unique->looseUpTo = looseUpTo; unique->gcEnabled = 1; unique->allocated = 0; unique->reclaimed = 0; unique->subtables = ABC_ALLOC(DdSubtable,unique->maxSize); if (unique->subtables == NULL) { ABC_FREE(unique); return(NULL); } unique->subtableZ = ABC_ALLOC(DdSubtable,unique->maxSizeZ); if (unique->subtableZ == NULL) { ABC_FREE(unique->subtables); ABC_FREE(unique); return(NULL); } unique->perm = ABC_ALLOC(int,unique->maxSize); if (unique->perm == NULL) { ABC_FREE(unique->subtables); ABC_FREE(unique->subtableZ); ABC_FREE(unique); return(NULL); } unique->invperm = ABC_ALLOC(int,unique->maxSize); if (unique->invperm == NULL) { ABC_FREE(unique->subtables); ABC_FREE(unique->subtableZ); ABC_FREE(unique->perm); ABC_FREE(unique); return(NULL); } unique->permZ = ABC_ALLOC(int,unique->maxSizeZ); if (unique->permZ == NULL) { ABC_FREE(unique->subtables); ABC_FREE(unique->subtableZ); ABC_FREE(unique->perm); ABC_FREE(unique->invperm); ABC_FREE(unique); return(NULL); } unique->invpermZ = ABC_ALLOC(int,unique->maxSizeZ); if (unique->invpermZ == NULL) { ABC_FREE(unique->subtables); ABC_FREE(unique->subtableZ); ABC_FREE(unique->perm); ABC_FREE(unique->invperm); ABC_FREE(unique->permZ); ABC_FREE(unique); return(NULL); } unique->map = NULL; unique->stack = ABC_ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1); if (unique->stack == NULL) { ABC_FREE(unique->subtables); ABC_FREE(unique->subtableZ); ABC_FREE(unique->perm); ABC_FREE(unique->invperm); ABC_FREE(unique->permZ); ABC_FREE(unique->invpermZ); ABC_FREE(unique); return(NULL); } unique->stack[0] = NULL; /* to suppress harmless UMR */ #ifndef DD_NO_DEATH_ROW unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2); unique->deathRow = ABC_ALLOC(DdNodePtr,unique->deathRowDepth); if (unique->deathRow == NULL) { ABC_FREE(unique->subtables); ABC_FREE(unique->subtableZ); ABC_FREE(unique->perm); ABC_FREE(unique->invperm); ABC_FREE(unique->permZ); ABC_FREE(unique->invpermZ); ABC_FREE(unique->stack); ABC_FREE(unique); return(NULL); } for (i = 0; i < unique->deathRowDepth; i++) { unique->deathRow[i] = NULL; } unique->nextDead = 0; unique->deadMask = unique->deathRowDepth - 1; #endif for (i = 0; (unsigned) i < numVars; i++) { unique->subtables[i].slots = slots; unique->subtables[i].shift = shift; unique->subtables[i].keys = 0; unique->subtables[i].dead = 0; unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; unique->subtables[i].bindVar = 0; unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; unique->subtables[i].pairIndex = 0; unique->subtables[i].varHandled = 0; unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; nodelist = unique->subtables[i].nodelist = ABC_ALLOC(DdNodePtr,slots); if (nodelist == NULL) { for (j = 0; j < i; j++) { ABC_FREE(unique->subtables[j].nodelist); } ABC_FREE(unique->subtables); ABC_FREE(unique->subtableZ); ABC_FREE(unique->perm); ABC_FREE(unique->invperm); ABC_FREE(unique->permZ); ABC_FREE(unique->invpermZ); ABC_FREE(unique->stack); ABC_FREE(unique); return(NULL); } for (j = 0; (unsigned) j < slots; j++) { nodelist[j] = sentinel; } unique->perm[i] = i; unique->invperm[i] = i; } for (i = 0; (unsigned) i < numVarsZ; i++) { unique->subtableZ[i].slots = slots; unique->subtableZ[i].shift = shift; unique->subtableZ[i].keys = 0; unique->subtableZ[i].dead = 0; unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; nodelist = unique->subtableZ[i].nodelist = ABC_ALLOC(DdNodePtr,slots); if (nodelist == NULL) { for (j = 0; (unsigned) j < numVars; j++) { ABC_FREE(unique->subtables[j].nodelist); } ABC_FREE(unique->subtables); for (j = 0; j < i; j++) { ABC_FREE(unique->subtableZ[j].nodelist); } ABC_FREE(unique->subtableZ); ABC_FREE(unique->perm); ABC_FREE(unique->invperm); ABC_FREE(unique->permZ); ABC_FREE(unique->invpermZ); ABC_FREE(unique->stack); ABC_FREE(unique); return(NULL); } for (j = 0; (unsigned) j < slots; j++) { nodelist[j] = NULL; } unique->permZ[i] = i; unique->invpermZ[i] = i; } unique->constants.slots = slots; unique->constants.shift = shift; unique->constants.keys = 0; unique->constants.dead = 0; unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; nodelist = unique->constants.nodelist = ABC_ALLOC(DdNodePtr,slots); if (nodelist == NULL) { for (j = 0; (unsigned) j < numVars; j++) { ABC_FREE(unique->subtables[j].nodelist); } ABC_FREE(unique->subtables); for (j = 0; (unsigned) j < numVarsZ; j++) { ABC_FREE(unique->subtableZ[j].nodelist); } ABC_FREE(unique->subtableZ); ABC_FREE(unique->perm); ABC_FREE(unique->invperm); ABC_FREE(unique->permZ); ABC_FREE(unique->invpermZ); ABC_FREE(unique->stack); ABC_FREE(unique); return(NULL); } for (j = 0; (unsigned) j < slots; j++) { nodelist[j] = NULL; } unique->memoryList = NULL; unique->nextFree = NULL; unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ) * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) * slots * sizeof(DdNodePtr) + (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr); #ifndef DD_NO_DEATH_ROW unique->memused += unique->deathRowDepth * sizeof(DdNodePtr); #endif /* Initialize fields concerned with automatic dynamic reordering */ unique->reorderings = 0; unique->autoDyn = 0; /* initially disabled */ unique->autoDynZ = 0; /* initially disabled */ unique->realign = 0; /* initially disabled */ unique->realignZ = 0; /* initially disabled */ unique->reordered = 0; unique->autoMethod = CUDD_REORDER_SIFT; unique->autoMethodZ = CUDD_REORDER_SIFT; unique->nextDyn = DD_FIRST_REORDER; unique->countDead = ~0; unique->siftMaxVar = DD_SIFT_MAX_VAR; unique->siftMaxSwap = DD_SIFT_MAX_SWAPS; unique->tree = NULL; unique->treeZ = NULL; unique->groupcheck = CUDD_GROUP_CHECK7; unique->recomb = DD_DEFAULT_RECOMB; unique->symmviolation = 0; unique->arcviolation = 0; unique->populationSize = 0; unique->numberXovers = 0; unique->linear = NULL; unique->linearSize = 0; /* Initialize ZDD universe. */ unique->univ = (DdNodePtr *)NULL; /* Initialize auxiliary fields. */ unique->localCaches = NULL; unique->preGCHook = NULL; unique->postGCHook = NULL; unique->preReorderingHook = NULL; unique->postReorderingHook = NULL; unique->out = stdout; unique->err = stderr; unique->errorCode = CUDD_NO_ERROR; /* Initialize statistical counters. */ unique->maxmemhard = ~ 0UL; unique->garbageCollections = 0; unique->GCTime = 0; unique->reordTime = 0; #ifdef DD_STATS unique->nodesDropped = 0; unique->nodesFreed = 0; #endif unique->peakLiveNodes = 0; #ifdef DD_UNIQUE_PROFILE unique->uniqueLookUps = 0; unique->uniqueLinks = 0; #endif #ifdef DD_COUNT unique->recursiveCalls = 0; unique->swapSteps = 0; #ifdef DD_STATS unique->nextSample = 250000; #endif #endif return(unique); } /* end of cuddInitTable */ /**Function******************************************************************** Synopsis [Frees the resources associated to a unique table.] Description [] SideEffects [None] SeeAlso [cuddInitTable] ******************************************************************************/ void cuddFreeTable( DdManager * unique) { DdNodePtr *next; DdNodePtr *memlist = unique->memoryList; int i; if (unique->univ != NULL) cuddZddFreeUniv(unique); while (memlist != NULL) { next = (DdNodePtr *) memlist[0]; /* link to next block */ ABC_FREE(memlist); memlist = next; } unique->nextFree = NULL; unique->memoryList = NULL; for (i = 0; i < unique->size; i++) { ABC_FREE(unique->subtables[i].nodelist); } for (i = 0; i < unique->sizeZ; i++) { ABC_FREE(unique->subtableZ[i].nodelist); } ABC_FREE(unique->constants.nodelist); ABC_FREE(unique->subtables); ABC_FREE(unique->subtableZ); ABC_FREE(unique->acache); ABC_FREE(unique->perm); ABC_FREE(unique->permZ); ABC_FREE(unique->invperm); ABC_FREE(unique->invpermZ); ABC_FREE(unique->vars); if (unique->map != NULL) ABC_FREE(unique->map); ABC_FREE(unique->stack); #ifndef DD_NO_DEATH_ROW ABC_FREE(unique->deathRow); #endif if (unique->tree != NULL) Mtr_FreeTree(unique->tree); if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ); if (unique->linear != NULL) ABC_FREE(unique->linear); while (unique->preGCHook != NULL) Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK); while (unique->postGCHook != NULL) Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK); while (unique->preReorderingHook != NULL) Cudd_RemoveHook(unique,unique->preReorderingHook->f, CUDD_PRE_REORDERING_HOOK); while (unique->postReorderingHook != NULL) Cudd_RemoveHook(unique,unique->postReorderingHook->f, CUDD_POST_REORDERING_HOOK); ABC_FREE(unique); } /* end of cuddFreeTable */ /**Function******************************************************************** Synopsis [Performs garbage collection on the unique tables.] Description [Performs garbage collection on the BDD and ZDD unique tables. If clearCache is 0, the cache is not cleared. This should only be specified if the cache has been cleared right before calling cuddGarbageCollect. (As in the case of dynamic reordering.) Returns the total number of deleted nodes.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddGarbageCollect( DdManager * unique, int clearCache) { DdHook *hook; DdCache *cache = unique->cache; DdNode *sentinel = &(unique->sentinel); DdNodePtr *nodelist; int i, j, deleted, totalDeleted, totalDeletedZ; DdCache *c; DdNode *node,*next; DdNodePtr *lastP; int slots; long localTime; #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST DdNodePtr tree; #else DdNodePtr *memListTrav, *nxtNode; DdNode *downTrav, *sentry; int k; #endif #endif #ifndef DD_NO_DEATH_ROW cuddClearDeathRow(unique); #endif hook = unique->preGCHook; while (hook != NULL) { int res = (hook->f)(unique,"DD",NULL); if (res == 0) return(0); hook = hook->next; } if (unique->dead + unique->deadZ == 0) { hook = unique->postGCHook; while (hook != NULL) { int res = (hook->f)(unique,"DD",NULL); if (res == 0) return(0); hook = hook->next; } return(0); } /* If many nodes are being reclaimed, we want to resize the tables ** more aggressively, to reduce the frequency of garbage collection. */ if (clearCache && unique->gcFrac == DD_GC_FRAC_LO && unique->slots <= unique->looseUpTo && unique->stash != NULL) { unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); #ifdef DD_VERBOSE (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI); (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); #endif unique->gcFrac = DD_GC_FRAC_HI; return(0); } localTime = util_cpu_time(); unique->garbageCollections++; #ifdef DD_VERBOSE (void) fprintf(unique->err, "garbage collecting (%d dead BDD nodes out of %d, min %d)...", unique->dead, unique->keys, unique->minDead); (void) fprintf(unique->err, " (%d dead ZDD nodes out of %d)...", unique->deadZ, unique->keysZ); #endif /* Remove references to garbage collected nodes from the cache. */ if (clearCache) { slots = unique->cacheSlots; for (i = 0; i < slots; i++) { c = &cache[i]; if (c->data != NULL) { if (cuddClean(c->f)->ref == 0 || cuddClean(c->g)->ref == 0 || (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || (c->data != DD_NON_CONSTANT && Cudd_Regular(c->data)->ref == 0)) { c->data = NULL; unique->cachedeletions++; } } } cuddLocalCacheClearDead(unique); } /* Now return dead nodes to free list. Count them for sanity check. */ totalDeleted = 0; #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST tree = NULL; #endif #endif for (i = 0; i < unique->size; i++) { if (unique->subtables[i].dead == 0) continue; nodelist = unique->subtables[i].nodelist; deleted = 0; slots = unique->subtables[i].slots; for (j = 0; j < slots; j++) { lastP = &(nodelist[j]); node = *lastP; while (node != sentinel) { next = node->next; if (node->ref == 0) { deleted++; #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif cuddOrderedInsert(&tree,node); #ifdef __osf__ #pragma pointer_size restore #endif #endif #else cuddDeallocNode(unique,node); #endif } else { *lastP = node; lastP = &(node->next); } node = next; } *lastP = sentinel; } if ((unsigned) deleted != unique->subtables[i].dead) { ddReportRefMess(unique, i, "cuddGarbageCollect"); } totalDeleted += deleted; unique->subtables[i].keys -= deleted; unique->subtables[i].dead = 0; } if (unique->constants.dead != 0) { nodelist = unique->constants.nodelist; deleted = 0; slots = unique->constants.slots; for (j = 0; j < slots; j++) { lastP = &(nodelist[j]); node = *lastP; while (node != NULL) { next = node->next; if (node->ref == 0) { deleted++; #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif cuddOrderedInsert(&tree,node); #ifdef __osf__ #pragma pointer_size restore #endif #endif #else cuddDeallocNode(unique,node); #endif } else { *lastP = node; lastP = &(node->next); } node = next; } *lastP = NULL; } if ((unsigned) deleted != unique->constants.dead) { ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect"); } totalDeleted += deleted; unique->constants.keys -= deleted; unique->constants.dead = 0; } if ((unsigned) totalDeleted != unique->dead) { ddReportRefMess(unique, -1, "cuddGarbageCollect"); } unique->keys -= totalDeleted; unique->dead = 0; #ifdef DD_STATS unique->nodesFreed += (double) totalDeleted; #endif totalDeletedZ = 0; for (i = 0; i < unique->sizeZ; i++) { if (unique->subtableZ[i].dead == 0) continue; nodelist = unique->subtableZ[i].nodelist; deleted = 0; slots = unique->subtableZ[i].slots; for (j = 0; j < slots; j++) { lastP = &(nodelist[j]); node = *lastP; while (node != NULL) { next = node->next; if (node->ref == 0) { deleted++; #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST #ifdef __osf__ #pragma pointer_size save #pragma pointer_size short #endif cuddOrderedInsert(&tree,node); #ifdef __osf__ #pragma pointer_size restore #endif #endif #else cuddDeallocNode(unique,node); #endif } else { *lastP = node; lastP = &(node->next); } node = next; } *lastP = NULL; } if ((unsigned) deleted != unique->subtableZ[i].dead) { ddReportRefMess(unique, i, "cuddGarbageCollect"); } totalDeletedZ += deleted; unique->subtableZ[i].keys -= deleted; unique->subtableZ[i].dead = 0; } /* No need to examine the constant table for ZDDs. ** If we did we should be careful not to count whatever dead ** nodes we found there among the dead ZDD nodes. */ if ((unsigned) totalDeletedZ != unique->deadZ) { ddReportRefMess(unique, -1, "cuddGarbageCollect"); } unique->keysZ -= totalDeletedZ; unique->deadZ = 0; #ifdef DD_STATS unique->nodesFreed += (double) totalDeletedZ; #endif #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST unique->nextFree = cuddOrderedThread(tree,unique->nextFree); #else memListTrav = unique->memoryList; sentry = NULL; while (memListTrav != NULL) { ptruint offset; nxtNode = (DdNodePtr *)memListTrav[0]; // offset = (ptruint) memListTrav & (sizeof(DdNode) - 1); // memListTrav += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); offset = (ptruint) memListTrav & (32 - 1); memListTrav += (32 - offset) / sizeof(DdNodePtr); downTrav = (DdNode *)memListTrav; k = 0; do { if (downTrav[k].ref == 0) { if (sentry == NULL) { unique->nextFree = sentry = &downTrav[k]; } else { /* First hook sentry->next to the dead node and then ** reassign sentry to the dead node. */ sentry = (sentry->next = &downTrav[k]); } } } while (++k < DD_MEM_CHUNK); memListTrav = nxtNode; } sentry->next = NULL; #endif #endif unique->GCTime += util_cpu_time() - localTime; hook = unique->postGCHook; while (hook != NULL) { int res = (hook->f)(unique,"DD",NULL); if (res == 0) return(0); hook = hook->next; } #ifdef DD_VERBOSE (void) fprintf(unique->err," done\n"); #endif return(totalDeleted+totalDeletedZ); } /* end of cuddGarbageCollect */ /**Function******************************************************************** Synopsis [Wrapper for cuddUniqueInterZdd.] Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD reduction rule. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.] SideEffects [None] SeeAlso [cuddUniqueInterZdd] ******************************************************************************/ DdNode * cuddZddGetNode( DdManager * zdd, int id, DdNode * T, DdNode * E) { DdNode *node; if (T == DD_ZERO(zdd)) return(E); node = cuddUniqueInterZdd(zdd, id, T, E); return(node); } /* end of cuddZddGetNode */ /**Function******************************************************************** Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable ordering.] Description [Wrapper for cuddUniqueInterZdd that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of g and h in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.] SideEffects [None] SeeAlso [cuddZddGetNode cuddZddIsop] ******************************************************************************/ DdNode * cuddZddGetNodeIVO( DdManager * dd, int index, DdNode * g, DdNode * h) { DdNode *f, *r, *t; DdNode *zdd_one = DD_ONE(dd); DdNode *zdd_zero = DD_ZERO(dd); f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero); if (f == NULL) { return(NULL); } cuddRef(f); t = cuddZddProduct(dd, f, g); if (t == NULL) { Cudd_RecursiveDerefZdd(dd, f); return(NULL); } cuddRef(t); Cudd_RecursiveDerefZdd(dd, f); r = cuddZddUnion(dd, t, h); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, t); return(NULL); } cuddRef(r); Cudd_RecursiveDerefZdd(dd, t); cuddDeref(r); return(r); } /* end of cuddZddGetNodeIVO */ /**Function******************************************************************** Synopsis [Checks the unique table for the existence of an internal node.] Description [Checks the unique table for the existence of an internal node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.] SideEffects [None] SeeAlso [cuddUniqueInterZdd] ******************************************************************************/ DdNode * cuddUniqueInter( DdManager * unique, int index, DdNode * T, DdNode * E) { int pos; unsigned int level; int retval; DdNodePtr *nodelist; DdNode *looking; DdNodePtr *previousP; DdSubtable *subtable; int gcNumber; #ifdef DD_UNIQUE_PROFILE unique->uniqueLookUps++; #endif if (index >= unique->size) { if (!ddResizeTable(unique,index)) return(NULL); } level = unique->perm[index]; subtable = &(unique->subtables[level]); #ifdef DD_DEBUG assert(level < (unsigned) cuddI(unique,T->index)); assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); #endif pos = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift); nodelist = subtable->nodelist; previousP = &(nodelist[pos]); looking = *previousP; while (T < cuddT(looking)) { previousP = &(looking->next); looking = *previousP; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } while (T == cuddT(looking) && E < cuddE(looking)) { previousP = &(looking->next); looking = *previousP; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } if (T == cuddT(looking) && E == cuddE(looking)) { if (looking->ref == 0) { cuddReclaim(unique,looking); } return(looking); } /* countDead is 0 if deads should be counted and ~0 if they should not. */ if (unique->autoDyn && unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) { #ifdef DD_DEBUG retval = Cudd_DebugCheck(unique); if (retval != 0) return(NULL); retval = Cudd_CheckKeys(unique); if (retval != 0) return(NULL); #endif retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */ if (retval == 0) unique->reordered = 2; #ifdef DD_DEBUG retval = Cudd_DebugCheck(unique); if (retval != 0) unique->reordered = 2; retval = Cudd_CheckKeys(unique); if (retval != 0) unique->reordered = 2; #endif return(NULL); } if (subtable->keys > subtable->maxKeys) { if (unique->gcEnabled && ((unique->dead > unique->minDead) || ((unique->dead > unique->minDead / 2) && (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */ (void) cuddGarbageCollect(unique,1); } else { cuddRehash(unique,(int)level); } /* Update pointer to insertion point. In the case of rehashing, ** the slot may have changed. In the case of garbage collection, ** the predecessor may have been dead. */ pos = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift); nodelist = subtable->nodelist; previousP = &(nodelist[pos]); looking = *previousP; while (T < cuddT(looking)) { previousP = &(looking->next); looking = *previousP; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } while (T == cuddT(looking) && E < cuddE(looking)) { previousP = &(looking->next); looking = *previousP; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } } gcNumber = unique->garbageCollections; looking = cuddAllocNode(unique); if (looking == NULL) { return(NULL); } unique->keys++; subtable->keys++; if (gcNumber != unique->garbageCollections) { DdNode *looking2; pos = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift); nodelist = subtable->nodelist; previousP = &(nodelist[pos]); looking2 = *previousP; while (T < cuddT(looking2)) { previousP = &(looking2->next); looking2 = *previousP; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } while (T == cuddT(looking2) && E < cuddE(looking2)) { previousP = &(looking2->next); looking2 = *previousP; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } } looking->index = index; cuddT(looking) = T; cuddE(looking) = E; looking->next = *previousP; *previousP = looking; cuddSatInc(T->ref); /* we know T is a regular pointer */ cuddRef(E); #ifdef DD_DEBUG cuddCheckCollisionOrdering(unique,level,pos); #endif // assert( Cudd_Regular(T)->Id < 100000000 ); // assert( Cudd_Regular(E)->Id < 100000000 ); return(looking); } /* end of cuddUniqueInter */ /**Function******************************************************************** Synopsis [Wrapper for cuddUniqueInter that is independent of variable ordering.] Description [Wrapper for cuddUniqueInter that is independent of variable ordering (IVO). This function does not require parameter index to precede the indices of the top nodes of T and E in the variable order. Returns a pointer to the result node under normal conditions; NULL if reordering occurred or memory was exhausted.] SideEffects [None] SeeAlso [cuddUniqueInter Cudd_MakeBddFromZddCover] ******************************************************************************/ DdNode * cuddUniqueInterIVO( DdManager * unique, int index, DdNode * T, DdNode * E) { DdNode *result; DdNode *v; v = cuddUniqueInter(unique, index, DD_ONE(unique), Cudd_Not(DD_ONE(unique))); if (v == NULL) return(NULL); cuddRef(v); result = cuddBddIteRecur(unique, v, T, E); Cudd_RecursiveDeref(unique, v); return(result); } /**Function******************************************************************** Synopsis [Checks the unique table for the existence of an internal ZDD node.] Description [Checks the unique table for the existence of an internal ZDD node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. For a newly created node, increments the reference counts of what T and E point to. Returns a pointer to the new node if successful; NULL if memory is exhausted or if reordering took place.] SideEffects [None] SeeAlso [cuddUniqueInter] ******************************************************************************/ DdNode * cuddUniqueInterZdd( DdManager * unique, int index, DdNode * T, DdNode * E) { int pos; unsigned int level; int retval; DdNodePtr *nodelist; DdNode *looking; DdSubtable *subtable; #ifdef DD_UNIQUE_PROFILE unique->uniqueLookUps++; #endif if (index >= unique->sizeZ) { if (!cuddResizeTableZdd(unique,index)) return(NULL); } level = unique->permZ[index]; subtable = &(unique->subtableZ[level]); #ifdef DD_DEBUG assert(level < (unsigned) cuddIZ(unique,T->index)); assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index)); #endif if (subtable->keys > subtable->maxKeys) { if (unique->gcEnabled && ((unique->deadZ > unique->minDead) || (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */ (void) cuddGarbageCollect(unique,1); } else { ddRehashZdd(unique,(int)level); } } pos = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift); nodelist = subtable->nodelist; looking = nodelist[pos]; while (looking != NULL) { if (cuddT(looking) == T && cuddE(looking) == E) { if (looking->ref == 0) { cuddReclaimZdd(unique,looking); } return(looking); } looking = looking->next; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } /* countDead is 0 if deads should be counted and ~0 if they should not. */ if (unique->autoDynZ && unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) { #ifdef DD_DEBUG retval = Cudd_DebugCheck(unique); if (retval != 0) return(NULL); retval = Cudd_CheckKeys(unique); if (retval != 0) return(NULL); #endif retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */ if (retval == 0) unique->reordered = 2; #ifdef DD_DEBUG retval = Cudd_DebugCheck(unique); if (retval != 0) unique->reordered = 2; retval = Cudd_CheckKeys(unique); if (retval != 0) unique->reordered = 2; #endif return(NULL); } unique->keysZ++; subtable->keys++; looking = cuddAllocNode(unique); if (looking == NULL) return(NULL); looking->index = index; cuddT(looking) = T; cuddE(looking) = E; looking->next = nodelist[pos]; nodelist[pos] = looking; cuddRef(T); cuddRef(E); return(looking); } /* end of cuddUniqueInterZdd */ /**Function******************************************************************** Synopsis [Checks the unique table for the existence of a constant node.] Description [Checks the unique table for the existence of a constant node. If it does not exist, it creates a new one. Does not modify the reference count of whatever is returned. A newly created internal node comes back with a reference count 0. Returns a pointer to the new node.] SideEffects [None] ******************************************************************************/ DdNode * cuddUniqueConst( DdManager * unique, CUDD_VALUE_TYPE value) { int pos; DdNodePtr *nodelist; DdNode *looking; hack split; #ifdef DD_UNIQUE_PROFILE unique->uniqueLookUps++; #endif if (unique->constants.keys > unique->constants.maxKeys) { if (unique->gcEnabled && ((unique->dead > unique->minDead) || (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */ (void) cuddGarbageCollect(unique,1); } else { cuddRehash(unique,CUDD_CONST_INDEX); } } cuddAdjust(value); /* for the case of crippled infinities */ if (ddAbs(value) < unique->epsilon) { value = 0.0; } split.value = value; pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift); nodelist = unique->constants.nodelist; looking = nodelist[pos]; /* Here we compare values both for equality and for difference less * than epsilon. The first comparison is required when values are * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for * every X. */ while (looking != NULL) { if (looking->type.value == value || ddEqualVal(looking->type.value,value,unique->epsilon)) { if (looking->ref == 0) { cuddReclaim(unique,looking); } return(looking); } looking = looking->next; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } unique->keys++; unique->constants.keys++; looking = cuddAllocNode(unique); if (looking == NULL) return(NULL); looking->index = CUDD_CONST_INDEX; looking->type.value = value; looking->next = nodelist[pos]; nodelist[pos] = looking; return(looking); } /* end of cuddUniqueConst */ /**Function******************************************************************** Synopsis [Rehashes a unique subtable.] Description [Doubles the size of a unique subtable and rehashes its contents.] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddRehash( DdManager * unique, int i) { unsigned int slots, oldslots; int shift, oldshift; int j, pos; DdNodePtr *nodelist, *oldnodelist; DdNode *node, *next; DdNode *sentinel = &(unique->sentinel); hack split; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) { unique->gcFrac = DD_GC_FRAC_LO; unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); #ifdef DD_VERBOSE (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO); (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); #endif } if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) { unique->gcFrac = DD_GC_FRAC_MIN; unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); #ifdef DD_VERBOSE (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN); (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); #endif cuddShrinkDeathRow(unique); if (cuddGarbageCollect(unique,1) > 0) return; } if (i != CUDD_CONST_INDEX) { oldslots = unique->subtables[i].slots; oldshift = unique->subtables[i].shift; oldnodelist = unique->subtables[i].nodelist; /* Compute the new size of the subtable. */ slots = oldslots << 1; shift = oldshift - 1; saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; nodelist = ABC_ALLOC(DdNodePtr, slots); MMoutOfMemory = saveHandler; if (nodelist == NULL) { (void) fprintf(unique->err, "Unable to resize subtable %d for lack of memory\n", i); /* Prevent frequent resizing attempts. */ (void) cuddGarbageCollect(unique,1); if (unique->stash != NULL) { ABC_FREE(unique->stash); unique->stash = NULL; /* Inhibit resizing of tables. */ cuddSlowTableGrowth(unique); } return; } unique->subtables[i].nodelist = nodelist; unique->subtables[i].slots = slots; unique->subtables[i].shift = shift; unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; /* Move the nodes from the old table to the new table. ** This code depends on the type of hash function. ** It assumes that the effect of doubling the size of the table ** is to retain one more bit of the 32-bit hash value. ** The additional bit is the LSB. */ for (j = 0; (unsigned) j < oldslots; j++) { DdNodePtr *evenP, *oddP; node = oldnodelist[j]; evenP = &(nodelist[j<<1]); oddP = &(nodelist[(j<<1)+1]); while (node != sentinel) { next = node->next; pos = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift); if (pos & 1) { *oddP = node; oddP = &(node->next); } else { *evenP = node; evenP = &(node->next); } node = next; } *evenP = *oddP = sentinel; } ABC_FREE(oldnodelist); #ifdef DD_VERBOSE (void) fprintf(unique->err, "rehashing layer %d: keys %d dead %d new size %d\n", i, unique->subtables[i].keys, unique->subtables[i].dead, slots); #endif } else { oldslots = unique->constants.slots; oldshift = unique->constants.shift; oldnodelist = unique->constants.nodelist; /* The constant subtable is never subjected to reordering. ** Therefore, when it is resized, it is because it has just ** reached the maximum load. We can safely just double the size, ** with no need for the loop we use for the other tables. */ slots = oldslots << 1; shift = oldshift - 1; saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; nodelist = ABC_ALLOC(DdNodePtr, slots); MMoutOfMemory = saveHandler; if (nodelist == NULL) { (void) fprintf(unique->err, "Unable to resize constant subtable for lack of memory\n"); (void) cuddGarbageCollect(unique,1); for (j = 0; j < unique->size; j++) { unique->subtables[j].maxKeys <<= 1; } unique->constants.maxKeys <<= 1; return; } unique->constants.slots = slots; unique->constants.shift = shift; unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; unique->constants.nodelist = nodelist; for (j = 0; (unsigned) j < slots; j++) { nodelist[j] = NULL; } for (j = 0; (unsigned) j < oldslots; j++) { node = oldnodelist[j]; while (node != NULL) { next = node->next; split.value = cuddV(node); pos = ddHash(split.bits[0], split.bits[1], shift); node->next = nodelist[pos]; nodelist[pos] = node; node = next; } } ABC_FREE(oldnodelist); #ifdef DD_VERBOSE (void) fprintf(unique->err, "rehashing constants: keys %d dead %d new size %d\n", unique->constants.keys,unique->constants.dead,slots); #endif } /* Update global data */ unique->memused += (slots - oldslots) * sizeof(DdNodePtr); unique->slots += (slots - oldslots); ddFixLimits(unique); } /* end of cuddRehash */ /**Function******************************************************************** Synopsis [Shrinks a subtable.] Description [Shrinks a subtable.] SideEffects [None] SeeAlso [cuddRehash] ******************************************************************************/ void cuddShrinkSubtable( DdManager *unique, int i) { int j; int shift, posn; DdNodePtr *nodelist, *oldnodelist; DdNode *node, *next; DdNode *sentinel = &(unique->sentinel); unsigned int slots, oldslots; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; oldnodelist = unique->subtables[i].nodelist; oldslots = unique->subtables[i].slots; slots = oldslots >> 1; saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; nodelist = ABC_ALLOC(DdNodePtr, slots); MMoutOfMemory = saveHandler; if (nodelist == NULL) { return; } unique->subtables[i].nodelist = nodelist; unique->subtables[i].slots = slots; unique->subtables[i].shift++; unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; #ifdef DD_VERBOSE (void) fprintf(unique->err, "shrunk layer %d (%d keys) from %d to %d slots\n", i, unique->subtables[i].keys, oldslots, slots); #endif for (j = 0; (unsigned) j < slots; j++) { nodelist[j] = sentinel; } shift = unique->subtables[i].shift; for (j = 0; (unsigned) j < oldslots; j++) { node = oldnodelist[j]; while (node != sentinel) { DdNode *looking, *T, *E; DdNodePtr *previousP; next = node->next; posn = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift); previousP = &(nodelist[posn]); looking = *previousP; T = cuddT(node); E = cuddE(node); while (T < cuddT(looking)) { previousP = &(looking->next); looking = *previousP; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } while (T == cuddT(looking) && E < cuddE(looking)) { previousP = &(looking->next); looking = *previousP; #ifdef DD_UNIQUE_PROFILE unique->uniqueLinks++; #endif } node->next = *previousP; *previousP = node; node = next; } } ABC_FREE(oldnodelist); unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *); unique->slots += slots - oldslots; unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); unique->cacheSlack = (int) ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - 2 * (int) unique->cacheSlots; } /* end of cuddShrinkSubtable */ /**Function******************************************************************** Synopsis [Inserts n new subtables in a unique table at level.] Description [Inserts n new subtables in a unique table at level. The number n should be positive, and level should be an existing level. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddDestroySubtables] ******************************************************************************/ int cuddInsertSubtables( DdManager * unique, int n, int level) { DdSubtable *newsubtables; DdNodePtr *newnodelist; DdNodePtr *newvars; DdNode *sentinel = &(unique->sentinel); int oldsize,newsize; int i,j,index,reorderSave; unsigned int numSlots = unique->initSlots; int *newperm, *newinvperm, *newmap=NULL; DdNode *one, *zero; #ifdef DD_DEBUG assert(n > 0 && level < unique->size); #endif oldsize = unique->size; /* Easy case: there is still room in the current table. */ if (oldsize + n <= unique->maxSize) { /* Shift the tables at and below level. */ for (i = oldsize - 1; i >= level; i--) { unique->subtables[i+n].slots = unique->subtables[i].slots; unique->subtables[i+n].shift = unique->subtables[i].shift; unique->subtables[i+n].keys = unique->subtables[i].keys; unique->subtables[i+n].maxKeys = unique->subtables[i].maxKeys; unique->subtables[i+n].dead = unique->subtables[i].dead; unique->subtables[i+n].nodelist = unique->subtables[i].nodelist; unique->subtables[i+n].bindVar = unique->subtables[i].bindVar; unique->subtables[i+n].varType = unique->subtables[i].varType; unique->subtables[i+n].pairIndex = unique->subtables[i].pairIndex; unique->subtables[i+n].varHandled = unique->subtables[i].varHandled; unique->subtables[i+n].varToBeGrouped = unique->subtables[i].varToBeGrouped; index = unique->invperm[i]; unique->invperm[i+n] = index; unique->perm[index] += n; } /* Create new subtables. */ for (i = 0; i < n; i++) { unique->subtables[level+i].slots = numSlots; unique->subtables[level+i].shift = sizeof(int) * 8 - cuddComputeFloorLog2(numSlots); unique->subtables[level+i].keys = 0; unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; unique->subtables[level+i].dead = 0; unique->subtables[level+i].bindVar = 0; unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT; unique->subtables[level+i].pairIndex = 0; unique->subtables[level+i].varHandled = 0; unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE; unique->perm[oldsize+i] = level + i; unique->invperm[level+i] = oldsize + i; newnodelist = unique->subtables[level+i].nodelist = ABC_ALLOC(DdNodePtr, numSlots); if (newnodelist == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } for (j = 0; (unsigned) j < numSlots; j++) { newnodelist[j] = sentinel; } } if (unique->map != NULL) { for (i = 0; i < n; i++) { unique->map[oldsize+i] = oldsize + i; } } } else { /* The current table is too small: we need to allocate a new, ** larger one; move all old subtables, and initialize the new ** subtables. */ newsize = oldsize + n + DD_DEFAULT_RESIZE; #ifdef DD_VERBOSE (void) fprintf(unique->err, "Increasing the table size from %d to %d\n", unique->maxSize, newsize); #endif /* Allocate memory for new arrays (except nodelists). */ newsubtables = ABC_ALLOC(DdSubtable,newsize); if (newsubtables == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } newvars = ABC_ALLOC(DdNodePtr,newsize); if (newvars == NULL) { unique->errorCode = CUDD_MEMORY_OUT; ABC_FREE(newsubtables); return(0); } newperm = ABC_ALLOC(int,newsize); if (newperm == NULL) { unique->errorCode = CUDD_MEMORY_OUT; ABC_FREE(newsubtables); ABC_FREE(newvars); return(0); } newinvperm = ABC_ALLOC(int,newsize); if (newinvperm == NULL) { unique->errorCode = CUDD_MEMORY_OUT; ABC_FREE(newsubtables); ABC_FREE(newvars); ABC_FREE(newperm); return(0); } if (unique->map != NULL) { newmap = ABC_ALLOC(int,newsize); if (newmap == NULL) { unique->errorCode = CUDD_MEMORY_OUT; ABC_FREE(newsubtables); ABC_FREE(newvars); ABC_FREE(newperm); ABC_FREE(newinvperm); return(0); } unique->memused += (newsize - unique->maxSize) * sizeof(int); } unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); /* Copy levels before insertion points from old tables. */ for (i = 0; i < level; i++) { newsubtables[i].slots = unique->subtables[i].slots; newsubtables[i].shift = unique->subtables[i].shift; newsubtables[i].keys = unique->subtables[i].keys; newsubtables[i].maxKeys = unique->subtables[i].maxKeys; newsubtables[i].dead = unique->subtables[i].dead; newsubtables[i].nodelist = unique->subtables[i].nodelist; newsubtables[i].bindVar = unique->subtables[i].bindVar; newsubtables[i].varType = unique->subtables[i].varType; newsubtables[i].pairIndex = unique->subtables[i].pairIndex; newsubtables[i].varHandled = unique->subtables[i].varHandled; newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; newvars[i] = unique->vars[i]; newperm[i] = unique->perm[i]; newinvperm[i] = unique->invperm[i]; } /* Finish initializing permutation for new table to old one. */ for (i = level; i < oldsize; i++) { newperm[i] = unique->perm[i]; } /* Initialize new levels. */ for (i = level; i < level + n; i++) { newsubtables[i].slots = numSlots; newsubtables[i].shift = sizeof(int) * 8 - cuddComputeFloorLog2(numSlots); newsubtables[i].keys = 0; newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; newsubtables[i].dead = 0; newsubtables[i].bindVar = 0; newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; newsubtables[i].pairIndex = 0; newsubtables[i].varHandled = 0; newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; newperm[oldsize + i - level] = i; newinvperm[i] = oldsize + i - level; newnodelist = newsubtables[i].nodelist = ABC_ALLOC(DdNodePtr, numSlots); if (newnodelist == NULL) { /* We are going to leak some memory. We should clean up. */ unique->errorCode = CUDD_MEMORY_OUT; return(0); } for (j = 0; (unsigned) j < numSlots; j++) { newnodelist[j] = sentinel; } } /* Copy the old tables for levels past the insertion point. */ for (i = level; i < oldsize; i++) { newsubtables[i+n].slots = unique->subtables[i].slots; newsubtables[i+n].shift = unique->subtables[i].shift; newsubtables[i+n].keys = unique->subtables[i].keys; newsubtables[i+n].maxKeys = unique->subtables[i].maxKeys; newsubtables[i+n].dead = unique->subtables[i].dead; newsubtables[i+n].nodelist = unique->subtables[i].nodelist; newsubtables[i+n].bindVar = unique->subtables[i].bindVar; newsubtables[i+n].varType = unique->subtables[i].varType; newsubtables[i+n].pairIndex = unique->subtables[i].pairIndex; newsubtables[i+n].varHandled = unique->subtables[i].varHandled; newsubtables[i+n].varToBeGrouped = unique->subtables[i].varToBeGrouped; newvars[i] = unique->vars[i]; index = unique->invperm[i]; newinvperm[i+n] = index; newperm[index] += n; } /* Update the map. */ if (unique->map != NULL) { for (i = 0; i < oldsize; i++) { newmap[i] = unique->map[i]; } for (i = oldsize; i < oldsize + n; i++) { newmap[i] = i; } ABC_FREE(unique->map); unique->map = newmap; } /* Install the new tables and free the old ones. */ ABC_FREE(unique->subtables); unique->subtables = newsubtables; unique->maxSize = newsize; ABC_FREE(unique->vars); unique->vars = newvars; ABC_FREE(unique->perm); unique->perm = newperm; ABC_FREE(unique->invperm); unique->invperm = newinvperm; /* Update the stack for iterative procedures. */ if (newsize > unique->maxSizeZ) { ABC_FREE(unique->stack); unique->stack = ABC_ALLOC(DdNodePtr,newsize + 1); if (unique->stack == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } unique->stack[0] = NULL; /* to suppress harmless UMR */ unique->memused += (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) * sizeof(DdNode *); } } /* Update manager parameters to account for the new subtables. */ unique->slots += n * numSlots; ddFixLimits(unique); unique->size += n; /* Now that the table is in a coherent state, create the new ** projection functions. We need to temporarily disable reordering, ** because we cannot reorder without projection functions in place. **/ one = unique->one; zero = Cudd_Not(one); reorderSave = unique->autoDyn; unique->autoDyn = 0; for (i = oldsize; i < oldsize + n; i++) { unique->vars[i] = cuddUniqueInter(unique,i,one,zero); if (unique->vars[i] == NULL) { unique->autoDyn = reorderSave; /* Shift everything back so table remains coherent. */ for (j = oldsize; j < i; j++) { Cudd_IterDerefBdd(unique,unique->vars[j]); cuddDeallocNode(unique,unique->vars[j]); unique->vars[j] = NULL; } for (j = level; j < oldsize; j++) { unique->subtables[j].slots = unique->subtables[j+n].slots; unique->subtables[j].slots = unique->subtables[j+n].slots; unique->subtables[j].shift = unique->subtables[j+n].shift; unique->subtables[j].keys = unique->subtables[j+n].keys; unique->subtables[j].maxKeys = unique->subtables[j+n].maxKeys; unique->subtables[j].dead = unique->subtables[j+n].dead; ABC_FREE(unique->subtables[j].nodelist); unique->subtables[j].nodelist = unique->subtables[j+n].nodelist; unique->subtables[j+n].nodelist = NULL; unique->subtables[j].bindVar = unique->subtables[j+n].bindVar; unique->subtables[j].varType = unique->subtables[j+n].varType; unique->subtables[j].pairIndex = unique->subtables[j+n].pairIndex; unique->subtables[j].varHandled = unique->subtables[j+n].varHandled; unique->subtables[j].varToBeGrouped = unique->subtables[j+n].varToBeGrouped; index = unique->invperm[j+n]; unique->invperm[j] = index; unique->perm[index] -= n; } unique->size = oldsize; unique->slots -= n * numSlots; ddFixLimits(unique); (void) Cudd_DebugCheck(unique); return(0); } cuddRef(unique->vars[i]); } if (unique->tree != NULL) { unique->tree->size += n; unique->tree->index = unique->invperm[0]; ddPatchTree(unique,unique->tree); } unique->autoDyn = reorderSave; return(1); } /* end of cuddInsertSubtables */ /**Function******************************************************************** Synopsis [Destroys the n most recently created subtables in a unique table.] Description [Destroys the n most recently created subtables in a unique table. n should be positive. The subtables should not contain any live nodes, except the (isolated) projection function. The projection functions are freed. Returns 1 if successful; 0 otherwise.] SideEffects [The variable map used for fast variable substitution is destroyed if it exists. In this case the cache is also cleared.] SeeAlso [cuddInsertSubtables Cudd_SetVarMap] ******************************************************************************/ int cuddDestroySubtables( DdManager * unique, int n) { DdSubtable *subtables; DdNodePtr *nodelist; DdNodePtr *vars; int firstIndex, lastIndex; int index, level, newlevel; int lowestLevel; int shift; int found; /* Sanity check and set up. */ if (n <= 0) return(0); if (n > unique->size) n = unique->size; subtables = unique->subtables; vars = unique->vars; firstIndex = unique->size - n; lastIndex = unique->size; /* Check for nodes labeled by the variables being destroyed ** that may still be in use. It is allowed to destroy a variable ** only if there are no such nodes. Also, find the lowest level ** among the variables being destroyed. This will make further ** processing more efficient. */ lowestLevel = unique->size; for (index = firstIndex; index < lastIndex; index++) { level = unique->perm[index]; if (level < lowestLevel) lowestLevel = level; nodelist = subtables[level].nodelist; if (subtables[level].keys - subtables[level].dead != 1) return(0); /* The projection function should be isolated. If the ref count ** is 1, everything is OK. If the ref count is saturated, then ** we need to make sure that there are no nodes pointing to it. ** As for the external references, we assume the application is ** responsible for them. */ if (vars[index]->ref != 1) { if (vars[index]->ref != DD_MAXREF) return(0); found = cuddFindParent(unique,vars[index]); if (found) { return(0); } else { vars[index]->ref = 1; } } Cudd_RecursiveDeref(unique,vars[index]); } /* Collect garbage, because we cannot afford having dead nodes pointing ** to the dead nodes in the subtables being destroyed. */ (void) cuddGarbageCollect(unique,1); /* Here we know we can destroy our subtables. */ for (index = firstIndex; index < lastIndex; index++) { level = unique->perm[index]; nodelist = subtables[level].nodelist; #ifdef DD_DEBUG assert(subtables[level].keys == 0); #endif ABC_FREE(nodelist); unique->memused -= sizeof(DdNodePtr) * subtables[level].slots; unique->slots -= subtables[level].slots; unique->dead -= subtables[level].dead; } /* Here all subtables to be destroyed have their keys field == 0 and ** their hash tables have been freed. ** We now scan the subtables from level lowestLevel + 1 to level size - 1, ** shifting the subtables as required. We keep a running count of ** how many subtables have been moved, so that we know by how many ** positions each subtable should be shifted. */ shift = 1; for (level = lowestLevel + 1; level < unique->size; level++) { if (subtables[level].keys == 0) { shift++; continue; } newlevel = level - shift; subtables[newlevel].slots = subtables[level].slots; subtables[newlevel].shift = subtables[level].shift; subtables[newlevel].keys = subtables[level].keys; subtables[newlevel].maxKeys = subtables[level].maxKeys; subtables[newlevel].dead = subtables[level].dead; subtables[newlevel].nodelist = subtables[level].nodelist; index = unique->invperm[level]; unique->perm[index] = newlevel; unique->invperm[newlevel] = index; subtables[newlevel].bindVar = subtables[level].bindVar; subtables[newlevel].varType = subtables[level].varType; subtables[newlevel].pairIndex = subtables[level].pairIndex; subtables[newlevel].varHandled = subtables[level].varHandled; subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped; } /* Destroy the map. If a surviving variable is ** mapped to a dying variable, and the map were used again, ** an out-of-bounds access to unique->vars would result. */ if (unique->map != NULL) { cuddCacheFlush(unique); ABC_FREE(unique->map); unique->map = NULL; } unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); unique->size -= n; return(1); } /* end of cuddDestroySubtables */ /**Function******************************************************************** Synopsis [Increases the number of ZDD subtables in a unique table so that it meets or exceeds index.] Description [Increases the number of ZDD subtables in a unique table so that it meets or exceeds index. When new ZDD variables are created, it is possible to preserve the functions unchanged, or it is possible to preserve the covers unchanged, but not both. cuddResizeTableZdd preserves the covers. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [ddResizeTable] ******************************************************************************/ int cuddResizeTableZdd( DdManager * unique, int index) { DdSubtable *newsubtables; DdNodePtr *newnodelist; int oldsize,newsize; int i,j,reorderSave; unsigned int numSlots = unique->initSlots; int *newperm, *newinvperm; oldsize = unique->sizeZ; /* Easy case: there is still room in the current table. */ if (index < unique->maxSizeZ) { for (i = oldsize; i <= index; i++) { unique->subtableZ[i].slots = numSlots; unique->subtableZ[i].shift = sizeof(int) * 8 - cuddComputeFloorLog2(numSlots); unique->subtableZ[i].keys = 0; unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; unique->subtableZ[i].dead = 0; unique->permZ[i] = i; unique->invpermZ[i] = i; newnodelist = unique->subtableZ[i].nodelist = ABC_ALLOC(DdNodePtr, numSlots); if (newnodelist == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } for (j = 0; (unsigned) j < numSlots; j++) { newnodelist[j] = NULL; } } } else { /* The current table is too small: we need to allocate a new, ** larger one; move all old subtables, and initialize the new ** subtables up to index included. */ newsize = index + DD_DEFAULT_RESIZE; #ifdef DD_VERBOSE (void) fprintf(unique->err, "Increasing the ZDD table size from %d to %d\n", unique->maxSizeZ, newsize); #endif newsubtables = ABC_ALLOC(DdSubtable,newsize); if (newsubtables == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } newperm = ABC_ALLOC(int,newsize); if (newperm == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } newinvperm = ABC_ALLOC(int,newsize); if (newinvperm == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) * sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); if (newsize > unique->maxSize) { ABC_FREE(unique->stack); unique->stack = ABC_ALLOC(DdNodePtr,newsize + 1); if (unique->stack == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } unique->stack[0] = NULL; /* to suppress harmless UMR */ unique->memused += (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) * sizeof(DdNode *); } for (i = 0; i < oldsize; i++) { newsubtables[i].slots = unique->subtableZ[i].slots; newsubtables[i].shift = unique->subtableZ[i].shift; newsubtables[i].keys = unique->subtableZ[i].keys; newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys; newsubtables[i].dead = unique->subtableZ[i].dead; newsubtables[i].nodelist = unique->subtableZ[i].nodelist; newperm[i] = unique->permZ[i]; newinvperm[i] = unique->invpermZ[i]; } for (i = oldsize; i <= index; i++) { newsubtables[i].slots = numSlots; newsubtables[i].shift = sizeof(int) * 8 - cuddComputeFloorLog2(numSlots); newsubtables[i].keys = 0; newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; newsubtables[i].dead = 0; newperm[i] = i; newinvperm[i] = i; newnodelist = newsubtables[i].nodelist = ABC_ALLOC(DdNodePtr, numSlots); if (newnodelist == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } for (j = 0; (unsigned) j < numSlots; j++) { newnodelist[j] = NULL; } } ABC_FREE(unique->subtableZ); unique->subtableZ = newsubtables; unique->maxSizeZ = newsize; ABC_FREE(unique->permZ); unique->permZ = newperm; ABC_FREE(unique->invpermZ); unique->invpermZ = newinvperm; } unique->slots += (index + 1 - unique->sizeZ) * numSlots; ddFixLimits(unique); unique->sizeZ = index + 1; /* Now that the table is in a coherent state, update the ZDD ** universe. We need to temporarily disable reordering, ** because we cannot reorder without universe in place. */ reorderSave = unique->autoDynZ; unique->autoDynZ = 0; cuddZddFreeUniv(unique); if (!cuddZddInitUniv(unique)) { unique->autoDynZ = reorderSave; return(0); } unique->autoDynZ = reorderSave; return(1); } /* end of cuddResizeTableZdd */ /**Function******************************************************************** Synopsis [Adjusts parameters of a table to slow down its growth.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void cuddSlowTableGrowth( DdManager *unique) { int i; unique->maxCacheHard = unique->cacheSlots - 1; unique->cacheSlack = - (int) (unique->cacheSlots + 1); for (i = 0; i < unique->size; i++) { unique->subtables[i].maxKeys <<= 2; } unique->gcFrac = DD_GC_FRAC_MIN; unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); cuddShrinkDeathRow(unique); (void) fprintf(unique->err,"Slowing down table growth: "); (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac); (void) fprintf(unique->err,"minDead = %u\n", unique->minDead); } /* end of cuddSlowTableGrowth */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Rehashes a ZDD unique subtable.] Description [] SideEffects [None] SeeAlso [cuddRehash] ******************************************************************************/ static void ddRehashZdd( DdManager * unique, int i) { unsigned int slots, oldslots; int shift, oldshift; int j, pos; DdNodePtr *nodelist, *oldnodelist; DdNode *node, *next; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; if (unique->slots > unique->looseUpTo) { unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); #ifdef DD_VERBOSE if (unique->gcFrac == DD_GC_FRAC_HI) { (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO); (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); } #endif unique->gcFrac = DD_GC_FRAC_LO; } assert(i != CUDD_MAXINDEX); oldslots = unique->subtableZ[i].slots; oldshift = unique->subtableZ[i].shift; oldnodelist = unique->subtableZ[i].nodelist; /* Compute the new size of the subtable. Normally, we just ** double. However, after reordering, a table may be severely ** overloaded. Therefore, we iterate. */ slots = oldslots; shift = oldshift; do { slots <<= 1; shift--; } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys); saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; nodelist = ABC_ALLOC(DdNodePtr, slots); MMoutOfMemory = saveHandler; if (nodelist == NULL) { (void) fprintf(unique->err, "Unable to resize ZDD subtable %d for lack of memory.\n", i); (void) cuddGarbageCollect(unique,1); for (j = 0; j < unique->sizeZ; j++) { unique->subtableZ[j].maxKeys <<= 1; } return; } unique->subtableZ[i].nodelist = nodelist; unique->subtableZ[i].slots = slots; unique->subtableZ[i].shift = shift; unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; for (j = 0; (unsigned) j < slots; j++) { nodelist[j] = NULL; } for (j = 0; (unsigned) j < oldslots; j++) { node = oldnodelist[j]; while (node != NULL) { next = node->next; pos = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift); node->next = nodelist[pos]; nodelist[pos] = node; node = next; } } ABC_FREE(oldnodelist); #ifdef DD_VERBOSE (void) fprintf(unique->err, "rehashing layer %d: keys %d dead %d new size %d\n", i, unique->subtableZ[i].keys, unique->subtableZ[i].dead, slots); #endif /* Update global data. */ unique->memused += (slots - oldslots) * sizeof(DdNode *); unique->slots += (slots - oldslots); ddFixLimits(unique); } /* end of ddRehashZdd */ /**Function******************************************************************** Synopsis [Increases the number of subtables in a unique table so that it meets or exceeds index.] Description [Increases the number of subtables in a unique table so that it meets or exceeds index. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddResizeTableZdd] ******************************************************************************/ static int ddResizeTable( DdManager * unique, int index) { DdSubtable *newsubtables; DdNodePtr *newnodelist; DdNodePtr *newvars; DdNode *sentinel = &(unique->sentinel); int oldsize,newsize; int i,j,reorderSave; int numSlots = unique->initSlots; int *newperm, *newinvperm, *newmap = NULL; DdNode *one, *zero; oldsize = unique->size; /* Easy case: there is still room in the current table. */ if (index < unique->maxSize) { for (i = oldsize; i <= index; i++) { unique->subtables[i].slots = numSlots; unique->subtables[i].shift = sizeof(int) * 8 - cuddComputeFloorLog2(numSlots); unique->subtables[i].keys = 0; unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; unique->subtables[i].dead = 0; unique->subtables[i].bindVar = 0; unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; unique->subtables[i].pairIndex = 0; unique->subtables[i].varHandled = 0; unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; unique->perm[i] = i; unique->invperm[i] = i; newnodelist = unique->subtables[i].nodelist = ABC_ALLOC(DdNodePtr, numSlots); if (newnodelist == NULL) { for (j = oldsize; j < i; j++) { ABC_FREE(unique->subtables[j].nodelist); } unique->errorCode = CUDD_MEMORY_OUT; return(0); } for (j = 0; j < numSlots; j++) { newnodelist[j] = sentinel; } } if (unique->map != NULL) { for (i = oldsize; i <= index; i++) { unique->map[i] = i; } } } else { /* The current table is too small: we need to allocate a new, ** larger one; move all old subtables, and initialize the new ** subtables up to index included. */ newsize = index + DD_DEFAULT_RESIZE; #ifdef DD_VERBOSE (void) fprintf(unique->err, "Increasing the table size from %d to %d\n", unique->maxSize, newsize); #endif newsubtables = ABC_ALLOC(DdSubtable,newsize); if (newsubtables == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } newvars = ABC_ALLOC(DdNodePtr,newsize); if (newvars == NULL) { ABC_FREE(newsubtables); unique->errorCode = CUDD_MEMORY_OUT; return(0); } newperm = ABC_ALLOC(int,newsize); if (newperm == NULL) { ABC_FREE(newsubtables); ABC_FREE(newvars); unique->errorCode = CUDD_MEMORY_OUT; return(0); } newinvperm = ABC_ALLOC(int,newsize); if (newinvperm == NULL) { ABC_FREE(newsubtables); ABC_FREE(newvars); ABC_FREE(newperm); unique->errorCode = CUDD_MEMORY_OUT; return(0); } if (unique->map != NULL) { newmap = ABC_ALLOC(int,newsize); if (newmap == NULL) { ABC_FREE(newsubtables); ABC_FREE(newvars); ABC_FREE(newperm); ABC_FREE(newinvperm); unique->errorCode = CUDD_MEMORY_OUT; return(0); } unique->memused += (newsize - unique->maxSize) * sizeof(int); } unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); if (newsize > unique->maxSizeZ) { ABC_FREE(unique->stack); unique->stack = ABC_ALLOC(DdNodePtr,newsize + 1); if (unique->stack == NULL) { ABC_FREE(newsubtables); ABC_FREE(newvars); ABC_FREE(newperm); ABC_FREE(newinvperm); if (unique->map != NULL) { ABC_FREE(newmap); } unique->errorCode = CUDD_MEMORY_OUT; return(0); } unique->stack[0] = NULL; /* to suppress harmless UMR */ unique->memused += (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) * sizeof(DdNode *); } for (i = 0; i < oldsize; i++) { newsubtables[i].slots = unique->subtables[i].slots; newsubtables[i].shift = unique->subtables[i].shift; newsubtables[i].keys = unique->subtables[i].keys; newsubtables[i].maxKeys = unique->subtables[i].maxKeys; newsubtables[i].dead = unique->subtables[i].dead; newsubtables[i].nodelist = unique->subtables[i].nodelist; newsubtables[i].bindVar = unique->subtables[i].bindVar; newsubtables[i].varType = unique->subtables[i].varType; newsubtables[i].pairIndex = unique->subtables[i].pairIndex; newsubtables[i].varHandled = unique->subtables[i].varHandled; newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; newvars[i] = unique->vars[i]; newperm[i] = unique->perm[i]; newinvperm[i] = unique->invperm[i]; } for (i = oldsize; i <= index; i++) { newsubtables[i].slots = numSlots; newsubtables[i].shift = sizeof(int) * 8 - cuddComputeFloorLog2(numSlots); newsubtables[i].keys = 0; newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; newsubtables[i].dead = 0; newsubtables[i].bindVar = 0; newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; newsubtables[i].pairIndex = 0; newsubtables[i].varHandled = 0; newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; newperm[i] = i; newinvperm[i] = i; newnodelist = newsubtables[i].nodelist = ABC_ALLOC(DdNodePtr, numSlots); if (newnodelist == NULL) { unique->errorCode = CUDD_MEMORY_OUT; return(0); } for (j = 0; j < numSlots; j++) { newnodelist[j] = sentinel; } } if (unique->map != NULL) { for (i = 0; i < oldsize; i++) { newmap[i] = unique->map[i]; } for (i = oldsize; i <= index; i++) { newmap[i] = i; } ABC_FREE(unique->map); unique->map = newmap; } ABC_FREE(unique->subtables); unique->subtables = newsubtables; unique->maxSize = newsize; ABC_FREE(unique->vars); unique->vars = newvars; ABC_FREE(unique->perm); unique->perm = newperm; ABC_FREE(unique->invperm); unique->invperm = newinvperm; } /* Now that the table is in a coherent state, create the new ** projection functions. We need to temporarily disable reordering, ** because we cannot reorder without projection functions in place. **/ one = unique->one; zero = Cudd_Not(one); unique->size = index + 1; unique->slots += (index + 1 - oldsize) * numSlots; ddFixLimits(unique); reorderSave = unique->autoDyn; unique->autoDyn = 0; for (i = oldsize; i <= index; i++) { unique->vars[i] = cuddUniqueInter(unique,i,one,zero); if (unique->vars[i] == NULL) { unique->autoDyn = reorderSave; for (j = oldsize; j < i; j++) { Cudd_IterDerefBdd(unique,unique->vars[j]); cuddDeallocNode(unique,unique->vars[j]); unique->vars[j] = NULL; } for (j = oldsize; j <= index; j++) { ABC_FREE(unique->subtables[j].nodelist); unique->subtables[j].nodelist = NULL; } unique->size = oldsize; unique->slots -= (index + 1 - oldsize) * numSlots; ddFixLimits(unique); return(0); } cuddRef(unique->vars[i]); } unique->autoDyn = reorderSave; return(1); } /* end of ddResizeTable */ /**Function******************************************************************** Synopsis [Searches the subtables above node for a parent.] Description [Searches the subtables above node for a parent. Returns 1 as soon as one parent is found. Returns 0 is the search is fruitless.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddFindParent( DdManager * table, DdNode * node) { int i,j; int slots; DdNodePtr *nodelist; DdNode *f; for (i = cuddI(table,node->index) - 1; i >= 0; i--) { nodelist = table->subtables[i].nodelist; slots = table->subtables[i].slots; for (j = 0; j < slots; j++) { f = nodelist[j]; while (cuddT(f) > node) { f = f->next; } while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) { f = f->next; } if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) { return(1); } } } return(0); } /* end of cuddFindParent */ /**Function******************************************************************** Synopsis [Adjusts the values of table limits.] Description [Adjusts the values of table fields controlling the. sizes of subtables and computed table. If the computed table is too small according to the new values, it is resized.] SideEffects [Modifies manager fields. May resize computed table.] SeeAlso [] ******************************************************************************/ DD_INLINE static void ddFixLimits( DdManager *unique) { unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); unique->cacheSlack = (int) ddMin(unique->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - 2 * (int) unique->cacheSlots; if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0) cuddCacheResize(unique); return; } /* end of ddFixLimits */ #ifndef DD_UNSORTED_FREE_LIST #ifdef DD_RED_BLACK_FREE_LIST /**Function******************************************************************** Synopsis [Inserts a DdNode in a red/black search tree.] Description [Inserts a DdNode in a red/black search tree. Nodes from the same "page" (defined by DD_PAGE_MASK) are linked in a LIFO list.] SideEffects [None] SeeAlso [cuddOrderedThread] ******************************************************************************/ static void cuddOrderedInsert( DdNodePtr * root, DdNodePtr node) { DdNode *scan; DdNodePtr *scanP; DdNodePtr *stack[DD_STACK_SIZE]; int stackN = 0; scanP = root; while ((scan = *scanP) != NULL) { stack[stackN++] = scanP; if (DD_INSERT_COMPARE(node, scan) == 0) { /* add to page list */ DD_NEXT(node) = DD_NEXT(scan); DD_NEXT(scan) = node; return; } scanP = (node < scan) ? &DD_LEFT(scan) : &DD_RIGHT(scan); } DD_RIGHT(node) = DD_LEFT(node) = DD_NEXT(node) = NULL; DD_COLOR(node) = DD_RED; *scanP = node; stack[stackN] = &node; cuddDoRebalance(stack,stackN); } /* end of cuddOrderedInsert */ /**Function******************************************************************** Synopsis [Threads all the nodes of a search tree into a linear list.] Description [Threads all the nodes of a search tree into a linear list. For each node of the search tree, the "left" child, if non-null, has a lower address than its parent, and the "right" child, if non-null, has a higher address than its parent. The list is sorted in order of increasing addresses. The search tree is destroyed as a result of this operation. The last element of the linear list is made to point to the address passed in list. Each node if the search tree is a linearly-linked list of nodes from the same memory page (as defined in DD_PAGE_MASK). When a node is added to the linear list, all the elements of the linked list are added.] SideEffects [The search tree is destroyed as a result of this operation.] SeeAlso [cuddOrderedInsert] ******************************************************************************/ static DdNode * cuddOrderedThread( DdNode * root, DdNode * list) { DdNode *current, *next, *prev, *end; current = root; /* The first word in the node is used to implement a stack that holds ** the nodes from the root of the tree to the current node. Here we ** put the root of the tree at the bottom of the stack. */ *((DdNodePtr *) current) = NULL; while (current != NULL) { if (DD_RIGHT(current) != NULL) { /* If possible, we follow the "right" link. Eventually we'll ** find the node with the largest address in the current tree. ** In this phase we use the first word of a node to implemen ** a stack of the nodes on the path from the root to "current". ** Also, we disconnect the "right" pointers to indicate that ** we have already followed them. */ next = DD_RIGHT(current); DD_RIGHT(current) = NULL; *((DdNodePtr *)next) = current; current = next; } else { /* We can't proceed along the "right" links any further. ** Hence "current" is the largest element in the current tree. ** We make this node the new head of "list". (Repeating this ** operation until the tree is empty yields the desired linear ** threading of all nodes.) */ prev = *((DdNodePtr *) current); /* save prev node on stack in prev */ /* Traverse the linked list of current until the end. */ for (end = current; DD_NEXT(end) != NULL; end = DD_NEXT(end)); DD_NEXT(end) = list; /* attach "list" at end and make */ list = current; /* "current" the new head of "list" */ /* Now, if current has a "left" child, we push it on the stack. ** Otherwise, we just continue with the parent of "current". */ if (DD_LEFT(current) != NULL) { next = DD_LEFT(current); *((DdNodePtr *) next) = prev; current = next; } else { current = prev; } } } return(list); } /* end of cuddOrderedThread */ /**Function******************************************************************** Synopsis [Performs the left rotation for red/black trees.] Description [] SideEffects [None] SeeAlso [cuddRotateRight] ******************************************************************************/ DD_INLINE static void cuddRotateLeft( DdNodePtr * nodeP) { DdNode *newRoot; DdNode *oldRoot = *nodeP; *nodeP = newRoot = DD_RIGHT(oldRoot); DD_RIGHT(oldRoot) = DD_LEFT(newRoot); DD_LEFT(newRoot) = oldRoot; } /* end of cuddRotateLeft */ /**Function******************************************************************** Synopsis [Performs the right rotation for red/black trees.] Description [] SideEffects [None] SeeAlso [cuddRotateLeft] ******************************************************************************/ DD_INLINE static void cuddRotateRight( DdNodePtr * nodeP) { DdNode *newRoot; DdNode *oldRoot = *nodeP; *nodeP = newRoot = DD_LEFT(oldRoot); DD_LEFT(oldRoot) = DD_RIGHT(newRoot); DD_RIGHT(newRoot) = oldRoot; } /* end of cuddRotateRight */ /**Function******************************************************************** Synopsis [Rebalances a red/black tree.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void cuddDoRebalance( DdNodePtr ** stack, int stackN) { DdNodePtr *xP, *parentP, *grandpaP; DdNode *x, *y, *parent, *grandpa; xP = stack[stackN]; x = *xP; /* Work our way back up, re-balancing the tree. */ while (--stackN >= 0) { parentP = stack[stackN]; parent = *parentP; if (DD_IS_BLACK(parent)) break; /* Since the root is black, here a non-null grandparent exists. */ grandpaP = stack[stackN-1]; grandpa = *grandpaP; if (parent == DD_LEFT(grandpa)) { y = DD_RIGHT(grandpa); if (y != NULL && DD_IS_RED(y)) { DD_COLOR(parent) = DD_BLACK; DD_COLOR(y) = DD_BLACK; DD_COLOR(grandpa) = DD_RED; x = grandpa; stackN--; } else { if (x == DD_RIGHT(parent)) { cuddRotateLeft(parentP); DD_COLOR(x) = DD_BLACK; } else { DD_COLOR(parent) = DD_BLACK; } DD_COLOR(grandpa) = DD_RED; cuddRotateRight(grandpaP); break; } } else { y = DD_LEFT(grandpa); if (y != NULL && DD_IS_RED(y)) { DD_COLOR(parent) = DD_BLACK; DD_COLOR(y) = DD_BLACK; DD_COLOR(grandpa) = DD_RED; x = grandpa; stackN--; } else { if (x == DD_LEFT(parent)) { cuddRotateRight(parentP); DD_COLOR(x) = DD_BLACK; } else { DD_COLOR(parent) = DD_BLACK; } DD_COLOR(grandpa) = DD_RED; cuddRotateLeft(grandpaP); } } } DD_COLOR(*(stack[0])) = DD_BLACK; } /* end of cuddDoRebalance */ #endif #endif /**Function******************************************************************** Synopsis [Fixes a variable tree after the insertion of new subtables.] Description [Fixes a variable tree after the insertion of new subtables. After such an insertion, the low fields of the tree below the insertion point are inconsistent.] SideEffects [None] SeeAlso [] ******************************************************************************/ static void ddPatchTree( DdManager *dd, MtrNode *treenode) { MtrNode *auxnode = treenode; while (auxnode != NULL) { auxnode->low = dd->perm[auxnode->index]; if (auxnode->child != NULL) { ddPatchTree(dd, auxnode->child); } auxnode = auxnode->younger; } return; } /* end of ddPatchTree */ #ifdef DD_DEBUG /**Function******************************************************************** Synopsis [Checks whether a collision list is ordered.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddCheckCollisionOrdering( DdManager *unique, int i, int j) { int slots; DdNode *node, *next; DdNodePtr *nodelist; DdNode *sentinel = &(unique->sentinel); nodelist = unique->subtables[i].nodelist; slots = unique->subtables[i].slots; node = nodelist[j]; if (node == sentinel) return(1); next = node->next; while (next != sentinel) { if (cuddT(node) < cuddT(next) || (cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) { (void) fprintf(unique->err, "Unordered list: index %u, position %d\n", i, j); return(0); } node = next; next = node->next; } return(1); } /* end of cuddCheckCollisionOrdering */ #endif /**Function******************************************************************** Synopsis [Reports problem in garbage collection.] Description [] SideEffects [None] SeeAlso [cuddGarbageCollect cuddGarbageCollectZdd] ******************************************************************************/ static void ddReportRefMess( DdManager *unique /* manager */, int i /* table in which the problem occurred */, const char *caller /* procedure that detected the problem */) { if (i == CUDD_CONST_INDEX) { (void) fprintf(unique->err, "%s: problem in constants\n", caller); } else if (i != -1) { (void) fprintf(unique->err, "%s: problem in table %d\n", caller, i); } (void) fprintf(unique->err, " dead count != deleted\n"); (void) fprintf(unique->err, " This problem is often due to a missing \ call to Cudd_Ref\n or to an extra call to Cudd_RecursiveDeref.\n \ See the CUDD Programmer's Guide for additional details."); abort(); } /* end of ddReportRefMess */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddUtil.c000066400000000000000000003423231300674244400234340ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddUtil.c] PackageName [cudd] Synopsis [Utility functions.] Description [External procedures included in this module:
        • Cudd_PrintMinterm()
        • Cudd_bddPrintCover()
        • Cudd_PrintDebug()
        • Cudd_DagSize()
        • Cudd_EstimateCofactor()
        • Cudd_EstimateCofactorSimple()
        • Cudd_SharingSize()
        • Cudd_CountMinterm()
        • Cudd_EpdCountMinterm()
        • Cudd_CountPath()
        • Cudd_CountPathsToNonZero()
        • Cudd_Support()
        • Cudd_SupportIndex()
        • Cudd_SupportSize()
        • Cudd_VectorSupport()
        • Cudd_VectorSupportIndex()
        • Cudd_VectorSupportSize()
        • Cudd_ClassifySupport()
        • Cudd_CountLeaves()
        • Cudd_bddPickOneCube()
        • Cudd_bddPickOneMinterm()
        • Cudd_bddPickArbitraryMinterms()
        • Cudd_SubsetWithMaskVars()
        • Cudd_FirstCube()
        • Cudd_NextCube()
        • Cudd_bddComputeCube()
        • Cudd_addComputeCube()
        • Cudd_FirstNode()
        • Cudd_NextNode()
        • Cudd_GenFree()
        • Cudd_IsGenEmpty()
        • Cudd_IndicesToCube()
        • Cudd_PrintVersion()
        • Cudd_AverageDistance()
        • Cudd_Random()
        • Cudd_Srandom()
        • Cudd_Density()
        Internal procedures included in this module:
        • cuddP()
        • cuddStCountfree()
        • cuddCollectNodes()
        • cuddNodeArray()
        Static procedures included in this module:
        • dp2()
        • ddPrintMintermAux()
        • ddDagInt()
        • ddCountMintermAux()
        • ddEpdCountMintermAux()
        • ddCountPathAux()
        • ddSupportStep()
        • ddClearFlag()
        • ddLeavesInt()
        • ddPickArbitraryMinterms()
        • ddPickRepresentativeCube()
        • ddEpdFree()
        ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /* Random generator constants. */ #define MODULUS1 2147483563 #define LEQA1 40014 #define LEQQ1 53668 #define LEQR1 12211 #define MODULUS2 2147483399 #define LEQA2 40692 #define LEQQ2 52774 #define LEQR2 3791 #define STAB_SIZE 64 #define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE) /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.81 2009/03/08 02:49:02 fabio Exp $"; #endif static DdNode *background, *zero; static long cuddRand = 0; static long cuddRand2; static long shuffleSelect; static long shuffleTable[STAB_SIZE]; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ #define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ') /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int dp2 (DdManager *dd, DdNode *f, st__table *t); static void ddPrintMintermAux (DdManager *dd, DdNode *node, int *list); static int ddDagInt (DdNode *n); static int cuddNodeArrayRecur (DdNode *f, DdNodePtr *table, int index); static int cuddEstimateCofactor (DdManager *dd, st__table *table, DdNode * node, int i, int phase, DdNode ** ptr); static DdNode * cuddUniqueLookup (DdManager * unique, int index, DdNode * T, DdNode * E); static int cuddEstimateCofactorSimple (DdNode * node, int i); static double ddCountMintermAux (DdNode *node, double max, DdHashTable *table); static int ddEpdCountMintermAux (DdNode *node, EpDouble *max, EpDouble *epd, st__table *table); static double ddCountPathAux (DdNode *node, st__table *table); static double ddCountPathsToNonZero (DdNode * N, st__table * table); static void ddSupportStep (DdNode *f, int *support); static void ddClearFlag (DdNode *f); static int ddLeavesInt (DdNode *n); static int ddPickArbitraryMinterms (DdManager *dd, DdNode *node, int nvars, int nminterms, char **string); static int ddPickRepresentativeCube (DdManager *dd, DdNode *node, double *weight, char *string); static enum st__retval ddEpdFree (char * key, char * value, char * arg); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints a disjoint sum of products.] Description [Prints a disjoint sum of product cover for the function rooted at node. Each product corresponds to a path from node to a leaf node different from the logical zero, and different from the background value. Uses the package default output file. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_PrintDebug Cudd_bddPrintCover] ******************************************************************************/ int Cudd_PrintMinterm( DdManager * manager, DdNode * node) { int i, *list; background = manager->background; zero = Cudd_Not(manager->one); list = ABC_ALLOC(int,manager->size); if (list == NULL) { manager->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < manager->size; i++) list[i] = 2; ddPrintMintermAux(manager,node,list); ABC_FREE(list); return(1); } /* end of Cudd_PrintMinterm */ /**Function******************************************************************** Synopsis [Prints a sum of prime implicants of a BDD.] Description [Prints a sum of product cover for an incompletely specified function given by a lower bound and an upper bound. Each product is a prime implicant obtained by expanding the product corresponding to a path from node to the constant one. Uses the package default output file. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_PrintMinterm] ******************************************************************************/ int Cudd_bddPrintCover( DdManager *dd, DdNode *l, DdNode *u) { int *array; int q, result; DdNode *lb; #ifdef DD_DEBUG DdNode *cover; #endif array = ABC_ALLOC(int, Cudd_ReadSize(dd)); if (array == NULL) return(0); lb = l; cuddRef(lb); #ifdef DD_DEBUG cover = Cudd_ReadLogicZero(dd); cuddRef(cover); #endif while (lb != Cudd_ReadLogicZero(dd)) { DdNode *implicant, *prime, *tmp; int length; implicant = Cudd_LargestCube(dd,lb,&length); if (implicant == NULL) { Cudd_RecursiveDeref(dd,lb); ABC_FREE(array); return(0); } cuddRef(implicant); prime = Cudd_bddMakePrime(dd,implicant,u); if (prime == NULL) { Cudd_RecursiveDeref(dd,lb); Cudd_RecursiveDeref(dd,implicant); ABC_FREE(array); return(0); } cuddRef(prime); Cudd_RecursiveDeref(dd,implicant); tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime)); if (tmp == NULL) { Cudd_RecursiveDeref(dd,lb); Cudd_RecursiveDeref(dd,prime); ABC_FREE(array); return(0); } cuddRef(tmp); Cudd_RecursiveDeref(dd,lb); lb = tmp; result = Cudd_BddToCubeArray(dd,prime,array); if (result == 0) { Cudd_RecursiveDeref(dd,lb); Cudd_RecursiveDeref(dd,prime); ABC_FREE(array); return(0); } for (q = 0; q < dd->size; q++) { switch (array[q]) { case 0: (void) fprintf(dd->out, "0"); break; case 1: (void) fprintf(dd->out, "1"); break; case 2: (void) fprintf(dd->out, "-"); break; default: (void) fprintf(dd->out, "?"); } } (void) fprintf(dd->out, " 1\n"); #ifdef DD_DEBUG tmp = Cudd_bddOr(dd,prime,cover); if (tmp == NULL) { Cudd_RecursiveDeref(dd,cover); Cudd_RecursiveDeref(dd,lb); Cudd_RecursiveDeref(dd,prime); ABC_FREE(array); return(0); } cuddRef(tmp); Cudd_RecursiveDeref(dd,cover); cover = tmp; #endif Cudd_RecursiveDeref(dd,prime); } (void) fprintf(dd->out, "\n"); Cudd_RecursiveDeref(dd,lb); ABC_FREE(array); #ifdef DD_DEBUG if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) { Cudd_RecursiveDeref(dd,cover); return(0); } Cudd_RecursiveDeref(dd,cover); #endif return(1); } /* end of Cudd_bddPrintCover */ /**Function******************************************************************** Synopsis [Prints to the standard output a DD and its statistics.] Description [Prints to the standard output a DD and its statistics. The statistics include the number of nodes, the number of leaves, and the number of minterms. (The number of minterms is the number of assignments to the variables that cause the function to be different from the logical zero (for BDDs) and from the background value (for ADDs.) The statistics are printed if pr > 0. Specifically:
        • pr = 0 : prints nothing
        • pr = 1 : prints counts of nodes and minterms
        • pr = 2 : prints counts + disjoint sum of product
        • pr = 3 : prints counts + list of nodes
        • pr > 3 : prints counts + disjoint sum of product + list of nodes
        For the purpose of counting the number of minterms, the function is supposed to depend on n variables. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm Cudd_PrintMinterm] ******************************************************************************/ int Cudd_PrintDebug( DdManager * dd, DdNode * f, int n, int pr) { DdNode *azero, *bzero; int nodes; int leaves; double minterms; int retval = 1; if (f == NULL) { (void) fprintf(dd->out,": is the NULL DD\n"); (void) fflush(dd->out); return(0); } azero = DD_ZERO(dd); bzero = Cudd_Not(DD_ONE(dd)); if ((f == azero || f == bzero) && pr > 0){ (void) fprintf(dd->out,": is the zero DD\n"); (void) fflush(dd->out); return(1); } if (pr > 0) { nodes = Cudd_DagSize(f); if (nodes == CUDD_OUT_OF_MEM) retval = 0; leaves = Cudd_CountLeaves(f); if (leaves == CUDD_OUT_OF_MEM) retval = 0; minterms = Cudd_CountMinterm(dd, f, n); if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0; (void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n", nodes, leaves, minterms); if (pr > 2) { if (!cuddP(dd, f)) retval = 0; } if (pr == 2 || pr > 3) { if (!Cudd_PrintMinterm(dd,f)) retval = 0; (void) fprintf(dd->out,"\n"); } (void) fflush(dd->out); } return(retval); } /* end of Cudd_PrintDebug */ /**Function******************************************************************** Synopsis [Counts the number of nodes in a DD.] Description [Counts the number of nodes in a DD. Returns the number of nodes in the graph rooted at node.] SideEffects [None] SeeAlso [Cudd_SharingSize Cudd_PrintDebug] ******************************************************************************/ int Cudd_DagSize( DdNode * node) { int i; i = ddDagInt(Cudd_Regular(node)); ddClearFlag(Cudd_Regular(node)); return(i); } /* end of Cudd_DagSize */ /**Function******************************************************************** Synopsis [Estimates the number of nodes in a cofactor of a DD.] Description [Estimates the number of nodes in a cofactor of a DD. Returns an estimate of the number of nodes in a cofactor of the graph rooted at node with respect to the variable whose index is i. In case of failure, returns CUDD_OUT_OF_MEM. This function uses a refinement of the algorithm of Cabodi et al. (ICCAD96). The refinement allows the procedure to account for part of the recombination that may occur in the part of the cofactor above the cofactoring variable. This procedure does no create any new node. It does keep a small table of results; therefore it may run out of memory. If this is a concern, one should use Cudd_EstimateCofactorSimple, which is faster, does not allocate any memory, but is less accurate.] SideEffects [None] SeeAlso [Cudd_DagSize Cudd_EstimateCofactorSimple] ******************************************************************************/ int Cudd_EstimateCofactor( DdManager *dd /* manager */, DdNode * f /* function */, int i /* index of variable */, int phase /* 1: positive; 0: negative */ ) { int val; DdNode *ptr; st__table *table; table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) return(CUDD_OUT_OF_MEM); val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr); ddClearFlag(Cudd_Regular(f)); st__free_table(table); return(val); } /* end of Cudd_EstimateCofactor */ /**Function******************************************************************** Synopsis [Estimates the number of nodes in a cofactor of a DD.] Description [Estimates the number of nodes in a cofactor of a DD. Returns an estimate of the number of nodes in the positive cofactor of the graph rooted at node with respect to the variable whose index is i. This procedure implements with minor changes the algorithm of Cabodi et al. (ICCAD96). It does not allocate any memory, it does not change the state of the manager, and it is fast. However, it has been observed to overestimate the size of the cofactor by as much as a factor of 2.] SideEffects [None] SeeAlso [Cudd_DagSize] ******************************************************************************/ int Cudd_EstimateCofactorSimple( DdNode * node, int i) { int val; val = cuddEstimateCofactorSimple(Cudd_Regular(node),i); ddClearFlag(Cudd_Regular(node)); return(val); } /* end of Cudd_EstimateCofactorSimple */ /**Function******************************************************************** Synopsis [Counts the number of nodes in an array of DDs.] Description [Counts the number of nodes in an array of DDs. Shared nodes are counted only once. Returns the total number of nodes.] SideEffects [None] SeeAlso [Cudd_DagSize] ******************************************************************************/ int Cudd_SharingSize( DdNode ** nodeArray, int n) { int i,j; i = 0; for (j = 0; j < n; j++) { i += ddDagInt(Cudd_Regular(nodeArray[j])); } for (j = 0; j < n; j++) { ddClearFlag(Cudd_Regular(nodeArray[j])); } return(i); } /* end of Cudd_SharingSize */ /**Function******************************************************************** Synopsis [Counts the number of minterms of a DD.] Description [Counts the number of minterms of a DD. The function is assumed to depend on nvars variables. The minterm count is represented as a double, to allow for a larger number of variables. Returns the number of minterms of the function rooted at node if successful; (double) CUDD_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [Cudd_PrintDebug Cudd_CountPath] ******************************************************************************/ double Cudd_CountMinterm( DdManager * manager, DdNode * node, int nvars) { double max; DdHashTable *table; double res; CUDD_VALUE_TYPE epsilon; background = manager->background; zero = Cudd_Not(manager->one); max = pow(2.0,(double)nvars); table = cuddHashTableInit(manager,1,2); if (table == NULL) { return((double)CUDD_OUT_OF_MEM); } epsilon = Cudd_ReadEpsilon(manager); Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0); res = ddCountMintermAux(node,max,table); cuddHashTableQuit(table); Cudd_SetEpsilon(manager,epsilon); return(res); } /* end of Cudd_CountMinterm */ /**Function******************************************************************** Synopsis [Counts the number of paths of a DD.] Description [Counts the number of paths of a DD. Paths to all terminal nodes are counted. The path count is represented as a double, to allow for a larger number of variables. Returns the number of paths of the function rooted at node if successful; (double) CUDD_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [Cudd_CountMinterm] ******************************************************************************/ double Cudd_CountPath( DdNode * node) { st__table *table; double i; table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) { return((double)CUDD_OUT_OF_MEM); } i = ddCountPathAux(Cudd_Regular(node),table); st__foreach(table, cuddStCountfree, NULL); st__free_table(table); return(i); } /* end of Cudd_CountPath */ /**Function******************************************************************** Synopsis [Counts the number of minterms of a DD with extended precision.] Description [Counts the number of minterms of a DD with extended precision. The function is assumed to depend on nvars variables. The minterm count is represented as an EpDouble, to allow any number of variables. Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [Cudd_PrintDebug Cudd_CountPath] ******************************************************************************/ int Cudd_EpdCountMinterm( DdManager * manager, DdNode * node, int nvars, EpDouble * epd) { EpDouble max, tmp; st__table *table; int status; background = manager->background; zero = Cudd_Not(manager->one); EpdPow2(nvars, &max); table = st__init_table(EpdCmp, st__ptrhash); if (table == NULL) { EpdMakeZero(epd, 0); return(CUDD_OUT_OF_MEM); } status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table); st__foreach(table, ddEpdFree, NULL); st__free_table(table); if (status == CUDD_OUT_OF_MEM) { EpdMakeZero(epd, 0); return(CUDD_OUT_OF_MEM); } if (Cudd_IsComplement(node)) { EpdSubtract3(&max, epd, &tmp); EpdCopy(&tmp, epd); } return(0); } /* end of Cudd_EpdCountMinterm */ /**Function******************************************************************** Synopsis [Counts the number of paths to a non-zero terminal of a DD.] Description [Counts the number of paths to a non-zero terminal of a DD. The path count is represented as a double, to allow for a larger number of variables. Returns the number of paths of the function rooted at node.] SideEffects [None] SeeAlso [Cudd_CountMinterm Cudd_CountPath] ******************************************************************************/ double Cudd_CountPathsToNonZero( DdNode * node) { st__table *table; double i; table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) { return((double)CUDD_OUT_OF_MEM); } i = ddCountPathsToNonZero(node,table); st__foreach(table, cuddStCountfree, NULL); st__free_table(table); return(i); } /* end of Cudd_CountPathsToNonZero */ /**Function******************************************************************** Synopsis [Finds the variables on which a DD depends.] Description [Finds the variables on which a DD depends. Returns a BDD consisting of the product of the variables if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_VectorSupport Cudd_ClassifySupport] ******************************************************************************/ DdNode * Cudd_Support( DdManager * dd /* manager */, DdNode * f /* DD whose support is sought */) { int *support; DdNode *res, *tmp, *var; int i,j; int size; /* Allocate and initialize support array for ddSupportStep. */ size = ddMax(dd->size, dd->sizeZ); support = ABC_ALLOC(int,size); if (support == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < size; i++) { support[i] = 0; } /* Compute support and clean up markers. */ ddSupportStep(Cudd_Regular(f),support); ddClearFlag(Cudd_Regular(f)); /* Transform support from array to cube. */ do { dd->reordered = 0; res = DD_ONE(dd); cuddRef(res); for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ i = (j >= dd->size) ? j : dd->invperm[j]; if (support[i] == 1) { /* The following call to cuddUniqueInter is guaranteed ** not to trigger reordering because the node we look up ** already exists. */ var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); cuddRef(var); tmp = cuddBddAndRecur(dd,res,var); if (tmp == NULL) { Cudd_RecursiveDeref(dd,res); Cudd_RecursiveDeref(dd,var); res = NULL; break; } cuddRef(tmp); Cudd_RecursiveDeref(dd,res); Cudd_RecursiveDeref(dd,var); res = tmp; } } } while (dd->reordered == 1); ABC_FREE(support); if (res != NULL) cuddDeref(res); return(res); } /* end of Cudd_Support */ /**Function******************************************************************** Synopsis [Finds the variables on which a DD depends.] Description [Finds the variables on which a DD depends. Returns an index array of the variables if successful; NULL otherwise. The size of the array equals the number of variables in the manager. Each entry of the array is 1 if the corresponding variable is in the support of the DD and 0 otherwise.] SideEffects [None] SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] ******************************************************************************/ int * Cudd_SupportIndex( DdManager * dd /* manager */, DdNode * f /* DD whose support is sought */) { int *support; int i; int size; /* Allocate and initialize support array for ddSupportStep. */ size = ddMax(dd->size, dd->sizeZ); support = ABC_ALLOC(int,size); if (support == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < size; i++) { support[i] = 0; } /* Compute support and clean up markers. */ ddSupportStep(Cudd_Regular(f),support); ddClearFlag(Cudd_Regular(f)); return(support); } /* end of Cudd_SupportIndex */ /**Function******************************************************************** Synopsis [Counts the variables on which a DD depends.] Description [Counts the variables on which a DD depends. Returns the number of the variables if successful; CUDD_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [Cudd_Support] ******************************************************************************/ int Cudd_SupportSize( DdManager * dd /* manager */, DdNode * f /* DD whose support size is sought */) { int *support; int i; int size; int count; /* Allocate and initialize support array for ddSupportStep. */ size = ddMax(dd->size, dd->sizeZ); support = ABC_ALLOC(int,size); if (support == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(CUDD_OUT_OF_MEM); } for (i = 0; i < size; i++) { support[i] = 0; } /* Compute support and clean up markers. */ ddSupportStep(Cudd_Regular(f),support); ddClearFlag(Cudd_Regular(f)); /* Count support variables. */ count = 0; for (i = 0; i < size; i++) { if (support[i] == 1) count++; } ABC_FREE(support); return(count); } /* end of Cudd_SupportSize */ /**Function******************************************************************** Synopsis [Finds the variables on which a set of DDs depends.] Description [Finds the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns a BDD consisting of the product of the variables if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_Support Cudd_ClassifySupport] ******************************************************************************/ DdNode * Cudd_VectorSupport( DdManager * dd /* manager */, DdNode ** F /* array of DDs whose support is sought */, int n /* size of the array */) { int *support; DdNode *res, *tmp, *var; int i,j; int size; /* Allocate and initialize support array for ddSupportStep. */ size = ddMax(dd->size, dd->sizeZ); support = ABC_ALLOC(int,size); if (support == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < size; i++) { support[i] = 0; } /* Compute support and clean up markers. */ for (i = 0; i < n; i++) { ddSupportStep(Cudd_Regular(F[i]),support); } for (i = 0; i < n; i++) { ddClearFlag(Cudd_Regular(F[i])); } /* Transform support from array to cube. */ res = DD_ONE(dd); cuddRef(res); for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ i = (j >= dd->size) ? j : dd->invperm[j]; if (support[i] == 1) { var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); cuddRef(var); tmp = Cudd_bddAnd(dd,res,var); if (tmp == NULL) { Cudd_RecursiveDeref(dd,res); Cudd_RecursiveDeref(dd,var); ABC_FREE(support); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(dd,res); Cudd_RecursiveDeref(dd,var); res = tmp; } } ABC_FREE(support); cuddDeref(res); return(res); } /* end of Cudd_VectorSupport */ /**Function******************************************************************** Synopsis [Finds the variables on which a set of DDs depends.] Description [Finds the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns an index array of the variables if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport] ******************************************************************************/ int * Cudd_VectorSupportIndex( DdManager * dd /* manager */, DdNode ** F /* array of DDs whose support is sought */, int n /* size of the array */) { int *support; int i; int size; /* Allocate and initialize support array for ddSupportStep. */ size = ddMax(dd->size, dd->sizeZ); support = ABC_ALLOC(int,size); if (support == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < size; i++) { support[i] = 0; } /* Compute support and clean up markers. */ for (i = 0; i < n; i++) { ddSupportStep(Cudd_Regular(F[i]),support); } for (i = 0; i < n; i++) { ddClearFlag(Cudd_Regular(F[i])); } return(support); } /* end of Cudd_VectorSupportIndex */ /**Function******************************************************************** Synopsis [Counts the variables on which a set of DDs depends.] Description [Counts the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns the number of the variables if successful; CUDD_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [Cudd_VectorSupport Cudd_SupportSize] ******************************************************************************/ int Cudd_VectorSupportSize( DdManager * dd /* manager */, DdNode ** F /* array of DDs whose support is sought */, int n /* size of the array */) { int *support; int i; int size; int count; /* Allocate and initialize support array for ddSupportStep. */ size = ddMax(dd->size, dd->sizeZ); support = ABC_ALLOC(int,size); if (support == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(CUDD_OUT_OF_MEM); } for (i = 0; i < size; i++) { support[i] = 0; } /* Compute support and clean up markers. */ for (i = 0; i < n; i++) { ddSupportStep(Cudd_Regular(F[i]),support); } for (i = 0; i < n; i++) { ddClearFlag(Cudd_Regular(F[i])); } /* Count vriables in support. */ count = 0; for (i = 0; i < size; i++) { if (support[i] == 1) count++; } ABC_FREE(support); return(count); } /* end of Cudd_VectorSupportSize */ /**Function******************************************************************** Synopsis [Classifies the variables in the support of two DDs.] Description [Classifies the variables in the support of two DDs f and g, depending on whther they appear in both DDs, only in f, or only in g. Returns 1 if successful; 0 otherwise.] SideEffects [The cubes of the three classes of variables are returned as side effects.] SeeAlso [Cudd_Support Cudd_VectorSupport] ******************************************************************************/ int Cudd_ClassifySupport( DdManager * dd /* manager */, DdNode * f /* first DD */, DdNode * g /* second DD */, DdNode ** common /* cube of shared variables */, DdNode ** onlyF /* cube of variables only in f */, DdNode ** onlyG /* cube of variables only in g */) { int *supportF, *supportG; DdNode *tmp, *var; int i,j; int size; /* Allocate and initialize support arrays for ddSupportStep. */ size = ddMax(dd->size, dd->sizeZ); supportF = ABC_ALLOC(int,size); if (supportF == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } supportG = ABC_ALLOC(int,size); if (supportG == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(supportF); return(0); } for (i = 0; i < size; i++) { supportF[i] = 0; supportG[i] = 0; } /* Compute supports and clean up markers. */ ddSupportStep(Cudd_Regular(f),supportF); ddClearFlag(Cudd_Regular(f)); ddSupportStep(Cudd_Regular(g),supportG); ddClearFlag(Cudd_Regular(g)); /* Classify variables and create cubes. */ *common = *onlyF = *onlyG = DD_ONE(dd); cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG); for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ i = (j >= dd->size) ? j : dd->invperm[j]; if (supportF[i] == 0 && supportG[i] == 0) continue; var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); cuddRef(var); if (supportG[i] == 0) { tmp = Cudd_bddAnd(dd,*onlyF,var); if (tmp == NULL) { Cudd_RecursiveDeref(dd,*common); Cudd_RecursiveDeref(dd,*onlyF); Cudd_RecursiveDeref(dd,*onlyG); Cudd_RecursiveDeref(dd,var); ABC_FREE(supportF); ABC_FREE(supportG); return(0); } cuddRef(tmp); Cudd_RecursiveDeref(dd,*onlyF); *onlyF = tmp; } else if (supportF[i] == 0) { tmp = Cudd_bddAnd(dd,*onlyG,var); if (tmp == NULL) { Cudd_RecursiveDeref(dd,*common); Cudd_RecursiveDeref(dd,*onlyF); Cudd_RecursiveDeref(dd,*onlyG); Cudd_RecursiveDeref(dd,var); ABC_FREE(supportF); ABC_FREE(supportG); return(0); } cuddRef(tmp); Cudd_RecursiveDeref(dd,*onlyG); *onlyG = tmp; } else { tmp = Cudd_bddAnd(dd,*common,var); if (tmp == NULL) { Cudd_RecursiveDeref(dd,*common); Cudd_RecursiveDeref(dd,*onlyF); Cudd_RecursiveDeref(dd,*onlyG); Cudd_RecursiveDeref(dd,var); ABC_FREE(supportF); ABC_FREE(supportG); return(0); } cuddRef(tmp); Cudd_RecursiveDeref(dd,*common); *common = tmp; } Cudd_RecursiveDeref(dd,var); } ABC_FREE(supportF); ABC_FREE(supportG); cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG); return(1); } /* end of Cudd_ClassifySupport */ /**Function******************************************************************** Synopsis [Counts the number of leaves in a DD.] Description [Counts the number of leaves in a DD. Returns the number of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [Cudd_PrintDebug] ******************************************************************************/ int Cudd_CountLeaves( DdNode * node) { int i; i = ddLeavesInt(Cudd_Regular(node)); ddClearFlag(Cudd_Regular(node)); return(i); } /* end of Cudd_CountLeaves */ /**Function******************************************************************** Synopsis [Picks one on-set cube randomly from the given DD.] Description [Picks one on-set cube randomly from the given DD. The cube is written into an array of characters. The array must have at least as many entries as there are variables. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_bddPickOneMinterm] ******************************************************************************/ int Cudd_bddPickOneCube( DdManager * ddm, DdNode * node, char * string) { DdNode *N, *T, *E; DdNode *one, *bzero; char dir; int i; if (string == NULL || node == NULL) return(0); /* The constant 0 function has no on-set cubes. */ one = DD_ONE(ddm); bzero = Cudd_Not(one); if (node == bzero) return(0); for (i = 0; i < ddm->size; i++) string[i] = 2; for (;;) { if (node == one) break; N = Cudd_Regular(node); T = cuddT(N); E = cuddE(N); if (Cudd_IsComplement(node)) { T = Cudd_Not(T); E = Cudd_Not(E); } if (T == bzero) { string[N->index] = 0; node = E; } else if (E == bzero) { string[N->index] = 1; node = T; } else { dir = (char) ((Cudd_Random() & 0x2000) >> 13); string[N->index] = dir; node = dir ? T : E; } } return(1); } /* end of Cudd_bddPickOneCube */ /**Function******************************************************************** Synopsis [Picks one on-set minterm randomly from the given DD.] Description [Picks one on-set minterm randomly from the given DD. The minterm is in terms of vars. The array vars should contain at least all variables in the support of f; if this condition is not met the minterm built by this procedure may not be contained in f. Builds a BDD for the minterm and returns a pointer to it if successful; NULL otherwise. There are three reasons why the procedure may fail:
        • It may run out of memory;
        • the function f may be the constant 0;
        • the minterm may not be contained in f.
        ] SideEffects [None] SeeAlso [Cudd_bddPickOneCube] ******************************************************************************/ DdNode * Cudd_bddPickOneMinterm( DdManager * dd /* manager */, DdNode * f /* function from which to pick one minterm */, DdNode ** vars /* array of variables */, int n /* size of vars */) { char *string; int i, size; int *indices; int result; DdNode *old, *neW; size = dd->size; string = ABC_ALLOC(char, size); if (string == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } indices = ABC_ALLOC(int,n); if (indices == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(string); return(NULL); } for (i = 0; i < n; i++) { indices[i] = vars[i]->index; } result = Cudd_bddPickOneCube(dd,f,string); if (result == 0) { ABC_FREE(string); ABC_FREE(indices); return(NULL); } /* Randomize choice for don't cares. */ for (i = 0; i < n; i++) { if (string[indices[i]] == 2) string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5); } /* Build result BDD. */ old = Cudd_ReadOne(dd); cuddRef(old); for (i = n-1; i >= 0; i--) { neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0)); if (neW == NULL) { ABC_FREE(string); ABC_FREE(indices); Cudd_RecursiveDeref(dd,old); return(NULL); } cuddRef(neW); Cudd_RecursiveDeref(dd,old); old = neW; } #ifdef DD_DEBUG /* Test. */ if (Cudd_bddLeq(dd,old,f)) { cuddDeref(old); } else { Cudd_RecursiveDeref(dd,old); old = NULL; } #else cuddDeref(old); #endif ABC_FREE(string); ABC_FREE(indices); return(old); } /* end of Cudd_bddPickOneMinterm */ /**Function******************************************************************** Synopsis [Picks k on-set minterms evenly distributed from given DD.] Description [Picks k on-set minterms evenly distributed from given DD. The minterms are in terms of vars. The array vars should contain at least all variables in the support of f; if this condition is not met the minterms built by this procedure may not be contained in f. Builds an array of BDDs for the minterms and returns a pointer to it if successful; NULL otherwise. There are three reasons why the procedure may fail:
        • It may run out of memory;
        • the function f may be the constant 0;
        • the minterms may not be contained in f.
        ] SideEffects [None] SeeAlso [Cudd_bddPickOneMinterm Cudd_bddPickOneCube] ******************************************************************************/ DdNode ** Cudd_bddPickArbitraryMinterms( DdManager * dd /* manager */, DdNode * f /* function from which to pick k minterms */, DdNode ** vars /* array of variables */, int n /* size of vars */, int k /* number of minterms to find */) { char **string; int i, j, l, size; int *indices; int result; DdNode **old, *neW; double minterms; char *saveString; int saveFlag, savePoint = -1, isSame; minterms = Cudd_CountMinterm(dd,f,n); if ((double)k > minterms) { return(NULL); } size = dd->size; string = ABC_ALLOC(char *, k); if (string == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < k; i++) { string[i] = ABC_ALLOC(char, size + 1); if (string[i] == NULL) { for (j = 0; j < i; j++) ABC_FREE(string[i]); ABC_FREE(string); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (j = 0; j < size; j++) string[i][j] = '2'; string[i][size] = '\0'; } indices = ABC_ALLOC(int,n); if (indices == NULL) { dd->errorCode = CUDD_MEMORY_OUT; for (i = 0; i < k; i++) ABC_FREE(string[i]); ABC_FREE(string); return(NULL); } for (i = 0; i < n; i++) { indices[i] = vars[i]->index; } result = ddPickArbitraryMinterms(dd,f,n,k,string); if (result == 0) { for (i = 0; i < k; i++) ABC_FREE(string[i]); ABC_FREE(string); ABC_FREE(indices); return(NULL); } old = ABC_ALLOC(DdNode *, k); if (old == NULL) { dd->errorCode = CUDD_MEMORY_OUT; for (i = 0; i < k; i++) ABC_FREE(string[i]); ABC_FREE(string); ABC_FREE(indices); return(NULL); } saveString = ABC_ALLOC(char, size + 1); if (saveString == NULL) { dd->errorCode = CUDD_MEMORY_OUT; for (i = 0; i < k; i++) ABC_FREE(string[i]); ABC_FREE(string); ABC_FREE(indices); ABC_FREE(old); return(NULL); } saveFlag = 0; /* Build result BDD array. */ for (i = 0; i < k; i++) { isSame = 0; if (!saveFlag) { for (j = i + 1; j < k; j++) { if (strcmp(string[i], string[j]) == 0) { savePoint = i; strcpy(saveString, string[i]); saveFlag = 1; break; } } } else { if (strcmp(string[i], saveString) == 0) { isSame = 1; } else { saveFlag = 0; for (j = i + 1; j < k; j++) { if (strcmp(string[i], string[j]) == 0) { savePoint = i; strcpy(saveString, string[i]); saveFlag = 1; break; } } } } /* Randomize choice for don't cares. */ for (j = 0; j < n; j++) { if (string[i][indices[j]] == '2') string[i][indices[j]] = (char) ((Cudd_Random() & 0x20) ? '1' : '0'); } while (isSame) { isSame = 0; for (j = savePoint; j < i; j++) { if (strcmp(string[i], string[j]) == 0) { isSame = 1; break; } } if (isSame) { strcpy(string[i], saveString); /* Randomize choice for don't cares. */ for (j = 0; j < n; j++) { if (string[i][indices[j]] == '2') string[i][indices[j]] = (char) ((Cudd_Random() & 0x20) ? '1' : '0'); } } } old[i] = Cudd_ReadOne(dd); cuddRef(old[i]); for (j = 0; j < n; j++) { if (string[i][indices[j]] == '0') { neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j])); } else { neW = Cudd_bddAnd(dd,old[i],vars[j]); } if (neW == NULL) { ABC_FREE(saveString); for (l = 0; l < k; l++) ABC_FREE(string[l]); ABC_FREE(string); ABC_FREE(indices); for (l = 0; l <= i; l++) Cudd_RecursiveDeref(dd,old[l]); ABC_FREE(old); return(NULL); } cuddRef(neW); Cudd_RecursiveDeref(dd,old[i]); old[i] = neW; } /* Test. */ if (!Cudd_bddLeq(dd,old[i],f)) { ABC_FREE(saveString); for (l = 0; l < k; l++) ABC_FREE(string[l]); ABC_FREE(string); ABC_FREE(indices); for (l = 0; l <= i; l++) Cudd_RecursiveDeref(dd,old[l]); ABC_FREE(old); return(NULL); } } ABC_FREE(saveString); for (i = 0; i < k; i++) { cuddDeref(old[i]); ABC_FREE(string[i]); } ABC_FREE(string); ABC_FREE(indices); return(old); } /* end of Cudd_bddPickArbitraryMinterms */ /**Function******************************************************************** Synopsis [Extracts a subset from a BDD.] Description [Extracts a subset from a BDD in the following procedure. 1. Compute the weight for each mask variable by counting the number of minterms for both positive and negative cofactors of the BDD with respect to each mask variable. (weight = #positive - #negative) 2. Find a representative cube of the BDD by using the weight. From the top variable of the BDD, for each variable, if the weight is greater than 0.0, choose THEN branch, othereise ELSE branch, until meeting the constant 1. 3. Quantify out the variables not in maskVars from the representative cube and if a variable in maskVars is don't care, replace the variable with a constant(1 or 0) depending on the weight. 4. Make a subset of the BDD by multiplying with the modified cube.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_SubsetWithMaskVars( DdManager * dd /* manager */, DdNode * f /* function from which to pick a cube */, DdNode ** vars /* array of variables */, int nvars /* size of vars */, DdNode ** maskVars /* array of variables */, int mvars /* size of maskVars */) { double *weight; char *string; int i, size; int *indices, *mask; int result; DdNode *zero, *cube, *newCube, *subset; DdNode *cof; DdNode *support; support = Cudd_Support(dd,f); cuddRef(support); Cudd_RecursiveDeref(dd,support); zero = Cudd_Not(dd->one); size = dd->size; weight = ABC_ALLOC(double,size); if (weight == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } for (i = 0; i < size; i++) { weight[i] = 0.0; } for (i = 0; i < mvars; i++) { cof = Cudd_Cofactor(dd, f, maskVars[i]); cuddRef(cof); weight[i] = Cudd_CountMinterm(dd, cof, nvars); Cudd_RecursiveDeref(dd,cof); cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i])); cuddRef(cof); weight[i] -= Cudd_CountMinterm(dd, cof, nvars); Cudd_RecursiveDeref(dd,cof); } string = ABC_ALLOC(char, size + 1); if (string == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(weight); return(NULL); } mask = ABC_ALLOC(int, size); if (mask == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(weight); ABC_FREE(string); return(NULL); } for (i = 0; i < size; i++) { string[i] = '2'; mask[i] = 0; } string[size] = '\0'; indices = ABC_ALLOC(int,nvars); if (indices == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(weight); ABC_FREE(string); ABC_FREE(mask); return(NULL); } for (i = 0; i < nvars; i++) { indices[i] = vars[i]->index; } result = ddPickRepresentativeCube(dd,f,weight,string); if (result == 0) { ABC_FREE(weight); ABC_FREE(string); ABC_FREE(mask); ABC_FREE(indices); return(NULL); } cube = Cudd_ReadOne(dd); cuddRef(cube); zero = Cudd_Not(Cudd_ReadOne(dd)); for (i = 0; i < nvars; i++) { if (string[indices[i]] == '0') { newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero); } else if (string[indices[i]] == '1') { newCube = Cudd_bddIte(dd,cube,vars[i],zero); } else continue; if (newCube == NULL) { ABC_FREE(weight); ABC_FREE(string); ABC_FREE(mask); ABC_FREE(indices); Cudd_RecursiveDeref(dd,cube); return(NULL); } cuddRef(newCube); Cudd_RecursiveDeref(dd,cube); cube = newCube; } Cudd_RecursiveDeref(dd,cube); for (i = 0; i < mvars; i++) { mask[maskVars[i]->index] = 1; } for (i = 0; i < nvars; i++) { if (mask[indices[i]]) { if (string[indices[i]] == '2') { if (weight[indices[i]] >= 0.0) string[indices[i]] = '1'; else string[indices[i]] = '0'; } } else { string[indices[i]] = '2'; } } cube = Cudd_ReadOne(dd); cuddRef(cube); zero = Cudd_Not(Cudd_ReadOne(dd)); /* Build result BDD. */ for (i = 0; i < nvars; i++) { if (string[indices[i]] == '0') { newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero); } else if (string[indices[i]] == '1') { newCube = Cudd_bddIte(dd,cube,vars[i],zero); } else continue; if (newCube == NULL) { ABC_FREE(weight); ABC_FREE(string); ABC_FREE(mask); ABC_FREE(indices); Cudd_RecursiveDeref(dd,cube); return(NULL); } cuddRef(newCube); Cudd_RecursiveDeref(dd,cube); cube = newCube; } subset = Cudd_bddAnd(dd,f,cube); cuddRef(subset); Cudd_RecursiveDeref(dd,cube); /* Test. */ if (Cudd_bddLeq(dd,subset,f)) { cuddDeref(subset); } else { Cudd_RecursiveDeref(dd,subset); subset = NULL; } ABC_FREE(weight); ABC_FREE(string); ABC_FREE(mask); ABC_FREE(indices); return(subset); } /* end of Cudd_SubsetWithMaskVars */ /**Function******************************************************************** Synopsis [Finds the first cube of a decision diagram.] Description [Defines an iterator on the onset of a decision diagram and finds its first cube. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.

        A cube is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents a complemented literal, 1 represents an uncomplemented literal, and 2 stands for don't care. The enumeration produces a disjoint cover of the function associated with the diagram. The size of the array equals the number of variables in the manager at the time Cudd_FirstCube is called.

        For each cube, a value is also returned. This value is always 1 for a BDD, while it may be different from 1 for an ADD. For BDDs, the offset is the set of cubes whose value is the logical zero. For ADDs, the offset is the set of cubes whose value is the background value. The cubes of the offset are not enumerated.] SideEffects [The first cube and its value are returned as side effects.] SeeAlso [Cudd_ForeachCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty Cudd_FirstNode] ******************************************************************************/ DdGen * Cudd_FirstCube( DdManager * dd, DdNode * f, int ** cube, CUDD_VALUE_TYPE * value) { DdGen *gen; DdNode *top, *treg, *next, *nreg, *prev, *preg; int i; int nvars; /* Sanity Check. */ if (dd == NULL || f == NULL) return(NULL); /* Allocate generator an initialize it. */ gen = ABC_ALLOC(DdGen,1); if (gen == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } gen->manager = dd; gen->type = CUDD_GEN_CUBES; gen->status = CUDD_GEN_EMPTY; gen->gen.cubes.cube = NULL; gen->gen.cubes.value = DD_ZERO_VAL; gen->stack.sp = 0; gen->stack.stack = NULL; gen->node = NULL; nvars = dd->size; gen->gen.cubes.cube = ABC_ALLOC(int,nvars); if (gen->gen.cubes.cube == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(gen); return(NULL); } for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2; /* The maximum stack depth is one plus the number of variables. ** because a path may have nodes at all levels, including the ** constant level. */ gen->stack.stack = ABC_ALLOC(DdNodePtr, nvars+1); if (gen->stack.stack == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(gen->gen.cubes.cube); ABC_FREE(gen); return(NULL); } for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL; /* Find the first cube of the onset. */ gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; while (1) { top = gen->stack.stack[gen->stack.sp-1]; treg = Cudd_Regular(top); if (!cuddIsConstant(treg)) { /* Take the else branch first. */ gen->gen.cubes.cube[treg->index] = 0; next = cuddE(treg); if (top != treg) next = Cudd_Not(next); gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) { /* Backtrack */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } prev = gen->stack.stack[gen->stack.sp-2]; preg = Cudd_Regular(prev); nreg = cuddT(preg); if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[preg->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[preg->index] = 2; gen->stack.sp--; top = gen->stack.stack[gen->stack.sp-1]; treg = Cudd_Regular(top); } } else { gen->status = CUDD_GEN_NONEMPTY; gen->gen.cubes.value = cuddV(top); goto done; } } done: *cube = gen->gen.cubes.cube; *value = gen->gen.cubes.value; return(gen); } /* end of Cudd_FirstCube */ /**Function******************************************************************** Synopsis [Generates the next cube of a decision diagram onset.] Description [Generates the next cube of a decision diagram onset, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.] SideEffects [The cube and its value are returned as side effects. The generator is modified.] SeeAlso [Cudd_ForeachCube Cudd_FirstCube Cudd_GenFree Cudd_IsGenEmpty Cudd_NextNode] ******************************************************************************/ int Cudd_NextCube( DdGen * gen, int ** cube, CUDD_VALUE_TYPE * value) { DdNode *top, *treg, *next, *nreg, *prev, *preg; DdManager *dd = gen->manager; /* Backtrack from previously reached terminal node. */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } top = gen->stack.stack[gen->stack.sp-1]; treg = Cudd_Regular(top); prev = gen->stack.stack[gen->stack.sp-2]; preg = Cudd_Regular(prev); nreg = cuddT(preg); if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[preg->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[preg->index] = 2; gen->stack.sp--; } while (1) { top = gen->stack.stack[gen->stack.sp-1]; treg = Cudd_Regular(top); if (!cuddIsConstant(treg)) { /* Take the else branch first. */ gen->gen.cubes.cube[treg->index] = 0; next = cuddE(treg); if (top != treg) next = Cudd_Not(next); gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) { /* Backtrack */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } prev = gen->stack.stack[gen->stack.sp-2]; preg = Cudd_Regular(prev); nreg = cuddT(preg); if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[preg->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[preg->index] = 2; gen->stack.sp--; top = gen->stack.stack[gen->stack.sp-1]; treg = Cudd_Regular(top); } } else { gen->status = CUDD_GEN_NONEMPTY; gen->gen.cubes.value = cuddV(top); goto done; } } done: if (gen->status == CUDD_GEN_EMPTY) return(0); *cube = gen->gen.cubes.cube; *value = gen->gen.cubes.value; return(1); } /* end of Cudd_NextCube */ /**Function******************************************************************** Synopsis [Finds the first prime of a Boolean function.] Description [Defines an iterator on a pair of BDDs describing a (possibly incompletely specified) Boolean functions and finds the first cube of a cover of the function. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.

        The two argument BDDs are the lower and upper bounds of an interval. It is a mistake to call this function with a lower bound that is not less than or equal to the upper bound.

        A cube is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents a complemented literal, 1 represents an uncomplemented literal, and 2 stands for don't care. The enumeration produces a prime and irredundant cover of the function associated with the two BDDs. The size of the array equals the number of variables in the manager at the time Cudd_FirstCube is called.

        This iterator can only be used on BDDs.] SideEffects [The first cube is returned as side effect.] SeeAlso [Cudd_ForeachPrime Cudd_NextPrime Cudd_GenFree Cudd_IsGenEmpty Cudd_FirstCube Cudd_FirstNode] ******************************************************************************/ DdGen * Cudd_FirstPrime( DdManager *dd, DdNode *l, DdNode *u, int **cube) { DdGen *gen; DdNode *implicant, *prime, *tmp; int length, result; /* Sanity Check. */ if (dd == NULL || l == NULL || u == NULL) return(NULL); /* Allocate generator an initialize it. */ gen = ABC_ALLOC(DdGen,1); if (gen == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } gen->manager = dd; gen->type = CUDD_GEN_PRIMES; gen->status = CUDD_GEN_EMPTY; gen->gen.primes.cube = NULL; gen->gen.primes.ub = u; gen->stack.sp = 0; gen->stack.stack = NULL; gen->node = l; cuddRef(l); gen->gen.primes.cube = ABC_ALLOC(int,dd->size); if (gen->gen.primes.cube == NULL) { dd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(gen); return(NULL); } if (gen->node == Cudd_ReadLogicZero(dd)) { gen->status = CUDD_GEN_EMPTY; } else { implicant = Cudd_LargestCube(dd,gen->node,&length); if (implicant == NULL) { Cudd_RecursiveDeref(dd,gen->node); ABC_FREE(gen->gen.primes.cube); ABC_FREE(gen); return(NULL); } cuddRef(implicant); prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub); if (prime == NULL) { Cudd_RecursiveDeref(dd,gen->node); Cudd_RecursiveDeref(dd,implicant); ABC_FREE(gen->gen.primes.cube); ABC_FREE(gen); return(NULL); } cuddRef(prime); Cudd_RecursiveDeref(dd,implicant); tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime)); if (tmp == NULL) { Cudd_RecursiveDeref(dd,gen->node); Cudd_RecursiveDeref(dd,prime); ABC_FREE(gen->gen.primes.cube); ABC_FREE(gen); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(dd,gen->node); gen->node = tmp; result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube); if (result == 0) { Cudd_RecursiveDeref(dd,gen->node); Cudd_RecursiveDeref(dd,prime); ABC_FREE(gen->gen.primes.cube); ABC_FREE(gen); return(NULL); } Cudd_RecursiveDeref(dd,prime); gen->status = CUDD_GEN_NONEMPTY; } *cube = gen->gen.primes.cube; return(gen); } /* end of Cudd_FirstPrime */ /**Function******************************************************************** Synopsis [Generates the next prime of a Boolean function.] Description [Generates the next cube of a Boolean function, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.] SideEffects [The cube and is returned as side effects. The generator is modified.] SeeAlso [Cudd_ForeachPrime Cudd_FirstPrime Cudd_GenFree Cudd_IsGenEmpty Cudd_NextCube Cudd_NextNode] ******************************************************************************/ int Cudd_NextPrime( DdGen *gen, int **cube) { DdNode *implicant, *prime, *tmp; DdManager *dd = gen->manager; int length, result; if (gen->node == Cudd_ReadLogicZero(dd)) { gen->status = CUDD_GEN_EMPTY; } else { implicant = Cudd_LargestCube(dd,gen->node,&length); if (implicant == NULL) { gen->status = CUDD_GEN_EMPTY; return(0); } cuddRef(implicant); prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub); if (prime == NULL) { Cudd_RecursiveDeref(dd,implicant); gen->status = CUDD_GEN_EMPTY; return(0); } cuddRef(prime); Cudd_RecursiveDeref(dd,implicant); tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime)); if (tmp == NULL) { Cudd_RecursiveDeref(dd,prime); gen->status = CUDD_GEN_EMPTY; return(0); } cuddRef(tmp); Cudd_RecursiveDeref(dd,gen->node); gen->node = tmp; result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube); if (result == 0) { Cudd_RecursiveDeref(dd,prime); gen->status = CUDD_GEN_EMPTY; return(0); } Cudd_RecursiveDeref(dd,prime); gen->status = CUDD_GEN_NONEMPTY; } if (gen->status == CUDD_GEN_EMPTY) return(0); *cube = gen->gen.primes.cube; return(1); } /* end of Cudd_NextPrime */ /**Function******************************************************************** Synopsis [Computes the cube of an array of BDD variables.] Description [Computes the cube of an array of BDD variables. If non-null, the phase argument indicates which literal of each variable should appear in the cube. If phase\[i\] is nonzero, then the positive literal is used. If phase is NULL, the cube is positive unate. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd] ******************************************************************************/ DdNode * Cudd_bddComputeCube( DdManager * dd, DdNode ** vars, int * phase, int n) { DdNode *cube; DdNode *fn; int i; cube = DD_ONE(dd); cuddRef(cube); for (i = n - 1; i >= 0; i--) { if (phase == NULL || phase[i] != 0) { fn = Cudd_bddAnd(dd,vars[i],cube); } else { fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube); } if (fn == NULL) { Cudd_RecursiveDeref(dd,cube); return(NULL); } cuddRef(fn); Cudd_RecursiveDeref(dd,cube); cube = fn; } cuddDeref(cube); return(cube); } /* end of Cudd_bddComputeCube */ /**Function******************************************************************** Synopsis [Computes the cube of an array of ADD variables.] Description [Computes the cube of an array of ADD variables. If non-null, the phase argument indicates which literal of each variable should appear in the cube. If phase\[i\] is nonzero, then the positive literal is used. If phase is NULL, the cube is positive unate. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [none] SeeAlso [Cudd_bddComputeCube] ******************************************************************************/ DdNode * Cudd_addComputeCube( DdManager * dd, DdNode ** vars, int * phase, int n) { DdNode *cube, *zero; DdNode *fn; int i; cube = DD_ONE(dd); cuddRef(cube); zero = DD_ZERO(dd); for (i = n - 1; i >= 0; i--) { if (phase == NULL || phase[i] != 0) { fn = Cudd_addIte(dd,vars[i],cube,zero); } else { fn = Cudd_addIte(dd,vars[i],zero,cube); } if (fn == NULL) { Cudd_RecursiveDeref(dd,cube); return(NULL); } cuddRef(fn); Cudd_RecursiveDeref(dd,cube); cube = fn; } cuddDeref(cube); return(cube); } /* end of Cudd_addComputeCube */ /**Function******************************************************************** Synopsis [Builds the BDD of a cube from a positional array.] Description [Builds a cube from a positional array. The array must have one integer entry for each BDD variable. If the i-th entry is 1, the variable of index i appears in true form in the cube; If the i-th entry is 0, the variable of index i appears complemented in the cube; otherwise the variable does not appear in the cube. Returns a pointer to the BDD for the cube if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray] ******************************************************************************/ DdNode * Cudd_CubeArrayToBdd( DdManager *dd, int *array) { DdNode *cube, *var, *tmp; int i; int size = Cudd_ReadSize(dd); cube = DD_ONE(dd); cuddRef(cube); for (i = size - 1; i >= 0; i--) { if ((array[i] & ~1) == 0) { var = Cudd_bddIthVar(dd,i); tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0)); if (tmp == NULL) { Cudd_RecursiveDeref(dd,cube); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(dd,cube); cube = tmp; } } cuddDeref(cube); return(cube); } /* end of Cudd_CubeArrayToBdd */ /**Function******************************************************************** Synopsis [Builds a positional array from the BDD of a cube.] Description [Builds a positional array from the BDD of a cube. Array must have one entry for each BDD variable. The positional array has 1 in i-th position if the variable of index i appears in true form in the cube; it has 0 in i-th position if the variable of index i appears in complemented form in the cube; finally, it has 2 in i-th position if the variable of index i does not appear in the cube. Returns 1 if successful (the BDD is indeed a cube); 0 otherwise.] SideEffects [The result is in the array passed by reference.] SeeAlso [Cudd_CubeArrayToBdd] ******************************************************************************/ int Cudd_BddToCubeArray( DdManager *dd, DdNode *cube, int *array) { DdNode *scan, *t, *e; int i; int size = Cudd_ReadSize(dd); DdNode *zero = Cudd_Not(DD_ONE(dd)); for (i = size-1; i >= 0; i--) { array[i] = 2; } scan = cube; while (!Cudd_IsConstant(scan)) { int index = Cudd_Regular(scan)->index; cuddGetBranches(scan,&t,&e); if (t == zero) { array[index] = 0; scan = e; } else if (e == zero) { array[index] = 1; scan = t; } else { return(0); /* cube is not a cube */ } } if (scan == zero) { return(0); } else { return(1); } } /* end of Cudd_BddToCubeArray */ /**Function******************************************************************** Synopsis [Finds the first node of a decision diagram.] Description [Defines an iterator on the nodes of a decision diagram and finds its first node. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise. The nodes are enumerated in a reverse topological order, so that a node is always preceded in the enumeration by its descendants.] SideEffects [The first node is returned as a side effect.] SeeAlso [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty Cudd_FirstCube] ******************************************************************************/ DdGen * Cudd_FirstNode( DdManager * dd, DdNode * f, DdNode ** node) { DdGen *gen; int size; /* Sanity Check. */ if (dd == NULL || f == NULL) return(NULL); /* Allocate generator an initialize it. */ gen = ABC_ALLOC(DdGen,1); if (gen == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } gen->manager = dd; gen->type = CUDD_GEN_NODES; gen->status = CUDD_GEN_EMPTY; gen->stack.sp = 0; gen->node = NULL; /* Collect all the nodes on the generator stack for later perusal. */ gen->stack.stack = cuddNodeArray(Cudd_Regular(f), &size); if (gen->stack.stack == NULL) { ABC_FREE(gen); dd->errorCode = CUDD_MEMORY_OUT; return(NULL); } gen->gen.nodes.size = size; /* Find the first node. */ if (gen->stack.sp < gen->gen.nodes.size) { gen->status = CUDD_GEN_NONEMPTY; gen->node = gen->stack.stack[gen->stack.sp]; *node = gen->node; } return(gen); } /* end of Cudd_FirstNode */ /**Function******************************************************************** Synopsis [Finds the next node of a decision diagram.] Description [Finds the node of a decision diagram, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.] SideEffects [The next node is returned as a side effect.] SeeAlso [Cudd_ForeachNode Cudd_FirstNode Cudd_GenFree Cudd_IsGenEmpty Cudd_NextCube] ******************************************************************************/ int Cudd_NextNode( DdGen * gen, DdNode ** node) { /* Find the next node. */ gen->stack.sp++; if (gen->stack.sp < gen->gen.nodes.size) { gen->node = gen->stack.stack[gen->stack.sp]; *node = gen->node; return(1); } else { gen->status = CUDD_GEN_EMPTY; return(0); } } /* end of Cudd_NextNode */ /**Function******************************************************************** Synopsis [Frees a CUDD generator.] Description [Frees a CUDD generator. Always returns 0, so that it can be used in mis-like foreach constructs.] SideEffects [None] SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty] ******************************************************************************/ int Cudd_GenFree( DdGen * gen) { if (gen == NULL) return(0); switch (gen->type) { case CUDD_GEN_CUBES: case CUDD_GEN_ZDD_PATHS: ABC_FREE(gen->gen.cubes.cube); ABC_FREE(gen->stack.stack); break; case CUDD_GEN_PRIMES: ABC_FREE(gen->gen.primes.cube); Cudd_RecursiveDeref(gen->manager,gen->node); break; case CUDD_GEN_NODES: ABC_FREE(gen->stack.stack); break; default: return(0); } ABC_FREE(gen); return(0); } /* end of Cudd_GenFree */ /**Function******************************************************************** Synopsis [Queries the status of a generator.] Description [Queries the status of a generator. Returns 1 if the generator is empty or NULL; 0 otherswise.] SideEffects [None] SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube Cudd_FirstNode Cudd_NextNode Cudd_GenFree] ******************************************************************************/ int Cudd_IsGenEmpty( DdGen * gen) { if (gen == NULL) return(1); return(gen->status == CUDD_GEN_EMPTY); } /* end of Cudd_IsGenEmpty */ /**Function******************************************************************** Synopsis [Builds a cube of BDD variables from an array of indices.] Description [Builds a cube of BDD variables from an array of indices. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddComputeCube Cudd_CubeArrayToBdd] ******************************************************************************/ DdNode * Cudd_IndicesToCube( DdManager * dd, int * array, int n) { DdNode *cube, *tmp; int i; cube = DD_ONE(dd); cuddRef(cube); for (i = n - 1; i >= 0; i--) { tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube); if (tmp == NULL) { Cudd_RecursiveDeref(dd,cube); return(NULL); } cuddRef(tmp); Cudd_RecursiveDeref(dd,cube); cube = tmp; } cuddDeref(cube); return(cube); } /* end of Cudd_IndicesToCube */ /**Function******************************************************************** Synopsis [Prints the package version number.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void Cudd_PrintVersion( FILE * fp) { (void) fprintf(fp, "%s\n", CUDD_VERSION); } /* end of Cudd_PrintVersion */ /**Function******************************************************************** Synopsis [Computes the average distance between adjacent nodes.] Description [Computes the average distance between adjacent nodes in the manager. Adjacent nodes are node pairs such that the second node is the then child, else child, or next node in the collision list.] SideEffects [None] SeeAlso [] ******************************************************************************/ double Cudd_AverageDistance( DdManager * dd) { double tetotal, nexttotal; double tesubtotal, nextsubtotal; double temeasured, nextmeasured; int i, j; int slots, nvars; long diff; DdNode *scan; DdNodePtr *nodelist; DdNode *sentinel = &(dd->sentinel); nvars = dd->size; if (nvars == 0) return(0.0); /* Initialize totals. */ tetotal = 0.0; nexttotal = 0.0; temeasured = 0.0; nextmeasured = 0.0; /* Scan the variable subtables. */ for (i = 0; i < nvars; i++) { nodelist = dd->subtables[i].nodelist; tesubtotal = 0.0; nextsubtotal = 0.0; slots = dd->subtables[i].slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != sentinel) { diff = (long) scan - (long) cuddT(scan); tesubtotal += (double) ddAbs(diff); diff = (long) scan - (long) Cudd_Regular(cuddE(scan)); tesubtotal += (double) ddAbs(diff); temeasured += 2.0; if (scan->next != sentinel) { diff = (long) scan - (long) scan->next; nextsubtotal += (double) ddAbs(diff); nextmeasured += 1.0; } scan = scan->next; } } tetotal += tesubtotal; nexttotal += nextsubtotal; } /* Scan the constant table. */ nodelist = dd->constants.nodelist; nextsubtotal = 0.0; slots = dd->constants.slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if (scan->next != NULL) { diff = (long) scan - (long) scan->next; nextsubtotal += (double) ddAbs(diff); nextmeasured += 1.0; } scan = scan->next; } } nexttotal += nextsubtotal; return((tetotal + nexttotal) / (temeasured + nextmeasured)); } /* end of Cudd_AverageDistance */ /**Function******************************************************************** Synopsis [Portable random number generator.] Description [Portable number generator based on ran2 from "Numerical Recipes in C." It is a long period (> 2 * 10^18) random number generator of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly distributed between 0 and 2147483561 (inclusive of the endpoint values). The random generator can be explicitly initialized by calling Cudd_Srandom. If no explicit initialization is performed, then the seed 1 is assumed.] SideEffects [None] SeeAlso [Cudd_Srandom] ******************************************************************************/ long Cudd_Random(void) { int i; /* index in the shuffle table */ long int w; /* work variable */ /* cuddRand == 0 if the geneartor has not been initialized yet. */ if (cuddRand == 0) Cudd_Srandom(1); /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding ** overflows by Schrage's method. */ w = cuddRand / LEQQ1; cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1; cuddRand += (cuddRand < 0) * MODULUS1; /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding ** overflows by Schrage's method. */ w = cuddRand2 / LEQQ2; cuddRand2 = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2; cuddRand2 += (cuddRand2 < 0) * MODULUS2; /* cuddRand is shuffled with the Bays-Durham algorithm. ** shuffleSelect and cuddRand2 are combined to generate the output. */ /* Pick one element from the shuffle table; "i" will be in the range ** from 0 to STAB_SIZE-1. */ i = (int) (shuffleSelect / STAB_DIV); /* Mix the element of the shuffle table with the current iterate of ** the second sub-generator, and replace the chosen element of the ** shuffle table with the current iterate of the first sub-generator. */ shuffleSelect = shuffleTable[i] - cuddRand2; shuffleTable[i] = cuddRand; shuffleSelect += (shuffleSelect < 1) * (MODULUS1 - 1); /* Since shuffleSelect != 0, and we want to be able to return 0, ** here we subtract 1 before returning. */ return(shuffleSelect - 1); } /* end of Cudd_Random */ /**Function******************************************************************** Synopsis [Initializer for the portable random number generator.] Description [Initializer for the portable number generator based on ran2 in "Numerical Recipes in C." The input is the seed for the generator. If it is negative, its absolute value is taken as seed. If it is 0, then 1 is taken as seed. The initialized sets up the two recurrences used to generate a long-period stream, and sets up the shuffle table.] SideEffects [None] SeeAlso [Cudd_Random] ******************************************************************************/ void Cudd_Srandom( long seed) { int i; if (seed < 0) cuddRand = -seed; else if (seed == 0) cuddRand = 1; else cuddRand = seed; cuddRand2 = cuddRand; /* Load the shuffle table (after 11 warm-ups). */ for (i = 0; i < STAB_SIZE + 11; i++) { long int w; w = cuddRand / LEQQ1; cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1; cuddRand += (cuddRand < 0) * MODULUS1; shuffleTable[i % STAB_SIZE] = cuddRand; } shuffleSelect = shuffleTable[1 % STAB_SIZE]; } /* end of Cudd_Srandom */ /**Function******************************************************************** Synopsis [Computes the density of a BDD or ADD.] Description [Computes the density of a BDD or ADD. The density is the ratio of the number of minterms to the number of nodes. If 0 is passed as number of variables, the number of variables existing in the manager is used. Returns the density if successful; (double) CUDD_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [Cudd_CountMinterm Cudd_DagSize] ******************************************************************************/ double Cudd_Density( DdManager * dd /* manager */, DdNode * f /* function whose density is sought */, int nvars /* size of the support of f */) { double minterms; int nodes; double density; if (nvars == 0) nvars = dd->size; minterms = Cudd_CountMinterm(dd,f,nvars); if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms); nodes = Cudd_DagSize(f); density = minterms / (double) nodes; return(density); } /* end of Cudd_Density */ /**Function******************************************************************** Synopsis [Warns that a memory allocation failed.] Description [Warns that a memory allocation failed. This function can be used as replacement of MMout_of_memory to prevent the safe_mem functions of the util package from exiting when malloc returns NULL. One possible use is in case of discretionary allocations; for instance, the allocation of memory to enlarge the computed table.] SideEffects [None] SeeAlso [] ******************************************************************************/ void Cudd_OutOfMem( long size /* size of the allocation that failed */) { (void) fflush(stdout); (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size); return; } /* end of Cudd_OutOfMem */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints a DD to the standard output. One line per node is printed.] Description [Prints a DD to the standard output. One line per node is printed. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_PrintDebug] ******************************************************************************/ int cuddP( DdManager * dd, DdNode * f) { int retval; st__table *table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) return(0); retval = dp2(dd,f,table); st__free_table(table); (void) fputc('\n',dd->out); return(retval); } /* end of cuddP */ /**Function******************************************************************** Synopsis [Frees the memory used to store the minterm counts recorded in the visited table.] Description [Frees the memory used to store the minterm counts recorded in the visited table. Returns st__CONTINUE.] SideEffects [None] ******************************************************************************/ enum st__retval cuddStCountfree( char * key, char * value, char * arg) { double *d; d = (double *)value; ABC_FREE(d); return( st__CONTINUE); } /* end of cuddStCountfree */ /**Function******************************************************************** Synopsis [Recursively collects all the nodes of a DD in a symbol table.] Description [Traverses the DD f and collects all its nodes in a symbol table. f is assumed to be a regular pointer and cuddCollectNodes guarantees this assumption in the recursive calls. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddCollectNodes( DdNode * f, st__table * visited) { DdNode *T, *E; int retval; #ifdef DD_DEBUG assert(!Cudd_IsComplement(f)); #endif /* If already visited, nothing to do. */ if ( st__is_member(visited, (char *) f) == 1) return(1); /* Check for abnormal condition that should never happen. */ if (f == NULL) return(0); /* Mark node as visited. */ if ( st__add_direct(visited, (char *) f, NULL) == st__OUT_OF_MEM) return(0); /* Check terminal case. */ if (cuddIsConstant(f)) return(1); /* Recursive calls. */ T = cuddT(f); retval = cuddCollectNodes(T,visited); if (retval != 1) return(retval); E = Cudd_Regular(cuddE(f)); retval = cuddCollectNodes(E,visited); return(retval); } /* end of cuddCollectNodes */ /**Function******************************************************************** Synopsis [Recursively collects all the nodes of a DD in an array.] Description [Traverses the DD f and collects all its nodes in an array. The caller should free the array returned by cuddNodeArray. Returns a pointer to the array of nodes in case of success; NULL otherwise. The nodes are collected in reverse topological order, so that a node is always preceded in the array by all its descendants.] SideEffects [The number of nodes is returned as a side effect.] SeeAlso [Cudd_FirstNode] ******************************************************************************/ DdNodePtr * cuddNodeArray( DdNode *f, int *n) { DdNodePtr *table; int size, retval; size = ddDagInt(Cudd_Regular(f)); table = ABC_ALLOC(DdNodePtr, size); if (table == NULL) { ddClearFlag(Cudd_Regular(f)); return(NULL); } retval = cuddNodeArrayRecur(f, table, 0); assert(retval == size); *n = size; return(table); } /* cuddNodeArray */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of cuddP.] Description [Performs the recursive step of cuddP. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int dp2( DdManager *dd, DdNode * f, st__table * t) { DdNode *g, *n, *N; int T,E; if (f == NULL) { return(0); } g = Cudd_Regular(f); if (cuddIsConstant(g)) { #if SIZEOF_VOID_P == 8 (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f), (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g)); #else (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f), (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g)); #endif return(1); } if ( st__is_member(t,(char *) g) == 1) { return(1); } if ( st__add_direct(t,(char *) g,NULL) == st__OUT_OF_MEM) return(0); #ifdef DD_STATS #if SIZEOF_VOID_P == 8 (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f), (ptruint) g / (ptruint) sizeof(DdNode), g->index, g->ref); #else (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f), (ptruint) g / (ptruint) sizeof(DdNode),g->index,g->ref); #endif #else #if SIZEOF_VOID_P == 8 (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %u\t", bang(f), (ptruint) g / (ptruint) sizeof(DdNode),g->index); #else (void) fprintf(dd->out,"ID = %c0x%x\tindex = %hu\t", bang(f), (ptruint) g / (ptruint) sizeof(DdNode),g->index); #endif #endif n = cuddT(g); if (cuddIsConstant(n)) { (void) fprintf(dd->out,"T = %-9g\t",cuddV(n)); T = 1; } else { #if SIZEOF_VOID_P == 8 (void) fprintf(dd->out,"T = 0x%lx\t",(ptruint) n / (ptruint) sizeof(DdNode)); #else (void) fprintf(dd->out,"T = 0x%x\t",(ptruint) n / (ptruint) sizeof(DdNode)); #endif T = 0; } n = cuddE(g); N = Cudd_Regular(n); if (cuddIsConstant(N)) { (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N)); E = 1; } else { #if SIZEOF_VOID_P == 8 (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode)); #else (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode)); #endif E = 0; } if (E == 0) { if (dp2(dd,N,t) == 0) return(0); } if (T == 0) { if (dp2(dd,cuddT(g),t) == 0) return(0); } return(1); } /* end of dp2 */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_PrintMinterm.] Description [] SideEffects [None] ******************************************************************************/ static void ddPrintMintermAux( DdManager * dd /* manager */, DdNode * node /* current node */, int * list /* current recursion path */) { DdNode *N,*Nv,*Nnv; int i,v,index; N = Cudd_Regular(node); if (cuddIsConstant(N)) { /* Terminal case: Print one cube based on the current recursion ** path, unless we have reached the background value (ADDs) or ** the logical zero (BDDs). */ if (node != background && node != zero) { for (i = 0; i < dd->size; i++) { v = list[i]; if (v == 0) (void) fprintf(dd->out,"0"); else if (v == 1) (void) fprintf(dd->out,"1"); else (void) fprintf(dd->out,"-"); } (void) fprintf(dd->out," % g\n", cuddV(node)); } } else { Nv = cuddT(N); Nnv = cuddE(N); if (Cudd_IsComplement(node)) { Nv = Cudd_Not(Nv); Nnv = Cudd_Not(Nnv); } index = N->index; list[index] = 0; ddPrintMintermAux(dd,Nnv,list); list[index] = 1; ddPrintMintermAux(dd,Nv,list); list[index] = 2; } return; } /* end of ddPrintMintermAux */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_DagSize.] Description [Performs the recursive step of Cudd_DagSize. Returns the number of nodes in the graph rooted at n.] SideEffects [None] ******************************************************************************/ static int ddDagInt( DdNode * n) { int tval, eval; if (Cudd_IsComplement(n->next)) { return(0); } n->next = Cudd_Not(n->next); if (cuddIsConstant(n)) { return(1); } tval = ddDagInt(cuddT(n)); eval = ddDagInt(Cudd_Regular(cuddE(n))); return(1 + tval + eval); } /* end of ddDagInt */ /**Function******************************************************************** Synopsis [Performs the recursive step of cuddNodeArray.] Description [Performs the recursive step of cuddNodeArray. Returns an the number of nodes in the DD. Clear the least significant bit of the next field that was used as visited flag by cuddNodeArrayRecur when counting the nodes. node is supposed to be regular; the invariant is maintained by this procedure.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddNodeArrayRecur( DdNode *f, DdNodePtr *table, int index) { int tindex, eindex; if (!Cudd_IsComplement(f->next)) { return(index); } /* Clear visited flag. */ f->next = Cudd_Regular(f->next); if (cuddIsConstant(f)) { table[index] = f; return(index + 1); } tindex = cuddNodeArrayRecur(cuddT(f), table, index); eindex = cuddNodeArrayRecur(Cudd_Regular(cuddE(f)), table, tindex); table[eindex] = f; return(eindex + 1); } /* end of cuddNodeArrayRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_CofactorEstimate.] Description [Performs the recursive step of Cudd_CofactorEstimate. Returns an estimate of the number of nodes in the DD of a cofactor of node. Uses the least significant bit of the next field as visited flag. node is supposed to be regular; the invariant is maintained by this procedure.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddEstimateCofactor( DdManager *dd, st__table *table, DdNode * node, int i, int phase, DdNode ** ptr) { int tval, eval, val; DdNode *ptrT, *ptrE; if (Cudd_IsComplement(node->next)) { if (! st__lookup(table,(char *)node,(char **)ptr)) { if ( st__add_direct(table,(char *)node,(char *)node) == st__OUT_OF_MEM) return(CUDD_OUT_OF_MEM); *ptr = node; } return(0); } node->next = Cudd_Not(node->next); if (cuddIsConstant(node)) { *ptr = node; if ( st__add_direct(table,(char *)node,(char *)node) == st__OUT_OF_MEM) return(CUDD_OUT_OF_MEM); return(1); } if ((int) node->index == i) { if (phase == 1) { *ptr = cuddT(node); val = ddDagInt(cuddT(node)); } else { *ptr = cuddE(node); val = ddDagInt(Cudd_Regular(cuddE(node))); } if (node->ref > 1) { if ( st__add_direct(table,(char *)node,(char *)*ptr) == st__OUT_OF_MEM) return(CUDD_OUT_OF_MEM); } return(val); } if (dd->perm[node->index] > dd->perm[i]) { *ptr = node; tval = ddDagInt(cuddT(node)); eval = ddDagInt(Cudd_Regular(cuddE(node))); if (node->ref > 1) { if ( st__add_direct(table,(char *)node,(char *)node) == st__OUT_OF_MEM) return(CUDD_OUT_OF_MEM); } val = 1 + tval + eval; return(val); } tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT); eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i, phase,&ptrE); ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node))); if (ptrT == ptrE) { /* recombination */ *ptr = ptrT; val = tval; if (node->ref > 1) { if ( st__add_direct(table,(char *)node,(char *)*ptr) == st__OUT_OF_MEM) return(CUDD_OUT_OF_MEM); } } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) && (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) { if (Cudd_IsComplement((*ptr)->next)) { val = 0; } else { val = 1 + tval + eval; } if (node->ref > 1) { if ( st__add_direct(table,(char *)node,(char *)*ptr) == st__OUT_OF_MEM) return(CUDD_OUT_OF_MEM); } } else { *ptr = node; val = 1 + tval + eval; } return(val); } /* end of cuddEstimateCofactor */ /**Function******************************************************************** Synopsis [Checks the unique table for the existence of an internal node.] Description [Checks the unique table for the existence of an internal node. Returns a pointer to the node if it is in the table; NULL otherwise.] SideEffects [None] SeeAlso [cuddUniqueInter] ******************************************************************************/ static DdNode * cuddUniqueLookup( DdManager * unique, int index, DdNode * T, DdNode * E) { int posn; unsigned int level; DdNodePtr *nodelist; DdNode *looking; DdSubtable *subtable; if (index >= unique->size) { return(NULL); } level = unique->perm[index]; subtable = &(unique->subtables[level]); #ifdef DD_DEBUG assert(level < (unsigned) cuddI(unique,T->index)); assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); #endif posn = ddHash(cuddF2L(T), cuddF2L(E), subtable->shift); nodelist = subtable->nodelist; looking = nodelist[posn]; while (T < cuddT(looking)) { looking = Cudd_Regular(looking->next); } while (T == cuddT(looking) && E < cuddE(looking)) { looking = Cudd_Regular(looking->next); } if (cuddT(looking) == T && cuddE(looking) == E) { return(looking); } return(NULL); } /* end of cuddUniqueLookup */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_CofactorEstimateSimple.] Description [Performs the recursive step of Cudd_CofactorEstimateSimple. Returns an estimate of the number of nodes in the DD of the positive cofactor of node. Uses the least significant bit of the next field as visited flag. node is supposed to be regular; the invariant is maintained by this procedure.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddEstimateCofactorSimple( DdNode * node, int i) { int tval, eval; if (Cudd_IsComplement(node->next)) { return(0); } node->next = Cudd_Not(node->next); if (cuddIsConstant(node)) { return(1); } tval = cuddEstimateCofactorSimple(cuddT(node),i); if ((int) node->index == i) return(tval); eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i); return(1 + tval + eval); } /* end of cuddEstimateCofactorSimple */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_CountMinterm.] Description [Performs the recursive step of Cudd_CountMinterm. It is based on the following identity. Let |f| be the number of minterms of f. Then:

        |f| = (|f0|+|f1|)/2 where f0 and f1 are the two cofactors of f. Does not use the identity |f'| = max - |f|, to minimize loss of accuracy due to roundoff. Returns the number of minterms of the function rooted at node.] SideEffects [None] ******************************************************************************/ static double ddCountMintermAux( DdNode * node, double max, DdHashTable * table) { DdNode *N, *Nt, *Ne; double min, minT, minE; DdNode *res; N = Cudd_Regular(node); if (cuddIsConstant(N)) { if (node == background || node == zero) { return(0.0); } else { return(max); } } if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { min = cuddV(res); if (res->ref == 0) { table->manager->dead++; table->manager->constants.dead++; } return(min); } Nt = cuddT(N); Ne = cuddE(N); if (Cudd_IsComplement(node)) { Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); } minT = ddCountMintermAux(Nt,max,table); if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); minT *= 0.5; minE = ddCountMintermAux(Ne,max,table); if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); minE *= 0.5; min = minT + minE; if (N->ref != 1) { ptrint fanout = (ptrint) N->ref; cuddSatDec(fanout); res = cuddUniqueConst(table->manager,min); if (!cuddHashTableInsert1(table,node,res,fanout)) { cuddRef(res); Cudd_RecursiveDeref(table->manager, res); return((double)CUDD_OUT_OF_MEM); } } return(min); } /* end of ddCountMintermAux */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_CountPath.] Description [Performs the recursive step of Cudd_CountPath. It is based on the following identity. Let |f| be the number of paths of f. Then: |f| = |f0|+|f1| where f0 and f1 are the two cofactors of f. Uses the identity |f'| = |f|, to improve the utilization of the (local) cache. Returns the number of paths of the function rooted at node.] SideEffects [None] ******************************************************************************/ static double ddCountPathAux( DdNode * node, st__table * table) { DdNode *Nv, *Nnv; double paths, *ppaths, paths1, paths2; double *dummy; if (cuddIsConstant(node)) { return(1.0); } if ( st__lookup(table, (const char *)node, (char **)&dummy)) { paths = *dummy; return(paths); } Nv = cuddT(node); Nnv = cuddE(node); paths1 = ddCountPathAux(Nv,table); if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); paths2 = ddCountPathAux(Cudd_Regular(Nnv),table); if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); paths = paths1 + paths2; ppaths = ABC_ALLOC(double,1); if (ppaths == NULL) { return((double)CUDD_OUT_OF_MEM); } *ppaths = paths; if ( st__add_direct(table,(char *)node, (char *)ppaths) == st__OUT_OF_MEM) { ABC_FREE(ppaths); return((double)CUDD_OUT_OF_MEM); } return(paths); } /* end of ddCountPathAux */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_EpdCountMinterm.] Description [Performs the recursive step of Cudd_EpdCountMinterm. It is based on the following identity. Let |f| be the number of minterms of f. Then: |f| = (|f0|+|f1|)/2 where f0 and f1 are the two cofactors of f. Does not use the identity |f'| = max - |f|, to minimize loss of accuracy due to roundoff. Returns the number of minterms of the function rooted at node.] SideEffects [None] ******************************************************************************/ static int ddEpdCountMintermAux( DdNode * node, EpDouble * max, EpDouble * epd, st__table * table) { DdNode *Nt, *Ne; EpDouble *min, minT, minE; EpDouble *res; int status; /* node is assumed to be regular */ if (cuddIsConstant(node)) { if (node == background || node == zero) { EpdMakeZero(epd, 0); } else { EpdCopy(max, epd); } return(0); } if (node->ref != 1 && st__lookup(table, (const char *)node, (char **)&res)) { EpdCopy(res, epd); return(0); } Nt = cuddT(node); Ne = cuddE(node); status = ddEpdCountMintermAux(Nt,max,&minT,table); if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); EpdMultiply(&minT, (double)0.5); status = ddEpdCountMintermAux(Cudd_Regular(Ne),max,&minE,table); if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); if (Cudd_IsComplement(Ne)) { EpdSubtract3(max, &minE, epd); EpdCopy(epd, &minE); } EpdMultiply(&minE, (double)0.5); EpdAdd3(&minT, &minE, epd); if (node->ref > 1) { min = EpdAlloc(); if (!min) return(CUDD_OUT_OF_MEM); EpdCopy(epd, min); if ( st__insert(table, (char *)node, (char *)min) == st__OUT_OF_MEM) { EpdFree(min); return(CUDD_OUT_OF_MEM); } } return(0); } /* end of ddEpdCountMintermAux */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_CountPathsToNonZero.] Description [Performs the recursive step of Cudd_CountPathsToNonZero. It is based on the following identity. Let |f| be the number of paths of f. Then: |f| = |f0|+|f1| where f0 and f1 are the two cofactors of f. Returns the number of paths of the function rooted at node.] SideEffects [None] ******************************************************************************/ static double ddCountPathsToNonZero( DdNode * N, st__table * table) { DdNode *node, *Nt, *Ne; double paths, *ppaths, paths1, paths2; double *dummy; node = Cudd_Regular(N); if (cuddIsConstant(node)) { return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL)); } if ( st__lookup(table, (const char *)N, (char **)&dummy)) { paths = *dummy; return(paths); } Nt = cuddT(node); Ne = cuddE(node); if (node != N) { Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); } paths1 = ddCountPathsToNonZero(Nt,table); if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); paths2 = ddCountPathsToNonZero(Ne,table); if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); paths = paths1 + paths2; ppaths = ABC_ALLOC(double,1); if (ppaths == NULL) { return((double)CUDD_OUT_OF_MEM); } *ppaths = paths; if ( st__add_direct(table,(char *)N, (char *)ppaths) == st__OUT_OF_MEM) { ABC_FREE(ppaths); return((double)CUDD_OUT_OF_MEM); } return(paths); } /* end of ddCountPathsToNonZero */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_Support.] Description [Performs the recursive step of Cudd_Support. Performs a DFS from f. The support is accumulated in supp as a side effect. Uses the LSB of the then pointer as visited flag.] SideEffects [None] SeeAlso [ddClearFlag] ******************************************************************************/ static void ddSupportStep( DdNode * f, int * support) { if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { return; } support[f->index] = 1; ddSupportStep(cuddT(f),support); ddSupportStep(Cudd_Regular(cuddE(f)),support); /* Mark as visited. */ f->next = Cudd_Not(f->next); return; } /* end of ddSupportStep */ /**Function******************************************************************** Synopsis [Performs a DFS from f, clearing the LSB of the next pointers.] Description [] SideEffects [None] SeeAlso [ddSupportStep ddDagInt] ******************************************************************************/ static void ddClearFlag( DdNode * f) { if (!Cudd_IsComplement(f->next)) { return; } /* Clear visited flag. */ f->next = Cudd_Regular(f->next); if (cuddIsConstant(f)) { return; } ddClearFlag(cuddT(f)); ddClearFlag(Cudd_Regular(cuddE(f))); return; } /* end of ddClearFlag */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_CountLeaves.] Description [Performs the recursive step of Cudd_CountLeaves. Returns the number of leaves in the DD rooted at n.] SideEffects [None] SeeAlso [Cudd_CountLeaves] ******************************************************************************/ static int ddLeavesInt( DdNode * n) { int tval, eval; if (Cudd_IsComplement(n->next)) { return(0); } n->next = Cudd_Not(n->next); if (cuddIsConstant(n)) { return(1); } tval = ddLeavesInt(cuddT(n)); eval = ddLeavesInt(Cudd_Regular(cuddE(n))); return(tval + eval); } /* end of ddLeavesInt */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddPickArbitraryMinterms.] Description [Performs the recursive step of Cudd_bddPickArbitraryMinterms. Returns 1 if successful; 0 otherwise.] SideEffects [none] SeeAlso [Cudd_bddPickArbitraryMinterms] ******************************************************************************/ static int ddPickArbitraryMinterms( DdManager *dd, DdNode *node, int nvars, int nminterms, char **string) { DdNode *N, *T, *E; DdNode *one, *bzero; int i, t, result; double min1, min2; if (string == NULL || node == NULL) return(0); /* The constant 0 function has no on-set cubes. */ one = DD_ONE(dd); bzero = Cudd_Not(one); if (nminterms == 0 || node == bzero) return(1); if (node == one) { return(1); } N = Cudd_Regular(node); T = cuddT(N); E = cuddE(N); if (Cudd_IsComplement(node)) { T = Cudd_Not(T); E = Cudd_Not(E); } min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0; if (min1 == (double)CUDD_OUT_OF_MEM) return(0); min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0; if (min2 == (double)CUDD_OUT_OF_MEM) return(0); t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5); for (i = 0; i < t; i++) string[i][N->index] = '1'; for (i = t; i < nminterms; i++) string[i][N->index] = '0'; result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]); if (result == 0) return(0); result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]); return(result); } /* end of ddPickArbitraryMinterms */ /**Function******************************************************************** Synopsis [Finds a representative cube of a BDD.] Description [Finds a representative cube of a BDD with the weight of each variable. From the top variable, if the weight is greater than or equal to 0.0, choose THEN branch unless the child is the constant 0. Otherwise, choose ELSE branch unless the child is the constant 0.] SideEffects [Cudd_SubsetWithMaskVars Cudd_bddPickOneCube] ******************************************************************************/ static int ddPickRepresentativeCube( DdManager *dd, DdNode *node, double *weight, char *string) { DdNode *N, *T, *E; DdNode *one, *bzero; if (string == NULL || node == NULL) return(0); /* The constant 0 function has no on-set cubes. */ one = DD_ONE(dd); bzero = Cudd_Not(one); if (node == bzero) return(0); if (node == DD_ONE(dd)) return(1); for (;;) { N = Cudd_Regular(node); if (N == one) break; T = cuddT(N); E = cuddE(N); if (Cudd_IsComplement(node)) { T = Cudd_Not(T); E = Cudd_Not(E); } if (weight[N->index] >= 0.0) { if (T == bzero) { node = E; string[N->index] = '0'; } else { node = T; string[N->index] = '1'; } } else { if (E == bzero) { node = T; string[N->index] = '1'; } else { node = E; string[N->index] = '0'; } } } return(1); } /* end of ddPickRepresentativeCube */ /**Function******************************************************************** Synopsis [Frees the memory used to store the minterm counts recorded in the visited table.] Description [Frees the memory used to store the minterm counts recorded in the visited table. Returns st__CONTINUE.] SideEffects [None] ******************************************************************************/ static enum st__retval ddEpdFree( char * key, char * value, char * arg) { EpDouble *epd; epd = (EpDouble *) value; EpdFree(epd); return( st__CONTINUE); } /* end of ddEpdFree */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddWindow.c000066400000000000000000000750261300674244400237710ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddWindow.c] PackageName [cudd] Synopsis [Functions for variable reordering by window permutation.] Description [Internal procedures included in this module:
        • cuddWindowReorder()
        Static procedures included in this module:
        • ddWindow2()
        • ddWindowConv2()
        • ddPermuteWindow3()
        • ddWindow3()
        • ddWindowConv3()
        • ddPermuteWindow4()
        • ddWindow4()
        • ddWindowConv4()
        ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddWindow.c,v 1.14 2009/02/20 02:14:58 fabio Exp $"; #endif #ifdef DD_STATS extern int ddTotalNumberSwapping; extern int ddTotalNISwaps; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int ddWindow2 (DdManager *table, int low, int high); static int ddWindowConv2 (DdManager *table, int low, int high); static int ddPermuteWindow3 (DdManager *table, int x); static int ddWindow3 (DdManager *table, int low, int high); static int ddWindowConv3 (DdManager *table, int low, int high); static int ddPermuteWindow4 (DdManager *table, int w); static int ddWindow4 (DdManager *table, int low, int high); static int ddWindowConv4 (DdManager *table, int low, int high); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Reorders by applying the method of the sliding window.] Description [Reorders by applying the method of the sliding window. Tries all possible permutations to the variables in a window that slides from low to high. The size of the window is determined by submethod. Assumes that no dead nodes are present. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ int cuddWindowReorder( DdManager * table /* DD table */, int low /* lowest index to reorder */, int high /* highest index to reorder */, Cudd_ReorderingType submethod /* window reordering option */) { int res; #ifdef DD_DEBUG int supposedOpt; #endif switch (submethod) { case CUDD_REORDER_WINDOW2: res = ddWindow2(table,low,high); break; case CUDD_REORDER_WINDOW3: res = ddWindow3(table,low,high); break; case CUDD_REORDER_WINDOW4: res = ddWindow4(table,low,high); break; case CUDD_REORDER_WINDOW2_CONV: res = ddWindowConv2(table,low,high); break; case CUDD_REORDER_WINDOW3_CONV: res = ddWindowConv3(table,low,high); #ifdef DD_DEBUG supposedOpt = table->keys - table->isolated; res = ddWindow3(table,low,high); if (table->keys - table->isolated != (unsigned) supposedOpt) { (void) fprintf(table->err, "Convergence failed! (%d != %d)\n", table->keys - table->isolated, supposedOpt); } #endif break; case CUDD_REORDER_WINDOW4_CONV: res = ddWindowConv4(table,low,high); #ifdef DD_DEBUG supposedOpt = table->keys - table->isolated; res = ddWindow4(table,low,high); if (table->keys - table->isolated != (unsigned) supposedOpt) { (void) fprintf(table->err,"Convergence failed! (%d != %d)\n", table->keys - table->isolated, supposedOpt); } #endif break; default: return(0); } return(res); } /* end of cuddWindowReorder */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Reorders by applying a sliding window of width 2.] Description [Reorders by applying a sliding window of width 2. Tries both permutations of the variables in a window that slides from low to high. Assumes that no dead nodes are present. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddWindow2( DdManager * table, int low, int high) { int x; int res; int size; #ifdef DD_DEBUG assert(low >= 0 && high < table->size); #endif if (high-low < 1) return(0); res = table->keys - table->isolated; for (x = low; x < high; x++) { size = res; res = cuddSwapInPlace(table,x,x+1); if (res == 0) return(0); if (res >= size) { /* no improvement: undo permutation */ res = cuddSwapInPlace(table,x,x+1); if (res == 0) return(0); } #ifdef DD_STATS if (res < size) { (void) fprintf(table->out,"-"); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } return(1); } /* end of ddWindow2 */ /**Function******************************************************************** Synopsis [Reorders by repeatedly applying a sliding window of width 2.] Description [Reorders by repeatedly applying a sliding window of width 2. Tries both permutations of the variables in a window that slides from low to high. Assumes that no dead nodes are present. Uses an event-driven approach to determine convergence. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddWindowConv2( DdManager * table, int low, int high) { int x; int res; int nwin; int newevent; int *events; int size; #ifdef DD_DEBUG assert(low >= 0 && high < table->size); #endif if (high-low < 1) return(ddWindowConv2(table,low,high)); nwin = high-low; events = ABC_ALLOC(int,nwin); if (events == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } for (x=0; xkeys - table->isolated; do { newevent = 0; for (x=0; x= size) { /* no improvement: undo permutation */ res = cuddSwapInPlace(table,x+low,x+low+1); if (res == 0) { ABC_FREE(events); return(0); } } if (res < size) { if (x < nwin-1) events[x+1] = 1; if (x > 0) events[x-1] = 1; newevent = 1; } events[x] = 0; #ifdef DD_STATS if (res < size) { (void) fprintf(table->out,"-"); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } } #ifdef DD_STATS if (newevent) { (void) fprintf(table->out,"|"); fflush(table->out); } #endif } while (newevent); ABC_FREE(events); return(1); } /* end of ddWindowConv3 */ /**Function******************************************************************** Synopsis [Tries all the permutations of the three variables between x and x+2 and retains the best.] Description [Tries all the permutations of the three variables between x and x+2 and retains the best. Assumes that no dead nodes are present. Returns the index of the best permutation (1-6) in case of success; 0 otherwise.Assumes that no dead nodes are present. Returns the index of the best permutation (1-6) in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddPermuteWindow3( DdManager * table, int x) { int y,z; int size,sizeNew; int best; #ifdef DD_DEBUG assert(table->dead == 0); assert(x+2 < table->size); #endif size = table->keys - table->isolated; y = x+1; z = y+1; /* The permutation pattern is: ** (x,y)(y,z) ** repeated three times to get all 3! = 6 permutations. */ #define ABC 1 best = ABC; #define BAC 2 sizeNew = cuddSwapInPlace(table,x,y); if (sizeNew < size) { if (sizeNew == 0) return(0); best = BAC; size = sizeNew; } #define BCA 3 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size) { if (sizeNew == 0) return(0); best = BCA; size = sizeNew; } #define CBA 4 sizeNew = cuddSwapInPlace(table,x,y); if (sizeNew < size) { if (sizeNew == 0) return(0); best = CBA; size = sizeNew; } #define CAB 5 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size) { if (sizeNew == 0) return(0); best = CAB; size = sizeNew; } #define ACB 6 sizeNew = cuddSwapInPlace(table,x,y); if (sizeNew < size) { if (sizeNew == 0) return(0); best = ACB; size = sizeNew; } /* Now take the shortest route to the best permuytation. ** The initial permutation is ACB. */ switch(best) { case BCA: if (!cuddSwapInPlace(table,y,z)) return(0); case CBA: if (!cuddSwapInPlace(table,x,y)) return(0); case ABC: if (!cuddSwapInPlace(table,y,z)) return(0); case ACB: break; case BAC: if (!cuddSwapInPlace(table,y,z)) return(0); case CAB: if (!cuddSwapInPlace(table,x,y)) return(0); break; default: return(0); } #ifdef DD_DEBUG assert(table->keys - table->isolated == (unsigned) size); #endif return(best); } /* end of ddPermuteWindow3 */ /**Function******************************************************************** Synopsis [Reorders by applying a sliding window of width 3.] Description [Reorders by applying a sliding window of width 3. Tries all possible permutations to the variables in a window that slides from low to high. Assumes that no dead nodes are present. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddWindow3( DdManager * table, int low, int high) { int x; int res; #ifdef DD_DEBUG assert(low >= 0 && high < table->size); #endif if (high-low < 2) return(ddWindow2(table,low,high)); for (x = low; x+1 < high; x++) { res = ddPermuteWindow3(table,x); if (res == 0) return(0); #ifdef DD_STATS if (res == ABC) { (void) fprintf(table->out,"="); } else { (void) fprintf(table->out,"-"); } fflush(table->out); #endif } return(1); } /* end of ddWindow3 */ /**Function******************************************************************** Synopsis [Reorders by repeatedly applying a sliding window of width 3.] Description [Reorders by repeatedly applying a sliding window of width 3. Tries all possible permutations to the variables in a window that slides from low to high. Assumes that no dead nodes are present. Uses an event-driven approach to determine convergence. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddWindowConv3( DdManager * table, int low, int high) { int x; int res; int nwin; int newevent; int *events; #ifdef DD_DEBUG assert(low >= 0 && high < table->size); #endif if (high-low < 2) return(ddWindowConv2(table,low,high)); nwin = high-low-1; events = ABC_ALLOC(int,nwin); if (events == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } for (x=0; x 1) events[x-2] = 1; newevent = 1; break; case BCA: case CBA: case CAB: if (x < nwin-2) events[x+2] = 1; if (x < nwin-1) events[x+1] = 1; if (x > 0) events[x-1] = 1; if (x > 1) events[x-2] = 1; newevent = 1; break; case ACB: if (x < nwin-2) events[x+2] = 1; if (x > 0) events[x-1] = 1; newevent = 1; break; default: ABC_FREE(events); return(0); } events[x] = 0; #ifdef DD_STATS if (res == ABC) { (void) fprintf(table->out,"="); } else { (void) fprintf(table->out,"-"); } fflush(table->out); #endif } } #ifdef DD_STATS if (newevent) { (void) fprintf(table->out,"|"); fflush(table->out); } #endif } while (newevent); ABC_FREE(events); return(1); } /* end of ddWindowConv3 */ /**Function******************************************************************** Synopsis [Tries all the permutations of the four variables between w and w+3 and retains the best.] Description [Tries all the permutations of the four variables between w and w+3 and retains the best. Assumes that no dead nodes are present. Returns the index of the best permutation (1-24) in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddPermuteWindow4( DdManager * table, int w) { int x,y,z; int size,sizeNew; int best; #ifdef DD_DEBUG assert(table->dead == 0); assert(w+3 < table->size); #endif size = table->keys - table->isolated; x = w+1; y = x+1; z = y+1; /* The permutation pattern is: * (w,x)(y,z)(w,x)(x,y) * (y,z)(w,x)(y,z)(x,y) * repeated three times to get all 4! = 24 permutations. * This gives a hamiltonian circuit of Cayley's graph. * The codes to the permutation are assigned in topological order. * The permutations at lower distance from the final permutation are * assigned lower codes. This way we can choose, between * permutations that give the same size, one that requires the minimum * number of swaps from the final permutation of the hamiltonian circuit. * There is an exception to this rule: ABCD is given Code 1, to * avoid oscillation when convergence is sought. */ #define ABCD 1 best = ABCD; #define BACD 7 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size) { if (sizeNew == 0) return(0); best = BACD; size = sizeNew; } #define BADC 13 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size) { if (sizeNew == 0) return(0); best = BADC; size = sizeNew; } #define ABDC 8 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size || (sizeNew == size && ABDC < best)) { if (sizeNew == 0) return(0); best = ABDC; size = sizeNew; } #define ADBC 14 sizeNew = cuddSwapInPlace(table,x,y); if (sizeNew < size) { if (sizeNew == 0) return(0); best = ADBC; size = sizeNew; } #define ADCB 9 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size || (sizeNew == size && ADCB < best)) { if (sizeNew == 0) return(0); best = ADCB; size = sizeNew; } #define DACB 15 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size) { if (sizeNew == 0) return(0); best = DACB; size = sizeNew; } #define DABC 20 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size) { if (sizeNew == 0) return(0); best = DABC; size = sizeNew; } #define DBAC 23 sizeNew = cuddSwapInPlace(table,x,y); if (sizeNew < size) { if (sizeNew == 0) return(0); best = DBAC; size = sizeNew; } #define BDAC 19 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size || (sizeNew == size && BDAC < best)) { if (sizeNew == 0) return(0); best = BDAC; size = sizeNew; } #define BDCA 21 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size || (sizeNew == size && BDCA < best)) { if (sizeNew == 0) return(0); best = BDCA; size = sizeNew; } #define DBCA 24 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size) { if (sizeNew == 0) return(0); best = DBCA; size = sizeNew; } #define DCBA 22 sizeNew = cuddSwapInPlace(table,x,y); if (sizeNew < size || (sizeNew == size && DCBA < best)) { if (sizeNew == 0) return(0); best = DCBA; size = sizeNew; } #define DCAB 18 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size || (sizeNew == size && DCAB < best)) { if (sizeNew == 0) return(0); best = DCAB; size = sizeNew; } #define CDAB 12 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size || (sizeNew == size && CDAB < best)) { if (sizeNew == 0) return(0); best = CDAB; size = sizeNew; } #define CDBA 17 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size || (sizeNew == size && CDBA < best)) { if (sizeNew == 0) return(0); best = CDBA; size = sizeNew; } #define CBDA 11 sizeNew = cuddSwapInPlace(table,x,y); if (sizeNew < size || (sizeNew == size && CBDA < best)) { if (sizeNew == 0) return(0); best = CBDA; size = sizeNew; } #define BCDA 16 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size || (sizeNew == size && BCDA < best)) { if (sizeNew == 0) return(0); best = BCDA; size = sizeNew; } #define BCAD 10 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size || (sizeNew == size && BCAD < best)) { if (sizeNew == 0) return(0); best = BCAD; size = sizeNew; } #define CBAD 5 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size || (sizeNew == size && CBAD < best)) { if (sizeNew == 0) return(0); best = CBAD; size = sizeNew; } #define CABD 3 sizeNew = cuddSwapInPlace(table,x,y); if (sizeNew < size || (sizeNew == size && CABD < best)) { if (sizeNew == 0) return(0); best = CABD; size = sizeNew; } #define CADB 6 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size || (sizeNew == size && CADB < best)) { if (sizeNew == 0) return(0); best = CADB; size = sizeNew; } #define ACDB 4 sizeNew = cuddSwapInPlace(table,w,x); if (sizeNew < size || (sizeNew == size && ACDB < best)) { if (sizeNew == 0) return(0); best = ACDB; size = sizeNew; } #define ACBD 2 sizeNew = cuddSwapInPlace(table,y,z); if (sizeNew < size || (sizeNew == size && ACBD < best)) { if (sizeNew == 0) return(0); best = ACBD; size = sizeNew; } /* Now take the shortest route to the best permutation. ** The initial permutation is ACBD. */ switch(best) { case DBCA: if (!cuddSwapInPlace(table,y,z)) return(0); case BDCA: if (!cuddSwapInPlace(table,x,y)) return(0); case CDBA: if (!cuddSwapInPlace(table,w,x)) return(0); case ADBC: if (!cuddSwapInPlace(table,y,z)) return(0); case ABDC: if (!cuddSwapInPlace(table,x,y)) return(0); case ACDB: if (!cuddSwapInPlace(table,y,z)) return(0); case ACBD: break; case DCBA: if (!cuddSwapInPlace(table,y,z)) return(0); case BCDA: if (!cuddSwapInPlace(table,x,y)) return(0); case CBDA: if (!cuddSwapInPlace(table,w,x)) return(0); if (!cuddSwapInPlace(table,x,y)) return(0); if (!cuddSwapInPlace(table,y,z)) return(0); break; case DBAC: if (!cuddSwapInPlace(table,x,y)) return(0); case DCAB: if (!cuddSwapInPlace(table,w,x)) return(0); case DACB: if (!cuddSwapInPlace(table,y,z)) return(0); case BACD: if (!cuddSwapInPlace(table,x,y)) return(0); case CABD: if (!cuddSwapInPlace(table,w,x)) return(0); break; case DABC: if (!cuddSwapInPlace(table,y,z)) return(0); case BADC: if (!cuddSwapInPlace(table,x,y)) return(0); case CADB: if (!cuddSwapInPlace(table,w,x)) return(0); if (!cuddSwapInPlace(table,y,z)) return(0); break; case BDAC: if (!cuddSwapInPlace(table,x,y)) return(0); case CDAB: if (!cuddSwapInPlace(table,w,x)) return(0); case ADCB: if (!cuddSwapInPlace(table,y,z)) return(0); case ABCD: if (!cuddSwapInPlace(table,x,y)) return(0); break; case BCAD: if (!cuddSwapInPlace(table,x,y)) return(0); case CBAD: if (!cuddSwapInPlace(table,w,x)) return(0); if (!cuddSwapInPlace(table,x,y)) return(0); break; default: return(0); } #ifdef DD_DEBUG assert(table->keys - table->isolated == (unsigned) size); #endif return(best); } /* end of ddPermuteWindow4 */ /**Function******************************************************************** Synopsis [Reorders by applying a sliding window of width 4.] Description [Reorders by applying a sliding window of width 4. Tries all possible permutations to the variables in a window that slides from low to high. Assumes that no dead nodes are present. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddWindow4( DdManager * table, int low, int high) { int w; int res; #ifdef DD_DEBUG assert(low >= 0 && high < table->size); #endif if (high-low < 3) return(ddWindow3(table,low,high)); for (w = low; w+2 < high; w++) { res = ddPermuteWindow4(table,w); if (res == 0) return(0); #ifdef DD_STATS if (res == ABCD) { (void) fprintf(table->out,"="); } else { (void) fprintf(table->out,"-"); } fflush(table->out); #endif } return(1); } /* end of ddWindow4 */ /**Function******************************************************************** Synopsis [Reorders by repeatedly applying a sliding window of width 4.] Description [Reorders by repeatedly applying a sliding window of width 4. Tries all possible permutations to the variables in a window that slides from low to high. Assumes that no dead nodes are present. Uses an event-driven approach to determine convergence. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int ddWindowConv4( DdManager * table, int low, int high) { int x; int res; int nwin; int newevent; int *events; #ifdef DD_DEBUG assert(low >= 0 && high < table->size); #endif if (high-low < 3) return(ddWindowConv3(table,low,high)); nwin = high-low-2; events = ABC_ALLOC(int,nwin); if (events == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } for (x=0; x 2) events[x-3] = 1; newevent = 1; break; case BADC: if (x < nwin-3) events[x+3] = 1; if (x < nwin-1) events[x+1] = 1; if (x > 0) events[x-1] = 1; if (x > 2) events[x-3] = 1; newevent = 1; break; case ABDC: if (x < nwin-3) events[x+3] = 1; if (x > 0) events[x-1] = 1; newevent = 1; break; case ADBC: case ADCB: case ACDB: if (x < nwin-3) events[x+3] = 1; if (x < nwin-2) events[x+2] = 1; if (x > 0) events[x-1] = 1; if (x > 1) events[x-2] = 1; newevent = 1; break; case DACB: case DABC: case DBAC: case BDAC: case BDCA: case DBCA: case DCBA: case DCAB: case CDAB: case CDBA: case CBDA: case BCDA: case CADB: if (x < nwin-3) events[x+3] = 1; if (x < nwin-2) events[x+2] = 1; if (x < nwin-1) events[x+1] = 1; if (x > 0) events[x-1] = 1; if (x > 1) events[x-2] = 1; if (x > 2) events[x-3] = 1; newevent = 1; break; case BCAD: case CBAD: case CABD: if (x < nwin-2) events[x+2] = 1; if (x < nwin-1) events[x+1] = 1; if (x > 1) events[x-2] = 1; if (x > 2) events[x-3] = 1; newevent = 1; break; case ACBD: if (x < nwin-2) events[x+2] = 1; if (x > 1) events[x-2] = 1; newevent = 1; break; default: ABC_FREE(events); return(0); } events[x] = 0; #ifdef DD_STATS if (res == ABCD) { (void) fprintf(table->out,"="); } else { (void) fprintf(table->out,"-"); } fflush(table->out); #endif } } #ifdef DD_STATS if (newevent) { (void) fprintf(table->out,"|"); fflush(table->out); } #endif } while (newevent); ABC_FREE(events); return(1); } /* end of ddWindowConv4 */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddCount.c000066400000000000000000000247221300674244400242510ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddCount.c] PackageName [cudd] Synopsis [Procedures to count the number of minterms of a ZDD.] Description [External procedures included in this module:
        • Cudd_zddCount();
        • Cudd_zddCountDouble();
        Internal procedures included in this module:
        Static procedures included in this module:
        • cuddZddCountStep();
        • cuddZddCountDoubleStep();
        • st__zdd_count_dbl_free()
        • st__zdd_countfree()
        ] SeeAlso [] Author [Hyong-Kyoon Shin, In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddCount.c,v 1.14 2004/08/13 18:04:53 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int cuddZddCountStep (DdNode *P, st__table *table, DdNode *base, DdNode *empty); static double cuddZddCountDoubleStep (DdNode *P, st__table *table, DdNode *base, DdNode *empty); static enum st__retval st__zdd_countfree (char *key, char *value, char *arg); static enum st__retval st__zdd_count_dbl_free (char *key, char *value, char *arg); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Counts the number of minterms in a ZDD.] Description [Returns an integer representing the number of minterms in a ZDD.] SideEffects [None] SeeAlso [Cudd_zddCountDouble] ******************************************************************************/ int Cudd_zddCount( DdManager * zdd, DdNode * P) { st__table *table; int res; DdNode *base, *empty; base = DD_ONE(zdd); empty = DD_ZERO(zdd); table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) return(CUDD_OUT_OF_MEM); res = cuddZddCountStep(P, table, base, empty); if (res == CUDD_OUT_OF_MEM) { zdd->errorCode = CUDD_MEMORY_OUT; } st__foreach(table, st__zdd_countfree, NIL(char)); st__free_table(table); return(res); } /* end of Cudd_zddCount */ /**Function******************************************************************** Synopsis [Counts the number of minterms of a ZDD.] Description [Counts the number of minterms of a ZDD. The result is returned as a double. If the procedure runs out of memory, it returns (double) CUDD_OUT_OF_MEM. This procedure is used in Cudd_zddCountMinterm.] SideEffects [None] SeeAlso [Cudd_zddCountMinterm Cudd_zddCount] ******************************************************************************/ double Cudd_zddCountDouble( DdManager * zdd, DdNode * P) { st__table *table; double res; DdNode *base, *empty; base = DD_ONE(zdd); empty = DD_ZERO(zdd); table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) return((double)CUDD_OUT_OF_MEM); res = cuddZddCountDoubleStep(P, table, base, empty); if (res == (double)CUDD_OUT_OF_MEM) { zdd->errorCode = CUDD_MEMORY_OUT; } st__foreach(table, st__zdd_count_dbl_free, NIL(char)); st__free_table(table); return(res); } /* end of Cudd_zddCountDouble */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddCount.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddCountStep( DdNode * P, st__table * table, DdNode * base, DdNode * empty) { int res; int *dummy; if (P == empty) return(0); if (P == base) return(1); /* Check cache. */ if ( st__lookup(table, (const char *)P, (char **)&dummy)) { res = *dummy; return(res); } res = cuddZddCountStep(cuddE(P), table, base, empty) + cuddZddCountStep(cuddT(P), table, base, empty); dummy = ABC_ALLOC(int, 1); if (dummy == NULL) { return(CUDD_OUT_OF_MEM); } *dummy = res; if ( st__insert(table, (char *)P, (char *)dummy) == st__OUT_OF_MEM) { ABC_FREE(dummy); return(CUDD_OUT_OF_MEM); } return(res); } /* end of cuddZddCountStep */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddCountDouble.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static double cuddZddCountDoubleStep( DdNode * P, st__table * table, DdNode * base, DdNode * empty) { double res; double *dummy; if (P == empty) return((double)0.0); if (P == base) return((double)1.0); /* Check cache */ if ( st__lookup(table, (const char *)P, (char **)&dummy)) { res = *dummy; return(res); } res = cuddZddCountDoubleStep(cuddE(P), table, base, empty) + cuddZddCountDoubleStep(cuddT(P), table, base, empty); dummy = ABC_ALLOC(double, 1); if (dummy == NULL) { return((double)CUDD_OUT_OF_MEM); } *dummy = res; if ( st__insert(table, (char *)P, (char *)dummy) == st__OUT_OF_MEM) { ABC_FREE(dummy); return((double)CUDD_OUT_OF_MEM); } return(res); } /* end of cuddZddCountDoubleStep */ /**Function******************************************************************** Synopsis [Frees the memory associated with the computed table of Cudd_zddCount.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static enum st__retval st__zdd_countfree( char * key, char * value, char * arg) { int *d; d = (int *)value; ABC_FREE(d); return( st__CONTINUE); } /* end of st__zdd_countfree */ /**Function******************************************************************** Synopsis [Frees the memory associated with the computed table of Cudd_zddCountDouble.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static enum st__retval st__zdd_count_dbl_free( char * key, char * value, char * arg) { double *d; d = (double *)value; ABC_FREE(d); return( st__CONTINUE); } /* end of st__zdd_count_dbl_free */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddFuncs.c000066400000000000000000001313311300674244400242320ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddFuncs.c] PackageName [cudd] Synopsis [Functions to manipulate covers represented as ZDDs.] Description [External procedures included in this module:
        • Cudd_zddProduct();
        • Cudd_zddUnateProduct();
        • Cudd_zddWeakDiv();
        • Cudd_zddWeakDivF();
        • Cudd_zddDivide();
        • Cudd_zddDivideF();
        • Cudd_zddComplement();
        Internal procedures included in this module:
        • cuddZddProduct();
        • cuddZddUnateProduct();
        • cuddZddWeakDiv();
        • cuddZddWeakDivF();
        • cuddZddDivide();
        • cuddZddDivideF();
        • cuddZddGetCofactors3()
        • cuddZddGetCofactors2()
        • cuddZddComplement();
        • cuddZddGetPosVarIndex();
        • cuddZddGetNegVarIndex();
        • cuddZddGetPosVarLevel();
        • cuddZddGetNegVarLevel();
        Static procedures included in this module:
        ] SeeAlso [] Author [In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddFuncs.c,v 1.16 2008/04/25 07:39:33 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the product of two covers represented by ZDDs.] Description [Computes the product of two covers represented by ZDDs. The result is also a ZDD. Returns a pointer to the result if successful; NULL otherwise. The covers on which Cudd_zddProduct operates use two ZDD variables for each function variable (one ZDD variable for each literal of the variable). Those two ZDD variables should be adjacent in the order.] SideEffects [None] SeeAlso [Cudd_zddUnateProduct] ******************************************************************************/ DdNode * Cudd_zddProduct( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddZddProduct(dd, f, g); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddProduct */ /**Function******************************************************************** Synopsis [Computes the product of two unate covers.] Description [Computes the product of two unate covers represented as ZDDs. Unate covers use one ZDD variable for each BDD variable. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_zddProduct] ******************************************************************************/ DdNode * Cudd_zddUnateProduct( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddZddUnateProduct(dd, f, g); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddUnateProduct */ /**Function******************************************************************** Synopsis [Applies weak division to two covers.] Description [Applies weak division to two ZDDs representing two covers. Returns a pointer to the ZDD representing the result if successful; NULL otherwise. The result of weak division depends on the variable order. The covers on which Cudd_zddWeakDiv operates use two ZDD variables for each function variable (one ZDD variable for each literal of the variable). Those two ZDD variables should be adjacent in the order.] SideEffects [None] SeeAlso [Cudd_zddDivide] ******************************************************************************/ DdNode * Cudd_zddWeakDiv( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddZddWeakDiv(dd, f, g); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddWeakDiv */ /**Function******************************************************************** Synopsis [Computes the quotient of two unate covers.] Description [Computes the quotient of two unate covers represented by ZDDs. Unate covers use one ZDD variable for each BDD variable. Returns a pointer to the resulting ZDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_zddWeakDiv] ******************************************************************************/ DdNode * Cudd_zddDivide( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddZddDivide(dd, f, g); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddDivide */ /**Function******************************************************************** Synopsis [Modified version of Cudd_zddWeakDiv.] Description [Modified version of Cudd_zddWeakDiv. This function may disappear in future releases.] SideEffects [None] SeeAlso [Cudd_zddWeakDiv] ******************************************************************************/ DdNode * Cudd_zddWeakDivF( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddZddWeakDivF(dd, f, g); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddWeakDivF */ /**Function******************************************************************** Synopsis [Modified version of Cudd_zddDivide.] Description [Modified version of Cudd_zddDivide. This function may disappear in future releases.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_zddDivideF( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; do { dd->reordered = 0; res = cuddZddDivideF(dd, f, g); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddDivideF */ /**Function******************************************************************** Synopsis [Computes a complement cover for a ZDD node.] Description [Computes a complement cover for a ZDD node. For lack of a better method, we first extract the function BDD from the ZDD cover, then make the complement of the ZDD cover from the complement of the BDD node by using ISOP. Returns a pointer to the resulting cover if successful; NULL otherwise. The result depends on current variable order.] SideEffects [The result depends on current variable order.] SeeAlso [] ******************************************************************************/ DdNode * Cudd_zddComplement( DdManager *dd, DdNode *node) { DdNode *b, *isop, *zdd_I; /* Check cache */ zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); if (zdd_I) return(zdd_I); b = Cudd_MakeBddFromZddCover(dd, node); if (!b) return(NULL); Cudd_Ref(b); isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); if (!isop) { Cudd_RecursiveDeref(dd, b); return(NULL); } Cudd_Ref(isop); Cudd_Ref(zdd_I); Cudd_RecursiveDeref(dd, b); Cudd_RecursiveDeref(dd, isop); cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); Cudd_Deref(zdd_I); return(zdd_I); } /* end of Cudd_zddComplement */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddProduct.] Description [] SideEffects [None] SeeAlso [Cudd_zddProduct] ******************************************************************************/ DdNode * cuddZddProduct( DdManager * dd, DdNode * f, DdNode * g) { int v, top_f, top_g; DdNode *tmp, *term1, *term2, *term3; DdNode *f0, *f1, *fd, *g0, *g1, *gd; DdNode *R0, *R1, *Rd, *N0, *N1; DdNode *r; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); int flag; int pv, nv; statLine(dd); if (f == zero || g == zero) return(zero); if (f == one) return(g); if (g == one) return(f); top_f = dd->permZ[f->index]; top_g = dd->permZ[g->index]; if (top_f > top_g) return(cuddZddProduct(dd, g, f)); /* Check cache */ r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g); if (r) return(r); v = f->index; /* either yi or zi */ flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); Cudd_Ref(gd); pv = cuddZddGetPosVarIndex(dd, v); nv = cuddZddGetNegVarIndex(dd, v); Rd = cuddZddProduct(dd, fd, gd); if (Rd == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(Rd); term1 = cuddZddProduct(dd, f0, g0); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); return(NULL); } Cudd_Ref(term1); term2 = cuddZddProduct(dd, f0, gd); if (term2 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, term1); return(NULL); } Cudd_Ref(term2); term3 = cuddZddProduct(dd, fd, g0); if (term3 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); return(NULL); } Cudd_Ref(term3); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g0); tmp = cuddZddUnion(dd, term1, term2); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); Cudd_RecursiveDerefZdd(dd, term3); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); R0 = cuddZddUnion(dd, tmp, term3); if (R0 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, term3); Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(R0); Cudd_RecursiveDerefZdd(dd, tmp); Cudd_RecursiveDerefZdd(dd, term3); N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */ if (N0 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, Rd); Cudd_RecursiveDerefZdd(dd, R0); return(NULL); } Cudd_Ref(N0); Cudd_RecursiveDerefZdd(dd, R0); Cudd_RecursiveDerefZdd(dd, Rd); term1 = cuddZddProduct(dd, f1, g1); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, N0); return(NULL); } Cudd_Ref(term1); term2 = cuddZddProduct(dd, f1, gd); if (term2 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, term1); return(NULL); } Cudd_Ref(term2); term3 = cuddZddProduct(dd, fd, g1); if (term3 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, gd); Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); return(NULL); } Cudd_Ref(term3); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); tmp = cuddZddUnion(dd, term1, term2); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); Cudd_RecursiveDerefZdd(dd, term3); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); R1 = cuddZddUnion(dd, tmp, term3); if (R1 == NULL) { Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, term3); Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(R1); Cudd_RecursiveDerefZdd(dd, tmp); Cudd_RecursiveDerefZdd(dd, term3); N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */ if (N1 == NULL) { Cudd_RecursiveDerefZdd(dd, N0); Cudd_RecursiveDerefZdd(dd, R1); return(NULL); } Cudd_Ref(N1); Cudd_RecursiveDerefZdd(dd, R1); Cudd_RecursiveDerefZdd(dd, N0); cuddCacheInsert2(dd, cuddZddProduct, f, g, N1); Cudd_Deref(N1); return(N1); } /* end of cuddZddProduct */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddUnateProduct.] Description [] SideEffects [None] SeeAlso [Cudd_zddUnateProduct] ******************************************************************************/ DdNode * cuddZddUnateProduct( DdManager * dd, DdNode * f, DdNode * g) { int v, top_f, top_g; DdNode *term1, *term2, *term3, *term4; DdNode *sum1, *sum2; DdNode *f0, *f1, *g0, *g1; DdNode *r; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); int flag; statLine(dd); if (f == zero || g == zero) return(zero); if (f == one) return(g); if (g == one) return(f); top_f = dd->permZ[f->index]; top_g = dd->permZ[g->index]; if (top_f > top_g) return(cuddZddUnateProduct(dd, g, f)); /* Check cache */ r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g); if (r) return(r); v = f->index; /* either yi or zi */ flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); term1 = cuddZddUnateProduct(dd, f1, g1); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); return(NULL); } Cudd_Ref(term1); term2 = cuddZddUnateProduct(dd, f1, g0); if (term2 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, term1); return(NULL); } Cudd_Ref(term2); term3 = cuddZddUnateProduct(dd, f0, g1); if (term3 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); return(NULL); } Cudd_Ref(term3); term4 = cuddZddUnateProduct(dd, f0, g0); if (term4 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); Cudd_RecursiveDerefZdd(dd, term3); return(NULL); } Cudd_Ref(term4); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); sum1 = cuddZddUnion(dd, term1, term2); if (sum1 == NULL) { Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); Cudd_RecursiveDerefZdd(dd, term3); Cudd_RecursiveDerefZdd(dd, term4); return(NULL); } Cudd_Ref(sum1); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term2); sum2 = cuddZddUnion(dd, sum1, term3); if (sum2 == NULL) { Cudd_RecursiveDerefZdd(dd, term3); Cudd_RecursiveDerefZdd(dd, term4); Cudd_RecursiveDerefZdd(dd, sum1); return(NULL); } Cudd_Ref(sum2); Cudd_RecursiveDerefZdd(dd, sum1); Cudd_RecursiveDerefZdd(dd, term3); r = cuddZddGetNode(dd, v, sum2, term4); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, term4); Cudd_RecursiveDerefZdd(dd, sum2); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDerefZdd(dd, sum2); Cudd_RecursiveDerefZdd(dd, term4); cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r); Cudd_Deref(r); return(r); } /* end of cuddZddUnateProduct */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddWeakDiv.] Description [] SideEffects [None] SeeAlso [Cudd_zddWeakDiv] ******************************************************************************/ DdNode * cuddZddWeakDiv( DdManager * dd, DdNode * f, DdNode * g) { int v; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); DdNode *f0, *f1, *fd, *g0, *g1, *gd; DdNode *q, *tmp; DdNode *r; int flag; statLine(dd); if (g == one) return(f); if (f == zero || f == one) return(zero); if (f == g) return(one); /* Check cache. */ r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g); if (r) return(r); v = g->index; flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); Cudd_Ref(gd); q = g; if (g0 != zero) { q = cuddZddWeakDiv(dd, f0, g0); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(q); } else Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g0); if (q == zero) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); Cudd_Deref(q); return(zero); } if (g1 != zero) { Cudd_RecursiveDerefZdd(dd, q); tmp = cuddZddWeakDiv(dd, f1, g1); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); if (q == g) q = tmp; else { q = cuddZddIntersect(dd, q, tmp); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, tmp); } } else { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); } if (q == zero) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); Cudd_Deref(q); return(zero); } if (gd != zero) { Cudd_RecursiveDerefZdd(dd, q); tmp = cuddZddWeakDiv(dd, fd, gd); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); if (q == g) q = tmp; else { q = cuddZddIntersect(dd, q, tmp); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, tmp); } } else { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); } cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q); Cudd_Deref(q); return(q); } /* end of cuddZddWeakDiv */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddWeakDivF.] Description [] SideEffects [None] SeeAlso [Cudd_zddWeakDivF] ******************************************************************************/ DdNode * cuddZddWeakDivF( DdManager * dd, DdNode * f, DdNode * g) { int v, top_f, top_g, vf, vg; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); DdNode *f0, *f1, *fd, *g0, *g1, *gd; DdNode *q, *tmp; DdNode *r; DdNode *term1, *term0, *termd; int flag; int pv, nv; statLine(dd); if (g == one) return(f); if (f == zero || f == one) return(zero); if (f == g) return(one); /* Check cache. */ r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g); if (r) return(r); top_f = dd->permZ[f->index]; top_g = dd->permZ[g->index]; vf = top_f >> 1; vg = top_g >> 1; v = ddMin(top_f, top_g); if (v == top_f && vf < vg) { v = f->index; flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); pv = cuddZddGetPosVarIndex(dd, v); nv = cuddZddGetNegVarIndex(dd, v); term1 = cuddZddWeakDivF(dd, f1, g); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDerefZdd(dd, f1); term0 = cuddZddWeakDivF(dd, f0, g); if (term0 == NULL) { Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, term1); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDerefZdd(dd, f0); termd = cuddZddWeakDivF(dd, fd, g); if (termd == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term0); return(NULL); } Cudd_Ref(termd); Cudd_RecursiveDerefZdd(dd, fd); tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */ if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, term0); Cudd_RecursiveDerefZdd(dd, termd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, term0); Cudd_RecursiveDerefZdd(dd, termd); q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */ if (q == NULL) { Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, term1); Cudd_RecursiveDerefZdd(dd, tmp); cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); Cudd_Deref(q); return(q); } if (v == top_f) v = f->index; else v = g->index; flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); Cudd_Ref(gd); q = g; if (g0 != zero) { q = cuddZddWeakDivF(dd, f0, g0); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(q); } else Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g0); if (q == zero) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); Cudd_Deref(q); return(zero); } if (g1 != zero) { Cudd_RecursiveDerefZdd(dd, q); tmp = cuddZddWeakDivF(dd, f1, g1); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); if (q == g) q = tmp; else { q = cuddZddIntersect(dd, q, tmp); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, tmp); } } else { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, g1); } if (q == zero) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); Cudd_Deref(q); return(zero); } if (gd != zero) { Cudd_RecursiveDerefZdd(dd, q); tmp = cuddZddWeakDivF(dd, fd, gd); if (tmp == NULL) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); return(NULL); } Cudd_Ref(tmp); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); if (q == g) q = tmp; else { q = cuddZddIntersect(dd, q, tmp); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, tmp); return(NULL); } Cudd_Ref(q); Cudd_RecursiveDerefZdd(dd, tmp); } } else { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDerefZdd(dd, gd); } cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); Cudd_Deref(q); return(q); } /* end of cuddZddWeakDivF */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddDivide.] Description [] SideEffects [None] SeeAlso [Cudd_zddDivide] ******************************************************************************/ DdNode * cuddZddDivide( DdManager * dd, DdNode * f, DdNode * g) { int v; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); DdNode *f0, *f1, *g0, *g1; DdNode *q, *r, *tmp; int flag; statLine(dd); if (g == one) return(f); if (f == zero || f == one) return(zero); if (f == g) return(one); /* Check cache. */ r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g); if (r) return(r); v = g->index; flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); r = cuddZddDivide(dd, f1, g1); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); return(NULL); } Cudd_Ref(r); if (r != zero && g0 != zero) { tmp = r; q = cuddZddDivide(dd, f0, g0); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); return(NULL); } Cudd_Ref(q); r = cuddZddIntersect(dd, r, q); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, q); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDerefZdd(dd, q); Cudd_RecursiveDerefZdd(dd, tmp); } Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); cuddCacheInsert2(dd, cuddZddDivide, f, g, r); Cudd_Deref(r); return(r); } /* end of cuddZddDivide */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddDivideF.] Description [] SideEffects [None] SeeAlso [Cudd_zddDivideF] ******************************************************************************/ DdNode * cuddZddDivideF( DdManager * dd, DdNode * f, DdNode * g) { int v; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); DdNode *f0, *f1, *g0, *g1; DdNode *q, *r, *tmp; int flag; statLine(dd); if (g == one) return(f); if (f == zero || f == one) return(zero); if (f == g) return(one); /* Check cache. */ r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g); if (r) return(r); v = g->index; flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); if (flag == 1) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ if (flag == 1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); return(NULL); } Cudd_Ref(g1); Cudd_Ref(g0); r = cuddZddDivideF(dd, f1, g1); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); return(NULL); } Cudd_Ref(r); if (r != zero && g0 != zero) { tmp = r; q = cuddZddDivideF(dd, f0, g0); if (q == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); return(NULL); } Cudd_Ref(q); r = cuddZddIntersect(dd, r, q); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); Cudd_RecursiveDerefZdd(dd, q); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDerefZdd(dd, q); Cudd_RecursiveDerefZdd(dd, tmp); } Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, g1); Cudd_RecursiveDerefZdd(dd, g0); cuddCacheInsert2(dd, cuddZddDivideF, f, g, r); Cudd_Deref(r); return(r); } /* end of cuddZddDivideF */ /**Function******************************************************************** Synopsis [Computes the three-way decomposition of f w.r.t. v.] Description [Computes the three-way decomposition of function f (represented by a ZDD) wit respect to variable v. Returns 0 if successful; 1 otherwise.] SideEffects [The results are returned in f1, f0, and fd.] SeeAlso [cuddZddGetCofactors2] ******************************************************************************/ int cuddZddGetCofactors3( DdManager * dd, DdNode * f, int v, DdNode ** f1, DdNode ** f0, DdNode ** fd) { DdNode *pc, *nc; DdNode *zero = DD_ZERO(dd); int top, hv, ht, pv, nv; int level; top = dd->permZ[f->index]; level = dd->permZ[v]; hv = level >> 1; ht = top >> 1; if (hv < ht) { *f1 = zero; *f0 = zero; *fd = f; } else { pv = cuddZddGetPosVarIndex(dd, v); nv = cuddZddGetNegVarIndex(dd, v); /* not to create intermediate ZDD node */ if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) { pc = cuddZddSubset1(dd, f, pv); if (pc == NULL) return(1); Cudd_Ref(pc); nc = cuddZddSubset0(dd, f, pv); if (nc == NULL) { Cudd_RecursiveDerefZdd(dd, pc); return(1); } Cudd_Ref(nc); *f1 = cuddZddSubset0(dd, pc, nv); if (*f1 == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); return(1); } Cudd_Ref(*f1); *f0 = cuddZddSubset1(dd, nc, nv); if (*f0 == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_RecursiveDerefZdd(dd, *f1); return(1); } Cudd_Ref(*f0); *fd = cuddZddSubset0(dd, nc, nv); if (*fd == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_RecursiveDerefZdd(dd, *f1); Cudd_RecursiveDerefZdd(dd, *f0); return(1); } Cudd_Ref(*fd); } else { pc = cuddZddSubset1(dd, f, nv); if (pc == NULL) return(1); Cudd_Ref(pc); nc = cuddZddSubset0(dd, f, nv); if (nc == NULL) { Cudd_RecursiveDerefZdd(dd, pc); return(1); } Cudd_Ref(nc); *f0 = cuddZddSubset0(dd, pc, pv); if (*f0 == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); return(1); } Cudd_Ref(*f0); *f1 = cuddZddSubset1(dd, nc, pv); if (*f1 == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_RecursiveDerefZdd(dd, *f0); return(1); } Cudd_Ref(*f1); *fd = cuddZddSubset0(dd, nc, pv); if (*fd == NULL) { Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_RecursiveDerefZdd(dd, *f1); Cudd_RecursiveDerefZdd(dd, *f0); return(1); } Cudd_Ref(*fd); } Cudd_RecursiveDerefZdd(dd, pc); Cudd_RecursiveDerefZdd(dd, nc); Cudd_Deref(*f1); Cudd_Deref(*f0); Cudd_Deref(*fd); } return(0); } /* end of cuddZddGetCofactors3 */ /**Function******************************************************************** Synopsis [Computes the two-way decomposition of f w.r.t. v.] Description [] SideEffects [The results are returned in f1 and f0.] SeeAlso [cuddZddGetCofactors3] ******************************************************************************/ int cuddZddGetCofactors2( DdManager * dd, DdNode * f, int v, DdNode ** f1, DdNode ** f0) { *f1 = cuddZddSubset1(dd, f, v); if (*f1 == NULL) return(1); *f0 = cuddZddSubset0(dd, f, v); if (*f0 == NULL) { Cudd_RecursiveDerefZdd(dd, *f1); return(1); } return(0); } /* end of cuddZddGetCofactors2 */ /**Function******************************************************************** Synopsis [Computes a complement of a ZDD node.] Description [Computes the complement of a ZDD node. So far, since we couldn't find a direct way to get the complement of a ZDD cover, we first convert a ZDD cover to a BDD, then make the complement of the ZDD cover from the complement of the BDD node by using ISOP.] SideEffects [The result depends on current variable order.] SeeAlso [] ******************************************************************************/ DdNode * cuddZddComplement( DdManager * dd, DdNode *node) { DdNode *b, *isop, *zdd_I; /* Check cache */ zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); if (zdd_I) return(zdd_I); b = cuddMakeBddFromZddCover(dd, node); if (!b) return(NULL); cuddRef(b); isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); if (!isop) { Cudd_RecursiveDeref(dd, b); return(NULL); } cuddRef(isop); cuddRef(zdd_I); Cudd_RecursiveDeref(dd, b); Cudd_RecursiveDeref(dd, isop); cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); cuddDeref(zdd_I); return(zdd_I); } /* end of cuddZddComplement */ /**Function******************************************************************** Synopsis [Returns the index of positive ZDD variable.] Description [Returns the index of positive ZDD variable.] SideEffects [] SeeAlso [] ******************************************************************************/ int cuddZddGetPosVarIndex( DdManager * dd, int index) { int pv = (index >> 1) << 1; return(pv); } /* end of cuddZddGetPosVarIndex */ /**Function******************************************************************** Synopsis [Returns the index of negative ZDD variable.] Description [Returns the index of negative ZDD variable.] SideEffects [] SeeAlso [] ******************************************************************************/ int cuddZddGetNegVarIndex( DdManager * dd, int index) { int nv = index | 0x1; return(nv); } /* end of cuddZddGetPosVarIndex */ /**Function******************************************************************** Synopsis [Returns the level of positive ZDD variable.] Description [Returns the level of positive ZDD variable.] SideEffects [] SeeAlso [] ******************************************************************************/ int cuddZddGetPosVarLevel( DdManager * dd, int index) { int pv = cuddZddGetPosVarIndex(dd, index); return(dd->permZ[pv]); } /* end of cuddZddGetPosVarLevel */ /**Function******************************************************************** Synopsis [Returns the level of negative ZDD variable.] Description [Returns the level of negative ZDD variable.] SideEffects [] SeeAlso [] ******************************************************************************/ int cuddZddGetNegVarLevel( DdManager * dd, int index) { int nv = cuddZddGetNegVarIndex(dd, index); return(dd->permZ[nv]); } /* end of cuddZddGetNegVarLevel */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddGroup.c000066400000000000000000001235001300674244400242470ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddGroup.c] PackageName [cudd] Synopsis [Functions for ZDD group sifting.] Description [External procedures included in this file:
        • Cudd_MakeZddTreeNode()
        Internal procedures included in this file:
        • cuddZddTreeSifting()
        Static procedures included in this module:
        • zddTreeSiftingAux()
        • zddCountInternalMtrNodes()
        • zddReorderChildren()
        • zddFindNodeHiLo()
        • zddUniqueCompareGroup()
        • zddGroupSifting()
        • zddGroupSiftingAux()
        • zddGroupSiftingUp()
        • zddGroupSiftingDown()
        • zddGroupMove()
        • zddGroupMoveBackward()
        • zddGroupSiftingBackward()
        • zddMergeGroups()
        ] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.20 2009/02/19 16:25:36 fabio Exp $"; #endif static int *entry; extern int zddTotalNumberSwapping; #ifdef DD_STATS static int extsymmcalls; static int extsymm; static int secdiffcalls; static int secdiff; static int secdiffmisfire; #endif #ifdef DD_DEBUG static int pr = 0; /* flag to enable printing while debugging */ /* by depositing a 1 into it */ #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int zddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method); #ifdef DD_STATS static int zddCountInternalMtrNodes (DdManager *table, MtrNode *treenode); #endif static int zddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method); static void zddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper); static int zddUniqueCompareGroup (int *ptrX, int *ptrY); static int zddGroupSifting (DdManager *table, int lower, int upper); static int zddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh); static int zddGroupSiftingUp (DdManager *table, int y, int xLow, Move **moves); static int zddGroupSiftingDown (DdManager *table, int x, int xHigh, Move **moves); static int zddGroupMove (DdManager *table, int x, int y, Move **moves); static int zddGroupMoveBackward (DdManager *table, int x, int y); static int zddGroupSiftingBackward (DdManager *table, Move *moves, int size); static void zddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Creates a new ZDD variable group.] Description [Creates a new ZDD variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.] SideEffects [The ZDD variable tree is changed.] SeeAlso [Cudd_MakeTreeNode] ******************************************************************************/ MtrNode * Cudd_MakeZddTreeNode( DdManager * dd /* manager */, unsigned int low /* index of the first group variable */, unsigned int size /* number of variables in the group */, unsigned int type /* MTR_DEFAULT or MTR_FIXED */) { MtrNode *group; MtrNode *tree; unsigned int level; /* If the variable does not exist yet, the position is assumed to be ** the same as the index. Therefore, applications that rely on ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new ** variables have to create the variables before they group them. */ level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low; if (level + size - 1> (int) MTR_MAXHIGH) return(NULL); /* If the tree does not exist yet, create it. */ tree = dd->treeZ; if (tree == NULL) { dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ); if (tree == NULL) return(NULL); tree->index = dd->invpermZ[0]; } /* Extend the upper bound of the tree if necessary. This allows the ** application to create groups even before the variables are created. */ tree->size = ddMax(tree->size, level + size); /* Create the group. */ group = Mtr_MakeGroup(tree, level, size, type); if (group == NULL) return(NULL); /* Initialize the index field to the index of the variable currently ** in position low. This field will be updated by the reordering ** procedure to provide a handle to the group once it has been moved. */ group->index = (MtrHalfWord) low; return(group); } /* end of Cudd_MakeZddTreeNode */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Tree sifting algorithm for ZDDs.] Description [Tree sifting algorithm for ZDDs. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling zddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ int cuddZddTreeSifting( DdManager * table /* DD table */, Cudd_ReorderingType method /* reordering method for the groups of leaves */) { int i; int nvars; int result; int tempTree; /* If no tree is provided we create a temporary one in which all ** variables are in a single group. After reordering this tree is ** destroyed. */ tempTree = table->treeZ == NULL; if (tempTree) { table->treeZ = Mtr_InitGroupTree(0,table->sizeZ); table->treeZ->index = table->invpermZ[0]; } nvars = table->sizeZ; #ifdef DD_DEBUG if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddZddTreeSifting:"); Mtr_PrintGroups(table->treeZ,pr <= 0); #endif #if 0 /* Debugging code. */ if (table->tree && table->treeZ) { (void) fprintf(table->out,"\n"); Mtr_PrintGroups(table->tree, 0); cuddPrintVarGroups(table,table->tree,0,0); for (i = 0; i < table->size; i++) { (void) fprintf(table->out,"%s%d", (i == 0) ? "" : ",", table->invperm[i]); } (void) fprintf(table->out,"\n"); for (i = 0; i < table->size; i++) { (void) fprintf(table->out,"%s%d", (i == 0) ? "" : ",", table->perm[i]); } (void) fprintf(table->out,"\n\n"); Mtr_PrintGroups(table->treeZ,0); cuddPrintVarGroups(table,table->treeZ,1,0); for (i = 0; i < table->sizeZ; i++) { (void) fprintf(table->out,"%s%d", (i == 0) ? "" : ",", table->invpermZ[i]); } (void) fprintf(table->out,"\n"); for (i = 0; i < table->sizeZ; i++) { (void) fprintf(table->out,"%s%d", (i == 0) ? "" : ",", table->permZ[i]); } (void) fprintf(table->out,"\n"); } /* End of debugging code. */ #endif #ifdef DD_STATS extsymmcalls = 0; extsymm = 0; secdiffcalls = 0; secdiff = 0; secdiffmisfire = 0; (void) fprintf(table->out,"\n"); if (!tempTree) (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", zddCountInternalMtrNodes(table,table->treeZ)); #endif /* Initialize the group of each subtable to itself. Initially ** there are no groups. Groups are created according to the tree ** structure in postorder fashion. */ for (i = 0; i < nvars; i++) table->subtableZ[i].next = i; /* Reorder. */ result = zddTreeSiftingAux(table, table->treeZ, method); #ifdef DD_STATS /* print stats */ if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && (table->groupcheck == CUDD_GROUP_CHECK7 || table->groupcheck == CUDD_GROUP_CHECK5)) { (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); (void) fprintf(table->out,"extsymm = %d",extsymm); } if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && table->groupcheck == CUDD_GROUP_CHECK7) { (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); (void) fprintf(table->out,"secdiff = %d\n",secdiff); (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); } #endif if (tempTree) Cudd_FreeZddTree(table); return(result); } /* end of cuddZddTreeSifting */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Visits the group tree and reorders each group.] Description [Recursively visits the group tree and reorders each group in postorder fashion. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddTreeSiftingAux( DdManager * table, MtrNode * treenode, Cudd_ReorderingType method) { MtrNode *auxnode; int res; #ifdef DD_DEBUG Mtr_PrintGroups(treenode,1); #endif auxnode = treenode; while (auxnode != NULL) { if (auxnode->child != NULL) { if (!zddTreeSiftingAux(table, auxnode->child, method)) return(0); res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); if (res == 0) return(0); } else if (auxnode->size > 1) { if (!zddReorderChildren(table, auxnode, method)) return(0); } auxnode = auxnode->younger; } return(1); } /* end of zddTreeSiftingAux */ #ifdef DD_STATS /**Function******************************************************************** Synopsis [Counts the number of internal nodes of the group tree.] Description [Counts the number of internal nodes of the group tree. Returns the count.] SideEffects [None] ******************************************************************************/ static int zddCountInternalMtrNodes( DdManager * table, MtrNode * treenode) { MtrNode *auxnode; int count,nodeCount; nodeCount = 0; auxnode = treenode; while (auxnode != NULL) { if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { nodeCount++; count = zddCountInternalMtrNodes(table,auxnode->child); nodeCount += count; } auxnode = auxnode->younger; } return(nodeCount); } /* end of zddCountInternalMtrNodes */ #endif /**Function******************************************************************** Synopsis [Reorders the children of a group tree node according to the options.] Description [Reorders the children of a group tree node according to the options. After reordering puts all the variables in the group and/or its descendents in a single group. This allows hierarchical reordering. If the variables in the group do not exist yet, simply does nothing. Returns 1 if successful; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddReorderChildren( DdManager * table, MtrNode * treenode, Cudd_ReorderingType method) { int lower; int upper = -1; int result; unsigned int initialSize; zddFindNodeHiLo(table,treenode,&lower,&upper); /* If upper == -1 these variables do not exist yet. */ if (upper == -1) return(1); if (treenode->flags == MTR_FIXED) { result = 1; } else { #ifdef DD_STATS (void) fprintf(table->out," "); #endif switch (method) { case CUDD_REORDER_RANDOM: case CUDD_REORDER_RANDOM_PIVOT: result = cuddZddSwapping(table,lower,upper,method); break; case CUDD_REORDER_SIFT: result = cuddZddSifting(table,lower,upper); break; case CUDD_REORDER_SIFT_CONVERGE: do { initialSize = table->keysZ; result = cuddZddSifting(table,lower,upper); if (initialSize <= table->keysZ) break; #ifdef DD_STATS else (void) fprintf(table->out,"\n"); #endif } while (result != 0); break; case CUDD_REORDER_SYMM_SIFT: result = cuddZddSymmSifting(table,lower,upper); break; case CUDD_REORDER_SYMM_SIFT_CONV: result = cuddZddSymmSiftingConv(table,lower,upper); break; case CUDD_REORDER_GROUP_SIFT: result = zddGroupSifting(table,lower,upper); break; case CUDD_REORDER_LINEAR: result = cuddZddLinearSifting(table,lower,upper); break; case CUDD_REORDER_LINEAR_CONVERGE: do { initialSize = table->keysZ; result = cuddZddLinearSifting(table,lower,upper); if (initialSize <= table->keysZ) break; #ifdef DD_STATS else (void) fprintf(table->out,"\n"); #endif } while (result != 0); break; default: return(0); } } /* Create a single group for all the variables that were sifted, ** so that they will be treated as a single block by successive ** invocations of zddGroupSifting. */ zddMergeGroups(table,treenode,lower,upper); #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:"); #endif return(result); } /* end of zddReorderChildren */ /**Function******************************************************************** Synopsis [Finds the lower and upper bounds of the group represented by treenode.] Description [Finds the lower and upper bounds of the group represented by treenode. The high and low fields of treenode are indices. From those we need to derive the current positions, and find maximum and minimum.] SideEffects [The bounds are returned as side effects.] SeeAlso [] ******************************************************************************/ static void zddFindNodeHiLo( DdManager * table, MtrNode * treenode, int * lower, int * upper) { int low; int high; /* Check whether no variables in this group already exist. ** If so, return immediately. The calling procedure will know from ** the values of upper that no reordering is needed. */ if ((int) treenode->low >= table->sizeZ) { *lower = table->sizeZ; *upper = -1; return; } *lower = low = (unsigned int) table->permZ[treenode->index]; high = (int) (low + treenode->size - 1); if (high >= table->sizeZ) { /* This is the case of a partially existing group. The aim is to ** reorder as many variables as safely possible. If the tree ** node is terminal, we just reorder the subset of the group ** that is currently in existence. If the group has ** subgroups, then we only reorder those subgroups that are ** fully instantiated. This way we avoid breaking up a group. */ MtrNode *auxnode = treenode->child; if (auxnode == NULL) { *upper = (unsigned int) table->sizeZ - 1; } else { /* Search the subgroup that strands the table->sizeZ line. ** If the first group starts at 0 and goes past table->sizeZ ** upper will get -1, thus correctly signaling that no reordering ** should take place. */ while (auxnode != NULL) { int thisLower = table->permZ[auxnode->low]; int thisUpper = thisLower + auxnode->size - 1; if (thisUpper >= table->sizeZ && thisLower < table->sizeZ) *upper = (unsigned int) thisLower - 1; auxnode = auxnode->younger; } } } else { /* Normal case: All the variables of the group exist. */ *upper = (unsigned int) high; } #ifdef DD_DEBUG /* Make sure that all variables in group are contiguous. */ assert(treenode->size >= *upper - *lower + 1); #endif return; } /* end of zddFindNodeHiLo */ /**Function******************************************************************** Synopsis [Comparison function used by qsort.] Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.] SideEffects [None] ******************************************************************************/ static int zddUniqueCompareGroup( int * ptrX, int * ptrY) { #if 0 if (entry[*ptrY] == entry[*ptrX]) { return((*ptrX) - (*ptrY)); } #endif return(entry[*ptrY] - entry[*ptrX]); } /* end of zddUniqueCompareGroup */ /**Function******************************************************************** Synopsis [Sifts from treenode->low to treenode->high.] Description [Sifts from treenode->low to treenode->high. If croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the end of the initial sifting. If a group is created, it is then sifted again. After sifting one variable, the group that contains it is dissolved. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddGroupSifting( DdManager * table, int lower, int upper) { int *var; int i,j,x,xInit; int nvars; int classes; int result; int *sifted; #ifdef DD_STATS unsigned previousSize; #endif int xindex; nvars = table->sizeZ; /* Order variables to sift. */ entry = NULL; sifted = NULL; var = ABC_ALLOC(int,nvars); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto zddGroupSiftingOutOfMem; } entry = ABC_ALLOC(int,nvars); if (entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto zddGroupSiftingOutOfMem; } sifted = ABC_ALLOC(int,nvars); if (sifted == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto zddGroupSiftingOutOfMem; } /* Here we consider only one representative for each group. */ for (i = 0, classes = 0; i < nvars; i++) { sifted[i] = 0; x = table->permZ[i]; if ((unsigned) x >= table->subtableZ[x].next) { entry[i] = table->subtableZ[x].keys; var[classes] = i; classes++; } } qsort((void *)var,classes,sizeof(int),(DD_QSFP)zddUniqueCompareGroup); /* Now sift. */ for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { if (zddTotalNumberSwapping >= table->siftMaxSwap) break; xindex = var[i]; if (sifted[xindex] == 1) /* variable already sifted as part of group */ continue; x = table->permZ[xindex]; /* find current level of this variable */ if (x < lower || x > upper) continue; #ifdef DD_STATS previousSize = table->keysZ; #endif #ifdef DD_DEBUG /* x is bottom of group */ assert((unsigned) x >= table->subtableZ[x].next); #endif result = zddGroupSiftingAux(table,x,lower,upper); if (!result) goto zddGroupSiftingOutOfMem; #ifdef DD_STATS if (table->keysZ < previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > previousSize) { (void) fprintf(table->out,"+"); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif /* Mark variables in the group just sifted. */ x = table->permZ[xindex]; if ((unsigned) x != table->subtableZ[x].next) { xInit = x; do { j = table->invpermZ[x]; sifted[j] = 1; x = table->subtableZ[x].next; } while (x != xInit); } #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:"); #endif } /* for */ ABC_FREE(sifted); ABC_FREE(var); ABC_FREE(entry); return(1); zddGroupSiftingOutOfMem: if (entry != NULL) ABC_FREE(entry); if (var != NULL) ABC_FREE(var); if (sifted != NULL) ABC_FREE(sifted); return(0); } /* end of zddGroupSifting */ /**Function******************************************************************** Synopsis [Sifts one variable up and down until it has taken all positions. Checks for aggregation.] Description [Sifts one variable up and down until it has taken all positions. Checks for aggregation. There may be at most two sweeps, even if the group grows. Assumes that x is either an isolated variable, or it is the bottom of a group. All groups may not have been found. The variable being moved is returned to the best position seen during sifting. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddGroupSiftingAux( DdManager * table, int x, int xLow, int xHigh) { Move *move; Move *moves; /* list of moves */ int initialSize; int result; #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh); assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */ #endif initialSize = table->keysZ; moves = NULL; if (x == xLow) { /* Sift down */ #ifdef DD_DEBUG /* x must be a singleton */ assert((unsigned) x == table->subtableZ[x].next); #endif if (x == xHigh) return(1); /* just one variable */ if (!zddGroupSiftingDown(table,x,xHigh,&moves)) goto zddGroupSiftingAuxOutOfMem; /* at this point x == xHigh, unless early term */ /* move backward and stop at best position */ result = zddGroupSiftingBackward(table,moves,initialSize); #ifdef DD_DEBUG assert(table->keysZ <= (unsigned) initialSize); #endif if (!result) goto zddGroupSiftingAuxOutOfMem; } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */ #ifdef DD_DEBUG /* x is bottom of group */ assert((unsigned) x >= table->subtableZ[x].next); #endif /* Find top of x's group */ x = table->subtableZ[x].next; if (!zddGroupSiftingUp(table,x,xLow,&moves)) goto zddGroupSiftingAuxOutOfMem; /* at this point x == xLow, unless early term */ /* move backward and stop at best position */ result = zddGroupSiftingBackward(table,moves,initialSize); #ifdef DD_DEBUG assert(table->keysZ <= (unsigned) initialSize); #endif if (!result) goto zddGroupSiftingAuxOutOfMem; } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ if (!zddGroupSiftingDown(table,x,xHigh,&moves)) goto zddGroupSiftingAuxOutOfMem; /* at this point x == xHigh, unless early term */ /* Find top of group */ if (moves) { x = moves->y; } while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; x = table->subtableZ[x].next; #ifdef DD_DEBUG /* x should be the top of a group */ assert((unsigned) x <= table->subtableZ[x].next); #endif if (!zddGroupSiftingUp(table,x,xLow,&moves)) goto zddGroupSiftingAuxOutOfMem; /* move backward and stop at best position */ result = zddGroupSiftingBackward(table,moves,initialSize); #ifdef DD_DEBUG assert(table->keysZ <= (unsigned) initialSize); #endif if (!result) goto zddGroupSiftingAuxOutOfMem; } else { /* moving up first: shorter */ /* Find top of x's group */ x = table->subtableZ[x].next; if (!zddGroupSiftingUp(table,x,xLow,&moves)) goto zddGroupSiftingAuxOutOfMem; /* at this point x == xHigh, unless early term */ if (moves) { x = moves->x; } while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; #ifdef DD_DEBUG /* x is bottom of a group */ assert((unsigned) x >= table->subtableZ[x].next); #endif if (!zddGroupSiftingDown(table,x,xHigh,&moves)) goto zddGroupSiftingAuxOutOfMem; /* move backward and stop at best position */ result = zddGroupSiftingBackward(table,moves,initialSize); #ifdef DD_DEBUG assert(table->keysZ <= (unsigned) initialSize); #endif if (!result) goto zddGroupSiftingAuxOutOfMem; } while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(1); zddGroupSiftingAuxOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(0); } /* end of zddGroupSiftingAux */ /**Function******************************************************************** Synopsis [Sifts up a variable until either it reaches position xLow or the size of the DD heap increases too much.] Description [Sifts up a variable until either it reaches position xLow or the size of the DD heap increases too much. Assumes that y is the top of a group (or a singleton). Checks y for aggregation to the adjacent variables. Records all the moves that are appended to the list of moves received as input and returned as a side effect. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddGroupSiftingUp( DdManager * table, int y, int xLow, Move ** moves) { Move *move; int x; int size; int gxtop; int limitSize; limitSize = table->keysZ; x = cuddZddNextLow(table,y); while (x >= xLow) { gxtop = table->subtableZ[x].next; if (table->subtableZ[x].next == (unsigned) x && table->subtableZ[y].next == (unsigned) y) { /* x and y are self groups */ size = cuddZddSwapInPlace(table,x,y); #ifdef DD_DEBUG assert(table->subtableZ[x].next == (unsigned) x); assert(table->subtableZ[y].next == (unsigned) y); #endif if (size == 0) goto zddGroupSiftingUpOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto zddGroupSiftingUpOutOfMem; move->x = x; move->y = y; move->flags = MTR_DEFAULT; move->size = size; move->next = *moves; *moves = move; #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n"); #endif if ((double) size > (double) limitSize * table->maxGrowth) return(1); if (size < limitSize) limitSize = size; } else { /* group move */ size = zddGroupMove(table,x,y,moves); if (size == 0) goto zddGroupSiftingUpOutOfMem; if ((double) size > (double) limitSize * table->maxGrowth) return(1); if (size < limitSize) limitSize = size; } y = gxtop; x = cuddZddNextLow(table,y); } return(1); zddGroupSiftingUpOutOfMem: while (*moves != NULL) { move = (*moves)->next; cuddDeallocMove(table, *moves); *moves = move; } return(0); } /* end of zddGroupSiftingUp */ /**Function******************************************************************** Synopsis [Sifts down a variable until it reaches position xHigh.] Description [Sifts down a variable until it reaches position xHigh. Assumes that x is the bottom of a group (or a singleton). Records all the moves. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddGroupSiftingDown( DdManager * table, int x, int xHigh, Move ** moves) { Move *move; int y; int size; int limitSize; int gybot; /* Initialize R */ limitSize = size = table->keysZ; y = cuddZddNextHigh(table,x); while (y <= xHigh) { /* Find bottom of y group. */ gybot = table->subtableZ[y].next; while (table->subtableZ[gybot].next != (unsigned) y) gybot = table->subtableZ[gybot].next; if (table->subtableZ[x].next == (unsigned) x && table->subtableZ[y].next == (unsigned) y) { /* x and y are self groups */ size = cuddZddSwapInPlace(table,x,y); #ifdef DD_DEBUG assert(table->subtableZ[x].next == (unsigned) x); assert(table->subtableZ[y].next == (unsigned) y); #endif if (size == 0) goto zddGroupSiftingDownOutOfMem; /* Record move. */ move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto zddGroupSiftingDownOutOfMem; move->x = x; move->y = y; move->flags = MTR_DEFAULT; move->size = size; move->next = *moves; *moves = move; #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n"); #endif if ((double) size > (double) limitSize * table->maxGrowth) return(1); if (size < limitSize) limitSize = size; x = y; y = cuddZddNextHigh(table,x); } else { /* Group move */ size = zddGroupMove(table,x,y,moves); if (size == 0) goto zddGroupSiftingDownOutOfMem; if ((double) size > (double) limitSize * table->maxGrowth) return(1); if (size < limitSize) limitSize = size; } x = gybot; y = cuddZddNextHigh(table,x); } return(1); zddGroupSiftingDownOutOfMem: while (*moves != NULL) { move = (*moves)->next; cuddDeallocMove(table, *moves); *moves = move; } return(0); } /* end of zddGroupSiftingDown */ /**Function******************************************************************** Synopsis [Swaps two groups and records the move.] Description [Swaps two groups and records the move. Returns the number of keys in the DD table in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddGroupMove( DdManager * table, int x, int y, Move ** moves) { Move *move; int size; int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; int swapx=-1,swapy=-1; #if defined(DD_DEBUG) && defined(DD_VERBOSE) int initialSize,bestSize; #endif #ifdef DD_DEBUG /* We assume that x < y */ assert(x < y); #endif /* Find top, bottom, and size for the two groups. */ xbot = x; xtop = table->subtableZ[x].next; xsize = xbot - xtop + 1; ybot = y; while ((unsigned) ybot < table->subtableZ[ybot].next) ybot = table->subtableZ[ybot].next; ytop = y; ysize = ybot - ytop + 1; #if defined(DD_DEBUG) && defined(DD_VERBOSE) initialSize = bestSize = table->keysZ; #endif /* Sift the variables of the second group up through the first group */ for (i = 1; i <= ysize; i++) { for (j = 1; j <= xsize; j++) { size = cuddZddSwapInPlace(table,x,y); if (size == 0) goto zddGroupMoveOutOfMem; #if defined(DD_DEBUG) && defined(DD_VERBOSE) if (size < bestSize) bestSize = size; #endif swapx = x; swapy = y; y = x; x = cuddZddNextLow(table,y); } y = ytop + i; x = cuddZddNextLow(table,y); } #if defined(DD_DEBUG) && defined(DD_VERBOSE) if ((bestSize < initialSize) && (bestSize < size)) (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); #endif /* fix groups */ y = xtop; /* ytop is now where xtop used to be */ for (i = 0; i < ysize - 1; i++) { table->subtableZ[y].next = cuddZddNextHigh(table,y); y = cuddZddNextHigh(table,y); } table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ /* it to top of its group */ x = cuddZddNextHigh(table,y); newxtop = x; for (i = 0; i < xsize - 1; i++) { table->subtableZ[x].next = cuddZddNextHigh(table,x); x = cuddZddNextHigh(table,x); } table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ /* it to top of its group */ #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n"); #endif /* Store group move */ move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto zddGroupMoveOutOfMem; move->x = swapx; move->y = swapy; move->flags = MTR_DEFAULT; move->size = table->keysZ; move->next = *moves; *moves = move; return(table->keysZ); zddGroupMoveOutOfMem: while (*moves != NULL) { move = (*moves)->next; cuddDeallocMove(table, *moves); *moves = move; } return(0); } /* end of zddGroupMove */ /**Function******************************************************************** Synopsis [Undoes the swap two groups.] Description [Undoes the swap two groups. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddGroupMoveBackward( DdManager * table, int x, int y) { int size; int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; #ifdef DD_DEBUG /* We assume that x < y */ assert(x < y); #endif /* Find top, bottom, and size for the two groups. */ xbot = x; xtop = table->subtableZ[x].next; xsize = xbot - xtop + 1; ybot = y; while ((unsigned) ybot < table->subtableZ[ybot].next) ybot = table->subtableZ[ybot].next; ytop = y; ysize = ybot - ytop + 1; /* Sift the variables of the second group up through the first group */ for (i = 1; i <= ysize; i++) { for (j = 1; j <= xsize; j++) { size = cuddZddSwapInPlace(table,x,y); if (size == 0) return(0); y = x; x = cuddZddNextLow(table,y); } y = ytop + i; x = cuddZddNextLow(table,y); } /* fix groups */ y = xtop; for (i = 0; i < ysize - 1; i++) { table->subtableZ[y].next = cuddZddNextHigh(table,y); y = cuddZddNextHigh(table,y); } table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ /* to its top */ x = cuddZddNextHigh(table,y); newxtop = x; for (i = 0; i < xsize - 1; i++) { table->subtableZ[x].next = cuddZddNextHigh(table,x); x = cuddZddNextHigh(table,x); } table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ /* to its top */ #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n"); #endif return(1); } /* end of zddGroupMoveBackward */ /**Function******************************************************************** Synopsis [Determines the best position for a variables and returns it there.] Description [Determines the best position for a variables and returns it there. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddGroupSiftingBackward( DdManager * table, Move * moves, int size) { Move *move; int res; for (move = moves; move != NULL; move = move->next) { if (move->size < size) { size = move->size; } } for (move = moves; move != NULL; move = move->next) { if (move->size == size) return(1); if ((table->subtableZ[move->x].next == move->x) && (table->subtableZ[move->y].next == move->y)) { res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); #ifdef DD_DEBUG if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n"); assert(table->subtableZ[move->x].next == move->x); assert(table->subtableZ[move->y].next == move->y); #endif } else { /* Group move necessary */ res = zddGroupMoveBackward(table,(int)move->x,(int)move->y); if (!res) return(0); } } return(1); } /* end of zddGroupSiftingBackward */ /**Function******************************************************************** Synopsis [Merges groups in the DD table.] Description [Creates a single group from low to high and adjusts the idex field of the tree node.] SideEffects [None] ******************************************************************************/ static void zddMergeGroups( DdManager * table, MtrNode * treenode, int low, int high) { int i; MtrNode *auxnode; int saveindex; int newindex; /* Merge all variables from low to high in one group, unless ** this is the topmost group. In such a case we do not merge lest ** we lose the symmetry information. */ if (treenode != table->treeZ) { for (i = low; i < high; i++) table->subtableZ[i].next = i+1; table->subtableZ[high].next = low; } /* Adjust the index fields of the tree nodes. If a node is the ** first child of its parent, then the parent may also need adjustment. */ saveindex = treenode->index; newindex = table->invpermZ[low]; auxnode = treenode; do { auxnode->index = newindex; if (auxnode->parent == NULL || (int) auxnode->parent->index != saveindex) break; auxnode = auxnode->parent; } while (1); return; } /* end of zddMergeGroups */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddIsop.c000066400000000000000000000664731300674244400241040ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddIsop.c] PackageName [cudd] Synopsis [Functions to find irredundant SOP covers as ZDDs from BDDs.] Description [External procedures included in this module:
        • Cudd_bddIsop()
        • Cudd_zddIsop()
        • Cudd_MakeBddFromZddCover()
        Internal procedures included in this module:
        • cuddBddIsop()
        • cuddZddIsop()
        • cuddMakeBddFromZddCover()
        Static procedures included in this module:
        ] SeeAlso [] Author [In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.20 2009/02/19 16:26:12 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes an ISOP in ZDD form from BDDs.] Description [Computes an irredundant sum of products (ISOP) in ZDD form from BDDs. The two BDDs L and U represent the lower bound and the upper bound, respectively, of the function. The ISOP uses two ZDD variables for each BDD variable: One for the positive literal, and one for the negative literal. These two variables should be adjacent in the ZDD order. The two ZDD variables corresponding to BDD variable i should have indices 2i and 2i+1. The result of this procedure depends on the variable order. If successful, Cudd_zddIsop returns the BDD for the function chosen from the interval. The ZDD representing the irredundant cover is returned as a side effect in zdd_I. In case of failure, NULL is returned.] SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on successful return.] SeeAlso [Cudd_bddIsop Cudd_zddVarsFromBddVars] ******************************************************************************/ DdNode * Cudd_zddIsop( DdManager * dd, DdNode * L, DdNode * U, DdNode ** zdd_I) { DdNode *res; int autoDynZ; autoDynZ = dd->autoDynZ; dd->autoDynZ = 0; do { dd->reordered = 0; res = cuddZddIsop(dd, L, U, zdd_I); } while (dd->reordered == 1); dd->autoDynZ = autoDynZ; return(res); } /* end of Cudd_zddIsop */ /**Function******************************************************************** Synopsis [Computes a BDD in the interval between L and U with a simple sum-of-produuct cover.] Description [Computes a BDD in the interval between L and U with a simple sum-of-produuct cover. This procedure is similar to Cudd_zddIsop, but it does not return the ZDD for the cover. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_zddIsop] ******************************************************************************/ DdNode * Cudd_bddIsop( DdManager * dd, DdNode * L, DdNode * U) { DdNode *res; do { dd->reordered = 0; res = cuddBddIsop(dd, L, U); } while (dd->reordered == 1); return(res); } /* end of Cudd_bddIsop */ /**Function******************************************************************** Synopsis [Converts a ZDD cover to a BDD graph.] Description [Converts a ZDD cover to a BDD graph. If successful, it returns a BDD node, otherwise it returns NULL.] SideEffects [] SeeAlso [cuddMakeBddFromZddCover] ******************************************************************************/ DdNode * Cudd_MakeBddFromZddCover( DdManager * dd, DdNode * node) { DdNode *res; do { dd->reordered = 0; res = cuddMakeBddFromZddCover(dd, node); } while (dd->reordered == 1); return(res); } /* end of Cudd_MakeBddFromZddCover */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddIsop.] Description [] SideEffects [None] SeeAlso [Cudd_zddIsop] ******************************************************************************/ DdNode * cuddZddIsop( DdManager * dd, DdNode * L, DdNode * U, DdNode ** zdd_I) { DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); DdNode *zdd_one = DD_ONE(dd); DdNode *zdd_zero = DD_ZERO(dd); int v, top_l, top_u; DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; DdNode *Isub0, *Isub1, *Id; DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id; DdNode *x; DdNode *term0, *term1, *sum; DdNode *Lv, *Uv, *Lnv, *Unv; DdNode *r, *y, *z; int index; DD_CTFP cacheOp; statLine(dd); if (L == zero) { *zdd_I = zdd_zero; return(zero); } if (U == one) { *zdd_I = zdd_one; return(one); } if (U == zero || L == one) { printf("*** ERROR : illegal condition for ISOP (U < L).\n"); exit(1); } /* Check the cache. We store two results for each recursive call. ** One is the BDD, and the other is the ZDD. Both are needed. ** Hence we need a double hit in the cache to terminate the ** recursion. Clearly, collisions may evict only one of the two ** results. */ cacheOp = (DD_CTFP) cuddZddIsop; r = cuddCacheLookup2(dd, cuddBddIsop, L, U); if (r) { *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U); if (*zdd_I) return(r); else { /* The BDD result may have been dead. In that case ** cuddCacheLookup2 would have called cuddReclaim, ** whose effects we now have to undo. */ cuddRef(r); Cudd_RecursiveDeref(dd, r); } } top_l = dd->perm[Cudd_Regular(L)->index]; top_u = dd->perm[Cudd_Regular(U)->index]; v = ddMin(top_l, top_u); /* Compute cofactors. */ if (top_l == v) { index = Cudd_Regular(L)->index; Lv = Cudd_T(L); Lnv = Cudd_E(L); if (Cudd_IsComplement(L)) { Lv = Cudd_Not(Lv); Lnv = Cudd_Not(Lnv); } } else { index = Cudd_Regular(U)->index; Lv = Lnv = L; } if (top_u == v) { Uv = Cudd_T(U); Unv = Cudd_E(U); if (Cudd_IsComplement(U)) { Uv = Cudd_Not(Uv); Unv = Cudd_Not(Unv); } } else { Uv = Unv = U; } Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); if (Lsub0 == NULL) return(NULL); Cudd_Ref(Lsub0); Usub0 = Unv; Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); if (Lsub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); return(NULL); } Cudd_Ref(Lsub1); Usub1 = Uv; Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0); if (Isub0 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Isub0))) && (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Isub0); Cudd_Ref(zdd_Isub0); Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1); if (Isub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Isub1))) && (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Isub1); Cudd_Ref(zdd_Isub1); Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); if (Lsuper0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); return(NULL); } Cudd_Ref(Lsuper0); Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); if (Lsuper1 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); return(NULL); } Cudd_Ref(Lsuper1); Usuper0 = Unv; Usuper1 = Uv; /* Ld = Lsuper0 + Lsuper1 */ Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); if (Ld == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); return(NULL); } Ld = Cudd_Not(Ld); Cudd_Ref(Ld); /* Ud = Usuper0 * Usuper1 */ Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); if (Ud == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Cudd_RecursiveDeref(dd, Ld); return(NULL); } Cudd_Ref(Ud); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id); if (Id == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Id))) && (Cudd_Regular(Id)->index != zdd_Id->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Id); Cudd_Ref(zdd_Id); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); x = cuddUniqueInter(dd, index, one, zero); if (x == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); return(NULL); } Cudd_Ref(x); /* term0 = x * Isub0 */ term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); if (term0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, x); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDeref(dd, Isub0); /* term1 = x * Isub1 */ term1 = cuddBddAndRecur(dd, x, Isub1); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, term0); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, Isub1); /* sum = term0 + term1 */ sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); if (sum == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); return(NULL); } sum = Cudd_Not(sum); Cudd_Ref(sum); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); /* r = sum + Id */ r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); r = Cudd_NotCond(r, r != NULL); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, sum); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDeref(dd, sum); Cudd_RecursiveDeref(dd, Id); if (zdd_Isub0 != zdd_zero) { z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id); if (z == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, r); return(NULL); } } else { z = zdd_Id; } Cudd_Ref(z); if (zdd_Isub1 != zdd_zero) { y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z); if (y == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, r); Cudd_RecursiveDerefZdd(dd, z); return(NULL); } } else y = z; Cudd_Ref(y); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDerefZdd(dd, z); cuddCacheInsert2(dd, cuddBddIsop, L, U, r); cuddCacheInsert2(dd, cacheOp, L, U, y); Cudd_Deref(r); Cudd_Deref(y); *zdd_I = y; /* if (Cudd_Regular(r)->index != y->index / 2) { printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n"); } */ return(r); } /* end of cuddZddIsop */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddIsop.] Description [] SideEffects [None] SeeAlso [Cudd_bddIsop] ******************************************************************************/ DdNode * cuddBddIsop( DdManager * dd, DdNode * L, DdNode * U) { DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); int v, top_l, top_u; DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; DdNode *Isub0, *Isub1, *Id; DdNode *x; DdNode *term0, *term1, *sum; DdNode *Lv, *Uv, *Lnv, *Unv; DdNode *r; int index; statLine(dd); if (L == zero) return(zero); if (U == one) return(one); /* Check cache */ r = cuddCacheLookup2(dd, cuddBddIsop, L, U); if (r) return(r); top_l = dd->perm[Cudd_Regular(L)->index]; top_u = dd->perm[Cudd_Regular(U)->index]; v = ddMin(top_l, top_u); /* Compute cofactors */ if (top_l == v) { index = Cudd_Regular(L)->index; Lv = Cudd_T(L); Lnv = Cudd_E(L); if (Cudd_IsComplement(L)) { Lv = Cudd_Not(Lv); Lnv = Cudd_Not(Lnv); } } else { index = Cudd_Regular(U)->index; Lv = Lnv = L; } if (top_u == v) { Uv = Cudd_T(U); Unv = Cudd_E(U); if (Cudd_IsComplement(U)) { Uv = Cudd_Not(Uv); Unv = Cudd_Not(Unv); } } else { Uv = Unv = U; } Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); if (Lsub0 == NULL) return(NULL); Cudd_Ref(Lsub0); Usub0 = Unv; Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); if (Lsub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); return(NULL); } Cudd_Ref(Lsub1); Usub1 = Uv; Isub0 = cuddBddIsop(dd, Lsub0, Usub0); if (Isub0 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); return(NULL); } Cudd_Ref(Isub0); Isub1 = cuddBddIsop(dd, Lsub1, Usub1); if (Isub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Cudd_RecursiveDeref(dd, Isub0); return(NULL); } Cudd_Ref(Isub1); Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); if (Lsuper0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); return(NULL); } Cudd_Ref(Lsuper0); Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); if (Lsuper1 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); return(NULL); } Cudd_Ref(Lsuper1); Usuper0 = Unv; Usuper1 = Uv; /* Ld = Lsuper0 + Lsuper1 */ Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); Ld = Cudd_NotCond(Ld, Ld != NULL); if (Ld == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); return(NULL); } Cudd_Ref(Ld); Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); if (Ud == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Cudd_RecursiveDeref(dd, Ld); return(NULL); } Cudd_Ref(Ud); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Id = cuddBddIsop(dd, Ld, Ud); if (Id == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); return(NULL); } Cudd_Ref(Id); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); x = cuddUniqueInter(dd, index, one, zero); if (x == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); return(NULL); } Cudd_Ref(x); term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); if (term0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, x); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDeref(dd, Isub0); term1 = cuddBddAndRecur(dd, x, Isub1); if (term1 == NULL) { Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, term0); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, Isub1); /* sum = term0 + term1 */ sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); sum = Cudd_NotCond(sum, sum != NULL); if (sum == NULL) { Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); return(NULL); } Cudd_Ref(sum); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); /* r = sum + Id */ r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); r = Cudd_NotCond(r, r != NULL); if (r == NULL) { Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, sum); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDeref(dd, sum); Cudd_RecursiveDeref(dd, Id); cuddCacheInsert2(dd, cuddBddIsop, L, U, r); Cudd_Deref(r); return(r); } /* end of cuddBddIsop */ /**Function******************************************************************** Synopsis [Converts a ZDD cover to a BDD graph.] Description [Converts a ZDD cover to a BDD graph. If successful, it returns a BDD node, otherwise it returns NULL. It is a recursive algorithm as the following. First computes 3 cofactors of a ZDD cover; f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd. Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v is the variable which has the index of the top node of the ZDD cover. In this case, since the index of v can be larger than either one of T or one of E, cuddUniqueInterIVO is called, here IVO stands for independent variable ordering.] SideEffects [] SeeAlso [Cudd_MakeBddFromZddCover] ******************************************************************************/ DdNode * cuddMakeBddFromZddCover( DdManager * dd, DdNode * node) { DdNode *neW; int v; DdNode *f1, *f0, *fd; DdNode *b1, *b0, *bd; DdNode *T, *E; statLine(dd); if (node == dd->one) return(dd->one); if (node == dd->zero) return(Cudd_Not(dd->one)); /* Check cache */ neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node); if (neW) return(neW); v = Cudd_Regular(node)->index; /* either yi or zi */ if (cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd)) return(NULL); Cudd_Ref(f1); Cudd_Ref(f0); Cudd_Ref(fd); b1 = cuddMakeBddFromZddCover(dd, f1); if (!b1) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); return(NULL); } Cudd_Ref(b1); b0 = cuddMakeBddFromZddCover(dd, f0); if (!b0) { Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDeref(dd, b1); return(NULL); } Cudd_Ref(b0); Cudd_RecursiveDerefZdd(dd, f1); Cudd_RecursiveDerefZdd(dd, f0); if (fd != dd->zero) { bd = cuddMakeBddFromZddCover(dd, fd); if (!bd) { Cudd_RecursiveDerefZdd(dd, fd); Cudd_RecursiveDeref(dd, b1); Cudd_RecursiveDeref(dd, b0); return(NULL); } Cudd_Ref(bd); Cudd_RecursiveDerefZdd(dd, fd); T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd)); if (!T) { Cudd_RecursiveDeref(dd, b1); Cudd_RecursiveDeref(dd, b0); Cudd_RecursiveDeref(dd, bd); return(NULL); } T = Cudd_NotCond(T, T != NULL); Cudd_Ref(T); Cudd_RecursiveDeref(dd, b1); E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd)); if (!E) { Cudd_RecursiveDeref(dd, b0); Cudd_RecursiveDeref(dd, bd); Cudd_RecursiveDeref(dd, T); return(NULL); } E = Cudd_NotCond(E, E != NULL); Cudd_Ref(E); Cudd_RecursiveDeref(dd, b0); Cudd_RecursiveDeref(dd, bd); } else { Cudd_RecursiveDerefZdd(dd, fd); T = b1; E = b0; } if (Cudd_IsComplement(T)) { neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E)); if (!neW) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } neW = Cudd_Not(neW); } else { neW = cuddUniqueInterIVO(dd, v / 2, T, E); if (!neW) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } Cudd_Ref(neW); Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW); Cudd_Deref(neW); return(neW); } /* end of cuddMakeBddFromZddCover */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddLin.c000066400000000000000000000766211300674244400237100ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddLin.c] PackageName [cudd] Synopsis [Procedures for dynamic variable ordering of ZDDs.] Description [Internal procedures included in this module:
        • cuddZddLinearSifting()
        Static procedures included in this module:
        • cuddZddLinearInPlace()
        • cuddZddLinerAux()
        • cuddZddLinearUp()
        • cuddZddLinearDown()
        • cuddZddLinearBackward()
        • cuddZddUndoMoves()
        ] SeeAlso [cuddLinear.c cuddZddReord.c] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define CUDD_SWAP_MOVE 0 #define CUDD_LINEAR_TRANSFORM_MOVE 1 #define CUDD_INVERSE_TRANSFORM_MOVE 2 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.14 2004/08/13 18:04:53 fabio Exp $"; #endif extern int *zdd_entry; extern int zddTotalNumberSwapping; static int zddTotalNumberLinearTr; static DdNode *empty; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int cuddZddLinearInPlace (DdManager * table, int x, int y); static int cuddZddLinearAux (DdManager *table, int x, int xLow, int xHigh); static Move * cuddZddLinearUp (DdManager *table, int y, int xLow, Move *prevMoves); static Move * cuddZddLinearDown (DdManager *table, int x, int xHigh, Move *prevMoves); static int cuddZddLinearBackward (DdManager *table, int size, Move *moves); static Move* cuddZddUndoMoves (DdManager *table, Move *moves); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implementation of the linear sifting algorithm for ZDDs.] Description [Implementation of the linear sifting algorithm for ZDDs. Assumes that no dead nodes are present.
        1. Order all the variables according to the number of entries in each unique table.
        2. Sift the variable up and down and applies the XOR transformation, remembering each time the total size of the DD heap.
        3. Select the best permutation.
        4. Repeat 3 and 4 for all variables.
        Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddLinearSifting( DdManager * table, int lower, int upper) { int i; int *var; int size; int x; int result; #ifdef DD_STATS int previousSize; #endif size = table->sizeZ; empty = table->zero; /* Find order in which to sift variables. */ var = NULL; zdd_entry = ABC_ALLOC(int, size); if (zdd_entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddZddSiftingOutOfMem; } var = ABC_ALLOC(int, size); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddZddSiftingOutOfMem; } for (i = 0; i < size; i++) { x = table->permZ[i]; zdd_entry[i] = table->subtableZ[x].keys; var[i] = i; } qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); /* Now sift. */ for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { if (zddTotalNumberSwapping >= table->siftMaxSwap) break; x = table->permZ[var[i]]; if (x < lower || x > upper) continue; #ifdef DD_STATS previousSize = table->keysZ; #endif result = cuddZddLinearAux(table, x, lower, upper); if (!result) goto cuddZddSiftingOutOfMem; #ifdef DD_STATS if (table->keysZ < (unsigned) previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > (unsigned) previousSize) { (void) fprintf(table->out,"+"); /* should never happen */ (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } ABC_FREE(var); ABC_FREE(zdd_entry); return(1); cuddZddSiftingOutOfMem: if (zdd_entry != NULL) ABC_FREE(zdd_entry); if (var != NULL) ABC_FREE(var); return(0); } /* end of cuddZddLinearSifting */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Linearly combines two adjacent variables.] Description [Linearly combines two adjacent variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddZddLinearInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddZddSwapInPlace cuddLinearInPlace] ******************************************************************************/ static int cuddZddLinearInPlace( DdManager * table, int x, int y) { DdNodePtr *xlist, *ylist; int xindex, yindex; int xslots, yslots; int xshift, yshift; int oldxkeys, oldykeys; int newxkeys, newykeys; int i; int posn; DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; DdNode *newf1, *newf0, *g, *next, *previous; DdNode *special; #ifdef DD_DEBUG assert(x < y); assert(cuddZddNextHigh(table,x) == y); assert(table->subtableZ[x].keys != 0); assert(table->subtableZ[y].keys != 0); assert(table->subtableZ[x].dead == 0); assert(table->subtableZ[y].dead == 0); #endif zddTotalNumberLinearTr++; /* Get parameters of x subtable. */ xindex = table->invpermZ[x]; xlist = table->subtableZ[x].nodelist; oldxkeys = table->subtableZ[x].keys; xslots = table->subtableZ[x].slots; xshift = table->subtableZ[x].shift; newxkeys = 0; /* Get parameters of y subtable. */ yindex = table->invpermZ[y]; ylist = table->subtableZ[y].nodelist; oldykeys = table->subtableZ[y].keys; yslots = table->subtableZ[y].slots; yshift = table->subtableZ[y].shift; newykeys = oldykeys; /* The nodes in the x layer are put in two chains. The chain ** pointed by g holds the normal nodes. When re-expressed they stay ** in the x list. The chain pointed by special holds the elements ** that will move to the y list. */ g = special = NULL; for (i = 0; i < xslots; i++) { f = xlist[i]; if (f == NULL) continue; xlist[i] = NULL; while (f != NULL) { next = f->next; f1 = cuddT(f); /* if (f1->index == yindex) */ cuddSatDec(f1->ref); f0 = cuddE(f); /* if (f0->index == yindex) */ cuddSatDec(f0->ref); if ((int) f1->index == yindex && cuddE(f1) == empty && (int) f0->index != yindex) { f->next = special; special = f; } else { f->next = g; g = f; } f = next; } /* while there are elements in the collision chain */ } /* for each slot of the x subtable */ /* Mark y nodes with pointers from above x. We mark them by ** changing their index to x. */ for (i = 0; i < yslots; i++) { f = ylist[i]; while (f != NULL) { if (f->ref != 0) { f->index = xindex; } f = f->next; } /* while there are elements in the collision chain */ } /* for each slot of the y subtable */ /* Move special nodes to the y list. */ f = special; while (f != NULL) { next = f->next; f1 = cuddT(f); f11 = cuddT(f1); cuddT(f) = f11; cuddSatInc(f11->ref); f0 = cuddE(f); cuddSatInc(f0->ref); f->index = yindex; /* Insert at the beginning of the list so that it will be ** found first if there is a duplicate. The duplicate will ** eventually be moved or garbage collected. No node ** re-expression will add a pointer to it. */ posn = ddHash(cuddF2L(f11), cuddF2L(f0), yshift); f->next = ylist[posn]; ylist[posn] = f; newykeys++; f = next; } /* Take care of the remaining x nodes that must be re-expressed. ** They form a linked list pointed by g. */ f = g; while (f != NULL) { #ifdef DD_COUNT table->swapSteps++; #endif next = f->next; /* Find f1, f0, f11, f10, f01, f00. */ f1 = cuddT(f); if ((int) f1->index == yindex || (int) f1->index == xindex) { f11 = cuddT(f1); f10 = cuddE(f1); } else { f11 = empty; f10 = f1; } f0 = cuddE(f); if ((int) f0->index == yindex || (int) f0->index == xindex) { f01 = cuddT(f0); f00 = cuddE(f0); } else { f01 = empty; f00 = f0; } /* Create the new T child. */ if (f01 == empty) { newf1 = f10; cuddSatInc(newf1->ref); } else { /* Check ylist for triple (yindex, f01, f10). */ posn = ddHash(cuddF2L(f01), cuddF2L(f10), yshift); /* For each element newf1 in collision list ylist[posn]. */ newf1 = ylist[posn]; /* Search the collision chain skipping the marked nodes. */ while (newf1 != NULL) { if (cuddT(newf1) == f01 && cuddE(newf1) == f10 && (int) newf1->index == yindex) { cuddSatInc(newf1->ref); break; /* match */ } newf1 = newf1->next; } /* while newf1 */ if (newf1 == NULL) { /* no match */ newf1 = cuddDynamicAllocNode(table); if (newf1 == NULL) goto zddSwapOutOfMem; newf1->index = yindex; newf1->ref = 1; cuddT(newf1) = f01; cuddE(newf1) = f10; /* Insert newf1 in the collision list ylist[pos]; ** increase the ref counts of f01 and f10 */ newykeys++; newf1->next = ylist[posn]; ylist[posn] = newf1; cuddSatInc(f01->ref); cuddSatInc(f10->ref); } } cuddT(f) = newf1; /* Do the same for f0. */ /* Create the new E child. */ if (f11 == empty) { newf0 = f00; cuddSatInc(newf0->ref); } else { /* Check ylist for triple (yindex, f11, f00). */ posn = ddHash(cuddF2L(f11), cuddF2L(f00), yshift); /* For each element newf0 in collision list ylist[posn]. */ newf0 = ylist[posn]; while (newf0 != NULL) { if (cuddT(newf0) == f11 && cuddE(newf0) == f00 && (int) newf0->index == yindex) { cuddSatInc(newf0->ref); break; /* match */ } newf0 = newf0->next; } /* while newf0 */ if (newf0 == NULL) { /* no match */ newf0 = cuddDynamicAllocNode(table); if (newf0 == NULL) goto zddSwapOutOfMem; newf0->index = yindex; newf0->ref = 1; cuddT(newf0) = f11; cuddE(newf0) = f00; /* Insert newf0 in the collision list ylist[posn]; ** increase the ref counts of f11 and f00. */ newykeys++; newf0->next = ylist[posn]; ylist[posn] = newf0; cuddSatInc(f11->ref); cuddSatInc(f00->ref); } } cuddE(f) = newf0; /* Re-insert the modified f in xlist. ** The modified f does not already exists in xlist. ** (Because of the uniqueness of the cofactors.) */ posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), xshift); newxkeys++; f->next = xlist[posn]; xlist[posn] = f; f = next; } /* while f != NULL */ /* GC the y layer and move the marked nodes to the x list. */ /* For each node f in ylist. */ for (i = 0; i < yslots; i++) { previous = NULL; f = ylist[i]; while (f != NULL) { next = f->next; if (f->ref == 0) { cuddSatDec(cuddT(f)->ref); cuddSatDec(cuddE(f)->ref); cuddDeallocNode(table, f); newykeys--; if (previous == NULL) ylist[i] = next; else previous->next = next; } else if ((int) f->index == xindex) { /* move marked node */ if (previous == NULL) ylist[i] = next; else previous->next = next; f1 = cuddT(f); cuddSatDec(f1->ref); /* Check ylist for triple (yindex, f1, empty). */ posn = ddHash(cuddF2L(f1), cuddF2L(empty), yshift); /* For each element newf1 in collision list ylist[posn]. */ newf1 = ylist[posn]; while (newf1 != NULL) { if (cuddT(newf1) == f1 && cuddE(newf1) == empty && (int) newf1->index == yindex) { cuddSatInc(newf1->ref); break; /* match */ } newf1 = newf1->next; } /* while newf1 */ if (newf1 == NULL) { /* no match */ newf1 = cuddDynamicAllocNode(table); if (newf1 == NULL) goto zddSwapOutOfMem; newf1->index = yindex; newf1->ref = 1; cuddT(newf1) = f1; cuddE(newf1) = empty; /* Insert newf1 in the collision list ylist[posn]; ** increase the ref counts of f1 and empty. */ newykeys++; newf1->next = ylist[posn]; ylist[posn] = newf1; if (posn == i && previous == NULL) previous = newf1; cuddSatInc(f1->ref); cuddSatInc(empty->ref); } cuddT(f) = newf1; f0 = cuddE(f); /* Insert f in x list. */ posn = ddHash(cuddF2L(newf1), cuddF2L(f0), xshift); newxkeys++; newykeys--; f->next = xlist[posn]; xlist[posn] = f; } else { previous = f; } f = next; } /* while f */ } /* for i */ /* Set the appropriate fields in table. */ table->subtableZ[x].keys = newxkeys; table->subtableZ[y].keys = newykeys; table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; /* Update univ section; univ[x] remains the same. */ table->univ[y] = cuddT(table->univ[x]); #if 0 (void) fprintf(table->out,"x = %d y = %d\n", x, y); (void) Cudd_DebugCheck(table); (void) Cudd_CheckKeys(table); #endif return (table->keysZ); zddSwapOutOfMem: (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); return (0); } /* end of cuddZddLinearInPlace */ /**Function******************************************************************** Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.] Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddLinearAux( DdManager * table, int x, int xLow, int xHigh) { Move *move; Move *moveUp; /* list of up move */ Move *moveDown; /* list of down move */ int initial_size; int result; initial_size = table->keysZ; #ifdef DD_DEBUG assert(table->subtableZ[x].keys > 0); #endif moveDown = NULL; moveUp = NULL; if (x == xLow) { moveDown = cuddZddLinearDown(table, x, xHigh, NULL); /* At this point x --> xHigh. */ if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto cuddZddLinearAuxOutOfMem; /* Move backward and stop at best position. */ result = cuddZddLinearBackward(table, initial_size, moveDown); if (!result) goto cuddZddLinearAuxOutOfMem; } else if (x == xHigh) { moveUp = cuddZddLinearUp(table, x, xLow, NULL); /* At this point x --> xLow. */ if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto cuddZddLinearAuxOutOfMem; /* Move backward and stop at best position. */ result = cuddZddLinearBackward(table, initial_size, moveUp); if (!result) goto cuddZddLinearAuxOutOfMem; } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ moveDown = cuddZddLinearDown(table, x, xHigh, NULL); /* At this point x --> xHigh. */ if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto cuddZddLinearAuxOutOfMem; moveUp = cuddZddUndoMoves(table,moveDown); #ifdef DD_DEBUG assert(moveUp == NULL || moveUp->x == x); #endif moveUp = cuddZddLinearUp(table, x, xLow, moveUp); if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto cuddZddLinearAuxOutOfMem; /* Move backward and stop at best position. */ result = cuddZddLinearBackward(table, initial_size, moveUp); if (!result) goto cuddZddLinearAuxOutOfMem; } else { moveUp = cuddZddLinearUp(table, x, xLow, NULL); /* At this point x --> xHigh. */ if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto cuddZddLinearAuxOutOfMem; /* Then move up. */ moveDown = cuddZddUndoMoves(table,moveUp); #ifdef DD_DEBUG assert(moveDown == NULL || moveDown->y == x); #endif moveDown = cuddZddLinearDown(table, x, xHigh, moveDown); if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto cuddZddLinearAuxOutOfMem; /* Move backward and stop at best position. */ result = cuddZddLinearBackward(table, initial_size, moveDown); if (!result) goto cuddZddLinearAuxOutOfMem; } while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } return(1); cuddZddLinearAuxOutOfMem: if (moveDown != (Move *) CUDD_OUT_OF_MEM) { while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } } if (moveUp != (Move *) CUDD_OUT_OF_MEM) { while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } } return(0); } /* end of cuddZddLinearAux */ /**Function******************************************************************** Synopsis [Sifts a variable up applying the XOR transformation.] Description [Sifts a variable up applying the XOR transformation. Moves y up until either it reaches the bound (xLow) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * cuddZddLinearUp( DdManager * table, int y, int xLow, Move * prevMoves) { Move *moves; Move *move; int x; int size, newsize; int limitSize; moves = prevMoves; limitSize = table->keysZ; x = cuddZddNextLow(table, y); while (x >= xLow) { size = cuddZddSwapInPlace(table, x, y); if (size == 0) goto cuddZddLinearUpOutOfMem; newsize = cuddZddLinearInPlace(table, x, y); if (newsize == 0) goto cuddZddLinearUpOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto cuddZddLinearUpOutOfMem; move->x = x; move->y = y; move->next = moves; moves = move; move->flags = CUDD_SWAP_MOVE; if (newsize > size) { /* Undo transformation. The transformation we apply is ** its own inverse. Hence, we just apply the transformation ** again. */ newsize = cuddZddLinearInPlace(table,x,y); if (newsize == 0) goto cuddZddLinearUpOutOfMem; #ifdef DD_DEBUG if (newsize != size) { (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); } #endif } else { size = newsize; move->flags = CUDD_LINEAR_TRANSFORM_MOVE; } move->size = size; if ((double)size > (double)limitSize * table->maxGrowth) break; if (size < limitSize) limitSize = size; y = x; x = cuddZddNextLow(table, y); } return(moves); cuddZddLinearUpOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return((Move *) CUDD_OUT_OF_MEM); } /* end of cuddZddLinearUp */ /**Function******************************************************************** Synopsis [Sifts a variable down and applies the XOR transformation.] Description [Sifts a variable down. Moves x down until either it reaches the bound (xHigh) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * cuddZddLinearDown( DdManager * table, int x, int xHigh, Move * prevMoves) { Move *moves; Move *move; int y; int size, newsize; int limitSize; moves = prevMoves; limitSize = table->keysZ; y = cuddZddNextHigh(table, x); while (y <= xHigh) { size = cuddZddSwapInPlace(table, x, y); if (size == 0) goto cuddZddLinearDownOutOfMem; newsize = cuddZddLinearInPlace(table, x, y); if (newsize == 0) goto cuddZddLinearDownOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto cuddZddLinearDownOutOfMem; move->x = x; move->y = y; move->next = moves; moves = move; move->flags = CUDD_SWAP_MOVE; if (newsize > size) { /* Undo transformation. The transformation we apply is ** its own inverse. Hence, we just apply the transformation ** again. */ newsize = cuddZddLinearInPlace(table,x,y); if (newsize == 0) goto cuddZddLinearDownOutOfMem; if (newsize != size) { (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); } } else { size = newsize; move->flags = CUDD_LINEAR_TRANSFORM_MOVE; } move->size = size; if ((double)size > (double)limitSize * table->maxGrowth) break; if (size < limitSize) limitSize = size; x = y; y = cuddZddNextHigh(table, x); } return(moves); cuddZddLinearDownOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return((Move *) CUDD_OUT_OF_MEM); } /* end of cuddZddLinearDown */ /**Function******************************************************************** Synopsis [Given a set of moves, returns the ZDD heap to the position giving the minimum size.] Description [Given a set of moves, returns the ZDD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddLinearBackward( DdManager * table, int size, Move * moves) { Move *move; int res; /* Find the minimum size among moves. */ for (move = moves; move != NULL; move = move->next) { if (move->size < size) { size = move->size; } } for (move = moves; move != NULL; move = move->next) { if (move->size == size) return(1); if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); } res = cuddZddSwapInPlace(table, move->x, move->y); if (!res) return(0); if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); if (!res) return(0); } } return(1); } /* end of cuddZddLinearBackward */ /**Function******************************************************************** Synopsis [Given a set of moves, returns the ZDD heap to the order in effect before the moves.] Description [Given a set of moves, returns the ZDD heap to the order in effect before the moves. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static Move* cuddZddUndoMoves( DdManager * table, Move * moves) { Move *invmoves = NULL; Move *move; Move *invmove; int size; for (move = moves; move != NULL; move = move->next) { invmove = (Move *) cuddDynamicAllocNode(table); if (invmove == NULL) goto cuddZddUndoMovesOutOfMem; invmove->x = move->x; invmove->y = move->y; invmove->next = invmoves; invmoves = invmove; if (move->flags == CUDD_SWAP_MOVE) { invmove->flags = CUDD_SWAP_MOVE; size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); if (!size) goto cuddZddUndoMovesOutOfMem; } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); if (!size) goto cuddZddUndoMovesOutOfMem; size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); if (!size) goto cuddZddUndoMovesOutOfMem; } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ #ifdef DD_DEBUG (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); #endif invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); if (!size) goto cuddZddUndoMovesOutOfMem; size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); if (!size) goto cuddZddUndoMovesOutOfMem; } invmove->size = size; } return(invmoves); cuddZddUndoMovesOutOfMem: while (invmoves != NULL) { move = invmoves->next; cuddDeallocMove(table, invmoves); invmoves = move; } return((Move *) CUDD_OUT_OF_MEM); } /* end of cuddZddUndoMoves */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddMisc.c000066400000000000000000000224201300674244400240450ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddMisc.c] PackageName [cudd] Synopsis [Miscellaneous utility functions for ZDDs.] Description [External procedures included in this module:
        • Cudd_zddDagSize()
        • Cudd_zddCountMinterm()
        • Cudd_zddPrintSubtable()
        Internal procedures included in this module:
        Static procedures included in this module:
        • cuddZddDagInt()
        ] SeeAlso [] Author [Hyong-Kyoon Shin, In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddMisc.c,v 1.16 2009/02/20 02:14:58 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int cuddZddDagInt (DdNode *n, st__table *tab); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Counts the number of nodes in a ZDD.] Description [Counts the number of nodes in a ZDD. This function duplicates Cudd_DagSize and is only retained for compatibility.] SideEffects [None] SeeAlso [Cudd_DagSize] ******************************************************************************/ int Cudd_zddDagSize( DdNode * p_node) { int i; st__table *table; table = st__init_table( st__ptrcmp, st__ptrhash); i = cuddZddDagInt(p_node, table); st__free_table(table); return(i); } /* end of Cudd_zddDagSize */ /**Function******************************************************************** Synopsis [Counts the number of minterms of a ZDD.] Description [Counts the number of minterms of the ZDD rooted at node. This procedure takes a parameter path that specifies how many variables are in the support of the function. If the procedure runs out of memory, it returns (double) CUDD_OUT_OF_MEM.] SideEffects [None] SeeAlso [Cudd_zddCountDouble] ******************************************************************************/ double Cudd_zddCountMinterm( DdManager * zdd, DdNode * node, int path) { double dc_var, minterms; dc_var = (double)((double)(zdd->sizeZ) - (double)path); minterms = Cudd_zddCountDouble(zdd, node) / pow(2.0, dc_var); return(minterms); } /* end of Cudd_zddCountMinterm */ /**Function******************************************************************** Synopsis [Prints the ZDD table.] Description [Prints the ZDD table for debugging purposes.] SideEffects [None] SeeAlso [] ******************************************************************************/ void Cudd_zddPrintSubtable( DdManager * table) { int i, j; DdNode *z1, *z1_next, *base; DdSubtable *ZSubTable; base = table->one; for (i = table->sizeZ - 1; i >= 0; i--) { ZSubTable = &(table->subtableZ[i]); printf("subtable[%d]:\n", i); for (j = ZSubTable->slots - 1; j >= 0; j--) { z1 = ZSubTable->nodelist[j]; while (z1 != NIL(DdNode)) { (void) fprintf(table->out, #if SIZEOF_VOID_P == 8 "ID = 0x%lx\tindex = %u\tr = %u\t", (ptruint) z1 / (ptruint) sizeof(DdNode), z1->index, z1->ref); #else "ID = 0x%x\tindex = %hu\tr = %hu\t", (ptruint) z1 / (ptruint) sizeof(DdNode), z1->index, z1->ref); #endif z1_next = cuddT(z1); if (Cudd_IsConstant(z1_next)) { (void) fprintf(table->out, "T = %d\t\t", (z1_next == base)); } else { #if SIZEOF_VOID_P == 8 (void) fprintf(table->out, "T = 0x%lx\t", (ptruint) z1_next / (ptruint) sizeof(DdNode)); #else (void) fprintf(table->out, "T = 0x%x\t", (ptruint) z1_next / (ptruint) sizeof(DdNode)); #endif } z1_next = cuddE(z1); if (Cudd_IsConstant(z1_next)) { (void) fprintf(table->out, "E = %d\n", (z1_next == base)); } else { #if SIZEOF_VOID_P == 8 (void) fprintf(table->out, "E = 0x%lx\n", (ptruint) z1_next / (ptruint) sizeof(DdNode)); #else (void) fprintf(table->out, "E = 0x%x\n", (ptruint) z1_next / (ptruint) sizeof(DdNode)); #endif } z1_next = z1->next; z1 = z1_next; } } } putchar('\n'); } /* Cudd_zddPrintSubtable */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddDagSize.] Description [Performs the recursive step of Cudd_zddDagSize. Does not check for out-of-memory conditions.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddDagInt( DdNode * n, st__table * tab) { if (n == NIL(DdNode)) return(0); if ( st__is_member(tab, (char *)n) == 1) return(0); if (Cudd_IsConstant(n)) return(0); (void) st__insert(tab, (char *)n, NIL(char)); return(1 + cuddZddDagInt(cuddT(n), tab) + cuddZddDagInt(cuddE(n), tab)); } /* cuddZddDagInt */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddPort.c000066400000000000000000000270411300674244400241020ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddPort.c] PackageName [cudd] Synopsis [Functions that translate BDDs to ZDDs.] Description [External procedures included in this module:
        • Cudd_zddPortFromBdd()
        • Cudd_zddPortToBdd()
        Internal procedures included in this module:
        Static procedures included in this module:
        • zddPortFromBddStep()
        • zddPortToBddStep()
        ] SeeAlso [] Author [Hyong-kyoon Shin, In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddPort.c,v 1.13 2004/08/13 18:04:53 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * zddPortFromBddStep (DdManager *dd, DdNode *B, int expected); static DdNode * zddPortToBddStep (DdManager *dd, DdNode *f, int depth); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Converts a BDD into a ZDD.] Description [Converts a BDD into a ZDD. This function assumes that there is a one-to-one correspondence between the BDD variables and the ZDD variables, and that the variable order is the same for both types of variables. These conditions are established if the ZDD variables are created by one call to Cudd_zddVarsFromBddVars with multiplicity = 1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_zddVarsFromBddVars] ******************************************************************************/ DdNode * Cudd_zddPortFromBdd( DdManager * dd, DdNode * B) { DdNode *res; do { dd->reordered = 0; res = zddPortFromBddStep(dd,B,0); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddPortFromBdd */ /**Function******************************************************************** Synopsis [Converts a ZDD into a BDD.] Description [Converts a ZDD into a BDD. Returns a pointer to the resulting ZDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_zddPortFromBdd] ******************************************************************************/ DdNode * Cudd_zddPortToBdd( DdManager * dd, DdNode * f) { DdNode *res; do { dd->reordered = 0; res = zddPortToBddStep(dd,f,0); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddPortToBdd */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * zddPortFromBddStep( DdManager * dd, DdNode * B, int expected) { DdNode *res, *prevZdd, *t, *e; DdNode *Breg, *Bt, *Be; int id, level; statLine(dd); /* Terminal cases. */ if (B == Cudd_Not(DD_ONE(dd))) return(DD_ZERO(dd)); if (B == DD_ONE(dd)) { if (expected >= dd->sizeZ) { return(DD_ONE(dd)); } else { return(dd->univ[expected]); } } Breg = Cudd_Regular(B); /* Computed table look-up. */ res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B); if (res != NULL) { level = cuddI(dd,Breg->index); /* Adding DC vars. */ if (expected < level) { /* Add suppressed variables. */ cuddRef(res); for (level--; level >= expected; level--) { prevZdd = res; id = dd->invperm[level]; res = cuddZddGetNode(dd, id, prevZdd, prevZdd); if (res == NULL) { Cudd_RecursiveDerefZdd(dd, prevZdd); return(NULL); } cuddRef(res); Cudd_RecursiveDerefZdd(dd, prevZdd); } cuddDeref(res); } return(res); } /* end of cache look-up */ if (Cudd_IsComplement(B)) { Bt = Cudd_Not(cuddT(Breg)); Be = Cudd_Not(cuddE(Breg)); } else { Bt = cuddT(Breg); Be = cuddE(Breg); } id = Breg->index; level = cuddI(dd,id); t = zddPortFromBddStep(dd, Bt, level+1); if (t == NULL) return(NULL); cuddRef(t); e = zddPortFromBddStep(dd, Be, level+1); if (e == NULL) { Cudd_RecursiveDerefZdd(dd, t); return(NULL); } cuddRef(e); res = cuddZddGetNode(dd, id, t, e); if (res == NULL) { Cudd_RecursiveDerefZdd(dd, t); Cudd_RecursiveDerefZdd(dd, e); return(NULL); } cuddRef(res); Cudd_RecursiveDerefZdd(dd, t); Cudd_RecursiveDerefZdd(dd, e); cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res); for (level--; level >= expected; level--) { prevZdd = res; id = dd->invperm[level]; res = cuddZddGetNode(dd, id, prevZdd, prevZdd); if (res == NULL) { Cudd_RecursiveDerefZdd(dd, prevZdd); return(NULL); } cuddRef(res); Cudd_RecursiveDerefZdd(dd, prevZdd); } cuddDeref(res); return(res); } /* end of zddPortFromBddStep */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddPortToBdd.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * zddPortToBddStep( DdManager * dd /* manager */, DdNode * f /* ZDD to be converted */, int depth /* recursion depth */) { DdNode *one, *zero, *T, *E, *res, *var; unsigned int index; unsigned int level; statLine(dd); one = DD_ONE(dd); zero = DD_ZERO(dd); if (f == zero) return(Cudd_Not(one)); if (depth == dd->sizeZ) return(one); index = dd->invpermZ[depth]; level = cuddIZ(dd,f->index); var = cuddUniqueInter(dd,index,one,Cudd_Not(one)); if (var == NULL) return(NULL); cuddRef(var); if (level > (unsigned) depth) { E = zddPortToBddStep(dd,f,depth+1); if (E == NULL) { Cudd_RecursiveDeref(dd,var); return(NULL); } cuddRef(E); res = cuddBddIteRecur(dd,var,Cudd_Not(one),E); if (res == NULL) { Cudd_RecursiveDeref(dd,var); Cudd_RecursiveDeref(dd,E); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd,var); Cudd_RecursiveDeref(dd,E); cuddDeref(res); return(res); } res = cuddCacheLookup1(dd,Cudd_zddPortToBdd,f); if (res != NULL) { Cudd_RecursiveDeref(dd,var); return(res); } T = zddPortToBddStep(dd,cuddT(f),depth+1); if (T == NULL) { Cudd_RecursiveDeref(dd,var); return(NULL); } cuddRef(T); E = zddPortToBddStep(dd,cuddE(f),depth+1); if (E == NULL) { Cudd_RecursiveDeref(dd,var); Cudd_RecursiveDeref(dd,T); return(NULL); } cuddRef(E); res = cuddBddIteRecur(dd,var,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd,var); Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd,var); Cudd_RecursiveDeref(dd,T); Cudd_RecursiveDeref(dd,E); cuddDeref(res); cuddCacheInsert1(dd,Cudd_zddPortToBdd,f,res); return(res); } /* end of zddPortToBddStep */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddReord.c000066400000000000000000001423711300674244400242350ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddReord.c] PackageName [cudd] Synopsis [Procedures for dynamic variable ordering of ZDDs.] Description [External procedures included in this module:
        • Cudd_zddReduceHeap()
        • Cudd_zddShuffleHeap()
        Internal procedures included in this module:
        • cuddZddAlignToBdd()
        • cuddZddNextHigh()
        • cuddZddNextLow()
        • cuddZddUniqueCompare()
        • cuddZddSwapInPlace()
        • cuddZddSwapping()
        • cuddZddSifting()
        Static procedures included in this module:
        • zddSwapAny()
        • cuddZddSiftingAux()
        • cuddZddSiftingUp()
        • cuddZddSiftingDown()
        • cuddZddSiftingBackward()
        • zddReorderPreprocess()
        • zddReorderPostprocess()
        • zddShuffle()
        • zddSiftUp()
        ] SeeAlso [] Author [Hyong-Kyoon Shin, In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define DD_MAX_SUBTABLE_SPARSITY 8 #define DD_SHRINK_FACTOR 2 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio Exp $"; #endif int *zdd_entry; int zddTotalNumberSwapping; static DdNode *empty; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static Move * zddSwapAny (DdManager *table, int x, int y); static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high); static Move * cuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size); static Move * cuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size); static int cuddZddSiftingBackward (DdManager *table, Move *moves, int size); static void zddReorderPreprocess (DdManager *table); static int zddReorderPostprocess (DdManager *table); static int zddShuffle (DdManager *table, int *permutation); static int zddSiftUp (DdManager *table, int x, int xLow); static void zddFixTree (DdManager *table, MtrNode *treenode); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Main dynamic reordering routine for ZDDs.] Description [Main dynamic reordering routine for ZDDs. Calls one of the possible reordering procedures:
        • Swapping
        • Sifting
        • Symmetric Sifting
        For sifting and symmetric sifting it is possible to request reordering to convergence.

        The core of all methods is the reordering procedure cuddZddSwapInPlace() which swaps two adjacent variables. Returns 1 in case of success; 0 otherwise. In the case of symmetric sifting (with and without convergence) returns 1 plus the number of symmetric variables, in case of success.] SideEffects [Changes the variable order for all ZDDs and clears the cache.] ******************************************************************************/ int Cudd_zddReduceHeap( DdManager * table /* DD manager */, Cudd_ReorderingType heuristic /* method used for reordering */, int minsize /* bound below which no reordering occurs */) { DdHook *hook; int result; unsigned int nextDyn; #ifdef DD_STATS unsigned int initialSize; unsigned int finalSize; #endif long localTime; /* Don't reorder if there are too many dead nodes. */ if (table->keysZ - table->deadZ < (unsigned) minsize) return(1); if (heuristic == CUDD_REORDER_SAME) { heuristic = table->autoMethodZ; } if (heuristic == CUDD_REORDER_NONE) { return(1); } /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore ** we count it. */ table->reorderings++; empty = table->zero; localTime = util_cpu_time(); /* Run the hook functions. */ hook = table->preReorderingHook; while (hook != NULL) { int res = (hook->f)(table, "ZDD", (void *)heuristic); if (res == 0) return(0); hook = hook->next; } /* Clear the cache and collect garbage. */ zddReorderPreprocess(table); zddTotalNumberSwapping = 0; #ifdef DD_STATS initialSize = table->keysZ; switch(heuristic) { case CUDD_REORDER_RANDOM: case CUDD_REORDER_RANDOM_PIVOT: (void) fprintf(table->out,"#:I_RANDOM "); break; case CUDD_REORDER_SIFT: case CUDD_REORDER_SIFT_CONVERGE: case CUDD_REORDER_SYMM_SIFT: case CUDD_REORDER_SYMM_SIFT_CONV: (void) fprintf(table->out,"#:I_SIFTING "); break; case CUDD_REORDER_LINEAR: case CUDD_REORDER_LINEAR_CONVERGE: (void) fprintf(table->out,"#:I_LINSIFT "); break; default: (void) fprintf(table->err,"Unsupported ZDD reordering method\n"); return(0); } (void) fprintf(table->out,"%8d: initial size",initialSize); #endif result = cuddZddTreeSifting(table,heuristic); #ifdef DD_STATS (void) fprintf(table->out,"\n"); finalSize = table->keysZ; (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", ((double)(util_cpu_time() - localTime)/1000.0)); (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", zddTotalNumberSwapping); #endif if (result == 0) return(0); if (!zddReorderPostprocess(table)) return(0); if (table->realignZ) { if (!cuddBddAlignToZdd(table)) return(0); } nextDyn = table->keysZ * DD_DYN_RATIO; if (table->reorderings < 20 || nextDyn > table->nextDyn) table->nextDyn = nextDyn; else table->nextDyn += 20; table->reordered = 1; /* Run hook functions. */ hook = table->postReorderingHook; while (hook != NULL) { int res = (hook->f)(table, "ZDD", (void *)localTime); if (res == 0) return(0); hook = hook->next; } /* Update cumulative reordering time. */ table->reordTime += util_cpu_time() - localTime; return(result); } /* end of Cudd_zddReduceHeap */ /**Function******************************************************************** Synopsis [Reorders ZDD variables according to given permutation.] Description [Reorders ZDD variables according to given permutation. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use. Returns 1 in case of success; 0 otherwise.] SideEffects [Changes the ZDD variable order for all diagrams and clears the cache.] SeeAlso [Cudd_zddReduceHeap] ******************************************************************************/ int Cudd_zddShuffleHeap( DdManager * table /* DD manager */, int * permutation /* required variable permutation */) { int result; empty = table->zero; zddReorderPreprocess(table); result = zddShuffle(table,permutation); if (!zddReorderPostprocess(table)) return(0); return(result); } /* end of Cudd_zddShuffleHeap */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Reorders ZDD variables according to the order of the BDD variables.] Description [Reorders ZDD variables according to the order of the BDD variables. This function can be called at the end of BDD reordering to insure that the order of the ZDD variables is consistent with the order of the BDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M be the ratio of the two numbers. cuddZddAlignToBdd then considers the ZDD variables from M*i to (M+1)*i-1 as corresponding to BDD variable i. This function should be normally called from Cudd_ReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.] SideEffects [Changes the ZDD variable order for all diagrams and performs garbage collection of the ZDD unique table.] SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap] ******************************************************************************/ int cuddZddAlignToBdd( DdManager * table /* DD manager */) { int *invpermZ; /* permutation array */ int M; /* ratio of ZDD variables to BDD variables */ int i,j; /* loop indices */ int result; /* return value */ /* We assume that a ratio of 0 is OK. */ if (table->sizeZ == 0) return(1); empty = table->zero; M = table->sizeZ / table->size; /* Check whether the number of ZDD variables is a multiple of the ** number of BDD variables. */ if (M * table->size != table->sizeZ) return(0); /* Create and initialize the inverse permutation array. */ invpermZ = ABC_ALLOC(int,table->sizeZ); if (invpermZ == NULL) { table->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < table->size; i++) { int index = table->invperm[i]; int indexZ = index * M; int levelZ = table->permZ[indexZ]; levelZ = (levelZ / M) * M; for (j = 0; j < M; j++) { invpermZ[M * i + j] = table->invpermZ[levelZ + j]; } } /* Eliminate dead nodes. Do not scan the cache again, because we ** assume that Cudd_ReduceHeap has already cleared it. */ cuddGarbageCollect(table,0); result = zddShuffle(table, invpermZ); ABC_FREE(invpermZ); /* Fix the ZDD variable group tree. */ zddFixTree(table,table->treeZ); return(result); } /* end of cuddZddAlignToBdd */ /**Function******************************************************************** Synopsis [Finds the next subtable with a larger index.] Description [Finds the next subtable with a larger index. Returns the index.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddNextHigh( DdManager * table, int x) { return(x + 1); } /* end of cuddZddNextHigh */ /**Function******************************************************************** Synopsis [Finds the next subtable with a smaller index.] Description [Finds the next subtable with a smaller index. Returns the index.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddNextLow( DdManager * table, int x) { return(x - 1); } /* end of cuddZddNextLow */ /**Function******************************************************************** Synopsis [Comparison function used by qsort.] Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddUniqueCompare( int * ptr_x, int * ptr_y) { return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]); } /* end of cuddZddUniqueCompare */ /**Function******************************************************************** Synopsis [Swaps two adjacent variables.] Description [Swaps two adjacent variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddZddSwapInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddSwapInPlace( DdManager * table, int x, int y) { DdNodePtr *xlist, *ylist; int xindex, yindex; int xslots, yslots; int xshift, yshift; int oldxkeys, oldykeys; int newxkeys, newykeys; int i; int posn; DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; DdNode *newf1=NULL, *newf0, *next; DdNodePtr g, *lastP, *previousP; #ifdef DD_DEBUG assert(x < y); assert(cuddZddNextHigh(table,x) == y); assert(table->subtableZ[x].keys != 0); assert(table->subtableZ[y].keys != 0); assert(table->subtableZ[x].dead == 0); assert(table->subtableZ[y].dead == 0); #endif zddTotalNumberSwapping++; /* Get parameters of x subtable. */ xindex = table->invpermZ[x]; xlist = table->subtableZ[x].nodelist; oldxkeys = table->subtableZ[x].keys; xslots = table->subtableZ[x].slots; xshift = table->subtableZ[x].shift; newxkeys = 0; yindex = table->invpermZ[y]; ylist = table->subtableZ[y].nodelist; oldykeys = table->subtableZ[y].keys; yslots = table->subtableZ[y].slots; yshift = table->subtableZ[y].shift; newykeys = oldykeys; /* The nodes in the x layer that don't depend on y directly ** will stay there; the others are put in a chain. ** The chain is handled as a FIFO; g points to the beginning and ** last points to the end. */ g = NULL; lastP = &g; for (i = 0; i < xslots; i++) { previousP = &(xlist[i]); f = *previousP; while (f != NULL) { next = f->next; f1 = cuddT(f); f0 = cuddE(f); if ((f1->index != (DdHalfWord) yindex) && (f0->index != (DdHalfWord) yindex)) { /* stays */ newxkeys++; *previousP = f; previousP = &(f->next); } else { f->index = yindex; *lastP = f; lastP = &(f->next); } f = next; } /* while there are elements in the collision chain */ *previousP = NULL; } /* for each slot of the x subtable */ *lastP = NULL; #ifdef DD_COUNT table->swapSteps += oldxkeys - newxkeys; #endif /* Take care of the x nodes that must be re-expressed. ** They form a linked list pointed by g. Their index has been ** changed to yindex already. */ f = g; while (f != NULL) { next = f->next; /* Find f1, f0, f11, f10, f01, f00. */ f1 = cuddT(f); if ((int) f1->index == yindex) { f11 = cuddT(f1); f10 = cuddE(f1); } else { f11 = empty; f10 = f1; } f0 = cuddE(f); if ((int) f0->index == yindex) { f01 = cuddT(f0); f00 = cuddE(f0); } else { f01 = empty; f00 = f0; } /* Decrease ref count of f1. */ cuddSatDec(f1->ref); /* Create the new T child. */ if (f11 == empty) { if (f01 != empty) { newf1 = f01; cuddSatInc(newf1->ref); } /* else case was already handled when finding nodes ** with both children below level y */ } else { /* Check xlist for triple (xindex, f11, f01). */ posn = ddHash(cuddF2L(f11), cuddF2L(f01), xshift); /* For each element newf1 in collision list xlist[posn]. */ newf1 = xlist[posn]; while (newf1 != NULL) { if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { cuddSatInc(newf1->ref); break; /* match */ } newf1 = newf1->next; } /* while newf1 */ if (newf1 == NULL) { /* no match */ newf1 = cuddDynamicAllocNode(table); if (newf1 == NULL) goto zddSwapOutOfMem; newf1->index = xindex; newf1->ref = 1; cuddT(newf1) = f11; cuddE(newf1) = f01; /* Insert newf1 in the collision list xlist[pos]; ** increase the ref counts of f11 and f01 */ newxkeys++; newf1->next = xlist[posn]; xlist[posn] = newf1; cuddSatInc(f11->ref); cuddSatInc(f01->ref); } } cuddT(f) = newf1; /* Do the same for f0. */ /* Decrease ref count of f0. */ cuddSatDec(f0->ref); /* Create the new E child. */ if (f10 == empty) { newf0 = f00; cuddSatInc(newf0->ref); } else { /* Check xlist for triple (xindex, f10, f00). */ posn = ddHash(cuddF2L(f10), cuddF2L(f00), xshift); /* For each element newf0 in collision list xlist[posn]. */ newf0 = xlist[posn]; while (newf0 != NULL) { if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { cuddSatInc(newf0->ref); break; /* match */ } newf0 = newf0->next; } /* while newf0 */ if (newf0 == NULL) { /* no match */ newf0 = cuddDynamicAllocNode(table); if (newf0 == NULL) goto zddSwapOutOfMem; newf0->index = xindex; newf0->ref = 1; cuddT(newf0) = f10; cuddE(newf0) = f00; /* Insert newf0 in the collision list xlist[posn]; ** increase the ref counts of f10 and f00. */ newxkeys++; newf0->next = xlist[posn]; xlist[posn] = newf0; cuddSatInc(f10->ref); cuddSatInc(f00->ref); } } cuddE(f) = newf0; /* Insert the modified f in ylist. ** The modified f does not already exists in ylist. ** (Because of the uniqueness of the cofactors.) */ posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), yshift); newykeys++; f->next = ylist[posn]; ylist[posn] = f; f = next; } /* while f != NULL */ /* GC the y layer. */ /* For each node f in ylist. */ for (i = 0; i < yslots; i++) { previousP = &(ylist[i]); f = *previousP; while (f != NULL) { next = f->next; if (f->ref == 0) { cuddSatDec(cuddT(f)->ref); cuddSatDec(cuddE(f)->ref); cuddDeallocNode(table, f); newykeys--; } else { *previousP = f; previousP = &(f->next); } f = next; } /* while f */ *previousP = NULL; } /* for i */ /* Set the appropriate fields in table. */ table->subtableZ[x].nodelist = ylist; table->subtableZ[x].slots = yslots; table->subtableZ[x].shift = yshift; table->subtableZ[x].keys = newykeys; table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; table->subtableZ[y].nodelist = xlist; table->subtableZ[y].slots = xslots; table->subtableZ[y].shift = xshift; table->subtableZ[y].keys = newxkeys; table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; table->permZ[xindex] = y; table->permZ[yindex] = x; table->invpermZ[x] = yindex; table->invpermZ[y] = xindex; table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; /* Update univ section; univ[x] remains the same. */ table->univ[y] = cuddT(table->univ[x]); return (table->keysZ); zddSwapOutOfMem: (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); return (0); } /* end of cuddZddSwapInPlace */ /**Function******************************************************************** Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] Description [Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps.

        1. Select two variables (RANDOM or HEURISTIC).
        2. Permute these variables.
        3. If the nodes have decreased accept the permutation.
        4. Otherwise reconstruct the original heap.
        5. Loop.
        Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddSwapping( DdManager * table, int lower, int upper, Cudd_ReorderingType heuristic) { int i, j; int max, keys; int nvars; int x, y; int iterate; int previousSize; Move *moves, *move; int pivot = -1; int modulo; int result; #ifdef DD_DEBUG /* Sanity check */ assert(lower >= 0 && upper < table->sizeZ && lower <= upper); #endif nvars = upper - lower + 1; iterate = nvars; for (i = 0; i < iterate; i++) { if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { /* Find pivot <= id with maximum keys. */ for (max = -1, j = lower; j <= upper; j++) { if ((keys = table->subtableZ[j].keys) > max) { max = keys; pivot = j; } } modulo = upper - pivot; if (modulo == 0) { y = pivot; /* y = nvars-1 */ } else { /* y = random # from {pivot+1 .. nvars-1} */ y = pivot + 1 + (int) (Cudd_Random() % modulo); } modulo = pivot - lower - 1; if (modulo < 1) { /* if pivot = 1 or 0 */ x = lower; } else { do { /* x = random # from {0 .. pivot-2} */ x = (int) Cudd_Random() % modulo; } while (x == y); /* Is this condition really needed, since x and y are in regions separated by pivot? */ } } else { x = (int) (Cudd_Random() % nvars) + lower; do { y = (int) (Cudd_Random() % nvars) + lower; } while (x == y); } previousSize = table->keysZ; moves = zddSwapAny(table, x, y); if (moves == NULL) goto cuddZddSwappingOutOfMem; result = cuddZddSiftingBackward(table, moves, previousSize); if (!result) goto cuddZddSwappingOutOfMem; while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } #ifdef DD_STATS if (table->keysZ < (unsigned) previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > (unsigned) previousSize) { (void) fprintf(table->out,"+"); /* should never happen */ } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } return(1); cuddZddSwappingOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(0); } /* end of cuddZddSwapping */ /**Function******************************************************************** Synopsis [Implementation of Rudell's sifting algorithm.] Description [Implementation of Rudell's sifting algorithm. Assumes that no dead nodes are present.
        1. Order all the variables according to the number of entries in each unique table.
        2. Sift the variable up and down, remembering each time the total size of the DD heap.
        3. Select the best permutation.
        4. Repeat 3 and 4 for all variables.
        Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddSifting( DdManager * table, int lower, int upper) { int i; int *var; int size; int x; int result; #ifdef DD_STATS int previousSize; #endif size = table->sizeZ; /* Find order in which to sift variables. */ var = NULL; zdd_entry = ABC_ALLOC(int, size); if (zdd_entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddZddSiftingOutOfMem; } var = ABC_ALLOC(int, size); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddZddSiftingOutOfMem; } for (i = 0; i < size; i++) { x = table->permZ[i]; zdd_entry[i] = table->subtableZ[x].keys; var[i] = i; } qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); /* Now sift. */ for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { if (zddTotalNumberSwapping >= table->siftMaxSwap) break; x = table->permZ[var[i]]; if (x < lower || x > upper) continue; #ifdef DD_STATS previousSize = table->keysZ; #endif result = cuddZddSiftingAux(table, x, lower, upper); if (!result) goto cuddZddSiftingOutOfMem; #ifdef DD_STATS if (table->keysZ < (unsigned) previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > (unsigned) previousSize) { (void) fprintf(table->out,"+"); /* should never happen */ (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } ABC_FREE(var); ABC_FREE(zdd_entry); return(1); cuddZddSiftingOutOfMem: if (zdd_entry != NULL) ABC_FREE(zdd_entry); if (var != NULL) ABC_FREE(var); return(0); } /* end of cuddZddSifting */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Swaps any two variables.] Description [Swaps any two variables. Returns the set of moves.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * zddSwapAny( DdManager * table, int x, int y) { Move *move, *moves; int tmp, size; int x_ref, y_ref; int x_next, y_next; int limit_size; if (x > y) { /* make x precede y */ tmp = x; x = y; y = tmp; } x_ref = x; y_ref = y; x_next = cuddZddNextHigh(table, x); y_next = cuddZddNextLow(table, y); moves = NULL; limit_size = table->keysZ; for (;;) { if (x_next == y_next) { /* x < x_next = y_next < y */ size = cuddZddSwapInPlace(table, x, x_next); if (size == 0) goto zddSwapAnyOutOfMem; move = (Move *) cuddDynamicAllocNode(table); if (move == NULL) goto zddSwapAnyOutOfMem; move->x = x; move->y = x_next; move->size = size; move->next = moves; moves = move; size = cuddZddSwapInPlace(table, y_next, y); if (size == 0) goto zddSwapAnyOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto zddSwapAnyOutOfMem; move->x = y_next; move->y = y; move->size = size; move->next = moves; moves = move; size = cuddZddSwapInPlace(table, x, x_next); if (size == 0) goto zddSwapAnyOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto zddSwapAnyOutOfMem; move->x = x; move->y = x_next; move->size = size; move->next = moves; moves = move; tmp = x; x = y; y = tmp; } else if (x == y_next) { /* x = y_next < y = x_next */ size = cuddZddSwapInPlace(table, x, x_next); if (size == 0) goto zddSwapAnyOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto zddSwapAnyOutOfMem; move->x = x; move->y = x_next; move->size = size; move->next = moves; moves = move; tmp = x; x = y; y = tmp; } else { size = cuddZddSwapInPlace(table, x, x_next); if (size == 0) goto zddSwapAnyOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto zddSwapAnyOutOfMem; move->x = x; move->y = x_next; move->size = size; move->next = moves; moves = move; size = cuddZddSwapInPlace(table, y_next, y); if (size == 0) goto zddSwapAnyOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto zddSwapAnyOutOfMem; move->x = y_next; move->y = y; move->size = size; move->next = moves; moves = move; x = x_next; y = y_next; } x_next = cuddZddNextHigh(table, x); y_next = cuddZddNextLow(table, y); if (x_next > y_ref) break; /* if x == y_ref */ if ((double) size > table->maxGrowth * (double) limit_size) break; if (size < limit_size) limit_size = size; } if (y_next >= x_ref) { size = cuddZddSwapInPlace(table, y_next, y); if (size == 0) goto zddSwapAnyOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto zddSwapAnyOutOfMem; move->x = y_next; move->y = y; move->size = size; move->next = moves; moves = move; } return(moves); zddSwapAnyOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(NULL); } /* end of zddSwapAny */ /**Function******************************************************************** Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.] Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddSiftingAux( DdManager * table, int x, int x_low, int x_high) { Move *move; Move *moveUp; /* list of up move */ Move *moveDown; /* list of down move */ int initial_size; int result; initial_size = table->keysZ; #ifdef DD_DEBUG assert(table->subtableZ[x].keys > 0); #endif moveDown = NULL; moveUp = NULL; if (x == x_low) { moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); /* after that point x --> x_high */ if (moveDown == NULL) goto cuddZddSiftingAuxOutOfMem; result = cuddZddSiftingBackward(table, moveDown, initial_size); /* move backward and stop at best position */ if (!result) goto cuddZddSiftingAuxOutOfMem; } else if (x == x_high) { moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); /* after that point x --> x_low */ if (moveUp == NULL) goto cuddZddSiftingAuxOutOfMem; result = cuddZddSiftingBackward(table, moveUp, initial_size); /* move backward and stop at best position */ if (!result) goto cuddZddSiftingAuxOutOfMem; } else if ((x - x_low) > (x_high - x)) { /* must go down first:shorter */ moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); /* after that point x --> x_high */ if (moveDown == NULL) goto cuddZddSiftingAuxOutOfMem; moveUp = cuddZddSiftingUp(table, moveDown->y, x_low, initial_size); if (moveUp == NULL) goto cuddZddSiftingAuxOutOfMem; result = cuddZddSiftingBackward(table, moveUp, initial_size); /* move backward and stop at best position */ if (!result) goto cuddZddSiftingAuxOutOfMem; } else { moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); /* after that point x --> x_high */ if (moveUp == NULL) goto cuddZddSiftingAuxOutOfMem; moveDown = cuddZddSiftingDown(table, moveUp->x, x_high, initial_size); /* then move up */ if (moveDown == NULL) goto cuddZddSiftingAuxOutOfMem; result = cuddZddSiftingBackward(table, moveDown, initial_size); /* move backward and stop at best position */ if (!result) goto cuddZddSiftingAuxOutOfMem; } while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } return(1); cuddZddSiftingAuxOutOfMem: while (moveDown != NULL) { move = moveDown->next; cuddDeallocMove(table, moveDown); moveDown = move; } while (moveUp != NULL) { move = moveUp->next; cuddDeallocMove(table, moveUp); moveUp = move; } return(0); } /* end of cuddZddSiftingAux */ /**Function******************************************************************** Synopsis [Sifts a variable up.] Description [Sifts a variable up. Moves y up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * cuddZddSiftingUp( DdManager * table, int x, int x_low, int initial_size) { Move *moves; Move *move; int y; int size; int limit_size = initial_size; moves = NULL; y = cuddZddNextLow(table, x); while (y >= x_low) { size = cuddZddSwapInPlace(table, y, x); if (size == 0) goto cuddZddSiftingUpOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto cuddZddSiftingUpOutOfMem; move->x = y; move->y = x; move->size = size; move->next = moves; moves = move; if ((double)size > (double)limit_size * table->maxGrowth) break; if (size < limit_size) limit_size = size; x = y; y = cuddZddNextLow(table, x); } return(moves); cuddZddSiftingUpOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(NULL); } /* end of cuddZddSiftingUp */ /**Function******************************************************************** Synopsis [Sifts a variable down.] Description [Sifts a variable down. Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * cuddZddSiftingDown( DdManager * table, int x, int x_high, int initial_size) { Move *moves; Move *move; int y; int size; int limit_size = initial_size; moves = NULL; y = cuddZddNextHigh(table, x); while (y <= x_high) { size = cuddZddSwapInPlace(table, x, y); if (size == 0) goto cuddZddSiftingDownOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto cuddZddSiftingDownOutOfMem; move->x = x; move->y = y; move->size = size; move->next = moves; moves = move; if ((double)size > (double)limit_size * table->maxGrowth) break; if (size < limit_size) limit_size = size; x = y; y = cuddZddNextHigh(table, x); } return(moves); cuddZddSiftingDownOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(NULL); } /* end of cuddZddSiftingDown */ /**Function******************************************************************** Synopsis [Given a set of moves, returns the ZDD heap to the position giving the minimum size.] Description [Given a set of moves, returns the ZDD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddSiftingBackward( DdManager * table, Move * moves, int size) { int i; int i_best; Move *move; int res; /* Find the minimum size among moves. */ i_best = -1; for (move = moves, i = 0; move != NULL; move = move->next, i++) { if (move->size < size) { i_best = i; size = move->size; } } for (move = moves, i = 0; move != NULL; move = move->next, i++) { if (i == i_best) break; res = cuddZddSwapInPlace(table, move->x, move->y); if (!res) return(0); if (i_best == -1 && res == size) break; } return(1); } /* end of cuddZddSiftingBackward */ /**Function******************************************************************** Synopsis [Prepares the ZDD heap for dynamic reordering.] Description [Prepares the ZDD heap for dynamic reordering. Does garbage collection, to guarantee that there are no dead nodes; and clears the cache, which is invalidated by dynamic reordering.] SideEffects [None] ******************************************************************************/ static void zddReorderPreprocess( DdManager * table) { /* Clear the cache. */ cuddCacheFlush(table); /* Eliminate dead nodes. Do not scan the cache again. */ cuddGarbageCollect(table,0); return; } /* end of ddReorderPreprocess */ /**Function******************************************************************** Synopsis [Shrinks almost empty ZDD subtables at the end of reordering to guarantee that they have a reasonable load factor.] Description [Shrinks almost empty subtables at the end of reordering to guarantee that they have a reasonable load factor. However, if there many nodes are being reclaimed, then no resizing occurs. Returns 1 in case of success; 0 otherwise.] SideEffects [None] ******************************************************************************/ static int zddReorderPostprocess( DdManager * table) { int i, j, posn; DdNodePtr *nodelist, *oldnodelist; DdNode *node, *next; unsigned int slots, oldslots; extern DD_OOMFP MMoutOfMemory; DD_OOMFP saveHandler; #ifdef DD_VERBOSE (void) fflush(table->out); #endif /* If we have very many reclaimed nodes, we do not want to shrink ** the subtables, because this will lead to more garbage ** collections. More garbage collections mean shorter mean life for ** nodes with zero reference count; hence lower probability of finding ** a result in the cache. */ if (table->reclaimed > table->allocated / 2) return(1); /* Resize subtables. */ for (i = 0; i < table->sizeZ; i++) { int shift; oldslots = table->subtableZ[i].slots; if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY || oldslots <= table->initSlots) continue; oldnodelist = table->subtableZ[i].nodelist; slots = oldslots >> 1; saveHandler = MMoutOfMemory; MMoutOfMemory = Cudd_OutOfMem; nodelist = ABC_ALLOC(DdNodePtr, slots); MMoutOfMemory = saveHandler; if (nodelist == NULL) { return(1); } table->subtableZ[i].nodelist = nodelist; table->subtableZ[i].slots = slots; table->subtableZ[i].shift++; table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; #ifdef DD_VERBOSE (void) fprintf(table->err, "shrunk layer %d (%d keys) from %d to %d slots\n", i, table->subtableZ[i].keys, oldslots, slots); #endif for (j = 0; (unsigned) j < slots; j++) { nodelist[j] = NULL; } shift = table->subtableZ[i].shift; for (j = 0; (unsigned) j < oldslots; j++) { node = oldnodelist[j]; while (node != NULL) { next = node->next; posn = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift); node->next = nodelist[posn]; nodelist[posn] = node; node = next; } } ABC_FREE(oldnodelist); table->memused += (slots - oldslots) * sizeof(DdNode *); table->slots += slots - oldslots; table->minDead = (unsigned) (table->gcFrac * (double) table->slots); table->cacheSlack = (int) ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) - 2 * (int) table->cacheSlots; } /* We don't look at the constant subtable, because it is not ** affected by reordering. */ return(1); } /* end of zddReorderPostprocess */ /**Function******************************************************************** Synopsis [Reorders ZDD variables according to a given permutation.] Description [Reorders ZDD variables according to a given permutation. The i-th permutation array contains the index of the variable that should be brought to the i-th level. zddShuffle assumes that no dead nodes are present. The reordering is achieved by a series of upward sifts. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int zddShuffle( DdManager * table, int * permutation) { int index; int level; int position; int numvars; int result; #ifdef DD_STATS long localTime; int initialSize; int finalSize; int previousSize; #endif zddTotalNumberSwapping = 0; #ifdef DD_STATS localTime = util_cpu_time(); initialSize = table->keysZ; (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", initialSize); #endif numvars = table->sizeZ; for (level = 0; level < numvars; level++) { index = permutation[level]; position = table->permZ[index]; #ifdef DD_STATS previousSize = table->keysZ; #endif result = zddSiftUp(table,position,level); if (!result) return(0); #ifdef DD_STATS if (table->keysZ < (unsigned) previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > (unsigned) previousSize) { (void) fprintf(table->out,"+"); /* should never happen */ } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } #ifdef DD_STATS (void) fprintf(table->out,"\n"); finalSize = table->keysZ; (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", ((double)(util_cpu_time() - localTime)/1000.0)); (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", zddTotalNumberSwapping); #endif return(1); } /* end of zddShuffle */ /**Function******************************************************************** Synopsis [Moves one ZDD variable up.] Description [Takes a ZDD variable from position x and sifts it up to position xLow; xLow should be less than or equal to x. Returns 1 if successful; 0 otherwise] SideEffects [None] SeeAlso [] ******************************************************************************/ static int zddSiftUp( DdManager * table, int x, int xLow) { int y; int size; y = cuddZddNextLow(table,x); while (y >= xLow) { size = cuddZddSwapInPlace(table,y,x); if (size == 0) { return(0); } x = y; y = cuddZddNextLow(table,x); } return(1); } /* end of zddSiftUp */ /**Function******************************************************************** Synopsis [Fixes the ZDD variable group tree after a shuffle.] Description [Fixes the ZDD variable group tree after a shuffle. Assumes that the order of the variables in a terminal node has not been changed.] SideEffects [Changes the ZDD variable group tree.] SeeAlso [] ******************************************************************************/ static void zddFixTree( DdManager * table, MtrNode * treenode) { if (treenode == NULL) return; treenode->low = ((int) treenode->index < table->sizeZ) ? table->permZ[treenode->index] : treenode->index; if (treenode->child != NULL) { zddFixTree(table, treenode->child); } if (treenode->younger != NULL) zddFixTree(table, treenode->younger); if (treenode->parent != NULL && treenode->low < treenode->parent->low) { treenode->parent->low = treenode->low; treenode->parent->index = treenode->index; } return; } /* end of zddFixTree */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddSetop.c000066400000000000000000000741661300674244400242620ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddSetop.c] PackageName [cudd] Synopsis [Set operations on ZDDs.] Description [External procedures included in this module:
        • Cudd_zddIte()
        • Cudd_zddUnion()
        • Cudd_zddIntersect()
        • Cudd_zddDiff()
        • Cudd_zddDiffConst()
        • Cudd_zddSubset1()
        • Cudd_zddSubset0()
        • Cudd_zddChange()
        Internal procedures included in this module:
        • cuddZddIte()
        • cuddZddUnion()
        • cuddZddIntersect()
        • cuddZddDiff()
        • cuddZddChangeAux()
        • cuddZddSubset1()
        • cuddZddSubset0()
        Static procedures included in this module:
        • zdd_subset1_aux()
        • zdd_subset0_aux()
        • zddVarToConst()
        ] SeeAlso [] Author [Hyong-Kyoon Shin, In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddSetop.c,v 1.25 2004/08/13 18:04:54 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * zdd_subset1_aux (DdManager *zdd, DdNode *P, DdNode *zvar); static DdNode * zdd_subset0_aux (DdManager *zdd, DdNode *P, DdNode *zvar); static void zddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the ITE of three ZDDs.] Description [Computes the ITE of three ZDDs. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_zddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *res; do { dd->reordered = 0; res = cuddZddIte(dd, f, g, h); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddIte */ /**Function******************************************************************** Synopsis [Computes the union of two ZDDs.] Description [Computes the union of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_zddUnion( DdManager * dd, DdNode * P, DdNode * Q) { DdNode *res; do { dd->reordered = 0; res = cuddZddUnion(dd, P, Q); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddUnion */ /**Function******************************************************************** Synopsis [Computes the intersection of two ZDDs.] Description [Computes the intersection of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_zddIntersect( DdManager * dd, DdNode * P, DdNode * Q) { DdNode *res; do { dd->reordered = 0; res = cuddZddIntersect(dd, P, Q); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddIntersect */ /**Function******************************************************************** Synopsis [Computes the difference of two ZDDs.] Description [Computes the difference of two ZDDs. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_zddDiffConst] ******************************************************************************/ DdNode * Cudd_zddDiff( DdManager * dd, DdNode * P, DdNode * Q) { DdNode *res; do { dd->reordered = 0; res = cuddZddDiff(dd, P, Q); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddDiff */ /**Function******************************************************************** Synopsis [Performs the inclusion test for ZDDs (P implies Q).] Description [Inclusion test for ZDDs (P implies Q). No new nodes are generated by this procedure. Returns empty if true; a valid pointer different from empty or DD_NON_CONSTANT otherwise.] SideEffects [None] SeeAlso [Cudd_zddDiff] ******************************************************************************/ DdNode * Cudd_zddDiffConst( DdManager * zdd, DdNode * P, DdNode * Q) { int p_top, q_top; DdNode *empty = DD_ZERO(zdd), *t, *res; DdManager *table = zdd; statLine(zdd); if (P == empty) return(empty); if (Q == empty) return(P); if (P == Q) return(empty); /* Check cache. The cache is shared by cuddZddDiff(). */ res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); if (res != NULL) return(res); if (cuddIsConstant(P)) p_top = P->index; else p_top = zdd->permZ[P->index]; if (cuddIsConstant(Q)) q_top = Q->index; else q_top = zdd->permZ[Q->index]; if (p_top < q_top) { res = DD_NON_CONSTANT; } else if (p_top > q_top) { res = Cudd_zddDiffConst(zdd, P, cuddE(Q)); } else { t = Cudd_zddDiffConst(zdd, cuddT(P), cuddT(Q)); if (t != empty) res = DD_NON_CONSTANT; else res = Cudd_zddDiffConst(zdd, cuddE(P), cuddE(Q)); } cuddCacheInsert2(table, cuddZddDiff, P, Q, res); return(res); } /* end of Cudd_zddDiffConst */ /**Function******************************************************************** Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.] Description [Computes the positive cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is asserted. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_zddSubset0] ******************************************************************************/ DdNode * Cudd_zddSubset1( DdManager * dd, DdNode * P, int var) { DdNode *r; do { dd->reordered = 0; r = cuddZddSubset1(dd, P, var); } while (dd->reordered == 1); return(r); } /* end of Cudd_zddSubset1 */ /**Function******************************************************************** Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.] Description [Computes the negative cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is negated. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_zddSubset1] ******************************************************************************/ DdNode * Cudd_zddSubset0( DdManager * dd, DdNode * P, int var) { DdNode *r; do { dd->reordered = 0; r = cuddZddSubset0(dd, P, var); } while (dd->reordered == 1); return(r); } /* end of Cudd_zddSubset0 */ /**Function******************************************************************** Synopsis [Substitutes a variable with its complement in a ZDD.] Description [Substitutes a variable with its complement in a ZDD. returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_zddChange( DdManager * dd, DdNode * P, int var) { DdNode *res; if ((unsigned int) var >= CUDD_MAXINDEX - 1) return(NULL); do { dd->reordered = 0; res = cuddZddChange(dd, P, var); } while (dd->reordered == 1); return(res); } /* end of Cudd_zddChange */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddIte.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddZddIte( DdManager * dd, DdNode * f, DdNode * g, DdNode * h) { DdNode *tautology, *empty; DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e; unsigned int topf,topg,toph,v,top; int index; statLine(dd); /* Trivial cases. */ /* One variable cases. */ if (f == (empty = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ return(h); } topf = cuddIZ(dd,f->index); topg = cuddIZ(dd,g->index); toph = cuddIZ(dd,h->index); v = ddMin(topg,toph); top = ddMin(topf,v); tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top]; if (f == tautology) { /* ITE(1,G,H) = G */ return(g); } /* From now on, f is known to not be a constant. */ zddVarToConst(f,&g,&h,tautology,empty); /* Check remaining one variable cases. */ if (g == h) { /* ITE(F,G,G) = G */ return(g); } if (g == tautology) { /* ITE(F,1,0) = F */ if (h == empty) return(f); } /* Check cache. */ r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h); if (r != NULL) { return(r); } /* Recompute these because they may have changed in zddVarToConst. */ topg = cuddIZ(dd,g->index); toph = cuddIZ(dd,h->index); v = ddMin(topg,toph); if (topf < v) { r = cuddZddIte(dd,cuddE(f),g,h); if (r == NULL) return(NULL); } else if (topf > v) { if (topg > v) { Gvn = g; index = h->index; } else { Gvn = cuddE(g); index = g->index; } if (toph > v) { Hv = empty; Hvn = h; } else { Hv = cuddT(h); Hvn = cuddE(h); } e = cuddZddIte(dd,f,Gvn,Hvn); if (e == NULL) return(NULL); cuddRef(e); r = cuddZddGetNode(dd,index,Hv,e); if (r == NULL) { Cudd_RecursiveDerefZdd(dd,e); return(NULL); } cuddDeref(e); } else { index = f->index; if (topg > v) { Gv = empty; Gvn = g; } else { Gv = cuddT(g); Gvn = cuddE(g); } if (toph > v) { Hv = empty; Hvn = h; } else { Hv = cuddT(h); Hvn = cuddE(h); } e = cuddZddIte(dd,cuddE(f),Gvn,Hvn); if (e == NULL) return(NULL); cuddRef(e); t = cuddZddIte(dd,cuddT(f),Gv,Hv); if (t == NULL) { Cudd_RecursiveDerefZdd(dd,e); return(NULL); } cuddRef(t); r = cuddZddGetNode(dd,index,t,e); if (r == NULL) { Cudd_RecursiveDerefZdd(dd,e); Cudd_RecursiveDerefZdd(dd,t); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r); return(r); } /* end of cuddZddIte */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddUnion.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddZddUnion( DdManager * zdd, DdNode * P, DdNode * Q) { int p_top, q_top; DdNode *empty = DD_ZERO(zdd), *t, *e, *res; DdManager *table = zdd; statLine(zdd); if (P == empty) return(Q); if (Q == empty) return(P); if (P == Q) return(P); /* Check cache */ res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q); if (res != NULL) return(res); if (cuddIsConstant(P)) p_top = P->index; else p_top = zdd->permZ[P->index]; if (cuddIsConstant(Q)) q_top = Q->index; else q_top = zdd->permZ[Q->index]; if (p_top < q_top) { e = cuddZddUnion(zdd, cuddE(P), Q); if (e == NULL) return (NULL); cuddRef(e); res = cuddZddGetNode(zdd, P->index, cuddT(P), e); if (res == NULL) { Cudd_RecursiveDerefZdd(table, e); return(NULL); } cuddDeref(e); } else if (p_top > q_top) { e = cuddZddUnion(zdd, P, cuddE(Q)); if (e == NULL) return(NULL); cuddRef(e); res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e); if (res == NULL) { Cudd_RecursiveDerefZdd(table, e); return(NULL); } cuddDeref(e); } else { t = cuddZddUnion(zdd, cuddT(P), cuddT(Q)); if (t == NULL) return(NULL); cuddRef(t); e = cuddZddUnion(zdd, cuddE(P), cuddE(Q)); if (e == NULL) { Cudd_RecursiveDerefZdd(table, t); return(NULL); } cuddRef(e); res = cuddZddGetNode(zdd, P->index, t, e); if (res == NULL) { Cudd_RecursiveDerefZdd(table, t); Cudd_RecursiveDerefZdd(table, e); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert2(table, cuddZddUnion, P, Q, res); return(res); } /* end of cuddZddUnion */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddIntersect.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddZddIntersect( DdManager * zdd, DdNode * P, DdNode * Q) { int p_top, q_top; DdNode *empty = DD_ZERO(zdd), *t, *e, *res; DdManager *table = zdd; statLine(zdd); if (P == empty) return(empty); if (Q == empty) return(empty); if (P == Q) return(P); /* Check cache. */ res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q); if (res != NULL) return(res); if (cuddIsConstant(P)) p_top = P->index; else p_top = zdd->permZ[P->index]; if (cuddIsConstant(Q)) q_top = Q->index; else q_top = zdd->permZ[Q->index]; if (p_top < q_top) { res = cuddZddIntersect(zdd, cuddE(P), Q); if (res == NULL) return(NULL); } else if (p_top > q_top) { res = cuddZddIntersect(zdd, P, cuddE(Q)); if (res == NULL) return(NULL); } else { t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q)); if (t == NULL) return(NULL); cuddRef(t); e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q)); if (e == NULL) { Cudd_RecursiveDerefZdd(table, t); return(NULL); } cuddRef(e); res = cuddZddGetNode(zdd, P->index, t, e); if (res == NULL) { Cudd_RecursiveDerefZdd(table, t); Cudd_RecursiveDerefZdd(table, e); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert2(table, cuddZddIntersect, P, Q, res); return(res); } /* end of cuddZddIntersect */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddDiff.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddZddDiff( DdManager * zdd, DdNode * P, DdNode * Q) { int p_top, q_top; DdNode *empty = DD_ZERO(zdd), *t, *e, *res; DdManager *table = zdd; statLine(zdd); if (P == empty) return(empty); if (Q == empty) return(P); if (P == Q) return(empty); /* Check cache. The cache is shared by Cudd_zddDiffConst(). */ res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); if (res != NULL && res != DD_NON_CONSTANT) return(res); if (cuddIsConstant(P)) p_top = P->index; else p_top = zdd->permZ[P->index]; if (cuddIsConstant(Q)) q_top = Q->index; else q_top = zdd->permZ[Q->index]; if (p_top < q_top) { e = cuddZddDiff(zdd, cuddE(P), Q); if (e == NULL) return(NULL); cuddRef(e); res = cuddZddGetNode(zdd, P->index, cuddT(P), e); if (res == NULL) { Cudd_RecursiveDerefZdd(table, e); return(NULL); } cuddDeref(e); } else if (p_top > q_top) { res = cuddZddDiff(zdd, P, cuddE(Q)); if (res == NULL) return(NULL); } else { t = cuddZddDiff(zdd, cuddT(P), cuddT(Q)); if (t == NULL) return(NULL); cuddRef(t); e = cuddZddDiff(zdd, cuddE(P), cuddE(Q)); if (e == NULL) { Cudd_RecursiveDerefZdd(table, t); return(NULL); } cuddRef(e); res = cuddZddGetNode(zdd, P->index, t, e); if (res == NULL) { Cudd_RecursiveDerefZdd(table, t); Cudd_RecursiveDerefZdd(table, e); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert2(table, cuddZddDiff, P, Q, res); return(res); } /* end of cuddZddDiff */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddChange.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddZddChangeAux( DdManager * zdd, DdNode * P, DdNode * zvar) { int top_var, level; DdNode *res, *t, *e; DdNode *base = DD_ONE(zdd); DdNode *empty = DD_ZERO(zdd); statLine(zdd); if (P == empty) return(empty); if (P == base) return(zvar); /* Check cache. */ res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar); if (res != NULL) return(res); top_var = zdd->permZ[P->index]; level = zdd->permZ[zvar->index]; if (top_var > level) { res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd)); if (res == NULL) return(NULL); } else if (top_var == level) { res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P)); if (res == NULL) return(NULL); } else { t = cuddZddChangeAux(zdd, cuddT(P), zvar); if (t == NULL) return(NULL); cuddRef(t); e = cuddZddChangeAux(zdd, cuddE(P), zvar); if (e == NULL) { Cudd_RecursiveDerefZdd(zdd, t); return(NULL); } cuddRef(e); res = cuddZddGetNode(zdd, P->index, t, e); if (res == NULL) { Cudd_RecursiveDerefZdd(zdd, t); Cudd_RecursiveDerefZdd(zdd, e); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res); return(res); } /* end of cuddZddChangeAux */ /**Function******************************************************************** Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.] Description [Computes the positive cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is asserted. Returns a pointer to the result if successful; NULL otherwise. cuddZddSubset1 performs the same function as Cudd_zddSubset1, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.] SideEffects [None] SeeAlso [cuddZddSubset0 Cudd_zddSubset1] ******************************************************************************/ DdNode * cuddZddSubset1( DdManager * dd, DdNode * P, int var) { DdNode *zvar, *r; DdNode *base, *empty; base = DD_ONE(dd); empty = DD_ZERO(dd); zvar = cuddUniqueInterZdd(dd, var, base, empty); if (zvar == NULL) { return(NULL); } else { cuddRef(zvar); r = zdd_subset1_aux(dd, P, zvar); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, zvar); return(NULL); } cuddRef(r); Cudd_RecursiveDerefZdd(dd, zvar); } cuddDeref(r); return(r); } /* end of cuddZddSubset1 */ /**Function******************************************************************** Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.] Description [Computes the negative cofactor of a ZDD w.r.t. a variable. In terms of combinations, the result is the set of all combinations in which the variable is negated. Returns a pointer to the result if successful; NULL otherwise. cuddZddSubset0 performs the same function as Cudd_zddSubset0, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.] SideEffects [None] SeeAlso [cuddZddSubset1 Cudd_zddSubset0] ******************************************************************************/ DdNode * cuddZddSubset0( DdManager * dd, DdNode * P, int var) { DdNode *zvar, *r; DdNode *base, *empty; base = DD_ONE(dd); empty = DD_ZERO(dd); zvar = cuddUniqueInterZdd(dd, var, base, empty); if (zvar == NULL) { return(NULL); } else { cuddRef(zvar); r = zdd_subset0_aux(dd, P, zvar); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, zvar); return(NULL); } cuddRef(r); Cudd_RecursiveDerefZdd(dd, zvar); } cuddDeref(r); return(r); } /* end of cuddZddSubset0 */ /**Function******************************************************************** Synopsis [Substitutes a variable with its complement in a ZDD.] Description [Substitutes a variable with its complement in a ZDD. returns a pointer to the result if successful; NULL otherwise. cuddZddChange performs the same function as Cudd_zddChange, but does not restart if reordering has taken place. Therefore it can be called from within a recursive procedure.] SideEffects [None] SeeAlso [Cudd_zddChange] ******************************************************************************/ DdNode * cuddZddChange( DdManager * dd, DdNode * P, int var) { DdNode *zvar, *res; zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd)); if (zvar == NULL) return(NULL); cuddRef(zvar); res = cuddZddChangeAux(dd, P, zvar); if (res == NULL) { Cudd_RecursiveDerefZdd(dd,zvar); return(NULL); } cuddRef(res); Cudd_RecursiveDerefZdd(dd,zvar); cuddDeref(res); return(res); } /* end of cuddZddChange */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddSubset1.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * zdd_subset1_aux( DdManager * zdd, DdNode * P, DdNode * zvar) { int top_var, level; DdNode *res, *t, *e; DdNode *empty; statLine(zdd); empty = DD_ZERO(zdd); /* Check cache. */ res = cuddCacheLookup2Zdd(zdd, zdd_subset1_aux, P, zvar); if (res != NULL) return(res); if (cuddIsConstant(P)) { res = empty; cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res); return(res); } top_var = zdd->permZ[P->index]; level = zdd->permZ[zvar->index]; if (top_var > level) { res = empty; } else if (top_var == level) { res = cuddT(P); } else { t = zdd_subset1_aux(zdd, cuddT(P), zvar); if (t == NULL) return(NULL); cuddRef(t); e = zdd_subset1_aux(zdd, cuddE(P), zvar); if (e == NULL) { Cudd_RecursiveDerefZdd(zdd, t); return(NULL); } cuddRef(e); res = cuddZddGetNode(zdd, P->index, t, e); if (res == NULL) { Cudd_RecursiveDerefZdd(zdd, t); Cudd_RecursiveDerefZdd(zdd, e); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res); return(res); } /* end of zdd_subset1_aux */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddSubset0.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * zdd_subset0_aux( DdManager * zdd, DdNode * P, DdNode * zvar) { int top_var, level; DdNode *res, *t, *e; statLine(zdd); /* Check cache. */ res = cuddCacheLookup2Zdd(zdd, zdd_subset0_aux, P, zvar); if (res != NULL) return(res); if (cuddIsConstant(P)) { res = P; cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res); return(res); } top_var = zdd->permZ[P->index]; level = zdd->permZ[zvar->index]; if (top_var > level) { res = P; } else if (top_var == level) { res = cuddE(P); } else { t = zdd_subset0_aux(zdd, cuddT(P), zvar); if (t == NULL) return(NULL); cuddRef(t); e = zdd_subset0_aux(zdd, cuddE(P), zvar); if (e == NULL) { Cudd_RecursiveDerefZdd(zdd, t); return(NULL); } cuddRef(e); res = cuddZddGetNode(zdd, P->index, t, e); if (res == NULL) { Cudd_RecursiveDerefZdd(zdd, t); Cudd_RecursiveDerefZdd(zdd, e); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res); return(res); } /* end of zdd_subset0_aux */ /**Function******************************************************************** Synopsis [Replaces variables with constants if possible (part of canonical form).] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void zddVarToConst( DdNode * f, DdNode ** gp, DdNode ** hp, DdNode * base, DdNode * empty) { DdNode *g = *gp; DdNode *h = *hp; if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ *gp = base; } if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ *hp = empty; } } /* end of zddVarToConst */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddSymm.c000066400000000000000000001531741300674244400241120ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddSymm.c] PackageName [cudd] Synopsis [Functions for symmetry-based ZDD variable reordering.] Description [External procedures included in this module:
        • Cudd_zddSymmProfile()
        Internal procedures included in this module:
        • cuddZddSymmCheck()
        • cuddZddSymmSifting()
        • cuddZddSymmSiftingConv()
        Static procedures included in this module:
        • cuddZddUniqueCompare()
        • cuddZddSymmSiftingAux()
        • cuddZddSymmSiftingConvAux()
        • cuddZddSymmSifting_up()
        • cuddZddSymmSifting_down()
        • zdd_group_move()
        • cuddZddSymmSiftingBackward()
        • zdd_group_move_backward()
        ] SeeAlso [cuddSymmetry.c] Author [Hyong-Kyoon Shin, In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define ZDD_MV_OOM (Move *)1 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.29 2004/08/13 18:04:54 fabio Exp $"; #endif extern int *zdd_entry; extern int zddTotalNumberSwapping; static DdNode *empty; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int cuddZddSymmSiftingAux (DdManager *table, int x, int x_low, int x_high); static int cuddZddSymmSiftingConvAux (DdManager *table, int x, int x_low, int x_high); static Move * cuddZddSymmSifting_up (DdManager *table, int x, int x_low, int initial_size); static Move * cuddZddSymmSifting_down (DdManager *table, int x, int x_high, int initial_size); static int cuddZddSymmSiftingBackward (DdManager *table, Move *moves, int size); static int zdd_group_move (DdManager *table, int x, int y, Move **moves); static int zdd_group_move_backward (DdManager *table, int x, int y); static void cuddZddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints statistics on symmetric ZDD variables.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void Cudd_zddSymmProfile( DdManager * table, int lower, int upper) { int i, x, gbot; int TotalSymm = 0; int TotalSymmGroups = 0; for (i = lower; i < upper; i++) { if (table->subtableZ[i].next != (unsigned) i) { x = i; (void) fprintf(table->out,"Group:"); do { (void) fprintf(table->out," %d", table->invpermZ[x]); TotalSymm++; gbot = x; x = table->subtableZ[x].next; } while (x != i); TotalSymmGroups++; #ifdef DD_DEBUG assert(table->subtableZ[gbot].next == (unsigned) i); #endif i = gbot; (void) fprintf(table->out,"\n"); } } (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm); (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups); } /* end of Cudd_zddSymmProfile */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Checks for symmetry of x and y.] Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddSymmCheck( DdManager * table, int x, int y) { int i; DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10; int yindex; int xsymmy = 1; int xsymmyp = 1; int arccount = 0; int TotalRefCount = 0; int symm_found; empty = table->zero; yindex = table->invpermZ[y]; for (i = table->subtableZ[x].slots - 1; i >= 0; i--) { f = table->subtableZ[x].nodelist[i]; while (f != NULL) { /* Find f1, f0, f11, f10, f01, f00 */ f1 = cuddT(f); f0 = cuddE(f); if ((int) f1->index == yindex) { f11 = cuddT(f1); f10 = cuddE(f1); if (f10 != empty) arccount++; } else { if ((int) f0->index != yindex) { return(0); /* f bypasses layer y */ } f11 = empty; f10 = f1; } if ((int) f0->index == yindex) { f01 = cuddT(f0); f00 = cuddE(f0); if (f00 != empty) arccount++; } else { f01 = empty; f00 = f0; } if (f01 != f10) xsymmy = 0; if (f11 != f00) xsymmyp = 0; if ((xsymmy == 0) && (xsymmyp == 0)) return(0); f = f->next; } /* for each element of the collision list */ } /* for each slot of the subtable */ /* Calculate the total reference counts of y ** whose else arc is not empty. */ for (i = table->subtableZ[y].slots - 1; i >= 0; i--) { f = table->subtableZ[y].nodelist[i]; while (f != NIL(DdNode)) { if (cuddE(f) != empty) TotalRefCount += f->ref; f = f->next; } } symm_found = (arccount == TotalRefCount); #if defined(DD_DEBUG) && defined(DD_VERBOSE) if (symm_found) { int xindex = table->invpermZ[x]; (void) fprintf(table->out, "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", xindex,yindex,x,y); } #endif return(symm_found); } /* end cuddZddSymmCheck */ /**Function******************************************************************** Synopsis [Symmetric sifting algorithm for ZDDs.] Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.
        1. Order all the variables according to the number of entries in each unique subtable.
        2. Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric.
        3. Select the best permutation.
        4. Repeat 3 and 4 for all variables.
        Returns 1 plus the number of symmetric variables if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddZddSymmSiftingConv] ******************************************************************************/ int cuddZddSymmSifting( DdManager * table, int lower, int upper) { int i; int *var; int nvars; int x; int result; int symvars; int symgroups; int iteration; #ifdef DD_STATS int previousSize; #endif nvars = table->sizeZ; /* Find order in which to sift variables. */ var = NULL; zdd_entry = ABC_ALLOC(int, nvars); if (zdd_entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddZddSymmSiftingOutOfMem; } var = ABC_ALLOC(int, nvars); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddZddSymmSiftingOutOfMem; } for (i = 0; i < nvars; i++) { x = table->permZ[i]; zdd_entry[i] = table->subtableZ[x].keys; var[i] = i; } qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); /* Initialize the symmetry of each subtable to itself. */ for (i = lower; i <= upper; i++) table->subtableZ[i].next = i; iteration = ddMin(table->siftMaxVar, nvars); for (i = 0; i < iteration; i++) { if (zddTotalNumberSwapping >= table->siftMaxSwap) break; x = table->permZ[var[i]]; #ifdef DD_STATS previousSize = table->keysZ; #endif if (x < lower || x > upper) continue; if (table->subtableZ[x].next == (unsigned) x) { result = cuddZddSymmSiftingAux(table, x, lower, upper); if (!result) goto cuddZddSymmSiftingOutOfMem; #ifdef DD_STATS if (table->keysZ < (unsigned) previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > (unsigned) previousSize) { (void) fprintf(table->out,"+"); #ifdef DD_VERBOSE (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); #endif } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } } ABC_FREE(var); ABC_FREE(zdd_entry); cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); #ifdef DD_STATS (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars); (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups); #endif return(1+symvars); cuddZddSymmSiftingOutOfMem: if (zdd_entry != NULL) ABC_FREE(zdd_entry); if (var != NULL) ABC_FREE(var); return(0); } /* end of cuddZddSymmSifting */ /**Function******************************************************************** Synopsis [Symmetric sifting to convergence algorithm for ZDDs.] Description [Symmetric sifting to convergence algorithm for ZDDs. Assumes that no dead nodes are present.
        1. Order all the variables according to the number of entries in each unique subtable.
        2. Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric.
        3. Select the best permutation.
        4. Repeat 3 and 4 for all variables.
        5. Repeat 1-4 until no further improvement.
        Returns 1 plus the number of symmetric variables if successful; 0 otherwise.] SideEffects [None] SeeAlso [cuddZddSymmSifting] ******************************************************************************/ int cuddZddSymmSiftingConv( DdManager * table, int lower, int upper) { int i; int *var; int nvars; int initialSize; int x; int result; int symvars; int symgroups; int classes; int iteration; #ifdef DD_STATS int previousSize; #endif initialSize = table->keysZ; nvars = table->sizeZ; /* Find order in which to sift variables. */ var = NULL; zdd_entry = ABC_ALLOC(int, nvars); if (zdd_entry == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddZddSymmSiftingConvOutOfMem; } var = ABC_ALLOC(int, nvars); if (var == NULL) { table->errorCode = CUDD_MEMORY_OUT; goto cuddZddSymmSiftingConvOutOfMem; } for (i = 0; i < nvars; i++) { x = table->permZ[i]; zdd_entry[i] = table->subtableZ[x].keys; var[i] = i; } qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare); /* Initialize the symmetry of each subtable to itself ** for first pass of converging symmetric sifting. */ for (i = lower; i <= upper; i++) table->subtableZ[i].next = i; iteration = ddMin(table->siftMaxVar, table->sizeZ); for (i = 0; i < iteration; i++) { if (zddTotalNumberSwapping >= table->siftMaxSwap) break; x = table->permZ[var[i]]; if (x < lower || x > upper) continue; /* Only sift if not in symmetry group already. */ if (table->subtableZ[x].next == (unsigned) x) { #ifdef DD_STATS previousSize = table->keysZ; #endif result = cuddZddSymmSiftingAux(table, x, lower, upper); if (!result) goto cuddZddSymmSiftingConvOutOfMem; #ifdef DD_STATS if (table->keysZ < (unsigned) previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > (unsigned) previousSize) { (void) fprintf(table->out,"+"); #ifdef DD_VERBOSE (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); #endif } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } } /* Sifting now until convergence. */ while ((unsigned) initialSize > table->keysZ) { initialSize = table->keysZ; #ifdef DD_STATS (void) fprintf(table->out,"\n"); #endif /* Here we consider only one representative for each symmetry class. */ for (x = lower, classes = 0; x <= upper; x++, classes++) { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; /* Here x is the largest index in a group. ** Groups consists of adjacent variables. ** Hence, the next increment of x will move it to a new group. */ i = table->invpermZ[x]; zdd_entry[i] = table->subtableZ[x].keys; var[classes] = i; } qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare); /* Now sift. */ iteration = ddMin(table->siftMaxVar, nvars); for (i = 0; i < iteration; i++) { if (zddTotalNumberSwapping >= table->siftMaxSwap) break; x = table->permZ[var[i]]; if ((unsigned) x >= table->subtableZ[x].next) { #ifdef DD_STATS previousSize = table->keysZ; #endif result = cuddZddSymmSiftingConvAux(table, x, lower, upper); if (!result) goto cuddZddSymmSiftingConvOutOfMem; #ifdef DD_STATS if (table->keysZ < (unsigned) previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > (unsigned) previousSize) { (void) fprintf(table->out,"+"); #ifdef DD_VERBOSE (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); #endif } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } } /* for */ } cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); #ifdef DD_STATS (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n", symvars); (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n", symgroups); #endif ABC_FREE(var); ABC_FREE(zdd_entry); return(1+symvars); cuddZddSymmSiftingConvOutOfMem: if (zdd_entry != NULL) ABC_FREE(zdd_entry); if (var != NULL) ABC_FREE(var); return(0); } /* end of cuddZddSymmSiftingConv */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Given x_low <= x <= x_high moves x up and down between the boundaries.] Description [Given x_low <= x <= x_high moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is not part of a symmetry group. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddSymmSiftingAux( DdManager * table, int x, int x_low, int x_high) { Move *move; Move *move_up; /* list of up move */ Move *move_down; /* list of down move */ int initial_size; int result; int i; int topbot; /* index to either top or bottom of symmetry group */ int init_group_size, final_group_size; initial_size = table->keysZ; move_down = NULL; move_up = NULL; /* Look for consecutive symmetries above x. */ for (i = x; i > x_low; i--) { if (!cuddZddSymmCheck(table, i - 1, i)) break; /* find top of i-1's symmetry */ topbot = table->subtableZ[i - 1].next; table->subtableZ[i - 1].next = i; table->subtableZ[x].next = topbot; /* x is bottom of group so its symmetry is top of i-1's group */ i = topbot + 1; /* add 1 for i--, new i is top of symm group */ } /* Look for consecutive symmetries below x. */ for (i = x; i < x_high; i++) { if (!cuddZddSymmCheck(table, i, i + 1)) break; /* find bottom of i+1's symm group */ topbot = i + 1; while ((unsigned) topbot < table->subtableZ[topbot].next) topbot = table->subtableZ[topbot].next; table->subtableZ[topbot].next = table->subtableZ[i].next; table->subtableZ[i].next = i + 1; i = topbot - 1; /* add 1 for i++, new i is bottom of symm group */ } /* Now x maybe in the middle of a symmetry group. */ if (x == x_low) { /* Sift down */ /* Find bottom of x's symm group */ while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; i = table->subtableZ[x].next; init_group_size = x - i + 1; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); /* after that point x --> x_high, unless early term */ if (move_down == ZDD_MV_OOM) goto cuddZddSymmSiftingAuxOutOfMem; if (move_down == NULL || table->subtableZ[move_down->y].next != move_down->y) { /* symmetry detected may have to make another complete pass */ if (move_down != NULL) x = move_down->y; else x = table->subtableZ[x].next; i = x; while ((unsigned) i < table->subtableZ[i].next) { i = table->subtableZ[i].next; } final_group_size = i - x + 1; if (init_group_size == final_group_size) { /* No new symmetry groups detected, return to best position */ result = cuddZddSymmSiftingBackward(table, move_down, initial_size); } else { initial_size = table->keysZ; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); result = cuddZddSymmSiftingBackward(table, move_up, initial_size); } } else { result = cuddZddSymmSiftingBackward(table, move_down, initial_size); /* move backward and stop at best position */ } if (!result) goto cuddZddSymmSiftingAuxOutOfMem; } else if (x == x_high) { /* Sift up */ /* Find top of x's symm group */ while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; x = table->subtableZ[x].next; i = x; while ((unsigned) i < table->subtableZ[i].next) { i = table->subtableZ[i].next; } init_group_size = i - x + 1; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); /* after that point x --> x_low, unless early term */ if (move_up == ZDD_MV_OOM) goto cuddZddSymmSiftingAuxOutOfMem; if (move_up == NULL || table->subtableZ[move_up->x].next != move_up->x) { /* symmetry detected may have to make another complete pass */ if (move_up != NULL) x = move_up->x; else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; } i = table->subtableZ[x].next; final_group_size = x - i + 1; if (init_group_size == final_group_size) { /* No new symmetry groups detected, return to best position */ result = cuddZddSymmSiftingBackward(table, move_up, initial_size); } else { initial_size = table->keysZ; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); result = cuddZddSymmSiftingBackward(table, move_down, initial_size); } } else { result = cuddZddSymmSiftingBackward(table, move_up, initial_size); /* move backward and stop at best position */ } if (!result) goto cuddZddSymmSiftingAuxOutOfMem; } else if ((x - x_low) > (x_high - x)) { /* must go down first: shorter */ /* Find bottom of x's symm group */ while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); /* after that point x --> x_high, unless early term */ if (move_down == ZDD_MV_OOM) goto cuddZddSymmSiftingAuxOutOfMem; if (move_down != NULL) { x = move_down->y; } else { x = table->subtableZ[x].next; } i = x; while ((unsigned) i < table->subtableZ[i].next) { i = table->subtableZ[i].next; } init_group_size = i - x + 1; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); if (move_up == ZDD_MV_OOM) goto cuddZddSymmSiftingAuxOutOfMem; if (move_up == NULL || table->subtableZ[move_up->x].next != move_up->x) { /* symmetry detected may have to make another complete pass */ if (move_up != NULL) { x = move_up->x; } else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; } i = table->subtableZ[x].next; final_group_size = x - i + 1; if (init_group_size == final_group_size) { /* No new symmetry groups detected, return to best position */ result = cuddZddSymmSiftingBackward(table, move_up, initial_size); } else { while (move_down != NULL) { move = move_down->next; cuddDeallocMove(table, move_down); move_down = move; } initial_size = table->keysZ; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); result = cuddZddSymmSiftingBackward(table, move_down, initial_size); } } else { result = cuddZddSymmSiftingBackward(table, move_up, initial_size); /* move backward and stop at best position */ } if (!result) goto cuddZddSymmSiftingAuxOutOfMem; } else { /* moving up first:shorter */ /* Find top of x's symmetry group */ while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; x = table->subtableZ[x].next; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); /* after that point x --> x_high, unless early term */ if (move_up == ZDD_MV_OOM) goto cuddZddSymmSiftingAuxOutOfMem; if (move_up != NULL) { x = move_up->x; } else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; } i = table->subtableZ[x].next; init_group_size = x - i + 1; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); if (move_down == ZDD_MV_OOM) goto cuddZddSymmSiftingAuxOutOfMem; if (move_down == NULL || table->subtableZ[move_down->y].next != move_down->y) { /* symmetry detected may have to make another complete pass */ if (move_down != NULL) { x = move_down->y; } else { x = table->subtableZ[x].next; } i = x; while ((unsigned) i < table->subtableZ[i].next) { i = table->subtableZ[i].next; } final_group_size = i - x + 1; if (init_group_size == final_group_size) { /* No new symmetries detected, go back to best position */ result = cuddZddSymmSiftingBackward(table, move_down, initial_size); } else { while (move_up != NULL) { move = move_up->next; cuddDeallocMove(table, move_up); move_up = move; } initial_size = table->keysZ; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); result = cuddZddSymmSiftingBackward(table, move_up, initial_size); } } else { result = cuddZddSymmSiftingBackward(table, move_down, initial_size); /* move backward and stop at best position */ } if (!result) goto cuddZddSymmSiftingAuxOutOfMem; } while (move_down != NULL) { move = move_down->next; cuddDeallocMove(table, move_down); move_down = move; } while (move_up != NULL) { move = move_up->next; cuddDeallocMove(table, move_up); move_up = move; } return(1); cuddZddSymmSiftingAuxOutOfMem: if (move_down != ZDD_MV_OOM) { while (move_down != NULL) { move = move_down->next; cuddDeallocMove(table, move_down); move_down = move; } } if (move_up != ZDD_MV_OOM) { while (move_up != NULL) { move = move_up->next; cuddDeallocMove(table, move_up); move_up = move; } } return(0); } /* end of cuddZddSymmSiftingAux */ /**Function******************************************************************** Synopsis [Given x_low <= x <= x_high moves x up and down between the boundaries.] Description [Given x_low <= x <= x_high moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is either an isolated variable, or it is the bottom of a symmetry group. All symmetries may not have been found, because of exceeded growth limit. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddSymmSiftingConvAux( DdManager * table, int x, int x_low, int x_high) { Move *move; Move *move_up; /* list of up move */ Move *move_down; /* list of down move */ int initial_size; int result; int i; int init_group_size, final_group_size; initial_size = table->keysZ; move_down = NULL; move_up = NULL; if (x == x_low) { /* Sift down */ i = table->subtableZ[x].next; init_group_size = x - i + 1; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); /* after that point x --> x_high, unless early term */ if (move_down == ZDD_MV_OOM) goto cuddZddSymmSiftingConvAuxOutOfMem; if (move_down == NULL || table->subtableZ[move_down->y].next != move_down->y) { /* symmetry detected may have to make another complete pass */ if (move_down != NULL) x = move_down->y; else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; x = table->subtableZ[x].next; } i = x; while ((unsigned) i < table->subtableZ[i].next) { i = table->subtableZ[i].next; } final_group_size = i - x + 1; if (init_group_size == final_group_size) { /* No new symmetries detected, go back to best position */ result = cuddZddSymmSiftingBackward(table, move_down, initial_size); } else { initial_size = table->keysZ; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); result = cuddZddSymmSiftingBackward(table, move_up, initial_size); } } else { result = cuddZddSymmSiftingBackward(table, move_down, initial_size); /* move backward and stop at best position */ } if (!result) goto cuddZddSymmSiftingConvAuxOutOfMem; } else if (x == x_high) { /* Sift up */ /* Find top of x's symm group */ while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; x = table->subtableZ[x].next; i = x; while ((unsigned) i < table->subtableZ[i].next) { i = table->subtableZ[i].next; } init_group_size = i - x + 1; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); /* after that point x --> x_low, unless early term */ if (move_up == ZDD_MV_OOM) goto cuddZddSymmSiftingConvAuxOutOfMem; if (move_up == NULL || table->subtableZ[move_up->x].next != move_up->x) { /* symmetry detected may have to make another complete pass */ if (move_up != NULL) x = move_up->x; else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; } i = table->subtableZ[x].next; final_group_size = x - i + 1; if (init_group_size == final_group_size) { /* No new symmetry groups detected, return to best position */ result = cuddZddSymmSiftingBackward(table, move_up, initial_size); } else { initial_size = table->keysZ; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); result = cuddZddSymmSiftingBackward(table, move_down, initial_size); } } else { result = cuddZddSymmSiftingBackward(table, move_up, initial_size); /* move backward and stop at best position */ } if (!result) goto cuddZddSymmSiftingConvAuxOutOfMem; } else if ((x - x_low) > (x_high - x)) { /* must go down first: shorter */ move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); /* after that point x --> x_high */ if (move_down == ZDD_MV_OOM) goto cuddZddSymmSiftingConvAuxOutOfMem; if (move_down != NULL) { x = move_down->y; } else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; x = table->subtableZ[x].next; } i = x; while ((unsigned) i < table->subtableZ[i].next) { i = table->subtableZ[i].next; } init_group_size = i - x + 1; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); if (move_up == ZDD_MV_OOM) goto cuddZddSymmSiftingConvAuxOutOfMem; if (move_up == NULL || table->subtableZ[move_up->x].next != move_up->x) { /* symmetry detected may have to make another complete pass */ if (move_up != NULL) { x = move_up->x; } else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; } i = table->subtableZ[x].next; final_group_size = x - i + 1; if (init_group_size == final_group_size) { /* No new symmetry groups detected, return to best position */ result = cuddZddSymmSiftingBackward(table, move_up, initial_size); } else { while (move_down != NULL) { move = move_down->next; cuddDeallocMove(table, move_down); move_down = move; } initial_size = table->keysZ; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); result = cuddZddSymmSiftingBackward(table, move_down, initial_size); } } else { result = cuddZddSymmSiftingBackward(table, move_up, initial_size); /* move backward and stop at best position */ } if (!result) goto cuddZddSymmSiftingConvAuxOutOfMem; } else { /* moving up first:shorter */ /* Find top of x's symmetry group */ x = table->subtableZ[x].next; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); /* after that point x --> x_high, unless early term */ if (move_up == ZDD_MV_OOM) goto cuddZddSymmSiftingConvAuxOutOfMem; if (move_up != NULL) { x = move_up->x; } else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; } i = table->subtableZ[x].next; init_group_size = x - i + 1; move_down = cuddZddSymmSifting_down(table, x, x_high, initial_size); if (move_down == ZDD_MV_OOM) goto cuddZddSymmSiftingConvAuxOutOfMem; if (move_down == NULL || table->subtableZ[move_down->y].next != move_down->y) { /* symmetry detected may have to make another complete pass */ if (move_down != NULL) { x = move_down->y; } else { while ((unsigned) x < table->subtableZ[x].next) x = table->subtableZ[x].next; x = table->subtableZ[x].next; } i = x; while ((unsigned) i < table->subtableZ[i].next) { i = table->subtableZ[i].next; } final_group_size = i - x + 1; if (init_group_size == final_group_size) { /* No new symmetries detected, go back to best position */ result = cuddZddSymmSiftingBackward(table, move_down, initial_size); } else { while (move_up != NULL) { move = move_up->next; cuddDeallocMove(table, move_up); move_up = move; } initial_size = table->keysZ; move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); result = cuddZddSymmSiftingBackward(table, move_up, initial_size); } } else { result = cuddZddSymmSiftingBackward(table, move_down, initial_size); /* move backward and stop at best position */ } if (!result) goto cuddZddSymmSiftingConvAuxOutOfMem; } while (move_down != NULL) { move = move_down->next; cuddDeallocMove(table, move_down); move_down = move; } while (move_up != NULL) { move = move_up->next; cuddDeallocMove(table, move_up); move_up = move; } return(1); cuddZddSymmSiftingConvAuxOutOfMem: if (move_down != ZDD_MV_OOM) { while (move_down != NULL) { move = move_down->next; cuddDeallocMove(table, move_down); move_down = move; } } if (move_up != ZDD_MV_OOM) { while (move_up != NULL) { move = move_up->next; cuddDeallocMove(table, move_up); move_up = move; } } return(0); } /* end of cuddZddSymmSiftingConvAux */ /**Function******************************************************************** Synopsis [Moves x up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much.] Description [Moves x up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much. Assumes that x is the top of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; ZDD_MV_OOM if memory is full.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * cuddZddSymmSifting_up( DdManager * table, int x, int x_low, int initial_size) { Move *moves; Move *move; int y; int size; int limit_size = initial_size; int i, gytop; moves = NULL; y = cuddZddNextLow(table, x); while (y >= x_low) { gytop = table->subtableZ[y].next; if (cuddZddSymmCheck(table, y, x)) { /* Symmetry found, attach symm groups */ table->subtableZ[y].next = x; i = table->subtableZ[x].next; while (table->subtableZ[i].next != (unsigned) x) i = table->subtableZ[i].next; table->subtableZ[i].next = gytop; } else if ((table->subtableZ[x].next == (unsigned) x) && (table->subtableZ[y].next == (unsigned) y)) { /* x and y have self symmetry */ size = cuddZddSwapInPlace(table, y, x); if (size == 0) goto cuddZddSymmSifting_upOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto cuddZddSymmSifting_upOutOfMem; move->x = y; move->y = x; move->size = size; move->next = moves; moves = move; if ((double)size > (double)limit_size * table->maxGrowth) return(moves); if (size < limit_size) limit_size = size; } else { /* Group move */ size = zdd_group_move(table, y, x, &moves); if ((double)size > (double)limit_size * table->maxGrowth) return(moves); if (size < limit_size) limit_size = size; } x = gytop; y = cuddZddNextLow(table, x); } return(moves); cuddZddSymmSifting_upOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(ZDD_MV_OOM); } /* end of cuddZddSymmSifting_up */ /**Function******************************************************************** Synopsis [Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much.] Description [Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much. Assumes that x is the bottom of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; ZDD_MV_OOM if memory is full.] SideEffects [None] SeeAlso [] ******************************************************************************/ static Move * cuddZddSymmSifting_down( DdManager * table, int x, int x_high, int initial_size) { Move *moves; Move *move; int y; int size; int limit_size = initial_size; int i, gxtop, gybot; moves = NULL; y = cuddZddNextHigh(table, x); while (y <= x_high) { gybot = table->subtableZ[y].next; while (table->subtableZ[gybot].next != (unsigned) y) gybot = table->subtableZ[gybot].next; if (cuddZddSymmCheck(table, x, y)) { /* Symmetry found, attach symm groups */ gxtop = table->subtableZ[x].next; table->subtableZ[x].next = y; i = table->subtableZ[y].next; while (table->subtableZ[i].next != (unsigned) y) i = table->subtableZ[i].next; table->subtableZ[i].next = gxtop; } else if ((table->subtableZ[x].next == (unsigned) x) && (table->subtableZ[y].next == (unsigned) y)) { /* x and y have self symmetry */ size = cuddZddSwapInPlace(table, x, y); if (size == 0) goto cuddZddSymmSifting_downOutOfMem; move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto cuddZddSymmSifting_downOutOfMem; move->x = x; move->y = y; move->size = size; move->next = moves; moves = move; if ((double)size > (double)limit_size * table->maxGrowth) return(moves); if (size < limit_size) limit_size = size; x = y; y = cuddZddNextHigh(table, x); } else { /* Group move */ size = zdd_group_move(table, x, y, &moves); if ((double)size > (double)limit_size * table->maxGrowth) return(moves); if (size < limit_size) limit_size = size; } x = gybot; y = cuddZddNextHigh(table, x); } return(moves); cuddZddSymmSifting_downOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocMove(table, moves); moves = move; } return(ZDD_MV_OOM); } /* end of cuddZddSymmSifting_down */ /**Function******************************************************************** Synopsis [Given a set of moves, returns the ZDD heap to the position giving the minimum size.] Description [Given a set of moves, returns the ZDD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int cuddZddSymmSiftingBackward( DdManager * table, Move * moves, int size) { int i; int i_best; Move *move; int res = -1; i_best = -1; for (move = moves, i = 0; move != NULL; move = move->next, i++) { if (move->size < size) { i_best = i; size = move->size; } } for (move = moves, i = 0; move != NULL; move = move->next, i++) { if (i == i_best) break; if ((table->subtableZ[move->x].next == move->x) && (table->subtableZ[move->y].next == move->y)) { res = cuddZddSwapInPlace(table, move->x, move->y); if (!res) return(0); } else { /* Group move necessary */ res = zdd_group_move_backward(table, move->x, move->y); } if (i_best == -1 && res == size) break; } return(1); } /* end of cuddZddSymmSiftingBackward */ /**Function******************************************************************** Synopsis [Swaps two groups.] Description [Swaps two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Updates the list of moves. Returns the number of keys in the table if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int zdd_group_move( DdManager * table, int x, int y, Move ** moves) { Move *move; int size; int i, temp, gxtop, gxbot, gybot, yprev; int swapx = -1, swapy = -1; #ifdef DD_DEBUG assert(x < y); /* we assume that x < y */ #endif /* Find top and bottom for the two groups. */ gxtop = table->subtableZ[x].next; gxbot = x; gybot = table->subtableZ[y].next; while (table->subtableZ[gybot].next != (unsigned) y) gybot = table->subtableZ[gybot].next; yprev = gybot; while (x <= y) { while (y > gxtop) { /* Set correct symmetries. */ temp = table->subtableZ[x].next; if (temp == x) temp = y; i = gxtop; for (;;) { if (table->subtableZ[i].next == (unsigned) x) { table->subtableZ[i].next = y; break; } else { i = table->subtableZ[i].next; } } if (table->subtableZ[y].next != (unsigned) y) { table->subtableZ[x].next = table->subtableZ[y].next; } else { table->subtableZ[x].next = x; } if (yprev != y) { table->subtableZ[yprev].next = x; } else { yprev = x; } table->subtableZ[y].next = temp; size = cuddZddSwapInPlace(table, x, y); if (size == 0) goto zdd_group_moveOutOfMem; swapx = x; swapy = y; y = x; x--; } /* while y > gxtop */ /* Trying to find the next y. */ if (table->subtableZ[y].next <= (unsigned) y) { gybot = y; } else { y = table->subtableZ[y].next; } yprev = gxtop; gxtop++; gxbot++; x = gxbot; } /* while x <= y, end of group movement */ move = (Move *)cuddDynamicAllocNode(table); if (move == NULL) goto zdd_group_moveOutOfMem; move->x = swapx; move->y = swapy; move->size = table->keysZ; move->next = *moves; *moves = move; return(table->keysZ); zdd_group_moveOutOfMem: while (*moves != NULL) { move = (*moves)->next; cuddDeallocMove(table, *moves); *moves = move; } return(0); } /* end of zdd_group_move */ /**Function******************************************************************** Synopsis [Undoes the swap of two groups.] Description [Undoes the swap of two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int zdd_group_move_backward( DdManager * table, int x, int y) { int size = -1; int i, temp, gxtop, gxbot, gybot, yprev; #ifdef DD_DEBUG assert(x < y); /* we assume that x < y */ #endif /* Find top and bottom of the two groups. */ gxtop = table->subtableZ[x].next; gxbot = x; gybot = table->subtableZ[y].next; while (table->subtableZ[gybot].next != (unsigned) y) gybot = table->subtableZ[gybot].next; yprev = gybot; while (x <= y) { while (y > gxtop) { /* Set correct symmetries. */ temp = table->subtableZ[x].next; if (temp == x) temp = y; i = gxtop; for (;;) { if (table->subtableZ[i].next == (unsigned) x) { table->subtableZ[i].next = y; break; } else { i = table->subtableZ[i].next; } } if (table->subtableZ[y].next != (unsigned) y) { table->subtableZ[x].next = table->subtableZ[y].next; } else { table->subtableZ[x].next = x; } if (yprev != y) { table->subtableZ[yprev].next = x; } else { yprev = x; } table->subtableZ[y].next = temp; size = cuddZddSwapInPlace(table, x, y); if (size == 0) return(0); y = x; x--; } /* while y > gxtop */ /* Trying to find the next y. */ if (table->subtableZ[y].next <= (unsigned) y) { gybot = y; } else { y = table->subtableZ[y].next; } yprev = gxtop; gxtop++; gxbot++; x = gxbot; } /* while x <= y, end of group movement backward */ return(size); } /* end of zdd_group_move_backward */ /**Function******************************************************************** Synopsis [Counts numbers of symmetric variables and symmetry groups.] Description [] SideEffects [None] ******************************************************************************/ static void cuddZddSymmSummary( DdManager * table, int lower, int upper, int * symvars, int * symgroups) { int i,x,gbot; int TotalSymm = 0; int TotalSymmGroups = 0; for (i = lower; i <= upper; i++) { if (table->subtableZ[i].next != (unsigned) i) { TotalSymmGroups++; x = i; do { TotalSymm++; gbot = x; x = table->subtableZ[x].next; } while (x != i); #ifdef DD_DEBUG assert(table->subtableZ[gbot].next == (unsigned) i); #endif i = gbot; } } *symvars = TotalSymm; *symgroups = TotalSymmGroups; return; } /* end of cuddZddSymmSummary */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/cuddZddUtil.c000066400000000000000000001043051300674244400240720ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [cuddZddUtil.c] PackageName [cudd] Synopsis [Utility functions for ZDDs.] Description [External procedures included in this module:
        • Cudd_zddPrintMinterm()
        • Cudd_zddPrintCover()
        • Cudd_zddPrintDebug()
        • Cudd_zddFirstPath()
        • Cudd_zddNextPath()
        • Cudd_zddCoverPathToString()
        • Cudd_zddDumpDot()
        Internal procedures included in this module:
        • cuddZddP()
        Static procedures included in this module:
        • zp2()
        • zdd_print_minterm_aux()
        • zddPrintCoverAux()
        ] SeeAlso [] Author [Hyong-Kyoon Shin, In-Ho Moon, Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "cuddInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: cuddZddUtil.c,v 1.27 2009/03/08 02:49:02 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int zp2 (DdManager *zdd, DdNode *f, st__table *t); static void zdd_print_minterm_aux (DdManager *zdd, DdNode *node, int level, int *list); static void zddPrintCoverAux (DdManager *zdd, DdNode *node, int level, int *list); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints a disjoint sum of product form for a ZDD.] Description [Prints a disjoint sum of product form for a ZDD. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_zddPrintDebug Cudd_zddPrintCover] ******************************************************************************/ int Cudd_zddPrintMinterm( DdManager * zdd, DdNode * node) { int i, size; int *list; size = (int)zdd->sizeZ; list = ABC_ALLOC(int, size); if (list == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */ zdd_print_minterm_aux(zdd, node, 0, list); ABC_FREE(list); return(1); } /* end of Cudd_zddPrintMinterm */ /**Function******************************************************************** Synopsis [Prints a sum of products from a ZDD representing a cover.] Description [Prints a sum of products from a ZDD representing a cover. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_zddPrintMinterm] ******************************************************************************/ int Cudd_zddPrintCover( DdManager * zdd, DdNode * node) { int i, size; int *list; size = (int)zdd->sizeZ; if (size % 2 != 0) return(0); /* number of variables should be even */ list = ABC_ALLOC(int, size); if (list == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; return(0); } for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */ zddPrintCoverAux(zdd, node, 0, list); ABC_FREE(list); return(1); } /* end of Cudd_zddPrintCover */ /**Function******************************************************************** Synopsis [Prints to the standard output a ZDD and its statistics.] Description [Prints to the standard output a DD and its statistics. The statistics include the number of nodes and the number of minterms. (The number of minterms is also the number of combinations in the set.) The statistics are printed if pr > 0. Specifically:
        • pr = 0 : prints nothing
        • pr = 1 : prints counts of nodes and minterms
        • pr = 2 : prints counts + disjoint sum of products
        • pr = 3 : prints counts + list of nodes
        • pr > 3 : prints counts + disjoint sum of products + list of nodes
        Returns 1 if successful; 0 otherwise. ] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_zddPrintDebug( DdManager * zdd, DdNode * f, int n, int pr) { DdNode *empty = DD_ZERO(zdd); int nodes; double minterms; int retval = 1; if (f == empty && pr > 0) { (void) fprintf(zdd->out,": is the empty ZDD\n"); (void) fflush(zdd->out); return(1); } if (pr > 0) { nodes = Cudd_zddDagSize(f); if (nodes == CUDD_OUT_OF_MEM) retval = 0; minterms = Cudd_zddCountMinterm(zdd, f, n); if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0; (void) fprintf(zdd->out,": %d nodes %g minterms\n", nodes, minterms); if (pr > 2) if (!cuddZddP(zdd, f)) retval = 0; if (pr == 2 || pr > 3) { if (!Cudd_zddPrintMinterm(zdd, f)) retval = 0; (void) fprintf(zdd->out,"\n"); } (void) fflush(zdd->out); } return(retval); } /* end of Cudd_zddPrintDebug */ /**Function******************************************************************** Synopsis [Finds the first path of a ZDD.] Description [Defines an iterator on the paths of a ZDD and finds its first path. Returns a generator that contains the information necessary to continue the enumeration if successful; NULL otherwise.

        A path is represented as an array of literals, which are integers in {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc out of a node, and 2 stands for the absence of a node. The size of the array equals the number of variables in the manager at the time Cudd_zddFirstCube is called.

        The paths that end in the empty terminal are not enumerated.] SideEffects [The first path is returned as a side effect.] SeeAlso [Cudd_zddForeachPath Cudd_zddNextPath Cudd_GenFree Cudd_IsGenEmpty] ******************************************************************************/ DdGen * Cudd_zddFirstPath( DdManager * zdd, DdNode * f, int ** path) { DdGen *gen; DdNode *top, *next, *prev; int i; int nvars; /* Sanity Check. */ if (zdd == NULL || f == NULL) return(NULL); /* Allocate generator an initialize it. */ gen = ABC_ALLOC(DdGen,1); if (gen == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; return(NULL); } gen->manager = zdd; gen->type = CUDD_GEN_ZDD_PATHS; gen->status = CUDD_GEN_EMPTY; gen->gen.cubes.cube = NULL; gen->gen.cubes.value = DD_ZERO_VAL; gen->stack.sp = 0; gen->stack.stack = NULL; gen->node = NULL; nvars = zdd->sizeZ; gen->gen.cubes.cube = ABC_ALLOC(int,nvars); if (gen->gen.cubes.cube == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(gen); return(NULL); } for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2; /* The maximum stack depth is one plus the number of variables. ** because a path may have nodes at all levels, including the ** constant level. */ gen->stack.stack = ABC_ALLOC(DdNodePtr, nvars+1); if (gen->stack.stack == NULL) { zdd->errorCode = CUDD_MEMORY_OUT; ABC_FREE(gen->gen.cubes.cube); ABC_FREE(gen); return(NULL); } for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL; /* Find the first path of the ZDD. */ gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; while (1) { top = gen->stack.stack[gen->stack.sp-1]; if (!cuddIsConstant(Cudd_Regular(top))) { /* Take the else branch first. */ gen->gen.cubes.cube[Cudd_Regular(top)->index] = 0; next = cuddE(Cudd_Regular(top)); gen->stack.stack[gen->stack.sp] = Cudd_Not(next); gen->stack.sp++; } else if (Cudd_Regular(top) == DD_ZERO(zdd)) { /* Backtrack. */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]); next = cuddT(prev); if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[prev->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[prev->index] = 2; gen->stack.sp--; top = gen->stack.stack[gen->stack.sp-1]; } } else { gen->status = CUDD_GEN_NONEMPTY; gen->gen.cubes.value = cuddV(Cudd_Regular(top)); goto done; } } done: *path = gen->gen.cubes.cube; return(gen); } /* end of Cudd_zddFirstPath */ /**Function******************************************************************** Synopsis [Generates the next path of a ZDD.] Description [Generates the next path of a ZDD onset, using generator gen. Returns 0 if the enumeration is completed; 1 otherwise.] SideEffects [The path is returned as a side effect. The generator is modified.] SeeAlso [Cudd_zddForeachPath Cudd_zddFirstPath Cudd_GenFree Cudd_IsGenEmpty] ******************************************************************************/ int Cudd_zddNextPath( DdGen * gen, int ** path) { DdNode *top, *next, *prev; DdManager *zdd = gen->manager; /* Backtrack from previously reached terminal node. */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } top = gen->stack.stack[gen->stack.sp-1]; prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]); next = cuddT(prev); if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[prev->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[prev->index] = 2; gen->stack.sp--; } while (1) { top = gen->stack.stack[gen->stack.sp-1]; if (!cuddIsConstant(Cudd_Regular(top))) { /* Take the else branch first. */ gen->gen.cubes.cube[Cudd_Regular(top)->index] = 0; next = cuddE(Cudd_Regular(top)); gen->stack.stack[gen->stack.sp] = Cudd_Not(next); gen->stack.sp++; } else if (Cudd_Regular(top) == DD_ZERO(zdd)) { /* Backtrack. */ while (1) { if (gen->stack.sp == 1) { /* The current node has no predecessor. */ gen->status = CUDD_GEN_EMPTY; gen->stack.sp--; goto done; } prev = Cudd_Regular(gen->stack.stack[gen->stack.sp-2]); next = cuddT(prev); if (next != top) { /* follow the then branch next */ gen->gen.cubes.cube[prev->index] = 1; gen->stack.stack[gen->stack.sp-1] = next; break; } /* Pop the stack and try again. */ gen->gen.cubes.cube[prev->index] = 2; gen->stack.sp--; top = gen->stack.stack[gen->stack.sp-1]; } } else { gen->status = CUDD_GEN_NONEMPTY; gen->gen.cubes.value = cuddV(Cudd_Regular(top)); goto done; } } done: if (gen->status == CUDD_GEN_EMPTY) return(0); *path = gen->gen.cubes.cube; return(1); } /* end of Cudd_zddNextPath */ /**Function******************************************************************** Synopsis [Converts a path of a ZDD representing a cover to a string.] Description [Converts a path of a ZDD representing a cover to a string. The string represents an implicant of the cover. The path is typically produced by Cudd_zddForeachPath. Returns a pointer to the string if successful; NULL otherwise. If the str input is NULL, it allocates a new string. The string passed to this function must have enough room for all variables and for the terminator.] SideEffects [None] SeeAlso [Cudd_zddForeachPath] ******************************************************************************/ char * Cudd_zddCoverPathToString( DdManager *zdd /* DD manager */, int *path /* path of ZDD representing a cover */, char *str /* pointer to string to use if != NULL */ ) { int nvars = zdd->sizeZ; int i; char *res; if (nvars & 1) return(NULL); nvars >>= 1; if (str == NULL) { res = ABC_ALLOC(char, nvars+1); if (res == NULL) return(NULL); } else { res = str; } for (i = 0; i < nvars; i++) { int v = (path[2*i] << 2) | path[2*i+1]; switch (v) { case 0: case 2: case 8: case 10: res[i] = '-'; break; case 1: case 9: res[i] = '0'; break; case 4: case 6: res[i] = '1'; break; default: res[i] = '?'; } } res[nvars] = 0; return(res); } /* end of Cudd_zddCoverPathToString */ /**Function******************************************************************** Synopsis [Writes a dot file representing the argument ZDDs.] Description [Writes a file representing the argument ZDDs in a format suitable for the graph drawing program dot. It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, file system full). Cudd_zddDumpDot does not close the file: This is the caller responsibility. Cudd_zddDumpDot uses a minimal unique subset of the hexadecimal address of a node as name for it. If the argument inames is non-null, it is assumed to hold the pointers to the names of the inputs. Similarly for onames. Cudd_zddDumpDot uses the following convention to draw arcs:

        • solid line: THEN arcs;
        • dashed line: ELSE arcs.
        The dot options are chosen so that the drawing fits on a letter-size sheet. ] SideEffects [None] SeeAlso [Cudd_DumpDot Cudd_zddPrintDebug] ******************************************************************************/ int Cudd_zddDumpDot( DdManager * dd /* manager */, int n /* number of output nodes to be dumped */, DdNode ** f /* array of output nodes to be dumped */, char ** inames /* array of input names (or NULL) */, char ** onames /* array of output names (or NULL) */, FILE * fp /* pointer to the dump file */) { DdNode *support = NULL; DdNode *scan; int *sorted = NULL; int nvars = dd->sizeZ; st__table *visited = NULL; st__generator *gen; int retval; int i, j; int slots; DdNodePtr *nodelist; long refAddr, diff, mask; /* Build a bit array with the support of f. */ sorted = ABC_ALLOC(int,nvars); if (sorted == NULL) { dd->errorCode = CUDD_MEMORY_OUT; goto failure; } for (i = 0; i < nvars; i++) sorted[i] = 0; /* Take the union of the supports of each output function. */ for (i = 0; i < n; i++) { support = Cudd_Support(dd,f[i]); if (support == NULL) goto failure; cuddRef(support); scan = support; while (!cuddIsConstant(scan)) { sorted[scan->index] = 1; scan = cuddT(scan); } Cudd_RecursiveDeref(dd,support); } support = NULL; /* so that we do not try to free it in case of failure */ /* Initialize symbol table for visited nodes. */ visited = st__init_table( st__ptrcmp, st__ptrhash); if (visited == NULL) goto failure; /* Collect all the nodes of this DD in the symbol table. */ for (i = 0; i < n; i++) { retval = cuddCollectNodes(f[i],visited); if (retval == 0) goto failure; } /* Find how many most significant hex digits are identical ** in the addresses of all the nodes. Build a mask based ** on this knowledge, so that digits that carry no information ** will not be printed. This is done in two steps. ** 1. We scan the symbol table to find the bits that differ ** in at least 2 addresses. ** 2. We choose one of the possible masks. There are 8 possible ** masks for 32-bit integer, and 16 possible masks for 64-bit ** integers. */ /* Find the bits that are different. */ refAddr = (long) f[0]; diff = 0; gen = st__init_gen(visited); while ( st__gen(gen, (const char **)&scan, NULL)) { diff |= refAddr ^ (long) scan; } st__free_gen(gen); /* Choose the mask. */ for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { mask = (1 << i) - 1; if (diff <= mask) break; } /* Write the header and the global attributes. */ retval = fprintf(fp,"digraph \"ZDD\" {\n"); if (retval == EOF) return(0); retval = fprintf(fp, "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n"); if (retval == EOF) return(0); /* Write the input name subgraph by scanning the support array. */ retval = fprintf(fp,"{ node [shape = plaintext];\n"); if (retval == EOF) goto failure; retval = fprintf(fp," edge [style = invis];\n"); if (retval == EOF) goto failure; /* We use a name ("CONST NODES") with an embedded blank, because ** it is unlikely to appear as an input name. */ retval = fprintf(fp," \"CONST NODES\" [style = invis];\n"); if (retval == EOF) goto failure; for (i = 0; i < nvars; i++) { if (sorted[dd->invpermZ[i]]) { if (inames == NULL) { retval = fprintf(fp,"\" %d \" -> ", dd->invpermZ[i]); } else { retval = fprintf(fp,"\" %s \" -> ", inames[dd->invpermZ[i]]); } if (retval == EOF) goto failure; } } retval = fprintf(fp,"\"CONST NODES\"; \n}\n"); if (retval == EOF) goto failure; /* Write the output node subgraph. */ retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n"); if (retval == EOF) goto failure; for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp,"\"F%d\"", i); } else { retval = fprintf(fp,"\" %s \"", onames[i]); } if (retval == EOF) goto failure; if (i == n - 1) { retval = fprintf(fp,"; }\n"); } else { retval = fprintf(fp," -> "); } if (retval == EOF) goto failure; } /* Write rank info: All nodes with the same index have the same rank. */ for (i = 0; i < nvars; i++) { if (sorted[dd->invpermZ[i]]) { retval = fprintf(fp,"{ rank = same; "); if (retval == EOF) goto failure; if (inames == NULL) { retval = fprintf(fp,"\" %d \";\n", dd->invpermZ[i]); } else { retval = fprintf(fp,"\" %s \";\n", inames[dd->invpermZ[i]]); } if (retval == EOF) goto failure; nodelist = dd->subtableZ[i].nodelist; slots = dd->subtableZ[i].slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if ( st__is_member(visited,(char *) scan)) { retval = fprintf(fp,"\"%p\";\n", (void *) ((mask & (ptrint) scan) / sizeof(DdNode))); if (retval == EOF) goto failure; } scan = scan->next; } } retval = fprintf(fp,"}\n"); if (retval == EOF) goto failure; } } /* All constants have the same rank. */ retval = fprintf(fp, "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; "); if (retval == EOF) goto failure; nodelist = dd->constants.nodelist; slots = dd->constants.slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if ( st__is_member(visited,(char *) scan)) { retval = fprintf(fp,"\"%p\";\n", (void *) ((mask & (ptrint) scan) / sizeof(DdNode))); if (retval == EOF) goto failure; } scan = scan->next; } } retval = fprintf(fp,"}\n}\n"); if (retval == EOF) goto failure; /* Write edge info. */ /* Edges from the output nodes. */ for (i = 0; i < n; i++) { if (onames == NULL) { retval = fprintf(fp,"\"F%d\"", i); } else { retval = fprintf(fp,"\" %s \"", onames[i]); } if (retval == EOF) goto failure; retval = fprintf(fp," -> \"%p\" [style = solid];\n", (void *) ((mask & (ptrint) f[i]) / sizeof(DdNode))); if (retval == EOF) goto failure; } /* Edges from internal nodes. */ for (i = 0; i < nvars; i++) { if (sorted[dd->invpermZ[i]]) { nodelist = dd->subtableZ[i].nodelist; slots = dd->subtableZ[i].slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if ( st__is_member(visited,(char *) scan)) { retval = fprintf(fp, "\"%p\" -> \"%p\";\n", (void *) ((mask & (ptrint) scan) / sizeof(DdNode)), (void *) ((mask & (ptrint) cuddT(scan)) / sizeof(DdNode))); if (retval == EOF) goto failure; retval = fprintf(fp, "\"%p\" -> \"%p\" [style = dashed];\n", (void *) ((mask & (ptrint) scan) / sizeof(DdNode)), (void *) ((mask & (ptrint) cuddE(scan)) / sizeof(DdNode))); if (retval == EOF) goto failure; } scan = scan->next; } } } } /* Write constant labels. */ nodelist = dd->constants.nodelist; slots = dd->constants.slots; for (j = 0; j < slots; j++) { scan = nodelist[j]; while (scan != NULL) { if ( st__is_member(visited,(char *) scan)) { retval = fprintf(fp,"\"%p\" [label = \"%g\"];\n", (void *) ((mask & (ptrint) scan) / sizeof(DdNode)), cuddV(scan)); if (retval == EOF) goto failure; } scan = scan->next; } } /* Write trailer and return. */ retval = fprintf(fp,"}\n"); if (retval == EOF) goto failure; st__free_table(visited); ABC_FREE(sorted); return(1); failure: if (sorted != NULL) ABC_FREE(sorted); if (visited != NULL) st__free_table(visited); return(0); } /* end of Cudd_zddDumpBlif */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints a ZDD to the standard output. One line per node is printed.] Description [Prints a ZDD to the standard output. One line per node is printed. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [Cudd_zddPrintDebug] ******************************************************************************/ int cuddZddP( DdManager * zdd, DdNode * f) { int retval; st__table *table = st__init_table( st__ptrcmp, st__ptrhash); if (table == NULL) return(0); retval = zp2(zdd, f, table); st__free_table(table); (void) fputc('\n', zdd->out); return(retval); } /* end of cuddZddP */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive step of cuddZddP.] Description [Performs the recursive step of cuddZddP. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int zp2( DdManager * zdd, DdNode * f, st__table * t) { DdNode *n; int T, E; DdNode *base = DD_ONE(zdd); if (f == NULL) return(0); if (Cudd_IsConstant(f)) { (void)fprintf(zdd->out, "ID = %d\n", (f == base)); return(1); } if ( st__is_member(t, (char *)f) == 1) return(1); if ( st__insert(t, (char *) f, NULL) == st__OUT_OF_MEM) return(0); #if SIZEOF_VOID_P == 8 (void) fprintf(zdd->out, "ID = 0x%lx\tindex = %u\tr = %u\t", (ptruint)f / (ptruint) sizeof(DdNode), f->index, f->ref); #else (void) fprintf(zdd->out, "ID = 0x%x\tindex = %hu\tr = %hu\t", (ptruint)f / (ptruint) sizeof(DdNode), f->index, f->ref); #endif n = cuddT(f); if (Cudd_IsConstant(n)) { (void) fprintf(zdd->out, "T = %d\t\t", (n == base)); T = 1; } else { #if SIZEOF_VOID_P == 8 (void) fprintf(zdd->out, "T = 0x%lx\t", (ptruint) n / (ptruint) sizeof(DdNode)); #else (void) fprintf(zdd->out, "T = 0x%x\t", (ptruint) n / (ptruint) sizeof(DdNode)); #endif T = 0; } n = cuddE(f); if (Cudd_IsConstant(n)) { (void) fprintf(zdd->out, "E = %d\n", (n == base)); E = 1; } else { #if SIZEOF_VOID_P == 8 (void) fprintf(zdd->out, "E = 0x%lx\n", (ptruint) n / (ptruint) sizeof(DdNode)); #else (void) fprintf(zdd->out, "E = 0x%x\n", (ptruint) n / (ptruint) sizeof(DdNode)); #endif E = 0; } if (E == 0) if (zp2(zdd, cuddE(f), t) == 0) return(0); if (T == 0) if (zp2(zdd, cuddT(f), t) == 0) return(0); return(1); } /* end of zp2 */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddPrintMinterm.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void zdd_print_minterm_aux( DdManager * zdd /* manager */, DdNode * node /* current node */, int level /* depth in the recursion */, int * list /* current recursion path */) { DdNode *Nv, *Nnv; int i, v; DdNode *base = DD_ONE(zdd); if (Cudd_IsConstant(node)) { if (node == base) { /* Check for missing variable. */ if (level != zdd->sizeZ) { list[zdd->invpermZ[level]] = 0; zdd_print_minterm_aux(zdd, node, level + 1, list); return; } /* Terminal case: Print one cube based on the current recursion ** path. */ for (i = 0; i < zdd->sizeZ; i++) { v = list[i]; if (v == 0) (void) fprintf(zdd->out,"0"); else if (v == 1) (void) fprintf(zdd->out,"1"); else if (v == 3) (void) fprintf(zdd->out,"@"); /* should never happen */ else (void) fprintf(zdd->out,"-"); } (void) fprintf(zdd->out," 1\n"); } } else { /* Check for missing variable. */ if (level != cuddIZ(zdd,node->index)) { list[zdd->invpermZ[level]] = 0; zdd_print_minterm_aux(zdd, node, level + 1, list); return; } Nnv = cuddE(node); Nv = cuddT(node); if (Nv == Nnv) { list[node->index] = 2; zdd_print_minterm_aux(zdd, Nnv, level + 1, list); return; } list[node->index] = 1; zdd_print_minterm_aux(zdd, Nv, level + 1, list); list[node->index] = 0; zdd_print_minterm_aux(zdd, Nnv, level + 1, list); } return; } /* end of zdd_print_minterm_aux */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddPrintCover.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void zddPrintCoverAux( DdManager * zdd /* manager */, DdNode * node /* current node */, int level /* depth in the recursion */, int * list /* current recursion path */) { DdNode *Nv, *Nnv; int i, v; DdNode *base = DD_ONE(zdd); if (Cudd_IsConstant(node)) { if (node == base) { /* Check for missing variable. */ if (level != zdd->sizeZ) { list[zdd->invpermZ[level]] = 0; zddPrintCoverAux(zdd, node, level + 1, list); return; } /* Terminal case: Print one cube based on the current recursion ** path. */ for (i = 0; i < zdd->sizeZ; i += 2) { v = list[i] * 4 + list[i+1]; if (v == 0) (void) putc('-',zdd->out); else if (v == 4) (void) putc('1',zdd->out); else if (v == 1) (void) putc('0',zdd->out); else (void) putc('@',zdd->out); /* should never happen */ } (void) fprintf(zdd->out," 1\n"); } } else { /* Check for missing variable. */ if (level != cuddIZ(zdd,node->index)) { list[zdd->invpermZ[level]] = 0; zddPrintCoverAux(zdd, node, level + 1, list); return; } Nnv = cuddE(node); Nv = cuddT(node); if (Nv == Nnv) { list[node->index] = 2; zddPrintCoverAux(zdd, Nnv, level + 1, list); return; } list[node->index] = 1; zddPrintCoverAux(zdd, Nv, level + 1, list); list[node->index] = 0; zddPrintCoverAux(zdd, Nnv, level + 1, list); } return; } /* end of zddPrintCoverAux */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/license000066400000000000000000000030071300674244400230510ustar00rootroot00000000000000Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/module.make000066400000000000000000000033641300674244400236360ustar00rootroot00000000000000SRC += src/bdd/cudd/cuddAPI.c \ src/bdd/cudd/cuddAddAbs.c \ src/bdd/cudd/cuddAddApply.c \ src/bdd/cudd/cuddAddFind.c \ src/bdd/cudd/cuddAddInv.c \ src/bdd/cudd/cuddAddIte.c \ src/bdd/cudd/cuddAddNeg.c \ src/bdd/cudd/cuddAddWalsh.c \ src/bdd/cudd/cuddAndAbs.c \ src/bdd/cudd/cuddAnneal.c \ src/bdd/cudd/cuddApa.c \ src/bdd/cudd/cuddApprox.c \ src/bdd/cudd/cuddBddAbs.c \ src/bdd/cudd/cuddBddCorr.c \ src/bdd/cudd/cuddBddIte.c \ src/bdd/cudd/cuddBridge.c \ src/bdd/cudd/cuddCache.c \ src/bdd/cudd/cuddCheck.c \ src/bdd/cudd/cuddClip.c \ src/bdd/cudd/cuddCof.c \ src/bdd/cudd/cuddCompose.c \ src/bdd/cudd/cuddDecomp.c \ src/bdd/cudd/cuddEssent.c \ src/bdd/cudd/cuddExact.c \ src/bdd/cudd/cuddExport.c \ src/bdd/cudd/cuddGenCof.c \ src/bdd/cudd/cuddGenetic.c \ src/bdd/cudd/cuddGroup.c \ src/bdd/cudd/cuddHarwell.c \ src/bdd/cudd/cuddInit.c \ src/bdd/cudd/cuddInteract.c \ src/bdd/cudd/cuddLCache.c \ src/bdd/cudd/cuddLevelQ.c \ src/bdd/cudd/cuddLinear.c \ src/bdd/cudd/cuddLiteral.c \ src/bdd/cudd/cuddMatMult.c \ src/bdd/cudd/cuddPriority.c \ src/bdd/cudd/cuddRead.c \ src/bdd/cudd/cuddRef.c \ src/bdd/cudd/cuddReorder.c \ src/bdd/cudd/cuddSat.c \ src/bdd/cudd/cuddSign.c \ src/bdd/cudd/cuddSolve.c \ src/bdd/cudd/cuddSplit.c \ src/bdd/cudd/cuddSubsetHB.c \ src/bdd/cudd/cuddSubsetSP.c \ src/bdd/cudd/cuddSymmetry.c \ src/bdd/cudd/cuddTable.c \ src/bdd/cudd/cuddUtil.c \ src/bdd/cudd/cuddWindow.c \ src/bdd/cudd/cuddZddCount.c \ src/bdd/cudd/cuddZddFuncs.c \ src/bdd/cudd/cuddZddGroup.c \ src/bdd/cudd/cuddZddIsop.c \ src/bdd/cudd/cuddZddLin.c \ src/bdd/cudd/cuddZddMisc.c \ src/bdd/cudd/cuddZddPort.c \ src/bdd/cudd/cuddZddReord.c \ src/bdd/cudd/cuddZddSetop.c \ src/bdd/cudd/cuddZddSymm.c \ src/bdd/cudd/cuddZddUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/r7x8.1.mat000066400000000000000000000004741300674244400231630ustar00rootroot000000000000007 9 0 0 1 0 1 1 0 2 1 0 3 4 0 4 3 0 5 3 0 6 3 0 8 3 1 0 4 1 1 3 1 2 2 1 3 4 1 4 1 1 5 2 1 6 4 1 8 3 2 0 1 2 1 1 2 2 4 2 4 2 2 5 3 2 6 3 2 8 3 3 0 2 3 1 1 3 3 4 3 4 4 3 5 1 3 8 1 4 0 2 4 1 3 4 2 2 4 3 4 4 4 1 4 5 1 4 6 2 4 8 2 5 0 3 5 1 3 5 2 4 5 3 4 5 4 1 5 5 3 5 6 3 5 8 4 6 1 1 6 2 1 6 3 4 6 4 2 6 5 4 6 6 4 6 8 2 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/r7x8.1.out000066400000000000000000000153631300674244400232140ustar00rootroot00000000000000# TestCudd Version #1.0, Release date 3/17/01 # ./testcudd -p 2 r7x8.1.mat :name: r7x8.1.mat: 7 rows 9 columns :1: M: 63 nodes 5 leaves 52 minterms 000000-- 1 000001-0 1 000001-1 4 000010-0 4 000010-1 3 000011-0 2 000011-1 4 000100-- 3 000101-0 3 000110-0 1 000110-1 2 000111-0 4 001000-- 1 001001-0 4 001010-0 2 001010-1 1 001011-1 4 001100-0 2 001100-1 3 001101-0 3 001110-0 4 001110-1 1 0100-0-0 3 011000-0 3 011010-0 1 100000-0 2 100000-1 3 100001-0 2 100001-1 4 100010-- 3 100011-- 4 100100-- 1 100101-0 2 100110-0 1 100110-1 3 100111-0 3 101000-1 1 101001-0 1 101001-1 4 101100-0 2 101100-1 4 101101-0 4 110000-0 2 110010-0 4 111000-0 2 :2: time to read the matrix = 0.00 sec :3: C: 22 nodes 1 leaves 52 minterms 0000---- 1 0001-0-- 1 0001-1-0 1 001000-- 1 001001-0 1 001010-- 1 001011-1 1 001100-- 1 001101-0 1 001110-- 1 01-0-0-0 1 1000---- 1 1001-0-- 1 1001-1-0 1 101000-1 1 101001-- 1 101100-- 1 101101-0 1 1100-0-0 1 111000-0 1 Testing iterator on cubes: 000000-- 1 000001-0 1 000001-1 4 000010-0 4 000010-1 3 000011-0 2 000011-1 4 000100-- 3 000101-0 3 000110-0 1 000110-1 2 000111-0 4 001000-- 1 001001-0 4 001010-0 2 001010-1 1 001011-1 4 001100-0 2 001100-1 3 001101-0 3 001110-0 4 001110-1 1 0100-0-0 3 011000-0 3 011010-0 1 100000-0 2 100000-1 3 100001-0 2 100001-1 4 100010-- 3 100011-- 4 100100-- 1 100101-0 2 100110-0 1 100110-1 3 100111-0 3 101000-1 1 101001-0 1 101001-1 4 101100-0 2 101100-1 4 101101-0 4 110000-0 2 110010-0 4 111000-0 2 Testing prime expansion of cubes: -000---- 1 -00--0-- 1 0--0-0-0 1 --00-0-0 1 -0-100-- 1 10-001-- 1 -00----0 1 00---0-- 1 -1-000-0 1 -0--01-0 1 -0--00-1 1 00-01--1 1 Testing iterator on primes (CNF): -0-0---- 1 -0---0-- 1 0-0-0--- 1 -0-----0 1 ---0-0-0 1 0101-1-1 1 --0-00-1 1 1-0-10-0 1 Cache used slots = 58.06% (expected 58.92%) xor1: 14 nodes 1 leaves 28 minterms 000--1-1 1 001-11-1 1 01---0-0 1 100--1-1 1 101-00-0 1 101-01-1 1 110--0-0 1 111-00-0 1 Chosen minterm for Hamming distance test: : 9 nodes 1 leaves 1 minterms 11110010 1 Minimum Hamming distance = 1 ycube: 5 nodes 1 leaves 8 minterms -0-0-0-0 1 CP: 11 nodes 1 leaves 7 minterms 00-0-0-0 1 1000-0-0 1 101000-1 1 :4: ineq: 10 nodes 1 leaves 42 minterms 001000-- 1 00101--- 1 1000---- 1 100100-- 1 10011--- 1 101----- 1 111000-- 1 11101--- 1 10------ 1 -01----- 1 1-1----- 1 -0-0---- 1 1--0---- 1 -0--10-- 1 --1010-- 1 1---10-- 1 :4: ess: 1 nodes 1 leaves 128 minterms -------- 1 :5: shortP: 7 nodes 1 leaves 2 minterms 000000-- 1 :5b: largest: 4 nodes 1 leaves 16 minterms 01-1---- 1 The value of M along the chosen shortest path is 1 :6: shortP: 5 nodes 1 leaves 8 minterms 0000---- 1 Average distance: 4133.34 Number of variables = 8 Number of slots = 2304 Number of keys = 995 Number of min dead = 9216 walsh1: 16 nodes 2 leaves 256 minterms -0--0--0--0- 1 -0--0--0--10 1 -0--0--0--11 -1 -0--0--10-0- 1 -0--0--10-10 1 -0--0--10-11 -1 -0--0--11-0- -1 -0--0--11-10 -1 -0--0--11-11 1 -0--10-0--0- 1 -0--10-0--10 1 -0--10-0--11 -1 -0--10-10-0- 1 -0--10-10-10 1 -0--10-10-11 -1 -0--10-11-0- -1 -0--10-11-10 -1 -0--10-11-11 1 -0--11-0--0- -1 -0--11-0--10 -1 -0--11-0--11 1 -0--11-10-0- -1 -0--11-10-10 -1 -0--11-10-11 1 -0--11-11-0- 1 -0--11-11-10 1 -0--11-11-11 -1 -10-0--0--0- 1 -10-0--0--10 1 -10-0--0--11 -1 -10-0--10-0- 1 -10-0--10-10 1 -10-0--10-11 -1 -10-0--11-0- -1 -10-0--11-10 -1 -10-0--11-11 1 -10-10-0--0- 1 -10-10-0--10 1 -10-10-0--11 -1 -10-10-10-0- 1 -10-10-10-10 1 -10-10-10-11 -1 -10-10-11-0- -1 -10-10-11-10 -1 -10-10-11-11 1 -10-11-0--0- -1 -10-11-0--10 -1 -10-11-0--11 1 -10-11-10-0- -1 -10-11-10-10 -1 -10-11-10-11 1 -10-11-11-0- 1 -10-11-11-10 1 -10-11-11-11 -1 -11-0--0--0- -1 -11-0--0--10 -1 -11-0--0--11 1 -11-0--10-0- -1 -11-0--10-10 -1 -11-0--10-11 1 -11-0--11-0- 1 -11-0--11-10 1 -11-0--11-11 -1 -11-10-0--0- -1 -11-10-0--10 -1 -11-10-0--11 1 -11-10-10-0- -1 -11-10-10-10 -1 -11-10-10-11 1 -11-10-11-0- 1 -11-10-11-10 1 -11-10-11-11 -1 -11-11-0--0- 1 -11-11-0--10 1 -11-11-0--11 -1 -11-11-10-0- 1 -11-11-10-10 1 -11-11-10-11 -1 -11-11-11-0- -1 -11-11-11-10 -1 -11-11-11-11 1 wtw: 14 nodes 2 leaves 16 minterms 0-00-00-00-0 16 0-00-00-01-1 16 0-00-01-10-0 16 0-00-01-11-1 16 0-01-10-00-0 16 0-01-10-01-1 16 0-01-11-10-0 16 0-01-11-11-1 16 1-10-00-00-0 16 1-10-00-01-1 16 1-10-01-10-0 16 1-10-01-11-1 16 1-11-10-00-0 16 1-11-10-01-1 16 1-11-11-10-0 16 1-11-11-11-1 16 Average length of non-empty lists = 1 **** CUDD modifiable parameters **** Hard limit for cache size: 7645866 Cache hit threshold for resizing: 30% Garbage collection enabled: yes Limit for fast unique table growth: 4587520 Maximum number of variables sifted per reordering: 1000 Maximum number of variable swaps per reordering: 2000000 Maximum growth while sifting a variable: 1.2 Dynamic reordering of BDDs enabled: no Default BDD reordering method: 4 Dynamic reordering of ZDDs enabled: no Default ZDD reordering method: 4 Realignment of ZDDs to BDDs enabled: no Realignment of BDDs to ZDDs enabled: no Dead nodes counted in triggering reordering: no Group checking criterion: 7 Recombination threshold: 0 Symmetry violation threshold: 0 Arc violation threshold: 0 GA population size: 0 Number of crossovers for GA: 0 Next reordering threshold: 4004 **** CUDD non-modifiable parameters **** Memory in use: 4274484 Peak number of nodes: 2044 Peak number of live nodes: 119 Number of BDD variables: 9 Number of ZDD variables: 0 Number of cache entries: 2048 Number of cache look-ups: 2846 Number of cache hits: 715 Number of cache insertions: 2289 Number of cache collisions: 937 Number of cache deletions: 1348 Cache used slots = 66.02% (expected 67.30%) Soft limit for cache size: 13312 Number of buckets in unique table: 2560 Used buckets in unique table: 0.51% (expected 0.51%) Number of BDD and ADD nodes: 13 Number of ZDD nodes: 0 Number of dead BDD and ADD nodes: 0 Number of dead ZDD nodes: 0 Total number of nodes allocated: 1091 Total number of nodes reclaimed: 950 Garbage collections so far: 1 Time for garbage collection: 0.00 sec Reorderings so far: 0 Time for reordering: 0.00 sec total time = 0.00 sec Runtime Statistics ------------------ Machine name: jobim.colorado.edu User time 0.0 seconds System time 0.0 seconds Average resident text size = 0K Average resident data+stack size = 0K Maximum resident size = 0K Virtual text size = 131644K Virtual data size = 151K data size initialized = 17K data size uninitialized = 0K data size sbrk = 134K Virtual memory limit = 358400K (4194304K) Major page faults = 0 Minor page faults = 1318 Swaps = 0 Input blocks = 0 Output blocks = 0 Context switch (voluntary) = 1 Context switch (involuntary) = 1 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/cudd/testcudd.c000066400000000000000000000723371300674244400235030ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [testcudd.c] PackageName [cudd] Synopsis [Sanity check tests for some CUDD functions.] Description [testcudd reads a matrix with real coefficients and transforms it into an ADD. It then performs various operations on the ADD and on the BDD corresponding to the ADD pattern. Finally, testcudd tests functions relate to Walsh matrices and matrix multiplication.] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "util.h" #include "cuddInt.h" /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define TESTCUDD_VERSION "TestCudd Version #1.0, Release date 3/17/01" /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] DD_UNUSED = "$Id: testcudd.c,v 1.20 2009/03/08 02:49:02 fabio Exp $"; #endif static const char *onames[] = { "C", "M" }; /* names of functions to be dumped */ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static void usage (char * prog); static FILE *open_file (char *filename, const char *mode); static int testIterators (DdManager *dd, DdNode *M, DdNode *C, int pr); static int testXor (DdManager *dd, DdNode *f, int pr, int nvars); static int testHamming (DdManager *dd, DdNode *f, int pr); static int testWalsh (DdManager *dd, int N, int cmu, int approach, int pr); /**AutomaticEnd***************************************************************/ /**Function******************************************************************** Synopsis [Main function for testcudd.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ int main(int argc, char **argv) { FILE *fp; /* pointer to input file */ char *file = (char *) ""; /* input file name */ FILE *dfp = NULL; /* pointer to dump file */ char *dfile; /* file for DD dump */ DdNode *dfunc[2]; /* addresses of the functions to be dumped */ DdManager *dd; /* pointer to DD manager */ DdNode *one; /* fast access to constant function */ DdNode *M; DdNode **x; /* pointers to variables */ DdNode **y; /* pointers to variables */ DdNode **xn; /* complements of row variables */ DdNode **yn_; /* complements of column variables */ DdNode **xvars; DdNode **yvars; DdNode *C; /* result of converting from ADD to BDD */ DdNode *ess; /* cube of essential variables */ DdNode *shortP; /* BDD cube of shortest path */ DdNode *largest; /* BDD of largest cube */ DdNode *shortA; /* ADD cube of shortest path */ DdNode *constN; /* value returned by evaluation of ADD */ DdNode *ycube; /* cube of the negated y vars for c-proj */ DdNode *CP; /* C-Projection of C */ DdNode *CPr; /* C-Selection of C */ int length; /* length of the shortest path */ int nx; /* number of variables */ int ny; int maxnx; int maxny; int m; int n; int N; int cmu; /* use CMU multiplication */ int pr; /* verbose printout level */ int harwell; int multiple; /* read multiple matrices */ int ok; int c; /* variable to read in options */ int approach; /* reordering approach */ int autodyn; /* automatic reordering */ int groupcheck; /* option for group sifting */ int profile; /* print heap profile if != 0 */ int keepperm; /* keep track of permutation */ int clearcache; /* clear the cache after each matrix */ int blifOrDot; /* dump format: 0 -> dot, 1 -> blif, ... */ int retval; /* return value */ int i; /* loop index */ long startTime; /* initial time */ long lapTime; int size; unsigned int cacheSize, maxMemory; unsigned int nvars,nslots; startTime = util_cpu_time(); approach = CUDD_REORDER_NONE; autodyn = 0; pr = 0; harwell = 0; multiple = 0; profile = 0; keepperm = 0; cmu = 0; N = 4; nvars = 4; cacheSize = 127; maxMemory = 0; nslots = CUDD_UNIQUE_SLOTS; clearcache = 0; groupcheck = CUDD_GROUP_CHECK7; dfile = NULL; blifOrDot = 0; /* dot format */ /* Parse command line. */ while ((c = util_getopt(argc, argv, (char *) "CDHMPS:a:bcd:g:hkmn:p:v:x:X:")) != EOF) { switch(c) { case 'C': cmu = 1; break; case 'D': autodyn = 1; break; case 'H': harwell = 1; break; case 'M': #ifdef MNEMOSYNE (void) mnem_setrecording(0); #endif break; case 'P': profile = 1; break; case 'S': nslots = atoi(util_optarg); break; case 'X': maxMemory = atoi(util_optarg); break; case 'a': approach = atoi(util_optarg); break; case 'b': blifOrDot = 1; /* blif format */ break; case 'c': clearcache = 1; break; case 'd': dfile = util_optarg; break; case 'g': groupcheck = atoi(util_optarg); break; case 'k': keepperm = 1; break; case 'm': multiple = 1; break; case 'n': N = atoi(util_optarg); break; case 'p': pr = atoi(util_optarg); break; case 'v': nvars = atoi(util_optarg); break; case 'x': cacheSize = atoi(util_optarg); break; case 'h': default: usage(argv[0]); break; } } if (argc - util_optind == 0) { file = (char *) "-"; } else if (argc - util_optind == 1) { file = argv[util_optind]; } else { usage(argv[0]); } if ((approach<0) || (approach>17)) { (void) fprintf(stderr,"Invalid approach: %d \n",approach); usage(argv[0]); } if (pr >= 0) { (void) printf("# %s\n", TESTCUDD_VERSION); /* Echo command line and arguments. */ (void) printf("#"); for (i = 0; i < argc; i++) { (void) printf(" %s", argv[i]); } (void) printf("\n"); (void) fflush(stdout); } /* Initialize manager and provide easy reference to terminals. */ dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory); one = DD_ONE(dd); dd->groupcheck = (Cudd_AggregationType) groupcheck; if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME); /* Open input file. */ fp = open_file(file, "r"); /* Open dump file if requested */ if (dfile != NULL) { dfp = open_file(dfile, "w"); } x = y = xn = yn_ = NULL; do { /* We want to start anew for every matrix. */ maxnx = maxny = 0; nx = maxnx; ny = maxny; if (pr>0) lapTime = util_cpu_time(); if (harwell) { if (pr >= 0) (void) printf(":name: "); ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, &m, &n, 0, 2, 1, 2, pr); } else { ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, &m, &n, 0, 2, 1, 2); if (pr >= 0) (void) printf(":name: %s: %d rows %d columns\n", file, m, n); } if (!ok) { (void) fprintf(stderr, "Error reading matrix\n"); exit(1); } if (nx > maxnx) maxnx = nx; if (ny > maxny) maxny = ny; /* Build cube of negated y's. */ ycube = DD_ONE(dd); Cudd_Ref(ycube); for (i = maxny - 1; i >= 0; i--) { DdNode *tmpp; tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube); if (tmpp == NULL) exit(2); Cudd_Ref(tmpp); Cudd_RecursiveDeref(dd,ycube); ycube = tmpp; } /* Initialize vectors of BDD variables used by priority func. */ xvars = ALLOC(DdNode *, nx); if (xvars == NULL) exit(2); for (i = 0; i < nx; i++) { xvars[i] = dd->vars[x[i]->index]; } yvars = ALLOC(DdNode *, ny); if (yvars == NULL) exit(2); for (i = 0; i < ny; i++) { yvars[i] = dd->vars[y[i]->index]; } /* Clean up */ for (i=0; i < maxnx; i++) { Cudd_RecursiveDeref(dd, x[i]); Cudd_RecursiveDeref(dd, xn[i]); } FREE(x); FREE(xn); for (i=0; i < maxny; i++) { Cudd_RecursiveDeref(dd, y[i]); Cudd_RecursiveDeref(dd, yn_[i]); } FREE(y); FREE(yn_); if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} if (pr>0) (void) printf(":2: time to read the matrix = %s\n", util_print_time(util_cpu_time() - lapTime)); C = Cudd_addBddPattern(dd, M); if (C == 0) exit(2); Cudd_Ref(C); if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);} /* Test iterators. */ retval = testIterators(dd,M,C,pr); if (retval == 0) exit(2); cuddCacheProfile(dd,stdout); /* Test XOR */ retval = testXor(dd,C,pr,nx+ny); if (retval == 0) exit(2); /* Test Hamming distance functions. */ retval = testHamming(dd,C,pr); if (retval == 0) exit(2); /* Test selection functions. */ CP = Cudd_CProjection(dd,C,ycube); if (CP == NULL) exit(2); Cudd_Ref(CP); if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);} if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);} if (nx == ny) { CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL, (DdNode *)NULL,ny,Cudd_Xgty); if (CPr == NULL) exit(2); Cudd_Ref(CPr); if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);} if (CP != CPr) { (void) printf("CP != CPr!\n"); } Cudd_RecursiveDeref(dd, CPr); } /* Test inequality generator. */ { int Nmin = ddMin(nx,ny); int q; DdGen *gen; int *cube; DdNode *f = Cudd_Inequality(dd,Nmin,2,xvars,yvars); if (f == NULL) exit(2); Cudd_Ref(f); if (pr>0) { (void) printf(":4: ineq"); Cudd_PrintDebug(dd,f,nx+ny,pr); if (pr>1) { Cudd_ForeachPrime(dd,Cudd_Not(f),Cudd_Not(f),gen,cube) { for (q = 0; q < dd->size; q++) { switch (cube[q]) { case 0: (void) printf("1"); break; case 1: (void) printf("0"); break; case 2: (void) printf("-"); break; default: (void) printf("?"); } } (void) printf(" 1\n"); } (void) printf("\n"); } } Cudd_IterDerefBdd(dd, f); } FREE(xvars); FREE(yvars); Cudd_RecursiveDeref(dd, CP); Cudd_RecursiveDeref(dd, ycube); /* Test functions for essential variables. */ ess = Cudd_FindEssential(dd,C); if (ess == NULL) exit(2); Cudd_Ref(ess); if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);} Cudd_RecursiveDeref(dd, ess); /* Test functions for shortest paths. */ shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length); if (shortP == NULL) exit(2); Cudd_Ref(shortP); if (pr>0) { (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); } /* Test functions for largest cubes. */ largest = Cudd_LargestCube(dd, Cudd_Not(C), &length); if (largest == NULL) exit(2); Cudd_Ref(largest); if (pr>0) { (void) printf(":5b: largest"); Cudd_PrintDebug(dd,largest,nx+ny,pr); } Cudd_RecursiveDeref(dd, largest); /* Test Cudd_addEvalConst and Cudd_addIteConstant. */ shortA = Cudd_BddToAdd(dd,shortP); if (shortA == NULL) exit(2); Cudd_Ref(shortA); Cudd_RecursiveDeref(dd, shortP); constN = Cudd_addEvalConst(dd,shortA,M); if (constN == DD_NON_CONSTANT) exit(2); if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2); if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));} Cudd_RecursiveDeref(dd, shortA); shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length); if (shortP == NULL) exit(2); Cudd_Ref(shortP); if (pr>0) { (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); } /* Test Cudd_bddIteConstant and Cudd_bddLeq. */ if (!Cudd_bddLeq(dd,shortP,C)) exit(2); if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),one,C) != one) exit(2); Cudd_RecursiveDeref(dd, shortP); if (profile) { retval = cuddHeapProfile(dd); } size = dd->size; if (pr>0) { (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); } /* Reorder if so requested. */ if (approach != CUDD_REORDER_NONE) { #ifndef DD_STATS retval = Cudd_EnableReorderingReporting(dd); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n"); exit(3); } #endif #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); exit(3); } retval = Cudd_CheckKeys(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); exit(3); } #endif retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); exit(3); } #ifndef DD_STATS retval = Cudd_DisableReorderingReporting(dd); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n"); exit(3); } #endif #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); exit(3); } retval = Cudd_CheckKeys(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); exit(3); } #endif if (approach == CUDD_REORDER_SYMM_SIFT || approach == CUDD_REORDER_SYMM_SIFT_CONV) { Cudd_SymmProfile(dd,0,dd->size-1); } if (pr>0) { (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); } if (keepperm) { /* Print variable permutation. */ (void) printf("Variable Permutation:"); for (i=0; iinvperm[i]); } (void) printf("\n"); (void) printf("Inverse Permutation:"); for (i=0; iperm[i]); } (void) printf("\n"); } if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} if (profile) { retval = cuddHeapProfile(dd); } } /* Dump DDs of C and M if so requested. */ if (dfile != NULL) { dfunc[0] = C; dfunc[1] = M; if (blifOrDot == 1) { /* Only dump C because blif cannot handle ADDs */ retval = Cudd_DumpBlif(dd,1,dfunc,NULL,(char **)onames, NULL,dfp,0); } else { retval = Cudd_DumpDot(dd,2,dfunc,NULL,(char **)onames,dfp); } if (retval != 1) { (void) fprintf(stderr,"abnormal termination\n"); exit(2); } } Cudd_RecursiveDeref(dd, C); Cudd_RecursiveDeref(dd, M); if (clearcache) { if (pr>0) {(void) printf("Clearing the cache... ");} for (i = dd->cacheSlots - 1; i>=0; i--) { dd->cache[i].data = NIL(DdNode); } if (pr>0) {(void) printf("done\n");} } if (pr>0) { (void) printf("Number of variables = %6d\t",dd->size); (void) printf("Number of slots = %6u\n",dd->slots); (void) printf("Number of keys = %6u\t",dd->keys); (void) printf("Number of min dead = %6u\n",dd->minDead); } } while (multiple && !feof(fp)); fclose(fp); if (dfile != NULL) { fclose(dfp); } /* Second phase: experiment with Walsh matrices. */ if (!testWalsh(dd,N,cmu,approach,pr)) { exit(2); } /* Check variable destruction. */ assert(cuddDestroySubtables(dd,3)); assert(Cudd_DebugCheck(dd) == 0); assert(Cudd_CheckKeys(dd) == 0); retval = Cudd_CheckZeroRef(dd); ok = retval != 0; /* ok == 0 means O.K. */ if (retval != 0) { (void) fprintf(stderr, "%d non-zero DD reference counts after dereferencing\n", retval); } if (pr >= 0) { (void) Cudd_PrintInfo(dd,stdout); } Cudd_Quit(dd); #ifdef MNEMOSYNE mnem_writestats(); #endif if (pr>0) (void) printf("total time = %s\n", util_print_time(util_cpu_time() - startTime)); if (pr >= 0) util_print_cpu_stats(stdout); exit(ok); /* NOTREACHED */ } /* end of main */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints usage info for testcudd.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static void usage(char *prog) { (void) fprintf(stderr, "usage: %s [options] [file]\n", prog); (void) fprintf(stderr, " -C\t\tuse CMU multiplication algorithm\n"); (void) fprintf(stderr, " -D\t\tenable automatic dynamic reordering\n"); (void) fprintf(stderr, " -H\t\tread matrix in Harwell format\n"); (void) fprintf(stderr, " -M\t\tturns off memory allocation recording\n"); (void) fprintf(stderr, " -P\t\tprint BDD heap profile\n"); (void) fprintf(stderr, " -S n\t\tnumber of slots for each subtable\n"); (void) fprintf(stderr, " -X n\t\ttarget maximum memory in bytes\n"); (void) fprintf(stderr, " -a n\t\tchoose reordering approach (0-13)\n"); (void) fprintf(stderr, " \t\t\t0: same as autoMethod\n"); (void) fprintf(stderr, " \t\t\t1: no reordering (default)\n"); (void) fprintf(stderr, " \t\t\t2: random\n"); (void) fprintf(stderr, " \t\t\t3: pivot\n"); (void) fprintf(stderr, " \t\t\t4: sifting\n"); (void) fprintf(stderr, " \t\t\t5: sifting to convergence\n"); (void) fprintf(stderr, " \t\t\t6: symmetric sifting\n"); (void) fprintf(stderr, " \t\t\t7: symmetric sifting to convergence\n"); (void) fprintf(stderr, " \t\t\t8-10: window of size 2-4\n"); (void) fprintf(stderr, " \t\t\t11-13: window of size 2-4 to conv.\n"); (void) fprintf(stderr, " \t\t\t14: group sifting\n"); (void) fprintf(stderr, " \t\t\t15: group sifting to convergence\n"); (void) fprintf(stderr, " \t\t\t16: simulated annealing\n"); (void) fprintf(stderr, " \t\t\t17: genetic algorithm\n"); (void) fprintf(stderr, " -b\t\tuse blif as format for dumps\n"); (void) fprintf(stderr, " -c\t\tclear the cache after each matrix\n"); (void) fprintf(stderr, " -d file\tdump DDs to file\n"); (void) fprintf(stderr, " -g\t\tselect aggregation criterion (0,5,7)\n"); (void) fprintf(stderr, " -h\t\tprints this message\n"); (void) fprintf(stderr, " -k\t\tprint the variable permutation\n"); (void) fprintf(stderr, " -m\t\tread multiple matrices (only with -H)\n"); (void) fprintf(stderr, " -n n\t\tnumber of variables\n"); (void) fprintf(stderr, " -p n\t\tcontrol verbosity\n"); (void) fprintf(stderr, " -v n\t\tinitial variables in the unique table\n"); (void) fprintf(stderr, " -x n\t\tinitial size of the cache\n"); exit(2); } /* end of usage */ /**Function******************************************************************** Synopsis [Opens a file.] Description [Opens a file, or fails with an error message and exits. Allows '-' as a synonym for standard input.] SideEffects [None] SeeAlso [] ******************************************************************************/ static FILE * open_file(char *filename, const char *mode) { FILE *fp; if (strcmp(filename, "-") == 0) { return mode[0] == 'r' ? stdin : stdout; } else if ((fp = fopen(filename, mode)) == NULL) { perror(filename); exit(1); } return fp; } /* end of open_file */ /**Function******************************************************************** Synopsis [Tests Walsh matrix multiplication.] Description [Tests Walsh matrix multiplication. Return 1 if successful; 0 otherwise.] SideEffects [May create new variables in the manager.] SeeAlso [] ******************************************************************************/ static int testWalsh( DdManager *dd /* manager */, int N /* number of variables */, int cmu /* use CMU approach to matrix multiplication */, int approach /* reordering approach */, int pr /* verbosity level */) { DdNode *walsh1, *walsh2, *wtw; DdNode **x, **v, **z; int i, retval; DdNode *one = DD_ONE(dd); DdNode *zero = DD_ZERO(dd); if (N > 3) { x = ALLOC(DdNode *,N); v = ALLOC(DdNode *,N); z = ALLOC(DdNode *,N); for (i = N-1; i >= 0; i--) { Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,one,zero)); Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,one,zero)); Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,one,zero)); } Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N)); if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);} Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N)); if (cmu) { Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N)); } else { Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N)); } if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);} if (approach != CUDD_REORDER_NONE) { #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); return(0); } #endif retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); if (retval == 0) { (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); return(0); } #ifdef DD_DEBUG retval = Cudd_DebugCheck(dd); if (retval != 0) { (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); return(0); } #endif if (approach == CUDD_REORDER_SYMM_SIFT || approach == CUDD_REORDER_SYMM_SIFT_CONV) { Cudd_SymmProfile(dd,0,dd->size-1); } } /* Clean up. */ Cudd_RecursiveDeref(dd, wtw); Cudd_RecursiveDeref(dd, walsh1); Cudd_RecursiveDeref(dd, walsh2); for (i=0; i < N; i++) { Cudd_RecursiveDeref(dd, x[i]); Cudd_RecursiveDeref(dd, v[i]); Cudd_RecursiveDeref(dd, z[i]); } FREE(x); FREE(v); FREE(z); } return(1); } /* end of testWalsh */ /**Function******************************************************************** Synopsis [Tests iterators.] Description [Tests iterators on cubes and nodes.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int testIterators( DdManager *dd, DdNode *M, DdNode *C, int pr) { int *cube; CUDD_VALUE_TYPE value; DdGen *gen; int q; /* Test iterator for cubes. */ if (pr>1) { (void) printf("Testing iterator on cubes:\n"); Cudd_ForeachCube(dd,M,gen,cube,value) { for (q = 0; q < dd->size; q++) { switch (cube[q]) { case 0: (void) printf("0"); break; case 1: (void) printf("1"); break; case 2: (void) printf("-"); break; default: (void) printf("?"); } } (void) printf(" %g\n",value); } (void) printf("\n"); } if (pr>1) { (void) printf("Testing prime expansion of cubes:\n"); if (!Cudd_bddPrintCover(dd,C,C)) return(0); } if (pr>1) { (void) printf("Testing iterator on primes (CNF):\n"); Cudd_ForeachPrime(dd,Cudd_Not(C),Cudd_Not(C),gen,cube) { for (q = 0; q < dd->size; q++) { switch (cube[q]) { case 0: (void) printf("1"); break; case 1: (void) printf("0"); break; case 2: (void) printf("-"); break; default: (void) printf("?"); } } (void) printf(" 1\n"); } (void) printf("\n"); } /* Test iterator on nodes. */ if (pr>2) { DdNode *node; (void) printf("Testing iterator on nodes:\n"); Cudd_ForeachNode(dd,M,gen,node) { if (Cudd_IsConstant(node)) { #if SIZEOF_VOID_P == 8 (void) printf("ID = 0x%lx\tvalue = %-9g\n", (ptruint) node / (ptruint) sizeof(DdNode), Cudd_V(node)); #else (void) printf("ID = 0x%x\tvalue = %-9g\n", (ptruint) node / (ptruint) sizeof(DdNode), Cudd_V(node)); #endif } else { #if SIZEOF_VOID_P == 8 (void) printf("ID = 0x%lx\tindex = %u\tr = %u\n", (ptruint) node / (ptruint) sizeof(DdNode), node->index, node->ref); #else (void) printf("ID = 0x%x\tindex = %u\tr = %u\n", (ptruint) node / (ptruint) sizeof(DdNode), node->index, node->ref); #endif } } (void) printf("\n"); } return(1); } /* end of testIterators */ /**Function******************************************************************** Synopsis [Tests the functions related to the exclusive OR.] Description [Tests the functions related to the exclusive OR. It builds the boolean difference of the given function in three different ways and checks that the results is the same. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int testXor(DdManager *dd, DdNode *f, int pr, int nvars) { DdNode *f1, *f0, *res1, *res2; int x; /* Extract cofactors w.r.t. mid variable. */ x = nvars / 2; f1 = Cudd_Cofactor(dd,f,dd->vars[x]); if (f1 == NULL) return(0); Cudd_Ref(f1); f0 = Cudd_Cofactor(dd,f,Cudd_Not(dd->vars[x])); if (f0 == NULL) { Cudd_RecursiveDeref(dd,f1); return(0); } Cudd_Ref(f0); /* Compute XOR of cofactors with ITE. */ res1 = Cudd_bddIte(dd,f1,Cudd_Not(f0),f0); if (res1 == NULL) return(0); Cudd_Ref(res1); if (pr>0) {(void) printf("xor1"); Cudd_PrintDebug(dd,res1,nvars,pr);} /* Compute XOR of cofactors with XOR. */ res2 = Cudd_bddXor(dd,f1,f0); if (res2 == NULL) { Cudd_RecursiveDeref(dd,res1); return(0); } Cudd_Ref(res2); if (res1 != res2) { if (pr>0) {(void) printf("xor2"); Cudd_PrintDebug(dd,res2,nvars,pr);} Cudd_RecursiveDeref(dd,res1); Cudd_RecursiveDeref(dd,res2); return(0); } Cudd_RecursiveDeref(dd,res1); Cudd_RecursiveDeref(dd,f1); Cudd_RecursiveDeref(dd,f0); /* Compute boolean difference directly. */ res1 = Cudd_bddBooleanDiff(dd,f,x); if (res1 == NULL) { Cudd_RecursiveDeref(dd,res2); return(0); } Cudd_Ref(res1); if (res1 != res2) { if (pr>0) {(void) printf("xor3"); Cudd_PrintDebug(dd,res1,nvars,pr);} Cudd_RecursiveDeref(dd,res1); Cudd_RecursiveDeref(dd,res2); return(0); } Cudd_RecursiveDeref(dd,res1); Cudd_RecursiveDeref(dd,res2); return(1); } /* end of testXor */ /**Function******************************************************************** Synopsis [Tests the Hamming distance functions.] Description [Tests the Hammming distance functions. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int testHamming( DdManager *dd, DdNode *f, int pr) { DdNode **vars, *minBdd, *zero, *scan; int i; int d; int *minterm; int size = Cudd_ReadSize(dd); vars = ALLOC(DdNode *, size); if (vars == NULL) return(0); for (i = 0; i < size; i++) { vars[i] = Cudd_bddIthVar(dd,i); } minBdd = Cudd_bddPickOneMinterm(dd,Cudd_Not(f),vars,size); Cudd_Ref(minBdd); if (pr > 0) { (void) printf("Chosen minterm for Hamming distance test: "); Cudd_PrintDebug(dd,minBdd,size,pr); } minterm = ALLOC(int,size); if (minterm == NULL) { FREE(vars); Cudd_RecursiveDeref(dd,minBdd); return(0); } scan = minBdd; zero = Cudd_Not(DD_ONE(dd)); while (!Cudd_IsConstant(scan)) { DdNode *R = Cudd_Regular(scan); DdNode *T = Cudd_T(R); DdNode *E = Cudd_E(R); if (R != scan) { T = Cudd_Not(T); E = Cudd_Not(E); } if (T == zero) { minterm[R->index] = 0; scan = E; } else { minterm[R->index] = 1; scan = T; } } Cudd_RecursiveDeref(dd,minBdd); d = Cudd_MinHammingDist(dd,f,minterm,size); (void) printf("Minimum Hamming distance = %d\n", d); FREE(vars); FREE(minterm); return(1); } /* end of testHamming */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/000077500000000000000000000000001300674244400213375ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/dsd.h000066400000000000000000000144641300674244400222730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dsd.h] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [External declarations of the package. This fast BDD-based recursive algorithm for simple (single-output) DSD is based on the following papers: (1) V. Bertacco and M. Damiani, "Disjunctive decomposition of logic functions," Proc. ICCAD '97, pp. 78-82. (2) Y. Matsunaga, "An exact and efficient algorithm for disjunctive decomposition", Proc. SASIMI '98, pp. 44-50. The scope of detected decompositions is the same as in the paper: T. Sasao and M. Matsuura, "DECOMPOS: An integrated system for functional decomposition," Proc. IWLS '98, pp. 471-477.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsd.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__bdd__dsd__dsd_h #define ABC__bdd__dsd__dsd_h //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START // types of DSD nodes enum Dsd_Type_t_ { DSD_NODE_NONE = 0, DSD_NODE_CONST1 = 1, DSD_NODE_BUF = 2, DSD_NODE_OR = 3, DSD_NODE_EXOR = 4, DSD_NODE_PRIME = 5, }; //////////////////////////////////////////////////////////////////////// /// TYPEDEF DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Dsd_Manager_t_ Dsd_Manager_t; typedef struct Dsd_Node_t_ Dsd_Node_t; typedef enum Dsd_Type_t_ Dsd_Type_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // complementation and testing for pointers for decomposition entries #define Dsd_IsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01))) #define Dsd_Regular(p) ((Dsd_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) #define Dsd_Not(p) ((Dsd_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) #define Dsd_NotCond(p,c) ((Dsd_Node_t *)((ABC_PTRUINT_T)(p) ^ (c))) //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // iterator through the transitions #define Dsd_NodeForEachChild( Node, Index, Child ) \ for ( Index = 0; \ Index < Dsd_NodeReadDecsNum(Node) && \ ((Child = Dsd_NodeReadDec(Node,Index))>=0); \ Index++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== dsdApi.c =======================================================*/ extern Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ); extern DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ); extern DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ); extern Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ); extern Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ); extern int Dsd_NodeReadDecsNum( Dsd_Node_t * p ); extern int Dsd_NodeReadMark( Dsd_Node_t * p ); extern void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ); extern DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ); extern Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ); extern Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ); extern Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ); /*=== dsdMan.c =======================================================*/ extern Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ); extern void Dsd_ManagerStop( Dsd_Manager_t * dMan ); /*=== dsdProc.c =======================================================*/ extern void Dsd_Decompose( Dsd_Manager_t * dMan, DdNode ** pbFuncs, int nFuncs ); extern Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ); /*=== dsdTree.c =======================================================*/ extern void Dsd_TreeNodeGetInfo( Dsd_Manager_t * dMan, int * DepthMax, int * GateSizeMax ); extern void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ); extern int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ); extern int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * dMan ); extern int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ); extern int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ); extern int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ); extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, int * pVars ); extern Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes ); extern Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ); extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ); extern void Dsd_TreePrint2( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int Output ); extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ); /*=== dsdLocal.c =======================================================*/ extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/dsdApi.c000066400000000000000000000103521300674244400227100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dsdApi.c] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [Implementation of API functions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsdApi.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dsdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [APIs of the DSD node.] Description [The node's type can be retrieved by calling Dsd_NodeReadType(). The type is one of the following: constant 1 node, the buffer (or the elementary variable), OR gate, EXOR gate, or PRIME function (a non-DSD-decomposable function with more than two inputs). The return value of Dsd_NodeReadFunc() is the global function of the DSD node. The return value of Dsd_NodeReadSupp() is the support of the global function of the DSD node. The array of DSD nodes returned by Dsd_NodeReadDecs() is the array of decomposition nodes for the formal inputs of the given node. The number of decomposition entries returned by Dsd_NodeReadDecsNum() is the number of formal inputs. The mark is explained below.] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ) { return p->Type; } DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ) { return p->G; } DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ) { return p->S; } Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ) { return p->pDecs; } Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ) { return p->pDecs[i]; } int Dsd_NodeReadDecsNum( Dsd_Node_t * p ) { return p->nDecs; } int Dsd_NodeReadMark( Dsd_Node_t * p ) { return p->Mark; } /**Function************************************************************* Synopsis [APIs of the DSD node.] Description [This API allows the user to set the integer mark in the given DSD node. The mark is guaranteed to persist as long as the calls to the decomposition are not performed. In any case, the mark is useful to associate the node with some temporary information, such as its number in the DFS ordered list of the DSD nodes or its number in the BLIF file that it being written.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ){ p->Mark = Mark; } /**Function************************************************************* Synopsis [APIs of the DSD manager.] Description [Allows the use to get hold of an individual leave of the DSD tree (Dsd_ManagerReadInput) or an individual root of the decomposition tree (Dsd_ManagerReadRoot). The root may have the complemented attribute.] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ) { return pMan->pRoots[i]; } Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ) { return pMan->pInputs[i]; } Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ) { return pMan->pConst1; } DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ) { return pMan->dd; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/dsdCheck.c000066400000000000000000000233601300674244400232170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dsdCheck.c] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [Procedures to check the identity of root functions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsdCheck.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dsdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Dsd_Cache_t_ Dds_Cache_t; typedef struct Dsd_Entry_t_ Dsd_Entry_t; struct Dsd_Cache_t_ { Dsd_Entry_t * pTable; int nTableSize; int nSuccess; int nFailure; }; struct Dsd_Entry_t_ { DdNode * bX[5]; }; static Dds_Cache_t * pCache; static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [(Re)allocates the local cache.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Dsd_CheckCacheAllocate( int nEntries ) { int nRequested; pCache = ABC_ALLOC( Dds_Cache_t, 1 ); memset( pCache, 0, sizeof(Dds_Cache_t) ); // check what is the size of the current cache nRequested = Abc_PrimeCudd( nEntries ); if ( pCache->nTableSize != nRequested ) { // the current size is different // deallocate the old, allocate the new if ( pCache->nTableSize ) Dsd_CheckCacheDeallocate(); // allocate memory for the hash table pCache->nTableSize = nRequested; pCache->pTable = ABC_ALLOC( Dsd_Entry_t, nRequested ); } // otherwise, there is no need to allocate, just clean Dsd_CheckCacheClear(); // printf( "\nThe number of allocated cache entries = %d.\n\n", pCache->nTableSize ); } /**Function******************************************************************** Synopsis [Deallocates the local cache.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Dsd_CheckCacheDeallocate() { ABC_FREE( pCache->pTable ); ABC_FREE( pCache ); } /**Function******************************************************************** Synopsis [Clears the local cache.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Dsd_CheckCacheClear() { int i; for ( i = 0; i < pCache->nTableSize; i++ ) pCache->pTable[0].bX[0] = NULL; } /**Function******************************************************************** Synopsis [Checks whether it is true that bF1(bC1=0) == bF2(bC2=0).] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) { int RetValue; // pCache->nSuccess = 0; // pCache->nFailure = 0; RetValue = Dsd_CheckRootFunctionIdentity_rec(dd, bF1, bF2, bC1, bC2); // printf( "Cache success = %d. Cache failure = %d.\n", pCache->nSuccess, pCache->nFailure ); return RetValue; } /**Function******************************************************************** Synopsis [Performs the recursive step of Dsd_CheckRootFunctionIdentity().] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) { unsigned HKey; // if either bC1 or bC2 is zero, the test is true // if ( bC1 == b0 || bC2 == b0 ) return 1; assert( bC1 != b0 ); assert( bC2 != b0 ); // if both bC1 and bC2 are one - perform comparison if ( bC1 == b1 && bC2 == b1 ) return (int)( bF1 == bF2 ); if ( bF1 == b0 ) return Cudd_bddLeq( dd, bC2, Cudd_Not(bF2) ); if ( bF1 == b1 ) return Cudd_bddLeq( dd, bC2, bF2 ); if ( bF2 == b0 ) return Cudd_bddLeq( dd, bC1, Cudd_Not(bF1) ); if ( bF2 == b1 ) return Cudd_bddLeq( dd, bC1, bF1 ); // otherwise, keep expanding // check cache // HKey = _Hash( ((unsigned)bF1), ((unsigned)bF2), ((unsigned)bC1), ((unsigned)bC2) ); HKey = hashKey4( bF1, bF2, bC1, bC2, pCache->nTableSize ); if ( pCache->pTable[HKey].bX[0] == bF1 && pCache->pTable[HKey].bX[1] == bF2 && pCache->pTable[HKey].bX[2] == bC1 && pCache->pTable[HKey].bX[3] == bC2 ) { pCache->nSuccess++; return (int)(ABC_PTRUINT_T)pCache->pTable[HKey].bX[4]; // the last bit records the result (yes/no) } else { // determine the top variables int RetValue; DdNode * bA[4] = { bF1, bF2, bC1, bC2 }; // arguments DdNode * bAR[4] = { Cudd_Regular(bF1), Cudd_Regular(bF2), Cudd_Regular(bC1), Cudd_Regular(bC2) }; // regular arguments int CurLevel[4] = { cuddI(dd,bAR[0]->index), cuddI(dd,bAR[1]->index), cuddI(dd,bAR[2]->index), cuddI(dd,bAR[3]->index) }; int TopLevel = CUDD_CONST_INDEX; int i; DdNode * bE[4], * bT[4]; DdNode * bF1next, * bF2next, * bC1next, * bC2next; pCache->nFailure++; // determine the top level for ( i = 0; i < 4; i++ ) if ( TopLevel > CurLevel[i] ) TopLevel = CurLevel[i]; // compute the cofactors for ( i = 0; i < 4; i++ ) if ( TopLevel == CurLevel[i] ) { if ( bA[i] != bAR[i] ) // complemented { bE[i] = Cudd_Not(cuddE(bAR[i])); bT[i] = Cudd_Not(cuddT(bAR[i])); } else { bE[i] = cuddE(bAR[i]); bT[i] = cuddT(bAR[i]); } } else bE[i] = bT[i] = bA[i]; // solve subproblems // three cases are possible // (1) the top var belongs to both C1 and C2 // in this case, any cofactor of F1 and F2 will do, // as long as the corresponding cofactor of C1 and C2 is not equal to 0 if ( TopLevel == CurLevel[2] && TopLevel == CurLevel[3] ) { if ( bE[2] != b0 ) // C1 { bF1next = bE[0]; bC1next = bE[2]; } else { bF1next = bT[0]; bC1next = bT[2]; } if ( bE[3] != b0 ) // C2 { bF2next = bE[1]; bC2next = bE[3]; } else { bF2next = bT[1]; bC2next = bT[3]; } RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bF2next, bC1next, bC2next ); } // (2) the top var belongs to either C1 or C2 // in this case normal splitting of cofactors else if ( TopLevel == CurLevel[2] && TopLevel != CurLevel[3] ) { if ( bE[2] != b0 ) // C1 { bF1next = bE[0]; bC1next = bE[2]; } else { bF1next = bT[0]; bC1next = bT[2]; } // split around this variable RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bE[1], bC1next, bE[3] ); if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bT[1], bC1next, bT[3] ); } else if ( TopLevel != CurLevel[2] && TopLevel == CurLevel[3] ) { if ( bE[3] != b0 ) // C2 { bF2next = bE[1]; bC2next = bE[3]; } else { bF2next = bT[1]; bC2next = bT[3]; } // split around this variable RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bF2next, bE[2], bC2next ); if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bF2next, bT[2], bC2next ); } // (3) the top var does not belong to C1 and C2 // in this case normal splitting of cofactors else // if ( TopLevel != CurLevel[2] && TopLevel != CurLevel[3] ) { // split around this variable RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bE[1], bE[2], bE[3] ); if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bT[1], bT[2], bT[3] ); } // set cache for ( i = 0; i < 4; i++ ) pCache->pTable[HKey].bX[i] = bA[i]; pCache->pTable[HKey].bX[4] = (DdNode*)(ABC_PTRUINT_T)RetValue; return RetValue; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/dsdInt.h000066400000000000000000000074011300674244400227370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dsdInt.h] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [Internal declarations of the package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsdInt.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__bdd__dsd__dsdInt_h #define ABC__bdd__dsd__dsdInt_h #include "bdd/extrab/extraBdd.h" #include "dsd.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// TYPEDEF DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef unsigned char byte; //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // DSD manager struct Dsd_Manager_t_ { DdManager * dd; // the BDD manager st__table * Table; // the mapping of BDDs into their DEs int nInputs; // the number of primary inputs int nRoots; // the number of primary outputs int nRootsAlloc;// the number of primary outputs Dsd_Node_t ** pInputs; // the primary input nodes Dsd_Node_t ** pRoots; // the primary output nodes Dsd_Node_t * pConst1; // the constant node int fVerbose; // the verbosity level }; // DSD node struct Dsd_Node_t_ { Dsd_Type_t Type; // decomposition type DdNode * G; // function of the node DdNode * S; // support of this function Dsd_Node_t ** pDecs; // pointer to structures for formal inputs int Mark; // the mark used by CASE 4 of disjoint decomposition short nDecs; // the number of formal inputs short nVisits; // the counter of visits }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define MAXINPUTS 1000 //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== dsdCheck.c =======================================================*/ extern void Dsd_CheckCacheAllocate( int nEntries ); extern void Dsd_CheckCacheDeallocate(); extern void Dsd_CheckCacheClear(); extern int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); /*=== dsdTree.c =======================================================*/ extern Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ); extern void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ); extern void Dsd_TreeUnmark( Dsd_Manager_t * dMan ); extern DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/dsdLocal.c000066400000000000000000000251411300674244400232330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dsdLocal.c] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [Deriving the local function of the DSD node.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsdLocal.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dsdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// static DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bFunc, st__table * pCache, int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ); static DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the local function of the DSD node. ] Description [The local function is computed using the global function of the node and the global functions of the formal inputs. The resulting local function is mapped using the topmost N variables of the manager. The number of variables N is equal to the number of formal inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) { int * pForm2Var; // the mapping of each formal input into its first var int * pVar2Form; // the mapping of each var into its formal inputs int i, iVar, iLev, * pPermute; DdNode ** pbCube0, ** pbCube1; DdNode * bFunc, * bRes, * bTemp; st__table * pCache; pPermute = ABC_ALLOC( int, dd->size ); pVar2Form = ABC_ALLOC( int, dd->size ); pForm2Var = ABC_ALLOC( int, dd->size ); pbCube0 = ABC_ALLOC( DdNode *, dd->size ); pbCube1 = ABC_ALLOC( DdNode *, dd->size ); // remap the global function in such a way that // the support variables of each formal input are adjacent iLev = 0; for ( i = 0; i < pNode->nDecs; i++ ) { pForm2Var[i] = dd->invperm[i]; for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) ) { iVar = dd->invperm[iLev]; pPermute[bTemp->index] = iVar; pVar2Form[iVar] = i; iLev++; } // collect the cubes representing each assignment pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( pbCube0[i] ); pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( pbCube1[i] ); } // remap the function bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc ); // remap the cube for ( i = 0; i < pNode->nDecs; i++ ) { pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] ); Cudd_RecursiveDeref( dd, bTemp ); pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] ); Cudd_RecursiveDeref( dd, bTemp ); } // remap the function pCache = st__init_table( st__ptrcmp, st__ptrhash);; bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes ); st__free_table( pCache ); Cudd_RecursiveDeref( dd, bFunc ); for ( i = 0; i < pNode->nDecs; i++ ) { Cudd_RecursiveDeref( dd, pbCube0[i] ); Cudd_RecursiveDeref( dd, pbCube1[i] ); } /* //////////// // permute the function once again // in such a way that i-th var stood for i-th formal input for ( i = 0; i < dd->size; i++ ) pPermute[i] = -1; for ( i = 0; i < pNode->nDecs; i++ ) pPermute[dd->invperm[i]] = i; bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); //////////// */ ABC_FREE(pPermute); ABC_FREE(pVar2Form); ABC_FREE(pForm2Var); ABC_FREE(pbCube0); ABC_FREE(pbCube1); Cudd_Deref( bRes ); return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bF, st__table * pCache, int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ) { DdNode * bFR, * bF0, * bF1; DdNode * bRes0, * bRes1, * bRes; int iForm; bFR = Cudd_Regular(bF); if ( cuddIsConstant(bFR) ) return bF; // check the hash-table if ( bFR->ref != 1 ) { if ( st__lookup( pCache, (char *)bF, (char **)&bRes ) ) return bRes; } // get the formal input iForm = pVar2Form[bFR->index]; // get the nodes pointed to by the cube bF0 = Extra_bddNodePointedByCube( dd, bF, pbCube0[iForm] ); bF1 = Extra_bddNodePointedByCube( dd, bF, pbCube1[iForm] ); // call recursively for these nodes bRes0 = Extra_dsdRemap( dd, bF0, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes0 ); bRes1 = Extra_dsdRemap( dd, bF1, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes1 ); // derive the result using ITE bRes = Cudd_bddIte( dd, dd->vars[ pForm2Var[iForm] ], bRes1, bRes0 ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bRes1 ); // add to the hash table if ( bFR->ref != 1 ) st__insert( pCache, (char *)bF, (char *)bRes ); Cudd_Deref( bRes ); return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ) { DdNode * bFR, * bCR; DdNode * bF0, * bF1; DdNode * bC0, * bC1; int LevelF, LevelC; assert( bC != b0 ); if ( bC == b1 ) return bF; // bRes = cuddCacheLookup2( dd, Extra_bddNodePointedByCube, bF, bC ); // if ( bRes ) // return bRes; // there is no need for caching because this operation is very fast // there will no gain reusing the results of this operations // instead, it will flush CUDD cache of other useful entries bFR = Cudd_Regular( bF ); bCR = Cudd_Regular( bC ); assert( !cuddIsConstant( bFR ) ); LevelF = dd->perm[bFR->index]; LevelC = dd->perm[bCR->index]; if ( LevelF <= LevelC ) { if ( bFR != bF ) { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } } else { bF0 = bF1 = bF; } if ( LevelC <= LevelF ) { if ( bCR != bC ) { bC0 = Cudd_Not( cuddE(bCR) ); bC1 = Cudd_Not( cuddT(bCR) ); } else { bC0 = cuddE(bCR); bC1 = cuddT(bCR); } } else { bC0 = bC1 = bC; } assert( bC0 == b0 || bC1 == b0 ); if ( bC0 == b0 ) return Extra_bddNodePointedByCube( dd, bF1, bC1 ); return Extra_bddNodePointedByCube( dd, bF0, bC0 ); } #if 0 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) { DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; int i; int fAllBuffs = 1; static int Permute[MAXINPUTS]; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->Type == DT_PRIME ); // transform the function of this block to depend on inputs // corresponding to the formal inputs // first, substitute those inputs that have some blocks associated with them // second, remap the inputs to the top of the manager (then, it is easy to output them) // start the function bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); // go over all primary inputs for ( i = 0; i < pNode->nDecs; i++ ) if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer { bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); Cudd_RecursiveDeref( dd, bCube0 ); bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); Cudd_RecursiveDeref( dd, bCube1 ); Cudd_RecursiveDeref( dd, bNewFunc ); // use the variable in the i-th level of the manager // bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); // use the first variale in the support of the component bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); } if ( fRemap ) { // remap the function to the top of the manager // remap the function to the first variables of the manager for ( i = 0; i < pNode->nDecs; i++ ) // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; Permute[ pNode->pDecs[i]->S->index ] = i; bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bNewFunc ); return bNewFunc; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/dsdMan.c000066400000000000000000000100531300674244400227100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dsdMan.c] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [APIs of the DSD manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsdMan.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dsdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// API OF DSD MANAGER /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the DSD manager.] Description [Takes the started BDD manager and the maximum support size of the function to be DSD-decomposed. The manager should have at least as many variables as there are variables in the support. The functions should be expressed using the first nSuppSizeMax variables in the manager (these may be ordered not necessarily on top of the manager).] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ) { Dsd_Manager_t * dMan; Dsd_Node_t * pNode; int i; assert( nSuppMax <= dd->size ); dMan = ABC_ALLOC( Dsd_Manager_t, 1 ); memset( dMan, 0, sizeof(Dsd_Manager_t) ); dMan->dd = dd; dMan->nInputs = nSuppMax; dMan->fVerbose = fVerbose; dMan->nRoots = 0; dMan->nRootsAlloc = 50; dMan->pRoots = (Dsd_Node_t **) ABC_ALLOC( char, dMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); dMan->pInputs = (Dsd_Node_t **) ABC_ALLOC( char, dMan->nInputs * sizeof(Dsd_Node_t *) ); // create the primary inputs and insert them into the table dMan->Table = st__init_table( st__ptrcmp, st__ptrhash); for ( i = 0; i < dMan->nInputs; i++ ) { pNode = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, 0 ); pNode->G = dd->vars[i]; Cudd_Ref( pNode->G ); pNode->S = dd->vars[i]; Cudd_Ref( pNode->S ); st__insert( dMan->Table, (char*)dd->vars[i], (char*)pNode ); dMan->pInputs[i] = pNode; } pNode = Dsd_TreeNodeCreate( DSD_NODE_CONST1, 0, 0 ); pNode->G = b1; Cudd_Ref( pNode->G ); pNode->S = b1; Cudd_Ref( pNode->S ); st__insert( dMan->Table, (char*)b1, (char*)pNode ); dMan->pConst1 = pNode; Dsd_CheckCacheAllocate( 5000 ); return dMan; } /**Function************************************************************* Synopsis [Stops the DSD manager.] Description [Stopping the DSD manager automatically derefereces and deallocates all the DSD nodes that were created during the life time of the DSD manager. As a result, the user does not need to deref or deallocate any DSD nodes or trees that are derived and placed in the manager while it exists.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_ManagerStop( Dsd_Manager_t * dMan ) { st__generator * gen; Dsd_Node_t * pNode; DdNode * bFunc; // delete the nodes st__foreach_item( dMan->Table, gen, (const char**)&bFunc, (char**)&pNode ) Dsd_TreeNodeDelete( dMan->dd, Dsd_Regular(pNode) ); st__free_table(dMan->Table); ABC_FREE( dMan->pInputs ); ABC_FREE( dMan->pRoots ); ABC_FREE( dMan ); Dsd_CheckCacheDeallocate(); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/dsdProc.c000066400000000000000000001760171300674244400231150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dsdProc.c] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [The core procedures of the package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsdProc.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dsdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the most important procedures void dsdKernelDecompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ); static Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * F ); // additional procedures static Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ); static int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ); static void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ); static int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ); // list copying static void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ); static void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int Skipped ); // debugging procedures static int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ); //////////////////////////////////////////////////////////////////////// /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// // the counter of marks static int s_Mark; // debugging flag //static int s_Show = 0; // temporary var used for debugging static int Depth = 0; static int s_Loops1; static int s_Loops2; static int s_Loops3; static int s_Common; static int s_CommonNo; static int s_Case4Calls; static int s_Case4CallsSpecial; //static int s_Case5; //static int s_Loops2Useless; // statistical variables static int s_nDecBlocks; static int s_nLiterals; static int s_nExorGates; static int s_nReusedBlocks; static int s_nCascades; static int s_nPrimeBlocks; static int HashSuccess = 0; static int HashFailure = 0; static int s_CacheEntries; //////////////////////////////////////////////////////////////////////// /// DECOMPOSITION FUNCTIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs DSD for the array of functions represented by BDDs.] Description [This function takes the DSD manager, which should be previously allocated by the call to Dsd_ManagerStart(). The resulting DSD tree is stored in the DSD manager (pDsdMan->pRoots, pDsdMan->nRoots). Access to the tree is through the APIs of the manager. The resulting tree is a shared DSD DAG for the functions given in the array. For one function the resulting DAG is always a tree. The root node pointers can be complemented, as discussed in the literature referred to in "dsd.h". This procedure can be called repeatedly for different functions. There is no need to remove the decomposition tree after it is returned, because the next call to the DSD manager will "recycle" the tree. The user should not modify or dereference any data associated with the nodes of the DSD trees (the user can only change the contents of a temporary mark associated with each node by the calling to Dsd_NodeSetMark()). All the decomposition trees and intermediate nodes will be removed when the DSD manager is deallocated at the end by calling Dsd_ManagerStop().] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_Decompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ) { DdManager * dd = pDsdMan->dd; int i; abctime clk; Dsd_Node_t * pTemp; int SumMaxGateSize = 0; int nDecOutputs = 0; int nCBFOutputs = 0; /* s_Loops1 = 0; s_Loops2 = 0; s_Loops3 = 0; s_Case4Calls = 0; s_Case4CallsSpecial = 0; s_Case5 = 0; s_Loops2Useless = 0; */ // resize the number of roots in the manager if ( pDsdMan->nRootsAlloc < nFuncs ) { if ( pDsdMan->nRootsAlloc > 0 ) ABC_FREE( pDsdMan->pRoots ); pDsdMan->nRootsAlloc = nFuncs; pDsdMan->pRoots = (Dsd_Node_t **) ABC_ALLOC( char, pDsdMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); } if ( pDsdMan->fVerbose ) printf( "\nDecomposability statistics for individual outputs:\n" ); // set the counter of decomposition nodes s_nDecBlocks = 0; // perform decomposition for all outputs clk = Abc_Clock(); pDsdMan->nRoots = 0; s_nCascades = 0; for ( i = 0; i < nFuncs; i++ ) { int nLiteralsPrev; int nDecBlocksPrev; int nExorGatesPrev; int nReusedBlocksPres; int nCascades; int MaxBlock; int nPrimeBlocks; abctime clk; clk = Abc_Clock(); nLiteralsPrev = s_nLiterals; nDecBlocksPrev = s_nDecBlocks; nExorGatesPrev = s_nExorGates; nReusedBlocksPres = s_nReusedBlocks; nPrimeBlocks = s_nPrimeBlocks; pDsdMan->pRoots[ pDsdMan->nRoots++ ] = dsdKernelDecompose_rec( pDsdMan, pbFuncs[i] ); Dsd_TreeNodeGetInfoOne( pDsdMan->pRoots[i], &nCascades, &MaxBlock ); s_nCascades = ddMax( s_nCascades, nCascades ); pTemp = Dsd_Regular(pDsdMan->pRoots[i]); if ( pTemp->Type != DSD_NODE_PRIME || pTemp->nDecs != Extra_bddSuppSize(dd,pTemp->S) ) nDecOutputs++; if ( MaxBlock < 3 ) nCBFOutputs++; SumMaxGateSize += MaxBlock; if ( pDsdMan->fVerbose ) { printf("#%02d: ", i ); printf("Ins=%2d. ", Cudd_SupportSize(dd,pbFuncs[i]) ); printf("Gts=%3d. ", Dsd_TreeCountNonTerminalNodesOne( pDsdMan->pRoots[i] ) ); printf("Pri=%3d. ", Dsd_TreeCountPrimeNodesOne( pDsdMan->pRoots[i] ) ); printf("Max=%3d. ", MaxBlock ); printf("Reuse=%2d. ", s_nReusedBlocks-nReusedBlocksPres ); printf("Csc=%2d. ", nCascades ); printf("T= %.2f s. ", (float)(Abc_Clock()-clk)/(float)(CLOCKS_PER_SEC) ) ; printf("Bdd=%2d. ", Cudd_DagSize(pbFuncs[i]) ); printf("\n"); fflush( stdout ); } } assert( pDsdMan->nRoots == nFuncs ); if ( pDsdMan->fVerbose ) { printf( "\n" ); printf( "The cumulative decomposability statistics:\n" ); printf( " Total outputs = %5d\n", nFuncs ); printf( " Decomposable outputs = %5d\n", nDecOutputs ); printf( " Completely decomposable outputs = %5d\n", nCBFOutputs ); printf( " The sum of max gate sizes = %5d\n", SumMaxGateSize ); printf( " Shared BDD size = %5d\n", Cudd_SharingSize( pbFuncs, nFuncs ) ); printf( " Decomposition entries = %5d\n", st__count( pDsdMan->Table ) ); printf( " Pure decomposition time = %.2f sec\n", (float)(Abc_Clock() - clk)/(float)(CLOCKS_PER_SEC) ); } /* printf( "s_Loops1 = %d.\n", s_Loops1 ); printf( "s_Loops2 = %d.\n", s_Loops2 ); printf( "s_Loops3 = %d.\n", s_Loops3 ); printf( "s_Case4Calls = %d.\n", s_Case4Calls ); printf( "s_Case4CallsSpecial = %d.\n", s_Case4CallsSpecial ); printf( "s_Case5 = %d.\n", s_Case5 ); printf( "s_Loops2Useless = %d.\n", s_Loops2Useless ); */ } /**Function************************************************************* Synopsis [Performs decomposition for one function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ) { return dsdKernelDecompose_rec( pDsdMan, bFunc ); } /**Function************************************************************* Synopsis [The main function of this module. Recursive implementation of DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * bFunc0 ) { DdManager * dd = pDsdMan->dd; DdNode * bLow; DdNode * bLowR; DdNode * bHigh; int VarInt; DdNode * bVarCur; Dsd_Node_t * pVarCurDE; // works only if var indices start from 0!!! DdNode * bSuppNew = NULL, * bTemp; int fContained; int nSuppLH; int nSuppL; int nSuppH; // various decomposition nodes Dsd_Node_t * pThis, * pL, * pH, * pLR, * pHR; Dsd_Node_t * pSmallR, * pLargeR; Dsd_Node_t * pTableEntry; // treat the complemented case DdNode * bF = Cudd_Regular(bFunc0); int fCompF = (int)(bF != bFunc0); // check cache if ( st__lookup( pDsdMan->Table, (char*)bF, (char**)&pTableEntry ) ) { // the entry is present HashSuccess++; return Dsd_NotCond( pTableEntry, fCompF ); } HashFailure++; Depth++; // proceed to consider "four cases" ////////////////////////////////////////////////////////////////////// // TERMINAL CASES - CASES 1 and 2 ////////////////////////////////////////////////////////////////////// bLow = cuddE(bF); bLowR = Cudd_Regular(bLow); bHigh = cuddT(bF); VarInt = bF->index; bVarCur = dd->vars[VarInt]; pVarCurDE = pDsdMan->pInputs[VarInt]; // works only if var indices start from 0!!! bSuppNew = NULL; if ( bLowR->index == CUDD_CONST_INDEX || bHigh->index == CUDD_CONST_INDEX ) { // one of the cofactors in the constant if ( bHigh == b1 ) // bHigh cannot be equal to b0, because then it will be complemented if ( bLow == b0 ) // bLow cannot be equal to b1, because then the node will have bLow == bHigh ///////////////////////////////////////////////////////////////// // bLow == 0, bHigh == 1, F = x'&0 + x&1 = x ///////////////////////////////////////////////////////////////// { // create the elementary variable node assert(0); // should be already in the hash table pThis = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, s_nDecBlocks++ ); pThis->pDecs[0] = NULL; } else // if ( bLow != constant ) ///////////////////////////////////////////////////////////////// // bLow != const, bHigh == 1, F = x'&bLow + x&1 = bLow + x --- DSD_NODE_OR(x,bLow) ///////////////////////////////////////////////////////////////// { pL = dsdKernelDecompose_rec( pDsdMan, bLow ); pLR = Dsd_Regular( pL ); bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); if ( pLR->Type == DSD_NODE_OR && pL == pLR ) // OR and no complement { // add to the components pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pL->nDecs+1, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, pVarCurDE, pL->pDecs, pL->nDecs ); } else // all other cases { // create a new 2-input OR-gate pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); } } else // if ( bHigh != const ) // meaning that bLow should be a constant { pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); pHR = Dsd_Regular( pH ); bSuppNew = Cudd_bddAnd( dd, bVarCur, pHR->S ); Cudd_Ref(bSuppNew); if ( bLow == b0 ) ///////////////////////////////////////////////////////////////// // Low == 0, High != 1, F = x'&0+x&High = (x'+High')'--- NOR(x',High') ///////////////////////////////////////////////////////////////// if ( pHR->Type == DSD_NODE_OR && pH != pHR ) // DSD_NODE_OR and complement { // add to the components pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pHR->nDecs+1, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pHR->pDecs, pHR->nDecs ); pThis = Dsd_Not(pThis); } else // all other cases { // create a new 2-input NOR gate pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); pH = Dsd_Not(pH); dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); pThis = Dsd_Not(pThis); } else // if ( bLow == b1 ) ///////////////////////////////////////////////////////////////// // Low == 1, High != 1, F = x'&1 + x&High = x' + High --- DSD_NODE_OR(x',High) ///////////////////////////////////////////////////////////////// if ( pHR->Type == DSD_NODE_OR && pH == pHR ) // OR and no complement { // add to the components pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pH->nDecs+1, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pH->pDecs, pH->nDecs ); } else // all other cases { // create a new 2-input OR-gate pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); } } goto EXIT; } // else if ( bLow != const && bHigh != const ) // the case of equal cofactors (up to complementation) if ( bLowR == bHigh ) ///////////////////////////////////////////////////////////////// // Low == G, High == G', F = x'&G + x&G' = (x(+)G) --- EXOR(x,Low) ///////////////////////////////////////////////////////////////// { pL = dsdKernelDecompose_rec( pDsdMan, bLow ); pLR = Dsd_Regular( pL ); bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); if ( pLR->Type == DSD_NODE_EXOR ) // complemented or not - does not matter! { // add to the components pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, pLR->nDecs+1, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, pVarCurDE, pLR->pDecs, pLR->nDecs ); if ( pL != pLR ) pThis = Dsd_Not( pThis ); } else // all other cases { // create a new 2-input EXOR-gate pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); if ( pL != pLR ) // complemented { dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pLR, 1 ); pThis = Dsd_Not( pThis ); } else // non-complemented dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); } goto EXIT; } ////////////////////////////////////////////////////////////////////// // solve subproblems ////////////////////////////////////////////////////////////////////// pL = dsdKernelDecompose_rec( pDsdMan, bLow ); pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); pLR = Dsd_Regular( pL ); pHR = Dsd_Regular( pH ); assert( pLR->Type == DSD_NODE_BUF || pLR->Type == DSD_NODE_OR || pLR->Type == DSD_NODE_EXOR || pLR->Type == DSD_NODE_PRIME ); assert( pHR->Type == DSD_NODE_BUF || pHR->Type == DSD_NODE_OR || pHR->Type == DSD_NODE_EXOR || pHR->Type == DSD_NODE_PRIME ); /* if ( Depth == 1 ) { // PRK(bLow,pDecTreeTotal->nInputs); // PRK(bHigh,pDecTreeTotal->nInputs); if ( s_Show ) { PRD( pL ); PRD( pH ); } } */ // compute the new support bTemp = Cudd_bddAnd( dd, pLR->S, pHR->S ); Cudd_Ref( bTemp ); nSuppL = Extra_bddSuppSize( dd, pLR->S ); nSuppH = Extra_bddSuppSize( dd, pHR->S ); nSuppLH = Extra_bddSuppSize( dd, bTemp ); bSuppNew = Cudd_bddAnd( dd, bTemp, bVarCur ); Cudd_Ref( bSuppNew ); Cudd_RecursiveDeref( dd, bTemp ); // several possibilities are possible // (1) support of one component contains another // (2) none of the supports is contained in another fContained = dsdKernelCheckContainment( pDsdMan, pLR, pHR, &pLargeR, &pSmallR ); ////////////////////////////////////////////////////////////////////// // CASE 3.b One of the cofactors in a constant (OR and EXOR) ////////////////////////////////////////////////////////////////////// // the support of the larger component should contain the support of the smaller // it is possible to have PRIME function in this role // for example: F = ITE( a+b, c(+)d, e+f ), F0 = ITE( b, c(+)d, e+f ), F1 = c(+)d if ( fContained ) { Dsd_Node_t * pSmall, * pLarge; int c, iCompLarge = -1; // the number of the component is Large is equal to the whole of Small; suppress "might be used uninitialized" int fLowIsLarge; DdNode * bFTemp; // the changed input function Dsd_Node_t * pDETemp, * pDENew; Dsd_Node_t * pComp = NULL; int nComp = -1; // Suppress "might be used uninitialized" if ( pSmallR == pLR ) { // Low is Small => High is Large pSmall = pL; pLarge = pH; fLowIsLarge = 0; } else { // vice versa pSmall = pH; pLarge = pL; fLowIsLarge = 1; } // treat the situation when the larger is PRIME if ( pLargeR->Type == DSD_NODE_PRIME ) //&& pLargeR->nDecs != pSmallR->nDecs ) { // QUESTION: Is it possible for pLargeR->nDecs > 3 // and pSmall contained as one of input in pLarge? // Yes, for example F = a'c + a & MUX(b,c',d) = a'c + abc' + ab'd is non-decomposable // Consider the function H(a->xy) = F( xy, b, c, d ) // H0 = H(x=0) = F(0,b,c,d) = c // H1 = F(x=1) = F(y,b,c,d) - non-decomposable // // QUESTION: Is it possible that pLarge is PRIME(3) and pSmall is OR(2), // which is not contained in PRIME as one input? // Yes, for example F = abcd + b'c'd' + a'c'd' = PRIME(ab, c, d) // F(a=0) = c'd' = NOT(OR(a,d)) F(a=1) = bcd + b'c'd' = PRIME(b,c,d) // To find decomposition, we have to prove that F(a=1)|b=0 = F(a=0) // Is it possible that (pLargeR->nDecs == pSmallR->nDecs) and yet this case holds? // Yes, consider the function such that F(a=0) = PRIME(a,b+c,d,e) and F(a=1) = OR(b,c,d,e) // They have the same number of inputs and it is possible that they will be the cofactors // as discribed in the previous example. // find the component, which when substituted for 0 or 1, produces the desired result int g, fFoundComp = -1; // {0,1} depending on whether setting cofactor to 0 or 1 worked out; suppress "might be used uninitialized" DdNode * bLarge, * bSmall; if ( fLowIsLarge ) { bLarge = bLow; bSmall = bHigh; } else { bLarge = bHigh; bSmall = bLow; } for ( g = 0; g < pLargeR->nDecs; g++ ) // if ( g != c ) { pDETemp = pLargeR->pDecs[g]; // cannot be complemented if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, pDETemp->G, b1 ) ) { fFoundComp = 1; break; } s_Loops1++; if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, Cudd_Not(pDETemp->G), b1 ) ) { fFoundComp = 0; break; } s_Loops1++; } if ( g != pLargeR->nDecs ) { // decomposition is found if ( fFoundComp ) if ( fLowIsLarge ) bFTemp = Cudd_bddOr( dd, bVarCur, pLargeR->pDecs[g]->G ); else bFTemp = Cudd_bddOr( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); else if ( fLowIsLarge ) bFTemp = Cudd_bddAnd( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); else bFTemp = Cudd_bddAnd( dd, bVarCur, pLargeR->pDecs[g]->G ); Cudd_Ref( bFTemp ); pDENew = dsdKernelDecompose_rec( pDsdMan, bFTemp ); pDENew = Dsd_Regular( pDENew ); Cudd_RecursiveDeref( dd, bFTemp ); // get the new gate pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLargeR->nDecs, s_nDecBlocks++ ); dsdKernelCopyListPlusOneMinusOne( pThis, pDENew, pLargeR->pDecs, pLargeR->nDecs, g ); goto EXIT; } } // try to find one component in the pLarger that is equal to the whole of pSmaller for ( c = 0; c < pLargeR->nDecs; c++ ) if ( pLargeR->pDecs[c] == pSmall || pLargeR->pDecs[c] == Dsd_Not(pSmall) ) { iCompLarge = c; break; } // assign the equal component if ( c != pLargeR->nDecs ) // the decomposition is possible! { pComp = pLargeR->pDecs[iCompLarge]; nComp = 1; } else // the decomposition is still possible { // for example F = OR(ab,c,d), F(a=0) = OR(c,d), F(a=1) = OR(b,c,d) // supp(F0) is contained in supp(F1), Polarity(F(a=0)) == Polarity(F(a=1)) // try to find a group of common components if ( pLargeR->Type == pSmallR->Type && (pLargeR->Type == DSD_NODE_EXOR || (pSmallR->Type == DSD_NODE_OR && ((pLarge==pLargeR) == (pSmall==pSmallR)))) ) { Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLargeR, pSmallR, &pCommon, &pLastDiffL, &pLastDiffH ); // if all the components of pSmall are contained in pLarge, // then the decomposition exists if ( nCommon == pSmallR->nDecs ) { pComp = pSmallR; nComp = pSmallR->nDecs; } } } if ( pComp ) // the decomposition is possible! { // Dsd_Node_t * pComp = pLargeR->pDecs[iCompLarge]; Dsd_Node_t * pCompR = Dsd_Regular( pComp ); int fComp1 = (int)( pLarge != pLargeR ); int fComp2 = (int)( pComp != pCompR ); int fComp3 = (int)( pSmall != pSmallR ); DdNode * bFuncComp; // the function of the given component DdNode * bFuncNew; // the function of the input component if ( pLargeR->Type == DSD_NODE_OR ) // Figure 4 of Matsunaga's paper { // the decomposition exists only if the polarity assignment // along the paths is the same if ( (fComp1 ^ fComp2) == fComp3 ) { // decomposition exists = consider 4 cases // consideration of cases leads to the following conclusion // fComp1 gives the polarity of the resulting DSD_NODE_OR gate // fComp2 gives the polarity of the common component feeding into the DSD_NODE_OR gate // // | fComp1 pL/ |pS // <> .........<=>....... <> | // | / | // [OR] [OR] | fComp3 // / \ fComp2 / | \ | // <> <> .......<=>... /..|..<> | // / \ / | \| // [OR] [C] S1 S2 C // / \ . // <> \ . // / \ . // [OR] [x] . // / \ . // S1 S2 . // // at this point we have the function F (bFTemp) and the common component C (bFuncComp) // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 // we compute the following R = Exist( F - C, supp(C) ) bFTemp = (fComp1)? Cudd_Not( bF ): bF; bFuncComp = (fComp2)? Cudd_Not( pCompR->G ): pCompR->G; bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bFuncComp), pCompR->S ); Cudd_Ref( bFuncNew ); // there is no need to copy the dec entry list first, because pComp is a component // which will not be destroyed by the recursive call to decomposition pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); assert( Dsd_IsComplement(pDENew) ); // follows from the consideration of cases Cudd_RecursiveDeref( dd, bFuncNew ); // get the new gate if ( nComp == 1 ) { pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); pThis->pDecs[0] = pDENew; pThis->pDecs[1] = pComp; // takes the complement } else { // pComp is not complemented pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nComp+1, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); } if ( fComp1 ) pThis = Dsd_Not( pThis ); goto EXIT; } } else if ( pLargeR->Type == DSD_NODE_EXOR ) // Figure 5 of Matsunaga's paper (with correction) { // decomposition always exists = consider 4 cases // consideration of cases leads to the following conclusion // fComp3 gives the COMPLEMENT of the polarity of the resulting EXOR gate // (if fComp3 is 0, the EXOR gate is complemented, and vice versa) // // | fComp1 pL/ |pS // <> .........<=>....... /....| fComp3 // | / | // [XOR] [XOR] | // / \ fComp2==0 / | \ | // / \ / | \ | // / \ / | \| // [OR] [C] S1 S2 C // / \ . // <> \ . // / \ . // [XOR] [x] . // / \ . // S1 S2 . // assert( fComp2 == 0 ); // find the functionality of the lower gates bFTemp = (fComp3)? bF: Cudd_Not( bF ); bFuncNew = Cudd_bddXor( dd, bFTemp, pComp->G ); Cudd_Ref( bFuncNew ); pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases Cudd_RecursiveDeref( dd, bFuncNew ); // get the new gate if ( nComp == 1 ) { pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); pThis->pDecs[0] = pDENew; pThis->pDecs[1] = pComp; } else { // pComp is not complemented pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nComp+1, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); } if ( !fComp3 ) pThis = Dsd_Not( pThis ); goto EXIT; } } } // this case was added to fix the trivial bug found November 4, 2002 in Japan // by running the example provided by T. Sasao if ( nSuppLH == nSuppL + nSuppH ) // the supports of the components are disjoint { // create a new component of the type ITE( a, pH, pL ) pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, 3, s_nDecBlocks++ ); if ( dd->perm[pLR->S->index] < dd->perm[pHR->S->index] ) // pLR is higher in the varible order { pThis->pDecs[1] = pLR; pThis->pDecs[2] = pHR; } else // pHR is higher in the varible order { pThis->pDecs[1] = pHR; pThis->pDecs[2] = pLR; } // add the first component pThis->pDecs[0] = pVarCurDE; goto EXIT; } ////////////////////////////////////////////////////////////////////// // CASE 3.a Neither of the cofactors is a constant (OR, EXOR, PRIME) ////////////////////////////////////////////////////////////////////// // the component types are identical // and if they are OR, they are either both complemented or both not complemented // and if they are PRIME, their dec numbers should be the same if ( pLR->Type == pHR->Type && pLR->Type != DSD_NODE_BUF && (pLR->Type != DSD_NODE_OR || ( (pL == pLR && pH == pHR) || (pL != pLR && pH != pHR) ) ) && (pLR->Type != DSD_NODE_PRIME || pLR->nDecs == pHR->nDecs) ) { // array to store common comps in pL and pH Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLR, pHR, &pCommon, &pLastDiffL, &pLastDiffH ); if ( nCommon ) { if ( pLR->Type == DSD_NODE_OR ) // Figure 2 of Matsunaga's paper { // at this point we have the function F and the group of common components C // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 // we compute the following R = Exist( F - C, supp(C) ) // compute the sum total of the common components and the union of their supports DdNode * bCommF, * bCommS, * bFTemp, * bFuncNew; Dsd_Node_t * pDENew; dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, &bCommS, 0 ); Cudd_Ref( bCommF ); Cudd_Ref( bCommS ); bFTemp = ( pL != pLR )? Cudd_Not(bF): bF; bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bCommF), bCommS ); Cudd_Ref( bFuncNew ); Cudd_RecursiveDeref( dd, bCommF ); Cudd_RecursiveDeref( dd, bCommS ); // get the new gate // copy the components first, then call the decomposition // because decomposition will distroy the list used for copying pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nCommon + 1, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); // call the decomposition recursively pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); // assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases Cudd_RecursiveDeref( dd, bFuncNew ); // add the first component pThis->pDecs[0] = pDENew; if ( pL != pLR ) pThis = Dsd_Not( pThis ); goto EXIT; } else if ( pLR->Type == DSD_NODE_EXOR ) // Figure 3 of Matsunaga's paper { // compute the sum total of the common components and the union of their supports DdNode * bCommF, * bFuncNew; Dsd_Node_t * pDENew; int fCompExor; dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, 1 ); Cudd_Ref( bCommF ); bFuncNew = Cudd_bddXor( dd, bF, bCommF ); Cudd_Ref( bFuncNew ); Cudd_RecursiveDeref( dd, bCommF ); // get the new gate // copy the components first, then call the decomposition // because decomposition will distroy the list used for copying pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nCommon + 1, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); // call the decomposition recursively pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); Cudd_RecursiveDeref( dd, bFuncNew ); // remember the fact that it was complemented fCompExor = Dsd_IsComplement(pDENew); pDENew = Dsd_Regular(pDENew); // add the first component pThis->pDecs[0] = pDENew; if ( fCompExor ) pThis = Dsd_Not( pThis ); goto EXIT; } else if ( pLR->Type == DSD_NODE_PRIME && (nCommon == pLR->nDecs-1 || nCommon == pLR->nDecs) ) { // for example the function F(a,b,c,d) = ITE(b,c,a(+)d) produces // two cofactors F(a=0) = PRIME(b,c,d) and F(a=1) = PRIME(b,c,d) // with exactly the same list of common components Dsd_Node_t * pDENew; DdNode * bFuncNew; int fCompComp = 0; // this flag can be {0,1,2} // if it is 0 there is no identity // if it is 1/2, the cofactored functions are equal in the direct/complemented polarity if ( nCommon == pLR->nDecs ) { // all the components are the same // find the formal input, in which pLow and pHigh differ (if such input exists) int m; Dsd_Node_t * pTempL, * pTempH; s_Common++; for ( m = 0; m < pLR->nDecs; m++ ) { pTempL = pLR->pDecs[m]; // cannot be complemented pTempH = pHR->pDecs[m]; // cannot be complemented if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pTempL->G, Cudd_Not(pTempH->G) ) && Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pTempL->G), pTempH->G ) ) { pLastDiffL = pTempL; pLastDiffH = pTempH; assert( pLastDiffL == pLastDiffH ); fCompComp = 2; break; } s_Loops2++; s_Loops2++; /* if ( s_Loops2 % 10000 == 0 ) { int i; for ( i = 0; i < pLR->nDecs; i++ ) printf( " %d(s=%d)", pLR->pDecs[i]->Type, Extra_bddSuppSize(dd, pLR->pDecs[i]->S) ); printf( "\n" ); } */ } // if ( pLR->nDecs == Extra_bddSuppSize(dd, pLR->S) ) // s_Loops2Useless += pLR->nDecs * 2; if ( fCompComp ) { // put the equal components into pCommon, so that they could be copied into the new dec entry nCommon = 0; for ( m = 0; m < pLR->nDecs; m++ ) if ( pLR->pDecs[m] != pLastDiffL ) pCommon[nCommon++] = pLR->pDecs[m]; assert( nCommon = pLR->nDecs-1 ); } } else { // the differing components are known - check that they have compatible PRIME function s_CommonNo++; // find the numbers of different components assert( pLastDiffL ); assert( pLastDiffH ); // also, they cannot be complemented, because the decomposition type is PRIME if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), Cudd_Not(pLastDiffH->G) ) && Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, pLastDiffH->G ) ) fCompComp = 1; else if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, Cudd_Not(pLastDiffH->G) ) && Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), pLastDiffH->G ) ) fCompComp = 2; s_Loops3 += 4; } if ( fCompComp ) { if ( fCompComp == 1 ) // it is true that bLow(G=0) == bHigh(H=0) && bLow(G=1) == bHigh(H=1) bFuncNew = Cudd_bddIte( dd, bVarCur, pLastDiffH->G, pLastDiffL->G ); else // it is true that bLow(G=0) == bHigh(H=1) && bLow(G=1) == bHigh(H=0) bFuncNew = Cudd_bddIte( dd, bVarCur, Cudd_Not(pLastDiffH->G), pLastDiffL->G ); Cudd_Ref( bFuncNew ); // get the new gate // copy the components first, then call the decomposition // because decomposition will distroy the list used for copying pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLR->nDecs, s_nDecBlocks++ ); dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); // create a new component pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); Cudd_RecursiveDeref( dd, bFuncNew ); // the BDD of the argument function in PRIME decomposition, should be regular pDENew = Dsd_Regular(pDENew); // add the first component pThis->pDecs[0] = pDENew; goto EXIT; } } // end of PRIME type } // end of existing common components } // end of CASE 3.a // if ( Depth != 1) // { //CASE4: ////////////////////////////////////////////////////////////////////// // CASE 4 ////////////////////////////////////////////////////////////////////// { // estimate the number of entries in the list int nEntriesMax = pDsdMan->nInputs - dd->perm[VarInt]; // create the new decomposition entry int nEntries = 0; DdNode * SuppL, * SuppH, * SuppL_init, * SuppH_init; Dsd_Node_t *pHigher = NULL; // Suppress "might be used uninitialized" Dsd_Node_t *pLower, * pTemp, * pDENew; int levTopSuppL; int levTopSuppH; int levTop; pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, nEntriesMax, s_nDecBlocks++ ); pThis->pDecs[ nEntries++ ] = pVarCurDE; // other entries will be added to this list one-by-one during analysis // count how many times does it happen that the decomposition entries are s_Case4Calls++; // consider the simplest case: when the supports are equal // and at least one of the components // is the PRIME without decompositions, or // when both of them are without decomposition if ( (((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) || (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) && pLR->S == pHR->S) || ((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) && (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) ) { s_Case4CallsSpecial++; // walk through both supports and create the decomposition list composed of simple entries SuppL = pLR->S; SuppH = pHR->S; do { // determine levels levTopSuppL = cuddI(dd,SuppL->index); levTopSuppH = cuddI(dd,SuppH->index); // skip the topmost variable in both supports if ( levTopSuppL <= levTopSuppH ) { levTop = levTopSuppL; SuppL = cuddT(SuppL); } else levTop = levTopSuppH; if ( levTopSuppH <= levTopSuppL ) SuppH = cuddT(SuppH); // set the new decomposition entry pThis->pDecs[ nEntries++ ] = pDsdMan->pInputs[ dd->invperm[levTop] ]; } while ( SuppL != b1 || SuppH != b1 ); } else { // compare two different decomposition lists SuppL_init = pLR->S; SuppH_init = pHR->S; // start references (because these supports will change) SuppL = pLR->S; Cudd_Ref( SuppL ); SuppH = pHR->S; Cudd_Ref( SuppH ); while ( SuppL != b1 || SuppH != b1 ) { // determine the top level in cofactors and // whether they have the same top level int TopLevL = cuddI(dd,SuppL->index); int TopLevH = cuddI(dd,SuppH->index); int TopLevel = TopLevH; int fEqualLevel = 0; DdNode * bVarTop; DdNode * bSuppSubract; if ( TopLevL < TopLevH ) { pHigher = pLR; pLower = pHR; TopLevel = TopLevL; } else if ( TopLevL > TopLevH ) { pHigher = pHR; pLower = pLR; } else fEqualLevel = 1; assert( TopLevel != CUDD_CONST_INDEX ); // find the currently top variable in the decomposition lists bVarTop = dd->vars[dd->invperm[TopLevel]]; if ( !fEqualLevel ) { // find the lower support DdNode * bSuppLower = (TopLevL < TopLevH)? SuppH_init: SuppL_init; // find the first component in pHigher // whose support does not overlap with supp(Lower) // and remember the previous component int fPolarity; Dsd_Node_t * pPrev = NULL; // the pointer to the component proceeding pCur Dsd_Node_t * pCur = pHigher; // the first component not contained in supp(Lower) while ( Extra_bddSuppOverlapping( dd, pCur->S, bSuppLower ) ) { // get the next component pPrev = pCur; pCur = dsdKernelFindContainingComponent( pDsdMan, pCur, bVarTop, &fPolarity ); }; // look for the possibility to subtract more than one component if ( pPrev == NULL || pPrev->Type == DSD_NODE_PRIME ) { // if there is no previous component, or if the previous component is PRIME // there is no way to subtract more than one component // add the new decomposition entry (it is already regular) pThis->pDecs[ nEntries++ ] = pCur; // assign the support to be subtracted from both components bSuppSubract = pCur->S; } else // all other types { // go through the decomposition list of pPrev and find components // whose support does not overlap with supp(Lower) static Dsd_Node_t * pNonOverlap[MAXINPUTS]; int i, nNonOverlap = 0; for ( i = 0; i < pPrev->nDecs; i++ ) { pTemp = Dsd_Regular( pPrev->pDecs[i] ); if ( !Extra_bddSuppOverlapping( dd, pTemp->S, bSuppLower ) ) pNonOverlap[ nNonOverlap++ ] = pPrev->pDecs[i]; } assert( nNonOverlap > 0 ); if ( nNonOverlap == 1 ) { // one one component was found, which is the original one assert( Dsd_Regular(pNonOverlap[0]) == pCur); // add the new decomposition entry pThis->pDecs[ nEntries++ ] = pCur; // assign the support to be subtracted from both components bSuppSubract = pCur->S; } else // more than one components was found { // find the OR (EXOR) of the non-overlapping components DdNode * bCommF; dsdKernelComputeSumOfComponents( pDsdMan, pNonOverlap, nNonOverlap, &bCommF, NULL, (int)(pPrev->Type==DSD_NODE_EXOR) ); Cudd_Ref( bCommF ); // create a new gated pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); Cudd_RecursiveDeref(dd, bCommF); // make it regular... it must be regular already assert( !Dsd_IsComplement(pDENew) ); // add the new decomposition entry pThis->pDecs[ nEntries++ ] = pDENew; // assign the support to be subtracted from both components bSuppSubract = pDENew->S; } } // subtract its support from the support of upper component if ( TopLevL < TopLevH ) { SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ); Cudd_Ref( SuppL ); Cudd_RecursiveDeref(dd, bTemp); } else { SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ); Cudd_Ref( SuppH ); Cudd_RecursiveDeref(dd, bTemp); } } // end of if ( !fEqualLevel ) else // if ( fEqualLevel ) -- they have the same top level var { static Dsd_Node_t * pMarkedLeft[MAXINPUTS]; // the pointers to the marked blocks static char pMarkedPols[MAXINPUTS]; // polarities of the marked blocks int nMarkedLeft = 0; int fPolarity = 0; Dsd_Node_t * pTempL = pLR; int fPolarityCurH = 0; Dsd_Node_t * pPrevH = NULL, * pCurH = pHR; int fPolarityCurL = 0; Dsd_Node_t * pPrevL = NULL, * pCurL = pLR; // = pMarkedLeft[0]; int index = 1; // set the new mark s_Mark++; // go over the dec list of pL, mark all components that contain the given variable assert( Extra_bddSuppContainVar( dd, pLR->S, bVarTop ) ); assert( Extra_bddSuppContainVar( dd, pHR->S, bVarTop ) ); do { pTempL->Mark = s_Mark; pMarkedLeft[ nMarkedLeft ] = pTempL; pMarkedPols[ nMarkedLeft ] = fPolarity; nMarkedLeft++; } while ( (pTempL = dsdKernelFindContainingComponent( pDsdMan, pTempL, bVarTop, &fPolarity )) ); // go over the dec list of pH, and find the component that is marked and the previos one // (such component always exists, because they have common variables) while ( pCurH->Mark != s_Mark ) { pPrevH = pCurH; pCurH = dsdKernelFindContainingComponent( pDsdMan, pCurH, bVarTop, &fPolarityCurH ); assert( pCurH ); } // go through the first list once again and find // the component proceeding the one marked found in the second list while ( pCurL != pCurH ) { pPrevL = pCurL; pCurL = pMarkedLeft[index]; fPolarityCurL = pMarkedPols[index]; index++; } // look for the possibility to subtract more than one component if ( !pPrevL || !pPrevH || pPrevL->Type != pPrevH->Type || pPrevL->Type == DSD_NODE_PRIME || fPolarityCurL != fPolarityCurH ) { // there is no way to extract more than one pThis->pDecs[ nEntries++ ] = pCurH; // assign the support to be subtracted from both components bSuppSubract = pCurH->S; } else { // find the equal components in two decomposition lists Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; int nCommon = dsdKernelFindCommonComponents( pDsdMan, pPrevL, pPrevH, &pCommon, &pLastDiffL, &pLastDiffH ); if ( nCommon == 0 || nCommon == 1 ) { // one one component was found, which is the original one // assert( Dsd_Regular(pCommon[0]) == pCurL); // add the new decomposition entry pThis->pDecs[ nEntries++ ] = pCurL; // assign the support to be subtracted from both components bSuppSubract = pCurL->S; } else // more than one components was found { // find the OR (EXOR) of the non-overlapping components DdNode * bCommF; dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, (int)(pPrevL->Type==DSD_NODE_EXOR) ); Cudd_Ref( bCommF ); pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); assert( !Dsd_IsComplement(pDENew) ); // cannot be complemented because of construction Cudd_RecursiveDeref( dd, bCommF ); // add the new decomposition entry pThis->pDecs[ nEntries++ ] = pDENew; // assign the support to be subtracted from both components bSuppSubract = pDENew->S; } } SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ), Cudd_Ref( SuppL ); Cudd_RecursiveDeref(dd, bTemp); SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ), Cudd_Ref( SuppH ); Cudd_RecursiveDeref(dd, bTemp); } // end of if ( fEqualLevel ) } // end of decomposition list comparison Cudd_RecursiveDeref( dd, SuppL ); Cudd_RecursiveDeref( dd, SuppH ); } // check that the estimation of the number of entries was okay assert( nEntries <= nEntriesMax ); // if ( nEntries != Extra_bddSuppSize(dd, bSuppNew) ) // s_Case5++; // update the number of entries in the new decomposition list pThis->nDecs = nEntries; } //} EXIT: { // if the component created is complemented, it represents a function without complement // therefore, as it is, without complement, it should recieve the complemented function Dsd_Node_t * pThisR = Dsd_Regular( pThis ); assert( pThisR->G == NULL ); assert( pThisR->S == NULL ); if ( pThisR == pThis ) // set regular function pThisR->G = bF; else // set complemented function pThisR->G = Cudd_Not(bF); Cudd_Ref(bF); // reference the function in the component assert( bSuppNew ); pThisR->S = bSuppNew; // takes the reference from the new support if ( st__insert( pDsdMan->Table, (char*)bF, (char*)pThis ) ) { assert( 0 ); } s_CacheEntries++; /* if ( dsdKernelVerifyDecomposition(dd, pThis) == 0 ) { // write the function, for which verification does not work cout << endl << "Internal verification failed!"" ); // create the variable mask static int s_pVarMask[MAXINPUTS]; int nInputCounter = 0; Cudd_SupportArray( dd, bF, s_pVarMask ); int k; for ( k = 0; k < dd->size; k++ ) if ( s_pVarMask[k] ) nInputCounter++; cout << endl << "The problem function is "" ); DdNode * zNewFunc = Cudd_zddIsopCover( dd, bF, bF ); Cudd_Ref( zNewFunc ); cuddWriteFunctionSop( stdout, dd, zNewFunc, -1, dd->size, "1", s_pVarMask ); Cudd_RecursiveDerefZdd( dd, zNewFunc ); } */ } Depth--; return Dsd_NotCond( pThis, fCompF ); } //////////////////////////////////////////////////////////////////////// /// OTHER FUNCTIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Finds the corresponding decomposition entry.] Description [This function returns the non-complemented pointer to the DecEntry of that component which contains the given variable in its support, or NULL if no such component exists] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ) { Dsd_Node_t * pTemp; int i; // assert( !Dsd_IsComplement( pWhere ) ); // assert( Extra_bddSuppContainVar( pDsdMan->dd, pWhere->S, Var ) ); if ( pWhere->nDecs == 1 ) return NULL; for( i = 0; i < pWhere->nDecs; i++ ) { pTemp = Dsd_Regular( pWhere->pDecs[i] ); if ( Extra_bddSuppContainVar( pDsdMan->dd, pTemp->S, Var ) ) { *fPolarity = (int)( pTemp != pWhere->pDecs[i] ); return pTemp; } } assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [Find the common decomposition components.] Description [This function determines the common components. It counts the number of common components in the decomposition lists of pL and pH and returns their number and the lists of common components. It assumes that pL and pH are regular pointers. It retuns also the pointers to the last different components encountered in pL and pH.] SideEffects [] SeeAlso [] ***********************************************************************/ int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ) { static Dsd_Node_t * Common[MAXINPUTS]; int nCommon = 0; // pointers to the current decomposition entries Dsd_Node_t * pLcur; Dsd_Node_t * pHcur; // the pointers to their supports DdNode * bSLcur; DdNode * bSHcur; // the top variable in the supports int TopVar; // the indices running through the components int iCurL = 0; int iCurH = 0; while ( iCurL < pL->nDecs && iCurH < pH->nDecs ) { // both did not run out pLcur = Dsd_Regular(pL->pDecs[iCurL]); pHcur = Dsd_Regular(pH->pDecs[iCurH]); bSLcur = pLcur->S; bSHcur = pHcur->S; // find out what component is higher in the BDD if ( pDsdMan->dd->perm[bSLcur->index] < pDsdMan->dd->perm[bSHcur->index] ) TopVar = bSLcur->index; else TopVar = bSHcur->index; if ( TopVar == bSLcur->index && TopVar == bSHcur->index ) { // the components may be equal - should match exactly! if ( pL->pDecs[iCurL] == pH->pDecs[iCurH] ) Common[nCommon++] = pL->pDecs[iCurL]; else { *pLastDiffL = pL->pDecs[iCurL]; *pLastDiffH = pH->pDecs[iCurH]; } // skip both iCurL++; iCurH++; } else if ( TopVar == bSLcur->index ) { // the components cannot be equal // skip the top-most one *pLastDiffL = pL->pDecs[iCurL++]; } else // if ( TopVar == bSHcur->index ) { // the components cannot be equal // skip the top-most one *pLastDiffH = pH->pDecs[iCurH++]; } } // if one of the lists still has components, write the first one down if ( iCurL < pL->nDecs ) *pLastDiffL = pL->pDecs[iCurL]; if ( iCurH < pH->nDecs ) *pLastDiffH = pH->pDecs[iCurH]; // return the pointer to the array *pCommon = Common; // return the number of common components return nCommon; } /**Function************************************************************* Synopsis [Computes the sum (OR or EXOR) of the functions of the components.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ) { DdManager * dd = pDsdMan->dd; DdNode * bF, * bFadd, * bTemp; DdNode * bS = NULL; // Suppress "might be used uninitialized" Dsd_Node_t * pDE, * pDER; int i; // start the function bF = b0; Cudd_Ref( bF ); // start the support if ( pCompS ) bS = b1, Cudd_Ref( bS ); assert( nCommon > 0 ); for ( i = 0; i < nCommon; i++ ) { pDE = pCommon[i]; pDER = Dsd_Regular( pDE ); bFadd = (pDE != pDER)? Cudd_Not(pDER->G): pDER->G; // add to the function if ( fExor ) bF = Cudd_bddXor( dd, bTemp = bF, bFadd ); else bF = Cudd_bddOr( dd, bTemp = bF, bFadd ); Cudd_Ref( bF ); Cudd_RecursiveDeref( dd, bTemp ); if ( pCompS ) { // add to the support bS = Cudd_bddAnd( dd, bTemp = bS, pDER->S ); Cudd_Ref( bS ); Cudd_RecursiveDeref( dd, bTemp ); } } // return the function Cudd_Deref( bF ); *pCompF = bF; // return the support if ( pCompS ) Cudd_Deref( bS ), *pCompS = bS; } /**Function************************************************************* Synopsis [Checks support containment of the decomposition components.] Description [This function returns 1 if support of one component is contained in that of another. In this case, pLarge (pSmall) is assigned to point to the larger (smaller) support. If the supports are identical return 0, and does not assign the components.] ] SideEffects [] SeeAlso [] ***********************************************************************/ int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ) { DdManager * dd = pDsdMan->dd; DdNode * bSuppLarge, * bSuppSmall; int RetValue; RetValue = Extra_bddSuppCheckContainment( dd, pL->S, pH->S, &bSuppLarge, &bSuppSmall ); if ( RetValue == 0 ) return 0; if ( pH->S == bSuppLarge ) { *pLarge = pH; *pSmall = pL; } else // if ( pL->S == bSuppLarge ) { *pLarge = pL; *pSmall = pH; } return 1; } /**Function************************************************************* Synopsis [Copies the list of components plus one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ) { int i; assert( nListSize+1 == p->nDecs ); p->pDecs[0] = First; for( i = 0; i < nListSize; i++ ) p->pDecs[i+1] = ppList[i]; } /**Function************************************************************* Synopsis [Copies the list of components plus one, and skips one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int iSkipped ) { int i, Counter; assert( nListSize == p->nDecs ); p->pDecs[0] = First; for( i = 0, Counter = 1; i < nListSize; i++ ) if ( i != iSkipped ) p->pDecs[Counter++] = ppList[i]; } /**Function************************************************************* Synopsis [Debugging procedure to compute the functionality of the decomposed structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ) { DdManager * dd = pDsdMan->dd; Dsd_Node_t * pR = Dsd_Regular(pDE); int RetValue; DdNode * bRes; if ( pR->Type == DSD_NODE_CONST1 ) bRes = b1; else if ( pR->Type == DSD_NODE_BUF ) bRes = pR->G; else if ( pR->Type == DSD_NODE_OR || pR->Type == DSD_NODE_EXOR ) dsdKernelComputeSumOfComponents( pDsdMan, pR->pDecs, pR->nDecs, &bRes, NULL, (int)(pR->Type == DSD_NODE_EXOR) ); else if ( pR->Type == DSD_NODE_PRIME ) { int i; static DdNode * bGVars[MAXINPUTS]; // transform the function of this block, so that it depended on inputs // corresponding to the formal inputs DdNode * bNewFunc = Dsd_TreeGetPrimeFunctionOld( dd, pR, 1 ); Cudd_Ref( bNewFunc ); // compose this function with the inputs // create the elementary permutation for ( i = 0; i < dd->size; i++ ) bGVars[i] = dd->vars[i]; // assign functions to be composed for ( i = 0; i < pR->nDecs; i++ ) bGVars[dd->invperm[i]] = pR->pDecs[i]->G; // perform the composition bRes = Cudd_bddVectorCompose( dd, bNewFunc, bGVars ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bNewFunc ); ///////////////////////////////////////////////////////// RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); ///////////////////////////////////////////////////////// Cudd_Deref( bRes ); } else { assert(0); } Cudd_Ref( bRes ); RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); Cudd_RecursiveDeref( dd, bRes ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/dsdTree.c000066400000000000000000001120001300674244400230670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dsdTree.c] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [Managing the decomposition tree.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsdTree.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dsdInt.h" #include "misc/util/utilTruth.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ); static void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ); static int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ); static int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ); static int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ); static void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ); static void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fCcmp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ); static void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ); //////////////////////////////////////////////////////////////////////// /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// static int s_DepthMax; static int s_GateSizeMax; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create the DSD node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ) { // allocate memory for this node Dsd_Node_t * p = (Dsd_Node_t *) ABC_ALLOC( char, sizeof(Dsd_Node_t) ); memset( p, 0, sizeof(Dsd_Node_t) ); p->Type = (Dsd_Type_t)Type; // the type of this block p->nDecs = nDecs; // the number of decompositions if ( p->nDecs ) { p->pDecs = (Dsd_Node_t **) ABC_ALLOC( char, p->nDecs * sizeof(Dsd_Node_t *) ); p->pDecs[0] = NULL; } return p; } /**Function************************************************************* Synopsis [Frees the DSD node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ) { if ( pNode->G ) Cudd_RecursiveDeref( dd, pNode->G ); if ( pNode->S ) Cudd_RecursiveDeref( dd, pNode->S ); ABC_FREE( pNode->pDecs ); ABC_FREE( pNode ); } /**Function************************************************************* Synopsis [Unmarks the decomposition tree.] Description [This function assumes that originally pNode->nVisits are set to zero!] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreeUnmark( Dsd_Manager_t * pDsdMan ) { int i; for ( i = 0; i < pDsdMan->nRoots; i++ ) Dsd_TreeUnmark_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); } /**Function************************************************************* Synopsis [Recursive unmarking.] Description [This function should be called with a non-complemented pointer.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ) { int i; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->nVisits > 0 ); if ( --pNode->nVisits ) // if this is not the last visit, return return; // upon the last visit, go through the list of successors and call recursively if ( pNode->Type != DSD_NODE_BUF && pNode->Type != DSD_NODE_CONST1 ) for ( i = 0; i < pNode->nDecs; i++ ) Dsd_TreeUnmark_rec( Dsd_Regular(pNode->pDecs[i]) ); } /**Function************************************************************* Synopsis [Getting information about the node.] Description [This function computes the max depth and the max gate size of the tree rooted at the node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreeNodeGetInfo( Dsd_Manager_t * pDsdMan, int * DepthMax, int * GateSizeMax ) { int i; s_DepthMax = 0; s_GateSizeMax = 0; for ( i = 0; i < pDsdMan->nRoots; i++ ) Dsd_TreeGetInfo_rec( Dsd_Regular( pDsdMan->pRoots[i] ), 0 ); if ( DepthMax ) *DepthMax = s_DepthMax; if ( GateSizeMax ) *GateSizeMax = s_GateSizeMax; } /**Function************************************************************* Synopsis [Getting information about the node.] Description [This function computes the max depth and the max gate size of the tree rooted at the node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ) { s_DepthMax = 0; s_GateSizeMax = 0; Dsd_TreeGetInfo_rec( Dsd_Regular(pNode), 0 ); if ( DepthMax ) *DepthMax = s_DepthMax; if ( GateSizeMax ) *GateSizeMax = s_GateSizeMax; } /**Function************************************************************* Synopsis [Performs the recursive step of Dsd_TreeNodeGetInfo().] Description [pNode is the node, for the tree rooted in which we are determining info. RankCur is the current rank to assign to the node. fSetRank is the flag saying whether the rank will be written in the node. s_DepthMax is the maximum depths of the tree. s_GateSizeMax is the maximum gate size.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ) { int i; int GateSize; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->nVisits >= 0 ); // we don't want the two-input gates to count for non-decomposable blocks if ( pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ) GateSize = 2; else GateSize = pNode->nDecs; // update the max size of the node if ( s_GateSizeMax < GateSize ) s_GateSizeMax = GateSize; if ( pNode->nDecs < 2 ) return; // update the max rank if ( s_DepthMax < RankCur+1 ) s_DepthMax = RankCur+1; // call recursively for ( i = 0; i < pNode->nDecs; i++ ) Dsd_TreeGetInfo_rec( Dsd_Regular(pNode->pDecs[i]), RankCur+1 ); } /**Function************************************************************* Synopsis [Counts AIG nodes needed to implement this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeGetAigCost_rec( Dsd_Node_t * pNode ) { int i, Counter = 0; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->nVisits >= 0 ); if ( pNode->nDecs < 2 ) return 0; // we don't want the two-input gates to count for non-decomposable blocks if ( pNode->Type == DSD_NODE_OR ) Counter += pNode->nDecs - 1; else if ( pNode->Type == DSD_NODE_EXOR ) Counter += 3*(pNode->nDecs - 1); else if ( pNode->Type == DSD_NODE_PRIME && pNode->nDecs == 3 ) Counter += 3; // call recursively for ( i = 0; i < pNode->nDecs; i++ ) Counter += Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode->pDecs[i]) ); return Counter; } /**Function************************************************************* Synopsis [Counts AIG nodes needed to implement this node.] Description [Assumes that the only primes of the DSD tree are MUXes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ) { return Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode) ); } /**Function************************************************************* Synopsis [Counts non-terminal nodes of the DSD tree.] Description [Nonterminal nodes include all the nodes with the support more than 1. These are OR, EXOR, and PRIME nodes. They do not include the elementary variable nodes and the constant 1 node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * pDsdMan ) { int Counter, i; Counter = 0; for ( i = 0; i < pDsdMan->nRoots; i++ ) Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); Dsd_TreeUnmark( pDsdMan ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ) { int Counter = 0; // go through the list of successors and call recursively Counter = Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pRoot) ); Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); return Counter; } /**Function************************************************************* Synopsis [Counts non-terminal nodes for one root.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ) { int i; int Counter = 0; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->nVisits >= 0 ); if ( pNode->nVisits++ ) // if this is not the first visit, return zero return 0; if ( pNode->nDecs <= 1 ) return 0; // upon the first visit, go through the list of successors and call recursively for ( i = 0; i < pNode->nDecs; i++ ) Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); return Counter + 1; } /**Function************************************************************* Synopsis [Counts prime nodes of the DSD tree.] Description [Prime nodes are nodes with the support more than 2, that is not an OR or EXOR gate.] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ) { int Counter, i; Counter = 0; for ( i = 0; i < pDsdMan->nRoots; i++ ) Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); Dsd_TreeUnmark( pDsdMan ); return Counter; } /**Function************************************************************* Synopsis [Counts prime nodes for one root.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ) { int Counter = 0; // go through the list of successors and call recursively Counter = Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pRoot) ); Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ) { int i; int Counter = 0; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->nVisits >= 0 ); if ( pNode->nVisits++ ) // if this is not the first visit, return zero return 0; if ( pNode->nDecs <= 1 ) return 0; // upon the first visit, go through the list of successors and call recursively for ( i = 0; i < pNode->nDecs; i++ ) Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); if ( pNode->Type == DSD_NODE_PRIME ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Collects the decomposable vars on the PI side.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * pDsdMan, int * pVars ) { int nVars; // set the vars collected to 0 nVars = 0; Dsd_TreeCollectDecomposableVars_rec( pDsdMan->dd, Dsd_Regular(pDsdMan->pRoots[0]), pVars, &nVars ); // return the number of collected vars return nVars; } /**Function************************************************************* Synopsis [Implements the recursive part of Dsd_TreeCollectDecomposableVars().] Description [Adds decomposable variables as they are found to pVars and increments nVars. Returns 1 if a non-dec node with more than 4 inputs was encountered in the processed subtree. Returns 0, otherwise. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ) { int fSkipThisNode, i; Dsd_Node_t * pTemp; int fVerbose = 0; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); if ( pNode->nDecs <= 1 ) return 0; // go through the list of successors and call recursively fSkipThisNode = 0; for ( i = 0; i < pNode->nDecs; i++ ) if ( Dsd_TreeCollectDecomposableVars_rec(dd, Dsd_Regular(pNode->pDecs[i]), pVars, nVars) ) fSkipThisNode = 1; if ( !fSkipThisNode && (pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR || pNode->nDecs <= 4) ) { if ( fVerbose ) printf( "Node of type <%d> (OR=6,EXOR=8,RAND=1): ", pNode->Type ); for ( i = 0; i < pNode->nDecs; i++ ) { pTemp = Dsd_Regular(pNode->pDecs[i]); if ( pTemp->Type == DSD_NODE_BUF ) { if ( pVars ) pVars[ (*nVars)++ ] = pTemp->S->index; else (*nVars)++; if ( fVerbose ) printf( "%d ", pTemp->S->index ); } } if ( fVerbose ) printf( "\n" ); } else fSkipThisNode = 1; return fSkipThisNode; } /**Function************************************************************* Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] Description [The collected nodes do not include the terminal nodes and the constant 1 node. The array of nodes is returned. The number of entries in the array is returned in the variale pnNodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * pDsdMan, int * pnNodes ) { Dsd_Node_t ** ppNodes; int nNodes, nNodesAlloc; int i; nNodesAlloc = Dsd_TreeCountNonTerminalNodes(pDsdMan); nNodes = 0; ppNodes = ABC_ALLOC( Dsd_Node_t *, nNodesAlloc ); for ( i = 0; i < pDsdMan->nRoots; i++ ) Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pDsdMan->pRoots[i]), ppNodes, &nNodes ); Dsd_TreeUnmark( pDsdMan ); assert( nNodesAlloc == nNodes ); *pnNodes = nNodes; return ppNodes; } /**Function************************************************************* Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] Description [The collected nodes do not include the terminal nodes and the constant 1 node. The array of nodes is returned. The number of entries in the array is returned in the variale pnNodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ) { Dsd_Node_t ** ppNodes; int nNodes, nNodesAlloc; nNodesAlloc = Dsd_TreeCountNonTerminalNodesOne(pNode); nNodes = 0; ppNodes = ABC_ALLOC( Dsd_Node_t *, nNodesAlloc ); Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode), ppNodes, &nNodes ); Dsd_TreeUnmark_rec(Dsd_Regular(pNode)); assert( nNodesAlloc == nNodes ); *pnNodes = nNodes; return ppNodes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ) { int i; assert( pNode ); assert( !Dsd_IsComplement(pNode) ); assert( pNode->nVisits >= 0 ); if ( pNode->nVisits++ ) // if this is not the first visit, return zero return; if ( pNode->nDecs <= 1 ) return; // upon the first visit, go through the list of successors and call recursively for ( i = 0; i < pNode->nDecs; i++ ) Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode->pDecs[i]), ppNodes, pnNodes ); ppNodes[ (*pnNodes)++ ] = pNode; } /**Function************************************************************* Synopsis [Prints the decompostion tree into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ) { Dsd_Node_t * pNode; int SigCounter; int i; SigCounter = 1; if ( Output == -1 ) { for ( i = 0; i < pDsdMan->nRoots; i++ ) { pNode = Dsd_Regular( pDsdMan->pRoots[i] ); Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[i]), pInputNames, pOutputNames[i], 0, &SigCounter, fShortNames ); } } else { assert( Output >= 0 && Output < pDsdMan->nRoots ); pNode = Dsd_Regular( pDsdMan->pRoots[Output] ); Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[Output]), pInputNames, pOutputNames[Output], 0, &SigCounter, fShortNames ); } } /**Function************************************************************* Synopsis [Prints the decompostion tree into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ) { char Buffer[100]; Dsd_Node_t * pInput; int * pInputNums; int fCompNew, i; assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); if ( !fComp ) fprintf( pFile, "%s = ", pOutputName ); else fprintf( pFile, "NOT(%s) = ", pOutputName ); pInputNums = ABC_ALLOC( int, pNode->nDecs ); if ( pNode->Type == DSD_NODE_CONST1 ) { fprintf( pFile, " Constant 1.\n" ); } else if ( pNode->Type == DSD_NODE_BUF ) { if ( fShortNames ) fprintf( pFile, "%d", 'a' + pNode->S->index ); else fprintf( pFile, "%s", pInputNames[pNode->S->index] ); fprintf( pFile, "\n" ); } else if ( pNode->Type == DSD_NODE_PRIME ) { // print the line fprintf( pFile, "PRIME(" ); for ( i = 0; i < pNode->nDecs; i++ ) { pInput = Dsd_Regular( pNode->pDecs[i] ); fCompNew = (int)( pInput != pNode->pDecs[i] ); if ( i ) fprintf( pFile, "," ); if ( fCompNew ) fprintf( pFile, " NOT(" ); else fprintf( pFile, " " ); if ( pInput->Type == DSD_NODE_BUF ) { pInputNums[i] = 0; if ( fShortNames ) fprintf( pFile, "%d", pInput->S->index ); else fprintf( pFile, "%s", pInputNames[pInput->S->index] ); } else { pInputNums[i] = (*pSigCounter)++; fprintf( pFile, "<%d>", pInputNums[i] ); } if ( fCompNew ) fprintf( pFile, ")" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks for ( i = 0; i < pNode->nDecs; i++ ) if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); } } else if ( pNode->Type == DSD_NODE_OR ) { // print the line fprintf( pFile, "OR(" ); for ( i = 0; i < pNode->nDecs; i++ ) { pInput = Dsd_Regular( pNode->pDecs[i] ); fCompNew = (int)( pInput != pNode->pDecs[i] ); if ( i ) fprintf( pFile, "," ); if ( fCompNew ) fprintf( pFile, " NOT(" ); else fprintf( pFile, " " ); if ( pInput->Type == DSD_NODE_BUF ) { pInputNums[i] = 0; if ( fShortNames ) fprintf( pFile, "%c", 'a' + pInput->S->index ); else fprintf( pFile, "%s", pInputNames[pInput->S->index] ); } else { pInputNums[i] = (*pSigCounter)++; fprintf( pFile, "<%d>", pInputNums[i] ); } if ( fCompNew ) fprintf( pFile, ")" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks for ( i = 0; i < pNode->nDecs; i++ ) if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); } } else if ( pNode->Type == DSD_NODE_EXOR ) { // print the line fprintf( pFile, "EXOR(" ); for ( i = 0; i < pNode->nDecs; i++ ) { pInput = Dsd_Regular( pNode->pDecs[i] ); fCompNew = (int)( pInput != pNode->pDecs[i] ); if ( i ) fprintf( pFile, "," ); if ( fCompNew ) fprintf( pFile, " NOT(" ); else fprintf( pFile, " " ); if ( pInput->Type == DSD_NODE_BUF ) { pInputNums[i] = 0; if ( fShortNames ) fprintf( pFile, "%c", 'a' + pInput->S->index ); else fprintf( pFile, "%s", pInputNames[pInput->S->index] ); } else { pInputNums[i] = (*pSigCounter)++; fprintf( pFile, "<%d>", pInputNums[i] ); } if ( fCompNew ) fprintf( pFile, ")" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks for ( i = 0; i < pNode->nDecs; i++ ) if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); } } ABC_FREE( pInputNums ); } /**Function************************************************************* Synopsis [Prints the decompostion tree into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Dsd_TreeFunc2Truth_rec( DdManager * dd, DdNode * bFunc ) { word Cof0, Cof1; int Level; if ( bFunc == b0 ) return 0; if ( bFunc == b1 ) return ~(word)0; if ( Cudd_IsComplement(bFunc) ) return ~Dsd_TreeFunc2Truth_rec( dd, Cudd_Not(bFunc) ); Level = dd->perm[bFunc->index]; assert( Level >= 0 && Level < 6 ); Cof0 = Dsd_TreeFunc2Truth_rec( dd, cuddE(bFunc) ); Cof1 = Dsd_TreeFunc2Truth_rec( dd, cuddT(bFunc) ); return (s_Truths6[Level] & Cof1) | (~s_Truths6[Level] & Cof0); } void Dsd_TreePrint2_rec( FILE * pFile, DdManager * dd, Dsd_Node_t * pNode, int fComp, char * pInputNames[] ) { int i; if ( pNode->Type == DSD_NODE_CONST1 ) { fprintf( pFile, "Const%d", !fComp ); return; } assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); // fprintf( pFile, "%s", (fComp ^ (pNode->Type == DSD_NODE_OR))? "!" : "" ); if ( pNode->Type == DSD_NODE_BUF ) { fprintf( pFile, "%s", fComp? "!" : "" ); fprintf( pFile, "%s", pInputNames[pNode->S->index] ); } else if ( pNode->Type == DSD_NODE_PRIME ) { fprintf( pFile, " " ); if ( pNode->nDecs <= 6 ) { char pCanonPerm[6]; int uCanonPhase; // compute truth table DdNode * bFunc = Dsd_TreeGetPrimeFunction( dd, pNode ); word uTruth = Dsd_TreeFunc2Truth_rec( dd, bFunc ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bFunc ); // canonicize truth table uCanonPhase = Abc_TtCanonicize( &uTruth, pNode->nDecs, pCanonPerm ); fprintf( pFile, "%s", (fComp ^ ((uCanonPhase >> pNode->nDecs) & 1)) ? "!" : "" ); Abc_TtPrintHexRev( pFile, &uTruth, pNode->nDecs ); fprintf( pFile, "{" ); for ( i = 0; i < pNode->nDecs; i++ ) { Dsd_Node_t * pInput = pNode->pDecs[(int)pCanonPerm[i]]; Dsd_TreePrint2_rec( pFile, dd, Dsd_Regular(pInput), Dsd_IsComplement(pInput) ^ ((uCanonPhase>>i)&1), pInputNames ); } fprintf( pFile, "} " ); } else { fprintf( pFile, "|%d|", pNode->nDecs ); fprintf( pFile, "{" ); for ( i = 0; i < pNode->nDecs; i++ ) Dsd_TreePrint2_rec( pFile, dd, Dsd_Regular(pNode->pDecs[i]), Dsd_IsComplement(pNode->pDecs[i]), pInputNames ); fprintf( pFile, "} " ); } } else if ( pNode->Type == DSD_NODE_OR ) { fprintf( pFile, "%s", !fComp? "!" : "" ); fprintf( pFile, "(" ); for ( i = 0; i < pNode->nDecs; i++ ) Dsd_TreePrint2_rec( pFile, dd, Dsd_Regular(pNode->pDecs[i]), !Dsd_IsComplement(pNode->pDecs[i]), pInputNames ); fprintf( pFile, ")" ); } else if ( pNode->Type == DSD_NODE_EXOR ) { fprintf( pFile, "%s", fComp? "!" : "" ); fprintf( pFile, "[" ); for ( i = 0; i < pNode->nDecs; i++ ) Dsd_TreePrint2_rec( pFile, dd, Dsd_Regular(pNode->pDecs[i]), Dsd_IsComplement(pNode->pDecs[i]), pInputNames ); fprintf( pFile, "]" ); } } void Dsd_TreePrint2( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int Output ) { if ( Output == -1 ) { int i; for ( i = 0; i < pDsdMan->nRoots; i++ ) { fprintf( pFile, "%8s = ", pOutputNames[i] ); Dsd_TreePrint2_rec( pFile, pDsdMan->dd, Dsd_Regular(pDsdMan->pRoots[i]), Dsd_IsComplement(pDsdMan->pRoots[i]), pInputNames ); fprintf( pFile, "\n" ); } } else { assert( Output >= 0 && Output < pDsdMan->nRoots ); fprintf( pFile, "%8s = ", pOutputNames[Output] ); Dsd_TreePrint2_rec( pFile, pDsdMan->dd, Dsd_Regular(pDsdMan->pRoots[Output]), Dsd_IsComplement(pDsdMan->pRoots[Output]), pInputNames ); fprintf( pFile, "\n" ); } } /**Function************************************************************* Synopsis [Prints the decompostion tree into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ) { Dsd_Node_t * pNodeR; int SigCounter = 1; pNodeR = Dsd_Regular(pNode); Dsd_NodePrint_rec( pFile, pNodeR, pNodeR != pNode, "F", 0, &SigCounter ); } /**Function************************************************************* Synopsis [Prints one node of the decomposition tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ) { char Buffer[100]; Dsd_Node_t * pInput; int * pInputNums; int fCompNew, i; assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); if ( !fComp ) fprintf( pFile, "%s = ", pOutputName ); else fprintf( pFile, "NOT(%s) = ", pOutputName ); pInputNums = ABC_ALLOC( int, pNode->nDecs ); if ( pNode->Type == DSD_NODE_CONST1 ) { fprintf( pFile, " Constant 1.\n" ); } else if ( pNode->Type == DSD_NODE_BUF ) { fprintf( pFile, " " ); fprintf( pFile, "%c", 'a' + pNode->S->index ); fprintf( pFile, "\n" ); } else if ( pNode->Type == DSD_NODE_PRIME ) { // print the line fprintf( pFile, "PRIME(" ); for ( i = 0; i < pNode->nDecs; i++ ) { pInput = Dsd_Regular( pNode->pDecs[i] ); fCompNew = (int)( pInput != pNode->pDecs[i] ); assert( fCompNew == 0 ); if ( i ) fprintf( pFile, "," ); if ( pInput->Type == DSD_NODE_BUF ) { pInputNums[i] = 0; fprintf( pFile, " %c", 'a' + pInput->S->index ); } else { pInputNums[i] = (*pSigCounter)++; fprintf( pFile, " <%d>", pInputNums[i] ); } if ( fCompNew ) fprintf( pFile, "\'" ); } fprintf( pFile, " )\n" ); /* fprintf( pFile, " ) " ); { DdNode * bLocal; bLocal = Dsd_TreeGetPrimeFunction( dd, pNodeDsd ); Cudd_Ref( bLocal ); Extra_bddPrint( dd, bLocal ); Cudd_RecursiveDeref( dd, bLocal ); } */ // call recursively for the following blocks for ( i = 0; i < pNode->nDecs; i++ ) if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); } } else if ( pNode->Type == DSD_NODE_OR ) { // print the line fprintf( pFile, "OR(" ); for ( i = 0; i < pNode->nDecs; i++ ) { pInput = Dsd_Regular( pNode->pDecs[i] ); fCompNew = (int)( pInput != pNode->pDecs[i] ); if ( i ) fprintf( pFile, "," ); if ( pInput->Type == DSD_NODE_BUF ) { pInputNums[i] = 0; fprintf( pFile, " %c", 'a' + pInput->S->index ); } else { pInputNums[i] = (*pSigCounter)++; fprintf( pFile, " <%d>", pInputNums[i] ); } if ( fCompNew ) fprintf( pFile, "\'" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks for ( i = 0; i < pNode->nDecs; i++ ) if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); } } else if ( pNode->Type == DSD_NODE_EXOR ) { // print the line fprintf( pFile, "EXOR(" ); for ( i = 0; i < pNode->nDecs; i++ ) { pInput = Dsd_Regular( pNode->pDecs[i] ); fCompNew = (int)( pInput != pNode->pDecs[i] ); assert( fCompNew == 0 ); if ( i ) fprintf( pFile, "," ); if ( pInput->Type == DSD_NODE_BUF ) { pInputNums[i] = 0; fprintf( pFile, " %c", 'a' + pInput->S->index ); } else { pInputNums[i] = (*pSigCounter)++; fprintf( pFile, " <%d>", pInputNums[i] ); } if ( fCompNew ) fprintf( pFile, "\'" ); } fprintf( pFile, " )\n" ); // call recursively for the following blocks for ( i = 0; i < pNode->nDecs; i++ ) if ( pInputNums[i] ) { pInput = Dsd_Regular( pNode->pDecs[i] ); sprintf( Buffer, "<%d>", pInputNums[i] ); Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); } } ABC_FREE( pInputNums ); } /**Function************************************************************* Synopsis [Retuns the function of one node of the decomposition tree.] Description [This is the old procedure. It is now superceded by the procedure Dsd_TreeGetPrimeFunction() found in "dsdLocal.c".] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) { DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; int i; static int Permute[MAXINPUTS]; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->Type == DSD_NODE_PRIME ); // transform the function of this block to depend on inputs // corresponding to the formal inputs // first, substitute those inputs that have some blocks associated with them // second, remap the inputs to the top of the manager (then, it is easy to output them) // start the function bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); // go over all primary inputs for ( i = 0; i < pNode->nDecs; i++ ) if ( pNode->pDecs[i]->Type != DSD_NODE_BUF ) // remap only if it is not the buffer { bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); Cudd_RecursiveDeref( dd, bCube0 ); bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); Cudd_RecursiveDeref( dd, bCube1 ); Cudd_RecursiveDeref( dd, bNewFunc ); // use the variable in the i-th level of the manager // bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); // use the first variale in the support of the component bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); } if ( fRemap ) { // remap the function to the top of the manager // remap the function to the first variables of the manager for ( i = 0; i < pNode->nDecs; i++ ) // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; Permute[ pNode->pDecs[i]->S->index ] = i; bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bNewFunc ); return bNewFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/dsd/module.make000066400000000000000000000002401300674244400234570ustar00rootroot00000000000000SRC += src/bdd/dsd/dsdApi.c \ src/bdd/dsd/dsdCheck.c \ src/bdd/dsd/dsdLocal.c \ src/bdd/dsd/dsdMan.c \ src/bdd/dsd/dsdProc.c \ src/bdd/dsd/dsdTree.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/epd/000077500000000000000000000000001300674244400213355ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/epd/epd.c000066400000000000000000001001271300674244400222520ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [epd.c] PackageName [epd] Synopsis [Arithmetic functions with extended double precision.] Description [] SeeAlso [] Author [In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] Revision [$Id: epd.c,v 1.10 2004/08/13 18:20:30 fabio Exp $] ******************************************************************************/ #include #include #include #include #include "misc/util/util_hack.h" #include "epd.h" ABC_NAMESPACE_IMPL_START /**Function******************************************************************** Synopsis [Allocates an EpDouble struct.] Description [Allocates an EpDouble struct.] SideEffects [] SeeAlso [] ******************************************************************************/ EpDouble * EpdAlloc(void) { EpDouble *epd; epd = ABC_ALLOC(EpDouble, 1); return(epd); } /**Function******************************************************************** Synopsis [Compares two EpDouble struct.] Description [Compares two EpDouble struct.] SideEffects [] SeeAlso [] ******************************************************************************/ int EpdCmp(const char *key1, const char *key2) { EpDouble *epd1 = (EpDouble *) key1; EpDouble *epd2 = (EpDouble *) key2; if (epd1->type.value != epd2->type.value || epd1->exponent != epd2->exponent) { return(1); } return(0); } /**Function******************************************************************** Synopsis [Frees an EpDouble struct.] Description [Frees an EpDouble struct.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdFree(EpDouble *epd) { ABC_FREE(epd); } /**Function******************************************************************** Synopsis [Converts an arbitrary precision double value to a string.] Description [Converts an arbitrary precision double value to a string.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdGetString(EpDouble *epd, char *str) { double value; int exponent; char *pos; if (IsNanDouble(epd->type.value)) { sprintf(str, "NaN"); return; } else if (IsInfDouble(epd->type.value)) { if (epd->type.bits.sign == 1) sprintf(str, "-Inf"); else sprintf(str, "Inf"); return; } assert(epd->type.bits.exponent == EPD_MAX_BIN || epd->type.bits.exponent == 0); EpdGetValueAndDecimalExponent(epd, &value, &exponent); sprintf(str, "%e", value); pos = strstr(str, "e"); if (exponent >= 0) { if (exponent < 10) sprintf(pos + 1, "+0%d", exponent); else sprintf(pos + 1, "+%d", exponent); } else { exponent *= -1; if (exponent < 10) sprintf(pos + 1, "-0%d", exponent); else sprintf(pos + 1, "-%d", exponent); } } /**Function******************************************************************** Synopsis [Converts double to EpDouble struct.] Description [Converts double to EpDouble struct.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdConvert(double value, EpDouble *epd) { epd->type.value = value; epd->exponent = 0; EpdNormalize(epd); } /**Function******************************************************************** Synopsis [Multiplies two arbitrary precision double values.] Description [Multiplies two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdMultiply(EpDouble *epd1, double value) { EpDouble epd2; double tmp; int exponent; if (EpdIsNan(epd1) || IsNanDouble(value)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || IsInfDouble(value)) { int sign; EpdConvert(value, &epd2); sign = epd1->type.bits.sign ^ epd2.type.bits.sign; EpdMakeInf(epd1, sign); return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); EpdConvert(value, &epd2); tmp = epd1->type.value * epd2.type.value; exponent = epd1->exponent + epd2.exponent; epd1->type.value = tmp; epd1->exponent = exponent; EpdNormalize(epd1); } /**Function******************************************************************** Synopsis [Multiplies two arbitrary precision double values.] Description [Multiplies two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdMultiply2(EpDouble *epd1, EpDouble *epd2) { double value; int exponent; if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; sign = epd1->type.bits.sign ^ epd2->type.bits.sign; EpdMakeInf(epd1, sign); return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); assert(epd2->type.bits.exponent == EPD_MAX_BIN); value = epd1->type.value * epd2->type.value; exponent = epd1->exponent + epd2->exponent; epd1->type.value = value; epd1->exponent = exponent; EpdNormalize(epd1); } /**Function******************************************************************** Synopsis [Multiplies two arbitrary precision double values.] Description [Multiplies two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2) { double value; int exponent; if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; sign = epd1->type.bits.sign ^ epd2->type.bits.sign; EpdMakeInf(epd1, sign); return; } value = epd1->type.value * epd2->type.value; exponent = epd1->exponent + epd2->exponent; epd1->type.value = value; epd1->exponent = exponent; EpdNormalizeDecimal(epd1); } /**Function******************************************************************** Synopsis [Multiplies two arbitrary precision double values.] Description [Multiplies two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) { if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; sign = epd1->type.bits.sign ^ epd2->type.bits.sign; EpdMakeInf(epd3, sign); return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); assert(epd2->type.bits.exponent == EPD_MAX_BIN); epd3->type.value = epd1->type.value * epd2->type.value; epd3->exponent = epd1->exponent + epd2->exponent; EpdNormalize(epd3); } /**Function******************************************************************** Synopsis [Multiplies two arbitrary precision double values.] Description [Multiplies two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) { if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; sign = epd1->type.bits.sign ^ epd2->type.bits.sign; EpdMakeInf(epd3, sign); return; } epd3->type.value = epd1->type.value * epd2->type.value; epd3->exponent = epd1->exponent + epd2->exponent; EpdNormalizeDecimal(epd3); } /**Function******************************************************************** Synopsis [Divides two arbitrary precision double values.] Description [Divides two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdDivide(EpDouble *epd1, double value) { EpDouble epd2; double tmp; int exponent; if (EpdIsNan(epd1) || IsNanDouble(value)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || IsInfDouble(value)) { int sign; EpdConvert(value, &epd2); if (EpdIsInf(epd1) && IsInfDouble(value)) { EpdMakeNan(epd1); } else if (EpdIsInf(epd1)) { sign = epd1->type.bits.sign ^ epd2.type.bits.sign; EpdMakeInf(epd1, sign); } else { sign = epd1->type.bits.sign ^ epd2.type.bits.sign; EpdMakeZero(epd1, sign); } return; } if (value == 0.0) { EpdMakeNan(epd1); return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); EpdConvert(value, &epd2); tmp = epd1->type.value / epd2.type.value; exponent = epd1->exponent - epd2.exponent; epd1->type.value = tmp; epd1->exponent = exponent; EpdNormalize(epd1); } /**Function******************************************************************** Synopsis [Divides two arbitrary precision double values.] Description [Divides two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdDivide2(EpDouble *epd1, EpDouble *epd2) { double value; int exponent; if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; if (EpdIsInf(epd1) && EpdIsInf(epd2)) { EpdMakeNan(epd1); } else if (EpdIsInf(epd1)) { sign = epd1->type.bits.sign ^ epd2->type.bits.sign; EpdMakeInf(epd1, sign); } else { sign = epd1->type.bits.sign ^ epd2->type.bits.sign; EpdMakeZero(epd1, sign); } return; } if (epd2->type.value == 0.0) { EpdMakeNan(epd1); return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); assert(epd2->type.bits.exponent == EPD_MAX_BIN); value = epd1->type.value / epd2->type.value; exponent = epd1->exponent - epd2->exponent; epd1->type.value = value; epd1->exponent = exponent; EpdNormalize(epd1); } /**Function******************************************************************** Synopsis [Divides two arbitrary precision double values.] Description [Divides two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) { if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd3); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; if (EpdIsInf(epd1) && EpdIsInf(epd2)) { EpdMakeNan(epd3); } else if (EpdIsInf(epd1)) { sign = epd1->type.bits.sign ^ epd2->type.bits.sign; EpdMakeInf(epd3, sign); } else { sign = epd1->type.bits.sign ^ epd2->type.bits.sign; EpdMakeZero(epd3, sign); } return; } if (epd2->type.value == 0.0) { EpdMakeNan(epd3); return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); assert(epd2->type.bits.exponent == EPD_MAX_BIN); epd3->type.value = epd1->type.value / epd2->type.value; epd3->exponent = epd1->exponent - epd2->exponent; EpdNormalize(epd3); } /**Function******************************************************************** Synopsis [Adds two arbitrary precision double values.] Description [Adds two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdAdd(EpDouble *epd1, double value) { EpDouble epd2; double tmp; int exponent, diff; if (EpdIsNan(epd1) || IsNanDouble(value)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || IsInfDouble(value)) { int sign; EpdConvert(value, &epd2); if (EpdIsInf(epd1) && IsInfDouble(value)) { sign = epd1->type.bits.sign ^ epd2.type.bits.sign; if (sign == 1) EpdMakeNan(epd1); } else if (EpdIsInf(&epd2)) { EpdCopy(&epd2, epd1); } return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); EpdConvert(value, &epd2); if (epd1->exponent > epd2.exponent) { diff = epd1->exponent - epd2.exponent; if (diff <= EPD_MAX_BIN) tmp = epd1->type.value + epd2.type.value / pow((double)2.0, (double)diff); else tmp = epd1->type.value; exponent = epd1->exponent; } else if (epd1->exponent < epd2.exponent) { diff = epd2.exponent - epd1->exponent; if (diff <= EPD_MAX_BIN) tmp = epd1->type.value / pow((double)2.0, (double)diff) + epd2.type.value; else tmp = epd2.type.value; exponent = epd2.exponent; } else { tmp = epd1->type.value + epd2.type.value; exponent = epd1->exponent; } epd1->type.value = tmp; epd1->exponent = exponent; EpdNormalize(epd1); } /**Function******************************************************************** Synopsis [Adds two arbitrary precision double values.] Description [Adds two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdAdd2(EpDouble *epd1, EpDouble *epd2) { double value; int exponent, diff; if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; if (EpdIsInf(epd1) && EpdIsInf(epd2)) { sign = epd1->type.bits.sign ^ epd2->type.bits.sign; if (sign == 1) EpdMakeNan(epd1); } else if (EpdIsInf(epd2)) { EpdCopy(epd2, epd1); } return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); assert(epd2->type.bits.exponent == EPD_MAX_BIN); if (epd1->exponent > epd2->exponent) { diff = epd1->exponent - epd2->exponent; if (diff <= EPD_MAX_BIN) { value = epd1->type.value + epd2->type.value / pow((double)2.0, (double)diff); } else value = epd1->type.value; exponent = epd1->exponent; } else if (epd1->exponent < epd2->exponent) { diff = epd2->exponent - epd1->exponent; if (diff <= EPD_MAX_BIN) { value = epd1->type.value / pow((double)2.0, (double)diff) + epd2->type.value; } else value = epd2->type.value; exponent = epd2->exponent; } else { value = epd1->type.value + epd2->type.value; exponent = epd1->exponent; } epd1->type.value = value; epd1->exponent = exponent; EpdNormalize(epd1); } /**Function******************************************************************** Synopsis [Adds two arbitrary precision double values.] Description [Adds two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) { double value; int exponent, diff; if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd3); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; if (EpdIsInf(epd1) && EpdIsInf(epd2)) { sign = epd1->type.bits.sign ^ epd2->type.bits.sign; if (sign == 1) EpdMakeNan(epd3); else EpdCopy(epd1, epd3); } else if (EpdIsInf(epd1)) { EpdCopy(epd1, epd3); } else { EpdCopy(epd2, epd3); } return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); assert(epd2->type.bits.exponent == EPD_MAX_BIN); if (epd1->exponent > epd2->exponent) { diff = epd1->exponent - epd2->exponent; if (diff <= EPD_MAX_BIN) { value = epd1->type.value + epd2->type.value / pow((double)2.0, (double)diff); } else value = epd1->type.value; exponent = epd1->exponent; } else if (epd1->exponent < epd2->exponent) { diff = epd2->exponent - epd1->exponent; if (diff <= EPD_MAX_BIN) { value = epd1->type.value / pow((double)2.0, (double)diff) + epd2->type.value; } else value = epd2->type.value; exponent = epd2->exponent; } else { value = epd1->type.value + epd2->type.value; exponent = epd1->exponent; } epd3->type.value = value; epd3->exponent = exponent; EpdNormalize(epd3); } /**Function******************************************************************** Synopsis [Subtracts two arbitrary precision double values.] Description [Subtracts two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdSubtract(EpDouble *epd1, double value) { EpDouble epd2; double tmp; int exponent, diff; if (EpdIsNan(epd1) || IsNanDouble(value)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || IsInfDouble(value)) { int sign; EpdConvert(value, &epd2); if (EpdIsInf(epd1) && IsInfDouble(value)) { sign = epd1->type.bits.sign ^ epd2.type.bits.sign; if (sign == 0) EpdMakeNan(epd1); } else if (EpdIsInf(&epd2)) { EpdCopy(&epd2, epd1); } return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); EpdConvert(value, &epd2); if (epd1->exponent > epd2.exponent) { diff = epd1->exponent - epd2.exponent; if (diff <= EPD_MAX_BIN) tmp = epd1->type.value - epd2.type.value / pow((double)2.0, (double)diff); else tmp = epd1->type.value; exponent = epd1->exponent; } else if (epd1->exponent < epd2.exponent) { diff = epd2.exponent - epd1->exponent; if (diff <= EPD_MAX_BIN) tmp = epd1->type.value / pow((double)2.0, (double)diff) - epd2.type.value; else tmp = epd2.type.value * (double)(-1.0); exponent = epd2.exponent; } else { tmp = epd1->type.value - epd2.type.value; exponent = epd1->exponent; } epd1->type.value = tmp; epd1->exponent = exponent; EpdNormalize(epd1); } /**Function******************************************************************** Synopsis [Subtracts two arbitrary precision double values.] Description [Subtracts two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdSubtract2(EpDouble *epd1, EpDouble *epd2) { double value; int exponent, diff; if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd1); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; if (EpdIsInf(epd1) && EpdIsInf(epd2)) { sign = epd1->type.bits.sign ^ epd2->type.bits.sign; if (sign == 0) EpdMakeNan(epd1); } else if (EpdIsInf(epd2)) { EpdCopy(epd2, epd1); } return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); assert(epd2->type.bits.exponent == EPD_MAX_BIN); if (epd1->exponent > epd2->exponent) { diff = epd1->exponent - epd2->exponent; if (diff <= EPD_MAX_BIN) { value = epd1->type.value - epd2->type.value / pow((double)2.0, (double)diff); } else value = epd1->type.value; exponent = epd1->exponent; } else if (epd1->exponent < epd2->exponent) { diff = epd2->exponent - epd1->exponent; if (diff <= EPD_MAX_BIN) { value = epd1->type.value / pow((double)2.0, (double)diff) - epd2->type.value; } else value = epd2->type.value * (double)(-1.0); exponent = epd2->exponent; } else { value = epd1->type.value - epd2->type.value; exponent = epd1->exponent; } epd1->type.value = value; epd1->exponent = exponent; EpdNormalize(epd1); } /**Function******************************************************************** Synopsis [Subtracts two arbitrary precision double values.] Description [Subtracts two arbitrary precision double values.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) { double value; int exponent, diff; if (EpdIsNan(epd1) || EpdIsNan(epd2)) { EpdMakeNan(epd3); return; } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { int sign; if (EpdIsInf(epd1) && EpdIsInf(epd2)) { sign = epd1->type.bits.sign ^ epd2->type.bits.sign; if (sign == 0) EpdCopy(epd1, epd3); else EpdMakeNan(epd3); } else if (EpdIsInf(epd1)) { EpdCopy(epd1, epd1); } else { sign = epd2->type.bits.sign ^ 0x1; EpdMakeInf(epd3, sign); } return; } assert(epd1->type.bits.exponent == EPD_MAX_BIN); assert(epd2->type.bits.exponent == EPD_MAX_BIN); if (epd1->exponent > epd2->exponent) { diff = epd1->exponent - epd2->exponent; if (diff <= EPD_MAX_BIN) { value = epd1->type.value - epd2->type.value / pow((double)2.0, (double)diff); } else value = epd1->type.value; exponent = epd1->exponent; } else if (epd1->exponent < epd2->exponent) { diff = epd2->exponent - epd1->exponent; if (diff <= EPD_MAX_BIN) { value = epd1->type.value / pow((double)2.0, (double)diff) - epd2->type.value; } else value = epd2->type.value * (double)(-1.0); exponent = epd2->exponent; } else { value = epd1->type.value - epd2->type.value; exponent = epd1->exponent; } epd3->type.value = value; epd3->exponent = exponent; EpdNormalize(epd3); } /**Function******************************************************************** Synopsis [Computes arbitrary precision pow of base 2.] Description [Computes arbitrary precision pow of base 2.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdPow2(int n, EpDouble *epd) { if (n <= EPD_MAX_BIN) { EpdConvert(pow((double)2.0, (double)n), epd); } else { EpDouble epd1, epd2; int n1, n2; n1 = n / 2; n2 = n - n1; EpdPow2(n1, &epd1); EpdPow2(n2, &epd2); EpdMultiply3(&epd1, &epd2, epd); } } /**Function******************************************************************** Synopsis [Computes arbitrary precision pow of base 2.] Description [Computes arbitrary precision pow of base 2.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdPow2Decimal(int n, EpDouble *epd) { if (n <= EPD_MAX_BIN) { epd->type.value = pow((double)2.0, (double)n); epd->exponent = 0; EpdNormalizeDecimal(epd); } else { EpDouble epd1, epd2; int n1, n2; n1 = n / 2; n2 = n - n1; EpdPow2Decimal(n1, &epd1); EpdPow2Decimal(n2, &epd2); EpdMultiply3Decimal(&epd1, &epd2, epd); } } /**Function******************************************************************** Synopsis [Normalize an arbitrary precision double value.] Description [Normalize an arbitrary precision double value.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdNormalize(EpDouble *epd) { int exponent; if (IsNanOrInfDouble(epd->type.value)) { epd->exponent = 0; return; } exponent = EpdGetExponent(epd->type.value); if (exponent == EPD_MAX_BIN) return; exponent -= EPD_MAX_BIN; epd->type.bits.exponent = EPD_MAX_BIN; epd->exponent += exponent; } /**Function******************************************************************** Synopsis [Normalize an arbitrary precision double value.] Description [Normalize an arbitrary precision double value.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdNormalizeDecimal(EpDouble *epd) { int exponent; if (IsNanOrInfDouble(epd->type.value)) { epd->exponent = 0; return; } exponent = EpdGetExponentDecimal(epd->type.value); epd->type.value /= pow((double)10.0, (double)exponent); epd->exponent += exponent; } /**Function******************************************************************** Synopsis [Returns value and decimal exponent of EpDouble.] Description [Returns value and decimal exponent of EpDouble.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent) { EpDouble epd1, epd2; if (EpdIsNanOrInf(epd)) return; if (EpdIsZero(epd)) { *value = 0.0; *exponent = 0; return; } epd1.type.value = epd->type.value; epd1.exponent = 0; EpdPow2Decimal(epd->exponent, &epd2); EpdMultiply2Decimal(&epd1, &epd2); *value = epd1.type.value; *exponent = epd1.exponent; } /**Function******************************************************************** Synopsis [Returns the exponent value of a double.] Description [Returns the exponent value of a double.] SideEffects [] SeeAlso [] ******************************************************************************/ int EpdGetExponent(double value) { int exponent; EpDouble epd; epd.type.value = value; exponent = epd.type.bits.exponent; return(exponent); } /**Function******************************************************************** Synopsis [Returns the decimal exponent value of a double.] Description [Returns the decimal exponent value of a double.] SideEffects [] SeeAlso [] ******************************************************************************/ int EpdGetExponentDecimal(double value) { char *pos, str[24]; int exponent; sprintf(str, "%E", value); pos = strstr(str, "E"); sscanf(pos, "E%d", &exponent); return(exponent); } /**Function******************************************************************** Synopsis [Makes EpDouble Inf.] Description [Makes EpDouble Inf.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdMakeInf(EpDouble *epd, int sign) { epd->type.bits.mantissa1 = 0; epd->type.bits.mantissa0 = 0; epd->type.bits.exponent = EPD_EXP_INF; epd->type.bits.sign = sign; epd->exponent = 0; } /**Function******************************************************************** Synopsis [Makes EpDouble Zero.] Description [Makes EpDouble Zero.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdMakeZero(EpDouble *epd, int sign) { epd->type.bits.mantissa1 = 0; epd->type.bits.mantissa0 = 0; epd->type.bits.exponent = 0; epd->type.bits.sign = sign; epd->exponent = 0; } /**Function******************************************************************** Synopsis [Makes EpDouble NaN.] Description [Makes EpDouble NaN.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdMakeNan(EpDouble *epd) { epd->type.nan.mantissa1 = 0; epd->type.nan.mantissa0 = 0; epd->type.nan.quiet_bit = 1; epd->type.nan.exponent = EPD_EXP_INF; epd->type.nan.sign = 1; epd->exponent = 0; } /**Function******************************************************************** Synopsis [Copies a EpDouble struct.] Description [Copies a EpDouble struct.] SideEffects [] SeeAlso [] ******************************************************************************/ void EpdCopy(EpDouble *from, EpDouble *to) { to->type.value = from->type.value; to->exponent = from->exponent; } /**Function******************************************************************** Synopsis [Checks whether the value is Inf.] Description [Checks whether the value is Inf.] SideEffects [] SeeAlso [] ******************************************************************************/ int EpdIsInf(EpDouble *epd) { return(IsInfDouble(epd->type.value)); } /**Function******************************************************************** Synopsis [Checks whether the value is Zero.] Description [Checks whether the value is Zero.] SideEffects [] SeeAlso [] ******************************************************************************/ int EpdIsZero(EpDouble *epd) { if (epd->type.value == 0.0) return(1); else return(0); } /**Function******************************************************************** Synopsis [Checks whether the value is NaN.] Description [Checks whether the value is NaN.] SideEffects [] SeeAlso [] ******************************************************************************/ int EpdIsNan(EpDouble *epd) { return(IsNanDouble(epd->type.value)); } /**Function******************************************************************** Synopsis [Checks whether the value is NaN or Inf.] Description [Checks whether the value is NaN or Inf.] SideEffects [] SeeAlso [] ******************************************************************************/ int EpdIsNanOrInf(EpDouble *epd) { return(IsNanOrInfDouble(epd->type.value)); } /**Function******************************************************************** Synopsis [Checks whether the value is Inf.] Description [Checks whether the value is Inf.] SideEffects [] SeeAlso [] ******************************************************************************/ int IsInfDouble(double value) { EpType val; val.value = value; if (val.bits.exponent == EPD_EXP_INF && val.bits.mantissa0 == 0 && val.bits.mantissa1 == 0) { if (val.bits.sign == 0) return(1); else return(-1); } return(0); } /**Function******************************************************************** Synopsis [Checks whether the value is NaN.] Description [Checks whether the value is NaN.] SideEffects [] SeeAlso [] ******************************************************************************/ int IsNanDouble(double value) { EpType val; val.value = value; if (val.nan.exponent == EPD_EXP_INF && val.nan.sign == 1 && val.nan.quiet_bit == 1 && val.nan.mantissa0 == 0 && val.nan.mantissa1 == 0) { return(1); } return(0); } /**Function******************************************************************** Synopsis [Checks whether the value is NaN or Inf.] Description [Checks whether the value is NaN or Inf.] SideEffects [] SeeAlso [] ******************************************************************************/ int IsNanOrInfDouble(double value) { EpType val; val.value = value; if (val.nan.exponent == EPD_EXP_INF && val.nan.mantissa0 == 0 && val.nan.mantissa1 == 0 && (val.nan.sign == 1 || val.nan.quiet_bit == 0)) { return(1); } return(0); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/epd/epd.h000066400000000000000000000162321300674244400222620ustar00rootroot00000000000000/**CHeaderFile***************************************************************** FileName [epd.h] PackageName [epd] Synopsis [The University of Colorado extended double precision package.] Description [arithmetic functions with extended double precision.] SeeAlso [] Author [In-Ho Moon] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] Revision [$Id: epd.h,v 1.9 2004/08/13 18:20:30 fabio Exp $] ******************************************************************************/ #ifndef ABC__bdd__epd__epd_h #define ABC__bdd__epd__epd_h ABC_NAMESPACE_HEADER_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define EPD_MAX_BIN 1023 #define EPD_MAX_DEC 308 #define EPD_EXP_INF 0x7ff /*---------------------------------------------------------------------------*/ /* Structure declarations */ /*---------------------------------------------------------------------------*/ /**Struct********************************************************************** Synopsis [IEEE double struct.] Description [IEEE double struct.] SeeAlso [] ******************************************************************************/ #ifdef EPD_BIG_ENDIAN struct IeeeDoubleStruct { /* BIG_ENDIAN */ unsigned int sign: 1; unsigned int exponent: 11; unsigned int mantissa0: 20; unsigned int mantissa1: 32; }; #else struct IeeeDoubleStruct { /* LITTLE_ENDIAN */ unsigned int mantissa1: 32; unsigned int mantissa0: 20; unsigned int exponent: 11; unsigned int sign: 1; }; #endif /**Struct********************************************************************** Synopsis [IEEE double NaN struct.] Description [IEEE double NaN struct.] SeeAlso [] ******************************************************************************/ #ifdef EPD_BIG_ENDIAN struct IeeeNanStruct { /* BIG_ENDIAN */ unsigned int sign: 1; unsigned int exponent: 11; unsigned int quiet_bit: 1; unsigned int mantissa0: 19; unsigned int mantissa1: 32; }; #else struct IeeeNanStruct { /* LITTLE_ENDIAN */ unsigned int mantissa1: 32; unsigned int mantissa0: 19; unsigned int quiet_bit: 1; unsigned int exponent: 11; unsigned int sign: 1; }; #endif /**Struct********************************************************************** Synopsis [Extended precision double to keep very large value.] Description [Extended precision double to keep very large value.] SeeAlso [] ******************************************************************************/ union EpTypeUnion { double value; struct IeeeDoubleStruct bits; struct IeeeNanStruct nan; }; struct EpDoubleStruct { union EpTypeUnion type; int exponent; }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ typedef struct EpDoubleStruct EpDouble; typedef struct IeeeDoubleStruct IeeeDouble; typedef struct IeeeNanStruct IeeeNan; typedef union EpTypeUnion EpType; /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Function prototypes */ /*---------------------------------------------------------------------------*/ extern EpDouble *EpdAlloc(void); extern int EpdCmp(const char *key1, const char *key2); extern void EpdFree(EpDouble *epd); extern void EpdGetString(EpDouble *epd, char *str); extern void EpdConvert(double value, EpDouble *epd); extern void EpdMultiply(EpDouble *epd1, double value); extern void EpdMultiply2(EpDouble *epd1, EpDouble *epd2); extern void EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2); extern void EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); extern void EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); extern void EpdDivide(EpDouble *epd1, double value); extern void EpdDivide2(EpDouble *epd1, EpDouble *epd2); extern void EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); extern void EpdAdd(EpDouble *epd1, double value); extern void EpdAdd2(EpDouble *epd1, EpDouble *epd2); extern void EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); extern void EpdSubtract(EpDouble *epd1, double value); extern void EpdSubtract2(EpDouble *epd1, EpDouble *epd2); extern void EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); extern void EpdPow2(int n, EpDouble *epd); extern void EpdPow2Decimal(int n, EpDouble *epd); extern void EpdNormalize(EpDouble *epd); extern void EpdNormalizeDecimal(EpDouble *epd); extern void EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent); extern int EpdGetExponent(double value); extern int EpdGetExponentDecimal(double value); extern void EpdMakeInf(EpDouble *epd, int sign); extern void EpdMakeZero(EpDouble *epd, int sign); extern void EpdMakeNan(EpDouble *epd); extern void EpdCopy(EpDouble *from, EpDouble *to); extern int EpdIsInf(EpDouble *epd); extern int EpdIsZero(EpDouble *epd); extern int EpdIsNan(EpDouble *epd); extern int EpdIsNanOrInf(EpDouble *epd); extern int IsInfDouble(double value); extern int IsNanDouble(double value); extern int IsNanOrInfDouble(double value); /**AutomaticEnd***************************************************************/ ABC_NAMESPACE_HEADER_END #endif /* _EPD */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/epd/module.make000066400000000000000000000000321300674244400234540ustar00rootroot00000000000000SRC += src/bdd/epd/epd.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/000077500000000000000000000000001300674244400220525ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBdd.h000066400000000000000000000417631300674244400237730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBdd.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Various reusable software utilities.] Description [This library contains a number of operators and traversal routines developed to extend the functionality of CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/) To compile your code with the library, #include "extra.h" in your source files and link your project to CUDD and this library. Use the library at your own risk and with caution. Note that debugging of some operators still continues.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraBdd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__extra__extra_bdd_h #define ABC__misc__extra__extra_bdd_h #ifdef _WIN32 #define inline __inline // compatible with MS VS 6.0 #endif /*---------------------------------------------------------------------------*/ /* Nested includes */ /*---------------------------------------------------------------------------*/ #include #include #include #include #include "misc/st/st.h" #include "bdd/cudd/cuddInt.h" #include "misc/extra/extra.h" ABC_NAMESPACE_HEADER_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /* constants of the manager */ #define b0 Cudd_Not((dd)->one) #define b1 (dd)->one #define z0 (dd)->zero #define z1 (dd)->one #define a0 (dd)->zero #define a1 (dd)->one // hash key macros #define hashKey1(a,TSIZE) \ ((ABC_PTRUINT_T)(a) % TSIZE) #define hashKey2(a,b,TSIZE) \ (((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * DD_P1) % TSIZE) #define hashKey3(a,b,c,TSIZE) \ (((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 ) % TSIZE) #define hashKey4(a,b,c,d,TSIZE) \ ((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ (ABC_PTRUINT_T)(d)) * DD_P3) % TSIZE) #define hashKey5(a,b,c,d,e,TSIZE) \ (((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ (ABC_PTRUINT_T)(d)) * DD_P3 + (ABC_PTRUINT_T)(e)) * DD_P1) % TSIZE) /*===========================================================================*/ /* Various Utilities */ /*===========================================================================*/ /*=== extraBddAuto.c ========================================================*/ extern DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ); extern DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); extern DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); extern DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); extern DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); extern DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); extern DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); extern DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); extern DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); extern DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ); extern DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); extern DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); extern DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); extern DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); extern DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); extern DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); extern DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); extern DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); extern DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ); extern DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ); /*=== extraBddCas.c =============================================================*/ /* performs the binary encoding of the set of function using the given vars */ extern DdNode * Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, int nFuncs, DdNode ** pbVars, int nVars ); /* solves the column encoding problem using a sophisticated method */ extern DdNode * Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, int nColumns, DdNode * bVarsCol, DdNode ** pCVars, int nMulti, int * pSimple ); /* collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root */ extern st__table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ); /* collects the nodes under the cut starting from the given set of ADD nodes */ extern int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ); /* find the profile of a DD (the number of edges crossing each level) */ extern int Extra_ProfileWidth( DdManager * dd, DdNode * F, int * Profile, int CutLevel ); /*=== extraBddImage.c ================================================================*/ typedef struct Extra_ImageTree_t_ Extra_ImageTree_t; extern Extra_ImageTree_t * Extra_bddImageStart( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars, int fVerbose ); extern DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ); extern void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree ); extern DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree ); typedef struct Extra_ImageTree2_t_ Extra_ImageTree2_t; extern Extra_ImageTree2_t * Extra_bddImageStart2( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars, int fVerbose ); extern DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare ); extern void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree ); extern DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ); /*=== extraBddMisc.c ========================================================*/ extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ); extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int nVars ); extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag ); extern void Extra_StopManager( DdManager * dd ); extern void Extra_bddPrint( DdManager * dd, DdNode * F ); extern void Extra_bddPrintSupport( DdManager * dd, DdNode * F ); extern void extraDecomposeCover( DdManager* dd, DdNode* zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 ); extern int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ); extern int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ); extern int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ); extern int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ); extern int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ); extern int * Extra_SupportArray( DdManager * dd, DdNode * F, int * support ); extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support ); extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ); extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ); extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ); extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ); extern int Extra_bddIsVar( DdNode * bFunc ); extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ); extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ); extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ); extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ); extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ); extern DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ); extern DdNode * Extra_bddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); extern DdNode * extraBddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); extern int Extra_bddVarIsInCube( DdNode * bCube, int iVar ); extern DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); extern int Extra_bddCountCubes( DdManager * dd, DdNode ** pFuncs, int nFuncs, int fMode, int nLimit, int * pGuide ); extern void Extra_zddDumpPla( DdManager * dd, DdNode * zCover, int nVars, char * pFileName ); #ifndef ABC_PRB #define ABC_PRB(dd,f) printf("%s = ", #f); Extra_bddPrint(dd,f); printf("\n") #endif /*=== extraBddKmap.c ================================================================*/ /* displays the Karnaugh Map of a function */ extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames ); /* displays the Karnaugh Map of a relation */ extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars ); /*=== extraBddSymm.c =================================================================*/ typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t; struct Extra_SymmInfo_t_ { int nVars; // the number of variables in the support int nVarsMax; // the number of variables in the DD manager int nSymms; // the number of pair-wise symmetries int nNodes; // the number of nodes in a ZDD (if applicable) int * pVars; // the list of all variables present in the support char ** pSymms; // the symmetry information }; /* computes the classical symmetry information for the function - recursive */ extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc ); /* computes the classical symmetry information for the function - using naive approach */ extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ); extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); /* allocates the data structure */ extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ); /* deallocates the data structure */ extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * ); /* print the contents the data structure */ extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * ); /* converts the ZDD into the Extra_SymmInfo_t structure */ extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars ); /* computes the classical symmetry information as a ZDD */ extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); /* returns a singleton-set ZDD containing all variables that are symmetric with the given one */ extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); /* converts a set of variables into a set of singleton subsets */ extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars ); extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars ); /* filters the set of variables using the support of the function */ extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); /* checks the possibility that the two vars are symmetric */ extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars ); /* build the set of all tuples of K variables out of N from the BDD cube */ extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN ); extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN ); /* selects one subset from a ZDD representing the set of subsets */ extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS ); extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ); /*=== extraBddUnate.c =================================================================*/ extern DdNode * Extra_bddAndTime( DdManager * dd, DdNode * f, DdNode * g, int TimeOut ); extern DdNode * Extra_bddAndAbstractTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int TimeOut ); extern DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut ); /*=== extraBddUnate.c =================================================================*/ typedef struct Extra_UnateVar_t_ Extra_UnateVar_t; struct Extra_UnateVar_t_ { unsigned iVar : 30; // index of the variable unsigned Pos : 1; // 1 if positive unate unsigned Neg : 1; // 1 if negative unate }; typedef struct Extra_UnateInfo_t_ Extra_UnateInfo_t; struct Extra_UnateInfo_t_ { int nVars; // the number of variables in the support int nVarsMax; // the number of variables in the DD manager int nUnate; // the number of unate variables Extra_UnateVar_t * pVars; // the array of variables present in the support }; /* allocates the data structure */ extern Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ); /* deallocates the data structure */ extern void Extra_UnateInfoDissolve( Extra_UnateInfo_t * ); /* print the contents the data structure */ extern void Extra_UnateInfoPrint( Extra_UnateInfo_t * ); /* converts the ZDD into the Extra_SymmInfo_t structure */ extern Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zUnate, DdNode * bVars ); /* naive check of unateness of one variable */ extern int Extra_bddCheckUnateNaive( DdManager * dd, DdNode * bF, int iVar ); /* computes the unateness information for the function */ extern Extra_UnateInfo_t * Extra_UnateComputeFast( DdManager * dd, DdNode * bFunc ); extern Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ); /* computes the classical symmetry information as a ZDD */ extern DdNode * Extra_zddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); extern DdNode * extraZddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); /* converts a set of variables into a set of singleton subsets */ extern DdNode * Extra_zddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); extern DdNode * extraZddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); /**AutomaticEnd***************************************************************/ ABC_NAMESPACE_HEADER_END #endif /* __EXTRA_H__ */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddAuto.c000066400000000000000000001073271300674244400246160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddAuto.c] PackageName [extra] Synopsis [Computation of autosymmetries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - September 1, 2003.] Revision [$Id: extraBddAuto.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] ***********************************************************************/ #include "extraBdd.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /* LinearSpace(f) = Space(f,f) Space(f,g) { if ( f = const ) { if ( f = g ) return 1; else return 0; } if ( g = const ) return 0; return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx'); } Equations(s) = Pos(s) + Neg(s); Pos(s) { if ( s = 0 ) return 1; if ( s = 1 ) return 0; if ( sx'= 0 ) return Pos(sx) + x; if ( sx = 0 ) return Pos(sx'); return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)]; } Neg(s) { if ( s = 0 ) return 1; if ( s = 1 ) return 0; if ( sx'= 0 ) return Neg(sx); if ( sx = 0 ) return Neg(sx') + x; return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)]; } SpaceP(A) { if ( A = 0 ) return 1; if ( A = 1 ) return 1; return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax); } SpaceN(A) { if ( A = 0 ) return 1; if ( A = 1 ) return 0; return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax); } LinInd(A) { if ( A = const ) return 1; if ( !LinInd(Ax') ) return 0; if ( !LinInd(Ax) ) return 0; if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0; if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0; return 1; } LinSumOdd(A) { if ( A = 0 ) return 0; // Odd0 ---e-- Odd1 if ( A = 1 ) return 1; // \ o Odd0 = LinSumOdd(Ax'); // x is absent // \ Even0 = LinSumEven(Ax'); // x is absent // / o Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1 Even1 = LinSumEven(Ax); // x is absent return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)]; } LinSumEven(A) { if ( A = 0 ) return 0; if ( A = 1 ) return 0; Odd0 = LinSumOdd(Ax'); // x is absent Even0 = LinSumEven(Ax'); // x is absent Odd1 = LinSumOdd(Ax); // x is present Even1 = LinSumEven(Ax); // x is absent return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)]; } */ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ) { int * pSupport; int * pPermute; int * pPermuteBack; DdNode ** pCompose; DdNode * bCube, * bTemp; DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift; int nSupp, Counter; int i, lev; // get the support pSupport = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) ); Extra_SupportArray( dd, bFunc, pSupport ); nSupp = 0; for ( i = 0; i < dd->size; i++ ) if ( pSupport[i] ) nSupp++; // make sure the manager has enough variables if ( 2*nSupp > dd->size ) { printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" ); fflush( stdout ); ABC_FREE( pSupport ); return NULL; } // create the permutation arrays pPermute = ABC_ALLOC( int, dd->size ); pPermuteBack = ABC_ALLOC( int, dd->size ); pCompose = ABC_ALLOC( DdNode *, dd->size ); for ( i = 0; i < dd->size; i++ ) { pPermute[i] = i; pPermuteBack[i] = i; pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] ); } // remap the function in such a way that the variables are interleaved Counter = 0; bCube = b1; Cudd_Ref( bCube ); for ( lev = 0; lev < dd->size; lev++ ) if ( pSupport[ dd->invperm[lev] ] ) { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter; pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter]; // var from level 2*Counter+1 should go back to the place of this var pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev]; // the permutation should be defined in such a way that variable // on level 2*Counter is replaced by an EXOR of itself and var on the next level Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] ); pCompose[ dd->invperm[2*Counter] ] = Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] ); Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] ); // add this variable to the cube bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); // increment the counter Counter ++; } // permute the functions bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 ); // compose to gate the function depending on both vars bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 ); // gate the vector space // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] ) bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift ); bSpaceShift = Cudd_Not( bSpaceShift ); // permute the space back into the original mapping bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace ); Cudd_RecursiveDeref( dd, bFunc1 ); Cudd_RecursiveDeref( dd, bFunc2 ); Cudd_RecursiveDeref( dd, bSpaceShift ); Cudd_RecursiveDeref( dd, bCube ); for ( i = 0; i < dd->size; i++ ) Cudd_RecursiveDeref( dd, pCompose[i] ); ABC_FREE( pPermute ); ABC_FREE( pPermuteBack ); ABC_FREE( pCompose ); ABC_FREE( pSupport ); Cudd_Deref( bSpace ); return bSpace; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) { DdNode * bRes; do { dd->reordered = 0; bRes = extraBddSpaceFromFunction( dd, bF, bG ); } while (dd->reordered == 1); return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ) { DdNode * bRes; do { dd->reordered = 0; bRes = extraBddSpaceFromFunctionPos( dd, bFunc ); } while (dd->reordered == 1); return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ) { DdNode * bRes; do { dd->reordered = 0; bRes = extraBddSpaceFromFunctionNeg( dd, bFunc ); } while (dd->reordered == 1); return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ) { DdNode * bRes; do { dd->reordered = 0; bRes = extraBddSpaceCanonVars( dd, bSpace ); } while (dd->reordered == 1); return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ) { DdNode * bNegCube; DdNode * bResult; bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars ); Cudd_Ref( bNegCube ); bResult = Cudd_Cofactor( dd, bFunc, bNegCube ); Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bNegCube ); Cudd_Deref( bResult ); return bResult; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ) { DdNode * zRes; DdNode * zEquPos; DdNode * zEquNeg; zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace ); Cudd_Ref( zEquPos ); zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace ); Cudd_Ref( zEquNeg ); zRes = Cudd_zddUnion( dd, zEquPos, zEquNeg ); Cudd_Ref( zRes ); Cudd_RecursiveDerefZdd( dd, zEquPos ); Cudd_RecursiveDerefZdd( dd, zEquNeg ); Cudd_Deref( zRes ); return zRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ) { DdNode * zRes; do { dd->reordered = 0; zRes = extraBddSpaceEquationsPos( dd, bSpace ); } while (dd->reordered == 1); return zRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ) { DdNode * zRes; do { dd->reordered = 0; zRes = extraBddSpaceEquationsNeg( dd, bSpace ); } while (dd->reordered == 1); return zRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) { DdNode * bRes; do { dd->reordered = 0; bRes = extraBddSpaceFromMatrixPos( dd, zA ); } while (dd->reordered == 1); return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) { DdNode * bRes; do { dd->reordered = 0; bRes = extraBddSpaceFromMatrixNeg( dd, zA ); } while (dd->reordered == 1); return bRes; } /**Function************************************************************* Synopsis [Counts the number of literals in one combination.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_zddLitCountComb( DdManager * dd, DdNode * zComb ) { int Counter; if ( zComb == z0 ) return 0; Counter = 0; for ( ; zComb != z1; zComb = cuddT(zComb) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [] Description [Returns the array of ZDDs with the number equal to the number of vars in the DD manager. If the given var is non-canonical, this array contains the referenced ZDD representing literals in the corresponding EXOR equation.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ) { DdNode ** pzRes; int * pVarsNonCan; DdNode * zEquRem; int iVarNonCan; DdNode * zExor, * zTemp; // get the set of non-canonical variables pVarsNonCan = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) ); Extra_SupportArray( dd, bFuncRed, pVarsNonCan ); // allocate storage for the EXOR sets pzRes = ABC_ALLOC( DdNode *, dd->size ); memset( pzRes, 0, sizeof(DdNode *) * dd->size ); // go through all the equations zEquRem = zEquations; Cudd_Ref( zEquRem ); while ( zEquRem != z0 ) { // extract one product zExor = Extra_zddSelectOneSubset( dd, zEquRem ); Cudd_Ref( zExor ); // remove it from the set zEquRem = Cudd_zddDiff( dd, zTemp = zEquRem, zExor ); Cudd_Ref( zEquRem ); Cudd_RecursiveDerefZdd( dd, zTemp ); // locate the non-canonical variable iVarNonCan = -1; for ( zTemp = zExor; zTemp != z1; zTemp = cuddT(zTemp) ) { if ( pVarsNonCan[zTemp->index/2] == 1 ) { assert( iVarNonCan == -1 ); iVarNonCan = zTemp->index/2; } } assert( iVarNonCan != -1 ); if ( Extra_zddLitCountComb( dd, zExor ) > 1 ) pzRes[ iVarNonCan ] = zExor; // takes ref else Cudd_RecursiveDerefZdd( dd, zExor ); } Cudd_RecursiveDerefZdd( dd, zEquRem ); ABC_FREE( pVarsNonCan ); return pzRes; } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the recursive steps of Extra_bddSpaceFromFunction.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) { DdNode * bRes; DdNode * bFR, * bGR; bFR = Cudd_Regular( bF ); bGR = Cudd_Regular( bG ); if ( cuddIsConstant(bFR) ) { if ( bF == bG ) return b1; else return b0; } if ( cuddIsConstant(bGR) ) return b0; // both bFunc and bCore are not constants // the operation is commutative - normalize the problem if ( (unsigned)(ABC_PTRUINT_T)bF > (unsigned)(ABC_PTRUINT_T)bG ) return extraBddSpaceFromFunction(dd, bG, bF); if ( (bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG)) ) return bRes; else { DdNode * bF0, * bF1; DdNode * bG0, * bG1; DdNode * bTemp1, * bTemp2; DdNode * bRes0, * bRes1; int LevelF, LevelG; int index; LevelF = dd->perm[bFR->index]; LevelG = dd->perm[bGR->index]; if ( LevelF <= LevelG ) { index = dd->invperm[LevelF]; if ( bFR != bF ) { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } } else { index = dd->invperm[LevelG]; bF0 = bF1 = bF; } if ( LevelG <= LevelF ) { if ( bGR != bG ) { bG0 = Cudd_Not( cuddE(bGR) ); bG1 = Cudd_Not( cuddT(bGR) ); } else { bG0 = cuddE(bGR); bG1 = cuddT(bGR); } } else bG0 = bG1 = bG; bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 ); if ( bTemp1 == NULL ) return NULL; cuddRef( bTemp1 ); bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 ); if ( bTemp2 == NULL ) { Cudd_RecursiveDeref( dd, bTemp1 ); return NULL; } cuddRef( bTemp2 ); bRes0 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); if ( bRes0 == NULL ) { Cudd_RecursiveDeref( dd, bTemp1 ); Cudd_RecursiveDeref( dd, bTemp2 ); return NULL; } cuddRef( bRes0 ); Cudd_RecursiveDeref( dd, bTemp1 ); Cudd_RecursiveDeref( dd, bTemp2 ); bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG1 ); if ( bTemp1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); return NULL; } cuddRef( bTemp1 ); bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG0 ); if ( bTemp2 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bTemp1 ); return NULL; } cuddRef( bTemp2 ); bRes1 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); if ( bRes1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bTemp1 ); Cudd_RecursiveDeref( dd, bTemp2 ); return NULL; } cuddRef( bRes1 ); Cudd_RecursiveDeref( dd, bTemp1 ); Cudd_RecursiveDeref( dd, bTemp2 ); // consider the case when Res0 and Res1 are the same node if ( bRes0 == bRes1 ) bRes = bRes1; // consider the case when Res1 is complemented else if ( Cudd_IsComplement(bRes1) ) { bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0)); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } bRes = Cudd_Not(bRes); } else { bRes = cuddUniqueInter( dd, index, bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } } cuddDeref( bRes0 ); cuddDeref( bRes1 ); // insert the result into cache cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes); return bRes; } } /* end of extraBddSpaceFromFunction */ /**Function************************************************************* Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bF ) { DdNode * bRes, * bFR; statLine( dd ); bFR = Cudd_Regular(bF); if ( cuddIsConstant(bFR) ) return b1; if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionPos, bF)) ) return bRes; else { DdNode * bF0, * bF1; DdNode * bPos0, * bPos1; DdNode * bNeg0, * bNeg1; DdNode * bRes0, * bRes1; if ( bFR != bF ) // bF is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } bPos0 = extraBddSpaceFromFunctionPos( dd, bF0 ); if ( bPos0 == NULL ) return NULL; cuddRef( bPos0 ); bPos1 = extraBddSpaceFromFunctionPos( dd, bF1 ); if ( bPos1 == NULL ) { Cudd_RecursiveDeref( dd, bPos0 ); return NULL; } cuddRef( bPos1 ); bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); if ( bRes0 == NULL ) { Cudd_RecursiveDeref( dd, bPos0 ); Cudd_RecursiveDeref( dd, bPos1 ); return NULL; } cuddRef( bRes0 ); Cudd_RecursiveDeref( dd, bPos0 ); Cudd_RecursiveDeref( dd, bPos1 ); bNeg0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); if ( bNeg0 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); return NULL; } cuddRef( bNeg0 ); bNeg1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); if ( bNeg1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bNeg0 ); return NULL; } cuddRef( bNeg1 ); bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); if ( bRes1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bNeg0 ); Cudd_RecursiveDeref( dd, bNeg1 ); return NULL; } cuddRef( bRes1 ); Cudd_RecursiveDeref( dd, bNeg0 ); Cudd_RecursiveDeref( dd, bNeg1 ); // consider the case when Res0 and Res1 are the same node if ( bRes0 == bRes1 ) bRes = bRes1; // consider the case when Res1 is complemented else if ( Cudd_IsComplement(bRes1) ) { bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } bRes = Cudd_Not(bRes); } else { bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } } cuddDeref( bRes0 ); cuddDeref( bRes1 ); cuddCacheInsert1( dd, extraBddSpaceFromFunctionPos, bF, bRes ); return bRes; } } /**Function************************************************************* Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF ) { DdNode * bRes, * bFR; statLine( dd ); bFR = Cudd_Regular(bF); if ( cuddIsConstant(bFR) ) return b0; if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF)) ) return bRes; else { DdNode * bF0, * bF1; DdNode * bPos0, * bPos1; DdNode * bNeg0, * bNeg1; DdNode * bRes0, * bRes1; if ( bFR != bF ) // bF is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } bPos0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); if ( bPos0 == NULL ) return NULL; cuddRef( bPos0 ); bPos1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); if ( bPos1 == NULL ) { Cudd_RecursiveDeref( dd, bPos0 ); return NULL; } cuddRef( bPos1 ); bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); if ( bRes0 == NULL ) { Cudd_RecursiveDeref( dd, bPos0 ); Cudd_RecursiveDeref( dd, bPos1 ); return NULL; } cuddRef( bRes0 ); Cudd_RecursiveDeref( dd, bPos0 ); Cudd_RecursiveDeref( dd, bPos1 ); bNeg0 = extraBddSpaceFromFunctionPos( dd, bF0 ); if ( bNeg0 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); return NULL; } cuddRef( bNeg0 ); bNeg1 = extraBddSpaceFromFunctionPos( dd, bF1 ); if ( bNeg1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bNeg0 ); return NULL; } cuddRef( bNeg1 ); bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); if ( bRes1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bNeg0 ); Cudd_RecursiveDeref( dd, bNeg1 ); return NULL; } cuddRef( bRes1 ); Cudd_RecursiveDeref( dd, bNeg0 ); Cudd_RecursiveDeref( dd, bNeg1 ); // consider the case when Res0 and Res1 are the same node if ( bRes0 == bRes1 ) bRes = bRes1; // consider the case when Res1 is complemented else if ( Cudd_IsComplement(bRes1) ) { bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } bRes = Cudd_Not(bRes); } else { bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } } cuddDeref( bRes0 ); cuddDeref( bRes1 ); cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes ); return bRes; } } /**Function************************************************************* Synopsis [Performs the recursive step of Extra_bddSpaceCanonVars().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF ) { DdNode * bRes, * bFR; statLine( dd ); bFR = Cudd_Regular(bF); if ( cuddIsConstant(bFR) ) return bF; if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF)) ) return bRes; else { DdNode * bF0, * bF1; DdNode * bRes, * bRes0; if ( bFR != bF ) // bF is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } if ( bF0 == b0 ) { bRes = extraBddSpaceCanonVars( dd, bF1 ); if ( bRes == NULL ) return NULL; } else if ( bF1 == b0 ) { bRes = extraBddSpaceCanonVars( dd, bF0 ); if ( bRes == NULL ) return NULL; } else { bRes0 = extraBddSpaceCanonVars( dd, bF0 ); if ( bRes0 == NULL ) return NULL; cuddRef( bRes0 ); bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref( dd,bRes0 ); return NULL; } cuddDeref( bRes0 ); } cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes ); return bRes; } } /**Function************************************************************* Synopsis [Performs the recursive step of Extra_bddSpaceEquationsPos().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bF ) { DdNode * zRes; statLine( dd ); if ( bF == b0 ) return z1; if ( bF == b1 ) return z0; if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsPos, bF)) ) return zRes; else { DdNode * bFR, * bF0, * bF1; DdNode * zPos0, * zPos1, * zNeg1; DdNode * zRes, * zRes0, * zRes1; bFR = Cudd_Regular(bF); if ( bFR != bF ) // bF is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } if ( bF0 == b0 ) { zRes1 = extraBddSpaceEquationsPos( dd, bF1 ); if ( zRes1 == NULL ) return NULL; cuddRef( zRes1 ); // add the current element to the set zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes1 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes1); return NULL; } cuddDeref( zRes1 ); } else if ( bF1 == b0 ) { zRes = extraBddSpaceEquationsPos( dd, bF0 ); if ( zRes == NULL ) return NULL; } else { zPos0 = extraBddSpaceEquationsPos( dd, bF0 ); if ( zPos0 == NULL ) return NULL; cuddRef( zPos0 ); zPos1 = extraBddSpaceEquationsPos( dd, bF1 ); if ( zPos1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zPos0); return NULL; } cuddRef( zPos1 ); zNeg1 = extraBddSpaceEquationsNeg( dd, bF1 ); if ( zNeg1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zNeg1 ); zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); if ( zRes0 == NULL ) { Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zRes0 ); zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); if ( zRes1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes0); Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zRes1 ); Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); // only zRes0 and zRes1 are refed at this point zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes0); Cudd_RecursiveDerefZdd(dd, zRes1); return NULL; } cuddDeref( zRes0 ); cuddDeref( zRes1 ); } cuddCacheInsert1( dd, extraBddSpaceEquationsPos, bF, zRes ); return zRes; } } /**Function************************************************************* Synopsis [Performs the recursive step of Extra_bddSpaceEquationsNev().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF ) { DdNode * zRes; statLine( dd ); if ( bF == b0 ) return z1; if ( bF == b1 ) return z0; if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF)) ) return zRes; else { DdNode * bFR, * bF0, * bF1; DdNode * zPos0, * zPos1, * zNeg1; DdNode * zRes, * zRes0, * zRes1; bFR = Cudd_Regular(bF); if ( bFR != bF ) // bF is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } if ( bF0 == b0 ) { zRes = extraBddSpaceEquationsNeg( dd, bF1 ); if ( zRes == NULL ) return NULL; } else if ( bF1 == b0 ) { zRes0 = extraBddSpaceEquationsNeg( dd, bF0 ); if ( zRes0 == NULL ) return NULL; cuddRef( zRes0 ); // add the current element to the set zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes0); return NULL; } cuddDeref( zRes0 ); } else { zPos0 = extraBddSpaceEquationsNeg( dd, bF0 ); if ( zPos0 == NULL ) return NULL; cuddRef( zPos0 ); zPos1 = extraBddSpaceEquationsNeg( dd, bF1 ); if ( zPos1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zPos0); return NULL; } cuddRef( zPos1 ); zNeg1 = extraBddSpaceEquationsPos( dd, bF1 ); if ( zNeg1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zNeg1 ); zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); if ( zRes0 == NULL ) { Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zRes0 ); zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); if ( zRes1 == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes0); Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); return NULL; } cuddRef( zRes1 ); Cudd_RecursiveDerefZdd(dd, zNeg1); Cudd_RecursiveDerefZdd(dd, zPos0); Cudd_RecursiveDerefZdd(dd, zPos1); // only zRes0 and zRes1 are refed at this point zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd(dd, zRes0); Cudd_RecursiveDerefZdd(dd, zRes1); return NULL; } cuddDeref( zRes0 ); cuddDeref( zRes1 ); } cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes ); return zRes; } } /**Function************************************************************* Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) { DdNode * bRes; statLine( dd ); if ( zA == z0 ) return b1; if ( zA == z1 ) return b1; if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixPos, zA)) ) return bRes; else { DdNode * bP0, * bP1; DdNode * bN0, * bN1; DdNode * bRes0, * bRes1; bP0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); if ( bP0 == NULL ) return NULL; cuddRef( bP0 ); bP1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); if ( bP1 == NULL ) { Cudd_RecursiveDeref( dd, bP0 ); return NULL; } cuddRef( bP1 ); bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); if ( bRes0 == NULL ) { Cudd_RecursiveDeref( dd, bP0 ); Cudd_RecursiveDeref( dd, bP1 ); return NULL; } cuddRef( bRes0 ); Cudd_RecursiveDeref( dd, bP0 ); Cudd_RecursiveDeref( dd, bP1 ); bN0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); if ( bN0 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); return NULL; } cuddRef( bN0 ); bN1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); if ( bN1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bN0 ); return NULL; } cuddRef( bN1 ); bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); if ( bRes1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bN0 ); Cudd_RecursiveDeref( dd, bN1 ); return NULL; } cuddRef( bRes1 ); Cudd_RecursiveDeref( dd, bN0 ); Cudd_RecursiveDeref( dd, bN1 ); // consider the case when Res0 and Res1 are the same node if ( bRes0 == bRes1 ) bRes = bRes1; // consider the case when Res1 is complemented else if ( Cudd_IsComplement(bRes1) ) { bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } bRes = Cudd_Not(bRes); } else { bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } } cuddDeref( bRes0 ); cuddDeref( bRes1 ); cuddCacheInsert1( dd, extraBddSpaceFromMatrixPos, zA, bRes ); return bRes; } } /**Function************************************************************* Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) { DdNode * bRes; statLine( dd ); if ( zA == z0 ) return b1; if ( zA == z1 ) return b0; if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA)) ) return bRes; else { DdNode * bP0, * bP1; DdNode * bN0, * bN1; DdNode * bRes0, * bRes1; bP0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); if ( bP0 == NULL ) return NULL; cuddRef( bP0 ); bP1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); if ( bP1 == NULL ) { Cudd_RecursiveDeref( dd, bP0 ); return NULL; } cuddRef( bP1 ); bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); if ( bRes0 == NULL ) { Cudd_RecursiveDeref( dd, bP0 ); Cudd_RecursiveDeref( dd, bP1 ); return NULL; } cuddRef( bRes0 ); Cudd_RecursiveDeref( dd, bP0 ); Cudd_RecursiveDeref( dd, bP1 ); bN0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); if ( bN0 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); return NULL; } cuddRef( bN0 ); bN1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); if ( bN1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bN0 ); return NULL; } cuddRef( bN1 ); bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); if ( bRes1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bN0 ); Cudd_RecursiveDeref( dd, bN1 ); return NULL; } cuddRef( bRes1 ); Cudd_RecursiveDeref( dd, bN0 ); Cudd_RecursiveDeref( dd, bN1 ); // consider the case when Res0 and Res1 are the same node if ( bRes0 == bRes1 ) bRes = bRes1; // consider the case when Res1 is complemented else if ( Cudd_IsComplement(bRes1) ) { bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } bRes = Cudd_Not(bRes); } else { bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } } cuddDeref( bRes0 ); cuddDeref( bRes1 ); cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes ); return bRes; } } /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddCas.c000066400000000000000000001264211300674244400244100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddCas.c] PackageName [extra] Synopsis [Procedures related to LUT cascade synthesis.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - September 1, 2003.] Revision [$Id: extraBddCas.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] ***********************************************************************/ #include "extraBdd.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ // the table to store cofactor operations #define _TABLESIZE_COF 51113 typedef struct { unsigned Sign; DdNode * Arg1; } _HashEntry_cof; _HashEntry_cof HHTable1[_TABLESIZE_COF]; // the table to store the result of computation of the number of minterms #define _TABLESIZE_MINT 15113 typedef struct { DdNode * Arg1; unsigned Arg2; unsigned Res; } _HashEntry_mint; _HashEntry_mint HHTable2[_TABLESIZE_MINT]; typedef struct { int nEdges; // the number of in-coming edges of the node DdNode * bSum; // the sum of paths of the incoming edges } traventry; // the signature used for hashing static unsigned s_Signature = 1; static int s_CutLevel = 0; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ // because the proposed solution to the optimal encoding problem has exponential complexity // we limit the depth of the branch and bound procedure to 5 levels static int s_MaxDepth = 5; static int s_nVarsBest; // the number of vars in the best ordering static int s_VarOrderBest[32]; // storing the best ordering of vars in the "simple encoding" static int s_VarOrderCur[32]; // storing the current ordering of vars // the place to store the supports of the encoded function static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth static DdNode * s_Encoded; // this is the original function static DdNode * s_VarAll; // the set of all column variables static int s_MultiStart; // the total number of encoding variables used // the array field now stores the supports static DdNode ** s_pbTemp; // the temporary storage for the columns static int s_BackTracks; static int s_BackTrackLimit = 100; static DdNode * s_Terminal; // the terminal value for counting minterms static int s_EncodingVarsLevel; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ); static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ); // functions called from EvaluateEncodings_rec() static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ); static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ); static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited ); static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes ); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the binary encoding of the set of function using the given vars.] Description [Performs a straight binary encoding of the set of functions using the variable cubes formed from the given set of variables. ] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, // pbFuncs is the array of columns to be encoded int nFuncs, // nFuncs is the number of columns in the array DdNode ** pbVars, // pbVars is the array of variables to use for the codes int nVars ) // nVars is the column multiplicity, [log2(nFuncs)] { int i; DdNode * bResult; DdNode * bCube, * bTemp, * bProd; assert( nVars >= Abc_Base2Log(nFuncs) ); bResult = b0; Cudd_Ref( bResult ); for ( i = 0; i < nFuncs; i++ ) { bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); bProd = Cudd_bddAnd( dd, bCube, pbFuncs[i] ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bCube ); bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } Cudd_Deref( bResult ); return bResult; } /* end of Extra_bddEncodingBinary */ /**Function******************************************************************** Synopsis [Solves the column encoding problem using a sophisticated method.] Description [The encoding is based on the idea of deriving functions which depend on only one variable, which corresponds to the case of non-disjoint decompostion. It is assumed that the variables pCVars are ordered below the variables representing the solumns, and the first variable pCVars[0] is the topmost one.] SideEffects [] SeeAlso [Extra_bddEncodingBinary] ******************************************************************************/ DdNode * Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, // pbColumns is the array of columns to be encoded; int nColumns, // nColumns is the number of columns in the array DdNode * bVarsCol, // bVarsCol is the cube of variables on which the columns depend DdNode ** pCVars, // pCVars is the array of variables to use for the codes int nMulti, // nMulti is the column multiplicity, [log2(nColumns)] int * pSimple ) // pSimple gets the number of code variables taken from the input varibles without change { DdNode * bEncoded, * bResult; int nVarsCol = Cudd_SupportSize(dd,bVarsCol); abctime clk; // cannot work with more that 32-bit codes assert( nMulti < 32 ); // perform the preliminary encoding using the straight binary code bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti ); Cudd_Ref( bEncoded ); //printf( "Node count = %d", Cudd_DagSize(bEncoded) ); // set the backgroup value for counting minterms s_Terminal = b0; // set the level of the encoding variables s_EncodingVarsLevel = dd->invperm[pCVars[0]->index]; // the current number of backtracks s_BackTracks = 0; // the variables that are cofactored on the topmost level where everything starts (no vars) s_Field[0][0] = b1; // the size of the best set of "simple" encoding variables found so far s_nVarsBest = 0; // set the relation to be accessible to traversal procedures s_Encoded = bEncoded; // the set of all vars to be accessible to traversal procedures s_VarAll = bVarsCol; // the column multiplicity s_MultiStart = nMulti; clk = Abc_Clock(); // find the simplest encoding if ( nColumns > 2 ) EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 ); // printf( "The number of backtracks = %d\n", s_BackTracks ); // s_EncSearchTime += Abc_Clock() - clk; // allocate the temporary storage for the columns s_pbTemp = (DdNode **)ABC_ALLOC( char, nColumns * sizeof(DdNode *) ); // clk = Abc_Clock(); bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars ); Cudd_Ref( bResult ); // s_EncComputeTime += Abc_Clock() - clk; // delocate the preliminarily encoded set Cudd_RecursiveDeref( dd, bEncoded ); // Cudd_RecursiveDeref( dd, aEncoded ); ABC_FREE( s_pbTemp ); *pSimple = s_nVarsBest; Cudd_Deref( bResult ); return bResult; } /**Function******************************************************************** Synopsis [Collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root.] Description [The table returned contains the set of BDD nodes pointed to under the cut and, for each node, the BDD of the sum of paths leading to this node from the root The sums of paths in the table are referenced. CutLevel is the first DD level considered to be under the cut.] SideEffects [] SeeAlso [Extra_bddNodePaths] ******************************************************************************/ st__table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ) { st__table * Visited; // temporary table to remember the visited nodes st__table * CutNodes; // the result goes here st__table * Result; // the result goes here DdNode * aFunc; s_CutLevel = CutLevel; Result = st__init_table( st__ptrcmp, st__ptrhash);; // the terminal cases if ( Cudd_IsConstant( bFunc ) ) { if ( bFunc == b1 ) { st__insert( Result, (char*)b1, (char*)b1 ); Cudd_Ref( b1 ); Cudd_Ref( b1 ); } else { st__insert( Result, (char*)b0, (char*)b0 ); Cudd_Ref( b0 ); Cudd_Ref( b0 ); } return Result; } // create the ADD to simplify processing (no complemented edges) aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); // Step 1: Start the tables and collect information about the nodes above the cut // this information tells how many edges point to each node Visited = st__init_table( st__ptrcmp, st__ptrhash);; CutNodes = st__init_table( st__ptrcmp, st__ptrhash);; CountNodeVisits_rec( dd, aFunc, Visited ); // Step 2: Traverse the BDD using the visited table and compute the sum of paths CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes ); // at this point the table of cut nodes is ready and the table of visited is useless { st__generator * gen; DdNode * aNode; traventry * p; st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p ) { Cudd_RecursiveDeref( dd, p->bSum ); ABC_FREE( p ); } st__free_table( Visited ); } // go through the table CutNodes and create the BDD and the path to be returned { st__generator * gen; DdNode * aNode, * bNode, * bSum; st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum) { // aNode is not referenced, because aFunc is holding it bNode = Cudd_addBddPattern( dd, aNode ); Cudd_Ref( bNode ); st__insert( Result, (char*)bNode, (char*)bSum ); // the new table takes both refs } st__free_table( CutNodes ); } // dereference the ADD Cudd_RecursiveDeref( dd, aFunc ); // return the table return Result; } /* end of Extra_bddNodePathsUnderCut */ /**Function******************************************************************** Synopsis [Collects the nodes under the cut in the ADD starting from the given set of ADD nodes.] Description [Takes the array, paNodes, of ADD nodes to start the traversal, the array, pbCubes, of BDD cubes to start the traversal with in each node, and the number, nNodes, of ADD nodes and BDD cubes in paNodes and pbCubes. Returns the number of columns found. Fills in paNodesRes (pbCubesRes) with the set of ADD columns (BDD paths). These arrays should be allocated by the user.] SideEffects [] SeeAlso [Extra_bddNodePaths] ******************************************************************************/ int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ) { st__table * Visited; // temporary table to remember the visited nodes st__table * CutNodes; // the nodes under the cut go here int i, Counter; s_CutLevel = CutLevel; // there should be some nodes assert( nNodes > 0 ); if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) ) { if ( paNodes[0] == a1 ) { paNodesRes[0] = a1; Cudd_Ref( a1 ); pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); } else { paNodesRes[0] = a0; Cudd_Ref( a0 ); pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); } return 1; } // Step 1: Start the table and collect information about the nodes above the cut // this information tells how many edges point to each node CutNodes = st__init_table( st__ptrcmp, st__ptrhash);; Visited = st__init_table( st__ptrcmp, st__ptrhash);; for ( i = 0; i < nNodes; i++ ) CountNodeVisits_rec( dd, paNodes[i], Visited ); // Step 2: Traverse the BDD using the visited table and compute the sum of paths for ( i = 0; i < nNodes; i++ ) CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes ); // at this point, the table of cut nodes is ready and the table of visited is useless { st__generator * gen; DdNode * aNode; traventry * p; st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p ) { Cudd_RecursiveDeref( dd, p->bSum ); ABC_FREE( p ); } st__free_table( Visited ); } // go through the table CutNodes and create the BDD and the path to be returned { st__generator * gen; DdNode * aNode, * bSum; Counter = 0; st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum) { paNodesRes[Counter] = aNode; Cudd_Ref( aNode ); pbCubesRes[Counter] = bSum; Counter++; } st__free_table( CutNodes ); } // return the number of cofactors found return Counter; } /* end of Extra_bddNodePathsUnderCutArray */ /**Function************************************************************* Synopsis [Collects all the BDD nodes into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void extraCollectNodes( DdNode * Func, st__table * tNodes ) { DdNode * FuncR; FuncR = Cudd_Regular(Func); if ( st__find_or_add( tNodes, (char*)FuncR, NULL ) ) return; if ( cuddIsConstant(FuncR) ) return; extraCollectNodes( cuddE(FuncR), tNodes ); extraCollectNodes( cuddT(FuncR), tNodes ); } /**Function************************************************************* Synopsis [Collects all the nodes of one DD into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ st__table * Extra_CollectNodes( DdNode * Func ) { st__table * tNodes; tNodes = st__init_table( st__ptrcmp, st__ptrhash ); extraCollectNodes( Func, tNodes ); return tNodes; } /**Function************************************************************* Synopsis [Updates the topmost level from which the given node is referenced.] Description [Takes the table which maps each BDD nodes (including the constants) into the topmost level on which this node counts as a cofactor. Takes the topmost level, on which this node counts as a cofactor (see Extra_ProfileWidthFast(). Takes the node, for which the table entry should be updated.] SideEffects [] SeeAlso [] ***********************************************************************/ void extraProfileUpdateTopLevel( st__table * tNodeTopRef, int TopLevelNew, DdNode * node ) { int * pTopLevel; if ( st__find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) ) { // the node is already referenced // the current top level should be updated if it is larger than the new level if ( *pTopLevel > TopLevelNew ) *pTopLevel = TopLevelNew; } else { // the node is not referenced // its level should be set to the current new level *pTopLevel = TopLevelNew; } } /**Function************************************************************* Synopsis [Fast computation of the BDD profile.] Description [The array to store the profile is given by the user and should contain at least as many entries as there is the maximum of the BDD/ZDD size of the manager PLUS ONE. When we say that the widths of the DD on level L is W, we mean the following. Let us create the cut between the level L-1 and the level L and count the number of different DD nodes pointed to across the cut. This number is the width W. From this it follows the on level 0, the width is equal to the number of external pointers to the considered DDs. If there is only one DD, then the profile on level 0 is always 1. If this DD is rooted in the topmost variable, then the width on level 1 is always 2, etc. The width at the level equal to dd->size is the number of terminal nodes in the DD. (Because we consider the first level #0 and the last level #dd->size, the profile array should contain dd->size+1 entries.) ] SideEffects [This procedure will not work for BDDs w/ complement edges, only for ADDs and ZDDs] SeeAlso [] ***********************************************************************/ int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel ) { st__generator * gen; st__table * tNodeTopRef; // this table stores the top level from which this node is pointed to st__table * tNodes; DdNode * node; DdNode * nodeR; int LevelStart, Limit; int i, size; int WidthMax; // start the mapping table tNodeTopRef = st__init_table( st__ptrcmp, st__ptrhash);; // add the topmost node to the profile extraProfileUpdateTopLevel( tNodeTopRef, 0, Func ); // collect all nodes tNodes = Extra_CollectNodes( Func ); // go though all the nodes and set the top level the cofactors are pointed from // Cudd_ForeachNode( dd, Func, genDD, node ) st__foreach_item( tNodes, gen, (const char**)&node, NULL ) { // assert( Cudd_Regular(node) ); // this procedure works only with ADD/ZDD (not BDD w/ compl.edges) nodeR = Cudd_Regular(node); if ( cuddIsConstant(nodeR) ) continue; // this node is not a constant - consider its cofactors extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) ); extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) ); } st__free_table( tNodes ); // clean the profile size = ddMax(dd->size, dd->sizeZ) + 1; for ( i = 0; i < size; i++ ) pProfile[i] = 0; // create the profile st__foreach_item( tNodeTopRef, gen, (const char**)&node, (char**)&LevelStart ) { nodeR = Cudd_Regular(node); Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index]; for ( i = LevelStart; i <= Limit; i++ ) pProfile[i]++; } if ( CutLevel != -1 && CutLevel != 0 ) size = CutLevel; // get the max width WidthMax = 0; for ( i = 0; i < size; i++ ) if ( WidthMax < pProfile[i] ) WidthMax = pProfile[i]; // deref the table st__free_table( tNodeTopRef ); return WidthMax; } /* end of Extra_ProfileWidth */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the non-strict codes when evaluation is finished.] Description [The information about the best code is stored in s_VarOrderBest, which has s_nVarsBest entries.] SideEffects [None] ******************************************************************************/ DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ) // bEncoded is the preliminarily encoded set of columns // Level is the current level in the recursion // pCVars are the variables to be used for encoding { DdNode * bRes; if ( Level == s_nVarsBest ) { // the terminal case, when we need to remap the encoded function // from the preliminary encoded variables to the new ones st__table * CutNodes; int nCols; // double nMints; /* #ifdef _DEBUG { DdNode * bTemp; // make sure that the given number of variables is enough bTemp = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll ); Cudd_Ref( bTemp ); // nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart ); nMints = Extra_CountMintermsSimple( bTemp, (1< Extra_Power2( s_MultiStart-Level ) ) { // the number of minterms is too large to encode the columns // using the given minimum number of encoding variables assert( 0 ); } Cudd_RecursiveDeref( dd, bTemp ); } #endif */ // get the columns to be re-encoded CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel ); // LUT size is the cut level because because the temporary encoding variables // are above the functional variables - this is not true!!! // the temporary variables are below! // put the entries from the table into the temporary array { st__generator * gen; DdNode * bColumn, * bCode; nCols = 0; st__foreach_item( CutNodes, gen, (const char**)&bCode, (char**)&bColumn ) { if ( bCode == b0 ) { // the unused part of the columns Cudd_RecursiveDeref( dd, bColumn ); Cudd_RecursiveDeref( dd, bCode ); continue; } else { s_pbTemp[ nCols ] = bColumn; // takes ref Cudd_RecursiveDeref( dd, bCode ); nCols++; } } st__free_table( CutNodes ); // assert( nCols == (int)nMints ); } // encode the columns if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion { assert( nCols == 1 ); // assert( (int)nMints == 1 ); bRes = s_pbTemp[0]; Cudd_Ref( bRes ); } else { bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes ); } // deref the columns { int i; for ( i = 0; i < nCols; i++ ) Cudd_RecursiveDeref( dd, s_pbTemp[i] ); } } else { // cofactor the problem as specified in the best solution DdNode * bCof0, * bCof1; DdNode * bRes0, * bRes1; DdNode * bProd0, * bProd1; DdNode * bTemp; DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ]; bCof0 = Cudd_Cofactor( dd, bEncoded, Cudd_Not( bVarNext ) ); Cudd_Ref( bCof0 ); bCof1 = Cudd_Cofactor( dd, bEncoded, bVarNext ); Cudd_Ref( bCof1 ); // call recursively bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars ); Cudd_Ref( bRes0 ); bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars ); Cudd_Ref( bRes1 ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); // compose the result using the identity (bVarNext <=> pCVars[Level]) - this is wrong! // compose the result as follows: x'y'F0 + xyF1 bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) ); Cudd_Ref( bProd0 ); bProd1 = Cudd_bddAnd( dd, bVarNext , pCVars[Level] ); Cudd_Ref( bProd1 ); bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 ); Cudd_Ref( bProd0 ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bRes0 ); bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 ); Cudd_Ref( bProd1 ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bRes1 ); bRes = Cudd_bddOr( dd, bProd0, bProd1 ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bProd0 ); Cudd_RecursiveDeref( dd, bProd1 ); } Cudd_Deref( bRes ); return bRes; } /**Function******************************************************************** Synopsis [Computes the current set of variables and counts the number of minterms.] Description [Old implementation.] SideEffects [] SeeAlso [] ******************************************************************************/ void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ) // bVarsCol is the set of remaining variables // nVarsCol is the number of remaining variables // nMulti is the number of encoding variables to be used // Level is the level of recursion, from which this function is called // if we successfully finish this procedure, Level also stands for how many encoding variabled we saved { int i, k; int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level DdNode * bVars0, * bVars1; // the cofactors unsigned nMint0, nMint1; // the number of minterms DdNode * bTempV; DdNode * bVarTop; int fBreak; // there is no need to search above this level if ( Level > s_MaxDepth ) return; // if there are no variables left, quit the research if ( bVarsCol == b1 ) return; if ( s_BackTracks > s_BackTrackLimit ) return; s_BackTracks++; // otherwise, go through the remaining variables for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) ) { // the currently tested variable bVarTop = dd->vars[bTempV->index]; // put it into the array s_VarOrderCur[Level-1] = bTempV->index; // go through the entries and fill them out by cofactoring fBreak = 0; for ( i = 0; i < nEntries; i++ ) { bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 ); Cudd_Ref( bVars0 ); if ( nMint0 > Extra_Power2( nMulti-1 ) ) { // there is no way to encode - dereference and return Cudd_RecursiveDeref( dd, bVars0 ); fBreak = 1; break; } bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 ); Cudd_Ref( bVars1 ); if ( nMint1 > Extra_Power2( nMulti-1 ) ) { // there is no way to encode - dereference and return Cudd_RecursiveDeref( dd, bVars0 ); Cudd_RecursiveDeref( dd, bVars1 ); fBreak = 1; break; } // otherwise, add these two cofactors s_Field[Level][2*i + 0] = bVars0; // takes ref s_Field[Level][2*i + 1] = bVars1; // takes ref } if ( !fBreak ) { DdNode * bVarsRem; // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition // save this situation if ( s_nVarsBest < Level ) { s_nVarsBest = Level; // copy the variable assignment for ( k = 0; k < Level; k++ ) s_VarOrderBest[k] = s_VarOrderCur[k]; } // call recursively // get the new variable set if ( nMulti-1 > 0 ) { bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop ); Cudd_Ref( bVarsRem ); EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 ); Cudd_RecursiveDeref( dd, bVarsRem ); } } // deref the contents of the array for ( k = 0; k < i; k++ ) { Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] ); Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] ); } // if the solution is found, there is no need to continue if ( s_nVarsBest == s_MaxDepth ) return; // if the solution is found, there is no need to continue if ( s_nVarsBest == s_MultiStart ) return; } // at this point, we have tried all possible directions in the space of variables } /**Function******************************************************************** Synopsis [Computes the current set of variables and counts the number of minterms.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) // takes bVars - the variables cofactored so far (some of them may be in negative polarity) // bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity) // returns the cost and the new set of variables (bVars & bVarTop) { DdNode * bVarsRes; // get the resulting set of variables bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); // increment signature before calling Cudd_CountCofactorMinterms() s_Signature++; *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll ); Cudd_Deref( bVarsRes ); // s_CountCalls++; return bVarsRes; } /**Function******************************************************************** Synopsis [Computes the current set of variables and counts the number of minterms.] Description [The old implementation, which is approximately 4 times slower.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) { DdNode * bVarsRes; DdNode * bCof, * bFun; bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); bCof = Cudd_Cofactor( dd, s_Encoded, bVarsRes ); Cudd_Ref( bCof ); bFun = Cudd_bddExistAbstract( dd, bCof, s_VarAll ); Cudd_Ref( bFun ); *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart ); Cudd_RecursiveDeref( dd, bFun ); Cudd_RecursiveDeref( dd, bCof ); Cudd_Deref( bVarsRes ); // s_CountCalls++; return bVarsRes; } /**Function******************************************************************** Synopsis [Counts the number of encoding minterms pointed to by the cofactor of the function.] Description [] SideEffects [None] ******************************************************************************/ unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ) // this function computes how many minterms depending on the encoding variables // are there in the cofactor of bFunc w.r.t. variables bVarsCof // bFunc is assumed to depend on variables s_VarsAll // the variables s_VarsAll should be ordered above the encoding variables { unsigned HKey; DdNode * bFuncR; // if the function is zero, there are no minterms // if ( bFunc == b0 ) // return 0; // if ( st__lookup(Visited, (char*)bFunc, NULL) ) // return 0; // HKey = hashKey2c( s_Signature, bFuncR ); // if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited // return 0; // check the hash-table bFuncR = Cudd_Regular(bFunc); // HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF ); HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF ); for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ) // if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited return 0; // if the function is already the code if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel ) { // st__insert(Visited, (char*)bFunc, NULL); // HHTable1[HKey].Sign = s_Signature; // HHTable1[HKey].Arg1 = bFuncR; assert( HHTable1[HKey].Sign != s_Signature ); HHTable1[HKey].Sign = s_Signature; // HHTable1[HKey].Arg1 = bFuncR; HHTable1[HKey].Arg1 = bFunc; return Extra_CountMintermsSimple( bFunc, (1<perm[bFuncR->index]; int LevelC = cuddI(dd,bVarsCofR->index); int LevelA = dd->perm[bVarsAll->index]; int LevelTop = LevelF; if ( LevelTop > LevelC ) LevelTop = LevelC; if ( LevelTop > LevelA ) LevelTop = LevelA; // the top var in the function or in cofactoring vars always belongs to the set of all vars assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA ); // cofactor the function if ( LevelTop == LevelF ) { if ( bFuncR != bFunc ) // bFunc is complemented { bFunc0 = Cudd_Not( cuddE(bFuncR) ); bFunc1 = Cudd_Not( cuddT(bFuncR) ); } else { bFunc0 = cuddE(bFuncR); bFunc1 = cuddT(bFuncR); } } else // bVars is higher in the variable order bFunc0 = bFunc1 = bFunc; // cofactor the cube if ( LevelTop == LevelC ) { if ( bVarsCofR != bVarsCof ) // bFunc is complemented { bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) ); bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) ); } else { bVarsCof0 = cuddE(bVarsCofR); bVarsCof1 = cuddT(bVarsCofR); } } else // bVars is higher in the variable order bVarsCof0 = bVarsCof1 = bVarsCof; // there are two cases: // (1) the top variable belongs to the cofactoring variables // (2) the top variable does not belong to the cofactoring variables // (1) the top variable belongs to the cofactoring variables Res = 0; if ( LevelTop == LevelC ) { if ( bVarsCof1 == b0 ) // this is a negative cofactor { if ( bFunc0 != b0 ) Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); } else // this is a positive cofactor { if ( bFunc1 != b0 ) Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); } } else { if ( bFunc0 != b0 ) Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); if ( bFunc1 != b0 ) Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); } // st__insert(Visited, (char*)bFunc, NULL); // HHTable1[HKey].Sign = s_Signature; // HHTable1[HKey].Arg1 = bFuncR; // skip through the entries with the same signatures // (these might have been created at the time of recursive calls) for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ); assert( HHTable1[HKey].Sign != s_Signature ); HHTable1[HKey].Sign = s_Signature; // HHTable1[HKey].Arg1 = bFuncR; HHTable1[HKey].Arg1 = bFunc; return Res; } } /**Function******************************************************************** Synopsis [Counts the number of minterms.] Description [This function counts minterms for functions up to 32 variables using a local cache. The terminal value (s_Termina) should be adjusted for BDDs and ADDs.] SideEffects [None] ******************************************************************************/ unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ) { unsigned HKey; // normalize if ( Cudd_IsComplement(bFunc) ) return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max ); // now it is known that the function is not complemented if ( cuddIsConstant(bFunc) ) return ((bFunc==s_Terminal)? 0: max); // check cache HKey = hashKey2( bFunc, max, _TABLESIZE_MINT ); if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max ) return HHTable2[HKey].Res; else { // min = min0/2 + min1/2; unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) + (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1); HHTable2[HKey].Arg1 = bFunc; HHTable2[HKey].Arg2 = max; HHTable2[HKey].Res = min; return min; } } /* end of Extra_CountMintermsSimple */ /**Function******************************************************************** Synopsis [Visits the nodes.] Description [Visits the nodes above the cut and the nodes pointed to below the cut; collects the visited nodes, counts how many times each node is visited, and sets the path-sum to be the constant zero BDD.] SideEffects [] SeeAlso [] ******************************************************************************/ void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited ) { traventry * p; char **slot; if ( st__find_or_add(Visited, (char*)aFunc, &slot) ) { // the entry already exists p = (traventry*) *slot; // increment the counter of incoming edges p->nEdges++; return; } // this node has not been visited assert( !Cudd_IsComplement(aFunc) ); // create the new traversal entry p = (traventry *) ABC_ALLOC( char, sizeof(traventry) ); // set the initial sum of edges to zero BDD p->bSum = b0; Cudd_Ref( b0 ); // set the starting number of incoming edges p->nEdges = 1; // set this entry into the slot *slot = (char*)p; // recur if the node is above the cut if ( cuddI(dd,aFunc->index) < s_CutLevel ) { CountNodeVisits_rec( dd, cuddE(aFunc), Visited ); CountNodeVisits_rec( dd, cuddT(aFunc), Visited ); } } /* end of CountNodeVisits_rec */ /**Function******************************************************************** Synopsis [Revisits the nodes and computes the paths.] Description [This function visits the nodes above the cut having the goal of summing all the incomming BDD edges; when this function comes across the node below the cut, it saves this node in the CutNode table.] SideEffects [] SeeAlso [] ******************************************************************************/ void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes ) { // find the node in the visited table DdNode * bTemp; traventry * p; char **slot; if ( st__find_or_add(Visited, (char*)aFunc, &slot) ) { // the node is found // get the pointer to the traversal entry p = (traventry*) *slot; // make sure that the counter of incoming edges is positive assert( p->nEdges > 0 ); // add the cube to the currently accumulated cubes p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube ); Cudd_Ref( p->bSum ); Cudd_RecursiveDeref( dd, bTemp ); // decrement the number of visits p->nEdges--; // if more visits to this node are expected, return if ( p->nEdges ) return; else // if ( p->nEdges == 0 ) { // this is the last visit - propagate the cube // check where this node is if ( cuddI(dd,aFunc->index) < s_CutLevel ) { // the node is above the cut DdNode * bCube0, * bCube1; // get the top-most variable DdNode * bVarTop = dd->vars[aFunc->index]; // compute the propagated cubes bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) ); Cudd_Ref( bCube0 ); bCube1 = Cudd_bddAnd( dd, p->bSum, bVarTop ); Cudd_Ref( bCube1 ); // call recursively CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes ); CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes ); // dereference the cubes Cudd_RecursiveDeref( dd, bCube0 ); Cudd_RecursiveDeref( dd, bCube1 ); return; } else { // the node is below the cut // add this node to the cut node table, if it is not yet there // DdNode * bNode; // bNode = Cudd_addBddPattern( dd, aFunc ); Cudd_Ref( bNode ); if ( st__find_or_add(CutNodes, (char*)aFunc, &slot) ) { // the node exists - should never happen assert( 0 ); } *slot = (char*) p->bSum; Cudd_Ref( p->bSum ); // the table takes the reference of bNode return; } } } // the node does not exist in the visited table - should never happen assert(0); } /* end of CollectNodesAndComputePaths_rec */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddImage.c000066400000000000000000001104701300674244400247210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddImage.c] PackageName [extra] Synopsis [Various reusable software utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2003.] Revision [$Id: extraBddImage.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "extraBdd.h" ABC_NAMESPACE_IMPL_START /* The ideas implemented in this file are inspired by the paper: Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in Image Computation. ICCAD, 2001. */ /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ typedef struct Extra_ImageNode_t_ Extra_ImageNode_t; typedef struct Extra_ImagePart_t_ Extra_ImagePart_t; typedef struct Extra_ImageVar_t_ Extra_ImageVar_t; struct Extra_ImageTree_t_ { Extra_ImageNode_t * pRoot; // the root of quantification tree Extra_ImageNode_t * pCare; // the leaf node with the care set DdNode * bCareSupp; // the cube to quantify from the care int fVerbose; // the verbosity flag int nNodesMax; // the max number of nodes in one iter int nNodesMaxT; // the overall max number of nodes int nIter; // the number of iterations with this tree }; struct Extra_ImageNode_t_ { DdManager * dd; // the manager DdNode * bCube; // the cube to quantify DdNode * bImage; // the partial image Extra_ImageNode_t * pNode1; // the first branch Extra_ImageNode_t * pNode2; // the second branch Extra_ImagePart_t * pPart; // the partition (temporary) }; struct Extra_ImagePart_t_ { DdNode * bFunc; // the partition DdNode * bSupp; // the support of this partition int nNodes; // the number of BDD nodes short nSupp; // the number of support variables short iPart; // the number of this partition }; struct Extra_ImageVar_t_ { int iNum; // the BDD index of this variable DdNode * bParts; // the partition numbers int nParts; // the number of partitions }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static Extra_ImagePart_t ** Extra_CreateParts( DdManager * dd, int nParts, DdNode ** pbParts, DdNode * bCare ); static Extra_ImageVar_t ** Extra_CreateVars( DdManager * dd, int nParts, Extra_ImagePart_t ** pParts, int nVars, DdNode ** pbVarsNs ); static Extra_ImageNode_t ** Extra_CreateNodes( DdManager * dd, int nParts, Extra_ImagePart_t ** pParts, int nVars, Extra_ImageVar_t ** pVars ); static void Extra_DeleteParts_rec( Extra_ImageNode_t * pNode ); static int Extra_BuildTreeNode( DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes, int nVars, Extra_ImageVar_t ** pVars ); static Extra_ImageNode_t * Extra_MergeTopNodes( DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes ); static void Extra_bddImageTreeDelete_rec( Extra_ImageNode_t * pNode ); static void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode ); static int Extra_FindBestVariable( DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes, int nVars, Extra_ImageVar_t ** pVars ); static void Extra_FindBestPartitions( DdManager * dd, DdNode * bParts, int nNodes, Extra_ImageNode_t ** pNodes, int * piNode1, int * piNode2 ); static Extra_ImageNode_t * Extra_CombineTwoNodes( DdManager * dd, DdNode * bCube, Extra_ImageNode_t * pNode1, Extra_ImageNode_t * pNode2 ); static void Extra_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars ); static void Extra_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, DdNode * bVarsCs, DdNode * bVarsNs, int iPart ); static void Extra_bddImagePrintTree( Extra_ImageTree_t * pTree ); static void Extra_bddImagePrintTree_rec( Extra_ImageNode_t * pNode, int nOffset ); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Starts the image computation using tree-based scheduling.] Description [This procedure starts the image computation. It uses the given care set to test-run the image computation and creates the quantification tree by scheduling variable quantifications. The tree can be used to compute images for other care sets without rescheduling. In this case, Extra_bddImageCompute() should be called.] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_ImageTree_t * Extra_bddImageStart( DdManager * dd, DdNode * bCare, // the care set int nParts, DdNode ** pbParts, // the partitions for image computation int nVars, DdNode ** pbVars, int fVerbose ) // the NS and parameter variables (not quantified!) { Extra_ImageTree_t * pTree; Extra_ImagePart_t ** pParts; Extra_ImageVar_t ** pVars; Extra_ImageNode_t ** pNodes; int v; if ( fVerbose && dd->size <= 80 ) Extra_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars ); // create variables, partitions and leaf nodes pParts = Extra_CreateParts( dd, nParts, pbParts, bCare ); pVars = Extra_CreateVars( dd, nParts + 1, pParts, nVars, pbVars ); pNodes = Extra_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars ); // create the tree pTree = ABC_ALLOC( Extra_ImageTree_t, 1 ); memset( pTree, 0, sizeof(Extra_ImageTree_t) ); pTree->pCare = pNodes[nParts]; pTree->fVerbose = fVerbose; // process the nodes while ( Extra_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars ) ); // make sure the variables are gone for ( v = 0; v < dd->size; v++ ) assert( pVars[v] == NULL ); ABC_FREE( pVars ); // merge the topmost nodes while ( (pTree->pRoot = Extra_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL ); // make sure the nodes are gone for ( v = 0; v < nParts + 1; v++ ) assert( pNodes[v] == NULL ); ABC_FREE( pNodes ); // if ( fVerbose ) // Extra_bddImagePrintTree( pTree ); // set the support of the care set pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp ); // clean the partitions Extra_DeleteParts_rec( pTree->pRoot ); ABC_FREE( pParts ); return pTree; } /**Function************************************************************* Synopsis [Compute the image.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ) { DdManager * dd = pTree->pCare->dd; DdNode * bSupp, * bRem; pTree->nIter++; // make sure the supports are okay bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); if ( bSupp != pTree->bCareSupp ) { bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); if ( bRem != b1 ) { printf( "Original care set support: " ); ABC_PRB( dd, pTree->bCareSupp ); printf( "Current care set support: " ); ABC_PRB( dd, bSupp ); Cudd_RecursiveDeref( dd, bSupp ); Cudd_RecursiveDeref( dd, bRem ); printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); return NULL; } Cudd_RecursiveDeref( dd, bRem ); } Cudd_RecursiveDeref( dd, bSupp ); // remove the previous image Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); // compute the image pTree->nNodesMax = 0; Extra_bddImageCompute_rec( pTree, pTree->pRoot ); if ( pTree->nNodesMaxT < pTree->nNodesMax ) pTree->nNodesMaxT = pTree->nNodesMax; // if ( pTree->fVerbose ) // printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); return pTree->pRoot->bImage; } /**Function************************************************************* Synopsis [Delete the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree ) { if ( pTree->bCareSupp ) Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp ); Extra_bddImageTreeDelete_rec( pTree->pRoot ); ABC_FREE( pTree ); } /**Function************************************************************* Synopsis [Reads the image from the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree ) { return pTree->pRoot->bImage; } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static Functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Creates partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_ImagePart_t ** Extra_CreateParts( DdManager * dd, int nParts, DdNode ** pbParts, DdNode * bCare ) { Extra_ImagePart_t ** pParts; int i; // start the partitions pParts = ABC_ALLOC( Extra_ImagePart_t *, nParts + 1 ); // create structures for each variable for ( i = 0; i < nParts; i++ ) { pParts[i] = ABC_ALLOC( Extra_ImagePart_t, 1 ); pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc ); pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp ); pParts[i]->nSupp = Extra_bddSuppSize( dd, pParts[i]->bSupp ); pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); pParts[i]->iPart = i; } // add the care set as the last partition pParts[nParts] = ABC_ALLOC( Extra_ImagePart_t, 1 ); pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc ); pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp ); pParts[nParts]->nSupp = Extra_bddSuppSize( dd, pParts[nParts]->bSupp ); pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc ); pParts[nParts]->iPart = nParts; return pParts; } /**Function************************************************************* Synopsis [Creates variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_ImageVar_t ** Extra_CreateVars( DdManager * dd, int nParts, Extra_ImagePart_t ** pParts, int nVars, DdNode ** pbVars ) { Extra_ImageVar_t ** pVars; DdNode ** pbFuncs; DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp; int nVarsTotal, iVar, p, Counter; // put all the functions into one array pbFuncs = ABC_ALLOC( DdNode *, nParts ); for ( p = 0; p < nParts; p++ ) pbFuncs[p] = pParts[p]->bSupp; bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp ); ABC_FREE( pbFuncs ); // remove the NS vars bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs ); bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCubeNs ); // get the number of I and CS variables to be quantified nVarsTotal = Extra_bddSuppSize( dd, bSupp ); // start the variables pVars = ABC_ALLOC( Extra_ImageVar_t *, dd->size ); memset( pVars, 0, sizeof(Extra_ImageVar_t *) * dd->size ); // create structures for each variable for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) { iVar = bSuppTemp->index; pVars[iVar] = ABC_ALLOC( Extra_ImageVar_t, 1 ); pVars[iVar]->iNum = iVar; // collect all the parts this var belongs to Counter = 0; bParts = b1; Cudd_Ref( bParts ); for ( p = 0; p < nParts; p++ ) if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) ) { bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts ); Cudd_RecursiveDeref( dd, bTemp ); Counter++; } pVars[iVar]->bParts = bParts; // takes ref pVars[iVar]->nParts = Counter; } Cudd_RecursiveDeref( dd, bSupp ); return pVars; } /**Function************************************************************* Synopsis [Creates variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_ImageNode_t ** Extra_CreateNodes( DdManager * dd, int nParts, Extra_ImagePart_t ** pParts, int nVars, Extra_ImageVar_t ** pVars ) { Extra_ImageNode_t ** pNodes; Extra_ImageNode_t * pNode; DdNode * bTemp; int i, v, iPart; /* DdManager * dd; // the manager DdNode * bCube; // the cube to quantify DdNode * bImage; // the partial image Extra_ImageNode_t * pNode1; // the first branch Extra_ImageNode_t * pNode2; // the second branch Extra_ImagePart_t * pPart; // the partition (temporary) */ // start the partitions pNodes = ABC_ALLOC( Extra_ImageNode_t *, nParts ); // create structures for each leaf nodes for ( i = 0; i < nParts; i++ ) { pNodes[i] = ABC_ALLOC( Extra_ImageNode_t, 1 ); memset( pNodes[i], 0, sizeof(Extra_ImageNode_t) ); pNodes[i]->dd = dd; pNodes[i]->pPart = pParts[i]; } // find the quantification cubes for each leaf node for ( v = 0; v < nVars; v++ ) { if ( pVars[v] == NULL ) continue; assert( pVars[v]->nParts > 0 ); if ( pVars[v]->nParts > 1 ) continue; iPart = pVars[v]->bParts->index; if ( pNodes[iPart]->bCube == NULL ) { pNodes[iPart]->bCube = dd->vars[v]; Cudd_Ref( dd->vars[v] ); } else { pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] ); Cudd_Ref( pNodes[iPart]->bCube ); Cudd_RecursiveDeref( dd, bTemp ); } // remove these variables Cudd_RecursiveDeref( dd, pVars[v]->bParts ); ABC_FREE( pVars[v] ); } // assign the leaf node images for ( i = 0; i < nParts; i++ ) { pNode = pNodes[i]; if ( pNode->bCube ) { // update the partition pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube ); Cudd_Ref( pParts[i]->bFunc ); Cudd_RecursiveDeref( dd, bTemp ); // update the support the partition pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); Cudd_Ref( pParts[i]->bSupp ); Cudd_RecursiveDeref( dd, bTemp ); // update the numbers pParts[i]->nSupp = Extra_bddSuppSize( dd, pParts[i]->bSupp ); pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); // get rid of the cube // save the last (care set) quantification cube if ( i < nParts - 1 ) { Cudd_RecursiveDeref( dd, pNode->bCube ); pNode->bCube = NULL; } } // copy the function pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage ); } /* for ( i = 0; i < nParts; i++ ) { pNode = pNodes[i]; ABC_PRB( dd, pNode->bCube ); ABC_PRB( dd, pNode->pPart->bFunc ); ABC_PRB( dd, pNode->pPart->bSupp ); printf( "\n" ); } */ return pNodes; } /**Function************************************************************* Synopsis [Delete the partitions from the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_DeleteParts_rec( Extra_ImageNode_t * pNode ) { Extra_ImagePart_t * pPart; if ( pNode->pNode1 ) Extra_DeleteParts_rec( pNode->pNode1 ); if ( pNode->pNode2 ) Extra_DeleteParts_rec( pNode->pNode2 ); pPart = pNode->pPart; Cudd_RecursiveDeref( pNode->dd, pPart->bFunc ); Cudd_RecursiveDeref( pNode->dd, pPart->bSupp ); ABC_FREE( pNode->pPart ); } /**Function************************************************************* Synopsis [Delete the partitions from the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImageTreeDelete_rec( Extra_ImageNode_t * pNode ) { if ( pNode->pNode1 ) Extra_bddImageTreeDelete_rec( pNode->pNode1 ); if ( pNode->pNode2 ) Extra_bddImageTreeDelete_rec( pNode->pNode2 ); if ( pNode->bCube ) Cudd_RecursiveDeref( pNode->dd, pNode->bCube ); if ( pNode->bImage ) Cudd_RecursiveDeref( pNode->dd, pNode->bImage ); assert( pNode->pPart == NULL ); ABC_FREE( pNode ); } /**Function************************************************************* Synopsis [Recompute the image.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode ) { DdManager * dd = pNode->dd; DdNode * bTemp; int nNodes; // trivial case if ( pNode->pNode1 == NULL ) { if ( pNode->bCube ) { pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); Cudd_Ref( pNode->bImage ); Cudd_RecursiveDeref( dd, bTemp ); } return; } // compute the children if ( pNode->pNode1 ) Extra_bddImageCompute_rec( pTree, pNode->pNode1 ); if ( pNode->pNode2 ) Extra_bddImageCompute_rec( pTree, pNode->pNode2 ); // clean the old image if ( pNode->bImage ) Cudd_RecursiveDeref( dd, pNode->bImage ); pNode->bImage = NULL; // compute the new image if ( pNode->bCube ) pNode->bImage = Cudd_bddAndAbstract( dd, pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); else pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); Cudd_Ref( pNode->bImage ); if ( pTree->fVerbose ) { nNodes = Cudd_DagSize( pNode->bImage ); if ( pTree->nNodesMax < nNodes ) pTree->nNodesMax = nNodes; } } /**Function************************************************************* Synopsis [Builds the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_BuildTreeNode( DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes, int nVars, Extra_ImageVar_t ** pVars ) { Extra_ImageNode_t * pNode1, * pNode2; Extra_ImageVar_t * pVar; Extra_ImageNode_t * pNode; DdNode * bCube, * bTemp, * bSuppTemp, * bParts; int iNode1, iNode2; int iVarBest, nSupp, v; // find the best variable iVarBest = Extra_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); if ( iVarBest == -1 ) return 0; pVar = pVars[iVarBest]; // this var cannot appear in one partition only nSupp = Extra_bddSuppSize( dd, pVar->bParts ); assert( nSupp == pVar->nParts ); assert( nSupp != 1 ); // if it appears in only two partitions, quantify it if ( pVar->nParts == 2 ) { // get the nodes iNode1 = pVar->bParts->index; iNode2 = cuddT(pVar->bParts)->index; pNode1 = pNodes[iNode1]; pNode2 = pNodes[iNode2]; // get the quantification cube bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); // add the variables that appear only in these partitions for ( v = 0; v < nVars; v++ ) if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) { // add this var bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); // clean this var Cudd_RecursiveDeref( dd, pVars[v]->bParts ); ABC_FREE( pVars[v] ); } // clean the best var Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); ABC_FREE( pVars[iVarBest] ); // combines two nodes pNode = Extra_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); Cudd_RecursiveDeref( dd, bCube ); } else // if ( pVar->nParts > 2 ) { // find two smallest BDDs that have this var Extra_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); pNode1 = pNodes[iNode1]; pNode2 = pNodes[iNode2]; // it is not possible that a var appears only in these two // otherwise, it would have a different cost bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); for ( v = 0; v < nVars; v++ ) if ( pVars[v] && pVars[v]->bParts == bParts ) assert( 0 ); Cudd_RecursiveDeref( dd, bParts ); // combines two nodes pNode = Extra_CombineTwoNodes( dd, b1, pNode1, pNode2 ); } // clean the old nodes pNodes[iNode1] = pNode; pNodes[iNode2] = NULL; // update the variables that appear in pNode[iNode2] for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) { pVar = pVars[bSuppTemp->index]; if ( pVar == NULL ) // this variable is not be quantified continue; // quantify this var assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); Cudd_RecursiveDeref( dd, bTemp ); // add the new var pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); Cudd_RecursiveDeref( dd, bTemp ); // update the score pVar->nParts = Extra_bddSuppSize( dd, pVar->bParts ); } return 1; } /**Function************************************************************* Synopsis [Merges the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_ImageNode_t * Extra_MergeTopNodes( DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes ) { Extra_ImageNode_t * pNode; int n1 = -1, n2 = -1, n; // find the first and the second non-empty spots for ( n = 0; n < nNodes; n++ ) if ( pNodes[n] ) { if ( n1 == -1 ) n1 = n; else if ( n2 == -1 ) { n2 = n; break; } } assert( n1 != -1 ); // check the situation when only one such node is detected if ( n2 == -1 ) { // save the node pNode = pNodes[n1]; // clean the node pNodes[n1] = NULL; return pNode; } // combines two nodes pNode = Extra_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] ); // clean the old nodes pNodes[n1] = pNode; pNodes[n2] = NULL; return NULL; } /**Function************************************************************* Synopsis [Merges two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_ImageNode_t * Extra_CombineTwoNodes( DdManager * dd, DdNode * bCube, Extra_ImageNode_t * pNode1, Extra_ImageNode_t * pNode2 ) { Extra_ImageNode_t * pNode; Extra_ImagePart_t * pPart; // create a new partition pPart = ABC_ALLOC( Extra_ImagePart_t, 1 ); memset( pPart, 0, sizeof(Extra_ImagePart_t) ); // create the function pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); // update the support the partition pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube ); Cudd_Ref( pPart->bSupp ); // update the numbers pPart->nSupp = Extra_bddSuppSize( dd, pPart->bSupp ); pPart->nNodes = Cudd_DagSize( pPart->bFunc ); pPart->iPart = -1; /* ABC_PRB( dd, pNode1->pPart->bSupp ); ABC_PRB( dd, pNode2->pPart->bSupp ); ABC_PRB( dd, pPart->bSupp ); */ // create a new node pNode = ABC_ALLOC( Extra_ImageNode_t, 1 ); memset( pNode, 0, sizeof(Extra_ImageNode_t) ); pNode->dd = dd; pNode->pPart = pPart; pNode->pNode1 = pNode1; pNode->pNode2 = pNode2; // compute the image pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); Cudd_Ref( pNode->bImage ); // save the cube if ( bCube != b1 ) { pNode->bCube = bCube; Cudd_Ref( bCube ); } return pNode; } /**Function************************************************************* Synopsis [Computes the best variable.] Description [The variables is the best if the sum of squares of the BDD sizes of the partitions, in which it participates, is the minimum.] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FindBestVariable( DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes, int nVars, Extra_ImageVar_t ** pVars ) { DdNode * bTemp; int iVarBest, v; double CostBest, CostCur; CostBest = 100000000000000.0; iVarBest = -1; for ( v = 0; v < nVars; v++ ) if ( pVars[v] ) { CostCur = 0; for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) CostCur += pNodes[bTemp->index]->pPart->nNodes * pNodes[bTemp->index]->pPart->nNodes; if ( CostBest > CostCur ) { CostBest = CostCur; iVarBest = v; } } return iVarBest; } /**Function************************************************************* Synopsis [Computes two smallest partions that have this var.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_FindBestPartitions( DdManager * dd, DdNode * bParts, int nNodes, Extra_ImageNode_t ** pNodes, int * piNode1, int * piNode2 ) { DdNode * bTemp; int iPart1, iPart2; int CostMin1, CostMin2, Cost; // go through the partitions iPart1 = iPart2 = -1; CostMin1 = CostMin2 = 1000000; for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) ) { Cost = pNodes[bTemp->index]->pPart->nNodes; if ( CostMin1 > Cost ) { CostMin2 = CostMin1; iPart2 = iPart1; CostMin1 = Cost; iPart1 = bTemp->index; } else if ( CostMin2 > Cost ) { CostMin2 = Cost; iPart2 = bTemp->index; } } *piNode1 = iPart1; *piNode2 = iPart2; } /**Function************************************************************* Synopsis [Prints the latch dependency matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, // the care set int nParts, DdNode ** pbParts, // the partitions for image computation int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!) { int i; DdNode * bVarsCs, * bVarsNs; bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs ); bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs ); printf( "The latch dependency matrix:\n" ); printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n", nParts, dd->size, nVars ); printf( " : " ); for ( i = 0; i < dd->size; i++ ) printf( "%d", i % 10 ); printf( "\n" ); for ( i = 0; i < nParts; i++ ) Extra_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i ); Extra_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts ); Cudd_RecursiveDeref( dd, bVarsCs ); Cudd_RecursiveDeref( dd, bVarsNs ); } /**Function************************************************************* Synopsis [Prints one row of the latch dependency matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, // the function DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars int iPart ) { DdNode * bSupport; int v; bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport ); printf( " %3d : ", iPart ); for ( v = 0; v < dd->size; v++ ) { if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) ) { if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) ) printf( "c" ); else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) printf( "n" ); else printf( "i" ); } else printf( "." ); } printf( "\n" ); Cudd_RecursiveDeref( dd, bSupport ); } /**Function************************************************************* Synopsis [Prints the tree for quenstification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImagePrintTree( Extra_ImageTree_t * pTree ) { printf( "The quantification scheduling tree:\n" ); Extra_bddImagePrintTree_rec( pTree->pRoot, 1 ); } /**Function************************************************************* Synopsis [Prints the tree for quenstification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImagePrintTree_rec( Extra_ImageNode_t * pNode, int Offset ) { DdNode * Cube; int i; Cube = pNode->bCube; if ( pNode->pNode1 == NULL ) { printf( "<%d> ", pNode->pPart->iPart ); if ( Cube != NULL ) { ABC_PRB( pNode->dd, Cube ); } else printf( "\n" ); return; } printf( "<*> " ); if ( Cube != NULL ) { ABC_PRB( pNode->dd, Cube ); } else printf( "\n" ); for ( i = 0; i < Offset; i++ ) printf( " " ); Extra_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 ); for ( i = 0; i < Offset; i++ ) printf( " " ); Extra_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 ); } struct Extra_ImageTree2_t_ { DdManager * dd; DdNode * bRel; DdNode * bCube; DdNode * bImage; }; /**Function************************************************************* Synopsis [Starts the monolithic image computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_ImageTree2_t * Extra_bddImageStart2( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars, int fVerbose ) { Extra_ImageTree2_t * pTree; DdNode * bCubeAll, * bCubeNot, * bTemp; int i; pTree = ABC_ALLOC( Extra_ImageTree2_t, 1 ); pTree->dd = dd; pTree->bImage = NULL; bCubeAll = Extra_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); bCubeNot = Extra_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); Cudd_RecursiveDeref( dd, bCubeAll ); Cudd_RecursiveDeref( dd, bCubeNot ); // derive the monolithic relation pTree->bRel = b1; Cudd_Ref( pTree->bRel ); for ( i = 0; i < nParts; i++ ) { pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); Cudd_RecursiveDeref( dd, bTemp ); } Extra_bddImageCompute2( pTree, bCare ); return pTree; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare ) { if ( pTree->bImage ) Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); Cudd_Ref( pTree->bImage ); return pTree->bImage; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree ) { if ( pTree->bRel ) Cudd_RecursiveDeref( pTree->dd, pTree->bRel ); if ( pTree->bCube ) Cudd_RecursiveDeref( pTree->dd, pTree->bCube ); if ( pTree->bImage ) Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); ABC_FREE( pTree ); } /**Function************************************************************* Synopsis [Returns the previously computed image.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ) { return pTree->bImage; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddKmap.c000066400000000000000000000722161300674244400245740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddKmap.c] PackageName [extra] Synopsis [Visualizing the K-map.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - September 1, 2003.] Revision [$Id: extraBddKmap.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] ***********************************************************************/ /// K-map visualization using pseudo graphics /// /// Version 1.0. Started - August 20, 2000 /// /// Version 2.0. Added to EXTRA - July 17, 2001 /// #include "extraBdd.h" #ifdef WIN32 #include #endif ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ // the maximum number of variables in the Karnaugh Map #define MAXVARS 20 /* // single line #define SINGLE_VERTICAL (char)179 #define SINGLE_HORIZONTAL (char)196 #define SINGLE_TOP_LEFT (char)218 #define SINGLE_TOP_RIGHT (char)191 #define SINGLE_BOT_LEFT (char)192 #define SINGLE_BOT_RIGHT (char)217 // double line #define DOUBLE_VERTICAL (char)186 #define DOUBLE_HORIZONTAL (char)205 #define DOUBLE_TOP_LEFT (char)201 #define DOUBLE_TOP_RIGHT (char)187 #define DOUBLE_BOT_LEFT (char)200 #define DOUBLE_BOT_RIGHT (char)188 // line intersections #define SINGLES_CROSS (char)197 #define DOUBLES_CROSS (char)206 #define S_HOR_CROSS_D_VER (char)215 #define S_VER_CROSS_D_HOR (char)216 // single line joining #define S_JOINS_S_VER_LEFT (char)180 #define S_JOINS_S_VER_RIGHT (char)195 #define S_JOINS_S_HOR_TOP (char)193 #define S_JOINS_S_HOR_BOT (char)194 // double line joining #define D_JOINS_D_VER_LEFT (char)185 #define D_JOINS_D_VER_RIGHT (char)204 #define D_JOINS_D_HOR_TOP (char)202 #define D_JOINS_D_HOR_BOT (char)203 // single line joining double line #define S_JOINS_D_VER_LEFT (char)182 #define S_JOINS_D_VER_RIGHT (char)199 #define S_JOINS_D_HOR_TOP (char)207 #define S_JOINS_D_HOR_BOT (char)209 */ // single line #define SINGLE_VERTICAL (char)'|' #define SINGLE_HORIZONTAL (char)'-' #define SINGLE_TOP_LEFT (char)'+' #define SINGLE_TOP_RIGHT (char)'+' #define SINGLE_BOT_LEFT (char)'+' #define SINGLE_BOT_RIGHT (char)'+' // double line #define DOUBLE_VERTICAL (char)'|' #define DOUBLE_HORIZONTAL (char)'-' #define DOUBLE_TOP_LEFT (char)'+' #define DOUBLE_TOP_RIGHT (char)'+' #define DOUBLE_BOT_LEFT (char)'+' #define DOUBLE_BOT_RIGHT (char)'+' // line intersections #define SINGLES_CROSS (char)'+' #define DOUBLES_CROSS (char)'+' #define S_HOR_CROSS_D_VER (char)'+' #define S_VER_CROSS_D_HOR (char)'+' // single line joining #define S_JOINS_S_VER_LEFT (char)'+' #define S_JOINS_S_VER_RIGHT (char)'+' #define S_JOINS_S_HOR_TOP (char)'+' #define S_JOINS_S_HOR_BOT (char)'+' // double line joining #define D_JOINS_D_VER_LEFT (char)'+' #define D_JOINS_D_VER_RIGHT (char)'+' #define D_JOINS_D_HOR_TOP (char)'+' #define D_JOINS_D_HOR_BOT (char)'+' // single line joining double line #define S_JOINS_D_VER_LEFT (char)'+' #define S_JOINS_D_VER_RIGHT (char)'+' #define S_JOINS_D_HOR_TOP (char)'+' #define S_JOINS_D_HOR_BOT (char)'+' // other symbols #define UNDERSCORE (char)95 //#define SYMBOL_ZERO (char)248 // degree sign //#define SYMBOL_ZERO (char)'o' #ifdef WIN32 #define SYMBOL_ZERO (char)'0' #else #define SYMBOL_ZERO (char)' ' #endif #define SYMBOL_ONE (char)'1' #define SYMBOL_DC (char)'-' #define SYMBOL_OVERLAP (char)'?' // full cells and half cells #define CELL_FREE (char)32 #define CELL_FULL (char)219 #define HALF_UPPER (char)223 #define HALF_LOWER (char)220 #define HALF_LEFT (char)221 #define HALF_RIGHT (char)222 /*---------------------------------------------------------------------------*/ /* Structure declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ // the array of BDD variables used internally static DdNode * s_XVars[MAXVARS]; // flag which determines where the horizontal variable names are printed static int fHorizontalVarNamesPrintedAbove = 1; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ // Oleg's way of generating the gray code static int GrayCode( int BinCode ); static int BinCode ( int GrayCode ); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Prints the K-map of the function.] Description [If the pointer to the array of variables XVars is NULL, fSuppType determines how the support will be determined. fSuppType == 0 -- takes the first nVars of the manager fSuppType == 1 -- takes the topmost nVars of the manager fSuppType == 2 -- determines support from the on-set and the offset ] SideEffects [] SeeAlso [] ******************************************************************************/ void Extra_PrintKMap( FILE * Output, /* the output stream */ DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, /* the flag which determines how support is computed */ char ** pVarNames ) { int fPrintTruth = 1; int d, p, n, s, v, h, w; int nVarsVer; int nVarsHor; int nCellsVer; int nCellsHor; int nSkipSpaces; // make sure that on-set and off-set do not overlap if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) ) { fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" ); return; } if ( nVars == 0 ) { printf( "Function is constant %d.\n", !Cudd_IsComplement(OnSet) ); return; } // print truth table for debugging if ( fPrintTruth ) { DdNode * bCube, * bPart; printf( "Truth table: " ); if ( nVars == 0 ) printf( "Constant" ); else if ( nVars == 1 ) printf( "1-var function" ); else { // printf( "0x" ); for ( d = (1<<(nVars-2)) - 1; d >= 0; d-- ) { int Value = 0; for ( s = 0; s < 4; s++ ) { bCube = Extra_bddBitsToCube( dd, 4*d+s, nVars, dd->vars, 0 ); Cudd_Ref( bCube ); bPart = Cudd_Cofactor( dd, OnSet, bCube ); Cudd_Ref( bPart ); Value |= ((int)(bPart == b1) << s); Cudd_RecursiveDeref( dd, bPart ); Cudd_RecursiveDeref( dd, bCube ); } if ( Value < 10 ) fprintf( stdout, "%d", Value ); else fprintf( stdout, "%c", 'a' + Value-10 ); } } printf( "\n" ); } /* if ( OnSet == b1 ) { fprintf( Output, "PrintKMap(): Constant 1\n" ); return; } if ( OffSet == b1 ) { fprintf( Output, "PrintKMap(): Constant 0\n" ); return; } */ if ( nVars < 0 || nVars > MAXVARS ) { fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); return; } // determine the support if it is not given if ( XVars == NULL ) { if ( fSuppType == 0 ) { // assume that the support includes the first nVars of the manager assert( nVars ); for ( v = 0; v < nVars; v++ ) s_XVars[v] = Cudd_bddIthVar( dd, v ); } else if ( fSuppType == 1 ) { // assume that the support includes the topmost nVars of the manager assert( nVars ); for ( v = 0; v < nVars; v++ ) s_XVars[v] = Cudd_bddIthVar( dd, dd->invperm[v] ); } else // determine the support { DdNode * SuppOn, * SuppOff, * Supp; int cVars = 0; DdNode * TempSupp; // determine support SuppOn = Cudd_Support( dd, OnSet ); Cudd_Ref( SuppOn ); SuppOff = Cudd_Support( dd, OffSet ); Cudd_Ref( SuppOff ); Supp = Cudd_bddAnd( dd, SuppOn, SuppOff ); Cudd_Ref( Supp ); Cudd_RecursiveDeref( dd, SuppOn ); Cudd_RecursiveDeref( dd, SuppOff ); nVars = Cudd_SupportSize( dd, Supp ); if ( nVars > MAXVARS ) { fprintf( Output, "PrintKMap(): The number of variables is more than %d\n", MAXVARS ); Cudd_RecursiveDeref( dd, Supp ); return; } // assign variables for ( TempSupp = Supp; TempSupp != dd->one; TempSupp = Cudd_T(TempSupp), cVars++ ) s_XVars[cVars] = Cudd_bddIthVar( dd, TempSupp->index ); Cudd_RecursiveDeref( dd, TempSupp ); } } else { // copy variables assert( XVars ); for ( v = 0; v < nVars; v++ ) s_XVars[v] = XVars[v]; } //////////////////////////////////////////////////////////////////// // determine the Karnaugh map parameters nVarsVer = nVars/2; nVarsHor = nVars - nVarsVer; nCellsVer = (1< MAXVARS ) { fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); return; } //////////////////////////////////////////////////////////////////// // determine the Karnaugh map parameters nVarsVer = nXVars; nVarsHor = nYVars; nCellsVer = (1<> 1 ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int BinCode ( int GrayCode ) { int bc = GrayCode; while( GrayCode >>= 1 ) bc ^= GrayCode; return bc; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddMisc.c000066400000000000000000002071661300674244400246030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddMisc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [DD-based utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $] ***********************************************************************/ #include "extraBdd.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ // file "extraDdTransfer.c" static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute ); static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ); static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) ); static DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); // file "cuddUtils.c" static void ddSupportStep(DdNode *f, int *support); static void ddClearFlag(DdNode *f); static DdNode* extraZddPrimes( DdManager *dd, DdNode* F ); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] Description [Convert a {A,B}DD from a manager to another one. The orders of the variables in the two managers may be different. Returns a pointer to the {A,B}DD in the destination manager if successful; NULL otherwise. The i-th entry in the array Permute tells what is the index of the i-th variable from the old manager in the new manager.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ) { DdNode * bRes; do { ddDestination->reordered = 0; bRes = extraTransferPermute( ddSource, ddDestination, f, Permute ); } while ( ddDestination->reordered == 1 ); return ( bRes ); } /* end of Extra_TransferPermute */ /**Function******************************************************************** Synopsis [Transfers the BDD from one manager into another level by level.] Description [Transfers the BDD from one manager into another while preserving the correspondence between variables level by level.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ) { DdNode * bRes; int * pPermute; int nMin, nMax, i; nMin = ddMin(ddSource->size, ddDestination->size); nMax = ddMax(ddSource->size, ddDestination->size); pPermute = ABC_ALLOC( int, nMax ); // set up the variable permutation for ( i = 0; i < nMin; i++ ) pPermute[ ddSource->invperm[i] ] = ddDestination->invperm[i]; if ( ddSource->size > ddDestination->size ) { for ( ; i < nMax; i++ ) pPermute[ ddSource->invperm[i] ] = -1; } bRes = Extra_TransferPermute( ddSource, ddDestination, f, pPermute ); ABC_FREE( pPermute ); return bRes; } /**Function******************************************************************** Synopsis [Remaps the function to depend on the topmost variables on the manager.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ) { int * pPermute; DdNode * bSupp, * bTemp, * bRes; int Counter; pPermute = ABC_ALLOC( int, dd->size ); // get support bSupp = Cudd_Support( dd, bF ); Cudd_Ref( bSupp ); // create the variable map // to remap the DD into the upper part of the manager Counter = 0; for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) pPermute[bTemp->index] = dd->invperm[Counter++]; // transfer the BDD and remap it bRes = Cudd_bddPermute( dd, bF, pPermute ); Cudd_Ref( bRes ); // remove support Cudd_RecursiveDeref( dd, bSupp ); // return Cudd_Deref( bRes ); ABC_FREE( pPermute ); return bRes; } /**Function******************************************************************** Synopsis [Moves the BDD by the given number of variables up or down.] Description [] SideEffects [] SeeAlso [Extra_bddShift] ******************************************************************************/ DdNode * Extra_bddMove( DdManager * dd, /* the DD manager */ DdNode * bF, int nVars) { DdNode * res; DdNode * bVars; if ( nVars == 0 ) return bF; if ( Cudd_IsConstant(bF) ) return bF; assert( nVars <= dd->size ); if ( nVars > 0 ) bVars = dd->vars[nVars]; else bVars = Cudd_Not(dd->vars[-nVars]); do { dd->reordered = 0; res = extraBddMove( dd, bF, bVars ); } while (dd->reordered == 1); return(res); } /* end of Extra_bddMove */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_StopManager( DdManager * dd ) { int RetValue; // check for remaining references in the package RetValue = Cudd_CheckZeroRef( dd ); if ( RetValue > 10 ) // if ( RetValue ) printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); // Cudd_PrintInfo( dd, stdout ); Cudd_Quit( dd ); } /**Function******************************************************************** Synopsis [Outputs the BDD in a readable format.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void Extra_bddPrint( DdManager * dd, DdNode * F ) { DdGen * Gen; int * Cube; CUDD_VALUE_TYPE Value; int nVars = dd->size; int fFirstCube = 1; int i; if ( F == NULL ) { printf("NULL"); return; } if ( F == b0 ) { printf("Constant 0"); return; } if ( F == b1 ) { printf("Constant 1"); return; } Cudd_ForeachCube( dd, F, Gen, Cube, Value ) { if ( fFirstCube ) fFirstCube = 0; else // Output << " + "; printf( " + " ); for ( i = 0; i < nVars; i++ ) if ( Cube[i] == 0 ) printf( "[%d]'", i ); // printf( "%c'", (char)('a'+i) ); else if ( Cube[i] == 1 ) printf( "[%d]", i ); // printf( "%c", (char)('a'+i) ); } // printf("\n"); } /**Function******************************************************************** Synopsis [Outputs the BDD in a readable format.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ void Extra_bddPrintSupport( DdManager * dd, DdNode * F ) { DdNode * bSupp; bSupp = Cudd_Support( dd, F ); Cudd_Ref( bSupp ); Extra_bddPrint( dd, bSupp ); Cudd_RecursiveDeref( dd, bSupp ); } /**Function******************************************************************** Synopsis [Returns the size of the support.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ) { int Counter = 0; while ( bSupp != b1 ) { assert( !Cudd_IsComplement(bSupp) ); assert( cuddE(bSupp) == b0 ); bSupp = cuddT(bSupp); Counter++; } return Counter; } /**Function******************************************************************** Synopsis [Returns 1 if the support contains the given BDD variable.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ) { for( ; bS != b1; bS = cuddT(bS) ) if ( bS->index == bVar->index ) return 1; return 0; } /**Function******************************************************************** Synopsis [Returns 1 if two supports represented as BDD cubes are overlapping.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ) { while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) { // if the top vars are the same, they intersect if ( S1->index == S2->index ) return 1; // if the top vars are different, skip the one, which is higher if ( dd->perm[S1->index] < dd->perm[S2->index] ) S1 = cuddT(S1); else S2 = cuddT(S2); } return 0; } /**Function******************************************************************** Synopsis [Returns the number of different vars in two supports.] Description [Counts the number of variables that appear in one support and does not appear in other support. If the number exceeds DiffMax, returns DiffMax.] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ) { int Result = 0; while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) { // if the top vars are the same, this var is the same if ( S1->index == S2->index ) { S1 = cuddT(S1); S2 = cuddT(S2); continue; } // the top var is different Result++; if ( Result >= DiffMax ) return DiffMax; // if the top vars are different, skip the one, which is higher if ( dd->perm[S1->index] < dd->perm[S2->index] ) S1 = cuddT(S1); else S2 = cuddT(S2); } // consider the remaining variables if ( S1->index != CUDD_CONST_INDEX ) Result += Extra_bddSuppSize(dd,S1); else if ( S2->index != CUDD_CONST_INDEX ) Result += Extra_bddSuppSize(dd,S2); if ( Result >= DiffMax ) return DiffMax; return Result; } /**Function******************************************************************** Synopsis [Checks the support containment.] Description [This function returns 1 if one support is contained in another. In this case, bLarge (bSmall) is assigned to point to the larger (smaller) support. If the supports are identical, return 0 and does not assign the supports!] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ) { DdNode * bSL = bL; DdNode * bSH = bH; int fLcontainsH = 1; int fHcontainsL = 1; int TopVar; if ( bSL == bSH ) return 0; while ( bSL != b1 || bSH != b1 ) { if ( bSL == b1 ) { // Low component has no vars; High components has some vars fLcontainsH = 0; if ( fHcontainsL == 0 ) return 0; else break; } if ( bSH == b1 ) { // similarly fHcontainsL = 0; if ( fLcontainsH == 0 ) return 0; else break; } // determine the topmost var of the supports by comparing their levels if ( dd->perm[bSL->index] < dd->perm[bSH->index] ) TopVar = bSL->index; else TopVar = bSH->index; if ( TopVar == bSL->index && TopVar == bSH->index ) { // they are on the same level // it does not tell us anything about their containment // skip this var bSL = cuddT(bSL); bSH = cuddT(bSH); } else if ( TopVar == bSL->index ) // and TopVar != bSH->index { // Low components is higher and contains more vars // it is not possible that High component contains Low fHcontainsL = 0; // skip this var bSL = cuddT(bSL); } else // if ( TopVar == bSH->index ) // and TopVar != bSL->index { // similarly fLcontainsH = 0; // skip this var bSH = cuddT(bSH); } // check the stopping condition if ( !fHcontainsL && !fLcontainsH ) return 0; } // only one of them can be true at the same time assert( !fHcontainsL || !fLcontainsH ); if ( fHcontainsL ) { *bLarge = bH; *bSmall = bL; } else // fLcontainsH { *bLarge = bL; *bSmall = bH; } return 1; } /**Function******************************************************************** Synopsis [Finds variables on which the DD depends and returns them as am array.] Description [Finds the variables on which the DD depends. Returns an array with entries set to 1 for those variables that belong to the support; NULL otherwise. The array is allocated by the user and should have at least as many entries as the maximum number of variables in BDD and ZDD parts of the manager.] SideEffects [None] SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] ******************************************************************************/ int * Extra_SupportArray( DdManager * dd, /* manager */ DdNode * f, /* DD whose support is sought */ int * support ) /* array allocated by the user */ { int i, size; /* Initialize support array for ddSupportStep. */ size = ddMax(dd->size, dd->sizeZ); for (i = 0; i < size; i++) support[i] = 0; /* Compute support and clean up markers. */ ddSupportStep(Cudd_Regular(f),support); ddClearFlag(Cudd_Regular(f)); return(support); } /* end of Extra_SupportArray */ /**Function******************************************************************** Synopsis [Finds the variables on which a set of DDs depends.] Description [Finds the variables on which a set of DDs depends. The set must contain either BDDs and ADDs, or ZDDs. Returns a BDD consisting of the product of the variables if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_Support Cudd_ClassifySupport] ******************************************************************************/ int * Extra_VectorSupportArray( DdManager * dd, /* manager */ DdNode ** F, /* array of DDs whose support is sought */ int n, /* size of the array */ int * support ) /* array allocated by the user */ { int i, size; /* Allocate and initialize support array for ddSupportStep. */ size = ddMax( dd->size, dd->sizeZ ); for ( i = 0; i < size; i++ ) support[i] = 0; /* Compute support and clean up markers. */ for ( i = 0; i < n; i++ ) ddSupportStep( Cudd_Regular(F[i]), support ); for ( i = 0; i < n; i++ ) ddClearFlag( Cudd_Regular(F[i]) ); return support; } /**Function******************************************************************** Synopsis [Find any cube belonging to the on-set of the function.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ) { char * s_Temp; DdNode * bCube, * bTemp; int v; // get the vector of variables in the cube s_Temp = ABC_ALLOC( char, dd->size ); Cudd_bddPickOneCube( dd, bF, s_Temp ); // start the cube bCube = b1; Cudd_Ref( bCube ); for ( v = 0; v < dd->size; v++ ) if ( s_Temp[v] == 0 ) { // Cube &= !s_XVars[v]; bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(dd->vars[v]) ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } else if ( s_Temp[v] == 1 ) { // Cube &= s_XVars[v]; bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[v] ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref(bCube); ABC_FREE( s_Temp ); return bCube; } /**Function******************************************************************** Synopsis [Returns one cube contained in the given BDD.] Description [This function returns the cube with the smallest bits-to-integer value.] SideEffects [] ******************************************************************************/ DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ) { DdNode * bFuncR, * bFunc0, * bFunc1; DdNode * bRes0, * bRes1, * bRes; bFuncR = Cudd_Regular(bFunc); if ( cuddIsConstant(bFuncR) ) return bFunc; // cofactor if ( Cudd_IsComplement(bFunc) ) { bFunc0 = Cudd_Not( cuddE(bFuncR) ); bFunc1 = Cudd_Not( cuddT(bFuncR) ); } else { bFunc0 = cuddE(bFuncR); bFunc1 = cuddT(bFuncR); } // try to find the cube with the negative literal bRes0 = Extra_bddGetOneCube( dd, bFunc0 ); Cudd_Ref( bRes0 ); if ( bRes0 != b0 ) { bRes = Cudd_bddAnd( dd, bRes0, Cudd_Not(dd->vars[bFuncR->index]) ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bRes0 ); } else { Cudd_RecursiveDeref( dd, bRes0 ); // try to find the cube with the positive literal bRes1 = Extra_bddGetOneCube( dd, bFunc1 ); Cudd_Ref( bRes1 ); assert( bRes1 != b0 ); bRes = Cudd_bddAnd( dd, bRes1, dd->vars[bFuncR->index] ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bRes1 ); } Cudd_Deref( bRes ); return bRes; } /**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) { DdNode * bTemp, * bProd; int i; assert( iStart <= iStop ); assert( iStart >= 0 && iStart <= dd->size ); assert( iStop >= 0 && iStop <= dd->size ); bProd = b1; Cudd_Ref( bProd ); for ( i = iStart; i < iStop; i++ ) { bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bProd ); return bProd; } /**Function******************************************************************** Synopsis [Computes the cube of BDD variables corresponding to bits it the bit-code] Description [Returns a bdd composed of elementary bdds found in array BddVars[] such that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1, the most significant bit is encoded with the first bdd variable). If the variables BddVars are not specified, takes the first CodeWidth variables of the manager] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ) { int z; DdNode * bTemp, * bVar, * bVarBdd, * bResult; bResult = b1; Cudd_Ref( bResult ); for ( z = 0; z < CodeWidth; z++ ) { bVarBdd = (pbVars)? pbVars[z]: dd->vars[z]; if ( fMsbFirst ) bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 ); else bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 ); bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar ); Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bResult ); return bResult; } /* end of Extra_bddBitsToCube */ /**Function******************************************************************** Synopsis [Finds the support as a negative polarity cube.] Description [Finds the variables on which a DD depends. Returns a BDD consisting of the product of the variables in the negative polarity if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_VectorSupport Cudd_Support] ******************************************************************************/ DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ) { int *support; DdNode *res, *tmp, *var; int i, j; int size; /* Allocate and initialize support array for ddSupportStep. */ size = ddMax( dd->size, dd->sizeZ ); support = ABC_ALLOC( int, size ); if ( support == NULL ) { dd->errorCode = CUDD_MEMORY_OUT; return ( NULL ); } for ( i = 0; i < size; i++ ) { support[i] = 0; } /* Compute support and clean up markers. */ ddSupportStep( Cudd_Regular( f ), support ); ddClearFlag( Cudd_Regular( f ) ); /* Transform support from array to cube. */ do { dd->reordered = 0; res = DD_ONE( dd ); cuddRef( res ); for ( j = size - 1; j >= 0; j-- ) { /* for each level bottom-up */ i = ( j >= dd->size ) ? j : dd->invperm[j]; if ( support[i] == 1 ) { var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) ); ////////////////////////////////////////////////////////////////// var = Cudd_Not(var); ////////////////////////////////////////////////////////////////// cuddRef( var ); tmp = cuddBddAndRecur( dd, res, var ); if ( tmp == NULL ) { Cudd_RecursiveDeref( dd, res ); Cudd_RecursiveDeref( dd, var ); res = NULL; break; } cuddRef( tmp ); Cudd_RecursiveDeref( dd, res ); Cudd_RecursiveDeref( dd, var ); res = tmp; } } } while ( dd->reordered == 1 ); ABC_FREE( support ); if ( res != NULL ) cuddDeref( res ); return ( res ); } /* end of Extra_SupportNeg */ /**Function******************************************************************** Synopsis [Returns 1 if the BDD is the BDD of elementary variable.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddIsVar( DdNode * bFunc ) { bFunc = Cudd_Regular( bFunc ); if ( cuddIsConstant(bFunc) ) return 0; return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) ); } /**Function******************************************************************** Synopsis [Creates AND composed of the first nVars of the manager.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ) { DdNode * bFunc, * bTemp; int i; bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); for ( i = 0; i < nVars; i++ ) { bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bFunc ); return bFunc; } /**Function******************************************************************** Synopsis [Creates OR composed of the first nVars of the manager.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ) { DdNode * bFunc, * bTemp; int i; bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); for ( i = 0; i < nVars; i++ ) { bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bFunc ); return bFunc; } /**Function******************************************************************** Synopsis [Creates EXOR composed of the first nVars of the manager.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ) { DdNode * bFunc, * bTemp; int i; bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); for ( i = 0; i < nVars; i++ ) { bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bFunc ); return bFunc; } /**Function******************************************************************** Synopsis [Computes the set of primes as a ZDD.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ) { DdNode *res; do { dd->reordered = 0; res = extraZddPrimes(dd, F); if ( dd->reordered == 1 ) printf("\nReordering in Extra_zddPrimes()\n"); } while (dd->reordered == 1); return(res); } /* end of Extra_zddPrimes */ /**Function******************************************************************** Synopsis [Permutes the variables of the array of BDDs.] Description [Given a permutation in array permut, creates a new BDD with permuted variables. There should be an entry in array permut for each variable in the manager. The i-th entry of permut holds the index of the variable that is to substitute the i-th variable. The DDs in the resulting array are already referenced.] SideEffects [None] SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] ******************************************************************************/ void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ) { DdHashTable *table; int i, k; do { manager->reordered = 0; table = cuddHashTableInit( manager, 1, 2 ); /* permute the output functions one-by-one */ for ( i = 0; i < nNodes; i++ ) { bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut ); if ( bNodesOut[i] == NULL ) { /* deref the array of the already computed outputs */ for ( k = 0; k < i; k++ ) Cudd_RecursiveDeref( manager, bNodesOut[k] ); break; } cuddRef( bNodesOut[i] ); } /* Dispose of local cache. */ cuddHashTableQuit( table ); } while ( manager->reordered == 1 ); } /* end of Extra_bddPermuteArray */ /**Function******************************************************************** Synopsis [Computes the positive polarty cube composed of the first vars in the array.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) { DdNode * bRes; DdNode * bTemp; int i; bRes = b1; Cudd_Ref( bRes ); for ( i = 0; i < nVars; i++ ) { bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); return bRes; } /**Function******************************************************************** Synopsis [Changes the polarity of vars listed in the cube.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddChangePolarity( DdManager * dd, /* the DD manager */ DdNode * bFunc, DdNode * bVars) { DdNode *res; do { dd->reordered = 0; res = extraBddChangePolarity( dd, bFunc, bVars ); } while (dd->reordered == 1); return(res); } /* end of Extra_bddChangePolarity */ /**Function************************************************************* Synopsis [Checks if the given variable belongs to the cube.] Description [Return -1 if the var does not appear in the cube. Otherwise, returns polarity (0 or 1) of the var in the cube.] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_bddVarIsInCube( DdNode * bCube, int iVar ) { DdNode * bCube0, * bCube1; while ( Cudd_Regular(bCube)->index != CUDD_CONST_INDEX ) { bCube0 = Cudd_NotCond( cuddE(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) ); bCube1 = Cudd_NotCond( cuddT(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) ); // make sure it is a cube assert( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) || // bCube0 == 0 (Cudd_IsComplement(bCube1) && Cudd_Regular(bCube1)->index == CUDD_CONST_INDEX) ); // bCube1 == 0 // quit if it is the last one if ( Cudd_Regular(bCube)->index == iVar ) return (int)(Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX); // get the next cube if ( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) ) bCube = bCube1; else bCube = bCube0; } return -1; } /**Function************************************************************* Synopsis [Computes the AND of two BDD with different orders.] Description [Derives the result of Boolean AND of bF and bG in ddF. The array pPermute gives the mapping of variables of ddG into that of ddF.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ) { DdHashTable * table; DdNode * bRes; do { ddF->reordered = 0; table = cuddHashTableInit( ddF, 2, 256 ); if (table == NULL) return NULL; bRes = extraBddAndPermute( table, ddF, bF, ddG, bG, pPermute ); if ( bRes ) cuddRef( bRes ); cuddHashTableQuit( table ); if ( bRes ) cuddDeref( bRes ); //if ( ddF->reordered == 1 ) //printf( "Reordering happened\n" ); } while ( ddF->reordered == 1 ); //printf( "|F| =%6d |G| =%6d |H| =%6d |F|*|G| =%9d\n", // Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes), // Cudd_DagSize(bF) * Cudd_DagSize(bG) ); return ( bRes ); } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraBddMove( DdManager * dd, /* the DD manager */ DdNode * bF, DdNode * bDist) { DdNode * bRes; if ( Cudd_IsConstant(bF) ) return bF; if ( (bRes = cuddCacheLookup2(dd, extraBddMove, bF, bDist)) ) return bRes; else { DdNode * bRes0, * bRes1; DdNode * bF0, * bF1; DdNode * bFR = Cudd_Regular(bF); int VarNew; if ( Cudd_IsComplement(bDist) ) VarNew = bFR->index - Cudd_Not(bDist)->index; else VarNew = bFR->index + bDist->index; assert( VarNew < dd->size ); // cofactor the functions if ( bFR != bF ) // bFunc is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } bRes0 = extraBddMove( dd, bF0, bDist ); if ( bRes0 == NULL ) return NULL; cuddRef( bRes0 ); bRes1 = extraBddMove( dd, bF1, bDist ); if ( bRes1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); return NULL; } cuddRef( bRes1 ); /* only bRes0 and bRes1 are referenced at this point */ bRes = cuddBddIteRecur( dd, dd->vars[VarNew], bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bRes1 ); return NULL; } cuddRef( bRes ); Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bRes1 ); /* insert the result into cache */ cuddCacheInsert2( dd, extraBddMove, bF, bDist, bRes ); cuddDeref( bRes ); return bRes; } } /* end of extraBddMove */ /**Function******************************************************************** Synopsis [Finds three cofactors of the cover w.r.t. to the topmost variable.] Description [Finds three cofactors of the cover w.r.t. to the topmost variable. Does not check the cover for being a constant. Assumes that ZDD variables encoding positive and negative polarities are adjacent in the variable order. Is different from cuddZddGetCofactors3() in that it does not compute the cofactors w.r.t. the given variable but takes the cofactors with respent to the topmost variable. This function is more efficient when used in recursive procedures because it does not require referencing of the resulting cofactors (compare cuddZddProduct() and extraZddPrimeProduct()).] SideEffects [None] SeeAlso [cuddZddGetCofactors3] ******************************************************************************/ void extraDecomposeCover( DdManager* dd, /* the manager */ DdNode* zC, /* the cover */ DdNode** zC0, /* the pointer to the negative var cofactor */ DdNode** zC1, /* the pointer to the positive var cofactor */ DdNode** zC2 ) /* the pointer to the cofactor without var */ { if ( (zC->index & 1) == 0 ) { /* the top variable is present in positive polarity and maybe in negative */ DdNode *Temp = cuddE( zC ); *zC1 = cuddT( zC ); if ( cuddIZ(dd,Temp->index) == cuddIZ(dd,zC->index) + 1 ) { /* Temp is not a terminal node * top var is present in negative polarity */ *zC2 = cuddE( Temp ); *zC0 = cuddT( Temp ); } else { /* top var is not present in negative polarity */ *zC2 = Temp; *zC0 = dd->zero; } } else { /* the top variable is present only in negative */ *zC1 = dd->zero; *zC2 = cuddE( zC ); *zC0 = cuddT( zC ); } } /* extraDecomposeCover */ /**Function******************************************************************** Synopsis [Counts the total number of cubes in the ISOPs of the functions.] Description [Returns -1 if the number of cubes exceeds the limit.] SideEffects [None] SeeAlso [Extra_TransferPermute] ******************************************************************************/ static DdNode * extraBddCountCubes( DdManager * dd, DdNode * L, DdNode * U, st__table *table, int * pnCubes, int Limit ) { DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); int v, top_l, top_u; DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; DdNode *Isub0, *Isub1, *Id; DdNode *x; DdNode *term0, *term1, *sum; DdNode *Lv, *Uv, *Lnv, *Unv; DdNode *r; int index; int Count0 = 0, Count1 = 0, Count2 = 0; statLine(dd); if (L == zero) { *pnCubes = 0; return(zero); } if (U == one) { *pnCubes = 1; return(one); } /* Check cache */ r = cuddCacheLookup2(dd, cuddBddIsop, L, U); if (r) { int nCubes = 0; if ( st__lookup( table, (char *)r, (char **)&nCubes ) ) *pnCubes = nCubes; else assert( 0 ); return r; } top_l = dd->perm[Cudd_Regular(L)->index]; top_u = dd->perm[Cudd_Regular(U)->index]; v = ddMin(top_l, top_u); /* Compute cofactors */ if (top_l == v) { index = Cudd_Regular(L)->index; Lv = Cudd_T(L); Lnv = Cudd_E(L); if (Cudd_IsComplement(L)) { Lv = Cudd_Not(Lv); Lnv = Cudd_Not(Lnv); } } else { index = Cudd_Regular(U)->index; Lv = Lnv = L; } if (top_u == v) { Uv = Cudd_T(U); Unv = Cudd_E(U); if (Cudd_IsComplement(U)) { Uv = Cudd_Not(Uv); Unv = Cudd_Not(Unv); } } else { Uv = Unv = U; } Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); if (Lsub0 == NULL) return(NULL); Cudd_Ref(Lsub0); Usub0 = Unv; Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); if (Lsub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); return(NULL); } Cudd_Ref(Lsub1); Usub1 = Uv; Isub0 = extraBddCountCubes(dd, Lsub0, Usub0, table, &Count0, Limit); if (Isub0 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); return(NULL); } Cudd_Ref(Isub0); Isub1 = extraBddCountCubes(dd, Lsub1, Usub1, table, &Count1, Limit); if (Isub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Cudd_RecursiveDeref(dd, Isub0); return(NULL); } Cudd_Ref(Isub1); Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); if (Lsuper0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); return(NULL); } Cudd_Ref(Lsuper0); Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); if (Lsuper1 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); return(NULL); } Cudd_Ref(Lsuper1); Usuper0 = Unv; Usuper1 = Uv; /* Ld = Lsuper0 + Lsuper1 */ Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); Ld = Cudd_NotCond(Ld, Ld != NULL); if (Ld == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); return(NULL); } Cudd_Ref(Ld); Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); if (Ud == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Cudd_RecursiveDeref(dd, Ld); return(NULL); } Cudd_Ref(Ud); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Id = extraBddCountCubes(dd, Ld, Ud, table, &Count2, Limit); if (Id == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); return(NULL); } Cudd_Ref(Id); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); x = cuddUniqueInter(dd, index, one, zero); if (x == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); return(NULL); } Cudd_Ref(x); term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); if (term0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, x); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDeref(dd, Isub0); term1 = cuddBddAndRecur(dd, x, Isub1); if (term1 == NULL) { Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, term0); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, Isub1); /* sum = term0 + term1 */ sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); sum = Cudd_NotCond(sum, sum != NULL); if (sum == NULL) { Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); return(NULL); } Cudd_Ref(sum); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); /* r = sum + Id */ r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); r = Cudd_NotCond(r, r != NULL); if (r == NULL) { Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, sum); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDeref(dd, sum); Cudd_RecursiveDeref(dd, Id); cuddCacheInsert2(dd, cuddBddIsop, L, U, r); *pnCubes = Count0 + Count1 + Count2; if ( st__add_direct( table, (char *)r, (char *)(ABC_PTRINT_T)*pnCubes ) == st__OUT_OF_MEM ) { Cudd_RecursiveDeref( dd, r ); return NULL; } if ( *pnCubes > Limit ) { Cudd_RecursiveDeref( dd, r ); return NULL; } //printf( "%d ", *pnCubes ); Cudd_Deref(r); return r; } int Extra_bddCountCubes( DdManager * dd, DdNode ** pFuncs, int nFuncs, int fMode, int nLimit, int * pGuide ) { DdNode * pF0, * pF1; int i, Count, Count0, Count1, CounterAll = 0; st__table *table = st__init_table( st__ptrcmp, st__ptrhash ); unsigned int saveLimit = dd->maxLive; dd->maxLive = dd->keys - dd->dead + 1000000; // limit on intermediate BDD nodes for ( i = 0; i < nFuncs; i++ ) { if ( !pFuncs[i] ) continue; pF1 = pF0 = NULL; Count0 = Count1 = nLimit; if ( fMode == -1 || fMode == 1 ) // both or pos pF1 = extraBddCountCubes( dd, pFuncs[i], pFuncs[i], table, &Count1, nLimit ); pFuncs[i] = Cudd_Not( pFuncs[i] ); if ( fMode == -1 || fMode == 0 ) // both or neg pF0 = extraBddCountCubes( dd, pFuncs[i], pFuncs[i], table, &Count0, Count1 ); pFuncs[i] = Cudd_Not( pFuncs[i] ); if ( !pF1 && !pF0 ) break; if ( !pF0 ) pGuide[i] = 1, Count = Count1; // use pos else if ( !pF1 ) pGuide[i] = 0, Count = Count0; // use neg else if ( Count1 <= Count0 ) pGuide[i] = 1, Count = Count1; // use pos else pGuide[i] = 0, Count = Count0; // use neg CounterAll += Count; //printf( "Output %5d has %5d cubes (%d) (%5d and %5d)\n", nOuts++, Count, pGuide[i], Count1, Count0 ); } dd->maxLive = saveLimit; st__free_table( table ); return i == nFuncs ? CounterAll : -1; } /* end of Extra_bddCountCubes */ /*---------------------------------------------------------------------------*/ /* Definition of static Functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Convert a BDD from a manager to another one.] Description [Convert a BDD from a manager to another one. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.] SideEffects [None] SeeAlso [Extra_TransferPermute] ******************************************************************************/ DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) { DdNode *res; st__table *table = NULL; st__generator *gen = NULL; DdNode *key, *value; table = st__init_table( st__ptrcmp, st__ptrhash ); if ( table == NULL ) goto failure; res = extraTransferPermuteRecur( ddS, ddD, f, table, Permute ); if ( res != NULL ) cuddRef( res ); /* Dereference all elements in the table and dispose of the table. ** This must be done also if res is NULL to avoid leaks in case of ** reordering. */ gen = st__init_gen( table ); if ( gen == NULL ) goto failure; while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) ) { Cudd_RecursiveDeref( ddD, value ); } st__free_gen( gen ); gen = NULL; st__free_table( table ); table = NULL; if ( res != NULL ) cuddDeref( res ); return ( res ); failure: if ( table != NULL ) st__free_table( table ); if ( gen != NULL ) st__free_gen( gen ); return ( NULL ); } /* end of extraTransferPermute */ /**Function******************************************************************** Synopsis [Performs the recursive step of Extra_TransferPermute.] Description [Performs the recursive step of Extra_TransferPermute. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [extraTransferPermute] ******************************************************************************/ static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute ) { DdNode *ft, *fe, *t, *e, *var, *res; DdNode *one, *zero; int index; int comple = 0; statLine( ddD ); one = DD_ONE( ddD ); comple = Cudd_IsComplement( f ); /* Trivial cases. */ if ( Cudd_IsConstant( f ) ) return ( Cudd_NotCond( one, comple ) ); /* Make canonical to increase the utilization of the cache. */ f = Cudd_NotCond( f, comple ); /* Now f is a regular pointer to a non-constant node. */ /* Check the cache. */ if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) ) return ( Cudd_NotCond( res, comple ) ); if ( ddS->TimeStop && Abc_Clock() > ddS->TimeStop ) return NULL; if ( ddD->TimeStop && Abc_Clock() > ddD->TimeStop ) return NULL; /* Recursive step. */ if ( Permute ) index = Permute[f->index]; else index = f->index; ft = cuddT( f ); fe = cuddE( f ); t = extraTransferPermuteRecur( ddS, ddD, ft, table, Permute ); if ( t == NULL ) { return ( NULL ); } cuddRef( t ); e = extraTransferPermuteRecur( ddS, ddD, fe, table, Permute ); if ( e == NULL ) { Cudd_RecursiveDeref( ddD, t ); return ( NULL ); } cuddRef( e ); zero = Cudd_Not(ddD->one); var = cuddUniqueInter( ddD, index, one, zero ); if ( var == NULL ) { Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); return ( NULL ); } res = cuddBddIteRecur( ddD, var, t, e ); if ( res == NULL ) { Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); return ( NULL ); } cuddRef( res ); Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); if ( st__add_direct( table, ( char * ) f, ( char * ) res ) == st__OUT_OF_MEM ) { Cudd_RecursiveDeref( ddD, res ); return ( NULL ); } return ( Cudd_NotCond( res, comple ) ); } /* end of extraTransferPermuteRecur */ /**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_Support.] Description [Performs the recursive step of Cudd_Support. Performs a DFS from f. The support is accumulated in supp as a side effect. Uses the LSB of the then pointer as visited flag.] SideEffects [None] SeeAlso [ddClearFlag] ******************************************************************************/ static void ddSupportStep( DdNode * f, int * support) { if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { return; } support[f->index] = 1; ddSupportStep(cuddT(f),support); ddSupportStep(Cudd_Regular(cuddE(f)),support); /* Mark as visited. */ f->next = Cudd_Not(f->next); return; } /* end of ddSupportStep */ /**Function******************************************************************** Synopsis [Performs a DFS from f, clearing the LSB of the next pointers.] Description [] SideEffects [None] SeeAlso [ddSupportStep ddDagInt] ******************************************************************************/ static void ddClearFlag( DdNode * f) { if (!Cudd_IsComplement(f->next)) { return; } /* Clear visited flag. */ f->next = Cudd_Regular(f->next); if (cuddIsConstant(f)) { return; } ddClearFlag(cuddT(f)); ddClearFlag(Cudd_Regular(cuddE(f))); return; } /* end of ddClearFlag */ /**Function******************************************************************** Synopsis [Composed three subcovers into one ZDD.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * extraComposeCover( DdManager* dd, /* the manager */ DdNode* zC0, /* the pointer to the negative var cofactor */ DdNode* zC1, /* the pointer to the positive var cofactor */ DdNode* zC2, /* the pointer to the cofactor without var */ int TopVar) /* the index of the positive ZDD var */ { DdNode * zRes, * zTemp; /* compose with-neg-var and without-var using the neg ZDD var */ zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 ); if ( zTemp == NULL ) { Cudd_RecursiveDerefZdd(dd, zC0); Cudd_RecursiveDerefZdd(dd, zC1); Cudd_RecursiveDerefZdd(dd, zC2); return NULL; } cuddRef( zTemp ); cuddDeref( zC0 ); cuddDeref( zC2 ); /* compose with-pos-var and previous result using the pos ZDD var */ zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd(dd, zC1); Cudd_RecursiveDerefZdd(dd, zTemp); return NULL; } cuddDeref( zC1 ); cuddDeref( zTemp ); return zRes; } /* extraComposeCover */ /**Function******************************************************************** Synopsis [Performs the recursive step of prime computation.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode* extraZddPrimes( DdManager *dd, DdNode* F ) { DdNode *zRes; if ( F == Cudd_Not( dd->one ) ) return dd->zero; if ( F == dd->one ) return dd->one; /* check cache */ zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F); if (zRes) return(zRes); { /* temporary variables */ DdNode *bF01, *zP0, *zP1; /* three components of the prime set */ DdNode *zResE, *zResP, *zResN; int fIsComp = Cudd_IsComplement( F ); /* find cofactors of F */ DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp ); DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp ); /* find the intersection of cofactors */ bF01 = cuddBddAndRecur( dd, bF0, bF1 ); if ( bF01 == NULL ) return NULL; cuddRef( bF01 ); /* solve the problems for cofactors */ zP0 = extraZddPrimes( dd, bF0 ); if ( zP0 == NULL ) { Cudd_RecursiveDeref( dd, bF01 ); return NULL; } cuddRef( zP0 ); zP1 = extraZddPrimes( dd, bF1 ); if ( zP1 == NULL ) { Cudd_RecursiveDeref( dd, bF01 ); Cudd_RecursiveDerefZdd( dd, zP0 ); return NULL; } cuddRef( zP1 ); /* check for local unateness */ if ( bF01 == bF0 ) /* unate increasing */ { /* intersection is useless */ cuddDeref( bF01 ); /* the primes of intersection are the primes of F0 */ zResE = zP0; /* there are no primes with negative var */ zResN = dd->zero; cuddRef( zResN ); /* primes with positive var are primes of F1 that are not primes of F01 */ zResP = cuddZddDiff( dd, zP1, zP0 ); if ( zResP == NULL ) { Cudd_RecursiveDerefZdd( dd, zResE ); Cudd_RecursiveDerefZdd( dd, zResN ); Cudd_RecursiveDerefZdd( dd, zP1 ); return NULL; } cuddRef( zResP ); Cudd_RecursiveDerefZdd( dd, zP1 ); } else if ( bF01 == bF1 ) /* unate decreasing */ { /* intersection is useless */ cuddDeref( bF01 ); /* the primes of intersection are the primes of F1 */ zResE = zP1; /* there are no primes with positive var */ zResP = dd->zero; cuddRef( zResP ); /* primes with negative var are primes of F0 that are not primes of F01 */ zResN = cuddZddDiff( dd, zP0, zP1 ); if ( zResN == NULL ) { Cudd_RecursiveDerefZdd( dd, zResE ); Cudd_RecursiveDerefZdd( dd, zResP ); Cudd_RecursiveDerefZdd( dd, zP0 ); return NULL; } cuddRef( zResN ); Cudd_RecursiveDerefZdd( dd, zP0 ); } else /* not unate */ { /* primes without the top var are primes of F10 */ zResE = extraZddPrimes( dd, bF01 ); if ( zResE == NULL ) { Cudd_RecursiveDerefZdd( dd, bF01 ); Cudd_RecursiveDerefZdd( dd, zP0 ); Cudd_RecursiveDerefZdd( dd, zP1 ); return NULL; } cuddRef( zResE ); Cudd_RecursiveDeref( dd, bF01 ); /* primes with the negative top var are those of P0 that are not in F10 */ zResN = cuddZddDiff( dd, zP0, zResE ); if ( zResN == NULL ) { Cudd_RecursiveDerefZdd( dd, zResE ); Cudd_RecursiveDerefZdd( dd, zP0 ); Cudd_RecursiveDerefZdd( dd, zP1 ); return NULL; } cuddRef( zResN ); Cudd_RecursiveDerefZdd( dd, zP0 ); /* primes with the positive top var are those of P1 that are not in F10 */ zResP = cuddZddDiff( dd, zP1, zResE ); if ( zResP == NULL ) { Cudd_RecursiveDerefZdd( dd, zResE ); Cudd_RecursiveDerefZdd( dd, zResN ); Cudd_RecursiveDerefZdd( dd, zP1 ); return NULL; } cuddRef( zResP ); Cudd_RecursiveDerefZdd( dd, zP1 ); } zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index ); if ( zRes == NULL ) return NULL; /* insert the result into cache */ cuddCacheInsert1(dd, extraZddPrimes, F, zRes); return zRes; } } /* end of extraZddPrimes */ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddPermute.] Description [ Recursively puts the BDD in the order given in the array permut. Checks for trivial cases to terminate recursion, then splits on the children of this node. Once the solutions for the children are obtained, it puts into the current position the node from the rest of the BDD that should be here. Then returns this BDD. The key here is that the node being visited is NOT put in its proper place by this instance, but rather is switched when its proper position is reached in the recursion tree.

        The DdNode * that is returned is the same BDD as passed in as node, but in the new order.] SideEffects [None] SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] ******************************************************************************/ static DdNode * cuddBddPermuteRecur( DdManager * manager /* DD manager */ , DdHashTable * table /* computed table */ , DdNode * node /* BDD to be reordered */ , int *permut /* permutation array */ ) { DdNode *N, *T, *E; DdNode *res; int index; statLine( manager ); N = Cudd_Regular( node ); /* Check for terminal case of constant node. */ if ( cuddIsConstant( N ) ) { return ( node ); } /* If problem already solved, look up answer and return. */ if ( N->ref != 1 && ( res = cuddHashTableLookup1( table, N ) ) != NULL ) { return ( Cudd_NotCond( res, N != node ) ); } /* Split and recur on children of this node. */ T = cuddBddPermuteRecur( manager, table, cuddT( N ), permut ); if ( T == NULL ) return ( NULL ); cuddRef( T ); E = cuddBddPermuteRecur( manager, table, cuddE( N ), permut ); if ( E == NULL ) { Cudd_IterDerefBdd( manager, T ); return ( NULL ); } cuddRef( E ); /* Move variable that should be in this position to this position ** by retrieving the single var BDD for that variable, and calling ** cuddBddIteRecur with the T and E we just created. */ index = permut[N->index]; res = cuddBddIteRecur( manager, manager->vars[index], T, E ); if ( res == NULL ) { Cudd_IterDerefBdd( manager, T ); Cudd_IterDerefBdd( manager, E ); return ( NULL ); } cuddRef( res ); Cudd_IterDerefBdd( manager, T ); Cudd_IterDerefBdd( manager, E ); /* Do not keep the result if the reference count is only 1, since ** it will not be visited again. */ if ( N->ref != 1 ) { ptrint fanout = ( ptrint ) N->ref; cuddSatDec( fanout ); if ( !cuddHashTableInsert1( table, N, res, fanout ) ) { Cudd_IterDerefBdd( manager, res ); return ( NULL ); } } cuddDeref( res ); return ( Cudd_NotCond( res, N != node ) ); } /* end of cuddBddPermuteRecur */ /**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_bddChangePolarity().] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraBddChangePolarity( DdManager * dd, /* the DD manager */ DdNode * bFunc, DdNode * bVars) { DdNode * bRes; if ( bVars == b1 ) return bFunc; if ( Cudd_IsConstant(bFunc) ) return bFunc; if ( (bRes = cuddCacheLookup2(dd, extraBddChangePolarity, bFunc, bVars)) ) return bRes; else { DdNode * bFR = Cudd_Regular(bFunc); int LevelF = dd->perm[bFR->index]; int LevelV = dd->perm[bVars->index]; if ( LevelV < LevelF ) bRes = extraBddChangePolarity( dd, bFunc, cuddT(bVars) ); else // if ( LevelF <= LevelV ) { DdNode * bRes0, * bRes1; DdNode * bF0, * bF1; DdNode * bVarsNext; // cofactor the functions if ( bFR != bFunc ) // bFunc is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } if ( LevelF == LevelV ) bVarsNext = cuddT(bVars); else bVarsNext = bVars; bRes0 = extraBddChangePolarity( dd, bF0, bVarsNext ); if ( bRes0 == NULL ) return NULL; cuddRef( bRes0 ); bRes1 = extraBddChangePolarity( dd, bF1, bVarsNext ); if ( bRes1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); return NULL; } cuddRef( bRes1 ); if ( LevelF == LevelV ) { // swap the cofactors DdNode * bTemp; bTemp = bRes0; bRes0 = bRes1; bRes1 = bTemp; } /* only aRes0 and aRes1 are referenced at this point */ /* consider the case when Res0 and Res1 are the same node */ if ( bRes0 == bRes1 ) bRes = bRes1; /* consider the case when Res1 is complemented */ else if ( Cudd_IsComplement(bRes1) ) { bRes = cuddUniqueInter(dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0)); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } bRes = Cudd_Not(bRes); } else { bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } } cuddDeref( bRes0 ); cuddDeref( bRes1 ); } /* insert the result into cache */ cuddCacheInsert2(dd, extraBddChangePolarity, bFunc, bVars, bRes); return bRes; } } /* end of extraBddChangePolarity */ static int Counter = 0; /**Function************************************************************* Synopsis [Computes the AND of two BDD with different orders.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ) { DdNode * bF0, * bF1, * bG0, * bG1, * bRes0, * bRes1, * bRes, * bVar; int LevF, LevG, Lev; // if F == 0, return 0 if ( bF == Cudd_Not(ddF->one) ) return Cudd_Not(ddF->one); // if G == 0, return 0 if ( bG == Cudd_Not(ddG->one) ) return Cudd_Not(ddF->one); // if G == 1, return F if ( bG == ddG->one ) return bF; // cannot use F == 1, because the var order of G has to be changed // check cache if ( //(Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1) && (bRes = cuddHashTableLookup2(table, bF, bG)) ) return bRes; Counter++; if ( ddF->TimeStop && Abc_Clock() > ddF->TimeStop ) return NULL; if ( ddG->TimeStop && Abc_Clock() > ddG->TimeStop ) return NULL; // find the topmost variable in F and G using var order of F LevF = cuddI( ddF, Cudd_Regular(bF)->index ); LevG = cuddI( ddF, pPermute ? pPermute[Cudd_Regular(bG)->index] : Cudd_Regular(bG)->index ); Lev = Abc_MinInt( LevF, LevG ); assert( Lev < ddF->size ); bVar = ddF->vars[ddF->invperm[Lev]]; // cofactor bF0 = (Lev < LevF) ? bF : Cudd_NotCond( cuddE(Cudd_Regular(bF)), Cudd_IsComplement(bF) ); bF1 = (Lev < LevF) ? bF : Cudd_NotCond( cuddT(Cudd_Regular(bF)), Cudd_IsComplement(bF) ); bG0 = (Lev < LevG) ? bG : Cudd_NotCond( cuddE(Cudd_Regular(bG)), Cudd_IsComplement(bG) ); bG1 = (Lev < LevG) ? bG : Cudd_NotCond( cuddT(Cudd_Regular(bG)), Cudd_IsComplement(bG) ); // call for cofactors bRes0 = extraBddAndPermute( table, ddF, bF0, ddG, bG0, pPermute ); if ( bRes0 == NULL ) return NULL; cuddRef( bRes0 ); // call for cofactors bRes1 = extraBddAndPermute( table, ddF, bF1, ddG, bG1, pPermute ); if ( bRes1 == NULL ) { Cudd_IterDerefBdd( ddF, bRes0 ); return NULL; } cuddRef( bRes1 ); // compose the result bRes = cuddBddIteRecur( ddF, bVar, bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_IterDerefBdd( ddF, bRes0 ); Cudd_IterDerefBdd( ddF, bRes1 ); return NULL; } cuddRef( bRes ); Cudd_IterDerefBdd( ddF, bRes0 ); Cudd_IterDerefBdd( ddF, bRes1 ); // cache the result // if ( Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1 ) { ptrint fanout = (ptrint)Cudd_Regular(bF)->ref * Cudd_Regular(bG)->ref; cuddSatDec(fanout); cuddHashTableInsert2( table, bF, bG, bRes, fanout ); } cuddDeref( bRes ); return bRes; } /**Function************************************************************* Synopsis [Testbench.] Description [This procedure takes BDD manager ddF and two BDDs in this manager (bF and bG). It creates a new manager ddG, transfers bG into it and then reorders it, resulting in bG2. Then it tries to compute the product of bF and bG2 in ddF.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TestAndPerm( DdManager * ddF, DdNode * bF, DdNode * bG ) { DdManager * ddG; DdNode * bG2, * bRes1, * bRes2; abctime clk; // disable variable ordering in ddF Cudd_AutodynDisable( ddF ); // create new BDD manager ddG = Cudd_Init( ddF->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // transfer BDD into it Cudd_ShuffleHeap( ddG, ddF->invperm ); bG2 = Extra_TransferLevelByLevel( ddF, ddG, bG ); Cudd_Ref( bG2 ); // reorder the new manager Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); // compute the result clk = Abc_Clock(); bRes1 = Cudd_bddAnd( ddF, bF, bG ); Cudd_Ref( bRes1 ); Abc_PrintTime( 1, "Runtime of Cudd_bddAnd ", Abc_Clock() - clk ); // compute the result Counter = 0; clk = Abc_Clock(); bRes2 = Extra_bddAndPermute( ddF, bF, ddG, bG2, NULL ); Cudd_Ref( bRes2 ); Abc_PrintTime( 1, "Runtime of new procedure", Abc_Clock() - clk ); printf( "Recursive calls = %d\n", Counter ); printf( "|F| =%6d |G| =%6d |H| =%6d |F|*|G| =%9d ", Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes2), Cudd_DagSize(bF) * Cudd_DagSize(bG) ); if ( bRes1 == bRes2 ) printf( "Result verified.\n\n" ); else printf( "Result is incorrect.\n\n" ); Cudd_RecursiveDeref( ddF, bRes1 ); Cudd_RecursiveDeref( ddF, bRes2 ); // quit the new manager Cudd_RecursiveDeref( ddG, bG2 ); Extra_StopManager( ddG ); // re-enable variable ordering in ddF Cudd_AutodynEnable( ddF, CUDD_REORDER_SYMM_SIFT ); } /**Function************************************************************* Synopsis [Writes ZDD into a PLA file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_zddDumpPla( DdManager * dd, DdNode * F, int nVars, char * pFileName ) { DdGen *gen; char * pCube; int * pPath, i; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } fprintf( pFile, "# PLA file dumped by Extra_zddDumpPla() in ABC\n" ); fprintf( pFile, ".i %d\n", nVars ); fprintf( pFile, ".o 1\n" ); pCube = ABC_CALLOC( char, dd->sizeZ ); Cudd_zddForeachPath( dd, F, gen, pPath ) { for ( i = 0; i < nVars; i++ ) pCube[i] = '-'; for ( i = 0; i < nVars; i++ ) if ( pPath[2*i] == 1 || pPath[2*i+1] == 1 ) pCube[i] = '0' + (pPath[2*i] == 1); fprintf( pFile, "%s 1\n", pCube ); } fprintf( pFile, ".e\n\n" ); fclose( pFile ); ABC_FREE( pCube ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddSymm.c000066400000000000000000001336001300674244400246240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddSymm.c] PackageName [extra] Synopsis [Efficient methods to compute the information about symmetric variables using the algorithm presented in the paper: A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. Transactions on CAD, Nov. 2003.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - September 1, 2003.] Revision [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "extraBdd.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ #define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the classical symmetry information for the function.] Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.] SideEffects [If the ZDD variables are not derived from BDD variables with multiplicity 2, this function may derive them in a wrong way.] SeeAlso [] ******************************************************************************/ Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, /* the manager */ DdNode * bFunc) /* the function whose symmetries are computed */ { DdNode * bSupp; DdNode * zRes; Extra_SymmInfo_t * p; bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp ); Cudd_RecursiveDeref( dd, bSupp ); Cudd_RecursiveDerefZdd( dd, zRes ); return p; } /* end of Extra_SymmPairsCompute */ /**Function******************************************************************** Synopsis [Computes the classical symmetry information as a ZDD.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_zddSymmPairsCompute( DdManager * dd, /* the DD manager */ DdNode * bF, DdNode * bVars) { DdNode * res; do { dd->reordered = 0; res = extraZddSymmPairsCompute( dd, bF, bVars ); } while (dd->reordered == 1); return(res); } /* end of Extra_zddSymmPairsCompute */ /**Function******************************************************************** Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_zddGetSymmetricVars( DdManager * dd, /* the DD manager */ DdNode * bF, /* the first function - originally, the positive cofactor */ DdNode * bG, /* the second fucntion - originally, the negative cofactor */ DdNode * bVars) /* the set of variables, on which F and G depend */ { DdNode * res; do { dd->reordered = 0; res = extraZddGetSymmetricVars( dd, bF, bG, bVars ); } while (dd->reordered == 1); return(res); } /* end of Extra_zddGetSymmetricVars */ /**Function******************************************************************** Synopsis [Converts a set of variables into a set of singleton subsets.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_zddGetSingletons( DdManager * dd, /* the DD manager */ DdNode * bVars) /* the set of variables */ { DdNode * res; do { dd->reordered = 0; res = extraZddGetSingletons( dd, bVars ); } while (dd->reordered == 1); return(res); } /* end of Extra_zddGetSingletons */ /**Function******************************************************************** Synopsis [Filters the set of variables using the support of the function.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_bddReduceVarSet( DdManager * dd, /* the DD manager */ DdNode * bVars, /* the set of variables to be reduced */ DdNode * bF) /* the function whose support is used for reduction */ { DdNode * res; do { dd->reordered = 0; res = extraBddReduceVarSet( dd, bVars, bF ); } while (dd->reordered == 1); return(res); } /* end of Extra_bddReduceVarSet */ /**Function******************************************************************** Synopsis [Allocates symmetry information structure.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ) { int i; Extra_SymmInfo_t * p; // allocate and clean the storage for symmetry info p = ABC_ALLOC( Extra_SymmInfo_t, 1 ); memset( p, 0, sizeof(Extra_SymmInfo_t) ); p->nVars = nVars; p->pVars = ABC_ALLOC( int, nVars ); p->pSymms = ABC_ALLOC( char *, nVars ); p->pSymms[0] = ABC_ALLOC( char , nVars * nVars ); memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) ); for ( i = 1; i < nVars; i++ ) p->pSymms[i] = p->pSymms[i-1] + nVars; return p; } /* end of Extra_SymmPairsAllocate */ /**Function******************************************************************** Synopsis [Deallocates symmetry information structure.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Extra_SymmPairsDissolve( Extra_SymmInfo_t * p ) { ABC_FREE( p->pVars ); ABC_FREE( p->pSymms[0] ); ABC_FREE( p->pSymms ); ABC_FREE( p ); } /* end of Extra_SymmPairsDissolve */ /**Function******************************************************************** Synopsis [Allocates symmetry information structure.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Extra_SymmPairsPrint( Extra_SymmInfo_t * p ) { int i, k; printf( "\n" ); for ( i = 0; i < p->nVars; i++ ) { for ( k = 0; k <= i; k++ ) printf( " " ); for ( k = i+1; k < p->nVars; k++ ) if ( p->pSymms[i][k] ) printf( "1" ); else printf( "." ); printf( "\n" ); } } /* end of Extra_SymmPairsPrint */ /**Function******************************************************************** Synopsis [Creates the symmetry information structure from ZDD.] Description [ZDD representation of symmetries is the set of cubes, each of which has two variables in the positive polarity. These variables correspond to the symmetric variable pair.] SideEffects [] SeeAlso [] ******************************************************************************/ Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) { int i; int nSuppSize; Extra_SymmInfo_t * p; int * pMapVars2Nums; DdNode * bTemp; DdNode * zSet, * zCube, * zTemp; int iVar1, iVar2; nSuppSize = Extra_bddSuppSize( dd, bSupp ); // allocate and clean the storage for symmetry info p = Extra_SymmPairsAllocate( nSuppSize ); // allocate the storage for the temporary map pMapVars2Nums = ABC_ALLOC( int, dd->size ); memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); // assign the variables p->nVarsMax = dd->size; // p->nNodes = Cudd_DagSize( zPairs ); p->nNodes = 0; for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) { p->pVars[i] = bTemp->index; pMapVars2Nums[bTemp->index] = i; } // write the symmetry info into the structure zSet = zPairs; Cudd_Ref( zSet ); while ( zSet != z0 ) { // get the next cube zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); // add these two variables to the data structure assert( cuddT( cuddT(zCube) ) == z1 ); iVar1 = zCube->index/2; iVar2 = cuddT(zCube)->index/2; if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] ) p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1; else p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1; // count the symmetric pairs p->nSymms ++; // update the cuver and deref the cube zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zCube ); } // for each cube Cudd_RecursiveDerefZdd( dd, zSet ); ABC_FREE( pMapVars2Nums ); return p; } /* end of Extra_SymmPairsCreateFromZdd */ /**Function******************************************************************** Synopsis [Checks the possibility of two variables being symmetric.] Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddCheckVarsSymmetric( DdManager * dd, /* the DD manager */ DdNode * bF, int iVar1, int iVar2) { DdNode * bVars; int Res; // return 1; assert( iVar1 != iVar2 ); assert( iVar1 < dd->size ); assert( iVar2 < dd->size ); bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] ); Cudd_Ref( bVars ); Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 ); Cudd_RecursiveDeref( dd, bVars ); return Res; } /* end of Extra_bddCheckVarsSymmetric */ /**Function******************************************************************** Synopsis [Computes the classical symmetry information for the function.] Description [Uses the naive way of comparing cofactors.] SideEffects [] SeeAlso [] ******************************************************************************/ Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ) { DdNode * bSupp, * bTemp; int nSuppSize; Extra_SymmInfo_t * p; int i, k; // compute the support bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); nSuppSize = Extra_bddSuppSize( dd, bSupp ); //printf( "Support = %d. ", nSuppSize ); //Extra_bddPrint( dd, bSupp ); //printf( "%d ", nSuppSize ); // allocate the storage for symmetry info p = Extra_SymmPairsAllocate( nSuppSize ); // assign the variables p->nVarsMax = dd->size; for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) p->pVars[i] = bTemp->index; // go through the candidate pairs and check using Idea1 for ( i = 0; i < nSuppSize; i++ ) for ( k = i+1; k < nSuppSize; k++ ) { p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] ); if ( p->pSymms[i][k] ) p->nSymms++; } Cudd_RecursiveDeref( dd, bSupp ); return p; } /* end of Extra_SymmPairsComputeNaive */ /**Function******************************************************************** Synopsis [Checks if the two variables are symmetric.] Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, /* the DD manager */ DdNode * bF, int iVar1, int iVar2) { DdNode * bCube1, * bCube2; DdNode * bCof01, * bCof10; int Res; assert( iVar1 != iVar2 ); assert( iVar1 < dd->size ); assert( iVar2 < dd->size ); bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 ); bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 ); bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 ); bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 ); Res = (int)( bCof10 == bCof01 ); Cudd_RecursiveDeref( dd, bCof01 ); Cudd_RecursiveDeref( dd, bCof10 ); Cudd_RecursiveDeref( dd, bCube1 ); Cudd_RecursiveDeref( dd, bCube2 ); return Res; } /* end of Extra_bddCheckVarsSymmetricNaive */ /**Function******************************************************************** Synopsis [Builds ZDD representing the set of fixed-size variable tuples.] Description [Creates ZDD of all combinations of variables in Support that is represented by a BDD.] SideEffects [New ZDD variables are created if indices of the variables present in the combination are larger than the currently allocated number of ZDD variables.] SeeAlso [] ******************************************************************************/ DdNode* Extra_zddTuplesFromBdd( DdManager * dd, /* the DD manager */ int K, /* the number of variables in tuples */ DdNode * bVarsN) /* the set of all variables represented as a BDD */ { DdNode *zRes; int autoDynZ; autoDynZ = dd->autoDynZ; dd->autoDynZ = 0; do { /* transform the numeric arguments (K) into a DdNode* argument; * this allows us to use the standard internal CUDD cache */ DdNode *bVarSet = bVarsN, *bVarsK = bVarsN; int nVars = 0, i; /* determine the number of variables in VarSet */ while ( bVarSet != b1 ) { nVars++; /* make sure that the VarSet is a cube */ if ( cuddE( bVarSet ) != b0 ) return NULL; bVarSet = cuddT( bVarSet ); } /* make sure that the number of variables in VarSet is less or equal that the number of variables that should be present in the tuples */ if ( K > nVars ) return NULL; /* the second argument in the recursive call stannds for ; * reate the first argument, which stands for * as when we are talking about the tuple of out of */ for ( i = 0; i < nVars-K; i++ ) bVarsK = cuddT( bVarsK ); dd->reordered = 0; zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN ); } while (dd->reordered == 1); dd->autoDynZ = autoDynZ; return zRes; } /* end of Extra_zddTuplesFromBdd */ /**Function******************************************************************** Synopsis [Selects one subset from the set of subsets represented by a ZDD.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode* Extra_zddSelectOneSubset( DdManager * dd, /* the DD manager */ DdNode * zS) /* the ZDD */ { DdNode *res; do { dd->reordered = 0; res = extraZddSelectOneSubset(dd, zS); } while (dd->reordered == 1); return(res); } /* end of Extra_zddSelectOneSubset */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs a recursive step of Extra_SymmPairsCompute.] Description [Returns the set of symmetric variable pairs represented as a set of two-literal ZDD cubes. Both variables always appear in the positive polarity in the cubes. This function works without building new BDD nodes. Some relatively small number of ZDD nodes may be built to ensure proper bookkeeping of the symmetry information.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraZddSymmPairsCompute( DdManager * dd, /* the manager */ DdNode * bFunc, /* the function whose symmetries are computed */ DdNode * bVars ) /* the set of variables on which this function depends */ { DdNode * zRes; DdNode * bFR = Cudd_Regular(bFunc); if ( cuddIsConstant(bFR) ) { int nVars, i; // determine how many vars are in the bVars nVars = Extra_bddSuppSize( dd, bVars ); if ( nVars < 2 ) return z0; else { DdNode * bVarsK; // create the BDD bVarsK corresponding to K = 2; bVarsK = bVars; for ( i = 0; i < nVars-2; i++ ) bVarsK = cuddT( bVarsK ); return extraZddTuplesFromBdd( dd, bVarsK, bVars ); } } assert( bVars != b1 ); if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars)) ) return zRes; else { DdNode * zRes0, * zRes1; DdNode * zTemp, * zPlus, * zSymmVars; DdNode * bF0, * bF1; DdNode * bVarsNew; int nVarsExtra; int LevelF; // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F // count how many extra vars are there in bVars nVarsExtra = 0; LevelF = dd->perm[bFR->index]; for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) nVarsExtra++; // the indexes (level) of variables should be synchronized now assert( bFR->index == bVarsNew->index ); // cofactor the function if ( bFR != bFunc ) // bFunc is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } // solve subproblems zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) ); if ( zRes0 == NULL ) return NULL; cuddRef( zRes0 ); // if there is no symmetries in the negative cofactor // there is no need to test the positive cofactor if ( zRes0 == z0 ) zRes = zRes0; // zRes takes reference else { zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) ); if ( zRes1 == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes0 ); return NULL; } cuddRef( zRes1 ); // only those variables are pair-wise symmetric // that are pair-wise symmetric in both cofactors // therefore, intersect the solutions zRes = cuddZddIntersect( dd, zRes0, zRes1 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes0 ); Cudd_RecursiveDerefZdd( dd, zRes1 ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zRes0 ); Cudd_RecursiveDerefZdd( dd, zRes1 ); } // consider the current top-most variable and find all the vars // that are pairwise symmetric with it // these variables are returned as a set of ZDD singletons zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) ); if ( zSymmVars == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zSymmVars ); // attach the topmost variable to the set, to get the variable pairs // use the positive polarity ZDD variable for the purpose // there is no need to do so, if zSymmVars is empty if ( zSymmVars == z0 ) Cudd_RecursiveDerefZdd( dd, zSymmVars ); else { zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); Cudd_RecursiveDerefZdd( dd, zSymmVars ); return NULL; } cuddRef( zPlus ); cuddDeref( zSymmVars ); // add these variable pairs to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); } // only zRes is referenced at this point // if we skipped some variables, these variables cannot be symmetric with // any variables that are currently in the support of bF, but they can be // symmetric with the variables that are in bVars but not in the support of bF if ( nVarsExtra ) { // it is possible to improve this step: // (1) there is no need to enter here, if nVarsExtra < 2 // create the set of topmost nVarsExtra in bVars DdNode * bVarsExtra; int nVars; // remove from bVars all the variable that are in the support of bFunc bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc ); if ( bVarsExtra == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( bVarsExtra ); // determine how many vars are in the bVarsExtra nVars = Extra_bddSuppSize( dd, bVarsExtra ); if ( nVars < 2 ) { Cudd_RecursiveDeref( dd, bVarsExtra ); } else { int i; DdNode * bVarsK; // create the BDD bVarsK corresponding to K = 2; bVarsK = bVarsExtra; for ( i = 0; i < nVars-2; i++ ) bVarsK = cuddT( bVarsK ); // create the 2 variable tuples zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra ); if ( zPlus == NULL ) { Cudd_RecursiveDeref( dd, bVarsExtra ); Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); Cudd_RecursiveDeref( dd, bVarsExtra ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); } } cuddDeref( zRes ); /* insert the result into cache */ cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes); return zRes; } } /* end of extraZddSymmPairsCompute */ /**Function******************************************************************** Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.] Description [Returns the set of ZDD singletons, containing those positive ZDD variables that correspond to BDD variables x, for which it is true that bF(x=0) == bG(x=1).] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraZddGetSymmetricVars( DdManager * dd, /* the DD manager */ DdNode * bF, /* the first function - originally, the positive cofactor */ DdNode * bG, /* the second function - originally, the negative cofactor */ DdNode * bVars) /* the set of variables, on which F and G depend */ { DdNode * zRes; DdNode * bFR = Cudd_Regular(bF); DdNode * bGR = Cudd_Regular(bG); if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) ) { if ( bF == bG ) return extraZddGetSingletons( dd, bVars ); else return z0; } assert( bVars != b1 ); if ( (zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars)) ) return zRes; else { DdNode * zRes0, * zRes1; DdNode * zPlus, * zTemp; DdNode * bF0, * bF1; DdNode * bG0, * bG1; DdNode * bVarsNew; int LevelF = cuddI(dd,bFR->index); int LevelG = cuddI(dd,bGR->index); int LevelFG; if ( LevelF < LevelG ) LevelFG = LevelF; else LevelFG = LevelG; // at least one of the arguments is not a constant assert( LevelFG < dd->size ); // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ); assert( LevelFG == dd->perm[bVarsNew->index] ); // cofactor the functions if ( LevelF == LevelFG ) { if ( bFR != bF ) // bF is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } } else bF0 = bF1 = bF; if ( LevelG == LevelFG ) { if ( bGR != bG ) // bG is complemented { bG0 = Cudd_Not( cuddE(bGR) ); bG1 = Cudd_Not( cuddT(bGR) ); } else { bG0 = cuddE(bGR); bG1 = cuddT(bGR); } } else bG0 = bG1 = bG; // solve subproblems zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) ); if ( zRes0 == NULL ) return NULL; cuddRef( zRes0 ); // if there is not symmetries in the negative cofactor // there is no need to test the positive cofactor if ( zRes0 == z0 ) zRes = zRes0; // zRes takes reference else { zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) ); if ( zRes1 == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes0 ); return NULL; } cuddRef( zRes1 ); // only those variables should belong to the resulting set // for which the property is true for both cofactors zRes = cuddZddIntersect( dd, zRes0, zRes1 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes0 ); Cudd_RecursiveDerefZdd( dd, zRes1 ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zRes0 ); Cudd_RecursiveDerefZdd( dd, zRes1 ); } // add one more singleton if the property is true for this variable if ( bF0 == bG1 ) { zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); // add these variable pairs to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); } if ( bF == bG && bVars != bVarsNew ) { // if the functions are equal, so are their cofactors // add those variables from V that are above F and G DdNode * bVarsExtra; assert( LevelFG > dd->perm[bVars->index] ); // create the BDD of the extra variables bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew ); if ( bVarsExtra == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( bVarsExtra ); zPlus = extraZddGetSingletons( dd, bVarsExtra ); if ( zPlus == NULL ) { Cudd_RecursiveDeref( dd, bVarsExtra ); Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); Cudd_RecursiveDeref( dd, bVarsExtra ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); } cuddDeref( zRes ); cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes ); return zRes; } } /* end of extraZddGetSymmetricVars */ /**Function******************************************************************** Synopsis [Performs a recursive step of Extra_zddGetSingletons.] Description [Returns the set of ZDD singletons, containing those positive polarity ZDD variables that correspond to the BDD variables in bVars.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraZddGetSingletons( DdManager * dd, /* the DD manager */ DdNode * bVars) /* the set of variables */ { DdNode * zRes; if ( bVars == b1 ) // if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004 return z1; if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars)) ) return zRes; else { DdNode * zTemp, * zPlus; // solve subproblem zRes = extraZddGetSingletons( dd, cuddT(bVars) ); if ( zRes == NULL ) return NULL; cuddRef( zRes ); zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); cuddDeref( zRes ); cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes ); return zRes; } } /* end of extraZddGetSingletons */ /**Function******************************************************************** Synopsis [Performs a recursive step of Extra_bddReduceVarSet.] Description [Returns the set of all variables in the given set that are not in the support of the given function.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraBddReduceVarSet( DdManager * dd, /* the DD manager */ DdNode * bVars, /* the set of variables to be reduced */ DdNode * bF) /* the function whose support is used for reduction */ { DdNode * bRes; DdNode * bFR = Cudd_Regular(bF); if ( cuddIsConstant(bFR) || bVars == b1 ) return bVars; if ( (bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF)) ) return bRes; else { DdNode * bF0, * bF1; DdNode * bVarsThis, * bVarsLower, * bTemp; int LevelF; // if LevelF is below LevelV, scroll through the vars in bVars LevelF = dd->perm[bFR->index]; for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) ); // scroll also through the current var, because it should be not be added if ( LevelF == cuddI(dd,bVarsThis->index) ) bVarsLower = cuddT(bVarsThis); else bVarsLower = bVarsThis; // cofactor the function if ( bFR != bF ) // bFunc is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } // solve subproblems bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 ); if ( bRes == NULL ) return NULL; cuddRef( bRes ); bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 ); if ( bRes == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); return NULL; } cuddRef( bRes ); Cudd_RecursiveDeref( dd, bTemp ); // the current var should not be added // add the skipped vars if ( bVarsThis != bVars ) { DdNode * bVarsExtra; // extract the skipped variables bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis ); if ( bVarsExtra == NULL ) { Cudd_RecursiveDeref( dd, bRes ); return NULL; } cuddRef( bVarsExtra ); // add these variables bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra ); if ( bRes == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bVarsExtra ); return NULL; } cuddRef( bRes ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bVarsExtra ); } cuddDeref( bRes ); cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes ); return bRes; } } /* end of extraBddReduceVarSet */ /**Function******************************************************************** Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().] Description [Returns b0 if the variables are not symmetric. Returns b1 if the variables can be symmetric. The variables are represented in the form of a two-variable cube. In case the cube contains one variable (below Var1 level), the cube's pointer is complemented if the variable Var1 occurred on the current path; otherwise, the cube's pointer is regular. Uses additional complemented bit (Hash_Not) to mark the result if in the BDD rooted that this node there is a branch passing though the node labeled with Var2.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraBddCheckVarsSymmetric( DdManager * dd, /* the DD manager */ DdNode * bF, DdNode * bVars) { DdNode * bRes; if ( bF == b0 ) return b1; assert( bVars != b1 ); if ( (bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars)) ) return bRes; else { DdNode * bRes0, * bRes1; DdNode * bF0, * bF1; DdNode * bFR = Cudd_Regular(bF); int LevelF = cuddI(dd,bFR->index); DdNode * bVarsR = Cudd_Regular(bVars); int fVar1Pres; int iLev1; int iLev2; if ( bVarsR != bVars ) // cube's pointer is complemented { assert( cuddT(bVarsR) == b1 ); fVar1Pres = 1; // the first var is present on the path iLev1 = -1; // we are already below the first var level iLev2 = dd->perm[bVarsR->index]; // the level of the second var } else // cube's pointer is NOT complemented { fVar1Pres = 0; // the first var is absent on the path if ( cuddT(bVars) == b1 ) { iLev1 = -1; // we are already below the first var level iLev2 = dd->perm[bVars->index]; // the level of the second var } else { assert( cuddT(cuddT(bVars)) == b1 ); iLev1 = dd->perm[bVars->index]; // the level of the first var iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var } } // cofactor the function // the cofactors are needed only if we are above the second level if ( LevelF < iLev2 ) { if ( bFR != bF ) // bFunc is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } } else bF0 = bF1 = NULL; // consider five cases: // (1) F is above iLev1 // (2) F is on the level iLev1 // (3) F is between iLev1 and iLev2 // (4) F is on the level iLev2 // (5) F is below iLev2 // (1) F is above iLev1 if ( LevelF < iLev1 ) { // the returned result cannot have the hash attribute // because we still did not reach the level of Var1; // the attribute never travels above the level of Var1 bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); // assert( !Hash_IsComplement( bRes0 ) ); assert( bRes0 != z0 ); if ( bRes0 == b0 ) bRes = b0; else bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars ); // assert( !Hash_IsComplement( bRes ) ); assert( bRes != z0 ); } // (2) F is on the level iLev1 else if ( LevelF == iLev1 ) { bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) ); if ( bRes0 == b0 ) bRes = b0; else { bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) ); if ( bRes1 == b0 ) bRes = b0; else { // if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) if ( bRes0 == z0 || bRes1 == z0 ) bRes = b1; else bRes = b0; } } } // (3) F is between iLev1 and iLev2 else if ( LevelF < iLev2 ) { bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); if ( bRes0 == b0 ) bRes = b0; else { bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars ); if ( bRes1 == b0 ) bRes = b0; else { // if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) // bRes = Hash_Not( b1 ); if ( bRes0 == z0 || bRes1 == z0 ) bRes = z0; else bRes = b1; } } } // (4) F is on the level iLev2 else if ( LevelF == iLev2 ) { // this is the only place where the hash attribute (Hash_Not) can be added // to the result; it can be added only if the path came through the node // lebeled with Var1; therefore, the hash attribute cannot be returned // to the caller function if ( fVar1Pres ) // bRes = Hash_Not( b1 ); bRes = z0; else bRes = b0; } // (5) F is below iLev2 else // if ( LevelF > iLev2 ) { // it is possible that the path goes through the node labeled by Var1 // and still everything is okay; we do not label with Hash_Not here // because the path does not go through node labeled by Var2 bRes = b1; } cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes); return bRes; } } /* end of extraBddCheckVarsSymmetric */ /**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().] Description [Generates in a bottom-up fashion ZDD for all combinations composed of k variables out of variables belonging to Support.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode* extraZddTuplesFromBdd( DdManager * dd, /* the DD manager */ DdNode * bVarsK, /* the number of variables in tuples */ DdNode * bVarsN) /* the set of all variables */ { DdNode *zRes, *zRes0, *zRes1; statLine(dd); /* terminal cases */ /* if ( k < 0 || k > n ) * return dd->zero; * if ( n == 0 ) * return dd->one; */ if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) ) return z0; if ( bVarsN == b1 ) return z1; /* check cache */ zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN); if (zRes) return(zRes); /* ZDD in which this variable is 0 */ /* zRes0 = extraZddTuplesFromBdd( dd, k, n-1 ); */ zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) ); if ( zRes0 == NULL ) return NULL; cuddRef( zRes0 ); /* ZDD in which this variable is 1 */ /* zRes1 = extraZddTuplesFromBdd( dd, k-1, n-1 ); */ if ( bVarsK == b1 ) { zRes1 = z0; cuddRef( zRes1 ); } else { zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) ); if ( zRes1 == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes0 ); return NULL; } cuddRef( zRes1 ); } /* compose Res0 and Res1 with the given ZDD variable */ zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes0 ); Cudd_RecursiveDerefZdd( dd, zRes1 ); return NULL; } cuddDeref( zRes0 ); cuddDeref( zRes1 ); /* insert the result into cache */ cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes); return zRes; } /* end of extraZddTuplesFromBdd */ /**Function******************************************************************** Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ) // selects one subset from the ZDD zS // returns z0 if and only if zS is an empty set of cubes { DdNode * zRes; if ( zS == z0 ) return z0; if ( zS == z1 ) return z1; // check cache if ( (zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS )) ) return zRes; else { DdNode * zS0, * zS1, * zTemp; zS0 = cuddE(zS); zS1 = cuddT(zS); if ( zS0 != z0 ) { zRes = extraZddSelectOneSubset( dd, zS0 ); if ( zRes == NULL ) return NULL; } else // if ( zS0 == z0 ) { assert( zS1 != z0 ); zRes = extraZddSelectOneSubset( dd, zS1 ); if ( zRes == NULL ) return NULL; cuddRef( zRes ); zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); return NULL; } cuddDeref( zTemp ); } // insert the result into cache cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes ); return zRes; } } /* end of extraZddSelectOneSubset */ /*---------------------------------------------------------------------------*/ /* Definition of static Functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddThresh.c000066400000000000000000000507421300674244400251410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddThresh.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Dealing with threshold functions.] Author [Augusto Neutzling, Jody Matos, and Alan Mishchenko (UC Berkeley).] Affiliation [Federal University of Rio Grande do Sul, Brazil] Date [Ver. 1.0. Started - October 7, 2014.] Revision [$Id: extraBddThresh.c,v 1.0 2014/10/07 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "base/main/main.h" #include "misc/extra/extra.h" #include "bdd/cudd/cudd.h" #include "bool/kit/kit.h" #include "misc/vec/vec.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks thresholdness of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ThreshPrintChow(int Chow0, int * pChow, int nVars) { int i; for (i = 0; i < nVars; i++) printf("%d ", pChow[i]); printf(" %d\n", Chow0); } int Extra_ThreshComputeChow(word * t, int nVars, int * pChow) { int i, k, Chow0 = 0, nMints = (1 << nVars); memset(pChow, 0, sizeof(int) * nVars); // compute Chow coefs for (i = 0; i < nMints; i++) if (Abc_TtGetBit(t, i)) for (Chow0++, k = 0; k < nVars; k++) if ((i >> k) & 1) pChow[k]++; // compute modified Chow coefs for (k = 0; k < nVars; k++) pChow[k] = 2 * pChow[k] - Chow0; return Chow0 - (1 << (nVars - 1)); } void Extra_ThreshSortByChow(word * t, int nVars, int * pChow) { int i, nWords = Abc_TtWordNum(nVars); //sort the variables by Chow in ascending order while (1) { int fChange = 0; for (i = 0; i < nVars - 1; i++) { if (pChow[i] >= pChow[i + 1]) continue; ABC_SWAP(int, pChow[i], pChow[i + 1]); Abc_TtSwapAdjacent(t, nWords, i); fChange = 1; } if (!fChange) return; } } void Extra_ThreshSortByChowInverted(word * t, int nVars, int * pChow) { int i, nWords = Abc_TtWordNum(nVars); //sort the variables by Chow in descending order while (1) { int fChange = 0; for (i = 0; i < nVars - 1; i++) { if (pChow[i] <= pChow[i + 1]) continue; ABC_SWAP(int, pChow[i], pChow[i + 1]); Abc_TtSwapAdjacent(t, nWords, i); fChange = 1; } if (!fChange) return; } } int Extra_ThreshInitializeChow(int nVars, int * pChow) { int i = 0, Aux[16], nChows = 0; //group the variables which have the same Chow for (i = 0; i < nVars; i++) { if (i == 0 || (pChow[i] == pChow[i - 1])) Aux[i] = nChows; else { nChows++; Aux[i] = nChows; } } for (i = 0; i < nVars; i++) pChow[i] = Aux[i]; nChows++; return nChows; } static inline int Extra_ThreshWeightedSum(int * pW, int nVars, int m) { int i, Cost = 0; for (i = 0; i < nVars; i++) if ((m >> i) & 1) Cost += pW[i]; return Cost; } static inline int Extra_ThreshCubeWeightedSum1(int * pWofChow, int * pChow, char * pIsop, int nVars, int j) { int k, Cost = 0; for (k = j; k < j + nVars; k++) if (pIsop[k] == '1') Cost += pWofChow[pChow[k - j]]; return Cost; } static inline int Extra_ThreshCubeWeightedSum2(int * pWofChow, int * pChow, char * pIsop, int nVars, int j) { int k, Cost = 0; for (k = j; k < j + nVars; k++) if (pIsop[k] == '-') Cost += pWofChow[pChow[k - j]]; return Cost; } static inline int Extra_ThreshCubeWeightedSum3(int * pWofChow, int nChows, unsigned long ** pGreaters, int j) { int i, Cost = 0; for (i = 0; i < nChows; i++) Cost += pWofChow[i] * pGreaters[j][i]; return Cost; } static inline int Extra_ThreshCubeWeightedSum4(int * pWofChow, int nChows, unsigned long ** pSmallers, int j) { int i, Cost = 0; for (i = 0; i < nChows; i++) Cost += pWofChow[i] * pSmallers[j][i]; return Cost; } int Extra_ThreshSelectWeights3(word * t, int nVars, int * pW) { int m, Lmin, Lmax, nMints = (1 << nVars); assert(nVars == 3); for (pW[2] = 1; pW[2] <= nVars; pW[2]++) for (pW[1] = pW[2]; pW[1] <= nVars; pW[1]++) for (pW[0] = pW[1]; pW[0] <= nVars; pW[0]++) { Lmin = 10000; Lmax = 0; for (m = 0; m < nMints; m++) { if (Abc_TtGetBit(t, m)) Lmin = Abc_MinInt(Lmin, Extra_ThreshWeightedSum(pW, nVars, m)); else Lmax = Abc_MaxInt(Lmax, Extra_ThreshWeightedSum(pW, nVars, m)); if (Lmax >= Lmin) break; // printf( "%c%d ", Abc_TtGetBit(t, m) ? '+' : '-', Extra_ThreshWeightedSum(pW, nVars, m) ); } // printf( " -%d +%d\n", Lmax, Lmin ); if (m < nMints) continue; assert(Lmax < Lmin); return Lmin; } return 0; } int Extra_ThreshSelectWeights4(word * t, int nVars, int * pW) { int m, Lmin, Lmax, nMints = (1 << nVars); assert(nVars == 4); for (pW[3] = 1; pW[3] <= nVars; pW[3]++) for (pW[2] = pW[3]; pW[2] <= nVars; pW[2]++) for (pW[1] = pW[2]; pW[1] <= nVars; pW[1]++) for (pW[0] = pW[1]; pW[0] <= nVars; pW[0]++) { Lmin = 10000; Lmax = 0; for (m = 0; m < nMints; m++) { if (Abc_TtGetBit(t, m)) Lmin = Abc_MinInt(Lmin, Extra_ThreshWeightedSum(pW, nVars, m)); else Lmax = Abc_MaxInt(Lmax, Extra_ThreshWeightedSum(pW, nVars, m)); if (Lmax >= Lmin) break; } if (m < nMints) continue; assert(Lmax < Lmin); return Lmin; } return 0; } int Extra_ThreshSelectWeights5(word * t, int nVars, int * pW) { int m, Lmin, Lmax, nMints = (1 << nVars), Limit = nVars + 0; assert(nVars == 5); for (pW[4] = 1; pW[4] <= Limit; pW[4]++) for (pW[3] = pW[4]; pW[3] <= Limit; pW[3]++) for (pW[2] = pW[3]; pW[2] <= Limit; pW[2]++) for (pW[1] = pW[2]; pW[1] <= Limit; pW[1]++) for (pW[0] = pW[1]; pW[0] <= Limit; pW[0]++) { Lmin = 10000; Lmax = 0; for (m = 0; m < nMints; m++) { if (Abc_TtGetBit(t, m)) Lmin = Abc_MinInt(Lmin, Extra_ThreshWeightedSum(pW, nVars, m)); else Lmax = Abc_MaxInt(Lmax, Extra_ThreshWeightedSum(pW, nVars, m)); if (Lmax >= Lmin) break; } if (m < nMints) continue; assert(Lmax < Lmin); return Lmin; } return 0; } int Extra_ThreshSelectWeights6(word * t, int nVars, int * pW) { int m, Lmin, Lmax, nMints = (1 << nVars), Limit = nVars + 3; assert(nVars == 6); for (pW[5] = 1; pW[5] <= Limit; pW[5]++) for (pW[4] = pW[5]; pW[4] <= Limit; pW[4]++) for (pW[3] = pW[4]; pW[3] <= Limit; pW[3]++) for (pW[2] = pW[3]; pW[2] <= Limit; pW[2]++) for (pW[1] = pW[2]; pW[1] <= Limit; pW[1]++) for (pW[0] = pW[1]; pW[0] <= Limit; pW[0]++) { Lmin = 10000; Lmax = 0; for (m = 0; m < nMints; m++) { if (Abc_TtGetBit(t, m)) Lmin = Abc_MinInt(Lmin, Extra_ThreshWeightedSum(pW, nVars, m)); else Lmax = Abc_MaxInt(Lmax, Extra_ThreshWeightedSum(pW, nVars, m)); if (Lmax >= Lmin) break; } if (m < nMints) continue; assert(Lmax < Lmin); return Lmin; } return 0; } int Extra_ThreshSelectWeights7(word * t, int nVars, int * pW) { int m, Lmin, Lmax, nMints = (1 << nVars), Limit = nVars + 6; assert(nVars == 7); for (pW[6] = 1; pW[6] <= Limit; pW[6]++) for (pW[5] = pW[6]; pW[5] <= Limit; pW[5]++) for (pW[4] = pW[5]; pW[4] <= Limit; pW[4]++) for (pW[3] = pW[4]; pW[3] <= Limit; pW[3]++) for (pW[2] = pW[3]; pW[2] <= Limit; pW[2]++) for (pW[1] = pW[2]; pW[1] <= Limit; pW[1]++) for (pW[0] = pW[1]; pW[0] <= Limit; pW[0]++) { Lmin = 10000; Lmax = 0; for (m = 0; m < nMints; m++) { if (Abc_TtGetBit(t, m)) Lmin = Abc_MinInt(Lmin, Extra_ThreshWeightedSum(pW, nVars, m)); else Lmax = Abc_MaxInt(Lmax, Extra_ThreshWeightedSum(pW, nVars, m)); if (Lmax >= Lmin) break; } if (m < nMints) continue; assert(Lmax < Lmin); return Lmin; } return 0; } int Extra_ThreshSelectWeights8(word * t, int nVars, int * pW) { int m, Lmin, Lmax, nMints = (1 << nVars), Limit = nVars + 1; // <<-- incomplete detection to save runtime! assert(nVars == 8); for (pW[7] = 1; pW[7] <= Limit; pW[7]++) for (pW[6] = pW[7]; pW[6] <= Limit; pW[6]++) for (pW[5] = pW[6]; pW[5] <= Limit; pW[5]++) for (pW[4] = pW[5]; pW[4] <= Limit; pW[4]++) for (pW[3] = pW[4]; pW[3] <= Limit; pW[3]++) for (pW[2] = pW[3]; pW[2] <= Limit; pW[2]++) for (pW[1] = pW[2]; pW[1] <= Limit; pW[1]++) for (pW[0] = pW[1]; pW[0] <= Limit; pW[0]++) { Lmin = 10000; Lmax = 0; for (m = 0; m < nMints; m++) { if (Abc_TtGetBit(t, m)) Lmin = Abc_MinInt(Lmin, Extra_ThreshWeightedSum(pW, nVars, m)); else Lmax = Abc_MaxInt(Lmax, Extra_ThreshWeightedSum(pW, nVars, m)); if (Lmax >= Lmin) break; } if (m < nMints) continue; assert(Lmax < Lmin); return Lmin; } return 0; } int Extra_ThreshSelectWeights(word * t, int nVars, int * pW) { if (nVars <= 2) return (t[0] & 0xF) != 6 && (t[0] & 0xF) != 9; if (nVars == 3) return Extra_ThreshSelectWeights3(t, nVars, pW); if (nVars == 4) return Extra_ThreshSelectWeights4(t, nVars, pW); if (nVars == 5) return Extra_ThreshSelectWeights5(t, nVars, pW); if (nVars == 6) return Extra_ThreshSelectWeights6(t, nVars, pW); if (nVars == 7) return Extra_ThreshSelectWeights7(t, nVars, pW); if (nVars == 8) return Extra_ThreshSelectWeights8(t, nVars, pW); return 0; } void Extra_ThreshIncrementWeights(int nChows, int * pWofChow, int i) { int k; for (k = i; k < nChows; k++) { pWofChow[k]++; } } void Extra_ThreshDecrementWeights(int nChows, int * pWofChow, int i) { int k; for (k = i; k < nChows; k++) { pWofChow[k]--; } } void Extra_ThreshPrintInequalities(unsigned long ** pGreaters, unsigned long ** pSmallers, int nChows, int nInequalities) { int i = 0, k = 0; for (k = 0; k < nInequalities; k++) { printf("\n Inequality [%d] = ", k); for (i = 0; i < nChows; i++) { printf("%ld ", pGreaters[k][i]); } printf(" > "); for (i = 0; i < nChows; i++) { printf("%ld ", pSmallers[k][i]); } } } void Extra_ThreshCreateInequalities(char * pIsop, char * pIsopFneg, int nVars, int * pWofChow, int * pChow, int nChows, int nInequalities, unsigned long ** pGreaters, unsigned long ** pSmallers) { int i = 0, j = 0, k = 0, m = 0; int nCubesIsop = strlen(pIsop) / (nVars + 3); int nCubesIsopFneg = strlen(pIsopFneg) / (nVars + 3); for (k = 0; k < nCubesIsop * nCubesIsopFneg; k++) for (i = 0; i < nChows; i++) { pGreaters[k][i] = 0; pSmallers[k][i] = 0; } m = 0; for (i = 0; i < (int)strlen(pIsop); i += (nVars + 3)) for (j = 0; j < nCubesIsopFneg; j++) { for (k = 0; k < nVars; k++) if (pIsop[i + k] == '1') pGreaters[m][pChow[k]] = pGreaters[m][(pChow[k])] + 1; m++; } m = 0; for (i = 0; i < nCubesIsop; i++) for (j = 0; j < (int)strlen(pIsopFneg); j += (nVars + 3)) { for (k = 0; k < nVars; k++) if (pIsopFneg[j + k] == '-') pSmallers[m][pChow[k]] = pSmallers[m][pChow[k]] + 1; m++; } // Extra_ThreshPrintInequalities( pGreaters, pSmallers, nChows, nInequalities); // printf( "\nInequalities was Created \n"); } void Extra_ThreshSimplifyInequalities(int nInequalities, int nChows, unsigned long ** pGreaters, unsigned long ** pSmallers) { int i = 0, k = 0; for (k = 0; k < nInequalities; k++) { for (i = 0; i < nChows; i++) { if ((pGreaters[k][i]) == (pSmallers[k][i])) { pGreaters[k][i] = 0; pSmallers[k][i] = 0; } else if ((pGreaters[k][i]) > (pSmallers[k][i])) { pGreaters[k][i] = pGreaters[k][i] - pSmallers[k][i]; pSmallers[k][i] = 0; } else { pSmallers[k][i] = pSmallers[k][i] - pGreaters[k][i]; ; pGreaters[k][i] = 0; } } } // Extra_ThreshPrintInequalities( pGreaters, pSmallers, nChows, nInequalities); // printf( "\nInequalities was Siplified \n"); } int Extra_ThreshAssignWeights(word * t, char * pIsop, char * pIsopFneg, int nVars, int * pW, int * pChow, int nChows, int Wmin) { int i = 0, j = 0, Lmin = 1000, Lmax = 0, Limit = nVars * 2, delta = 0, deltaOld = -1000, fIncremented = 0; //****************************** int * pWofChow = ABC_ALLOC( int, nChows ); int nCubesIsop = strlen(pIsop) / (nVars + 3); int nCubesIsopFneg = strlen(pIsopFneg) / (nVars + 3); int nInequalities = nCubesIsop * nCubesIsopFneg; unsigned long **pGreaters; unsigned long **pSmallers; pGreaters = (unsigned long **)malloc(nCubesIsop * nCubesIsopFneg * sizeof *pGreaters); for (i = 0; i < nCubesIsop * nCubesIsopFneg; i++) { pGreaters[i] = (unsigned long *)malloc(nChows * sizeof *pGreaters[i]); } pSmallers = (unsigned long **)malloc(nCubesIsop * nCubesIsopFneg * sizeof *pSmallers); for (i = 0; i < nCubesIsop * nCubesIsopFneg; i++) { pSmallers[i] = (unsigned long *)malloc(nChows * sizeof *pSmallers[i]); } //****************************** Extra_ThreshCreateInequalities(pIsop, pIsopFneg, nVars, pWofChow, pChow, nChows, nInequalities, pGreaters, pSmallers); Extra_ThreshSimplifyInequalities(nInequalities, nChows, pGreaters, pSmallers); //initializes the weights pWofChow[0] = Wmin; for (i = 1; i < nChows; i++) { pWofChow[i] = pWofChow[i - 1] + 1; } i = 0; //assign the weights respecting the inequalities while (i < nChows && pWofChow[nChows - 1] <= Limit) { Lmin = 1000; Lmax = 0; while (j < nInequalities) { if (pGreaters[j][i] != 0) { Lmin = Extra_ThreshCubeWeightedSum3(pWofChow, nChows, pGreaters, j); Lmax = Extra_ThreshCubeWeightedSum4(pWofChow, nChows, pSmallers, j); delta = Lmin - Lmax; if (delta > 0) { if (fIncremented == 1) { j = 0; fIncremented = 0; deltaOld = -1000; } else j++; continue; } if (delta > deltaOld) { Extra_ThreshIncrementWeights(nChows, pWofChow, i); deltaOld = delta; fIncremented = 1; } else if (fIncremented == 1) { Extra_ThreshDecrementWeights(nChows, pWofChow, i); j++; deltaOld = -1000; fIncremented = 0; continue; } else j++; } else j++; } i++; j = 0; } //****************************** for (i = 0; i < nCubesIsop * nCubesIsopFneg; i++) { free(pGreaters[i]); } free(pGreaters); for (i = 0; i < nCubesIsop * nCubesIsopFneg; i++) { free(pSmallers[i]); } free(pSmallers); //****************************** i = 0; Lmin = 1000; Lmax = 0; //check the assigned weights in the original system for (j = 0; j < (int)strlen(pIsop); j += (nVars + 3)) Lmin = Abc_MinInt(Lmin, Extra_ThreshCubeWeightedSum1(pWofChow, pChow, pIsop, nVars, j)); for (j = 0; j < (int)strlen(pIsopFneg); j += (nVars + 3)) Lmax = Abc_MaxInt(Lmax, Extra_ThreshCubeWeightedSum2(pWofChow, pChow, pIsopFneg, nVars, j)); for (i = 0; i < nVars; i++) { pW[i] = pWofChow[pChow[i]]; } ABC_FREE( pWofChow ); if (Lmin > Lmax) return Lmin; else return 0; } void Extra_ThreshPrintWeights(int T, int * pW, int nVars) { int i; if (T == 0) fprintf( stdout, "\nHeuristic method: is not TLF\n\n"); else { fprintf( stdout, "\nHeuristic method: Weights and threshold value:\n"); for (i = 0; i < nVars; i++) printf("%d ", pW[i]); printf(" %d\n", T); } } /**Function************************************************************* Synopsis [Checks thresholdness of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_ThreshCheck(word * t, int nVars, int * pW) { int Chow0, Chow[16]; if (!Abc_TtIsUnate(t, nVars)) return 0; Abc_TtMakePosUnate(t, nVars); Chow0 = Extra_ThreshComputeChow(t, nVars, Chow); Extra_ThreshSortByChow(t, nVars, Chow); return Extra_ThreshSelectWeights(t, nVars, pW); } /**Function************************************************************* Synopsis [Checks thresholdness of the function by using a heuristic method.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_ThreshHeuristic(word * t, int nVars, int * pW) { extern char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ); int Chow0, Chow[16], nChows, i, T = 0; DdManager * dd; Vec_Str_t * vCube; DdNode * ddNode, * ddNodeFneg; char * pIsop, * pIsopFneg; if (nVars <= 1) return 1; if (!Abc_TtIsUnate(t, nVars)) return 0; Abc_TtMakePosUnate(t, nVars); Chow0 = Extra_ThreshComputeChow(t, nVars, Chow); Extra_ThreshSortByChowInverted(t, nVars, Chow); nChows = Extra_ThreshInitializeChow(nVars, Chow); dd = (DdManager *) Abc_FrameReadManDd(); vCube = Vec_StrAlloc(nVars); for (i = 0; i < nVars; i++) Cudd_bddIthVar(dd, i); ddNode = Kit_TruthToBdd(dd, (unsigned *) t, nVars, 0); Cudd_Ref(ddNode); pIsop = Abc_ConvertBddToSop( NULL, dd, ddNode, ddNode, nVars, 1, vCube, 1); Abc_TtNot(t, Abc_TruthWordNum(nVars)); ddNodeFneg = Kit_TruthToBdd(dd, (unsigned *) t, nVars, 0); Cudd_Ref(ddNodeFneg); pIsopFneg = Abc_ConvertBddToSop( NULL, dd, ddNodeFneg, ddNodeFneg, nVars, 1, vCube, 1); Cudd_RecursiveDeref(dd, ddNode); Cudd_RecursiveDeref(dd, ddNodeFneg); T = Extra_ThreshAssignWeights(t, pIsop, pIsopFneg, nVars, pW, Chow, nChows, 1); for (i = 2; (i < 4) && (T == 0) && (nVars >= 6); i++) T = Extra_ThreshAssignWeights(t, pIsop, pIsopFneg, nVars, pW, Chow, nChows, i); free(pIsop); free(pIsopFneg); Vec_StrFree(vCube); return T; } /**Function************************************************************* Synopsis [Checks unateness of a function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ThreshCheckTest() { int nVars = 6; int T, Chow0, Chow[16], Weights[16]; // word t = s_Truths6[0] & s_Truths6[1] & s_Truths6[2] & s_Truths6[3] & s_Truths6[4]; // word t = (s_Truths6[0] & s_Truths6[1]) | (s_Truths6[0] & s_Truths6[2] & s_Truths6[3]) | (s_Truths6[0] & s_Truths6[2] & s_Truths6[4]); // word t = (s_Truths6[2] & s_Truths6[1]) // | (s_Truths6[2] & s_Truths6[0] & s_Truths6[3]) // | (s_Truths6[2] & s_Truths6[0] & ~s_Truths6[4]); word t = (s_Truths6[0] & s_Truths6[1] & s_Truths6[2])| (s_Truths6[0] & s_Truths6[1] & s_Truths6[3]) | (s_Truths6[0] & s_Truths6[1] & s_Truths6[4] & s_Truths6[5]) | (s_Truths6[0] & s_Truths6[2] & s_Truths6[3] & s_Truths6[4] & s_Truths6[5]); // word t = (s_Truths6[0] & s_Truths6[1]) | (s_Truths6[0] & s_Truths6[2] & s_Truths6[3]) | (s_Truths6[0] & s_Truths6[2] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[2] & s_Truths6[3]); // word t = (s_Truths6[0] & s_Truths6[1]) | (s_Truths6[0] & s_Truths6[2]) | (s_Truths6[0] & s_Truths6[3] & s_Truths6[4] & s_Truths6[5]) | // (s_Truths6[1] & s_Truths6[2] & s_Truths6[3]) | (s_Truths6[1] & s_Truths6[2] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[2] & s_Truths6[5]); int i; assert(nVars <= 8); for (i = 0; i < nVars; i++) printf("%d %d %d\n", i, Abc_TtPosVar(&t, nVars, i), Abc_TtNegVar(&t, nVars, i)); // word t = s_Truths6[0] & s_Truths6[1] & s_Truths6[2]; Chow0 = Extra_ThreshComputeChow(&t, nVars, Chow); if ((T = Extra_ThreshCheck(&t, nVars, Weights))) Extra_ThreshPrintChow(T, Weights, nVars); else printf("No threshold\n"); } void Extra_ThreshHeuristicTest() { int nVars = 6; int T, Weights[16]; // word t = 19983902376700760000; word t = (s_Truths6[0] & s_Truths6[1] & s_Truths6[2])| (s_Truths6[0] & s_Truths6[1] & s_Truths6[3]) | (s_Truths6[0] & s_Truths6[1] & s_Truths6[4] & s_Truths6[5]) | (s_Truths6[0] & s_Truths6[2] & s_Truths6[3] & s_Truths6[4] & s_Truths6[5]); word * pT = &t; T = Extra_ThreshHeuristic(pT, nVars, Weights); Extra_ThreshPrintWeights(T, Weights, nVars); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddTime.c000066400000000000000000000444231300674244400246010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddTime.c] PackageName [extra] Synopsis [Procedures to control runtime in BDD operators.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - September 1, 2003.] Revision [$Id: extraBddTime.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] ***********************************************************************/ #include "extraBdd.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #define CHECK_FACTOR 10 /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static DdNode * cuddBddAndRecurTime( DdManager * manager, DdNode * f, DdNode * g, int * pRecCalls, int TimeOut ); static DdNode * cuddBddAndAbstractRecurTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int * pRecCalls, int TimeOut ); static DdNode * extraTransferPermuteTime( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute, int TimeOut ); static DdNode * extraTransferPermuteRecurTime( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute, int TimeOut ); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the conjunction of two BDDs f and g.] Description [Computes the conjunction of two BDDs f and g. Returns a pointer to the resulting BDD if successful; NULL if the intermediate result blows up.] SideEffects [None] SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor] ******************************************************************************/ DdNode * Extra_bddAndTime( DdManager * dd, DdNode * f, DdNode * g, int TimeOut) { DdNode *res; int Counter = 0; do { dd->reordered = 0; res = cuddBddAndRecurTime(dd,f,g, &Counter, TimeOut); } while (dd->reordered == 1); return(res); } /* end of Extra_bddAndTime */ /**Function******************************************************************** Synopsis [Takes the AND of two BDDs and simultaneously abstracts the variables in cube.] Description [Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise. Cudd_bddAndAbstract implements the semiring matrix multiplication algorithm for the boolean semiring.] SideEffects [None] SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd] ******************************************************************************/ DdNode * Extra_bddAndAbstractTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int TimeOut) { DdNode *res; int Counter = 0; do { manager->reordered = 0; res = cuddBddAndAbstractRecurTime(manager, f, g, cube, &Counter, TimeOut); } while (manager->reordered == 1); return(res); } /* end of Extra_bddAndAbstractTime */ /**Function******************************************************************** Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] Description [Convert a {A,B}DD from a manager to another one. The orders of the variables in the two managers may be different. Returns a pointer to the {A,B}DD in the destination manager if successful; NULL otherwise. The i-th entry in the array Permute tells what is the index of the i-th variable from the old manager in the new manager.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut ) { DdNode * bRes; do { ddDestination->reordered = 0; bRes = extraTransferPermuteTime( ddSource, ddDestination, f, Permute, TimeOut ); } while ( ddDestination->reordered == 1 ); return ( bRes ); } /* end of Extra_TransferPermuteTime */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddAnd.] Description [Implements the recursive step of Cudd_bddAnd by taking the conjunction of two BDDs. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddAnd] ******************************************************************************/ DdNode * cuddBddAndRecurTime( DdManager * manager, DdNode * f, DdNode * g, int * pRecCalls, int TimeOut) { DdNode *F, *fv, *fnv, *G, *gv, *gnv; DdNode *one, *r, *t, *e; unsigned int topf, topg, index; statLine(manager); one = DD_ONE(manager); /* Terminal cases. */ F = Cudd_Regular(f); G = Cudd_Regular(g); if (F == G) { if (f == g) return(f); else return(Cudd_Not(one)); } if (F == one) { if (f == one) return(g); else return(f); } if (G == one) { if (g == one) return(f); else return(g); } /* At this point f and g are not constant. */ if (f > g) { /* Try to increase cache efficiency. */ DdNode *tmp = f; f = g; g = tmp; F = Cudd_Regular(f); G = Cudd_Regular(g); } /* Check cache. */ if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); if (r != NULL) return(r); } // if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < Abc_Clock() ) if ( TimeOut && Abc_Clock() > TimeOut ) return NULL; /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[F->index]; topg = manager->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = F->index; fv = cuddT(F); fnv = cuddE(F); if (Cudd_IsComplement(f)) { fv = Cudd_Not(fv); fnv = Cudd_Not(fnv); } } else { index = G->index; fv = fnv = f; } if (topg <= topf) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } t = cuddBddAndRecurTime(manager, fv, gv, pRecCalls, TimeOut); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddAndRecurTime(manager, fnv, gnv, pRecCalls, TimeOut); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } } cuddDeref(e); cuddDeref(t); if (F->ref != 1 || G->ref != 1) cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); return(r); } /* end of cuddBddAndRecur */ /**Function******************************************************************** Synopsis [Takes the AND of two BDDs and simultaneously abstracts the variables in cube.] Description [Takes the AND of two BDDs and simultaneously abstracts the variables in cube. The variables are existentially abstracted. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddAndAbstract] ******************************************************************************/ DdNode * cuddBddAndAbstractRecurTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int * pRecCalls, int TimeOut) { DdNode *F, *ft, *fe, *G, *gt, *ge; DdNode *one, *zero, *r, *t, *e; unsigned int topf, topg, topcube, top, index; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* Terminal cases. */ if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); if (f == one && g == one) return(one); if (cube == one) { return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut)); } if (f == one || f == g) { return(cuddBddExistAbstractRecur(manager, g, cube)); } if (g == one) { return(cuddBddExistAbstractRecur(manager, f, cube)); } /* At this point f, g, and cube are not constant. */ if (f > g) { /* Try to increase cache efficiency. */ DdNode *tmp = f; f = g; g = tmp; } /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ F = Cudd_Regular(f); G = Cudd_Regular(g); topf = manager->perm[F->index]; topg = manager->perm[G->index]; top = ddMin(topf, topg); topcube = manager->perm[cube->index]; while (topcube < top) { cube = cuddT(cube); if (cube == one) { return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut)); } topcube = manager->perm[cube->index]; } /* Now, topcube >= top. */ /* Check cache. */ if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); if (r != NULL) { return(r); } } // if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < Abc_Clock() ) if ( TimeOut && Abc_Clock() > TimeOut ) return NULL; if (topf == top) { index = F->index; ft = cuddT(F); fe = cuddE(F); if (Cudd_IsComplement(f)) { ft = Cudd_Not(ft); fe = Cudd_Not(fe); } } else { index = G->index; ft = fe = f; } if (topg == top) { gt = cuddT(G); ge = cuddE(G); if (Cudd_IsComplement(g)) { gt = Cudd_Not(gt); ge = Cudd_Not(ge); } } else { gt = ge = g; } if (topcube == top) { /* quantify */ DdNode *Cube = cuddT(cube); t = cuddBddAndAbstractRecurTime(manager, ft, gt, Cube, pRecCalls, TimeOut); if (t == NULL) return(NULL); /* Special case: 1 OR anything = 1. Hence, no need to compute ** the else branch if t is 1. Likewise t + t * anything == t. ** Notice that t == fe implies that fe does not depend on the ** variables in Cube. Likewise for t == ge. */ if (t == one || t == fe || t == ge) { if (F->ref != 1 || G->ref != 1) cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, t); return(t); } cuddRef(t); /* Special case: t + !t * anything == t + anything. */ if (t == Cudd_Not(fe)) { e = cuddBddExistAbstractRecur(manager, ge, Cube); } else if (t == Cudd_Not(ge)) { e = cuddBddExistAbstractRecur(manager, fe, Cube); } else { e = cuddBddAndAbstractRecurTime(manager, fe, ge, Cube, pRecCalls, TimeOut); } if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } if (t == e) { r = t; cuddDeref(t); } else { cuddRef(e); r = cuddBddAndRecurTime(manager, Cudd_Not(t), Cudd_Not(e), pRecCalls, TimeOut); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); cuddRef(r); Cudd_DelayedDerefBdd(manager, t); Cudd_DelayedDerefBdd(manager, e); cuddDeref(r); } } else { t = cuddBddAndAbstractRecurTime(manager, ft, gt, cube, pRecCalls, TimeOut); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddAndAbstractRecurTime(manager, fe, ge, cube, pRecCalls, TimeOut); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } if (t == e) { r = t; cuddDeref(t); } else { cuddRef(e); if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager, (int) index, Cudd_Not(t), Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } cuddDeref(e); cuddDeref(t); } } if (F->ref != 1 || G->ref != 1) cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); return (r); } /* end of cuddBddAndAbstractRecur */ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Convert a BDD from a manager to another one.] Description [Convert a BDD from a manager to another one. Returns a pointer to the BDD in the destination manager if successful; NULL otherwise.] SideEffects [None] SeeAlso [Extra_TransferPermute] ******************************************************************************/ DdNode * extraTransferPermuteTime( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute, int TimeOut ) { DdNode *res; st__table *table = NULL; st__generator *gen = NULL; DdNode *key, *value; table = st__init_table( st__ptrcmp, st__ptrhash ); if ( table == NULL ) goto failure; res = extraTransferPermuteRecurTime( ddS, ddD, f, table, Permute, TimeOut ); if ( res != NULL ) cuddRef( res ); /* Dereference all elements in the table and dispose of the table. ** This must be done also if res is NULL to avoid leaks in case of ** reordering. */ gen = st__init_gen( table ); if ( gen == NULL ) goto failure; while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) ) { Cudd_RecursiveDeref( ddD, value ); } st__free_gen( gen ); gen = NULL; st__free_table( table ); table = NULL; if ( res != NULL ) cuddDeref( res ); return ( res ); failure: if ( table != NULL ) st__free_table( table ); if ( gen != NULL ) st__free_gen( gen ); return ( NULL ); } /* end of extraTransferPermuteTime */ /**Function******************************************************************** Synopsis [Performs the recursive step of Extra_TransferPermute.] Description [Performs the recursive step of Extra_TransferPermute. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [extraTransferPermuteTime] ******************************************************************************/ static DdNode * extraTransferPermuteRecurTime( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute, int TimeOut ) { DdNode *ft, *fe, *t, *e, *var, *res; DdNode *one, *zero; int index; int comple = 0; statLine( ddD ); one = DD_ONE( ddD ); comple = Cudd_IsComplement( f ); /* Trivial cases. */ if ( Cudd_IsConstant( f ) ) return ( Cudd_NotCond( one, comple ) ); /* Make canonical to increase the utilization of the cache. */ f = Cudd_NotCond( f, comple ); /* Now f is a regular pointer to a non-constant node. */ /* Check the cache. */ if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) ) return ( Cudd_NotCond( res, comple ) ); if ( TimeOut && Abc_Clock() > TimeOut ) return NULL; /* Recursive step. */ if ( Permute ) index = Permute[f->index]; else index = f->index; ft = cuddT( f ); fe = cuddE( f ); t = extraTransferPermuteRecurTime( ddS, ddD, ft, table, Permute, TimeOut ); if ( t == NULL ) { return ( NULL ); } cuddRef( t ); e = extraTransferPermuteRecurTime( ddS, ddD, fe, table, Permute, TimeOut ); if ( e == NULL ) { Cudd_RecursiveDeref( ddD, t ); return ( NULL ); } cuddRef( e ); zero = Cudd_Not(ddD->one); var = cuddUniqueInter( ddD, index, one, zero ); if ( var == NULL ) { Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); return ( NULL ); } res = cuddBddIteRecur( ddD, var, t, e ); if ( res == NULL ) { Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); return ( NULL ); } cuddRef( res ); Cudd_RecursiveDeref( ddD, t ); Cudd_RecursiveDeref( ddD, e ); if ( st__add_direct( table, ( char * ) f, ( char * ) res ) == st__OUT_OF_MEM ) { Cudd_RecursiveDeref( ddD, res ); return ( NULL ); } return ( Cudd_NotCond( res, comple ) ); } /* end of extraTransferPermuteRecurTime */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/extraBddUnate.c000066400000000000000000000505171300674244400247600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraBddUnate.c] PackageName [extra] Synopsis [Efficient methods to compute the information about unate variables using an algorithm that is conceptually similar to the algorithm for two-variable symmetry computation presented in: A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. Transactions on CAD, Nov. 2003.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - September 1, 2003.] Revision [$Id: extraBddUnate.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "extraBdd.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the classical symmetry information for the function.] Description [Returns the symmetry information in the form of Extra_UnateInfo_t structure.] SideEffects [If the ZDD variables are not derived from BDD variables with multiplicity 2, this function may derive them in a wrong way.] SeeAlso [] ******************************************************************************/ Extra_UnateInfo_t * Extra_UnateComputeFast( DdManager * dd, /* the manager */ DdNode * bFunc) /* the function whose symmetries are computed */ { DdNode * bSupp; DdNode * zRes; Extra_UnateInfo_t * p; bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); zRes = Extra_zddUnateInfoCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); p = Extra_UnateInfoCreateFromZdd( dd, zRes, bSupp ); Cudd_RecursiveDeref( dd, bSupp ); Cudd_RecursiveDerefZdd( dd, zRes ); return p; } /* end of Extra_UnateInfoCompute */ /**Function******************************************************************** Synopsis [Computes the classical symmetry information as a ZDD.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_zddUnateInfoCompute( DdManager * dd, /* the DD manager */ DdNode * bF, DdNode * bVars) { DdNode * res; do { dd->reordered = 0; res = extraZddUnateInfoCompute( dd, bF, bVars ); } while (dd->reordered == 1); return(res); } /* end of Extra_zddUnateInfoCompute */ /**Function******************************************************************** Synopsis [Converts a set of variables into a set of singleton subsets.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_zddGetSingletonsBoth( DdManager * dd, /* the DD manager */ DdNode * bVars) /* the set of variables */ { DdNode * res; do { dd->reordered = 0; res = extraZddGetSingletonsBoth( dd, bVars ); } while (dd->reordered == 1); return(res); } /* end of Extra_zddGetSingletonsBoth */ /**Function******************************************************************** Synopsis [Allocates unateness information structure.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ) { Extra_UnateInfo_t * p; // allocate and clean the storage for unateness info p = ABC_ALLOC( Extra_UnateInfo_t, 1 ); memset( p, 0, sizeof(Extra_UnateInfo_t) ); p->nVars = nVars; p->pVars = ABC_ALLOC( Extra_UnateVar_t, nVars ); memset( p->pVars, 0, nVars * sizeof(Extra_UnateVar_t) ); return p; } /* end of Extra_UnateInfoAllocate */ /**Function******************************************************************** Synopsis [Deallocates symmetry information structure.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Extra_UnateInfoDissolve( Extra_UnateInfo_t * p ) { ABC_FREE( p->pVars ); ABC_FREE( p ); } /* end of Extra_UnateInfoDissolve */ /**Function******************************************************************** Synopsis [Allocates symmetry information structure.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Extra_UnateInfoPrint( Extra_UnateInfo_t * p ) { char * pBuffer; int i; pBuffer = ABC_ALLOC( char, p->nVarsMax+1 ); memset( pBuffer, ' ', p->nVarsMax ); pBuffer[p->nVarsMax] = 0; for ( i = 0; i < p->nVars; i++ ) if ( p->pVars[i].Neg ) pBuffer[ p->pVars[i].iVar ] = 'n'; else if ( p->pVars[i].Pos ) pBuffer[ p->pVars[i].iVar ] = 'p'; else pBuffer[ p->pVars[i].iVar ] = '.'; printf( "%s\n", pBuffer ); ABC_FREE( pBuffer ); } /* end of Extra_UnateInfoPrint */ /**Function******************************************************************** Synopsis [Creates the symmetry information structure from ZDD.] Description [ZDD representation of symmetries is the set of cubes, each of which has two variables in the positive polarity. These variables correspond to the symmetric variable pair.] SideEffects [] SeeAlso [] ******************************************************************************/ Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) { Extra_UnateInfo_t * p; DdNode * bTemp, * zSet, * zCube, * zTemp; int * pMapVars2Nums; int i, nSuppSize; nSuppSize = Extra_bddSuppSize( dd, bSupp ); // allocate and clean the storage for symmetry info p = Extra_UnateInfoAllocate( nSuppSize ); // allocate the storage for the temporary map pMapVars2Nums = ABC_ALLOC( int, dd->size ); memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); // assign the variables p->nVarsMax = dd->size; for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) { p->pVars[i].iVar = bTemp->index; pMapVars2Nums[bTemp->index] = i; } // write the symmetry info into the structure zSet = zPairs; Cudd_Ref( zSet ); // Cudd_zddPrintCover( dd, zPairs ); printf( "\n" ); while ( zSet != z0 ) { // get the next cube zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); // add this var to the data structure assert( cuddT(zCube) == z1 && cuddE(zCube) == z0 ); if ( zCube->index & 1 ) // neg p->pVars[ pMapVars2Nums[zCube->index/2] ].Neg = 1; else p->pVars[ pMapVars2Nums[zCube->index/2] ].Pos = 1; // count the unate vars p->nUnate++; // update the cuver and deref the cube zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zCube ); } // for each cube Cudd_RecursiveDerefZdd( dd, zSet ); ABC_FREE( pMapVars2Nums ); return p; } /* end of Extra_UnateInfoCreateFromZdd */ /**Function******************************************************************** Synopsis [Computes the classical unateness information for the function.] Description [Uses the naive way of comparing cofactors.] SideEffects [] SeeAlso [] ******************************************************************************/ Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ) { int nSuppSize; DdNode * bSupp, * bTemp; Extra_UnateInfo_t * p; int i, Res; // compute the support bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); nSuppSize = Extra_bddSuppSize( dd, bSupp ); //printf( "Support = %d. ", nSuppSize ); //Extra_bddPrint( dd, bSupp ); //printf( "%d ", nSuppSize ); // allocate the storage for symmetry info p = Extra_UnateInfoAllocate( nSuppSize ); // assign the variables p->nVarsMax = dd->size; for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) { Res = Extra_bddCheckUnateNaive( dd, bFunc, bTemp->index ); p->pVars[i].iVar = bTemp->index; if ( Res == -1 ) p->pVars[i].Neg = 1; else if ( Res == 1 ) p->pVars[i].Pos = 1; p->nUnate += (Res != 0); } Cudd_RecursiveDeref( dd, bSupp ); return p; } /* end of Extra_UnateComputeSlow */ /**Function******************************************************************** Synopsis [Checks if the two variables are symmetric.] Description [Returns 0 if vars are not unate. Return -1/+1 if the var is neg/pos unate.] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_bddCheckUnateNaive( DdManager * dd, /* the DD manager */ DdNode * bF, int iVar) { DdNode * bCof0, * bCof1; int Res; assert( iVar < dd->size ); bCof0 = Cudd_Cofactor( dd, bF, Cudd_Not(Cudd_bddIthVar(dd,iVar)) ); Cudd_Ref( bCof0 ); bCof1 = Cudd_Cofactor( dd, bF, Cudd_bddIthVar(dd,iVar) ); Cudd_Ref( bCof1 ); if ( Cudd_bddLeq( dd, bCof0, bCof1 ) ) Res = 1; else if ( Cudd_bddLeq( dd, bCof1, bCof0 ) ) Res =-1; else Res = 0; Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); return Res; } /* end of Extra_bddCheckUnateNaive */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Performs a recursive step of Extra_UnateInfoCompute.] Description [Returns the set of symmetric variable pairs represented as a set of two-literal ZDD cubes. Both variables always appear in the positive polarity in the cubes. This function works without building new BDD nodes. Some relatively small number of ZDD nodes may be built to ensure proper bookkeeping of the symmetry information.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraZddUnateInfoCompute( DdManager * dd, /* the manager */ DdNode * bFunc, /* the function whose symmetries are computed */ DdNode * bVars ) /* the set of variables on which this function depends */ { DdNode * zRes; DdNode * bFR = Cudd_Regular(bFunc); if ( cuddIsConstant(bFR) ) { if ( cuddIsConstant(bVars) ) return z0; return extraZddGetSingletonsBoth( dd, bVars ); } assert( bVars != b1 ); if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddUnateInfoCompute, bFunc, bVars)) ) return zRes; else { DdNode * zRes0, * zRes1; DdNode * zTemp, * zPlus; DdNode * bF0, * bF1; DdNode * bVarsNew; int nVarsExtra; int LevelF; int AddVar; // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F // count how many extra vars are there in bVars nVarsExtra = 0; LevelF = dd->perm[bFR->index]; for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) nVarsExtra++; // the indexes (level) of variables should be synchronized now assert( bFR->index == bVarsNew->index ); // cofactor the function if ( bFR != bFunc ) // bFunc is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } // solve subproblems zRes0 = extraZddUnateInfoCompute( dd, bF0, cuddT(bVarsNew) ); if ( zRes0 == NULL ) return NULL; cuddRef( zRes0 ); // if there is no symmetries in the negative cofactor // there is no need to test the positive cofactor if ( zRes0 == z0 ) zRes = zRes0; // zRes takes reference else { zRes1 = extraZddUnateInfoCompute( dd, bF1, cuddT(bVarsNew) ); if ( zRes1 == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes0 ); return NULL; } cuddRef( zRes1 ); // only those variables are pair-wise symmetric // that are pair-wise symmetric in both cofactors // therefore, intersect the solutions zRes = cuddZddIntersect( dd, zRes0, zRes1 ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes0 ); Cudd_RecursiveDerefZdd( dd, zRes1 ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zRes0 ); Cudd_RecursiveDerefZdd( dd, zRes1 ); } // consider the current top-most variable AddVar = -1; if ( Cudd_bddLeq( dd, bF0, bF1 ) ) // pos AddVar = 0; else if ( Cudd_bddLeq( dd, bF1, bF0 ) ) // neg AddVar = 1; if ( AddVar >= 0 ) { // create the singleton zPlus = cuddZddGetNode( dd, 2*bFR->index + AddVar, z1, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); } // only zRes is referenced at this point // if we skipped some variables, these variables cannot be symmetric with // any variables that are currently in the support of bF, but they can be // symmetric with the variables that are in bVars but not in the support of bF for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) { // create the negative singleton zPlus = cuddZddGetNode( dd, 2*bVarsNew->index+1, z1, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); // create the positive singleton zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); } cuddDeref( zRes ); /* insert the result into cache */ cuddCacheInsert2(dd, extraZddUnateInfoCompute, bFunc, bVars, zRes); return zRes; } } /* end of extraZddUnateInfoCompute */ /**Function******************************************************************** Synopsis [Performs a recursive step of Extra_zddGetSingletons.] Description [Returns the set of ZDD singletons, containing those pos/neg polarity ZDD variables that correspond to the BDD variables in bVars.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraZddGetSingletonsBoth( DdManager * dd, /* the DD manager */ DdNode * bVars) /* the set of variables */ { DdNode * zRes; if ( bVars == b1 ) return z1; if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletonsBoth, bVars)) ) return zRes; else { DdNode * zTemp, * zPlus; // solve subproblem zRes = extraZddGetSingletonsBoth( dd, cuddT(bVars) ); if ( zRes == NULL ) return NULL; cuddRef( zRes ); // create the negative singleton zPlus = cuddZddGetNode( dd, 2*bVars->index+1, z1, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); // create the positive singleton zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); if ( zPlus == NULL ) { Cudd_RecursiveDerefZdd( dd, zRes ); return NULL; } cuddRef( zPlus ); // add these to the result zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); if ( zRes == NULL ) { Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); return NULL; } cuddRef( zRes ); Cudd_RecursiveDerefZdd( dd, zTemp ); Cudd_RecursiveDerefZdd( dd, zPlus ); cuddDeref( zRes ); cuddCacheInsert1( dd, extraZddGetSingletonsBoth, bVars, zRes ); return zRes; } } /* end of extraZddGetSingletonsBoth */ /*---------------------------------------------------------------------------*/ /* Definition of static Functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/extrab/module.make000066400000000000000000000004601300674244400241760ustar00rootroot00000000000000SRC += src/bdd/extrab/extraBddAuto.c \ src/bdd/extrab/extraBddCas.c \ src/bdd/extrab/extraBddImage.c \ src/bdd/extrab/extraBddKmap.c \ src/bdd/extrab/extraBddMisc.c \ src/bdd/extrab/extraBddSymm.c \ src/bdd/extrab/extraBddThresh.c \ src/bdd/extrab/extraBddTime.c \ src/bdd/extrab/extraBddUnate.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/000077500000000000000000000000001300674244400213365ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb.c000066400000000000000000000026451300674244400222620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb.h000066400000000000000000000074511300674244400222670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD-based reachability.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 8, 2010.] Revision [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__llb__llb_h #define ABC__aig__llb__llb_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Gia_ParLlb_t_ Gia_ParLlb_t; struct Gia_ParLlb_t_ { int nBddMax; // maximum BDD size int nIterMax; // maximum iteration count int nClusterMax; // maximum cluster size int nHintDepth; // the number of times to cofactor int HintFirst; // the number of first hint to use int fUseFlow; // use flow computation int nVolumeMax; // the largest volume int nVolumeMin; // the smallest volume int nPartValue; // partitioning value int fBackward; // enable backward reachability int fReorder; // enable dynamic variable reordering int fIndConstr; // extract inductive constraints int fUsePivots; // use internal pivot variables int fCluster; // use partition clustering int fSchedule; // use cluster scheduling int fDumpReached; // dump reached states into a file int fVerbose; // print verbose information int fVeryVerbose; // print dependency matrices int fSilent; // do not print any infomation int fSkipReach; // skip reachability (preparation phase only) int fSkipOutCheck; // does not check the property output int TimeLimit; // time limit for one reachability run int TimeLimitGlo; // time limit for all reachability runs // internal parameters abctime TimeTarget; // the time to stop int iFrame; // explored up to this frame }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== llbCore.c ==========================================================*/ extern void Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars ); /*=== llb4Nonlin.c ==========================================================*/ extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Cluster.c000066400000000000000000000230621300674244400237010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Cluster.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Clustering algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 ) { int iVar, Weight = 0; for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) { // count each removed variable as 2 if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 ) Weight += 2; // count each added variale as -1 else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) ) Weight--; } return Weight; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManComputeBestQuant( Llb_Mtr_t * p ) { int i, k, WeightBest = -100000, WeightCur, RetValue = -1; for ( i = 1; i < p->nCols-1; i++ ) for ( k = i+1; k < p->nCols-1; k++ ) { if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) continue; if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) continue; WeightCur = Llb_ManComputeCommonQuant( p, i, k ); if ( WeightCur <= 0 ) continue; if ( WeightBest < WeightCur ) { WeightBest = WeightCur; RetValue = (i << 16) | k; } } // printf( "Choosing best quant Weight %4d\n", WeightCur ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float ** Llb_ManComputeQuant( Llb_Mtr_t * p ) { float ** pCosts; int i, k; // alloc and clean pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); for ( i = 0; i < p->nCols; i++ ) for ( k = 0; k < p->nCols; k++ ) pCosts[i][i] = 0.0; // fill up for ( i = 1; i < p->nCols-1; i++ ) for ( k = i+1; k < p->nCols-1; k++ ) pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k ); return pCosts; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 ) { int iVar, CountComm = 0, CountDiff = 0; for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) { if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 ) CountComm++; else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 ) CountDiff++; } /* printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n", iCol1, iCol2, CountDiff, CountComm, -1.0 * CountDiff / ( CountComm + CountDiff ) ); */ return -1.0 * CountDiff / ( CountComm + CountDiff ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManComputeBestAttr( Llb_Mtr_t * p ) { float WeightBest = -100000, WeightCur; int i, k, RetValue = -1; for ( i = 1; i < p->nCols-1; i++ ) for ( k = i+1; k < p->nCols-1; k++ ) { if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) continue; if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) continue; WeightCur = Llb_ManComputeCommonAttr( p, i, k ); if ( WeightBest < WeightCur ) { WeightBest = WeightCur; RetValue = (i << 16) | k; } } return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float ** Llb_ManComputeAttr( Llb_Mtr_t * p ) { float ** pCosts; int i, k; // alloc and clean pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); for ( i = 0; i < p->nCols; i++ ) for ( k = 0; k < p->nCols; k++ ) pCosts[i][i] = 0.0; // fill up for ( i = 1; i < p->nCols-1; i++ ) for ( k = i+1; k < p->nCols-1; k++ ) pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k ); return pCosts; } /**Function************************************************************* Synopsis [Returns the number of variables that will be saved.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 ) { int iVar; assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 ); assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 ); assert( p->pColGrps[iGrp1] != NULL ); assert( p->pColGrps[iGrp2] != NULL ); for ( iVar = 0; iVar < p->nRows; iVar++ ) { if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 ) p->pRowSums[iVar]--; if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 ) { p->pMatrix[iGrp1][iVar] = 1; p->pColSums[iGrp1]++; } if ( p->pMatrix[iGrp2][iVar] == 1 ) p->pMatrix[iGrp2][iVar] = 0; } p->pColSums[iGrp2] = 0; } /**Function************************************************************* Synopsis [Combines one pair of columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 ) { int fVerbose = 0; Llb_Grp_t * pGrp; int iVar; if ( fVerbose ) { printf( "Combining %d and %d\n", iCol1, iCol2 ); for ( iVar = 0; iVar < p->nRows; iVar++ ) { if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 ) continue; printf( "%3d : %c%c\n", iVar, p->pMatrix[iCol1][iVar]? '*':' ', p->pMatrix[iCol2][iVar]? '*':' ' ); } } pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] ); Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 ); p->pColGrps[iCol1] = pGrp; p->pColGrps[iCol2] = NULL; } /**Function************************************************************* Synopsis [Removes empty columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManClusterCompress( Llb_Mtr_t * p ) { int i, k = 0; for ( i = 0; i < p->nCols; i++ ) { if ( p->pColGrps[i] == NULL ) { assert( p->pColSums[i] == 0 ); assert( p->pMatrix[i] != NULL ); ABC_FREE( p->pMatrix[i] ); continue; } p->pMatrix[k] = p->pMatrix[i]; p->pColGrps[k] = p->pColGrps[i]; p->pColSums[k] = p->pColSums[i]; k++; } p->nCols = k; } /**Function************************************************************* Synopsis [Combines one pair of columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManCluster( Llb_Mtr_t * p ) { int RetValue; do { do { RetValue = Llb_ManComputeBestQuant( p ); if ( RetValue > 0 ) Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); } while ( RetValue > 0 ); RetValue = Llb_ManComputeBestAttr( p ); if ( RetValue > 0 ) Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); Llb_MtrVerifyMatrix( p ); } while ( RetValue > 0 ); Llb_ManClusterCompress( p ); Llb_MtrVerifyMatrix( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Constr.c000066400000000000000000000224701300674244400235320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Constr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Computing inductive constraints.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManCountEntries( Vec_Int_t * vCands ) { int i, Entry, Counter = 0; Vec_IntForEachEntry( vCands, Entry, i ) Counter += ((Entry == 0) || (Entry == 1)); return Counter; } /**Function************************************************************* Synopsis [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ) { int i, Entry; if ( vCands == NULL ) { printf( "There is no hints.\n" ); return; } Entry = Llb_ManCountEntries(vCands); printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") ); Vec_IntForEachEntry( vCands, Entry, i ) { if ( Entry != 0 && Entry != 1 ) continue; printf( "%c", Entry ? '+' : '-' ); printf( "%-6d : ", i ); Aig_ObjPrint( p, Aig_ManObj(p, i) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Dereference BDD nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); } /**Function************************************************************* Synopsis [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) { DdNode * bBdd0, * bBdd1; DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); if ( bFunc != NULL ) return bFunc; assert( Aig_ObjIsNode(pObj) ); bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) { Vec_Ptr_t * vBdds; Aig_Obj_t * pObj; DdNode * bFunc; int i, Entry; vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); Saig_ManForEachPi( p, pObj, i ) { bFunc = Cudd_bddIthVar( dd, Aig_ManCiNum(p) + i ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); } Saig_ManForEachLi( p, pObj, i ) { bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); } Vec_IntForEachEntry( vNodes, Entry, i ) { if ( Entry != 0 && Entry != 1 ) continue; pObj = Aig_ManObj( p, i ); bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds ); if ( Entry == 0 ) { // Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" ); // Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" ); if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) ) Vec_IntWriteEntry( vNodes, i, -1 ); } else if ( Entry == 1 ) { // Extra_bddPrint( dd, pObj->pData ); printf( "\n" ); // Extra_bddPrint( dd, bFunc ); printf( "\n" ); if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) ) Vec_IntWriteEntry( vNodes, i, -1 ); } } Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i ) if ( bFunc ) Cudd_RecursiveDeref( dd, bFunc ); Vec_PtrFree( vBdds ); } /**Function************************************************************* Synopsis [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd ) { Vec_Int_t * vNodes; Aig_Obj_t * pObj, * pRoot; int i; pRoot = Aig_ManCo( p, 0 ); vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) ); Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) ) Vec_IntWriteEntry( vNodes, i, 1 ); else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) ) Vec_IntWriteEntry( vNodes, i, 0 ); } return vNodes; } /**Function************************************************************* Synopsis [Constructs global BDDs for each object in the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p ) { DdManager * dd; DdNode * bBdd0, * bBdd1; Aig_Obj_t * pObj; int i; 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 ); } Aig_ManForEachNode( p, pObj, i ) { bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); } Aig_ManForEachCo( p, pObj, i ) { pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); } return dd; } /**Function************************************************************* Synopsis [Derives inductive constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ) { DdManager * dd; Vec_Int_t * vNodes; if ( Saig_ManPoNum(p) != 1 ) { printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) ); return NULL; } assert( Saig_ManPoNum(p) == 1 ); dd = Llb_ManConstructGlobalBdds( p ); vNodes = Llb_ManComputeBaseCase( p, dd ); if ( Llb_ManCountEntries(vNodes) > 0 ) Llb_ManComputeIndCase( p, dd, vNodes ); if ( Llb_ManCountEntries(vNodes) == 0 ) Vec_IntFreeP( &vNodes ); Llb_ManDerefenceBdds( p, dd ); Extra_StopManager( dd ); return vNodes; } /**Function************************************************************* Synopsis [Tests derived constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManConstrTest( Aig_Man_t * p ) { Vec_Int_t * vNodes; vNodes = Llb_ManDeriveConstraints( p ); Llb_ManPrintEntries( p, vNodes ); Vec_IntFreeP( &vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Core.c000066400000000000000000000145531300674244400231550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Core.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Top-level procedure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" #include "aig/gia/gia.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManSetDefaultParams( Gia_ParLlb_t * p ) { memset( p, 0, sizeof(Gia_ParLlb_t) ); p->nBddMax = 10000000; p->nIterMax = 10000000; p->nClusterMax = 20; p->nHintDepth = 0; p->HintFirst = 0; p->fUseFlow = 0; // use flow p->nVolumeMax = 100; // max volume p->nVolumeMin = 30; // min volume p->nPartValue = 5; // partitioning value p->fBackward = 0; // forward by default p->fReorder = 1; p->fIndConstr = 0; p->fUsePivots = 0; p->fCluster = 0; p->fSchedule = 0; p->fDumpReached = 0; p->fVerbose = 0; p->fVeryVerbose = 0; p->fSilent = 0; p->TimeLimit = 0; // p->TimeLimit = 0; p->TimeLimitGlo = 0; p->TimeTarget = 0; p->iFrame = -1; } /**Function************************************************************* Synopsis [Prints statistics about MFFCs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManPrintAig( Llb_Man_t * p ) { Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) ); Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) ); Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) ); Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManCiNum(p->pAig)-Saig_ManRegNum(p->pAig) ); Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) ); Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 ); Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) ); Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) ); // Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) ); Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ) { Llb_Man_t * p = NULL; Aig_Man_t * pAig; int RetValue = -1; abctime clk = Abc_Clock(); if ( pPars->fIndConstr ) { assert( vHints == NULL ); vHints = Llb_ManDeriveConstraints( pAigGlo ); } // derive AIG for hints if ( vHints == NULL ) pAig = Aig_ManDupSimple( pAigGlo ); else { if ( pPars->fVerbose ) Llb_ManPrintEntries( pAigGlo, vHints ); pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints ); } if ( pPars->fUseFlow ) { // p = Llb_ManStartFlow( pAigGlo, pAig, pPars ); } else { p = Llb_ManStart( pAigGlo, pAig, pPars ); if ( pPars->fVerbose ) { Llb_ManPrintAig( p ); printf( "Original matrix: " ); Llb_MtrPrintMatrixStats( p->pMatrix ); if ( pPars->fVeryVerbose ) Llb_MtrPrint( p->pMatrix, 1 ); } if ( pPars->fCluster ) { Llb_ManCluster( p->pMatrix ); if ( pPars->fVerbose ) { printf( "Matrix after clustering: " ); Llb_MtrPrintMatrixStats( p->pMatrix ); if ( pPars->fVeryVerbose ) Llb_MtrPrint( p->pMatrix, 1 ); } } if ( pPars->fSchedule ) { Llb_MtrSchedule( p->pMatrix ); if ( pPars->fVerbose ) { printf( "Matrix after scheduling: " ); Llb_MtrPrintMatrixStats( p->pMatrix ); if ( pPars->fVeryVerbose ) Llb_MtrPrint( p->pMatrix, 1 ); } } } if ( !p->pPars->fSkipReach ) RetValue = Llb_ManReachability( p, vHints, pddGlo ); Llb_ManStop( p ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( pPars->fIndConstr ) Vec_IntFreeP( &vHints ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ) { Gia_Man_t * pGia2; Aig_Man_t * pAig; int RetValue = -1; pGia2 = Gia_ManDupDfs( pGia ); pAig = Gia_ManToAigSimple( pGia2 ); Gia_ManStop( pGia2 ); //Aig_ManShow( pAig, 0, NULL ); if ( pPars->nHintDepth == 0 ) RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL ); else RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars ); pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; Aig_ManStop( pAig ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Group.c000066400000000000000000000307501300674244400233560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Group.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Initial partition computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ) { Llb_Grp_t * p; p = ABC_CALLOC( Llb_Grp_t, 1 ); p->pMan = pMan; p->vIns = Vec_PtrAlloc( 8 ); p->vOuts = Vec_PtrAlloc( 8 ); p->Id = Vec_PtrSize( pMan->vGroups ); Vec_PtrPush( pMan->vGroups, p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManGroupStop( Llb_Grp_t * p ) { if ( p == NULL ) return; Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL ); Vec_PtrFreeP( &p->vIns ); Vec_PtrFreeP( &p->vOuts ); Vec_PtrFreeP( &p->vNodes ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsConst1(pObj) ) return; if ( Aig_ObjIsCo(pObj) ) { Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); return; } assert( Aig_ObjIsAnd(pObj) ); Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Collects the support of MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; vNodes = Vec_PtrAlloc( 100 ); Aig_ManIncrementTravId( pGroup->pMan->pAig ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes ); return vNodes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsConst1(pObj) ) return; if ( pObj->fMarkA ) { Vec_PtrPush( vSupp, pObj ); return; } assert( Aig_ObjIsAnd(pObj) ); Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp ); Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj ) { Llb_Grp_t * p; assert( pObj->fMarkA == 1 ); // derive group p = Llb_ManGroupAlloc( pMan ); Vec_PtrPush( p->vOuts, pObj ); Aig_ManIncrementTravId( pMan->pAig ); if ( Aig_ObjIsCo(pObj) ) Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); else { Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns ); } // derive internal objects assert( p->vNodes == NULL ); p->vNodes = Llb_ManGroupCollect( p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan ) { Llb_Grp_t * p; Aig_Obj_t * pObj; int i; p = Llb_ManGroupAlloc( pMan ); Saig_ManForEachLo( pMan->pAig, pObj, i ) Vec_PtrPush( p->vOuts, pObj ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan ) { Llb_Grp_t * p; Aig_Obj_t * pObj; int i; p = Llb_ManGroupAlloc( pMan ); Saig_ManForEachLi( pMan->pAig, pObj, i ) Vec_PtrPush( p->vIns, pObj ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ) { Llb_Grp_t * p; Aig_Obj_t * pObj; int i; p = Llb_ManGroupAlloc( p1->pMan ); // create inputs Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i ) Vec_PtrPush( p->vIns, pObj ); Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i ) Vec_PtrPushUnique( p->vIns, pObj ); // create outputs Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i ) Vec_PtrPush( p->vOuts, pObj ); Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i ) Vec_PtrPushUnique( p->vOuts, pObj ); // derive internal objects assert( p->vNodes == NULL ); p->vNodes = Llb_ManGroupCollect( p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; if ( Aig_ObjIsTravIdPrevious(p, pObj) ) { Aig_ObjSetTravIdCurrent(p, pObj); return; } Aig_ObjSetTravIdCurrent(p, pObj); assert( Aig_ObjIsNode(pObj) ); Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) ); Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Creates group from two cuts derived by the flow computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ) { Llb_Grp_t * p; Aig_Obj_t * pObj; int i; p = Llb_ManGroupAlloc( pMan ); // mark Cut1 Aig_ManIncrementTravId( pMan->pAig ); Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) Aig_ObjSetTravIdCurrent( pMan->pAig, pObj ); // collect unmarked Cut2 Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) Vec_PtrPush( p->vOuts, pObj ); // mark nodes reachable from Cut2 Aig_ManIncrementTravId( pMan->pAig ); Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj ); // collect marked Cut1 Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) Vec_PtrPush( p->vIns, pObj ); // derive internal objects assert( p->vNodes == NULL ); p->vNodes = Llb_ManGroupCollect( p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManPrepareGroups( Llb_Man_t * pMan ) { Aig_Obj_t * pObj; int i; assert( pMan->vGroups == NULL ); pMan->vGroups = Vec_PtrAlloc( 1000 ); Llb_ManGroupCreateFirst( pMan ); Aig_ManForEachNode( pMan->pAig, pObj, i ) { if ( pObj->fMarkA ) Llb_ManGroupCreate( pMan, pObj ); } Saig_ManForEachLi( pMan->pAig, pObj, i ) { if ( pObj->fMarkA ) Llb_ManGroupCreate( pMan, pObj ); } Llb_ManGroupCreateLast( pMan ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManPrintSpan( Llb_Man_t * p ) { Llb_Grp_t * pGroup; Aig_Obj_t * pVar; int i, k, Span = 0, SpanMax = 0; Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) { Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) Span++; Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) Span++; SpanMax = Abc_MaxInt( SpanMax, Span ); printf( "%d ", Span ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) Span--; Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) Span--; } printf( "\n" ); printf( "Max = %d\n", SpanMax ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar ) { Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup ); Aig_Obj_t * pObj; int i; Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) if ( pObj->Id == iVar ) return 1; Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) if ( pObj->Id == iVar ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManPrintHisto( Llb_Man_t * p ) { Aig_Obj_t * pObj; int i, k; Aig_ManForEachObj( p->pAig, pObj, i ) { if ( Vec_IntEntry(p->vObj2Var, i) < 0 ) continue; printf( "%3d :", i ); for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ ) printf( " " ); for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ ) printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' ); printf( "\n" ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Hint.c000066400000000000000000000154621300674244400231670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Hint.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns CI index with the largest number of fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManMaxFanoutCi( Aig_Man_t * pAig ) { Aig_Obj_t * pObj; int i, WeightMax = -ABC_INFINITY, iInput = -1; Aig_ManForEachCi( pAig, pObj, i ) if ( WeightMax < Aig_ObjRefs(pObj) ) { WeightMax = Aig_ObjRefs(pObj); iInput = i; } assert( iInput >= 0 ); return iInput; } /**Function************************************************************* Synopsis [Derives AIG whose PI is substituted by a constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth ) { Aig_Man_t * pNew, * pTemp; int i, iInput; pNew = Aig_ManDupDfs( pAig ); for ( i = 0; i < nHintDepth; i++ ) { iInput = Llb_ManMaxFanoutCi( pNew ); Abc_Print( 1, "%d %3d\n", i, iInput ); pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 ); Aig_ManStop( pTemp ); } return pNew; } /**Function************************************************************* Synopsis [Returns CI index with the largest number of fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly ) { Vec_Int_t * vFanouts, * vResult; Aig_Obj_t * pObj; int i, fChanges, PivotValue; // int Entry; // collect fanout counts vFanouts = Vec_IntAlloc( 100 ); Aig_ManForEachObj( pAig, pObj, i ) { // if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) continue; Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) ); } Vec_IntSort( vFanouts, 1 ); // pick the separator nCandMax = Abc_MinInt( nCandMax, Vec_IntSize(vFanouts) - 1 ); PivotValue = Vec_IntEntry( vFanouts, nCandMax ); Vec_IntFree( vFanouts ); // collect obj satisfying the constraints vResult = Vec_IntAlloc( 100 ); Aig_ManForEachObj( pAig, pObj, i ) { // if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) continue; if ( Aig_ObjRefs(pObj) < PivotValue ) continue; Vec_IntPush( vResult, Aig_ObjId(pObj) ); } assert( Vec_IntSize(vResult) >= nCandMax ); // order in the decreasing order of fanouts do { fChanges = 0; for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ ) if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) ) { int Temp = Vec_IntEntry( vResult, i ); Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) ); Vec_IntWriteEntry( vResult, i+1, Temp ); fChanges = 1; } } while ( fChanges ); /* Vec_IntForEachEntry( vResult, Entry, i ) printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) ); printf( "\n" ); */ return vResult; } /**Function************************************************************* Synopsis [Derives AIG whose PI is substituted by a constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ) { DdManager * ddGlo = NULL; Vec_Int_t * vHints; Vec_Int_t * vHFCands; int i, Entry, RetValue = -1; abctime clk = Abc_Clock(); assert( pPars->nHintDepth > 0 ); /* // perform reachability without hints RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL ); if ( RetValue >= 0 ) return RetValue; */ // create hints representation vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 ); vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) ); // add one hint at a time till the problem is solved Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst ) { Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!! // solve under hints RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); if ( RetValue == 0 ) goto Finish; if ( RetValue == 1 ) break; } if ( RetValue == -1 ) goto Finish; // undo the hints one at a time for ( ; i >= pPars->HintFirst; i-- ) { Entry = Vec_IntEntry( vHFCands, i ); Vec_IntWriteEntry( vHints, Entry, -1 ); // solve under relaxed hints RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); if ( RetValue == 0 ) goto Finish; if ( RetValue == 1 ) continue; break; } Finish: if ( ddGlo ) { if ( ddGlo->bFunc ) Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc ); Extra_StopManager( ddGlo ); } Vec_IntFreeP( &vHFCands ); Vec_IntFreeP( &vHints ); if ( pPars->fVerbose ) Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clk ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Man.c000066400000000000000000000151141300674244400227720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Man.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Reachability manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManPrepareVarMap( Llb_Man_t * p ) { Aig_Obj_t * pObjLi, * pObjLo; int i, iVarLi, iVarLo; assert( p->vNs2Glo == NULL ); assert( p->vCs2Glo == NULL ); assert( p->vGlo2Cs == NULL ); assert( p->vGlo2Ns == NULL ); p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi)); iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) ); assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) ); Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); } // add mapping of the PIs Saig_ManForEachPi( p->pAig, pObjLo, i ) { iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManPrepareVarLimits( Llb_Man_t * p ) { Llb_Grp_t * pGroup; Aig_Obj_t * pVar; int i, k; assert( p->vVarBegs == NULL ); assert( p->vVarEnds == NULL ); p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols ); for ( i = 0; i < p->pMatrix->nCols; i++ ) { pGroup = p->pMatrix->pColGrps[i]; Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManStop( Llb_Man_t * p ) { Llb_Grp_t * pGrp; DdNode * bTemp; int i; // Vec_IntFreeP( &p->vMem ); // Vec_PtrFreeP( &p->vTops ); // Vec_PtrFreeP( &p->vBots ); // Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts ); if ( p->pMatrix ) Llb_MtrFree( p->pMatrix ); Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i ) Llb_ManGroupStop( pGrp ); if ( p->dd ) { // printf( "Manager dd\n" ); Extra_StopManager( p->dd ); } if ( p->ddG ) { // printf( "Manager ddG\n" ); if ( p->ddG->bFunc ) Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); Extra_StopManager( p->ddG ); } if ( p->ddR ) { // printf( "Manager ddR\n" ); if ( p->ddR->bFunc ) Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) Cudd_RecursiveDeref( p->ddR, bTemp ); Extra_StopManager( p->ddR ); } Aig_ManStop( p->pAig ); Vec_PtrFreeP( &p->vGroups ); Vec_IntFreeP( &p->vVar2Obj ); Vec_IntFreeP( &p->vObj2Var ); Vec_IntFreeP( &p->vVarBegs ); Vec_IntFreeP( &p->vVarEnds ); Vec_PtrFreeP( &p->vRings ); Vec_IntFreeP( &p->vNs2Glo ); Vec_IntFreeP( &p->vCs2Glo ); Vec_IntFreeP( &p->vGlo2Cs ); Vec_IntFreeP( &p->vGlo2Ns ); // Vec_IntFreeP( &p->vHints ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) { Llb_Man_t * p; Aig_ManCleanMarkA( pAig ); p = ABC_CALLOC( Llb_Man_t, 1 ); p->pAigGlo = pAigGlo; p->pPars = pPars; p->pAig = pAig; p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots ); p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 ); p->vRings = Vec_PtrAlloc( 100 ); Llb_ManPrepareVarMap( p ); Llb_ManPrepareGroups( p ); Aig_ManCleanMarkA( pAig ); p->pMatrix = Llb_MtrCreate( p ); p->pMatrix->pMan = p; return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Matrix.c000066400000000000000000000266211300674244400235300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Matrix.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Partition clustering as a matrix problem.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // 0123 nCols // +---------------------> // pi 0 | 111 row0 pRowSums[0] // pi 1 | 1 11 row1 pRowSums[1] // pi 2 | 1 11 row2 pRowSums[2] // CS |1 1 // CS |1 111 // CS |111 111 // int | 11111 // int | 111 // int | 111 // int | 111 // NS | 11 11 // NS | 11 1 // NS | 111 // nRows | // v // cccc pColSums[0] // oooo pColSums[1] // llll pColSums[2] // 0123 pColSums[3] //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Verify columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p ) { int iRow, iCol, Counter; for ( iCol = 0; iCol < p->nCols; iCol++ ) { Counter = 0; for ( iRow = 0; iRow < p->nRows; iRow++ ) if ( p->pMatrix[iCol][iRow] == 1 ) Counter++; assert( Counter == p->pColSums[iCol] ); } } /**Function************************************************************* Synopsis [Verify columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p ) { int iRow, iCol, Counter; for ( iRow = 0; iRow < p->nRows; iRow++ ) { Counter = 0; for ( iCol = 0; iCol < p->nCols; iCol++ ) if ( p->pMatrix[iCol][iRow] == 1 ) Counter++; assert( Counter == p->pRowSums[iRow] ); } } /**Function************************************************************* Synopsis [Verify columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ) { Llb_MtrVerifyRowsAll( p ); Llb_MtrVerifyColumnsAll( p ); } /**Function************************************************************* Synopsis [Sort variables in the order of removal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Llb_MtrFindVarOrder( Llb_Mtr_t * p ) { int * pOrder, * pLast; int i, k, fChanges, Temp; pOrder = ABC_CALLOC( int, p->nRows ); pLast = ABC_CALLOC( int, p->nRows ); for ( i = 0; i < p->nRows; i++ ) { pOrder[i] = i; for ( k = p->nCols - 1; k >= 0; k-- ) if ( p->pMatrix[k][i] ) { pLast[i] = k; break; } } do { fChanges = 0; for ( i = 0; i < p->nRows - 1; i++ ) if ( pLast[i] > pLast[i+1] ) { Temp = pOrder[i]; pOrder[i] = pOrder[i+1]; pOrder[i+1] = Temp; Temp = pLast[i]; pLast[i] = pLast[i+1]; pLast[i+1] = Temp; fChanges = 1; } } while ( fChanges ); ABC_FREE( pLast ); return pOrder; } /**Function************************************************************* Synopsis [Returns type of a variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar ) { static char Buffer[10]; if ( iVar < p->nPis ) strcpy( Buffer, "pi" ); else if ( iVar < p->nPis + p->nFfs ) strcpy( Buffer, "CS" ); else if ( iVar >= p->nRows - p->nFfs ) strcpy( Buffer, "NS" ); else strcpy( Buffer, "int" ); return Buffer; } /**Function************************************************************* Synopsis [Creates one column with vars in the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ) { int * pOrder = NULL; int i, iRow, iCol; if ( fOrder ) pOrder = Llb_MtrFindVarOrder( p ); for ( i = 0; i < p->nRows; i++ ) { iRow = pOrder ? pOrder[i] : i; printf( "%3d : ", iRow ); printf( "%3d ", p->pRowSums[iRow] ); printf( "%3s ", Llb_MtrVarName(p, iRow) ); for ( iCol = 0; iCol < p->nCols; iCol++ ) printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' ); printf( "\n" ); } ABC_FREE( pOrder ); } /**Function************************************************************* Synopsis [Verify columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ) { int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0; int * pGrp1 = ABC_CALLOC( int, p->nRows ); int * pGrp2 = ABC_CALLOC( int, p->nRows ); for ( iVar = 0; iVar < p->nRows; iVar++ ) { if ( p->pRowSums[iVar] == 0 ) continue; for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ ) if ( p->pMatrix[iGrp1][iVar] == 1 ) break; for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- ) if ( p->pMatrix[iGrp2][iVar] == 1 ) break; assert( iGrp1 <= iGrp2 ); pGrp1[iVar] = iGrp1; pGrp2[iVar] = iGrp2; Span += iGrp2 - iGrp1; } // compute span for ( iGrp = 0; iGrp < p->nCols; iGrp++ ) { for ( iVar = 0; iVar < p->nRows; iVar++ ) if ( pGrp1[iVar] == iGrp ) nCutSize++; if ( nCutSizeMax < nCutSize ) nCutSizeMax = nCutSize; for ( iVar = 0; iVar < p->nRows; iVar++ ) if ( pGrp2[iVar] == iGrp ) nCutSize--; } ABC_FREE( pGrp1 ); ABC_FREE( pGrp2 ); printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n", p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax ); if ( nCutSize ) Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize ); } /**Function************************************************************* Synopsis [Starts the matrix representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows ) { Llb_Mtr_t * p; int i; p = ABC_CALLOC( Llb_Mtr_t, 1 ); p->nPis = nPis; p->nFfs = nFfs; p->nRows = nRows; p->nCols = nCols; p->pRowSums = ABC_CALLOC( int, nRows ); p->pColSums = ABC_CALLOC( int, nCols ); p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols ); p->pMatrix = ABC_CALLOC( char *, nCols ); for ( i = 0; i < nCols; i++ ) p->pMatrix[i] = ABC_CALLOC( char, nRows ); // partial product p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions return p; } /**Function************************************************************* Synopsis [Stops the matrix representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrFree( Llb_Mtr_t * p ) { int i; ABC_FREE( p->pProdVars ); ABC_FREE( p->pProdNums ); for ( i = 0; i < p->nCols; i++ ) ABC_FREE( p->pMatrix[i] ); ABC_FREE( p->pRowSums ); ABC_FREE( p->pColSums ); ABC_FREE( p->pMatrix ); ABC_FREE( p->pColGrps ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates one column with vars in the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp ) { Aig_Obj_t * pVar; int i, iRow, iCol = pGrp->Id; assert( iCol >= 0 && iCol < p->nCols ); p->pColGrps[iCol] = pGrp; Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i ) { iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); assert( iRow >= 0 && iRow < p->nRows ); p->pMatrix[iCol][iRow] = 1; p->pColSums[iCol]++; p->pRowSums[iRow]++; } Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i ) { iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); assert( iRow >= 0 && iRow < p->nRows ); p->pMatrix[iCol][iRow] = 1; p->pColSums[iCol]++; p->pRowSums[iRow]++; } } /**Function************************************************************* Synopsis [Matrix reduce.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p ) { int i, k; for ( i = 0; i < p->nRows; i++ ) if ( p->pRowSums[i] < 2 ) { p->pRowSums[i] = 0; for ( k = 0; k < p->nCols; k++ ) { if ( p->pMatrix[k][i] == 1 ) { p->pMatrix[k][i] = 0; p->pColSums[k]--; } } } } /**Function************************************************************* Synopsis [Matrix reduce.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ) { Llb_Mtr_t * pMatrix; Llb_Grp_t * pGroup; int i; pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) ); Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) Llb_MtrAddColumn( pMatrix, pGroup ); // Llb_MtrRemoveSingletonRows( pMatrix ); return pMatrix; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Pivot.c000066400000000000000000000150461300674244400233640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Pivot.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Determining pivot variables.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot ) { Aig_Obj_t * pFanout; int k, iFan = -1; if ( Aig_ObjIsTravIdPrevious(p, pObj) ) return 0; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return 1; if ( Saig_ObjIsLi(p, pObj) ) return 0; if ( Saig_ObjIsPo(p, pObj) ) return 0; if ( pObj == pPivot ) return 1; assert( Aig_ObjIsCand(pObj) ); Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k ) if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) ) { Aig_ObjSetTravIdPrevious(p, pObj); return 0; } Aig_ObjSetTravIdCurrent(p, pObj); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ) { Aig_Obj_t * pObj; int i, Counter = 0; Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0) Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1) Saig_ManForEachLo( p, pObj, i ) Counter += Llb_ManTracePaths_rec( p, pObj, pPivot ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManTestCuts( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Count; Aig_ManFanoutStart( p ); Aig_ManForEachNode( p, pObj, i ) { if ( Aig_ObjRefs(pObj) <= 1 ) continue; Count = Llb_ManTracePaths( p, pObj ); printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n", i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count ); } Aig_ManFanoutStop( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj->fMarkB ) return; pObj->fMarkB = 1; assert( Aig_ObjIsNode(pObj) ); Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Determine starting cut-points.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManLabelLiCones( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; // mark const and PIs Aig_ManConst1(p)->fMarkB = 1; Aig_ManForEachCi( p, pObj, i ) pObj->fMarkB = 1; // mark cones Saig_ManForEachLi( p, pObj, i ) Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [Determine starting cut-points.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManMarkInternalPivots( Aig_Man_t * p ) { Vec_Ptr_t * vMuxes; Aig_Obj_t * pObj; int i, Counter = 0; // remove refs due to MUXes vMuxes = Aig_ManMuxesCollect( p ); Aig_ManMuxesDeref( p, vMuxes ); // mark nodes feeding into LIs Aig_ManCleanMarkB( p ); Llb_ManLabelLiCones( p ); // mark internal nodes Aig_ManFanoutStart( p ); Aig_ManForEachNode( p, pObj, i ) if ( pObj->fMarkB && pObj->nRefs > 1 ) { if ( Llb_ManTracePaths(p, pObj) > 0 ) pObj->fMarkA = 1; Counter++; } Aig_ManFanoutStop( p ); // printf( "TracePath tried = %d.\n", Counter ); // mark nodes feeding into LIs Aig_ManCleanMarkB( p ); // add refs due to MUXes Aig_ManMuxesRef( p, vMuxes ); Vec_PtrFree( vMuxes ); } /**Function************************************************************* Synopsis [Determine starting cut-points.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ) { Vec_Int_t * vVar2Obj; Aig_Obj_t * pObj; int i; // mark inputs/outputs Aig_ManForEachCi( p, pObj, i ) pObj->fMarkA = 1; Saig_ManForEachLi( p, pObj, i ) pObj->fMarkA = 1; // mark internal pivot nodes if ( fUseInternal ) Llb_ManMarkInternalPivots( p ); // assign variable numbers Aig_ManConst1(p)->fMarkA = 0; vVar2Obj = Vec_IntAlloc( 100 ); Aig_ManForEachCi( p, pObj, i ) Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); Aig_ManForEachNode( p, pObj, i ) if ( pObj->fMarkA ) Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); Saig_ManForEachLi( p, pObj, i ) Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); return vVar2Obj; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Reach.c000066400000000000000000001035011300674244400232770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Reach.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Reachability analysis.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives global BDD for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd ) { DdNode * bBdd0, * bBdd1, * bFunc; Vec_Ptr_t * vNodes; Aig_Obj_t * pObj = NULL; int i; abctime TimeStop; if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) ) return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) ); TimeStop = dd->TimeStop; dd->TimeStop = 0; vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 ); assert( Vec_PtrSize(vNodes) > 0 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( !Aig_ObjIsNode(pObj) ) continue; bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); } bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( !Aig_ObjIsNode(pObj) ) continue; Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); } Vec_PtrFree( vNodes ); if ( Aig_ObjIsCo(pNode) ) bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) ); Cudd_Deref( bFunc ); dd->TimeStop = TimeStop; return bFunc; } /**Function************************************************************* Synopsis [Derives BDD for the group.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup ) { Aig_Obj_t * pObj; DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp; int i, k; Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) { bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); // pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget ); pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 ); if ( pObj->pData == NULL ) { Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) if ( pObj->pData ) Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); return NULL; } Cudd_Ref( (DdNode *)pObj->pData ); } bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) { if ( Aig_ObjIsCo(pObj) ) bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); else bBdd0 = (DdNode *)pObj->pData; bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor ); // bRes = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget ); bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) ); if ( bRes == NULL ) { Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bXor ); Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) if ( pObj->pData ) Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); return NULL; } Cudd_Ref( bRes ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bXor ); } Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); Cudd_Deref( bRes ); return bRes; } /**Function************************************************************* Synopsis [Derives quantification cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward ) { Aig_Obj_t * pObj; DdNode * bRes, * bTemp, * bVar; int i, iGroupFirst, iGroupLast; abctime TimeStop; TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) { if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) continue; iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); assert( iGroupFirst <= iGroupLast ); if ( iGroupFirst < iGroupLast ) continue; bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( p->dd, bTemp ); } Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) { if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) continue; iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); assert( iGroupFirst <= iGroupLast ); if ( iGroupFirst < iGroupLast ) continue; bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( p->dd, bTemp ); } Cudd_Deref( bRes ); p->dd->TimeStop = TimeStop; return bRes; } /**Function************************************************************* Synopsis [Derives quantification cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) { Aig_Obj_t * pObj; DdNode * bRes, * bTemp, * bVar; int i, iGroupLast; abctime TimeStop; TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) { iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); assert( iGroupLast >= iGrpPlace ); if ( iGroupLast > iGrpPlace ) continue; bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( p->dd, bTemp ); } Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) { iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); assert( iGroupLast >= iGrpPlace ); if ( iGroupLast > iGrpPlace ) continue; bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( p->dd, bTemp ); } Cudd_Deref( bRes ); p->dd->TimeStop = TimeStop; return bRes; } /**Function************************************************************* Synopsis [Derives quantification cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) { Aig_Obj_t * pObj; DdNode * bRes, * bTemp, * bVar; int i, iGroupFirst; abctime TimeStop; TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) { if ( Saig_ObjIsPi(p->pAig, pObj) ) continue; iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); assert( iGroupFirst <= iGrpPlace ); if ( iGroupFirst < iGrpPlace ) continue; bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( p->dd, bTemp ); } Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) { if ( Saig_ObjIsPi(p->pAig, pObj) ) continue; iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); assert( iGroupFirst <= iGrpPlace ); if ( iGroupFirst < iGrpPlace ) continue; bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( p->dd, bTemp ); } Cudd_Deref( bRes ); p->dd->TimeStop = TimeStop; return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd ) { Aig_Obj_t * pObj; DdNode * bRes, * bVar, * bTemp; int i, iVar; abctime TimeStop; TimeStop = dd->TimeStop; dd->TimeStop = 0; bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); Saig_ManForEachLo( p->pAig, pObj, i ) { iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)); bVar = Cudd_bddIthVar( dd, iVar ); bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); dd->TimeStop = TimeStop; return bRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward ) { int fCheckSupport = 0; Llb_Grp_t * pGroup; DdNode * bImage, * bGroup, * bCube, * bTemp; int k, Index; bImage = bInit; Cudd_Ref( bImage ); for ( k = 1; k < p->pMatrix->nCols-1; k++ ) { if ( fBackward ) Index = p->pMatrix->nCols - 1 - k; else Index = k; // compute group BDD pGroup = p->pMatrix->pColGrps[Index]; bGroup = Llb_ManConstructGroupBdd( p, pGroup ); if ( bGroup == NULL ) { Cudd_RecursiveDeref( p->dd, bImage ); return NULL; } Cudd_Ref( bGroup ); // quantify variables appearing only in this group bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward ); Cudd_Ref( bCube ); bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube ); if ( bGroup == NULL ) { Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bCube ); return NULL; } Cudd_Ref( bGroup ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bCube ); // perform partial product if ( fBackward ) bCube = Llb_ManConstructQuantCubeBwd( p, pGroup, Index ); else bCube = Llb_ManConstructQuantCubeFwd( p, pGroup, Index ); Cudd_Ref( bCube ); // bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget ); bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube ); if ( bImage == NULL ) { Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bGroup ); Cudd_RecursiveDeref( p->dd, bCube ); return NULL; } Cudd_Ref( bImage ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bGroup ); Cudd_RecursiveDeref( p->dd, bCube ); } // make sure image depends on next state vars if ( fCheckSupport ) { bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube ); for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) ) { int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index ); Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId ); if ( !Saig_ObjIsLi(p->pAig, pObj) ) printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId ); } Cudd_RecursiveDeref( p->dd, bCube ); } Cudd_Deref( bImage ); return bImage; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars ) { DdNode * bConstr, * bFunc, * bTemp; Aig_Obj_t * pObj; int i, Entry; abctime TimeStop; if ( vHints == NULL ) return Cudd_ReadOne( p->dd ); TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; assert( Aig_ManCiNum(p->pAig) == Aig_ManCiNum(p->pAigGlo) ); // assign const and PI nodes to the original AIG Aig_ManCleanData( p->pAig ); Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd ); Saig_ManForEachPi( p->pAig, pObj, i ) pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); Saig_ManForEachLo( p->pAig, pObj, i ) { if ( fUseNsVars ) Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) ); else Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) ); pObj->pData = Cudd_bddIthVar( p->dd, Entry ); } // transfer them to the global AIG Aig_ManCleanData( p->pAigGlo ); Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); Aig_ManForEachCi( p->pAigGlo, pObj, i ) pObj->pData = Aig_ManCi(p->pAig, i)->pData; // derive consraints bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr ); Vec_IntForEachEntry( vHints, Entry, i ) { if ( Entry != 0 && Entry != 1 ) continue; bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc ); bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint // make the product bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bFunc ); } Cudd_Deref( bConstr ); p->dd->TimeStop = TimeStop; return bConstr; } /**Function************************************************************* Synopsis [Perform reachability with hints and returns reached states in ppGlo.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; int i, v, RetValue, nPiOffset; char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); assert( Vec_PtrSize(p->vRings) > 0 ); p->dd->TimeStop = 0; p->ddR->TimeStop = 0; /* Saig_ManForEachLo( p->pAig, pObj, i ) printf( "%d ", pObj->Id ); printf( "\n" ); Saig_ManForEachLi( p->pAig, pObj, i ) printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); printf( "\n" ); */ // allocate room for the counter-example pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); pCex->iFrame = Vec_PtrSize(p->vRings) - 1; pCex->iPo = -1; // get the last cube bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); Cudd_RecursiveDeref( p->ddR, bOneCube ); assert( RetValue ); // write PIs of counter-example nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); Saig_ManForEachPi( p->pAig, pObj, i ) if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) Abc_InfoSetBit( pCex->pData, nPiOffset + i ); // write state in terms of NS variables if ( Vec_PtrSize(p->vRings) > 1 ) { bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); } // perform backward analysis Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) { if ( v == Vec_PtrSize(p->vRings) - 1 ) continue; //Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); //Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); // compute the next states bImage = Llb_ManComputeImage( p, bState, 1 ); assert( bImage != NULL ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( p->dd, bState ); //Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); // move reached states into ring manager bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( p->dd, bTemp ); //Extra_bddPrintSupport( p->ddR, bImage ); printf( "\n" ); // intersect with the previous set bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); Cudd_RecursiveDeref( p->ddR, bImage ); // find any assignment of the BDD RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); Cudd_RecursiveDeref( p->ddR, bOneCube ); assert( RetValue ); /* for ( i = 0; i < p->ddR->size; i++ ) printf( "%d ", pValues[i] ); printf( "\n" ); */ // write PIs of counter-example nPiOffset -= Saig_ManPiNum(p->pAig); Saig_ManForEachPi( p->pAig, pObj, i ) if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) Abc_InfoSetBit( pCex->pData, nPiOffset + i ); // check that we get the init state if ( v == 0 ) { Saig_ManForEachLo( p->pAig, pObj, i ) assert( pValues[i] == 0 ); break; } // write state in terms of NS variables bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); } assert( nPiOffset == Saig_ManRegNum(p->pAig) ); // update the output number //Abc_CexPrint( pCex ); RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex ); assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!! pCex->iPo = RetValue; // cleanup ABC_FREE( pValues ); return pCex; } /**Function************************************************************* Synopsis [Perform reachability with hints and returns reached states in ppGlo.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ) { int * pNs2Glo = Vec_IntArray( p->vNs2Glo ); int * pCs2Glo = Vec_IntArray( p->vCs2Glo ); int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs ); DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube; DdNode * bConstrCs, * bConstrNs; abctime clk2, clk = Abc_Clock(); int nIters, nBddSize = 0; // int nThreshold = 10000; // compute time to stop p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; // define variable limits Llb_ManPrepareVarLimits( p ); // start the managers assert( p->dd == NULL ); assert( p->ddG == NULL ); assert( p->ddR == NULL ); p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); p->ddR = Cudd_Init( Aig_ManCiNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); if ( pddGlo && *pddGlo ) p->ddG = *pddGlo, *pddGlo = NULL; else p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); if ( p->pPars->fReorder ) { Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); } else { Cudd_AutodynDisable( p->dd ); Cudd_AutodynDisable( p->ddG ); Cudd_AutodynDisable( p->ddR ); } // set the stop time parameter p->dd->TimeStop = p->pPars->TimeTarget; p->ddG->TimeStop = p->pPars->TimeTarget; p->ddR->TimeStop = p->pPars->TimeTarget; // create bad state in the ring manager p->ddR->bFunc = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget ); if ( p->ddR->bFunc == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } Cudd_Ref( p->ddR->bFunc ); // derive constraints bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs ); bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs ); //Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" ); //Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" ); // perform reachability analysis // compute the starting set of states if ( p->ddG->bFunc ) { bReached = p->ddG->bFunc; p->ddG->bFunc = NULL; bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent ); } else { bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached ); bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent ); } //Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" ); //Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); //Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) { clk2 = Abc_Clock(); // check the runtime limit if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) { if ( !p->pPars->fSilent ) printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } // save the onion ring bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo ); if ( bTemp == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bTemp ); Vec_PtrPush( p->vRings, bTemp ); // check it for bad states if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) { assert( p->pAigGlo->pSeqModel == NULL ); if ( !p->pPars->fBackward ) p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p ); if ( !p->pPars->fSilent ) { if ( !p->pPars->fBackward ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAigGlo->pSeqModel->iPo, p->pAigGlo->pName, p->pAigGlo->pName, nIters ); else Abc_Print( 1, "Output ??? of miter \"%s\" was asserted in frame %d (counter-example is not produced). ", p->pAigGlo->pName, nIters ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return 0; } // restrict reachable states using constraints if ( vHints ) { bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent ); Cudd_RecursiveDeref( p->dd, bTemp ); } // quantify variables appearing only in the init state bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 ); Cudd_Ref( bCube ); bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bCube ); // compute the next states bNext = Llb_ManComputeImage( p, bCurrent, 0 ); if ( bNext == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bNext ); Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; // restrict reachable states using constraints if ( vHints ) { bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext ); Cudd_RecursiveDeref( p->dd, bTemp ); } //Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); // remap these states into the current state vars // bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext ); // Cudd_RecursiveDeref( p->dd, bTemp ); // bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget ); bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); if ( bNext == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bNext ); Cudd_RecursiveDeref( p->dd, bTemp ); // check if there are any new states if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states { Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; break; } // check the BDD size nBddSize = Cudd_DagSize(bNext); if ( nBddSize > p->pPars->nBddMax ) { Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; break; } // get the new states bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); if ( bCurrent == NULL ) { Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; break; } Cudd_Ref( bCurrent ); // minimize the new states with the reached states // bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); // bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); // Cudd_RecursiveDeref( p->ddG, bTemp ); //printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) ); // remap these states into the current state vars // bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent ); // Cudd_RecursiveDeref( p->ddG, bTemp ); // bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget ); bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); if ( bCurrent == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->ddG, bTemp ); Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bCurrent ); Cudd_RecursiveDeref( p->ddG, bTemp ); // add to the reached states bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); if ( bReached == NULL ) { Cudd_RecursiveDeref( p->ddG, bTemp ); bTemp = NULL; Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; break; } Cudd_Ref( bReached ); Cudd_RecursiveDeref( p->ddG, bTemp ); Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; if ( p->pPars->fVerbose ) { fprintf( stdout, "F =%5d : ", nIters ); fprintf( stdout, "Im =%6d ", nBddSize ); fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) ); fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); } /* if ( p->pPars->fVerbose ) { double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); // Extra_bddPrint( p->ddG, bReached );printf( "\n" ); fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); fflush( stdout ); } */ } Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; if ( bReached == NULL ) { p->pPars->iFrame = nIters - 1; return 0; // reachable } // assert( bCurrent == NULL ); if ( bCurrent ) Cudd_RecursiveDeref( p->dd, bCurrent ); // report the stats if ( p->pPars->fVerbose ) { double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); else fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); fflush( stdout ); } if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) { if ( !p->pPars->fSilent ) printf( "Verified only for states reachable in %d frames. ", nIters ); p->pPars->iFrame = p->pPars->nIterMax; Cudd_RecursiveDeref( p->ddG, bReached ); return -1; // undecided } if ( pddGlo ) { assert( p->ddG->bFunc == NULL ); p->ddG->bFunc = bReached; bReached = NULL; assert( *pddGlo == NULL ); *pddGlo = p->ddG; p->ddG = NULL; } else Cudd_RecursiveDeref( p->ddG, bReached ); if ( !p->pPars->fSilent ) printf( "The miter is proved unreachable after %d iterations. ", nIters ); p->pPars->iFrame = nIters - 1; return 1; // unreachable } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb1Sched.c000066400000000000000000000170241300674244400233070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb1Sched.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Partition scheduling algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Swaps two rows.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 ) { Llb_Grp_t * pGemp; char * pTemp; int iTemp; assert( iCol1 >= 0 && iCol1 < p->nCols ); assert( iCol2 >= 0 && iCol2 < p->nCols ); if ( iCol1 == iCol2 ) return; assert( iCol1 != iCol2 ); // swap col groups pGemp = p->pColGrps[iCol1]; p->pColGrps[iCol1] = p->pColGrps[iCol2]; p->pColGrps[iCol2] = pGemp; // swap col vectors pTemp = p->pMatrix[iCol1]; p->pMatrix[iCol1] = p->pMatrix[iCol2]; p->pMatrix[iCol2] = pTemp; // swap col sums iTemp = p->pColSums[iCol1]; p->pColSums[iCol1] = p->pColSums[iCol2]; p->pColSums[iCol2] = iTemp; } /**Function************************************************************* Synopsis [Find columns which brings as few vars as possible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart ) { int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY; int WeightCur, WeightBest = -ABC_INFINITY, iGrp = -1, iGrpBest = -1; int k, c, iVar, Counter; // find partition that reduces partial product as much as possible for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) { if ( p->pRowSums[iVar] < 2 ) continue; // look at present variables that can be quantified if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) ) continue; // check that it appears in one partition only Counter = 0; for ( c = iGrpStart; c < p->nCols-1; c++ ) if ( p->pMatrix[c][iVar] == 1 ) { iGrp = c; Counter++; } assert( Counter == 1 ); if ( Counter != 1 ) Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" ); // find weight of this column WeightCur = 0; for ( k = 0; k < p->nRows; k++ ) { // increase weight if variable k will be quantified from partial product if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) WeightCur += 2; // decrease weight if variable k will be added to partial product if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) WeightCur--; } if ( WeightCur > 0 && WeightBest < WeightCur ) { WeightBest = WeightCur; iGrpBest = iGrp; } } if ( iGrpBest >= 0 ) return iGrpBest; // could not find the group with any vars to quantify // select the group that contains as few extra variables as possible // if there is a tie, select variables that appear in less groups than others for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ ) { Cost = Cost2 = 0; for ( k = 0; k < p->nRows; k++ ) if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) { Cost++; Cost2 += p->pProdNums[k]; } if ( CostBest > Cost || (CostBest == Cost && Cost2 > Cost2Best) ) { CostBest = Cost; Cost2Best = Cost2; iGrpBest = iGrp; } } return iGrpBest; } /**Function************************************************************* Synopsis [Returns the number of variables that will be saved.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol ) { int iVar; assert( iCol >= 1 && iCol < p->nCols - 1 ); for ( iVar = 0; iVar < p->nRows; iVar++ ) { if ( p->pMatrix[iCol][iVar] == 0 ) continue; if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 ) { p->pProdVars[iVar] = 0; p->pProdNums[iVar] = 0; continue; } if ( p->pProdVars[iVar] == 0 ) { p->pProdVars[iVar] = 1; p->pProdNums[iVar] = p->pRowSums[iVar]; } p->pProdNums[iVar]--; assert( p->pProdNums[iVar] >= 0 ); if ( p->pProdNums[iVar] < 0 ) Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" ); } } /**Function************************************************************* Synopsis [Verify columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart ) { int iVar, iGrp, Counter; for ( iVar = 0; iVar < p->nRows; iVar++ ) { if ( p->pProdVars[iVar] == 0 ) continue; Counter = 0; for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ ) if ( p->pMatrix[iGrp][iVar] == 1 ) Counter++; assert( Counter == p->pProdNums[iVar] ); if ( Counter != p->pProdNums[iVar] ) Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" ); } } /**Function************************************************************* Synopsis [Matrix reduce.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MtrSchedule( Llb_Mtr_t * p ) { int iGrp, iGrpBest, i; // start partial product for ( i = 0; i < p->nRows; i++ ) { if ( i >= p->nPis && i < p->nPis + p->nFfs ) { p->pProdVars[i] = 1; p->pProdNums[i] = p->pRowSums[i] - 1; } else { p->pProdVars[i] = 0; p->pProdNums[i] = p->pRowSums[i]; } } // order the partitions Llb_MtrVerifyMatrix( p ); for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ ) { Llb_MtrVerifyColumns( p, iGrp ); iGrpBest = Llb_MtrFindBestColumn( p, iGrp ); Llb_MtrUseSelectedColumn( p, iGrpBest ); Llb_MtrSwapColumns( p, iGrp, iGrpBest ); } Llb_MtrVerifyMatrix( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb2Bad.c000066400000000000000000000107771300674244400227600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Bad.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Computing bad states.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes bad in working manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut ) { Vec_Ptr_t * vNodes; DdNode * bBdd0, * bBdd1, * bTemp, * bResult; Aig_Obj_t * pObj; int i, k; assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) ); // initialize elementary variables Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd ); Saig_ManForEachLo( pInit, pObj, i ) pObj->pData = Cudd_bddIthVar( dd, i ); Saig_ManForEachPi( pInit, pObj, i ) pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); // compute internal nodes vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vCos), Saig_ManPoNum(pInit) ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( !Aig_ObjIsNode(pObj) ) continue; bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); // pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); if ( pObj->pData == NULL ) { Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) if ( pObj->pData ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); Vec_PtrFree( vNodes ); return NULL; } Cudd_Ref( (DdNode *)pObj->pData ); } // quantify PIs of each PO bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); Saig_ManForEachPo( pInit, pObj, i ) { bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bTemp ); } // deref Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( !Aig_ObjIsNode(pObj) ) continue; Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); } Vec_PtrFree( vNodes ); Cudd_Deref( bResult ); return bResult; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ) { DdNode * bVar, * bCube, * bTemp; Aig_Obj_t * pObj; int i; abctime TimeStop; assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) ); TimeStop = dd->TimeStop; dd->TimeStop = 0; // create PI cube bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); Saig_ManForEachPi( pInit, pObj, i ) { bVar = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } // quantify PI cube bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bCube ); Cudd_Deref( bFunc ); dd->TimeStop = TimeStop; return bFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb2Core.c000066400000000000000000000675641300674244400231700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Core.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Core procedure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Llb_Img_t_ Llb_Img_t; struct Llb_Img_t_ { Aig_Man_t * pInit; // AIG manager Aig_Man_t * pAig; // AIG manager Gia_ParLlb_t * pPars; // parameters DdManager * dd; // BDD manager DdManager * ddG; // BDD manager DdManager * ddR; // BDD manager Vec_Ptr_t * vDdMans; // BDD managers for each partition Vec_Ptr_t * vRings; // onion rings in ddR Vec_Int_t * vDriRefs; // driver references Vec_Int_t * vVarsCs; // cur state variables Vec_Int_t * vVarsNs; // next state variables Vec_Int_t * vCs2Glo; // cur state variables into global variables Vec_Int_t * vNs2Glo; // next state variables into global variables Vec_Int_t * vGlo2Cs; // global variables into cur state variables Vec_Int_t * vGlo2Ns; // global variables into next state variables }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes cube composed of given variables with given values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ) { DdNode * bRes, * bVar, * bTemp; int i, iVar, Index; abctime TimeStop; TimeStop = dd->TimeStop; dd->TimeStop = 0; bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); Vec_IntForEachEntry( vVars, Index, i ) { iVar = fUseVarIndex ? Index : i; bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) ); bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); dd->TimeStop = TimeStop; return bRes; } /**Function************************************************************* Synopsis [Derives counter-example by backward reachability.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; int i, v, RetValue, nPiOffset; char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); assert( Vec_PtrSize(p->vRings) > 0 ); p->dd->TimeStop = 0; p->ddR->TimeStop = 0; // get supports and quantified variables Vec_PtrReverseOrder( p->vDdMans ); vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 ); Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 ); Vec_VecFree( (Vec_Vec_t *)vSupps ); Llb_ImgQuantifyReset( p->vDdMans ); // Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 ); // allocate room for the counter-example pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); pCex->iFrame = Vec_PtrSize(p->vRings) - 1; pCex->iPo = -1; // get the last cube bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); Cudd_RecursiveDeref( p->ddR, bOneCube ); assert( RetValue ); // write PIs of counter-example nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); Saig_ManForEachPi( p->pAig, pObj, i ) if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) Abc_InfoSetBit( pCex->pData, nPiOffset + i ); // write state in terms of NS variables if ( Vec_PtrSize(p->vRings) > 1 ) { bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); } // perform backward analysis Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) { if ( v == Vec_PtrSize(p->vRings) - 1 ) continue; // compute the next states bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState, vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 ); assert( bImage != NULL ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( p->dd, bState ); //Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); // move reached states into ring manager bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( p->dd, bTemp ); // intersect with the previous set bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); Cudd_RecursiveDeref( p->ddR, bImage ); // find any assignment of the BDD RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); Cudd_RecursiveDeref( p->ddR, bOneCube ); assert( RetValue ); // write PIs of counter-example nPiOffset -= Saig_ManPiNum(p->pAig); Saig_ManForEachPi( p->pAig, pObj, i ) if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) Abc_InfoSetBit( pCex->pData, nPiOffset + i ); // check that we get the init state if ( v == 0 ) { Saig_ManForEachLo( p->pAig, pObj, i ) assert( pValues[i] == 0 ); break; } // write state in terms of NS variables bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); } assert( nPiOffset == Saig_ManRegNum(p->pAig) ); // update the output number RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! pCex->iPo = RetValue; // cleanup ABC_FREE( pValues ); Vec_VecFree( (Vec_Vec_t *)vQuant0 ); Vec_VecFree( (Vec_Vec_t *)vQuant1 ); return pCex; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 ) { int * pLoc2Glo = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo ); int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo ); int * pGlo2Loc = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs ); DdNode * bCurrent, * bReached, * bNext, * bTemp; abctime clk2, clk = Abc_Clock(); int nIters, nBddSize;//, iOutFail = -1; /* // compute time to stop if ( p->pPars->TimeLimit ) p->pPars->TimeTarget = Abc_Clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC; else p->pPars->TimeTarget = 0; */ if ( Abc_Clock() > p->pPars->TimeTarget ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } // set the stop time parameter p->dd->TimeStop = p->pPars->TimeTarget; p->ddG->TimeStop = p->pPars->TimeTarget; p->ddR->TimeStop = p->pPars->TimeTarget; // compute initial states if ( p->pPars->fBackward ) { // create init state in the global manager bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); if ( bTemp == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } Cudd_Ref( bTemp ); // create bad state in the ring manager p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc ); bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp ); Cudd_Ref( bCurrent ); Cudd_RecursiveDeref( p->ddR, bTemp ); bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent ); Cudd_Ref( bReached ); Cudd_RecursiveDeref( p->ddR, bCurrent ); // move init state to the working manager bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc ); if ( bCurrent == NULL ) { Cudd_RecursiveDeref( p->ddG, bReached ); if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } Cudd_Ref( bCurrent ); } else { // create bad state in the ring manager p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); if ( p->ddR->bFunc == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } Cudd_Ref( p->ddR->bFunc ); // create init state in the working and global manager bCurrent = Llb_CoreComputeCube( p->dd, p->vVarsCs, 1, NULL ); Cudd_Ref( bCurrent ); bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL ); Cudd_Ref( bReached ); //Extra_bddPrint( p->dd, bCurrent ); printf( "\n" ); //Extra_bddPrint( p->ddG, bReached ); printf( "\n" ); } // compute onion rings for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) { clk2 = Abc_Clock(); // check the runtime limit if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } // save the onion ring bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR ); if ( bTemp == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bTemp ); Vec_PtrPush( p->vRings, bTemp ); // check it for bad states if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) { assert( p->pInit->pSeqModel == NULL ); if ( !p->pPars->fBackward ) p->pInit->pSeqModel = Llb_CoreDeriveCex( p ); Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; if ( !p->pPars->fSilent ) { if ( !p->pPars->fBackward ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, p->pInit->pName, nIters ); else Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } p->pPars->iFrame = nIters - 1; return 0; } // compute the next states bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent, vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose ); if ( bNext == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bNext ); Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; //Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); // remap these states into the global manager // bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); Cudd_Ref( bNext ); // Cudd_RecursiveDeref( p->dd, bTemp ); // bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget ); bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); if ( bNext == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bNext ); Cudd_RecursiveDeref( p->dd, bTemp ); nBddSize = Cudd_DagSize(bNext); // check if there are any new states if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states { Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; break; } // get the new states bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); if ( bCurrent == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->ddG, bNext ); Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bCurrent ); // remap these states into the current state vars // bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); Cudd_Ref( bCurrent ); // Cudd_RecursiveDeref( p->ddG, bTemp ); // bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget ); bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); if ( bCurrent == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->ddG, bTemp ); Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } Cudd_Ref( bCurrent ); Cudd_RecursiveDeref( p->ddG, bTemp ); // add to the reached states bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); Cudd_Ref( bReached ); Cudd_RecursiveDeref( p->ddG, bTemp ); Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; if ( p->pPars->fVeryVerbose ) { double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); // Extra_bddPrint( p->ddG, bReached );printf( "\n" ); fprintf( stdout, " Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); fflush( stdout ); } if ( p->pPars->fVerbose ) { fprintf( stdout, "F =%3d : ", nIters ); fprintf( stdout, "Image =%6d ", nBddSize ); fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) ); fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); } // check timeframe limit if ( nIters == p->pPars->nIterMax - 1 ) { if ( !p->pPars->fSilent ) printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); p->pPars->iFrame = nIters; Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; return -1; } } if ( bReached == NULL ) { p->pPars->iFrame = nIters - 1; return 0; // reachable } if ( bCurrent ) Cudd_RecursiveDeref( p->dd, bCurrent ); // report the stats if ( p->pPars->fVerbose ) { double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); if ( nIters >= p->pPars->nIterMax ) fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); else fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); fflush( stdout ); } if ( p->pPars->fDumpReached ) { Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" ); printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) ); } Cudd_RecursiveDeref( p->ddG, bReached ); if ( nIters >= p->pPars->nIterMax ) { if ( !p->pPars->fSilent ) { printf( "Verified only for states reachable in %d frames. ", nIters ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } p->pPars->iFrame = p->pPars->nIterMax; return -1; // undecided } if ( !p->pPars->fSilent ) { printf( "The miter is proved unreachable after %d iterations. ", nIters ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } p->pPars->iFrame = nIters - 1; return 1; // unreachable } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_CoreReachability( Llb_Img_t * p ) { Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; int RetValue; // get supports and quantified variables if ( p->pPars->fBackward ) { Vec_PtrReverseOrder( p->vDdMans ); vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose ); } else vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose ); Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose ); Vec_VecFree( (Vec_Vec_t *)vSupps ); // remove variables Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose ); // perform reachability RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 ); Vec_VecFree( (Vec_Vec_t *)vQuant0 ); Vec_VecFree( (Vec_Vec_t *)vQuant1 ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, abctime TimeTarget ) { DdManager * dd; Vec_Ptr_t * vDdMans; Vec_Ptr_t * vLower, * vUpper = NULL; int i; vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) ); Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) { if ( i < Vec_PtrSize(vResult) - 1 ) dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget ); else dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget ); if ( dd == NULL ) { Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) { if ( dd == NULL ) continue; if ( dd->bFunc ) Cudd_RecursiveDeref( dd, dd->bFunc ); Extra_StopManager( dd ); } Vec_PtrFree( vDdMans ); return NULL; } Vec_PtrWriteEntry( vDdMans, i, dd ); vUpper = vLower; } return vDdMans; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_CoreSetVarMaps( Llb_Img_t * p ) { Aig_Obj_t * pObj; int i, iVarCs, iVarNs; assert( p->vVarsCs != NULL ); assert( p->vVarsNs != NULL ); assert( p->vCs2Glo == NULL ); assert( p->vNs2Glo == NULL ); assert( p->vGlo2Cs == NULL ); assert( p->vGlo2Ns == NULL ); p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) { iVarCs = Vec_IntEntry( p->vVarsCs, i ); iVarNs = Vec_IntEntry( p->vVarsNs, i ); assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) ); assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) ); Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i ); Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i ); Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs ); Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs ); } // add mapping of the PIs Saig_ManForEachPi( p->pAig, pObj, i ) Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) { Llb_Img_t * p; p = ABC_CALLOC( Llb_Img_t, 1 ); p->pInit = pInit; p->pAig = pAig; p->pPars = pPars; p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); p->vRings = Vec_PtrAlloc( 100 ); p->vDriRefs = Llb_DriverCountRefs( pAig ); p->vVarsCs = Llb_DriverCollectCs( pAig ); p->vVarsNs = Llb_DriverCollectNs( pAig, p->vDriRefs ); Llb_CoreSetVarMaps( p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_CoreStop( Llb_Img_t * p ) { DdManager * dd; DdNode * bTemp; int i; if ( p->vDdMans ) Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i ) { if ( dd->bFunc ) Cudd_RecursiveDeref( dd, dd->bFunc ); if ( dd->bFunc2 ) Cudd_RecursiveDeref( dd, dd->bFunc2 ); Extra_StopManager( dd ); } Vec_PtrFreeP( &p->vDdMans ); if ( p->ddR->bFunc ) Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) Cudd_RecursiveDeref( p->ddR, bTemp ); Vec_PtrFree( p->vRings ); Extra_StopManager( p->dd ); Extra_StopManager( p->ddG ); Extra_StopManager( p->ddR ); Vec_IntFreeP( &p->vDriRefs ); Vec_IntFreeP( &p->vVarsCs ); Vec_IntFreeP( &p->vVarsNs ); Vec_IntFreeP( &p->vCs2Glo ); Vec_IntFreeP( &p->vNs2Glo ); Vec_IntFreeP( &p->vGlo2Cs ); Vec_IntFreeP( &p->vGlo2Ns ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ) { int RetValue; Llb_Img_t * p; // printf( "\n" ); // pPars->fVerbose = 1; p = Llb_CoreStart( pInit, pAig, pPars ); p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget ); if ( p->vDdMans == NULL ) { if ( !pPars->fSilent ) printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit ); Llb_CoreStop( p ); return -1; } RetValue = Llb_CoreReachability( p ); Llb_CoreStop( p ); return RetValue; } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) { extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ); Vec_Ptr_t * vResult; Aig_Man_t * p; int RetValue = -1; abctime clk = Abc_Clock(); // compute time to stop pPars->TimeTarget = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; p = Aig_ManDupFlopsOnly( pAig ); //Aig_ManShow( p, 0, NULL ); if ( pPars->fVerbose ) Aig_ManPrintStats( pAig ); if ( pPars->fVerbose ) Aig_ManPrintStats( p ); Aig_ManFanoutStart( p ); vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose ); if ( pPars->TimeLimit && Abc_Clock() > pPars->TimeTarget ) { if ( !pPars->fSilent ) printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit ); Vec_VecFree( (Vec_Vec_t *)vResult ); Aig_ManFanoutStop( p ); Aig_ManCleanMarkAB( p ); Aig_ManStop( p ); return RetValue; } if ( !pPars->fSkipReach ) RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget ); Vec_VecFree( (Vec_Vec_t *)vResult ); Aig_ManFanoutStop( p ); Aig_ManCleanMarkAB( p ); Aig_ManStop( p ); if ( RetValue == -1 ) Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", Abc_Clock() - clk ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb2Driver.c000066400000000000000000000147401300674244400235170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Driver.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Procedures working with flop drivers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // driver issue:arises when creating // - driver ref-counter array // - Ns2Glo maps // - final partition // - change-phase cube // LI variable is used when // - driver drives more than one LI // - driver is a PI // - driver is a constant //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the array of times each flop driver is referenced.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ) { Vec_Int_t * vCounts; Aig_Obj_t * pObj; int i; vCounts = Vec_IntStart( Aig_ManObjNumMax(p) ); Saig_ManForEachLi( p, pObj, i ) Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 ); return vCounts; } /**Function************************************************************* Synopsis [Returns array of NS variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ) { Vec_Int_t * vVars; Aig_Obj_t * pObj, * pDri; int i; vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); Saig_ManForEachLi( pAig, pObj, i ) { pDri = Aig_ObjFanin0(pObj); if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) ) Vec_IntPush( vVars, Aig_ObjId(pObj) ); else Vec_IntPush( vVars, Aig_ObjId(pDri) ); } return vVars; } /**Function************************************************************* Synopsis [Returns array of CS variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ) { Vec_Int_t * vVars; Aig_Obj_t * pObj; int i; vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); Saig_ManForEachLo( pAig, pObj, i ) Vec_IntPush( vVars, Aig_ObjId(pObj) ); return vVars; } /**Function************************************************************* Synopsis [Create cube for phase swapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ) { DdNode * bCube, * bVar, * bTemp; Aig_Obj_t * pObj; int i; abctime TimeStop; TimeStop = dd->TimeStop; dd->TimeStop = 0; bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); Saig_ManForEachLi( pAig, pObj, i ) { assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 ); if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 ) continue; if ( !Aig_ObjFaninC0(pObj) ) continue; bVar = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bCube ); dd->TimeStop = TimeStop; return bCube; } /**Function************************************************************* Synopsis [Compute the last partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget ) { // int fVerbose = 1; DdManager * dd; DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp; Aig_Obj_t * pObj; int i; dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); dd->TimeStop = TimeTarget; bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); // mark the duplicated flop inputs Aig_ManForEachObjVec( vVarsNs, p, pObj, i ) { if ( !Saig_ObjIsLi(p, pObj) ) continue; bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) bVar2 = Cudd_ReadOne(dd); bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) ); bProd = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bProd ); // bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); // bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); if ( bRes == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); return NULL; } Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } /* Saig_ManForEachLi( p, pObj, i ) printf( "%d ", Aig_ObjId(pObj) ); printf( "\n" ); Saig_ManForEachLi( p, pObj, i ) printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) ); printf( "\n" ); */ Cudd_AutodynDisable( dd ); // Cudd_RecursiveDeref( dd, bRes ); // Extra_StopManager( dd ); dd->bFunc = bRes; dd->TimeStop = 0; return dd; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb2Dump.c000066400000000000000000000060521300674244400231660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Dump.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Dumps the BDD of reached states into a file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns a dummy name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits ) { static char Buffer[2000]; sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); return Buffer; } /**Function************************************************************* Synopsis [Writes reached state BDD into a BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ) { FILE * pFile; Vec_Ptr_t * vNamesIn, * vNamesOut; char * pName; int i, nDigits; // reorder the BDD Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); // create input names nDigits = Abc_Base10Log( Cudd_ReadSize(ddG) ); vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) ); for ( i = 0; i < Cudd_ReadSize(ddG); i++ ) { pName = Llb_ManGetDummyName( "ff", i, nDigits ); Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) ); } // create output names vNamesOut = Vec_PtrAlloc( 1 ); Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") ); // write the file pFile = fopen( pFileName, "wb" ); Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 ); fclose( pFile ); // cleanup Vec_PtrForEachEntry( char *, vNamesIn, pName, i ) ABC_FREE( pName ); Vec_PtrForEachEntry( char *, vNamesOut, pName, i ) ABC_FREE( pName ); Vec_PtrFree( vNamesIn ); Vec_PtrFree( vNamesOut ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb2Flow.c000066400000000000000000001157061300674244400231770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Flow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Flow computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1; } static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pFanout; int i, iFanout = -1; assert( Llb_ObjGetPath(pObj) ); Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) if ( Llb_ObjGetPath(pFanout) == pObj ) return pFanout; return NULL; } extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [For each cut, returns PIs that can be quantified.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult ) { Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper; int i; vSupps = Vec_PtrAlloc( 100 ); Vec_PtrPush( vSupps, Vec_PtrAlloc(0) ); vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) { vOne = Llb_ManCutSupp( p, vLower, vUpper ); Vec_PtrPush( vSupps, vOne ); vLower = vUpper; } assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) ); return vSupps; } /**Function************************************************************* Synopsis [For each cut, returns PIs that can be quantified.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps ) { int fShowMatrix = 1; Vec_Ptr_t * vMaps, * vOne; Vec_Int_t * vMap, * vPrev, * vNext; Aig_Obj_t * pObj; int * piFirst, * piLast; int i, k, CounterPlus, CounterMinus, Counter; vMaps = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i ) { vMap = Vec_IntStart( Aig_ManObjNumMax(p) ); Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) { if ( !Saig_ObjIsPi(p, pObj) ) Vec_IntWriteEntry( vMap, pObj->Id, 1 ); // else //printf( "*" ); //printf( "%d ", pObj->Id ); } Vec_PtrPush( vMaps, vMap ); //printf( "\n" ); } Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) ); assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 ); // collect the first and last PIs piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) ); piLast = ABC_ALLOC( int, Saig_ManPiNum(p) ); Saig_ManForEachPi( p, pObj, i ) piFirst[i] = piLast[i] = -1; Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i ) { Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) { if ( !Saig_ObjIsPi(p, pObj) ) continue; if ( piFirst[Aig_ObjCioId(pObj)] == -1 ) piFirst[Aig_ObjCioId(pObj)] = i; piLast[Aig_ObjCioId(pObj)] = i; } } // PIs feeding into the flops should be extended to the last frame Saig_ManForEachLi( p, pObj, i ) { if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) ) continue; piLast[Aig_ObjCioId(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1; } // set the PI map Saig_ManForEachPi( p, pObj, i ) { if ( piFirst[i] == -1 ) continue; if ( piFirst[i] == piLast[i] ) { vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] ); Vec_IntWriteEntry( vMap, pObj->Id, 2 ); continue; } // set support for all in between for ( k = piFirst[i]; k <= piLast[i]; k++ ) { vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k ); Vec_IntWriteEntry( vMap, pObj->Id, 1 ); } } ABC_FREE( piFirst ); ABC_FREE( piLast ); // find all that will appear here Counter = Aig_ManRegNum(p); printf( "%d ", Counter ); Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 ) { vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 ); vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 ); CounterPlus = CounterMinus = 0; Aig_ManForEachObj( p, pObj, k ) { if ( Saig_ObjIsPi(p, pObj) ) { if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) CounterPlus++; if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) ) CounterMinus++; } else { if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) CounterPlus++; if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 ) CounterMinus++; } } Counter = Counter + CounterPlus - CounterMinus; printf( "%d=%d ", i, Counter ); } printf( "\n" ); if ( !fShowMatrix ) return vMaps; Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) continue; Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) if ( Vec_IntEntry(vMap, i) ) break; if ( k == Vec_PtrSize(vMaps) ) continue; printf( "Obj = %4d : ", i ); if ( Saig_ObjIsPi(p,pObj) ) printf( "pi " ); else if ( Saig_ObjIsLo(p,pObj) ) printf( "lo " ); else if ( Aig_ObjIsNode(pObj) ) printf( "and " ); Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) printf( "%d", Vec_IntEntry(vMap, i) ); printf( "\n" ); } return vMaps; } /**Function************************************************************* Synopsis [Counts the number of PIs in the cut] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) { Aig_Obj_t * pObj; int i, Counter = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) if ( Saig_ObjIsPi(p,pObj) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Counts the number of LOs in the cut] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) { Aig_Obj_t * pObj; int i, Counter = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) if ( Saig_ObjIsLo(p,pObj) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Counts the number of LIs in the cut] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) { Aig_Obj_t * pFanout; Aig_Obj_t * pObj; int i, k, iFanout = -1, Counter = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) { if ( Aig_ObjIsCi(pObj) ) continue; Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) { if ( Saig_ObjIsLi(p, pFanout) ) { Counter++; break; } } } return Counter; } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return 0; Aig_ObjSetTravIdCurrent(p, pObj); assert( Aig_ObjIsNode(pObj) ); return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) + Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj)); } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) { Aig_Obj_t * pObj; int i, Counter = 0; // mark the lower cut with the traversal ID Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // count the upper cut Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) Counter += Llb_ManCutVolume_rec( p, pObj ); return Counter; } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); assert( Aig_ObjIsNode(pObj) ); Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; // mark the lower cut with the traversal ID Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // count the upper cut vNodes = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) Llb_ManCutNodes_rec( p, pObj, vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) { Vec_Ptr_t * vNodes, * vSupp; Aig_Obj_t * pObj; int i; vNodes = Llb_ManCutNodes( p, vLower, vUpper ); // mark support of the nodes Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { assert( Aig_ObjIsNode(pObj) ); Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) ); Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) ); } Vec_PtrFree( vNodes ); // collect the support nodes vSupp = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) if ( Aig_ObjIsTravIdCurrent(p, pObj) ) Vec_PtrPush( vSupp, pObj ); return vSupp; } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) { Vec_Ptr_t * vRange; Aig_Obj_t * pObj; int i; // mark the lower cut with the traversal ID Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // collect the upper ones that are not marked vRange = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) Vec_PtrPush( vRange, pObj ); return vRange; } /**Function************************************************************* Synopsis [Prints the given cluster.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) { Vec_Ptr_t * vSupp, * vRange; int Pis, Ffs, And; Pis = Llb_ManCutPiNum(p, vLower); Ffs = Llb_ManCutLoNum(p, vLower); And = Vec_PtrSize(vLower) - Pis - Ffs; printf( "Leaf: %3d=%3d+%3d+%3d ", Vec_PtrSize(vLower), Pis, Ffs, And ); Pis = Llb_ManCutPiNum(p, vUpper); Ffs = Llb_ManCutLiNum(p, vUpper); And = Vec_PtrSize(vUpper) - Pis - Ffs; printf( "Root: %3d=%3d+%3d+%3d ", Vec_PtrSize(vUpper), Pis, Ffs, And ); vSupp = Llb_ManCutSupp( p, vLower, vUpper ); Pis = Llb_ManCutPiNum(p, vSupp); Ffs = Llb_ManCutLoNum(p, vSupp); And = Vec_PtrSize(vSupp) - Pis - Ffs; printf( "Supp: %3d=%3d+%3d+%3d ", Vec_PtrSize(vSupp), Pis, Ffs, And ); vRange = Llb_ManCutRange( p, vLower, vUpper ); Pis = Llb_ManCutPiNum(p, vRange); Ffs = Llb_ManCutLiNum(p, vRange); And = Vec_PtrSize(vRange) - Pis - Ffs; printf( "Range: %3d=%3d+%3d+%3d ", Vec_PtrSize(vRange), Pis, Ffs, And ); printf( "S =%3d. V =%3d.\n", Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) ); Vec_PtrFree( vSupp ); Vec_PtrFree( vRange ); /* { Aig_Obj_t * pObj; int i; printf( "Lower: " ); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) printf( " %d", pObj->Id ); printf( " " ); printf( "Upper: " ); Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) printf( " %d", pObj->Id ); printf( "\n" ); } */ } /**Function************************************************************* Synopsis [Prints the given cluster.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult ) { Vec_Ptr_t * vLower, * vUpper = NULL; int i; Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) { if ( i < Vec_PtrSize(vResult) - 1 ) Llb_ManCutPrint( p, vLower, vUpper ); vUpper = vLower; } } /**Function************************************************************* Synopsis [Tries to find an augmenting path originating in this node.] Description [This procedure works for directed graphs only!] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pFanout; assert( Aig_ObjIsNode(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ); // skip visited nodes if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return 0; Aig_ObjSetTravIdCurrent(p, pObj); // process node without flow if ( !Llb_ObjGetPath(pObj) ) { // start the path if we reached a terminal node if ( pObj->fMarkA ) return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 ); // explore the fanins // Abc_ObjForEachFanin( pObj, pFanin, i ) // if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) // return Abc_ObjSetPath( pObj, pFanin ); if ( Aig_ObjIsNode(pObj) ) { if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) ) return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) ); if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) ) return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) ); } return 0; } // pObj has flow - find the fanout with flow pFanout = Llb_ObjGetFanoutPath( p, pObj ); if ( pFanout == NULL ) return 0; // go through the fanins of the fanout with flow // Abc_ObjForEachFanin( pFanout, pFanin, i ) // if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) ) // return Abc_ObjSetPath( pFanout, pFanin ); assert( Aig_ObjIsNode(pFanout) ); if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) ) return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) ); if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) ) return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) ); // try the fanout if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) ) return Llb_ObjSetPath( pFanout, NULL ); return 0; } /**Function************************************************************* Synopsis [Cleans markB.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) return; assert( Aig_ObjIsNode(pObj) ); Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) ); Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) { Aig_Obj_t * pObj; int i; // label the TFI of the cut nodes Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) Llb_ManFlowLabelTfi_rec( p, pObj ); // collect labeled fanins of non-labeled nodes Vec_PtrClear( vMinCut ); Aig_ManIncrementTravId(p); Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsCo(pObj) && !Aig_ObjIsNode(pObj) ) continue; if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) ) continue; if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) ) { Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj)); Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) ); } if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) ) { Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj)); Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) ); } } } /**Function************************************************************* Synopsis [Find minimum-volume minumum cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p ) { Vec_Ptr_t * vMinCut; Aig_Obj_t * pObj; int i; // collect the cut nodes vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) ); Aig_ManForEachObj( p, pObj, i ) { // node without flow is not a cut node if ( !Llb_ObjGetPath(pObj) ) continue; // unvisited node is below the cut if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) continue; // add terminal with flow or node whose path is not visited if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) ) Vec_PtrPush( vMinCut, pObj ); } return vMinCut; } /**Function************************************************************* Synopsis [Verifies the min-cut is indeed a cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { // skip visited nodes if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return 1; Aig_ObjSetTravIdCurrent(p, pObj); // visit the node if ( Aig_ObjIsConst1(pObj) ) return 1; if ( Aig_ObjIsCi(pObj) ) return 0; // explore the fanins assert( Aig_ObjIsNode(pObj) ); if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) ) return 0; if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) ) return 0; return 1; } /**Function************************************************************* Synopsis [Verifies the min-cut is indeed a cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) { Aig_Obj_t * pObj; int i; // mark the cut with the current traversal ID Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // search from the latches for a path to the COs/CIs Saig_ManForEachLi( p, pObj, i ) { if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Implementation of max-flow/min-cut computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ) { Vec_Ptr_t * vMinCut; Aig_Obj_t * pObj; int Flow, FlowCur, RetValue, i; // find the max-flow Flow = 0; Aig_ManCleanData( p ); Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) { assert( !pObj->fMarkA && pObj->fMarkB ); if ( !Aig_ObjFanin0(pObj)->fMarkB ) { FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); Flow += FlowCur; if ( FlowCur ) Aig_ManIncrementTravId(p); } if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) { FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); Flow += FlowCur; if ( FlowCur ) Aig_ManIncrementTravId(p); } } if ( pnFlow ) *pnFlow = Flow; // mark the nodes reachable from the latches Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) { assert( !pObj->fMarkA && pObj->fMarkB ); if ( !Aig_ObjFanin0(pObj)->fMarkB ) { RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); assert( RetValue == 0 ); } if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) { RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); assert( RetValue == 0 ); } } // find the min-cut with the smallest volume vMinCut = Llb_ManFlowMinCut( p ); assert( Vec_PtrSize(vMinCut) == Flow ); // verify the cut if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); // Llb_ManFlowPrintCut( p, vMinCut ); return vMinCut; } /**Function************************************************************* Synopsis [Implementation of max-flow/min-cut computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p ) { Vec_Ptr_t * vMinCut; Aig_Obj_t * pObj; int Flow, FlowCur, RetValue, i; // find the max-flow Flow = 0; Aig_ManCleanData( p ); Aig_ManIncrementTravId(p); Aig_ManForEachObj( p, pObj, i ) { if ( !pObj->fMarkB ) continue; assert( !pObj->fMarkA ); if ( !Aig_ObjFanin0(pObj)->fMarkB ) { //printf( "%d ", Aig_ObjFanin0(pObj)->Id ); FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); Flow += FlowCur; if ( FlowCur ) Aig_ManIncrementTravId(p); } if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) { //printf( "%d ", Aig_ObjFanin1(pObj)->Id ); FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); Flow += FlowCur; if ( FlowCur ) Aig_ManIncrementTravId(p); } } //printf( "\n" ); // mark the nodes reachable from the latches Aig_ManIncrementTravId(p); Aig_ManForEachObj( p, pObj, i ) { if ( !pObj->fMarkB ) continue; assert( !pObj->fMarkA ); if ( !Aig_ObjFanin0(pObj)->fMarkB ) { RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); assert( RetValue == 0 ); } if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) { RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); assert( RetValue == 0 ); } } // find the min-cut with the smallest volume vMinCut = Llb_ManFlowMinCut( p ); assert( Vec_PtrSize(vMinCut) == Flow ); //printf( "%d ", Vec_PtrSize(vMinCut) ); Llb_ManFlowUpdateCut( p, vMinCut ); //printf( "%d ", Vec_PtrSize(vMinCut) ); // verify the cut if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); // Llb_ManFlowPrintCut( p, vMinCut ); return vMinCut; } /**Function************************************************************* Synopsis [Cleans markB.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj ) { if ( pObj->fMarkB == 0 ) return; pObj->fMarkB = 0; assert( Aig_ObjIsNode(pObj) ); Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) ); Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Cleans markB.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj ) { if ( pObj->fMarkA ) return; pObj->fMarkA = 1; if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) return; assert( Aig_ObjIsNode(pObj) ); Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) ); Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Prepares flow computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) { Aig_Obj_t * pObj; int i; // reset marks Aig_ManForEachObj( p, pObj, i ) { pObj->fMarkA = 0; pObj->fMarkB = 1; } // clean PIs and const Aig_ManConst1(p)->fMarkB = 0; Aig_ManForEachCi( p, pObj, i ) pObj->fMarkB = 0; // clean upper cut //printf( "Upper: "); Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) { Llb_ManFlowCleanMarkB_rec( pObj ); //printf( "%d ", pObj->Id ); } //printf( "\n" ); // set lower cut //printf( "Lower: "); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) { //printf( "%d ", pObj->Id ); assert( pObj->fMarkB == 0 ); Llb_ManFlowSetMarkA_rec( pObj ); } //printf( "\n" ); } /**Function************************************************************* Synopsis [Prepares flow computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone ) { Aig_Obj_t * pObj; int i; Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i ) { assert( Aig_ObjIsNode(pObj) ); assert( pObj->fMarkB == 1 ); pObj->fMarkB = 0; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone ) { Aig_Obj_t * pFanout; int i, iFanout = -1; if ( Saig_ObjIsLi(p, pObj) ) return; if ( pObj->fMarkB ) return; if ( pObj->fMarkA == 0 ) { assert( Aig_ObjIsNode(pObj) ); pObj->fMarkB = 1; if ( Aig_ObjIsNode(pObj) ) Vec_PtrPush( vCone, pObj ); } Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone ); } /**Function************************************************************* Synopsis [Collects the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone ) { Aig_Obj_t * pObj; int i; Vec_PtrClear( vCone ); Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i ) { assert( pObj->fMarkA && !pObj->fMarkB ); Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone ); } } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p ) { Vec_Ptr_t * vMinCut; Aig_Obj_t * pObj; int i; vMinCut = Vec_PtrAlloc( 100 ); Aig_ManForEachCi( p, pObj, i ) Vec_PtrPush( vMinCut, pObj ); return vMinCut; } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p ) { Vec_Ptr_t * vMinCut; Aig_Obj_t * pObj; int i; assert( Saig_ManPoNum(p) == 0 ); vMinCut = Vec_PtrAlloc( 100 ); Aig_ManIncrementTravId(p); Saig_ManForEachLi( p, pObj, i ) { pObj = Aig_ObjFanin0(pObj); if ( Aig_ObjIsConst1(pObj) ) continue; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) continue; Aig_ObjSetTravIdCurrent(p, pObj); Vec_PtrPush( vMinCut, pObj ); } return vMinCut; } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet ) { Aig_Obj_t * pObj; int i; Vec_PtrClear( vSet ); for ( i = 0; i < nSize; i++ ) { pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) ); Vec_PtrPush( vSet, pObj ); } } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num ) { int nVolMin = Aig_ManNodeNum(p) / Num / 2; Vec_Ptr_t * vMinCut; Vec_Ptr_t * vCone, * vSet; Aig_Obj_t * pObj; int i, s, Vol, VolLower, VolUpper, VolCmp; int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0; Vol = Llb_ManCutVolume( p, vLower, vUpper ); assert( Vol > nVolMin ); VolCmp = Abc_MinInt( nVolMin, Vol - nVolMin ); vCone = Vec_PtrAlloc( 100 ); vSet = Vec_PtrAlloc( 100 ); Llb_ManFlowPrepareCut( p, vLower, vUpper ); for ( s = 1; s < Aig_ManRegNum(p); s += 5 ) { Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) { Llb_ManFlowGetObjSet( p, vLower, i, s, vSet ); Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); if ( Vec_PtrSize(vCone) == 0 ) continue; vMinCut = Llb_ManFlowCompute( p ); Llb_ManFlowUnmarkCone( p, vCone ); VolLower = Llb_ManCutVolume( p, vLower, vMinCut ); VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper ); Vol = Abc_MinInt( VolLower, VolUpper ); if ( Vol >= VolCmp && (iMinCut == -1 || iMinCut > Vec_PtrSize(vMinCut) || (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) ) { iBest = i; iMinCut = Vec_PtrSize(vMinCut); iVolBest = Vol; } Vec_PtrFree( vMinCut ); } if ( iBest >= 0 ) break; } if ( iBest == -1 ) { // cleanup Vec_PtrFree( vCone ); Vec_PtrFree( vSet ); return NULL; } // get the best cut assert( iBest >= 0 ); Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet ); Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); vMinCut = Llb_ManFlowCompute( p ); Llb_ManFlowUnmarkCone( p, vCone ); // cleanup Vec_PtrFree( vCone ); Vec_PtrFree( vSet ); return vMinCut; } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ) { int nVolMax = Aig_ManNodeNum(p) / Num; Vec_Ptr_t * vResult, * vMinCut = NULL, * vLower, * vUpper; int i, k, nVol; abctime clk = Abc_Clock(); vResult = Vec_PtrAlloc( 100 ); Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) ); Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) ); while ( 1 ) { // find a place to insert new cut vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) { nVol = Llb_ManCutVolume( p, vLower, vUpper ); if ( nVol <= nVolMax ) { vLower = vUpper; continue; } if ( fVeryVerbose ) Llb_ManCutPrint( p, vLower, vUpper ); vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num ); if ( vMinCut == NULL ) { if ( fVeryVerbose ) printf( "Could not break the cut.\n" ); if ( fVeryVerbose ) printf( "\n" ); vLower = vUpper; continue; } if ( fVeryVerbose ) Llb_ManCutPrint( p, vMinCut, vUpper ); if ( fVeryVerbose ) Llb_ManCutPrint( p, vLower, vMinCut ); if ( fVeryVerbose ) printf( "\n" ); break; } if ( i == Vec_PtrSize(vResult) ) break; // insert vMinCut before vUpper Vec_PtrPush( vResult, NULL ); for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- ) Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) ); Vec_PtrWriteEntry( vResult, i, vMinCut ); } if ( fVerbose ) { printf( "Finished computing %d partitions. ", Vec_PtrSize(vResult) - 1 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Llb_ManResultPrint( p, vResult ); } return vResult; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_BddSetDefaultParams( Gia_ParLlb_t * p ) { memset( p, 0, sizeof(Gia_ParLlb_t) ); p->nBddMax = 1000000; p->nIterMax = 10000000; p->nClusterMax = 20; p->nHintDepth = 0; p->HintFirst = 0; p->fUseFlow = 0; // use flow p->nVolumeMax = 100; // max volume p->nVolumeMin = 30; // min volume p->fReorder = 1; p->fIndConstr = 0; p->fUsePivots = 0; p->fCluster = 0; p->fSchedule = 0; p->fVerbose = 0; p->fVeryVerbose = 0; p->fSilent = 0; p->TimeLimit = 0; // p->TimeLimit = 0; p->TimeLimitGlo = 0; p->TimeTarget = 0; p->iFrame = -1; } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num ) { extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult ); extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps ); // int fVerbose = 1; Gia_ParLlb_t Pars, * pPars = &Pars; Vec_Ptr_t * vResult;//, * vSupps, * vMaps; Aig_Man_t * p; Llb_BddSetDefaultParams( pPars ); p = Aig_ManDupFlopsOnly( pAig ); //Aig_ManShow( p, 0, NULL ); Aig_ManPrintStats( pAig ); Aig_ManPrintStats( p ); Aig_ManFanoutStart( p ); vResult = Llb_ManComputeCuts( p, Num, 1, 0 ); // vSupps = Llb_ManCutSupps( p, vResult ); // vMaps = Llb_ManCutMap( p, vResult, vSupps ); // Llb_BddExperiment( pAig, p, pPars, vResult, vMaps ); Llb_CoreExperiment( pAig, p, pPars, vResult, 0 ); // Vec_VecFree( (Vec_Vec_t *)vMaps ); // Vec_VecFree( (Vec_Vec_t *)vSupps ); Vec_VecFree( (Vec_Vec_t *)vResult ); Aig_ManFanoutStop( p ); Aig_ManCleanMarkAB( p ); Aig_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb2Image.c000066400000000000000000000376201300674244400233100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Image.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Computes image using partitioned structure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes supports of the partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ) { Vec_Ptr_t * vSupps; Vec_Int_t * vOne; Aig_Obj_t * pObj; DdManager * dd; DdNode * bSupp, * bTemp; int i, Entry, nSize; nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) ); vSupps = Vec_PtrAlloc( 100 ); // create initial vOne = Vec_IntStart( nSize ); Vec_IntForEachEntry( vStart, Entry, i ) Vec_IntWriteEntry( vOne, Entry, 1 ); Vec_PtrPush( vSupps, vOne ); // create intermediate Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) { vOne = Vec_IntStart( nSize ); bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp ); for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) Vec_IntWriteEntry( vOne, bTemp->index, 1 ); Cudd_RecursiveDeref( dd, bSupp ); Vec_PtrPush( vSupps, vOne ); } // create final vOne = Vec_IntStart( nSize ); Vec_IntForEachEntry( vStop, Entry, i ) Vec_IntWriteEntry( vOne, Entry, 1 ); if ( fAddPis ) Saig_ManForEachPi( p, pObj, i ) Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 ); Vec_PtrPush( vSupps, vOne ); // print supports assert( nSize == Aig_ManObjNumMax(p) ); if ( !fVerbose ) return vSupps; Aig_ManForEachObj( p, pObj, i ) { int k, Counter = 0; Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) Counter += Vec_IntEntry(vOne, i); if ( Counter == 0 ) continue; printf( "Obj = %4d : ", i ); if ( Saig_ObjIsPi(p,pObj) ) printf( "pi " ); else if ( Saig_ObjIsLo(p,pObj) ) printf( "lo " ); else if ( Saig_ObjIsLi(p,pObj) ) printf( "li " ); else if ( Aig_ObjIsNode(pObj) ) printf( "and " ); Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) printf( "%d", Vec_IntEntry(vOne, i) ); printf( "\n" ); } return vSupps; } /**Function************************************************************* Synopsis [Computes quantification schedule.] Description [Input array contains supports: 0=starting, ... intermediate... N-1=final. Output arrays contain immediately quantifiable vars (vQuant0) and vars that should be quantified after conjunction (vQuant1).] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ) { Vec_Int_t * vOne; int nVarsAll, Counter, iSupp = -1, Entry, i, k; // start quantification arrays *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) { Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) ); Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) ); } // count how many times each var appears nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) ); for ( i = 0; i < nVarsAll; i++ ) { Counter = 0; Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) if ( Vec_IntEntry(vOne, i) ) { iSupp = k; Counter++; } if ( Counter == 0 ) continue; if ( Counter == 1 ) Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i ); else // if ( Counter > 1 ) Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i ); } if ( fVerbose ) for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) { printf( "%2d : Quant0 = ", i ); Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k ) printf( "%d ", Entry ); printf( "\n" ); } if ( fVerbose ) for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) { printf( "%2d : Quant1 = ", i ); Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k ) printf( "%d ", Entry ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Computes one partition in a separate BDD manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget ) { Vec_Ptr_t * vNodes, * vRange; Aig_Obj_t * pObj; DdManager * dd; DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp; int i; dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); dd->TimeStop = TimeTarget; Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); vNodes = Llb_ManCutNodes( p, vLower, vUpper ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); // pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); // pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget ); pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); if ( pObj->pData == NULL ) { Cudd_Quit( dd ); Vec_PtrFree( vNodes ); return NULL; } Cudd_Ref( (DdNode *)pObj->pData ); } vRange = Llb_ManCutRange( p, vLower, vUpper ); bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i ) { assert( Aig_ObjIsNode(pObj) ); bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); // bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); // bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); if ( bRes == NULL ) { Cudd_Quit( dd ); Vec_PtrFree( vRange ); Vec_PtrFree( vNodes ); return NULL; } Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); Vec_PtrFree( vRange ); Vec_PtrFree( vNodes ); Cudd_AutodynDisable( dd ); // Cudd_RecursiveDeref( dd, bRes ); // Extra_StopManager( dd ); dd->bFunc = bRes; dd->TimeStop = 0; return dd; } /**Function************************************************************* Synopsis [Derives positive cube composed of nodes IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd ) { DdNode * bProd, * bTemp; Aig_Obj_t * pObj; int i; abctime TimeStop; TimeStop = dd->TimeStop; dd->TimeStop = 0; bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd ); Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i ) { bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bProd ); dd->TimeStop = TimeStop; return bProd; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ) { DdManager * dd; DdNode * bProd, * bRes, * bTemp; int i; abctime clk = Abc_Clock(); Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) { // remember unquantified ones assert( dd->bFunc2 == NULL ); dd->bFunc2 = dd->bFunc; Cudd_Ref( dd->bFunc2 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); bRes = dd->bFunc; if ( fVerbose ) Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) ); bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd ); Cudd_Ref( bProd ); bRes = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); dd->bFunc = bRes; Cudd_AutodynDisable( dd ); if ( fVerbose ) Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); if ( fVerbose ) Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); if ( fVerbose ) Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); if ( fVerbose ) Abc_Print( 1, "Supp = %3d. ", Cudd_SupportSize(dd, bRes) ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ) { DdManager * dd; int i; Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) { assert( dd->bFunc2 != NULL ); Cudd_RecursiveDeref( dd, dd->bFunc ); dd->bFunc = dd->bFunc2; dd->bFunc2 = NULL; } } /**Function************************************************************* Synopsis [Computes image of the initial set of states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, abctime TimeTarget, int fBackward, int fReorder, int fVerbose ) { // int fCheckSupport = 0; DdManager * ddPart; DdNode * bImage, * bGroup, * bCube, * bTemp; int i; abctime clk, clk0 = Abc_Clock(); bImage = bInit; Cudd_Ref( bImage ); if ( fBackward ) { // change polarity bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); } else { // quantify unique vriables bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); if ( bImage == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); return NULL; } Cudd_Ref( bImage ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); } // perform image computation Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i ) { clk = Abc_Clock(); if ( fVerbose ) printf( " %2d : ", i ); // transfer the BDD from the group manager to the main manager bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc ); if ( bGroup == NULL ) return NULL; Cudd_Ref( bGroup ); if ( fVerbose ) printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) ); // perform partial product bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube ); // bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); // bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget ); bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); if ( bImage == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); Cudd_RecursiveDeref( dd, bGroup ); return NULL; } Cudd_Ref( bImage ); if ( fVerbose ) printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) ); //printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n"); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); Cudd_RecursiveDeref( dd, bGroup ); // Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); // Abc_Print( 1, "Reo =%6d. ", Cudd_DagSize(bImage) ); if ( fVerbose ) printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) ); if ( fVerbose ) Abc_PrintTime( 1, "T", Abc_Clock() - clk ); } if ( !fBackward ) { // change polarity bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); } else { // quantify unique vriables bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); } if ( fReorder ) { if ( fVerbose ) Abc_Print( 1, " Reordering... Before =%5d. ", Cudd_DagSize(bImage) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); if ( fVerbose ) Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); // Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); // Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk0 ); // Abc_Print( 1, "\n" ); } Cudd_Deref( bImage ); return bImage; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb3Image.c000066400000000000000000001013731300674244400233060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb3Image.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Computes image using partitioned structure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Llb_Var_t_ Llb_Var_t; struct Llb_Var_t_ { int iVar; // variable number int nScore; // variable score Vec_Int_t * vParts; // partitions }; typedef struct Llb_Prt_t_ Llb_Prt_t; struct Llb_Prt_t_ { int iPart; // partition number int nSize; // the number of BDD nodes DdNode * bFunc; // the partition Vec_Int_t * vVars; // support }; typedef struct Llb_Mgr_t_ Llb_Mgr_t; struct Llb_Mgr_t_ { Aig_Man_t * pAig; // AIG manager Vec_Ptr_t * vLeaves; // leaves in the AIG manager Vec_Ptr_t * vRoots; // roots in the AIG manager DdManager * dd; // working BDD manager int * pVars2Q; // variables to quantify // internal Llb_Prt_t ** pParts; // partitions Llb_Var_t ** pVars; // variables int iPartFree; // next free partition int nVars; // the number of BDD variables int nSuppMax; // maximum support size // temporary int * pSupp; // temporary support storage }; static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } // iterator over vars #define Llb_MgrForEachVar( p, pVar, i ) \ for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else // iterator over parts #define Llb_MgrForEachPart( p, pPart, i ) \ for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else // iterator over vars of one partition #define Llb_PartForEachVar( p, pPart, pVar, i ) \ for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) // iterator over parts of one variable #define Llb_VarForEachPart( p, pVar, pPart, i ) \ for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) // statistics abctime timeBuild, timeAndEx, timeOther; int nSuppMax; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Removes one variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) { assert( p->pVars[pVar->iVar] == pVar ); p->pVars[pVar->iVar] = NULL; Vec_IntFree( pVar->vParts ); ABC_FREE( pVar ); } /**Function************************************************************* Synopsis [Removes one partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) { assert( p->pParts[pPart->iPart] == pPart ); p->pParts[pPart->iPart] = NULL; Vec_IntFree( pPart->vVars ); Cudd_RecursiveDeref( p->dd, pPart->bFunc ); ABC_FREE( pPart ); } /**Function************************************************************* Synopsis [Create cube with singleton variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) { DdNode * bCube, * bTemp; Llb_Var_t * pVar; int i; abctime TimeStop; TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); Llb_PartForEachVar( p, pPart, pVar, i ) { assert( Vec_IntSize(pVar->vParts) > 0 ); if ( Vec_IntSize(pVar->vParts) != 1 ) continue; assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( p->dd, bTemp ); } Cudd_Deref( bCube ); p->dd->TimeStop = TimeStop; return bCube; } /**Function************************************************************* Synopsis [Create cube of variables appearing only in two partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) { DdNode * bCube, * bTemp; Llb_Var_t * pVar; int i; abctime TimeStop; TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); Llb_PartForEachVar( p, pPart1, pVar, i ) { assert( Vec_IntSize(pVar->vParts) > 0 ); if ( Vec_IntSize(pVar->vParts) != 2 ) continue; if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) { bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( p->dd, bTemp ); } } Cudd_Deref( bCube ); p->dd->TimeStop = TimeStop; return bCube; } /**Function************************************************************* Synopsis [Returns 1 if partition has singleton variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) { Llb_Var_t * pVar; int i; Llb_PartForEachVar( p, pPart, pVar, i ) if ( Vec_IntSize(pVar->vParts) == 1 ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns 1 if partition has singleton variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinPrint( Llb_Mgr_t * p ) { Llb_Prt_t * pPart; Llb_Var_t * pVar; int i, k; printf( "\n" ); Llb_MgrForEachVar( p, pVar, i ) { printf( "Var %3d : ", i ); Llb_VarForEachPart( p, pVar, pPart, k ) printf( "%d ", pPart->iPart ); printf( "\n" ); } Llb_MgrForEachPart( p, pPart, i ) { printf( "Part %3d : ", i ); Llb_PartForEachVar( p, pPart, pVar, k ) printf( "%d ", pVar->iVar ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Quantifies singles belonging to one partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset ) { Llb_Var_t * pVar; Llb_Prt_t * pTemp; Vec_Ptr_t * vSingles; DdNode * bCube, * bTemp; int i, RetValue, nSizeNew; if ( fSubset ) { int Length; // int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc ); // pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 ); Cudd_Ref( pPart->bFunc ); pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length ); Cudd_Ref( pPart->bFunc ); printf( "Subsetting %3d : ", pPart->iPart ); printf( "(Supp =%3d Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp), Cudd_DagSize(bTemp) ); printf( "(Supp =%3d Node =%5d)\n", Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) ); RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc)); Cudd_RecursiveDeref( p->dd, bTemp ); if ( RetValue ) return 1; } else { // create cube to be quantified bCube = Llb_NonlinCreateCube1( p, pPart ); Cudd_Ref( bCube ); // assert( !Cudd_IsConstant(bCube) ); // derive new function pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bCube ); } // get support vSingles = Vec_PtrAlloc( 0 ); nSizeNew = Cudd_DagSize(pPart->bFunc); Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); Llb_PartForEachVar( p, pPart, pVar, i ) if ( p->pSupp[pVar->iVar] ) { assert( Vec_IntSize(pVar->vParts) > 1 ); pVar->nScore -= pPart->nSize - nSizeNew; } else { RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); assert( RetValue ); pVar->nScore -= pPart->nSize; if ( Vec_IntSize(pVar->vParts) == 0 ) Llb_NonlinRemoveVar( p, pVar ); else if ( Vec_IntSize(pVar->vParts) == 1 ) Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); } // update partition pPart->nSize = nSizeNew; Vec_IntClear( pPart->vVars ); for ( i = 0; i < p->nVars; i++ ) if ( p->pSupp[i] && p->pVars2Q[i] ) Vec_IntPush( pPart->vVars, i ); // remove other variables Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) Llb_NonlinQuantify1( p, pTemp, 0 ); Vec_PtrFree( vSingles ); return 0; } /**Function************************************************************* Synopsis [Quantifies singles belonging to one partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) { int fVerbose = 0; Llb_Var_t * pVar; Llb_Prt_t * pTemp; Vec_Ptr_t * vSingles; DdNode * bCube, * bFunc; int i, RetValue, nSuppSize; // int iPart1 = pPart1->iPart; // int iPart2 = pPart2->iPart; // create cube to be quantified bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); if ( fVerbose ) { printf( "\n" ); printf( "\n" ); Llb_NonlinPrint( p ); printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); } // derive new function // bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); Cudd_Ref( bFunc ); /* bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit ); if ( bFunc == NULL ) { int RetValue; Cudd_RecursiveDeref( p->dd, bCube ); if ( pPart1->nSize < pPart2->nSize ) RetValue = Llb_NonlinQuantify1( p, pPart1, 1 ); else RetValue = Llb_NonlinQuantify1( p, pPart2, 1 ); if ( RetValue ) Limit = Limit + 1000; Llb_NonlinQuantify2( p, pPart1, pPart2 ); return 0; } Cudd_Ref( bFunc ); */ // bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut ); bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); if ( bFunc == NULL ) { Cudd_RecursiveDeref( p->dd, bCube ); return 0; } Cudd_Ref( bFunc ); Cudd_RecursiveDeref( p->dd, bCube ); // create new partition pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); pTemp->iPart = p->iPartFree++; pTemp->nSize = Cudd_DagSize(bFunc); pTemp->bFunc = bFunc; pTemp->vVars = Vec_IntAlloc( 8 ); // update variables Llb_PartForEachVar( p, pPart1, pVar, i ) { RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); assert( RetValue ); pVar->nScore -= pPart1->nSize; } // update variables Llb_PartForEachVar( p, pPart2, pVar, i ) { RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); assert( RetValue ); pVar->nScore -= pPart2->nSize; } // add variables to the new partition nSuppSize = 0; Extra_SupportArray( p->dd, bFunc, p->pSupp ); for ( i = 0; i < p->nVars; i++ ) { nSuppSize += p->pSupp[i]; if ( p->pSupp[i] && p->pVars2Q[i] ) { pVar = Llb_MgrVar( p, i ); pVar->nScore += pTemp->nSize; Vec_IntPush( pVar->vParts, pTemp->iPart ); Vec_IntPush( pTemp->vVars, i ); } } p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); // remove variables and collect partitions with singleton variables vSingles = Vec_PtrAlloc( 0 ); Llb_PartForEachVar( p, pPart1, pVar, i ) { if ( Vec_IntSize(pVar->vParts) == 0 ) Llb_NonlinRemoveVar( p, pVar ); else if ( Vec_IntSize(pVar->vParts) == 1 ) { if ( fVerbose ) printf( "Adding partition %d because of var %d.\n", Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); } } Llb_PartForEachVar( p, pPart2, pVar, i ) { if ( pVar == NULL ) continue; if ( Vec_IntSize(pVar->vParts) == 0 ) Llb_NonlinRemoveVar( p, pVar ); else if ( Vec_IntSize(pVar->vParts) == 1 ) { if ( fVerbose ) printf( "Adding partition %d because of var %d.\n", Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); } } // remove partitions Llb_NonlinRemovePart( p, pPart1 ); Llb_NonlinRemovePart( p, pPart2 ); // remove other variables if ( fVerbose ) Llb_NonlinPrint( p ); Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) { if ( fVerbose ) printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); Llb_NonlinQuantify1( p, pTemp, 0 ); } if ( fVerbose ) Llb_NonlinPrint( p ); Vec_PtrFree( vSingles ); return 1; } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Saig_ObjIsLi(p, pObj) ) { Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); return; } if ( Aig_ObjIsConst1(pObj) ) return; assert( Aig_ObjIsNode(pObj) ); Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; // mark the lower cut with the traversal ID Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // count the upper cut vNodes = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) Llb_NonlinCutNodes_rec( p, pObj, vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Returns array of BDDs for the roots in terms of the leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd ) { Vec_Ptr_t * vNodes, * vResult; Aig_Obj_t * pObj; DdNode * bBdd0, * bBdd1, * bProd; int i, k; Aig_ManConst1(p)->pData = Cudd_ReadOne( dd ); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); vNodes = Llb_NonlinCutNodes( p, vLower, vUpper ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); // pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); if ( pObj->pData == NULL ) { Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) if ( pObj->pData ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); Vec_PtrFree( vNodes ); return NULL; } Cudd_Ref( (DdNode *)pObj->pData ); } vResult = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) { if ( Aig_ObjIsNode(pObj) ) { bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); } else { assert( Saig_ObjIsLi(p, pObj) ); bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 ); Cudd_Ref( bProd ); } Vec_PtrPush( vResult, bProd ); } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); Vec_PtrFree( vNodes ); return vResult; } /**Function************************************************************* Synopsis [Starts non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar ) { if ( p->pVars[iVar] == NULL ) { p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); p->pVars[iVar]->iVar = iVar; p->pVars[iVar]->nScore = 0; p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); } Vec_IntPush( p->pVars[iVar]->vParts, iPart ); Vec_IntPush( p->pParts[iPart]->vVars, iVar ); } /**Function************************************************************* Synopsis [Starts non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) { int k, nSuppSize; assert( !Cudd_IsConstant(bFunc) ); // create partition p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); p->pParts[i]->iPart = i; p->pParts[i]->bFunc = bFunc; p->pParts[i]->vVars = Vec_IntAlloc( 8 ); // add support dependencies nSuppSize = 0; Extra_SupportArray( p->dd, bFunc, p->pSupp ); for ( k = 0; k < p->nVars; k++ ) { nSuppSize += p->pSupp[k]; if ( p->pSupp[k] && p->pVars2Q[k] ) Llb_NonlinAddPair( p, bFunc, i, k ); } p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); } /**Function************************************************************* Synopsis [Starts non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinStart( Llb_Mgr_t * p ) { Vec_Ptr_t * vRootBdds; DdNode * bFunc; int i; // create and collect BDDs vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd ); // come referenced if ( vRootBdds == NULL ) return 0; // add pairs (refs are consumed inside) Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i ) Llb_NonlinAddPartition( p, i, bFunc ); Vec_PtrFree( vRootBdds ); return 1; } /**Function************************************************************* Synopsis [Checks that each var appears in at least one partition.] Description [] SideEffects [] SeeAlso [] **********************************************************************/ void Llb_NonlinCheckVars( Llb_Mgr_t * p ) { Llb_Var_t * pVar; int i; Llb_MgrForEachVar( p, pVar, i ) assert( Vec_IntSize(pVar->vParts) > 1 ); } /**Function************************************************************* Synopsis [Find next partition to quantify] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) { Llb_Var_t * pVar, * pVarBest = NULL; Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; int i; Llb_NonlinCheckVars( p ); // find variable with minimum score Llb_MgrForEachVar( p, pVar, i ) if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) pVarBest = pVar; if ( pVarBest == NULL ) return 0; // find two partitions with minimum size Llb_VarForEachPart( p, pVarBest, pPart, i ) { if ( pPart1Best == NULL ) pPart1Best = pPart; else if ( pPart2Best == NULL ) pPart2Best = pPart; else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) { if ( pPart1Best->nSize > pPart2Best->nSize ) pPart1Best = pPart; else pPart2Best = pPart; } } *ppPart1 = pPart1Best; *ppPart2 = pPart2Best; return 1; } /**Function************************************************************* Synopsis [Reorders BDDs in the working manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose ) { abctime clk = Abc_Clock(); if ( fVerbose ) Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); if ( fVerbose ) Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); if ( fTwice ) { Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); if ( fVerbose ) Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); } if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Recomputes scores after variable reordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinRecomputeScores( Llb_Mgr_t * p ) { Llb_Prt_t * pPart; Llb_Var_t * pVar; int i, k; Llb_MgrForEachPart( p, pPart, i ) pPart->nSize = Cudd_DagSize(pPart->bFunc); Llb_MgrForEachVar( p, pVar, i ) { pVar->nScore = 0; Llb_VarForEachPart( p, pVar, pPart, k ) pVar->nScore += pPart->nSize; } } /**Function************************************************************* Synopsis [Recomputes scores after variable reordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinVerifyScores( Llb_Mgr_t * p ) { Llb_Prt_t * pPart; Llb_Var_t * pVar; int i, k, nScore; Llb_MgrForEachPart( p, pPart, i ) assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); Llb_MgrForEachVar( p, pVar, i ) { nScore = 0; Llb_VarForEachPart( p, pVar, pPart, k ) nScore += pPart->nSize; assert( nScore == pVar->nScore ); } } /**Function************************************************************* Synopsis [Starts non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd ) { Llb_Mgr_t * p; p = ABC_CALLOC( Llb_Mgr_t, 1 ); p->pAig = pAig; p->vLeaves = vLeaves; p->vRoots = vRoots; p->dd = dd; p->pVars2Q = pVars2Q; p->nVars = Cudd_ReadSize(dd); p->iPartFree = Vec_PtrSize(vRoots); p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); return p; } /**Function************************************************************* Synopsis [Stops non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinFree( Llb_Mgr_t * p ) { Llb_Prt_t * pPart; Llb_Var_t * pVar; int i; Llb_MgrForEachVar( p, pVar, i ) Llb_NonlinRemoveVar( p, pVar ); Llb_MgrForEachPart( p, pPart, i ) Llb_NonlinRemovePart( p, pPart ); ABC_FREE( p->pVars ); ABC_FREE( p->pParts ); ABC_FREE( p->pSupp ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Performs image computation.] Description [Computes image of BDDs (vFuncs).] SideEffects [BDDs in vFuncs are derefed inside. The result is refed.] SeeAlso [] ***********************************************************************/ DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder ) { Llb_Prt_t * pPart, * pPart1, * pPart2; Llb_Mgr_t * p; DdNode * bFunc, * bTemp; int i, nReorders, timeInside; abctime clk = Abc_Clock(), clk2; // start the manager clk2 = Abc_Clock(); p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); if ( !Llb_NonlinStart( p ) ) { Llb_NonlinFree( p ); return NULL; } // add partition Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); // remove singles Llb_MgrForEachPart( p, pPart, i ) if ( Llb_NonlinHasSingletonVars(p, pPart) ) Llb_NonlinQuantify1( p, pPart, 0 ); timeBuild += Abc_Clock() - clk2; timeInside = Abc_Clock() - clk2; // compute scores Llb_NonlinRecomputeScores( p ); // save permutation if ( pOrder ) memcpy( pOrder, dd->invperm, sizeof(int) * dd->size ); // iteratively quantify variables while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) { clk2 = Abc_Clock(); nReorders = Cudd_ReadReorderings(dd); if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) ) { Llb_NonlinFree( p ); return NULL; } timeAndEx += Abc_Clock() - clk2; timeInside += Abc_Clock() - clk2; if ( nReorders < Cudd_ReadReorderings(dd) ) Llb_NonlinRecomputeScores( p ); // else // Llb_NonlinVerifyScores( p ); } // load partitions bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); Llb_MgrForEachPart( p, pPart, i ) { bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( p->dd, bTemp ); } nSuppMax = p->nSuppMax; Llb_NonlinFree( p ); // reorder variables if ( fReorder ) Llb_NonlinReorder( dd, 0, fVerbose ); timeOther += Abc_Clock() - clk - timeInside; // return Cudd_Deref( bFunc ); return bFunc; } static Llb_Mgr_t * p = NULL; /**Function************************************************************* Synopsis [Starts image computation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget ) { DdManager * dd; abctime clk = Abc_Clock(); assert( p == NULL ); // start a new manager (disable reordering) dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); dd->TimeStop = TimeTarget; Cudd_ShuffleHeap( dd, pOrder ); // if ( fFirst ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); // start the manager p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); if ( !Llb_NonlinStart( p ) ) { Llb_NonlinFree( p ); p = NULL; return NULL; } timeBuild += Abc_Clock() - clk; // if ( !fFirst ) // Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); return dd; } /**Function************************************************************* Synopsis [Performs image computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ) { Llb_Prt_t * pPart, * pPart1, * pPart2; DdNode * bFunc, * bTemp; int i, nReorders, timeInside = 0; abctime clk = Abc_Clock(), clk2; // add partition Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); // remove singles Llb_MgrForEachPart( p, pPart, i ) if ( Llb_NonlinHasSingletonVars(p, pPart) ) Llb_NonlinQuantify1( p, pPart, 0 ); // reorder if ( fReorder ) Llb_NonlinReorder( p->dd, 0, 0 ); // save permutation memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size ); // compute scores Llb_NonlinRecomputeScores( p ); // iteratively quantify variables while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) { clk2 = Abc_Clock(); nReorders = Cudd_ReadReorderings(p->dd); if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) ) { Llb_NonlinFree( p ); return NULL; } timeAndEx += Abc_Clock() - clk2; timeInside += Abc_Clock() - clk2; if ( nReorders < Cudd_ReadReorderings(p->dd) ) Llb_NonlinRecomputeScores( p ); // else // Llb_NonlinVerifyScores( p ); } // load partitions bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); Llb_MgrForEachPart( p, pPart, i ) { bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); if ( bFunc == NULL ) { Cudd_RecursiveDeref( p->dd, bTemp ); Llb_NonlinFree( p ); return NULL; } Cudd_Ref( bFunc ); Cudd_RecursiveDeref( p->dd, bTemp ); } nSuppMax = p->nSuppMax; // reorder variables // if ( fReorder ) // Llb_NonlinReorder( p->dd, 0, fVerbose ); // save permutation // memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) ); timeOther += Abc_Clock() - clk - timeInside; // return Cudd_Deref( bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Quits image computation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinImageQuit() { DdManager * dd; if ( p == NULL ) return; dd = p->dd; Llb_NonlinFree( p ); if ( dd->bFunc ) Cudd_RecursiveDeref( dd, dd->bFunc ); Extra_StopManager( dd ); // Cudd_Quit ( dd ); p = NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb3Nonlin.c000066400000000000000000000735031300674244400235240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Nonlin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Non-linear quantification scheduling.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Llb_Mnn_t_ Llb_Mnn_t; struct Llb_Mnn_t_ { Aig_Man_t * pInit; // AIG manager Aig_Man_t * pAig; // AIG manager Gia_ParLlb_t * pPars; // parameters DdManager * dd; // BDD manager DdManager * ddG; // BDD manager DdManager * ddR; // BDD manager Vec_Ptr_t * vRings; // onion rings in ddR Vec_Ptr_t * vLeaves; Vec_Ptr_t * vRoots; int * pVars2Q; int * pOrderL; int * pOrderL2; int * pOrderG; Vec_Int_t * vCs2Glo; // cur state variables into global variables Vec_Int_t * vNs2Glo; // next state variables into global variables Vec_Int_t * vGlo2Cs; // global variables into cur state variables Vec_Int_t * vGlo2Ns; // global variables into next state variables int ddLocReos; int ddLocGrbs; abctime timeImage; abctime timeTran1; abctime timeTran2; abctime timeGloba; abctime timeOther; abctime timeTotal; abctime timeReo; abctime timeReoG; }; extern abctime timeBuild, timeAndEx, timeOther; extern int nSuppMax; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Finds variable whose 0-cofactor is the smallest.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig ) { int fVerbose = 0; Aig_Obj_t * pObj; DdNode * bCof, * bVar; int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1; int Size, Size0, Size1; abctime clk = Abc_Clock(); Size = Cudd_DagSize(bFunc); // printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n", // Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) ); Saig_ManForEachLo( pAig, pObj, i ) { iVar = Aig_ObjId(pObj); if ( fVerbose ) printf( "Var =%3d : ", iVar ); bVar = Cudd_bddIthVar(dd, iVar); bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof ); Size0 = Cudd_DagSize(bCof); if ( fVerbose ) printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) ); if ( fVerbose ) printf( "Size0 =%6d ", Size0 ); Cudd_RecursiveDeref( dd, bCof ); bCof = Cudd_bddAnd( dd, bFunc, bVar ); Cudd_Ref( bCof ); Size1 = Cudd_DagSize(bCof); if ( fVerbose ) printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) ); if ( fVerbose ) printf( "Size1 =%6d ", Size1 ); Cudd_RecursiveDeref( dd, bCof ); iValue = Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) + Size0 + Size1 - Size; if ( fVerbose ) printf( "D =%6d ", Size0 + Size1 - Size ); if ( fVerbose ) printf( "B =%6d ", Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) ); if ( fVerbose ) printf( "S =%6d\n", iValue ); if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue ) { iValueBest = iValue; iVarBest = i; Size0Best = Size0; } } printf( "BestVar = %4d/%4d. Value =%6d. Orig =%6d. Size0 =%6d. ", iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return iVarBest; } /**Function************************************************************* Synopsis [Finds variable whose 0-cofactor is the smallest.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc ) { DdNode * bNew; printf( "Original = %6d. SuppSize = %3d. ", Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) ); bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 ); Cudd_Ref( bNew ); printf( "Result = %6d. SuppSize = %3d.\n", Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) ); Cudd_RecursiveDeref( dd, bNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p ) { Aig_Obj_t * pObjLi, * pObjLo, * pObj; int i, iVarLi, iVarLo; p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { iVarLi = Aig_ObjId(pObjLi); iVarLo = Aig_ObjId(pObjLo); assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) ); assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) ); Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); } // add mapping of the PIs Saig_ManForEachPi( p->pAig, pObj, i ) { Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ) { Aig_Obj_t * pObj; DdNode * bRes, * bVar, * bTemp; int i, iVar; abctime TimeStop; TimeStop = dd->TimeStop; dd->TimeStop = 0; bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); Saig_ManForEachLo( pAig, pObj, i ) { iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj); bVar = Cudd_bddIthVar( dd, iVar ); bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); dd->TimeStop = TimeStop; return bRes; } /**Function************************************************************* Synopsis [Derives counter-example by backward reachability.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; Vec_Int_t * vVarsNs; DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; int i, v, RetValue, nPiOffset; char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); assert( Vec_PtrSize(p->vRings) > 0 ); p->dd->TimeStop = 0; p->ddR->TimeStop = 0; // update quantifiable vars memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) ); vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) ); Saig_ManForEachLi( p->pAig, pObj, i ) { p->pVars2Q[Aig_ObjId(pObj)] = 1; Vec_IntPush( vVarsNs, Aig_ObjId(pObj) ); } /* Saig_ManForEachLo( p->pAig, pObj, i ) printf( "%d ", pObj->Id ); printf( "\n" ); Saig_ManForEachLi( p->pAig, pObj, i ) printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); printf( "\n" ); */ // allocate room for the counter-example pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); pCex->iFrame = Vec_PtrSize(p->vRings) - 1; pCex->iPo = -1; // get the last cube bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); Cudd_RecursiveDeref( p->ddR, bOneCube ); assert( RetValue ); // write PIs of counter-example nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); Saig_ManForEachPi( p->pAig, pObj, i ) if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) Abc_InfoSetBit( pCex->pData, nPiOffset + i ); // write state in terms of NS variables if ( Vec_PtrSize(p->vRings) > 1 ) { bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); } // perform backward analysis Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) { if ( v == Vec_PtrSize(p->vRings) - 1 ) continue; //Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); //Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); // compute the next states bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState, p->pPars->fReorder, p->pPars->fVeryVerbose, NULL ); // consumed reference assert( bImage != NULL ); Cudd_Ref( bImage ); //Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); // move reached states into ring manager bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( p->dd, bTemp ); // intersect with the previous set bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); Cudd_RecursiveDeref( p->ddR, bImage ); // find any assignment of the BDD RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); Cudd_RecursiveDeref( p->ddR, bOneCube ); assert( RetValue ); // write PIs of counter-example nPiOffset -= Saig_ManPiNum(p->pAig); Saig_ManForEachPi( p->pAig, pObj, i ) if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) Abc_InfoSetBit( pCex->pData, nPiOffset + i ); // check that we get the init state if ( v == 0 ) { Saig_ManForEachLo( p->pAig, pObj, i ) assert( pValues[i] == 0 ); break; } // write state in terms of NS variables bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); } assert( nPiOffset == Saig_ManRegNum(p->pAig) ); // update the output number //Abc_CexPrint( pCex ); RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! pCex->iPo = RetValue; // cleanup ABC_FREE( pValues ); Vec_IntFree( vVarsNs ); return pCex; } /**Function************************************************************* Synopsis [Perform reachability with hints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method ) { Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc; Aig_Obj_t * pObj; int i; printf( "Order: " ); for ( i = 0; i < Cudd_ReadSize(dd); i++ ) { pObj = Aig_ManObj( pAig, i ); if ( pObj == NULL ) continue; if ( Saig_ObjIsPi(pAig, pObj) ) printf( "pi" ); else if ( Saig_ObjIsLo(pAig, pObj) ) printf( "lo" ); else if ( Saig_ObjIsPo(pAig, pObj) ) printf( "po" ); else if ( Saig_ObjIsLi(pAig, pObj) ) printf( "li" ); else continue; printf( "%d=%d ", i, dd->perm[i] ); } printf( "\n" ); return 1; } /**Function************************************************************* Synopsis [Perform reachability with hints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev ) { DdSubtable * pSubt; int i, Sum = 0, Entry; for ( i = 0; i < dd->size; i++ ) { pSubt = &(dd->subtables[dd->perm[i]]); if ( pSubt->keys == pSubt->dead + 1 ) continue; Entry = Abc_MaxInt(dd->perm[i], pVar2Lev[i]) - Abc_MinInt(dd->perm[i], pVar2Lev[i]); Sum += Entry; //printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry ); } return Sum; } /**Function************************************************************* Synopsis [Perform reachability with hints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinReachability( Llb_Mnn_t * p ) { DdNode * bTemp, * bNext; int nIters, nBddSize0, nBddSize = -1, NumCmp;//, Limit = p->pPars->nBddMax; abctime clk2, clk3, clk = Abc_Clock(); assert( Aig_ManRegNum(p->pAig) > 0 ); // compute time to stop p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; // set the stop time parameter p->dd->TimeStop = p->pPars->TimeTarget; p->ddG->TimeStop = p->pPars->TimeTarget; p->ddR->TimeStop = p->pPars->TimeTarget; // set reordering hooks assert( p->dd->bFunc == NULL ); // p->dd->bFunc = (DdNode *)p->pAig; // Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK ); // create bad state in the ring manager p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); if ( p->ddR->bFunc == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } Cudd_Ref( p->ddR->bFunc ); // compute the starting set of states Cudd_Quit( p->dd ); p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget ); if ( p->dd == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } p->dd->bFunc = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( p->dd->bFunc ); // current p->ddG->bFunc = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc ); // reached p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc2 ); // frontier for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) { // check the runtime limit clk2 = Abc_Clock(); if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Llb_NonlinImageQuit(); return -1; } // save the onion ring bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) ); if ( bTemp == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Llb_NonlinImageQuit(); return -1; } Cudd_Ref( bTemp ); Vec_PtrPush( p->vRings, bTemp ); // check it for bad states if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) { assert( p->pInit->pSeqModel == NULL ); if ( !p->pPars->fBackward ) p->pInit->pSeqModel = Llb_NonlinDeriveCex( p ); if ( !p->pPars->fSilent ) { if ( !p->pPars->fBackward ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, nIters ); else Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } p->pPars->iFrame = nIters - 1; Llb_NonlinImageQuit(); return 0; } // compute the next states clk3 = Abc_Clock(); nBddSize0 = Cudd_DagSize( p->dd->bFunc ); bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref // bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent, // p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget ); if ( bNext == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Llb_NonlinImageQuit(); return -1; } Cudd_Ref( bNext ); nBddSize = Cudd_DagSize( bNext ); p->timeImage += Abc_Clock() - clk3; // transfer to the state manager clk3 = Abc_Clock(); Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) ); // p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) ); if ( p->ddG->bFunc2 == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bNext ); Llb_NonlinImageQuit(); return -1; } Cudd_Ref( p->ddG->bFunc2 ); Cudd_RecursiveDeref( p->dd, bNext ); p->timeTran1 += Abc_Clock() - clk3; // save permutation NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 ); // save order before image computation memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size ); // update the image computation manager p->timeReo += Cudd_ReadReorderingTime(p->dd); p->ddLocReos += Cudd_ReadReorderings(p->dd); p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd); Llb_NonlinImageQuit(); p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget ); if ( p->dd == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; return -1; } //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 ); // derive new states clk3 = Abc_Clock(); p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) ); if ( p->ddG->bFunc2 == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->ddG, bTemp ); Llb_NonlinImageQuit(); return -1; } Cudd_Ref( p->ddG->bFunc2 ); Cudd_RecursiveDeref( p->ddG, bTemp ); p->timeGloba += Abc_Clock() - clk3; if ( Cudd_IsConstant(p->ddG->bFunc2) ) break; // add to the reached set clk3 = Abc_Clock(); p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 ); if ( p->ddG->bFunc == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->ddG, bTemp ); Llb_NonlinImageQuit(); return -1; } Cudd_Ref( p->ddG->bFunc ); Cudd_RecursiveDeref( p->ddG, bTemp ); p->timeGloba += Abc_Clock() - clk3; // reset permutation // RetValue = Cudd_CheckZeroRef( dd ); // assert( RetValue == 0 ); // Cudd_ShuffleHeap( dd, pOrderG ); // move new states to the working manager clk3 = Abc_Clock(); p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); if ( p->dd->bFunc == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Llb_NonlinImageQuit(); return -1; } Cudd_Ref( p->dd->bFunc ); p->timeTran2 += Abc_Clock() - clk3; // report the results if ( p->pPars->fVerbose ) { printf( "I =%3d : ", nIters ); printf( "Fr =%7d ", nBddSize0 ); printf( "Im =%7d ", nBddSize ); printf( "(%4d %4d) ", p->ddLocReos, p->ddLocGrbs ); printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) ); printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); printf( "S =%4d ", nSuppMax ); printf( "cL =%5d ", NumCmp ); printf( "cG =%5d ", Llb_NonlinCompPerms( p->ddG, p->pOrderG ) ); Abc_PrintTime( 1, "T", Abc_Clock() - clk2 ); memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size ); } /* if ( pPars->fVerbose ) { double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) ); // Extra_bddPrint( ddG, bReached );printf( "\n" ); printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) ); fflush( stdout ); } */ if ( nIters == p->pPars->nIterMax - 1 ) { if ( !p->pPars->fSilent ) printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); p->pPars->iFrame = nIters; Llb_NonlinImageQuit(); return -1; } } Llb_NonlinImageQuit(); // report the stats if ( p->pPars->fVerbose ) { double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) ); if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) printf( "Reachability analysis is stopped after %d frames.\n", nIters ); else printf( "Reachability analysis completed after %d frames.\n", nIters ); printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); fflush( stdout ); } if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) { if ( !p->pPars->fSilent ) printf( "Verified only for states reachable in %d frames. ", nIters ); p->pPars->iFrame = p->pPars->nIterMax; return -1; // undecided } // report if ( !p->pPars->fSilent ) printf( "The miter is proved unreachable after %d iterations. ", nIters ); p->pPars->iFrame = nIters - 1; Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return 1; // unreachable } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) { Llb_Mnn_t * p; Aig_Obj_t * pObj; int i; p = ABC_CALLOC( Llb_Mnn_t, 1 ); p->pInit = pInit; p->pAig = pAig; p->pPars = pPars; p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); p->vRings = Vec_PtrAlloc( 100 ); // create leaves p->vLeaves = Vec_PtrAlloc( Aig_ManCiNum(pAig) ); Aig_ManForEachCi( pAig, pObj, i ) Vec_PtrPush( p->vLeaves, pObj ); // create roots p->vRoots = Vec_PtrAlloc( Aig_ManCoNum(pAig) ); Saig_ManForEachLi( pAig, pObj, i ) Vec_PtrPush( p->vRoots, pObj ); // variables to quantify p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); Aig_ManForEachCi( pAig, pObj, i ) p->pVars2Q[Aig_ObjId(pObj)] = 1; for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i; Llb_NonlinPrepareVarMap( p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MnnStop( Llb_Mnn_t * p ) { DdNode * bTemp; int i; if ( p->pPars->fVerbose ) { p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba; p->timeReoG = Cudd_ReadReorderingTime(p->ddG); ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); ABC_PRTP( " build ", timeBuild, p->timeTotal ); ABC_PRTP( " and-ex ", timeAndEx, p->timeTotal ); ABC_PRTP( " other ", timeOther, p->timeTotal ); ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal ); ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal ); ABC_PRTP( "Global ", p->timeGloba, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); ABC_PRTP( " reoG ", p->timeReoG, p->timeTotal ); } if ( p->ddR->bFunc ) Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) Cudd_RecursiveDeref( p->ddR, bTemp ); Vec_PtrFree( p->vRings ); if ( p->ddG->bFunc ) Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); if ( p->ddG->bFunc2 ) Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); // printf( "manager1\n" ); // Extra_StopManager( p->dd ); // printf( "manager2\n" ); Extra_StopManager( p->ddG ); // printf( "manager3\n" ); Extra_StopManager( p->ddR ); Vec_IntFreeP( &p->vCs2Glo ); Vec_IntFreeP( &p->vNs2Glo ); Vec_IntFreeP( &p->vGlo2Cs ); Vec_IntFreeP( &p->vGlo2Ns ); Vec_PtrFree( p->vLeaves ); Vec_PtrFree( p->vRoots ); ABC_FREE( p->pVars2Q ); ABC_FREE( p->pOrderL ); ABC_FREE( p->pOrderL2 ); ABC_FREE( p->pOrderG ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num ) { Llb_Mnn_t * pMnn; Gia_ParLlb_t Pars, * pPars = &Pars; Aig_Man_t * p; abctime clk = Abc_Clock(); Llb_ManSetDefaultParams( pPars ); pPars->fVerbose = 1; p = Aig_ManDupFlopsOnly( pAig ); //Aig_ManShow( p, 0, NULL ); Aig_ManPrintStats( pAig ); Aig_ManPrintStats( p ); pMnn = Llb_MnnStart( pAig, p, pPars ); Llb_NonlinReachability( pMnn ); pMnn->timeTotal = Abc_Clock() - clk; Llb_MnnStop( pMnn ); Aig_ManStop( p ); } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) { Llb_Mnn_t * pMnn; Aig_Man_t * p; int RetValue = -1; p = Aig_ManDupFlopsOnly( pAig ); //Aig_ManShow( p, 0, NULL ); if ( pPars->fVerbose ) Aig_ManPrintStats( pAig ); if ( pPars->fVerbose ) Aig_ManPrintStats( p ); if ( !pPars->fSkipReach ) { abctime clk = Abc_Clock(); pMnn = Llb_MnnStart( pAig, p, pPars ); RetValue = Llb_NonlinReachability( pMnn ); pMnn->timeTotal = Abc_Clock() - clk; Llb_MnnStop( pMnn ); } Aig_ManStop( p ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb4Cex.c000066400000000000000000000252151300674244400230040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Cex.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Non-linear quantification scheduling.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Translates a sequence of states into a counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ) { Abc_Cex_t * pCex; Cnf_Dat_t * pCnf; Vec_Int_t * vAssumps; sat_solver * pSat; Aig_Obj_t * pObj; unsigned * pNext, * pThis; int i, k, iBit, status, nRegs;//, clk = Abc_Clock(); /* Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) { printf( "%4d : ", i ); Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); printf( "\n" ); } */ // derive SAT solver nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0; pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); pAig->nRegs = nRegs; // Cnf_DataTranformPolarity( pCnf, 0 ); // convert into SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat == NULL ) { printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" ); Cnf_DataFree( pCnf ); return NULL; } // simplify the problem status = sat_solver_simplify(pSat); if ( status == 0 ) { printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); return NULL; } // start the counter-example pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) ); pCex->iFrame = Vec_PtrSize(vStates)-1; pCex->iPo = -1; // solve each time frame iBit = Saig_ManRegNum(pAig); pThis = (unsigned *)Vec_PtrEntry( vStates, 0 ); vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) ); Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 ) { // create assumptions Vec_IntClear( vAssumps ); Saig_ManForEachLo( pAig, pObj, k ) Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); Saig_ManForEachLi( pAig, pObj, k ) Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pNext,k) ) ); // solve SAT problem status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); // if the problem is SAT, get the counterexample if ( status != l_True ) { printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i ); Vec_IntFree( vAssumps ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); ABC_FREE( pCex ); return NULL; } // get the assignment of PIs Saig_ManForEachPi( pAig, pObj, k ) if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) Abc_InfoSetBit( pCex->pData, iBit + k ); // update the counter iBit += Saig_ManPiNum(pAig); pThis = pNext; } // add the last frame when the property fails Vec_IntClear( vAssumps ); if ( iCexPo >= 0 ) { Saig_ManForEachPo( pAig, pObj, k ) if ( k == iCexPo ) Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); } else { Saig_ManForEachPo( pAig, pObj, k ) Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); } // add clause status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) ); if ( status == 0 ) { printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" ); Vec_IntFree( vAssumps ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); ABC_FREE( pCex ); return NULL; } // create assumptions Vec_IntClear( vAssumps ); Saig_ManForEachLo( pAig, pObj, k ) Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); // solve the last frame status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status != l_True ) { printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" ); Vec_IntFree( vAssumps ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); ABC_FREE( pCex ); return NULL; } // get the assignment of PIs Saig_ManForEachPi( pAig, pObj, k ) if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) Abc_InfoSetBit( pCex->pData, iBit + k ); iBit += Saig_ManPiNum(pAig); assert( iBit == pCex->nBits ); // free the sat_solver Vec_IntFree( vAssumps ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); // verify counter-example status = Saig_ManFindFailedPoCex( pAig, pCex ); if ( status >= 0 && status < Saig_ManPoNum(pAig) ) pCex->iPo = status; else { printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" ); ABC_FREE( pCex ); return NULL; } // report the results // if ( fVerbose ) // Abc_PrintTime( 1, "SAT-based cex generation time", Abc_Clock() - clk ); return pCex; } /**Function************************************************************* Synopsis [Resimulates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) { Vec_Ptr_t * vStates; Aig_Obj_t * pObj, * pObjRi, * pObjRo; int i, k, iBit = 0; // create storage for states vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); // verify counter-example Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) pObj->fMarkB = 0; //Abc_InfoHasBit(p->pData, iBit++); // do not require equal flop count in the AIG and in the CEX iBit = p->nRegs; for ( i = 0; i <= p->iFrame; i++ ) { // save current state Saig_ManForEachLo( pAig, pObj, k ) if ( pObj->fMarkB ) Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k ); // compute new state 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; } /* { unsigned * pNext; Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) { printf( "%4d : ", i ); Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); printf( "\n" ); } } */ assert( iBit == p->nBits ); // if ( Aig_ManCo(pAig, p->iPo)->fMarkB == 0 ) // Vec_PtrFreeP( &vStates ); for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- ) { if ( Aig_ManCo(pAig, i)->fMarkB ) { p->iPo = i; break; } } if ( i == -1 ) Vec_PtrFreeP( &vStates ); Aig_ManCleanMarkB(pAig); return vStates; } /**Function************************************************************* Synopsis [Translates a sequence of states into a counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm ) { Abc_Cex_t * pCexOrg; Vec_Ptr_t * vStates; // check parameters of the AIG if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) ) { printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" ); return NULL; } /* if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs ) { printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" ); return NULL; } */ if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis ) { printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" ); return NULL; } // get the sequence of states vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm ); if ( vStates == NULL ) { Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" ); return NULL; } // derive updated counter-example pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 ); Vec_PtrFree( vStates ); return pCexOrg; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb4Cluster.c000066400000000000000000000343541300674244400237120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Cluster.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Non-linear quantification scheduling.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find good static variable ordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) { Aig_Obj_t * pFanin0, * pFanin1; if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent( pAig, pObj ); assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); if ( Aig_ObjIsCi(pObj) ) { Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); return; } // try fanins with higher level first pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); // if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) if ( pFanin0->Level > pFanin1->Level ) { Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); } else { Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); } if ( pObj->fMarkA ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); } /**Function************************************************************* Synopsis [Find good static variable ordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter ) { Vec_Int_t * vNodes = NULL; Vec_Int_t * vOrder; Aig_Obj_t * pObj; int i, Counter = 0; // mark nodes to exclude: AND with low level and CO drivers Aig_ManCleanMarkA( pAig ); Aig_ManForEachNode( pAig, pObj, i ) if ( Aig_ObjLevel(pObj) > 3 ) pObj->fMarkA = 1; Aig_ManForEachCo( pAig, pObj, i ) Aig_ObjFanin0(pObj)->fMarkA = 0; // collect nodes in the order vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); Aig_ManIncrementTravId( pAig ); Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); // Aig_ManForEachCo( pAig, pObj, i ) Saig_ManForEachLi( pAig, pObj, i ) { Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); } Aig_ManForEachCi( pAig, pObj, i ) if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); Aig_ManCleanMarkA( pAig ); Vec_IntFreeP( &vNodes ); // assert( Counter == Aig_ManObjNum(pAig) - 1 ); /* Saig_ManForEachPi( pAig, pObj, i ) printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) ); printf( "\n" ); Saig_ManForEachLo( pAig, pObj, i ) printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) ); printf( "\n" ); Saig_ManForEachPo( pAig, pObj, i ) printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) ); printf( "\n" ); Saig_ManForEachLi( pAig, pObj, i ) printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) ); printf( "\n" ); Aig_ManForEachNode( pAig, pObj, i ) printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) ); printf( "\n" ); */ if ( pCounter ) *pCounter = Counter; return vOrder; } /**Function************************************************************* Synopsis [Derives BDDs for the partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) { DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; if ( Aig_ObjIsConst1(pObj) ) return Cudd_ReadOne(dd); if ( Aig_ObjIsCi(pObj) ) return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); if ( pObj->pData ) return (DdNode *)pObj->pData; if ( Aig_ObjIsCo(pObj) ) { bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); Vec_PtrPush( vRoots, bPart ); return NULL; } bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) { vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); Vec_PtrPush( vRoots, bPart ); Cudd_RecursiveDeref( dd, bBdd ); bBdd = vVar; Cudd_Ref( vVar ); } pObj->pData = bBdd; return bBdd; } /**Function************************************************************* Synopsis [Derives BDDs for the partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs ) { Vec_Ptr_t * vRoots; Aig_Obj_t * pObj; int i; Aig_ManCleanData( pAig ); vRoots = Vec_PtrAlloc( 100 ); if ( fOutputs ) { Saig_ManForEachPo( pAig, pObj, i ) Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); } else { Saig_ManForEachLi( pAig, pObj, i ) Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); } Aig_ManForEachNode( pAig, pObj, i ) if ( pObj->pData ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); return vRoots; } /**Function************************************************************* Synopsis [Creates quantifiable variables for both types of traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) { Vec_Int_t * vVars2Q; Aig_Obj_t * pObj; int i; vVars2Q = Vec_IntAlloc( 0 ); Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); Saig_ManForEachLo( pAig, pObj, i ) Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); // Aig_ManForEachCo( pAig, pObj, i ) Saig_ManForEachLi( pAig, pObj, i ) Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); return vVars2Q; } /**Function************************************************************* Synopsis [Creates quantifiable variables for both types of traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop ) { DdNode * bSupp; Aig_Obj_t * pObj; int i, Counter = 0; bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); if ( !fCo && !fFlop ) { Saig_ManForEachPi( pAig, pObj, i ) if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); } else if ( fCo && !fFlop ) { Saig_ManForEachPo( pAig, pObj, i ) if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); } else if ( !fCo && fFlop ) { Saig_ManForEachLo( pAig, pObj, i ) if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); } else if ( fCo && fFlop ) { Saig_ManForEachLi( pAig, pObj, i ) if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); } Cudd_RecursiveDeref( dd, bSupp ); return Counter; } /**Function************************************************************* Synopsis [Creates quantifiable variables for both types of traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) { DdNode * bTemp; int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd; Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) { //Extra_bddPrintSupport(dd, bTemp); printf("\n" ); nSuppAll = Cudd_SupportSize(dd,bTemp); nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0); nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0); nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1); nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1); nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo); if ( Cudd_DagSize(bTemp) <= 10 ) continue; printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll ); printf( "pi =%3d ", nSuppPi ); printf( "po =%3d ", nSuppPo ); printf( "lo =%3d ", nSuppLo ); printf( "li =%3d ", nSuppLi ); printf( "and =%3d", nSuppAnd ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Creates quantifiable variables for both types of traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) { Aig_Obj_t * pObj; int i, * pSupp; int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); Aig_ManForEachObj( pAig, pObj, i ) { if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) continue; // remove variables that do not participate if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) { if ( Aig_ObjIsNode(pObj) ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); continue; } nSuppAll++; if ( Saig_ObjIsPi(pAig, pObj) ) nSuppPi++; else if ( Saig_ObjIsLo(pAig, pObj) ) nSuppLo++; else if ( Saig_ObjIsPo(pAig, pObj) ) nSuppPo++; else if ( Saig_ObjIsLi(pAig, pObj) ) nSuppLi++; else nSuppAnd++; } ABC_FREE( pSupp ); printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); printf( "Variables: all =%4d ", nSuppAll ); printf( "pi =%4d ", nSuppPi ); printf( "po =%4d ", nSuppPo ); printf( "lo =%4d ", nSuppLo ); printf( "li =%4d ", nSuppLi ); printf( "and =%4d", nSuppAnd ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ) { DdManager * dd; Vec_Int_t * vOrder, * vVars2Q; Vec_Ptr_t * vParts, * vGroups; DdNode * bTemp; int i, nVarNum; // create the BDD manager vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum ); dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder ); vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 ); vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax ); Vec_IntFree( vVars2Q ); Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i ) Cudd_RecursiveDeref( dd, bTemp ); Vec_PtrFree( vParts ); // if ( fVerbose ) Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups ); if ( fVerbose ) printf( "Before reordering\n" ); if ( fVerbose ) Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); // Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); // printf( "After reordering\n" ); // Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); if ( pvOrder ) *pvOrder = vOrder; else Vec_IntFree( vOrder ); if ( pvGroups ) *pvGroups = vGroups; else { Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) Cudd_RecursiveDeref( dd, bTemp ); Vec_PtrFree( vGroups ); } if ( pdd ) *pdd = dd; else Extra_StopManager( dd ); // Cudd_Quit( dd ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb4Image.c000066400000000000000000000631741300674244400233150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb3Image.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Computes image using partitioned structure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Llb_Var_t_ Llb_Var_t; struct Llb_Var_t_ { int iVar; // variable number int nScore; // variable score Vec_Int_t * vParts; // partitions }; typedef struct Llb_Prt_t_ Llb_Prt_t; struct Llb_Prt_t_ { int iPart; // partition number int nSize; // the number of BDD nodes DdNode * bFunc; // the partition Vec_Int_t * vVars; // support }; typedef struct Llb_Mgr_t_ Llb_Mgr_t; struct Llb_Mgr_t_ { DdManager * dd; // working BDD manager Vec_Int_t * vVars2Q; // variables to quantify int nSizeMax; // maximum size of the cluster // internal Llb_Prt_t ** pParts; // partitions Llb_Var_t ** pVars; // variables int iPartFree; // next free partition int nVars; // the number of BDD variables int nSuppMax; // maximum support size // temporary int * pSupp; // temporary support storage }; static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } // iterator over vars #define Llb_MgrForEachVar( p, pVar, i ) \ for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else // iterator over parts #define Llb_MgrForEachPart( p, pPart, i ) \ for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else // iterator over vars of one partition #define Llb_PartForEachVar( p, pPart, pVar, i ) \ for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) // iterator over parts of one variable #define Llb_VarForEachPart( p, pVar, pPart, i ) \ for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) // statistics //abctime timeBuild, timeAndEx, timeOther; //int nSuppMax; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Removes one variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) { assert( p->pVars[pVar->iVar] == pVar ); p->pVars[pVar->iVar] = NULL; Vec_IntFree( pVar->vParts ); ABC_FREE( pVar ); } /**Function************************************************************* Synopsis [Removes one partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) { //printf( "Removing %d\n", pPart->iPart ); assert( p->pParts[pPart->iPart] == pPart ); p->pParts[pPart->iPart] = NULL; Vec_IntFree( pPart->vVars ); Cudd_RecursiveDeref( p->dd, pPart->bFunc ); ABC_FREE( pPart ); } /**Function************************************************************* Synopsis [Create cube with singleton variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) { DdNode * bCube, * bTemp; Llb_Var_t * pVar; int i; abctime TimeStop; TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); Llb_PartForEachVar( p, pPart, pVar, i ) { assert( Vec_IntSize(pVar->vParts) > 0 ); if ( Vec_IntSize(pVar->vParts) != 1 ) continue; assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( p->dd, bTemp ); } Cudd_Deref( bCube ); p->dd->TimeStop = TimeStop; return bCube; } /**Function************************************************************* Synopsis [Create cube of variables appearing only in two partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) { DdNode * bCube, * bTemp; Llb_Var_t * pVar; int i; abctime TimeStop; TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); Llb_PartForEachVar( p, pPart1, pVar, i ) { assert( Vec_IntSize(pVar->vParts) > 0 ); if ( Vec_IntSize(pVar->vParts) != 2 ) continue; if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) { bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( p->dd, bTemp ); } } Cudd_Deref( bCube ); p->dd->TimeStop = TimeStop; return bCube; } /**Function************************************************************* Synopsis [Returns 1 if partition has singleton variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) { Llb_Var_t * pVar; int i; Llb_PartForEachVar( p, pPart, pVar, i ) if ( Vec_IntSize(pVar->vParts) == 1 ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns 1 if partition has singleton variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4Print( Llb_Mgr_t * p ) { Llb_Prt_t * pPart; Llb_Var_t * pVar; int i, k; printf( "\n" ); Llb_MgrForEachVar( p, pVar, i ) { printf( "Var %3d : ", i ); Llb_VarForEachPart( p, pVar, pPart, k ) printf( "%d ", pPart->iPart ); printf( "\n" ); } Llb_MgrForEachPart( p, pPart, i ) { printf( "Part %3d : ", i ); Llb_PartForEachVar( p, pPart, pVar, k ) printf( "%d ", pVar->iVar ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Quantifies singles belonging to one partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) { Llb_Var_t * pVar; Llb_Prt_t * pTemp; Vec_Ptr_t * vSingles; DdNode * bCube, * bTemp; int i, RetValue, nSizeNew; // create cube to be quantified bCube = Llb_Nonlin4CreateCube1( p, pPart ); Cudd_Ref( bCube ); // assert( !Cudd_IsConstant(bCube) ); // derive new function pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); Cudd_RecursiveDeref( p->dd, bTemp ); Cudd_RecursiveDeref( p->dd, bCube ); // get support vSingles = Vec_PtrAlloc( 0 ); nSizeNew = Cudd_DagSize(pPart->bFunc); Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); Llb_PartForEachVar( p, pPart, pVar, i ) if ( p->pSupp[pVar->iVar] ) { assert( Vec_IntSize(pVar->vParts) > 1 ); pVar->nScore -= pPart->nSize - nSizeNew; } else { RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); assert( RetValue ); pVar->nScore -= pPart->nSize; if ( Vec_IntSize(pVar->vParts) == 0 ) Llb_Nonlin4RemoveVar( p, pVar ); else if ( Vec_IntSize(pVar->vParts) == 1 ) Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); } // update partition pPart->nSize = nSizeNew; Vec_IntClear( pPart->vVars ); for ( i = 0; i < p->nVars; i++ ) if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) Vec_IntPush( pPart->vVars, i ); // remove other variables Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) Llb_Nonlin4Quantify1( p, pTemp ); Vec_PtrFree( vSingles ); return 0; } /**Function************************************************************* Synopsis [Quantifies singles belonging to one partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) { int fVerbose = 0; Llb_Var_t * pVar; Llb_Prt_t * pTemp; Vec_Ptr_t * vSingles; DdNode * bCube, * bFunc; int i, RetValue, nSuppSize; // int iPart1 = pPart1->iPart; // int iPart2 = pPart2->iPart; int liveBeg, liveEnd; // create cube to be quantified bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); //printf( "Quantifying " ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); if ( fVerbose ) { printf( "\n" ); printf( "\n" ); Llb_Nonlin4Print( p ); printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); } liveBeg = p->dd->keys - p->dd->dead; bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); liveEnd = p->dd->keys - p->dd->dead; //printf( "%d ", liveEnd-liveBeg ); if ( bFunc == NULL ) { Cudd_RecursiveDeref( p->dd, bCube ); return 0; } Cudd_Ref( bFunc ); Cudd_RecursiveDeref( p->dd, bCube ); //printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc ); printf( "\n" ); //printf( "Creating %d\n", p->iPartFree ); // create new partition pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); pTemp->iPart = p->iPartFree++; pTemp->nSize = Cudd_DagSize(bFunc); pTemp->bFunc = bFunc; pTemp->vVars = Vec_IntAlloc( 8 ); // update variables Llb_PartForEachVar( p, pPart1, pVar, i ) { RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); assert( RetValue ); pVar->nScore -= pPart1->nSize; } // update variables Llb_PartForEachVar( p, pPart2, pVar, i ) { RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); assert( RetValue ); pVar->nScore -= pPart2->nSize; } // add variables to the new partition nSuppSize = 0; Extra_SupportArray( p->dd, bFunc, p->pSupp ); for ( i = 0; i < p->nVars; i++ ) { nSuppSize += p->pSupp[i]; if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) { pVar = Llb_MgrVar( p, i ); pVar->nScore += pTemp->nSize; Vec_IntPush( pVar->vParts, pTemp->iPart ); Vec_IntPush( pTemp->vVars, i ); } } p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); // remove variables and collect partitions with singleton variables vSingles = Vec_PtrAlloc( 0 ); Llb_PartForEachVar( p, pPart1, pVar, i ) { if ( Vec_IntSize(pVar->vParts) == 0 ) Llb_Nonlin4RemoveVar( p, pVar ); else if ( Vec_IntSize(pVar->vParts) == 1 ) { if ( fVerbose ) printf( "Adding partition %d because of var %d.\n", Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); } } Llb_PartForEachVar( p, pPart2, pVar, i ) { if ( pVar == NULL ) continue; if ( Vec_IntSize(pVar->vParts) == 0 ) Llb_Nonlin4RemoveVar( p, pVar ); else if ( Vec_IntSize(pVar->vParts) == 1 ) { if ( fVerbose ) printf( "Adding partition %d because of var %d.\n", Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); } } // remove partitions Llb_Nonlin4RemovePart( p, pPart1 ); Llb_Nonlin4RemovePart( p, pPart2 ); // remove other variables if ( fVerbose ) Llb_Nonlin4Print( p ); Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) { if ( fVerbose ) printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); Llb_Nonlin4Quantify1( p, pTemp ); } if ( fVerbose ) Llb_Nonlin4Print( p ); Vec_PtrFree( vSingles ); return 1; } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Saig_ObjIsLi(p, pObj) ) { Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); return; } if ( Aig_ObjIsConst1(pObj) ) return; assert( Aig_ObjIsNode(pObj) ); Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Computes volume of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; // mark the lower cut with the traversal ID Aig_ManIncrementTravId(p); Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // count the upper cut vNodes = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) Llb_Nonlin4CutNodes_rec( p, pObj, vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Starts non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar ) { if ( p->pVars[iVar] == NULL ) { p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); p->pVars[iVar]->iVar = iVar; p->pVars[iVar]->nScore = 0; p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); } Vec_IntPush( p->pVars[iVar]->vParts, iPart ); Vec_IntPush( p->pParts[iPart]->vVars, iVar ); } /**Function************************************************************* Synopsis [Starts non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) { int k, nSuppSize; assert( !Cudd_IsConstant(bFunc) ); //printf( "Creating init %d\n", i ); // create partition p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); p->pParts[i]->iPart = i; p->pParts[i]->bFunc = bFunc; Cudd_Ref( bFunc ); p->pParts[i]->vVars = Vec_IntAlloc( 8 ); // add support dependencies nSuppSize = 0; Extra_SupportArray( p->dd, bFunc, p->pSupp ); for ( k = 0; k < p->nVars; k++ ) { nSuppSize += p->pSupp[k]; if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) ) Llb_Nonlin4AddPair( p, i, k ); } p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); } /**Function************************************************************* Synopsis [Checks that each var appears in at least one partition.] Description [] SideEffects [] SeeAlso [] **********************************************************************/ void Llb_Nonlin4CheckVars( Llb_Mgr_t * p ) { Llb_Var_t * pVar; int i; Llb_MgrForEachVar( p, pVar, i ) assert( Vec_IntSize(pVar->vParts) > 1 ); } /**Function************************************************************* Synopsis [Find next partition to quantify] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) { Llb_Var_t * pVar, * pVarBest = NULL; Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; int i; Llb_Nonlin4CheckVars( p ); // find variable with minimum score Llb_MgrForEachVar( p, pVar, i ) { if ( p->nSizeMax && pVar->nScore > p->nSizeMax ) continue; // if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore ) if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) pVarBest = pVar; // printf( "%d ", pVar->nScore ); } //printf( "\n" ); if ( pVarBest == NULL ) return 0; // find two partitions with minimum size Llb_VarForEachPart( p, pVarBest, pPart, i ) { if ( pPart1Best == NULL ) pPart1Best = pPart; else if ( pPart2Best == NULL ) pPart2Best = pPart; else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) { if ( pPart1Best->nSize > pPart2Best->nSize ) pPart1Best = pPart; else pPart2Best = pPart; } } //printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize ); //Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" ); //Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" ); *ppPart1 = pPart1Best; *ppPart2 = pPart2Best; return 1; } /**Function************************************************************* Synopsis [Recomputes scores after variable reordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p ) { Llb_Prt_t * pPart; Llb_Var_t * pVar; int i, k; Llb_MgrForEachPart( p, pPart, i ) pPart->nSize = Cudd_DagSize(pPart->bFunc); Llb_MgrForEachVar( p, pVar, i ) { pVar->nScore = 0; Llb_VarForEachPart( p, pVar, pPart, k ) pVar->nScore += pPart->nSize; } } /**Function************************************************************* Synopsis [Recomputes scores after variable reordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p ) { Llb_Prt_t * pPart; Llb_Var_t * pVar; int i, k, nScore; Llb_MgrForEachPart( p, pPart, i ) assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); Llb_MgrForEachVar( p, pVar, i ) { nScore = 0; Llb_VarForEachPart( p, pVar, pPart, k ) nScore += pPart->nSize; assert( nScore == pVar->nScore ); } } /**Function************************************************************* Synopsis [Starts non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax ) { Llb_Mgr_t * p; DdNode * bFunc; int i; p = ABC_CALLOC( Llb_Mgr_t, 1 ); p->dd = dd; p->nSizeMax = nSizeMax; p->vVars2Q = vVars2Q; p->nVars = Cudd_ReadSize(dd); p->iPartFree = Vec_PtrSize(vParts); p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); // add pairs (refs are consumed inside) Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) Llb_Nonlin4AddPartition( p, i, bFunc ); // add partition if ( bCurrent ) Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent ); return p; } /**Function************************************************************* Synopsis [Stops non-linear quantification scheduling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4Free( Llb_Mgr_t * p ) { Llb_Prt_t * pPart; Llb_Var_t * pVar; int i; Llb_MgrForEachVar( p, pVar, i ) Llb_Nonlin4RemoveVar( p, pVar ); Llb_MgrForEachPart( p, pPart, i ) Llb_Nonlin4RemovePart( p, pPart ); ABC_FREE( p->pVars ); ABC_FREE( p->pParts ); ABC_FREE( p->pSupp ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ) { Llb_Prt_t * pPart, * pPart1, * pPart2; Llb_Mgr_t * p; DdNode * bFunc, * bTemp; int i, nReorders; // start the manager p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 ); // remove singles Llb_MgrForEachPart( p, pPart, i ) if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) Llb_Nonlin4Quantify1( p, pPart ); // compute scores Llb_Nonlin4RecomputeScores( p ); // iteratively quantify variables while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) { nReorders = Cudd_ReadReorderings(dd); if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) { Llb_Nonlin4Free( p ); return NULL; } if ( nReorders < Cudd_ReadReorderings(dd) ) Llb_Nonlin4RecomputeScores( p ); // else // Llb_Nonlin4VerifyScores( p ); } // load partitions bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); Llb_MgrForEachPart( p, pPart, i ) { bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( p->dd, bTemp ); } // nSuppMax = p->nSuppMax; Llb_Nonlin4Free( p ); //printf( "\n" ); // return Cudd_Deref( bFunc ); return bFunc; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ) { Vec_Ptr_t * vGroups; Llb_Prt_t * pPart, * pPart1, * pPart2; Llb_Mgr_t * p; int i, nReorders;//, clk = Abc_Clock(); // start the manager p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax ); // remove singles Llb_MgrForEachPart( p, pPart, i ) if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) Llb_Nonlin4Quantify1( p, pPart ); // compute scores Llb_Nonlin4RecomputeScores( p ); // iteratively quantify variables while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) { nReorders = Cudd_ReadReorderings(dd); if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) { Llb_Nonlin4Free( p ); return NULL; } if ( nReorders < Cudd_ReadReorderings(dd) ) Llb_Nonlin4RecomputeScores( p ); // else // Llb_Nonlin4VerifyScores( p ); } // load partitions vGroups = Vec_PtrAlloc( 1000 ); Llb_MgrForEachPart( p, pPart, i ) { //printf( "Iteration %d ", pPart->iPart ); if ( Cudd_IsConstant(pPart->bFunc) ) { //printf( "Constant\n" ); assert( !Cudd_IsComplement(pPart->bFunc) ); continue; } //printf( "\n" ); Vec_PtrPush( vGroups, pPart->bFunc ); Cudd_Ref( pPart->bFunc ); //printf( "Part %d ", pPart->iPart ); //Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" ); } Llb_Nonlin4Free( p ); //Abc_PrintTime( 1, "Reparametrization time", Abc_Clock() - clk ); return vGroups; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb4Map.c000066400000000000000000000066651300674244400230120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Map.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Non-linear quantification scheduling.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" #include "base/abc/abc.h" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns internal nodes used in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ) { extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); extern void Gia_ManSetIfParsDefault( void * pPars ); If_Par_t Pars, * pPars = &Pars; If_Man_t * pIfMan; If_Obj_t * pAnd; Abc_Ntk_t * pNtk; Abc_Obj_t * pNode; Vec_Int_t * vNodes; Aig_Obj_t * pObj; int i; // create ABC network pNtk = Abc_NtkFromAigPhase( pAig ); assert( Abc_NtkIsStrash(pNtk) ); // derive mapping parameters Gia_ManSetIfParsDefault( pPars ); pPars->nLutSize = nLutSize; // get timing information pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); // perform LUT mapping pIfMan = Abc_NtkToIf( pNtk, pPars ); if ( pIfMan == NULL ) { Abc_NtkDelete( pNtk ); return NULL; } if ( !If_ManPerformMapping( pIfMan ) ) { Abc_NtkDelete( pNtk ); If_ManStop( pIfMan ); return NULL; } // mark nodes in the AIG used in the mapping Aig_ManCleanMarkA( pAig ); Aig_ManForEachNode( pAig, pObj, i ) { pNode = (Abc_Obj_t *)pObj->pData; if ( pNode == NULL ) continue; pAnd = (If_Obj_t *)pNode->pCopy; if ( pAnd == NULL ) continue; if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin ) pObj->fMarkA = 1; } Abc_NtkDelete( pNtk ); If_ManStop( pIfMan ); // unmark flop drivers Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjFanin0(pObj)->fMarkA = 0; // collect mapping vNodes = Vec_IntAlloc( 100 ); Aig_ManForEachNode( pAig, pObj, i ) if ( pObj->fMarkA ) Vec_IntPush( vNodes, Aig_ObjId(pObj) ); Aig_ManCleanMarkA( pAig ); return vNodes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb4Nonlin.c000066400000000000000000001156461300674244400235320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Nonlin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Non-linear quantification scheduling.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" #include "base/abc/abc.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Llb_Mnx_t_ Llb_Mnx_t; struct Llb_Mnx_t_ { // user info Aig_Man_t * pAig; // AIG manager Gia_ParLlb_t * pPars; // parameters // intermediate BDDs DdManager * dd; // BDD manager DdNode * bBad; // bad states in terms of CIs DdNode * bReached; // reached states DdNode * bCurrent; // from states DdNode * bNext; // to states Vec_Ptr_t * vRings; // onion rings in ddR Vec_Ptr_t * vRoots; // BDDs for partitions // structural info Vec_Int_t * vOrder; // for each object ID, its BDD variable number or -1 Vec_Int_t * vVars2Q; // 1 if variable is quantifiable; 0 othervise abctime timeImage; abctime timeRemap; abctime timeReo; abctime timeOther; abctime timeTotal; }; //extern int timeBuild, timeAndEx, timeOther; //extern int nSuppMax; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes bad in working manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) { Vec_Ptr_t * vNodes; DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube; Aig_Obj_t * pObj; int i; Aig_ManCleanData( pAig ); // assign elementary variables Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); // compute internal nodes vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vCos), Saig_ManPoNum(pAig) ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( !Aig_ObjIsNode(pObj) ) continue; bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); if ( bBdd == NULL ) { Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); Vec_PtrFree( vNodes ); return NULL; } Cudd_Ref( bBdd ); pObj->pData = bBdd; } // quantify PIs of each PO bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); Saig_ManForEachPo( pAig, pObj, i ) { bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); if ( bResult == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); break; } Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bTemp ); } // deref Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); Vec_PtrFree( vNodes ); if ( bResult ) { bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); Saig_ManForEachPi( pAig, pObj, i ) { bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData ); if ( bCube == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bResult ); bResult = NULL; break; } Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } if ( bResult != NULL ) { bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube ); Cudd_Ref( bResult ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); Cudd_Deref( bResult ); } } //if ( bResult ) //printf( "Bad state = %d.\n", Cudd_DagSize(bResult) ); return bResult; } /**Function************************************************************* Synopsis [Derives BDDs for the partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) { Vec_Ptr_t * vRoots; Aig_Obj_t * pObj; DdNode * bBdd, * bBdd0, * bBdd1, * bPart; int i; Aig_ManCleanData( pAig ); // assign elementary variables Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Aig_ManForEachNode( pAig, pObj, i ) if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) { pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); } Saig_ManForEachLi( pAig, pObj, i ) pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); // compute intermediate BDDs vRoots = Vec_PtrAlloc( 100 ); Aig_ManForEachNode( pAig, pObj, i ) { bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); if ( bBdd == NULL ) goto finish; Cudd_Ref( bBdd ); if ( pObj->pData == NULL ) { pObj->pData = bBdd; continue; } // create new partition bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd ); if ( bPart == NULL ) goto finish; Cudd_Ref( bPart ); Cudd_RecursiveDeref( dd, bBdd ); Vec_PtrPush( vRoots, bPart ); //printf( "%d ", Cudd_DagSize(bPart) ); } // compute register output BDDs Saig_ManForEachLi( pAig, pObj, i ) { bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 ); if ( bPart == NULL ) goto finish; Cudd_Ref( bPart ); Vec_PtrPush( vRoots, bPart ); //printf( "%d ", Cudd_DagSize(bPart) ); } //printf( "\n" ); Aig_ManForEachNode( pAig, pObj, i ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); return vRoots; // early termination finish: Aig_ManForEachNode( pAig, pObj, i ) if ( pObj->pData ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i ) Cudd_RecursiveDeref( dd, bPart ); Vec_PtrFree( vRoots ); return NULL; } /**Function************************************************************* Synopsis [Find simple variable ordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig ) { Vec_Int_t * vOrder; Aig_Obj_t * pObj; int i, Counter = 0; vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); Aig_ManForEachCi( pAig, pObj, i ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); Saig_ManForEachLi( pAig, pObj, i ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); return vOrder; } /**Function************************************************************* Synopsis [Find good static variable ordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) { Aig_Obj_t * pFanin0, * pFanin1; if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent( pAig, pObj ); assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); if ( Aig_ObjIsCi(pObj) ) { // if ( Saig_ObjIsLo(pAig, pObj) ) // Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ ); Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); return; } // try fanins with higher level first pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); // if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) if ( pFanin0->Level > pFanin1->Level ) { Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); } else { Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); } if ( pObj->fMarkA ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); } /**Function************************************************************* Synopsis [Collect nodes with the given fanout count.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans ) { Vec_Int_t * vNodes; Aig_Obj_t * pObj; int i; Aig_ManCleanMarkA( pAig ); Aig_ManForEachNode( pAig, pObj, i ) if ( Aig_ObjRefs(pObj) >= nFans ) pObj->fMarkA = 1; // unmark flop drivers Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjFanin0(pObj)->fMarkA = 0; // collect mapping vNodes = Vec_IntAlloc( 100 ); Aig_ManForEachNode( pAig, pObj, i ) if ( pObj->fMarkA ) Vec_IntPush( vNodes, Aig_ObjId(pObj) ); Aig_ManCleanMarkA( pAig ); return vNodes; } /**Function************************************************************* Synopsis [Find good static variable ordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig ) { Vec_Int_t * vNodes = NULL; Vec_Int_t * vOrder; Aig_Obj_t * pObj; int i, Counter = 0; /* // mark internal nodes to be used Aig_ManCleanMarkA( pAig ); vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 ); Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) pObj->fMarkA = 1; printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) ); */ // collect nodes in the order vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); Aig_ManIncrementTravId( pAig ); Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); Saig_ManForEachLi( pAig, pObj, i ) { Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); } Aig_ManForEachCi( pAig, pObj, i ) if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) { // if ( Saig_ObjIsLo(pAig, pObj) ) // Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ ); Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); } assert( Counter <= Aig_ManCiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) ); Aig_ManCleanMarkA( pAig ); Vec_IntFreeP( &vNodes ); return vOrder; } /**Function************************************************************* Synopsis [Creates quantifiable varaibles for both types of traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) { Vec_Int_t * vVars2Q; Aig_Obj_t * pObjLi, * pObjLo; int i; vVars2Q = Vec_IntAlloc( 0 ); Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 ); return vVars2Q; } /**Function************************************************************* Synopsis [Compute initial state in terms of current state variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) { DdNode ** pVarsX, ** pVarsY; Aig_Obj_t * pObjLo, * pObjLi; int i; pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i ) { assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 ); assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 ); pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) ); pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); } Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) ); ABC_FREE( pVarsX ); ABC_FREE( pVarsY ); } /**Function************************************************************* Synopsis [Compute initial state in terms of current state variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) { Aig_Obj_t * pObjLi, * pObjLo; DdNode * bRes, * bVar, * bTemp; int i; abctime TimeStop; TimeStop = dd->TimeStop; dd->TimeStop = 0; bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) ); bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); dd->TimeStop = TimeStop; return bRes; } /**Function************************************************************* Synopsis [Compute initial state in terms of current state variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag ) { Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp; DdNode * bRes, * bVar, * bTemp; int i; abctime TimeStop; TimeStop = dd->TimeStop; dd->TimeStop = 0; bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { if ( Flag ) pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp; // get the correspoding flop input variable bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 ) bVar = Cudd_Not(bVar); // create cube bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); dd->TimeStop = TimeStop; return bRes; } /**Function************************************************************* Synopsis [Compute initial state in terms of current state variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward ) { Aig_Obj_t * pObjLo, * pObjLi; int i; Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 ) Abc_InfoSetBit( pState, i ); } /**Function************************************************************* Synopsis [Multiply every partition by the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts ) { Vec_Ptr_t * vNew; DdNode * bTemp, * bFunc; int i; vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) ); Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) { bTemp = Cudd_bddAnd( dd, bFunc, bCube ); Cudd_Ref( bTemp ); Vec_PtrPush( vNew, bTemp ); } return vNew; } /**Function************************************************************* Synopsis [Multiply every partition by the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts ) { DdNode * bFunc; int i; Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) Cudd_RecursiveDeref( dd, bFunc ); Vec_PtrFree( vParts ); } /**Function************************************************************* Synopsis [Derives counter-example by backward reachability.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose ) { Vec_Int_t * vVars2Q; Vec_Ptr_t * vStates, * vRootsNew; Aig_Obj_t * pObj; DdNode * bState = NULL, * bImage, * bOneCube, * bRing; int i, v, RetValue;//, clk = Abc_Clock(); char * pValues; assert( Vec_PtrSize(p->vRings) > 0 ); // disable the timeout p->dd->TimeStop = 0; // start the state set vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); if ( fBackward ) Vec_PtrReverseOrder( vStates ); // get the last cube pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) ); bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad ); Cudd_Ref( bOneCube ); RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); Cudd_RecursiveDeref( p->dd, bOneCube ); assert( RetValue ); // record the cube Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward ); // write state in terms of NS variables if ( Vec_PtrSize(p->vRings) > 1 ) { bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); } // perform backward analysis vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward ); Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) { if ( v == Vec_PtrSize(p->vRings) - 1 ) continue; // preprocess partitions vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots ); Cudd_RecursiveDeref( p->dd, bState ); // compute the next states bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage ); Llb_Nonlin4Deref( p->dd, vRootsNew ); // intersect with the previous set bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing ); Cudd_Ref( bOneCube ); Cudd_RecursiveDeref( p->dd, bImage ); // find any assignment of the BDD RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); Cudd_RecursiveDeref( p->dd, bOneCube ); assert( RetValue ); // record the cube Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward ); // check that we get the init state if ( v == 0 ) { Saig_ManForEachLo( p->pAig, pObj, i ) assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 ); break; } // write state in terms of NS variables bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); } Vec_IntFree( vVars2Q ); ABC_FREE( pValues ); if ( fBackward ) Vec_PtrReverseOrder( vStates ); // if ( fVerbose ) // Abc_PrintTime( 1, "BDD-based cex generation time", Abc_Clock() - clk ); return vStates; } /**Function************************************************************* Synopsis [Perform reachability with hints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_Nonlin4Reachability( Llb_Mnx_t * p ) { DdNode * bAux; int nIters, nBddSizeFr = 0, nBddSizeTo = 0, nBddSizeTo2 = 0; abctime clkTemp, clkIter, clk = Abc_Clock(); assert( Aig_ManRegNum(p->pAig) > 0 ); if ( p->pPars->fBackward ) { // create bad state in the ring manager if ( !p->pPars->fSkipOutCheck ) { p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bBad ); } // create init state if ( p->pPars->fCluster ) p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL; else { p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); if ( p->bCurrent == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } Cudd_Ref( p->bCurrent ); } // remap into the next states p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent ); if ( p->bCurrent == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during remapping bad states.\n", p->pPars->TimeLimit ); Cudd_RecursiveDeref( p->dd, bAux ); p->pPars->iFrame = -1; return -1; } Cudd_Ref( p->bCurrent ); Cudd_RecursiveDeref( p->dd, bAux ); } else { // create bad state in the ring manager if ( !p->pPars->fSkipOutCheck ) { if ( p->pPars->fCluster ) p->bBad = p->dd->bFunc, p->dd->bFunc = NULL; else { p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); if ( p->bBad == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); p->pPars->iFrame = -1; return -1; } Cudd_Ref( p->bBad ); } } else if ( p->dd->bFunc ) Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL; // compute the starting set of states p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bCurrent ); } // perform iterations p->bReached = p->bCurrent; Cudd_Ref( p->bReached ); for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) { clkIter = Abc_Clock(); // check the runtime limit if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; return -1; } // save the onion ring Vec_PtrPush( p->vRings, p->bCurrent ); Cudd_Ref( p->bCurrent ); // check it for bad states if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) ) { Vec_Ptr_t * vStates; assert( p->pAig->pSeqModel == NULL ); vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose ); p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose ); Vec_PtrFreeP( &vStates ); if ( !p->pPars->fSilent ) { Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAig->pSeqModel->iPo, p->pAig->pName, nIters ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } p->pPars->iFrame = nIters - 1; return 0; } // compute the next states clkTemp = Abc_Clock(); p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q ); if ( p->bNext == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; return -1; } Cudd_Ref( p->bNext ); p->timeImage += Abc_Clock() - clkTemp; // remap into current states clkTemp = Abc_Clock(); p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext ); if ( p->bNext == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during remapping next states.\n", p->pPars->TimeLimit ); Cudd_RecursiveDeref( p->dd, bAux ); p->pPars->iFrame = nIters - 1; return -1; } Cudd_Ref( p->bNext ); Cudd_RecursiveDeref( p->dd, bAux ); p->timeRemap += Abc_Clock() - clkTemp; // collect statistics if ( p->pPars->fVerbose ) { nBddSizeFr = Cudd_DagSize( p->bCurrent ); nBddSizeTo = Cudd_DagSize( bAux ); nBddSizeTo2 = Cudd_DagSize( p->bNext ); } Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL; // derive new states p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) ); if ( p->bCurrent == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; return -1; } Cudd_Ref( p->bCurrent ); Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL; if ( Cudd_IsConstant(p->bCurrent) ) break; /* // reduce BDD size using constrain // Cudd_bddRestrict p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) ); Cudd_Ref( p->bCurrent ); printf( "Before = %d. After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) ); Cudd_RecursiveDeref( p->dd, bAux ); */ // add to the reached set p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent ); if ( p->bReached == NULL ) { if ( !p->pPars->fSilent ) printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); p->pPars->iFrame = nIters - 1; Cudd_RecursiveDeref( p->dd, bAux ); return -1; } Cudd_Ref( p->bReached ); Cudd_RecursiveDeref( p->dd, bAux ); // report the results if ( p->pPars->fVerbose ) { printf( "I =%5d : ", nIters ); printf( "Fr =%7d ", nBddSizeFr ); printf( "ImNs =%7d ", nBddSizeTo ); printf( "ImCs =%7d ", nBddSizeTo2 ); printf( "Rea =%7d ", Cudd_DagSize(p->bReached) ); printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); Abc_PrintTime( 1, "T", Abc_Clock() - clkIter ); } /* if ( pPars->fVerbose ) { double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) ); // Extra_bddPrint( p->dd, bReached );printf( "\n" ); printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); fflush( stdout ); } */ if ( nIters == p->pPars->nIterMax - 1 ) { if ( !p->pPars->fSilent ) printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); p->pPars->iFrame = nIters; return -1; } } // report the stats if ( p->pPars->fVerbose ) { double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) ); if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) ) printf( "Reachability analysis completed after %d frames.\n", nIters ); else printf( "Reachability analysis is stopped after %d frames.\n", nIters ); printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); fflush( stdout ); } if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) ) { if ( !p->pPars->fSilent ) printf( "Verified only for states reachable in %d frames. ", nIters ); p->pPars->iFrame = p->pPars->nIterMax; return -1; // undecided } // report if ( !p->pPars->fSilent ) printf( "The miter is proved unreachable after %d iterations. ", nIters ); if ( !p->pPars->fSilent ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); p->pPars->iFrame = nIters - 1; return 1; // unreachable } /**Function************************************************************* Synopsis [Reorders BDDs in the working manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose ) { abctime clk = Abc_Clock(); if ( fVerbose ) Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); if ( fVerbose ) Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); if ( fTwice ) { Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); if ( fVerbose ) Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); } if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) { Llb_Mnx_t * p; p = ABC_CALLOC( Llb_Mnx_t, 1 ); p->pAig = pAig; p->pPars = pPars; // compute time to stop p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; if ( pPars->fCluster ) { // Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose ); // Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose ); // set the stop time parameter p->dd->TimeStop = p->pPars->TimeTarget; } else { // p->vOrder = Llb_Nonlin4CreateOrderSimple( pAig ); p->vOrder = Llb_Nonlin4CreateOrder( pAig ); p->dd = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); Cudd_SetMaxGrowth( p->dd, 1.05 ); // set the stop time parameter p->dd->TimeStop = p->pPars->TimeTarget; p->vRoots = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder ); } Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder ); p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward ); p->vRings = Vec_PtrAlloc( 100 ); if ( pPars->fReorder ) Llb_Nonlin4Reorder( p->dd, 0, 1 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MnxStop( Llb_Mnx_t * p ) { DdNode * bTemp; int i; if ( p->pPars->fVerbose ) { p->timeReo = Cudd_ReadReorderingTime(p->dd); p->timeOther = p->timeTotal - p->timeImage - p->timeRemap; ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); ABC_PRTP( "Remap ", p->timeRemap, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); } // remove BDDs if ( p->bBad ) Cudd_RecursiveDeref( p->dd, p->bBad ); if ( p->bReached ) Cudd_RecursiveDeref( p->dd, p->bReached ); if ( p->bCurrent ) Cudd_RecursiveDeref( p->dd, p->bCurrent ); if ( p->bNext ) Cudd_RecursiveDeref( p->dd, p->bNext ); if ( p->vRings ) Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) Cudd_RecursiveDeref( p->dd, bTemp ); if ( p->vRoots ) Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i ) Cudd_RecursiveDeref( p->dd, bTemp ); // remove arrays Vec_PtrFreeP( &p->vRings ); Vec_PtrFreeP( &p->vRoots ); //Cudd_PrintInfo( p->dd, stdout ); Extra_StopManager( p->dd ); Vec_IntFreeP( &p->vOrder ); Vec_IntFreeP( &p->vVars2Q ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p ) { Aig_Obj_t * pObj; int i, Counter0 = 0, Counter1 = 0; Saig_ManForEachLi( p->pAig, pObj, i ) if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) ) { if ( Aig_ObjFaninC0(pObj) ) Counter0++; else Counter1++; } printf( "Total = %d. Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 ); } /**Function************************************************************* Synopsis [Finds balanced cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) { Llb_Mnx_t * pMnn; int RetValue = -1; if ( pPars->fVerbose ) Aig_ManPrintStats( pAig ); if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) ) { printf( "The number of objects is more than 2^15. Clustering cannot be used.\n" ); return RetValue; } { abctime clk = Abc_Clock(); pMnn = Llb_MnxStart( pAig, pPars ); //Llb_MnxCheckNextStateVars( pMnn ); if ( !pPars->fSkipReach ) RetValue = Llb_Nonlin4Reachability( pMnn ); pMnn->timeTotal = Abc_Clock() - clk; Llb_MnxStop( pMnn ); } return RetValue; } /**Function************************************************************* Synopsis [Takes an AIG and returns an AIG representing reachable states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Llb_ReachableStates( Aig_Man_t * pAig ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Vec_Int_t * vPermute; Vec_Ptr_t * vNames; Gia_ParLlb_t Pars, * pPars = &Pars; DdManager * dd; DdNode * bReached; Llb_Mnx_t * pMnn; Abc_Ntk_t * pNtk, * pNtkMuxes; Aig_Obj_t * pObj; int i, RetValue; abctime clk = Abc_Clock(); // create parameters Llb_ManSetDefaultParams( pPars ); pPars->fSkipOutCheck = 1; pPars->fCluster = 0; pPars->fReorder = 0; pPars->fSilent = 1; pPars->nBddMax = 100; pPars->nClusterMax = 500; // run reachability pMnn = Llb_MnxStart( pAig, pPars ); RetValue = Llb_Nonlin4Reachability( pMnn ); assert( RetValue == 1 ); // print BDD // Extra_bddPrint( pMnn->dd, pMnn->bReached ); // Extra_bddPrintSupport( pMnn->dd, pMnn->bReached ); // printf( "\n" ); // collect flop output variables vPermute = Vec_IntStartFull( Cudd_ReadSize(pMnn->dd) ); Saig_ManForEachLo( pAig, pObj, i ) Vec_IntWriteEntry( vPermute, Llb_ObjBddVar(pMnn->vOrder, pObj), i ); // transfer the reached state BDD into the new manager dd = Cudd_Init( Saig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); bReached = Extra_TransferPermute( pMnn->dd, dd, pMnn->bReached, Vec_IntArray(vPermute) ); Cudd_Ref( bReached ); Vec_IntFree( vPermute ); assert( Cudd_ReadSize(dd) == Saig_ManRegNum(pAig) ); // quit reachability engine pMnn->timeTotal = Abc_Clock() - clk; Llb_MnxStop( pMnn ); // derive the network vNames = Abc_NodeGetFakeNames( Saig_ManRegNum(pAig) ); pNtk = Abc_NtkDeriveFromBdd( dd, bReached, "reached", vNames ); Abc_NodeFreeNames( vNames ); Cudd_RecursiveDeref( dd, bReached ); Cudd_Quit( dd ); // convert pNtkMuxes = Abc_NtkBddToMuxes( pNtk ); Abc_NtkDelete( pNtk ); pNtk = Abc_NtkStrash( pNtkMuxes, 0, 1, 0 ); Abc_NtkDelete( pNtkMuxes ); pAig = Abc_NtkToDar( pNtk, 0, 0 ); Abc_NtkDelete( pNtk ); return pAig; } Gia_Man_t * Llb_ReachableStatesGia( Gia_Man_t * p ) { Gia_Man_t * pNew; Aig_Man_t * pAig, * pReached; pAig = Gia_ManToAigSimple( p ); pReached = Llb_ReachableStates( pAig ); Aig_ManStop( pAig ); pNew = Gia_ManFromAigSimple( pReached ); Aig_ManStop( pReached ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llb4Sweep.c000066400000000000000000000456651300674244400233630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llb2Sweep.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD based reachability.] Synopsis [Non-linear quantification scheduling.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "llbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find good static variable ordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll ) { Aig_Obj_t * pFanin0, * pFanin1; if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent( pAig, pObj ); assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); if ( Aig_ObjIsCi(pObj) ) { Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); return; } // try fanins with higher level first pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); // if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) if ( pFanin0->Level > pFanin1->Level ) { Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); } else { Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); } if ( fSaveAll || pObj->fMarkA ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); } /**Function************************************************************* Synopsis [Find good static variable ordering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll ) { Vec_Int_t * vOrder; Aig_Obj_t * pObj; int i, Counter = 0; // collect nodes in the order vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); Aig_ManIncrementTravId( pAig ); Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); Aig_ManForEachCo( pAig, pObj, i ) { Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll ); } Aig_ManForEachCi( pAig, pObj, i ) if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); // assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes if ( pCounter ) *pCounter = Counter - Aig_ManCiNum(pAig) - Aig_ManCoNum(pAig); return vOrder; } /**Function************************************************************* Synopsis [Performs BDD sweep on the netlist.] Description [Returns AIG with internal cut points labeled with fMarkA.] SideEffects [] SeeAlso [] ***********************************************************************/ int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose ) { DdManager * dd; DdNode * bFunc0, * bFunc1, * bFunc; Aig_Obj_t * pObj; int i, Counter = 0, Counter1 = 0; dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // assign elementary variables Aig_ManCleanData( pAig ); Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); // sweep internal nodes Aig_ManForEachNode( pAig, pObj, i ) { /* if ( pObj->nRefs >= 4 ) { bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( bFunc ); pObj->pData = bFunc; Counter1++; continue; } */ bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); if ( Cudd_DagSize(bFunc) > nBddLimit ) { // if ( fVerbose ) // printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) ); // add cutpoint at a larger one Cudd_RecursiveDeref( dd, bFunc ); if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) ) { Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData ); bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) ); Aig_ObjFanin0(pObj)->pData = bFunc; Cudd_Ref( bFunc ); Aig_ObjFanin0(pObj)->fMarkA = 1; // if ( fVerbose ) // printf( "Ref =%3d ", Aig_ObjFanin0(pObj)->nRefs ); } else { Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData ); bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) ); Aig_ObjFanin1(pObj)->pData = bFunc; Cudd_Ref( bFunc ); Aig_ObjFanin1(pObj)->fMarkA = 1; // if ( fVerbose ) // printf( "Ref =%3d ", Aig_ObjFanin1(pObj)->nRefs ); } // perform new operation bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); // assert( Cudd_DagSize(bFunc) <= nBddLimit ); // if ( fVerbose ) // printf( "End =%5d.\n", Cudd_DagSize(bFunc) ); Counter++; } pObj->pData = bFunc; //printf( "%d ", Cudd_DagSize(bFunc) ); } //printf( "\n" ); // clean up Aig_ManForEachNode( pAig, pObj, i ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); Extra_StopManager( dd ); // Aig_ManCleanMarkA( pAig ); if ( fVerbose ) printf( "Added %d cut points. Used %d high fanout points.\n", Counter, Counter1 ); return Counter + Counter1; } /**Function************************************************************* Synopsis [Derives BDDs for the partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) { DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; if ( Aig_ObjIsConst1(pObj) ) return Cudd_ReadOne(dd); if ( Aig_ObjIsCi(pObj) ) return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); if ( pObj->pData ) return (DdNode *)pObj->pData; if ( Aig_ObjIsCo(pObj) ) { bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); Vec_PtrPush( vRoots, bPart ); return NULL; } bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) { vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); Vec_PtrPush( vRoots, bPart ); Cudd_RecursiveDeref( dd, bBdd ); bBdd = vVar; Cudd_Ref( vVar ); } pObj->pData = bBdd; return bBdd; } /**Function************************************************************* Synopsis [Derives BDDs for the partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition ) { Vec_Ptr_t * vRoots; Aig_Obj_t * pObj; int i; Aig_ManCleanData( pAig ); vRoots = Vec_PtrAlloc( 100 ); if ( fTransition ) { Saig_ManForEachLi( pAig, pObj, i ) Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); } else { Saig_ManForEachPo( pAig, pObj, i ) Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); } Aig_ManForEachNode( pAig, pObj, i ) if ( pObj->pData ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); return vRoots; } /**Function************************************************************* Synopsis [Get bad state monitor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd ) { Aig_Obj_t * pObj; DdNode * bRes, * bVar, * bTemp; int i; abctime TimeStop; TimeStop = dd->TimeStop; dd->TimeStop = 0; bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); Saig_ManForEachPo( pAig, pObj, i ) { bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bRes ); dd->TimeStop = TimeStop; return Cudd_Not(bRes); } /**Function************************************************************* Synopsis [Creates quantifiable variables for both types of traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis ) { Vec_Int_t * vVars2Q; Aig_Obj_t * pObj; int i; vVars2Q = Vec_IntAlloc( 0 ); Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 ); // add flop outputs Saig_ManForEachLo( pAig, pObj, i ) Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); // add flop inputs if ( fAddLis ) Saig_ManForEachLi( pAig, pObj, i ) Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); return vVars2Q; } /**Function************************************************************* Synopsis [Multiply every partition by the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts ) { DdNode * bFunc; int i; Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) Cudd_RecursiveDeref( dd, bFunc ); Vec_PtrFree( vParts ); } /**Function************************************************************* Synopsis [Multiply every partition by the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs ) { DdNode * bFunc; int i; printf( "(%d) ", Vec_PtrSize(vFuncs) ); Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) printf( "%d ", Cudd_DagSize(bFunc) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Computes bad states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars ) { DdManager * dd; Vec_Ptr_t * vParts; Vec_Int_t * vVars2Q; DdNode * bMonitor, * bImage; // get quantifiable variables vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 ); // start BDD manager and create partitions dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 ); //printf( "Outputs: " ); //Llb_Nonlin4SweepPrint( vParts ); // compute image of the partitions bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd ); Cudd_Ref( bMonitor ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q ); Cudd_Ref( bImage ); Cudd_RecursiveDeref( dd, bMonitor ); Llb_Nonlin4SweepDeref( dd, vParts ); Vec_IntFree( vVars2Q ); // save image and return dd->bFunc = bImage; return dd; } /**Function************************************************************* Synopsis [Computes clusters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose ) { DdManager * dd; Vec_Ptr_t * vParts; Vec_Int_t * vVars2Q; // get quantifiable variables vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 ); // start BDD manager and create partitions dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 ); //printf( "Transitions: " ); //Llb_Nonlin4SweepPrint( vParts ); // compute image of the partitions Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp ); Llb_Nonlin4SweepDeref( dd, vParts ); // *pvGroups = vParts; if ( fVerbose ) { printf( "Groups: " ); Llb_Nonlin4SweepPrint( *pvGroups ); } Vec_IntFree( vVars2Q ); return dd; } /**Function************************************************************* Synopsis [Creates quantifiable variables for both types of traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose ) { Aig_Obj_t * pObj; int i, * pSupp; int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); Aig_ManForEachObj( pAig, pObj, i ) { if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) continue; // remove variables that do not participate if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) { if ( Aig_ObjIsNode(pObj) ) Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); continue; } nSuppAll++; if ( Saig_ObjIsPi(pAig, pObj) ) nSuppPi++; else if ( Saig_ObjIsLo(pAig, pObj) ) nSuppLo++; else if ( Saig_ObjIsPo(pAig, pObj) ) nSuppPo++; else if ( Saig_ObjIsLi(pAig, pObj) ) nSuppLi++; else nSuppAnd++; } ABC_FREE( pSupp ); if ( fVerbose ) { printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); printf( "Variables: all =%4d ", nSuppAll ); printf( "pi =%4d ", nSuppPi ); printf( "po =%4d ", nSuppPo ); printf( "lo =%4d ", nSuppLo ); printf( "li =%4d ", nSuppLi ); printf( "and =%4d", nSuppAnd ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Performs BDD sweep on the netlist.] Description [Returns BDD manager, ordering, clusters, and bad states inside dd->bFunc.] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ) { DdManager * ddBad, * ddWork; Vec_Ptr_t * vGroups; Vec_Int_t * vOrder; int Counter, nCutPoints; // get the original ordering Aig_ManCleanMarkA( pAig ); vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 ); assert( Counter == Aig_ManNodeNum(pAig) ); // mark the nodes nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose ); Vec_IntFree( vOrder ); // get better ordering vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 ); assert( Counter == nCutPoints ); Aig_ManCleanMarkA( pAig ); // compute the BAD states ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig) ); // compute the clusters ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig), &vGroups, nClusterMax, fVerbose ); // transfer the result from the Bad manager //printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) ); ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc ); Cudd_Ref( ddWork->bFunc ); Cudd_RecursiveDeref( ddBad, ddBad->bFunc ); ddBad->bFunc = NULL; Extra_StopManager( ddBad ); // update ordering to exclude quantified variables //printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) ); Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose ); // return the result *pdd = ddWork; *pvOrder = vOrder; *pvGroups = vGroups; } /**Function************************************************************* Synopsis [Performs BDD sweep on the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig ) { DdManager * dd; Vec_Int_t * vOrder; Vec_Ptr_t * vGroups; Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 ); Llb_Nonlin4SweepDeref( dd, vGroups ); Cudd_RecursiveDeref( dd, dd->bFunc ); Extra_StopManager( dd ); Vec_IntFree( vOrder ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/llbInt.h000066400000000000000000000271341300674244400227420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [llbInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [BDD-based reachability.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 8, 2010.] Revision [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__llb__llbInt_h #define ABC__aig__llb__llbInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include "proof/ssw/ssw.h" #include "llb.h" #include "bdd/extrab/extraBdd.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Llb_Man_t_ Llb_Man_t; typedef struct Llb_Mtr_t_ Llb_Mtr_t; typedef struct Llb_Grp_t_ Llb_Grp_t; struct Llb_Man_t_ { Gia_ParLlb_t * pPars; // parameters Aig_Man_t * pAigGlo; // initial AIG manager (owned by the caller) Aig_Man_t * pAig; // derived AIG manager (created in this package) DdManager * dd; // BDD manager DdManager * ddG; // BDD manager DdManager * ddR; // BDD manager Vec_Int_t * vObj2Var; // mapping AIG ObjId into BDD var index Vec_Int_t * vVar2Obj; // mapping BDD var index into AIG ObjId Vec_Ptr_t * vGroups; // group Id into group pointer Llb_Mtr_t * pMatrix; // dependency matrix // image computation Vec_Ptr_t * vRings; // onion rings Vec_Int_t * vVarBegs; // the first group where the var appears Vec_Int_t * vVarEnds; // the last group where the var appears // variable mapping Vec_Int_t * vNs2Glo; // next state variables into global variables Vec_Int_t * vCs2Glo; // next state variables into global variables Vec_Int_t * vGlo2Cs; // global variables into current state variables Vec_Int_t * vGlo2Ns; // global variables into current state variables // flow computation // Vec_Int_t * vMem; // Vec_Ptr_t * vTops; // Vec_Ptr_t * vBots; // Vec_Ptr_t * vCuts; }; struct Llb_Mtr_t_ { int nPis; // number of primary inputs int nFfs; // number of flip-flops int nRows; // number of rows int nCols; // number of columns int * pColSums; // sum of values in a column Llb_Grp_t ** pColGrps; // group structure for each col int * pRowSums; // sum of values in a row char ** pMatrix; // dependency matrix Llb_Man_t * pMan; // manager // partial product char * pProdVars; // variables in the partial product int * pProdNums; // var counts in the remaining partitions }; struct Llb_Grp_t_ { int Id; // group ID Vec_Ptr_t * vIns; // input AIG objs Vec_Ptr_t * vOuts; // output AIG objs Vec_Ptr_t * vNodes; // internal AIG objs Llb_Man_t * pMan; // manager Llb_Grp_t * pPrev; // previous group Llb_Grp_t * pNext; // next group }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== llbConstr.c ======================================================*/ extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ); extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ); /*=== llbCore.c ======================================================*/ extern int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ); /*=== llbCluster.c ======================================================*/ extern void Llb_ManCluster( Llb_Mtr_t * p ); /*=== llbDump.c ======================================================*/ extern void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ); /*=== llbFlow.c ======================================================*/ extern Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ); /*=== llbHint.c ======================================================*/ extern int Llb_ManReachabilityWithHints( Llb_Man_t * p ); extern int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ); /*=== llbMan.c =======================================================*/ extern void Llb_ManPrepareVarMap( Llb_Man_t * p ); extern Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); extern void Llb_ManStop( Llb_Man_t * p ); /*=== llbMatrix.c ====================================================*/ extern void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ); extern Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ); extern void Llb_MtrFree( Llb_Mtr_t * p ); extern void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ); extern void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ); /*=== llbPart.c ======================================================*/ extern Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ); extern void Llb_ManGroupStop( Llb_Grp_t * p ); extern void Llb_ManPrepareGroups( Llb_Man_t * pMan ); extern Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ); extern Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ); extern void Llb_ManPrepareVarLimits( Llb_Man_t * p ); /*=== llbPivot.c =====================================================*/ extern int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ); extern Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ); /*=== llbReach.c =====================================================*/ extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ); /*=== llbSched.c =====================================================*/ extern void Llb_MtrSchedule( Llb_Mtr_t * p ); /*=== llb2Bad.c ======================================================*/ extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut ); extern DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ); /*=== llb2Core.c ======================================================*/ extern DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ); extern int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ); /*=== llb2Driver.c ======================================================*/ extern Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ); extern Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ); extern Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ); extern DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ); extern DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget ); /*=== llb2Image.c ======================================================*/ extern Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ); extern void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ); extern DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget ); extern void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ); extern void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ); extern DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, abctime TimeTarget, int fBackward, int fReorder, int fVerbose ); extern DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget ); extern DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ); extern void Llb_NonlinImageQuit(); /*=== llb3Image.c =======================================================*/ extern DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder ); /*=== llb3Nonlin.c ======================================================*/ extern DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ); /*=== llb4Cex.c =======================================================*/ extern Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ); /*=== llb4Cluster.c =======================================================*/ //extern void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ); /*=== llb4Image.c =======================================================*/ extern DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ); extern Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ); /*=== llb4Map.c =========================================================*/ //extern Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ); /*=== llb4Nonlin.c ======================================================*/ //extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); /*=== llb4Sweep.c ======================================================*/ extern void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/llb/module.make000066400000000000000000000011221300674244400234560ustar00rootroot00000000000000SRC += src/bdd/llb/llb1Cluster.c \ src/bdd/llb/llb1Constr.c \ src/bdd/llb/llb1Core.c \ src/bdd/llb/llb1Group.c \ src/bdd/llb/llb1Hint.c \ src/bdd/llb/llb1Man.c \ src/bdd/llb/llb1Matrix.c \ src/bdd/llb/llb1Pivot.c \ src/bdd/llb/llb1Reach.c \ src/bdd/llb/llb1Sched.c \ src/bdd/llb/llb2Bad.c \ src/bdd/llb/llb2Core.c \ src/bdd/llb/llb2Driver.c \ src/bdd/llb/llb2Dump.c \ src/bdd/llb/llb2Flow.c \ src/bdd/llb/llb2Image.c \ src/bdd/llb/llb3Image.c \ src/bdd/llb/llb3Nonlin.c \ src/bdd/llb/llb4Cex.c \ src/bdd/llb/llb4Image.c \ src/bdd/llb/llb4Nonlin.c \ src/bdd/llb/llb4Sweep.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/mtr/000077500000000000000000000000001300674244400213675ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/mtr/module.make000066400000000000000000000000711300674244400235110ustar00rootroot00000000000000SRC += src/bdd/mtr/mtrBasic.c \ src/bdd/mtr/mtrGroup.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/mtr/mtr.h000066400000000000000000000157521300674244400223540ustar00rootroot00000000000000/**CHeaderFile***************************************************************** FileName [mtr.h] PackageName [mtr] Synopsis [Multiway-branch tree manipulation] Description [This package provides two layers of functions. Functions of the lower level manipulate multiway-branch trees, implemented according to the classical scheme whereby each node points to its first child and its previous and next siblings. These functions are collected in mtrBasic.c.

        Functions of the upper layer deal with group trees, that is the trees used by group sifting to represent the grouping of variables. These functions are collected in mtrGroup.c.] SeeAlso [The CUDD package documentation; specifically on group sifting.] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] Revision [$Id: mtr.h,v 1.14 2009/02/20 02:03:47 fabio Exp $] ******************************************************************************/ #ifndef ABC__bdd__mtr__mtr_h #define ABC__bdd__mtr__mtr_h /*---------------------------------------------------------------------------*/ /* Nested includes */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_HEADER_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ #ifndef SIZEOF_VOID_P #define SIZEOF_VOID_P 4 #endif #ifndef SIZEOF_INT #define SIZEOF_INT 4 #endif //#undef CONST //#if defined(__STDC__) || defined(__cplusplus) //#define CONST const //#else /* !(__STDC__ || __cplusplus) */ //#define CONST //#endif /* !(__STDC__ || __cplusplus) */ #if defined(__GNUC__) #define MTR_INLINE __inline__ # if (__GNUC__ >2 || __GNUC_MINOR__ >=7) # define MTR_UNUSED __attribute__ ((unused)) # else # define MTR_UNUSED # endif #else #define MTR_INLINE #define MTR_UNUSED #endif /* Flag definitions */ #define MTR_DEFAULT 0x00000000 #define MTR_TERMINAL 0x00000001 #define MTR_SOFT 0x00000002 #define MTR_FIXED 0x00000004 #define MTR_NEWNODE 0x00000008 /* MTR_MAXHIGH is defined in such a way that on 32-bit and 64-bit ** machines one can cast a value to (int) without generating a negative ** number. */ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 #define MTR_MAXHIGH (((MtrHalfWord) ~0) >> 1) #else #define MTR_MAXHIGH ((MtrHalfWord) ~0) #endif /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 typedef unsigned int MtrHalfWord; #else typedef unsigned short MtrHalfWord; #endif typedef struct MtrNode { MtrHalfWord flags; MtrHalfWord low; MtrHalfWord size; MtrHalfWord index; struct MtrNode *parent; struct MtrNode *child; struct MtrNode *elder; struct MtrNode *younger; } MtrNode; /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /* Flag manipulation macros */ #define MTR_SET(node, flag) (node->flags |= (flag)) #define MTR_RESET(node, flag) (node->flags &= ~ (flag)) #define MTR_TEST(node, flag) (node->flags & (flag)) /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Function prototypes */ /*---------------------------------------------------------------------------*/ extern MtrNode * Mtr_AllocNode (void); extern void Mtr_DeallocNode (MtrNode *node); extern MtrNode * Mtr_InitTree (void); extern void Mtr_FreeTree (MtrNode *node); extern MtrNode * Mtr_CopyTree (MtrNode *node, int expansion); extern void Mtr_MakeFirstChild (MtrNode *parent, MtrNode *child); extern void Mtr_MakeLastChild (MtrNode *parent, MtrNode *child); extern MtrNode * Mtr_CreateFirstChild (MtrNode *parent); extern MtrNode * Mtr_CreateLastChild (MtrNode *parent); extern void Mtr_MakeNextSibling (MtrNode *first, MtrNode *second); extern void Mtr_PrintTree (MtrNode *node); extern MtrNode * Mtr_InitGroupTree (int lower, int size); extern MtrNode * Mtr_MakeGroup (MtrNode *root, unsigned int low, unsigned int high, unsigned int flags); extern MtrNode * Mtr_DissolveGroup (MtrNode *group); extern MtrNode * Mtr_FindGroup (MtrNode *root, unsigned int low, unsigned int high); extern int Mtr_SwapGroups (MtrNode *first, MtrNode *second); extern void Mtr_PrintGroups (MtrNode *root, int silent); extern MtrNode * Mtr_ReadGroups (FILE *fp, int nleaves); /**AutomaticEnd***************************************************************/ ABC_NAMESPACE_HEADER_END #endif /* __MTR */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/mtr/mtrBasic.c000066400000000000000000000317401300674244400233040ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [mtrBasic.c] PackageName [mtr] Synopsis [Basic manipulation of multiway branching trees.] Description [External procedures included in this module:

        • Mtr_AllocNode()
        • Mtr_DeallocNode()
        • Mtr_InitTree()
        • Mtr_FreeTree()
        • Mtr_CopyTree()
        • Mtr_MakeFirstChild()
        • Mtr_MakeLastChild()
        • Mtr_CreateFirstChild()
        • Mtr_CreateLastChild()
        • Mtr_MakeNextSibling()
        • Mtr_PrintTree()
        ] SeeAlso [cudd package] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "mtrInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] MTR_UNUSED = "$Id: mtrBasic.c,v 1.13 2009/02/20 02:03:47 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Allocates new tree node.] Description [Allocates new tree node. Returns pointer to node.] SideEffects [None] SeeAlso [Mtr_DeallocNode] ******************************************************************************/ MtrNode * Mtr_AllocNode(void) { MtrNode *node; node = ABC_ALLOC(MtrNode,1); return node; } /* Mtr_AllocNode */ /**Function******************************************************************** Synopsis [Deallocates tree node.] Description [] SideEffects [None] SeeAlso [Mtr_AllocNode] ******************************************************************************/ void Mtr_DeallocNode( MtrNode * node /* node to be deallocated */) { ABC_FREE(node); return; } /* end of Mtr_DeallocNode */ /**Function******************************************************************** Synopsis [Initializes tree with one node.] Description [Initializes tree with one node. Returns pointer to node.] SideEffects [None] SeeAlso [Mtr_FreeTree Mtr_InitGroupTree] ******************************************************************************/ MtrNode * Mtr_InitTree(void) { MtrNode *node; node = Mtr_AllocNode(); if (node == NULL) return(NULL); node->parent = node->child = node->elder = node->younger = NULL; node->flags = 0; return(node); } /* end of Mtr_InitTree */ /**Function******************************************************************** Synopsis [Disposes of tree rooted at node.] Description [] SideEffects [None] SeeAlso [Mtr_InitTree] ******************************************************************************/ void Mtr_FreeTree( MtrNode * node) { if (node == NULL) return; if (! MTR_TEST(node,MTR_TERMINAL)) Mtr_FreeTree(node->child); Mtr_FreeTree(node->younger); Mtr_DeallocNode(node); return; } /* end of Mtr_FreeTree */ /**Function******************************************************************** Synopsis [Makes a copy of tree.] Description [Makes a copy of tree. If parameter expansion is greater than 1, it will expand the tree by that factor. It is an error for expansion to be less than 1. Returns a pointer to the copy if successful; NULL otherwise.] SideEffects [None] SeeAlso [Mtr_InitTree] ******************************************************************************/ MtrNode * Mtr_CopyTree( MtrNode * node, int expansion) { MtrNode *copy; if (node == NULL) return(NULL); if (expansion < 1) return(NULL); copy = Mtr_AllocNode(); if (copy == NULL) return(NULL); copy->parent = copy->elder = copy->child = copy->younger = NULL; if (node->child != NULL) { copy->child = Mtr_CopyTree(node->child, expansion); if (copy->child == NULL) { Mtr_DeallocNode(copy); return(NULL); } } if (node->younger != NULL) { copy->younger = Mtr_CopyTree(node->younger, expansion); if (copy->younger == NULL) { Mtr_FreeTree(copy); return(NULL); } } copy->flags = node->flags; copy->low = node->low * expansion; copy->size = node->size * expansion; copy->index = node->index * expansion; if (copy->younger) copy->younger->elder = copy; if (copy->child) { MtrNode *auxnode = copy->child; while (auxnode != NULL) { auxnode->parent = copy; auxnode = auxnode->younger; } } return(copy); } /* end of Mtr_CopyTree */ /**Function******************************************************************** Synopsis [Makes child the first child of parent.] Description [] SideEffects [None] SeeAlso [Mtr_MakeLastChild Mtr_CreateFirstChild] ******************************************************************************/ void Mtr_MakeFirstChild( MtrNode * parent, MtrNode * child) { child->parent = parent; child->younger = parent->child; child->elder = NULL; if (parent->child != NULL) { #ifdef MTR_DEBUG assert(parent->child->elder == NULL); #endif parent->child->elder = child; } parent->child = child; return; } /* end of Mtr_MakeFirstChild */ /**Function******************************************************************** Synopsis [Makes child the last child of parent.] Description [] SideEffects [None] SeeAlso [Mtr_MakeFirstChild Mtr_CreateLastChild] ******************************************************************************/ void Mtr_MakeLastChild( MtrNode * parent, MtrNode * child) { MtrNode *node; child->younger = NULL; if (parent->child == NULL) { parent->child = child; child->elder = NULL; } else { for (node = parent->child; node->younger != NULL; node = node->younger); node->younger = child; child->elder = node; } child->parent = parent; return; } /* end of Mtr_MakeLastChild */ /**Function******************************************************************** Synopsis [Creates a new node and makes it the first child of parent.] Description [Creates a new node and makes it the first child of parent. Returns pointer to new child.] SideEffects [None] SeeAlso [Mtr_MakeFirstChild Mtr_CreateLastChild] ******************************************************************************/ MtrNode * Mtr_CreateFirstChild( MtrNode * parent) { MtrNode *child; child = Mtr_AllocNode(); if (child == NULL) return(NULL); child->child = child->younger = child-> elder = NULL; child->flags = 0; Mtr_MakeFirstChild(parent,child); return(child); } /* end of Mtr_CreateFirstChild */ /**Function******************************************************************** Synopsis [Creates a new node and makes it the last child of parent.] Description [Creates a new node and makes it the last child of parent. Returns pointer to new child.] SideEffects [None] SeeAlso [Mtr_MakeLastChild Mtr_CreateFirstChild] ******************************************************************************/ MtrNode * Mtr_CreateLastChild( MtrNode * parent) { MtrNode *child; child = Mtr_AllocNode(); if (child == NULL) return(NULL); child->child = child->younger = child->elder = NULL; child->flags = 0; Mtr_MakeLastChild(parent,child); return(child); } /* end of Mtr_CreateLastChild */ /**Function******************************************************************** Synopsis [Makes second the next sibling of first.] Description [Makes second the next sibling of first. Second becomes a child of the parent of first.] SideEffects [None] SeeAlso [] ******************************************************************************/ void Mtr_MakeNextSibling( MtrNode * first, MtrNode * second) { second->younger = first->younger; if (first->younger != NULL) { first->younger->elder = second; } second->parent = first->parent; first->younger = second; second->elder = first; return; } /* end of Mtr_MakeNextSibling */ /**Function******************************************************************** Synopsis [Prints a tree, one node per line.] Description [] SideEffects [None] SeeAlso [Mtr_PrintGroups] ******************************************************************************/ void Mtr_PrintTree( MtrNode * node) { if (node == NULL) return; (void) fprintf(stdout, #if SIZEOF_VOID_P == 8 "N=0x%-8lx C=0x%-8lx Y=0x%-8lx E=0x%-8lx P=0x%-8lx F=%x L=%u S=%u\n", (unsigned long) node, (unsigned long) node->child, (unsigned long) node->younger, (unsigned long) node->elder, (unsigned long) node->parent, node->flags, node->low, node->size); #else "N=0x%-8x C=0x%-8x Y=0x%-8x E=0x%-8x P=0x%-8x F=%x L=%hu S=%hu\n", (unsigned) node, (unsigned) node->child, (unsigned) node->younger, (unsigned) node->elder, (unsigned) node->parent, node->flags, node->low, node->size); #endif if (!MTR_TEST(node,MTR_TERMINAL)) Mtr_PrintTree(node->child); Mtr_PrintTree(node->younger); return; } /* end of Mtr_PrintTree */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/mtr/mtrGroup.c000066400000000000000000000571001300674244400233550ustar00rootroot00000000000000/**CFile*********************************************************************** FileName [mtrGroup.c] PackageName [mtr] Synopsis [Functions to support group specification for reordering.] Description [External procedures included in this module:
        • Mtr_InitGroupTree()
        • Mtr_MakeGroup()
        • Mtr_DissolveGroup()
        • Mtr_FindGroup()
        • Mtr_SwapGroups()
        • Mtr_PrintGroups()
        • Mtr_ReadGroups()
        Static procedures included in this module:
        • mtrShiftHL
        ] SeeAlso [cudd package] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] ******************************************************************************/ #include "misc/util/util_hack.h" #include "mtrInt.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ #ifndef lint static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.18 2009/02/20 02:03:47 fabio Exp $"; #endif /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int mtrShiftHL (MtrNode *node, int shift); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Allocate new tree.] Description [Allocate new tree with one node, whose low and size fields are specified by the lower and size parameters. Returns pointer to tree root.] SideEffects [None] SeeAlso [Mtr_InitTree Mtr_FreeTree] ******************************************************************************/ MtrNode * Mtr_InitGroupTree( int lower, int size) { MtrNode *root; root = Mtr_InitTree(); if (root == NULL) return(NULL); root->flags = MTR_DEFAULT; root->low = lower; root->size = size; return(root); } /* end of Mtr_InitGroupTree */ /**Function******************************************************************** Synopsis [Makes a new group with size leaves starting at low.] Description [Makes a new group with size leaves starting at low. If the new group intersects an existing group, it must either contain it or be contained by it. This procedure relies on the low and size fields of each node. It also assumes that the children of each node are sorted in order of increasing low. In case of a valid request, the flags of the new group are set to the value passed in `flags.' This can also be used to change the flags of an existing group. Returns the pointer to the root of the new group upon successful termination; NULL otherwise. If the group already exists, the pointer to its root is returned.] SideEffects [None] SeeAlso [Mtr_DissolveGroup Mtr_ReadGroups Mtr_FindGroup] ******************************************************************************/ MtrNode * Mtr_MakeGroup( MtrNode * root /* root of the group tree */, unsigned int low /* lower bound of the group */, unsigned int size /* upper bound of the group */, unsigned int flags /* flags for the new group */) { MtrNode *node, *first, *last, *previous, *newn; /* Sanity check. */ if (size == 0) return(NULL); /* Check whether current group includes new group. This check is ** necessary at the top-level call. In the subsequent calls it is ** redundant. */ if (low < (unsigned int) root->low || low + size > (unsigned int) (root->low + root->size)) return(NULL); /* Trying to create an existing group has the effect of updating ** the flags. */ if (root->size == size && root->low == low) { root->flags = flags; return(root); } /* At this point we know that the new group is properly contained ** in the group of root. We have two possible cases here: - root ** is a terminal node; - root has children. */ /* Root has no children: create a new group. */ if (root->child == NULL) { newn = Mtr_AllocNode(); if (newn == NULL) return(NULL); /* out of memory */ newn->low = low; newn->size = size; newn->flags = flags; newn->parent = root; newn->elder = newn->younger = newn->child = NULL; root->child = newn; return(newn); } /* Root has children: Find all chidren of root that are included ** in the new group. If the group of any child entirely contains ** the new group, call Mtr_MakeGroup recursively. */ previous = NULL; first = root->child; /* guaranteed to be non-NULL */ while (first != NULL && low >= (unsigned int) (first->low + first->size)) { previous = first; first = first->younger; } if (first == NULL) { /* We have scanned the entire list and we need to append a new ** child at the end of it. Previous points to the last child ** of root. */ newn = Mtr_AllocNode(); if (newn == NULL) return(NULL); /* out of memory */ newn->low = low; newn->size = size; newn->flags = flags; newn->parent = root; newn->elder = previous; previous->younger = newn; newn->younger = newn->child = NULL; return(newn); } /* Here first is non-NULL and low < first->low + first->size. */ if (low >= (unsigned int) first->low && low + size <= (unsigned int) (first->low + first->size)) { /* The new group is contained in the group of first. */ newn = Mtr_MakeGroup(first, low, size, flags); return(newn); } else if (low + size <= first->low) { /* The new group is entirely contained in the gap between ** previous and first. */ newn = Mtr_AllocNode(); if (newn == NULL) return(NULL); /* out of memory */ newn->low = low; newn->size = size; newn->flags = flags; newn->child = NULL; newn->parent = root; newn->elder = previous; newn->younger = first; first->elder = newn; if (previous != NULL) { previous->younger = newn; } else { root->child = newn; } return(newn); } else if (low < (unsigned int) first->low && low + size < (unsigned int) (first->low + first->size)) { /* Trying to cut an existing group: not allowed. */ return(NULL); } else if (low > first->low) { /* The new group neither is contained in the group of first ** (this was tested above) nor contains it. It is therefore ** trying to cut an existing group: not allowed. */ return(NULL); } /* First holds the pointer to the first child contained in the new ** group. Here low <= first->low and low + size >= first->low + ** first->size. One of the two inequalities is strict. */ last = first->younger; while (last != NULL && (unsigned int) (last->low + last->size) < low + size) { last = last->younger; } if (last == NULL) { /* All the chilren of root from first onward become children ** of the new group. */ newn = Mtr_AllocNode(); if (newn == NULL) return(NULL); /* out of memory */ newn->low = low; newn->size = size; newn->flags = flags; newn->child = first; newn->parent = root; newn->elder = previous; newn->younger = NULL; first->elder = NULL; if (previous != NULL) { previous->younger = newn; } else { root->child = newn; } last = first; while (last != NULL) { last->parent = newn; last = last->younger; } return(newn); } /* Here last != NULL and low + size <= last->low + last->size. */ if (low + size - 1 >= (unsigned int) last->low && low + size < (unsigned int) (last->low + last->size)) { /* Trying to cut an existing group: not allowed. */ return(NULL); } /* First and last point to the first and last of the children of ** root that are included in the new group. Allocate a new node ** and make all children of root between first and last chidren of ** the new node. Previous points to the child of root immediately ** preceeding first. If it is NULL, then first is the first child ** of root. */ newn = Mtr_AllocNode(); if (newn == NULL) return(NULL); /* out of memory */ newn->low = low; newn->size = size; newn->flags = flags; newn->child = first; newn->parent = root; if (previous == NULL) { root->child = newn; } else { previous->younger = newn; } newn->elder = previous; newn->younger = last->younger; if (last->younger != NULL) { last->younger->elder = newn; } last->younger = NULL; first->elder = NULL; for (node = first; node != NULL; node = node->younger) { node->parent = newn; } return(newn); } /* end of Mtr_MakeGroup */ /**Function******************************************************************** Synopsis [Merges the children of `group' with the children of its parent.] Description [Merges the children of `group' with the children of its parent. Disposes of the node pointed by group. If group is the root of the group tree, this procedure leaves the tree unchanged. Returns the pointer to the parent of `group' upon successful termination; NULL otherwise.] SideEffects [None] SeeAlso [Mtr_MakeGroup] ******************************************************************************/ MtrNode * Mtr_DissolveGroup( MtrNode * group /* group to be dissolved */) { MtrNode *parent; MtrNode *last; parent = group->parent; if (parent == NULL) return(NULL); if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL); /* Make all children of group children of its parent, and make ** last point to the last child of group. */ for (last = group->child; last->younger != NULL; last = last->younger) { last->parent = parent; } last->parent = parent; last->younger = group->younger; if (group->younger != NULL) { group->younger->elder = last; } group->child->elder = group->elder; if (group == parent->child) { parent->child = group->child; } else { group->elder->younger = group->child; } Mtr_DeallocNode(group); return(parent); } /* end of Mtr_DissolveGroup */ /**Function******************************************************************** Synopsis [Finds a group with size leaves starting at low, if it exists.] Description [Finds a group with size leaves starting at low, if it exists. This procedure relies on the low and size fields of each node. It also assumes that the children of each node are sorted in order of increasing low. Returns the pointer to the root of the group upon successful termination; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ MtrNode * Mtr_FindGroup( MtrNode * root /* root of the group tree */, unsigned int low /* lower bound of the group */, unsigned int size /* upper bound of the group */) { MtrNode *node; #ifdef MTR_DEBUG /* We cannot have a non-empty proper subgroup of a singleton set. */ assert(!MTR_TEST(root,MTR_TERMINAL)); #endif /* Sanity check. */ if (size < 1) return(NULL); /* Check whether current group includes the group sought. This ** check is necessary at the top-level call. In the subsequent ** calls it is redundant. */ if (low < (unsigned int) root->low || low + size > (unsigned int) (root->low + root->size)) return(NULL); if (root->size == size && root->low == low) return(root); if (root->child == NULL) return(NULL); /* Find all chidren of root that are included in the new group. If ** the group of any child entirely contains the new group, call ** Mtr_MakeGroup recursively. */ node = root->child; while (low >= (unsigned int) (node->low + node->size)) { node = node->younger; } if (low + size <= (unsigned int) (node->low + node->size)) { /* The group is contained in the group of node. */ node = Mtr_FindGroup(node, low, size); return(node); } else { return(NULL); } } /* end of Mtr_FindGroup */ /**Function******************************************************************** Synopsis [Swaps two children of a tree node.] Description [Swaps two children of a tree node. Adjusts the high and low fields of the two nodes and their descendants. The two children must be adjacent. However, first may be the younger sibling of second. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Mtr_SwapGroups( MtrNode * first /* first node to be swapped */, MtrNode * second /* second node to be swapped */) { MtrNode *node; MtrNode *parent; int sizeFirst; int sizeSecond; if (second->younger == first) { /* make first first */ node = first; first = second; second = node; } else if (first->younger != second) { /* non-adjacent */ return(0); } sizeFirst = first->size; sizeSecond = second->size; /* Swap the two nodes. */ parent = first->parent; if (parent == NULL || second->parent != parent) return(0); if (parent->child == first) { parent->child = second; } else { /* first->elder != NULL */ first->elder->younger = second; } if (second->younger != NULL) { second->younger->elder = first; } first->younger = second->younger; second->elder = first->elder; first->elder = second; second->younger = first; /* Adjust the high and low fields. */ if (!mtrShiftHL(first,sizeSecond)) return(0); if (!mtrShiftHL(second,-sizeFirst)) return(0); return(1); } /* end of Mtr_SwapGroups */ /**Function******************************************************************** Synopsis [Prints the groups as a parenthesized list.] Description [Prints the groups as a parenthesized list. After each group, the group's flag are printed, preceded by a `|'. For each flag (except MTR_TERMINAL) a character is printed.
        • F: MTR_FIXED
        • N: MTR_NEWNODE
        • S: MTR_SOFT
        The second argument, silent, if different from 0, causes Mtr_PrintGroups to only check the syntax of the group tree. ] SideEffects [None] SeeAlso [Mtr_PrintTree] ******************************************************************************/ void Mtr_PrintGroups( MtrNode * root /* root of the group tree */, int silent /* flag to check tree syntax only */) { MtrNode *node; assert(root != NULL); assert(root->younger == NULL || root->younger->elder == root); assert(root->elder == NULL || root->elder->younger == root); #if SIZEOF_VOID_P == 8 if (!silent) (void) printf("(%u",root->low); #else if (!silent) (void) printf("(%hu",root->low); #endif if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { if (!silent) (void) printf(","); } else { node = root->child; while (node != NULL) { assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); assert(node->parent == root); Mtr_PrintGroups(node,silent); node = node->younger; } } if (!silent) { #if SIZEOF_VOID_P == 8 (void) printf("%u", root->low + root->size - 1); #else (void) printf("%hu", root->low + root->size - 1); #endif if (root->flags != MTR_DEFAULT) { (void) printf("|"); if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); } (void) printf(")"); if (root->parent == NULL) (void) printf("\n"); } assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); return; } /* end of Mtr_PrintGroups */ /**Function******************************************************************** Synopsis [Reads groups from a file and creates a group tree.] Description [Reads groups from a file and creates a group tree. Each group is specified by three fields: low size flags. Low and size are (short) integers. Flags is a string composed of the following characters (with associated translation):
        • D: MTR_DEFAULT
        • F: MTR_FIXED
        • N: MTR_NEWNODE
        • S: MTR_SOFT
        • T: MTR_TERMINAL
        Normally, the only flags that are needed are D and F. Groups and fields are separated by white space (spaces, tabs, and newlines). Returns a pointer to the group tree if successful; NULL otherwise.] SideEffects [None] SeeAlso [Mtr_InitGroupTree Mtr_MakeGroup] ******************************************************************************/ MtrNode * Mtr_ReadGroups( FILE * fp /* file pointer */, int nleaves /* number of leaves of the new tree */) { int low; int size; int err; unsigned int flags; MtrNode *root; MtrNode *node; char attrib[8*sizeof(unsigned int)+1]; char *c; root = Mtr_InitGroupTree(0,nleaves); if (root == NULL) return NULL; while (! feof(fp)) { /* Read a triple and check for consistency. */ err = fscanf(fp, "%d %d %s", &low, &size, attrib); if (err == EOF) { break; } else if (err != 3) { Mtr_FreeTree(root); return(NULL); } else if (low < 0 || low+size > nleaves || size < 1) { Mtr_FreeTree(root); return(NULL); } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) { /* Not enough bits in the flags word to store these many ** attributes. */ Mtr_FreeTree(root); return(NULL); } /* Parse the flag string. Currently all flags are permitted, ** to make debugging easier. Normally, specifying NEWNODE ** wouldn't be allowed. */ flags = MTR_DEFAULT; for (c=attrib; *c != 0; c++) { switch (*c) { case 'D': break; case 'F': flags |= MTR_FIXED; break; case 'N': flags |= MTR_NEWNODE; break; case 'S': flags |= MTR_SOFT; break; case 'T': flags |= MTR_TERMINAL; break; default: return NULL; } } node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size, flags); if (node == NULL) { Mtr_FreeTree(root); return(NULL); } } return(root); } /* end of Mtr_ReadGroups */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Adjusts the low fields of a node and its descendants.] Description [Adjusts the low fields of a node and its descendants. Adds shift to low of each node. Checks that no out-of-bounds values result. Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static int mtrShiftHL( MtrNode * node /* group tree node */, int shift /* amount by which low should be changed */) { MtrNode *auxnode; int low; low = (int) node->low; low += shift; if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0); node->low = (MtrHalfWord) low; if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) { auxnode = node->child; do { if (!mtrShiftHL(auxnode,shift)) return(0); auxnode = auxnode->younger; } while (auxnode != NULL); } return(1); } /* end of mtrShiftHL */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/mtr/mtrInt.h000066400000000000000000000077031300674244400230240ustar00rootroot00000000000000/**CHeaderFile***************************************************************** FileName [mtrInt.h] PackageName [mtr] Synopsis [Internal data structures of the mtr package] Description [In this package all definitions are external.] SeeAlso [] Author [Fabio Somenzi] Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.] Revision [$Id: mtrInt.h,v 1.2 2004/08/13 18:15:12 fabio Exp $] ******************************************************************************/ #ifndef ABC__bdd__mtr__mtrInt_h #define ABC__bdd__mtr__mtrInt_h #include "mtr.h" /*---------------------------------------------------------------------------*/ /* Nested includes */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_HEADER_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Function prototypes */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_HEADER_END /**AutomaticEnd***************************************************************/ #endif /* _MTRINT */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/000077500000000000000000000000001300674244400213525ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/module.make000066400000000000000000000003361300674244400235000ustar00rootroot00000000000000SRC += src/bdd/reo/reoApi.c \ src/bdd/reo/reoCore.c \ src/bdd/reo/reoProfile.c \ src/bdd/reo/reoShuffle.c \ src/bdd/reo/reoSift.c \ src/bdd/reo/reoSwap.c \ src/bdd/reo/reoTransfer.c \ src/bdd/reo/reoUnits.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reo.h000066400000000000000000000243351300674244400223170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reo.h] PackageName [REO: A specialized DD reordering engine.] Synopsis [External and internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reo.h,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__bdd__reo__reo_h #define ABC__bdd__reo__reo_h #include #include #include "bdd/extrab/extraBdd.h" //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START // reordering parameters #define REO_REORDER_LIMIT 1.15 // determines the quality/runtime trade-off #define REO_QUAL_PAR 3 // the quality [1 = simple lower bound, 2 = strict, larger = heuristic] // internal parameters #define REO_CONST_LEVEL 30000 // the number of the constant level #define REO_TOPREF_UNDEF 30000 // the undefined top reference #define REO_CHUNK_SIZE 5000 // the number of units allocated at one time #define REO_COST_EPSILON 0.0000001 // difference in cost large enough so that it counted as an error #define REO_HIGH_VALUE 10000000 // a large value used to initialize some variables // interface parameters #define REO_ENABLE 1 // the value of the enable flag #define REO_DISABLE 0 // the value of the disable flag // the types of minimization currently supported typedef enum { REO_MINIMIZE_NODES, REO_MINIMIZE_WIDTH, // may not work for BDDs with complemented edges REO_MINIMIZE_APL } reo_min_type; //////////////////////////////////////////////////////////////////////// /// DATA STRUCTURES /// //////////////////////////////////////////////////////////////////////// typedef struct _reo_unit reo_unit; // the unit representing one DD node during reordering typedef struct _reo_plane reo_plane; // the set of nodes on one level typedef struct _reo_hash reo_hash; // the entry in the hash table typedef struct _reo_man reo_man; // the reordering manager typedef struct _reo_test reo_test; // struct _reo_unit { short lev; // the level of this node at the beginning short TopRef; // the top level from which this node is refed (used to update BDD width) short TopRefNew; // the new top level from which this node is refed (used to update BDD width) short n; // the number of incoming edges (similar to ref count in the BDD) int Sign; // the signature reo_unit * pE; // the pointer to the "else" branch reo_unit * pT; // the pointer to the "then" branch reo_unit * Next; // the link to the next one in the list double Weight; // the probability of traversing this node }; struct _reo_plane { int fSifted; // to mark the sifted variables int statsNodes; // the number of nodes in the current level int statsWidth; // the width on the current level double statsApl; // the sum of node probabilities on this level double statsCost; // the current cost is stored here double statsCostAbove; // the current cost is stored here double statsCostBelow; // the current cost is stored here reo_unit * pHead; // the pointer to the beginning of the unit list }; struct _reo_hash { int Sign; // signature of the current cache operation reo_unit * Arg1; // the first argument reo_unit * Arg2; // the second argument reo_unit * Arg3; // the third argument }; struct _reo_man { // these paramaters can be set by the API functions int fMinWidth; // the flag to enable reordering for minimum width int fMinApl; // the flag to enable reordering for minimum APL int fVerbose; // the verbosity level int fVerify; // the flag toggling verification int fRemapUp; // the flag to enable remapping int nIters; // the number of interations of sifting to perform // parameters given by the user when reordering is called DdManager * dd; // the CUDD BDD manager int * pOrder; // the resulting variable order will be returned here // derived parameters int fThisIsAdd; // this flag is one if the function is the ADD int * pSupp; // the support of the given function int nSuppAlloc; // the max allowed number of support variables int nSupp; // the number of support variables int * pOrderInt; // the array storing the internal variable permutation double * pVarCosts; // other arrays int * pLevelOrder; // other arrays reo_unit ** pWidthCofs; // temporary storage for cofactors used during reordering for width // parameters related to cost int nNodesBeg; int nNodesCur; int nNodesEnd; int nWidthCur; int nWidthBeg; int nWidthEnd; double nAplCur; double nAplBeg; double nAplEnd; // mapping of the function into planes and back int * pMapToPlanes; // the mapping of var indexes into plane levels int * pMapToDdVarsOrig;// the mapping of plane levels into the original indexes int * pMapToDdVarsFinal;// the mapping of plane levels into the final indexes // the planes table reo_plane * pPlanes; int nPlanes; reo_unit ** pTops; int nTops; int nTopsAlloc; // the hash table reo_hash * HTable; // the table itself int nTableSize; // the size of the hash table int Signature; // the signature counter // the referenced node list int nNodesMaxAlloc; // this parameters determins how much memory is allocated DdNode ** pRefNodes; int nRefNodes; int nRefNodesAlloc; // unit memory management reo_unit * pUnitFreeList; reo_unit ** pMemChunks; int nMemChunks; int nMemChunksAlloc; int nUnitsUsed; // statistic variables int HashSuccess; int HashFailure; int nSwaps; // the number of swaps int nNISwaps; // the number of swaps without interaction }; // used to manipulate units #define Unit_Regular(u) ((reo_unit *)((ABC_PTRUINT_T)(u) & ~01)) #define Unit_Not(u) ((reo_unit *)((ABC_PTRUINT_T)(u) ^ 01)) #define Unit_NotCond(u,c) ((reo_unit *)((ABC_PTRUINT_T)(u) ^ (c))) #define Unit_IsConstant(u) ((int)((u)->lev == REO_CONST_LEVEL)) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // ======================= reoApi.c ======================================== extern reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ); extern void Extra_ReorderQuit( reo_man * p ); extern void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType ); extern void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp ); extern void Extra_ReorderSetIterations( reo_man * p, int nIters ); extern void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose ); extern void Extra_ReorderSetVerification( reo_man * p, int fVerify ); extern DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ); extern void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ); // ======================= reoCore.c ======================================= extern void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ); extern void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs ); // ======================= reoProfile.c ====================================== extern void reoProfileNodesStart( reo_man * p ); extern void reoProfileAplStart( reo_man * p ); extern void reoProfileWidthStart( reo_man * p ); extern void reoProfileWidthStart2( reo_man * p ); extern void reoProfileAplPrint( reo_man * p ); extern void reoProfileNodesPrint( reo_man * p ); extern void reoProfileWidthPrint( reo_man * p ); extern void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level ); // ======================= reoSift.c ======================================= extern void reoReorderSift( reo_man * p ); // ======================= reoSwap.c ======================================= extern double reoReorderSwapAdjacentVars( reo_man * p, int Level, int fMovingUp ); // ======================= reoTransfer.c =================================== extern reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ); extern DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ); // ======================= reoUnits.c ====================================== extern reo_unit * reoUnitsGetNextUnit(reo_man * p ); extern void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit ); extern void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane ); extern void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit ); extern void reoUnitsStopDispenser( reo_man * p ); // ======================= reoTest.c ======================================= extern void Extra_ReorderTest( DdManager * dd, DdNode * Func ); extern DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] ); extern int Extra_bddReorderTest( DdManager * dd, DdNode * bF ); extern int Extra_addReorderTest( DdManager * dd, DdNode * aF ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoApi.c000066400000000000000000000244271300674244400227460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoApi.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Implementation of API functions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoApi.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Initializes the reordering engine.] Description [The first argument is the max number of variables in the CUDD DD manager which will be used with the reordering engine (this number of should be the maximum of BDD and ZDD parts). The second argument is the maximum number of BDD nodes in the BDDs to be reordered. These limits are soft. Setting lower limits will later cause the reordering manager to resize internal data structures. However, setting the exact values will make reordering more efficient because resizing will be not necessary.] SideEffects [] SeeAlso [] ***********************************************************************/ reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ) { reo_man * p; // allocate and clean the data structure p = ABC_ALLOC( reo_man, 1 ); memset( p, 0, sizeof(reo_man) ); // resize the manager to meet user's needs reoResizeStructures( p, nDdVarsMax, nNodesMax, 100 ); // set the defaults p->fMinApl = 0; p->fMinWidth = 0; p->fRemapUp = 0; p->fVerbose = 0; p->fVerify = 0; p->nIters = 1; return p; } /**Function************************************************************* Synopsis [Disposes of the reordering engine.] Description [Removes all memory associated with the reordering engine.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderQuit( reo_man * p ) { ABC_FREE( p->pTops ); ABC_FREE( p->pSupp ); ABC_FREE( p->pOrderInt ); ABC_FREE( p->pWidthCofs ); ABC_FREE( p->pMapToPlanes ); ABC_FREE( p->pMapToDdVarsOrig ); ABC_FREE( p->pMapToDdVarsFinal ); ABC_FREE( p->pPlanes ); ABC_FREE( p->pVarCosts ); ABC_FREE( p->pLevelOrder ); ABC_FREE( p->HTable ); ABC_FREE( p->pRefNodes ); reoUnitsStopDispenser( p ); ABC_FREE( p->pMemChunks ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Sets the type of DD minimizationl that will be performed.] Description [Currently, three different types of minimization are supported. It is possible to minimize the number of BDD nodes. This is a classical type of minimization, which is attempting to reduce the total number of nodes in the (shared) BDD of the given Boolean functions. It is also possible to minimize the BDD width, defined as the sum total of the number of cofactors on each level in the (shared) BDD (note that the number of cofactors on the given level may be larger than the number of nodes appearing on the given level). It is also possible to minimize the average path length in the (shared) BDD defined as the sum of products, for all BDD paths from the top node to any terminal node, of the number of minterms on the path by the number of nodes on the path. The default reordering type is minimization for the number of BDD nodes. Calling this function with REO_MINIMIZE_WIDTH or REO_MINIMIZE_APL as the second argument, changes the default minimization option for all the reorder calls performed afterwards.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType ) { if ( fMinType == REO_MINIMIZE_NODES ) { p->fMinWidth = 0; p->fMinApl = 0; } else if ( fMinType == REO_MINIMIZE_WIDTH ) { p->fMinWidth = 1; p->fMinApl = 0; } else if ( fMinType == REO_MINIMIZE_APL ) { p->fMinWidth = 0; p->fMinApl = 1; } else { assert( 0 ); } } /**Function************************************************************* Synopsis [Sets the type of remapping performed by the engine.] Description [The remapping refers to the way the resulting BDD is expressed using the elementary variables of the CUDD BDD manager. Currently, two types possibilities are supported: remapping and no remapping. Remapping means that the function(s) after reordering depend on the topmost variables in the manager. No remapping means that the function(s) after reordering depend on the same variables as before. Consider the following example. Suppose the initial four variable function depends on variables 2,4,5, and 9 on the CUDD BDD manager, which may be found anywhere in the current variable order. If remapping is set, the function after ordering depends on the topmost variables in the manager, which may or may not be the same as the variables 2,4,5, and 9. If no remapping is set, then the reordered function depend on the same variables 2,4,5, and 9, but the meaning of each variale has changed according to the new ordering. The resulting ordering is returned in the array "pOrder" filled out by the reordering engine in the call to Extra_Reorder(). The default is no remapping.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp ) { p->fRemapUp = fRemapUp; } /**Function************************************************************* Synopsis [Sets the number of iterations of sifting performed.] Description [The default is one iteration. But a higher minimization quality is desired, it is possible to set the number of iterations to any number larger than 1. Convergence is often reached after several iterations, so typically it make no sense to set the number of iterations higher than 3.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderSetIterations( reo_man * p, int nIters ) { p->nIters = nIters; } /**Function************************************************************* Synopsis [Sets the verification mode.] Description [Setting the level to 1 results in verifying the results of variable reordering. Verification is performed by remapping the resulting functions into the original variable order and comparing them with the original functions given by the user. Enabling verification typically leads to 20-30% increase in the total runtime of REO.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderSetVerification( reo_man * p, int fVerify ) { p->fVerify = fVerify; } /**Function************************************************************* Synopsis [Sets the verbosity level.] Description [Setting the level to 1 results in printing statistics before and after the reordering.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose ) { p->fVerbose = fVerbose; } /**Function************************************************************* Synopsis [Performs reordering of the function.] Description [Returns the DD minimized by variable reordering in the REO engine. Takes the CUDD decision diagram manager (dd) and the function (Func) represented as a BDD or ADD (MTBDD). If the variable array (pOrder) is not NULL, returns the resulting variable permutation. The permutation is such that if the resulting function is permuted by Cudd_(add,bdd)Permute() using pOrder as the permutation array, the initial function (Func) results. Several flag set by other interface functions specify reordering options: - Remappig can be set by Extra_ReorderSetRemapping(). Then the resulting DD after reordering is remapped into the topmost levels of the DD manager. Otherwise, the resulting DD after reordering is mapped using the same variables, on which it originally depended, only (possibly) permuted as a result of reordering. - Minimization type can be set by Extra_ReorderSetMinimizationType(). Note that when the BDD is minimized for the total width of the total APL, the number BDD nodes can increase. The total width is defines as sum total of widths on each level. The width on one level is defined as the number of distinct BDD nodes pointed by the nodes situated above the given level. - The number of iterations of sifting can be set by Extra_ReorderSetIterations(). The decision diagram returned by this procedure is not referenced.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ) { DdNode * FuncRes; Extra_ReorderArray( p, dd, &Func, &FuncRes, 1, pOrder ); Cudd_Deref( FuncRes ); return FuncRes; } /**Function************************************************************* Synopsis [Performs reordering of the array of functions.] Description [The options are similar to the procedure Extra_Reorder(), except that the user should also provide storage for the resulting DDs, which are returned referenced.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) { reoReorderArray( p, dd, Funcs, FuncsRes, nFuncs, pOrder ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoCore.c000066400000000000000000000310471300674244400231210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoCore.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Implementation of the core reordering procedure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoCore.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int reoRecursiveDeref( reo_unit * pUnit ); static int reoCheckZeroRefs( reo_plane * pPlane ); static int reoCheckLevels( reo_man * p ); double s_AplBefore; double s_AplAfter; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) { int Counter, i; // set the initial parameters p->dd = dd; p->pOrder = pOrder; p->nTops = nFuncs; // get the initial number of nodes p->nNodesBeg = Cudd_SharingSize( Funcs, nFuncs ); // resize the internal data structures of the manager if necessary reoResizeStructures( p, ddMax(dd->size,dd->sizeZ), p->nNodesBeg, nFuncs ); // compute the support p->pSupp = Extra_VectorSupportArray( dd, Funcs, nFuncs, p->pSupp ); // get the number of support variables p->nSupp = 0; for ( i = 0; i < dd->size; i++ ) p->nSupp += p->pSupp[i]; // if it is the constant function, no need to reorder if ( p->nSupp == 0 ) { for ( i = 0; i < nFuncs; i++ ) { FuncsRes[i] = Funcs[i]; Cudd_Ref( FuncsRes[i] ); } return; } // create the internal variable maps // go through variable levels in the manager Counter = 0; for ( i = 0; i < dd->size; i++ ) if ( p->pSupp[ dd->invperm[i] ] ) { p->pMapToPlanes[ dd->invperm[i] ] = Counter; p->pMapToDdVarsOrig[Counter] = dd->invperm[i]; if ( !p->fRemapUp ) p->pMapToDdVarsFinal[Counter] = dd->invperm[i]; else p->pMapToDdVarsFinal[Counter] = dd->invperm[Counter]; p->pOrderInt[Counter] = Counter; Counter++; } // set the initial parameters p->nUnitsUsed = 0; p->nNodesCur = 0; p->fThisIsAdd = 0; p->Signature++; // transfer the function from the CUDD package into REO"s internal data structure for ( i = 0; i < nFuncs; i++ ) p->pTops[i] = reoTransferNodesToUnits_rec( p, Funcs[i] ); assert( p->nNodesBeg == p->nNodesCur ); if ( !p->fThisIsAdd && p->fMinWidth ) { printf( "An important message from the REO reordering engine:\n" ); printf( "The BDD given to the engine for reordering contains complemented edges.\n" ); printf( "Currently, such BDDs cannot be reordered for the minimum width.\n" ); printf( "Therefore, minimization for the number of BDD nodes is performed.\n" ); fflush( stdout ); p->fMinApl = 0; p->fMinWidth = 0; } if ( p->fMinWidth ) reoProfileWidthStart(p); else if ( p->fMinApl ) reoProfileAplStart(p); else reoProfileNodesStart(p); if ( p->fVerbose ) { printf( "INITIAL:\n" ); if ( p->fMinWidth ) reoProfileWidthPrint(p); else if ( p->fMinApl ) reoProfileAplPrint(p); else reoProfileNodesPrint(p); } /////////////////////////////////////////////////////////////////// // performs the reordering p->nSwaps = 0; p->nNISwaps = 0; for ( i = 0; i < p->nIters; i++ ) { reoReorderSift( p ); // print statistics after each iteration if ( p->fVerbose ) { printf( "ITER #%d:\n", i+1 ); if ( p->fMinWidth ) reoProfileWidthPrint(p); else if ( p->fMinApl ) reoProfileAplPrint(p); else reoProfileNodesPrint(p); } // if the cost function did not change, stop iterating if ( p->fMinWidth ) { p->nWidthEnd = p->nWidthCur; assert( p->nWidthEnd <= p->nWidthBeg ); if ( p->nWidthEnd == p->nWidthBeg ) break; } else if ( p->fMinApl ) { p->nAplEnd = p->nAplCur; assert( p->nAplEnd <= p->nAplBeg ); if ( p->nAplEnd == p->nAplBeg ) break; } else { p->nNodesEnd = p->nNodesCur; assert( p->nNodesEnd <= p->nNodesBeg ); if ( p->nNodesEnd == p->nNodesBeg ) break; } } assert( reoCheckLevels( p ) ); /////////////////////////////////////////////////////////////////// s_AplBefore = p->nAplBeg; s_AplAfter = p->nAplEnd; // set the initial parameters p->nRefNodes = 0; p->nNodesCur = 0; p->Signature++; // transfer the BDDs from REO's internal data structure to CUDD for ( i = 0; i < nFuncs; i++ ) { FuncsRes[i] = reoTransferUnitsToNodes_rec( p, p->pTops[i] ); Cudd_Ref( FuncsRes[i] ); } // undo the DDs referenced for storing in the cache for ( i = 0; i < p->nRefNodes; i++ ) Cudd_RecursiveDeref( dd, p->pRefNodes[i] ); // verify zero refs of the terminal nodes for ( i = 0; i < nFuncs; i++ ) { assert( reoRecursiveDeref( p->pTops[i] ) ); } assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); // prepare the variable map to return to the user if ( p->pOrder ) { // i is the current level in the planes data structure // p->pOrderInt[i] is the original level in the planes data structure // p->pMapToDdVarsOrig[i] is the variable, into which we remap when we construct the BDD from planes // p->pMapToDdVarsOrig[ p->pOrderInt[i] ] is the original BDD variable corresponding to this level // Therefore, p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ] // creates the permutation, which remaps the resulting BDD variable into the original BDD variable for ( i = 0; i < p->nSupp; i++ ) p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; } if ( p->fVerify ) { int fVerification; DdNode * FuncRemapped; int * pOrder; if ( p->pOrder == NULL ) { pOrder = ABC_ALLOC( int, p->nSupp ); for ( i = 0; i < p->nSupp; i++ ) pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; } else pOrder = p->pOrder; fVerification = 1; for ( i = 0; i < nFuncs; i++ ) { // verify the result if ( p->fThisIsAdd ) FuncRemapped = Cudd_addPermute( dd, FuncsRes[i], pOrder ); else FuncRemapped = Cudd_bddPermute( dd, FuncsRes[i], pOrder ); Cudd_Ref( FuncRemapped ); if ( FuncRemapped != Funcs[i] ) { fVerification = 0; printf( "REO: Internal verification has failed!\n" ); fflush( stdout ); } Cudd_RecursiveDeref( dd, FuncRemapped ); } if ( fVerification ) printf( "REO: Internal verification is okay!\n" ); if ( p->pOrder == NULL ) ABC_FREE( pOrder ); } // recycle the data structure for ( i = 0; i <= p->nSupp; i++ ) reoUnitsRecycleUnitList( p, p->pPlanes + i ); } /**Function************************************************************* Synopsis [Resizes the internal manager data structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs ) { // resize data structures depending on the number of variables in the DD manager if ( p->nSuppAlloc == 0 ) { p->pSupp = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pOrderInt = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pMapToPlanes = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pMapToDdVarsOrig = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pMapToDdVarsFinal = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pPlanes = ABC_CALLOC( reo_plane, nDdVarsMax + 1 ); p->pVarCosts = ABC_ALLOC( double, nDdVarsMax + 1 ); p->pLevelOrder = ABC_ALLOC( int, nDdVarsMax + 1 ); p->nSuppAlloc = nDdVarsMax + 1; } else if ( p->nSuppAlloc < nDdVarsMax ) { ABC_FREE( p->pSupp ); ABC_FREE( p->pOrderInt ); ABC_FREE( p->pMapToPlanes ); ABC_FREE( p->pMapToDdVarsOrig ); ABC_FREE( p->pMapToDdVarsFinal ); ABC_FREE( p->pPlanes ); ABC_FREE( p->pVarCosts ); ABC_FREE( p->pLevelOrder ); p->pSupp = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pOrderInt = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pMapToPlanes = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pMapToDdVarsOrig = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pMapToDdVarsFinal = ABC_ALLOC( int, nDdVarsMax + 1 ); p->pPlanes = ABC_CALLOC( reo_plane, nDdVarsMax + 1 ); p->pVarCosts = ABC_ALLOC( double, nDdVarsMax + 1 ); p->pLevelOrder = ABC_ALLOC( int, nDdVarsMax + 1 ); p->nSuppAlloc = nDdVarsMax + 1; } // resize the data structures depending on the number of nodes if ( p->nRefNodesAlloc == 0 ) { p->nNodesMaxAlloc = nNodesMax; p->nTableSize = 3*nNodesMax + 1; p->nRefNodesAlloc = 3*nNodesMax + 1; p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1; p->HTable = ABC_CALLOC( reo_hash, p->nTableSize ); p->pRefNodes = ABC_ALLOC( DdNode *, p->nRefNodesAlloc ); p->pWidthCofs = ABC_ALLOC( reo_unit *, p->nRefNodesAlloc ); p->pMemChunks = ABC_ALLOC( reo_unit *, p->nMemChunksAlloc ); } else if ( p->nNodesMaxAlloc < nNodesMax ) { reo_unit ** pTemp; int nMemChunksAllocPrev = p->nMemChunksAlloc; p->nNodesMaxAlloc = nNodesMax; p->nTableSize = 3*nNodesMax + 1; p->nRefNodesAlloc = 3*nNodesMax + 1; p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1; ABC_FREE( p->HTable ); ABC_FREE( p->pRefNodes ); ABC_FREE( p->pWidthCofs ); p->HTable = ABC_CALLOC( reo_hash, p->nTableSize ); p->pRefNodes = ABC_ALLOC( DdNode *, p->nRefNodesAlloc ); p->pWidthCofs = ABC_ALLOC( reo_unit *, p->nRefNodesAlloc ); // p->pMemChunks should be reallocated because it contains pointers currently in use pTemp = ABC_ALLOC( reo_unit *, p->nMemChunksAlloc ); memmove( pTemp, p->pMemChunks, sizeof(reo_unit *) * nMemChunksAllocPrev ); ABC_FREE( p->pMemChunks ); p->pMemChunks = pTemp; } // resize the data structures depending on the number of functions if ( p->nTopsAlloc == 0 ) { p->pTops = ABC_ALLOC( reo_unit *, nFuncs ); p->nTopsAlloc = nFuncs; } else if ( p->nTopsAlloc < nFuncs ) { ABC_FREE( p->pTops ); p->pTops = ABC_ALLOC( reo_unit *, nFuncs ); p->nTopsAlloc = nFuncs; } } /**Function************************************************************* Synopsis [Dereferences units the data structure after reordering.] Description [This function is only useful for debugging.] SideEffects [] SeeAlso [] ***********************************************************************/ int reoRecursiveDeref( reo_unit * pUnit ) { reo_unit * pUnitR; pUnitR = Unit_Regular(pUnit); pUnitR->n--; if ( Unit_IsConstant(pUnitR) ) return 1; if ( pUnitR->n == 0 ) { reoRecursiveDeref( pUnitR->pE ); reoRecursiveDeref( pUnitR->pT ); } return 1; } /**Function************************************************************* Synopsis [Checks the zero references for the given plane.] Description [This function is only useful for debugging.] SideEffects [] SeeAlso [] ***********************************************************************/ int reoCheckZeroRefs( reo_plane * pPlane ) { reo_unit * pUnit; for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) { if ( pUnit->n != 0 ) { assert( 0 ); } } return 1; } /**Function************************************************************* Synopsis [Checks the zero references for the given plane.] Description [This function is only useful for debugging.] SideEffects [] SeeAlso [] ***********************************************************************/ int reoCheckLevels( reo_man * p ) { reo_unit * pUnit; int i; for ( i = 0; i < p->nSupp; i++ ) { // there are some nodes left on each level assert( p->pPlanes[i].statsNodes ); for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) { // the level is properly set assert( pUnit->lev == i ); } } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoProfile.c000066400000000000000000000251731300674244400236340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoProfile.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Procudures that compute variables profiles (nodes, width, APL).] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoProfile.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [Start the profile for the BDD nodes.] Description [TopRef is the first level, on this the given node counts towards the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] SideEffects [] SeeAlso [] ******************************************************************************/ void reoProfileNodesStart( reo_man * p ) { int Total, i; Total = 0; for ( i = 0; i <= p->nSupp; i++ ) { p->pPlanes[i].statsCost = p->pPlanes[i].statsNodes; Total += p->pPlanes[i].statsNodes; } assert( Total == p->nNodesCur ); p->nNodesBeg = p->nNodesCur; } /**Function************************************************************* Synopsis [Start the profile for the APL.] Description [Computes the total path length. The path length is normalized by dividing it by 2^|supp(f)|. To get the "real" APL, multiply by 2^|supp(f)|. This procedure assumes that Weight field of all nodes has been set to 0.0 before the call, except for the weight of the topmost node, which is set to 1.0 (1.0 is the probability of traversing the topmost node). This procedure assigns the edge weights. Because of the equal probability of selecting 0 and 1 assignment at a node, the edge weights are the same for the node. Instead of storing them, we store the weight of the node, which is the probability of traversing the node (pUnit->Weight) during the top down evalation of the BDD. ] SideEffects [] SeeAlso [] ***********************************************************************/ void reoProfileAplStart( reo_man * p ) { reo_unit * pER, * pTR; reo_unit * pUnit; double Res, Half; int i; // clean the weights of all nodes for ( i = 0; i < p->nSupp; i++ ) for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) pUnit->Weight = 0.0; // to assign the node weights (the probability of visiting each node) // we visit the node after visiting its predecessors // set the probability of visits to the top nodes for ( i = 0; i < p->nTops; i++ ) Unit_Regular(p->pTops[i])->Weight += 1.0; // to compute the path length (the sum of products of edge weight by edge length) // we visit the nodes in any order (the above order will do) Res = 0.0; for ( i = 0; i < p->nSupp; i++ ) { p->pPlanes[i].statsCost = 0.0; for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) { pER = Unit_Regular(pUnit->pE); pTR = Unit_Regular(pUnit->pT); Half = 0.5 * pUnit->Weight; pER->Weight += Half; pTR->Weight += Half; // add to the path length p->pPlanes[i].statsCost += pUnit->Weight; } Res += p->pPlanes[i].statsCost; } p->pPlanes[p->nSupp].statsCost = 0.0; p->nAplBeg = p->nAplCur = Res; } /**Function******************************************************************** Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N + n).] Description [TopRef is the first level, on which the given node counts towards the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] SideEffects [] SeeAlso [] ******************************************************************************/ void reoProfileWidthStart( reo_man * p ) { reo_unit * pUnit; int * pWidthStart; int * pWidthStop; int v; // allocate and clean the storage for starting and stopping levels pWidthStart = ABC_ALLOC( int, p->nSupp + 1 ); pWidthStop = ABC_ALLOC( int, p->nSupp + 1 ); memset( pWidthStart, 0, sizeof(int) * (p->nSupp + 1) ); memset( pWidthStop, 0, sizeof(int) * (p->nSupp + 1) ); // go through the non-constant nodes and set the topmost level of their cofactors for ( v = 0; v <= p->nSupp; v++ ) for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) { pUnit->TopRef = REO_TOPREF_UNDEF; pUnit->Sign = 0; } // add the topmost level of the width profile for ( v = 0; v < p->nTops; v++ ) { pUnit = Unit_Regular(p->pTops[v]); if ( pUnit->TopRef == REO_TOPREF_UNDEF ) { // set the starting level pUnit->TopRef = 0; pWidthStart[pUnit->TopRef]++; // set the stopping level if ( pUnit->lev != REO_CONST_LEVEL ) pWidthStop[pUnit->lev+1]++; } } for ( v = 0; v < p->nSupp; v++ ) for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) { if ( pUnit->pE->TopRef == REO_TOPREF_UNDEF ) { // set the starting level pUnit->pE->TopRef = pUnit->lev + 1; pWidthStart[pUnit->pE->TopRef]++; // set the stopping level if ( pUnit->pE->lev != REO_CONST_LEVEL ) pWidthStop[pUnit->pE->lev+1]++; } if ( pUnit->pT->TopRef == REO_TOPREF_UNDEF ) { // set the starting level pUnit->pT->TopRef = pUnit->lev + 1; pWidthStart[pUnit->pT->TopRef]++; // set the stopping level if ( pUnit->pT->lev != REO_CONST_LEVEL ) pWidthStop[pUnit->pT->lev+1]++; } } // verify the top reference for ( v = 0; v < p->nSupp; v++ ) reoProfileWidthVerifyLevel( p->pPlanes + v, v ); // derive the profile p->nWidthCur = 0; for ( v = 0; v <= p->nSupp; v++ ) { if ( v == 0 ) p->pPlanes[v].statsWidth = pWidthStart[v] - pWidthStop[v]; else p->pPlanes[v].statsWidth = p->pPlanes[v-1].statsWidth + pWidthStart[v] - pWidthStop[v]; p->pPlanes[v].statsCost = p->pPlanes[v].statsWidth; p->nWidthCur += p->pPlanes[v].statsWidth; printf( "Level %2d: Width = %5d.\n", v, p->pPlanes[v].statsWidth ); } p->nWidthBeg = p->nWidthCur; ABC_FREE( pWidthStart ); ABC_FREE( pWidthStop ); } /**Function******************************************************************** Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N * n).] Description [TopRef is the first level, on which the given node counts towards the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] SideEffects [] SeeAlso [] ******************************************************************************/ void reoProfileWidthStart2( reo_man * p ) { reo_unit * pUnit; int i, v; // clean the profile for ( i = 0; i <= p->nSupp; i++ ) p->pPlanes[i].statsWidth = 0; // clean the node structures for ( v = 0; v <= p->nSupp; v++ ) for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) { pUnit->TopRef = REO_TOPREF_UNDEF; pUnit->Sign = 0; } // set the topref to the topmost nodes for ( i = 0; i < p->nTops; i++ ) Unit_Regular(p->pTops[i])->TopRef = 0; // go through the non-constant nodes and set the topmost level of their cofactors for ( i = 0; i < p->nSupp; i++ ) for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) { if ( pUnit->pE->TopRef > i+1 ) pUnit->pE->TopRef = i+1; if ( pUnit->pT->TopRef > i+1 ) pUnit->pT->TopRef = i+1; } // verify the top reference for ( i = 0; i < p->nSupp; i++ ) reoProfileWidthVerifyLevel( p->pPlanes + i, i ); // compute the profile for the internal nodes for ( i = 0; i < p->nSupp; i++ ) for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) for ( v = pUnit->TopRef; v <= pUnit->lev; v++ ) p->pPlanes[v].statsWidth++; // compute the profile for the constant nodes for ( pUnit = p->pPlanes[p->nSupp].pHead; pUnit; pUnit = pUnit->Next ) for ( v = pUnit->TopRef; v <= p->nSupp; v++ ) p->pPlanes[v].statsWidth++; // get the width cost p->nWidthCur = 0; for ( i = 0; i <= p->nSupp; i++ ) { p->pPlanes[i].statsCost = p->pPlanes[i].statsWidth; p->nWidthCur += p->pPlanes[i].statsWidth; } p->nWidthBeg = p->nWidthCur; } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void reoProfileNodesPrint( reo_man * p ) { printf( "NODES: Total = %6d. Average = %6.2f.\n", p->nNodesCur, p->nNodesCur / (float)p->nSupp ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void reoProfileAplPrint( reo_man * p ) { printf( "APL: Total = %8.2f. Average =%6.2f.\n", p->nAplCur, p->nAplCur / (float)p->nSupp ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void reoProfileWidthPrint( reo_man * p ) { int WidthMax; int TotalWidth; int i; WidthMax = 0; TotalWidth = 0; for ( i = 0; i <= p->nSupp; i++ ) { printf( "Level = %2d. Width = %3d.\n", i, p->pPlanes[i].statsWidth ); if ( WidthMax < p->pPlanes[i].statsWidth ) WidthMax = p->pPlanes[i].statsWidth; TotalWidth += p->pPlanes[i].statsWidth; } assert( p->nWidthCur == TotalWidth ); printf( "WIDTH: " ); printf( "Maximum = %5d. ", WidthMax ); printf( "Total = %7d. ", p->nWidthCur ); printf( "Average = %6.2f.\n", TotalWidth / (float)p->nSupp ); } /**Function******************************************************************** Synopsis [] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level ) { reo_unit * pUnit; for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) { assert( pUnit->TopRef <= Level ); assert( pUnit->pE->TopRef <= Level + 1 ); assert( pUnit->pT->TopRef <= Level + 1 ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoShuffle.c000066400000000000000000000152331300674244400236240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoShuffle.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Implementation of the two-variable swap.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoShuffle.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure is similar to Cudd_ShuffleHeap() and Cudd_bddPermute().] Description [The first argument is the REO manager. The 2nd/3d arguments are the function and its CUDD manager. The last argument is the permutation to be implemented. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use (that is, the size of CUDD manager and the size of REO manager).] SideEffects [Note that the resulting BDD is not referenced.] SeeAlso [] ***********************************************************************/ DdNode * reoShuffle( reo_man * p, DdManager * dd, DdNode * bFunc, int * pPerm, int * pPermInv ) { DdNode * bFuncRes = NULL; int i, k, v; if ( Cudd_IsConstant(bFunc) ) return bFunc; // set the initial parameters p->dd = dd; p->nSupp = Cudd_SupportSize( dd, bFunc ); p->nTops = 1; // p->nNodesBeg = Cudd_DagSize( bFunc ); // set the starting permutation for ( i = 0; i < p->nSupp; i++ ) { p->pOrderInt[i] = i; p->pMapToPlanes[ dd->invperm[i] ] = i; p->pMapToDdVarsFinal[i] = dd->invperm[i]; } // set the initial parameters p->nUnitsUsed = 0; p->nNodesCur = 0; p->fThisIsAdd = 0; p->Signature++; // transfer the function from the CUDD package into REO's internal data structure p->pTops[0] = reoTransferNodesToUnits_rec( p, bFunc ); // assert( p->nNodesBeg == p->nNodesCur ); // reorder one variable at a time for ( i = 0; i < p->nSupp; i++ ) { if ( p->pOrderInt[i] == pPerm[i] ) continue; // find where is variable number pPerm[i] for ( k = i + 1; k < p->nSupp; k++ ) if ( pPerm[i] == p->pOrderInt[k] ) break; if ( k == p->nSupp ) { printf( "reoShuffle() Error: Cannot find a variable.\n" ); goto finish; } // move the variable up for ( v = k - 1; v >= i; v-- ) { reoReorderSwapAdjacentVars( p, v, 1 ); // check if the number of nodes is not too large if ( p->nNodesCur > 10000 ) { printf( "reoShuffle() Error: BDD size is too large.\n" ); goto finish; } } assert( p->pOrderInt[i] == pPerm[i] ); } // set the initial parameters p->nRefNodes = 0; p->nNodesCur = 0; p->Signature++; // transfer the BDDs from REO's internal data structure to CUDD bFuncRes = reoTransferUnitsToNodes_rec( p, p->pTops[0] ); Cudd_Ref( bFuncRes ); // undo the DDs referenced for storing in the cache for ( i = 0; i < p->nRefNodes; i++ ) Cudd_RecursiveDeref( dd, p->pRefNodes[i] ); // verify zero refs of the terminal nodes // assert( reoRecursiveDeref( p->pTops[0] ) ); // assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); // perform verification if ( p->fVerify ) { DdNode * bFuncPerm; bFuncPerm = Cudd_bddPermute( dd, bFunc, pPermInv ); Cudd_Ref( bFuncPerm ); if ( bFuncPerm != bFuncRes ) { printf( "REO: Internal verification has failed!\n" ); fflush( stdout ); } Cudd_RecursiveDeref( dd, bFuncPerm ); } // recycle the data structure for ( i = 0; i <= p->nSupp; i++ ) reoUnitsRecycleUnitList( p, p->pPlanes + i ); finish : if ( bFuncRes ) Cudd_Deref( bFuncRes ); return bFuncRes; } /**Function************************************************************* Synopsis [Reorders the DD using REO and CUDD.] Description [This function can be used to test the performance of the reordering package.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ShuffleTest( reo_man * pReo, DdManager * dd, DdNode * Func ) { // extern int runtime1, runtime2; DdNode * Temp, * bRemap; int nSuppSize, OffSet, Num, i; abctime clk; int pOrder[1000], pOrderInv[1000]; assert( dd->size < 1000 ); srand( 0x12341234 ); nSuppSize = Cudd_SupportSize( dd, Func ); if ( nSuppSize < 2 ) return; for ( i = 0; i < nSuppSize; i++ ) pOrder[i] = i; for ( i = 0; i < 120; i++ ) { OffSet = rand() % (nSuppSize - 1); Num = pOrder[OffSet]; pOrder[OffSet] = pOrder[OffSet+1]; pOrder[OffSet+1] = Num; } for ( i = 0; i < nSuppSize; i++ ) pOrderInv[pOrder[i]] = i; /* printf( "Permutation: " ); for ( i = 0; i < nSuppSize; i++ ) printf( "%d ", pOrder[i] ); printf( "\n" ); printf( "Inverse permutation: " ); for ( i = 0; i < nSuppSize; i++ ) printf( "%d ", pOrderInv[i] ); printf( "\n" ); */ // create permutation // Extra_ReorderSetVerification( pReo, 1 ); bRemap = Extra_bddRemapUp( dd, Func ); Cudd_Ref( bRemap ); clk = Abc_Clock(); Temp = reoShuffle( pReo, dd, bRemap, pOrder, pOrderInv ); Cudd_Ref( Temp ); //runtime1 += Abc_Clock() - clk; //printf( "Initial = %d. Final = %d.\n", Cudd_DagSize(bRemap), Cudd_DagSize(Temp) ); { DdNode * bFuncPerm; clk = Abc_Clock(); bFuncPerm = Cudd_bddPermute( dd, bRemap, pOrderInv ); Cudd_Ref( bFuncPerm ); //runtime2 += Abc_Clock() - clk; if ( bFuncPerm != Temp ) { printf( "REO: Internal verification has failed!\n" ); fflush( stdout ); } Cudd_RecursiveDeref( dd, bFuncPerm ); } Cudd_RecursiveDeref( dd, Temp ); Cudd_RecursiveDeref( dd, bRemap ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoSift.c000066400000000000000000000305251300674244400231360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoSift.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Implementation of the sifting algorihtm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoSift.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Implements the variable sifting algorithm.] Description [Performs a sequence of adjacent variable swaps known as "sifting". Uses the cost functions determined by the flag.] SideEffects [] SeeAlso [] ***********************************************************************/ void reoReorderSift( reo_man * p ) { double CostCurrent; // the cost of the current permutation double CostLimit; // the maximum increase in cost that can be tolerated double CostBest; // the best cost int BestQ; // the best position int VarCurrent; // the current variable to move int q; // denotes the current position of the variable int c; // performs the loops over variables until all of them are sifted int v; // used for other purposes assert( p->nSupp > 0 ); // set the current cost depending on the minimization criteria if ( p->fMinWidth ) CostCurrent = p->nWidthCur; else if ( p->fMinApl ) CostCurrent = p->nAplCur; else CostCurrent = p->nNodesCur; // find the upper bound on tbe cost growth CostLimit = 1 + (int)(REO_REORDER_LIMIT * CostCurrent); // perform sifting for each of p->nSupp variables for ( c = 0; c < p->nSupp; c++ ) { // select the current variable to be the one with the largest number of nodes that is not sifted yet VarCurrent = -1; CostBest = -1.0; for ( v = 0; v < p->nSupp; v++ ) { p->pVarCosts[v] = REO_HIGH_VALUE; if ( !p->pPlanes[v].fSifted ) { // VarCurrent = v; // if ( CostBest < p->pPlanes[v].statsCost ) if ( CostBest < p->pPlanes[v].statsNodes ) { // CostBest = p->pPlanes[v].statsCost; CostBest = p->pPlanes[v].statsNodes; VarCurrent = v; } } } assert( VarCurrent != -1 ); // mark this variable as sifted p->pPlanes[VarCurrent].fSifted = 1; // set the current value p->pVarCosts[VarCurrent] = CostCurrent; // set the best cost CostBest = CostCurrent; BestQ = VarCurrent; // determine which way to move the variable first (up or down) // the rationale is that if we move the shorter way first // it is more likely that the best position will be found on the longer way // and the reverse movement (to take the best position) will be faster if ( VarCurrent < p->nSupp/2 ) // move up first, then down { // set the total cost on all levels above the current level p->pPlanes[0].statsCostAbove = 0; for ( v = 1; v <= VarCurrent; v++ ) p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; // set the total cost on all levels below the current level p->pPlanes[p->nSupp].statsCostBelow = 0; for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + p->pPlanes[VarCurrent].statsCost + p->pPlanes[VarCurrent].statsCostBelow ); // move up for ( q = VarCurrent-1; q >= 0; q-- ) { CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); // now q points to the position of this var in the order p->pVarCosts[q] = CostCurrent; // update the lower bound (assuming that for level q+1 it is set correctly) p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; // check the upper bound if ( CostCurrent >= CostLimit ) break; // check the lower bound if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) break; // update the best cost if ( CostBest > CostCurrent ) { CostBest = CostCurrent; BestQ = q; // adjust node limit CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); } // when we are reordering for width or APL, it may happen that // the number of nodes has grown above certain limit, // in which case we have to resize the data structures if ( p->fMinWidth || p->fMinApl ) { if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) { // printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); reoResizeStructures( p, 0, p->nNodesCur, 0 ); } } } // fix the plane index if ( q == -1 ) q++; // now p points to the position of this var in the order // move down for ( ; q < p->nSupp-1; ) { CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); q++; // change q to point to the position of this var in the order // sanity check: the number of nodes on the back pass should be the same if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); p->pVarCosts[q] = CostCurrent; // update the lower bound (assuming that for level q-1 it is set correctly) p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; // check the bounds only if the variable already reached its previous position if ( q >= BestQ ) { // check the upper bound if ( CostCurrent >= CostLimit ) break; // check the lower bound if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) break; } // update the best cost if ( CostBest >= CostCurrent ) { CostBest = CostCurrent; BestQ = q; // adjust node limit CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); } // when we are reordering for width or APL, it may happen that // the number of nodes has grown above certain limit, // in which case we have to resize the data structures if ( p->fMinWidth || p->fMinApl ) { if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) { // printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); reoResizeStructures( p, 0, p->nNodesCur, 0 ); } } } // move the variable up from the given position (q) to the best position (BestQ) assert( q >= BestQ ); for ( ; q > BestQ; q-- ) { CostCurrent -= reoReorderSwapAdjacentVars( p, q-1, 1 ); // sanity check: the number of nodes on the back pass should be the same if ( fabs( p->pVarCosts[q-1] - CostCurrent ) > REO_COST_EPSILON ) { printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); fflush(stdout); } } } else // move down first, then up { // set the current number of nodes on all levels above the given level p->pPlanes[0].statsCostAbove = 0; for ( v = 1; v <= VarCurrent; v++ ) p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; // set the current number of nodes on all levels below the given level p->pPlanes[p->nSupp].statsCostBelow = 0; for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + p->pPlanes[VarCurrent].statsCost + p->pPlanes[VarCurrent].statsCostBelow ); // move down for ( q = VarCurrent; q < p->nSupp-1; ) { CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); q++; // change q to point to the position of this var in the order p->pVarCosts[q] = CostCurrent; // update the lower bound (assuming that for level q-1 it is set correctly) p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; // check the upper bound if ( CostCurrent >= CostLimit ) break; // check the lower bound if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) break; // update the best cost if ( CostBest > CostCurrent ) { CostBest = CostCurrent; BestQ = q; // adjust node limit CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); } // when we are reordering for width or APL, it may happen that // the number of nodes has grown above certain limit, // in which case we have to resize the data structures if ( p->fMinWidth || p->fMinApl ) { if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) { // printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); reoResizeStructures( p, 0, p->nNodesCur, 0 ); } } } // move up for ( --q; q >= 0; q-- ) { CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); // now q points to the position of this var in the order // sanity check: the number of nodes on the back pass should be the same if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); p->pVarCosts[q] = CostCurrent; // update the lower bound (assuming that for level q+1 it is set correctly) p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; // check the bounds only if the variable already reached its previous position if ( q <= BestQ ) { // check the upper bound if ( CostCurrent >= CostLimit ) break; // check the lower bound if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) break; } // update the best cost if ( CostBest >= CostCurrent ) { CostBest = CostCurrent; BestQ = q; // adjust node limit CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); } // when we are reordering for width or APL, it may happen that // the number of nodes has grown above certain limit, // in which case we have to resize the data structures if ( p->fMinWidth || p->fMinApl ) { if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) { // printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); reoResizeStructures( p, 0, p->nNodesCur, 0 ); } } } // fix the plane index if ( q == -1 ) q++; // now q points to the position of this var in the order // move the variable down from the given position (q) to the best position (BestQ) assert( q <= BestQ ); for ( ; q < BestQ; q++ ) { CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); // sanity check: the number of nodes on the back pass should be the same if ( fabs( p->pVarCosts[q+1] - CostCurrent ) > REO_COST_EPSILON ) { printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); fflush(stdout); } } } assert( fabs( CostBest - CostCurrent ) < REO_COST_EPSILON ); // update the cost if ( p->fMinWidth ) p->nWidthCur = (int)CostBest; else if ( p->fMinApl ) p->nAplCur = CostCurrent; else p->nNodesCur = (int)CostBest; } // remove the sifted attributes if any for ( v = 0; v < p->nSupp; v++ ) p->pPlanes[v].fSifted = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoSwap.c000066400000000000000000000666531300674244400231560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoSwap.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Implementation of the two-variable swap.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoSwap.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define AddToLinkedList( ppList, pLink ) (((pLink)->Next = *(ppList)), (*(ppList) = (pLink))) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [Takes the level (lev0) of the plane, which should be swapped with the next plane. Returns the gain using the current cost function.] SideEffects [] SeeAlso [] ***********************************************************************/ double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) { // the levels in the decision diagram int lev1 = lev0 + 1, lev2 = lev0 + 2; // the new nodes on lev0 reo_unit * pLoop, * pUnit; // the new nodes on lev1 reo_unit * pNewPlane20 = NULL, * pNewPlane21 = NULL; // Suppress "might be used uninitialized" reo_unit * pNewPlane20R; reo_unit * pUnitE, * pUnitER, * pUnitT; // the nodes below lev1 reo_unit * pNew1E, * pNew1T, * pNew2E, * pNew2T; reo_unit * pNew1ER, * pNew2ER; // the old linked lists reo_unit * pListOld0 = p->pPlanes[lev0].pHead; reo_unit * pListOld1 = p->pPlanes[lev1].pHead; // working planes and one more temporary plane reo_unit * pListNew0 = NULL, ** ppListNew0 = &pListNew0; reo_unit * pListNew1 = NULL, ** ppListNew1 = &pListNew1; reo_unit * pListTemp = NULL, ** ppListTemp = &pListTemp; // various integer variables int fComp, fCompT, fFound, HKey, fInteract, temp, c; int nWidthCofs = -1; // Suppress "might be used uninitialized" // statistical variables int nNodesUpMovedDown = 0; int nNodesDownMovedUp = 0; int nNodesUnrefRemoved = 0; int nNodesUnrefAdded = 0; int nWidthReduction = 0; double AplWeightTotalLev0 = 0.0; // Suppress "might be used uninitialized" double AplWeightTotalLev1 = 0.0; // Suppress "might be used uninitialized" double AplWeightHalf = 0.0; // Suppress "might be used uninitialized" double AplWeightPrev = 0.0; // Suppress "might be used uninitialized" double AplWeightAfter = 0.0; // Suppress "might be used uninitialized" double nCostGain; // set the old lists assert( lev0 >= 0 && lev1 < p->nSupp ); pListOld0 = p->pPlanes[lev0].pHead; pListOld1 = p->pPlanes[lev1].pHead; // make sure the planes have nodes assert( p->pPlanes[lev0].statsNodes && p->pPlanes[lev1].statsNodes ); assert( pListOld0 && pListOld1 ); if ( p->fMinWidth ) { // verify that the width parameters are set correctly reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); // start the storage for cofactors nWidthCofs = 0; } else if ( p->fMinApl ) { AplWeightPrev = p->nAplCur; AplWeightAfter = p->nAplCur; AplWeightTotalLev0 = 0.0; AplWeightTotalLev1 = 0.0; } // check if the planes interact fInteract = 0; // assume that they do not interact for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) { if ( pUnit->pT->lev == lev1 || Unit_Regular(pUnit->pE)->lev == lev1 ) { fInteract = 1; break; } // change the level now, this is done for efficiency reasons pUnit->lev = lev1; } // set the new signature for hashing p->nSwaps++; if ( !fInteract ) // if ( 0 ) { // perform the swap without interaction p->nNISwaps++; // change the levels if ( p->fMinWidth ) { // go through the current lower level, which will become upper for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) { pUnit->lev = lev0; pUnitER = Unit_Regular(pUnit->pE); if ( pUnitER->TopRef > lev0 ) { if ( pUnitER->Sign != p->nSwaps ) { if ( pUnitER->TopRef == lev2 ) { pUnitER->TopRef = lev1; nWidthReduction--; } else { assert( pUnitER->TopRef == lev1 ); } pUnitER->Sign = p->nSwaps; } } pUnitT = pUnit->pT; if ( pUnitT->TopRef > lev0 ) { if ( pUnitT->Sign != p->nSwaps ) { if ( pUnitT->TopRef == lev2 ) { pUnitT->TopRef = lev1; nWidthReduction--; } else { assert( pUnitT->TopRef == lev1 ); } pUnitT->Sign = p->nSwaps; } } } // go through the current upper level, which will become lower for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) { pUnit->lev = lev1; pUnitER = Unit_Regular(pUnit->pE); if ( pUnitER->TopRef > lev0 ) { if ( pUnitER->Sign != p->nSwaps ) { assert( pUnitER->TopRef == lev1 ); pUnitER->TopRef = lev2; pUnitER->Sign = p->nSwaps; nWidthReduction++; } } pUnitT = pUnit->pT; if ( pUnitT->TopRef > lev0 ) { if ( pUnitT->Sign != p->nSwaps ) { assert( pUnitT->TopRef == lev1 ); pUnitT->TopRef = lev2; pUnitT->Sign = p->nSwaps; nWidthReduction++; } } } } else { // for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) // pUnit->lev = lev1; for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) pUnit->lev = lev0; } // set the new linked lists, which will be attached to the planes pListNew0 = pListOld1; pListNew1 = pListOld0; if ( p->fMinApl ) { AplWeightTotalLev0 = p->pPlanes[lev1].statsCost; AplWeightTotalLev1 = p->pPlanes[lev0].statsCost; } // set the changes in terms of nodes nNodesUpMovedDown = p->pPlanes[lev0].statsNodes; nNodesDownMovedUp = p->pPlanes[lev1].statsNodes; goto finish; } p->Signature++; // two-variable swap is done in three easy steps // previously I thought that steps (1) and (2) can be merged into one step // now it is clear that this cannot be done without changing a lot of other stuff... // (1) walk through the upper level, find units without cofactors in the lower level // and move them to the new lower level (while adding to the cache) // (2) walk through the uppoer level, and tranform all the remaning nodes // while employing cache for the new lower level // (3) walk through the old lower level, find those nodes whose ref counters are not zero, // and move them to the new uppoer level, free other nodes // (1) walk through the upper level, find units without cofactors in the lower level // and move them to the new lower level (while adding to the cache) for ( pLoop = pListOld0; pLoop; ) { pUnit = pLoop; pLoop = pLoop->Next; pUnitE = pUnit->pE; pUnitER = Unit_Regular(pUnitE); pUnitT = pUnit->pT; if ( pUnitER->lev != lev1 && pUnitT->lev != lev1 ) { // before after // // . // 0 / \ 1 . // / \ . // / \ . // / \ . // / \ 0 / \ 1 . // / \ / \ . // / \ / \ . // F0 F1 F0 F1 // move to plane-2-new // nothing changes in the process (cofactors, ref counter, APL weight) pUnit->lev = lev1; AddToLinkedList( ppListNew1, pUnit ); if ( p->fMinApl ) AplWeightTotalLev1 += pUnit->Weight; // add to cache - find the cell with different signature (not the current one!) for ( HKey = hashKey3(p->Signature, pUnitE, pUnitT, p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); assert( p->HTable[HKey].Sign != p->Signature ); p->HTable[HKey].Sign = p->Signature; p->HTable[HKey].Arg1 = pUnitE; p->HTable[HKey].Arg2 = pUnitT; p->HTable[HKey].Arg3 = pUnit; nNodesUpMovedDown++; if ( p->fMinWidth ) { // update the cofactors's top ref if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { assert( pUnitER->TopRef == lev1 ); pUnitER->TopRefNew = lev2; if ( pUnitER->Sign != p->nSwaps ) { pUnitER->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pUnitER; } } if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { assert( pUnitT->TopRef == lev1 ); pUnitT->TopRefNew = lev2; if ( pUnitT->Sign != p->nSwaps ) { pUnitT->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pUnitT; } } } } else { // add to the temporary plane AddToLinkedList( ppListTemp, pUnit ); } } // (2) walk through the uppoer level, and tranform all the remaning nodes // while employing cache for the new lower level for ( pLoop = pListTemp; pLoop; ) { pUnit = pLoop; pLoop = pLoop->Next; pUnitE = pUnit->pE; pUnitER = Unit_Regular(pUnitE); pUnitT = pUnit->pT; fComp = (int)(pUnitER != pUnitE); // count the amount of weight to reduce the APL of the children of this node if ( p->fMinApl ) AplWeightHalf = 0.5 * pUnit->Weight; // determine what situation is this if ( pUnitER->lev == lev1 && pUnitT->lev == lev1 ) { if ( fComp == 0 ) { // before after // // . // 0 / \ 1 0 / \ 1 . // / \ / \ . // / \ / \ . // . // 0 / \ 1 0 / \ 1 0 / \ 1 0 / \ 1 . // / \ / \ / \ / \ . // / \ / \ / \ / \ . // F0 F1 F2 F3 F0 F2 F1 F3 . // pNew1E pNew1T pNew2E pNew2T // pNew1E = pUnitE->pE; // F0 pNew1T = pUnitT->pE; // F2 pNew2E = pUnitE->pT; // F1 pNew2T = pUnitT->pT; // F3 } else { // before after // // . // 0 . \ 1 0 / \ 1 . // . \ / \ . // . \ / \ . // . // 0 / \ 1 0 / \ 1 0 . \ 1 0 . \ 1 . // / \ / \ . \ . \ . // / \ / \ . \ . \ . // F0 F1 F2 F3 F0 F2 F1 F3 . // pNew1E pNew1T pNew2E pNew2T // pNew1E = Unit_Not(pUnitER->pE); // F0 pNew1T = pUnitT->pE; // F2 pNew2E = Unit_Not(pUnitER->pT); // F1 pNew2T = pUnitT->pT; // F3 } // subtract ref counters - on the level P2 pUnitER->n--; pUnitT->n--; // mark the change in the APL weights if ( p->fMinApl ) { pUnitER->Weight -= AplWeightHalf; pUnitT->Weight -= AplWeightHalf; AplWeightAfter -= pUnit->Weight; } } else if ( pUnitER->lev == lev1 ) { if ( fComp == 0 ) { // before after // // . // 0 / \ 1 0 / \ 1 . // / \ / \ . // / \ / \ . // \ . // 0 / \ 1 \ 0 / \ 1 0 / \ 1 . // / \ \ / \ / \ . // / \ \ / \ / \ . // F0 F1 F3 F0 F3 F1 F3 . // pNew1E pNew1T pNew2E pNew2T // pNew1E = pUnitER->pE; // F0 pNew1T = pUnitT; // F3 pNew2E = pUnitER->pT; // F1 pNew2T = pUnitT; // F3 } else { // before after // // . // 0 . \ 1 0 / \ 1 . // . \ / \ . // . \ / \ . // \ . // 0 / \ 1 \ 0 . \ 1 0 . \ 1 . // / \ \ . \ . \ . // / \ \ . \ . \ . // F0 F1 F3 F0 F3 F1 F3 . // pNew1E pNew1T pNew2E pNew2T // pNew1E = Unit_Not(pUnitER->pE); // F0 pNew1T = pUnitT; // F3 pNew2E = Unit_Not(pUnitER->pT); // F1 pNew2T = pUnitT; // F3 } // subtract ref counter - on the level P2 pUnitER->n--; // subtract ref counter - on other levels pUnitT->n--; /// // mark the change in the APL weights if ( p->fMinApl ) { pUnitER->Weight -= AplWeightHalf; AplWeightAfter -= AplWeightHalf; } } else if ( pUnitT->lev == lev1 ) { // before after // // . // 0 / \ 1 0 / \ 1 . // / \ / \ . // / \ / \ . // / . // / 0 / \ 1 0 / \ 1 0 / \ 1 . // / / \ / \ / \ . // / / \ / \ / \ . // F0 F2 F3 F0 F2 F0 F3 . // pNew1E pNew1T pNew2E pNew2T // pNew1E = pUnitE; // F0 pNew1T = pUnitT->pE; // F2 pNew2E = pUnitE; // F0 pNew2T = pUnitT->pT; // F3 // subtract incoming edge counter - on the level P2 pUnitT->n--; // subtract ref counter - on other levels pUnitER->n--; /// // mark the change in the APL weights if ( p->fMinApl ) { pUnitT->Weight -= AplWeightHalf; AplWeightAfter -= AplWeightHalf; } } else { assert( 0 ); // should never happen } // consider all the cases except the last one if ( pNew1E == pNew1T ) { pNewPlane20 = pNew1T; if ( p->fMinWidth ) { // update the cofactors's top ref if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { pNew1T->TopRefNew = lev1; if ( pNew1T->Sign != p->nSwaps ) { pNew1T->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pNew1T; } } } } else { // pNew1T can be complemented fCompT = Cudd_IsComplement(pNew1T); if ( fCompT ) { pNew1E = Unit_Not(pNew1E); pNew1T = Unit_Not(pNew1T); } // check the hash-table fFound = 0; for ( HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T ) { // the entry is present // assign this entry pNewPlane20 = p->HTable[HKey].Arg3; assert( pNewPlane20->lev == lev1 ); fFound = 1; p->HashSuccess++; break; } if ( !fFound ) { // create the new entry pNewPlane20 = reoUnitsGetNextUnit( p ); // increments the unit counter pNewPlane20->pE = pNew1E; pNewPlane20->pT = pNew1T; pNewPlane20->n = 0; // ref will be added later pNewPlane20->lev = lev1; if ( p->fMinWidth ) { pNewPlane20->TopRef = lev1; pNewPlane20->Sign = 0; } // set the weight of this node if ( p->fMinApl ) pNewPlane20->Weight = 0.0; // increment ref counters of children pNew1ER = Unit_Regular(pNew1E); pNew1ER->n++; // pNew1T->n++; // // insert into the data structure AddToLinkedList( ppListNew1, pNewPlane20 ); // add this entry to cache assert( p->HTable[HKey].Sign != p->Signature ); p->HTable[HKey].Sign = p->Signature; p->HTable[HKey].Arg1 = pNew1E; p->HTable[HKey].Arg2 = pNew1T; p->HTable[HKey].Arg3 = pNewPlane20; nNodesUnrefAdded++; if ( p->fMinWidth ) { // update the cofactors's top ref if ( pNew1ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { if ( pNew1ER->Sign != p->nSwaps ) { pNew1ER->TopRefNew = lev2; if ( pNew1ER->Sign != p->nSwaps ) { pNew1ER->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pNew1ER; } } // otherwise the level is already set correctly else { assert( pNew1ER->TopRefNew == lev1 || pNew1ER->TopRefNew == lev2 ); } } // update the cofactors's top ref if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { if ( pNew1T->Sign != p->nSwaps ) { pNew1T->TopRefNew = lev2; if ( pNew1T->Sign != p->nSwaps ) { pNew1T->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pNew1T; } } // otherwise the level is already set correctly else { assert( pNew1T->TopRefNew == lev1 || pNew1T->TopRefNew == lev2 ); } } } } if ( p->fMinApl ) { // increment the weight of this node pNewPlane20->Weight += AplWeightHalf; // mark the change in the APL weight AplWeightAfter += AplWeightHalf; // update the total weight of this level AplWeightTotalLev1 += AplWeightHalf; } if ( fCompT ) pNewPlane20 = Unit_Not(pNewPlane20); } if ( pNew2E == pNew2T ) { pNewPlane21 = pNew2T; if ( p->fMinWidth ) { // update the cofactors's top ref if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { pNew2T->TopRefNew = lev1; if ( pNew2T->Sign != p->nSwaps ) { pNew2T->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pNew2T; } } } } else { assert( !Cudd_IsComplement(pNew2T) ); // check the hash-table fFound = 0; for ( HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T ) { // the entry is present // assign this entry pNewPlane21 = p->HTable[HKey].Arg3; assert( pNewPlane21->lev == lev1 ); fFound = 1; p->HashSuccess++; break; } if ( !fFound ) { // create the new entry pNewPlane21 = reoUnitsGetNextUnit( p ); // increments the unit counter pNewPlane21->pE = pNew2E; pNewPlane21->pT = pNew2T; pNewPlane21->n = 0; // ref will be added later pNewPlane21->lev = lev1; if ( p->fMinWidth ) { pNewPlane21->TopRef = lev1; pNewPlane21->Sign = 0; } // set the weight of this node if ( p->fMinApl ) pNewPlane21->Weight = 0.0; // increment ref counters of children pNew2ER = Unit_Regular(pNew2E); pNew2ER->n++; // pNew2T->n++; // // insert into the data structure // reoUnitsAddUnitToPlane( &P2new, pNewPlane21 ); AddToLinkedList( ppListNew1, pNewPlane21 ); // add this entry to cache assert( p->HTable[HKey].Sign != p->Signature ); p->HTable[HKey].Sign = p->Signature; p->HTable[HKey].Arg1 = pNew2E; p->HTable[HKey].Arg2 = pNew2T; p->HTable[HKey].Arg3 = pNewPlane21; nNodesUnrefAdded++; if ( p->fMinWidth ) { // update the cofactors's top ref if ( pNew2ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { if ( pNew2ER->Sign != p->nSwaps ) { pNew2ER->TopRefNew = lev2; if ( pNew2ER->Sign != p->nSwaps ) { pNew2ER->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pNew2ER; } } // otherwise the level is already set correctly else { assert( pNew2ER->TopRefNew == lev1 || pNew2ER->TopRefNew == lev2 ); } } // update the cofactors's top ref if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { if ( pNew2T->Sign != p->nSwaps ) { pNew2T->TopRefNew = lev2; if ( pNew2T->Sign != p->nSwaps ) { pNew2T->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pNew2T; } } // otherwise the level is already set correctly else { assert( pNew2T->TopRefNew == lev1 || pNew2T->TopRefNew == lev2 ); } } } } if ( p->fMinApl ) { // increment the weight of this node pNewPlane21->Weight += AplWeightHalf; // mark the change in the APL weight AplWeightAfter += AplWeightHalf; // update the total weight of this level AplWeightTotalLev1 += AplWeightHalf; } } // in all cases, the node will be added to the plane-1 // this should be the same node (pUnit) as was originally there // because it is referenced by the above nodes assert( !Cudd_IsComplement(pNewPlane21) ); // should be the case; otherwise reordering is not a local operation pUnit->pE = pNewPlane20; pUnit->pT = pNewPlane21; assert( pUnit->lev == lev0 ); // reference counter remains the same; the APL weight remains the same // increment ref counters of children pNewPlane20R = Unit_Regular(pNewPlane20); pNewPlane20R->n++; /// pNewPlane21->n++; /// // insert into the data structure AddToLinkedList( ppListNew0, pUnit ); if ( p->fMinApl ) AplWeightTotalLev0 += pUnit->Weight; } // (3) walk through the old lower level, find those nodes whose ref counters are not zero, // and move them to the new uppoer level, free other nodes for ( pLoop = pListOld1; pLoop; ) { pUnit = pLoop; pLoop = pLoop->Next; if ( pUnit->n ) { assert( !p->fMinApl || pUnit->Weight > 0.0 ); // the node should be added to the new level // no need to check the hash table pUnit->lev = lev0; AddToLinkedList( ppListNew0, pUnit ); if ( p->fMinApl ) AplWeightTotalLev0 += pUnit->Weight; nNodesDownMovedUp++; if ( p->fMinWidth ) { pUnitER = Unit_Regular(pUnit->pE); pUnitT = pUnit->pT; // update the cofactors's top ref if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { pUnitER->TopRefNew = lev1; if ( pUnitER->Sign != p->nSwaps ) { pUnitER->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pUnitER; } } if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels { pUnitT->TopRefNew = lev1; if ( pUnitT->Sign != p->nSwaps ) { pUnitT->Sign = p->nSwaps; // set the current signature p->pWidthCofs[ nWidthCofs++ ] = pUnitT; } } } } else { assert( !p->fMinApl || pUnit->Weight == 0.0 ); // decrement reference counters of children pUnitER = Unit_Regular(pUnit->pE); pUnitT = pUnit->pT; pUnitER->n--; /// pUnitT->n--; /// // the node should be thrown away reoUnitsRecycleUnit( p, pUnit ); nNodesUnrefRemoved++; } } finish: // attach the new levels to the planes p->pPlanes[lev0].pHead = pListNew0; p->pPlanes[lev1].pHead = pListNew1; // swap the sift status temp = p->pPlanes[lev0].fSifted; p->pPlanes[lev0].fSifted = p->pPlanes[lev1].fSifted; p->pPlanes[lev1].fSifted = temp; // swap variables in the variable map if ( p->pOrderInt ) { temp = p->pOrderInt[lev0]; p->pOrderInt[lev0] = p->pOrderInt[lev1]; p->pOrderInt[lev1] = temp; } // adjust the node profile p->pPlanes[lev0].statsNodes -= (nNodesUpMovedDown - nNodesDownMovedUp); p->pPlanes[lev1].statsNodes -= (nNodesDownMovedUp - nNodesUpMovedDown) + nNodesUnrefRemoved - nNodesUnrefAdded; p->nNodesCur -= nNodesUnrefRemoved - nNodesUnrefAdded; // adjust the node profile on this level if ( p->fMinWidth ) { for ( c = 0; c < nWidthCofs; c++ ) { if ( p->pWidthCofs[c]->TopRefNew < p->pWidthCofs[c]->TopRef ) { p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; nWidthReduction--; } else if ( p->pWidthCofs[c]->TopRefNew > p->pWidthCofs[c]->TopRef ) { p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; nWidthReduction++; } } // verify that the profile is okay reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); // compute the total gain in terms of width nCostGain = (nNodesDownMovedUp - nNodesUpMovedDown + nNodesUnrefRemoved - nNodesUnrefAdded) + nWidthReduction; // adjust the width on this level p->pPlanes[lev1].statsWidth -= (int)nCostGain; // set the cost p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsWidth; } else if ( p->fMinApl ) { // compute the total gain in terms of APL nCostGain = AplWeightPrev - AplWeightAfter; // make sure that the ALP is updated correctly // assert( p->pPlanes[lev0].statsCost + p->pPlanes[lev1].statsCost - nCostGain == // AplWeightTotalLev0 + AplWeightTotalLev1 ); // adjust the profile p->pPlanes[lev0].statsApl = AplWeightTotalLev0; p->pPlanes[lev1].statsApl = AplWeightTotalLev1; // set the cost p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsApl; p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsApl; } else { // compute the total gain in terms of the number of nodes nCostGain = nNodesUnrefRemoved - nNodesUnrefAdded; // adjust the profile (adjusted above) // set the cost p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsNodes; p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsNodes; } return nCostGain; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoTest.c000066400000000000000000000203031300674244400231410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoTest.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Various testing procedures (may be outdated).] Author [Alan Mishchenko ] Affiliation [ECE Department. Portland State University, Portland, Oregon.] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoTest.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reorders the DD using REO and CUDD.] Description [This function can be used to test the performance of the reordering package.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderTest( DdManager * dd, DdNode * Func ) { reo_man * pReo; DdNode * Temp, * Temp1; int pOrder[1000]; pReo = Extra_ReorderInit( 100, 100 ); //Extra_DumpDot( dd, &Func, 1, "beforReo.dot", 0 ); Temp = Extra_Reorder( pReo, dd, Func, pOrder ); Cudd_Ref( Temp ); //Extra_DumpDot( dd, &Temp, 1, "afterReo.dot", 0 ); Temp1 = Extra_ReorderCudd(dd, Func, NULL ); Cudd_Ref( Temp1 ); printf( "Initial = %d. Final = %d. Cudd = %d.\n", Cudd_DagSize(Func), Cudd_DagSize(Temp), Cudd_DagSize(Temp1) ); Cudd_RecursiveDeref( dd, Temp1 ); Cudd_RecursiveDeref( dd, Temp ); Extra_ReorderQuit( pReo ); } /**Function************************************************************* Synopsis [Reorders the DD using REO and CUDD.] Description [This function can be used to test the performance of the reordering package.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ReorderTestArray( DdManager * dd, DdNode * Funcs[], int nFuncs ) { reo_man * pReo; DdNode * FuncsRes[1000]; int pOrder[1000]; int i; pReo = Extra_ReorderInit( 100, 100 ); Extra_ReorderArray( pReo, dd, Funcs, FuncsRes, nFuncs, pOrder ); Extra_ReorderQuit( pReo ); printf( "Initial = %d. Final = %d.\n", Cudd_SharingSize(Funcs,nFuncs), Cudd_SharingSize(FuncsRes,nFuncs) ); for ( i = 0; i < nFuncs; i++ ) Cudd_RecursiveDeref( dd, FuncsRes[i] ); } /**Function************************************************************* Synopsis [Reorders the DD using CUDD package.] Description [Transfers the DD into a temporary manager in such a way that the level correspondence is preserved. Reorders the manager and transfers the DD back into the original manager using the topmost levels of the manager, in such a way that the ordering of levels is preserved. The resulting permutation is returned in the array given by the user.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] ) { static DdManager * ddReorder = NULL; static int * Permute = NULL; static int * PermuteReo1 = NULL; static int * PermuteReo2 = NULL; DdNode * aFuncReorder, * aFuncNew; int lev, var; // start the reordering manager if ( ddReorder == NULL ) { Permute = ABC_ALLOC( int, dd->size ); PermuteReo1 = ABC_ALLOC( int, dd->size ); PermuteReo2 = ABC_ALLOC( int, dd->size ); ddReorder = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynDisable(ddReorder); } // determine the permutation of variable to make sure that var order in bFunc // will not change when this function is transfered into the new manager for ( lev = 0; lev < dd->size; lev++ ) { Permute[ dd->invperm[lev] ] = ddReorder->invperm[lev]; PermuteReo1[ ddReorder->invperm[lev] ] = dd->invperm[lev]; } // transfer this function into the new manager in such a way that ordering of vars does not change aFuncReorder = Extra_TransferPermute( dd, ddReorder, aFunc, Permute ); Cudd_Ref( aFuncReorder ); // assert( Cudd_DagSize(aFunc) == Cudd_DagSize(aFuncReorder) ); // perform the reordering printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) ); Cudd_ReduceHeap( ddReorder, CUDD_REORDER_SYMM_SIFT, 1 ); printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) ); // determine the reverse variable permutation for ( lev = 0; lev < dd->size; lev++ ) { Permute[ ddReorder->invperm[lev] ] = dd->invperm[lev]; PermuteReo2[ dd->invperm[lev] ] = ddReorder->invperm[lev]; } // transfer this function into the new manager in such a way that ordering of vars does not change aFuncNew = Extra_TransferPermute( ddReorder, dd, aFuncReorder, Permute ); Cudd_Ref( aFuncNew ); // assert( Cudd_DagSize(aFuncNew) == Cudd_DagSize(aFuncReorder) ); Cudd_RecursiveDeref( ddReorder, aFuncReorder ); // derive the resulting variable ordering if ( pPermuteReo ) for ( var = 0; var < dd->size; var++ ) pPermuteReo[var] = PermuteReo1[ PermuteReo2[var] ]; Cudd_Deref( aFuncNew ); return aFuncNew; } /**Function************************************************************* Synopsis [] Description [Transfers the BDD into another manager minimizes it and returns the min number of nodes; disposes of the BDD in the new manager. Useful for debugging or comparing the performance of other reordering procedures.] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_bddReorderTest( DdManager * dd, DdNode * bF ) { static DdManager * s_ddmin; DdNode * bFmin; int nNodes; // abctime clk1; if ( s_ddmin == NULL ) s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); // Cudd_ShuffleHeap( s_ddmin, dd->invperm ); // clk1 = Abc_Clock(); bFmin = Cudd_bddTransfer( dd, s_ddmin, bF ); Cudd_Ref( bFmin ); Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1); // Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); nNodes = Cudd_DagSize( bFmin ); Cudd_RecursiveDeref( s_ddmin, bFmin ); // printf( "Classical variable reordering time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); return nNodes; } /**Function************************************************************* Synopsis [] Description [Transfers the ADD into another manager minimizes it and returns the min number of nodes; disposes of the BDD in the new manager. Useful for debugging or comparing the performance of other reordering procedures.] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_addReorderTest( DdManager * dd, DdNode * aF ) { static DdManager * s_ddmin; DdNode * bF; DdNode * bFmin; DdNode * aFmin; int nNodesBeg; int nNodesEnd; abctime clk1; if ( s_ddmin == NULL ) s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); // Cudd_ShuffleHeap( s_ddmin, dd->invperm ); clk1 = Abc_Clock(); bF = Cudd_addBddPattern( dd, aF ); Cudd_Ref( bF ); bFmin = Cudd_bddTransfer( dd, s_ddmin, bF ); Cudd_Ref( bFmin ); Cudd_RecursiveDeref( dd, bF ); aFmin = Cudd_BddToAdd( s_ddmin, bFmin ); Cudd_Ref( aFmin ); Cudd_RecursiveDeref( s_ddmin, bFmin ); nNodesBeg = Cudd_DagSize( aFmin ); Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1); // Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); nNodesEnd = Cudd_DagSize( aFmin ); Cudd_RecursiveDeref( s_ddmin, aFmin ); printf( "Classical reordering of ADDs: Before = %d. After = %d.\n", nNodesBeg, nNodesEnd ); printf( "Classical variable reordering time = %.2f sec\n", (float)(Abc_Clock() - clk1)/(float)(CLOCKS_PER_SEC) ); return nNodesEnd; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoTransfer.c000066400000000000000000000141751300674244400240200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoTransfer.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Transfering a DD from the CUDD manager into REO"s internal data structures and back.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoTransfer.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transfers the DD into the internal reordering data structure.] Description [It is important that the hash table is lossless.] SideEffects [] SeeAlso [] ***********************************************************************/ reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ) { DdManager * dd = p->dd; reo_unit * pUnit; int HKey = -1; // Suppress "might be used uninitialized" int fComp; fComp = Cudd_IsComplement(F); F = Cudd_Regular(F); // check the hash-table if ( F->ref != 1 ) { // search cache - use linear probing for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) if ( p->HTable[HKey].Arg1 == (reo_unit *)F ) { pUnit = p->HTable[HKey].Arg2; assert( pUnit ); // increment the edge counter pUnit->n++; return Unit_NotCond( pUnit, fComp ); } } // the entry in not found in the cache // create a new entry pUnit = reoUnitsGetNextUnit( p ); pUnit->n = 1; if ( cuddIsConstant(F) ) { pUnit->lev = REO_CONST_LEVEL; pUnit->pE = (reo_unit*)(ABC_PTRUINT_T)(cuddV(F)); pUnit->pT = NULL; // check if the diagram that is being reordering has complement edges if ( F != dd->one ) p->fThisIsAdd = 1; // insert the unit into the corresponding plane reoUnitsAddUnitToPlane( &(p->pPlanes[p->nSupp]), pUnit ); // increments the unit counter } else { pUnit->lev = p->pMapToPlanes[F->index]; pUnit->pE = reoTransferNodesToUnits_rec( p, cuddE(F) ); pUnit->pT = reoTransferNodesToUnits_rec( p, cuddT(F) ); // insert the unit into the corresponding plane reoUnitsAddUnitToPlane( &(p->pPlanes[pUnit->lev]), pUnit ); // increments the unit counter } // add to the hash table if ( F->ref != 1 ) { // the next free entry is already found - it is pointed to by HKey // while we traversed the diagram, the hash entry to which HKey points, // might have been used. Make sure that its signature is different. for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); p->HTable[HKey].Sign = p->Signature; p->HTable[HKey].Arg1 = (reo_unit *)F; p->HTable[HKey].Arg2 = pUnit; } // increment the counter of nodes p->nNodesCur++; return Unit_NotCond( pUnit, fComp ); } /**Function************************************************************* Synopsis [Creates the DD from the internal reordering data structure.] Description [It is important that the hash table is lossless.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) { DdManager * dd = p->dd; DdNode * bRes, * E, * T; int HKey = -1; // Suppress "might be used uninitialized" int fComp; fComp = Cudd_IsComplement(pUnit); pUnit = Unit_Regular(pUnit); // check the hash-table if ( pUnit->n != 1 ) { for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) if ( p->HTable[HKey].Arg1 == pUnit ) { bRes = (DdNode*) p->HTable[HKey].Arg2; assert( bRes ); return Cudd_NotCond( bRes, fComp ); } } // treat the case of constants if ( Unit_IsConstant(pUnit) ) { bRes = cuddUniqueConst( dd, ((double)((int)(ABC_PTRUINT_T)(pUnit->pE))) ); cuddRef( bRes ); } else { // split and recur on children of this node E = reoTransferUnitsToNodes_rec( p, pUnit->pE ); if ( E == NULL ) return NULL; cuddRef(E); T = reoTransferUnitsToNodes_rec( p, pUnit->pT ); if ( T == NULL ) { Cudd_RecursiveDeref(dd, E); return NULL; } cuddRef(T); // consider the case when Res0 and Res1 are the same node assert( E != T ); assert( !Cudd_IsComplement(T) ); bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,E); Cudd_RecursiveDeref(dd,T); return NULL; } cuddRef( bRes ); cuddDeref( E ); cuddDeref( T ); } // do not keep the result if the ref count is only 1, since it will not be visited again if ( pUnit->n != 1 ) { // while we traversed the diagram, the hash entry to which HKey points, // might have been used. Make sure that its signature is different. for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); p->HTable[HKey].Sign = p->Signature; p->HTable[HKey].Arg1 = pUnit; p->HTable[HKey].Arg2 = (reo_unit *)bRes; // add the DD to the referenced DD list in order to be able to store it in cache p->pRefNodes[p->nRefNodes++] = bRes; Cudd_Ref( bRes ); // no need to do this, because the garbage collection will not take bRes away // it is held by the diagram in the making } // increment the counter of nodes p->nNodesCur++; cuddDeref( bRes ); return Cudd_NotCond( bRes, fComp ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bdd/reo/reoUnits.c000066400000000000000000000115021300674244400233250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [reoUnits.c] PackageName [REO: A specialized DD reordering engine.] Synopsis [Procedures which support internal data structures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 15, 2002.] Revision [$Id: reoUnits.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include "reo.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void reoUnitsAddToFreeUnitList( reo_man * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Extract the next unit from the free unit list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ reo_unit * reoUnitsGetNextUnit(reo_man * p ) { reo_unit * pUnit; // check there are stil units to extract if ( p->pUnitFreeList == NULL ) reoUnitsAddToFreeUnitList( p ); // extract the next unit from the linked list pUnit = p->pUnitFreeList; p->pUnitFreeList = pUnit->Next; p->nUnitsUsed++; return pUnit; } /**Function************************************************************* Synopsis [Returns the unit to the free unit list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit ) { pUnit->Next = p->pUnitFreeList; p->pUnitFreeList = pUnit; p->nUnitsUsed--; } /**Function************************************************************* Synopsis [Returns the list of units to the free unit list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane ) { reo_unit * pUnit; reo_unit * pTail = NULL; // Suppress "might be used uninitialized" if ( pPlane->pHead == NULL ) return; // find the tail for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) pTail = pUnit; pTail->Next = p->pUnitFreeList; p->pUnitFreeList = pPlane->pHead; memset( pPlane, 0, sizeof(reo_plane) ); // pPlane->pHead = NULL; } /**Function************************************************************* Synopsis [Stops the unit dispenser.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoUnitsStopDispenser( reo_man * p ) { int i; for ( i = 0; i < p->nMemChunks; i++ ) ABC_FREE( p->pMemChunks[i] ); // printf("\nThe number of chunks used is %d, each of them %d units\n", p->nMemChunks, REO_CHUNK_SIZE ); p->nMemChunks = 0; } /**Function************************************************************* Synopsis [Adds one unit to the list of units which constitutes the plane.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit ) { if ( pPlane->pHead == NULL ) { pPlane->pHead = pUnit; pUnit->Next = NULL; } else { pUnit->Next = pPlane->pHead; pPlane->pHead = pUnit; } pPlane->statsNodes++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoUnitsAddToFreeUnitList( reo_man * p ) { int c; // check that we still have chunks left if ( p->nMemChunks == p->nMemChunksAlloc ) { printf( "reoUnitsAddToFreeUnitList(): Memory manager ran out of memory!\n" ); fflush( stdout ); return; } // allocate the next chunk assert( p->pUnitFreeList == NULL ); p->pUnitFreeList = ABC_ALLOC( reo_unit, REO_CHUNK_SIZE ); // split chunks into list-connected units for ( c = 0; c < REO_CHUNK_SIZE-1; c++ ) (p->pUnitFreeList + c)->Next = p->pUnitFreeList + c + 1; // set the last pointer to NULL (p->pUnitFreeList + REO_CHUNK_SIZE-1)->Next = NULL; // add the chunk to the array of chunks p->pMemChunks[p->nMemChunks++] = p->pUnitFreeList; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/000077500000000000000000000000001300674244400207675ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/000077500000000000000000000000001300674244400215175ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/bdc.h000066400000000000000000000103641300674244400224240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bdc.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table-based bi-decomposition engine.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 30, 2007.] Revision [$Id: bdc.h,v 1.00 2007/01/30 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__bdc__bdc_h #define ABC__aig__bdc__bdc_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Bdc_Fun_t_ Bdc_Fun_t; typedef struct Bdc_Man_t_ Bdc_Man_t; typedef struct Bdc_Par_t_ Bdc_Par_t; struct Bdc_Par_t_ { // general parameters int nVarsMax; // the maximum support int fVerbose; // enable basic stats int fVeryVerbose; // enable detailed stats }; // working with complemented attributes of objects static inline int Bdc_IsComplement( Bdc_Fun_t * p ) { return (int)((ABC_PTRUINT_T)p & (ABC_PTRUINT_T)01); } static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p & ~(ABC_PTRUINT_T)01); } static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)01); } static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c ) { return (Bdc_Fun_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)(c!=0)); } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== bdcCore.c ==========================================================*/ extern Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ); extern void Bdc_ManFree( Bdc_Man_t * p ); extern void Bdc_ManDecPrint( Bdc_Man_t * p ); extern int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax ); extern Bdc_Fun_t * Bdc_ManFunc( Bdc_Man_t * p, int i ); extern Bdc_Fun_t * Bdc_ManRoot( Bdc_Man_t * p ); extern int Bdc_ManNodeNum( Bdc_Man_t * p ); extern int Bdc_ManAndNum( Bdc_Man_t * p ); extern Bdc_Fun_t * Bdc_FuncFanin0( Bdc_Fun_t * p ); extern Bdc_Fun_t * Bdc_FuncFanin1( Bdc_Fun_t * p ); extern void * Bdc_FuncCopy( Bdc_Fun_t * p ); extern int Bdc_FuncCopyInt( Bdc_Fun_t * p ); extern void Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy ); extern void Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy ); /*=== working with saved copies ==========================================*/ static inline int Bdc_FunObjCopy( Bdc_Fun_t * pObj ) { return Abc_LitNotCond( Bdc_FuncCopyInt(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } static inline int Bdc_FunFanin0Copy( Bdc_Fun_t * pObj ) { return Bdc_FunObjCopy( Bdc_FuncFanin0(pObj) ); } static inline int Bdc_FunFanin1Copy( Bdc_Fun_t * pObj ) { return Bdc_FunObjCopy( Bdc_FuncFanin1(pObj) ); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/bdcCore.c000066400000000000000000000277111300674244400232340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bdcCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table-based bi-decomposition engine.] Synopsis [The gateway to bi-decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 30, 2007.] Revision [$Id: bdcCore.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bdcInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Accessing contents of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bdc_Fun_t * Bdc_ManFunc( Bdc_Man_t * p, int i ) { return Bdc_FunWithId(p, i); } Bdc_Fun_t * Bdc_ManRoot( Bdc_Man_t * p ) { return p->pRoot; } int Bdc_ManNodeNum( Bdc_Man_t * p ) { return p->nNodes; } int Bdc_ManAndNum( Bdc_Man_t * p ) { return p->nNodes-p->nVars-1;} Bdc_Fun_t * Bdc_FuncFanin0( Bdc_Fun_t * p ) { return p->pFan0; } Bdc_Fun_t * Bdc_FuncFanin1( Bdc_Fun_t * p ) { return p->pFan1; } void * Bdc_FuncCopy( Bdc_Fun_t * p ) { return p->pCopy; } int Bdc_FuncCopyInt( Bdc_Fun_t * p ) { return p->iCopy; } void Bdc_FuncSetCopy( Bdc_Fun_t * p, void * pCopy ) { p->pCopy = pCopy; } void Bdc_FuncSetCopyInt( Bdc_Fun_t * p, int iCopy ) { p->iCopy = iCopy; } /**Function************************************************************* Synopsis [Allocate resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ) { Bdc_Man_t * p; p = ABC_ALLOC( Bdc_Man_t, 1 ); memset( p, 0, sizeof(Bdc_Man_t) ); assert( pPars->nVarsMax > 1 && pPars->nVarsMax < 16 ); p->pPars = pPars; p->nWords = Kit_TruthWordNum( pPars->nVarsMax ); p->nDivsLimit = 200; // internal nodes p->nNodesAlloc = 512; p->pNodes = ABC_ALLOC( Bdc_Fun_t, p->nNodesAlloc ); // memory p->vMemory = Vec_IntStart( 8 * p->nWords * p->nNodesAlloc ); Vec_IntClear(p->vMemory); // set up hash table p->nTableSize = (1 << p->pPars->nVarsMax); p->pTable = ABC_ALLOC( Bdc_Fun_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Bdc_Fun_t *) * p->nTableSize ); p->vSpots = Vec_IntAlloc( 256 ); // truth tables p->vTruths = Vec_PtrAllocTruthTables( p->pPars->nVarsMax ); p->puTemp1 = ABC_ALLOC( unsigned, 4 * p->nWords ); p->puTemp2 = p->puTemp1 + p->nWords; p->puTemp3 = p->puTemp2 + p->nWords; p->puTemp4 = p->puTemp3 + p->nWords; // start the internal ISFs p->pIsfOL = &p->IsfOL; Bdc_IsfStart( p, p->pIsfOL ); p->pIsfOR = &p->IsfOR; Bdc_IsfStart( p, p->pIsfOR ); p->pIsfAL = &p->IsfAL; Bdc_IsfStart( p, p->pIsfAL ); p->pIsfAR = &p->IsfAR; Bdc_IsfStart( p, p->pIsfAR ); return p; } /**Function************************************************************* Synopsis [Deallocate resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_ManFree( Bdc_Man_t * p ) { if ( p->pPars->fVerbose ) { printf( "Bi-decomposition stats: Calls = %d. Nodes = %d. Reuse = %d.\n", p->numCalls, p->numNodes, p->numReuse ); printf( "ANDs = %d. ORs = %d. Weak = %d. Muxes = %d. Memory = %.2f K\n", p->numAnds, p->numOrs, p->numWeaks, p->numMuxes, 4.0 * Vec_IntSize(p->vMemory) / (1<<10) ); ABC_PRT( "Cache", p->timeCache ); ABC_PRT( "Check", p->timeCheck ); ABC_PRT( "Muxes", p->timeMuxes ); ABC_PRT( "Supps", p->timeSupps ); ABC_PRT( "TOTAL", p->timeTotal ); } Vec_IntFree( p->vMemory ); Vec_IntFree( p->vSpots ); Vec_PtrFree( p->vTruths ); ABC_FREE( p->puTemp1 ); ABC_FREE( p->pNodes ); ABC_FREE( p->pTable ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Clears the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs ) { unsigned * puTruth; Bdc_Fun_t * pNode; int i; Bdc_TableClear( p ); Vec_IntClear( p->vMemory ); // add constant 1 and elementary vars p->nNodes = 0; p->nNodesNew = - 1 - p->nVars - (vDivs? Vec_PtrSize(vDivs) : 0); // add constant 1 pNode = Bdc_FunNew( p ); pNode->Type = BDC_TYPE_CONST1; pNode->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); Kit_TruthFill( pNode->puFunc, p->nVars ); pNode->uSupp = 0; Bdc_TableAdd( p, pNode ); // add variables for ( i = 0; i < p->nVars; i++ ) { pNode = Bdc_FunNew( p ); pNode->Type = BDC_TYPE_PI; pNode->puFunc = (unsigned *)Vec_PtrEntry( p->vTruths, i ); pNode->uSupp = (1 << i); Bdc_TableAdd( p, pNode ); } // add the divisors if ( vDivs ) Vec_PtrForEachEntry( unsigned *, vDivs, puTruth, i ) { pNode = Bdc_FunNew( p ); pNode->Type = BDC_TYPE_PI; pNode->puFunc = puTruth; pNode->uSupp = Kit_TruthSupport( puTruth, p->nVars ); Bdc_TableAdd( p, pNode ); if ( i == p->nDivsLimit ) break; } assert( p->nNodesNew == 0 ); } /**Function************************************************************* Synopsis [Prints bi-decomposition in a simple format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_ManDecPrintSimple( Bdc_Man_t * p ) { Bdc_Fun_t * pNode; int i; printf( " 0 : Const 1\n" ); for ( i = 1; i < p->nNodes; i++ ) { printf( " %d : ", i ); pNode = p->pNodes + i; if ( pNode->Type == BDC_TYPE_PI ) printf( "PI " ); else { printf( "%s%d &", Bdc_IsComplement(pNode->pFan0)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan0)) ); printf( " %s%d ", Bdc_IsComplement(pNode->pFan1)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan1)) ); } // Extra_PrintBinary( stdout, pNode->puFunc, (1<nVars) ); printf( "\n" ); } printf( "Root = %s%d.\n", Bdc_IsComplement(p->pRoot)? "-":"", Bdc_FunId(p,Bdc_Regular(p->pRoot)) ); } /**Function************************************************************* Synopsis [Prints bi-decomposition recursively.] Description [This procedure prints bi-decomposition as a factored form. In doing so, logic sharing, if present, will be replicated several times.] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_ManDecPrint_rec( Bdc_Man_t * p, Bdc_Fun_t * pNode ) { if ( pNode->Type == BDC_TYPE_PI ) printf( "%c", 'a' + Bdc_FunId(p,pNode) - 1 ); else if ( pNode->Type == BDC_TYPE_AND ) { Bdc_Fun_t * pNode0 = Bdc_FuncFanin0( pNode ); Bdc_Fun_t * pNode1 = Bdc_FuncFanin1( pNode ); if ( Bdc_IsComplement(pNode0) ) printf( "!" ); if ( Bdc_IsComplement(pNode0) && Bdc_Regular(pNode0)->Type != BDC_TYPE_PI ) printf( "(" ); Bdc_ManDecPrint_rec( p, Bdc_Regular(pNode0) ); if ( Bdc_IsComplement(pNode0) && Bdc_Regular(pNode0)->Type != BDC_TYPE_PI ) printf( ")" ); if ( Bdc_IsComplement(pNode1) ) printf( "!" ); if ( Bdc_IsComplement(pNode1) && Bdc_Regular(pNode1)->Type != BDC_TYPE_PI ) printf( "(" ); Bdc_ManDecPrint_rec( p, Bdc_Regular(pNode1) ); if ( Bdc_IsComplement(pNode1) && Bdc_Regular(pNode1)->Type != BDC_TYPE_PI ) printf( ")" ); } else assert( 0 ); } void Bdc_ManDecPrint( Bdc_Man_t * p ) { Bdc_Fun_t * pRoot = Bdc_Regular(p->pRoot); printf( "F = " ); if ( pRoot->Type == BDC_TYPE_CONST1 ) // constant 0 printf( "Constant %d", !Bdc_IsComplement(p->pRoot) ); else if ( pRoot->Type == BDC_TYPE_PI ) // literal printf( "%s%d", Bdc_IsComplement(p->pRoot) ? "!" : "", Bdc_FunId(p,pRoot)-1 ); else { if ( Bdc_IsComplement(p->pRoot) ) printf( "!(" ); Bdc_ManDecPrint_rec( p, pRoot ); if ( Bdc_IsComplement(p->pRoot) ) printf( ")" ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Performs decomposition of one function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax ) { Bdc_Isf_t Isf, * pIsf = &Isf; abctime clk = Abc_Clock(); assert( nVars <= p->pPars->nVarsMax ); // set current manager parameters p->nVars = nVars; p->nWords = Kit_TruthWordNum( nVars ); p->nNodesMax = nNodesMax; Bdc_ManPrepare( p, vDivs ); if ( puCare && Kit_TruthIsConst0( puCare, nVars ) ) { p->pRoot = Bdc_Not(p->pNodes); return 0; } // copy the function Bdc_IsfStart( p, pIsf ); if ( puCare ) { Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars ); Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars ); } else { Kit_TruthCopy( pIsf->puOn, puFunc, p->nVars ); Kit_TruthNot( pIsf->puOff, puFunc, p->nVars ); } Bdc_SuppMinimize( p, pIsf ); // call decomposition p->pRoot = Bdc_ManDecompose_rec( p, pIsf ); p->timeTotal += Abc_Clock() - clk; p->numCalls++; p->numNodes += p->nNodesNew; if ( p->pRoot == NULL ) return -1; if ( !Bdc_ManNodeVerify( p, pIsf, p->pRoot ) ) printf( "Bdc_ManDecompose(): Internal verification failed.\n" ); // assert( Bdc_ManNodeVerify( p, pIsf, p->pRoot ) ); return p->nNodesNew; } /**Function************************************************************* Synopsis [Performs decomposition of one function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_ManDecomposeTest( unsigned uTruth, int nVars ) { static int Counter = 0; static int Total = 0; Bdc_Par_t Pars = {0}, * pPars = &Pars; Bdc_Man_t * p; int RetValue; // unsigned uCare = ~0x888f888f; unsigned uCare = ~0; // unsigned uFunc = 0x88888888; // unsigned uFunc = 0xf888f888; // unsigned uFunc = 0x117e117e; // unsigned uFunc = 0x018b018b; unsigned uFunc = uTruth; pPars->nVarsMax = 8; p = Bdc_ManAlloc( pPars ); RetValue = Bdc_ManDecompose( p, &uFunc, &uCare, nVars, NULL, 1000 ); Total += RetValue; printf( "%5d : Nodes = %5d. Total = %8d.\n", ++Counter, RetValue, Total ); // Bdc_ManDecPrint( p ); Bdc_ManFree( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/bdcDec.c000066400000000000000000000617131300674244400230370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bdcDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table-based bi-decomposition engine.] Synopsis [Decomposition procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 30, 2007.] Revision [$Id: bdcDec.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bdcInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Minimizes the support of the ISF.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SuppMinimize2( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) { int v; abctime clk = 0; // Suppress "might be used uninitialized" if ( p->pPars->fVerbose ) clk = Abc_Clock(); // compute support pIsf->uSupp = Kit_TruthSupport( pIsf->puOn, p->nVars ) | Kit_TruthSupport( pIsf->puOff, p->nVars ); // go through the support variables for ( v = 0; v < p->nVars; v++ ) { if ( (pIsf->uSupp & (1 << v)) == 0 ) continue; Kit_TruthExistNew( p->puTemp1, pIsf->puOn, p->nVars, v ); Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, v ); if ( !Kit_TruthIsDisjoint( p->puTemp1, p->puTemp2, p->nVars ) ) continue; // if ( !Kit_TruthVarIsVacuous( pIsf->puOn, pIsf->puOff, p->nVars, v ) ) // continue; // remove the variable Kit_TruthCopy( pIsf->puOn, p->puTemp1, p->nVars ); Kit_TruthCopy( pIsf->puOff, p->puTemp2, p->nVars ); // Kit_TruthExist( pIsf->puOn, p->nVars, v ); // Kit_TruthExist( pIsf->puOff, p->nVars, v ); pIsf->uSupp &= ~(1 << v); } if ( p->pPars->fVerbose ) p->timeSupps += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Minimizes the support of the ISF.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) { int v; abctime clk = 0; // Suppress "might be used uninitialized" if ( p->pPars->fVerbose ) clk = Abc_Clock(); // go through the support variables pIsf->uSupp = 0; for ( v = 0; v < p->nVars; v++ ) { if ( !Kit_TruthVarInSupport( pIsf->puOn, p->nVars, v ) && !Kit_TruthVarInSupport( pIsf->puOff, p->nVars, v ) ) continue; if ( Kit_TruthVarIsVacuous( pIsf->puOn, pIsf->puOff, p->nVars, v ) ) { Kit_TruthExist( pIsf->puOn, p->nVars, v ); Kit_TruthExist( pIsf->puOff, p->nVars, v ); continue; } pIsf->uSupp |= (1 << v); } if ( p->pPars->fVerbose ) p->timeSupps += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Updates the ISF of the right after the left was decompoosed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, Bdc_Fun_t * pFunc0, Bdc_Type_t Type ) { unsigned * puTruth = p->puTemp1; // get the truth table of the left branch if ( Bdc_IsComplement(pFunc0) ) Kit_TruthNot( puTruth, Bdc_Regular(pFunc0)->puFunc, p->nVars ); else Kit_TruthCopy( puTruth, pFunc0->puFunc, p->nVars ); // split into parts if ( Type == BDC_TYPE_OR ) { // Right.Q = bdd_appex( Q, CompSpecLeftF, bddop_diff, setRightRes ); // Right.R = bdd_exist( R, setRightRes ); // if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q ); // if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R ); // pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Cudd_Not(CompSpecF), pL->V ); Cudd_Ref( pR->Q ); // pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R ); // assert( pR->R != b0 ); // return (int)( pR->Q == b0 ); Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars ); Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uUniq ); Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uUniq ); // assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); return Kit_TruthIsConst0(pIsfR->puOn, p->nVars); } else if ( Type == BDC_TYPE_AND ) { // Right.R = bdd_appex( R, CompSpecLeftF, bddop_and, setRightRes ); // Right.Q = bdd_exist( Q, setRightRes ); // if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q ); // if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R ); // pR->R = Cudd_bddAndAbstract( dd, pF->R, CompSpecF, pL->V ); Cudd_Ref( pR->R ); // pR->Q = Cudd_bddExistAbstract( dd, pF->Q, pL->V ); Cudd_Ref( pR->Q ); // assert( pR->Q != b0 ); // return (int)( pR->R == b0 ); Kit_TruthAnd( pIsfR->puOff, pIsf->puOff, puTruth, p->nVars ); Kit_TruthExistSet( pIsfR->puOff, pIsfR->puOff, p->nVars, pIsfL->uUniq ); Kit_TruthExistSet( pIsfR->puOn, pIsf->puOn, p->nVars, pIsfL->uUniq ); // assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) ); return Kit_TruthIsConst0(pIsfR->puOff, p->nVars); } return 0; } /**Function************************************************************* Synopsis [Checks existence of OR-bidecomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Bdc_DecomposeGetCost( Bdc_Man_t * p, int nLeftVars, int nRightVars ) { assert( nLeftVars > 0 ); assert( nRightVars > 0 ); // compute the decomposition coefficient if ( nLeftVars >= nRightVars ) return BDC_SCALE * (p->nVars * nRightVars + nLeftVars); else // if ( nLeftVars < nRightVars ) return BDC_SCALE * (p->nVars * nLeftVars + nRightVars); } /**Function************************************************************* Synopsis [Checks existence of weak OR-bidecomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_DecomposeFindInitialVarSet( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) { char pVars[16]; int v, nVars, Beg, End; assert( pIsfL->uSupp == 0 ); assert( pIsfR->uSupp == 0 ); // fill in the variables nVars = 0; for ( v = 0; v < p->nVars; v++ ) if ( pIsf->uSupp & (1 << v) ) pVars[nVars++] = v; // try variable pairs for ( Beg = 0; Beg < nVars; Beg++ ) { Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pVars[Beg] ); for ( End = nVars - 1; End > Beg; End-- ) { Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pVars[End] ); if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp1, p->puTemp2, p->nVars) ) { pIsfL->uUniq = (1 << pVars[Beg]); pIsfR->uUniq = (1 << pVars[End]); return 1; } } } return 0; } /**Function************************************************************* Synopsis [Checks existence of weak OR-bidecomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) { int v, VarCost; int VarBest = -1; // Suppress "might be used uninitialized" int Cost, VarCostBest = 0; for ( v = 0; v < p->nVars; v++ ) { if ( (pIsf->uSupp & (1 << v)) == 0 ) continue; // if ( (Q & !bdd_exist( R, VarSetXa )) != bddfalse ) // Exist = Cudd_bddExistAbstract( dd, pF->R, Var ); Cudd_Ref( Exist ); // if ( Cudd_bddIteConstant( dd, pF->Q, Cudd_Not(Exist), b0 ) != b0 ) Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v ); if ( !Kit_TruthIsImply( pIsf->puOn, p->puTemp1, p->nVars ) ) { // measure the cost of this variable // VarCost = bdd_satcountset( bdd_forall( Q, VarSetXa ), VarCube ); // Univ = Cudd_bddUnivAbstract( dd, pF->Q, Var ); Cudd_Ref( Univ ); // VarCost = Kit_TruthCountOnes( Univ, p->nVars ); // Cudd_RecursiveDeref( dd, Univ ); Kit_TruthForallNew( p->puTemp2, pIsf->puOn, p->nVars, v ); VarCost = Kit_TruthCountOnes( p->puTemp2, p->nVars ); if ( VarCost == 0 ) VarCost = 1; if ( VarCostBest < VarCost ) { VarCostBest = VarCost; VarBest = v; } } } // derive the components for weak-bi-decomposition if the variable is found if ( VarCostBest ) { // funQLeftRes = Q & bdd_exist( R, setRightORweak ); // Temp = Cudd_bddExistAbstract( dd, pF->R, VarBest ); Cudd_Ref( Temp ); // pL->Q = Cudd_bddAnd( dd, pF->Q, Temp ); Cudd_Ref( pL->Q ); // Cudd_RecursiveDeref( dd, Temp ); Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, VarBest ); Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars ); // pL->R = pF->R; Cudd_Ref( pL->R ); // pL->V = VarBest; Cudd_Ref( pL->V ); Kit_TruthCopy( pIsfL->puOff, pIsf->puOff, p->nVars ); pIsfL->uUniq = (1 << VarBest); pIsfR->uUniq = 0; // assert( pL->Q != b0 ); // assert( pL->R != b0 ); // assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); // assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); // express cost in percents of the covered boolean space Cost = VarCostBest * BDC_SCALE / (1<nVars); if ( Cost == 0 ) Cost = 1; return Cost; } return 0; } /**Function************************************************************* Synopsis [Checks existence of OR-bidecomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) { unsigned uSupportRem; int v, nLeftVars = 1, nRightVars = 1; // clean the var sets Bdc_IsfStart( p, pIsfL ); Bdc_IsfStart( p, pIsfR ); // check that the support is correct assert( Kit_TruthSupport(pIsf->puOn, p->nVars) == Kit_TruthSupport(pIsf->puOff, p->nVars) ); assert( pIsf->uSupp == Kit_TruthSupport(pIsf->puOn, p->nVars) ); // find initial variable sets if ( !Bdc_DecomposeFindInitialVarSet( p, pIsf, pIsfL, pIsfR ) ) return Bdc_DecomposeWeakOr( p, pIsf, pIsfL, pIsfR ); // prequantify the variables in the offset Kit_TruthExistSet( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->uUniq ); Kit_TruthExistSet( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->uUniq ); // go through the remaining variables uSupportRem = pIsf->uSupp & ~pIsfL->uUniq & ~pIsfR->uUniq; for ( v = 0; v < p->nVars; v++ ) { if ( (uSupportRem & (1 << v)) == 0 ) continue; // prequantify this variable Kit_TruthExistNew( p->puTemp3, p->puTemp1, p->nVars, v ); Kit_TruthExistNew( p->puTemp4, p->puTemp2, p->nVars, v ); if ( nLeftVars < nRightVars ) { // if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse ) // if ( VerifyORCondition( dd, pF->Q, pF->R, pL->V, pR->V, VarNew ) ) if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) ) { // pL->V &= VarNew; pIsfL->uUniq |= (1 << v); nLeftVars++; Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars ); } // else if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse ) else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) ) { // pR->V &= VarNew; pIsfR->uUniq |= (1 << v); nRightVars++; Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars ); } } else { // if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse ) if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) ) { // pR->V &= VarNew; pIsfR->uUniq |= (1 << v); nRightVars++; Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars ); } // else if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse ) else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) ) { // pL->V &= VarNew; pIsfL->uUniq |= (1 << v); nLeftVars++; Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars ); } } } // derive the functions Q and R for the left branch // pL->Q = bdd_appex( pF->Q, bdd_exist( pF->R, pL->V ), bddop_and, pR->V ); // pL->R = bdd_exist( pF->R, pR->V ); // Temp = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( Temp ); // pL->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pR->V ); Cudd_Ref( pL->Q ); // Cudd_RecursiveDeref( dd, Temp ); // pL->R = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( pL->R ); Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars ); Kit_TruthExistSet( pIsfL->puOn, pIsfL->puOn, p->nVars, pIsfR->uUniq ); Kit_TruthCopy( pIsfL->puOff, p->puTemp2, p->nVars ); // assert( pL->Q != b0 ); // assert( pL->R != b0 ); // assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); assert( !Kit_TruthIsConst0(pIsfL->puOn, p->nVars) ); assert( !Kit_TruthIsConst0(pIsfL->puOff, p->nVars) ); // assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); // derive the functions Q and R for the right branch // Temp = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( Temp ); // pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pL->V ); Cudd_Ref( pR->Q ); // Cudd_RecursiveDeref( dd, Temp ); // pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R ); Kit_TruthAnd( pIsfR->puOn, pIsf->puOn, p->puTemp2, p->nVars ); Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uUniq ); Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars ); assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) ); assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); // assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); assert( pIsfL->uUniq ); assert( pIsfR->uUniq ); return Bdc_DecomposeGetCost( p, nLeftVars, nRightVars ); } /**Function************************************************************* Synopsis [Performs one step of bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) { int WeightOr, WeightAnd, WeightOrL, WeightOrR, WeightAndL, WeightAndR; Bdc_IsfClean( p->pIsfOL ); Bdc_IsfClean( p->pIsfOR ); Bdc_IsfClean( p->pIsfAL ); Bdc_IsfClean( p->pIsfAR ); // perform OR decomposition WeightOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR ); // perform AND decomposition Bdc_IsfNot( pIsf ); WeightAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR ); Bdc_IsfNot( pIsf ); Bdc_IsfNot( p->pIsfAL ); Bdc_IsfNot( p->pIsfAR ); // check the case when decomposition does not exist if ( WeightOr == 0 && WeightAnd == 0 ) { Bdc_IsfCopy( pIsfL, p->pIsfOL ); Bdc_IsfCopy( pIsfR, p->pIsfOR ); return BDC_TYPE_MUX; } // check the hash table assert( WeightOr || WeightAnd ); WeightOrL = WeightOrR = 0; if ( WeightOr ) { if ( p->pIsfOL->uUniq ) { Bdc_SuppMinimize( p, p->pIsfOL ); WeightOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL); } if ( p->pIsfOR->uUniq ) { Bdc_SuppMinimize( p, p->pIsfOR ); WeightOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL); } } WeightAndL = WeightAndR = 0; if ( WeightAnd ) { if ( p->pIsfAL->uUniq ) { Bdc_SuppMinimize( p, p->pIsfAL ); WeightAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL); } if ( p->pIsfAR->uUniq ) { Bdc_SuppMinimize( p, p->pIsfAR ); WeightAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL); } } // check if there is any reuse for the components if ( WeightOrL + WeightOrR > WeightAndL + WeightAndR ) { p->numReuse++; p->numOrs++; Bdc_IsfCopy( pIsfL, p->pIsfOL ); Bdc_IsfCopy( pIsfR, p->pIsfOR ); return BDC_TYPE_OR; } if ( WeightOrL + WeightOrR < WeightAndL + WeightAndR ) { p->numReuse++; p->numAnds++; Bdc_IsfCopy( pIsfL, p->pIsfAL ); Bdc_IsfCopy( pIsfR, p->pIsfAR ); return BDC_TYPE_AND; } // compare the two-component costs if ( WeightOr > WeightAnd ) { if ( WeightOr < BDC_SCALE ) p->numWeaks++; p->numOrs++; Bdc_IsfCopy( pIsfL, p->pIsfOL ); Bdc_IsfCopy( pIsfR, p->pIsfOR ); return BDC_TYPE_OR; } if ( WeightAnd < BDC_SCALE ) p->numWeaks++; p->numAnds++; Bdc_IsfCopy( pIsfL, p->pIsfAL ); Bdc_IsfCopy( pIsfR, p->pIsfAR ); return BDC_TYPE_AND; } /**Function************************************************************* Synopsis [Find variable that leads to minimum sum of support sizes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_DecomposeStepMux( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) { int Var, VarMin, nSuppMin, nSuppCur; unsigned uSupp0, uSupp1; abctime clk = 0; // Suppress "might be used uninitialized" if ( p->pPars->fVerbose ) clk = Abc_Clock(); VarMin = -1; nSuppMin = 1000; for ( Var = 0; Var < p->nVars; Var++ ) { if ( (pIsf->uSupp & (1 << Var)) == 0 ) continue; Kit_TruthCofactor0New( pIsfL->puOn, pIsf->puOn, p->nVars, Var ); Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, Var ); Kit_TruthCofactor1New( pIsfR->puOn, pIsf->puOn, p->nVars, Var ); Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, Var ); uSupp0 = Kit_TruthSupport( pIsfL->puOn, p->nVars ) & Kit_TruthSupport( pIsfL->puOff, p->nVars ); uSupp1 = Kit_TruthSupport( pIsfR->puOn, p->nVars ) & Kit_TruthSupport( pIsfR->puOff, p->nVars ); nSuppCur = Kit_WordCountOnes(uSupp0) + Kit_WordCountOnes(uSupp1); if ( nSuppMin > nSuppCur ) { nSuppMin = nSuppCur; VarMin = Var; break; } } if ( VarMin >= 0 ) { Kit_TruthCofactor0New( pIsfL->puOn, pIsf->puOn, p->nVars, VarMin ); Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, VarMin ); Kit_TruthCofactor1New( pIsfR->puOn, pIsf->puOn, p->nVars, VarMin ); Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, VarMin ); Bdc_SuppMinimize( p, pIsfL ); Bdc_SuppMinimize( p, pIsfR ); } if ( p->pPars->fVerbose ) p->timeMuxes += Abc_Clock() - clk; return VarMin; } /**Function************************************************************* Synopsis [Creates gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc ) { unsigned * puTruth = p->puTemp1; if ( Bdc_IsComplement(pFunc) ) Kit_TruthNot( puTruth, Bdc_Regular(pFunc)->puFunc, p->nVars ); else Kit_TruthCopy( puTruth, pFunc->puFunc, p->nVars ); return Bdc_TableCheckContainment( p, pIsf, puTruth ); } /**Function************************************************************* Synopsis [Creates gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bdc_Fun_t * Bdc_ManCreateGate( Bdc_Man_t * p, Bdc_Fun_t * pFunc0, Bdc_Fun_t * pFunc1, Bdc_Type_t Type ) { Bdc_Fun_t * pFunc; pFunc = Bdc_FunNew( p ); if ( pFunc == NULL ) return NULL; pFunc->Type = Type; pFunc->pFan0 = pFunc0; pFunc->pFan1 = pFunc1; pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); // get the truth table of the left branch if ( Bdc_IsComplement(pFunc0) ) Kit_TruthNot( p->puTemp1, Bdc_Regular(pFunc0)->puFunc, p->nVars ); else Kit_TruthCopy( p->puTemp1, pFunc0->puFunc, p->nVars ); // get the truth table of the right branch if ( Bdc_IsComplement(pFunc1) ) Kit_TruthNot( p->puTemp2, Bdc_Regular(pFunc1)->puFunc, p->nVars ); else Kit_TruthCopy( p->puTemp2, pFunc1->puFunc, p->nVars ); // compute the function of node if ( pFunc->Type == BDC_TYPE_AND ) { Kit_TruthAnd( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars ); } else if ( pFunc->Type == BDC_TYPE_OR ) { Kit_TruthOr( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars ); // transform to AND gate pFunc->Type = BDC_TYPE_AND; pFunc->pFan0 = Bdc_Not(pFunc->pFan0); pFunc->pFan1 = Bdc_Not(pFunc->pFan1); Kit_TruthNot( pFunc->puFunc, pFunc->puFunc, p->nVars ); pFunc = Bdc_Not(pFunc); } else assert( 0 ); // add to table Bdc_Regular(pFunc)->uSupp = Kit_TruthSupport( Bdc_Regular(pFunc)->puFunc, p->nVars ); Bdc_TableAdd( p, Bdc_Regular(pFunc) ); return pFunc; } /**Function************************************************************* Synopsis [Performs one step of bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) { // int static Counter = 0; // int LocalCounter = Counter++; Bdc_Type_t Type; Bdc_Fun_t * pFunc, * pFunc0, * pFunc1; Bdc_Isf_t IsfL, * pIsfL = &IsfL; Bdc_Isf_t IsfB, * pIsfR = &IsfB; int iVar; abctime clk = 0; // Suppress "might be used uninitialized" /* printf( "Init function (%d):\n", LocalCounter ); Extra_PrintBinary( stdout, pIsf->puOn, 1<<4 );printf("\n"); Extra_PrintBinary( stdout, pIsf->puOff, 1<<4 );printf("\n"); */ // check computed results assert( Kit_TruthIsDisjoint(pIsf->puOn, pIsf->puOff, p->nVars) ); if ( p->pPars->fVerbose ) clk = Abc_Clock(); pFunc = Bdc_TableLookup( p, pIsf ); if ( p->pPars->fVerbose ) p->timeCache += Abc_Clock() - clk; if ( pFunc ) return pFunc; // decide on the decomposition type if ( p->pPars->fVerbose ) clk = Abc_Clock(); Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR ); if ( p->pPars->fVerbose ) p->timeCheck += Abc_Clock() - clk; if ( Type == BDC_TYPE_MUX ) { if ( p->pPars->fVerbose ) clk = Abc_Clock(); iVar = Bdc_DecomposeStepMux( p, pIsf, pIsfL, pIsfR ); if ( p->pPars->fVerbose ) p->timeMuxes += Abc_Clock() - clk; p->numMuxes++; pFunc0 = Bdc_ManDecompose_rec( p, pIsfL ); pFunc1 = Bdc_ManDecompose_rec( p, pIsfR ); if ( pFunc0 == NULL || pFunc1 == NULL ) return NULL; pFunc = Bdc_FunWithId( p, iVar + 1 ); pFunc0 = Bdc_ManCreateGate( p, Bdc_Not(pFunc), pFunc0, BDC_TYPE_AND ); pFunc1 = Bdc_ManCreateGate( p, pFunc, pFunc1, BDC_TYPE_AND ); if ( pFunc0 == NULL || pFunc1 == NULL ) return NULL; pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, BDC_TYPE_OR ); } else { pFunc0 = Bdc_ManDecompose_rec( p, pIsfL ); if ( pFunc0 == NULL ) return NULL; // decompose the right branch if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc0, Type ) ) { p->nNodesNew--; return pFunc0; } Bdc_SuppMinimize( p, pIsfR ); pFunc1 = Bdc_ManDecompose_rec( p, pIsfR ); if ( pFunc1 == NULL ) return NULL; // create new gate pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, Type ); } return pFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/bdcInt.h000066400000000000000000000160271300674244400231010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bdcInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table-based bi-decomposition engine.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__bdc__bdcInt_h #define ABC__aig__bdc__bdcInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "bool/kit/kit.h" #include "bdc.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define BDC_SCALE 1000 // value used to compute the cost //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // network types typedef enum { BDC_TYPE_NONE = 0, // 0: unknown BDC_TYPE_CONST1, // 1: constant 1 BDC_TYPE_PI, // 2: primary input BDC_TYPE_AND, // 3: AND-gate BDC_TYPE_OR, // 4: OR-gate (temporary) BDC_TYPE_XOR, // 5: XOR-gate BDC_TYPE_MUX, // 6: MUX-gate BDC_TYPE_OTHER // 7: unused } Bdc_Type_t; struct Bdc_Fun_t_ { int Type; // Const1, PI, AND, XOR, MUX Bdc_Fun_t * pFan0; // fanin of the given node Bdc_Fun_t * pFan1; // fanin of the given node unsigned uSupp; // bit mask of current support unsigned * puFunc; // the function of the node Bdc_Fun_t * pNext; // next function with same support union { int iCopy; // the literal of the node (AIG) void * pCopy; }; // the function of the node (BDD or AIG) }; typedef struct Bdc_Isf_t_ Bdc_Isf_t; struct Bdc_Isf_t_ { unsigned uSupp; // the complete support of this component unsigned uUniq; // the unique variables of this component unsigned * puOn; // on-set unsigned * puOff; // off-set }; struct Bdc_Man_t_ { // external parameters Bdc_Par_t * pPars; // parameter set int nVars; // the number of variables int nWords; // the number of words int nNodesMax; // the limit on the number of new nodes int nDivsLimit; // the limit on the number of divisors // internal nodes Bdc_Fun_t * pNodes; // storage for decomposition nodes int nNodesAlloc; // the number of nodes allocated int nNodes; // the number of all nodes created so far int nNodesNew; // the number of new AND nodes created so far Bdc_Fun_t * pRoot; // the root node // resub candidates Bdc_Fun_t ** pTable; // hash table of candidates int nTableSize; // hash table size (1 << nVarsMax) Vec_Int_t * vSpots; // the occupied spots in the table // elementary truth tables Vec_Ptr_t * vTruths; // for const 1 and elementary variables unsigned * puTemp1; // temporary truth table unsigned * puTemp2; // temporary truth table unsigned * puTemp3; // temporary truth table unsigned * puTemp4; // temporary truth table // temporary ISFs Bdc_Isf_t * pIsfOL, IsfOL; Bdc_Isf_t * pIsfOR, IsfOR; Bdc_Isf_t * pIsfAL, IsfAL; Bdc_Isf_t * pIsfAR, IsfAR; // internal memory manager Vec_Int_t * vMemory; // memory for internal truth tables // statistics int numCalls; int numNodes; int numMuxes; int numAnds; int numOrs; int numWeaks; int numReuse; // runtime abctime timeCache; abctime timeCheck; abctime timeMuxes; abctime timeSupps; abctime timeTotal; }; static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes >= p->nNodesAlloc || p->nNodesNew >= p->nNodesMax ) return NULL; pRes = p->pNodes + p->nNodes++; p->nNodesNew++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); return pRes; } static inline Bdc_Fun_t * Bdc_FunWithId( Bdc_Man_t * p, int Id ) { assert( Id < p->nNodes ); return p->pNodes + Id; } static inline int Bdc_FunId( Bdc_Man_t * p, Bdc_Fun_t * pFun ) { return pFun - p->pNodes; } static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); assert( pF->puOff && pF->puOn ); } static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->uUniq = 0; } static inline void Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q ) { Bdc_Isf_t T = *p; *p = *q; *q = T; } static inline void Bdc_IsfNot( Bdc_Isf_t * p ) { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== bdcDec.c ==========================================================*/ extern Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); extern void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); extern int Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc ); /*=== bdcTable.c ==========================================================*/ extern Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); extern void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc ); extern void Bdc_TableClear( Bdc_Man_t * p ); extern int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/bdcSpfd.c000066400000000000000000001034471300674244400232410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bdcSpfd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table-based bi-decomposition engine.] Synopsis [The gateway to bi-decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 30, 2007.] Revision [$Id: bdcSpfd.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bdcInt.h" #include "aig/aig/aig.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Bdc_Nod_t_ Bdc_Nod_t; struct Bdc_Nod_t_ { unsigned iFan0g : 8; unsigned iFan0n : 12; unsigned Type : 12; // 0-3 = AND; 4 = XOR unsigned iFan1g : 8; unsigned iFan1n : 12; unsigned Weight : 12; word Truth; }; static word Truths[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; static inline int Bdc_CountOnes( word t ) { t = (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555)); t = (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333)); t = (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F)); t = (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF)); t = (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF)); return (t & ABC_CONST(0x00000000FFFFFFFF)) + (t>>32); } static inline int Bdc_CountSpfd( word t, word f ) { int n00 = Bdc_CountOnes( ~t & ~f ); int n01 = Bdc_CountOnes( t & ~f ); int n10 = Bdc_CountOnes( ~t & f ); int n11 = Bdc_CountOnes( t & f ); return n00 * n11 + n10 * n01; } static inline word Bdc_Cof6( word t, int iVar, int fCof1 ) { assert( iVar >= 0 && iVar < 6 ); if ( fCof1 ) return (t & Truths[iVar]) | ((t & Truths[iVar]) >> (1< 0 ); printf( "(" ); if ( pNode->Type & 1 ) printf( "!" ); if ( pNode->iFan0g == 0 ) printf( "%c", 'a' + pNode->iFan0n ); else { Bdc_Nod_t * pNode0 = (Bdc_Nod_t *)Vec_PtrEntry(vLevels, pNode->iFan0g); Bdc_SpfdPrint_rec( pNode0 + pNode->iFan0n, pNode->iFan0g, vLevels ); } if ( pNode->Type & 4 ) printf( "+" ); else printf( "*" ); if ( pNode->Type & 2 ) printf( "!" ); if ( pNode->iFan1g == 0 ) printf( "%c", 'a' + pNode->iFan1n ); else { Bdc_Nod_t * pNode1 = (Bdc_Nod_t *)Vec_PtrEntry(vLevels, pNode->iFan1g); Bdc_SpfdPrint_rec( pNode1 + pNode->iFan1n, pNode->iFan1g, vLevels ); } printf( ")" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SpfdPrint( Bdc_Nod_t * pNode, int Level, Vec_Ptr_t * vLevels, word Truth ) { word Diff = Truth ^ pNode->Truth; Extra_PrintHex( stdout, (unsigned *)&pNode->Truth, 6 ); printf( " " ); Extra_PrintHex( stdout, (unsigned *)&Diff, 6 ); printf( " " ); Bdc_SpfdPrint_rec( pNode, Level, vLevels ); printf( " %d\n", pNode->Weight ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SpfdDecompose( word Truth, int nVars, int nCands, int nGatesMax ) { int nSize = nCands * nCands * (nGatesMax + 1) * 5; Vec_Ptr_t * vLevels; Vec_Int_t * vBegs, * vWeight; Bdc_Nod_t * pNode, * pNode0, * pNode1, * pNode2; int Count0, Count1, * pPerm; int i, j, k, c, n; abctime clk; assert( nGatesMax < (1<<8) ); assert( nCands < (1<<12) ); assert( (1<<(nVars-1))*(1<<(nVars-1)) < (1<<12) ); // max SPFD printf( "Storage size = %d (%d * %d * %d * %d).\n", nSize, nCands, nCands, nGatesMax + 1, 5 ); printf( "SPFD = %d.\n", Bdc_CountOnes(Truth) * Bdc_CountOnes(~Truth) ); // consider elementary functions if ( Truth == 0 || Truth == ~0 ) { printf( "Function is a constant.\n" ); return; } for ( i = 0; i < nVars; i++ ) if ( Truth == Truths[i] || Truth == ~Truths[i] ) { printf( "Function is an elementary variable.\n" ); return; } // allocate vLevels = Vec_PtrAlloc( 100 ); vBegs = Vec_IntAlloc( 100 ); vWeight = Vec_IntAlloc( 100 ); // initialize elementary variables pNode = ABC_CALLOC( Bdc_Nod_t, nVars ); for ( i = 0; i < nVars; i++ ) pNode[i].Truth = Truths[i]; for ( i = 0; i < nVars; i++ ) pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); Vec_PtrPush( vLevels, pNode ); Vec_IntPush( vBegs, nVars ); // the next level clk = Abc_Clock(); pNode0 = pNode; pNode = ABC_CALLOC( Bdc_Nod_t, 5 * nVars * (nVars - 1) / 2 ); for ( c = i = 0; i < nVars; i++ ) for ( j = i+1; j < nVars; j++ ) { pNode[c].Truth = pNode0[i].Truth & pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; pNode[c].Truth = ~pNode0[i].Truth & pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; pNode[c].Truth = pNode0[i].Truth & ~pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; pNode[c].Truth = ~pNode0[i].Truth & ~pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; pNode[c].Truth = pNode0[i].Truth ^ pNode0[j].Truth; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; } assert( c == 5 * nVars * (nVars - 1) / 2 ); Vec_PtrPush( vLevels, pNode ); Vec_IntPush( vBegs, c ); for ( i = 0; i < c; i++ ) { pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); //Bdc_SpfdPrint( pNode + i, 1, vLevels ); if ( Truth == pNode[i].Truth || Truth == ~pNode[i].Truth ) { printf( "Function can be implemented using 1 gate.\n" ); pNode = NULL; goto cleanup; } } printf( "Selected %6d gates on level %2d. ", c, 1 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // iterate through levels pNode = ABC_CALLOC( Bdc_Nod_t, nSize ); for ( n = 2; n <= nGatesMax; n++ ) { clk = Abc_Clock(); c = 0; pNode1 = (Bdc_Nod_t *)Vec_PtrEntry( vLevels, n-1 ); Count1 = Vec_IntEntry( vBegs, n-1 ); // go through previous levels for ( k = 0; k < n-1; k++ ) { pNode0 = (Bdc_Nod_t *)Vec_PtrEntry( vLevels, k ); Count0 = Vec_IntEntry( vBegs, k ); for ( i = 0; i < Count0; i++ ) for ( j = 0; j < Count1; j++ ) { pNode[c].Truth = pNode0[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; pNode[c].Truth = ~pNode0[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; pNode[c].Truth = pNode0[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; pNode[c].Truth = ~pNode0[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; pNode[c].Truth = pNode0[i].Truth ^ pNode1[j].Truth; pNode[c].iFan0g = k; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; } assert( c < nSize ); } // go through current level for ( i = 0; i < Count1; i++ ) for ( j = i+1; j < Count1; j++ ) { pNode[c].Truth = pNode1[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 0; pNode[c].Truth = ~pNode1[i].Truth & pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 1; pNode[c].Truth = pNode1[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 2; pNode[c].Truth = ~pNode1[i].Truth & ~pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 3; pNode[c].Truth = pNode1[i].Truth ^ pNode1[j].Truth; pNode[c].iFan0g = n-1; pNode[c].iFan1g = n-1; pNode[c].iFan0n = i; pNode[c].iFan1n = j; pNode[c++].Type = 4; } assert( c < nSize ); // sort Vec_IntClear( vWeight ); for ( i = 0; i < c; i++ ) { pNode[i].Weight = Bdc_CountSpfd( pNode[i].Truth, Truth ); if ( pNode[i].Weight > 300 ) Bdc_SpfdPrint( pNode + i, 1, vLevels, Truth ); Vec_IntPush( vWeight, pNode[i].Weight ); if ( Truth == pNode[i].Truth || Truth == ~pNode[i].Truth ) { printf( "Function can be implemented using %d gates.\n", n ); Bdc_SpfdPrint( pNode + i, n, vLevels, Truth ); goto cleanup; } } pPerm = Abc_MergeSortCost( Vec_IntArray(vWeight), c ); assert( Vec_IntEntry(vWeight, pPerm[0]) <= Vec_IntEntry(vWeight, pPerm[c-1]) ); printf( "Best SPFD = %d.\n", Vec_IntEntry(vWeight, pPerm[c-1]) ); // for ( i = 0; i < c; i++ ) //printf( "%d ", Vec_IntEntry(vWeight, pPerm[i]) ); // choose the best ones pNode2 = ABC_CALLOC( Bdc_Nod_t, nCands ); for ( j = 0, i = c-1; i >= 0; i-- ) { pNode2[j++] = pNode[pPerm[i]]; if ( j == nCands ) break; } ABC_FREE( pPerm ); Vec_PtrPush( vLevels, pNode2 ); Vec_IntPush( vBegs, j ); printf( "Selected %6d gates (out of %6d) on level %2d. ", j, c, n ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); for ( i = 0; i < 10; i++ ) Bdc_SpfdPrint( pNode2 + i, n, vLevels, Truth ); } cleanup: ABC_FREE( pNode ); Vec_PtrForEachEntry( Bdc_Nod_t *, vLevels, pNode, i ) ABC_FREE( pNode ); Vec_PtrFree( vLevels ); Vec_IntFree( vBegs ); Vec_IntFree( vWeight ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SpfdDecomposeTest_() { int fTry = 0; // word T[17]; // int i; // word Truth = Truths[0] & ~Truths[3]; // word Truth = (Truths[0] & Truths[1]) | (Truths[2] & Truths[3]) | (Truths[4] & Truths[5]); // word Truth = (Truths[0] & Truths[1]) | ((Truths[2] & ~Truths[3]) ^ (Truths[4] & ~Truths[5])); // word Truth = (Truths[0] & Truths[1]) | (Truths[2] & Truths[3]); // word Truth = 0x9ef7a8d9c7193a0f; // AAFFAAFF0A0F0A0F // word Truth = 0x34080226CD163000; word Truth = ABC_CONST(0x5052585a0002080a); int nVars = 6; int nCands = 200;// 75; int nGatesMax = 20; if ( fTry ) Bdc_SpfdDecompose( Truth, nVars, nCands, nGatesMax ); /* for ( i = 0; i < 6; i++ ) T[i] = Truths[i]; T[7] = 0; T[8] = ~T[1] & T[3]; T[9] = ~T[8] & T[0]; T[10] = T[1] & T[4]; T[11] = T[10] & T[2]; T[12] = T[11] & T[9]; T[13] = ~T[0] & T[5]; T[14] = T[2] & T[13]; T[15] = ~T[12] & ~T[14]; T[16] = ~T[15]; // if ( T[16] != Truth ) // printf( "Failed\n" ); for ( i = 0; i < 17; i++ ) { // printf( "%2d = %3d ", i, Bdc_CountSpfd(T[i], Truth) ); printf( "%2d = %3d ", i, Bdc_CountSpfd(T[i], T[16]) ); Extra_PrintBinary( stdout, (unsigned *)&T[i], 64 ); printf( "\n" ); } // Extra_PrintBinary( stdout, (unsigned *)&Truth, 64 ); printf( "\n" ); */ } typedef struct Bdc_Ent_t_ Bdc_Ent_t; // 24 bytes struct Bdc_Ent_t_ { unsigned iFan0 : 29; unsigned fCompl0 : 1; unsigned fCompl : 1; unsigned fMark0 : 1; unsigned iFan1 : 29; unsigned fCompl1 : 1; unsigned fExor : 1; unsigned fMark1 : 1; int iNext; int iList; word Truth; }; #define BDC_TERM 0x1FFFFFFF /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_SpfdMark0( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) { if ( pEnt->iFan0 == BDC_TERM ) return 0; if ( pEnt->fMark0 ) return 0; pEnt->fMark0 = 1; return pEnt->fMark1 + Bdc_SpfdMark0(p, p + pEnt->iFan0) + Bdc_SpfdMark0(p, p + pEnt->iFan1); } int Bdc_SpfdMark1( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) { if ( pEnt->iFan0 == BDC_TERM ) return 0; if ( pEnt->fMark1 ) return 0; pEnt->fMark1 = 1; return pEnt->fMark0 + Bdc_SpfdMark1(p, p + pEnt->iFan0) + Bdc_SpfdMark1(p, p + pEnt->iFan1); } void Bdc_SpfdUnmark0( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) { if ( pEnt->iFan0 == BDC_TERM ) return; pEnt->fMark0 = 0; Bdc_SpfdUnmark0( p, p + pEnt->iFan0 ); Bdc_SpfdUnmark0( p, p + pEnt->iFan1 ); } void Bdc_SpfdUnmark1( Bdc_Ent_t * p, Bdc_Ent_t * pEnt ) { if ( pEnt->iFan0 == BDC_TERM ) return; pEnt->fMark1 = 0; Bdc_SpfdUnmark1( p, p + pEnt->iFan0 ); Bdc_SpfdUnmark1( p, p + pEnt->iFan1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_SpfdCheckOverlap( Bdc_Ent_t * p, Bdc_Ent_t * pEnt0, Bdc_Ent_t * pEnt1 ) { int RetValue; RetValue = Bdc_SpfdMark0( p, pEnt0 ); assert( RetValue == 0 ); RetValue = Bdc_SpfdMark1( p, pEnt1 ); Bdc_SpfdUnmark0( p, pEnt0 ); Bdc_SpfdUnmark1( p, pEnt1 ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_SpfdHashValue( word t, int Size ) { // http://planetmath.org/encyclopedia/GoodHashTablePrimes.html // 53, // 97, // 193, // 389, // 769, // 1543, // 3079, // 6151, // 12289, // 24593, // 49157, // 98317, // 196613, // 393241, // 786433, // 1572869, // 3145739, // 6291469, // 12582917, // 25165843, // 50331653, // 100663319, // 201326611, // 402653189, // 805306457, // 1610612741, static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; unsigned char * s = (unsigned char *)&t; unsigned i, Value = 0; for ( i = 0; i < 8; i++ ) Value ^= BigPrimes[i] * s[i]; return Value % Size; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Bdc_SpfdHashLookup( Bdc_Ent_t * p, int Size, word t ) { Bdc_Ent_t * pBin = p + Bdc_SpfdHashValue( t, Size ); if ( pBin->iList == 0 ) return &pBin->iList; for ( pBin = p + pBin->iList; ; pBin = p + pBin->iNext ) { if ( pBin->Truth == t ) return NULL; if ( pBin->iNext == 0 ) return &pBin->iNext; } assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Bdc_SpfdDecomposeTest__( Vec_Int_t ** pvWeights ) { // int nFuncs = 8000000; // the number of functions to compute // int nSize = 2777111; // the hash table size to use // int Limit = 6; // int nFuncs = 51000000; // the number of functions to compute // int nSize = 50331653; // the hash table size to use // int Limit = 6; int nFuncs = 250000000; // the number of functions to compute int nSize = 201326611; // the hash table size to use int Limit = 6; int * pPlace, i, n, m, k, s, fCompl; abctime clk = Abc_Clock(), clk2; Vec_Int_t * vStops; Vec_Wrd_t * vTruths; Vec_Int_t * vWeights; Bdc_Ent_t * p, * q, * pBeg0, * pEnd0, * pBeg1, * pEnd1, * pThis0, * pThis1; word t0, t1, t; assert( nSize <= nFuncs ); printf( "Allocating %.2f MB of internal memory.\n", 1.0*sizeof(Bdc_Ent_t)*nFuncs/(1<<20) ); p = (Bdc_Ent_t *)calloc( nFuncs, sizeof(Bdc_Ent_t) ); memset( p, 255, sizeof(Bdc_Ent_t) ); p->iList = 0; for ( q = p; q < p+nFuncs; q++ ) q->iList = 0; q = p + 1; printf( "Added %d + %d + 0 = %d. Total = %8d.\n", 0, 0, 0, (int)(q-p) ); vTruths = Vec_WrdStart( nFuncs ); vWeights = Vec_IntStart( nFuncs ); Vec_WrdClear( vTruths ); Vec_IntClear( vWeights ); // create elementary vars vStops = Vec_IntAlloc( 10 ); Vec_IntPush( vStops, 1 ); for ( i = 0; i < 6; i++ ) { q->iFan0 = BDC_TERM; q->iFan1 = i; q->Truth = Truths[i]; pPlace = Bdc_SpfdHashLookup( p, nSize, q->Truth ); *pPlace = q-p; q++; Vec_WrdPush( vTruths, Truths[i] ); Vec_IntPush( vWeights, 0 ); } Vec_IntPush( vStops, 7 ); printf( "Added %d + %d + 0 = %d. Total = %8d.\n", 0, 0, 0, (int)(q-p) ); // create gates for ( n = 0; n < Limit; n++ ) { // try previous for ( k = 0; k < Limit; k++ ) for ( m = 0; m < Limit; m++ ) { if ( k + m != n || k > m ) continue; // set the start and stop pBeg0 = p + Vec_IntEntry( vStops, k ); pEnd0 = p + Vec_IntEntry( vStops, k+1 ); // set the start and stop pBeg1 = p + Vec_IntEntry( vStops, m ); pEnd1 = p + Vec_IntEntry( vStops, m+1 ); clk2 = Abc_Clock(); printf( "Trying %7d x %7d. ", (int)(pEnd0-pBeg0), (int)(pEnd1-pBeg1) ); for ( pThis0 = pBeg0; pThis0 < pEnd0; pThis0++ ) for ( pThis1 = pBeg1; pThis1 < pEnd1; pThis1++ ) if ( k < m || pThis1 > pThis0 ) // if ( n < 5 || Bdc_SpfdCheckOverlap(p, pThis0, pThis1) ) for ( s = 0; s < 5; s++ ) { t0 = (s&1) ? ~pThis0->Truth : pThis0->Truth; t1 = ((s>>1)&1) ? ~pThis1->Truth : pThis1->Truth; t = ((s>>2)&1) ? t0 ^ t1 : t0 & t1; fCompl = t & 1; if ( fCompl ) t = ~t; if ( t == 0 ) continue; pPlace = Bdc_SpfdHashLookup( p, nSize, t ); if ( pPlace == NULL ) continue; q->iFan0 = pThis0-p; q->fCompl0 = s&1; q->iFan1 = pThis1-p; q->fCompl1 = (s>>1)&1; q->fExor = (s>>2)&1; q->Truth = t; q->fCompl = fCompl; *pPlace = q-p; q++; Vec_WrdPush( vTruths, t ); // Vec_IntPush( vWeights, n == 5 ? n : n+1 ); Vec_IntPush( vWeights, n+1 ); if ( q-p == nFuncs ) { printf( "Reached limit of %d functions.\n", nFuncs ); goto finish; } } printf( "Added %d + %d + 1 = %d. Total = %8d. ", k, m, n+1, (int)(q-p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); } Vec_IntPush( vStops, q-p ); } Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); { FILE * pFile = fopen( "func6v6n_bin.txt", "wb" ); fwrite( Vec_WrdArray(vTruths), sizeof(word), Vec_WrdSize(vTruths), pFile ); fclose( pFile ); } { FILE * pFile = fopen( "func6v6nW_bin.txt", "wb" ); fwrite( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); fclose( pFile ); } finish: Vec_IntFree( vStops ); free( p ); *pvWeights = vWeights; // Vec_WrdFree( vTruths ); return vTruths; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Bdc_SpfdReadFiles5( Vec_Int_t ** pvWeights ) { Vec_Int_t * vWeights; Vec_Wrd_t * vDivs; FILE * pFile; int RetValue; vDivs = Vec_WrdStart( 3863759 ); pFile = fopen( "func6v5n_bin.txt", "rb" ); RetValue = fread( Vec_WrdArray(vDivs), sizeof(word), Vec_WrdSize(vDivs), pFile ); fclose( pFile ); vWeights = Vec_IntStart( 3863759 ); pFile = fopen( "func6v5nW_bin.txt", "rb" ); RetValue = fread( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); fclose( pFile ); *pvWeights = vWeights; return vDivs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Bdc_SpfdReadFiles6( Vec_Int_t ** pvWeights ) { Vec_Int_t * vWeights; Vec_Wrd_t * vDivs = Vec_WrdStart( 12776759 ); FILE * pFile = fopen( "func6v6n_bin.txt", "rb" ); int RetValue; RetValue = fread( Vec_WrdArray(vDivs), sizeof(word), Vec_WrdSize(vDivs), pFile ); fclose( pFile ); vWeights = Vec_IntStart( 12776759 ); pFile = fopen( "func6v6nW_bin.txt", "rb" ); RetValue = fread( Vec_IntArray(vWeights), sizeof(int), Vec_IntSize(vWeights), pFile ); fclose( pFile ); *pvWeights = vWeights; return vDivs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_SpfdComputeCost( word f, int i, Vec_Int_t * vWeights ) { int Ones = Bdc_CountOnes(f); if ( Ones == 0 ) return -1; return 7*Ones + 10*(8 - Vec_IntEntry(vWeights, i)); // return Bdc_CountOnes(f); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Bdc_SpfdFindBest( Vec_Wrd_t * vDivs, Vec_Int_t * vWeights, word F0, word F1, int * pCost ) { word Func, FuncBest; int i, Cost, CostBest = -1, NumBest = -1; Vec_WrdForEachEntry( vDivs, Func, i ) { if ( (Func & F0) == 0 ) { Cost = Bdc_SpfdComputeCost(Func & F1, i, vWeights); if ( CostBest < Cost ) { CostBest = Cost; FuncBest = Func; NumBest = i; } } if ( (Func & F1) == 0 ) { Cost = Bdc_SpfdComputeCost(Func & F0, i, vWeights); if ( CostBest < Cost ) { CostBest = Cost; FuncBest = Func; NumBest = i; } } if ( (~Func & F0) == 0 ) { Cost = Bdc_SpfdComputeCost(~Func & F1, i, vWeights); if ( CostBest < Cost ) { CostBest = Cost; FuncBest = ~Func; NumBest = i; } } if ( (~Func & F1) == 0 ) { Cost = Bdc_SpfdComputeCost(~Func & F0, i, vWeights); if ( CostBest < Cost ) { CostBest = Cost; FuncBest = ~Func; NumBest = i; } } } (*pCost) += Vec_IntEntry(vWeights, NumBest); assert( CostBest > 0 ); printf( "Selected %8d with cost %2d and weight %d: ", NumBest, 0, Vec_IntEntry(vWeights, NumBest) ); Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); printf( "\n" ); return FuncBest; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_SpfdDecomposeTestOne( word t, Vec_Wrd_t * vDivs, Vec_Int_t * vWeights ) { word F1 = t; word F0 = ~F1; word Func; int i, Cost = 0; printf( "Trying: " ); Extra_PrintHex( stdout, (unsigned *)&t, 6 ); printf( "\n" ); // Abc_Show6VarFunc( F0, F1 ); for ( i = 0; F0 && F1; i++ ) { printf( "*** ITER %2d ", i ); Func = Bdc_SpfdFindBest( vDivs, vWeights, F0, F1, &Cost ); F0 &= ~Func; F1 &= ~Func; // Abc_Show6VarFunc( F0, F1 ); } Cost += (i-1); printf( "Produce solution with cost %2d (with adj cost %4d).\n", Cost, Bdc_SpfdAdjCost(t) ); return Cost; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SpfdDecomposeTest44() { // word t = 0x5052585a0002080a; word t = ABC_CONST(0x9ef7a8d9c7193a0f); // word t = 0x6BFDA276C7193A0F; // word t = 0xA3756AFE0B1DF60B; // word t = 0xFEF7AEBFCE80AA0F; // word t = 0x9EF7FDBFC77F6F0F; // word t = 0xDEF7FDFF377F6FFF; // word t = 0x345D02736DB390A5; // xor with var 0 // word t = 0x3EFDA2736D139A0F; // best solution after changes Vec_Int_t * vWeights; Vec_Wrd_t * vDivs; word c0, c1, s, tt, tbest; int i, j, Cost, CostBest = 100000; abctime clk = Abc_Clock(); return; // printf( "%d\n", RAND_MAX ); vDivs = Bdc_SpfdDecomposeTest__( &vWeights ); // vDivs = Bdc_SpfdReadFiles5( &vWeights ); // Abc_Show6VarFunc( ~t, t ); // try function tt = t; Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); if ( CostBest > Cost ) { CostBest = Cost; tbest = tt; } printf( "\n" ); // try complemented output for ( i = 0; i < 6; i++ ) { tt = t ^ Truths[i]; Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); if ( CostBest > Cost ) { CostBest = Cost; tbest = tt; } } printf( "\n" ); // try complemented input for ( i = 0; i < 6; i++ ) for ( j = 0; j < 6; j++ ) { if ( i == j ) continue; c0 = Bdc_Cof6( t, i, 0 ); c1 = Bdc_Cof6( t, i, 1 ); s = Truths[i] ^ Truths[j]; tt = (~s & c0) | (s & c1); Cost = Bdc_SpfdDecomposeTestOne( tt, vDivs, vWeights ); if ( CostBest > Cost ) { CostBest = Cost; tbest = tt; } } /* for ( i = 0; i < 6; i++ ) for ( j = 0; j < 6; j++ ) { if ( i == j ) continue; c0 = Bdc_Cof6( t, i, 0 ); c1 = Bdc_Cof6( t, i, 1 ); s = Truths[i] ^ Truths[j]; tt = (~s & c0) | (s & c1); for ( k = 0; k < 6; k++ ) for ( n = 0; n < 6; n++ ) { if ( k == n ) continue; c0 = Bdc_Cof6( tt, k, 0 ); c1 = Bdc_Cof6( tt, k, 1 ); s = Truths[k] ^ Truths[n]; ttt= (~s & c0) | (s & c1); Cost = Bdc_SpfdDecomposeTestOne( ttt, vDivs, vWeights ); if ( CostBest > Cost ) { CostBest = Cost; tbest = ttt; } } } */ printf( "Best solution found with cost %d. ", CostBest ); Extra_PrintHex( stdout, (unsigned *)&tbest, 6 ); //printf( "\n" ); Abc_PrintTime( 1, " Time", Abc_Clock() - clk ); Vec_WrdFree( vDivs ); Vec_IntFree( vWeights ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SpfdDecomposeTest3() { int nSizeM = (1 << 26); int nSizeK = (1 << 3); Vec_Wrd_t * v1M; Vec_Wrd_t * v1K; int i, k, Counter; abctime clk; // int EntryM, EntryK; Aig_ManRandom64( 1 ); v1M = Vec_WrdAlloc( nSizeM ); for ( i = 0; i < nSizeM; i++ ) Vec_WrdPush( v1M, Aig_ManRandom64(0) ); v1K = Vec_WrdAlloc( nSizeK ); for ( i = 0; i < nSizeK; i++ ) Vec_WrdPush( v1K, Aig_ManRandom64(0) ); clk = Abc_Clock(); Counter = 0; for ( i = 0; i < nSizeM; i++ ) for ( k = 0; k < nSizeK; k++ ) Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); // Vec_WrdForEachEntry( v1M, EntryM, i ) // Vec_WrdForEachEntry( v1K, EntryK, k ) // Counter += ((EntryM & EntryK) == EntryK); printf( "Total = %8d. ", Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); clk = Abc_Clock(); Counter = 0; for ( k = 0; k < nSizeK; k++ ) for ( i = 0; i < nSizeM; i++ ) Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); printf( "Total = %8d. ", Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SpfdDecomposeTest8() { // word t = 0x9ef7a8d9c7193a0f; // word t = 0x9EF7FDBFC77F6F0F; word t = ABC_CONST(0x513B57150819050F); Vec_Int_t * vWeights; Vec_Wrd_t * vDivs; word Func, FuncBest; int Cost, CostBest = ABC_INFINITY; int i; abctime clk = Abc_Clock(); // return; vDivs = Bdc_SpfdReadFiles5( &vWeights ); printf( "Best init = %4d. ", Bdc_SpfdAdjCost(t) ); Extra_PrintHex( stdout, (unsigned *)&t, 6 ); //printf( "\n" ); Abc_PrintTime( 1, " Time", Abc_Clock() - clk ); Vec_WrdForEachEntry( vDivs, Func, i ) { Cost = Bdc_SpfdAdjCost( t ^ Func ); if ( CostBest > Cost ) { CostBest = Cost; FuncBest = Func; } } printf( "Best cost = %4d. ", CostBest ); Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); //printf( "\n" ); Abc_PrintTime( 1, " Time", Abc_Clock() - clk ); Abc_Show6VarFunc( 0, t ); Abc_Show6VarFunc( 0, FuncBest ); Abc_Show6VarFunc( 0, (FuncBest ^ t) ); FuncBest ^= t; Extra_PrintHex( stdout, (unsigned *)&FuncBest, 6 ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_SpfdDecomposeTest() { int nSizeM = (1 << 26); // big array size int nSizeK = (1 << 3); // small array size Vec_Wrd_t * v1M, * v1K; int EntryM, EntryK; int i, k, Counter; abctime clk; Aig_ManRandom64( 1 ); v1M = Vec_WrdAlloc( nSizeM ); for ( i = 0; i < nSizeM; i++ ) Vec_WrdPush( v1M, Aig_ManRandom64(0) ); v1K = Vec_WrdAlloc( nSizeK ); for ( i = 0; i < nSizeK; i++ ) Vec_WrdPush( v1K, Aig_ManRandom64(0) ); clk = Abc_Clock(); Counter = 0; // for ( i = 0; i < nSizeM; i++ ) // for ( k = 0; k < nSizeK; k++ ) // Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); Vec_WrdForEachEntry( v1M, EntryM, i ) Vec_WrdForEachEntry( v1K, EntryK, k ) Counter += ((EntryM & EntryK) == EntryK); printf( "Total = %8d. ", Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); clk = Abc_Clock(); Counter = 0; // for ( k = 0; k < nSizeK; k++ ) // for ( i = 0; i < nSizeM; i++ ) // Counter += ((v1M->pArray[i] & v1K->pArray[k]) == v1K->pArray[k]); Vec_WrdForEachEntry( v1K, EntryK, k ) Vec_WrdForEachEntry( v1M, EntryM, i ) Counter += ((EntryM & EntryK) == EntryK); printf( "Total = %8d. ", Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/bdcTable.c000066400000000000000000000075241300674244400233730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bdcTable.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table-based bi-decomposition engine.] Synopsis [Hash table for intermediate nodes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 30, 2007.] Revision [$Id: bdcTable.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bdcInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks containment of the function in the ISF.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ) { return Kit_TruthIsImply( pIsf->puOn, puTruth, p->nVars ) && Kit_TruthIsDisjoint( puTruth, pIsf->puOff, p->nVars ); } /**Function************************************************************* Synopsis [Adds the new entry to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) { int fDisableCache = 0; Bdc_Fun_t * pFunc; if ( fDisableCache && Kit_WordCountOnes(pIsf->uSupp) > 1 ) return NULL; if ( pIsf->uSupp == 0 ) { assert( p->pTable[pIsf->uSupp] == p->pNodes ); if ( Kit_TruthIsConst1( pIsf->puOn, p->nVars ) ) return p->pNodes; assert( Kit_TruthIsConst1( pIsf->puOff, p->nVars ) ); return Bdc_Not(p->pNodes); } for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) return pFunc; Bdc_IsfNot( pIsf ); for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) { Bdc_IsfNot( pIsf ); return Bdc_Not(pFunc); } Bdc_IsfNot( pIsf ); return NULL; } /**Function************************************************************* Synopsis [Adds the new entry to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc ) { if ( p->pTable[pFunc->uSupp] == NULL ) Vec_IntPush( p->vSpots, pFunc->uSupp ); pFunc->pNext = p->pTable[pFunc->uSupp]; p->pTable[pFunc->uSupp] = pFunc; } /**Function************************************************************* Synopsis [Adds the new entry to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bdc_TableClear( Bdc_Man_t * p ) { int Spot, i; Vec_IntForEachEntry( p->vSpots, Spot, i ) p->pTable[Spot] = NULL; Vec_IntClear( p->vSpots ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/bdc_.c000066400000000000000000000026771300674244400225660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bdc_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table-based bi-decomposition engine.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 30, 2007.] Revision [$Id: bdc_.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bdcInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/bdc/module.make000066400000000000000000000001631300674244400236430ustar00rootroot00000000000000SRC += src/bool/bdc/bdcCore.c \ src/bool/bdc/bdcDec.c \ src/bool/bdc/bdcSpfd.c \ src/bool/bdc/bdcTable.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/dec/000077500000000000000000000000001300674244400215225ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/dec/dec.h000066400000000000000000000511751300674244400224370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dec.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [A simple decomposition tree/node data structure and its APIs.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__dec__dec_h #define ABC__opt__dec__dec_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Dec_Edge_t_ Dec_Edge_t; struct Dec_Edge_t_ { unsigned fCompl : 1; // the complemented bit unsigned Node : 30; // the decomposition node pointed by the edge }; typedef struct Dec_Node_t_ Dec_Node_t; struct Dec_Node_t_ { Dec_Edge_t eEdge0; // the left child of the node Dec_Edge_t eEdge1; // the right child of the node // other info union { int iFunc; // the literal of the node (AIG) void * pFunc; }; // the function of the node (BDD or AIG) unsigned Level : 14; // the level of this node in the global AIG // printing info unsigned fNodeOr : 1; // marks the original OR node unsigned fCompl0 : 1; // marks the original complemented edge unsigned fCompl1 : 1; // marks the original complemented edge // latch info unsigned nLat0 : 5; // the number of latches on the first edge unsigned nLat1 : 5; // the number of latches on the second edge unsigned nLat2 : 5; // the number of latches on the output edge }; typedef struct Dec_Graph_t_ Dec_Graph_t; struct Dec_Graph_t_ { int fConst; // marks the constant 1 graph int nLeaves; // the number of leaves int nSize; // the number of nodes (including the leaves) int nCap; // the number of allocated nodes Dec_Node_t * pNodes; // the array of leaves and internal nodes Dec_Edge_t eRoot; // the pointer to the topmost node }; typedef struct Dec_Man_t_ Dec_Man_t; struct Dec_Man_t_ { void * pMvcMem; // memory manager for MVC cover (used for factoring) Vec_Int_t * vCubes; // storage for cubes Vec_Int_t * vLits; // storage for literals // precomputation information about 4-variable functions unsigned short * puCanons; // canonical forms char * pPhases; // canonical phases char * pPerms; // canonical permutations unsigned char * pMap; // mapping of functions into class numbers }; //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // interator throught the leaves #define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) // interator throught the internal nodes #define Dec_GraphForEachNode( pGraph, pAnd, i ) \ for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== decAbc.c ========================================================*/ /*=== decFactor.c ========================================================*/ extern Dec_Graph_t * Dec_Factor( char * pSop ); /*=== decMan.c ========================================================*/ extern Dec_Man_t * Dec_ManStart(); extern void Dec_ManStop( Dec_Man_t * p ); /*=== decPrint.c ========================================================*/ extern void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ); /*=== decUtil.c ========================================================*/ extern unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates an edge pointing to the node in the given polarity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) { Dec_Edge_t eEdge = { fCompl, Node }; return eEdge; } /**Function************************************************************* Synopsis [Converts the edge into unsigned integer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) { return (eEdge.Node << 1) | eEdge.fCompl; } /**Function************************************************************* Synopsis [Converts unsigned integer into the edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) { return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); } /**Function************************************************************* Synopsis [Converts the edge into unsigned integer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dec_EdgeToInt_( Dec_Edge_t m ) { union { Dec_Edge_t x; unsigned y; } v; v.x = m; return v.y; } /* static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge ) { return *(unsigned *)&eEdge; } */ /**Function************************************************************* Synopsis [Converts unsigned integer into the edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_IntToEdge_( unsigned m ) { union { Dec_Edge_t x; unsigned y; } v; v.y = m; return v.x; } /* static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge ) { return *(Dec_Edge_t *)&Edge; } */ /**Function************************************************************* Synopsis [Creates a graph with the given number of leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves ) { Dec_Graph_t * pGraph; pGraph = ABC_ALLOC( Dec_Graph_t, 1 ); memset( pGraph, 0, sizeof(Dec_Graph_t) ); pGraph->nLeaves = nLeaves; pGraph->nSize = nLeaves; pGraph->nCap = 2 * nLeaves + 50; pGraph->pNodes = ABC_ALLOC( Dec_Node_t, pGraph->nCap ); memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize ); return pGraph; } /**Function************************************************************* Synopsis [Creates constant 0 graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Graph_t * Dec_GraphCreateConst0() { Dec_Graph_t * pGraph; pGraph = ABC_ALLOC( Dec_Graph_t, 1 ); memset( pGraph, 0, sizeof(Dec_Graph_t) ); pGraph->fConst = 1; pGraph->eRoot.fCompl = 1; return pGraph; } /**Function************************************************************* Synopsis [Creates constant 1 graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Graph_t * Dec_GraphCreateConst1() { Dec_Graph_t * pGraph; pGraph = ABC_ALLOC( Dec_Graph_t, 1 ); memset( pGraph, 0, sizeof(Dec_Graph_t) ); pGraph->fConst = 1; return pGraph; } /**Function************************************************************* Synopsis [Creates the literal graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) { Dec_Graph_t * pGraph; assert( 0 <= iLeaf && iLeaf < nLeaves ); pGraph = Dec_GraphCreate( nLeaves ); pGraph->eRoot.Node = iLeaf; pGraph->eRoot.fCompl = fCompl; return pGraph; } /**Function************************************************************* Synopsis [Creates a graph with the given number of leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) { ABC_FREE( pGraph->pNodes ); ABC_FREE( pGraph ); } /**Function************************************************************* Synopsis [Returns 1 if the graph is a constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph ) { return pGraph->fConst; } /**Function************************************************************* Synopsis [Returns 1 if the graph is constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph ) { return pGraph->fConst && pGraph->eRoot.fCompl; } /**Function************************************************************* Synopsis [Returns 1 if the graph is constant 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph ) { return pGraph->fConst && !pGraph->eRoot.fCompl; } /**Function************************************************************* Synopsis [Returns 1 if the graph is complemented.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph ) { return pGraph->eRoot.fCompl; } /**Function************************************************************* Synopsis [Checks if the graph is complemented.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dec_GraphComplement( Dec_Graph_t * pGraph ) { pGraph->eRoot.fCompl ^= 1; } /**Function************************************************************* Synopsis [Returns the number of leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph ) { return pGraph->nLeaves; } /**Function************************************************************* Synopsis [Returns the number of internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph ) { return pGraph->nSize - pGraph->nLeaves; } /**Function************************************************************* Synopsis [Returns the pointer to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i ) { return pGraph->pNodes + i; } /**Function************************************************************* Synopsis [Returns the pointer to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph ) { return pGraph->pNodes + pGraph->nSize - 1; } /**Function************************************************************* Synopsis [Returns the number of the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) { return pNode - pGraph->pNodes; } /**Function************************************************************* Synopsis [Check if the graph represents elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph ) { return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; } /**Function************************************************************* Synopsis [Check if the graph represents elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) { return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; } /**Function************************************************************* Synopsis [Returns the elementary variable elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph ) { assert( Dec_GraphIsVar( pGraph ) ); return Dec_GraphNode( pGraph, pGraph->eRoot.Node ); } /**Function************************************************************* Synopsis [Returns the number of the elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph ) { assert( Dec_GraphIsVar( pGraph ) ); return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) ); } /**Function************************************************************* Synopsis [Sets the root of the graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot ) { pGraph->eRoot = eRoot; } /**Function************************************************************* Synopsis [Appends a new node to the graph.] Description [This procedure is meant for internal use.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph ) { Dec_Node_t * pNode; if ( pGraph->nSize == pGraph->nCap ) { pGraph->pNodes = ABC_REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); pGraph->nCap = 2 * pGraph->nCap; } pNode = pGraph->pNodes + pGraph->nSize++; memset( pNode, 0, sizeof(Dec_Node_t) ); return pNode; } /**Function************************************************************* Synopsis [Creates an AND node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) { Dec_Node_t * pNode; // get the new node pNode = Dec_GraphAppendNode( pGraph ); // set the inputs and other info pNode->eEdge0 = eEdge0; pNode->eEdge1 = eEdge1; pNode->fCompl0 = eEdge0.fCompl; pNode->fCompl1 = eEdge1.fCompl; return Dec_EdgeCreate( pGraph->nSize - 1, 0 ); } /**Function************************************************************* Synopsis [Creates an OR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) { Dec_Node_t * pNode; // get the new node pNode = Dec_GraphAppendNode( pGraph ); // set the inputs and other info pNode->eEdge0 = eEdge0; pNode->eEdge1 = eEdge1; pNode->fCompl0 = eEdge0.fCompl; pNode->fCompl1 = eEdge1.fCompl; // make adjustments for the OR gate pNode->fNodeOr = 1; pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; return Dec_EdgeCreate( pGraph->nSize - 1, 1 ); } /**Function************************************************************* Synopsis [Creates an XOR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type ) { Dec_Edge_t eNode0, eNode1, eNode; if ( Type == 0 ) { // derive the first AND eEdge0.fCompl ^= 1; eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); eEdge0.fCompl ^= 1; // derive the second AND eEdge1.fCompl ^= 1; eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the final OR eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); } else { // derive the first AND eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the second AND eEdge0.fCompl ^= 1; eEdge1.fCompl ^= 1; eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the final OR eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); eNode.fCompl ^= 1; } return eNode; } /**Function************************************************************* Synopsis [Creates an XOR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type ) { Dec_Edge_t eNode0, eNode1, eNode; if ( Type == 0 ) { // derive the first AND eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); // derive the second AND eEdgeC.fCompl ^= 1; eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); // derive the final OR eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); } else { // complement the arguments eEdgeT.fCompl ^= 1; eEdgeE.fCompl ^= 1; // derive the first AND eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); // derive the second AND eEdgeC.fCompl ^= 1; eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); // derive the final OR eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); eNode.fCompl ^= 1; } return eNode; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/dec/decAbc.c000066400000000000000000000314131300674244400230310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [decAbc.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Interface between the decomposition package and ABC network.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: decAbc.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "aig/ivy/ivy.h" #include "dec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**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 [] ***********************************************************************/ Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) { Abc_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 Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Abc_ObjNotCond( (Abc_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 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAnd0, pAnd1 ); } // complement the result if necessary return Abc_ObjNotCond( (Abc_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Dec_SopToAig( Abc_Ntk_t * pNtk, char * pSop, Vec_Ptr_t * vFaninAigs ) { Abc_Obj_t * pFunc; Dec_Graph_t * pFForm; Dec_Node_t * pNode; int i; pFForm = Dec_Factor( pSop ); Dec_GraphForEachLeaf( pFForm, pNode, i ) pNode->pFunc = Vec_PtrEntry( vFaninAigs, i ); pFunc = Dec_GraphToNetwork( pNtk, pFForm ); Dec_GraphFree( pFForm ); return pFunc; } /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Dec_GraphToAig( Abc_Ntk_t * pNtk, Dec_Graph_t * pFForm, Vec_Ptr_t * vFaninAigs ) { Abc_Obj_t * pFunc; Dec_Node_t * pNode; int i; Dec_GraphForEachLeaf( pFForm, pNode, i ) pNode->pFunc = Vec_PtrEntry( vFaninAigs, i ); pFunc = Dec_GraphToNetwork( pNtk, pFForm ); return pFunc; } /**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 [] ***********************************************************************/ Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) { Abc_Obj_t * pAnd, * pAnd0, * pAnd1; Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" int i; // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Abc_ObjNotCond( (Abc_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 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Abc_ObjNotCond( (Abc_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); // pNode->pFunc = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAnd0, pAnd1 ); pAnd = Abc_NtkCreateNode( pNtk ); Abc_ObjAddFanin( pAnd, pAnd0 ); Abc_ObjAddFanin( pAnd, pAnd1 ); pNode->pFunc = pAnd; } // complement the result if necessary return Abc_ObjNotCond( (Abc_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } /**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 Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) { Abc_Aig_t * pMan = (Abc_Aig_t *)pRoot->pNtk->pManFunc; Dec_Node_t * pNode, * pNode0, * pNode1; Abc_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 = Abc_ObjRegular((Abc_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 = (Abc_Obj_t *)pNode0->pFunc; pAnd1 = (Abc_Obj_t *)pNode1->pFunc; if ( pAnd0 && pAnd1 ) { // if they are both present, find the resulting node pAnd0 = Abc_ObjNotCond( pAnd0, pNode->eEdge0.fCompl ); pAnd1 = Abc_ObjNotCond( pAnd1, pNode->eEdge1.fCompl ); pAnd = Abc_AigAndLookup( pMan, pAnd0, pAnd1 ); // return -1 if the node is the same as the original root if ( Abc_ObjRegular(pAnd) == pRoot ) return -1; } else pAnd = NULL; // count the number of added nodes if ( pAnd == NULL || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pAnd)) ) { if ( ++Counter > NodeMax ) return -1; } // count the number of new levels LevelNew = 1 + Abc_MaxInt( pNode0->Level, pNode1->Level ); if ( pAnd ) { if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pRoot->pNtk) ) LevelNew = 0; else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd0) ) LevelNew = (int)Abc_ObjRegular(pAnd0)->Level; else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd1) ) LevelNew = (int)Abc_ObjRegular(pAnd1)->Level; LevelOld = (int)Abc_ObjRegular(pAnd)->Level; // assert( LevelNew == LevelOld ); } if ( LevelNew > LevelMax ) return -1; pNode->pFunc = pAnd; pNode->Level = LevelNew; } return Counter; } /**Function************************************************************* Synopsis [Replaces MFFC of the node by the new factored form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) { extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ); Abc_Obj_t * pRootNew; Abc_Ntk_t * pNtk = pRoot->pNtk; int nNodesNew, nNodesOld; nNodesOld = Abc_NtkNodeNum(pNtk); // create the new structure of nodes pRootNew = Dec_GraphToNetwork( pNtk, pGraph ); // remove the old nodes Abc_AigReplace( (Abc_Aig_t *)pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel ); // compare the gains nNodesNew = Abc_NtkNodeNum(pNtk); assert( nGain <= nNodesOld - nNodesNew ); } /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph ) { Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" Hop_Obj_t * pAnd0, * pAnd1; int i; // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Hop_NotCond( Hop_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Hop_NotCond( (Hop_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 = Hop_NotCond( (Hop_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Hop_NotCond( (Hop_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); } // complement the result if necessary return Hop_NotCond( (Hop_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ) { Hop_Obj_t * pFunc; Dec_Graph_t * pFForm; Dec_Node_t * pNode; int i; // perform factoring pFForm = Dec_Factor( pSop ); // collect the fanins Dec_GraphForEachLeaf( pFForm, pNode, i ) pNode->pFunc = Hop_IthVar( pMan, i ); // perform strashing pFunc = Dec_GraphToNetworkAig( pMan, pFForm ); Dec_GraphFree( pFForm ); return pFunc; } /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ) { Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" Ivy_Obj_t * pAnd0, * pAnd1; int i; // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Ivy_NotCond( Ivy_ManConst1(pMan), 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( pMan, pAnd0, pAnd1 ); } // complement the result if necessary return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/dec/decFactor.c000066400000000000000000000302201300674244400235550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ftFactor.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Procedures for algebraic factoring.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: ftFactor.c,v 1.3 2003/09/01 04:56:43 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "misc/mvc/mvc.h" #include "dec.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); static Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ); static Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); static Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ); static Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ); static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ); static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Factors the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Dec_Factor( char * pSop ) { Mvc_Cover_t * pCover; Dec_Graph_t * pFForm; Dec_Edge_t eRoot; if ( Abc_SopIsConst0(pSop) ) return Dec_GraphCreateConst0(); if ( Abc_SopIsConst1(pSop) ) return Dec_GraphCreateConst1(); // derive the cover from the SOP representation pCover = Dec_ConvertSopToMvc( pSop ); // make sure the cover is CCS free (should be done before CST) Mvc_CoverContain( pCover ); // check for trivial functions assert( !Mvc_CoverIsEmpty(pCover) ); assert( !Mvc_CoverIsTautology(pCover) ); // perform CST Mvc_CoverInverse( pCover ); // CST // start the factored form pFForm = Dec_GraphCreate( Abc_SopGetVarNum(pSop) ); // factor the cover eRoot = Dec_Factor_rec( pFForm, pCover ); // finalize the factored form Dec_GraphSetRoot( pFForm, eRoot ); // complement the factored form if SOP is complemented if ( Abc_SopIsComplement(pSop) ) Dec_GraphComplement( pFForm ); // verify the factored form // if ( !Dec_FactorVerify( pSop, pFForm ) ) // printf( "Verification has failed.\n" ); // Mvc_CoverInverse( pCover ); // undo CST Mvc_CoverFree( pCover ); return pFForm; } /**Function************************************************************* Synopsis [Internal recursive factoring procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) { Mvc_Cover_t * pDiv, * pQuo, * pRem, * pCom; Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; Dec_Edge_t eNodeAnd, eNode; // make sure the cover contains some cubes assert( Mvc_CoverReadCubeNum(pCover) ); // get the divisor pDiv = Mvc_CoverDivisor( pCover ); if ( pDiv == NULL ) return Dec_FactorTrivial( pFForm, pCover ); // divide the cover by the divisor Mvc_CoverDivideInternal( pCover, pDiv, &pQuo, &pRem ); assert( Mvc_CoverReadCubeNum(pQuo) ); Mvc_CoverFree( pDiv ); Mvc_CoverFree( pRem ); // check the trivial case if ( Mvc_CoverReadCubeNum(pQuo) == 1 ) { eNode = Dec_FactorLF_rec( pFForm, pCover, pQuo ); Mvc_CoverFree( pQuo ); return eNode; } // make the quotient cube ABC_FREE Mvc_CoverMakeCubeFree( pQuo ); // divide the cover by the quotient Mvc_CoverDivideInternal( pCover, pQuo, &pDiv, &pRem ); // check the trivial case if ( Mvc_CoverIsCubeFree( pDiv ) ) { eNodeDiv = Dec_Factor_rec( pFForm, pDiv ); eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); Mvc_CoverFree( pDiv ); Mvc_CoverFree( pQuo ); eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); if ( Mvc_CoverReadCubeNum(pRem) == 0 ) { Mvc_CoverFree( pRem ); return eNodeAnd; } else { eNodeRem = Dec_Factor_rec( pFForm, pRem ); Mvc_CoverFree( pRem ); return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); } } // get the common cube pCom = Mvc_CoverCommonCubeCover( pDiv ); Mvc_CoverFree( pDiv ); Mvc_CoverFree( pQuo ); Mvc_CoverFree( pRem ); // solve the simple problem eNode = Dec_FactorLF_rec( pFForm, pCover, pCom ); Mvc_CoverFree( pCom ); return eNode; } /**Function************************************************************* Synopsis [Internal recursive factoring procedure for the leaf case.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) { Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); Vec_Int_t * vEdgeLits = pManDec->vLits; Mvc_Cover_t * pDiv, * pQuo, * pRem; Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; Dec_Edge_t eNodeAnd; // get the most often occurring literal pDiv = Mvc_CoverBestLiteralCover( pCover, pSimple ); // divide the cover by the literal Mvc_CoverDivideByLiteral( pCover, pDiv, &pQuo, &pRem ); // get the node pointer for the literal eNodeDiv = Dec_FactorTrivialCube( pFForm, pDiv, Mvc_CoverReadCubeHead(pDiv), vEdgeLits ); Mvc_CoverFree( pDiv ); // factor the quotient and remainder eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); Mvc_CoverFree( pQuo ); eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); if ( Mvc_CoverReadCubeNum(pRem) == 0 ) { Mvc_CoverFree( pRem ); return eNodeAnd; } else { eNodeRem = Dec_Factor_rec( pFForm, pRem ); Mvc_CoverFree( pRem ); return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); } } /**Function************************************************************* Synopsis [Factoring the cover, which has no algebraic divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) { Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); Vec_Int_t * vEdgeCubes = pManDec->vCubes; Vec_Int_t * vEdgeLits = pManDec->vLits; Dec_Edge_t eNode; Mvc_Cube_t * pCube; // create the factored form for each cube Vec_IntClear( vEdgeCubes ); Mvc_CoverForEachCube( pCover, pCube ) { eNode = Dec_FactorTrivialCube( pFForm, pCover, pCube, vEdgeLits ); Vec_IntPush( vEdgeCubes, Dec_EdgeToInt_(eNode) ); } // balance the factored forms return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeCubes->pArray, vEdgeCubes->nSize, 1 ); } /**Function************************************************************* Synopsis [Factoring the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ) { Dec_Edge_t eNode; int iBit, Value; // create the factored form for each literal Vec_IntClear( vEdgeLits ); Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) if ( Value ) { eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) ); } // balance the factored forms return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 ); } /**Function************************************************************* Synopsis [Create the well-balanced tree of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ) { Dec_Edge_t eNode1, eNode2; int nNodes1, nNodes2; if ( nNodes == 1 ) return peNodes[0]; // split the nodes into two parts nNodes1 = nNodes/2; nNodes2 = nNodes - nNodes1; // nNodes2 = nNodes/2; // nNodes1 = nNodes - nNodes2; // recursively construct the tree for the parts eNode1 = Dec_FactorTrivialTree_rec( pFForm, peNodes, nNodes1, fNodeOr ); eNode2 = Dec_FactorTrivialTree_rec( pFForm, peNodes + nNodes1, nNodes2, fNodeOr ); if ( fNodeOr ) return Dec_GraphAddNodeOr( pFForm, eNode1, eNode2 ); else return Dec_GraphAddNodeAnd( pFForm, eNode1, eNode2 ); } /**Function************************************************************* Synopsis [Converts SOP into MVC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ) { Dec_Man_t * pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); Mvc_Manager_t * pMem = (Mvc_Manager_t *)pManDec->pMvcMem; Mvc_Cover_t * pMvc; Mvc_Cube_t * pMvcCube; char * pCube; int nVars, Value, v; // start the cover nVars = Abc_SopGetVarNum(pSop); assert( nVars > 0 ); pMvc = Mvc_CoverAlloc( pMem, nVars * 2 ); // check the logic function of the node Abc_SopForEachCube( pSop, nVars, pCube ) { // create and add the cube pMvcCube = Mvc_CubeAlloc( pMvc ); Mvc_CoverAddCubeTail( pMvc, pMvcCube ); // fill in the literals Mvc_CubeBitFill( pMvcCube ); Abc_CubeForEachVar( pCube, Value, v ) { if ( Value == '0' ) Mvc_CubeBitRemove( pMvcCube, v * 2 + 1 ); else if ( Value == '1' ) Mvc_CubeBitRemove( pMvcCube, v * 2 ); } } return pMvc; } #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Verifies that the factoring is correct.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ) { extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars ); extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ); DdManager * dd = (DdManager *)Abc_FrameReadManDd(); DdNode * bFunc1, * bFunc2; int RetValue; bFunc1 = Abc_ConvertSopToBdd( dd, pSop, NULL ); Cudd_Ref( bFunc1 ); bFunc2 = Dec_GraphDeriveBdd( dd, pFForm ); Cudd_Ref( bFunc2 ); //Extra_bddPrint( dd, bFunc1 ); printf("\n"); //Extra_bddPrint( dd, bFunc2 ); printf("\n"); RetValue = (bFunc1 == bFunc2); if ( bFunc1 != bFunc2 ) { int s; Extra_bddPrint( dd, bFunc1 ); printf("\n"); Extra_bddPrint( dd, bFunc2 ); printf("\n"); s = 0; } Cudd_RecursiveDeref( dd, bFunc1 ); Cudd_RecursiveDeref( dd, bFunc2 ); return RetValue; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/dec/decMan.c000066400000000000000000000047251300674244400230650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [decMan.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Decomposition manager.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: decMan.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "misc/mvc/mvc.h" #include "dec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Start the MVC manager used in the factoring package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Man_t * Dec_ManStart() { Dec_Man_t * p; // abctime clk = Abc_Clock(); p = ABC_ALLOC( Dec_Man_t, 1 ); p->pMvcMem = Mvc_ManagerStart(); p->vCubes = Vec_IntAlloc( 8 ); p->vLits = Vec_IntAlloc( 8 ); // canonical forms, phases, perms Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap ); //ABC_PRT( "NPN classes precomputation time", Abc_Clock() - clk ); return p; } /**Function************************************************************* Synopsis [Stops the MVC maanager used in the factoring package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dec_ManStop( Dec_Man_t * p ) { Mvc_ManagerFree( (Mvc_Manager_t *)p->pMvcMem ); Vec_IntFree( p->vCubes ); Vec_IntFree( p->vLits ); ABC_FREE( p->puCanons ); ABC_FREE( p->pPhases ); ABC_FREE( p->pPerms ); ABC_FREE( p->pMap ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/dec/decPrint.c000066400000000000000000000222041300674244400234360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [decPrint.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Procedures to print the decomposition graphs (factored forms).] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: decPrint.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "dec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ); static int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ); static void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ); static int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prints the decomposition graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ) { Vec_Ptr_t * vNamesIn = NULL; int LitSizeMax, LitSizeCur, Pos, i; // create the names if not given by the user if ( pNamesIn == NULL ) { vNamesIn = Abc_NodeGetFakeNames( Dec_GraphLeaveNum(pGraph) ); pNamesIn = (char **)vNamesIn->pArray; } if ( pNameOut == NULL ) pNameOut = "F"; // get the size of the longest literal LitSizeMax = 0; for ( i = 0; i < Dec_GraphLeaveNum(pGraph); i++ ) { LitSizeCur = strlen(pNamesIn[i]); if ( LitSizeMax < LitSizeCur ) LitSizeMax = LitSizeCur; } if ( LitSizeMax > 50 ) LitSizeMax = 20; // write the decomposition graph (factored form) if ( Dec_GraphIsConst(pGraph) ) // constant { Pos = Dec_GraphPrintOutputName( pFile, pNameOut ); fprintf( pFile, "Constant %d", !Dec_GraphIsComplement(pGraph) ); } else if ( Dec_GraphIsVar(pGraph) ) // literal { Pos = Dec_GraphPrintOutputName( pFile, pNameOut ); Dec_GraphPrintGetLeafName( pFile, Dec_GraphVarInt(pGraph), Dec_GraphIsComplement(pGraph), pNamesIn ); } else { Pos = Dec_GraphPrintOutputName( pFile, pNameOut ); Dec_GraphPrint_rec( pFile, pGraph, Dec_GraphNodeLast(pGraph), Dec_GraphIsComplement(pGraph), pNamesIn, &Pos, LitSizeMax ); } fprintf( pFile, "\n" ); if ( vNamesIn ) Abc_NodeFreeNames( vNamesIn ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) { Dec_Node_t * pNode0, * pNode1; pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) { (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); return; } if ( !pNode->fNodeOr ) // FT_NODE_AND ) { if ( !pNode0->fNodeOr ) // != FT_NODE_OR ) Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); else { fprintf( pFile, "(" ); (*pPos)++; Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); fprintf( pFile, ")" ); (*pPos)++; } fprintf( pFile, " " ); (*pPos)++; Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); if ( !pNode1->fNodeOr ) // != FT_NODE_OR ) Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); else { fprintf( pFile, "(" ); (*pPos)++; Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); fprintf( pFile, ")" ); (*pPos)++; } return; } if ( pNode->fNodeOr ) // FT_NODE_OR ) { Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); fprintf( pFile, " + " ); (*pPos) += 3; Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); return; } assert( 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) { Dec_Node_t * pNode0, * pNode1; Dec_Node_t * pNode00, * pNode01, * pNode10, * pNode11; pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) { (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); return; } if ( !Dec_GraphNodeIsVar(pGraph, pNode0) && !Dec_GraphNodeIsVar(pGraph, pNode1) ) { pNode00 = Dec_GraphNode(pGraph, pNode0->eEdge0.Node); pNode01 = Dec_GraphNode(pGraph, pNode0->eEdge1.Node); pNode10 = Dec_GraphNode(pGraph, pNode1->eEdge0.Node); pNode11 = Dec_GraphNode(pGraph, pNode1->eEdge1.Node); if ( (pNode00 == pNode10 || pNode00 == pNode11) && (pNode01 == pNode10 || pNode01 == pNode11) ) { fprintf( pFile, "(" ); (*pPos)++; Dec_GraphPrint_rec( pFile, pGraph, pNode00, pNode00->fCompl0, pNamesIn, pPos, LitSizeMax ); fprintf( pFile, " # " ); (*pPos) += 3; Dec_GraphPrint_rec( pFile, pGraph, pNode01, pNode01->fCompl1, pNamesIn, pPos, LitSizeMax ); fprintf( pFile, ")" ); (*pPos)++; return; } } if ( fCompl ) { fprintf( pFile, "(" ); (*pPos)++; Dec_GraphPrint_rec( pFile, pGraph, pNode0, !pNode->eEdge0.fCompl, pNamesIn, pPos, LitSizeMax ); fprintf( pFile, " + " ); (*pPos) += 3; Dec_GraphPrint_rec( pFile, pGraph, pNode1, !pNode->eEdge1.fCompl, pNamesIn, pPos, LitSizeMax ); fprintf( pFile, ")" ); (*pPos)++; } else { fprintf( pFile, "(" ); (*pPos)++; Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->eEdge0.fCompl, pNamesIn, pPos, LitSizeMax ); Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->eEdge1.fCompl, pNamesIn, pPos, LitSizeMax ); fprintf( pFile, ")" ); (*pPos)++; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ) { static char Buffer[100]; sprintf( Buffer, "%s%s", fCompl? "!" : "", pNamesIn[iLeaf] ); fprintf( pFile, "%s", Buffer ); return strlen( Buffer ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ) { int i; if ( *pPos + LitSizeMax < 77 ) return; fprintf( pFile, "\n" ); for ( i = 0; i < 10; i++ ) fprintf( pFile, " " ); *pPos = 10; } /**Function************************************************************* Synopsis [Starts the printout for a decomposition graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut ) { if ( pNameOut == NULL ) return 0; fprintf( pFile, "%6s = ", pNameOut ); return 10; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/dec/decUtil.c000066400000000000000000000114051300674244400232600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [decUtil.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Decomposition unitilies.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: decUtil.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "dec.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 graph to BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ) { DdNode * bFunc, * bFunc0, * bFunc1; Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" int i; // sanity checks assert( Dec_GraphLeaveNum(pGraph) >= 0 ); assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Cudd_NotCond( b1, Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Cudd_NotCond( Cudd_bddIthVar(dd, Dec_GraphVarInt(pGraph)), Dec_GraphIsComplement(pGraph) ); // assign the elementary variables Dec_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = Cudd_bddIthVar( dd, i ); // compute the function for each internal node Dec_GraphForEachNode( pGraph, pNode, i ) { bFunc0 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); bFunc1 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( (DdNode *)pNode->pFunc ); } // deref the intermediate results bFunc = (DdNode *)pNode->pFunc; Cudd_Ref( bFunc ); Dec_GraphForEachNode( pGraph, pNode, i ) Cudd_RecursiveDeref( dd, (DdNode *)pNode->pFunc ); Cudd_Deref( bFunc ); // complement the result if necessary return Cudd_NotCond( bFunc, Dec_GraphIsComplement(pGraph) ); } #endif /**Function************************************************************* Synopsis [Derives the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ) { unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; unsigned uTruth = 0; // Suppress "might be used uninitialized" unsigned uTruth0, uTruth1; Dec_Node_t * pNode; int i; // sanity checks assert( Dec_GraphLeaveNum(pGraph) >= 0 ); assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); assert( Dec_GraphLeaveNum(pGraph) <= 5 ); // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Dec_GraphIsComplement(pGraph)? 0 : ~((unsigned)0); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Dec_GraphIsComplement(pGraph)? ~uTruths[Dec_GraphVarInt(pGraph)] : uTruths[Dec_GraphVarInt(pGraph)]; // assign the elementary variables Dec_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = (void *)(ABC_PTRUINT_T)uTruths[i]; // compute the function for each internal node Dec_GraphForEachNode( pGraph, pNode, i ) { uTruth0 = (unsigned)(ABC_PTRUINT_T)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; uTruth1 = (unsigned)(ABC_PTRUINT_T)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0; uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1; uTruth = uTruth0 & uTruth1; pNode->pFunc = (void *)(ABC_PTRUINT_T)uTruth; } // complement the result if necessary return Dec_GraphIsComplement(pGraph)? ~uTruth : uTruth; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/dec/module.make000066400000000000000000000002451300674244400236470ustar00rootroot00000000000000SRC += src/bool/dec/decAbc.c \ src/bool/dec/decFactor.c \ src/bool/dec/decMan.c \ src/bool/dec/decPrint.c \ src/bool/dec/decUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/deco/000077500000000000000000000000001300674244400217015ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/deco/deco.h000066400000000000000000000477071300674244400230030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [deco.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [A simple decomposition tree/node data structure and its APIs.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__deco__deco_h #define ABC__aig__deco__deco_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Dec_Edge_t_ Dec_Edge_t; struct Dec_Edge_t_ { unsigned fCompl : 1; // the complemented bit unsigned Node : 30; // the decomposition node pointed by the edge }; typedef struct Dec_Node_t_ Dec_Node_t; struct Dec_Node_t_ { Dec_Edge_t eEdge0; // the left child of the node Dec_Edge_t eEdge1; // the right child of the node // other info union { int iFunc; // the literal of the node (AIG) void * pFunc; }; // the function of the node (BDD or AIG) unsigned Level : 14; // the level of this node in the global AIG // printing info unsigned fNodeOr : 1; // marks the original OR node unsigned fCompl0 : 1; // marks the original complemented edge unsigned fCompl1 : 1; // marks the original complemented edge // latch info unsigned nLat0 : 5; // the number of latches on the first edge unsigned nLat1 : 5; // the number of latches on the second edge unsigned nLat2 : 5; // the number of latches on the output edge }; typedef struct Dec_Graph_t_ Dec_Graph_t; struct Dec_Graph_t_ { int fConst; // marks the constant 1 graph int nLeaves; // the number of leaves int nSize; // the number of nodes (including the leaves) int nCap; // the number of allocated nodes Dec_Node_t * pNodes; // the array of leaves and internal nodes Dec_Edge_t eRoot; // the pointer to the topmost node }; typedef struct Dec_Man_t_ Dec_Man_t; struct Dec_Man_t_ { void * pMvcMem; // memory manager for MVC cover (used for factoring) Vec_Int_t * vCubes; // storage for cubes Vec_Int_t * vLits; // storage for literals // precomputation information about 4-variable functions unsigned short * puCanons; // canonical forms char * pPhases; // canonical phases char * pPerms; // canonical permutations unsigned char * pMap; // mapping of functions into class numbers }; //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // interator throught the leaves #define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) // interator throught the internal nodes #define Dec_GraphForEachNode( pGraph, pAnd, i ) \ for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates an edge pointing to the node in the given polarity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) { Dec_Edge_t eEdge = { fCompl, Node }; return eEdge; } /**Function************************************************************* Synopsis [Converts the edge into unsigned integer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) { return (eEdge.Node << 1) | eEdge.fCompl; } /**Function************************************************************* Synopsis [Converts unsigned integer into the edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) { return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); } /**Function************************************************************* Synopsis [Converts the edge into unsigned integer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dec_EdgeToInt_( Dec_Edge_t m ) { union { Dec_Edge_t x; unsigned y; } v; v.x = m; return v.y; } /* static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge ) { return *(unsigned *)&eEdge; } */ /**Function************************************************************* Synopsis [Converts unsigned integer into the edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_IntToEdge_( unsigned m ) { union { Dec_Edge_t x; unsigned y; } v; v.y = m; return v.x; } /* static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge ) { return *(Dec_Edge_t *)&Edge; } */ /**Function************************************************************* Synopsis [Creates a graph with the given number of leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves ) { Dec_Graph_t * pGraph; pGraph = ABC_ALLOC( Dec_Graph_t, 1 ); memset( pGraph, 0, sizeof(Dec_Graph_t) ); pGraph->nLeaves = nLeaves; pGraph->nSize = nLeaves; pGraph->nCap = 2 * nLeaves + 50; pGraph->pNodes = ABC_ALLOC( Dec_Node_t, pGraph->nCap ); memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize ); return pGraph; } /**Function************************************************************* Synopsis [Creates constant 0 graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Graph_t * Dec_GraphCreateConst0() { Dec_Graph_t * pGraph; pGraph = ABC_ALLOC( Dec_Graph_t, 1 ); memset( pGraph, 0, sizeof(Dec_Graph_t) ); pGraph->fConst = 1; pGraph->eRoot.fCompl = 1; return pGraph; } /**Function************************************************************* Synopsis [Creates constant 1 graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Graph_t * Dec_GraphCreateConst1() { Dec_Graph_t * pGraph; pGraph = ABC_ALLOC( Dec_Graph_t, 1 ); memset( pGraph, 0, sizeof(Dec_Graph_t) ); pGraph->fConst = 1; return pGraph; } /**Function************************************************************* Synopsis [Creates the literal graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) { Dec_Graph_t * pGraph; assert( 0 <= iLeaf && iLeaf < nLeaves ); pGraph = Dec_GraphCreate( nLeaves ); pGraph->eRoot.Node = iLeaf; pGraph->eRoot.fCompl = fCompl; return pGraph; } /**Function************************************************************* Synopsis [Creates a graph with the given number of leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) { ABC_FREE( pGraph->pNodes ); ABC_FREE( pGraph ); } /**Function************************************************************* Synopsis [Returns 1 if the graph is a constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph ) { return pGraph->fConst; } /**Function************************************************************* Synopsis [Returns 1 if the graph is constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph ) { return pGraph->fConst && pGraph->eRoot.fCompl; } /**Function************************************************************* Synopsis [Returns 1 if the graph is constant 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph ) { return pGraph->fConst && !pGraph->eRoot.fCompl; } /**Function************************************************************* Synopsis [Returns 1 if the graph is complemented.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph ) { return pGraph->eRoot.fCompl; } /**Function************************************************************* Synopsis [Checks if the graph is complemented.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dec_GraphComplement( Dec_Graph_t * pGraph ) { pGraph->eRoot.fCompl ^= 1; } /**Function************************************************************* Synopsis [Returns the number of leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph ) { return pGraph->nLeaves; } /**Function************************************************************* Synopsis [Returns the number of internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph ) { return pGraph->nSize - pGraph->nLeaves; } /**Function************************************************************* Synopsis [Returns the pointer to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i ) { return pGraph->pNodes + i; } /**Function************************************************************* Synopsis [Returns the pointer to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph ) { return pGraph->pNodes + pGraph->nSize - 1; } /**Function************************************************************* Synopsis [Returns the number of the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) { return pNode - pGraph->pNodes; } /**Function************************************************************* Synopsis [Check if the graph represents elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph ) { return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; } /**Function************************************************************* Synopsis [Check if the graph represents elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) { return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; } /**Function************************************************************* Synopsis [Returns the elementary variable elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph ) { assert( Dec_GraphIsVar( pGraph ) ); return Dec_GraphNode( pGraph, pGraph->eRoot.Node ); } /**Function************************************************************* Synopsis [Returns the number of the elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph ) { assert( Dec_GraphIsVar( pGraph ) ); return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) ); } /**Function************************************************************* Synopsis [Sets the root of the graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot ) { pGraph->eRoot = eRoot; } /**Function************************************************************* Synopsis [Appends a new node to the graph.] Description [This procedure is meant for internal use.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph ) { Dec_Node_t * pNode; if ( pGraph->nSize == pGraph->nCap ) { pGraph->pNodes = ABC_REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); pGraph->nCap = 2 * pGraph->nCap; } pNode = pGraph->pNodes + pGraph->nSize++; memset( pNode, 0, sizeof(Dec_Node_t) ); return pNode; } /**Function************************************************************* Synopsis [Creates an AND node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) { Dec_Node_t * pNode; // get the new node pNode = Dec_GraphAppendNode( pGraph ); // set the inputs and other info pNode->eEdge0 = eEdge0; pNode->eEdge1 = eEdge1; pNode->fCompl0 = eEdge0.fCompl; pNode->fCompl1 = eEdge1.fCompl; return Dec_EdgeCreate( pGraph->nSize - 1, 0 ); } /**Function************************************************************* Synopsis [Creates an OR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) { Dec_Node_t * pNode; // get the new node pNode = Dec_GraphAppendNode( pGraph ); // set the inputs and other info pNode->eEdge0 = eEdge0; pNode->eEdge1 = eEdge1; pNode->fCompl0 = eEdge0.fCompl; pNode->fCompl1 = eEdge1.fCompl; // make adjustments for the OR gate pNode->fNodeOr = 1; pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; return Dec_EdgeCreate( pGraph->nSize - 1, 1 ); } /**Function************************************************************* Synopsis [Creates an XOR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type ) { Dec_Edge_t eNode0, eNode1, eNode; if ( Type == 0 ) { // derive the first AND eEdge0.fCompl ^= 1; eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); eEdge0.fCompl ^= 1; // derive the second AND eEdge1.fCompl ^= 1; eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the final OR eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); } else { // derive the first AND eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the second AND eEdge0.fCompl ^= 1; eEdge1.fCompl ^= 1; eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the final OR eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); eNode.fCompl ^= 1; } return eNode; } /**Function************************************************************* Synopsis [Creates an XOR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type ) { Dec_Edge_t eNode0, eNode1, eNode; if ( Type == 0 ) { // derive the first AND eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); // derive the second AND eEdgeC.fCompl ^= 1; eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); // derive the final OR eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); } else { // complement the arguments eEdgeT.fCompl ^= 1; eEdgeE.fCompl ^= 1; // derive the first AND eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); // derive the second AND eEdgeC.fCompl ^= 1; eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); // derive the final OR eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); eNode.fCompl ^= 1; } return eNode; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/deco/module.make000066400000000000000000000000101300674244400240140ustar00rootroot00000000000000SRC += berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/000077500000000000000000000000001300674244400215565ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/cloud.c000066400000000000000000000636631300674244400230460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cloudCore.c] PackageName [Fast application-specific BDD package.] Synopsis [The package core.] Author [Alan Mishchenko ] Affiliation [ECE Department. Portland State University, Portland, Oregon.] Date [Ver. 1.0. Started - June 10, 2002.] Revision [$Id: cloudCore.c,v 1.0 2002/06/10 03:00:00 alanmi Exp $] ***********************************************************************/ #include #include "cloud.h" ABC_NAMESPACE_IMPL_START // the number of operators using cache static int CacheOperNum = 4; // the ratio of cache size to the unique table size for each operator static int CacheLogRatioDefault[4] = { 2, // CLOUD_OPER_AND, 8, // CLOUD_OPER_XOR, 8, // CLOUD_OPER_BDIFF, 8 // CLOUD_OPER_LEQ }; // the ratio of cache size to the unique table size for each operator static int CacheSize[4] = { 2, // CLOUD_OPER_AND, 2, // CLOUD_OPER_XOR, 2, // CLOUD_OPER_BDIFF, 2 // CLOUD_OPER_LEQ }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // static functions static CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ); static void cloudCacheAllocate( CloudManager * dd, CloudOper oper ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function******************************************************************** Synopsis [Starts the cloud manager.] Description [The first arguments is the number of elementary variables used. The second arguments is the number of bits of the unsigned integer used to represent nodes in the unique table. If the second argument is 0, the package assumes 23 to represent nodes, which is equivalent to 2^23 = 8,388,608 nodes.] SideEffects [] SeeAlso [] ******************************************************************************/ CloudManager * Cloud_Init( int nVars, int nBits ) { CloudManager * dd; int i; abctime clk1, clk2; assert( nVars <= 100000 ); assert( nBits < 32 ); // assign the defaults if ( nBits == 0 ) nBits = CLOUD_NODE_BITS; // start the manager dd = ABC_CALLOC( CloudManager, 1 ); dd->nMemUsed += sizeof(CloudManager); // variables dd->nVars = nVars; // the number of variables allocated // bits dd->bitsNode = nBits; // the number of bits used for the node for ( i = 0; i < CacheOperNum; i++ ) dd->bitsCache[i] = nBits - CacheLogRatioDefault[i]; // shifts dd->shiftUnique = 8*sizeof(unsigned) - (nBits + 1); // gets node index in the hash table for ( i = 0; i < CacheOperNum; i++ ) dd->shiftCache[i] = 8*sizeof(unsigned) - dd->bitsCache[i]; // nodes dd->nNodesAlloc = (1 << (nBits + 1)); // 2 ^ (nBits + 1) dd->nNodesLimit = (1 << nBits); // 2 ^ nBits // unique table clk1 = Abc_Clock(); dd->tUnique = ABC_CALLOC( CloudNode, dd->nNodesAlloc ); dd->nMemUsed += sizeof(CloudNode) * dd->nNodesAlloc; clk2 = Abc_Clock(); //ABC_PRT( "calloc() time", clk2 - clk1 ); // set up the constant node (the only node that is not in the hash table) dd->nSignCur = 1; dd->tUnique[0].s = dd->nSignCur; dd->tUnique[0].v = CLOUD_CONST_INDEX; dd->tUnique[0].e = NULL; dd->tUnique[0].t = NULL; dd->one = dd->tUnique; dd->zero = Cloud_Not(dd->one); dd->nNodesCur = 1; // special nodes dd->pNodeStart = dd->tUnique + 1; dd->pNodeEnd = dd->tUnique + dd->nNodesAlloc; // set up the elementary variables dd->vars = ABC_ALLOC( CloudNode *, dd->nVars ); dd->nMemUsed += sizeof(CloudNode *) * dd->nVars; for ( i = 0; i < dd->nVars; i++ ) dd->vars[i] = cloudMakeNode( dd, i, dd->one, dd->zero ); return dd; }; /**Function******************************************************************** Synopsis [Stops the cloud manager.] Description [The first arguments tells show many elementary variables are used. The second arguments tells how many bits of the unsigned integer are used to represent regular nodes in the unique table.] SideEffects [] SeeAlso [] ******************************************************************************/ void Cloud_Quit( CloudManager * dd ) { int i; ABC_FREE( dd->ppNodes ); ABC_FREE( dd->tUnique ); ABC_FREE( dd->vars ); for ( i = 0; i < 4; i++ ) ABC_FREE( dd->tCaches[i] ); ABC_FREE( dd ); } /**Function******************************************************************** Synopsis [Prepares the manager for another run.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Cloud_Restart( CloudManager * dd ) { int i; assert( dd->one->s == dd->nSignCur ); dd->nSignCur++; dd->one->s++; for ( i = 0; i < dd->nVars; i++ ) dd->vars[i]->s++; dd->nNodesCur = 1 + dd->nVars; } /**Function******************************************************************** Synopsis [This optional function allocates operation cache of the given size.] Description [Cache for each operation is allocated independently when the first operation of the given type is performed. The user can allocate cache of his/her preferred size by calling Cloud_CacheAllocate before the first operation of the given type is performed, but this call is optional. Argument "logratio" gives the binary logarithm of the ratio of the size of the unique table to that of cache. For example, if "logratio" is equal to 3, and the unique table will be 2^3=8 times larger than cache; so, if unique table is 2^23 = 8,388,608 nodes, the cache size will be 2^3=8 times smaller and equal to 2^20 = 1,048,576 entries.] SideEffects [] SeeAlso [] ******************************************************************************/ void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int logratio ) { assert( logratio > 0 ); // cache cannot be larger than the unique table assert( logratio < dd->bitsNode ); // cache cannot be smaller than 2 entries if ( logratio ) { dd->bitsCache[oper] = dd->bitsNode - logratio; dd->shiftCache[oper] = 8*sizeof(unsigned) - dd->bitsCache[oper]; } cloudCacheAllocate( dd, oper ); } /**Function******************************************************************** Synopsis [Internal cache allocation.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void cloudCacheAllocate( CloudManager * dd, CloudOper oper ) { int nCacheEntries = (1 << dd->bitsCache[oper]); if ( CacheSize[oper] == 1 ) { dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry1, nCacheEntries ); dd->nMemUsed += sizeof(CloudCacheEntry1) * nCacheEntries; } else if ( CacheSize[oper] == 2 ) { dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry2, nCacheEntries ); dd->nMemUsed += sizeof(CloudCacheEntry2) * nCacheEntries; } else if ( CacheSize[oper] == 3 ) { dd->tCaches[oper] = (CloudCacheEntry2 *)ABC_CALLOC( CloudCacheEntry3, nCacheEntries ); dd->nMemUsed += sizeof(CloudCacheEntry3) * nCacheEntries; } } /**Function******************************************************************** Synopsis [Returns or creates a new node] Description [Checks the unique table for the existance of the node. If the node is present, returns the node. If the node is absent, creates a new node.] SideEffects [] SeeAlso [] ******************************************************************************/ CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ) { CloudNode * pRes; CLOUD_ASSERT(t); CLOUD_ASSERT(e); assert( v < Cloud_V(t) && v < Cloud_V(e) ); // variable should be above in the order if ( Cloud_IsComplement(t) ) { pRes = cloudMakeNode( dd, v, Cloud_Not(t), Cloud_Not(e) ); if ( pRes != NULL ) pRes = Cloud_Not(pRes); } else pRes = cloudMakeNode( dd, v, t, e ); return pRes; } /**Function******************************************************************** Synopsis [Returns or creates a new node] Description [Checks the unique table for the existance of the node. If the node is present, returns the node. If the node is absent, creates a new node.] SideEffects [] SeeAlso [] ******************************************************************************/ CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ) { CloudNode * entryUnique; CLOUD_ASSERT(t); CLOUD_ASSERT(e); assert( ((int)v) >= 0 && ((int)v) < dd->nVars ); // the variable must be in the range assert( v < Cloud_V(t) && v < Cloud_V(e) ); // variable should be above in the order assert( !Cloud_IsComplement(t) ); // the THEN edge must not be complemented // make sure we are not searching for the constant node assert( t && e ); // get the unique entry entryUnique = dd->tUnique + cloudHashCudd3(v, t, e, dd->shiftUnique); while ( entryUnique->s == dd->nSignCur ) { // compare the node if ( entryUnique->v == v && entryUnique->t == t && entryUnique->e == e ) { // the node is found dd->nUniqueHits++; return entryUnique; // returns the node } // increment the hash value modulus the hash table size if ( ++entryUnique - dd->tUnique == dd->nNodesAlloc ) entryUnique = dd->tUnique + 1; // increment the number of steps through the table dd->nUniqueSteps++; } dd->nUniqueMisses++; // check if the new node can be created if ( ++dd->nNodesCur == dd->nNodesLimit ) { // initiate the restart printf( "Cloud needs restart!\n" ); // fflush( stdout ); // exit(1); return NULL; } // create the node entryUnique->s = dd->nSignCur; entryUnique->v = v; entryUnique->t = t; entryUnique->e = e; return entryUnique; // returns the node } /**Function******************************************************************** Synopsis [Performs the AND or two BDDs] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ CloudNode * cloudBddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ) { CloudNode * F, * G, * r; CloudCacheEntry2 * cacheEntry; CloudNode * fv, * fnv, * gv, * gnv, * t, * e; CloudVar var; assert( f <= g ); // terminal cases F = Cloud_Regular(f); G = Cloud_Regular(g); if ( F == G ) { if ( f == g ) return f; else return dd->zero; } if ( F == dd->one ) { if ( f == dd->one ) return g; else return f; } // check cache cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashCudd2(f, g, dd->shiftCache[CLOUD_OPER_AND]); // cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashBuddy2(f, g, dd->shiftCache[CLOUD_OPER_AND]); r = cloudCacheLookup2( cacheEntry, dd->nSignCur, f, g ); if ( r != NULL ) { dd->nCacheHits++; return r; } dd->nCacheMisses++; // compute cofactors if ( cloudV(F) <= cloudV(G) ) { var = cloudV(F); if ( Cloud_IsComplement(f) ) { fnv = Cloud_Not(cloudE(F)); fv = Cloud_Not(cloudT(F)); } else { fnv = cloudE(F); fv = cloudT(F); } } else { var = cloudV(G); fv = fnv = f; } if ( cloudV(G) <= cloudV(F) ) { if ( Cloud_IsComplement(g) ) { gnv = Cloud_Not(cloudE(G)); gv = Cloud_Not(cloudT(G)); } else { gnv = cloudE(G); gv = cloudT(G); } } else { gv = gnv = g; } if ( fv <= gv ) t = cloudBddAnd( dd, fv, gv ); else t = cloudBddAnd( dd, gv, fv ); if ( t == NULL ) return NULL; if ( fnv <= gnv ) e = cloudBddAnd( dd, fnv, gnv ); else e = cloudBddAnd( dd, gnv, fnv ); if ( e == NULL ) return NULL; if ( t == e ) r = t; else { if ( Cloud_IsComplement(t) ) { r = cloudMakeNode( dd, var, Cloud_Not(t), Cloud_Not(e) ); if ( r == NULL ) return NULL; r = Cloud_Not(r); } else { r = cloudMakeNode( dd, var, t, e ); if ( r == NULL ) return NULL; } } cloudCacheInsert2( cacheEntry, dd->nSignCur, f, g, r ); return r; } /**Function******************************************************************** Synopsis [Performs the AND or two BDDs] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ static inline CloudNode * cloudBddAnd_gate( CloudManager * dd, CloudNode * f, CloudNode * g ) { if ( f <= g ) return cloudBddAnd(dd,f,g); else return cloudBddAnd(dd,g,f); } /**Function******************************************************************** Synopsis [Performs the AND or two BDDs] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ) { if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL ) return NULL; CLOUD_ASSERT(f); CLOUD_ASSERT(g); if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) cloudCacheAllocate( dd, CLOUD_OPER_AND ); return cloudBddAnd_gate( dd, f, g ); } /**Function******************************************************************** Synopsis [Performs the OR or two BDDs] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g ) { CloudNode * res; if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL ) return NULL; CLOUD_ASSERT(f); CLOUD_ASSERT(g); if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) cloudCacheAllocate( dd, CLOUD_OPER_AND ); res = cloudBddAnd_gate( dd, Cloud_Not(f), Cloud_Not(g) ); res = Cloud_NotCond( res, res != NULL ); return res; } /**Function******************************************************************** Synopsis [Performs the XOR or two BDDs] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ CloudNode * Cloud_bddXor( CloudManager * dd, CloudNode * f, CloudNode * g ) { CloudNode * t0, * t1, * r; if ( Cloud_Regular(f) == NULL || Cloud_Regular(g) == NULL ) return NULL; CLOUD_ASSERT(f); CLOUD_ASSERT(g); if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) cloudCacheAllocate( dd, CLOUD_OPER_AND ); t0 = cloudBddAnd_gate( dd, f, Cloud_Not(g) ); if ( t0 == NULL ) return NULL; t1 = cloudBddAnd_gate( dd, Cloud_Not(f), g ); if ( t1 == NULL ) return NULL; r = Cloud_bddOr( dd, t0, t1 ); return r; } /**Function******************************************************************** Synopsis [Performs a DFS from f, clearing the LSB of the next pointers.] Description [] SideEffects [None] SeeAlso [cloudSupport cloudDagSize] ******************************************************************************/ static void cloudClearMark( CloudManager * dd, CloudNode * n ) { if ( !cloudNodeIsMarked(n) ) return; // clear visited flag cloudNodeUnmark(n); if ( cloudIsConstant(n) ) return; cloudClearMark( dd, cloudT(n) ); cloudClearMark( dd, Cloud_Regular(cloudE(n)) ); } /**Function******************************************************************** Synopsis [Performs the recursive step of Cloud_Support.] Description [Performs the recursive step of Cloud_Support. Performs a DFS from f. The support is accumulated in supp as a side effect. Uses the LSB of the then pointer as visited flag.] SideEffects [None] SeeAlso [] ******************************************************************************/ static void cloudSupport( CloudManager * dd, CloudNode * n, int * support ) { if ( cloudIsConstant(n) || cloudNodeIsMarked(n) ) return; // set visited flag cloudNodeMark(n); support[cloudV(n)] = 1; cloudSupport( dd, cloudT(n), support ); cloudSupport( dd, Cloud_Regular(cloudE(n)), support ); } /**Function******************************************************************** Synopsis [Finds the variables on which a DD depends.] Description [Finds the variables on which a DD depends. Returns a BDD consisting of the product of the variables if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n ) { CloudNode * res; int * support, i; CLOUD_ASSERT(n); // allocate and initialize support array for cloudSupport support = ABC_CALLOC( int, dd->nVars ); // compute support and clean up markers cloudSupport( dd, Cloud_Regular(n), support ); cloudClearMark( dd, Cloud_Regular(n) ); // transform support from array to cube res = dd->one; for ( i = dd->nVars - 1; i >= 0; i-- ) // for each level bottom-up if ( support[i] == 1 ) { res = Cloud_bddAnd( dd, res, dd->vars[i] ); if ( res == NULL ) break; } ABC_FREE( support ); return res; } /**Function******************************************************************** Synopsis [Counts the variables on which a DD depends.] Description [Counts the variables on which a DD depends. Returns the number of the variables if successful; Cloud_OUT_OF_MEM otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cloud_SupportSize( CloudManager * dd, CloudNode * n ) { int * support, i, count; CLOUD_ASSERT(n); // allocate and initialize support array for cloudSupport support = ABC_CALLOC( int, dd->nVars ); // compute support and clean up markers cloudSupport( dd, Cloud_Regular(n), support ); cloudClearMark( dd, Cloud_Regular(n) ); // count support variables count = 0; for ( i = 0; i < dd->nVars; i++ ) { if ( support[i] == 1 ) count++; } ABC_FREE( support ); return count; } /**Function******************************************************************** Synopsis [Performs the recursive step of Cloud_DagSize.] Description [Performs the recursive step of Cloud_DagSize. Returns the number of nodes in the graph rooted at n.] SideEffects [None] ******************************************************************************/ static int cloudDagSize( CloudManager * dd, CloudNode * n ) { int tval, eval; if ( cloudNodeIsMarked(n) ) return 0; // set visited flag cloudNodeMark(n); if ( cloudIsConstant(n) ) return 1; tval = cloudDagSize( dd, cloudT(n) ); eval = cloudDagSize( dd, Cloud_Regular(cloudE(n)) ); return tval + eval + 1; } /**Function******************************************************************** Synopsis [Counts the number of nodes in a DD.] Description [Counts the number of nodes in a DD. Returns the number of nodes in the graph rooted at node.] SideEffects [] SeeAlso [] ******************************************************************************/ int Cloud_DagSize( CloudManager * dd, CloudNode * n ) { int res; res = cloudDagSize( dd, Cloud_Regular( n ) ); cloudClearMark( dd, Cloud_Regular( n ) ); return res; } /**Function******************************************************************** Synopsis [Performs the recursive step of Cloud_DagSize.] Description [Performs the recursive step of Cloud_DagSize. Returns the number of nodes in the graph rooted at n.] SideEffects [None] ******************************************************************************/ static int Cloud_DagCollect_rec( CloudManager * dd, CloudNode * n, int * pCounter ) { int tval, eval; if ( cloudNodeIsMarked(n) ) return 0; // set visited flag cloudNodeMark(n); if ( cloudIsConstant(n) ) { dd->ppNodes[(*pCounter)++] = n; return 1; } tval = Cloud_DagCollect_rec( dd, cloudT(n), pCounter ); eval = Cloud_DagCollect_rec( dd, Cloud_Regular(cloudE(n)), pCounter ); dd->ppNodes[(*pCounter)++] = n; return tval + eval + 1; } /**Function******************************************************************** Synopsis [Counts the number of nodes in a DD.] Description [Counts the number of nodes in a DD. Returns the number of nodes in the graph rooted at node.] SideEffects [] SeeAlso [] ******************************************************************************/ int Cloud_DagCollect( CloudManager * dd, CloudNode * n ) { int res, Counter = 0; if ( dd->ppNodes == NULL ) dd->ppNodes = ABC_ALLOC( CloudNode *, dd->nNodesLimit ); res = Cloud_DagCollect_rec( dd, Cloud_Regular( n ), &Counter ); cloudClearMark( dd, Cloud_Regular( n ) ); assert( res == Counter ); return res; } /**Function******************************************************************** Synopsis [Counts the number of nodes in an array of DDs.] Description [Counts the number of nodes in a DD. Returns the number of nodes in the graph rooted at node.] SideEffects [] SeeAlso [] ******************************************************************************/ int Cloud_SharingSize( CloudManager * dd, CloudNode ** pn, int nn ) { int res, i; res = 0; for ( i = 0; i < nn; i++ ) res += cloudDagSize( dd, Cloud_Regular( pn[i] ) ); for ( i = 0; i < nn; i++ ) cloudClearMark( dd, Cloud_Regular( pn[i] ) ); return res; } /**Function******************************************************************** Synopsis [Returns one cube contained in the given BDD.] Description [] SideEffects [] ******************************************************************************/ CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * bFunc ) { CloudNode * bFunc0, * bFunc1, * res; if ( Cloud_IsConstant(bFunc) ) return bFunc; // cofactor if ( Cloud_IsComplement(bFunc) ) { bFunc0 = Cloud_Not( cloudE(bFunc) ); bFunc1 = Cloud_Not( cloudT(bFunc) ); } else { bFunc0 = cloudE(bFunc); bFunc1 = cloudT(bFunc); } // try to find the cube with the negative literal res = Cloud_GetOneCube( dd, bFunc0 ); if ( res == NULL ) return NULL; if ( res != dd->zero ) { res = Cloud_bddAnd( dd, res, Cloud_Not(dd->vars[Cloud_V(bFunc)]) ); } else { // try to find the cube with the positive literal res = Cloud_GetOneCube( dd, bFunc1 ); if ( res == NULL ) return NULL; assert( res != dd->zero ); res = Cloud_bddAnd( dd, res, dd->vars[Cloud_V(bFunc)] ); } return res; } /**Function******************************************************************** Synopsis [Prints the BDD as a set of disjoint cubes to the standard output.] Description [] SideEffects [] ******************************************************************************/ void Cloud_bddPrint( CloudManager * dd, CloudNode * Func ) { CloudNode * Cube; int fFirst = 1; if ( Func == dd->zero ) printf( "Constant 0." ); else if ( Func == dd->one ) printf( "Constant 1." ); else { while ( 1 ) { Cube = Cloud_GetOneCube( dd, Func ); if ( Cube == NULL || Cube == dd->zero ) break; if ( fFirst ) fFirst = 0; else printf( " + " ); Cloud_bddPrintCube( dd, Cube ); Func = Cloud_bddAnd( dd, Func, Cloud_Not(Cube) ); } } printf( "\n" ); } /**Function******************************************************************** Synopsis [Prints one cube.] Description [] SideEffects [] ******************************************************************************/ void Cloud_bddPrintCube( CloudManager * dd, CloudNode * bCube ) { CloudNode * bCube0, * bCube1; assert( !Cloud_IsConstant(bCube) ); while ( 1 ) { // get the node structure if ( Cloud_IsConstant(bCube) ) break; // cofactor the cube if ( Cloud_IsComplement(bCube) ) { bCube0 = Cloud_Not( cloudE(bCube) ); bCube1 = Cloud_Not( cloudT(bCube) ); } else { bCube0 = cloudE(bCube); bCube1 = cloudT(bCube); } if ( bCube0 != dd->zero ) { assert( bCube1 == dd->zero ); printf( "[%d]'", cloudV(bCube) ); bCube = bCube0; } else { assert( bCube1 != dd->zero ); printf( "[%d]", cloudV(bCube) ); bCube = bCube1; } } } /**Function******************************************************************** Synopsis [Prints info.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Cloud_PrintInfo( CloudManager * dd ) { if ( dd == NULL ) return; printf( "The number of unique table nodes allocated = %12d.\n", dd->nNodesAlloc ); printf( "The number of unique table nodes present = %12d.\n", dd->nNodesCur ); printf( "The number of unique table hits = %12d.\n", dd->nUniqueHits ); printf( "The number of unique table misses = %12d.\n", dd->nUniqueMisses ); printf( "The number of unique table steps = %12d.\n", dd->nUniqueSteps ); printf( "The number of cache hits = %12d.\n", dd->nCacheHits ); printf( "The number of cache misses = %12d.\n", dd->nCacheMisses ); printf( "The current signature = %12d.\n", dd->nSignCur ); printf( "The total memory in use = %12d.\n", dd->nMemUsed ); } /**Function******************************************************************** Synopsis [Prints the state of the hash table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Cloud_PrintHashTable( CloudManager * dd ) { int i; for ( i = 0; i < dd->nNodesAlloc; i++ ) if ( dd->tUnique[i].v == CLOUD_CONST_INDEX ) printf( "-" ); else printf( "+" ); printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/cloud.h000066400000000000000000000235271300674244400230460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cloud.h] PackageName [Fast application-specific BDD package.] Synopsis [Interface of the package.] Author [Alan Mishchenko ] Affiliation [ECE Department. Portland State University, Portland, Oregon.] Date [Ver. 1.0. Started - June 10, 2002.] Revision [$Id: cloud.h,v 1.0 2002/06/10 03:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__kit__cloud_h #define ABC__aig__kit__cloud_h #include #include #include #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START #ifdef _WIN32 #define inline __inline // compatible with MS VS 6.0 #endif //////////////////////////////////////////////////////////////////////// // n | 2^n || n | 2^n || n | 2^n || n | 2^n // //====================================================================// // 1 | 2 || 9 | 512 || 17 | 131,072 || 25 | 33,554,432 // // 2 | 4 || 10 | 1,024 || 18 | 262,144 || 26 | 67,108,864 // // 3 | 8 || 11 | 2,048 || 19 | 524,288 || 27 | 134,217,728 // // 4 | 16 || 12 | 4,096 || 20 | 1,048,576 || 28 | 268,435,456 // // 5 | 32 || 13 | 8,192 || 21 | 2,097,152 || 29 | 536,870,912 // // 6 | 64 || 14 | 16,384 || 22 | 4,194,304 || 30 | 1,073,741,824 // // 7 | 128 || 15 | 32,768 || 23 | 8,388,608 || 31 | 2,147,483,648 // // 8 | 256 || 16 | 65,536 || 24 | 16,777,216 || 32 | 4,294,967,296 // //////////////////////////////////////////////////////////////////////// // data structure typedefs typedef struct cloudManager CloudManager; typedef unsigned CloudVar; typedef unsigned CloudSign; typedef struct cloudNode CloudNode; typedef struct cloudCacheEntry1 CloudCacheEntry1; typedef struct cloudCacheEntry2 CloudCacheEntry2; typedef struct cloudCacheEntry3 CloudCacheEntry3; // operation codes used to set up the cache typedef enum { CLOUD_OPER_AND, CLOUD_OPER_XOR, CLOUD_OPER_BDIFF, CLOUD_OPER_LEQ } CloudOper; /* // the number of operators using cache static int CacheOperNum = 4; // the ratio of cache size to the unique table size for each operator static int CacheLogRatioDefault[4] = { 4, // CLOUD_OPER_AND, 8, // CLOUD_OPER_XOR, 8, // CLOUD_OPER_BDIFF, 8 // CLOUD_OPER_LEQ }; // the ratio of cache size to the unique table size for each operator static int CacheSize[4] = { 2, // CLOUD_OPER_AND, 2, // CLOUD_OPER_XOR, 2, // CLOUD_OPER_BDIFF, 2 // CLOUD_OPER_LEQ }; */ // data structure definitions struct cloudManager // the fast bdd manager { // variables int nVars; // the number of variables allocated // bits int bitsNode; // the number of bits used for the node int bitsCache[4]; // default: bitsNode - CacheSizeRatio[i] // shifts int shiftUnique; // 8*sizeof(unsigned) - (bitsNode + 1) int shiftCache[4]; // 8*sizeof(unsigned) - bitsCache[i] // nodes int nNodesAlloc; // 2 ^ (bitsNode + 1) int nNodesLimit; // 2 ^ bitsNode int nNodesCur; // the current number of nodes (including const1 and vars) // signature CloudSign nSignCur; // statistics int nMemUsed; // memory usage in bytes // cache stats int nUniqueHits; // hits in the unique table int nUniqueMisses; // misses in the unique table int nCacheHits; // hits in the caches int nCacheMisses; // misses in the caches // the number of steps through the hash table int nUniqueSteps; // tables CloudNode * tUnique; // the unique table to store BDD nodes // special nodes CloudNode * pNodeStart; // the pointer to the first node CloudNode * pNodeEnd; // the pointer to the first node out of the table // constants and variables CloudNode * one; // the one function CloudNode * zero; // the zero function CloudNode ** vars; // the elementary variables // temporary storage for nodes CloudNode ** ppNodes; // caches CloudCacheEntry2 * tCaches[20]; // caches }; struct cloudNode // representation of the node in the unique table { CloudSign s; // signature CloudVar v; // variable CloudNode * e; // negative cofactor CloudNode * t; // positive cofactor }; struct cloudCacheEntry1 // one-argument cache { CloudSign s; // signature CloudNode * a; // argument 1 CloudNode * r; // result }; struct cloudCacheEntry2 // the two-argument cache { CloudSign s; // signature CloudNode * a; CloudNode * b; CloudNode * r; }; struct cloudCacheEntry3 // the three-argument cache { CloudSign s; // signature CloudNode * a; CloudNode * b; CloudNode * c; CloudNode * r; }; // parameters #define CLOUD_NODE_BITS 23 #define CLOUD_CONST_INDEX ((unsigned)0x0fffffff) #define CLOUD_MARK_ON ((unsigned)0x10000000) #define CLOUD_MARK_OFF ((unsigned)0xefffffff) // hash functions a la Buddy #define cloudHashBuddy2(x,y,s) ((((x)+(y))*((x)+(y)+1)/2) & ((1<<(32-(s)))-1)) #define cloudHashBuddy3(x,y,z,s) (cloudHashBuddy2((cloudHashBuddy2((x),(y),(s))),(z),(s)) & ((1<<(32-(s)))-1)) // hash functions a la Cudd #define DD_P1 12582917 #define DD_P2 4256249 #define DD_P3 741457 #define DD_P4 1618033999 #define cloudHashCudd2(f,g,s) ((((unsigned)(ABC_PTRUINT_T)(f) * DD_P1 + (unsigned)(ABC_PTRUINT_T)(g)) * DD_P2) >> (s)) #define cloudHashCudd3(f,g,h,s) (((((unsigned)(ABC_PTRUINT_T)(f) * DD_P1 + (unsigned)(ABC_PTRUINT_T)(g)) * DD_P2 + (unsigned)(ABC_PTRUINT_T)(h)) * DD_P3) >> (s)) // node complementation (using node) #define Cloud_Regular(p) ((CloudNode*)(((ABC_PTRUINT_T)(p)) & ~01)) // get the regular node (w/o bubble) #define Cloud_Not(p) ((CloudNode*)(((ABC_PTRUINT_T)(p)) ^ 01)) // complement the node #define Cloud_NotCond(p,c) ((CloudNode*)(((ABC_PTRUINT_T)(p)) ^ (c))) // complement the node conditionally #define Cloud_IsComplement(p) ((int)(((ABC_PTRUINT_T)(p)) & 01)) // check if complemented // checking constants (using node) #define Cloud_IsConstant(p) (((Cloud_Regular(p))->v & CLOUD_MARK_OFF) == CLOUD_CONST_INDEX) #define cloudIsConstant(p) (((p)->v & CLOUD_MARK_OFF) == CLOUD_CONST_INDEX) // retrieving values from the node (using node structure) #define Cloud_V(p) ((Cloud_Regular(p))->v) #define Cloud_E(p) ((Cloud_Regular(p))->e) #define Cloud_T(p) ((Cloud_Regular(p))->t) // retrieving values from the regular node (using node structure) #define cloudV(p) ((p)->v) #define cloudE(p) ((p)->e) #define cloudT(p) ((p)->t) // marking/unmarking (using node structure) #define cloudNodeMark(p) ((p)->v |= CLOUD_MARK_ON) #define cloudNodeUnmark(p) ((p)->v &= CLOUD_MARK_OFF) #define cloudNodeIsMarked(p) ((int)((p)->v & CLOUD_MARK_ON)) // cache lookups and inserts (using node) #define cloudCacheLookup1(p,sign,f) (((p)->s == (sign) && (p)->a == (f))? ((p)->r): (0)) #define cloudCacheLookup2(p,sign,f,g) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g))? ((p)->r): (0)) #define cloudCacheLookup3(p,sign,f,g,h) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g) && (p)->c == (h))? ((p)->r): (0)) // cache inserts #define cloudCacheInsert1(p,sign,f,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->r = (r))) #define cloudCacheInsert2(p,sign,f,g,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->b = (g)), ((p)->r = (r))) #define cloudCacheInsert3(p,sign,f,g,h,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->b = (g)), ((p)->c = (h)), ((p)->r = (r))) //#define CLOUD_ASSERT(p) (assert((p) >= (dd->pNodeStart-1) && (p) < dd->pNodeEnd)) #define CLOUD_ASSERT(p) assert((p) >= dd->tUnique && (p) < dd->tUnique+dd->nNodesAlloc) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // starting/stopping extern CloudManager * Cloud_Init( int nVars, int nBits ); extern void Cloud_Quit( CloudManager * dd ); extern void Cloud_Restart( CloudManager * dd ); extern void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int size ); extern CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ); // support and node count extern CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n ); extern int Cloud_SupportSize( CloudManager * dd, CloudNode * n ); extern int Cloud_DagSize( CloudManager * dd, CloudNode * n ); extern int Cloud_DagCollect( CloudManager * dd, CloudNode * n ); extern int Cloud_SharingSize( CloudManager * dd, CloudNode * * pn, int nn ); // cubes extern CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * n ); extern void Cloud_bddPrint( CloudManager * dd, CloudNode * Func ); extern void Cloud_bddPrintCube( CloudManager * dd, CloudNode * Cube ); // operations extern CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ); extern CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g ); // stats extern void Cloud_PrintInfo( CloudManager * dd ); extern void Cloud_PrintHashTable( CloudManager * dd ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kit.h000066400000000000000000001053221300674244400225210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kit.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kit.h,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__kit__kit_h #define ABC__aig__kit__kit_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "cloud.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Kit_Sop_t_ Kit_Sop_t; struct Kit_Sop_t_ { int nLits; // the number of literals int nCubes; // the number of cubes unsigned * pCubes; // the storage for cubes }; typedef struct Kit_Edge_t_ Kit_Edge_t; struct Kit_Edge_t_ { unsigned fCompl : 1; // the complemented bit unsigned Node : 30; // the decomposition node pointed by the edge }; typedef struct Kit_Node_t_ Kit_Node_t; struct Kit_Node_t_ { Kit_Edge_t eEdge0; // the left child of the node Kit_Edge_t eEdge1; // the right child of the node // other info union { int iFunc; // the function of the node (BDD or AIG) void * pFunc; }; // the function of the node (BDD or AIG) unsigned Level : 14; // the level of this node in the global AIG // printing info unsigned fNodeOr : 1; // marks the original OR node unsigned fCompl0 : 1; // marks the original complemented edge unsigned fCompl1 : 1; // marks the original complemented edge // latch info unsigned nLat0 : 5; // the number of latches on the first edge unsigned nLat1 : 5; // the number of latches on the second edge unsigned nLat2 : 5; // the number of latches on the output edge }; typedef struct Kit_Graph_t_ Kit_Graph_t; struct Kit_Graph_t_ { int fConst; // marks the constant 1 graph int nLeaves; // the number of leaves int nSize; // the number of nodes (including the leaves) int nCap; // the number of allocated nodes Kit_Node_t * pNodes; // the array of leaves and internal nodes Kit_Edge_t eRoot; // the pointer to the topmost node }; // DSD node types typedef enum { KIT_DSD_NONE = 0, // 0: unknown KIT_DSD_CONST1, // 1: constant 1 KIT_DSD_VAR, // 2: elementary variable KIT_DSD_AND, // 3: multi-input AND KIT_DSD_XOR, // 4: multi-input XOR KIT_DSD_PRIME // 5: arbitrary function of 3+ variables } Kit_Dsd_t; // DSD node typedef struct Kit_DsdObj_t_ Kit_DsdObj_t; struct Kit_DsdObj_t_ { unsigned Id : 6; // the number of this node unsigned Type : 3; // none, const, var, AND, XOR, MUX, PRIME unsigned fMark : 1; // finished checking output unsigned Offset : 8; // offset to the truth table unsigned nRefs : 8; // offset to the truth table unsigned nFans : 6; // the number of fanins of this node unsigned short pFans[0]; // the fanin literals }; // DSD network typedef struct Kit_DsdNtk_t_ Kit_DsdNtk_t; struct Kit_DsdNtk_t_ { unsigned short nVars; // at most 16 (perhaps 18?) unsigned short nNodesAlloc; // the number of allocated nodes (at most nVars) unsigned short nNodes; // the number of nodes unsigned short Root; // the root of the tree unsigned * pMem; // memory for the truth tables (memory manager?) unsigned * pSupps; // supports of the nodes Kit_DsdObj_t** pNodes; // the nodes }; // DSD manager typedef struct Kit_DsdMan_t_ Kit_DsdMan_t; struct Kit_DsdMan_t_ { int nVars; // the maximum number of variables int nWords; // the number of words in TTs Vec_Ptr_t * vTtElems; // elementary truth tables Vec_Ptr_t * vTtNodes; // the node truth tables // BDD representation CloudManager * dd; // BDD package Vec_Ptr_t * vTtBdds; // the node truth tables Vec_Int_t * vNodes; // temporary array for BDD nodes }; static inline unsigned Kit_DsdObjOffset( int nFans ) { return (nFans >> 1) + ((nFans & 1) > 0); } static inline unsigned * Kit_DsdObjTruth( Kit_DsdObj_t * pObj ) { return pObj->Type == KIT_DSD_PRIME ? (unsigned *)pObj->pFans + pObj->Offset: NULL; } static inline int Kit_DsdNtkObjNum( Kit_DsdNtk_t * pNtk ){ return pNtk->nVars + pNtk->nNodes; } static inline Kit_DsdObj_t * Kit_DsdNtkObj( Kit_DsdNtk_t * pNtk, int Id ) { assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return Id < pNtk->nVars ? NULL : pNtk->pNodes[Id - pNtk->nVars]; } static inline Kit_DsdObj_t * Kit_DsdNtkRoot( Kit_DsdNtk_t * pNtk ) { return Kit_DsdNtkObj( pNtk, Abc_Lit2Var(pNtk->Root) ); } static inline int Kit_DsdLitIsLeaf( Kit_DsdNtk_t * pNtk, int Lit ) { int Id = Abc_Lit2Var(Lit); assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return Id < pNtk->nVars; } static inline unsigned Kit_DsdLitSupport( Kit_DsdNtk_t * pNtk, int Lit ) { int Id = Abc_Lit2Var(Lit); assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return pNtk->pSupps? (Id < pNtk->nVars? (1 << Id) : pNtk->pSupps[Id - pNtk->nVars]) : 0; } #define Kit_DsdNtkForEachObj( pNtk, pObj, i ) \ for ( i = 0; (i < (pNtk)->nNodes) && ((pObj) = (pNtk)->pNodes[i]); i++ ) #define Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) \ for ( i = 0; (i < (int)(pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ ) #define Kit_DsdObjForEachFaninReverse( pNtk, pObj, iLit, i ) \ for ( i = (int)(pObj)->nFans - 1; (i >= 0) && ((iLit) = (pObj)->pFans[i], 1); i-- ) #define Kit_PlaForEachCube( pSop, nFanins, pCube ) \ for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) #define Kit_PlaCubeForEachVar( pCube, Value, i ) \ for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define KIT_MIN(a,b) (((a) < (b))? (a) : (b)) #define KIT_MAX(a,b) (((a) > (b))? (a) : (b)) #define KIT_INFINITY (100000000) static inline int Kit_CubeHasLit( unsigned uCube, int i ) { return(uCube & (unsigned)(1< 0; } static inline unsigned Kit_CubeSetLit( unsigned uCube, int i ) { return uCube | (unsigned)(1<> (32-nVar); } static inline int Kit_CubeIsMarked( unsigned uCube ) { return Kit_CubeHasLit( uCube, 31 ); } static inline unsigned Kit_CubeMark( unsigned uCube ) { return Kit_CubeSetLit( uCube, 31 ); } static inline unsigned Kit_CubeUnmark( unsigned uCube ) { return Kit_CubeRemLit( uCube, 31 ); } static inline int Kit_SopCubeNum( Kit_Sop_t * cSop ) { return cSop->nCubes; } static inline unsigned Kit_SopCube( Kit_Sop_t * cSop, int i ) { return cSop->pCubes[i]; } static inline void Kit_SopShrink( Kit_Sop_t * cSop, int nCubesNew ) { cSop->nCubes = nCubesNew; } static inline void Kit_SopPushCube( Kit_Sop_t * cSop, unsigned uCube ) { cSop->pCubes[cSop->nCubes++] = uCube; } static inline void Kit_SopWriteCube( Kit_Sop_t * cSop, unsigned uCube, int i ) { cSop->pCubes[i] = uCube; } static inline Kit_Edge_t Kit_EdgeCreate( int Node, int fCompl ) { Kit_Edge_t eEdge = { fCompl, Node }; return eEdge; } static inline unsigned Kit_EdgeToInt( Kit_Edge_t eEdge ) { return (eEdge.Node << 1) | eEdge.fCompl; } static inline Kit_Edge_t Kit_IntToEdge( unsigned Edge ) { return Kit_EdgeCreate( Edge >> 1, Edge & 1 ); } //static inline unsigned Kit_EdgeToInt_( Kit_Edge_t eEdge ) { return *(unsigned *)&eEdge; } //static inline Kit_Edge_t Kit_IntToEdge_( unsigned Edge ) { return *(Kit_Edge_t *)&Edge; } static inline unsigned Kit_EdgeToInt_( Kit_Edge_t m ) { union { Kit_Edge_t x; unsigned y; } v; v.x = m; return v.y; } static inline Kit_Edge_t Kit_IntToEdge_( unsigned m ) { union { Kit_Edge_t x; unsigned y; } v; v.y = m; return v.x; } static inline int Kit_GraphIsConst( Kit_Graph_t * pGraph ) { return pGraph->fConst; } static inline int Kit_GraphIsConst0( Kit_Graph_t * pGraph ) { return pGraph->fConst && pGraph->eRoot.fCompl; } static inline int Kit_GraphIsConst1( Kit_Graph_t * pGraph ) { return pGraph->fConst && !pGraph->eRoot.fCompl; } static inline int Kit_GraphIsComplement( Kit_Graph_t * pGraph ) { return pGraph->eRoot.fCompl; } static inline int Kit_GraphIsVar( Kit_Graph_t * pGraph ) { return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; } static inline void Kit_GraphComplement( Kit_Graph_t * pGraph ) { pGraph->eRoot.fCompl ^= 1; } static inline void Kit_GraphSetRoot( Kit_Graph_t * pGraph, Kit_Edge_t eRoot ) { pGraph->eRoot = eRoot; } static inline int Kit_GraphLeaveNum( Kit_Graph_t * pGraph ) { return pGraph->nLeaves; } static inline int Kit_GraphNodeNum( Kit_Graph_t * pGraph ) { return pGraph->nSize - pGraph->nLeaves; } static inline Kit_Node_t * Kit_GraphNode( Kit_Graph_t * pGraph, int i ) { return pGraph->pNodes + i; } static inline Kit_Node_t * Kit_GraphNodeLast( Kit_Graph_t * pGraph ) { return pGraph->pNodes + pGraph->nSize - 1; } static inline int Kit_GraphNodeInt( Kit_Graph_t * pGraph, Kit_Node_t * pNode ) { return pNode - pGraph->pNodes; } static inline int Kit_GraphNodeIsVar( Kit_Graph_t * pGraph, Kit_Node_t * pNode ) { return Kit_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; } static inline Kit_Node_t * Kit_GraphVar( Kit_Graph_t * pGraph ) { assert( Kit_GraphIsVar( pGraph ) ); return Kit_GraphNode( pGraph, pGraph->eRoot.Node ); } static inline int Kit_GraphVarInt( Kit_Graph_t * pGraph ) { assert( Kit_GraphIsVar( pGraph ) ); return Kit_GraphNodeInt( pGraph, Kit_GraphVar(pGraph) ); } static inline Kit_Node_t * Kit_GraphNodeFanin0( Kit_Graph_t * pGraph, Kit_Node_t * pNode ){ return Kit_GraphNodeIsVar(pGraph, pNode)? NULL : Kit_GraphNode(pGraph, pNode->eEdge0.Node); } static inline Kit_Node_t * Kit_GraphNodeFanin1( Kit_Graph_t * pGraph, Kit_Node_t * pNode ){ return Kit_GraphNodeIsVar(pGraph, pNode)? NULL : Kit_GraphNode(pGraph, pNode->eEdge1.Node); } static inline int Kit_GraphRootLevel( Kit_Graph_t * pGraph ) { return Kit_GraphNode(pGraph, pGraph->eRoot.Node)->Level; } static inline int Kit_SuppIsMinBase( int Supp ) { return (Supp & (Supp+1)) == 0; } static inline int Kit_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); } static inline int Kit_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } static inline unsigned Kit_BitMask( int nBits ) { assert( nBits <= 32 ); return ~((~(unsigned)0) << nBits); } static inline void Kit_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); } static inline void Kit_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); } static inline int Kit_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; } static inline int Kit_WordFindFirstBit( unsigned uWord ) { int i; for ( i = 0; i < 32; i++ ) if ( uWord & (1 << i) ) return i; return -1; } static inline int Kit_WordHasOneBit( unsigned uWord ) { return (uWord & (uWord - 1)) == 0; } static inline int Kit_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 Kit_TruthCountOnes( unsigned * pIn, int nVars ) { int w, Counter = 0; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) Counter += Kit_WordCountOnes(pIn[w]); return Counter; } static inline int Kit_TruthFindFirstBit( unsigned * pIn, int nVars ) { int w; for ( w = 0; w < Kit_TruthWordNum(nVars); w++ ) if ( pIn[w] ) return 32*w + Kit_WordFindFirstBit(pIn[w]); return -1; } static inline int Kit_TruthFindFirstZero( unsigned * pIn, int nVars ) { int w; for ( w = 0; w < Kit_TruthWordNum(nVars); w++ ) if ( ~pIn[w] ) return 32*w + Kit_WordFindFirstBit(~pIn[w]); return -1; } static inline int Kit_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn0[w] != pIn1[w] ) return 0; return 1; } static inline int Kit_TruthIsEqualWithCare( unsigned * pIn0, unsigned * pIn1, unsigned * pCare, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( (pIn0[w] & pCare[w]) != (pIn1[w] & pCare[w]) ) return 0; return 1; } static inline int Kit_TruthIsOpposite( unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn0[w] != ~pIn1[w] ) return 0; return 1; } static inline int Kit_TruthIsEqualWithPhase( unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; if ( (pIn0[0] & 1) == (pIn1[0] & 1) ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn0[w] != pIn1[w] ) return 0; } else { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn0[w] != ~pIn1[w] ) return 0; } return 1; } static inline int Kit_TruthIsConst0( unsigned * pIn, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn[w] ) return 0; return 1; } static inline int Kit_TruthIsConst1( unsigned * pIn, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn[w] != ~(unsigned)0 ) return 0; return 1; } static inline int Kit_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn1[w] & ~pIn2[w] ) return 0; return 1; } static inline int Kit_TruthIsDisjoint( unsigned * pIn1, unsigned * pIn2, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn1[w] & pIn2[w] ) return 0; return 1; } static inline int Kit_TruthIsDisjoint3( unsigned * pIn1, unsigned * pIn2, unsigned * pIn3, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn1[w] & pIn2[w] & pIn3[w] ) return 0; return 1; } static inline void Kit_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn[w]; } static inline void Kit_TruthClear( unsigned * pOut, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = 0; } static inline void Kit_TruthFill( unsigned * pOut, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(unsigned)0; } static inline void Kit_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn[w]; } static inline void Kit_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & pIn1[w]; } static inline void Kit_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] | pIn1[w]; } static inline void Kit_TruthXor( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] ^ pIn1[w]; } static inline void Kit_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & ~pIn1[w]; } static inline void Kit_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(pIn0[w] & pIn1[w]); } static inline void Kit_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 ) { int w; if ( fCompl0 && fCompl1 ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(pIn0[w] | pIn1[w]); } else if ( fCompl0 && !fCompl1 ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn0[w] & pIn1[w]; } else if ( !fCompl0 && fCompl1 ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & ~pIn1[w]; } else // if ( !fCompl0 && !fCompl1 ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & pIn1[w]; } } static inline void Kit_TruthOrPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 ) { int w; if ( fCompl0 && fCompl1 ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(pIn0[w] & pIn1[w]); } else if ( fCompl0 && !fCompl1 ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn0[w] | pIn1[w]; } else if ( !fCompl0 && fCompl1 ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] | ~pIn1[w]; } else // if ( !fCompl0 && !fCompl1 ) { for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] | pIn1[w]; } } static inline void Kit_TruthMux( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, unsigned * pCtrl, int nVars ) { int w; for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = (pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); } static inline void Kit_TruthMuxPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, unsigned * pCtrl, int nVars, int fComp0 ) { int w; if ( fComp0 ) for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = (~pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); else for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = (pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); } static inline void Kit_TruthIthVar( unsigned * pTruth, int nVars, int iVar ) { unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; int k, nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); if ( iVar < 5 ) { for ( k = 0; k < nWords; k++ ) pTruth[k] = Masks[iVar]; } else { for ( k = 0; k < nWords; k++ ) if ( k & (1 << (iVar-5)) ) pTruth[k] = ~(unsigned)0; else pTruth[k] = 0; } } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// #define Kit_SopForEachCube( cSop, uCube, i ) \ for ( i = 0; (i < Kit_SopCubeNum(cSop)) && ((uCube) = Kit_SopCube(cSop, i)); i++ ) #define Kit_CubeForEachLiteral( uCube, Lit, nLits, i ) \ for ( i = 0; (i < (nLits)) && ((Lit) = Kit_CubeHasLit(uCube, i)); i++ ) #define Kit_GraphForEachLeaf( pGraph, pLeaf, i ) \ for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Kit_GraphNode(pGraph, i)), 1); i++ ) #define Kit_GraphForEachNode( pGraph, pAnd, i ) \ for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Kit_GraphNode(pGraph, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== kitBdd.c ==========================================================*/ #ifdef ABC_USE_CUDD extern DdNode * Kit_SopToBdd( DdManager * dd, Kit_Sop_t * cSop, int nVars ); extern DdNode * Kit_GraphToBdd( DdManager * dd, Kit_Graph_t * pGraph ); extern DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars, int fMSBonTop ); #endif /*=== kitCloud.c ==========================================================*/ extern CloudNode * Kit_TruthToCloud( CloudManager * dd, unsigned * pTruth, int nVars ); extern unsigned * Kit_CloudToTruth( Vec_Int_t * vNodes, int nVars, Vec_Ptr_t * vStore, int fInv ); extern int Kit_CreateCloud( CloudManager * dd, CloudNode * pFunc, Vec_Int_t * vNodes ); extern int Kit_CreateCloudFromTruth( CloudManager * dd, unsigned * pTruth, int nVars, Vec_Int_t * vNodes ); extern unsigned * Kit_TruthCompose( CloudManager * dd, unsigned * pTruth, int nVars, unsigned ** pInputs, int nVarsAll, Vec_Ptr_t * vStore, Vec_Int_t * vNodes ); extern void Kit_TruthCofSupports( Vec_Int_t * vBddDir, Vec_Int_t * vBddInv, int nVars, Vec_Int_t * vMemory, unsigned * puSupps ); /*=== kitDsd.c ==========================================================*/ extern Kit_DsdMan_t * Kit_DsdManAlloc( int nVars, int nNodes ); extern void Kit_DsdManFree( Kit_DsdMan_t * p ); extern Kit_DsdNtk_t * Kit_DsdDeriveNtk( unsigned * pTruth, int nVars, int nLutSize ); extern unsigned * Kit_DsdTruthCompute( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk ); extern void Kit_DsdTruth( Kit_DsdNtk_t * pNtk, unsigned * pTruthRes ); extern void Kit_DsdTruthPartial( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned * pTruthRes, unsigned uSupp ); extern void Kit_DsdTruthPartialTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthCo, unsigned * pTruthDec ); extern void Kit_DsdPrint( FILE * pFile, Kit_DsdNtk_t * pNtk ); extern void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk ); extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); extern void Kit_DsdPrintFromTruth2( FILE * pFile, unsigned * pTruth, int nVars ); extern void Kit_DsdWriteFromTruth( char * pBuffer, unsigned * pTruth, int nVars ); extern Kit_DsdNtk_t * Kit_DsdDecompose( unsigned * pTruth, int nVars ); extern Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars ); extern Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux ); extern void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars ); extern void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk ); extern int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk ); extern Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk ); extern unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk ); extern int Kit_DsdCountAigNodes( Kit_DsdNtk_t * pNtk ); extern unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p ); extern Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p ); extern Kit_DsdNtk_t * Kit_DsdShrink( Kit_DsdNtk_t * p, int pPrios[] ); extern void Kit_DsdRotate( Kit_DsdNtk_t * p, int pFreqs[] ); extern int Kit_DsdCofactoring( unsigned * pTruth, int nVars, int * pCofVars, int nLimit, int fVerbose ); /*=== kitFactor.c ==========================================================*/ extern Kit_Graph_t * Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory ); /*=== kitGraph.c ==========================================================*/ extern Kit_Graph_t * Kit_GraphCreate( int nLeaves ); extern Kit_Graph_t * Kit_GraphCreateConst0(); extern Kit_Graph_t * Kit_GraphCreateConst1(); extern Kit_Graph_t * Kit_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ); extern void Kit_GraphFree( Kit_Graph_t * pGraph ); extern Kit_Node_t * Kit_GraphAppendNode( Kit_Graph_t * pGraph ); extern Kit_Edge_t Kit_GraphAddNodeAnd( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ); extern Kit_Edge_t Kit_GraphAddNodeOr( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ); extern Kit_Edge_t Kit_GraphAddNodeXor( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1, int Type ); extern Kit_Edge_t Kit_GraphAddNodeMux( Kit_Graph_t * pGraph, Kit_Edge_t eEdgeC, Kit_Edge_t eEdgeT, Kit_Edge_t eEdgeE, int Type ); extern unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph ); extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); extern int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf ); /*=== kitHop.c ==========================================================*/ //extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); //extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); //extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); //extern Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ); /*=== kitIsop.c ==========================================================*/ extern int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ); extern void Kit_TruthIsopPrint( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ); extern void Kit_TruthIsopPrintCover( Vec_Int_t * vCover, int nVars, int fCompl ); /*=== kitPla.c ==========================================================*/ extern int Kit_PlaIsConst0( char * pSop ); extern int Kit_PlaIsConst1( char * pSop ); extern int Kit_PlaIsBuf( char * pSop ); extern int Kit_PlaIsInv( char * pSop ); extern int Kit_PlaGetVarNum( char * pSop ); extern int Kit_PlaGetCubeNum( char * pSop ); extern int Kit_PlaIsComplement( char * pSop ); extern void Kit_PlaComplement( char * pSop ); extern char * Kit_PlaStart( void * p, int nCubes, int nVars ); extern char * Kit_PlaCreateFromIsop( void * p, int nVars, Vec_Int_t * vCover ); extern void Kit_PlaToIsop( char * pSop, Vec_Int_t * vCover ); extern char * Kit_PlaStoreSop( void * p, char * pSop ); extern char * Kit_PlaFromTruth( void * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ); extern char * Kit_PlaFromTruthNew( unsigned * pTruth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vStr ); extern ABC_UINT64_T Kit_PlaToTruth6( char * pSop, int nVars ); extern void Kit_PlaToTruth( char * pSop, int nVars, Vec_Ptr_t * vVars, unsigned * pTemp, unsigned * pTruth ); /*=== kitSop.c ==========================================================*/ extern void Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ); extern void Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ); extern void Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ); extern void Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit ); extern void Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ); extern void Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ); extern void Kit_SopMakeCubeFree( Kit_Sop_t * cSop ); extern int Kit_SopIsCubeFree( Kit_Sop_t * cSop ); extern void Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ); extern int Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits ); extern int Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ); extern void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory ); /*=== kitTruth.c ==========================================================*/ extern void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start ); extern void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ); extern void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn ); extern void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ); extern int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ); extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars ); extern unsigned Kit_TruthSupport( unsigned * pTruth, int nVars ); extern void Kit_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ); extern void Kit_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ); extern void Kit_TruthCofactor0New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ); extern void Kit_TruthCofactor1New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ); extern int Kit_TruthVarIsVacuous( unsigned * pOnset, unsigned * pOffset, int nVars, int iVar ); extern void Kit_TruthExist( unsigned * pTruth, int nVars, int iVar ); extern void Kit_TruthExistNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); extern void Kit_TruthExistSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ); extern void Kit_TruthForall( unsigned * pTruth, int nVars, int iVar ); extern void Kit_TruthForallNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); extern void Kit_TruthForallSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ); extern void Kit_TruthUniqueNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); extern void Kit_TruthMuxVar( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ); extern void Kit_TruthMuxVarPhase( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar, int fCompl0 ); extern void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ); extern int Kit_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ); extern int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ); extern int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ); extern int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ); extern void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, int * pStore ); extern void Kit_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, int * pStore ); extern void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, int * pStore, unsigned * pAux ); extern unsigned Kit_TruthHash( unsigned * pIn, int nWords ); extern unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm ); extern char * Kit_TruthDumpToFile( unsigned * pTruth, int nVars, int nFile ); extern void Kit_TruthPrintProfile( unsigned * pTruth, int nVars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitAig.c000066400000000000000000000077121300674244400231410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitAig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Procedures involving AIGs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitAig.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Kit_GraphToAigInternal( Aig_Man_t * pMan, Kit_Graph_t * pGraph ) { Kit_Node_t * pNode = NULL; Aig_Obj_t * pAnd0, * pAnd1; int i; // check for constant function if ( Kit_GraphIsConst(pGraph) ) return Aig_NotCond( Aig_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); // check for a literal if ( Kit_GraphIsVar(pGraph) ) return Aig_NotCond( (Aig_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph Kit_GraphForEachNode( pGraph, pNode, i ) { pAnd0 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Aig_And( pMan, pAnd0, pAnd1 ); } // complement the result if necessary return Aig_NotCond( (Aig_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) ); } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Kit_GraphToAig( Aig_Man_t * pMan, Aig_Obj_t ** pFanins, Kit_Graph_t * pGraph ) { Kit_Node_t * pNode = NULL; int i; // collect the fanins Kit_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = pFanins[i]; // perform strashing return Kit_GraphToAigInternal( pMan, pGraph ); } /**Function************************************************************* Synopsis [Strashed onen logic nodes using its truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Kit_TruthToAig( Aig_Man_t * pMan, Aig_Obj_t ** pFanins, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) { Aig_Obj_t * pObj; Kit_Graph_t * pGraph; // transform truth table into the decomposition tree if ( vMemory == NULL ) { vMemory = Vec_IntAlloc( 0 ); pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); Vec_IntFree( vMemory ); } else pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); // derive the AIG for the decomposition tree pObj = Kit_GraphToAig( pMan, pFanins, pGraph ); Kit_GraphFree( pGraph ); return pObj; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitBdd.c000066400000000000000000000172161300674244400231320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitBdd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Procedures involving BDDs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitBdd.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Derives the BDD for the given SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Kit_SopToBdd( DdManager * dd, Kit_Sop_t * cSop, int nVars ) { DdNode * bSum, * bCube, * bTemp, * bVar; unsigned uCube; int Value, i, v; assert( nVars < 16 ); // start the cover bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum ); // check the logic function of the node Kit_SopForEachCube( cSop, uCube, i ) { bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); for ( v = 0; v < nVars; v++ ) { Value = ((uCube >> 2*v) & 3); if ( Value == 1 ) bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) ); else if ( Value == 2 ) bVar = 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 Cudd_Deref( bSum ); return bSum; } /**Function************************************************************* Synopsis [Converts graph to BDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Kit_GraphToBdd( DdManager * dd, Kit_Graph_t * pGraph ) { DdNode * bFunc, * bFunc0, * bFunc1; Kit_Node_t * pNode = NULL; // Suppress "might be used uninitialized" int i; // sanity checks assert( Kit_GraphLeaveNum(pGraph) >= 0 ); assert( Kit_GraphLeaveNum(pGraph) <= pGraph->nSize ); // check for constant function if ( Kit_GraphIsConst(pGraph) ) return Cudd_NotCond( b1, Kit_GraphIsComplement(pGraph) ); // check for a literal if ( Kit_GraphIsVar(pGraph) ) return Cudd_NotCond( Cudd_bddIthVar(dd, Kit_GraphVarInt(pGraph)), Kit_GraphIsComplement(pGraph) ); // assign the elementary variables Kit_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = Cudd_bddIthVar( dd, i ); // compute the function for each internal node Kit_GraphForEachNode( pGraph, pNode, i ) { bFunc0 = Cudd_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); bFunc1 = Cudd_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( (DdNode *)pNode->pFunc ); } // deref the intermediate results bFunc = (DdNode *)pNode->pFunc; Cudd_Ref( bFunc ); Kit_GraphForEachNode( pGraph, pNode, i ) Cudd_RecursiveDeref( dd, (DdNode *)pNode->pFunc ); Cudd_Deref( bFunc ); // complement the result if necessary return Cudd_NotCond( bFunc, Kit_GraphIsComplement(pGraph) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Kit_TruthToBdd_rec( DdManager * dd, unsigned * pTruth, int iBit, int nVars, int nVarsTotal, int fMSBonTop ) { DdNode * bF0, * bF1, * bF; int Var; if ( nVars <= 5 ) { unsigned uTruth, uMask; uMask = ((~(unsigned)0) >> (32 - (1<>5] >> (iBit&31)) & uMask; if ( uTruth == 0 ) return b0; if ( uTruth == uMask ) return b1; } // find the variable to use Var = fMSBonTop? nVarsTotal-nVars : nVars-1; // other special cases can be added bF0 = Kit_TruthToBdd_rec( dd, pTruth, iBit, nVars-1, nVarsTotal, fMSBonTop ); Cudd_Ref( bF0 ); bF1 = Kit_TruthToBdd_rec( dd, pTruth, iBit+(1<<(nVars-1)), nVars-1, nVarsTotal, fMSBonTop ); Cudd_Ref( bF1 ); bF = Cudd_bddIte( dd, dd->vars[Var], bF1, bF0 ); Cudd_Ref( bF ); Cudd_RecursiveDeref( dd, bF0 ); Cudd_RecursiveDeref( dd, bF1 ); Cudd_Deref( bF ); return bF; } /**Function************************************************************* Synopsis [Compute BDD corresponding to the truth table.] Description [If truth table has N vars, the BDD depends on N topmost variables of the BDD manager. The most significant variable of the table is encoded by the topmost variable of the manager. BDD construction is efficient in this case because BDD is constructed one node at a time, by simply adding BDD nodes on top of existent BDD nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars, int fMSBonTop ) { return Kit_TruthToBdd_rec( dd, pTruth, 0, nVars, nVars, fMSBonTop ); } /**Function************************************************************* Synopsis [Verifies that the factoring is correct.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_SopFactorVerify( Vec_Int_t * vCover, Kit_Graph_t * pFForm, int nVars ) { static DdManager * dd = NULL; Kit_Sop_t Sop, * cSop = &Sop; DdNode * bFunc1, * bFunc2; Vec_Int_t * vMemory; int RetValue; // get the manager if ( dd == NULL ) dd = Cudd_Init( 16, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // derive SOP vMemory = Vec_IntAlloc( Vec_IntSize(vCover) ); Kit_SopCreate( cSop, vCover, nVars, vMemory ); // get the functions bFunc1 = Kit_SopToBdd( dd, cSop, nVars ); Cudd_Ref( bFunc1 ); bFunc2 = Kit_GraphToBdd( dd, pFForm ); Cudd_Ref( bFunc2 ); //Extra_bddPrint( dd, bFunc1 ); printf("\n"); //Extra_bddPrint( dd, bFunc2 ); printf("\n"); RetValue = (bFunc1 == bFunc2); if ( bFunc1 != bFunc2 ) { int s; Extra_bddPrint( dd, bFunc1 ); printf("\n"); Extra_bddPrint( dd, bFunc2 ); printf("\n"); s = 0; } Cudd_RecursiveDeref( dd, bFunc1 ); Cudd_RecursiveDeref( dd, bFunc2 ); Vec_IntFree( vMemory ); return RetValue; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitCloud.c000066400000000000000000000307531300674244400235100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitCloud.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Procedures using BDD package CLOUD.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitCloud.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // internal representation of the function to be decomposed typedef struct Kit_Mux_t_ Kit_Mux_t; struct Kit_Mux_t_ { unsigned v : 5; // variable unsigned t : 12; // then edge unsigned e : 12; // else edge unsigned c : 1; // complemented attr of else edge unsigned i : 1; // complemented attr of top node }; static inline int Kit_Mux2Int( Kit_Mux_t m ) { union { Kit_Mux_t x; int y; } v; v.x = m; return v.y; } static inline Kit_Mux_t Kit_Int2Mux( int m ) { union { Kit_Mux_t x; int y; } v; v.y = m; return v.x; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derive BDD from the truth table for 5 variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ CloudNode * Kit_TruthToCloud5_rec( CloudManager * dd, unsigned uTruth, int nVars, int nVarsAll ) { static unsigned uVars[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; CloudNode * pCof0, * pCof1; unsigned uCof0, uCof1; assert( nVars <= 5 ); if ( uTruth == 0 ) return dd->zero; if ( uTruth == ~0 ) return dd->one; if ( nVars == 1 ) { if ( uTruth == uVars[0] ) return dd->vars[nVarsAll-1]; if ( uTruth == ~uVars[0] ) return Cloud_Not(dd->vars[nVarsAll-1]); assert( 0 ); } // Count++; assert( nVars > 1 ); uCof0 = uTruth & ~uVars[nVars-1]; uCof1 = uTruth & uVars[nVars-1]; uCof0 |= uCof0 << (1<<(nVars-1)); uCof1 |= uCof1 >> (1<<(nVars-1)); if ( uCof0 == uCof1 ) return Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); if ( uCof0 == ~uCof1 ) { pCof0 = Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); pCof1 = Cloud_Not( pCof0 ); } else { pCof0 = Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); pCof1 = Kit_TruthToCloud5_rec( dd, uCof1, nVars - 1, nVarsAll ); } return Cloud_MakeNode( dd, nVarsAll - nVars, pCof1, pCof0 ); } /**Function******************************************************************** Synopsis [Compute BDD for the truth table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ CloudNode * Kit_TruthToCloud_rec( CloudManager * dd, unsigned * pTruth, int nVars, int nVarsAll ) { CloudNode * pCof0, * pCof1; unsigned * pTruth0, * pTruth1; if ( nVars <= 5 ) return Kit_TruthToCloud5_rec( dd, pTruth[0], nVars, nVarsAll ); if ( Kit_TruthIsConst0(pTruth, nVars) ) return dd->zero; if ( Kit_TruthIsConst1(pTruth, nVars) ) return dd->one; // Count++; pTruth0 = pTruth; pTruth1 = pTruth + Kit_TruthWordNum(nVars-1); if ( Kit_TruthIsEqual( pTruth0, pTruth1, nVars - 1 ) ) return Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); if ( Kit_TruthIsOpposite( pTruth0, pTruth1, nVars - 1 ) ) { pCof0 = Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); pCof1 = Cloud_Not( pCof0 ); } else { pCof0 = Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); pCof1 = Kit_TruthToCloud_rec( dd, pTruth1, nVars - 1, nVarsAll ); } return Cloud_MakeNode( dd, nVarsAll - nVars, pCof1, pCof0 ); } /**Function******************************************************************** Synopsis [Compute BDD for the truth table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ CloudNode * Kit_TruthToCloud( CloudManager * dd, unsigned * pTruth, int nVars ) { CloudNode * pRes; pRes = Kit_TruthToCloud_rec( dd, pTruth, nVars, nVars ); // printf( "%d/%d ", Count, Cloud_DagSize(dd, pRes) ); return pRes; } /**Function******************************************************************** Synopsis [Transforms the array of BDDs into the integer array.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Kit_CreateCloud( CloudManager * dd, CloudNode * pFunc, Vec_Int_t * vNodes ) { Kit_Mux_t Mux; int nNodes, i; // collect BDD nodes nNodes = Cloud_DagCollect( dd, pFunc ); if ( nNodes >= (1<<12) ) // because in Kit_Mux_t edge is 12 bit return 0; assert( nNodes == Cloud_DagSize( dd, pFunc ) ); assert( nNodes < dd->nNodesLimit ); Vec_IntClear( vNodes ); Vec_IntPush( vNodes, 0 ); // const1 node dd->ppNodes[0]->s = 0; for ( i = 1; i < nNodes; i++ ) { dd->ppNodes[i]->s = i; Mux.v = dd->ppNodes[i]->v; Mux.t = dd->ppNodes[i]->t->s; Mux.e = Cloud_Regular(dd->ppNodes[i]->e)->s; Mux.c = Cloud_IsComplement(dd->ppNodes[i]->e); Mux.i = (i == nNodes - 1)? Cloud_IsComplement(pFunc) : 0; // put the MUX into the array Vec_IntPush( vNodes, Kit_Mux2Int(Mux) ); } assert( Vec_IntSize(vNodes) == nNodes ); // reset signatures for ( i = 0; i < nNodes; i++ ) dd->ppNodes[i]->s = dd->nSignCur; return 1; } /**Function******************************************************************** Synopsis [Transforms the array of BDDs into the integer array.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Kit_CreateCloudFromTruth( CloudManager * dd, unsigned * pTruth, int nVars, Vec_Int_t * vNodes ) { CloudNode * pFunc; Cloud_Restart( dd ); pFunc = Kit_TruthToCloud( dd, pTruth, nVars ); Vec_IntClear( vNodes ); return Kit_CreateCloud( dd, pFunc, vNodes ); } /**Function************************************************************* Synopsis [Computes composition of truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_CloudToTruth( Vec_Int_t * vNodes, int nVars, Vec_Ptr_t * vStore, int fInv ) { unsigned * pThis, * pFan0, * pFan1; Kit_Mux_t Mux; int i, Entry; assert( Vec_IntSize(vNodes) <= Vec_PtrSize(vStore) ); pThis = (unsigned *)Vec_PtrEntry( vStore, 0 ); Kit_TruthFill( pThis, nVars ); Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) { Mux = Kit_Int2Mux(Entry); assert( (int)Mux.e < i && (int)Mux.t < i && (int)Mux.v < nVars ); pFan0 = (unsigned *)Vec_PtrEntry( vStore, Mux.e ); pFan1 = (unsigned *)Vec_PtrEntry( vStore, Mux.t ); pThis = (unsigned *)Vec_PtrEntry( vStore, i ); Kit_TruthMuxVarPhase( pThis, pFan0, pFan1, nVars, fInv? Mux.v : nVars-1-Mux.v, Mux.c ); } // complement the result if ( Mux.i ) Kit_TruthNot( pThis, pThis, nVars ); return pThis; } /**Function************************************************************* Synopsis [Computes composition of truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_TruthCompose( CloudManager * dd, unsigned * pTruth, int nVars, unsigned ** pInputs, int nVarsAll, Vec_Ptr_t * vStore, Vec_Int_t * vNodes ) { CloudNode * pFunc; unsigned * pThis, * pFan0, * pFan1; Kit_Mux_t Mux; int i, Entry, RetValue; // derive BDD from truth table Cloud_Restart( dd ); pFunc = Kit_TruthToCloud( dd, pTruth, nVars ); // convert it into nodes RetValue = Kit_CreateCloud( dd, pFunc, vNodes ); if ( RetValue == 0 ) printf( "Kit_TruthCompose(): Internal failure!!!\n" ); // verify the result // pFan0 = Kit_CloudToTruth( vNodes, nVars, vStore, 0 ); // if ( !Kit_TruthIsEqual( pTruth, pFan0, nVars ) ) // printf( "Failed!\n" ); // compute truth table from the BDD assert( Vec_IntSize(vNodes) <= Vec_PtrSize(vStore) ); pThis = (unsigned *)Vec_PtrEntry( vStore, 0 ); Kit_TruthFill( pThis, nVarsAll ); Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) { Mux = Kit_Int2Mux(Entry); pFan0 = (unsigned *)Vec_PtrEntry( vStore, Mux.e ); pFan1 = (unsigned *)Vec_PtrEntry( vStore, Mux.t ); pThis = (unsigned *)Vec_PtrEntry( vStore, i ); Kit_TruthMuxPhase( pThis, pFan0, pFan1, pInputs[nVars-1-Mux.v], nVarsAll, Mux.c ); } // complement the result if ( Mux.i ) Kit_TruthNot( pThis, pThis, nVarsAll ); return pThis; } /**Function******************************************************************** Synopsis [Compute BDD for the truth table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Kit_TruthCofSupports( Vec_Int_t * vBddDir, Vec_Int_t * vBddInv, int nVars, Vec_Int_t * vMemory, unsigned * puSupps ) { Kit_Mux_t Mux; unsigned * puSuppAll; unsigned * pThis = NULL; // Suppress "might be used uninitialized" unsigned * pFan0, * pFan1; int i, v, Var, Entry, nSupps; nSupps = 2 * nVars; // extend storage if ( Vec_IntSize( vMemory ) < nSupps * Vec_IntSize(vBddDir) ) Vec_IntGrow( vMemory, nSupps * Vec_IntSize(vBddDir) ); puSuppAll = (unsigned *)Vec_IntArray( vMemory ); // clear storage for the const node memset( puSuppAll, 0, sizeof(unsigned) * nSupps ); // compute supports from nodes Vec_IntForEachEntryStart( vBddDir, Entry, i, 1 ) { Mux = Kit_Int2Mux(Entry); Var = nVars - 1 - Mux.v; pFan0 = puSuppAll + nSupps * Mux.e; pFan1 = puSuppAll + nSupps * Mux.t; pThis = puSuppAll + nSupps * i; for ( v = 0; v < nSupps; v++ ) pThis[v] = pFan0[v] | pFan1[v] | (1<nVarsMax = nVarsMax; p->nWordsMax = Kit_TruthWordNum( p->nVarsMax ); p->vTruthVars = Vec_PtrAllocTruthTables( p->nVarsMax ); p->vTruthNodes = Vec_PtrAllocSimInfo( 64, p->nWordsMax ); p->vLutsIn = Vec_IntAlloc( 50 ); p->vSuppIn = Vec_IntAlloc( 50 ); p->vLutsOut = Vec_IntAlloc( 50 ); p->vSuppOut = Vec_IntAlloc( 50 ); 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 Kit_ManDecStop( Kit_ManDec_t * p ) { ABC_FREE( p->pTruthIn ); ABC_FREE( p->pTruthOut ); Vec_IntFreeP( &p->vLutsIn ); Vec_IntFreeP( &p->vSuppIn ); Vec_IntFreeP( &p->vLutsOut ); Vec_IntFreeP( &p->vSuppOut ); Vec_PtrFreeP( &p->vTruthVars ); Vec_PtrFreeP( &p->vTruthNodes ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Deriving timing information for the decomposed structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DecComputeOuputArrival( int nVars, Vec_Int_t * vSupps, int LutSize, char ATimesIn[], char ATimesOut[] ) { int i, v, iVar, nLuts, Delay; nLuts = Vec_IntSize(vSupps) / LutSize; assert( nLuts > 0 ); assert( Vec_IntSize(vSupps) % LutSize == 0 ); for ( v = 0; v < nVars; v++ ) ATimesOut[v] = ATimesIn[v]; for ( v = 0; v < nLuts; v++ ) { Delay = 0; for ( i = 0; i < LutSize; i++ ) { iVar = Vec_IntEntry( vSupps, v * LutSize + i ); assert( iVar < nVars + v ); Delay = Abc_MaxInt( Delay, ATimesOut[iVar] ); } ATimesOut[nVars + v] = Delay + 1; } return ATimesOut[nVars + nLuts - 1]; } /**Function************************************************************* Synopsis [Derives the truth table] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DecComputeTruthOne( int LutSize, unsigned * pTruthLut, int nVars, unsigned * pTruths[], unsigned * pTemp, unsigned * pRes ) { int i, v; Kit_TruthClear( pRes, nVars ); for ( i = 0; i < (1< 0 ); assert( Vec_IntSize(vSupps) % LutSize == 0 ); assert( nLuts * nTruthLutWords == Vec_IntSize(vLuts) ); for ( v = 0; v < nLuts; v++ ) { for ( i = 0; i < LutSize; i++ ) { iVar = Vec_IntEntry( vSupps, v * LutSize + i ); assert( iVar < nVars + v ); pTruths[i] = (iVar < nVars)? (unsigned *)Vec_PtrEntry(p->vTruthVars, iVar) : (unsigned *)Vec_PtrEntry(p->vTruthNodes, iVar-nVars); } pResult = (v == nLuts - 1) ? pRes : (unsigned *)Vec_PtrEntry(p->vTruthNodes, v); Kit_DecComputeTruthOne( LutSize, pTruthLuts, nVars, pTruths, (unsigned *)Vec_PtrEntry(p->vTruthNodes, v+1), pResult ); pTruthLuts += nTruthLutWords; } } /**Function************************************************************* Synopsis [Derives the truth table] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DecComputePattern( int nVars, unsigned * pTruth, int LutSize, int Pattern[] ) { int nCofs = (1 << LutSize); int i, k, nMyu = 0; assert( LutSize <= 6 ); assert( LutSize < nVars ); if ( nVars - LutSize <= 5 ) { unsigned uCofs[64]; int nBits = (1 << (nVars - LutSize)); for ( i = 0; i < nCofs; i++ ) uCofs[i] = (pTruth[(i*nBits)/32] >> ((i*nBits)%32)) & ((1<= 0 && Shared1[m] >= 0 && Shared0[u] == Shared1[m] ) { Shared[nShared++] = Shared0[u]; Shared0[u] = Shared1[m] = -1; } return nShared; } return 0; } /**Function************************************************************* Synopsis [Returns the number of shared variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DecComputeShared( int Pattern[], int LutSize, int Shared[] ) { int i, Vars[6]; assert( LutSize <= 6 ); for ( i = 0; i < LutSize; i++ ) Vars[i] = i; return Kit_DecComputeShared_rec( Pattern, Vars, LutSize, Shared, 0 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitDsd.c000066400000000000000000003314131300674244400231510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Performs disjoint-support decomposition based on truth tables.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitDsd.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the DSD manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdMan_t * Kit_DsdManAlloc( int nVars, int nNodes ) { Kit_DsdMan_t * p; p = ABC_ALLOC( Kit_DsdMan_t, 1 ); memset( p, 0, sizeof(Kit_DsdMan_t) ); p->nVars = nVars; p->nWords = Kit_TruthWordNum( p->nVars ); p->vTtElems = Vec_PtrAllocTruthTables( p->nVars ); p->vTtNodes = Vec_PtrAllocSimInfo( nNodes, p->nWords ); p->dd = Cloud_Init( 16, 14 ); p->vTtBdds = Vec_PtrAllocSimInfo( (1<<12), p->nWords ); p->vNodes = Vec_IntAlloc( 512 ); return p; } /**Function************************************************************* Synopsis [Deallocates the DSD manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdManFree( Kit_DsdMan_t * p ) { Cloud_Quit( p->dd ); Vec_IntFree( p->vNodes ); Vec_PtrFree( p->vTtBdds ); Vec_PtrFree( p->vTtElems ); Vec_PtrFree( p->vTtNodes ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Allocates the DSD node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdObj_t * Kit_DsdObjAlloc( Kit_DsdNtk_t * pNtk, Kit_Dsd_t Type, int nFans ) { Kit_DsdObj_t * pObj; int nSize = sizeof(Kit_DsdObj_t) + sizeof(unsigned) * (Kit_DsdObjOffset(nFans) + (Type == KIT_DSD_PRIME) * Kit_TruthWordNum(nFans)); pObj = (Kit_DsdObj_t *)ABC_ALLOC( char, nSize ); memset( pObj, 0, nSize ); pObj->Id = pNtk->nVars + pNtk->nNodes; pObj->Type = Type; pObj->nFans = nFans; pObj->Offset = Kit_DsdObjOffset( nFans ); // add the object if ( pNtk->nNodes == pNtk->nNodesAlloc ) { pNtk->nNodesAlloc *= 2; pNtk->pNodes = ABC_REALLOC( Kit_DsdObj_t *, pNtk->pNodes, pNtk->nNodesAlloc ); } assert( pNtk->nNodes < pNtk->nNodesAlloc ); pNtk->pNodes[pNtk->nNodes++] = pObj; return pObj; } /**Function************************************************************* Synopsis [Deallocates the DSD node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdObjFree( Kit_DsdNtk_t * p, Kit_DsdObj_t * pObj ) { ABC_FREE( pObj ); } /**Function************************************************************* Synopsis [Allocates the DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdNtk_t * Kit_DsdNtkAlloc( int nVars ) { Kit_DsdNtk_t * pNtk; pNtk = ABC_ALLOC( Kit_DsdNtk_t, 1 ); memset( pNtk, 0, sizeof(Kit_DsdNtk_t) ); pNtk->pNodes = ABC_ALLOC( Kit_DsdObj_t *, nVars+1 ); pNtk->nVars = nVars; pNtk->nNodesAlloc = nVars+1; pNtk->pMem = ABC_ALLOC( unsigned, 6 * Kit_TruthWordNum(nVars) ); return pNtk; } /**Function************************************************************* Synopsis [Deallocate the DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk ) { Kit_DsdObj_t * pObj; unsigned i; Kit_DsdNtkForEachObj( pNtk, pObj, i ) ABC_FREE( pObj ); ABC_FREE( pNtk->pSupps ); ABC_FREE( pNtk->pNodes ); ABC_FREE( pNtk->pMem ); ABC_FREE( pNtk ); } /**Function************************************************************* Synopsis [Prints the hex unsigned into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrintHex( FILE * pFile, unsigned * pTruth, int nFans ) { int nDigits, Digit, k; nDigits = (1 << nFans) / 4; for ( k = nDigits - 1; k >= 0; k-- ) { Digit = ((pTruth[k/8] >> ((k%8) * 4)) & 15); if ( Digit < 10 ) fprintf( pFile, "%d", Digit ); else fprintf( pFile, "%c", 'A' + Digit-10 ); } } /**Function************************************************************* Synopsis [Prints the hex unsigned into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_DsdWriteHex( char * pBuff, unsigned * pTruth, int nFans ) { int nDigits, Digit, k; nDigits = (1 << nFans) / 4; for ( k = nDigits - 1; k >= 0; k-- ) { Digit = ((pTruth[k/8] >> ((k%8) * 4)) & 15); if ( Digit < 10 ) *pBuff++ = '0' + Digit; else *pBuff++ = 'A' + Digit-10; } return pBuff; } /**Function************************************************************* Synopsis [Recursively print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrint2_rec( FILE * pFile, Kit_DsdNtk_t * pNtk, int Id ) { Kit_DsdObj_t * pObj; unsigned iLit, i; char Symbol; pObj = Kit_DsdNtkObj( pNtk, Id ); if ( pObj == NULL ) { assert( Id < pNtk->nVars ); fprintf( pFile, "%c", 'a' + Id ); return; } if ( pObj->Type == KIT_DSD_CONST1 ) { assert( pObj->nFans == 0 ); fprintf( pFile, "Const1" ); return; } if ( pObj->Type == KIT_DSD_VAR ) assert( pObj->nFans == 1 ); if ( pObj->Type == KIT_DSD_AND ) Symbol = '*'; else if ( pObj->Type == KIT_DSD_XOR ) Symbol = '+'; else Symbol = ','; if ( pObj->Type == KIT_DSD_PRIME ) fprintf( pFile, "[" ); else fprintf( pFile, "(" ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { if ( Abc_LitIsCompl(iLit) ) fprintf( pFile, "!" ); Kit_DsdPrint2_rec( pFile, pNtk, Abc_Lit2Var(iLit) ); if ( i < pObj->nFans - 1 ) fprintf( pFile, "%c", Symbol ); } if ( pObj->Type == KIT_DSD_PRIME ) fprintf( pFile, "]" ); else fprintf( pFile, ")" ); } /**Function************************************************************* Synopsis [Print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrint2( FILE * pFile, Kit_DsdNtk_t * pNtk ) { // fprintf( pFile, "F = " ); if ( Abc_LitIsCompl(pNtk->Root) ) fprintf( pFile, "!" ); Kit_DsdPrint2_rec( pFile, pNtk, Abc_Lit2Var(pNtk->Root) ); // fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Recursively print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrint_rec( FILE * pFile, Kit_DsdNtk_t * pNtk, int Id ) { Kit_DsdObj_t * pObj; unsigned iLit, i; char Symbol; pObj = Kit_DsdNtkObj( pNtk, Id ); if ( pObj == NULL ) { assert( Id < pNtk->nVars ); fprintf( pFile, "%c", 'a' + Id ); return; } if ( pObj->Type == KIT_DSD_CONST1 ) { assert( pObj->nFans == 0 ); fprintf( pFile, "Const1" ); return; } if ( pObj->Type == KIT_DSD_VAR ) assert( pObj->nFans == 1 ); if ( pObj->Type == KIT_DSD_AND ) Symbol = '*'; else if ( pObj->Type == KIT_DSD_XOR ) Symbol = '+'; else Symbol = ','; if ( pObj->Type == KIT_DSD_PRIME ) Kit_DsdPrintHex( pFile, Kit_DsdObjTruth(pObj), pObj->nFans ); fprintf( pFile, "(" ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { if ( Abc_LitIsCompl(iLit) ) fprintf( pFile, "!" ); Kit_DsdPrint_rec( pFile, pNtk, Abc_Lit2Var(iLit) ); if ( i < pObj->nFans - 1 ) fprintf( pFile, "%c", Symbol ); } fprintf( pFile, ")" ); } /**Function************************************************************* Synopsis [Print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrint( FILE * pFile, Kit_DsdNtk_t * pNtk ) { fprintf( pFile, "F = " ); if ( Abc_LitIsCompl(pNtk->Root) ) fprintf( pFile, "!" ); Kit_DsdPrint_rec( pFile, pNtk, Abc_Lit2Var(pNtk->Root) ); // fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Recursively print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_DsdWrite_rec( char * pBuff, Kit_DsdNtk_t * pNtk, int Id ) { Kit_DsdObj_t * pObj; unsigned iLit, i; char Symbol; pObj = Kit_DsdNtkObj( pNtk, Id ); if ( pObj == NULL ) { assert( Id < pNtk->nVars ); *pBuff++ = 'a' + Id; return pBuff; } if ( pObj->Type == KIT_DSD_CONST1 ) { assert( pObj->nFans == 0 ); sprintf( pBuff, "%s", "Const1" ); return pBuff + strlen("Const1"); } if ( pObj->Type == KIT_DSD_VAR ) assert( pObj->nFans == 1 ); if ( pObj->Type == KIT_DSD_AND ) Symbol = '*'; else if ( pObj->Type == KIT_DSD_XOR ) Symbol = '+'; else Symbol = ','; if ( pObj->Type == KIT_DSD_PRIME ) pBuff = Kit_DsdWriteHex( pBuff, Kit_DsdObjTruth(pObj), pObj->nFans ); *pBuff++ = '('; Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { if ( Abc_LitIsCompl(iLit) ) *pBuff++ = '!'; pBuff = Kit_DsdWrite_rec( pBuff, pNtk, Abc_Lit2Var(iLit) ); if ( i < pObj->nFans - 1 ) *pBuff++ = Symbol; } *pBuff++ = ')'; return pBuff; } /**Function************************************************************* Synopsis [Print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdWrite( char * pBuff, Kit_DsdNtk_t * pNtk ) { if ( Abc_LitIsCompl(pNtk->Root) ) *pBuff++ = '!'; pBuff = Kit_DsdWrite_rec( pBuff, pNtk, Abc_Lit2Var(pNtk->Root) ); *pBuff = 0; } /**Function************************************************************* Synopsis [Print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk ) { Kit_DsdNtk_t * pTemp; pTemp = Kit_DsdExpand( pNtk ); Kit_DsdPrint( stdout, pTemp ); Kit_DsdNtkFree( pTemp ); } /**Function************************************************************* Synopsis [Print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ) { Kit_DsdNtk_t * pTemp, * pTemp2; // pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 8 ); // Kit_DsdPrintExpanded( pTemp ); pTemp2 = Kit_DsdExpand( pTemp ); Kit_DsdPrint( stdout, pTemp2 ); Kit_DsdVerify( pTemp2, pTruth, nVars ); Kit_DsdNtkFree( pTemp2 ); Kit_DsdNtkFree( pTemp ); } /**Function************************************************************* Synopsis [Print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrintFromTruth2( FILE * pFile, unsigned * pTruth, int nVars ) { Kit_DsdNtk_t * pTemp, * pTemp2; pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 0 ); pTemp2 = Kit_DsdExpand( pTemp ); Kit_DsdPrint2( pFile, pTemp2 ); Kit_DsdVerify( pTemp2, pTruth, nVars ); Kit_DsdNtkFree( pTemp2 ); Kit_DsdNtkFree( pTemp ); } /**Function************************************************************* Synopsis [Print the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdWriteFromTruth( char * pBuffer, unsigned * pTruth, int nVars ) { Kit_DsdNtk_t * pTemp, * pTemp2; // pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 8 ); // Kit_DsdPrintExpanded( pTemp ); pTemp2 = Kit_DsdExpand( pTemp ); Kit_DsdWrite( pBuffer, pTemp2 ); Kit_DsdVerify( pTemp2, pTruth, nVars ); Kit_DsdNtkFree( pTemp2 ); Kit_DsdNtkFree( pTemp ); } /**Function************************************************************* Synopsis [Derives the truth table of the DSD node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_DsdTruthComputeNode_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id ) { Kit_DsdObj_t * pObj; unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; unsigned i, iLit, fCompl; // unsigned m, nMints, * pTruthPrime, * pTruthMint; // get the node with this ID pObj = Kit_DsdNtkObj( pNtk, Id ); pTruthRes = (unsigned *)Vec_PtrEntry( p->vTtNodes, Id ); // special case: literal of an internal node if ( pObj == NULL ) { assert( Id < pNtk->nVars ); return pTruthRes; } // constant node if ( pObj->Type == KIT_DSD_CONST1 ) { assert( pObj->nFans == 0 ); Kit_TruthFill( pTruthRes, pNtk->nVars ); return pTruthRes; } // elementary variable node if ( pObj->Type == KIT_DSD_VAR ) { assert( pObj->nFans == 1 ); iLit = pObj->pFans[0]; pTruthFans[0] = Kit_DsdTruthComputeNode_rec( p, pNtk, Abc_Lit2Var(iLit) ); if ( Abc_LitIsCompl(iLit) ) Kit_TruthNot( pTruthRes, pTruthFans[0], pNtk->nVars ); else Kit_TruthCopy( pTruthRes, pTruthFans[0], pNtk->nVars ); return pTruthRes; } // collect the truth tables of the fanins Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) pTruthFans[i] = Kit_DsdTruthComputeNode_rec( p, pNtk, Abc_Lit2Var(iLit) ); // create the truth table // simple gates if ( pObj->Type == KIT_DSD_AND ) { Kit_TruthFill( pTruthRes, pNtk->nVars ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) ); return pTruthRes; } if ( pObj->Type == KIT_DSD_XOR ) { Kit_TruthClear( pTruthRes, pNtk->nVars ); fCompl = 0; Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); fCompl ^= Abc_LitIsCompl(iLit); } if ( fCompl ) Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); return pTruthRes; } assert( pObj->Type == KIT_DSD_PRIME ); /* // get the truth table of the prime node pTruthPrime = Kit_DsdObjTruth( pObj ); // get storage for the temporary minterm pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); // go through the minterms nMints = (1 << pObj->nFans); Kit_TruthClear( pTruthRes, pNtk->nVars ); for ( m = 0; m < nMints; m++ ) { if ( !Kit_TruthHasBit(pTruthPrime, m) ) continue; Kit_TruthFill( pTruthMint, pNtk->nVars ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); } */ Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) if ( Abc_LitIsCompl(iLit) ) Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars ); pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); return pTruthRes; } /**Function************************************************************* Synopsis [Derives the truth table of the DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_DsdTruthCompute( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk ) { unsigned * pTruthRes; int i; // assign elementary truth ables assert( pNtk->nVars <= p->nVars ); for ( i = 0; i < (int)pNtk->nVars; i++ ) Kit_TruthCopy( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars ); // compute truth table for each node pTruthRes = Kit_DsdTruthComputeNode_rec( p, pNtk, Abc_Lit2Var(pNtk->Root) ); // complement the truth table if needed if ( Abc_LitIsCompl(pNtk->Root) ) Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); return pTruthRes; } /**Function************************************************************* Synopsis [Derives the truth table of the DSD node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_DsdTruthComputeNodeOne_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id, unsigned uSupp ) { Kit_DsdObj_t * pObj; unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; unsigned i, iLit, fCompl, nPartial = 0; // unsigned m, nMints, * pTruthPrime, * pTruthMint; // get the node with this ID pObj = Kit_DsdNtkObj( pNtk, Id ); pTruthRes = (unsigned *)Vec_PtrEntry( p->vTtNodes, Id ); // special case: literal of an internal node if ( pObj == NULL ) { assert( Id < pNtk->nVars ); assert( !uSupp || uSupp != (uSupp & ~(1<Type == KIT_DSD_CONST1 ) { assert( pObj->nFans == 0 ); Kit_TruthFill( pTruthRes, pNtk->nVars ); return pTruthRes; } // elementary variable node if ( pObj->Type == KIT_DSD_VAR ) { assert( pObj->nFans == 1 ); iLit = pObj->pFans[0]; assert( Kit_DsdLitIsLeaf( pNtk, iLit ) ); pTruthFans[0] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), uSupp ); if ( Abc_LitIsCompl(iLit) ) Kit_TruthNot( pTruthRes, pTruthFans[0], pNtk->nVars ); else Kit_TruthCopy( pTruthRes, pTruthFans[0], pNtk->nVars ); return pTruthRes; } // collect the truth tables of the fanins if ( uSupp ) { Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) if ( uSupp != (uSupp & ~Kit_DsdLitSupport(pNtk, iLit)) ) pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), uSupp ); else { pTruthFans[i] = NULL; nPartial = 1; } } else { Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), uSupp ); } // create the truth table // simple gates if ( pObj->Type == KIT_DSD_AND ) { Kit_TruthFill( pTruthRes, pNtk->nVars ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) if ( pTruthFans[i] ) Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) ); return pTruthRes; } if ( pObj->Type == KIT_DSD_XOR ) { Kit_TruthClear( pTruthRes, pNtk->nVars ); fCompl = 0; Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { if ( pTruthFans[i] ) { Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); fCompl ^= Abc_LitIsCompl(iLit); } } if ( fCompl ) Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); return pTruthRes; } assert( pObj->Type == KIT_DSD_PRIME ); if ( uSupp && nPartial ) { // find the only non-empty component Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) if ( pTruthFans[i] ) break; assert( i < pObj->nFans ); return pTruthFans[i]; } /* // get the truth table of the prime node pTruthPrime = Kit_DsdObjTruth( pObj ); // get storage for the temporary minterm pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); // go through the minterms nMints = (1 << pObj->nFans); Kit_TruthClear( pTruthRes, pNtk->nVars ); for ( m = 0; m < nMints; m++ ) { if ( !Kit_TruthHasBit(pTruthPrime, m) ) continue; Kit_TruthFill( pTruthMint, pNtk->nVars ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); } */ Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) if ( Abc_LitIsCompl(iLit) ) Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars ); pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); return pTruthRes; } /**Function************************************************************* Synopsis [Derives the truth table of the DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_DsdTruthComputeOne( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp ) { unsigned * pTruthRes; int i; // if support is specified, request that supports are available if ( uSupp ) Kit_DsdGetSupports( pNtk ); // assign elementary truth tables assert( pNtk->nVars <= p->nVars ); for ( i = 0; i < (int)pNtk->nVars; i++ ) Kit_TruthCopy( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars ); // compute truth table for each node pTruthRes = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(pNtk->Root), uSupp ); // complement the truth table if needed if ( Abc_LitIsCompl(pNtk->Root) ) Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); return pTruthRes; } /**Function************************************************************* Synopsis [Derives the truth table of the DSD node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_DsdTruthComputeNodeTwo_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id, unsigned uSupp, int iVar, unsigned * pTruthDec ) { Kit_DsdObj_t * pObj; int pfBoundSet[16]; unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; unsigned i, iLit, fCompl, nPartial, uSuppFan, uSuppCur; // unsigned m, nMints, * pTruthPrime, * pTruthMint; assert( uSupp > 0 ); // get the node with this ID pObj = Kit_DsdNtkObj( pNtk, Id ); pTruthRes = (unsigned *)Vec_PtrEntry( p->vTtNodes, Id ); if ( pObj == NULL ) { assert( Id < pNtk->nVars ); return pTruthRes; } assert( pObj->Type != KIT_DSD_CONST1 ); assert( pObj->Type != KIT_DSD_VAR ); // count the number of intersecting fanins // collect the total support of the intersecting fanins nPartial = 0; uSuppFan = 0; Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { uSuppCur = Kit_DsdLitSupport(pNtk, iLit); if ( uSupp & uSuppCur ) { nPartial++; uSuppFan |= uSuppCur; } } // if there is no intersection, or full intersection, use simple procedure if ( nPartial == 0 || nPartial == pObj->nFans ) return Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Id, 0 ); // if support of the component includes some other variables // we need to continue constructing it as usual by the two-function procedure if ( uSuppFan != (uSuppFan & uSupp) ) { assert( nPartial == 1 ); // return Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Id, uSupp, iVar, pTruthDec ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { if ( uSupp & Kit_DsdLitSupport(pNtk, iLit) ) pTruthFans[i] = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Abc_Lit2Var(iLit), uSupp, iVar, pTruthDec ); else pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), 0 ); } // create composition/decomposition functions if ( pObj->Type == KIT_DSD_AND ) { Kit_TruthFill( pTruthRes, pNtk->nVars ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) ); return pTruthRes; } if ( pObj->Type == KIT_DSD_XOR ) { Kit_TruthClear( pTruthRes, pNtk->nVars ); fCompl = 0; Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { fCompl ^= Abc_LitIsCompl(iLit); Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); } if ( fCompl ) Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); return pTruthRes; } assert( pObj->Type == KIT_DSD_PRIME ); } else { assert( uSuppFan == (uSuppFan & uSupp) ); assert( nPartial < pObj->nFans ); // the support of the insecting component(s) is contained in the bound-set // and yet there are components that are not contained in the bound set // solve the fanins and collect info, which components belong to the bound set Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Abc_Lit2Var(iLit), 0 ); pfBoundSet[i] = (int)((uSupp & Kit_DsdLitSupport(pNtk, iLit)) > 0); } // create composition/decomposition functions if ( pObj->Type == KIT_DSD_AND ) { Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); Kit_TruthFill( pTruthDec, pNtk->nVars ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) if ( pfBoundSet[i] ) Kit_TruthAndPhase( pTruthDec, pTruthDec, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) ); else Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Abc_LitIsCompl(iLit) ); return pTruthRes; } if ( pObj->Type == KIT_DSD_XOR ) { Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); Kit_TruthClear( pTruthDec, pNtk->nVars ); fCompl = 0; Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) { fCompl ^= Abc_LitIsCompl(iLit); if ( pfBoundSet[i] ) Kit_TruthXor( pTruthDec, pTruthDec, pTruthFans[i], pNtk->nVars ); else Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); } if ( fCompl ) Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); return pTruthRes; } assert( pObj->Type == KIT_DSD_PRIME ); assert( nPartial == 1 ); // find the only non-empty component Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) if ( pfBoundSet[i] ) break; assert( i < pObj->nFans ); // save this component as the decomposed function Kit_TruthCopy( pTruthDec, pTruthFans[i], pNtk->nVars ); // set the corresponding component to be the new variable Kit_TruthIthVar( pTruthFans[i], pNtk->nVars, iVar ); } /* // get the truth table of the prime node pTruthPrime = Kit_DsdObjTruth( pObj ); // get storage for the temporary minterm pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); // go through the minterms nMints = (1 << pObj->nFans); Kit_TruthClear( pTruthRes, pNtk->nVars ); for ( m = 0; m < nMints; m++ ) { if ( !Kit_TruthHasBit(pTruthPrime, m) ) continue; Kit_TruthFill( pTruthMint, pNtk->nVars ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); } */ // Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) // assert( !Abc_LitIsCompl(iLit) ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) if ( Abc_LitIsCompl(iLit) ) Kit_TruthNot( pTruthFans[i], pTruthFans[i], pNtk->nVars ); pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); return pTruthRes; } /**Function************************************************************* Synopsis [Derives the truth table of the DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_DsdTruthComputeTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthDec ) { unsigned * pTruthRes, uSuppAll; int i; assert( uSupp > 0 ); assert( pNtk->nVars <= p->nVars ); // compute support of all nodes uSuppAll = Kit_DsdGetSupports( pNtk ); // consider special case - there is no overlap if ( (uSupp & uSuppAll) == 0 ) { Kit_TruthClear( pTruthDec, pNtk->nVars ); return Kit_DsdTruthCompute( p, pNtk ); } // consider special case - support is fully contained if ( (uSupp & uSuppAll) == uSuppAll ) { pTruthRes = Kit_DsdTruthCompute( p, pNtk ); Kit_TruthCopy( pTruthDec, pTruthRes, pNtk->nVars ); Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); return pTruthRes; } // assign elementary truth tables for ( i = 0; i < (int)pNtk->nVars; i++ ) Kit_TruthCopy( (unsigned *)Vec_PtrEntry(p->vTtNodes, i), (unsigned *)Vec_PtrEntry(p->vTtElems, i), p->nVars ); // compute truth table for each node pTruthRes = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Abc_Lit2Var(pNtk->Root), uSupp, iVar, pTruthDec ); // complement the truth table if needed if ( Abc_LitIsCompl(pNtk->Root) ) Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); return pTruthRes; } /**Function************************************************************* Synopsis [Derives the truth table of the DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdTruth( Kit_DsdNtk_t * pNtk, unsigned * pTruthRes ) { Kit_DsdMan_t * p; unsigned * pTruth; p = Kit_DsdManAlloc( pNtk->nVars, Kit_DsdNtkObjNum(pNtk) ); pTruth = Kit_DsdTruthCompute( p, pNtk ); Kit_TruthCopy( pTruthRes, pTruth, pNtk->nVars ); Kit_DsdManFree( p ); } /**Function************************************************************* Synopsis [Derives the truth table of the DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdTruthPartialTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthCo, unsigned * pTruthDec ) { unsigned * pTruth = Kit_DsdTruthComputeTwo( p, pNtk, uSupp, iVar, pTruthDec ); if ( pTruthCo ) Kit_TruthCopy( pTruthCo, pTruth, pNtk->nVars ); } /**Function************************************************************* Synopsis [Derives the truth table of the DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdTruthPartial( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned * pTruthRes, unsigned uSupp ) { unsigned * pTruth = Kit_DsdTruthComputeOne( p, pNtk, uSupp ); Kit_TruthCopy( pTruthRes, pTruth, pNtk->nVars ); /* // verification { // compute the same function using different procedure unsigned * pTruthTemp = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes + 1); pNtk->pSupps = NULL; Kit_DsdTruthComputeTwo( p, pNtk, uSupp, -1, pTruthTemp ); // if ( !Kit_TruthIsEqual( pTruthTemp, pTruthRes, pNtk->nVars ) ) if ( !Kit_TruthIsEqualWithPhase( pTruthTemp, pTruthRes, pNtk->nVars ) ) { printf( "Verification FAILED!\n" ); Kit_DsdPrint( stdout, pNtk ); Kit_DsdPrintFromTruth( pTruthRes, pNtk->nVars ); Kit_DsdPrintFromTruth( pTruthTemp, pNtk->nVars ); } // else // printf( "Verification successful.\n" ); } */ } /**Function************************************************************* Synopsis [Counts the number of blocks of the given number of inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdCountLuts_rec( Kit_DsdNtk_t * pNtk, int nLutSize, int Id, int * pCounter ) { Kit_DsdObj_t * pObj; unsigned iLit, i, Res0, Res1; pObj = Kit_DsdNtkObj( pNtk, Id ); if ( pObj == NULL ) return 0; if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) { assert( pObj->nFans == 2 ); Res0 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(pObj->pFans[0]), pCounter ); Res1 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(pObj->pFans[1]), pCounter ); if ( Res0 == 0 && Res1 > 0 ) return Res1 - 1; if ( Res0 > 0 && Res1 == 0 ) return Res0 - 1; (*pCounter)++; return nLutSize - 2; } assert( pObj->Type == KIT_DSD_PRIME ); if ( (int)pObj->nFans > nLutSize ) //+ 1 ) { *pCounter = 1000; return 0; } Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(iLit), pCounter ); (*pCounter)++; // if ( (int)pObj->nFans == nLutSize + 1 ) // (*pCounter)++; return nLutSize - pObj->nFans; } /**Function************************************************************* Synopsis [Counts the number of blocks of the given number of inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdCountLuts( Kit_DsdNtk_t * pNtk, int nLutSize ) { int Counter = 0; if ( Kit_DsdNtkRoot(pNtk)->Type == KIT_DSD_CONST1 ) return 0; if ( Kit_DsdNtkRoot(pNtk)->Type == KIT_DSD_VAR ) return 0; Kit_DsdCountLuts_rec( pNtk, nLutSize, Abc_Lit2Var(pNtk->Root), &Counter ); if ( Counter >= 1000 ) return -1; return Counter; } /**Function************************************************************* Synopsis [Returns the size of the largest non-DSD block.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk ) { Kit_DsdObj_t * pObj; unsigned i, nSizeMax = 0; Kit_DsdNtkForEachObj( pNtk, pObj, i ) { if ( pObj->Type != KIT_DSD_PRIME ) continue; if ( nSizeMax < pObj->nFans ) nSizeMax = pObj->nFans; } return nSizeMax; } /**Function************************************************************* Synopsis [Returns the largest non-DSD block.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdObj_t * Kit_DsdNonDsdPrimeMax( Kit_DsdNtk_t * pNtk ) { Kit_DsdObj_t * pObj, * pObjMax = NULL; unsigned i, nSizeMax = 0; Kit_DsdNtkForEachObj( pNtk, pObj, i ) { if ( pObj->Type != KIT_DSD_PRIME ) continue; if ( nSizeMax < pObj->nFans ) { nSizeMax = pObj->nFans; pObjMax = pObj; } } return pObjMax; } /**Function************************************************************* Synopsis [Finds the union of supports of the non-DSD blocks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk ) { Kit_DsdObj_t * pObj; unsigned i, uSupport = 0; // ABC_FREE( pNtk->pSupps ); Kit_DsdGetSupports( pNtk ); Kit_DsdNtkForEachObj( pNtk, pObj, i ) { if ( pObj->Type != KIT_DSD_PRIME ) continue; uSupport |= Kit_DsdLitSupport( pNtk, Abc_Var2Lit(pObj->Id,0) ); } return uSupport; } /**Function************************************************************* Synopsis [Expands the node.] Description [Returns the new literal.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdExpandCollectAnd_rec( Kit_DsdNtk_t * p, unsigned iLit, unsigned * piLitsNew, int * nLitsNew ) { Kit_DsdObj_t * pObj; unsigned i, iLitFanin; // check the end of the supergate pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( Abc_LitIsCompl(iLit) || Abc_Lit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_AND ) { piLitsNew[(*nLitsNew)++] = iLit; return; } // iterate through the fanins Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) Kit_DsdExpandCollectAnd_rec( p, iLitFanin, piLitsNew, nLitsNew ); } /**Function************************************************************* Synopsis [Expands the node.] Description [Returns the new literal.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdExpandCollectXor_rec( Kit_DsdNtk_t * p, unsigned iLit, unsigned * piLitsNew, int * nLitsNew ) { Kit_DsdObj_t * pObj; unsigned i, iLitFanin; // check the end of the supergate pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( Abc_Lit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_XOR ) { piLitsNew[(*nLitsNew)++] = iLit; return; } // iterate through the fanins pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) Kit_DsdExpandCollectXor_rec( p, iLitFanin, piLitsNew, nLitsNew ); // if the literal was complemented, pass the complemented attribute somewhere if ( Abc_LitIsCompl(iLit) ) piLitsNew[0] = Abc_LitNot( piLitsNew[0] ); } /**Function************************************************************* Synopsis [Expands the node.] Description [Returns the new literal.] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdExpandNode_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit ) { unsigned * pTruth, * pTruthNew; unsigned i, iLitFanin, piLitsNew[16], nLitsNew = 0; Kit_DsdObj_t * pObj, * pObjNew; // consider the case of simple gate pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) return iLit; if ( pObj->Type == KIT_DSD_AND ) { Kit_DsdExpandCollectAnd_rec( p, Abc_LitRegular(iLit), piLitsNew, (int *)&nLitsNew ); pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_AND, nLitsNew ); for ( i = 0; i < pObjNew->nFans; i++ ) pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, piLitsNew[i] ); return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) ); } if ( pObj->Type == KIT_DSD_XOR ) { int fCompl = Abc_LitIsCompl(iLit); Kit_DsdExpandCollectXor_rec( p, Abc_LitRegular(iLit), piLitsNew, (int *)&nLitsNew ); pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, nLitsNew ); for ( i = 0; i < pObjNew->nFans; i++ ) { pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, Abc_LitRegular(piLitsNew[i]) ); fCompl ^= Abc_LitIsCompl(piLitsNew[i]); } return Abc_Var2Lit( pObjNew->Id, fCompl ); } assert( pObj->Type == KIT_DSD_PRIME ); // create new PRIME node pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_PRIME, pObj->nFans ); // copy the truth table pTruth = Kit_DsdObjTruth( pObj ); pTruthNew = Kit_DsdObjTruth( pObjNew ); Kit_TruthCopy( pTruthNew, pTruth, pObj->nFans ); // create fanins Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) { pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, iLitFanin ); // complement the corresponding inputs of the truth table if ( Abc_LitIsCompl(pObjNew->pFans[i]) ) { pObjNew->pFans[i] = Abc_LitRegular(pObjNew->pFans[i]); Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); } } if ( pObj->nFans == 3 && (pTruthNew[0] == 0xCACACACA || pTruthNew[0] == 0xC5C5C5C5 || pTruthNew[0] == 0x3A3A3A3A || pTruthNew[0] == 0x35353535) ) { // translate into regular MUXes if ( pTruthNew[0] == 0xC5C5C5C5 ) pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]); else if ( pTruthNew[0] == 0x3A3A3A3A ) pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]); else if ( pTruthNew[0] == 0x35353535 ) { pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]); pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]); } pTruthNew[0] = 0xCACACACA; // resolve the complemented control input if ( Abc_LitIsCompl(pObjNew->pFans[2]) ) { unsigned char Temp = pObjNew->pFans[0]; pObjNew->pFans[0] = pObjNew->pFans[1]; pObjNew->pFans[1] = Temp; pObjNew->pFans[2] = Abc_LitNot(pObjNew->pFans[2]); } // resolve the complemented true input if ( Abc_LitIsCompl(pObjNew->pFans[1]) ) { iLit = Abc_LitNot(iLit); pObjNew->pFans[0] = Abc_LitNot(pObjNew->pFans[0]); pObjNew->pFans[1] = Abc_LitNot(pObjNew->pFans[1]); } return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) ); } else { // if the incoming phase is complemented, absorb it into the prime node if ( Abc_LitIsCompl(iLit) ) Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); return Abc_Var2Lit( pObjNew->Id, 0 ); } } /**Function************************************************************* Synopsis [Expands the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p ) { Kit_DsdNtk_t * pNew; Kit_DsdObj_t * pObjNew; assert( p->nVars <= 16 ); // create a new network pNew = Kit_DsdNtkAlloc( p->nVars ); // consider simple special cases if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) { pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); pNew->Root = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(p->Root) ); return pNew; } if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) { pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); pObjNew->pFans[0] = Kit_DsdNtkRoot(p)->pFans[0]; pNew->Root = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(p->Root) ); return pNew; } // convert the root node pNew->Root = Kit_DsdExpandNode_rec( pNew, p, p->Root ); return pNew; } /**Function************************************************************* Synopsis [Sorts the literals by their support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdCompSort( int pPrios[], unsigned uSupps[], unsigned short * piLits, int nVars, unsigned piLitsRes[] ) { int nSuppSizes[16], Priority[16], pOrder[16]; int i, k, iVarBest, SuppMax, PrioMax; // compute support sizes and priorities of the components for ( i = 0; i < nVars; i++ ) { assert( uSupps[i] ); pOrder[i] = i; Priority[i] = KIT_INFINITY; for ( k = 0; k < 16; k++ ) if ( uSupps[i] & (1 << k) ) Priority[i] = KIT_MIN( Priority[i], pPrios[k] ); assert( Priority[i] != 16 ); nSuppSizes[i] = Kit_WordCountOnes(uSupps[i]); } // sort the components by pririty Extra_BubbleSort( pOrder, Priority, nVars, 0 ); // find the component by with largest size and lowest priority iVarBest = -1; SuppMax = 0; PrioMax = 0; for ( i = 0; i < nVars; i++ ) { if ( SuppMax < nSuppSizes[i] || (SuppMax == nSuppSizes[i] && PrioMax < Priority[i]) ) { SuppMax = nSuppSizes[i]; PrioMax = Priority[i]; iVarBest = i; } } assert( iVarBest != -1 ); // copy the resulting literals k = 0; piLitsRes[k++] = piLits[iVarBest]; for ( i = 0; i < nVars; i++ ) { if ( pOrder[i] == iVarBest ) continue; piLitsRes[k++] = piLits[pOrder[i]]; } assert( k == nVars ); } /**Function************************************************************* Synopsis [Shrinks multi-input nodes.] Description [Takes the array of variable priorities pPrios.] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdShrink_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit, int pPrios[] ) { Kit_DsdObj_t * pObj; Kit_DsdObj_t * pObjNew = NULL; // Suppress "might be used uninitialized" unsigned * pTruth, * pTruthNew; unsigned i, piLitsNew[16], uSupps[16]; int iLitFanin, iLitNew; // consider the case of simple gate pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) return iLit; if ( pObj->Type == KIT_DSD_AND ) { // get the supports Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) uSupps[i] = Kit_DsdLitSupport( p, iLitFanin ); // put the largest component last // sort other components in the decreasing order of priority of their vars Kit_DsdCompSort( pPrios, uSupps, pObj->pFans, pObj->nFans, piLitsNew ); // construct the two-input node network iLitNew = Kit_DsdShrink_rec( pNew, p, piLitsNew[0], pPrios ); for ( i = 1; i < pObj->nFans; i++ ) { pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_AND, 2 ); pObjNew->pFans[0] = Kit_DsdShrink_rec( pNew, p, piLitsNew[i], pPrios ); pObjNew->pFans[1] = iLitNew; iLitNew = Abc_Var2Lit( pObjNew->Id, 0 ); } return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) ); } if ( pObj->Type == KIT_DSD_XOR ) { // get the supports Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) { assert( !Abc_LitIsCompl(iLitFanin) ); uSupps[i] = Kit_DsdLitSupport( p, iLitFanin ); } // put the largest component last // sort other components in the decreasing order of priority of their vars Kit_DsdCompSort( pPrios, uSupps, pObj->pFans, pObj->nFans, piLitsNew ); // construct the two-input node network iLitNew = Kit_DsdShrink_rec( pNew, p, piLitsNew[0], pPrios ); for ( i = 1; i < pObj->nFans; i++ ) { pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, 2 ); pObjNew->pFans[0] = Kit_DsdShrink_rec( pNew, p, piLitsNew[i], pPrios ); pObjNew->pFans[1] = iLitNew; iLitNew = Abc_Var2Lit( pObjNew->Id, 0 ); } return Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(iLit) ); } assert( pObj->Type == KIT_DSD_PRIME ); // create new PRIME node pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_PRIME, pObj->nFans ); // copy the truth table pTruth = Kit_DsdObjTruth( pObj ); pTruthNew = Kit_DsdObjTruth( pObjNew ); Kit_TruthCopy( pTruthNew, pTruth, pObj->nFans ); // create fanins Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) { pObjNew->pFans[i] = Kit_DsdShrink_rec( pNew, p, iLitFanin, pPrios ); // complement the corresponding inputs of the truth table if ( Abc_LitIsCompl(pObjNew->pFans[i]) ) { pObjNew->pFans[i] = Abc_LitRegular(pObjNew->pFans[i]); Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); } } // if the incoming phase is complemented, absorb it into the prime node if ( Abc_LitIsCompl(iLit) ) Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); return Abc_Var2Lit( pObjNew->Id, 0 ); } /**Function************************************************************* Synopsis [Shrinks the network.] Description [Transforms the network to have two-input nodes so that the higher-ordered nodes were decomposed out first.] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdNtk_t * Kit_DsdShrink( Kit_DsdNtk_t * p, int pPrios[] ) { Kit_DsdNtk_t * pNew; Kit_DsdObj_t * pObjNew; assert( p->nVars <= 16 ); // create a new network pNew = Kit_DsdNtkAlloc( p->nVars ); // consider simple special cases if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) { pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); pNew->Root = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(p->Root) ); return pNew; } if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) { pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); pObjNew->pFans[0] = Kit_DsdNtkRoot(p)->pFans[0]; pNew->Root = Abc_Var2Lit( pObjNew->Id, Abc_LitIsCompl(p->Root) ); return pNew; } // convert the root node pNew->Root = Kit_DsdShrink_rec( pNew, p, p->Root, pPrios ); return pNew; } /**Function************************************************************* Synopsis [Rotates the network.] Description [Transforms prime nodes to have the fanin with the highest frequency of supports go first.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdRotate( Kit_DsdNtk_t * p, int pFreqs[] ) { Kit_DsdObj_t * pObj; unsigned * pIn, * pOut, * pTemp, k; int i, v, Temp, uSuppFanin, iFaninLit, WeightMax, FaninMax, nSwaps; int Weights[16]; // go through the prime nodes Kit_DsdNtkForEachObj( p, pObj, i ) { if ( pObj->Type != KIT_DSD_PRIME ) continue; // count the fanin frequencies Kit_DsdObjForEachFanin( p, pObj, iFaninLit, k ) { uSuppFanin = Kit_DsdLitSupport( p, iFaninLit ); Weights[k] = 0; for ( v = 0; v < 16; v++ ) if ( uSuppFanin & (1 << v) ) Weights[k] += pFreqs[v] - 1; } // find the most frequent fanin WeightMax = 0; FaninMax = -1; for ( k = 0; k < pObj->nFans; k++ ) if ( WeightMax < Weights[k] ) { WeightMax = Weights[k]; FaninMax = k; } // no need to reorder if there are no frequent fanins if ( FaninMax == -1 ) continue; // move the fanins number k to the first place nSwaps = 0; pIn = Kit_DsdObjTruth(pObj); pOut = p->pMem; // for ( v = FaninMax; v < ((int)pObj->nFans)-1; v++ ) for ( v = FaninMax-1; v >= 0; v-- ) { // swap the fanins Temp = pObj->pFans[v]; pObj->pFans[v] = pObj->pFans[v+1]; pObj->pFans[v+1] = Temp; // swap the truth table variables Kit_TruthSwapAdjacentVars( pOut, pIn, pObj->nFans, v ); pTemp = pIn; pIn = pOut; pOut = pTemp; nSwaps++; } if ( nSwaps & 1 ) Kit_TruthCopy( pOut, pIn, pObj->nFans ); } } /**Function************************************************************* Synopsis [Compute the support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Kit_DsdGetSupports_rec( Kit_DsdNtk_t * p, int iLit ) { Kit_DsdObj_t * pObj; unsigned uSupport, k; int iFaninLit; pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) return Kit_DsdLitSupport( p, iLit ); uSupport = 0; Kit_DsdObjForEachFanin( p, pObj, iFaninLit, k ) uSupport |= Kit_DsdGetSupports_rec( p, iFaninLit ); p->pSupps[pObj->Id - p->nVars] = uSupport; assert( uSupport <= 0xFFFF ); return uSupport; } /**Function************************************************************* Synopsis [Compute the support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p ) { Kit_DsdObj_t * pRoot; unsigned uSupport; assert( p->pSupps == NULL ); p->pSupps = ABC_ALLOC( unsigned, p->nNodes ); // consider simple special cases pRoot = Kit_DsdNtkRoot(p); if ( pRoot->Type == KIT_DSD_CONST1 ) { assert( p->nNodes == 1 ); uSupport = p->pSupps[0] = 0; } if ( pRoot->Type == KIT_DSD_VAR ) { assert( p->nNodes == 1 ); uSupport = p->pSupps[0] = Kit_DsdLitSupport( p, pRoot->pFans[0] ); } else uSupport = Kit_DsdGetSupports_rec( p, p->Root ); assert( uSupport <= 0xFFFF ); return uSupport; } /**Function************************************************************* Synopsis [Returns 1 if there is a component with more than 3 inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdFindLargeBox_rec( Kit_DsdNtk_t * pNtk, int Id, int Size ) { Kit_DsdObj_t * pObj; unsigned iLit, i, RetValue; pObj = Kit_DsdNtkObj( pNtk, Id ); if ( pObj == NULL ) return 0; if ( pObj->Type == KIT_DSD_PRIME && (int)pObj->nFans > Size ) return 1; RetValue = 0; Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) RetValue |= Kit_DsdFindLargeBox_rec( pNtk, Abc_Lit2Var(iLit), Size ); return RetValue; } /**Function************************************************************* Synopsis [Returns 1 if there is a component with more than 3 inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdFindLargeBox( Kit_DsdNtk_t * pNtk, int Size ) { return Kit_DsdFindLargeBox_rec( pNtk, Abc_Lit2Var(pNtk->Root), Size ); } /**Function************************************************************* Synopsis [Returns 1 if there is a component with more than 3 inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdCountAigNodes_rec( Kit_DsdNtk_t * pNtk, int Id ) { Kit_DsdObj_t * pObj; unsigned iLit, i, RetValue; pObj = Kit_DsdNtkObj( pNtk, Id ); if ( pObj == NULL ) return 0; if ( pObj->Type == KIT_DSD_CONST1 || pObj->Type == KIT_DSD_VAR ) return 0; if ( pObj->nFans < 2 ) // why this happens? - need to figure out return 0; assert( pObj->nFans > 1 ); if ( pObj->Type == KIT_DSD_AND ) RetValue = ((int)pObj->nFans - 1); else if ( pObj->Type == KIT_DSD_XOR ) RetValue = ((int)pObj->nFans - 1) * 3; else if ( pObj->Type == KIT_DSD_PRIME ) { // assuming MUX decomposition assert( (int)pObj->nFans == 3 ); RetValue = 3; } else assert( 0 ); Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) RetValue += Kit_DsdCountAigNodes_rec( pNtk, Abc_Lit2Var(iLit) ); return RetValue; } /**Function************************************************************* Synopsis [Returns 1 if there is a component with more than 3 inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdCountAigNodes2( Kit_DsdNtk_t * pNtk ) { return Kit_DsdCountAigNodes_rec( pNtk, Abc_Lit2Var(pNtk->Root) ); } /**Function************************************************************* Synopsis [Returns 1 if there is a component with more than 3 inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdCountAigNodes( Kit_DsdNtk_t * pNtk ) { Kit_DsdObj_t * pObj; int i, Counter = 0; for ( i = 0; i < pNtk->nNodes; i++ ) { pObj = pNtk->pNodes[i]; if ( pObj->Type == KIT_DSD_AND ) Counter += ((int)pObj->nFans - 1); else if ( pObj->Type == KIT_DSD_XOR ) Counter += ((int)pObj->nFans - 1) * 3; else if ( pObj->Type == KIT_DSD_PRIME ) // assuming MUX decomposition Counter += 3; } return Counter; } /**Function************************************************************* Synopsis [Returns 1 if the non-DSD 4-var func is implementable with two 3-LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdRootNodeHasCommonVars( Kit_DsdObj_t * pObj0, Kit_DsdObj_t * pObj1 ) { unsigned i, k; for ( i = 0; i < pObj0->nFans; i++ ) { if ( Abc_Lit2Var(pObj0->pFans[i]) >= 4 ) continue; for ( k = 0; k < pObj1->nFans; k++ ) if ( Abc_Lit2Var(pObj0->pFans[i]) == Abc_Lit2Var(pObj1->pFans[k]) ) return 1; } return 0; } /**Function************************************************************* Synopsis [Returns 1 if the non-DSD 4-var func is implementable with two 3-LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdCheckVar4Dec2( Kit_DsdNtk_t * pNtk0, Kit_DsdNtk_t * pNtk1 ) { assert( pNtk0->nVars == 4 ); assert( pNtk1->nVars == 4 ); if ( Kit_DsdFindLargeBox(pNtk0, 2) ) return 0; if ( Kit_DsdFindLargeBox(pNtk1, 2) ) return 0; return Kit_DsdRootNodeHasCommonVars( Kit_DsdNtkRoot(pNtk0), Kit_DsdNtkRoot(pNtk1) ); } /**Function************************************************************* Synopsis [Performs decomposition of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdDecompose_rec( Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pObj, unsigned uSupp, unsigned short * pPar, int nDecMux ) { Kit_DsdObj_t * pRes, * pRes0, * pRes1; int nWords = Kit_TruthWordNum(pObj->nFans); unsigned * pTruth = Kit_DsdObjTruth(pObj); unsigned * pCofs2[2] = { pNtk->pMem, pNtk->pMem + nWords }; unsigned * pCofs4[2][2] = { {pNtk->pMem + 2 * nWords, pNtk->pMem + 3 * nWords}, {pNtk->pMem + 4 * nWords, pNtk->pMem + 5 * nWords} }; int i, iLit0, iLit1, nFans0, nFans1, nPairs; int fEquals[2][2], fOppos, fPairs[4][4]; unsigned j, k, nFansNew, uSupp0, uSupp1; assert( pObj->nFans > 0 ); assert( pObj->Type == KIT_DSD_PRIME ); assert( uSupp == (uSupp0 = (unsigned)Kit_TruthSupport(pTruth, pObj->nFans)) ); // compress the truth table if ( uSupp != Kit_BitMask(pObj->nFans) ) { nFansNew = Kit_WordCountOnes(uSupp); Kit_TruthShrink( pNtk->pMem, pTruth, nFansNew, pObj->nFans, uSupp, 1 ); for ( j = k = 0; j < pObj->nFans; j++ ) if ( uSupp & (1 << j) ) pObj->pFans[k++] = pObj->pFans[j]; assert( k == nFansNew ); pObj->nFans = k; uSupp = Kit_BitMask(pObj->nFans); } // consider the single variable case if ( pObj->nFans == 1 ) { pObj->Type = KIT_DSD_NONE; if ( pTruth[0] == 0x55555555 ) pObj->pFans[0] = Abc_LitNot(pObj->pFans[0]); else assert( pTruth[0] == 0xAAAAAAAA ); // update the parent pointer *pPar = Abc_LitNotCond( pObj->pFans[0], Abc_LitIsCompl(*pPar) ); return; } // decompose the output if ( !pObj->fMark ) for ( i = pObj->nFans - 1; i >= 0; i-- ) { // get the two-variable cofactors Kit_TruthCofactor0New( pCofs2[0], pTruth, pObj->nFans, i ); Kit_TruthCofactor1New( pCofs2[1], pTruth, pObj->nFans, i ); // assert( !Kit_TruthVarInSupport( pCofs2[0], pObj->nFans, i) ); // assert( !Kit_TruthVarInSupport( pCofs2[1], pObj->nFans, i) ); // get the constant cofs fEquals[0][0] = Kit_TruthIsConst0( pCofs2[0], pObj->nFans ); fEquals[0][1] = Kit_TruthIsConst0( pCofs2[1], pObj->nFans ); fEquals[1][0] = Kit_TruthIsConst1( pCofs2[0], pObj->nFans ); fEquals[1][1] = Kit_TruthIsConst1( pCofs2[1], pObj->nFans ); fOppos = Kit_TruthIsOpposite( pCofs2[0], pCofs2[1], pObj->nFans ); assert( !Kit_TruthIsEqual(pCofs2[0], pCofs2[1], pObj->nFans) ); if ( fEquals[0][0] + fEquals[0][1] + fEquals[1][0] + fEquals[1][1] + fOppos == 0 ) { // check the MUX decomposition uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); assert( uSupp == (uSupp0 | uSupp1 | (1<nFans ); pRes1 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); for ( k = 0; k < pObj->nFans; k++ ) { pRes0->pFans[k] = (uSupp0 & (1 << k))? pObj->pFans[k] : 127; pRes1->pFans[k] = (uSupp1 & (1 << k))? pObj->pFans[k] : 127; } Kit_TruthCopy( Kit_DsdObjTruth(pRes0), pCofs2[0], pObj->nFans ); Kit_TruthCopy( Kit_DsdObjTruth(pRes1), pCofs2[1], pObj->nFans ); // update the current one assert( pObj->Type == KIT_DSD_PRIME ); pTruth[0] = 0xCACACACA; pObj->nFans = 3; pObj->pFans[2] = pObj->pFans[i]; pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++; pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++; // call recursively Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux ); Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux ); return; } // create the new node pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_AND, 2 ); pRes->nRefs++; pRes->nFans = 2; pRes->pFans[0] = pObj->pFans[i]; pObj->pFans[i] = 127; uSupp &= ~(1 << i); pRes->pFans[1] = 2*pObj->Id; // update the parent pointer *pPar = Abc_LitNotCond( 2 * pRes->Id, Abc_LitIsCompl(*pPar) ); // consider different decompositions if ( fEquals[0][0] ) { Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans ); } else if ( fEquals[0][1] ) { pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]); Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); } else if ( fEquals[1][0] ) { *pPar = Abc_LitNot(*pPar); pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]); Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans ); } else if ( fEquals[1][1] ) { *pPar = Abc_LitNot(*pPar); pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]); pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]); Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); } else if ( fOppos ) { pRes->Type = KIT_DSD_XOR; Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); } else assert( 0 ); // decompose the remainder assert( Kit_DsdObjTruth(pObj) == pTruth ); Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pRes->pFans + 1, nDecMux ); return; } pObj->fMark = 1; // decompose the input for ( i = pObj->nFans - 1; i >= 0; i-- ) { assert( Kit_TruthVarInSupport( pTruth, pObj->nFans, i ) ); // get the single variale cofactors Kit_TruthCofactor0New( pCofs2[0], pTruth, pObj->nFans, i ); Kit_TruthCofactor1New( pCofs2[1], pTruth, pObj->nFans, i ); // check the existence of MUX decomposition uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); assert( uSupp == (uSupp0 | uSupp1 | (1<fMark = 0; Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); return; } assert( uSupp0 && uSupp1 ); // get the number of unique variables nFans0 = Kit_WordCountOnes( uSupp0 & ~uSupp1 ); nFans1 = Kit_WordCountOnes( uSupp1 & ~uSupp0 ); if ( nFans0 == 1 && nFans1 == 1 ) { // get the cofactors w.r.t. the unique variables iLit0 = Kit_WordFindFirstBit( uSupp0 & ~uSupp1 ); iLit1 = Kit_WordFindFirstBit( uSupp1 & ~uSupp0 ); // get four cofactors Kit_TruthCofactor0New( pCofs4[0][0], pCofs2[0], pObj->nFans, iLit0 ); Kit_TruthCofactor1New( pCofs4[0][1], pCofs2[0], pObj->nFans, iLit0 ); Kit_TruthCofactor0New( pCofs4[1][0], pCofs2[1], pObj->nFans, iLit1 ); Kit_TruthCofactor1New( pCofs4[1][1], pCofs2[1], pObj->nFans, iLit1 ); // check existence conditions fEquals[0][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][0], pObj->nFans ); fEquals[0][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][1], pObj->nFans ); fEquals[1][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][1], pObj->nFans ); fEquals[1][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][0], pObj->nFans ); if ( (fEquals[0][0] && fEquals[0][1]) || (fEquals[1][0] && fEquals[1][1]) ) { // construct the MUX pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, 3 ); Kit_DsdObjTruth(pRes)[0] = 0xCACACACA; pRes->nRefs++; pRes->nFans = 3; pRes->pFans[0] = pObj->pFans[iLit0]; pObj->pFans[iLit0] = 127; uSupp &= ~(1 << iLit0); pRes->pFans[1] = pObj->pFans[iLit1]; pObj->pFans[iLit1] = 127; uSupp &= ~(1 << iLit1); pRes->pFans[2] = pObj->pFans[i]; pObj->pFans[i] = 2 * pRes->Id; // remains in support // update the node // if ( fEquals[0][0] && fEquals[0][1] ) // Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, i ); // else // Kit_TruthMuxVar( pTruth, pCofs4[0][1], pCofs4[0][0], pObj->nFans, i ); Kit_TruthMuxVar( pTruth, pCofs4[1][0], pCofs4[1][1], pObj->nFans, i ); if ( fEquals[1][0] && fEquals[1][1] ) pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]); // decompose the remainder Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); return; } } // try other inputs for ( k = i+1; k < pObj->nFans; k++ ) { // get four cofactors ik Kit_TruthCofactor0New( pCofs4[0][0], pCofs2[0], pObj->nFans, k ); // 00 Kit_TruthCofactor1New( pCofs4[0][1], pCofs2[0], pObj->nFans, k ); // 01 Kit_TruthCofactor0New( pCofs4[1][0], pCofs2[1], pObj->nFans, k ); // 10 Kit_TruthCofactor1New( pCofs4[1][1], pCofs2[1], pObj->nFans, k ); // 11 // compare equal pairs fPairs[0][1] = fPairs[1][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[0][1], pObj->nFans ); fPairs[0][2] = fPairs[2][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][0], pObj->nFans ); fPairs[0][3] = fPairs[3][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][1], pObj->nFans ); fPairs[1][2] = fPairs[2][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][0], pObj->nFans ); fPairs[1][3] = fPairs[3][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][1], pObj->nFans ); fPairs[2][3] = fPairs[3][2] = Kit_TruthIsEqual( pCofs4[1][0], pCofs4[1][1], pObj->nFans ); nPairs = fPairs[0][1] + fPairs[0][2] + fPairs[0][3] + fPairs[1][2] + fPairs[1][3] + fPairs[2][3]; if ( nPairs != 3 && nPairs != 2 ) continue; // decomposition exists pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_AND, 2 ); pRes->nRefs++; pRes->nFans = 2; pRes->pFans[0] = pObj->pFans[k]; pObj->pFans[k] = 2 * pRes->Id; // remains in support pRes->pFans[1] = pObj->pFans[i]; pObj->pFans[i] = 127; uSupp &= ~(1 << i); if ( !fPairs[0][1] && !fPairs[0][2] && !fPairs[0][3] ) // 00 { pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]); pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]); Kit_TruthMuxVar( pTruth, pCofs4[1][1], pCofs4[0][0], pObj->nFans, k ); } else if ( !fPairs[1][0] && !fPairs[1][2] && !fPairs[1][3] ) // 01 { pRes->pFans[1] = Abc_LitNot(pRes->pFans[1]); Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, k ); } else if ( !fPairs[2][0] && !fPairs[2][1] && !fPairs[2][3] ) // 10 { pRes->pFans[0] = Abc_LitNot(pRes->pFans[0]); Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[1][0], pObj->nFans, k ); } else if ( !fPairs[3][0] && !fPairs[3][1] && !fPairs[3][2] ) // 11 { // unsigned uSupp0 = Kit_TruthSupport(pCofs4[0][0], pObj->nFans); // unsigned uSupp1 = Kit_TruthSupport(pCofs4[1][1], pObj->nFans); // unsigned uSupp; // Extra_PrintBinary( stdout, &uSupp0, pObj->nFans ); printf( "\n" ); // Extra_PrintBinary( stdout, &uSupp1, pObj->nFans ); printf( "\n" ); Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[1][1], pObj->nFans, k ); // uSupp = Kit_TruthSupport(pTruth, pObj->nFans); // Extra_PrintBinary( stdout, &uSupp, pObj->nFans ); printf( "\n" ); printf( "\n" ); } else { assert( fPairs[0][3] && fPairs[1][2] ); pRes->Type = KIT_DSD_XOR;; Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, k ); } // decompose the remainder Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); return; } } // if all decomposition methods failed and we are still above the limit, perform MUX-decomposition if ( nDecMux > 0 && (int)pObj->nFans > nDecMux ) { int iBestVar = Kit_TruthBestCofVar( pTruth, pObj->nFans, pCofs2[0], pCofs2[1] ); uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); // perform MUX decomposition pRes0 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); pRes1 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); for ( k = 0; k < pObj->nFans; k++ ) pRes0->pFans[k] = pRes1->pFans[k] = pObj->pFans[k]; Kit_TruthCopy( Kit_DsdObjTruth(pRes0), pCofs2[0], pObj->nFans ); Kit_TruthCopy( Kit_DsdObjTruth(pRes1), pCofs2[1], pObj->nFans ); // update the current one assert( pObj->Type == KIT_DSD_PRIME ); pTruth[0] = 0xCACACACA; pObj->nFans = 3; pObj->pFans[2] = pObj->pFans[iBestVar]; pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++; pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++; // call recursively Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux ); Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux ); } } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdNtk_t * Kit_DsdDecomposeInt( unsigned * pTruth, int nVars, int nDecMux ) { Kit_DsdNtk_t * pNtk; Kit_DsdObj_t * pObj; unsigned uSupp; int i, nVarsReal; assert( nVars <= 16 ); pNtk = Kit_DsdNtkAlloc( nVars ); pNtk->Root = Abc_Var2Lit( pNtk->nVars, 0 ); // create the first node pObj = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, nVars ); assert( pNtk->pNodes[0] == pObj ); for ( i = 0; i < nVars; i++ ) pObj->pFans[i] = Abc_Var2Lit( i, 0 ); Kit_TruthCopy( Kit_DsdObjTruth(pObj), pTruth, nVars ); uSupp = Kit_TruthSupport( pTruth, nVars ); // consider special cases nVarsReal = Kit_WordCountOnes( uSupp ); if ( nVarsReal == 0 ) { pObj->Type = KIT_DSD_CONST1; pObj->nFans = 0; if ( pTruth[0] == 0 ) pNtk->Root = Abc_LitNot(pNtk->Root); return pNtk; } if ( nVarsReal == 1 ) { pObj->Type = KIT_DSD_VAR; pObj->nFans = 1; pObj->pFans[0] = Abc_Var2Lit( Kit_WordFindFirstBit(uSupp), (pTruth[0] & 1) ); return pNtk; } Kit_DsdDecompose_rec( pNtk, pNtk->pNodes[0], uSupp, &pNtk->Root, nDecMux ); return pNtk; } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdNtk_t * Kit_DsdDecompose( unsigned * pTruth, int nVars ) { return Kit_DsdDecomposeInt( pTruth, nVars, 0 ); } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars ) { Kit_DsdNtk_t * pNtk, * pTemp; pNtk = Kit_DsdDecomposeInt( pTruth, nVars, 0 ); pNtk = Kit_DsdExpand( pTemp = pNtk ); Kit_DsdNtkFree( pTemp ); return pNtk; } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [Uses MUXes to break-down large prime nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux ) { /* Kit_DsdNtk_t * pNew; Kit_DsdObj_t * pObjNew; assert( nVars <= 16 ); // create a new network pNew = Kit_DsdNtkAlloc( nVars ); // consider simple special cases if ( nVars == 0 ) { pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); pNew->Root = Abc_Var2Lit( pObjNew->Id, (int)(pTruth[0] == 0) ); return pNew; } if ( nVars == 1 ) { pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); pObjNew->pFans[0] = Abc_Var2Lit( 0, 0 ); pNew->Root = Abc_Var2Lit( pObjNew->Id, (int)(pTruth[0] != 0xAAAAAAAA) ); return pNew; } */ return Kit_DsdDecomposeInt( pTruth, nVars, nDecMux ); } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdTestCofs( Kit_DsdNtk_t * pNtk, unsigned * pTruthInit ) { Kit_DsdNtk_t * pNtk0, * pNtk1, * pTemp; // Kit_DsdObj_t * pRoot; unsigned * pCofs2[2] = { pNtk->pMem, pNtk->pMem + Kit_TruthWordNum(pNtk->nVars) }; unsigned i, * pTruth; int fVerbose = 1; int RetValue = 0; pTruth = pTruthInit; // pRoot = Kit_DsdNtkRoot(pNtk); // pTruth = Kit_DsdObjTruth(pRoot); // assert( pRoot->nFans == pNtk->nVars ); if ( fVerbose ) { printf( "Function: " ); // Extra_PrintBinary( stdout, pTruth, (1 << pNtk->nVars) ); Extra_PrintHexadecimal( stdout, pTruth, pNtk->nVars ); printf( "\n" ); Kit_DsdPrint( stdout, pNtk ), printf( "\n" ); } for ( i = 0; i < pNtk->nVars; i++ ) { Kit_TruthCofactor0New( pCofs2[0], pTruth, pNtk->nVars, i ); pNtk0 = Kit_DsdDecompose( pCofs2[0], pNtk->nVars ); pNtk0 = Kit_DsdExpand( pTemp = pNtk0 ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) { printf( "Cof%d0: ", i ); Kit_DsdPrint( stdout, pNtk0 ), printf( "\n" ); } Kit_TruthCofactor1New( pCofs2[1], pTruth, pNtk->nVars, i ); pNtk1 = Kit_DsdDecompose( pCofs2[1], pNtk->nVars ); pNtk1 = Kit_DsdExpand( pTemp = pNtk1 ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) { printf( "Cof%d1: ", i ); Kit_DsdPrint( stdout, pNtk1 ), printf( "\n" ); } // if ( Kit_DsdCheckVar4Dec2( pNtk0, pNtk1 ) ) // RetValue = 1; Kit_DsdNtkFree( pNtk0 ); Kit_DsdNtkFree( pNtk1 ); } if ( fVerbose ) printf( "\n" ); return RetValue; } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdEval( unsigned * pTruth, int nVars, int nLutSize ) { Kit_DsdMan_t * p; Kit_DsdNtk_t * pNtk; unsigned * pTruthC; int Result; // decompose the function pNtk = Kit_DsdDecompose( pTruth, nVars ); Result = Kit_DsdCountLuts( pNtk, nLutSize ); // printf( "\n" ); // Kit_DsdPrint( stdout, pNtk ); // printf( "Eval = %d.\n", Result ); // recompute the truth table p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk) ); pTruthC = Kit_DsdTruthCompute( p, pNtk ); if ( !Kit_TruthIsEqual( pTruth, pTruthC, nVars ) ) printf( "Verification failed.\n" ); Kit_DsdManFree( p ); Kit_DsdNtkFree( pNtk ); return Result; } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars ) { Kit_DsdMan_t * p; unsigned * pTruthC; p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk)+2 ); pTruthC = Kit_DsdTruthCompute( p, pNtk ); if ( !Extra_TruthIsEqual( pTruth, pTruthC, nVars ) ) printf( "Verification failed.\n" ); Kit_DsdManFree( p ); } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdTest( unsigned * pTruth, int nVars ) { Kit_DsdMan_t * p; unsigned * pTruthC; Kit_DsdNtk_t * pNtk, * pTemp; pNtk = Kit_DsdDecompose( pTruth, nVars ); // if ( Kit_DsdFindLargeBox(pNtk, Abc_Lit2Var(pNtk->Root)) ) // Kit_DsdPrint( stdout, pNtk ); // if ( Kit_DsdNtkRoot(pNtk)->nFans == (unsigned)nVars && nVars == 6 ) // printf( "\n" ); // Kit_DsdPrint( stdout, pNtk ); pNtk = Kit_DsdExpand( pTemp = pNtk ); Kit_DsdNtkFree( pTemp ); Kit_DsdPrint( stdout, pNtk ), printf( "\n" ); // if ( Kit_DsdFindLargeBox(pNtk, Abc_Lit2Var(pNtk->Root)) ) // Kit_DsdTestCofs( pNtk, pTruth ); // recompute the truth table p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk) ); pTruthC = Kit_DsdTruthCompute( p, pNtk ); // Extra_PrintBinary( stdout, pTruth, 1 << nVars ); printf( "\n" ); // Extra_PrintBinary( stdout, pTruthC, 1 << nVars ); printf( "\n" ); if ( Extra_TruthIsEqual( pTruth, pTruthC, nVars ) ) { // printf( "Verification is okay.\n" ); } else printf( "Verification failed.\n" ); Kit_DsdManFree( p ); Kit_DsdNtkFree( pNtk ); } /**Function************************************************************* Synopsis [Performs decomposition of the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrecompute4Vars() { Kit_DsdMan_t * p; Kit_DsdNtk_t * pNtk, * pTemp; FILE * pFile; unsigned uTruth; unsigned * pTruthC; char Buffer[256]; int i, RetValue; int Counter1 = 0, Counter2 = 0; pFile = fopen( "5npn/npn4.txt", "r" ); for ( i = 0; fgets( Buffer, 100, pFile ); i++ ) { Buffer[6] = 0; Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); uTruth = ((uTruth & 0xffff) << 16) | (uTruth & 0xffff); pNtk = Kit_DsdDecompose( &uTruth, 4 ); pNtk = Kit_DsdExpand( pTemp = pNtk ); Kit_DsdNtkFree( pTemp ); if ( Kit_DsdFindLargeBox(pNtk, 3) ) { // RetValue = 0; RetValue = Kit_DsdTestCofs( pNtk, &uTruth ); printf( "\n" ); printf( "%3d : Non-DSD function %s %s\n", i, Buffer + 2, RetValue? "implementable" : "" ); Kit_DsdPrint( stdout, pNtk ), printf( "\n" ); Counter1++; Counter2 += RetValue; } /* printf( "%3d : Function %s ", i, Buffer + 2 ); if ( !Kit_DsdFindLargeBox(pNtk, 3) ) Kit_DsdPrint( stdout, pNtk ); else printf( "\n" ); */ p = Kit_DsdManAlloc( 4, Kit_DsdNtkObjNum(pNtk) ); pTruthC = Kit_DsdTruthCompute( p, pNtk ); if ( !Extra_TruthIsEqual( &uTruth, pTruthC, 4 ) ) printf( "Verification failed.\n" ); Kit_DsdManFree( p ); Kit_DsdNtkFree( pNtk ); } fclose( pFile ); printf( "non-DSD = %d implementable = %d\n", Counter1, Counter2 ); } /**Function************************************************************* Synopsis [Returns the set of cofactoring variables.] Description [If there is no DSD components returns 0.] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdCofactoringGetVars( Kit_DsdNtk_t ** ppNtk, int nSize, int * pVars ) { Kit_DsdObj_t * pObj; unsigned m; int i, k, v, Var, nVars, iFaninLit; // go through all the networks nVars = 0; for ( i = 0; i < nSize; i++ ) { // go through the prime objects of each networks Kit_DsdNtkForEachObj( ppNtk[i], pObj, k ) { if ( pObj->Type != KIT_DSD_PRIME ) continue; if ( pObj->nFans == 3 ) continue; // collect direct fanin variables Kit_DsdObjForEachFanin( ppNtk[i], pObj, iFaninLit, m ) { if ( !Kit_DsdLitIsLeaf(ppNtk[i], iFaninLit) ) continue; // add it to the array Var = Abc_Lit2Var( iFaninLit ); for ( v = 0; v < nVars; v++ ) if ( pVars[v] == Var ) break; if ( v == nVars ) pVars[nVars++] = Var; } } } return nVars; } /**Function************************************************************* Synopsis [Canonical decomposition into completely DSD-structure.] Description [Returns the number of cofactoring steps. Also returns the cofactoring variables in pVars.] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_DsdCofactoring( unsigned * pTruth, int nVars, int * pCofVars, int nLimit, int fVerbose ) { Kit_DsdNtk_t * ppNtks[5][16] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; Kit_DsdNtk_t * pTemp; unsigned * ppCofs[5][16]; int pTryVars[16], nTryVars; int nPrimeSizeMin, nPrimeSizeMax, nPrimeSizeCur; int nSuppSizeMin, nSuppSizeMax, iVarBest; int i, k, v, nStep, nSize, nMemSize; assert( nLimit < 5 ); // allocate storage for cofactors nMemSize = Kit_TruthWordNum(nVars); ppCofs[0][0] = ABC_ALLOC( unsigned, 80 * nMemSize ); nSize = 0; for ( i = 0; i < 5; i++ ) for ( k = 0; k < 16; k++ ) ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; assert( nSize == 80 ); // copy the function Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); ppNtks[0][0] = Kit_DsdDecompose( ppCofs[0][0], nVars ); if ( fVerbose ) printf( "\nProcessing prime function with %d support variables:\n", nVars ); // perform recursive cofactoring for ( nStep = 0; nStep < nLimit; nStep++ ) { nSize = (1 << nStep); // find the variables to use in the cofactoring step nTryVars = Kit_DsdCofactoringGetVars( ppNtks[nStep], nSize, pTryVars ); if ( nTryVars == 0 ) break; // cofactor w.r.t. the above variables iVarBest = -1; nPrimeSizeMin = 10000; nSuppSizeMin = 10000; for ( v = 0; v < nTryVars; v++ ) { nPrimeSizeMax = 0; nSuppSizeMax = 0; for ( i = 0; i < nSize; i++ ) { // cofactor and decompose cofactors Kit_TruthCofactor0New( ppCofs[nStep+1][2*i+0], ppCofs[nStep][i], nVars, pTryVars[v] ); Kit_TruthCofactor1New( ppCofs[nStep+1][2*i+1], ppCofs[nStep][i], nVars, pTryVars[v] ); ppNtks[nStep+1][2*i+0] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+0], nVars ); ppNtks[nStep+1][2*i+1] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+1], nVars ); // compute the largest non-decomp block nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[nStep+1][2*i+0]); nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[nStep+1][2*i+1]); nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); // compute the sum total of supports nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nStep+1][2*i+0], nVars ); nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nStep+1][2*i+1], nVars ); // free the networks Kit_DsdNtkFree( ppNtks[nStep+1][2*i+0] ); Kit_DsdNtkFree( ppNtks[nStep+1][2*i+1] ); } // find the min max support size of the prime component if ( nPrimeSizeMin > nPrimeSizeMax || (nPrimeSizeMin == nPrimeSizeMax && nSuppSizeMin > nSuppSizeMax) ) { nPrimeSizeMin = nPrimeSizeMax; nSuppSizeMin = nSuppSizeMax; iVarBest = pTryVars[v]; } } assert( iVarBest != -1 ); // save the variable if ( pCofVars ) pCofVars[nStep] = iVarBest; // cofactor w.r.t. the best for ( i = 0; i < nSize; i++ ) { Kit_TruthCofactor0New( ppCofs[nStep+1][2*i+0], ppCofs[nStep][i], nVars, iVarBest ); Kit_TruthCofactor1New( ppCofs[nStep+1][2*i+1], ppCofs[nStep][i], nVars, iVarBest ); ppNtks[nStep+1][2*i+0] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+0], nVars ); ppNtks[nStep+1][2*i+1] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+1], nVars ); if ( fVerbose ) { ppNtks[nStep+1][2*i+0] = Kit_DsdExpand( pTemp = ppNtks[nStep+1][2*i+0] ); Kit_DsdNtkFree( pTemp ); ppNtks[nStep+1][2*i+1] = Kit_DsdExpand( pTemp = ppNtks[nStep+1][2*i+1] ); Kit_DsdNtkFree( pTemp ); printf( "Cof%d%d: ", nStep+1, 2*i+0 ); Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+0] ), printf( "\n" ); printf( "Cof%d%d: ", nStep+1, 2*i+1 ); Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+1] ), printf( "\n" ); } } } // free the networks for ( i = 0; i < 5; i++ ) for ( k = 0; k < 16; k++ ) if ( ppNtks[i][k] ) Kit_DsdNtkFree( ppNtks[i][k] ); ABC_FREE( ppCofs[0][0] ); assert( nStep <= nLimit ); return nStep; } /**Function************************************************************* Synopsis [Canonical decomposition into completely DSD-structure.] Description [Returns the number of cofactoring steps. Also returns the cofactoring variables in pVars.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose ) { Kit_DsdNtk_t * ppNtks[32] = {0}, * pTemp; unsigned * ppCofs[5][16]; int piCofVar[5]; int nPrimeSizeMax, nPrimeSizeCur, nSuppSizeMax; int i, k, v1, v2, v3, v4, s, nSteps, nSize, nMemSize; assert( nCofLevel < 5 ); // print the function ppNtks[0] = Kit_DsdDecompose( pTruth, nVars ); ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) Kit_DsdPrint( stdout, ppNtks[0] ), printf( "\n" ); Kit_DsdNtkFree( ppNtks[0] ); // allocate storage for cofactors nMemSize = Kit_TruthWordNum(nVars); ppCofs[0][0] = ABC_ALLOC( unsigned, 80 * nMemSize ); nSize = 0; for ( i = 0; i < 5; i++ ) for ( k = 0; k < 16; k++ ) ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; assert( nSize == 80 ); // copy the function Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); if ( nCofLevel == 1 ) for ( v1 = 0; v1 < nVars; v1++ ) { nSteps = 0; piCofVar[nSteps++] = v1; printf( " Variables { " ); for ( i = 0; i < nSteps; i++ ) printf( "%c ", 'a' + piCofVar[i] ); printf( "}\n" ); // single cofactors for ( s = 1; s <= nSteps; s++ ) { for ( k = 0; k < s; k++ ) { nSize = (1 << k); for ( i = 0; i < nSize; i++ ) { Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); } } } // compute DSD networks nSize = (1 << nSteps); nPrimeSizeMax = 0; nSuppSizeMax = 0; for ( i = 0; i < nSize; i++ ) { ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) { printf( "Cof%d%d: ", nSteps, i ); Kit_DsdPrint( stdout, ppNtks[i] ), printf( "\n" ); } // compute the largest non-decomp block nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); Kit_DsdNtkFree( ppNtks[i] ); nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); } printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); } if ( nCofLevel == 2 ) for ( v1 = 0; v1 < nVars; v1++ ) for ( v2 = v1+1; v2 < nVars; v2++ ) { nSteps = 0; piCofVar[nSteps++] = v1; piCofVar[nSteps++] = v2; printf( " Variables { " ); for ( i = 0; i < nSteps; i++ ) printf( "%c ", 'a' + piCofVar[i] ); printf( "}\n" ); // single cofactors for ( s = 1; s <= nSteps; s++ ) { for ( k = 0; k < s; k++ ) { nSize = (1 << k); for ( i = 0; i < nSize; i++ ) { Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); } } } // compute DSD networks nSize = (1 << nSteps); nPrimeSizeMax = 0; nSuppSizeMax = 0; for ( i = 0; i < nSize; i++ ) { ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) { printf( "Cof%d%d: ", nSteps, i ); Kit_DsdPrint( stdout, ppNtks[i] ), printf( "\n" ); } // compute the largest non-decomp block nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); Kit_DsdNtkFree( ppNtks[i] ); nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); } printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); } if ( nCofLevel == 3 ) for ( v1 = 0; v1 < nVars; v1++ ) for ( v2 = v1+1; v2 < nVars; v2++ ) for ( v3 = v2+1; v3 < nVars; v3++ ) { nSteps = 0; piCofVar[nSteps++] = v1; piCofVar[nSteps++] = v2; piCofVar[nSteps++] = v3; printf( " Variables { " ); for ( i = 0; i < nSteps; i++ ) printf( "%c ", 'a' + piCofVar[i] ); printf( "}\n" ); // single cofactors for ( s = 1; s <= nSteps; s++ ) { for ( k = 0; k < s; k++ ) { nSize = (1 << k); for ( i = 0; i < nSize; i++ ) { Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); } } } // compute DSD networks nSize = (1 << nSteps); nPrimeSizeMax = 0; nSuppSizeMax = 0; for ( i = 0; i < nSize; i++ ) { ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) { printf( "Cof%d%d: ", nSteps, i ); Kit_DsdPrint( stdout, ppNtks[i] ), printf( "\n" ); } // compute the largest non-decomp block nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); Kit_DsdNtkFree( ppNtks[i] ); nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); } printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); } if ( nCofLevel == 4 ) for ( v1 = 0; v1 < nVars; v1++ ) for ( v2 = v1+1; v2 < nVars; v2++ ) for ( v3 = v2+1; v3 < nVars; v3++ ) for ( v4 = v3+1; v4 < nVars; v4++ ) { nSteps = 0; piCofVar[nSteps++] = v1; piCofVar[nSteps++] = v2; piCofVar[nSteps++] = v3; piCofVar[nSteps++] = v4; printf( " Variables { " ); for ( i = 0; i < nSteps; i++ ) printf( "%c ", 'a' + piCofVar[i] ); printf( "}\n" ); // single cofactors for ( s = 1; s <= nSteps; s++ ) { for ( k = 0; k < s; k++ ) { nSize = (1 << k); for ( i = 0; i < nSize; i++ ) { Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); } } } // compute DSD networks nSize = (1 << nSteps); nPrimeSizeMax = 0; nSuppSizeMax = 0; for ( i = 0; i < nSize; i++ ) { ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) { printf( "Cof%d%d: ", nSteps, i ); Kit_DsdPrint( stdout, ppNtks[i] ), printf( "\n" ); } // compute the largest non-decomp block nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); Kit_DsdNtkFree( ppNtks[i] ); nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); } printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); } ABC_FREE( ppCofs[0][0] ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char ** Kit_DsdNpn4ClassNames() { static const char * pNames[222] = { "F = 0", /* 0 */ "F = (!d*(!c*(!b*!a)))", /* 1 */ "F = (!d*(!c*!b))", /* 2 */ "F = (!d*(!c*(b+a)))", /* 3 */ "F = (!d*(!c*!(b*a)))", /* 4 */ "F = (!d*!c)", /* 5 */ "F = (!d*16(a,b,c))", /* 6 */ "F = (!d*17(a,b,c))", /* 7 */ "F = (!d*18(a,b,c))", /* 8 */ "F = (!d*19(a,b,c))", /* 9 */ "F = (!d*CA(!b,!c,a))", /* 10 */ "F = (!d*(c+!(!b*!a)))", /* 11 */ "F = (!d*!(c*!(!b*!a)))", /* 12 */ "F = (!d*(c+b))", /* 13 */ "F = (!d*3D(a,b,c))", /* 14 */ "F = (!d*!(c*b))", /* 15 */ "F = (!d*(c+(b+!a)))", /* 16 */ "F = (!d*6B(a,b,c))", /* 17 */ "F = (!d*!(c*!(b+a)))", /* 18 */ "F = (!d*7E(a,b,c))", /* 19 */ "F = (!d*!(c*(b*a)))", /* 20 */ "F = (!d)", /* 21 */ "F = 0116(a,b,c,d)", /* 22 */ "F = 0117(a,b,c,d)", /* 23 */ "F = 0118(a,b,c,d)", /* 24 */ "F = 0119(a,b,c,d)", /* 25 */ "F = 011A(a,b,c,d)", /* 26 */ "F = 011B(a,b,c,d)", /* 27 */ "F = 29((!b*!a),c,d)", /* 28 */ "F = 2B((!b*!a),c,d)", /* 29 */ "F = 012C(a,b,c,d)", /* 30 */ "F = 012D(a,b,c,d)", /* 31 */ "F = 012F(a,b,c,d)", /* 32 */ "F = 013C(a,b,c,d)", /* 33 */ "F = 013D(a,b,c,d)", /* 34 */ "F = 013E(a,b,c,d)", /* 35 */ "F = 013F(a,b,c,d)", /* 36 */ "F = 0168(a,b,c,d)", /* 37 */ "F = 0169(a,b,c,d)", /* 38 */ "F = 016A(a,b,c,d)", /* 39 */ "F = 016B(a,b,c,d)", /* 40 */ "F = 016E(a,b,c,d)", /* 41 */ "F = 016F(a,b,c,d)", /* 42 */ "F = 017E(a,b,c,d)", /* 43 */ "F = 017F(a,b,c,d)", /* 44 */ "F = 0180(a,b,c,d)", /* 45 */ "F = 0181(a,b,c,d)", /* 46 */ "F = 0182(a,b,c,d)", /* 47 */ "F = 0183(a,b,c,d)", /* 48 */ "F = 0186(a,b,c,d)", /* 49 */ "F = 0187(a,b,c,d)", /* 50 */ "F = 0189(a,b,c,d)", /* 51 */ "F = 018B(a,b,c,d)", /* 52 */ "F = 018F(a,b,c,d)", /* 53 */ "F = 0196(a,b,c,d)", /* 54 */ "F = 0197(a,b,c,d)", /* 55 */ "F = 0198(a,b,c,d)", /* 56 */ "F = 0199(a,b,c,d)", /* 57 */ "F = 019A(a,b,c,d)", /* 58 */ "F = 019B(a,b,c,d)", /* 59 */ "F = 019E(a,b,c,d)", /* 60 */ "F = 019F(a,b,c,d)", /* 61 */ "F = 42(a,(!c*!b),d)", /* 62 */ "F = 46(a,(!c*!b),d)", /* 63 */ "F = 4A(a,(!c*!b),d)", /* 64 */ "F = CA((!c*!b),!d,a)", /* 65 */ "F = 01AC(a,b,c,d)", /* 66 */ "F = 01AD(a,b,c,d)", /* 67 */ "F = 01AE(a,b,c,d)", /* 68 */ "F = 01AF(a,b,c,d)", /* 69 */ "F = 01BC(a,b,c,d)", /* 70 */ "F = 01BD(a,b,c,d)", /* 71 */ "F = 01BE(a,b,c,d)", /* 72 */ "F = 01BF(a,b,c,d)", /* 73 */ "F = 01E8(a,b,c,d)", /* 74 */ "F = 01E9(a,b,c,d)", /* 75 */ "F = 01EA(a,b,c,d)", /* 76 */ "F = 01EB(a,b,c,d)", /* 77 */ "F = 25((!b*!a),c,d)", /* 78 */ "F = !CA(d,c,(!b*!a))", /* 79 */ "F = (d+!(!c*(!b*!a)))", /* 80 */ "F = 16(b,c,d)", /* 81 */ "F = 033D(a,b,c,d)", /* 82 */ "F = 17(b,c,d)", /* 83 */ "F = ((!d*!a)+(!c*!b))", /* 84 */ "F = !(!(!c*!b)*!(!d*!a))", /* 85 */ "F = 0358(a,b,c,d)", /* 86 */ "F = 0359(a,b,c,d)", /* 87 */ "F = 035A(a,b,c,d)", /* 88 */ "F = 035B(a,b,c,d)", /* 89 */ "F = 035E(a,b,c,d)", /* 90 */ "F = 035F(a,b,c,d)", /* 91 */ "F = 0368(a,b,c,d)", /* 92 */ "F = 0369(a,b,c,d)", /* 93 */ "F = 036A(a,b,c,d)", /* 94 */ "F = 036B(a,b,c,d)", /* 95 */ "F = 036C(a,b,c,d)", /* 96 */ "F = 036D(a,b,c,d)", /* 97 */ "F = 036E(a,b,c,d)", /* 98 */ "F = 036F(a,b,c,d)", /* 99 */ "F = 037C(a,b,c,d)", /* 100 */ "F = 037D(a,b,c,d)", /* 101 */ "F = 037E(a,b,c,d)", /* 102 */ "F = 18(b,c,d)", /* 103 */ "F = 03C1(a,b,c,d)", /* 104 */ "F = 19(b,c,d)", /* 105 */ "F = 03C5(a,b,c,d)", /* 106 */ "F = 03C6(a,b,c,d)", /* 107 */ "F = 03C7(a,b,c,d)", /* 108 */ "F = CA(!c,!d,b)", /* 109 */ "F = 03D4(a,b,c,d)", /* 110 */ "F = 03D5(a,b,c,d)", /* 111 */ "F = 03D6(a,b,c,d)", /* 112 */ "F = 03D7(a,b,c,d)", /* 113 */ "F = 03D8(a,b,c,d)", /* 114 */ "F = 03D9(a,b,c,d)", /* 115 */ "F = 03DB(a,b,c,d)", /* 116 */ "F = 03DC(a,b,c,d)", /* 117 */ "F = 03DD(a,b,c,d)", /* 118 */ "F = 03DE(a,b,c,d)", /* 119 */ "F = (d+!(!c*!b))", /* 120 */ "F = ((d+c)*(b+a))", /* 121 */ "F = 0661(a,b,c,d)", /* 122 */ "F = 0662(a,b,c,d)", /* 123 */ "F = 0663(a,b,c,d)", /* 124 */ "F = (!(d*c)*(b+a))", /* 125 */ "F = 0667(a,b,c,d)", /* 126 */ "F = 29((b+a),c,d)", /* 127 */ "F = 066B(a,b,c,d)", /* 128 */ "F = 2B((b+a),c,d)", /* 129 */ "F = 0672(a,b,c,d)", /* 130 */ "F = 0673(a,b,c,d)", /* 131 */ "F = 0676(a,b,c,d)", /* 132 */ "F = 0678(a,b,c,d)", /* 133 */ "F = 0679(a,b,c,d)", /* 134 */ "F = 067A(a,b,c,d)", /* 135 */ "F = 067B(a,b,c,d)", /* 136 */ "F = 067E(a,b,c,d)", /* 137 */ "F = 24((b+a),c,d)", /* 138 */ "F = 0691(a,b,c,d)", /* 139 */ "F = 0693(a,b,c,d)", /* 140 */ "F = 26((b+a),c,d)", /* 141 */ "F = 0697(a,b,c,d)", /* 142 */ "F = !CA(d,c,(b+a))", /* 143 */ "F = 06B0(a,b,c,d)", /* 144 */ "F = 06B1(a,b,c,d)", /* 145 */ "F = 06B2(a,b,c,d)", /* 146 */ "F = 06B3(a,b,c,d)", /* 147 */ "F = 06B4(a,b,c,d)", /* 148 */ "F = 06B5(a,b,c,d)", /* 149 */ "F = 06B6(a,b,c,d)", /* 150 */ "F = 06B7(a,b,c,d)", /* 151 */ "F = 06B9(a,b,c,d)", /* 152 */ "F = 06BD(a,b,c,d)", /* 153 */ "F = 2C((b+a),c,d)", /* 154 */ "F = 06F1(a,b,c,d)", /* 155 */ "F = 06F2(a,b,c,d)", /* 156 */ "F = CA((b+a),!d,c)", /* 157 */ "F = (d+!(!c*!(b+!a)))", /* 158 */ "F = 0776(a,b,c,d)", /* 159 */ "F = 16((b*a),c,d)", /* 160 */ "F = 0779(a,b,c,d)", /* 161 */ "F = 077A(a,b,c,d)", /* 162 */ "F = 077E(a,b,c,d)", /* 163 */ "F = 07B0(a,b,c,d)", /* 164 */ "F = 07B1(a,b,c,d)", /* 165 */ "F = 07B4(a,b,c,d)", /* 166 */ "F = 07B5(a,b,c,d)", /* 167 */ "F = 07B6(a,b,c,d)", /* 168 */ "F = 07BC(a,b,c,d)", /* 169 */ "F = 07E0(a,b,c,d)", /* 170 */ "F = 07E1(a,b,c,d)", /* 171 */ "F = 07E2(a,b,c,d)", /* 172 */ "F = 07E3(a,b,c,d)", /* 173 */ "F = 07E6(a,b,c,d)", /* 174 */ "F = 07E9(a,b,c,d)", /* 175 */ "F = 1C((b*a),c,d)", /* 176 */ "F = 07F1(a,b,c,d)", /* 177 */ "F = 07F2(a,b,c,d)", /* 178 */ "F = (d+!(!c*!(b*a)))", /* 179 */ "F = (d+c)", /* 180 */ "F = 1668(a,b,c,d)", /* 181 */ "F = 1669(a,b,c,d)", /* 182 */ "F = 166A(a,b,c,d)", /* 183 */ "F = 166B(a,b,c,d)", /* 184 */ "F = 166E(a,b,c,d)", /* 185 */ "F = 167E(a,b,c,d)", /* 186 */ "F = 1681(a,b,c,d)", /* 187 */ "F = 1683(a,b,c,d)", /* 188 */ "F = 1686(a,b,c,d)", /* 189 */ "F = 1687(a,b,c,d)", /* 190 */ "F = 1689(a,b,c,d)", /* 191 */ "F = 168B(a,b,c,d)", /* 192 */ "F = 168E(a,b,c,d)", /* 193 */ "F = 1696(a,b,c,d)", /* 194 */ "F = 1697(a,b,c,d)", /* 195 */ "F = 1698(a,b,c,d)", /* 196 */ "F = 1699(a,b,c,d)", /* 197 */ "F = 169A(a,b,c,d)", /* 198 */ "F = 169B(a,b,c,d)", /* 199 */ "F = 169E(a,b,c,d)", /* 200 */ "F = 16A9(a,b,c,d)", /* 201 */ "F = 16AC(a,b,c,d)", /* 202 */ "F = 16AD(a,b,c,d)", /* 203 */ "F = 16BC(a,b,c,d)", /* 204 */ "F = (d+E9(a,b,c))", /* 205 */ "F = 177E(a,b,c,d)", /* 206 */ "F = 178E(a,b,c,d)", /* 207 */ "F = 1796(a,b,c,d)", /* 208 */ "F = 1798(a,b,c,d)", /* 209 */ "F = 179A(a,b,c,d)", /* 210 */ "F = 17AC(a,b,c,d)", /* 211 */ "F = (d+E8(a,b,c))", /* 212 */ "F = (d+E7(a,b,c))", /* 213 */ "F = 19E1(a,b,c,d)", /* 214 */ "F = 19E3(a,b,c,d)", /* 215 */ "F = (d+E6(a,b,c))", /* 216 */ "F = 1BD8(a,b,c,d)", /* 217 */ "F = (d+CA(b,c,a))", /* 218 */ "F = (d+(c+(!b*!a)))", /* 219 */ "F = (d+(c+!b))", /* 220 */ "F = (d+(c+(b+a)))" /* 221 */ }; return (char **)pNames; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitFactor.c000066400000000000000000000256001300674244400236530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitFactor.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Algebraic factoring.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitFactor.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // factoring fails if intermediate memory usage exceed this limit #define KIT_FACTOR_MEM_LIMIT (1<<20) static Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ); static Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory ); static Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits ); static Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits ); extern int Kit_SopFactorVerify( Vec_Int_t * cSop, Kit_Graph_t * pFForm, int nVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Factors the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Graph_t * Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory ) { Kit_Sop_t Sop, * cSop = &Sop; Kit_Graph_t * pFForm; Kit_Edge_t eRoot; // int nCubes; // works for up to 15 variables because division procedure // used the last bit for marking the cubes going to the remainder assert( nVars < 16 ); // check for trivial functions if ( Vec_IntSize(vCover) == 0 ) return Kit_GraphCreateConst0(); if ( Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0 ) return Kit_GraphCreateConst1(); // prepare memory manager // Vec_IntClear( vMemory ); Vec_IntGrow( vMemory, KIT_FACTOR_MEM_LIMIT ); // perform CST Kit_SopCreateInverse( cSop, vCover, 2 * nVars, vMemory ); // CST // start the factored form pFForm = Kit_GraphCreate( nVars ); // factor the cover eRoot = Kit_SopFactor_rec( pFForm, cSop, 2 * nVars, vMemory ); // finalize the factored form Kit_GraphSetRoot( pFForm, eRoot ); if ( fCompl ) Kit_GraphComplement( pFForm ); // verify the factored form // nCubes = Vec_IntSize(vCover); // Vec_IntShrink( vCover, nCubes ); // if ( !Kit_SopFactorVerify( vCover, pFForm, nVars ) ) // printf( "Verification has failed.\n" ); return pFForm; } /**Function************************************************************* Synopsis [Recursive factoring procedure.] Description [For the pseudo-code, see Hachtel/Somenzi, Logic synthesis and verification algorithms, Kluwer, 1996, p. 432.] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ) { Kit_Sop_t Div, Quo, Rem, Com; Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem, * cCom = &Com; Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd; // make sure the cover contains some cubes assert( Kit_SopCubeNum(cSop) > 0 ); // get the divisor if ( !Kit_SopDivisor(cDiv, cSop, nLits, vMemory) ) return Kit_SopFactorTrivial( pFForm, cSop, nLits ); // divide the cover by the divisor Kit_SopDivideInternal( cSop, cDiv, cQuo, cRem, vMemory ); // check the trivial case assert( Kit_SopCubeNum(cQuo) > 0 ); if ( Kit_SopCubeNum(cQuo) == 1 ) return Kit_SopFactorLF_rec( pFForm, cSop, cQuo, nLits, vMemory ); // make the quotient cube ABC_FREE Kit_SopMakeCubeFree( cQuo ); // divide the cover by the quotient Kit_SopDivideInternal( cSop, cQuo, cDiv, cRem, vMemory ); // check the trivial case if ( Kit_SopIsCubeFree( cDiv ) ) { eNodeDiv = Kit_SopFactor_rec( pFForm, cDiv, nLits, vMemory ); eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory ); eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); if ( Kit_SopCubeNum(cRem) == 0 ) return eNodeAnd; eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory ); return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); } // get the common cube Kit_SopCommonCubeCover( cCom, cDiv, vMemory ); // solve the simple problem return Kit_SopFactorLF_rec( pFForm, cSop, cCom, nLits, vMemory ); } /**Function************************************************************* Synopsis [Internal recursive factoring procedure for the leaf case.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory ) { Kit_Sop_t Div, Quo, Rem; Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem; Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd; assert( Kit_SopCubeNum(cSimple) == 1 ); // get the most often occurring literal Kit_SopBestLiteralCover( cDiv, cSop, Kit_SopCube(cSimple, 0), nLits, vMemory ); // divide the cover by the literal Kit_SopDivideByCube( cSop, cDiv, cQuo, cRem, vMemory ); // get the node pointer for the literal eNodeDiv = Kit_SopFactorTrivialCube( pFForm, Kit_SopCube(cDiv, 0), nLits ); // factor the quotient and remainder eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory ); eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); if ( Kit_SopCubeNum(cRem) == 0 ) return eNodeAnd; eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory ); return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); } /**Function************************************************************* Synopsis [Factoring cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_SopFactorTrivialCube_rec( Kit_Graph_t * pFForm, unsigned uCube, int nStart, int nFinish ) { Kit_Edge_t eNode1, eNode2; int i, iLit = -1, nLits, nLits1, nLits2; assert( uCube ); // count the number of literals in this interval nLits = 0; for ( i = nStart; i < nFinish; i++ ) if ( Kit_CubeHasLit(uCube, i) ) { iLit = i; nLits++; } assert( iLit != -1 ); // quit if there is only one literal if ( nLits == 1 ) return Kit_EdgeCreate( iLit/2, iLit%2 ); // CST // split the literals into two parts nLits1 = nLits/2; nLits2 = nLits - nLits1; // nLits2 = nLits/2; // nLits1 = nLits - nLits2; // find the splitting point nLits = 0; for ( i = nStart; i < nFinish; i++ ) if ( Kit_CubeHasLit(uCube, i) ) { if ( nLits == nLits1 ) break; nLits++; } // recursively construct the tree for the parts eNode1 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, nStart, i ); eNode2 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, i, nFinish ); return Kit_GraphAddNodeAnd( pFForm, eNode1, eNode2 ); } /**Function************************************************************* Synopsis [Factoring cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits ) { return Kit_SopFactorTrivialCube_rec( pFForm, uCube, 0, nLits ); } /**Function************************************************************* Synopsis [Factoring SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_SopFactorTrivial_rec( Kit_Graph_t * pFForm, unsigned * pCubes, int nCubes, int nLits ) { Kit_Edge_t eNode1, eNode2; int nCubes1, nCubes2; if ( nCubes == 1 ) return Kit_SopFactorTrivialCube_rec( pFForm, pCubes[0], 0, nLits ); // split the cubes into two parts nCubes1 = nCubes/2; nCubes2 = nCubes - nCubes1; // nCubes2 = nCubes/2; // nCubes1 = nCubes - nCubes2; // recursively construct the tree for the parts eNode1 = Kit_SopFactorTrivial_rec( pFForm, pCubes, nCubes1, nLits ); eNode2 = Kit_SopFactorTrivial_rec( pFForm, pCubes + nCubes1, nCubes2, nLits ); return Kit_GraphAddNodeOr( pFForm, eNode1, eNode2 ); } /**Function************************************************************* Synopsis [Factoring the cover, which has no algebraic divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits ) { return Kit_SopFactorTrivial_rec( pFForm, cSop->pCubes, cSop->nCubes, nLits ); } /**Function************************************************************* Synopsis [Testing procedure for the factoring code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_FactorTest( unsigned * pTruth, int nVars ) { Vec_Int_t * vCover, * vMemory; Kit_Graph_t * pGraph; // unsigned uTruthRes; int RetValue; // derive SOP vCover = Vec_IntAlloc( 0 ); RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); assert( RetValue == 0 ); // derive factored form vMemory = Vec_IntAlloc( 0 ); pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory ); /* // derive truth table assert( nVars <= 5 ); uTruthRes = Kit_GraphToTruth( pGraph ); if ( uTruthRes != pTruth[0] ) printf( "Verification failed!" ); */ printf( "Vars = %2d. Cubes = %3d. FFNodes = %3d. FF_memory = %3d.\n", nVars, Vec_IntSize(vCover), Kit_GraphNodeNum(pGraph), Vec_IntSize(vMemory) ); Vec_IntFree( vMemory ); Vec_IntFree( vCover ); Kit_GraphFree( pGraph ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitGraph.c000066400000000000000000000270141300674244400234770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitGraph.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Decomposition graph representation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitGraph.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates a graph with the given number of leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Graph_t * Kit_GraphCreate( int nLeaves ) { Kit_Graph_t * pGraph; pGraph = ABC_ALLOC( Kit_Graph_t, 1 ); memset( pGraph, 0, sizeof(Kit_Graph_t) ); pGraph->nLeaves = nLeaves; pGraph->nSize = nLeaves; pGraph->nCap = 2 * nLeaves + 50; pGraph->pNodes = ABC_ALLOC( Kit_Node_t, pGraph->nCap ); memset( pGraph->pNodes, 0, sizeof(Kit_Node_t) * pGraph->nSize ); return pGraph; } /**Function************************************************************* Synopsis [Creates constant 0 graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Graph_t * Kit_GraphCreateConst0() { Kit_Graph_t * pGraph; pGraph = ABC_ALLOC( Kit_Graph_t, 1 ); memset( pGraph, 0, sizeof(Kit_Graph_t) ); pGraph->fConst = 1; pGraph->eRoot.fCompl = 1; return pGraph; } /**Function************************************************************* Synopsis [Creates constant 1 graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Graph_t * Kit_GraphCreateConst1() { Kit_Graph_t * pGraph; pGraph = ABC_ALLOC( Kit_Graph_t, 1 ); memset( pGraph, 0, sizeof(Kit_Graph_t) ); pGraph->fConst = 1; return pGraph; } /**Function************************************************************* Synopsis [Creates the literal graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Graph_t * Kit_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) { Kit_Graph_t * pGraph; assert( 0 <= iLeaf && iLeaf < nLeaves ); pGraph = Kit_GraphCreate( nLeaves ); pGraph->eRoot.Node = iLeaf; pGraph->eRoot.fCompl = fCompl; return pGraph; } /**Function************************************************************* Synopsis [Creates a graph with the given number of leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_GraphFree( Kit_Graph_t * pGraph ) { ABC_FREE( pGraph->pNodes ); ABC_FREE( pGraph ); } /**Function************************************************************* Synopsis [Appends a new node to the graph.] Description [This procedure is meant for internal use.] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Node_t * Kit_GraphAppendNode( Kit_Graph_t * pGraph ) { Kit_Node_t * pNode; if ( pGraph->nSize == pGraph->nCap ) { pGraph->pNodes = ABC_REALLOC( Kit_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); pGraph->nCap = 2 * pGraph->nCap; } pNode = pGraph->pNodes + pGraph->nSize++; memset( pNode, 0, sizeof(Kit_Node_t) ); return pNode; } /**Function************************************************************* Synopsis [Creates an AND node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_GraphAddNodeAnd( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ) { Kit_Node_t * pNode; // get the new node pNode = Kit_GraphAppendNode( pGraph ); // set the inputs and other info pNode->eEdge0 = eEdge0; pNode->eEdge1 = eEdge1; pNode->fCompl0 = eEdge0.fCompl; pNode->fCompl1 = eEdge1.fCompl; return Kit_EdgeCreate( pGraph->nSize - 1, 0 ); } /**Function************************************************************* Synopsis [Creates an OR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_GraphAddNodeOr( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ) { Kit_Node_t * pNode; // get the new node pNode = Kit_GraphAppendNode( pGraph ); // set the inputs and other info pNode->eEdge0 = eEdge0; pNode->eEdge1 = eEdge1; pNode->fCompl0 = eEdge0.fCompl; pNode->fCompl1 = eEdge1.fCompl; // make adjustments for the OR gate pNode->fNodeOr = 1; pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; return Kit_EdgeCreate( pGraph->nSize - 1, 1 ); } /**Function************************************************************* Synopsis [Creates an XOR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_GraphAddNodeXor( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1, int Type ) { Kit_Edge_t eNode0, eNode1, eNode; if ( Type == 0 ) { // derive the first AND eEdge0.fCompl ^= 1; eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); eEdge0.fCompl ^= 1; // derive the second AND eEdge1.fCompl ^= 1; eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the final OR eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); } else { // derive the first AND eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the second AND eEdge0.fCompl ^= 1; eEdge1.fCompl ^= 1; eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); // derive the final OR eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); eNode.fCompl ^= 1; } return eNode; } /**Function************************************************************* Synopsis [Creates an XOR node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Edge_t Kit_GraphAddNodeMux( Kit_Graph_t * pGraph, Kit_Edge_t eEdgeC, Kit_Edge_t eEdgeT, Kit_Edge_t eEdgeE, int Type ) { Kit_Edge_t eNode0, eNode1, eNode; if ( Type == 0 ) { // derive the first AND eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); // derive the second AND eEdgeC.fCompl ^= 1; eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); // derive the final OR eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); } else { // complement the arguments eEdgeT.fCompl ^= 1; eEdgeE.fCompl ^= 1; // derive the first AND eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); // derive the second AND eEdgeC.fCompl ^= 1; eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); // derive the final OR eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); eNode.fCompl ^= 1; } return eNode; } /**Function************************************************************* Synopsis [Derives the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph ) { unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; unsigned uTruth = 0, uTruth0, uTruth1; Kit_Node_t * pNode; int i; // sanity checks assert( Kit_GraphLeaveNum(pGraph) >= 0 ); assert( Kit_GraphLeaveNum(pGraph) <= pGraph->nSize ); assert( Kit_GraphLeaveNum(pGraph) <= 5 ); // check for constant function if ( Kit_GraphIsConst(pGraph) ) return Kit_GraphIsComplement(pGraph)? 0 : ~((unsigned)0); // check for a literal if ( Kit_GraphIsVar(pGraph) ) return Kit_GraphIsComplement(pGraph)? ~uTruths[Kit_GraphVarInt(pGraph)] : uTruths[Kit_GraphVarInt(pGraph)]; // assign the elementary variables Kit_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = (void *)(long)uTruths[i]; // compute the function for each internal node Kit_GraphForEachNode( pGraph, pNode, i ) { uTruth0 = (unsigned)(long)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; uTruth1 = (unsigned)(long)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0; uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1; uTruth = uTruth0 & uTruth1; pNode->pFunc = (void *)(long)uTruth; } // complement the result if necessary return Kit_GraphIsComplement(pGraph)? ~uTruth : uTruth; } /**Function************************************************************* Synopsis [Derives the factored form from the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) { Kit_Graph_t * pGraph; int RetValue; // derive SOP RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 1 ); // tried 1 and found not useful in "renode" if ( RetValue == -1 ) return NULL; if ( Vec_IntSize(vMemory) > (1<<16) ) return NULL; // printf( "Isop size = %d.\n", Vec_IntSize(vMemory) ); assert( RetValue == 0 || RetValue == 1 ); // derive factored form pGraph = Kit_SopFactor( vMemory, RetValue, nVars, vMemory ); return pGraph; } /**Function************************************************************* Synopsis [Derives the maximum depth from the leaf to the root.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf ) { int Depth0, Depth1, Depth; if ( pNode == pLeaf ) return 0; if ( Kit_GraphNodeIsVar(pGraph, pNode) ) return -100; Depth0 = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeFanin0(pGraph, pNode), pLeaf ); Depth1 = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeFanin1(pGraph, pNode), pLeaf ); Depth = KIT_MAX( Depth0, Depth1 ); Depth = (Depth == -100) ? -100 : Depth + 1; return Depth; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitHop.c000066400000000000000000000154361300674244400231710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitHop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Procedures involving AIGs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitHop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" #include "aig/hop/hop.h" #include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_GraphToGiaInternal( Gia_Man_t * pMan, Kit_Graph_t * pGraph, int fHash ) { Kit_Node_t * pNode = NULL; int i, pAnd0, pAnd1; // check for constant function if ( Kit_GraphIsConst(pGraph) ) return Abc_LitNotCond( 1, Kit_GraphIsComplement(pGraph) ); // check for a literal if ( Kit_GraphIsVar(pGraph) ) return Abc_LitNotCond( Kit_GraphVar(pGraph)->iFunc, Kit_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph Kit_GraphForEachNode( pGraph, pNode, i ) { pAnd0 = Abc_LitNotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->iFunc, pNode->eEdge0.fCompl ); pAnd1 = Abc_LitNotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->iFunc, pNode->eEdge1.fCompl ); if ( fHash ) pNode->iFunc = Gia_ManHashAnd( pMan, pAnd0, pAnd1 ); else pNode->iFunc = Gia_ManAppendAnd2( pMan, pAnd0, pAnd1 ); } // complement the result if necessary return Abc_LitNotCond( pNode->iFunc, Kit_GraphIsComplement(pGraph) ); } int Kit_GraphToGia( Gia_Man_t * pMan, Kit_Graph_t * pGraph, Vec_Int_t * vLeaves, int fHash ) { Kit_Node_t * pNode = NULL; int i; // collect the fanins Kit_GraphForEachLeaf( pGraph, pNode, i ) pNode->iFunc = vLeaves ? Vec_IntEntry(vLeaves, i) : Gia_Obj2Lit(pMan, Gia_ManPi(pMan, i)); // perform strashing return Kit_GraphToGiaInternal( pMan, pGraph, fHash ); } int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ) { int iLit; Kit_Graph_t * pGraph; // transform truth table into the decomposition tree if ( vMemory == NULL ) { vMemory = Vec_IntAlloc( 0 ); pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); Vec_IntFree( vMemory ); } else pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); if ( pGraph == NULL ) { printf( "Kit_TruthToGia(): Converting truth table to AIG has failed for function:\n" ); Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" ); } // derive the AIG for the decomposition tree iLit = Kit_GraphToGia( pMan, pGraph, vLeaves, fHash ); Kit_GraphFree( pGraph ); return iLit; } /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) { Kit_Node_t * pNode = NULL; Hop_Obj_t * pAnd0, * pAnd1; int i; // check for constant function if ( Kit_GraphIsConst(pGraph) ) return Hop_NotCond( Hop_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); // check for a literal if ( Kit_GraphIsVar(pGraph) ) return Hop_NotCond( (Hop_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph Kit_GraphForEachNode( pGraph, pNode, i ) { pAnd0 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Hop_NotCond( (Hop_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); } // complement the result if necessary return Hop_NotCond( (Hop_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) ); } Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) { Kit_Node_t * pNode = NULL; int i; // collect the fanins Kit_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = Hop_IthVar( pMan, i ); // perform strashing return Kit_GraphToHopInternal( pMan, pGraph ); } Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) { Hop_Obj_t * pObj; Kit_Graph_t * pGraph; // transform truth table into the decomposition tree if ( vMemory == NULL ) { vMemory = Vec_IntAlloc( 0 ); pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); Vec_IntFree( vMemory ); } else pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); if ( pGraph == NULL ) { printf( "Kit_TruthToHop(): Converting truth table to AIG has failed for function:\n" ); Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" ); } // derive the AIG for the decomposition tree pObj = Kit_GraphToHop( pMan, pGraph ); Kit_GraphFree( pGraph ); return pObj; } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ) { Kit_Graph_t * pGraph; Hop_Obj_t * pFunc; // perform factoring Vec_IntClear( vMemory ); pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory ); // convert graph to the AIG pFunc = Kit_GraphToHop( pMan, pGraph ); Kit_GraphFree( pGraph ); return pFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitIsop.c000066400000000000000000000302501300674244400233440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitIsop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [ISOP computation based on Morreale's algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitIsop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // ISOP computation fails if intermediate memory usage exceed this limit #define KIT_ISOP_MEM_LIMIT (1<<20) // static procedures to compute ISOP static unsigned * Kit_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ); static unsigned Kit_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes ISOP from TT.] Description [Returns the cover in vMemory. Uses the rest of array in vMemory as an intermediate memory storage. Returns the cover with -1 cubes, if the the computation exceeded the memory limit (KIT_ISOP_MEM_LIMIT words of intermediate data).] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ) { Kit_Sop_t cRes, * pcRes = &cRes; Kit_Sop_t cRes2, * pcRes2 = &cRes2; unsigned * pResult; int RetValue = 0; assert( nVars >= 0 && nVars <= 16 ); // if nVars < 5, make sure it does not depend on those vars // for ( i = nVars; i < 5; i++ ) // assert( !Kit_TruthVarInSupport(puTruth, 5, i) ); // prepare memory manager Vec_IntClear( vMemory ); Vec_IntGrow( vMemory, KIT_ISOP_MEM_LIMIT ); // compute ISOP for the direct polarity pResult = Kit_TruthIsop_rec( puTruth, puTruth, nVars, pcRes, vMemory ); if ( pcRes->nCubes == -1 ) { vMemory->nSize = -1; return -1; } assert( Kit_TruthIsEqual( puTruth, pResult, nVars ) ); if ( pcRes->nCubes == 0 || (pcRes->nCubes == 1 && pcRes->pCubes[0] == 0) ) { vMemory->pArray[0] = 0; Vec_IntShrink( vMemory, pcRes->nCubes ); return 0; } if ( fTryBoth ) { // compute ISOP for the complemented polarity Kit_TruthNot( puTruth, puTruth, nVars ); pResult = Kit_TruthIsop_rec( puTruth, puTruth, nVars, pcRes2, vMemory ); if ( pcRes2->nCubes >= 0 ) { assert( Kit_TruthIsEqual( puTruth, pResult, nVars ) ); if ( pcRes->nCubes > pcRes2->nCubes || (pcRes->nCubes == pcRes2->nCubes && pcRes->nLits > pcRes2->nLits) ) { RetValue = 1; pcRes = pcRes2; } } Kit_TruthNot( puTruth, puTruth, nVars ); } // printf( "%d ", vMemory->nSize ); // move the cover representation to the beginning of the memory buffer memmove( vMemory->pArray, pcRes->pCubes, pcRes->nCubes * sizeof(unsigned) ); Vec_IntShrink( vMemory, pcRes->nCubes ); return RetValue; } void Kit_TruthIsopPrintCover( Vec_Int_t * vCover, int nVars, int fCompl ) { int i, k, Entry, Literal; if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0) ) { printf( "Constant %d\n", Vec_IntSize(vCover) ); return; } Vec_IntForEachEntry( vCover, Entry, i ) { for ( k = 0; k < nVars; k++ ) { Literal = 3 & (Entry >> (k << 1)); if ( Literal == 1 ) // neg literal printf( "0" ); else if ( Literal == 2 ) // pos literal printf( "1" ); else if ( Literal == 0 ) printf( "-" ); else assert( 0 ); } printf( " %d\n", !fCompl ); } } void Kit_TruthIsopPrint( unsigned * puTruth, int nVars, Vec_Int_t * vCover, int fTryBoth ) { int fCompl = Kit_TruthIsop( puTruth, nVars, vCover, fTryBoth ); Kit_TruthIsopPrintCover( vCover, nVars, fCompl ); } /**Function************************************************************* Synopsis [Computes ISOP 6 variables or more.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Kit_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ) { Kit_Sop_t cRes0, cRes1, cRes2; Kit_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; unsigned * puRes0, * puRes1, * puRes2; unsigned * puOn0, * puOn1, * puOnDc0, * puOnDc1, * pTemp, * pTemp0, * pTemp1; int i, k, Var, nWords, nWordsAll; // assert( Kit_TruthIsImply( puOn, puOnDc, nVars ) ); // allocate room for the resulting truth table nWordsAll = Kit_TruthWordNum( nVars ); pTemp = Vec_IntFetch( vStore, nWordsAll ); if ( pTemp == NULL ) { pcRes->nCubes = -1; return NULL; } // check for constants if ( Kit_TruthIsConst0( puOn, nVars ) ) { pcRes->nLits = 0; pcRes->nCubes = 0; pcRes->pCubes = NULL; Kit_TruthClear( pTemp, nVars ); return pTemp; } if ( Kit_TruthIsConst1( puOnDc, nVars ) ) { pcRes->nLits = 0; pcRes->nCubes = 1; pcRes->pCubes = Vec_IntFetch( vStore, 1 ); if ( pcRes->pCubes == NULL ) { pcRes->nCubes = -1; return NULL; } pcRes->pCubes[0] = 0; Kit_TruthFill( pTemp, nVars ); return pTemp; } assert( nVars > 0 ); // find the topmost var for ( Var = nVars-1; Var >= 0; Var-- ) if ( Kit_TruthVarInSupport( puOn, nVars, Var ) || Kit_TruthVarInSupport( puOnDc, nVars, Var ) ) break; assert( Var >= 0 ); // consider a simple case when one-word computation can be used if ( Var < 5 ) { unsigned uRes = Kit_TruthIsop5_rec( puOn[0], puOnDc[0], Var+1, pcRes, vStore ); for ( i = 0; i < nWordsAll; i++ ) pTemp[i] = uRes; return pTemp; } assert( Var >= 5 ); nWords = Kit_TruthWordNum( Var ); // cofactor puOn0 = puOn; puOn1 = puOn + nWords; puOnDc0 = puOnDc; puOnDc1 = puOnDc + nWords; pTemp0 = pTemp; pTemp1 = pTemp + nWords; // solve for cofactors Kit_TruthSharp( pTemp0, puOn0, puOnDc1, Var ); puRes0 = Kit_TruthIsop_rec( pTemp0, puOnDc0, Var, pcRes0, vStore ); if ( pcRes0->nCubes == -1 ) { pcRes->nCubes = -1; return NULL; } Kit_TruthSharp( pTemp1, puOn1, puOnDc0, Var ); puRes1 = Kit_TruthIsop_rec( pTemp1, puOnDc1, Var, pcRes1, vStore ); if ( pcRes1->nCubes == -1 ) { pcRes->nCubes = -1; return NULL; } Kit_TruthSharp( pTemp0, puOn0, puRes0, Var ); Kit_TruthSharp( pTemp1, puOn1, puRes1, Var ); Kit_TruthOr( pTemp0, pTemp0, pTemp1, Var ); Kit_TruthAnd( pTemp1, puOnDc0, puOnDc1, Var ); puRes2 = Kit_TruthIsop_rec( pTemp0, pTemp1, Var, pcRes2, vStore ); if ( pcRes2->nCubes == -1 ) { pcRes->nCubes = -1; return NULL; } // create the resulting cover pcRes->nLits = pcRes0->nLits + pcRes1->nLits + pcRes2->nLits + pcRes0->nCubes + pcRes1->nCubes; pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); if ( pcRes->pCubes == NULL ) { pcRes->nCubes = -1; return NULL; } k = 0; for ( i = 0; i < pcRes0->nCubes; i++ ) pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+0)); for ( i = 0; i < pcRes1->nCubes; i++ ) pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+1)); for ( i = 0; i < pcRes2->nCubes; i++ ) pcRes->pCubes[k++] = pcRes2->pCubes[i]; assert( k == pcRes->nCubes ); // create the resulting truth table Kit_TruthOr( pTemp0, puRes0, puRes2, Var ); Kit_TruthOr( pTemp1, puRes1, puRes2, Var ); // copy the table if needed nWords <<= 1; for ( i = 1; i < nWordsAll/nWords; i++ ) for ( k = 0; k < nWords; k++ ) pTemp[i*nWords + k] = pTemp[k]; // verify in the end // assert( Kit_TruthIsImply( puOn, pTemp, nVars ) ); // assert( Kit_TruthIsImply( pTemp, puOnDc, nVars ) ); return pTemp; } /**Function************************************************************* Synopsis [Computes ISOP for 5 variables or less.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Kit_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ) { unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; Kit_Sop_t cRes0, cRes1, cRes2; Kit_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; unsigned uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2; int i, k, Var; assert( nVars <= 5 ); assert( (uOn & ~uOnDc) == 0 ); if ( uOn == 0 ) { pcRes->nLits = 0; pcRes->nCubes = 0; pcRes->pCubes = NULL; return 0; } if ( uOnDc == 0xFFFFFFFF ) { pcRes->nLits = 0; pcRes->nCubes = 1; pcRes->pCubes = Vec_IntFetch( vStore, 1 ); if ( pcRes->pCubes == NULL ) { pcRes->nCubes = -1; return 0; } pcRes->pCubes[0] = 0; return 0xFFFFFFFF; } assert( nVars > 0 ); // find the topmost var for ( Var = nVars-1; Var >= 0; Var-- ) if ( Kit_TruthVarInSupport( &uOn, 5, Var ) || Kit_TruthVarInSupport( &uOnDc, 5, Var ) ) break; assert( Var >= 0 ); // cofactor uOn0 = uOn1 = uOn; uOnDc0 = uOnDc1 = uOnDc; Kit_TruthCofactor0( &uOn0, Var + 1, Var ); Kit_TruthCofactor1( &uOn1, Var + 1, Var ); Kit_TruthCofactor0( &uOnDc0, Var + 1, Var ); Kit_TruthCofactor1( &uOnDc1, Var + 1, Var ); // solve for cofactors uRes0 = Kit_TruthIsop5_rec( uOn0 & ~uOnDc1, uOnDc0, Var, pcRes0, vStore ); if ( pcRes0->nCubes == -1 ) { pcRes->nCubes = -1; return 0; } uRes1 = Kit_TruthIsop5_rec( uOn1 & ~uOnDc0, uOnDc1, Var, pcRes1, vStore ); if ( pcRes1->nCubes == -1 ) { pcRes->nCubes = -1; return 0; } uRes2 = Kit_TruthIsop5_rec( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pcRes2, vStore ); if ( pcRes2->nCubes == -1 ) { pcRes->nCubes = -1; return 0; } // create the resulting cover pcRes->nLits = pcRes0->nLits + pcRes1->nLits + pcRes2->nLits + pcRes0->nCubes + pcRes1->nCubes; pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); if ( pcRes->pCubes == NULL ) { pcRes->nCubes = -1; return 0; } k = 0; for ( i = 0; i < pcRes0->nCubes; i++ ) pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+0)); for ( i = 0; i < pcRes1->nCubes; i++ ) pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+1)); for ( i = 0; i < pcRes2->nCubes; i++ ) pcRes->pCubes[k++] = pcRes2->pCubes[i]; assert( k == pcRes->nCubes ); // derive the final truth table uRes2 |= (uRes0 & ~uMasks[Var]) | (uRes1 & uMasks[Var]); // assert( (uOn & ~uRes2) == 0 ); // assert( (uRes2 & ~uOnDc) == 0 ); return uRes2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitPerm.c000066400000000000000000000251251300674244400233420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitPerm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Procedures for permuting truth tables.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 26, 2011.] Revision [$Id: kitPerm.c,v 1.00 2011/11/26 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "kit.h" #define inline __inline // compatible with MS VS 6.0 //ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef unsigned __int64 word; typedef unsigned short shot; typedef unsigned char byte; static shot S[256] = { 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 }; static byte P[256] = { 0x00, 0x01, 0x10, 0x11, 0x04, 0x05, 0x14, 0x15, 0x40, 0x41, 0x50, 0x51, 0x44, 0x45, 0x54, 0x55, 0x02, 0x03, 0x12, 0x13, 0x06, 0x07, 0x16, 0x17, 0x42, 0x43, 0x52, 0x53, 0x46, 0x47, 0x56, 0x57, 0x20, 0x21, 0x30, 0x31, 0x24, 0x25, 0x34, 0x35, 0x60, 0x61, 0x70, 0x71, 0x64, 0x65, 0x74, 0x75, 0x22, 0x23, 0x32, 0x33, 0x26, 0x27, 0x36, 0x37, 0x62, 0x63, 0x72, 0x73, 0x66, 0x67, 0x76, 0x77, 0x08, 0x09, 0x18, 0x19, 0x0c, 0x0d, 0x1c, 0x1d, 0x48, 0x49, 0x58, 0x59, 0x4c, 0x4d, 0x5c, 0x5d, 0x0a, 0x0b, 0x1a, 0x1b, 0x0e, 0x0f, 0x1e, 0x1f, 0x4a, 0x4b, 0x5a, 0x5b, 0x4e, 0x4f, 0x5e, 0x5f, 0x28, 0x29, 0x38, 0x39, 0x2c, 0x2d, 0x3c, 0x3d, 0x68, 0x69, 0x78, 0x79, 0x6c, 0x6d, 0x7c, 0x7d, 0x2a, 0x2b, 0x3a, 0x3b, 0x2e, 0x2f, 0x3e, 0x3f, 0x6a, 0x6b, 0x7a, 0x7b, 0x6e, 0x6f, 0x7e, 0x7f, 0x80, 0x81, 0x90, 0x91, 0x84, 0x85, 0x94, 0x95, 0xc0, 0xc1, 0xd0, 0xd1, 0xc4, 0xc5, 0xd4, 0xd5, 0x82, 0x83, 0x92, 0x93, 0x86, 0x87, 0x96, 0x97, 0xc2, 0xc3, 0xd2, 0xd3, 0xc6, 0xc7, 0xd6, 0xd7, 0xa0, 0xa1, 0xb0, 0xb1, 0xa4, 0xa5, 0xb4, 0xb5, 0xe0, 0xe1, 0xf0, 0xf1, 0xe4, 0xe5, 0xf4, 0xf5, 0xa2, 0xa3, 0xb2, 0xb3, 0xa6, 0xa7, 0xb6, 0xb7, 0xe2, 0xe3, 0xf2, 0xf3, 0xe6, 0xe7, 0xf6, 0xf7, 0x88, 0x89, 0x98, 0x99, 0x8c, 0x8d, 0x9c, 0x9d, 0xc8, 0xc9, 0xd8, 0xd9, 0xcc, 0xcd, 0xdc, 0xdd, 0x8a, 0x8b, 0x9a, 0x9b, 0x8e, 0x8f, 0x9e, 0x9f, 0xca, 0xcb, 0xda, 0xdb, 0xce, 0xcf, 0xde, 0xdf, 0xa8, 0xa9, 0xb8, 0xb9, 0xac, 0xad, 0xbc, 0xbd, 0xe8, 0xe9, 0xf8, 0xf9, 0xec, 0xed, 0xfc, 0xfd, 0xaa, 0xab, 0xba, 0xbb, 0xae, 0xaf, 0xbe, 0xbf, 0xea, 0xeb, 0xfa, 0xfb, 0xee, 0xef, 0xfe, 0xff }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_PermCreateS() { int i, n, r; for ( i = 0; i < 256; i++ ) { if ( i % 8 == 0 ) printf( "\n" ); for ( r = n = 0; n < 8; n++ ) r |= ((i & (1 << n)) << n); printf( "0x%04x, ", r ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_PermCreateP() { int i, s1, s2, r; for ( i = 0; i < 256; i++ ) { if ( i % 16 == 0 ) printf( "\n" ); s1 = i & 0x0A; s2 = i & 0x50; r = i ^ s1 ^ s2 ^ (s1 << 3) ^ (s2 >> 3); assert( r < 256 ); printf( "0x%02x, ", r ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Kit_PermCycleOne( shot * s, byte * b, int v ) { int i, n = (1 << (v-3)); assert( v > 2 && v < 16 ); for ( i = 0; i < n; i++ ) s[i] = S[b[i]] | (S[b[i+n]] << 1); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Kit_PermCycleMany( shot * s, byte * b, int V, int v ) { int i, n = (1 << (V - 1 - v)), m = (1 << (v-2)); assert( v > 2 && v < V ); for ( i = 0; i < n; i++, s += (m >> 1), b += m ) Kit_PermCycleOne( s, b, v ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_PermCompute( word * o, word * i, int V ) { word * t; int v, n = (1 << (V-3)); assert( V >= 6 && V <= 16 ); for ( v = 0; v < n; v++ ) ((byte *)i)[v] = P[((byte *)i)[v]]; for ( v = 3; v < V; v++ ) { Kit_PermCycleMany( (shot *)o, (byte *)i, V, v ); t = i; i = o; o = t; } if ( V & 1 ) { n = (1 << (V-6)); for ( v = 0; v < n; v++ ) o[v] = i[v]; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_PermComputeNaive( word * F, int nVars ) { extern void If_CluReverseOrder( word * pF, int nVars, int * V2P, int * P2V, int iVarStart ); int i, V2P[16], P2V[16]; for ( i = 0; i < nVars; i++ ) V2P[i] = P2V[i] = i; If_CluReverseOrder( F, nVars, V2P, P2V, 0 ); } word M ( word f1, word f2, int n) { word temp = 0; word a = 1; int i; for( i = 0; i < n; i++) temp = temp + (((f1>>i)&a) << (2*i) ) + (((f2>>i)&a) << (2*i+1)); return temp; } word Tf ( word f, int n) { if(n==1) return f; else { // int x = (int)pow(2,n-1); int x; x = (1 << (n-1)); return ( M (Tf( (f << x) >> x, n-1), Tf( (f >> x), n-1), x) ); //def. of M just below the function } } //#define ABC_PRT(a,t) (printf("%s = ", (a)), printf("%7.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))) #define NFUNCS (1<<20) /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_PermComputeTest() { word * T = (word *)malloc( 8 * NFUNCS ); word i, o, w = 0; int k, b; abctime clk; srand( 0 ); clk = Abc_Clock(); for ( k = 0; k < NFUNCS; k++ ) for ( b = 0; b < 8; b++ ) ((byte *)(T + k))[b] = (byte)(rand() & 0xFF); ABC_PRT( "Assign", Abc_Clock() - clk ); // T[0] = 0xacaccacaaccaacca; // Kit_DsdPrintFromTruth( T, 6 ); // perform measurements clk = Abc_Clock(); for ( k = 0; k < NFUNCS; k++ ) { i = T[k]; // Kit_PermComputeNaive( &i, 6 ); Tf( i, 6 ); } ABC_PRT( "Perm1 ", Abc_Clock() - clk ); // perform measurements clk = Abc_Clock(); for ( k = 0; k < NFUNCS; k++ ) { i = T[k]; Kit_PermCompute( &o, &i, 6 ); // w = T[k]; // Kit_PermComputeNaive( &w, 6 ); // assert( w == o ); } ABC_PRT( "Perm2 ", Abc_Clock() - clk ); assert( w == 0 ); free( T ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ` ***********************************************************************/ void Kit_PermComputeTest_() { word t, s; t = 0xacaccacaaccaacca; // Kit_DsdPrintFromTruth( &t, 6 ); printf( "\n" ); s = Tf( t, 6 ); // Kit_PermComputeNaive( &t, 6 ); // Kit_DsdPrintFromTruth( &s, 6 ); printf( "\n" ); } /* { extern void Kit_PermComputeTest(); Kit_PermComputeTest(); } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// //ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitPla.c000066400000000000000000000346451300674244400231620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitPla.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Manipulating SOP in the form of a C-string.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitPla.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if the cover is constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_PlaIsConst0( char * pSop ) { return pSop[0] == ' ' && pSop[1] == '0'; } /**Function************************************************************* Synopsis [Checks if the cover is constant 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_PlaIsConst1( char * pSop ) { return pSop[0] == ' ' && pSop[1] == '1'; } /**Function************************************************************* Synopsis [Checks if the cover is a buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_PlaIsBuf( 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 an inverter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_PlaIsInv( 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 [Reads the number of variables in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_PlaGetVarNum( char * pSop ) { char * pCur; for ( pCur = pSop; *pCur != '\n'; pCur++ ) if ( *pCur == 0 ) return -1; return pCur - pSop - 2; } /**Function************************************************************* Synopsis [Reads the number of cubes in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_PlaGetCubeNum( char * pSop ) { char * pCur; int nCubes = 0; if ( pSop == NULL ) return 0; for ( pCur = pSop; *pCur; pCur++ ) nCubes += (*pCur == '\n'); return nCubes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_PlaIsComplement( 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_PlaComplement( 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 [Creates the constant 1 cover with the given number of variables and cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_PlaStart( void * p, int nCubes, int nVars ) { Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; char * pSopCover, * pCube; int i, Length; Length = nCubes * (nVars + 3); pSopCover = Aig_MmFlexEntryFetch( pMan, Length + 1 ); memset( pSopCover, '-', 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 cover from the ISOP computed from TT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_PlaCreateFromIsop( void * p, int nVars, Vec_Int_t * vCover ) { Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; char * pSop, * pCube; int i, k, Entry, Literal; assert( Vec_IntSize(vCover) > 0 ); if ( Vec_IntSize(vCover) == 0 ) return NULL; // start the cover pSop = Kit_PlaStart( 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 [] ***********************************************************************/ void Kit_PlaToIsop( char * pSop, Vec_Int_t * vCover ) { char * pCube; int k, nVars, Entry; nVars = Kit_PlaGetVarNum( 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 [Allocates memory and copies the SOP into it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_PlaStoreSop( void * p, char * pSop ) { Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; char * pStore; pStore = Aig_MmFlexEntryFetch( pMan, strlen(pSop) + 1 ); strcpy( pStore, pSop ); return pStore; } /**Function************************************************************* Synopsis [Transforms truth table into the SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_PlaFromTruth( void * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ) { Aig_MmFlex_t * pMan = (Aig_MmFlex_t *)p; char * pSop; int RetValue; if ( Kit_TruthIsConst0(pTruth, nVars) ) return Kit_PlaStoreSop( pMan, " 0\n" ); if ( Kit_TruthIsConst1(pTruth, nVars) ) return Kit_PlaStoreSop( pMan, " 1\n" ); RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); // 1 ); assert( RetValue == 0 || RetValue == 1 ); pSop = Kit_PlaCreateFromIsop( pMan, nVars, vCover ); if ( RetValue ) Kit_PlaComplement( pSop ); return pSop; } /**Function************************************************************* Synopsis [Creates the cover from the ISOP computed from TT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_PlaFromIsop( Vec_Str_t * vStr, int nVars, Vec_Int_t * vCover ) { int i, k, Entry, Literal; assert( Vec_IntSize(vCover) > 0 ); if ( Vec_IntSize(vCover) == 0 ) return NULL; Vec_StrClear( vStr ); Vec_IntForEachEntry( vCover, Entry, i ) { for ( k = 0; k < nVars; k++ ) { Literal = 3 & (Entry >> (k << 1)); if ( Literal == 1 ) Vec_StrPush( vStr, '0' ); else if ( Literal == 2 ) Vec_StrPush( vStr, '1' ); else if ( Literal == 0 ) Vec_StrPush( vStr, '-' ); else assert( 0 ); } Vec_StrPush( vStr, ' ' ); Vec_StrPush( vStr, '1' ); Vec_StrPush( vStr, '\n' ); } Vec_StrPush( vStr, '\0' ); return Vec_StrArray( vStr ); } /**Function************************************************************* Synopsis [Creates the SOP from TT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_PlaFromTruthNew( unsigned * pTruth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vStr ) { char * pResult; // transform truth table into the SOP int RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 1 ); assert( RetValue == 0 || RetValue == 1 ); // check the case of constant cover if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) { assert( RetValue == 0 ); Vec_StrClear( vStr ); Vec_StrAppend( vStr, (Vec_IntSize(vCover) == 0) ? " 0\n" : " 1\n" ); Vec_StrPush( vStr, '\0' ); return Vec_StrArray( vStr ); } pResult = Kit_PlaFromIsop( vStr, nVars, vCover ); if ( RetValue ) Kit_PlaComplement( pResult ); if ( nVars < 6 ) assert( pTruth[0] == (unsigned)Kit_PlaToTruth6(pResult, nVars) ); else if ( nVars == 6 ) assert( *((ABC_UINT64_T*)pTruth) == Kit_PlaToTruth6(pResult, nVars) ); return pResult; } /**Function************************************************************* Synopsis [Converts SOP into a truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ ABC_UINT64_T Kit_PlaToTruth6( char * pSop, int nVars ) { static ABC_UINT64_T 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) }; ABC_UINT64_T valueAnd, valueOr = Truth[6]; int v, lit = 0; assert( nVars < 7 ); do { valueAnd = Truth[7]; for ( v = 0; v < nVars; v++, lit++ ) { if ( pSop[lit] == '1' ) valueAnd &= Truth[v]; else if ( pSop[lit] == '0' ) valueAnd &= ~Truth[v]; else if ( pSop[lit] != '-' ) assert( 0 ); } valueOr |= valueAnd; assert( pSop[lit] == ' ' ); lit++; lit++; assert( pSop[lit] == '\n' ); lit++; } while ( pSop[lit] ); if ( Kit_PlaIsComplement(pSop) ) valueOr = ~valueOr; return valueOr; } /**Fnction************************************************************* Synopsis [Converting SOP into a truth table.] Description [The SOP is represented as a C-string, as documented in file "bblif.h". The truth table is returned as a bit-string composed of 2^nVars bits. For functions of less than 6 variables, the full machine word is returned. (The truth table looks as if the function had 5 variables.) The use of this procedure should be limited to Boolean functions with no more than 16 inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_PlaToTruth( char * pSop, int nVars, Vec_Ptr_t * vVars, unsigned * pTemp, unsigned * pTruth ) { int v, c, nCubes, fCompl = 0; assert( pSop != NULL ); assert( nVars >= 0 ); if ( strlen(pSop) % (nVars + 3) != 0 ) { printf( "Kit_PlaToTruth(): SOP is represented incorrectly.\n" ); return; } // iterate through the cubes Kit_TruthClear( pTruth, nVars ); nCubes = strlen(pSop) / (nVars + 3); for ( c = 0; c < nCubes; c++ ) { fCompl = (pSop[nVars+1] == '0'); Kit_TruthFill( pTemp, nVars ); // iterate through the literals of the cube for ( v = 0; v < nVars; v++ ) if ( pSop[v] == '1' ) Kit_TruthAnd( pTemp, pTemp, (unsigned *)Vec_PtrEntry(vVars, v), nVars ); else if ( pSop[v] == '0' ) Kit_TruthSharp( pTemp, pTemp, (unsigned *)Vec_PtrEntry(vVars, v), nVars ); // add cube to storage Kit_TruthOr( pTruth, pTruth, pTemp, nVars ); // go to the next cube pSop += (nVars + 3); } if ( fCompl ) Kit_TruthNot( pTruth, pTruth, nVars ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitSop.c000066400000000000000000000402641300674244400232010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitSop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Procedures involving SOPs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitSop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates SOP from the cube array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ) { unsigned uCube; int i; // start the cover cResult->nCubes = 0; cResult->pCubes = Vec_IntFetch( vMemory, Vec_IntSize(vInput) ); // add the cubes Vec_IntForEachEntry( vInput, uCube, i ) Kit_SopPushCube( cResult, uCube ); } /**Function************************************************************* Synopsis [Creates SOP from the cube array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nLits, Vec_Int_t * vMemory ) { unsigned uCube, uMask = 0; int i, nCubes = Vec_IntSize(vInput); // start the cover cResult->nCubes = 0; cResult->pCubes = Vec_IntFetch( vMemory, nCubes ); // add the cubes // Vec_IntForEachEntry( vInput, uCube, i ) for ( i = 0; i < nCubes; i++ ) { uCube = Vec_IntEntry( vInput, i ); uMask = ((uCube | (uCube >> 1)) & 0x55555555); uMask |= (uMask << 1); Kit_SopPushCube( cResult, uCube ^ uMask ); } } /**Function************************************************************* Synopsis [Duplicates SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ) { unsigned uCube; int i; // start the cover cResult->nCubes = 0; cResult->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); // add the cubes Kit_SopForEachCube( cSop, uCube, i ) Kit_SopPushCube( cResult, uCube ); } /**Function************************************************************* Synopsis [Derives the quotient of division by literal.] Description [Reduces the cover to be equal to the result of division of the given cover by the literal.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit ) { unsigned uCube; int i, k = 0; Kit_SopForEachCube( cSop, uCube, i ) { if ( Kit_CubeHasLit(uCube, iLit) ) Kit_SopWriteCube( cSop, Kit_CubeRemLit(uCube, iLit), k++ ); } Kit_SopShrink( cSop, k ); } /**Function************************************************************* Synopsis [Divides cover by one cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ) { unsigned uCube, uDiv; int i; // get the only cube assert( Kit_SopCubeNum(cDiv) == 1 ); uDiv = Kit_SopCube(cDiv, 0); // allocate covers vQuo->nCubes = 0; vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); vRem->nCubes = 0; vRem->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); // sort the cubes Kit_SopForEachCube( cSop, uCube, i ) { if ( Kit_CubeContains( uCube, uDiv ) ) Kit_SopPushCube( vQuo, Kit_CubeSharp(uCube, uDiv) ); else Kit_SopPushCube( vRem, uCube ); } } /**Function************************************************************* Synopsis [Divides cover by one cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ) { unsigned uCube, uDiv; unsigned uCube2 = 0; // Suppress "might be used uninitialized" unsigned uDiv2, uQuo; int i, i2, k, k2, nCubesRem; assert( Kit_SopCubeNum(cSop) >= Kit_SopCubeNum(cDiv) ); // consider special case if ( Kit_SopCubeNum(cDiv) == 1 ) { Kit_SopDivideByCube( cSop, cDiv, vQuo, vRem, vMemory ); return; } // allocate quotient vQuo->nCubes = 0; vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) / Kit_SopCubeNum(cDiv) ); // for each cube of the cover // it either belongs to the quotient or to the remainder Kit_SopForEachCube( cSop, uCube, i ) { // skip taken cubes if ( Kit_CubeIsMarked(uCube) ) continue; // find a matching cube in the divisor uDiv = ~0; Kit_SopForEachCube( cDiv, uDiv, k ) if ( Kit_CubeContains( uCube, uDiv ) ) break; // the cube is not found if ( k == Kit_SopCubeNum(cDiv) ) continue; // the quotient cube exists uQuo = Kit_CubeSharp( uCube, uDiv ); // find corresponding cubes for other cubes of the divisor uDiv2 = ~0; Kit_SopForEachCube( cDiv, uDiv2, k2 ) { if ( k2 == k ) continue; // find a matching cube Kit_SopForEachCube( cSop, uCube2, i2 ) { // skip taken cubes if ( Kit_CubeIsMarked(uCube2) ) continue; // check if the cube can be used if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) ) break; } // the case when the cube is not found if ( i2 == Kit_SopCubeNum(cSop) ) break; } // we did not find some cubes - continue looking at other cubes if ( k2 != Kit_SopCubeNum(cDiv) ) continue; // we found all cubes - add the quotient cube Kit_SopPushCube( vQuo, uQuo ); // mark the first cube Kit_SopWriteCube( cSop, Kit_CubeMark(uCube), i ); // mark other cubes that have this quotient Kit_SopForEachCube( cDiv, uDiv2, k2 ) { if ( k2 == k ) continue; // find a matching cube Kit_SopForEachCube( cSop, uCube2, i2 ) { // skip taken cubes if ( Kit_CubeIsMarked(uCube2) ) continue; // check if the cube can be used if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) ) break; } assert( i2 < Kit_SopCubeNum(cSop) ); // the cube is found, mark it // (later we will add all unmarked cubes to the remainder) Kit_SopWriteCube( cSop, Kit_CubeMark(uCube2), i2 ); } } // determine the number of cubes in the remainder nCubesRem = Kit_SopCubeNum(cSop) - Kit_SopCubeNum(vQuo) * Kit_SopCubeNum(cDiv); // allocate remainder vRem->nCubes = 0; vRem->pCubes = Vec_IntFetch( vMemory, nCubesRem ); // finally add the remaining unmarked cubes to the remainder // and clean the marked cubes in the cover Kit_SopForEachCube( cSop, uCube, i ) { if ( !Kit_CubeIsMarked(uCube) ) { Kit_SopPushCube( vRem, uCube ); continue; } Kit_SopWriteCube( cSop, Kit_CubeUnmark(uCube), i ); } assert( nCubesRem == Kit_SopCubeNum(vRem) ); } /**Function************************************************************* Synopsis [Returns the common cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Kit_SopCommonCube( Kit_Sop_t * cSop ) { unsigned uMask, uCube; int i; uMask = ~(unsigned)0; Kit_SopForEachCube( cSop, uCube, i ) uMask &= uCube; return uMask; } /**Function************************************************************* Synopsis [Makes the cover cube-free.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopMakeCubeFree( Kit_Sop_t * cSop ) { unsigned uMask, uCube; int i; uMask = Kit_SopCommonCube( cSop ); if ( uMask == 0 ) return; // remove the common cube Kit_SopForEachCube( cSop, uCube, i ) Kit_SopWriteCube( cSop, Kit_CubeSharp(uCube, uMask), i ); } /**Function************************************************************* Synopsis [Checks if the cover is cube-free.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_SopIsCubeFree( Kit_Sop_t * cSop ) { return Kit_SopCommonCube( cSop ) == 0; } /**Function************************************************************* Synopsis [Creates SOP composes of the common cube of the given SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ) { assert( Kit_SopCubeNum(cSop) > 0 ); cResult->nCubes = 0; cResult->pCubes = Vec_IntFetch( vMemory, 1 ); Kit_SopPushCube( cResult, Kit_SopCommonCube(cSop) ); } /**Function************************************************************* Synopsis [Find any literal that occurs more than once.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits ) { unsigned uCube; int i, k, nLitsCur; // go through each literal for ( i = 0; i < nLits; i++ ) { // go through all the cubes nLitsCur = 0; Kit_SopForEachCube( cSop, uCube, k ) if ( Kit_CubeHasLit(uCube, i) ) nLitsCur++; if ( nLitsCur > 1 ) return i; } return -1; } /**Function************************************************************* Synopsis [Find the least often occurring literal.] Description [Find the least often occurring literal among those that occur more than once.] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_SopWorstLiteral( Kit_Sop_t * cSop, int nLits ) { unsigned uCube; int i, k, iMin, nLitsMin, nLitsCur; int fUseFirst = 1; // go through each literal iMin = -1; nLitsMin = 1000000; for ( i = 0; i < nLits; i++ ) { // go through all the cubes nLitsCur = 0; Kit_SopForEachCube( cSop, uCube, k ) if ( Kit_CubeHasLit(uCube, i) ) nLitsCur++; // skip the literal that does not occur or occurs once if ( nLitsCur < 2 ) continue; // check if this is the best literal if ( fUseFirst ) { if ( nLitsMin > nLitsCur ) { nLitsMin = nLitsCur; iMin = i; } } else { if ( nLitsMin >= nLitsCur ) { nLitsMin = nLitsCur; iMin = i; } } } if ( nLitsMin < 1000000 ) return iMin; return -1; } /**Function************************************************************* Synopsis [Find the least often occurring literal.] Description [Find the least often occurring literal among those that occur more than once.] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_SopBestLiteral( Kit_Sop_t * cSop, int nLits, unsigned uMask ) { unsigned uCube; int i, k, iMax, nLitsMax, nLitsCur; int fUseFirst = 1; // go through each literal iMax = -1; nLitsMax = -1; for ( i = 0; i < nLits; i++ ) { if ( !Kit_CubeHasLit(uMask, i) ) continue; // go through all the cubes nLitsCur = 0; Kit_SopForEachCube( cSop, uCube, k ) if ( Kit_CubeHasLit(uCube, i) ) nLitsCur++; // skip the literal that does not occur or occurs once if ( nLitsCur < 2 ) continue; // check if this is the best literal if ( fUseFirst ) { if ( nLitsMax < nLitsCur ) { nLitsMax = nLitsCur; iMax = i; } } else { if ( nLitsMax <= nLitsCur ) { nLitsMax = nLitsCur; iMax = i; } } } if ( nLitsMax >= 0 ) return iMax; return -1; } /**Function************************************************************* Synopsis [Computes a level-zero kernel.] Description [Modifies the cover to contain one level-zero kernel.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopDivisorZeroKernel_rec( Kit_Sop_t * cSop, int nLits ) { int iLit; // find any literal that occurs at least two times iLit = Kit_SopWorstLiteral( cSop, nLits ); if ( iLit == -1 ) return; // derive the cube-free quotient Kit_SopDivideByLiteralQuo( cSop, iLit ); // the same cover Kit_SopMakeCubeFree( cSop ); // the same cover // call recursively Kit_SopDivisorZeroKernel_rec( cSop, nLits ); // the same cover } /**Function************************************************************* Synopsis [Computes the quick divisor of the cover.] Description [Returns 0, if there is no divisor other than trivial.] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ) { if ( Kit_SopCubeNum(cSop) <= 1 ) return 0; if ( Kit_SopAnyLiteral( cSop, nLits ) == -1 ) return 0; // duplicate the cover Kit_SopDup( cResult, cSop, vMemory ); // perform the kerneling Kit_SopDivisorZeroKernel_rec( cResult, nLits ); assert( Kit_SopCubeNum(cResult) > 0 ); return 1; } /**Function************************************************************* Synopsis [Create the one-literal cover with the best literal from cSop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory ) { int iLitBest; // get the best literal iLitBest = Kit_SopBestLiteral( cSop, nLits, uCube ); // start the cover cResult->nCubes = 0; cResult->pCubes = Vec_IntFetch( vMemory, 1 ); // set the cube Kit_SopPushCube( cResult, Kit_CubeSetLit(0, iLitBest) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kitTruth.c000066400000000000000000002224051300674244400235450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kitTruth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [Procedures involving truth tables.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kitTruth.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Swaps two adjacent variables in the truth table.] Description [Swaps var number Start and var number Start+1 (0-based numbers). The input truth table is pIn. The output truth table is pOut.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) { static unsigned PMasks[4][3] = { { 0x99999999, 0x22222222, 0x44444444 }, { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } }; int nWords = Kit_TruthWordNum( nVars ); int i, k, Step, Shift; assert( iVar < nVars - 1 ); if ( iVar < 4 ) { Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); } else if ( iVar > 4 ) { Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 4*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pIn[i]; for ( i = 0; i < Step; i++ ) pOut[Step+i] = pIn[2*Step+i]; for ( i = 0; i < Step; i++ ) pOut[2*Step+i] = pIn[Step+i]; for ( i = 0; i < Step; i++ ) pOut[3*Step+i] = pIn[3*Step+i]; pIn += 4*Step; pOut += 4*Step; } } else // if ( iVar == 4 ) { for ( i = 0; i < nWords; i += 2 ) { pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); } } } /**Function************************************************************* Synopsis [Swaps two adjacent variables in the truth table.] Description [Swaps var number Start and var number Start+1 (0-based numbers). The input truth table is pIn. The output truth table is pOut.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start ) { int nWords = (nVars <= 5)? 1 : (1 << (nVars-5)); int i, k, Step; assert( Start < nVars - 1 ); switch ( Start ) { case 0: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1); return; case 1: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2); return; case 2: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4); return; case 3: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8); return; case 4: for ( i = 0; i < nWords; i += 2 ) { pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); } return; default: Step = (1 << (Start - 5)); for ( k = 0; k < nWords; k += 4*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pIn[i]; for ( i = 0; i < Step; i++ ) pOut[Step+i] = pIn[2*Step+i]; for ( i = 0; i < Step; i++ ) pOut[2*Step+i] = pIn[Step+i]; for ( i = 0; i < Step; i++ ) pOut[3*Step+i] = pIn[3*Step+i]; pIn += 4*Step; pOut += 4*Step; } return; } } /**Function************************************************************* Synopsis [Expands the truth table according to the phase.] Description [The input and output truth tables are in pIn/pOut. The current number of variables is nVars. The total number of variables in nVarsAll. The last argument (Phase) contains shows where the variables should go.] SideEffects [The input truth table is modified.] SeeAlso [] ***********************************************************************/ void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ) { unsigned * pTemp; int i, k, Var = nVars - 1, Counter = 0; for ( i = nVarsAll - 1; i >= 0; i-- ) if ( Phase & (1 << i) ) { for ( k = Var; k < i; k++ ) { Kit_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); pTemp = pIn; pIn = pOut; pOut = pTemp; Counter++; } Var--; } assert( Var == -1 ); // swap if it was moved an even number of times if ( fReturnIn ^ !(Counter & 1) ) Kit_TruthCopy( pOut, pIn, nVarsAll ); } /**Function************************************************************* Synopsis [Shrinks the truth table according to the phase.] Description [The input and output truth tables are in pIn/pOut. The current number of variables is nVars. The total number of variables in nVarsAll. The last argument (Phase) shows what variables should remain.] SideEffects [The input truth table is modified.] SeeAlso [] ***********************************************************************/ void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ) { unsigned * pTemp; int i, k, Var = 0, Counter = 0; for ( i = 0; i < nVarsAll; i++ ) if ( Phase & (1 << i) ) { for ( k = i-1; k >= Var; k-- ) { Kit_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); pTemp = pIn; pIn = pOut; pOut = pTemp; Counter++; } Var++; } assert( Var == nVars ); // swap if it was moved an even number of times if ( fReturnIn ^ !(Counter & 1) ) Kit_TruthCopy( pOut, pIn, nVarsAll ); } /**Function************************************************************* Synopsis [Implement give permutation.] Description [The input and output truth tables are in pIn/pOut. The number of variables is nVars. Permutation is in pPerm.] SideEffects [The input truth table is modified.] SeeAlso [] ***********************************************************************/ void Kit_TruthPermute( unsigned * pOut, unsigned * pIn, int nVars, char * pPerm, int fReturnIn ) { unsigned * pTemp; int i, Temp, fChange, Counter = 0; do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { assert( pPerm[i] != pPerm[i+1] ); if ( pPerm[i] <= pPerm[i+1] ) continue; Counter++; fChange = 1; Temp = pPerm[i]; pPerm[i] = pPerm[i+1]; pPerm[i+1] = Temp; Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; } } while ( fChange ); if ( fReturnIn ^ !(Counter & 1) ) Kit_TruthCopy( pOut, pIn, nVars ); } /**Function************************************************************* Synopsis [Returns 1 if TT depends on the given variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) ) return 1; return 0; case 1: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) ) return 1; return 0; case 2: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) ) return 1; return 0; case 3: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) ) return 1; return 0; case 4: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) ) return 1; return 0; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) if ( pTruth[i] != pTruth[Step+i] ) return 1; pTruth += 2*Step; } return 0; } } /**Function************************************************************* Synopsis [Returns the number of support vars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthSupportSize( unsigned * pTruth, int nVars ) { int i, Counter = 0; for ( i = 0; i < nVars; i++ ) Counter += Kit_TruthVarInSupport( pTruth, nVars, i ); return Counter; } /**Function************************************************************* Synopsis [Returns support of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Kit_TruthSupport( unsigned * pTruth, int nVars ) { int i, Support = 0; for ( i = 0; i < nVars; i++ ) if ( Kit_TruthVarInSupport( pTruth, nVars, i ) ) Support |= (1 << i); return Support; } /**Function************************************************************* Synopsis [Computes negative cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) pTruth[Step+i] = pTruth[i]; pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Computes negative cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthCofactor0Count( unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step, Counter = 0; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes(pTruth[i] & 0x55555555); return Counter; case 1: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes(pTruth[i] & 0x33333333); return Counter; case 2: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes(pTruth[i] & 0x0F0F0F0F); return Counter; case 3: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes(pTruth[i] & 0x00FF00FF); return Counter; case 4: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes(pTruth[i] & 0x0000FFFF); return Counter; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) Counter += Kit_WordCountOnes(pTruth[i]); pTruth += 2*Step; } return Counter; } } /**Function************************************************************* Synopsis [Computes positive cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) pTruth[i] = pTruth[Step+i]; pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Computes positive cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthCofactor0New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0x55555555) | ((pIn[i] & 0x55555555) << 1); return; case 1: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0x33333333) | ((pIn[i] & 0x33333333) << 2); return; case 2: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0x0F0F0F0F) | ((pIn[i] & 0x0F0F0F0F) << 4); return; case 3: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0x00FF00FF) | ((pIn[i] & 0x00FF00FF) << 8); return; case 4: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i] & 0x0000FFFF) << 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pOut[Step+i] = pIn[i]; pIn += 2*Step; pOut += 2*Step; } return; } } /**Function************************************************************* Synopsis [Computes positive cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthCofactor1New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xAAAAAAAA) | ((pIn[i] & 0xAAAAAAAA) >> 1); return; case 1: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xCCCCCCCC) | ((pIn[i] & 0xCCCCCCCC) >> 2); return; case 2: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xF0F0F0F0) | ((pIn[i] & 0xF0F0F0F0) >> 4); return; case 3: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xFF00FF00) | ((pIn[i] & 0xFF00FF00) >> 8); return; case 4: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pOut[Step+i] = pIn[Step+i]; pIn += 2*Step; pOut += 2*Step; } return; } } /**Function************************************************************* Synopsis [Computes negative cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthVarIsVacuous( unsigned * pOnset, unsigned * pOffset, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) if ( ((pOnset[i] & (pOffset[i] >> 1)) | (pOffset[i] & (pOnset[i] >> 1))) & 0x55555555 ) return 0; return 1; case 1: for ( i = 0; i < nWords; i++ ) if ( ((pOnset[i] & (pOffset[i] >> 2)) | (pOffset[i] & (pOnset[i] >> 2))) & 0x33333333 ) return 0; return 1; case 2: for ( i = 0; i < nWords; i++ ) if ( ((pOnset[i] & (pOffset[i] >> 4)) | (pOffset[i] & (pOnset[i] >> 4))) & 0x0F0F0F0F ) return 0; return 1; case 3: for ( i = 0; i < nWords; i++ ) if ( ((pOnset[i] & (pOffset[i] >> 8)) | (pOffset[i] & (pOnset[i] >> 8))) & 0x00FF00FF ) return 0; return 1; case 4: for ( i = 0; i < nWords; i++ ) if ( ((pOnset[i] & (pOffset[i] >> 16)) | (pOffset[i] & (pOnset[i] >> 16))) & 0x0000FFFF ) return 0; return 1; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) if ( (pOnset[i] & pOffset[Step+i]) | (pOffset[i] & pOnset[Step+i]) ) return 0; pOnset += 2*Step; pOffset += 2*Step; } return 1; } } /**Function************************************************************* Synopsis [Existentially quantifies the variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthExist( unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pTruth[i] |= pTruth[Step+i]; pTruth[Step+i] = pTruth[i]; } pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Existentially quantifies the variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthExistNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] | ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); return; case 1: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] | ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); return; case 2: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] | ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); return; case 3: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] | ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); return; case 4: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] | ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pRes[i] = pTruth[i] | pTruth[Step+i]; pRes[Step+i] = pRes[i]; } pRes += 2*Step; pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Existantially quantifies the set of variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthExistSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ) { int v; Kit_TruthCopy( pRes, pTruth, nVars ); for ( v = 0; v < nVars; v++ ) if ( uMask & (1 << v) ) Kit_TruthExist( pRes, nVars, v ); } /**Function************************************************************* Synopsis [Unversally quantifies the variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthForall( unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pTruth[i] &= pTruth[Step+i]; pTruth[Step+i] = pTruth[i]; } pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Universally quantifies the variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthForallNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] & (((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1)); return; case 1: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] & (((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2)); return; case 2: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] & (((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4)); return; case 3: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] & (((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8)); return; case 4: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] & (((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16)); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pRes[i] = pTruth[i] & pTruth[Step+i]; pRes[Step+i] = pRes[i]; } pRes += 2*Step; pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Universally quantifies the variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthUniqueNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1)); return; case 1: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2)); return; case 2: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4)); return; case 3: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8)); return; case 4: for ( i = 0; i < nWords; i++ ) pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16)); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pRes[i] = pTruth[i] ^ pTruth[Step+i]; pRes[Step+i] = pRes[i]; } pRes += 2*Step; pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Returns the number of minterms in the Boolean difference.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthBooleanDiffCount( unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step, Counter = 0; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 1)) & 0x55555555 ); return Counter; case 1: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 2)) & 0x33333333 ); return Counter; case 2: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 4)) & 0x0F0F0F0F ); return Counter; case 3: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >> 8)) & 0x00FF00FF ); return Counter; case 4: for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes( (pTruth[i] ^ (pTruth[i] >>16)) & 0x0000FFFF ); return Counter; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) Counter += Kit_WordCountOnes( pTruth[i] ^ pTruth[Step+i] ); pTruth += 2*Step; } return Counter; } } /**Function************************************************************* Synopsis [Returns the number of minterms in the Boolean difference.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthXorCount( unsigned * pTruth0, unsigned * pTruth1, int nVars ) { int nWords = Kit_TruthWordNum( nVars ); int i, Counter = 0; for ( i = 0; i < nWords; i++ ) Counter += Kit_WordCountOnes( pTruth0[i] ^ pTruth1[i] ); return Counter; } /**Function************************************************************* Synopsis [Universally quantifies the set of variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthForallSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ) { int v; Kit_TruthCopy( pRes, pTruth, nVars ); for ( v = 0; v < nVars; v++ ) if ( uMask & (1 << v) ) Kit_TruthForall( pRes, nVars, v ); } /**Function************************************************************* Synopsis [Multiplexes two functions with the given variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthMuxVar( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); return; case 1: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); return; case 2: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); return; case 3: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); return; case 4: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pOut[i] = pCof0[i]; pOut[Step+i] = pCof1[Step+i]; } pOut += 2*Step; pCof0 += 2*Step; pCof1 += 2*Step; } return; } } /**Function************************************************************* Synopsis [Multiplexes two functions with the given variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthMuxVarPhase( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar, int fCompl0 ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; if ( fCompl0 == 0 ) { Kit_TruthMuxVar( pOut, pCof0, pCof1, nVars, iVar ); return; } assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pOut[i] = (~pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); return; case 1: for ( i = 0; i < nWords; i++ ) pOut[i] = (~pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); return; case 2: for ( i = 0; i < nWords; i++ ) pOut[i] = (~pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); return; case 3: for ( i = 0; i < nWords; i++ ) pOut[i] = (~pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); return; case 4: for ( i = 0; i < nWords; i++ ) pOut[i] = (~pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pOut[i] = ~pCof0[i]; pOut[Step+i] = pCof1[Step+i]; } pOut += 2*Step; pCof0 += 2*Step; pCof1 += 2*Step; } return; } } /**Function************************************************************* Synopsis [Checks symmetry of two variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ) { static unsigned uTemp0[32], uTemp1[32]; if ( pCof0 == NULL ) { assert( nVars <= 10 ); pCof0 = uTemp0; } if ( pCof1 == NULL ) { assert( nVars <= 10 ); pCof1 = uTemp1; } // compute Cof01 Kit_TruthCopy( pCof0, pTruth, nVars ); Kit_TruthCofactor0( pCof0, nVars, iVar0 ); Kit_TruthCofactor1( pCof0, nVars, iVar1 ); // compute Cof10 Kit_TruthCopy( pCof1, pTruth, nVars ); Kit_TruthCofactor1( pCof1, nVars, iVar0 ); Kit_TruthCofactor0( pCof1, nVars, iVar1 ); // compare return Kit_TruthIsEqual( pCof0, pCof1, nVars ); } /**Function************************************************************* Synopsis [Checks antisymmetry of two variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1, unsigned * pCof0, unsigned * pCof1 ) { static unsigned uTemp0[32], uTemp1[32]; if ( pCof0 == NULL ) { assert( nVars <= 10 ); pCof0 = uTemp0; } if ( pCof1 == NULL ) { assert( nVars <= 10 ); pCof1 = uTemp1; } // compute Cof00 Kit_TruthCopy( pCof0, pTruth, nVars ); Kit_TruthCofactor0( pCof0, nVars, iVar0 ); Kit_TruthCofactor0( pCof0, nVars, iVar1 ); // compute Cof11 Kit_TruthCopy( pCof1, pTruth, nVars ); Kit_TruthCofactor1( pCof1, nVars, iVar0 ); Kit_TruthCofactor1( pCof1, nVars, iVar1 ); // compare return Kit_TruthIsEqual( pCof0, pCof1, nVars ); } /**Function************************************************************* Synopsis [Changes phase of the function w.r.t. one variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Step; unsigned Temp; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { Temp = pTruth[i]; pTruth[i] = pTruth[Step+i]; pTruth[Step+i] = Temp; } pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Computes minimum overlap in supports of cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ) { static unsigned uCofactor[16]; int i, ValueCur, ValueMin, VarMin; unsigned uSupp0, uSupp1; int nVars0, nVars1; assert( nVars <= 9 ); ValueMin = 32; VarMin = -1; for ( i = 0; i < nVars; i++ ) { // get negative cofactor Kit_TruthCopy( uCofactor, pTruth, nVars ); Kit_TruthCofactor0( uCofactor, nVars, i ); uSupp0 = Kit_TruthSupport( uCofactor, nVars ); nVars0 = Kit_WordCountOnes( uSupp0 ); //Kit_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" ); // get positive cofactor Kit_TruthCopy( uCofactor, pTruth, nVars ); Kit_TruthCofactor1( uCofactor, nVars, i ); uSupp1 = Kit_TruthSupport( uCofactor, nVars ); nVars1 = Kit_WordCountOnes( uSupp1 ); //Kit_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" ); // get the number of common vars ValueCur = Kit_WordCountOnes( uSupp0 & uSupp1 ); if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 ) { ValueMin = ValueCur; VarMin = i; } if ( ValueMin == 0 ) break; } if ( pVarMin ) *pVarMin = VarMin; return ValueMin; } /**Function************************************************************* Synopsis [Find the best cofactoring variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ) { int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin; if ( Kit_TruthIsConst0(pTruth, nVars) || Kit_TruthIsConst1(pTruth, nVars) ) return -1; // iterate through variables iBestVar = -1; nSuppSizeMin = KIT_INFINITY; for ( i = 0; i < nVars; i++ ) { // cofactor the functiona and get support sizes Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars ); nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars ); nSuppSizeCur = nSuppSizeCur0 + nSuppSizeCur1; // compare this variable with other variables if ( nSuppSizeMin > nSuppSizeCur ) { nSuppSizeMin = nSuppSizeCur; iBestVar = i; } } assert( iBestVar != -1 ); // cofactor w.r.t. this variable Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar ); Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar ); return iBestVar; } /**Function************************************************************* Synopsis [Counts the number of 1's in each cofactor.] Description [The resulting numbers are stored in the array of ints, whose length is 2*nVars. The number of 1's is counted in a different space than the original function. For example, if the function depends on k variables, the cofactors are assumed to depend on k-1 variables.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, int * pStore ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Counter; memset( pStore, 0, sizeof(int) * 2 * nVars ); if ( nVars <= 5 ) { if ( nVars > 0 ) { pStore[2*0+0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 ); pStore[2*0+1] = Kit_WordCountOnes( pTruth[0] & 0xAAAAAAAA ); } if ( nVars > 1 ) { pStore[2*1+0] = Kit_WordCountOnes( pTruth[0] & 0x33333333 ); pStore[2*1+1] = Kit_WordCountOnes( pTruth[0] & 0xCCCCCCCC ); } if ( nVars > 2 ) { pStore[2*2+0] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); pStore[2*2+1] = Kit_WordCountOnes( pTruth[0] & 0xF0F0F0F0 ); } if ( nVars > 3 ) { pStore[2*3+0] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF ); pStore[2*3+1] = Kit_WordCountOnes( pTruth[0] & 0xFF00FF00 ); } if ( nVars > 4 ) { pStore[2*4+0] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF ); pStore[2*4+1] = Kit_WordCountOnes( pTruth[0] & 0xFFFF0000 ); } return; } // nVars >= 6 // count 1's for all other variables for ( k = 0; k < nWords; k++ ) { Counter = Kit_WordCountOnes( pTruth[k] ); for ( i = 5; i < nVars; i++ ) if ( k & (1 << (i-5)) ) pStore[2*i+1] += Counter; else pStore[2*i+0] += Counter; } // count 1's for the first five variables for ( k = 0; k < nWords/2; k++ ) { pStore[2*0+0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); pStore[2*0+1] += Kit_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) ); pStore[2*1+0] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); pStore[2*1+1] += Kit_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) ); pStore[2*2+0] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); pStore[2*2+1] += Kit_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) ); pStore[2*3+0] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); pStore[2*3+1] += Kit_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) ); pStore[2*4+0] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); pStore[2*4+1] += Kit_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) ); pTruth += 2; } } /**Function************************************************************* Synopsis [Counts the number of 1's in each negative cofactor.] Description [The resulting numbers are stored in the array of ints, whose length is nVars. The number of 1's is counted in a different space than the original function. For example, if the function depends on k variables, the cofactors are assumed to depend on k-1 variables.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthCountOnesInCofs0( unsigned * pTruth, int nVars, int * pStore ) { int nWords = Kit_TruthWordNum( nVars ); int i, k, Counter; memset( pStore, 0, sizeof(int) * nVars ); if ( nVars <= 5 ) { if ( nVars > 0 ) pStore[0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 ); if ( nVars > 1 ) pStore[1] = Kit_WordCountOnes( pTruth[0] & 0x33333333 ); if ( nVars > 2 ) pStore[2] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); if ( nVars > 3 ) pStore[3] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF ); if ( nVars > 4 ) pStore[4] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF ); return; } // nVars >= 6 // count 1's for all other variables for ( k = 0; k < nWords; k++ ) { Counter = Kit_WordCountOnes( pTruth[k] ); for ( i = 5; i < nVars; i++ ) if ( (k & (1 << (i-5))) == 0 ) pStore[i] += Counter; } // count 1's for the first five variables for ( k = 0; k < nWords/2; k++ ) { pStore[0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); pStore[1] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); pStore[2] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); pStore[3] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); pStore[4] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); pTruth += 2; } } /**Function************************************************************* Synopsis [Counts the number of 1's in each cofactor.] Description [Verifies the above procedure.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, int * pStore, unsigned * pAux ) { int i; for ( i = 0; i < nVars; i++ ) { Kit_TruthCofactor0New( pAux, pTruth, nVars, i ); pStore[2*i+0] = Kit_TruthCountOnes( pAux, nVars ) / 2; Kit_TruthCofactor1New( pAux, pTruth, nVars, i ); pStore[2*i+1] = Kit_TruthCountOnes( pAux, nVars ) / 2; } } /**Function************************************************************* Synopsis [Canonicize the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Kit_TruthHash( unsigned * pIn, int nWords ) { // The 1,024 smallest prime numbers used to compute the hash value // http://www.math.utah.edu/~alfeld/math/primelist.html static int HashPrimes[1024] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161 }; int i; unsigned uHashKey; assert( nWords <= 1024 ); uHashKey = 0; for ( i = 0; i < nWords; i++ ) uHashKey ^= HashPrimes[i] * pIn[i]; return uHashKey; } /**Function************************************************************* Synopsis [Canonicize the truth table.] Description [Returns the phase. ] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm ) { int pStore[32]; unsigned * pIn = pInOut, * pOut = pAux, * pTemp; int nWords = Kit_TruthWordNum( nVars ); int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit; unsigned uCanonPhase; // canonicize output uCanonPhase = 0; for ( i = 0; i < nVars; i++ ) pCanonPerm[i] = i; nOnes = Kit_TruthCountOnes(pIn, nVars); //if(pIn[0] & 1) if ( (nOnes > nWords * 16) )//|| ((nOnes == nWords * 16) && (pIn[0] & 1)) ) { uCanonPhase |= (1 << nVars); Kit_TruthNot( pIn, pIn, nVars ); } // collect the minterm counts Kit_TruthCountOnesInCofs( pIn, nVars, pStore ); /* Kit_TruthCountOnesInCofsSlow( pIn, nVars, pStore2, pAux ); for ( i = 0; i < 2*nVars; i++ ) { assert( pStore[i] == pStore2[i] ); } */ // canonicize phase for ( i = 0; i < nVars; i++ ) { if ( pStore[2*i+0] >= pStore[2*i+1] ) continue; uCanonPhase |= (1 << i); Temp = pStore[2*i+0]; pStore[2*i+0] = pStore[2*i+1]; pStore[2*i+1] = Temp; Kit_TruthChangePhase( pIn, nVars, i ); } // Kit_PrintHexadecimal( stdout, pIn, nVars ); // printf( "\n" ); // permute Counter = 0; do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[2*i] >= pStore[2*(i+1)] ) continue; Counter++; fChange = 1; Temp = pCanonPerm[i]; pCanonPerm[i] = pCanonPerm[i+1]; pCanonPerm[i+1] = Temp; Temp = pStore[2*i]; pStore[2*i] = pStore[2*(i+1)]; pStore[2*(i+1)] = Temp; Temp = pStore[2*i+1]; pStore[2*i+1] = pStore[2*(i+1)+1]; pStore[2*(i+1)+1] = Temp; // if the polarity of variables is different, swap them if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) ) { uCanonPhase ^= (1 << i); uCanonPhase ^= (1 << (i+1)); } Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; } } while ( fChange ); /* Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " ); for ( i = 0; i < nVars; i++ ) printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] ); printf( " C = %d\n", Counter ); Extra_PrintHexadecimal( stdout, pIn, nVars ); printf( "\n" ); */ /* // process symmetric variable groups uSymms = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric continue; if ( pStore[2*i] != pStore[2*i+1] ) continue; if ( Kit_TruthVarsSymm( pIn, nVars, i, i+1 ) ) continue; if ( Kit_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) ) Kit_TruthChangePhase( pIn, nVars, i+1 ); } */ /* // process symmetric variable groups uSymms = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric continue; // i and i+1 can be symmetric // find the end of this group for ( k = i+1; k < nVars; k++ ) if ( pStore[2*i] != pStore[2*k] ) break; Limit = k; assert( i < Limit-1 ); // go through the variables in this group for ( j = i + 1; j < Limit; j++ ) { // check symmetry if ( Kit_TruthVarsSymm( pIn, nVars, i, j ) ) { uSymms |= (1 << j); continue; } // they are phase-unknown if ( pStore[2*i] == pStore[2*i+1] ) { if ( Kit_TruthVarsAntiSymm( pIn, nVars, i, j ) ) { Kit_TruthChangePhase( pIn, nVars, j ); uCanonPhase ^= (1 << j); uSymms |= (1 << j); continue; } } // they are not symmetric - move j as far as it goes in the group for ( k = j; k < Limit-1; k++ ) { Counter++; Temp = pCanonPerm[k]; pCanonPerm[k] = pCanonPerm[k+1]; pCanonPerm[k+1] = Temp; assert( pStore[2*k] == pStore[2*(k+1)] ); Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, k ); pTemp = pIn; pIn = pOut; pOut = pTemp; } Limit--; j--; } i = Limit - 1; } */ // swap if it was moved an even number of times if ( Counter & 1 ) Kit_TruthCopy( pOut, pIn, nVars ); return uCanonPhase; } /**Function************************************************************* Synopsis [Fast counting minterms in the cofactors of a function.] Description [Returns the total number of minterms in the function. The resulting array (pRes) contains the number of minterms in 0-cofactor w.r.t. each variables. The additional array (pBytes) is used for internal storage. It should have the size equal to the number of truth table bytes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Kit_TruthCountMinterms( unsigned * pTruth, int nVars, int * pRes, int * pBytesInit ) { // the number of 1s if every byte as well as in the 0-cofactors w.r.t. three variables static unsigned Table[256] = { 0x00000000, 0x01010101, 0x01010001, 0x02020102, 0x01000101, 0x02010202, 0x02010102, 0x03020203, 0x01000001, 0x02010102, 0x02010002, 0x03020103, 0x02000102, 0x03010203, 0x03010103, 0x04020204, 0x00010101, 0x01020202, 0x01020102, 0x02030203, 0x01010202, 0x02020303, 0x02020203, 0x03030304, 0x01010102, 0x02020203, 0x02020103, 0x03030204, 0x02010203, 0x03020304, 0x03020204, 0x04030305, 0x00010001, 0x01020102, 0x01020002, 0x02030103, 0x01010102, 0x02020203, 0x02020103, 0x03030204, 0x01010002, 0x02020103, 0x02020003, 0x03030104, 0x02010103, 0x03020204, 0x03020104, 0x04030205, 0x00020102, 0x01030203, 0x01030103, 0x02040204, 0x01020203, 0x02030304, 0x02030204, 0x03040305, 0x01020103, 0x02030204, 0x02030104, 0x03040205, 0x02020204, 0x03030305, 0x03030205, 0x04040306, 0x00000101, 0x01010202, 0x01010102, 0x02020203, 0x01000202, 0x02010303, 0x02010203, 0x03020304, 0x01000102, 0x02010203, 0x02010103, 0x03020204, 0x02000203, 0x03010304, 0x03010204, 0x04020305, 0x00010202, 0x01020303, 0x01020203, 0x02030304, 0x01010303, 0x02020404, 0x02020304, 0x03030405, 0x01010203, 0x02020304, 0x02020204, 0x03030305, 0x02010304, 0x03020405, 0x03020305, 0x04030406, 0x00010102, 0x01020203, 0x01020103, 0x02030204, 0x01010203, 0x02020304, 0x02020204, 0x03030305, 0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x02010204, 0x03020305, 0x03020205, 0x04030306, 0x00020203, 0x01030304, 0x01030204, 0x02040305, 0x01020304, 0x02030405, 0x02030305, 0x03040406, 0x01020204, 0x02030305, 0x02030205, 0x03040306, 0x02020305, 0x03030406, 0x03030306, 0x04040407, 0x00000001, 0x01010102, 0x01010002, 0x02020103, 0x01000102, 0x02010203, 0x02010103, 0x03020204, 0x01000002, 0x02010103, 0x02010003, 0x03020104, 0x02000103, 0x03010204, 0x03010104, 0x04020205, 0x00010102, 0x01020203, 0x01020103, 0x02030204, 0x01010203, 0x02020304, 0x02020204, 0x03030305, 0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x02010204, 0x03020305, 0x03020205, 0x04030306, 0x00010002, 0x01020103, 0x01020003, 0x02030104, 0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x01010003, 0x02020104, 0x02020004, 0x03030105, 0x02010104, 0x03020205, 0x03020105, 0x04030206, 0x00020103, 0x01030204, 0x01030104, 0x02040205, 0x01020204, 0x02030305, 0x02030205, 0x03040306, 0x01020104, 0x02030205, 0x02030105, 0x03040206, 0x02020205, 0x03030306, 0x03030206, 0x04040307, 0x00000102, 0x01010203, 0x01010103, 0x02020204, 0x01000203, 0x02010304, 0x02010204, 0x03020305, 0x01000103, 0x02010204, 0x02010104, 0x03020205, 0x02000204, 0x03010305, 0x03010205, 0x04020306, 0x00010203, 0x01020304, 0x01020204, 0x02030305, 0x01010304, 0x02020405, 0x02020305, 0x03030406, 0x01010204, 0x02020305, 0x02020205, 0x03030306, 0x02010305, 0x03020406, 0x03020306, 0x04030407, 0x00010103, 0x01020204, 0x01020104, 0x02030205, 0x01010204, 0x02020305, 0x02020205, 0x03030306, 0x01010104, 0x02020205, 0x02020105, 0x03030206, 0x02010205, 0x03020306, 0x03020206, 0x04030307, 0x00020204, 0x01030305, 0x01030205, 0x02040306, 0x01020305, 0x02030406, 0x02030306, 0x03040407, 0x01020205, 0x02030306, 0x02030206, 0x03040307, 0x02020306, 0x03030407, 0x03030307, 0x04040408 }; unsigned uSum; unsigned char * pTruthC, * pLimit; int * pBytes = pBytesInit; int i, iVar, Step, nWords, nBytes, nTotal; assert( nVars <= 20 ); // clear storage memset( pRes, 0, sizeof(int) * nVars ); // count the number of one's in 0-cofactors of the first three variables nTotal = uSum = 0; nWords = Kit_TruthWordNum( nVars ); nBytes = nWords * 4; pTruthC = (unsigned char *)pTruth; pLimit = pTruthC + nBytes; for ( ; pTruthC < pLimit; pTruthC++ ) { uSum += Table[*pTruthC]; *pBytes++ = (Table[*pTruthC] & 0xff); if ( (uSum & 0xff) > 246 ) { nTotal += (uSum & 0xff); pRes[0] += ((uSum >> 8) & 0xff); pRes[2] += ((uSum >> 16) & 0xff); pRes[3] += ((uSum >> 24) & 0xff); uSum = 0; } } if ( uSum ) { nTotal += (uSum & 0xff); pRes[0] += ((uSum >> 8) & 0xff); pRes[1] += ((uSum >> 16) & 0xff); pRes[2] += ((uSum >> 24) & 0xff); } // count all other variables for ( iVar = 3, Step = 1; Step < nBytes; Step *= 2, iVar++ ) for ( i = 0; i < nBytes; i += Step + Step ) { pRes[iVar] += pBytesInit[i]; pBytesInit[i] += pBytesInit[i+Step]; } assert( pBytesInit[0] == nTotal ); assert( iVar == nVars ); for ( i = 0; i < nVars; i++ ) assert( pRes[i] == Kit_TruthCofactor0Count(pTruth, nVars, i) ); return nTotal; } /**Function************************************************************* Synopsis [Prints the hex unsigned into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ) { int nDigits, Digit, k; // write the number into the file nDigits = (1 << nVars) / 4; for ( k = nDigits - 1; k >= 0; k-- ) { Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); if ( Digit < 10 ) fprintf( pFile, "%d", Digit ); else fprintf( pFile, "%c", 'a' + Digit-10 ); } // fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Fast counting minterms for the functions.] Description [Returns 0 if the function is a constant.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthCountMintermsPrecomp() { int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; unsigned i, uWord; for ( i = 0; i < 256; i++ ) { if ( i % 8 == 0 ) printf( "\n" ); uWord = bit_count[i]; uWord |= (bit_count[i & 0x55] << 8); uWord |= (bit_count[i & 0x33] << 16); uWord |= (bit_count[i & 0x0f] << 24); printf( "0x" ); Kit_PrintHexadecimal( stdout, &uWord, 5 ); printf( ", " ); } } /**Function************************************************************* Synopsis [Dumps truth table into a file.] Description [Generates script file for reading into ABC.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Kit_TruthDumpToFile( unsigned * pTruth, int nVars, int nFile ) { static char pFileName[100]; FILE * pFile; sprintf( pFileName, "tt\\s%04d", nFile ); pFile = fopen( pFileName, "w" ); fprintf( pFile, "rt " ); Kit_PrintHexadecimal( pFile, pTruth, nVars ); fprintf( pFile, "; bdd; sop; ps\n" ); fclose( pFile ); return pFileName; } /**Function************************************************************* Synopsis [Dumps truth table into a file.] Description [Generates script file for reading into ABC.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthPrintProfile_int( unsigned * pTruth, int nVars ) { int Mints[20]; int Mints0[20]; int Mints1[20]; int Unique1[20]; int Total2[20][20]; int Unique2[20][20]; int Common2[20][20]; int nWords = Kit_TruthWordNum( nVars ); int * pBytes = ABC_ALLOC( int, nWords * 4 ); unsigned * pIn = ABC_ALLOC( unsigned, nWords ); unsigned * pOut = ABC_ALLOC( unsigned, nWords ); unsigned * pCof00 = ABC_ALLOC( unsigned, nWords ); unsigned * pCof01 = ABC_ALLOC( unsigned, nWords ); unsigned * pCof10 = ABC_ALLOC( unsigned, nWords ); unsigned * pCof11 = ABC_ALLOC( unsigned, nWords ); unsigned * pTemp; int nTotalMints, nTotalMints0, nTotalMints1; int v, u, i, iVar, nMints1; int Cof00, Cof01, Cof10, Cof11; int Coz00, Coz01, Coz10, Coz11; assert( nVars <= 20 ); assert( nVars >= 6 ); nTotalMints = Kit_TruthCountMinterms( pTruth, nVars, Mints, pBytes ); for ( v = 0; v < nVars; v++ ) Unique1[v] = Kit_TruthBooleanDiffCount( pTruth, nVars, v ); for ( v = 0; v < nVars; v++ ) for ( u = 0; u < nVars; u++ ) Total2[v][u] = Unique2[v][u] = Common2[v][u] = -1; nMints1 = (1<<(nVars-2)); for ( v = 0; v < nVars; v++ ) { // move this var to be the first Kit_TruthCopy( pIn, pTruth, nVars ); // Extra_PrintBinary( stdout, pIn, (1<= 0 && Cof00 <= nMints1 ); assert( Cof01 >= 0 && Cof01 <= nMints1 ); assert( Cof10 >= 0 && Cof10 <= nMints1 ); assert( Cof11 >= 0 && Cof11 <= nMints1 ); assert( Coz00 >= 0 && Coz00 <= nMints1 ); assert( Coz01 >= 0 && Coz01 <= nMints1 ); assert( Coz10 >= 0 && Coz10 <= nMints1 ); assert( Coz11 >= 0 && Coz11 <= nMints1 ); Common2[v][iVar] = Common2[iVar][v] = Cof00 * Coz11 + Coz00 * Cof11 + Cof01 * Coz10 + Coz01 * Cof10; Total2[v][iVar] = Total2[iVar][v] = Cof00 * Coz01 + Coz00 * Cof01 + Cof00 * Coz10 + Coz00 * Cof10 + Cof00 * Coz11 + Coz00 * Cof11 + Cof01 * Coz10 + Coz01 * Cof10 + Cof01 * Coz11 + Coz01 * Cof11 + Cof10 * Coz11 + Coz10 * Cof11 ; Kit_TruthCofactor0New( pCof00, pIn, nVars-1, u ); Kit_TruthCofactor1New( pCof01, pIn, nVars-1, u ); Kit_TruthCofactor0New( pCof10, pIn+nWords/2, nVars-1, u ); Kit_TruthCofactor1New( pCof11, pIn+nWords/2, nVars-1, u ); Unique2[v][iVar] = Unique2[iVar][v] = Kit_TruthXorCount( pCof00, pCof01, nVars-1 ) + Kit_TruthXorCount( pCof00, pCof10, nVars-1 ) + Kit_TruthXorCount( pCof00, pCof11, nVars-1 ) + Kit_TruthXorCount( pCof01, pCof10, nVars-1 ) + Kit_TruthXorCount( pCof01, pCof11, nVars-1 ) + Kit_TruthXorCount( pCof10, pCof11, nVars-1 ); } } printf( "\n" ); printf( " V: " ); for ( v = 0; v < nVars; v++ ) printf( "%8c ", v+'a' ); printf( "\n" ); printf( " M: " ); for ( v = 0; v < nVars; v++ ) printf( "%8d ", Mints[v] ); printf( "\n" ); printf( " U: " ); for ( v = 0; v < nVars; v++ ) printf( "%8d ", Unique1[v] ); printf( "\n" ); printf( "\n" ); printf( "Unique:\n" ); for ( i = 0; i < nVars; i++ ) { printf( " %2d ", i ); for ( v = 0; v < nVars; v++ ) printf( "%8d ", Unique2[i][v] ); printf( "\n" ); } printf( "Common:\n" ); for ( i = 0; i < nVars; i++ ) { printf( " %2d ", i ); for ( v = 0; v < nVars; v++ ) printf( "%8d ", Common2[i][v] ); printf( "\n" ); } printf( "Total:\n" ); for ( i = 0; i < nVars; i++ ) { printf( " %2d ", i ); for ( v = 0; v < nVars; v++ ) printf( "%8d ", Total2[i][v] ); printf( "\n" ); } ABC_FREE( pIn ); ABC_FREE( pOut ); ABC_FREE( pCof00 ); ABC_FREE( pCof01 ); ABC_FREE( pCof10 ); ABC_FREE( pCof11 ); ABC_FREE( pBytes ); } /**Function************************************************************* Synopsis [Dumps truth table into a file.] Description [Generates script file for reading into ABC.] SideEffects [] SeeAlso [] ***********************************************************************/ void Kit_TruthPrintProfile( unsigned * pTruth, int nVars ) { unsigned uTruth[2]; if ( nVars >= 6 ) { Kit_TruthPrintProfile_int( pTruth, nVars ); return; } assert( nVars >= 2 ); uTruth[0] = pTruth[0]; uTruth[1] = pTruth[0]; Kit_TruthPrintProfile( uTruth, 6 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/kit_.c000066400000000000000000000026341300674244400226550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kit_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Computation kit.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 6, 2006.] Revision [$Id: kit_.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] ***********************************************************************/ #include "kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/kit/module.make000066400000000000000000000005021300674244400236770ustar00rootroot00000000000000SRC += src/bool/kit/kitAig.c \ src/bool/kit/kitBdd.c \ src/bool/kit/kitCloud.c src/bool/kit/cloud.c \ src/bool/kit/kitDsd.c \ src/bool/kit/kitFactor.c \ src/bool/kit/kitGraph.c \ src/bool/kit/kitHop.c \ src/bool/kit/kitIsop.c \ src/bool/kit/kitPla.c \ src/bool/kit/kitSop.c \ src/bool/kit/kitTruth.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/000077500000000000000000000000001300674244400221165ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/lucky.c000066400000000000000000000544071300674244400234230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lucky.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Semi-canonical form computation package.] Synopsis [Truth table minimization procedures.] Author [Jake] Date [Started - August 2012] ***********************************************************************/ #include "luckyInt.h" ABC_NAMESPACE_IMPL_START int memCompare(word* x, word* y, int nVars) { int i; for(i=Kit_TruthWordNum_64bit( nVars )-1;i>=0;i--) { if(x[i]==y[i]) continue; else if(x[i]>y[i]) return 1; else return -1; } return 0; } ///////sort Word* a/////////////////////////////////////////////////////////////////////////////////////////////////////// int compareWords1 (const void * a, const void * b) { if( *(word*)a > *(word*)b ) return 1; else return( *(word*)a < *(word*)b ) ? -1: 0; } void sortAndUnique1(word* a, Abc_TtStore_t* p) { int i, count=1, WordsN = p->nFuncs; word tempWord; qsort(a,WordsN,sizeof(word),compareWords1); tempWord = a[0]; for(i=1;inFuncs = count; } //////////sort Word** a////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int compareWords2 (const void ** x, const void ** y) { if(**(word**)x > **(word**)y) return 1; else if(**(word**)x < **(word**)y) return -1; else return 0; } int compareWords (const void ** a, const void ** b) { if( memcmp(*(word**)a,*(word**)b,sizeof(word)*1) > 0 ) return 1; else return ( memcmp(*(word**)a,*(word**)b,sizeof(word)*1) < 0 ) ? -1: 0; } int compareWords3 (const void ** x, const void ** y) { return memCompare(*(word**)x, *(word**)y, 16); } void sortAndUnique(word** a, Abc_TtStore_t* p) { int i, count=1, WordsPtrN = p->nFuncs; word* tempWordPtr; qsort(a,WordsPtrN,sizeof(word*),(int(*)(const void *,const void *))compareWords3); tempWordPtr = a[0]; for(i=1;inWords)) != 0) { a[count] = a[i]; tempWordPtr = a[i]; count++; } p->nFuncs = count; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// typedef struct { int totalCycles; int maxNCycles; int minNCycles; }cycleCtr; cycleCtr* setCycleCtrPtr() { cycleCtr* x = (cycleCtr*) malloc(sizeof(cycleCtr)); x->totalCycles=0; x->maxNCycles=0; x->minNCycles=111111111; return x; } void freeCycleCtr(cycleCtr* x) { free(x); } word** makeArray(Abc_TtStore_t* p) { int i; word** a; a = (word**)malloc(sizeof(word*)*(p->nFuncs)); for(i=0;inFuncs;i++) { a[i] = (word*)malloc(sizeof(word)*(p->nWords)); memcpy(a[i],p->pFuncs[i],sizeof(word)*(p->nWords)); } return a; } void freeArray(word** a,Abc_TtStore_t* p) { int i; for(i=0;inFuncs;i++) free(a[i]); free(a); } word* makeArrayB(word** a, int nFuncs) { int i; word* b; b = (word*)malloc(sizeof(word)*(nFuncs)); for(i=0;i inverse // if pInOnt changed(minimized) by function return 1 if not 0 // int minimalInitialFlip_propper(word* pInOut, word* pDuplicat, int nVars) // { // word oneWord=1; // Kit_TruthCopy_64bit( pDuplicat, pInOut, nVars ); // Kit_TruthNot_64bit( pDuplicat, nVars ); // if( memCompare(pDuplicat,pInOut,nVars) == -1) // { // Kit_TruthCopy_64bit(pInOut, pDuplicat, nVars ); // return 1; // } // return 0; // } // int minimalFlip(word* pInOut, word* pMinimal, word* PDuplicat, int nVars) // { // int i; // int blockSize = Kit_TruthWordNum_64bit( nVars )*sizeof(word); // memcpy(pMinimal, pInOut, blockSize); // memcpy(PDuplicat, pInOut, blockSize); // for(i=0;i0 ) // && cycles < 10 if we wanna limit cycles // { // counter=0; // counter += minimalInitialFlip(pInOut, nVars); // counter += minimalFlip(pInOut, pAux, pAux1, nVars); // counter += minimalSwap(pInOut, pAux, pAux1, nVars); // cCtr->totalCycles++; // cycles++; // } // if(cycles < cCtr->minNCycles) // cCtr->minNCycles = cycles; // else if(cycles > cCtr->maxNCycles) // cCtr->maxNCycles = cycles; // } // runs paralel F and ~F in luckyCanonicizer // void luckyCanonicizer2(word* pInOut, word* pAux, word* pAux1, word* temp, int nVars) // { // int nWords = Kit_TruthWordNum_64bit( nVars ); // int counter=1, nOnes; // assert( nVars <= 16 ); // nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars); // // if ( (nOnes*2 == nWords * 32) ) // { // Kit_TruthCopy_64bit( temp, pInOut, nVars ); // Kit_TruthNot_64bit( temp, nVars ); // luckyCanonicizer1_simple(pInOut, pAux, pAux1, nVars); // luckyCanonicizer1_simple(temp, pAux, pAux1, nVars); // if( memCompare(temp,pInOut,nVars) == -1) // Kit_TruthCopy_64bit(pInOut, temp, nVars ); // return; // } // while(counter>0 ) // && cycles < 10 if we wanna limit cycles // { // counter=0; // counter += minimalInitialFlip_propper(pInOut, pAux, nVars); // counter += minimalFlip1(pInOut, pAux, pAux1, nVars); // counter += minimalSwap1(pInOut, pAux, pAux1, nVars); // } // } // same as luckyCanonicizer + cycleCtr stutistics // void luckyCanonicizer1(word* pInOut, word* pAux, word* pAux1, int nVars, cycleCtr* cCtr) // { // int counter=1, cycles=0; // assert( nVars <= 16 ); // while(counter>0 ) // && cycles < 10 if we wanna limit cycles // { // counter=0; // counter += minimalInitialFlip1(pInOut, nVars); // counter += minimalFlip1(pInOut, pAux, pAux1, nVars); // counter += minimalSwap1(pInOut, pAux, pAux1, nVars); // cCtr->totalCycles++; // cycles++; // } // if(cycles < cCtr->minNCycles) // cCtr->minNCycles = cycles; // else if(cycles > cCtr->maxNCycles) // cCtr->maxNCycles = cycles; // } // luckyCanonicizer void printCCtrInfo(cycleCtr* cCtr, int nFuncs) { printf("maxNCycles = %d\n",cCtr->maxNCycles); printf("minNCycles = %d\n",cCtr->minNCycles); printf("average NCycles = %.3f\n",cCtr->totalCycles/(double)nFuncs); } ////////////////////////////////////////New Faster versoin///////////////////////////////////////////////////////// // if highest bit in F ( all ones min term ) is one => inverse // returns: if pInOnt changed(minimized) by function return 1 if not 0 int minimalInitialFlip1(word* pInOut, int nVars) { word oneWord=1; if( (pInOut[Kit_TruthWordNum_64bit( nVars ) -1]>>63) & oneWord ) { Kit_TruthNot_64bit( pInOut, nVars ); return 1; } return 0; } // compare F with F1 = (F with changed phase in one of the vars). // keeps smaller. // same for all vars in F. // returns: if pInOnt changed(minimized) by function return 1 if not 0 int minimalFlip1(word* pInOut, word* pMinimal, word* PDuplicat, int nVars) { int i; int blockSize = Kit_TruthWordNum_64bit( nVars )*sizeof(word); memcpy(pMinimal, pInOut, blockSize); memcpy(PDuplicat, pInOut, blockSize); Kit_TruthChangePhase_64bit( pInOut, nVars, 0 ); for(i=1;i inverse // returns: if pInOnt changed(minimized) by function return 1 if not 0 int minimalInitialFlip(word* pInOut, int nVars, unsigned* p_uCanonPhase) { word oneWord=1; if( (pInOut[Kit_TruthWordNum_64bit( nVars ) -1]>>63) & oneWord ) { Kit_TruthNot_64bit( pInOut, nVars ); *p_uCanonPhase ^= (1 << nVars); return 1; } return 0; } // compare F with F1 = (F with changed phase in one of the vars). // keeps smaller. // same for all vars in F. // returns: if pInOnt changed(minimized) by function return 1 if not 0 int minimalFlip(word* pInOut, word* pMinimal, word* PDuplicat, int nVars, unsigned* p_uCanonPhase) { int i; unsigned minTemp = *p_uCanonPhase; int blockSize = Kit_TruthWordNum_64bit( nVars )*sizeof(word); memcpy(pMinimal, pInOut, blockSize); memcpy(PDuplicat, pInOut, blockSize); //////////////need one more unsigned!!!!!!!!!!!!! Kit_TruthChangePhase_64bit( pInOut, nVars, 0 ); *p_uCanonPhase ^= (unsigned)1; for(i=1;i 0) != ((*p_uCanonPhase & (1 << (iVar+1))) > 0) ) { *p_uCanonPhase ^= (1 << iVar); *p_uCanonPhase ^= (1 << (iVar+1)); } } // compare F with F1 = (F with swapped two adjacent vars). // keeps smaller. // same for all vars in F. // returns: if pInOnt changed(minimized) by function return 1 if not 0 /* // this version is buggy and is fixed below int minimalSwap(word* pInOut, word* pMinimal, word* PDuplicat, int nVars, char * pCanonPerm, char * tempArray, unsigned* p_uCanonPhase) { int i; int blockSizeWord = Kit_TruthWordNum_64bit( nVars )*sizeof(word); int blockSizeChar = nVars *sizeof(char); memcpy(pMinimal, pInOut, blockSizeWord); memcpy(PDuplicat, pInOut, blockSizeWord); memcpy(tempArray, pCanonPerm, blockSizeChar); Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, 0 ); swapInfoAdjacentVars(0, pCanonPerm, p_uCanonPhase); for(i=1;i 0) != ((*pUCanonPhase & (1 << jVar)) > 0) ) { *pUCanonPhase ^= (1 << iVarInPosition); *pUCanonPhase ^= (1 << jVar); } if(*pUCanonPhase>>iVarInPosition & (unsigned)1 == 1) Kit_TruthChangePhase_64bit( pAfter, nVars, iVarInPosition ); } int luckyCheck(word* pAfter, word* pBefore, int nVars, char * pCanonPerm, unsigned uCanonPhase) { int i,j; char tempChar; for(j=0;j>nVars & (unsigned)1 == 1) Kit_TruthNot_64bit(pAfter, nVars ); if(memcmp(pAfter, pBefore, Kit_TruthWordNum_64bit( nVars )*sizeof(word)) == 0) return 0; else return 1; } */ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void luckyCanonicizer(word* pInOut, word* pAux, word* pAux1, int nVars, char * pCanonPerm, char * tempArray, unsigned* p_uCanonPhase) { int counter=1; assert( nVars <= 16 ); while(counter>0 ) // && cycles < 10 if we wanna limit cycles { counter=0; counter += minimalInitialFlip(pInOut, nVars, p_uCanonPhase); counter += minimalFlip(pInOut, pAux, pAux1, nVars, p_uCanonPhase); counter += minimalSwap(pInOut, pAux, pAux1, nVars, pCanonPerm, tempArray, p_uCanonPhase); } } // tries to find minimal F till F at the beginning of the loop is the same as at the end - irreducible unsigned luckyCanonicizer1_simple(word* pInOut, word* pAux, word* pAux1, int nVars, char * pCanonPerm, unsigned CanonPhase) { int counter=1; assert( nVars <= 16 ); while(counter>0 ) // && cycles < 10 if we wanna limit cycles { counter=0; counter += minimalInitialFlip1(pInOut, nVars); counter += minimalFlip1(pInOut, pAux, pAux1, nVars); counter += minimalSwap1(pInOut, pAux, pAux1, nVars); } return CanonPhase; } void luckyCanonicizer_final(word* pInOut, word* pAux, word* pAux1, int nVars) { Kit_TruthSemiCanonicize_Yasha_simple( pInOut, nVars, NULL ); luckyCanonicizer1_simple(pInOut, pAux, pAux1, nVars, NULL, 0); } // this procedure calls internal canoniziers // it returns canonical phase (as return value) and canonical permutation (in pCanonPerm) unsigned Kit_TruthSemiCanonicize_new_internal( word * pInOut, int nVars, char * pCanonPerm ) { word pAux[1024], pAux1[1024]; char tempArray[16]; unsigned CanonPhase; assert( nVars <= 16 ); CanonPhase = Kit_TruthSemiCanonicize_Yasha( pInOut, nVars, pCanonPerm ); luckyCanonicizer(pInOut, pAux, pAux1, nVars, pCanonPerm, tempArray, &CanonPhase); return CanonPhase; } // this procedure is translates truth table from 'unsingeds' into 'words' unsigned Kit_TruthSemiCanonicize_new( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm ) { unsigned Result; if ( nVars < 6 ) { word Temp = ((word)pInOut[0] << 32) | (word)pInOut[0]; Result = Kit_TruthSemiCanonicize_new_internal( &Temp, nVars, pCanonPerm ); pInOut[0] = (unsigned)Temp; } else Result = Kit_TruthSemiCanonicize_new_internal( (word *)pInOut, nVars, pCanonPerm ); return Result; } // compile main() procedure only if running outside of ABC environment #ifndef _RUNNING_ABC_ int main () { // char * pFileInput = "nonDSDfunc06var1M.txt"; // char * pFileInput1 = "partDSDfunc06var1M.txt"; // char * pFileInput2 = "fullDSDfunc06var1M.txt"; // char * pFileInput = "nonDSDfunc10var100K.txt"; // char * pFileInput1 = "partDSDfunc10var100K.txt"; // char * pFileInput2 = "fullDSDfunc10var100K.txt"; // char * pFileInput = "partDSDfunc12var100K.txt"; // char * pFileInput = "nonDSDfunc12var100K.txt"; // char * pFileInput1 = "partDSDfunc12var100K.txt"; // char * pFileInput2 = "fullDSDfunc12var100K.txt"; // char * pFileInput = "nonDSDfunc14var10K.txt"; // char * pFileInput1 = "partDSDfunc14var10K.txt"; // char * pFileInput2 = "fullDSDfunc14var10K.txt"; char * pFileInput = "nonDSDfunc16var10K.txt"; char * pFileInput1 = "partDSDfunc16var10K.txt"; char * pFileInput2 = "fullDSDfunc16var10K.txt"; int i, j, tempNF; char** charArray; word** a, ** b; Abc_TtStore_t* p; word * pAux, * pAux1; int * pStore; // cycleCtr* cCtr; charArray = (char**)malloc(sizeof(char*)*3); charArray[0] = pFileInput; charArray[1] = pFileInput1; charArray[2] = pFileInput2; for(j=0;j<3;j++) { p = setTtStore(charArray[j]); // p = setTtStore(pFileInput); a = makeArray(p); b = makeArray(p); // cCtr = setCycleCtrPtr(); pAux = (word*)malloc(sizeof(word)*(p->nWords)); pAux1 = (word*)malloc(sizeof(word)*(p->nWords)); pStore = (int*)malloc(sizeof(int)*(p->nVars)); printf("In %s Fs at start = %d\n",charArray[j],p->nFuncs); tempNF = p->nFuncs; TimePrint("start"); for(i=0;inFuncs;i++) luckyCanonicizer_final(a[i], pAux, pAux1, p->nVars, pStore); TimePrint("done with A"); sortAndUnique(a, p); printf("F left in A final = %d\n",p->nFuncs); freeArray(a,p); TimePrint("Done with sort"); // delete data-structures free(pAux); free(pAux1); free(pStore); // freeCycleCtr(cCtr); Abc_TruthStoreFree( p ); } return 0; } #endif ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/lucky.h000066400000000000000000000023661300674244400234250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lucky.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Semi-canonical form computation package.] Synopsis [External declarations.] Author [Jake] Date [Started - August 2012] ***********************************************************************/ #ifndef ABC__bool__lucky__LUCKY_H_ #define ABC__bool__lucky__LUCKY_H_ ABC_NAMESPACE_HEADER_START typedef struct { int varN; int* swapArray; int swapCtr; int totalSwaps; int* flipArray; int flipCtr; int totalFlips; }permInfo; extern unsigned Kit_TruthSemiCanonicize_new( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm ); extern unsigned luckyCanonicizer_final_fast( word * pInOut, int nVars, char * pCanonPerm ); extern unsigned luckyCanonicizer_final_fast1( word * pInOut, int nVars, char * pCanonPerm ); extern void resetPCanonPermArray(char* x, int nVars); extern permInfo* setPermInfoPtr(int var); extern void freePermInfoPtr(permInfo* x); extern void simpleMinimal(word* x, word* pAux,word* minimal, permInfo* pi, int nVars); ABC_NAMESPACE_HEADER_END #endif /* LUCKY_H_ */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/luckyFast16.c000066400000000000000000001013761300674244400244060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [luckyFast16.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Semi-canonical form computation package.] Synopsis [Truth table minimization procedures for up to 16 vars.] Author [Jake] Date [Started - September 2012] ***********************************************************************/ #include "luckyInt.h" //#define LUCKY_VERIFY ABC_NAMESPACE_IMPL_START static word SFmask[5][4] = { {ABC_CONST(0x8888888888888888),ABC_CONST(0x4444444444444444),ABC_CONST(0x2222222222222222),ABC_CONST(0x1111111111111111)}, {ABC_CONST(0xC0C0C0C0C0C0C0C0),ABC_CONST(0x3030303030303030),ABC_CONST(0x0C0C0C0C0C0C0C0C),ABC_CONST(0x0303030303030303)}, {ABC_CONST(0xF000F000F000F000),ABC_CONST(0x0F000F000F000F00),ABC_CONST(0x00F000F000F000F0),ABC_CONST(0x000F000F000F000F)}, {ABC_CONST(0xFF000000FF000000),ABC_CONST(0x00FF000000FF0000),ABC_CONST(0x0000FF000000FF00),ABC_CONST(0x000000FF000000FF)}, {ABC_CONST(0xFFFF000000000000),ABC_CONST(0x0000FFFF00000000),ABC_CONST(0x00000000FFFF0000),ABC_CONST(0x000000000000FFFF)} }; // we need next two functions only for verification of lucky method in debugging mode void swapAndFlip(word* pAfter, int nVars, int iVarInPosition, int jVar, char * pCanonPerm, unsigned* pUCanonPhase) { int Temp; swap_ij(pAfter, nVars, iVarInPosition, jVar); Temp = pCanonPerm[iVarInPosition]; pCanonPerm[iVarInPosition] = pCanonPerm[jVar]; pCanonPerm[jVar] = Temp; if ( ((*pUCanonPhase & (1 << iVarInPosition)) > 0) != ((*pUCanonPhase & (1 << jVar)) > 0) ) { *pUCanonPhase ^= (1 << iVarInPosition); *pUCanonPhase ^= (1 << jVar); } if((*pUCanonPhase>>iVarInPosition) & 1) Kit_TruthChangePhase_64bit( pAfter, nVars, iVarInPosition ); } int luckyCheck(word* pAfter, word* pBefore, int nVars, char * pCanonPerm, unsigned uCanonPhase) { int i,j; char tempChar; for(j=0;j>nVars) & 1) Kit_TruthNot_64bit(pAfter, nVars ); if(memcmp(pAfter, pBefore, Kit_TruthWordNum_64bit( nVars )*sizeof(word)) == 0) return 0; else return 1; } ////////////////////////////////////lessThen5///////////////////////////////////////////////////////////////////////////////////////////// // there are 4 parts in every block to compare and rearrange - quoters(0Q,1Q,2Q,3Q) //updataInfo updates CanonPerm and CanonPhase based on what quoter in position iQ and jQ void updataInfo(int iQ, int jQ, int iVar, char * pCanonPerm, unsigned* pCanonPhase) { *pCanonPhase = adjustInfoAfterSwap(pCanonPerm, *pCanonPhase, iVar, ((abs(iQ-jQ)-1)<<2) + iQ ); } // returns the first shift from the left in word x that has One bit in it. // blockSize = ShiftSize/4 int firstShiftWithOneBit(word x, int blockSize) { int n = 0; if(blockSize == 16){ return 0;} if (x >= ABC_CONST(0x0000000100000000)) {n = n + 32; x = x >> 32;} if(blockSize == 8){ return (64-n)/32;} if (x >= ABC_CONST(0x0000000000010000)) {n = n + 16; x = x >> 16;} if(blockSize == 4){ return (64-n)/16;} if (x >= ABC_CONST(0x0000000000000100)) {n = n + 8; x = x >> 8;} if(blockSize == 2){ return (64-n)/8;} if (x >= ABC_CONST(0x0000000000000010)) {n = n + 4; x = x >> 4;} return (64-n)/4; } // It rearranges InOut (swaps and flips through rearrangement of quoters) // It updates Info at the end void arrangeQuoters_superFast_lessThen5(word* pInOut, int start, int iQ, int jQ, int kQ, int lQ, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) { int i, blockSize = 1<=0;i--) { assert( iQ*blockSize < 64 ); assert( jQ*blockSize < 64 ); assert( kQ*blockSize < 64 ); assert( lQ*blockSize < 64 ); assert( 3*blockSize < 64 ); pInOut[i] = (pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize) | (((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize))>>blockSize) | (((pInOut[i] & SFmask[iVar][kQ])<<(kQ*blockSize))>>2*blockSize) | (((pInOut[i] & SFmask[iVar][lQ])<<(lQ*blockSize))>>3*blockSize); } updataInfo(iQ, jQ, iVar, pCanonPerm, pCanonPhase); // printf("out arrangeQuoters_superFast_lessThen5\n"); } // static word SFmask[5][4] = { // {0x8888888888888888,0x4444444444444444,0x2222222222222222,0x1111111111111111}, // {0xC0C0C0C0C0C0C0C0,0x3030303030303030,0x0C0C0C0C0C0C0C0C,0x0303030303030303}, // {0xF000F000F000F000,0x0F000F000F000F00,0x00F000F000F000F0,0x000F000F000F000F}, // {0xFF000000FF000000,0x00FF000000FF0000,0x0000FF000000FF00,0x000000FF000000FF}, // {0xFFFF000000000000,0x0000FFFF00000000,0x00000000FFFF0000,0x000000000000FFFF} // }; //It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa // DifStart contains the information about the first different bit in 0Q and 3Q int minTemp0_fast(word* pInOut, int iVar, int nWords, int* pDifStart) { int i, blockSize = 1<=0; i--) { assert( 3*blockSize < 64 ); temp = ((pInOut[i] & SFmask[iVar][0])) ^ ((pInOut[i] & SFmask[iVar][3])<<(3*blockSize)); if( temp == 0) continue; else { *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize); if( ((pInOut[i] & SFmask[iVar][0])) < ((pInOut[i] & SFmask[iVar][3])<<(3*blockSize)) ) return 0; else return 3; } } *pDifStart=0; return 0; } //It compares 1Q and 2Q and returns 1 if 1Q is smaller then 2Q ( comparison starts at highest bit) and visa versa // DifStart contains the information about the first different bit in 1Q and 2Q int minTemp1_fast(word* pInOut, int iVar, int nWords, int* pDifStart) { int i, blockSize = 1<=0; i--) { assert( 2*blockSize < 64 ); temp = ((pInOut[i] & SFmask[iVar][1])<<(blockSize)) ^ ((pInOut[i] & SFmask[iVar][2])<<(2*blockSize)); if( temp == 0) continue; else { *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize); if( ((pInOut[i] & SFmask[iVar][1])<<(blockSize)) < ((pInOut[i] & SFmask[iVar][2])<<(2*blockSize)) ) return 1; else return 2; } } *pDifStart=0; return 1; } //It compares iQ and jQ and returns 0 if iQ is smaller then jQ ( comparison starts at highest bit) and 1 if jQ is // DifStart contains the information about the first different bit in iQ and jQ int minTemp2_fast(word* pInOut, int iVar, int iQ, int jQ, int nWords, int* pDifStart) { int i, blockSize = 1<=0; i--) { assert( jQ*blockSize < 64 ); temp = ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) ^ ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)); if( temp == 0) continue; else { *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize); if( ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) <= ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)) ) return 0; else return 1; } } *pDifStart=0; return 0; } // same as minTemp2_fast but this one has a start position int minTemp3_fast(word* pInOut, int iVar, int start, int finish, int iQ, int jQ, int* pDifStart) { int i, blockSize = 1<=finish; i--) { assert( jQ*blockSize < 64 ); temp = ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) ^ ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)); if( temp == 0) continue; else { *pDifStart = i*100 + 20 - firstShiftWithOneBit(temp, blockSize); if( ((pInOut[i] & SFmask[iVar][iQ])<<(iQ*blockSize)) <= ((pInOut[i] & SFmask[iVar][jQ])<<(jQ*blockSize)) ) return 0; else return 1; } } *pDifStart=0; return 0; } // It considers all swap and flip possibilities of iVar and iVar+1 and switches InOut to a minimal of them void minimalSwapAndFlipIVar_superFast_lessThen5(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) { int min1, min2, DifStart0, DifStart1, DifStartMin, DifStart4=0; int M[2]; M[0] = minTemp0_fast(pInOut, iVar, nWords, &DifStart0); // 0, 3 M[1] = minTemp1_fast(pInOut, iVar, nWords, &DifStart1); // 1, 2 min1 = minTemp2_fast(pInOut, iVar, M[0], M[1], nWords, &DifStartMin); // printf("\nDifStart0 = %d, DifStart1 = %d, DifStartMin = %d\n",DifStart0, DifStart1, DifStartMin); // printf("M[0] = %d, M[1] = %d, min1 = %d\n", M[0], M[1], min1); if(DifStart0 != DifStart1) { // printf("if\n"); if( DifStartMin>=DifStart1 && DifStartMin>=DifStart0 ) arrangeQuoters_superFast_lessThen5(pInOut, DifStartMin/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase); else if( DifStart0 > DifStart1) arrangeQuoters_superFast_lessThen5(pInOut,luckyMax(DifStartMin/100, DifStart0/100), M[0], M[1], 3 - M[1], 3 - M[0], iVar, nWords, pCanonPerm, pCanonPhase); else arrangeQuoters_superFast_lessThen5(pInOut,luckyMax(DifStartMin/100, DifStart1/100), M[1], M[0], 3 - M[0], 3 - M[1], iVar, nWords, pCanonPerm, pCanonPhase); } else { // printf("else\n"); if(DifStartMin>=DifStart0) arrangeQuoters_superFast_lessThen5(pInOut, DifStartMin/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase); else { min2 = minTemp3_fast(pInOut, iVar, DifStart0/100, DifStartMin/100, 3-M[0], 3-M[1], &DifStart4); // no reuse DifStart1 because DifStart1 = DifStart1=0 // printf("after minTemp3_fast min2 = %d, DifStart4 = %d\n", min2, DifStart4); if(DifStart4>DifStartMin) arrangeQuoters_superFast_lessThen5(pInOut, DifStart0/100, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], iVar, nWords, pCanonPerm, pCanonPhase); else arrangeQuoters_superFast_lessThen5(pInOut, DifStart0/100, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, nWords, pCanonPerm, pCanonPhase); } } } void minimalSwapAndFlipIVar_superFast_lessThen5_noEBFC(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) { int DifStart1; if(minTemp1_fast(pInOut, iVar, nWords, &DifStart1) == 2) arrangeQuoters_superFast_lessThen5(pInOut, DifStart1/100, 0, 2, 1, 3, iVar, nWords, pCanonPerm, pCanonPhase); } ////////////////////////////////////iVar = 5///////////////////////////////////////////////////////////////////////////////////////////// // It rearranges InOut (swaps and flips through rearrangement of quoters) // It updates Info at the end void arrangeQuoters_superFast_iVar5(unsigned* pInOut, unsigned* temp, int start, int iQ, int jQ, int kQ, int lQ, char * pCanonPerm, unsigned* pCanonPhase) { int i,blockSize,shiftSize; unsigned* tempPtr = temp+start; // printf("in arrangeQuoters_superFast_iVar5\n"); if(iQ == 0 && jQ == 1) return; blockSize = sizeof(unsigned); shiftSize = 4; for(i=start-1;i>0;i-=shiftSize) { tempPtr -= 1; memcpy(tempPtr, pInOut+i-iQ, blockSize); tempPtr -= 1; memcpy(tempPtr, pInOut+i-jQ, blockSize); tempPtr -= 1; memcpy(tempPtr, pInOut+i-kQ, blockSize); tempPtr -= 1; memcpy(tempPtr, pInOut+i-lQ, blockSize); } memcpy(pInOut, temp, start*sizeof(unsigned)); updataInfo(iQ, jQ, 5, pCanonPerm, pCanonPhase); } //It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa // DifStart contains the information about the first different bit in 0Q and 3Q int minTemp0_fast_iVar5(unsigned* pInOut, int nWords, int* pDifStart) { int i, temp; // printf("in minTemp0_fast_iVar5\n"); for(i=(nWords)*2 - 1; i>=0; i-=4) { temp = CompareWords(pInOut[i],pInOut[i-3]); if(temp == 0) continue; else if(temp == -1) { *pDifStart = i+1; return 0; } else { *pDifStart = i+1; return 3; } } *pDifStart=0; return 0; } //It compares 1Q and 2Q and returns 1 if 1Q is smaller then 2Q ( comparison starts at highest bit) and visa versa // DifStart contains the information about the first different bit in 1Q and 2Q int minTemp1_fast_iVar5(unsigned* pInOut, int nWords, int* pDifStart) { int i, temp; // printf("in minTemp1_fast_iVar5\n"); for(i=(nWords)*2 - 2; i>=0; i-=4) { temp = CompareWords(pInOut[i],pInOut[i-1]); if(temp == 0) continue; else if(temp == -1) { *pDifStart = i+2; return 1; } else { *pDifStart = i+2; return 2; } } *pDifStart=0; return 1; } //It compares iQ and jQ and returns 0 if iQ is smaller then jQ ( comparison starts at highest bit) and visa versa // DifStart contains the information about the first different bit in iQ and jQ int minTemp2_fast_iVar5(unsigned* pInOut, int iQ, int jQ, int nWords, int* pDifStart) { int i, temp; // printf("in minTemp2_fast_iVar5\n"); for(i=(nWords)*2 - 1; i>=0; i-=4) { temp = CompareWords(pInOut[i-iQ],pInOut[i-jQ]); if(temp == 0) continue; else if(temp == -1) { *pDifStart = i+1; return 0; } else { *pDifStart = i+1; return 1; } } *pDifStart=0; return 0; } // same as minTemp2_fast but this one has a start position int minTemp3_fast_iVar5(unsigned* pInOut, int start, int finish, int iQ, int jQ, int* pDifStart) { int i, temp; // printf("in minTemp3_fast_iVar5\n"); for(i=start-1; i>=finish; i-=4) { temp = CompareWords(pInOut[i-iQ],pInOut[i-jQ]); if(temp == 0) continue; else if(temp == -1) { *pDifStart = i+1; return 0; } else { *pDifStart = i+1; return 1; } } *pDifStart=0; return 0; } // It considers all swap and flip possibilities of iVar and iVar+1 and switches InOut to a minimal of them void minimalSwapAndFlipIVar_superFast_iVar5(unsigned* pInOut, int nWords, char * pCanonPerm, unsigned* pCanonPhase) { int min1, min2, DifStart0, DifStart1, DifStartMin; int M[2]; unsigned temp[2048]; // printf("in minimalSwapAndFlipIVar_superFast_iVar5\n"); M[0] = minTemp0_fast_iVar5(pInOut, nWords, &DifStart0); // 0, 3 M[1] = minTemp1_fast_iVar5(pInOut, nWords, &DifStart1); // 1, 2 min1 = minTemp2_fast_iVar5(pInOut, M[0], M[1], nWords, &DifStartMin); if(DifStart0 != DifStart1) { if( DifStartMin>=DifStart1 && DifStartMin>=DifStart0 ) arrangeQuoters_superFast_iVar5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase); else if( DifStart0 > DifStart1) arrangeQuoters_superFast_iVar5(pInOut, temp, luckyMax(DifStartMin,DifStart0), M[0], M[1], 3 - M[1], 3 - M[0], pCanonPerm, pCanonPhase); else arrangeQuoters_superFast_iVar5(pInOut, temp, luckyMax(DifStartMin,DifStart1), M[1], M[0], 3 - M[0], 3 - M[1], pCanonPerm, pCanonPhase); } else { if(DifStartMin>=DifStart0) arrangeQuoters_superFast_iVar5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase); else { min2 = minTemp3_fast_iVar5(pInOut, DifStart0, DifStartMin, 3-M[0], 3-M[1], &DifStart1); // reuse DifStart1 because DifStart1 = DifStart1=0 if(DifStart1>DifStartMin) arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart0, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], pCanonPerm, pCanonPhase); else arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart0, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], pCanonPerm, pCanonPhase); } } } void minimalSwapAndFlipIVar_superFast_iVar5_noEBFC(unsigned* pInOut, int nWords, char * pCanonPerm, unsigned* pCanonPhase) { int DifStart1; unsigned temp[2048]; if(minTemp1_fast_iVar5(pInOut, nWords, &DifStart1) == 2) arrangeQuoters_superFast_iVar5(pInOut, temp, DifStart1, 0, 2, 1, 3, pCanonPerm, pCanonPhase); } ////////////////////////////////////moreThen5///////////////////////////////////////////////////////////////////////////////////////////// // It rearranges InOut (swaps and flips through rearrangement of quoters) // It updates Info at the end void arrangeQuoters_superFast_moreThen5(word* pInOut, word* temp, int start, int iQ, int jQ, int kQ, int lQ, int iVar, char * pCanonPerm, unsigned* pCanonPhase) { int i,wordBlock,blockSize,shiftSize; word* tempPtr = temp+start; // printf("in arrangeQuoters_superFast_moreThen5\n"); if(iQ == 0 && jQ == 1) return; wordBlock = (1<<(iVar-6)); blockSize = wordBlock*sizeof(word); shiftSize = wordBlock*4; for(i=start-wordBlock;i>0;i-=shiftSize) { tempPtr -= wordBlock; memcpy(tempPtr, pInOut+i-iQ*wordBlock, blockSize); tempPtr -= wordBlock; memcpy(tempPtr, pInOut+i-jQ*wordBlock, blockSize); tempPtr -= wordBlock; memcpy(tempPtr, pInOut+i-kQ*wordBlock, blockSize); tempPtr -= wordBlock; memcpy(tempPtr, pInOut+i-lQ*wordBlock, blockSize); } memcpy(pInOut, temp, start*sizeof(word)); updataInfo(iQ, jQ, iVar, pCanonPerm, pCanonPhase); // printf("out arrangeQuoters_superFast_moreThen5\n"); } //It compares 0Q and 3Q and returns 0 if 0Q is smaller then 3Q ( comparison starts at highest bit) and visa versa // DifStart contains the information about the first different bit in 0Q and 3Q int minTemp0_fast_moreThen5(word* pInOut, int iVar, int nWords, int* pDifStart) { int i, j, temp; int wordBlock = 1<<(iVar-6); int wordDif = 3*wordBlock; int shiftBlock = wordBlock*4; // printf("in minTemp0_fast_moreThen5\n"); for(i=nWords - 1; i>=0; i-=shiftBlock) for(j=0;j=0; i-=shiftBlock) for(j=0;j=0; i-=shiftBlock) for(j=0;j=finish; i-=shiftBlock) for(j=0;j=DifStart1 && DifStartMin>=DifStart0 ) arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase); else if( DifStart0 > DifStart1) arrangeQuoters_superFast_moreThen5(pInOut, temp, luckyMax(DifStartMin,DifStart0), M[0], M[1], 3 - M[1], 3 - M[0], iVar, pCanonPerm, pCanonPhase); else arrangeQuoters_superFast_moreThen5(pInOut, temp, luckyMax(DifStartMin,DifStart1), M[1], M[0], 3 - M[0], 3 - M[1], iVar, pCanonPerm, pCanonPhase); } else { if(DifStartMin>=DifStart0) arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStartMin, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase); else { min2 = minTemp3_fast_moreThen5(pInOut, iVar, DifStart0, DifStartMin, 3-M[0], 3-M[1], &DifStart1); // reuse DifStart1 because DifStart1 = DifStart1=0 if(DifStart1>DifStartMin) arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart0, M[(min2+1)&1], M[min2], 3 - M[min2], 3 - M[(min2+1)&1], iVar, pCanonPerm, pCanonPhase); else arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart0, M[min1], M[(min1+1)&1], 3 - M[(min1+1)&1], 3 - M[min1], iVar, pCanonPerm, pCanonPhase); } } // printf("out minimalSwapAndFlipIVar_superFast_moreThen5\n"); } void minimalSwapAndFlipIVar_superFast_moreThen5_noEBFC(word* pInOut, int iVar, int nWords, char * pCanonPerm, unsigned* pCanonPhase) { int DifStart1; word temp[1024]; if(minTemp1_fast_moreThen5(pInOut, iVar, nWords, &DifStart1) == 2) arrangeQuoters_superFast_moreThen5(pInOut, temp, DifStart1, 0, 2, 1, 3, iVar, pCanonPerm, pCanonPhase); } /////////////////////////////////// for all ///////////////////////////////////////////////////////////////////////////////////////////// void minimalInitialFlip_fast_16Vars(word* pInOut, int nVars, unsigned* pCanonPhase) { word oneWord=1; if( (pInOut[Kit_TruthWordNum_64bit( nVars ) -1]>>63) & oneWord ) { Kit_TruthNot_64bit( pInOut, nVars ); (* pCanonPhase) ^=(1<> (nVars+1)) & 1) while( minimalSwapAndFlipIVar_superFast_all(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase) != 0) continue; else while( minimalSwapAndFlipIVar_superFast_all_noEBFC(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase) != 0) continue; } void luckyCanonicizerS_F_first_16Vars11(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) { word duplicate[1024]; char pCanonPerm1[16]; unsigned uCanonPhase1; if((* pCanonPhase) >> (nVars+2) ) { memcpy(duplicate, pInOut, sizeof(word)*nWords); Kit_TruthNot_64bit(duplicate, nVars); uCanonPhase1 = *pCanonPhase; uCanonPhase1 ^= (1 << nVars); memcpy(pCanonPerm1,pCanonPerm,sizeof(char)*16); luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase); luckyCanonicizerS_F_first_16Vars1(duplicate, nVars, nWords, pStore, pCanonPerm1, &uCanonPhase1); if(memCompare(pInOut, duplicate,nVars) == 1) { *pCanonPhase = uCanonPhase1; memcpy(pCanonPerm,pCanonPerm1,sizeof(char)*16); memcpy(pInOut, duplicate, sizeof(word)*nWords); } } else { luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase); } } void luckyCanonicizer_final_fast_16Vars(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) { assert( nVars > 6 && nVars <= 16 ); (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( pInOut, nVars, pCanonPerm, pStore ); luckyCanonicizerS_F_first_16Vars1(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase ); } void bitReverceOrder(word* x, int nVars) { int i; for(i= nVars-1;i>=0;i--) Kit_TruthChangePhase_64bit( x, nVars, i ); } void luckyCanonicizer_final_fast_16Vars1(word* pInOut, int nVars, int nWords, int * pStore, char * pCanonPerm, unsigned* pCanonPhase) { assert( nVars > 6 && nVars <= 16 ); (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( pInOut, nVars, pCanonPerm, pStore ); luckyCanonicizerS_F_first_16Vars11(pInOut, nVars, nWords, pStore, pCanonPerm, pCanonPhase ); bitReverceOrder(pInOut, nVars); (*pCanonPhase) ^= (1<>63) ) { (* pCanonPhase) ^=(1<<6); return ~x; } else return x; } unsigned adjustInfoAfterSwap(char* pCanonPerm, unsigned uCanonPhase, int iVar, unsigned info) { if(info<4) return (uCanonPhase ^= (info << iVar)); else { char temp; uCanonPhase ^= ((info-4) << iVar); temp=pCanonPerm[iVar]; pCanonPerm[iVar]=pCanonPerm[iVar+1]; pCanonPerm[iVar+1]=temp; if ( ((uCanonPhase & (1 << iVar)) > 0) != ((uCanonPhase & (1 << (iVar+1))) > 0) ) { uCanonPhase ^= (1 << iVar); uCanonPhase ^= (1 << (iVar+1)); } return uCanonPhase; } } word Extra_Truth6SwapAdjacent( word t, int iVar ) { // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; assert( iVar < 5 ); return (t & PMasks[iVar][0]) | ((t & PMasks[iVar][1]) << (1 << iVar)) | ((t & PMasks[iVar][2]) >> (1 << iVar)); } word Extra_Truth6ChangePhase( word t, int iVar) { // elementary truth tables static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; assert( iVar < 6 ); return ((t & ~Truth6[iVar]) << (1 << iVar)) | ((t & Truth6[iVar]) >> (1 << iVar)); } word Extra_Truth6MinimumRoundOne( word t, int iVar, char* pCanonPerm, unsigned* pCanonPhase ) { word tCur, tMin = t; // ab unsigned info =0; assert( iVar >= 0 && iVar < 5 ); tCur = Extra_Truth6ChangePhase( t, iVar ); // !a b if(tCur= 0 && iVar < 5 ); tMin = Extra_Truth6SwapAdjacent( t, iVar ); // b a if(t> 7) { case 0 : { return Extra_Truth6MinimumRoundMany_noEBFC( t, pStore, pCanonPerm, pCanonPhase); } case 1 : { return Extra_Truth6MinimumRoundMany( t, pStore, pCanonPerm, pCanonPhase); } case 2 : { uCanonPhase1 = *pCanonPhase; uCanonPhase1 ^= (1 << 6); memcpy(pCanonPerm1,pCanonPerm,sizeof(char)*16); tMin0 = Extra_Truth6MinimumRoundMany_noEBFC( t, pStore, pCanonPerm, pCanonPhase); tMin = Extra_Truth6MinimumRoundMany_noEBFC( ~t, pStore, pCanonPerm1, &uCanonPhase1); if(tMin0 <=tMin) return tMin0; else { *pCanonPhase = uCanonPhase1; memcpy(pCanonPerm,pCanonPerm1,sizeof(char)*16); return tMin; } } case 3 : { uCanonPhase1 = *pCanonPhase; uCanonPhase1 ^= (1 << 6); memcpy(pCanonPerm1,pCanonPerm,sizeof(char)*16); tMin0 = Extra_Truth6MinimumRoundMany( t, pStore, pCanonPerm, pCanonPhase); tMin = Extra_Truth6MinimumRoundMany( ~t, pStore, pCanonPerm1, &uCanonPhase1); if(tMin0 <=tMin) return tMin0; else { *pCanonPhase = uCanonPhase1; memcpy(pCanonPerm,pCanonPerm1,sizeof(char)*16); return tMin; } } } return Extra_Truth6MinimumRoundMany( t, pStore, pCanonPerm, pCanonPhase); } word luckyCanonicizer_final_fast_6Vars(word InOut, int* pStore, char* pCanonPerm, unsigned* pCanonPhase) { (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( &InOut, 6, pCanonPerm, pStore); return Extra_Truth6MinimumRoundMany1(InOut, pStore, pCanonPerm, pCanonPhase); } word luckyCanonicizer_final_fast_6Vars1(word InOut, int* pStore, char* pCanonPerm, unsigned* pCanonPhase ) { (* pCanonPhase) = Kit_TruthSemiCanonicize_Yasha1( &InOut, 6, pCanonPerm, pStore); InOut = Extra_Truth6MinimumRoundMany1(InOut, pStore, pCanonPerm, pCanonPhase); Kit_TruthChangePhase_64bit( &InOut, 6, 5 ); Kit_TruthChangePhase_64bit( &InOut, 6, 4 ); Kit_TruthChangePhase_64bit( &InOut, 6, 3 ); Kit_TruthChangePhase_64bit( &InOut, 6, 2 ); Kit_TruthChangePhase_64bit( &InOut, 6, 1 ); Kit_TruthChangePhase_64bit( &InOut, 6, 0 ); (*pCanonPhase) ^= 0x3F; return Extra_Truth6MinimumRoundMany1(InOut, pStore, pCanonPerm, pCanonPhase); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/luckyInt.h000066400000000000000000000077121300674244400241000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [luckyInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Semi-canonical form computation package.] Synopsis [Internal declarations.] Author [Jake] Date [Started - August 2012] ***********************************************************************/ #ifndef ABC__bool__lucky__LUCKY_INT_H_ #define ABC__bool__lucky__LUCKY_INT_H_ #include #include #include #include #include #include // comment out this line to run Lucky Code outside of ABC #define _RUNNING_ABC_ #ifdef _RUNNING_ABC_ #include "misc/util/abc_global.h" #include "lucky.h" #else #define ABC_NAMESPACE_HEADER_START #define ABC_NAMESPACE_HEADER_END #define ABC_NAMESPACE_IMPL_START #define ABC_NAMESPACE_IMPL_END typedef unsigned __int64 word; #define bool int #define false 0 #define true 1 #define inline __inline // compatible with MS VS 6.0 #define ABC_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) // #define LUCKY_VERIFY typedef struct { int varN; int* swapArray; int swapCtr; int totalSwaps; int* flipArray; int flipCtr; int totalFlips; }permInfo; #endif ABC_NAMESPACE_HEADER_START typedef struct { int nVars; int nWords; int nFuncs; word ** pFuncs; }Abc_TtStore_t; typedef struct { int direction; int position; } varInfo; typedef struct { varInfo* posArray; int* realArray; int varN; int positionToSwap1; int positionToSwap2; } swapInfo; static inline void TimePrint( char* Message ) { static int timeBegin; double time = 1.0*(Abc_Clock() - timeBegin)/CLOCKS_PER_SEC ; if ( Message != NULL) printf("%s = %f sec.\n", Message, time); timeBegin = Abc_Clock(); } static inline int CompareWords( word x, word y) { if( x > y ) return 1; if( x < y ) return -1; return 0; } static inline int luckyMin( int x, int y ) { return (x < y) ? x : y; } static inline int luckyMax( int x, int y ) { return (x < y) ? y : x; } extern int memCompare(word* x, word* y, int nVars); extern int Kit_TruthWordNum_64bit( int nVars ); extern Abc_TtStore_t * setTtStore(char * pFileInput); extern void Abc_TruthStoreFree( Abc_TtStore_t * p ); extern void Kit_TruthChangePhase_64bit( word * pInOut, int nVars, int iVar ); extern void Kit_TruthNot_64bit(word * pIn, int nVars ); extern void Kit_TruthCopy_64bit( word * pOut, word * pIn, int nVars ); extern void Kit_TruthSwapAdjacentVars_64bit( word * pInOut, int nVars, int iVar ); extern int Kit_TruthCountOnes_64bit( word* pIn, int nVars ); extern void simpleMinimal(word* x, word* pAux,word* minimal, permInfo* pi, int nVars); extern permInfo * setPermInfoPtr(int var); extern void freePermInfoPtr(permInfo* x); extern void Kit_TruthSemiCanonicize_Yasha_simple( word* pInOut, int nVars, int * pStore ); extern unsigned Kit_TruthSemiCanonicize_Yasha( word* pInOut, int nVars, char * pCanonPerm); extern unsigned Kit_TruthSemiCanonicize_Yasha1( word* pInOut, int nVars, char * pCanonPerm, int * pStore); extern word luckyCanonicizer_final_fast_6Vars(word InOut, int* pStore, char* pCanonPerm, unsigned* pCanonPhase); extern word luckyCanonicizer_final_fast_6Vars1(word InOut, int* pStore, char* pCanonPerm, unsigned* pCanonPhase); extern unsigned adjustInfoAfterSwap(char* pCanonPerm, unsigned uCanonPhase, int iVar, unsigned info); extern void resetPCanonPermArray_6Vars(char* x); extern void swap_ij( word* f,int totalVars, int varI, int varJ); ABC_NAMESPACE_HEADER_END #endif /* LUCKY_H_ */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/luckyRead.c000066400000000000000000000257511300674244400242170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [luckyRead.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Semi-canonical form computation package.] Synopsis [Reading truth tables from file.] Author [Jake] Date [Started - August 2012] ***********************************************************************/ #include "luckyInt.h" ABC_NAMESPACE_IMPL_START // read/write/flip i-th bit of a bit string table: static inline int Abc_TruthGetBit( word * p, int i ) { return (int)(p[i>>6] >> (i & 63)) & 1; } static inline void Abc_TruthSetBit( word * p, int i ) { p[i>>6] |= (((word)1)<<(i & 63)); } static inline void Abc_TruthXorBit( word * p, int i ) { p[i>>6] ^= (((word)1)<<(i & 63)); } // read/write k-th digit d of a hexadecimal number: static inline int Abc_TruthGetHex( word * p, int k ) { return (int)(p[k>>4] >> ((k<<2) & 63)) & 15; } static inline void Abc_TruthSetHex( word * p, int k, int d ) { p[k>>4] |= (((word)d)<<((k<<2) & 63)); } static inline void Abc_TruthXorHex( word * p, int k, int d ) { p[k>>4] ^= (((word)d)<<((k<<2) & 63)); } // read one hex character static inline int Abc_TruthReadHexDigit( char HexChar ) { if ( HexChar >= '0' && HexChar <= '9' ) return HexChar - '0'; if ( HexChar >= 'A' && HexChar <= 'F' ) return HexChar - 'A' + 10; if ( HexChar >= 'a' && HexChar <= 'f' ) return HexChar - 'a' + 10; assert( 0 ); // not a hexadecimal symbol return -1; // return value which makes no sense } // write one hex character static inline void Abc_TruthWriteHexDigit( FILE * pFile, int HexDigit ) { assert( HexDigit >= 0 && HexDigit < 16 ); if ( HexDigit < 10 ) fprintf( pFile, "%d", HexDigit ); else fprintf( pFile, "%c", 'A' + HexDigit-10 ); } // read one truth table in hexadecimal static inline void Abc_TruthReadHex( word * pTruth, char * pString, int nVars ) { int nWords = (nVars < 7)? 1 : (1 << (nVars-6)); int k, Digit, nDigits = (nVars < 7) ? (1 << (nVars-2)) : (nWords << 4); char EndSymbol; // skip the first 2 symbols if they are "0x" if ( pString[0] == '0' && pString[1] == 'x' ) pString += 2; // get the last symbol EndSymbol = pString[nDigits]; // the end symbol of the TT (the one immediately following hex digits) // should be one of the following: space, a new-line, or a zero-terminator // (note that on Windows symbols '\r' can be inserted before each '\n') assert( EndSymbol == ' ' || EndSymbol == '\n' || EndSymbol == '\r' || EndSymbol == '\0' ); // read hexadecimal digits in the reverse order // (the last symbol in the string is the least significant digit) for ( k = 0; k < nDigits; k++ ) { Digit = Abc_TruthReadHexDigit( pString[nDigits - 1 - k] ); assert( Digit >= 0 && Digit < 16 ); Abc_TruthSetHex( pTruth, k, Digit ); } } // write one truth table in hexadecimal (do not add end-of-line!) static inline void Abc_TruthWriteHex( FILE * pFile, word * pTruth, int nVars ) { int nDigits, Digit, k; // write hexadecimal digits in the reverse order // (the last symbol in the string is the least significant digit) nDigits = (1 << (nVars-2)); for ( k = 0; k < nDigits; k++ ) { Digit = Abc_TruthGetHex( pTruth, nDigits - 1 - k ); assert( Digit >= 0 && Digit < 16 ); Abc_TruthWriteHexDigit( pFile, Digit ); } } // allocate and clear memory to store 'nTruths' truth tables of 'nVars' variables static inline Abc_TtStore_t * Abc_TruthStoreAlloc( int nVars, int nFuncs ) { Abc_TtStore_t * p; int i; p = (Abc_TtStore_t *)malloc( sizeof(Abc_TtStore_t) ); p->nVars = nVars; p->nWords = (nVars < 7) ? 1 : (1 << (nVars-6)); p->nFuncs = nFuncs; // alloc array of 'nFuncs' pointers to truth tables p->pFuncs = (word **)malloc( sizeof(word *) * p->nFuncs ); // alloc storage for 'nFuncs' truth tables as one chunk of memory p->pFuncs[0] = (word *)calloc( sizeof(word), p->nFuncs * p->nWords ); // split it up into individual truth tables for ( i = 1; i < p->nFuncs; i++ ) p->pFuncs[i] = p->pFuncs[i-1] + p->nWords; return p; } // free memory previously allocated for storing truth tables void Abc_TruthStoreFree( Abc_TtStore_t * p ) { free( p->pFuncs[0] ); free( p->pFuncs ); free( p ); } // read file contents static char * Abc_FileRead( char * pFileName ) { FILE * pFile; char * pBuffer; int nFileSize; int RetValue; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return NULL; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = (char *)malloc( nFileSize + 3 ); RetValue = fread( pBuffer, nFileSize, 1, pFile ); // add several empty lines at the end // (these will be used to signal the end of parsing) pBuffer[ nFileSize + 0] = '\n'; pBuffer[ nFileSize + 1] = '\n'; // terminate the string with '\0' pBuffer[ nFileSize + 2] = '\0'; fclose( pFile ); return pBuffer; } // determine the number of variables by reading the first line // determine the number of functions by counting the lines static void Abc_TruthGetParams( char * pFileName, int * pnVars, int * pnTruths ) { char * pContents; int i, nVars, nLines; // prepare the output if ( pnVars ) *pnVars = 0; if ( pnTruths ) *pnTruths = 0; // read data from file pContents = Abc_FileRead( pFileName ); if ( pContents == NULL ) return; // count the number of symbols before the first space or new-line // (note that on Windows symbols '\r' can be inserted before each '\n') for ( i = 0; pContents[i]; i++ ) if ( pContents[i] == ' ' || pContents[i] == '\n' || pContents[i] == '\r' ) break; if ( pContents[i] == 0 ) printf( "Strange, the input file does not have spaces and new-lines...\n" ); // account for the fact that truth tables may have "0x" at the beginning of each line if ( pContents[0] == '0' && pContents[1] == 'x' ) i = i - 2; // determine the number of variables for ( nVars = 0; nVars < 32; nVars++ ) if ( 4 * i == (1 << nVars) ) // the number of bits equal to the size of truth table break; if ( nVars < 2 || nVars > 16 ) { printf( "Does not look like the input file contains truth tables...\n" ); return; } if ( pnVars ) *pnVars = nVars; // determine the number of functions by counting the lines nLines = 0; for ( i = 0; pContents[i]; i++ ) nLines += (pContents[i] == '\n'); if ( pnTruths ) *pnTruths = nLines; } static Abc_TtStore_t * Abc_Create_TtSpore (char * pFileInput) { int nVars, nTruths; Abc_TtStore_t * p; Abc_TruthGetParams( pFileInput, &nVars, &nTruths ); p = Abc_TruthStoreAlloc( nVars, nTruths ); return p; } // read truth tables from file static void Abc_TruthStoreRead( char * pFileName, Abc_TtStore_t* p ) { char * pContents; int i, nLines; pContents = Abc_FileRead( pFileName ); if ( pContents == NULL ) return; // here it is assumed (without checking!) that each line of the file // begins with a string of hexadecimal chars followed by space // the file will be read till the first empty line (pContents[i] == '\n') // (note that Abc_FileRead() added several empty lines at the end of the file contents) for ( nLines = i = 0; pContents[i] != '\n'; ) { // read one line Abc_TruthReadHex( p->pFuncs[nLines++], &pContents[i], p->nVars ); // skip till after the end-of-line symbol // (note that end-of-line symbol is also skipped) while ( pContents[i++] != '\n' ); } // adjust the number of functions read // (we may have allocated more storage because some lines in the file were empty) assert( p->nFuncs >= nLines ); p->nFuncs = nLines; } // write truth tables into file // (here we write one symbol at a time - it can be optimized by writing // each truth table into a string and then writing the string into a file) static void Abc_TruthStoreWrite( char * pFileName, Abc_TtStore_t * p ) { FILE * pFile; int i; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } for ( i = 0; i < p->nFuncs; i++ ) { Abc_TruthWriteHex( pFile, p->pFuncs[i], p->nVars ); fprintf( pFile, "\n" ); } fclose( pFile ); } static void WriteToFile(char * pFileName, Abc_TtStore_t * p, word* a) { FILE * pFile; int i; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } for ( i = 0; i < p->nFuncs; i++ ) { Abc_TruthWriteHex( pFile, &a[i], p->nVars ); fprintf( pFile, "\n" ); } fclose( pFile ); } static void WriteToFile1(char * pFileName, Abc_TtStore_t * p, word** a) { FILE * pFile; int i,j; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } for ( i = 0; i < p->nFuncs; i++ ) { fprintf( pFile, "0" ); fprintf( pFile, "x" ); for ( j=p->nWords-1; j >= 0; j-- ) Abc_TruthWriteHex( pFile, &a[i][j], p->nVars ); fprintf( pFile, "\n" ); } fprintf( pFile, "\n" ); fclose( pFile ); } static void WriteToFile2(char * pFileName, Abc_TtStore_t * p, word* a) { FILE * pFile; int i,j; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } for ( i = 0; i < p->nFuncs; i++ ) { fprintf( pFile, "0" ); fprintf( pFile, "x" ); for ( j=p->nWords-1; j >= 0; j-- ) Abc_TruthWriteHex( pFile, a+i, p->nVars ); fprintf( pFile, "\n" ); } fprintf( pFile, "\n" ); fclose( pFile ); } Abc_TtStore_t * setTtStore(char * pFileInput) { int nVars, nTruths; Abc_TtStore_t * p; // figure out how many truth table and how many variables Abc_TruthGetParams( pFileInput, &nVars, &nTruths ); // allocate data-structure p = Abc_TruthStoreAlloc( nVars, nTruths ); Abc_TruthStoreRead( pFileInput, p ); return p; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/luckySimple.c000066400000000000000000000204421300674244400245650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [luckySimple.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Semi-canonical form computation package.] Synopsis [Truth table minimization procedures.] Author [Jake] Date [Started - August 2012] ***********************************************************************/ #include "luckyInt.h" ABC_NAMESPACE_IMPL_START static swapInfo* setSwapInfoPtr(int varsN) { int i; swapInfo* x = (swapInfo*) malloc(sizeof(swapInfo)); x->posArray = (varInfo*) malloc (sizeof(varInfo)*(varsN+2)); x->realArray = (int*) malloc (sizeof(int)*(varsN+2)); x->varN = varsN; x->realArray[0]=varsN+100; for(i=1;i<=varsN;i++) { x->posArray[i].position=i; x->posArray[i].direction=-1; x->realArray[i]=i; } x->realArray[varsN+1]=varsN+10; return x; } static void freeSwapInfoPtr(swapInfo* x) { free(x->posArray); free(x->realArray); free(x); } int nextSwap(swapInfo* x) { int i,j,temp; for(i=x->varN;i>1;i--) { if( i > x->realArray[x->posArray[i].position + x->posArray[i].direction] ) { x->posArray[i].position = x->posArray[i].position + x->posArray[i].direction; temp = x->realArray[x->posArray[i].position]; x->realArray[x->posArray[i].position] = i; x->realArray[x->posArray[i].position - x->posArray[i].direction] = temp; x->posArray[temp].position = x->posArray[i].position - x->posArray[i].direction; for(j=x->varN;j>i;j--) { x->posArray[j].direction = x->posArray[j].direction * -1; } x->positionToSwap1 = x->posArray[temp].position - 1; x->positionToSwap2 = x->posArray[i].position - 1; return 1; } } return 0; } void fillInSwapArray(permInfo* pi) { int counter=pi->totalSwaps-1; swapInfo* x= setSwapInfoPtr(pi->varN); while(nextSwap(x)==1) { if(x->positionToSwap1positionToSwap2) pi->swapArray[counter--]=x->positionToSwap1; else pi->swapArray[counter--]=x->positionToSwap2; } freeSwapInfoPtr(x); } int oneBitPosition(int x, int size) { int i; for(i=0;i>i)&1) return i; return -1; } void fillInFlipArray(permInfo* pi) { int i, temp=0, grayNumber; for(i=1;i<=pi->totalFlips;i++) { grayNumber = i^(i>>1); pi->flipArray[pi->totalFlips-i]=oneBitPosition(temp^grayNumber, pi->varN); temp = grayNumber; } } static inline int factorial(int n) { return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n; } permInfo* setPermInfoPtr(int var) { permInfo* x; x = (permInfo*) malloc(sizeof(permInfo)); x->flipCtr=0; x->varN = var; x->totalFlips=(1<swapCtr=0; x->totalSwaps=factorial(var)-1; x->flipArray = (int*) malloc(sizeof(int)*x->totalFlips); x->swapArray = (int*) malloc(sizeof(int)*x->totalSwaps); fillInSwapArray(x); fillInFlipArray(x); return x; } void freePermInfoPtr(permInfo* x) { free(x->flipArray); free(x->swapArray); free(x); } static inline void minWord(word* a, word* b, word* minimal, int nVars) { if(memCompare(a, b, nVars) == -1) Kit_TruthCopy_64bit( minimal, a, nVars ); else Kit_TruthCopy_64bit( minimal, b, nVars ); } static inline void minWord3(word* a, word* b, word* minimal, int nVars) { if (memCompare(a, b, nVars) <= 0) { if (memCompare(a, minimal, nVars) < 0) Kit_TruthCopy_64bit( minimal, a, nVars ); else return ; } if (memCompare(b, minimal, nVars) <= 0) Kit_TruthCopy_64bit( minimal, b, nVars ); } static inline void minWord1(word* a, word* minimal, int nVars) { if (memCompare(a, minimal, nVars) <= 0) Kit_TruthCopy_64bit( minimal, a, nVars ); } void simpleMinimal(word* x, word* pAux,word* minimal, permInfo* pi, int nVars) { int i,j=0; Kit_TruthCopy_64bit( pAux, x, nVars ); Kit_TruthNot_64bit( x, nVars ); minWord(x, pAux, minimal, nVars); for(i=pi->totalSwaps-1;i>=0;i--) { Kit_TruthSwapAdjacentVars_64bit(x, nVars, pi->swapArray[i]); Kit_TruthSwapAdjacentVars_64bit(pAux, nVars, pi->swapArray[i]); minWord3(x, pAux, minimal, nVars); } for(j=pi->totalFlips-1;j>=0;j--) { Kit_TruthSwapAdjacentVars_64bit(x, nVars, 0); Kit_TruthSwapAdjacentVars_64bit(pAux, nVars, 0); Kit_TruthChangePhase_64bit(x, nVars, pi->flipArray[j]); Kit_TruthChangePhase_64bit(pAux, nVars, pi->flipArray[j]); minWord3(x, pAux, minimal, nVars); for(i=pi->totalSwaps-1;i>=0;i--) { Kit_TruthSwapAdjacentVars_64bit(x, nVars, pi->swapArray[i]); Kit_TruthSwapAdjacentVars_64bit(pAux, nVars, pi->swapArray[i]); minWord3(x, pAux, minimal, nVars); } } Kit_TruthCopy_64bit( x, minimal, nVars ); } /** * pGroups: we assume that the variables are merged into adjacent groups, * the size of each group is stored in pGroups * nGroups: the number of groups * * pis: we compute all permInfos from 0 to nVars (incl.) */ void simpleMinimalGroups(word* x, word* pAux, word* minimal, int* pGroups, int nGroups, permInfo** pis, int nVars, int fFlipOutput, int fFlipInput) { /* variables */ int i, j, o, nn; permInfo* pi; int * a, * c, * m; /* reorder groups and calculate group offsets */ int * offset = ABC_ALLOC( int, nGroups ); o = 0; j = 0; for ( i = 0; i < nGroups; ++i ) { offset[j] = o; o += pGroups[j]; ++j; } if ( fFlipOutput ) { /* keep regular and inverted version of x */ Kit_TruthCopy_64bit( pAux, x, nVars ); Kit_TruthNot_64bit( x, nVars ); minWord(x, pAux, minimal, nVars); } else { Kit_TruthCopy_64bit( minimal, x, nVars ); } /* iterate through all combinations of pGroups using mixed radix enumeration */ nn = ( nGroups << 1 ) + 1; a = ABC_ALLOC( int, nn ); c = ABC_ALLOC( int, nn ); m = ABC_ALLOC( int, nn ); /* fill a and m arrays */ m[0] = 2; for ( i = 1; i <= nGroups; ++i ) { m[i] = pis[pGroups[i - 1]]->totalFlips + 1; } for ( i = 1; i <= nGroups; ++i ) { m[nGroups + i] = pis[pGroups[i - 1]]->totalSwaps + 1; } for ( i = 0; i < nn; ++i ) { a[i] = c[i] = 0; } while ( 1 ) { /* consider all flips */ for ( i = 1; i <= nGroups; ++i ) { if ( !c[i] ) { continue; } if ( !fFlipInput && pGroups[i - 1] == 1 ) { continue; } pi = pis[pGroups[i - 1]]; j = a[i] == 0 ? 0 : pi->totalFlips - a[i]; Kit_TruthChangePhase_64bit(x, nVars, offset[i - 1] + pi->flipArray[j]); if ( fFlipOutput ) { Kit_TruthChangePhase_64bit(pAux, nVars, offset[i - 1] + pi->flipArray[j]); minWord3(x, pAux, minimal, nVars); } else { minWord1(x, minimal, nVars); } } /* consider all swaps */ for ( i = 1; i <= nGroups; ++i ) { if ( !c[nGroups + i] ) { continue; } if ( pGroups[i - 1] == 1 ) { continue; } pi = pis[pGroups[i - 1]]; if ( a[nGroups + i] == pi->totalSwaps ) { j = 0; } else { j = pi->swapArray[pi->totalSwaps - a[nGroups + i] - 1]; } Kit_TruthSwapAdjacentVars_64bit(x, nVars, offset[i - 1] + j); if ( fFlipOutput ) { Kit_TruthSwapAdjacentVars_64bit(pAux, nVars, offset[i - 1] + j); minWord3(x, pAux, minimal, nVars); } else { minWord1(x, minimal, nVars); } } /* update a's */ memset(c, 0, sizeof(int) * nn); j = nn - 1; while ( a[j] == m[j] - 1 ) { c[j] = 1; a[j--] = 0; } /* done? */ if ( j == 0 ) { break; } c[j] = 1; a[j]++; } ABC_FREE( offset ); ABC_FREE( a ); ABC_FREE( c ); ABC_FREE( m ); Kit_TruthCopy_64bit( x, minimal, nVars ); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/luckySwap.c000066400000000000000000000324671300674244400242600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [luckySwap.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Semi-canonical form computation package.] Synopsis [Swapping variables in the truth table.] Author [Jake] Date [Started - August 2012] ***********************************************************************/ #include "luckyInt.h" ABC_NAMESPACE_IMPL_START static word mask0[6] = { ABC_CONST(0x5555555555555555),ABC_CONST(0x3333333333333333), ABC_CONST(0x0F0F0F0F0F0F0F0F),ABC_CONST(0x00FF00FF00FF00FF),ABC_CONST(0x0000FFFF0000FFFF), ABC_CONST(0x00000000FFFFFFFF)}; /* static word mask1[6] = { 0xAAAAAAAAAAAAAAAA,0xCCCCCCCCCCCCCCCC, 0xF0F0F0F0F0F0F0F0,0xFF00FF00FF00FF00,0xFFFF0000FFFF0000, 0xFFFFFFFF00000000 }; static word mask[6][2] = { {0x5555555555555555,0xAAAAAAAAAAAAAAAA}, {0x3333333333333333,0xCCCCCCCCCCCCCCCC}, {0x0F0F0F0F0F0F0F0F,0xF0F0F0F0F0F0F0F0}, {0x00FF00FF00FF00FF,0xFF00FF00FF00FF00}, {0x0000FFFF0000FFFF,0xFFFF0000FFFF0000}, {0x00000000FFFFFFFF,0xFFFFFFFF00000000} }; */ int Kit_TruthWordNum_64bit( int nVars ) { return nVars <= 6 ? 1 : (1 << (nVars - 6));} int Kit_WordCountOnes_64bit(word x) { x = x - ((x >> 1) & ABC_CONST(0x5555555555555555)); x = (x & ABC_CONST(0x3333333333333333)) + ((x >> 2) & ABC_CONST(0x3333333333333333)); x = (x + (x >> 4)) & ABC_CONST(0x0F0F0F0F0F0F0F0F); x = x + (x >> 8); x = x + (x >> 16); x = x + (x >> 32); return (int)(x & 0xFF); } int Kit_TruthCountOnes_64bit( word* pIn, int nVars ) { int w, Counter = 0; for ( w = Kit_TruthWordNum_64bit(nVars)-1; w >= 0; w-- ) Counter += Kit_WordCountOnes_64bit(pIn[w]); return Counter; } void Kit_TruthCountOnesInCofs_64bit( word * pTruth, int nVars, int * pStore ) { int nWords = Kit_TruthWordNum_64bit( nVars ); int i, k, Counter; memset( pStore, 0, sizeof(int) * nVars ); if ( nVars <= 6 ) { if ( nVars > 0 ) pStore[0] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x5555555555555555) ); if ( nVars > 1 ) pStore[1] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x3333333333333333) ); if ( nVars > 2 ) pStore[2] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x0F0F0F0F0F0F0F0F) ); if ( nVars > 3 ) pStore[3] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x00FF00FF00FF00FF) ); if ( nVars > 4 ) pStore[4] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x0000FFFF0000FFFF) ); if ( nVars > 5 ) pStore[5] = Kit_WordCountOnes_64bit( pTruth[0] & ABC_CONST(0x00000000FFFFFFFF) ); return; } // nVars > 6 // count 1's for all other variables for ( k = 0; k < nWords; k++ ) { Counter = Kit_WordCountOnes_64bit( pTruth[k] ); for ( i = 6; i < nVars; i++ ) if ( (k & (1 << (i-6))) == 0) pStore[i] += Counter; } // count 1's for the first six variables for ( k = nWords/2; k>0; k-- ) { pStore[0] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x5555555555555555)) | ((pTruth[1] & ABC_CONST(0x5555555555555555)) << 1) ); pStore[1] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x3333333333333333)) | ((pTruth[1] & ABC_CONST(0x3333333333333333)) << 2) ); pStore[2] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x0F0F0F0F0F0F0F0F)) | ((pTruth[1] & ABC_CONST(0x0F0F0F0F0F0F0F0F)) << 4) ); pStore[3] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x00FF00FF00FF00FF)) | ((pTruth[1] & ABC_CONST(0x00FF00FF00FF00FF)) << 8) ); pStore[4] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x0000FFFF0000FFFF)) | ((pTruth[1] & ABC_CONST(0x0000FFFF0000FFFF)) << 16) ); pStore[5] += Kit_WordCountOnes_64bit( (pTruth[0] & ABC_CONST(0x00000000FFFFFFFF)) | ((pTruth[1] & ABC_CONST(0x00000000FFFFFFFF)) << 32) ); pTruth += 2; } } void Kit_TruthChangePhase_64bit( word * pInOut, int nVars, int iVar ) { int nWords = Kit_TruthWordNum_64bit( nVars ); int i, Step,SizeOfBlock; word Temp[512]; assert( iVar < nVars ); if(iVar<=5) { for ( i = 0; i < nWords; i++ ) pInOut[i] = ((pInOut[i] & mask0[iVar]) << (1<<(iVar))) | ((pInOut[i] & ~mask0[iVar]) >> (1<<(iVar))); } else { Step = (1 << (iVar - 6)); SizeOfBlock = sizeof(word)*Step; for ( i = 0; i < nWords; i += 2*Step ) { memcpy(Temp,pInOut,SizeOfBlock); memcpy(pInOut,pInOut+Step,SizeOfBlock); memcpy(pInOut+Step,Temp,SizeOfBlock); // Temp = pInOut[i]; // pInOut[i] = pInOut[Step+i]; // pInOut[Step+i] = Temp; pInOut += 2*Step; } } } void Kit_TruthNot_64bit(word * pIn, int nVars ) { int w; for ( w = Kit_TruthWordNum_64bit(nVars)-1; w >= 0; w-- ) pIn[w] = ~pIn[w]; } void Kit_TruthCopy_64bit( word * pOut, word * pIn, int nVars ) { memcpy(pOut,pIn,Kit_TruthWordNum_64bit(nVars)*sizeof(word)); } void Kit_TruthSwapAdjacentVars_64bit( word * pInOut, int nVars, int iVar ) { int i, Step, Shift, SizeOfBlock; // word temp[256]; // to make only pInOut possible static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; int nWords = Kit_TruthWordNum_64bit( nVars ); assert( iVar < nVars - 1 ); if ( iVar < 5 ) { Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) pInOut[i] = (pInOut[i] & PMasks[iVar][0]) | ((pInOut[i] & PMasks[iVar][1]) << Shift) | ((pInOut[i] & PMasks[iVar][2]) >> Shift); } else if ( iVar > 5 ) { Step = 1 << (iVar - 6); SizeOfBlock = sizeof(word)*Step; pInOut += 2*Step; for(i=2*Step; i> 32; pInOut[i] = (pInOut[i] & 0x00000000FFFFFFFF) | temp[0]; } } } unsigned Kit_TruthSemiCanonicize_Yasha( word* pInOut, int nVars, char * pCanonPerm ) { int pStore[16]; int nWords = Kit_TruthWordNum_64bit( nVars ); int i, Temp, fChange, nOnes; unsigned uCanonPhase=0; assert( nVars <= 16 ); nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars); if ( (nOnes > nWords * 32) ) { uCanonPhase |= (1 << nVars); Kit_TruthNot_64bit( pInOut, nVars ); nOnes = nWords*64 - nOnes; } // collect the minterm counts Kit_TruthCountOnesInCofs_64bit( pInOut, nVars, pStore ); // canonicize phase for ( i = 0; i < nVars; i++ ) { if ( pStore[i] >= nOnes-pStore[i]) continue; uCanonPhase |= (1 << i); pStore[i] = nOnes-pStore[i]; Kit_TruthChangePhase_64bit( pInOut, nVars, i ); } do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[i] <= pStore[i+1] ) continue; fChange = 1; Temp = pCanonPerm[i]; pCanonPerm[i] = pCanonPerm[i+1]; pCanonPerm[i+1] = Temp; Temp = pStore[i]; pStore[i] = pStore[i+1]; pStore[i+1] = Temp; // if the polarity of variables is different, swap them if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) ) { uCanonPhase ^= (1 << i); uCanonPhase ^= (1 << (i+1)); } Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i ); } } while ( fChange ); return uCanonPhase; } unsigned Kit_TruthSemiCanonicize_Yasha1( word* pInOut, int nVars, char * pCanonPerm, int * pStore ) { int nWords = Kit_TruthWordNum_64bit( nVars ); int i, fChange, nOnes; int Temp; unsigned uCanonPhase=0; assert( nVars <= 16 ); nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars); if ( nOnes == nWords * 32 ) uCanonPhase |= (1 << (nVars+2)); else if ( (nOnes > nWords * 32) ) { uCanonPhase |= (1 << nVars); Kit_TruthNot_64bit( pInOut, nVars ); nOnes = nWords*64 - nOnes; } // collect the minterm counts Kit_TruthCountOnesInCofs_64bit( pInOut, nVars, pStore ); // canonicize phase for ( i = 0; i < nVars; i++ ) { if ( 2*pStore[i] == nOnes) { uCanonPhase |= (1 << (nVars+1)); continue; } if ( pStore[i] > nOnes-pStore[i]) continue; uCanonPhase |= (1 << i); pStore[i] = nOnes-pStore[i]; Kit_TruthChangePhase_64bit( pInOut, nVars, i ); } do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[i] <= pStore[i+1] ) continue; fChange = 1; Temp = pCanonPerm[i]; pCanonPerm[i] = pCanonPerm[i+1]; pCanonPerm[i+1] = Temp; Temp = pStore[i]; pStore[i] = pStore[i+1]; pStore[i+1] = Temp; // if the polarity of variables is different, swap them if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) ) { uCanonPhase ^= (1 << i); uCanonPhase ^= (1 << (i+1)); } Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i ); } } while ( fChange ); return uCanonPhase; } // unsigned Kit_TruthSemiCanonicize_Yasha_simple( word* pInOut, int nVars, char * pCanonPerm ) // { // unsigned uCanonPhase = 0; // int pStore[16]; // int nWords = Kit_TruthWordNum_64bit( nVars ); // int i, Temp, fChange, nOnes; // assert( nVars <= 16 ); // // nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars); // // if ( (nOnes > nWords * 32) ) // { // Kit_TruthNot_64bit( pInOut, nVars ); // nOnes = nWords*64 - nOnes; // } // // // collect the minterm counts // Kit_TruthCountOnesInCofs_64bit( pInOut, nVars, pStore ); // // // canonicize phase // for ( i = 0; i < nVars; i++ ) // { // if ( pStore[i] >= nOnes-pStore[i]) // continue; // pStore[i] = nOnes-pStore[i]; // Kit_TruthChangePhase_64bit( pInOut, nVars, i ); // } // // do { // fChange = 0; // for ( i = 0; i < nVars-1; i++ ) // { // if ( pStore[i] <= pStore[i+1] ) // continue; // fChange = 1; // // Temp = pStore[i]; // pStore[i] = pStore[i+1]; // pStore[i+1] = Temp; // // Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i ); // } // } while ( fChange ); // return uCanonPhase; // } void Kit_TruthSemiCanonicize_Yasha_simple( word* pInOut, int nVars, int * pStore ) { int nWords = Kit_TruthWordNum_64bit( nVars ); int i, Temp, fChange, nOnes; assert( nVars <= 16 ); nOnes = Kit_TruthCountOnes_64bit(pInOut, nVars); if ( (nOnes > nWords * 32) ) { Kit_TruthNot_64bit( pInOut, nVars ); nOnes = nWords*64 - nOnes; } // collect the minterm counts Kit_TruthCountOnesInCofs_64bit( pInOut, nVars, pStore ); // canonicize phase for ( i = 0; i < nVars; i++ ) { if ( pStore[i] >= nOnes-pStore[i]) continue; pStore[i] = nOnes-pStore[i]; Kit_TruthChangePhase_64bit( pInOut, nVars, i ); } do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[i] <= pStore[i+1] ) continue; fChange = 1; Temp = pStore[i]; pStore[i] = pStore[i+1]; pStore[i+1] = Temp; Kit_TruthSwapAdjacentVars_64bit( pInOut, nVars, i ); } } while ( fChange ); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/luckySwapIJ.c000066400000000000000000000104661300674244400244760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [luckySwapIJ.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Semi-canonical form computation package.] Synopsis [just for support of swap_ij() function] Author [Jake] Date [Started - September 2012] ***********************************************************************/ #include "luckyInt.h" ABC_NAMESPACE_IMPL_START void swap_ij_case1( word* f,int totalVars, int i, int j) { int e,wordsNumber,n,shift; word maskArray[45]= { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) ,ABC_CONST(0xA5A5A5A5A5A5A5A5), ABC_CONST(0x0A0A0A0A0A0A0A0A), ABC_CONST(0x5050505050505050), ABC_CONST(0xAA55AA55AA55AA55), ABC_CONST(0x00AA00AA00AA00AA), ABC_CONST(0x5500550055005500) ,ABC_CONST(0xAAAA5555AAAA5555), ABC_CONST(0x0000AAAA0000AAAA), ABC_CONST(0x5555000055550000), ABC_CONST(0xAAAAAAAA55555555), ABC_CONST(0x00000000AAAAAAAA), ABC_CONST(0x5555555500000000) ,ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030), ABC_CONST(0xCC33CC33CC33CC33), ABC_CONST(0x00CC00CC00CC00CC), ABC_CONST(0x3300330033003300) ,ABC_CONST(0xCCCC3333CCCC3333), ABC_CONST(0x0000CCCC0000CCCC), ABC_CONST(0x3333000033330000), ABC_CONST(0xCCCCCCCC33333333), ABC_CONST(0x00000000CCCCCCCC), ABC_CONST(0x3333333300000000) ,ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00), ABC_CONST(0xF0F00F0FF0F00F0F), ABC_CONST(0x0000F0F00000F0F0), ABC_CONST(0x0F0F00000F0F0000) ,ABC_CONST(0xF0F0F0F00F0F0F0F), ABC_CONST(0x00000000F0F0F0F0), ABC_CONST(0x0F0F0F0F00000000), ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) ,ABC_CONST(0xFF00FF0000FF00FF), ABC_CONST(0x00000000FF00FF00), ABC_CONST(0x00FF00FF00000000), ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) }; e = 3*((9*i - i*i -2)/2 + j); // Exact formula for index in maskArray wordsNumber = Kit_TruthWordNum_64bit(totalVars); shift = (1<> shift); } // "width" - how many "Words" in a row have "1s" (or "0s")in position "i" // wi - width of i // wj - width of j // wwi = 2*wi; wwj = 2*wj; void swap_ij_case2( word* f,int totalVars, int i, int j) { word mask[] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; word temp; int x,y,wj; int WORDS_IN_TT = Kit_TruthWordNum_64bit(totalVars); // int forShift = ((Word)1)<> forShift); f[x] = ((f[x])&(~mask[i])) + ((temp&(~mask[i])) << forShift); } } void swap_ij_case3( word* f,int totalVars, int i, int j) { int x,y,wwi,wwj,shift; int WORDS_IN_TT; int SizeOfBlock; word* temp; wwi = 1 << (i - 5); wwj = 1 << (j - 5); shift = (wwj - wwi)/2; WORDS_IN_TT = Kit_TruthWordNum_64bit(totalVars); SizeOfBlock = sizeof(word)*wwi/2; temp = (word *)malloc(SizeOfBlock); for(y=wwj/2; yvarJ) swap_ij( f,totalVars,varJ,varI); else if((varI <= 4) && (varJ <= 5)) swap_ij_case1(f,totalVars, varI, varJ); else if((varI <= 5) && (varJ > 5)) swap_ij_case2(f,totalVars, varI, varJ); else if((varI > 5) && (varJ > 5)) swap_ij_case3(f,totalVars,varI,varJ); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/lucky/module.make000066400000000000000000000003411300674244400242400ustar00rootroot00000000000000SRC += src/bool/lucky/lucky.c \ src/bool/lucky/luckyFast16.c \ src/bool/lucky/luckyFast6.c \ src/bool/lucky/luckyRead.c \ src/bool/lucky/luckySimple.c \ src/bool/lucky/luckySwapIJ.c \ src/bool/lucky/luckySwap.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rpo/000077500000000000000000000000001300674244400215675ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rpo/literal.h000066400000000000000000000217351300674244400234040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [literal.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [RPO] Synopsis [Literal structure] Author [Mayler G. A. Martins / Vinicius Callegaro] Affiliation [UFRGS] Date [Ver. 1.0. Started - May 08, 2013.] Revision [$Id: literal.h,v 1.00 2013/05/08 00:00:00 mgamartins Exp $] ***********************************************************************/ #ifndef ABC__bool__rpo__literal_h #define ABC__bool__rpo__literal_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include "bool/kit/kit.h" #include "misc/vec/vec.h" #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // associations typedef enum { LIT_NONE = 0, // 0: unknown LIT_AND, // 1: AND association LIT_OR, // 2: OR association LIT_XOR // 3: XOR association (not used yet) } Operator_t; typedef struct Literal_t_ Literal_t; struct Literal_t_ { unsigned * transition; unsigned * function; Vec_Str_t * expression; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Compute the positive transition] Description [The inputs are a function, the number of variables and a variable index and the output is a function] SideEffects [Should this function be in kitTruth.c ?] SeeAlso [] // ***********************************************************************/ static inline void Lit_TruthPositiveTransition( unsigned * pIn, unsigned * pOut, int nVars, int varIdx ) { unsigned * cof0 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) ); unsigned * cof1 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) ); unsigned * ncof0; Kit_TruthCofactor0New(cof0, pIn,nVars,varIdx); Kit_TruthCofactor1New(cof1, pIn,nVars,varIdx); ncof0 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) ); Kit_TruthNot(ncof0,cof0,nVars); Kit_TruthAnd(pOut,ncof0,cof1, nVars); ABC_FREE(cof0); ABC_FREE(ncof0); ABC_FREE(cof1); } /**Function************************************************************* Synopsis [Compute the negative transition] Description [The inputs are a function, the number of variables and a variable index and the output is a function] SideEffects [Should this function be in kitTruth.c ?] SeeAlso [] ***********************************************************************/ static inline void Lit_TruthNegativeTransition( unsigned * pIn, unsigned * pOut, int nVars, int varIdx ) { unsigned * cof0 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) ); unsigned * cof1 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) ); unsigned * ncof1; Kit_TruthCofactor0New(cof0, pIn,nVars,varIdx); Kit_TruthCofactor1New(cof1, pIn,nVars,varIdx); ncof1 = ABC_ALLOC (unsigned, Kit_TruthWordNum(nVars) ); Kit_TruthNot(ncof1,cof1,nVars); Kit_TruthAnd(pOut,ncof1,cof0,nVars); ABC_FREE(cof0); ABC_FREE(cof1); ABC_FREE(ncof1); } /**Function************************************************************* Synopsis [Create a literal given a polarity ] Description [The inputs are the function, index and its polarity and a the output is a literal] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Literal_t* Lit_Alloc(unsigned* pTruth, int nVars, int varIdx, char pol) { unsigned * transition; unsigned * function; Vec_Str_t * exp; Literal_t* lit; assert(pol == '+' || pol == '-'); transition = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); if (pol == '+') { Lit_TruthPositiveTransition(pTruth, transition, nVars, varIdx); } else { Lit_TruthNegativeTransition(pTruth, transition, nVars, varIdx); } if (!Kit_TruthIsConst0(transition,nVars)) { function = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); Kit_TruthIthVar(function, nVars, varIdx); //Abc_Print(-2, "Allocating function %X %d %c \n", *function, varIdx, pol); exp = Vec_StrAlloc(5); if (pol == '-') { Kit_TruthNot(function, function, nVars); Vec_StrPutC(exp, '!'); } Vec_StrPutC(exp, (char)('a' + varIdx)); Vec_StrPutC(exp, '\0'); lit = ABC_ALLOC(Literal_t, 1); lit->function = function; lit->transition = transition; lit->expression = exp; return lit; } else { ABC_FREE(transition); // free the function. return NULL; } } /**Function************************************************************* Synopsis [Group 2 literals using AND or OR] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Literal_t* Lit_GroupLiterals(Literal_t* lit1, Literal_t* lit2, Operator_t op, int nVars) { unsigned * newFunction = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); unsigned * newTransition = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); Vec_Str_t * newExp = Vec_StrAlloc(lit1->expression->nSize + lit2->expression->nSize + 3); Literal_t* newLiteral; char opChar = '%'; switch (op) { case LIT_AND: { //Abc_Print(-2, "Grouping AND %X %X \n", *lit1->function, *lit2->function); Kit_TruthAnd(newFunction, lit1->function, lit2->function, nVars); opChar = '*'; break; } case LIT_OR: { //Abc_Print(-2, "Grouping OR %X %X \n", *lit1->function, *lit2->function); Kit_TruthOr(newFunction, lit1->function, lit2->function, nVars); opChar = '+'; break; } default: { Abc_Print(-2, "Lit_GroupLiterals with op not defined."); //TODO Call ABC Abort } } Kit_TruthOr(newTransition, lit1->transition, lit2->transition, nVars); // create a new expression. Vec_StrPutC(newExp, '('); Vec_StrAppend(newExp, lit1->expression->pArray); //Vec_StrPop(newExp); // pop the \0 Vec_StrPutC(newExp, opChar); Vec_StrAppend(newExp, lit2->expression->pArray); //Vec_StrPop(newExp); // pop the \0 Vec_StrPutC(newExp, ')'); Vec_StrPutC(newExp, '\0'); newLiteral = ABC_ALLOC(Literal_t, 1); newLiteral->function = newFunction; newLiteral->transition = newTransition; newLiteral->expression = newExp; return newLiteral; } /**Function************************************************************* Synopsis [Create a const literal ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Literal_t* Lit_CreateLiteralConst(unsigned* pTruth, int nVars, int constant) { Vec_Str_t * exp = Vec_StrAlloc(3); Literal_t* lit; Vec_StrPutC(exp, (char)('0' + constant)); Vec_StrPutC(exp, '\0'); lit = ABC_ALLOC(Literal_t, 1); lit->expression = exp; lit->function = pTruth; lit->transition = pTruth; // wrong but no effect ### return lit; } static inline Literal_t* Lit_Copy(Literal_t* lit, int nVars) { Literal_t* newLit = ABC_ALLOC(Literal_t,1); newLit->function = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); Kit_TruthCopy(newLit->function,lit->function,nVars); newLit->transition = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); Kit_TruthCopy(newLit->transition,lit->transition,nVars); newLit->expression = Vec_StrDup(lit->expression); // Abc_Print(-2,"Copying: %s\n",newLit->expression->pArray); return newLit; } static inline void Lit_PrintTT(unsigned* tt, int nVars) { int w; for(w=nVars-1; w>=0; w--) { Abc_Print(-2, "%08X", tt[w]); } } static inline void Lit_PrintExp(Literal_t* lit) { Abc_Print(-2, "%s", lit->expression->pArray); } /**Function************************************************************* Synopsis [Delete the literal ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Lit_Free(Literal_t * lit) { if(lit == NULL) { return; } // Abc_Print(-2,"Freeing: %s\n",lit->expression->pArray); ABC_FREE(lit->function); ABC_FREE(lit->transition); Vec_StrFree(lit->expression); ABC_FREE(lit); } ABC_NAMESPACE_HEADER_END #endif /* LITERAL_H */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rpo/module.make000066400000000000000000000000311300674244400237050ustar00rootroot00000000000000SRC += src/bool/rpo/rpo.cberkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rpo/rpo.c000066400000000000000000000261011300674244400225330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rpo.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [RPO] Synopsis [Performs read polarity once factorization.] Author [Mayler G. A. Martins / Vinicius Callegaro] Affiliation [UFRGS] Date [Ver. 1.0. Started - May 08, 2013.] Revision [$Id: rpo.c,v 1.00 2013/05/08 00:00:00 mgamartins Exp $] ***********************************************************************/ #include #include "literal.h" #include "rpo.h" #include "bool/kit/kit.h" #include "misc/util/abc_global.h" #include "misc/vec/vec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Rpo_Man_t_ Rpo_Man_t; struct Rpo_Man_t_ { unsigned * target; int nVars; Literal_t ** literals; int nLits; int nLitsMax; Rpo_LCI_Edge_t* lci; int nLCIElems; int thresholdMax; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Check if two literals are AND-grouped] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rpo_CheckANDGroup(Literal_t* lit1, Literal_t* lit2, int nVars) { unsigned* notLit1Func = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); unsigned* notLit2Func = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); unsigned* and1; unsigned* and2; int isZero; Kit_TruthNot(notLit1Func, lit1->function, nVars); Kit_TruthNot(notLit2Func, lit2->function, nVars); and1 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); and2 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); Kit_TruthAnd(and1, lit1->transition, notLit2Func, nVars); isZero = Kit_TruthIsConst0(and1, nVars); if (isZero) { Kit_TruthAnd(and2, lit2->transition, notLit1Func, nVars); isZero = Kit_TruthIsConst0(and2, nVars); } ABC_FREE(notLit1Func); ABC_FREE(notLit2Func); ABC_FREE(and1); ABC_FREE(and2); return isZero; } /**Function************************************************************* Synopsis [Check if two literals are AND-grouped] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rpo_CheckORGroup(Literal_t* lit1, Literal_t* lit2, int nVars) { unsigned* and1 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); unsigned* and2 = ABC_ALLOC(unsigned, Kit_TruthWordNum(nVars)); int isZero; Kit_TruthAnd(and1, lit1->transition, lit2->function, nVars); isZero = Kit_TruthIsConst0(and1, nVars); if (isZero) { Kit_TruthAnd(and2, lit2->transition, lit1->function, nVars); isZero = Kit_TruthIsConst0(and2, nVars); } ABC_FREE(and1); ABC_FREE(and2); return isZero; } Rpo_LCI_Edge_t* Rpo_CreateEdge(Operator_t op, int i, int j, int* vertexDegree) { Rpo_LCI_Edge_t* edge = ABC_ALLOC(Rpo_LCI_Edge_t, 1); edge->connectionType = op; edge->idx1 = i; edge->idx2 = j; edge->visited = 0; vertexDegree[i]++; vertexDegree[j]++; return edge; } int Rpo_computeMinEdgeCost(Rpo_LCI_Edge_t** edges, int edgeCount, int* vertexDegree) { int minCostIndex = -1; int minVertexIndex = -1; unsigned int minCost = ~0; Rpo_LCI_Edge_t* edge; unsigned int edgeCost; int minVertex; int i; for (i = 0; i < edgeCount; ++i) { edge = edges[i]; if (!edge->visited) { edgeCost = vertexDegree[edge->idx1] + vertexDegree[edge->idx2]; minVertex = (edge->idx1 < edge->idx2) ? edge->idx1 : edge->idx2; if (edgeCost < minCost) { minCost = edgeCost; minCostIndex = i; minVertexIndex = minVertex; } else if ((edgeCost == minCost) && minVertex < minVertexIndex) { minCost = edgeCost; minCostIndex = i; minVertexIndex = minVertex; } } } return minCostIndex; } void Rpo_PrintEdge(Rpo_LCI_Edge_t* edge) { Abc_Print(-2, "Edge (%d,%d)/%d\n", edge->idx1, edge->idx2, edge->connectionType); } /**Function************************************************************* Synopsis [Test] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Literal_t* Rpo_Factorize(unsigned* target, int nVars, int nThreshold, int verbose) { int nLitCap = nVars * 2; int nLit = 0; int w; Literal_t** vecLit; Literal_t* lit; Literal_t* result; int thresholdCount = 0; if (Kit_TruthIsConst0(target, nVars)) { return Lit_CreateLiteralConst(target, nVars, 0); } else if (Kit_TruthIsConst1(target, nVars)) { return Lit_CreateLiteralConst(target, nVars, 1); } // if (nThreshold == -1) { // nThreshold = nLitCap + nVars; // } if (verbose) { Abc_Print(-2, "Target: "); Lit_PrintTT(target, nVars); Abc_Print(-2, "\n"); } vecLit = ABC_ALLOC(Literal_t*, nLitCap); for (w = nVars - 1; w >= 0; w--) { lit = Lit_Alloc(target, nVars, w, '+'); if (lit != NULL) { vecLit[nLit] = lit; nLit++; } lit = Lit_Alloc(target, nVars, w, '-'); if (lit != NULL) { vecLit[nLit] = lit; nLit++; } } if (verbose) { Abc_Print(-2, "Allocated %d literal clusters\n", nLit); } result = Rpo_Recursion(target, vecLit, nLit, nLit, nVars, &thresholdCount, nThreshold, verbose); //freeing the memory for (w = 0; w < nLit; ++w) { Lit_Free(vecLit[w]); } ABC_FREE(vecLit); return result; } Literal_t* Rpo_Recursion(unsigned* target, Literal_t** vecLit, int nLit, int nLitCount, int nVars, int* thresholdCount, int thresholdMax, int verbose) { int i, j, k; Literal_t* copyResult; int* vertexDegree; int v; int edgeSize; Rpo_LCI_Edge_t** edges; int edgeCount = 0; int isAnd; int isOr; Rpo_LCI_Edge_t* edge; Literal_t* result = NULL; int edgeIndex; int minLitIndex; int maxLitIndex; Literal_t* oldLit1; Literal_t* oldLit2; Literal_t* newLit; *thresholdCount = *thresholdCount + 1; if (*thresholdCount == thresholdMax) { return NULL; } if (verbose) { Abc_Print(-2, "Entering recursion %d\n", *thresholdCount); } // verify if solution is the target or not if (nLitCount == 1) { if (verbose) { Abc_Print(-2, "Checking solution: "); } for (k = 0; k < nLit; ++k) { if (vecLit[k] != NULL) { if (Kit_TruthIsEqual(target, vecLit[k]->function, nVars)) { copyResult = Lit_Copy(vecLit[k], nVars); if (verbose) { Abc_Print(-2, "FOUND!\n", thresholdCount); } thresholdCount = 0; //?? return copyResult; } } } if (verbose) { Abc_Print(-2, "FAILED!\n", thresholdCount); } return NULL; } vertexDegree = ABC_ALLOC(int, nLit); // if(verbose) { // Abc_Print(-2,"Allocating vertexDegree...\n"); // } for (v = 0; v < nLit; v++) { vertexDegree[v] = 0; } // building edges edgeSize = (nLit * (nLit - 1)) / 2; edges = ABC_ALLOC(Rpo_LCI_Edge_t*, edgeSize); if (verbose) { Abc_Print(-2, "Creating Edges: \n"); } for (i = 0; i < nLit; ++i) { if (vecLit[i] == NULL) { continue; } for (j = i; j < nLit; ++j) { if (vecLit[j] == NULL) { continue; } isAnd = Rpo_CheckANDGroup(vecLit[i], vecLit[j], nVars); isOr = Rpo_CheckORGroup(vecLit[i], vecLit[j], nVars); if (isAnd) { if (verbose) { Abc_Print(-2, "Grouped: "); Lit_PrintExp(vecLit[j]); Abc_Print(-2, " AND "); Lit_PrintExp(vecLit[i]); Abc_Print(-2, "\n"); } // add edge edge = Rpo_CreateEdge(LIT_AND, i, j, vertexDegree); edges[edgeCount++] = edge; } if (isOr) { if (verbose) { Abc_Print(-2, "Grouped: "); Lit_PrintExp(vecLit[j]); Abc_Print(-2, " OR "); Lit_PrintExp(vecLit[i]); Abc_Print(-2, "\n"); } // add edge edge = Rpo_CreateEdge(LIT_OR, i, j, vertexDegree); edges[edgeCount++] = edge; } } } if (verbose) { Abc_Print(-2, "%d edges created.\n", edgeCount); } //traverse the edges, grouping new Literal Clusters do { edgeIndex = Rpo_computeMinEdgeCost(edges, edgeCount, vertexDegree); if (edgeIndex < 0) { if (verbose) { Abc_Print(-2, "There is no edges unvisited... Exiting recursion.\n"); //exit(-1); } break; //return NULL; // the graph does not have unvisited edges } edge = edges[edgeIndex]; edge->visited = 1; //Rpo_PrintEdge(edge); minLitIndex = (edge->idx1 < edge->idx2) ? edge->idx1 : edge->idx2; maxLitIndex = (edge->idx1 > edge->idx2) ? edge->idx1 : edge->idx2; oldLit1 = vecLit[minLitIndex]; oldLit2 = vecLit[maxLitIndex]; newLit = Lit_GroupLiterals(oldLit1, oldLit2, (Operator_t)edge->connectionType, nVars); vecLit[minLitIndex] = newLit; vecLit[maxLitIndex] = NULL; if (verbose) { Abc_Print(-2, "New Literal Cluster found: "); Lit_PrintExp(newLit); Abc_Print(-2, " -> "); Lit_PrintTT(newLit->function, nVars); Abc_Print(-2, "\n"); } result = Rpo_Recursion(target, vecLit, nLit, (nLitCount - 1), nVars, thresholdCount, thresholdMax, verbose); //independent of result, free the newLit and restore the vector of Literal Clusters Lit_Free(newLit); vecLit[minLitIndex] = oldLit1; vecLit[maxLitIndex] = oldLit2; if (*thresholdCount == thresholdMax) { break; } } while (result == NULL); //freeing memory // if(verbose) { // Abc_Print(-2,"Freeing vertexDegree...\n"); // } ABC_FREE(vertexDegree); for (i = 0; i < edgeCount; ++i) { //Abc_Print(-2, "%p ", edges[i]); ABC_FREE(edges[i]); } ABC_FREE(edges); return result; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rpo/rpo.h000066400000000000000000000041161300674244400225420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rpo.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [RPO] Synopsis [Rpo Header] Author [Mayler G. A. Martins / Vinicius Callegaro] Affiliation [UFRGS] Date [Ver. 1.0. Started - May 08, 2013.] Revision [$Id: rpo.h,v 1.00 2013/05/08 00:00:00 mgamartins Exp $] ***********************************************************************/ #ifndef ABC__bool__rpo__rpo_h #define ABC__bool__rpo__rpo_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "literal.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Rpo_LCI_Edge_t_ Rpo_LCI_Edge_t; struct Rpo_LCI_Edge_t_ { unsigned long visited : 1; unsigned long connectionType : 2; unsigned long reserved : 1; unsigned long idx1 : 30; unsigned long idx2 : 30; }; void Rpo_PrintEdge(Rpo_LCI_Edge_t* edge); int Rpo_CheckANDGroup(Literal_t* lit1, Literal_t* lit2, int nVars); int Rpo_CheckORGroup(Literal_t* lit1, Literal_t* lit2, int nVars); Literal_t* Rpo_Factorize(unsigned* target, int nVars, int nThreshold, int verbose); Literal_t* Rpo_Recursion(unsigned* target, Literal_t** vecLit, int nLit, int nLitCount, int nVars, int* thresholdCount, int thresholdMax, int verbose); Rpo_LCI_Edge_t* Rpo_CreateEdge(Operator_t op, int i, int j, int* vertexDegree); int Rpo_computeMinEdgeCost(Rpo_LCI_Edge_t** edges, int edgeCount, int* vertexDegree); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rsb/000077500000000000000000000000001300674244400215555ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rsb/module.make000066400000000000000000000000671300674244400237040ustar00rootroot00000000000000SRC += src/bool/rsb/rsbDec6.c \ src/bool/rsb/rsbMan.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rsb/rsb.h000066400000000000000000000047721300674244400225260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rsb.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table based resubstitution.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rsb.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__bool_Rsb_h #define ABC__bool_Rsb_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Rsb_Man_t_ Rsb_Man_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== rsbMan.c ==========================================================*/ extern Rsb_Man_t * Rsb_ManAlloc( int nLeafMax, int nDivMax, int nDecMax, int fVerbose ); extern void Rsb_ManFree( Rsb_Man_t * p ); extern Vec_Int_t * Rsb_ManGetFanins( Rsb_Man_t * p ); extern Vec_Int_t * Rsb_ManGetFaninsOld( Rsb_Man_t * p ); /*=== rsbDec6.c ==========================================================*/ extern int Rsb_ManPerformResub6( Rsb_Man_t * p, int nVars, word uTruth, Vec_Wrd_t * vDivTruths, word * puTruth0, word * puTruth1, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rsb/rsbDec6.c000066400000000000000000000615241300674244400232210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rsbDec6.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table-based resubstitution.] Synopsis [Implementation of the algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rsbDec6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rsbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Rsb_DecTry0( word c ) { return (unsigned)(c != 0); } static inline unsigned Rsb_DecTry1( word c, word f1 ) { return (Rsb_DecTry0(c&f1) << 1) | Rsb_DecTry0(c&~f1); } static inline unsigned Rsb_DecTry2( word c, word f1, word f2 ) { return (Rsb_DecTry1(c&f2, f1) << 2) | Rsb_DecTry1(c&~f2, f1); } static inline unsigned Rsb_DecTry3( word c, word f1, word f2, word f3 ) { return (Rsb_DecTry2(c&f3, f1, f2) << 4) | Rsb_DecTry2(c&~f3, f1, f2); } static inline unsigned Rsb_DecTry4( word c, word f1, word f2, word f3, word f4 ) { return (Rsb_DecTry3(c&f4, f1, f2, f3) << 8) | Rsb_DecTry3(c&~f4, f1, f2, f3); } static inline unsigned Rsb_DecTry5( word c, word f1, word f2, word f3, word f4, word f5 ) { return (Rsb_DecTry4(c&f5, f1, f2, f3, f4) << 16) | Rsb_DecTry4(c&~f5, f1, f2, f3, f4); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Rsb_DecTryCex( word * g, int iCexA, int iCexB ) { return Abc_TtGetBit(g, iCexA) == Abc_TtGetBit(g, iCexB); } static inline void Rsb_DecVerifyCex( word * f, word ** g, int nGs, int iCexA, int iCexB ) { int i; // f distinquished it if ( Rsb_DecTryCex( f, iCexA, iCexB ) ) printf( "Verification of CEX has failed: f(A) == f(B)!!!\n" ); // g do not distinguish it for ( i = 0; i < nGs; i++ ) if ( !Rsb_DecTryCex( g[i], iCexA, iCexB ) ) printf( "Verification of CEX has failed: g[%d](A) != g[%d](B)!!!\n", i, i ); } static inline void Rsb_DecRecordCex( word ** g, int nGs, int iCexA, int iCexB, word * pCexes, int nCexes ) { int i; assert( nCexes < 64 ); for ( i = 0; i < nGs; i++ ) if ( Rsb_DecTryCex(g[i], iCexA, iCexB) ) Abc_TtSetBit( pCexes + i, nCexes ); } /**Function************************************************************* Synopsis [Checks decomposability of f with divisors g.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Rsb_DecCofactor( word ** g, int nGs, int w, int iMint ) { int i; word Cof = ~(word)0; for ( i = 0; i < nGs; i++ ) Cof &= ((iMint >> i) & 1) ? g[i][w] : ~g[i][w]; return Cof; } unsigned Rsb_DecCheck( int nVars, word * f, word ** g, int nGs, unsigned * pPat, int * pCexA, int * pCexB ) { word CofA, CofB; int nWords = Abc_TtWordNum( nVars ); int w, k, iMint, iShift = ( 1 << nGs ); unsigned uMask = (~(unsigned)0) >> (32-iShift); unsigned uTotal = 0; assert( nGs > 0 && nGs < 5 ); for ( w = 0; w < nWords; w++ ) { // generate decomposition pattern if ( nGs == 1 ) pPat[w] = Rsb_DecTry2( ~(word)0, g[0][w], f[w] ); else if ( nGs == 2 ) pPat[w] = Rsb_DecTry3( ~(word)0, g[0][w], g[1][w], f[w] ); else if ( nGs == 3 ) pPat[w] = Rsb_DecTry4( ~(word)0, g[0][w], g[1][w], g[2][w], f[w] ); else if ( nGs == 4 ) pPat[w] = Rsb_DecTry5( ~(word)0, g[0][w], g[1][w], g[2][w], g[3][w], f[w] ); // check if it is consistent iMint = Abc_Tt6FirstBit( (pPat[w] >> iShift) & pPat[w] & uMask ); if ( iMint >= 0 ) { // generate a cex CofA = Rsb_DecCofactor( g, nGs, w, iMint ); assert( (~f[w] & CofA) && (f[w] & CofA) ); *pCexA = w * 64 + Abc_Tt6FirstBit( ~f[w] & CofA ); *pCexB = w * 64 + Abc_Tt6FirstBit( f[w] & CofA ); return 0; } uTotal |= pPat[w]; if ( w == 0 ) continue; // check if it is consistent with other patterns seen so far iMint = Abc_Tt6FirstBit( (uTotal >> iShift) & uTotal & uMask ); if ( iMint == -1 ) continue; // find an overlap and generate a cex for ( k = 0; k < w; k++ ) { iMint = Abc_Tt6FirstBit( ((pPat[k] | pPat[w]) >> iShift) & (pPat[k] | pPat[w]) & uMask ); if ( iMint == -1 ) continue; CofA = Rsb_DecCofactor( g, nGs, k, iMint ); CofB = Rsb_DecCofactor( g, nGs, w, iMint ); if ( (~f[k] & CofA) && (f[w] & CofB) ) { *pCexA = k * 64 + Abc_Tt6FirstBit( ~f[k] & CofA ); *pCexB = w * 64 + Abc_Tt6FirstBit( f[w] & CofB ); } else { assert( (f[k] & CofA) && (~f[w] & CofB) ); *pCexA = k * 64 + Abc_Tt6FirstBit( f[k] & CofA ); *pCexB = w * 64 + Abc_Tt6FirstBit( ~f[w] & CofB ); } return 0; } } return uTotal; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rsb_DecPrintTable( word * pCexes, int nGs, int nGsAll, Vec_Int_t * vTries ) { int pCands[16], nCands; int i, c, Cand, iStart = 0; if ( Vec_IntSize(vTries) == 0 ) return; // printf( "\n" ); for ( i = 0; i < 4; i++ ) printf( " " ); printf( " " ); for ( i = 0; i < nGs; i++ ) printf( "%d", (i % 100) / 10 ); printf( "|" ); for ( ; i < nGsAll; i++ ) printf( "%d", (i % 100) / 10 ); printf( "\n" ); for ( i = 0; i < 4; i++ ) printf( " " ); printf( " " ); for ( i = 0; i < nGs; i++ ) printf( "%d", i % 10 ); printf( "|" ); for ( ; i < nGsAll; i++ ) printf( "%d", i % 10 ); printf( "\n" ); printf( "\n" ); for ( c = 0; iStart < Vec_IntSize(vTries); c++ ) { // collect candidates for ( i = 0; i < 4; i++ ) pCands[i] = -1; nCands = 0; Vec_IntForEachEntryStart( vTries, Cand, i, iStart ) if ( Cand == -1 ) { iStart = i + 1; break; } else pCands[nCands++] = Cand; assert( nCands <= 4 ); // print them for ( i = 0; i < 4; i++ ) if ( pCands[i] >= 0 ) printf( "%4d", pCands[i] ); else printf( " " ); // print the bit-string printf( " " ); for ( i = 0; i < nGs; i++ ) printf( "%c", Abc_TtGetBit( pCexes + i, c ) ? '.' : '+' ); printf( "|" ); for ( ; i < nGsAll; i++ ) printf( "%c", Abc_TtGetBit( pCexes + i, c ) ? '.' : '+' ); printf( " %3d\n", c ); } printf( "\n" ); // write the number of ones for ( i = 0; i < 4; i++ ) printf( " " ); printf( " " ); for ( i = 0; i < nGs; i++ ) printf( "%d", Abc_TtCountOnes(pCexes[i]) / 10 ); printf( "|" ); for ( ; i < nGsAll; i++ ) printf( "%d", Abc_TtCountOnes(pCexes[i]) / 10 ); printf( "\n" ); for ( i = 0; i < 4; i++ ) printf( " " ); printf( " " ); for ( i = 0; i < nGs; i++ ) printf( "%d", Abc_TtCountOnes(pCexes[i]) % 10 ); printf( "|" ); for ( ; i < nGsAll; i++ ) printf( "%d", Abc_TtCountOnes(pCexes[i]) % 10 ); printf( "\n" ); printf( "\n" ); } /**Function************************************************************* Synopsis [Init ] Description [Returns the numbers of the decomposition functions and the truth table of a function up to 4 variables.] SideEffects [] SeeAlso [] ***********************************************************************/ int Rsb_DecInitCexes( int nVars, word * f, word ** g, int nGs, int nGsAll, word * pCexes, Vec_Int_t * vTries ) { int nWords = Abc_TtWordNum( nVars ); int ValueB = Abc_TtGetBit( f, 0 ); int ValueE = Abc_TtGetBit( f, 64*nWords-1 ); int iCexT0, iCexT1, iCexF0, iCexF1; iCexT0 = ValueB ? 0 : Abc_TtFindFirstBit( f, nVars ); iCexT1 = ValueE ? 64*nWords-1 : Abc_TtFindLastBit( f, nVars ); iCexF0 = !ValueB ? 0 : Abc_TtFindFirstZero( f, nVars ); iCexF1 = !ValueE ? 64*nWords-1 : Abc_TtFindLastZero( f, nVars ); assert( !Rsb_DecTryCex( f, iCexT0, iCexF0 ) ); assert( !Rsb_DecTryCex( f, iCexT0, iCexF1 ) ); assert( !Rsb_DecTryCex( f, iCexT1, iCexF0 ) ); assert( !Rsb_DecTryCex( f, iCexT1, iCexF1 ) ); Rsb_DecRecordCex( g, nGsAll, iCexT0, iCexF0, pCexes, 0 ); Rsb_DecRecordCex( g, nGsAll, iCexT0, iCexF1, pCexes, 1 ); Rsb_DecRecordCex( g, nGsAll, iCexT1, iCexF0, pCexes, 2 ); Rsb_DecRecordCex( g, nGsAll, iCexT1, iCexF1, pCexes, 3 ); if ( vTries ) { Vec_IntPush( vTries, -1 ); Vec_IntPush( vTries, -1 ); Vec_IntPush( vTries, -1 ); Vec_IntPush( vTries, -1 ); } return 4; } /**Function************************************************************* Synopsis [Finds a setset of gs to decompose f.] Description [Returns the numbers of the decomposition functions and the truth table of a function up to 4 variables.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Rsb_DecPerformInt( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, int nGsAll, int fFindAll ) { word * pCexes = Vec_WrdArray(p->vCexes); unsigned * pPat = (unsigned *)Vec_IntArray(p->vDecPats); /* The following filtering hueristic can be used: after the first round (if there is more than 5 cexes, remove all the divisors, except fanins of the node This should lead to a speadup without sacrifying quality. Another idea is to precompute several counter-examples like the first and last 0 and 1 mints of the function which yields 4 cexes. */ word * pDivs[16]; unsigned uTruth = 0; int i, k, j, n, iCexA, iCexB, nCexes = 0; memset( pCexes, 0, sizeof(word) * nGsAll ); Vec_IntClear( p->vTries ); // populate the counter-examples with the three most obvious // nCexes = Rsb_DecInitCexes( nVars, f, g, nGs, nGsAll, pCexes, vTries ); // start by checking each function p->vFanins->nSize = 1; for ( i = 0; i < nGs; i++ ) { if ( pCexes[i] ) continue; pDivs[0] = g[i]; p->vFanins->pArray[0] = i; uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB ); if ( uTruth ) { if ( fFindAll ) { uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 1 ); Kit_DsdPrintFromTruth( &uTruth, 1 ); printf( " " ); Vec_IntPrint(p->vFanins); continue; } else return uTruth; } if ( nCexes == 64 ) return 0; Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB ); Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ ); if ( !p->fVerbose ) continue; Vec_IntPush( p->vTries, i ); Vec_IntPush( p->vTries, -1 ); } if ( p->nDecMax == 1 ) return 0; // continue by checking pairs p->vFanins->nSize = 2; for ( i = 1; i < nGs; i++ ) for ( k = 0; k < i; k++ ) { if ( pCexes[i] & pCexes[k] ) continue; pDivs[0] = g[i]; p->vFanins->pArray[0] = i; pDivs[1] = g[k]; p->vFanins->pArray[1] = k; uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB ); if ( uTruth ) { if ( fFindAll ) { uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 2 ); Kit_DsdPrintFromTruth( &uTruth, 2 ); printf( " " ); Vec_IntPrint(p->vFanins); continue; } else return uTruth; } if ( nCexes == 64 ) return 0; Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB ); Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ ); if ( !p->fVerbose ) continue; Vec_IntPush( p->vTries, i ); Vec_IntPush( p->vTries, k ); Vec_IntPush( p->vTries, -1 ); } if ( p->nDecMax == 2 ) return 0; // continue by checking triples p->vFanins->nSize = 3; for ( i = 2; i < nGs; i++ ) for ( k = 1; k < i; k++ ) for ( j = 0; j < k; j++ ) { if ( pCexes[i] & pCexes[k] & pCexes[j] ) continue; pDivs[0] = g[i]; p->vFanins->pArray[0] = i; pDivs[1] = g[k]; p->vFanins->pArray[1] = k; pDivs[2] = g[j]; p->vFanins->pArray[2] = j; uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB ); if ( uTruth ) { if ( fFindAll ) { uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 3 ); Kit_DsdPrintFromTruth( &uTruth, 3 ); printf( " " ); Vec_IntPrint(p->vFanins); continue; } else return uTruth; } if ( nCexes == 64 ) return 0; Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB ); Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ ); if ( !p->fVerbose ) continue; Vec_IntPush( p->vTries, i ); Vec_IntPush( p->vTries, k ); Vec_IntPush( p->vTries, j ); Vec_IntPush( p->vTries, -1 ); } if ( p->nDecMax == 3 ) return 0; // continue by checking quadras p->vFanins->nSize = 4; for ( i = 3; i < nGs; i++ ) for ( k = 2; k < i; k++ ) for ( j = 1; j < k; j++ ) for ( n = 0; n < j; n++ ) { if ( pCexes[i] & pCexes[k] & pCexes[j] & pCexes[n] ) continue; pDivs[0] = g[i]; p->vFanins->pArray[0] = i; pDivs[1] = g[k]; p->vFanins->pArray[1] = k; pDivs[2] = g[j]; p->vFanins->pArray[2] = j; pDivs[3] = g[n]; p->vFanins->pArray[3] = n; uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFanins), pPat, &iCexA, &iCexB ); if ( uTruth ) { if ( fFindAll ) { uTruth = (unsigned)Abc_Tt6Stretch( (word)uTruth, 4 ); Kit_DsdPrintFromTruth( &uTruth, 4 ); printf( " " ); Vec_IntPrint(p->vFanins); continue; } else return uTruth; } if ( nCexes == 64 ) return 0; Rsb_DecVerifyCex( f, pDivs, Vec_IntSize(p->vFanins), iCexA, iCexB ); Rsb_DecRecordCex( g, nGsAll, iCexA, iCexB, pCexes, nCexes++ ); if ( !p->fVerbose ) continue; Vec_IntPush( p->vTries, i ); Vec_IntPush( p->vTries, k ); Vec_IntPush( p->vTries, j ); Vec_IntPush( p->vTries, n ); Vec_IntPush( p->vTries, -1 ); } // printf( "%d ", nCexes ); if ( p->nDecMax == 4 ) return 0; return 0; } /**Function************************************************************* Synopsis [Verifies 4-input decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rsb_DecPrintFunc( Rsb_Man_t * p, unsigned Truth4, word * f, word ** ppGs, int nGs, int nVarsAll ) { int nVars = Vec_IntSize(p->vFanins); word Copy = Truth4; word wOn = Abc_Tt6Stretch( Copy >> (1 << nVars), nVars ); word wOnDc = ~Abc_Tt6Stretch( Copy, nVars ); word wIsop = Abc_Tt6Isop( wOn, wOnDc, nVars, NULL ); int i; printf( "Offset : " ); Abc_TtPrintBinary( &Copy, nVars ); //printf( "\n" ); Copy >>= ((word)1 << nVars); printf( "Onset : " ); Abc_TtPrintBinary( &Copy, nVars ); //printf( "\n" ); printf( "Result : " ); Abc_TtPrintBinary( &wIsop, nVars ); //printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&wIsop, nVars ); printf( "\n" ); // print functions printf( "Func : " ); Abc_TtPrintBinary( f, nVarsAll ); //printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)f, nVarsAll ); printf( "\n" ); for ( i = 0; i < nGs; i++ ) { printf( "Div%3d : ", i ); Kit_DsdPrintFromTruth( (unsigned *)ppGs[i], nVarsAll ); printf( "\n" ); } printf( "Solution : " ); for ( i = 0; i < Vec_IntSize(p->vFanins); i++ ) printf( "%d ", Vec_IntEntry(p->vFanins, i) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Verifies 4-input decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rsb_DecVerify( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, unsigned Truth4, word * pTemp1, word * pTemp2 ) { word * pFanins[16]; int b, m, Num, nSuppSize; int nWords = Abc_TtWordNum(nVars); Truth4 >>= (1 << Vec_IntSize(p->vFanins)); Truth4 = (unsigned)Abc_Tt6Stretch( (word)Truth4, Vec_IntSize(p->vFanins) ); //Kit_DsdPrintFromTruth( (unsigned *)&Truth4, Vec_IntSize(p->vFanins) ); //printf( "\n" ); // nSuppSize = Rsb_Word6SupportSize( Truth4 ); // assert( nSuppSize == Vec_IntSize(p->vFanins) ); nSuppSize = Vec_IntSize(p->vFanins); // collect the fanins Vec_IntForEachEntry( p->vFanins, Num, b ) { assert( Num < nGs ); pFanins[b] = g[Num]; } // create the or of ands Abc_TtClear( pTemp1, nWords ); for ( m = 0; m < (1<> m) & 1) == 0 ) continue; Abc_TtFill( pTemp2, nWords ); for ( b = 0; b < nSuppSize; b++ ) if ( (m >> b) & 1 ) Abc_TtAnd( pTemp2, pTemp2, pFanins[b], nWords, 0 ); else Abc_TtSharp( pTemp2, pTemp2, pFanins[b], nWords ); Abc_TtOr( pTemp1, pTemp1, pTemp2, nWords ); } // check the function if ( !Abc_TtEqual( pTemp1, f, nWords ) ) printf( "Verification failed.\n" ); // else // printf( "Verification passed.\n" ); return 1; } /**Function************************************************************* Synopsis [Finds a setset of gs to decompose f.] Description [Returns the numbers of the decomposition functions and the truth table of a function up to 4 variables.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Rsb_ManPerform( Rsb_Man_t * p, int nVars, word * f, word ** g, int nGs, int nGsAll, int fVerbose0 ) { word * pCexes = Vec_WrdArray(p->vCexes); unsigned * pPat = (unsigned *)Vec_IntArray(p->vDecPats); int fVerbose = 0;//(nGs > 40); Vec_Int_t * vTries = NULL; unsigned uTruth; // verify original decomposition if ( Vec_IntSize(p->vFaninsOld) && Vec_IntSize(p->vFaninsOld) <= 4 ) { word * pDivs[8]; int i, Entry, iCexA, iCexB; Vec_IntForEachEntry( p->vFaninsOld, Entry, i ) pDivs[i] = g[Entry]; uTruth = Rsb_DecCheck( nVars, f, pDivs, Vec_IntSize(p->vFaninsOld), pPat, &iCexA, &iCexB ); // assert( uTruth != 0 ); if ( fVerbose ) { printf( "Verified orig decomp with %d vars {", Vec_IntSize(p->vFaninsOld) ); Vec_IntForEachEntry( p->vFaninsOld, Entry, i ) printf( " %d", Entry ); printf( " }\n" ); } if ( uTruth ) { // if ( fVerbose ) // Rsb_DecPrintFunc( p, uTruth ); } else { printf( "Verified orig decomp with %d vars {", Vec_IntSize(p->vFaninsOld) ); Vec_IntForEachEntry( p->vFaninsOld, Entry, i ) printf( " %d", Entry ); printf( " }\n" ); printf( "Verification FAILED.\n" ); } } // start tries if ( fVerbose ) vTries = Vec_IntAlloc( 100 ); assert( nGs < nGsAll ); uTruth = Rsb_DecPerformInt( p, nVars, f, g, nGs, nGsAll, 0 ); if ( uTruth ) { if ( fVerbose ) { int i, Entry; printf( "Found decomp with %d vars {", Vec_IntSize(p->vFanins) ); Vec_IntForEachEntry( p->vFanins, Entry, i ) printf( " %d", Entry ); printf( " }\n" ); // Rsb_DecPrintFunc( p, uTruth ); // Rsb_DecVerify( nVars, f, g, nGs, p->vFanins, uTruth, g[nGsAll], g[nGsAll+1] ); } } else { Vec_IntShrink( p->vFanins, 0 ); if ( fVerbose ) printf( "Did not find decomposition with 4 variables.\n" ); } if ( fVerbose ) Rsb_DecPrintTable( pCexes, nGs, nGsAll, vTries ); if ( fVerbose ) Vec_IntFree( vTries ); return uTruth; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rsb_ManPerformResub6( Rsb_Man_t * p, int nVarsAll, word uTruth, Vec_Wrd_t * vDivTruths, word * puTruth0, word * puTruth1, int fVerbose ) { word * pGs[200]; unsigned uTruthRes; int i, nVars, nGs = Vec_WrdSize(vDivTruths); assert( nGs < 200 ); for ( i = 0; i < nGs; i++ ) pGs[i] = Vec_WrdEntryP(vDivTruths,i); uTruthRes = Rsb_DecPerformInt( p, nVarsAll, &uTruth, pGs, nGs, nGs, 0 ); if ( uTruthRes == 0 ) return 0; if ( fVerbose ) Rsb_DecPrintFunc( p, uTruthRes, &uTruth, pGs, nGs, nVarsAll ); if ( fVerbose ) Rsb_DecPrintTable( Vec_WrdArray(p->vCexes), nGs, nGs, p->vTries ); nVars = Vec_IntSize(p->vFanins); *puTruth0 = Abc_Tt6Stretch( uTruthRes, nVars ); *puTruth1 = Abc_Tt6Stretch( uTruthRes >> (1 << nVars), nVars ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rsb_ManPerformResub6Test() { Rsb_Man_t * p; Vec_Wrd_t * vDivTruths; int RetValue; word a = s_Truths6[0]; word b = s_Truths6[1]; word c = s_Truths6[2]; word d = s_Truths6[3]; word e = s_Truths6[4]; word f = s_Truths6[5]; word ab = a & b; word cd = c & d; word ef = e & f; word F = ab | cd | ef; word uTruth0, uTruth1; vDivTruths = Vec_WrdAlloc( 100 ); Vec_WrdPush( vDivTruths, a ); Vec_WrdPush( vDivTruths, b ); Vec_WrdPush( vDivTruths, c ); Vec_WrdPush( vDivTruths, d ); Vec_WrdPush( vDivTruths, e ); Vec_WrdPush( vDivTruths, f ); Vec_WrdPush( vDivTruths, ab ); Vec_WrdPush( vDivTruths, cd ); Vec_WrdPush( vDivTruths, ef ); p = Rsb_ManAlloc( 6, 64, 4, 1 ); RetValue = Rsb_ManPerformResub6( p, 6, F, vDivTruths, &uTruth0, &uTruth1, 1 ); Rsb_ManFree( p ); Vec_WrdFree( vDivTruths ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rsb/rsbInt.h000066400000000000000000000055511300674244400231750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rsbInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table based resubstitution.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rsbInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__bool_RsbInt_h #define ABC__bool_RsbInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "misc/util/utilTruth.h" #include "bool/kit/kit.h" #include "rsb.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // truth table computation manager struct Rsb_Man_t_ { // parameters int nLeafMax; // the max number of leaves of a cut int nDivMax; // the max number of divisors to collect int nDecMax; // the max number of decompositions int fVerbose; // verbosity level // decomposition Vec_Wrd_t * vCexes; // counter-examples Vec_Int_t * vDecPats; // decomposition patterns Vec_Int_t * vFanins; // the result of decomposition Vec_Int_t * vFaninsOld; // original fanins Vec_Int_t * vTries; // intermediate }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== rsbMan.c ==========================================================*/ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/bool/rsb/rsbMan.c000066400000000000000000000052501300674244400231450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rsbMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth-table based resubstitution.] Synopsis [Manager maintenance.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rsbMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rsbInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rsb_Man_t * Rsb_ManAlloc( int nLeafMax, int nDivMax, int nDecMax, int fVerbose ) { Rsb_Man_t * p; assert( nLeafMax <= 20 ); assert( nDivMax <= 200 ); p = ABC_CALLOC( Rsb_Man_t, 1 ); p->nLeafMax = nLeafMax; p->nDivMax = nDivMax; p->nDecMax = nDecMax; p->fVerbose = fVerbose; // decomposition p->vCexes = Vec_WrdAlloc( nDivMax + 150 ); p->vDecPats = Vec_IntAlloc( Abc_TtWordNum(nLeafMax) ); p->vFanins = Vec_IntAlloc( 10 ); p->vFaninsOld = Vec_IntAlloc( 10 ); p->vTries = Vec_IntAlloc( 10 ); return p; } void Rsb_ManFree( Rsb_Man_t * p ) { Vec_WrdFree( p->vCexes ); Vec_IntFree( p->vDecPats ); Vec_IntFree( p->vFanins ); Vec_IntFree( p->vFaninsOld ); Vec_IntFree( p->vTries ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Rsb_ManGetFanins( Rsb_Man_t * p ) { return p->vFanins; } Vec_Int_t * Rsb_ManGetFaninsOld( Rsb_Man_t * p ) { return p->vFaninsOld; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/demo.c000066400000000000000000000133171300674244400211310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [demo.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [ABC as a static library.] Synopsis [A demo program illustrating the use of ABC as a static library.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: demo.c,v 1.00 2005/11/14 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // procedures to start and stop the ABC framework // (should be called before and after the ABC procedures are called) extern void Abc_Start(); extern void Abc_Stop(); // procedures to get the ABC framework and execute commands in it extern void * Abc_FrameGetGlobalFrame(); extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [The main() procedure.] Description [This procedure compiles into a stand-alone program for DAG-aware rewriting of the AIGs. A BLIF or PLA file to be considered for rewriting should be given as a command-line argument. Implementation of the rewriting is inspired by the paper: Per Bjesse, Arne Boralv, "DAG-aware circuit compression for formal verification", Proc. ICCAD 2004.] SideEffects [] SeeAlso [] ***********************************************************************/ int main( int argc, char * argv[] ) { // parameters int fUseResyn2 = 0; int fPrintStats = 1; int fVerify = 1; // variables void * pAbc; char * pFileName; char Command[1000]; clock_t clkRead, clkResyn, clkVer, clk; ////////////////////////////////////////////////////////////////////////// // get the input file name if ( argc != 2 ) { printf( "Wrong number of command-line arguments.\n" ); return 1; } pFileName = argv[1]; ////////////////////////////////////////////////////////////////////////// // start the ABC framework Abc_Start(); pAbc = Abc_FrameGetGlobalFrame(); clk = clock(); ////////////////////////////////////////////////////////////////////////// // read the file sprintf( Command, "read %s", pFileName ); if ( Cmd_CommandExecute( pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return 1; } ////////////////////////////////////////////////////////////////////////// // balance sprintf( Command, "balance" ); if ( Cmd_CommandExecute( pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return 1; } clkRead = clock() - clk; ////////////////////////////////////////////////////////////////////////// // print stats if ( fPrintStats ) { sprintf( Command, "print_stats" ); if ( Cmd_CommandExecute( pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return 1; } } clk = clock(); ////////////////////////////////////////////////////////////////////////// // synthesize if ( fUseResyn2 ) { sprintf( Command, "balance; rewrite -l; refactor -l; balance; rewrite -l; rewrite -lz; balance; refactor -lz; rewrite -lz; balance" ); if ( Cmd_CommandExecute( pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return 1; } } else { sprintf( Command, "balance; rewrite -l; rewrite -lz; balance; rewrite -lz; balance" ); if ( Cmd_CommandExecute( pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return 1; } } clkResyn = clock() - clk; ////////////////////////////////////////////////////////////////////////// // print stats if ( fPrintStats ) { sprintf( Command, "print_stats" ); if ( Cmd_CommandExecute( pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return 1; } } ////////////////////////////////////////////////////////////////////////// // write the result in blif sprintf( Command, "write_blif result.blif" ); if ( Cmd_CommandExecute( pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return 1; } ////////////////////////////////////////////////////////////////////////// // perform verification clk = clock(); if ( fVerify ) { sprintf( Command, "cec %s result.blif", pFileName ); if ( Cmd_CommandExecute( pAbc, Command ) ) { fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); return 1; } } clkVer = clock() - clk; printf( "Reading = %6.2f sec ", (float)(clkRead)/(float)(CLOCKS_PER_SEC) ); printf( "Rewriting = %6.2f sec ", (float)(clkResyn)/(float)(CLOCKS_PER_SEC) ); printf( "Verification = %6.2f sec\n", (float)(clkVer)/(float)(CLOCKS_PER_SEC) ); ////////////////////////////////////////////////////////////////////////// // stop the ABC framework Abc_Stop(); return 0; } berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/generic.c000066400000000000000000000026071300674244400216210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "__Int.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/generic.h000066400000000000000000000036771300674244400216360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__generic_h #define ABC__generic_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== zzz.c ==========================================================*/ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/000077500000000000000000000000001300674244400206115ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/000077500000000000000000000000001300674244400215275ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amap.h000066400000000000000000000070211300674244400226160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amap.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amap.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__amap__amap_h #define ABC__map__amap__amap_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Amap_Lib_t_ Amap_Lib_t; typedef struct Amap_Par_t_ Amap_Par_t; struct Amap_Par_t_ { int nIterFlow; // iterations of area flow int nIterArea; // iteratoins of exact area int nCutsMax; // the maximum number of cuts at a node int fUseMuxes; // enables the use of MUXes int fUseXors; // enables the use of XORs int fFreeInvs; // assume inverters are free (area = 0) float fEpsilon; // used to compare floating point numbers float fADratio; // ratio of area/delay improvement int fVerbose; // verbosity flag }; typedef struct Amap_Out_t_ Amap_Out_t; struct Amap_Out_t_ { char * pName; // gate name short Type; // node type (-1=input; 0=internal; 1=output) short nFans; // number of fanins int pFans[0]; // fanin }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== amapCore.c ==========================================================*/ extern void Amap_ManSetDefaultParams( Amap_Par_t * pPars ); //extern Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars ); /*=== amapLib.c ==========================================================*/ extern void Amap_LibFree( Amap_Lib_t * p ); extern void Amap_LibPrintSelectedGates( Amap_Lib_t * p, int fAllGates ); extern Amap_Lib_t * Amap_LibReadAndPrepare( char * pFileName, char * pBuffer, int fVerbose, int fVeryVerbose ); /*=== amapLiberty.c ==========================================================*/ extern int Amap_LibertyParse( char * pFileName, int fVerbose ); extern Vec_Str_t * Amap_LibertyParseStr( char * pFileName, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapCore.c000066400000000000000000000064651300674244400234350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Core mapping procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManSetDefaultParams( Amap_Par_t * p ) { memset( p, 0, sizeof(Amap_Par_t) ); p->nIterFlow = 1; // iterations of area flow p->nIterArea = 4; // iteratoins of exact area p->nCutsMax = 500; // the maximum number of cuts at a node p->fUseMuxes = 0; // enables the use of MUXes p->fUseXors = 1; // enables the use of XORs p->fFreeInvs = 0; // assume inverters are free (area = 0) p->fEpsilon = (float)0.001; // used to compare floating point numbers p->fVerbose = 0; // verbosity flag } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Amap_ManTest( Aig_Man_t * pAig, Amap_Par_t * pPars ) { // extern void * Abc_FrameReadLibGen2(); Vec_Ptr_t * vRes; Amap_Man_t * p; Amap_Lib_t * pLib; abctime clkTotal = Abc_Clock(); pLib = (Amap_Lib_t *)Abc_FrameReadLibGen2(); if ( pLib == NULL ) { printf( "Library is not available.\n" ); return NULL; } p = Amap_ManStart( Aig_ManNodeNum(pAig) ); p->pPars = pPars; p->pLib = pLib; p->fAreaInv = pPars->fFreeInvs? 0.0 : pLib->pGateInv->dArea; p->fUseMux = pPars->fUseMuxes && pLib->fHasMux; p->fUseXor = pPars->fUseXors && pLib->fHasXor; p->ppCutsTemp = ABC_CALLOC( Amap_Cut_t *, 2 * pLib->nNodes ); p->pMatsTemp = ABC_CALLOC( int, 2 * pLib->nNodes ); Amap_ManCreate( p, pAig ); Amap_ManMap( p ); vRes = NULL; vRes = Amap_ManProduceMapped( p ); Amap_ManStop( p ); if ( pPars->fVerbose ) { ABC_PRT( "Total runtime", Abc_Clock() - clkTotal ); } return vRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapGraph.c000066400000000000000000000320601300674244400235740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapGraph.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Internal AIG manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapGraph.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManSetupObj( Amap_Man_t * p ) { Amap_Obj_t * pObj; pObj = (Amap_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObj ); memset( pObj, 0, sizeof(Amap_Obj_t) ); pObj->nFouts[0] = 1; // needed for flow to work in the first pass pObj->Id = Vec_PtrSize(p->vObjs); Vec_PtrPush( p->vObjs, pObj ); return pObj; } /**Function************************************************************* Synopsis [Creates constant 1 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreateConst1( Amap_Man_t * p ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_CONST1; pObj->fPhase = 1; p->nObjs[AMAP_OBJ_CONST1]++; return pObj; } /**Function************************************************************* Synopsis [Creates primary input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreatePi( Amap_Man_t * p ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_PI; pObj->IdPio = Vec_PtrSize( p->vPis ); Vec_PtrPush( p->vPis, pObj ); p->nObjs[AMAP_OBJ_PI]++; return pObj; } /**Function************************************************************* Synopsis [Creates primary output with the given driver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->IdPio = Vec_PtrSize( p->vPos ); Vec_PtrPush( p->vPos, pObj ); pObj->Type = AMAP_OBJ_PO; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Level = Amap_Regular(pFan0)->Level; if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 p->nObjs[AMAP_OBJ_PO]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_AND; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; assert( Abc_Lit2Var(pObj->Fan[0]) != Abc_Lit2Var(pObj->Fan[1]) ); pObj->fPhase = Amap_ObjPhaseReal(pFan0) & Amap_ObjPhaseReal(pFan1); pObj->Level = 1 + Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 p->nObjs[AMAP_OBJ_AND]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_XOR; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; pObj->fPhase = Amap_ObjPhaseReal(pFan0) ^ Amap_ObjPhaseReal(pFan1); pObj->Level = 2 + Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 p->nObjs[AMAP_OBJ_XOR]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC ) { Amap_Obj_t * pObj; pObj = Amap_ManSetupObj( p ); pObj->Type = AMAP_OBJ_MUX; pObj->Fan[0] = Amap_ObjToLit(pFan0); Amap_Regular(pFan0)->nRefs++; pObj->Fan[1] = Amap_ObjToLit(pFan1); Amap_Regular(pFan1)->nRefs++; pObj->Fan[2] = Amap_ObjToLit(pFanC); Amap_Regular(pFanC)->nRefs++; pObj->fPhase = (Amap_ObjPhaseReal(pFan1) & Amap_ObjPhaseReal(pFanC)) | (Amap_ObjPhaseReal(pFan0) & ~Amap_ObjPhaseReal(pFanC)); pObj->Level = Abc_MaxInt( Amap_Regular(pFan0)->Level, Amap_Regular(pFan1)->Level ); pObj->Level = 2 + Abc_MaxInt( pObj->Level, Amap_Regular(pFanC)->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 p->nObjs[AMAP_OBJ_MUX]++; return pObj; } /**Function************************************************************* Synopsis [Creates the choice node.] Description [Should be called after the equivalence class nodes are linked.] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj ) { Amap_Obj_t * pTemp; // mark the node as a representative if its class // assert( pObj->fRepr == 0 ); pObj->fRepr = 1; // update the level of this node (needed for correct required time computation) for ( pTemp = pObj; pTemp; pTemp = Amap_ObjChoice(p, pTemp) ) { pObj->Level = Abc_MaxInt( pObj->Level, pTemp->Level ); // pTemp->nVisits++; pTemp->nVisitsCopy++; } // mark the largest level if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; assert( p->nLevelMax < 4094 ); // 2^12-2 } /**Function************************************************************* Synopsis [Creates XOR/MUX choices for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCreateXorChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pChoices[] ) { pChoices[0] = Amap_ManCreateXor( p, pFan0, pFan1 ); pChoices[1] = Amap_ManCreateXor( p, Amap_Not(pFan0), pFan1 ); pChoices[2] = Amap_ManCreateXor( p, pFan0, Amap_Not(pFan1) ); pChoices[3] = Amap_ManCreateXor( p, Amap_Not(pFan0), Amap_Not(pFan1) ); } /**Function************************************************************* Synopsis [Creates XOR/MUX choices for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCreateMuxChoices( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1, Amap_Obj_t * pFanC, Amap_Obj_t * pChoices[] ) { pChoices[0] = Amap_ManCreateMux( p, pFan0, pFan1, pFanC ); pChoices[1] = Amap_ManCreateMux( p, Amap_Not(pFan0), Amap_Not(pFan1), pFanC ); pChoices[2] = Amap_ManCreateMux( p, pFan1, pFan0, Amap_Not(pFanC) ); pChoices[3] = Amap_ManCreateMux( p, Amap_Not(pFan1), Amap_Not(pFan0), Amap_Not(pFanC) ); } /**Function************************************************************* Synopsis [Drags pointer out through the copy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Amap_Obj_t * Amap_AndToObj( Aig_Obj_t * pObj ) { return Amap_NotCond( (Amap_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj) ); } /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Obj_t * Amap_ManGetLast_rec( Amap_Man_t * p, Amap_Obj_t * pObj ) { if ( pObj->Equiv == 0 ) return pObj; return Amap_ManGetLast_rec( p, Amap_ObjChoice(p, pObj) ); } /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig ) { Vec_Ptr_t * vNodes; Amap_Obj_t * pChoices[4]; Aig_Obj_t * pObj, * pFanin, * pPrev, * pFan0, * pFan1, * pFanC; int i, fChoices; if ( pAig->pEquivs ) vNodes = Aig_ManDfsChoices( pAig ); else vNodes = Aig_ManDfs( pAig, 1 ); p->pConst1 = Amap_ManCreateConst1( p ); // print warning about excessive memory usage if ( p->pPars->fVerbose ) { if ( 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30) > 0.1 ) printf( "Warning: Mapper allocates %.3f GB for subject graph with %d objects.\n", 1.0 * Aig_ManObjNum(pAig) * sizeof(Amap_Obj_t) / (1<<30), Aig_ManObjNum(pAig) ); } // create PIs and remember them in the old nodes Aig_ManCleanData(pAig); Aig_ManConst1(pAig)->pData = Amap_ManConst1( p ); Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Amap_ManCreatePi( p ); // load the AIG into the mapper Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { fChoices = 0; if ( p->fUseXor && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1 ) ) { Amap_ManCreateXorChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), pChoices ); fChoices = 1; } else if ( p->fUseMux && Aig_ObjIsMuxType(pObj) ) { pFanC = Aig_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); Amap_ManCreateMuxChoices( p, Amap_AndToObj(pFan0), Amap_AndToObj(pFan1), Amap_AndToObj(pFanC), pChoices ); fChoices = 1; } pObj->pData = Amap_ManCreateAnd( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj), (Amap_Obj_t *)Aig_ObjChild1Copy(pObj) ); if ( fChoices ) { p->nChoicesAdded++; Amap_ObjSetChoice( (Amap_Obj_t *)pObj->pData, pChoices[0] ); Amap_ObjSetChoice( pChoices[0], pChoices[1] ); Amap_ObjSetChoice( pChoices[1], pChoices[2] ); Amap_ObjSetChoice( pChoices[2], pChoices[3] ); Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData ); } if ( Aig_ObjIsChoice( pAig, pObj ) ) { // assert( !fChoices ); p->nChoicesGiven++; for ( pPrev = pObj, pFanin = Aig_ObjEquiv(pAig, pObj); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(pAig, pFanin) ) { ((Amap_Obj_t *)pFanin->pData)->fRepr = 0; Amap_ObjSetChoice( Amap_ManGetLast_rec(p, (Amap_Obj_t *)pPrev->pData), (Amap_Obj_t *)pFanin->pData ); } Amap_ManCreateChoice( p, (Amap_Obj_t *)pObj->pData ); } } Vec_PtrFree( vNodes ); // set the primary outputs without copying the phase Aig_ManForEachCo( pAig, pObj, i ) pObj->pData = Amap_ManCreatePo( p, (Amap_Obj_t *)Aig_ObjChild0Copy(pObj) ); if ( p->pPars->fVerbose ) printf( "Performing mapping with %d given and %d created choices.\n", p->nChoicesGiven, p->nChoicesAdded ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapInt.h000066400000000000000000000465701300674244400233050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__amap__amapInt_h #define ABC__map__amap__amapInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/extra/extra.h" #include "aig/aig/aig.h" #include "amap.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START // the largest gate size in the library // (gates above this size will be ignored) #define AMAP_MAXINS 15 #define AMAP_STRING_CONST0 "CONST0" #define AMAP_STRING_CONST1 "CONST1" // object types typedef enum { AMAP_OBJ_NONE, // 0: non-existent object AMAP_OBJ_CONST1, // 1: constant 1 AMAP_OBJ_PI, // 2: primary input AMAP_OBJ_PO, // 3: primary output AMAP_OBJ_AND, // 4: AND node AMAP_OBJ_XOR, // 5: XOR node AMAP_OBJ_MUX, // 6: MUX node AMAP_OBJ_VOID // 7: unused object } Amap_Type_t; //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Amap_Pin_t_ Amap_Pin_t; typedef struct Amap_Gat_t_ Amap_Gat_t; typedef struct Amap_Nod_t_ Amap_Nod_t; typedef struct Amap_Set_t_ Amap_Set_t; typedef struct Amap_Man_t_ Amap_Man_t; typedef struct Amap_Obj_t_ Amap_Obj_t; typedef struct Amap_Cut_t_ Amap_Cut_t; typedef struct Amap_Mat_t_ Amap_Mat_t; struct Amap_Man_t_ { // user data Amap_Par_t * pPars; Amap_Lib_t * pLib; // internal parameters float fEpsilonInternal; float fAreaInv; int fUseXor; int fUseMux; // internal AIG with choices Vec_Ptr_t * vPis; Vec_Ptr_t * vPos; Vec_Ptr_t * vObjs; Aig_MmFixed_t * pMemObj; Aig_MmFlex_t * pMemCuts; Aig_MmFlex_t * pMemCutBest; Aig_MmFlex_t * pMemTemp; Amap_Obj_t * pConst1; int nObjs[AMAP_OBJ_VOID]; int nLevelMax; int nChoicesGiven; int nChoicesAdded; // mapping data-structures Vec_Int_t * vTemp; int * pMatsTemp; Amap_Cut_t ** ppCutsTemp; Amap_Cut_t * pCutsPi; Vec_Ptr_t * vCuts0; Vec_Ptr_t * vCuts1; Vec_Ptr_t * vCuts2; // statistics int nCutsUsed; int nCutsTried; int nCutsTried3; int nBytesUsed; }; struct Amap_Lib_t_ { char * pName; // library name Vec_Ptr_t * vGates; // represenation of gates Vec_Ptr_t * vSorted; // gates sorted for area-only mapping Vec_Ptr_t * vSelect; // gates selected for area-only mapping Amap_Gat_t * pGate0; // the constant zero gate Amap_Gat_t * pGate1; // the constant one gate Amap_Gat_t * pGateBuf; // the buffer Amap_Gat_t * pGateInv; // the inverter Aig_MmFlex_t * pMemGates; // memory manager for objects int fHasXor; // XOR/NXOR gates are present int fHasMux; // MUX/NMUX gates are present // structural representation int fVerbose; // enable detailed statistics Amap_Nod_t * pNodes; // representation nodes int nNodes; // the number of nodes used int nNodesAlloc; // the number of nodes allocated Vec_Ptr_t * vRules; // the rule of AND gate Vec_Ptr_t * vRulesX; // the rule of XOR gate Vec_Int_t * vRules3; // the rule of MUX gate int ** pRules; // simplified representation int ** pRulesX; // simplified representation Aig_MmFlex_t * pMemSet; // memory manager for sets int nSets; // the number of sets created }; struct Amap_Pin_t_ { char * pName; int Phase; double dLoadInput; double dLoadMax; double dDelayBlockRise; double dDelayFanoutRise; double dDelayBlockFall; double dDelayFanoutFall; double dDelayBlockMax; }; struct Amap_Gat_t_ { Amap_Lib_t * pLib; // library Amap_Gat_t * pTwin; // twin gate char * pName; // the name of the gate char * pOutName; // name of the output double dArea; // the area of the gate char * pForm; // the formula describing functionality unsigned * pFunc; // truth table unsigned Id : 23; // unique number of the gate unsigned fMux : 1; // denotes MUX-gates unsigned nPins : 8; // number of inputs Amap_Pin_t Pins[0]; // description of inputs }; struct Amap_Set_t_ { Amap_Set_t * pNext; unsigned iGate : 16; unsigned fInv : 1; unsigned nIns : 15; char Ins[AMAP_MAXINS];// mapping from gate inputs into fanins }; struct Amap_Nod_t_ { unsigned Id : 16; // ID of the node unsigned nSuppSize: 8; // support size unsigned Type : 8; // the type of node short iFan0; // fanin0 short iFan1; // fanin1 short iFan2; // fanin2 short Unused; // Amap_Set_t * pSets; // implementable gates }; struct Amap_Cut_t_ { unsigned iMat : 16; unsigned fInv : 1; unsigned nFans : 15; int Fans[0]; }; struct Amap_Mat_t_ { Amap_Cut_t * pCut; // the cut Amap_Set_t * pSet; // the set float Area; // area flow / exact area of the node float AveFan; // edge flow of the node float Delay; // delay of the node }; struct Amap_Obj_t_ { unsigned Type : 3; unsigned Id : 29; unsigned IdPio : 29; unsigned fPhase : 1; unsigned fRepr : 1; unsigned fPolar : 1; // pCutBest->fInv ^ pSetBest->fInv unsigned Level : 12; // 20 (July 16, 2009) unsigned nCuts : 20; // 12 (July 16, 2009) int nRefs; int Equiv; int Fan[3]; union { void * pData; int iData; }; // match of the node float EstRefs; // the number of estimated fanouts int nFouts[2]; // the number of refs in each polarity Amap_Mat_t Best; // the best match of the node }; static inline Amap_Obj_t * Amap_Regular( Amap_Obj_t * p ) { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Amap_Obj_t * Amap_Not( Amap_Obj_t * p ) { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Amap_Obj_t * Amap_NotCond( Amap_Obj_t * p, int c ) { return (Amap_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int Amap_IsComplement( Amap_Obj_t * p ) { return (int )(((ABC_PTRUINT_T)p) & 01); } static inline int Amap_ManPiNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_PI]; } static inline int Amap_ManPoNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_PO]; } static inline int Amap_ManAndNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_AND]; } static inline int Amap_ManXorNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_XOR]; } static inline int Amap_ManMuxNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_MUX]; } static inline int Amap_ManObjNum( Amap_Man_t * p ) { return Vec_PtrSize(p->vObjs); } static inline int Amap_ManNodeNum( Amap_Man_t * p ) { return p->nObjs[AMAP_OBJ_AND] + p->nObjs[AMAP_OBJ_XOR] + p->nObjs[AMAP_OBJ_MUX]; } static inline Amap_Obj_t * Amap_ManConst1( Amap_Man_t * p ) { return p->pConst1; } static inline Amap_Obj_t * Amap_ManPi( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vPis, i ); } static inline Amap_Obj_t * Amap_ManPo( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vPos, i ); } static inline Amap_Obj_t * Amap_ManObj( Amap_Man_t * p, int i ) { return (Amap_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } static inline int Amap_ObjIsConst1( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_CONST1; } static inline int Amap_ObjIsPi( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_PI; } static inline int Amap_ObjIsPo( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_PO; } static inline int Amap_ObjIsAnd( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_AND; } static inline int Amap_ObjIsXor( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_XOR; } static inline int Amap_ObjIsMux( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_MUX; } static inline int Amap_ObjIsNode( Amap_Obj_t * pObj ) { return pObj->Type == AMAP_OBJ_AND || pObj->Type == AMAP_OBJ_XOR || pObj->Type == AMAP_OBJ_MUX; } static inline int Amap_ObjToLit( Amap_Obj_t * pObj ) { return Abc_Var2Lit( Amap_Regular(pObj)->Id, Amap_IsComplement(pObj) ); } static inline Amap_Obj_t * Amap_ObjFanin0( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[0])); } static inline Amap_Obj_t * Amap_ObjFanin1( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[1])); } static inline Amap_Obj_t * Amap_ObjFanin2( Amap_Man_t * p, Amap_Obj_t * pObj ) { return Amap_ManObj(p, Abc_Lit2Var(pObj->Fan[2])); } static inline int Amap_ObjFaninC0( Amap_Obj_t * pObj ) { return Abc_LitIsCompl(pObj->Fan[0]); } static inline int Amap_ObjFaninC1( Amap_Obj_t * pObj ) { return Abc_LitIsCompl(pObj->Fan[1]); } static inline int Amap_ObjFaninC2( Amap_Obj_t * pObj ) { return Abc_LitIsCompl(pObj->Fan[2]); } static inline void * Amap_ObjCopy( Amap_Obj_t * pObj ) { return pObj->pData; } static inline int Amap_ObjLevel( Amap_Obj_t * pObj ) { return pObj->Level; } static inline void Amap_ObjSetLevel( Amap_Obj_t * pObj, int Level ) { pObj->Level = Level; } static inline void Amap_ObjSetCopy( Amap_Obj_t * pObj, void * pCopy ) { pObj->pData = pCopy; } static inline Amap_Obj_t * Amap_ObjChoice( Amap_Man_t * p, Amap_Obj_t * pObj ) { return pObj->Equiv? Amap_ManObj(p, pObj->Equiv) : NULL; } static inline void Amap_ObjSetChoice( Amap_Obj_t * pObj, Amap_Obj_t * pEqu){ assert(pObj->Equiv==0); if (pObj->Id != pEqu->Id) pObj->Equiv = pEqu->Id; } static inline int Amap_ObjPhaseReal( Amap_Obj_t * pObj ) { return Amap_Regular(pObj)->fPhase ^ Amap_IsComplement(pObj); } static inline int Amap_ObjRefsTotal( Amap_Obj_t * pObj ) { return pObj->nFouts[0] + pObj->nFouts[1]; } static inline Amap_Gat_t * Amap_LibGate( Amap_Lib_t * p, int i ) { return (Amap_Gat_t *)Vec_PtrEntry(p->vGates, i); } static inline Amap_Nod_t * Amap_LibNod( Amap_Lib_t * p, int i ) { return p->pNodes + i; } // returns pointer to the next cut (internal cuts only) static inline Amap_Cut_t * Amap_ManCutNext( Amap_Cut_t * pCut ) { return (Amap_Cut_t *)(((int *)pCut)+pCut->nFans+1); } // returns pointer to the place of the next cut (temporary cuts only) static inline Amap_Cut_t ** Amap_ManCutNextP( Amap_Cut_t * pCut ) { return (Amap_Cut_t **)(((int *)pCut)+pCut->nFans+1); } extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // iterator over the primary inputs #define Amap_ManForEachPi( p, pObj, i ) \ Vec_PtrForEachEntry( Amap_Obj_t *, p->vPis, pObj, i ) // iterator over the primary outputs #define Amap_ManForEachPo( p, pObj, i ) \ Vec_PtrForEachEntry( Amap_Obj_t *, p->vPos, pObj, i ) // iterator over all objects, including those currently not used #define Amap_ManForEachObj( p, pObj, i ) \ Vec_PtrForEachEntry( Amap_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else // iterator over all nodes #define Amap_ManForEachNode( p, pObj, i ) \ Vec_PtrForEachEntry( Amap_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Amap_ObjIsNode(pObj) ) {} else // iterator through all gates of the library #define Amap_LibForEachGate( pLib, pGate, i ) \ Vec_PtrForEachEntry( Amap_Gat_t *, pLib->vGates, pGate, i ) // iterator through all pins of the gate #define Amap_GateForEachPin( pGate, pPin ) \ for ( pPin = pGate->Pins; pPin < pGate->Pins + pGate->nPins; pPin++ ) // iterator through all cuts of the node #define Amap_NodeForEachCut( pNode, pCut, i ) \ for ( i = 0, pCut = (Amap_Cut_t *)pNode->pData; i < (int)pNode->nCuts; \ i++, pCut = Amap_ManCutNext(pCut) ) // iterator through all sets of one library node #define Amap_LibNodeForEachSet( pNod, pSet ) \ for ( pSet = pNod->pSets; pSet; pSet = pSet->pNext ) // iterates through each fanin of the match #define Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i ) \ for ( i = 0; i < (int)(pM)->pCut->nFans && \ ((pFanin = Amap_ManObj((p), Abc_Lit2Var((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])]))), 1) && \ ((fCompl = Abc_LitIsCompl((pM)->pSet->Ins[i]) ^ Abc_LitIsCompl((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])])), 1); \ i++ ) // iterates through each fanin of the match #define Amap_MatchForEachFanin( p, pM, pFanin, i ) \ for ( i = 0; i < (int)(pM)->pCut->nFans && \ ((pFanin = Amap_ManObj((p), Abc_Lit2Var((pM)->pCut->Fans[Abc_Lit2Var((pM)->pSet->Ins[i])]))), 1); \ i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== amapCore.c ==========================================================*/ /*=== amapGraph.c ==========================================================*/ extern Amap_Obj_t * Amap_ManCreatePi( Amap_Man_t * p ); extern Amap_Obj_t * Amap_ManCreatePo( Amap_Man_t * p, Amap_Obj_t * pFan0 ); extern Amap_Obj_t * Amap_ManCreateAnd( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ); extern Amap_Obj_t * Amap_ManCreateXor( Amap_Man_t * p, Amap_Obj_t * pFan0, Amap_Obj_t * pFan1 ); extern Amap_Obj_t * Amap_ManCreateMux( Amap_Man_t * p, Amap_Obj_t * pFanC, Amap_Obj_t * pFan1, Amap_Obj_t * pFan0 ); extern void Amap_ManCreateChoice( Amap_Man_t * p, Amap_Obj_t * pObj ); extern void Amap_ManCreate( Amap_Man_t * p, Aig_Man_t * pAig ); /*=== amapLib.c ==========================================================*/ extern Amap_Lib_t * Amap_LibAlloc(); extern int Amap_LibNumPinsMax( Amap_Lib_t * p ); extern void Amap_LibWrite( FILE * pFile, Amap_Lib_t * pLib, int fPrintDsd ); extern Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose ); /*=== amapMan.c ==========================================================*/ extern Amap_Man_t * Amap_ManStart( int nNodes ); extern void Amap_ManStop( Amap_Man_t * p ); /*=== amapMatch.c ==========================================================*/ extern void Amap_ManMap( Amap_Man_t * p ); /*=== amapMerge.c ==========================================================*/ extern void Amap_ManMerge( Amap_Man_t * p ); /*=== amapOutput.c ==========================================================*/ extern Vec_Ptr_t * Amap_ManProduceMapped( Amap_Man_t * p ); /*=== amapParse.c ==========================================================*/ extern int Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose ); /*=== amapPerm.c ==========================================================*/ /*=== amapRead.c ==========================================================*/ extern Amap_Lib_t * Amap_LibReadBuffer( char * pBuffer, int fVerbose ); extern Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose ); /*=== amapRule.c ==========================================================*/ extern short * Amap_LibTableFindNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor ); extern void Amap_LibCreateRules( Amap_Lib_t * p, int fVeryVerbose ); /*=== amapUniq.c ==========================================================*/ extern int Amap_LibFindNode( Amap_Lib_t * pLib, int iFan0, int iFan1, int fXor ); extern int Amap_LibFindMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ); extern int Amap_LibCreateVar( Amap_Lib_t * p ); extern int Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor ); extern int Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ); extern int ** Amap_LibLookupTableAlloc( Vec_Ptr_t * vVec, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapLib.c000066400000000000000000000245531300674244400232510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapLib.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Standard-cell library.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocs a library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Lib_t * Amap_LibAlloc() { Amap_Lib_t * p; p = (Amap_Lib_t *)ABC_ALLOC( Amap_Lib_t, 1 ); memset( p, 0, sizeof(Amap_Lib_t) ); p->vGates = Vec_PtrAlloc( 100 ); p->pMemGates = Aig_MmFlexStart(); p->pMemSet = Aig_MmFlexStart(); return p; } /**Function************************************************************* Synopsis [Deallocs a library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibFree( Amap_Lib_t * p ) { if ( p == NULL ) return; if ( p->vSelect ) Vec_PtrFree( p->vSelect ); if ( p->vSorted ) Vec_PtrFree( p->vSorted ); if ( p->vGates ) Vec_PtrFree( p->vGates ); if ( p->vRules ) Vec_VecFree( (Vec_Vec_t *)p->vRules ); if ( p->vRulesX ) Vec_VecFree( (Vec_Vec_t *)p->vRulesX ); if ( p->vRules3 ) Vec_IntFree( p->vRules3 ); Aig_MmFlexStop( p->pMemGates, 0 ); Aig_MmFlexStop( p->pMemSet, 0 ); ABC_FREE( p->pRules ); ABC_FREE( p->pRulesX ); ABC_FREE( p->pNodes ); ABC_FREE( p->pName ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the largest gate size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibNumPinsMax( Amap_Lib_t * p ) { Amap_Gat_t * pGate; int i, Counter = 0; Amap_LibForEachGate( p, pGate, i ) if ( Counter < (int)pGate->nPins ) Counter = pGate->nPins; return Counter; } /**Function************************************************************* Synopsis [Writes one pin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibWritePin( FILE * pFile, Amap_Pin_t * pPin ) { char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" }; fprintf( pFile, " PIN " ); fprintf( pFile, "%9s ", pPin->pName ); fprintf( pFile, "%10s ", pPhaseNames[pPin->Phase] ); fprintf( pFile, "%6d ", (int)pPin->dLoadInput ); fprintf( pFile, "%6d ", (int)pPin->dLoadMax ); fprintf( pFile, "%6.2f ", pPin->dDelayBlockRise ); fprintf( pFile, "%6.2f ", pPin->dDelayFanoutRise ); fprintf( pFile, "%6.2f ", pPin->dDelayBlockFall ); fprintf( pFile, "%6.2f", pPin->dDelayFanoutFall ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Writes one gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibWriteGate( FILE * pFile, Amap_Gat_t * pGate, int fPrintDsd ) { Amap_Pin_t * pPin; fprintf( pFile, "GATE " ); fprintf( pFile, "%12s ", pGate->pName ); fprintf( pFile, "%10.2f ", pGate->dArea ); fprintf( pFile, "%s=%s;\n", pGate->pOutName, pGate->pForm ); if ( fPrintDsd ) { if ( pGate->pFunc == NULL ) printf( "Truth table is not available.\n" ); else Kit_DsdPrintFromTruth( pGate->pFunc, pGate->nPins ); } Amap_GateForEachPin( pGate, pPin ) Amap_LibWritePin( pFile, pPin ); } /**Function************************************************************* Synopsis [Writes library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibWrite( FILE * pFile, Amap_Lib_t * pLib, int fPrintDsd ) { Amap_Gat_t * pGate; int i; fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName ); Amap_LibForEachGate( pLib, pGate, i ) Amap_LibWriteGate( pFile, pGate, fPrintDsd ); } /**Function************************************************************* Synopsis [Compares two gates by area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibCompareGatesByArea( Amap_Gat_t ** pp1, Amap_Gat_t ** pp2 ) { double Diff = (*pp1)->dArea - (*pp2)->dArea; if ( Diff < 0.0 ) return -1; if ( Diff > 0.0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Compares gates by area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Amap_LibSortGatesByArea( Amap_Lib_t * pLib ) { Vec_Ptr_t * vSorted; vSorted = Vec_PtrDup( pLib->vGates ); qsort( (void *)Vec_PtrArray(vSorted), Vec_PtrSize(vSorted), sizeof(void *), (int (*)(const void *, const void *)) Amap_LibCompareGatesByArea ); return vSorted; } /**Function************************************************************* Synopsis [Finds min-area gate with the given function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Gat_t * Amap_LibFindGate( Amap_Lib_t * p, unsigned uTruth ) { Amap_Gat_t * pGate; int i; Vec_PtrForEachEntry( Amap_Gat_t *, p->vSorted, pGate, i ) if ( pGate->nPins <= 5 && pGate->pFunc[0] == uTruth ) return pGate; return NULL; } /**Function************************************************************* Synopsis [Selects gates useful for area-only mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose ) { Vec_Ptr_t * vSelect; Amap_Gat_t * pGate, * pGate2; int i, k;//, clk = Abc_Clock(); p->pGate0 = Amap_LibFindGate( p, 0 ); p->pGate1 = Amap_LibFindGate( p, ~0 ); p->pGateBuf = Amap_LibFindGate( p, 0xAAAAAAAA ); p->pGateInv = Amap_LibFindGate( p, ~0xAAAAAAAA ); vSelect = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Amap_Gat_t *, p->vSorted, pGate, i ) { if ( pGate->pFunc == NULL || pGate->pTwin != NULL ) continue; Vec_PtrForEachEntryStop( Amap_Gat_t *, p->vSorted, pGate2, k, i ) { if ( pGate2->pFunc == NULL || pGate2->pTwin != NULL ) continue; if ( pGate2->nPins != pGate->nPins ) continue; if ( !memcmp( pGate2->pFunc, pGate->pFunc, sizeof(unsigned) * Abc_TruthWordNum(pGate->nPins) ) ) break; } if ( k < i ) continue; Vec_PtrPush( vSelect, pGate ); } return vSelect; } /**Function************************************************************* Synopsis [Selects gates useful for area-only mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibPrintSelectedGates( Amap_Lib_t * p, int fAllGates ) { Vec_Ptr_t * vArray; Amap_Gat_t * pGate; int i; vArray = fAllGates? p->vGates : p->vSelect; Vec_PtrForEachEntry( Amap_Gat_t *, vArray, pGate, i ) { printf( "%3d :%12s %d %9.2f ", i, pGate->pName, pGate->nPins, pGate->dArea ); printf( "%4s=%40s ", pGate->pOutName, pGate->pForm ); printf( "DSD: " ); Kit_DsdPrintFromTruth( pGate->pFunc, pGate->nPins ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Parses equations for the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Lib_t * Amap_LibReadAndPrepare( char * pFileName, char * pBuffer, int fVerbose, int fVeryVerbose ) { Amap_Lib_t * p; abctime clk = Abc_Clock(); if ( pBuffer == NULL ) p = Amap_LibReadFile( pFileName, fVerbose ); else { p = Amap_LibReadBuffer( pBuffer, fVerbose ); if ( p ) p->pName = Abc_UtilStrsav( pFileName ); } if ( fVerbose ) printf( "Read %d gates from file \"%s\".\n", Vec_PtrSize(p->vGates), pFileName ); if ( p == NULL ) return NULL; if ( !Amap_LibParseEquations( p, fVerbose ) ) { Amap_LibFree( p ); return NULL; } p->vSorted = Amap_LibSortGatesByArea( p ); p->vSelect = Amap_LibSelectGates( p, fVerbose ); if ( fVerbose ) { printf( "Selected %d functionally unique gates. ", Vec_PtrSize(p->vSelect) ); ABC_PRT( "Time", Abc_Clock() - clk ); // Amap_LibPrintSelectedGates( p, 0 ); } clk = Abc_Clock(); Amap_LibCreateRules( p, fVeryVerbose ); if ( fVerbose ) { printf( "Created %d rules and %d matches. ", p->nNodes, p->nSets ); ABC_PRT( "Time", Abc_Clock() - clk ); } return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapLiberty.c000066400000000000000000001026351300674244400241530ustar00rootroot00000000000000/**CFile**************************************************************** FileHead [amapLiberty.c] SystemHead [ABC: Logic synthesis and verification system.] PackageHead [Technology mapper for standard cells.] Synopsis [Liberty parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapLiberty.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_MAX_LIB_STR_LEN 5000 // entry types typedef enum { AMAP_LIBERTY_NONE = 0, // 0: unknown AMAP_LIBERTY_PROC, // 1: procedure : key(head){body} AMAP_LIBERTY_EQUA, // 2: equation : key:head; AMAP_LIBERTY_LIST // 3: list : key(head) } Amap_LibertyType_t; typedef struct Amap_Pair_t_ Amap_Pair_t; struct Amap_Pair_t_ { int Beg; // item beginning int End; // item end }; typedef struct Amap_Item_t_ Amap_Item_t; struct Amap_Item_t_ { int Type; // Amap_LibertyType_t int iLine; // file line where the item's spec begins Amap_Pair_t Key; // key part Amap_Pair_t Head; // head part Amap_Pair_t Body; // body part int Next; // next item in the list int Child; // first child item }; typedef struct Amap_Tree_t_ Amap_Tree_t; struct Amap_Tree_t_ { char * pFileName; // input Liberty file name char * pContents; // file contents int nContents; // file size int nLines; // line counter int nItems; // number of items int nItermAlloc; // number of items allocated Amap_Item_t * pItems; // the items char * pError; // the error string }; static inline Amap_Item_t * Amap_LibertyRoot( Amap_Tree_t * p ) { return p->pItems; } static inline Amap_Item_t * Amap_LibertyItem( Amap_Tree_t * p, int v ) { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v; } static inline int Amap_LibertyCompare( Amap_Tree_t * p, Amap_Pair_t Pair, char * pStr ) { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ); } static inline void Amap_PrintWord( FILE * pFile, Amap_Tree_t * p, Amap_Pair_t Pair ) { char * pBeg = p->pContents+Pair.Beg, * pEnd = p->pContents+Pair.End; while ( pBeg < pEnd ) fputc( *pBeg++, pFile ); } static inline void Amap_PrintSpace( FILE * pFile, int nOffset ) { int i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile); } static inline int Amap_LibertyItemId( Amap_Tree_t * p, Amap_Item_t * pItem ) { return pItem - p->pItems; } #define Amap_ItemForEachChild( p, pItem, pChild ) \ for ( pChild = Amap_LibertyItem(p, pItem->Child); pChild; pChild = Amap_LibertyItem(p, pChild->Next) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prints parse tree in Liberty format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibertyPrintLibertyItem( FILE * pFile, Amap_Tree_t * p, Amap_Item_t * pItem, int nOffset ) { if ( pItem->Type == AMAP_LIBERTY_PROC ) { Amap_PrintSpace( pFile, nOffset ); Amap_PrintWord( pFile, p, pItem->Key ); fprintf( pFile, "(" ); Amap_PrintWord( pFile, p, pItem->Head ); fprintf( pFile, ") {\n" ); if ( Amap_LibertyItem(p, pItem->Child) ) Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyItem(p, pItem->Child), nOffset + 1 ); Amap_PrintSpace( pFile, nOffset ); fprintf( pFile, "}\n" ); } else if ( pItem->Type == AMAP_LIBERTY_EQUA ) { Amap_PrintSpace( pFile, nOffset ); Amap_PrintWord( pFile, p, pItem->Key ); fprintf( pFile, " : " ); Amap_PrintWord( pFile, p, pItem->Head ); fprintf( pFile, ";\n" ); } else if ( pItem->Type == AMAP_LIBERTY_LIST ) { Amap_PrintSpace( pFile, nOffset ); Amap_PrintWord( pFile, p, pItem->Key ); fprintf( pFile, "(" ); Amap_PrintWord( pFile, p, pItem->Head ); fprintf( pFile, ");\n" ); } else assert( 0 ); if ( Amap_LibertyItem(p, pItem->Next) ) Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyItem(p, pItem->Next), nOffset ); } /**Function************************************************************* Synopsis [Prints parse tree in Liberty format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibertyPrintLiberty( Amap_Tree_t * p, char * pFileName ) { FILE * pFile; if ( pFileName == NULL ) pFile = stdout; else { pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Amap_LibertyPrintLiberty(): The output file is unavailable (absent or open).\n" ); return 0; } } Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyRoot(p), 0 ); if ( pFile != stdout ) fclose( pFile ); return 1; } /**Function************************************************************* Synopsis [Returns the time stamp.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Amap_LibertyTimeStamp() { static char Buffer[100]; char * TimeStamp; time_t ltime; // get the current time time( <ime ); TimeStamp = asctime( localtime( <ime ) ); TimeStamp[ strlen(TimeStamp) - 1 ] = 0; assert( strlen(TimeStamp) < 100 ); strcpy( Buffer, TimeStamp ); return Buffer; } /**Function************************************************************* Synopsis [Returns cell's function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibertyCellIsFlop( Amap_Tree_t * p, Amap_Item_t * pCell ) { Amap_Item_t * pAttr; Amap_ItemForEachChild( p, pCell, pAttr ) if ( !Amap_LibertyCompare(p, pAttr->Key, "ff") || !Amap_LibertyCompare(p, pAttr->Key, "latch") ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns pin's function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Item_t * Amap_LibertyPinFunction( Amap_Tree_t * p, Amap_Item_t * pPin ) { Amap_Item_t * pFunc; Amap_ItemForEachChild( p, pPin, pFunc ) if ( !Amap_LibertyCompare(p, pFunc->Key, "function") ) return pFunc; return NULL; } /**Function************************************************************* Synopsis [Returns output pin(s).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Item_t * Amap_LibertyCellOutput( Amap_Tree_t * p, Amap_Item_t * pCell ) { Amap_Item_t * pPin; Amap_ItemForEachChild( p, pCell, pPin ) { if ( Amap_LibertyCompare(p, pPin->Key, "pin") ) continue; if ( Amap_LibertyPinFunction(p, pPin) ) return pPin; } return NULL; } Vec_Ptr_t * Amap_LibertyCellOutputs( Amap_Tree_t * p, Amap_Item_t * pCell ) { Amap_Item_t * pPin; Vec_Ptr_t * vOutPins; vOutPins = Vec_PtrAlloc( 2 ); Amap_ItemForEachChild( p, pCell, pPin ) { if ( Amap_LibertyCompare(p, pPin->Key, "pin") ) continue; if ( Amap_LibertyPinFunction(p, pPin) ) Vec_PtrPush( vOutPins, pPin ); } return vOutPins; } /**Function************************************************************* Synopsis [Returns cell's area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Item_t * Amap_LibertyCellArea( Amap_Tree_t * p, Amap_Item_t * pCell ) { Amap_Item_t * pArea; Amap_ItemForEachChild( p, pCell, pArea ) { if ( Amap_LibertyCompare(p, pArea->Key, "area") ) continue; return pArea; } return NULL; } /**Function************************************************************* Synopsis [Count cell's output pins (pins with a logic function).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibertyCellCountOutputs( Amap_Tree_t * p, Amap_Item_t * pCell ) { Amap_Item_t * pPin; int Counter = 0; Amap_ItemForEachChild( p, pCell, pPin ) { if ( Amap_LibertyCompare(p, pPin->Key, "pin") ) continue; if ( Amap_LibertyPinFunction(p, pPin) ) Counter++; } return Counter; } /**Function************************************************************* Synopsis [Gets the name to write.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Amap_LibertyGetString( Amap_Tree_t * p, Amap_Pair_t Pair ) { static char Buffer[ABC_MAX_LIB_STR_LEN]; assert( Pair.End-Pair.Beg < ABC_MAX_LIB_STR_LEN ); strncpy( Buffer, p->pContents+Pair.Beg, Pair.End-Pair.Beg ); Buffer[Pair.End-Pair.Beg] = 0; return Buffer; } /**Function************************************************************* Synopsis [Gets the name to write.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Amap_LibertyGetStringFormula( Amap_Tree_t * p, Amap_Pair_t Pair ) { static char Buffer[ABC_MAX_LIB_STR_LEN]; assert( Pair.End-Pair.Beg-2 < ABC_MAX_LIB_STR_LEN ); strncpy( Buffer, p->pContents+Pair.Beg+1, Pair.End-Pair.Beg-2 ); Buffer[Pair.End-Pair.Beg-2] = 0; return Buffer; } /**Function************************************************************* Synopsis [Prints parse tree in Genlib format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibertyPrintGenlib( Amap_Tree_t * p, char * pFileName, int fVerbose ) { FILE * pFile; Vec_Ptr_t * vOutputs; Amap_Item_t * pCell, * pArea, * pFunc, * pPin, * pOutput; char * pForm; int i, Counter; if ( pFileName == NULL ) pFile = stdout; else { pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Amap_LibertyPrintGenlib(): The output file is unavailable (absent or open).\n" ); return 0; } } fprintf( pFile, "# This Genlib file was generated by ABC on %s\n", Amap_LibertyTimeStamp() ); fprintf( pFile, "# The standard cell library \"%s\" is from Liberty file \"%s\"\n", Amap_LibertyGetString(p, Amap_LibertyRoot(p)->Head), p->pFileName ); fprintf( pFile, "# (To find out more about Genlib format, google for \"sis_paper.ps\")\n" ); fprintf( pFile, "GATE " ); fprintf( pFile, "%16s ", "_const0_" ); fprintf( pFile, "%f ", 0.0 ); fprintf( pFile, "%s=", "z" ); fprintf( pFile, "%s;\n", "CONST0" ); fprintf( pFile, "GATE " ); fprintf( pFile, "%16s ", "_const1_" ); fprintf( pFile, "%f ", 0.0 ); fprintf( pFile, "%s=", "z" ); fprintf( pFile, "%s;\n", "CONST1" ); Amap_ItemForEachChild( p, Amap_LibertyRoot(p), pCell ) { /* if ( strcmp(Amap_LibertyGetString(p, pCell->Head), "HA1SVTX1") == 0 ) { int s = 0; } */ if ( Amap_LibertyCompare(p, pCell->Key, "cell") ) continue; if ( Amap_LibertyCellIsFlop(p, pCell) ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } Counter = Amap_LibertyCellCountOutputs( p, pCell ); if ( Counter == 0 ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" without logic function.\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } /* if ( Counter > 1 ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped multi-output cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } */ pArea = Amap_LibertyCellArea( p, pCell ); if ( pArea == NULL ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with unspecified area.\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } // pOutput = Amap_LibertyCellOutput( p, pCell ); vOutputs = Amap_LibertyCellOutputs( p, pCell ); Vec_PtrForEachEntry( Amap_Item_t *, vOutputs, pOutput, i ) { pFunc = Amap_LibertyPinFunction( p, pOutput ); pForm = Amap_LibertyGetStringFormula( p, pFunc->Head ); if ( !strcmp(pForm, "0") || !strcmp(pForm, "1") ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Amap_LibertyGetString(p, pCell->Head), pForm ); continue; } fprintf( pFile, "GATE " ); fprintf( pFile, "%16s ", Amap_LibertyGetString(p, pCell->Head) ); fprintf( pFile, "%f ", atof(Amap_LibertyGetString(p, pArea->Head)) ); fprintf( pFile, "%s=", Amap_LibertyGetString(p, pOutput->Head) ); fprintf( pFile, "%s;\n", Amap_LibertyGetStringFormula(p, pFunc->Head) ); Amap_ItemForEachChild( p, pCell, pPin ) if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") ) fprintf( pFile, " PIN %13s UNKNOWN 1 999 1.00 0.00 1.00 0.00\n", Amap_LibertyGetString(p, pPin->Head) ); } Vec_PtrFree( vOutputs ); } if ( pFile != stdout ) fclose( pFile ); return 1; } /**Function************************************************************* Synopsis [Prints parse tree in Genlib format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Amap_LibertyPrintGenlibStr( Amap_Tree_t * p, int fVerbose ) { Vec_Str_t * vStr; char Buffer[100]; Vec_Ptr_t * vOutputs; Amap_Item_t * pCell, * pArea, * pFunc, * pPin, * pOutput; int i, Counter; char * pForm; vStr = Vec_StrAlloc( 1000 ); Vec_StrPrintStr( vStr, "GATE _const0_ 0.000000 z=CONST0;\n" ); Vec_StrPrintStr( vStr, "GATE _const1_ 0.000000 z=CONST1;\n" ); Amap_ItemForEachChild( p, Amap_LibertyRoot(p), pCell ) { if ( Amap_LibertyCompare(p, pCell->Key, "cell") ) continue; if ( Amap_LibertyCellIsFlop(p, pCell) ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } Counter = Amap_LibertyCellCountOutputs( p, pCell ); if ( Counter == 0 ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" without logic function.\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } pArea = Amap_LibertyCellArea( p, pCell ); if ( pArea == NULL ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with unspecified area.\n", Amap_LibertyGetString(p, pCell->Head) ); continue; } vOutputs = Amap_LibertyCellOutputs( p, pCell ); Vec_PtrForEachEntry( Amap_Item_t *, vOutputs, pOutput, i ) { pFunc = Amap_LibertyPinFunction( p, pOutput ); pForm = Amap_LibertyGetStringFormula( p, pFunc->Head ); if ( !strcmp(pForm, "0") || !strcmp(pForm, "1") ) { if ( fVerbose ) printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Amap_LibertyGetString(p, pCell->Head), pForm ); continue; } /* fprintf( pFile, "GATE " ); fprintf( pFile, "%16s ", Amap_LibertyGetString(p, pCell->Head) ); fprintf( pFile, "%f ", atof(Amap_LibertyGetString(p, pArea->Head)) ); fprintf( pFile, "%s=", Amap_LibertyGetString(p, pOutput->Head) ); fprintf( pFile, "%s;\n", Amap_LibertyGetStringFormula(p, pFunc->Head) ); Amap_ItemForEachChild( p, pCell, pPin ) if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") ) fprintf( pFile, " PIN %13s UNKNOWN 1 999 1.00 0.00 1.00 0.00\n", Amap_LibertyGetString(p, pPin->Head) ); */ Vec_StrPrintStr( vStr, "GATE " ); Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pCell->Head) ); Vec_StrPrintStr( vStr, " " ); sprintf( Buffer, "%f", atof(Amap_LibertyGetString(p, pArea->Head)) ); Vec_StrPrintStr( vStr, Buffer ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pOutput->Head) ); Vec_StrPrintStr( vStr, "=" ); Vec_StrPrintStr( vStr, Amap_LibertyGetStringFormula(p, pFunc->Head) ); Vec_StrPrintStr( vStr, ";\n" ); Amap_ItemForEachChild( p, pCell, pPin ) if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") ) { Vec_StrPrintStr( vStr, " PIN " ); Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pPin->Head) ); Vec_StrPrintStr( vStr, " UNKNOWN 1 999 1.00 0.00 1.00 0.00\n" ); } } Vec_PtrFree( vOutputs ); } Vec_StrPrintStr( vStr, "\n.end\n" ); Vec_StrPush( vStr, '\0' ); // printf( "%s", Vec_StrArray(vStr) ); return vStr; } /**Function************************************************************* Synopsis [Returns the file size.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibertyFileSize( char * pFileName ) { FILE * pFile; int nFileSize; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Amap_LibertyFileSize(): The input 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 [] ***********************************************************************/ void Amap_LibertyFixFileHead( char * pFileName ) { char * pHead; for ( pHead = pFileName; *pHead; pHead++ ) if ( *pHead == '>' ) *pHead = '\\'; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibertyCountItems( char * pBeg, char * pEnd ) { int Counter = 0; for ( ; pBeg < pEnd; pBeg++ ) Counter += (*pBeg == '(' || *pBeg == ':'); return Counter; } /**Function************************************************************* Synopsis [Removes C-style comments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibertyWipeOutComments( char * pBeg, char * pEnd ) { char * pCur, * pStart; for ( pCur = pBeg; pCur < pEnd; pCur++ ) if ( pCur[0] == '/' && pCur[1] == '*' ) for ( pStart = pCur; pCur < pEnd; pCur++ ) if ( pCur[0] == '*' && pCur[1] == '/' ) { for ( ; pStart < pCur + 2; pStart++ ) if ( *pStart != '\n' ) *pStart = ' '; break; } } /**Function************************************************************* Synopsis [Returns 1 if the character is space.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Amap_LibertyCharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\'; } /**Function************************************************************* Synopsis [Skips spaces.] Description [Returns 1 if reached the end.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Amap_LibertySkipSpaces( Amap_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine ) { char * pPos = *ppPos; for ( ; pPos < pEnd; pPos++ ) { if ( *pPos == '\n' ) { p->nLines++; if ( fStopAtNewLine ) break; } if ( !Amap_LibertyCharIsSpace(*pPos) ) break; } *ppPos = pPos; return pPos == pEnd; } /**Function************************************************************* Synopsis [Skips entry delimited by " :;(){}" ] Description [Returns 1 if reached the end.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Amap_LibertySkipEntry( char ** ppPos, char * pEnd ) { char * pPos = *ppPos; if ( *pPos == '\"' ) { for ( pPos++; pPos < pEnd; pPos++ ) if ( *pPos == '\"' ) { pPos++; break; } } else { for ( ; pPos < pEnd; pPos++ ) if ( *pPos == ' ' || *pPos == '\r' || *pPos == '\n' || *pPos == '\t' || *pPos == ':' || *pPos == ';' || *pPos == '(' || *pPos == ')' || *pPos == '{' || *pPos == '}' ) break; } *ppPos = pPos; return pPos == pEnd; } /**Function************************************************************* Synopsis [Find the matching closing symbol.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char * Amap_LibertyFindMatch( char * pPos, char * pEnd ) { int Counter = 0; assert( *pPos == '(' || *pPos == '{' ); if ( *pPos == '(' ) { for ( ; pPos < pEnd; pPos++ ) { if ( *pPos == '(' ) Counter++; if ( *pPos == ')' ) Counter--; if ( Counter == 0 ) break; } } else { for ( ; pPos < pEnd; pPos++ ) { if ( *pPos == '{' ) Counter++; if ( *pPos == '}' ) Counter--; if ( Counter == 0 ) break; } } assert( *pPos == ')' || *pPos == '}' ); return pPos; } /**Function************************************************************* Synopsis [Find the matching closing symbol.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Amap_Pair_t Amap_LibertyUpdateHead( Amap_Tree_t * p, Amap_Pair_t Head ) { Amap_Pair_t Res; char * pBeg = p->pContents + Head.Beg; char * pEnd = p->pContents + Head.End; char * pFirstNonSpace = NULL; char * pLastNonSpace = NULL; char * pChar; for ( pChar = pBeg; pChar < pEnd; pChar++ ) { if ( *pChar == '\n' ) p->nLines++; if ( Amap_LibertyCharIsSpace(*pChar) ) continue; pLastNonSpace = pChar; if ( pFirstNonSpace == NULL ) pFirstNonSpace = pChar; } if ( pFirstNonSpace == NULL || pLastNonSpace == NULL ) return Head; assert( pFirstNonSpace && pLastNonSpace ); Res.Beg = pFirstNonSpace - p->pContents; Res.End = pLastNonSpace - p->pContents + 1; return Res; } /**Function************************************************************* Synopsis [Returns free item.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Amap_Item_t * Amap_LibertyNewItem( Amap_Tree_t * p, int Type ) { p->pItems[p->nItems].iLine = p->nLines; p->pItems[p->nItems].Type = Type; p->pItems[p->nItems].Child = -1; p->pItems[p->nItems].Next = -1; return p->pItems + p->nItems++; } /**Function************************************************************* Synopsis [Returns free item.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibertyBuildItem( Amap_Tree_t * p, char ** ppPos, char * pEnd ) { Amap_Item_t * pItem; Amap_Pair_t Key, Head, Body; char * pNext, * pStop; Key.End = 0; if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) return -2; Key.Beg = *ppPos - p->pContents; if ( Amap_LibertySkipEntry( ppPos, pEnd ) ) goto exit; Key.End = *ppPos - p->pContents; if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) goto exit; pNext = *ppPos; if ( *pNext == ':' ) { *ppPos = pNext + 1; if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) goto exit; Head.Beg = *ppPos - p->pContents; if ( Amap_LibertySkipEntry( ppPos, pEnd ) ) goto exit; Head.End = *ppPos - p->pContents; if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 1 ) ) goto exit; pNext = *ppPos; if ( *pNext != ';' && *pNext != '\n' ) goto exit; *ppPos = pNext + 1; // end of equation pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_EQUA ); pItem->Key = Key; pItem->Head = Amap_LibertyUpdateHead( p, Head ); pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd ); if ( pItem->Next == -1 ) goto exit; return Amap_LibertyItemId( p, pItem ); } if ( *pNext == '(' ) { pStop = Amap_LibertyFindMatch( pNext, pEnd ); Head.Beg = pNext - p->pContents + 1; Head.End = pStop - p->pContents; *ppPos = pStop + 1; if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) { // end of list pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_LIST ); pItem->Key = Key; pItem->Head = Amap_LibertyUpdateHead( p, Head ); return Amap_LibertyItemId( p, pItem ); } pNext = *ppPos; if ( *pNext == '{' ) // beginning of body { pStop = Amap_LibertyFindMatch( pNext, pEnd ); Body.Beg = pNext - p->pContents + 1; Body.End = pStop - p->pContents; // end of body pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_PROC ); pItem->Key = Key; pItem->Head = Amap_LibertyUpdateHead( p, Head ); pItem->Body = Body; *ppPos = pNext + 1; pItem->Child = Amap_LibertyBuildItem( p, ppPos, pStop ); if ( pItem->Child == -1 ) goto exit; *ppPos = pStop + 1; pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd ); if ( pItem->Next == -1 ) goto exit; return Amap_LibertyItemId( p, pItem ); } // end of list if ( *pNext == ';' ) *ppPos = pNext + 1; pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_LIST ); pItem->Key = Key; pItem->Head = Amap_LibertyUpdateHead( p, Head ); pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd ); if ( pItem->Next == -1 ) goto exit; return Amap_LibertyItemId( p, pItem ); } exit: if ( p->pError == NULL ) { p->pError = ABC_ALLOC( char, 1000 ); sprintf( p->pError, "File \"%s\". Line %6d. Failed to parse entry \"%s\".\n", p->pFileName, p->nLines, Amap_LibertyGetString(p, Key) ); } return -1; } /**Function************************************************************* Synopsis [Starts the parsing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Tree_t * Amap_LibertyStart( char * pFileName ) { FILE * pFile; Amap_Tree_t * p; int RetValue; // start the manager p = ABC_ALLOC( Amap_Tree_t, 1 ); memset( p, 0, sizeof(Amap_Tree_t) ); // read the file into the buffer Amap_LibertyFixFileHead( pFileName ); p->nContents = Amap_LibertyFileSize( pFileName ); if ( p->nContents == 0 ) { ABC_FREE( p ); return NULL; } pFile = fopen( pFileName, "rb" ); p->pContents = ABC_ALLOC( char, p->nContents+1 ); RetValue = fread( p->pContents, p->nContents, 1, pFile ); fclose( pFile ); p->pContents[p->nContents] = 0; // other p->pFileName = Abc_UtilStrsav( pFileName ); p->nItermAlloc = 10 + Amap_LibertyCountItems( p->pContents, p->pContents+p->nContents ); p->pItems = ABC_CALLOC( Amap_Item_t, p->nItermAlloc ); p->nItems = 0; p->nLines = 1; return p; } /**Function************************************************************* Synopsis [Stops the parsing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibertyStop( Amap_Tree_t * p ) { ABC_FREE( p->pFileName ); ABC_FREE( p->pContents ); ABC_FREE( p->pItems ); ABC_FREE( p->pError ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Parses the standard cell library in Liberty format.] Description [Writes the resulting file in Genlib format.] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibertyParse( char * pFileName, int fVerbose ) { Amap_Tree_t * p; char * pPos; abctime clk = Abc_Clock(); int RetValue; p = Amap_LibertyStart( pFileName ); if ( p == NULL ) return 0; pPos = p->pContents; Amap_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents ); if ( Amap_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 ) { if ( fVerbose ) printf( "Parsing finished successfully.\n" ); // Amap_LibertyPrintLiberty( p, "temp_.lib" ); Amap_LibertyPrintGenlib( p, Extra_FileNameGenericAppend(pFileName, ".genlib"), fVerbose ); RetValue = 1; } else { if ( p->pError ) printf( "%s", p->pError ); if ( fVerbose ) printf( "Parsing failed.\n" ); RetValue = 0; } if ( fVerbose ) { printf( "Memory = %7.2f MB. ", 1.0*(p->nContents+p->nItermAlloc*sizeof(Amap_Item_t))/(1<<20) ); ABC_PRT( "Time", Abc_Clock() - clk ); } Amap_LibertyStop( p ); return RetValue; } /**Function************************************************************* Synopsis [Parses the standard cell library in Liberty format.] Description [Writes the resulting file in Genlib format.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Amap_LibertyParseStr( char * pFileName, int fVerbose ) { Amap_Tree_t * p; Vec_Str_t * vStr = NULL; char * pPos; abctime clk = Abc_Clock(); int RetValue; p = Amap_LibertyStart( pFileName ); if ( p == NULL ) return 0; pPos = p->pContents; Amap_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents ); if ( Amap_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 ) { if ( fVerbose ) printf( "Parsing finished successfully.\n" ); // Amap_LibertyPrintLiberty( p, "temp_.lib" ); vStr = Amap_LibertyPrintGenlibStr( p, fVerbose ); RetValue = 1; } else { if ( p->pError ) printf( "%s", p->pError ); if ( fVerbose ) printf( "Parsing failed.\n" ); RetValue = 0; } if ( fVerbose ) { printf( "Memory = %7.2f MB. ", 1.0*(p->nContents+p->nItermAlloc*sizeof(Amap_Item_t))/(1<<20) ); ABC_PRT( "Time", Abc_Clock() - clk ); } Amap_LibertyStop( p ); return vStr; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapMan.c000066400000000000000000000056441300674244400232560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Mapping manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Man_t * Amap_ManStart( int nNodes ) { Amap_Man_t * p; // start the manager p = ABC_ALLOC( Amap_Man_t, 1 ); memset( p, 0, sizeof(Amap_Man_t) ); p->fEpsilonInternal = (float)0.01; // allocate arrays for nodes p->vPis = Vec_PtrAlloc( 100 ); p->vPos = Vec_PtrAlloc( 100 ); p->vObjs = Vec_PtrAlloc( 100 ); p->vTemp = Vec_IntAlloc( 100 ); p->vCuts0 = Vec_PtrAlloc( 100 ); p->vCuts1 = Vec_PtrAlloc( 100 ); p->vCuts2 = Vec_PtrAlloc( 100 ); // prepare the memory manager p->pMemObj = Aig_MmFixedStart( sizeof(Amap_Obj_t), nNodes ); p->pMemCuts = Aig_MmFlexStart(); p->pMemCutBest = Aig_MmFlexStart(); p->pMemTemp = Aig_MmFlexStart(); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManStop( Amap_Man_t * p ) { Vec_PtrFree( p->vPis ); Vec_PtrFree( p->vPos ); Vec_PtrFree( p->vObjs ); Vec_PtrFree( p->vCuts0 ); Vec_PtrFree( p->vCuts1 ); Vec_PtrFree( p->vCuts2 ); Vec_IntFree( p->vTemp ); Aig_MmFixedStop( p->pMemObj, 0 ); Aig_MmFlexStop( p->pMemCuts, 0 ); Aig_MmFlexStop( p->pMemCutBest, 0 ); Aig_MmFlexStop( p->pMemTemp, 0 ); ABC_FREE( p->pMatsTemp ); ABC_FREE( p->ppCutsTemp ); ABC_FREE( p->pCutsPi ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapMatch.c000066400000000000000000000437431300674244400236010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapMatch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapMatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Duplicates the cut using new memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Cut_t * Amap_ManDupCut( Amap_Man_t * p, Amap_Cut_t * pCut ) { Amap_Cut_t * pNew; int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * pCut->nFans; pNew = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCutBest, nBytes ); memcpy( pNew, pCut, nBytes ); return pNew; } /**Function************************************************************* Synopsis [Starts the match with cut and set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Amap_ManMatchStart( Amap_Mat_t * p, Amap_Cut_t * pCut, Amap_Set_t * pSet ) { memset( p, 0, sizeof(Amap_Mat_t) ); p->pCut = pCut; p->pSet = pSet; } /**Function************************************************************* Synopsis [Cleans reference counters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCleanRefs( Amap_Man_t * p ) { Amap_Obj_t * pObj; int i; Amap_ManForEachObj( p, pObj, i ) pObj->nFouts[0] = pObj->nFouts[1] = 0; } /**Function************************************************************* Synopsis [Computes delay.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Amap_ManMaxDelay( Amap_Man_t * p ) { Amap_Obj_t * pObj; float Delay = 0.0; int i; Amap_ManForEachPo( p, pObj, i ) Delay = Abc_MaxInt( Delay, Amap_ObjFanin0(p,pObj)->Best.Delay ); return Delay; } /**Function************************************************************* Synopsis [Cleans reference counters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCleanData( Amap_Man_t * p ) { Amap_Obj_t * pObj; int i; // Amap_ManForEachNode( p, pObj, i ) // ABC_FREE( pObj->pData ); Amap_ManForEachObj( p, pObj, i ) pObj->pData = NULL; } /**Function************************************************************* Synopsis [Compute nodes used in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Amap_ManComputeMapping_rec( Amap_Man_t * p, Amap_Obj_t * pObj, int fCompl ) { Amap_Mat_t * pM = &pObj->Best; Amap_Obj_t * pFanin; Amap_Gat_t * pGate; int i, iFanin, fComplFanin; float Area; if ( pObj->nFouts[fCompl]++ + pObj->nFouts[!fCompl] > 0 ) return 0.0; if ( Amap_ObjIsPi(pObj) || Amap_ObjIsConst1(pObj) ) return 0.0; pGate = Amap_LibGate( p->pLib, pM->pSet->iGate ); assert( pGate->nPins == pM->pCut->nFans ); Area = pGate->dArea; for ( i = 0; i < (int)pGate->nPins; i++ ) { iFanin = Abc_Lit2Var( pM->pSet->Ins[i] ); pFanin = Amap_ManObj( p, Abc_Lit2Var(pM->pCut->Fans[iFanin]) ); fComplFanin = Abc_LitIsCompl( pM->pSet->Ins[i] ) ^ Abc_LitIsCompl( pM->pCut->Fans[iFanin] ); Area += Amap_ManComputeMapping_rec( p, pFanin, fComplFanin ); } return Area; } /**Function************************************************************* Synopsis [Compute nodes used in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Amap_ManComputeMapping( Amap_Man_t * p ) { Amap_Obj_t * pObj; float Area = 0.0; int i; Amap_ManCleanRefs( p ); Amap_ManForEachPo( p, pObj, i ) Area += Amap_ManComputeMapping_rec( p, Amap_ObjFanin0(p, pObj), Amap_ObjFaninC0(pObj) ); return Area; } /**Function************************************************************* Synopsis [Counts the number of inverters to be added.] Description [Should be called after mapping has been set.] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_ManCountInverters( Amap_Man_t * p ) { Amap_Obj_t * pObj; int i, Counter = 0; Amap_ManForEachObj( p, pObj, i ) Counter += (int)(pObj->nFouts[!pObj->fPolar] > 0); return Counter; } /**Function************************************************************* Synopsis [Compare two matches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Amap_CutCompareDelay( Amap_Man_t * p, Amap_Mat_t * pM0, Amap_Mat_t * pM1 ) { // compare delay if ( pM0->Delay < pM1->Delay - p->pPars->fEpsilon ) return -1; if ( pM0->Delay > pM1->Delay + p->pPars->fEpsilon ) return 1; // compare area flows if ( pM0->Area < pM1->Area - p->pPars->fEpsilon ) return -1; if ( pM0->Area > pM1->Area + p->pPars->fEpsilon ) return 1; // compare average fanouts if ( pM0->AveFan > pM1->AveFan - p->pPars->fEpsilon ) return -1; if ( pM0->AveFan < pM1->AveFan + p->pPars->fEpsilon ) return 1; return 1; } static inline int Amap_CutCompareArea( Amap_Man_t * p, Amap_Mat_t * pM0, Amap_Mat_t * pM1 ) { // compare area flows if ( pM0->Area < pM1->Area - p->pPars->fEpsilon ) return -1; if ( pM0->Area > pM1->Area + p->pPars->fEpsilon ) return 1; // compare average fanouts if ( pM0->AveFan > pM1->AveFan - p->pPars->fEpsilon ) return -1; if ( pM0->AveFan < pM1->AveFan + p->pPars->fEpsilon ) return 1; // compare delay if ( pM0->Delay < pM1->Delay - p->pPars->fEpsilon ) return -1; if ( pM0->Delay > pM1->Delay + p->pPars->fEpsilon ) return 1; return 1; } /**Function************************************************************* Synopsis [Counts area while dereferencing the match.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Amap_CutAreaDeref( Amap_Man_t * p, Amap_Mat_t * pM ) { Amap_Obj_t * pFanin; int i, fCompl; float Area = Amap_LibGate( p->pLib, pM->pSet->iGate )->dArea; Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i ) { assert( Amap_ObjRefsTotal(pFanin) > 0 ); if ( (int)pFanin->fPolar != fCompl && pFanin->nFouts[fCompl] == 1 ) Area += p->fAreaInv; if ( --pFanin->nFouts[fCompl] + pFanin->nFouts[!fCompl] == 0 && Amap_ObjIsNode(pFanin) ) Area += Amap_CutAreaDeref( p, &pFanin->Best ); } return Area; } /**Function************************************************************* Synopsis [Counts area while referencing the match.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Amap_CutAreaRef( Amap_Man_t * p, Amap_Mat_t * pM ) { Amap_Obj_t * pFanin; int i, fCompl; float Area = Amap_LibGate( p->pLib, pM->pSet->iGate )->dArea; Amap_MatchForEachFaninCompl( p, pM, pFanin, fCompl, i ) { assert( Amap_ObjRefsTotal(pFanin) >= 0 ); if ( (int)pFanin->fPolar != fCompl && pFanin->nFouts[fCompl] == 0 ) Area += p->fAreaInv; if ( pFanin->nFouts[fCompl]++ + pFanin->nFouts[!fCompl] == 0 && Amap_ObjIsNode(pFanin) ) Area += Amap_CutAreaRef( p, &pFanin->Best ); } return Area; } /**Function************************************************************* Synopsis [Derives area of the match for a non-referenced node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Amap_CutAreaDerefed( Amap_Man_t * p, Amap_Obj_t * pNode, Amap_Mat_t * pM ) { float aResult, aResult2; int fComplNew; aResult2 = Amap_CutAreaRef( p, pM ); aResult = Amap_CutAreaDeref( p, pM ); assert( aResult > aResult2 - p->fEpsilonInternal ); assert( aResult < aResult2 + p->fEpsilonInternal ); // if node is needed in another polarity, add inverter fComplNew = pM->pCut->fInv ^ pM->pSet->fInv; if ( pNode->nFouts[fComplNew] == 0 && pNode->nFouts[!fComplNew] > 0 ) aResult += p->fAreaInv; return aResult; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Amap_CutAreaTest( Amap_Man_t * p, Amap_Obj_t * pNode ) { float aResult, aResult2; if ( Amap_ObjRefsTotal(pNode) == 0 ) { aResult2 = Amap_CutAreaRef( p, &pNode->Best ); aResult = Amap_CutAreaDeref( p, &pNode->Best ); assert( aResult > aResult2 - p->fEpsilonInternal ); assert( aResult < aResult2 + p->fEpsilonInternal ); } else { aResult = Amap_CutAreaDeref( p, &pNode->Best ); aResult2 = Amap_CutAreaRef( p, &pNode->Best ); assert( aResult > aResult2 - p->fEpsilonInternal ); assert( aResult < aResult2 + p->fEpsilonInternal ); } } /**Function************************************************************* Synopsis [Derives parameters for the match.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Amap_ManMatchGetFlows( Amap_Man_t * p, Amap_Mat_t * pM ) { Amap_Mat_t * pMFanin; Amap_Obj_t * pFanin; Amap_Gat_t * pGate; int i; pGate = Amap_LibGate( p->pLib, pM->pSet->iGate ); assert( pGate->nPins == pM->pCut->nFans ); assert( pM->Area == 0.0 ); pM->Area = pGate->dArea; pM->AveFan = 0.0; pM->Delay = 0.0; Amap_MatchForEachFanin( p, pM, pFanin, i ) { pMFanin = &pFanin->Best; pM->Delay = Abc_MaxInt( pM->Delay, pMFanin->Delay ); pM->AveFan += Amap_ObjRefsTotal(pFanin); if ( Amap_ObjRefsTotal(pFanin) == 0 ) pM->Area += pMFanin->Area; else pM->Area += pMFanin->Area / pFanin->EstRefs; } pM->AveFan /= pGate->nPins; pM->Delay += 1.0; } /**Function************************************************************* Synopsis [Derives parameters for the match.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Amap_ManMatchGetExacts( Amap_Man_t * p, Amap_Obj_t * pNode, Amap_Mat_t * pM ) { Amap_Mat_t * pMFanin; Amap_Obj_t * pFanin; Amap_Gat_t * pGate; int i; pGate = Amap_LibGate( p->pLib, pM->pSet->iGate ); assert( pGate->nPins == pM->pCut->nFans ); assert( pM->Area == 0.0 ); pM->AveFan = 0.0; pM->Delay = 0.0; Amap_MatchForEachFanin( p, pM, pFanin, i ) { pMFanin = &pFanin->Best; pM->Delay = Abc_MaxInt( pM->Delay, pMFanin->Delay ); pM->AveFan += Amap_ObjRefsTotal(pFanin); } pM->AveFan /= pGate->nPins; pM->Delay += 1.0; pM->Area = Amap_CutAreaDerefed( p, pNode, pM ); } /**Function************************************************************* Synopsis [Computes the best match at each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManMatchNode( Amap_Man_t * p, Amap_Obj_t * pNode, int fFlow, int fRefs ) { int fVerbose = 0; //(pNode->Level == 2 || pNode->Level == 4); int fVeryVerbose = fVerbose; Amap_Mat_t MA = {0}, MD = {0}, M = {0}; Amap_Mat_t * pMBestA = &MA, * pMBestD = &MD, * pMThis = &M, * pMBest; Amap_Cut_t * pCut; Amap_Set_t * pSet; Amap_Nod_t * pNod; int i; if ( fRefs ) pNode->EstRefs = (float)((2.0 * pNode->EstRefs + Amap_ObjRefsTotal(pNode)) / 3.0); else pNode->EstRefs = (float)pNode->nRefs; if ( fRefs && Amap_ObjRefsTotal(pNode) > 0 ) Amap_CutAreaDeref( p, &pNode->Best ); if ( fVerbose ) printf( "\nNode %d (%d)\n", pNode->Id, pNode->Level ); pMBestA->pCut = pMBestD->pCut = NULL; Amap_NodeForEachCut( pNode, pCut, i ) { if ( pCut->iMat == 0 ) continue; pNod = Amap_LibNod( p->pLib, pCut->iMat ); Amap_LibNodeForEachSet( pNod, pSet ) { Amap_ManMatchStart( pMThis, pCut, pSet ); if ( fFlow ) Amap_ManMatchGetFlows( p, pMThis ); else Amap_ManMatchGetExacts( p, pNode, pMThis ); if ( pMBestD->pCut == NULL || Amap_CutCompareDelay(p, pMBestD, pMThis) == 1 ) *pMBestD = *pMThis; if ( pMBestA->pCut == NULL || Amap_CutCompareArea(p, pMBestA, pMThis) == 1 ) *pMBestA = *pMThis; if ( fVeryVerbose ) { printf( "Cut %2d (%d) : ", i, pCut->nFans ); printf( "Gate %10s ", Amap_LibGate(p->pLib, pMThis->pSet->iGate)->pName ); printf( "%s ", pMThis->pSet->fInv ? "inv" : " " ); printf( "Delay %5.2f ", pMThis->Delay ); printf( "Area %5.2f ", pMThis->Area ); printf( "\n" ); } } } if ( Abc_AbsFloat(pMBestA->Area - pMBestD->Area) / pMBestD->Area >= p->pPars->fADratio * Abc_AbsFloat(pMBestA->Delay - pMBestD->Delay) / pMBestA->Delay ) pMBest = pMBestA; else pMBest = pMBestD; if ( fVerbose ) { printf( "BEST MATCHA: " ); printf( "Gate %10s ", Amap_LibGate(p->pLib, pMBestA->pSet->iGate)->pName ); printf( "%s ", pMBestA->pSet->fInv ? "inv" : " " ); printf( "Delay %5.2f ", pMBestA->Delay ); printf( "Area %5.2f ", pMBestA->Area ); printf( "\n" ); printf( "BEST MATCHD: " ); printf( "Gate %10s ", Amap_LibGate(p->pLib, pMBestD->pSet->iGate)->pName ); printf( "%s ", pMBestD->pSet->fInv ? "inv" : " " ); printf( "Delay %5.2f ", pMBestD->Delay ); printf( "Area %5.2f ", pMBestD->Area ); printf( "\n" ); printf( "BEST MATCH : " ); printf( "Gate %10s ", Amap_LibGate(p->pLib, pMBest->pSet->iGate)->pName ); printf( "%s ", pMBest->pSet->fInv ? "inv" : " " ); printf( "Delay %5.2f ", pMBest->Delay ); printf( "Area %5.2f ", pMBest->Area ); printf( "\n" ); } pNode->fPolar = pMBest->pCut->fInv ^ pMBest->pSet->fInv; pNode->Best = *pMBest; pNode->Best.pCut = Amap_ManDupCut( p, pNode->Best.pCut ); if ( fRefs && Amap_ObjRefsTotal(pNode) > 0 ) Amap_CutAreaRef( p, &pNode->Best ); } /**Function************************************************************* Synopsis [Performs one round of mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManMatch( Amap_Man_t * p, int fFlow, int fRefs ) { Aig_MmFlex_t * pMemOld; Amap_Obj_t * pObj; float Area; int i, nInvs; abctime clk = Abc_Clock(); pMemOld = p->pMemCutBest; p->pMemCutBest = Aig_MmFlexStart(); Amap_ManForEachNode( p, pObj, i ) if ( pObj->pData ) Amap_ManMatchNode( p, pObj, fFlow, fRefs ); Aig_MmFlexStop( pMemOld, 0 ); Area = Amap_ManComputeMapping( p ); nInvs = Amap_ManCountInverters( p ); if ( p->pPars->fVerbose ) { printf( "Area =%9.2f. Gate =%9.2f. Inv =%9.2f. (%6d.) Delay =%6.2f. ", Area + nInvs * p->fAreaInv, Area, nInvs * p->fAreaInv, nInvs, Amap_ManMaxDelay(p) ); ABC_PRT( "Time ", Abc_Clock() - clk ); } // test procedures // Amap_ManForEachNode( p, pObj, i ) // Amap_CutAreaTest( p, pObj ); } /**Function************************************************************* Synopsis [Performs mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManMap( Amap_Man_t * p ) { int i; Amap_ManMerge( p ); for ( i = 0; i < p->pPars->nIterFlow; i++ ) Amap_ManMatch( p, 1, i>0 ); for ( i = 0; i < p->pPars->nIterArea; i++ ) Amap_ManMatch( p, 0, p->pPars->nIterFlow>0||i>0 ); /* for ( i = 0; i < p->pPars->nIterFlow; i++ ) Amap_ManMatch( p, 1, 1 ); for ( i = 0; i < p->pPars->nIterArea; i++ ) Amap_ManMatch( p, 0, 1 ); */ Amap_ManCleanData( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapMerge.c000066400000000000000000000433531300674244400236010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapMerge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Computing cuts for the node.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates new cut and adds it to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Cut_t * Amap_ManSetupPis( Amap_Man_t * p ) { Amap_Obj_t * pObj; Amap_Cut_t * pCut; int i, nBytes = sizeof(Amap_Cut_t) + sizeof(int); char * pBuffer = ABC_ALLOC( char, Amap_ManPiNum(p) * nBytes ); Amap_ManForEachPi( p, pObj, i ) { pCut = (Amap_Cut_t *)( pBuffer + i*nBytes ); pCut->iMat = 0; pCut->fInv = 0; pCut->nFans = 1; pCut->Fans[0] = Abc_Var2Lit( pObj->Id, 0 ); pObj->pData = pCut; pObj->nCuts = 1; pObj->EstRefs = (float)1.0; } return (Amap_Cut_t *)pBuffer; } /**Function************************************************************* Synopsis [Creates new cut and adds it to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Cut_t * Amap_ManCutStore( Amap_Man_t * p, Amap_Cut_t * pCut, int fCompl ) { Amap_Cut_t * pNew; int iFan, nBytes = sizeof(Amap_Cut_t) + sizeof(int) * pCut->nFans + sizeof(Amap_Cut_t *); pNew = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes ); pNew->iMat = pCut->iMat; pNew->fInv = pCut->fInv ^ fCompl; pNew->nFans = pCut->nFans; memcpy( pNew->Fans, pCut->Fans, sizeof(int) * pCut->nFans ); // add it to storage iFan = Abc_Var2Lit( pNew->iMat, pNew->fInv ); if ( p->ppCutsTemp[ iFan ] == NULL ) Vec_IntPushOrder( p->vTemp, iFan ); *Amap_ManCutNextP( pNew ) = p->ppCutsTemp[ iFan ]; p->ppCutsTemp[ iFan ] = pNew; return pNew; } /**Function************************************************************* Synopsis [Creates new cut and adds it to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Cut_t * Amap_ManCutCreate( Amap_Man_t * p, Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, int iMat ) { Amap_Cut_t * pCut; int i, nSize = pCut0->nFans + pCut1->nFans; int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * nSize + sizeof(Amap_Cut_t *); assert( pCut0->iMat >= pCut1->iMat ); pCut = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes ); pCut->iMat = iMat; pCut->fInv = 0; pCut->nFans = nSize; for ( i = 0; i < (int)pCut0->nFans; i++ ) pCut->Fans[i] = pCut0->Fans[i]; for ( i = 0; i < (int)pCut1->nFans; i++ ) pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i]; // add it to storage if ( p->ppCutsTemp[ pCut->iMat ] == NULL ) Vec_IntPushOrder( p->vTemp, pCut->iMat ); *Amap_ManCutNextP( pCut ) = p->ppCutsTemp[ pCut->iMat ]; p->ppCutsTemp[ pCut->iMat ] = pCut; return pCut; } /**Function************************************************************* Synopsis [Creates new cut and adds it to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Cut_t * Amap_ManCutCreate3( Amap_Man_t * p, Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, Amap_Cut_t * pCut2, int iMat ) { Amap_Cut_t * pCut; int i, nSize = pCut0->nFans + pCut1->nFans + pCut2->nFans; int nBytes = sizeof(Amap_Cut_t) + sizeof(int) * nSize + sizeof(Amap_Cut_t *); pCut = (Amap_Cut_t *)Aig_MmFlexEntryFetch( p->pMemTemp, nBytes ); pCut->iMat = iMat; pCut->fInv = 0; pCut->nFans = nSize; for ( i = 0; i < (int)pCut0->nFans; i++ ) pCut->Fans[i] = pCut0->Fans[i]; for ( i = 0; i < (int)pCut1->nFans; i++ ) pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i]; for ( i = 0; i < (int)pCut2->nFans; i++ ) pCut->Fans[pCut0->nFans+pCut1->nFans+i] = pCut2->Fans[i]; // add it to storage if ( p->ppCutsTemp[ pCut->iMat ] == NULL ) Vec_IntPushOrder( p->vTemp, pCut->iMat ); *Amap_ManCutNextP( pCut ) = p->ppCutsTemp[ pCut->iMat ]; p->ppCutsTemp[ pCut->iMat ] = pCut; return pCut; } /**Function************************************************************* Synopsis [Removes cuts from the temporary storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManCutSaveStored( Amap_Man_t * p, Amap_Obj_t * pNode ) { int nMaxCuts = p->pPars->nCutsMax; int * pBuffer; Amap_Cut_t * pNext, * pCut; int i, nWords, Entry, nCuts, nCuts2; assert( pNode->pData == NULL ); // count memory needed nCuts = 1; nWords = 2; Vec_IntForEachEntry( p->vTemp, Entry, i ) { for ( pCut = p->ppCutsTemp[Entry]; pCut; pCut = *Amap_ManCutNextP(pCut) ) { nCuts++; if ( nCuts < nMaxCuts ) nWords += pCut->nFans + 1; } } p->nBytesUsed += 4*nWords; // allocate memory pBuffer = (int *)Aig_MmFlexEntryFetch( p->pMemCuts, 4*nWords ); pNext = (Amap_Cut_t *)pBuffer; // add the first cut pNext->iMat = 0; pNext->fInv = 0; pNext->nFans = 1; pNext->Fans[0] = Abc_Var2Lit(pNode->Id, 0); pNext = (Amap_Cut_t *)(pBuffer + 2); // add other cuts nCuts2 = 1; Vec_IntForEachEntry( p->vTemp, Entry, i ) { for ( pCut = p->ppCutsTemp[Entry]; pCut; pCut = *Amap_ManCutNextP(pCut) ) { nCuts2++; if ( nCuts2 < nMaxCuts ) { memcpy( pNext, pCut, sizeof(int) * (pCut->nFans + 1) ); pNext = (Amap_Cut_t *)((int *)pNext + pCut->nFans + 1); } } p->ppCutsTemp[Entry] = NULL; } assert( nCuts == nCuts2 ); assert( (int *)pNext - pBuffer == nWords ); // restore the storage Vec_IntClear( p->vTemp ); Aig_MmFlexRestart( p->pMemTemp ); for ( i = 0; i < 2*p->pLib->nNodes; i++ ) if ( p->ppCutsTemp[i] != NULL ) printf( "Amap_ManCutSaveStored(): Error!\n" ); pNode->pData = (Amap_Cut_t *)pBuffer; pNode->nCuts = Abc_MinInt( nCuts, nMaxCuts-1 ); assert( nCuts < (1<<20) ); // printf("%d ", nCuts ); // verify cuts pCut = NULL; Amap_NodeForEachCut( pNode, pNext, i ) // for ( i = 0, pNext = (Amap_Cut_t *)pNode->pData; i < (int)pNode->nCuts; // i++, pNext = Amap_ManCutNext(pNext) ) { if ( i == nMaxCuts ) break; assert( pCut == NULL || pCut->iMat <= pNext->iMat ); pCut = pNext; } } /**Function************************************************************* Synopsis [Returns the number of possible new cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_ManMergeCountCuts( Amap_Man_t * p, Amap_Obj_t * pNode ) { Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode ); Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode ); Amap_Cut_t * pCut0, * pCut1; int Entry, c0, c1, iCompl0, iCompl1, iFan0, iFan1; int Counter = 1; Amap_NodeForEachCut( pFanin0, pCut0, c0 ) Amap_NodeForEachCut( pFanin1, pCut1, c1 ) { iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode); iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode); iFan0 = !pCut0->iMat? 0: Abc_Var2Lit( pCut0->iMat, iCompl0 ); iFan1 = !pCut1->iMat? 0: Abc_Var2Lit( pCut1->iMat, iCompl1 ); Entry = Amap_LibFindNode( p->pLib, iFan0, iFan1, pNode->Type == AMAP_OBJ_XOR ); Counter += ( Entry >=0 ); // if ( Entry >=0 ) // printf( "Full: %d + %d = %d\n", iFan0, iFan1, Entry ); } return Counter; } /**Function************************************************************* Synopsis [Print cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManPrintCuts( Amap_Obj_t * pNode ) { Amap_Cut_t * pCut; int c, i; printf( "NODE %5d : Type = ", pNode->Id ); if ( pNode->Type == AMAP_OBJ_AND ) printf( "AND" ); else if ( pNode->Type == AMAP_OBJ_XOR ) printf( "XOR" ); else if ( pNode->Type == AMAP_OBJ_MUX ) printf( "MUX" ); printf( " Cuts = %d\n", pNode->nCuts ); Amap_NodeForEachCut( pNode, pCut, c ) { printf( "%3d : Mat= %3d Inv=%d ", c, pCut->iMat, pCut->fInv ); for ( i = 0; i < (int)pCut->nFans; i++ ) printf( "%d%c ", Abc_Lit2Var(pCut->Fans[i]), Abc_LitIsCompl(pCut->Fans[i])?'-':'+' ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Derives cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManMergeNodeChoice( Amap_Man_t * p, Amap_Obj_t * pNode ) { Amap_Obj_t * pTemp; Amap_Cut_t * pCut; int c; // go through the nodes of the choice node for ( pTemp = pNode; pTemp; pTemp = Amap_ObjChoice(p, pTemp) ) { Amap_NodeForEachCut( pTemp, pCut, c ) { if (!pCut) break; // mikelee added; abort when pCut is NULL if ( pCut->iMat ) Amap_ManCutStore( p, pCut, pNode->fPhase ^ pTemp->fPhase ); } pTemp->pData = NULL; } Amap_ManCutSaveStored( p, pNode ); // Amap_ManPrintCuts( pNode ); } /**Function************************************************************* Synopsis [Derives cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_ManFindCut( Amap_Obj_t * pNode, Amap_Obj_t * pFanin, int fComplFanin, int Val, Vec_Ptr_t * vCuts ) { Amap_Cut_t * pCut; int c, iCompl, iFan; Vec_PtrClear( vCuts ); Amap_NodeForEachCut( pFanin, pCut, c ) { iCompl = pCut->fInv ^ fComplFanin; iFan = !pCut->iMat? 0: Abc_Var2Lit( pCut->iMat, iCompl ); if ( iFan == Val ) Vec_PtrPush( vCuts, pCut ); } return Vec_PtrSize(vCuts) == 0; } /**Function************************************************************* Synopsis [Derives cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManMergeNodeCutsMux( Amap_Man_t * p, Amap_Obj_t * pNode ) { Vec_Int_t * vRules = p->pLib->vRules3; Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode ); Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode ); Amap_Obj_t * pFanin2 = Amap_ObjFanin2( p, pNode ); int fComplFanin0 = Amap_ObjFaninC0( pNode ); int fComplFanin1 = Amap_ObjFaninC1( pNode ); int fComplFanin2 = Amap_ObjFaninC2( pNode ); Amap_Cut_t * pCut0, * pCut1, * pCut2; int x, c0, c1, c2; assert( pNode->pData == NULL ); assert( pNode->Type == AMAP_OBJ_MUX ); assert( pNode->fRepr == 0 ); // go through the rules for ( x = 0; x < Vec_IntSize(vRules); x += 4 ) { if ( Amap_ManFindCut( pNode, pFanin0, fComplFanin0, Vec_IntEntry(vRules, x), p->vCuts0 ) ) continue; if ( Amap_ManFindCut( pNode, pFanin1, fComplFanin1, Vec_IntEntry(vRules, x+1), p->vCuts1 ) ) continue; if ( Amap_ManFindCut( pNode, pFanin2, fComplFanin2, Vec_IntEntry(vRules, x+2), p->vCuts2 ) ) continue; Vec_PtrForEachEntry( Amap_Cut_t *, p->vCuts0, pCut0, c0 ) Vec_PtrForEachEntry( Amap_Cut_t *, p->vCuts1, pCut1, c1 ) Vec_PtrForEachEntry( Amap_Cut_t *, p->vCuts2, pCut2, c2 ) { Amap_Nod_t * pNod = Amap_LibNod( p->pLib, Vec_IntEntry(vRules, x+3) ); if ( pNod->pSets == NULL ) continue; // complement literals if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) ) pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]); if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) ) pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]); if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) ) pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]); // create new cut Amap_ManCutCreate3( p, pCut0, pCut1, pCut2, Vec_IntEntry(vRules, x+3) ); // uncomplement literals if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) ) pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]); if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) ) pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]); if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) ) pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]); } } Amap_ManCutSaveStored( p, pNode ); p->nCutsUsed += pNode->nCuts; p->nCutsTried3 += pFanin0->nCuts * pFanin1->nCuts * pFanin2->nCuts; // Amap_ManPrintCuts( pNode ); } /**Function************************************************************* Synopsis [Derives cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManMergeNodeCuts( Amap_Man_t * p, Amap_Obj_t * pNode ) { Amap_Obj_t * pFanin0 = Amap_ObjFanin0( p, pNode ); Amap_Obj_t * pFanin1 = Amap_ObjFanin1( p, pNode ); Amap_Cut_t * pCut0, * pCut1; int ** pRules, Entry, i, k, c, iCompl0, iCompl1, iFan0, iFan1; assert( pNode->pData == NULL ); if ( pNode->Type == AMAP_OBJ_MUX ) { Amap_ManMergeNodeCutsMux( p, pNode ); return; } assert( pNode->Type != AMAP_OBJ_MUX ); pRules = (pNode->Type == AMAP_OBJ_AND)? p->pLib->pRules: p->pLib->pRulesX; Amap_NodeForEachCut( pFanin0, pCut0, c ) { iCompl0 = pCut0->fInv ^ Amap_ObjFaninC0(pNode); iFan0 = !pCut0->iMat? 0: Abc_Var2Lit( pCut0->iMat, iCompl0 ); // complement literals if ( pCut0->nFans == 1 && iCompl0 ) pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]); // label resulting sets for ( i = 0; (Entry = pRules[iFan0][i]); i++ ) p->pMatsTemp[Entry & 0xffff] = (Entry >> 16); // iterate through the cuts Amap_NodeForEachCut( pFanin1, pCut1, k ) { iCompl1 = pCut1->fInv ^ Amap_ObjFaninC1(pNode); iFan1 = !pCut1->iMat? 0: Abc_Var2Lit( pCut1->iMat, iCompl1 ); if ( p->pMatsTemp[iFan1] == 0 ) continue; // complement literals if ( pCut1->nFans == 1 && iCompl1 ) pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]); // create new cut if ( iFan0 >= iFan1 ) Amap_ManCutCreate( p, pCut0, pCut1, p->pMatsTemp[iFan1] ); else Amap_ManCutCreate( p, pCut1, pCut0, p->pMatsTemp[iFan1] ); // uncomplement literals if ( pCut1->nFans == 1 && iCompl1 ) pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]); } // uncomplement literals if ( pCut0->nFans == 1 && iCompl0 ) pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]); // label resulting sets for ( i = 0; (Entry = pRules[iFan0][i]); i++ ) p->pMatsTemp[Entry & 0xffff] = 0; } Amap_ManCutSaveStored( p, pNode ); p->nCutsUsed += pNode->nCuts; p->nCutsTried += pFanin0->nCuts * pFanin1->nCuts; // assert( (int)pNode->nCuts == Amap_ManMergeCountCuts(p, pNode) ); if ( pNode->fRepr ) Amap_ManMergeNodeChoice( p, pNode ); // Amap_ManPrintCuts( pNode ); } /**Function************************************************************* Synopsis [Derives cuts for all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_ManMerge( Amap_Man_t * p ) { Amap_Obj_t * pObj; int i; abctime clk = Abc_Clock(); p->pCutsPi = Amap_ManSetupPis( p ); Amap_ManForEachNode( p, pObj, i ) Amap_ManMergeNodeCuts( p, pObj ); if ( p->pPars->fVerbose ) { printf( "AIG object is %d bytes. ", (int)sizeof(Amap_Obj_t) ); printf( "Internal AIG = %5.2f MB. Cuts = %5.2f MB. CutsMax = %d.\n", 1.0*Amap_ManObjNum(p)*sizeof(Amap_Obj_t)/(1<<20), 1.0*p->nBytesUsed/(1<<20), p->pPars->nCutsMax ); printf( "Node =%6d. Try =%9d. Try3 =%10d. Used =%7d. R =%6.2f. ", Amap_ManNodeNum(p), p->nCutsTried, p->nCutsTried3, p->nCutsUsed, 1.0*p->nCutsUsed/Amap_ManNodeNum(p) ); ABC_PRT( "Time ", Abc_Clock() - clk ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapOutput.c000066400000000000000000000143471300674244400240430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapOutput.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Core mapping procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapOutput.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline char * Amap_OuputStrsav( Aig_MmFlex_t * p, char * pStr ) { return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates structure for storing one gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Out_t * Amap_OutputStructAlloc( Aig_MmFlex_t * pMem, Amap_Gat_t * pGate ) { Amap_Out_t * pRes; int nFans = pGate? pGate->nPins : 1; pRes = (Amap_Out_t *)Aig_MmFlexEntryFetch( pMem, sizeof(Amap_Out_t)+sizeof(int)*nFans ); memset( pRes, 0, sizeof(Amap_Out_t) ); memset( pRes->pFans, 0xff, sizeof(int)*nFans ); pRes->pName = pGate? Amap_OuputStrsav( pMem, pGate->pName ) : NULL; pRes->nFans = nFans; return pRes; } /**Function************************************************************* Synopsis [Returns mapped network as an array of structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Amap_ManProduceMapped( Amap_Man_t * p ) { Vec_Ptr_t * vNodes; Aig_MmFlex_t * pMem; Amap_Obj_t * pObj, * pFanin; Amap_Gat_t * pGate; Amap_Out_t * pRes; int i, k, iFanin, fCompl; float TotalArea = 0.0; pMem = Aig_MmFlexStart(); // create mapping object for each node used in the mapping vNodes = Vec_PtrAlloc( 10 ); Amap_ManForEachObj( p, pObj, i ) { if ( Amap_ObjIsPi(pObj) ) { assert( pObj->fPolar == 0 ); pRes = Amap_OutputStructAlloc( pMem, NULL ); pRes->Type = -1; pRes->nFans = 0; // save this structure pObj->iData = Vec_PtrSize( vNodes ); Vec_PtrPush( vNodes, pRes ); // create invertor if needed if ( pObj->nFouts[1] ) // this PI is used in the neg polarity { pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGateInv ); pRes->pFans[0] = pObj->iData; // save this structure Vec_PtrPush( vNodes, pRes ); TotalArea += p->pLib->pGateInv->dArea; } continue; } if ( Amap_ObjIsNode(pObj) ) { // skip the node that is not used in the mapping if ( Amap_ObjRefsTotal(pObj) == 0 ) continue; // get the gate pGate = Amap_LibGate( p->pLib, pObj->Best.pSet->iGate ); assert( pGate->nPins == pObj->Best.pCut->nFans ); // allocate structure pRes = Amap_OutputStructAlloc( pMem, pGate ); Amap_MatchForEachFaninCompl( p, &pObj->Best, pFanin, fCompl, k ) { assert( Amap_ObjRefsTotal(pFanin) ); if ( (int)pFanin->fPolar == fCompl ) pRes->pFans[k] = pFanin->iData; else pRes->pFans[k] = pFanin->iData + 1; } // save this structure pObj->iData = Vec_PtrSize( vNodes ); Vec_PtrPush( vNodes, pRes ); TotalArea += pGate->dArea; // create invertor if needed if ( pObj->nFouts[!pObj->fPolar] ) // needed in the opposite polarity { pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGateInv ); pRes->pFans[0] = pObj->iData; // save this structure Vec_PtrPush( vNodes, pRes ); TotalArea += p->pLib->pGateInv->dArea; } continue; } if ( Amap_ObjIsPo(pObj) ) { assert( pObj->fPolar == 0 ); pFanin = Amap_ObjFanin0(p, pObj); assert( Amap_ObjRefsTotal(pFanin) ); if ( Amap_ObjIsConst1(pFanin) ) { // create constant node if ( Amap_ObjFaninC0(pObj) ) { pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGate0 ); TotalArea += p->pLib->pGate0->dArea; } else { pRes = Amap_OutputStructAlloc( pMem, p->pLib->pGate1 ); TotalArea += p->pLib->pGate1->dArea; } // save this structure iFanin = Vec_PtrSize( vNodes ); Vec_PtrPush( vNodes, pRes ); } else { if ( (int)pFanin->fPolar == Amap_ObjFaninC0(pObj) ) iFanin = pFanin->iData; else iFanin = pFanin->iData + 1; } // create PO node pRes = Amap_OutputStructAlloc( pMem, NULL ); pRes->Type = 1; pRes->pFans[0] = iFanin; // save this structure Vec_PtrPush( vNodes, pRes ); } } // return memory manager in the last entry of the array Vec_PtrPush( vNodes, pMem ); return vNodes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapParse.c000066400000000000000000000400471300674244400236110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapParse.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Parses representations of gates.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapParse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" #include "aig/hop/hop.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the list of operation symbols to be used in expressions #define AMAP_EQN_SYM_OPEN '(' // opening parenthesis #define AMAP_EQN_SYM_CLOSE ')' // closing parenthesis #define AMAP_EQN_SYM_CONST0 '0' // constant 0 #define AMAP_EQN_SYM_CONST1 '1' // constant 1 #define AMAP_EQN_SYM_NEG '!' // negation before the variable #define AMAP_EQN_SYM_NEGAFT '\'' // negation after the variable #define AMAP_EQN_SYM_AND '*' // logic AND #define AMAP_EQN_SYM_AND2 '&' // logic AND #define AMAP_EQN_SYM_XOR '^' // logic XOR #define AMAP_EQN_SYM_OR '+' // logic OR #define AMAP_EQN_SYM_OR2 '|' // logic OR // the list of opcodes (also specifying operation precedence) #define AMAP_EQN_OPER_NEG 10 // negation #define AMAP_EQN_OPER_AND 9 // logic AND #define AMAP_EQN_OPER_XOR 8 // logic XOR #define AMAP_EQN_OPER_OR 7 // logic OR #define AMAP_EQN_OPER_MARK 1 // OpStack token standing for an opening parenthesis // these are values of the internal Flag #define AMAP_EQN_FLAG_START 1 // after the opening parenthesis #define AMAP_EQN_FLAG_VAR 2 // after operation is received #define AMAP_EQN_FLAG_OPER 3 // after operation symbol is received #define AMAP_EQN_FLAG_ERROR 4 // when error is detected //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs the operation on the top entries in the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Amap_ParseFormulaOper( Hop_Man_t * pMan, Vec_Ptr_t * pStackFn, int Oper ) { Hop_Obj_t * gArg1, * gArg2, * gFunc; // perform the given operation gArg2 = (Hop_Obj_t *)Vec_PtrPop( pStackFn ); gArg1 = (Hop_Obj_t *)Vec_PtrPop( pStackFn ); if ( Oper == AMAP_EQN_OPER_AND ) gFunc = Hop_And( pMan, gArg1, gArg2 ); else if ( Oper == AMAP_EQN_OPER_OR ) gFunc = Hop_Or( pMan, gArg1, gArg2 ); else if ( Oper == AMAP_EQN_OPER_XOR ) gFunc = Hop_Exor( pMan, gArg1, gArg2 ); else return NULL; // Cudd_Ref( gFunc ); // Cudd_RecursiveDeref( dd, gArg1 ); // Cudd_RecursiveDeref( dd, gArg2 ); Vec_PtrPush( pStackFn, gFunc ); return gFunc; } /**Function************************************************************* Synopsis [Derives the AIG corresponding to the equation.] Description [Takes the stream to output messages, the formula, the vector of variable names and the AIG manager.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Amap_ParseFormula( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan, char * pGateName ) { char * pFormula; Vec_Ptr_t * pStackFn; Vec_Int_t * pStackOp; Hop_Obj_t * gFunc; char * pTemp, * pName; int nParans, fFound, Flag; int Oper, Oper1, Oper2; int i, v; // make sure that the number of opening and closing parentheses is the same nParans = 0; for ( pTemp = pFormInit; *pTemp; pTemp++ ) if ( *pTemp == '(' ) nParans++; else if ( *pTemp == ')' ) nParans--; if ( nParans != 0 ) { fprintf( pOutput, "Amap_ParseFormula(): Different number of opening and closing parentheses ().\n" ); return NULL; } // copy the formula pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 ); sprintf( pFormula, "(%s)", pFormInit ); // start the stacks pStackFn = Vec_PtrAlloc( 100 ); pStackOp = Vec_IntAlloc( 100 ); Flag = AMAP_EQN_FLAG_START; for ( pTemp = pFormula; *pTemp; pTemp++ ) { switch ( *pTemp ) { // skip all spaces, tabs, and end-of-lines case ' ': case '\t': case '\r': case '\n': continue; case AMAP_EQN_SYM_CONST0: Vec_PtrPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 ); if ( Flag == AMAP_EQN_FLAG_VAR ) { fprintf( pOutput, "Amap_ParseFormula(): No operation symbol before constant 0.\n" ); Flag = AMAP_EQN_FLAG_ERROR; break; } Flag = AMAP_EQN_FLAG_VAR; break; case AMAP_EQN_SYM_CONST1: Vec_PtrPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 ); if ( Flag == AMAP_EQN_FLAG_VAR ) { fprintf( pOutput, "Amap_ParseFormula(): No operation symbol before constant 1.\n" ); Flag = AMAP_EQN_FLAG_ERROR; break; } Flag = AMAP_EQN_FLAG_VAR; break; case AMAP_EQN_SYM_NEG: if ( Flag == AMAP_EQN_FLAG_VAR ) {// if NEGBEF follows a variable, AND is assumed Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND ); Flag = AMAP_EQN_FLAG_OPER; } Vec_IntPush( pStackOp, AMAP_EQN_OPER_NEG ); break; case AMAP_EQN_SYM_NEGAFT: if ( Flag != AMAP_EQN_FLAG_VAR ) {// if there is no variable before NEGAFT, it is an error fprintf( pOutput, "Amap_ParseFormula(): No variable is specified before the negation suffix.\n" ); Flag = AMAP_EQN_FLAG_ERROR; break; } else // if ( Flag == PARSE_FLAG_VAR ) Vec_PtrPush( pStackFn, Hop_Not( (Hop_Obj_t *)Vec_PtrPop(pStackFn) ) ); break; case AMAP_EQN_SYM_AND: case AMAP_EQN_SYM_AND2: case AMAP_EQN_SYM_OR: case AMAP_EQN_SYM_OR2: case AMAP_EQN_SYM_XOR: if ( Flag != AMAP_EQN_FLAG_VAR ) { fprintf( pOutput, "Amap_ParseFormula(): There is no variable before AND, EXOR, or OR.\n" ); Flag = AMAP_EQN_FLAG_ERROR; break; } if ( *pTemp == AMAP_EQN_SYM_AND || *pTemp == AMAP_EQN_SYM_AND2 ) Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND ); else if ( *pTemp == AMAP_EQN_SYM_OR || *pTemp == AMAP_EQN_SYM_OR2 ) Vec_IntPush( pStackOp, AMAP_EQN_OPER_OR ); else //if ( *pTemp == AMAP_EQN_SYM_XOR ) Vec_IntPush( pStackOp, AMAP_EQN_OPER_XOR ); Flag = AMAP_EQN_FLAG_OPER; break; case AMAP_EQN_SYM_OPEN: if ( Flag == AMAP_EQN_FLAG_VAR ) { Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND ); // fprintf( pOutput, "Amap_ParseFormula(): An opening parenthesis follows a var without operation sign.\n" ); // Flag = AMAP_EQN_FLAG_ERROR; // break; } Vec_IntPush( pStackOp, AMAP_EQN_OPER_MARK ); // after an opening bracket, it feels like starting over again Flag = AMAP_EQN_FLAG_START; break; case AMAP_EQN_SYM_CLOSE: if ( Vec_IntSize( pStackOp ) != 0 ) { while ( 1 ) { if ( Vec_IntSize( pStackOp ) == 0 ) { fprintf( pOutput, "Amap_ParseFormula(): There is no opening parenthesis\n" ); Flag = AMAP_EQN_FLAG_ERROR; break; } Oper = Vec_IntPop( pStackOp ); if ( Oper == AMAP_EQN_OPER_MARK ) break; // perform the given operation if ( Amap_ParseFormulaOper( pMan, pStackFn, Oper ) == NULL ) { fprintf( pOutput, "Amap_ParseFormula(): Unknown operation\n" ); ABC_FREE( pFormula ); Vec_PtrFreeP( &pStackFn ); Vec_IntFreeP( &pStackOp ); return NULL; } } } else { fprintf( pOutput, "Amap_ParseFormula(): There is no opening parenthesis\n" ); Flag = AMAP_EQN_FLAG_ERROR; break; } if ( Flag != AMAP_EQN_FLAG_ERROR ) Flag = AMAP_EQN_FLAG_VAR; break; default: // scan the next name for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && pTemp[i] != AMAP_EQN_SYM_AND && pTemp[i] != AMAP_EQN_SYM_AND2 && pTemp[i] != AMAP_EQN_SYM_OR && pTemp[i] != AMAP_EQN_SYM_OR2 && pTemp[i] != AMAP_EQN_SYM_XOR && pTemp[i] != AMAP_EQN_SYM_NEGAFT && pTemp[i] != AMAP_EQN_SYM_CLOSE; i++ ) { if ( pTemp[i] == AMAP_EQN_SYM_NEG || pTemp[i] == AMAP_EQN_SYM_OPEN ) { fprintf( pOutput, "Amap_ParseFormula(): The negation sign or an opening parenthesis inside the variable name.\n" ); Flag = AMAP_EQN_FLAG_ERROR; break; } } // variable name is found fFound = 0; Vec_PtrForEachEntry( char *, vVarNames, pName, v ) if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) { pTemp += i-1; fFound = 1; break; } if ( !fFound ) { fprintf( pOutput, "Amap_ParseFormula(): The parser cannot find var \"%s\" in the input var list of gate \"%s\".\n", pTemp, pGateName ); Flag = AMAP_EQN_FLAG_ERROR; break; } /* if ( Flag == AMAP_EQN_FLAG_VAR ) { fprintf( pOutput, "Amap_ParseFormula(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); Flag = AMAP_EQN_FLAG_ERROR; break; } */ if ( Flag == AMAP_EQN_FLAG_VAR ) Vec_IntPush( pStackOp, AMAP_EQN_OPER_AND ); Vec_PtrPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] ); Flag = AMAP_EQN_FLAG_VAR; break; } if ( Flag == AMAP_EQN_FLAG_ERROR ) break; // error exit else if ( Flag == AMAP_EQN_FLAG_START ) continue; // go on parsing else if ( Flag == AMAP_EQN_FLAG_VAR ) while ( 1 ) { // check if there are negations in the OpStack if ( Vec_IntSize( pStackOp ) == 0 ) break; Oper = Vec_IntPop( pStackOp ); if ( Oper != AMAP_EQN_OPER_NEG ) { Vec_IntPush( pStackOp, Oper ); break; } else { Vec_PtrPush( pStackFn, Hop_Not((Hop_Obj_t *)Vec_PtrPop(pStackFn)) ); } } else // if ( Flag == AMAP_EQN_FLAG_OPER ) while ( 1 ) { // execute all the operations in the OpStack // with precedence higher or equal than the last one Oper1 = Vec_IntPop( pStackOp ); // the last operation if ( Vec_IntSize( pStackOp ) == 0 ) { // if it is the only operation, push it back Vec_IntPush( pStackOp, Oper1 ); break; } Oper2 = Vec_IntPop( pStackOp ); // the operation before the last one if ( Oper2 >= Oper1 ) { // if Oper2 precedence is higher or equal, execute it if ( Amap_ParseFormulaOper( pMan, pStackFn, Oper2 ) == NULL ) { fprintf( pOutput, "Amap_ParseFormula(): Unknown operation\n" ); ABC_FREE( pFormula ); Vec_PtrFreeP( &pStackFn ); Vec_IntFreeP( &pStackOp ); return NULL; } Vec_IntPush( pStackOp, Oper1 ); // push the last operation back } else { // if Oper2 precedence is lower, push them back and done Vec_IntPush( pStackOp, Oper2 ); Vec_IntPush( pStackOp, Oper1 ); break; } } } if ( Flag != AMAP_EQN_FLAG_ERROR ) { if ( Vec_PtrSize(pStackFn) != 0 ) { gFunc = (Hop_Obj_t *)Vec_PtrPop(pStackFn); if ( Vec_PtrSize(pStackFn) == 0 ) if ( Vec_IntSize( pStackOp ) == 0 ) { // Cudd_Deref( gFunc ); ABC_FREE( pFormula ); Vec_PtrFreeP( &pStackFn ); Vec_IntFreeP( &pStackOp ); return gFunc; } else fprintf( pOutput, "Amap_ParseFormula(): Something is left in the operation stack\n" ); else fprintf( pOutput, "Amap_ParseFormula(): Something is left in the function stack\n" ); } else fprintf( pOutput, "Amap_ParseFormula(): The input string is empty\n" ); } ABC_FREE( pFormula ); Vec_PtrFreeP( &pStackFn ); Vec_IntFreeP( &pStackOp ); return NULL; } /**Function************************************************************* Synopsis [Parses equations for the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibParseEquations( Amap_Lib_t * p, int fVerbose ) { // extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars ); Hop_Man_t * pMan; Hop_Obj_t * pObj; Vec_Ptr_t * vNames; Vec_Int_t * vTruth; Amap_Gat_t * pGate; Amap_Pin_t * pPin; unsigned * pTruth; int i, nPinMax; nPinMax = Amap_LibNumPinsMax(p); if ( nPinMax > AMAP_MAXINS ) printf( "Gates with more than %d inputs will be ignored.\n", AMAP_MAXINS ); vTruth = Vec_IntAlloc( 1 << 16 ); vNames = Vec_PtrAlloc( 100 ); pMan = Hop_ManStart(); Hop_IthVar( pMan, nPinMax - 1 ); Vec_PtrForEachEntry( Amap_Gat_t *, p->vGates, pGate, i ) { if ( pGate->nPins == 0 ) { pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, 4 ); if ( strcmp( pGate->pForm, AMAP_STRING_CONST0 ) == 0 ) pGate->pFunc[0] = 0; else if ( strcmp( pGate->pForm, AMAP_STRING_CONST1 ) == 0 ) pGate->pFunc[0] = ~0; else { printf( "Cannot parse formula \"%s\" of gate \"%s\" with no pins.\n", pGate->pForm, pGate->pName ); break; } continue; } if ( pGate->nPins > AMAP_MAXINS ) continue; Vec_PtrClear( vNames ); Amap_GateForEachPin( pGate, pPin ) Vec_PtrPush( vNames, pPin->pName ); pObj = Amap_ParseFormula( stdout, pGate->pForm, vNames, pMan, pGate->pName ); if ( pObj == NULL ) break; pTruth = Hop_ManConvertAigToTruth( pMan, pObj, pGate->nPins, vTruth, 0 ); if ( Kit_TruthSupportSize(pTruth, pGate->nPins) < (int)pGate->nPins ) { if ( fVerbose ) printf( "Skipping gate \"%s\" because its output \"%s\" does not depend on all input variables.\n", pGate->pName, pGate->pForm ); continue; } pGate->pFunc = (unsigned *)Aig_MmFlexEntryFetch( p->pMemGates, sizeof(unsigned)*Abc_TruthWordNum(pGate->nPins) ); memcpy( pGate->pFunc, pTruth, sizeof(unsigned)*Abc_TruthWordNum(pGate->nPins) ); } Vec_PtrFree( vNames ); Vec_IntFree( vTruth ); Hop_ManStop( pMan ); return i == Vec_PtrSize(p->vGates); } /**Function************************************************************* Synopsis [Parses equations for the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibParseTest( char * pFileName ) { int fVerbose = 0; Amap_Lib_t * p; abctime clk = Abc_Clock(); p = Amap_LibReadFile( pFileName, fVerbose ); if ( p == NULL ) return; Amap_LibParseEquations( p, fVerbose ); Amap_LibFree( p ); ABC_PRT( "Total time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapPerm.c000066400000000000000000000316111300674244400234370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapPerm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Deriving permutation for the gate.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapPerm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects fanins of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibCollectFanins_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, Vec_Int_t * vFanins ) { Amap_Nod_t * pFan0, * pFan1; if ( pNod->Id == 0 ) { Vec_IntPush( vFanins, 0 ); return; } pFan0 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); if ( Abc_LitIsCompl(pNod->iFan0) || pFan0->Type != pNod->Type ) Vec_IntPush( vFanins, pNod->iFan0 ); else Amap_LibCollectFanins_rec( pLib, pFan0, vFanins ); pFan1 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); if ( Abc_LitIsCompl(pNod->iFan1) || pFan1->Type != pNod->Type ) Vec_IntPush( vFanins, pNod->iFan1 ); else Amap_LibCollectFanins_rec( pLib, pFan1, vFanins ); } /**Function************************************************************* Synopsis [Collects fanins of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Amap_LibCollectFanins( Amap_Lib_t * pLib, Amap_Nod_t * pNod ) { Vec_Int_t * vFanins = Vec_IntAlloc( 10 ); Amap_LibCollectFanins_rec( pLib, pNod, vFanins ); return vFanins; } /**Function************************************************************* Synopsis [Matches the node with the DSD node.] Description [Returns perm if the node can be matched.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Amap_LibDeriveGatePerm_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * pNtk, int iLit, Amap_Nod_t * pNod ) { Vec_Int_t * vPerm, * vPermFanin, * vNodFanin, * vDsdLits; Kit_DsdObj_t * pDsdObj, * pDsdFanin; Amap_Nod_t * pNodFanin; int iDsdFanin, iNodFanin, Value, iDsdLit, i, k, j; // assert( !Abc_LitIsCompl(iLit) ); pDsdObj = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iLit) ); if ( pDsdObj == NULL ) { vPerm = Vec_IntAlloc( 1 ); Vec_IntPush( vPerm, iLit ); return vPerm; } if ( pDsdObj->Type == KIT_DSD_PRIME && pNod->Type == AMAP_OBJ_MUX ) { vPerm = Vec_IntAlloc( 10 ); iDsdFanin = pDsdObj->pFans[0]; pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); if ( vPermFanin == NULL ) { Vec_IntFree( vPerm ); return NULL; } Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); iDsdFanin = pDsdObj->pFans[1]; pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); if ( vPermFanin == NULL ) { Vec_IntFree( vPerm ); return NULL; } Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); iDsdFanin = pDsdObj->pFans[2]; pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan2) ); vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, iDsdFanin, pNodFanin ); if ( vPermFanin == NULL ) { Vec_IntFree( vPerm ); return NULL; } Vec_IntForEachEntry( vPermFanin, Value, k ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); return vPerm; } // return if wrong types if ( pDsdObj->Type == KIT_DSD_PRIME || pNod->Type == AMAP_OBJ_MUX ) return NULL; // return if sizes do not agree vNodFanin = Amap_LibCollectFanins( pLib, pNod ); if ( Vec_IntSize(vNodFanin) != (int)pDsdObj->nFans ) { Vec_IntFree( vNodFanin ); return NULL; } // match fanins of DSD with fanins of nodes // clean the mark and save variable literals vPerm = Vec_IntAlloc( 10 ); vDsdLits = Vec_IntAlloc( 10 ); Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i ) { pDsdFanin = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iDsdFanin) ); if ( pDsdFanin ) pDsdFanin->fMark = 0; else Vec_IntPush( vDsdLits, iDsdFanin ); } // match each fanins of the node iDsdLit = 0; Vec_IntForEachEntry( vNodFanin, iNodFanin, k ) { if ( iNodFanin == 0 ) { if ( iDsdLit >= Vec_IntSize(vDsdLits) ) { Vec_IntFree( vPerm ); Vec_IntFree( vDsdLits ); Vec_IntFree( vNodFanin ); return NULL; } iDsdFanin = Vec_IntEntry( vDsdLits, iDsdLit++ ); Vec_IntPush( vPerm, iDsdFanin ); continue; } // find a matching component pNodFanin = Amap_LibNod( pLib, Abc_Lit2Var(iNodFanin) ); Kit_DsdObjForEachFaninReverse( pNtk, pDsdObj, iDsdFanin, i ) { pDsdFanin = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iDsdFanin) ); if ( pDsdFanin == NULL ) continue; if ( pDsdFanin->fMark == 1 ) continue; if ( !((pDsdFanin->Type == KIT_DSD_AND && pNodFanin->Type == AMAP_OBJ_AND) || (pDsdFanin->Type == KIT_DSD_XOR && pNodFanin->Type == AMAP_OBJ_XOR) || (pDsdFanin->Type == KIT_DSD_PRIME && pNodFanin->Type == AMAP_OBJ_MUX)) ) continue; vPermFanin = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Abc_LitRegular(iDsdFanin), pNodFanin ); if ( vPermFanin == NULL ) { Vec_IntFree( vNodFanin ); Vec_IntFree( vDsdLits ); Vec_IntFree( vPerm ); return NULL; } pDsdFanin->fMark = 1; Vec_IntForEachEntry( vPermFanin, Value, j ) Vec_IntPush( vPerm, Value ); Vec_IntFree( vPermFanin ); break; } } // assert( iDsdLit == Vec_IntSize(vDsdLits) ); if ( iDsdLit != Vec_IntSize(vDsdLits) ) Vec_IntFreeP( &vPerm ); Vec_IntFree( vNodFanin ); Vec_IntFree( vDsdLits ); return vPerm; } /**Function************************************************************* Synopsis [Performs verification of one gate and one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Amap_LibVerifyPerm_rec( Amap_Lib_t * pLib, Amap_Nod_t * pNod, Vec_Ptr_t * vTtElems, Vec_Int_t * vTruth, int nWords, int * piInput ) { Amap_Nod_t * pFan0, * pFan1; unsigned * pTruth0, * pTruth1, * pTruth; int i; assert( pNod->Type != AMAP_OBJ_MUX ); if ( pNod->Id == 0 ) return (unsigned *)Vec_PtrEntry( vTtElems, (*piInput)++ ); pFan0 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan0) ); pTruth0 = Amap_LibVerifyPerm_rec( pLib, pFan0, vTtElems, vTruth, nWords, piInput ); pFan1 = Amap_LibNod( pLib, Abc_Lit2Var(pNod->iFan1) ); pTruth1 = Amap_LibVerifyPerm_rec( pLib, pFan1, vTtElems, vTruth, nWords, piInput ); pTruth = Vec_IntFetch( vTruth, nWords ); if ( pNod->Type == AMAP_OBJ_XOR ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] ^ pTruth1[i]; else if ( !Abc_LitIsCompl(pNod->iFan0) && !Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & pTruth1[i]; else if ( !Abc_LitIsCompl(pNod->iFan0) && Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & ~pTruth1[i]; else if ( Abc_LitIsCompl(pNod->iFan0) && !Abc_LitIsCompl(pNod->iFan1) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & pTruth1[i]; else // if ( Abc_LitIsCompl(pNod->iFan0) && Hop_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; return pTruth; } /**Function************************************************************* Synopsis [Performs verification of one gate and one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibVerifyPerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, int * pArray ) { Vec_Ptr_t * vTtElems; Vec_Ptr_t * vTtElemsPol; Vec_Int_t * vTruth; unsigned * pTruth; int i, nWords; int iInput = 0; // allocate storage for truth tables assert( pGate->nPins > 1 ); nWords = Kit_TruthWordNum( pGate->nPins ); vTruth = Vec_IntAlloc( nWords * AMAP_MAXINS ); vTtElems = Vec_PtrAllocTruthTables( pGate->nPins ); vTtElemsPol = Vec_PtrAlloc( pGate->nPins ); for ( i = 0; i < (int)pGate->nPins; i++ ) { pTruth = (unsigned *)Vec_PtrEntry( vTtElems, Abc_Lit2Var(pArray[i]) ); if ( Abc_LitIsCompl( pArray[i] ) ) Kit_TruthNot( pTruth, pTruth, pGate->nPins ); Vec_PtrPush( vTtElemsPol, pTruth ); } //Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 0), 4 ); printf("\n" ); //Extra_PrintBinary( stdout, Vec_PtrEntry(vTtElemsPol, 1), 4 ); printf("\n" ); // compute the truth table recursively pTruth = Amap_LibVerifyPerm_rec( pLib, pNod, vTtElemsPol, vTruth, nWords, &iInput ); assert( iInput == (int)pGate->nPins ); if ( Abc_LitIsCompl(pNtk->Root) ) Kit_TruthNot( pTruth, pTruth, pGate->nPins ); //Extra_PrintBinary( stdout, pTruth, 4 ); printf("\n" ); //Extra_PrintBinary( stdout, pGate->pFunc, 4 ); printf("\n" ); // compare if ( !Kit_TruthIsEqual(pGate->pFunc, pTruth, pGate->nPins) ) printf( "Verification failed for gate %d (%s) and node %d.\n", pGate->Id, pGate->pForm, pNod->Id ); Vec_IntFree( vTruth ); Vec_PtrFree( vTtElems ); Vec_PtrFree( vTtElemsPol ); } /**Function************************************************************* Synopsis [Matches the node with the DSD of a gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray ) { int fVerbose = 0; Vec_Int_t * vPerm; int Entry, Entry2, i, k; // Kit_DsdPrint( stdout, pNtk ); vPerm = Amap_LibDeriveGatePerm_rec( pLib, pNtk, Abc_LitRegular(pNtk->Root), pNod ); if ( vPerm == NULL ) return 0; // check that the permutation is valid assert( Vec_IntSize(vPerm) == (int)pNod->nSuppSize ); Vec_IntForEachEntry( vPerm, Entry, i ) Vec_IntForEachEntryStart( vPerm, Entry2, k, i+1 ) if ( Abc_Lit2Var(Entry) == Abc_Lit2Var(Entry2) ) { Vec_IntFree( vPerm ); return 0; } // reverse the permutation Vec_IntForEachEntry( vPerm, Entry, i ) { assert( Entry < 2 * (int)pNod->nSuppSize ); pArray[Abc_Lit2Var(Entry)] = Abc_Var2Lit( i, Abc_LitIsCompl(Entry) ); // pArray[i] = Entry; //printf( "%d=%d%c ", Abc_Lit2Var(Entry), i, Abc_LitIsCompl(Entry)?'-':'+' ); } //printf( "\n" ); // if ( Kit_DsdNonDsdSizeMax(pNtk) < 3 ) // Amap_LibVerifyPerm( pLib, pGate, pNtk, pNod, Vec_IntArray(vPerm) ); Vec_IntFree( vPerm ); // print the result if ( fVerbose ) { printf( "node %4d : ", pNod->Id ); for ( i = 0; i < (int)pNod->nSuppSize; i++ ) printf( "%d=%d%c ", i, Abc_Lit2Var(pArray[i]), Abc_LitIsCompl(pArray[i])?'-':'+' ); printf( "\n" ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapRead.c000066400000000000000000000360761300674244400234210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapRead.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapRead.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" #include "base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define AMAP_STRING_GATE "GATE" #define AMAP_STRING_PIN "PIN" #define AMAP_STRING_NONINV "NONINV" #define AMAP_STRING_INV "INV" #define AMAP_STRING_UNKNOWN "UNKNOWN" // these symbols (and no other) can appear in the formulas #define AMAP_SYMB_AND '*' #define AMAP_SYMB_AND2 '&' #define AMAP_SYMB_OR1 '+' #define AMAP_SYMB_OR2 '|' #define AMAP_SYMB_XOR '^' #define AMAP_SYMB_NOT '!' #define AMAP_SYMB_AFTNOT '\'' #define AMAP_SYMB_OPEN '(' #define AMAP_SYMB_CLOSE ')' typedef enum { AMAP_PHASE_UNKNOWN, AMAP_PHASE_INV, AMAP_PHASE_NONINV } Amap_PinPhase_t; static inline Amap_Gat_t * Amap_ParseGateAlloc( Aig_MmFlex_t * p, int nPins ) { return (Amap_Gat_t *)Aig_MmFlexEntryFetch( p, sizeof(Amap_Gat_t)+sizeof(Amap_Pin_t)*nPins ); } static inline char * Amap_ParseStrsav( Aig_MmFlex_t * p, char * pStr ) { return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Loads the file into temporary buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Amap_LoadFile( char * pFileName ) { // extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ); FILE * pFile; char * pBuffer; int nFileSize; int RetValue; // open the BLIF file for binary reading pFile = Io_FileOpen( pFileName, "open_path", "rb", 1 ); // pFile = fopen( FileName, "rb" ); // if we got this far, file should be okay otherwise would // have been detected by caller if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return NULL; } assert ( pFile != NULL ); // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nFileSize + 10 ); RetValue = fread( pBuffer, nFileSize, 1, pFile ); // terminate the string with '\0' pBuffer[ nFileSize ] = '\0'; strcat( pBuffer, "\n.end\n" ); // close file fclose( pFile ); return pBuffer; } /**Function************************************************************* Synopsis [Eliminates comments from the input file.] Description [As a byproduct, this procedure also counts the number lines and dot-statements in the input file. This also joins non-comment lines that are joined with a backspace '\'] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_RemoveComments( char * pBuffer, int * pnDots, int * pnLines ) { char * pCur; int nDots, nLines; // scan through the buffer and eliminate comments // (in the BLIF file, comments are lines starting with "#") nDots = nLines = 0; for ( pCur = pBuffer; *pCur; pCur++ ) { // if this is the beginning of comment // clean it with spaces until the new line statement if ( *pCur == '#' ) while ( *pCur != '\n' ) *pCur++ = ' '; // count the number of new lines and dots if ( *pCur == '\n' ) { if (*(pCur-1)=='\r') { // DOS(R) file support if (*(pCur-2)!='\\') nLines++; else { // rewind to backslash and overwrite with a space *(pCur-2) = ' '; *(pCur-1) = ' '; *pCur = ' '; } } else { // UNIX(TM) file support if (*(pCur-1)!='\\') nLines++; else { // rewind to backslash and overwrite with a space *(pCur-1) = ' '; *pCur = ' '; } } } else if ( *pCur == '.' ) nDots++; } if ( pnDots ) *pnDots = nDots; if ( pnLines ) *pnLines = nLines; } /**Function************************************************************* Synopsis [Splits the stream into tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Amap_DeriveTokens( char * pBuffer ) { Vec_Ptr_t * vTokens; char * pToken; vTokens = Vec_PtrAlloc( 1000 ); pToken = strtok( pBuffer, " =\t\r\n" ); while ( pToken ) { Vec_PtrPush( vTokens, pToken ); pToken = strtok( NULL, " =\t\r\n" ); // skip latches if ( pToken && strcmp( pToken, "LATCH" ) == 0 ) while ( pToken && strcmp( pToken, "GATE" ) != 0 ) pToken = strtok( NULL, " =\t\r\n" ); } return vTokens; } /**Function************************************************************* Synopsis [Finds the number of pins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_ParseCountPins( Vec_Ptr_t * vTokens, int iPos ) { char * pToken; int i, Counter = 0; Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, iPos ) if ( !strcmp( pToken, AMAP_STRING_PIN ) ) Counter++; else if ( !strcmp( pToken, AMAP_STRING_GATE ) ) return Counter; return Counter; } /**Function************************************************************* Synopsis [Collect the pin names used in the formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_GateCollectNames( Aig_MmFlex_t * pMem, char * pForm, char * pPinNames[] ) { char Buffer[1000]; char * pTemp; int nPins, i; // save the formula as it was strcpy( Buffer, pForm ); // remove the non-name symbols for ( pTemp = Buffer; *pTemp; pTemp++ ) if ( *pTemp == AMAP_SYMB_AND || *pTemp == AMAP_SYMB_OR1 || *pTemp == AMAP_SYMB_OR2 || *pTemp == AMAP_SYMB_XOR || *pTemp == AMAP_SYMB_NOT || *pTemp == AMAP_SYMB_OPEN || *pTemp == AMAP_SYMB_CLOSE || *pTemp == AMAP_SYMB_AFTNOT || *pTemp == AMAP_SYMB_AND2 ) *pTemp = ' '; // save the names nPins = 0; pTemp = strtok( Buffer, " " ); while ( pTemp ) { for ( i = 0; i < nPins; i++ ) if ( strcmp( pTemp, pPinNames[i] ) == 0 ) break; if ( i == nPins ) { // cannot find this name; save it pPinNames[nPins++] = Amap_ParseStrsav( pMem, pTemp ); } // get the next name pTemp = strtok( NULL, " " ); } return nPins; } /**Function************************************************************* Synopsis [Creates a duplicate gate with pins specified.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Gat_t * Amap_ParseGateWithSamePins( Amap_Gat_t * p ) { Amap_Gat_t * pGate; Amap_Pin_t * pPin; char * pPinNames[128]; int nPinNames; assert( p->nPins == 1 && !strcmp( p->Pins->pName, "*" ) ); nPinNames = Amap_GateCollectNames( p->pLib->pMemGates, p->pForm, pPinNames ); pGate = Amap_ParseGateAlloc( p->pLib->pMemGates, nPinNames ); *pGate = *p; pGate->nPins = nPinNames; Amap_GateForEachPin( pGate, pPin ) { *pPin = *p->Pins; pPin->pName = pPinNames[pPin - pGate->Pins]; } return pGate; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_CollectFormulaTokens( Vec_Ptr_t * vTokens, char * pToken, int iPos ) { char * pNext, * pPrev; pPrev = pToken + strlen(pToken); while ( *(pPrev-1) != ';' ) { *pPrev++ = ' '; pNext = (char *)Vec_PtrEntry(vTokens, iPos++); while ( *pNext ) *pPrev++ = *pNext++; } *(pPrev-1) = 0; return iPos; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose ) { Amap_Lib_t * p; Amap_Gat_t * pGate, * pPrev; Amap_Pin_t * pPin; char * pToken, * pMoGate = NULL; int i, nPins, iPos = 0, Count = 0; p = Amap_LibAlloc(); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); do { if ( strcmp( pToken, AMAP_STRING_GATE ) ) { Amap_LibFree( p ); printf( "The first line should begin with %s.\n", AMAP_STRING_GATE ); return NULL; } // start gate nPins = Amap_ParseCountPins( vTokens, iPos ); pGate = Amap_ParseGateAlloc( p->pMemGates, nPins ); memset( pGate, 0, sizeof(Amap_Gat_t) ); pGate->Id = Vec_PtrSize( p->vGates ); Vec_PtrPush( p->vGates, pGate ); pGate->pLib = p; pGate->nPins = nPins; // read gate pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pGate->pName = Amap_ParseStrsav( p->pMemGates, pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pGate->dArea = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pGate->pOutName = Amap_ParseStrsav( p->pMemGates, pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); iPos = Amap_CollectFormulaTokens( vTokens, pToken, iPos ); pGate->pForm = Amap_ParseStrsav( p->pMemGates, pToken ); // read pins Amap_GateForEachPin( pGate, pPin ) { pToken = (char *)Vec_PtrEntry(vTokens, iPos++); if ( strcmp( pToken, AMAP_STRING_PIN ) ) { Amap_LibFree( p ); printf( "Cannot parse gate %s.\n", pGate->pName ); return NULL; } // read pin pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->pName = Amap_ParseStrsav( p->pMemGates, pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); if ( strcmp( pToken, AMAP_STRING_UNKNOWN ) == 0 ) pPin->Phase = AMAP_PHASE_UNKNOWN; else if ( strcmp( pToken, AMAP_STRING_INV ) == 0 ) pPin->Phase = AMAP_PHASE_INV; else if ( strcmp( pToken, AMAP_STRING_NONINV ) == 0 ) pPin->Phase = AMAP_PHASE_NONINV; else { Amap_LibFree( p ); printf( "Cannot read phase of pin %s of gate %s\n", pPin->pName, pGate->pName ); return NULL; } pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dLoadInput = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dLoadMax = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dDelayBlockRise = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dDelayFanoutRise = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dDelayBlockFall = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dDelayFanoutFall = atof( pToken ); if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall ) pPin->dDelayBlockMax = pPin->dDelayBlockRise; else pPin->dDelayBlockMax = pPin->dDelayBlockFall; } // fix the situation when all pins are represented as one if ( pGate->nPins == 1 && !strcmp( pGate->Pins->pName, "*" ) ) { pGate = Amap_ParseGateWithSamePins( pGate ); Vec_PtrPop( p->vGates ); Vec_PtrPush( p->vGates, pGate ); } pToken = (char *)Vec_PtrEntry(vTokens, iPos++); //printf( "Finished reading gate %s (%s)\n", pGate->pName, pGate->pOutName ); } while ( strcmp( pToken, ".end" ) ); // check if there are gates with identical names pPrev = NULL; Amap_LibForEachGate( p, pGate, i ) { if ( pPrev && !strcmp(pPrev->pName, pGate->pName) ) { pPrev->pTwin = pGate, pGate->pTwin = pPrev; // printf( "Warning: Detected multi-output gate \"%s\".\n", pGate->pName ); if ( pMoGate == NULL ) pMoGate = pGate->pName; Count++; } pPrev = pGate; } if ( Count ) printf( "Warning: Detected %d multi-output gates (for example, \"%s\").\n", Count, pMoGate ); return p; } /**Function************************************************************* Synopsis [Reads the library from the input file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Lib_t * Amap_LibReadBuffer( char * pBuffer, int fVerbose ) { Amap_Lib_t * pLib; Vec_Ptr_t * vTokens; Amap_RemoveComments( pBuffer, NULL, NULL ); vTokens = Amap_DeriveTokens( pBuffer ); pLib = Amap_ParseTokens( vTokens, fVerbose ); if ( pLib == NULL ) { Vec_PtrFree( vTokens ); return NULL; } Vec_PtrFree( vTokens ); return pLib; } /**Function************************************************************* Synopsis [Reads the library from the input file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose ) { Amap_Lib_t * pLib; char * pBuffer; pBuffer = Amap_LoadFile( pFileName ); if ( pBuffer == NULL ) return NULL; pLib = Amap_LibReadBuffer( pBuffer, fVerbose ); if ( pLib ) pLib->pName = Abc_UtilStrsav( pFileName ); ABC_FREE( pBuffer ); return pLib; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapRule.c000066400000000000000000000364401300674244400234500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapRule.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Matching rules.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapRule.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Amap_LibDeriveGatePerm( Amap_Lib_t * pLib, Amap_Gat_t * pGate, Kit_DsdNtk_t * pNtk, Amap_Nod_t * pNod, char * pArray ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if the three-argument rule exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Amap_CreateRulesPrime( Amap_Lib_t * p, Vec_Int_t * vNods0, Vec_Int_t * vNods1, Vec_Int_t * vNods2 ) { Vec_Int_t * vRes; int i, k, j, iNod, iNod0, iNod1, iNod2; if ( p->vRules3 == NULL ) p->vRules3 = Vec_IntAlloc( 100 ); vRes = Vec_IntAlloc( 10 ); Vec_IntForEachEntry( vNods0, iNod0, i ) Vec_IntForEachEntry( vNods1, iNod1, k ) Vec_IntForEachEntry( vNods2, iNod2, j ) { iNod = Amap_LibFindMux( p, iNod0, iNod1, iNod2 ); if ( iNod == -1 ) iNod = Amap_LibCreateMux( p, iNod0, iNod1, iNod2 ); Vec_IntPush( vRes, Abc_Var2Lit(iNod, 0) ); } return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_CreateRulesTwo( Amap_Lib_t * p, Vec_Int_t * vNods, Vec_Int_t * vNods0, Vec_Int_t * vNods1, int fXor ) { int i, k, iNod, iNod0, iNod1; Vec_IntForEachEntry( vNods0, iNod0, i ) Vec_IntForEachEntry( vNods1, iNod1, k ) { iNod = Amap_LibFindNode( p, iNod0, iNod1, fXor ); if ( iNod == -1 ) iNod = Amap_LibCreateNode( p, iNod0, iNod1, fXor ); Vec_IntPushUnique( vNods, Abc_Var2Lit(iNod, 0) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_CreateCheckAllZero( Vec_Ptr_t * vVecNods ) { Vec_Int_t * vNods; int i; Vec_PtrForEachEntryReverse( Vec_Int_t *, vVecNods, vNods, i ) if ( Vec_IntSize(vNods) != 1 || Vec_IntEntry(vNods,0) != 0 ) return 0; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Amap_CreateRulesVector_rec( Amap_Lib_t * p, Vec_Ptr_t * vVecNods, int fXor ) { Vec_Ptr_t * vVecNods0, * vVecNods1; Vec_Int_t * vRes, * vNods, * vNods0, * vNods1; int i, k; if ( Vec_PtrSize(vVecNods) == 1 ) return Vec_IntDup( (Vec_Int_t *)Vec_PtrEntry(vVecNods, 0) ); vRes = Vec_IntAlloc( 10 ); vVecNods0 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) ); vVecNods1 = Vec_PtrAlloc( Vec_PtrSize(vVecNods) ); if ( Amap_CreateCheckAllZero(vVecNods) ) { for ( i = Vec_PtrSize(vVecNods)-1; i > 0; i-- ) { Vec_PtrClear( vVecNods0 ); Vec_PtrClear( vVecNods1 ); Vec_PtrForEachEntryStop( Vec_Int_t *, vVecNods, vNods, k, i ) Vec_PtrPush( vVecNods0, vNods ); Vec_PtrForEachEntryStart( Vec_Int_t *, vVecNods, vNods, k, i ) Vec_PtrPush( vVecNods1, vNods ); vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor ); vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor ); Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor ); Vec_IntFree( vNods0 ); Vec_IntFree( vNods1 ); } } else { int Limit = (1 << Vec_PtrSize(vVecNods))-2; for ( i = 1; i < Limit; i++ ) { Vec_PtrClear( vVecNods0 ); Vec_PtrClear( vVecNods1 ); Vec_PtrForEachEntryReverse( Vec_Int_t *, vVecNods, vNods, k ) { if ( i & (1 << k) ) Vec_PtrPush( vVecNods1, vNods ); else Vec_PtrPush( vVecNods0, vNods ); } assert( Vec_PtrSize(vVecNods0) > 0 ); assert( Vec_PtrSize(vVecNods1) > 0 ); assert( Vec_PtrSize(vVecNods0) < Vec_PtrSize(vVecNods) ); assert( Vec_PtrSize(vVecNods1) < Vec_PtrSize(vVecNods) ); vNods0 = Amap_CreateRulesVector_rec( p, vVecNods0, fXor ); vNods1 = Amap_CreateRulesVector_rec( p, vVecNods1, fXor ); Amap_CreateRulesTwo( p, vRes, vNods0, vNods1, fXor ); Vec_IntFree( vNods0 ); Vec_IntFree( vNods1 ); } } Vec_PtrFree( vVecNods0 ); Vec_PtrFree( vVecNods1 ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Amap_CreateRulesFromDsd_rec( Amap_Lib_t * pLib, Kit_DsdNtk_t * p, int iLit ) { Vec_Int_t * vRes; Vec_Ptr_t * vVecNods; Vec_Int_t * vNodsFanin; Kit_DsdObj_t * pObj; unsigned i; int iFanin, iNod, k; assert( !Abc_LitIsCompl(iLit) ); pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) return Vec_IntStartNatural( 1 ); // solve for the inputs vVecNods = Vec_PtrAlloc( pObj->nFans ); Kit_DsdObjForEachFanin( p, pObj, iFanin, i ) { vNodsFanin = Amap_CreateRulesFromDsd_rec( pLib, p, Abc_LitRegular(iFanin) ); if ( Abc_LitIsCompl(iFanin) ) { Vec_IntForEachEntry( vNodsFanin, iNod, k ) if ( iNod > 0 ) Vec_IntWriteEntry( vNodsFanin, k, Abc_LitNot(iNod) ); } Vec_PtrPush( vVecNods, vNodsFanin ); } if ( pObj->Type == KIT_DSD_AND ) vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 0 ); else if ( pObj->Type == KIT_DSD_XOR ) vRes = Amap_CreateRulesVector_rec( pLib, vVecNods, 1 ); else if ( pObj->Type == KIT_DSD_PRIME ) { assert( pObj->nFans == 3 ); assert( Kit_DsdObjTruth(pObj)[0] == 0xCACACACA ); vRes = Amap_CreateRulesPrime( pLib, (Vec_Int_t *)Vec_PtrEntry(vVecNods, 0), (Vec_Int_t *)Vec_PtrEntry(vVecNods, 1), (Vec_Int_t *)Vec_PtrEntry(vVecNods, 2) ); } else assert( 0 ); Vec_PtrForEachEntry( Vec_Int_t *, vVecNods, vNodsFanin, k ) Vec_IntFree( vNodsFanin ); Vec_PtrFree( vVecNods ); return vRes; } Vec_Int_t * Amap_CreateRulesFromDsd( Amap_Lib_t * pLib, Kit_DsdNtk_t * p ) { Vec_Int_t * vNods; int iNod, i; assert( p->nVars >= 2 ); vNods = Amap_CreateRulesFromDsd_rec( pLib, p, Abc_LitRegular(p->Root) ); if ( vNods == NULL ) return NULL; if ( Abc_LitIsCompl(p->Root) ) { Vec_IntForEachEntry( vNods, iNod, i ) Vec_IntWriteEntry( vNods, i, Abc_LitNot(iNod) ); } return vNods; } /**Function************************************************************* Synopsis [Returns 1 if DSD network contains asymentry due to complements.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_CreateCheckEqual_rec( Kit_DsdNtk_t * p, int iLit0, int iLit1 ) { Kit_DsdObj_t * pObj0, * pObj1; int i; assert( !Abc_LitIsCompl(iLit0) ); assert( !Abc_LitIsCompl(iLit1) ); pObj0 = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit0) ); pObj1 = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit1) ); if ( pObj0 == NULL && pObj1 == NULL ) return 1; if ( pObj0 == NULL || pObj1 == NULL ) return 0; if ( pObj0->Type != pObj1->Type ) return 0; if ( pObj0->nFans != pObj1->nFans ) return 0; if ( pObj0->Type == KIT_DSD_PRIME ) return 0; assert( pObj0->Type == KIT_DSD_AND || pObj0->Type == KIT_DSD_XOR ); for ( i = 0; i < (int)pObj0->nFans; i++ ) { if ( Abc_LitIsCompl(pObj0->pFans[i]) != Abc_LitIsCompl(pObj1->pFans[i]) ) return 0; if ( !Amap_CreateCheckEqual_rec( p, Abc_LitRegular(pObj0->pFans[i]), Abc_LitRegular(pObj1->pFans[i]) ) ) return 0; } return 1; } void Amap_CreateCheckAsym_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t ** pvSyms ) { Kit_DsdObj_t * pObj; int i, k, iFanin; assert( !Abc_LitIsCompl(iLit) ); pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) return; Kit_DsdObjForEachFanin( p, pObj, iFanin, i ) Amap_CreateCheckAsym_rec( p, Abc_LitRegular(iFanin), pvSyms ); if ( pObj->Type == KIT_DSD_PRIME ) return; assert( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ); for ( i = 0; i < (int)pObj->nFans; i++ ) for ( k = i+1; k < (int)pObj->nFans; k++ ) { if ( Abc_LitIsCompl(pObj->pFans[i]) != Abc_LitIsCompl(pObj->pFans[k]) && Kit_DsdNtkObj(p, Abc_Lit2Var(pObj->pFans[i])) == NULL && Kit_DsdNtkObj(p, Abc_Lit2Var(pObj->pFans[k])) == NULL ) { if ( *pvSyms == NULL ) *pvSyms = Vec_IntAlloc( 16 ); Vec_IntPush( *pvSyms, (Abc_Lit2Var(pObj->pFans[i]) << 8) | Abc_Lit2Var(pObj->pFans[k]) ); } } } void Amap_CreateCheckAsym( Kit_DsdNtk_t * p, Vec_Int_t ** pvSyms ) { Amap_CreateCheckAsym_rec( p, Abc_LitRegular(p->Root), pvSyms ); } /**Function************************************************************* Synopsis [Creates rules for the given gate] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_CreateRulesForGate( Amap_Lib_t * pLib, Amap_Gat_t * pGate ) { Kit_DsdNtk_t * pNtk, * pTemp; Vec_Int_t * vSyms = NULL; Vec_Int_t * vNods; Amap_Nod_t * pNod; Amap_Set_t * pSet, * pSet2; int iNod, i, k, Entry; // if ( pGate->nPins > 4 ) // return; pNtk = Kit_DsdDecomposeMux( pGate->pFunc, pGate->nPins, 2 ); if ( pGate->nPins == 2 && (pGate->pFunc[0] == 0x66666666 || pGate->pFunc[0] == ~0x66666666) ) pLib->fHasXor = 1; if ( Kit_DsdNonDsdSizeMax(pNtk) == 3 ) pLib->fHasMux = pGate->fMux = 1; pNtk = Kit_DsdExpand( pTemp = pNtk ); Kit_DsdNtkFree( pTemp ); Kit_DsdVerify( pNtk, pGate->pFunc, pGate->nPins ); // check symmetries Amap_CreateCheckAsym( pNtk, &vSyms ); // if ( vSyms ) // Kit_DsdPrint( stdout, pNtk ), printf( "\n" ); if ( pLib->fVerbose ) //if ( pGate->fMux ) { printf( "\nProcessing library gate %4d: %10s ", pGate->Id, pGate->pName ); Kit_DsdPrint( stdout, pNtk ); } vNods = Amap_CreateRulesFromDsd( pLib, pNtk ); if ( vNods ) { Vec_IntForEachEntry( vNods, iNod, i ) { assert( iNod > 1 ); pNod = Amap_LibNod( pLib, Abc_Lit2Var(iNod) ); // assert( pNod->Type == AMAP_OBJ_MUX || pNod->nSuppSize == pGate->nPins ); pSet = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) ); memset( pSet, 0, sizeof(Amap_Set_t) ); pSet->iGate = pGate->Id; pSet->fInv = Abc_LitIsCompl(iNod); pSet->nIns = pGate->nPins; if ( Amap_LibDeriveGatePerm( pLib, pGate, pNtk, pNod, pSet->Ins ) == 0 ) { if ( pLib->fVerbose ) { printf( "Cound not prepare gate \"%s\": ", pGate->pName ); Kit_DsdPrint( stdout, pNtk ); } continue; } pSet->pNext = pNod->pSets; pNod->pSets = pSet; pLib->nSets++; if ( vSyms == NULL ) continue; // continue; // add sets equivalent due to symmetry Vec_IntForEachEntry( vSyms, Entry, k ) { int iThis = Entry & 0xff; int iThat = Entry >> 8; // printf( "%d %d\n", iThis, iThat ); // create new set pSet2 = (Amap_Set_t *)Aig_MmFlexEntryFetch( pLib->pMemSet, sizeof(Amap_Set_t) ); memset( pSet2, 0, sizeof(Amap_Set_t) ); pSet2->iGate = pGate->Id; pSet2->fInv = Abc_LitIsCompl(iNod); pSet2->nIns = pGate->nPins; memcpy( pSet2->Ins, pSet->Ins, pGate->nPins ); // update inputs pSet2->Ins[iThis] = Abc_Var2Lit( Abc_Lit2Var(pSet->Ins[iThat]), Abc_LitIsCompl(pSet->Ins[iThis]) ); pSet2->Ins[iThat] = Abc_Var2Lit( Abc_Lit2Var(pSet->Ins[iThis]), Abc_LitIsCompl(pSet->Ins[iThat]) ); // add set to collection pSet2->pNext = pNod->pSets; pNod->pSets = pSet2; pLib->nSets++; } } Vec_IntFree( vNods ); } Kit_DsdNtkFree( pNtk ); Vec_IntFreeP( &vSyms ); } /**Function************************************************************* Synopsis [Creates rules for the given gate] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_LibCreateRules( Amap_Lib_t * pLib, int fVeryVerbose ) { Amap_Gat_t * pGate; int i, nGates = 0; // abctime clk = Abc_Clock(); pLib->fVerbose = fVeryVerbose; pLib->vRules = Vec_PtrAlloc( 100 ); pLib->vRulesX = Vec_PtrAlloc( 100 ); pLib->vRules3 = Vec_IntAlloc( 100 ); Amap_LibCreateVar( pLib ); Vec_PtrForEachEntry( Amap_Gat_t *, pLib->vSelect, pGate, i ) { if ( pGate->nPins < 2 ) continue; if ( pGate->pFunc == NULL ) { printf( "Amap_LibCreateRules(): Skipping gate %s (%s).\n", pGate->pName, pGate->pForm ); continue; } Amap_CreateRulesForGate( pLib, pGate ); nGates++; } assert( Vec_PtrSize(pLib->vRules) == 2*pLib->nNodes ); assert( Vec_PtrSize(pLib->vRulesX) == 2*pLib->nNodes ); pLib->pRules = Amap_LibLookupTableAlloc( pLib->vRules, 0 ); pLib->pRulesX = Amap_LibLookupTableAlloc( pLib->vRulesX, 0 ); Vec_VecFree( (Vec_Vec_t *)pLib->vRules ); pLib->vRules = NULL; Vec_VecFree( (Vec_Vec_t *)pLib->vRulesX ); pLib->vRulesX = NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/amapUniq.c000066400000000000000000000220361300674244400234510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [amapUniq.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [Checks if the structural node already exists.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapUniq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if the entry exists and returns value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntCheckWithMask( Vec_Int_t * p, int Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( (0xffff & p->pArray[i]) == (0xffff & Entry) ) return p->pArray[i] >> 16; return -1; } /**Function************************************************************* Synopsis [Pushes entry in the natural order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntPushOrderWithMask( Vec_Int_t * p, int Entry ) { int i; if ( p->nSize == p->nCap ) Vec_IntGrow( p, 2 * p->nCap ); p->nSize++; for ( i = p->nSize-2; i >= 0; i-- ) if ( (0xffff & p->pArray[i]) > (0xffff & Entry) ) p->pArray[i+1] = p->pArray[i]; else break; p->pArray[i+1] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibFindNode( Amap_Lib_t * pLib, int iFan0, int iFan1, int fXor ) { if ( fXor ) return Vec_IntCheckWithMask( (Vec_Int_t *)Vec_PtrEntry(pLib->vRulesX, iFan0), iFan1 ); else return Vec_IntCheckWithMask( (Vec_Int_t *)Vec_PtrEntry(pLib->vRules, iFan0), iFan1 ); } /**Function************************************************************* Synopsis [Checks if the three-argument rule exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibFindMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ) { int x; for ( x = 0; x < Vec_IntSize(p->vRules3); x += 4 ) { if ( Vec_IntEntry(p->vRules3, x) == iFan0 && Vec_IntEntry(p->vRules3, x+1) == iFan1 && Vec_IntEntry(p->vRules3, x+2) == iFan2 ) { return Vec_IntEntry(p->vRules3, x+3); } } return -1; } /**Function************************************************************* Synopsis [Creates a new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Nod_t * Amap_LibCreateObj( Amap_Lib_t * p ) { Amap_Nod_t * pNode; if ( p->nNodes == p->nNodesAlloc ) { p->pNodes = ABC_REALLOC( Amap_Nod_t, p->pNodes, 2*p->nNodesAlloc ); p->nNodesAlloc *= 2; } pNode = Amap_LibNod( p, p->nNodes ); memset( pNode, 0, sizeof(Amap_Nod_t) ); pNode->Id = p->nNodes++; Vec_PtrPush( p->vRules, Vec_IntAlloc(8) ); Vec_PtrPush( p->vRules, Vec_IntAlloc(8) ); Vec_PtrPush( p->vRulesX, Vec_IntAlloc(8) ); Vec_PtrPush( p->vRulesX, Vec_IntAlloc(8) ); return pNode; } /**Function************************************************************* Synopsis [Creates a new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibCreateVar( Amap_Lib_t * p ) { Amap_Nod_t * pNode; // start the manager assert( p->pNodes == NULL ); p->nNodesAlloc = 256; p->pNodes = ABC_ALLOC( Amap_Nod_t, p->nNodesAlloc ); // create the first node pNode = Amap_LibCreateObj( p ); p->pNodes->Type = AMAP_OBJ_PI; p->pNodes->nSuppSize = 1; return 0; } /**Function************************************************************* Synopsis [Creates a new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibCreateNode( Amap_Lib_t * p, int iFan0, int iFan1, int fXor ) { Amap_Nod_t * pNode; int iFan; if ( iFan0 < iFan1 ) { iFan = iFan0; iFan0 = iFan1; iFan1 = iFan; } pNode = Amap_LibCreateObj( p ); pNode->Type = fXor? AMAP_OBJ_XOR : AMAP_OBJ_AND; pNode->nSuppSize = p->pNodes[Abc_Lit2Var(iFan0)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan1)].nSuppSize; pNode->iFan0 = iFan0; pNode->iFan1 = iFan1; if ( p->fVerbose ) printf( "Creating node %5d %c : iFan0 = %5d%c iFan1 = %5d%c\n", pNode->Id, (fXor?'x':' '), Abc_Lit2Var(iFan0), (Abc_LitIsCompl(iFan0)?'-':'+'), Abc_Lit2Var(iFan1), (Abc_LitIsCompl(iFan1)?'-':'+') ); if ( fXor ) { if ( iFan0 == iFan1 ) Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRulesX, iFan0), (pNode->Id << 16) | iFan1 ); else { Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRulesX, iFan0), (pNode->Id << 16) | iFan1 ); Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRulesX, iFan1), (pNode->Id << 16) | iFan0 ); } } else { if ( iFan0 == iFan1 ) Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRules, iFan0), (pNode->Id << 16) | iFan1 ); else { Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRules, iFan0), (pNode->Id << 16) | iFan1 ); Vec_IntPushOrderWithMask( (Vec_Int_t *)Vec_PtrEntry(p->vRules, iFan1), (pNode->Id << 16) | iFan0 ); } } return pNode->Id; } /**Function************************************************************* Synopsis [Creates a new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_LibCreateMux( Amap_Lib_t * p, int iFan0, int iFan1, int iFan2 ) { Amap_Nod_t * pNode; pNode = Amap_LibCreateObj( p ); pNode->Type = AMAP_OBJ_MUX; pNode->nSuppSize = p->pNodes[Abc_Lit2Var(iFan0)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan1)].nSuppSize + p->pNodes[Abc_Lit2Var(iFan2)].nSuppSize; pNode->iFan0 = iFan0; pNode->iFan1 = iFan1; pNode->iFan2 = iFan2; if ( p->fVerbose ) printf( "Creating node %5d %c : iFan0 = %5d%c iFan1 = %5d%c iFan2 = %5d%c\n", pNode->Id, 'm', Abc_Lit2Var(iFan0), (Abc_LitIsCompl(iFan0)?'-':'+'), Abc_Lit2Var(iFan1), (Abc_LitIsCompl(iFan1)?'-':'+'), Abc_Lit2Var(iFan2), (Abc_LitIsCompl(iFan2)?'-':'+') ); Vec_IntPush( p->vRules3, iFan0 ); Vec_IntPush( p->vRules3, iFan1 ); Vec_IntPush( p->vRules3, iFan2 ); Vec_IntPush( p->vRules3, pNode->Id ); return pNode->Id; } /**Function************************************************************* Synopsis [Allocates triangular lookup table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int ** Amap_LibLookupTableAlloc( Vec_Ptr_t * vVec, int fVerbose ) { Vec_Int_t * vOne; int ** pRes, * pBuffer; int i, k, nTotal, nSize, nEntries, Value; // count the total size nEntries = nSize = Vec_PtrSize( vVec ); Vec_PtrForEachEntry( Vec_Int_t *, vVec, vOne, i ) nEntries += Vec_IntSize(vOne); pBuffer = ABC_ALLOC( int, nSize * sizeof(void *) + nEntries ); pRes = (int **)pBuffer; pRes[0] = pBuffer + nSize * sizeof(void *); nTotal = 0; Vec_PtrForEachEntry( Vec_Int_t *, vVec, vOne, i ) { pRes[i] = pRes[0] + nTotal; nTotal += Vec_IntSize(vOne) + 1; if ( fVerbose ) printf( "%d : ", i ); Vec_IntForEachEntry( vOne, Value, k ) { pRes[i][k] = Value; if ( fVerbose ) printf( "%d(%d) ", Value&0xffff, Value>>16 ); } if ( fVerbose ) printf( "\n" ); pRes[i][k] = 0; } assert( nTotal == nEntries ); return pRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/amap/module.make000066400000000000000000000005531300674244400236560ustar00rootroot00000000000000SRC += src/map/amap/amapCore.c \ src/map/amap/amapGraph.c \ src/map/amap/amapLib.c \ src/map/amap/amapLiberty.c \ src/map/amap/amapMan.c \ src/map/amap/amapMatch.c \ src/map/amap/amapMerge.c \ src/map/amap/amapOutput.c \ src/map/amap/amapParse.c \ src/map/amap/amapPerm.c \ src/map/amap/amapRead.c \ src/map/amap/amapRule.c \ src/map/amap/amapUniq.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/000077500000000000000000000000001300674244400214005ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/cov.h000066400000000000000000000115321300674244400223420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cov.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cov.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__cov__cov_h #define ABC__map__cov__cov_h #include "base/abc/abc.h" #include "covInt.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Cov_Man_t_ Cov_Man_t; typedef struct Cov_Obj_t_ Cov_Obj_t; // storage for node information struct Cov_Obj_t_ { Min_Cube_t * pCover[3]; // pos/neg/esop Vec_Int_t * vSupp; // computed support (all nodes except CIs) }; // storage for additional information struct Cov_Man_t_ { // general characteristics int nFaninMax; // the number of vars int nCubesMax; // the limit on the number of cubes in the intermediate covers int nWords; // the number of words Vec_Int_t * vFanCounts; // fanout counts Vec_Ptr_t * vObjStrs; // object structures void * pMemory; // memory for the internal data strctures Min_Man_t * pManMin; // the cube manager int fUseEsop; // enables ESOPs int fUseSop; // enables SOPs // arrays to map local variables Vec_Int_t * vComTo0; // mapping of common variables into first fanin Vec_Int_t * vComTo1; // mapping of common variables into second fanin Vec_Int_t * vPairs0; // the first var in each pair of common vars Vec_Int_t * vPairs1; // the second var in each pair of common vars Vec_Int_t * vTriv0; // trival support of the first node Vec_Int_t * vTriv1; // trival support of the second node // statistics int nSupps; // supports created int nSuppsMax; // the maximum number of supports int nBoundary; // the boundary size int nNodes; // the number of nodes processed }; static inline Cov_Obj_t * Abc_ObjGetStr( Abc_Obj_t * pObj ) { return (Cov_Obj_t *)Vec_PtrEntry(((Cov_Man_t *)pObj->pNtk->pManCut)->vObjStrs, pObj->Id); } static inline void Abc_ObjSetSupp( Abc_Obj_t * pObj, Vec_Int_t * vVec ) { Abc_ObjGetStr(pObj)->vSupp = vVec; } static inline Vec_Int_t * Abc_ObjGetSupp( Abc_Obj_t * pObj ) { return Abc_ObjGetStr(pObj)->vSupp; } static inline void Abc_ObjSetCover2( Abc_Obj_t * pObj, Min_Cube_t * pCov ) { Abc_ObjGetStr(pObj)->pCover[2] = pCov; } static inline Min_Cube_t * Abc_ObjGetCover2( Abc_Obj_t * pObj ) { return Abc_ObjGetStr(pObj)->pCover[2]; } static inline void Abc_ObjSetCover( Abc_Obj_t * pObj, Min_Cube_t * pCov, int Pol ) { Abc_ObjGetStr(pObj)->pCover[Pol] = pCov; } static inline Min_Cube_t * Abc_ObjGetCover( Abc_Obj_t * pObj, int Pol ) { return Abc_ObjGetStr(pObj)->pCover[Pol]; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== covBuild.c ==========================================================*/ extern Abc_Ntk_t * Abc_NtkCovDerive( Cov_Man_t * p, Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_NtkCovDeriveClean( Cov_Man_t * p, Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_NtkCovDeriveRegular( Cov_Man_t * p, Abc_Ntk_t * pNtk ); /*=== covCore.c ===========================================================*/ extern Abc_Ntk_t * Abc_NtkSopEsopCover( Abc_Ntk_t * pNtk, int nFaninMax, int nCubesMax, int fUseEsop, int fUseSop, int fUseInvs, int fVerbose ); /*=== covMan.c ============================================================*/ extern Cov_Man_t * Cov_ManAlloc( Abc_Ntk_t * pNtk, int nFaninMax, int nCubesMax ); extern void Cov_ManFree( Cov_Man_t * p ); extern void Abc_NodeCovDropData( Cov_Man_t * p, Abc_Obj_t * pObj ); /*=== covTest.c ===========================================================*/ extern Abc_Ntk_t * Abc_NtkCovTestSop( Abc_Ntk_t * pNtk ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covBuild.c000066400000000000000000000414731300674244400233240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covBuild.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [Network construction procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covBuild.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cov.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCovDeriveCube( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, Min_Cube_t * pCube, Vec_Int_t * vSupp, int fCompl ) { Vec_Int_t * vLits; Abc_Obj_t * pNodeNew, * pFanin; int i, iFanin, Lit; // create empty cube if ( pCube->nLits == 0 ) { if ( fCompl ) return Abc_NtkCreateNodeConst0(pNtkNew); return Abc_NtkCreateNodeConst1(pNtkNew); } // get the literals of this cube vLits = Vec_IntAlloc( 10 ); Min_CubeGetLits( pCube, vLits ); assert( pCube->nLits == (unsigned)vLits->nSize ); // create special case when there is only one literal if ( pCube->nLits == 1 ) { iFanin = Vec_IntEntry(vLits,0); pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) ); Lit = Min_CubeGetVar(pCube, iFanin); assert( Lit == 1 || Lit == 2 ); Vec_IntFree( vLits ); if ( (Lit == 1) ^ fCompl )// negative return Abc_NtkCreateNodeInv( pNtkNew, pFanin->pCopy ); return pFanin->pCopy; } assert( pCube->nLits > 1 ); // create the AND cube pNodeNew = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < vLits->nSize; i++ ) { iFanin = Vec_IntEntry(vLits,i); pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) ); Lit = Min_CubeGetVar(pCube, iFanin); assert( Lit == 1 || Lit == 2 ); Vec_IntWriteEntry( vLits, i, Lit==1 ); Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); } pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, vLits->pArray ); if ( fCompl ) Abc_SopComplement( (char *)pNodeNew->pData ); Vec_IntFree( vLits ); return pNodeNew; } /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCovDeriveNode_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int Level ) { Min_Cube_t * pCover, * pCube; Abc_Obj_t * pFaninNew, * pNodeNew, * pFanin; Vec_Int_t * vSupp; int Entry, nCubes, i; if ( Abc_ObjIsCi(pObj) ) return pObj->pCopy; assert( Abc_ObjIsNode(pObj) ); // skip if already computed if ( pObj->pCopy ) return pObj->pCopy; // get the support and the cover vSupp = Abc_ObjGetSupp( pObj ); pCover = Abc_ObjGetCover2( pObj ); assert( vSupp ); /* if ( pCover && pCover->nVars - Min_CoverSuppVarNum(p->pManMin, pCover) > 0 ) { printf( "%d\n ", pCover->nVars - Min_CoverSuppVarNum(p->pManMin, pCover) ); Min_CoverWrite( stdout, pCover ); } */ /* // print the support of this node printf( "{ " ); Vec_IntForEachEntry( vSupp, Entry, i ) printf( "%d ", Entry ); printf( "} cubes = %d\n", Min_CoverCountCubes( pCover ) ); */ // process the fanins Vec_IntForEachEntry( vSupp, Entry, i ) { pFanin = Abc_NtkObj(pObj->pNtk, Entry); Abc_NtkCovDeriveNode_rec( p, pNtkNew, pFanin, Level+1 ); } // for each cube, construct the node nCubes = Min_CoverCountCubes( pCover ); if ( nCubes == 0 ) pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew); else if ( nCubes == 1 ) pNodeNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCover, vSupp, 0 ); else { pNodeNew = Abc_NtkCreateNode( pNtkNew ); Min_CoverForEachCube( pCover, pCube ) { pFaninNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCube, vSupp, 0 ); Abc_ObjAddFanin( pNodeNew, pFaninNew ); } pNodeNew->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, nCubes ); } /* printf( "Created node %d(%d) at level %d: ", pNodeNew->Id, pObj->Id, Level ); Vec_IntForEachEntry( vSupp, Entry, i ) { pFanin = Abc_NtkObj(pObj->pNtk, Entry); printf( "%d(%d) ", pFanin->pCopy->Id, pFanin->Id ); } printf( "\n" ); Min_CoverWrite( stdout, pCover ); */ pObj->pCopy = pNodeNew; return pNodeNew; } /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCovDerive( Cov_Man_t * p, Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsStrash(pNtk) ); // perform strashing pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // reconstruct the network Abc_NtkForEachCo( pNtk, pObj, i ) { Abc_NtkCovDeriveNode_rec( p, pNtkNew, Abc_ObjFanin0(pObj), 0 ); // printf( "*** CO %s : %d -> %d \n", Abc_ObjName(pObj), pObj->pCopy->Id, Abc_ObjFanin0(pObj)->pCopy->Id ); } // add the COs Abc_NtkFinalize( pNtk, pNtkNew ); Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkCovDerive: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCovDeriveInv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCompl ) { assert( pObj->pCopy ); if ( !fCompl ) return pObj->pCopy; if ( pObj->pCopy->pCopy == NULL ) pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); return pObj->pCopy->pCopy; } /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCovDeriveCubeInv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, Min_Cube_t * pCube, Vec_Int_t * vSupp ) { Vec_Int_t * vLits; Abc_Obj_t * pNodeNew, * pFanin; int i, iFanin, Lit; // create empty cube if ( pCube->nLits == 0 ) return Abc_NtkCreateNodeConst1(pNtkNew); // get the literals of this cube vLits = Vec_IntAlloc( 10 ); Min_CubeGetLits( pCube, vLits ); assert( pCube->nLits == (unsigned)vLits->nSize ); // create special case when there is only one literal if ( pCube->nLits == 1 ) { iFanin = Vec_IntEntry(vLits,0); pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) ); Lit = Min_CubeGetVar(pCube, iFanin); assert( Lit == 1 || Lit == 2 ); Vec_IntFree( vLits ); // if ( Lit == 1 )// negative // return Abc_NtkCreateNodeInv( pNtkNew, pFanin->pCopy ); // return pFanin->pCopy; return Abc_NtkCovDeriveInv( pNtkNew, pFanin, Lit==1 ); } assert( pCube->nLits > 1 ); // create the AND cube pNodeNew = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < vLits->nSize; i++ ) { iFanin = Vec_IntEntry(vLits,i); pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) ); Lit = Min_CubeGetVar(pCube, iFanin); assert( Lit == 1 || Lit == 2 ); Vec_IntWriteEntry( vLits, i, Lit==1 ); // Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); Abc_ObjAddFanin( pNodeNew, Abc_NtkCovDeriveInv( pNtkNew, pFanin, Lit==1 ) ); } // pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, vLits->pArray ); pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, NULL ); Vec_IntFree( vLits ); return pNodeNew; } /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCovDeriveNodeInv_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCompl ) { Min_Cube_t * pCover, * pCube; Abc_Obj_t * pFaninNew, * pNodeNew, * pFanin; Vec_Int_t * vSupp; int Entry, nCubes, i; // skip if already computed if ( pObj->pCopy ) return Abc_NtkCovDeriveInv( pNtkNew, pObj, fCompl ); assert( Abc_ObjIsNode(pObj) ); // get the support and the cover vSupp = Abc_ObjGetSupp( pObj ); pCover = Abc_ObjGetCover2( pObj ); assert( vSupp ); // process the fanins Vec_IntForEachEntry( vSupp, Entry, i ) { pFanin = Abc_NtkObj(pObj->pNtk, Entry); Abc_NtkCovDeriveNodeInv_rec( p, pNtkNew, pFanin, 0 ); } // for each cube, construct the node nCubes = Min_CoverCountCubes( pCover ); if ( nCubes == 0 ) pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew); else if ( nCubes == 1 ) pNodeNew = Abc_NtkCovDeriveCubeInv( pNtkNew, pObj, pCover, vSupp ); else { pNodeNew = Abc_NtkCreateNode( pNtkNew ); Min_CoverForEachCube( pCover, pCube ) { pFaninNew = Abc_NtkCovDeriveCubeInv( pNtkNew, pObj, pCube, vSupp ); Abc_ObjAddFanin( pNodeNew, pFaninNew ); } pNodeNew->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, nCubes ); } pObj->pCopy = pNodeNew; return Abc_NtkCovDeriveInv( pNtkNew, pObj, fCompl ); } /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [The resulting network contains only pure AND/OR/EXOR gates and inverters. This procedure is usedful to generate Verilog.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCovDeriveClean( Cov_Man_t * p, Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNodeNew; int i; assert( Abc_NtkIsStrash(pNtk) ); // perform strashing pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // reconstruct the network Abc_NtkForEachCo( pNtk, pObj, i ) { pNodeNew = Abc_NtkCovDeriveNodeInv_rec( p, pNtkNew, Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); Abc_ObjAddFanin( pObj->pCopy, pNodeNew ); } // add the COs Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkCovDeriveInv: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCovDerive_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) { int fVerbose = 0; Min_Cube_t * pCover, * pCovers[3]; Abc_Obj_t * pNodeNew, * pFanin; Vec_Int_t * vSupp; Vec_Str_t * vCover; int i, Entry, nCubes, Type; // skip if already computed if ( pObj->pCopy ) return pObj->pCopy; assert( Abc_ObjIsNode(pObj) ); // get the support and the cover vSupp = Abc_ObjGetSupp( pObj ); assert( vSupp ); // choose the cover to implement pCovers[0] = Abc_ObjGetCover( pObj, 0 ); pCovers[1] = Abc_ObjGetCover( pObj, 1 ); pCovers[2] = Abc_ObjGetCover2( pObj ); // use positive polarity if ( pCovers[0] && (!pCovers[1] || Min_CoverCountCubes(pCovers[0]) <= Min_CoverCountCubes(pCovers[1])) && (!pCovers[2] || Min_CoverCountCubes(pCovers[0]) <= Min_CoverCountCubes(pCovers[2])) ) { pCover = pCovers[0]; Type = '1'; } else // use negative polarity if ( pCovers[1] && (!pCovers[0] || Min_CoverCountCubes(pCovers[1]) <= Min_CoverCountCubes(pCovers[0])) && (!pCovers[2] || Min_CoverCountCubes(pCovers[1]) <= Min_CoverCountCubes(pCovers[2])) ) { pCover = pCovers[1]; Type = '0'; } else // use XOR polarity if ( pCovers[2] && (!pCovers[0] || Min_CoverCountCubes(pCovers[2]) < Min_CoverCountCubes(pCovers[0])) && (!pCovers[1] || Min_CoverCountCubes(pCovers[2]) < Min_CoverCountCubes(pCovers[1])) ) { pCover = pCovers[2]; Type = 'x'; } else assert( 0 ); // print the support of this node if ( fVerbose ) { printf( "{ " ); Vec_IntForEachEntry( vSupp, Entry, i ) printf( "%d ", Entry ); printf( "} cubes = %d\n", Min_CoverCountCubes( pCover ) ); } // process the fanins Vec_IntForEachEntry( vSupp, Entry, i ) { pFanin = Abc_NtkObj(pObj->pNtk, Entry); Abc_NtkCovDerive_rec( p, pNtkNew, pFanin ); } // for each cube, construct the node nCubes = Min_CoverCountCubes( pCover ); if ( nCubes == 0 ) pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew); else if ( nCubes == 1 ) pNodeNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCover, vSupp, Type == '0' ); else { // create the node pNodeNew = Abc_NtkCreateNode( pNtkNew ); Vec_IntForEachEntry( vSupp, Entry, i ) { pFanin = Abc_NtkObj(pObj->pNtk, Entry); Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); } // derive the function vCover = Vec_StrAlloc( 100 ); Min_CoverCreate( vCover, pCover, (char)Type ); pNodeNew->pData = Abc_SopRegister((Mem_Flex_t *)pNtkNew->pManFunc, Vec_StrArray(vCover) ); Vec_StrFree( vCover ); } /* printf( "Created node %d(%d) at level %d: ", pNodeNew->Id, pObj->Id, Level ); Vec_IntForEachEntry( vSupp, Entry, i ) { pFanin = Abc_NtkObj(pObj->pNtk, Entry); printf( "%d(%d) ", pFanin->pCopy->Id, pFanin->Id ); } printf( "\n" ); Min_CoverWrite( stdout, pCover ); */ return pObj->pCopy = pNodeNew; } /**Function************************************************************* Synopsis [Derives the decomposed network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCovDeriveRegular( Cov_Man_t * p, Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNodeNew; int i; assert( Abc_NtkIsStrash(pNtk) ); // perform strashing pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // reconstruct the network if ( Abc_ObjFanoutNum(Abc_AigConst1(pNtk)) > 0 ) Abc_AigConst1(pNtk)->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); Abc_NtkForEachCo( pNtk, pObj, i ) { pNodeNew = Abc_NtkCovDerive_rec( p, pNtkNew, Abc_ObjFanin0(pObj) ); if ( Abc_ObjFaninC0(pObj) ) { if ( pNodeNew->pData && Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 1 ) Abc_SopComplement( (char *)pNodeNew->pData ); else pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew ); } Abc_ObjAddFanin( pObj->pCopy, pNodeNew ); } // add the COs Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkCovDerive: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covCore.c000066400000000000000000000742201300674244400231510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cov.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkCovCovers( Cov_Man_t * p, Abc_Ntk_t * pNtk, int fVerbose ); static int Abc_NtkCovCoversOne( Cov_Man_t * p, Abc_Ntk_t * pNtk, int fVerbose ); static void Abc_NtkCovCovers_rec( Cov_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vBoundary ); /* static int Abc_NodeCovPropagateEsop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 ); static int Abc_NodeCovPropagateSop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 ); static int Abc_NodeCovUnionEsop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp ); static int Abc_NodeCovUnionSop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp ); static int Abc_NodeCovProductEsop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp ); static int Abc_NodeCovProductSop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp ); */ static int Abc_NodeCovPropagate( Cov_Man_t * p, Abc_Obj_t * pObj ); static Min_Cube_t * Abc_NodeCovProduct( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int fEsop, int nSupp ); static Min_Cube_t * Abc_NodeCovSum( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int fEsop, int nSupp ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSopEsopCover( Abc_Ntk_t * pNtk, int nFaninMax, int nCubesMax, int fUseEsop, int fUseSop, int fUseInvs, int fVerbose ) { Abc_Ntk_t * pNtkNew; Cov_Man_t * p; assert( Abc_NtkIsStrash(pNtk) ); // create the manager p = Cov_ManAlloc( pNtk, nFaninMax, nCubesMax ); p->fUseEsop = fUseEsop; p->fUseSop = fUseSop; pNtk->pManCut = p; // perform mapping Abc_NtkCovCovers( p, pNtk, fVerbose ); // derive the final network // if ( fUseInvs ) // pNtkNew = Abc_NtkCovDeriveClean( p, pNtk ); // else // pNtkNew = Abc_NtkCovDerive( p, pNtk ); // pNtkNew = NULL; pNtkNew = Abc_NtkCovDeriveRegular( p, pNtk ); Cov_ManFree( p ); pNtk->pManCut = NULL; // make sure that everything is okay if ( pNtkNew && !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkCov: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Compute the supports.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCovCovers( Cov_Man_t * p, Abc_Ntk_t * pNtk, int fVerbose ) { Abc_Obj_t * pObj; int i; abctime clk = Abc_Clock(); // start the manager p->vFanCounts = Abc_NtkFanoutCounts(pNtk); // set trivial cuts for the constant and the CIs pObj = Abc_AigConst1(pNtk); pObj->fMarkA = 1; Abc_NtkForEachCi( pNtk, pObj, i ) pObj->fMarkA = 1; // perform iterative decomposition for ( i = 0; ; i++ ) { if ( fVerbose ) printf( "Iter %d : ", i+1 ); if ( Abc_NtkCovCoversOne(p, pNtk, fVerbose) ) break; } // clean the cut-point markers Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkA = 0; if ( fVerbose ) { ABC_PRT( "Total", Abc_Clock() - clk ); } } /**Function************************************************************* Synopsis [Compute the supports.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCovCoversOne( Cov_Man_t * p, Abc_Ntk_t * pNtk, int fVerbose ) { ProgressBar * pProgress; Abc_Obj_t * pObj; Vec_Ptr_t * vBoundary; int i; abctime clk = Abc_Clock(); int Counter = 0; int fStop = 1; // array to collect the nodes in the new boundary vBoundary = Vec_PtrAlloc( 100 ); // start from the COs and mark visited nodes using pObj->fMarkB pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // skip the solved nodes (including the CIs) pObj = Abc_ObjFanin0(pObj); if ( pObj->fMarkA ) { Counter++; continue; } // traverse the cone starting from this node if ( Abc_ObjGetSupp(pObj) == NULL ) Abc_NtkCovCovers_rec( p, pObj, vBoundary ); // count the number of solved cones if ( Abc_ObjGetSupp(pObj) == NULL ) fStop = 0; else Counter++; /* printf( "%-15s : ", Abc_ObjName(pObj) ); printf( "lev = %5d ", pObj->Level ); if ( Abc_ObjGetSupp(pObj) == NULL ) { printf( "\n" ); continue; } printf( "supp = %3d ", Abc_ObjGetSupp(pObj)->nSize ); printf( "esop = %3d ", Min_CoverCountCubes( Abc_ObjGetCover2(pObj) ) ); printf( "\n" ); */ } Extra_ProgressBarStop( pProgress ); // clean visited nodes Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkB = 0; // create the new boundary p->nBoundary = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vBoundary, pObj, i ) { if ( !pObj->fMarkA ) { pObj->fMarkA = 1; p->nBoundary++; } } Vec_PtrFree( vBoundary ); if ( fVerbose ) { printf( "Outs = %4d (%4d) Node = %6d (%6d) Max = %6d Bound = %4d ", Counter, Abc_NtkCoNum(pNtk), p->nSupps, Abc_NtkNodeNum(pNtk), p->nSuppsMax, p->nBoundary ); ABC_PRT( "T", Abc_Clock() - clk ); } return fStop; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCovCovers_rec( Cov_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vBoundary ) { Abc_Obj_t * pObj0, * pObj1; // return if the support is already computed if ( pObj->fMarkB || pObj->fMarkA )//|| Abc_ObjGetSupp(pObj) ) // why do we need Supp check here??? return; // mark as visited pObj->fMarkB = 1; // get the fanins pObj0 = Abc_ObjFanin0(pObj); pObj1 = Abc_ObjFanin1(pObj); // solve for the fanins Abc_NtkCovCovers_rec( p, pObj0, vBoundary ); Abc_NtkCovCovers_rec( p, pObj1, vBoundary ); // skip the node that spaced out if ( (!pObj0->fMarkA && !Abc_ObjGetSupp(pObj0)) || // fanin is not ready (!pObj1->fMarkA && !Abc_ObjGetSupp(pObj1)) || // fanin is not ready !Abc_NodeCovPropagate( p, pObj ) ) // node's support or covers cannot be computed { // save the nodes of the future boundary if ( !pObj0->fMarkA && Abc_ObjGetSupp(pObj0) ) Vec_PtrPush( vBoundary, pObj0 ); if ( !pObj1->fMarkA && Abc_ObjGetSupp(pObj1) ) Vec_PtrPush( vBoundary, pObj1 ); return; } // consider dropping the fanin supports // Abc_NodeCovDropData( p, pObj0 ); // Abc_NodeCovDropData( p, pObj1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NodeCovSupport( Cov_Man_t * p, Vec_Int_t * vSupp0, Vec_Int_t * vSupp1 ) { Vec_Int_t * vSupp; int k0, k1; assert( vSupp0 && vSupp1 ); Vec_IntFill( p->vComTo0, vSupp0->nSize + vSupp1->nSize, -1 ); Vec_IntFill( p->vComTo1, vSupp0->nSize + vSupp1->nSize, -1 ); Vec_IntClear( p->vPairs0 ); Vec_IntClear( p->vPairs1 ); vSupp = Vec_IntAlloc( vSupp0->nSize + vSupp1->nSize ); for ( k0 = k1 = 0; k0 < vSupp0->nSize && k1 < vSupp1->nSize; ) { if ( vSupp0->pArray[k0] == vSupp1->pArray[k1] ) { Vec_IntWriteEntry( p->vComTo0, vSupp->nSize, k0 ); Vec_IntWriteEntry( p->vComTo1, vSupp->nSize, k1 ); Vec_IntPush( p->vPairs0, k0 ); Vec_IntPush( p->vPairs1, k1 ); Vec_IntPush( vSupp, vSupp0->pArray[k0] ); k0++; k1++; } else if ( vSupp0->pArray[k0] < vSupp1->pArray[k1] ) { Vec_IntWriteEntry( p->vComTo0, vSupp->nSize, k0 ); Vec_IntPush( vSupp, vSupp0->pArray[k0] ); k0++; } else { Vec_IntWriteEntry( p->vComTo1, vSupp->nSize, k1 ); Vec_IntPush( vSupp, vSupp1->pArray[k1] ); k1++; } } for ( ; k0 < vSupp0->nSize; k0++ ) { Vec_IntWriteEntry( p->vComTo0, vSupp->nSize, k0 ); Vec_IntPush( vSupp, vSupp0->pArray[k0] ); } for ( ; k1 < vSupp1->nSize; k1++ ) { Vec_IntWriteEntry( p->vComTo1, vSupp->nSize, k1 ); Vec_IntPush( vSupp, vSupp1->pArray[k1] ); } /* printf( "Zero : " ); for ( k0 = 0; k0 < vSupp0->nSize; k0++ ) printf( "%d ", vSupp0->pArray[k0] ); printf( "\n" ); printf( "One : " ); for ( k1 = 0; k1 < vSupp1->nSize; k1++ ) printf( "%d ", vSupp1->pArray[k1] ); printf( "\n" ); printf( "Sum : " ); for ( k0 = 0; k0 < vSupp->nSize; k0++ ) printf( "%d ", vSupp->pArray[k0] ); printf( "\n" ); printf( "\n" ); */ return vSupp; } /**Function************************************************************* Synopsis [Propagates all types of covers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCovPropagate( Cov_Man_t * p, Abc_Obj_t * pObj ) { Min_Cube_t * pCoverP = NULL, * pCoverN = NULL, * pCoverX = NULL; Min_Cube_t * pCov0, * pCov1, * pCover0, * pCover1; Vec_Int_t * vSupp, * vSupp0, * vSupp1; Abc_Obj_t * pObj0, * pObj1; int fCompl0, fCompl1; pObj0 = Abc_ObjFanin0( pObj ); pObj1 = Abc_ObjFanin1( pObj ); if ( pObj0->fMarkA ) Vec_IntWriteEntry( p->vTriv0, 0, pObj0->Id ); if ( pObj1->fMarkA ) Vec_IntWriteEntry( p->vTriv1, 0, pObj1->Id ); // get the resulting support vSupp0 = pObj0->fMarkA? p->vTriv0 : Abc_ObjGetSupp(pObj0); vSupp1 = pObj1->fMarkA? p->vTriv1 : Abc_ObjGetSupp(pObj1); vSupp = Abc_NodeCovSupport( p, vSupp0, vSupp1 ); // quit if support if too large if ( vSupp->nSize > p->nFaninMax ) { Vec_IntFree( vSupp ); return 0; } // get the complemented attributes fCompl0 = Abc_ObjFaninC0( pObj ); fCompl1 = Abc_ObjFaninC1( pObj ); // propagate ESOP if ( p->fUseEsop ) { // get the covers pCov0 = pObj0->fMarkA? p->pManMin->pTriv0[0] : Abc_ObjGetCover2(pObj0); pCov1 = pObj1->fMarkA? p->pManMin->pTriv1[0] : Abc_ObjGetCover2(pObj1); if ( pCov0 && pCov1 ) { // complement the first if needed if ( !fCompl0 ) pCover0 = pCov0; else if ( pCov0 && pCov0->nLits == 0 ) // topmost one is the tautology cube pCover0 = pCov0->pNext; else pCover0 = p->pManMin->pOne0, p->pManMin->pOne0->pNext = pCov0; // complement the second if needed if ( !fCompl1 ) pCover1 = pCov1; else if ( pCov1 && pCov1->nLits == 0 ) // topmost one is the tautology cube pCover1 = pCov1->pNext; else pCover1 = p->pManMin->pOne1, p->pManMin->pOne1->pNext = pCov1; // derive the new cover pCoverX = Abc_NodeCovProduct( p, pCover0, pCover1, 1, vSupp->nSize ); } } // propagate SOPs if ( p->fUseSop ) { // get the covers for the direct polarity pCover0 = pObj0->fMarkA? p->pManMin->pTriv0[fCompl0] : Abc_ObjGetCover(pObj0, fCompl0); pCover1 = pObj1->fMarkA? p->pManMin->pTriv1[fCompl1] : Abc_ObjGetCover(pObj1, fCompl1); // derive the new cover if ( pCover0 && pCover1 ) pCoverP = Abc_NodeCovProduct( p, pCover0, pCover1, 0, vSupp->nSize ); // get the covers for the inverse polarity pCover0 = pObj0->fMarkA? p->pManMin->pTriv0[!fCompl0] : Abc_ObjGetCover(pObj0, !fCompl0); pCover1 = pObj1->fMarkA? p->pManMin->pTriv1[!fCompl1] : Abc_ObjGetCover(pObj1, !fCompl1); // derive the new cover if ( pCover0 && pCover1 ) pCoverN = Abc_NodeCovSum( p, pCover0, pCover1, 0, vSupp->nSize ); } // if none of the covers can be computed quit if ( !pCoverX && !pCoverP && !pCoverN ) { Vec_IntFree( vSupp ); return 0; } // set the covers assert( Abc_ObjGetSupp(pObj) == NULL ); Abc_ObjSetSupp( pObj, vSupp ); Abc_ObjSetCover( pObj, pCoverP, 0 ); Abc_ObjSetCover( pObj, pCoverN, 1 ); Abc_ObjSetCover2( pObj, pCoverX ); //printf( "%3d : %4d %4d %4d\n", pObj->Id, Min_CoverCountCubes(pCoverP), Min_CoverCountCubes(pCoverN), Min_CoverCountCubes(pCoverX) ); // count statistics p->nSupps++; p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Min_Cube_t * Abc_NodeCovProduct( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int fEsop, int nSupp ) { Min_Cube_t * pCube, * pCube0, * pCube1; Min_Cube_t * pCover; int i, Val0, Val1; assert( pCover0 && pCover1 ); // clean storage Min_ManClean( p->pManMin, nSupp ); // go through the cube pairs Min_CoverForEachCube( pCover0, pCube0 ) Min_CoverForEachCube( pCover1, pCube1 ) { // go through the support variables of the cubes for ( i = 0; i < p->vPairs0->nSize; i++ ) { Val0 = Min_CubeGetVar( pCube0, p->vPairs0->pArray[i] ); Val1 = Min_CubeGetVar( pCube1, p->vPairs1->pArray[i] ); if ( (Val0 & Val1) == 0 ) break; } // check disjointness if ( i < p->vPairs0->nSize ) continue; if ( p->pManMin->nCubes > p->nCubesMax ) { pCover = Min_CoverCollect( p->pManMin, nSupp ); //Min_CoverWriteFile( pCover, "large", 1 ); Min_CoverRecycle( p->pManMin, pCover ); return NULL; } // create the product cube pCube = Min_CubeAlloc( p->pManMin ); // add the literals pCube->nLits = 0; for ( i = 0; i < nSupp; i++ ) { if ( p->vComTo0->pArray[i] == -1 ) Val0 = 3; else Val0 = Min_CubeGetVar( pCube0, p->vComTo0->pArray[i] ); if ( p->vComTo1->pArray[i] == -1 ) Val1 = 3; else Val1 = Min_CubeGetVar( pCube1, p->vComTo1->pArray[i] ); if ( (Val0 & Val1) == 3 ) continue; Min_CubeXorVar( pCube, i, (Val0 & Val1) ^ 3 ); pCube->nLits++; } // add the cube to storage if ( fEsop ) Min_EsopAddCube( p->pManMin, pCube ); else Min_SopAddCube( p->pManMin, pCube ); } // minimize the cover if ( fEsop ) Min_EsopMinimize( p->pManMin ); else Min_SopMinimize( p->pManMin ); pCover = Min_CoverCollect( p->pManMin, nSupp ); // quit if the cover is too large if ( Min_CoverCountCubes(pCover) > p->nFaninMax ) { /* Min_CoverWriteFile( pCover, "large", 1 ); Min_CoverExpand( p->pManMin, pCover ); Min_EsopMinimize( p->pManMin ); Min_EsopMinimize( p->pManMin ); Min_EsopMinimize( p->pManMin ); Min_EsopMinimize( p->pManMin ); Min_EsopMinimize( p->pManMin ); Min_EsopMinimize( p->pManMin ); Min_EsopMinimize( p->pManMin ); Min_EsopMinimize( p->pManMin ); Min_EsopMinimize( p->pManMin ); pCover = Min_CoverCollect( p->pManMin, nSupp ); */ Min_CoverRecycle( p->pManMin, pCover ); return NULL; } return pCover; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Min_Cube_t * Abc_NodeCovSum( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int fEsop, int nSupp ) { Min_Cube_t * pCube, * pCube0, * pCube1; Min_Cube_t * pCover; int i, Val0, Val1; assert( pCover0 && pCover1 ); // clean storage Min_ManClean( p->pManMin, nSupp ); Min_CoverForEachCube( pCover0, pCube0 ) { // create the cube pCube = Min_CubeAlloc( p->pManMin ); pCube->nLits = 0; for ( i = 0; i < p->vComTo0->nSize; i++ ) { if ( p->vComTo0->pArray[i] == -1 ) continue; Val0 = Min_CubeGetVar( pCube0, p->vComTo0->pArray[i] ); if ( Val0 == 3 ) continue; Min_CubeXorVar( pCube, i, Val0 ^ 3 ); pCube->nLits++; } if ( p->pManMin->nCubes > p->nCubesMax ) { pCover = Min_CoverCollect( p->pManMin, nSupp ); Min_CoverRecycle( p->pManMin, pCover ); return NULL; } // add the cube to storage if ( fEsop ) Min_EsopAddCube( p->pManMin, pCube ); else Min_SopAddCube( p->pManMin, pCube ); } Min_CoverForEachCube( pCover1, pCube1 ) { // create the cube pCube = Min_CubeAlloc( p->pManMin ); pCube->nLits = 0; for ( i = 0; i < p->vComTo1->nSize; i++ ) { if ( p->vComTo1->pArray[i] == -1 ) continue; Val1 = Min_CubeGetVar( pCube1, p->vComTo1->pArray[i] ); if ( Val1 == 3 ) continue; Min_CubeXorVar( pCube, i, Val1 ^ 3 ); pCube->nLits++; } if ( p->pManMin->nCubes > p->nCubesMax ) { pCover = Min_CoverCollect( p->pManMin, nSupp ); Min_CoverRecycle( p->pManMin, pCover ); return NULL; } // add the cube to storage if ( fEsop ) Min_EsopAddCube( p->pManMin, pCube ); else Min_SopAddCube( p->pManMin, pCube ); } // minimize the cover if ( fEsop ) Min_EsopMinimize( p->pManMin ); else Min_SopMinimize( p->pManMin ); pCover = Min_CoverCollect( p->pManMin, nSupp ); // quit if the cover is too large if ( Min_CoverCountCubes(pCover) > p->nFaninMax ) { Min_CoverRecycle( p->pManMin, pCover ); return NULL; } return pCover; } #if 0 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCovPropagateEsop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 ) { Min_Cube_t * pCover, * pCover0, * pCover1, * pCov0, * pCov1; Vec_Int_t * vSupp, * vSupp0, * vSupp1; if ( pObj0->fMarkA ) Vec_IntWriteEntry( p->vTriv0, 0, pObj0->Id ); if ( pObj1->fMarkA ) Vec_IntWriteEntry( p->vTriv1, 0, pObj1->Id ); // get the resulting support vSupp0 = pObj0->fMarkA? p->vTriv0 : Abc_ObjGetSupp(pObj0); vSupp1 = pObj1->fMarkA? p->vTriv1 : Abc_ObjGetSupp(pObj1); vSupp = Abc_NodeCovSupport( p, vSupp0, vSupp1 ); // quit if support if too large if ( vSupp->nSize > p->nFaninMax ) { Vec_IntFree( vSupp ); return 0; } // get the covers pCov0 = pObj0->fMarkA? p->pManMin->pTriv0[0] : Abc_ObjGetCover2(pObj0); pCov1 = pObj1->fMarkA? p->pManMin->pTriv1[0] : Abc_ObjGetCover2(pObj1); // complement the first if needed if ( !Abc_ObjFaninC0(pObj) ) pCover0 = pCov0; else if ( pCov0 && pCov0->nLits == 0 ) // topmost one is the tautology cube pCover0 = pCov0->pNext; else pCover0 = p->pManMin->pOne0, p->pManMin->pOne0->pNext = pCov0; // complement the second if needed if ( !Abc_ObjFaninC1(pObj) ) pCover1 = pCov1; else if ( pCov1 && pCov1->nLits == 0 ) // topmost one is the tautology cube pCover1 = pCov1->pNext; else pCover1 = p->pManMin->pOne1, p->pManMin->pOne1->pNext = pCov1; // derive and minimize the cover (quit if too large) if ( !Abc_NodeCovProductEsop( p, pCover0, pCover1, vSupp->nSize ) ) { pCover = Min_CoverCollect( p->pManMin, vSupp->nSize ); Min_CoverRecycle( p->pManMin, pCover ); Vec_IntFree( vSupp ); return 0; } // minimize the cover Min_EsopMinimize( p->pManMin ); pCover = Min_CoverCollect( p->pManMin, vSupp->nSize ); // quit if the cover is too large if ( Min_CoverCountCubes(pCover) > p->nFaninMax ) { Min_CoverRecycle( p->pManMin, pCover ); Vec_IntFree( vSupp ); return 0; } // count statistics p->nSupps++; p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps ); // set the covers assert( Abc_ObjGetSupp(pObj) == NULL ); Abc_ObjSetSupp( pObj, vSupp ); Abc_ObjSetCover2( pObj, pCover ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCovPropagateSop( Cov_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 ) { Min_Cube_t * pCoverP, * pCoverN, * pCover0, * pCover1; Vec_Int_t * vSupp, * vSupp0, * vSupp1; int fCompl0, fCompl1; if ( pObj0->fMarkA ) Vec_IntWriteEntry( p->vTriv0, 0, pObj0->Id ); if ( pObj1->fMarkA ) Vec_IntWriteEntry( p->vTriv1, 0, pObj1->Id ); // get the resulting support vSupp0 = pObj0->fMarkA? p->vTriv0 : Abc_ObjGetSupp(pObj0); vSupp1 = pObj1->fMarkA? p->vTriv1 : Abc_ObjGetSupp(pObj1); vSupp = Abc_NodeCovSupport( p, vSupp0, vSupp1 ); // quit if support if too large if ( vSupp->nSize > p->nFaninMax ) { Vec_IntFree( vSupp ); return 0; } // get the complemented attributes fCompl0 = Abc_ObjFaninC0(pObj); fCompl1 = Abc_ObjFaninC1(pObj); // prepare the positive cover pCover0 = pObj0->fMarkA? p->pManMin->pTriv0[fCompl0] : Abc_ObjGetCover(pObj0, fCompl0); pCover1 = pObj1->fMarkA? p->pManMin->pTriv1[fCompl1] : Abc_ObjGetCover(pObj1, fCompl1); // derive and minimize the cover (quit if too large) if ( !pCover0 || !pCover1 ) pCoverP = NULL; else if ( !Abc_NodeCovProductSop( p, pCover0, pCover1, vSupp->nSize ) ) { pCoverP = Min_CoverCollect( p->pManMin, vSupp->nSize ); Min_CoverRecycle( p->pManMin, pCoverP ); pCoverP = NULL; } else { Min_SopMinimize( p->pManMin ); pCoverP = Min_CoverCollect( p->pManMin, vSupp->nSize ); // quit if the cover is too large if ( Min_CoverCountCubes(pCoverP) > p->nFaninMax ) { Min_CoverRecycle( p->pManMin, pCoverP ); pCoverP = NULL; } } // prepare the negative cover pCover0 = pObj0->fMarkA? p->pManMin->pTriv0[!fCompl0] : Abc_ObjGetCover(pObj0, !fCompl0); pCover1 = pObj1->fMarkA? p->pManMin->pTriv1[!fCompl1] : Abc_ObjGetCover(pObj1, !fCompl1); // derive and minimize the cover (quit if too large) if ( !pCover0 || !pCover1 ) pCoverN = NULL; else if ( !Abc_NodeCovUnionSop( p, pCover0, pCover1, vSupp->nSize ) ) { pCoverN = Min_CoverCollect( p->pManMin, vSupp->nSize ); Min_CoverRecycle( p->pManMin, pCoverN ); pCoverN = NULL; } else { Min_SopMinimize( p->pManMin ); pCoverN = Min_CoverCollect( p->pManMin, vSupp->nSize ); // quit if the cover is too large if ( Min_CoverCountCubes(pCoverN) > p->nFaninMax ) { Min_CoverRecycle( p->pManMin, pCoverN ); pCoverN = NULL; } } if ( pCoverP == NULL && pCoverN == NULL ) { Vec_IntFree( vSupp ); return 0; } // count statistics p->nSupps++; p->nSuppsMax = Abc_MaxInt( p->nSuppsMax, p->nSupps ); // set the covers assert( Abc_ObjGetSupp(pObj) == NULL ); Abc_ObjSetSupp( pObj, vSupp ); Abc_ObjSetCover( pObj, pCoverP, 0 ); Abc_ObjSetCover( pObj, pCoverN, 1 ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCovProductEsop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp ) { Min_Cube_t * pCube, * pCube0, * pCube1; int i, Val0, Val1; // clean storage Min_ManClean( p->pManMin, nSupp ); if ( pCover0 == NULL || pCover1 == NULL ) return 1; // go through the cube pairs Min_CoverForEachCube( pCover0, pCube0 ) Min_CoverForEachCube( pCover1, pCube1 ) { // go through the support variables of the cubes for ( i = 0; i < p->vPairs0->nSize; i++ ) { Val0 = Min_CubeGetVar( pCube0, p->vPairs0->pArray[i] ); Val1 = Min_CubeGetVar( pCube1, p->vPairs1->pArray[i] ); if ( (Val0 & Val1) == 0 ) break; } // check disjointness if ( i < p->vPairs0->nSize ) continue; if ( p->pManMin->nCubes >= p->nCubesMax ) return 0; // create the product cube pCube = Min_CubeAlloc( p->pManMin ); // add the literals pCube->nLits = 0; for ( i = 0; i < nSupp; i++ ) { if ( p->vComTo0->pArray[i] == -1 ) Val0 = 3; else Val0 = Min_CubeGetVar( pCube0, p->vComTo0->pArray[i] ); if ( p->vComTo1->pArray[i] == -1 ) Val1 = 3; else Val1 = Min_CubeGetVar( pCube1, p->vComTo1->pArray[i] ); if ( (Val0 & Val1) == 3 ) continue; Min_CubeXorVar( pCube, i, (Val0 & Val1) ^ 3 ); pCube->nLits++; } // add the cube to storage Min_EsopAddCube( p->pManMin, pCube ); } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCovProductSop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp ) { return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCovUnionEsop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp ) { Min_Cube_t * pCube, * pCube0, * pCube1; int i, Val0, Val1; // clean storage Min_ManClean( p->pManMin, nSupp ); if ( pCover0 ) { Min_CoverForEachCube( pCover0, pCube0 ) { // create the cube pCube = Min_CubeAlloc( p->pManMin ); pCube->nLits = 0; for ( i = 0; i < p->vComTo0->nSize; i++ ) { if ( p->vComTo0->pArray[i] == -1 ) continue; Val0 = Min_CubeGetVar( pCube0, p->vComTo0->pArray[i] ); if ( Val0 == 3 ) continue; Min_CubeXorVar( pCube, i, Val0 ^ 3 ); pCube->nLits++; } if ( p->pManMin->nCubes >= p->nCubesMax ) return 0; // add the cube to storage Min_EsopAddCube( p->pManMin, pCube ); } } if ( pCover1 ) { Min_CoverForEachCube( pCover1, pCube1 ) { // create the cube pCube = Min_CubeAlloc( p->pManMin ); pCube->nLits = 0; for ( i = 0; i < p->vComTo1->nSize; i++ ) { if ( p->vComTo1->pArray[i] == -1 ) continue; Val1 = Min_CubeGetVar( pCube1, p->vComTo1->pArray[i] ); if ( Val1 == 3 ) continue; Min_CubeXorVar( pCube, i, Val1 ^ 3 ); pCube->nLits++; } if ( p->pManMin->nCubes >= p->nCubesMax ) return 0; // add the cube to storage Min_EsopAddCube( p->pManMin, pCube ); } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCovUnionSop( Cov_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1, int nSupp ) { return 1; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covInt.h000066400000000000000000000465431300674244400230270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__cov__covInt_h #define ABC__map__cov__covInt_h #include "base/abc/abc.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Min_Man_t_ Min_Man_t; typedef struct Min_Cube_t_ Min_Cube_t; struct Min_Man_t_ { int nVars; // the number of vars int nWords; // the number of words Extra_MmFixed_t * pMemMan; // memory manager for cubes // temporary cubes Min_Cube_t * pOne0; // tautology cube Min_Cube_t * pOne1; // tautology cube Min_Cube_t * pTriv0[2]; // trivial cube Min_Cube_t * pTriv1[2]; // trivial cube Min_Cube_t * pTemp; // cube for computing the distance Min_Cube_t * pBubble; // cube used as a separator // temporary storage for the new cover int nCubes; // the number of cubes Min_Cube_t ** ppStore; // storage for cubes by number of literals }; struct Min_Cube_t_ { Min_Cube_t * pNext; // the pointer to the next cube in the cover unsigned nVars : 10; // the number of variables unsigned nWords : 12; // the number of machine words unsigned nLits : 10; // the number of literals in the cube unsigned uData[1]; // the bit-data for the cube }; // iterators through the entries in the linked lists of cubes #define Min_CoverForEachCube( pCover, pCube ) \ for ( pCube = pCover; \ pCube; \ pCube = pCube->pNext ) #define Min_CoverForEachCubeSafe( pCover, pCube, pCube2 ) \ for ( pCube = pCover, \ pCube2 = pCube? pCube->pNext: NULL; \ pCube; \ pCube = pCube2, \ pCube2 = pCube? pCube->pNext: NULL ) #define Min_CoverForEachCubePrev( pCover, pCube, ppPrev ) \ for ( pCube = pCover, \ ppPrev = &(pCover); \ pCube; \ ppPrev = &pCube->pNext, \ pCube = pCube->pNext ) // macros to get hold of bits and values in the cubes static inline int Min_CubeHasBit( Min_Cube_t * p, int i ) { return (p->uData[(i)>>5] & (1<<((i) & 31))) > 0; } static inline void Min_CubeSetBit( Min_Cube_t * p, int i ) { p->uData[(i)>>5] |= (1<<((i) & 31)); } static inline void Min_CubeXorBit( Min_Cube_t * p, int i ) { p->uData[(i)>>5] ^= (1<<((i) & 31)); } static inline int Min_CubeGetVar( Min_Cube_t * p, int Var ) { return 3 & (p->uData[(2*Var)>>5] >> ((2*Var) & 31)); } static inline void Min_CubeXorVar( Min_Cube_t * p, int Var, int Value ) { p->uData[(2*Var)>>5] ^= (Value<<((2*Var) & 31)); } /*=== covMinEsop.c ==========================================================*/ extern void Min_EsopMinimize( Min_Man_t * p ); extern void Min_EsopAddCube( Min_Man_t * p, Min_Cube_t * pCube ); /*=== covMinSop.c ==========================================================*/ extern void Min_SopMinimize( Min_Man_t * p ); extern void Min_SopAddCube( Min_Man_t * p, Min_Cube_t * pCube ); /*=== covMinMan.c ==========================================================*/ extern Min_Man_t * Min_ManAlloc( int nVars ); extern void Min_ManClean( Min_Man_t * p, int nSupp ); extern void Min_ManFree( Min_Man_t * p ); /*=== covMinUtil.c ==========================================================*/ extern void Min_CoverCreate( Vec_Str_t * vCover, Min_Cube_t * pCover, char Type ); extern void Min_CubeWrite( FILE * pFile, Min_Cube_t * pCube ); extern void Min_CoverWrite( FILE * pFile, Min_Cube_t * pCover ); extern void Min_CoverWriteStore( FILE * pFile, Min_Man_t * p ); extern void Min_CoverWriteFile( Min_Cube_t * pCover, char * pName, int fEsop ); extern void Min_CoverCheck( Min_Man_t * p ); extern int Min_CubeCheck( Min_Cube_t * pCube ); extern Min_Cube_t * Min_CoverCollect( Min_Man_t * p, int nSuppSize ); extern void Min_CoverExpand( Min_Man_t * p, Min_Cube_t * pCover ); extern int Min_CoverSuppVarNum( Min_Man_t * p, Min_Cube_t * pCover ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Min_Cube_t * Min_CubeAlloc( Min_Man_t * p ) { Min_Cube_t * pCube; pCube = (Min_Cube_t *)Extra_MmFixedEntryFetch( p->pMemMan ); pCube->pNext = NULL; pCube->nVars = p->nVars; pCube->nWords = p->nWords; pCube->nLits = 0; memset( pCube->uData, 0xff, sizeof(unsigned) * p->nWords ); return pCube; } /**Function************************************************************* Synopsis [Creates the cube representing elementary var.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Min_Cube_t * Min_CubeAllocVar( Min_Man_t * p, int iVar, int fCompl ) { Min_Cube_t * pCube; pCube = Min_CubeAlloc( p ); Min_CubeXorBit( pCube, iVar*2+fCompl ); pCube->nLits = 1; return pCube; } /**Function************************************************************* Synopsis [Creates the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Min_Cube_t * Min_CubeDup( Min_Man_t * p, Min_Cube_t * pCopy ) { Min_Cube_t * pCube; pCube = Min_CubeAlloc( p ); memcpy( pCube->uData, pCopy->uData, sizeof(unsigned) * p->nWords ); pCube->nLits = pCopy->nLits; return pCube; } /**Function************************************************************* Synopsis [Recycles the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Min_CubeRecycle( Min_Man_t * p, Min_Cube_t * pCube ) { Extra_MmFixedEntryRecycle( p->pMemMan, (char *)pCube ); } /**Function************************************************************* Synopsis [Recycles the cube cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Min_CoverRecycle( Min_Man_t * p, Min_Cube_t * pCover ) { Min_Cube_t * pCube, * pCube2; Min_CoverForEachCubeSafe( pCover, pCube, pCube2 ) Extra_MmFixedEntryRecycle( p->pMemMan, (char *)pCube ); } /**Function************************************************************* Synopsis [Counts the number of cubes in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Min_CubeCountLits( Min_Cube_t * pCube ) { unsigned uData; int Count = 0, i, w; for ( w = 0; w < (int)pCube->nWords; w++ ) { uData = pCube->uData[w] ^ (pCube->uData[w] >> 1); for ( i = 0; i < 32; i += 2 ) if ( uData & (1 << i) ) Count++; } return Count; } /**Function************************************************************* Synopsis [Counts the number of cubes in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Min_CubeGetLits( Min_Cube_t * pCube, Vec_Int_t * vLits ) { unsigned uData; int i, w; Vec_IntClear( vLits ); for ( w = 0; w < (int)pCube->nWords; w++ ) { uData = pCube->uData[w] ^ (pCube->uData[w] >> 1); for ( i = 0; i < 32; i += 2 ) if ( uData & (1 << i) ) Vec_IntPush( vLits, w*16 + i/2 ); } } /**Function************************************************************* Synopsis [Counts the number of cubes in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Min_CoverCountCubes( Min_Cube_t * pCover ) { Min_Cube_t * pCube; int Count = 0; Min_CoverForEachCube( pCover, pCube ) Count++; return Count; } /**Function************************************************************* Synopsis [Checks if two cubes are disjoint.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Min_CubesDisjoint( Min_Cube_t * pCube0, Min_Cube_t * pCube1 ) { unsigned uData; int i; assert( pCube0->nVars == pCube1->nVars ); for ( i = 0; i < (int)pCube0->nWords; i++ ) { uData = pCube0->uData[i] & pCube1->uData[i]; uData = (uData | (uData >> 1)) & 0x55555555; if ( uData != 0x55555555 ) return 1; } return 0; } /**Function************************************************************* Synopsis [Collects the disjoint variables of the two cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Min_CoverGetDisjVars( Min_Cube_t * pThis, Min_Cube_t * pCube, Vec_Int_t * vVars ) { unsigned uData; int i, w; Vec_IntClear( vVars ); for ( w = 0; w < (int)pCube->nWords; w++ ) { uData = pThis->uData[w] & (pThis->uData[w] >> 1) & 0x55555555; uData &= (pCube->uData[w] ^ (pCube->uData[w] >> 1)); if ( uData == 0 ) continue; for ( i = 0; i < 32; i += 2 ) if ( uData & (1 << i) ) Vec_IntPush( vVars, w*16 + i/2 ); } } /**Function************************************************************* Synopsis [Checks if two cubes are disjoint.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Min_CubesDistOne( Min_Cube_t * pCube0, Min_Cube_t * pCube1, Min_Cube_t * pTemp ) { unsigned uData; int i, fFound = 0; for ( i = 0; i < (int)pCube0->nWords; i++ ) { uData = pCube0->uData[i] ^ pCube1->uData[i]; if ( uData == 0 ) { if ( pTemp ) pTemp->uData[i] = 0; continue; } if ( fFound ) return 0; uData = (uData | (uData >> 1)) & 0x55555555; if ( (uData & (uData-1)) > 0 ) // more than one 1 return 0; if ( pTemp ) pTemp->uData[i] = uData | (uData << 1); fFound = 1; } if ( fFound == 0 ) { printf( "\n" ); Min_CubeWrite( stdout, pCube0 ); Min_CubeWrite( stdout, pCube1 ); printf( "Error: Min_CubesDistOne() looks at two equal cubes!\n" ); } return 1; } /**Function************************************************************* Synopsis [Checks if two cubes are disjoint.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Min_CubesDistTwo( Min_Cube_t * pCube0, Min_Cube_t * pCube1, int * pVar0, int * pVar1 ) { unsigned uData;//, uData2; int i, k, Var0 = -1, Var1 = -1; for ( i = 0; i < (int)pCube0->nWords; i++ ) { uData = pCube0->uData[i] ^ pCube1->uData[i]; if ( uData == 0 ) continue; if ( Var0 >= 0 && Var1 >= 0 ) // more than two 1s return 0; uData = (uData | (uData >> 1)) & 0x55555555; if ( (Var0 >= 0 || Var1 >= 0) && (uData & (uData-1)) > 0 ) return 0; for ( k = 0; k < 32; k += 2 ) if ( uData & (1 << k) ) { if ( Var0 == -1 ) Var0 = 16 * i + k/2; else if ( Var1 == -1 ) Var1 = 16 * i + k/2; else return 0; } /* if ( Var0 >= 0 ) { uData &= 0xFFFF; uData2 = (uData >> 16); if ( uData && uData2 ) return 0; if ( uData ) { } uData }= uData2; uData &= 0x } */ } if ( Var0 >= 0 && Var1 >= 0 ) { *pVar0 = Var0; *pVar1 = Var1; return 1; } if ( Var0 == -1 || Var1 == -1 ) { printf( "\n" ); Min_CubeWrite( stdout, pCube0 ); Min_CubeWrite( stdout, pCube1 ); printf( "Error: Min_CubesDistTwo() looks at two equal cubes or dist1 cubes!\n" ); } return 0; } /**Function************************************************************* Synopsis [Makes the produce of two cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Min_Cube_t * Min_CubesProduct( Min_Man_t * p, Min_Cube_t * pCube0, Min_Cube_t * pCube1 ) { Min_Cube_t * pCube; int i; assert( pCube0->nVars == pCube1->nVars ); pCube = Min_CubeAlloc( p ); for ( i = 0; i < p->nWords; i++ ) pCube->uData[i] = pCube0->uData[i] & pCube1->uData[i]; pCube->nLits = Min_CubeCountLits( pCube ); return pCube; } /**Function************************************************************* Synopsis [Makes the produce of two cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Min_Cube_t * Min_CubesXor( Min_Man_t * p, Min_Cube_t * pCube0, Min_Cube_t * pCube1 ) { Min_Cube_t * pCube; int i; assert( pCube0->nVars == pCube1->nVars ); pCube = Min_CubeAlloc( p ); for ( i = 0; i < p->nWords; i++ ) pCube->uData[i] = pCube0->uData[i] ^ pCube1->uData[i]; pCube->nLits = Min_CubeCountLits( pCube ); return pCube; } /**Function************************************************************* Synopsis [Makes the produce of two cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Min_CubesAreEqual( Min_Cube_t * pCube0, Min_Cube_t * pCube1 ) { int i; for ( i = 0; i < (int)pCube0->nWords; i++ ) if ( pCube0->uData[i] != pCube1->uData[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if pCube1 is contained in pCube0, bitwise.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Min_CubeIsContained( Min_Cube_t * pCube0, Min_Cube_t * pCube1 ) { int i; for ( i = 0; i < (int)pCube0->nWords; i++ ) if ( (pCube0->uData[i] & pCube1->uData[i]) != pCube1->uData[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Transforms the cube into the result of merging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Min_CubesTransform( Min_Cube_t * pCube, Min_Cube_t * pDist, Min_Cube_t * pMask ) { int w; for ( w = 0; w < (int)pCube->nWords; w++ ) { pCube->uData[w] = pCube->uData[w] ^ pDist->uData[w]; pCube->uData[w] |= (pDist->uData[w] & ~pMask->uData[w]); } } /**Function************************************************************* Synopsis [Transforms the cube into the result of distance-1 merging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Min_CubesTransformOr( Min_Cube_t * pCube, Min_Cube_t * pDist ) { int w; for ( w = 0; w < (int)pCube->nWords; w++ ) pCube->uData[w] |= pDist->uData[w]; } /**Function************************************************************* Synopsis [Sorts the cover in the increasing number of literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Min_CoverExpandRemoveEqual( Min_Man_t * p, Min_Cube_t * pCover ) { Min_Cube_t * pCube, * pCube2, * pThis; if ( pCover == NULL ) { Min_ManClean( p, p->nVars ); return; } Min_ManClean( p, pCover->nVars ); Min_CoverForEachCubeSafe( pCover, pCube, pCube2 ) { // go through the linked list Min_CoverForEachCube( p->ppStore[pCube->nLits], pThis ) if ( Min_CubesAreEqual( pCube, pThis ) ) { Min_CubeRecycle( p, pCube ); break; } if ( pThis != NULL ) continue; pCube->pNext = p->ppStore[pCube->nLits]; p->ppStore[pCube->nLits] = pCube; p->nCubes++; } } /**Function************************************************************* Synopsis [Returns 1 if the given cube is contained in one of the cubes of the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Min_CoverContainsCube( Min_Man_t * p, Min_Cube_t * pCube ) { Min_Cube_t * pThis; int i; /* // this cube cannot be equal to any cube Min_CoverForEachCube( p->ppStore[pCube->nLits], pThis ) { if ( Min_CubesAreEqual( pCube, pThis ) ) { Min_CubeWrite( stdout, pCube ); assert( 0 ); } } */ // try to find a containing cube for ( i = 0; i <= (int)pCube->nLits; i++ ) Min_CoverForEachCube( p->ppStore[i], pThis ) { // skip the bubble if ( pThis != p->pBubble && Min_CubeIsContained( pThis, pCube ) ) return 1; } return 0; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covMan.c000066400000000000000000000104721300674244400227730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [Decomposition manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cov.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cov_Man_t * Cov_ManAlloc( Abc_Ntk_t * pNtk, int nFaninMax, int nCubesMax ) { Cov_Man_t * pMan; Cov_Obj_t * pMem; Abc_Obj_t * pObj; int i; assert( pNtk->pManCut == NULL ); // start the manager pMan = ABC_ALLOC( Cov_Man_t, 1 ); memset( pMan, 0, sizeof(Cov_Man_t) ); pMan->nFaninMax = nFaninMax; pMan->nCubesMax = nCubesMax; pMan->nWords = Abc_BitWordNum( nFaninMax * 2 ); // get the cubes pMan->vComTo0 = Vec_IntAlloc( 2*nFaninMax ); pMan->vComTo1 = Vec_IntAlloc( 2*nFaninMax ); pMan->vPairs0 = Vec_IntAlloc( nFaninMax ); pMan->vPairs1 = Vec_IntAlloc( nFaninMax ); pMan->vTriv0 = Vec_IntAlloc( 1 ); Vec_IntPush( pMan->vTriv0, -1 ); pMan->vTriv1 = Vec_IntAlloc( 1 ); Vec_IntPush( pMan->vTriv1, -1 ); // allocate memory for object structures pMan->pMemory = pMem = ABC_ALLOC( Cov_Obj_t, sizeof(Cov_Obj_t) * Abc_NtkObjNumMax(pNtk) ); memset( pMem, 0, sizeof(Cov_Obj_t) * Abc_NtkObjNumMax(pNtk) ); // allocate storage for the pointers to the memory pMan->vObjStrs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) ); Vec_PtrFill( pMan->vObjStrs, Abc_NtkObjNumMax(pNtk), NULL ); Abc_NtkForEachObj( pNtk, pObj, i ) Vec_PtrWriteEntry( pMan->vObjStrs, i, pMem + i ); // create the cube manager pMan->pManMin = Min_ManAlloc( nFaninMax ); return pMan; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cov_ManFree( Cov_Man_t * p ) { Vec_Int_t * vSupp; int i; for ( i = 0; i < p->vObjStrs->nSize; i++ ) { vSupp = ((Cov_Obj_t *)p->vObjStrs->pArray[i])->vSupp; if ( vSupp ) Vec_IntFree( vSupp ); } Min_ManFree( p->pManMin ); Vec_PtrFree( p->vObjStrs ); Vec_IntFree( p->vFanCounts ); Vec_IntFree( p->vTriv0 ); Vec_IntFree( p->vTriv1 ); Vec_IntFree( p->vComTo0 ); Vec_IntFree( p->vComTo1 ); Vec_IntFree( p->vPairs0 ); Vec_IntFree( p->vPairs1 ); ABC_FREE( p->pMemory ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Drop the covers at the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeCovDropData( Cov_Man_t * p, Abc_Obj_t * pObj ) { int nFanouts; assert( p->vFanCounts ); nFanouts = Vec_IntEntry( p->vFanCounts, pObj->Id ); assert( nFanouts > 0 ); if ( --nFanouts == 0 ) { Vec_IntFree( Abc_ObjGetSupp(pObj) ); Abc_ObjSetSupp( pObj, NULL ); Min_CoverRecycle( p->pManMin, Abc_ObjGetCover2(pObj) ); Abc_ObjSetCover2( pObj, NULL ); p->nSupps--; } Vec_IntWriteEntry( p->vFanCounts, pObj->Id, nFanouts ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covMinEsop.c000066400000000000000000000225471300674244400236400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covMinEsop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [ESOP manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covMinEsop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "covInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Min_EsopRewrite( Min_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_EsopMinimize( Min_Man_t * p ) { int nCubesInit, nCubesOld, nIter; if ( p->nCubes < 3 ) return; nIter = 0; nCubesInit = p->nCubes; do { nCubesOld = p->nCubes; Min_EsopRewrite( p ); nIter++; } while ( 100.0*(nCubesOld - p->nCubes)/nCubesOld > 3.0 ); // printf( "%d:%d->%d ", nIter, nCubesInit, p->nCubes ); } /**Function************************************************************* Synopsis [Performs one round of rewriting using distance 2 cubes.] Description [The weakness of this procedure is that it tries each cube with only one distance-2 cube. If this pair does not lead to improvement the cube is inserted into the cover anyhow, and we try another pair. A possible improvement would be to try this cube with all distance-2 cubes, until an improvement is found, or until all such cubes are tried.] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_EsopRewrite( Min_Man_t * p ) { Min_Cube_t * pCube, ** ppPrev; Min_Cube_t * pThis, ** ppPrevT; int v00, v01, v10, v11, Var0, Var1, Index, nCubesOld; int nPairs = 0; // insert the bubble before the first cube p->pBubble->pNext = p->ppStore[0]; p->ppStore[0] = p->pBubble; p->pBubble->nLits = 0; // go through the cubes while ( 1 ) { // get the index of the bubble Index = p->pBubble->nLits; // find the bubble Min_CoverForEachCubePrev( p->ppStore[Index], pCube, ppPrev ) if ( pCube == p->pBubble ) break; assert( pCube == p->pBubble ); // remove the bubble, get the next cube after the bubble *ppPrev = p->pBubble->pNext; pCube = p->pBubble->pNext; if ( pCube == NULL ) for ( Index++; Index <= p->nVars; Index++ ) if ( p->ppStore[Index] ) { ppPrev = &(p->ppStore[Index]); pCube = p->ppStore[Index]; break; } // stop if there is no more cubes if ( pCube == NULL ) break; // find the first dist2 cube Min_CoverForEachCubePrev( pCube->pNext, pThis, ppPrevT ) if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) ) break; if ( pThis == NULL && Index < p->nVars ) Min_CoverForEachCubePrev( p->ppStore[Index+1], pThis, ppPrevT ) if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) ) break; if ( pThis == NULL && Index < p->nVars - 1 ) Min_CoverForEachCubePrev( p->ppStore[Index+2], pThis, ppPrevT ) if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) ) break; // continue if there is no dist2 cube if ( pThis == NULL ) { // insert the bubble after the cube p->pBubble->pNext = pCube->pNext; pCube->pNext = p->pBubble; p->pBubble->nLits = pCube->nLits; continue; } nPairs++; // remove the cubes, insert the bubble instead of pCube *ppPrevT = pThis->pNext; *ppPrev = p->pBubble; p->pBubble->pNext = pCube->pNext; p->pBubble->nLits = pCube->nLits; p->nCubes -= 2; // Exorlink-2: // A{v00} B{v01} + A{v10} B{v11} = // A{v00+v10} B{v01} + A{v10} B{v01+v11} = // A{v00} B{v01+v11} + A{v00+v10} B{v11} // save the dist2 parameters v00 = Min_CubeGetVar( pCube, Var0 ); v01 = Min_CubeGetVar( pCube, Var1 ); v10 = Min_CubeGetVar( pThis, Var0 ); v11 = Min_CubeGetVar( pThis, Var1 ); //printf( "\n" ); //Min_CubeWrite( stdout, pCube ); //Min_CubeWrite( stdout, pThis ); // derive the first pair of resulting cubes Min_CubeXorVar( pCube, Var0, v10 ); pCube->nLits -= (v00 != 3); pCube->nLits += ((v00 ^ v10) != 3); Min_CubeXorVar( pThis, Var1, v01 ); pThis->nLits -= (v11 != 3); pThis->nLits += ((v01 ^ v11) != 3); // add the cubes nCubesOld = p->nCubes; Min_EsopAddCube( p, pCube ); Min_EsopAddCube( p, pThis ); // check if the cubes were absorbed if ( p->nCubes < nCubesOld + 2 ) continue; // pull out both cubes assert( pThis == p->ppStore[pThis->nLits] ); p->ppStore[pThis->nLits] = pThis->pNext; assert( pCube == p->ppStore[pCube->nLits] ); p->ppStore[pCube->nLits] = pCube->pNext; p->nCubes -= 2; // derive the second pair of resulting cubes Min_CubeXorVar( pCube, Var0, v10 ); pCube->nLits -= ((v00 ^ v10) != 3); pCube->nLits += (v00 != 3); Min_CubeXorVar( pCube, Var1, v11 ); pCube->nLits -= (v01 != 3); pCube->nLits += ((v01 ^ v11) != 3); Min_CubeXorVar( pThis, Var0, v00 ); pThis->nLits -= (v10 != 3); pThis->nLits += ((v00 ^ v10) != 3); Min_CubeXorVar( pThis, Var1, v01 ); pThis->nLits -= ((v01 ^ v11) != 3); pThis->nLits += (v11 != 3); // add them anyhow Min_EsopAddCube( p, pCube ); Min_EsopAddCube( p, pThis ); } // printf( "Pairs = %d ", nPairs ); } /**Function************************************************************* Synopsis [Adds the cube to storage.] Description [Returns 0 if the cube is added or removed. Returns 1 if the cube is glued with some other cube and has to be added again. Do not forget to clean the storage!] SideEffects [] SeeAlso [] ***********************************************************************/ int Min_EsopAddCubeInt( Min_Man_t * p, Min_Cube_t * pCube ) { Min_Cube_t * pThis, ** ppPrev; // try to find the identical cube Min_CoverForEachCubePrev( p->ppStore[pCube->nLits], pThis, ppPrev ) { if ( Min_CubesAreEqual( pCube, pThis ) ) { *ppPrev = pThis->pNext; Min_CubeRecycle( p, pCube ); Min_CubeRecycle( p, pThis ); p->nCubes--; return 0; } } // find a distance-1 cube if it exists if ( pCube->nLits < pCube->nVars ) Min_CoverForEachCubePrev( p->ppStore[pCube->nLits+1], pThis, ppPrev ) { if ( Min_CubesDistOne( pCube, pThis, p->pTemp ) ) { *ppPrev = pThis->pNext; Min_CubesTransform( pCube, pThis, p->pTemp ); pCube->nLits++; Min_CubeRecycle( p, pThis ); p->nCubes--; return 1; } } Min_CoverForEachCubePrev( p->ppStore[pCube->nLits], pThis, ppPrev ) { if ( Min_CubesDistOne( pCube, pThis, p->pTemp ) ) { *ppPrev = pThis->pNext; Min_CubesTransform( pCube, pThis, p->pTemp ); pCube->nLits--; Min_CubeRecycle( p, pThis ); p->nCubes--; return 1; } } if ( pCube->nLits > 0 ) Min_CoverForEachCubePrev( p->ppStore[pCube->nLits-1], pThis, ppPrev ) { if ( Min_CubesDistOne( pCube, pThis, p->pTemp ) ) { *ppPrev = pThis->pNext; Min_CubesTransform( pCube, pThis, p->pTemp ); Min_CubeRecycle( p, pThis ); p->nCubes--; return 1; } } // add the cube pCube->pNext = p->ppStore[pCube->nLits]; p->ppStore[pCube->nLits] = pCube; p->nCubes++; return 0; } /**Function************************************************************* Synopsis [Adds the cube to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_EsopAddCube( Min_Man_t * p, Min_Cube_t * pCube ) { assert( pCube != p->pBubble ); assert( (int)pCube->nLits == Min_CubeCountLits(pCube) ); while ( Min_EsopAddCubeInt( p, pCube ) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covMinMan.c000066400000000000000000000066371300674244400234470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covMinMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [SOP manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covMinMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "covInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the minimization manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Min_Man_t * Min_ManAlloc( int nVars ) { Min_Man_t * pMan; // start the manager pMan = ABC_ALLOC( Min_Man_t, 1 ); memset( pMan, 0, sizeof(Min_Man_t) ); pMan->nVars = nVars; pMan->nWords = Abc_BitWordNum( nVars * 2 ); pMan->pMemMan = Extra_MmFixedStart( sizeof(Min_Cube_t) + sizeof(unsigned) * (pMan->nWords - 1) ); // allocate storage for the temporary cover pMan->ppStore = ABC_ALLOC( Min_Cube_t *, pMan->nVars + 1 ); // create tautology cubes Min_ManClean( pMan, nVars ); pMan->pOne0 = Min_CubeAlloc( pMan ); pMan->pOne1 = Min_CubeAlloc( pMan ); pMan->pTemp = Min_CubeAlloc( pMan ); pMan->pBubble = Min_CubeAlloc( pMan ); pMan->pBubble->uData[0] = 0; // create trivial cubes Min_ManClean( pMan, 1 ); pMan->pTriv0[0] = Min_CubeAllocVar( pMan, 0, 0 ); pMan->pTriv0[1] = Min_CubeAllocVar( pMan, 0, 1 ); pMan->pTriv1[0] = Min_CubeAllocVar( pMan, 0, 0 ); pMan->pTriv1[1] = Min_CubeAllocVar( pMan, 0, 1 ); Min_ManClean( pMan, nVars ); return pMan; } /**Function************************************************************* Synopsis [Cleans the minimization manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_ManClean( Min_Man_t * p, int nSupp ) { // set the size of the cube manager p->nVars = nSupp; p->nWords = Abc_BitWordNum(2*nSupp); // clean the storage memset( p->ppStore, 0, sizeof(Min_Cube_t *) * (nSupp + 1) ); p->nCubes = 0; } /**Function************************************************************* Synopsis [Stops the minimization manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_ManFree( Min_Man_t * p ) { Extra_MmFixedStop( p->pMemMan ); ABC_FREE( p->ppStore ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covMinSop.c000066400000000000000000000453021300674244400234650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covMinSop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [SOP manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covMinSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "covInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Min_SopRewrite( Min_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_SopMinimize( Min_Man_t * p ) { int nCubesInit, nCubesOld, nIter; if ( p->nCubes < 3 ) return; nIter = 0; nCubesInit = p->nCubes; do { nCubesOld = p->nCubes; Min_SopRewrite( p ); nIter++; // printf( "%d:%d->%d ", nIter, nCubesInit, p->nCubes ); } while ( 100.0*(nCubesOld - p->nCubes)/nCubesOld > 3.0 ); // printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_SopRewrite( Min_Man_t * p ) { Min_Cube_t * pCube, ** ppPrev; Min_Cube_t * pThis, ** ppPrevT; Min_Cube_t * pTemp; int v00, v01, v10, v11, Var0, Var1, Index, fCont0, fCont1, nCubesOld; int nPairs = 0; /* { Min_Cube_t * pCover; pCover = Min_CoverCollect( p, p->nVars ); printf( "\n\n" ); Min_CoverWrite( stdout, pCover ); Min_CoverExpand( p, pCover ); } */ // insert the bubble before the first cube p->pBubble->pNext = p->ppStore[0]; p->ppStore[0] = p->pBubble; p->pBubble->nLits = 0; // go through the cubes while ( 1 ) { // get the index of the bubble Index = p->pBubble->nLits; // find the bubble Min_CoverForEachCubePrev( p->ppStore[Index], pCube, ppPrev ) if ( pCube == p->pBubble ) break; assert( pCube == p->pBubble ); // remove the bubble, get the next cube after the bubble *ppPrev = p->pBubble->pNext; pCube = p->pBubble->pNext; if ( pCube == NULL ) for ( Index++; Index <= p->nVars; Index++ ) if ( p->ppStore[Index] ) { ppPrev = &(p->ppStore[Index]); pCube = p->ppStore[Index]; break; } // stop if there is no more cubes if ( pCube == NULL ) break; // find the first dist2 cube Min_CoverForEachCubePrev( pCube->pNext, pThis, ppPrevT ) if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) ) break; if ( pThis == NULL && Index < p->nVars ) Min_CoverForEachCubePrev( p->ppStore[Index+1], pThis, ppPrevT ) if ( Min_CubesDistTwo( pCube, pThis, &Var0, &Var1 ) ) break; // continue if there is no dist2 cube if ( pThis == NULL ) { // insert the bubble after the cube p->pBubble->pNext = pCube->pNext; pCube->pNext = p->pBubble; p->pBubble->nLits = pCube->nLits; continue; } nPairs++; /* printf( "\n" ); Min_CubeWrite( stdout, pCube ); Min_CubeWrite( stdout, pThis ); */ // remove the cubes, insert the bubble instead of pCube *ppPrevT = pThis->pNext; *ppPrev = p->pBubble; p->pBubble->pNext = pCube->pNext; p->pBubble->nLits = pCube->nLits; p->nCubes -= 2; assert( pCube != p->pBubble && pThis != p->pBubble ); // save the dist2 parameters v00 = Min_CubeGetVar( pCube, Var0 ); v01 = Min_CubeGetVar( pCube, Var1 ); v10 = Min_CubeGetVar( pThis, Var0 ); v11 = Min_CubeGetVar( pThis, Var1 ); assert( v00 != v10 && v01 != v11 ); assert( v00 != 3 || v01 != 3 ); assert( v10 != 3 || v11 != 3 ); //printf( "\n" ); //Min_CubeWrite( stdout, pCube ); //Min_CubeWrite( stdout, pThis ); //printf( "\n" ); //Min_CubeWrite( stdout, pCube ); //Min_CubeWrite( stdout, pThis ); // consider the case when both cubes have non-empty literals if ( v00 != 3 && v01 != 3 && v10 != 3 && v11 != 3 ) { assert( v00 == (v10 ^ 3) ); assert( v01 == (v11 ^ 3) ); // create the temporary cube equal to the first corner Min_CubeXorVar( pCube, Var0, 3 ); // check if this cube is contained fCont0 = Min_CoverContainsCube( p, pCube ); // create the temporary cube equal to the first corner Min_CubeXorVar( pCube, Var0, 3 ); Min_CubeXorVar( pCube, Var1, 3 ); //printf( "\n" ); //Min_CubeWrite( stdout, pCube ); //Min_CubeWrite( stdout, pThis ); // check if this cube is contained fCont1 = Min_CoverContainsCube( p, pCube ); // undo the change Min_CubeXorVar( pCube, Var1, 3 ); // check if the cubes can be overwritten if ( fCont0 && fCont1 ) { // one of the cubes can be recycled, the other expanded and added Min_CubeRecycle( p, pThis ); // remove the literals Min_CubeXorVar( pCube, Var0, v00 ^ 3 ); Min_CubeXorVar( pCube, Var1, v01 ^ 3 ); pCube->nLits -= 2; Min_SopAddCube( p, pCube ); } else if ( fCont0 ) { // expand both cubes and add them Min_CubeXorVar( pCube, Var0, v00 ^ 3 ); pCube->nLits--; Min_SopAddCube( p, pCube ); Min_CubeXorVar( pThis, Var1, v11 ^ 3 ); pThis->nLits--; Min_SopAddCube( p, pThis ); } else if ( fCont1 ) { // expand both cubes and add them Min_CubeXorVar( pCube, Var1, v01 ^ 3 ); pCube->nLits--; Min_SopAddCube( p, pCube ); Min_CubeXorVar( pThis, Var0, v10 ^ 3 ); pThis->nLits--; Min_SopAddCube( p, pThis ); } else { Min_SopAddCube( p, pCube ); Min_SopAddCube( p, pThis ); } // otherwise, no change is possible continue; } // if one of them does not have DC lit, move it if ( v00 != 3 && v01 != 3 ) { assert( v10 == 3 || v11 == 3 ); pTemp = pCube; pCube = pThis; pThis = pTemp; Index = v00; v00 = v10; v10 = Index; Index = v01; v01 = v11; v11 = Index; } // make sure the first cube has first var DC if ( v00 != 3 ) { assert( v01 == 3 ); Index = Var0; Var0 = Var1; Var1 = Index; Index = v00; v00 = v01; v01 = Index; Index = v10; v10 = v11; v11 = Index; } // consider both cases: both have DC lit if ( v00 == 3 && v11 == 3 ) { assert( v01 != 3 && v10 != 3 ); // try the remaining minterm // create the temporary cube equal to the first corner Min_CubeXorVar( pCube, Var0, v10 ); Min_CubeXorVar( pCube, Var1, 3 ); pCube->nLits++; // check if this cube is contained fCont0 = Min_CoverContainsCube( p, pCube ); // undo the cube transformations Min_CubeXorVar( pCube, Var0, v10 ); Min_CubeXorVar( pCube, Var1, 3 ); pCube->nLits--; // check the case when both are covered if ( fCont0 ) { // one of the cubes can be recycled, the other expanded and added Min_CubeRecycle( p, pThis ); // remove the literals Min_CubeXorVar( pCube, Var1, v01 ^ 3 ); pCube->nLits--; Min_SopAddCube( p, pCube ); } else { // try two reduced cubes Min_CubeXorVar( pCube, Var0, v10 ); pCube->nLits++; // remember the cubes nCubesOld = p->nCubes; Min_SopAddCube( p, pCube ); // check if the cube is absorbed if ( p->nCubes < nCubesOld + 1 ) { // absorbed - add the second cube Min_SopAddCube( p, pThis ); } else { // remove this cube, and try another one assert( pCube == p->ppStore[pCube->nLits] ); p->ppStore[pCube->nLits] = pCube->pNext; p->nCubes--; // return the cube to the previous state Min_CubeXorVar( pCube, Var0, v10 ); pCube->nLits--; // generate another reduced cube Min_CubeXorVar( pThis, Var1, v01 ); pThis->nLits++; // add both cubes Min_SopAddCube( p, pCube ); Min_SopAddCube( p, pThis ); } } } else // the first cube has DC lit { assert( v01 != 3 && v10 != 3 && v11 != 3 ); // try the remaining minterm // create the temporary cube equal to the minterm Min_CubeXorVar( pThis, Var0, 3 ); // check if this cube is contained fCont0 = Min_CoverContainsCube( p, pThis ); // undo the cube transformations Min_CubeXorVar( pThis, Var0, 3 ); // check the case when both are covered if ( fCont0 ) { // one of the cubes can be recycled, the other expanded and added Min_CubeRecycle( p, pThis ); // remove the literals Min_CubeXorVar( pCube, Var1, v01 ^ 3 ); pCube->nLits--; Min_SopAddCube( p, pCube ); } else { // try reshaping the cubes // reduce the first cube Min_CubeXorVar( pCube, Var0, v10 ); pCube->nLits++; // expand the second cube Min_CubeXorVar( pThis, Var1, v11 ^ 3 ); pThis->nLits--; // add both cubes Min_SopAddCube( p, pCube ); Min_SopAddCube( p, pThis ); } } } // printf( "Pairs = %d ", nPairs ); } /**Function************************************************************* Synopsis [Adds cube to the SOP cover stored in the manager.] Description [Returns 0 if the cube is added or removed. Returns 1 if the cube is glued with some other cube and has to be added again.] SideEffects [] SeeAlso [] ***********************************************************************/ int Min_SopAddCubeInt( Min_Man_t * p, Min_Cube_t * pCube ) { Min_Cube_t * pThis, * pThis2, ** ppPrev; int i; // try to find the identical cube Min_CoverForEachCube( p->ppStore[pCube->nLits], pThis ) { if ( Min_CubesAreEqual( pCube, pThis ) ) { Min_CubeRecycle( p, pCube ); return 0; } } // try to find a containing cube for ( i = 0; i < (int)pCube->nLits; i++ ) Min_CoverForEachCube( p->ppStore[i], pThis ) { if ( pThis != p->pBubble && Min_CubeIsContained( pThis, pCube ) ) { Min_CubeRecycle( p, pCube ); return 0; } } // try to find distance one in the same bin Min_CoverForEachCubePrev( p->ppStore[pCube->nLits], pThis, ppPrev ) { if ( Min_CubesDistOne( pCube, pThis, NULL ) ) { *ppPrev = pThis->pNext; Min_CubesTransformOr( pCube, pThis ); pCube->nLits--; Min_CubeRecycle( p, pThis ); p->nCubes--; return 1; } } // clean the other cubes using this one for ( i = pCube->nLits + 1; i <= (int)pCube->nVars; i++ ) { ppPrev = &p->ppStore[i]; Min_CoverForEachCubeSafe( p->ppStore[i], pThis, pThis2 ) { if ( pThis != p->pBubble && Min_CubeIsContained( pCube, pThis ) ) { *ppPrev = pThis->pNext; Min_CubeRecycle( p, pThis ); p->nCubes--; } else ppPrev = &pThis->pNext; } } // add the cube pCube->pNext = p->ppStore[pCube->nLits]; p->ppStore[pCube->nLits] = pCube; p->nCubes++; return 0; } /**Function************************************************************* Synopsis [Adds the cube to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_SopAddCube( Min_Man_t * p, Min_Cube_t * pCube ) { assert( Min_CubeCheck( pCube ) ); assert( pCube != p->pBubble ); assert( (int)pCube->nLits == Min_CubeCountLits(pCube) ); while ( Min_SopAddCubeInt( p, pCube ) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_SopContain( Min_Man_t * p ) { Min_Cube_t * pCube, * pCube2, ** ppPrev; int i, k; for ( i = 0; i <= p->nVars; i++ ) { Min_CoverForEachCube( p->ppStore[i], pCube ) Min_CoverForEachCubePrev( pCube->pNext, pCube2, ppPrev ) { if ( !Min_CubesAreEqual( pCube, pCube2 ) ) continue; *ppPrev = pCube2->pNext; Min_CubeRecycle( p, pCube2 ); p->nCubes--; } for ( k = i + 1; k <= p->nVars; k++ ) Min_CoverForEachCubePrev( p->ppStore[k], pCube2, ppPrev ) { if ( !Min_CubeIsContained( pCube, pCube2 ) ) continue; *ppPrev = pCube2->pNext; Min_CubeRecycle( p, pCube2 ); p->nCubes--; } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_SopDist1Merge( Min_Man_t * p ) { Min_Cube_t * pCube, * pCube2, * pCubeNew; int i; for ( i = p->nVars; i >= 0; i-- ) { Min_CoverForEachCube( p->ppStore[i], pCube ) Min_CoverForEachCube( pCube->pNext, pCube2 ) { assert( pCube->nLits == pCube2->nLits ); if ( !Min_CubesDistOne( pCube, pCube2, NULL ) ) continue; pCubeNew = Min_CubesXor( p, pCube, pCube2 ); assert( pCubeNew->nLits == pCube->nLits - 1 ); pCubeNew->pNext = p->ppStore[pCubeNew->nLits]; p->ppStore[pCubeNew->nLits] = pCubeNew; p->nCubes++; } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Min_Cube_t * Min_SopComplement( Min_Man_t * p, Min_Cube_t * pSharp ) { Vec_Int_t * vVars; Min_Cube_t * pCover, * pCube, * pNext, * pReady, * pThis, ** ppPrev; int Num, Value, i; // get the variables vVars = Vec_IntAlloc( 100 ); // create the tautology cube pCover = Min_CubeAlloc( p ); // sharp it with all cubes Min_CoverForEachCube( pSharp, pCube ) Min_CoverForEachCubePrev( pCover, pThis, ppPrev ) { if ( Min_CubesDisjoint( pThis, pCube ) ) continue; // remember the next pointer pNext = pThis->pNext; // get the variables, in which pThis is '-' while pCube is fixed Min_CoverGetDisjVars( pThis, pCube, vVars ); // generate the disjoint cubes pReady = pThis; Vec_IntForEachEntryReverse( vVars, Num, i ) { // correct the literal Min_CubeXorVar( pReady, vVars->pArray[i], 3 ); if ( i == 0 ) break; // create the new cube and clean this value Value = Min_CubeGetVar( pReady, vVars->pArray[i] ); pReady = Min_CubeDup( p, pReady ); Min_CubeXorVar( pReady, vVars->pArray[i], 3 ^ Value ); // add to the cover *ppPrev = pReady; ppPrev = &pReady->pNext; } pThis = pReady; pThis->pNext = pNext; } Vec_IntFree( vVars ); // perform dist-1 merge and contain Min_CoverExpandRemoveEqual( p, pCover ); Min_SopDist1Merge( p ); Min_SopContain( p ); return Min_CoverCollect( p, p->nVars ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Min_SopCheck( Min_Man_t * p ) { Min_Cube_t * pCube, * pThis; int i; pCube = Min_CubeAlloc( p ); Min_CubeXorBit( pCube, 2*0+1 ); Min_CubeXorBit( pCube, 2*1+1 ); Min_CubeXorBit( pCube, 2*2+0 ); Min_CubeXorBit( pCube, 2*3+0 ); Min_CubeXorBit( pCube, 2*4+0 ); Min_CubeXorBit( pCube, 2*5+1 ); Min_CubeXorBit( pCube, 2*6+1 ); pCube->nLits = 7; // Min_CubeWrite( stdout, pCube ); // check that the cubes contain it for ( i = 0; i <= p->nVars; i++ ) Min_CoverForEachCube( p->ppStore[i], pThis ) if ( pThis != p->pBubble && Min_CubeIsContained( pThis, pCube ) ) { Min_CubeRecycle( p, pCube ); return 1; } Min_CubeRecycle( p, pCube ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covMinUtil.c000066400000000000000000000215541300674244400236440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covMinUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [Utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covMinUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "covInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_CubeCreate( Vec_Str_t * vCover, Min_Cube_t * pCube, char Type ) { int i; assert( (int)pCube->nLits == Min_CubeCountLits(pCube) ); for ( i = 0; i < (int)pCube->nVars; i++ ) if ( Min_CubeHasBit(pCube, i*2) ) { if ( Min_CubeHasBit(pCube, i*2+1) ) // fprintf( pFile, "-" ); Vec_StrPush( vCover, '-' ); else // fprintf( pFile, "0" ); Vec_StrPush( vCover, '0' ); } else { if ( Min_CubeHasBit(pCube, i*2+1) ) // fprintf( pFile, "1" ); Vec_StrPush( vCover, '1' ); else // fprintf( pFile, "?" ); Vec_StrPush( vCover, '?' ); } // fprintf( pFile, " 1\n" ); Vec_StrPush( vCover, ' ' ); Vec_StrPush( vCover, Type ); Vec_StrPush( vCover, '\n' ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_CoverCreate( Vec_Str_t * vCover, Min_Cube_t * pCover, char Type ) { Min_Cube_t * pCube; assert( pCover != NULL ); Vec_StrClear( vCover ); Min_CoverForEachCube( pCover, pCube ) Min_CubeCreate( vCover, pCube, Type ); Vec_StrPush( vCover, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_CubeWrite( FILE * pFile, Min_Cube_t * pCube ) { int i; assert( (int)pCube->nLits == Min_CubeCountLits(pCube) ); for ( i = 0; i < (int)pCube->nVars; i++ ) if ( Min_CubeHasBit(pCube, i*2) ) { if ( Min_CubeHasBit(pCube, i*2+1) ) fprintf( pFile, "-" ); else fprintf( pFile, "0" ); } else { if ( Min_CubeHasBit(pCube, i*2+1) ) fprintf( pFile, "1" ); else fprintf( pFile, "?" ); } fprintf( pFile, " 1\n" ); // fprintf( pFile, " %d\n", pCube->nLits ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_CoverWrite( FILE * pFile, Min_Cube_t * pCover ) { Min_Cube_t * pCube; Min_CoverForEachCube( pCover, pCube ) Min_CubeWrite( pFile, pCube ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_CoverWriteStore( FILE * pFile, Min_Man_t * p ) { Min_Cube_t * pCube; int i; for ( i = 0; i <= p->nVars; i++ ) { Min_CoverForEachCube( p->ppStore[i], pCube ) { printf( "%2d : ", i ); if ( pCube == p->pBubble ) { printf( "Bubble\n" ); continue; } Min_CubeWrite( pFile, pCube ); } } printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_CoverWriteFile( Min_Cube_t * pCover, char * pName, int fEsop ) { char Buffer[1000]; Min_Cube_t * pCube; FILE * pFile; int i; sprintf( Buffer, "%s.%s", pName, fEsop? "esop" : "pla" ); for ( i = strlen(Buffer) - 1; i >= 0; i-- ) if ( Buffer[i] == '<' || Buffer[i] == '>' ) Buffer[i] = '_'; pFile = fopen( Buffer, "w" ); fprintf( pFile, "# %s cover for output %s generated by ABC on %s\n", fEsop? "ESOP":"SOP", pName, Extra_TimeStamp() ); fprintf( pFile, ".i %d\n", pCover? pCover->nVars : 0 ); fprintf( pFile, ".o %d\n", 1 ); fprintf( pFile, ".p %d\n", Min_CoverCountCubes(pCover) ); if ( fEsop ) fprintf( pFile, ".type esop\n" ); Min_CoverForEachCube( pCover, pCube ) Min_CubeWrite( pFile, pCube ); fprintf( pFile, ".e\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_CoverCheck( Min_Man_t * p ) { Min_Cube_t * pCube; int i; for ( i = 0; i <= p->nVars; i++ ) Min_CoverForEachCube( p->ppStore[i], pCube ) assert( i == (int)pCube->nLits ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Min_CubeCheck( Min_Cube_t * pCube ) { int i; for ( i = 0; i < (int)pCube->nVars; i++ ) if ( Min_CubeGetVar( pCube, i ) == 0 ) return 0; return 1; } /**Function************************************************************* Synopsis [Converts the cover from the sorted structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Min_Cube_t * Min_CoverCollect( Min_Man_t * p, int nSuppSize ) { Min_Cube_t * pCov = NULL, ** ppTail = &pCov; Min_Cube_t * pCube, * pCube2; int i; for ( i = 0; i <= nSuppSize; i++ ) { Min_CoverForEachCubeSafe( p->ppStore[i], pCube, pCube2 ) { assert( i == (int)pCube->nLits ); *ppTail = pCube; ppTail = &pCube->pNext; assert( pCube->uData[0] ); // not a bubble } } *ppTail = NULL; return pCov; } /**Function************************************************************* Synopsis [Sorts the cover in the increasing number of literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Min_CoverExpand( Min_Man_t * p, Min_Cube_t * pCover ) { Min_Cube_t * pCube, * pCube2; Min_ManClean( p, p->nVars ); Min_CoverForEachCubeSafe( pCover, pCube, pCube2 ) { pCube->pNext = p->ppStore[pCube->nLits]; p->ppStore[pCube->nLits] = pCube; p->nCubes++; } } /**Function************************************************************* Synopsis [Sorts the cover in the increasing number of literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Min_CoverSuppVarNum( Min_Man_t * p, Min_Cube_t * pCover ) { Min_Cube_t * pCube; int i, Counter; if ( pCover == NULL ) return 0; // clean the cube for ( i = 0; i < (int)pCover->nWords; i++ ) p->pTemp->uData[i] = ~((unsigned)0); // add the bit data Min_CoverForEachCube( pCover, pCube ) for ( i = 0; i < (int)pCover->nWords; i++ ) p->pTemp->uData[i] &= pCube->uData[i]; // count the vars Counter = 0; for ( i = 0; i < (int)pCover->nVars; i++ ) Counter += ( Min_CubeGetVar(p->pTemp, i) != 3 ); return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/covTest.c000066400000000000000000000267371300674244400232120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [covTest.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Mapping into network of SOPs/ESOPs.] Synopsis [Testing procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: covTest.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cov.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Min_Cube_t * Abc_NodeDeriveCoverPro( Min_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1 ) { Min_Cube_t * pCover; Min_Cube_t * pCube0, * pCube1, * pCube; if ( pCover0 == NULL || pCover1 == NULL ) return NULL; // clean storage Min_ManClean( p, p->nVars ); // go through the cube pairs Min_CoverForEachCube( pCover0, pCube0 ) Min_CoverForEachCube( pCover1, pCube1 ) { if ( Min_CubesDisjoint( pCube0, pCube1 ) ) continue; pCube = Min_CubesProduct( p, pCube0, pCube1 ); // add the cube to storage Min_SopAddCube( p, pCube ); } Min_SopMinimize( p ); pCover = Min_CoverCollect( p, p->nVars ); assert( p->nCubes == Min_CoverCountCubes(pCover) ); return pCover; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Min_Cube_t * Abc_NodeDeriveCoverSum( Min_Man_t * p, Min_Cube_t * pCover0, Min_Cube_t * pCover1 ) { Min_Cube_t * pCover; Min_Cube_t * pThis, * pCube; if ( pCover0 == NULL || pCover1 == NULL ) return NULL; // clean storage Min_ManClean( p, p->nVars ); // add the cubes to storage Min_CoverForEachCube( pCover0, pThis ) { pCube = Min_CubeDup( p, pThis ); Min_SopAddCube( p, pCube ); } Min_CoverForEachCube( pCover1, pThis ) { pCube = Min_CubeDup( p, pThis ); Min_SopAddCube( p, pCube ); } Min_SopMinimize( p ); pCover = Min_CoverCollect( p, p->nVars ); assert( p->nCubes == Min_CoverCountCubes(pCover) ); return pCover; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeDeriveSops( Min_Man_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vSupp, Vec_Ptr_t * vNodes ) { Min_Cube_t * pCov0[2], * pCov1[2]; Min_Cube_t * pCoverP, * pCoverN; Abc_Obj_t * pObj; int i, nCubes, fCompl0, fCompl1; // set elementary vars Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) { pObj->pCopy = (Abc_Obj_t *)Min_CubeAllocVar( p, i, 0 ); pObj->pNext = (Abc_Obj_t *)Min_CubeAllocVar( p, i, 1 ); } // get the cover for each node in the array Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // get the complements fCompl0 = Abc_ObjFaninC0(pObj); fCompl1 = Abc_ObjFaninC1(pObj); // get the covers pCov0[0] = (Min_Cube_t *)Abc_ObjFanin0(pObj)->pCopy; pCov0[1] = (Min_Cube_t *)Abc_ObjFanin0(pObj)->pNext; pCov1[0] = (Min_Cube_t *)Abc_ObjFanin1(pObj)->pCopy; pCov1[1] = (Min_Cube_t *)Abc_ObjFanin1(pObj)->pNext; // compute the covers pCoverP = Abc_NodeDeriveCoverPro( p, pCov0[ fCompl0], pCov1[ fCompl1] ); pCoverN = Abc_NodeDeriveCoverSum( p, pCov0[!fCompl0], pCov1[!fCompl1] ); // set the covers pObj->pCopy = (Abc_Obj_t *)pCoverP; pObj->pNext = (Abc_Obj_t *)pCoverN; } nCubes = ABC_MIN( Min_CoverCountCubes(pCoverN), Min_CoverCountCubes(pCoverP) ); /* printf( "\n\n" ); Min_CoverWrite( stdout, pCoverP ); printf( "\n\n" ); Min_CoverWrite( stdout, pCoverN ); */ // printf( "\n" ); // Min_CoverWrite( stdout, pCoverP ); // Min_CoverExpand( p, pCoverP ); // Min_SopMinimize( p ); // pCoverP = Min_CoverCollect( p, p->nVars ); // printf( "\n" ); // Min_CoverWrite( stdout, pCoverP ); // nCubes = Min_CoverCountCubes(pCoverP); // clean the copy fields Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = pObj->pNext = NULL; Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) pObj->pCopy = pObj->pNext = NULL; // Min_CoverWriteFile( pCoverP, Abc_ObjName(pRoot), 0 ); // printf( "\n" ); // Min_CoverWrite( stdout, pCoverP ); // printf( "\n" ); // Min_CoverWrite( stdout, pCoverP ); // printf( "\n" ); // Min_CoverWrite( stdout, pCoverN ); return nCubes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTestSop( Abc_Ntk_t * pNtk ) { Min_Man_t * p; Vec_Ptr_t * vSupp, * vNodes; Abc_Obj_t * pObj; int i, nCubes; assert( Abc_NtkIsStrash(pNtk) ); Abc_NtkCleanCopy(pNtk); Abc_NtkCleanNext(pNtk); Abc_NtkForEachCo( pNtk, pObj, i ) { if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) { printf( "%-20s : Trivial.\n", Abc_ObjName(pObj) ); continue; } vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); printf( "%20s : Cone = %5d. Supp = %5d. ", Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize ); // if ( vSupp->nSize <= 128 ) { p = Min_ManAlloc( vSupp->nSize ); nCubes = Abc_NodeDeriveSops( p, pObj, vSupp, vNodes ); printf( "Cubes = %5d. ", nCubes ); Min_ManFree( p ); } printf( "\n" ); Vec_PtrFree( vNodes ); Vec_PtrFree( vSupp ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Min_Cube_t * Abc_NodeDeriveCover( Min_Man_t * p, Min_Cube_t * pCov0, Min_Cube_t * pCov1, int fComp0, int fComp1 ) { Min_Cube_t * pCover0, * pCover1, * pCover; Min_Cube_t * pCube0, * pCube1, * pCube; // complement the first if needed if ( !fComp0 ) pCover0 = pCov0; else if ( pCov0 && pCov0->nLits == 0 ) // topmost one is the tautology cube pCover0 = pCov0->pNext; else pCover0 = p->pOne0, p->pOne0->pNext = pCov0; // complement the second if needed if ( !fComp1 ) pCover1 = pCov1; else if ( pCov1 && pCov1->nLits == 0 ) // topmost one is the tautology cube pCover1 = pCov1->pNext; else pCover1 = p->pOne1, p->pOne1->pNext = pCov1; if ( pCover0 == NULL || pCover1 == NULL ) return NULL; // clean storage Min_ManClean( p, p->nVars ); // go through the cube pairs Min_CoverForEachCube( pCover0, pCube0 ) Min_CoverForEachCube( pCover1, pCube1 ) { if ( Min_CubesDisjoint( pCube0, pCube1 ) ) continue; pCube = Min_CubesProduct( p, pCube0, pCube1 ); // add the cube to storage Min_EsopAddCube( p, pCube ); } if ( p->nCubes > 10 ) { // printf( "(%d,", p->nCubes ); Min_EsopMinimize( p ); // printf( "%d) ", p->nCubes ); } pCover = Min_CoverCollect( p, p->nVars ); assert( p->nCubes == Min_CoverCountCubes(pCover) ); // if ( p->nCubes > 1000 ) // printf( "%d ", p->nCubes ); return pCover; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeDeriveEsops( Min_Man_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vSupp, Vec_Ptr_t * vNodes ) { Min_Cube_t * pCover, * pCube; Abc_Obj_t * pObj; int i; // set elementary vars Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Min_CubeAllocVar( p, i, 0 ); // get the cover for each node in the array Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { pCover = Abc_NodeDeriveCover( p, (Min_Cube_t *)Abc_ObjFanin0(pObj)->pCopy, (Min_Cube_t *)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); pObj->pCopy = (Abc_Obj_t *)pCover; if ( p->nCubes > 3000 ) return -1; } // add complement if needed if ( Abc_ObjFaninC0(pRoot) ) { if ( pCover && pCover->nLits == 0 ) // topmost one is the tautology cube { pCube = pCover; pCover = pCover->pNext; Min_CubeRecycle( p, pCube ); p->nCubes--; } else { pCube = Min_CubeAlloc( p ); pCube->pNext = pCover; p->nCubes++; } } /* Min_CoverExpand( p, pCover ); Min_EsopMinimize( p ); pCover = Min_CoverCollect( p, p->nVars ); */ // clean the copy fields Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = NULL; Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) pObj->pCopy = NULL; // Min_CoverWriteFile( pCover, Abc_ObjName(pRoot), 1 ); // Min_CoverWrite( stdout, pCover ); return p->nCubes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTestEsop( Abc_Ntk_t * pNtk ) { Min_Man_t * p; Vec_Ptr_t * vSupp, * vNodes; Abc_Obj_t * pObj; int i, nCubes; assert( Abc_NtkIsStrash(pNtk) ); Abc_NtkCleanCopy(pNtk); Abc_NtkForEachCo( pNtk, pObj, i ) { if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) { printf( "%-20s : Trivial.\n", Abc_ObjName(pObj) ); continue; } vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); printf( "%20s : Cone = %5d. Supp = %5d. ", Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize ); // if ( vSupp->nSize <= 128 ) { p = Min_ManAlloc( vSupp->nSize ); nCubes = Abc_NodeDeriveEsops( p, pObj, vSupp, vNodes ); printf( "Cubes = %5d. ", nCubes ); Min_ManFree( p ); } printf( "\n" ); Vec_PtrFree( vNodes ); Vec_PtrFree( vSupp ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/cov/module.make000066400000000000000000000002751300674244400235300ustar00rootroot00000000000000SRC += src/map/cov/covBuild.c \ src/map/cov/covCore.c \ src/map/cov/covMan.c \ src/map/cov/covMinEsop.c \ src/map/cov/covMinMan.c \ src/map/cov/covMinSop.c \ src/map/cov/covMinUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/000077500000000000000000000000001300674244400215265ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpga.c000066400000000000000000000215031300674244400226100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpga.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Command file for the FPGA package.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpga.c,v 1.4 2004/10/28 17:36:07 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); // the library file format should be as follows: /* # The area/delay of k-variable LUTs: # k area delay 1 1 1 2 2 2 3 4 3 4 8 4 5 16 5 6 32 6 */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Package initialization procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_Init( Abc_Frame_t * pAbc ) { // set the default library //Fpga_LutLib_t s_LutLib = { "lutlib", 6, 0, {0,1,2,4,8,16,32}, {{0},{1},{2},{3},{4},{5},{6}} }; // Fpga_LutLib_t s_LutLib = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} }; Fpga_LutLib_t s_LutLib = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} }; //Fpga_LutLib_t s_LutLib = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} }; Abc_FrameSetLibLut( Fpga_LutLibDup(&s_LutLib) ); Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut", Fpga_CommandReadLibrary, 0 ); Cmd_CommandAdd( pAbc, "FPGA mapping", "print_lut", Fpga_CommandPrintLibrary, 0 ); } /**Function************************************************************* Synopsis [Package ending procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_End( Abc_Frame_t * pAbc ) { Fpga_LutLibFree( (Fpga_LutLib_t *)Abc_FrameReadLibLut() ); } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; Fpga_LutLib_t * pLib; Abc_Ntk_t * pNet; char * FileName; int fVerbose; int c; pNet = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) ) fprintf( pErr, "Did you mean \"%s\"?", FileName ); fprintf( pErr, "\n" ); return 1; } fclose( pFile ); // set the new network pLib = Fpga_LutLibRead( FileName, fVerbose ); if ( pLib == NULL ) { fprintf( pErr, "Reading LUT library has failed.\n" ); goto usage; } // replace the current library Fpga_LutLibFree( (Fpga_LutLib_t *)Abc_FrameReadLibLut() ); Abc_FrameSetLibLut( pLib ); return 0; usage: fprintf( pErr, "usage: read_lut [-vh]\n"); fprintf( pErr, "\t read the LUT library from the file\n" ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\t \n"); fprintf( pErr, "\t File format for a LUT library:\n"); fprintf( pErr, "\t (the default library is shown)\n"); fprintf( pErr, "\t \n"); fprintf( pErr, "\t # The area/delay of k-variable LUTs:\n"); fprintf( pErr, "\t # k area delay\n"); fprintf( pErr, "\t 1 1 1\n"); fprintf( pErr, "\t 2 2 2\n"); fprintf( pErr, "\t 3 4 3\n"); fprintf( pErr, "\t 4 8 4\n"); fprintf( pErr, "\t 5 16 5\n"); fprintf( pErr, "\t 6 32 6\n"); return 1; /* error exit */ } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNet; int fVerbose; int c; pNet = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind ) { goto usage; } // set the new network Fpga_LutLibPrint( (Fpga_LutLib_t *)Abc_FrameReadLibLut() ); return 0; usage: fprintf( pErr, "usage: print_lut [-vh]\n"); fprintf( pErr, "\t print the current LUT library\n" ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; /* error exit */ } /**Function************************************************************* Synopsis [Sets simple LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_SetSimpleLutLib( int nLutSize ) { Fpga_LutLib_t s_LutLib10= { "lutlib",10, 0, {0,1,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1},{1}} }; Fpga_LutLib_t s_LutLib9 = { "lutlib", 9, 0, {0,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1}} }; Fpga_LutLib_t s_LutLib8 = { "lutlib", 8, 0, {0,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1}} }; Fpga_LutLib_t s_LutLib7 = { "lutlib", 7, 0, {0,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1}} }; Fpga_LutLib_t s_LutLib6 = { "lutlib", 6, 0, {0,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1}} }; Fpga_LutLib_t s_LutLib5 = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} }; Fpga_LutLib_t s_LutLib4 = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} }; Fpga_LutLib_t s_LutLib3 = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} }; Fpga_LutLib_t * pLutLib; assert( nLutSize >= 3 && nLutSize <= 10 ); switch ( nLutSize ) { case 3: pLutLib = &s_LutLib3; break; case 4: pLutLib = &s_LutLib4; break; case 5: pLutLib = &s_LutLib5; break; case 6: pLutLib = &s_LutLib6; break; case 7: pLutLib = &s_LutLib7; break; case 8: pLutLib = &s_LutLib8; break; case 9: pLutLib = &s_LutLib9; break; case 10: pLutLib = &s_LutLib10; break; default: pLutLib = NULL; break; } if ( pLutLib == NULL ) return; Fpga_LutLibFree( (Fpga_LutLib_t *)Abc_FrameReadLibLut() ); Abc_FrameSetLibLut( Fpga_LutLibDup(pLutLib) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpga.h000066400000000000000000000220401300674244400226120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpga.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpga.h,v 1.7 2004/09/30 21:18:09 satrajit Exp $] ***********************************************************************/ #ifndef ABC__map__fpga__fpga_h #define ABC__map__fpga__fpga_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START // the maximum size of LUTs used for mapping #define FPGA_MAX_LUTSIZE 32 //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Fpga_ManStruct_t_ Fpga_Man_t; typedef struct Fpga_NodeStruct_t_ Fpga_Node_t; typedef struct Fpga_NodeVecStruct_t_ Fpga_NodeVec_t; typedef struct Fpga_CutStruct_t_ Fpga_Cut_t; typedef struct Fpga_LutLibStruct_t_ Fpga_LutLib_t; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Fpga_IsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01))) #define Fpga_Regular(p) ((Fpga_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) #define Fpga_Not(p) ((Fpga_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) #define Fpga_NotCond(p,c) ((Fpga_Node_t *)((ABC_PTRUINT_T)(p) ^ (c))) #define Fpga_Ref(p) #define Fpga_Deref(p) #define Fpga_RecursiveDeref(p,c) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== fpgaCreate.c =============================================================*/ extern Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose ); extern Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); extern void Fpga_ManFree( Fpga_Man_t * pMan ); extern void Fpga_ManPrintTimeStats( Fpga_Man_t * p ); extern int Fpga_ManReadInputNum( Fpga_Man_t * p ); extern int Fpga_ManReadOutputNum( Fpga_Man_t * p ); extern Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p ); extern Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ); extern Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ); extern float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ); extern int Fpga_ManReadVerbose( Fpga_Man_t * p ); extern int Fpga_ManReadVarMax( Fpga_Man_t * p ); extern float * Fpga_ManReadLutAreas( Fpga_Man_t * p ); extern Fpga_NodeVec_t* Fpga_ManReadMapping( Fpga_Man_t * p ); extern void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ); extern void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ); extern void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ); extern void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit ); extern void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit ); extern void Fpga_ManSetObeyFanoutLimits( Fpga_Man_t * p, int fObeyFanoutLimits ); extern void Fpga_ManSetNumIterations( Fpga_Man_t * p, int nNumIterations ); extern int Fpga_ManReadFanoutViolations( Fpga_Man_t * p ); extern void Fpga_ManSetFanoutViolations( Fpga_Man_t * p, int nVio ); extern void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ); extern void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ); extern void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ); extern void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching ); extern void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths ); extern void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ); extern void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget ); extern void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ); extern int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ); extern char * Fpga_NodeReadData0( Fpga_Node_t * p ); extern Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ); extern int Fpga_NodeReadRefs( Fpga_Node_t * p ); extern int Fpga_NodeReadNum( Fpga_Node_t * p ); extern int Fpga_NodeReadLevel( Fpga_Node_t * p ); extern Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ); extern Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p ); extern Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p ); extern Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p ); extern void Fpga_NodeSetLevel( Fpga_Node_t * p, Fpga_Node_t * pNode ); extern void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData ); extern void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode ); extern void Fpga_NodeSetArrival( Fpga_Node_t * p, float Time ); extern void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ); extern void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr ); extern void Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching ); extern int Fpga_NodeIsConst( Fpga_Node_t * p ); extern int Fpga_NodeIsVar( Fpga_Node_t * p ); extern int Fpga_NodeIsAnd( Fpga_Node_t * p ); extern int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ); extern int Fpga_CutReadLeavesNum( Fpga_Cut_t * p ); extern Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p ); extern Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); extern Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); extern Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); extern Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeT, Fpga_Node_t * pNodeE ); extern void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew ); extern void Fpga_ManStats( Fpga_Man_t * p ); /*=== fpgaCore.c =============================================================*/ extern int Fpga_Mapping( Fpga_Man_t * p ); /*=== fpgaCut.c ===============================================================*/ extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ); extern void Fpga_CutsCleanSign( Fpga_Man_t * pMan ); extern void Fpga_CutsCleanRoot( Fpga_Man_t * pMan ); /*=== fpgaCutUtils.c =============================================================*/ extern void Fpga_CutCreateFromNode( Fpga_Man_t * p, int iRoot, int * pLeaves, int nLeaves ); extern void Fpga_MappingSetUsedCuts( Fpga_Man_t * p ); /*=== fpgaLib.c =============================================================*/ extern Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p ); extern int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ); extern float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ); extern float * Fpga_LutLibReadLutDelays( Fpga_LutLib_t * p ); extern float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ); extern float Fpga_LutLibReadLutDelay( Fpga_LutLib_t * p, int Size ); /*=== fpgaTruth.c =============================================================*/ extern void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ); extern int Fpga_CutVolume( Fpga_Cut_t * pCut ); /*=== fpgaUtil.c =============================================================*/ extern int Fpga_ManCheckConsistency( Fpga_Man_t * p ); extern void Fpga_ManCleanData0( Fpga_Man_t * pMan ); extern Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode ); /*=== fpga.c =============================================================*/ extern void Fpga_SetSimpleLutLib( int nLutSize ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaCore.c000066400000000000000000000135641300674244400234310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaCore.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Fpga_MappingPostProcess( Fpga_Man_t * p ); extern clock_t s_MappingTime; extern int s_MappingMem; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs technology mapping for the given object graph.] Description [The object graph is stored in the mapping manager. First, all the AND-nodes, which fanout into the POs, are collected in the DFS fashion. Next, three steps are performed: the k-feasible cuts are computed for each node, the truth tables are computed for each cut, and the delay-optimal matches are assigned for each node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_Mapping( Fpga_Man_t * p ) { clock_t clk, clkTotal = clock(); // collect the nodes reachable from POs in the DFS order (including the choices) p->vAnds = Fpga_MappingDfs( p, 1 ); Fpga_ManReportChoices( p ); // recomputes levels Fpga_MappingSetChoiceLevels( p ); // compute the cuts of nodes in the DFS order clk = clock(); Fpga_MappingCuts( p ); p->timeCuts = clock() - clk; // match the truth tables to the supergates clk = clock(); if ( !Fpga_MappingMatches( p, 1 ) ) return 0; p->timeMatch = clock() - clk; // perform area recovery clk = clock(); if ( !Fpga_MappingPostProcess( p ) ) return 0; p->timeRecover = clock() - clk; //ABC_PRT( "Total mapping time", clock() - clkTotal ); s_MappingTime = clock() - clkTotal; s_MappingMem = Fpga_CutCountAll(p) * (sizeof(Fpga_Cut_t) - sizeof(int) * (FPGA_MAX_LEAVES - p->nVarsMax)); // print the AI-graph used for mapping //Fpga_ManShow( p, "test" ); // if ( p->fVerbose ) // Fpga_MappingPrintOutputArrivals( p ); if ( p->fVerbose ) { ABC_PRT( "Total time", clock() - clkTotal ); } return 1; } /**Function************************************************************* Synopsis [Postprocesses the mapped network for area recovery.] Description [This procedure assumes that the mapping is assigned. It iterates the loop, in which the required times are computed and the mapping is updated. It is conceptually similar to the paper: V. Manohararajah, S. D. Brown, Z. G. Vranesic, Heuristics for area minimization in LUT-based FPGA technology mapping. Proc. IWLS '04.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MappingPostProcess( Fpga_Man_t * p ) { int fShowSwitching = 0; int fRecoverAreaFlow = 1; int fRecoverArea = 1; float aAreaTotalCur, aAreaTotalCur2; int Iter; clock_t clk; //if ( p->fVerbose ) // printf( "Best clock period = %5.2f\n", Fpga_TimeComputeArrivalMax(p) ); // compute area, set references, and collect nodes used in the mapping Iter = 1; aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); if ( p->fVerbose ) { printf( "Iteration %dD : Area = %8.1f ", Iter++, aAreaTotalCur ); if ( fShowSwitching ) printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); else printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); ABC_PRT( "Time", p->timeMatch ); } if ( !p->fAreaRecovery ) return 1; if ( fRecoverAreaFlow ) { clk = clock(); // compute the required times and the fanouts Fpga_TimeComputeRequiredGlobal( p, 1 ); // remap topologically Fpga_MappingMatches( p, 0 ); // get the resulting area // aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); aAreaTotalCur = Fpga_MappingAreaTrav( p ); // note that here we do not update the reference counter // for some reason, this works better on benchmarks if ( p->fVerbose ) { printf( "Iteration %dF : Area = %8.1f ", Iter++, aAreaTotalCur ); if ( fShowSwitching ) printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); else printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); ABC_PRT( "Time", clock() - clk ); } } // update reference counters aAreaTotalCur2 = Fpga_MappingSetRefsAndArea( p ); assert( aAreaTotalCur == aAreaTotalCur2 ); if ( fRecoverArea ) { clk = clock(); // compute the required times and the fanouts Fpga_TimeComputeRequiredGlobal( p, 0 ); // remap topologically if ( p->fSwitching ) Fpga_MappingMatchesSwitch( p ); else Fpga_MappingMatchesArea( p ); // get the resulting area aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); if ( p->fVerbose ) { printf( "Iteration %d%s : Area = %8.1f ", Iter++, (p->fSwitching?"S":"A"), aAreaTotalCur ); if ( fShowSwitching ) printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); else printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); ABC_PRT( "Time", clock() - clk ); } } p->fAreaGlo = aAreaTotalCur; return 1; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaCreate.c000066400000000000000000000504651300674244400237450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaCreate.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaCreate.c,v 1.8 2004/09/30 21:18:09 satrajit Exp $] ***********************************************************************/ #include "fpgaInt.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Fpga_TableCreate( Fpga_Man_t * p ); static void Fpga_TableResize( Fpga_Man_t * p ); static Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); // hash key for the structural hash table static inline unsigned Fpga_HashKey2( Fpga_Node_t * p0, Fpga_Node_t * p1, int TableSize ) { return (unsigned)(((ABC_PTRUINT_T)(p0) + (ABC_PTRUINT_T)(p1) * 12582917) % TableSize); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads parameters of the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_ManReadInputNum( Fpga_Man_t * p ) { return p->nInputs; } int Fpga_ManReadOutputNum( Fpga_Man_t * p ) { return p->nOutputs; } Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p ) { return p->pInputs; } Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ) { return p->pOutputs; } Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ) { return p->pConst1; } float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ) { return p->pInputArrivals;} int Fpga_ManReadVerbose( Fpga_Man_t * p ) { return p->fVerbose; } int Fpga_ManReadVarMax( Fpga_Man_t * p ) { return p->pLutLib->LutMax; } float * Fpga_ManReadLutAreas( Fpga_Man_t * p ) { return p->pLutLib->pLutAreas; } Fpga_NodeVec_t* Fpga_ManReadMapping( Fpga_Man_t * p ) { return p->vMapping; } void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ) { p->pInputArrivals = pArrivals; } void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;} void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit ) { p->DelayLimit = DelayLimit; } void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit ) { p->AreaLimit = AreaLimit; } void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; } void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ) { p->nChoices = nChoices; } void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; } void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths ) { p->fLatchPaths = fLatchPaths; } void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ) { p->nLatches = nLatches; } void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget; } void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ) { p->pFileName = pFileName; } /**Function************************************************************* Synopsis [Reads the parameters of the LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ) { return pLib->LutMax; } /**Function************************************************************* Synopsis [Reads parameters of the mapping node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Fpga_NodeReadData0( Fpga_Node_t * p ) { return p->pData0; } Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ) { return p->pLevel; } int Fpga_NodeReadRefs( Fpga_Node_t * p ) { return p->nRefs; } int Fpga_NodeReadNum( Fpga_Node_t * p ) { return p->Num; } int Fpga_NodeReadLevel( Fpga_Node_t * p ) { return Fpga_Regular(p)->Level; } Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ) { return p->pCuts; } Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p ) { return p->pCutBest; } Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p ) { return p->p1; } Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p ) { return p->p2; } void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData ) { p->pData0 = pData; } void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode ) { p->pLevel = pNode; } void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ) { p->pNextE = pNextE; } void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr ) { p->pRepr = pRepr; } void Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching ) { p->Switching = Switching; } /**Function************************************************************* Synopsis [Checks the type of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_NodeIsConst( Fpga_Node_t * p ) { return (Fpga_Regular(p))->Num == -1; } int Fpga_NodeIsVar( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 == NULL && (Fpga_Regular(p))->Num >= 0; } int Fpga_NodeIsAnd( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 != NULL; } int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ) { assert( !Fpga_IsComplement(p1) ); assert( !Fpga_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } /**Function************************************************************* Synopsis [Reads parameters from the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutReadLeavesNum( Fpga_Cut_t * p ) { return p->nLeaves; } Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p ) { return p->ppLeaves; } /**Function************************************************************* Synopsis [Create the mapping manager.] Description [The number of inputs and outputs is assumed to be known is advance. It is much simpler to have them fixed upfront. When it comes to representing the object graph in the form of AIG, the resulting manager is similar to the regular AIG manager, except that it does not use reference counting (and therefore does not have garbage collections). It does have table resizing. The data structure is more flexible to represent additional information needed for mapping.] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose ) { Fpga_Man_t * p; int i; // start the manager p = ABC_ALLOC( Fpga_Man_t, 1 ); memset( p, 0, sizeof(Fpga_Man_t) ); p->pLutLib = (Fpga_LutLib_t *)Abc_FrameReadLibLut(); p->nVarsMax = p->pLutLib->LutMax; p->fVerbose = fVerbose; p->fAreaRecovery = 1; p->fEpsilon = (float)0.001; Fpga_TableCreate( p ); //if ( p->fVerbose ) // printf( "Node = %d (%d) bytes. Cut = %d bytes.\n", sizeof(Fpga_Node_t), FPGA_NUM_BYTES(sizeof(Fpga_Node_t)), sizeof(Fpga_Cut_t) ); p->mmNodes = Extra_MmFixedStart( FPGA_NUM_BYTES(sizeof(Fpga_Node_t)) ); p->mmCuts = Extra_MmFixedStart( sizeof(Fpga_Cut_t) ); assert( p->nVarsMax > 0 ); // Fpga_MappingSetupTruthTables( p->uTruths ); // make sure the constant node will get index -1 p->nNodes = -1; // create the constant node p->pConst1 = Fpga_NodeCreate( p, NULL, NULL ); p->vNodesAll = Fpga_NodeVecAlloc( 1000 ); p->vMapping = Fpga_NodeVecAlloc( 1000 ); // create the PI nodes p->nInputs = nInputs; p->pInputs = ABC_ALLOC( Fpga_Node_t *, nInputs ); for ( i = 0; i < nInputs; i++ ) p->pInputs[i] = Fpga_NodeCreate( p, NULL, NULL ); // create the place for the output nodes p->nOutputs = nOutputs; p->pOutputs = ABC_ALLOC( Fpga_Node_t *, nOutputs ); memset( p->pOutputs, 0, sizeof(Fpga_Node_t *) * nOutputs ); return p; } /**Function************************************************************* Synopsis [Deallocates the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_ManFree( Fpga_Man_t * p ) { // Fpga_ManStats( p ); // int i; // for ( i = 0; i < p->vNodesAll->nSize; i++ ) // Fpga_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts ); // Fpga_NodeVecFree( p->pConst1->vFanouts ); if ( p->vMapping ) Fpga_NodeVecFree( p->vMapping ); if ( p->vAnds ) Fpga_NodeVecFree( p->vAnds ); if ( p->vNodesAll ) Fpga_NodeVecFree( p->vNodesAll ); Extra_MmFixedStop( p->mmNodes ); Extra_MmFixedStop( p->mmCuts ); ABC_FREE( p->ppOutputNames ); ABC_FREE( p->pInputArrivals ); ABC_FREE( p->pInputs ); ABC_FREE( p->pOutputs ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints runtime statistics of the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_ManPrintTimeStats( Fpga_Man_t * p ) { // extern char * pNetName; // extern int TotalLuts; // FILE * pTable; /* pTable = fopen( "stats.txt", "a+" ); fprintf( pTable, "%s ", pNetName ); fprintf( pTable, "%.0f ", p->fRequiredGlo ); // fprintf( pTable, "%.0f ", p->fAreaGlo );//+ (float)nOutputInvs ); fprintf( pTable, "%.0f ", (float)TotalLuts ); fprintf( pTable, "%4.2f\n", (float)(p->timeTotal-p->timeToMap)/(float)(CLOCKS_PER_SEC) ); fclose( pTable ); */ // printf( "N-canonical = %d. Matchings = %d. ", p->nCanons, p->nMatches ); // printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices ); ABC_PRT( "ToMap", p->timeToMap ); ABC_PRT( "Cuts ", p->timeCuts ); ABC_PRT( "Match", p->timeMatch ); ABC_PRT( "Area ", p->timeRecover ); ABC_PRT( "ToNet", p->timeToNet ); ABC_PRT( "TOTAL", p->timeTotal ); if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); } if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); } } /**Function************************************************************* Synopsis [Creates a new node.] Description [This procedure should be called to create the constant node and the PI nodes first.] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) { Fpga_Node_t * pNode; // create the node pNode = (Fpga_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes ); memset( pNode, 0, sizeof(Fpga_Node_t) ); // set very large required time pNode->tRequired = FPGA_FLOAT_LARGE; pNode->aEstFanouts = -1; pNode->p1 = p1; pNode->p2 = p2; // set the number of this node pNode->Num = p->nNodes++; // place to store the fanouts // pNode->vFanouts = Fpga_NodeVecAlloc( 5 ); // store this node in the internal array if ( pNode->Num >= 0 ) Fpga_NodeVecPush( p->vNodesAll, pNode ); else pNode->fInv = 1; // set the level of this node if ( p1 ) { #ifdef FPGA_ALLOCATE_FANOUT // create the fanout info Fpga_NodeAddFaninFanout( Fpga_Regular(p1), pNode ); Fpga_NodeAddFaninFanout( Fpga_Regular(p2), pNode ); #endif // compute the level pNode->Level = 1 + FPGA_MAX(Fpga_Regular(p1)->Level, Fpga_Regular(p2)->Level); pNode->fInv = Fpga_NodeIsSimComplement(p1) & Fpga_NodeIsSimComplement(p2); } // reference the inputs if ( p1 ) Fpga_NodeRef(p1); if ( p2 ) Fpga_NodeRef(p2); return pNode; } /**Function************************************************************* Synopsis [Create the unique table of AND gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_TableCreate( Fpga_Man_t * pMan ) { assert( pMan->pBins == NULL ); pMan->nBins = Abc_PrimeCudd(50000); pMan->pBins = ABC_ALLOC( Fpga_Node_t *, pMan->nBins ); memset( pMan->pBins, 0, sizeof(Fpga_Node_t *) * pMan->nBins ); pMan->nNodes = 0; } /**Function************************************************************* Synopsis [Looks up the AND2 node in the unique table.] Description [This procedure implements one-level hashing. All the nodes are hashed by their children. If the node with the same children was already created, it is returned by the call to this procedure. If it does not exist, this procedure creates a new node with these children. ] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * pMan, Fpga_Node_t * p1, Fpga_Node_t * p2 ) { Fpga_Node_t * pEnt; unsigned Key; if ( p1 == p2 ) return p1; if ( p1 == Fpga_Not(p2) ) return Fpga_Not(pMan->pConst1); if ( Fpga_NodeIsConst(p1) ) { if ( p1 == pMan->pConst1 ) return p2; return Fpga_Not(pMan->pConst1); } if ( Fpga_NodeIsConst(p2) ) { if ( p2 == pMan->pConst1 ) return p1; return Fpga_Not(pMan->pConst1); } if ( Fpga_Regular(p1)->Num > Fpga_Regular(p2)->Num ) pEnt = p1, p1 = p2, p2 = pEnt; Key = Fpga_HashKey2( p1, p2, pMan->nBins ); for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext ) if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) return pEnt; // resize the table if ( pMan->nNodes >= 2 * pMan->nBins ) { Fpga_TableResize( pMan ); Key = Fpga_HashKey2( p1, p2, pMan->nBins ); } // create the new node pEnt = Fpga_NodeCreate( pMan, p1, p2 ); // add the node to the corresponding linked list in the table pEnt->pNext = pMan->pBins[Key]; pMan->pBins[Key] = pEnt; return pEnt; } /**Function************************************************************* Synopsis [Resizes the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_TableResize( Fpga_Man_t * pMan ) { Fpga_Node_t ** pBinsNew; Fpga_Node_t * pEnt, * pEnt2; int nBinsNew, Counter, i; clock_t clk; unsigned Key; clk = clock(); // get the new table size nBinsNew = Abc_PrimeCudd(2 * pMan->nBins); // allocate a new array pBinsNew = ABC_ALLOC( Fpga_Node_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Fpga_Node_t *) * nBinsNew ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < pMan->nBins; i++ ) for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) { Key = Fpga_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); pEnt->pNext = pBinsNew[Key]; pBinsNew[Key] = pEnt; Counter++; } assert( Counter == pMan->nNodes - pMan->nInputs ); if ( pMan->fVerbose ) { // printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew ); // ABC_PRT( "Time", clock() - clk ); } // replace the table and the parameters ABC_FREE( pMan->pBins ); pMan->pBins = pBinsNew; pMan->nBins = nBinsNew; } /**Function************************************************************* Synopsis [Elementary AND operation on the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) { Fpga_Node_t * pNode; pNode = Fpga_TableLookup( p, p1, p2 ); return pNode; } /**Function************************************************************* Synopsis [Elementary OR operation on the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) { Fpga_Node_t * pNode; pNode = Fpga_Not( Fpga_TableLookup( p, Fpga_Not(p1), Fpga_Not(p2) ) ); return pNode; } /**Function************************************************************* Synopsis [Elementary EXOR operation on the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) { return Fpga_NodeMux( p, p1, Fpga_Not(p2), p2 ); } /**Function************************************************************* Synopsis [Elementary MUX operation on the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pC, Fpga_Node_t * pT, Fpga_Node_t * pE ) { Fpga_Node_t * pAnd1, * pAnd2, * pRes; pAnd1 = Fpga_TableLookup( p, pC, pT ); pAnd2 = Fpga_TableLookup( p, Fpga_Not(pC), pE ); pRes = Fpga_NodeOr( p, pAnd1, pAnd2 ); return pRes; } /**Function************************************************************* Synopsis [Sets the node to be equivalent to the given one.] Description [This procedure is a work-around for the equivalence check. Does not verify the equivalence. Use at the user's risk.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew ) { pNodeNew->pNextE = pNodeOld->pNextE; pNodeOld->pNextE = pNodeNew; pNodeNew->pRepr = pNodeOld; } /**Function************************************************************* Synopsis [Prints some interesting stats.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_ManStats( Fpga_Man_t * p ) { FILE * pTable; pTable = fopen( "stats.txt", "a+" ); fprintf( pTable, "%s ", p->pFileName ); fprintf( pTable, "%4d ", p->nInputs - p->nLatches ); fprintf( pTable, "%4d ", p->nOutputs - p->nLatches ); fprintf( pTable, "%4d ", p->nLatches ); fprintf( pTable, "%7d ", p->vAnds->nSize ); fprintf( pTable, "%7d ", Fpga_CutCountAll(p) ); fprintf( pTable, "%2d\n", (int)p->fRequiredGlo ); fclose( pTable ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaCut.c000066400000000000000000001123531300674244400232700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaCut.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaCut.c,v 1.3 2004/07/06 04:55:57 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Fpga_CutTableStrutct_t Fpga_CutTable_t; struct Fpga_CutTableStrutct_t { Fpga_Cut_t ** pBins; // the table used for linear probing int nBins; // the size of the table int * pCuts; // the array of cuts currently stored int nCuts; // the number of cuts currently stored Fpga_Cut_t ** pArray; // the temporary array of cuts Fpga_Cut_t ** pCuts1; // the temporary array of cuts Fpga_Cut_t ** pCuts2; // the temporary array of cuts }; // the largest number of cuts considered //#define FPGA_CUTS_MAX_COMPUTE 500 #define FPGA_CUTS_MAX_COMPUTE 2000 // the largest number of cuts used //#define FPGA_CUTS_MAX_USE 200 #define FPGA_CUTS_MAX_USE 1000 // primes used to compute the hash key static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; static int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; #define FPGA_COUNT_ONES(u) (bit_count[(u)&255]+bit_count[((u)>>8)&255]+bit_count[((u)>>16)&255]+bit_count[(u)>>24]) static Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode ); static void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ); static Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ); static int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax ); static Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 ); static int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes ); extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ); extern int Fpga_CutCountAll( Fpga_Man_t * pMan ); static void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ); static void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ); static void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot ); static Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ); static void Fpga_CutTableStop( Fpga_CutTable_t * p ); static unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes ); static int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ); static Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ); static void Fpga_CutTableRestart( Fpga_CutTable_t * p ); static int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 ); static Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList ); static int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList ); static Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ); // iterator through all the cuts of the list #define Fpga_ListForEachCut( pList, pCut ) \ for ( pCut = pList; \ pCut; \ pCut = pCut->pNext ) #define Fpga_ListForEachCutSafe( pList, pCut, pCut2 ) \ for ( pCut = pList, \ pCut2 = pCut? pCut->pNext: NULL; \ pCut; \ pCut = pCut2, \ pCut2 = pCut? pCut->pNext: NULL ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the cuts for each node in the object graph.] Description [The cuts are computed in one sweep over the mapping graph. First, the elementary cuts, which include the node itself, are assigned to the PI nodes. The internal nodes are considered in the DFS order. Each node is two-input AND-gate. So to compute the cuts at a node, we need to merge the sets of cuts of its two predecessors. The merged set contains only unique cuts with the number of inputs equal to k or less. Finally, the elementary cut, composed of the node itself, is added to the set of cuts for the node. This procedure is pretty fast for 5-feasible cuts, but it dramatically slows down on some "dense" networks when computing 6-feasible cuts. The problem is that there are too many cuts in this case. We should think how to heuristically trim the number of cuts in such cases, to have reasonable runtime.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingCuts( Fpga_Man_t * p ) { ProgressBar * pProgress; Fpga_CutTable_t * pTable; Fpga_Node_t * pNode; int nCuts, nNodes, i; clock_t clk = clock(); // set the elementary cuts for the PI variables assert( p->nVarsMax > 1 && p->nVarsMax < 11 ); Fpga_MappingCreatePiCuts( p ); // compute the cuts for the internal nodes nNodes = p->vAnds->nSize; pProgress = Extra_ProgressBarStart( stdout, nNodes ); pTable = Fpga_CutTableStart( p ); for ( i = 0; i < nNodes; i++ ) { Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." ); pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; Fpga_CutCompute( p, pTable, pNode ); } Extra_ProgressBarStop( pProgress ); Fpga_CutTableStop( pTable ); // report the stats if ( p->fVerbose ) { nCuts = Fpga_CutCountAll(p); printf( "Nodes = %6d. Total %d-cuts = %d. Cuts per node = %.1f. ", p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); ABC_PRT( "Time", clock() - clk ); } // print the cuts for the first primary output // Fpga_CutListPrint( p, Fpga_Regular(p->pOutputs[0]) ); } /**Function************************************************************* Synopsis [Performs technology mapping for variable-size-LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ) { Fpga_Cut_t * pCut; int i; // set the elementary cuts for the PI variables for ( i = 0; i < p->nInputs; i++ ) { pCut = Fpga_CutAlloc( p ); pCut->nLeaves = 1; pCut->ppLeaves[0] = p->pInputs[i]; pCut->uSign = (1 << (i%31)); p->pInputs[i]->pCuts = pCut; p->pInputs[i]->pCutBest = pCut; // set the input arrival times // p->pInputs[i]->pCut[1]->tArrival = p->pInputArrivals[i]; } } /**Function************************************************************* Synopsis [Computes the cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode ) { Fpga_Node_t * pTemp; Fpga_Cut_t * pList, * pList1, * pList2; Fpga_Cut_t * pCut; int fTree = 0; int fPivot1 = fTree && (Fpga_NodeReadRef(pNode->p1)>2); int fPivot2 = fTree && (Fpga_NodeReadRef(pNode->p2)>2); // if the cuts are computed return them if ( pNode->pCuts ) return pNode->pCuts; // compute the cuts for the children pList1 = Fpga_Regular(pNode->p1)->pCuts; pList2 = Fpga_Regular(pNode->p2)->pCuts; // merge the lists pList = Fpga_CutMergeLists( p, pTable, pList1, pList2, Fpga_IsComplement(pNode->p1), Fpga_IsComplement(pNode->p2), fPivot1, fPivot2 ); // if there are functionally equivalent nodes, union them with this list assert( pList ); // only add to the list of cuts if the node is a representative one if ( pNode->pRepr == NULL ) { for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) { assert( pTemp->pCuts ); pList = Fpga_CutUnionLists( pList, pTemp->pCuts ); assert( pTemp->pCuts ); pList = Fpga_CutSortCuts( p, pTable, pList ); } } // add the new cut pCut = Fpga_CutAlloc( p ); pCut->nLeaves = 1; pCut->ppLeaves[0] = pNode; pCut->uSign = (1 << (pNode->Num%31)); pCut->fLevel = (float)pCut->ppLeaves[0]->Level; // append (it is important that the elementary cut is appended first) pCut->pNext = pList; // set at the node pNode->pCuts = pCut; // remove the dominated cuts // Fpga_CutFilter( p, pNode ); // set the phase correctly if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) ) { Fpga_ListForEachCut( pNode->pCuts, pCut ) pCut->Phase = 1; } /* { Fpga_Cut_t * pPrev; int i, Counter = 0; for ( pCut = pNode->pCuts->pNext, pPrev = pNode->pCuts; pCut; pCut = pCut->pNext ) { for ( i = 0; i < pCut->nLeaves; i++ ) if ( pCut->ppLeaves[i]->Level >= pNode->Level ) break; if ( i != pCut->nLeaves ) pPrev->pNext = pCut->pNext; else pPrev = pCut; } } { int i, Counter = 0;; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) for ( i = 0; i < pCut->nLeaves; i++ ) Counter += (pCut->ppLeaves[i]->Level >= pNode->Level); if ( Counter ) printf( " %d", Counter ); } */ return pCut; } /**Function************************************************************* Synopsis [Filter the cuts using dominance.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ) { Fpga_Cut_t * pTemp, * pPrev, * pCut, * pCut2; int i, k, Counter; Counter = 0; pPrev = pNode->pCuts; Fpga_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 ) { // go through all the previous cuts up to pCut for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext ) { // check if every node in pTemp is contained in pCut for ( i = 0; i < pTemp->nLeaves; i++ ) { for ( k = 0; k < pCut->nLeaves; k++ ) if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] ) break; if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut break; } if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut { Counter++; break; } } if ( pTemp != pCut ) // pTemp contain pCut { pPrev->pNext = pCut->pNext; // skip pCut // recycle pCut Fpga_CutFree( p, pCut ); } else pPrev = pCut; } // printf( "Dominated = %3d. \n", Counter ); } /**Function************************************************************* Synopsis [Merges two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ) { Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES]; Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL }; Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; int nNodes, Counter, i; Fpga_Cut_t ** ppArray1, ** ppArray2, ** ppArray3; int nCuts1, nCuts2, nCuts3, k, fComp3; ppArray1 = pTable->pCuts1; ppArray2 = pTable->pCuts2; nCuts1 = Fpga_CutList2Array( ppArray1, pList1 ); nCuts2 = Fpga_CutList2Array( ppArray2, pList2 ); if ( fPivot1 ) nCuts1 = 1; if ( fPivot2 ) nCuts2 = 1; // swap the lists based on their length if ( nCuts1 > nCuts2 ) { ppArray3 = ppArray1; ppArray1 = ppArray2; ppArray2 = ppArray3; nCuts3 = nCuts1; nCuts1 = nCuts2; nCuts2 = nCuts3; fComp3 = fComp1; fComp1 = fComp2; fComp2 = fComp3; } // pList1 is shorter or equal length compared to pList2 // prepare the manager for the cut computation Fpga_CutTableRestart( pTable ); // go through the cut pairs Counter = 0; // for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) // for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) for ( i = 0; i < nCuts1; i++ ) { for ( k = 0; k <= i; k++ ) { pTemp1 = ppArray1[i]; pTemp2 = ppArray2[k]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; } // check if k-feasible cut exists nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); // create the signature pCut->uSign = pTemp1->uSign | pTemp2->uSign; // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == FPGA_CUTS_MAX_COMPUTE ) goto QUITS; } for ( k = 0; k < i; k++ ) { pTemp1 = ppArray1[k]; pTemp2 = ppArray2[i]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; } // check if k-feasible cut exists nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); // create the signature pCut->uSign = pTemp1->uSign | pTemp2->uSign; // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == FPGA_CUTS_MAX_COMPUTE ) goto QUITS; } } // consider the rest of them for ( i = nCuts1; i < nCuts2; i++ ) for ( k = 0; k < nCuts1; k++ ) { pTemp1 = ppArray1[k]; pTemp2 = ppArray2[i]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; if ( pTemp1->ppLeaves[2] != pTemp2->ppLeaves[2] ) continue; } // check if k-feasible cut exists nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); // create the signature pCut->uSign = pTemp1->uSign | pTemp2->uSign; // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == FPGA_CUTS_MAX_COMPUTE ) goto QUITS; } QUITS : // combine all the lists into one pListNew = NULL; ppListNew = &pListNew; for ( i = 1; i <= p->nVarsMax; i++ ) { if ( pLists[i] == NULL ) continue; // find the last entry for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; pPrev = pCut, pCut = pCut->pNext ); // connect these lists *ppListNew = pLists[i]; ppListNew = &pPrev->pNext; } *ppListNew = NULL; // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE pListNew = Fpga_CutSortCuts( p, pTable, pListNew ); return pListNew; } /**Function************************************************************* Synopsis [Merges two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutMergeLists2( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ) { Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES]; Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL }; Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; int nNodes, Counter, i; // prepare the manager for the cut computation Fpga_CutTableRestart( pTable ); // go through the cut pairs Counter = 0; for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) { // check if k-feasible cut exists nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == FPGA_CUTS_MAX_COMPUTE ) goto QUITS; } QUITS : // combine all the lists into one pListNew = NULL; ppListNew = &pListNew; for ( i = 1; i <= p->nVarsMax; i++ ) { if ( pLists[i] == NULL ) continue; // find the last entry for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; pPrev = pCut, pCut = pCut->pNext ); // connect these lists *ppListNew = pLists[i]; ppListNew = &pPrev->pNext; } *ppListNew = NULL; // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE pListNew = Fpga_CutSortCuts( p, pTable, pListNew ); return pListNew; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [Returns the number of nodes in the resulting cut, or 0 if the cut is infeasible. Returns the resulting nodes in the array ppNodes[].] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax ) { Fpga_Node_t * pNodeTemp; int nTotal, i, k, min, Counter; unsigned uSign; // use quick prefiltering uSign = pCut1->uSign | pCut2->uSign; Counter = FPGA_COUNT_ONES(uSign); if ( Counter > nNodesMax ) return 0; /* // check the special case when at least of the cuts is the largest if ( pCut1->nLeaves == nNodesMax ) { if ( pCut2->nLeaves == nNodesMax ) { // return 0 if the cuts are different for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] ) return 0; // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut1->ppLeaves[i]; return nNodesMax; } else if ( pCut2->nLeaves == nNodesMax - 1 ) { // return 0 if the cuts are different fMismatch = 0; for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] ) { if ( fMismatch == 1 ) return 0; fMismatch = 1; } // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut1->ppLeaves[i]; return nNodesMax; } } else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax ) { // return 0 if the cuts are different fMismatch = 0; for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] ) { if ( fMismatch == 1 ) return 0; fMismatch = 1; } // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut2->ppLeaves[i]; return nNodesMax; } */ // count the number of unique entries in pCut2 nTotal = pCut1->nLeaves; for ( i = 0; i < pCut2->nLeaves; i++ ) { // try to find this entry among the leaves of pCut1 for ( k = 0; k < pCut1->nLeaves; k++ ) if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] ) break; if ( k < pCut1->nLeaves ) // found continue; // we found a new entry to add if ( nTotal == nNodesMax ) return 0; ppNodes[nTotal++] = pCut2->ppLeaves[i]; } // we know that the feasible cut exists // add the starting entries for ( k = 0; k < pCut1->nLeaves; k++ ) ppNodes[k] = pCut1->ppLeaves[k]; // selection-sort the entries for ( i = 0; i < nTotal - 1; i++ ) { min = i; for ( k = i+1; k < nTotal; k++ ) // if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!) if ( ppNodes[k]->Num < ppNodes[min]->Num ) min = k; pNodeTemp = ppNodes[i]; ppNodes[i] = ppNodes[min]; ppNodes[min] = pNodeTemp; } return nTotal; } /**Function************************************************************* Synopsis [Computes the union of the two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 ) { Fpga_Cut_t * pTemp, * pRoot; // find the last cut in the first list pRoot = pList1; Fpga_ListForEachCut( pList1, pTemp ) pRoot = pTemp; // attach the non-trival part of the second cut to the end of the first assert( pRoot->pNext == NULL ); pRoot->pNext = pList2->pNext; pList2->pNext = NULL; return pList1; } /**Function************************************************************* Synopsis [Checks whether the given cut belongs to the list.] Description [This procedure takes most of the runtime in the cut computation.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes ) { Fpga_Cut_t * pTemp; int i; for ( pTemp = pList; pTemp; pTemp = pTemp->pNext ) { for ( i = 0; i < nNodes; i++ ) if ( pTemp->ppLeaves[i] != ppNodes[i] ) break; if ( i == nNodes ) return 1; } return 0; } /**Function************************************************************* Synopsis [Counts all the cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutCountAll( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode; Fpga_Cut_t * pCut; int i, nCuts; // go through all the nodes in the unique table of the manager nCuts = 0; for ( i = 0; i < pMan->nBins; i++ ) for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) if ( pCut->nLeaves > 1 ) // skip the elementary cuts { // Fpga_CutVolume( pCut ); nCuts++; } return nCuts; } /**Function************************************************************* Synopsis [Clean the signatures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutsCleanSign( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode; Fpga_Cut_t * pCut; int i; for ( i = 0; i < pMan->nBins; i++ ) for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) pCut->uSign = 0; } /**Function************************************************************* Synopsis [Clean the signatures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutsCleanRoot( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode; Fpga_Cut_t * pCut; int i; for ( i = 0; i < pMan->nBins; i++ ) for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) pCut->pRoot = NULL; } /**Function************************************************************* Synopsis [Prints the cuts in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ) { Fpga_Cut_t * pTemp; int Counter; for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) { printf( "%2d : ", Counter + 1 ); Fpga_CutPrint_( pMan, pTemp, pRoot ); } } /**Function************************************************************* Synopsis [Prints the cuts in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ) { Fpga_Cut_t * pTemp; int Counter; for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) { printf( "%2d : ", Counter + 1 ); Fpga_CutPrint_( pMan, pTemp, pRoot ); } } /**Function************************************************************* Synopsis [Prints the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot ) { int i; printf( "(%3d) {", pRoot->Num ); for ( i = 0; i < pMan->nVarsMax; i++ ) if ( pCut->ppLeaves[i] ) printf( " %3d", pCut->ppLeaves[i]->Num ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Starts the hash table to canonicize cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ) { Fpga_CutTable_t * p; // allocate the table p = ABC_ALLOC( Fpga_CutTable_t, 1 ); memset( p, 0, sizeof(Fpga_CutTable_t) ); p->nBins = Abc_PrimeCudd( 10 * FPGA_CUTS_MAX_COMPUTE ); p->pBins = ABC_ALLOC( Fpga_Cut_t *, p->nBins ); memset( p->pBins, 0, sizeof(Fpga_Cut_t *) * p->nBins ); p->pCuts = ABC_ALLOC( int, 2 * FPGA_CUTS_MAX_COMPUTE ); p->pArray = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); p->pCuts1 = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); p->pCuts2 = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); return p; } /**Function************************************************************* Synopsis [Stops the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutTableStop( Fpga_CutTable_t * p ) { ABC_FREE( p->pCuts1 ); ABC_FREE( p->pCuts2 ); ABC_FREE( p->pArray ); ABC_FREE( p->pBins ); ABC_FREE( p->pCuts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Computes the hash value of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes ) { unsigned uRes; int i; uRes = 0; for ( i = 0; i < nNodes; i++ ) uRes += s_HashPrimes[i] * ppNodes[i]->Num; return uRes; } /**Function************************************************************* Synopsis [Looks up the table for the available cut.] Description [Returns -1 if the same cut is found. Returns the index of the cell where the cut should be added, if it does not exist.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ) { Fpga_Cut_t * pCut; unsigned Key; int b, i; Key = Fpga_CutTableHash(ppNodes, nNodes) % p->nBins; for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins ) { pCut = p->pBins[b]; if ( pCut->nLeaves != nNodes ) continue; for ( i = 0; i < nNodes; i++ ) if ( pCut->ppLeaves[i] != ppNodes[i] ) break; if ( i == nNodes ) return -1; } return b; } /**Function************************************************************* Synopsis [Starts the hash table to canonicize cuts.] Description [Considers addition of the cut to the hash table.] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ) { Fpga_Cut_t * pCut; int Place, i; // check the cut Place = Fpga_CutTableLookup( p, ppNodes, nNodes ); if ( Place == -1 ) return NULL; assert( nNodes > 0 ); // create the new cut pCut = Fpga_CutAlloc( pMan ); pCut->nLeaves = nNodes; pCut->fLevel = 0.0; for ( i = 0; i < nNodes; i++ ) { pCut->ppLeaves[i] = ppNodes[i]; pCut->fLevel += ppNodes[i]->Level; } pCut->fLevel /= nNodes; // add the cut to the table assert( p->pBins[Place] == NULL ); p->pBins[Place] = pCut; // add the cut to the new list p->pCuts[ p->nCuts++ ] = Place; return pCut; } /**Function************************************************************* Synopsis [Prepares the table to be used with other cuts.] Description [Restarts the table by cleaning the info about cuts stored when the previous node was considered.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutTableRestart( Fpga_CutTable_t * p ) { int i; for ( i = 0; i < p->nCuts; i++ ) { assert( p->pBins[ p->pCuts[i] ] ); p->pBins[ p->pCuts[i] ] = NULL; } p->nCuts = 0; } /**Function************************************************************* Synopsis [Compares the cuts by the number of leaves and then by delay.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 ) { if ( (*pC1)->nLeaves < (*pC2)->nLeaves ) return -1; if ( (*pC1)->nLeaves > (*pC2)->nLeaves ) return 1; /* if ( (*pC1)->fLevel > (*pC2)->fLevel ) return -1; if ( (*pC1)->fLevel < (*pC2)->fLevel ) return 1; */ return 0; } /**Function************************************************************* Synopsis [Sorts the cuts by average arrival time.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList ) { Fpga_Cut_t * pListNew; int nCuts, i; // move the cuts from the list into the array nCuts = Fpga_CutList2Array( p->pCuts1, pList ); assert( nCuts <= FPGA_CUTS_MAX_COMPUTE ); // sort the cuts qsort( (void *)p->pCuts1, nCuts, sizeof(void *), (int (*)(const void *, const void *)) Fpga_CutSortCutsCompare ); // move them back into the list if ( nCuts > FPGA_CUTS_MAX_USE - 1 ) { // printf( "*" ); // free the remaining cuts for ( i = FPGA_CUTS_MAX_USE - 1; i < nCuts; i++ ) Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] ); // update the number of cuts nCuts = FPGA_CUTS_MAX_USE - 1; } pListNew = Fpga_CutArray2List( p->pCuts1, nCuts ); return pListNew; } /**Function************************************************************* Synopsis [Moves the nodes from the list into the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList ) { int i; for ( i = 0; pList; pList = pList->pNext, i++ ) pArray[i] = pList; return i; } /**Function************************************************************* Synopsis [Moves the nodes from the array into the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ) { Fpga_Cut_t * pListNew, ** ppListNew; int i; pListNew = NULL; ppListNew = &pListNew; for ( i = 0; i < nCuts; i++ ) { // connect these lists *ppListNew = pArray[i]; ppListNew = &pArray[i]->pNext; //printf( " %d(%.2f)", pArray[i]->nLeaves, pArray[i]->fLevel ); } //printf( "\n" ); *ppListNew = NULL; return pListNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaCutUtils.c000066400000000000000000000314341300674244400243110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaCutUtils.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ) { Fpga_Cut_t * pCut; pCut = (Fpga_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts ); memset( pCut, 0, sizeof(Fpga_Cut_t) ); return pCut; } /**Function************************************************************* Synopsis [Duplicates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld ) { Fpga_Cut_t * pCutNew; int i; pCutNew = Fpga_CutAlloc( p ); pCutNew->pRoot = pCutOld->pRoot; pCutNew->nLeaves = pCutOld->nLeaves; for ( i = 0; i < pCutOld->nLeaves; i++ ) pCutNew->ppLeaves[i] = pCutOld->ppLeaves[i]; return pCutNew; } /**Function************************************************************* Synopsis [Deallocates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut ) { if ( pCut ) Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut ) { int i; printf( "CUT: Delay = %4.2f. Area = %4.2f. Nodes = %d -> {", pCut->tArrival, pCut->aFlow, pRoot->Num ); for ( i = 0; i < pCut->nLeaves; i++ ) printf( " %d", pCut->ppLeaves[i]->Num ); printf( " } \n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode ) { Fpga_Cut_t * pCut; pCut = Fpga_CutAlloc( p ); pCut->pRoot = pNode; pCut->nLeaves = 1; pCut->ppLeaves[0] = pNode; pCut->uSign = FPGA_SEQ_SIGN(pCut->ppLeaves[0]); return pCut; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut ) { return p->pLutLib->pLutAreas[(int)pCut->nLeaves]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets ) { Fpga_Cut_t * pPrev = NULL; // Suppress "might be used uninitialized" Fpga_Cut_t * pTemp; if ( pSetAll == NULL ) return pSets; if ( pSets == NULL ) return pSetAll; // find the last one for ( pTemp = pSets; pTemp; pTemp = pTemp->pNext ) pPrev = pTemp; // append all the end of the current set assert( pPrev->pNext == NULL ); pPrev->pNext = pSetAll; return pSets; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave ) { Fpga_Cut_t * pNext, * pTemp; for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; pTemp; pTemp = pNext, pNext = pNext? pNext->pNext : NULL ) if ( pTemp != pSave ) Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutListCount( Fpga_Cut_t * pSets ) { Fpga_Cut_t * pTemp; int i; for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ ); return i; } #if 0 /**function************************************************************* synopsis [Removes the fanouts of the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) { Fpga_NodeVec_t * vFanouts; int i, k; for ( i = 0; i < pCut->nLeaves; i++ ) { vFanouts = pCut->ppLeaves[i]->vFanouts; for ( k = 0; k < vFanouts->nSize; k++ ) if ( vFanouts->pArray[k] == pNode ) break; assert( k != vFanouts->nSize ); for ( k++; k < vFanouts->nSize; k++ ) vFanouts->pArray[k-1] = vFanouts->pArray[k]; vFanouts->nSize--; } } /**function************************************************************* synopsis [Removes the fanouts of the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) { int i; for ( i = 0; i < pCut->nLeaves; i++ ) Fpga_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode ); } #endif /**Function************************************************************* Synopsis [Computes the arrival time and the area flow of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { Fpga_Cut_t * pFaninCut; int i; pCut->tArrival = -FPGA_FLOAT_LARGE; pCut->aFlow = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves]; for ( i = 0; i < pCut->nLeaves; i++ ) { pFaninCut = pCut->ppLeaves[i]->pCutBest; if ( pCut->tArrival < pFaninCut->tArrival ) pCut->tArrival = pFaninCut->tArrival; // if the fanout count is not set, assume it to be 1 if ( pCut->ppLeaves[i]->nRefs == 0 ) pCut->aFlow += pFaninCut->aFlow; else // pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->nRefs; pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->aEstFanouts; } // use the first pin to compute the delay of the LUT // (this mapper does not support the variable pin delay model) pCut->tArrival += pMan->pLutLib->pLutDelays[(int)pCut->nLeaves][0]; } /**function************************************************************* synopsis [Computes the area flow of the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { Fpga_Cut_t * pCutFanin; int i; pCut->aFlow = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves]; for ( i = 0; i < pCut->nLeaves; i++ ) { // get the cut implementing this phase of the fanin pCutFanin = pCut->ppLeaves[i]->pCutBest; assert( pCutFanin ); pCut->aFlow += pCutFanin->aFlow / pCut->ppLeaves[i]->nRefs; } return pCut->aFlow; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { float aResult, aResult2; if ( pCut->nLeaves == 1 ) return 0; aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); return aResult; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { float aResult, aResult2; if ( pCut->nLeaves == 1 ) return 0; aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); return aResult; } /**function************************************************************* synopsis [References the cut.] description [This procedure is similar to the procedure NodeReclaim.] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) { Fpga_Node_t * pNodeChild; float aArea; int i; // deref the fanouts // if ( fFanouts ) // Fpga_CutInsertFanouts( pMan, pNode, pCut ); // start the area of this cut aArea = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves]; // go through the children for ( i = 0; i < pCut->nLeaves; i++ ) { pNodeChild = pCut->ppLeaves[i]; assert( pNodeChild->nRefs >= 0 ); if ( pNodeChild->nRefs++ > 0 ) continue; if ( !Fpga_NodeIsAnd(pNodeChild) ) continue; aArea += Fpga_CutRef( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); } return aArea; } /**function************************************************************* synopsis [Dereferences the cut.] description [This procedure is similar to the procedure NodeRecusiveDeref.] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) { Fpga_Node_t * pNodeChild; float aArea; int i; // deref the fanouts // if ( fFanouts ) // Fpga_CutRemoveFanouts( pMan, pNode, pCut ); // start the area of this cut aArea = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves]; // go through the children for ( i = 0; i < pCut->nLeaves; i++ ) { pNodeChild = pCut->ppLeaves[i]; assert( pNodeChild->nRefs > 0 ); if ( --pNodeChild->nRefs > 0 ) continue; if ( !Fpga_NodeIsAnd(pNodeChild) ) continue; aArea += Fpga_CutDeref( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); } return aArea; } /**Function************************************************************* Synopsis [Sets the used cuts to be the currently selected ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingSetUsedCuts( Fpga_Man_t * pMan ) { int i; for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) if ( pMan->vNodesAll->pArray[i]->pCutOld ) { pMan->vNodesAll->pArray[i]->pCutBest = pMan->vNodesAll->pArray[i]->pCutOld; pMan->vNodesAll->pArray[i]->pCutOld = NULL; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaFanout.c000066400000000000000000000101231300674244400237610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaFanout.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaFanout.c,v 1.1 2005/01/23 06:59:41 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START #ifdef MAP_ALLOCATE_FANOUT //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Add the fanout to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout ) { Fpga_Node_t * pPivot; // pFanins is a fanin of pFanout assert( !Fpga_IsComplement(pFanin) ); assert( !Fpga_IsComplement(pFanout) ); assert( Fpga_Regular(pFanout->p1) == pFanin || Fpga_Regular(pFanout->p2) == pFanin ); pPivot = pFanin->pFanPivot; if ( pPivot == NULL ) { pFanin->pFanPivot = pFanout; return; } if ( Fpga_Regular(pPivot->p1) == pFanin ) { if ( Fpga_Regular(pFanout->p1) == pFanin ) { pFanout->pFanFanin1 = pPivot->pFanFanin1; pPivot->pFanFanin1 = pFanout; } else // if ( Fpga_Regular(pFanout->p2) == pFanin ) { pFanout->pFanFanin2 = pPivot->pFanFanin1; pPivot->pFanFanin1 = pFanout; } } else // if ( Fpga_Regular(pPivot->p2) == pFanin ) { assert( Fpga_Regular(pPivot->p2) == pFanin ); if ( Fpga_Regular(pFanout->p1) == pFanin ) { pFanout->pFanFanin1 = pPivot->pFanFanin2; pPivot->pFanFanin2 = pFanout; } else // if ( Fpga_Regular(pFanout->p2) == pFanin ) { pFanout->pFanFanin2 = pPivot->pFanFanin2; pPivot->pFanFanin2 = pFanout; } } } /**Function************************************************************* Synopsis [Add the fanout to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove ) { Fpga_Node_t * pFanout, * pFanout2, ** ppFanList; // start the linked list of fanouts ppFanList = &pFanin->pFanPivot; // go through the fanouts Fpga_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) { // skip the fanout-to-remove if ( pFanout == pFanoutToRemove ) continue; // add useful fanouts to the list *ppFanList = pFanout; ppFanList = Fpga_NodeReadNextFanoutPlace( pFanin, pFanout ); } *ppFanList = NULL; } /**Function************************************************************* Synopsis [Returns the number of fanouts of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode ) { Fpga_Node_t * pFanout; int Counter = 0; Fpga_NodeForEachFanout( pNode, pFanout ) Counter++; return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #endif ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaGENERIC.c000066400000000000000000000026471300674244400236150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpga__.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: fpga__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaInt.h000066400000000000000000000521671300674244400233020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaInt.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $] ***********************************************************************/ #ifndef ABC__map__fpga__fpgaInt_h #define ABC__map__fpga__fpgaInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include "misc/extra/extra.h" #include "fpga.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // uncomment to have fanouts represented in the mapping graph //#define FPGA_ALLOCATE_FANOUT 1 //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef _WIN32 #define inline __inline // compatible with MS VS 6.0 #endif // the maximum number of cut leaves (currently does not work for 7) #define FPGA_MAX_LEAVES 6 // the bit masks #define FPGA_MASK(n) ((~((unsigned)0)) >> (32-(n))) #define FPGA_FULL (~((unsigned)0)) #define FPGA_NO_VAR (-9999.0) #define FPGA_NUM_BYTES(n) (((n)/16 + (((n)%16) > 0))*16) // maximum/minimum operators #define FPGA_MIN(a,b) (((a) < (b))? (a) : (b)) #define FPGA_MAX(a,b) (((a) > (b))? (a) : (b)) // the small and large numbers (min/max float are 1.17e-38/3.40e+38) #define FPGA_FLOAT_LARGE ((float)1.0e+20) #define FPGA_FLOAT_SMALL ((float)1.0e-20) #define FPGA_INT_LARGE (10000000) // the macro to compute the signature #define FPGA_SEQ_SIGN(p) (1 << (((ABC_PTRUINT_T)p)%31)); // internal macros to work with cuts #define Fpga_CutIsComplement(p) (((int)((ABC_PTRUINT_T)(p) & 01))) #define Fpga_CutRegular(p) ((Fpga_Cut_t *)((ABC_PTRUINT_T)(p) & ~01)) #define Fpga_CutNot(p) ((Fpga_Cut_t *)((ABC_PTRUINT_T)(p) ^ 01)) #define Fpga_CutNotCond(p,c) ((Fpga_Cut_t *)((ABC_PTRUINT_T)(p) ^ (c))) // the cut nodes #define Fpga_SeqIsComplement( p ) (((int)((ABC_PTRUINT_T) (p) & 01))) #define Fpga_SeqRegular( p ) ((Fpga_Node_t *)((ABC_PTRUINT_T)(p) & ~015)) #define Fpga_SeqIndex( p ) ((((ABC_PTRUINT_T)(p)) >> 1) & 07) #define Fpga_SeqIndexCreate( p, Ind ) (((ABC_PTRUINT_T)(p)) | (1 << (((ABC_PTRUINT_T)(Ind)) & 07))) // internal macros for referencing of nodes #define Fpga_NodeReadRef(p) ((Fpga_Regular(p))->nRefs) #define Fpga_NodeRef(p) ((Fpga_Regular(p))->nRefs++) // returns the complemented attribute of the node #define Fpga_NodeIsSimComplement(p) (Fpga_IsComplement(p)? !(Fpga_Regular(p)->fInv) : (p)->fInv) // generating random unsigned (#define RAND_MAX 0x7fff) #define FPGA_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // the mapping manager struct Fpga_ManStruct_t_ { // the mapping graph Fpga_Node_t ** pBins; // the table of nodes hashed by their children int nBins; // the size of the table Fpga_Node_t ** pInputs; // the array of inputs int nInputs; // the number of inputs Fpga_Node_t ** pOutputs; // the array of outputs int nOutputs; // the number of outputs int nNodes; // the total number of nodes int nLatches; // the number of latches in the circuit Fpga_Node_t * pConst1; // the constant 1 node Fpga_NodeVec_t * vNodesAll; // the nodes by number Fpga_NodeVec_t * vAnds; // the nodes reachable from COs Fpga_NodeVec_t * vMapping; // the nodes used in the current mapping // info about the original circuit char * pFileName; // the file name char ** ppOutputNames; // the primary output names float * pInputArrivals;// the PI arrival times // mapping parameters int nVarsMax; // the max number of variables int fAreaRecovery; // the flag to use area flow as the first parameter int fVerbose; // the verbosiness flag int fSwitching; // minimize the switching activity (instead of area) int fLatchPaths; // optimize latch paths for delay, other paths for area int nTravIds; // the counter of traversal IDs float DelayTarget; // the target required times // support of choice nodes int nChoiceNodes; // the number of choice nodes int nChoices; // the number of all choices int nCanons; int nMatches; // the supergate library Fpga_LutLib_t * pLutLib; // the current LUT library // the memory managers Extra_MmFixed_t * mmNodes; // the memory manager for nodes Extra_MmFixed_t * mmCuts; // the memory manager for cuts // resynthesis parameters int fResynthesis; // the resynthesis flag float fRequiredGlo; // the global required times float fRequiredShift;// the shift of the required times float fRequiredStart;// the starting global required times float fRequiredGain; // the reduction in delay float fAreaGlo; // the total area float fAreaGain; // the reduction in area float fEpsilon; // the epsilon used to compare floats float fDelayWindow; // the delay window for delay-oriented resynthesis float DelayLimit; // for resynthesis float AreaLimit; // for resynthesis float TimeLimit; // for resynthesis // runtime statistics clock_t timeToMap; // time to transfer to the mapping structure clock_t timeCuts; // time to compute k-feasible cuts clock_t timeTruth; // time to compute the truth table for each cut clock_t timeMatch; // time to perform matching for each node clock_t timeRecover; // time to perform area recovery clock_t timeToNet; // time to transfer back to the network clock_t timeTotal; // the total mapping time clock_t time1; // time to transfer to the mapping structure clock_t time2; // time to transfer to the mapping structure }; // the LUT library struct Fpga_LutLibStruct_t_ { char * pName; // the name of the LUT library int LutMax; // the maximum LUT size int fVarPinDelays; // set to 1 if variable pin delays are specified float pLutAreas[FPGA_MAX_LUTSIZE+1]; // the areas of LUTs float pLutDelays[FPGA_MAX_LUTSIZE+1][FPGA_MAX_LUTSIZE+1];// the delays of LUTs }; // the mapping node struct Fpga_NodeStruct_t_ { // general information about the node Fpga_Node_t * pNext; // the next node in the hash table Fpga_Node_t * pLevel; // the next node in the linked list by level int Num; // the unique number of this node int NumA; // the unique number of this node int Num2; // the temporary number of this node int nRefs; // the number of references (fanouts) of the given node unsigned fMark0 : 1; // the mark used for traversals unsigned fMark1 : 1; // the mark used for traversals unsigned fInv : 1; // the complemented attribute for the equivalent nodes unsigned Value : 2; // the value of the nodes unsigned fUsed : 1; // the flag indicating that the node is used in the mapping unsigned fTemp : 1; // unused unsigned Level :11; // the level of the given node unsigned uData :14; // used to mark the fanins, for which resynthesis was tried int TravId; // the successors of this node Fpga_Node_t * p1; // the first child Fpga_Node_t * p2; // the second child Fpga_Node_t * pNextE; // the next functionally equivalent node Fpga_Node_t * pRepr; // the representative of the functionally equivalent class #ifdef FPGA_ALLOCATE_FANOUT // representation of node's fanouts Fpga_Node_t * pFanPivot; // the first fanout of this node Fpga_Node_t * pFanFanin1; // the next fanout of p1 Fpga_Node_t * pFanFanin2; // the next fanout of p2 // Fpga_NodeVec_t * vFanouts; // the array of fanouts of the gate #endif // the delay information float tRequired; // the best area flow float aEstFanouts; // the fanout estimation float Switching; // the probability of switching int LValue; // the l-value of the node short nLatches1; // the number of latches on the first edge short nLatches2; // the number of latches on the second edge // cut information Fpga_Cut_t * pCutBest; // the best mapping Fpga_Cut_t * pCutOld; // the old mapping Fpga_Cut_t * pCuts; // mapping choices for the node (elementary comes first) Fpga_Cut_t * pCutsN; // mapping choices for the node (elementary comes first) // misc information char * pData0; // temporary storage for the corresponding network node }; // the cuts used for matching struct Fpga_CutStruct_t_ { Fpga_Cut_t * pOne; // the father of this cut Fpga_Cut_t * pTwo; // the mother of this cut Fpga_Node_t * pRoot; // the root of the cut Fpga_Node_t * ppLeaves[FPGA_MAX_LEAVES+1]; // the leaves of this cut float fLevel; // the average level of the fanins unsigned uSign; // signature for quick comparison char fMark; // the mark to denote visited cut char Phase; // the mark to denote complemented cut char nLeaves; // the number of leaves of this cut char nVolume; // the volume of this cut float tArrival; // the arrival time float aFlow; // the area flow of the cut Fpga_Cut_t * pNext; // the pointer to the next cut in the list }; // the vector of nodes struct Fpga_NodeVecStruct_t_ { Fpga_Node_t ** pArray; // the array of nodes int nSize; // the number of entries in the array int nCap; // the number of allocated entries }; // getting hold of the next fanout of the node #define Fpga_NodeReadNextFanout( pNode, pFanout ) \ ( ( pFanout == NULL )? NULL : \ ((Fpga_Regular((pFanout)->p1) == (pNode))? \ (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) // getting hold of the place where the next fanout will be attached #define Fpga_NodeReadNextFanoutPlace( pNode, pFanout ) \ ( (Fpga_Regular((pFanout)->p1) == (pNode))? \ &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) // iterator through the fanouts of the node #define Fpga_NodeForEachFanout( pNode, pFanout ) \ for ( pFanout = (pNode)->pFanPivot; pFanout; \ pFanout = Fpga_NodeReadNextFanout(pNode, pFanout) ) // safe iterator through the fanouts of the node #define Fpga_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ for ( pFanout = (pNode)->pFanPivot, \ pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout); \ pFanout; \ pFanout = pFanout2, \ pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout) ) static inline int Fpga_FloatMoreThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 + p->fEpsilon; } static inline int Fpga_FloatLessThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 < Arg2 - p->fEpsilon; } static inline int Fpga_FloatEqual( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 - p->fEpsilon && Arg1 < Arg2 + p->fEpsilon; } //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== fpgaCut.c ===============================================================*/ extern void Fpga_MappingCuts( Fpga_Man_t * p ); extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ); extern int Fpga_CutCountAll( Fpga_Man_t * pMan ); /*=== fpgaCutUtils.c ===============================================================*/ extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ); extern Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld ); extern void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut ); extern void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut ); extern Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode ); extern float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut ); extern Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets ); extern void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave ); extern int Fpga_CutListCount( Fpga_Cut_t * pSets ); extern void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); extern void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); extern float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); extern float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); extern float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); extern float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); extern float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); extern void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); /*=== fraigFanout.c =============================================================*/ extern void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout ); extern void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove ); extern int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode ); /*=== fpgaLib.c ============================================================*/ extern Fpga_LutLib_t * Fpga_LutLibRead( char * FileName, int fVerbose ); extern void Fpga_LutLibFree( Fpga_LutLib_t * p ); extern void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib ); extern int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib ); /*=== fpgaMatch.c ===============================================================*/ extern int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented ); extern int Fpga_MappingMatchesArea( Fpga_Man_t * p ); extern int Fpga_MappingMatchesSwitch( Fpga_Man_t * p ); /*=== fpgaShow.c =============================================================*/ extern void Fpga_MappingShow( Fpga_Man_t * pMan, char * pFileName ); extern void Fpga_MappingShowNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppRoots, int nRoots, char * pFileName ); /*=== fpgaSwitch.c =============================================================*/ extern float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); extern float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); extern float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); extern float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping ); /*=== fpgaTime.c ===============================================================*/ extern float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); extern float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); extern float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p ); extern void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime ); extern void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired ); extern void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ); extern void Fpga_TimePropagateArrival( Fpga_Man_t * p ); /*=== fpgaVec.c =============================================================*/ extern Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap ); extern void Fpga_NodeVecFree( Fpga_NodeVec_t * p ); extern Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p ); extern int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p ); extern void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin ); extern void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew ); extern void Fpga_NodeVecClear( Fpga_NodeVec_t * p ); extern void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ); extern int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ); extern Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p ); extern void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry ); extern Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i ); extern void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p ); extern void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p ); extern void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 ); extern void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing ); extern void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes ); /*=== fpgaUtils.c ===============================================================*/ extern Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ); extern Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv ); extern int Fpga_CountLevels( Fpga_Man_t * pMan ); extern float Fpga_MappingGetAreaFlow( Fpga_Man_t * p ); extern float Fpga_MappingArea( Fpga_Man_t * pMan ); extern float Fpga_MappingAreaTrav( Fpga_Man_t * pMan ); extern float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan ); extern void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p ); extern void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] ); extern void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax ); extern void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing ); extern Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels ); extern Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes ); extern int Fpga_MappingMaxLevel( Fpga_Man_t * pMan ); extern void Fpga_ManReportChoices( Fpga_Man_t * pMan ); extern void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaLib.c000066400000000000000000000162531300674244400232450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaLib.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaLib.c,v 1.4 2005/01/23 06:59:41 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [APIs to access LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ) { return p->LutMax; } float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ) { return p->pLutAreas; } float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ) { assert( Size <= p->LutMax ); return p->pLutAreas[Size]; } /**Function************************************************************* Synopsis [Reads the description of LUTs from the LUT library file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_LutLib_t * Fpga_LutLibRead( char * FileName, int fVerbose ) { char pBuffer[1000], * pToken; Fpga_LutLib_t * p; FILE * pFile; int i, k; pFile = fopen( FileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open LUT library file \"%s\".\n", FileName ); return NULL; } p = ABC_ALLOC( Fpga_LutLib_t, 1 ); memset( p, 0, sizeof(Fpga_LutLib_t) ); p->pName = Extra_UtilStrsav( FileName ); i = 1; while ( fgets( pBuffer, 1000, pFile ) != NULL ) { pToken = strtok( pBuffer, " \t\n" ); if ( pToken == NULL ) continue; if ( pToken[0] == '#' ) continue; if ( i != atoi(pToken) ) { printf( "Error in the LUT library file \"%s\".\n", FileName ); ABC_FREE( p ); return NULL; } // read area pToken = strtok( NULL, " \t\n" ); p->pLutAreas[i] = (float)atof(pToken); // read delays k = 0; while ( (pToken = strtok( NULL, " \t\n" )) ) p->pLutDelays[i][k++] = (float)atof(pToken); // check for out-of-bound if ( k > i ) { printf( "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i ); return NULL; } // check if var delays are specifies if ( k > 1 ) p->fVarPinDelays = 1; if ( i == FPGA_MAX_LUTSIZE ) { printf( "Skipping LUTs of size more than %d.\n", i ); return NULL; } i++; } p->LutMax = i-1; /* if ( p->LutMax > FPGA_MAX_LEAVES ) { p->LutMax = FPGA_MAX_LEAVES; printf( "Warning: LUTs with more than %d inputs will not be used.\n", FPGA_MAX_LEAVES ); } */ // check the library if ( p->fVarPinDelays ) { for ( i = 1; i <= p->LutMax; i++ ) for ( k = 0; k < i; k++ ) { if ( p->pLutDelays[i][k] <= 0.0 ) printf( "Warning: Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", k, i, p->pLutDelays[i][k] ); if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] ) printf( "Warning: Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n", k-1, i, p->pLutDelays[i][k-1], k, i, p->pLutDelays[i][k] ); } } else { for ( i = 1; i <= p->LutMax; i++ ) { if ( p->pLutDelays[i][0] <= 0.0 ) printf( "Warning: LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", i, p->pLutDelays[i][0] ); } } return p; } /**Function************************************************************* Synopsis [Duplicates the LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p ) { Fpga_LutLib_t * pNew; pNew = ABC_ALLOC( Fpga_LutLib_t, 1 ); *pNew = *p; pNew->pName = Extra_UtilStrsav( pNew->pName ); return pNew; } /**Function************************************************************* Synopsis [Frees the LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_LutLibFree( Fpga_LutLib_t * pLutLib ) { if ( pLutLib == NULL ) return; ABC_FREE( pLutLib->pName ); ABC_FREE( pLutLib ); } /**Function************************************************************* Synopsis [Prints the LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib ) { int i, k; printf( "# The area/delay of k-variable LUTs:\n" ); printf( "# k area delay\n" ); if ( pLutLib->fVarPinDelays ) { for ( i = 1; i <= pLutLib->LutMax; i++ ) { printf( "%d %7.2f ", i, pLutLib->pLutAreas[i] ); for ( k = 0; k < i; k++ ) printf( " %7.2f", pLutLib->pLutDelays[i][k] ); printf( "\n" ); } } else for ( i = 1; i <= pLutLib->LutMax; i++ ) printf( "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i][0] ); } /**Function************************************************************* Synopsis [Returns 1 if the delays are discrete.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib ) { float Delay; int i; for ( i = 1; i <= pLutLib->LutMax; i++ ) { Delay = pLutLib->pLutDelays[i][0]; if ( ((float)((int)Delay)) != Delay ) return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaMatch.c000066400000000000000000000611011300674244400235630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaMatch.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented ); static int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode ); static int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode ); static Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pFanout, Fpga_Node_t * pNodeNo ); static int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Finds the best delay assignment of LUTs.] Description [This procedure iterates through all the nodes of the object graph reachable from the POs and assigns the best match to each of them. If the flag fDelayOriented is set to 1, it tries to minimize the arrival time and uses the area flow as a tie-breaker. If the flag is set to 0, it considers all the cuts, whose arrival times matches the required time at the node, and minimizes the area flow using the arrival time as a tie-breaker. Before this procedure is called, the required times should be set and the fanout counts should be computed. In the first iteration, the required times are set to very large number (by NodeCreate) and the fanout counts are set to the number of fanouts in the AIG. In the following iterations, the required times are set by the backward traversal, while the fanouts are estimated approximately. If the arrival times of the PI nodes are given, they should be assigned to the PIs after the cuts are computed and before this procedure is called for the first time.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented ) { ProgressBar * pProgress; Fpga_Node_t * pNode; int i, nNodes; // assign the arrival times of the PIs for ( i = 0; i < p->nInputs; i++ ) p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; // match LUTs with nodes in the topological order nNodes = p->vAnds->nSize; pProgress = Extra_ProgressBarStart( stdout, nNodes ); for ( i = 0; i < nNodes; i++ ) { pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; // skip a secondary node if ( pNode->pRepr ) continue; // match the node Fpga_MatchNode( p, pNode, fDelayOriented ); Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); } Extra_ProgressBarStop( pProgress ); /* if ( !fDelayOriented ) { float Area = 0.0; for ( i = 0; i < p->nOutputs; i++ ) { printf( "%5.2f ", Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow ); Area += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow; } printf( "\nTotal = %5.2f\n", Area ); } */ return 1; } /**Function************************************************************* Synopsis [Computes the best matching for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented ) { Fpga_Cut_t * pCut, * pCutBestOld; clock_t clk; // make sure that at least one cut other than the trivial is present if ( pNode->pCuts->pNext == NULL ) { printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); return 0; } // estimate the fanouts of the node if ( pNode->aEstFanouts < 0 ) pNode->aEstFanouts = (float)pNode->nRefs; else pNode->aEstFanouts = (float)((2.0 * pNode->aEstFanouts + pNode->nRefs) / 3.0); // pNode->aEstFanouts = (float)pNode->nRefs; pCutBestOld = pNode->pCutBest; pNode->pCutBest = NULL; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) { // compute the arrival time of the cut and its area flow clk = clock(); Fpga_CutGetParameters( p, pCut ); //p->time2 += clock() - clk; // drop the cut if it does not meet the required times if ( Fpga_FloatMoreThan(p, pCut->tArrival, pNode->tRequired) ) continue; // if no cut is assigned, use the current one if ( pNode->pCutBest == NULL ) { pNode->pCutBest = pCut; continue; } // choose the best cut using one of the two criteria: // (1) delay oriented mapping (first traversal), delay first, area-flow as a tie-breaker // (2) area recovery (subsequent traversals), area-flow first, delay as a tie-breaker if ( (fDelayOriented && (Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) || (Fpga_FloatEqual(p, pNode->pCutBest->tArrival, pCut->tArrival) && Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow)) )) || (!fDelayOriented && (Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || (Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival)))) ) { pNode->pCutBest = pCut; } } // make sure the match is found if ( pNode->pCutBest == NULL ) { if ( pCutBestOld == NULL ) { // printf( "\nError: Could not match a node in the object graph.\n" ); return 0; } pNode->pCutBest = pCutBestOld; } return 1; } /**Function************************************************************* Synopsis [Finds the best area assignment of LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MappingMatchesArea( Fpga_Man_t * p ) { ProgressBar * pProgress; Fpga_Node_t * pNode; int i, nNodes; // assign the arrival times of the PIs for ( i = 0; i < p->nInputs; i++ ) p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; // match LUTs with nodes in the topological order nNodes = p->vAnds->nSize; pProgress = Extra_ProgressBarStart( stdout, nNodes ); for ( i = 0; i < nNodes; i++ ) { pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; // skip a secondary node if ( pNode->pRepr ) continue; // match the node Fpga_MatchNodeArea( p, pNode ); Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); } Extra_ProgressBarStop( pProgress ); return 1; } /**Function************************************************************* Synopsis [Finds the best area assignment of LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ) { Fpga_Node_t * pNode; int i; // match LUTs with nodes in the topological order for ( i = 0; i < vNodes->nSize; i++ ) { pNode = vNodes->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; // skip a secondary node if ( pNode->pRepr ) continue; // match the node if ( !Fpga_MatchNodeArea( p, pNode ) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Computes the best matching for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode ) { Fpga_Cut_t * pCut, * pCutBestOld; float aAreaCutBest; clock_t clk; // make sure that at least one cut other than the trivial is present if ( pNode->pCuts->pNext == NULL ) { printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); return 0; } // remember the old cut pCutBestOld = pNode->pCutBest; // deref the old cut if ( pNode->nRefs ) aAreaCutBest = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 ); // search for a better cut pNode->pCutBest = NULL; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) { // compute the arrival time of the cut and its area flow clk = clock(); pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); //p->time2 += clock() - clk; // drop the cut if it does not meet the required times if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) ) continue; // get the area of this cut pCut->aFlow = Fpga_CutGetAreaDerefed( p, pCut ); // if no cut is assigned, use the current one if ( pNode->pCutBest == NULL ) { pNode->pCutBest = pCut; continue; } // choose the best cut as follows: exact area first, delay as a tie-breaker if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || (Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival)) ) { pNode->pCutBest = pCut; } } // make sure the match is found if ( pNode->pCutBest == NULL ) { pNode->pCutBest = pCutBestOld; // insert the new cut if ( pNode->nRefs ) pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); // printf( "\nError: Could not match a node in the object graph.\n" ); return 0; } // insert the new cut // make sure the area selected is not worse then the original area if ( pNode->nRefs ) { pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); // assert( pNode->pCutBest->aFlow <= aAreaCutBest ); // assert( pNode->tRequired < FPGA_FLOAT_LARGE ); } return 1; } /**Function************************************************************* Synopsis [Finds the best area assignment of LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MappingMatchesSwitch( Fpga_Man_t * p ) { ProgressBar * pProgress; Fpga_Node_t * pNode; int i, nNodes; // assign the arrival times of the PIs for ( i = 0; i < p->nInputs; i++ ) p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; // match LUTs with nodes in the topological order nNodes = p->vAnds->nSize; pProgress = Extra_ProgressBarStart( stdout, nNodes ); for ( i = 0; i < nNodes; i++ ) { pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; // skip a secondary node if ( pNode->pRepr ) continue; // match the node Fpga_MatchNodeSwitch( p, pNode ); Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); } Extra_ProgressBarStop( pProgress ); return 1; } /**Function************************************************************* Synopsis [Computes the best matching for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode ) { Fpga_Cut_t * pCut, * pCutBestOld; float aAreaCutBest = FPGA_FLOAT_LARGE; clock_t clk; // make sure that at least one cut other than the trivial is present if ( pNode->pCuts->pNext == NULL ) { printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); return 0; } // remember the old cut pCutBestOld = pNode->pCutBest; // deref the old cut if ( pNode->nRefs ) aAreaCutBest = Fpga_CutDerefSwitch( p, pNode, pNode->pCutBest, 0 ); // search for a better cut pNode->pCutBest = NULL; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) { // compute the arrival time of the cut and its area flow clk = clock(); pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); //p->time2 += clock() - clk; // drop the cut if it does not meet the required times if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) ) continue; // get the area of this cut pCut->aFlow = Fpga_CutGetSwitchDerefed( p, pNode, pCut ); // if no cut is assigned, use the current one if ( pNode->pCutBest == NULL ) { pNode->pCutBest = pCut; continue; } // choose the best cut as follows: exact area first, delay as a tie-breaker if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || (Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival)) ) { pNode->pCutBest = pCut; } } // make sure the match is found if ( pNode->pCutBest == NULL ) { pNode->pCutBest = pCutBestOld; // insert the new cut if ( pNode->nRefs ) pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 ); // printf( "\nError: Could not match a node in the object graph.\n" ); return 0; } // insert the new cut // make sure the area selected is not worse then the original area if ( pNode->nRefs ) { pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 ); assert( pNode->pCutBest->aFlow <= aAreaCutBest + 0.001 ); // assert( pNode->tRequired < FPGA_FLOAT_LARGE ); } return 1; } #if 0 /**function************************************************************* synopsis [References the cut.] description [This procedure is similar to the procedure NodeReclaim.] sideeffects [] seealso [] ***********************************************************************/ void Fpga_Experiment( Fpga_Man_t * p ) { int Counter[10] = {0}; Fpga_Node_t * pNode; int i; for ( i = 0; i < p->nOutputs; i++ ) { pNode = Fpga_Regular(p->pOutputs[i]); pNode->vFanouts = NULL; } for ( i = 0; i < p->vAnds->nSize; i++ ) { pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; if ( pNode->vFanouts == NULL ) continue; if ( pNode->vFanouts->nSize >= 10 ) continue; Counter[pNode->vFanouts->nSize]++; } printf( "Fanout stats: " ); for ( i = 0; i < 10; i++ ) printf( " %d=%d", i, Counter[i] ); printf( "\n" ); printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) ); for ( i = 0; i < p->vAnds->nSize; i++ ) { Fpga_NodeVec_t * vNodesTfo; float AreaBefore; pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; if ( pNode->vFanouts == NULL ) continue; if ( pNode->vFanouts->nSize != 1 && pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 ) continue; // assert( pNode->nRefs > 0 ); if ( pNode->nRefs == 0 ) continue; AreaBefore = pNode->pCutBest->aFlow; pNode->pCutBest->aFlow = FPGA_FLOAT_LARGE; Fpga_TimeComputeRequiredGlobal( p, 0 ); vNodesTfo = Fpga_CollectNodeTfo( p, pNode ); if ( Fpga_MappingMatchesAreaArray( p, vNodesTfo ) == 0 ) printf( "attempt failed\n" ); else printf( "attempt succeeded\n" ); Fpga_NodeVecFree( vNodesTfo ); pNode->pCutBest->aFlow = AreaBefore; // break; } printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) ); // printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) ); } /**function************************************************************* synopsis [References the cut.] description [This procedure is similar to the procedure NodeReclaim.] sideeffects [] seealso [] ***********************************************************************/ void Fpga_Experiment2( Fpga_Man_t * p ) { int Counter[10] = {0}; Fpga_Cut_t * ppCutsNew[10]; Fpga_Cut_t * ppCutsOld[10]; Fpga_Node_t * pFanout, * pNode; float Gain, Loss, GainTotal, Area1, Area2; int i, k; for ( i = 0; i < p->nOutputs; i++ ) { pNode = Fpga_Regular(p->pOutputs[i]); pNode->vFanouts = NULL; } for ( i = 0; i < p->vAnds->nSize; i++ ) { pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; if ( pNode->vFanouts == NULL ) continue; if ( pNode->vFanouts->nSize >= 10 ) continue; Counter[pNode->vFanouts->nSize]++; } printf( "Fanout stats: " ); for ( i = 0; i < 10; i++ ) printf( " %d=%d", i, Counter[i] ); printf( "\n" ); printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) ); GainTotal = 0; for ( i = 0; i < p->vAnds->nSize; i++ ) { pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; if ( pNode->vFanouts == NULL ) continue; if ( pNode->vFanouts->nSize != 2 )//&& pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 ) continue; assert( pNode->nRefs > 0 ); // for all fanouts, find the best cut without this node for ( k = 0; k < pNode->vFanouts->nSize; k++ ) { pFanout = pNode->vFanouts->pArray[k]; ppCutsOld[k] = pFanout->pCutBest; ppCutsNew[k] = Fpga_MappingAreaWithoutNode( p, pFanout, pNode ); if ( ppCutsNew[k] == NULL ) break; } if ( k != pNode->vFanouts->nSize ) { printf( "Node %4d: Skipped.\n", pNode->Num ); continue; } // compute the area after replacing all the cuts Gain = 0; for ( k = 0; k < pNode->vFanouts->nSize; k++ ) { pFanout = pNode->vFanouts->pArray[k]; // deref old cut Area1 = Fpga_MatchAreaDeref( p, ppCutsOld[k] ); // assign new cut pFanout->pCutBest = ppCutsNew[k]; // ref new cut Area2 = Fpga_MatchAreaRef( p, ppCutsNew[k] ); // compute the gain Gain += Area1 - Area2; } printf( "%d ", pNode->nRefs ); // undo the whole thing Loss = 0; for ( k = 0; k < pNode->vFanouts->nSize; k++ ) { pFanout = pNode->vFanouts->pArray[k]; // deref old cut Area1 = Fpga_MatchAreaDeref( p, ppCutsNew[k] ); // assign new cut pFanout->pCutBest = ppCutsOld[k]; // ref new cut Area2 = Fpga_MatchAreaRef( p, ppCutsOld[k] ); // compute the gain Loss += Area2 - Area1; } assert( Gain == Loss ); printf( "Node %4d: Fanouts = %d. Cut area = %4.2f. Gain = %4.2f.\n", pNode->Num, pNode->nRefs, pNode->pCutBest->aFlow, Gain ); if ( Gain > 0 ) GainTotal += Gain; } printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) ); printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) ); } /**function************************************************************* synopsis [Computes the loss of area when node is not allowed.] description [Returning FPGA_FLOAT_LARGE means it does not exist.] sideeffects [] seealso [] ***********************************************************************/ Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeNo ) { Fpga_Cut_t * pCut, * pCutBestOld, * pCutRes; float aAreaCutBest; int i; clock_t clk; // make sure that at least one cut other than the trivial is present if ( pNode->pCuts->pNext == NULL ) { printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); return 0; } assert( pNode->nRefs > 0 ); // remember the old cut pCutBestOld = pNode->pCutBest; // deref the old cut aAreaCutBest = Fpga_MatchAreaDeref( p, pNode->pCutBest ); // search for a better cut pNode->pCutBest = NULL; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) { // compute the arrival time of the cut and its area flow clk = clock(); Fpga_MatchCutGetArrTime( p, pCut ); //p->time2 += clock() - clk; // drop the cut if it does not meet the required times if ( pCut->tArrival > pNode->tRequired ) continue; // skip the cut if it contains the no-node for ( i = 0; i < pCut->nLeaves; i++ ) if ( pCut->ppLeaves[i] == pNodeNo ) break; if ( i != pCut->nLeaves ) continue; // get the area of this cut pCut->aFlow = Fpga_MatchAreaCount( p, pCut ); // if no cut is assigned, use the current one if ( pNode->pCutBest == NULL ) { pNode->pCutBest = pCut; continue; } // choose the best cut as follows: exact area first, delay as a tie-breaker if ( pNode->pCutBest->aFlow > pCut->aFlow || pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival ) { pNode->pCutBest = pCut; } } // make sure the match is found if ( pNode->pCutBest == NULL ) { pNode->pCutBest = pCutBestOld; // insert the new cut pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest ); return NULL; } pCutRes = pNode->pCutBest; pNode->pCutBest = pCutBestOld; // insert the new cut pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest ); // make sure the area selected is not worse then the original area assert( pNode->pCutBest->aFlow == aAreaCutBest ); assert( pNode->tRequired < FPGA_FLOAT_LARGE ); return pCutRes; } #endif /**function************************************************************* synopsis [Performs area minimization using a heuristic algorithm.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_FindBestNode( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes, Fpga_Node_t ** ppNode, Fpga_Cut_t ** ppCutBest ) { Fpga_Node_t * pNode; Fpga_Cut_t * pCut; float Gain, CutArea1, CutArea2, CutArea3; int i; Gain = 0; for ( i = 0; i < vNodes->nSize; i++ ) { pNode = vNodes->pArray[i]; // deref the current cut CutArea1 = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 ); // ref all the cuts for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) { if ( pCut == pNode->pCutBest ) continue; if ( pCut->tArrival > pNode->tRequired ) continue; CutArea2 = Fpga_CutGetAreaDerefed( p, pCut ); if ( Gain < CutArea1 - CutArea2 ) { *ppNode = pNode; *ppCutBest = pCut; Gain = CutArea1 - CutArea2; } } // ref the old cut CutArea3 = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); assert( CutArea1 == CutArea3 ); } if ( Gain == 0 ) printf( "Returning no gain.\n" ); return Gain; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaSwitch.c000066400000000000000000000112131300674244400237670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaSwitch.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: fpgaSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) { float aResult, aResult2; aResult2 = Fpga_CutRefSwitch( pMan, pNode, pCut, 0 ); aResult = Fpga_CutDerefSwitch( pMan, pNode, pCut, 0 ); // assert( aResult == aResult2 ); return aResult; } /**function************************************************************* synopsis [References the cut.] description [This procedure is similar to the procedure NodeReclaim.] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) { Fpga_Node_t * pNodeChild; float aArea; int i; // start the area of this cut aArea = pNode->Switching; if ( pCut->nLeaves == 1 ) return aArea; // go through the children for ( i = 0; i < pCut->nLeaves; i++ ) { pNodeChild = pCut->ppLeaves[i]; assert( pNodeChild->nRefs >= 0 ); if ( pNodeChild->nRefs++ > 0 ) continue; aArea += Fpga_CutRefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); } return aArea; } /**function************************************************************* synopsis [Dereferences the cut.] description [This procedure is similar to the procedure NodeRecusiveDeref.] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) { Fpga_Node_t * pNodeChild; float aArea; int i; // start the area of this cut aArea = pNode->Switching; if ( pCut->nLeaves == 1 ) return aArea; // go through the children for ( i = 0; i < pCut->nLeaves; i++ ) { pNodeChild = pCut->ppLeaves[i]; assert( pNodeChild->nRefs > 0 ); if ( --pNodeChild->nRefs > 0 ) continue; aArea += Fpga_CutDerefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); } return aArea; } /**Function************************************************************* Synopsis [Computes the array of mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping ) { Fpga_Node_t * pNode; float Switch; int i; Switch = 0.0; for ( i = 0; i < vMapping->nSize; i++ ) { pNode = vMapping->pArray[i]; // at least one phase has the best cut assigned assert( !Fpga_NodeIsAnd(pNode) || pNode->pCutBest != NULL ); // at least one phase is used in the mapping assert( pNode->nRefs > 0 ); // compute the array due to the supergate Switch += pNode->Switching; } // add buffer for each CO driven by a CI for ( i = 0; i < pMan->nOutputs; i++ ) if ( Fpga_NodeIsVar(Fpga_Regular(pMan->pOutputs[i])) && !Fpga_IsComplement(pMan->pOutputs[i]) ) Switch += Fpga_Regular(pMan->pOutputs[i])->Switching; return Switch; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaTime.c000066400000000000000000000204741300674244400234350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaTime.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaTime.c,v 1.1 2005/01/23 06:59:42 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the arrival times of the cut.] Description [Computes the maximum arrival time of the cut leaves and adds the delay of the LUT.] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { int i; float tArrival; tArrival = -FPGA_FLOAT_LARGE; for ( i = 0; i < pCut->nLeaves; i++ ) if ( tArrival < pCut->ppLeaves[i]->pCutBest->tArrival ) tArrival = pCut->ppLeaves[i]->pCutBest->tArrival; tArrival += pMan->pLutLib->pLutDelays[(int)pCut->nLeaves][0]; return tArrival; } /**Function************************************************************* Synopsis [Computes the arrival times of the cut recursively.] Description [When computing the arrival time for the previously unused cuts, their arrival time may be incorrect because their fanins have incorrect arrival time. This procedure is called to fix this problem.] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { int i; for ( i = 0; i < pCut->nLeaves; i++ ) if ( pCut->ppLeaves[i]->nRefs == 0 ) Fpga_TimeCutComputeArrival_rec( pMan, pCut->ppLeaves[i]->pCutBest ); return Fpga_TimeCutComputeArrival( pMan, pCut ); } /**Function************************************************************* Synopsis [Computes the maximum arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p ) { float fRequired; int i; if ( p->fLatchPaths && p->nLatches == 0 ) { printf( "Delay optimization of latch path is not performed because there is no latches.\n" ); p->fLatchPaths = 0; } // get the critical PO arrival time fRequired = -FPGA_FLOAT_LARGE; if ( p->fLatchPaths ) { for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ ) { if ( Fpga_NodeIsConst(p->pOutputs[i]) ) continue; fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); // printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); } // printf( "Required latches = %5.1f\n", fRequired ); } else { for ( i = 0; i < p->nOutputs; i++ ) { if ( Fpga_NodeIsConst(p->pOutputs[i]) ) continue; fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); // printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); } // printf( "Required outputs = %5.1f\n", fRequired ); } return fRequired; } /**Function************************************************************* Synopsis [Computes the required times of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime ) { p->fRequiredGlo = Fpga_TimeComputeArrivalMax( p ); // update the required times according to the target if ( p->DelayTarget != -1 ) { if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon ) { if ( fFirstTime ) printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->DelayTarget ); } else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon ) { if ( fFirstTime ) printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget ); p->fRequiredGlo = p->DelayTarget; } } Fpga_TimeComputeRequired( p, p->fRequiredGlo ); } /**Function************************************************************* Synopsis [Computes the required times of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired ) { int i; // clean the required times and the fanout counts for all nodes for ( i = 0; i < p->vAnds->nSize; i++ ) p->vAnds->pArray[i]->tRequired = FPGA_FLOAT_LARGE; // set the required times for the POs if ( p->fLatchPaths ) for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ ) Fpga_Regular(p->pOutputs[i])->tRequired = fRequired; else for ( i = 0; i < p->nOutputs; i++ ) Fpga_Regular(p->pOutputs[i])->tRequired = fRequired; // collect nodes reachable from POs in the DFS order through the best cuts Fpga_TimePropagateRequired( p, p->vMapping ); /* { int Counter = 0; for ( i = 0; i < p->vAnds->nSize; i++ ) if ( p->vAnds->pArray[i]->tRequired > FPGA_FLOAT_LARGE - 100 ) Counter++; printf( "The number of nodes with large required times = %d.\n", Counter ); } */ } /**Function************************************************************* Synopsis [Computes the required times of the given nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ) { Fpga_Node_t * pNode, * pChild; float fRequired; int i, k; // sorts the nodes in the decreasing order of levels // Fpga_MappingSortByLevel( p, vNodes, 0 ); // the nodes area already sorted in Fpga_MappingSetRefsAndArea() // go through the nodes in the reverse topological order for ( k = 0; k < vNodes->nSize; k++ ) { pNode = vNodes->pArray[k]; if ( !Fpga_NodeIsAnd(pNode) ) continue; // get the required time for children fRequired = pNode->tRequired - p->pLutLib->pLutDelays[(int)pNode->pCutBest->nLeaves][0]; // update the required time of the children for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) { pChild = pNode->pCutBest->ppLeaves[i]; pChild->tRequired = FPGA_MIN( pChild->tRequired, fRequired ); } } } /**Function************************************************************* Synopsis [Computes the required times of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_TimePropagateArrival( Fpga_Man_t * p ) { Fpga_Node_t * pNode; Fpga_Cut_t * pCut; int i; // clean the required times and the fanout counts for all nodes for ( i = 0; i < p->vAnds->nSize; i++ ) { pNode = p->vAnds->pArray[i]; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaTruth.c000066400000000000000000000126261300674244400236450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaTruth.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaTruth.c,v 1.4 2005/01/23 06:59:42 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" #include "bdd/cudd/cudd.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Recursively derives the truth table for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Fpga_TruthsCutBdd_rec( DdManager * dd, Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited ) { DdNode * bFunc, * bFunc0, * bFunc1; assert( !Fpga_IsComplement(pCut) ); // if the cut is visited, return the result if ( pCut->uSign ) return (DdNode *)(ABC_PTRUINT_T)pCut->uSign; // compute the functions of the children bFunc0 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pOne), vVisited ); Cudd_Ref( bFunc0 ); bFunc0 = Cudd_NotCond( bFunc0, Fpga_CutIsComplement(pCut->pOne) ); bFunc1 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pTwo), vVisited ); Cudd_Ref( bFunc1 ); bFunc1 = Cudd_NotCond( bFunc1, Fpga_CutIsComplement(pCut->pTwo) ); // get the function of the cut bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); bFunc = Cudd_NotCond( bFunc, pCut->Phase ); Cudd_RecursiveDeref( dd, bFunc0 ); Cudd_RecursiveDeref( dd, bFunc1 ); assert( pCut->uSign == 0 ); pCut->uSign = (unsigned)(ABC_PTRUINT_T)bFunc; // add this cut to the visited list Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut ); return bFunc; } /**Function************************************************************* Synopsis [Derives the truth table for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ) { Fpga_NodeVec_t * vVisited; DdNode * bFunc; int i; assert( pCut->nLeaves > 1 ); // set the leaf variables for ( i = 0; i < pCut->nLeaves; i++ ) pCut->ppLeaves[i]->pCuts->uSign = (unsigned)(ABC_PTRUINT_T)Cudd_bddIthVar( (DdManager *)dd, i ); // recursively compute the function vVisited = Fpga_NodeVecAlloc( 10 ); bFunc = Fpga_TruthsCutBdd_rec( (DdManager *)dd, pCut, vVisited ); Cudd_Ref( bFunc ); // clean the intermediate BDDs for ( i = 0; i < pCut->nLeaves; i++ ) pCut->ppLeaves[i]->pCuts->uSign = 0; for ( i = 0; i < vVisited->nSize; i++ ) { pCut = (Fpga_Cut_t *)vVisited->pArray[i]; Cudd_RecursiveDeref( (DdManager *)dd, (DdNode*)(ABC_PTRUINT_T)pCut->uSign ); pCut->uSign = 0; } // printf( "%d ", vVisited->nSize ); Fpga_NodeVecFree( vVisited ); Cudd_Deref( bFunc ); return bFunc; } /**Function************************************************************* Synopsis [Recursively derives the truth table for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutVolume_rec( Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited ) { assert( !Fpga_IsComplement(pCut) ); if ( pCut->fMark ) return; pCut->fMark = 1; Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pOne), vVisited ); Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pTwo), vVisited ); Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut ); } /**Function************************************************************* Synopsis [Derives the truth table for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutVolume( Fpga_Cut_t * pCut ) { Fpga_NodeVec_t * vVisited; int Volume, i; assert( pCut->nLeaves > 1 ); // set the leaf variables for ( i = 0; i < pCut->nLeaves; i++ ) pCut->ppLeaves[i]->pCuts->fMark = 1; // recursively compute the function vVisited = Fpga_NodeVecAlloc( 10 ); Fpga_CutVolume_rec( pCut, vVisited ); // clean the marks for ( i = 0; i < pCut->nLeaves; i++ ) pCut->ppLeaves[i]->pCuts->fMark = 0; for ( i = 0; i < vVisited->nSize; i++ ) { pCut = (Fpga_Cut_t *)vVisited->pArray[i]; pCut->fMark = 0; } Volume = vVisited->nSize; printf( "%d ", Volume ); Fpga_NodeVecFree( vVisited ); return Volume; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaUtils.c000066400000000000000000000727561300674244400236510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaUtils.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaUtils.c,v 1.3 2004/07/06 04:55:58 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define FPGA_CO_LIST_SIZE 5 static void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv ); static void Fpga_MappingDfsCuts_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes ); static int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 ); static void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax ); static void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes ); static int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo ); static Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ) { Fpga_NodeVec_t * vNodes;//, * vNodesCo; Fpga_Node_t * pNode; int i; // collect the CO nodes by level // vNodesCo = Fpga_MappingOrderCosByLevel( pMan ); // start the array vNodes = Fpga_NodeVecAlloc( 100 ); // collect the PIs for ( i = 0; i < pMan->nInputs; i++ ) { pNode = pMan->pInputs[i]; Fpga_NodeVecPush( vNodes, pNode ); pNode->fMark0 = 1; } // perform the traversal for ( i = 0; i < pMan->nOutputs; i++ ) Fpga_MappingDfs_rec( Fpga_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv ); // for ( i = vNodesCo->nSize - 1; i >= 0 ; i-- ) // for ( pNode = vNodesCo->pArray[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 ) // Fpga_MappingDfs_rec( pNode, vNodes, fCollectEquiv ); // clean the node marks for ( i = 0; i < vNodes->nSize; i++ ) vNodes->pArray[i]->fMark0 = 0; // for ( i = 0; i < pMan->nOutputs; i++ ) // Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) ); // Fpga_NodeVecFree( vNodesCo ); return vNodes; } /**Function************************************************************* Synopsis [Recursively computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv ) { assert( !Fpga_IsComplement(pNode) ); if ( pNode->fMark0 ) return; // visit the transitive fanin if ( Fpga_NodeIsAnd(pNode) ) { Fpga_MappingDfs_rec( Fpga_Regular(pNode->p1), vNodes, fCollectEquiv ); Fpga_MappingDfs_rec( Fpga_Regular(pNode->p2), vNodes, fCollectEquiv ); } // visit the equivalent nodes if ( fCollectEquiv && pNode->pNextE ) Fpga_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv ); // make sure the node is not visited through the equivalent nodes assert( pNode->fMark0 == 0 ); // mark the node as visited pNode->fMark0 = 1; // add the node to the list Fpga_NodeVecPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv ) { Fpga_NodeVec_t * vNodes; int i; // perform the traversal vNodes = Fpga_NodeVecAlloc( 200 ); for ( i = 0; i < nNodes; i++ ) Fpga_MappingDfs_rec( ppNodes[i], vNodes, fEquiv ); for ( i = 0; i < vNodes->nSize; i++ ) vNodes->pArray[i]->fMark0 = 0; return vNodes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_MappingGetAreaFlow( Fpga_Man_t * p ) { float aFlowFlowTotal = 0; int i; for ( i = 0; i < p->nOutputs; i++ ) { if ( Fpga_NodeIsConst(p->pOutputs[i]) ) continue; aFlowFlowTotal += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow; } return aFlowFlowTotal; } /**Function************************************************************* Synopsis [Computes the area of the current mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_MappingArea( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode; float aTotal; int i; // perform the traversal aTotal = 0; for ( i = 0; i < pMan->vMapping->nSize; i++ ) { pNode = pMan->vMapping->pArray[i]; aTotal += pMan->pLutLib->pLutAreas[(int)pNode->pCutBest->nLeaves]; } return aTotal; } /**Function************************************************************* Synopsis [Recursively computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_MappingArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes ) { float aArea; int i; assert( !Fpga_IsComplement(pNode) ); if ( !Fpga_NodeIsAnd(pNode) ) return 0; if ( pNode->fMark0 ) return 0; assert( pNode->pCutBest != NULL ); // visit the transitive fanin of the selected cut aArea = 0; for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) aArea += Fpga_MappingArea_rec( pMan, pNode->pCutBest->ppLeaves[i], vNodes ); // make sure the node is not visited through the fanin nodes assert( pNode->fMark0 == 0 ); // mark the node as visited pNode->fMark0 = 1; // add the node to the list aArea += pMan->pLutLib->pLutAreas[(int)pNode->pCutBest->nLeaves]; // add the node to the list Fpga_NodeVecPush( vNodes, pNode ); return aArea; } /**Function************************************************************* Synopsis [Computes the area of the current mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_MappingAreaTrav( Fpga_Man_t * pMan ) { Fpga_NodeVec_t * vNodes; float aTotal; int i; // perform the traversal aTotal = 0; vNodes = Fpga_NodeVecAlloc( 100 ); for ( i = 0; i < pMan->nOutputs; i++ ) aTotal += Fpga_MappingArea_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), vNodes ); for ( i = 0; i < vNodes->nSize; i++ ) vNodes->pArray[i]->fMark0 = 0; Fpga_NodeVecFree( vNodes ); return aTotal; } /**Function************************************************************* Synopsis [Recursively computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_MappingSetRefsAndArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Node_t ** ppStore ) { float aArea; int i; assert( !Fpga_IsComplement(pNode) ); if ( pNode->nRefs++ ) return 0; if ( !Fpga_NodeIsAnd(pNode) ) return 0; assert( pNode->pCutBest != NULL ); // store the node in the structure by level pNode->pData0 = (char *)ppStore[pNode->Level]; ppStore[pNode->Level] = pNode; // visit the transitive fanin of the selected cut aArea = pMan->pLutLib->pLutAreas[(int)pNode->pCutBest->nLeaves]; for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode->pCutBest->ppLeaves[i], ppStore ); return aArea; } /**Function************************************************************* Synopsis [Sets the correct reference counts for the mapping.] Description [Collects the nodes in reverse topological order and places in them in array pMan->vMapping.] SideEffects [] SeeAlso [] ***********************************************************************/ float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode, ** ppStore; float aArea; int i, LevelMax; // clean all references for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) pMan->vNodesAll->pArray[i]->nRefs = 0; // allocate place to store the nodes LevelMax = Fpga_MappingMaxLevel( pMan ); ppStore = ABC_ALLOC( Fpga_Node_t *, LevelMax + 1 ); memset( ppStore, 0, sizeof(Fpga_Node_t *) * (LevelMax + 1) ); // collect nodes reachable from POs in the DFS order through the best cuts aArea = 0; for ( i = 0; i < pMan->nOutputs; i++ ) { pNode = Fpga_Regular(pMan->pOutputs[i]); if ( pNode == pMan->pConst1 ) continue; aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode, ppStore ); pNode->nRefs++; } // reconnect the nodes in reverse topological order pMan->vMapping->nSize = 0; for ( i = LevelMax; i >= 0; i-- ) for ( pNode = ppStore[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 ) Fpga_NodeVecPush( pMan->vMapping, pNode ); ABC_FREE( ppStore ); return aArea; } /**Function************************************************************* Synopsis [Compares the outputs by their arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 ) { Fpga_Node_t * pNode1 = Fpga_Regular(*ppNode1); Fpga_Node_t * pNode2 = Fpga_Regular(*ppNode2); float Arrival1 = pNode1->pCutBest? pNode1->pCutBest->tArrival : 0; float Arrival2 = pNode2->pCutBest? pNode2->pCutBest->tArrival : 0; if ( Arrival1 < Arrival2 ) return -1; if ( Arrival1 > Arrival2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Finds given number of latest arriving COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax ) { int nNodes, i, k, v; assert( p->nOutputs >= nNodesMax ); pNodes[0] = 0; nNodes = 1; for ( i = 1; i < p->nOutputs; i++ ) { for ( k = nNodes - 1; k >= 0; k-- ) if ( Fpga_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 ) break; if ( k == nNodesMax - 1 ) continue; if ( nNodes < nNodesMax ) nNodes++; for ( v = nNodes - 1; v > k+1; v-- ) pNodes[v] = pNodes[v-1]; pNodes[k+1] = i; } } /**Function************************************************************* Synopsis [Prints a bunch of latest arriving outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p ) { Fpga_Node_t * pNode; int pSorted[FPGA_CO_LIST_SIZE]; int fCompl, Limit, MaxNameSize, i; // determine the number of nodes to print Limit = (p->nOutputs > FPGA_CO_LIST_SIZE)? FPGA_CO_LIST_SIZE : p->nOutputs; // determine the order Fpga_MappingFindLatest( p, pSorted, Limit ); // determine max size of the node's name MaxNameSize = 0; for ( i = 0; i < Limit; i++ ) if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) ) MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]); // print the latest outputs for ( i = 0; i < Limit; i++ ) { // get the i-th latest output pNode = Fpga_Regular(p->pOutputs[pSorted[i]]); fCompl = Fpga_IsComplement(p->pOutputs[pSorted[i]]); // print out the best arrival time printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] ); printf( "Delay = %8.2f ", (double)pNode->pCutBest->tArrival ); if ( fCompl ) printf( "NEG" ); else printf( "POS" ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Sets up the truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] ) { int m, v; // set up the truth tables for ( m = 0; m < 32; m++ ) for ( v = 0; v < 5; v++ ) if ( m & (1 << v) ) uTruths[v][0] |= (1 << m); // make adjustments for the case of 6 variables for ( v = 0; v < 5; v++ ) uTruths[v][1] = uTruths[v][0]; uTruths[5][0] = 0; uTruths[5][1] = FPGA_FULL; } /**Function************************************************************* Synopsis [Sets up the mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax ) { if ( nVarsMax == 6 ) uMask[0] = uMask[1] = FPGA_FULL; else { uMask[0] = FPGA_MASK(1 << nVarsMax); uMask[1] = 0; } } /**Function************************************************************* Synopsis [Verify one useful property.] Description [This procedure verifies one useful property. After the FRAIG construction with choice nodes is over, each primary node should have fanins that are primary nodes. The primary nodes is the one that does not have pNode->pRepr set to point to another node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_ManCheckConsistency( Fpga_Man_t * p ) { Fpga_Node_t * pNode; Fpga_NodeVec_t * pVec; int i; pVec = Fpga_MappingDfs( p, 0 ); for ( i = 0; i < pVec->nSize; i++ ) { pNode = pVec->pArray[i]; if ( Fpga_NodeIsVar(pNode) ) { if ( pNode->pRepr ) printf( "Primary input %d is a secondary node.\n", pNode->Num ); } else if ( Fpga_NodeIsConst(pNode) ) { if ( pNode->pRepr ) printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); } else { if ( pNode->pRepr ) printf( "Internal node %d is a secondary node.\n", pNode->Num ); if ( Fpga_Regular(pNode->p1)->pRepr ) printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num ); if ( Fpga_Regular(pNode->p2)->pRepr ) printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num ); } } Fpga_NodeVecFree( pVec ); return 1; } /**Function************************************************************* Synopsis [Compares the supergates by their level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CompareNodesByLevelDecreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) { if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level ) return -1; if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level ) return 1; return 0; } /**Function************************************************************* Synopsis [Compares the supergates by their level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CompareNodesByLevelIncreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) { if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level ) return -1; if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level ) return 1; return 0; } /**Function************************************************************* Synopsis [Orders the nodes in the decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing ) { if ( fIncreasing ) qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelIncreasing ); else qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelDecreasing ); // assert( Fpga_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 ); } /**Function************************************************************* Synopsis [Computes the limited DFS ordering for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels ) { Fpga_NodeVec_t * vNodes; int i; // perform the traversal vNodes = Fpga_NodeVecAlloc( 100 ); Fpga_DfsLim_rec( pNode, nLevels, vNodes ); for ( i = 0; i < vNodes->nSize; i++ ) vNodes->pArray[i]->fMark0 = 0; return vNodes; } /**Function************************************************************* Synopsis [Recursively computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes ) { assert( !Fpga_IsComplement(pNode) ); if ( pNode->fMark0 ) return; pNode->fMark0 = 1; // visit the transitive fanin Level--; if ( Level > 0 && Fpga_NodeIsAnd(pNode) ) { Fpga_DfsLim_rec( Fpga_Regular(pNode->p1), Level, vNodes ); Fpga_DfsLim_rec( Fpga_Regular(pNode->p2), Level, vNodes ); } // add the node to the list Fpga_NodeVecPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Computes the limited DFS ordering for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_ManCleanData0( Fpga_Man_t * pMan ) { int i; for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) pMan->vNodesAll->pArray[i]->pData0 = 0; } /**Function************************************************************* Synopsis [Collects the TFO of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode ) { Fpga_NodeVec_t * vVisited, * vTfo; int i; // perform the traversal vVisited = Fpga_NodeVecAlloc( 100 ); vTfo = Fpga_NodeVecAlloc( 100 ); for ( i = 0; i < pMan->nOutputs; i++ ) Fpga_CollectNodeTfo_rec( Fpga_Regular(pMan->pOutputs[i]), pNode, vVisited, vTfo ); for ( i = 0; i < vVisited->nSize; i++ ) vVisited->pArray[i]->fMark0 = vVisited->pArray[i]->fMark1 = 0; Fpga_NodeVecFree( vVisited ); return vTfo; } /**Function************************************************************* Synopsis [Collects the TFO of the node.] Description [Returns 1 if the node should be collected.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo ) { int Ret1, Ret2; assert( !Fpga_IsComplement(pNode) ); // skip visited nodes if ( pNode->fMark0 ) return pNode->fMark1; pNode->fMark0 = 1; Fpga_NodeVecPush( vVisited, pNode ); // return the pivot node if ( pNode == pPivot ) { pNode->fMark1 = 1; return 1; } if ( pNode->Level < pPivot->Level ) { pNode->fMark1 = 0; return 0; } // visit the transitive fanin assert( Fpga_NodeIsAnd(pNode) ); Ret1 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p1), pPivot, vVisited, vTfo ); Ret2 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p2), pPivot, vVisited, vTfo ); if ( Ret1 || Ret2 ) { pNode->fMark1 = 1; Fpga_NodeVecPush( vTfo, pNode ); } else pNode->fMark1 = 0; return pNode->fMark1; } /**Function************************************************************* Synopsis [Levelizes the nodes accessible from the POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes ) { Fpga_NodeVec_t * vLevels; Fpga_Node_t ** ppNodes; Fpga_Node_t * pNode; int nNodes, nLevelsMax, i; // reassign the levels (this may be necessary for networks which choices) ppNodes = vNodes->pArray; nNodes = vNodes->nSize; for ( i = 0; i < nNodes; i++ ) { pNode = ppNodes[i]; if ( !Fpga_NodeIsAnd(pNode) ) { pNode->Level = 0; continue; } pNode->Level = 1 + FPGA_MAX( Fpga_Regular(pNode->p1)->Level, Fpga_Regular(pNode->p2)->Level ); } // get the max levels nLevelsMax = 0; for ( i = 0; i < pMan->nOutputs; i++ ) nLevelsMax = FPGA_MAX( nLevelsMax, (int)Fpga_Regular(pMan->pOutputs[i])->Level ); nLevelsMax++; // allocate storage for levels vLevels = Fpga_NodeVecAlloc( nLevelsMax ); for ( i = 0; i < nLevelsMax; i++ ) Fpga_NodeVecPush( vLevels, NULL ); // go through the nodes and add them to the levels for ( i = 0; i < nNodes; i++ ) { pNode = ppNodes[i]; pNode->pLevel = NULL; if ( !Fpga_NodeIsAnd(pNode) ) continue; // attach the node to this level pNode->pLevel = Fpga_NodeVecReadEntry( vLevels, pNode->Level ); Fpga_NodeVecWriteEntry( vLevels, pNode->Level, pNode ); } return vLevels; } /**Function************************************************************* Synopsis [Sets up the mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MappingMaxLevel( Fpga_Man_t * pMan ) { int nLevelMax, i; nLevelMax = 0; for ( i = 0; i < pMan->nOutputs; i++ ) nLevelMax = nLevelMax > (int)Fpga_Regular(pMan->pOutputs[i])->Level? nLevelMax : (int)Fpga_Regular(pMan->pOutputs[i])->Level; return nLevelMax; } /**Function************************************************************* Synopsis [Analyses choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_MappingUpdateLevel_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int fMaximum ) { Fpga_Node_t * pTemp; int Level1, Level2, LevelE; assert( !Fpga_IsComplement(pNode) ); if ( !Fpga_NodeIsAnd(pNode) ) return pNode->Level; // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return pNode->Level; pNode->TravId = pMan->nTravIds; // compute levels of the children nodes Level1 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p1), fMaximum ); Level2 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p2), fMaximum ); pNode->Level = 1 + FPGA_MAX( Level1, Level2 ); if ( pNode->pNextE ) { LevelE = Fpga_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); if ( fMaximum ) { if ( pNode->Level < (unsigned)LevelE ) pNode->Level = LevelE; } else { if ( pNode->Level > (unsigned)LevelE ) pNode->Level = LevelE; } // set the level of all equivalent nodes to be the same minimum if ( pNode->pRepr == NULL ) // the primary node for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) pTemp->Level = pNode->Level; } return pNode->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 [] ***********************************************************************/ void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ) { int i; pMan->nTravIds++; for ( i = 0; i < pMan->nOutputs; i++ ) Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 1 ); } /**Function************************************************************* Synopsis [Reports statistics on choice nodes.] Description [The number of choice nodes is the number of primary nodes, which has pNextE set to a pointer. The number of choices is the number of entries in the equivalent-node lists of the primary nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_ManReportChoices( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode, * pTemp; int nChoiceNodes, nChoices; int i, LevelMax1, LevelMax2; // report the number of levels LevelMax1 = Fpga_MappingMaxLevel( pMan ); pMan->nTravIds++; for ( i = 0; i < pMan->nOutputs; i++ ) Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 0 ); LevelMax2 = Fpga_MappingMaxLevel( pMan ); // report statistics about choices nChoiceNodes = nChoices = 0; for ( i = 0; i < pMan->vAnds->nSize; i++ ) { pNode = pMan->vAnds->pArray[i]; if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) { // this is a choice node = the primary node that has equivalent nodes nChoiceNodes++; for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) nChoices++; } } if ( pMan->fVerbose ) { printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); } /* { FILE * pTable; pTable = fopen( "stats_choice.txt", "a+" ); fprintf( pTable, "%s ", pMan->pFileName ); fprintf( pTable, "%4d ", LevelMax1 ); fprintf( pTable, "%4d ", pMan->vAnds->nSize - pMan->nInputs ); fprintf( pTable, "%4d ", LevelMax2 ); fprintf( pTable, "%7d ", nChoiceNodes ); fprintf( pTable, "%7d ", nChoices + nChoiceNodes ); fprintf( pTable, "\n" ); fclose( pTable ); } */ } /**Function************************************************************* Synopsis [Returns the array of CO nodes sorted by level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode; Fpga_NodeVec_t * vNodes; int i, nLevels; // get the largest level of a CO nLevels = Fpga_MappingMaxLevel( pMan ); // allocate the array of nodes vNodes = Fpga_NodeVecAlloc( nLevels + 1 ); for ( i = 0; i <= nLevels; i++ ) Fpga_NodeVecPush( vNodes, NULL ); // clean the marks for ( i = 0; i < pMan->nOutputs; i++ ) Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0; // put the nodes into the structure for ( i = 0; i < pMan->nOutputs; i++ ) { pNode = Fpga_Regular(pMan->pOutputs[i]); if ( pNode->fMark0 ) continue; pNode->fMark0 = 1; pNode->pData0 = (char *)Fpga_NodeVecReadEntry( vNodes, pNode->Level ); Fpga_NodeVecWriteEntry( vNodes, pNode->Level, pNode ); } for ( i = 0; i < pMan->nOutputs; i++ ) Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0; return vNodes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/fpgaVec.c000066400000000000000000000244331300674244400232530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fpgaVec.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Technology mapping for variable-size-LUT FPGAs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaVec.c,v 1.3 2005/01/23 06:59:42 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap ) { Fpga_NodeVec_t * p; p = ABC_ALLOC( Fpga_NodeVec_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( Fpga_Node_t *, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecFree( Fpga_NodeVec_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p ) { return p->pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( Fpga_Node_t *, p->pArray, nCapMin ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecClear( Fpga_NodeVec_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Fpga_NodeVecGrow( p, 16 ); else Fpga_NodeVecGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } /**Function************************************************************* Synopsis [Add the element while ensuring uniqueness.] Description [Returns 1 if the element was found, and 0 if it was new. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Fpga_NodeVecPush( p, Entry ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p ) { return p->pArray[--p->nSize]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } /**Function************************************************************* Synopsis [Comparison procedure for two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 ) { int Level1 = Fpga_Regular(*pp1)->Level; int Level2 = Fpga_Regular(*pp2)->Level; if ( Level1 < Level2 ) return -1; if ( Level1 > Level2 ) return 1; if ( Fpga_Regular(*pp1)->Num < Fpga_Regular(*pp2)->Num ) return -1; if ( Fpga_Regular(*pp1)->Num > Fpga_Regular(*pp2)->Num ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p ) { qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *), (int (*)(const void *, const void *)) Fpga_NodeVecCompareLevels ); } /**Function************************************************************* Synopsis [Compares the arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_NodeVecCompareArrivals( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) { if ( (*ppS1)->pCutBest->tArrival < (*ppS2)->pCutBest->tArrival ) return -1; if ( (*ppS1)->pCutBest->tArrival > (*ppS2)->pCutBest->tArrival ) return 1; return 0; } /**Function************************************************************* Synopsis [Orders the nodes in the increasing order of the arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p ) { qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *), (int (*)(const void *, const void *)) Fpga_NodeVecCompareArrivals ); // assert( Fpga_CompareNodesByLevel( p->pArray, p->pArray + p->nSize - 1 ) <= 0 ); } /**Function************************************************************* Synopsis [Computes the union of nodes in two arrays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 ) { int i; Fpga_NodeVecClear( p ); for ( i = 0; i < p1->nSize; i++ ) Fpga_NodeVecPush( p, p1->pArray[i] ); for ( i = 0; i < p2->nSize; i++ ) Fpga_NodeVecPush( p, p2->pArray[i] ); } /**Function************************************************************* Synopsis [Inserts a new node in the order by arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing ) { Fpga_Node_t * pNode1, * pNode2; int i; Fpga_NodeVecPush( vNodes, pNode ); // find the place of the node for ( i = vNodes->nSize-1; i > 0; i-- ) { pNode1 = vNodes->pArray[i ]; pNode2 = vNodes->pArray[i-1]; if (( fIncreasing && pNode1->pCutBest->tArrival >= pNode2->pCutBest->tArrival) || (!fIncreasing && pNode1->pCutBest->tArrival <= pNode2->pCutBest->tArrival) ) break; vNodes->pArray[i ] = pNode2; vNodes->pArray[i-1] = pNode1; } } /**Function************************************************************* Synopsis [Inserts a new node in the order by arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes ) { Fpga_Node_t * pNode1, * pNode2; int i; for ( i = 0; i < vNodes->nSize/2; i++ ) { pNode1 = vNodes->pArray[i]; pNode2 = vNodes->pArray[vNodes->nSize-1-i]; vNodes->pArray[i] = pNode2; vNodes->pArray[vNodes->nSize-1-i] = pNode1; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/fpga/module.make000066400000000000000000000005521300674244400236540ustar00rootroot00000000000000SRC += src/map/fpga/fpga.c \ src/map/fpga/fpgaCore.c \ src/map/fpga/fpgaCreate.c \ src/map/fpga/fpgaCut.c \ src/map/fpga/fpgaCutUtils.c \ src/map/fpga/fpgaFanout.c \ src/map/fpga/fpgaLib.c \ src/map/fpga/fpgaMatch.c \ src/map/fpga/fpgaSwitch.c \ src/map/fpga/fpgaTime.c \ src/map/fpga/fpgaTruth.c \ src/map/fpga/fpgaUtils.c \ src/map/fpga/fpgaVec.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/000077500000000000000000000000001300674244400212075ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/if.h000066400000000000000000001272621300674244400217700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [if.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: if.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__if__if_h #define ABC__map__if__if_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "misc/mem/mem.h" #include "misc/tim/tim.h" #include "misc/util/utilNam.h" #include "misc/vec/vecMem.h" #include "misc/util/utilTruth.h" #include "opt/dau/dau.h" #include "misc/vec/vecHash.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // the maximum size of LUTs used for mapping (should be the same as FPGA_MAX_LUTSIZE defined in "fpga.h"!!!) #define IF_MAX_LUTSIZE 32 // the largest possible number of LUT inputs when funtionality of the LUTs are computed #define IF_MAX_FUNC_LUTSIZE 15 // a very large number #define IF_INFINITY 100000000 // the largest possible user cut cost #define IF_COST_MAX 4095 // ((1<<12)-1) #define IF_BIG_CHAR ((char)120) // object types typedef enum { IF_NONE, // 0: non-existent object IF_CONST1, // 1: constant 1 IF_CI, // 2: combinational input IF_CO, // 3: combinational output IF_AND, // 4: AND node IF_VOID // 5: unused object } If_Type_t; //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct If_Man_t_ If_Man_t; typedef struct If_Par_t_ If_Par_t; typedef struct If_Obj_t_ If_Obj_t; typedef struct If_Cut_t_ If_Cut_t; typedef struct If_Set_t_ If_Set_t; typedef struct If_LibLut_t_ If_LibLut_t; typedef struct If_LibBox_t_ If_LibBox_t; typedef struct If_DsdMan_t_ If_DsdMan_t; typedef struct Ifn_Ntk_t_ Ifn_Ntk_t; typedef struct Ifif_Par_t_ Ifif_Par_t; struct Ifif_Par_t_ { int nLutSize; // the LUT size If_LibLut_t * pLutLib; // the LUT library float pLutDelays[IF_MAX_LUTSIZE]; // pin-to-pin delays of the max LUT float DelayWire; // wire delay int nDegree; // structure degree int fCascade; // cascade int fVerbose; // verbose int fVeryVerbose; // verbose }; // parameters struct If_Par_t_ { // user-controlable parameters int nLutSize; // the LUT size int nCutsMax; // the max number of cuts int nFlowIters; // the number of iterations of area recovery int nAreaIters; // the number of iterations of area recovery int nGateSize; // the max size of the AND/OR gate to map into int nNonDecLimit; // the max size of non-dec nodes float DelayTarget; // delay target float Epsilon; // value used in comparison floating point numbers int nRelaxRatio; // delay relaxation ratio int nStructType; // type of the structure int nAndDelay; // delay of AND-gate in LUT library units int nAndArea; // area of AND-gate in LUT library units int fPreprocess; // preprossing int fArea; // area-oriented mapping int fFancy; // a fancy feature int fExpRed; // expand/reduce of the best cuts int fLatchPaths; // reset timing on latch paths int fEdge; // uses edge-based cut selection heuristics int fPower; // uses power-aware cut selection heuristics int fCutMin; // performs cut minimization by removing functionally reducdant variables int fDelayOpt; // special delay optimization int fDelayOptLut; // delay optimization for LUTs int fDsdBalance; // special delay optimization int fUserRecLib; // use recorded library int fUserSesLib; // use SAT-based synthesis int fBidec; // use bi-decomposition int fUse34Spec; // use specialized matching int fUseBat; // use one specialized feature int fUseBuffs; // use buffers to decouple outputs int fEnableCheck07;// enable additional checking int fEnableCheck08;// enable additional checking int fEnableCheck10;// enable additional checking int fEnableCheck75;// enable additional checking int fEnableCheck75u;// enable additional checking int fUseDsd; // compute DSD of the cut functions int fUseDsdTune; // use matching based on precomputed manager int fUseCofVars; // use cofactoring variables int fUseAndVars; // use bi-decomposition int fUseTtPerm; // compute truth tables of the cut functions int fDeriveLuts; // enables deriving LUT structures int fDoAverage; // optimize average rather than maximum level int fHashMapping; // perform AIG hashing after mapping int fVerbose; // the verbosity flag char * pLutStruct; // LUT structure float WireDelay; // wire delay // internal parameters int fSkipCutFilter;// skip cut filter int fAreaOnly; // area only mode int fTruth; // truth table computation enabled int fUsePerm; // use permutation (delay info) int fUseBdds; // use local BDDs as a cost function int fUseSops; // use local SOPs as a cost function int fUseCnfs; // use local CNFs as a cost function int fUseMv; // use local MV-SOPs as a cost function int nLatchesCi; // the number of latches among the CIs int nLatchesCo; // the number of latches among the COs int nLatchesCiBox; // the number of white box outputs among the CIs int nLatchesCoBox; // the number of white box inputs among the COs int fLiftLeaves; // shift the leaves for seq mapping int fUseCoAttrs; // use CO attributes float DelayTargetNew;// new delay target float FinalDelay; // final delay after mapping float FinalArea; // final area after mapping If_LibLut_t * pLutLib; // the LUT library float * pTimesArr; // arrival times float * pTimesReq; // required times int (* pFuncCost) (If_Man_t *, If_Cut_t *); // procedure to compute the user's cost of a cut int (* pFuncUser) (If_Man_t *, If_Obj_t *, If_Cut_t *); // procedure called for each cut when cut computation is finished int (* pFuncCell) (If_Man_t *, unsigned *, int, int, char *); // procedure called for cut functions void * pReoMan; // reordering manager }; // the LUT library struct If_LibLut_t_ { char * pName; // the name of the LUT library int LutMax; // the maximum LUT size int fVarPinDelays; // set to 1 if variable pin delays are specified float pLutAreas[IF_MAX_LUTSIZE+1]; // the areas of LUTs float pLutDelays[IF_MAX_LUTSIZE+1][IF_MAX_LUTSIZE+1];// the delays of LUTs }; // manager struct If_Man_t_ { char * pName; // mapping parameters If_Par_t * pPars; // mapping nodes If_Obj_t * pConst1; // the constant 1 node Vec_Ptr_t * vCis; // the primary inputs Vec_Ptr_t * vCos; // the primary outputs Vec_Ptr_t * vObjs; // all objects Vec_Ptr_t * vObjsRev; // reverse topological order of objects Vec_Ptr_t * vTemp; // temporary array int nObjs[IF_VOID];// the number of objects by type // various data int nLevelMax; // the max number of AIG levels float fEpsilon; // epsilon used for comparison float RequiredGlo; // global required times float RequiredGlo2; // global required times float AreaGlo; // global area int nNets; // the sum total of fanins of all LUTs in the mapping float dPower; // the sum total of switching activities of all LUTs in the mapping int nCutsUsed; // the number of cuts currently used int nCutsMerged; // the total number of cuts merged unsigned * puTemp[4]; // used for the truth table computation word * puTempW; // used for the truth table computation int SortMode; // one of the three sorting modes int fNextRound; // set to 1 after the first round int nChoices; // the number of choice nodes Vec_Int_t * vSwitching; // switching activity of each node int pPerm[3][IF_MAX_LUTSIZE]; // permutations unsigned uSharedMask; // mask of shared variables int nShared; // the number of shared variables int fReqTimeWarn; // warning about exceeding required times was printed // SOP balancing Vec_Int_t * vCover; // used to compute ISOP Vec_Int_t * vArray; // intermediate storage Vec_Wrd_t * vAnds; // intermediate storage Vec_Wrd_t * vOrGate; // intermediate storage Vec_Wrd_t * vAndGate; // intermediate storage // sequential mapping Vec_Ptr_t * vLatchOrder; // topological ordering of latches Vec_Int_t * vLags; // sequentail lags of all nodes int nAttempts; // the number of attempts in binary search int nMaxIters; // the maximum number of iterations int Period; // the current value of the clock period (for seq mapping) // memory management int nTruth6Words[IF_MAX_FUNC_LUTSIZE+1]; // the size of the truth table if allocated int nPermWords; // the size of the permutation array (in words) int nObjBytes; // the size of the object int nCutBytes; // the size of the cut int nSetBytes; // the size of the cut set Mem_Fixed_t * pMemObj; // memory manager for objects (entrysize = nEntrySize) Mem_Fixed_t * pMemSet; // memory manager for sets of cuts (entrysize = nCutSize*(nCutsMax+1)) If_Set_t * pMemCi; // memory for CI cutsets If_Set_t * pMemAnd; // memory for AND cutsets If_Set_t * pFreeList; // the list of free cutsets int nSmallSupp; // the small support int nCutsTotal; int nCutsUseless[32]; int nCutsCount[32]; int nCutsCountAll; int nCutsUselessAll; int nCuts5, nCuts5a; If_DsdMan_t * pIfDsdMan; // DSD manager Vec_Mem_t * vTtMem[IF_MAX_FUNC_LUTSIZE+1]; // truth table memory and hash table Vec_Wec_t * vTtIsops[IF_MAX_FUNC_LUTSIZE+1]; // mapping of truth table into DSD Vec_Int_t * vTtDsds[IF_MAX_FUNC_LUTSIZE+1]; // mapping of truth table into DSD Vec_Str_t * vTtPerms[IF_MAX_FUNC_LUTSIZE+1]; // mapping of truth table into permutations Vec_Str_t * vTtVars[IF_MAX_FUNC_LUTSIZE+1]; // mapping of truth table into selected vars Vec_Int_t * vTtDecs[IF_MAX_FUNC_LUTSIZE+1]; // mapping of truth table into decomposition pattern Vec_Int_t * vTtOccurs[IF_MAX_FUNC_LUTSIZE+1];// truth table occurange counters Hash_IntMan_t * vPairHash; // hashing pairs of truth tables Vec_Int_t * vPairRes; // resulting truth table Vec_Str_t * vPairPerms; // resulting permutation char pCanonPerm[IF_MAX_LUTSIZE]; unsigned uCanonPhase; int nCacheHits; int nCacheMisses; abctime timeCache[6]; int nBestCutSmall[2]; int nCountNonDec[2]; Vec_Int_t * vCutData; // cut data storage int pArrTimeProfile[IF_MAX_FUNC_LUTSIZE]; Vec_Ptr_t * vVisited; // timing manager Tim_Man_t * pManTim; Vec_Int_t * vCoAttrs; // CO attributes 0=optimize; 1=keep; 2=relax // hash table for functions int nTableSize[2]; // hash table size int nTableEntries[2]; // hash table entries void ** pHashTable[2]; // hash table bins Mem_Fixed_t * pMemEntries; // memory manager for hash table entries // statistics // abctime timeTruth; }; // priority cut struct If_Cut_t_ { float Area; // area (or area-flow) of the cut float Edge; // the edge flow float Power; // the power flow float Delay; // delay of the cut int iCutFunc; // TT ID of the cut int uMaskFunc; // polarity bitmask unsigned uSign; // cut signature unsigned Cost : 12; // the user's cost of the cut (related to IF_COST_MAX) unsigned fCompl : 1; // the complemented attribute unsigned fUser : 1; // using the user's area and delay unsigned fUseless: 1; // cannot be used in the mapping unsigned fAndCut : 1; // matched with AND gate unsigned nLimit : 8; // the maximum number of leaves unsigned nLeaves : 8; // the number of leaves int pLeaves[0]; }; // set of priority cut struct If_Set_t_ { short nCutsMax; // the max number of cuts short nCuts; // the current number of cuts If_Set_t * pNext; // next cutset in the free list If_Cut_t ** ppCuts; // the array of pointers to the cuts }; // node extension struct If_Obj_t_ { unsigned Type : 4; // object unsigned fCompl0 : 1; // complemented attribute unsigned fCompl1 : 1; // complemented attribute unsigned fPhase : 1; // phase of the node unsigned fRepr : 1; // representative of the equivalence class unsigned fMark : 1; // multipurpose mark unsigned fVisit : 1; // multipurpose mark unsigned fSpec : 1; // multipurpose mark unsigned fDriver : 1; // multipurpose mark unsigned fSkipCut: 1; // multipurpose mark unsigned Level : 19; // logic level of the node int Id; // integer ID int IdPio; // integer ID of PIs/POs int nRefs; // the number of references int nVisits; // the number of visits to this node int nVisitsCopy; // the number of visits to this node If_Obj_t * pFanin0; // the first fanin If_Obj_t * pFanin1; // the second fanin If_Obj_t * pEquiv; // the choice node float EstRefs; // estimated reference counter float Required; // required time of the onde float LValue; // sequential arrival time of the node union{ void * pCopy; // used for object duplication int iCopy; }; If_Set_t * pCutSet; // the pointer to the cutset If_Cut_t CutBest; // the best cut selected }; typedef struct If_Box_t_ If_Box_t; struct If_Box_t_ { char * pName; char fSeq; char fBlack; char fOuter; char fUnused; int Id; int nPis; int nPos; int * pDelays; }; struct If_LibBox_t_ { Vec_Ptr_t * vBoxes; }; static inline If_Obj_t * If_Regular( If_Obj_t * p ) { return (If_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline If_Obj_t * If_Not( If_Obj_t * p ) { return (If_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline If_Obj_t * If_NotCond( If_Obj_t * p, int c ) { return (If_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int If_IsComplement( If_Obj_t * p ) { return (int )(((ABC_PTRUINT_T)p) & 01); } static inline int If_ManCiNum( If_Man_t * p ) { return p->nObjs[IF_CI]; } static inline int If_ManCoNum( If_Man_t * p ) { return p->nObjs[IF_CO]; } static inline int If_ManAndNum( If_Man_t * p ) { return p->nObjs[IF_AND]; } static inline int If_ManObjNum( If_Man_t * p ) { return Vec_PtrSize(p->vObjs); } static inline If_Obj_t * If_ManConst1( If_Man_t * p ) { return p->pConst1; } static inline If_Obj_t * If_ManCi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i ); } static inline If_Obj_t * If_ManCo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i ); } static inline If_Obj_t * If_ManLi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, If_ManCoNum(p) - p->pPars->nLatchesCo + i ); } static inline If_Obj_t * If_ManLo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, If_ManCiNum(p) - p->pPars->nLatchesCi + i ); } static inline If_Obj_t * If_ManObj( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } static inline int If_ObjIsConst1( If_Obj_t * pObj ) { return pObj->Type == IF_CONST1; } static inline int If_ObjIsCi( If_Obj_t * pObj ) { return pObj->Type == IF_CI; } static inline int If_ObjIsCo( If_Obj_t * pObj ) { return pObj->Type == IF_CO; } static inline int If_ObjIsTerm( If_Obj_t * pObj ) { return pObj->Type == IF_CI || pObj->Type == IF_CO; } static inline int If_ObjIsLatch( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 != NULL; } static inline int If_ObjIsAnd( If_Obj_t * pObj ) { return pObj->Type == IF_AND; } static inline int If_ObjId( If_Obj_t * pObj ) { return pObj->Id; } static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj ) { return pObj->pFanin0; } static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj ) { return pObj->pFanin1; } static inline int If_ObjFaninC0( If_Obj_t * pObj ) { return pObj->fCompl0; } static inline int If_ObjFaninC1( If_Obj_t * pObj ) { return pObj->fCompl1; } static inline void * If_ObjCopy( If_Obj_t * pObj ) { return pObj->pCopy; } static inline int If_ObjLevel( If_Obj_t * pObj ) { return pObj->Level; } static inline void If_ObjSetLevel( If_Obj_t * pObj, int Level ) { pObj->Level = Level; } static inline void If_ObjSetCopy( If_Obj_t * pObj, void * pCopy ) { pObj->pCopy = pCopy; } static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu; } static inline int If_CutLeaveNum( If_Cut_t * pCut ) { return pCut->nLeaves; } static inline int * If_CutLeaves( If_Cut_t * pCut ) { return pCut->pLeaves; } static inline If_Obj_t * If_CutLeaf( If_Man_t * p, If_Cut_t * pCut, int i ) { assert(i >= 0 && i < (int)pCut->nLeaves); return If_ManObj(p, pCut->pLeaves[i]); } static inline unsigned If_CutSuppMask( If_Cut_t * pCut ) { return (~(unsigned)0) >> (32-pCut->nLeaves); } static inline int If_CutTruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 2 : (1 << (nVarsMax - 5)); } static inline int If_CutPermWords( int nVarsMax ) { return nVarsMax / sizeof(int) + ((nVarsMax % sizeof(int)) > 0); } static inline int If_CutLeafBit( If_Cut_t * pCut, int i ) { return (pCut->uMaskFunc >> i) & 1; } static inline char * If_CutPerm( If_Cut_t * pCut ) { return (char *)(pCut->pLeaves + pCut->nLeaves); } static inline void If_CutCopy( If_Man_t * p, If_Cut_t * pDst, If_Cut_t * pSrc ) { memcpy( pDst, pSrc, p->nCutBytes ); } static inline void If_CutSetup( If_Man_t * p, If_Cut_t * pCut ) { memset(pCut, 0, p->nCutBytes); pCut->nLimit = p->pPars->nLutSize; } static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return &pObj->CutBest; } static inline unsigned If_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId % 31)); } static inline unsigned If_ObjCutSignCompute( If_Cut_t * p ) { unsigned s = 0; int i; for ( i = 0; i < If_CutLeaveNum(p); i++ ) s |= If_ObjCutSign(p->pLeaves[i]); return s; } static inline float If_ObjArrTime( If_Obj_t * pObj ) { return If_ObjCutBest(pObj)->Delay; } static inline void If_ObjSetArrTime( If_Obj_t * pObj, float ArrTime ) { If_ObjCutBest(pObj)->Delay = ArrTime; } static inline float If_ObjLValue( If_Obj_t * pObj ) { return pObj->LValue; } static inline void If_ObjSetLValue( If_Obj_t * pObj, float LValue ) { pObj->LValue = LValue; } static inline void * If_CutData( If_Cut_t * pCut ) { return *(void **)pCut; } static inline void If_CutSetData( If_Cut_t * pCut, void * pData ) { *(void **)pCut = pData; } static inline int If_CutDataInt( If_Cut_t * pCut ) { return *(int *)pCut; } static inline void If_CutSetDataInt( If_Cut_t * pCut, int Data ) { *(int *)pCut = Data; } static inline int If_CutTruthLit( If_Cut_t * pCut ) { assert( pCut->iCutFunc >= 0 ); return pCut->iCutFunc; } static inline int If_CutTruthIsCompl( If_Cut_t * pCut ) { assert( pCut->iCutFunc >= 0 ); return Abc_LitIsCompl(pCut->iCutFunc); } static inline word * If_CutTruthWR( If_Man_t * p, If_Cut_t * pCut ) { return p->vTtMem[pCut->nLeaves] ? Vec_MemReadEntry(p->vTtMem[pCut->nLeaves], Abc_Lit2Var(pCut->iCutFunc)) : NULL; } static inline unsigned * If_CutTruthUR( If_Man_t * p, If_Cut_t * pCut) { return (unsigned *)If_CutTruthWR(p, pCut); } static inline word * If_CutTruthW( If_Man_t * p, If_Cut_t * pCut ) { assert( pCut->iCutFunc >= 0 ); Abc_TtCopy( p->puTempW, If_CutTruthWR(p, pCut), p->nTruth6Words[pCut->nLeaves], If_CutTruthIsCompl(pCut) ); return p->puTempW; } static inline unsigned * If_CutTruth( If_Man_t * p, If_Cut_t * pCut ) { return (unsigned *)If_CutTruthW(p, pCut); } static inline int If_CutDsdLit( If_Man_t * p, If_Cut_t * pCut ) { return Abc_Lit2LitL( Vec_IntArray(p->vTtDsds[pCut->nLeaves]), If_CutTruthLit(pCut) ); } static inline int If_CutDsdIsCompl( If_Man_t * p, If_Cut_t * pCut ) { return Abc_LitIsCompl( If_CutDsdLit(p, pCut) ); } static inline char * If_CutDsdPerm( If_Man_t * p, If_Cut_t * pCut ) { return Vec_StrEntryP( p->vTtPerms[pCut->nLeaves], Abc_Lit2Var(pCut->iCutFunc) * Abc_MaxInt(6, pCut->nLeaves) ); } static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return pCut->fAndCut ? p->pPars->nAndArea : (pCut->fUser? (float)pCut->Cost : (p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0)); } static inline float If_CutLutDelay( If_LibLut_t * p, int Size, int iPin ) { return p ? (p->fVarPinDelays ? p->pLutDelays[Size][iPin] : p->pLutDelays[Size][0]) : 1.0; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define IF_MIN(a,b) (((a) < (b))? (a) : (b)) #define IF_MAX(a,b) (((a) > (b))? (a) : (b)) // the small and large numbers (min/max float are 1.17e-38/3.40e+38) #define IF_FLOAT_LARGE ((float)1.0e+20) #define IF_FLOAT_SMALL ((float)1.0e-20) #define IF_INT_LARGE (10000000) // iterator over the primary inputs #define If_ManForEachCi( p, pObj, i ) \ Vec_PtrForEachEntry( If_Obj_t *, p->vCis, pObj, i ) // iterator over the primary outputs #define If_ManForEachCo( p, pObj, i ) \ Vec_PtrForEachEntry( If_Obj_t *, p->vCos, pObj, i ) // iterator over the primary inputs #define If_ManForEachPi( p, pObj, i ) \ Vec_PtrForEachEntryStop( If_Obj_t *, p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatchesCi - p->pPars->nLatchesCiBox ) // iterator over the primary outputs #define If_ManForEachPo( p, pObj, i ) \ Vec_PtrForEachEntryStartStop( If_Obj_t *, p->vCos, pObj, i, p->pPars->nLatchesCoBox, If_ManCoNum(p) - p->pPars->nLatchesCo ) // iterator over the latches #define If_ManForEachLatchInput( p, pObj, i ) \ Vec_PtrForEachEntryStart( If_Obj_t *, p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatchesCo ) #define If_ManForEachLatchOutput( p, pObj, i ) \ Vec_PtrForEachEntryStartStop( If_Obj_t *, p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatchesCi - p->pPars->nLatchesCiBox, If_ManCiNum(p) - p->pPars->nLatchesCiBox ) // iterator over all objects in topological order #define If_ManForEachObj( p, pObj, i ) \ Vec_PtrForEachEntry( If_Obj_t *, p->vObjs, pObj, i ) // iterator over all objects in reverse topological order #define If_ManForEachObjReverse( p, pObj, i ) \ Vec_PtrForEachEntry( If_Obj_t *, p->vObjsRev, pObj, i ) // iterator over logic nodes #define If_ManForEachNode( p, pObj, i ) \ If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else // iterator over cuts of the node #define If_ObjForEachCut( pObj, pCut, i ) \ for ( i = 0; (i < (pObj)->pCutSet->nCuts) && ((pCut) = (pObj)->pCutSet->ppCuts[i]); i++ ) // iterator over the leaves of the cut #define If_CutForEachLeaf( p, pCut, pLeaf, i ) \ for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ ) #define If_CutForEachLeafReverse( p, pCut, pLeaf, i ) \ for ( i = (int)(pCut)->nLeaves - 1; (i >= 0) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i-- ) //#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \ \\prevent multiline comment // for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, p->pPars->fLiftLeaves? (pCut)->pLeaves[i] >> 8 : (pCut)->pLeaves[i])); i++ ) // iterator over the leaves of the sequential cut #define If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i ) \ for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i] >> 8)) && (((Shift) = ((pCut)->pLeaves[i] & 255)) >= 0); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== ifCore.c ===========================================================*/ extern void If_ManSetDefaultPars( If_Par_t * pPars ); extern int If_ManPerformMapping( If_Man_t * p ); extern int If_ManPerformMappingComb( If_Man_t * p ); extern void If_ManComputeSwitching( If_Man_t * p ); /*=== ifCut.c ============================================================*/ extern int If_CutVerifyCuts( If_Set_t * pCutSet, int fOrdered ); extern int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut, int fSaveCut0 ); extern void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ); extern void If_CutOrder( If_Cut_t * pCut ); extern int If_CutMergeOrdered( If_Man_t * p, If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut ); extern int If_CutMerge( If_Man_t * p, If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut ); extern int If_CutCheck( If_Cut_t * pCut ); extern void If_CutPrint( If_Cut_t * pCut ); extern void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut ); extern void If_CutLift( If_Cut_t * pCut ); extern void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc ); extern float If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutPowerFlow( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); extern float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut ); extern float If_CutPowerDeref( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); extern float If_CutPowerRef( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); extern float If_CutPowerDerefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); extern float If_CutPowerRefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ); /*=== ifDec.c =============================================================*/ extern word If_CutPerformDerive07( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck07( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck08( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck10( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck16( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern float If_CutDelayLutStruct( If_Man_t * p, If_Cut_t * pCut, char * pStr, float WireDelay ); extern int If_CluCheckExt( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutRoot, char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 ); extern int If_CluCheckExt3( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, char * pLut0, char * pLut1, char * pLut2, word * pFunc0, word * pFunc1, word * pFunc2 ); /*=== ifDelay.c =============================================================*/ extern int If_CutDelaySop( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutSopBalanceEvalInt( Vec_Int_t * vCover, int * pTimes, int * pFaninLits, Vec_Int_t * vAig, int * piRes, int nSuppAll, int * pArea ); extern int If_CutSopBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig ); extern int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * pTimes, word * pFaninRes, int nSuppAll, word * pRes ); extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); /*=== ifDsd.c =============================================================*/ extern If_DsdMan_t * If_DsdManAlloc( int nVars, int nLutSize ); extern void If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize ); extern void If_DsdManPrint( If_DsdMan_t * p, char * pFileName, int Number, int Support, int fOccurs, int fTtDump, int fVerbose ); extern void If_DsdManTune( If_DsdMan_t * p, int LutSize, int fFast, int fAdd, int fSpec, int fVerbose ); extern void Id_DsdManTuneStr( If_DsdMan_t * p, char * pStruct, int nConfls, int nProcs, int fVerbose ); extern void If_DsdManFree( If_DsdMan_t * p, int fVerbose ); extern void If_DsdManSave( If_DsdMan_t * p, char * pFileName ); extern If_DsdMan_t * If_DsdManLoad( char * pFileName ); extern void If_DsdManMerge( If_DsdMan_t * p, If_DsdMan_t * pNew ); extern void If_DsdManCleanOccur( If_DsdMan_t * p, int fVerbose ); extern void If_DsdManCleanMarks( If_DsdMan_t * p, int fVerbose ); extern void If_DsdManInvertMarks( If_DsdMan_t * p, int fVerbose ); extern If_DsdMan_t * If_DsdManFilter( If_DsdMan_t * p, int Limit ); extern int If_DsdManCompute( If_DsdMan_t * p, word * pTruth, int nLeaves, unsigned char * pPerm, char * pLutStruct ); extern char * If_DsdManFileName( If_DsdMan_t * p ); extern int If_DsdManVarNum( If_DsdMan_t * p ); extern int If_DsdManObjNum( If_DsdMan_t * p ); extern int If_DsdManLutSize( If_DsdMan_t * p ); extern int If_DsdManTtBitNum( If_DsdMan_t * p ); extern int If_DsdManPermBitNum( If_DsdMan_t * p ); extern void If_DsdManSetLutSize( If_DsdMan_t * p, int nLutSize ); extern int If_DsdManSuppSize( If_DsdMan_t * p, int iDsd ); extern int If_DsdManCheckDec( If_DsdMan_t * p, int iDsd ); extern int If_DsdManReadMark( If_DsdMan_t * p, int iDsd ); extern void If_DsdManSetNewAsUseless( If_DsdMan_t * p ); extern word * If_DsdManGetFuncConfig( If_DsdMan_t * p, int iDsd ); extern char * If_DsdManGetCellStr( If_DsdMan_t * p ); extern unsigned If_DsdManCheckXY( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, unsigned uMaskNot, int fHighEffort, int fVerbose ); extern int If_CutDsdBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig ); extern int If_CutDsdBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ); extern void Id_DsdManTuneThresh( If_DsdMan_t * p, int fUnate, int fThresh, int fThreshHeuristic, int fVerbose ); /*=== ifLib.c =============================================================*/ extern If_LibLut_t * If_LibLutRead( char * FileName ); extern If_LibLut_t * If_LibLutDup( If_LibLut_t * p ); extern void If_LibLutFree( If_LibLut_t * pLutLib ); extern void If_LibLutPrint( If_LibLut_t * pLutLib ); extern int If_LibLutDelaysAreDiscrete( If_LibLut_t * pLutLib ); extern int If_LibLutDelaysAreDifferent( If_LibLut_t * pLutLib ); extern If_LibLut_t * If_LibLutSetSimple( int nLutSize ); extern float If_LibLutFastestPinDelay( If_LibLut_t * p ); extern float If_LibLutSlowestPinDelay( If_LibLut_t * p ); /*=== ifLibBox.c =============================================================*/ extern If_LibBox_t * If_LibBoxStart(); extern void If_LibBoxFree( If_LibBox_t * p ); extern If_Box_t * If_LibBoxReadBox( If_LibBox_t * p, int Id ); extern If_Box_t * If_LibBoxFindBox( If_LibBox_t * p, char * pName ); extern void If_LibBoxAdd( If_LibBox_t * p, If_Box_t * pBox ); extern If_LibBox_t * If_LibBoxRead( char * pFileName ); extern If_LibBox_t * If_LibBoxRead2( char * pFileName ); extern void If_LibBoxPrint( FILE * pFile, If_LibBox_t * p ); extern void If_LibBoxWrite( char * pFileName, If_LibBox_t * p ); extern int If_LibBoxLoad( char * pFileName ); /*=== ifMan.c =============================================================*/ extern If_Man_t * If_ManStart( If_Par_t * pPars ); extern void If_ManRestart( If_Man_t * p ); extern void If_ManStop( If_Man_t * p ); extern If_Obj_t * If_ManCreateCi( If_Man_t * p ); extern If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver ); extern If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ); extern If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ); extern If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl ); extern void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pRepr ); extern void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId ); extern void If_ManSetupCiCutSets( If_Man_t * p ); extern If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj ); extern void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj ); extern void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj ); extern void If_ManSetupSetAll( If_Man_t * p, int nCrossCut ); /*=== ifMap.c =============================================================*/ extern int * If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut ); extern void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess, int fFirst ); extern void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ); extern int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, int fFirst, char * pLabel ); /*=== ifReduce.c ==========================================================*/ extern void If_ManImproveMapping( If_Man_t * p ); /*=== ifSat.c ==========================================================*/ extern void * If_ManSatBuildXY( int nLutSize ); extern void * If_ManSatBuildXYZ( int nLutSize ); extern void If_ManSatUnbuild( void * p ); extern int If_ManSatCheckXY( void * pSat, int nLutSize, word * pTruth, int nVars, unsigned uSet, word * pTBound, word * pTFree, Vec_Int_t * vLits ); extern unsigned If_ManSatCheckXYall( void * pSat, int nLutSize, word * pTruth, int nVars, Vec_Int_t * vLits ); /*=== ifSeq.c =============================================================*/ extern int If_ManPerformMappingSeq( If_Man_t * p ); /*=== ifTime.c ============================================================*/ extern float If_CutDelay( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut ); extern void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, float Required ); extern float If_ManDelayMax( If_Man_t * p, int fSeq ); extern void If_ManComputeRequired( If_Man_t * p ); /*=== ifTruth.c ===========================================================*/ extern void If_CutRotatePins( If_Man_t * p, If_Cut_t * pCut ); extern int If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ); extern int If_CutComputeTruthPerm( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ); /*=== ifTune.c ===========================================================*/ extern Ifn_Ntk_t * Ifn_NtkParse( char * pStr ); extern int Ifn_NtkTtBits( char * pStr ); extern int Ifn_NtkMatch( Ifn_Ntk_t * p, word * pTruth, int nVars, int nConfls, int fVerbose, int fVeryVerbose, word * pConfig ); extern void Ifn_NtkPrint( Ifn_Ntk_t * p ); extern int Ifn_NtkLutSizeMax( Ifn_Ntk_t * p ); extern int Ifn_NtkInputNum( Ifn_Ntk_t * p ); extern void * If_ManSatBuildFromCell( char * pStr, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars, Ifn_Ntk_t ** ppNtk ); extern int If_ManSatFindCofigBits( void * pSat, Vec_Int_t * vPiVars, Vec_Int_t * vPoVars, word * pTruth, int nVars, word Perm, int nInps, Vec_Int_t * vValues ); extern int If_ManSatDeriveGiaFromBits( void * pNew, Ifn_Ntk_t * p, word * pTtData, Vec_Int_t * vLeaves, Vec_Int_t * vValues ); extern void * If_ManDeriveGiaFromCells( void * p ); /*=== ifUtil.c ============================================================*/ extern void If_ManCleanNodeCopy( If_Man_t * p ); extern void If_ManCleanCutData( If_Man_t * p ); extern void If_ManCleanMarkV( If_Man_t * p ); extern float If_ManScanMapping( If_Man_t * p ); extern float If_ManScanMappingDirect( If_Man_t * p ); extern float If_ManScanMappingSeq( If_Man_t * p ); extern void If_ManResetOriginalRefs( If_Man_t * p ); extern int If_ManCrossCut( If_Man_t * p ); extern Vec_Ptr_t * If_ManReverseOrder( If_Man_t * p ); extern void If_ManMarkMapping( If_Man_t * p ); extern Vec_Ptr_t * If_ManCollectMappingDirect( If_Man_t * p ); extern Vec_Int_t * If_ManCollectMappingInt( If_Man_t * p ); extern int If_ManCountSpecialPos( If_Man_t * p ); extern void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ); extern void If_ObjPrint( If_Obj_t * pObj ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifCache.c000066400000000000000000000064661300674244400227110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifCache.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifCache.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "misc/vec/vecHsh.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCacheRecord( If_Man_t * p, int iDsd0, int iDsd1, int nShared, int iDsd ) { assert( nShared >= 0 && nShared <= p->pPars->nLutSize ); if ( p->vCutData == NULL ) p->vCutData = Vec_IntAlloc( 10000 ); if ( iDsd0 > iDsd1 ) ABC_SWAP( int, iDsd0, iDsd1 ); Vec_IntPush( p->vCutData, iDsd0 ); Vec_IntPush( p->vCutData, iDsd1 ); Vec_IntPush( p->vCutData, nShared ); Vec_IntPush( p->vCutData, iDsd ); // printf( "%6d %6d %6d %6d\n", iDsd0, iDsd1, nShared, iDsd ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCacheAnalize( If_Man_t * p ) { Vec_Int_t * vRes, * vTest[32]; int i, Entry, uUnique; vRes = Hsh_IntManHashArray( p->vCutData, 4 ); for ( i = 0; i <= p->pPars->nLutSize; i++ ) vTest[i] = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( vRes, Entry, i ) Vec_IntPush( vTest[Vec_IntEntry(p->vCutData, 4*i+2)], Entry ); for ( i = 0; i <= p->pPars->nLutSize; i++ ) { uUnique = Vec_IntCountUnique(vTest[i]); printf( "%2d-var entries = %8d. (%6.2f %%) Unique entries = %8d. (%6.2f %%)\n", i, Vec_IntSize(vTest[i]), 100.0*Vec_IntSize(vTest[i])/Abc_MaxInt(1, Vec_IntSize(vRes)), uUnique, 100.0*uUnique/Abc_MaxInt(1, Vec_IntSize(vTest[i])) ); } for ( i = 0; i <= p->pPars->nLutSize; i++ ) Vec_IntFree( vTest[i] ); uUnique = Vec_IntCountUnique(vRes); printf( "Total entries = %8d. (%6.2f %%) Unique entries = %8d. (%6.2f %%)\n", Vec_IntSize(p->vCutData)/4, 100.0, uUnique, 100.0*uUnique/Abc_MaxInt(1, Vec_IntSize(p->vCutData)/4) ); Vec_IntFree( vRes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifCheck.c000066400000000000000000000140321300674244400227070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifCheck.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Sequential mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifCheck.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef WIN32 typedef unsigned __int64 word; #else typedef unsigned long long word; #endif // elementary truth tables static word Truths6[6] = { 0xAAAAAAAAAAAAAAAA, 0xCCCCCCCCCCCCCCCC, 0xF0F0F0F0F0F0F0F0, 0xFF00FF00FF00FF00, 0xFFFF0000FFFF0000, 0xFFFFFFFF00000000 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if the node Leaf is reachable on the path.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManCutReach_rec( If_Obj_t * pPath, If_Obj_t * pLeaf ) { if ( pPath == pLeaf ) return 1; if ( pPath->fMark ) return 0; assert( If_ObjIsAnd(pPath) ); if ( If_ManCutReach_rec( If_ObjFanin0(pPath), pLeaf ) ) return 1; if ( If_ManCutReach_rec( If_ObjFanin1(pPath), pLeaf ) ) return 1; return 0; } int If_ManCutReach( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pPath, If_Obj_t * pLeaf ) { If_Obj_t * pTemp; int i, RetValue; If_CutForEachLeaf( p, pCut, pTemp, i ) pTemp->fMark = 1; RetValue = If_ManCutReach_rec( pPath, pLeaf ); If_CutForEachLeaf( p, pCut, pTemp, i ) pTemp->fMark = 0; return RetValue; } /**Function************************************************************* Synopsis [Derive truth table for each cofactor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManCutTruthCheck_rec( If_Obj_t * pObj, word * pTruths ) { word T0, T1; if ( pObj->fMark ) return pTruths[If_ObjId(pObj)]; assert( If_ObjIsAnd(pObj) ); T0 = If_ManCutTruthCheck_rec( If_ObjFanin0(pObj), pTruths ); T1 = If_ManCutTruthCheck_rec( If_ObjFanin1(pObj), pTruths ); T0 = If_ObjFaninC0(pObj) ? ~T0 : T0; T1 = If_ObjFaninC1(pObj) ? ~T1 : T1; return T0 & T1; } int If_ManCutTruthCheck( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, If_Obj_t * pLeaf, int Cof, word * pTruths ) { word Truth; If_Obj_t * pTemp; int i, k = 0; assert( Cof == 0 || Cof == 1 ); If_CutForEachLeaf( p, pCut, pTemp, i ) { assert( pTemp->fMark == 0 ); pTemp->fMark = 1; if ( pLeaf == pTemp ) pTruths[If_ObjId(pTemp)] = (Cof ? ~((word)0) : 0); else pTruths[If_ObjId(pTemp)] = Truths6[k++] ; } assert( k + 1 == If_CutLeaveNum(pCut) ); // compute truth table Truth = If_ManCutTruthCheck_rec( pObj, pTruths ); If_CutForEachLeaf( p, pCut, pTemp, i ) pTemp->fMark = 0; return Truth == 0 || Truth == ~((word)0); } /**Function************************************************************* Synopsis [Checks if cut can be structurally/functionally decomposed.] Description [The decomposition is Fn(a,b,c,...) = F2(a, Fn-1(b,c,...)).] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCutCheck( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut ) { static int nDecCalls = 0; static int nDecStruct = 0; static int nDecStruct2 = 0; static int nDecFunction = 0; word * pTruths; If_Obj_t * pLeaf, * pPath; int i; if ( pCut == NULL ) { printf( "DecStr = %9d (%6.2f %%).\n", nDecStruct, 100.0*nDecStruct/nDecCalls ); printf( "DecStr2 = %9d (%6.2f %%).\n", nDecStruct2, 100.0*nDecStruct2/nDecCalls ); printf( "DecFunc = %9d (%6.2f %%).\n", nDecFunction, 100.0*nDecFunction/nDecCalls ); printf( "Total = %9d (%6.2f %%).\n", nDecCalls, 100.0*nDecCalls/nDecCalls ); return; } assert( If_ObjIsAnd(pObj) ); assert( pCut->nLeaves <= 7 ); nDecCalls++; // check structural decomposition If_CutForEachLeaf( p, pCut, pLeaf, i ) if ( pLeaf == If_ObjFanin0(pObj) || pLeaf == If_ObjFanin1(pObj) ) break; if ( i < If_CutLeaveNum(pCut) ) { pPath = (pLeaf == If_ObjFanin0(pObj)) ? If_ObjFanin1(pObj) : If_ObjFanin0(pObj); if ( !If_ManCutReach( p, pCut, pPath, pLeaf ) ) { nDecStruct++; // nDecFunction++; // return; } else nDecStruct2++; } // check functional decomposition pTruths = malloc( sizeof(word) * If_ManObjNum(p) ); If_CutForEachLeaf( p, pCut, pLeaf, i ) { if ( If_ManCutTruthCheck( p, pObj, pCut, pLeaf, 0, pTruths ) ) { nDecFunction++; break; } if ( If_ManCutTruthCheck( p, pObj, pCut, pLeaf, 1, pTruths ) ) { nDecFunction++; break; } } free( pTruths ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifCom.c000066400000000000000000000257131300674244400224200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifCom.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Command handlers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifCom.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int If_CommandReadLut ( Abc_Frame_t * pAbc, int argc, char **argv ); static int If_CommandPrintLut( Abc_Frame_t * pAbc, int argc, char **argv ); static int If_CommandReadBox ( Abc_Frame_t * pAbc, int argc, char **argv ); static int If_CommandPrintBox( Abc_Frame_t * pAbc, int argc, char **argv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Package initialization procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_Init( Abc_Frame_t * pAbc ) { // set the default library If_LibLut_t s_LutLib = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} }; Abc_FrameSetLibLut( If_LibLutDup(&s_LutLib) ); Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut", If_CommandReadLut, 0 ); Cmd_CommandAdd( pAbc, "FPGA mapping", "print_lut", If_CommandPrintLut, 0 ); Cmd_CommandAdd( pAbc, "FPGA mapping", "read_box", If_CommandReadBox, 0 ); Cmd_CommandAdd( pAbc, "FPGA mapping", "print_box", If_CommandPrintBox, 0 ); } /**Function************************************************************* Synopsis [Package ending procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_End( Abc_Frame_t * pAbc ) { If_LibLutFree( (If_LibLut_t *) Abc_FrameReadLibLut() ); If_LibBoxFree( (If_LibBox_t *)Abc_FrameReadLibBox() ); } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CommandReadLut( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; If_LibLut_t * pLib; Abc_Ntk_t * pNet; char * FileName; int fVerbose; int c; pNet = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) ) fprintf( pErr, "Did you mean \"%s\"?", FileName ); fprintf( pErr, "\n" ); return 1; } fclose( pFile ); // set the new network pLib = If_LibLutRead( FileName ); if ( pLib == NULL ) { fprintf( pErr, "Reading LUT library has failed.\n" ); goto usage; } // replace the current library If_LibLutFree( (If_LibLut_t *)Abc_FrameReadLibLut() ); Abc_FrameSetLibLut( pLib ); return 0; usage: fprintf( pErr, "\nusage: read_lut [-vh]\n"); fprintf( pErr, "\t read the LUT library from the file\n" ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\t \n"); fprintf( pErr, "\t File format for a LUT library:\n"); fprintf( pErr, "\t (the default library is shown)\n"); fprintf( pErr, "\t \n"); fprintf( pErr, "\t # The area/delay of k-variable LUTs:\n"); fprintf( pErr, "\t # k area delay\n"); fprintf( pErr, "\t 1 1 1\n"); fprintf( pErr, "\t 2 2 2\n"); fprintf( pErr, "\t 3 4 3\n"); fprintf( pErr, "\t 4 8 4\n"); fprintf( pErr, "\t 5 16 5\n"); fprintf( pErr, "\t 6 32 6\n"); return 1; /* error exit */ } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CommandPrintLut( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNet; int fVerbose; int c; pNet = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind ) goto usage; // set the new network If_LibLutPrint( (If_LibLut_t *)Abc_FrameReadLibLut() ); return 0; usage: fprintf( pErr, "\nusage: print_lut [-vh]\n"); fprintf( pErr, "\t print the current LUT library\n" ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; /* error exit */ } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CommandReadBox( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; If_LibBox_t * pLib; Abc_Ntk_t * pNet; char * FileName; int fExtended; int fVerbose; int c; pNet = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fExtended = 0; fVerbose = 1; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "evh")) != EOF ) { switch (c) { case 'e': fExtended ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) ) fprintf( pErr, "Did you mean \"%s\"?", FileName ); fprintf( pErr, "\n" ); return 1; } fclose( pFile ); // set the new network pLib = fExtended ? If_LibBoxRead2( FileName ) : If_LibBoxRead( FileName ); if ( pLib == NULL ) { fprintf( pErr, "Reading box library has failed.\n" ); goto usage; } // replace the current library If_LibBoxFree( (If_LibBox_t *)Abc_FrameReadLibBox() ); Abc_FrameSetLibBox( pLib ); return 0; usage: fprintf( pErr, "\nusage: read_box [-evh]\n"); fprintf( pErr, "\t read the box library from the file\n" ); fprintf( pErr, "\t-e : toggles reading extended format [default = %s]\n", (fExtended? "yes" : "no") ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; /* error exit */ } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CommandPrintBox( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNet; int fVerbose; int c; pNet = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind ) goto usage; // set the new network If_LibBoxPrint( stdout, (If_LibBox_t *)Abc_FrameReadLibBox() ); return 0; usage: fprintf( pErr, "\nusage: print_box [-vh]\n"); fprintf( pErr, "\t print the current box library\n" ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; /* error exit */ } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifCore.c000066400000000000000000000135061300674244400225670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [The central part of the mapper.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifCore.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern abctime s_MappingTime; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetDefaultPars( If_Par_t * pPars ) { memset( pPars, 0, sizeof(If_Par_t) ); pPars->nLutSize = -1; pPars->nCutsMax = 8; pPars->nFlowIters = 1; pPars->nAreaIters = 2; pPars->DelayTarget = -1; pPars->Epsilon = (float)0.005; pPars->fPreprocess = 1; pPars->fArea = 0; pPars->fFancy = 0; pPars->fExpRed = 1; pPars->fLatchPaths = 0; pPars->fEdge = 1; pPars->fPower = 0; pPars->fCutMin = 0; pPars->fBidec = 0; pPars->fVerbose = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPerformMapping( If_Man_t * p ) { p->pPars->fAreaOnly = p->pPars->fArea; // temporary // create the CI cutsets If_ManSetupCiCutSets( p ); // allocate memory for other cutsets If_ManSetupSetAll( p, If_ManCrossCut(p) ); // derive reverse top order p->vObjsRev = If_ManReverseOrder( p ); return If_ManPerformMappingComb( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPerformMappingComb( If_Man_t * p ) { If_Obj_t * pObj; abctime clkTotal = Abc_Clock(); int i; // set arrival times and fanout estimates If_ManForEachCi( p, pObj, i ) { If_ObjSetArrTime( pObj, p->pPars->pTimesArr ? p->pPars->pTimesArr[i] : (float)0.0 ); pObj->EstRefs = (float)1.0; } // delay oriented mapping if ( p->pPars->fPreprocess && !p->pPars->fArea ) { // map for delay If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 1, "Delay" ); // map for delay second option p->pPars->fFancy = 1; If_ManResetOriginalRefs( p ); If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 0, "Delay-2" ); p->pPars->fFancy = 0; // map for area p->pPars->fArea = 1; If_ManResetOriginalRefs( p ); If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 0, "Area" ); p->pPars->fArea = 0; } else If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, 1, "Delay" ); // try to improve area by expanding and reducing the cuts if ( p->pPars->fExpRed ) If_ManImproveMapping( p ); // area flow oriented mapping for ( i = 0; i < p->pPars->nFlowIters; i++ ) { If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, 0, "Flow" ); if ( p->pPars->fExpRed ) If_ManImproveMapping( p ); } // area oriented mapping for ( i = 0; i < p->pPars->nAreaIters; i++ ) { If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, 0, "Area" ); if ( p->pPars->fExpRed ) If_ManImproveMapping( p ); } if ( p->pPars->fVerbose ) { // Abc_Print( 1, "Total memory = %7.2f MB. Peak cut memory = %7.2f MB. ", // 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), // 1.0 * p->nSetBytes * Mem_FixedReadMaxEntriesUsed(p->pMemSet) / (1<<20) ); Abc_PrintTime( 1, "Total time", Abc_Clock() - clkTotal ); } // Abc_Print( 1, "Cross cut memory = %d.\n", Mem_FixedReadMaxEntriesUsed(p->pMemSet) ); s_MappingTime = Abc_Clock() - clkTotal; // Abc_Print( 1, "Special POs = %d.\n", If_ManCountSpecialPos(p) ); /* { static char * pLastName = NULL; FILE * pTable = fopen( "fpga/ucsb/stats.txt", "a+" ); if ( pLastName == NULL || strcmp(pLastName, p->pName) ) { fprintf( pTable, "\n" ); fprintf( pTable, "%s ", p->pName ); fprintf( pTable, "%d ", If_ManCiNum(p) ); fprintf( pTable, "%d ", If_ManCoNum(p) ); fprintf( pTable, "%d ", If_ManAndNum(p) ); ABC_FREE( pLastName ); pLastName = Abc_UtilStrsav( p->pName ); } fprintf( pTable, "%d ", (int)p->AreaGlo ); fprintf( pTable, "%d ", (int)p->RequiredGlo ); fclose( pTable ); } */ p->pPars->FinalDelay = p->RequiredGlo; p->pPars->FinalArea = p->AreaGlo; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifCount.h000066400000000000000000000421751300674244400230000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifCount.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifCount.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__if__if_Count_h #define ABC__map__if__if_Count_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_LogCreateAnd( Vec_Int_t * vAig, int iLit0, int iLit1, int nSuppAll ) { int iObjId = Vec_IntSize(vAig)/2 + nSuppAll; assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) ); Vec_IntPush( vAig, iLit0 ); Vec_IntPush( vAig, iLit1 ); return Abc_Var2Lit( iObjId, 0 ); } static inline int If_LogCreateMux( Vec_Int_t * vAig, int iLitC, int iLit1, int iLit0, int nSuppAll ) { int iFanLit0 = If_LogCreateAnd( vAig, iLitC, iLit1, nSuppAll ); int iFanLit1 = If_LogCreateAnd( vAig, Abc_LitNot(iLitC), iLit0, nSuppAll ); int iResLit = If_LogCreateAnd( vAig, Abc_LitNot(iFanLit0), Abc_LitNot(iFanLit1), nSuppAll ); return Abc_LitNot(iResLit); } static inline int If_LogCreateXor( Vec_Int_t * vAig, int iLit0, int iLit1, int nSuppAll ) { return If_LogCreateMux( vAig, iLit0, Abc_LitNot(iLit1), iLit1, nSuppAll ); } static inline int If_LogCreateAndXor( Vec_Int_t * vAig, int iLit0, int iLit1, int nSuppAll, int fXor ) { return fXor ? If_LogCreateXor(vAig, iLit0, iLit1, nSuppAll) : If_LogCreateAnd(vAig, iLit0, iLit1, nSuppAll); } static inline int If_LogCreateAndXorMulti( Vec_Int_t * vAig, int * pFaninLits, int nFanins, int nSuppAll, int fXor ) { int i; assert( nFanins > 0 ); for ( i = nFanins - 1; i > 0; i-- ) pFaninLits[i-1] = If_LogCreateAndXor( vAig, pFaninLits[i], pFaninLits[i-1], nSuppAll, fXor ); return pFaninLits[0]; } static inline int If_LogCounterAddAig( int * pTimes, int * pnTimes, int * pFaninLits, int Num, int iLit, Vec_Int_t * vAig, int nSuppAll, int fXor, int fXorFunc ) { int nTimes = *pnTimes; if ( vAig ) pFaninLits[nTimes] = iLit; pTimes[nTimes++] = Num; if ( nTimes > 1 ) { int i, k; for ( k = nTimes-1; k > 0; k-- ) { if ( pTimes[k] < pTimes[k-1] ) break; if ( pTimes[k] > pTimes[k-1] ) { ABC_SWAP( int, pTimes[k], pTimes[k-1] ); if ( vAig ) ABC_SWAP( int, pFaninLits[k], pFaninLits[k-1] ); continue; } pTimes[k-1] += 1 + fXor; if ( vAig ) pFaninLits[k-1] = If_LogCreateAndXor( vAig, pFaninLits[k], pFaninLits[k-1], nSuppAll, fXorFunc ); for ( nTimes--, i = k; i < nTimes; i++ ) { pTimes[i] = pTimes[i+1]; if ( vAig ) pFaninLits[i] = pFaninLits[i+1]; } } } assert( nTimes > 0 ); *pnTimes = nTimes; return pTimes[0] + (nTimes > 1 ? 1 + fXor : 0); } static inline int If_LogCounterDelayXor( int * pTimes, int nTimes ) { int i; assert( nTimes > 0 ); for ( i = nTimes - 1; i > 0; i-- ) pTimes[i-1] = 2 + Abc_MaxInt( pTimes[i], pTimes[i-1] ); return pTimes[0]; } /**Function************************************************************* Synopsis [Compute delay/area profile of the structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_CutPinDelayGet( word D, int v ) { assert(v >= 0 && v < 16); return (int)((D >> (v << 2)) & 0xF); } static inline void If_CutPinDelaySet( word * pD, int v, int d ) { assert(v >= 0 && v < 16); assert(d >= 0 && d < 16); *pD |= ((word)d << (v << 2)); } static inline word If_CutPinDelayInit( int v ) { assert(v >= 0 && v < 16); return (word)1 << (v << 2); } static inline word If_CutPinDelayMax( word D1, word D2, int nVars, int AddOn ) { int v, Max; word D = 0; for ( v = 0; v < nVars; v++ ) if ( (Max = Abc_MaxInt(If_CutPinDelayGet(D1, v), If_CutPinDelayGet(D2, v))) ) If_CutPinDelaySet( &D, v, Abc_MinInt(Max + AddOn, 15) ); return D; } static inline word If_CutPinDelayDecrement( word D1, int nVars ) { int v; word D = 0; for ( v = 0; v < nVars; v++ ) if ( If_CutPinDelayGet(D1, v) ) If_CutPinDelaySet( &D, v, If_CutPinDelayGet(D1, v) - 1 ); return D; } static inline int If_CutPinDelayEqual( word D1, word D2, int nVars ) // returns 1 if D1 has the same delays than D2 { int v; for ( v = 0; v < nVars; v++ ) if ( If_CutPinDelayGet(D1, v) != If_CutPinDelayGet(D2, v) ) return 0; return 1; } static inline int If_CutPinDelayDom( word D1, word D2, int nVars ) // returns 1 if D1 has the same or smaller delays than D2 { int v; for ( v = 0; v < nVars; v++ ) if ( If_CutPinDelayGet(D1, v) > If_CutPinDelayGet(D2, v) ) return 0; return 1; } static inline void If_CutPinDelayTranslate( word D, int nVars, char * pPerm ) { int v, Delay; for ( v = 0; v < nVars; v++ ) { Delay = If_CutPinDelayGet(D, v); assert( Delay > 1 ); pPerm[v] = Delay - 1; } } static inline void If_CutPinDelayPrint( word D, int nVars ) { int v; printf( "Delay profile = {" ); for ( v = 0; v < nVars; v++ ) printf( " %d", If_CutPinDelayGet(D, v) ); printf( " }\n" ); } static inline int If_LogCounterPinDelays( int * pTimes, int * pnTimes, word * pPinDels, int Num, word PinDel, int nSuppAll, int fXor ) { int nTimes = *pnTimes; pPinDels[nTimes] = PinDel; pTimes[nTimes++] = Num; if ( nTimes > 1 ) { int i, k; for ( k = nTimes-1; k > 0; k-- ) { if ( pTimes[k] < pTimes[k-1] ) break; if ( pTimes[k] > pTimes[k-1] ) { ABC_SWAP( int, pTimes[k], pTimes[k-1] ); ABC_SWAP( word, pPinDels[k], pPinDels[k-1] ); continue; } pTimes[k-1] += 1 + fXor; pPinDels[k-1] = If_CutPinDelayMax( pPinDels[k], pPinDels[k-1], nSuppAll, 1 + fXor ); for ( nTimes--, i = k; i < nTimes; i++ ) { pTimes[i] = pTimes[i+1]; pPinDels[i] = pPinDels[i+1]; } } } assert( nTimes > 0 ); *pnTimes = nTimes; return pTimes[0] + (nTimes > 1 ? 1 + fXor : 0); } static inline word If_LogPinDelaysMulti( word * pPinDels, int nFanins, int nSuppAll, int fXor ) { int i; assert( nFanins > 0 ); for ( i = nFanins - 1; i > 0; i-- ) pPinDels[i-1] = If_CutPinDelayMax( pPinDels[i], pPinDels[i-1], nSuppAll, 1 + fXor ); return pPinDels[0]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word If_AigVerifyArray( Vec_Int_t * vAig, int nLeaves ) { assert( Vec_IntSize(vAig) > 0 ); assert( Vec_IntEntryLast(vAig) < 2 ); if ( Vec_IntSize(vAig) == 1 ) // const return Vec_IntEntry(vAig, 0) ? ~((word)0) : 0; if ( Vec_IntSize(vAig) == 2 ) // variable { assert( Vec_IntEntry(vAig, 0) == 0 ); return Vec_IntEntry(vAig, 1) ? ~s_Truths6[0] : s_Truths6[0]; } else { word Truth0 = 0, Truth1 = 0, TruthR; int i, iVar0, iVar1, iLit0, iLit1; assert( Vec_IntSize(vAig) & 1 ); Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i ) { iVar0 = Abc_Lit2Var( iLit0 ); iVar1 = Abc_Lit2Var( iLit1 ); Truth0 = iVar0 < nLeaves ? s_Truths6[iVar0] : Vec_WrdEntry( (Vec_Wrd_t *)vAig, iVar0 - nLeaves ); Truth1 = iVar1 < nLeaves ? s_Truths6[iVar1] : Vec_WrdEntry( (Vec_Wrd_t *)vAig, iVar1 - nLeaves ); if ( Abc_LitIsCompl(iLit0) ) Truth0 = ~Truth0; if ( Abc_LitIsCompl(iLit1) ) Truth1 = ~Truth1; assert( (i & 1) == 0 ); Vec_WrdWriteEntry( (Vec_Wrd_t *)vAig, Abc_Lit2Var(i), Truth0 & Truth1 ); // overwriting entries } assert( i == Vec_IntSize(vAig) - 1 ); TruthR = Truth0 & Truth1; if ( Vec_IntEntry(vAig, i) ) TruthR = ~TruthR; Vec_IntClear( vAig ); // useless return TruthR; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void If_AigPrintArray( Vec_Int_t * vAig, int nLeaves ) { assert( Vec_IntSize(vAig) > 0 ); assert( Vec_IntEntryLast(vAig) < 2 ); if ( Vec_IntSize(vAig) == 1 ) // const printf( "Const %d\n", Vec_IntEntry(vAig, 0) ); else if ( Vec_IntSize(vAig) == 2 ) // variable printf( "Variable %s\n", Vec_IntEntry(vAig, 1) ? "Compl" : "" ); else { int i, iLit0, iLit1; assert( Vec_IntSize(vAig) & 1 ); Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i ) printf( "%d %d\n", iLit0, iLit1 ); assert( i == Vec_IntSize(vAig) - 1 ); printf( "%s\n", Vec_IntEntry(vAig, i) ? "Compl" : "" ); } } /**Function************************************************************* Synopsis [Naive implementation of log-counter.] Description [Incrementally computes [log2(SUMi(2^di)).] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_LogCounter64Eval( word Count ) { int n = ((Count & (Count - 1)) > 0) ? -1 : 0; assert( Count > 0 ); if ( (Count & ABC_CONST(0xFFFFFFFF00000000)) == 0 ) { n += 32; Count <<= 32; } if ( (Count & ABC_CONST(0xFFFF000000000000)) == 0 ) { n += 16; Count <<= 16; } if ( (Count & ABC_CONST(0xFF00000000000000)) == 0 ) { n += 8; Count <<= 8; } if ( (Count & ABC_CONST(0xF000000000000000)) == 0 ) { n += 4; Count <<= 4; } if ( (Count & ABC_CONST(0xC000000000000000)) == 0 ) { n += 2; Count <<= 2; } if ( (Count & ABC_CONST(0x8000000000000000)) == 0 ) { n++; } return 63 - n; } static word If_LogCounter64Add( word Count, int Num ) { assert( Num < 48 ); return Count + (((word)1) << Num); } /**Function************************************************************* Synopsis [Implementation of log-counter.] Description [Incrementally computes [log2(SUMi(2^di)). Supposed to work correctly up to 16 entries.] SideEffects [] SeeAlso [] ***********************************************************************/ static int If_LogCounter32Eval( unsigned Count, int Start ) { int n = (Abc_LitIsCompl(Start) || (Count & (Count - 1)) > 0) ? -1 : 0; assert( Count > 0 ); if ( (Count & 0xFFFF0000) == 0 ) { n += 16; Count <<= 16; } if ( (Count & 0xFF000000) == 0 ) { n += 8; Count <<= 8; } if ( (Count & 0xF0000000) == 0 ) { n += 4; Count <<= 4; } if ( (Count & 0xC0000000) == 0 ) { n += 2; Count <<= 2; } if ( (Count & 0x80000000) == 0 ) { n++; } return Abc_Lit2Var(Start) + 31 - n; } static unsigned If_LogCounter32Add( unsigned Count, int * pStart, int Num ) { int Start = Abc_Lit2Var(*pStart); if ( Num < Start ) { *pStart |= 1; return Count; } if ( Num > Start + 16 ) { int Shift = Num - (Start + 16); if ( !Abc_LitIsCompl(*pStart) && (Shift >= 32 ? Count : Count & ~(~0 << Shift)) > 0 ) *pStart |= 1; Count >>= Shift; Start += Shift; *pStart = Abc_Var2Lit( Start, Abc_LitIsCompl(*pStart) ); assert( Num <= Start + 16 ); } return Count + (1 << (Num-Start)); } /**Function************************************************************* Synopsis [Testing of the counter] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* void If_LogCounterTest2() { word Count64 = 0; unsigned Count = 0; int Start = 0; int Result, Result64; Count = If_LogCounter32Add( Count, &Start, 39 ); Count = If_LogCounter32Add( Count, &Start, 35 ); Count = If_LogCounter32Add( Count, &Start, 35 ); Count = If_LogCounter32Add( Count, &Start, 36 ); Count = If_LogCounter32Add( Count, &Start, 37 ); Count = If_LogCounter32Add( Count, &Start, 38 ); Count = If_LogCounter32Add( Count, &Start, 40 ); Count = If_LogCounter32Add( Count, &Start, 1 ); Count = If_LogCounter32Add( Count, &Start, 41 ); Count = If_LogCounter32Add( Count, &Start, 42 ); Count64 = If_LogCounter64Add( Count64, 1 ); Count64 = If_LogCounter64Add( Count64, 35 ); Count64 = If_LogCounter64Add( Count64, 35 ); Count64 = If_LogCounter64Add( Count64, 36 ); Count64 = If_LogCounter64Add( Count64, 37 ); Count64 = If_LogCounter64Add( Count64, 38 ); Count64 = If_LogCounter64Add( Count64, 39 ); Count64 = If_LogCounter64Add( Count64, 40 ); Count64 = If_LogCounter64Add( Count64, 41 ); Count64 = If_LogCounter64Add( Count64, 42 ); Result = If_LogCounter32Eval( Count, Start ); Result64 = If_LogCounter64Eval( Count64 ); printf( "%d %d\n", Result, Result64 ); } */ /**Function************************************************************* Synopsis [Adds the number to the numbers stored.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_LogCounterAdd( int * pTimes, int * pnTimes, int Num, int fXor ) { int nTimes = *pnTimes; pTimes[nTimes++] = Num; if ( nTimes > 1 ) { int i, k; for ( k = nTimes-1; k > 0; k-- ) { if ( pTimes[k] < pTimes[k-1] ) break; if ( pTimes[k] > pTimes[k-1] ) { ABC_SWAP( int, pTimes[k], pTimes[k-1] ); continue; } pTimes[k-1] += 1 + fXor; for ( nTimes--, i = k; i < nTimes; i++ ) pTimes[i] = pTimes[i+1]; } } assert( nTimes > 0 ); *pnTimes = nTimes; return pTimes[0] + (nTimes > 1 ? 1 + fXor : 0); } /**Function************************************************************* Synopsis [Testing of the counter] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* void If_LogCounterTest() { int pArray[10] = { 1, 2, 4, 5, 6, 3, 1 }; int i, nSize = 4; word Count64 = 0; int Result, Result64; int pTimes[100]; int nTimes = 0; for ( i = 0; i < nSize; i++ ) Count64 = If_LogCounter64Add( Count64, pArray[i] ); Result64 = If_LogCounter64Eval( Count64 ); for ( i = 0; i < nSize; i++ ) Result = If_LogCounterAdd( pTimes, &nTimes, pArray[i], 0 ); printf( "%d %d\n", Result64, Result ); } */ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifCut.c000066400000000000000000001222341300674244400224310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifCut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_CutVerifyCut( If_Cut_t * pBase, If_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; } int If_CutVerifyCuts( If_Set_t * pCutSet, int fOrdered ) { static int Count = 0; If_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( pCutSet->nCuts > 0 ); for ( i = 0; i < pCutSet->nCuts; i++ ) { pCut0 = pCutSet->ppCuts[i]; assert( pCut0->uSign == If_ObjCutSignCompute(pCut0) ); if ( fOrdered ) { // check duplicates for ( m = 1; m < (int)pCut0->nLeaves; m++ ) assert( pCut0->pLeaves[m-1] < pCut0->pLeaves[m] ); } else { // 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 < pCutSet->nCuts; k++ ) { pCut1 = pCutSet->ppCuts[k]; if ( pCut0 == pCut1 ) continue; Count++; // check containments Value = If_CutVerifyCut( pCut0, pCut1 ); // assert( Value == 0 ); if ( Value ) { assert( pCut0->uSign == If_ObjCutSignCompute(pCut0) ); assert( pCut1->uSign == If_ObjCutSignCompute(pCut1) ); If_CutPrint( pCut0 ); If_CutPrint( pCut1 ); assert( 0 ); } } } return 1; } /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_CutCheckDominance( If_Cut_t * pDom, If_Cut_t * pCut ) { int i, k; assert( pDom->nLeaves <= pCut->nLeaves ); for ( i = 0; i < (int)pDom->nLeaves; i++ ) { for ( k = 0; k < (int)pCut->nLeaves; k++ ) if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) break; if ( k == (int)pCut->nLeaves ) // 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 If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut, int fSaveCut0 ) { If_Cut_t * pTemp; int i, k; assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut ); for ( i = 0; i < pCutSet->nCuts; i++ ) { pTemp = pCutSet->ppCuts[i]; if ( pTemp->nLeaves > pCut->nLeaves ) { // do not fiter the first cut if ( i == 0 && ((pCutSet->nCuts > 1 && pCutSet->ppCuts[1]->fUseless) || (fSaveCut0 && pCutSet->nCuts == 1)) ) continue; // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) continue; // check containment seriously if ( If_CutCheckDominance( pCut, pTemp ) ) { // p->ppCuts[i] = p->ppCuts[p->nCuts-1]; // p->ppCuts[p->nCuts-1] = pTemp; // p->nCuts--; // i--; // remove contained cut for ( k = i; k < pCutSet->nCuts; k++ ) pCutSet->ppCuts[k] = pCutSet->ppCuts[k+1]; pCutSet->ppCuts[pCutSet->nCuts] = pTemp; pCutSet->nCuts--; i--; } } else { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) continue; // check containment seriously if ( If_CutCheckDominance( pTemp, pCut ) ) return 1; } } return 0; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutMergeOrdered_( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC ) { int nSizeC0 = pC0->nLeaves; int nSizeC1 = pC1->nLeaves; int nLimit = pC0->nLimit; int i, k, c, s; // both cuts are the largest if ( nSizeC0 == nLimit && nSizeC1 == nLimit ) { for ( i = 0; i < nSizeC0; i++ ) { if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) return 0; p->pPerm[0][i] = p->pPerm[1][i] = p->pPerm[2][i] = i; pC->pLeaves[i] = pC0->pLeaves[i]; } pC->nLeaves = nLimit; pC->uSign = pC0->uSign | pC1->uSign; p->uSharedMask = Abc_InfoMask( nLimit ); return 1; } // compare two cuts with different numbers i = k = c = s = 0; p->uSharedMask = 0; if ( nSizeC0 == 0 ) goto FlushCut1; if ( nSizeC1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nLimit ) return 0; if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) { p->pPerm[0][i] = c; pC->pLeaves[c++] = pC0->pLeaves[i++]; if ( i == nSizeC0 ) goto FlushCut1; } else if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) { p->pPerm[1][k] = c; pC->pLeaves[c++] = pC1->pLeaves[k++]; if ( k == nSizeC1 ) goto FlushCut0; } else { p->uSharedMask |= (1 << c); p->pPerm[0][i] = p->pPerm[1][k] = p->pPerm[2][s++] = c; pC->pLeaves[c++] = pC0->pLeaves[i++]; k++; if ( i == nSizeC0 ) goto FlushCut1; if ( k == nSizeC1 ) goto FlushCut0; } } FlushCut0: if ( c + nSizeC0 > nLimit + i ) return 0; while ( i < nSizeC0 ) { p->pPerm[0][i] = c; pC->pLeaves[c++] = pC0->pLeaves[i++]; } pC->nLeaves = c; pC->uSign = pC0->uSign | pC1->uSign; assert( c > 0 ); return 1; FlushCut1: if ( c + nSizeC1 > nLimit + k ) return 0; while ( k < nSizeC1 ) { p->pPerm[1][k] = c; pC->pLeaves[c++] = pC1->pLeaves[k++]; } pC->nLeaves = c; pC->uSign = pC0->uSign | pC1->uSign; assert( c > 0 ); return 1; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutMergeOrdered( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC ) { int nSizeC0 = pC0->nLeaves; int nSizeC1 = pC1->nLeaves; int nLimit = pC0->nLimit; int i, k, c, s; // both cuts are the largest if ( nSizeC0 == nLimit && nSizeC1 == nLimit ) { for ( i = 0; i < nSizeC0; i++ ) { if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) return 0; pC->pLeaves[i] = pC0->pLeaves[i]; } pC->nLeaves = nLimit; pC->uSign = pC0->uSign | pC1->uSign; return 1; } // compare two cuts with different numbers i = k = c = s = 0; if ( nSizeC0 == 0 ) goto FlushCut1; if ( nSizeC1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nLimit ) return 0; if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) { pC->pLeaves[c++] = pC0->pLeaves[i++]; if ( i == nSizeC0 ) goto FlushCut1; } else if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) { pC->pLeaves[c++] = pC1->pLeaves[k++]; if ( k == nSizeC1 ) goto FlushCut0; } else { pC->pLeaves[c++] = pC0->pLeaves[i++]; k++; if ( i == nSizeC0 ) goto FlushCut1; if ( k == nSizeC1 ) goto FlushCut0; } } FlushCut0: if ( c + nSizeC0 > nLimit + i ) return 0; while ( i < nSizeC0 ) pC->pLeaves[c++] = pC0->pLeaves[i++]; pC->nLeaves = c; pC->uSign = pC0->uSign | pC1->uSign; return 1; FlushCut1: if ( c + nSizeC1 > nLimit + k ) return 0; while ( k < nSizeC1 ) pC->pLeaves[c++] = pC1->pLeaves[k++]; pC->nLeaves = c; pC->uSign = pC0->uSign | pC1->uSign; return 1; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutMerge( If_Man_t * p, If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut ) { int nLutSize = pCut0->nLimit; 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 ) { p->pPerm[1][i] = k; continue; } if ( c == nLutSize ) return 0; p->pPerm[1][i] = c; pC[c++] = pC1[i]; } for ( i = 0; i < nSize0; i++ ) pC[i] = pC0[i]; pCut->nLeaves = c; pCut->uSign = pCut0->uSign | pCut1->uSign; return 1; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutCompareDelay( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) { If_Cut_t * pC0 = *ppC0; If_Cut_t * pC1 = *ppC1; if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; return 0; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutCompareDelayOld( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) { If_Cut_t * pC0 = *ppC0; If_Cut_t * pC1 = *ppC1; if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; return 0; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutCompareArea( If_Man_t * p, If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) { If_Cut_t * pC0 = *ppC0; If_Cut_t * pC1 = *ppC1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; // if ( pC0->AveRefs > pC1->AveRefs ) // return -1; // if ( pC0->AveRefs < pC1->AveRefs ) // return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; return 0; } /**Function************************************************************* Synopsis [Comparison function for two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 ) { if ( p->pPars->fPower ) { if ( p->SortMode == 1 ) // area flow { if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; //Abc_Print( 1,"area(%.2f, %.2f), power(%.2f, %.2f), edge(%.2f, %.2f)\n", // pC0->Area, pC1->Area, pC0->Power, pC1->Power, pC0->Edge, pC1->Edge); if ( pC0->Power < pC1->Power - p->fEpsilon ) return -1; if ( pC0->Power > pC1->Power + p->fEpsilon ) return 1; if ( pC0->Edge < pC1->Edge - p->fEpsilon ) return -1; if ( pC0->Edge > pC1->Edge + p->fEpsilon ) return 1; // if ( pC0->AveRefs > pC1->AveRefs ) // return -1; // if ( pC0->AveRefs < pC1->AveRefs ) // return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; return 0; } if ( p->SortMode == 0 ) // delay { if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; if ( pC0->Power < pC1->Power - p->fEpsilon ) return -1; if ( pC0->Power > pC1->Power + p->fEpsilon ) return 1; if ( pC0->Edge < pC1->Edge - p->fEpsilon ) return -1; if ( pC0->Edge > pC1->Edge + p->fEpsilon ) return 1; return 0; } assert( p->SortMode == 2 ); // delay old, exact area if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; if ( pC0->Power < pC1->Power - p->fEpsilon ) return -1; if ( pC0->Power > pC1->Power + p->fEpsilon ) return 1; if ( pC0->Edge < pC1->Edge - p->fEpsilon ) return -1; if ( pC0->Edge > pC1->Edge + p->fEpsilon ) return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; return 0; } else // regular { if ( p->SortMode == 1 ) // area { if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; if ( pC0->Edge < pC1->Edge - p->fEpsilon ) return -1; if ( pC0->Edge > pC1->Edge + p->fEpsilon ) return 1; if ( pC0->Power < pC1->Power - p->fEpsilon ) return -1; if ( pC0->Power > pC1->Power + p->fEpsilon ) return 1; // if ( pC0->AveRefs > pC1->AveRefs ) // return -1; // if ( pC0->AveRefs < pC1->AveRefs ) // return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; return 0; } if ( p->SortMode == 0 ) // delay { if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; if ( pC0->Edge < pC1->Edge - p->fEpsilon ) return -1; if ( pC0->Edge > pC1->Edge + p->fEpsilon ) return 1; if ( pC0->Power < pC1->Power - p->fEpsilon ) return -1; if ( pC0->Power > pC1->Power + p->fEpsilon ) return 1; return 0; } assert( p->SortMode == 2 ); // delay old if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; if ( pC0->Edge < pC1->Edge - p->fEpsilon ) return -1; if ( pC0->Edge > pC1->Edge + p->fEpsilon ) return 1; if ( pC0->Power < pC1->Power - p->fEpsilon ) return -1; if ( pC0->Power > pC1->Power + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; return 0; } } /**Function************************************************************* Synopsis [Comparison function for two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_ManSortCompare_old( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 ) { if ( p->SortMode == 1 ) // area { if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; // if ( pC0->AveRefs > pC1->AveRefs ) // return -1; // if ( pC0->AveRefs < pC1->AveRefs ) // return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; return 0; } if ( p->SortMode == 0 ) // delay { if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; return 0; } assert( p->SortMode == 2 ); // delay old if ( pC0->Delay < pC1->Delay - p->fEpsilon ) return -1; if ( pC0->Delay > pC1->Delay + p->fEpsilon ) return 1; if ( pC0->Area < pC1->Area - p->fEpsilon ) return -1; if ( pC0->Area > pC1->Area + p->fEpsilon ) return 1; if ( pC0->nLeaves < pC1->nLeaves ) return -1; if ( pC0->nLeaves > pC1->nLeaves ) return 1; return 0; } /**Function************************************************************* Synopsis [Performs incremental sorting of cuts.] Description [Currently only the trivial sorting is implemented.] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) { // int Counter = 0; int i; // the new cut is the last one assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut ); assert( pCutSet->nCuts <= pCutSet->nCutsMax ); // cut structure is empty if ( pCutSet->nCuts == 0 ) { pCutSet->nCuts++; return; } if ( !pCut->fUseless && (p->pPars->fUseDsd || p->pPars->fUseBat || p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u) ) { If_Cut_t * pFirst = pCutSet->ppCuts[0]; if ( pFirst->fUseless || If_ManSortCompare(p, pFirst, pCut) == 1 ) { pCutSet->ppCuts[0] = pCut; pCutSet->ppCuts[pCutSet->nCuts] = pFirst; If_CutSort( p, pCutSet, pFirst ); return; } } // the cut will be added - find its place for ( i = pCutSet->nCuts-1; i >= 0; i-- ) { // Counter++; if ( If_ManSortCompare( p, pCutSet->ppCuts[i], pCut ) <= 0 || (i == 0 && !pCutSet->ppCuts[0]->fUseless && pCut->fUseless) ) break; pCutSet->ppCuts[i+1] = pCutSet->ppCuts[i]; pCutSet->ppCuts[i] = pCut; } // Abc_Print( 1, "%d ", Counter ); // update the number of cuts if ( pCutSet->nCuts < pCutSet->nCutsMax ) pCutSet->nCuts++; } /**Function************************************************************* Synopsis [Orders the leaves of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutOrder( If_Cut_t * pCut ) { int i, Temp, fChanges; do { fChanges = 0; for ( i = 0; i < (int)pCut->nLeaves - 1; i++ ) { assert( pCut->pLeaves[i] != pCut->pLeaves[i+1] ); if ( pCut->pLeaves[i] <= pCut->pLeaves[i+1] ) continue; Temp = pCut->pLeaves[i]; pCut->pLeaves[i] = pCut->pLeaves[i+1]; pCut->pLeaves[i+1] = Temp; fChanges = 1; } } while ( fChanges ); } /**Function************************************************************* Synopsis [Checks correctness of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutCheck( If_Cut_t * pCut ) { int i; assert( pCut->nLeaves <= pCut->nLimit ); if ( pCut->nLeaves < 2 ) return 1; for ( i = 1; i < (int)pCut->nLeaves; i++ ) { if ( pCut->pLeaves[i-1] >= pCut->pLeaves[i] ) { Abc_Print( -1, "If_CutCheck(): Cut has wrong ordering of inputs.\n" ); return 0; } assert( pCut->pLeaves[i-1] < pCut->pLeaves[i] ); } return 1; } /**Function************************************************************* Synopsis [Prints one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutPrint( If_Cut_t * pCut ) { unsigned i; Abc_Print( 1, "{" ); for ( i = 0; i < pCut->nLeaves; i++ ) Abc_Print( 1, " %s%d", If_CutLeafBit(pCut, i) ? "!":"", pCut->pLeaves[i] ); Abc_Print( 1, " }\n" ); } /**Function************************************************************* Synopsis [Prints one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; unsigned i; Abc_Print( 1, "{" ); If_CutForEachLeaf( p, pCut, pLeaf, i ) Abc_Print( 1, " %d(%.2f/%.2f)", pLeaf->Id, If_ObjCutBest(pLeaf)->Delay, pLeaf->Required ); Abc_Print( 1, " }\n" ); } /**Function************************************************************* Synopsis [Moves the cut over the latch.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutLift( If_Cut_t * pCut ) { unsigned i; for ( i = 0; i < pCut->nLeaves; i++ ) { assert( (pCut->pLeaves[i] & 255) < 255 ); pCut->pLeaves[i]++; } } /**Function************************************************************* Synopsis [Computes area flow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutAreaFlow( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; float Flow; int i; Flow = If_CutLutArea(p, pCut); If_CutForEachLeaf( p, pCut, pLeaf, i ) { if ( pLeaf->nRefs == 0 || If_ObjIsConst1(pLeaf) ) Flow += If_ObjCutBest(pLeaf)->Area; else { assert( pLeaf->EstRefs > p->fEpsilon ); Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->EstRefs; } } return Flow; } /**Function************************************************************* Synopsis [Computes area flow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutEdgeFlow( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; float Flow; int i; Flow = pCut->nLeaves; If_CutForEachLeaf( p, pCut, pLeaf, i ) { if ( pLeaf->nRefs == 0 || If_ObjIsConst1(pLeaf) ) Flow += If_ObjCutBest(pLeaf)->Edge; else { assert( pLeaf->EstRefs > p->fEpsilon ); Flow += If_ObjCutBest(pLeaf)->Edge / pLeaf->EstRefs; } } return Flow; } /**Function************************************************************* Synopsis [Computes area flow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutPowerFlow( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) { If_Obj_t * pLeaf; float * pSwitching = (float *)p->vSwitching->pArray; float Power = 0; int i; If_CutForEachLeaf( p, pCut, pLeaf, i ) { Power += pSwitching[pLeaf->Id]; if ( pLeaf->nRefs == 0 || If_ObjIsConst1(pLeaf) ) Power += If_ObjCutBest(pLeaf)->Power; else { assert( pLeaf->EstRefs > p->fEpsilon ); Power += If_ObjCutBest(pLeaf)->Power / pLeaf->EstRefs; } } return Power; } /**Function************************************************************* Synopsis [Average number of references of the leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; int nRefsTotal, i; nRefsTotal = 0; If_CutForEachLeaf( p, pCut, pLeaf, i ) nRefsTotal += pLeaf->nRefs; return ((float)nRefsTotal)/pCut->nLeaves; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutAreaDeref( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; float Area; int i; Area = If_CutLutArea(p, pCut); If_CutForEachLeaf( p, pCut, pLeaf, i ) { assert( pLeaf->nRefs > 0 ); if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) ) continue; Area += If_CutAreaDeref( p, If_ObjCutBest(pLeaf) ); } return Area; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutAreaRef( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; float Area; int i; Area = If_CutLutArea(p, pCut); If_CutForEachLeaf( p, pCut, pLeaf, i ) { assert( pLeaf->nRefs >= 0 ); if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) ) continue; Area += If_CutAreaRef( p, If_ObjCutBest(pLeaf) ); } return Area; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut ) { float aResult, aResult2; if ( pCut->nLeaves < 2 ) return 0; aResult2 = If_CutAreaRef( p, pCut ); aResult = If_CutAreaDeref( p, pCut ); assert( aResult > aResult2 - p->fEpsilon ); assert( aResult < aResult2 + p->fEpsilon ); return aResult; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut ) { float aResult, aResult2; if ( pCut->nLeaves < 2 ) return 0; aResult2 = If_CutAreaDeref( p, pCut ); aResult = If_CutAreaRef( p, pCut ); assert( aResult > aResult2 - p->fEpsilon ); assert( aResult < aResult2 + p->fEpsilon ); return aResult; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutEdgeDeref( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; float Edge; int i; Edge = pCut->nLeaves; If_CutForEachLeaf( p, pCut, pLeaf, i ) { assert( pLeaf->nRefs > 0 ); if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) ) continue; Edge += If_CutEdgeDeref( p, If_ObjCutBest(pLeaf) ); } return Edge; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutEdgeRef( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; float Edge; int i; Edge = pCut->nLeaves; If_CutForEachLeaf( p, pCut, pLeaf, i ) { assert( pLeaf->nRefs >= 0 ); if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) ) continue; Edge += If_CutEdgeRef( p, If_ObjCutBest(pLeaf) ); } return Edge; } /**Function************************************************************* Synopsis [Computes edge of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutEdgeDerefed( If_Man_t * p, If_Cut_t * pCut ) { float aResult, aResult2; if ( pCut->nLeaves < 2 ) return pCut->nLeaves; aResult2 = If_CutEdgeRef( p, pCut ); aResult = If_CutEdgeDeref( p, pCut ); assert( aResult > aResult2 - p->fEpsilon ); assert( aResult < aResult2 + p->fEpsilon ); return aResult; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutEdgeRefed( If_Man_t * p, If_Cut_t * pCut ) { float aResult, aResult2; if ( pCut->nLeaves < 2 ) return pCut->nLeaves; aResult2 = If_CutEdgeDeref( p, pCut ); aResult = If_CutEdgeRef( p, pCut ); assert( aResult > aResult2 - p->fEpsilon ); assert( aResult < aResult2 + p->fEpsilon ); return aResult; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutPowerDeref( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) { If_Obj_t * pLeaf; float * pSwitching = (float *)p->vSwitching->pArray; float Power = 0; int i; If_CutForEachLeaf( p, pCut, pLeaf, i ) { Power += pSwitching[pLeaf->Id]; assert( pLeaf->nRefs > 0 ); if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) ) continue; Power += If_CutPowerDeref( p, If_ObjCutBest(pLeaf), pRoot ); } return Power; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutPowerRef( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) { If_Obj_t * pLeaf; float * pSwitching = (float *)p->vSwitching->pArray; float Power = 0; int i; If_CutForEachLeaf( p, pCut, pLeaf, i ) { Power += pSwitching[pLeaf->Id]; assert( pLeaf->nRefs >= 0 ); if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) ) continue; Power += If_CutPowerRef( p, If_ObjCutBest(pLeaf), pRoot ); } return Power; } /**Function************************************************************* Synopsis [Computes Power of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutPowerDerefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) { float aResult, aResult2; if ( pCut->nLeaves < 2 ) return 0; aResult2 = If_CutPowerRef( p, pCut, pRoot ); aResult = If_CutPowerDeref( p, pCut, pRoot ); assert( aResult > aResult2 - p->fEpsilon ); assert( aResult < aResult2 + p->fEpsilon ); return aResult; } /**Function************************************************************* Synopsis [Computes area of the first level.] Description [The cut need to be derefed.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutPowerRefed( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pRoot ) { float aResult, aResult2; if ( pCut->nLeaves < 2 ) return 0; aResult2 = If_CutPowerDeref( p, pCut, pRoot ); aResult = If_CutPowerRef( p, pCut, pRoot ); assert( aResult > aResult2 - p->fEpsilon ); assert( aResult < aResult2 + p->fEpsilon ); return aResult; } /**Function************************************************************* Synopsis [Computes the cone of the cut in AIG with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutGetCutMinLevel( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; int i, nMinLevel = IF_INFINITY; If_CutForEachLeaf( p, pCut, pLeaf, i ) nMinLevel = IF_MIN( nMinLevel, (int)pLeaf->Level ); return nMinLevel; } /**Function************************************************************* Synopsis [Computes the cone of the cut in AIG with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutGetCone_rec( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut ) { If_Obj_t * pTemp; int i, RetValue; // check if the node is in the cut for ( i = 0; i < (int)pCut->nLeaves; i++ ) if ( pCut->pLeaves[i] == pObj->Id ) return 1; else if ( pCut->pLeaves[i] > pObj->Id ) break; // return if we reached the boundary if ( If_ObjIsCi(pObj) ) return 0; // check the choice node for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) { // check if the node itself is bound RetValue = If_CutGetCone_rec( p, If_ObjFanin0(pTemp), pCut ); if ( RetValue ) RetValue &= If_CutGetCone_rec( p, If_ObjFanin1(pTemp), pCut ); if ( RetValue ) return 1; } return 0; } /**Function************************************************************* Synopsis [Computes the cone of the cut in AIG with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutGetCones( If_Man_t * p ) { If_Obj_t * pObj; int i, Counter = 0; abctime clk = Abc_Clock(); If_ManForEachObj( p, pObj, i ) { if ( If_ObjIsAnd(pObj) && pObj->nRefs ) { Counter += !If_CutGetCone_rec( p, pObj, If_ObjCutBest(pObj) ); // Abc_Print( 1, "%d ", If_CutGetCutMinLevel( p, If_ObjCutBest(pObj) ) ); } } Abc_Print( 1, "Cound not find boundary for %d nodes.\n", Counter ); Abc_PrintTime( 1, "Cones", Abc_Clock() - clk ); return 1; } /**Function************************************************************* Synopsis [Computes the cone of the cut in AIG with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutFoundFanins_rec( If_Obj_t * pObj, Vec_Int_t * vLeaves ) { if ( pObj->nRefs || If_ObjIsCi(pObj) ) { Vec_IntPushUnique( vLeaves, pObj->Id ); return; } If_CutFoundFanins_rec( If_ObjFanin0(pObj), vLeaves ); If_CutFoundFanins_rec( If_ObjFanin1(pObj), vLeaves ); } /**Function************************************************************* Synopsis [Computes the cone of the cut in AIG with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutCountTotalFanins( If_Man_t * p ) { If_Obj_t * pObj; Vec_Int_t * vLeaves; int i, nFaninsTotal = 0, Counter = 0; abctime clk = Abc_Clock(); vLeaves = Vec_IntAlloc( 100 ); If_ManForEachObj( p, pObj, i ) { if ( If_ObjIsAnd(pObj) && pObj->nRefs ) { nFaninsTotal += If_ObjCutBest(pObj)->nLeaves; Vec_IntClear( vLeaves ); If_CutFoundFanins_rec( If_ObjFanin0(pObj), vLeaves ); If_CutFoundFanins_rec( If_ObjFanin1(pObj), vLeaves ); Counter += Vec_IntSize(vLeaves); } } Abc_Print( 1, "Total cut inputs = %d. Total fanins incremental = %d.\n", nFaninsTotal, Counter ); Abc_PrintTime( 1, "Fanins", Abc_Clock() - clk ); Vec_IntFree( vLeaves ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifData2.c000066400000000000000000000027721300674244400226350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifData2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Precomputed data.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2009.] Revision [$Id: ifData2.c,v 1.00 2009/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifDec07.c000066400000000000000000001033071300674244400225400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifDec07.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Performs additional check.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifDec07.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "misc/extra/extra.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the bit count for the first 256 integer numbers static int BitCount8[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; // elementary truth tables static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; static word Truth7[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)} }; extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// void If_DecPrintConfig( word z ) { unsigned S[1]; S[0] = (z & 0xffff) | ((z & 0xffff) << 16); Extra_PrintBinary( stdout, S, 16 ); printf( " " ); Kit_DsdPrintFromTruth( S, 4 ); printf( " " ); printf( " %d", (int)((z >> 16) & 7) ); printf( " %d", (int)((z >> 20) & 7) ); printf( " %d", (int)((z >> 24) & 7) ); printf( " %d", (int)((z >> 28) & 7) ); printf( " " ); S[0] = ((z >> 32) & 0xffff) | (((z >> 32) & 0xffff) << 16); Extra_PrintBinary( stdout, S, 16 ); printf( " " ); Kit_DsdPrintFromTruth( S, 4 ); printf( " " ); printf( " %d", (int)((z >> 48) & 7) ); printf( " %d", (int)((z >> 52) & 7) ); printf( " %d", (int)((z >> 56) & 7) ); printf( " %d", (int)((z >> 60) & 7) ); printf( "\n" ); } // verification for 6-input function static word If_Dec6ComposeLut4( int t, word f[4] ) { int m, v; word c, r = 0; for ( m = 0; m < 16; m++ ) { if ( !((t >> m) & 1) ) continue; c = ~(word)0; for ( v = 0; v < 4; v++ ) c &= ((m >> v) & 1) ? f[v] : ~f[v]; r |= c; } return r; } word If_Dec6Truth( word z ) { word r, q, f[4]; int i, v; assert( z ); for ( i = 0; i < 4; i++ ) { v = (z >> (16+(i<<2))) & 7; assert( v != 7 ); if ( v == 6 ) continue; f[i] = Truth6[v]; } q = If_Dec6ComposeLut4( (int)(z & 0xffff), f ); for ( i = 0; i < 4; i++ ) { v = (z >> (48+(i<<2))) & 7; if ( v == 6 ) continue; f[i] = (v == 7) ? q : Truth6[v]; } r = If_Dec6ComposeLut4( (int)((z >> 32) & 0xffff), f ); return r; } void If_Dec6Verify( word t, word z ) { word r = If_Dec6Truth( z ); if ( r != t ) { If_DecPrintConfig( z ); Kit_DsdPrintFromTruth( (unsigned*)&t, 6 ); printf( "\n" ); // Kit_DsdPrintFromTruth( (unsigned*)&q, 6 ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)&r, 6 ); printf( "\n" ); printf( "Verification failed!\n" ); } } // verification for 7-input function static void If_Dec7ComposeLut4( int t, word f[4][2], word r[2] ) { int m, v; word c[2]; r[0] = r[1] = 0; for ( m = 0; m < 16; m++ ) { if ( !((t >> m) & 1) ) continue; c[0] = c[1] = ~(word)0; for ( v = 0; v < 4; v++ ) { c[0] &= ((m >> v) & 1) ? f[v][0] : ~f[v][0]; c[1] &= ((m >> v) & 1) ? f[v][1] : ~f[v][1]; } r[0] |= c[0]; r[1] |= c[1]; } } void If_Dec7Verify( word t[2], word z ) { word f[4][2], r[2]; int i, v; assert( z ); for ( i = 0; i < 4; i++ ) { v = (z >> (16+(i<<2))) & 7; f[i][0] = Truth7[v][0]; f[i][1] = Truth7[v][1]; } If_Dec7ComposeLut4( (int)(z & 0xffff), f, r ); f[3][0] = r[0]; f[3][1] = r[1]; for ( i = 0; i < 3; i++ ) { v = (z >> (48+(i<<2))) & 7; f[i][0] = Truth7[v][0]; f[i][1] = Truth7[v][1]; } If_Dec7ComposeLut4( (int)((z >> 32) & 0xffff), f, r ); if ( r[0] != t[0] || r[1] != t[1] ) { If_DecPrintConfig( z ); Kit_DsdPrintFromTruth( (unsigned*)t, 7 ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)r, 7 ); printf( "\n" ); printf( "Verification failed!\n" ); } } // count the number of unique cofactors static inline int If_Dec6CofCount2( word t ) { int i, Mask = 0; for ( i = 0; i < 16; i++ ) Mask |= (1 << ((t >> (i<<2)) & 15)); return BitCount8[((unsigned char*)&Mask)[0]] + BitCount8[((unsigned char*)&Mask)[1]]; } // count the number of unique cofactors (up to 3) static inline int If_Dec7CofCount3( word t[2] ) { unsigned char * pTruth = (unsigned char *)t; int i, iCof2 = 0; for ( i = 1; i < 16; i++ ) { if ( pTruth[i] == pTruth[0] ) continue; if ( iCof2 == 0 ) iCof2 = i; else if ( pTruth[i] != pTruth[iCof2] ) return 3; } assert( iCof2 ); return 2; } // permute 6-input function static inline word If_Dec6SwapAdjacent( word t, int v ) { assert( v < 5 ); return (t & PMasks[v][0]) | ((t & PMasks[v][1]) << (1 << v)) | ((t & PMasks[v][2]) >> (1 << v)); } static inline word If_Dec6MoveTo( word t, int v, int p, int Pla2Var[6], int Var2Pla[6] ) { int iPlace0, iPlace1; assert( Var2Pla[v] >= p ); while ( Var2Pla[v] != p ) { iPlace0 = Var2Pla[v]-1; iPlace1 = Var2Pla[v]; t = If_Dec6SwapAdjacent( t, iPlace0 ); Var2Pla[Pla2Var[iPlace0]]++; Var2Pla[Pla2Var[iPlace1]]--; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; } assert( Pla2Var[p] == v ); return t; } // permute 7-input function static inline void If_Dec7SwapAdjacent( word t[2], int v ) { if ( v == 5 ) { unsigned Temp = (t[0] >> 32); t[0] = (t[0] & 0xFFFFFFFF) | ((t[1] & 0xFFFFFFFF) << 32); t[1] ^= (t[1] & 0xFFFFFFFF) ^ Temp; return; } assert( v < 5 ); t[0] = If_Dec6SwapAdjacent( t[0], v ); t[1] = If_Dec6SwapAdjacent( t[1], v ); } static inline void If_Dec7MoveTo( word t[2], int v, int p, int Pla2Var[7], int Var2Pla[7] ) { int iPlace0, iPlace1; assert( Var2Pla[v] >= p ); while ( Var2Pla[v] != p ) { iPlace0 = Var2Pla[v]-1; iPlace1 = Var2Pla[v]; If_Dec7SwapAdjacent( t, iPlace0 ); Var2Pla[Pla2Var[iPlace0]]++; Var2Pla[Pla2Var[iPlace1]]--; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; } assert( Pla2Var[p] == v ); } // derive binary function static inline int If_Dec6DeriveCount2( word t, int * pCof0, int * pCof1 ) { int i, Mask = 0; *pCof0 = (t & 15); *pCof1 = (t & 15); for ( i = 1; i < 16; i++ ) if ( *pCof0 != ((t >> (i<<2)) & 15) ) { *pCof1 = ((t >> (i<<2)) & 15); Mask |= (1 << i); } return Mask; } static inline int If_Dec7DeriveCount3( word t[2], int * pCof0, int * pCof1 ) { unsigned char * pTruth = (unsigned char *)t; int i, Mask = 0; *pCof0 = pTruth[0]; *pCof1 = pTruth[0]; for ( i = 1; i < 16; i++ ) if ( *pCof0 != pTruth[i] ) { *pCof1 = pTruth[i]; Mask |= (1 << i); } return Mask; } // derives decomposition static inline word If_Dec6Cofactor( word t, int iVar, int fCof1 ) { assert( iVar >= 0 && iVar < 6 ); if ( fCof1 ) return (t & Truth6[iVar]) | ((t & Truth6[iVar]) >> (1<= 2 && s <= 5 ); for ( i = 0; i < 6; i++ ) { Pla2Var[i] = Pla2Var0[i]; Var2Pla[i] = Var2Pla0[i]; } for ( i = s; i < 5; i++ ) { t = If_Dec6SwapAdjacent( t, i ); Var2Pla[Pla2Var[i]]++; Var2Pla[Pla2Var[i+1]]--; Pla2Var[i] ^= Pla2Var[i+1]; Pla2Var[i+1] ^= Pla2Var[i]; Pla2Var[i] ^= Pla2Var[i+1]; } c0 = If_Dec6Cofactor( t, 5, 0 ); c1 = If_Dec6Cofactor( t, 5, 1 ); assert( 2 >= If_Dec6CofCount2(c0) ); assert( 2 >= If_Dec6CofCount2(c1) ); Truth0 = If_Dec6DeriveCount2( c0, &Cof0[0], &Cof0[1] ); Truth1 = If_Dec6DeriveCount2( c1, &Cof1[0], &Cof1[1] ); z = ((Truth1 & 0xFF) << 8) | (Truth0 & 0xFF); for ( i = 0; i < 4; i++ ) z |= (((word)Pla2Var[i+2]) << (16 + 4*i)); z |= ((word)((Cof0[1] << 4) | Cof0[0]) << 32); z |= ((word)((Cof1[1] << 4) | Cof1[0]) << 40); for ( i = 0; i < 2; i++ ) z |= (((word)Pla2Var[i]) << (48 + 4*i)); z |= (((word)7) << (48 + 4*i++)); z |= (((word)Pla2Var[5]) << (48 + 4*i++)); assert( i == 4 ); return z; } static word If_Dec7DeriveDisjoint( word t[2], int Pla2Var[7], int Var2Pla[7] ) { int i, Cof0, Cof1; word z = If_Dec7DeriveCount3( t, &Cof0, &Cof1 ); for ( i = 0; i < 4; i++ ) z |= (((word)Pla2Var[i+3]) << (16 + 4*i)); z |= ((word)((Cof1 << 8) | Cof0) << 32); for ( i = 0; i < 3; i++ ) z |= (((word)Pla2Var[i]) << (48 + 4*i)); z |= (((word)7) << (48 + 4*i)); return z; } static inline int If_Dec6CountOnes( word t ) { t = (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555)); t = (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333)); t = (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F)); t = (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF)); t = (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF)); return (t & ABC_CONST(0x00000000FFFFFFFF)) + (t>>32); } static inline int If_Dec6HasVar( word t, int v ) { return ((t & Truth6[v]) >> (1<= 0 && v < 7 ); if ( v == 6 ) return t[0] != t[1]; return ((t[0] & Truth6[v]) >> (1<> (1< 1 ); if ( Count == 2 ) return !fDerive ? 1 : If_Dec6DeriveDisjoint( t, Pla2Var, Var2Pla ); // check non-disjoint decomposition if ( !r && (Count == 3 || Count == 4) ) { for ( x = 0; x < 4; x++ ) { word c0 = If_Dec6Cofactor( t, x+2, 0 ); word c1 = If_Dec6Cofactor( t, x+2, 1 ); if ( If_Dec6CofCount2( c0 ) <= 2 && If_Dec6CofCount2( c1 ) <= 2 ) { r = !fDerive ? 1 : If_Dec6DeriveNonDisjoint( t, x+2, Pla2Var, Var2Pla ); break; } } } } assert( i == 15 ); return r; } word If_Dec7Perform( word t0[2], int fDerive ) { word t[2] = {t0[0], t0[1]}; int i, v, u, y, Pla2Var[7], Var2Pla[7]; // start arrays for ( i = 0; i < 7; i++ ) { /* if ( i < 6 ) assert( If_Dec6HasVar( t[0], i ) || If_Dec6HasVar( t[1], i ) ); else assert( t[0] != t[1] ); */ Pla2Var[i] = Var2Pla[i] = i; } // generate permutations for ( v = 0; v < 7; v++ ) for ( u = v+1; u < 7; u++ ) for ( y = u+1; y < 7; y++ ) { If_Dec7MoveTo( t, v, 0, Pla2Var, Var2Pla ); If_Dec7MoveTo( t, u, 1, Pla2Var, Var2Pla ); If_Dec7MoveTo( t, y, 2, Pla2Var, Var2Pla ); // If_DecVerifyPerm( Pla2Var, Var2Pla ); if ( If_Dec7CofCount3( t ) == 2 ) { return !fDerive ? 1 : If_Dec7DeriveDisjoint( t, Pla2Var, Var2Pla ); } } return 0; } // support minimization static inline int If_DecSuppIsMinBase( int Supp ) { return (Supp & (Supp+1)) == 0; } static inline word If_Dec6TruthShrink( word uTruth, int nVars, int nVarsAll, unsigned Phase ) { int i, k, Var = 0; assert( nVarsAll <= 6 ); for ( i = 0; i < nVarsAll; i++ ) if ( Phase & (1 << i) ) { for ( k = i-1; k >= Var; k-- ) uTruth = If_Dec6SwapAdjacent( uTruth, k ); Var++; } assert( Var == nVars ); return uTruth; } word If_Dec6MinimumBase( word uTruth, int * pSupp, int nVarsAll, int * pnVars ) { int v, iVar = 0, uSupp = 0; assert( nVarsAll <= 6 ); for ( v = 0; v < nVarsAll; v++ ) if ( If_Dec6HasVar( uTruth, v ) ) { uSupp |= (1 << v); if ( pSupp ) pSupp[iVar] = pSupp[v]; iVar++; } if ( pnVars ) *pnVars = iVar; if ( If_DecSuppIsMinBase( uSupp ) ) return uTruth; return If_Dec6TruthShrink( uTruth, iVar, nVarsAll, uSupp ); } static inline void If_Dec7TruthShrink( word uTruth[2], int nVars, int nVarsAll, unsigned Phase ) { int i, k, Var = 0; assert( nVarsAll <= 7 ); for ( i = 0; i < nVarsAll; i++ ) if ( Phase & (1 << i) ) { for ( k = i-1; k >= Var; k-- ) If_Dec7SwapAdjacent( uTruth, k ); Var++; } assert( Var == nVars ); } void If_Dec7MinimumBase( word uTruth[2], int * pSupp, int nVarsAll, int * pnVars ) { int v, iVar = 0, uSupp = 0; assert( nVarsAll <= 7 ); for ( v = 0; v < nVarsAll; v++ ) if ( If_Dec7HasVar( uTruth, v ) ) { uSupp |= (1 << v); if ( pSupp ) pSupp[iVar] = pSupp[v]; iVar++; } if ( pnVars ) *pnVars = iVar; if ( If_DecSuppIsMinBase( uSupp ) ) return; If_Dec7TruthShrink( uTruth, iVar, nVarsAll, uSupp ); } // check for MUX decomposition static inline int If_Dec6SuppSize( word t ) { int v, Count = 0; for ( v = 0; v < 6; v++ ) if ( If_Dec6Cofactor(t, v, 0) != If_Dec6Cofactor(t, v, 1) ) Count++; return Count; } static inline int If_Dec6CheckMux( word t ) { int v; for ( v = 0; v < 6; v++ ) if ( If_Dec6SuppSize(If_Dec6Cofactor(t, v, 0)) < 5 && If_Dec6SuppSize(If_Dec6Cofactor(t, v, 1)) < 5 ) return v; return -1; } // check for MUX decomposition static inline void If_Dec7Cofactor( word t[2], int iVar, int fCof1, word r[2] ) { assert( iVar >= 0 && iVar < 7 ); if ( iVar == 6 ) { if ( fCof1 ) r[0] = r[1] = t[1]; else r[0] = r[1] = t[0]; } else { if ( fCof1 ) { r[0] = (t[0] & Truth6[iVar]) | ((t[0] & Truth6[iVar]) >> (1<> (1< Count0 + Count1 ) { CountBest = Count0 + Count1; vBest = v; Cofs[0] = If_Dec6Cofactor(t, v, 0); Cofs[1] = If_Dec6Cofactor(t, v, 1); } } return vBest; } int If_Dec7PickBestMux( word t[2], word c0r[2], word c1r[2] ) { word c0[2], c1[2]; int v, vBest = -1, Count0, Count1, CountBest = 1000; for ( v = 0; v < 7; v++ ) { If_Dec7Cofactor( t, v, 0, c0 ); If_Dec7Cofactor( t, v, 1, c1 ); Count0 = If_Dec7SuppSize(c0); Count1 = If_Dec7SuppSize(c1); if ( Count0 < 5 && Count1 < 5 && CountBest > Count0 + Count1 ) { CountBest = Count0 + Count1; vBest = v; c0r[0] = c0[0]; c0r[1] = c0[1]; c1r[0] = c1[0]; c1r[1] = c1[1]; } } return vBest; } /**Function************************************************************* Synopsis [Checks decomposability ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // count the number of unique cofactors static inline word If_Dec5CofCount2( word t, int x, int y, int * Pla2Var, word t0, int fDerive ) { int m, i, Mask; assert( x >= 0 && x < 4 ); assert( y >= 0 && y < 4 ); for ( m = 0; m < 4; m++ ) { for ( Mask = i = 0; i < 16; i++ ) if ( ((i >> x) & 1) == ((m >> 0) & 1) && ((i >> y) & 1) == ((m >> 1) & 1) ) Mask |= (1 << ((t >> (i<<1)) & 3)); if ( BitCount8[Mask & 0xF] > 2 ) return 0; } // Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf( "\n" ); if ( !fDerive ) return 1; else { int fHas2, fHas3; // composition function C depends on {x, y, Out, v[0]} // decomposed function D depends on {x, y, z1, z2} word F[4] = { 0, ABC_CONST(0x5555555555555555), ABC_CONST(0xAAAAAAAAAAAAAAAA), ~((word)0) }; word C2[4], D2[4] = {0}, C1[2], D1[2], C, D, z; int v, zz1 = -1, zz2 = -1; // find two variables for ( v = 0; v < 4; v++ ) if ( v != x && v != y ) { zz1 = v; break; } for ( v = 1; v < 4; v++ ) if ( v != x && v != y && v != zz1 ) { zz2 = v; break; } assert( zz1 != -1 && zz2 != -1 ); // find the cofactors for ( m = 0; m < 4; m++ ) { // for each cofactor, derive C2 and D2 for ( Mask = i = 0; i < 16; i++ ) if ( ((i >> x) & 1) == ((m >> 0) & 1) && ((i >> y) & 1) == ((m >> 1) & 1) ) Mask |= (1 << ((t >> (i<<1)) & 3)); // find the values if ( BitCount8[Mask & 0xF] == 1 ) { C2[m] = F[Abc_Tt6FirstBit( Mask )]; D2[m] = ~(word)0; } else if ( BitCount8[Mask & 0xF] == 2 ) { int Bit0 = Abc_Tt6FirstBit( Mask ); int Bit1 = Abc_Tt6FirstBit( Mask ^ (((word)1)<> x) & 1) == ((m >> 0) & 1) && ((i >> y) & 1) == ((m >> 1) & 1) ) if ( Bit1 == ((t >> (i<<1)) & 3) ) D2[m] |= (((word)1) << ( (((i >> zz2) & 1) << 1) | ((i >> zz1) & 1) )); } else assert( 0 ); D2[m] = Abc_Tt6Stretch( D2[m], 2 ); } // combine C1[0] = (C2[1] & Truth6[2]) | (C2[0] & ~Truth6[2]); C1[1] = (C2[3] & Truth6[2]) | (C2[2] & ~Truth6[2]); C = (C1[1] & Truth6[3]) | (C1[0] & ~Truth6[3]); // combine D1[0] = (D2[1] & Truth6[2]) | (D2[0] & ~Truth6[2]); D1[1] = (D2[3] & Truth6[2]) | (D2[2] & ~Truth6[2]); D = (D1[1] & Truth6[3]) | (D1[0] & ~Truth6[3]); // printf( "\n" ); // Kit_DsdPrintFromTruth( (unsigned *)&C, 5 ); printf("\n"); // Kit_DsdPrintFromTruth( (unsigned *)&D, 5 ); printf("\n"); // create configuration // find one fHas2 = Abc_TtHasVar(&D, 5, 2); fHas3 = Abc_TtHasVar(&D, 5, 3); if ( fHas2 && fHas3 ) { z = D & 0xFFFF; z |= (((word)Pla2Var[zz1+1]) << (16 + 4*0)); z |= (((word)Pla2Var[zz2+1]) << (16 + 4*1)); z |= (((word)Pla2Var[x+1]) << (16 + 4*2)); z |= (((word)Pla2Var[y+1]) << (16 + 4*3)); } else if ( fHas2 && !fHas3 ) { z = D & 0xFFFF; z |= (((word)Pla2Var[zz1+1]) << (16 + 4*0)); z |= (((word)Pla2Var[zz2+1]) << (16 + 4*1)); z |= (((word)Pla2Var[x+1]) << (16 + 4*2)); z |= (((word)6) << (16 + 4*3)); } else if ( !fHas2 && fHas3 ) { Abc_TtSwapVars( &D, 5, 2, 3 ); z = D & 0xFFFF; z |= (((word)Pla2Var[zz1+1]) << (16 + 4*0)); z |= (((word)Pla2Var[zz2+1]) << (16 + 4*1)); z |= (((word)Pla2Var[y+1]) << (16 + 4*2)); z |= (((word)6) << (16 + 4*3)); } else { z = D & 0xFFFF; z |= (((word)Pla2Var[zz1+1]) << (16 + 4*0)); z |= (((word)Pla2Var[zz2+1]) << (16 + 4*1)); z |= (((word)6) << (16 + 4*2)); z |= (((word)6) << (16 + 4*3)); } // second one fHas2 = Abc_TtHasVar(&C, 5, 2); fHas3 = Abc_TtHasVar(&C, 5, 3); if ( fHas2 && fHas3 ) { z |= ((C & 0xFFFF) << 32); z |= (((word)Pla2Var[0]) << (48 + 4*0)); z |= (((word)7) << (48 + 4*1)); z |= (((word)Pla2Var[x+1]) << (48 + 4*2)); z |= (((word)Pla2Var[y+1]) << (48 + 4*3)); } else if ( fHas2 && !fHas3 ) { z |= ((C & 0xFFFF) << 32); z |= (((word)Pla2Var[0]) << (48 + 4*0)); z |= (((word)7) << (48 + 4*1)); z |= (((word)Pla2Var[x+1]) << (48 + 4*2)); z |= (((word)6) << (48 + 4*3)); } else if ( !fHas2 && fHas3 ) { Abc_TtSwapVars( &C, 5, 2, 3 ); z |= ((C & 0xFFFF) << 32); z |= (((word)Pla2Var[0]) << (48 + 4*0)); z |= (((word)7) << (48 + 4*1)); z |= (((word)Pla2Var[y+1]) << (48 + 4*2)); z |= (((word)6) << (48 + 4*3)); } else { z |= ((C & 0xFFFF) << 32); z |= (((word)Pla2Var[0]) << (48 + 4*0)); z |= (((word)7) << (48 + 4*1)); z |= (((word)6) << (48 + 4*2)); z |= (((word)6) << (48 + 4*3)); } // verify { word t1 = If_Dec6Truth( z ); if ( t1 != t0 ) { printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&C2[0], 5 ); printf("\n"); Kit_DsdPrintFromTruth( (unsigned *)&C2[1], 5 ); printf("\n"); Kit_DsdPrintFromTruth( (unsigned *)&C2[2], 5 ); printf("\n"); Kit_DsdPrintFromTruth( (unsigned *)&C2[3], 5 ); printf("\n"); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&D2[0], 5 ); printf("\n"); Kit_DsdPrintFromTruth( (unsigned *)&D2[1], 5 ); printf("\n"); Kit_DsdPrintFromTruth( (unsigned *)&D2[2], 5 ); printf("\n"); Kit_DsdPrintFromTruth( (unsigned *)&D2[3], 5 ); printf("\n"); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&C, 5 ); printf("\n"); Kit_DsdPrintFromTruth( (unsigned *)&D, 5 ); printf("\n"); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&t1, 5 ); printf("\n"); Kit_DsdPrintFromTruth( (unsigned *)&t0, 5 ); printf("\n"); } assert( t1 == t0 ); } return z; } } word If_Dec5Perform( word t, int fDerive ) { int Pla2Var[7], Var2Pla[7]; int i, j, v; word t0 = t; /* word c0, c1, c00, c01, c10, c11; for ( i = 0; i < 5; i++ ) { c0 = If_Dec6Cofactor( t, i, 0 ); c1 = If_Dec6Cofactor( t, i, 1 ); if ( c0 == 0 ) return 1; if ( ~c0 == 0 ) return 1; if ( c1 == 0 ) return 1; if ( ~c1 == 0 ) return 1; if ( c0 == ~c1 ) return 1; } for ( i = 0; i < 4; i++ ) { c0 = If_Dec6Cofactor( t, i, 0 ); c1 = If_Dec6Cofactor( t, i, 1 ); for ( j = i + 1; j < 5; j++ ) { c00 = If_Dec6Cofactor( c0, j, 0 ); c01 = If_Dec6Cofactor( c0, j, 1 ); c10 = If_Dec6Cofactor( c1, j, 0 ); c11 = If_Dec6Cofactor( c1, j, 1 ); if ( c00 == c01 && c00 == c10 ) return 1; if ( c11 == c01 && c11 == c10 ) return 1; if ( c11 == c00 && c11 == c01 ) return 1; if ( c11 == c00 && c11 == c10 ) return 1; if ( c00 == c11 && c01 == c10 ) return 1; } } */ // start arrays for ( i = 0; i < 7; i++ ) Pla2Var[i] = Var2Pla[i] = i; // generate permutations for ( v = 0; v < 5; v++ ) { t = If_Dec6MoveTo( t, v, 0, Pla2Var, Var2Pla ); If_DecVerifyPerm( Pla2Var, Var2Pla ); for ( i = 0; i < 4; i++ ) for ( j = i + 1; j < 4; j++ ) { word z = If_Dec5CofCount2( t, i, j, Pla2Var, t0, fDerive ); if ( z ) { /* if ( v == 0 && i == 1 && j == 2 ) { Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf( "\n" ); } */ return z; } } } /* // start arrays for ( i = 0; i < 7; i++ ) Pla2Var[i] = Var2Pla[i] = i; t = t0; for ( v = 0; v < 5; v++ ) { int x, y; t = If_Dec6MoveTo( t, v, 0, Pla2Var, Var2Pla ); If_DecVerifyPerm( Pla2Var, Var2Pla ); for ( i = 0; i < 16; i++ ) printf( "%d ", ((t >> (i<<1)) & 3) ); printf( "\n" ); for ( x = 0; x < 4; x++ ) for ( y = x + 1; y < 4; y++ ) { for ( i = 0; i < 16; i++ ) if ( !((i >> x) & 1) && !((i >> y) & 1) ) printf( "%d ", ((t >> (i<<1)) & 3) ); printf( "\n" ); for ( i = 0; i < 16; i++ ) if ( ((i >> x) & 1) && !((i >> y) & 1) ) printf( "%d ", ((t >> (i<<1)) & 3) ); printf( "\n" ); for ( i = 0; i < 16; i++ ) if ( !((i >> x) & 1) && ((i >> y) & 1) ) printf( "%d ", ((t >> (i<<1)) & 3) ); printf( "\n" ); for ( i = 0; i < 16; i++ ) if ( ((i >> x) & 1) && ((i >> y) & 1) ) printf( "%d ", ((t >> (i<<1)) & 3) ); printf( "\n" ); printf( "\n" ); } } */ // Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf( "\n" ); return 0; } word If_Dec5PerformEx() { word z; // find one z = (word)(0x17ac & 0xFFFF); z |= (((word)3) << (16 + 4*0)); z |= (((word)4) << (16 + 4*1)); z |= (((word)1) << (16 + 4*2)); z |= (((word)2) << (16 + 4*3)); // second one z |= (((word)(0x179a & 0xFFFF)) << 32); z |= (((word)0) << (48 + 4*0)); z |= (((word)7) << (48 + 4*1)); z |= (((word)1) << (48 + 4*2)); z |= (((word)2) << (48 + 4*3)); return z; } void If_Dec5PerformTest() { word z, t, t1; // s = If_Dec5PerformEx(); // t = If_Dec6Truth( s ); t = 0xB0F3B0FFB0F3B0FF; Kit_DsdPrintFromTruth( (unsigned *)&t, 5 ); printf("\n"); z = If_Dec5Perform( t, 1 ); t1 = If_Dec6Truth( z ); assert( t == t1 ); } /**Function************************************************************* Synopsis [Performs additional check.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word If_CutPerformDerive07( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ) { if ( nLeaves < 5 ) return 1; if ( nLeaves == 5 ) { word z, t = ((word)pTruth[0] << 32) | (word)pTruth[0]; z = If_Dec5Perform( t, 1 ); If_Dec6Verify( t, z ); return z; } if ( nLeaves == 6 ) { word z, t = ((word *)pTruth)[0]; z = If_Dec6Perform( t, 1 ); If_Dec6Verify( t, z ); return z; } if ( nLeaves == 7 ) { word z, t[2]; t[0] = ((word *)pTruth)[0]; t[1] = ((word *)pTruth)[1]; z = If_Dec7Perform( t, 1 ); If_Dec7Verify( t, z ); return z; } assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Performs additional check.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutPerformCheck07( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ) { int fDerive = 0; int v; // skip non-support minimal for ( v = 0; v < nLeaves; v++ ) if ( !Abc_TtHasVar( (word *)pTruth, nVars, v ) ) return 0; // check if ( nLeaves < 5 ) return 1; if ( nLeaves == 5 ) { word z, t = ((word)pTruth[0] << 32) | (word)pTruth[0]; z = If_Dec5Perform( t, fDerive ); if ( fDerive && z ) If_Dec6Verify( t, z ); return z != 0; } if ( nLeaves == 6 ) { word z, t = ((word *)pTruth)[0]; z = If_Dec6Perform( t, fDerive ); if ( fDerive && z ) { // If_DecPrintConfig( z ); If_Dec6Verify( t, z ); } // if ( z == 0 ) // Extra_PrintHex(stdout, (unsigned *)&t, 6), printf( " " ), Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ), printf( "\n" ); return z != 0; } if ( nLeaves == 7 ) { word z, t[2]; t[0] = ((word *)pTruth)[0]; t[1] = ((word *)pTruth)[1]; // if ( If_Dec7CheckMux(t) >= 0 ) // return 1; z = If_Dec7Perform( t, fDerive ); if ( fDerive && z ) If_Dec7Verify( t, z ); return z != 0; } assert( 0 ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifDec08.c000066400000000000000000000470611300674244400225450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifDec08.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Performs additional check.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifDec08.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "misc/extra/extra.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the bit count for the first 256 integer numbers static int BitCount8[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; // elementary truth tables static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; static word Truth10[10][16] = { {ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA)}, {ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC)}, {ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0)}, {ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00)}, {ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000)}, {ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)} }; extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int If_Dec08WordNum( int nVars ) { return nVars <= 6 ? 1 : 1 << (nVars-6); } static void If_Dec08PrintConfigOne( unsigned z ) { unsigned t; t = (z & 0xffff) | ((z & 0xffff) << 16); Extra_PrintBinary( stdout, &t, 16 ); printf( " " ); Kit_DsdPrintFromTruth( &t, 4 ); printf( " " ); printf( " %d", (z >> 16) & 7 ); printf( " %d", (z >> 20) & 7 ); printf( " %d", (z >> 24) & 7 ); printf( " %d", (z >> 28) & 7 ); printf( "\n" ); } void If_Dec08PrintConfig( unsigned * pZ ) { while ( *pZ ) If_Dec08PrintConfigOne( *pZ++ ); } static inline void If_Dec08ComposeLut4( int t, word ** pF, word * pR, int nVars ) { word pC[16]; int m, w, v, nWords; assert( nVars <= 10 ); nWords = If_Dec08WordNum( nVars ); for ( w = 0; w < nWords; w++ ) pR[w] = 0; for ( m = 0; m < 16; m++ ) { if ( !((t >> m) & 1) ) continue; for ( w = 0; w < nWords; w++ ) pC[w] = ~(word)0; for ( v = 0; v < 4; v++ ) for ( w = 0; w < nWords; w++ ) pC[w] &= ((m >> v) & 1) ? pF[v][w] : ~pF[v][w]; for ( w = 0; w < nWords; w++ ) pR[w] |= pC[w]; } } void If_Dec08Verify( word * pF, int nVars, unsigned * pZ ) { word pN[16][16], * pG[4]; int i, w, v, k, nWords; unsigned z; nWords = If_Dec08WordNum( nVars ); for ( k = 0; k < nVars; k++ ) for ( w = 0; w < nWords; w++ ) pN[k][w] = Truth10[k][w]; for ( i = 0; (z = pZ[i]); i++, k++ ) { for ( v = 0; v < 4; v++ ) pG[v] = pN[ (z >> (16+(v<<2))) & 7 ]; If_Dec08ComposeLut4( (int)(z & 0xffff), pG, pN[k], nVars ); } k--; for ( w = 0; w < nWords; w++ ) if ( pN[k][w] != pF[w] ) { If_Dec08PrintConfig( pZ ); Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pN[k], nVars ); printf( "\n" ); printf( "Verification failed!\n" ); break; } } // count the number of unique cofactors static inline int If_Dec08CofCount2( word * pF, int nVars ) { int nShift = (1 << (nVars - 3)); word Mask = (((word)1) << nShift) - 1; word iCof0 = pF[0] & Mask; word iCof1 = iCof0, iCof; int i; assert( nVars >= 6 && nVars <= 8 ); // if ( nVars == 10 ) // Mask = ~(word)0; for ( i = 1; i < 8; i++ ) { iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask; if ( iCof == iCof0 ) continue; if ( iCof1 == iCof0 ) iCof1 = iCof; else if ( iCof != iCof1 ) return 3; } return 2; } static inline int If_Dec08CofCount( word * pF, int nVars ) { int nShift = (1 << (nVars - 3)); word Mask = (((word)1) << nShift) - 1; word iCofs[16], iCof; int i, c, nCofs = 1; // if ( nVars == 10 ) // Mask = ~(word)0; iCofs[0] = pF[0] & Mask; for ( i = 1; i < 8; i++ ) { iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask; for ( c = 0; c < nCofs; c++ ) if ( iCof == iCofs[c] ) break; if ( c == nCofs ) iCofs[nCofs++] = iCof; } return nCofs; } // variable permutation for large functions static inline void If_Dec08Copy( word * pOut, word * pIn, int nVars ) { int w, nWords = If_Dec08WordNum( nVars ); for ( w = 0; w < nWords; w++ ) pOut[w] = pIn[w]; } static inline void If_Dec08SwapAdjacent( word * pOut, word * pIn, int iVar, int nVars ) { int i, k, nWords = If_Dec08WordNum( nVars ); assert( iVar < nVars - 1 ); if ( iVar < 5 ) { int Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); } else if ( iVar > 5 ) { int Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 4*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pIn[i]; for ( i = 0; i < Step; i++ ) pOut[Step+i] = pIn[2*Step+i]; for ( i = 0; i < Step; i++ ) pOut[2*Step+i] = pIn[Step+i]; for ( i = 0; i < Step; i++ ) pOut[3*Step+i] = pIn[3*Step+i]; pIn += 4*Step; pOut += 4*Step; } } else // if ( iVar == 5 ) { for ( i = 0; i < nWords; i += 2 ) { pOut[i] = (pIn[i] & ABC_CONST(0x00000000FFFFFFFF)) | ((pIn[i+1] & ABC_CONST(0x00000000FFFFFFFF)) << 32); pOut[i+1] = (pIn[i+1] & ABC_CONST(0xFFFFFFFF00000000)) | ((pIn[i] & ABC_CONST(0xFFFFFFFF00000000)) >> 32); } } } static inline void If_Dec08MoveTo( word * pF, int nVars, int v, int p, int Pla2Var[], int Var2Pla[] ) { word pG[16], * pIn = pF, * pOut = pG, * pTemp; int iPlace0, iPlace1, Count = 0; assert( Var2Pla[v] <= p ); while ( Var2Pla[v] != p ) { iPlace0 = Var2Pla[v]; iPlace1 = Var2Pla[v]+1; If_Dec08SwapAdjacent( pOut, pIn, iPlace0, nVars ); pTemp = pIn; pIn = pOut, pOut = pTemp; Var2Pla[Pla2Var[iPlace0]]++; Var2Pla[Pla2Var[iPlace1]]--; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Count++; } if ( Count & 1 ) If_Dec08Copy( pF, pIn, nVars ); assert( Pla2Var[p] == v ); } /* // derive binary function static inline int If_Dec08DeriveCount2( word * pF, word * pRes, int nVars ) { int nShift = (1 << (nVars - 4)); word Mask = (((word)1) << nShift) - 1; int i, MaskDec = 0; word iCof0 = pF[0] & Mask; word iCof1 = pF[0] & Mask; word iCof, * pCof0, * pCof1; if ( nVars == 10 ) Mask = ~(word)0; for ( i = 1; i < 16; i++ ) { iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask; if ( *pCof0 != iCof ) { *pCof1 = iCof; MaskDec |= (1 << i); } } *pRes = ((iCof1 << nShift) | iCof0); return MaskDec; } static inline word If_DecTruthStretch( word t, int nVars ) { assert( nVars > 1 ); if ( nVars == 1 ) nVars++, t = (t & 0x3) | ((t & 0x3) << 2); if ( nVars == 2 ) nVars++, t = (t & 0xF) | ((t & 0xF) << 4); if ( nVars == 3 ) nVars++, t = (t & 0xFF) | ((t & 0xFF) << 8); if ( nVars == 4 ) nVars++, t = (t & 0xFFFF) | ((t & 0xFFFF) << 16); if ( nVars == 5 ) nVars++, t = (t & 0xFFFFFFFF) | ((t & 0xFFFFFFFF) << 32); assert( nVars >= 6 ); } */ // support minimization static inline int If_DecSuppIsMinBase( int Supp ) { return (Supp & (Supp+1)) == 0; } static inline int If_Dec08HasVar( word * t, int nVars, int iVar ) { int nWords = If_Dec08WordNum( nVars ); assert( iVar < nVars ); if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) if ( (t[i] & ~Truth6[iVar]) != ((t[i] & Truth6[iVar]) >> Shift) ) return 1; return 0; } else { int i, k, Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) if ( t[i] != t[Step+i] ) return 1; t += 2*Step; } return 0; } } static inline int If_Dec08Support( word * t, int nVars ) { int v, Supp = 0; for ( v = 0; v < nVars; v++ ) if ( If_Dec08HasVar( t, nVars, v ) ) Supp |= (1 << v); return Supp; } // checks void If_Dec08Cofactors( word * pF, int nVars, int iVar, word * pCof0, word * pCof1 ) { int nWords = If_Dec08WordNum( nVars ); assert( iVar < nVars ); if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) { pCof0[i] = (pF[i] & ~Truth6[iVar]) | ((pF[i] & ~Truth6[iVar]) << Shift); pCof1[i] = (pF[i] & Truth6[iVar]) | ((pF[i] & Truth6[iVar]) >> Shift); } return; } else { int i, k, Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pCof0[i] = pCof0[Step+i] = pF[i]; pCof1[i] = pCof1[Step+i] = pF[Step+i]; } pF += 2*Step; pCof0 += 2*Step; pCof1 += 2*Step; } return; } } static inline int If_Dec08Count16( int Num16 ) { assert( Num16 < (1<<16)-1 ); return BitCount8[Num16 & 255] + BitCount8[(Num16 >> 8) & 255]; } static inline void If_DecVerifyPerm( int Pla2Var[10], int Var2Pla[10], int nVars ) { int i; for ( i = 0; i < nVars; i++ ) assert( Pla2Var[Var2Pla[i]] == i ); } int If_Dec08Perform( word * pF, int nVars, int fDerive ) { // static int Cnt = 0; word pCof0[16], pCof1[16]; int Pla2Var[10], Var2Pla[10], Count[210], Masks[210]; int i, i0,i1,i2, v, x; assert( nVars >= 6 && nVars <= 8 ); // start arrays for ( i = 0; i < nVars; i++ ) { assert( If_Dec08HasVar( pF, nVars, i ) ); Pla2Var[i] = Var2Pla[i] = i; } /* Cnt++; //if ( Cnt == 108 ) { printf( "%d\n", Cnt ); //Extra_PrintHex( stdout, (unsigned *)pF, nVars ); //printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)pF, nVars ); printf( "\n" ); printf( "\n" ); } */ // generate permutations v = 0; for ( i0 = 0; i0 < nVars; i0++ ) for ( i1 = i0+1; i1 < nVars; i1++ ) for ( i2 = i1+1; i2 < nVars; i2++, v++ ) { If_Dec08MoveTo( pF, nVars, i0, nVars-1, Pla2Var, Var2Pla ); If_Dec08MoveTo( pF, nVars, i1, nVars-2, Pla2Var, Var2Pla ); If_Dec08MoveTo( pF, nVars, i2, nVars-3, Pla2Var, Var2Pla ); If_DecVerifyPerm( Pla2Var, Var2Pla, nVars ); Count[v] = If_Dec08CofCount( pF, nVars ); Masks[v] = (1 << i0) | (1 << i1) | (1 << i2); assert( Count[v] > 1 ); //printf( "%d ", Count[v] ); if ( Count[v] == 2 || Count[v] > 5 ) continue; for ( x = 0; x < 4; x++ ) { If_Dec08Cofactors( pF, nVars, nVars-1-x, pCof0, pCof1 ); if ( If_Dec08CofCount2(pCof0, nVars) <= 2 && If_Dec08CofCount2(pCof1, nVars) <= 2 ) { Count[v] = -Count[v]; break; } } } //printf( "\n" ); assert( v <= 210 ); // check if there are compatible bound sets for ( i0 = 0; i0 < v; i0++ ) for ( i1 = i0+1; i1 < v; i1++ ) { if ( If_Dec08Count16(Masks[i0] & Masks[i1]) > 8 - nVars ) continue; if ( nVars == 8 ) { if ( Count[i0] == 2 && Count[i1] == 2 ) return 1; } else if ( nVars == 7 ) { if ( (Count[i0] == 2 && Count[i1] == 2) || (Count[i0] == 2 && Count[i1] < 0) || (Count[i0] < 0 && Count[i1] == 2) ) return 1; } else { if ( (Count[i0] == 2 && Count[i1] == 2) || (Count[i0] == 2 && Count[i1] < 0) || (Count[i0] < 0 && Count[i1] == 2) || (Count[i0] < 0 && Count[i1] < 0) ) return 1; } } // printf( "not found\n" ); return 0; } /**Function************************************************************* Synopsis [Performs additional check.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutPerformCheck08( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ) { int nSupp, fDerive = 0; word pF[16]; if ( nLeaves <= 5 ) return 1; If_Dec08Copy( pF, (word *)pTruth, nVars ); nSupp = If_Dec08Support( pF, nLeaves ); if ( !nSupp || !If_DecSuppIsMinBase(nSupp) ) return 0; if ( If_Dec08Perform( pF, nLeaves, fDerive ) ) { // printf( "1" ); return 1; // If_Dec08Verify( t, nLeaves, NULL ); } // printf( "0" ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifDec10.c000066400000000000000000000470461300674244400225410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifDec10.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Performs additional check.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifDec10.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "misc/extra/extra.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the bit count for the first 256 integer numbers static int BitCount8[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; // elementary truth tables static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; static word Truth10[10][16] = { {ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA)}, {ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC)}, {ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0)}, {ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00)}, {ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000)}, {ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF)} }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int If_Dec10WordNum( int nVars ) { return nVars <= 6 ? 1 : 1 << (nVars-6); } static void If_Dec10PrintConfigOne( unsigned z ) { unsigned t; t = (z & 0xffff) | ((z & 0xffff) << 16); Extra_PrintBinary( stdout, &t, 16 ); printf( " " ); Kit_DsdPrintFromTruth( &t, 4 ); printf( " " ); printf( " %d", (z >> 16) & 7 ); printf( " %d", (z >> 20) & 7 ); printf( " %d", (z >> 24) & 7 ); printf( " %d", (z >> 28) & 7 ); printf( "\n" ); } void If_Dec10PrintConfig( unsigned * pZ ) { while ( *pZ ) If_Dec10PrintConfigOne( *pZ++ ); } static inline void If_Dec10ComposeLut4( int t, word ** pF, word * pR, int nVars ) { word pC[16]; int m, w, v, nWords; assert( nVars <= 10 ); nWords = If_Dec10WordNum( nVars ); for ( w = 0; w < nWords; w++ ) pR[w] = 0; for ( m = 0; m < 16; m++ ) { if ( !((t >> m) & 1) ) continue; for ( w = 0; w < nWords; w++ ) pC[w] = ~(word)0; for ( v = 0; v < 4; v++ ) for ( w = 0; w < nWords; w++ ) pC[w] &= ((m >> v) & 1) ? pF[v][w] : ~pF[v][w]; for ( w = 0; w < nWords; w++ ) pR[w] |= pC[w]; } } void If_Dec10Verify( word * pF, int nVars, unsigned * pZ ) { word pN[16][16], * pG[4]; int i, w, v, k, nWords; unsigned z; nWords = If_Dec10WordNum( nVars ); for ( k = 0; k < nVars; k++ ) for ( w = 0; w < nWords; w++ ) pN[k][w] = Truth10[k][w]; for ( i = 0; (z = pZ[i]); i++, k++ ) { for ( v = 0; v < 4; v++ ) pG[v] = pN[ (z >> (16+(v<<2))) & 7 ]; If_Dec10ComposeLut4( (int)(z & 0xffff), pG, pN[k], nVars ); } k--; for ( w = 0; w < nWords; w++ ) if ( pN[k][w] != pF[w] ) { If_Dec10PrintConfig( pZ ); Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pN[k], nVars ); printf( "\n" ); printf( "Verification failed!\n" ); break; } } // count the number of unique cofactors static inline int If_Dec10CofCount2( word * pF, int nVars ) { int nShift = (1 << (nVars - 4)); word Mask = (((word)1) << nShift) - 1; word iCof0 = pF[0] & Mask; word iCof1 = iCof0, iCof; int i; assert( nVars > 6 && nVars <= 10 ); if ( nVars == 10 ) Mask = ~(word)0; for ( i = 1; i < 16; i++ ) { iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask; if ( iCof == iCof0 ) continue; if ( iCof1 == iCof0 ) iCof1 = iCof; else if ( iCof != iCof1 ) return 3; } return 2; } static inline int If_Dec10CofCount( word * pF, int nVars ) { int nShift = (1 << (nVars - 4)); word Mask = (((word)1) << nShift) - 1; word iCofs[16], iCof; int i, c, nCofs = 1; if ( nVars == 10 ) Mask = ~(word)0; iCofs[0] = pF[0] & Mask; for ( i = 1; i < 16; i++ ) { iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask; for ( c = 0; c < nCofs; c++ ) if ( iCof == iCofs[c] ) break; if ( c == nCofs ) iCofs[nCofs++] = iCof; } return nCofs; } // variable permutation for large functions static inline void If_Dec10Copy( word * pOut, word * pIn, int nVars ) { int w, nWords = If_Dec10WordNum( nVars ); for ( w = 0; w < nWords; w++ ) pOut[w] = pIn[w]; } static inline void If_Dec10SwapAdjacent( word * pOut, word * pIn, int iVar, int nVars ) { int i, k, nWords = If_Dec10WordNum( nVars ); assert( iVar < nVars - 1 ); if ( iVar < 5 ) { int Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); } else if ( iVar > 5 ) { int Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 4*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pIn[i]; for ( i = 0; i < Step; i++ ) pOut[Step+i] = pIn[2*Step+i]; for ( i = 0; i < Step; i++ ) pOut[2*Step+i] = pIn[Step+i]; for ( i = 0; i < Step; i++ ) pOut[3*Step+i] = pIn[3*Step+i]; pIn += 4*Step; pOut += 4*Step; } } else // if ( iVar == 5 ) { for ( i = 0; i < nWords; i += 2 ) { pOut[i] = (pIn[i] & ABC_CONST(0x00000000FFFFFFFF)) | ((pIn[i+1] & ABC_CONST(0x00000000FFFFFFFF)) << 32); pOut[i+1] = (pIn[i+1] & ABC_CONST(0xFFFFFFFF00000000)) | ((pIn[i] & ABC_CONST(0xFFFFFFFF00000000)) >> 32); } } } static inline void If_Dec10MoveTo( word * pF, int nVars, int v, int p, int Pla2Var[], int Var2Pla[] ) { word pG[16], * pIn = pF, * pOut = pG, * pTemp; int iPlace0, iPlace1, Count = 0; assert( Var2Pla[v] <= p ); while ( Var2Pla[v] != p ) { iPlace0 = Var2Pla[v]; iPlace1 = Var2Pla[v]+1; If_Dec10SwapAdjacent( pOut, pIn, iPlace0, nVars ); pTemp = pIn; pIn = pOut, pOut = pTemp; Var2Pla[Pla2Var[iPlace0]]++; Var2Pla[Pla2Var[iPlace1]]--; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Count++; } if ( Count & 1 ) If_Dec10Copy( pF, pIn, nVars ); assert( Pla2Var[p] == v ); } /* // derive binary function static inline int If_Dec10DeriveCount2( word * pF, word * pRes, int nVars ) { int nShift = (1 << (nVars - 4)); word Mask = (((word)1) << nShift) - 1; int i, MaskDec = 0; word iCof0 = pF[0] & Mask; word iCof1 = pF[0] & Mask; word iCof, * pCof0, * pCof1; if ( nVars == 10 ) Mask = ~(word)0; for ( i = 1; i < 16; i++ ) { iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask; if ( *pCof0 != iCof ) { *pCof1 = iCof; MaskDec |= (1 << i); } } *pRes = ((iCof1 << nShift) | iCof0); return MaskDec; } static inline word If_DecTruthStretch( word t, int nVars ) { assert( nVars > 1 ); if ( nVars == 1 ) nVars++, t = (t & 0x3) | ((t & 0x3) << 2); if ( nVars == 2 ) nVars++, t = (t & 0xF) | ((t & 0xF) << 4); if ( nVars == 3 ) nVars++, t = (t & 0xFF) | ((t & 0xFF) << 8); if ( nVars == 4 ) nVars++, t = (t & 0xFFFF) | ((t & 0xFFFF) << 16); if ( nVars == 5 ) nVars++, t = (t & 0xFFFFFFFF) | ((t & 0xFFFFFFFF) << 32); assert( nVars >= 6 ); } */ // support minimization static inline int If_DecSuppIsMinBase( int Supp ) { return (Supp & (Supp+1)) == 0; } static inline int If_Dec10HasVar( word * t, int nVars, int iVar ) { int nWords = If_Dec10WordNum( nVars ); assert( iVar < nVars ); if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) if ( (t[i] & ~Truth6[iVar]) != ((t[i] & Truth6[iVar]) >> Shift) ) return 1; return 0; } else { int i, k, Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) if ( t[i] != t[Step+i] ) return 1; t += 2*Step; } return 0; } } static inline int If_Dec10Support( word * t, int nVars ) { int v, Supp = 0; for ( v = 0; v < nVars; v++ ) if ( If_Dec10HasVar( t, nVars, v ) ) Supp |= (1 << v); return Supp; } // checks void If_Dec10Cofactors( word * pF, int nVars, int iVar, word * pCof0, word * pCof1 ) { int nWords = If_Dec10WordNum( nVars ); assert( iVar < nVars ); if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) { pCof0[i] = (pF[i] & ~Truth6[iVar]) | ((pF[i] & ~Truth6[iVar]) << Shift); pCof1[i] = (pF[i] & Truth6[iVar]) | ((pF[i] & Truth6[iVar]) >> Shift); } return; } else { int i, k, Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pCof0[i] = pCof0[Step+i] = pF[i]; pCof1[i] = pCof1[Step+i] = pF[Step+i]; } pF += 2*Step; pCof0 += 2*Step; pCof1 += 2*Step; } return; } } static inline int If_Dec10Count16( int Num16 ) { assert( Num16 < (1<<16)-1 ); return BitCount8[Num16 & 255] + BitCount8[(Num16 >> 8) & 255]; } static inline void If_DecVerifyPerm( int Pla2Var[10], int Var2Pla[10], int nVars ) { int i; for ( i = 0; i < nVars; i++ ) assert( Pla2Var[Var2Pla[i]] == i ); } int If_Dec10Perform( word * pF, int nVars, int fDerive ) { // static int Cnt = 0; word pCof0[16], pCof1[16]; int Pla2Var[10], Var2Pla[10], Count[210], Masks[210]; int i, i0,i1,i2,i3, v, x; assert( nVars >= 6 && nVars <= 10 ); // start arrays for ( i = 0; i < nVars; i++ ) { assert( If_Dec10HasVar( pF, nVars, i ) ); Pla2Var[i] = Var2Pla[i] = i; } /* Cnt++; //if ( Cnt == 108 ) { printf( "%d\n", Cnt ); //Extra_PrintHex( stdout, (unsigned *)pF, nVars ); //printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)pF, nVars ); printf( "\n" ); printf( "\n" ); } */ // generate permutations v = 0; for ( i0 = 0; i0 < nVars; i0++ ) for ( i1 = i0+1; i1 < nVars; i1++ ) for ( i2 = i1+1; i2 < nVars; i2++ ) for ( i3 = i2+1; i3 < nVars; i3++, v++ ) { If_Dec10MoveTo( pF, nVars, i0, nVars-1, Pla2Var, Var2Pla ); If_Dec10MoveTo( pF, nVars, i1, nVars-2, Pla2Var, Var2Pla ); If_Dec10MoveTo( pF, nVars, i2, nVars-3, Pla2Var, Var2Pla ); If_Dec10MoveTo( pF, nVars, i3, nVars-4, Pla2Var, Var2Pla ); If_DecVerifyPerm( Pla2Var, Var2Pla, nVars ); Count[v] = If_Dec10CofCount( pF, nVars ); Masks[v] = (1 << i0) | (1 << i1) | (1 << i2) | (1 << i3); assert( Count[v] > 1 ); //printf( "%d ", Count[v] ); if ( Count[v] == 2 || Count[v] > 5 ) continue; for ( x = 0; x < 4; x++ ) { If_Dec10Cofactors( pF, nVars, nVars-1-x, pCof0, pCof1 ); if ( If_Dec10CofCount2(pCof0, nVars) <= 2 && If_Dec10CofCount2(pCof1, nVars) <= 2 ) { Count[v] = -Count[v]; break; } } } //printf( "\n" ); assert( v <= 210 ); // check if there are compatible bound sets for ( i0 = 0; i0 < v; i0++ ) for ( i1 = i0+1; i1 < v; i1++ ) { if ( If_Dec10Count16(Masks[i0] & Masks[i1]) > 10 - nVars ) continue; if ( nVars == 10 ) { if ( Count[i0] == 2 && Count[i1] == 2 ) return 1; } else if ( nVars == 9 ) { if ( (Count[i0] == 2 && Count[i1] == 2) || (Count[i0] == 2 && Count[i1] < 0) || (Count[i0] < 0 && Count[i1] == 2) ) return 1; } else { if ( (Count[i0] == 2 && Count[i1] == 2) || (Count[i0] == 2 && Count[i1] < 0) || (Count[i0] < 0 && Count[i1] == 2) || (Count[i0] < 0 && Count[i1] < 0) ) return 1; } } // printf( "not found\n" ); return 0; } /**Function************************************************************* Synopsis [Performs additional check.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutPerformCheck10( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ) { int nSupp, fDerive = 0; word pF[16]; if ( nLeaves <= 6 ) return 1; If_Dec10Copy( pF, (word *)pTruth, nVars ); nSupp = If_Dec10Support( pF, nLeaves ); if ( !nSupp || !If_DecSuppIsMinBase(nSupp) ) return 0; if ( If_Dec10Perform( pF, nLeaves, fDerive ) ) { // printf( "1" ); return 1; // If_Dec10Verify( t, nLeaves, NULL ); } // printf( "0" ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifDec16.c000066400000000000000000002305271300674244400225450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifDec16.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Fast checking procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifDec16.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "bool/kit/kit.h" #include "misc/vec/vecMem.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define CLU_VAR_MAX 16 #define CLU_WRD_MAX (1 << ((CLU_VAR_MAX)-6)) #define CLU_MEM_MAX 1000 // 1 GB #define CLU_UNUSED 0xff // decomposition typedef struct If_Grp_t_ If_Grp_t; struct If_Grp_t_ { char nVars; char nMyu; char pVars[CLU_VAR_MAX]; }; // hash table entry typedef struct If_Hte_t_ If_Hte_t; struct If_Hte_t_ { If_Hte_t * pNext; unsigned Group; unsigned Counter; word pTruth[1]; }; // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; // elementary truth tables static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; static word TruthAll[CLU_VAR_MAX][CLU_WRD_MAX] = {{0}}; extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ); extern int If_CluSupportSize( word * t, int nVars ); int s_Count2 = 0; int s_Count3 = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned If_CluGrp2Uns( If_Grp_t * pG ) { char * pChar = (char *)pG; unsigned Res = 0; int i; for ( i = 0; i < 8; i++ ) Res |= ((pChar[i] & 15) << (i << 2)); return Res; } static inline void If_CluUns2Grp( unsigned Group, If_Grp_t * pG ) { char * pChar = (char *)pG; int i; for ( i = 0; i < 8; i++ ) pChar[i] = ((Group >> (i << 2)) & 15); } unsigned int If_CluPrimeCudd( unsigned int p ) { int i,pn; p--; do { p++; if (p&1) { pn = 1; i = 3; while ((unsigned) (i * i) <= p) { if (p % i == 0) { pn = 0; break; } i += 2; } } else { pn = 0; } } while (!pn); return(p); } /* end of Cudd_Prime */ // hash table static inline int If_CluWordNum( int nVars ) { return nVars <= 6 ? 1 : 1 << (nVars-6); } static inline int If_CluCountOnes( word t ) { t = (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555)); t = (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333)); t = (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F)); t = (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF)); t = (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF)); return (t & ABC_CONST(0x00000000FFFFFFFF)) + (t>>32); } void If_CluHashTableCheck( If_Man_t * p ) { int t = 1; If_Hte_t * pEntry; int i, RetValue, Status; for ( i = 0; i < p->nTableSize[t]; i++ ) { for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext ) { Status = ((pEntry->Group & 15) > 0); RetValue = If_CutPerformCheck16( NULL, (unsigned *)pEntry->pTruth, 13, If_CluSupportSize(pEntry->pTruth, 13), "555" ); if ( RetValue != Status ) { Kit_DsdPrintFromTruth( (unsigned*)pEntry->pTruth, 13 ); printf( "\n" ); RetValue = If_CutPerformCheck16( NULL, (unsigned *)pEntry->pTruth, 13, If_CluSupportSize(pEntry->pTruth, 13), "555" ); printf( "Hash table problem!!!\n" ); } } } } void If_CluHashPrintStats( If_Man_t * p, int t ) { If_Hte_t * pEntry; int i, Counter; for ( i = 0; i < p->nTableSize[t]; i++ ) { Counter = 0; for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext ) Counter++; if ( Counter == 0 ) continue; if ( Counter < 10 ) continue; printf( "%d=%d ", i, Counter ); } } int If_CluHashFindMedian( If_Man_t * p, int t ) { If_Hte_t * pEntry; Vec_Int_t * vCounters; int i, Max = 0, Total = 0, Half = 0; vCounters = Vec_IntStart( 1000 ); for ( i = 0; i < p->nTableSize[t]; i++ ) { for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext ) { if ( Max < (int)pEntry->Counter ) { Max = pEntry->Counter; Vec_IntSetEntry( vCounters, pEntry->Counter, 0 ); } Vec_IntAddToEntry( vCounters, pEntry->Counter, 1 ); Total++; } } for ( i = Max; i > 0; i-- ) { Half += Vec_IntEntry( vCounters, i ); if ( Half > Total/2 ) break; } /* printf( "total = %d ", Total ); printf( "half = %d ", Half ); printf( "i = %d ", i ); printf( "Max = %d.\n", Max ); */ Vec_IntFree( vCounters ); return Abc_MaxInt( i, 1 ); } int If_CluHashKey( word * pTruth, int nWords, int Size ) { static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; unsigned Value = 0; int i; if ( nWords < 4 ) { unsigned char * s = (unsigned char *)pTruth; for ( i = 0; i < 8 * nWords; i++ ) Value ^= BigPrimes[i % 7] * s[i]; } else { unsigned * s = (unsigned *)pTruth; for ( i = 0; i < 2 * nWords; i++ ) Value ^= BigPrimes[i % 7] * s[i]; } return Value % Size; } unsigned * If_CluHashLookup( If_Man_t * p, word * pTruth, int t ) { If_Hte_t * pEntry, * pPrev; int nWords, HashKey; if ( p == NULL ) return NULL; nWords = If_CluWordNum(p->pPars->nLutSize); if ( p->pMemEntries == NULL ) p->pMemEntries = Mem_FixedStart( sizeof(If_Hte_t) + sizeof(word) * (If_CluWordNum(p->pPars->nLutSize) - 1) ); if ( p->pHashTable[t] == NULL ) { // decide how large should be the table int nEntriesMax1 = 4 * If_CluPrimeCudd( Vec_PtrSize(p->vObjs) * p->pPars->nCutsMax ); int nEntriesMax2 = (int)(((double)CLU_MEM_MAX * (1 << 20)) / If_CluWordNum(p->pPars->nLutSize) / 8); // int nEntriesMax2 = 10000; // create table p->nTableSize[t] = If_CluPrimeCudd( Abc_MinInt(nEntriesMax1, nEntriesMax2)/2 ); p->pHashTable[t] = ABC_CALLOC( void *, p->nTableSize[t] ); } // check if this entry exists HashKey = If_CluHashKey( pTruth, nWords, p->nTableSize[t] ); for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pEntry; pEntry = pEntry->pNext ) if ( memcmp(pEntry->pTruth, pTruth, sizeof(word) * nWords) == 0 ) { pEntry->Counter++; return &pEntry->Group; } // resize the hash table if ( p->nTableEntries[t] >= 2 * p->nTableSize[t] ) { // collect useful entries If_Hte_t * pPrev; Vec_Ptr_t * vUseful = Vec_PtrAlloc( p->nTableEntries[t] ); int i, Median = If_CluHashFindMedian( p, t ); for ( i = 0; i < p->nTableSize[t]; i++ ) { for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; ) { if ( (int)pEntry->Counter > Median ) { Vec_PtrPush( vUseful, pEntry ); pEntry = pEntry->pNext; } else { pPrev = pEntry->pNext; Mem_FixedEntryRecycle( p->pMemEntries, (char *)pEntry ); pEntry = pPrev; } } } // add useful entries memset( p->pHashTable[t], 0, sizeof(void *) * p->nTableSize[t] ); Vec_PtrForEachEntry( If_Hte_t *, vUseful, pEntry, i ) { HashKey = If_CluHashKey( pEntry->pTruth, nWords, p->nTableSize[t] ); pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey]; if ( pPrev == NULL || pEntry->Counter >= pPrev->Counter ) { pEntry->pNext = pPrev; ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; } else { while ( pPrev->pNext && pEntry->Counter < pPrev->pNext->Counter ) pPrev = pPrev->pNext; pEntry->pNext = pPrev->pNext; pPrev->pNext = pEntry; } } p->nTableEntries[t] = Vec_PtrSize( vUseful ); Vec_PtrFree( vUseful ); } // create entry p->nTableEntries[t]++; pEntry = (If_Hte_t *)Mem_FixedEntryFetch( p->pMemEntries ); memcpy( pEntry->pTruth, pTruth, sizeof(word) * nWords ); pEntry->Group = CLU_UNUSED; pEntry->Counter = 1; // insert at the beginning // pEntry->pNext = ((If_Hte_t **)p->pHashTable[t])[HashKey]; // ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; // insert at the end pEntry->pNext = NULL; for ( pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pPrev && pPrev->pNext; pPrev = pPrev->pNext ); if ( pPrev == NULL ) ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry; else pPrev->pNext = pEntry; return &pEntry->Group; } // variable permutation for large functions static inline void If_CluClear( word * pIn, int nVars ) { int w, nWords = If_CluWordNum( nVars ); for ( w = 0; w < nWords; w++ ) pIn[w] = 0; } static inline void If_CluFill( word * pIn, int nVars ) { int w, nWords = If_CluWordNum( nVars ); for ( w = 0; w < nWords; w++ ) pIn[w] = ~(word)0; } static inline void If_CluCopy( word * pOut, word * pIn, int nVars ) { int w, nWords = If_CluWordNum( nVars ); for ( w = 0; w < nWords; w++ ) pOut[w] = pIn[w]; } static inline int If_CluEqual( word * pOut, word * pIn, int nVars ) { int w, nWords = If_CluWordNum( nVars ); for ( w = 0; w < nWords; w++ ) if ( pOut[w] != pIn[w] ) return 0; return 1; } static inline void If_CluAnd( word * pRes, word * pIn1, word * pIn2, int nVars ) { int w, nWords = If_CluWordNum( nVars ); for ( w = 0; w < nWords; w++ ) pRes[w] = pIn1[w] & pIn2[w]; } static inline void If_CluSharp( word * pRes, word * pIn1, word * pIn2, int nVars ) { int w, nWords = If_CluWordNum( nVars ); for ( w = 0; w < nWords; w++ ) pRes[w] = pIn1[w] & ~pIn2[w]; } static inline void If_CluOr( word * pRes, word * pIn1, word * pIn2, int nVars ) { int w, nWords = If_CluWordNum( nVars ); for ( w = 0; w < nWords; w++ ) pRes[w] = pIn1[w] | pIn2[w]; } static inline word If_CluAdjust( word t, int nVars ) { assert( nVars >= 0 && nVars <= 6 ); if ( nVars == 6 ) return t; t &= (((word)1) << (1 << nVars)) - 1; if ( nVars == 0 ) t |= t << (1<> Shift); } else if ( iVar > 5 ) { int Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 4*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pIn[i]; for ( i = 0; i < Step; i++ ) pOut[Step+i] = pIn[2*Step+i]; for ( i = 0; i < Step; i++ ) pOut[2*Step+i] = pIn[Step+i]; for ( i = 0; i < Step; i++ ) pOut[3*Step+i] = pIn[3*Step+i]; pIn += 4*Step; pOut += 4*Step; } } else // if ( iVar == 5 ) { for ( i = 0; i < nWords; i += 2 ) { pOut[i] = (pIn[i] & ABC_CONST(0x00000000FFFFFFFF)) | ((pIn[i+1] & ABC_CONST(0x00000000FFFFFFFF)) << 32); pOut[i+1] = (pIn[i+1] & ABC_CONST(0xFFFFFFFF00000000)) | ((pIn[i] & ABC_CONST(0xFFFFFFFF00000000)) >> 32); } } } void If_CluChangePhase( word * pF, int nVars, int iVar ) { int nWords = If_CluWordNum( nVars ); assert( iVar < nVars ); if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) pF[i] = ((pF[i] & ~Truth6[iVar]) << Shift) | ((pF[i] & Truth6[iVar]) >> Shift); } else { word Temp; int i, k, Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { Temp = pF[i]; pF[i] = pF[Step+i]; pF[Step+i] = Temp; } pF += 2*Step; } } } void If_CluCountOnesInCofs( word * pTruth, int nVars, int * pStore ) { int nWords = If_CluWordNum( nVars ); int i, k, nOnes = 0, Limit = Abc_MinInt( nVars, 6 ); memset( pStore, 0, sizeof(int) * 2 * nVars ); // compute positive cofactors for ( k = 0; k < nWords; k++ ) for ( i = 0; i < Limit; i++ ) pStore[2*i+1] += If_CluCountOnes( pTruth[k] & Truth6[i] ); if ( nVars > 6 ) for ( k = 0; k < nWords; k++ ) for ( i = 6; i < nVars; i++ ) if ( k & (1 << (i-6)) ) pStore[2*i+1] += If_CluCountOnes( pTruth[k] ); // compute negative cofactors for ( k = 0; k < nWords; k++ ) nOnes += If_CluCountOnes( pTruth[k] ); for ( i = 0; i < nVars; i++ ) pStore[2*i] = nOnes - pStore[2*i+1]; } unsigned If_CluSemiCanonicize( word * pTruth, int nVars, int * pCanonPerm ) { word pFunc[CLU_WRD_MAX], * pIn = pTruth, * pOut = pFunc, * pTemp; int pStore[CLU_VAR_MAX*2]; unsigned uCanonPhase = 0; int i, Temp, fChange, Counter = 0; //Kit_DsdPrintFromTruth( (unsigned*)pTruth, nVars ); printf( "\n" ); // collect signatures If_CluCountOnesInCofs( pTruth, nVars, pStore ); // canonicize phase for ( i = 0; i < nVars; i++ ) { if ( pStore[2*i+0] <= pStore[2*i+1] ) continue; uCanonPhase |= (1 << i); Temp = pStore[2*i+0]; pStore[2*i+0] = pStore[2*i+1]; pStore[2*i+1] = Temp; If_CluChangePhase( pIn, nVars, i ); } // compute permutation for ( i = 0; i < nVars; i++ ) pCanonPerm[i] = i; do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[2*i] <= pStore[2*(i+1)] ) continue; Counter++; fChange = 1; Temp = pCanonPerm[i]; pCanonPerm[i] = pCanonPerm[i+1]; pCanonPerm[i+1] = Temp; Temp = pStore[2*i]; pStore[2*i] = pStore[2*(i+1)]; pStore[2*(i+1)] = Temp; Temp = pStore[2*i+1]; pStore[2*i+1] = pStore[2*(i+1)+1]; pStore[2*(i+1)+1] = Temp; If_CluSwapAdjacent( pOut, pIn, i, nVars ); pTemp = pIn; pIn = pOut; pOut = pTemp; } } while ( fChange ); // swap if it was moved an odd number of times if ( Counter & 1 ) If_CluCopy( pOut, pIn, nVars ); return uCanonPhase; } void If_CluSemiCanonicizeVerify( word * pTruth, word * pTruth0, int nVars, int * pCanonPerm, unsigned uCanonPhase ) { word pFunc[CLU_WRD_MAX], pGunc[CLU_WRD_MAX], * pIn = pTruth, * pOut = pFunc, * pTemp; int i, Temp, fChange, Counter = 0; If_CluCopy( pGunc, pTruth, nVars ); // undo permutation do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pCanonPerm[i] < pCanonPerm[i+1] ) continue; Counter++; fChange = 1; Temp = pCanonPerm[i]; pCanonPerm[i] = pCanonPerm[i+1]; pCanonPerm[i+1] = Temp; If_CluSwapAdjacent( pOut, pIn, i, nVars ); pTemp = pIn; pIn = pOut; pOut = pTemp; } } while ( fChange ); if ( Counter & 1 ) If_CluCopy( pOut, pIn, nVars ); // undo phase for ( i = 0; i < nVars; i++ ) if ( (uCanonPhase >> i) & 1 ) If_CluChangePhase( pTruth, nVars, i ); // compare if ( !If_CluEqual(pTruth0, pTruth, nVars) ) { Kit_DsdPrintFromTruth( (unsigned*)pTruth0, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pGunc, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pTruth, nVars ); printf( "\n" ); printf( "SemiCanonical verification FAILED!\n" ); } } void If_CluPrintGroup( If_Grp_t * g ) { int i; printf( "Vars = %d ", g->nVars ); printf( "Myu = %d {", g->nMyu ); for ( i = 0; i < g->nVars; i++ ) printf( " %c", 'a' + g->pVars[i] ); printf( " }\n" ); } void If_CluPrintConfig( int nVars, If_Grp_t * g, If_Grp_t * r, word BStruth, word * pFStruth ) { assert( r->nVars == nVars - g->nVars + 1 + (g->nMyu > 2) ); If_CluPrintGroup( g ); if ( g->nVars < 6 ) BStruth = If_CluAdjust( BStruth, g->nVars ); Kit_DsdPrintFromTruth( (unsigned *)&BStruth, g->nVars ); printf( "\n" ); If_CluPrintGroup( r ); if ( r->nVars < 6 ) pFStruth[0] = If_CluAdjust( pFStruth[0], r->nVars ); Kit_DsdPrintFromTruth( (unsigned *)pFStruth, r->nVars ); printf( "\n" ); } void If_CluInitTruthTables() { int i, k; assert( CLU_VAR_MAX <= 16 ); for ( i = 0; i < 6; i++ ) for ( k = 0; k < CLU_WRD_MAX; k++ ) TruthAll[i][k] = Truth6[i]; for ( i = 6; i < CLU_VAR_MAX; i++ ) for ( k = 0; k < CLU_WRD_MAX; k++ ) TruthAll[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0; // Extra_PrintHex( stdout, TruthAll[6], 8 ); printf( "\n" ); // Extra_PrintHex( stdout, TruthAll[7], 8 ); printf( "\n" ); } // verification static void If_CluComposeLut( int nVars, If_Grp_t * g, word * t, word f[6][CLU_WRD_MAX], word * r ) { word c[CLU_WRD_MAX]; int m, v; If_CluClear( r, nVars ); for ( m = 0; m < (1<nVars); m++ ) { if ( !((t[m >> 6] >> (m & 63)) & 1) ) continue; If_CluFill( c, nVars ); for ( v = 0; v < g->nVars; v++ ) if ( (m >> v) & 1 ) If_CluAnd( c, c, f[v], nVars ); else If_CluSharp( c, c, f[v], nVars ); If_CluOr( r, r, c, nVars ); } } void If_CluVerify( word * pF, int nVars, If_Grp_t * g, If_Grp_t * r, word BStruth, word * pFStruth ) { word pTTFans[6][CLU_WRD_MAX], pTTWire[CLU_WRD_MAX], pTTRes[CLU_WRD_MAX]; int i; assert( g->nVars <= 6 && r->nVars <= 6 ); if ( TruthAll[0][0] == 0 ) If_CluInitTruthTables(); for ( i = 0; i < g->nVars; i++ ) If_CluCopy( pTTFans[i], TruthAll[(int)g->pVars[i]], nVars ); If_CluComposeLut( nVars, g, &BStruth, pTTFans, pTTWire ); for ( i = 0; i < r->nVars; i++ ) if ( r->pVars[i] == nVars ) If_CluCopy( pTTFans[i], pTTWire, nVars ); else If_CluCopy( pTTFans[i], TruthAll[(int)r->pVars[i]], nVars ); If_CluComposeLut( nVars, r, pFStruth, pTTFans, pTTRes ); if ( !If_CluEqual(pTTRes, pF, nVars) ) { printf( "\n" ); If_CluPrintConfig( nVars, g, r, BStruth, pFStruth ); Kit_DsdPrintFromTruth( (unsigned*)pTTRes, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" ); // Extra_PrintHex( stdout, (unsigned *)pF, nVars ); printf( "\n" ); printf( "Verification FAILED!\n" ); } // else // printf( "Verification succeed!\n" ); } void If_CluVerify3( word * pF, int nVars, If_Grp_t * g, If_Grp_t * g2, If_Grp_t * r, word BStruth, word BStruth2, word FStruth ) { word pTTFans[6][CLU_WRD_MAX], pTTWire[CLU_WRD_MAX], pTTWire2[CLU_WRD_MAX], pTTRes[CLU_WRD_MAX]; int i; assert( g->nVars >= 2 && g2->nVars >= 2 && r->nVars >= 2 ); assert( g->nVars <= 6 && g2->nVars <= 6 && r->nVars <= 6 ); if ( TruthAll[0][0] == 0 ) If_CluInitTruthTables(); for ( i = 0; i < g->nVars; i++ ) If_CluCopy( pTTFans[i], TruthAll[(int)g->pVars[i]], nVars ); If_CluComposeLut( nVars, g, &BStruth, pTTFans, pTTWire ); for ( i = 0; i < g2->nVars; i++ ) If_CluCopy( pTTFans[i], TruthAll[(int)g2->pVars[i]], nVars ); If_CluComposeLut( nVars, g2, &BStruth2, pTTFans, pTTWire2 ); for ( i = 0; i < r->nVars; i++ ) if ( r->pVars[i] == nVars ) If_CluCopy( pTTFans[i], pTTWire, nVars ); else if ( r->pVars[i] == nVars + 1 ) If_CluCopy( pTTFans[i], pTTWire2, nVars ); else If_CluCopy( pTTFans[i], TruthAll[(int)r->pVars[i]], nVars ); If_CluComposeLut( nVars, r, &FStruth, pTTFans, pTTRes ); if ( !If_CluEqual(pTTRes, pF, nVars) ) { printf( "%d\n", nVars ); // If_CluPrintConfig( nVars, g, r, BStruth, pFStruth ); // Extra_PrintHex( stdout, (unsigned *)pF, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)&BStruth, g->nVars ); printf( " " ); If_CluPrintGroup(g); // printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)&BStruth2, g2->nVars ); printf( " " ); If_CluPrintGroup(g2); // printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)&FStruth, r->nVars ); printf( " " ); If_CluPrintGroup(r); // printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pTTWire, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pTTWire2, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pTTRes, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" ); // Extra_PrintHex( stdout, (unsigned *)pF, nVars ); printf( "\n" ); printf( "Verification FAILED!\n" ); } // else // printf( "Verification succeed!\n" ); } void If_CluSwapVars( word * pTruth, int nVars, int * V2P, int * P2V, int iVar, int jVar ) { word low2High, high2Low, temp; int nWords = If_CluWordNum(nVars); int shift, step, iStep, jStep; int w = 0, i = 0, j = 0; static word PPMasks[6][6] = { { ABC_CONST(0x2222222222222222), ABC_CONST(0x0A0A0A0A0A0A0A0A), ABC_CONST(0x00AA00AA00AA00AA), ABC_CONST(0x0000AAAA0000AAAA), ABC_CONST(0x00000000AAAAAAAA), ABC_CONST(0xAAAAAAAAAAAAAAAA) }, { ABC_CONST(0x0000000000000000), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x00CC00CC00CC00CC), ABC_CONST(0x0000CCCC0000CCCC), ABC_CONST(0x00000000CCCCCCCC), ABC_CONST(0xCCCCCCCCCCCCCCCC) }, { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0000F0F00000F0F0), ABC_CONST(0x00000000F0F0F0F0), ABC_CONST(0xF0F0F0F0F0F0F0F0) }, { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00000000FF00FF00), ABC_CONST(0xFF00FF00FF00FF00) }, { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0xFFFF0000FFFF0000) }, { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFF00000000) } }; if( iVar == jVar ) return; if( jVar < iVar ) { int varTemp = jVar; jVar = iVar; iVar = varTemp; } if ( iVar <= 5 && jVar <= 5 ) { shift = (1 << jVar) - (1 << iVar); for ( w = 0; w < nWords; w++ ) { low2High = (pTruth[w] & PPMasks[iVar][jVar - 1] ) << shift; pTruth[w] &= ~PPMasks[iVar][jVar - 1]; high2Low = (pTruth[w] & (PPMasks[iVar][jVar - 1] << shift )) >> shift; pTruth[w] &= ~ (PPMasks[iVar][jVar - 1] << shift); pTruth[w] = pTruth[w] | low2High | high2Low; } } else if( iVar <= 5 && jVar > 5 ) { step = If_CluWordNum(jVar + 1)/2; shift = 1 << iVar; for ( w = 0; w < nWords; w += 2*step ) { for (j = 0; j < step; j++) { low2High = (pTruth[w + j] & PPMasks[iVar][5]) >> shift; pTruth[w + j] &= ~PPMasks[iVar][5]; high2Low = (pTruth[w + step + j] & (PPMasks[iVar][5] >> shift)) << shift; pTruth[w + step + j] &= ~(PPMasks[iVar][5] >> shift); pTruth[w + j] |= high2Low; pTruth[w + step + j] |= low2High; } } } else { iStep = If_CluWordNum(iVar + 1)/2; jStep = If_CluWordNum(jVar + 1)/2; for (w = 0; w < nWords; w += 2*jStep) { for (i = 0; i < jStep; i += 2*iStep) { for (j = 0; j < iStep; j++) { temp = pTruth[w + iStep + i + j]; pTruth[w + iStep + i + j] = pTruth[w + jStep + i + j]; pTruth[w + jStep + i + j] = temp; } } } } if ( V2P && P2V ) { V2P[P2V[iVar]] = jVar; V2P[P2V[jVar]] = iVar; P2V[iVar] ^= P2V[jVar]; P2V[jVar] ^= P2V[iVar]; P2V[iVar] ^= P2V[jVar]; } } void If_CluReverseOrder( word * pTruth, int nVars, int * V2P, int * P2V, int iVarStart ) { int i, j, k; for ( k = 0; k < (nVars-iVarStart)/2 ; k++ ) { i = iVarStart + k; j = nVars - 1 - k; If_CluSwapVars( pTruth, nVars, V2P, P2V, i, j ); } } // moves one var (v) to the given position (p) void If_CluMoveVar2( word * pF, int nVars, int * Var2Pla, int * Pla2Var, int v, int p ) { If_CluSwapVars( pF, nVars, Var2Pla, Pla2Var, Var2Pla[v], p ); } // moves one var (v) to the given position (p) void If_CluMoveVar( word * pF, int nVars, int * Var2Pla, int * Pla2Var, int v, int p ) { word pG[CLU_WRD_MAX], * pIn = pF, * pOut = pG, * pTemp; int iPlace0, iPlace1, Count = 0; assert( v >= 0 && v < nVars ); while ( Var2Pla[v] < p ) { iPlace0 = Var2Pla[v]; iPlace1 = Var2Pla[v]+1; If_CluSwapAdjacent( pOut, pIn, iPlace0, nVars ); pTemp = pIn; pIn = pOut, pOut = pTemp; Var2Pla[Pla2Var[iPlace0]]++; Var2Pla[Pla2Var[iPlace1]]--; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Count++; } while ( Var2Pla[v] > p ) { iPlace0 = Var2Pla[v]-1; iPlace1 = Var2Pla[v]; If_CluSwapAdjacent( pOut, pIn, iPlace0, nVars ); pTemp = pIn; pIn = pOut, pOut = pTemp; Var2Pla[Pla2Var[iPlace0]]++; Var2Pla[Pla2Var[iPlace1]]--; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Count++; } if ( Count & 1 ) If_CluCopy( pF, pIn, nVars ); assert( Pla2Var[p] == v ); } // moves vars to be the most signiticant ones (Group[0] is MSB) void If_CluMoveGroupToMsb( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g ) { int v; for ( v = 0; v < g->nVars; v++ ) If_CluMoveVar( pF, nVars, V2P, P2V, g->pVars[g->nVars - 1 - v], nVars - 1 - v ); } // reverses the variable order void If_CluReverseOrder_old( word * pF, int nVars, int * V2P, int * P2V, int iVarStart ) { word pG[CLU_WRD_MAX]; int v; If_CluCopy( pG, pF, nVars ); // for ( v = 0; v < nVars; v++ ) // printf( "%c ", 'a' + P2V[v] ); // printf( " --- " ); for ( v = iVarStart; v < nVars; v++ ) If_CluMoveVar( pF, nVars, V2P, P2V, P2V[iVarStart], nVars - 1 - (v - iVarStart) ); // for ( v = 0; v < nVars; v++ ) // printf( "%c ", 'a' + P2V[v] ); // printf( "\n" ); // if ( iVarStart > 0 ) // return; If_CluReverseOrder( pG, nVars, NULL, NULL, iVarStart ); if ( If_CluEqual( pG, pF, nVars ) ) { // printf( "+" ); } else { /* printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)pG, nVars ); printf( "\n" ); */ printf( "%d ", nVars ); } } // return the number of cofactors w.r.t. the topmost vars (nBSsize) int If_CluCountCofs( word * pF, int nVars, int nBSsize, int iShift, word pCofs[3][CLU_WRD_MAX/4] ) { word iCofs[128], iCof, Result = 0; word * pCofA, * pCofB; int nMints = (1 << nBSsize); int i, c, w, nCofs; assert( nBSsize >= 2 && nBSsize <= 7 && nBSsize < nVars ); if ( nVars - nBSsize < 6 ) { int nShift = (1 << (nVars - nBSsize)); word Mask = ((((word)1) << nShift) - 1); for ( nCofs = i = 0; i < nMints; i++ ) { iCof = (pF[(iShift + i * nShift) / 64] >> ((iShift + i * nShift) & 63)) & Mask; for ( c = 0; c < nCofs; c++ ) if ( iCof == iCofs[c] ) break; if ( c == nCofs ) iCofs[nCofs++] = iCof; if ( pCofs && iCof != iCofs[0] ) Result |= (((word)1) << i); if ( nCofs == 5 ) break; } if ( nCofs <= 2 && pCofs ) { assert( nBSsize <= 6 ); pCofs[0][0] = iCofs[0]; pCofs[1][0] = (nCofs == 2) ? iCofs[1] : iCofs[0]; pCofs[2][0] = Result; } } else { int nWords = If_CluWordNum( nVars - nBSsize ); assert( nWords * nMints == If_CluWordNum(nVars) ); for ( nCofs = i = 0; i < nMints; i++ ) { pCofA = pF + i * nWords; for ( c = 0; c < nCofs; c++ ) { pCofB = pF + iCofs[c] * nWords; for ( w = 0; w < nWords; w++ ) if ( pCofA[w] != pCofB[w] ) break; if ( w == nWords ) break; } if ( c == nCofs ) iCofs[nCofs++] = i; if ( pCofs ) { assert( nBSsize <= 6 ); pCofB = pF + iCofs[0] * nWords; for ( w = 0; w < nWords; w++ ) if ( pCofA[w] != pCofB[w] ) break; if ( w != nWords ) Result |= (((word)1) << i); } if ( nCofs == 5 ) break; } if ( nCofs <= 2 && pCofs ) { If_CluCopy( pCofs[0], pF + iCofs[0] * nWords, nVars - nBSsize ); If_CluCopy( pCofs[1], pF + ((nCofs == 2) ? iCofs[1] : iCofs[0]) * nWords, nVars - nBSsize ); pCofs[2][0] = Result; } } assert( nCofs >= 1 && nCofs <= 5 ); return nCofs; } // return the number of cofactors w.r.t. the topmost vars (nBSsize) int If_CluCountCofs4( word * pF, int nVars, int nBSsize, word pCofs[6][CLU_WRD_MAX/4] ) { word iCofs[128], iCof, Result0 = 0, Result1 = 0; int nMints = (1 << nBSsize); int i, c, nCofs; assert( pCofs ); assert( nBSsize >= 2 && nBSsize <= 6 && nBSsize < nVars ); if ( nVars - nBSsize < 6 ) { int nShift = (1 << (nVars - nBSsize)); word Mask = ((((word)1) << nShift) - 1); for ( nCofs = i = 0; i < nMints; i++ ) { iCof = (pF[(i * nShift) / 64] >> ((i * nShift) & 63)) & Mask; for ( c = 0; c < nCofs; c++ ) if ( iCof == iCofs[c] ) break; if ( c == nCofs ) iCofs[nCofs++] = iCof; if ( c == 1 || c == 3 ) Result0 |= (((word)1) << i); if ( c == 2 || c == 3 ) Result1 |= (((word)1) << i); } assert( nCofs >= 3 && nCofs <= 4 ); pCofs[0][0] = iCofs[0]; pCofs[1][0] = iCofs[1]; pCofs[2][0] = iCofs[2]; pCofs[3][0] = (nCofs == 4) ? iCofs[3] : iCofs[2]; pCofs[4][0] = Result0; pCofs[5][0] = Result1; } else assert( 0 ); return nCofs; } void If_CluCofactors( word * pF, int nVars, int iVar, word * pCof0, word * pCof1 ) { int nWords = If_CluWordNum( nVars ); assert( iVar < nVars ); if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) { pCof0[i] = (pF[i] & ~Truth6[iVar]) | ((pF[i] & ~Truth6[iVar]) << Shift); pCof1[i] = (pF[i] & Truth6[iVar]) | ((pF[i] & Truth6[iVar]) >> Shift); } } else { int i, k, Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pCof0[i] = pCof0[Step+i] = pF[i]; pCof1[i] = pCof1[Step+i] = pF[Step+i]; } pF += 2*Step; pCof0 += 2*Step; pCof1 += 2*Step; } } } // returns 1 if we have special case of cofactors; otherwise, returns 0 int If_CluDetectSpecialCaseCofs( word * pF, int nVars, int iVar ) { word Cof0, Cof1; int State[6] = {0}; int i, nWords = If_CluWordNum( nVars ); assert( iVar < nVars ); if ( iVar < 6 ) { int Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) { Cof0 = (pF[i] & ~Truth6[iVar]); Cof1 = ((pF[i] & Truth6[iVar]) >> Shift); if ( Cof0 == 0 ) State[0]++; else if ( Cof0 == ~Truth6[iVar] ) State[1]++; else if ( Cof1 == 0 ) State[2]++; else if ( Cof1 == ~Truth6[iVar] ) State[3]++; else if ( Cof0 == ~Cof1 ) State[4]++; else if ( Cof0 == Cof1 ) State[5]++; } } else { int k, Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { Cof0 = pF[i]; Cof1 = pF[Step+i]; if ( Cof0 == 0 ) State[0]++; else if ( Cof0 == ~(word)0 ) State[1]++; else if ( Cof1 == 0 ) State[2]++; else if ( Cof1 == ~(word)0 ) State[3]++; else if ( Cof0 == ~Cof1 ) State[4]++; else if ( Cof0 == Cof1 ) State[5]++; } pF += 2*Step; } nWords /= 2; } assert( State[5] != nWords ); for ( i = 0; i < 5; i++ ) { assert( State[i] <= nWords ); if ( State[i] == nWords ) return i; } return -1; } // returns 1 if we have special case of cofactors; otherwise, returns 0 If_Grp_t If_CluDecUsingCofs( word * pTruth, int nVars, int nLutLeaf ) { If_Grp_t G = {0}; word pF2[CLU_WRD_MAX], * pF = pF2; int Var2Pla[CLU_VAR_MAX+2], Pla2Var[CLU_VAR_MAX+2]; int V2P[CLU_VAR_MAX+2], P2V[CLU_VAR_MAX+2]; int nVarsNeeded = nVars - nLutLeaf; int v, i, k, iVar, State; //Kit_DsdPrintFromTruth( (unsigned*)pTruth, nVars ); printf( "\n" ); // create local copy If_CluCopy( pF, pTruth, nVars ); for ( k = 0; k < nVars; k++ ) Var2Pla[k] = Pla2Var[k] = k; // find decomposable vars for ( i = 0; i < nVarsNeeded; i++ ) { for ( v = nVars - 1; v >= 0; v-- ) { State = If_CluDetectSpecialCaseCofs( pF, nVars, v ); if ( State == -1 ) continue; // update the variable place iVar = Pla2Var[v]; while ( Var2Pla[iVar] < nVars - 1 ) { int iPlace0 = Var2Pla[iVar]; int iPlace1 = Var2Pla[iVar]+1; Var2Pla[Pla2Var[iPlace0]]++; Var2Pla[Pla2Var[iPlace1]]--; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; } // move this variable to the top for ( k = 0; k < nVars; k++ ) V2P[k] = P2V[k] = k; //Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" ); If_CluMoveVar( pF, nVars, V2P, P2V, v, nVars - 1 ); //Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" ); // choose cofactor to follow iVar = nVars - 1; if ( State == 0 || State == 1 ) // need cof1 { if ( iVar < 6 ) pF[0] = (pF[0] & Truth6[iVar]) | ((pF[0] & Truth6[iVar]) >> (1 << iVar)); else pF += If_CluWordNum( nVars ) / 2; } else // need cof0 { if ( iVar < 6 ) pF[0] = (pF[0] & ~Truth6[iVar]) | ((pF[0] & ~Truth6[iVar]) << (1 << iVar)); } // update the variable count nVars--; break; } if ( v == -1 ) return G; } // create the resulting group G.nVars = nLutLeaf; G.nMyu = 2; for ( v = 0; v < G.nVars; v++ ) G.pVars[v] = Pla2Var[v]; return G; } // deriving decomposition word If_CluDeriveDisjoint( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g, If_Grp_t * r ) { word pCofs[3][CLU_WRD_MAX/4]; int i, RetValue, nFSset = nVars - g->nVars; RetValue = If_CluCountCofs( pF, nVars, g->nVars, 0, pCofs ); // assert( RetValue == 2 ); if ( nFSset < 6 ) pF[0] = (pCofs[1][0] << (1 << nFSset)) | pCofs[0][0]; else { If_CluCopy( pF, pCofs[0], nFSset ); If_CluCopy( pF + If_CluWordNum(nFSset), pCofs[1], nFSset ); } // create the resulting group if ( r ) { r->nVars = nFSset + 1; r->nMyu = 0; for ( i = 0; i < nFSset; i++ ) r->pVars[i] = P2V[i]; r->pVars[nFSset] = nVars; } return pCofs[2][0]; } void If_CluDeriveDisjoint4( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g, If_Grp_t * r, word * pTruth0, word * pTruth1 ) { word pCofs[6][CLU_WRD_MAX/4]; word Cof0, Cof1; int i, RetValue, nFSset = nVars - g->nVars; assert( g->nVars <= 6 && nFSset <= 4 ); RetValue = If_CluCountCofs4( pF, nVars, g->nVars, pCofs ); if ( RetValue != 3 && RetValue != 4 ) printf( "If_CluDeriveDisjoint4(): Error!!!\n" ); Cof0 = (pCofs[1][0] << (1 << nFSset)) | pCofs[0][0]; Cof1 = (pCofs[3][0] << (1 << nFSset)) | pCofs[2][0]; pF[0] = (Cof1 << (1 << (nFSset+1))) | Cof0; pF[0] = If_CluAdjust( pF[0], nFSset + 2 ); // create the resulting group r->nVars = nFSset + 2; r->nMyu = 0; for ( i = 0; i < nFSset; i++ ) r->pVars[i] = P2V[i]; r->pVars[nFSset] = nVars; r->pVars[nFSset+1] = nVars+1; *pTruth0 = If_CluAdjust( pCofs[4][0], g->nVars ); *pTruth1 = If_CluAdjust( pCofs[5][0], g->nVars ); } word If_CluDeriveNonDisjoint( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g, If_Grp_t * r ) { word pCofs[2][CLU_WRD_MAX]; word Truth0, Truth1, Truth; int i, nFSset = nVars - g->nVars, nFSset1 = nFSset + 1; If_CluCofactors( pF, nVars, nVars - 1, pCofs[0], pCofs[1] ); // Extra_PrintHex( stdout, (unsigned *)pCofs[0], nVars ); printf( "\n" ); // Extra_PrintHex( stdout, (unsigned *)pCofs[1], nVars ); printf( "\n" ); g->nVars--; Truth0 = If_CluDeriveDisjoint( pCofs[0], nVars - 1, V2P, P2V, g, NULL ); Truth1 = If_CluDeriveDisjoint( pCofs[1], nVars - 1, V2P, P2V, g, NULL ); Truth = (Truth1 << (1 << g->nVars)) | Truth0; g->nVars++; if ( nFSset1 < 6 ) pF[0] = (pCofs[1][0] << (1 << nFSset1)) | pCofs[0][0]; else { If_CluCopy( pF, pCofs[0], nFSset1 ); If_CluCopy( pF + If_CluWordNum(nFSset1), pCofs[1], nFSset1 ); } // Extra_PrintHex( stdout, (unsigned *)&Truth0, 6 ); printf( "\n" ); // Extra_PrintHex( stdout, (unsigned *)&Truth1, 6 ); printf( "\n" ); // Extra_PrintHex( stdout, (unsigned *)&pCofs[0][0], 6 ); printf( "\n" ); // Extra_PrintHex( stdout, (unsigned *)&pCofs[1][0], 6 ); printf( "\n" ); // Extra_PrintHex( stdout, (unsigned *)&Truth, 6 ); printf( "\n" ); // Extra_PrintHex( stdout, (unsigned *)&pF[0], 6 ); printf( "\n" ); // create the resulting group r->nVars = nFSset + 2; r->nMyu = 0; for ( i = 0; i < nFSset; i++ ) r->pVars[i] = P2V[i]; r->pVars[nFSset] = nVars; r->pVars[nFSset+1] = g->pVars[g->nVars - 1]; return Truth; } // check non-disjoint decomposition int If_CluCheckNonDisjointGroup( word * pF, int nVars, int * V2P, int * P2V, If_Grp_t * g ) { int v, i, nCofsBest2; if ( (g->nMyu == 3 || g->nMyu == 4) ) { word pCofs[2][CLU_WRD_MAX]; // try cofactoring w.r.t. each variable for ( v = 0; v < g->nVars; v++ ) { If_CluCofactors( pF, nVars, V2P[(int)g->pVars[v]], pCofs[0], pCofs[1] ); nCofsBest2 = If_CluCountCofs( pCofs[0], nVars, g->nVars, 0, NULL ); if ( nCofsBest2 > 2 ) continue; nCofsBest2 = If_CluCountCofs( pCofs[1], nVars, g->nVars, 0, NULL ); if ( nCofsBest2 > 2 ) continue; // found good shared variable - move to the end If_CluMoveVar( pF, nVars, V2P, P2V, g->pVars[v], nVars-1 ); for ( i = 0; i < g->nVars; i++ ) g->pVars[i] = P2V[nVars-g->nVars+i]; return 1; } } return 0; } // finds a good var group (cof count < 6; vars are MSBs) If_Grp_t If_CluFindGroup( word * pF, int nVars, int iVarStart, int iVarStop, int * V2P, int * P2V, int nBSsize, int fDisjoint ) { int fVerbose = 0; int nRounds = 2;//nBSsize; If_Grp_t G = {0}, * g = &G;//, BestG = {0}; int i, r, v, nCofs, VarBest, nCofsBest2; assert( nVars > nBSsize && nVars >= nBSsize + iVarStart && nVars <= CLU_VAR_MAX ); assert( nBSsize >= 2 && nBSsize <= 6 ); assert( !iVarStart || !iVarStop ); // start with the default group g->nVars = nBSsize; g->nMyu = If_CluCountCofs( pF, nVars, nBSsize, 0, NULL ); for ( i = 0; i < nBSsize; i++ ) g->pVars[i] = P2V[nVars-nBSsize+i]; // check if good enough if ( g->nMyu == 2 ) return G; if ( !fDisjoint && If_CluCheckNonDisjointGroup( pF, nVars, V2P, P2V, g ) ) { // BestG = G; return G; } if ( nVars == nBSsize + iVarStart ) { g->nVars = 0; return G; } if ( fVerbose ) { printf( "Iter %2d ", -1 ); If_CluPrintGroup( g ); } // try to find better group for ( r = 0; r < nRounds; r++ ) { if ( nBSsize < nVars-1 ) { // find the best var to add VarBest = P2V[nVars-1-nBSsize]; nCofsBest2 = If_CluCountCofs( pF, nVars, nBSsize+1, 0, NULL ); for ( v = nVars-2-nBSsize; v >= iVarStart; v-- ) { // If_CluMoveVar( pF, nVars, V2P, P2V, P2V[v], nVars-1-nBSsize ); If_CluMoveVar2( pF, nVars, V2P, P2V, P2V[v], nVars-1-nBSsize ); nCofs = If_CluCountCofs( pF, nVars, nBSsize+1, 0, NULL ); if ( nCofsBest2 >= nCofs ) { nCofsBest2 = nCofs; VarBest = P2V[nVars-1-nBSsize]; } } // go back // If_CluMoveVar( pF, nVars, V2P, P2V, VarBest, nVars-1-nBSsize ); If_CluMoveVar2( pF, nVars, V2P, P2V, VarBest, nVars-1-nBSsize ); // update best bound set nCofs = If_CluCountCofs( pF, nVars, nBSsize+1, 0, NULL ); assert( nCofs == nCofsBest2 ); } // find the best var to remove VarBest = P2V[nVars-1-nBSsize]; nCofsBest2 = If_CluCountCofs( pF, nVars, nBSsize, 0, NULL ); for ( v = nVars-nBSsize; v < nVars-iVarStop; v++ ) { // If_CluMoveVar( pF, nVars, V2P, P2V, P2V[v], nVars-1-nBSsize ); If_CluMoveVar2( pF, nVars, V2P, P2V, P2V[v], nVars-1-nBSsize ); nCofs = If_CluCountCofs( pF, nVars, nBSsize, 0, NULL ); if ( nCofsBest2 >= nCofs ) { nCofsBest2 = nCofs; VarBest = P2V[nVars-1-nBSsize]; } } // go back // If_CluMoveVar( pF, nVars, V2P, P2V, VarBest, nVars-1-nBSsize ); If_CluMoveVar2( pF, nVars, V2P, P2V, VarBest, nVars-1-nBSsize ); // update best bound set nCofs = If_CluCountCofs( pF, nVars, nBSsize, 0, NULL ); assert( nCofs == nCofsBest2 ); if ( g->nMyu >= nCofs ) { g->nVars = nBSsize; g->nMyu = nCofs; for ( i = 0; i < nBSsize; i++ ) g->pVars[i] = P2V[nVars-nBSsize+i]; } if ( fVerbose ) { printf( "Iter %2d ", r ); If_CluPrintGroup( g ); } // check if good enough if ( g->nMyu == 2 ) return G; if ( !fDisjoint && If_CluCheckNonDisjointGroup( pF, nVars, V2P, P2V, g ) ) { // BestG = G; return G; } } assert( r == nRounds ); g->nVars = 0; return G; // return BestG; } // double check that the given group has a decomposition void If_CluCheckGroup( word * pTruth, int nVars, If_Grp_t * g ) { word pF[CLU_WRD_MAX]; int v, nCofs, V2P[CLU_VAR_MAX], P2V[CLU_VAR_MAX]; assert( g->nVars >= 2 && g->nVars <= 6 ); // vars assert( g->nMyu >= 2 && g->nMyu <= 4 ); // cofs // create permutation for ( v = 0; v < nVars; v++ ) V2P[v] = P2V[v] = v; // create truth table If_CluCopy( pF, pTruth, nVars ); // move group up If_CluMoveGroupToMsb( pF, nVars, V2P, P2V, g ); // check the number of cofactors nCofs = If_CluCountCofs( pF, nVars, g->nVars, 0, NULL ); if ( nCofs != g->nMyu ) printf( "Group check 0 has failed.\n" ); // check compatible if ( nCofs > 2 ) { nCofs = If_CluCountCofs( pF, nVars-1, g->nVars-1, 0, NULL ); if ( nCofs > 2 ) printf( "Group check 1 has failed.\n" ); nCofs = If_CluCountCofs( pF, nVars-1, g->nVars-1, (1 << (nVars-1)), NULL ); if ( nCofs > 2 ) printf( "Group check 2 has failed.\n" ); } } // double check that the permutation derived is correct void If_CluCheckPerm( word * pTruth, word * pF, int nVars, int * V2P, int * P2V ) { int i; for ( i = 0; i < nVars; i++ ) If_CluMoveVar( pF, nVars, V2P, P2V, i, i ); if ( !If_CluEqual( pTruth, pF, nVars ) ) printf( "Permutation FAILED.\n" ); // else // printf( "Permutation successful\n" ); } static inline int If_CluSuppIsMinBase( int Supp ) { return (Supp & (Supp+1)) == 0; } static inline int If_CluHasVar( word * t, int nVars, int iVar ) { int nWords = If_CluWordNum( nVars ); assert( iVar < nVars ); if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) if ( (t[i] & ~Truth6[iVar]) != ((t[i] & Truth6[iVar]) >> Shift) ) return 1; return 0; } else { int i, k, Step = (1 << (iVar - 6)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) if ( t[i] != t[Step+i] ) return 1; t += 2*Step; } return 0; } } static inline int If_CluSupport( word * t, int nVars ) { int v, Supp = 0; for ( v = 0; v < nVars; v++ ) if ( If_CluHasVar( t, nVars, v ) ) Supp |= (1 << v); return Supp; } int If_CluSupportSize( word * t, int nVars ) { int v, SuppSize = 0; for ( v = 0; v < nVars; v++ ) if ( If_CluHasVar( t, nVars, v ) ) SuppSize++; return SuppSize; } static inline void If_CluTruthShrink( word * pF, int nVars, int nVarsAll, unsigned Phase ) { word pG[CLU_WRD_MAX], * pIn = pF, * pOut = pG, * pTemp; int i, k, Var = 0, Counter = 0; assert( nVarsAll <= 16 ); for ( i = 0; i < nVarsAll; i++ ) if ( Phase & (1 << i) ) { for ( k = i-1; k >= Var; k-- ) { If_CluSwapAdjacent( pOut, pIn, k, nVarsAll ); pTemp = pIn; pIn = pOut, pOut = pTemp; Counter++; } Var++; } assert( Var == nVars ); // swap if it was moved an odd number of times if ( Counter & 1 ) If_CluCopy( pOut, pIn, nVarsAll ); } int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ) { int v, iVar = 0, uSupp = 0; assert( nVarsAll <= 16 ); for ( v = 0; v < nVarsAll; v++ ) if ( If_CluHasVar( t, nVarsAll, v ) ) { uSupp |= (1 << v); if ( pSupp ) pSupp[iVar] = pSupp[v]; iVar++; } if ( pnVars ) *pnVars = iVar; if ( If_CluSuppIsMinBase( uSupp ) ) return 0; If_CluTruthShrink( t, iVar, nVarsAll, uSupp ); return 1; } // returns the best group found If_Grp_t If_CluCheck( If_Man_t * p, word * pTruth0, int nVars, int iVarStart, int iVarStop, int nLutLeaf, int nLutRoot, If_Grp_t * pR, word * pFunc0, word * pFunc1, word * pLeftOver, int fHashing ) { // int fEnableHashing = 0; If_Grp_t G1 = {0}, R = {0}; unsigned * pHashed = NULL; word Truth, pTruth[CLU_WRD_MAX], pF[CLU_WRD_MAX];//, pG[CLU_WRD_MAX]; int V2P[CLU_VAR_MAX+2], P2V[CLU_VAR_MAX+2], pCanonPerm[CLU_VAR_MAX]; int i, nSupp, uCanonPhase; int nLutSize = p ? p->pPars->nLutSize : nVars; assert( nVars <= CLU_VAR_MAX ); assert( nVars <= nLutLeaf + nLutRoot - 1 ); if ( pR ) { pR->nVars = 0; *pFunc0 = 0; *pFunc1 = 0; } // canonicize truth table If_CluCopy( pTruth, pTruth0, nLutSize ); if ( 0 ) { uCanonPhase = If_CluSemiCanonicize( pTruth, nVars, pCanonPerm ); If_CluAdjustBig( pTruth, nVars, nLutSize ); } // If_CluSemiCanonicizeVerify( pTruth, pTruth0, nVars, pCanonPerm, uCanonPhase ); // If_CluCopy( pTruth, pTruth0, nLutSize ); /* { int pCanonPerm[32]; short pStore[32]; unsigned uCanonPhase; If_CluCopy( pF, pTruth, nVars ); uCanonPhase = Kit_TruthSemiCanonicize( pF, pG, nVars, pCanonPerm ); G1.nVars = 1; return G1; } */ // check minnimum base If_CluCopy( pF, pTruth, nVars ); for ( i = 0; i < nVars; i++ ) V2P[i] = P2V[i] = i; // check support nSupp = If_CluSupport( pF, nVars ); //Extra_PrintBinary( stdout, &nSupp, 16 ); printf( "\n" ); if ( !nSupp || !If_CluSuppIsMinBase(nSupp) ) { // assert( 0 ); return G1; } // check hash table if ( p && fHashing ) { pHashed = If_CluHashLookup( p, pTruth, 0 ); if ( pHashed && *pHashed != CLU_UNUSED ) If_CluUns2Grp( *pHashed, &G1 ); } // update the variable order so that the first var was the last one if ( iVarStop ) If_CluMoveVar( pF, nVars, V2P, P2V, 0, nVars-1 ); if ( G1.nVars == 0 ) { s_Count2++; // detect easy cofs if ( iVarStart == 0 ) G1 = If_CluDecUsingCofs( pTruth, nVars, nLutLeaf ); if ( G1.nVars == 0 ) { // perform testing G1 = If_CluFindGroup( pF, nVars, iVarStart, iVarStop, V2P, P2V, nLutLeaf, nLutLeaf + nLutRoot == nVars + 1 ); // If_CluCheckPerm( pTruth, pF, nVars, V2P, P2V ); if ( G1.nVars == 0 ) { // perform testing with a smaller set if ( nVars < nLutLeaf + nLutRoot - 2 ) { nLutLeaf--; G1 = If_CluFindGroup( pF, nVars, iVarStart, iVarStop, V2P, P2V, nLutLeaf, nLutLeaf + nLutRoot == nVars + 1 ); nLutLeaf++; } // perform testing with a smaller set if ( nLutLeaf > 4 && nVars < nLutLeaf + nLutRoot - 3 ) { nLutLeaf--; nLutLeaf--; G1 = If_CluFindGroup( pF, nVars, iVarStart, iVarStop, V2P, P2V, nLutLeaf, nLutLeaf + nLutRoot == nVars + 1 ); nLutLeaf++; nLutLeaf++; } if ( G1.nVars == 0 ) { // perform testing with a different order If_CluReverseOrder( pF, nVars, V2P, P2V, iVarStart ); G1 = If_CluFindGroup( pF, nVars, iVarStart, iVarStop, V2P, P2V, nLutLeaf, nLutLeaf + nLutRoot == nVars + 1 ); // check permutation // If_CluCheckPerm( pTruth, pF, nVars, V2P, P2V ); if ( G1.nVars == 0 ) { // remember free set, just in case // for ( i = 0; i < nVars - nLutLeaf; i++ ) /// G1.pVars[nLutLeaf+i] = P2V[i]; // if , this will not be used // if , this will not be hashed /* if ( nVars == 6 ) { Extra_PrintHex( stdout, (unsigned *)pF, nVars ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned*)pF, nVars ); printf( "\n" ); if ( !If_CutPerformCheck07( (unsigned *)pF, 6, 6, NULL ) ) printf( "no\n" ); } */ if ( pHashed ) *pHashed = If_CluGrp2Uns( &G1 ); return G1; } } } } } // derive if ( pR ) { int iNewPos; If_CluMoveGroupToMsb( pF, nVars, V2P, P2V, &G1 ); if ( G1.nMyu == 2 ) { Truth = If_CluDeriveDisjoint( pF, nVars, V2P, P2V, &G1, &R ); iNewPos = R.nVars - 1; } else { Truth = If_CluDeriveNonDisjoint( pF, nVars, V2P, P2V, &G1, &R ); iNewPos = R.nVars - 2; } assert( R.pVars[iNewPos] == nVars ); // adjust the functions Truth = If_CluAdjust( Truth, G1.nVars ); if ( R.nVars < 6 ) pF[0] = If_CluAdjust( pF[0], R.nVars ); // Kit_DsdPrintFromTruth( (unsigned*)&Truth, G1.nVars ); printf( " ...1\n" ); // Kit_DsdPrintFromTruth( (unsigned*)pF, R.nVars ); printf( " ...1\n" ); // update the variable order of R so that the new var was the first one // if ( iVarStart == 0 ) { int k, V2P2[CLU_VAR_MAX+2], P2V2[CLU_VAR_MAX+2]; assert( iNewPos >= iVarStart ); for ( k = 0; k < R.nVars; k++ ) V2P2[k] = P2V2[k] = k; If_CluMoveVar( pF, R.nVars, V2P2, P2V2, iNewPos, iVarStart ); for ( k = iNewPos; k > iVarStart; k-- ) R.pVars[k] = R.pVars[k-1]; R.pVars[iVarStart] = nVars; } // Kit_DsdPrintFromTruth( (unsigned*)pF, R.nVars ); printf( " ...2\n" ); if ( pLeftOver ) { if ( R.nVars < 6 ) *pLeftOver = If_CluAdjust( pF[0], R.nVars ); else If_CluCopy( pLeftOver, pF, R.nVars ); If_CluAdjustBig( pLeftOver, R.nVars, nLutSize ); } // perform checking if ( 0 ) { If_CluCheckGroup( pTruth, nVars, &G1 ); If_CluVerify( pTruth, nVars, &G1, &R, Truth, pF ); } // save functions *pR = R; if ( pFunc0 ) *pFunc0 = pF[0]; if ( pFunc1 ) *pFunc1 = Truth; } if ( pHashed ) *pHashed = If_CluGrp2Uns( &G1 ); return G1; } /* static inline word Abc_Tt6Cofactor0( word t, int iVar ) { assert( iVar >= 0 && iVar < 6 ); return (t &~Truth6[iVar]) | ((t &~Truth6[iVar]) << (1<= 0 && iVar < 6 ); return (t & Truth6[iVar]) | ((t & Truth6[iVar]) >> (1< 4LUT If_Grp_t G, R; word Func0, Func1; G = If_CluCheck( p, (word *)pTruth, nLeaves, 0, 0, 5, 4, &R, &Func0, &Func1, NULL, 0 ); if ( G.nVars == 0 ) return 0; Func0 = If_CluAdjust( Func0, R.nVars ); Func1 = If_CluAdjust( Func1, G.nVars ); #if 0 Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)&Func0, R.nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)&Func1, G.nVars ); printf( "\n" ); If_CluPrintGroup( &R ); If_CluPrintGroup( &G ); #endif if ( G.nVars < 5 || (p->pPars->fEnableCheck75 && If_CluCheckDecOut(Func1, 5)) || (p->pPars->fEnableCheck75u && If_CluCheckDecOutU(Func1, 5)) ) return 1; return 0; } int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ) { // 4LUT -> 5LUT If_Grp_t G, R; word Func0, Func1; G = If_CluCheck( p, (word *)pTruth, nLeaves, 0, 0, 4, 5, &R, &Func0, &Func1, NULL, 0 ); if ( G.nVars == 0 ) return 0; Func0 = If_CluAdjust( Func0, R.nVars ); Func1 = If_CluAdjust( Func1, G.nVars ); #if 0 Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)&Func0, R.nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned*)&Func1, G.nVars ); printf( "\n" ); If_CluPrintGroup( &R ); If_CluPrintGroup( &G ); #endif if ( R.nVars < 5 || (p->pPars->fEnableCheck75 && If_CluCheckDecIn(Func0, 5)) || (p->pPars->fEnableCheck75u && If_CluCheckDecInU(Func0, 5)) ) return 1; return 0; } // returns the best group found If_Grp_t If_CluCheck3( If_Man_t * p, word * pTruth0, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, If_Grp_t * pR, If_Grp_t * pG2, word * pFunc0, word * pFunc1, word * pFunc2 ) { int fEnableHashing = 0; static int Counter = 0; unsigned * pHashed = NULL; word pLeftOver[CLU_WRD_MAX], Func0, Func1, Func2; If_Grp_t G1 = {0}, G2 = {0}, R = {0}, R2 = {0}; int i; Counter++; // if ( Counter == 37590 ) // { // int ns = 0; // } // check hash table if ( p && fEnableHashing ) { pHashed = If_CluHashLookup( p, pTruth0, 1 ); if ( pHashed && *pHashed != CLU_UNUSED ) { If_CluUns2Grp( *pHashed, &G1 ); return G1; } } s_Count3++; // check two-node decomposition G1 = If_CluCheck( p, pTruth0, nVars, 0, 0, nLutLeaf, nLutRoot + nLutLeaf2 - 1, &R2, &Func0, &Func1, pLeftOver, 0 ); // decomposition does not exist if ( G1.nVars == 0 ) { // check for decomposition with two outputs if ( (G1.nMyu == 3 || G1.nMyu == 4) && nLutLeaf == nLutLeaf2 && nVars - nLutLeaf + 2 <= nLutRoot ) { int V2P[CLU_VAR_MAX+2], P2V[CLU_VAR_MAX+2]; word Func0, Func1, Func2; int iVar0, iVar1; G1.nVars = nLutLeaf; If_CluCopy( pLeftOver, pTruth0, nVars ); for ( i = 0; i < nVars; i++ ) V2P[i] = P2V[i] = i; If_CluMoveGroupToMsb( pLeftOver, nVars, V2P, P2V, &G1 ); If_CluDeriveDisjoint4( pLeftOver, nVars, V2P, P2V, &G1, &R, &Func1, &Func2 ); // move the two vars to the front for ( i = 0; i < R.nVars; i++ ) V2P[i] = P2V[i] = i; If_CluMoveVar( pLeftOver, R.nVars, V2P, P2V, R.nVars-2, 0 ); If_CluMoveVar( pLeftOver, R.nVars, V2P, P2V, R.nVars-1, 1 ); iVar0 = R.pVars[R.nVars-2]; iVar1 = R.pVars[R.nVars-1]; for ( i = R.nVars-1; i > 1; i-- ) R.pVars[i] = R.pVars[i-2]; R.pVars[0] = iVar0; R.pVars[1] = iVar1; Func0 = pLeftOver[0]; If_CluVerify3( pTruth0, nVars, &G1, &G1, &R, Func1, Func2, Func0 ); if ( pFunc1 && pFunc2 ) { *pFunc0 = Func0; *pFunc1 = Func1; *pFunc2 = Func2; *pG2 = G1; *pR = R; } if ( pHashed ) *pHashed = If_CluGrp2Uns( &G1 ); // Kit_DsdPrintFromTruth( (unsigned*)pTruth0, nVars ); printf( "\n" ); // If_CluPrintGroup( &G1 ); return G1; } /* // if ( nVars == 6 ) { // Extra_PrintHex( stdout, (unsigned *)pTruth0, nVars ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned*)pTruth0, nVars ); printf( "\n" ); if ( p != NULL ) If_CluCheck3( NULL, pTruth0, nVars, nLutLeaf, nLutLeaf2, nLutRoot, pR, pG2, pFunc0, pFunc1, pFunc2 ); } */ if ( pHashed ) *pHashed = If_CluGrp2Uns( &G1 ); return G1; } // decomposition exists and sufficient if ( R2.nVars <= nLutRoot ) { if ( pG2 ) *pG2 = G2; if ( pR ) *pR = R2; if ( pFunc0 ) *pFunc0 = Func0; if ( pFunc1 ) *pFunc1 = Func1; if ( pFunc2 ) *pFunc2 = 0; if ( pHashed ) *pHashed = If_CluGrp2Uns( &G1 ); return G1; } // try second decomposition { int Test = 0; if ( Test ) { Kit_DsdPrintFromTruth( (unsigned*)&pLeftOver, R2.nVars ); printf( "\n" ); } } // the new variable is at the bottom - skip it (iVarStart = 1) if ( p->pPars->nStructType == 0 ) // allowed G2 = If_CluCheck( p, pLeftOver, R2.nVars, 0, 0, nLutLeaf2, nLutRoot, &R, &Func0, &Func2, NULL, 0 ); else if ( p->pPars->nStructType == 1 ) // not allowed G2 = If_CluCheck( p, pLeftOver, R2.nVars, 1, 0, nLutLeaf2, nLutRoot, &R, &Func0, &Func2, NULL, 0 ); else if ( p->pPars->nStructType == 2 ) // required G2 = If_CluCheck( p, pLeftOver, R2.nVars, 0, 1, nLutLeaf2, nLutRoot, &R, &Func0, &Func2, NULL, 0 ); else assert( 0 ); if ( G2.nVars == 0 ) { if ( pHashed ) *pHashed = If_CluGrp2Uns( &G2 ); return G2; } // remap variables for ( i = 0; i < G2.nVars; i++ ) { assert( G2.pVars[i] < R2.nVars ); G2.pVars[i] = R2.pVars[ (int)G2.pVars[i] ]; } // remap variables for ( i = 0; i < R.nVars; i++ ) { if ( R.pVars[i] == R2.nVars ) R.pVars[i] = nVars + 1; else R.pVars[i] = R2.pVars[ (int)R.pVars[i] ]; } // decomposition exist if ( pG2 ) *pG2 = G2; if ( pR ) *pR = R; if ( pFunc0 ) *pFunc0 = Func0; if ( pFunc1 ) *pFunc1 = Func1; if ( pFunc2 ) *pFunc2 = Func2; if ( pHashed ) *pHashed = If_CluGrp2Uns( &G1 ); // verify // If_CluVerify3( pTruth0, nVars, &G1, &G2, &R, Func1, Func2, Func0 ); return G1; } // returns the best group found int If_CluCheckExt( void * pMan, word * pTruth, int nVars, int nLutLeaf, int nLutRoot, char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 ) { If_Man_t * p = (If_Man_t *)pMan; If_Grp_t G, R; G = If_CluCheck( p, pTruth, nVars, 0, 0, nLutLeaf, nLutRoot, &R, pFunc0, pFunc1, NULL, 0 ); memcpy( pLut0, &R, sizeof(If_Grp_t) ); memcpy( pLut1, &G, sizeof(If_Grp_t) ); // memcpy( pLut2, &G2, sizeof(If_Grp_t) ); return (G.nVars > 0); } // returns the best group found int If_CluCheckExt3( void * pMan, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, char * pLut0, char * pLut1, char * pLut2, word * pFunc0, word * pFunc1, word * pFunc2 ) { If_Man_t * p = (If_Man_t *)pMan; If_Grp_t G, G2, R; G = If_CluCheck3( p, pTruth, nVars, nLutLeaf, nLutLeaf2, nLutRoot, &R, &G2, pFunc0, pFunc1, pFunc2 ); memcpy( pLut0, &R, sizeof(If_Grp_t) ); memcpy( pLut1, &G, sizeof(If_Grp_t) ); memcpy( pLut2, &G2, sizeof(If_Grp_t) ); return (G.nVars > 0); } // computes delay of the decomposition float If_CluDelayMax( If_Grp_t * g, float * pDelays ) { float Delay = 0.0; int i; for ( i = 0; i < g->nVars; i++ ) Delay = Abc_MaxFloat( Delay, pDelays[(int)g->pVars[i]] ); return Delay; } // returns delay of the decomposition; sets area of the cut as its cost float If_CutDelayLutStruct( If_Man_t * p, If_Cut_t * pCut, char * pStr, float WireDelay ) { float Delays[CLU_VAR_MAX+2]; int fUsed[CLU_VAR_MAX+2] = {0}; If_Obj_t * pLeaf; If_Grp_t G1 = {0}, G2 = {0}, G3 = {0}; int nLeaves = If_CutLeaveNum(pCut); int i, nLutLeaf, nLutRoot; // mark the cut as user cut // pCut->fUser = 1; // quit if parameters are wrong if ( strlen(pStr) != 2 ) { printf( "Wrong LUT struct (%s)\n", pStr ); return ABC_INFINITY; } nLutLeaf = pStr[0] - '0'; if ( nLutLeaf < 3 || nLutLeaf > 6 ) { printf( "Leaf size (%d) should belong to {3,4,5,6}.\n", nLutLeaf ); return ABC_INFINITY; } nLutRoot = pStr[1] - '0'; if ( nLutRoot < 3 || nLutRoot > 6 ) { printf( "Root size (%d) should belong to {3,4,5,6}.\n", nLutRoot ); return ABC_INFINITY; } if ( nLeaves > nLutLeaf + nLutRoot - 1 ) { printf( "The cut size (%d) is too large for the LUT structure %d%d.\n", If_CutLeaveNum(pCut), nLutLeaf, nLutRoot ); return ABC_INFINITY; } // remember the delays If_CutForEachLeaf( p, pCut, pLeaf, i ) Delays[i] = If_ObjCutBest(pLeaf)->Delay; // consider easy case if ( nLeaves <= Abc_MaxInt( nLutLeaf, nLutRoot ) ) { char * pPerm = If_CutPerm( pCut ); assert( nLeaves <= 6 ); for ( i = 0; i < nLeaves; i++ ) { pPerm[i] = 1; G1.pVars[i] = i; } G1.nVars = nLeaves; return 1.0 + If_CluDelayMax( &G1, Delays ); } // derive the first group G1 = If_CluCheck( p, If_CutTruthW(p, pCut), nLeaves, 0, 0, nLutLeaf, nLutRoot, NULL, NULL, NULL, NULL, 1 ); if ( G1.nVars == 0 ) return ABC_INFINITY; // compute the delay Delays[nLeaves] = If_CluDelayMax( &G1, Delays ) + ((WireDelay == 0.0)?1.0:WireDelay); if ( G2.nVars ) Delays[nLeaves+1] = If_CluDelayMax( &G2, Delays ) + ((WireDelay == 0.0)?1.0:WireDelay); // mark used groups for ( i = 0; i < G1.nVars; i++ ) fUsed[(int)G1.pVars[i]] = 1; for ( i = 0; i < G2.nVars; i++ ) fUsed[(int)G2.pVars[i]] = 1; // mark unused groups assert( G1.nMyu >= 2 && G1.nMyu <= 4 ); if ( G1.nMyu > 2 ) fUsed[(int)G1.pVars[G1.nVars-1]] = 0; assert( !G2.nVars || (G2.nMyu >= 2 && G2.nMyu <= 4) ); if ( G2.nMyu > 2 ) fUsed[(int)G2.pVars[G2.nVars-1]] = 0; // create remaining group assert( G3.nVars == 0 ); for ( i = 0; i < nLeaves; i++ ) if ( !fUsed[i] ) G3.pVars[(int)G3.nVars++] = i; G3.pVars[(int)G3.nVars++] = nLeaves; if ( G2.nVars ) G3.pVars[(int)G3.nVars++] = nLeaves+1; assert( G1.nVars + G2.nVars + G3.nVars == nLeaves + (G1.nVars > 0) + (G2.nVars > 0) + (G1.nMyu > 2) + (G2.nMyu > 2) ); // what if both non-disjoint vars are the same??? pCut->Cost = 2 + (G2.nVars > 0); return 1.0 + If_CluDelayMax( &G3, Delays ); } //#define IF_TRY_NEW #ifdef IF_TRY_NEW static Vec_Mem_t * s_vTtMem = NULL; static Vec_Mem_t * s_vTtMem2 = NULL; int If_TtMemCutNum() { return Vec_MemEntryNum(s_vTtMem); } int If_TtMemCutNum2() { return Vec_MemEntryNum(s_vTtMem2); } // printf( "Unique TTs = %d. Unique classes = %d. ", If_TtMemCutNum(), If_TtMemCutNum2() ); // printf( "Check2 = %d. Check3 = %d.\n", s_Count2, s_Count3 ); #endif /**Function************************************************************* Synopsis [Performs additional check.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutPerformCheck16( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr ) { unsigned pTruth[IF_MAX_FUNC_LUTSIZE > 5 ? 1 << (IF_MAX_FUNC_LUTSIZE - 5) : 1]; If_Grp_t G1 = {0};//, G3 = {0}; int i, nLutLeaf, nLutLeaf2, nLutRoot, Length; // stretch the truth table assert( nVars >= 6 ); memcpy( pTruth, pTruth0, sizeof(word) * Abc_TtWordNum(nVars) ); Abc_TtStretch6( (word *)pTruth, nLeaves, p->pPars->nLutSize ); #ifdef IF_TRY_NEW { word pCopy[1024]; int nWords = Abc_TruthWordNum(nVars); int iNum; if ( s_vTtMem == NULL ) { s_vTtMem = Vec_MemAlloc( Abc_Truth6WordNum(nVars), 12 ); // 32 KB/page for 6-var functions Vec_MemHashAlloc( s_vTtMem, 10000 ); } if ( s_vTtMem2 == NULL ) { s_vTtMem2 = Vec_MemAlloc( Abc_Truth6WordNum(nVars), 12 ); // 32 KB/page for 6-var functions Vec_MemHashAlloc( s_vTtMem2, 10000 ); } memcpy( pCopy, pTruth, sizeof(word) * Abc_Truth6WordNum(nVars) ); if ( pCopy[0] & 1 ) for ( i = 0; i < nWords; i++ ) pCopy[i] = ~pCopy[i]; iNum = Vec_MemHashInsert( s_vTtMem, pCopy ); if ( iNum == Vec_MemEntryNum(s_vTtMem) - 1 ) { int pCanonPerm[16]; char pCanonPermC[16]; Abc_TtCanonicize( pCopy, nVars, pCanonPermC ); // If_CluSemiCanonicize( pCopy, nVars, pCanonPerm ); Vec_MemHashInsert( s_vTtMem2, pCopy ); } } #endif // if cutmin is disabled, minimize the function if ( !p->pPars->fCutMin ) nLeaves = Abc_TtMinBase( (word *)pTruth, NULL, nLeaves, nVars ); // quit if parameters are wrong Length = strlen(pStr); if ( Length != 2 && Length != 3 ) { printf( "Wrong LUT struct (%s)\n", pStr ); return 0; } 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 0; } 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 cut size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); return 0; } // consider easy case if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) ) return 1; // derive the first group if ( Length == 2 ) G1 = If_CluCheck( p, (word *)pTruth, nLeaves, 0, 0, nLutLeaf, nLutRoot, NULL, NULL, NULL, NULL, 1 ); else G1 = If_CluCheck3( p, (word *)pTruth, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, NULL, NULL, NULL, NULL, NULL ); // if ( G1.nVars > 0 ) // If_CluPrintGroup( &G1 ); return (int)(G1.nVars > 0); } // testing procedure void If_CluTest() { // word t = 0xff00f0f0ccccaaaa; // word t = 0xfedcba9876543210; // word t = 0xec64000000000000; // word t = 0x0100200000000001; // word t2[4] = { 0x0000800080008000, 0x8000000000008000, 0x8000000080008000, 0x0000000080008000 }; // word t = 0x07770FFF07770FFF; // word t = 0x002000D000D00020; // word t = 0x000F000E000F000F; // word t = 0xF7FFF7F7F7F7F7F7; // word t = 0x0234AFDE23400BCE; // word t = 0x0080008880A088FF; // word s = t; // word t = 0xFFBBBBFFF0B0B0F0; word t = ABC_CONST(0x6DD9926D962D6996); int nVars = 6; int nLutLeaf = 4; int nLutLeaf2 = 4; int nLutRoot = 4; /* word t2[2] = { 0x7f807f807f80807f, 0x7f807f807f807f80 }; int nVars = 7; int nLutLeaf = 3; int nLutLeaf2 = 3; int nLutRoot = 3; */ If_Grp_t G; If_Grp_t G2, R; word Func0, Func1, Func2; return; /* int pCanonPerm[CLU_VAR_MAX]; int uCanonPhase; Kit_DsdPrintFromTruth( (unsigned*)&s, nVars ); printf( "\n" ); uCanonPhase = If_CluSemiCanonicize( &s, nVars, pCanonPerm ); Kit_DsdPrintFromTruth( (unsigned*)&s, nVars ); printf( "\n" ); If_CluSemiCanonicizeVerify( &s, &t, nVars, pCanonPerm, uCanonPhase ); */ Kit_DsdPrintFromTruth( (unsigned*)&t, nVars ); printf( "\n" ); G = If_CluCheck3( NULL, &t, nVars, nLutLeaf, nLutLeaf2, nLutRoot, &R, &G2, &Func0, &Func1, &Func2 ); If_CluPrintGroup( &G ); If_CluPrintGroup( &G2 ); If_CluPrintGroup( &R ); // If_CluVerify3( &t, nVars, &G, &G2, &R, Func1, Func2, Func0 ); return; // If_CutPerformCheck07( NULL, (unsigned *)&t, 6, 6, NULL ); // return; // Kit_DsdPrintFromTruth( (unsigned*)&t, nVars ); printf( "\n" ); // G = If_CluCheck( NULL, &t, nVars, 0, nLutLeaf, nLutRoot, NULL, NULL, NULL, NULL, 0 ); // If_CluPrintGroup( &G ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifDec75.c000066400000000000000000000255041300674244400225470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifDec75.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Performs additional check.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifDec75.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "misc/extra/extra.h" #include "bool/kit/kit.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Finds all boundsets for which decomposition exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdCheckDecExist_rec( char * pStr, char ** p, int * pMatches, int * pnSupp ) { if ( **p == '!' ) (*p)++; while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) (*p)++; if ( **p >= 'a' && **p <= 'z' ) // var { (*pnSupp)++; return 0; } if ( **p == '(' || **p == '[' ) // and/xor { unsigned Mask = 0; int m, pSupps[8] = {0}, nParts = 0, nMints; char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) { Mask |= Dau_DsdCheckDecExist_rec( pStr, p, pMatches, &pSupps[nParts] ); *pnSupp += pSupps[nParts++]; } assert( *p == q ); assert( nParts > 1 ); nMints = (1 << nParts); for ( m = 1; m < nMints; m++ ) { int i, Sum = 0; for ( i = 0; i < nParts; i++ ) if ( (m >> i) & 1 ) Sum += pSupps[i]; assert( Sum > 0 && Sum <= 8 ); if ( Sum >= 2 ) Mask |= (1 << Sum); } return Mask; } if ( **p == '<' || **p == '{' ) // mux { int uSupp; unsigned Mask = 0; char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) { uSupp = 0; Mask |= Dau_DsdCheckDecExist_rec( pStr, p, pMatches, &uSupp ); *pnSupp += uSupp; } assert( *p == q ); Mask |= (1 << *pnSupp); return Mask; } assert( 0 ); return 0; } int Dau_DsdCheckDecExist( char * pDsd ) { int nSupp = 0; if ( pDsd[1] == 0 ) return 0; return Dau_DsdCheckDecExist_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd), &nSupp ); } /**Function************************************************************* Synopsis [Finds all boundsets for which AND-decomposition exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdCheckDecAndExist_rec( char * pStr, char ** p, int * pMatches, int * pnSupp ) { if ( **p == '!' ) (*p)++; while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) (*p)++; if ( **p >= 'a' && **p <= 'z' ) // var { (*pnSupp)++; return 0; } if ( **p == '(' ) // and { unsigned Mask = 0; int m, i, pSupps[8] = {0}, nParts = 0, nSimple = 0, nMints; char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) { Mask |= Dau_DsdCheckDecAndExist_rec( pStr, p, pMatches, &pSupps[nParts] ); nSimple += (pSupps[nParts] == 1); *pnSupp += pSupps[nParts++]; } assert( *p == q ); assert( nParts > 1 ); if ( nSimple > 0 ) { nMints = (1 << nParts); for ( m = 1; m < nMints; m++ ) { int Sum = 0; for ( i = 0; i < nParts; i++ ) if ( pSupps[i] > 1 && ((m >> i) & 1) ) Sum += pSupps[i]; assert( Sum <= 8 ); if ( Sum >= 2 ) for ( i = 0; i < nSimple; i++ ) Mask |= (1 << (Sum + i)); } for ( i = 2; i < nSimple; i++ ) Mask |= (1 << i); } return Mask; } if ( **p == '<' || **p == '{' || **p == '[' ) // mux/xor/nondec { int uSupp; unsigned Mask = 0; char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) { uSupp = 0; Mask |= Dau_DsdCheckDecAndExist_rec( pStr, p, pMatches, &uSupp ); *pnSupp += uSupp; } assert( *p == q ); return Mask; } assert( 0 ); return 0; } int Dau_DsdCheckDecAndExist( char * pDsd ) { int nSupp = 0; if ( pDsd[1] == 0 ) return 1; return Dau_DsdCheckDecAndExist_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd), &nSupp ); } /**Function************************************************************* Synopsis [Performs additional check.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutPerformCheck75__( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr ) { char pDsdStr[1000]; int nSizeNonDec, nDecExists, nDecAndExists; static int Counter = 0; Counter++; if ( nLeaves < 6 ) return 1; assert( nLeaves <= 8 ); if ( nLeaves < 8 && If_CutPerformCheck16( p, pTruth, nVars, nLeaves, "44" ) ) return 1; // check decomposability nSizeNonDec = Dau_DsdDecompose( (word *)pTruth, nLeaves, 0, 0, pDsdStr ); // printf( "Vars = %d %s", nLeaves, pDsdStr ); printf( "\n" ); // Extra_PrintBinary( stdout, &nDecExists, 8 ); printf( "\n" ); // Extra_PrintBinary( stdout, &nDecAndExists, 8 ); printf( "\n" ); if ( nLeaves == 8 ) { if ( nSizeNonDec >= 5 ) return 0; nDecAndExists = Dau_DsdCheckDecAndExist( pDsdStr ); if ( nDecAndExists & 0x10 ) // bit 4 return 1; else return 0; } if ( nLeaves == 7 ) { extern void If_Dec7MinimumBase( word uTruth[2], int * pSupp, int nVarsAll, int * pnVars ); word * pT = (word *)pTruth; word pCof0[2], pCof1[2]; int v, nVarsMin; if ( nSizeNonDec < 5 ) { nDecExists = Dau_DsdCheckDecExist( pDsdStr ); if ( nDecExists & 0x10 ) // bit 4 return 1; nDecAndExists = Dau_DsdCheckDecAndExist( pDsdStr ); if ( nDecAndExists & 0x18 ) // bit 4, 3 return 1; } // check cofactors for ( v = 0; v < 7; v++ ) { pCof0[0] = pCof1[0] = pT[0]; pCof0[1] = pCof1[1] = pT[1]; Abc_TtCofactor0( pCof0, 2, v ); Abc_TtCofactor1( pCof1, 2, v ); if ( Abc_TtSupportSize(pCof0, 7) < 4 ) { If_Dec7MinimumBase( pCof1, NULL, 7, &nVarsMin ); nSizeNonDec = Dau_DsdDecompose( pCof1, nVarsMin, 0, 0, pDsdStr ); if ( nSizeNonDec >= 5 ) continue; nDecExists = Dau_DsdCheckDecExist( pDsdStr ); if ( nDecExists & 0x18 ) // bit 4, 3 return 1; } else if ( Abc_TtSupportSize(pCof1, 7) < 4 ) { If_Dec7MinimumBase( pCof0, NULL, 7, &nVarsMin ); nSizeNonDec = Dau_DsdDecompose( pCof0, nVarsMin, 0, 0, pDsdStr ); if ( nSizeNonDec >= 5 ) continue; nDecExists = Dau_DsdCheckDecExist( pDsdStr ); if ( nDecExists & 0x18 ) // bit 4, 3 return 1; } } return 0; } if ( nLeaves == 6 ) { if ( nSizeNonDec < 5 ) { nDecExists = Dau_DsdCheckDecExist( pDsdStr ); if ( nDecExists & 0x18 ) // bit 4, 3 return 1; nDecAndExists = Dau_DsdCheckDecAndExist( pDsdStr ); if ( nDecAndExists & 0x1C ) // bit 4, 3, 2 return 1; } return If_CutPerformCheck07( p, pTruth, nVars, nLeaves, pStr ); } assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Performs additional check.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr ) { word * pTruthW = (word *)pTruth0; word pTruth[4] = { pTruthW[0], pTruthW[1], pTruthW[2], pTruthW[3] }; assert( nLeaves <= 8 ); if ( !p->pPars->fCutMin ) Abc_TtMinimumBase( pTruth, NULL, nLeaves, &nLeaves ); if ( nLeaves < 6 ) return 1; // if ( nLeaves < 8 && If_CutPerformCheck07( p, (unsigned *)pTruth, nVars, nLeaves, "44" ) ) if ( nLeaves < 8 && If_CutPerformCheck16( p, (unsigned *)pTruth, nVars, nLeaves, "44" ) ) return 1; // this is faster but not compatible with -z if ( !p->pPars->fDeriveLuts && p->pPars->fEnableCheck75 && nLeaves == 8 ) { // char pDsdStr[1000] = "(!(abd)!(c!([fe][gh])))"; char pDsdStr[1000]; int nSizeNonDec = Dau_DsdDecompose( (word *)pTruth, nLeaves, 0, 0, pDsdStr ); if ( nSizeNonDec >= 5 ) return 0; if ( Dau_DsdCheckDecAndExist(pDsdStr) & 0x10 ) // bit 4 return 1; return 0; } if ( If_CutPerformCheck45( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) ) return 1; if ( If_CutPerformCheck54( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) ) return 1; return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifDelay.c000066400000000000000000000405211300674244400227320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifDelay.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Delay balancing for cut functions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifDelay.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "ifCount.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define IF_MAX_CUBES 70 //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the SOP delay using balanced AND decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_CutMaxCubeSize( Vec_Int_t * vCover, int nVars ) { int i, k, Entry, Literal, Count, CountMax = 0; Vec_IntForEachEntry( vCover, Entry, i ) { Count = 0; for ( k = 0; k < nVars; k++ ) { Literal = (3 & (Entry >> (k << 1))); if ( Literal == 1 || Literal == 2 ) Count++; } CountMax = Abc_MaxInt( CountMax, Count ); } return CountMax; } int If_CutDelaySop( If_Man_t * p, If_Cut_t * pCut ) { char * pPerm = If_CutPerm( pCut ); // delay is calculated using 1+log2(NumFanins) 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_Int_t * vCover; If_Obj_t * pLeaf; int i, nLitMax, Delay, DelayMax; // mark cut as a user cut pCut->fUser = 1; if ( pCut->nLeaves == 0 ) return 0; if ( pCut->nLeaves == 1 ) return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; vCover = Vec_WecEntry( p->vTtIsops[pCut->nLeaves], Abc_Lit2Var(If_CutTruthLit(pCut)) ); if ( Vec_IntSize(vCover) == 0 ) return -1; // mark the output as complemented // vAnds = If_CutDelaySopAnds( p, pCut, vCover, RetValue ^ pCut->fCompl ); if ( Vec_IntSize(vCover) > p->pPars->nGateSize ) return -1; // set the area cost assert( If_CutLeaveNum(pCut) >= 0 && If_CutLeaveNum(pCut) <= 16 ); // compute the gate delay nLitMax = If_CutMaxCubeSize( vCover, If_CutLeaveNum(pCut) ); if ( Vec_IntSize(vCover) < 2 ) { pCut->Cost = Vec_IntSize(vCover); Delay = (int)(GateDelays[If_CutLeaveNum(pCut)] + 0.5); DelayMax = 0; If_CutForEachLeaf( p, pCut, pLeaf, i ) DelayMax = Abc_MaxInt( DelayMax, If_ObjCutBest(pLeaf)->Delay + (pPerm[i] = (char)Delay) ); } else { pCut->Cost = Vec_IntSize(vCover) + 1; Delay = (int)(GateDelays[If_CutLeaveNum(pCut)] + GateDelays[nLitMax] + 0.5); DelayMax = 0; If_CutForEachLeaf( p, pCut, pLeaf, i ) DelayMax = Abc_MaxInt( DelayMax, If_ObjCutBest(pLeaf)->Delay + (pPerm[i] = (char)Delay) ); } return DelayMax; } /**Function************************************************************* Synopsis [Compute pin delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * pTimes, word * pFaninRes, int nSuppAll, word * pRes ) { word pPinDelsAnd[IF_MAX_FUNC_LUTSIZE], pPinDelsOr[IF_MAX_CUBES]; int nCounterAnd, pCounterAnd[IF_MAX_FUNC_LUTSIZE]; int nCounterOr, pCounterOr[IF_MAX_CUBES]; int i, k, Entry, Literal, Delay = 0; word ResAnd; if ( Vec_IntSize(vCover) > IF_MAX_CUBES ) return -1; nCounterOr = 0; Vec_IntForEachEntry( vCover, Entry, i ) { nCounterAnd = 0; for ( k = 0; k < nSuppAll; k++ ) { Literal = 3 & (Entry >> (k << 1)); if ( Literal == 1 || Literal == 2 ) // neg or pos literal Delay = If_LogCounterPinDelays( pCounterAnd, &nCounterAnd, pPinDelsAnd, pTimes[k], pFaninRes[k], nSuppAll, 0 ); else if ( Literal != 0 ) assert( 0 ); } assert( nCounterAnd > 0 ); ResAnd = If_LogPinDelaysMulti( pPinDelsAnd, nCounterAnd, nSuppAll, 0 ); Delay = If_LogCounterPinDelays( pCounterOr, &nCounterOr, pPinDelsOr, Delay, ResAnd, nSuppAll, 0 ); } assert( nCounterOr > 0 ); *pRes = If_LogPinDelaysMulti( pPinDelsOr, nCounterOr, nSuppAll, 0 ); return Delay; } int If_CutSopBalancePinDelaysIntInt( Vec_Int_t * vCover, int * pTimes, int nSuppAll, char * pPerm ) { int i, Delay; word Res, FaninRes[IF_MAX_FUNC_LUTSIZE]; for ( i = 0; i < nSuppAll; i++ ) FaninRes[i] = If_CutPinDelayInit(i); Delay = If_CutSopBalancePinDelaysInt( vCover, pTimes, FaninRes, nSuppAll, &Res ); If_CutPinDelayTranslate( Res, nSuppAll, pPerm ); return Delay; } int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ) { if ( pCut->nLeaves == 0 ) // const return 0; if ( pCut->nLeaves == 1 ) // variable { pPerm[0] = 0; return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; } else { Vec_Int_t * vCover; int i, pTimes[IF_MAX_FUNC_LUTSIZE]; vCover = Vec_WecEntry( p->vTtIsops[pCut->nLeaves], Abc_Lit2Var(If_CutTruthLit(pCut)) ); if ( Vec_IntSize(vCover) == 0 ) return -1; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; return If_CutSopBalancePinDelaysIntInt( vCover, pTimes, If_CutLeaveNum(pCut), pPerm ); } } /**Function************************************************************* Synopsis [Evaluate delay using SOP balancing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutSopBalanceEvalInt( Vec_Int_t * vCover, int * pTimes, int * pFaninLits, Vec_Int_t * vAig, int * piRes, int nSuppAll, int * pArea ) { int nCounterAnd, pCounterAnd[IF_MAX_FUNC_LUTSIZE], pFaninLitsAnd[IF_MAX_FUNC_LUTSIZE]; int nCounterOr, pCounterOr[IF_MAX_CUBES], pFaninLitsOr[IF_MAX_CUBES]; int i, k, Entry, Literal, nLits, Delay = 0, iRes = 0; if ( Vec_IntSize(vCover) > IF_MAX_CUBES ) return -1; nCounterOr = 0; Vec_IntForEachEntry( vCover, Entry, i ) { nCounterAnd = nLits = 0; for ( k = 0; k < nSuppAll; k++ ) { Literal = 3 & (Entry >> (k << 1)); if ( Literal == 1 ) // neg literal nLits++, Delay = If_LogCounterAddAig( pCounterAnd, &nCounterAnd, pFaninLitsAnd, pTimes[k], vAig ? Abc_LitNot(pFaninLits[k]) : -1, vAig, nSuppAll, 0, 0 ); else if ( Literal == 2 ) // pos literal nLits++, Delay = If_LogCounterAddAig( pCounterAnd, &nCounterAnd, pFaninLitsAnd, pTimes[k], vAig ? pFaninLits[k] : -1, vAig, nSuppAll, 0, 0 ); else if ( Literal != 0 ) assert( 0 ); } assert( nCounterAnd > 0 ); assert( nLits > 0 ); if ( vAig ) iRes = If_LogCreateAndXorMulti( vAig, pFaninLitsAnd, nCounterAnd, nSuppAll, 0 ); else *pArea += nLits == 1 ? 0 : nLits - 1; Delay = If_LogCounterAddAig( pCounterOr, &nCounterOr, pFaninLitsOr, Delay, vAig ? Abc_LitNot(iRes) : -1, vAig, nSuppAll, 0, 0 ); } assert( nCounterOr > 0 ); if ( vAig ) { *piRes = Abc_LitNot( If_LogCreateAndXorMulti( vAig, pFaninLitsOr, nCounterOr, nSuppAll, 0 ) ); if ( ((vCover->nCap >> 16) & 1) ) // hack to remember complemented attribute *piRes = Abc_LitNot( *piRes ); } else *pArea += Vec_IntSize(vCover) == 1 ? 0 : Vec_IntSize(vCover) - 1; return Delay; } int If_CutSopBalanceEvalIntInt( Vec_Int_t * vCover, int nLeaves, int * pTimes, Vec_Int_t * vAig, int fCompl, int * pArea ) { int pFaninLits[IF_MAX_FUNC_LUTSIZE]; int iRes = 0, Res, k; if ( vAig ) for ( k = 0; k < nLeaves; k++ ) pFaninLits[k] = Abc_Var2Lit(k, 0); Res = If_CutSopBalanceEvalInt( vCover, pTimes, pFaninLits, vAig, &iRes, nLeaves, pArea ); if ( Res == -1 ) return -1; assert( vAig == NULL || Abc_Lit2Var(iRes) == nLeaves + Abc_Lit2Var(Vec_IntSize(vAig)) - 1 ); if ( vAig ) Vec_IntPush( vAig, Abc_LitIsCompl(iRes) ^ fCompl ); assert( vAig == NULL || (Vec_IntSize(vAig) & 1) ); return Res; } int If_CutSopBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig ) { pCut->fUser = 1; if ( vAig ) Vec_IntClear( vAig ); if ( pCut->nLeaves == 0 ) // const { assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); if ( vAig ) Vec_IntPush( vAig, Abc_LitIsCompl(If_CutTruthLit(pCut)) ); pCut->Cost = 0; return 0; } if ( pCut->nLeaves == 1 ) // variable { assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); if ( vAig ) Vec_IntPush( vAig, 0 ); if ( vAig ) Vec_IntPush( vAig, Abc_LitIsCompl(If_CutTruthLit(pCut)) ); pCut->Cost = 0; return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; } else { int fVerbose = 0; Vec_Int_t * vCover = Vec_WecEntry( p->vTtIsops[pCut->nLeaves], Abc_Lit2Var(If_CutTruthLit(pCut)) ); int Delay, Area = 0; int i, pTimes[IF_MAX_FUNC_LUTSIZE]; if ( vCover == NULL ) return -1; assert( Vec_IntSize(vCover) > 0 ); for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; Delay = If_CutSopBalanceEvalIntInt( vCover, If_CutLeaveNum(pCut), pTimes, vAig, Abc_LitIsCompl(If_CutTruthLit(pCut)) ^ pCut->fCompl, &Area ); pCut->Cost = Area; if ( fVerbose ) { int Max = 0, Two = 0; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) Max = Abc_MaxInt( Max, pTimes[i] ); for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) if ( pTimes[i] != Max ) Two = Abc_MaxInt( Two, pTimes[i] ); if ( Two + 2 < Max && Max + 3 < Delay ) { for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) printf( "%3d ", pTimes[i] ); for ( ; i < p->pPars->nLutSize; i++ ) printf( " " ); printf( "-> %3d ", Delay ); Dau_DsdPrintFromTruth( If_CutTruthW(p, pCut), If_CutLeaveNum(pCut) ); Kit_TruthIsopPrintCover( vCover, If_CutLeaveNum(pCut), Abc_LitIsCompl(If_CutTruthLit(pCut)) ^ pCut->fCompl ); { Vec_Int_t vIsop; int pIsop[64]; vIsop.nCap = vIsop.nSize = Abc_Tt6Esop( *If_CutTruthW(p, pCut), pCut->nLeaves, pIsop ); vIsop.pArray = pIsop; printf( "ESOP (%d -> %d)\n", Vec_IntSize(vCover), vIsop.nSize ); Kit_TruthIsopPrintCover( &vIsop, If_CutLeaveNum(pCut), 0 ); } printf( "\n" ); } } return Delay; } } /**Function************************************************************* Synopsis [Evaluate delay using SOP balancing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ) { if ( pCut->nLeaves == 0 ) // const return 0; if ( pCut->nLeaves == 1 ) // variable { pPerm[0] = 0; return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; } else { char * pCutPerm = If_CutDsdPerm( p, pCut ); int LutSize = p->pPars->pLutStruct[0] - '0'; int i, Delay, DelayMax = -1; assert( (If_CutLeaveNum(pCut) > LutSize) == (pCut->uMaskFunc > 0) ); for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) { if ( If_CutLeaveNum(pCut) > LutSize && ((pCut->uMaskFunc >> (i << 1)) & 1) ) pPerm[Abc_Lit2Var((int)pCutPerm[i])] = 2; else pPerm[Abc_Lit2Var((int)pCutPerm[i])] = 1; } for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) { Delay = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; DelayMax = Abc_MaxInt( DelayMax, Delay + (int)pPerm[i] ); } return DelayMax; } } /**Function************************************************************* Synopsis [Evaluate delay using SOP balancing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) { pCut->fUser = 1; pCut->Cost = pCut->nLeaves > 1 ? 1 : 0; pCut->uMaskFunc = 0; if ( pCut->nLeaves == 0 ) // const { assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 ); return 0; } if ( pCut->nLeaves == 1 ) // variable { assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 ); return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; } else { char * pCutPerm = If_CutDsdPerm( p, pCut ); int LutSize = p->pPars->pLutStruct[0] - '0'; int i, pTimes[IF_MAX_FUNC_LUTSIZE]; int DelayMax = -1, nLeafMax = 0; unsigned uLeafMask = 0; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) { pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, Abc_Lit2Var((int)pCutPerm[i])))->Delay; if ( DelayMax < pTimes[i] ) DelayMax = pTimes[i], nLeafMax = 1, uLeafMask = (1 << (i << 1)); else if ( DelayMax == pTimes[i] ) nLeafMax++, uLeafMask |= (1 << (i << 1)); } if ( If_CutLeaveNum(pCut) <= LutSize ) return DelayMax + 1; pCut->Cost = 2; if ( nLeafMax <= LutSize - 1 ) { pCut->uMaskFunc = If_DsdManCheckXY( p->pIfDsdMan, If_CutDsdLit(p, pCut), LutSize, 1, uLeafMask, 0, 0 ); if ( pCut->uMaskFunc > 0 ) return DelayMax + 1; } pCut->uMaskFunc = If_DsdManCheckXY( p->pIfDsdMan, If_CutDsdLit(p, pCut), LutSize, 1, 0, 0, 0 ); if ( pCut->uMaskFunc == 0 ) return -1; return DelayMax + 2; } } /* int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut ) { char pPerm[16]; int Delay2, Delay = If_CutLutBalanceEvalInt( p, pCut ); if ( Delay == -1 ) return -1; Delay2 = If_CutLutBalancePinDelays( p, pCut, pPerm ); if ( Delay2 != Delay ) { int s = 0; char * pCutPerm = If_CutDsdPerm( p, pCut ); If_DsdManPrintNode( p->pIfDsdMan, If_CutDsdLit(p, pCut) ); Dau_DecPrintSet( pCut->uMaskFunc, pCut->nLeaves, 1 ); Kit_DsdPrintFromTruth( If_CutTruthUR(p, pCut), pCut->nLeaves ); printf( "\n" ); for ( s = 0; s < pCut->nLeaves; s++ ) // printf( "%d ", (int)If_ObjCutBest(If_CutLeaf(p, pCut, Abc_Lit2Var((int)pCutPerm[s])))->Delay ); printf( "%d ", (int)If_ObjCutBest(If_CutLeaf(p, pCut, s))->Delay ); printf( "\n" ); Delay = If_CutLutBalanceEvalInt( p, pCut ); Delay2 = If_CutLutBalancePinDelays( p, pCut, pPerm ); } return Delay; } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifDsd.c000066400000000000000000003277571300674244400224310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Computation of DSD representation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "if.h" #include "ifCount.h" #include "misc/extra/extra.h" #include "sat/bsat/satSolver.h" #include "aig/gia/gia.h" #include "bool/kit/kit.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif #ifdef ABC_USE_PTHREADS #ifdef _WIN32 #include "../lib/pthread.h" #else #include #include #endif #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define DSD_VERSION "dsd1" // network types typedef enum { IF_DSD_NONE = 0, // 0: unknown IF_DSD_CONST0, // 1: constant IF_DSD_VAR, // 2: variable IF_DSD_AND, // 3: AND IF_DSD_XOR, // 4: XOR IF_DSD_MUX, // 5: MUX IF_DSD_PRIME // 6: PRIME } If_DsdType_t; typedef struct If_DsdObj_t_ If_DsdObj_t; struct If_DsdObj_t_ { unsigned Id; // node ID unsigned Type : 3; // node type unsigned nSupp : 5; // variable unsigned fMark : 1; // user mark unsigned Count : 18; // variable unsigned nFans : 5; // fanin count unsigned pFans[0]; // fanins }; struct If_DsdMan_t_ { char * pStore; // input/output file int nVars; // max var number int LutSize; // LUT size int nWords; // word number int nBins; // table size unsigned * pBins; // hash table Mem_Flex_t * pMem; // memory for nodes Vec_Ptr_t vObjs; // objects Vec_Int_t vNexts; // next pointers Vec_Int_t vTruths; // truth IDs of prime nodes Vec_Int_t * vTemp1; // temp Vec_Int_t * vTemp2; // temp word ** pTtElems; // elementary TTs Vec_Mem_t * vTtMem[IF_MAX_FUNC_LUTSIZE+1]; // truth table memory and hash table Vec_Ptr_t * vTtDecs[IF_MAX_FUNC_LUTSIZE+1]; // truth table decompositions Vec_Wec_t * vIsops[IF_MAX_FUNC_LUTSIZE+1]; // ISOP for each function int * pSched[IF_MAX_FUNC_LUTSIZE]; // grey code schedules int nTtBits; // the number of truth table bits int nConfigWords; // the number of words for config data per node Vec_Wrd_t * vConfigs; // permutations Gia_Man_t * pTtGia; // GIA to represent truth tables Vec_Int_t * vCover; // temporary memory void * pSat; // SAT solver char * pCellStr; // symbolic cell description int nObjsPrev; // previous number of objects int fNewAsUseless; // set new as useless int nUniqueHits; // statistics int nUniqueMisses; // statistics abctime timeDsd; // statistics abctime timeCanon; // statistics abctime timeCheck; // statistics abctime timeCheck2; // statistics abctime timeVerify; // statistics }; static inline int If_DsdObjWordNum( int nFans ) { return sizeof(If_DsdObj_t) / 8 + nFans / 2 + ((nFans & 1) > 0); } static inline int If_DsdObjTruthId( If_DsdMan_t * p, If_DsdObj_t * pObj ) { return (pObj->Type == IF_DSD_PRIME && pObj->nFans > 2) ? Vec_IntEntry(&p->vTruths, pObj->Id) : -1; } static inline word * If_DsdObjTruth( If_DsdMan_t * p, If_DsdObj_t * pObj ) { return Vec_MemReadEntry(p->vTtMem[pObj->nFans], If_DsdObjTruthId(p, pObj)); } static inline void If_DsdObjSetTruth( If_DsdMan_t * p, If_DsdObj_t * pObj, int Id ) { assert( pObj->Type == IF_DSD_PRIME && pObj->nFans > 2 ); Vec_IntWriteEntry(&p->vTruths, pObj->Id, Id); } static inline void If_DsdObjClean( If_DsdObj_t * pObj ) { memset( pObj, 0, sizeof(If_DsdObj_t) ); } static inline int If_DsdObjId( If_DsdObj_t * pObj ) { return pObj->Id; } static inline int If_DsdObjType( If_DsdObj_t * pObj ) { return pObj->Type; } static inline int If_DsdObjIsVar( If_DsdObj_t * pObj ) { return (int)(pObj->Type == IF_DSD_VAR); } static inline int If_DsdObjSuppSize( If_DsdObj_t * pObj ) { return pObj->nSupp; } static inline int If_DsdObjFaninNum( If_DsdObj_t * pObj ) { return pObj->nFans; } static inline int If_DsdObjFaninC( If_DsdObj_t * pObj, int i ) { assert(i < (int)pObj->nFans); return Abc_LitIsCompl(pObj->pFans[i]); } static inline int If_DsdObjFaninLit( If_DsdObj_t * pObj, int i ) { assert(i < (int)pObj->nFans); return pObj->pFans[i]; } static inline If_DsdObj_t * If_DsdVecObj( Vec_Ptr_t * p, int Id ) { return (If_DsdObj_t *)Vec_PtrEntry(p, Id); } static inline If_DsdObj_t * If_DsdVecConst0( Vec_Ptr_t * p ) { return If_DsdVecObj( p, 0 ); } static inline If_DsdObj_t * If_DsdVecVar( Vec_Ptr_t * p, int v ) { return If_DsdVecObj( p, v+1 ); } static inline int If_DsdVecObjSuppSize( Vec_Ptr_t * p, int iObj ) { return If_DsdVecObj( p, iObj )->nSupp; } static inline int If_DsdVecLitSuppSize( Vec_Ptr_t * p, int iLit ) { return If_DsdVecObjSuppSize( p, Abc_Lit2Var(iLit) ); } static inline int If_DsdVecObjRef( Vec_Ptr_t * p, int iObj ) { return If_DsdVecObj( p, iObj )->Count; } static inline void If_DsdVecObjIncRef( Vec_Ptr_t * p, int iObj ) { if ( If_DsdVecObjRef(p, iObj) < 0x3FFFF ) If_DsdVecObj( p, iObj )->Count++; } static inline If_DsdObj_t * If_DsdObjFanin( Vec_Ptr_t * p, If_DsdObj_t * pObj, int i ) { assert(i < (int)pObj->nFans); return If_DsdVecObj(p, Abc_Lit2Var(pObj->pFans[i])); } static inline int If_DsdVecObjMark( Vec_Ptr_t * p, int iObj ) { return If_DsdVecObj( p, iObj )->fMark; } static inline void If_DsdVecObjSetMark( Vec_Ptr_t * p, int iObj ) { If_DsdVecObj( p, iObj )->fMark = 1; } static inline void If_DsdVecObjClearMark( Vec_Ptr_t * p, int iObj ) { If_DsdVecObj( p, iObj )->fMark = 0; } #define If_DsdVecForEachObj( vVec, pObj, i ) \ Vec_PtrForEachEntry( If_DsdObj_t *, vVec, pObj, i ) #define If_DsdVecForEachObjStart( vVec, pObj, i, Start ) \ Vec_PtrForEachEntryStart( If_DsdObj_t *, vVec, pObj, i, Start ) #define If_DsdVecForEachObjVec( vNodes, vVec, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vNodes)) && ((pObj) = If_DsdVecObj(vVec, Vec_IntEntry(vNodes,i))); i++ ) #define If_DsdVecForEachNode( vVec, pObj, i ) \ Vec_PtrForEachEntryStart( If_DsdObj_t *, vVec, pObj, i, 2 ) #define If_DsdObjForEachFanin( vVec, pObj, pFanin, i ) \ for ( i = 0; (i < If_DsdObjFaninNum(pObj)) && ((pFanin) = If_DsdObjFanin(vVec, pObj, i)); i++ ) #define If_DsdObjForEachFaninLit( vVec, pObj, iLit, i ) \ for ( i = 0; (i < If_DsdObjFaninNum(pObj)) && ((iLit) = If_DsdObjFaninLit(pObj, 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * If_DsdManFileName( If_DsdMan_t * p ) { return p->pStore; } int If_DsdManVarNum( If_DsdMan_t * p ) { return p->nVars; } int If_DsdManObjNum( If_DsdMan_t * p ) { return Vec_PtrSize( &p->vObjs ); } int If_DsdManLutSize( If_DsdMan_t * p ) { return p->LutSize; } int If_DsdManTtBitNum( If_DsdMan_t * p ) { return p->nTtBits; } int If_DsdManPermBitNum( If_DsdMan_t * p ) { return (Abc_Base2Log(p->nVars + 1) + 1) * p->nVars; } void If_DsdManSetLutSize( If_DsdMan_t * p, int nLutSize ) { p->LutSize = nLutSize; } int If_DsdManSuppSize( If_DsdMan_t * p, int iDsd ) { return If_DsdVecLitSuppSize( &p->vObjs, iDsd ); } int If_DsdManCheckDec( If_DsdMan_t * p, int iDsd ) { return If_DsdVecObjMark( &p->vObjs, Abc_Lit2Var(iDsd) ); } int If_DsdManReadMark( If_DsdMan_t * p, int iDsd ) { return If_DsdVecObjMark( &p->vObjs, Abc_Lit2Var(iDsd) ); } void If_DsdManSetNewAsUseless( If_DsdMan_t * p ) { if ( p->nObjsPrev == 0 ) p->nObjsPrev = If_DsdManObjNum(p); p->fNewAsUseless = 1; } word * If_DsdManGetFuncConfig( If_DsdMan_t * p, int iDsd ) { return p->vConfigs ? Vec_WrdEntryP(p->vConfigs, p->nConfigWords * Abc_Lit2Var(iDsd)) : NULL; } char * If_DsdManGetCellStr( If_DsdMan_t * p ) { return p->pCellStr; } /**Function************************************************************* Synopsis [DSD manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word ** If_ManDsdTtElems() { static word TtElems[DAU_MAX_VAR+1][DAU_MAX_WORD], * pTtElems[DAU_MAX_VAR+1] = {NULL}; if ( pTtElems[0] == NULL ) { int v; for ( v = 0; v <= DAU_MAX_VAR; v++ ) pTtElems[v] = TtElems[v]; Abc_TtElemInit( pTtElems, DAU_MAX_VAR ); } return pTtElems; } If_DsdObj_t * If_DsdObjAlloc( If_DsdMan_t * p, int Type, int nFans ) { int nWords = If_DsdObjWordNum( nFans ); If_DsdObj_t * pObj = (If_DsdObj_t *)Mem_FlexEntryFetch( p->pMem, sizeof(word) * nWords ); If_DsdObjClean( pObj ); pObj->Type = Type; pObj->nFans = nFans; pObj->Id = Vec_PtrSize( &p->vObjs ); pObj->fMark = p->fNewAsUseless; pObj->Count = 0; Vec_PtrPush( &p->vObjs, pObj ); Vec_IntPush( &p->vNexts, 0 ); Vec_IntPush( &p->vTruths, -1 ); assert( Vec_IntSize(&p->vNexts) == Vec_PtrSize(&p->vObjs) ); assert( Vec_IntSize(&p->vTruths) == Vec_PtrSize(&p->vObjs) ); return pObj; } If_DsdMan_t * If_DsdManAlloc( int nVars, int LutSize ) { If_DsdMan_t * p; int v; char pFileName[10]; assert( nVars <= DAU_MAX_VAR ); sprintf( pFileName, "%02d.dsd", nVars ); p = ABC_CALLOC( If_DsdMan_t, 1 ); p->pStore = Abc_UtilStrsav( pFileName ); p->nVars = nVars; p->LutSize = LutSize; p->nWords = Abc_TtWordNum( nVars ); p->nBins = Abc_PrimeCudd( 100000 ); p->pBins = ABC_CALLOC( unsigned, p->nBins ); p->pMem = Mem_FlexStart(); p->nConfigWords = 1; Vec_PtrGrow( &p->vObjs, 10000 ); Vec_IntGrow( &p->vNexts, 10000 ); Vec_IntGrow( &p->vTruths, 10000 ); If_DsdObjAlloc( p, IF_DSD_CONST0, 0 ); If_DsdObjAlloc( p, IF_DSD_VAR, 0 )->nSupp = 1; p->vTemp1 = Vec_IntAlloc( 32 ); p->vTemp2 = Vec_IntAlloc( 32 ); p->pTtElems = If_ManDsdTtElems(); for ( v = 3; v <= nVars; v++ ) { p->vTtMem[v] = Vec_MemAlloc( Abc_TtWordNum(v), 12 ); Vec_MemHashAlloc( p->vTtMem[v], 10000 ); p->vTtDecs[v] = Vec_PtrAlloc( 1000 ); } /* p->pTtGia = Gia_ManStart( nVars ); Gia_ManHashAlloc( p->pTtGia ); for ( v = 0; v < nVars; v++ ) Gia_ManAppendCi( p->pTtGia ); */ for ( v = 2; v < nVars; v++ ) p->pSched[v] = Extra_GreyCodeSchedule( v ); if ( LutSize ) p->pSat = If_ManSatBuildXY( LutSize ); p->vCover = Vec_IntAlloc( 0 ); return p; } void If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize ) { Vec_Int_t * vLevel; int v, i, fCompl; word * pTruth; if ( p->vIsops[3] != NULL ) return; if ( Vec_PtrSize(&p->vObjs) > 2 ) printf( "Warning: DSD manager is already started without ISOPs.\n" ); for ( v = 3; v <= nLutSize; v++ ) { p->vIsops[v] = Vec_WecAlloc( 100 ); Vec_MemForEachEntry( p->vTtMem[v], pTruth, i ) { vLevel = Vec_WecPushLevel( p->vIsops[v] ); fCompl = Kit_TruthIsop( (unsigned *)pTruth, v, p->vCover, 1 ); if ( fCompl >= 0 && Vec_IntSize(p->vCover) <= 8 ) { Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) ); Vec_IntAppend( vLevel, p->vCover ); if ( fCompl ) vLevel->nCap ^= (1<<16); // hack to remember complemented attribute } } assert( Vec_WecSize(p->vIsops[v]) == Vec_MemEntryNum(p->vTtMem[v]) ); } } void If_DsdManFree( If_DsdMan_t * p, int fVerbose ) { int v; // If_DsdManDumpDsd( p ); if ( fVerbose ) If_DsdManPrint( p, NULL, 0, 0, 0, 0, 0 ); if ( fVerbose ) { char FileName[10]; for ( v = 3; v <= p->nVars; v++ ) { sprintf( FileName, "dumpdsd%02d", v ); Vec_MemDumpTruthTables( p->vTtMem[v], FileName, v ); } } for ( v = 2; v < p->nVars; v++ ) ABC_FREE( p->pSched[v] ); for ( v = 3; v <= p->nVars; v++ ) { Vec_MemHashFree( p->vTtMem[v] ); Vec_MemFree( p->vTtMem[v] ); Vec_VecFree( (Vec_Vec_t *)(p->vTtDecs[v]) ); if ( p->vIsops[v] ) Vec_WecFree( p->vIsops[v] ); } Vec_WrdFreeP( &p->vConfigs ); Vec_IntFreeP( &p->vTemp1 ); Vec_IntFreeP( &p->vTemp2 ); ABC_FREE( p->vObjs.pArray ); ABC_FREE( p->vNexts.pArray ); ABC_FREE( p->vTruths.pArray ); Mem_FlexStop( p->pMem, 0 ); Gia_ManStopP( &p->pTtGia ); Vec_IntFreeP( &p->vCover ); If_ManSatUnbuild( p->pSat ); ABC_FREE( p->pCellStr ); ABC_FREE( p->pStore ); ABC_FREE( p->pBins ); ABC_FREE( p ); } void If_DsdManDumpDsd( If_DsdMan_t * p, int Support ) { char * pFileName = "tts_nondsd.txt"; If_DsdObj_t * pObj; Vec_Int_t * vMap; FILE * pFile = fopen( pFileName, "wb" ); int v, i; if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return; } for ( v = 3; v <= p->nVars; v++ ) { vMap = Vec_IntStart( Vec_MemEntryNum(p->vTtMem[v]) ); If_DsdVecForEachObj( &p->vObjs, pObj, i ) { if ( Support && Support != If_DsdObjSuppSize(pObj) ) continue; if ( If_DsdObjType(pObj) != IF_DSD_PRIME ) continue; if ( Vec_IntEntry(vMap, If_DsdObjTruthId(p, pObj)) ) continue; Vec_IntWriteEntry(vMap, If_DsdObjTruthId(p, pObj), 1); fprintf( pFile, "0x" ); Abc_TtPrintHexRev( pFile, If_DsdObjTruth(p, pObj), Support ? Abc_MaxInt(Support, 6) : v ); fprintf( pFile, "\n" ); //printf( " " ); //Dau_DsdPrintFromTruth( If_DsdObjTruth(p, pObj), p->nVars ); } Vec_IntFree( vMap ); } fclose( pFile ); } void If_DsdManDumpAll( If_DsdMan_t * p, int Support ) { extern word * If_DsdManComputeTruth( If_DsdMan_t * p, int iDsd, unsigned char * pPermLits ); char * pFileName = "tts_all.txt"; If_DsdObj_t * pObj; word * pRes; int i; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return; } If_DsdVecForEachObj( &p->vObjs, pObj, i ) { if ( Support && Support != If_DsdObjSuppSize(pObj) ) continue; pRes = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL ); fprintf( pFile, "0x" ); Abc_TtPrintHexRev( pFile, pRes, Support ? Abc_MaxInt(Support, 6) : p->nVars ); fprintf( pFile, "\n" ); // printf( " " ); // Dau_DsdPrintFromTruth( pRes, p->nVars ); } fclose( pFile ); } int If_DsdManHasMarks( If_DsdMan_t * p ) { If_DsdObj_t * pObj; int i; If_DsdVecForEachObj( &p->vObjs, pObj, i ) if ( pObj->fMark ) return 1; return 0; } /**Function************************************************************* Synopsis [Printing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_DsdManHashProfile( If_DsdMan_t * p ) { If_DsdObj_t * pObj; unsigned * pSpot; int i, Counter; for ( i = 0; i < p->nBins; i++ ) { Counter = 0; for ( pSpot = p->pBins + i; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(&p->vNexts, pObj->Id), Counter++ ) pObj = If_DsdVecObj( &p->vObjs, *pSpot ); // if ( Counter > 5 ) // printf( "%d ", Counter ); // if ( i > 10000 ) // break; } // printf( "\n" ); } int If_DsdManCheckNonDec_rec( If_DsdMan_t * p, int Id ) { If_DsdObj_t * pObj; int i, iFanin; pObj = If_DsdVecObj( &p->vObjs, Id ); if ( If_DsdObjType(pObj) == IF_DSD_CONST0 ) return 0; if ( If_DsdObjType(pObj) == IF_DSD_VAR ) return 0; if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) return 1; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) if ( If_DsdManCheckNonDec_rec( p, Abc_Lit2Var(iFanin) ) ) return 1; return 0; } void If_DsdManPrint_rec( FILE * pFile, If_DsdMan_t * p, int iDsdLit, unsigned char * pPermLits, int * pnSupp ) { char OpenType[7] = {0, 0, 0, '(', '[', '<', '{'}; char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'}; If_DsdObj_t * pObj; int i, iFanin; fprintf( pFile, "%s", Abc_LitIsCompl(iDsdLit) ? "!" : "" ); pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsdLit) ); if ( If_DsdObjType(pObj) == IF_DSD_CONST0 ) { fprintf( pFile, "0" ); return; } if ( If_DsdObjType(pObj) == IF_DSD_VAR ) { int iPermLit = pPermLits ? (int)pPermLits[(*pnSupp)++] : Abc_Var2Lit((*pnSupp)++, 0); fprintf( pFile, "%s%c", Abc_LitIsCompl(iPermLit)? "!":"", 'a' + Abc_Lit2Var(iPermLit) ); return; } if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) Abc_TtPrintHexRev( pFile, If_DsdObjTruth(p, pObj), If_DsdObjFaninNum(pObj) ); fprintf( pFile, "%c", OpenType[If_DsdObjType(pObj)] ); If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) If_DsdManPrint_rec( pFile, p, iFanin, pPermLits, pnSupp ); fprintf( pFile, "%c", CloseType[If_DsdObjType(pObj)] ); } void If_DsdManPrintOne( FILE * pFile, If_DsdMan_t * p, int iObjId, unsigned char * pPermLits, int fNewLine ) { int nSupp = 0; fprintf( pFile, "%6d : ", iObjId ); fprintf( pFile, "%2d ", If_DsdVecObjSuppSize(&p->vObjs, iObjId) ); fprintf( pFile, "%8d ", If_DsdVecObjRef(&p->vObjs, iObjId) ); fprintf( pFile, "%d ", If_DsdVecObjMark(&p->vObjs, iObjId) ); If_DsdManPrint_rec( pFile, p, Abc_Var2Lit(iObjId, 0), pPermLits, &nSupp ); if ( fNewLine ) fprintf( pFile, "\n" ); assert( nSupp == If_DsdVecObjSuppSize(&p->vObjs, iObjId) ); } #define DSD_ARRAY_LIMIT 16 void If_DsdManPrintDecs( FILE * pFile, If_DsdMan_t * p ) { Vec_Int_t * vDecs; int i, k, v, nSuppSize, nDecMax = 0; int pDecMax[IF_MAX_FUNC_LUTSIZE] = {0}; int pCountsAll[IF_MAX_FUNC_LUTSIZE] = {0}; int pCountsSSizes[IF_MAX_FUNC_LUTSIZE] = {0}; int pCounts[IF_MAX_FUNC_LUTSIZE][DSD_ARRAY_LIMIT+2] = {{0}}; word * pTruth; for ( v = 3; v <= p->nVars; v++ ) { assert( Vec_MemEntryNum(p->vTtMem[v]) == Vec_PtrSize(p->vTtDecs[v]) ); // find max number of decompositions Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vDecs, i ) { pTruth = Vec_MemReadEntry( p->vTtMem[v], i ); nSuppSize = Abc_TtSupportSize( pTruth, p->nVars ); pDecMax[nSuppSize] = Abc_MaxInt( pDecMax[nSuppSize], Vec_IntSize(vDecs) ); nDecMax = Abc_MaxInt( nDecMax, Vec_IntSize(vDecs) ); } // fill up Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vDecs, i ) { pTruth = Vec_MemReadEntry( p->vTtMem[v], i ); nSuppSize = Abc_TtSupportSize( pTruth, p->nVars ); pCountsAll[nSuppSize]++; pCountsSSizes[nSuppSize] += Vec_IntSize(vDecs); pCounts[nSuppSize][Abc_MinInt(DSD_ARRAY_LIMIT+1,Vec_IntSize(vDecs))]++; // pCounts[nSuppSize][Abc_MinInt(DSD_ARRAY_LIMIT+1,Vec_IntSize(vDecs)?1+(Vec_IntSize(vDecs)/10):0)]++; /* if ( nSuppSize == 6 && Vec_IntSize(vDecs) == pDecMax[6] ) { fprintf( pFile, "0x" ); Abc_TtPrintHex( pTruth, nSuppSize ); Dau_DecPrintSets( vDecs, nSuppSize ); } */ } } // print header fprintf( pFile, " N : " ); fprintf( pFile, " Total " ); for ( k = 0; k <= DSD_ARRAY_LIMIT; k++ ) fprintf( pFile, "%6d", k ); fprintf( pFile, " " ); fprintf( pFile, " More" ); fprintf( pFile, " Ave" ); fprintf( pFile, " Max" ); fprintf( pFile, "\n" ); // print rows for ( i = 0; i <= p->nVars; i++ ) { fprintf( pFile, "%2d : ", i ); fprintf( pFile, "%6d ", pCountsAll[i] ); for ( k = 0; k <= DSD_ARRAY_LIMIT; k++ ) // fprintf( pFile, "%6d", pCounts[i][k] ); fprintf( pFile, "%6.1f", 100.0*pCounts[i][k]/Abc_MaxInt(1,pCountsAll[i]) ); fprintf( pFile, " " ); // fprintf( pFile, "%6d", pCounts[i][k] ); fprintf( pFile, "%6.1f", 100.0*pCounts[i][k]/Abc_MaxInt(1,pCountsAll[i]) ); fprintf( pFile, " " ); fprintf( pFile, "%6.1f", 1.0*pCountsSSizes[i]/Abc_MaxInt(1,pCountsAll[i]) ); fprintf( pFile, " " ); fprintf( pFile, "%6d", pDecMax[i] ); fprintf( pFile, "\n" ); } } void If_DsdManPrintOccurs( FILE * pFile, If_DsdMan_t * p ) { char Buffer[100]; If_DsdObj_t * pObj; Vec_Int_t * vOccurs; int nOccurs, nOccursMax, nOccursAll; int i, k, nSizeMax, Counter = 0; // determine the largest fanin and fanout nOccursMax = nOccursAll = 0; If_DsdVecForEachNode( &p->vObjs, pObj, i ) { nOccurs = pObj->Count; nOccursAll += nOccurs; nOccursMax = Abc_MaxInt( nOccursMax, nOccurs ); } // allocate storage for fanin/fanout numbers nSizeMax = 10 * (Abc_Base10Log(nOccursMax) + 1); vOccurs = Vec_IntStart( nSizeMax ); // count the number of fanins and fanouts If_DsdVecForEachNode( &p->vObjs, pObj, i ) { nOccurs = pObj->Count; if ( nOccurs < 10 ) Vec_IntAddToEntry( vOccurs, nOccurs, 1 ); else if ( nOccurs < 100 ) Vec_IntAddToEntry( vOccurs, 10 + nOccurs/10, 1 ); else if ( nOccurs < 1000 ) Vec_IntAddToEntry( vOccurs, 20 + nOccurs/100, 1 ); else if ( nOccurs < 10000 ) Vec_IntAddToEntry( vOccurs, 30 + nOccurs/1000, 1 ); else if ( nOccurs < 100000 ) Vec_IntAddToEntry( vOccurs, 40 + nOccurs/10000, 1 ); else if ( nOccurs < 1000000 ) Vec_IntAddToEntry( vOccurs, 50 + nOccurs/100000, 1 ); else if ( nOccurs < 10000000 ) Vec_IntAddToEntry( vOccurs, 60 + nOccurs/1000000, 1 ); } fprintf( pFile, "The distribution of object occurrences:\n" ); for ( k = 0; k < nSizeMax; k++ ) { if ( Vec_IntEntry(vOccurs, k) == 0 ) continue; if ( k < 10 ) fprintf( pFile, "%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 ); fprintf( pFile, "%15s : ", Buffer ); } fprintf( pFile, "%12d ", Vec_IntEntry(vOccurs, k) ); Counter += Vec_IntEntry(vOccurs, k); fprintf( pFile, "(%6.2f %%)", 100.0*Counter/Vec_PtrSize(&p->vObjs) ); fprintf( pFile, "\n" ); } Vec_IntFree( vOccurs ); fprintf( pFile, "Fanins: Max = %d. Ave = %.2f.\n", nOccursMax, 1.0*nOccursAll/Vec_PtrSize(&p->vObjs) ); } void If_DsdManPrintDistrib( If_DsdMan_t * p ) { If_DsdObj_t * pObj; int i; int CountObj[IF_MAX_FUNC_LUTSIZE+2] = {0}; int CountObjNon[IF_MAX_FUNC_LUTSIZE+2] = {0}; int CountObjNpn[IF_MAX_FUNC_LUTSIZE+2] = {0}; int CountStr[IF_MAX_FUNC_LUTSIZE+2] = {0}; int CountStrNon[IF_MAX_FUNC_LUTSIZE+2] = {0}; int CountMarked[IF_MAX_FUNC_LUTSIZE+2] = {0}; for ( i = 3; i <= p->nVars; i++ ) { CountObjNpn[i] = Vec_MemEntryNum(p->vTtMem[i]); CountObjNpn[p->nVars+1] += Vec_MemEntryNum(p->vTtMem[i]); } If_DsdVecForEachObj( &p->vObjs, pObj, i ) { CountObj[If_DsdObjFaninNum(pObj)]++, CountObj[p->nVars+1]++; if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) CountObjNon[If_DsdObjFaninNum(pObj)]++, CountObjNon[p->nVars+1]++; CountStr[If_DsdObjSuppSize(pObj)]++, CountStr[p->nVars+1]++; if ( If_DsdManCheckNonDec_rec(p, i) ) CountStrNon[If_DsdObjSuppSize(pObj)]++, CountStrNon[p->nVars+1]++; if ( If_DsdVecObjMark(&p->vObjs, i) ) CountMarked[If_DsdObjSuppSize(pObj)]++, CountMarked[p->nVars+1]++; } printf( "***** DSD MANAGER STATISTICS *****\n" ); printf( "Support " ); printf( "Obj " ); printf( "ObjNDSD " ); printf( "NPNNDSD " ); printf( "Str " ); printf( "StrNDSD " ); printf( "Marked " ); printf( "\n" ); for ( i = 0; i <= p->nVars + 1; i++ ) { if ( i == p->nVars + 1 ) printf( "All : " ); else printf( "%3d : ", i ); printf( "%9d ", CountObj[i] ); printf( "%9d ", CountObjNon[i] ); printf( "%6.2f %% ", 100.0 * CountObjNon[i] / Abc_MaxInt(1, CountObj[i]) ); printf( "%9d ", CountObjNpn[i] ); printf( "%6.2f %% ", 100.0 * CountObjNpn[i] / Abc_MaxInt(1, CountObj[i]) ); printf( " " ); printf( "%9d ", CountStr[i] ); printf( "%9d ", CountStrNon[i] ); printf( "%6.2f %% ", 100.0 * CountStrNon[i] / Abc_MaxInt(1, CountStr[i]) ); printf( "%9d ", CountMarked[i] ); printf( "%6.2f %%", 100.0 * CountMarked[i] / Abc_MaxInt(1, CountStr[i]) ); printf( "\n" ); } } void If_DsdManPrint( If_DsdMan_t * p, char * pFileName, int Number, int Support, int fOccurs, int fTtDump, int fVerbose ) { If_DsdObj_t * pObj; Vec_Int_t * vStructs, * vCounts; int CountUsed = 0, CountNonDsd = 0, CountNonDsdStr = 0, CountMarked = 0, CountPrime = 0; int i, v, * pPerm, DsdMax = 0, MemSizeTTs = 0, MemSizeDecs = 0; FILE * pFile; pFile = pFileName ? fopen( pFileName, "wb" ) : stdout; if ( pFileName && pFile == NULL ) { printf( "cannot open output file\n" ); return; } if ( fVerbose ) { fprintf( pFile, "***** NOTATIONS USED BELOW *****\n" ); fprintf( pFile, "Support -- the support size\n" ); fprintf( pFile, "Obj -- the number of nodes in the DSD manager for each support size\n" ); fprintf( pFile, " (the constant node and the primary input node have no support)\n" ); fprintf( pFile, "ObjNDSD -- the number of prime nodes (that is, nodes whose function has no DSD)\n" ); fprintf( pFile, " (percentage is relative to the number of all nodes of that size)\n" ); fprintf( pFile, "NPNNDSD -- the number of different NPN classes of prime nodes\n" ); fprintf( pFile, " (Each NPN class may appear more than once. For example: F1 = 17(ab(cd))\n" ); fprintf( pFile, " and F2 = 17(ab[cd]) both have prime majority node (hex TT is 17),\n" ); fprintf( pFile, " but in one case the majority node is fed by AND, and in another by XOR.\n" ); fprintf( pFile, " These two majority nodes are different nodes in the DSD manager\n" ); fprintf( pFile, "Str -- the number of structures for each support size\n" ); fprintf( pFile, " (each structure is composed of one or more nodes)\n" ); fprintf( pFile, "StrNDSD -- the number of DSD structures containing at least one prime node\n" ); fprintf( pFile, "Marked -- the number of DSD structures matchable with the LUT structure (say, \"44\")\n" ); } If_DsdVecForEachObj( &p->vObjs, pObj, i ) { if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) DsdMax = Abc_MaxInt( DsdMax, pObj->nFans ); CountPrime += If_DsdObjType(pObj) == IF_DSD_PRIME; CountNonDsdStr += If_DsdManCheckNonDec_rec( p, pObj->Id ); CountUsed += ( If_DsdVecObjRef(&p->vObjs, pObj->Id) > 0 ); CountMarked += If_DsdVecObjMark( &p->vObjs, i ); } for ( v = 3; v <= p->nVars; v++ ) { CountNonDsd += Vec_MemEntryNum(p->vTtMem[v]); MemSizeTTs += Vec_MemEntrySize(p->vTtMem[v]) * Vec_MemEntryNum(p->vTtMem[v]); MemSizeDecs += (int)Vec_VecMemoryInt((Vec_Vec_t *)(p->vTtDecs[v])); } If_DsdManPrintDistrib( p ); printf( "Number of inputs = %d. LUT size = %d. Marks = %s. NewAsUseless = %s. Bookmark = %d.\n", p->nVars, p->LutSize, If_DsdManHasMarks(p)? "yes" : "no", p->fNewAsUseless? "yes" : "no", p->nObjsPrev ); if ( p->pCellStr ) printf( "Symbolic cell description: %s\n", p->pCellStr ); if ( p->pTtGia ) fprintf( pFile, "Non-DSD AIG nodes = %8d\n", Gia_ManAndNum(p->pTtGia) ); fprintf( pFile, "Unique table misses = %8d\n", p->nUniqueMisses ); fprintf( pFile, "Unique table hits = %8d\n", p->nUniqueHits ); fprintf( pFile, "Memory used for objects = %8.2f MB.\n", 1.0*Mem_FlexReadMemUsage(p->pMem)/(1<<20) ); fprintf( pFile, "Memory used for functions = %8.2f MB.\n", 8.0*(MemSizeTTs+sizeof(int)*Vec_IntCap(&p->vTruths))/(1<<20) ); fprintf( pFile, "Memory used for hash table = %8.2f MB.\n", 1.0*sizeof(int)*(p->nBins+Vec_IntCap(&p->vNexts))/(1<<20) ); fprintf( pFile, "Memory used for bound sets = %8.2f MB.\n", 1.0*MemSizeDecs/(1<<20) ); fprintf( pFile, "Memory used for array = %8.2f MB.\n", 1.0*sizeof(void *)*Vec_PtrCap(&p->vObjs)/(1<<20) ); if ( p->pTtGia ) fprintf( pFile, "Memory used for AIG = %8.2f MB.\n", 8.0*Gia_ManAndNum(p->pTtGia)/(1<<20) ); if ( p->timeDsd ) { Abc_PrintTime( 1, "Time DSD ", p->timeDsd ); Abc_PrintTime( 1, "Time canon ", p->timeCanon-p->timeCheck ); Abc_PrintTime( 1, "Time check ", p->timeCheck ); Abc_PrintTime( 1, "Time check2", p->timeCheck2 ); Abc_PrintTime( 1, "Time verify", p->timeVerify ); } if ( fOccurs ) If_DsdManPrintOccurs( stdout, p ); // If_DsdManHashProfile( p ); if ( fTtDump ) If_DsdManDumpDsd( p, Support ); if ( fTtDump ) If_DsdManDumpAll( p, Support ); // If_DsdManPrintDecs( stdout, p ); if ( !fVerbose ) return; vStructs = Vec_IntAlloc( 1000 ); vCounts = Vec_IntAlloc( 1000 ); If_DsdVecForEachObj( &p->vObjs, pObj, i ) { if ( Number && i % Number ) continue; if ( Support && Support != If_DsdObjSuppSize(pObj) ) continue; Vec_IntPush( vStructs, i ); Vec_IntPush( vCounts, -(int)pObj->Count ); // If_DsdManPrintOne( pFile, p, pObj->Id, NULL, 1 ); } // fprintf( pFile, "\n" ); pPerm = Abc_MergeSortCost( Vec_IntArray(vCounts), Vec_IntSize(vCounts) ); for ( i = 0; i < Abc_MinInt(Vec_IntSize(vCounts), 20); i++ ) { printf( "%2d : ", i+1 ); pObj = If_DsdVecObj( &p->vObjs, Vec_IntEntry(vStructs, pPerm[i]) ); If_DsdManPrintOne( pFile, p, pObj->Id, NULL, 1 ); } ABC_FREE( pPerm ); Vec_IntFree( vStructs ); Vec_IntFree( vCounts ); if ( pFileName ) fclose( pFile ); } /**Function************************************************************* Synopsis [Check if the function is non-trivial.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_DsdManCheckNonTriv( If_DsdMan_t * p, int Id, int nVars, int iVarMax ) { If_DsdObj_t * pObj; int i, iFanin; pObj = If_DsdVecObj( &p->vObjs, Id ); if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) return 1; if ( If_DsdObjFaninNum(pObj) == nVars ) return 0; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) if ( Abc_Lit2Var(iFanin) == 1 && i == iVarMax ) return 0; return 1; } /**Function************************************************************* Synopsis [Sorting DSD literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_DsdObjCompare( If_DsdMan_t * pMan, Vec_Ptr_t * p, int iLit0, int iLit1 ) { If_DsdObj_t * p0 = If_DsdVecObj(p, Abc_Lit2Var(iLit0)); If_DsdObj_t * p1 = If_DsdVecObj(p, Abc_Lit2Var(iLit1)); int i, Res; if ( If_DsdObjType(p0) < If_DsdObjType(p1) ) return -1; if ( If_DsdObjType(p0) > If_DsdObjType(p1) ) return 1; if ( If_DsdObjType(p0) < IF_DSD_AND ) return 0; if ( If_DsdObjFaninNum(p0) < If_DsdObjFaninNum(p1) ) return -1; if ( If_DsdObjFaninNum(p0) > If_DsdObjFaninNum(p1) ) return 1; if ( If_DsdObjType(p0) == IF_DSD_PRIME ) { if ( If_DsdObjTruthId(pMan, p0) < If_DsdObjTruthId(pMan, p1) ) return -1; if ( If_DsdObjTruthId(pMan, p0) > If_DsdObjTruthId(pMan, p1) ) return 1; } for ( i = 0; i < If_DsdObjFaninNum(p0); i++ ) { Res = If_DsdObjCompare( pMan, p, If_DsdObjFaninLit(p0, i), If_DsdObjFaninLit(p1, i) ); if ( Res != 0 ) return Res; } if ( Abc_LitIsCompl(iLit0) > Abc_LitIsCompl(iLit1) ) return -1; if ( Abc_LitIsCompl(iLit0) < Abc_LitIsCompl(iLit1) ) return 1; assert( iLit0 == iLit1 ); return 0; } void If_DsdObjSort( If_DsdMan_t * pMan, Vec_Ptr_t * p, int * pLits, int nLits, int * pPerm ) { int i, j, best_i; for ( i = 0; i < nLits-1; i++ ) { best_i = i; for ( j = i+1; j < nLits; j++ ) if ( If_DsdObjCompare(pMan, p, pLits[best_i], pLits[j]) == 1 ) best_i = j; if ( i == best_i ) continue; ABC_SWAP( int, pLits[i], pLits[best_i] ); if ( pPerm ) ABC_SWAP( int, pPerm[i], pPerm[best_i] ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned If_DsdObjHashKey( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId ) { static int s_Primes[24] = { 1049, 1297, 1559, 1823, 2089, 2371, 2663, 2909, 3221, 3517, 3779, 4073, 4363, 4663, 4973, 5281, 5573, 5861, 6199, 6481, 6803, 7109, 7477, 7727 }; int i; unsigned uHash = Type * 7873 + nLits * 8147; for ( i = 0; i < nLits; i++ ) uHash += pLits[i] * s_Primes[i & 0xF]; if ( Type == IF_DSD_PRIME ) uHash += truthId * s_Primes[i & 0xF]; return uHash % p->nBins; } unsigned * If_DsdObjHashLookup( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId ) { If_DsdObj_t * pObj; unsigned * pSpot = p->pBins + If_DsdObjHashKey(p, Type, pLits, nLits, truthId); for ( ; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(&p->vNexts, pObj->Id) ) { pObj = If_DsdVecObj( &p->vObjs, *pSpot ); if ( If_DsdObjType(pObj) == Type && If_DsdObjFaninNum(pObj) == nLits && !memcmp(pObj->pFans, pLits, sizeof(int)*If_DsdObjFaninNum(pObj)) && truthId == If_DsdObjTruthId(p, pObj) ) { p->nUniqueHits++; return pSpot; } } p->nUniqueMisses++; return pSpot; } static void If_DsdObjHashResize( If_DsdMan_t * p ) { If_DsdObj_t * pObj; unsigned * pSpot; int i, Prev = p->nUniqueMisses; p->nBins = Abc_PrimeCudd( 2 * p->nBins ); p->pBins = ABC_REALLOC( unsigned, p->pBins, p->nBins ); memset( p->pBins, 0, sizeof(unsigned) * p->nBins ); Vec_IntFill( &p->vNexts, Vec_PtrSize(&p->vObjs), 0 ); If_DsdVecForEachNode( &p->vObjs, pObj, i ) { pSpot = If_DsdObjHashLookup( p, pObj->Type, (int *)pObj->pFans, pObj->nFans, If_DsdObjTruthId(p, pObj) ); assert( *pSpot == 0 ); *pSpot = pObj->Id; } assert( p->nUniqueMisses - Prev == Vec_PtrSize(&p->vObjs) - 2 ); p->nUniqueMisses = Prev; } int If_DsdObjCreate( If_DsdMan_t * p, int Type, int * pLits, int nLits, int truthId ) { If_DsdObj_t * pObj, * pFanin; int i, iPrev = -1; // check structural canonicity assert( Type != DAU_DSD_MUX || nLits == 3 ); // assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(pLits[0]) ); assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(pLits[1]) || !Abc_LitIsCompl(pLits[2]) ); // check that leaves are in good order if ( Type == DAU_DSD_AND || Type == DAU_DSD_XOR ) { for ( i = 0; i < nLits; i++ ) { pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[i]) ); assert( Type != DAU_DSD_AND || Abc_LitIsCompl(pLits[i]) || If_DsdObjType(pFanin) != DAU_DSD_AND ); assert( Type != DAU_DSD_XOR || If_DsdObjType(pFanin) != DAU_DSD_XOR ); assert( iPrev == -1 || If_DsdObjCompare(p, &p->vObjs, iPrev, pLits[i]) <= 0 ); iPrev = pLits[i]; } } // create new node pObj = If_DsdObjAlloc( p, Type, nLits ); if ( Type == DAU_DSD_PRIME ) If_DsdObjSetTruth( p, pObj, truthId ); assert( pObj->nSupp == 0 ); for ( i = 0; i < nLits; i++ ) { pObj->pFans[i] = pLits[i]; pObj->nSupp += If_DsdVecLitSuppSize(&p->vObjs, pLits[i]); } // check decomposability if ( p->LutSize && !If_DsdManCheckXY(p, Abc_Var2Lit(pObj->Id, 0), p->LutSize, 0, 0, 0, 0) ) If_DsdVecObjSetMark( &p->vObjs, pObj->Id ); return pObj->Id; } int If_DsdObjFindOrAdd( If_DsdMan_t * p, int Type, int * pLits, int nLits, word * pTruth ) { int PrevSize = (Type == IF_DSD_PRIME) ? Vec_MemEntryNum( p->vTtMem[nLits] ) : -1; int objId, truthId = (Type == IF_DSD_PRIME) ? Vec_MemHashInsert(p->vTtMem[nLits], pTruth) : -1; unsigned * pSpot = If_DsdObjHashLookup( p, Type, pLits, nLits, truthId ); //abctime clk; if ( *pSpot ) return (int)*pSpot; //clk = Abc_Clock(); if ( p->LutSize && truthId >= 0 && truthId == Vec_PtrSize(p->vTtDecs[nLits]) ) { Vec_Int_t * vSets = Dau_DecFindSets_int( pTruth, nLits, p->pSched ); assert( truthId == Vec_MemEntryNum(p->vTtMem[nLits])-1 ); Vec_PtrPush( p->vTtDecs[nLits], vSets ); // Dau_DecPrintSets( vSets, nLits ); } if ( p->vIsops[nLits] && truthId >= 0 && PrevSize != Vec_MemEntryNum(p->vTtMem[nLits]) ) { Vec_Int_t * vLevel = Vec_WecPushLevel( p->vIsops[nLits] ); int fCompl = Kit_TruthIsop( (unsigned *)pTruth, nLits, p->vCover, 1 ); if ( fCompl >= 0 && Vec_IntSize(p->vCover) <= 8 ) { Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) ); Vec_IntAppend( vLevel, p->vCover ); if ( fCompl ) vLevel->nCap ^= (1<<16); // hack to remember complemented attribute } assert( Vec_WecSize(p->vIsops[nLits]) == Vec_MemEntryNum(p->vTtMem[nLits]) ); } if ( p->pTtGia && truthId >= 0 && truthId == Vec_MemEntryNum(p->vTtMem[nLits])-1 ) { // int nObjOld = Gia_ManAndNum(p->pTtGia); int Lit = Kit_TruthToGia( p->pTtGia, (unsigned *)pTruth, nLits, p->vCover, NULL, 1 ); // printf( "%d ", Gia_ManAndNum(p->pTtGia)-nObjOld ); Gia_ManAppendCo( p->pTtGia, Lit ); } //p->timeCheck += Abc_Clock() - clk; *pSpot = Vec_PtrSize( &p->vObjs ); objId = If_DsdObjCreate( p, Type, pLits, nLits, truthId ); if ( Vec_PtrSize(&p->vObjs) > p->nBins ) If_DsdObjHashResize( p ); return objId; } /**Function************************************************************* Synopsis [Saving/loading DSD manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_DsdManSave( If_DsdMan_t * p, char * pFileName ) { If_DsdObj_t * pObj; Vec_Int_t * vSets; word * pTruth; int i, v, Num; FILE * pFile = fopen( pFileName ? pFileName : p->pStore, "wb" ); if ( pFile == NULL ) { printf( "Writing DSD manager file \"%s\" has failed.\n", pFileName ? pFileName : p->pStore ); return; } fwrite( DSD_VERSION, 4, 1, pFile ); Num = p->nVars; fwrite( &Num, 4, 1, pFile ); Num = p->LutSize; fwrite( &Num, 4, 1, pFile ); Num = Vec_PtrSize(&p->vObjs); fwrite( &Num, 4, 1, pFile ); Vec_PtrForEachEntryStart( If_DsdObj_t *, &p->vObjs, pObj, i, 2 ) { Num = If_DsdObjWordNum( pObj->nFans ); fwrite( &Num, 4, 1, pFile ); fwrite( pObj, sizeof(word)*Num, 1, pFile ); if ( pObj->Type == IF_DSD_PRIME ) fwrite( Vec_IntEntryP(&p->vTruths, i), 4, 1, pFile ); } for ( v = 3; v <= p->nVars; v++ ) { int nBytes = sizeof(word)*Vec_MemEntrySize(p->vTtMem[v]); Num = Vec_MemEntryNum(p->vTtMem[v]); fwrite( &Num, 4, 1, pFile ); Vec_MemForEachEntry( p->vTtMem[v], pTruth, i ) fwrite( pTruth, nBytes, 1, pFile ); Num = Vec_PtrSize(p->vTtDecs[v]); fwrite( &Num, 4, 1, pFile ); Vec_PtrForEachEntry( Vec_Int_t *, p->vTtDecs[v], vSets, i ) { Num = Vec_IntSize(vSets); fwrite( &Num, 4, 1, pFile ); fwrite( Vec_IntArray(vSets), sizeof(int)*Num, 1, pFile ); } } Num = p->nConfigWords; fwrite( &Num, 4, 1, pFile ); Num = p->nTtBits; fwrite( &Num, 4, 1, pFile ); Num = p->vConfigs ? Vec_WrdSize(p->vConfigs) : 0; fwrite( &Num, 4, 1, pFile ); if ( Num ) fwrite( Vec_WrdArray(p->vConfigs), sizeof(word)*Num, 1, pFile ); Num = p->pCellStr ? strlen(p->pCellStr) : 0; fwrite( &Num, 4, 1, pFile ); if ( Num ) fwrite( p->pCellStr, sizeof(char)*Num, 1, pFile ); fclose( pFile ); } If_DsdMan_t * If_DsdManLoad( char * pFileName ) { If_DsdMan_t * p; If_DsdObj_t * pObj; Vec_Int_t * vSets; char pBuffer[10]; unsigned * pSpot; word * pTruth; int i, v, Num, Num2, RetValue; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Reading DSD manager file \"%s\" has failed.\n", pFileName ); return NULL; } RetValue = fread( pBuffer, 4, 1, pFile ); if ( strncmp(pBuffer, DSD_VERSION, strlen(DSD_VERSION)) ) { printf( "Unrecognized format of file \"%s\".\n", pFileName ); return NULL; } RetValue = fread( &Num, 4, 1, pFile ); p = If_DsdManAlloc( Num, 0 ); ABC_FREE( p->pStore ); p->pStore = Abc_UtilStrsav( pFileName ); RetValue = fread( &Num, 4, 1, pFile ); p->LutSize = Num; p->pSat = If_ManSatBuildXY( p->LutSize ); RetValue = fread( &Num, 4, 1, pFile ); assert( Num >= 2 ); Vec_PtrFillExtra( &p->vObjs, Num, NULL ); Vec_IntFill( &p->vNexts, Num, 0 ); Vec_IntFill( &p->vTruths, Num, -1 ); p->nBins = Abc_PrimeCudd( 2*Num ); p->pBins = ABC_REALLOC( unsigned, p->pBins, p->nBins ); memset( p->pBins, 0, sizeof(unsigned) * p->nBins ); for ( i = 2; i < Vec_PtrSize(&p->vObjs); i++ ) { RetValue = fread( &Num, 4, 1, pFile ); pObj = (If_DsdObj_t *)Mem_FlexEntryFetch( p->pMem, sizeof(word) * Num ); RetValue = fread( pObj, sizeof(word)*Num, 1, pFile ); Vec_PtrWriteEntry( &p->vObjs, i, pObj ); if ( pObj->Type == IF_DSD_PRIME ) { RetValue = fread( &Num, 4, 1, pFile ); Vec_IntWriteEntry( &p->vTruths, i, Num ); } pSpot = If_DsdObjHashLookup( p, pObj->Type, (int *)pObj->pFans, pObj->nFans, If_DsdObjTruthId(p, pObj) ); assert( *pSpot == 0 ); *pSpot = pObj->Id; } assert( p->nUniqueMisses == Vec_PtrSize(&p->vObjs) - 2 ); p->nUniqueMisses = 0; pTruth = ABC_ALLOC( word, p->nWords ); for ( v = 3; v <= p->nVars; v++ ) { int nBytes = sizeof(word)*Vec_MemEntrySize(p->vTtMem[v]); RetValue = fread( &Num, 4, 1, pFile ); for ( i = 0; i < Num; i++ ) { RetValue = fread( pTruth, nBytes, 1, pFile ); Vec_MemHashInsert( p->vTtMem[v], pTruth ); } assert( Num == Vec_MemEntryNum(p->vTtMem[v]) ); RetValue = fread( &Num2, 4, 1, pFile ); for ( i = 0; i < Num2; i++ ) { RetValue = fread( &Num, 4, 1, pFile ); vSets = Vec_IntAlloc( Num ); RetValue = fread( Vec_IntArray(vSets), sizeof(int)*Num, 1, pFile ); vSets->nSize = Num; Vec_PtrPush( p->vTtDecs[v], vSets ); } assert( Num2 == Vec_PtrSize(p->vTtDecs[v]) ); } ABC_FREE( pTruth ); RetValue = fread( &Num, 4, 1, pFile ); p->nConfigWords = Num; RetValue = fread( &Num, 4, 1, pFile ); p->nTtBits = Num; RetValue = fread( &Num, 4, 1, pFile ); if ( RetValue && Num ) { p->vConfigs = Vec_WrdStart( Num ); RetValue = fread( Vec_WrdArray(p->vConfigs), sizeof(word)*Num, 1, pFile ); } RetValue = fread( &Num, 4, 1, pFile ); if ( RetValue && Num ) { p->pCellStr = ABC_CALLOC( char, Num + 1 ); RetValue = fread( p->pCellStr, sizeof(char)*Num, 1, pFile ); } fclose( pFile ); return p; } void If_DsdManMerge( If_DsdMan_t * p, If_DsdMan_t * pNew ) { If_DsdObj_t * pObj; Vec_Int_t * vMap; int pFanins[DAU_MAX_VAR]; int i, k, iFanin, Id; if ( p->nVars < pNew->nVars ) { printf( "The number of variables should be the same or smaller.\n" ); return; } if ( p->LutSize != pNew->LutSize ) { printf( "LUT size should be the same.\n" ); return; } assert( p->nTtBits == pNew->nTtBits ); assert( p->nConfigWords == pNew->nConfigWords ); if ( If_DsdManHasMarks(p) != If_DsdManHasMarks(pNew) ) printf( "Warning! Old manager has %smarks while new manager has %smarks.\n", If_DsdManHasMarks(p) ? "" : "no ", If_DsdManHasMarks(pNew) ? "" : "no " ); vMap = Vec_IntAlloc( Vec_PtrSize(&pNew->vObjs) ); Vec_IntPush( vMap, 0 ); Vec_IntPush( vMap, 1 ); if ( p->vConfigs && pNew->vConfigs ) Vec_WrdFillExtra( p->vConfigs, p->nConfigWords * (Vec_PtrSize(&p->vObjs) + Vec_PtrSize(&pNew->vObjs)), 0 ); If_DsdVecForEachNode( &pNew->vObjs, pObj, i ) { If_DsdObjForEachFaninLit( &pNew->vObjs, pObj, iFanin, k ) pFanins[k] = Abc_Lit2LitV( Vec_IntArray(vMap), iFanin ); Id = If_DsdObjFindOrAdd( p, pObj->Type, pFanins, pObj->nFans, pObj->Type == IF_DSD_PRIME ? If_DsdObjTruth(pNew, pObj) : NULL ); if ( pObj->fMark ) If_DsdVecObjSetMark( &p->vObjs, Id ); if ( p->vConfigs && pNew->vConfigs && p->nConfigWords * i < Vec_WrdSize(pNew->vConfigs) ) { //Vec_WrdFillExtra( p->vConfigs, Id, Vec_WrdEntry(pNew->vConfigs, i) ); word * pConfigNew = Vec_WrdEntryP(pNew->vConfigs, p->nConfigWords * i); word * pConfigOld = Vec_WrdEntryP(p->vConfigs, p->nConfigWords * Id); memcpy( pConfigOld, pConfigNew, sizeof(word) * p->nConfigWords ); } Vec_IntPush( vMap, Id ); } assert( Vec_IntSize(vMap) == Vec_PtrSize(&pNew->vObjs) ); Vec_IntFree( vMap ); if ( p->vConfigs && pNew->vConfigs ) Vec_WrdShrink( p->vConfigs, p->nConfigWords * Vec_PtrSize(&p->vObjs) ); } void If_DsdManCleanOccur( If_DsdMan_t * p, int fVerbose ) { If_DsdObj_t * pObj; int i; If_DsdVecForEachObj( &p->vObjs, pObj, i ) pObj->Count = 0; } void If_DsdManCleanMarks( If_DsdMan_t * p, int fVerbose ) { If_DsdObj_t * pObj; int i; ABC_FREE( p->pCellStr ); Vec_WrdFreeP( &p->vConfigs ); If_DsdVecForEachObj( &p->vObjs, pObj, i ) pObj->fMark = 0; } void If_DsdManInvertMarks( If_DsdMan_t * p, int fVerbose ) { If_DsdObj_t * pObj; int i; ABC_FREE( p->pCellStr ); //Vec_WrdFreeP( &p->vConfigs ); If_DsdVecForEachObj( &p->vObjs, pObj, i ) pObj->fMark = !pObj->fMark; } void If_DsdManFilter_rec( If_DsdMan_t * pNew, If_DsdMan_t * p, int i, Vec_Int_t * vMap ) { If_DsdObj_t * pObj; int pFanins[DAU_MAX_VAR]; int k, iFanin, Id; if ( Vec_IntEntry(vMap, i) >= 0 ) return; // call recursively pObj = If_DsdVecObj( &p->vObjs, i ); If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, k ) If_DsdManFilter_rec( pNew, p, Abc_Lit2Var(iFanin), vMap ); // duplicate this one If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, k ) pFanins[k] = Abc_Lit2LitV( Vec_IntArray(vMap), iFanin ); Id = If_DsdObjFindOrAdd( pNew, pObj->Type, pFanins, pObj->nFans, pObj->Type == IF_DSD_PRIME ? If_DsdObjTruth(p, pObj) : NULL ); if ( pObj->fMark ) If_DsdVecObjSetMark( &pNew->vObjs, Id ); If_DsdVecObj( &pNew->vObjs, Id )->Count = pObj->Count; // save the result Vec_IntWriteEntry( vMap, i, Id ); } If_DsdMan_t * If_DsdManFilter( If_DsdMan_t * p, int Limit ) { If_DsdMan_t * pNew = If_DsdManAlloc( p->nVars, p->LutSize ); If_DsdObj_t * pObj; Vec_Int_t * vMap; int i; vMap = Vec_IntStartFull( Vec_PtrSize(&p->vObjs) ); Vec_IntWriteEntry( vMap, 0, 0 ); Vec_IntWriteEntry( vMap, 1, 1 ); If_DsdVecForEachNode( &p->vObjs, pObj, i ) if ( (int)pObj->Count >= Limit ) If_DsdManFilter_rec( pNew, p, i, vMap ); Vec_IntFree( vMap ); return pNew; } /**Function************************************************************* Synopsis [Collect nodes of the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_DsdManCollect_rec( If_DsdMan_t * p, int Id, Vec_Int_t * vNodes, Vec_Int_t * vFirsts, int * pnSupp ) { int i, iFanin, iFirst; If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id ); if ( If_DsdObjType(pObj) == IF_DSD_CONST0 ) return; if ( If_DsdObjType(pObj) == IF_DSD_VAR ) { (*pnSupp)++; return; } iFirst = *pnSupp; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) If_DsdManCollect_rec( p, Abc_Lit2Var(iFanin), vNodes, vFirsts, pnSupp ); Vec_IntPush( vNodes, Id ); Vec_IntPush( vFirsts, iFirst ); } void If_DsdManCollect( If_DsdMan_t * p, int Id, Vec_Int_t * vNodes, Vec_Int_t * vFirsts ) { int nSupp = 0; Vec_IntClear( vNodes ); Vec_IntClear( vFirsts ); If_DsdManCollect_rec( p, Id, vNodes, vFirsts, &nSupp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_DsdManComputeTruth_rec( If_DsdMan_t * p, int iDsd, word * pRes, unsigned char * pPermLits, int * pnSupp ) { int i, iFanin, fCompl = Abc_LitIsCompl(iDsd); If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) ); if ( If_DsdObjType(pObj) == IF_DSD_VAR ) { int iPermLit = pPermLits ? (int)pPermLits[*pnSupp] : Abc_Var2Lit(*pnSupp, 0); (*pnSupp)++; assert( (*pnSupp) <= p->nVars ); Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], p->nWords, fCompl ^ Abc_LitIsCompl(iPermLit) ); return; } if ( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR ) { word pTtTemp[DAU_MAX_WORD]; if ( If_DsdObjType(pObj) == IF_DSD_AND ) Abc_TtConst1( pRes, p->nWords ); else Abc_TtConst0( pRes, p->nWords ); If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) { If_DsdManComputeTruth_rec( p, iFanin, pTtTemp, pPermLits, pnSupp ); if ( If_DsdObjType(pObj) == IF_DSD_AND ) Abc_TtAnd( pRes, pRes, pTtTemp, p->nWords, 0 ); else Abc_TtXor( pRes, pRes, pTtTemp, p->nWords, 0 ); } if ( fCompl ) Abc_TtNot( pRes, p->nWords ); return; } if ( If_DsdObjType(pObj) == IF_DSD_MUX ) // mux { word pTtTemp[3][DAU_MAX_WORD]; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) If_DsdManComputeTruth_rec( p, iFanin, pTtTemp[i], pPermLits, pnSupp ); assert( i == 3 ); Abc_TtMux( pRes, pTtTemp[0], pTtTemp[1], pTtTemp[2], p->nWords ); if ( fCompl ) Abc_TtNot( pRes, p->nWords ); return; } if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) // function { word pFanins[DAU_MAX_VAR][DAU_MAX_WORD]; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) If_DsdManComputeTruth_rec( p, iFanin, pFanins[i], pPermLits, pnSupp ); Dau_DsdTruthCompose_rec( If_DsdObjTruth(p, pObj), pFanins, pRes, pObj->nFans, p->nWords ); if ( fCompl ) Abc_TtNot( pRes, p->nWords ); return; } assert( 0 ); } void If_DsdManComputeTruthPtr( If_DsdMan_t * p, int iDsd, unsigned char * pPermLits, word * pRes ) { int nSupp = 0; If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) ); if ( iDsd == 0 ) Abc_TtConst0( pRes, p->nWords ); else if ( iDsd == 1 ) Abc_TtConst1( pRes, p->nWords ); else if ( pObj->Type == IF_DSD_VAR ) { int iPermLit = pPermLits ? (int)pPermLits[nSupp] : Abc_Var2Lit(nSupp, 0); nSupp++; Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], p->nWords, Abc_LitIsCompl(iDsd) ^ Abc_LitIsCompl(iPermLit) ); } else If_DsdManComputeTruth_rec( p, iDsd, pRes, pPermLits, &nSupp ); assert( nSupp == If_DsdVecLitSuppSize(&p->vObjs, iDsd) ); } word * If_DsdManComputeTruth( If_DsdMan_t * p, int iDsd, unsigned char * pPermLits ) { word * pRes = p->pTtElems[DAU_MAX_VAR]; If_DsdManComputeTruthPtr( p, iDsd, pPermLits, pRes ); return pRes; } /**Function************************************************************* Synopsis [Procedures to propagate the invertor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_DsdManCheckInv_rec( If_DsdMan_t * p, int iLit ) { If_DsdObj_t * pObj; int i, iFanin; pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLit) ); if ( If_DsdObjType(pObj) == IF_DSD_VAR ) return 1; if ( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_PRIME ) return 0; if ( If_DsdObjType(pObj) == IF_DSD_XOR ) { If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) if ( If_DsdManCheckInv_rec(p, iFanin) ) return 1; return 0; } if ( If_DsdObjType(pObj) == IF_DSD_MUX ) return If_DsdManCheckInv_rec(p, pObj->pFans[1]) && If_DsdManCheckInv_rec(p, pObj->pFans[2]); assert( 0 ); return 0; } int If_DsdManPushInv_rec( If_DsdMan_t * p, int iLit, unsigned char * pPerm ) { If_DsdObj_t * pObj; int i, iFanin; pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLit) ); if ( If_DsdObjType(pObj) == IF_DSD_VAR ) pPerm[0] = (unsigned char)Abc_LitNot((int)pPerm[0]); else if ( If_DsdObjType(pObj) == IF_DSD_XOR ) { If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) { if ( If_DsdManCheckInv_rec(p, iFanin) ) { If_DsdManPushInv_rec( p, iFanin, pPerm ); break; } pPerm += If_DsdVecLitSuppSize(&p->vObjs, iFanin); } } else if ( If_DsdObjType(pObj) == IF_DSD_MUX ) { assert( If_DsdManCheckInv_rec(p, pObj->pFans[1]) && If_DsdManCheckInv_rec(p, pObj->pFans[2]) ); pPerm += If_DsdVecLitSuppSize(&p->vObjs, pObj->pFans[0]); If_DsdManPushInv_rec(p, pObj->pFans[1], pPerm); pPerm += If_DsdVecLitSuppSize(&p->vObjs, pObj->pFans[1]); If_DsdManPushInv_rec(p, pObj->pFans[2], pPerm); } else assert( 0 ); return 1; } int If_DsdManPushInv( If_DsdMan_t * p, int iLit, unsigned char * pPerm ) { if ( Abc_LitIsCompl(iLit) && If_DsdManCheckInv_rec(p, iLit) ) return If_DsdManPushInv_rec( p, iLit, pPerm ); return 0; } /**Function************************************************************* Synopsis [Performs DSD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_DsdManComputeFirstArray( If_DsdMan_t * p, int * pLits, int nLits, int * pFirsts ) { int i, nSSize = 0; for ( i = 0; i < nLits; i++ ) { pFirsts[i] = nSSize; nSSize += If_DsdVecLitSuppSize(&p->vObjs, pLits[i]); } return nSSize; } int If_DsdManComputeFirst( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pFirsts ) { return If_DsdManComputeFirstArray( p, (int *)pObj->pFans, pObj->nFans, pFirsts ); } int If_DsdManOperation( If_DsdMan_t * p, int Type, int * pLits, int nLits, unsigned char * pPerm, word * pTruth ) { If_DsdObj_t * pObj, * pFanin; unsigned char pPermNew[DAU_MAX_VAR], * pPermStart = pPerm; int nChildren = 0, pChildren[DAU_MAX_VAR], pBegEnd[DAU_MAX_VAR]; int i, k, j, Id, iFanin, fCompl = 0, nSSize = 0; if ( Type == IF_DSD_AND || Type == IF_DSD_XOR ) { for ( k = 0; k < nLits; k++ ) { if ( Type == IF_DSD_XOR && Abc_LitIsCompl(pLits[k]) ) { pLits[k] = Abc_LitNot(pLits[k]); fCompl ^= 1; } pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) ); if ( Type == If_DsdObjType(pObj) && (Type == IF_DSD_XOR || !Abc_LitIsCompl(pLits[k])) ) { If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) { assert( Type == IF_DSD_AND || !Abc_LitIsCompl(iFanin) ); pChildren[nChildren] = iFanin; pBegEnd[nChildren++] = (nSSize << 16) | (nSSize + If_DsdVecLitSuppSize(&p->vObjs, iFanin)); nSSize += If_DsdVecLitSuppSize(&p->vObjs, iFanin); } } else { pChildren[nChildren] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) ); pBegEnd[nChildren++] = (nSSize << 16) | (nSSize + If_DsdObjSuppSize(pObj)); nSSize += If_DsdObjSuppSize(pObj); } pPermStart += If_DsdObjSuppSize(pObj); } If_DsdObjSort( p, &p->vObjs, pChildren, nChildren, pBegEnd ); // create permutation for ( j = i = 0; i < nChildren; i++ ) for ( k = (pBegEnd[i] >> 16); k < (pBegEnd[i] & 0xFF); k++ ) pPermNew[j++] = pPerm[k]; assert( j == nSSize ); for ( j = 0; j < nSSize; j++ ) pPerm[j] = pPermNew[j]; } else if ( Type == IF_DSD_MUX ) { int RetValue; assert( nLits == 3 ); for ( k = 0; k < nLits; k++ ) { pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) ); pLits[k] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) ); pPermStart += pFanin->nSupp; } RetValue = If_DsdObjCompare( p, &p->vObjs, pLits[1], pLits[2] ); if ( RetValue == 1 || (RetValue == 0 && Abc_LitIsCompl(pLits[0])) ) { int nSupp0 = If_DsdVecLitSuppSize( &p->vObjs, pLits[0] ); int nSupp1 = If_DsdVecLitSuppSize( &p->vObjs, pLits[1] ); int nSupp2 = If_DsdVecLitSuppSize( &p->vObjs, pLits[2] ); pLits[0] = Abc_LitNot(pLits[0]); ABC_SWAP( int, pLits[1], pLits[2] ); for ( j = k = 0; k < nSupp0; k++ ) pPermNew[j++] = pPerm[k]; for ( k = 0; k < nSupp2; k++ ) pPermNew[j++] = pPerm[nSupp0 + nSupp1 + k]; for ( k = 0; k < nSupp1; k++ ) pPermNew[j++] = pPerm[nSupp0 + k]; for ( j = 0; j < nSupp0 + nSupp1 + nSupp2; j++ ) pPerm[j] = pPermNew[j]; } if ( Abc_LitIsCompl(pLits[1]) ) { pLits[1] = Abc_LitNot(pLits[1]); pLits[2] = Abc_LitNot(pLits[2]); fCompl ^= 1; } pPermStart = pPerm; for ( k = 0; k < nLits; k++ ) { pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(pLits[k]) ); pChildren[nChildren++] = Abc_LitNotCond( pLits[k], If_DsdManPushInv(p, pLits[k], pPermStart) ); pPermStart += pFanin->nSupp; } } else if ( Type == IF_DSD_PRIME ) { char pCanonPerm[DAU_MAX_VAR]; int i, uCanonPhase, pFirsts[DAU_MAX_VAR]; uCanonPhase = Abc_TtCanonicize( pTruth, nLits, pCanonPerm ); fCompl = ((uCanonPhase >> nLits) & 1); nSSize = If_DsdManComputeFirstArray( p, pLits, nLits, pFirsts ); for ( j = i = 0; i < nLits; i++ ) { int iLitNew = Abc_LitNotCond( pLits[(int)pCanonPerm[i]], ((uCanonPhase>>i)&1) ); pFanin = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iLitNew) ); pPermStart = pPerm + pFirsts[(int)pCanonPerm[i]]; pChildren[nChildren++] = Abc_LitNotCond( iLitNew, If_DsdManPushInv(p, iLitNew, pPermStart) ); for ( k = 0; k < (int)pFanin->nSupp; k++ ) pPermNew[j++] = pPermStart[k]; } assert( j == nSSize ); for ( j = 0; j < nSSize; j++ ) pPerm[j] = pPermNew[j]; Abc_TtStretch6( pTruth, nLits, p->nVars ); } else assert( 0 ); // create new graph Id = If_DsdObjFindOrAdd( p, Type, pChildren, nChildren, pTruth ); return Abc_Var2Lit( Id, fCompl ); } /**Function************************************************************* Synopsis [Creating DSD network from SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void If_DsdMergeMatches( char * pDsd, int * pMatches ) { int pNested[DAU_MAX_VAR]; int i, nNested = 0; for ( i = 0; pDsd[i]; i++ ) { pMatches[i] = 0; if ( pDsd[i] == '(' || pDsd[i] == '[' || pDsd[i] == '<' || pDsd[i] == '{' ) pNested[nNested++] = i; else if ( pDsd[i] == ')' || pDsd[i] == ']' || pDsd[i] == '>' || pDsd[i] == '}' ) pMatches[pNested[--nNested]] = i; assert( nNested < DAU_MAX_VAR ); } assert( nNested == 0 ); } int If_DsdManAddDsd_rec( char * pStr, char ** p, int * pMatches, If_DsdMan_t * pMan, word * pTruth, unsigned char * pPerm, int * pnSupp ) { unsigned char * pPermStart = pPerm + *pnSupp; int iRes = -1, fCompl = 0; if ( **p == '!' ) { fCompl = 1; (*p)++; } if ( **p >= 'a' && **p <= 'z' ) // var { pPerm[(*pnSupp)++] = Abc_Var2Lit( **p - 'a', fCompl ); return 2; } if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor { int Type, nLits = 0, pLits[DAU_MAX_VAR]; char * q = pStr + pMatches[ *p - pStr ]; if ( **p == '(' ) Type = DAU_DSD_AND; else if ( **p == '[' ) Type = DAU_DSD_XOR; else if ( **p == '<' ) Type = DAU_DSD_MUX; else if ( **p == '{' ) Type = DAU_DSD_PRIME; else assert( 0 ); assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) pLits[nLits++] = If_DsdManAddDsd_rec( pStr, p, pMatches, pMan, pTruth, pPerm, pnSupp ); assert( *p == q ); iRes = If_DsdManOperation( pMan, Type, pLits, nLits, pPermStart, pTruth ); return Abc_LitNotCond( iRes, fCompl ); } if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { word pFunc[DAU_MAX_WORD]; int nLits = 0, pLits[DAU_MAX_VAR]; char * q; int i, nVarsF = Abc_TtReadHex( pFunc, *p ); *p += Abc_TtHexDigitNum( nVarsF ); q = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q == '}' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) pLits[nLits++] = If_DsdManAddDsd_rec( pStr, p, pMatches, pMan, pTruth, pPerm, pnSupp ); assert( i == nVarsF ); assert( *p == q ); iRes = If_DsdManOperation( pMan, DAU_DSD_PRIME, pLits, nLits, pPermStart, pFunc ); return Abc_LitNotCond( iRes, fCompl ); } assert( 0 ); return -1; } int If_DsdManAddDsd( If_DsdMan_t * p, char * pDsd, word * pTruth, unsigned char * pPerm, int * pnSupp ) { int iRes = -1, fCompl = 0; if ( *pDsd == '!' ) pDsd++, fCompl = 1; if ( Dau_DsdIsConst0(pDsd) ) iRes = 0; else if ( Dau_DsdIsConst1(pDsd) ) iRes = 1; else if ( Dau_DsdIsVar(pDsd) ) { pPerm[(*pnSupp)++] = Dau_DsdReadVar(pDsd); iRes = 2; } else { int pMatches[DAU_MAX_STR]; If_DsdMergeMatches( pDsd, pMatches ); iRes = If_DsdManAddDsd_rec( pDsd, &pDsd, pMatches, p, pTruth, pPerm, pnSupp ); } return Abc_LitNotCond( iRes, fCompl ); } /**Function************************************************************* Synopsis [Returns 1 if XY-decomposability holds to this LUT size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // create signature of the support of the node unsigned If_DsdSign_rec( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pnSupp ) { unsigned uSign = 0; int i; If_DsdObj_t * pFanin; if ( If_DsdObjType(pObj) == IF_DSD_VAR ) return (1 << (2*(*pnSupp)++)); If_DsdObjForEachFanin( &p->vObjs, pObj, pFanin, i ) uSign |= If_DsdSign_rec( p, pFanin, pnSupp ); return uSign; } unsigned If_DsdSign( If_DsdMan_t * p, If_DsdObj_t * pObj, int iFan, int iFirst, int fShared ) { If_DsdObj_t * pFanin = If_DsdObjFanin( &p->vObjs, pObj, iFan ); unsigned uSign = If_DsdSign_rec( p, pFanin, &iFirst ); return fShared ? (uSign << 1) | uSign : uSign; } // collect supports of the node void If_DsdManGetSuppSizes( If_DsdMan_t * p, If_DsdObj_t * pObj, int * pSSizes ) { If_DsdObj_t * pFanin; int i; If_DsdObjForEachFanin( &p->vObjs, pObj, pFanin, i ) pSSizes[i] = If_DsdObjSuppSize(pFanin); } // checks if there is a way to package some fanins unsigned If_DsdManCheckAndXor( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose ) { int i[6], LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR]; int nFans = If_DsdObjFaninNum(pObj), pFirsts[DAU_MAX_VAR]; unsigned uRes; assert( pObj->nFans > 2 ); assert( If_DsdObjSuppSize(pObj) > LutSize ); If_DsdManGetSuppSizes( p, pObj, pSSizes ); LimitOut = LutSize - (nSuppAll - pObj->nSupp + 1); assert( LimitOut < LutSize ); for ( i[0] = 0; i[0] < nFans; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ ) { SizeIn = pSSizes[i[0]] + pSSizes[i[1]]; SizeOut = pObj->nSupp - SizeIn; if ( SizeIn > LutSize || SizeOut > LimitOut ) continue; if ( !fDerive ) return ~0; If_DsdManComputeFirst( p, pObj, pFirsts ); uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0); if ( uRes & uMaskNot ) continue; return uRes; } if ( pObj->nFans == 3 ) return 0; for ( i[0] = 0; i[0] < nFans; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nFans; i[2]++ ) { SizeIn = pSSizes[i[0]] + pSSizes[i[1]] + pSSizes[i[2]]; SizeOut = pObj->nSupp - SizeIn; if ( SizeIn > LutSize || SizeOut > LimitOut ) continue; if ( !fDerive ) return ~0; If_DsdManComputeFirst( p, pObj, pFirsts ); uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0) | If_DsdSign(p, pObj, i[2], iFirst + pFirsts[i[2]], 0); if ( uRes & uMaskNot ) continue; return uRes; } if ( pObj->nFans == 4 ) return 0; for ( i[0] = 0; i[0] < nFans; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nFans; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nFans; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nFans; i[3]++ ) { SizeIn = pSSizes[i[0]] + pSSizes[i[1]] + pSSizes[i[2]] + pSSizes[i[3]]; SizeOut = pObj->nSupp - SizeIn; if ( SizeIn > LutSize || SizeOut > LimitOut ) continue; if ( !fDerive ) return ~0; If_DsdManComputeFirst( p, pObj, pFirsts ); uRes = If_DsdSign(p, pObj, i[0], iFirst + pFirsts[i[0]], 0) | If_DsdSign(p, pObj, i[1], iFirst + pFirsts[i[1]], 0) | If_DsdSign(p, pObj, i[2], iFirst + pFirsts[i[2]], 0) | If_DsdSign(p, pObj, i[3], iFirst + pFirsts[i[3]], 0); if ( uRes & uMaskNot ) continue; return uRes; } return 0; } // checks if there is a way to package some fanins unsigned If_DsdManCheckMux( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose ) { int LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR], pFirsts[DAU_MAX_VAR]; unsigned uRes; assert( If_DsdObjFaninNum(pObj) == 3 ); assert( If_DsdObjSuppSize(pObj) > LutSize ); If_DsdManGetSuppSizes( p, pObj, pSSizes ); LimitOut = LutSize - (nSuppAll - If_DsdObjSuppSize(pObj) + 1); assert( LimitOut < LutSize ); // first input SizeIn = pSSizes[0] + pSSizes[1]; SizeOut = pSSizes[0] + pSSizes[2] + 1; if ( SizeIn <= LutSize && SizeOut <= LimitOut ) { if ( !fDerive ) return ~0; If_DsdManComputeFirst( p, pObj, pFirsts ); uRes = If_DsdSign(p, pObj, 0, iFirst + pFirsts[0], 1) | If_DsdSign(p, pObj, 1, iFirst + pFirsts[1], 0); if ( (uRes & uMaskNot) == 0 ) return uRes; } // second input SizeIn = pSSizes[0] + pSSizes[2]; SizeOut = pSSizes[0] + pSSizes[1] + 1; if ( SizeIn <= LutSize && SizeOut <= LimitOut ) { if ( !fDerive ) return ~0; If_DsdManComputeFirst( p, pObj, pFirsts ); uRes = If_DsdSign(p, pObj, 0, iFirst + pFirsts[0], 1) | If_DsdSign(p, pObj, 2, iFirst + pFirsts[2], 0); if ( (uRes & uMaskNot) == 0 ) return uRes; } return 0; } // checks if there is a way to package some fanins unsigned If_DsdManCheckPrime( If_DsdMan_t * p, int iFirst, unsigned uMaskNot, If_DsdObj_t * pObj, int nSuppAll, int LutSize, int fDerive, int fVerbose ) { int i, v, set, LimitOut, SizeIn, SizeOut, pSSizes[DAU_MAX_VAR], pFirsts[DAU_MAX_VAR]; int truthId = If_DsdObjTruthId(p, pObj); int nFans = If_DsdObjFaninNum(pObj); Vec_Int_t * vSets = (Vec_Int_t *)Vec_PtrEntry(p->vTtDecs[pObj->nFans], truthId); if ( fVerbose ) printf( "\n" ); if ( fVerbose ) Dau_DecPrintSets( vSets, nFans ); assert( If_DsdObjFaninNum(pObj) > 2 ); assert( If_DsdObjSuppSize(pObj) > LutSize ); If_DsdManGetSuppSizes( p, pObj, pSSizes ); LimitOut = LutSize - (nSuppAll - If_DsdObjSuppSize(pObj) + 1); assert( LimitOut < LutSize ); Vec_IntForEachEntry( vSets, set, i ) { SizeIn = SizeOut = 0; for ( v = 0; v < nFans; v++ ) { int Value = ((set >> (v << 1)) & 3); if ( Value == 0 ) SizeOut += pSSizes[v]; else if ( Value == 1 ) SizeIn += pSSizes[v]; else if ( Value == 3 ) { SizeIn += pSSizes[v]; SizeOut += pSSizes[v]; } else assert( 0 ); if ( SizeIn > LutSize || SizeOut > LimitOut ) break; } if ( v == nFans ) { unsigned uRes = 0; if ( !fDerive ) return ~0; If_DsdManComputeFirst( p, pObj, pFirsts ); for ( v = 0; v < nFans; v++ ) { int Value = ((set >> (v << 1)) & 3); if ( Value == 0 ) {} else if ( Value == 1 ) uRes |= If_DsdSign(p, pObj, v, iFirst + pFirsts[v], 0); else if ( Value == 3 ) uRes |= If_DsdSign(p, pObj, v, iFirst + pFirsts[v], 1); else assert( 0 ); } if ( uRes & uMaskNot ) continue; return uRes; } } return 0; } unsigned If_DsdManCheckXY_int( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, unsigned uMaskNot, int fVerbose ) { If_DsdObj_t * pObj, * pTemp; int i, Mask, iFirst; unsigned uRes; pObj = If_DsdVecObj( &p->vObjs, Abc_Lit2Var(iDsd) ); if ( fVerbose ) If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 0 ); if ( If_DsdObjSuppSize(pObj) <= LutSize ) { if ( fVerbose ) printf( " Trivial\n" ); return ~0; } If_DsdManCollect( p, pObj->Id, p->vTemp1, p->vTemp2 ); If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i ) if ( If_DsdObjSuppSize(pTemp) <= LutSize && If_DsdObjSuppSize(pObj) - If_DsdObjSuppSize(pTemp) <= LutSize - 1 ) { if ( fVerbose ) printf( " Dec using node " ); if ( fVerbose ) If_DsdManPrintOne( stdout, p, pTemp->Id, NULL, 1 ); iFirst = Vec_IntEntry(p->vTemp2, i); uRes = If_DsdSign_rec(p, pTemp, &iFirst); if ( uRes & uMaskNot ) continue; return uRes; } If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i ) if ( (If_DsdObjType(pTemp) == IF_DSD_AND || If_DsdObjType(pTemp) == IF_DSD_XOR) && If_DsdObjFaninNum(pTemp) > 2 && If_DsdObjSuppSize(pTemp) > LutSize ) { if ( (Mask = If_DsdManCheckAndXor(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) ) { if ( fVerbose ) printf( " " ); if ( fVerbose ) Abc_TtPrintBinary( (word *)&Mask, 4 ); if ( fVerbose ) printf( " Using multi-input AND/XOR node\n" ); return Mask; } } If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i ) if ( If_DsdObjType(pTemp) == IF_DSD_MUX && If_DsdObjSuppSize(pTemp) > LutSize ) { if ( (Mask = If_DsdManCheckMux(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) ) { if ( fVerbose ) printf( " " ); if ( fVerbose ) Abc_TtPrintBinary( (word *)&Mask, 4 ); if ( fVerbose ) printf( " Using multi-input MUX node\n" ); return Mask; } } If_DsdVecForEachObjVec( p->vTemp1, &p->vObjs, pTemp, i ) if ( If_DsdObjType(pTemp) == IF_DSD_PRIME && If_DsdObjSuppSize(pTemp) > LutSize ) { if ( (Mask = If_DsdManCheckPrime(p, Vec_IntEntry(p->vTemp2, i), uMaskNot, pTemp, If_DsdObjSuppSize(pObj), LutSize, fDerive, fVerbose)) ) { if ( fVerbose ) printf( " " ); if ( fVerbose ) Dau_DecPrintSet( Mask, If_DsdObjFaninNum(pTemp), 0 ); if ( fVerbose ) printf( " Using prime node\n" ); return Mask; } } if ( fVerbose ) printf( " UNDEC\n" ); // If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 1 ); return 0; } unsigned If_DsdManCheckXY( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, unsigned uMaskNot, int fHighEffort, int fVerbose ) { unsigned uSet = If_DsdManCheckXY_int( p, iDsd, LutSize, fDerive, uMaskNot, fVerbose ); if ( uSet == 0 && fHighEffort ) { // abctime clk = Abc_Clock(); int nVars = If_DsdVecLitSuppSize( &p->vObjs, iDsd ); word * pRes = If_DsdManComputeTruth( p, iDsd, NULL ); uSet = If_ManSatCheckXYall( p->pSat, LutSize, pRes, nVars, p->vTemp1 ); if ( uSet ) { // If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), NULL, 1 ); // Dau_DecPrintSet( uSet, nVars, 1 ); } // p->timeCheck2 += Abc_Clock() - clk; } return uSet; } /**Function************************************************************* Synopsis [Checks existence of decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned If_DsdManCheckXYZ( If_DsdMan_t * p, int iDsd, int LutSize, int fDerive, int fVerbose ) { return ~0; } /**Function************************************************************* Synopsis [Add the function to the DSD manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_DsdManCompute( If_DsdMan_t * p, word * pTruth, int nLeaves, unsigned char * pPerm, char * pLutStruct ) { word pCopy[DAU_MAX_WORD], * pRes; char pDsd[DAU_MAX_STR]; int iDsd, nSizeNonDec, nSupp = 0; int nWords = Abc_TtWordNum(nLeaves); // abctime clk = 0; assert( nLeaves <= DAU_MAX_VAR ); Abc_TtCopy( pCopy, pTruth, nWords, 0 ); //clk = Abc_Clock(); nSizeNonDec = Dau_DsdDecompose( pCopy, nLeaves, 0, 1, pDsd ); //p->timeDsd += Abc_Clock() - clk; if ( nSizeNonDec > 0 ) Abc_TtStretch6( pCopy, nSizeNonDec, p->nVars ); memset( pPerm, 0xFF, nLeaves ); //clk = Abc_Clock(); iDsd = If_DsdManAddDsd( p, pDsd, pCopy, pPerm, &nSupp ); //p->timeCanon += Abc_Clock() - clk; assert( nSupp == nLeaves ); // verify the result //clk = Abc_Clock(); pRes = If_DsdManComputeTruth( p, iDsd, pPerm ); //p->timeVerify += Abc_Clock() - clk; if ( !Abc_TtEqual(pRes, pTruth, nWords) ) { // If_DsdManPrint( p, NULL ); printf( "\n" ); printf( "Verification failed!\n" ); printf( "%s\n", pDsd ); Dau_DsdPrintFromTruth( pTruth, nLeaves ); Dau_DsdPrintFromTruth( pRes, nLeaves ); If_DsdManPrintOne( stdout, p, Abc_Lit2Var(iDsd), pPerm, 1 ); printf( "\n" ); } If_DsdVecObjIncRef( &p->vObjs, Abc_Lit2Var(iDsd) ); assert( If_DsdVecLitSuppSize(&p->vObjs, iDsd) == nLeaves ); return iDsd; } /**Function************************************************************* Synopsis [Checks existence of decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_DsdManTest() { Vec_Int_t * vSets; word t = 0x5277; t = Abc_Tt6Stretch( t, 4 ); // word t = 0xD9D900D900D900001010001000100000; vSets = Dau_DecFindSets( &t, 6 ); Vec_IntFree( vSets ); } /**Function************************************************************* Synopsis [Compute pin delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutDsdBalancePinDelays_rec( If_DsdMan_t * p, int Id, int * pTimes, word * pRes, int * pnSupp, int nSuppAll, char * pPermLits ) { If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id ); if ( If_DsdObjType(pObj) == IF_DSD_VAR ) { int iCutVar = Abc_Lit2Var(pPermLits[(*pnSupp)++]); *pRes = If_CutPinDelayInit(iCutVar); return pTimes[iCutVar]; } if ( If_DsdObjType(pObj) == IF_DSD_MUX ) { word pFaninRes[3], Res0, Res1; int i, iFanin, Delays[3]; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) Delays[i] = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits ); Res0 = If_CutPinDelayMax( pFaninRes[0], pFaninRes[1], nSuppAll, 1 ); Res1 = If_CutPinDelayMax( pFaninRes[0], pFaninRes[2], nSuppAll, 1 ); *pRes = If_CutPinDelayMax( Res0, Res1, nSuppAll, 1 ); return 2 + Abc_MaxInt(Delays[0], Abc_MaxInt(Delays[1], Delays[2])); } if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) { word pFaninRes[IF_MAX_FUNC_LUTSIZE]; int i, iFanin, Delays[IF_MAX_FUNC_LUTSIZE]; Vec_Int_t * vCover = Vec_WecEntry( p->vIsops[pObj->nFans], If_DsdObjTruthId(p, pObj) ); assert( Vec_IntSize(vCover) > 0 ); If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) Delays[i] = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits ); return If_CutSopBalancePinDelaysInt( vCover, Delays, pFaninRes, nSuppAll, pRes ); } assert( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR ); { word pFaninRes[IF_MAX_FUNC_LUTSIZE]; int i, iFanin, Delay, Result = 0; int fXor = 0;//(If_DsdObjType(pObj) == IF_DSD_XOR); int nCounter = 0, pCounter[IF_MAX_FUNC_LUTSIZE]; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) { Delay = If_CutDsdBalancePinDelays_rec( p, Abc_Lit2Var(iFanin), pTimes, pFaninRes+i, pnSupp, nSuppAll, pPermLits ); Result = If_LogCounterPinDelays( pCounter, &nCounter, pFaninRes, Delay, pFaninRes[i], nSuppAll, fXor ); } assert( nCounter > 0 ); if ( fXor ) Result = If_LogCounterDelayXor( pCounter, nCounter ); // estimation *pRes = If_LogPinDelaysMulti( pFaninRes, nCounter, nSuppAll, fXor ); return Result; } } int If_CutDsdBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm ) { if ( pCut->nLeaves == 0 ) // const return 0; if ( pCut->nLeaves == 1 ) // variable { pPerm[0] = 0; return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; } else { word Result = 0; int i, Delay, nSupp = 0, pTimes[IF_MAX_FUNC_LUTSIZE]; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; Delay = If_CutDsdBalancePinDelays_rec( p->pIfDsdMan, Abc_Lit2Var(If_CutDsdLit(p, pCut)), pTimes, &Result, &nSupp, If_CutLeaveNum(pCut), If_CutDsdPerm(p, pCut) ); assert( nSupp == If_CutLeaveNum(pCut) ); If_CutPinDelayTranslate( Result, If_CutLeaveNum(pCut), pPerm ); return Delay; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutDsdPermLitMax( char * pPermLits, int nVars, int iVar ) { int i; assert( iVar >= 0 && iVar < nVars ); for ( i = 0; i < nVars; i++ ) if ( iVar == Abc_Lit2Var((int)pPermLits[i]) ) return i; assert( 0 ); return -1; } /**Function************************************************************* Synopsis [Evaluate delay using DSD balancing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutDsdBalanceEval_rec( If_DsdMan_t * p, int Id, int * pTimes, int * pnSupp, Vec_Int_t * vAig, int * piLit, int nSuppAll, int * pArea, char * pPermLits ) { If_DsdObj_t * pObj = If_DsdVecObj( &p->vObjs, Id ); if ( If_DsdObjType(pObj) == IF_DSD_VAR ) { int iCutVar = Abc_Lit2Var( pPermLits[*pnSupp] ); if ( vAig ) *piLit = Abc_Var2Lit( iCutVar, Abc_LitIsCompl(pPermLits[*pnSupp]) ); (*pnSupp)++; return pTimes[iCutVar]; } if ( If_DsdObjType(pObj) == IF_DSD_MUX ) { int i, iFanin, Delays[3], pFaninLits[3]; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) { Delays[i] = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits ); if ( Delays[i] == -1 ) return -1; if ( vAig ) pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) ); } if ( vAig ) *piLit = If_LogCreateMux( vAig, pFaninLits[0], pFaninLits[1], pFaninLits[2], nSuppAll ); else *pArea += 3; return 2 + Abc_MaxInt(Delays[0], Abc_MaxInt(Delays[1], Delays[2])); } if ( If_DsdObjType(pObj) == IF_DSD_PRIME ) { int i, iFanin, Delays[IF_MAX_FUNC_LUTSIZE], pFaninLits[IF_MAX_FUNC_LUTSIZE]; Vec_Int_t * vCover = Vec_WecEntry( p->vIsops[pObj->nFans], If_DsdObjTruthId(p, pObj) ); if ( Vec_IntSize(vCover) == 0 ) return -1; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) { Delays[i] = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits ); if ( Delays[i] == -1 ) return -1; if ( vAig ) pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) ); } return If_CutSopBalanceEvalInt( vCover, Delays, pFaninLits, vAig, piLit, nSuppAll, pArea ); } assert( If_DsdObjType(pObj) == IF_DSD_AND || If_DsdObjType(pObj) == IF_DSD_XOR ); { int i, iFanin, Delay, Result = 0; int fXor = 0;//(If_DsdObjType(pObj) == IF_DSD_XOR); int fXorFunc = (If_DsdObjType(pObj) == IF_DSD_XOR); int nCounter = 0, pCounter[IF_MAX_FUNC_LUTSIZE], pFaninLits[IF_MAX_FUNC_LUTSIZE]; If_DsdObjForEachFaninLit( &p->vObjs, pObj, iFanin, i ) { Delay = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iFanin), pTimes, pnSupp, vAig, pFaninLits+i, nSuppAll, pArea, pPermLits ); if ( Delay == -1 ) return -1; if ( vAig ) pFaninLits[i] = Abc_LitNotCond( pFaninLits[i], Abc_LitIsCompl(iFanin) ); Result = If_LogCounterAddAig( pCounter, &nCounter, pFaninLits, Delay, vAig ? pFaninLits[i] : -1, vAig, nSuppAll, fXor, fXorFunc ); } assert( nCounter > 0 ); if ( fXor ) Result = If_LogCounterDelayXor( pCounter, nCounter ); // estimation if ( vAig ) *piLit = If_LogCreateAndXorMulti( vAig, pFaninLits, nCounter, nSuppAll, fXorFunc ); else *pArea += (pObj->nFans - 1) * (1 + 2 * fXor); return Result; } } int If_CutDsdBalanceEvalInt( If_DsdMan_t * p, int iDsd, int * pTimes, Vec_Int_t * vAig, int * pArea, char * pPermLits ) { int nSupp = 0, iLit = 0; int nSuppAll = If_DsdVecLitSuppSize( &p->vObjs, iDsd ); int Res = If_CutDsdBalanceEval_rec( p, Abc_Lit2Var(iDsd), pTimes, &nSupp, vAig, &iLit, nSuppAll, pArea, pPermLits ); if ( Res == -1 ) return -1; assert( nSupp == nSuppAll ); assert( vAig == NULL || Abc_Lit2Var(iLit) == nSupp + Abc_Lit2Var(Vec_IntSize(vAig)) - 1 ); if ( vAig ) Vec_IntPush( vAig, Abc_LitIsCompl(iLit) ^ Abc_LitIsCompl(iDsd) ); assert( vAig == NULL || (Vec_IntSize(vAig) & 1) ); return Res; } int If_CutDsdBalanceEval( If_Man_t * p, If_Cut_t * pCut, Vec_Int_t * vAig ) { int fUseCofs = 0; pCut->fUser = 1; if ( vAig ) Vec_IntClear( vAig ); if ( pCut->nLeaves == 0 ) // const { assert( Abc_Lit2Var(If_CutDsdLit(p, pCut)) == 0 ); if ( vAig ) Vec_IntPush( vAig, Abc_LitIsCompl(If_CutDsdLit(p, pCut)) ); pCut->Cost = 0; return 0; } if ( pCut->nLeaves == 1 ) // variable { assert( Abc_Lit2Var(If_CutDsdLit(p, pCut)) == 1 ); if ( vAig ) Vec_IntPush( vAig, 0 ); if ( vAig ) Vec_IntPush( vAig, Abc_LitIsCompl(If_CutDsdLit(p, pCut)) ); pCut->Cost = 0; return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay; } else { int fVerbose = 0; int i, pTimes[IF_MAX_FUNC_LUTSIZE]; int Delay, Area = 0; char * pPermLits = If_CutDsdPerm(p, pCut); for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) pTimes[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; Delay = If_CutDsdBalanceEvalInt( p->pIfDsdMan, Abc_LitNotCond(If_CutDsdLit(p, pCut), pCut->fCompl), pTimes, vAig, &Area, If_CutDsdPerm(p, pCut) ); pCut->Cost = Area; // try cofactoring if ( fUseCofs ) { // count how many times the max one appears int iMax = 0, nCountMax = 1; for ( i = 1; i < If_CutLeaveNum(pCut); i++ ) if ( pTimes[i] > pTimes[iMax] ) iMax = i, nCountMax = 1; else if ( pTimes[i] == pTimes[iMax] ) nCountMax++; // decide when to try the decomposition if ( nCountMax == 1 && pTimes[iMax] + 2 < Delay && If_DsdManCheckNonTriv( p->pIfDsdMan, Abc_Lit2Var(If_CutDsdLit(p, pCut)), If_CutLeaveNum(pCut), If_CutDsdPermLitMax(pPermLits, If_CutLeaveNum(pCut), iMax)) ) { // fVerbose = 1; Delay = pTimes[iMax] + 2; } } // report the result if ( fVerbose ) { /* int Max = 0, Two = 0; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) Max = Abc_MaxInt( Max, pTimes[i] ); for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) if ( pTimes[i] != Max ) Two = Abc_MaxInt( Two, pTimes[i] ); if ( Two + 2 < Max && Max + 3 < Delay ) */ { for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) printf( "%3d ", pTimes[Abc_Lit2Var(pPermLits[i])] ); for ( ; i < p->pPars->nLutSize; i++ ) printf( " " ); printf( "-> %3d ", Delay ); If_DsdManPrintOne( stdout, p->pIfDsdMan, Abc_Lit2Var(If_CutDsdLit(p, pCut)), NULL, 0 ); printf( "\n" ); } } return Delay; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_DsdManTune( If_DsdMan_t * p, int LutSize, int fFast, int fAdd, int fSpec, int fVerbose ) { ProgressBar * pProgress = NULL; sat_solver * pSat = NULL; If_DsdObj_t * pObj; Vec_Int_t * vLits; int i, Value, nVars; word * pTruth; if ( !fAdd || !LutSize ) If_DsdVecForEachObj( &p->vObjs, pObj, i ) pObj->fMark = 0; if ( LutSize == 0 ) return; vLits = Vec_IntAlloc( 1000 ); pSat = (sat_solver *)If_ManSatBuildXY( LutSize ); pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) ); If_DsdVecForEachObj( &p->vObjs, pObj, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); nVars = If_DsdObjSuppSize(pObj); if ( nVars <= LutSize ) continue; if ( fAdd && !pObj->fMark ) continue; pObj->fMark = 0; if ( If_DsdManCheckXY(p, Abc_Var2Lit(i, 0), LutSize, 0, 0, 0, 0) ) continue; if ( fFast ) Value = 0; else { pTruth = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL ); Value = If_ManSatCheckXYall( pSat, LutSize, pTruth, nVars, vLits ); } if ( Value ) continue; If_DsdVecObjSetMark( &p->vObjs, i ); } Extra_ProgressBarStop( pProgress ); If_ManSatUnbuild( pSat ); Vec_IntFree( vLits ); if ( fVerbose ) If_DsdManPrintDistrib( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Id_DsdManTuneStr1( If_DsdMan_t * p, char * pStruct, int nConfls, int fVerbose ) { int fVeryVerbose = 0; ProgressBar * pProgress = NULL; If_DsdObj_t * pObj; word * pTruth, * pConfig; int i, nVars, Value, LutSize; abctime clk = Abc_Clock(); // parse the structure Ifn_Ntk_t * pNtk = Ifn_NtkParse( pStruct ); if ( pNtk == NULL ) return; if ( If_DsdManVarNum(p) > Ifn_NtkInputNum(pNtk) ) { printf( "The support of DSD manager (%d) exceeds the support of the structure (%d).\n", If_DsdManVarNum(p), Ifn_NtkInputNum(pNtk) ); ABC_FREE( pNtk ); return; } ABC_FREE( p->pCellStr ); p->pCellStr = Abc_UtilStrsav( pStruct ); if ( If_DsdManVarNum(p) < Ifn_NtkInputNum(pNtk) ) printf( "Warning: The support of DSD manager (%d) is less than the support of the structure (%d).\n", If_DsdManVarNum(p), Ifn_NtkInputNum(pNtk) ); LutSize = Ifn_NtkLutSizeMax(pNtk); p->nTtBits = Ifn_NtkTtBits( pStruct ); p->nConfigWords = 1 + Abc_Bit6WordNum( p->nTtBits ); // print if ( fVerbose ) { printf( "Considering programmable cell: " ); Ifn_NtkPrint( pNtk ); printf( "Largest LUT size = %d.\n", LutSize ); } if ( p->nObjsPrev > 0 ) printf( "Starting the tuning process from object %d (out of %d).\n", p->nObjsPrev, Vec_PtrSize(&p->vObjs) ); // clean the attributes If_DsdVecForEachObj( &p->vObjs, pObj, i ) if ( i >= p->nObjsPrev ) pObj->fMark = 0; if ( p->vConfigs == NULL ) p->vConfigs = Vec_WrdStart( p->nConfigWords * Vec_PtrSize(&p->vObjs) ); else Vec_WrdFillExtra( p->vConfigs, p->nConfigWords * Vec_PtrSize(&p->vObjs), 0 ); pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) ); If_DsdVecForEachObjStart( &p->vObjs, pObj, i, p->nObjsPrev ) { if ( (i & 0xFF) == 0 ) Extra_ProgressBarUpdate( pProgress, i, NULL ); nVars = If_DsdObjSuppSize(pObj); //if ( nVars <= LutSize ) // continue; pTruth = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL ); if ( fVeryVerbose ) Dau_DsdPrintFromTruth( pTruth, nVars ); if ( fVerbose ) printf( "%6d : %2d ", i, nVars ); pConfig = Vec_WrdEntryP( p->vConfigs, p->nConfigWords * i ); Value = Ifn_NtkMatch( pNtk, pTruth, nVars, nConfls, fVerbose, fVeryVerbose, pConfig ); if ( fVeryVerbose ) printf( "\n" ); if ( Value == 0 ) { If_DsdVecObjSetMark( &p->vObjs, i ); memset( pConfig, 0, sizeof(word) * p->nConfigWords ); } } p->nObjsPrev = 0; p->LutSize = 0; Extra_ProgressBarStop( pProgress ); printf( "Finished matching %d functions. ", Vec_PtrSize(&p->vObjs) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fVeryVerbose ) If_DsdManPrintDistrib( p ); ABC_FREE( pNtk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #ifndef ABC_USE_PTHREADS void Id_DsdManTuneStr( If_DsdMan_t * p, char * pStruct, int nConfls, int nProcs, int fVerbose ) { Id_DsdManTuneStr1( p, pStruct, nConfls, fVerbose ); } #else // pthreads are used #define PAR_THR_MAX 100 typedef struct Ifn_ThData_t_ { Ifn_Ntk_t * pNtk; // network word pTruth[DAU_MAX_WORD]; word pConfig[10]; // configuration data int nConfigWords;// configuration data word count int nVars; // support int Id; // object int nConfls; // conflicts int Result; // result int Status; // state abctime clkUsed; // total runtime } Ifn_ThData_t; void * Ifn_WorkerThread( void * pArg ) { Ifn_ThData_t * pThData = (Ifn_ThData_t *)pArg; 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; } clk = Abc_Clock(); memset( pThData->pConfig, 0, sizeof(word) * pThData->nConfigWords ); pThData->Result = Ifn_NtkMatch( pThData->pNtk, pThData->pTruth, pThData->nVars, pThData->nConfls, 0, 0, pThData->pConfig ); pThData->clkUsed += Abc_Clock() - clk; pThData->Status = 0; // printf( "Finished object %d\n", pThData->Id ); } assert( 0 ); return NULL; } void Id_DsdManTuneStr( If_DsdMan_t * p, char * pStruct, int nConfls, int nProcs, int fVerbose ) { int fVeryVerbose = 0; ProgressBar * pProgress = NULL; int i, k, nVars, LutSize; abctime clk = Abc_Clock(); Ifn_Ntk_t * pNtk; If_DsdObj_t * pObj; if ( nProcs == 1 ) { Id_DsdManTuneStr1( p, pStruct, nConfls, fVerbose ); return; } if ( nProcs > PAR_THR_MAX ) { printf( "The number of processes (%d) exceeds the precompiled limit (%d).\n", nProcs, PAR_THR_MAX ); return; } // parse the structure pNtk = Ifn_NtkParse( pStruct ); if ( pNtk == NULL ) return; if ( If_DsdManVarNum(p) > Ifn_NtkInputNum(pNtk) ) { printf( "The support of DSD manager (%d) exceeds the support of the structure (%d).\n", If_DsdManVarNum(p), Ifn_NtkInputNum(pNtk) ); ABC_FREE( pNtk ); return; } ABC_FREE( p->pCellStr ); p->pCellStr = Abc_UtilStrsav( pStruct ); if ( If_DsdManVarNum(p) < Ifn_NtkInputNum(pNtk) ) printf( "Warning: The support of DSD manager (%d) is less than the support of the structure (%d).\n", If_DsdManVarNum(p), Ifn_NtkInputNum(pNtk) ); // check the largest LUT LutSize = Ifn_NtkLutSizeMax(pNtk); p->nTtBits = Ifn_NtkTtBits( pStruct ); p->nConfigWords = 1 + Abc_Bit6WordNum( p->nTtBits ); assert( p->nConfigWords <= 10 ); if ( fVerbose ) { printf( "Considering programmable cell: " ); Ifn_NtkPrint( pNtk ); printf( "Largest LUT size = %d.\n", LutSize ); } ABC_FREE( pNtk ); if ( p->nObjsPrev > 0 ) printf( "Starting the tuning process from object %d (out of %d).\n", p->nObjsPrev, Vec_PtrSize(&p->vObjs) ); // clean the attributes If_DsdVecForEachObj( &p->vObjs, pObj, i ) if ( i >= p->nObjsPrev ) pObj->fMark = 0; if ( p->vConfigs == NULL ) p->vConfigs = Vec_WrdStart( p->nConfigWords * Vec_PtrSize(&p->vObjs) ); else Vec_WrdFillExtra( p->vConfigs, p->nConfigWords * Vec_PtrSize(&p->vObjs), 0 ); pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) ); // perform concurrent solving { pthread_t WorkerThread[PAR_THR_MAX]; Ifn_ThData_t ThData[PAR_THR_MAX]; abctime clk, clkUsed = 0; int status, fRunning = 1, iCurrentObj = p->nObjsPrev; // start the threads for ( i = 0; i < nProcs; i++ ) { ThData[i].pNtk = Ifn_NtkParse( pStruct ); ThData[i].nVars = -1; // support ThData[i].Id = -1; // object ThData[i].nConfls = nConfls; // conflicts ThData[i].Result = -1; // result ThData[i].Status = 0; // state ThData[i].clkUsed = 0; // total runtime ThData[i].nConfigWords = p->nConfigWords; status = pthread_create( WorkerThread + i, NULL, Ifn_WorkerThread, (void *)(ThData + i) ); assert( status == 0 ); } // run the threads while ( fRunning || iCurrentObj < Vec_PtrSize(&p->vObjs) ) { for ( i = 0; i < nProcs; i++ ) { if ( ThData[i].Status ) continue; assert( ThData[i].Status == 0 ); if ( ThData[i].Id >= 0 ) { //printf( "Closing obj %d with Thread %d:\n", ThData[i].Id, i ); assert( ThData[i].Result == 0 || ThData[i].Result == 1 ); if ( ThData[i].Result == 0 ) If_DsdVecObjSetMark( &p->vObjs, ThData[i].Id ); else { word * pTtWords = Vec_WrdEntryP( p->vConfigs, p->nConfigWords * ThData[i].Id ); memcpy( pTtWords, ThData[i].pConfig, sizeof(word) * p->nConfigWords ); } ThData[i].Id = -1; ThData[i].Result = -1; } for ( k = iCurrentObj; k < Vec_PtrSize(&p->vObjs); k++ ) { if ( (k & 0xFF) == 0 ) Extra_ProgressBarUpdate( pProgress, k, NULL ); pObj = If_DsdVecObj( &p->vObjs, k ); nVars = If_DsdObjSuppSize(pObj); //if ( nVars <= LutSize ) // continue; clk = Abc_Clock(); If_DsdManComputeTruthPtr( p, Abc_Var2Lit(k, 0), NULL, ThData[i].pTruth ); clkUsed += Abc_Clock() - clk; ThData[i].nVars = nVars; ThData[i].Id = k; ThData[i].Result = -1; ThData[i].Status = 1; //printf( "Scheduling %d for Thread %d\n", ThData[i].Id, i ); iCurrentObj = k+1; break; } } 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 ); } // stop the threads for ( i = 0; i < nProcs; i++ ) { assert( ThData[i].Status == 0 ); ThData[i].Id = -1; ThData[i].Status = 1; ABC_FREE( ThData[i].pNtk ); } if ( fVerbose ) { printf( "Main : " ); Abc_PrintTime( 1, "Time", clkUsed ); for ( i = 0; i < nProcs; i++ ) { printf( "Thread %d : ", i ); Abc_PrintTime( 1, "Time", ThData[i].clkUsed ); } } } p->nObjsPrev = 0; p->LutSize = 0; Extra_ProgressBarStop( pProgress ); printf( "Finished matching %d functions. ", Vec_PtrSize(&p->vObjs) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fVeryVerbose ) If_DsdManPrintDistrib( p ); } #endif // pthreads are used /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #ifdef ABC_USE_CUDD void Id_DsdManTuneThresh( If_DsdMan_t * p, int fUnate, int fThresh, int fThreshHeuristic, int fVerbose ) { extern int Extra_ThreshCheck( word * t, int nVars, int * pW ); extern int Extra_ThreshHeuristic( word * t, int nVars, int * pW ); int fVeryVerbose = 0; int pW[16]; ProgressBar * pProgress = NULL; If_DsdObj_t * pObj; word * pTruth, Perm; int i, nVars, Value; abctime clk = Abc_Clock(); assert( fUnate + fThresh + fThreshHeuristic <= 1 ); if ( p->nObjsPrev > 0 ) printf( "Starting the tuning process from object %d (out of %d).\n", p->nObjsPrev, Vec_PtrSize(&p->vObjs) ); // clean the attributes If_DsdVecForEachObj( &p->vObjs, pObj, i ) if ( i >= p->nObjsPrev ) pObj->fMark = 0; if ( p->vConfigs == NULL ) p->vConfigs = Vec_WrdStart( Vec_PtrSize(&p->vObjs) ); else Vec_WrdFillExtra( p->vConfigs, Vec_PtrSize(&p->vObjs), 0 ); pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(&p->vObjs) ); If_DsdVecForEachObjStart( &p->vObjs, pObj, i, p->nObjsPrev ) { if ( (i & 0xFF) == 0 ) Extra_ProgressBarUpdate( pProgress, i, NULL ); nVars = If_DsdObjSuppSize(pObj); if ( nVars > 8 ) continue; pTruth = If_DsdManComputeTruth( p, Abc_Var2Lit(i, 0), NULL ); if ( fVeryVerbose ) Dau_DsdPrintFromTruth( pTruth, nVars ); if ( fVerbose ) printf( "%6d : %2d ", i, nVars ); if ( fUnate ) Value = Abc_TtIsUnate( pTruth, nVars ); else if ( fThresh ) Value = Extra_ThreshCheck( pTruth, nVars, pW ); else if ( fThreshHeuristic ) Value = Extra_ThreshHeuristic( pTruth, nVars, pW ); else Value = 0; Perm = 0; if ( fVeryVerbose ) printf( "\n" ); if ( Value ) If_DsdVecObjSetMark( &p->vObjs, i ); else Vec_WrdWriteEntry( p->vConfigs, i, Perm ); } p->nObjsPrev = 0; p->LutSize = 0; Extra_ProgressBarStop( pProgress ); printf( "Finished matching %d functions. ", Vec_PtrSize(&p->vObjs) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fVeryVerbose ) If_DsdManPrintDistrib( p ); } #endif // ABC_USE_CUDD are used //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifLibBox.c000066400000000000000000000264561300674244400230660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifLibBox.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Box library.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifLibBox.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "misc/extra/extra.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define If_LibBoxForEachBox( p, pBox, i ) \ Vec_PtrForEachEntry( If_Box_t *, p->vBoxes, pBox, i ) if ( pBox == NULL ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Box_t * If_BoxStart( char * pName, int Id, int nPis, int nPos, int fSeq, int fBlack, int fOuter ) { If_Box_t * p; p = ABC_CALLOC( If_Box_t, 1 ); p->pName = pName; // consumes memory p->Id = Id; p->fSeq = (char)fSeq; p->fBlack = (char)fBlack; p->fOuter = (char)fOuter; p->nPis = nPis; p->nPos = nPos; p->pDelays = ABC_CALLOC( int, nPis * nPos ); return p; } If_Box_t * If_BoxDup( If_Box_t * p ) { If_Box_t * pNew = NULL; return pNew; } void If_BoxFree( If_Box_t * p ) { ABC_FREE( p->pDelays ); ABC_FREE( p->pName ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_LibBox_t * If_LibBoxStart() { If_LibBox_t * p; p = ABC_CALLOC( If_LibBox_t, 1 ); p->vBoxes = Vec_PtrAlloc( 100 ); return p; } If_LibBox_t * If_LibBoxDup( If_Box_t * p ) { If_LibBox_t * pNew = NULL; return pNew; } void If_LibBoxFree( If_LibBox_t * p ) { If_Box_t * pBox; int i; if ( p == NULL ) return; If_LibBoxForEachBox( p, pBox, i ) If_BoxFree( pBox ); Vec_PtrFree( p->vBoxes ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Box_t * If_LibBoxReadBox( If_LibBox_t * p, int Id ) { return (If_Box_t *)Vec_PtrEntry( p->vBoxes, Id ); } If_Box_t * If_LibBoxFindBox( If_LibBox_t * p, char * pName ) { If_Box_t * pBox; int i; if ( p == NULL ) return NULL; If_LibBoxForEachBox( p, pBox, i ) if ( !strcmp(pBox->pName, pName) ) return pBox; return NULL; } void If_LibBoxAdd( If_LibBox_t * p, If_Box_t * pBox ) { if ( pBox->Id >= Vec_PtrSize(p->vBoxes) ) Vec_PtrFillExtra( p->vBoxes, 2 * pBox->Id + 10, NULL ); assert( Vec_PtrEntry( p->vBoxes, pBox->Id ) == NULL ); Vec_PtrWriteEntry( p->vBoxes, pBox->Id, pBox ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_LibBox_t * If_LibBoxRead2( char * pFileName ) { int nSize = 100000; char * pBuffer; FILE * pFile; If_LibBox_t * p = NULL; If_Box_t * pBox = NULL; char * pToken, * pName; int fSeq, fBlack, fOuter; int i, Id, nPis, nPos; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return NULL; } // read lines nPis = nPos = 0; pBuffer = ABC_ALLOC( char, nSize ); while ( fgets( pBuffer, nSize, pFile ) ) { pToken = strtok( pBuffer, " \n\r\t" ); if ( pToken == NULL ) continue; if ( pToken[0] == '.' ) { if ( !strcmp(pToken, ".box") ) { // save ID pToken = strtok( NULL, " \n\r\t" ); Id = atoi( pToken ); // save name pToken = strtok( NULL, " \n\r\t" ); pName = Abc_UtilStrsav(pToken); // save PIs pToken = strtok( NULL, " \n\r\t" ); nPis = atoi( pToken ); // save POs pToken = strtok( NULL, " \n\r\t" ); nPos = atoi( pToken ); // save attributes fSeq = fBlack = fOuter = 0; pToken = strtok( NULL, " \n\r\t" ); while ( pToken ) { if ( !strcmp(pToken, "seq") ) fSeq = 1; else if ( !strcmp(pToken, "black") ) fBlack = 1; else if ( !strcmp(pToken, "outer") ) fOuter = 1; else assert( !strcmp(pToken, "comb") || !strcmp(pToken, "white") || !strcmp(pToken, "inner") ); pToken = strtok( NULL, " \n\r\t" ); } // create library if ( p == NULL ) p = If_LibBoxStart(); // create box pBox = If_BoxStart( pName, Id, nPis, nPos, fSeq, fBlack, fOuter ); If_LibBoxAdd( p, pBox ); } continue; } // read the table assert( nPis > 0 && nPos > 0 ); for ( i = 0; i < nPis * nPos; i++ ) { while ( pToken == NULL ) { if ( fgets( pBuffer, nSize, pFile ) == NULL ) { printf( "The table does not have enough entries.\n" ); fflush(stdout); assert( 0 ); } pToken = strtok( pBuffer, " \n\r\t" ); } pBox->pDelays[i] = (pToken[0] == '-') ? -1 : atoi(pToken); pToken = strtok( NULL, " \n\r\t" ); } pBox = NULL; } ABC_FREE( pBuffer ); fclose( pFile ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * If_LibBoxGetToken( FILE * pFile ) { static char pBuffer[1000]; int c; char * pTemp = pBuffer; while ( (c = fgetc(pFile)) != EOF ) { if ( c == '#' ) { while ( (c = fgetc(pFile)) != EOF ) if ( c == '\n' ) break; } if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' ) { if ( pTemp > pBuffer ) break; continue; } *pTemp++ = c; } *pTemp = 0; return pTemp > pBuffer ? pBuffer : NULL; } If_LibBox_t * If_LibBoxRead( char * pFileName ) { FILE * pFile; If_LibBox_t * p; If_Box_t * pBox; char * pToken, * pName; int i, Id, fBlack, nPis, nPos; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return NULL; } // get the library name pToken = If_LibBoxGetToken( pFile ); if ( pToken == NULL ) { fclose( pFile ); printf( "Cannot read library name from file \"%s\".\n", pFileName ); return NULL; } if ( pToken[0] == '.' ) { fclose( pFile ); printf( "Wrong box format. Please try \"read_box -e\".\n" ); return NULL; } // create library p = If_LibBoxStart(); while ( pToken ) { // save name pName = Abc_UtilStrsav(pToken); // save ID pToken = If_LibBoxGetToken( pFile ); Id = atoi( pToken ); // save white/black pToken = If_LibBoxGetToken( pFile ); fBlack = !atoi( pToken ); // save PIs pToken = If_LibBoxGetToken( pFile ); nPis = atoi( pToken ); // save POs pToken = If_LibBoxGetToken( pFile ); nPos = atoi( pToken ); // create box pBox = If_BoxStart( pName, Id, nPis, nPos, 0, fBlack, 0 ); If_LibBoxAdd( p, pBox ); // read the table for ( i = 0; i < nPis * nPos; i++ ) { pToken = If_LibBoxGetToken( pFile ); pBox->pDelays[i] = (pToken[0] == '-') ? -ABC_INFINITY : atoi(pToken); } // extract next name pToken = If_LibBoxGetToken( pFile ); } fclose( pFile ); return p; } void If_LibBoxPrint( FILE * pFile, If_LibBox_t * p ) { If_Box_t * pBox; int i, j, k; fprintf( pFile, "# Box library written by ABC on %s.\n", Extra_TimeStamp() ); fprintf( pFile, "# \n" ); If_LibBoxForEachBox( p, pBox, i ) { fprintf( pFile, "%s %d %d %d %d\n", pBox->pName, pBox->Id, !pBox->fBlack, pBox->nPis, pBox->nPos ); for ( j = 0; j < pBox->nPos; j++, printf("\n") ) for ( k = 0; k < pBox->nPis; k++ ) if ( pBox->pDelays[j * pBox->nPis + k] == -ABC_INFINITY ) fprintf( pFile, " - " ); else fprintf( pFile, "%5d ", pBox->pDelays[j * pBox->nPis + k] ); } } void If_LibBoxWrite( char * pFileName, If_LibBox_t * p ) { FILE * pFile; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return; } If_LibBoxPrint( pFile, p ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_LibBoxLoad( char * pFileName ) { FILE * pFile; If_LibBox_t * pLib; char * pFileNameOther; // check if library can be read pFileNameOther = Extra_FileNameGenericAppend( pFileName, ".cdl" ); pFile = fopen( pFileNameOther, "r" ); if ( pFile == NULL ) return 0; fclose( pFile ); // read library pLib = If_LibBoxRead2( pFileNameOther ); // replace the current library If_LibBoxFree( (If_LibBox_t *)Abc_FrameReadLibBox() ); Abc_FrameSetLibBox( pLib ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifLibLut.c000066400000000000000000000236171300674244400230760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifLibLut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [LUT library.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifLibLut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline char * If_UtilStrsav( char *s ) { return !s ? s : strcpy(ABC_ALLOC(char, strlen(s)+1), s); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the description of LUTs from the LUT library file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_LibLut_t * If_LibLutRead( char * FileName ) { char pBuffer[1000], * pToken; If_LibLut_t * p; FILE * pFile; int i, k; pFile = fopen( FileName, "r" ); if ( pFile == NULL ) { Abc_Print( -1, "Cannot open LUT library file \"%s\".\n", FileName ); return NULL; } p = ABC_ALLOC( If_LibLut_t, 1 ); memset( p, 0, sizeof(If_LibLut_t) ); p->pName = If_UtilStrsav( FileName ); i = 1; while ( fgets( pBuffer, 1000, pFile ) != NULL ) { pToken = strtok( pBuffer, " \t\n" ); if ( pToken == NULL ) continue; if ( pToken[0] == '#' ) continue; if ( i != atoi(pToken) ) { Abc_Print( 1, "Error in the LUT library file \"%s\".\n", FileName ); ABC_FREE( p->pName ); ABC_FREE( p ); return NULL; } // read area pToken = strtok( NULL, " \t\n" ); p->pLutAreas[i] = (float)atof(pToken); // read delays k = 0; while ( (pToken = strtok( NULL, " \t\n" )) ) p->pLutDelays[i][k++] = (float)atof(pToken); // check for out-of-bound if ( k > i ) { ABC_FREE( p->pName ); ABC_FREE( p ); Abc_Print( 1, "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i ); return NULL; } // check if var delays are specified if ( k > 1 ) p->fVarPinDelays = 1; if ( i == IF_MAX_LUTSIZE ) { ABC_FREE( p->pName ); ABC_FREE( p ); Abc_Print( 1, "Skipping LUTs of size more than %d.\n", i ); return NULL; } i++; } p->LutMax = i-1; // check the library if ( p->fVarPinDelays ) { for ( i = 1; i <= p->LutMax; i++ ) for ( k = 0; k < i; k++ ) { if ( p->pLutDelays[i][k] <= 0.0 ) Abc_Print( 0, "Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", k, i, p->pLutDelays[i][k] ); if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] ) Abc_Print( 0, "Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n", k-1, i, p->pLutDelays[i][k-1], k, i, p->pLutDelays[i][k] ); } } else { for ( i = 1; i <= p->LutMax; i++ ) { if ( p->pLutDelays[i][0] <= 0.0 ) Abc_Print( 0, "LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", i, p->pLutDelays[i][0] ); } } return p; } /**Function************************************************************* Synopsis [Duplicates the LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_LibLut_t * If_LibLutDup( If_LibLut_t * p ) { If_LibLut_t * pNew; pNew = ABC_ALLOC( If_LibLut_t, 1 ); *pNew = *p; pNew->pName = If_UtilStrsav( pNew->pName ); return pNew; } /**Function************************************************************* Synopsis [Frees the LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_LibLutFree( If_LibLut_t * pLutLib ) { if ( pLutLib == NULL ) return; ABC_FREE( pLutLib->pName ); ABC_FREE( pLutLib ); } /**Function************************************************************* Synopsis [Prints the LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_LibLutPrint( If_LibLut_t * pLutLib ) { int i, k; Abc_Print( 1, "# The area/delay of k-variable LUTs:\n" ); Abc_Print( 1, "# k area delay\n" ); if ( pLutLib->fVarPinDelays ) { for ( i = 1; i <= pLutLib->LutMax; i++ ) { Abc_Print( 1, "%d %7.2f ", i, pLutLib->pLutAreas[i] ); for ( k = 0; k < i; k++ ) Abc_Print( 1, " %7.2f", pLutLib->pLutDelays[i][k] ); Abc_Print( 1, "\n" ); } } else for ( i = 1; i <= pLutLib->LutMax; i++ ) Abc_Print( 1, "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i][0] ); } /**Function************************************************************* Synopsis [Returns 1 if the delays are discrete.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_LibLutDelaysAreDiscrete( If_LibLut_t * pLutLib ) { float Delay; int i; for ( i = 1; i <= pLutLib->LutMax; i++ ) { Delay = pLutLib->pLutDelays[i][0]; if ( ((float)((int)Delay)) != Delay ) return 0; } return 1; } /**Function************************************************************* Synopsis [Returns 1 if the delays are discrete.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_LibLutDelaysAreDifferent( If_LibLut_t * pLutLib ) { int i, k; float Delay = pLutLib->pLutDelays[1][0]; if ( pLutLib->fVarPinDelays ) { for ( i = 2; i <= pLutLib->LutMax; i++ ) for ( k = 0; k < i; k++ ) if ( pLutLib->pLutDelays[i][k] != Delay ) return 1; } else { for ( i = 2; i <= pLutLib->LutMax; i++ ) if ( pLutLib->pLutDelays[i][0] != Delay ) return 1; } return 0; } /**Function************************************************************* Synopsis [Sets simple LUT library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_LibLut_t * If_LibLutSetSimple( int nLutSize ) { If_LibLut_t s_LutLib10= { "lutlib",10, 0, {0,1,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1},{1}} }; If_LibLut_t s_LutLib9 = { "lutlib", 9, 0, {0,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1}} }; If_LibLut_t s_LutLib8 = { "lutlib", 8, 0, {0,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1}} }; If_LibLut_t s_LutLib7 = { "lutlib", 7, 0, {0,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1}} }; If_LibLut_t s_LutLib6 = { "lutlib", 6, 0, {0,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1}} }; If_LibLut_t s_LutLib5 = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} }; If_LibLut_t s_LutLib4 = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} }; If_LibLut_t s_LutLib3 = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} }; If_LibLut_t * pLutLib; assert( nLutSize >= 3 && nLutSize <= 10 ); switch ( nLutSize ) { case 3: pLutLib = &s_LutLib3; break; case 4: pLutLib = &s_LutLib4; break; case 5: pLutLib = &s_LutLib5; break; case 6: pLutLib = &s_LutLib6; break; case 7: pLutLib = &s_LutLib7; break; case 8: pLutLib = &s_LutLib8; break; case 9: pLutLib = &s_LutLib9; break; case 10: pLutLib = &s_LutLib10; break; default: pLutLib = NULL; break; } if ( pLutLib == NULL ) return NULL; return If_LibLutDup(pLutLib); } /**Function************************************************************* Synopsis [Gets the delay of the fastest pin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_LibLutFastestPinDelay( If_LibLut_t * p ) { return !p? 1.0 : p->pLutDelays[p->LutMax][0]; } /**Function************************************************************* Synopsis [Gets the delay of the slowest pin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_LibLutSlowestPinDelay( If_LibLut_t * p ) { return !p? 1.0 : (p->fVarPinDelays? p->pLutDelays[p->LutMax][p->LutMax-1]: p->pLutDelays[p->LutMax][0]); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifMan.c000066400000000000000000000604331300674244400224130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Mapping manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifMan.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static If_Obj_t * If_ManSetupObj( If_Man_t * p ); static void If_ManCutSetRecycle( If_Man_t * p, If_Set_t * pSet ) { pSet->pNext = p->pFreeList; p->pFreeList = pSet; } static If_Set_t * If_ManCutSetFetch( If_Man_t * p ) { If_Set_t * pTemp = p->pFreeList; p->pFreeList = p->pFreeList->pNext; return pTemp; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Man_t * If_ManStart( If_Par_t * pPars ) { If_Man_t * p; int v; assert( !pPars->fUseDsd || !pPars->fUseTtPerm ); // start the manager p = ABC_ALLOC( If_Man_t, 1 ); memset( p, 0, sizeof(If_Man_t) ); p->pPars = pPars; p->fEpsilon = pPars->Epsilon; // allocate arrays for nodes p->vCis = Vec_PtrAlloc( 100 ); p->vCos = Vec_PtrAlloc( 100 ); p->vObjs = Vec_PtrAlloc( 100 ); p->vTemp = Vec_PtrAlloc( 100 ); p->vVisited = Vec_PtrAlloc( 100 ); // prepare the memory manager if ( p->pPars->fTruth ) { for ( v = 0; v <= p->pPars->nLutSize; v++ ) p->nTruth6Words[v] = Abc_Truth6WordNum( v ); for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ ) p->vTtMem[v] = Vec_MemAllocForTT( v, pPars->fUseTtPerm ); for ( v = 0; v < 6; v++ ) p->vTtMem[v] = p->vTtMem[6]; if ( p->pPars->fDelayOpt || pPars->nGateSize > 0 ) { for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ ) p->vTtIsops[v] = Vec_WecAlloc( 1000 ); for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ ) Vec_WecInit( p->vTtIsops[v], 2 ); for ( v = 0; v < 6; v++ ) p->vTtIsops[v] = p->vTtIsops[6]; } if ( pPars->fDelayOpt || pPars->nGateSize > 0 || pPars->fDsdBalance ) { p->vCover = Vec_IntAlloc( 0 ); p->vArray = Vec_IntAlloc( 1000 ); } } p->nPermWords = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0; p->nObjBytes = sizeof(If_Obj_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords); p->nCutBytes = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords); p->nSetBytes = sizeof(If_Set_t) + (sizeof(If_Cut_t *) + p->nCutBytes) * (p->pPars->nCutsMax + 1); p->pMemObj = Mem_FixedStart( p->nObjBytes ); // report expected memory usage if ( p->pPars->fVerbose ) Abc_Print( 1, "K = %d. Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d. CutMin = %s\n", p->pPars->nLutSize, 8 * p->nTruth6Words[p->pPars->nLutSize], p->nCutBytes, p->nObjBytes, p->nSetBytes, p->pPars->fCutMin? "yes":"no" ); // room for temporary truth tables p->puTemp[0] = p->pPars->fTruth? ABC_ALLOC( unsigned, 8 * p->nTruth6Words[p->pPars->nLutSize] ) : NULL; p->puTemp[1] = p->puTemp[0] + p->nTruth6Words[p->pPars->nLutSize]*2; p->puTemp[2] = p->puTemp[1] + p->nTruth6Words[p->pPars->nLutSize]*2; p->puTemp[3] = p->puTemp[2] + p->nTruth6Words[p->pPars->nLutSize]*2; p->puTempW = p->pPars->fTruth? ABC_ALLOC( word, p->nTruth6Words[p->pPars->nLutSize] ) : NULL; if ( pPars->fUseDsd ) { for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ ) { p->vTtDsds[v] = Vec_IntAlloc( 1000 ); Vec_IntPush( p->vTtDsds[v], 0 ); Vec_IntPush( p->vTtDsds[v], 2 ); p->vTtPerms[v] = Vec_StrAlloc( 10000 ); Vec_StrFill( p->vTtPerms[v], 2 * v, IF_BIG_CHAR ); Vec_StrWriteEntry( p->vTtPerms[v], v, 0 ); } for ( v = 0; v < 6; v++ ) { p->vTtDsds[v] = p->vTtDsds[6]; p->vTtPerms[v] = p->vTtPerms[6]; } } if ( pPars->fUseTtPerm ) { p->vPairHash = Hash_IntManStart( 10000 ); p->vPairPerms = Vec_StrAlloc( 10000 ); Vec_StrFill( p->vPairPerms, p->pPars->nLutSize, 0 ); p->vPairRes = Vec_IntAlloc( 1000 ); Vec_IntPush( p->vPairRes, -1 ); for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ ) p->vTtOccurs[v] = Vec_IntAlloc( 1000 ); for ( v = 0; v < 6; v++ ) p->vTtOccurs[v] = p->vTtOccurs[6]; for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ ) Vec_IntPushTwo( p->vTtOccurs[v], 0, 0 ); } if ( pPars->fUseCofVars ) { for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ ) { p->vTtVars[v] = Vec_StrAlloc( 1000 ); Vec_StrPush( p->vTtVars[v], 0 ); Vec_StrPush( p->vTtVars[v], 0 ); } for ( v = 0; v < 6; v++ ) p->vTtVars[v] = p->vTtVars[6]; } if ( pPars->fUseAndVars ) { for ( v = 6; v <= Abc_MaxInt(6,p->pPars->nLutSize); v++ ) { p->vTtDecs[v] = Vec_IntAlloc( 1000 ); Vec_IntPush( p->vTtDecs[v], 0 ); Vec_IntPush( p->vTtDecs[v], 0 ); } for ( v = 0; v < 6; v++ ) p->vTtDecs[v] = p->vTtDecs[6]; } if ( pPars->fUseBat ) { // abctime clk = Abc_Clock(); extern int Bat_ManCellFuncLookup( void * pMan, unsigned * pTruth, int nVars, int nLeaves, char * pStr ); extern void Bat_ManFuncSetupTable(); pPars->pFuncCell = (int (*) (If_Man_t *, unsigned *, int, int, char *))Bat_ManCellFuncLookup; Bat_ManFuncSetupTable(); // Abc_PrintTime( 1, "Setup time", Abc_Clock() - clk ); } // create the constant node p->pConst1 = If_ManSetupObj( p ); p->pConst1->Type = IF_CONST1; p->pConst1->fPhase = 1; p->nObjs[IF_CONST1]++; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManRestart( If_Man_t * p ) { ABC_FREE( p->pMemCi ); Vec_PtrClear( p->vCis ); Vec_PtrClear( p->vCos ); Vec_PtrClear( p->vObjs ); Vec_PtrClear( p->vTemp ); Mem_FixedRestart( p->pMemObj ); // create the constant node p->pConst1 = If_ManSetupObj( p ); p->pConst1->Type = IF_CONST1; p->pConst1->fPhase = 1; // reset the counter of other nodes p->nObjs[IF_CI] = p->nObjs[IF_CO] = p->nObjs[IF_AND] = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManStop( If_Man_t * p ) { extern void If_ManCacheAnalize( If_Man_t * p ); int i; if ( p->pPars->fVerbose && p->vCutData ) If_ManCacheAnalize( p ); if ( p->pPars->fVerbose && p->pPars->fTruth ) { int nUnique = 0, nMemTotal = 0; for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) nUnique += Vec_MemEntryNum(p->vTtMem[i]); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) nMemTotal += (int)Vec_MemMemory(p->vTtMem[i]); printf( "Unique truth tables = %d Memory = %.2f MB ", nUnique, 1.0 * nMemTotal / (1<<20) ); Abc_PrintTime( 1, "Time", p->timeCache[4] ); if ( p->nCacheMisses ) { printf( "Cache hits = %d. Cache misses = %d (%.2f %%)\n", p->nCacheHits, p->nCacheMisses, 100.0 * p->nCacheMisses / (p->nCacheHits + p->nCacheMisses) ); Abc_PrintTime( 1, "Non-DSD ", p->timeCache[0] ); Abc_PrintTime( 1, "DSD hits ", p->timeCache[1] ); Abc_PrintTime( 1, "DSD misses", p->timeCache[2] ); Abc_PrintTime( 1, "TOTAL ", p->timeCache[0] + p->timeCache[1] + p->timeCache[2] ); Abc_PrintTime( 1, "Canon ", p->timeCache[3] ); } } if ( p->pPars->fVerbose && p->nCutsUselessAll ) { for ( i = 0; i <= 16; i++ ) if ( p->nCutsUseless[i] ) Abc_Print( 1, "Useless cuts %2d = %9d (out of %9d) (%6.2f %%)\n", i, p->nCutsUseless[i], p->nCutsCount[i], 100.0*p->nCutsUseless[i]/Abc_MaxInt(p->nCutsCount[i],1) ); Abc_Print( 1, "Useless cuts all = %9d (out of %9d) (%6.2f %%)\n", p->nCutsUselessAll, p->nCutsCountAll, 100.0*p->nCutsUselessAll/Abc_MaxInt(p->nCutsCountAll,1) ); } // if ( p->pPars->fVerbose && p->nCuts5 ) // Abc_Print( 1, "Statistics about 5-cuts: Total = %d Non-decomposable = %d (%.2f %%)\n", p->nCuts5, p->nCuts5-p->nCuts5a, 100.0*(p->nCuts5-p->nCuts5a)/p->nCuts5 ); if ( p->pIfDsdMan ) p->pIfDsdMan = NULL; if ( p->pPars->fUseDsd && (p->nCountNonDec[0] || p->nCountNonDec[1]) ) printf( "NonDec0 = %d. NonDec1 = %d.\n", p->nCountNonDec[0], p->nCountNonDec[1] ); Vec_IntFreeP( &p->vCoAttrs ); Vec_PtrFree( p->vCis ); Vec_PtrFree( p->vCos ); Vec_PtrFree( p->vObjs ); Vec_PtrFree( p->vTemp ); Vec_IntFreeP( &p->vCover ); Vec_IntFreeP( &p->vArray ); Vec_WrdFreeP( &p->vAnds ); Vec_WrdFreeP( &p->vAndGate ); Vec_WrdFreeP( &p->vOrGate ); Vec_PtrFreeP( &p->vObjsRev ); Vec_PtrFreeP( &p->vLatchOrder ); Vec_IntFreeP( &p->vLags ); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) Vec_IntFreeP( &p->vTtDsds[i] ); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) Vec_StrFreeP( &p->vTtPerms[i] ); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) Vec_StrFreeP( &p->vTtVars[i] ); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) Vec_IntFreeP( &p->vTtDecs[i] ); Vec_IntFreeP( &p->vCutData ); Vec_IntFreeP( &p->vPairRes ); Vec_StrFreeP( &p->vPairPerms ); Vec_PtrFreeP( &p->vVisited ); if ( p->vPairHash ) Hash_IntManStop( p->vPairHash ); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) Vec_MemHashFree( p->vTtMem[i] ); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) Vec_MemFreeP( &p->vTtMem[i] ); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) Vec_WecFreeP( &p->vTtIsops[i] ); for ( i = 6; i <= Abc_MaxInt(6,p->pPars->nLutSize); i++ ) Vec_IntFreeP( &p->vTtOccurs[i] ); Mem_FixedStop( p->pMemObj, 0 ); ABC_FREE( p->pMemCi ); ABC_FREE( p->pMemAnd ); ABC_FREE( p->puTemp[0] ); ABC_FREE( p->puTempW ); // free pars memory ABC_FREE( p->pPars->pTimesArr ); ABC_FREE( p->pPars->pTimesReq ); if ( p->pManTim ) Tim_ManStop( p->pManTim ); if ( p->vSwitching ) Vec_IntFree( p->vSwitching ); if ( p->pPars->fUseBat ) { extern void Bat_ManFuncSetdownTable(); Bat_ManFuncSetdownTable(); } // hash table // if ( p->pPars->fVerbose && p->nTableEntries[0] ) // printf( "Hash table 2: Entries = %7d. Size = %7d.\n", p->nTableEntries[0], p->nTableSize[0] ); // if ( p->pPars->fVerbose && p->nTableEntries[1] ) // printf( "Hash table 3: Entries = %7d. Size = %7d.\n", p->nTableEntries[1], p->nTableSize[1] ); ABC_FREE( p->pHashTable[0] ); ABC_FREE( p->pHashTable[1] ); if ( p->pMemEntries ) Mem_FixedStop( p->pMemEntries, 0 ); ABC_FREE( p->pName ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates primary input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateCi( If_Man_t * p ) { If_Obj_t * pObj; pObj = If_ManSetupObj( p ); pObj->Type = IF_CI; pObj->IdPio = Vec_PtrSize( p->vCis ); Vec_PtrPush( p->vCis, pObj ); p->nObjs[IF_CI]++; return pObj; } /**Function************************************************************* Synopsis [Creates primary output with the given driver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver ) { If_Obj_t * pObj; pObj = If_ManSetupObj( p ); pObj->IdPio = Vec_PtrSize( p->vCos ); Vec_PtrPush( p->vCos, pObj ); pObj->Type = IF_CO; pObj->fCompl0 = If_IsComplement(pDriver); pDriver = If_Regular(pDriver); pObj->pFanin0 = pDriver; pDriver->nRefs++; pObj->fPhase = (pObj->fCompl0 ^ pDriver->fPhase); pObj->Level = pDriver->Level; if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; p->nObjs[IF_CO]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ) { If_Obj_t * pObj; // perform constant propagation if ( pFan0 == pFan1 ) return pFan0; if ( pFan0 == If_Not(pFan1) ) return If_Not(p->pConst1); if ( If_Regular(pFan0) == p->pConst1 ) return pFan0 == p->pConst1 ? pFan1 : If_Not(p->pConst1); if ( If_Regular(pFan1) == p->pConst1 ) return pFan1 == p->pConst1 ? pFan0 : If_Not(p->pConst1); // get memory for the new object pObj = If_ManSetupObj( p ); pObj->Type = IF_AND; pObj->fCompl0 = If_IsComplement(pFan0); pFan0 = If_Regular(pFan0); pObj->fCompl1 = If_IsComplement(pFan1); pFan1 = If_Regular(pFan1); pObj->pFanin0 = pFan0; pFan0->nRefs++; pFan0->nVisits++; pFan0->nVisitsCopy++; pObj->pFanin1 = pFan1; pFan1->nRefs++; pFan1->nVisits++; pFan1->nVisitsCopy++; pObj->fPhase = (pObj->fCompl0 ^ pFan0->fPhase) & (pObj->fCompl1 ^ pFan1->fPhase); pObj->Level = 1 + IF_MAX( pFan0->Level, pFan1->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; p->nObjs[IF_AND]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ) { If_Obj_t * pRes1, * pRes2; pRes1 = If_ManCreateAnd( p, If_Not(pFan0), pFan1 ); pRes2 = If_ManCreateAnd( p, pFan0, If_Not(pFan1) ); return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) ); } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl ) { If_Obj_t * pRes1, * pRes2; pRes1 = If_ManCreateAnd( p, pFan0, If_Not(pCtrl) ); pRes2 = If_ManCreateAnd( p, pFan1, pCtrl ); return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) ); } /**Function************************************************************* Synopsis [Creates the choice node.] Description [Should be called after the equivalence class nodes are linked.] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pTemp; // mark the node as a representative if its class assert( pObj->fRepr == 0 ); pObj->fRepr = 1; // update the level of this node (needed for correct required time computation) for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) { pObj->Level = IF_MAX( pObj->Level, pTemp->Level ); pTemp->nVisits++; pTemp->nVisitsCopy++; } // mark the largest level if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; p->nChoices++; } /**Function************************************************************* Synopsis [Prepares memory for one cutset.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupSet( If_Man_t * p, If_Set_t * pSet ) { char * pArray; int i; pSet->nCuts = 0; pSet->nCutsMax = p->pPars->nCutsMax; pSet->ppCuts = (If_Cut_t **)(pSet + 1); pArray = (char *)pSet->ppCuts + sizeof(If_Cut_t *) * (pSet->nCutsMax+1); for ( i = 0; i <= pSet->nCutsMax; i++ ) { pSet->ppCuts[i] = (If_Cut_t *)(pArray + i * p->nCutBytes); If_CutSetup( p, pSet->ppCuts[i] ); } // pArray += (pSet->nCutsMax + 1) * p->nCutBytes; // assert( ((char *)pArray) - ((char *)pSet) == p->nSetBytes ); } /**Function************************************************************* Synopsis [Prepares memory for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId ) { pCut->fCompl = 0; pCut->nLimit = p->pPars->nLutSize; pCut->nLeaves = 1; pCut->pLeaves[0] = p->pPars->fLiftLeaves? (ObjId << 8) : ObjId; pCut->uSign = If_ObjCutSign( pCut->pLeaves[0] ); pCut->iCutFunc = p->pPars->fUseTtPerm ? 3 : (p->pPars->fTruth ? 2: -1); pCut->uMaskFunc = 0; assert( pCut->pLeaves[0] < p->vObjs->nSize ); } /**Function************************************************************* Synopsis [Prepares memory for the node with cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManSetupObj( If_Man_t * p ) { If_Obj_t * pObj; // get memory for the object pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMemObj ); memset( pObj, 0, sizeof(If_Obj_t) ); If_CutSetup( p, &pObj->CutBest ); // assign ID and save pObj->Id = Vec_PtrSize(p->vObjs); Vec_PtrPush( p->vObjs, pObj ); // set the required times pObj->Required = IF_FLOAT_LARGE; return pObj; } /**Function************************************************************* Synopsis [Prepares memory for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupCiCutSets( If_Man_t * p ) { If_Obj_t * pObj; int i; assert( p->pMemCi == NULL ); // create elementary cuts for the CIs If_ManForEachCi( p, pObj, i ) If_ManSetupCutTriv( p, &pObj->CutBest, pObj->Id ); // create elementary cutsets for the CIs p->pMemCi = (If_Set_t *)ABC_ALLOC( char, If_ManCiNum(p) * (sizeof(If_Set_t) + sizeof(void *)) ); If_ManForEachCi( p, pObj, i ) { pObj->pCutSet = (If_Set_t *)((char *)p->pMemCi + i * (sizeof(If_Set_t) + sizeof(void *))); pObj->pCutSet->nCuts = 1; pObj->pCutSet->nCutsMax = p->pPars->nCutsMax; pObj->pCutSet->ppCuts = (If_Cut_t **)(pObj->pCutSet + 1); pObj->pCutSet->ppCuts[0] = &pObj->CutBest; } } /**Function************************************************************* Synopsis [Prepares cutset of the node.] Description [Elementary cutset will be added last.] SideEffects [] SeeAlso [] ***********************************************************************/ If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj ) { assert( If_ObjIsAnd(pObj) ); assert( pObj->pCutSet == NULL ); // pObj->pCutSet = (If_Set_t *)Mem_FixedEntryFetch( p->pMemSet ); // If_ManSetupSet( p, pObj->pCutSet ); pObj->pCutSet = If_ManCutSetFetch( p ); pObj->pCutSet->nCuts = 0; pObj->pCutSet->nCutsMax = p->pPars->nCutsMax; return pObj->pCutSet; } /**Function************************************************************* Synopsis [Dereferences cutset of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pFanin; assert( If_ObjIsAnd(pObj) ); // consider the node assert( pObj->nVisits >= 0 ); if ( pObj->nVisits == 0 ) { // Mem_FixedEntryRecycle( p->pMemSet, (char *)pObj->pCutSet ); If_ManCutSetRecycle( p, pObj->pCutSet ); pObj->pCutSet = NULL; } // consider the first fanin pFanin = If_ObjFanin0(pObj); assert( pFanin->nVisits > 0 ); if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) { // Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet ); If_ManCutSetRecycle( p, pFanin->pCutSet ); pFanin->pCutSet = NULL; } // consider the second fanin pFanin = If_ObjFanin1(pObj); assert( pFanin->nVisits > 0 ); if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) { // Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet ); If_ManCutSetRecycle( p, pFanin->pCutSet ); pFanin->pCutSet = NULL; } } /**Function************************************************************* Synopsis [Dereferences cutset of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pTemp; assert( If_ObjIsAnd(pObj) ); assert( pObj->fRepr ); assert( pObj->nVisits > 0 ); // consider the nodes in the choice class for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) { // assert( pTemp == pObj || pTemp->nVisits == 1 ); if ( --pTemp->nVisits == 0 ) { // Mem_FixedEntryRecycle( p->pMemSet, (char *)pTemp->pCutSet ); If_ManCutSetRecycle( p, pTemp->pCutSet ); pTemp->pCutSet = NULL; } } } /**Function************************************************************* Synopsis [Dereferences cutset of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupSetAll( If_Man_t * p, int nCrossCut ) { If_Set_t * pCutSet; int i, nCutSets; nCutSets = 128 + nCrossCut; p->pFreeList = p->pMemAnd = pCutSet = (If_Set_t *)ABC_ALLOC( char, nCutSets * p->nSetBytes ); for ( i = 0; i < nCutSets; i++ ) { If_ManSetupSet( p, pCutSet ); if ( i == nCutSets - 1 ) pCutSet->pNext = NULL; else pCutSet->pNext = (If_Set_t *)( (char *)pCutSet + p->nSetBytes ); pCutSet = pCutSet->pNext; } assert( pCutSet == NULL ); if ( p->pPars->fVerbose ) { Abc_Print( 1, "Node = %7d. Ch = %5d. Total mem = %7.2f MB. Peak cut mem = %7.2f MB.\n", If_ManAndNum(p), p->nChoices, 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), 1.0 * p->nSetBytes * nCrossCut / (1<<20) ); } // Abc_Print( 1, "Cross cut = %d.\n", nCrossCut ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifMap.c000066400000000000000000000675701300674244400224260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifMap.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Mapping procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifMap.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern char * Dau_DsdMerge( char * pDsd0i, int * pPerm0, char * pDsd1i, int * pPerm1, int fCompl0, int fCompl1, int nVars ); extern int If_CutDelayRecCost3( If_Man_t* p, If_Cut_t* pCut, If_Obj_t * pObj ); extern int Abc_ExactDelayCost( word * pTruth, int nVars, int * pArrTimeProfile, char * pPerm, int * Cost, int AigLevel ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Compute delay of the cut's output in terms of logic levels.] Description [Uses the best arrival time of the fanins of the cut to compute the arrival times of the output of the cut.] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManCutAigDelay_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vVisited ) { int Delay0, Delay1; if ( pObj->fVisit ) return pObj->iCopy; if ( If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) ) return -1; // store the node in the structure by level assert( If_ObjIsAnd(pObj) ); pObj->fVisit = 1; Vec_PtrPush( vVisited, pObj ); Delay0 = If_ManCutAigDelay_rec( p, pObj->pFanin0, vVisited ); Delay1 = If_ManCutAigDelay_rec( p, pObj->pFanin1, vVisited ); pObj->iCopy = (Delay0 >= 0 && Delay1 >= 0) ? 1 + Abc_MaxInt(Delay0, Delay1) : -1; return pObj->iCopy; } int If_ManCutAigDelay( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut ) { If_Obj_t * pLeaf; int i, Delay; Vec_PtrClear( p->vVisited ); If_CutForEachLeaf( p, pCut, pLeaf, i ) { assert( pLeaf->fVisit == 0 ); pLeaf->fVisit = 1; Vec_PtrPush( p->vVisited, pLeaf ); pLeaf->iCopy = If_ObjCutBest(pLeaf)->Delay; } Delay = If_ManCutAigDelay_rec( p, pObj, p->vVisited ); Vec_PtrForEachEntry( If_Obj_t *, p->vVisited, pLeaf, i ) pLeaf->fVisit = 0; // assert( Delay <= (int)pObj->Level ); return Delay; } /**Function************************************************************* Synopsis [Counts the number of 1s in the signature.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_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); } /**Function************************************************************* Synopsis [Counts the number of 1s in the signature.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutDelaySpecial( If_Man_t * p, If_Cut_t * pCut, int fCarry ) { static float Pin2Pin[2][3] = { {1.0, 1.0, 1.0}, {1.0, 1.0, 0.0} }; If_Obj_t * pLeaf; float DelayCur, Delay = -IF_FLOAT_LARGE; int i; assert( pCut->nLeaves <= 3 ); If_CutForEachLeaf( p, pCut, pLeaf, i ) { DelayCur = If_ObjCutBest(pLeaf)->Delay; Delay = IF_MAX( Delay, Pin2Pin[fCarry][i] + DelayCur ); } return Delay; } /**Function************************************************************* Synopsis [Returns arrival time profile of the cut.] Description [The procedure returns static storage, which should not be deallocated and is only valid until before the procedure is called again.] SideEffects [] SeeAlso [] ***********************************************************************/ int * If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut ) { int i; for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) p->pArrTimeProfile[i] = (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay; return p->pArrTimeProfile; } /**Function************************************************************* Synopsis [Finds the best cut for the given node.] Description [Mapping modes: delay (0), area flow (1), area (2).] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess, int fFirst ) { If_Set_t * pCutSet; If_Cut_t * pCut0, * pCut1, * pCut; If_Cut_t * pCut0R, * pCut1R; int fFunc0R, fFunc1R; int i, k, v, iCutDsd, fChange; int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct != NULL; int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0); assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 ); assert( !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 0 ); // prepare if ( Mode == 0 ) pObj->EstRefs = (float)pObj->nRefs; else if ( Mode == 1 ) pObj->EstRefs = (float)((2.0 * pObj->EstRefs + pObj->nRefs) / 3.0); // deref the selected cut if ( Mode && pObj->nRefs > 0 ) If_CutAreaDeref( p, If_ObjCutBest(pObj) ); // prepare the cutset pCutSet = If_ManSetupNodeCutSet( p, pObj ); // get the current assigned best cut pCut = If_ObjCutBest(pObj); if ( !fFirst ) { // recompute the parameters of the best cut if ( p->pPars->fDelayOpt ) pCut->Delay = If_CutSopBalanceEval( p, pCut, NULL ); else if ( p->pPars->fDsdBalance ) pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL ); else if ( p->pPars->fUserRecLib ) pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); else if ( p->pPars->fUserSesLib ) { int Cost = 0; pCut->fUser = 1; pCut->Delay = (float)Abc_ExactDelayCost( If_CutTruthW(p, pCut), If_CutLeaveNum(pCut), If_CutArrTimeProfile(p, pCut), If_CutPerm(pCut), &Cost, If_ManCutAigDelay(p, pObj, pCut) ); if ( Cost == ABC_INFINITY ) { for ( v = 0; v < If_CutLeaveNum(pCut); v++ ) If_CutPerm(pCut)[v] = IF_BIG_CHAR; pCut->Cost = IF_COST_MAX; pCut->fUseless = 1; } } else if ( p->pPars->fDelayOptLut ) pCut->Delay = If_CutLutBalanceEval( p, pCut ); else if( p->pPars->nGateSize > 0 ) pCut->Delay = If_CutDelaySop( p, pCut ); else pCut->Delay = If_CutDelay( p, pObj, pCut ); assert( pCut->Delay != -1 ); // assert( pCut->Delay <= pObj->Required + p->fEpsilon ); if ( pCut->Delay > pObj->Required + 2*p->fEpsilon ) Abc_Print( 1, "If_ObjPerformMappingAnd(): Warning! Delay of node %d (%f) exceeds the required times (%f).\n", pObj->Id, pCut->Delay, pObj->Required + p->fEpsilon ); pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut ); if ( p->pPars->fEdge ) pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut ); if ( p->pPars->fPower ) pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj ); // save the best cut from the previous iteration if ( !fPreprocess ) If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut ); } // generate cuts If_ObjForEachCut( pObj->pFanin0, pCut0, i ) If_ObjForEachCut( pObj->pFanin1, pCut1, k ) { // get the next free cut assert( pCutSet->nCuts <= pCutSet->nCutsMax ); pCut = pCutSet->ppCuts[pCutSet->nCuts]; // make sure K-feasible cut exists if ( If_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->pPars->nLutSize ) continue; pCut0R = pCut0; pCut1R = pCut1; fFunc0R = pCut0->iCutFunc ^ pCut0->fCompl ^ pObj->fCompl0; fFunc1R = pCut1->iCutFunc ^ pCut1->fCompl ^ pObj->fCompl1; if ( !p->pPars->fUseTtPerm || pCut0->nLeaves > pCut1->nLeaves || (pCut0->nLeaves == pCut1->nLeaves && fFunc0R > fFunc1R) ) { } else { ABC_SWAP( If_Cut_t *, pCut0R, pCut1R ); ABC_SWAP( int, fFunc0R, fFunc1R ); } // merge the cuts if ( p->pPars->fUseTtPerm ) { if ( !If_CutMerge( p, pCut0R, pCut1R, pCut ) ) continue; } else { if ( !If_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) continue; } if ( pObj->fSpec && pCut->nLeaves == (unsigned)p->pPars->nLutSize ) continue; p->nCutsMerged++; p->nCutsTotal++; // check if this cut is contained in any of the available cuts if ( !p->pPars->fSkipCutFilter && If_CutFilter( pCutSet, pCut, fSave0 ) ) continue; // check if the cut is a special AND-gate cut pCut->fAndCut = fUseAndCut && pCut->nLeaves == 2 && pCut->pLeaves[0] == pObj->pFanin0->Id && pCut->pLeaves[1] == pObj->pFanin1->Id; //assert( pCut->nLeaves != 2 || pCut->pLeaves[0] < pCut->pLeaves[1] ); //assert( pCut->nLeaves != 2 || pObj->pFanin0->Id < pObj->pFanin1->Id ); // compute the truth table pCut->iCutFunc = -1; pCut->fCompl = 0; if ( p->pPars->fTruth ) { // int nShared = pCut0->nLeaves + pCut1->nLeaves - pCut->nLeaves; abctime clk = 0; if ( p->pPars->fVerbose ) clk = Abc_Clock(); if ( p->pPars->fUseTtPerm ) fChange = If_CutComputeTruthPerm( p, pCut, pCut0R, pCut1R, fFunc0R, fFunc1R ); else fChange = If_CutComputeTruth( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 ); if ( p->pPars->fVerbose ) p->timeCache[4] += Abc_Clock() - clk; if ( !p->pPars->fSkipCutFilter && fChange && If_CutFilter( pCutSet, pCut, fSave0 ) ) continue; if ( p->pPars->fUseDsd ) { extern void If_ManCacheRecord( If_Man_t * p, int iDsd0, int iDsd1, int nShared, int iDsd ); int truthId = Abc_Lit2Var(pCut->iCutFunc); if ( truthId >= Vec_IntSize(p->vTtDsds[pCut->nLeaves]) || Vec_IntEntry(p->vTtDsds[pCut->nLeaves], truthId) == -1 ) { while ( truthId >= Vec_IntSize(p->vTtDsds[pCut->nLeaves]) ) { Vec_IntPush( p->vTtDsds[pCut->nLeaves], -1 ); for ( v = 0; v < Abc_MaxInt(6, pCut->nLeaves); v++ ) Vec_StrPush( p->vTtPerms[pCut->nLeaves], IF_BIG_CHAR ); } iCutDsd = If_DsdManCompute( p->pIfDsdMan, If_CutTruthWR(p, pCut), pCut->nLeaves, (unsigned char *)If_CutDsdPerm(p, pCut), p->pPars->pLutStruct ); Vec_IntWriteEntry( p->vTtDsds[pCut->nLeaves], truthId, iCutDsd ); } assert( If_DsdManSuppSize(p->pIfDsdMan, If_CutDsdLit(p, pCut)) == (int)pCut->nLeaves ); //If_ManCacheRecord( p, If_CutDsdLit(p, pCut0), If_CutDsdLit(p, pCut1), nShared, If_CutDsdLit(p, pCut) ); } // run user functions pCut->fUseless = 0; if ( p->pPars->pFuncCell ) { assert( p->pPars->fUseTtPerm == 0 ); assert( pCut->nLimit >= 4 && pCut->nLimit <= 16 ); if ( p->pPars->fUseDsd ) pCut->fUseless = If_DsdManCheckDec( p->pIfDsdMan, If_CutDsdLit(p, pCut) ); else pCut->fUseless = !p->pPars->pFuncCell( p, If_CutTruth(p, pCut), Abc_MaxInt(6, pCut->nLeaves), pCut->nLeaves, p->pPars->pLutStruct ); p->nCutsUselessAll += pCut->fUseless; p->nCutsUseless[pCut->nLeaves] += pCut->fUseless; p->nCutsCountAll++; p->nCutsCount[pCut->nLeaves]++; // skip 5-input cuts, which cannot be decomposed if ( (p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u) && pCut->nLeaves == 5 && pCut->nLimit == 5 ) { extern int If_CluCheckDecInAny( word t, int nVars ); extern int If_CluCheckDecOut( word t, int nVars ); unsigned TruthU = *If_CutTruth(p, pCut); word Truth = (((word)TruthU << 32) | (word)TruthU); p->nCuts5++; if ( If_CluCheckDecInAny( Truth, 5 ) ) p->nCuts5a++; else continue; } else if ( p->pPars->fVerbose && pCut->nLeaves == 5 ) { extern int If_CluCheckDecInAny( word t, int nVars ); extern int If_CluCheckDecOut( word t, int nVars ); unsigned TruthU = *If_CutTruth(p, pCut); word Truth = (((word)TruthU << 32) | (word)TruthU); p->nCuts5++; if ( If_CluCheckDecInAny( Truth, 5 ) || If_CluCheckDecOut( Truth, 5 ) ) p->nCuts5a++; } } else if ( p->pPars->fUseDsdTune ) { pCut->fUseless = If_DsdManReadMark( p->pIfDsdMan, If_CutDsdLit(p, pCut) ); p->nCutsUselessAll += pCut->fUseless; p->nCutsUseless[pCut->nLeaves] += pCut->fUseless; p->nCutsCountAll++; p->nCutsCount[pCut->nLeaves]++; } else if ( p->pPars->fUse34Spec ) { assert( pCut->nLeaves <= 4 ); if ( pCut->nLeaves == 4 && !Abc_Tt4Check( (int)(0xFFFF & *If_CutTruth(p, pCut)) ) ) pCut->fUseless = 1; } else { if ( p->pPars->fUseAndVars ) { int iDecMask = -1, truthId = Abc_Lit2Var(pCut->iCutFunc); assert( p->pPars->nLutSize <= 13 ); if ( truthId >= Vec_IntSize(p->vTtDecs[pCut->nLeaves]) || Vec_IntEntry(p->vTtDecs[pCut->nLeaves], truthId) == -1 ) { while ( truthId >= Vec_IntSize(p->vTtDecs[pCut->nLeaves]) ) Vec_IntPush( p->vTtDecs[pCut->nLeaves], -1 ); if ( (int)pCut->nLeaves > p->pPars->nLutSize / 2 && (int)pCut->nLeaves <= 2 * (p->pPars->nLutSize / 2) ) iDecMask = Abc_TtProcessBiDec( If_CutTruthWR(p, pCut), (int)pCut->nLeaves, p->pPars->nLutSize / 2 ); else iDecMask = 0; Vec_IntWriteEntry( p->vTtDecs[pCut->nLeaves], truthId, iDecMask ); } iDecMask = Vec_IntEntry(p->vTtDecs[pCut->nLeaves], truthId); assert( iDecMask >= 0 ); pCut->fUseless = (int)(iDecMask == 0 && (int)pCut->nLeaves > p->pPars->nLutSize / 2); p->nCutsUselessAll += pCut->fUseless; p->nCutsUseless[pCut->nLeaves] += pCut->fUseless; p->nCutsCountAll++; p->nCutsCount[pCut->nLeaves]++; } if ( p->pPars->fUseCofVars && (!p->pPars->fUseAndVars || pCut->fUseless) ) { int iCofVar = -1, truthId = Abc_Lit2Var(pCut->iCutFunc); if ( truthId >= Vec_StrSize(p->vTtVars[pCut->nLeaves]) || Vec_StrEntry(p->vTtVars[pCut->nLeaves], truthId) == (char)-1 ) { while ( truthId >= Vec_StrSize(p->vTtVars[pCut->nLeaves]) ) Vec_StrPush( p->vTtVars[pCut->nLeaves], (char)-1 ); iCofVar = Abc_TtCheckCondDep( If_CutTruthWR(p, pCut), pCut->nLeaves, p->pPars->nLutSize / 2 ); Vec_StrWriteEntry( p->vTtVars[pCut->nLeaves], truthId, (char)iCofVar ); } iCofVar = Vec_StrEntry(p->vTtVars[pCut->nLeaves], truthId); assert( iCofVar >= 0 && iCofVar <= (int)pCut->nLeaves ); pCut->fUseless = (int)(iCofVar == (int)pCut->nLeaves && pCut->nLeaves > 0); p->nCutsUselessAll += pCut->fUseless; p->nCutsUseless[pCut->nLeaves] += pCut->fUseless; p->nCutsCountAll++; p->nCutsCount[pCut->nLeaves]++; } } } // compute the application-specific cost and depth pCut->fUser = (p->pPars->pFuncCost != NULL); pCut->Cost = p->pPars->pFuncCost? p->pPars->pFuncCost(p, pCut) : 0; if ( pCut->Cost == IF_COST_MAX ) continue; // check if the cut satisfies the required times if ( p->pPars->fDelayOpt ) pCut->Delay = If_CutSopBalanceEval( p, pCut, NULL ); else if ( p->pPars->fDsdBalance ) pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL ); else if ( p->pPars->fUserRecLib ) pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj ); else if ( p->pPars->fUserSesLib ) { int Cost = 0; pCut->fUser = 1; pCut->Delay = (float)Abc_ExactDelayCost( If_CutTruthW(p, pCut), If_CutLeaveNum(pCut), If_CutArrTimeProfile(p, pCut), If_CutPerm(pCut), &Cost, If_ManCutAigDelay(p, pObj, pCut) ); if ( Cost == ABC_INFINITY ) { for ( v = 0; v < If_CutLeaveNum(pCut); v++ ) If_CutPerm(pCut)[v] = IF_BIG_CHAR; pCut->Cost = IF_COST_MAX; pCut->fUseless = 1; } } else if ( p->pPars->fDelayOptLut ) pCut->Delay = If_CutLutBalanceEval( p, pCut ); else if( p->pPars->nGateSize > 0 ) pCut->Delay = If_CutDelaySop( p, pCut ); else pCut->Delay = If_CutDelay( p, pObj, pCut ); if ( pCut->Delay == -1 ) continue; if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon ) continue; // compute area of the cut (this area may depend on the application specific cost) pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut ); if ( p->pPars->fEdge ) pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut ); if ( p->pPars->fPower ) pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj ); // pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); // insert the cut into storage If_CutSort( p, pCutSet, pCut ); // If_CutTraverse( p, pObj, pCut ); } assert( pCutSet->nCuts > 0 ); // If_CutVerifyCuts( pCutSet, !p->pPars->fUseTtPerm ); // update the best cut if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon ) { If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] ); if ( p->pPars->fUserRecLib || p->pPars->fUserSesLib ) assert(If_ObjCutBest(pObj)->Cost < IF_COST_MAX && If_ObjCutBest(pObj)->Delay < ABC_INFINITY); } // add the trivial cut to the set if ( !pObj->fSkipCut && If_ObjCutBest(pObj)->nLeaves > 1 ) { If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id ); assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 ); } // if ( If_ObjCutBest(pObj)->nLeaves == 0 ) // p->nBestCutSmall[0]++; // else if ( If_ObjCutBest(pObj)->nLeaves == 1 ) // p->nBestCutSmall[1]++; // ref the selected cut if ( Mode && pObj->nRefs > 0 ) If_CutAreaRef( p, If_ObjCutBest(pObj) ); if ( If_ObjCutBest(pObj)->fUseless ) Abc_Print( 1, "The best cut is useless.\n" ); // call the user specified function for each cut if ( p->pPars->pFuncUser ) If_ObjForEachCut( pObj, pCut, i ) p->pPars->pFuncUser( p, pObj, pCut ); // free the cuts If_ManDerefNodeCutSet( p, pObj ); } /**Function************************************************************* Synopsis [Finds the best cut for the choice node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ) { If_Set_t * pCutSet; If_Obj_t * pTemp; If_Cut_t * pCutTemp, * pCut; int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec; assert( pObj->pEquiv != NULL ); // prepare if ( Mode && pObj->nRefs > 0 ) If_CutAreaDeref( p, If_ObjCutBest(pObj) ); // remove elementary cuts for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) pTemp->pCutSet->nCuts--; // update the cutset of the node pCutSet = pObj->pCutSet; // generate cuts for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv ) { if ( pTemp->pCutSet->nCuts == 0 ) continue; // go through the cuts of this node If_ObjForEachCut( pTemp, pCutTemp, i ) { if ( pCutTemp->fUseless ) continue; // get the next free cut assert( pCutSet->nCuts <= pCutSet->nCutsMax ); pCut = pCutSet->ppCuts[pCutSet->nCuts]; // copy the cut into storage If_CutCopy( p, pCut, pCutTemp ); // check if this cut is contained in any of the available cuts if ( If_CutFilter( pCutSet, pCut, fSave0 ) ) continue; // check if the cut satisfies the required times // assert( pCut->Delay == If_CutDelay( p, pTemp, pCut ) ); if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon ) continue; // set the phase attribute pCut->fCompl = pObj->fPhase ^ pTemp->fPhase; // compute area of the cut (this area may depend on the application specific cost) pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut ) : If_CutAreaFlow( p, pCut ); if ( p->pPars->fEdge ) pCut->Edge = (Mode == 2)? If_CutEdgeDerefed( p, pCut ) : If_CutEdgeFlow( p, pCut ); if ( p->pPars->fPower ) pCut->Power = (Mode == 2)? If_CutPowerDerefed( p, pCut, pObj ) : If_CutPowerFlow( p, pCut, pObj ); // pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); // insert the cut into storage If_CutSort( p, pCutSet, pCut ); } } assert( pCutSet->nCuts > 0 ); // update the best cut if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon ) If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] ); // add the trivial cut to the set if ( !pObj->fSkipCut && If_ObjCutBest(pObj)->nLeaves > 1 ) { If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id ); assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 ); } // ref the selected cut if ( Mode && pObj->nRefs > 0 ) If_CutAreaRef( p, If_ObjCutBest(pObj) ); // free the cuts If_ManDerefChoiceCutSet( p, pObj ); } /**Function************************************************************* Synopsis [Performs one mapping pass over all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, int fFirst, char * pLabel ) { ProgressBar * pProgress = NULL; If_Obj_t * pObj; int i; abctime clk = Abc_Clock(); float arrTime; assert( Mode >= 0 && Mode <= 2 ); p->nBestCutSmall[0] = p->nBestCutSmall[1] = 0; // set the sorting function if ( Mode || p->pPars->fArea ) // area p->SortMode = 1; else if ( p->pPars->fFancy ) p->SortMode = 2; else p->SortMode = 0; // set the cut number p->nCutsUsed = nCutsUsed; p->nCutsMerged = 0; // make sure the visit counters are all zero If_ManForEachNode( p, pObj, i ) assert( pObj->nVisits == pObj->nVisitsCopy ); // map the internal nodes if ( p->pManTim != NULL ) { Tim_ManIncrementTravId( p->pManTim ); If_ManForEachObj( p, pObj, i ) { if ( If_ObjIsAnd(pObj) ) { If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess, fFirst ); if ( pObj->fRepr ) If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess ); } else if ( If_ObjIsCi(pObj) ) { //Abc_Print( 1, "processing CI %d\n", pObj->Id ); arrTime = Tim_ManGetCiArrival( p->pManTim, pObj->IdPio ); If_ObjSetArrTime( pObj, arrTime ); } else if ( If_ObjIsCo(pObj) ) { arrTime = If_ObjArrTime( If_ObjFanin0(pObj) ); Tim_ManSetCoArrival( p->pManTim, pObj->IdPio, arrTime ); } else if ( If_ObjIsConst1(pObj) ) { } else assert( 0 ); } // Tim_ManPrint( p->pManTim ); } else { pProgress = Extra_ProgressBarStart( stdout, If_ManObjNum(p) ); If_ManForEachNode( p, pObj, i ) { Extra_ProgressBarUpdate( pProgress, i, pLabel ); If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess, fFirst ); if ( pObj->fRepr ) If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess ); } } Extra_ProgressBarStop( pProgress ); // make sure the visit counters are all zero If_ManForEachNode( p, pObj, i ) assert( pObj->nVisits == 0 ); // compute required times and stats If_ManComputeRequired( p ); // Tim_ManPrint( p->pManTim ); if ( p->pPars->fVerbose ) { char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A')); Abc_Print( 1, "%c: Del = %7.2f. Ar = %9.1f. Edge = %8d. ", Symb, p->RequiredGlo, p->AreaGlo, p->nNets ); if ( p->dPower ) Abc_Print( 1, "Switch = %7.2f. ", p->dPower ); Abc_Print( 1, "Cut = %8d. ", p->nCutsMerged ); Abc_PrintTime( 1, "T", Abc_Clock() - clk ); // Abc_Print( 1, "Max number of cuts = %d. Average number of cuts = %5.2f.\n", // p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifMatch2.c000066400000000000000000000033021300674244400230060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifMatch2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Specialized matching.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2009.] Revision [$Id: ifMatch2.c,v 1.00 2009/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bat_ManFuncSetupTable() { } void Bat_ManFuncSetdownTable() { } int Bat_ManCellFuncLookup( void * pMan, unsigned * pTruth, int nVars, int nLeaves, char * pStr ) { return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifReduce.c000066400000000000000000000332021300674244400231010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifExpand.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Incremental improvement of current mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifExpand.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void If_ManImproveExpand( If_Man_t * p, int nLimit ); static void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ); static void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ); static void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront ); static void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Improves current mapping using expand/Expand of one cut.] Description [Assumes current mapping assigned and required times computed.] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveMapping( If_Man_t * p ) { abctime clk; clk = Abc_Clock(); If_ManImproveExpand( p, p->pPars->nLutSize ); If_ManComputeRequired( p ); if ( p->pPars->fVerbose ) { Abc_Print( 1, "E: Del = %7.2f. Ar = %9.1f. Edge = %8d. ", p->RequiredGlo, p->AreaGlo, p->nNets ); if ( p->dPower ) Abc_Print( 1, "Switch = %7.2f. ", p->dPower ); Abc_Print( 1, "Cut = %8d. ", p->nCutsMerged ); Abc_PrintTime( 1, "T", Abc_Clock() - clk ); } } /**Function************************************************************* Synopsis [Performs area recovery for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveExpand( If_Man_t * p, int nLimit ) { Vec_Ptr_t * vFront, * vFrontOld, * vVisited; If_Obj_t * pObj; int i; vFront = Vec_PtrAlloc( nLimit ); vFrontOld = Vec_PtrAlloc( nLimit ); vVisited = Vec_PtrAlloc( 100 ); // iterate through all nodes in the topological order If_ManForEachNode( p, pObj, i ) If_ManImproveNodeExpand( p, pObj, nLimit, vFront, vFrontOld, vVisited ); Vec_PtrFree( vFront ); Vec_PtrFree( vFrontOld ); Vec_PtrFree( vVisited ); } /**Function************************************************************* Synopsis [Counts the number of nodes with no external fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManImproveCutCost( If_Man_t * p, Vec_Ptr_t * vFront ) { If_Obj_t * pFanin; int i, Counter = 0; Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i ) if ( pFanin->nRefs == 0 ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Performs area recovery for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ) { If_Obj_t * pFanin; If_Cut_t * pCut; int CostBef, CostAft, i; float DelayOld, AreaBef, AreaAft; pCut = If_ObjCutBest(pObj); pCut->Delay = If_CutDelay( p, pObj, pCut ); assert( pCut->Delay <= pObj->Required + p->fEpsilon ); if ( pObj->nRefs == 0 ) return; // get the delay DelayOld = pCut->Delay; // get the area AreaBef = If_CutAreaRefed( p, pCut ); // if ( AreaBef == 1 ) // return; // the cut is non-trivial If_ManImproveNodePrepare( p, pObj, nLimit, vFront, vFrontOld, vVisited ); // iteratively modify the cut If_CutAreaDeref( p, pCut ); CostBef = If_ManImproveCutCost( p, vFront ); If_ManImproveNodeFaninCompact( p, pObj, nLimit, vFront, vVisited ); CostAft = If_ManImproveCutCost( p, vFront ); If_CutAreaRef( p, pCut ); assert( CostBef >= CostAft ); // clean up Vec_PtrForEachEntry( If_Obj_t *, vVisited, pFanin, i ) pFanin->fMark = 0; // update the node If_ManImproveNodeUpdate( p, pObj, vFront ); pCut->Delay = If_CutDelay( p, pObj, pCut ); // get the new area AreaAft = If_CutAreaRefed( p, pCut ); if ( AreaAft > AreaBef || pCut->Delay > pObj->Required + p->fEpsilon ) { If_ManImproveNodeUpdate( p, pObj, vFrontOld ); AreaAft = If_CutAreaRefed( p, pCut ); assert( AreaAft == AreaBef ); pCut->Delay = DelayOld; } } /**Function************************************************************* Synopsis [Performs area recovery for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveMark_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vVisited ) { if ( pObj->fMark ) return; assert( If_ObjIsAnd(pObj) ); If_ManImproveMark_rec( p, If_ObjFanin0(pObj), vVisited ); If_ManImproveMark_rec( p, If_ObjFanin1(pObj), vVisited ); Vec_PtrPush( vVisited, pObj ); pObj->fMark = 1; } /**Function************************************************************* Synopsis [Prepares node mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ) { If_Cut_t * pCut; If_Obj_t * pLeaf; int i; Vec_PtrClear( vFront ); Vec_PtrClear( vFrontOld ); Vec_PtrClear( vVisited ); // expand the cut downwards from the given place pCut = If_ObjCutBest(pObj); If_CutForEachLeaf( p, pCut, pLeaf, i ) { Vec_PtrPush( vFront, pLeaf ); Vec_PtrPush( vFrontOld, pLeaf ); Vec_PtrPush( vVisited, pLeaf ); pLeaf->fMark = 1; } // mark the nodes in the cone If_ManImproveMark_rec( p, pObj, vVisited ); } /**Function************************************************************* Synopsis [Updates the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront ) { If_Cut_t * pCut; If_Obj_t * pFanin; int i; pCut = If_ObjCutBest(pObj); // deref node's cut If_CutAreaDeref( p, pCut ); // update the node's cut pCut->nLeaves = Vec_PtrSize(vFront); Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i ) pCut->pLeaves[i] = pFanin->Id; If_CutOrder( pCut ); pCut->uSign = If_ObjCutSignCompute(pCut); // ref the new cut If_CutAreaRef( p, pCut ); } /**Function************************************************************* Synopsis [Returns 1 if the number of fanins will grow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManImproveNodeWillGrow( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pFanin0, * pFanin1; assert( If_ObjIsAnd(pObj) ); pFanin0 = If_ObjFanin0(pObj); pFanin1 = If_ObjFanin1(pObj); return !pFanin0->fMark && !pFanin1->fMark; } /**Function************************************************************* Synopsis [Returns the increase in the number of fanins with no external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManImproveNodeFaninCost( If_Man_t * p, If_Obj_t * pObj ) { int Counter = 0; assert( If_ObjIsAnd(pObj) ); // check if the node has external refs if ( pObj->nRefs == 0 ) Counter--; // increment the number of fanins without external refs if ( !If_ObjFanin0(pObj)->fMark && If_ObjFanin0(pObj)->nRefs == 0 ) Counter++; // increment the number of fanins without external refs if ( !If_ObjFanin1(pObj)->fMark && If_ObjFanin1(pObj)->nRefs == 0 ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Updates the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveNodeFaninUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) { If_Obj_t * pFanin; assert( If_ObjIsAnd(pObj) ); Vec_PtrRemove( vFront, pObj ); pFanin = If_ObjFanin0(pObj); if ( !pFanin->fMark ) { Vec_PtrPush( vFront, pFanin ); Vec_PtrPush( vVisited, pFanin ); pFanin->fMark = 1; } pFanin = If_ObjFanin1(pObj); if ( !pFanin->fMark ) { Vec_PtrPush( vFront, pFanin ); Vec_PtrPush( vVisited, pFanin ); pFanin->fMark = 1; } } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManImproveNodeFaninCompact0( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) { If_Obj_t * pFanin; int i; Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i ) { if ( If_ObjIsCi(pFanin) ) continue; if ( If_ManImproveNodeWillGrow(p, pFanin) ) continue; if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 ) { If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManImproveNodeFaninCompact1( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) { If_Obj_t * pFanin; int i; Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i ) { if ( If_ObjIsCi(pFanin) ) continue; if ( If_ManImproveNodeFaninCost(p, pFanin) < 0 ) { If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManImproveNodeFaninCompact2( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) { If_Obj_t * pFanin; int i; Vec_PtrForEachEntry( If_Obj_t *, vFront, pFanin, i ) { if ( If_ObjIsCi(pFanin) ) continue; if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 ) { If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManImproveNodeFaninCompact_int( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) { if ( If_ManImproveNodeFaninCompact0(p, pObj, nLimit, vFront, vVisited) ) return 1; if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact1(p, pObj, nLimit, vFront, vVisited) ) return 1; // if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact2(p, pObj, nLimit, vFront, vVisited) ) // return 1; assert( Vec_PtrSize(vFront) <= nLimit ); return 0; } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) { while ( If_ManImproveNodeFaninCompact_int( p, pObj, nLimit, vFront, vVisited ) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifSat.c000066400000000000000000000531241300674244400224260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [SAT-based evaluation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifSat.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Builds SAT instance for the given structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * If_ManSatBuildXY( int nLutSize ) { int nMintsL = (1 << nLutSize); int nMintsF = (1 << (2 * nLutSize - 1)); int nVars = 2 * nMintsL + nMintsF; int iVarP0 = 0; // LUT0 parameters (total nMintsL) int iVarP1 = nMintsL; // LUT1 parameters (total nMintsL) int m,iVarM = 2 * nMintsL; // MUX vars (total nMintsF) sat_solver * p = sat_solver_new(); sat_solver_setnvars( p, nVars ); for ( m = 0; m < nMintsF; m++ ) sat_solver_add_mux( p, iVarM + m, iVarP0 + m % nMintsL, iVarP1 + 2 * (m / nMintsL) + 1, iVarP1 + 2 * (m / nMintsL), 0, 0, 0, 0 ); return p; } void * If_ManSatBuildXYZ( int nLutSize ) { int nMintsL = (1 << nLutSize); int nMintsF = (1 << (3 * nLutSize - 2)); int nVars = 3 * nMintsL + nMintsF; int iVarP0 = 0; // LUT0 parameters (total nMintsL) int iVarP1 = nMintsL; // LUT1 parameters (total nMintsL) int iVarP2 = 2 * nMintsL; // LUT2 parameters (total nMintsL) int m,iVarM = 3 * nMintsL; // MUX vars (total nMintsF) sat_solver * p = sat_solver_new(); sat_solver_setnvars( p, nVars ); for ( m = 0; m < nMintsF; m++ ) sat_solver_add_mux41( p, iVarM + m, iVarP0 + m % nMintsL, iVarP1 + (m >> nLutSize) % nMintsL, iVarP2 + 4 * (m >> (2 * nLutSize)) + 0, iVarP2 + 4 * (m >> (2 * nLutSize)) + 1, iVarP2 + 4 * (m >> (2 * nLutSize)) + 2, iVarP2 + 4 * (m >> (2 * nLutSize)) + 3 ); return p; } void If_ManSatUnbuild( void * p ) { if ( p ) sat_solver_delete( (sat_solver *)p ); } /**Function************************************************************* Synopsis [Verification for 6-input function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static word If_ManSat6ComposeLut4( int t, word f[4], int k ) { int m, v, nMints = (1 << k); word c, r = 0; assert( k <= 4 ); for ( m = 0; m < nMints; m++ ) { if ( !((t >> m) & 1) ) continue; c = ~(word)0; for ( v = 0; v < k; v++ ) c &= ((m >> v) & 1) ? f[v] : ~f[v]; r |= c; } return r; } word If_ManSat6Truth( word uBound, word uFree, int * pBSet, int nBSet, int * pSSet, int nSSet, int * pFSet, int nFSet ) { word r, q, f[4]; int i, k = 0; // bound set vars for ( i = 0; i < nSSet; i++ ) f[k++] = s_Truths6[pSSet[i]]; for ( i = 0; i < nBSet; i++ ) f[k++] = s_Truths6[pBSet[i]]; q = If_ManSat6ComposeLut4( (int)(uBound & 0xffff), f, k ); // free set vars k = 0; f[k++] = q; for ( i = 0; i < nSSet; i++ ) f[k++] = s_Truths6[pSSet[i]]; for ( i = 0; i < nFSet; i++ ) f[k++] = s_Truths6[pFSet[i]]; r = If_ManSat6ComposeLut4( (int)(uFree & 0xffff), f, k ); return r; } /**Function************************************************************* Synopsis [Returns config string for the given truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManSatCheckXY( void * pSat, int nLutSize, word * pTruth, int nVars, unsigned uSet, word * pTBound, word * pTFree, Vec_Int_t * vLits ) { sat_solver * p = (sat_solver *)pSat; int iBSet, nBSet = 0, pBSet[IF_MAX_FUNC_LUTSIZE]; int iSSet, nSSet = 0, pSSet[IF_MAX_FUNC_LUTSIZE]; int iFSet, nFSet = 0, pFSet[IF_MAX_FUNC_LUTSIZE]; int nMintsL = (1 << nLutSize); int nMintsF = (1 << (2 * nLutSize - 1)); int v, Value, m, mNew, nMintsFNew, nMintsLNew; word Res; // collect variable sets Dau_DecSortSet( uSet, nVars, &nBSet, &nSSet, &nFSet ); assert( nBSet + nSSet + nFSet == nVars ); // check variable bounds assert( nSSet + nBSet <= nLutSize ); assert( nLutSize + nSSet + nFSet <= 2*nLutSize - 1 ); nMintsFNew = (1 << (nLutSize + nSSet + nFSet)); // remap minterms Vec_IntFill( vLits, nMintsF, -1 ); for ( m = 0; m < (1 << nVars); m++ ) { mNew = iBSet = iSSet = iFSet = 0; for ( v = 0; v < nVars; v++ ) { Value = ((uSet >> (v << 1)) & 3); if ( Value == 0 ) // FS { if ( ((m >> v) & 1) ) mNew |= 1 << (nLutSize + nSSet + iFSet), pFSet[iFSet] = v; iFSet++; } else if ( Value == 1 ) // BS { if ( ((m >> v) & 1) ) mNew |= 1 << (nSSet + iBSet), pBSet[iBSet] = v; iBSet++; } else if ( Value == 3 ) // SS { if ( ((m >> v) & 1) ) { mNew |= 1 << iSSet; mNew |= 1 << (nLutSize + iSSet); pSSet[iSSet] = v; } iSSet++; } else assert( Value == 0 ); } assert( iBSet == nBSet && iFSet == nFSet ); assert( Vec_IntEntry(vLits, mNew) == -1 ); Vec_IntWriteEntry( vLits, mNew, Abc_TtGetBit(pTruth, m) ); } // find assumptions v = 0; Vec_IntForEachEntry( vLits, Value, m ) { // printf( "%d", (Value >= 0) ? Value : 2 ); if ( Value >= 0 ) Vec_IntWriteEntry( vLits, v++, Abc_Var2Lit(2 * nMintsL + m, !Value) ); } Vec_IntShrink( vLits, v ); // printf( " %d\n", Vec_IntSize(vLits) ); // run SAT solver Value = sat_solver_solve( p, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); if ( Value != l_True ) return 0; if ( pTBound && pTFree ) { // collect config assert( nSSet + nBSet <= nLutSize ); *pTBound = 0; nMintsLNew = (1 << (nSSet + nBSet)); for ( m = 0; m < nMintsLNew; m++ ) if ( sat_solver_var_value(p, m) ) Abc_TtSetBit( pTBound, m ); *pTBound = Abc_Tt6Stretch( *pTBound, nSSet + nBSet ); // collect configs assert( nSSet + nFSet + 1 <= nLutSize ); *pTFree = 0; nMintsLNew = (1 << (1 + nSSet + nFSet)); for ( m = 0; m < nMintsLNew; m++ ) if ( sat_solver_var_value(p, nMintsL+m) ) Abc_TtSetBit( pTFree, m ); *pTFree = Abc_Tt6Stretch( *pTFree, 1 + nSSet + nFSet ); if ( nVars != 6 || nLutSize != 4 ) return 1; // verify the result Res = If_ManSat6Truth( *pTBound, *pTFree, pBSet, nBSet, pSSet, nSSet, pFSet, nFSet ); if ( pTruth[0] != Res ) { Dau_DsdPrintFromTruth( pTruth, nVars ); Dau_DsdPrintFromTruth( &Res, nVars ); Dau_DsdPrintFromTruth( pTBound, nSSet+nBSet ); Dau_DsdPrintFromTruth( pTFree, nSSet+nFSet+1 ); printf( "Verification failed!\n" ); } } return 1; } /**Function************************************************************* Synopsis [Returns config string for the given truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned If_ManSatCheckXYall_int( void * pSat, int nLutSize, word * pTruth, int nVars, Vec_Int_t * vLits ) { unsigned uSet = 0; int nTotal = 2 * nLutSize - 1; int nShared = nTotal - nVars; int i[6], s[4]; assert( nLutSize >= 2 && nLutSize <= 6 ); assert( nLutSize < nVars && nVars <= nTotal ); assert( nShared >= 0 && nShared < nLutSize - 1 ); if ( nLutSize == 2 ) { assert( nShared == 0 ); for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])); if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) ) return uSet; } } else if ( nLutSize == 3 ) { for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])); if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) ) return uSet; } if ( nShared < 1 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])); } } else if ( nLutSize == 4 ) { for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])); if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) ) return uSet; } if ( nShared < 1 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])); } if ( nShared < 2 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])); { for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])); } } } else if ( nLutSize == 5 ) { for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])); if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) ) return uSet; } if ( nShared < 1 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])); } if ( nShared < 2 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])); } if ( nShared < 3 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ ) for ( s[2] = s[1]+1; s[2] < nLutSize; s[2]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])); } } else if ( nLutSize == 6 ) { for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5])); if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet, NULL, NULL, vLits) ) return uSet; } if ( nShared < 1 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])); } if ( nShared < 2 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])); } if ( nShared < 3 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ ) for ( s[2] = s[1]+1; s[2] < nLutSize; s[2]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])); } if ( nShared < 4 ) return 0; for ( i[0] = 0; i[0] < nVars; i[0]++ ) for ( i[1] = i[0]+1; i[1] < nVars; i[1]++ ) for ( i[2] = i[1]+1; i[2] < nVars; i[2]++ ) for ( i[3] = i[2]+1; i[3] < nVars; i[3]++ ) for ( i[4] = i[3]+1; i[4] < nVars; i[4]++ ) for ( i[5] = i[4]+1; i[5] < nVars; i[5]++ ) { uSet = (1 << (2*i[0])) | (1 << (2*i[1])) | (1 << (2*i[2])) | (1 << (2*i[3])) | (1 << (2*i[4])) | (1 << (2*i[5])); for ( s[0] = 0; s[0] < nLutSize; s[0]++ ) for ( s[1] = s[0]+1; s[1] < nLutSize; s[1]++ ) for ( s[2] = s[1]+1; s[2] < nLutSize; s[2]++ ) for ( s[3] = s[1]+1; s[3] < nLutSize; s[3]++ ) if ( If_ManSatCheckXY(pSat, nLutSize, pTruth, nVars, uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])) | (3 << (2*i[s[3]])), NULL, NULL, vLits) ) return uSet | (3 << (2*i[s[0]])) | (3 << (2*i[s[1]])) | (3 << (2*i[s[2]])) | (3 << (2*i[s[3]])); } } return 0; } unsigned If_ManSatCheckXYall( void * pSat, int nLutSize, word * pTruth, int nVars, Vec_Int_t * vLits ) { unsigned uSet = If_ManSatCheckXYall_int( pSat, nLutSize, pTruth, nVars, vLits ); // Dau_DecPrintSet( uSet, nVars, 1 ); return uSet; } /**Function************************************************************* Synopsis [Test procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSatTest2() { int nVars = 6; int nLutSize = 4; sat_solver * p = (sat_solver *)If_ManSatBuildXY( nLutSize ); // char * pDsd = "(abcdefg)"; // char * pDsd = "([a!bc]d!e)"; char * pDsd = "0123456789ABCDEF{abcdef}"; word * pTruth = Dau_DsdToTruth( pDsd, nVars ); word uBound, uFree; Vec_Int_t * vLits = Vec_IntAlloc( 100 ); // unsigned uSet = (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6); // unsigned uSet = (3 << 0) | (1 << 2) | (1 << 8) | (1 << 4); unsigned uSet = (1 << 0) | (3 << 2) | (1 << 4) | (1 << 6); int RetValue = If_ManSatCheckXY( p, nLutSize, pTruth, nVars, uSet, &uBound, &uFree, vLits ); assert( RetValue ); // Abc_TtPrintBinary( pTruth, nVars ); // Abc_TtPrintBinary( &uBound, nLutSize ); // Abc_TtPrintBinary( &uFree, nLutSize ); Dau_DsdPrintFromTruth( pTruth, nVars ); Dau_DsdPrintFromTruth( &uBound, nLutSize ); Dau_DsdPrintFromTruth( &uFree, nLutSize ); sat_solver_delete(p); Vec_IntFree( vLits ); } void If_ManSatTest3() { int nVars = 6; int nLutSize = 4; sat_solver * p = (sat_solver *)If_ManSatBuildXY( nLutSize ); // char * pDsd = "(abcdefg)"; // char * pDsd = "([a!bc]d!e)"; char * pDsd = "0123456789ABCDEF{abcdef}"; word * pTruth = Dau_DsdToTruth( pDsd, nVars ); Vec_Int_t * vLits = Vec_IntAlloc( 100 ); // unsigned uSet = (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6); // unsigned uSet = (3 << 0) | (1 << 2) | (1 << 8) | (1 << 4); unsigned uSet = (1 << 0) | (3 << 2) | (1 << 4) | (1 << 6); uSet = If_ManSatCheckXYall( p, nLutSize, pTruth, nVars, vLits ); Dau_DecPrintSet( uSet, nVars, 1 ); sat_solver_delete(p); Vec_IntFree( vLits ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifSelect.c000066400000000000000000000465071300674244400231250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifSelect.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Cut selection procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifSelect.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prints the logic cone with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ObjConePrint_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) { If_Cut_t * pCut; pCut = If_ObjCutBest(pIfObj); if ( If_CutDataInt(pCut) ) return; Vec_PtrPush( vVisited, pCut ); // insert the worst case If_CutSetDataInt( pCut, ~0 ); // skip in case of primary input if ( If_ObjIsCi(pIfObj) ) return; // compute the functions of the children if ( pIfObj->pEquiv ) If_ObjConePrint_rec( pIfMan, pIfObj->pEquiv, vVisited ); If_ObjConePrint_rec( pIfMan, pIfObj->pFanin0, vVisited ); If_ObjConePrint_rec( pIfMan, pIfObj->pFanin1, vVisited ); printf( "%5d = %5d & %5d | %5d\n", pIfObj->Id, pIfObj->pFanin0->Id, pIfObj->pFanin1->Id, pIfObj->pEquiv ? pIfObj->pEquiv->Id : 0 ); } void If_ObjConePrint( If_Man_t * pIfMan, If_Obj_t * pIfObj ) { If_Cut_t * pCut; If_Obj_t * pLeaf; int i; Vec_PtrClear( pIfMan->vTemp ); If_ObjConePrint_rec( pIfMan, pIfObj, pIfMan->vTemp ); Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) If_CutSetDataInt( pCut, 0 ); // print the leaf variables printf( "Cut " ); pCut = If_ObjCutBest(pIfObj); If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) printf( "%d ", pLeaf->Id ); printf( "\n" ); } /**Function************************************************************* Synopsis [Recursively derives local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManNodeShapeMap_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, Vec_Int_t * vShape ) { If_Cut_t * pCut; If_Obj_t * pTemp; int i, 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 ( i = 0, pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv, i++ ) { iFunc0 = If_ManNodeShapeMap_rec( pIfMan, pTemp->pFanin0, vVisited, vShape ); if ( iFunc0 == ~0 ) continue; iFunc1 = If_ManNodeShapeMap_rec( pIfMan, pTemp->pFanin1, vVisited, vShape ); if ( iFunc1 == ~0 ) continue; // both branches are solved Vec_IntPush( vShape, pIfObj->Id ); Vec_IntPush( vShape, pTemp->Id ); If_CutSetDataInt( pCut, 1 ); break; } return If_CutDataInt(pCut); } int If_ManNodeShapeMap( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape ) { 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 ) { assert( If_CutDataInt( If_ObjCutBest(pLeaf) ) == 0 ); If_CutSetDataInt( If_ObjCutBest(pLeaf), 1 ); } // recursively compute the function while collecting visited cuts Vec_IntClear( vShape ); Vec_PtrClear( pIfMan->vTemp ); iRes = If_ManNodeShapeMap_rec( pIfMan, pIfObj, pIfMan->vTemp, vShape ); if ( iRes == ~0 ) { Abc_Print( -1, "If_ManNodeShapeMap(): 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 1; } /**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int If_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); } int If_ManNodeShapeMap2_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, Vec_Int_t * vShape ) { If_Cut_t * pCut; If_Obj_t * pTemp, * pTempBest = NULL; int i, iFunc, iFunc0, iFunc1, iBest = 0; // 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 ( i = 0, pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv, i++ ) { iFunc0 = If_ManNodeShapeMap2_rec( pIfMan, pTemp->pFanin0, vVisited, vShape ); if ( iFunc0 == ~0 ) continue; iFunc1 = If_ManNodeShapeMap2_rec( pIfMan, pTemp->pFanin1, vVisited, vShape ); if ( iFunc1 == ~0 ) continue; iFunc = iFunc0 | iFunc1; // if ( If_WordCountOnes(iBest) <= If_WordCountOnes(iFunc) ) if ( iBest < iFunc ) { iBest = iFunc; pTempBest = pTemp; } } if ( pTempBest ) { Vec_IntPush( vShape, pIfObj->Id ); Vec_IntPush( vShape, pTempBest->Id ); If_CutSetDataInt( pCut, iBest ); } return If_CutDataInt(pCut); } int If_ManNodeShapeMap2( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape ) { 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), (1 << i) ); // recursively compute the function while collecting visited cuts Vec_IntClear( vShape ); Vec_PtrClear( pIfMan->vTemp ); iRes = If_ManNodeShapeMap2_rec( pIfMan, pIfObj, pIfMan->vTemp, vShape ); if ( iRes == ~0 ) { Abc_Print( -1, "If_ManNodeShapeMap2(): 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 1; } /**Function************************************************************* Synopsis [Collects logic cone with choices] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManConeCollect_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, Vec_Ptr_t * vCone ) { If_Cut_t * pCut; If_Obj_t * pTemp; int iFunc0, iFunc1; int fRootAdded = 0; int fNodeAdded = 0; // 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 = If_ManConeCollect_rec( pIfMan, pTemp->pFanin0, vVisited, vCone ); if ( iFunc0 == ~0 ) continue; iFunc1 = If_ManConeCollect_rec( pIfMan, pTemp->pFanin1, vVisited, vCone ); if ( iFunc1 == ~0 ) continue; fNodeAdded = 1; If_CutSetDataInt( pCut, 1 ); Vec_PtrPush( vCone, pTemp ); if ( fRootAdded == 0 && pTemp == pIfObj ) fRootAdded = 1; } if ( fNodeAdded && !fRootAdded ) Vec_PtrPush( vCone, pIfObj ); return If_CutDataInt(pCut); } Vec_Ptr_t * If_ManConeCollect( If_Man_t * pIfMan, If_Obj_t * pIfObj, If_Cut_t * pCut ) { Vec_Ptr_t * vCone; If_Obj_t * pLeaf; int i, RetValue; // set the leaf variables If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) { assert( If_CutDataInt( If_ObjCutBest(pLeaf) ) == 0 ); If_CutSetDataInt( If_ObjCutBest(pLeaf), 1 ); } // recursively compute the function while collecting visited cuts vCone = Vec_PtrAlloc( 100 ); Vec_PtrClear( pIfMan->vTemp ); RetValue = If_ManConeCollect_rec( pIfMan, pIfObj, pIfMan->vTemp, vCone ); assert( RetValue ); // 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 vCone; } /**Function************************************************************* Synopsis [Adding clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void sat_solver_add_choice( sat_solver * pSat, int iVar, Vec_Int_t * vVars ) { int * pVars = Vec_IntArray(vVars); int nVars = Vec_IntSize(vVars); int i, k, Lits[2], Value; assert( Vec_IntSize(vVars) < Vec_IntCap(vVars) ); // create literals for ( i = 0; i < nVars; i++ ) pVars[i] = Abc_Var2Lit( pVars[i], 0 ); pVars[i] = Abc_Var2Lit( iVar, 1 ); // add clause Value = sat_solver_addclause( pSat, pVars, pVars + nVars + 1 ); assert( Value ); // undo literals for ( i = 0; i < nVars; i++ ) pVars[i] = Abc_Lit2Var( pVars[i] ); // add !out => !in Lits[0] = Abc_Var2Lit( iVar, 0 ); for ( i = 0; i < nVars; i++ ) { Lits[1] = Abc_Var2Lit( pVars[i], 1 ); Value = sat_solver_addclause( pSat, Lits, Lits + 2 ); assert( Value ); } // add excluvisity for ( i = 0; i < nVars; i++ ) for ( k = i+1; k < nVars; k++ ) { Lits[0] = Abc_Var2Lit( pVars[i], 1 ); Lits[1] = Abc_Var2Lit( pVars[k], 1 ); Value = sat_solver_addclause( pSat, Lits, Lits + 2 ); assert( Value ); } } static inline int If_ObjSatVar( If_Obj_t * pIfObj ) { return If_CutDataInt(If_ObjCutBest(pIfObj)); } static inline void If_ObjSetSatVar( If_Obj_t * pIfObj, int v ) { If_CutSetDataInt( If_ObjCutBest(pIfObj), v ); } /**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManNodeShape2_rec( sat_solver * pSat, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape ) { If_Obj_t * pTemp; assert( sat_solver_var_value(pSat, If_ObjSatVar(pIfObj)) == 1 ); if ( pIfObj->fMark ) return; pIfObj->fMark = 1; for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) if ( sat_solver_var_value(pSat, If_ObjSatVar(pTemp)+1) == 1 ) break; assert( pTemp != NULL ); If_ManNodeShape2_rec( pSat, pIfMan, pTemp->pFanin0, vShape ); If_ManNodeShape2_rec( pSat, pIfMan, pTemp->pFanin1, vShape ); Vec_IntPush( vShape, pIfObj->Id ); Vec_IntPush( vShape, pTemp->Id ); } /**Function************************************************************* Synopsis [Solve the problem of selecting choices for the given cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManNodeShapeSat( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape ) { sat_solver * pSat; If_Cut_t * pCut; Vec_Ptr_t * vCone; Vec_Int_t * vFanins; If_Obj_t * pObj, * pTemp; int i, Lit, Status; // get best cut pCut = If_ObjCutBest(pIfObj); assert( pCut->nLeaves > 1 ); // collect the cone vCone = If_ManConeCollect( pIfMan, pIfObj, pCut ); // assign SAT variables // EXTERNAL variable is even numbered // INTERNAL variable is odd numbered If_CutForEachLeaf( pIfMan, pCut, pObj, i ) { assert( If_ObjSatVar(pObj) == 0 ); If_ObjSetSatVar( pObj, 2*(i+1) ); } Vec_PtrForEachEntry( If_Obj_t *, vCone, pObj, i ) { assert( If_ObjSatVar(pObj) == 0 ); If_ObjSetSatVar( pObj, 2*(i+1+pCut->nLeaves) ); } // start SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, 2 * (pCut->nLeaves + Vec_PtrSize(vCone) + 1) ); // add constraints vFanins = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( If_Obj_t *, vCone, pObj, i ) { assert( If_ObjIsAnd(pObj) ); Vec_IntClear( vFanins ); for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) if ( If_ObjSatVar(pTemp) ) Vec_IntPush( vFanins, If_ObjSatVar(pTemp)+1 ); // internal assert( Vec_IntSize(vFanins) > 0 ); sat_solver_add_choice( pSat, If_ObjSatVar(pObj), vFanins ); // external assert( If_ObjSatVar(pObj) > 0 ); // sat_solver_add_and( pSat, If_ObjSatVar(pObj)+1, If_ObjSatVar(pObj->pFanin0), If_ObjSatVar(pObj->pFanin1), 0, 0, 0 ); if ( If_ObjSatVar(pObj->pFanin0) > 0 && If_ObjSatVar(pObj->pFanin1) > 0 ) { int Lits[2]; Lits[0] = Abc_Var2Lit( If_ObjSatVar(pObj)+1, 1 ); Lits[1] = Abc_Var2Lit( If_ObjSatVar(pObj->pFanin0), 0 ); Status = sat_solver_addclause( pSat, Lits, Lits + 2 ); assert( Status ); Lits[0] = Abc_Var2Lit( If_ObjSatVar(pObj)+1, 1 ); Lits[1] = Abc_Var2Lit( If_ObjSatVar(pObj->pFanin1), 0 ); Status = sat_solver_addclause( pSat, Lits, Lits + 2 ); assert( Status ); } } Vec_IntFree( vFanins ); // set cut variables to 1 pCut = If_ObjCutBest(pIfObj); If_CutForEachLeaf( pIfMan, pCut, pObj, i ) { Lit = Abc_Var2Lit( If_ObjSatVar(pObj), 0 ); // external Status = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( Status ); } // set output variable to 1 Lit = Abc_Var2Lit( If_ObjSatVar(pIfObj), 0 ); // external Status = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( Status ); // solve the problem Status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); assert( Status == l_True ); // mark cut nodes If_CutForEachLeaf( pIfMan, pCut, pObj, i ) { assert( pObj->fMark == 0 ); pObj->fMark = 1; } // select the node's shape Vec_IntClear( vShape ); assert( pIfObj->fMark == 0 ); If_ManNodeShape2_rec( pSat, pIfMan, pIfObj, vShape ); // cleanup sat_solver_delete( pSat ); If_CutForEachLeaf( pIfMan, pCut, pObj, i ) { If_ObjSetSatVar( pObj, 0 ); pObj->fMark = 0; } Vec_PtrForEachEntry( If_Obj_t *, vCone, pObj, i ) { If_ObjSetSatVar( pObj, 0 ); pObj->fMark = 0; } Vec_PtrFree( vCone ); return 1; } /**Function************************************************************* Synopsis [Verify that the shape is correct.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManCheckShape( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape ) { If_Cut_t * pCut; If_Obj_t * pLeaf; int i, Entry1, Entry2, RetValue = 1; // check that the marks are not set pCut = If_ObjCutBest(pIfObj); If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) assert( pLeaf->fMark == 0 ); // set the marks of the shape Vec_IntForEachEntryDouble( vShape, Entry1, Entry2, i ) { pLeaf = If_ManObj(pIfMan, Entry2); pLeaf->pFanin0->fMark = 1; pLeaf->pFanin1->fMark = 1; } // check that the leaves are marked If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) if ( pLeaf->fMark == 0 ) RetValue = 0; else pLeaf->fMark = 0; // clean the inner marks Vec_IntForEachEntryDouble( vShape, Entry1, Entry2, i ) { pLeaf = If_ManObj(pIfMan, Entry2); pLeaf->pFanin0->fMark = 0; pLeaf->pFanin1->fMark = 0; } return RetValue; } /**Function************************************************************* Synopsis [Recursively compute the set of nodes supported by the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManNodeShape( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vShape, int fExact ) { int RetValue; // if ( pIfMan->nChoices == 0 ) { RetValue = If_ManNodeShapeMap( pIfMan, pIfObj, vShape ); assert( RetValue ); if ( !fExact || If_ManCheckShape(pIfMan, pIfObj, vShape) ) return 1; } // if ( pIfObj->Id == 1254 && If_ObjCutBest(pIfObj)->nLeaves == 7 ) // If_ObjConePrint( pIfMan, pIfObj ); RetValue = If_ManNodeShapeMap2( pIfMan, pIfObj, vShape ); assert( RetValue ); RetValue = If_ManCheckShape(pIfMan, pIfObj, vShape); // assert( RetValue ); // printf( "%d", RetValue ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifSeq.c000066400000000000000000000264651300674244400224370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifSeq.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Sequential mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifSeq.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern abctime s_MappingTime; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prepares for sequential mapping by linking the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManPrepareMappingSeq( If_Man_t * p ) { If_Obj_t * pObjLi, * pObjLo; int i; // link the latch outputs (CIs) directly to the drivers of latch inputs (COs) for ( i = 0; i < p->pPars->nLatchesCi; i++ ) { pObjLi = If_ManLi( p, i ); pObjLo = If_ManLo( p, i ); pObjLo->pFanin0 = If_ObjFanin0( pObjLi ); pObjLo->fCompl0 = If_ObjFaninC0( pObjLi ); } } /**Function************************************************************* Synopsis [Collects latches in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches ) { if ( !If_ObjIsLatch(pObj) ) return; if ( pObj->fMark ) return; pObj->fMark = 1; If_ManCollectLatches_rec( pObj->pFanin0, vLatches ); Vec_PtrPush( vLatches, pObj ); } /**Function************************************************************* Synopsis [Collects latches in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p ) { Vec_Ptr_t * vLatches; If_Obj_t * pObj; int i; // collect latches vLatches = Vec_PtrAlloc( p->pPars->nLatchesCi ); If_ManForEachLatchOutput( p, pObj, i ) If_ManCollectLatches_rec( pObj, vLatches ); // clean marks Vec_PtrForEachEntry( If_Obj_t *, vLatches, pObj, i ) pObj->fMark = 0; assert( Vec_PtrSize(vLatches) == p->pPars->nLatchesCi ); return vLatches; } /**Function************************************************************* Synopsis [Performs one pass of l-value computation over all nodes.] Description [Experimentally it was found that checking POs changes is not enough to detect the convergence of l-values in the network.] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter ) { If_Obj_t * pObj; int i; abctime clk = Abc_Clock(); int fVeryVerbose = 0; int fChange = 0; if ( nIter == 1 ) { // if some latches depend on PIs, update their values Vec_PtrForEachEntry( If_Obj_t *, p->vLatchOrder, pObj, i ) { If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period ); If_ObjSetArrTime( pObj, If_ObjLValue(pObj) ); } } // map the internal nodes p->nCutsMerged = 0; If_ManForEachNode( p, pObj, i ) { If_ObjPerformMappingAnd( p, pObj, 0, 0, 0 ); if ( pObj->fRepr ) If_ObjPerformMappingChoice( p, pObj, 0, 0 ); } // postprocess the mapping //Abc_Print( 1, "Itereation %d: \n", nIter ); If_ManForEachNode( p, pObj, i ) { // update the LValues stored separately if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon ) { If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay ); fChange = 1; } //Abc_Print( 1, "%d ", (int)If_ObjLValue(pObj) ); // reset the visit counters assert( pObj->nVisits == 0 ); pObj->nVisits = pObj->nVisitsCopy; } //Abc_Print( 1, "\n" ); // propagate LValues over the registers Vec_PtrForEachEntry( If_Obj_t *, p->vLatchOrder, pObj, i ) { If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period ); If_ObjSetArrTime( pObj, If_ObjLValue(pObj) ); } // compute area and delay If_ManMarkMapping( p ); if ( fVeryVerbose ) { p->RequiredGlo = If_ManDelayMax( p, 1 ); // p->AreaGlo = If_ManScanMapping(p); Abc_Print( 1, "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ", nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged ); Abc_PrintTime( 1, "T", Abc_Clock() - clk ); } return fChange; } /**Function************************************************************* Synopsis [Returns 1 if retiming with this clock period is feasible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManBinarySearchPeriod( If_Man_t * p ) { If_Obj_t * pObj; int i, c, fConverged; // int fResetRefs = 0; p->nAttempts++; // reset initial LValues (PIs to 0; others to -inf) If_ManForEachObj( p, pObj, i ) { If_ObjSetLValue( pObj, (float)-IF_INFINITY ); If_ObjSetArrTime( pObj, (float)-IF_INFINITY ); // undo any previous mapping, except for CIs if ( If_ObjIsAnd(pObj) ) If_ObjCutBest(pObj)->nLeaves = 0; } pObj = If_ManConst1( p ); If_ObjSetLValue( pObj, (float)0.0 ); If_ObjSetArrTime( pObj, (float)0.0 ); If_ManForEachPi( p, pObj, i ) { pObj = If_ManCi( p, i ); If_ObjSetLValue( pObj, (float)0.0 ); If_ObjSetArrTime( pObj, (float)0.0 ); } // update all values iteratively fConverged = 0; for ( c = 1; c <= p->nMaxIters; c++ ) { if ( !If_ManPerformMappingRoundSeq( p, c ) ) { p->RequiredGlo = If_ManDelayMax( p, 1 ); fConverged = 1; break; } p->RequiredGlo = If_ManDelayMax( p, 1 ); //Abc_Print( 1, "Global = %d \n", (int)p->RequiredGlo ); if ( p->RequiredGlo > p->Period + p->fEpsilon ) break; } // report the results If_ManMarkMapping( p ); if ( p->pPars->fVerbose ) { // p->AreaGlo = If_ManScanMapping(p); Abc_Print( 1, "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period ); if ( fConverged ) Abc_Print( 1, " Feasible" ); else if ( c > p->nMaxIters ) Abc_Print( 1, "Infeasible (timeout)" ); else Abc_Print( 1, "Infeasible" ); Abc_Print( 1, "\n" ); } return fConverged; } /**Function************************************************************* Synopsis [Performs binary search for the optimal clock period.] Description [Assumes that FiMin is infeasible while FiMax is feasible.] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax ) { assert( FiMin < FiMax ); if ( FiMin + 1 == FiMax ) return FiMax; // compute the median p->Period = FiMin + (FiMax - FiMin)/2; if ( If_ManBinarySearchPeriod( p ) ) return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible else return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible } /**Function************************************************************* Synopsis [Performs sequential mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManPerformMappingSeqPost( If_Man_t * p ) { If_Obj_t * pObjLi, * pObjLo, * pObj; int i; assert( 0 ); // set arrival times assert( p->pPars->pTimesArr != NULL ); If_ManForEachLatchOutput( p, pObjLo, i ) p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo); // set the required times assert( p->pPars->pTimesReq == NULL ); p->pPars->pTimesReq = ABC_ALLOC( float, If_ManCoNum(p) ); If_ManForEachPo( p, pObj, i ) p->pPars->pTimesReq[i] = p->RequiredGlo2; If_ManForEachLatchInput( p, pObjLi, i ) p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi)); // undo previous mapping If_ManForEachObj( p, pObj, i ) if ( If_ObjIsAnd(pObj) ) If_ObjCutBest(pObj)->nLeaves = 0; // map again combinationally // p->pPars->fSeqMap = 0; If_ManPerformMappingComb( p ); // p->pPars->fSeqMap = 1; } /**Function************************************************************* Synopsis [Performs sequential mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPerformMappingSeq( If_Man_t * p ) { abctime clkTotal = Abc_Clock(); int PeriodBest; p->SortMode = 0; // perform combinational mapping to get the upper bound on the clock period If_ManPerformMappingRound( p, 1, 0, 0, 1, NULL ); p->RequiredGlo = If_ManDelayMax( p, 0 ); p->RequiredGlo2 = p->RequiredGlo; // set direct linking of latches with their inputs If_ManPrepareMappingSeq( p ); // collect latches p->vLatchOrder = If_ManCollectLatches( p ); // set parameters p->nCutsUsed = p->pPars->nCutsMax; p->nAttempts = 0; p->nMaxIters = 50; p->Period = (int)p->RequiredGlo; // make sure the clock period works if ( !If_ManBinarySearchPeriod( p ) ) { Abc_Print( 1, "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" ); return 0; } // perform binary search PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period ); // recompute the best l-values if ( p->Period != PeriodBest ) { p->Period = PeriodBest; if ( !If_ManBinarySearchPeriod( p ) ) { Abc_Print( 1, "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" ); return 0; } } // if ( p->pPars->fVerbose ) { Abc_Print( 1, "The best clock period is %3d. ", p->Period ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } p->RequiredGlo = (float)(PeriodBest); // postprocess it using combinational mapping If_ManPerformMappingSeqPost( p ); s_MappingTime = Abc_Clock() - clkTotal; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifTest.c000066400000000000000000000236551300674244400226240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifTest.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifTest.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "aig/gia/gia.h" #ifdef ABC_USE_PTHREADS #ifdef _WIN32 #include "../lib/pthread.h" #else #include #include #endif #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifndef ABC_USE_PTHREADS // do nothing #else // pthreads are used static inline word * Gia_ParTestObj( Gia_Man_t * p, int Id ) { return (word *)p->pData + Id * p->iData; } static inline void Gia_ParTestAlloc( Gia_Man_t * p, int nWords ) { assert( !p->pData ); p->pData = (unsigned *)ABC_ALLOC(word, Gia_ManObjNum(p) * nWords); p->iData = nWords; } static inline void Gia_ParTestFree( Gia_Man_t * p ) { ABC_FREE( p->pData ); p->iData = 0; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ParComputeSignature( Gia_Man_t * p, int nWords ) { Gia_Obj_t * pObj; word * pData, Sign = 0; int i, k; Gia_ManForEachCo( p, pObj, k ) { pData = Gia_ParTestObj( p, Gia_ObjId(p, pObj) ); for ( i = 0; i < p->iData; i++ ) Sign ^= pData[i]; } Abc_TtPrintHexRev( stdout, &Sign, 6 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ParTestSimulateInit( Gia_Man_t * p ) { Gia_Obj_t * pObj; word * pData; int i, k; Gia_ManForEachCi( p, pObj, k ) { pData = Gia_ParTestObj( p, Gia_ObjId(p, pObj) ); for ( i = 0; i < p->iData; i++ ) pData[i] = Gia_ManRandomW( 0 ); } } void Gia_ParTestSimulateObj( Gia_Man_t * p, int Id ) { Gia_Obj_t * pObj = Gia_ManObj( p, Id ); word * pData, * pData0, * pData1; int i; if ( Gia_ObjIsAnd(pObj) ) { pData = Gia_ParTestObj( p, Id ); pData0 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) ); pData1 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) ); if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) for ( i = 0; i < p->iData; i++ ) pData[i] = ~(pData0[i] | pData1[i]); else for ( i = 0; i < p->iData; i++ ) pData[i] = ~pData0[i] & pData1[i]; } else { if ( Gia_ObjFaninC1(pObj) ) for ( i = 0; i < p->iData; i++ ) pData[i] = pData0[i] & ~pData1[i]; else for ( i = 0; i < p->iData; i++ ) pData[i] = pData0[i] & pData1[i]; } } else if ( Gia_ObjIsCo(pObj) ) { pData = Gia_ParTestObj( p, Id ); pData0 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) ); if ( Gia_ObjFaninC0(pObj) ) for ( i = 0; i < p->iData; i++ ) pData[i] = ~pData0[i]; else for ( i = 0; i < p->iData; i++ ) pData[i] = pData0[i]; } else if ( Gia_ObjIsCi(pObj) ) { } else if ( Gia_ObjIsConst0(pObj) ) { pData = Gia_ParTestObj( p, Id ); for ( i = 0; i < p->iData; i++ ) pData[i] = 0; } else assert( 0 ); } void Gia_ParTestSimulate( Gia_Man_t * p, int nWords ) { Gia_Obj_t * pObj; int i; Gia_ManRandom( 1 ); Gia_ParTestAlloc( p, nWords ); Gia_ParTestSimulateInit( p ); Gia_ManForEachObj( p, pObj, i ) Gia_ParTestSimulateObj( p, i ); // Gia_ParComputeSignature( p, nWords ); printf( " " ); Gia_ParTestFree( p ); } /**Function************************************************************* Synopsis [Assigns references.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_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 ); else if ( Gia_ObjIsCo(pObj) ) Vec_IntPush( vCounts, 1 ); else Vec_IntPush( vCounts, 0 ); } assert( Vec_IntSize(vCounts) == Gia_ManObjNum(p) ); return vCounts; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define PAR_THR_MAX 100 typedef struct Par_ThData_t_ { Gia_Man_t * p; int Id; int Status; } Par_ThData_t; void * Gia_ParWorkerThread( void * pArg ) { Par_ThData_t * pThData = (Par_ThData_t *)pArg; volatile int * pPlace = &pThData->Status; while ( 1 ) { while ( *pPlace == 0 ); assert( pThData->Status == 1 ); if ( pThData->Id == -1 ) { pthread_exit( NULL ); assert( 0 ); return NULL; } assert( pThData->Id >= 0 ); Gia_ParTestSimulateObj( pThData->p, pThData->Id ); pThData->Status = 0; } assert( 0 ); return NULL; } void Gia_ParTestSimulate2( Gia_Man_t * p, int nWords, int nProcs ) { pthread_t WorkerThread[PAR_THR_MAX]; Par_ThData_t ThData[PAR_THR_MAX]; Vec_Int_t * vStack, * vFanins; int i, k, iFan, status, nCountFanins; assert( nProcs <= PAR_THR_MAX ); Gia_ManRandom( 1 ); Gia_ParTestAlloc( p, nWords ); Gia_ParTestSimulateInit( p ); // start the stack vStack = Vec_IntAlloc( 1000 ); Vec_IntForEachEntryReverse( p->vCis, iFan, i ) Vec_IntPush( vStack, iFan ); Vec_IntPush( vStack, 0 ); Gia_ManStaticFanoutStart( p ); vFanins = Gia_ManCreateFaninCounts( p ); nCountFanins = Vec_IntSum(vFanins); // start the threads for ( i = 0; i < nProcs; i++ ) { ThData[i].p = p; ThData[i].Id = -1; ThData[i].Status = 0; status = pthread_create( WorkerThread + i, NULL, Gia_ParWorkerThread, (void *)(ThData + i) ); assert( status == 0 ); } while ( nCountFanins > 0 || Vec_IntSize(vStack) > 0 ) { for ( i = 0; i < nProcs; i++ ) { if ( ThData[i].Status ) continue; assert( ThData[i].Status == 0 ); if ( ThData[i].Id >= 0 ) { Gia_ObjForEachFanoutStaticId( p, ThData[i].Id, iFan, k ) { 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; } } } Vec_IntForEachEntry( vFanins, iFan, k ) if ( iFan != 0 ) { printf( "%d -> %d ", k, iFan ); Gia_ObjPrint( p, Gia_ManObj(p, k) ); } // assert( Vec_IntSum(vFanins) == 0 ); // stop the threads while ( 1 ) { for ( i = 0; i < nProcs; i++ ) if ( ThData[i].Status ) break; if ( i == nProcs ) break; } for ( i = 0; i < nProcs; i++ ) { assert( ThData[i].Status == 0 ); ThData[i].Id = -1; ThData[i].Status = 1; } Gia_ManStaticFanoutStop( p ); Vec_IntFree( vStack ); Vec_IntFree( vFanins ); // Gia_ParComputeSignature( p, nWords ); printf( " " ); Gia_ParTestFree( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ParTest( Gia_Man_t * p, int nWords, int nProcs ) { abctime clk; printf( "Trying with %d words and %d threads. ", nWords, nProcs ); printf( "Memory usage = %.2f MB\n", (8.0*nWords*Gia_ManObjNum(p))/(1<<20) ); clk = Abc_Clock(); Gia_ParTestSimulate( p, nWords ); Abc_PrintTime( 1, "Regular time", Abc_Clock() - clk ); clk = Abc_Clock(); Gia_ParTestSimulate2( p, nWords, nProcs ); Abc_PrintTime( 1, "Special time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #endif // pthreads are used ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifTime.c000066400000000000000000000445741300674244400226060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifTime.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Computation of delay paramters depending on the library.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifTime.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sorts the pins in the decreasing order of delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutSortInputPins( If_Man_t * p, If_Cut_t * pCut, int * pPinPerm, float * pPinDelays ) { If_Obj_t * pLeaf; int i, j, best_i, temp; // start the trivial permutation and collect pin delays If_CutForEachLeaf( p, pCut, pLeaf, i ) { pPinPerm[i] = i; pPinDelays[i] = If_ObjCutBest(pLeaf)->Delay; } // 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 < (int)pCut->nLeaves-1; i++ ) { best_i = i; for ( j = i+1; j < (int)pCut->nLeaves; 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( pPinPerm[0] < (int)pCut->nLeaves ); for ( i = 1; i < (int)pCut->nLeaves; i++ ) { assert( pPinPerm[i] < (int)pCut->nLeaves ); assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); } */ } /**Function************************************************************* Synopsis [Computes delay.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_CutDelay( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut ) { static int pPinPerm[IF_MAX_LUTSIZE]; static float pPinDelays[IF_MAX_LUTSIZE]; char * pPerm = If_CutPerm( pCut ); If_Obj_t * pLeaf; float Delay, DelayCur; float * pLutDelays; int i, Shift, Pin2PinDelay;//, iLeaf; Delay = -IF_FLOAT_LARGE; if ( pCut->fAndCut ) { If_CutForEachLeaf( p, pCut, pLeaf, i ) { DelayCur = If_ObjCutBest(pLeaf)->Delay + p->pPars->nAndDelay; Delay = IF_MAX( Delay, DelayCur ); } } else if ( p->pPars->pLutLib ) { assert( !p->pPars->fLiftLeaves ); pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves]; if ( p->pPars->pLutLib->fVarPinDelays ) { // compute the delay using sorted pins If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { DelayCur = pPinDelays[pPinPerm[i]] + pLutDelays[i]; Delay = IF_MAX( Delay, DelayCur ); } } else { If_CutForEachLeaf( p, pCut, pLeaf, i ) { DelayCur = If_ObjCutBest(pLeaf)->Delay + pLutDelays[0]; Delay = IF_MAX( Delay, DelayCur ); } } } else { if ( pCut->fUser ) { assert( !p->pPars->fLiftLeaves ); If_CutForEachLeaf( p, pCut, pLeaf, i ) { Pin2PinDelay = pPerm ? (pPerm[i] == IF_BIG_CHAR ? -IF_BIG_CHAR : pPerm[i]) : 1; DelayCur = If_ObjCutBest(pLeaf)->Delay + (float)Pin2PinDelay; Delay = IF_MAX( Delay, DelayCur ); } } else { if ( p->pPars->fLiftLeaves ) { If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i ) { DelayCur = If_ObjCutBest(pLeaf)->Delay - Shift * p->Period; Delay = IF_MAX( Delay, DelayCur + 1.0 ); } } else { If_CutForEachLeaf( p, pCut, pLeaf, i ) { DelayCur = If_ObjCutBest(pLeaf)->Delay + 1.0; Delay = IF_MAX( Delay, DelayCur ); } } } } return Delay; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, float ObjRequired ) { static int pPinPerm[IF_MAX_LUTSIZE]; static float pPinDelays[IF_MAX_LUTSIZE]; If_Obj_t * pLeaf; float * pLutDelays; float Required; int i, Pin2PinDelay;//, iLeaf; assert( !p->pPars->fLiftLeaves ); // compute the pins if ( pCut->fAndCut ) { If_CutForEachLeaf( p, pCut, pLeaf, i ) pLeaf->Required = IF_MIN( pLeaf->Required, ObjRequired - p->pPars->nAndDelay ); } else if ( p->pPars->pLutLib ) { pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves]; if ( p->pPars->pLutLib->fVarPinDelays ) { // compute the delay using sorted pins If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { Required = ObjRequired - pLutDelays[i]; pLeaf = If_ManObj( p, pCut->pLeaves[pPinPerm[i]] ); pLeaf->Required = IF_MIN( pLeaf->Required, Required ); } } else { Required = ObjRequired; If_CutForEachLeaf( p, pCut, pLeaf, i ) pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] ); } } else { if ( pCut->fUser ) { char Perm[IF_MAX_FUNC_LUTSIZE], * pPerm = Perm; if ( p->pPars->fDelayOpt ) { int Delay = If_CutSopBalancePinDelays( p, pCut, pPerm ); assert( Delay == (int)pCut->Delay ); } else if ( p->pPars->fDelayOptLut ) { int Delay = If_CutLutBalancePinDelays( p, pCut, pPerm ); assert( Delay == (int)pCut->Delay ); } else if ( p->pPars->fDsdBalance ) { int Delay = If_CutDsdBalancePinDelays( p, pCut, pPerm ); assert( Delay == (int)pCut->Delay ); } else pPerm = If_CutPerm(pCut); If_CutForEachLeaf( p, pCut, pLeaf, i ) { Pin2PinDelay = pPerm ? (pPerm[i] == IF_BIG_CHAR ? -IF_BIG_CHAR : pPerm[i]) : 1; Required = ObjRequired - (float)Pin2PinDelay; pLeaf->Required = IF_MIN( pLeaf->Required, Required ); } } else { Required = ObjRequired; If_CutForEachLeaf( p, pCut, pLeaf, i ) pLeaf->Required = IF_MIN( pLeaf->Required, Required - (float)1.0 ); } } } /**Function************************************************************* Synopsis [Returns the max delay of the POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_ManDelayMax( If_Man_t * p, int fSeq ) { If_Obj_t * pObj; float DelayBest; int i; if ( p->pPars->fLatchPaths && (p->pPars->nLatchesCi == 0 || p->pPars->nLatchesCo == 0) ) { Abc_Print( 0, "Delay optimization of latch path is not performed because there is no latches.\n" ); p->pPars->fLatchPaths = 0; } DelayBest = -IF_FLOAT_LARGE; if ( fSeq ) { assert( p->pPars->nLatchesCi > 0 ); If_ManForEachPo( p, pObj, i ) if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); } else if ( p->pPars->fLatchPaths ) { If_ManForEachLatchInput( p, pObj, i ) if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); } else { If_ManForEachCo( p, pObj, i ) if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); } return DelayBest; } /**Function************************************************************* Synopsis [Computes the required times of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManComputeRequired( If_Man_t * p ) { If_Obj_t * pObj; int i, Counter; float reqTime; // compute area, clean required times, collect nodes used in the mapping // p->AreaGlo = If_ManScanMapping( p ); If_ManMarkMapping( p ); if ( p->pManTim == NULL ) { // consider the case when the required times are given if ( p->pPars->pTimesReq && !p->pPars->fAreaOnly ) { // make sure that the required time hold Counter = 0; If_ManForEachCo( p, pObj, i ) { if ( If_ObjArrTime(If_ObjFanin0(pObj)) > p->pPars->pTimesReq[i] + p->fEpsilon ) { If_ObjFanin0(pObj)->Required = If_ObjArrTime(If_ObjFanin0(pObj)); Counter++; // Abc_Print( 0, "Required times are violated for output %d (arr = %d; req = %d).\n", // i, (int)If_ObjArrTime(If_ObjFanin0(pObj)), (int)p->pPars->pTimesReq[i] ); } else If_ObjFanin0(pObj)->Required = p->pPars->pTimesReq[i]; } if ( Counter && !p->fReqTimeWarn ) { Abc_Print( 0, "Required times are exceeded at %d output%s. The earliest arrival times are used.\n", Counter, Counter > 1 ? "s":"" ); p->fReqTimeWarn = 1; } } else { // get the global required times p->RequiredGlo = If_ManDelayMax( p, 0 ); // find new delay target if ( p->pPars->nRelaxRatio && p->pPars->DelayTargetNew == 0 ) p->pPars->DelayTargetNew = p->RequiredGlo * (100.0 + p->pPars->nRelaxRatio) / 100.0; // update the required times according to the target if ( p->pPars->DelayTarget != -1 ) { if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon ) { if ( p->fNextRound == 0 ) { p->fNextRound = 1; Abc_Print( 0, "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget ); } } else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon ) { if ( p->fNextRound == 0 ) { p->fNextRound = 1; // Abc_Print( 0, "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget ); } p->RequiredGlo = p->pPars->DelayTarget; } } else if ( p->pPars->DelayTargetNew > 0 ) // relax the required times p->RequiredGlo = p->pPars->DelayTargetNew; // do not propagate required times if area minimization is requested if ( p->pPars->fAreaOnly ) return; // set the required times for the POs if ( p->pPars->fDoAverage ) { if ( p->pPars->nRelaxRatio ) { If_ManForEachCo( p, pObj, i ) If_ObjFanin0(pObj)->Required = If_ObjArrTime(If_ObjFanin0(pObj)) * (100.0 + p->pPars->nRelaxRatio) / 100.0; } else { If_ManForEachCo( p, pObj, i ) If_ObjFanin0(pObj)->Required = If_ObjArrTime(If_ObjFanin0(pObj)); } } else if ( p->pPars->fLatchPaths ) { If_ManForEachLatchInput( p, pObj, i ) If_ObjFanin0(pObj)->Required = p->RequiredGlo; } else { If_ManForEachCo( p, pObj, i ) If_ObjFanin0(pObj)->Required = p->RequiredGlo; } } // go through the nodes in the reverse topological order // Vec_PtrForEachEntry( If_Obj_t *, p->vMapped, pObj, i ) // If_CutPropagateRequired( p, pObj, If_ObjCutBest(pObj), pObj->Required ); If_ManForEachObjReverse( p, pObj, i ) { if ( pObj->nRefs == 0 ) continue; If_CutPropagateRequired( p, pObj, If_ObjCutBest(pObj), pObj->Required ); } } else { // get the global required times p->RequiredGlo = If_ManDelayMax( p, 0 ); // find new delay target if ( p->pPars->nRelaxRatio && p->pPars->DelayTargetNew == 0 ) p->pPars->DelayTargetNew = p->RequiredGlo * (100.0 + p->pPars->nRelaxRatio) / 100.0; // update the required times according to the target if ( p->pPars->DelayTarget != -1 ) { if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon ) { if ( p->fNextRound == 0 ) { p->fNextRound = 1; Abc_Print( 0, "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget ); } } else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon ) { if ( p->fNextRound == 0 ) { p->fNextRound = 1; // Abc_Print( 0, "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget ); } p->RequiredGlo = p->pPars->DelayTarget; } } else if ( p->pPars->DelayTargetNew > 0 ) // relax the required times p->RequiredGlo = p->pPars->DelayTargetNew; // do not propagate required times if area minimization is requested if ( p->pPars->fAreaOnly ) return; // set the required times for the POs Tim_ManIncrementTravId( p->pManTim ); if ( p->vCoAttrs ) { assert( If_ManCoNum(p) == Vec_IntSize(p->vCoAttrs) ); If_ManForEachCo( p, pObj, i ) { if ( Vec_IntEntry(p->vCoAttrs, i) == -1 ) // -1=internal continue; if ( Vec_IntEntry(p->vCoAttrs, i) == 0 ) // 0=optimize Tim_ManSetCoRequired( p->pManTim, i, p->RequiredGlo ); else if ( Vec_IntEntry(p->vCoAttrs, i) == 1 ) // 1=keep Tim_ManSetCoRequired( p->pManTim, i, If_ObjArrTime(If_ObjFanin0(pObj)) ); else if ( Vec_IntEntry(p->vCoAttrs, i) == 2 ) // 2=relax Tim_ManSetCoRequired( p->pManTim, i, IF_FLOAT_LARGE ); else assert( 0 ); } } else if ( p->pPars->fDoAverage ) { if ( p->pPars->nRelaxRatio ) { If_ManForEachCo( p, pObj, i ) Tim_ManSetCoRequired( p->pManTim, i, If_ObjArrTime(If_ObjFanin0(pObj)) * (100.0 + p->pPars->nRelaxRatio) / 100.0 ); } else { If_ManForEachCo( p, pObj, i ) Tim_ManSetCoRequired( p->pManTim, i, If_ObjArrTime(If_ObjFanin0(pObj)) ); } } else if ( p->pPars->fLatchPaths ) { If_ManForEachPo( p, pObj, i ) Tim_ManSetCoRequired( p->pManTim, i, IF_FLOAT_LARGE ); If_ManForEachLatchInput( p, pObj, i ) Tim_ManSetCoRequired( p->pManTim, i, p->RequiredGlo ); } else { Tim_ManInitPoRequiredAll( p->pManTim, p->RequiredGlo ); // If_ManForEachCo( p, pObj, i ) // Tim_ManSetCoRequired( p->pManTim, pObj->IdPio, p->RequiredGlo ); } // go through the nodes in the reverse topological order If_ManForEachObjReverse( p, pObj, i ) { if ( If_ObjIsAnd(pObj) ) { if ( pObj->nRefs == 0 ) continue; If_CutPropagateRequired( p, pObj, If_ObjCutBest(pObj), pObj->Required ); } else if ( If_ObjIsCi(pObj) ) { reqTime = pObj->Required; Tim_ManSetCiRequired( p->pManTim, pObj->IdPio, reqTime ); } else if ( If_ObjIsCo(pObj) ) { reqTime = Tim_ManGetCoRequired( p->pManTim, pObj->IdPio ); If_ObjFanin0(pObj)->Required = IF_MIN( reqTime, If_ObjFanin0(pObj)->Required ); } else if ( If_ObjIsConst1(pObj) ) { } else // add the node to the mapper assert( 0 ); } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifTruth.c000066400000000000000000000332741300674244400230110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifTruth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Computation of truth tables of the cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //#define IF_TRY_NEW //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sorts the pins in the decreasing order of delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_CutTruthPermute( word * pTruth, int nLeaves, int nVars, int nWords, float * pDelays, int * pVars ) { while ( 1 ) { int i, fChange = 0; for ( i = 0; i < nLeaves - 1; i++ ) { if ( pDelays[i] >= pDelays[i+1] ) continue; ABC_SWAP( float, pDelays[i], pDelays[i+1] ); ABC_SWAP( int, pVars[i], pVars[i+1] ); if ( pTruth ) Abc_TtSwapAdjacent( pTruth, nWords, i ); fChange = 1; } if ( !fChange ) return; } } void If_CutRotatePins( If_Man_t * p, If_Cut_t * pCut ) { If_Obj_t * pLeaf; float PinDelays[IF_MAX_LUTSIZE]; int i, truthId; assert( !p->pPars->fUseTtPerm ); If_CutForEachLeaf( p, pCut, pLeaf, i ) PinDelays[i] = If_ObjCutBest(pLeaf)->Delay; if ( p->vTtMem[pCut->nLeaves] == NULL ) { If_CutTruthPermute( NULL, If_CutLeaveNum(pCut), pCut->nLeaves, p->nTruth6Words[pCut->nLeaves], PinDelays, If_CutLeaves(pCut) ); return; } Abc_TtCopy( p->puTempW, If_CutTruthWR(p, pCut), p->nTruth6Words[pCut->nLeaves], 0 ); If_CutTruthPermute( p->puTempW, If_CutLeaveNum(pCut), pCut->nLeaves, p->nTruth6Words[pCut->nLeaves], PinDelays, If_CutLeaves(pCut) ); truthId = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], p->puTempW ); pCut->iCutFunc = Abc_Var2Lit( truthId, If_CutTruthIsCompl(pCut) ); assert( (p->puTempW[0] & 1) == 0 ); } /**Function************************************************************* Synopsis [Truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ) { int fCompl, truthId, nLeavesNew, PrevSize, RetValue = 0; word * pTruth0s = Vec_MemReadEntry( p->vTtMem[pCut0->nLeaves], Abc_Lit2Var(pCut0->iCutFunc) ); word * pTruth1s = Vec_MemReadEntry( p->vTtMem[pCut1->nLeaves], Abc_Lit2Var(pCut1->iCutFunc) ); word * pTruth0 = (word *)p->puTemp[0]; word * pTruth1 = (word *)p->puTemp[1]; word * pTruth = (word *)p->puTemp[2]; Abc_TtCopy( pTruth0, pTruth0s, p->nTruth6Words[pCut0->nLeaves], fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iCutFunc) ); Abc_TtCopy( pTruth1, pTruth1s, p->nTruth6Words[pCut1->nLeaves], fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iCutFunc) ); Abc_TtStretch6( pTruth0, pCut0->nLeaves, pCut->nLeaves ); Abc_TtStretch6( pTruth1, pCut1->nLeaves, pCut->nLeaves ); Abc_TtExpand( pTruth0, pCut->nLeaves, pCut0->pLeaves, pCut0->nLeaves, pCut->pLeaves, pCut->nLeaves ); Abc_TtExpand( pTruth1, pCut->nLeaves, pCut1->pLeaves, pCut1->nLeaves, pCut->pLeaves, pCut->nLeaves ); fCompl = (pTruth0[0] & pTruth1[0] & 1); Abc_TtAnd( pTruth, pTruth0, pTruth1, p->nTruth6Words[pCut->nLeaves], fCompl ); if ( p->pPars->fCutMin && (pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || pCut0->nLeaves == 0 || pCut1->nLeaves == 0) ) { nLeavesNew = Abc_TtMinBase( pTruth, pCut->pLeaves, pCut->nLeaves, pCut->nLeaves ); if ( nLeavesNew < If_CutLeaveNum(pCut) ) { pCut->nLeaves = nLeavesNew; pCut->uSign = If_ObjCutSignCompute( pCut ); RetValue = 1; } } PrevSize = Vec_MemEntryNum( p->vTtMem[pCut->nLeaves] ); truthId = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], pTruth ); pCut->iCutFunc = Abc_Var2Lit( truthId, fCompl ); assert( (pTruth[0] & 1) == 0 ); #ifdef IF_TRY_NEW { word pCopy[1024]; char pCanonPerm[16]; memcpy( pCopy, If_CutTruthW(pCut), sizeof(word) * p->nTruth6Words[pCut->nLeaves] ); Abc_TtCanonicize( pCopy, pCut->nLeaves, pCanonPerm ); } #endif if ( p->vTtIsops[pCut->nLeaves] && PrevSize != Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) ) { Vec_Int_t * vLevel = Vec_WecPushLevel( p->vTtIsops[pCut->nLeaves] ); fCompl = Kit_TruthIsop( (unsigned *)pTruth, pCut->nLeaves, p->vCover, 1 ); if ( fCompl >= 0 ) { Vec_IntGrow( vLevel, Vec_IntSize(p->vCover) ); Vec_IntAppend( vLevel, p->vCover ); if ( fCompl ) vLevel->nCap ^= (1<<16); // hack to remember complemented attribute } assert( Vec_WecSize(p->vTtIsops[pCut->nLeaves]) == Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) ); } return RetValue; } /**Function************************************************************* Synopsis [Truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_CutComputeTruthPerm_int( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int iCutFunc0, int iCutFunc1 ) { int fVerbose = 0; abctime clk = 0; int pPerm[IF_MAX_LUTSIZE]; int v, Place, fCompl, truthId, nLeavesNew, RetValue = 0; word * pTruth0s = Vec_MemReadEntry( p->vTtMem[pCut0->nLeaves], Abc_Lit2Var(iCutFunc0) ); word * pTruth1s = Vec_MemReadEntry( p->vTtMem[pCut1->nLeaves], Abc_Lit2Var(iCutFunc1) ); word * pTruth0 = (word *)p->puTemp[0]; word * pTruth1 = (word *)p->puTemp[1]; word * pTruth = (word *)p->puTemp[2]; assert( pCut0->uMaskFunc >= 0 ); assert( pCut1->uMaskFunc >= 0 ); Abc_TtCopy( pTruth0, pTruth0s, p->nTruth6Words[pCut0->nLeaves], Abc_LitIsCompl(iCutFunc0) ); Abc_TtCopy( pTruth1, pTruth1s, p->nTruth6Words[pCut1->nLeaves], Abc_LitIsCompl(iCutFunc1) ); Abc_TtStretch6( pTruth0, pCut0->nLeaves, pCut->nLeaves ); Abc_TtStretch6( pTruth1, pCut1->nLeaves, pCut->nLeaves ); if ( fVerbose ) { //Kit_DsdPrintFromTruth( pTruth0, pCut0->nLeaves ); printf( "\n" ); //Kit_DsdPrintFromTruth( pTruth1, pCut1->nLeaves ); printf( "\n" ); } // create literals for ( v = 0; v < (int)pCut0->nLeaves; v++ ) pCut->pLeaves[v] = Abc_Var2Lit( pCut0->pLeaves[v], If_CutLeafBit(pCut0, v) ); for ( v = 0; v < (int)pCut1->nLeaves; v++ ) if ( p->pPerm[1][v] >= (int)pCut0->nLeaves ) pCut->pLeaves[p->pPerm[1][v]] = Abc_Var2Lit( pCut1->pLeaves[v], If_CutLeafBit(pCut1, v) ); else if ( If_CutLeafBit(pCut0, p->pPerm[1][v]) != If_CutLeafBit(pCut1, v) ) Abc_TtFlip( pTruth1, p->nTruth6Words[pCut1->nLeaves], v ); // permute variables for ( v = (int)pCut1->nLeaves; v < (int)pCut->nLeaves; v++ ) p->pPerm[1][v] = -1; for ( v = 0; v < (int)pCut1->nLeaves; v++ ) { Place = p->pPerm[1][v]; if ( Place == v || Place == -1 ) continue; Abc_TtSwapVars( pTruth1, pCut->nLeaves, v, Place ); p->pPerm[1][v] = p->pPerm[1][Place]; p->pPerm[1][Place] = Place; v--; } if ( fVerbose ) { //Kit_DsdPrintFromTruth( pTruth0, pCut0->nLeaves ); printf( "\n" ); //Kit_DsdPrintFromTruth( pTruth1, pCut->nLeaves ); printf( "\n" ); } // perform operation Abc_TtAnd( pTruth, pTruth0, pTruth1, p->nTruth6Words[pCut->nLeaves], 0 ); // minimize support if ( p->pPars->fCutMin && (pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || pCut0->nLeaves == 0 || pCut1->nLeaves == 0) ) { nLeavesNew = Abc_TtMinBase( pTruth, pCut->pLeaves, pCut->nLeaves, pCut->nLeaves ); if ( nLeavesNew < If_CutLeaveNum(pCut) ) { pCut->nLeaves = nLeavesNew; RetValue = 1; } } // compute canonical form if ( p->pPars->fVerbose ) clk = Abc_Clock(); p->uCanonPhase = Abc_TtCanonicize( pTruth, pCut->nLeaves, p->pCanonPerm ); if ( p->pPars->fVerbose ) p->timeCache[3] += Abc_Clock() - clk; for ( v = 0; v < (int)pCut->nLeaves; v++ ) pPerm[v] = Abc_LitNotCond( pCut->pLeaves[(int)p->pCanonPerm[v]], ((p->uCanonPhase>>v)&1) ); pCut->uMaskFunc = 0; for ( v = 0; v < (int)pCut->nLeaves; v++ ) { pCut->pLeaves[v] = Abc_Lit2Var(pPerm[v]); if ( Abc_LitIsCompl(pPerm[v]) ) pCut->uMaskFunc |= (1 << v); } // create signature after lowering literals if ( RetValue ) pCut->uSign = If_ObjCutSignCompute( pCut ); else assert( pCut->uSign == If_ObjCutSignCompute( pCut ) ); assert( Vec_IntSize(p->vTtOccurs[pCut->nLeaves]) == Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) ); // hash function fCompl = ((p->uCanonPhase >> pCut->nLeaves) & 1); truthId = Vec_MemHashInsert( p->vTtMem[pCut->nLeaves], pTruth ); pCut->iCutFunc = Abc_Var2Lit( truthId, fCompl ); // count how many time this truth table is used if ( Vec_IntSize(p->vTtOccurs[pCut->nLeaves]) < Vec_MemEntryNum(p->vTtMem[pCut->nLeaves]) ) Vec_IntPush( p->vTtOccurs[pCut->nLeaves], 0 ); Vec_IntAddToEntry( p->vTtOccurs[pCut->nLeaves], truthId, 1 ); if ( fVerbose ) { //Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); printf( "\n" ); //If_CutPrint( pCut0 ); //If_CutPrint( pCut1 ); //If_CutPrint( pCut ); //printf( "%d\n\n", pCut->iCutFunc ); } return RetValue; } int If_CutComputeTruthPerm( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int iCutFunc0, int iCutFunc1 ) { abctime clk = 0; int i, Num, nEntriesOld, RetValue; if ( pCut0->nLeaves + pCut1->nLeaves > pCut->nLeaves || iCutFunc0 < 2 || iCutFunc1 < 2 ) { if ( p->pPars->fVerbose ) clk = Abc_Clock(); RetValue = If_CutComputeTruthPerm_int( p, pCut, pCut0, pCut1, iCutFunc0, iCutFunc1 ); if ( p->pPars->fVerbose ) p->timeCache[0] += Abc_Clock() - clk; return RetValue; } assert( pCut0->nLeaves + pCut1->nLeaves == pCut->nLeaves ); nEntriesOld = Hash_IntManEntryNum(p->vPairHash); Num = Hash_Int2ManInsert( p->vPairHash, (iCutFunc0 << 5)|pCut0->nLeaves, (iCutFunc1 << 5)|pCut1->nLeaves, -1 ); assert( Num > 0 ); if ( nEntriesOld == Hash_IntManEntryNum(p->vPairHash) ) { char * pCanonPerm; int v, pPerm[IF_MAX_LUTSIZE]; pCut->iCutFunc = Vec_IntEntry( p->vPairRes, Num ); // move complements from the fanin cuts for ( v = 0; v < (int)pCut->nLeaves; v++ ) if ( v < (int)pCut0->nLeaves ) pCut->pLeaves[v] = Abc_Var2Lit( pCut->pLeaves[v], If_CutLeafBit(pCut0, v) ); else pCut->pLeaves[v] = Abc_Var2Lit( pCut->pLeaves[v], If_CutLeafBit(pCut1, v-(int)pCut0->nLeaves) ); // reorder the cut pCanonPerm = Vec_StrEntryP( p->vPairPerms, Num * pCut->nLimit ); for ( v = 0; v < (int)pCut->nLeaves; v++ ) pPerm[v] = Abc_LitNotCond( pCut->pLeaves[Abc_Lit2Var((int)pCanonPerm[v])], Abc_LitIsCompl((int)pCanonPerm[v]) ); // generate the result pCut->uMaskFunc = 0; for ( v = 0; v < (int)pCut->nLeaves; v++ ) { pCut->pLeaves[v] = Abc_Lit2Var(pPerm[v]); if ( Abc_LitIsCompl(pPerm[v]) ) pCut->uMaskFunc |= (1 << v); } // printf( "Found: %d(%d) %d(%d) -> %d(%d)\n", iCutFunc0, pCut0->nLeaves, iCutFunc1, pCut0->nLeaves, pCut->iCutFunc, pCut->nLeaves ); p->nCacheHits++; //p->timeCache[1] += Abc_Clock() - clk; return 0; } if ( p->pPars->fVerbose ) clk = Abc_Clock(); p->nCacheMisses++; RetValue = If_CutComputeTruthPerm_int( p, pCut, pCut0, pCut1, iCutFunc0, iCutFunc1 ); assert( RetValue == 0 ); // printf( "Added: %d(%d) %d(%d) -> %d(%d)\n", iCutFunc0, pCut0->nLeaves, iCutFunc1, pCut0->nLeaves, pCut->iCutFunc, pCut->nLeaves ); // save the result assert( Num == Vec_IntSize(p->vPairRes) ); Vec_IntPush( p->vPairRes, pCut->iCutFunc ); // save the permutation assert( Num * (int)pCut->nLimit == Vec_StrSize(p->vPairPerms) ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) Vec_StrPush( p->vPairPerms, (char)Abc_Var2Lit((int)p->pCanonPerm[i], ((p->uCanonPhase>>i)&1)) ); for ( i = (int)pCut0->nLeaves + (int)pCut1->nLeaves; i < (int)pCut->nLimit; i++ ) Vec_StrPush( p->vPairPerms, (char)-1 ); if ( p->pPars->fVerbose ) p->timeCache[2] += Abc_Clock() - clk; return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifTune.c000066400000000000000000001475501300674244400226210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifTune.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Library tuning.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifTune.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" #include "aig/gia/giaAig.h" #include "sat/bsat/satStore.h" #include "sat/cnf/cnf.h" #include "misc/extra/extra.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define IFN_INS 11 #define IFN_WRD (IFN_INS > 6 ? 1 << (IFN_INS-6) : 1) #define IFN_PAR 1024 // network types typedef enum { IFN_DSD_NONE = 0, // 0: unknown IFN_DSD_CONST0, // 1: constant IFN_DSD_VAR, // 2: variable IFN_DSD_AND, // 3: AND IFN_DSD_XOR, // 4: XOR IFN_DSD_MUX, // 5: MUX IFN_DSD_PRIME // 6: PRIME } Ifn_DsdType_t; // object types static char * Ifn_Symbs[16] = { NULL, // 0: unknown "const", // 1: constant "var", // 2: variable "()", // 3: AND "[]", // 4: XOR "<>", // 5: MUX "{}" // 6: PRIME }; typedef struct Ifn_Obj_t_ Ifn_Obj_t; struct Ifn_Obj_t_ { unsigned Type : 3; // node type unsigned nFanins : 5; // fanin counter unsigned iFirst : 8; // first parameter unsigned Var : 16; // current variable int Fanins[IFN_INS]; // fanin IDs }; struct Ifn_Ntk_t_ { // cell structure int nInps; // inputs int nObjs; // objects Ifn_Obj_t Nodes[2*IFN_INS]; // nodes // constraints int pConstr[IFN_INS*IFN_INS]; // constraint pairs int nConstr; // number of pairs // user data int nVars; // variables int nWords; // truth table words int nParsVNum; // selection parameters per variable int nParsVIni; // first selection parameter int nPars; // total parameters word * pTruth; // user truth table // matching procedures int Values[IFN_PAR]; // variable values word pTtElems[IFN_INS*IFN_WRD]; // elementary truth tables word pTtObjs[2*IFN_INS*IFN_WRD]; // object truth tables }; static inline word * Ifn_ElemTruth( Ifn_Ntk_t * p, int i ) { return p->pTtElems + i * Abc_TtWordNum(p->nInps); } static inline word * Ifn_ObjTruth( Ifn_Ntk_t * p, int i ) { return p->pTtObjs + i * p->nWords; } // variable ordering // - primary inputs [0; p->nInps) // - internal nodes [p->nInps; p->nObjs) // - configuration params [p->nObjs; p->nParsVIni) // - variable selection params [p->nParsVIni; p->nPars) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prepare network to check the given function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ifn_Prepare( Ifn_Ntk_t * p, word * pTruth, int nVars ) { int i, fVerbose = 0; assert( nVars <= p->nInps ); p->pTruth = pTruth; p->nVars = nVars; p->nWords = Abc_TtWordNum(nVars); p->nPars = p->nObjs; for ( i = p->nInps; i < p->nObjs; i++ ) { if ( p->Nodes[i].Type != IFN_DSD_PRIME ) continue; p->Nodes[i].iFirst = p->nPars; p->nPars += (1 << p->Nodes[i].nFanins); if ( fVerbose ) printf( "Node %d Start %d Vars %d\n", i, p->Nodes[i].iFirst, (1 << p->Nodes[i].nFanins) ); } if ( fVerbose ) printf( "Groups start %d\n", p->nPars ); p->nParsVIni = p->nPars; p->nParsVNum = Abc_Base2Log(nVars); p->nPars += p->nParsVNum * p->nInps; assert( p->nPars <= IFN_PAR ); memset( p->Values, 0xFF, sizeof(int) * p->nPars ); return p->nPars; } void Ifn_NtkPrint( Ifn_Ntk_t * p ) { int i, k; if ( p == NULL ) printf( "String is empty.\n" ); if ( p == NULL ) return; for ( i = p->nInps; i < p->nObjs; i++ ) { printf( "%c=", 'a'+i ); printf( "%c", Ifn_Symbs[p->Nodes[i].Type][0] ); for ( k = 0; k < (int)p->Nodes[i].nFanins; k++ ) printf( "%c", 'a'+p->Nodes[i].Fanins[k] ); printf( "%c", Ifn_Symbs[p->Nodes[i].Type][1] ); printf( ";" ); } printf( "\n" ); } int Ifn_NtkLutSizeMax( Ifn_Ntk_t * p ) { int i, LutSize = 0; for ( i = p->nInps; i < p->nObjs; i++ ) if ( p->Nodes[i].Type == IFN_DSD_PRIME ) LutSize = Abc_MaxInt( LutSize, (int)p->Nodes[i].nFanins ); return LutSize; } int Ifn_NtkInputNum( Ifn_Ntk_t * p ) { return p->nInps; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ifn_ErrorMessage( const char * format, ... ) { char * pMessage; va_list args; va_start( args, format ); pMessage = vnsprintf( format, args ); va_end( args ); printf( "%s", pMessage ); ABC_FREE( pMessage ); return 0; } int Inf_ManOpenSymb( char * pStr ) { if ( pStr[0] == '(' ) return 3; if ( pStr[0] == '[' ) return 4; if ( pStr[0] == '<' ) return 5; if ( pStr[0] == '{' ) return 6; return 0; } int Ifn_ManStrCheck( char * pStr, int * pnInps, int * pnObjs ) { int i, nNodes = 0, Marks[32] = {0}, MaxVar = -1; for ( i = 0; pStr[i]; i++ ) { if ( Inf_ManOpenSymb(pStr+i) ) nNodes++; if ( pStr[i] == ';' || pStr[i] == '(' || pStr[i] == ')' || pStr[i] == '[' || pStr[i] == ']' || pStr[i] == '<' || pStr[i] == '>' || pStr[i] == '{' || pStr[i] == '}' ) continue; if ( pStr[i] >= 'A' && pStr[i] <= 'Z' ) continue; if ( pStr[i] >= 'a' && pStr[i] <= 'z' ) { MaxVar = Abc_MaxInt( MaxVar, (int)(pStr[i] - 'a') ); Marks[pStr[i] - 'a'] = 1; continue; } return Ifn_ErrorMessage( "String \"%s\" contains unrecognized symbol \'%c\'.\n", pStr, pStr[i] ); } for ( i = 0; i <= MaxVar; i++ ) if ( Marks[i] == 0 ) return Ifn_ErrorMessage( "String \"%s\" has no symbol \'%c\'.\n", pStr, 'a' + i ); *pnInps = MaxVar + 1; *pnObjs = MaxVar + 1 + nNodes; return 1; } static inline char * Ifn_NtkParseFindClosingParenthesis( char * pStr, char Open, char Close ) { int Counter = 0; assert( *pStr == Open ); for ( ; *pStr; pStr++ ) { if ( *pStr == Open ) Counter++; if ( *pStr == Close ) Counter--; if ( Counter == 0 ) return pStr; } return NULL; } int Ifn_NtkParseInt_rec( char * pStr, Ifn_Ntk_t * p, char ** ppFinal, int * piNode ) { Ifn_Obj_t * pObj; int nFanins = 0, pFanins[IFN_INS]; int Type = Inf_ManOpenSymb( pStr ); char * pLim = Ifn_NtkParseFindClosingParenthesis( pStr++, Ifn_Symbs[Type][0], Ifn_Symbs[Type][1] ); *ppFinal = NULL; if ( pLim == NULL ) return Ifn_ErrorMessage( "For symbol \'%c\' cannot find matching symbol \'%c\'.\n", Ifn_Symbs[Type][0], Ifn_Symbs[Type][1] ); while ( pStr < pLim ) { assert( nFanins < IFN_INS ); if ( pStr[0] >= 'a' && pStr[0] <= 'z' ) pFanins[nFanins++] = pStr[0] - 'a', pStr++; else if ( Inf_ManOpenSymb(pStr) ) { if ( !Ifn_NtkParseInt_rec( pStr, p, &pStr, piNode ) ) return 0; pFanins[nFanins++] = *piNode - 1; } else return Ifn_ErrorMessage( "Substring \"%s\" contans unrecognized symbol \'%c\'.\n", pStr, pStr[0] ); } assert( pStr == pLim ); pObj = p->Nodes + (*piNode)++; pObj->Type = Type; assert( pObj->nFanins == 0 ); pObj->nFanins = nFanins; memcpy( pObj->Fanins, pFanins, sizeof(int) * nFanins ); *ppFinal = pLim + 1; if ( Type == IFN_DSD_MUX && nFanins != 3 ) return Ifn_ErrorMessage( "MUX should have exactly three fanins.\n" ); return 1; } int Ifn_NtkParseInt( char * pStr, Ifn_Ntk_t * p ) { char * pFinal; int iNode; if ( !Ifn_ManStrCheck(pStr, &p->nInps, &p->nObjs) ) return 0; if ( p->nInps > IFN_INS ) return Ifn_ErrorMessage( "The number of variables (%d) exceeds predefined limit (%d). Recompile with different value of IFN_INS.\n", p->nInps, IFN_INS ); assert( p->nInps > 1 && p->nInps < p->nObjs && p->nInps <= IFN_INS && p->nObjs < 2*IFN_INS ); if ( !Inf_ManOpenSymb(pStr) ) return Ifn_ErrorMessage( "The first symbol should be one of the symbols: (, [, <, {.\n" ); iNode = p->nInps; if ( !Ifn_NtkParseInt_rec( pStr, p, &pFinal, &iNode ) ) return 0; if ( pFinal[0] && pFinal[0] != ';' ) return Ifn_ErrorMessage( "The last symbol should be \';\'.\n" ); if ( iNode != p->nObjs ) return Ifn_ErrorMessage( "Mismatch in the number of nodes.\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ifn_ManStrType2( char * pStr ) { int i; for ( i = 0; pStr[i]; i++ ) if ( pStr[i] == '=' ) return 1; return 0; } int Ifn_ManStrCheck2( char * pStr, int * pnInps, int * pnObjs ) { int i, Marks[32] = {0}, MaxVar = 0, MaxDef = 0; for ( i = 0; pStr[i]; i++ ) { if ( pStr[i] == '=' || pStr[i] == ';' || pStr[i] == '(' || pStr[i] == ')' || pStr[i] == '[' || pStr[i] == ']' || pStr[i] == '<' || pStr[i] == '>' || pStr[i] == '{' || pStr[i] == '}' ) continue; if ( pStr[i] >= 'A' && pStr[i] <= 'Z' ) continue; if ( pStr[i] >= 'a' && pStr[i] <= 'z' ) { if ( pStr[i+1] == '=' ) Marks[pStr[i] - 'a'] = 2, MaxDef = Abc_MaxInt(MaxDef, pStr[i] - 'a'); continue; } return Ifn_ErrorMessage( "String \"%s\" contains unrecognized symbol \'%c\'.\n", pStr, pStr[i] ); } for ( i = 0; pStr[i]; i++ ) { if ( pStr[i] == '=' || pStr[i] == ';' || pStr[i] == '(' || pStr[i] == ')' || pStr[i] == '[' || pStr[i] == ']' || pStr[i] == '<' || pStr[i] == '>' || pStr[i] == '{' || pStr[i] == '}' ) continue; if ( pStr[i] >= 'A' && pStr[i] <= 'Z' ) continue; if ( pStr[i] >= 'a' && pStr[i] <= 'z' ) { if ( pStr[i+1] != '=' && Marks[pStr[i] - 'a'] != 2 ) Marks[pStr[i] - 'a'] = 1, MaxVar = Abc_MaxInt(MaxVar, pStr[i] - 'a'); continue; } return Ifn_ErrorMessage( "String \"%s\" contains unrecognized symbol \'%c\'.\n", pStr, pStr[i] ); } MaxVar++; MaxDef++; for ( i = 0; i < MaxDef; i++ ) if ( Marks[i] == 0 ) return Ifn_ErrorMessage( "String \"%s\" has no symbol \'%c\'.\n", pStr, 'a' + i ); for ( i = 0; i < MaxVar; i++ ) if ( Marks[i] == 2 ) return Ifn_ErrorMessage( "String \"%s\" has definition of input variable \'%c\'.\n", pStr, 'a' + i ); for ( i = MaxVar; i < MaxDef; i++ ) if ( Marks[i] == 1 ) return Ifn_ErrorMessage( "String \"%s\" has no definition for internal variable \'%c\'.\n", pStr, 'a' + i ); *pnInps = MaxVar; *pnObjs = MaxDef; return 1; } int Ifn_NtkParseInt2( char * pStr, Ifn_Ntk_t * p ) { int i, k, n, f, nFans, iFan; if ( !Ifn_ManStrCheck2(pStr, &p->nInps, &p->nObjs) ) return 0; if ( p->nInps > IFN_INS ) return Ifn_ErrorMessage( "The number of variables (%d) exceeds predefined limit (%d). Recompile with different value of IFN_INS.\n", p->nInps, IFN_INS ); assert( p->nInps > 1 && p->nInps < p->nObjs && p->nInps <= IFN_INS && p->nObjs < 2*IFN_INS ); for ( i = p->nInps; i < p->nObjs; i++ ) { char Next = 0; for ( k = 0; pStr[k]; k++ ) if ( pStr[k] == 'a' + i && pStr[k+1] == '=' ) break; if ( pStr[k] == 0 ) return Ifn_ErrorMessage( "Cannot find definition of signal \'%c\'.\n", 'a' + i ); if ( pStr[k+2] == '(' ) p->Nodes[i].Type = IFN_DSD_AND, Next = ')'; else if ( pStr[k+2] == '[' ) p->Nodes[i].Type = IFN_DSD_XOR, Next = ']'; else if ( pStr[k+2] == '<' ) p->Nodes[i].Type = IFN_DSD_MUX, Next = '>'; else if ( pStr[k+2] == '{' ) p->Nodes[i].Type = IFN_DSD_PRIME, Next = '}'; else return Ifn_ErrorMessage( "Cannot find openning operation symbol in the definition of signal \'%c\'.\n", 'a' + i ); for ( n = k + 3; pStr[n]; n++ ) if ( pStr[n] == Next ) break; if ( pStr[n] == 0 ) return Ifn_ErrorMessage( "Cannot find closing operation symbol in the definition of signal \'%c\'.\n", 'a' + i ); nFans = n - k - 3; if ( nFans > 8 ) return Ifn_ErrorMessage( "Cannot find matching operation symbol in the definition of signal \'%c\'.\n", 'a' + i ); for ( f = 0; f < nFans; f++ ) { iFan = pStr[k + 3 + f] - 'a'; if ( iFan < 0 || iFan >= i ) return Ifn_ErrorMessage( "Fanin number %d is signal %d is out of range.\n", f, 'a' + i ); p->Nodes[i].Fanins[f] = iFan; } p->Nodes[i].nFanins = nFans; } return 1; } void Ifn_NtkParseConstraints( char * pStr, Ifn_Ntk_t * p ) { int i, k; // parse constraints p->nConstr = 0; for ( i = 0; i < p->nInps; i++ ) for ( k = 0; pStr[k]; k++ ) if ( pStr[k] == 'A' + i && pStr[k-1] == ';' ) { assert( p->nConstr < IFN_INS*IFN_INS ); p->pConstr[p->nConstr++] = ((int)(pStr[k] - 'A') << 16) | (int)(pStr[k+1] - 'A'); // printf( "Added constraint (%c < %c)\n", pStr[k], pStr[k+1] ); } // if ( p->nConstr ) // printf( "Total constraints = %d\n", p->nConstr ); } Ifn_Ntk_t * Ifn_NtkParse( char * pStr ) { Ifn_Ntk_t * p = ABC_CALLOC( Ifn_Ntk_t, 1 ); if ( Ifn_ManStrType2(pStr) ) { if ( !Ifn_NtkParseInt2( pStr, p ) ) { ABC_FREE( p ); return NULL; } } else { if ( !Ifn_NtkParseInt( pStr, p ) ) { ABC_FREE( p ); return NULL; } } Ifn_NtkParseConstraints( pStr, p ); Abc_TtElemInit2( p->pTtElems, p->nInps ); // printf( "Finished parsing: " ); Ifn_NtkPrint(p); return p; } int Ifn_NtkTtBits( char * pStr ) { int i, Counter = 0; Ifn_Ntk_t * pNtk = Ifn_NtkParse( pStr ); for ( i = pNtk->nInps; i < pNtk->nObjs; i++ ) if ( pNtk->Nodes[i].Type == IFN_DSD_PRIME ) Counter += (1 << pNtk->Nodes[i].nFanins); ABC_FREE( pNtk ); return Counter; } /**Function************************************************************* Synopsis [Derive AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Ifn_ManStrFindModel( Ifn_Ntk_t * p ) { Gia_Man_t * pNew, * pTemp; int i, k, iLit, * pVarMap = ABC_FALLOC( int, p->nParsVIni ); pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( "model" ); Gia_ManHashStart( pNew ); for ( i = 0; i < p->nInps; i++ ) pVarMap[i] = Gia_ManAppendCi(pNew); for ( i = p->nObjs; i < p->nParsVIni; i++ ) pVarMap[i] = Gia_ManAppendCi(pNew); for ( i = p->nInps; i < p->nObjs; i++ ) { int Type = p->Nodes[i].Type; int nFans = p->Nodes[i].nFanins; int * pFans = p->Nodes[i].Fanins; int iFanin = p->Nodes[i].iFirst; if ( Type == IFN_DSD_AND ) { iLit = 1; for ( k = 0; k < nFans; k++ ) iLit = Gia_ManHashAnd( pNew, iLit, pVarMap[pFans[k]] ); pVarMap[i] = iLit; } else if ( Type == IFN_DSD_XOR ) { iLit = 0; for ( k = 0; k < nFans; k++ ) iLit = Gia_ManHashXor( pNew, iLit, pVarMap[pFans[k]] ); pVarMap[i] = iLit; } else if ( Type == IFN_DSD_MUX ) { assert( nFans == 3 ); pVarMap[i] = Gia_ManHashMux( pNew, pVarMap[pFans[0]], pVarMap[pFans[1]], pVarMap[pFans[2]] ); } else if ( Type == IFN_DSD_PRIME ) { int n, Step, pVarsData[256]; int nMints = (1 << nFans); assert( nFans >= 0 && nFans <= 8 ); for ( k = 0; k < nMints; k++ ) pVarsData[k] = pVarMap[iFanin + k]; for ( Step = 1, k = 0; k < nFans; k++, Step <<= 1 ) for ( n = 0; n < nMints; n += Step << 1 ) pVarsData[n] = Gia_ManHashMux( pNew, pVarMap[pFans[k]], pVarsData[n+Step], pVarsData[n] ); assert( Step == nMints ); pVarMap[i] = pVarsData[0]; } else assert( 0 ); } Gia_ManAppendCo( pNew, pVarMap[p->nObjs-1] ); ABC_FREE( pVarMap ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); assert( Gia_ManPiNum(pNew) == p->nParsVIni - (p->nObjs - p->nInps) ); assert( Gia_ManPoNum(pNew) == 1 ); return pNew; } // compute cofactors w.r.t. the first nIns variables Gia_Man_t * Ifn_ManStrFindCofactors( int nIns, Gia_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, m, nMints = 1 << nIns; pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) if ( i >= nIns ) pObj->Value = Gia_ManAppendCi( pNew ); for ( m = 0; m < nMints; m++ ) { Gia_ManForEachCi( p, pObj, i ) if ( i < nIns ) pObj->Value = ((m >> i) & 1); 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) ); } pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Derive SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p ) { Cnf_Dat_t * pCnf; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); pAig->nRegs = 0; pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Aig_ManStop( pAig ); return pCnf; } sat_solver * Ifn_ManStrFindSolver( Gia_Man_t * p, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars ) { sat_solver * pSat; Gia_Obj_t * pObj; Cnf_Dat_t * pCnf; int i; pCnf = Cnf_DeriveGiaRemapped( p ); // start the SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, pCnf->nVars ); // add timeframe clauses for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) assert( 0 ); // inputs/outputs *pvPiVars = Vec_IntAlloc( Gia_ManPiNum(p) ); Gia_ManForEachCi( p, pObj, i ) Vec_IntPush( *pvPiVars, pCnf->pVarNums[Gia_ObjId(p, pObj)] ); *pvPoVars = Vec_IntAlloc( Gia_ManPoNum(p) ); Gia_ManForEachCo( p, pObj, i ) Vec_IntPush( *pvPoVars, pCnf->pVarNums[Gia_ObjId(p, pObj)] ); Cnf_DataFree( pCnf ); return pSat; } sat_solver * Ifn_ManSatBuild( Ifn_Ntk_t * p, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars ) { Gia_Man_t * p1, * p2; sat_solver * pSat = NULL; *pvPiVars = *pvPoVars = NULL; p1 = Ifn_ManStrFindModel( p ); // Gia_AigerWrite( p1, "satbuild.aig", 0, 0 ); p2 = Ifn_ManStrFindCofactors( p->nInps, p1 ); Gia_ManStop( p1 ); // Gia_AigerWrite( p2, "satbuild2.aig", 0, 0 ); pSat = Ifn_ManStrFindSolver( p2, pvPiVars, pvPoVars ); Gia_ManStop( p2 ); return pSat; } void * If_ManSatBuildFromCell( char * pStr, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars, Ifn_Ntk_t ** ppNtk ) { Ifn_Ntk_t * p = Ifn_NtkParse( pStr ); Ifn_Prepare( p, NULL, p->nInps ); *ppNtk = p; if ( p == NULL ) return NULL; // Ifn_NtkPrint( p ); return Ifn_ManSatBuild( p, pvPiVars, pvPoVars ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ifn_ManSatPrintPerm( char * pPerms, int nVars ) { int i; for ( i = 0; i < nVars; i++ ) printf( "%c", 'a' + pPerms[i] ); printf( "\n" ); } int Ifn_ManSatCheckOne( sat_solver * pSat, Vec_Int_t * vPoVars, word * pTruth, int nVars, int * pPerm, int nInps, Vec_Int_t * vLits ) { int v, Value, m, mNew, nMints = (1 << nVars); // (1 << nInps); assert( (1 << nInps) == Vec_IntSize(vPoVars) ); assert( nVars <= nInps ); // remap minterms Vec_IntFill( vLits, Vec_IntSize(vPoVars), -1 ); for ( m = 0; m < nMints; m++ ) { mNew = 0; for ( v = 0; v < nInps; v++ ) { assert( pPerm[v] < nVars ); if ( ((m >> pPerm[v]) & 1) ) mNew |= (1 << v); } assert( Vec_IntEntry(vLits, mNew) == -1 ); Vec_IntWriteEntry( vLits, mNew, Abc_TtGetBit(pTruth, m) ); } // find assumptions v = 0; Vec_IntForEachEntry( vLits, Value, m ) if ( Value >= 0 ) Vec_IntWriteEntry( vLits, v++, Abc_Var2Lit(Vec_IntEntry(vPoVars, m), !Value) ); Vec_IntShrink( vLits, v ); // run SAT solver Value = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); return (int)(Value == l_True); } void Ifn_ManSatDeriveOne( sat_solver * pSat, Vec_Int_t * vPiVars, Vec_Int_t * vValues ) { int i, iVar; Vec_IntClear( vValues ); Vec_IntForEachEntry( vPiVars, iVar, i ) Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) ); } int If_ManSatFindCofigBits( void * pSat, Vec_Int_t * vPiVars, Vec_Int_t * vPoVars, word * pTruth, int nVars, word Perm, int nInps, Vec_Int_t * vValues ) { // extract permutation int RetValue, i, pPerm[IF_MAX_FUNC_LUTSIZE]; assert( nInps <= IF_MAX_FUNC_LUTSIZE ); for ( i = 0; i < nInps; i++ ) { pPerm[i] = Abc_TtGetHex( &Perm, i ); assert( pPerm[i] < nVars ); } // perform SAT check RetValue = Ifn_ManSatCheckOne( (sat_solver *)pSat, vPoVars, pTruth, nVars, pPerm, nInps, vValues ); Vec_IntClear( vValues ); if ( RetValue == 0 ) return 0; Ifn_ManSatDeriveOne( (sat_solver*)pSat, vPiVars, vValues ); return 1; } int Ifn_ManSatFindCofigBitsTest( Ifn_Ntk_t * p, word * pTruth, int nVars, word Perm ) { Vec_Int_t * vValues = Vec_IntAlloc( 100 ); Vec_Int_t * vPiVars, * vPoVars; sat_solver * pSat = Ifn_ManSatBuild( p, &vPiVars, &vPoVars ); int RetValue = If_ManSatFindCofigBits( pSat, vPiVars, vPoVars, pTruth, nVars, Perm, p->nInps, vValues ); Vec_IntPrint( vValues ); // cleanup sat_solver_delete( pSat ); Vec_IntFreeP( &vPiVars ); Vec_IntFreeP( &vPoVars ); Vec_IntFreeP( &vValues ); return RetValue; } /**Function************************************************************* Synopsis [Derive GIA using programmable bits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManSatDeriveGiaFromBits( void * pGia, Ifn_Ntk_t * p, word * pConfigData, Vec_Int_t * vLeaves, Vec_Int_t * vCover ) { Gia_Man_t * pNew = (Gia_Man_t *)pGia; int i, k, iLit, iVar = 0, nVarsNew, pVarMap[1000]; int nTtBits = p->nParsVIni - p->nObjs; int nPermBits = Abc_Base2Log(p->nInps + 1) + 1; int fCompl = Abc_TtGetBit( pConfigData, nTtBits + nPermBits * p->nInps ); assert( Vec_IntSize(vLeaves) <= p->nInps && p->nParsVIni < 1000 ); for ( i = 0; i < p->nInps; i++ ) { for ( iLit = k = 0; k < nPermBits; k++ ) if ( Abc_TtGetBit(pConfigData, nTtBits + i * nPermBits + k) ) iLit |= (1 << k); assert( Abc_Lit2Var(iLit) < Vec_IntSize(vLeaves) ); pVarMap[i] = Abc_Lit2LitL( Vec_IntArray(vLeaves), iLit ); } for ( i = p->nInps; i < p->nObjs; i++ ) { int Type = p->Nodes[i].Type; int nFans = p->Nodes[i].nFanins; int * pFans = p->Nodes[i].Fanins; //int iFanin = p->Nodes[i].iFirst; assert( nFans <= 6 ); if ( Type == IFN_DSD_AND ) { iLit = 1; for ( k = 0; k < nFans; k++ ) iLit = Gia_ManHashAnd( pNew, iLit, pVarMap[pFans[k]] ); pVarMap[i] = iLit; } else if ( Type == IFN_DSD_XOR ) { iLit = 0; for ( k = 0; k < nFans; k++ ) iLit = Gia_ManHashXor( pNew, iLit, pVarMap[pFans[k]] ); pVarMap[i] = iLit; } else if ( Type == IFN_DSD_MUX ) { assert( nFans == 3 ); pVarMap[i] = Gia_ManHashMux( pNew, pVarMap[pFans[0]], pVarMap[pFans[1]], pVarMap[pFans[2]] ); } else if ( Type == IFN_DSD_PRIME ) { int pFaninLits[16]; // collect truth table word uTruth = 0; int nMints = (1 << nFans); for ( k = 0; k < nMints; k++ ) if ( Abc_TtGetBit(pConfigData, iVar++) ) uTruth |= ((word)1 << k); uTruth = Abc_Tt6Stretch( uTruth, nFans ); // collect function for ( k = 0; k < nFans; k++ ) pFaninLits[k] = pVarMap[pFans[k]]; // implement the function nVarsNew = Abc_TtMinBase( &uTruth, pFaninLits, nFans, 6 ); if ( nVarsNew == 0 ) pVarMap[i] = (int)(uTruth & 1); else { extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); Vec_Int_t Leaves = { nVarsNew, nVarsNew, pFaninLits }; pVarMap[i] = Kit_TruthToGia( pNew, (unsigned *)&uTruth, nVarsNew, vCover, &Leaves, 1 ); // hashing enabled!!! } } else assert( 0 ); } assert( iVar == nTtBits ); return Abc_LitNotCond( pVarMap[p->nObjs - 1], fCompl ); } /**Function************************************************************* Synopsis [Derive GIA using programmable bits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * If_ManDeriveGiaFromCells( void * pGia ) { Gia_Man_t * p = (Gia_Man_t *)pGia; Gia_Man_t * pNew, * pTemp; Vec_Int_t * vCover, * vLeaves; Ifn_Ntk_t * pNtkCell; Gia_Obj_t * pObj; word * pConfigData; //word * pTruth; int k, i, iLut, iVar; int nConfigInts, Count = 0; assert( p->vConfigs != NULL ); assert( p->pCellStr != NULL ); assert( Gia_ManHasMapping(p) ); // derive cell network pNtkCell = Ifn_NtkParse( p->pCellStr ); Ifn_Prepare( pNtkCell, NULL, pNtkCell->nInps ); nConfigInts = Vec_IntEntry( p->vConfigs, 1 ); // create new manager pNew = Gia_ManStart( 6*Gia_ManObjNum(p)/5 + 100 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // map primary inputs Gia_ManFillValue(p); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // iterate through nodes used in the mapping vLeaves = Vec_IntAlloc( 16 ); vCover = Vec_IntAlloc( 1 << 16 ); Gia_ManHashStart( pNew ); //Gia_ObjComputeTruthTableStart( p, Gia_ManLutSizeMax(p) ); Gia_ManForEachAnd( p, pObj, iLut ) { if ( Gia_ObjIsBuf(pObj) ) { pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); continue; } if ( !Gia_ObjIsLut(p, iLut) ) continue; // collect leaves //Vec_IntClear( vLeaves ); //Gia_LutForEachFanin( p, iLut, iVar, k ) // Vec_IntPush( vLeaves, iVar ); //pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, iLut), vLeaves ); // collect incoming literals Vec_IntClear( vLeaves ); Gia_LutForEachFanin( p, iLut, iVar, k ) Vec_IntPush( vLeaves, Gia_ManObj(p, iVar)->Value ); pConfigData = (word *)Vec_IntEntryP( p->vConfigs, 2 + nConfigInts * Count++ ); Gia_ManObj(p, iLut)->Value = If_ManSatDeriveGiaFromBits( pNew, pNtkCell, pConfigData, vLeaves, vCover ); } assert( Vec_IntEntry(p->vConfigs, 0) == Count ); assert( Vec_IntSize(p->vConfigs) == 2 + nConfigInts * Count ); //Gia_ObjComputeTruthTableStop( p ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Vec_IntFree( vLeaves ); Vec_IntFree( vCover ); ABC_FREE( pNtkCell ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Derive truth table given the configulation values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word * Ifn_NtkDeriveTruth( Ifn_Ntk_t * p, int * pValues ) { int i, v, f, iVar, iStart; // elementary variables for ( i = 0; i < p->nInps; i++ ) { // find variable iStart = p->nParsVIni + i * p->nParsVNum; for ( v = iVar = 0; v < p->nParsVNum; v++ ) if ( p->Values[iStart+v] ) iVar += (1 << v); // assign variable Abc_TtCopy( Ifn_ObjTruth(p, i), Ifn_ElemTruth(p, iVar), p->nWords, 0 ); } // internal variables for ( i = p->nInps; i < p->nObjs; i++ ) { int nFans = p->Nodes[i].nFanins; int * pFans = p->Nodes[i].Fanins; word * pTruth = Ifn_ObjTruth( p, i ); if ( p->Nodes[i].Type == IFN_DSD_AND ) { Abc_TtFill( pTruth, p->nWords ); for ( f = 0; f < nFans; f++ ) Abc_TtAnd( pTruth, pTruth, Ifn_ObjTruth(p, pFans[f]), p->nWords, 0 ); } else if ( p->Nodes[i].Type == IFN_DSD_XOR ) { Abc_TtClear( pTruth, p->nWords ); for ( f = 0; f < nFans; f++ ) Abc_TtXor( pTruth, pTruth, Ifn_ObjTruth(p, pFans[f]), p->nWords, 0 ); } else if ( p->Nodes[i].Type == IFN_DSD_MUX ) { assert( nFans == 3 ); Abc_TtMux( pTruth, Ifn_ObjTruth(p, pFans[0]), Ifn_ObjTruth(p, pFans[1]), Ifn_ObjTruth(p, pFans[2]), p->nWords ); } else if ( p->Nodes[i].Type == IFN_DSD_PRIME ) { int nValues = (1 << nFans); word * pTemp = Ifn_ObjTruth(p, p->nObjs); Abc_TtClear( pTruth, p->nWords ); for ( v = 0; v < nValues; v++ ) { if ( pValues[p->Nodes[i].iFirst + v] == 0 ) continue; Abc_TtFill( pTemp, p->nWords ); for ( f = 0; f < nFans; f++ ) if ( (v >> f) & 1 ) Abc_TtAnd( pTemp, pTemp, Ifn_ObjTruth(p, pFans[f]), p->nWords, 0 ); else Abc_TtSharp( pTemp, pTemp, Ifn_ObjTruth(p, pFans[f]), p->nWords ); Abc_TtOr( pTruth, pTruth, pTemp, p->nWords ); } } else assert( 0 ); //Dau_DsdPrintFromTruth( pTruth, p->nVars ); } return Ifn_ObjTruth(p, p->nObjs-1); } /**Function************************************************************* Synopsis [Compute more or equal] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ifn_TtComparisonConstr( word * pTruth, int nVars, int fMore, int fEqual ) { word Cond[4], Equa[4], Temp[4]; word s_TtElems[8][4] = { { ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA) }, { ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC) }, { ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0) }, { ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00) }, { ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000) }, { ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000) }, { ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF) }, { ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF) } }; int i, nWords = Abc_TtWordNum(2*nVars); assert( nVars > 0 && nVars <= 4 ); Abc_TtClear( pTruth, nWords ); Abc_TtFill( Equa, nWords ); for ( i = nVars - 1; i >= 0; i-- ) { if ( fMore ) Abc_TtSharp( Cond, s_TtElems[2*i+1], s_TtElems[2*i+0], nWords ); else Abc_TtSharp( Cond, s_TtElems[2*i+0], s_TtElems[2*i+1], nWords ); Abc_TtAnd( Temp, Equa, Cond, nWords, 0 ); Abc_TtOr( pTruth, pTruth, Temp, nWords ); Abc_TtXor( Temp, s_TtElems[2*i+0], s_TtElems[2*i+1], nWords, 1 ); Abc_TtAnd( Equa, Equa, Temp, nWords, 0 ); } if ( fEqual ) Abc_TtNot( pTruth, nWords ); } /**Function************************************************************* Synopsis [Adds parameter constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ifn_AddClause( sat_solver * pSat, int * pBeg, int * pEnd ) { int fVerbose = 0; int RetValue = sat_solver_addclause( pSat, pBeg, pEnd ); if ( fVerbose ) { for ( ; pBeg < pEnd; pBeg++ ) printf( "%c%d ", Abc_LitIsCompl(*pBeg) ? '-':'+', Abc_Lit2Var(*pBeg) ); printf( "\n" ); } return RetValue; } void Ifn_NtkAddConstrOne( sat_solver * pSat, Vec_Int_t * vCover, int * pVars, int nVars ) { int RetValue, k, c, Cube, Literal, nLits, pLits[IFN_INS]; Vec_IntForEachEntry( vCover, Cube, c ) { nLits = 0; for ( k = 0; k < nVars; k++ ) { Literal = 3 & (Cube >> (k << 1)); if ( Literal == 1 ) // '0' -> pos lit pLits[nLits++] = Abc_Var2Lit(pVars[k], 0); else if ( Literal == 2 ) // '1' -> neg lit pLits[nLits++] = Abc_Var2Lit(pVars[k], 1); else if ( Literal != 0 ) assert( 0 ); } RetValue = Ifn_AddClause( pSat, pLits, pLits + nLits ); assert( RetValue ); } } void Ifn_NtkAddConstraints( Ifn_Ntk_t * p, sat_solver * pSat ) { int fAddConstr = 1; Vec_Int_t * vCover = Vec_IntAlloc( 0 ); word uTruth = Abc_Tt6Stretch( ~Abc_Tt6Mask(p->nVars), p->nParsVNum ); assert( p->nParsVNum <= 4 ); if ( uTruth ) { int i, k, pVars[IFN_INS]; int RetValue = Kit_TruthIsop( (unsigned *)&uTruth, p->nParsVNum, vCover, 0 ); assert( RetValue == 0 ); // Dau_DsdPrintFromTruth( &uTruth, p->nParsVNum ); // add capacity constraints for ( i = 0; i < p->nInps; i++ ) { for ( k = 0; k < p->nParsVNum; k++ ) pVars[k] = p->nParsVIni + i * p->nParsVNum + k; Ifn_NtkAddConstrOne( pSat, vCover, pVars, p->nParsVNum ); } } // ordering constraints if ( fAddConstr && p->nConstr ) { word pTruth[4]; int i, k, RetValue, pVars[2*IFN_INS]; int fForceDiff = (p->nVars == p->nInps); Ifn_TtComparisonConstr( pTruth, p->nParsVNum, fForceDiff, fForceDiff ); RetValue = Kit_TruthIsop( (unsigned *)pTruth, 2*p->nParsVNum, vCover, 0 ); assert( RetValue == 0 ); // Kit_TruthIsopPrintCover( vCover, 2*p->nParsVNum, 0 ); for ( i = 0; i < p->nConstr; i++ ) { int iVar1 = p->pConstr[i] >> 16; int iVar2 = p->pConstr[i] & 0xFFFF; for ( k = 0; k < p->nParsVNum; k++ ) { pVars[2*k+0] = p->nParsVIni + iVar1 * p->nParsVNum + k; pVars[2*k+1] = p->nParsVIni + iVar2 * p->nParsVNum + k; } Ifn_NtkAddConstrOne( pSat, vCover, pVars, 2*p->nParsVNum ); // printf( "added constraint with %d clauses for %d and %d\n", Vec_IntSize(vCover), iVar1, iVar2 ); } } Vec_IntFree( vCover ); } /**Function************************************************************* Synopsis [Derive clauses given variable assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ifn_NtkAddClauses( Ifn_Ntk_t * p, int * pValues, sat_solver * pSat ) { int i, f, v, nLits, pLits[IFN_INS+2], pLits2[IFN_INS+2]; // assign new variables int nSatVars = sat_solver_nvars(pSat); // for ( i = 0; i < p->nObjs-1; i++ ) for ( i = 0; i < p->nObjs; i++ ) p->Nodes[i].Var = nSatVars++; //p->Nodes[p->nObjs-1].Var = 0xFFFF; sat_solver_setnvars( pSat, nSatVars ); // verify variable values for ( i = 0; i < p->nVars; i++ ) assert( pValues[i] != -1 ); for ( i = p->nVars; i < p->nObjs-1; i++ ) assert( pValues[i] == -1 ); assert( pValues[p->nObjs-1] != -1 ); // internal variables //printf( "\n" ); for ( i = 0; i < p->nInps; i++ ) { int iParStart = p->nParsVIni + i * p->nParsVNum; for ( v = 0; v < p->nVars; v++ ) { // add output literal pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, pValues[v]==0 ); // add clause literals for ( f = 0; f < p->nParsVNum; f++ ) pLits[f+1] = Abc_Var2Lit( iParStart + f, (v >> f) & 1 ); if ( !Ifn_AddClause( pSat, pLits, pLits+p->nParsVNum+1 ) ) return 0; } } //printf( "\n" ); for ( i = p->nInps; i < p->nObjs; i++ ) { int nFans = p->Nodes[i].nFanins; int * pFans = p->Nodes[i].Fanins; if ( p->Nodes[i].Type == IFN_DSD_AND ) { nLits = 0; pLits[nLits++] = Abc_Var2Lit( p->Nodes[i].Var, 0 ); for ( f = 0; f < nFans; f++ ) { pLits[nLits++] = Abc_Var2Lit( p->Nodes[pFans[f]].Var, 1 ); // add small clause pLits2[0] = Abc_Var2Lit( p->Nodes[i].Var, 1 ); pLits2[1] = Abc_Var2Lit( p->Nodes[pFans[f]].Var, 0 ); if ( !Ifn_AddClause( pSat, pLits2, pLits2 + 2 ) ) return 0; } // add big clause if ( !Ifn_AddClause( pSat, pLits, pLits + nLits ) ) return 0; } else if ( p->Nodes[i].Type == IFN_DSD_XOR ) { int m, nMints = (1 << (nFans+1)); for ( m = 0; m < nMints; m++ ) { // skip even int Count = 0; for ( v = 0; v <= nFans; v++ ) Count += ((m >> v) & 1); if ( (Count & 1) == 0 ) continue; // generate minterm pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, (m >> nFans) & 1 ); for ( v = 0; v < nFans; v++ ) pLits[v+1] = Abc_Var2Lit( p->Nodes[pFans[v]].Var, (m >> v) & 1 ); if ( !Ifn_AddClause( pSat, pLits, pLits + nFans + 1 ) ) return 0; } } else if ( p->Nodes[i].Type == IFN_DSD_MUX ) { pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, 0 ); pLits[1] = Abc_Var2Lit( p->Nodes[pFans[0]].Var, 1 ); // ctrl pLits[2] = Abc_Var2Lit( p->Nodes[pFans[1]].Var, 1 ); if ( !Ifn_AddClause( pSat, pLits, pLits + 3 ) ) return 0; pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, 1 ); pLits[1] = Abc_Var2Lit( p->Nodes[pFans[0]].Var, 1 ); // ctrl pLits[2] = Abc_Var2Lit( p->Nodes[pFans[1]].Var, 0 ); if ( !Ifn_AddClause( pSat, pLits, pLits + 3 ) ) return 0; pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, 0 ); pLits[1] = Abc_Var2Lit( p->Nodes[pFans[0]].Var, 0 ); // ctrl pLits[2] = Abc_Var2Lit( p->Nodes[pFans[2]].Var, 1 ); if ( !Ifn_AddClause( pSat, pLits, pLits + 3 ) ) return 0; pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, 1 ); pLits[1] = Abc_Var2Lit( p->Nodes[pFans[0]].Var, 0 ); // ctrl pLits[2] = Abc_Var2Lit( p->Nodes[pFans[2]].Var, 0 ); if ( !Ifn_AddClause( pSat, pLits, pLits + 3 ) ) return 0; } else if ( p->Nodes[i].Type == IFN_DSD_PRIME ) { int nValues = (1 << nFans); int iParStart = p->Nodes[i].iFirst; for ( v = 0; v < nValues; v++ ) { nLits = 0; if ( pValues[i] == -1 ) { pLits[nLits] = Abc_Var2Lit( p->Nodes[i].Var, 0 ); pLits2[nLits] = Abc_Var2Lit( p->Nodes[i].Var, 1 ); nLits++; } for ( f = 0; f < nFans; f++, nLits++ ) pLits[nLits] = pLits2[nLits] = Abc_Var2Lit( p->Nodes[pFans[f]].Var, (v >> f) & 1 ); pLits[nLits] = Abc_Var2Lit( iParStart + v, 1 ); pLits2[nLits] = Abc_Var2Lit( iParStart + v, 0 ); nLits++; if ( pValues[i] != 0 ) { if ( !Ifn_AddClause( pSat, pLits2, pLits2 + nLits ) ) return 0; } if ( pValues[i] != 1 ) { if ( !Ifn_AddClause( pSat, pLits, pLits + nLits ) ) return 0; } } } else assert( 0 ); //printf( "\n" ); } // add last clause (not needed if the root node is IFN_DSD_PRIME) pLits[0] = Abc_Var2Lit( p->Nodes[p->nObjs-1].Var, pValues[p->nObjs-1]==0 ); if ( !Ifn_AddClause( pSat, pLits, pLits + 1 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns the minterm number for which there is a mismatch.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ifn_NtkMatchPrintStatus( sat_solver * p, int Iter, int status, int iMint, int Value, abctime clk ) { printf( "Iter = %5d ", Iter ); printf( "Mint = %5d ", iMint ); printf( "Value = %2d ", Value ); printf( "Var = %6d ", sat_solver_nvars(p) ); printf( "Cla = %6d ", sat_solver_nclauses(p) ); printf( "Conf = %6d ", sat_solver_nconflicts(p) ); if ( status == l_False ) printf( "status = unsat" ); else if ( status == l_True ) printf( "status = sat " ); else printf( "status = undec" ); Abc_PrintTime( 1, "Time", clk ); } void Ifn_NtkMatchPrintConfig( Ifn_Ntk_t * p, sat_solver * pSat ) { int v, i; for ( v = p->nObjs; v < p->nPars; v++ ) { for ( i = p->nInps; i < p->nObjs; i++ ) if ( p->Nodes[i].Type == IFN_DSD_PRIME && (int)p->Nodes[i].iFirst == v ) break; if ( i < p->nObjs ) printf( " " ); else if ( v >= p->nParsVIni && (v - p->nParsVIni) % p->nParsVNum == 0 ) printf( " %d=", (v - p->nParsVIni) / p->nParsVNum ); printf( "%d", sat_solver_var_value(pSat, v) ); } } word Ifn_NtkMatchCollectPerm( Ifn_Ntk_t * p, sat_solver * pSat ) { word Perm = 0; int i, v, Mint; assert( p->nParsVNum <= 4 ); for ( i = 0; i < p->nInps; i++ ) { for ( Mint = v = 0; v < p->nParsVNum; v++ ) if ( sat_solver_var_value(pSat, p->nParsVIni + i * p->nParsVNum + v) ) Mint |= (1 << v); Abc_TtSetHex( &Perm, i, Mint ); } return Perm; } void Ifn_NtkMatchCollectConfig( Ifn_Ntk_t * p, sat_solver * pSat, word * pConfig ) { int i, v, Mint; assert( p->nParsVNum <= 4 ); for ( i = 0; i < p->nInps; i++ ) { for ( Mint = v = 0; v < p->nParsVNum; v++ ) if ( sat_solver_var_value(pSat, p->nParsVIni + i * p->nParsVNum + v) ) Mint |= (1 << v); Abc_TtSetHex( pConfig, i, Mint ); } for ( v = p->nObjs; v < p->nParsVIni; v++ ) if ( sat_solver_var_value(pSat, v) ) Abc_TtSetBit( pConfig + 1, v - p->nObjs ); } void Ifn_NtkMatchPrintPerm( word Perm, int nInps ) { int i; assert( nInps <= 16 ); for ( i = 0; i < nInps; i++ ) printf( "%c", 'a' + Abc_TtGetHex(&Perm, i) ); printf( "\n" ); } int Ifn_NtkMatch( Ifn_Ntk_t * p, word * pTruth, int nVars, int nConfls, int fVerbose, int fVeryVerbose, word * pConfig ) { word * pTruth1; int RetValue = 0; int nIterMax = (1<nPars ); Ifn_NtkAddConstraints( p, pSat ); if ( fVeryVerbose ) Ifn_NtkMatchPrintStatus( pSat, 0, l_True, -1, -1, Abc_Clock() - clk ); if ( pConfig ) assert( *pConfig == 0 ); for ( i = 0; i < nIterMax; i++ ) { // get variable assignment for ( v = 0; v < p->nObjs; v++ ) p->Values[v] = v < p->nVars ? (iMint >> v) & 1 : -1; p->Values[p->nObjs-1] = Abc_TtGetBit( pTruth, iMint ); // derive clauses if ( !Ifn_NtkAddClauses( p, p->Values, pSat ) ) break; // find assignment of parameters // clk2 = Abc_Clock(); status = sat_solver_solve( pSat, NULL, NULL, nConfls, 0, 0, 0 ); // clkSat += Abc_Clock() - clk2; if ( fVeryVerbose ) Ifn_NtkMatchPrintStatus( pSat, i+1, status, iMint, p->Values[p->nObjs-1], Abc_Clock() - clk ); if ( status != l_True ) break; // collect assignment for ( v = p->nObjs; v < p->nPars; v++ ) p->Values[v] = sat_solver_var_value(pSat, v); // find truth table // clk2 = Abc_Clock(); pTruth1 = Ifn_NtkDeriveTruth( p, p->Values ); // clkTru += Abc_Clock() - clk2; Abc_TtXor( pTruth1, pTruth1, p->pTruth, p->nWords, 0 ); // find mismatch if present iMint = Abc_TtFindFirstBit( pTruth1, p->nVars ); if ( iMint == -1 ) { if ( pConfig ) Ifn_NtkMatchCollectConfig( p, pSat, pConfig ); /* if ( pPerm ) { int RetValue = Ifn_ManSatFindCofigBitsTest( p, pTruth, nVars, *pPerm ); Ifn_NtkMatchPrintPerm( *pPerm, p->nInps ); if ( RetValue == 0 ) printf( "Verification failed.\n" ); } */ RetValue = 1; break; } } assert( i < nIterMax ); if ( fVerbose ) { printf( "%s Iter =%4d. Confl = %6d. ", RetValue ? "yes":"no ", i, sat_solver_nconflicts(pSat) ); if ( RetValue ) Ifn_NtkMatchPrintConfig( p, pSat ); printf( "\n" ); } sat_solver_delete( pSat ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // Abc_PrintTime( 1, "Sat", clkSat ); // Abc_PrintTime( 1, "Tru", clkTru ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ifn_NtkRead() { int RetValue; int nVars = 8; // word * pTruth = Dau_DsdToTruth( "(abcdefghi)", nVars ); word * pTruth = Dau_DsdToTruth( "1008{(1008{(ab)cde}f)ghi}", nVars ); // word * pTruth = Dau_DsdToTruth( "18{(1008{(ab)cde}f)gh}", nVars ); // word * pTruth = Dau_DsdToTruth( "1008{(1008{[ab]cde}f)ghi}", nVars ); // word * pTruth = Dau_DsdToTruth( "(abcd)", nVars ); // word * pTruth = Dau_DsdToTruth( "(abc)", nVars ); // word * pTruth = Dau_DsdToTruth( "18{(1008{(ab)cde}f)gh}", nVars ); // char * pStr = "e={abc};f={ed};"; // char * pStr = "d={ab};e={cd};"; // char * pStr = "j=(ab);k={jcde};l=(kf);m={lghi};"; // char * pStr = "i={abc};j={ide};k={ifg};l={jkh};"; // char * pStr = "h={abcde};i={abcdf};j=;"; // char * pStr = "g=;h=;i={fgh};"; // char * pStr = "i=;j=(def);k=[gh];l={ijk};"; char * pStr = "{({(ab)cde}f)ghi};AB;CD;DE;GH;HI"; Ifn_Ntk_t * p = Ifn_NtkParse( pStr ); word Perm = 0; if ( p == NULL ) return; Ifn_NtkPrint( p ); Dau_DsdPrintFromTruth( pTruth, nVars ); // get the given function RetValue = Ifn_NtkMatch( p, pTruth, nVars, 0, 1, 1, &Perm ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/ifUtil.c000066400000000000000000000441131300674244400226120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ifUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifUtil.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sets all the node copy to NULL.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCleanNodeCopy( If_Man_t * p ) { If_Obj_t * pObj; int i; If_ManForEachObj( p, pObj, i ) If_ObjSetCopy( pObj, NULL ); } /**Function************************************************************* Synopsis [Sets all the cut data to NULL.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCleanCutData( If_Man_t * p ) { If_Obj_t * pObj; int i; If_ManForEachObj( p, pObj, i ) If_CutSetData( If_ObjCutBest(pObj), NULL ); } /**Function************************************************************* Synopsis [Sets all visited marks to 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCleanMarkV( If_Man_t * p ) { If_Obj_t * pObj; int i; If_ManForEachObj( p, pObj, i ) pObj->fVisit = 0; } #if 0 /**Function************************************************************* Synopsis [Computes area, references, and nodes used in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_ManScanMapping_rec( If_Man_t * p, If_Obj_t * pObj, If_Obj_t ** ppStore ) { If_Obj_t * pLeaf; If_Cut_t * pCutBest; float aArea; int i; if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) ) return 0.0; // store the node in the structure by level assert( If_ObjIsAnd(pObj) ); pObj->pCopy = (char *)ppStore[pObj->Level]; ppStore[pObj->Level] = pObj; // visit the transitive fanin of the selected cut pCutBest = If_ObjCutBest(pObj); p->nNets += pCutBest->nLeaves; aArea = If_CutLutArea( p, pCutBest ); If_CutForEachLeaf( p, pCutBest, pLeaf, i ) aArea += If_ManScanMapping_rec( p, pLeaf, ppStore ); return aArea; } /**Function************************************************************* Synopsis [Computes area, references, and nodes used in the mapping.] Description [Collects the nodes in reverse topological order in array p->vMapping.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_ManScanMapping( If_Man_t * p ) { If_Obj_t * pObj, ** ppStore; float aArea; int i; assert( !p->pPars->fLiftLeaves ); // clean all references p->nNets = 0; If_ManForEachObj( p, pObj, i ) { pObj->Required = IF_FLOAT_LARGE; pObj->nVisits = pObj->nVisitsCopy; pObj->nRefs = 0; } // allocate place to store the nodes ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 ); memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); // collect nodes reachable from POs in the DFS order through the best cuts aArea = 0; If_ManForEachCo( p, pObj, i ) aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore ); // reconnect the nodes in reverse topological order Vec_PtrClear( p->vMapped ); for ( i = p->nLevelMax; i >= 0; i-- ) for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy ) Vec_PtrPush( p->vMapped, pObj ); ABC_FREE( ppStore ); return aArea; } /**Function************************************************************* Synopsis [Computes area, references, and nodes used in the mapping.] Description [Collects the nodes in reverse topological order in array p->vMapping.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_ManScanMappingDirect( If_Man_t * p ) { If_Obj_t * pObj, ** ppStore; float aArea; int i; assert( !p->pPars->fLiftLeaves ); // clean all references If_ManForEachObj( p, pObj, i ) { pObj->Required = IF_FLOAT_LARGE; pObj->nVisits = pObj->nVisitsCopy; pObj->nRefs = 0; } // allocate place to store the nodes ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 ); memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); // collect nodes reachable from POs in the DFS order through the best cuts aArea = 0; If_ManForEachCo( p, pObj, i ) aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore ); // reconnect the nodes in reverse topological order Vec_PtrClear( p->vMapped ); // for ( i = p->nLevelMax; i >= 0; i-- ) for ( i = 0; i <= p->nLevelMax; i++ ) for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy ) Vec_PtrPush( p->vMapped, pObj ); ABC_FREE( ppStore ); return aArea; } /**Function************************************************************* Synopsis [Computes area, references, and nodes used in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_ManScanMappingSeq_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vMapped ) { If_Obj_t * pLeaf; If_Cut_t * pCutBest; float aArea; int i, Shift; // treat latches transparently if ( If_ObjIsLatch(pObj) ) return If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), vMapped ); // consider trivial cases if ( pObj->nRefs++ || If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) ) return 0.0; // store the node in the structure by level assert( If_ObjIsAnd(pObj) ); // visit the transitive fanin of the selected cut pCutBest = If_ObjCutBest(pObj); aArea = If_ObjIsAnd(pObj)? If_CutLutArea(p, pCutBest) : (float)0.0; If_CutForEachLeafSeq( p, pCutBest, pLeaf, Shift, i ) aArea += If_ManScanMappingSeq_rec( p, pLeaf, vMapped ); // add the node Vec_PtrPush( vMapped, pObj ); return aArea; } /**Function************************************************************* Synopsis [Computes area, references, and nodes used in the mapping.] Description [Collects the nodes in reverse topological order in array p->vMapping.] SideEffects [] SeeAlso [] ***********************************************************************/ float If_ManScanMappingSeq( If_Man_t * p ) { If_Obj_t * pObj; float aArea; int i; assert( p->pPars->fLiftLeaves ); // clean all references If_ManForEachObj( p, pObj, i ) pObj->nRefs = 0; // collect nodes reachable from POs in the DFS order through the best cuts aArea = 0; Vec_PtrClear( p->vMapped ); If_ManForEachPo( p, pObj, i ) aArea += If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), p->vMapped ); return aArea; } #endif /**Function************************************************************* Synopsis [Computes area, references, and nodes used in the mapping.] Description [Collects the nodes in reverse topological order in array p->vMapping.] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManResetOriginalRefs( If_Man_t * p ) { If_Obj_t * pObj; int i; If_ManForEachObj( p, pObj, i ) pObj->nRefs = 0; If_ManForEachObj( p, pObj, i ) { if ( If_ObjIsAnd(pObj) ) { pObj->pFanin0->nRefs++; pObj->pFanin1->nRefs++; } else if ( If_ObjIsCo(pObj) ) pObj->pFanin0->nRefs++; } } /**Function************************************************************* Synopsis [Computes cross-cut of the circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManCrossCut( If_Man_t * p ) { If_Obj_t * pObj, * pFanin; int i, nCutSize = 0, nCutSizeMax = 0; If_ManForEachObj( p, pObj, i ) { if ( !If_ObjIsAnd(pObj) ) continue; // consider the node if ( nCutSizeMax < ++nCutSize ) nCutSizeMax = nCutSize; if ( pObj->nVisits == 0 ) nCutSize--; // consider the fanins pFanin = If_ObjFanin0(pObj); if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) nCutSize--; pFanin = If_ObjFanin1(pObj); if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) nCutSize--; // consider the choice class if ( pObj->fRepr ) for ( pFanin = pObj; pFanin; pFanin = pFanin->pEquiv ) if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) nCutSize--; } If_ManForEachObj( p, pObj, i ) { assert( If_ObjIsCi(pObj) || pObj->fVisit == 0 ); pObj->nVisits = pObj->nVisitsCopy; } assert( nCutSize == 0 ); // Abc_Print( 1, "Max cross cut size = %6d.\n", nCutSizeMax ); return nCutSizeMax; } /**Function************************************************************* Synopsis [Computes the reverse topological order of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * If_ManReverseOrder( If_Man_t * p ) { Vec_Ptr_t * vOrder; If_Obj_t * pObj, ** ppStore; int i; // allocate place to store the nodes ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 ); memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); // add the nodes If_ManForEachObj( p, pObj, i ) { assert( pObj->Level >= 0 && pObj->Level <= (unsigned)p->nLevelMax ); pObj->pCopy = (char *)ppStore[pObj->Level]; ppStore[pObj->Level] = pObj; } vOrder = Vec_PtrAlloc( If_ManObjNum(p) ); for ( i = p->nLevelMax; i >= 0; i-- ) for ( pObj = ppStore[i]; pObj; pObj = (If_Obj_t *)pObj->pCopy ) Vec_PtrPush( vOrder, pObj ); ABC_FREE( ppStore ); // print the order // Vec_PtrForEachEntry( If_Obj_t *, vOrder, pObj, i ) // Abc_Print( 1, "Obj %2d Type %d Level = %d\n", pObj->Id, pObj->Type, pObj->Level ); return vOrder; } /**Function************************************************************* Synopsis [Computes area, references, and nodes used in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pLeaf; If_Cut_t * pCutBest; float * pSwitching = p->vSwitching? (float*)p->vSwitching->pArray : NULL; float aArea; int i; if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) ) return 0.0; // store the node in the structure by level assert( If_ObjIsAnd(pObj) ); // visit the transitive fanin of the selected cut pCutBest = If_ObjCutBest(pObj); p->nNets += pCutBest->nLeaves; aArea = If_CutLutArea( p, pCutBest ); If_CutForEachLeaf( p, pCutBest, pLeaf, i ) { p->dPower += pSwitching? pSwitching[pLeaf->Id] : 0.0; aArea += If_ManMarkMapping_rec( p, pLeaf ); } return aArea; } /**Function************************************************************* Synopsis [Computes area, references, and nodes used in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManMarkMapping( If_Man_t * p ) { If_Obj_t * pObj; int i; If_ManForEachObj( p, pObj, i ) { pObj->Required = IF_FLOAT_LARGE; pObj->nVisits = pObj->nVisitsCopy; pObj->nRefs = 0; } p->nNets = 0; p->dPower = 0.0; p->AreaGlo = 0.0; If_ManForEachCo( p, pObj, i ) p->AreaGlo += If_ManMarkMapping_rec( p, If_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [Collects nodes used in the mapping in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * If_ManCollectMappingDirect( If_Man_t * p ) { Vec_Ptr_t * vOrder; If_Obj_t * pObj; int i; If_ManMarkMapping( p ); vOrder = Vec_PtrAlloc( If_ManObjNum(p) ); If_ManForEachObj( p, pObj, i ) if ( If_ObjIsAnd(pObj) && pObj->nRefs ) Vec_PtrPush( vOrder, pObj ); return vOrder; } /**Function************************************************************* Synopsis [Collects nodes used in the mapping in the topological order.] Description [Represents mapping as an array of integers.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * If_ManCollectMappingInt( If_Man_t * p ) { Vec_Int_t * vOrder; If_Cut_t * pCutBest; If_Obj_t * pObj; int i, k, nLeaves, * ppLeaves; If_ManMarkMapping( p ); vOrder = Vec_IntAlloc( If_ManObjNum(p) ); If_ManForEachObj( p, pObj, i ) if ( If_ObjIsAnd(pObj) && pObj->nRefs ) { pCutBest = If_ObjCutBest( pObj ); nLeaves = If_CutLeaveNum( pCutBest ); ppLeaves = If_CutLeaves( pCutBest ); // save the number of leaves, the leaves, and finally, the root Vec_IntPush( vOrder, nLeaves ); for ( k = 0; k < nLeaves; k++ ) Vec_IntPush( vOrder, ppLeaves[k] ); Vec_IntPush( vOrder, pObj->Id ); } return vOrder; } /**Function************************************************************* Synopsis [Returns the number of POs pointing to the same internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManCountSpecialPos( If_Man_t * p ) { If_Obj_t * pObj; int i, Counter = 0; // clean all marks If_ManForEachPo( p, pObj, i ) If_ObjFanin0(pObj)->fMark = 0; // label nodes If_ManForEachPo( p, pObj, i ) if ( !If_ObjFaninC0(pObj) ) If_ObjFanin0(pObj)->fMark = 1; // label nodes If_ManForEachPo( p, pObj, i ) if ( If_ObjFaninC0(pObj) ) Counter += If_ObjFanin0(pObj)->fMark; // clean all marks If_ManForEachPo( p, pObj, i ) If_ObjFanin0(pObj)->fMark = 0; return Counter; } /**Function************************************************************* Synopsis [Traverse the cut and counts its volume.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void If_CutTraverse_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes ) { if ( pNode->fMark ) return; pNode->fMark = 1; // assert( !If_ObjIsCi(pNode) ); // does not hold with cut minimization if ( If_ObjIsAnd(pNode) ) If_CutTraverse_rec( If_ObjFanin0(pNode), vNodes ); if ( If_ObjIsAnd(pNode) ) If_CutTraverse_rec( If_ObjFanin1(pNode), vNodes ); Vec_PtrPush( vNodes, pNode ); } void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ) { If_Obj_t * pLeaf; int i; // collect the internal nodes of the cut Vec_PtrClear( vNodes ); If_CutForEachLeaf( p, pCut, pLeaf, i ) { Vec_PtrPush( vNodes, pLeaf ); assert( pLeaf->fMark == 0 ); pLeaf->fMark = 1; } // collect other nodes If_CutTraverse_rec( pRoot, vNodes ); // clean the mark Vec_PtrForEachEntry( If_Obj_t *, vNodes, pLeaf, i ) pLeaf->fMark = 0; } void If_CutTraverseTest( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut ) { Vec_Ptr_t * vNodes; vNodes = Vec_PtrAlloc( 1000 ); If_CutTraverse( p, pRoot, pCut, vNodes ); //if ( Vec_PtrSize(vNodes) > 30 ) //printf( "%d ", Vec_PtrSize(vNodes) ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ObjPrint( If_Obj_t * pObj ) { if ( pObj == NULL ) { printf( "Object is NULL." ); return; } printf( "Obj %4d : ", If_ObjId(pObj) ); if ( If_ObjIsConst1(pObj) ) printf( "constant 1" ); else if ( If_ObjIsCi(pObj) ) printf( "PI" ); else if ( If_ObjIsCo(pObj) ) printf( "PO( %4d%s )", If_ObjId(If_ObjFanin0(pObj)), (If_ObjFaninC0(pObj)? "\'" : " ") ); else printf( "AND( %4d%s, %4d%s )", If_ObjId(If_ObjFanin0(pObj)), (If_ObjFaninC0(pObj)? "\'" : " "), If_ObjId(If_ObjFanin1(pObj)), (If_ObjFaninC1(pObj)? "\'" : " ") ); printf( " (refs = %3d)", pObj->nVisitsCopy ); printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/if_.c000066400000000000000000000026621300674244400221160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [if_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: if_.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/if/module.make000066400000000000000000000011501300674244400233300ustar00rootroot00000000000000SRC += src/map/if/ifCom.c \ src/map/if/ifCache.c \ src/map/if/ifCore.c \ src/map/if/ifCut.c \ src/map/if/ifData2.c \ src/map/if/ifDec07.c \ src/map/if/ifDec08.c \ src/map/if/ifDec10.c \ src/map/if/ifDec16.c \ src/map/if/ifDec75.c \ src/map/if/ifDelay.c \ src/map/if/ifDsd.c \ src/map/if/ifLibBox.c \ src/map/if/ifLibLut.c \ src/map/if/ifMan.c \ src/map/if/ifMap.c \ src/map/if/ifMatch2.c \ src/map/if/ifReduce.c \ src/map/if/ifSat.c \ src/map/if/ifSelect.c \ src/map/if/ifSeq.c \ src/map/if/ifTest.c \ src/map/if/ifTime.c \ src/map/if/ifTruth.c \ src/map/if/ifTune.c \ src/map/if/ifUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/000077500000000000000000000000001300674244400220755ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapper.c000066400000000000000000000124011300674244400235230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapper.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Command file for the mapper package.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapper.c,v 1.7 2005/01/23 06:59:42 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "map/mio/mio.h" #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Map_CommandReadLibrary ( Abc_Frame_t * pAbc, int argc, char **argv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "SC mapping", "read_super", Map_CommandReadLibrary, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_End( Abc_Frame_t * pAbc ) { // Map_SuperLibFree( s_pSuperLib ); Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; Map_SuperLib_t * pLib; Abc_Ntk_t * pNet; char * FileName, * ExcludeFile; int fVerbose; int fAlgorithm; int c; pNet = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 1; fAlgorithm = 1; ExcludeFile = 0; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "eovh")) != EOF ) { switch (c) { case 'e': ExcludeFile = argv[globalUtilOptind]; if ( ExcludeFile == 0 ) goto usage; globalUtilOptind++; break; case 'o': fAlgorithm ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name FileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) // if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); if (( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) ) fprintf( pErr, "Did you mean \"%s\"?", FileName ); fprintf( pErr, "\n" ); return 1; } fclose( pFile ); if ( Abc_FrameReadLibGen() == NULL ) { fprintf( pErr, "Genlib library should be read in first..\n" ); return 1; } // set the new network pLib = Map_SuperLibCreate( (Mio_Library_t *)Abc_FrameReadLibGen(), NULL, FileName, ExcludeFile, fAlgorithm, fVerbose ); if ( pLib == NULL ) { fprintf( pErr, "Reading supergate library has failed.\n" ); return 1; } // replace the current library // Map_SuperLibFree( s_pSuperLib ); // s_pSuperLib = pLib; Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() ); Abc_FrameSetLibSuper( pLib ); // replace the current genlib library // Mio_LibraryDelete( (Mio_Library_t *)Abc_FrameReadLibGen() ); // Abc_FrameSetLibGen( (Mio_Library_t *)pLib->pGenlib ); return 0; usage: fprintf( pErr, "\nusage: read_super [-ovh]\n"); fprintf( pErr, "\t read the supergate library from the file\n" ); fprintf( pErr, "\t-e file : file contains list of genlib gates to exclude\n" ); fprintf( pErr, "\t-o : toggles the use of old file format [default = %s]\n", (fAlgorithm? "new" : "old") ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; /* error exit */ } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapper.h000066400000000000000000000254301300674244400235360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapper.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapper.h,v 1.11 2005/02/28 05:34:26 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__mapper__mapper_h #define ABC__map__mapper__mapper_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Map_ManStruct_t_ Map_Man_t; typedef struct Map_NodeStruct_t_ Map_Node_t; typedef struct Map_NodeVecStruct_t_ Map_NodeVec_t; typedef struct Map_CutStruct_t_ Map_Cut_t; typedef struct Map_MatchStruct_t_ Map_Match_t; typedef struct Map_SuperStruct_t_ Map_Super_t; typedef struct Map_SuperLibStruct_t_ Map_SuperLib_t; typedef struct Map_HashTableStruct_t_ Map_HashTable_t; typedef struct Map_HashEntryStruct_t_ Map_HashEntry_t; typedef struct Map_TimeStruct_t_ Map_Time_t; // the pair of rise/fall time parameters struct Map_TimeStruct_t_ { float Rise; float Fall; float Worst; }; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Map_IsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01))) #define Map_Regular(p) ((Map_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) #define Map_Not(p) ((Map_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) #define Map_NotCond(p,c) ((Map_Node_t *)((ABC_PTRUINT_T)(p) ^ (c))) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mapperCreate.c =============================================================*/ extern Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ); extern Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); extern void Map_ManCreateNodeDelays( Map_Man_t * p, int LogFan ); extern void Map_ManFree( Map_Man_t * pMan ); extern void Map_ManPrintTimeStats( Map_Man_t * p ); extern void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, abctime Time ); extern int Map_ManReadInputNum( Map_Man_t * p ); extern int Map_ManReadOutputNum( Map_Man_t * p ); extern int Map_ManReadBufNum( Map_Man_t * p ); extern Map_Node_t ** Map_ManReadInputs ( Map_Man_t * p ); extern Map_Node_t ** Map_ManReadOutputs( Map_Man_t * p ); extern Map_Node_t ** Map_ManReadBufs( Map_Man_t * p ); extern Map_Node_t * Map_ManReadBufDriver( Map_Man_t * p, int i ); extern Map_Node_t * Map_ManReadConst1 ( Map_Man_t * p ); extern Map_Time_t * Map_ManReadInputArrivals( Map_Man_t * p ); extern Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p ); extern int Map_ManReadVerbose( Map_Man_t * p ); extern float Map_ManReadAreaFinal( Map_Man_t * p ); extern float Map_ManReadRequiredGlo( Map_Man_t * p ); extern void Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames ); extern void Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery ); extern void Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget ); extern void Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals ); extern void Map_ManSetOutputRequireds( Map_Man_t * p, Map_Time_t * pArrivals ); extern void Map_ManSetObeyFanoutLimits( Map_Man_t * p, int fObeyFanoutLimits ); extern void Map_ManSetNumIterations( Map_Man_t * p, int nNumIterations ); extern int Map_ManReadPass( Map_Man_t * p ); extern void Map_ManSetPass( Map_Man_t * p, int nPass ); extern int Map_ManReadFanoutViolations( Map_Man_t * p ); extern void Map_ManSetFanoutViolations( Map_Man_t * p, int nVio ); extern void Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes ); extern void Map_ManSetChoiceNum( Map_Man_t * p, int nChoices ); extern void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ); extern void Map_ManSetSwitching( Map_Man_t * p, int fSwitching ); extern void Map_ManSetSkipFanout( Map_Man_t * p, int fSkipFanout ); extern void Map_ManSetUseProfile( Map_Man_t * p ); extern Map_Man_t * Map_NodeReadMan( Map_Node_t * p ); extern char * Map_NodeReadData( Map_Node_t * p, int fPhase ); extern int Map_NodeReadNum( Map_Node_t * p ); extern int Map_NodeReadLevel( Map_Node_t * p ); extern Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ); extern Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ); extern Map_Node_t * Map_NodeReadOne( Map_Node_t * p ); extern Map_Node_t * Map_NodeReadTwo( Map_Node_t * p ); extern void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ); extern void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ); extern void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ); extern void Map_NodeSetSwitching( Map_Node_t * p, float Switching ); extern int Map_NodeIsConst( Map_Node_t * p ); extern int Map_NodeIsVar( Map_Node_t * p ); extern int Map_NodeIsBuf( Map_Node_t * p ); extern int Map_NodeIsAnd( Map_Node_t * p ); extern int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ); extern Map_Super_t * Map_CutReadSuperBest( Map_Cut_t * p, int fPhase ); extern Map_Super_t * Map_CutReadSuper0( Map_Cut_t * p ); extern Map_Super_t * Map_CutReadSuper1( Map_Cut_t * p ); extern int Map_CutReadLeavesNum( Map_Cut_t * p ); extern Map_Node_t ** Map_CutReadLeaves( Map_Cut_t * p ); extern unsigned Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase ); extern unsigned Map_CutReadPhase0( Map_Cut_t * p ); extern unsigned Map_CutReadPhase1( Map_Cut_t * p ); extern Map_Cut_t * Map_CutReadNext( Map_Cut_t * p ); extern char * Map_SuperReadFormula( Map_Super_t * p ); extern Mio_Gate_t * Map_SuperReadRoot( Map_Super_t * p ); extern int Map_SuperReadNum( Map_Super_t * p ); extern Map_Super_t ** Map_SuperReadFanins( Map_Super_t * p ); extern int Map_SuperReadFaninNum( Map_Super_t * p ); extern Map_Super_t * Map_SuperReadNext( Map_Super_t * p ); extern int Map_SuperReadNumPhases( Map_Super_t * p ); extern unsigned char * Map_SuperReadPhases( Map_Super_t * p ); extern int Map_SuperReadFanoutLimit( Map_Super_t * p ); extern Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p ); extern float Map_SuperLibReadAreaInv( Map_SuperLib_t * p ); extern Map_Time_t Map_SuperLibReadDelayInv( Map_SuperLib_t * p ); extern int Map_SuperLibReadVarsMax( Map_SuperLib_t * p ); extern Map_Node_t * Map_NodeAnd( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); extern Map_Node_t * Map_NodeBuf( Map_Man_t * p, Map_Node_t * p1 ); extern void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew ); /*=== resmCanon.c =============================================================*/ extern int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ); extern int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ); /*=== mapperCut.c =============================================================*/ extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p ); /*=== mapperCutUtils.c =============================================================*/ extern void Map_CutCreateFromNode( Map_Man_t * p, Map_Super_t * pSuper, int iRoot, unsigned uPhaseRoot, int * pLeaves, int nLeaves, unsigned uPhaseLeaves ); /*=== mapperCore.c =============================================================*/ extern int Map_Mapping( Map_Man_t * p ); /*=== mapperLib.c =============================================================*/ extern int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib, int fVerbose ); extern void Map_SuperLibFree( Map_SuperLib_t * p ); /*=== mapperMntk.c =============================================================*/ //extern Mntk_Man_t * Map_ConvertMappingToMntk( Map_Man_t * pMan ); /*=== mapperSuper.c =============================================================*/ extern char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings ); /*=== mapperSweep.c =============================================================*/ extern void Map_NetworkSweep( Abc_Ntk_t * pNet ); /*=== mapperTable.c =============================================================*/ extern Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * pLib, unsigned uTruth[] ); /*=== mapperTime.c =============================================================*/ /*=== mapperUtil.c =============================================================*/ extern int Map_ManCheckConsistency( Map_Man_t * p ); extern st__table * Map_CreateTableGate2Super( Map_Man_t * p ); extern void Map_ManCleanData( Map_Man_t * p ); extern void Map_MappingSetupTruthTables( unsigned uTruths[][2] ); extern void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperCanon.c000066400000000000000000000217671300674244400245210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperCanon.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperCanon.c,v 1.2 2005/01/23 06:59:42 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ); static void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the N-canonical form of the Boolean function.] Description [The N-canonical form is defined as the truth table with the minimum integer value. This function exhaustively enumerates through the complete set of 2^N phase assignments.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ) { unsigned uTruthPerm[2]; int nMints, nPhases, m; nPhases = 0; nMints = (1 << nVarsReal); if ( nVarsMax < 6 ) { uTruthRes[0] = MAP_MASK(32); for ( m = 0; m < nMints; m++ ) { uTruthPerm[0] = Map_CanonComputePhase( uTruths, nVarsMax, uTruth[0], m ); if ( uTruthRes[0] > uTruthPerm[0] ) { uTruthRes[0] = uTruthPerm[0]; nPhases = 0; puPhases[nPhases++] = (unsigned char)m; } else if ( uTruthRes[0] == uTruthPerm[0] ) { if ( nPhases < 4 ) // the max number of phases in Map_Super_t puPhases[nPhases++] = (unsigned char)m; } } uTruthRes[1] = uTruthRes[0]; } else { uTruthRes[0] = MAP_MASK(32); uTruthRes[1] = MAP_MASK(32); for ( m = 0; m < nMints; m++ ) { Map_CanonComputePhase6( uTruths, nVarsMax, uTruth, m, uTruthPerm ); if ( uTruthRes[1] > uTruthPerm[1] || (uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] > uTruthPerm[0]) ) { uTruthRes[0] = uTruthPerm[0]; uTruthRes[1] = uTruthPerm[1]; nPhases = 0; puPhases[nPhases++] = (unsigned char)m; } else if ( uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] == uTruthPerm[0] ) { if ( nPhases < 4 ) // the max number of phases in Map_Super_t puPhases[nPhases++] = (unsigned char)m; } } } assert( nPhases > 0 ); // printf( "%d ", nPhases ); return nPhases; } /**Function************************************************************* Synopsis [Performs phase transformation for one function of less than 6 variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ) { int v, Shift; for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) if ( uPhase & Shift ) uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift)); return uTruth; } /**Function************************************************************* Synopsis [Performs phase transformation for one function of 6 variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ) { unsigned uTemp; int v, Shift; // initialize the result uTruthRes[0] = uTruth[0]; uTruthRes[1] = uTruth[1]; if ( uPhase == 0 ) return; // compute the phase for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) if ( uPhase & Shift ) { if ( Shift < 32 ) { uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift)); uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift)); } else { uTemp = uTruthRes[0]; uTruthRes[0] = uTruthRes[1]; uTruthRes[1] = uTemp; } } } /**Function************************************************************* Synopsis [Computes the N-canonical form of the Boolean function.] Description [The N-canonical form is defined as the truth table with the minimum integer value. This function exhaustively enumerates through the complete set of 2^N phase assignments.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ) { unsigned uTruth0, uTruth1; unsigned uCanon0, uCanon1, uCanonBest; unsigned uPhaseBest = 16; // Suppress "might be used uninitialized" (asserts require < 16) int i, Limit; if ( nVarsMax == 6 ) return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); if ( nVarsReal < 5 ) { // return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); uTruth0 = uTruth[0] & 0xFFFF; assert( p->pCounters[uTruth0] > 0 ); uTruthRes[0] = (p->uCanons[uTruth0] << 16) | p->uCanons[uTruth0]; uTruthRes[1] = uTruthRes[0]; puPhases[0] = p->uPhases[uTruth0][0]; return 1; } assert( nVarsMax == 5 ); assert( nVarsReal == 5 ); uTruth0 = uTruth[0] & 0xFFFF; uTruth1 = (uTruth[0] >> 16); if ( uTruth1 == 0 ) { uTruthRes[0] = p->uCanons[uTruth0]; uTruthRes[1] = uTruthRes[0]; Limit = (p->pCounters[uTruth0] > 4)? 4 : p->pCounters[uTruth0]; for ( i = 0; i < Limit; i++ ) puPhases[i] = p->uPhases[uTruth0][i]; return Limit; } else if ( uTruth0 == 0 ) { uTruthRes[0] = p->uCanons[uTruth1]; uTruthRes[1] = uTruthRes[0]; Limit = (p->pCounters[uTruth1] > 4)? 4 : p->pCounters[uTruth1]; for ( i = 0; i < Limit; i++ ) { puPhases[i] = p->uPhases[uTruth1][i]; puPhases[i] |= (1 << 4); } return Limit; } uCanon0 = p->uCanons[uTruth0]; uCanon1 = p->uCanons[uTruth1]; if ( uCanon0 >= uCanon1 ) // using nCanon1 as the main one { assert( p->pCounters[uTruth1] > 0 ); uCanonBest = 0xFFFFFFFF; for ( i = 0; i < p->pCounters[uTruth1]; i++ ) { uCanon0 = Extra_TruthPolarize( uTruth0, p->uPhases[uTruth1][i], 4 ); if ( uCanonBest > uCanon0 ) { uCanonBest = uCanon0; uPhaseBest = p->uPhases[uTruth1][i]; assert( uPhaseBest < 16 ); } } uTruthRes[0] = (uCanon1 << 16) | uCanonBest; uTruthRes[1] = uTruthRes[0]; puPhases[0] = uPhaseBest; return 1; } else if ( uCanon0 < uCanon1 ) { assert( p->pCounters[uTruth0] > 0 ); uCanonBest = 0xFFFFFFFF; for ( i = 0; i < p->pCounters[uTruth0]; i++ ) { uCanon1 = Extra_TruthPolarize( uTruth1, p->uPhases[uTruth0][i], 4 ); if ( uCanonBest > uCanon1 ) { uCanonBest = uCanon1; uPhaseBest = p->uPhases[uTruth0][i]; assert( uPhaseBest < 16 ); } } uTruthRes[0] = (uCanon0 << 16) | uCanonBest; uTruthRes[1] = uTruthRes[0]; puPhases[0] = uPhaseBest | (1 << 4); return 1; } else { assert( 0 ); return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperCore.c000066400000000000000000000205351300674244400243430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperCore.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $] ***********************************************************************/ #include "mapperInt.h" //#include "resm.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs technology mapping for the given object graph.] Description [The object graph is stored in the mapping manager. First, the AND nodes that fanout into POs are collected in the DFS order. Two preprocessing steps are performed: the k-feasible cuts are computed for each node and the truth tables are computed for each cut. Next, the delay-optimal matches are assigned for each node, followed by several iterations of area recoveryd: using area flow (global optimization) and using exact area at a node (local optimization).] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_Mapping( Map_Man_t * p ) { int fShowSwitching = 0; int fUseAreaFlow = 1; int fUseExactArea = !p->fSwitching; int fUseExactAreaWithPhase = !p->fSwitching; abctime clk; ////////////////////////////////////////////////////////////////////// // perform pre-mapping computations if ( p->fVerbose ) Map_MappingReportChoices( p ); Map_MappingSetChoiceLevels( p ); // should always be called before mapping! // return 1; // compute the cuts of nodes in the DFS order clk = Abc_Clock(); Map_MappingCuts( p ); p->timeCuts = Abc_Clock() - clk; // derive the truth tables clk = Abc_Clock(); Map_MappingTruths( p ); p->timeTruth = Abc_Clock() - clk; ////////////////////////////////////////////////////////////////////// //ABC_PRT( "Truths", Abc_Clock() - clk ); ////////////////////////////////////////////////////////////////////// // compute the minimum-delay mapping clk = Abc_Clock(); p->fMappingMode = 0; if ( !Map_MappingMatches( p ) ) return 0; p->timeMatch = Abc_Clock() - clk; // compute the references and collect the nodes used in the mapping Map_MappingSetRefs( p ); p->AreaBase = Map_MappingGetArea( p ); if ( p->fVerbose ) { printf( "Delay : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", fShowSwitching? "Switch" : "Delay", fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, Map_MappingGetAreaFlow(p), p->AreaBase, 0.0 ); ABC_PRT( "Time", p->timeMatch ); } ////////////////////////////////////////////////////////////////////// if ( !p->fAreaRecovery ) { if ( p->fVerbose ) Map_MappingPrintOutputArrivals( p ); return 1; } ////////////////////////////////////////////////////////////////////// // perform area recovery using area flow clk = Abc_Clock(); if ( fUseAreaFlow ) { // compute the required times Map_TimeComputeRequiredGlobal( p ); // recover area flow p->fMappingMode = 1; Map_MappingMatches( p ); // compute the references and collect the nodes used in the mapping Map_MappingSetRefs( p ); p->AreaFinal = Map_MappingGetArea( p ); if ( p->fVerbose ) { printf( "AreaFlow : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", fShowSwitching? "Switch" : "Delay", fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, Map_MappingGetAreaFlow(p), p->AreaFinal, 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); ABC_PRT( "Time", Abc_Clock() - clk ); } } p->timeArea += Abc_Clock() - clk; ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // perform area recovery using exact area clk = Abc_Clock(); if ( fUseExactArea ) { // compute the required times Map_TimeComputeRequiredGlobal( p ); // recover area p->fMappingMode = 2; Map_MappingMatches( p ); // compute the references and collect the nodes used in the mapping Map_MappingSetRefs( p ); p->AreaFinal = Map_MappingGetArea( p ); if ( p->fVerbose ) { printf( "Area : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", fShowSwitching? "Switch" : "Delay", fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 0.0, p->AreaFinal, 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); ABC_PRT( "Time", Abc_Clock() - clk ); } } p->timeArea += Abc_Clock() - clk; ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // perform area recovery using exact area clk = Abc_Clock(); if ( fUseExactAreaWithPhase ) { // compute the required times Map_TimeComputeRequiredGlobal( p ); // recover area p->fMappingMode = 3; Map_MappingMatches( p ); // compute the references and collect the nodes used in the mapping Map_MappingSetRefs( p ); p->AreaFinal = Map_MappingGetArea( p ); if ( p->fVerbose ) { printf( "Area : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", fShowSwitching? "Switch" : "Delay", fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 0.0, p->AreaFinal, 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); ABC_PRT( "Time", Abc_Clock() - clk ); } } p->timeArea += Abc_Clock() - clk; ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // perform area recovery using exact area clk = Abc_Clock(); if ( p->fSwitching ) { // compute the required times Map_TimeComputeRequiredGlobal( p ); // recover switching activity p->fMappingMode = 4; Map_MappingMatches( p ); // compute the references and collect the nodes used in the mapping Map_MappingSetRefs( p ); p->AreaFinal = Map_MappingGetArea( p ); if ( p->fVerbose ) { printf( "Switching: %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", fShowSwitching? "Switch" : "Delay", fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 0.0, p->AreaFinal, 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); ABC_PRT( "Time", Abc_Clock() - clk ); } // compute the required times Map_TimeComputeRequiredGlobal( p ); // recover switching activity p->fMappingMode = 4; Map_MappingMatches( p ); // compute the references and collect the nodes used in the mapping Map_MappingSetRefs( p ); p->AreaFinal = Map_MappingGetArea( p ); if ( p->fVerbose ) { printf( "Switching: %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", fShowSwitching? "Switch" : "Delay", fShowSwitching? Map_MappingGetSwitching(p) : p->fRequiredGlo, 0.0, p->AreaFinal, 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); ABC_PRT( "Time", Abc_Clock() - clk ); } } p->timeArea += Abc_Clock() - clk; ////////////////////////////////////////////////////////////////////// // print the arrival times of the latest outputs if ( p->fVerbose ) Map_MappingPrintOutputArrivals( p ); return 1; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperCreate.c000066400000000000000000000545031300674244400246600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperCreate.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperCreate.c,v 1.15 2005/02/28 05:34:26 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Map_TableCreate( Map_Man_t * p ); static void Map_TableResize( Map_Man_t * p ); // hash key for the structural hash table static inline unsigned Map_HashKey2( Map_Node_t * p0, Map_Node_t * p1, int TableSize ) { return (unsigned)(((ABC_PTRUINT_T)(p0) + (ABC_PTRUINT_T)(p1) * 12582917) % TableSize); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads parameters from the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_ManReadInputNum( Map_Man_t * p ) { return p->nInputs; } int Map_ManReadOutputNum( Map_Man_t * p ) { return p->nOutputs; } int Map_ManReadBufNum( Map_Man_t * p ) { return Map_NodeVecReadSize(p->vMapBufs); } Map_Node_t ** Map_ManReadInputs ( Map_Man_t * p ) { return p->pInputs; } Map_Node_t ** Map_ManReadOutputs( Map_Man_t * p ) { return p->pOutputs; } Map_Node_t ** Map_ManReadBufs( Map_Man_t * p ) { return Map_NodeVecReadArray(p->vMapBufs); } Map_Node_t * Map_ManReadBufDriver( Map_Man_t * p, int i ) { return Map_ManReadBufs(p)[i]->p1; } Map_Node_t * Map_ManReadConst1 ( Map_Man_t * p ) { return p->pConst1; } Map_Time_t * Map_ManReadInputArrivals( Map_Man_t * p ) { return p->pInputArrivals; } Map_Time_t * Map_ManReadOutputRequireds( Map_Man_t * p ) { return p->pOutputRequireds; } Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p ) { return p->pSuperLib->pGenlib; } int Map_ManReadVerbose( Map_Man_t * p ) { return p->fVerbose; } float Map_ManReadAreaFinal( Map_Man_t * p ) { return p->AreaFinal; } float Map_ManReadRequiredGlo( Map_Man_t * p ) { return p->fRequiredGlo; } void Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames;} void Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;} void Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget;} void Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals ) { p->pInputArrivals = pArrivals; } void Map_ManSetOutputRequireds( Map_Man_t * p, Map_Time_t * pRequireds ) { p->pOutputRequireds = pRequireds; } void Map_ManSetObeyFanoutLimits( Map_Man_t * p, int fObeyFanoutLimits ) { p->fObeyFanoutLimits = fObeyFanoutLimits; } void Map_ManSetNumIterations( Map_Man_t * p, int nIterations ) { p->nIterations = nIterations; } int Map_ManReadFanoutViolations( Map_Man_t * p ) { return p->nFanoutViolations; } void Map_ManSetFanoutViolations( Map_Man_t * p, int nVio ) { p->nFanoutViolations = nVio; } void Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; } void Map_ManSetChoiceNum( Map_Man_t * p, int nChoices ) { p->nChoices = nChoices; } void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } void Map_ManSetSwitching( Map_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; } void Map_ManSetSkipFanout( Map_Man_t * p, int fSkipFanout ) { p->fSkipFanout = fSkipFanout; } void Map_ManSetUseProfile( Map_Man_t * p ) { p->fUseProfile = 1; } /**Function************************************************************* Synopsis [Reads parameters from the mapping node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Man_t * Map_NodeReadMan( Map_Node_t * p ) { return p->p; } char * Map_NodeReadData( Map_Node_t * p, int fPhase ) { return fPhase? p->pData1 : p->pData0; } int Map_NodeReadNum( Map_Node_t * p ) { return p->Num; } int Map_NodeReadLevel( Map_Node_t * p ) { return Map_Regular(p)->Level; } Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ) { return p->pCuts; } Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ) { return p->pCutBest[fPhase]; } Map_Node_t * Map_NodeReadOne( Map_Node_t * p ) { return p->p1; } Map_Node_t * Map_NodeReadTwo( Map_Node_t * p ) { return p->p2; } void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ) { if (fPhase) p->pData1 = pData; else p->pData0 = pData; } void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ) { p->pNextE = pNextE; } void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ) { p->pRepr = pRepr; } void Map_NodeSetSwitching( Map_Node_t * p, float Switching ) { p->Switching = Switching; } /**Function************************************************************* Synopsis [Checks the type of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeIsConst( Map_Node_t * p ) { return (Map_Regular(p))->Num == -1; } int Map_NodeIsVar( Map_Node_t * p ) { return (Map_Regular(p))->p1 == NULL && (Map_Regular(p))->Num >= 0; } int Map_NodeIsBuf( Map_Node_t * p ) { return (Map_Regular(p))->p1 != NULL && (Map_Regular(p))->p2 == NULL; } int Map_NodeIsAnd( Map_Node_t * p ) { return (Map_Regular(p))->p1 != NULL && (Map_Regular(p))->p2 != NULL; } int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ) { assert( !Map_IsComplement(p1) ); assert( !Map_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } /**Function************************************************************* Synopsis [Reads parameters from the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Super_t * Map_CutReadSuperBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].pSuperBest;} Map_Super_t * Map_CutReadSuper0( Map_Cut_t * p ) { return p->M[0].pSuperBest;} Map_Super_t * Map_CutReadSuper1( Map_Cut_t * p ) { return p->M[1].pSuperBest;} int Map_CutReadLeavesNum( Map_Cut_t * p ) { return p->nLeaves; } Map_Node_t ** Map_CutReadLeaves( Map_Cut_t * p ) { return p->ppLeaves; } unsigned Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].uPhaseBest;} unsigned Map_CutReadPhase0( Map_Cut_t * p ) { return p->M[0].uPhaseBest;} unsigned Map_CutReadPhase1( Map_Cut_t * p ) { return p->M[1].uPhaseBest;} Map_Cut_t * Map_CutReadNext( Map_Cut_t * p ) { return p->pNext; } /**Function************************************************************* Synopsis [Reads parameters from the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Map_SuperReadFormula( Map_Super_t * p ) { return p->pFormula; } Mio_Gate_t * Map_SuperReadRoot( Map_Super_t * p ) { return p->pRoot; } int Map_SuperReadNum( Map_Super_t * p ) { return p->Num; } Map_Super_t ** Map_SuperReadFanins( Map_Super_t * p ) { return p->pFanins; } int Map_SuperReadFaninNum( Map_Super_t * p ) { return p->nFanins; } Map_Super_t * Map_SuperReadNext( Map_Super_t * p ) { return p->pNext; } int Map_SuperReadNumPhases( Map_Super_t * p ) { return p->nPhases; } unsigned char * Map_SuperReadPhases( Map_Super_t * p ) { return p->uPhases; } int Map_SuperReadFanoutLimit( Map_Super_t * p ) { return p->nFanLimit;} Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p ) { return p->pGenlib; } float Map_SuperLibReadAreaInv( Map_SuperLib_t * p ) { return p->AreaInv; } Map_Time_t Map_SuperLibReadDelayInv( Map_SuperLib_t * p ) { return p->tDelayInv;} int Map_SuperLibReadVarsMax( Map_SuperLib_t * p ) { return p->nVarsMax; } /**Function************************************************************* Synopsis [Create the mapping manager.] Description [The number of inputs and outputs is assumed to be known is advance. It is much simpler to have them fixed upfront. When it comes to representing the object graph in the form of AIG, the resulting manager is similar to the regular AIG manager, except that it does not use reference counting (and therefore does not have garbage collections). It does have table resizing. The data structure is more flexible to represent additional information needed for mapping.] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ) { Map_Man_t * p; int i; // derive the supergate library if ( Abc_FrameReadLibSuper() == NULL ) { printf( "The supergate library is not specified. Use \"read_super\".\n" ); return NULL; } // start the manager p = ABC_ALLOC( Map_Man_t, 1 ); memset( p, 0, sizeof(Map_Man_t) ); p->pSuperLib = (Map_SuperLib_t *)Abc_FrameReadLibSuper(); p->nVarsMax = p->pSuperLib->nVarsMax; p->fVerbose = fVerbose; p->fEpsilon = (float)0.001; assert( p->nVarsMax > 0 ); if ( p->nVarsMax == 5 ) Extra_Truth4VarN( &p->uCanons, &p->uPhases, &p->pCounters, 8 ); // start various data structures Map_TableCreate( p ); Map_MappingSetupTruthTables( p->uTruths ); Map_MappingSetupTruthTablesLarge( p->uTruthsLarge ); // printf( "Node = %d bytes. Cut = %d bytes. Super = %d bytes.\n", sizeof(Map_Node_t), sizeof(Map_Cut_t), sizeof(Map_Super_t) ); p->mmNodes = Extra_MmFixedStart( sizeof(Map_Node_t) ); p->mmCuts = Extra_MmFixedStart( sizeof(Map_Cut_t) ); // make sure the constant node will get index -1 p->nNodes = -1; // create the constant node p->pConst1 = Map_NodeCreate( p, NULL, NULL ); p->vMapObjs = Map_NodeVecAlloc( 100 ); p->vMapBufs = Map_NodeVecAlloc( 100 ); p->vVisited = Map_NodeVecAlloc( 100 ); // create the PI nodes p->nInputs = nInputs; p->pInputs = ABC_ALLOC( Map_Node_t *, nInputs ); for ( i = 0; i < nInputs; i++ ) p->pInputs[i] = Map_NodeCreate( p, NULL, NULL ); // create the place for the output nodes p->nOutputs = nOutputs; p->pOutputs = ABC_ALLOC( Map_Node_t *, nOutputs ); memset( p->pOutputs, 0, sizeof(Map_Node_t *) * nOutputs ); return p; } /**Function************************************************************* Synopsis [Deallocates the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_ManFree( Map_Man_t * p ) { // int i; // for ( i = 0; i < p->vMapObjs->nSize; i++ ) // Map_NodeVecFree( p->vMapObjs->pArray[i]->vFanouts ); // Map_NodeVecFree( p->pConst1->vFanouts ); Map_NodeVecFree( p->vMapObjs ); Map_NodeVecFree( p->vMapBufs ); Map_NodeVecFree( p->vVisited ); if ( p->uCanons ) ABC_FREE( p->uCanons ); if ( p->uPhases ) ABC_FREE( p->uPhases ); if ( p->pCounters ) ABC_FREE( p->pCounters ); Extra_MmFixedStop( p->mmNodes ); Extra_MmFixedStop( p->mmCuts ); ABC_FREE( p->pNodeDelays ); ABC_FREE( p->pInputArrivals ); ABC_FREE( p->pOutputRequireds ); ABC_FREE( p->pInputs ); ABC_FREE( p->pOutputs ); ABC_FREE( p->pBins ); ABC_FREE( p->ppOutputNames ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates node delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_ManCreateNodeDelays( Map_Man_t * p, int LogFan ) { Map_Node_t * pNode; int k; assert( p->pNodeDelays == NULL ); p->pNodeDelays = ABC_CALLOC( float, p->vMapObjs->nSize ); for ( k = 0; k < p->vMapObjs->nSize; k++ ) { pNode = p->vMapObjs->pArray[k]; if ( pNode->nRefs == 0 ) continue; p->pNodeDelays[k] = 0.014426 * LogFan * p->pSuperLib->tDelayInv.Worst * log( (double)pNode->nRefs ); // 1.4426 = 1/ln(2) // printf( "%d = %d (%.2f) ", k, pNode->nRefs, p->pNodeDelays[k] ); } // printf( "\n" ); } /**Function************************************************************* Synopsis [Deallocates the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_ManPrintTimeStats( Map_Man_t * p ) { printf( "N-canonical = %d. Matchings = %d. Phases = %d. ", p->nCanons, p->nMatches, p->nPhases ); printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices ); ABC_PRT( "ToMap", p->timeToMap ); ABC_PRT( "Cuts ", p->timeCuts ); ABC_PRT( "Truth", p->timeTruth ); ABC_PRT( "Match", p->timeMatch ); ABC_PRT( "Area ", p->timeArea ); ABC_PRT( "Sweep", p->timeSweep ); ABC_PRT( "ToNet", p->timeToNet ); ABC_PRT( "TOTAL", p->timeTotal ); if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); } if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); } if ( p->time3 ) { ABC_PRT( "time3", p->time3 ); } } /**Function************************************************************* Synopsis [Prints the mapping stats.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, abctime Time ) { FILE * pTable; pTable = fopen( "map_stats.txt", "a+" ); fprintf( pTable, "%s ", pName ); fprintf( pTable, "%4.2f ", Area ); fprintf( pTable, "%4.2f ", Delay ); fprintf( pTable, "%4.2f\n", (float)(Time)/(float)(CLOCKS_PER_SEC) ); fclose( pTable ); } /**Function************************************************************* Synopsis [Creates a new node.] Description [This procedure should be called to create the constant node and the PI nodes first.] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) { Map_Node_t * pNode; // create the node pNode = (Map_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes ); memset( pNode, 0, sizeof(Map_Node_t) ); pNode->tRequired[0].Rise = pNode->tRequired[0].Fall = pNode->tRequired[0].Worst = MAP_FLOAT_LARGE; pNode->tRequired[1].Rise = pNode->tRequired[1].Fall = pNode->tRequired[1].Worst = MAP_FLOAT_LARGE; pNode->p1 = p1; pNode->p2 = p2; pNode->p = p; // set the number of this node pNode->Num = p->nNodes++; // place to store the fanouts // pNode->vFanouts = Map_NodeVecAlloc( 5 ); // store this node in the internal array if ( pNode->Num >= 0 ) Map_NodeVecPush( p->vMapObjs, pNode ); else pNode->fInv = 1; // set the level of this node if ( p1 ) { #ifdef MAP_ALLOCATE_FANOUT // create the fanout info Map_NodeAddFaninFanout( Map_Regular(p1), pNode ); if ( p2 ) Map_NodeAddFaninFanout( Map_Regular(p2), pNode ); #endif if ( p2 ) { pNode->Level = 1 + MAP_MAX(Map_Regular(pNode->p1)->Level, Map_Regular(pNode->p2)->Level); pNode->fInv = Map_NodeIsSimComplement(p1) & Map_NodeIsSimComplement(p2); } else { pNode->Level = Map_Regular(pNode->p1)->Level; pNode->fInv = Map_NodeIsSimComplement(p1); } } // reference the inputs (will be used to compute the number of fanouts) if ( p1 ) Map_NodeRef(p1); if ( p2 ) Map_NodeRef(p2); pNode->nRefEst[0] = pNode->nRefEst[1] = -1; return pNode; } /**Function************************************************************* Synopsis [Create the unique table of AND gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_TableCreate( Map_Man_t * pMan ) { assert( pMan->pBins == NULL ); pMan->nBins = Abc_PrimeCudd(5000); pMan->pBins = ABC_ALLOC( Map_Node_t *, pMan->nBins ); memset( pMan->pBins, 0, sizeof(Map_Node_t *) * pMan->nBins ); pMan->nNodes = 0; } /**Function************************************************************* Synopsis [Looks up the AND2 node in the unique table.] Description [This procedure implements one-level hashing. All the nodes are hashed by their children. If the node with the same children was already created, it is returned by the call to this procedure. If it does not exist, this procedure creates a new node with these children. ] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Node_t * Map_NodeAnd( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 ) { Map_Node_t * pEnt; unsigned Key; if ( p1 == p2 ) return p1; if ( p1 == Map_Not(p2) ) return Map_Not(pMan->pConst1); if ( Map_NodeIsConst(p1) ) { if ( p1 == pMan->pConst1 ) return p2; return Map_Not(pMan->pConst1); } if ( Map_NodeIsConst(p2) ) { if ( p2 == pMan->pConst1 ) return p1; return Map_Not(pMan->pConst1); } if ( Map_Regular(p1)->Num > Map_Regular(p2)->Num ) pEnt = p1, p1 = p2, p2 = pEnt; Key = Map_HashKey2( p1, p2, pMan->nBins ); for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext ) if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) return pEnt; // resize the table if ( pMan->nNodes >= 2 * pMan->nBins ) { Map_TableResize( pMan ); Key = Map_HashKey2( p1, p2, pMan->nBins ); } // create the new node pEnt = Map_NodeCreate( pMan, p1, p2 ); // add the node to the corresponding linked list in the table pEnt->pNext = pMan->pBins[Key]; pMan->pBins[Key] = pEnt; return pEnt; } /**Function************************************************************* Synopsis [Resizes the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_TableResize( Map_Man_t * pMan ) { Map_Node_t ** pBinsNew; Map_Node_t * pEnt, * pEnt2; int nBinsNew, Counter, i; abctime clk; unsigned Key; clk = Abc_Clock(); // get the new table size nBinsNew = Abc_PrimeCudd(2 * pMan->nBins); // allocate a new array pBinsNew = ABC_ALLOC( Map_Node_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Map_Node_t *) * nBinsNew ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < pMan->nBins; i++ ) for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) { Key = Map_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); pEnt->pNext = pBinsNew[Key]; pBinsNew[Key] = pEnt; Counter++; } assert( Counter == pMan->nNodes - pMan->nInputs ); if ( pMan->fVerbose ) { // printf( "Increasing the unique 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Node_t * Map_NodeBuf( Map_Man_t * p, Map_Node_t * p1 ) { Map_Node_t * pNode = Map_NodeCreate( p, p1, NULL ); Map_NodeVecPush( p->vMapBufs, pNode ); return pNode; } /**Function************************************************************* Synopsis [Sets the node to be equivalent to the given one.] Description [This procedure is a work-around for the equivalence check. Does not verify the equivalence. Use at the user's risk.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew ) { pNodeNew->pNextE = pNodeOld->pNextE; pNodeOld->pNextE = pNodeNew; pNodeNew->pRepr = pNodeOld; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperCut.c000066400000000000000000001140251300674244400242040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperCut.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperCut.c,v 1.12 2005/02/28 05:34:27 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the largest number of cuts considered #define MAP_CUTS_MAX_COMPUTE 1000 // the largest number of cuts used #define MAP_CUTS_MAX_USE 250 // temporary hash table to store the cuts typedef struct Map_CutTableStrutct_t Map_CutTable_t; struct Map_CutTableStrutct_t { Map_Cut_t ** pBins; // the table used for linear probing int nBins; // the size of the table int * pCuts; // the array of cuts currently stored int nCuts; // the number of cuts currently stored Map_Cut_t ** pArray; // the temporary array of cuts Map_Cut_t ** pCuts1; // the temporary array of cuts Map_Cut_t ** pCuts2; // the temporary array of cuts }; // primes used to compute the hash key static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; static Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode ); static void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode ); static Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ); static int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax ); static Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 ); static int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes ); static void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot ); static void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot ); static void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot ); static Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan ); static void Map_CutTableStop( Map_CutTable_t * p ); static unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes ); static int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ); static Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ); static void Map_CutTableRestart( Map_CutTable_t * p ); static Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList ); static int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList ); static Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts ); static unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 ); // iterator through all the cuts of the list #define Map_ListForEachCut( pList, pCut ) \ for ( pCut = pList; \ pCut; \ pCut = pCut->pNext ) #define Map_ListForEachCutSafe( pList, pCut, pCut2 ) \ for ( pCut = pList, \ pCut2 = pCut? pCut->pNext: NULL; \ pCut; \ pCut = pCut2, \ pCut2 = pCut? pCut->pNext: NULL ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Counts all the cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingCountAllCuts( Map_Man_t * pMan ) { Map_Node_t * pNode; Map_Cut_t * pCut; int i, nCuts; // int nCuts55 = 0, nCuts5x = 0, nCuts4x = 0, nCuts3x = 0; // int pCounts[7] = {0}; nCuts = 0; for ( i = 0; i < pMan->nBins; i++ ) for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) if ( pCut->nLeaves > 1 ) // skip the elementary cuts { nCuts++; /* if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 && Map_CutRegular(pCut->pTwo)->nLeaves == 5 ) nCuts55++; if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 || Map_CutRegular(pCut->pTwo)->nLeaves == 5 ) nCuts5x++; else if ( Map_CutRegular(pCut->pOne)->nLeaves == 4 || Map_CutRegular(pCut->pTwo)->nLeaves == 4 ) nCuts4x++; else if ( Map_CutRegular(pCut->pOne)->nLeaves == 3 || Map_CutRegular(pCut->pTwo)->nLeaves == 3 ) nCuts3x++; */ // pCounts[ Map_CutRegular(pCut->pOne)->nLeaves ]++; // pCounts[ Map_CutRegular(pCut->pTwo)->nLeaves ]++; } // printf( "Total cuts = %6d. 55 = %6d. 5x = %6d. 4x = %6d. 3x = %6d.\n", nCuts, nCuts55, nCuts5x, nCuts4x, nCuts3x ); // printf( "Total cuts = %6d. 6= %6d. 5= %6d. 4= %6d. 3= %6d. 2= %6d. 1= %6d.\n", // nCuts, pCounts[6], pCounts[5], pCounts[4], pCounts[3], pCounts[2], pCounts[1] ); return nCuts; } /**Function************************************************************* Synopsis [Computes the cuts for each node in the object graph.] Description [The cuts are computed in one sweep over the mapping graph. First, the elementary cuts, which include the node itself, are assigned to the PI nodes. The internal nodes are considered in the DFS order. Each node is two-input AND-gate. So to compute the cuts at a node, we need to merge the sets of cuts of its two predecessors. The merged set contains only unique cuts with the number of inputs equal to k or less. Finally, the elementary cut, composed of the node itself, is added to the set of cuts for the node. This procedure is pretty fast for 5-feasible cuts, but it dramatically slows down on some "dense" networks when computing 6-feasible cuts. The problem is that there are too many cuts in this case. We should think how to heuristically trim the number of cuts in such cases, to have reasonable runtime.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingCutsInput( Map_Man_t * p, Map_Node_t * pNode ) { Map_Cut_t * pCut; assert( Map_NodeIsVar(pNode) || Map_NodeIsBuf(pNode) ); pCut = Map_CutAlloc( p ); pCut->nLeaves = 1; pCut->ppLeaves[0] = pNode; pNode->pCuts = pCut; pNode->pCutBest[0] = NULL; // negative polarity is not mapped pNode->pCutBest[1] = pCut; // positive polarity is a trivial cut pCut->uTruth = 0xAAAAAAAA; // the first variable "1010" pCut->M[0].AreaFlow = 0.0; pCut->M[1].AreaFlow = 0.0; } void Map_MappingCuts( Map_Man_t * p ) { ProgressBar * pProgress; Map_CutTable_t * pTable; Map_Node_t * pNode; int nCuts, nNodes, i; abctime clk = Abc_Clock(); // set the elementary cuts for the PI variables assert( p->nVarsMax > 1 && p->nVarsMax < 7 ); for ( i = 0; i < p->nInputs; i++ ) Map_MappingCutsInput( p, p->pInputs[i] ); // compute the cuts for the internal nodes nNodes = p->vMapObjs->nSize; pProgress = Extra_ProgressBarStart( stdout, nNodes ); pTable = Map_CutTableStart( p ); for ( i = 0; i < nNodes; i++ ) { pNode = p->vMapObjs->pArray[i]; if ( Map_NodeIsBuf(pNode) ) Map_MappingCutsInput( p, pNode ); else if ( Map_NodeIsAnd(pNode) ) Map_CutCompute( p, pTable, pNode ); else continue; Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." ); } Extra_ProgressBarStop( pProgress ); Map_CutTableStop( pTable ); // report the stats if ( p->fVerbose ) { nCuts = Map_MappingCountAllCuts(p); printf( "Nodes = %6d. Total %d-feasible cuts = %10d. Per node = %.1f. ", p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); ABC_PRT( "Time", Abc_Clock() - clk ); } // print the cuts for the first primary output // Map_CutListPrint( p, Map_Regular(p->pOutputs[0]) ); } /**Function************************************************************* Synopsis [Computes the cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode ) { Map_Node_t * pTemp; Map_Cut_t * pList, * pList1, * pList2; Map_Cut_t * pCut; // if the cuts are computed return them if ( pNode->pCuts ) return pNode->pCuts; // compute the cuts for the children pList1 = Map_Regular(pNode->p1)->pCuts; pList2 = Map_Regular(pNode->p2)->pCuts; // merge the lists pList = Map_CutMergeLists( p, pTable, pList1, pList2, Map_IsComplement(pNode->p1), Map_IsComplement(pNode->p2) ); // if there are functionally equivalent nodes, union them with this list assert( pList ); // only add to the list of cuts if the node is a representative one if ( pNode->pRepr == NULL ) { for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) { assert( pTemp->pCuts ); pList = Map_CutUnionLists( pList, pTemp->pCuts ); assert( pTemp->pCuts ); pList = Map_CutSortCuts( p, pTable, pList ); } } // add the new cut pCut = Map_CutAlloc( p ); pCut->nLeaves = 1; pCut->ppLeaves[0] = pNode; pCut->uTruth = 0xAAAAAAAA; // append (it is important that the elementary cut is appended first) pCut->pNext = pList; // set at the node pNode->pCuts = pCut; // remove the dominated cuts Map_CutFilter( p, pNode ); // set the phase correctly if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) ) { Map_ListForEachCut( pNode->pCuts, pCut ) pCut->Phase = 1; } /* { int i, Counter = 0;; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) for ( i = 0; i < pCut->nLeaves; i++ ) Counter += (pCut->ppLeaves[i]->Level >= pNode->Level); // if ( Counter ) // printf( " %d", Counter ); } */ return pCut; } /**Function************************************************************* Synopsis [Filter the cuts using dominance.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode ) { Map_Cut_t * pTemp, * pPrev, * pCut, * pCut2; int i, k, Counter; Counter = 0; pPrev = pNode->pCuts; Map_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 ) { // go through all the previous cuts up to pCut for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext ) { // check if every node in pTemp is contained in pCut for ( i = 0; i < pTemp->nLeaves; i++ ) { for ( k = 0; k < pCut->nLeaves; k++ ) if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] ) break; if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut break; } if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut { Counter++; break; } } if ( pTemp != pCut ) // pTemp contain pCut { pPrev->pNext = pCut->pNext; // skip pCut // recycle pCut Map_CutFree( p, pCut ); } else pPrev = pCut; } // printf( "Dominated = %3d. \n", Counter ); } /**Function************************************************************* Synopsis [Merges two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ) { Map_Node_t * ppNodes[6]; Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL }; Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; int nNodes, Counter, i; Map_Cut_t ** ppArray1, ** ppArray2, ** ppArray3; int nCuts1, nCuts2, nCuts3, k, fComp3; ppArray1 = pTable->pCuts1; ppArray2 = pTable->pCuts2; nCuts1 = Map_CutList2Array( ppArray1, pList1 ); nCuts2 = Map_CutList2Array( ppArray2, pList2 ); // swap the lists based on their length if ( nCuts1 > nCuts2 ) { ppArray3 = ppArray1; ppArray1 = ppArray2; ppArray2 = ppArray3; nCuts3 = nCuts1; nCuts1 = nCuts2; nCuts2 = nCuts3; fComp3 = fComp1; fComp1 = fComp2; fComp2 = fComp3; } // pList1 is shorter or equal length compared to pList2 // prepare the manager for the cut computation Map_CutTableRestart( pTable ); // go through the cut pairs Counter = 0; // for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) // for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) for ( i = 0; i < nCuts1; i++ ) { for ( k = 0; k <= i; k++ ) { pTemp1 = ppArray1[i]; pTemp2 = ppArray2[k]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; } // check if k-feasible cut exists nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); // if ( p->nVarsMax == 5 ) // pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == MAP_CUTS_MAX_COMPUTE ) goto QUITS; } for ( k = 0; k < i; k++ ) { pTemp1 = ppArray1[k]; pTemp2 = ppArray2[i]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; } // check if k-feasible cut exists nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); // if ( p->nVarsMax == 5 ) // pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == MAP_CUTS_MAX_COMPUTE ) goto QUITS; } } // consider the rest of them for ( i = nCuts1; i < nCuts2; i++ ) for ( k = 0; k < nCuts1; k++ ) { pTemp1 = ppArray1[k]; pTemp2 = ppArray2[i]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; } // check if k-feasible cut exists nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); // if ( p->nVarsMax == 5 ) // pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == MAP_CUTS_MAX_COMPUTE ) goto QUITS; } QUITS : // combine all the lists into one pListNew = NULL; ppListNew = &pListNew; for ( i = 1; i <= p->nVarsMax; i++ ) { if ( pLists[i] == NULL ) continue; // find the last entry for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; pPrev = pCut, pCut = pCut->pNext ); // connect these lists *ppListNew = pLists[i]; ppListNew = &pPrev->pNext; } *ppListNew = NULL; // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE pListNew = Map_CutSortCuts( p, pTable, pListNew ); return pListNew; } /**Function************************************************************* Synopsis [Merges two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Cut_t * Map_CutMergeLists2( Map_Man_t * p, Map_CutTable_t * pTable, Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ) { Map_Node_t * ppNodes[6]; Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL }; Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; int nNodes, Counter, i; // prepare the manager for the cut computation Map_CutTableRestart( pTable ); // go through the cut pairs Counter = 0; for ( pTemp1 = pList1; pTemp1; pTemp1 = pTemp1->pNext ) for ( pTemp2 = pList2; pTemp2; pTemp2 = pTemp2->pNext ) { // check if k-feasible cut exists nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == MAP_CUTS_MAX_COMPUTE ) goto QUITS; } QUITS : // combine all the lists into one pListNew = NULL; ppListNew = &pListNew; for ( i = 1; i <= p->nVarsMax; i++ ) { if ( pLists[i] == NULL ) continue; // find the last entry for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; pPrev = pCut, pCut = pCut->pNext ); // connect these lists *ppListNew = pLists[i]; ppListNew = &pPrev->pNext; } *ppListNew = NULL; // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE pListNew = Map_CutSortCuts( p, pTable, pListNew ); return pListNew; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [Returns the number of nodes in the resulting cut, or 0 if the cut is infeasible. Returns the resulting nodes in the array ppNodes[].] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax ) { Map_Node_t * pNodeTemp; int nTotal, i, k, min, fMismatch; // check the special case when at least of the cuts is the largest if ( pCut1->nLeaves == nNodesMax ) { if ( pCut2->nLeaves == nNodesMax ) { // return 0 if the cuts are different for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] ) return 0; // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut1->ppLeaves[i]; return nNodesMax; } else if ( pCut2->nLeaves == nNodesMax - 1 ) { // return 0 if the cuts are different fMismatch = 0; for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] ) { if ( fMismatch == 1 ) return 0; fMismatch = 1; } // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut1->ppLeaves[i]; return nNodesMax; } } else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax ) { // return 0 if the cuts are different fMismatch = 0; for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] ) { if ( fMismatch == 1 ) return 0; fMismatch = 1; } // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut2->ppLeaves[i]; return nNodesMax; } // count the number of unique entries in pCut2 nTotal = pCut1->nLeaves; for ( i = 0; i < pCut2->nLeaves; i++ ) { // try to find this entry among the leaves of pCut1 for ( k = 0; k < pCut1->nLeaves; k++ ) if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] ) break; if ( k < pCut1->nLeaves ) // found continue; // we found a new entry to add if ( nTotal == nNodesMax ) return 0; ppNodes[nTotal++] = pCut2->ppLeaves[i]; } // we know that the feasible cut exists // add the starting entries for ( k = 0; k < pCut1->nLeaves; k++ ) ppNodes[k] = pCut1->ppLeaves[k]; // selection-sort the entries for ( i = 0; i < nTotal - 1; i++ ) { min = i; for ( k = i+1; k < nTotal; k++ ) // if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!) if ( ppNodes[k]->Num < ppNodes[min]->Num ) min = k; pNodeTemp = ppNodes[i]; ppNodes[i] = ppNodes[min]; ppNodes[min] = pNodeTemp; } return nTotal; } /**Function************************************************************* Synopsis [Computes the union of the two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 ) { Map_Cut_t * pTemp, * pRoot; // find the last cut in the first list pRoot = pList1; Map_ListForEachCut( pList1, pTemp ) pRoot = pTemp; // attach the non-trival part of the second cut to the end of the first assert( pRoot->pNext == NULL ); pRoot->pNext = pList2->pNext; pList2->pNext = NULL; return pList1; } /**Function************************************************************* Synopsis [Checks whether the given cut belongs to the list.] Description [This procedure takes most of the runtime in the cut computation.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes ) { Map_Cut_t * pTemp; int i; for ( pTemp = pList; pTemp; pTemp = pTemp->pNext ) { for ( i = 0; i < nNodes; i++ ) if ( pTemp->ppLeaves[i] != ppNodes[i] ) break; if ( i == nNodes ) return 1; } return 0; } /**Function************************************************************* Synopsis [Prints the cuts in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot ) { Map_Cut_t * pTemp; int Counter; for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) { printf( "%2d : ", Counter + 1 ); Map_CutPrint_( pMan, pTemp, pRoot ); } } /**Function************************************************************* Synopsis [Prints the cuts in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot ) { Map_Cut_t * pTemp; int Counter; for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) { printf( "%2d : ", Counter + 1 ); Map_CutPrint_( pMan, pTemp, pRoot ); } } /**Function************************************************************* Synopsis [Prints the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot ) { int i; printf( "(%3d) {", pRoot->Num ); for ( i = 0; i < pMan->nVarsMax; i++ ) if ( pCut->ppLeaves[i] ) printf( " %3d", pCut->ppLeaves[i]->Num ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Starts the hash table to canonicize cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan ) { Map_CutTable_t * p; // allocate the table p = ABC_ALLOC( Map_CutTable_t, 1 ); memset( p, 0, sizeof(Map_CutTable_t) ); p->nBins = Abc_PrimeCudd( 10 * MAP_CUTS_MAX_COMPUTE ); p->pBins = ABC_ALLOC( Map_Cut_t *, p->nBins ); memset( p->pBins, 0, sizeof(Map_Cut_t *) * p->nBins ); p->pCuts = ABC_ALLOC( int, 2 * MAP_CUTS_MAX_COMPUTE ); p->pArray = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); p->pCuts1 = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); p->pCuts2 = ABC_ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); return p; } /**Function************************************************************* Synopsis [Stops the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutTableStop( Map_CutTable_t * p ) { ABC_FREE( p->pCuts1 ); ABC_FREE( p->pCuts2 ); ABC_FREE( p->pArray ); ABC_FREE( p->pBins ); ABC_FREE( p->pCuts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Computes the hash value of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes ) { unsigned uRes; int i; uRes = 0; for ( i = 0; i < nNodes; i++ ) uRes += s_HashPrimes[i] * ppNodes[i]->Num; return uRes; } /**Function************************************************************* Synopsis [Looks up the table for the available cut.] Description [Returns -1 if the same cut is found. Returns the index of the cell where the cut should be added, if it does not exist.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ) { Map_Cut_t * pCut; unsigned Key; int b, i; Key = Map_CutTableHash(ppNodes, nNodes) % p->nBins; for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins ) { pCut = p->pBins[b]; if ( pCut->nLeaves != nNodes ) continue; for ( i = 0; i < nNodes; i++ ) if ( pCut->ppLeaves[i] != ppNodes[i] ) break; if ( i == nNodes ) return -1; } return b; } /**Function************************************************************* Synopsis [Starts the hash table to canonicize cuts.] Description [Considers addition of the cut to the hash table.] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ) { Map_Cut_t * pCut; int Place, i; // abctime clk; // check the cut Place = Map_CutTableLookup( p, ppNodes, nNodes ); if ( Place == -1 ) return NULL; assert( nNodes > 0 ); // create the new cut //clk = Abc_Clock(); pCut = Map_CutAlloc( pMan ); //pMan->time1 += Abc_Clock() - clk; pCut->nLeaves = nNodes; for ( i = 0; i < nNodes; i++ ) pCut->ppLeaves[i] = ppNodes[i]; // add the cut to the table assert( p->pBins[Place] == NULL ); p->pBins[Place] = pCut; // add the cut to the new list p->pCuts[ p->nCuts++ ] = Place; return pCut; } /**Function************************************************************* Synopsis [Prepares the table to be used with other cuts.] Description [Restarts the table by cleaning the info about cuts stored when the previous node was considered.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutTableRestart( Map_CutTable_t * p ) { int i; for ( i = 0; i < p->nCuts; i++ ) { assert( p->pBins[ p->pCuts[i] ] ); p->pBins[ p->pCuts[i] ] = NULL; } p->nCuts = 0; } /**Function************************************************************* Synopsis [Compares the cuts by the number of leaves and then by delay.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CutSortCutsCompare( Map_Cut_t ** pC1, Map_Cut_t ** pC2 ) { if ( (*pC1)->nLeaves < (*pC2)->nLeaves ) return -1; if ( (*pC1)->nLeaves > (*pC2)->nLeaves ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorts the cuts by average arrival time.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList ) { Map_Cut_t * pListNew; int nCuts, i; // abctime clk; // move the cuts from the list into the array nCuts = Map_CutList2Array( p->pCuts1, pList ); assert( nCuts <= MAP_CUTS_MAX_COMPUTE ); // sort the cuts //clk = Abc_Clock(); qsort( (void *)p->pCuts1, nCuts, sizeof(Map_Cut_t *), (int (*)(const void *, const void *)) Map_CutSortCutsCompare ); //pMan->time2 += Abc_Clock() - clk; // move them back into the list if ( nCuts > MAP_CUTS_MAX_USE - 1 ) { // free the remaining cuts for ( i = MAP_CUTS_MAX_USE - 1; i < nCuts; i++ ) Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] ); // update the number of cuts nCuts = MAP_CUTS_MAX_USE - 1; } pListNew = Map_CutArray2List( p->pCuts1, nCuts ); return pListNew; } /**Function************************************************************* Synopsis [Moves the nodes from the list into the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList ) { int i; for ( i = 0; pList; pList = pList->pNext, i++ ) pArray[i] = pList; return i; } /**Function************************************************************* Synopsis [Moves the nodes from the array into the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts ) { Map_Cut_t * pListNew, ** ppListNew; int i; pListNew = NULL; ppListNew = &pListNew; for ( i = 0; i < nCuts; i++ ) { // connect these lists *ppListNew = pArray[i]; ppListNew = &pArray[i]->pNext; } //printf( "\n" ); *ppListNew = NULL; return pListNew; } /**Function************************************************************* Synopsis [Computes the truth table of the 5-input cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 ) { static unsigned ** pPerms53 = NULL; static unsigned ** pPerms54 = NULL; unsigned uPhase, uTruth, uTruth0, uTruth1; int i, k; if ( pPerms53 == NULL ) { pPerms53 = (unsigned **)Extra_TruthPerm53(); pPerms54 = (unsigned **)Extra_TruthPerm54(); } // find the mapping from the old nodes to the new if ( pTemp0->nLeaves == pCut->nLeaves ) uTruth0 = pTemp0->uTruth; else { assert( pTemp0->nLeaves < pCut->nLeaves ); uPhase = 0; for ( i = 0; i < (int)pTemp0->nLeaves; i++ ) { for ( k = 0; k < pCut->nLeaves; k++ ) if ( pTemp0->ppLeaves[i] == pCut->ppLeaves[k] ) break; uPhase |= (1 << k); } assert( uPhase < 32 ); if ( pTemp0->nLeaves == 4 ) { if ( uPhase == 31-16 ) // 01111 uTruth0 = pTemp0->uTruth; else if ( uPhase == 31-8 ) // 10111 uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][0]; else if ( uPhase == 31-4 ) // 11011 uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][1]; else if ( uPhase == 31-2 ) // 11101 uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][2]; else if ( uPhase == 31-1 ) // 11110 uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][3]; else assert( 0 ); } else uTruth0 = pPerms53[pTemp0->uTruth & 0xFF][uPhase]; } uTruth0 = fComp0? ~uTruth0: uTruth0; // find the mapping from the old nodes to the new if ( pTemp1->nLeaves == pCut->nLeaves ) uTruth1 = pTemp1->uTruth; else { assert( pTemp1->nLeaves < pCut->nLeaves ); uPhase = 0; for ( i = 0; i < (int)pTemp1->nLeaves; i++ ) { for ( k = 0; k < pCut->nLeaves; k++ ) if ( pTemp1->ppLeaves[i] == pCut->ppLeaves[k] ) break; uPhase |= (1 << k); } assert( uPhase < 32 ); if ( pTemp1->nLeaves == 4 ) { if ( uPhase == 31-16 ) // 01111 uTruth1 = pTemp1->uTruth; else if ( uPhase == 31-8 ) // 10111 uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][0]; else if ( uPhase == 31-4 ) // 11011 uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][1]; else if ( uPhase == 31-2 ) // 11101 uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][2]; else if ( uPhase == 31-1 ) // 11110 uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][3]; else assert( 0 ); } else uTruth1 = pPerms53[pTemp1->uTruth & 0xFF][uPhase]; } uTruth1 = fComp1? ~uTruth1: uTruth1; uTruth = uTruth0 & uTruth1; return uTruth; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperCutUtils.c000066400000000000000000000167041300674244400252320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperCutUtils.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Cut_t * Map_CutAlloc( Map_Man_t * p ) { Map_Cut_t * pCut; Map_Match_t * pMatch; pCut = (Map_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts ); memset( pCut, 0, sizeof(Map_Cut_t) ); pMatch = pCut->M; pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned pMatch = pCut->M + 1; pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned return pCut; } /**Function************************************************************* Synopsis [Deallocates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut ) { if ( pCut ) Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase ) { int i; printf( "CUT: Delay = (%4.2f, %4.2f). Area = %4.2f. Nodes = %d -> {", pCut->M[fPhase].tArrive.Rise, pCut->M[fPhase].tArrive.Fall, pCut->M[fPhase].AreaFlow, pRoot->Num ); for ( i = 0; i < pCut->nLeaves; i++ ) printf( " %d", pCut->ppLeaves[i]->Num ); printf( " } \n" ); } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase ) { assert( pCut->M[fPhase].pSuperBest ); return pCut->M[fPhase].pSuperBest->Area; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf ) { assert( pCut->M[fPhase].pSuperBest ); return (( pCut->M[fPhase].uPhaseBest & (1<pCutBest[fPhase]->M[fPhase].pSuperBest ); return (( pNode->pCutBest[fPhase]->M[fPhase].uPhaseBest & (1<pNext ) pPrev = pTemp; // append all the end of the current set assert( pPrev->pNext == NULL ); pPrev->pNext = pSetAll; return pSets; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave ) { Map_Cut_t * pNext, * pTemp; for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; pTemp; pTemp = pNext, pNext = pNext? pNext->pNext : NULL ) if ( pTemp != pSave ) Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CutListCount( Map_Cut_t * pSets ) { Map_Cut_t * pTemp; int i; for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ ); return i; } #if 0 /**function************************************************************* synopsis [Removes the fanouts of the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) { Map_NodeVec_t * vFanouts; int i, k; for ( i = 0; i < pCut->nLeaves; i++ ) { vFanouts = pCut->ppLeaves[i]->vFanouts; for ( k = 0; k < vFanouts->nSize; k++ ) if ( vFanouts->pArray[k] == pNode ) break; assert( k != vFanouts->nSize ); for ( k++; k < vFanouts->nSize; k++ ) vFanouts->pArray[k-1] = vFanouts->pArray[k]; vFanouts->nSize--; } } /**function************************************************************* synopsis [Removes the fanouts of the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) { int i; for ( i = 0; i < pCut->nLeaves; i++ ) Map_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode ); } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperFanout.c000066400000000000000000000100751300674244400247050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperFanout.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperFanout.c,v 1.5 2005/01/23 06:59:43 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START #ifdef MAP_ALLOCATE_FANOUT //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Add the fanout to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout ) { Map_Node_t * pPivot; // pFanins is a fanin of pFanout assert( !Map_IsComplement(pFanin) ); assert( !Map_IsComplement(pFanout) ); assert( Map_Regular(pFanout->p1) == pFanin || Map_Regular(pFanout->p2) == pFanin ); pPivot = pFanin->pFanPivot; if ( pPivot == NULL ) { pFanin->pFanPivot = pFanout; return; } if ( Map_Regular(pPivot->p1) == pFanin ) { if ( Map_Regular(pFanout->p1) == pFanin ) { pFanout->pFanFanin1 = pPivot->pFanFanin1; pPivot->pFanFanin1 = pFanout; } else // if ( Map_Regular(pFanout->p2) == pFanin ) { pFanout->pFanFanin2 = pPivot->pFanFanin1; pPivot->pFanFanin1 = pFanout; } } else // if ( Map_Regular(pPivot->p2) == pFanin ) { assert( Map_Regular(pPivot->p2) == pFanin ); if ( Map_Regular(pFanout->p1) == pFanin ) { pFanout->pFanFanin1 = pPivot->pFanFanin2; pPivot->pFanFanin2 = pFanout; } else // if ( Map_Regular(pFanout->p2) == pFanin ) { pFanout->pFanFanin2 = pPivot->pFanFanin2; pPivot->pFanFanin2 = pFanout; } } } /**Function************************************************************* Synopsis [Add the fanout to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove ) { Map_Node_t * pFanout, * pFanout2, ** ppFanList; // start the linked list of fanouts ppFanList = &pFanin->pFanPivot; // go through the fanouts Map_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) { // skip the fanout-to-remove if ( pFanout == pFanoutToRemove ) continue; // add useful fanouts to the list *ppFanList = pFanout; ppFanList = Map_NodeReadNextFanoutPlace( pFanin, pFanout ); } *ppFanList = NULL; } /**Function************************************************************* Synopsis [Returns the number of fanouts of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeGetFanoutNum( Map_Node_t * pNode ) { Map_Node_t * pFanout; int Counter = 0; Map_NodeForEachFanout( pNode, pFanout ) Counter++; return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #endif ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperInt.h000066400000000000000000000634551300674244400242220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperInt.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $] ***********************************************************************/ #ifndef ABC__map__mapper__mapperInt_h #define ABC__map__mapper__mapperInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "base/main/main.h" #include "map/mio/mio.h" #include "mapper.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // uncomment to have fanouts represented in the mapping graph //#define MAP_ALLOCATE_FANOUT 1 //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // the bit masks #define MAP_MASK(n) ((~((unsigned)0)) >> (32-(n))) #define MAP_FULL (~((unsigned)0)) #define MAP_NO_VAR (-9999.0) // maximum/minimum operators #define MAP_MIN(a,b) (((a) < (b))? (a) : (b)) #define MAP_MAX(a,b) (((a) > (b))? (a) : (b)) // the small and large numbers (min/max float are 1.17e-38/3.40e+38) #define MAP_FLOAT_LARGE ((float)(FLT_MAX/10)) #define MAP_FLOAT_SMALL ((float)1.0e-03) // generating random unsigned (#define RAND_MAX 0x7fff) #define MAP_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) // internal macros to work with cuts #define Map_CutIsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01))) #define Map_CutRegular(p) ((Map_Cut_t *)((ABC_PTRUINT_T)(p) & ~01)) #define Map_CutNot(p) ((Map_Cut_t *)((ABC_PTRUINT_T)(p) ^ 01)) #define Map_CutNotCond(p,c) ((Map_Cut_t *)((ABC_PTRUINT_T)(p) ^ (c))) // internal macros for referencing of nodes #define Map_NodeReadRef(p) ((Map_Regular(p))->nRefs) #define Map_NodeRef(p) ((Map_Regular(p))->nRefs++) // macros to get hold of the bits in the support info #define Map_InfoSetVar(p,i) (p[(i)>>5] |= (1<<((i) & 31))) #define Map_InfoRemVar(p,i) (p[(i)>>5] &= ~(1<<((i) & 31))) #define Map_InfoFlipVar(p,i) (p[(i)>>5] ^= (1<<((i) & 31))) #define Map_InfoReadVar(p,i) ((p[(i)>>5] & (1<<((i) & 31))) > 0) // returns the complemented attribute of the node #define Map_NodeIsSimComplement(p) (Map_IsComplement(p)? !(Map_Regular(p)->fInv) : (p)->fInv) //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // the mapping manager struct Map_ManStruct_t_ { // the mapping graph Map_Node_t ** pBins; // the table of nodes hashed by their children int nBins; // the size of the table Map_Node_t ** pInputs; // the array of inputs int nInputs; // the number of inputs Map_Node_t ** pOutputs; // the array of outputs int nOutputs; // the number of outputs int nNodes; // the total number of nodes Map_Node_t * pConst1; // the constant 1 node Map_NodeVec_t * vMapObjs; // the array of all nodes Map_NodeVec_t * vMapBufs; // the array of all nodes float * pNodeDelays; // the array of node delays // info about the original circuit char ** ppOutputNames; // the primary output names Map_Time_t * pInputArrivals;// the PI arrival times Map_Time_t * pOutputRequireds;// the PI arrival times // mapping parameters int nVarsMax; // the max number of variables int fAreaRecovery; // the flag to enable area recovery int fVerbose; // the verbosiness flag int fMappingMode; // set to 1 when doing area float fRequiredGlo; // the global required times float fEpsilon; // the epsilon used to compare floats float AreaBase; // the area after delay-oriented mapping float AreaFinal; // the area after delay-oriented mapping int nIterations; // How many matching passes to do int fObeyFanoutLimits;// Should mapper try to obey fanout limits or not float DelayTarget; // the required times set by the user int nTravIds; // the traversal counter int fSwitching; // use switching activity int fSkipFanout; // skip large gates when mapping high-fanout nodes int fUseProfile; // use standard-cell profile // the supergate library Map_SuperLib_t * pSuperLib; // the current supergate library unsigned uTruths[6][2]; // the elementary truth tables unsigned uTruthsLarge[10][32]; // the elementary truth tables int nCounts[32]; // the counter of minterms int nCountsBest[32];// the counter of minterms Map_NodeVec_t * vVisited; // the visited cuts during cut computation // the memory managers Extra_MmFixed_t * mmNodes; // the memory manager for nodes Extra_MmFixed_t * mmCuts; // the memory manager for cuts // precomputed N-canonical forms unsigned short * uCanons; // N-canonical forms char ** uPhases; // N-canonical phases char * pCounters; // counters of phases // various statistical variables int nChoiceNodes; // the number of choice nodes int nChoices; // the number of all choices int nCanons; // the number of times N-canonical form was computed int nMatches; // the number of times supergate matching was performed int nPhases; // the number of phases considered during matching int nFanoutViolations; // the number of nodes in mapped circuit violating fanout // runtime statistics abctime timeToMap; // time to transfer to the mapping structure abctime timeCuts; // time to compute k-feasible cuts abctime timeTruth; // time to compute the truth table for each cut abctime timeMatch; // time to perform matching for each node abctime timeArea; // time to recover area after delay oriented mapping abctime timeSweep; // time to perform technology dependent sweep abctime timeToNet; // time to transfer back to the network abctime timeTotal; // the total mapping time abctime time1; // time to transfer to the mapping structure abctime time2; // time to transfer to the mapping structure abctime time3; // time to transfer to the mapping structure }; // the supergate library struct Map_SuperLibStruct_t_ { // general info char * pName; // the name of the supergate library Mio_Library_t * pGenlib; // the generic library // other info int nVarsMax; // the max number of variables int nSupersAll; // the total number of supergates int nSupersReal; // the total number of supergates int nLines; // the total number of lines in the supergate file int fVerbose; // the verbosity flag // hash tables Map_Super_t ** ppSupers; // the array of supergates Map_HashTable_t * tTableC; // the table mapping N-canonical forms into supergates Map_HashTable_t * tTable; // the table mapping truth tables into supergates // data structures for N-canonical form computation unsigned uTruths[6][2]; // the elementary truth tables unsigned uMask[2]; // the mask for the truth table // the invertor Mio_Gate_t * pGateInv; // the pointer to the intertor gate Map_Time_t tDelayInv; // the delay of the inverter float AreaInv; // the area of the inverter float AreaBuf; // the area of the buffer Map_Super_t * pSuperInv; // the supergate representing the inverter // the memory manager for the internal table Extra_MmFixed_t * mmSupers; // the mamory manager for supergates Extra_MmFixed_t * mmEntries; // the memory manager for the entries Extra_MmFlex_t * mmForms; // the memory manager for formulas }; // the mapping node struct Map_NodeStruct_t_ { // general information about the node Map_Man_t * p; // the mapping manager Map_Node_t * pNext; // the next node in the hash table int Num; // the unique number of this node int TravId; // the traversal ID (use to avoid cleaning marks) int nRefs; // the number of references (fanouts) of the given node unsigned fMark0 : 1; // the mark used for traversals unsigned fMark1 : 1; // the mark used for traversals unsigned fUsed : 1; // the mark to mark the node or its fanins unsigned fInv : 1; // the complemented attribute for the equivalent nodes unsigned fInvert: 1; // the flag to denote the use of interter unsigned Level :16; // the level of the given node unsigned NumTemp:10; // the level of the given node int nRefAct[3]; // estimated fanout for current covering phase, neg and pos and sum float nRefEst[3]; // actual fanout for previous covering phase, neg and pos and sum float Switching; // the probability of switching // connectivity Map_Node_t * p1; // the first child Map_Node_t * p2; // the second child Map_Node_t * pNextE; // the next functionally equivalent node Map_Node_t * pRepr; // the representative of the functionally equivalent class #ifdef MAP_ALLOCATE_FANOUT // representation of node's fanouts Map_Node_t * pFanPivot; // the first fanout of this node Map_Node_t * pFanFanin1; // the next fanout of p1 Map_Node_t * pFanFanin2; // the next fanout of p2 // Map_NodeVec_t * vFanouts; // the array of fanouts of the gate #endif // the delay information Map_Time_t tArrival[2]; // the best arrival time of the neg (0) and pos (1) phases Map_Time_t tRequired[2]; // the required time of the neg (0) and pos (1) phases // misc information Map_Cut_t * pCutBest[2]; // the best mapping for neg and pos phase Map_Cut_t * pCuts; // mapping choices for the node (elementary comes first) char * pData0; // temporary storage for the corresponding network node char * pData1; // temporary storage for the corresponding network node }; // the match of the cut struct Map_MatchStruct_t_ { // information used for matching Map_Super_t * pSupers; unsigned uPhase; // information about the best selected match unsigned uPhaseBest; // the best phase (the EXOR of match's phase and gate's phase) Map_Super_t * pSuperBest; // the best supergate matched // the parameters of the match Map_Time_t tArrive; // the arrival time of this match float AreaFlow; // the area flow or area of this match }; // the cuts used for matching struct Map_CutStruct_t_ { Map_Cut_t * pNext; // the pointer to the next cut in the list Map_Cut_t * pOne; // the father of this cut Map_Cut_t * pTwo; // the mother of this cut Map_Node_t * ppLeaves[6]; // the leaves of this cut unsigned uTruth; // truth table for five-input cuts char nLeaves; // the number of leaves char nVolume; // the volume of this cut char fMark; // the mark to denote visited cut char Phase; // the mark to denote complemented cut Map_Match_t M[2]; // the matches for positive/negative phase }; // the supergate internally represented struct Map_SuperStruct_t_ { int Num; // the ID of the supergate unsigned fSuper : 1; // the flag to distinquish a real super from a fake one unsigned fExclude: 1; // the flag if set causes gate to be excluded from being used for mapping unsigned nFanins : 3; // the number of inputs unsigned nGates : 3; // the number of gates inside this supergate unsigned nFanLimit: 4; // the max number of fanout count unsigned nSupers : 16; // the number of supergates in the list unsigned nPhases : 4; // the number of phases for matching with canonical form unsigned char uPhases[4]; // the maximum of 4 phases for matching with canonical form int nUsed; // the number of times the supergate is used Map_Super_t * pFanins[6]; // the fanins of the gate Mio_Gate_t * pRoot; // the root gate unsigned uTruth[2]; // the truth table Map_Time_t tDelaysR[6]; // the pin-to-pin delay constraints for the rise of the output Map_Time_t tDelaysF[6]; // the pin-to-pin delay constraints for the rise of the output Map_Time_t tDelayMax; // the maximum delay float Area; // the area char * pFormula; // the symbolic formula Map_Super_t * pNext; // the pointer to the next super in the list }; // the vector of nodes struct Map_NodeVecStruct_t_ { Map_Node_t ** pArray; // the array of nodes int nSize; // the number of entries in the array int nCap; // the number of allocated entries }; // the hash table struct Map_HashTableStruct_t_ { Map_HashEntry_t ** pBins; // the table bins int nBins; // the size of the table int nEntries; // the total number of entries in the table Extra_MmFixed_t * mmMan; // the memory manager for entries }; // the entry in the hash table struct Map_HashEntryStruct_t_ { unsigned uTruth[2]; // the truth table for 6-var function unsigned uPhase; // the phase to tranform it into the canonical form Map_Super_t * pGates; // the linked list of matching supergates Map_HashEntry_t * pNext; // the next entry in the hash table }; // getting hold of the next fanout of the node #define Map_NodeReadNextFanout( pNode, pFanout ) \ ( ( pFanout == NULL )? NULL : \ ((Map_Regular((pFanout)->p1) == (pNode))? \ (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) // getting hold of the place where the next fanout will be attached #define Map_NodeReadNextFanoutPlace( pNode, pFanout ) \ ( (Map_Regular((pFanout)->p1) == (pNode))? \ &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) // iterator through the fanouts of the node #define Map_NodeForEachFanout( pNode, pFanout ) \ for ( pFanout = (pNode)->pFanPivot; pFanout; \ pFanout = Map_NodeReadNextFanout(pNode, pFanout) ) // safe iterator through the fanouts of the node #define Map_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ for ( pFanout = (pNode)->pFanPivot, \ pFanout2 = Map_NodeReadNextFanout(pNode, pFanout); \ pFanout; \ pFanout = pFanout2, \ pFanout2 = Map_NodeReadNextFanout(pNode, pFanout) ) //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mapperCanon.c =============================================================*/ /*=== mapperCut.c ===============================================================*/ extern void Map_MappingCuts( Map_Man_t * p ); /*=== mapperCutUtils.c ===============================================================*/ extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p ); extern void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut ); extern void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase ); extern float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase ); extern int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf ); extern int Map_NodeGetLeafPhase( Map_Node_t * pNode, int fPhase, int iLeaf ); extern Map_Cut_t * Map_CutListAppend( Map_Cut_t * pSetAll, Map_Cut_t * pSets ); extern void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave ); extern int Map_CutListCount( Map_Cut_t * pSets ); extern void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); extern void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); /*=== mapperFanout.c =============================================================*/ extern void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout ); extern void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove ); extern int Map_NodeGetFanoutNum( Map_Node_t * pNode ); /*=== mapperLib.c ============================================================*/ extern Map_SuperLib_t * Map_SuperLibCreate( Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName, char * pExcludeFile, int fAlgorithm, int fVerbose ); extern void Map_SuperLibFree( Map_SuperLib_t * p ); /*=== mapperMatch.c ===============================================================*/ extern int Map_MappingMatches( Map_Man_t * p ); /*=== mapperRefs.c =============================================================*/ extern void Map_MappingEstimateRefsInit( Map_Man_t * p ); extern void Map_MappingEstimateRefs( Map_Man_t * p ); extern float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase ); extern float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase ); extern float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase ); extern float Map_CutRef( Map_Cut_t * pCut, int fPhase, int fProfile ); extern float Map_CutDeref( Map_Cut_t * pCut, int fPhase, int fProfile ); extern void Map_MappingSetRefs( Map_Man_t * pMan ); extern float Map_MappingGetArea( Map_Man_t * pMan ); /*=== mapperSwitch.c =============================================================*/ extern float Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); extern float Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); extern float Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); extern float Map_MappingGetSwitching( Map_Man_t * pMan ); /*=== mapperTree.c ===============================================================*/ extern int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st__table * tExcludeGate ); extern int Map_LibraryReadFileTreeStr( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName ); extern int Map_LibraryReadTree( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, char * pFileName, char * pExcludeFile ); extern void Map_LibraryPrintTree( Map_SuperLib_t * pLib ); /*=== mapperSuper.c ===============================================================*/ extern int Map_LibraryRead( Map_SuperLib_t * p, char * pFileName ); extern void Map_LibraryPrintSupergate( Map_Super_t * pGate ); /*=== mapperTable.c ============================================================*/ extern Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib ); extern void Map_SuperTableFree( Map_HashTable_t * p ); extern int Map_SuperTableInsertC( Map_HashTable_t * pLib, unsigned uTruthC[], Map_Super_t * pGate ); extern int Map_SuperTableInsert( Map_HashTable_t * pLib, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase ); extern Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase ); extern void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax ); extern void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax ); /*=== mapperTime.c =============================================================*/ extern float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstCaseLimit ); extern float Map_TimeComputeArrivalMax( Map_Man_t * p ); extern void Map_TimeComputeRequiredGlobal( Map_Man_t * p ); /*=== mapperTruth.c ===============================================================*/ extern void Map_MappingTruths( Map_Man_t * pMan ); extern int Map_TruthsCutDontCare( Map_Man_t * pMan, Map_Cut_t * pCut, unsigned * uTruthDc ); extern int Map_TruthCountOnes( unsigned * uTruth, int nLeaves ); extern int Map_TruthDetectTwoFirst( unsigned * uTruth, int nLeaves ); /*=== mapperUtils.c ===============================================================*/ extern Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv ); extern int Map_MappingCountLevels( Map_Man_t * pMan ); extern void Map_MappingUnmark( Map_Man_t * pMan ); extern void Map_MappingMark_rec( Map_Node_t * pNode ); extern void Map_MappingUnmark_rec( Map_Node_t * pNode ); extern void Map_MappingPrintOutputArrivals( Map_Man_t * p ); extern void Map_MappingSetupMask( unsigned uMask[], int nVarsMax ); extern int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol ); extern float Map_MappingGetAreaFlow( Map_Man_t * p ); extern void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes ); extern int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes ); extern void Map_MappingExpandTruth( unsigned uTruth[2], int nVars ); extern float Map_MappingPrintSwitching( Map_Man_t * pMan ); extern void Map_MappingSetPlacementInfo( Map_Man_t * p ); extern float Map_MappingPrintWirelength( Map_Man_t * p ); extern void Map_MappingWireReport( Map_Man_t * p ); extern float Map_MappingComputeDelayWithFanouts( Map_Man_t * p ); extern int Map_MappingGetMaxLevel( Map_Man_t * pMan ); extern void Map_MappingSetChoiceLevels( Map_Man_t * pMan ); extern void Map_MappingReportChoices( Map_Man_t * pMan ); /*=== mapperVec.c =============================================================*/ extern Map_NodeVec_t * Map_NodeVecAlloc( int nCap ); extern void Map_NodeVecFree( Map_NodeVec_t * p ); extern Map_NodeVec_t * Map_NodeVecDup( Map_NodeVec_t * p ); extern Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p ); extern int Map_NodeVecReadSize( Map_NodeVec_t * p ); extern void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin ); extern void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew ); extern void Map_NodeVecClear( Map_NodeVec_t * p ); extern void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry ); extern int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry ); extern Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p ); extern void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry ); extern void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry ); extern Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i ); extern void Map_NodeVecSortByLevel( Map_NodeVec_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperLib.c000066400000000000000000000200311300674244400241500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperLib.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperLib.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] ***********************************************************************/ #define _BSD_SOURCE #ifndef WIN32 #include #endif #include "mapperInt.h" #include "map/super/super.h" #include "map/mapper/mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads in the supergate library and prepares it for use.] Description [The supergates library comes in a .super file. This file contains descriptions of supergates along with some relevant information. This procedure reads the supergate file, canonicizes the supergates, and constructs an additional lookup table, which can be used to map truth tables of the cuts into the pair (phase, supergate). The phase indicates how the current truth table should be phase assigned to match the canonical form of the supergate. The resulting phase is the bitwise EXOR of the phase needed to canonicize the supergate and the phase needed to transform the truth table into its canonical form.] SideEffects [] SeeAlso [] ***********************************************************************/ Map_SuperLib_t * Map_SuperLibCreate( Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName, char * pExcludeFile, int fAlgorithm, int fVerbose ) { Map_SuperLib_t * p; abctime clk; // start the supergate library p = ABC_ALLOC( Map_SuperLib_t, 1 ); memset( p, 0, sizeof(Map_SuperLib_t) ); p->pName = Abc_UtilStrsav(pFileName); p->fVerbose = fVerbose; p->mmSupers = Extra_MmFixedStart( sizeof(Map_Super_t) ); p->mmEntries = Extra_MmFixedStart( sizeof(Map_HashEntry_t) ); p->mmForms = Extra_MmFlexStart(); Map_MappingSetupTruthTables( p->uTruths ); // start the hash table p->tTableC = Map_SuperTableCreate( p ); p->tTable = Map_SuperTableCreate( p ); // read the supergate library from file clk = Abc_Clock(); if ( vStr != NULL ) { // read the supergate library from file int Status = Map_LibraryReadFileTreeStr( p, pGenlib, vStr, pFileName ); if ( Status == 0 ) { Map_SuperLibFree( p ); return NULL; } // prepare the info about the library Status = Map_LibraryDeriveGateInfo( p, NULL ); if ( Status == 0 ) { Map_SuperLibFree( p ); return NULL; } assert( p->nVarsMax > 0 ); } else if ( fAlgorithm ) { if ( !Map_LibraryReadTree( p, pGenlib, pFileName, pExcludeFile ) ) { Map_SuperLibFree( p ); return NULL; } } else { if ( pExcludeFile != 0 ) { Map_SuperLibFree( p ); printf ("Error: Exclude file support not present for old format. Stop.\n"); return NULL; } if ( !Map_LibraryRead( p, pFileName ) ) { Map_SuperLibFree( p ); return NULL; } } assert( p->nVarsMax > 0 ); // report the stats if ( fVerbose ) { printf( "Loaded %d unique %d-input supergates from \"%s\". ", p->nSupersReal, p->nVarsMax, pFileName ); ABC_PRT( "Time", Abc_Clock() - clk ); } // assign the interver parameters p->pGateInv = Mio_LibraryReadInv( p->pGenlib ); p->tDelayInv.Rise = Mio_LibraryReadDelayInvRise( p->pGenlib ); p->tDelayInv.Fall = Mio_LibraryReadDelayInvFall( p->pGenlib ); p->tDelayInv.Worst = MAP_MAX( p->tDelayInv.Rise, p->tDelayInv.Fall ); p->AreaInv = Mio_LibraryReadAreaInv( p->pGenlib ); p->AreaBuf = Mio_LibraryReadAreaBuf( p->pGenlib ); // assign the interver supergate p->pSuperInv = (Map_Super_t *)Extra_MmFixedEntryFetch( p->mmSupers ); memset( p->pSuperInv, 0, sizeof(Map_Super_t) ); p->pSuperInv->Num = -1; p->pSuperInv->nGates = 1; p->pSuperInv->nFanins = 1; p->pSuperInv->nFanLimit = 10; p->pSuperInv->pFanins[0] = p->ppSupers[0]; p->pSuperInv->pRoot = p->pGateInv; p->pSuperInv->Area = p->AreaInv; p->pSuperInv->tDelayMax = p->tDelayInv; p->pSuperInv->tDelaysR[0].Rise = MAP_NO_VAR; p->pSuperInv->tDelaysR[0].Fall = p->tDelayInv.Rise; p->pSuperInv->tDelaysF[0].Rise = p->tDelayInv.Fall; p->pSuperInv->tDelaysF[0].Fall = MAP_NO_VAR; return p; } /**Function************************************************************* Synopsis [Deallocates the supergate library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_SuperLibFree( Map_SuperLib_t * p ) { if ( p == NULL ) return; if ( p->pGenlib ) { if ( p->pGenlib != Abc_FrameReadLibGen() ) Mio_LibraryDelete( p->pGenlib ); p->pGenlib = NULL; } if ( p->tTableC ) Map_SuperTableFree( p->tTableC ); if ( p->tTable ) Map_SuperTableFree( p->tTable ); Extra_MmFixedStop( p->mmSupers ); Extra_MmFixedStop( p->mmEntries ); Extra_MmFlexStop( p->mmForms ); ABC_FREE( p->ppSupers ); ABC_FREE( p->pName ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Derives the library from the genlib library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib, int fVerbose ) { Map_SuperLib_t * pLibSuper; Vec_Str_t * vStr; char * pFileName; if ( pLib == NULL ) return 0; // compute supergates vStr = Super_PrecomputeStr( pLib, 5, 1, 100000000, 10000000, 10000000, 100, 1, 0 ); if ( vStr == NULL ) return 0; // create supergate library pFileName = Extra_FileNameGenericAppend( Mio_LibraryReadName(pLib), ".super" ); pLibSuper = Map_SuperLibCreate( pLib, vStr, pFileName, NULL, 1, 0 ); Vec_StrFree( vStr ); // replace the library Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() ); Abc_FrameSetLibSuper( pLibSuper ); return 1; } /**Function************************************************************* Synopsis [Derives the library from the genlib library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_SuperLibDeriveFromGenlib2( Mio_Library_t * pLib, int fVerbose ) { Abc_Frame_t * pAbc = Abc_FrameGetGlobalFrame(); char * pFileName; if ( pLib == NULL ) return 0; // compute supergates pFileName = Extra_FileNameGenericAppend(Mio_LibraryReadName(pLib), ".super"); Super_Precompute( pLib, 5, 1, 100000000, 10000000, 10000000, 100, 1, 0, pFileName ); // assuming that it terminated successfully if ( Cmd_CommandExecute( pAbc, pFileName ) ) { fprintf( stdout, "Cannot execute command \"read_super %s\".\n", pFileName ); return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperMatch.c000066400000000000000000000610421300674244400245050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperMatch.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $] ***********************************************************************/ #include "mapperInt.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" ABC_NAMESPACE_IMPL_START /* A potential improvement: When an internal node is not used in the mapping, its required times are set to be +infinity. So when we recover area, we try to find the best match for area and completely disregard the delay for the nodes that are not currently used in the mapping because any match whose arrival times are less than the required times (+infinity) can be used. It may be possible to develop a better approach to recover area for the nodes that are not currently used in the mapping... */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Cleans the match.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MatchClean( Map_Match_t * pMatch ) { memset( pMatch, 0, sizeof(Map_Match_t) ); pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned } /**Function************************************************************* Synopsis [Compares two matches.] Description [Returns 1 if the second match is better. Otherwise returns 0.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MatchCompare( Map_Man_t * pMan, Map_Match_t * pM1, Map_Match_t * pM2, int fDoingArea ) { // if ( pM1->pSuperBest == pM2->pSuperBest ) // return 0; if ( !fDoingArea ) { // compare the arrival times if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon ) return 0; if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon ) return 1; // compare the areas or area flows if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon ) return 0; if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon ) return 1; // compare the fanout limits if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit ) return 0; if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit ) return 1; // compare the number of leaves if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins ) return 0; if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins ) return 1; // otherwise prefer the old cut return 0; } else { // compare the areas or area flows if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon ) return 0; if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon ) return 1; // make decision based on cell profile if ( pMan->fUseProfile && pM1->pSuperBest && pM1->pSuperBest ) { int M1req = Mio_GateReadProfile(pM1->pSuperBest->pRoot); int M2req = Mio_GateReadProfile(pM2->pSuperBest->pRoot); int M1act = Mio_GateReadProfile2(pM1->pSuperBest->pRoot); int M2act = Mio_GateReadProfile2(pM2->pSuperBest->pRoot); //printf( "%d %d ", M1req, M2req ); if ( M1act < M1req && M2act > M2req ) return 0; if ( M2act < M2req && M1act > M1req ) return 1; } // compare the arrival times if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon ) return 0; if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon ) return 1; // compare the fanout limits if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit ) return 0; if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit ) return 1; // compare the number of leaves if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins ) return 0; if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins ) return 1; // otherwise prefer the old cut return 0; } } /**Function************************************************************* Synopsis [Find the best matching of the cut.] Description [The parameters: the node (pNode), the cut (pCut), the phase to be matched (fPhase), and the upper bound on the arrival times of the cut (fWorstLimit). This procedure goes through the matching supergates up to the phase assignment, and selects the best supergate, which will be used to map the cut. As a result of calling this procedure the matching information is written into pMatch.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MatchNodeCut( Map_Man_t * p, Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float fWorstLimit ) { Map_Match_t MatchBest, * pMatch = pCut->M + fPhase; Map_Super_t * pSuper; int i, Counter; // save the current match of the cut MatchBest = *pMatch; // go through the supergates for ( pSuper = pMatch->pSupers, Counter = 0; pSuper; pSuper = pSuper->pNext, Counter++ ) { p->nMatches++; // this is an attempt to reduce the runtime of matching and area // at the cost of rare and very minor increase in delay // (the supergates are sorted by increasing area) if ( Counter == 30 ) break; // go through different phases of the given match and supergate pMatch->pSuperBest = pSuper; for ( i = 0; i < (int)pSuper->nPhases; i++ ) { p->nPhases++; // find the overall phase of this match pMatch->uPhaseBest = pMatch->uPhase ^ pSuper->uPhases[i]; if ( p->fMappingMode == 0 ) { // get the arrival time Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit ); // skip the cut if the arrival times exceed the required times if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) continue; // get the area (area flow) pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); } else { // get the area (area flow) if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase ); else if ( p->fMappingMode == 4 ) pMatch->AreaFlow = Map_SwitchCutGetDerefed( pNode, pCut, fPhase ); else pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); // skip if the cut is too large if ( pMatch->AreaFlow > MatchBest.AreaFlow + p->fEpsilon ) continue; // get the arrival time Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit ); // skip the cut if the arrival times exceed the required times if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) continue; } // if the cut is non-trivial, compare it if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) ) { MatchBest = *pMatch; // if we are mapping for delay, the worst-case limit should be reduced if ( p->fMappingMode == 0 ) fWorstLimit = MatchBest.tArrive.Worst; } } } // set the best match *pMatch = MatchBest; // recompute the arrival time and area (area flow) of this cut if ( pMatch->pSuperBest ) { Map_TimeCutComputeArrival( pNode, pCut, fPhase, MAP_FLOAT_LARGE ); if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase ); else if ( p->fMappingMode == 4 ) pMatch->AreaFlow = Map_SwitchCutGetDerefed( pNode, pCut, fPhase ); else pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); } return 1; } /**Function************************************************************* Synopsis [Find the matching of one polarity of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ) { Map_Match_t MatchBest, * pMatch; Map_Cut_t * pCut, * pCutBest; float Area1 = 0.0; // Suppress "might be used uninitialized float Area2, fWorstLimit; // skip the cuts that have been unassigned during area recovery pCutBest = pNode->pCutBest[fPhase]; if ( p->fMappingMode != 0 && pCutBest == NULL ) return 1; // recompute the arrival times of the current best match // because the arrival times of the fanins may have changed // as a result of remapping fanins in the topological order if ( p->fMappingMode != 0 ) { Map_TimeCutComputeArrival( pNode, pCutBest, fPhase, MAP_FLOAT_LARGE ); // make sure that the required times are met // assert( pCutBest->M[fPhase].tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon ); // assert( pCutBest->M[fPhase].tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon ); } // recompute the exact area of the current best match // because the exact area of the fanins may have changed // as a result of remapping fanins in the topological order if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) { pMatch = pCutBest->M + fPhase; if ( pNode->nRefAct[fPhase] > 0 || (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) ) pMatch->AreaFlow = Area1 = Map_CutDeref( pCutBest, fPhase, p->fUseProfile ); else pMatch->AreaFlow = Area1 = Map_CutGetAreaDerefed( pCutBest, fPhase ); } else if ( p->fMappingMode == 4 ) { pMatch = pCutBest->M + fPhase; if ( pNode->nRefAct[fPhase] > 0 || (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) ) pMatch->AreaFlow = Area1 = Map_SwitchCutDeref( pNode, pCutBest, fPhase ); else pMatch->AreaFlow = Area1 = Map_SwitchCutGetDerefed( pNode, pCutBest, fPhase ); } // save the old mapping if ( pCutBest ) MatchBest = pCutBest->M[fPhase]; else Map_MatchClean( &MatchBest ); // select the new best cut fWorstLimit = pNode->tRequired[fPhase].Worst; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) { // limit gate sizes based on fanout count if ( p->fSkipFanout && ((pNode->nRefs > 3 && pCut->nLeaves > 2) || (pNode->nRefs > 1 && pCut->nLeaves > 3)) ) continue; pMatch = pCut->M + fPhase; if ( pMatch->pSupers == NULL ) continue; // find the matches for the cut Map_MatchNodeCut( p, pNode, pCut, fPhase, fWorstLimit ); if ( pMatch->pSuperBest == NULL || pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) continue; // if the cut can be matched compare the matchings if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) ) { pCutBest = pCut; MatchBest = *pMatch; // if we are mapping for delay, the worst-case limit should be tightened if ( p->fMappingMode == 0 ) fWorstLimit = MatchBest.tArrive.Worst; } } if ( pCutBest == NULL ) return 1; // set the new mapping pNode->pCutBest[fPhase] = pCutBest; pCutBest->M[fPhase] = MatchBest; // reference the new cut if it used if ( p->fMappingMode >= 2 && (pNode->nRefAct[fPhase] > 0 || (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0)) ) { if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) Area2 = Map_CutRef( pNode->pCutBest[fPhase], fPhase, p->fUseProfile ); else if ( p->fMappingMode == 4 ) Area2 = Map_SwitchCutRef( pNode, pNode->pCutBest[fPhase], fPhase ); else assert( 0 ); // assert( Area2 < Area1 + p->fEpsilon ); } // make sure that the requited times are met // assert( MatchBest.tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon ); // assert( MatchBest.tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon ); return 1; } /**Function************************************************************* Synopsis [Sets the PI arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingSetPiArrivalTimes( Map_Man_t * p ) { Map_Node_t * pNode; int i; for ( i = 0; i < p->nInputs; i++ ) { pNode = p->pInputs[i]; // set the arrival time of the positive phase if ( Scl_ConIsRunning() ) { float Time = Scl_ConGetInArrFloat( i ); pNode->tArrival[1].Fall = Time; pNode->tArrival[1].Rise = Time; pNode->tArrival[1].Worst = Time; } else pNode->tArrival[1] = p->pInputArrivals[i]; pNode->tArrival[1].Rise += p->pNodeDelays ? p->pNodeDelays[pNode->Num] : 0; pNode->tArrival[1].Fall += p->pNodeDelays ? p->pNodeDelays[pNode->Num] : 0; pNode->tArrival[1].Worst += p->pNodeDelays ? p->pNodeDelays[pNode->Num] : 0; // set the arrival time of the negative phase pNode->tArrival[0].Rise = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise; pNode->tArrival[0].Fall = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall; pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall); } } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Map_TimeMatchWithInverter( Map_Man_t * p, Map_Match_t * pMatch ) { Map_Time_t tArrInv; tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall; tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise; tArrInv.Worst = MAP_MAX( tArrInv.Rise, tArrInv.Fall ); return tArrInv.Worst; } /**Function************************************************************* Synopsis [Attempts dropping one phase of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode ) { Map_Match_t * pMatchBest0, * pMatchBest1; float tWorst0Using1, tWorst1Using0; int fUsePhase1, fUsePhase0; // nothing to do if one of the phases is already dropped if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL ) return; // do not drop while recovering area flow if ( p->fMappingMode == 1 )//|| p->fMappingMode == 2 ) return; // get the pointers to the matches of the best cuts pMatchBest0 = pNode->pCutBest[0]->M + 0; pMatchBest1 = pNode->pCutBest[1]->M + 1; // get the worst arrival times of each phase // implemented using the other phase with inverter added tWorst0Using1 = Map_TimeMatchWithInverter( p, pMatchBest1 ); tWorst1Using0 = Map_TimeMatchWithInverter( p, pMatchBest0 ); // consider the case of mapping for delay if ( p->fMappingMode == 0 && p->DelayTarget < ABC_INFINITY ) { // if the arrival time of a phase is larger than the arrival time // of the opposite phase plus the inverter, drop this phase if ( pMatchBest0->tArrive.Worst > tWorst0Using1 + p->fEpsilon ) pNode->pCutBest[0] = NULL; else if ( pMatchBest1->tArrive.Worst > tWorst1Using0 + p->fEpsilon ) pNode->pCutBest[1] = NULL; return; } // do not perform replacement if one of the phases is unused if ( pNode->nRefAct[0] == 0 || pNode->nRefAct[1] == 0 ) return; // check if replacement of each phase is possible using required times fUsePhase0 = fUsePhase1 = 0; if ( p->fMappingMode == 2 ) { fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon); fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon); } else if ( p->fMappingMode == 3 || p->fMappingMode == 4 ) { fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + p->fEpsilon); fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + p->fEpsilon); } if ( !fUsePhase0 && !fUsePhase1 ) return; // if replacement is possible both ways, use the one that works better if ( fUsePhase0 && fUsePhase1 ) { if ( pMatchBest0->AreaFlow < pMatchBest1->AreaFlow ) fUsePhase1 = 0; else fUsePhase0 = 0; } // only one phase should be used assert( fUsePhase0 ^ fUsePhase1 ); // set the corresponding cut to NULL if ( fUsePhase0 ) { // deref phase 1 cut if necessary if ( p->fMappingMode >= 2 && pNode->nRefAct[1] > 0 ) Map_CutDeref( pNode->pCutBest[1], 1, p->fUseProfile ); // get rid of the cut pNode->pCutBest[1] = NULL; // ref phase 0 cut if necessary if ( p->fMappingMode >= 2 && pNode->nRefAct[0] == 0 ) Map_CutRef( pNode->pCutBest[0], 0, p->fUseProfile ); } else { // deref phase 0 cut if necessary if ( p->fMappingMode >= 2 && pNode->nRefAct[0] > 0 ) Map_CutDeref( pNode->pCutBest[0], 0, p->fUseProfile ); // get rid of the cut pNode->pCutBest[0] = NULL; // ref phase 1 cut if necessary if ( p->fMappingMode >= 2 && pNode->nRefAct[1] == 0 ) Map_CutRef( pNode->pCutBest[1], 1, p->fUseProfile ); } } /**Function************************************************************* Synopsis [Transfers the arrival times from the best cuts to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode ) { // if both phases are available, set their arrival times if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) { pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive; pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive; } // if only one phase is available, compute the arrival time of other phase else if ( pNode->pCutBest[0] ) { pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive; pNode->tArrival[1].Rise = pNode->tArrival[0].Fall + p->pSuperLib->tDelayInv.Rise; pNode->tArrival[1].Fall = pNode->tArrival[0].Rise + p->pSuperLib->tDelayInv.Fall; pNode->tArrival[1].Worst = MAP_MAX(pNode->tArrival[1].Rise, pNode->tArrival[1].Fall); } else if ( pNode->pCutBest[1] ) { pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive; pNode->tArrival[0].Rise = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise; pNode->tArrival[0].Fall = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall; pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall); } else { assert( 0 ); } // assert( pNode->tArrival[0].Rise < pNode->tRequired[0].Rise + p->fEpsilon ); // assert( pNode->tArrival[0].Fall < pNode->tRequired[0].Fall + p->fEpsilon ); // assert( pNode->tArrival[1].Rise < pNode->tRequired[1].Rise + p->fEpsilon ); // assert( pNode->tArrival[1].Fall < pNode->tRequired[1].Fall + p->fEpsilon ); } /**Function************************************************************* Synopsis [Computes the best matches of the nodes.] Description [Uses parameter p->fMappingMode to decide how to assign the matches for both polarities of the node. While the matches are being assigned, one of them may turn out to be better than the other (in terms of delay, for example). In this case, the worse match can be permanently dropped, and the corresponding pointer set to NULL.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingMatches( Map_Man_t * p ) { ProgressBar * pProgress; Map_Node_t * pNode; int i; assert( p->fMappingMode >= 0 && p->fMappingMode <= 4 ); // use the externally given PI arrival times if ( p->fMappingMode == 0 ) Map_MappingSetPiArrivalTimes( p ); // estimate the fanouts if ( p->fMappingMode == 0 ) Map_MappingEstimateRefsInit( p ); else if ( p->fMappingMode == 1 ) Map_MappingEstimateRefs( p ); // the PI cuts are matched in the cut computation package // in the loop below we match the internal nodes pProgress = Extra_ProgressBarStart( stdout, p->vMapObjs->nSize ); for ( i = 0; i < p->vMapObjs->nSize; i++ ) { pNode = p->vMapObjs->pArray[i]; if ( Map_NodeIsBuf(pNode) ) { assert( pNode->p2 == NULL ); pNode->tArrival[0] = Map_Regular(pNode->p1)->tArrival[ Map_IsComplement(pNode->p1)]; pNode->tArrival[1] = Map_Regular(pNode->p1)->tArrival[!Map_IsComplement(pNode->p1)]; continue; } // skip primary inputs and secondary nodes if mapping with choices if ( !Map_NodeIsAnd( pNode ) || pNode->pRepr ) continue; // make sure that at least one non-trival cut is present if ( pNode->pCuts->pNext == NULL ) { Extra_ProgressBarStop( pProgress ); printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); return 0; } // match negative phase if ( !Map_MatchNodePhase( p, pNode, 0 ) ) { Extra_ProgressBarStop( pProgress ); return 0; } // match positive phase if ( !Map_MatchNodePhase( p, pNode, 1 ) ) { Extra_ProgressBarStop( pProgress ); return 0; } // make sure that at least one phase is mapped if ( pNode->pCutBest[0] == NULL && pNode->pCutBest[1] == NULL ) { printf( "\nError: Could not match both phases of AIG node %d.\n", pNode->Num ); printf( "Please make sure that the supergate library has equivalents of AND2 or NAND2.\n" ); printf( "If such supergates exist in the library, report a bug.\n" ); Extra_ProgressBarStop( pProgress ); return 0; } // if both phases are assigned, check if one of them can be dropped Map_NodeTryDroppingOnePhase( p, pNode ); // set the arrival times of the node using the best cuts Map_NodeTransferArrivalTimes( p, pNode ); // update the progress bar Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); } Extra_ProgressBarStop( pProgress ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperRefs.c000066400000000000000000000435111300674244400243510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperRefs.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperRefs.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the actual reference counter of a phase.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase ) { assert( !Map_IsComplement(pNode) ); if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned return pNode->nRefAct[fPhase]; assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned return pNode->nRefAct[2]; } /**Function************************************************************* Synopsis [Reads the estimated reference counter of a phase.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase ) { assert( !Map_IsComplement(pNode) ); if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned return pNode->nRefEst[fPhase]; assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned // return pNode->nRefEst[0] + pNode->nRefEst[1]; return pNode->nRefEst[2]; } /**Function************************************************************* Synopsis [Increments the actual reference counter of a phase.] Description [Returns the old reference counter.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase ) { assert( !Map_IsComplement(pNode) ); if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned return pNode->nRefAct[fPhase]++; assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned return pNode->nRefAct[2]++; } /**Function************************************************************* Synopsis [Decrements the actual reference counter of a phase.] Description [Returns the new reference counter.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase ) { assert( !Map_IsComplement(pNode) ); if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned return --pNode->nRefAct[fPhase]; assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned return --pNode->nRefAct[2]; } /**Function************************************************************* Synopsis [Sets the estimated reference counter for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingEstimateRefsInit( Map_Man_t * p ) { Map_Node_t * pNode; int i; for ( i = 0; i < p->vMapObjs->nSize; i++ ) { pNode = p->vMapObjs->pArray[i]; // pNode->nRefEst[0] = pNode->nRefEst[1] = ((float)pNode->nRefs)*(float)2.0; pNode->nRefEst[0] = pNode->nRefEst[1] = pNode->nRefEst[2] = ((float)pNode->nRefs); } } /**Function************************************************************* Synopsis [Sets the estimated reference counter.] Description [When this procedure is called for the first time, the reference counter is estimated from the AIG. Otherwise, it is a linear combination of reference counters in the last two iterations.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingEstimateRefs( Map_Man_t * p ) { Map_Node_t * pNode; int i; for ( i = 0; i < p->vMapObjs->nSize; i++ ) { pNode = p->vMapObjs->pArray[i]; // pNode->nRefEst[0] = (float)((2.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 3.0); // pNode->nRefEst[1] = (float)((2.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 3.0); // pNode->nRefEst[2] = (float)((2.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 3.0); pNode->nRefEst[0] = (float)((3.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 4.0); pNode->nRefEst[1] = (float)((3.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 4.0); pNode->nRefEst[2] = (float)((3.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 4.0); } } /**function************************************************************* synopsis [Computes the area flow of the cut.] description [Computes the area flow of the cut if it is implemented using the best supergate with the best phase.] sideeffects [] seealso [] ***********************************************************************/ float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase ) { Map_Match_t * pM = pCut->M + fPhase; Map_Super_t * pSuper = pM->pSuperBest; unsigned uPhaseTot = pM->uPhaseBest; Map_Cut_t * pCutFanin; float aFlowRes, aFlowFanin, nRefs; int i, fPinPhasePos; // start the resulting area flow aFlowRes = pSuper->Area; // iterate through the leaves for ( i = 0; i < pCut->nLeaves; i++ ) { // get the phase of this fanin fPinPhasePos = ((uPhaseTot & (1 << i)) == 0); // get the cut implementing this phase of the fanin pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos]; // if the cut is not available, we have to use the opposite phase if ( pCutFanin == NULL ) { fPinPhasePos = !fPinPhasePos; pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos]; } aFlowFanin = pCutFanin->M[fPinPhasePos].AreaFlow; // ignores the area of the interter // get the fanout count of the cut in the given phase nRefs = Map_NodeReadRefPhaseEst( pCut->ppLeaves[i], fPinPhasePos ); // if the node does no fanout, assume fanout count equal to 1 if ( nRefs == (float)0.0 ) nRefs = (float)1.0; // add the area flow due to the fanin aFlowRes += aFlowFanin / nRefs; } pM->AreaFlow = aFlowRes; return aFlowRes; } /**function************************************************************* synopsis [References or dereferences the cut.] description [This reference part is similar to Cudd_NodeReclaim(). The dereference part is similar to Cudd_RecursiveDeref().] sideeffects [] seealso [] ***********************************************************************/ float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference, int fUpdateProf ) { Map_Node_t * pNodeChild; Map_Cut_t * pCutChild; float aArea; int i, fPhaseChild; // int nRefs; // consider the elementary variable if ( pCut->nLeaves == 1 ) return 0; // start the area of this cut aArea = Map_CutGetRootArea( pCut, fPhase ); if ( fUpdateProf ) { if ( fReference ) Mio_GateIncProfile2( pCut->M[fPhase].pSuperBest->pRoot ); else Mio_GateDecProfile2( pCut->M[fPhase].pSuperBest->pRoot ); } // go through the children for ( i = 0; i < pCut->nLeaves; i++ ) { pNodeChild = pCut->ppLeaves[i]; fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i ); // get the reference counter of the child /* // this code does not take inverters into account // the quality of area recovery seems to always be a little worse if ( fReference ) nRefs = Map_NodeIncRefPhaseAct( pNodeChild, fPhaseChild ); else nRefs = Map_NodeDecRefPhaseAct( pNodeChild, fPhaseChild ); assert( nRefs >= 0 ); // skip if the child was already reference before if ( nRefs > 0 ) continue; */ if ( fReference ) { if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present { // if this phase of the node is referenced, there is no recursive call pNodeChild->nRefAct[2]++; if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 ) continue; } else // only one phase is present { // inverter should be added if the phase // (a) has no reference and (b) is implemented using other phase if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) aArea += pNodeChild->p->pSuperLib->AreaInv; // if the node is referenced, there is no recursive call if ( pNodeChild->nRefAct[2]++ > 0 ) continue; } } else { if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present { // if this phase of the node is referenced, there is no recursive call --pNodeChild->nRefAct[2]; if ( --pNodeChild->nRefAct[fPhaseChild] > 0 ) continue; } else // only one phase is present { // inverter should be added if the phase // (a) has no reference and (b) is implemented using other phase if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) aArea += pNodeChild->p->pSuperLib->AreaInv; // if the node is referenced, there is no recursive call if ( --pNodeChild->nRefAct[2] > 0 ) continue; } assert( pNodeChild->nRefAct[fPhaseChild] >= 0 ); } // get the child cut pCutChild = pNodeChild->pCutBest[fPhaseChild]; // if the child does not have this phase mapped, take the opposite phase if ( pCutChild == NULL ) { fPhaseChild = !fPhaseChild; pCutChild = pNodeChild->pCutBest[fPhaseChild]; } // reference and compute area recursively aArea += Map_CutRefDeref( pCutChild, fPhaseChild, fReference, fUpdateProf ); } return aArea; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [Assumes that the cut is referenced.] sideeffects [] seealso [] ***********************************************************************/ float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase ) { float aResult, aResult2; aResult2 = Map_CutRefDeref( pCut, fPhase, 0, 0 ); // dereference aResult = Map_CutRefDeref( pCut, fPhase, 1, 0 ); // reference // assert( aResult == aResult2 ); return aResult; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase ) { float aResult, aResult2; aResult2 = Map_CutRefDeref( pCut, fPhase, 1, 0 ); // reference aResult = Map_CutRefDeref( pCut, fPhase, 0, 0 ); // dereference // assert( aResult == aResult2 ); return aResult; } /**function************************************************************* synopsis [References the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Map_CutRef( Map_Cut_t * pCut, int fPhase, int fProfile ) { return Map_CutRefDeref( pCut, fPhase, 1, fProfile ); // reference } /**function************************************************************* synopsis [Dereferences the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Map_CutDeref( Map_Cut_t * pCut, int fPhase, int fProfile ) { return Map_CutRefDeref( pCut, fPhase, 0, fProfile ); // dereference } /**Function************************************************************* Synopsis [Computes actual reference counters.] Description [Collects the nodes used in the mapping in array pMan->vMapping. Nodes are collected in reverse topological order to facilitate the computation of required times.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode ) { Map_Cut_t * pCut; Map_Node_t * pNodeR; unsigned uPhase; int i, fPhase, fInvPin; // get the regular node and its phase pNodeR = Map_Regular(pNode); fPhase = !Map_IsComplement(pNode); pNodeR->nRefAct[2]++; // quit if the node was already visited in this phase if ( pNodeR->nRefAct[fPhase]++ ) return; // quit if this is a PI node if ( Map_NodeIsVar(pNodeR) ) return; // propagate through buffer if ( Map_NodeIsBuf(pNodeR) ) { Map_MappingSetRefs_rec( pMan, Map_NotCond(pNodeR->p1, Map_IsComplement(pNode)) ); return; } assert( Map_NodeIsAnd(pNode) ); // get the cut implementing this or opposite polarity pCut = pNodeR->pCutBest[fPhase]; if ( pCut == NULL ) { fPhase = !fPhase; pCut = pNodeR->pCutBest[fPhase]; } if ( pMan->fUseProfile ) Mio_GateIncProfile2( pCut->M[fPhase].pSuperBest->pRoot ); // visit the transitive fanin uPhase = pCut->M[fPhase].uPhaseBest; for ( i = 0; i < pCut->nLeaves; i++ ) { fInvPin = ((uPhase & (1 << i)) > 0); Map_MappingSetRefs_rec( pMan, Map_NotCond(pCut->ppLeaves[i], fInvPin) ); } } void Map_MappingSetRefs( Map_Man_t * pMan ) { Map_Node_t * pNode; int i; if ( pMan->fUseProfile ) Mio_LibraryCleanProfile2( pMan->pSuperLib->pGenlib ); // clean all references for ( i = 0; i < pMan->vMapObjs->nSize; i++ ) { pNode = pMan->vMapObjs->pArray[i]; pNode->nRefAct[0] = 0; pNode->nRefAct[1] = 0; pNode->nRefAct[2] = 0; } // visit nodes reachable from POs in the DFS order through the best cuts for ( i = 0; i < pMan->nOutputs; i++ ) { pNode = pMan->pOutputs[i]; if ( !Map_NodeIsConst(pNode) ) Map_MappingSetRefs_rec( pMan, pNode ); } } /**Function************************************************************* Synopsis [Computes the array of mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_MappingGetArea( Map_Man_t * pMan ) { Map_Node_t * pNode; float Area = 0.0; int i; if ( pMan->fUseProfile ) Mio_LibraryCleanProfile2( pMan->pSuperLib->pGenlib ); for ( i = 0; i < pMan->vMapObjs->nSize; i++ ) { pNode = pMan->vMapObjs->pArray[i]; if ( pNode->nRefAct[2] == 0 ) continue; if ( Map_NodeIsBuf(pNode) ) continue; // at least one phase has the best cut assigned assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); // at least one phase is used in the mapping assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); // compute the array due to the supergate if ( Map_NodeIsAnd(pNode) ) { // count area of the negative phase if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) { Area += pNode->pCutBest[0]->M[0].pSuperBest->Area; if ( pMan->fUseProfile ) Mio_GateIncProfile2( pNode->pCutBest[0]->M[0].pSuperBest->pRoot ); } // count area of the positive phase if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) { Area += pNode->pCutBest[1]->M[1].pSuperBest->Area; if ( pMan->fUseProfile ) Mio_GateIncProfile2( pNode->pCutBest[1]->M[1].pSuperBest->pRoot ); } } // count area of the interver if we need to implement one phase with another phase if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) ) Area += pMan->pSuperLib->AreaInv; } // add buffers for each CO driven by a CI for ( i = 0; i < pMan->nOutputs; i++ ) if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) ) Area += pMan->pSuperLib->AreaBuf; return Area; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperSuper.c000066400000000000000000000340501300674244400245460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperSuper.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperSuper.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile ); static Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars ); static int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate ); static void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] ); static void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] ); static void Map_LibraryPrintClasses( Map_SuperLib_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the supergate library from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_LibraryRead( Map_SuperLib_t * pLib, char * pFileName ) { FILE * pFile; int Status; // read the beginning of the file assert( pLib->pGenlib == NULL ); pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return 0; } Status = Map_LibraryReadFile( pLib, pFile ); fclose( pFile ); // Map_LibraryPrintClasses( pLib ); return Status; } /**Function************************************************************* Synopsis [Reads the library file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile ) { ProgressBar * pProgress; char pBuffer[5000]; FILE * pFileGen; Map_Super_t * pGate; char * pTemp = NULL; // Suppress "might be used uninitialized" char * pLibName; int nCounter, nGatesTotal; unsigned uCanon[2]; int RetValue; // skip empty and comment lines while ( fgets( pBuffer, 2000, pFile ) != NULL ) { // skip leading spaces for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); // skip comment lines and empty lines if ( *pTemp != 0 && *pTemp != '#' ) break; } // get the genlib file name pLibName = strtok( pTemp, " \t\r\n" ); if ( strcmp( pLibName, "GATE" ) == 0 ) { printf( "The input file \"%s\" looks like a genlib file and not a supergate library file.\n", pLib->pName ); return 0; } pFileGen = fopen( pLibName, "r" ); if ( pFileGen == NULL ) { printf( "Cannot open the genlib file \"%s\".\n", pLibName ); return 0; } fclose( pFileGen ); // read the genlib library pLib->pGenlib = Mio_LibraryRead( pLibName, NULL, 0, 0 ); if ( pLib->pGenlib == NULL ) { printf( "Cannot read genlib file \"%s\".\n", pLibName ); return 0; } // read the number of variables RetValue = fscanf( pFile, "%d\n", &pLib->nVarsMax ); if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) { printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); return 0; } // read the number of gates RetValue = fscanf( pFile, "%d\n", &nGatesTotal ); if ( nGatesTotal < 1 || nGatesTotal > 10000000 ) { printf( "Suspicious number of gates (%d).\n", nGatesTotal ); return 0; } // read the lines nCounter = 0; pProgress = Extra_ProgressBarStart( stdout, nGatesTotal ); while ( fgets( pBuffer, 5000, pFile ) != NULL ) { for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); if ( pTemp[0] == '\0' ) continue; // get the gate pGate = Map_LibraryReadGate( pLib, pTemp, pLib->nVarsMax ); assert( pGate->Num == nCounter + 1 ); // count the number of parentheses in the formula - this is the number of gates for ( pTemp = pGate->pFormula; *pTemp; pTemp++ ) pGate->nGates += (*pTemp == '('); // verify the truth table assert( Map_LibraryTruthVerify(pLib, pGate) ); // find the N-canonical form of this supergate pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, pLib->nVarsMax, pGate->uTruth, pGate->uPhases, uCanon ); // add the supergate into the table by its N-canonical table Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate ); // update the progress bar Extra_ProgressBarUpdate( pProgress, ++nCounter, NULL ); } Extra_ProgressBarStop( pProgress ); pLib->nSupersAll = nCounter; if ( nCounter != nGatesTotal ) printf( "The number of gates read (%d) is different what the file says (%d).\n", nGatesTotal, nCounter ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars ) { Map_Super_t * pGate; char * pTemp; int i; // start and clean the gate pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); memset( pGate, 0, sizeof(Map_Super_t) ); // read the number pTemp = strtok( pBuffer, " " ); pGate->Num = atoi(pTemp); // read the signature pTemp = strtok( NULL, " " ); if ( pLib->nVarsMax < 6 ) { pGate->uTruth[0] = Extra_ReadBinary(pTemp); pGate->uTruth[1] = 0; } else { pGate->uTruth[0] = Extra_ReadBinary(pTemp+32); pTemp[32] = 0; pGate->uTruth[1] = Extra_ReadBinary(pTemp); } // read the max delay pTemp = strtok( NULL, " " ); pGate->tDelayMax.Rise = (float)atof(pTemp); pGate->tDelayMax.Fall = pGate->tDelayMax.Rise; // read the pin-to-pin delay for ( i = 0; i < nVars; i++ ) { pTemp = strtok( NULL, " " ); pGate->tDelaysR[i].Rise = (float)atof(pTemp); pGate->tDelaysF[i].Fall = pGate->tDelaysR[i].Rise; } // read the area pTemp = strtok( NULL, " " ); pGate->Area = (float)atof(pTemp); // the rest is the gate name pTemp = strtok( NULL, " \r\n" ); if ( strlen(pTemp) == 0 ) printf( "A gate name is empty.\n" ); // save the gate name pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp) + 1 ); strcpy( pGate->pFormula, pTemp ); // the rest is the gate name pTemp = strtok( NULL, " \n\0" ); if ( pTemp != NULL ) printf( "The following trailing symbols found \"%s\".\n", pTemp ); return pGate; } /**Function************************************************************* Synopsis [Performs one step of parsing the formula into parts.] Description [This function will eventually be replaced when the tree-supergate library representation will become standard.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings ) { char * pName, * pPar1, * pPar2, * pCur; int nStrings, CountPars; // skip leading spaces for ( pName = pFormula; *pName && *pName == ' '; pName++ ); assert( *pName ); // find the first opening parenthesis for ( pPar1 = pName; *pPar1 && *pPar1 != '('; pPar1++ ); if ( *pPar1 == 0 ) { *pnStrings = 0; return pName; } // overwrite it with space assert( *pPar1 == '(' ); *pPar1 = 0; // find the corresponding closing parenthesis for ( CountPars = 1, pPar2 = pPar1 + 1; *pPar2 && CountPars; pPar2++ ) if ( *pPar2 == '(' ) CountPars++; else if ( *pPar2 == ')' ) CountPars--; pPar2--; assert( CountPars == 0 ); // overwrite it with space assert( *pPar2 == ')' ); *pPar2 = 0; // save the intervals between the commas nStrings = 0; pCur = pPar1 + 1; while ( 1 ) { // save the current string pStrings[ nStrings++ ] = pCur; // find the beginning of the next string for ( CountPars = 0; *pCur && (CountPars || *pCur != ','); pCur++ ) if ( *pCur == '(' ) CountPars++; else if ( *pCur == ')' ) CountPars--; if ( *pCur == 0 ) break; assert( *pCur == ',' ); *pCur = 0; pCur++; } // save the results and return *pnStrings = nStrings; return pName; } /**Function************************************************************* Synopsis [Verifies the truth table of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate ) { unsigned uTruthRes[2]; Map_LibraryComputeTruth( pLib, pGate->pFormula, uTruthRes ); if ( uTruthRes[0] != pGate->uTruth[0] || uTruthRes[1] != pGate->uTruth[1] ) return 0; return 1; } /**Function************************************************************* Synopsis [Derives the functionality of the supergate.] Description [This procedure is useful for verification the supergate library. The truth table derived by this procedure should be the same as the one contained in the original supergate file.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] ) { char Buffer[1000]; strcpy( Buffer, pFormula ); Map_LibraryComputeTruth_rec( pLib, Buffer, pLib->uTruths, uTruthRes ); } /**Function************************************************************* Synopsis [Derives the functionality of the supergate.] Description [This procedure is useful for verification the supergate library. The truth table derived by this procedure should be the same as the one contained in the original supergate file.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] ) { Mio_Gate_t * pMioGate; char * pGateName, * pStrings[6]; unsigned uTruthsFanins[6][2]; int nStrings, i; // perform one step parsing of the formula // detect the root gate name, the next-step strings, and their number pGateName = Map_LibraryReadFormulaStep( pFormula, pStrings, &nStrings ); if ( nStrings == 0 ) // elementary variable { assert( pGateName[0] - 'a' < pLib->nVarsMax ); uTruthRes[0] = uTruthsIn[pGateName[0] - 'a'][0]; uTruthRes[1] = uTruthsIn[pGateName[0] - 'a'][1]; return; } // derive the functionality of the fanins for ( i = 0; i < nStrings; i++ ) Map_LibraryComputeTruth_rec( pLib, pStrings[i], uTruthsIn, uTruthsFanins[i] ); // get the root supergate pMioGate = Mio_LibraryReadGateByName( pLib->pGenlib, pGateName, NULL ); if ( pMioGate == NULL ) printf( "A supergate contains gate \"%s\" that is not in \"%s\".\n", pGateName, Mio_LibraryReadName(pLib->pGenlib) ); // derive the functionality of the output of the supergate Mio_DeriveTruthTable( pMioGate, uTruthsFanins, nStrings, pLib->nVarsMax, uTruthRes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_LibraryPrintSupergate( Map_Super_t * pGate ) { printf( "%5d : ", pGate->nUsed ); printf( "%5d ", pGate->Num ); printf( "A = %5.2f ", pGate->Area ); printf( "D = %5.2f/%5.2f/%5.2f ", pGate->tDelayMax.Rise, pGate->tDelayMax.Fall, pGate->tDelayMax.Worst ); printf( "%s", pGate->pFormula ); printf( "\n" ); } /**Function************************************************************* Synopsis [Prints N-classes of supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_LibraryPrintClasses( Map_SuperLib_t * p ) { /* st__generator * gen; Map_Super_t * pSuper, * pSuper2; unsigned Key, uTruth; int Counter = 0; // copy all the supergates into one array st__foreach_item( p->tSuplib, gen, (char **)&Key, (char **)&pSuper ) { for ( pSuper2 = pSuper; pSuper2; pSuper2 = pSuper2->pNext ) { uTruth = pSuper2->Phase; Extra_PrintBinary( stdout, &uTruth, 5 ); printf( " %5d ", pSuper2->Num ); printf( "%s", pSuper2->pFormula ); printf( "\n" ); } printf( "\n" ); if ( ++ Counter == 100 ) break; } */ } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperSwitch.c000066400000000000000000000200101300674244400247000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperSwitch.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mapperSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) { float aResult, aResult2; // assert( pNode->Switching > 0 ); aResult2 = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference aResult = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference // assert( aResult == aResult2 ); return aResult; } /**function************************************************************* synopsis [References the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) { return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference } /**function************************************************************* synopsis [References the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) { return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference } /**function************************************************************* synopsis [References or dereferences the cut.] description [This reference part is similar to Cudd_NodeReclaim(). The dereference part is similar to Cudd_RecursiveDeref().] sideeffects [] seealso [] ***********************************************************************/ float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference ) { Map_Node_t * pNodeChild; Map_Cut_t * pCutChild; float aSwitchActivity; int i, fPhaseChild; // start switching activity for the node aSwitchActivity = pNode->Switching; // consider the elementary variable if ( pCut->nLeaves == 1 ) return aSwitchActivity; // go through the children assert( pCut->M[fPhase].pSuperBest ); for ( i = 0; i < pCut->nLeaves; i++ ) { pNodeChild = pCut->ppLeaves[i]; fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i ); // get the reference counter of the child if ( fReference ) { if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present { // if this phase of the node is referenced, there is no recursive call pNodeChild->nRefAct[2]++; if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 ) continue; } else // only one phase is present { // inverter should be added if the phase // (a) has no reference and (b) is implemented using other phase if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node // if the node is referenced, there is no recursive call if ( pNodeChild->nRefAct[2]++ > 0 ) continue; } } else { if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present { // if this phase of the node is referenced, there is no recursive call --pNodeChild->nRefAct[2]; if ( --pNodeChild->nRefAct[fPhaseChild] > 0 ) continue; } else // only one phase is present { // inverter should be added if the phase // (a) has no reference and (b) is implemented using other phase if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node // if the node is referenced, there is no recursive call if ( --pNodeChild->nRefAct[2] > 0 ) continue; } assert( pNodeChild->nRefAct[fPhaseChild] >= 0 ); } // get the child cut pCutChild = pNodeChild->pCutBest[fPhaseChild]; // if the child does not have this phase mapped, take the opposite phase if ( pCutChild == NULL ) { fPhaseChild = !fPhaseChild; pCutChild = pNodeChild->pCutBest[fPhaseChild]; } // reference and compute area recursively aSwitchActivity += Map_SwitchCutRefDeref( pNodeChild, pCutChild, fPhaseChild, fReference ); } return aSwitchActivity; } /**Function************************************************************* Synopsis [Computes the array of mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_MappingGetSwitching( Map_Man_t * pMan ) { Map_Node_t * pNode; float Switch = 0.0; int i; for ( i = 0; i < pMan->vMapObjs->nSize; i++ ) { pNode = pMan->vMapObjs->pArray[i]; if ( pNode->nRefAct[2] == 0 ) continue; // at least one phase has the best cut assigned assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); // at least one phase is used in the mapping assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); // compute the array due to the supergate if ( Map_NodeIsAnd(pNode) ) { // count switching of the negative phase if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) Switch += pNode->Switching; // count switching of the positive phase if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) Switch += pNode->Switching; } // count switching of the interver if we need to implement one phase with another phase if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) ) Switch += pNode->Switching; // inverter switches the same as the node } // add buffers for each CO driven by a CI for ( i = 0; i < pMan->nOutputs; i++ ) if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) ) Switch += pMan->pOutputs[i]->Switching; return Switch; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperTable.c000066400000000000000000000316021300674244400244770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperTable.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperTable.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the table function for the tables #define MAP_TABLE_HASH(u1,u2,nSize) (((u1) + 2003 * (u2)) % nSize) static void Map_SuperTableResize( Map_HashTable_t * pLib ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the hash table for supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib ) { Map_HashTable_t * p; // allocate the table p = ABC_ALLOC( Map_HashTable_t, 1 ); memset( p, 0, sizeof(Map_HashTable_t) ); p->mmMan = pLib->mmEntries; // allocate and clean the bins p->nBins = Abc_PrimeCudd(20000); p->pBins = ABC_ALLOC( Map_HashEntry_t *, p->nBins ); memset( p->pBins, 0, sizeof(Map_HashEntry_t *) * p->nBins ); return p; } /**Function************************************************************* Synopsis [Deallocates the supergate hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_SuperTableFree( Map_HashTable_t * p ) { ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Inserts a new entry into the hash table.] Description [This function inserts the new gate (pGate), which will be accessible through its canonical form (uTruthC).] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_SuperTableInsertC( Map_HashTable_t * p, unsigned uTruthC[], Map_Super_t * pGate ) { Map_HashEntry_t * pEnt; unsigned Key; // resize the table if ( p->nEntries >= 2 * p->nBins ) Map_SuperTableResize( p ); // check if another supergate with the same canonical form exists Key = MAP_TABLE_HASH( uTruthC[0], uTruthC[1], p->nBins ); for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) if ( pEnt->uTruth[0] == uTruthC[0] && pEnt->uTruth[1] == uTruthC[1] ) break; // create a new entry if it does not exist if ( pEnt == NULL ) { // add the new entry to the table pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan ); memset( pEnt, 0, sizeof(Map_HashEntry_t) ); pEnt->uTruth[0] = uTruthC[0]; pEnt->uTruth[1] = uTruthC[1]; // add the hash table entry to the corresponding linked list in the table pEnt->pNext = p->pBins[Key]; p->pBins[Key] = pEnt; p->nEntries++; } // add the supergate to the entry pGate->pNext = pEnt->pGates; pEnt->pGates = pGate; return 0; } /**Function************************************************************* Synopsis [Inserts a new entry into the library.] Description [This function inserts the new gate (pGate), which will be accessible through its unfolded function (uTruth).] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_SuperTableInsert( Map_HashTable_t * p, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase ) { Map_HashEntry_t * pEnt; unsigned Key; // resize the table if ( p->nEntries >= 2 * p->nBins ) Map_SuperTableResize( p ); // check if this entry already exists Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins ); for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) return 1; // add the new hash table entry to the table pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan ); memset( pEnt, 0, sizeof(Map_HashEntry_t) ); pEnt->uTruth[0] = uTruth[0]; pEnt->uTruth[1] = uTruth[1]; pEnt->pGates = pGate; pEnt->uPhase = uPhase; // add the hash table to the corresponding linked list in the table pEnt->pNext = p->pBins[Key]; p->pBins[Key] = pEnt; p->nEntries++; /* printf( "Adding gate: %10u ", Key ); Map_LibraryPrintSupergate( pGate ); Extra_PrintBinary( stdout, uTruth, 32 ); printf( "\n" ); */ return 0; } /**Function************************************************************* Synopsis [Looks up an entry in the library.] Description [This function looks up the function, given by its truth table, and return two things: (1) the linked list of supergates, which can implement the functions of this N-class; (2) the phase, which should be applied to the given function, in order to derive the canonical form of this N-class.] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * p, unsigned uTruth[] ) { Map_HashEntry_t * pEnt; unsigned Key; Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->tTableC->nBins ); for ( pEnt = p->tTableC->pBins[Key]; pEnt; pEnt = pEnt->pNext ) if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) return pEnt->pGates; return NULL; } /**Function************************************************************* Synopsis [Looks up an entry in the library.] Description [This function looks up the function, given by its truth table, and return two things: (1) the linked list of supergates, which can implement the functions of this N-class; (2) the phase, which should be applied to the given function, in order to derive the canonical form of this N-class.] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase ) { Map_HashEntry_t * pEnt; unsigned Key; Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins ); for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) { *puPhase = pEnt->uPhase; return pEnt->pGates; } return NULL; } /**Function************************************************************* Synopsis [Resizes the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_SuperTableResize( Map_HashTable_t * p ) { Map_HashEntry_t ** pBinsNew; Map_HashEntry_t * pEnt, * pEnt2; int nBinsNew, Counter, i; unsigned Key; // get the new table size nBinsNew = Abc_PrimeCudd(2 * p->nBins); // allocate a new array pBinsNew = ABC_ALLOC( Map_HashEntry_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Map_HashEntry_t *) * nBinsNew ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < p->nBins; i++ ) for ( pEnt = p->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) { Key = MAP_TABLE_HASH( pEnt->uTruth[0], pEnt->uTruth[1], nBinsNew ); pEnt->pNext = pBinsNew[Key]; pBinsNew[Key] = pEnt; Counter++; } assert( Counter == p->nEntries ); // replace the table and the parameters ABC_FREE( p->pBins ); p->pBins = pBinsNew; p->nBins = nBinsNew; } /**Function************************************************************* Synopsis [Compares the supergates by the number of times they are used.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_SuperTableCompareSupergates( Map_Super_t ** ppS1, Map_Super_t ** ppS2 ) { if ( (*ppS1)->nUsed > (*ppS2)->nUsed ) return -1; if ( (*ppS1)->nUsed < (*ppS2)->nUsed ) return 1; return 0; } /**Function************************************************************* Synopsis [Compares the supergates by the number of times they are used.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_SuperTableCompareGatesInList( Map_Super_t ** ppS1, Map_Super_t ** ppS2 ) { // if ( (*ppS1)->tDelayMax.Rise > (*ppS2)->tDelayMax.Rise ) if ( (*ppS1)->Area > (*ppS2)->Area ) return -1; // if ( (*ppS1)->tDelayMax.Rise < (*ppS2)->tDelayMax.Rise ) if ( (*ppS1)->Area < (*ppS2)->Area ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorts supergates by usefulness and prints out most useful.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax ) { Map_HashEntry_t * pEnt; Map_Super_t ** ppSupers; Map_Super_t * pSuper; int nSupers, i; // copy all the supergates into one array ppSupers = ABC_ALLOC( Map_Super_t *, nSupersMax ); nSupers = 0; for ( i = 0; i < p->nBins; i++ ) for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext ) for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext ) ppSupers[nSupers++] = pSuper; // sort by usage qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), (int (*)(const void *, const void *)) Map_SuperTableCompareSupergates ); assert( Map_SuperTableCompareSupergates( ppSupers, ppSupers + nSupers - 1 ) <= 0 ); // print out the "top ten" // for ( i = 0; i < nSupers; i++ ) for ( i = 0; i < 10; i++ ) { if ( ppSupers[i]->nUsed == 0 ) break; printf( "%5d : ", ppSupers[i]->nUsed ); printf( "%5d ", ppSupers[i]->Num ); printf( "A = %5.2f ", ppSupers[i]->Area ); printf( "D = %5.2f ", ppSupers[i]->tDelayMax.Rise ); printf( "%s", ppSupers[i]->pFormula ); printf( "\n" ); } ABC_FREE( ppSupers ); } /**Function************************************************************* Synopsis [Sorts supergates by max delay for each truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax ) { Map_HashEntry_t * pEnt; Map_Super_t ** ppSupers; Map_Super_t * pSuper; int nSupers, i, k; ppSupers = ABC_ALLOC( Map_Super_t *, nSupersMax ); for ( i = 0; i < p->nBins; i++ ) for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext ) { // collect the gates in this entry nSupers = 0; for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext ) { // skip supergates, whose root is the AND gate // if ( strcmp( Mio_GateReadName(pSuper->pRoot), "and" ) == 0 ) // continue; ppSupers[nSupers++] = pSuper; } pEnt->pGates = NULL; if ( nSupers == 0 ) continue; // sort the gates by delay qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), (int (*)(const void *, const void *)) Map_SuperTableCompareGatesInList ); assert( Map_SuperTableCompareGatesInList( ppSupers, ppSupers + nSupers - 1 ) <= 0 ); // link them in the reverse order for ( k = 0; k < nSupers; k++ ) { ppSupers[k]->pNext = pEnt->pGates; pEnt->pGates = ppSupers[k]; } // save the number of supergates in the list pEnt->pGates->nSupers = nSupers; } ABC_FREE( ppSupers ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperTime.c000066400000000000000000000437351300674244400243600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperTime.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperTime.c,v 1.3 2005/03/02 02:35:54 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the maximum arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_TimeComputeArrivalMax( Map_Man_t * p ) { float tReqMax, tReq; int i, fPhase; // get the critical PO arrival time tReqMax = -MAP_FLOAT_LARGE; for ( i = 0; i < p->nOutputs; i++ ) { if ( Map_NodeIsConst(p->pOutputs[i]) ) continue; fPhase = !Map_IsComplement(p->pOutputs[i]); tReq = Map_Regular(p->pOutputs[i])->tArrival[fPhase].Worst; tReqMax = MAP_MAX( tReqMax, tReq ); } return tReqMax; } /**Function************************************************************* Synopsis [Computes the arrival times of the cut.] Description [Computes the arrival times of the cut if it is implemented using the given supergate with the given phase. Uses the constraint-type specification of rise/fall arrival times.] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstLimit ) { Map_Match_t * pM = pCut->M + fPhase; Map_Super_t * pSuper = pM->pSuperBest; unsigned uPhaseTot = pM->uPhaseBest; Map_Time_t * ptArrRes = &pM->tArrive; Map_Time_t * ptArrIn; int fPinPhase; float tDelay, tExtra; int i; tExtra = pNode->p->pNodeDelays ? pNode->p->pNodeDelays[pNode->Num] : 0; ptArrRes->Rise = ptArrRes->Fall = 0.0; ptArrRes->Worst = MAP_FLOAT_LARGE; for ( i = pCut->nLeaves - 1; i >= 0; i-- ) { // get the phase of the given pin fPinPhase = ((uPhaseTot & (1 << i)) == 0); ptArrIn = pCut->ppLeaves[i]->tArrival + fPinPhase; // get the rise of the output due to rise of the inputs if ( pSuper->tDelaysR[i].Rise > 0 ) { tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise + tExtra; if ( tDelay > tWorstLimit ) return MAP_FLOAT_LARGE; if ( ptArrRes->Rise < tDelay ) ptArrRes->Rise = tDelay; } // get the rise of the output due to fall of the inputs if ( pSuper->tDelaysR[i].Fall > 0 ) { tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall + tExtra; if ( tDelay > tWorstLimit ) return MAP_FLOAT_LARGE; if ( ptArrRes->Rise < tDelay ) ptArrRes->Rise = tDelay; } // get the fall of the output due to rise of the inputs if ( pSuper->tDelaysF[i].Rise > 0 ) { tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise + tExtra; if ( tDelay > tWorstLimit ) return MAP_FLOAT_LARGE; if ( ptArrRes->Fall < tDelay ) ptArrRes->Fall = tDelay; } // get the fall of the output due to fall of the inputs if ( pSuper->tDelaysF[i].Fall > 0 ) { tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall + tExtra; if ( tDelay > tWorstLimit ) return MAP_FLOAT_LARGE; if ( ptArrRes->Fall < tDelay ) ptArrRes->Fall = tDelay; } } // return the worst-case of rise/fall arrival times ptArrRes->Worst = MAP_MAX(ptArrRes->Rise, ptArrRes->Fall); return ptArrRes->Worst; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ) { Map_Time_t * ptReqIn, * ptReqOut; Map_Cut_t * pCut; Map_Super_t * pSuper; float tNewReqTime, tExtra; unsigned uPhase; int fPinPhase, i; tExtra = pNode->p->pNodeDelays ? pNode->p->pNodeDelays[pNode->Num] : 0; // get the cut to be propagated pCut = pNode->pCutBest[fPhase]; assert( pCut != NULL ); // get the supergate and its polarity pSuper = pCut->M[fPhase].pSuperBest; uPhase = pCut->M[fPhase].uPhaseBest; // get the required time of the output of the supergate ptReqOut = pNode->tRequired + fPhase; // set the required time of the children for ( i = 0; i < pCut->nLeaves; i++ ) { // get the phase of the given pin of the supergate fPinPhase = ((uPhase & (1 << i)) == 0); ptReqIn = pCut->ppLeaves[i]->tRequired + fPinPhase; assert( pCut->ppLeaves[i]->nRefAct[2] > 0 ); // get the rise of the output due to rise of the inputs // if ( ptArrOut->Rise < ptArrIn->Rise + pSuper->tDelaysR[i].Rise ) // ptArrOut->Rise = ptArrIn->Rise + pSuper->tDelaysR[i].Rise; if ( pSuper->tDelaysR[i].Rise > 0 ) { tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Rise - tExtra; ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime ); } // get the rise of the output due to fall of the inputs // if ( ptArrOut->Rise < ptArrIn->Fall + pSuper->tDelaysR[i].Fall ) // ptArrOut->Rise = ptArrIn->Fall + pSuper->tDelaysR[i].Fall; if ( pSuper->tDelaysR[i].Fall > 0 ) { tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Fall - tExtra; ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime ); } // get the fall of the output due to rise of the inputs // if ( ptArrOut->Fall < ptArrIn->Rise + pSuper->tDelaysF[i].Rise ) // ptArrOut->Fall = ptArrIn->Rise + pSuper->tDelaysF[i].Rise; if ( pSuper->tDelaysF[i].Rise > 0 ) { tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Rise - tExtra; ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime ); } // get the fall of the output due to fall of the inputs // if ( ptArrOut->Fall < ptArrIn->Fall + pSuper->tDelaysF[i].Fall ) // ptArrOut->Fall = ptArrIn->Fall + pSuper->tDelaysF[i].Fall; if ( pSuper->tDelaysF[i].Fall > 0 ) { tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Fall - tExtra; ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime ); } } // compare the required times with the arrival times // assert( pNode->tArrival[fPhase].Rise < ptReqOut->Rise + p->fEpsilon ); // assert( pNode->tArrival[fPhase].Fall < ptReqOut->Fall + p->fEpsilon ); } float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes ) { Map_Time_t * ptArrIn; Map_Super_t * pSuper; unsigned uPhaseTot; int fPinPhase, i; float tDelay; // get the supergate and the phase pSuper = pCut->M[fPhase].pSuperBest; uPhaseTot = pCut->M[fPhase].uPhaseBest; // propagate the arrival times ptArrRes->Rise = ptArrRes->Fall = -MAP_FLOAT_LARGE; for ( i = 0; i < pCut->nLeaves; i++ ) { // get the phase of the given pin fPinPhase = ((uPhaseTot & (1 << i)) == 0); ptArrIn = pCut->ppLeaves[i]->tRequired + fPinPhase; // assert( ptArrIn->Worst < MAP_FLOAT_LARGE ); // get the rise of the output due to rise of the inputs if ( pSuper->tDelaysR[i].Rise > 0 ) { tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise; if ( ptArrRes->Rise < tDelay ) ptArrRes->Rise = tDelay; } // get the rise of the output due to fall of the inputs if ( pSuper->tDelaysR[i].Fall > 0 ) { tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall; if ( ptArrRes->Rise < tDelay ) ptArrRes->Rise = tDelay; } // get the fall of the output due to rise of the inputs if ( pSuper->tDelaysF[i].Rise > 0 ) { tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise; if ( ptArrRes->Fall < tDelay ) ptArrRes->Fall = tDelay; } // get the fall of the output due to fall of the inputs if ( pSuper->tDelaysF[i].Fall > 0 ) { tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall; if ( ptArrRes->Fall < tDelay ) ptArrRes->Fall = tDelay; } } // return the worst-case of rise/fall arrival times return MAP_MAX(ptArrRes->Rise, ptArrRes->Fall); } /**Function************************************************************* Synopsis [Computes the required times of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_TimePropagateRequired( Map_Man_t * p ) { Map_Node_t * pNode; //Map_Time_t tReqOutTest, * ptReqOutTest = &tReqOutTest; Map_Time_t * ptReqIn, * ptReqOut; int fPhase, k; // go through the nodes in the reverse topological order for ( k = p->vMapObjs->nSize - 1; k >= 0; k-- ) { pNode = p->vMapObjs->pArray[k]; if ( pNode->nRefAct[2] == 0 ) continue; // propagate required times through the buffer if ( Map_NodeIsBuf(pNode) ) { assert( pNode->p2 == NULL ); Map_Regular(pNode->p1)->tRequired[ Map_IsComplement(pNode->p1)] = pNode->tRequired[0]; Map_Regular(pNode->p1)->tRequired[!Map_IsComplement(pNode->p1)] = pNode->tRequired[1]; continue; } // this computation works for regular nodes only assert( !Map_IsComplement(pNode) ); // at least one phase should be mapped assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); // the node should be used in the currently assigned mapping assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); // if one of the cuts is not given, project the required times from the other cut if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL ) { // assert( 0 ); // get the missing phase fPhase = (pNode->pCutBest[1] == NULL); // check if the missing phase is needed in the mapping if ( pNode->nRefAct[fPhase] > 0 ) { // get the pointers to the required times of the missing phase ptReqOut = pNode->tRequired + fPhase; // assert( ptReqOut->Fall < MAP_FLOAT_LARGE ); // get the pointers to the required times of the present phase ptReqIn = pNode->tRequired + !fPhase; // propagate the required times from the missing phase to the present phase // tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall; // tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise; ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, ptReqOut->Rise - p->pSuperLib->tDelayInv.Rise ); ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, ptReqOut->Fall - p->pSuperLib->tDelayInv.Fall ); } } // finalize the worst case computation pNode->tRequired[0].Worst = MAP_MIN( pNode->tRequired[0].Fall, pNode->tRequired[0].Rise ); pNode->tRequired[1].Worst = MAP_MIN( pNode->tRequired[1].Fall, pNode->tRequired[1].Rise ); // skip the PIs if ( !Map_NodeIsAnd(pNode) ) continue; // propagate required times of different phases of the node // the ordering of phases does not matter since they are mapped independently if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE ) Map_TimePropagateRequiredPhase( p, pNode, 0 ); if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE ) Map_TimePropagateRequiredPhase( p, pNode, 1 ); } /* // in the end, we verify the required times // for this, we compute the arrival times of the outputs of each phase // of the supergates using the fanins' required times as the fanins' arrival times // the resulting arrival time of the supergate should be less than the actual required time for ( k = p->vMapObjs->nSize - 1; k >= 0; k-- ) { pNode = p->vMapObjs->pArray[k]; if ( pNode->nRefAct[2] == 0 ) continue; if ( !Map_NodeIsAnd(pNode) ) continue; // verify that the required times are propagated correctly // if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE/2 ) { Map_MatchComputeReqTimes( pNode->pCutBest[0], 0, ptReqOutTest ); // assert( ptReqOutTest->Rise < pNode->tRequired[0].Rise + p->fEpsilon ); // assert( ptReqOutTest->Fall < pNode->tRequired[0].Fall + p->fEpsilon ); } // if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE/2 ) { Map_MatchComputeReqTimes( pNode->pCutBest[1], 1, ptReqOutTest ); // assert( ptReqOutTest->Rise < pNode->tRequired[1].Rise + p->fEpsilon ); // assert( ptReqOutTest->Fall < pNode->tRequired[1].Fall + p->fEpsilon ); } } */ } void Map_TimeComputeRequiredGlobal( Map_Man_t * p ) { int fUseConMan = Scl_ConIsRunning() && Scl_ConHasOutReqs(); Map_Time_t * ptTime, * ptTimeA; int fPhase, i; // update the required times according to the target p->fRequiredGlo = Map_TimeComputeArrivalMax( p ); if ( p->DelayTarget != -1 ) { if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon ) { if ( p->fMappingMode == 1 ) printf( "Cannot meet the target required times (%4.2f). Continue anyway.\n", p->DelayTarget ); } else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon ) { if ( p->fMappingMode == 1 && p->fVerbose ) printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget ); p->fRequiredGlo = p->DelayTarget; } } // clean the required times for ( i = 0; i < p->vMapObjs->nSize; i++ ) { p->vMapObjs->pArray[i]->tRequired[0].Rise = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[0].Fall = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[0].Worst = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[1].Rise = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[1].Fall = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[1].Worst = MAP_FLOAT_LARGE; } // set the required times for the POs for ( i = 0; i < p->nOutputs; i++ ) { fPhase = !Map_IsComplement(p->pOutputs[i]); ptTime = Map_Regular(p->pOutputs[i])->tRequired + fPhase; ptTimeA = Map_Regular(p->pOutputs[i])->tArrival + fPhase; if ( fUseConMan ) { float Value = Scl_ConGetOutReqFloat(i); // if external required time can be achieved, use it if ( Value > 0 && ptTimeA->Worst <= Value )//&& Value <= p->fRequiredGlo ) ptTime->Rise = ptTime->Fall = ptTime->Worst = Value; // if external required cannot be achieved, set the earliest possible arrival time else if ( Value > 0 && ptTimeA->Worst > Value ) ptTime->Rise = ptTime->Fall = ptTime->Worst = ptTimeA->Worst; // otherwise, set the global required time else ptTime->Rise = ptTime->Fall = ptTime->Worst = p->fRequiredGlo; } else { // if external required time can be achieved, use it if ( p->pOutputRequireds && p->pOutputRequireds[i].Worst > 0 && ptTimeA->Worst <= p->pOutputRequireds[i].Worst )//&& p->pOutputRequireds[i].Worst <= p->fRequiredGlo ) ptTime->Rise = ptTime->Fall = ptTime->Worst = p->pOutputRequireds[i].Worst; // if external required cannot be achieved, set the earliest possible arrival time else if ( p->pOutputRequireds && p->pOutputRequireds[i].Worst > 0 && ptTimeA->Worst > p->pOutputRequireds[i].Worst ) ptTime->Rise = ptTime->Fall = ptTime->Worst = ptTimeA->Worst; // otherwise, set the global required time else ptTime->Rise = ptTime->Fall = ptTime->Worst = p->fRequiredGlo; } } // visit nodes in the reverse topological order Map_TimePropagateRequired( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperTree.c000066400000000000000000001106131300674244400243470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperTree.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperTree.c,v 1.9 2005/01/23 06:59:45 alanmi Exp $] ***********************************************************************/ #ifdef __linux__ #include #endif #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin ); static int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate ); static unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ); // fanout limits static const int s_MapFanoutLimits[10] = { 1/*0*/, 10/*1*/, 5/*2*/, 2/*3*/, 1/*4*/, 1/*5*/, 1/*6*/ }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads one gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVarsMax ) { Map_Super_t * pGate; char * pTemp; int i, Num; // start and clean the gate pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); memset( pGate, 0, sizeof(Map_Super_t) ); // set the gate number pGate->Num = Number; // read the mark pTemp = strtok( pBuffer, " " ); if ( pTemp[0] == '*' ) { pGate->fSuper = 1; pTemp = strtok( NULL, " " ); } // read the root gate pGate->pRoot = Mio_LibraryReadGateByName( pLib->pGenlib, pTemp, NULL ); if ( pGate->pRoot == NULL ) { printf( "Cannot read the root gate names %s.\n", pTemp ); return NULL; } // set the max number of fanouts pGate->nFanLimit = s_MapFanoutLimits[ Mio_GateReadPinNum(pGate->pRoot) ]; // read the pin-to-pin delay for ( i = 0; ( pTemp = strtok( NULL, " \n\0" ) ); i++ ) { if ( pTemp[0] == '#' ) break; if ( i == nVarsMax ) { printf( "There are too many entries on the line.\n" ); return NULL; } Num = atoi(pTemp); if ( Num < 0 ) { printf( "The number of a child supergate is negative.\n" ); return NULL; } if ( Num > pLib->nLines ) { printf( "The number of a child supergate (%d) exceeded the number of lines (%d).\n", Num, pLib->nLines ); return NULL; } pGate->pFanins[i] = pLib->ppSupers[Num]; } pGate->nFanins = i; if ( pGate->nFanins != (unsigned)Mio_GateReadPinNum(pGate->pRoot) ) { printf( "The number of fanins of a root gate is wrong.\n" ); return NULL; } // save the gate name, just in case if ( pTemp && pTemp[0] == '#' ) { if ( pTemp[1] == 0 ) pTemp = strtok( NULL, " \n\0" ); else // skip spaces for ( pTemp++; *pTemp == ' '; pTemp++ ); // save the formula pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp)+1 ); strcpy( pGate->pFormula, pTemp ); } // check the rest of the string pTemp = strtok( NULL, " \n\0" ); if ( pTemp != NULL ) printf( "The following trailing symbols found \"%s\".\n", pTemp ); return pGate; } /**Function************************************************************* Synopsis [Reads the supergate library from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName ) { ProgressBar * pProgress; char pBuffer[5000]; Map_Super_t * pGate; char * pTemp = 0, * pLibName; int nCounter, k, i; int RetValue; // skip empty and comment lines while ( fgets( pBuffer, 5000, pFile ) != NULL ) { // skip leading spaces for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); // skip comment lines and empty lines if ( *pTemp != 0 && *pTemp != '#' ) break; } pLibName = strtok( pTemp, " \t\r\n" ); pLib->pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pLib->pGenlib == NULL || strcmp( Mio_LibraryReadName(pLib->pGenlib), pLibName ) ) { printf( "Supergate library \"%s\" requires the use of genlib library \"%s\".\n", pFileName, pLibName ); return 0; } // read the number of variables RetValue = fscanf( pFile, "%d\n", &pLib->nVarsMax ); if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) { printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); return 0; } // read the number of gates RetValue = fscanf( pFile, "%d\n", &pLib->nSupersReal ); if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 ) { printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal ); return 0; } // read the number of lines RetValue = fscanf( pFile, "%d\n", &pLib->nLines ); if ( pLib->nLines < 1 || pLib->nLines > 10000000 ) { printf( "Suspicious number of lines (%d).\n", pLib->nLines ); return 0; } // allocate room for supergate pointers pLib->ppSupers = ABC_ALLOC( Map_Super_t *, pLib->nLines + 10000 ); // create the elementary supergates for ( i = 0; i < pLib->nVarsMax; i++ ) { // get a new gate pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); memset( pGate, 0, sizeof(Map_Super_t) ); // assign the elementary variable, the truth table, and the delays pGate->Num = i; // set the truth table pGate->uTruth[0] = pLib->uTruths[i][0]; pGate->uTruth[1] = pLib->uTruths[i][1]; // set the arrival times of all input to non-existent delay for ( k = 0; k < pLib->nVarsMax; k++ ) { pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; } // set an existent arrival time for rise and fall pGate->tDelaysR[i].Rise = 0.0; pGate->tDelaysF[i].Fall = 0.0; // set the gate pLib->ppSupers[i] = pGate; } // read the lines nCounter = pLib->nVarsMax; pProgress = Extra_ProgressBarStart( stdout, pLib->nLines ); while ( fgets( pBuffer, 5000, pFile ) != NULL ) { for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); if ( pTemp[0] == '\0' ) continue; // if ( pTemp[0] == 'a' || pTemp[2] == 'a' ) // { // pLib->nLines--; // continue; // } // get the gate pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax ); if ( pGate == NULL ) { Extra_ProgressBarStop( pProgress ); return 0; } pLib->ppSupers[nCounter++] = pGate; // later we will derive: truth table, delays, area, number of component gates, etc // update the progress bar Extra_ProgressBarUpdate( pProgress, nCounter, NULL ); } Extra_ProgressBarStop( pProgress ); if ( nCounter != pLib->nLines ) printf( "The number of lines read (%d) is different what the file says (%d).\n", nCounter, pLib->nLines ); pLib->nSupersAll = nCounter; // count the number of real supergates nCounter = 0; for ( k = 0; k < pLib->nLines; k++ ) nCounter += pLib->ppSupers[k]->fSuper; if ( nCounter != pLib->nSupersReal ) printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal ); pLib->nSupersReal = nCounter; return 1; } int Map_LibraryReadTree2( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile ) { FILE * pFile; int Status, num; Abc_Frame_t * pAbc; st__table * tExcludeGate = 0; // read the beginning of the file assert( pLib->pGenlib == NULL ); pFile = Io_FileOpen( pFileName, "open_path", "r", 1 ); // pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return 0; } if ( pExcludeFile ) { pAbc = Abc_FrameGetGlobalFrame(); tExcludeGate = st__init_table(strcmp, st__strhash); if ( (num = Mio_LibraryReadExclude( pExcludeFile, tExcludeGate )) == -1 ) { st__free_table( tExcludeGate ); tExcludeGate = 0; return 0; } fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num ); } Status = Map_LibraryReadFileTree( pLib, pFile, pFileName ); fclose( pFile ); if ( Status == 0 ) return 0; // prepare the info about the library return Map_LibraryDeriveGateInfo( pLib, tExcludeGate ); } */ /**Function************************************************************* Synopsis [Similar to fgets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Vec_StrGets( char * pBuffer, int nBufferSize, Vec_Str_t * vStr, int * pPos ) { char * pCur; char * pBeg = Vec_StrArray(vStr) + *pPos; char * pEnd = Vec_StrArray(vStr) + Vec_StrSize(vStr); assert( nBufferSize > 1 ); if ( pBeg == pEnd ) { *pBuffer = 0; return 0; } assert( pBeg < pEnd ); for ( pCur = pBeg; pCur < pEnd; pCur++ ) { *pBuffer++ = *pCur; if ( *pCur == 0 ) { *pPos += pCur - pBeg; return 0; } if ( *pCur == '\n' ) { *pPos += pCur - pBeg + 1; *pBuffer = 0; return 1; } if ( pCur - pBeg == nBufferSize-1 ) { *pPos += pCur - pBeg + 1; *pBuffer = 0; return 1; } } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_LibraryCompareLibNames( char * pName1, char * pName2 ) { char * p1 = Abc_UtilStrsav( pName1 ); char * p2 = Abc_UtilStrsav( pName2 ); int i, RetValue; for ( i = 0; p1[i]; i++ ) if ( p1[i] == '>' || p1[i] == '\\' || p1[i] == '/' ) p1[i] = '/'; for ( i = 0; p2[i]; i++ ) if ( p2[i] == '>' || p2[i] == '\\' || p2[i] == '/' ) p2[i] = '/'; RetValue = strcmp( p1, p2 ); ABC_FREE( p1 ); ABC_FREE( p2 ); return RetValue; } /**Function************************************************************* Synopsis [Reads the supergate library from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_LibraryReadFileTreeStr( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, Vec_Str_t * vStr, char * pFileName ) { ProgressBar * pProgress; char pBuffer[5000]; Map_Super_t * pGate; char * pTemp = 0, * pLibName; int nCounter, k, i; int RetValue, nPos = 0; // skip empty and comment lines // while ( fgets( pBuffer, 5000, pFile ) != NULL ) while ( 1 ) { RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos ); if ( RetValue == 0 ) return 0; // skip leading spaces for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); // skip comment lines and empty lines if ( *pTemp != 0 && *pTemp != '#' ) break; } pLibName = strtok( pTemp, " \t\r\n" ); // pLib->pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); pLib->pGenlib = pGenlib; // if ( pLib->pGenlib == NULL || strcmp( , pLibName ) ) if ( pLib->pGenlib == NULL || Map_LibraryCompareLibNames(Mio_LibraryReadName(pLib->pGenlib), pLibName) ) { printf( "Supergate library \"%s\" requires the use of genlib library \"%s\".\n", pFileName, pLibName ); return 0; } // read the number of variables RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos ); if ( RetValue == 0 ) return 0; RetValue = sscanf( pBuffer, "%d\n", &pLib->nVarsMax ); if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) { printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); return 0; } // read the number of gates RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos ); if ( RetValue == 0 ) return 0; RetValue = sscanf( pBuffer, "%d\n", &pLib->nSupersReal ); if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 ) { printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal ); return 0; } // read the number of lines RetValue = Vec_StrGets( pBuffer, 5000, vStr, &nPos ); if ( RetValue == 0 ) return 0; RetValue = sscanf( pBuffer, "%d\n", &pLib->nLines ); if ( pLib->nLines < 1 || pLib->nLines > 10000000 ) { printf( "Suspicious number of lines (%d).\n", pLib->nLines ); return 0; } // allocate room for supergate pointers pLib->ppSupers = ABC_ALLOC( Map_Super_t *, pLib->nLines + 10000 ); // create the elementary supergates for ( i = 0; i < pLib->nVarsMax; i++ ) { // get a new gate pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); memset( pGate, 0, sizeof(Map_Super_t) ); // assign the elementary variable, the truth table, and the delays pGate->Num = i; // set the truth table pGate->uTruth[0] = pLib->uTruths[i][0]; pGate->uTruth[1] = pLib->uTruths[i][1]; // set the arrival times of all input to non-existent delay for ( k = 0; k < pLib->nVarsMax; k++ ) { pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; } // set an existent arrival time for rise and fall pGate->tDelaysR[i].Rise = 0.0; pGate->tDelaysF[i].Fall = 0.0; // set the gate pLib->ppSupers[i] = pGate; } // read the lines nCounter = pLib->nVarsMax; pProgress = Extra_ProgressBarStart( stdout, pLib->nLines ); // while ( fgets( pBuffer, 5000, pFile ) != NULL ) while ( Vec_StrGets( pBuffer, 5000, vStr, &nPos ) ) { for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); if ( pTemp[0] == '\0' ) continue; // if ( pTemp[0] == 'a' || pTemp[2] == 'a' ) // { // pLib->nLines--; // continue; // } // get the gate pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax ); if ( pGate == NULL ) { Extra_ProgressBarStop( pProgress ); return 0; } pLib->ppSupers[nCounter++] = pGate; // later we will derive: truth table, delays, area, number of component gates, etc // update the progress bar Extra_ProgressBarUpdate( pProgress, nCounter, NULL ); } Extra_ProgressBarStop( pProgress ); if ( nCounter != pLib->nLines ) printf( "The number of lines read (%d) is different from what the file says (%d).\n", nCounter, pLib->nLines ); pLib->nSupersAll = nCounter; // count the number of real supergates nCounter = 0; for ( k = 0; k < pLib->nLines; k++ ) nCounter += pLib->ppSupers[k]->fSuper; if ( nCounter != pLib->nSupersReal ) printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal ); pLib->nSupersReal = nCounter; return 1; } int Map_LibraryReadTree( Map_SuperLib_t * pLib, Mio_Library_t * pGenlib, char * pFileName, char * pExcludeFile ) { char * pBuffer; Vec_Str_t * vStr; int Status, num; Abc_Frame_t * pAbc; st__table * tExcludeGate = 0; // read the beginning of the file assert( pLib->pGenlib == NULL ); // pFile = Io_FileOpen( pFileName, "open_path", "r", 1 ); pBuffer = Mio_ReadFile( pFileName, 0 ); if ( pBuffer == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return 0; } vStr = Vec_StrAllocArray( pBuffer, strlen(pBuffer) ); if ( pExcludeFile ) { pAbc = Abc_FrameGetGlobalFrame(); tExcludeGate = st__init_table(strcmp, st__strhash); if ( (num = Mio_LibraryReadExclude( pExcludeFile, tExcludeGate )) == -1 ) { st__free_table( tExcludeGate ); tExcludeGate = 0; Vec_StrFree( vStr ); return 0; } fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num ); } Status = Map_LibraryReadFileTreeStr( pLib, pGenlib, vStr, pFileName ); Vec_StrFree( vStr ); if ( Status == 0 ) return 0; // prepare the info about the library return Map_LibraryDeriveGateInfo( pLib, tExcludeGate ); } /**Function************************************************************* Synopsis [Derives information about the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st__table * tExcludeGate ) { Map_Super_t * pGate, * pFanin; Mio_Pin_t * pPin; unsigned uCanon[2]; unsigned uTruths[6][2]; int i, k, nRealVars; // set all the derivable info related to the supergates for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ ) { pGate = pLib->ppSupers[i]; if ( tExcludeGate ) { if ( st__is_member( tExcludeGate, Mio_GateReadName( pGate->pRoot ) ) ) pGate->fExclude = 1; for ( k = 0; k < (int)pGate->nFanins; k++ ) { pFanin = pGate->pFanins[k]; if ( pFanin->fExclude ) { pGate->fExclude = 1; continue; } } } // collect the truth tables of the fanins for ( k = 0; k < (int)pGate->nFanins; k++ ) { pFanin = pGate->pFanins[k]; uTruths[k][0] = pFanin->uTruth[0]; uTruths[k][1] = pFanin->uTruth[1]; } // derive the new truth table Mio_DeriveTruthTable( pGate->pRoot, uTruths, pGate->nFanins, 6, pGate->uTruth ); // set the initial delays of the supergate for ( k = 0; k < pLib->nVarsMax; k++ ) { pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; } // get the linked list of pins for the given root gate pPin = Mio_GateReadPins( pGate->pRoot ); // update the initial delay of the supergate using info from the corresponding pin for ( k = 0; k < (int)pGate->nFanins; k++, pPin = Mio_PinReadNext(pPin) ) { // if there is no corresponding pin, this is a bug, return fail if ( pPin == NULL ) { printf( "There are less pins than gate inputs.\n" ); return 0; } // update the delay information of k-th fanins info from the corresponding pin Map_LibraryAddFaninDelays( pLib, pGate, pGate->pFanins[k], pPin ); } // if there are some pins left, this is a bug, return fail if ( pPin != NULL ) { printf( "There are more pins than gate inputs.\n" ); return 0; } // find the max delay pGate->tDelayMax.Rise = pGate->tDelayMax.Fall = MAP_NO_VAR; for ( k = 0; k < pLib->nVarsMax; k++ ) { // the rise of the output depends on the rise and fall of the output if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Rise ) pGate->tDelayMax.Rise = pGate->tDelaysR[k].Rise; if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Fall ) pGate->tDelayMax.Rise = pGate->tDelaysR[k].Fall; // the fall of the output depends on the rise and fall of the output if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Rise ) pGate->tDelayMax.Fall = pGate->tDelaysF[k].Rise; if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Fall ) pGate->tDelayMax.Fall = pGate->tDelaysF[k].Fall; pGate->tDelaysF[k].Worst = MAP_MAX( pGate->tDelaysF[k].Fall, pGate->tDelaysF[k].Rise ); pGate->tDelaysR[k].Worst = MAP_MAX( pGate->tDelaysR[k].Fall, pGate->tDelaysR[k].Rise ); } // count gates and area of the supergate pGate->nGates = 1; pGate->Area = (float)Mio_GateReadArea(pGate->pRoot); for ( k = 0; k < (int)pGate->nFanins; k++ ) { pGate->nGates += pGate->pFanins[k]->nGates; pGate->Area += pGate->pFanins[k]->Area; } // do not add the gate to the table, if this gate is an internal gate // of some supegate and does not correspond to a supergate output if ( ( !pGate->fSuper ) || pGate->fExclude ) continue; // find the maximum index of a variable in the support of the supergates // this is important for two reasons: // (1) to limit the number of permutations considered for canonicization // (2) to get rid of equivalence phases to speed-up matching nRealVars = Map_LibraryGetMaxSuperPi_rec( pGate ) + 1; assert( nRealVars > 0 && nRealVars <= pLib->nVarsMax ); // if there are some problems with this code, try this instead // nRealVars = pLib->nVarsMax; // find the N-canonical form of this supergate pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon ); // add the supergate into the table by its N-canonical table Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate ); /* { int uCanon1, uCanon2; uCanon1 = uCanon[0]; pGate->uTruth[0] = ~pGate->uTruth[0]; pGate->uTruth[1] = ~pGate->uTruth[1]; Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon ); uCanon2 = uCanon[0]; Rwt_Man5ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 ); } */ } // sort the gates in each line Map_SuperTableSortSupergatesByDelay( pLib->tTableC, pLib->nSupersAll ); // let the glory be manifest // Map_LibraryPrintTree( pLib ); return 1; } /**Function************************************************************* Synopsis [Finds the largest PI number in the support of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate ) { int i, VarCur, VarMax = 0; if ( pGate->pRoot == NULL ) return pGate->Num; for ( i = 0; i < (int)pGate->nFanins; i++ ) { VarCur = Map_LibraryGetMaxSuperPi_rec( pGate->pFanins[i] ); if ( VarMax < VarCur ) VarMax = VarCur; } return VarMax; } /**Function************************************************************* Synopsis [Finds the largest PI number in the support of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ) { unsigned uSupport; int i; if ( pGate->pRoot == NULL ) return (unsigned)(1 << (pGate->Num)); uSupport = 0; for ( i = 0; i < (int)pGate->nFanins; i++ ) uSupport |= Map_LibraryGetGateSupp_rec( pGate->pFanins[i] ); return uSupport; } /**Function************************************************************* Synopsis [Derives the pin-to-pin delay constraints for the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin ) { Mio_PinPhase_t PinPhase; float tDelayBlockRise, tDelayBlockFall, tDelayPin; int fMaxDelay = 0; int i; // use this node to enable max-delay model if ( fMaxDelay ) { float tDelayBlockMax; // get the maximum delay tDelayBlockMax = (float)Mio_PinReadDelayBlockMax(pPin); // go through the supergate inputs for ( i = 0; i < pLib->nVarsMax; i++ ) { if ( pFanin->tDelaysR[i].Rise < 0 ) continue; tDelayPin = pFanin->tDelaysR[i].Rise + tDelayBlockMax; if ( pGate->tDelaysR[i].Rise < tDelayPin ) pGate->tDelaysR[i].Rise = tDelayPin; } // go through the supergate inputs for ( i = 0; i < pLib->nVarsMax; i++ ) { if ( pFanin->tDelaysF[i].Fall < 0 ) continue; tDelayPin = pFanin->tDelaysF[i].Fall + tDelayBlockMax; if ( pGate->tDelaysF[i].Fall < tDelayPin ) pGate->tDelaysF[i].Fall = tDelayPin; } return; } // get the interesting parameters of this pin PinPhase = Mio_PinReadPhase(pPin); tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); // update the rise and fall of the output depending on the phase of the pin if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present { // the rise of the gate is determined by the rise of the fanin // the fall of the gate is determined by the fall of the fanin for ( i = 0; i < pLib->nVarsMax; i++ ) { //////////////////////////////////////////////////////// // consider the rise of the gate //////////////////////////////////////////////////////// // check two types of constraints on the rise of the fanin: // (1) the constraints related to the rise of the PIs // (2) the constraints related to the fall of the PIs if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) { // fanin's rise depends on the rise of i-th PI // update the rise of the gate's output if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockRise ) pGate->tDelaysR[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockRise; } if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) { // fanin's rise depends on the fall of i-th PI // update the rise of the gate's output if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockRise ) pGate->tDelaysR[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockRise; } //////////////////////////////////////////////////////// //////////////////////////////////////////////////////// // consider the fall of the gate (similar) //////////////////////////////////////////////////////// // check two types of constraints on the fall of the fanin: // (1) the constraints related to the rise of the PIs // (2) the constraints related to the fall of the PIs if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) { if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockFall ) pGate->tDelaysF[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockFall; } if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) { if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockFall ) pGate->tDelaysF[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockFall; } //////////////////////////////////////////////////////// } } if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present { // the rise of the gate is determined by the fall of the fanin // the fall of the gate is determined by the rise of the fanin for ( i = 0; i < pLib->nVarsMax; i++ ) { //////////////////////////////////////////////////////// // consider the rise of the gate's output //////////////////////////////////////////////////////// // check two types of constraints on the fall of the fanin: // (1) the constraints related to the rise of the PIs // (2) the constraints related to the fall of the PIs if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) { // fanin's rise depends on the rise of i-th PI // update the rise of the gate if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockRise ) pGate->tDelaysR[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockRise; } if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) { // fanin's rise depends on the fall of i-th PI // update the rise of the gate if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockRise ) pGate->tDelaysR[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockRise; } //////////////////////////////////////////////////////// //////////////////////////////////////////////////////// // consider the fall of the gate (similar) //////////////////////////////////////////////////////// // check two types of constraints on the rise of the fanin: // (1) the constraints related to the rise of the PIs // (2) the constraints related to the fall of the PIs if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) { if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockFall ) pGate->tDelaysF[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockFall; } if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) { if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockFall ) pGate->tDelaysF[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockFall; } //////////////////////////////////////////////////////// } } } /**Function************************************************************* Synopsis [Performs phase transformation for one function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Map_CalculatePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ) { int v, Shift; for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) if ( uPhase & Shift ) uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift)); return uTruth; } /**Function************************************************************* Synopsis [Performs phase transformation for one function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CalculatePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ) { unsigned uTemp; int v, Shift; // initialize the result uTruthRes[0] = uTruth[0]; uTruthRes[1] = uTruth[1]; if ( uPhase == 0 ) return; // compute the phase for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) if ( uPhase & Shift ) { if ( Shift < 32 ) { uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift)); uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift)); } else { uTemp = uTruthRes[0]; uTruthRes[0] = uTruthRes[1]; uTruthRes[1] = uTemp; } } } /**Function************************************************************* Synopsis [Prints the supergate library after deriving parameters.] Description [This procedure is very useful to see the library after it has been read into the mapper by "read_super" and all the information about the supergates derived.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_LibraryPrintTree( Map_SuperLib_t * pLib ) { Map_Super_t * pGate; int i, k; // print all the info related to the supergates // for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ ) for ( i = pLib->nVarsMax; i < 20; i++ ) { pGate = pLib->ppSupers[i]; // write the gate's fanin info and formula printf( "%6d ", pGate->Num ); printf( "%c ", pGate->fSuper? '*' : ' ' ); printf( "%6s", Mio_GateReadName(pGate->pRoot) ); for ( k = 0; k < (int)pGate->nFanins; k++ ) printf( " %6d", pGate->pFanins[k]->Num ); printf( " %s", pGate->pFormula ); printf( "\n" ); // write the gate's derived info Extra_PrintBinary( stdout, pGate->uTruth, 64 ); printf( " %3d", pGate->nGates ); printf( " %6.2f", pGate->Area ); printf( " (%4.2f, %4.2f)", pGate->tDelayMax.Rise, pGate->tDelayMax.Fall ); printf( "\n" ); for ( k = 0; k < pLib->nVarsMax; k++ ) { // print the constraint on the rise of the gate in the form (D1, D2), // where D1 is the constraint related to the rise of the k-th PI // where D2 is the constraint related to the fall of the k-th PI if ( pGate->tDelaysR[k].Rise < 0 && pGate->tDelaysR[k].Fall < 0 ) printf( " (----, ----)" ); else if ( pGate->tDelaysR[k].Fall < 0 ) printf( " (%4.2f, ----)", pGate->tDelaysR[k].Rise ); else if ( pGate->tDelaysR[k].Rise < 0 ) printf( " (----, %4.2f)", pGate->tDelaysR[k].Fall ); else printf( " (%4.2f, %4.2f)", pGate->tDelaysR[k].Rise, pGate->tDelaysR[k].Fall ); // print the constraint on the fall of the gate in the form (D1, D2), // where D1 is the constraint related to the rise of the k-th PI // where D2 is the constraint related to the fall of the k-th PI if ( pGate->tDelaysF[k].Rise < 0 && pGate->tDelaysF[k].Fall < 0 ) printf( " (----, ----)" ); else if ( pGate->tDelaysF[k].Fall < 0 ) printf( " (%4.2f, ----)", pGate->tDelaysF[k].Rise ); else if ( pGate->tDelaysF[k].Rise < 0 ) printf( " (----, %4.2f)", pGate->tDelaysF[k].Fall ); else printf( " (%4.2f, %4.2f)", pGate->tDelaysF[k].Rise, pGate->tDelaysF[k].Fall ); printf( "\n" ); } printf( "\n" ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperTruth.c000066400000000000000000000237221300674244400245620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperTruth.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperTruth.c,v 1.8 2005/01/23 06:59:45 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Map_TruthsCut( Map_Man_t * pMan, Map_Cut_t * pCut ); extern void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] ); static void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives truth tables for each cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingTruths( Map_Man_t * pMan ) { ProgressBar * pProgress; Map_Node_t * pNode; Map_Cut_t * pCut; int nNodes, i; // compute the cuts for the POs nNodes = pMan->vMapObjs->nSize; pProgress = Extra_ProgressBarStart( stdout, nNodes ); for ( i = 0; i < nNodes; i++ ) { pNode = pMan->vMapObjs->pArray[i]; if ( !Map_NodeIsAnd( pNode ) ) continue; assert( pNode->pCuts ); assert( pNode->pCuts->nLeaves == 1 ); // match the simple cut pNode->pCuts->M[0].uPhase = 0; pNode->pCuts->M[0].pSupers = pMan->pSuperLib->pSuperInv; pNode->pCuts->M[0].uPhaseBest = 0; pNode->pCuts->M[0].pSuperBest = pMan->pSuperLib->pSuperInv; pNode->pCuts->M[1].uPhase = 0; pNode->pCuts->M[1].pSupers = pMan->pSuperLib->pSuperInv; pNode->pCuts->M[1].uPhaseBest = 1; pNode->pCuts->M[1].pSuperBest = pMan->pSuperLib->pSuperInv; // match the rest of the cuts for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) Map_TruthsCut( pMan, pCut ); Extra_ProgressBarUpdate( pProgress, i, "Tables ..." ); } Extra_ProgressBarStop( pProgress ); } /**Function************************************************************* Synopsis [Derives the truth table for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut ) { // unsigned uCanon1, uCanon2; unsigned uTruth[2], uCanon[2]; unsigned char uPhases[16]; unsigned * uCanon2; char * pPhases2; int fUseFast = 1; int fUseSlow = 0; int fUseRec = 0; // this does not work for Solaris extern int Map_CanonCompute( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ); // generally speaking, 1-input cut can be matched into a wire! if ( pCut->nLeaves == 1 ) return; /* if ( p->nVarsMax == 5 ) { uTruth[0] = pCut->uTruth; uTruth[1] = pCut->uTruth; } else */ Map_TruthsCutOne( p, pCut, uTruth ); // compute the canonical form for the positive phase if ( fUseFast ) Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); else if ( fUseSlow ) Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); else if ( fUseRec ) { // Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); Extra_TruthCanonFastN( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); /* if ( uCanon[0] != uCanon2[0] || uPhases[0] != pPhases2[0] ) { int k = 0; Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); } */ uCanon[0] = uCanon2[0]; uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; uPhases[0] = pPhases2[0]; } else Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon ); pCut->M[1].uPhase = uPhases[0]; p->nCanons++; //uCanon1 = uCanon[0] & 0xFFFF; // compute the canonical form for the negative phase uTruth[0] = ~uTruth[0]; uTruth[1] = ~uTruth[1]; if ( fUseFast ) Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); else if ( fUseSlow ) Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); else if ( fUseRec ) { // Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); Extra_TruthCanonFastN( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); /* if ( uCanon[0] != uCanon2[0] || uPhases[0] != pPhases2[0] ) { int k = 0; Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); } */ uCanon[0] = uCanon2[0]; uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; uPhases[0] = pPhases2[0]; } else Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon ); pCut->M[0].uPhase = uPhases[0]; p->nCanons++; //uCanon2 = uCanon[0] & 0xFFFF; //assert( p->nVarsMax == 4 ); //Rwt_Man4ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 ); // restore the truth table uTruth[0] = ~uTruth[0]; uTruth[1] = ~uTruth[1]; } /**Function************************************************************* Synopsis [Computes the truth table of one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] ) { unsigned uTruth1[2], uTruth2[2]; Map_Cut_t * pTemp = NULL; // Suppress "might be used uninitialized" int i; // mark the cut leaves for ( i = 0; i < pCut->nLeaves; i++ ) { pTemp = pCut->ppLeaves[i]->pCuts; pTemp->fMark = 1; pTemp->M[0].uPhaseBest = p->uTruths[i][0]; pTemp->M[1].uPhaseBest = p->uTruths[i][1]; } assert( pCut->fMark == 0 ); // collect the cuts in the cut cone p->vVisited->nSize = 0; Map_CutsCollect_rec( pCut, p->vVisited ); assert( p->vVisited->nSize > 0 ); pCut->nVolume = p->vVisited->nSize; // compute the tables and unmark for ( i = 0; i < pCut->nLeaves; i++ ) { pTemp = pCut->ppLeaves[i]->pCuts; pTemp->fMark = 0; } for ( i = 0; i < p->vVisited->nSize; i++ ) { // get the cut pTemp = (Map_Cut_t *)p->vVisited->pArray[i]; pTemp->fMark = 0; // get truth table of the first branch if ( Map_CutIsComplement(pTemp->pOne) ) { uTruth1[0] = ~Map_CutRegular(pTemp->pOne)->M[0].uPhaseBest; uTruth1[1] = ~Map_CutRegular(pTemp->pOne)->M[1].uPhaseBest; } else { uTruth1[0] = Map_CutRegular(pTemp->pOne)->M[0].uPhaseBest; uTruth1[1] = Map_CutRegular(pTemp->pOne)->M[1].uPhaseBest; } // get truth table of the second branch if ( Map_CutIsComplement(pTemp->pTwo) ) { uTruth2[0] = ~Map_CutRegular(pTemp->pTwo)->M[0].uPhaseBest; uTruth2[1] = ~Map_CutRegular(pTemp->pTwo)->M[1].uPhaseBest; } else { uTruth2[0] = Map_CutRegular(pTemp->pTwo)->M[0].uPhaseBest; uTruth2[1] = Map_CutRegular(pTemp->pTwo)->M[1].uPhaseBest; } // get the truth table of the output if ( !pTemp->Phase ) { pTemp->M[0].uPhaseBest = uTruth1[0] & uTruth2[0]; pTemp->M[1].uPhaseBest = uTruth1[1] & uTruth2[1]; } else { pTemp->M[0].uPhaseBest = ~(uTruth1[0] & uTruth2[0]); pTemp->M[1].uPhaseBest = ~(uTruth1[1] & uTruth2[1]); } } uTruth[0] = pTemp->M[0].uPhaseBest; uTruth[1] = pTemp->M[1].uPhaseBest; } /**Function************************************************************* Synopsis [Recursively collect the cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited ) { if ( pCut->fMark ) return; Map_CutsCollect_rec( Map_CutRegular(pCut->pOne), vVisited ); Map_CutsCollect_rec( Map_CutRegular(pCut->pTwo), vVisited ); assert( pCut->fMark == 0 ); pCut->fMark = 1; Map_NodeVecPush( vVisited, (Map_Node_t *)pCut ); } /* { unsigned * uCanon2; char * pPhases2; Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); if ( uCanon2[0] != uCanon[0] ) { int v = 0; Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); } // else // { // printf( "Correct.\n" ); // } } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperUtils.c000066400000000000000000000635661300674244400245660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperUtils.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperUtils.c,v 1.8 2004/11/03 22:41:45 satrajit Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define MAP_CO_LIST_SIZE 5 static int Map_MappingCountLevels_rec( Map_Node_t * pNode ); static float Map_MappingSetRefsAndArea_rec( Map_Man_t * pMan, Map_Node_t * pNode ); static float Map_MappingSetRefsAndSwitch_rec( Map_Man_t * pMan, Map_Node_t * pNode ); static float Map_MappingSetRefsAndWire_rec( Map_Man_t * pMan, Map_Node_t * pNode ); static void Map_MappingDfsCuts_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes ); static float Map_MappingArea_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_NodeVec_t * vNodes ); static int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 ); static void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax ); static unsigned Map_MappingExpandTruth_rec( unsigned uTruth, int nVars ); static int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv ) { assert( !Map_IsComplement(pNode) ); if ( pNode->fMark0 ) return; // visit the transitive fanin if ( Map_NodeIsAnd(pNode) ) { Map_MappingDfs_rec( Map_Regular(pNode->p1), vNodes, fCollectEquiv ); Map_MappingDfs_rec( Map_Regular(pNode->p2), vNodes, fCollectEquiv ); } // visit the equivalent nodes if ( fCollectEquiv && pNode->pNextE ) Map_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv ); // make sure the node is not visited through the equivalent nodes assert( pNode->fMark0 == 0 ); // mark the node as visited pNode->fMark0 = 1; // add the node to the list Map_NodeVecPush( vNodes, pNode ); } Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv ) { Map_NodeVec_t * vNodes; int i; // perform the traversal vNodes = Map_NodeVecAlloc( 100 ); for ( i = 0; i < pMan->nOutputs; i++ ) Map_MappingDfs_rec( Map_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv ); for ( i = 0; i < vNodes->nSize; i++ ) vNodes->pArray[i]->fMark0 = 0; // for ( i = 0; i < pMan->nOutputs; i++ ) // Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); return vNodes; } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [] SideEffects [Note that this procedure will reassign the levels assigned originally by NodeCreate() because it counts the number of levels with choices differently!] SeeAlso [] ***********************************************************************/ int Map_MappingCountLevels( Map_Man_t * pMan ) { int i, LevelsMax, LevelsCur; // perform the traversal LevelsMax = -1; for ( i = 0; i < pMan->nOutputs; i++ ) { LevelsCur = Map_MappingCountLevels_rec( Map_Regular(pMan->pOutputs[i]) ); if ( LevelsMax < LevelsCur ) LevelsMax = LevelsCur; } for ( i = 0; i < pMan->nOutputs; i++ ) Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); return LevelsMax; } /**Function************************************************************* Synopsis [Recursively computes the number of logic levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingCountLevels_rec( Map_Node_t * pNode ) { int Level1, Level2; assert( !Map_IsComplement(pNode) ); if ( !Map_NodeIsAnd(pNode) ) { pNode->Level = 0; return 0; } if ( pNode->fMark0 ) return pNode->Level; pNode->fMark0 = 1; // visit the transitive fanin Level1 = Map_MappingCountLevels_rec( Map_Regular(pNode->p1) ); Level2 = Map_MappingCountLevels_rec( Map_Regular(pNode->p2) ); // set the number of levels pNode->Level = 1 + ((Level1>Level2)? Level1: Level2); return pNode->Level; } /**Function************************************************************* Synopsis [Unmarks the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingUnmark( Map_Man_t * pMan ) { int i; for ( i = 0; i < pMan->nOutputs; i++ ) Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); } /**Function************************************************************* Synopsis [Recursively unmarks the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingUnmark_rec( Map_Node_t * pNode ) { assert( !Map_IsComplement(pNode) ); if ( pNode->fMark0 == 0 ) return; pNode->fMark0 = 0; if ( !Map_NodeIsAnd(pNode) ) return; Map_MappingUnmark_rec( Map_Regular(pNode->p1) ); Map_MappingUnmark_rec( Map_Regular(pNode->p2) ); // visit the equivalent nodes if ( pNode->pNextE ) Map_MappingUnmark_rec( pNode->pNextE ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingMark_rec( Map_Node_t * pNode ) { assert( !Map_IsComplement(pNode) ); if ( pNode->fMark0 == 1 ) return; pNode->fMark0 = 1; if ( !Map_NodeIsAnd(pNode) ) return; // visit the transitive fanin of the selected cut Map_MappingMark_rec( Map_Regular(pNode->p1) ); Map_MappingMark_rec( Map_Regular(pNode->p2) ); } /**Function************************************************************* Synopsis [Compares the outputs by their arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 ) { Map_Node_t * pNode1 = Map_Regular(*ppNode1); Map_Node_t * pNode2 = Map_Regular(*ppNode2); int fPhase1 = !Map_IsComplement(*ppNode1); int fPhase2 = !Map_IsComplement(*ppNode2); float Arrival1 = pNode1->tArrival[fPhase1].Worst; float Arrival2 = pNode2->tArrival[fPhase2].Worst; if ( Arrival1 < Arrival2 ) return -1; if ( Arrival1 > Arrival2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Finds given number of latest arriving COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax ) { int nNodes, i, k, v; assert( p->nOutputs >= nNodesMax ); pNodes[0] = 0; nNodes = 1; for ( i = 1; i < p->nOutputs; i++ ) { for ( k = nNodes - 1; k >= 0; k-- ) if ( Map_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 ) break; if ( k == nNodesMax - 1 ) continue; if ( nNodes < nNodesMax ) nNodes++; for ( v = nNodes - 1; v > k+1; v-- ) pNodes[v] = pNodes[v-1]; pNodes[k+1] = i; } } /**Function************************************************************* Synopsis [Prints a bunch of latest arriving outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingPrintOutputArrivals( Map_Man_t * p ) { int pSorted[MAP_CO_LIST_SIZE]; Map_Time_t * pTimes; Map_Node_t * pNode; int fPhase, Limit, i; int MaxNameSize; // determine the number of nodes to print Limit = (p->nOutputs > MAP_CO_LIST_SIZE)? MAP_CO_LIST_SIZE : p->nOutputs; // determine the order Map_MappingFindLatest( p, pSorted, Limit ); // determine max size of the node's name MaxNameSize = 0; for ( i = 0; i < Limit; i++ ) if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) ) MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]); // print the latest outputs for ( i = 0; i < Limit; i++ ) { // get the i-th latest output pNode = Map_Regular(p->pOutputs[pSorted[i]]); fPhase =!Map_IsComplement(p->pOutputs[pSorted[i]]); pTimes = pNode->tArrival + fPhase; // print out the best arrival time printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] ); printf( "Delay = (%5.2f, %5.2f) ", (double)pTimes->Rise, (double)pTimes->Fall ); printf( "%s", fPhase? "POS" : "NEG" ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Sets up the truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingSetupTruthTables( unsigned uTruths[][2] ) { int m, v; // set up the truth tables for ( m = 0; m < 32; m++ ) for ( v = 0; v < 5; v++ ) if ( m & (1 << v) ) uTruths[v][0] |= (1 << m); // make adjustments for the case of 6 variables for ( v = 0; v < 5; v++ ) uTruths[v][1] = uTruths[v][0]; uTruths[5][0] = 0; uTruths[5][1] = MAP_FULL; } /**Function************************************************************* Synopsis [Sets up the truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] ) { int m, v; // clean everything for ( m = 0; m < 32; m++ ) for ( v = 0; v < 10; v++ ) uTruths[v][m] = 0; // set up the truth tables for ( m = 0; m < 32; m++ ) for ( v = 0; v < 5; v++ ) if ( m & (1 << v) ) { uTruths[v][0] |= (1 << m); uTruths[v+5][m] = MAP_FULL; } // extend this info for the rest of the first 5 variables for ( m = 0; m < 32; m++ ) for ( v = 0; v < 5; v++ ) uTruths[v][m] = uTruths[v][0]; /* // verify for ( m = 0; m < 1024; m++, printf("\n") ) for ( v = 0; v < 10; v++ ) if ( Map_InfoReadVar( uTruths[v], m ) ) printf( "1" ); else printf( "0" ); */ } /**Function************************************************************* Synopsis [Sets up the mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingSetupMask( unsigned uMask[], int nVarsMax ) { if ( nVarsMax == 6 ) uMask[0] = uMask[1] = MAP_FULL; else { uMask[0] = MAP_MASK(1 << nVarsMax); uMask[1] = 0; } } /**Function************************************************************* Synopsis [Verify one useful property.] Description [This procedure verifies one useful property. After the FRAIG construction with choice nodes is over, each primary node should have fanins that are primary nodes. The primary nodes is the one that does not have pNode->pRepr set to point to another node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_ManCheckConsistency( Map_Man_t * p ) { Map_Node_t * pNode; Map_NodeVec_t * pVec; int i; pVec = Map_MappingDfs( p, 0 ); for ( i = 0; i < pVec->nSize; i++ ) { pNode = pVec->pArray[i]; if ( Map_NodeIsVar(pNode) ) { if ( pNode->pRepr ) printf( "Primary input %d is a secondary node.\n", pNode->Num ); } else if ( Map_NodeIsConst(pNode) ) { if ( pNode->pRepr ) printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); } else { if ( pNode->pRepr ) printf( "Internal node %d is a secondary node.\n", pNode->Num ); if ( Map_Regular(pNode->p1)->pRepr ) printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num ); if ( Map_Regular(pNode->p2)->pRepr ) printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num ); } } Map_NodeVecFree( pVec ); return 1; } /**Function************************************************************* Synopsis [Returns 1 if current mapping of the node violates fanout limits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol ) { return pNode->nRefAct[fPosPol] > (int)pCut->M[fPosPol].pSuperBest->nFanLimit; } /**Function************************************************************* Synopsis [Computes the total are flow of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_MappingGetAreaFlow( Map_Man_t * p ) { Map_Node_t * pNode; Map_Cut_t * pCut; float aFlowFlowTotal = 0; int fPosPol, i; for ( i = 0; i < p->nOutputs; i++ ) { pNode = Map_Regular(p->pOutputs[i]); if ( !Map_NodeIsAnd(pNode) ) continue; fPosPol = !Map_IsComplement(p->pOutputs[i]); pCut = pNode->pCutBest[fPosPol]; if ( pCut == NULL ) { fPosPol = !fPosPol; pCut = pNode->pCutBest[fPosPol]; } aFlowFlowTotal += pNode->pCutBest[fPosPol]->M[fPosPol].AreaFlow; } return aFlowFlowTotal; } /**Function************************************************************* Synopsis [Compares the supergates by their level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CompareNodesByLevel( Map_Node_t ** ppS1, Map_Node_t ** ppS2 ) { Map_Node_t * pN1 = Map_Regular(*ppS1); Map_Node_t * pN2 = Map_Regular(*ppS2); if ( pN1->Level > pN2->Level ) return -1; if ( pN1->Level < pN2->Level ) return 1; return 0; } /**Function************************************************************* Synopsis [Orders the nodes in the decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes ) { qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Map_Node_t *), (int (*)(const void *, const void *)) Map_CompareNodesByLevel ); // assert( Map_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 ); } /**Function************************************************************* Synopsis [Compares the supergates by their pointer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_CompareNodesByPointer( Map_Node_t ** ppS1, Map_Node_t ** ppS2 ) { if ( *ppS1 < *ppS2 ) return -1; if ( *ppS1 > *ppS2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Counts how many AIG nodes are mapped in both polarities.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes ) { Map_Node_t * pNode; int Counter, i; // count the number of equal adjacent nodes Counter = 0; for ( i = 0; i < vNodes->nSize; i++ ) { pNode = vNodes->pArray[i]; if ( !Map_NodeIsAnd(pNode) ) continue; if ( (pNode->nRefAct[0] && pNode->pCutBest[0]) && (pNode->nRefAct[1] && pNode->pCutBest[1]) ) Counter++; } return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ st__table * Map_CreateTableGate2Super( Map_Man_t * pMan ) { Map_Super_t * pSuper; st__table * tTable; int i, nInputs, v; tTable = st__init_table(strcmp, st__strhash); for ( i = 0; i < pMan->pSuperLib->nSupersAll; i++ ) { pSuper = pMan->pSuperLib->ppSupers[i]; if ( pSuper->nGates == 1 ) { // skip different versions of the same root gate nInputs = Mio_GateReadPinNum(pSuper->pRoot); for ( v = 0; v < nInputs; v++ ) if ( pSuper->pFanins[v]->Num != nInputs - 1 - v ) break; if ( v != nInputs ) continue; // printf( "%s\n", Mio_GateReadName(pSuper->pRoot) ); if ( st__insert( tTable, (char *)pSuper->pRoot, (char *)pSuper ) ) { assert( 0 ); } } } return tTable; } /**Function************************************************************* Synopsis [Get the FRAIG node with phase.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_ManCleanData( Map_Man_t * p ) { int i; for ( i = 0; i < p->vMapObjs->nSize; i++ ) p->vMapObjs->pArray[i]->pData0 = p->vMapObjs->pArray[i]->pData1 = 0; } /**Function************************************************************* Synopsis [Expand the truth table] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingExpandTruth( unsigned uTruth[2], int nVars ) { assert( nVars < 7 ); if ( nVars == 6 ) return; if ( nVars < 5 ) { uTruth[0] &= MAP_MASK( (1<vMapObjs->nSize; i++ ) { // skip primary inputs pNode = p->vMapObjs->pArray[i]; if ( !Map_NodeIsAnd( pNode ) ) continue; // skip a secondary node if ( pNode->pRepr ) continue; // count the switching nodes if ( pNode->nRefAct[0] > 0 ) Map_TimeCutComputeArrival( pNode, pNode->pCutBest[0], 0, MAP_FLOAT_LARGE ); if ( pNode->nRefAct[1] > 0 ) Map_TimeCutComputeArrival( pNode, pNode->pCutBest[1], 1, MAP_FLOAT_LARGE ); } Result = Map_TimeComputeArrivalMax(p); printf( "Max arrival times with fanouts = %10.2f.\n", Result ); return Result; } /**Function************************************************************* Synopsis [Sets up the mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingGetMaxLevel( Map_Man_t * pMan ) { int nLevelMax, i; nLevelMax = 0; for ( i = 0; i < pMan->nOutputs; i++ ) nLevelMax = ((unsigned)nLevelMax) > Map_Regular(pMan->pOutputs[i])->Level? nLevelMax : Map_Regular(pMan->pOutputs[i])->Level; return nLevelMax; } /**Function************************************************************* Synopsis [Analyses choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingUpdateLevel_rec( Map_Man_t * pMan, Map_Node_t * pNode, int fMaximum ) { Map_Node_t * pTemp; int Level1, Level2, LevelE; assert( !Map_IsComplement(pNode) ); if ( !Map_NodeIsAnd(pNode) ) return pNode->Level; // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return pNode->Level; pNode->TravId = pMan->nTravIds; // compute levels of the children nodes Level1 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p1), fMaximum ); Level2 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p2), fMaximum ); pNode->Level = 1 + MAP_MAX( Level1, Level2 ); if ( pNode->pNextE ) { LevelE = Map_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); if ( fMaximum ) { if ( pNode->Level < (unsigned)LevelE ) pNode->Level = LevelE; } else { if ( pNode->Level > (unsigned)LevelE ) pNode->Level = LevelE; } // set the level of all equivalent nodes to be the same minimum if ( pNode->pRepr == NULL ) // the primary node for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) pTemp->Level = pNode->Level; } return pNode->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 [] ***********************************************************************/ void Map_MappingSetChoiceLevels( Map_Man_t * pMan ) { int i; pMan->nTravIds++; for ( i = 0; i < pMan->nOutputs; i++ ) Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 ); } /**Function************************************************************* Synopsis [Reports statistics on choice nodes.] Description [The number of choice nodes is the number of primary nodes, which has pNextE set to a pointer. The number of choices is the number of entries in the equivalent-node lists of the primary nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingReportChoices( Map_Man_t * pMan ) { Map_Node_t * pNode, * pTemp; int nChoiceNodes, nChoices; int i, LevelMax1, LevelMax2; // report the number of levels LevelMax1 = Map_MappingGetMaxLevel( pMan ); pMan->nTravIds++; for ( i = 0; i < pMan->nOutputs; i++ ) Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 ); LevelMax2 = Map_MappingGetMaxLevel( pMan ); // report statistics about choices nChoiceNodes = nChoices = 0; for ( i = 0; i < pMan->vMapObjs->nSize; i++ ) { pNode = pMan->vMapObjs->pArray[i]; if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) { // this is a choice node = the primary node that has equivalent nodes nChoiceNodes++; for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) nChoices++; } } printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); } /**Function************************************************************* Synopsis [Computes the maximum and minimum levels of the choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices ) { Map_NodeVec_t * vNodes; int Result; vNodes = Map_MappingDfs( pMan, fChoices ); Result = vNodes->nSize; Map_NodeVecFree( vNodes ); return Result; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/mapperVec.c000066400000000000000000000201321300674244400241610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mapperVec.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - June 1, 2004.] Revision [$Id: mapperVec.c,v 1.3 2005/01/23 06:59:45 alanmi Exp $] ***********************************************************************/ #include "mapperInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_NodeVec_t * Map_NodeVecAlloc( int nCap ) { Map_NodeVec_t * p; p = ABC_ALLOC( Map_NodeVec_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( Map_Node_t *, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeVecFree( Map_NodeVec_t * p ) { if ( p == NULL ) return; ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_NodeVec_t * Map_NodeVecDup( Map_NodeVec_t * p ) { Map_NodeVec_t * pNew = Map_NodeVecAlloc( p->nSize ); memcpy( pNew->pArray, p->pArray, sizeof(int) * p->nSize ); pNew->nSize = p->nSize; return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p ) { return p->pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeVecReadSize( Map_NodeVec_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( Map_Node_t *, p->pArray, nCapMin ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeVecClear( Map_NodeVec_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Map_NodeVecGrow( p, 16 ); else Map_NodeVecGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } /**Function************************************************************* Synopsis [Add the element while ensuring uniqueness.] Description [Returns 1 if the element was found, and 0 if it was new. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Map_NodeVecPush( p, Entry ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p ) { return p->pArray[--p->nSize]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) break; assert( i < p->nSize ); for ( i++; i < p->nSize; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeVecSortByLevel( Map_NodeVec_t * p ) { qsort( (void *)p->pArray, p->nSize, sizeof(Map_Node_t *), (int (*)(const void *, const void *)) Map_NodeVecCompareLevels ); } /**Function************************************************************* Synopsis [Comparison procedure for two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 ) { int Level1 = Map_Regular(*pp1)->Level; int Level2 = Map_Regular(*pp2)->Level; if ( Level1 < Level2 ) return -1; if ( Level1 > Level2 ) return 1; if ( Map_Regular(*pp1)->Num < Map_Regular(*pp2)->Num ) return -1; if ( Map_Regular(*pp1)->Num > Map_Regular(*pp2)->Num ) return 1; return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mapper/module.make000066400000000000000000000010331300674244400242160ustar00rootroot00000000000000SRC += src/map/mapper/mapper.c \ src/map/mapper/mapperCanon.c \ src/map/mapper/mapperCore.c \ src/map/mapper/mapperCreate.c \ src/map/mapper/mapperCut.c \ src/map/mapper/mapperCutUtils.c \ src/map/mapper/mapperLib.c \ src/map/mapper/mapperMatch.c \ src/map/mapper/mapperRefs.c \ src/map/mapper/mapperSuper.c \ src/map/mapper/mapperSwitch.c \ src/map/mapper/mapperTable.c \ src/map/mapper/mapperTime.c \ src/map/mapper/mapperTree.c \ src/map/mapper/mapperTruth.c \ src/map/mapper/mapperUtils.c \ src/map/mapper/mapperVec.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/000077500000000000000000000000001300674244400213755ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/exp.h000066400000000000000000000312241300674244400223440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [exp.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Boolean expression.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: exp.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__mio__exp_h #define ABC__map__mio__exp_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define EXP_CONST0 -1 #define EXP_CONST1 -2 static inline Vec_Int_t * Exp_Const0() { Vec_Int_t * vExp; vExp = Vec_IntAlloc( 1 ); Vec_IntPush( vExp, EXP_CONST0 ); return vExp; } static inline Vec_Int_t * Exp_Const1() { Vec_Int_t * vExp; vExp = Vec_IntAlloc( 1 ); Vec_IntPush( vExp, EXP_CONST1 ); return vExp; } static inline int Exp_IsConst( Vec_Int_t * p ) { return Vec_IntEntry(p,0) == EXP_CONST0 || Vec_IntEntry(p,0) == EXP_CONST1; } static inline int Exp_IsConst0( Vec_Int_t * p ) { return Vec_IntEntry(p,0) == EXP_CONST0; } static inline int Exp_IsConst1( Vec_Int_t * p ) { return Vec_IntEntry(p,0) == EXP_CONST1; } static inline Vec_Int_t * Exp_Var( int iVar ) { Vec_Int_t * vExp; vExp = Vec_IntAlloc( 1 ); Vec_IntPush( vExp, 2 * iVar ); return vExp; } static inline int Exp_LitShift( int nVars, int Lit, int Shift ) { if ( Lit < 2 * nVars ) return Lit; return Lit + 2 * Shift; } static inline int Exp_IsLit( Vec_Int_t * p ) { return Vec_IntSize(p) == 1 && !Exp_IsConst(p); } static inline int Exp_NodeNum( Vec_Int_t * p ) { return Vec_IntSize(p)/2; } static inline Vec_Int_t * Exp_Not( Vec_Int_t * p ) { Vec_IntWriteEntry( p, 0, Vec_IntEntry(p,0) ^ 1 ); return p; } static inline void Exp_PrintLit( int nVars, int Lit ) { if ( Lit == EXP_CONST0 ) Abc_Print( 1, "Const0" ); else if ( Lit == EXP_CONST1 ) Abc_Print( 1, "Const1" ); else if ( Lit < 2 * nVars ) Abc_Print( 1, "%s%c", (Lit&1) ? "!" : " ", 'a' + Lit/2 ); else Abc_Print( 1, "%s%d", (Lit&1) ? "!" : " ", Lit/2 ); } static inline void Exp_Print( int nVars, Vec_Int_t * p ) { int i; for ( i = 0; i < Exp_NodeNum(p); i++ ) { Abc_Print( 1, "%2d = ", nVars + i ); Exp_PrintLit( nVars, Vec_IntEntry(p, 2*i+0) ); Abc_Print( 1, " & " ); Exp_PrintLit( nVars, Vec_IntEntry(p, 2*i+1) ); Abc_Print( 1, "\n" ); } Abc_Print( 1, " F = " ); Exp_PrintLit( nVars, Vec_IntEntryLast(p) ); Abc_Print( 1, "\n" ); } static inline Vec_Int_t * Exp_Reverse( Vec_Int_t * p ) { Vec_IntReverseOrder( p ); return p; } static inline void Exp_PrintReverse( int nVars, Vec_Int_t * p ) { Exp_Reverse( p ); Exp_Print( nVars, p ); Exp_Reverse( p ); } static inline Vec_Int_t * Exp_And( int * pMan, int nVars, Vec_Int_t * p0, Vec_Int_t * p1, int fCompl0, int fCompl1 ) { int i, Len0 = Vec_IntSize(p0), Len1 = Vec_IntSize(p1); Vec_Int_t * r = Vec_IntAlloc( Len0 + Len1 + 1 ); assert( (Len0 & 1) && (Len1 & 1) ); Vec_IntPush( r, 2 * (nVars + Len0/2 + Len1/2) ); Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, 0) ^ fCompl0, Len1/2 ) ); Vec_IntPush( r, Vec_IntEntry(p1, 0) ^ fCompl1 ); for ( i = 1; i < Len0; i++ ) Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, i), Len1/2 ) ); for ( i = 1; i < Len1; i++ ) Vec_IntPush( r, Vec_IntEntry(p1, i) ); assert( Vec_IntSize(r) == Len0 + Len1 + 1 ); return r; } static inline Vec_Int_t * Exp_Or( int * pMan, int nVars, Vec_Int_t * p0, Vec_Int_t * p1 ) { return Exp_Not( Exp_And(pMan, nVars, p0, p1, 1, 1) ); } static inline Vec_Int_t * Exp_Xor( int * pMan, int nVars, Vec_Int_t * p0, Vec_Int_t * p1 ) { int i, Len0 = Vec_IntSize(p0), Len1 = Vec_IntSize(p1); Vec_Int_t * r = Vec_IntAlloc( Len0 + Len1 + 5 ); assert( (Len0 & 1) && (Len1 & 1) ); Vec_IntPush( r, 2 * (nVars + Len0/2 + Len1/2 + 2) ); Vec_IntPush( r, 2 * (nVars + Len0/2 + Len1/2 + 1) + 1 ); Vec_IntPush( r, 2 * (nVars + Len0/2 + Len1/2 + 0) + 1 ); Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, 0) ^ 1, Len1/2 ) ); Vec_IntPush( r, Vec_IntEntry(p1, 0) ); Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, 0), Len1/2 ) ); Vec_IntPush( r, Vec_IntEntry(p1, 0) ^ 1 ); for ( i = 1; i < Len0; i++ ) Vec_IntPush( r, Exp_LitShift( nVars, Vec_IntEntry(p0, i), Len1/2 ) ); for ( i = 1; i < Len1; i++ ) Vec_IntPush( r, Vec_IntEntry(p1, i) ); assert( Vec_IntSize(r) == Len0 + Len1 + 5 ); return Exp_Not( r ); } static inline word Exp_Truth6Lit( int nVars, int Lit, word * puFanins, word * puNodes ) { if ( Lit == EXP_CONST0 ) return 0; if ( Lit == EXP_CONST1 ) return ~(word)0; if ( Lit < 2 * nVars ) return (Lit&1) ? ~puFanins[Lit/2] : puFanins[Lit/2]; return (Lit&1) ? ~puNodes[Lit/2-nVars] : puNodes[Lit/2-nVars]; } static inline word Exp_Truth6( int nVars, Vec_Int_t * p, word * puFanins ) { static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; word * puNodes, Res; int i; if ( puFanins == NULL ) puFanins = (word *)Truth6; puNodes = ABC_CALLOC( word, Exp_NodeNum(p) ); for ( i = 0; i < Exp_NodeNum(p); i++ ) puNodes[i] = Exp_Truth6Lit( nVars, Vec_IntEntry(p, 2*i+0), puFanins, puNodes ) & Exp_Truth6Lit( nVars, Vec_IntEntry(p, 2*i+1), puFanins, puNodes ); Res = Exp_Truth6Lit( nVars, Vec_IntEntryLast(p), puFanins, puNodes ); ABC_FREE( puNodes ); return Res; } static inline void Exp_Truth8( int nVars, Vec_Int_t * p, word ** puFanins, word * puRes ) { word Truth8[8][4] = { { ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA) }, { ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC) }, { ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0) }, { ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00) }, { ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000) }, { ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000) }, { ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF) }, { ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF) } }; word * puFaninsInt[8], * pStore, * pThis = NULL; int i, k, iRoot = Vec_IntEntryLast(p); if ( puFanins == NULL ) { puFanins = puFaninsInt; for ( k = 0; k < 8; k++ ) puFanins[k] = Truth8[k]; } if ( Exp_NodeNum(p) == 0 ) { assert( iRoot < 2 * nVars ); if ( iRoot == EXP_CONST0 || iRoot == EXP_CONST1 ) for ( k = 0; k < 4; k++ ) puRes[k] = iRoot == EXP_CONST0 ? 0 : ~(word)0; else for ( k = 0; k < 4; k++ ) puRes[k] = Abc_LitIsCompl(iRoot) ? ~puFanins[Abc_Lit2Var(iRoot)][k] : puFanins[Abc_Lit2Var(iRoot)][k]; return; } pStore = ABC_CALLOC( word, 4 * Exp_NodeNum(p) ); for ( i = 0; i < Exp_NodeNum(p); i++ ) { int iVar0 = Abc_Lit2Var( Vec_IntEntry(p, 2*i+0) ); int iVar1 = Abc_Lit2Var( Vec_IntEntry(p, 2*i+1) ); int fCompl0 = Abc_LitIsCompl( Vec_IntEntry(p, 2*i+0) ); int fCompl1 = Abc_LitIsCompl( Vec_IntEntry(p, 2*i+1) ); word * pIn0 = iVar0 < nVars ? puFanins[iVar0] : pStore + 4 * (iVar0 - nVars); word * pIn1 = iVar1 < nVars ? puFanins[iVar1] : pStore + 4 * (iVar1 - nVars); pThis = pStore + 4 * i; if ( fCompl0 && fCompl1 ) for ( k = 0; k < 4; k++ ) pThis[k] = ~pIn0[k] & ~pIn1[k]; else if ( fCompl0 && !fCompl1 ) for ( k = 0; k < 4; k++ ) pThis[k] = ~pIn0[k] & pIn1[k]; else if ( !fCompl0 && fCompl1 ) for ( k = 0; k < 4; k++ ) pThis[k] = pIn0[k] & ~pIn1[k]; else //if ( !fCompl0 && !fCompl1 ) for ( k = 0; k < 4; k++ ) pThis[k] = pIn0[k] & pIn1[k]; } assert( Abc_Lit2Var(iRoot) - nVars == i - 1 ); for ( k = 0; k < 4; k++ ) puRes[k] = Abc_LitIsCompl(iRoot) ? ~pThis[k] : pThis[k]; ABC_FREE( pStore ); } static inline void Exp_TruthLit( int nVars, int Lit, word ** puFanins, word ** puNodes, word * pRes, int nWords ) { int w; if ( Lit == EXP_CONST0 ) for ( w = 0; w < nWords; w++ ) pRes[w] = 0; else if ( Lit == EXP_CONST1 ) for ( w = 0; w < nWords; w++ ) pRes[w] = ~(word)0; else if ( Lit < 2 * nVars ) for ( w = 0; w < nWords; w++ ) pRes[w] = (Lit&1) ? ~puFanins[Lit/2][w] : puFanins[Lit/2][w]; else for ( w = 0; w < nWords; w++ ) pRes[w] = (Lit&1) ? ~puNodes[Lit/2-nVars][w] : puNodes[Lit/2-nVars][w]; } static inline void Exp_Truth( int nVars, Vec_Int_t * p, word * pRes ) { static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; word ** puFanins, ** puNodes, * pTemp0, * pTemp1; int i, w, nWords = (nVars <= 6 ? 1 : 1 << (nVars-6)); // create elementary variables puFanins = ABC_ALLOC( word *, nVars ); for ( i = 0; i < nVars; i++ ) puFanins[i] = ABC_ALLOC( word, nWords ); // assign elementary truth tables for ( i = 0; i < nVars; i++ ) if ( i < 6 ) for ( w = 0; w < nWords; w++ ) puFanins[i][w] = Truth6[i]; else for ( w = 0; w < nWords; w++ ) puFanins[i][w] = (w & (1 << (i-6))) ? ~(word)0 : 0; // create intermediate nodes puNodes = ABC_ALLOC( word *, Exp_NodeNum(p) ); for ( i = 0; i < Exp_NodeNum(p); i++ ) puNodes[i] = ABC_ALLOC( word, nWords ); // evaluate the expression pTemp0 = ABC_ALLOC( word, nWords ); pTemp1 = ABC_ALLOC( word, nWords ); for ( i = 0; i < Exp_NodeNum(p); i++ ) { Exp_TruthLit( nVars, Vec_IntEntry(p, 2*i+0), puFanins, puNodes, pTemp0, nWords ); Exp_TruthLit( nVars, Vec_IntEntry(p, 2*i+1), puFanins, puNodes, pTemp1, nWords ); for ( w = 0; w < nWords; w++ ) puNodes[i][w] = pTemp0[w] & pTemp1[w]; } ABC_FREE( pTemp0 ); ABC_FREE( pTemp1 ); // copy the final result Exp_TruthLit( nVars, Vec_IntEntryLast(p), puFanins, puNodes, pRes, nWords ); // cleanup for ( i = 0; i < nVars; i++ ) ABC_FREE( puFanins[i] ); ABC_FREE( puFanins ); for ( i = 0; i < Exp_NodeNum(p); i++ ) ABC_FREE( puNodes[i] ); ABC_FREE( puNodes ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mio.c000066400000000000000000000554651300674244400223440ustar00rootroot00000000000000/**CFile**************************************************************** pFileName [mio.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [File reading/writing for technology mapping.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 18, 2003.] Revision [$Id: mio.c,v 1.4 2004/08/05 18:34:51 satrajit Exp $] ***********************************************************************/ #define _BSD_SOURCE #ifndef WIN32 #include #endif #include "base/main/main.h" #include "mio.h" #include "map/mapper/mapper.h" #include "map/amap/amap.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Mio_CommandReadLiberty( Abc_Frame_t * pAbc, int argc, char **argv ); static int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv ); static int Mio_CommandWriteGenlib( Abc_Frame_t * pAbc, int argc, char **argv ); static int Mio_CommandPrintGenlib( Abc_Frame_t * pAbc, int argc, char **argv ); static int Mio_CommandReadProfile( Abc_Frame_t * pAbc, int argc, char **argv ); static int Mio_CommandWriteProfile( Abc_Frame_t * pAbc, int argc, char **argv ); static int Mio_CommandPrintProfile( Abc_Frame_t * pAbc, int argc, char **argv ); /* // internal version of genlib library static char * pMcncGenlib[25] = { "GATE inv1 1 O=!a; PIN * INV 1 999 0.9 0.0 0.9 0.0\n", "GATE inv2 2 O=!a; PIN * INV 2 999 1.0 0.0 1.0 0.0\n", "GATE inv3 3 O=!a; PIN * INV 3 999 1.1 0.0 1.1 0.0\n", "GATE inv4 4 O=!a; PIN * INV 4 999 1.2 0.0 1.2 0.0\n", "GATE nand2 2 O=!(a*b); PIN * INV 1 999 1.0 0.0 1.0 0.0\n", "GATE nand3 3 O=!(a*b*c); PIN * INV 1 999 1.1 0.0 1.1 0.0\n", "GATE nand4 4 O=!(a*b*c*d); PIN * INV 1 999 1.4 0.0 1.4 0.0\n", "GATE nor2 2 O=!(a+b); PIN * INV 1 999 1.4 0.0 1.4 0.0\n", "GATE nor3 3 O=!(a+b+c); PIN * INV 1 999 2.4 0.0 2.4 0.0\n", "GATE nor4 4 O=!(a+b+c+d); PIN * INV 1 999 3.8 0.0 3.8 0.0\n", "GATE xora 5 O=a*!b+!a*b; PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n", "GATE xorb 5 O=!(a*b+!a*!b); PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n", "GATE xnora 5 O=a*b+!a*!b; PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n", "GATE xnorb 5 O=!(!a*b+a*!b); PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n", "GATE aoi21 3 O=!(a*b+c); PIN * INV 1 999 1.6 0.0 1.6 0.0\n", "GATE aoi22 4 O=!(a*b+c*d); PIN * INV 1 999 2.0 0.0 2.0 0.0\n", "GATE oai21 3 O=!((a+b)*c); PIN * INV 1 999 1.6 0.0 1.6 0.0\n", "GATE oai22 4 O=!((a+b)*(c+d)); PIN * INV 1 999 2.0 0.0 2.0 0.0\n", "GATE buf 1 O=a; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", "GATE zero 0 O=CONST0;\n", "GATE one 0 O=CONST1;\n" }; */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_Init( Abc_Frame_t * pAbc ) { // Cmd_CommandAdd( pAbc, "SC mapping", "read_liberty", Mio_CommandReadLiberty, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "read_genlib", Mio_CommandReadGenlib, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "write_genlib", Mio_CommandWriteGenlib, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "print_genlib", Mio_CommandPrintGenlib, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "read_profile", Mio_CommandReadProfile, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "write_profile", Mio_CommandWriteProfile, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "print_profile", Mio_CommandPrintProfile, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "read_library", Mio_CommandReadGenlib, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "write_library", Mio_CommandWriteGenlib, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "print_library", Mio_CommandPrintGenlib, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_End( Abc_Frame_t * pAbc ) { Mio_LibraryDelete( (Mio_Library_t *)Abc_FrameReadLibGen() ); Amap_LibFree( (Amap_Lib_t *)Abc_FrameReadLibGen2() ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_UpdateGenlib( Mio_Library_t * pLib ) { // free the current superlib because it depends on the old Mio library if ( Abc_FrameReadLibSuper() ) { Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() ); Abc_FrameSetLibSuper( NULL ); } // replace the current library Mio_LibraryDelete( (Mio_Library_t *)Abc_FrameReadLibGen() ); Abc_FrameSetLibGen( pLib ); // replace the current library Amap_LibFree( (Amap_Lib_t *)Abc_FrameReadLibGen2() ); Abc_FrameSetLibGen2( NULL ); } int Mio_UpdateGenlib2( Vec_Str_t * vStr, Vec_Str_t * vStr2, char * pFileName, int fVerbose ) { Mio_Library_t * pLib; // set the new network pLib = Mio_LibraryRead( pFileName, Vec_StrArray(vStr), NULL, fVerbose ); if ( pLib == NULL ) return 0; // free the current superlib because it depends on the old Mio library if ( Abc_FrameReadLibSuper() ) { Map_SuperLibFree( (Map_SuperLib_t *)Abc_FrameReadLibSuper() ); Abc_FrameSetLibSuper( NULL ); } // replace the current library Mio_LibraryDelete( (Mio_Library_t *)Abc_FrameReadLibGen() ); Abc_FrameSetLibGen( pLib ); // set the new network pLib = (Mio_Library_t *)Amap_LibReadAndPrepare( pFileName, Vec_StrArray(vStr2), 0, 0 ); if ( pLib == NULL ) return 0; // replace the current library Amap_LibFree( (Amap_Lib_t *)Abc_FrameReadLibGen2() ); Abc_FrameSetLibGen2( pLib ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_CommandReadLiberty( Abc_Frame_t * pAbc, int argc, char **argv ) { int fUseFileInterface = 0; char Command[1000]; FILE * pFile; FILE * pOut, * pErr; char * pFileName; int fVerbose; int c; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults fVerbose = 0; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) { switch (c) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".scl", ".g", NULL )) ) fprintf( pErr, "Did you mean \"%s\"?", pFileName ); fprintf( pErr, "\n" ); return 1; } fclose( pFile ); if ( fUseFileInterface ) { if ( !Amap_LibertyParse( pFileName, fVerbose ) ) return 0; assert( strlen(pFileName) < 900 ); sprintf( Command, "read_genlib %s", Extra_FileNameGenericAppend(pFileName, ".genlib") ); Cmd_CommandExecute( pAbc, Command ); } else { Vec_Str_t * vStr, * vStr2; int RetValue; vStr = Amap_LibertyParseStr( pFileName, fVerbose ); if ( vStr == NULL ) return 0; vStr2 = Vec_StrDup(vStr); RetValue = Mio_UpdateGenlib2( vStr, vStr2, pFileName, fVerbose ); Vec_StrFree( vStr ); Vec_StrFree( vStr2 ); if ( !RetValue ) printf( "Reading library has filed.\n" ); } return 0; usage: fprintf( pErr, "usage: read_liberty [-vh]\n"); fprintf( pErr, "\t read standard cell library in Liberty format\n" ); fprintf( pErr, "\t (if the library contains more than one gate\n" ); fprintf( pErr, "\t with the same Boolean function, only the gate\n" ); fprintf( pErr, "\t with the smallest area will be used)\n" ); fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : enable verbose output\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; Mio_Library_t * pLib; Amap_Lib_t * pLib2; char * pFileName; char * pExcludeFile = NULL; double WireDelay = 0.0; int fShortNames = 0; int c, fVerbose = 1; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "WEnvh")) != EOF ) { switch (c) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a floating point number.\n" ); goto usage; } WireDelay = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( WireDelay <= 0.0 ) goto usage; break; case 'E': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-E\" should be followed by a file name.\n" ); goto usage; } pExcludeFile = argv[globalUtilOptind]; globalUtilOptind++; break; case 'n': fShortNames ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".scl", ".g", NULL )) ) fprintf( pErr, "Did you mean \"%s\"?", pFileName ); fprintf( pErr, "\n" ); return 1; } fclose( pFile ); // set the new network pLib = Mio_LibraryRead( pFileName, NULL, pExcludeFile, fVerbose ); if ( pLib == NULL ) { fprintf( pErr, "Reading genlib library has failed.\n" ); return 1; } if ( fVerbose ) printf( "Entered genlib library with %d gates from file \"%s\".\n", Mio_LibraryReadGateNum(pLib), pFileName ); // convert the library if needed if ( fShortNames ) Mio_LibraryShortNames( pLib ); // add the fixed number (wire delay) to all delays in the library if ( WireDelay != 0.0 ) Mio_LibraryShiftDelay( pLib, WireDelay ); // prepare libraries Mio_UpdateGenlib( pLib ); // replace the current library pLib2 = Amap_LibReadAndPrepare( pFileName, NULL, 0, 0 ); if ( pLib2 == NULL ) { fprintf( pErr, "Reading second genlib library has failed.\n" ); return 1; } Abc_FrameSetLibGen2( pLib2 ); return 0; usage: fprintf( pErr, "usage: read_genlib [-W float] [-E filename] [-nvh]\n"); fprintf( pErr, "\t read the library from a genlib file\n" ); fprintf( pErr, "\t (if the library contains more than one gate\n" ); fprintf( pErr, "\t with the same Boolean function, only the gate\n" ); fprintf( pErr, "\t with the smallest area will be used)\n" ); fprintf( pErr, "\t-W float : wire delay (added to pin-to-pin gate delays) [default = %g]\n", WireDelay ); fprintf( pErr, "\t-E file : the file name with gates to be excluded [default = none]\n" ); fprintf( pErr, "\t-n : toggle replacing gate/pin names by short strings [default = %s]\n", fShortNames? "yes": "no" ); fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pErr, "\t-h : enable verbose output\n"); return 1; } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_CommandWriteGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pOut, * pErr, * pFile; char * pFileName; int fSelected = 0; int fVerbose = 0; int c; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "vah")) != EOF ) { switch (c) { case 'v': fVerbose ^= 1; break; case 'a': fSelected ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( Abc_FrameReadLibGen() == NULL ) { printf( "Library is not available.\n" ); return 1; } if ( argc != globalUtilOptind + 1 ) { printf( "The file name is not given.\n" ); return 1; } pFileName = argv[globalUtilOptind]; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Error! Cannot open file \"%s\" for writing the library.\n", pFileName ); return 1; } Mio_WriteLibrary( pFile, (Mio_Library_t *)Abc_FrameReadLibGen(), 0, 0, fSelected ); fclose( pFile ); printf( "The current genlib library is written into file \"%s\".\n", pFileName ); return 0; usage: fprintf( pErr, "\nusage: write_genlib [-vah] \n"); fprintf( pErr, "\t writes the current genlib library into a file\n" ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", fVerbose? "yes" : "no" ); fprintf( pErr, "\t-a : toggles writing min-area gates [default = %s]\n", fSelected? "yes" : "no" ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\t : optional file name to write the library\n"); return 1; } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_CommandPrintGenlib( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pOut, * pErr; int fShort = 0; int fSelected = 0; int fVerbose = 0; int c; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "savh")) != EOF ) { switch (c) { case 's': fShort ^= 1; break; case 'a': fSelected ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( Abc_FrameReadLibGen() == NULL ) { printf( "Library is not available.\n" ); return 1; } Mio_WriteLibrary( stdout, (Mio_Library_t *)Abc_FrameReadLibGen(), 0, fShort, fSelected ); return 0; usage: fprintf( pErr, "\nusage: print_genlib [-savh]\n"); fprintf( pErr, "\t print the current genlib library\n" ); fprintf( pErr, "\t-s : toggles writing short form [default = %s]\n", fShort? "yes" : "no" ); fprintf( pErr, "\t-a : toggles writing min-area gates [default = %s]\n", fSelected? "yes" : "no" ); fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", fVerbose? "yes" : "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_CommandReadProfile( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile, * pOut, * pErr; Mio_Library_t * pLib; char * pFileName; int c; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "h")) != EOF ) { switch (c) { case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pLib == NULL ) { fprintf( pErr, "There is no Genlib library entered.\n" ); return 1; } // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", pFileName ); if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".profile", NULL, NULL, NULL, NULL )) ) fprintf( pErr, "Did you mean \"%s\"?", pFileName ); fprintf( pErr, "\n" ); return 1; } // set the new network Mio_LibraryReadProfile( pFile, pLib ); fclose( pFile ); return 0; usage: fprintf( pErr, "usage: read_profile [-h] \n"); fprintf( pErr, "\t read a gate profile from a profile file\n" ); fprintf( pErr, "\t-h : enable verbose output\n"); fprintf( pErr, "\t : file name to read the profile\n"); return 1; } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_CommandWriteProfile( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pOut, * pErr, * pFile; char * pFileName; int c; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "h")) != EOF ) { switch (c) { case 'h': goto usage; break; default: goto usage; } } if ( Abc_FrameReadLibGen() == NULL ) { printf( "Library is not available.\n" ); return 1; } if ( argc != globalUtilOptind + 1 ) { printf( "The file name is not given.\n" ); return 1; } pFileName = argv[globalUtilOptind]; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Error! Cannot open file \"%s\" for writing the library.\n", pFileName ); return 1; } Mio_LibraryWriteProfile( pFile, (Mio_Library_t *)Abc_FrameReadLibGen() ); fclose( pFile ); printf( "The current profile is written into file \"%s\".\n", pFileName ); return 0; usage: fprintf( pErr, "\nusage: write_profile [-h] \n"); fprintf( pErr, "\t writes the current profile into a file\n" ); fprintf( pErr, "\t-h : print the command usage\n"); fprintf( pErr, "\t : file name to write the profile\n"); return 1; } /**Function************************************************************* Synopsis [Command procedure to read LUT libraries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_CommandPrintProfile( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pOut, * pErr; int fShort = 0; int fSelected = 0; int fVerbose = 0; int c; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "savh")) != EOF ) { switch (c) { case 's': fShort ^= 1; break; case 'a': fSelected ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( Abc_FrameReadLibGen() == NULL ) { printf( "Library is not available.\n" ); return 1; } Mio_LibraryWriteProfile( stdout, (Mio_Library_t *)Abc_FrameReadLibGen() ); return 0; usage: fprintf( pErr, "\nusage: print_profile [-h]\n"); fprintf( pErr, "\t print the current gate profile\n" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mio.h000066400000000000000000000341101300674244400223310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mio.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [File reading/writing for technology mapping.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mio.h,v 1.6 2004/08/09 22:16:31 satrajit Exp $] ***********************************************************************/ #ifndef ABC__map__mio__mio_h #define ABC__map__mio__mio_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef enum { MIO_PHASE_UNKNOWN, MIO_PHASE_INV, MIO_PHASE_NONINV } Mio_PinPhase_t; typedef struct Mio_LibraryStruct_t_ Mio_Library_t; typedef struct Mio_GateStruct_t_ Mio_Gate_t; typedef struct Mio_PinStruct_t_ Mio_Pin_t; typedef struct Mio_Cell_t_ Mio_Cell_t; struct Mio_Cell_t_ { char * pName; // name unsigned Id : 28; // gate ID unsigned nFanins : 4; // gate fanins float Area; // area word uTruth; // truth table float Delays[6]; // delay }; typedef struct Mio_Cell2_t_ Mio_Cell2_t; struct Mio_Cell2_t_ { char * pName; // name Vec_Int_t * vExpr; // expression unsigned Id : 26; // gate ID unsigned Type : 2; // gate type unsigned nFanins : 4; // gate fanins float AreaF; // area word AreaW; // area word uTruth; // truth table int iDelayAve; // average delay int iDelays[6]; // delay void * pMioGate; // gate pointer }; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Mio_LibraryForEachGate( Lib, Gate ) \ for ( Gate = Mio_LibraryReadGates(Lib); \ Gate; \ Gate = Mio_GateReadNext(Gate) ) #define Mio_LibraryForEachGateSafe( Lib, Gate, Gate2 ) \ for ( Gate = Mio_LibraryReadGates(Lib), \ Gate2 = (Gate? Mio_GateReadNext(Gate): NULL); \ Gate; \ Gate = Gate2, \ Gate2 = (Gate? Mio_GateReadNext(Gate): NULL) ) #define Mio_GateForEachPin( Gate, Pin ) \ for ( Pin = Mio_GateReadPins(Gate); \ Pin; \ Pin = Mio_PinReadNext(Pin) ) #define Mio_GateForEachPinSafe( Gate, Pin, Pin2 ) \ for ( Pin = Mio_GateReadPins(Gate), \ Pin2 = (Pin? Mio_PinReadNext(Pin): NULL); \ Pin; \ Pin = Pin2, \ Pin2 = (Pin? Mio_PinReadNext(Pin): NULL) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mio.c =============================================================*/ extern void Mio_UpdateGenlib( Mio_Library_t * pLib ); extern int Mio_UpdateGenlib2( Vec_Str_t * vStr, Vec_Str_t * vStr2, char * pFileName, int fVerbose ); /*=== mioApi.c =============================================================*/ extern char * Mio_LibraryReadName ( Mio_Library_t * pLib ); extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ); extern Mio_Gate_t ** Mio_LibraryReadGateArray ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName, char * pOutName ); extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char * pName ); extern Mio_Gate_t * Mio_LibraryReadGateByTruth( Mio_Library_t * pLib, word t ); extern Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadAnd2 ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadNor2 ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadOr2 ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ); extern Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ); extern float Mio_LibraryReadDelayInvRise( Mio_Library_t * pLib ); extern float Mio_LibraryReadDelayInvFall( Mio_Library_t * pLib ); extern float Mio_LibraryReadDelayInvMax( Mio_Library_t * pLib ); extern float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ); extern float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ); extern float Mio_LibraryReadDelayNand2Max( Mio_Library_t * pLib ); extern float Mio_LibraryReadDelayAnd2Max( Mio_Library_t * pLib ); extern float Mio_LibraryReadDelayAigNode( Mio_Library_t * pLib ); extern float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ); extern float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib ); extern float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ); extern int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib ); extern char * Mio_GateReadName ( Mio_Gate_t * pGate ); extern char * Mio_GateReadOutName ( Mio_Gate_t * pGate ); extern double Mio_GateReadArea ( Mio_Gate_t * pGate ); extern char * Mio_GateReadForm ( Mio_Gate_t * pGate ); extern Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ); extern Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ); extern Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ); extern Mio_Gate_t * Mio_GateReadTwin ( Mio_Gate_t * pGate ); extern int Mio_GateReadPinNum ( Mio_Gate_t * pGate ); extern double Mio_GateReadDelayMax ( Mio_Gate_t * pGate ); extern char * Mio_GateReadSop ( Mio_Gate_t * pGate ); extern Vec_Int_t * Mio_GateReadExpr ( Mio_Gate_t * pGate ); extern word Mio_GateReadTruth ( Mio_Gate_t * pGate ); extern word * Mio_GateReadTruthP ( Mio_Gate_t * pGate ); extern int Mio_GateReadValue ( Mio_Gate_t * pGate ); extern int Mio_GateReadCell ( Mio_Gate_t * pGate ); extern int Mio_GateReadProfile ( Mio_Gate_t * pGate ); extern int Mio_GateReadProfile2 ( Mio_Gate_t * pGate ); extern char * Mio_GateReadPinName ( Mio_Gate_t * pGate, int iPin ); extern float Mio_GateReadPinDelay ( Mio_Gate_t * pGate, int iPin ); extern void Mio_GateSetValue ( Mio_Gate_t * pGate, int Value ); extern void Mio_GateSetCell ( Mio_Gate_t * pGate, int Cell ); extern void Mio_GateSetProfile ( Mio_Gate_t * pGate, int Prof ); extern void Mio_GateSetProfile2 ( Mio_Gate_t * pGate, int Prof ); extern void Mio_GateIncProfile2 ( Mio_Gate_t * pGate ); extern void Mio_GateDecProfile2 ( Mio_Gate_t * pGate ); extern void Mio_GateAddToProfile ( Mio_Gate_t * pGate, int Prof ); extern void Mio_GateAddToProfile2 ( Mio_Gate_t * pGate, int Prof ); extern int Mio_GateIsInv ( Mio_Gate_t * pGate ); extern char * Mio_PinReadName ( Mio_Pin_t * pPin ); extern Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin ); extern double Mio_PinReadInputLoad ( Mio_Pin_t * pPin ); extern double Mio_PinReadMaxLoad ( Mio_Pin_t * pPin ); extern double Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin ); extern double Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin ); extern double Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin ); extern double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin ); extern double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin ); extern Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin ); /*=== mioRead.c =============================================================*/ extern char * Mio_ReadFile( char * FileName, int fAddEnd ); extern Mio_Library_t * Mio_LibraryRead( char * FileName, char * pBuffer, char * ExcludeFile, int fVerbose ); extern int Mio_LibraryReadExclude( char * ExcludeFile, st__table * tExcludeGate ); /*=== mioFunc.c =============================================================*/ extern int Mio_LibraryParseFormulas( Mio_Library_t * pLib ); /*=== mioParse.c =============================================================*/ extern Vec_Int_t * Mio_ParseFormula( char * pFormInit, char ** ppVarNames, int nVars ); extern Vec_Wrd_t * Mio_ParseFormulaTruth( char * pFormInit, char ** ppVarNames, int nVars ); extern int Mio_ParseCheckFormula( Mio_Gate_t * pGate, char * pForm ); /*=== mioSop.c =============================================================*/ extern char * Mio_LibDeriveSop( int nVars, Vec_Int_t * vExpr, Vec_Str_t * vStr ); /*=== mioUtils.c =============================================================*/ extern void Mio_LibraryDelete( Mio_Library_t * pLib ); extern void Mio_GateDelete( Mio_Gate_t * pGate ); extern void Mio_PinDelete( Mio_Pin_t * pPin ); extern Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ); extern void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops, int fShort, int fSelected ); extern Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, int fSkipInv, int * pnGates, int fVerbose ); extern Mio_Cell_t * Mio_CollectRootsNew( Mio_Library_t * pLib, int nInputs, int * pnGates, int fVerbose ); extern Mio_Cell_t * Mio_CollectRootsNewDefault( int nInputs, int * pnGates, int fVerbose ); extern Mio_Cell2_t * Mio_CollectRootsNewDefault2( int nInputs, int * pnGates, int fVerbose ); extern word Mio_DeriveTruthTable6( Mio_Gate_t * pGate ); extern void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] ); extern void Mio_DeriveGateDelays( Mio_Gate_t * pGate, float ** ptPinDelays, int nPins, int nInputs, float tDelayZero, float * ptDelaysRes, float * ptPinDelayMax ); extern Mio_Gate_t * Mio_GateCreatePseudo( int nInputs ); extern void Mio_LibraryShiftDelay( Mio_Library_t * pLib, double Shift ); extern void Mio_LibraryMultiArea( Mio_Library_t * pLib, double Multi ); extern void Mio_LibraryMultiDelay( Mio_Library_t * pLib, double Multi ); extern void Mio_LibraryTransferDelays( Mio_Library_t * pLibD, Mio_Library_t * pLibS ); extern void Mio_LibraryTransferCellIds(); extern void Mio_LibraryReadProfile( FILE * pFile, Mio_Library_t * pLib ); extern void Mio_LibraryWriteProfile( FILE * pFile, Mio_Library_t * pLib ); extern void Mio_LibraryTransferProfile( Mio_Library_t * pLibDst, Mio_Library_t * pLibSrc ); extern void Mio_LibraryTransferProfile2( Mio_Library_t * pLibDst, Mio_Library_t * pLibSrc ); extern int Mio_LibraryHasProfile( Mio_Library_t * pLib ); extern void Mio_LibraryCleanProfile2( Mio_Library_t * pLib ); extern void Mio_LibraryShortNames( Mio_Library_t * pLib ); extern void Mio_LibraryMatchesStop( Mio_Library_t * pLib ); extern void Mio_LibraryMatchesStart( Mio_Library_t * pLib, int fPinFilter, int fPinPerm, int fPinQuick ); extern void Mio_LibraryMatchesFetch( Mio_Library_t * pLib, Vec_Mem_t ** pvTtMem, Vec_Wec_t ** pvTt2Match, Mio_Cell2_t ** ppCells, int * pnCells, int fPinFilter, int fPinPerm, int fPinQuick ); /*=== sclUtil.c =========================================================*/ extern Mio_Library_t * Abc_SclDeriveGenlibSimple( void * pScl ); extern Mio_Library_t * Abc_SclDeriveGenlib( void * pScl, void * pMio, float Slew, float Gain, int nGatesMin, int fVerbose ); extern int Abc_SclHasDelayInfo( void * pScl ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mioApi.c000066400000000000000000000271441300674244400227670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mioApi.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [File reading/writing for technology mapping.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mioApi.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] ***********************************************************************/ #include "mioInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_LibraryReadName ( Mio_Library_t * pLib ) { return pLib->pName; } int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ) { return pLib->nGates; } Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { return pLib->pGates; } Mio_Gate_t ** Mio_LibraryReadGateArray ( Mio_Library_t * pLib ) { return pLib->ppGatesName;} Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ) { return pLib->pGateBuf; } Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ) { return pLib->pGateInv; } Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ) { return pLib->pGate0; } Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ) { return pLib->pGate1; } Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib ) { return pLib->pGateNand2; } Mio_Gate_t * Mio_LibraryReadAnd2 ( Mio_Library_t * pLib ) { return pLib->pGateAnd2; } Mio_Gate_t * Mio_LibraryReadNor2 ( Mio_Library_t * pLib ) { return pLib->pGateNor2; } Mio_Gate_t * Mio_LibraryReadOr2 ( Mio_Library_t * pLib ) { return pLib->pGateOr2; } float Mio_LibraryReadDelayInvRise ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockRise : 0.0); } float Mio_LibraryReadDelayInvFall ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockFall : 0.0); } float Mio_LibraryReadDelayInvMax ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockMax : 0.0); } float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockRise : 0.0); } float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockFall : 0.0); } float Mio_LibraryReadDelayNand2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockMax : 0.0); } float Mio_LibraryReadDelayAnd2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateAnd2? pLib->pGateAnd2->pPins->dDelayBlockMax : 0.0); } float Mio_LibraryReadDelayAigNode ( Mio_Library_t * pLib ) { return pLib->pGateAnd2 ? Mio_LibraryReadDelayAnd2Max(pLib) : Mio_LibraryReadDelayNand2Max(pLib); } // approximate delay of the AIG node float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->dArea : 0.0); } float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib ) { return (float)(pLib->pGateBuf? pLib->pGateBuf->dArea : 0.0); } float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->dArea : 0.0); } /**Function************************************************************* Synopsis [Returns the longest gate name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; int LenMax = 0, LenCur; Mio_LibraryForEachGate( pLib, pGate ) { LenCur = strlen( Mio_GateReadName(pGate) ); if ( LenMax < LenCur ) LenMax = LenCur; } return LenMax; } /**Function************************************************************* Synopsis [Read Mvc of the gate by name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mio_Gate_t * Mio_LibraryReadGateByName( Mio_Library_t * pLib, char * pName, char * pOutName ) { Mio_Gate_t * pGate; if ( ! st__lookup( pLib->tName2Gate, pName, (char **)&pGate ) ) return NULL; if ( pOutName == NULL ) return pGate; if ( !strcmp(pGate->pOutName, pOutName) ) return pGate; if ( pGate->pTwin && !strcmp(pGate->pTwin->pOutName, pOutName) ) return pGate->pTwin; return NULL; } /**Function************************************************************* Synopsis [Returns the first gate in the library with the given TT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mio_Gate_t * Mio_LibraryReadGateByTruth( Mio_Library_t * pLib, word t ) { Mio_Gate_t * pGate; Mio_LibraryForEachGate( pLib, pGate ) if ( pGate->nInputs <= 6 && pGate->uTruth == t ) return pGate; return NULL; } /**Function************************************************************* Synopsis [Read Mvc of the gate by name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_LibraryReadSopByName( Mio_Library_t * pLib, char * pName ) { Mio_Gate_t * pGate; if ( st__lookup( pLib->tName2Gate, pName, (char **)&pGate ) ) return pGate->pSop; return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_GateReadName ( Mio_Gate_t * pGate ) { return pGate->pName; } char * Mio_GateReadOutName ( Mio_Gate_t * pGate ) { return pGate->pOutName; } double Mio_GateReadArea ( Mio_Gate_t * pGate ) { return pGate->dArea; } char * Mio_GateReadForm ( Mio_Gate_t * pGate ) { return pGate->pForm; } Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ) { return pGate->pPins; } Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ) { return pGate->pLib; } Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ) { return pGate->pNext; } Mio_Gate_t * Mio_GateReadTwin ( Mio_Gate_t * pGate ) { return pGate->pTwin; } int Mio_GateReadPinNum ( Mio_Gate_t * pGate ) { return pGate->nInputs; } double Mio_GateReadDelayMax ( Mio_Gate_t * pGate ) { return pGate->dDelayMax; } char * Mio_GateReadSop ( Mio_Gate_t * pGate ) { return pGate->pSop; } Vec_Int_t * Mio_GateReadExpr ( Mio_Gate_t * pGate ) { return pGate->vExpr; } word Mio_GateReadTruth ( Mio_Gate_t * pGate ) { return pGate->nInputs <= 6 ? pGate->uTruth : 0; } word * Mio_GateReadTruthP ( Mio_Gate_t * pGate ) { return pGate->nInputs <= 6 ? &pGate->uTruth: pGate->pTruth; } int Mio_GateReadValue ( Mio_Gate_t * pGate ) { return pGate->Value; } int Mio_GateReadCell ( Mio_Gate_t * pGate ) { return pGate->Cell; } int Mio_GateReadProfile ( Mio_Gate_t * pGate ) { return pGate->Profile; } int Mio_GateReadProfile2 ( Mio_Gate_t * pGate ) { return pGate->Profile2; } void Mio_GateSetValue ( Mio_Gate_t * pGate, int Value ) { pGate->Value = Value; } void Mio_GateSetCell ( Mio_Gate_t * pGate, int Cell ) { pGate->Cell = Cell; } void Mio_GateSetProfile ( Mio_Gate_t * pGate, int Prof ) { pGate->Profile = Prof; } void Mio_GateSetProfile2 ( Mio_Gate_t * pGate, int Prof ) { pGate->Profile2 = Prof; } void Mio_GateIncProfile2 ( Mio_Gate_t * pGate ) { pGate->Profile2++; } void Mio_GateDecProfile2 ( Mio_Gate_t * pGate ) { pGate->Profile2--; } void Mio_GateAddToProfile ( Mio_Gate_t * pGate, int Prof ) { pGate->Profile += Prof; } void Mio_GateAddToProfile2( Mio_Gate_t * pGate, int Prof ) { pGate->Profile2 += Prof; } int Mio_GateIsInv ( Mio_Gate_t * pGate ) { return pGate->uTruth == ABC_CONST(0x5555555555555555); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_PinReadName ( Mio_Pin_t * pPin ) { return pPin->pName; } Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin ) { return pPin->Phase; } double Mio_PinReadInputLoad ( Mio_Pin_t * pPin ) { return pPin->dLoadInput; } double Mio_PinReadMaxLoad ( Mio_Pin_t * pPin ) { return pPin->dLoadMax; } double Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockRise; } double Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin ) { return pPin->dDelayFanoutRise;} double Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockFall; } double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin ) { return pPin->dDelayFanoutFall;} double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockMax; } Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin ) { return pPin->pNext; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_GateReadPinName( Mio_Gate_t * pGate, int iPin ) { Mio_Pin_t * pPin; int i = 0; Mio_GateForEachPin( pGate, pPin ) if ( i++ == iPin ) return Mio_PinReadName(pPin); return NULL; } float Mio_GateReadPinDelay( Mio_Gate_t * pGate, int iPin ) { Mio_Pin_t * pPin; int i = 0; Mio_GateForEachPin( pGate, pPin ) if ( i++ == iPin ) return 0.5 * pPin->dDelayBlockRise + 0.5 * pPin->dDelayBlockFall; return ABC_INFINITY; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mioForm.c000066400000000000000000000222571300674244400231610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mioForm.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Parsing equestion formula.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mioForm.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] ***********************************************************************/ #include "mioInt.h" #include "bdd/parse/parse.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // these symbols (and no other) can appear in the formulas #define MIO_SYMB_AND '*' #define MIO_SYMB_AND2 '&' #define MIO_SYMB_OR '+' #define MIO_SYMB_OR2 '|' #define MIO_SYMB_XOR '^' #define MIO_SYMB_NOT '!' #define MIO_SYMB_AFTNOT '\'' #define MIO_SYMB_OPEN '(' #define MIO_SYMB_CLOSE ')' static int Mio_GateParseFormula( Mio_Gate_t * pGate ); static int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Deriving the functionality of the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_LibraryParseFormulas( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; // count the gates pLib->nGates = 0; Mio_LibraryForEachGate( pLib, pGate ) pLib->nGates++; // start a temporary BDD manager pLib->dd = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // introduce ZDD variables Cudd_zddVarsFromBddVars( pLib->dd, 2 ); // for each gate, derive its function Mio_LibraryForEachGate( pLib, pGate ) if ( Mio_GateParseFormula( pGate ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Registers the cube string with the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_SopRegister( Mem_Flex_t * pMan, char * pName ) { char * pRegName; if ( pName == NULL ) return NULL; pRegName = Mem_FlexEntryFetch( pMan, strlen(pName) + 1 ); strcpy( pRegName, pName ); return pRegName; } /**Function************************************************************* Synopsis [Deriving the functionality of the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_GateParseFormula( Mio_Gate_t * pGate ) { extern char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ); DdManager * dd = pGate->pLib->dd; char * pPinNames[100]; char * pPinNamesCopy[100]; Mio_Pin_t * pPin, ** ppPin; int nPins, iPin, i; // set the maximum delay of the gate; count pins pGate->dDelayMax = 0.0; nPins = 0; Mio_GateForEachPin( pGate, pPin ) { // set the maximum delay of the gate if ( pGate->dDelayMax < pPin->dDelayBlockMax ) pGate->dDelayMax = pPin->dDelayBlockMax; // count the pin nPins++; } // check for the gate with const function if ( nPins == 0 ) { if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 ) { pGate->bFunc = b0; pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, " 0\n" ); pGate->pLib->pGate0 = pGate; } else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 ) { pGate->bFunc = b1; pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, " 1\n" ); pGate->pLib->pGate1 = pGate; } else { printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); return 1; } Cudd_Ref( pGate->bFunc ); return 0; } // collect the names as they appear in the formula nPins = Mio_GateCollectNames( pGate->pForm, pPinNames ); if ( nPins == 0 ) { printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); return 1; } // set the number of inputs pGate->nInputs = nPins; // consider the case when all the pins have identical pin info if ( strcmp( pGate->pPins->pName, "*" ) == 0 ) { // get the topmost (generic) pin pPin = pGate->pPins; ABC_FREE( pPin->pName ); // create individual pins from the generic pin ppPin = &pPin->pNext; for ( i = 1; i < nPins; i++ ) { // get the new pin *ppPin = Mio_PinDup( pPin ); // set its name (*ppPin)->pName = pPinNames[i]; // prepare the next place in the list ppPin = &((*ppPin)->pNext); } *ppPin = NULL; // set the name of the topmost pin pPin->pName = pPinNames[0]; } else { // reorder the variable names to appear the save way as the pins iPin = 0; Mio_GateForEachPin( pGate, pPin ) { // find the pin with the name pPin->pName for ( i = 0; i < nPins; i++ ) { if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 ) { // free pPinNames[i] because it is already available as pPin->pName // setting pPinNames[i] to NULL is useful to make sure that // this name is not assigned to two pins in the list ABC_FREE( pPinNames[i] ); pPinNamesCopy[iPin++] = pPin->pName; break; } if ( i == nPins ) { printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n", pPin->pName, pGate->pForm, pGate->pName ); return 1; } } } // check for the remaining names for ( i = 0; i < nPins; i++ ) if ( pPinNames[i] ) { printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n", pPinNames[i], pGate->pForm, pGate->pName ); return 1; } // copy the names back memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) ); } // expand the manager if necessary if ( dd->size < nPins ) { Cudd_Quit( dd ); dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_zddVarsFromBddVars( dd, 2 ); } // derive the formula as the BDD pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars ); if ( pGate->bFunc == NULL ) return 1; Cudd_Ref( pGate->bFunc ); // derive the cover (SOP) pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 ); // derive the truth table if ( pGate->nInputs <= 6 ) pGate->uTruth = Mio_DeriveTruthTable6( pGate ); return 0; } /**Function************************************************************* Synopsis [Collect the pin names in the formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ) { char Buffer[1000]; char * pTemp; int nPins, i; // save the formula as it was strcpy( Buffer, pFormula ); // remove the non-name symbols for ( pTemp = Buffer; *pTemp; pTemp++ ) if ( *pTemp == MIO_SYMB_AND || *pTemp == MIO_SYMB_AND2 || *pTemp == MIO_SYMB_OR || *pTemp == MIO_SYMB_OR2 || *pTemp == MIO_SYMB_XOR || *pTemp == MIO_SYMB_NOT || *pTemp == MIO_SYMB_AFTNOT || *pTemp == MIO_SYMB_OPEN || *pTemp == MIO_SYMB_CLOSE ) *pTemp = ' '; // save the names nPins = 0; pTemp = strtok( Buffer, " " ); while ( pTemp ) { for ( i = 0; i < nPins; i++ ) if ( strcmp( pTemp, pPinNames[i] ) == 0 ) break; if ( i == nPins ) { // cannot find this name; save it pPinNames[nPins++] = Abc_UtilStrsav(pTemp); } // get the next name pTemp = strtok( NULL, " " ); } return nPins; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mioFunc.c000066400000000000000000000231641300674244400231470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mioFunc.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [File reading/writing for technology mapping.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mioFunc.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] ***********************************************************************/ #include "mioInt.h" //#include "parse.h" #include "exp.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // these symbols (and no other) can appear in the formulas #define MIO_SYMB_AND '*' #define MIO_SYMB_AND2 '&' #define MIO_SYMB_OR '+' #define MIO_SYMB_OR2 '|' #define MIO_SYMB_XOR '^' #define MIO_SYMB_NOT '!' #define MIO_SYMB_AFTNOT '\'' #define MIO_SYMB_OPEN '(' #define MIO_SYMB_CLOSE ')' //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Registers the cube string with the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_SopRegister( Mem_Flex_t * pMan, char * pName ) { char * pRegName; if ( pName == NULL ) return NULL; pRegName = Mem_FlexEntryFetch( pMan, strlen(pName) + 1 ); strcpy( pRegName, pName ); return pRegName; } /**Function************************************************************* Synopsis [Collect the pin names in the formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ) { char * Buffer; char * pTemp; int nPins, i; // save the formula as it was //strcpy( Buffer, pFormula ); Buffer = Abc_UtilStrsav( pFormula ); // remove the non-name symbols for ( pTemp = Buffer; *pTemp; pTemp++ ) if ( *pTemp == MIO_SYMB_AND || *pTemp == MIO_SYMB_AND2 || *pTemp == MIO_SYMB_OR || *pTemp == MIO_SYMB_OR2 || *pTemp == MIO_SYMB_XOR || *pTemp == MIO_SYMB_NOT || *pTemp == MIO_SYMB_AFTNOT || *pTemp == MIO_SYMB_OPEN || *pTemp == MIO_SYMB_CLOSE ) *pTemp = ' '; // save the names nPins = 0; pTemp = strtok( Buffer, " " ); while ( pTemp ) { for ( i = 0; i < nPins; i++ ) if ( strcmp( pTemp, pPinNames[i] ) == 0 ) break; if ( i == nPins ) { // cannot find this name; save it pPinNames[nPins++] = Abc_UtilStrsav(pTemp); } // get the next name pTemp = strtok( NULL, " " ); } ABC_FREE( Buffer ); return nPins; } /**Function************************************************************* Synopsis [Deriving the functionality of the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_GateParseFormula( Mio_Gate_t * pGate ) { char * pPinNames[100]; char * pPinNamesCopy[100]; Mio_Pin_t * pPin, ** ppPin; int nPins, iPin, i; // set the maximum delay of the gate; count pins pGate->dDelayMax = 0.0; nPins = 0; Mio_GateForEachPin( pGate, pPin ) { // set the maximum delay of the gate if ( pGate->dDelayMax < pPin->dDelayBlockMax ) pGate->dDelayMax = pPin->dDelayBlockMax; // count the pin nPins++; } // check for the gate with const function if ( nPins == 0 ) { if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 ) { // pGate->bFunc = b0; pGate->vExpr = Exp_Const0(); pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, " 0\n" ); pGate->uTruth = 0; pGate->pLib->pGate0 = pGate; } else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 ) { // pGate->bFunc = b1; pGate->vExpr = Exp_Const1(); pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, " 1\n" ); pGate->uTruth = ~(word)0; pGate->pLib->pGate1 = pGate; } else { printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); return 1; } // Cudd_Ref( pGate->bFunc ); return 0; } // collect the names as they appear in the formula nPins = Mio_GateCollectNames( pGate->pForm, pPinNames ); if ( nPins == 0 ) { printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); return 1; } // set the number of inputs pGate->nInputs = nPins; // consider the case when all the pins have identical pin info if ( strcmp( pGate->pPins->pName, "*" ) == 0 ) { // get the topmost (generic) pin pPin = pGate->pPins; ABC_FREE( pPin->pName ); // create individual pins from the generic pin ppPin = &pPin->pNext; for ( i = 1; i < nPins; i++ ) { // get the new pin *ppPin = Mio_PinDup( pPin ); // set its name (*ppPin)->pName = pPinNames[i]; // prepare the next place in the list ppPin = &((*ppPin)->pNext); } *ppPin = NULL; // set the name of the topmost pin pPin->pName = pPinNames[0]; } else { // reorder the variable names to appear the save way as the pins iPin = 0; Mio_GateForEachPin( pGate, pPin ) { // find the pin with the name pPin->pName for ( i = 0; i < nPins; i++ ) { if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 ) { // free pPinNames[i] because it is already available as pPin->pName // setting pPinNames[i] to NULL is useful to make sure that // this name is not assigned to two pins in the list ABC_FREE( pPinNames[i] ); pPinNamesCopy[iPin++] = pPin->pName; break; } if ( i == nPins ) { printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n", pPin->pName, pGate->pForm, pGate->pName ); return 1; } } } // check for the remaining names for ( i = 0; i < nPins; i++ ) if ( pPinNames[i] ) { printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n", pPinNames[i], pGate->pForm, pGate->pName ); return 1; } // copy the names back memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) ); } /* // expand the manager if necessary if ( dd->size < nPins ) { Cudd_Quit( dd ); dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_zddVarsFromBddVars( dd, 2 ); } // derive formula as the BDD pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars ); if ( pGate->bFunc == NULL ) return 1; Cudd_Ref( pGate->bFunc ); // derive cover pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 ); */ // derive expression pGate->vExpr = Mio_ParseFormula( pGate->pForm, (char **)pPinNames, nPins ); // Mio_ParseFormulaTruthTest( pGate->pForm, (char **)pPinNames, nPins ); // derive cover pGate->pSop = Mio_LibDeriveSop( nPins, pGate->vExpr, pGate->pLib->vCube ); pGate->pSop = Mio_SopRegister( (Mem_Flex_t *)pGate->pLib->pMmFlex, pGate->pSop ); // derive truth table if ( nPins <= 6 ) pGate->uTruth = Exp_Truth6( nPins, pGate->vExpr, NULL ); /* // verify if ( pGate->nInputs <= 6 ) { extern word Abc_SopToTruth( char * pSop, int nInputs ); word t2 = Abc_SopToTruth( pGate->pSop, nPins ); if ( pGate->uTruth != t2 ) { printf( "%s\n", pGate->pForm ); Exp_Print( nPins, pGate->vExpr ); printf( "Verification failed!\n" ); } } */ return 0; } /**Function************************************************************* Synopsis [Deriving the functionality of the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_LibraryParseFormulas( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; // count the gates pLib->nGates = 0; Mio_LibraryForEachGate( pLib, pGate ) pLib->nGates++; // for each gate, derive its function Mio_LibraryForEachGate( pLib, pGate ) if ( Mio_GateParseFormula( pGate ) ) return 1; return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mioInt.h000066400000000000000000000137741300674244400230210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mioInt.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [File reading/writing for technology mapping.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mioInt.h,v 1.4 2004/06/28 14:20:25 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__mio__mioInt_h #define ABC__map__mio__mioInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "misc/mem/mem.h" #include "misc/st/st.h" #include "mio.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #define MIO_STRING_GATE "GATE" #define MIO_STRING_LATCH "LATCH" #define MIO_STRING_PIN "PIN" #define MIO_STRING_NONINV "NONINV" #define MIO_STRING_INV "INV" #define MIO_STRING_UNKNOWN "UNKNOWN" #define MIO_STRING_CONST0 "CONST0" #define MIO_STRING_CONST1 "CONST1" // the bit masks #define MIO_MASK(n) ((~((unsigned)0)) >> (32-(n))) #define MIO_FULL (~((unsigned)0)) //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// struct Mio_LibraryStruct_t_ { char * pName; // the name of the library int nGates; // the number of the gates Mio_Gate_t ** ppGates0; // the array of gates in the original order Mio_Gate_t ** ppGatesName; // the array of gates sorted by name Mio_Gate_t * pGates; // the linked list of all gates in no particular order Mio_Gate_t * pGate0; // the constant zero gate Mio_Gate_t * pGate1; // the constant one gate Mio_Gate_t * pGateBuf; // the buffer Mio_Gate_t * pGateInv; // the inverter Mio_Gate_t * pGateNand2; // the NAND2 gate Mio_Gate_t * pGateAnd2; // the AND2 gate Mio_Gate_t * pGateNor2; // the NOR2 gate Mio_Gate_t * pGateOr2; // the OR2 gate st__table * tName2Gate; // the mapping of gate names into their pointer Mem_Flex_t * pMmFlex; // the memory manaqer for SOPs Vec_Str_t * vCube; // temporary cube // matching int fPinFilter; // pin filtering int fPinPerm; // pin permutation int fPinQuick; // pin permutation 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 }; struct Mio_GateStruct_t_ { // information derived from the genlib file char * pName; // the name of the gate double dArea; // the area of the gate char * pForm; // the formula describing functionality of the gate Mio_Pin_t * pPins; // the linked list of all pins (one pin if info is the same) char * pOutName; // the name of the output pin // the library to which this gate belongs Mio_Library_t * pLib; // the next gate in the list Mio_Gate_t * pNext; Mio_Gate_t * pTwin; // the derived information int Cell; // cell id int nInputs; // the number of inputs int Profile; // the number of occurrences int Profile2; // the number of occurrences double dDelayMax; // the maximum delay char * pSop; // sum-of-products Vec_Int_t * vExpr; // boolean expression union { word uTruth; // truth table word * pTruth; }; // pointer to the truth table int Value; // user's information }; struct Mio_PinStruct_t_ { char * pName; Mio_PinPhase_t Phase; double dLoadInput; double dLoadMax; double dDelayBlockRise; double dDelayFanoutRise; double dDelayBlockFall; double dDelayFanoutFall; double dDelayBlockMax; Mio_Pin_t * pNext; }; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mio.c =============================================================*/ /*=== mioRead.c =============================================================*/ /*=== mioUtils.c =============================================================*/ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mioParse.c000066400000000000000000000415031300674244400233230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mioParse.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Parsing Boolean expressions.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mioParse.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] ***********************************************************************/ #include "mioInt.h" #include "exp.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the list of operation symbols to be used in expressions #define MIO_EQN_SYM_OPEN '(' // opening parenthesis #define MIO_EQN_SYM_CLOSE ')' // closing parenthesis #define MIO_EQN_SYM_CONST0 '0' // constant 0 #define MIO_EQN_SYM_CONST1 '1' // constant 1 #define MIO_EQN_SYM_NEG '!' // negation before the variable #define MIO_EQN_SYM_NEGAFT '\'' // negation after the variable #define MIO_EQN_SYM_AND '*' // logic AND #define MIO_EQN_SYM_AND2 '&' // logic AND #define MIO_EQN_SYM_XOR '^' // logic XOR #define MIO_EQN_SYM_OR '+' // logic OR #define MIO_EQN_SYM_OR2 '|' // logic OR // the list of opcodes (also specifying operation precedence) #define MIO_EQN_OPER_NEG 10 // negation #define MIO_EQN_OPER_AND 9 // logic AND #define MIO_EQN_OPER_XOR 8 // logic XOR #define MIO_EQN_OPER_OR 7 // logic OR #define MIO_EQN_OPER_MARK 1 // OpStack token standing for an opening parenthesis // these are values of the internal Flag #define MIO_EQN_FLAG_START 1 // after the opening parenthesis #define MIO_EQN_FLAG_VAR 2 // after operation is received #define MIO_EQN_FLAG_OPER 3 // after operation symbol is received #define MIO_EQN_FLAG_ERROR 4 // when error is detected //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs the operation on the top entries in the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mio_ParseFormulaOper( int * pMan, int nVars, Vec_Ptr_t * pStackFn, int Oper ) { Vec_Int_t * gArg1, * gArg2, * gFunc; // perform the given operation gArg2 = (Vec_Int_t *)Vec_PtrPop( pStackFn ); gArg1 = (Vec_Int_t *)Vec_PtrPop( pStackFn ); if ( Oper == MIO_EQN_OPER_AND ) gFunc = Exp_And( pMan, nVars, gArg1, gArg2, 0, 0 ); else if ( Oper == MIO_EQN_OPER_OR ) gFunc = Exp_Or( pMan, nVars, gArg1, gArg2 ); else if ( Oper == MIO_EQN_OPER_XOR ) gFunc = Exp_Xor( pMan, nVars, gArg1, gArg2 ); else return NULL; // Cudd_Ref( gFunc ); // Cudd_RecursiveDeref( dd, gArg1 ); // Cudd_RecursiveDeref( dd, gArg2 ); Vec_IntFree( gArg1 ); Vec_IntFree( gArg2 ); Vec_PtrPush( pStackFn, gFunc ); return gFunc; } /**Function************************************************************* Synopsis [Derives the AIG corresponding to the equation.] Description [Takes the stream to output messages, the formula, the vector of variable names and the AIG manager.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mio_ParseFormula( char * pFormInit, char ** ppVarNames, int nVars ) { char * pFormula; int Man = nVars, * pMan = &Man; Vec_Ptr_t * pStackFn; Vec_Int_t * pStackOp; Vec_Int_t * gFunc; char * pTemp, * pName; int nParans, fFound, Flag; int Oper, Oper1, Oper2; int i, v; // make sure that the number of opening and closing parentheses is the same nParans = 0; for ( pTemp = pFormInit; *pTemp; pTemp++ ) if ( *pTemp == '(' ) nParans++; else if ( *pTemp == ')' ) nParans--; if ( nParans != 0 ) { fprintf( stdout, "Mio_ParseFormula(): Different number of opening and closing parentheses ().\n" ); return NULL; } // copy the formula pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 ); sprintf( pFormula, "(%s)", pFormInit ); // start the stacks pStackFn = Vec_PtrAlloc( 100 ); pStackOp = Vec_IntAlloc( 100 ); Flag = MIO_EQN_FLAG_START; for ( pTemp = pFormula; *pTemp; pTemp++ ) { switch ( *pTemp ) { // skip all spaces, tabs, and end-of-lines case ' ': case '\t': case '\r': case '\n': continue; case MIO_EQN_SYM_CONST0: Vec_PtrPush( pStackFn, Exp_Const0() ); // Cudd_Ref( b0 ); if ( Flag == MIO_EQN_FLAG_VAR ) { fprintf( stdout, "Mio_ParseFormula(): No operation symbol before constant 0.\n" ); Flag = MIO_EQN_FLAG_ERROR; break; } Flag = MIO_EQN_FLAG_VAR; break; case MIO_EQN_SYM_CONST1: Vec_PtrPush( pStackFn, Exp_Const1() ); // Cudd_Ref( b1 ); if ( Flag == MIO_EQN_FLAG_VAR ) { fprintf( stdout, "Mio_ParseFormula(): No operation symbol before constant 1.\n" ); Flag = MIO_EQN_FLAG_ERROR; break; } Flag = MIO_EQN_FLAG_VAR; break; case MIO_EQN_SYM_NEG: if ( Flag == MIO_EQN_FLAG_VAR ) {// if NEGBEF follows a variable, AND is assumed Vec_IntPush( pStackOp, MIO_EQN_OPER_AND ); Flag = MIO_EQN_FLAG_OPER; } Vec_IntPush( pStackOp, MIO_EQN_OPER_NEG ); break; case MIO_EQN_SYM_NEGAFT: if ( Flag != MIO_EQN_FLAG_VAR ) {// if there is no variable before NEGAFT, it is an error fprintf( stdout, "Mio_ParseFormula(): No variable is specified before the negation suffix.\n" ); Flag = MIO_EQN_FLAG_ERROR; break; } else // if ( Flag == PARSE_FLAG_VAR ) Vec_PtrPush( pStackFn, Exp_Not( (Vec_Int_t *)Vec_PtrPop(pStackFn) ) ); break; case MIO_EQN_SYM_AND: case MIO_EQN_SYM_AND2: case MIO_EQN_SYM_OR: case MIO_EQN_SYM_OR2: case MIO_EQN_SYM_XOR: if ( Flag != MIO_EQN_FLAG_VAR ) { fprintf( stdout, "Mio_ParseFormula(): There is no variable before AND, EXOR, or OR.\n" ); Flag = MIO_EQN_FLAG_ERROR; break; } if ( *pTemp == MIO_EQN_SYM_AND || *pTemp == MIO_EQN_SYM_AND2 ) Vec_IntPush( pStackOp, MIO_EQN_OPER_AND ); else if ( *pTemp == MIO_EQN_SYM_OR || *pTemp == MIO_EQN_SYM_OR2 ) Vec_IntPush( pStackOp, MIO_EQN_OPER_OR ); else //if ( *pTemp == MIO_EQN_SYM_XOR ) Vec_IntPush( pStackOp, MIO_EQN_OPER_XOR ); Flag = MIO_EQN_FLAG_OPER; break; case MIO_EQN_SYM_OPEN: if ( Flag == MIO_EQN_FLAG_VAR ) { Vec_IntPush( pStackOp, MIO_EQN_OPER_AND ); // fprintf( stdout, "Mio_ParseFormula(): An opening parenthesis follows a var without operation sign.\n" ); // Flag = MIO_EQN_FLAG_ERROR; // break; } Vec_IntPush( pStackOp, MIO_EQN_OPER_MARK ); // after an opening bracket, it feels like starting over again Flag = MIO_EQN_FLAG_START; break; case MIO_EQN_SYM_CLOSE: if ( Vec_IntSize( pStackOp ) != 0 ) { while ( 1 ) { if ( Vec_IntSize( pStackOp ) == 0 ) { fprintf( stdout, "Mio_ParseFormula(): There is no opening parenthesis\n" ); Flag = MIO_EQN_FLAG_ERROR; break; } Oper = Vec_IntPop( pStackOp ); if ( Oper == MIO_EQN_OPER_MARK ) break; // perform the given operation if ( Mio_ParseFormulaOper( pMan, nVars, pStackFn, Oper ) == NULL ) { fprintf( stdout, "Mio_ParseFormula(): Unknown operation\n" ); ABC_FREE( pFormula ); Vec_PtrFreeP( &pStackFn ); Vec_IntFreeP( &pStackOp ); return NULL; } } } else { fprintf( stdout, "Mio_ParseFormula(): There is no opening parenthesis\n" ); Flag = MIO_EQN_FLAG_ERROR; break; } if ( Flag != MIO_EQN_FLAG_ERROR ) Flag = MIO_EQN_FLAG_VAR; break; default: // scan the next name for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && pTemp[i] != MIO_EQN_SYM_AND && pTemp[i] != MIO_EQN_SYM_AND2 && pTemp[i] != MIO_EQN_SYM_OR && pTemp[i] != MIO_EQN_SYM_OR2 && pTemp[i] != MIO_EQN_SYM_XOR && pTemp[i] != MIO_EQN_SYM_NEGAFT && pTemp[i] != MIO_EQN_SYM_CLOSE; i++ ) { if ( pTemp[i] == MIO_EQN_SYM_NEG || pTemp[i] == MIO_EQN_SYM_OPEN ) { fprintf( stdout, "Mio_ParseFormula(): The negation sign or an opening parenthesis inside the variable name.\n" ); Flag = MIO_EQN_FLAG_ERROR; break; } } // variable name is found fFound = 0; // Vec_PtrForEachEntry( char *, vVarNames, pName, v ) for ( v = 0; v < nVars; v++ ) { pName = ppVarNames[v]; if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) { pTemp += i-1; fFound = 1; break; } } if ( !fFound ) { fprintf( stdout, "Mio_ParseFormula(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); Flag = MIO_EQN_FLAG_ERROR; break; } /* if ( Flag == MIO_EQN_FLAG_VAR ) { fprintf( stdout, "Mio_ParseFormula(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); Flag = MIO_EQN_FLAG_ERROR; break; } */ if ( Flag == MIO_EQN_FLAG_VAR ) Vec_IntPush( pStackOp, MIO_EQN_OPER_AND ); Vec_PtrPush( pStackFn, Exp_Var(v) ); // Cudd_Ref( pbVars[v] ); Flag = MIO_EQN_FLAG_VAR; break; } if ( Flag == MIO_EQN_FLAG_ERROR ) break; // error exit else if ( Flag == MIO_EQN_FLAG_START ) continue; // go on parsing else if ( Flag == MIO_EQN_FLAG_VAR ) while ( 1 ) { // check if there are negations in the OpStack if ( Vec_IntSize( pStackOp ) == 0 ) break; Oper = Vec_IntPop( pStackOp ); if ( Oper != MIO_EQN_OPER_NEG ) { Vec_IntPush( pStackOp, Oper ); break; } else { Vec_PtrPush( pStackFn, Exp_Not((Vec_Int_t *)Vec_PtrPop(pStackFn)) ); } } else // if ( Flag == MIO_EQN_FLAG_OPER ) while ( 1 ) { // execute all the operations in the OpStack // with precedence higher or equal than the last one Oper1 = Vec_IntPop( pStackOp ); // the last operation if ( Vec_IntSize( pStackOp ) == 0 ) { // if it is the only operation, push it back Vec_IntPush( pStackOp, Oper1 ); break; } Oper2 = Vec_IntPop( pStackOp ); // the operation before the last one if ( Oper2 >= Oper1 ) { // if Oper2 precedence is higher or equal, execute it if ( Mio_ParseFormulaOper( pMan, nVars, pStackFn, Oper2 ) == NULL ) { fprintf( stdout, "Mio_ParseFormula(): Unknown operation\n" ); ABC_FREE( pFormula ); Vec_PtrFreeP( &pStackFn ); Vec_IntFreeP( &pStackOp ); return NULL; } Vec_IntPush( pStackOp, Oper1 ); // push the last operation back } else { // if Oper2 precedence is lower, push them back and done Vec_IntPush( pStackOp, Oper2 ); Vec_IntPush( pStackOp, Oper1 ); break; } } } if ( Flag != MIO_EQN_FLAG_ERROR ) { if ( Vec_PtrSize(pStackFn) != 0 ) { gFunc = (Vec_Int_t *)Vec_PtrPop(pStackFn); if ( Vec_PtrSize(pStackFn) == 0 ) if ( Vec_IntSize( pStackOp ) == 0 ) { // Cudd_Deref( gFunc ); ABC_FREE( pFormula ); Vec_PtrFreeP( &pStackFn ); Vec_IntFreeP( &pStackOp ); return Exp_Reverse(gFunc); } else fprintf( stdout, "Mio_ParseFormula(): Something is left in the operation stack\n" ); else fprintf( stdout, "Mio_ParseFormula(): Something is left in the function stack\n" ); } else fprintf( stdout, "Mio_ParseFormula(): The input string is empty\n" ); } ABC_FREE( pFormula ); Vec_PtrFreeP( &pStackFn ); Vec_IntFreeP( &pStackOp ); return NULL; } /**Function************************************************************* Synopsis [Derives the TT corresponding to the equation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Mio_ParseFormulaTruth( char * pFormInit, char ** ppVarNames, int nVars ) { Vec_Int_t * vExpr; Vec_Wrd_t * vTruth; // derive expression vExpr = Mio_ParseFormula( pFormInit, ppVarNames, nVars ); if ( vExpr == NULL ) return NULL; // convert it into a truth table vTruth = Vec_WrdStart( Abc_Truth6WordNum(nVars) ); Exp_Truth( nVars, vExpr, Vec_WrdArray(vTruth) ); Vec_IntFree( vExpr ); return vTruth; } void Mio_ParseFormulaTruthTest( char * pFormInit, char ** ppVarNames, int nVars ) { Vec_Wrd_t * vTruth; vTruth = Mio_ParseFormulaTruth( pFormInit, ppVarNames, nVars ); // Kit_DsdPrintFromTruth( (unsigned *)Vec_WrdArray(vTruth), nVars ); printf( "\n" ); Vec_WrdFree( vTruth ); } /**Function************************************************************* Synopsis [Checks if the gate's formula essentially depends on all variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_ParseCheckName( Mio_Gate_t * pGate, char ** ppStr ) { Mio_Pin_t * pPin; int i, iBest = -1; // find the longest pin name that matches substring char * pNameBest = NULL; for ( pPin = Mio_GateReadPins(pGate), i = 0; pPin; pPin = Mio_PinReadNext(pPin), i++ ) if ( !strncmp( *ppStr, Mio_PinReadName(pPin), strlen(Mio_PinReadName(pPin)) ) ) if ( pNameBest == NULL || strlen(pNameBest) < strlen(Mio_PinReadName(pPin)) ) pNameBest = Mio_PinReadName(pPin), iBest = i; // if pin is not found, return -1 if ( pNameBest ) *ppStr += strlen(pNameBest) - 1; return iBest; } int Mio_ParseCheckFormula( Mio_Gate_t * pGate, char * pForm ) { Mio_Pin_t * pPin; char * pStr; int i, iPin, fVisit[32] = {0}; if ( Mio_GateReadPins(pGate) == NULL || !strcmp(Mio_PinReadName(Mio_GateReadPins(pGate)), "*") ) return 1; /* // find the equality sign pForm = strstr( pForm, "=" ); if ( pForm == NULL ) { printf( "Skipping gate \"%s\" because formula \"%s\" has not equality sign (=).\n", pGate->pName, pForm ); return 0; } */ //printf( "Checking gate %s\n", pGate->pName ); for ( pStr = pForm; *pStr; pStr++ ) { if ( *pStr == ' ' || *pStr == MIO_EQN_SYM_OPEN || *pStr == MIO_EQN_SYM_CLOSE || *pStr == MIO_EQN_SYM_CONST0 || *pStr == MIO_EQN_SYM_CONST1 || *pStr == MIO_EQN_SYM_NEG || *pStr == MIO_EQN_SYM_NEGAFT || *pStr == MIO_EQN_SYM_AND || *pStr == MIO_EQN_SYM_AND2 || *pStr == MIO_EQN_SYM_XOR || *pStr == MIO_EQN_SYM_OR || *pStr == MIO_EQN_SYM_OR2 ) continue; // return the number of the pin which has this name iPin = Mio_ParseCheckName( pGate, &pStr ); if ( iPin == -1 ) { printf( "Skipping gate \"%s\" because substring \"%s\" does not match with a pin name.\n", pGate->pName, pStr ); return 0; } assert( iPin < 32 ); fVisit[iPin] = 1; } // check that all pins are used for ( pPin = Mio_GateReadPins(pGate), i = 0; pPin; pPin = Mio_PinReadNext(pPin), i++ ) if ( fVisit[i] == 0 ) { // printf( "Skipping gate \"%s\" because pin \"%s\" does not appear in the formula \"%s\".\n", pGate->pName, Mio_PinReadName(pPin), pForm ); return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mioRead.c000066400000000000000000000555171300674244400231360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mioRead.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [File reading/writing for technology mapping.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mioRead.c,v 1.9 2004/10/19 06:40:16 satrajit Exp $] ***********************************************************************/ #include #include "mioInt.h" #include "base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ); static Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ); static int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ); static Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, int fExtendedFormat ); static Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, int fExtendedFormat ); static char * chomp( char *s ); static void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ); static void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines ); /**Function************************************************************* Synopsis [Read the genlib type of library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mio_Library_t * Mio_LibraryRead( char * FileName, char * pBuffer, char * ExcludeFile, int fVerbose ) { Mio_Library_t * pLib; int num; char * pBufferCopy; st__table * tExcludeGate = 0; if ( ExcludeFile ) { tExcludeGate = st__init_table(strcmp, st__strhash); if ( (num = Mio_LibraryReadExclude( ExcludeFile, tExcludeGate )) == -1 ) { st__free_table( tExcludeGate ); tExcludeGate = 0; return 0; } fprintf ( stdout, "Read %d gates from exclude file\n", num ); } pBufferCopy = Abc_UtilStrsav(pBuffer); if ( pBuffer == NULL ) pLib = Mio_LibraryReadOne( FileName, 0, tExcludeGate, fVerbose ); // try normal format first .. else { pLib = Mio_LibraryReadBuffer( pBuffer, 0, tExcludeGate, fVerbose ); // try normal format first .. if ( pLib ) pLib->pName = Abc_UtilStrsav( Extra_FileNameGenericAppend(FileName, ".genlib") ); } if ( pLib == NULL ) { if ( pBuffer == NULL ) pLib = Mio_LibraryReadOne( FileName, 1, tExcludeGate, fVerbose ); // try normal format first .. else { pLib = Mio_LibraryReadBuffer( pBufferCopy, 1, tExcludeGate, fVerbose ); // try normal format first .. if ( pLib ) pLib->pName = Abc_UtilStrsav( Extra_FileNameGenericAppend(FileName, ".genlib") ); } if ( pLib != NULL ) printf ( "Warning: Read extended genlib format but ignoring extensions\n" ); } ABC_FREE( pBufferCopy ); if ( tExcludeGate ) st__free_table( tExcludeGate ); return pLib; } /**Function************************************************************* Synopsis [Read contents of the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_ReadFile( char * FileName, int fAddEnd ) { char * pBuffer; FILE * pFile; int nFileSize; int RetValue; // open the BLIF file for binary reading pFile = Io_FileOpen( FileName, "open_path", "rb", 1 ); // pFile = fopen( FileName, "rb" ); // if we got this far, file should be okay otherwise would // have been detected by caller assert ( pFile != NULL ); // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nFileSize + 10 ); RetValue = fread( pBuffer, nFileSize, 1, pFile ); // terminate the string with '\0' pBuffer[ nFileSize ] = '\0'; if ( fAddEnd ) strcat( pBuffer, "\n.end\n" ); // close file fclose( pFile ); return pBuffer; } /**Function************************************************************* Synopsis [Read the genlib type of library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ) { Mio_Library_t * pLib; // allocate the genlib structure pLib = ABC_CALLOC( Mio_Library_t, 1 ); pLib->tName2Gate = st__init_table(strcmp, st__strhash); pLib->pMmFlex = Mem_FlexStart(); pLib->vCube = Vec_StrAlloc( 100 ); Io_ReadFileRemoveComments( pBuffer, NULL, NULL ); // parse the contents of the file if ( Mio_LibraryReadInternal( pLib, pBuffer, fExtendedFormat, tExcludeGate, fVerbose ) ) { Mio_LibraryDelete( pLib ); return NULL; } // derive the functinality of gates if ( Mio_LibraryParseFormulas( pLib ) ) { printf( "Mio_LibraryRead: Had problems parsing formulas.\n" ); Mio_LibraryDelete( pLib ); return NULL; } // detect INV and NAND2 Mio_LibraryDetectSpecialGates( pLib ); //Mio_WriteLibrary( stdout, pLib ); return pLib; } /**Function************************************************************* Synopsis [Read the genlib type of library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mio_Library_t * Mio_LibraryReadOne( char * FileName, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ) { Mio_Library_t * pLib; char * pBuffer; // read the file and clean comments // pBuffer = Io_ReadFileFileContents( FileName, NULL ); // we don't use above function but actually do the same thing explicitly // to handle open_path expansion correctly pBuffer = Mio_ReadFile( FileName, 1 ); if ( pBuffer == NULL ) return NULL; pLib = Mio_LibraryReadBuffer( pBuffer, fExtendedFormat, tExcludeGate, fVerbose ); ABC_FREE( pBuffer ); if ( pLib ) pLib->pName = Abc_UtilStrsav( FileName ); return pLib; } /**Function************************************************************* Synopsis [Read the genlib type of library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int fVerbose ) { Mio_Gate_t * pGate, ** ppGate; char * pToken; int nGates = 0; int nDel = 0; // start the linked list of gates pLib->pGates = NULL; ppGate = &pLib->pGates; // read gates one by one pToken = strtok( pBuffer, " \t\r\n" ); while ( pToken && (strcmp( pToken, MIO_STRING_GATE ) == 0 || strcmp( pToken, MIO_STRING_LATCH ) == 0) ) { // skip latches if ( strcmp( pToken, MIO_STRING_LATCH ) == 0 ) { while ( pToken && strcmp( pToken, MIO_STRING_GATE ) != 0 && strcmp( pToken, ".end" ) != 0 ) { if ( strcmp( pToken, MIO_STRING_LATCH ) == 0 ) { pToken = strtok( NULL, " \t\r\n" ); printf( "Skipping latch \"%s\"...\n", pToken ); continue; } pToken = strtok( NULL, " \t\r\n" ); } if ( !(pToken && strcmp( pToken, MIO_STRING_GATE ) == 0) ) break; } // derive the next gate pGate = Mio_LibraryReadGate( &pToken, fExtendedFormat ); if ( pGate == NULL ) return 1; // skip the gate if its formula has problems if ( !Mio_ParseCheckFormula(pGate, pGate->pForm) ) { Mio_GateDelete( pGate ); continue; } // set the library pGate->pLib = pLib; // printf ("Processing: '%s'\n", pGate->pName); if ( tExcludeGate && st__is_member( tExcludeGate, pGate->pName ) ) { //printf ("Excluding: '%s'\n", pGate->pName); Mio_GateDelete( pGate ); nDel++; } else { // add this gate to the list *ppGate = pGate; ppGate = &pGate->pNext; nGates++; // remember this gate by name if ( ! st__is_member( pLib->tName2Gate, pGate->pName ) ) st__insert( pLib->tName2Gate, pGate->pName, (char *)pGate ); else { Mio_Gate_t * pBase = Mio_LibraryReadGateByName( pLib, pGate->pName, NULL ); if ( pBase->pTwin != NULL ) { printf( "Gates with more than 2 outputs are not supported.\n" ); continue; } pBase->pTwin = pGate; pGate->pTwin = pBase; // printf( "Gate \"%s\" appears two times. Creating a 2-output gate.\n", pGate->pName ); } } } if ( nGates == 0 ) { printf( "The library contains no gates.\n" ); return 1; } // check what is the last word read if ( pToken && strcmp( pToken, ".end" ) != 0 ) return 1; if ( nDel != 0 ) printf( "Actually excluded %d cells\n", nDel ); return 0; } /**Function************************************************************* Synopsis [Read the genlib type of gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_LibraryCleanStr( char * p ) { int i, k; int whitespace_state = 0; char * pRes = Abc_UtilStrsav( p ); for ( i = k = 0; pRes[i]; i++ ) if ( pRes[i] != ' ' && pRes[i] != '\t' && pRes[i] != '\r' && pRes[i] != '\n' ) { if ( pRes[i] != '(' && pRes[i] != ')' && pRes[i] != '+' && pRes[i] != '*' && pRes[i] != '|' && pRes[i] != '&' && pRes[i] != '^' && pRes[i] != '\'' && pRes[i] != '!' ) { if (whitespace_state == 2) pRes[k++] = ' '; whitespace_state = 1; } else whitespace_state = 0; pRes[k++] = pRes[i]; } else whitespace_state = whitespace_state ? 2 : 0; pRes[k] = 0; return pRes; } Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, int fExtendedFormat ) { Mio_Gate_t * pGate; Mio_Pin_t * pPin, ** ppPin; char * pToken = *ppToken; // allocate the gate structure pGate = ABC_CALLOC( Mio_Gate_t, 1 ); pGate->Cell = -1; // read the name pToken = strtok( NULL, " \t\r\n" ); pGate->pName = Abc_UtilStrsav( pToken ); // read the area pToken = strtok( NULL, " \t\r\n" ); pGate->dArea = atof( pToken ); // read the formula // first the output name pToken = strtok( NULL, "=" ); pGate->pOutName = chomp( pToken ); // then rest of the expression pToken = strtok( NULL, ";" ); // pGate->pForm = Mio_LibraryCleanStr( pToken ); pGate->pForm = Abc_UtilStrsav( pToken ); // read the pin info // start the linked list of pins pGate->pPins = NULL; ppPin = &pGate->pPins; // read gates one by one pToken = strtok( NULL, " \t\r\n" ); while ( pToken && strcmp( pToken, MIO_STRING_PIN ) == 0 ) { // derive the next gate pPin = Mio_LibraryReadPin( &pToken, fExtendedFormat ); if ( pPin == NULL ) { Mio_GateDelete( pGate ); *ppToken = pToken; return NULL; } // add this pin to the list *ppPin = pPin; ppPin = &pPin->pNext; // get the next token pToken = strtok( NULL, " \t\r\n" ); } *ppToken = pToken; return pGate; } /**Function************************************************************* Synopsis [Read the genlib type of pin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, int fExtendedFormat ) { Mio_Pin_t * pPin; char * pToken = *ppToken; // allocate the gate structure pPin = ABC_CALLOC( Mio_Pin_t, 1 ); // read the name pToken = strtok( NULL, " \t\r\n" ); pPin->pName = Abc_UtilStrsav( pToken ); // read the pin phase pToken = strtok( NULL, " \t\r\n" ); if ( strcmp( pToken, MIO_STRING_UNKNOWN ) == 0 ) pPin->Phase = MIO_PHASE_UNKNOWN; else if ( strcmp( pToken, MIO_STRING_INV ) == 0 ) pPin->Phase = MIO_PHASE_INV; else if ( strcmp( pToken, MIO_STRING_NONINV ) == 0 ) pPin->Phase = MIO_PHASE_NONINV; else { printf( "Cannot read pin phase specification\n" ); Mio_PinDelete( pPin ); *ppToken = pToken; return NULL; } pToken = strtok( NULL, " \t\r\n" ); pPin->dLoadInput = atof( pToken ); pToken = strtok( NULL, " \t\r\n" ); pPin->dLoadMax = atof( pToken ); pToken = strtok( NULL, " \t\r\n" ); pPin->dDelayBlockRise = atof( pToken ); pToken = strtok( NULL, " \t\r\n" ); pPin->dDelayFanoutRise = atof( pToken ); pToken = strtok( NULL, " \t\r\n" ); pPin->dDelayBlockFall = atof( pToken ); pToken = strtok( NULL, " \t\r\n" ); pPin->dDelayFanoutFall = atof( pToken ); if ( fExtendedFormat ) { /* In extended format, the field after dDelayFanoutRise * is to be ignored **/ pPin->dDelayBlockFall = pPin->dDelayFanoutFall; pToken = strtok( NULL, " \t" ); pPin->dDelayFanoutFall = atof( pToken ); /* last field is ignored */ pToken = strtok( NULL, " \t\r\n" ); } if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall ) pPin->dDelayBlockMax = pPin->dDelayBlockRise; else pPin->dDelayBlockMax = pPin->dDelayBlockFall; *ppToken = pToken; return pPin; } /**Function************************************************************* Synopsis [Duplicates string and returns it with leading and trailing spaces removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * chomp( char *s ) { char *a, *b, *c; // remove leading spaces for ( b = s; *b; b++ ) if ( !isspace(*b) ) break; // strsav the string a = strcpy( ABC_ALLOC(char, strlen(b)+1), b ); // remove trailing spaces for ( c = a+strlen(a); c > a; c-- ) if ( *c == 0 || isspace(*c) ) *c = 0; else break; return a; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_LibraryCompareGatesByArea( Mio_Gate_t ** pp1, Mio_Gate_t ** pp2 ) { double Diff = (*pp1)->dArea - (*pp2)->dArea; if ( Diff < 0.0 ) return -1; if ( Diff > 0.0 ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_LibraryCompareGatesByName( Mio_Gate_t ** pp1, Mio_Gate_t ** pp2 ) { int Diff = strcmp( (*pp1)->pName, (*pp2)->pName ); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibrarySortGates( Mio_Library_t * pLib ) { Mio_Gate_t ** ppGates, * pGate; int i = 0; ppGates = ABC_ALLOC( Mio_Gate_t *, pLib->nGates ); Mio_LibraryForEachGate( pLib, pGate ) ppGates[i++] = pGate; assert( i == pLib->nGates ); // sort gates by name pLib->ppGates0 = ABC_ALLOC( Mio_Gate_t *, pLib->nGates ); for ( i = 0; i < pLib->nGates; i++ ) pLib->ppGates0[i] = ppGates[i]; qsort( (void *)ppGates, pLib->nGates, sizeof(void *), (int (*)(const void *, const void *)) Mio_LibraryCompareGatesByName ); for ( i = 0; i < pLib->nGates; i++ ) ppGates[i]->pNext = (i < pLib->nGates-1)? ppGates[i+1] : NULL; pLib->pGates = ppGates[0]; pLib->ppGatesName = ppGates; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Mio_Gate_t * Mio_GateCompare( Mio_Gate_t * pThis, Mio_Gate_t * pNew, word uTruth ) { if ( pNew->uTruth != uTruth ) return pThis; if ( pThis == NULL ) return pNew; if ( pThis->dArea > pNew->dArea || (pThis->dArea == pNew->dArea && strcmp(pThis->pName, pNew->pName) > 0) ) return pNew; return pThis; } void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; word uFuncBuf, uFuncInv, uFuncNand2, uFuncAnd2, uFuncNor2, uFuncOr2; Mio_LibrarySortGates( pLib ); uFuncBuf = ABC_CONST(0xAAAAAAAAAAAAAAAA); uFuncAnd2 = ABC_CONST(0xAAAAAAAAAAAAAAAA) & ABC_CONST(0xCCCCCCCCCCCCCCCC); uFuncOr2 = ABC_CONST(0xAAAAAAAAAAAAAAAA) | ABC_CONST(0xCCCCCCCCCCCCCCCC); uFuncInv = ~uFuncBuf; uFuncNand2 = ~uFuncAnd2; uFuncNor2 = ~uFuncOr2; // get smallest-area buffer Mio_LibraryForEachGate( pLib, pGate ) pLib->pGateBuf = Mio_GateCompare( pLib->pGateBuf, pGate, uFuncBuf ); if ( pLib->pGateBuf == NULL ) { printf( "Warnings: genlib library reader cannot detect the buffer gate.\n" ); printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); } // get smallest-area inverter Mio_LibraryForEachGate( pLib, pGate ) pLib->pGateInv = Mio_GateCompare( pLib->pGateInv, pGate, uFuncInv ); if ( pLib->pGateInv == NULL ) { printf( "Warnings: genlib library reader cannot detect the invertor gate.\n" ); printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); } // get smallest-area NAND2/AND2 gates Mio_LibraryForEachGate( pLib, pGate ) { pLib->pGateNand2 = Mio_GateCompare( pLib->pGateNand2, pGate, uFuncNand2 ); pLib->pGateAnd2 = Mio_GateCompare( pLib->pGateAnd2, pGate, uFuncAnd2 ); pLib->pGateNor2 = Mio_GateCompare( pLib->pGateNor2, pGate, uFuncNor2 ); pLib->pGateOr2 = Mio_GateCompare( pLib->pGateOr2, pGate, uFuncOr2 ); } if ( pLib->pGateAnd2 == NULL && pLib->pGateNand2 == NULL && pLib->pGateNor2 == NULL && pLib->pGateOr2 == NULL ) { printf( "Warnings: genlib library reader cannot detect the AND2, NAND2, OR2, and NOR2 gate.\n" ); printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); } } /**Function************************************************************* Synopsis [populate hash table of gates to be exlcuded from genlib] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_LibraryReadExclude( char * ExcludeFile, st__table * tExcludeGate ) { int nDel = 0; FILE *pEx; char buffer[128]; assert ( tExcludeGate ); if ( ExcludeFile ) { pEx = fopen( ExcludeFile, "r" ); if ( pEx == NULL ) { fprintf ( stdout, "Error: Could not open exclude file %s. Stop.\n", ExcludeFile ); return -1; } while (1 == fscanf( pEx, "%127s", buffer )) { //printf ("Read: '%s'\n", buffer ); st__insert( tExcludeGate, Abc_UtilStrsav( buffer ), (char *)0 ); nDel++; } fclose( pEx ); } return nDel; } /**Function************************************************************* Synopsis [Eliminates comments from the input file.] Description [As a byproduct, this procedure also counts the number lines and dot-statements in the input file. This also joins non-comment lines that are joined with a backspace '\'] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines ) { char * pCur; int nDots, nLines; // scan through the buffer and eliminate comments // (in the BLIF file, comments are lines starting with "#") nDots = nLines = 0; for ( pCur = pBuffer; *pCur; pCur++ ) { // if this is the beginning of comment // clean it with spaces until the new line statement if ( *pCur == '#' ) while ( *pCur != '\n' ) *pCur++ = ' '; // count the number of new lines and dots if ( *pCur == '\n' ) { if (*(pCur-1)=='\r') { // DOS(R) file support if (*(pCur-2)!='\\') nLines++; else { // rewind to backslash and overwrite with a space *(pCur-2) = ' '; *(pCur-1) = ' '; *pCur = ' '; } } else { // UNIX(TM) file support if (*(pCur-1)!='\\') nLines++; else { // rewind to backslash and overwrite with a space *(pCur-1) = ' '; *pCur = ' '; } } } else if ( *pCur == '.' ) nDots++; } if ( pnDots ) *pnDots = nDots; if ( pnLines ) *pnLines = nLines; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mioSop.c000066400000000000000000000236501300674244400230150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mioSop.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Derives SOP from Boolean expression.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mioSop.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] ***********************************************************************/ #include "mioInt.h" #include "exp.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned Mio_CubeVar0( int v ) { return (1<< (v<<1) ); } static inline unsigned Mio_CubeVar1( int v ) { return (1<<((v<<1)+1)); } static inline int Mio_CubeHasVar0( unsigned x, int v ) { return (x & Mio_CubeVar0(v)) > 0; } static inline int Mio_CubeHasVar1( unsigned x, int v ) { return (x & Mio_CubeVar1(v)) > 0; } static inline int Mio_CubeEmpty( unsigned x ) { return (x & (x>>1) & 0x55555555) != 0; } static inline unsigned Mio_CubeAnd( unsigned x, unsigned y ) { return x | y; } static inline int Mio_CubeContains( unsigned x, unsigned y ) { return (x | y) == y; } // x contains y //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Push while performing SCC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_SopPushSCC( Vec_Int_t * p, unsigned c ) { unsigned Entry; int i, k = 0; Vec_IntForEachEntry( p, Entry, i ) { if ( Mio_CubeContains( Entry, c ) ) // Entry contains c { assert( i == k ); return; } if ( Mio_CubeContains( c, Entry ) ) // c contains Entry continue; Vec_IntWriteEntry( p, k++, Entry ); } Vec_IntShrink( p, k ); Vec_IntPush( p, c ); } /**Function************************************************************* Synopsis [Make the OR of two covers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mio_SopCoverOr( Vec_Int_t * p, Vec_Int_t * q ) { Vec_Int_t * r; unsigned Entry; int i; r = Vec_IntAlloc( Vec_IntSize(p) + Vec_IntSize(q) ); Vec_IntForEachEntry( p, Entry, i ) Vec_IntPush( r, Entry ); Vec_IntForEachEntry( q, Entry, i ) Mio_SopPushSCC( r, Entry ); return r; } /**Function************************************************************* Synopsis [Make the AND of two covers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mio_SopCoverAnd( Vec_Int_t * p, Vec_Int_t * q ) { Vec_Int_t * r; unsigned EntryP, EntryQ; int i, k; r = Vec_IntAlloc( Vec_IntSize(p) * Vec_IntSize(q) ); Vec_IntForEachEntry( p, EntryP, i ) Vec_IntForEachEntry( q, EntryQ, k ) if ( !Mio_CubeEmpty( Mio_CubeAnd(EntryP, EntryQ) ) ) Mio_SopPushSCC( r, Mio_CubeAnd(EntryP, EntryQ) ); return r; } /**Function************************************************************* Synopsis [Create negative literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mio_SopVar0( int i ) { Vec_Int_t * vSop; vSop = Vec_IntAlloc( 1 ); Vec_IntPush( vSop, Mio_CubeVar0(i) ); return vSop; } /**Function************************************************************* Synopsis [Create positive literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mio_SopVar1( int i ) { Vec_Int_t * vSop; vSop = Vec_IntAlloc( 1 ); Vec_IntPush( vSop, Mio_CubeVar1(i) ); return vSop; } /**Function************************************************************* Synopsis [Create constant 0 literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mio_SopConst0() { Vec_Int_t * vSop; vSop = Vec_IntAlloc( 1 ); return vSop; } /**Function************************************************************* Synopsis [Create constant 1 literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mio_SopConst1() { Vec_Int_t * vSop; vSop = Vec_IntAlloc( 1 ); Vec_IntPush( vSop, 0 ); return vSop; } /**Function************************************************************* Synopsis [Derives SOP representation as the char string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_SopDeriveFromArray( Vec_Int_t * vSop, int nVars, Vec_Str_t * vStr, int fPolarity ) { unsigned Entry; int i, k; Vec_StrClear( vStr ); if ( Vec_IntSize(vSop) == 0 ) { Vec_StrPush( vStr, ' ' ); Vec_StrPush( vStr, (char)('1'-fPolarity) ); Vec_StrPush( vStr, '\n' ); Vec_StrPush( vStr, '\0' ); return Vec_StrArray( vStr ); } if ( Vec_IntSize(vSop) == 1 && Vec_IntEntry(vSop, 0) == 0 ) { Vec_StrPush( vStr, ' ' ); Vec_StrPush( vStr, (char)('0'+fPolarity) ); Vec_StrPush( vStr, '\n' ); Vec_StrPush( vStr, '\0' ); return Vec_StrArray( vStr ); } // create cubes Vec_IntForEachEntry( vSop, Entry, i ) { for ( k = 0; k < nVars; k++ ) { if ( Mio_CubeHasVar0( Entry, k ) ) Vec_StrPush( vStr, '0' ); else if ( Mio_CubeHasVar1( Entry, k ) ) Vec_StrPush( vStr, '1' ); else Vec_StrPush( vStr, '-' ); } Vec_StrPush( vStr, ' ' ); Vec_StrPush( vStr, (char)('0'+fPolarity) ); Vec_StrPush( vStr, '\n' ); } Vec_StrPush( vStr, '\0' ); return Vec_StrArray( vStr ); } /**Function************************************************************* Synopsis [Derives SOP representation.] Description [The SOP is guaranteed to be SCC-free but not minimal.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mio_LibDeriveSop( int nVars, Vec_Int_t * vExpr, Vec_Str_t * vStr ) { Vec_Int_t * vSop; Vec_Ptr_t * vSops0, * vSops1, * vTemp; int i, Index0, Index1, fCompl0, fCompl1; Vec_StrClear( vStr ); if ( Exp_IsConst0(vExpr) ) { Vec_StrPrintStr( vStr, " 0\n" ); Vec_StrPush( vStr, '\0' ); return Vec_StrArray( vStr ); } if ( Exp_IsConst1(vExpr) ) { Vec_StrPrintStr( vStr, " 1\n" ); Vec_StrPush( vStr, '\0' ); return Vec_StrArray( vStr ); } if ( Exp_IsLit(vExpr) ) { for ( i = 0; i < nVars; i++ ) Vec_StrPush( vStr, '-' ); Vec_StrPrintStr( vStr, " 1\n" ); Vec_StrPush( vStr, '\0' ); assert( (Vec_IntEntry(vExpr,0) >> 1) < nVars ); Vec_StrWriteEntry( vStr, Vec_IntEntry(vExpr,0) >> 1, (char)('1' - (Vec_IntEntry(vExpr,0) & 1)) ); return Vec_StrArray( vStr ); } vSops0 = Vec_PtrAlloc( nVars + Exp_NodeNum(vExpr) ); vSops1 = Vec_PtrAlloc( nVars + Exp_NodeNum(vExpr) ); for ( i = 0; i < nVars; i++ ) { Vec_PtrPush( vSops0, Mio_SopVar0(i) ); Vec_PtrPush( vSops1, Mio_SopVar1(i) ); } for ( i = 0; i < Exp_NodeNum(vExpr); i++ ) { Index0 = Vec_IntEntry( vExpr, 2*i+0 ) >> 1; Index1 = Vec_IntEntry( vExpr, 2*i+1 ) >> 1; fCompl0 = Vec_IntEntry( vExpr, 2*i+0 ) & 1; fCompl1 = Vec_IntEntry( vExpr, 2*i+1 ) & 1; // positive polarity vSop = Mio_SopCoverAnd( fCompl0 ? (Vec_Int_t *)Vec_PtrEntry(vSops0, Index0) : (Vec_Int_t *)Vec_PtrEntry(vSops1, Index0), fCompl1 ? (Vec_Int_t *)Vec_PtrEntry(vSops0, Index1) : (Vec_Int_t *)Vec_PtrEntry(vSops1, Index1) ); Vec_PtrPush( vSops1, vSop ); // negative polarity vSop = Mio_SopCoverOr( fCompl0 ? (Vec_Int_t *)Vec_PtrEntry(vSops1, Index0) : (Vec_Int_t *)Vec_PtrEntry(vSops0, Index0), fCompl1 ? (Vec_Int_t *)Vec_PtrEntry(vSops1, Index1) : (Vec_Int_t *)Vec_PtrEntry(vSops0, Index1) ); Vec_PtrPush( vSops0, vSop ); } // complement if ( Vec_IntEntryLast(vExpr) & 1 ) { vTemp = vSops0; vSops0 = vSops1; vSops1 = vTemp; } // select the best polarity if ( Vec_IntSize( (Vec_Int_t *)Vec_PtrEntryLast(vSops0) ) < Vec_IntSize( (Vec_Int_t *)Vec_PtrEntryLast(vSops1) ) ) vSop = (Vec_Int_t *)Vec_PtrEntryLast(vSops0); else vSop = (Vec_Int_t *)Vec_PtrEntryLast(vSops1); // convert positive polarity into SOP Mio_SopDeriveFromArray( vSop, nVars, vStr, (vSop == Vec_PtrEntryLast(vSops1)) ); Vec_VecFree( (Vec_Vec_t *)vSops0 ); Vec_VecFree( (Vec_Vec_t *)vSops1 ); return Vec_StrArray( vStr ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/mioUtils.c000066400000000000000000001502751300674244400233600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mioUtils.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [File reading/writing for technology mapping.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: mioUtils.c,v 1.6 2004/09/03 18:02:20 satrajit Exp $] ***********************************************************************/ #include #include "mioInt.h" #include "base/main/main.h" #include "exp.h" #include "misc/util/utilTruth.h" #include "opt/dau/dau.h" #include "misc/util/utilNam.h" #include "map/scl/sclLib.h" #include "map/scl/sclCon.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibraryDelete( Mio_Library_t * pLib ) { Mio_Gate_t * pGate, * pGate2; if ( pLib == NULL ) return; Mio_LibraryMatchesStop( pLib ); // free the bindings of nodes to gates from this library for all networks Abc_FrameUnmapAllNetworks( Abc_FrameGetGlobalFrame() ); // free the library ABC_FREE( pLib->pName ); Mio_LibraryForEachGateSafe( pLib, pGate, pGate2 ) Mio_GateDelete( pGate ); Mem_FlexStop( pLib->pMmFlex, 0 ); Vec_StrFree( pLib->vCube ); if ( pLib->tName2Gate ) st__free_table( pLib->tName2Gate ); // if ( pLib->dd ) // Cudd_Quit( pLib->dd ); ABC_FREE( pLib->ppGates0 ); ABC_FREE( pLib->ppGatesName ); ABC_FREE( pLib ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_GateDelete( Mio_Gate_t * pGate ) { Mio_Pin_t * pPin, * pPin2; if ( pGate->nInputs > 6 ) ABC_FREE( pGate->pTruth ); Vec_IntFreeP( &pGate->vExpr ); ABC_FREE( pGate->pOutName ); ABC_FREE( pGate->pName ); ABC_FREE( pGate->pForm ); // if ( pGate->bFunc ) // Cudd_RecursiveDeref( pGate->pLib->dd, pGate->bFunc ); Mio_GateForEachPinSafe( pGate, pPin, pPin2 ) Mio_PinDelete( pPin ); ABC_FREE( pGate ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_PinDelete( Mio_Pin_t * pPin ) { ABC_FREE( pPin->pName ); ABC_FREE( pPin ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ) { Mio_Pin_t * pPinNew; pPinNew = ABC_ALLOC( Mio_Pin_t, 1 ); *pPinNew = *pPin; pPinNew->pName = (pPinNew->pName ? Abc_UtilStrsav(pPinNew->pName) : NULL); pPinNew->pNext = NULL; return pPinNew; } /**Function************************************************************* Synopsis [Check if pin characteristics are the same.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_CheckPins( Mio_Pin_t * pPin1, Mio_Pin_t * pPin2 ) { if ( pPin1 == NULL || pPin2 == NULL ) return 1; if ( pPin1->dLoadInput != pPin2->dLoadInput ) return 0; if ( pPin1->dLoadMax != pPin2->dLoadMax ) return 0; if ( pPin1->dDelayBlockRise != pPin2->dDelayBlockRise ) return 0; if ( pPin1->dDelayFanoutRise != pPin2->dDelayFanoutRise ) return 0; if ( pPin1->dDelayBlockFall != pPin2->dDelayBlockFall ) return 0; if ( pPin1->dDelayFanoutFall != pPin2->dDelayFanoutFall ) return 0; return 1; } int Mio_CheckGates( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; Mio_Pin_t * pPin0 = NULL, * pPin = NULL; Mio_LibraryForEachGate( pLib, pGate ) Mio_GateForEachPin( pGate, pPin ) if ( Mio_CheckPins( pPin0, pPin ) ) pPin0 = pPin; else return 0; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin, int NameLen, int fAllPins ) { char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" }; if ( fAllPins ) fprintf( pFile, "PIN * " ); else fprintf( pFile, "\n PIN %*s ", NameLen, pPin->pName ); fprintf( pFile, "%7s ", pPhaseNames[pPin->Phase] ); fprintf( pFile, "%3d ", (int)pPin->dLoadInput ); fprintf( pFile, "%3d ", (int)pPin->dLoadMax ); fprintf( pFile, "%8.2f ", pPin->dDelayBlockRise ); fprintf( pFile, "%8.2f ", pPin->dDelayFanoutRise ); fprintf( pFile, "%8.2f ", pPin->dDelayBlockFall ); fprintf( pFile, "%8.2f", pPin->dDelayFanoutFall ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int GateLen, int NameLen, int FormLen, int fPrintSops, int fAllPins ) { char Buffer[5000]; Mio_Pin_t * pPin; assert( NameLen+FormLen+2 < 5000 ); sprintf( Buffer, "%s=%s;", pGate->pOutName, pGate->pForm ); fprintf( pFile, "GATE %-*s ", GateLen, pGate->pName ); fprintf( pFile, "%8.2f ", pGate->dArea ); fprintf( pFile, "%-*s ", Abc_MinInt(NameLen+FormLen+2, 60), Buffer ); // print the pins if ( fPrintSops ) fprintf( pFile, "%s", pGate->pSop? pGate->pSop : "unspecified\n" ); if ( fAllPins && pGate->pPins ) // equal pins Mio_WritePin( pFile, pGate->pPins, NameLen, 1 ); else // different pins Mio_GateForEachPin( pGate, pPin ) Mio_WritePin( pFile, pPin, NameLen, 0 ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops, int fShort, int fSelected ) { Mio_Gate_t * pGate; Mio_Pin_t * pPin; Vec_Ptr_t * vGates = Vec_PtrAlloc( 1000 ); int i, nCells, GateLen = 0, NameLen = 0, FormLen = 0; int fAllPins = fShort || Mio_CheckGates( pLib ); if ( fSelected ) { Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); for ( i = 0; i < nCells; i++ ) Vec_PtrPush( vGates, pCells[i].pMioGate ); ABC_FREE( pCells ); } else { for ( i = 0; i < pLib->nGates; i++ ) Vec_PtrPush( vGates, pLib->ppGates0[i] ); } Vec_PtrForEachEntry( Mio_Gate_t *, vGates, pGate, i ) { GateLen = Abc_MaxInt( GateLen, strlen(pGate->pName) ); NameLen = Abc_MaxInt( NameLen, strlen(pGate->pOutName) ); FormLen = Abc_MaxInt( FormLen, strlen(pGate->pForm) ); Mio_GateForEachPin( pGate, pPin ) NameLen = Abc_MaxInt( NameLen, strlen(pPin->pName) ); } fprintf( pFile, "# The genlib library \"%s\" with %d gates written by ABC on %s\n", pLib->pName, Vec_PtrSize(vGates), Extra_TimeStamp() ); Vec_PtrForEachEntry( Mio_Gate_t *, vGates, pGate, i ) Mio_WriteGate( pFile, pGate, GateLen, NameLen, FormLen, fPrintSops, fAllPins ); Vec_PtrFree( vGates ); } /**Function************************************************************* Synopsis [Compares the max delay of two gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 ) { int Comp; float Eps = (float)0.0094636; if ( (*ppG1)->dDelayMax < (*ppG2)->dDelayMax - Eps ) return -1; if ( (*ppG1)->dDelayMax > (*ppG2)->dDelayMax + Eps ) return 1; // compare names Comp = strcmp( (*ppG1)->pName, (*ppG2)->pName ); if ( Comp < 0 ) return -1; if ( Comp > 0 ) return 1; assert( 0 ); return 0; } int Mio_AreaCompare( Mio_Cell_t * pG1, Mio_Cell_t * pG2 ) { int Comp; float Eps = (float)0.0094636; if ( pG1->nFanins < pG2->nFanins ) return -1; if ( pG1->nFanins > pG2->nFanins ) return 1; if ( pG1->Area < pG2->Area - Eps ) return -1; if ( pG1->Area > pG2->Area + Eps ) return 1; // compare names Comp = strcmp( pG1->pName, pG2->pName ); if ( Comp < 0 ) return -1; if ( Comp > 0 ) return 1; assert( 0 ); return 0; } int Mio_AreaCompare2( Mio_Cell2_t * pG1, Mio_Cell2_t * pG2 ) { int Comp; if ( pG1->nFanins < pG2->nFanins ) return -1; if ( pG1->nFanins > pG2->nFanins ) return 1; if ( pG1->AreaW < pG2->AreaW ) return -1; if ( pG1->AreaW > pG2->AreaW ) return 1; // compare names Comp = strcmp( pG1->pName, pG2->pName ); if ( Comp < 0 ) return -1; if ( Comp > 0 ) return 1; assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Collects the set of root gates.] Description [Only collects the gates with unique functionality, which have fewer inputs and shorter delay than the given limits.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Mio_CellDelayAve( Mio_Cell_t * pCell ) { float CellDelay = 0; int k; for ( k = 0; k < (int)pCell->nFanins; k++ ) CellDelay += pCell->Delays[k]; if ( pCell->nFanins ) CellDelay /= pCell->nFanins; return CellDelay; } static inline float Mio_GateDelayAve( Mio_Gate_t * pGate ) { float GateDelay = 0; Mio_Pin_t * pPin; Mio_GateForEachPin( pGate, pPin ) GateDelay += (float)(0.5 * pPin->dDelayBlockRise + 0.5 * pPin->dDelayBlockFall); if ( pGate->nInputs ) GateDelay /= pGate->nInputs; return GateDelay; } static inline int Mio_CompareTwoGates( Mio_Gate_t * pCell, Mio_Gate_t * pGate ) { int Comp; float Eps = (float)0.0094636; float CellDelay, GateDelay; // compare areas if ( pCell->dArea > (float)pGate->dArea + Eps ) return 1; if ( pCell->dArea < (float)pGate->dArea - Eps ) return 0; // compare delays CellDelay = Mio_GateDelayAve( pCell ); GateDelay = Mio_GateDelayAve( pGate ); if ( CellDelay > GateDelay + Eps ) return 1; if ( CellDelay < GateDelay - Eps ) return 0; // compare names Comp = strcmp( pCell->pName, pGate->pName ); if ( Comp > 0 ) return 1; if ( Comp < 0 ) return 0; assert( 0 ); return 0; } Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, int fSkipInv, int * pnGates, int fVerbose ) { Mio_Gate_t * pGate; Mio_Gate_t ** ppGates; int i, nGates, iGate, fProfile; nGates = Mio_LibraryReadGateNum( pLib ); ppGates = ABC_ALLOC( Mio_Gate_t *, nGates ); iGate = 0; // check if profile is entered fProfile = Mio_LibraryHasProfile( pLib ); if ( fProfile ) printf( "Mio_CollectRoots(): Using gate profile to select gates for mapping.\n" ); // for each functionality, select gate with the smallest area // if equal areas, select gate with lexicographically smaller name Mio_LibraryForEachGate( pLib, pGate ) { if ( pGate->nInputs > nInputs ) continue; if ( fProfile && Mio_GateReadProfile(pGate) == 0 && pGate->nInputs > 1 ) continue; if ( tDelay > 0.0 && pGate->dDelayMax > (double)tDelay ) continue; if ( pGate->uTruth == 0 || pGate->uTruth == ~(word)0 ) continue; if ( pGate->uTruth == ABC_CONST(0xAAAAAAAAAAAAAAAA) ) continue; if ( pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA) && fSkipInv ) continue; if ( pGate->pTwin ) // skip multi-output gates for now continue; // check if the gate with this functionality already exists for ( i = 0; i < iGate; i++ ) if ( ppGates[i]->uTruth == pGate->uTruth ) { if ( Mio_CompareTwoGates(ppGates[i], pGate) ) ppGates[i] = pGate; break; } if ( i < iGate ) continue; assert( iGate < nGates ); ppGates[ iGate++ ] = pGate; if ( fVerbose ) printf( "Selected gate %3d: %-20s A = %7.2f D = %7.2f %3s = %-s\n", iGate+1, pGate->pName, pGate->dArea, pGate->dDelayMax, pGate->pOutName, pGate->pForm ); } // sort by delay if ( iGate > 0 ) { qsort( (void *)ppGates, iGate, sizeof(Mio_Gate_t *), (int (*)(const void *, const void *)) Mio_DelayCompare ); assert( Mio_DelayCompare( ppGates, ppGates + iGate - 1 ) <= 0 ); } if ( pnGates ) *pnGates = iGate; return ppGates; } /**Function************************************************************* Synopsis [Collects the set of root gates.] Description [Only collects the gates with unique functionality, which have fewer inputs and shorter delay than the given limits.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mio_CompareTwo( Mio_Cell_t * pCell, Mio_Gate_t * pGate ) { int Comp; float Eps = (float)0.0094636; float CellDelay, GateDelay; // compare areas if ( pCell->Area > (float)pGate->dArea + Eps ) return 1; if ( pCell->Area < (float)pGate->dArea - Eps ) return 0; // compare delays CellDelay = Mio_CellDelayAve( pCell ); GateDelay = Mio_GateDelayAve( pGate ); if ( CellDelay > GateDelay + Eps ) return 1; if ( CellDelay < GateDelay - Eps ) return 0; // compare names Comp = strcmp( pCell->pName, pGate->pName ); if ( Comp > 0 ) return 1; if ( Comp < 0 ) return 0; assert( 0 ); return 0; } static inline void Mio_CollectCopy( Mio_Cell_t * pCell, Mio_Gate_t * pGate ) { Mio_Pin_t * pPin; int k; pCell->pName = pGate->pName; pCell->uTruth = pGate->uTruth; pCell->Area = (float)pGate->dArea; pCell->nFanins = pGate->nInputs; for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ ) pCell->Delays[k] = (float)(0.5 * pPin->dDelayBlockRise + 0.5 * pPin->dDelayBlockFall); } Mio_Cell_t * Mio_CollectRootsNew( Mio_Library_t * pLib, int nInputs, int * pnGates, int fVerbose ) { Mio_Gate_t * pGate; Mio_Cell_t * ppCells; int i, nGates, iCell = 4; nGates = Mio_LibraryReadGateNum( pLib ); ppCells = ABC_CALLOC( Mio_Cell_t, nGates + 4 ); // for each functionality, select gate with the smallest area // if equal areas, select gate with smaller average pin delay // if these are also equal, select lexicographically smaller name Mio_LibraryForEachGate( pLib, pGate ) { if ( pGate->nInputs > nInputs || pGate->pTwin ) // skip large and multi-output continue; // check if the gate with this functionality already exists for ( i = 0; i < iCell; i++ ) if ( ppCells[i].pName && ppCells[i].uTruth == pGate->uTruth ) { if ( Mio_CompareTwo( ppCells + i, pGate ) ) Mio_CollectCopy( ppCells + i, pGate ); break; } if ( i < iCell ) continue; if ( pGate->uTruth == 0 || pGate->uTruth == ~(word)0 ) { int Idx = (int)(pGate->uTruth == ~(word)0); assert( pGate->nInputs == 0 ); Mio_CollectCopy( ppCells + Idx, pGate ); continue; } if ( pGate->uTruth == ABC_CONST(0xAAAAAAAAAAAAAAAA) || pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA) ) { int Idx = 2 + (int)(pGate->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA)); assert( pGate->nInputs == 1 ); Mio_CollectCopy( ppCells + Idx, pGate ); continue; } Mio_CollectCopy( ppCells + iCell++, pGate ); } if ( ppCells[0].pName == NULL ) { printf( "Error: Cannot find constant 0 gate in the library.\n" ); return NULL; } if ( ppCells[1].pName == NULL ) { printf( "Error: Cannot find constant 1 gate in the library.\n" ); return NULL; } if ( ppCells[2].pName == NULL ) { printf( "Error: Cannot find buffer gate in the library.\n" ); return NULL; } if ( ppCells[3].pName == NULL ) { printf( "Error: Cannot find inverter gate in the library.\n" ); return NULL; } // sort by delay if ( iCell > 1 ) { qsort( (void *)(ppCells + 4), iCell - 4, sizeof(Mio_Cell_t), (int (*)(const void *, const void *)) Mio_AreaCompare ); assert( Mio_AreaCompare( ppCells + 4, ppCells + iCell - 1 ) <= 0 ); } // assign IDs for ( i = 0; i < iCell; i++ ) ppCells[i].Id = ppCells[i].pName ? i : -1; // report if ( fVerbose ) { // count gates int * pCounts = ABC_CALLOC( int, nGates + 4 ); Mio_LibraryForEachGate( pLib, pGate ) { if ( pGate->nInputs > nInputs || pGate->pTwin ) // skip large and multi-output continue; for ( i = 0; i < iCell; i++ ) if ( ppCells[i].pName && ppCells[i].uTruth == pGate->uTruth ) { pCounts[i]++; break; } assert( i < iCell ); } for ( i = 0; i < iCell; i++ ) { Mio_Cell_t * pCell = ppCells + i; printf( "%4d : ", i ); if ( pCell->pName == NULL ) printf( "None\n" ); else printf( "%-20s In = %d N = %3d A = %12.6f D = %12.6f\n", pCell->pName, pCell->nFanins, pCounts[i], pCell->Area, Mio_CellDelayAve(pCell) ); } ABC_FREE( pCounts ); } if ( pnGates ) *pnGates = iCell; return ppCells; } Mio_Cell_t * Mio_CollectRootsNewDefault( int nInputs, int * pnGates, int fVerbose ) { return Mio_CollectRootsNew( (Mio_Library_t *)Abc_FrameReadLibGen(), nInputs, pnGates, fVerbose ); } /**Function************************************************************* Synopsis [Collects the set of root gates.] Description [Only collects the gates with unique functionality, which have fewer inputs and shorter delay than the given limits.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mio_CompareTwo2( Mio_Cell2_t * pCell1, Mio_Cell2_t * pCell2 ) { int Comp; // compare areas if ( pCell1->AreaW > pCell2->AreaW ) return 1; if ( pCell1->AreaW < pCell2->AreaW ) return 0; // compare delays if ( pCell1->iDelayAve > pCell2->iDelayAve ) return 1; if ( pCell1->iDelayAve < pCell2->iDelayAve ) return 0; // compare names Comp = strcmp( pCell1->pName, pCell2->pName ); if ( Comp > 0 ) return 1; if ( Comp < 0 ) return 0; assert( 0 ); return 0; } static inline void Mio_CollectCopy2( Mio_Cell2_t * pCell, Mio_Gate_t * pGate ) { Mio_Pin_t * pPin; int k; pCell->pName = pGate->pName; pCell->vExpr = pGate->vExpr; pCell->uTruth = pGate->uTruth; pCell->AreaF = pGate->dArea; pCell->AreaW = (word)(SCL_NUM * pGate->dArea); pCell->nFanins = pGate->nInputs; pCell->pMioGate = pGate; pCell->iDelayAve = 0; for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ ) { pCell->iDelays[k] = (int)(SCL_NUM/2 * pPin->dDelayBlockRise + SCL_NUM/2 * pPin->dDelayBlockFall); pCell->iDelayAve += pCell->iDelays[k]; } if ( pCell->nFanins ) pCell->iDelayAve /= pCell->nFanins; } Mio_Cell2_t * Mio_CollectRootsNew2( Mio_Library_t * pLib, int nInputs, int * pnGates, int fVerbose ) { Mio_Gate_t * pGate0; Mio_Cell2_t * ppCells0, * ppCells, * pCell; int i, nGates, iCell0 = 0, iCell = 4; // create space for new cells nGates = Mio_LibraryReadGateNum( pLib ); ppCells = ABC_CALLOC( Mio_Cell2_t, nGates + 4 ); // copy all gates first ppCells0 = ABC_CALLOC( Mio_Cell2_t, nGates ); Mio_LibraryForEachGate( pLib, pGate0 ) if ( !(pGate0->nInputs > nInputs || pGate0->pTwin) ) // skip large and multi-output Mio_CollectCopy2( ppCells0 + iCell0++, pGate0 ); assert( iCell0 <= nGates ); // for each functionality, select gate with the smallest area // if equal areas, select gate with smaller average pin delay // if these are also equal, select lexicographically smaller name for ( pCell = ppCells0; pCell < ppCells0 + iCell0; pCell++ ) { // check if the gate with this functionality already exists for ( i = 0; i < iCell; i++ ) if ( ppCells[i].pName && ppCells[i].uTruth == pCell->uTruth ) { if ( Mio_CompareTwo2( ppCells + i, pCell ) ) ppCells[i] = *pCell; break; } if ( i < iCell ) continue; if ( pCell->uTruth == 0 || pCell->uTruth == ~(word)0 ) { int Idx = (int)(pCell->uTruth == ~(word)0); assert( pCell->nFanins == 0 ); ppCells[Idx] = *pCell; continue; } if ( pCell->uTruth == ABC_CONST(0xAAAAAAAAAAAAAAAA) || pCell->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA) ) { int Idx = 2 + (int)(pCell->uTruth == ~ABC_CONST(0xAAAAAAAAAAAAAAAA)); assert( pCell->nFanins == 1 ); ppCells[Idx] = *pCell; continue; } ppCells[iCell++] = *pCell; } ABC_FREE( ppCells0 ); if ( ppCells[0].pName == NULL ) { printf( "Error: Cannot find constant 0 gate in the library.\n" ); return NULL; } if ( ppCells[1].pName == NULL ) { printf( "Error: Cannot find constant 1 gate in the library.\n" ); return NULL; } if ( ppCells[2].pName == NULL ) { printf( "Error: Cannot find buffer gate in the library.\n" ); return NULL; } if ( ppCells[3].pName == NULL ) { printf( "Error: Cannot find inverter gate in the library.\n" ); return NULL; } // sort by delay if ( iCell > 1 ) { qsort( (void *)(ppCells + 4), iCell - 4, sizeof(Mio_Cell2_t), (int (*)(const void *, const void *)) Mio_AreaCompare2 ); assert( Mio_AreaCompare2( ppCells + 4, ppCells + iCell - 1 ) <= 0 ); } // assign IDs Mio_LibraryForEachGate( pLib, pGate0 ) Mio_GateSetCell( pGate0, -1 ); for ( i = 0; i < iCell; i++ ) { ppCells[i].Id = ppCells[i].pName ? i : -1; Mio_GateSetCell( (Mio_Gate_t *)ppCells[i].pMioGate, i ); } // report if ( fVerbose ) { // count gates int * pCounts = ABC_CALLOC( int, nGates + 4 ); Mio_LibraryForEachGate( pLib, pGate0 ) { if ( pGate0->nInputs > nInputs || pGate0->pTwin ) // skip large and multi-output continue; for ( i = 0; i < iCell; i++ ) if ( ppCells[i].pName && ppCells[i].uTruth == pGate0->uTruth ) { pCounts[i]++; break; } assert( i < iCell ); } for ( i = 0; i < iCell; i++ ) { Mio_Cell2_t * pCell = ppCells + i; printf( "%4d : ", i ); if ( pCell->pName == NULL ) printf( "None\n" ); else printf( "%-20s In = %d N = %3d A = %12.6f D = %12.6f\n", pCell->pName, pCell->nFanins, pCounts[i], pCell->AreaF, Scl_Int2Flt(pCell->iDelayAve) ); } ABC_FREE( pCounts ); } if ( pnGates ) *pnGates = iCell; return ppCells; } Mio_Cell2_t * Mio_CollectRootsNewDefault2( int nInputs, int * pnGates, int fVerbose ) { return Mio_CollectRootsNew2( (Mio_Library_t *)Abc_FrameReadLibGen(), nInputs, pnGates, fVerbose ); } /**Function************************************************************* Synopsis [Derives the truth table of the gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Mio_DeriveTruthTable6( Mio_Gate_t * pGate ) { static unsigned uTruths6[6][2] = { { 0xAAAAAAAA, 0xAAAAAAAA }, { 0xCCCCCCCC, 0xCCCCCCCC }, { 0xF0F0F0F0, 0xF0F0F0F0 }, { 0xFF00FF00, 0xFF00FF00 }, { 0xFFFF0000, 0xFFFF0000 }, { 0x00000000, 0xFFFFFFFF } }; union { unsigned u[2]; word w; } uTruthRes; assert( pGate->nInputs <= 6 ); Mio_DeriveTruthTable( pGate, uTruths6, pGate->nInputs, 6, uTruthRes.u ); return uTruthRes.w; } #if 0 /**Function************************************************************* Synopsis [Recursively derives the truth table of the gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] ) { unsigned uTruthsCof0[2]; unsigned uTruthsCof1[2]; // complement the resulting truth table, if the function is complemented if ( Cudd_IsComplement(bFunc) ) { Mio_DeriveTruthTable_rec( Cudd_Not(bFunc), uTruthsIn, uTruthRes ); uTruthRes[0] = ~uTruthRes[0]; uTruthRes[1] = ~uTruthRes[1]; return; } // if the function is constant 1, return the constant 1 truth table if ( bFunc->index == CUDD_CONST_INDEX ) { uTruthRes[0] = MIO_FULL; uTruthRes[1] = MIO_FULL; return; } // solve the problem for both cofactors Mio_DeriveTruthTable_rec( cuddE(bFunc), uTruthsIn, uTruthsCof0 ); Mio_DeriveTruthTable_rec( cuddT(bFunc), uTruthsIn, uTruthsCof1 ); // derive the resulting truth table using the input truth tables uTruthRes[0] = (uTruthsCof0[0] & ~uTruthsIn[bFunc->index][0]) | (uTruthsCof1[0] & uTruthsIn[bFunc->index][0]); uTruthRes[1] = (uTruthsCof0[1] & ~uTruthsIn[bFunc->index][1]) | (uTruthsCof1[1] & uTruthsIn[bFunc->index][1]); } /**Function************************************************************* Synopsis [Derives the truth table of the gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] ) { Mio_DeriveTruthTable_rec( pGate->bFunc, uTruthsIn, uTruthRes ); } #endif /**Function************************************************************* Synopsis [Derives the truth table of the gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] ) { word uRes, uFanins[6]; int i; assert( pGate->nInputs == nSigns ); for ( i = 0; i < nSigns; i++ ) uFanins[i] = (((word)uTruthsIn[i][1]) << 32) | (word)uTruthsIn[i][0]; uRes = Exp_Truth6( nSigns, pGate->vExpr, (word *)uFanins ); uTruthRes[0] = uRes & 0xFFFFFFFF; uTruthRes[1] = uRes >> 32; } /**Function************************************************************* Synopsis [Reads the number of variables in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mio_SopGetVarNum( char * pSop ) { char * pCur; for ( pCur = pSop; *pCur != '\n'; pCur++ ) if ( *pCur == 0 ) return -1; return pCur - pSop - 2; } /**Function************************************************************* Synopsis [Derives the truth table of the root of the gate.] Description [Given the truth tables of the leaves of the gate, this procedure derives the truth table of the root.] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_DeriveTruthTable2( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nTruths, int nInputs, unsigned uTruthRes[] ) { unsigned uSignCube[2]; int i, nFanins; char * pCube; // make sure that the number of input truth tables in equal to the number of gate inputs assert( pGate->nInputs == nTruths ); assert( nInputs < 7 ); nFanins = Mio_SopGetVarNum( pGate->pSop ); assert( nFanins == nInputs ); // clean the resulting truth table uTruthRes[0] = 0; uTruthRes[1] = 0; if ( nInputs < 6 ) { // Abc_SopForEachCube( pGate->pSop, nFanins, pCube ) for ( pCube = pGate->pSop; *pCube; pCube += (nFanins) + 3 ) { // add the clause uSignCube[0] = MIO_FULL; for ( i = 0; i < nFanins; i++ ) { if ( pCube[i] == '0' ) uSignCube[0] &= ~uTruthsIn[i][0]; else if ( pCube[i] == '1' ) uSignCube[0] &= uTruthsIn[i][0]; } } if ( nInputs < 5 ) uTruthRes[0] &= MIO_MASK(1<pSop, nFanins, pCube ) for ( pCube = pGate->pSop; *pCube; pCube += (nFanins) + 3 ) { uSignCube[0] = MIO_FULL; uSignCube[1] = MIO_FULL; for ( i = 0; i < nFanins; i++ ) { if ( pCube[i] == '0' ) { uSignCube[0] &= ~uTruthsIn[i][0]; uSignCube[1] &= ~uTruthsIn[i][1]; } else if ( pCube[i] == '1' ) { uSignCube[0] &= uTruthsIn[i][0]; uSignCube[1] &= uTruthsIn[i][1]; } } uTruthRes[0] |= uSignCube[0]; uTruthRes[1] |= uSignCube[1]; } } } /**Function************************************************************* Synopsis [Derives the area and delay of the root of the gate.] Description [Array of the resulting delays should be initialized to the (negative) SUPER_NO_VAR value.] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_DeriveGateDelays( Mio_Gate_t * pGate, float ** ptPinDelays, int nPins, int nInputs, float tDelayZero, float * ptDelaysRes, float * ptPinDelayMax ) { Mio_Pin_t * pPin; float Delay, DelayMax; int i, k; assert( pGate->nInputs == nPins ); // set all the delays to the unused delay for ( i = 0; i < nInputs; i++ ) ptDelaysRes[i] = tDelayZero; // compute the delays for each input and the max delay at the same time DelayMax = 0; for ( i = 0; i < nInputs; i++ ) { for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ ) { if ( ptPinDelays[k][i] < 0 ) continue; Delay = ptPinDelays[k][i] + (float)pPin->dDelayBlockMax; if ( ptDelaysRes[i] < Delay ) ptDelaysRes[i] = Delay; } if ( k != nPins ) { printf ("DEBUG: problem gate is %s\n", Mio_GateReadName( pGate )); } assert( k == nPins ); if ( DelayMax < ptDelaysRes[i] ) DelayMax = ptDelaysRes[i]; } *ptPinDelayMax = DelayMax; } /**Function************************************************************* Synopsis [Creates a pseudo-gate.] Description [The pseudo-gate is a N-input gate with all info set to 0.] SideEffects [] SeeAlso [] ***********************************************************************/ Mio_Gate_t * Mio_GateCreatePseudo( int nInputs ) { Mio_Gate_t * pGate; Mio_Pin_t * pPin; int i; // allocate the gate structure pGate = ABC_ALLOC( Mio_Gate_t, 1 ); memset( pGate, 0, sizeof(Mio_Gate_t) ); pGate->nInputs = nInputs; // create pins for ( i = 0; i < nInputs; i++ ) { pPin = ABC_ALLOC( Mio_Pin_t, 1 ); memset( pPin, 0, sizeof(Mio_Pin_t) ); pPin->pNext = pGate->pPins; pGate->pPins = pPin; } return pGate; } /**Function************************************************************* Synopsis [Adds constant value to all delay values.] Description [The pseudo-gate is a N-input gate with all info set to 0.] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibraryShiftDelay( Mio_Library_t * pLib, double Shift ) { Mio_Gate_t * pGate; Mio_Pin_t * pPin; Mio_LibraryForEachGate( pLib, pGate ) { pGate->dDelayMax += Shift; Mio_GateForEachPin( pGate, pPin ) { pPin->dDelayBlockRise += Shift; pPin->dDelayBlockFall += Shift; pPin->dDelayBlockMax += Shift; } } } /**Function************************************************************* Synopsis [Multiply areas/delays by values proportional to fanin count.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibraryMultiArea( Mio_Library_t * pLib, double Multi ) { Mio_Gate_t * pGate; Mio_LibraryForEachGate( pLib, pGate ) { if ( pGate->nInputs < 2 ) continue; // printf( "Before %8.3f ", pGate->dArea ); pGate->dArea *= pow( pGate->nInputs, Multi ); // printf( "After %8.3f Inputs = %d. Factor = %8.3f\n", pGate->dArea, pGate->nInputs, pow( pGate->nInputs, Multi ) ); } } void Mio_LibraryMultiDelay( Mio_Library_t * pLib, double Multi ) { Mio_Gate_t * pGate; Mio_Pin_t * pPin; Mio_LibraryForEachGate( pLib, pGate ) { if ( pGate->nInputs < 2 ) continue; // printf( "Before %8.3f ", pGate->dDelayMax ); pGate->dDelayMax *= pow( pGate->nInputs, Multi ); // printf( "After %8.3f Inputs = %d. Factor = %8.3f\n", pGate->dDelayMax, pGate->nInputs, pow( pGate->nInputs, Multi ) ); Mio_GateForEachPin( pGate, pPin ) { pPin->dDelayBlockRise *= pow( pGate->nInputs, Multi ); pPin->dDelayBlockFall *= pow( pGate->nInputs, Multi ); pPin->dDelayBlockMax *= pow( pGate->nInputs, Multi ); } } } /**Function************************************************************* Synopsis [Transfers delays from the second to the first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibraryTransferDelays( Mio_Library_t * pLibD, Mio_Library_t * pLibS ) { Mio_Gate_t * pGateD, * pGateS; Mio_Pin_t * pPinD, * pPinS; Mio_LibraryForEachGate( pLibS, pGateS ) { Mio_LibraryForEachGate( pLibD, pGateD ) { if ( pGateD->uTruth != pGateS->uTruth ) continue; pPinS = Mio_GateReadPins( pGateS ); Mio_GateForEachPin( pGateD, pPinD ) { if (pPinS) { pPinD->dDelayBlockRise = pPinS->dDelayBlockRise; pPinD->dDelayBlockFall = pPinS->dDelayBlockFall; pPinD->dDelayBlockMax = pPinS->dDelayBlockMax; pPinS = Mio_PinReadNext(pPinS); } else { pPinD->dDelayBlockRise = 0; pPinD->dDelayBlockFall = 0; pPinD->dDelayBlockMax = 0; } } } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nf_ManPrepareGate( int nVars, word uTruth, int * pComp, int * pPerm, Vec_Wrd_t * vResult ) { int nPerms = Extra_Factorial( nVars ); int nMints = (1 << nVars); word tCur, tTemp1, tTemp2; int i, p, c; Vec_WrdClear( vResult ); for ( i = 0; i < 2; i++ ) { tCur = i ? ~uTruth : uTruth; tTemp1 = tCur; for ( p = 0; p < nPerms; p++ ) { tTemp2 = tCur; for ( c = 0; c < nMints; c++ ) { Vec_WrdPush( vResult, tCur ); tCur = Abc_Tt6Flip( tCur, pComp[c] ); } assert( tTemp2 == tCur ); tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[p] ); } assert( tTemp1 == tCur ); } } void Nf_ManPreparePrint( int nVars, int * pComp, int * pPerm, char Line[2*720*64][8] ) { int nPerms = Extra_Factorial( nVars ); int nMints = (1 << nVars); char * pChar, * pChar2; int i, p, c, n = 0; for ( i = 0; i < nVars; i++ ) Line[0][i] = 'A' + nVars - 1 - i; Line[0][nVars] = '+'; Line[0][nVars+1] = 0; for ( i = 0; i < 2; i++ ) { Line[n][nVars] = i ? '-' : '+'; for ( p = 0; p < nPerms; p++ ) { for ( c = 0; c < nMints; c++ ) { strcpy( Line[n+1], Line[n] ); n++; pChar = &Line[n][pComp[c]]; if ( *pChar >= 'A' && *pChar <= 'Z' ) *pChar += 'a' - 'A'; else if ( *pChar >= 'a' && *pChar <= 'z' ) *pChar -= 'a' - 'A'; } pChar = &Line[n][pPerm[p]]; pChar2 = pChar + 1; ABC_SWAP( char, *pChar, *pChar2 ); } } assert( n == 2*nPerms*nMints ); n = 0; for ( i = 0; i < 2; i++ ) for ( p = 0; p < nPerms; p++ ) for ( c = 0; c < nMints; c++ ) printf("%8d : %d %3d %2d : %s\n", n, i, p, c, Line[n]), n++; } void Nf_ManPrepareLibrary( Mio_Library_t * pLib ) { // char Lines[2*720*64][8]; // Nf_ManPreparePrint( 6, pComp, pPerm, Lines ); int * pComp[7]; int * pPerm[7]; Mio_Gate_t ** ppGates; Vec_Wrd_t * vResult; word * pTruths; int * pSizes; int nGates, i, nClasses = 0, nTotal; abctime clk = Abc_Clock(); for ( i = 2; i <= 6; i++ ) pComp[i] = Extra_GreyCodeSchedule( i ); for ( i = 2; i <= 6; i++ ) pPerm[i] = Extra_PermSchedule( i ); // collect truth tables ppGates = Mio_CollectRoots( pLib, 6, (float)1.0e+20, 1, &nGates, 0 ); pSizes = ABC_CALLOC( int, nGates ); pTruths = ABC_CALLOC( word, nGates ); vResult = Vec_WrdAlloc( 2 * 720 * 64 ); for ( i = 0; i < nGates; i++ ) { pSizes[i] = Mio_GateReadPinNum( ppGates[i] ); assert( pSizes[i] > 1 && pSizes[i] <= 6 ); pTruths[i] = Mio_GateReadTruth( ppGates[i] ); Nf_ManPrepareGate( pSizes[i], pTruths[i], pComp[pSizes[i]], pPerm[pSizes[i]], vResult ); Vec_WrdUniqify(vResult); nClasses += Vec_WrdSize(vResult); nTotal = (1 << (pSizes[i]+1)) * Extra_Factorial(pSizes[i]); printf( "%6d : ", i ); printf( "%16s : ", Mio_GateReadName( ppGates[i] ) ); printf( "%48s : ", Mio_GateReadForm( ppGates[i] ) ); printf( "Inputs = %2d ", pSizes[i] ); printf( "Total = %6d ", nTotal ); printf( "Classes = %6d ", Vec_WrdSize(vResult) ); printf( "Configs = %8.2f ", 1.0*nTotal/Vec_WrdSize(vResult) ); printf( "%6.2f %% ", 100.0*Vec_WrdSize(vResult)/nTotal ); Dau_DsdPrintFromTruth( &pTruths[i], pSizes[i] ); // printf( "\n" ); } Vec_WrdFree( vResult ); ABC_FREE( ppGates ); ABC_FREE( pSizes ); ABC_FREE( pTruths ); for ( i = 2; i <= 6; i++ ) ABC_FREE( pComp[i] ); for ( i = 2; i <= 6; i++ ) ABC_FREE( pPerm[i] ); printf( "Classes = %d. ", nClasses ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } void Nf_ManPrepareLibraryTest2() { Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pLib != NULL ) Nf_ManPrepareLibrary( pLib ); else printf( "Standard cell library is not available.\n" ); } /**Function************************************************************* Synopsis [Install library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibraryTransferCellIds() { Mio_Gate_t * pGate; Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); SC_Lib * pScl = (SC_Lib *)Abc_FrameReadLibScl(); int CellId; if ( pScl == NULL ) { printf( "SC library cannot be found.\n" ); return; } if ( pLib == NULL ) { printf( "Genlib library cannot be found.\n" ); return; } Mio_LibraryForEachGate( pLib, pGate ) { if ( Mio_GateReadPinNum(pGate) == 0 ) continue; CellId = Abc_SclCellFind( pScl, Mio_GateReadName(pGate) ); if ( CellId < 0 ) printf( "Cannot find cell ID of gate %s.\n", Mio_GateReadName(pGate) ); else Mio_GateSetCell( pGate, CellId ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibraryReadProfile( FILE * pFile, Mio_Library_t * pLib ) { Mio_Gate_t * pGate; char pBuffer[1000]; while ( fgets( pBuffer, 1000, pFile ) != NULL ) { char * pToken = strtok( pBuffer, " \t\n" ); if ( pToken == NULL ) continue; if ( pToken[0] == '#' ) continue; // read gate pGate = Mio_LibraryReadGateByName( pLib, pToken, NULL ); if ( pGate == NULL ) { printf( "Cannot find gate \"%s\" in library \"%s\".\n", pToken, Mio_LibraryReadName(pLib) ); continue; } // read profile pToken = strtok( NULL, " \t\n" ); Mio_GateSetProfile( pGate, atoi(pToken) ); } } void Mio_LibraryWriteProfile( FILE * pFile, Mio_Library_t * pLib ) { Mio_Gate_t * pGate; Mio_LibraryForEachGate( pLib, pGate ) if ( Mio_GateReadProfile(pGate) > 0 ) fprintf( pFile, "%-24s %6d\n", Mio_GateReadName(pGate), Mio_GateReadProfile(pGate) ); } int Mio_LibraryHasProfile( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; Mio_LibraryForEachGate( pLib, pGate ) if ( Mio_GateReadProfile(pGate) > 0 ) return 1; return 0; } void Mio_LibraryTransferProfile( Mio_Library_t * pLibDst, Mio_Library_t * pLibSrc ) { Mio_Gate_t * pGateSrc, * pGateDst; Mio_LibraryForEachGate( pLibDst, pGateDst ) Mio_GateSetProfile( pGateDst, 0 ); Mio_LibraryForEachGate( pLibSrc, pGateSrc ) if ( Mio_GateReadProfile(pGateSrc) > 0 ) { // find gate by name pGateDst = Mio_LibraryReadGateByName( pLibDst, Mio_GateReadName(pGateSrc), NULL ); if ( pGateDst == NULL ) { // find gate by function Mio_LibraryForEachGate( pLibDst, pGateDst ) if ( pGateDst->uTruth == pGateSrc->uTruth ) break; if ( pGateDst == NULL ) { printf( "Cannot find gate \"%s\" in library \"%s\".\n", Mio_GateReadName(pGateSrc), Mio_LibraryReadName(pLibDst) ); continue; } } Mio_GateAddToProfile( pGateDst, Mio_GateReadProfile(pGateSrc) ); } } void Mio_LibraryTransferProfile2( Mio_Library_t * pLibDst, Mio_Library_t * pLibSrc ) { Mio_Gate_t * pGateSrc, * pGateDst; Mio_LibraryForEachGate( pLibDst, pGateDst ) Mio_GateSetProfile2( pGateDst, 0 ); Mio_LibraryForEachGate( pLibSrc, pGateSrc ) if ( Mio_GateReadProfile2(pGateSrc) > 0 ) { // find gate by name pGateDst = Mio_LibraryReadGateByName( pLibDst, Mio_GateReadName(pGateSrc), NULL ); if ( pGateDst == NULL ) { // find gate by function Mio_LibraryForEachGate( pLibDst, pGateDst ) if ( pGateDst->uTruth == pGateSrc->uTruth ) break; if ( pGateDst == NULL ) { printf( "Cannot find gate \"%s\" in library \"%s\".\n", Mio_GateReadName(pGateSrc), Mio_LibraryReadName(pLibDst) ); continue; } } Mio_GateAddToProfile2( pGateDst, Mio_GateReadProfile2(pGateSrc) ); } } void Mio_LibraryCleanProfile2( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; Mio_LibraryForEachGate( pLib, pGate ) Mio_GateSetProfile2( pGate, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibraryHashGates( Mio_Library_t * pLib ) { Mio_Gate_t * pGate; Mio_LibraryForEachGate( pLib, pGate ) if ( pGate->pTwin ) { printf( "Gates with multiple outputs are not supported.\n" ); return; } if ( pLib->tName2Gate ) st__free_table( pLib->tName2Gate ); pLib->tName2Gate = st__init_table(strcmp, st__strhash); Mio_LibraryForEachGate( pLib, pGate ) st__insert( pLib->tName2Gate, pGate->pName, (char *)pGate ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_SclIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } static inline int Abc_SclIsName( char c ) { return Abc_SclIsChar(c) || (c >= '0' && c <= '9'); } static inline char * Abc_SclFindLimit( char * pName ) { assert( Abc_SclIsChar(*pName) ); while ( Abc_SclIsName(*pName) ) pName++; return pName; } static inline int Abc_SclAreEqual( char * pBase, char * pName, char * pLimit ) { return !strncmp( pBase, pName, pLimit - pName ); } void Mio_LibraryShortFormula( Mio_Gate_t * pCell, char * pForm, char * pBuffer ) { Mio_Pin_t * pPin; char * pTemp, * pLimit; int i; if ( !strncmp(pForm, "CONST", 5) ) { sprintf( pBuffer, "%s", pForm ); return; } for ( pTemp = pForm; *pTemp; ) { if ( !Abc_SclIsChar(*pTemp) ) { *pBuffer++ = *pTemp++; continue; } pLimit = Abc_SclFindLimit( pTemp ); i = 0; Mio_GateForEachPin( pCell, pPin ) { if ( Abc_SclAreEqual( pPin->pName, pTemp, pLimit ) ) { *pBuffer++ = 'a' + i; break; } i++; } pTemp = pLimit; } *pBuffer++ = 0; } void Mio_LibraryShortNames( Mio_Library_t * pLib ) { char Buffer[10000]; Mio_Gate_t * pGate; Mio_Pin_t * pPin; int c = 0, i, nDigits = Abc_Base10Log( Mio_LibraryReadGateNum(pLib) ); // itereate through classes Mio_LibraryForEachGate( pLib, pGate ) { ABC_FREE( pGate->pName ); sprintf( Buffer, "g%0*d", nDigits, ++c ); pGate->pName = Abc_UtilStrsav( Buffer ); // update formula Mio_LibraryShortFormula( pGate, pGate->pForm, Buffer ); ABC_FREE( pGate->pForm ); pGate->pForm = Abc_UtilStrsav( Buffer ); // pin names i = 0; Mio_GateForEachPin( pGate, pPin ) { ABC_FREE( pPin->pName ); sprintf( Buffer, "%c", 'a'+i ); pPin->pName = Abc_UtilStrsav( Buffer ); i++; } // output pin ABC_FREE( pGate->pOutName ); sprintf( Buffer, "z" ); pGate->pOutName = Abc_UtilStrsav( Buffer ); } Mio_LibraryHashGates( pLib ); // update library name printf( "Renaming library \"%s\" into \"%s%d\".\n", pLib->pName, "lib", Mio_LibraryReadGateNum(pLib) ); ABC_FREE( pLib->pName ); sprintf( Buffer, "lib%d", Mio_LibraryReadGateNum(pLib) ); pLib->pName = Abc_UtilStrsav( Buffer ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mio_LibraryMatchesStop( Mio_Library_t * pLib ) { if ( !pLib->vTtMem ) return; Vec_WecFree( pLib->vTt2Match ); Vec_MemHashFree( pLib->vTtMem ); Vec_MemFree( pLib->vTtMem ); ABC_FREE( pLib->pCells ); } void Mio_LibraryMatchesStart( Mio_Library_t * pLib, int fPinFilter, int fPinPerm, int fPinQuick ) { extern Mio_Cell2_t * Nf_StoDeriveMatches( Vec_Mem_t * vTtMem, Vec_Wec_t * vTt2Match, int * pnCells, int fPinFilter, int fPinPerm, int fPinQuick ); if ( pLib->vTtMem && pLib->fPinFilter == fPinFilter && pLib->fPinPerm == fPinPerm && pLib->fPinQuick == fPinQuick ) return; if ( pLib->vTtMem ) Mio_LibraryMatchesStop( pLib ); pLib->fPinFilter = fPinFilter; // pin filtering pLib->fPinPerm = fPinPerm; // pin permutation pLib->fPinQuick = fPinQuick; // pin permutation pLib->vTtMem = Vec_MemAllocForTT( 6, 0 ); pLib->vTt2Match = Vec_WecAlloc( 1000 ); Vec_WecPushLevel( pLib->vTt2Match ); Vec_WecPushLevel( pLib->vTt2Match ); assert( Vec_WecSize(pLib->vTt2Match) == Vec_MemEntryNum(pLib->vTtMem) ); pLib->pCells = Nf_StoDeriveMatches( pLib->vTtMem, pLib->vTt2Match, &pLib->nCells, fPinFilter, fPinPerm, fPinQuick ); } void Mio_LibraryMatchesFetch( Mio_Library_t * pLib, Vec_Mem_t ** pvTtMem, Vec_Wec_t ** pvTt2Match, Mio_Cell2_t ** ppCells, int * pnCells, int fPinFilter, int fPinPerm, int fPinQuick ) { Mio_LibraryMatchesStart( pLib, fPinFilter, fPinPerm, fPinQuick ); *pvTtMem = pLib->vTtMem; // truth tables *pvTt2Match = pLib->vTt2Match; // matches for truth tables *ppCells = pLib->pCells; // library gates *pnCells = pLib->nCells; // library gate count } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mio/module.make000066400000000000000000000002601300674244400235170ustar00rootroot00000000000000SRC += src/map/mio/mio.c \ src/map/mio/mioApi.c \ src/map/mio/mioFunc.c \ src/map/mio/mioParse.c \ src/map/mio/mioRead.c \ src/map/mio/mioSop.c \ src/map/mio/mioUtils.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/000077500000000000000000000000001300674244400214025ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/module.make000066400000000000000000000004241300674244400235260ustar00rootroot00000000000000SRC += src/map/mpm/mpmAbc.c \ src/map/mpm/mpmCore.c \ src/map/mpm/mpmDsd.c \ src/map/mpm/mpmGates.c \ src/map/mpm/mpmLib.c \ src/map/mpm/mpmMan.c \ src/map/mpm/mpmMap.c \ src/map/mpm/mpmMig.c \ src/map/mpm/mpmPre.c \ src/map/mpm/mpmTruth.c \ src/map/mpm/mpmUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpm.c000066400000000000000000000027071300674244400223450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpm.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mpm_ManTest() { } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpm.h000066400000000000000000000066531300674244400223560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpm.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpm.h,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__mpm__h #define ABC__map__mpm__h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #define MPM_VAR_MAX 12 //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Mpm_LibLut_t_ Mpm_LibLut_t; struct Mpm_LibLut_t_ { char * pName; // the name of the LUT library int LutMax; // the maximum LUT size int fVarPinDelays; // set to 1 if variable pin delays are specified int pLutAreas[MPM_VAR_MAX+1]; // the areas of LUTs int pLutDelays[MPM_VAR_MAX+1][MPM_VAR_MAX+1]; // the delays of LUTs }; typedef struct Mpm_Par_t_ Mpm_Par_t; struct Mpm_Par_t_ { Mpm_LibLut_t * pLib; void * pScl; int nNumCuts; int DelayTarget; int fUseGates; int fUseTruth; int fUseDsd; int fCutMin; int fOneRound; int fDeriveLuts; int fMap4Cnf; int fMap4Aig; int fMap4Gates; int fVerbose; int fVeryVerbose; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== mpmCore.c ===========================================================*/ extern void Mpm_ManSetParsDefault( Mpm_Par_t * p ); /*=== mpmLib.c ===========================================================*/ extern Mpm_LibLut_t * Mpm_LibLutSetSimple( int nLutSize ); extern void Mpm_LibLutFree( Mpm_LibLut_t * pLib ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmAbc.c000066400000000000000000000324431300674244400227530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmAbc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Interface with ABC data structures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmAbc.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig/gia/gia.h" #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mig_ManCreateChoices( Mig_Man_t * pMig, Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; assert( Mig_ManObjNum(pMig) == Gia_ManObjNum(p) ); assert( Vec_IntSize(&pMig->vSibls) == 0 ); Vec_IntFill( &pMig->vSibls, Gia_ManObjNum(p), 0 ); Gia_ManMarkFanoutDrivers( p ); Gia_ManForEachObj( p, pObj, i ) { Gia_ObjSetPhase( p, pObj ); assert( Abc_Lit2Var(pObj->Value) == i ); Mig_ObjSetPhase( Mig_ManObj(pMig, i), pObj->fPhase ); 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)) ) Mig_ObjSetSiblId( Mig_ManObj(pMig, Abc_Lit2Var(pPrev->Value)), Abc_Lit2Var(pSibl->Value) ); pMig->nChoices++; } } Gia_ManCleanMark0( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mig_ObjFanin0Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } static inline int Mig_ObjFanin1Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); } Mig_Man_t * Mig_ManCreate( void * pGia ) { Gia_Man_t * p = (Gia_Man_t *)pGia; Mig_Man_t * pNew; Gia_Obj_t * pObj; int i; pNew = Mig_ManStart(); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsMuxId(p, i) ) pObj->Value = Mig_ManAppendMux( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin2Copy(p, pObj) ); else if ( Gia_ObjIsXor(pObj) ) pObj->Value = Mig_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Mig_ManAppendAnd( pNew, Mig_ObjFanin0Copy(pObj), Mig_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = Mig_ManAppendCi( pNew ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Mig_ManAppendCo( pNew, Mig_ObjFanin0Copy(pObj) ); else assert( 0 ); } Mig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); if ( Gia_ManHasChoices(p) ) Mig_ManCreateChoices( pNew, p ); return pNew; } /**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Mpm_CutDataInt( Mpm_Cut_t * pCut ) { return pCut->hNext; } static inline void Mpm_CutSetDataInt( Mpm_Cut_t * pCut, int Data ) { pCut->hNext = Data; } int Mpm_ManNodeIfToGia_rec( Gia_Man_t * pNew, Mpm_Man_t * pMan, Mig_Obj_t * pObj, Vec_Ptr_t * vVisited, int fHash ) { Mig_Obj_t * pTemp; Mpm_Cut_t * pCut; int iFunc, iFunc0, iFunc1, iFunc2 = 0; assert( fHash == 0 ); // get the best cut pCut = Mpm_ObjCutBestP( pMan, pObj ); // if the cut is visited, return the result if ( Mpm_CutDataInt(pCut) ) return Mpm_CutDataInt(pCut); // mark the node as visited Vec_PtrPush( vVisited, pCut ); // insert the worst case Mpm_CutSetDataInt( pCut, ~0 ); // skip in case of primary input if ( Mig_ObjIsCi(pObj) ) return Mpm_CutDataInt(pCut); // compute the functions of the children for ( pTemp = pObj; pTemp; pTemp = Mig_ObjSibl(pTemp) ) { iFunc0 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin0(pTemp), vVisited, fHash ); if ( iFunc0 == ~0 ) continue; iFunc1 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin1(pTemp), vVisited, fHash ); if ( iFunc1 == ~0 ) continue; if ( Mig_ObjIsNode3(pTemp) ) { iFunc2 = Mpm_ManNodeIfToGia_rec( pNew, pMan, Mig_ObjFanin2(pTemp), vVisited, fHash ); if ( iFunc2 == ~0 ) continue; iFunc2 = Abc_LitNotCond(iFunc2, Mig_ObjFaninC2(pTemp)); } iFunc0 = Abc_LitNotCond(iFunc0, Mig_ObjFaninC0(pTemp)); iFunc1 = Abc_LitNotCond(iFunc1, Mig_ObjFaninC1(pTemp)); // both branches are solved if ( fHash ) { if ( Mig_ObjIsMux(pTemp) ) iFunc = Gia_ManHashMux( pNew, iFunc2, iFunc1, iFunc0 ); else if ( Mig_ObjIsXor(pTemp) ) iFunc = Gia_ManHashXor( pNew, iFunc0, iFunc1 ); else iFunc = Gia_ManHashAnd( pNew, iFunc0, iFunc1 ); } else { if ( Mig_ObjIsMux(pTemp) ) iFunc = Gia_ManAppendMux( pNew, iFunc2, iFunc1, iFunc0 ); else if ( Mig_ObjIsXor(pTemp) ) iFunc = Gia_ManAppendXor( pNew, iFunc0, iFunc1 ); else iFunc = Gia_ManAppendAnd( pNew, iFunc0, iFunc1 ); } if ( Mig_ObjPhase(pTemp) != Mig_ObjPhase(pObj) ) iFunc = Abc_LitNot(iFunc); Mpm_CutSetDataInt( pCut, iFunc ); break; } return Mpm_CutDataInt(pCut); } int Mpm_ManNodeIfToGia( Gia_Man_t * pNew, Mpm_Man_t * pMan, Mig_Obj_t * pObj, Vec_Int_t * vLeaves, int fHash ) { Mpm_Cut_t * pCut; Mig_Obj_t * pFanin; int i, iRes; // get the best cut pCut = Mpm_ObjCutBestP( pMan, pObj ); assert( pCut->nLeaves > 1 ); // set the leaf variables Mpm_CutForEachLeaf( pMan->pMig, pCut, pFanin, i ) Mpm_CutSetDataInt( Mpm_ObjCutBestP(pMan, pFanin), Vec_IntEntry(vLeaves, i) ); // recursively compute the function while collecting visited cuts Vec_PtrClear( pMan->vTemp ); iRes = Mpm_ManNodeIfToGia_rec( pNew, pMan, pObj, pMan->vTemp, fHash ); if ( iRes == ~0 ) { Abc_Print( -1, "Mpm_ManNodeIfToGia(): Computing local AIG has failed.\n" ); return ~0; } // clean the cuts Mpm_CutForEachLeaf( pMan->pMig, pCut, pFanin, i ) Mpm_CutSetDataInt( Mpm_ObjCutBestP(pMan, pFanin), 0 ); Vec_PtrForEachEntry( Mpm_Cut_t *, pMan->vTemp, pCut, i ) Mpm_CutSetDataInt( pCut, 0 ); return iRes; } void * Mpm_ManFromIfLogic( Mpm_Man_t * pMan ) { Gia_Man_t * pNew; Mpm_Cut_t * pCutBest; Mig_Obj_t * pObj, * pFanin; Vec_Int_t * vMapping, * vMapping2, * vPacking = NULL; Vec_Int_t * vLeaves, * vLeaves2, * vCover; word uTruth, * pTruth = &uTruth; int i, k, Entry, iLitNew; // assert( !pMan->pPars->fDeriveLuts || pMan->pPars->fTruth ); // start mapping and packing vMapping = Vec_IntStart( Mig_ManObjNum(pMan->pMig) ); vMapping2 = Vec_IntStart( 1 ); if ( 0 ) // pMan->pPars->fDeriveLuts && pMan->pPars->pLutStruct ) { vPacking = Vec_IntAlloc( 1000 ); Vec_IntPush( vPacking, 0 ); } // create new manager pNew = Gia_ManStart( Mig_ManObjNum(pMan->pMig) ); // iterate through nodes used in the mapping vCover = Vec_IntAlloc( 1 << 16 ); vLeaves = Vec_IntAlloc( 16 ); vLeaves2 = Vec_IntAlloc( 16 ); Mig_ManCleanCopy( pMan->pMig ); Mig_ManForEachObj( pMan->pMig, pObj ) { if ( !Mpm_ObjMapRef(pMan, pObj) && !Mig_ObjIsTerm(pObj) ) continue; if ( Mig_ObjIsNode(pObj) ) { // collect leaves of the best cut Vec_IntClear( vLeaves ); pCutBest = Mpm_ObjCutBestP( pMan, pObj ); Mpm_CutForEachLeaf( pMan->pMig, pCutBest, pFanin, k ) Vec_IntPush( vLeaves, Mig_ObjCopy(pFanin) ); if ( pMan->pPars->fDeriveLuts && (pMan->pPars->fUseTruth || pMan->pPars->fUseDsd) ) { extern int Gia_ManFromIfLogicNode( void * p, 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 ); if ( pMan->pPars->fUseTruth ) pTruth = Mpm_CutTruth(pMan, Abc_Lit2Var(pCutBest->iFunc)); else uTruth = Mpm_CutTruthFromDsd( pMan, pCutBest, Abc_Lit2Var(pCutBest->iFunc) ); // Kit_DsdPrintFromTruth( pTruth, Vec_IntSize(vLeaves) ); printf( "\n" ); // perform decomposition of the cut iLitNew = Gia_ManFromIfLogicNode( NULL, pNew, Mig_ObjId(pObj), vLeaves, vLeaves2, pTruth, NULL, vCover, vMapping, vMapping2, vPacking, 0, 0 ); iLitNew = Abc_LitNotCond( iLitNew, pCutBest->fCompl ^ Abc_LitIsCompl(pCutBest->iFunc) ); } else { // perform one of the two types of mapping: with and without structures iLitNew = Mpm_ManNodeIfToGia( pNew, pMan, pObj, vLeaves, 0 ); // write mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitNew), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, Entry, k ) assert( Abc_Lit2Var(Entry) < Abc_Lit2Var(iLitNew) ); Vec_IntForEachEntry( vLeaves, Entry, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(Entry) ); Vec_IntPush( vMapping2, Abc_Lit2Var(iLitNew) ); } } else if ( Mig_ObjIsCi(pObj) ) iLitNew = Gia_ManAppendCi(pNew); else if ( Mig_ObjIsCo(pObj) ) iLitNew = Gia_ManAppendCo( pNew, Abc_LitNotCond(Mig_ObjCopy(Mig_ObjFanin0(pObj)), Mig_ObjFaninC0(pObj)) ); else if ( Mig_ObjIsConst0(pObj) ) { iLitNew = 0; // create const LUT Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, 0 ); Vec_IntPush( vMapping2, 0 ); } else assert( 0 ); Mig_ObjSetCopy( pObj, iLitNew ); } Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); Vec_IntFree( vLeaves2 ); // printf( "Mapping array size: IfMan = %d. Gia = %d. Increase = %.2f\n", // Mig_ManObjNum(pMan), Gia_ManObjNum(pNew), 1.0 * Gia_ManObjNum(pNew) / Mig_ManObjNum(pMan) ); // 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 ); pNew->vMapping = vMapping; pNew->vPacking = vPacking; // 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)) ); } return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* void Mig_ManTest2( Gia_Man_t * pGia ) { extern int Gia_ManSuppSizeTest( Gia_Man_t * p ); Mig_Man_t * p; Gia_ManSuppSizeTest( pGia ); p = Mig_ManCreate( pGia ); Mig_ManSuppSizeTest( p ); Mig_ManStop( p ); } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmCore.c000066400000000000000000000066531300674244400231620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmCore.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig/gia/gia.h" #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mpm_ManSetParsDefault( Mpm_Par_t * p ) { memset( p, 0, sizeof(Mpm_Par_t) ); p->pLib = NULL; // LUT library p->nNumCuts = 8; // cut number p->fUseTruth = 0; // uses truth tables p->fUseDsd = 0; // uses DSDs p->fCutMin = 0; // enables cut minimization p->fOneRound = 0; // enabled one round p->DelayTarget = -1; // delay target p->fDeriveLuts = 0; // use truth tables to derive AIG structure p->fMap4Cnf = 0; // mapping for CNF p->fMap4Aig = 0; // mapping for AIG p->fMap4Gates = 0; // mapping for gates p->fVerbose = 0; // verbose output p->fVeryVerbose = 0; // verbose output } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Mpm_ManPerformLutMapping( Mig_Man_t * pMig, Mpm_Par_t * pPars ) { Gia_Man_t * pNew; Mpm_Man_t * p; p = Mpm_ManStart( pMig, pPars ); if ( p->pPars->fVerbose ) Mpm_ManPrintStatsInit( p ); Mpm_ManPrepare( p ); Mpm_ManPerform( p ); if ( p->pPars->fVerbose ) Mpm_ManPrintStats( p ); pNew = (Gia_Man_t *)Mpm_ManFromIfLogic( p ); Mpm_ManStop( p ); return pNew; } Gia_Man_t * Mpm_ManLutMapping( Gia_Man_t * pGia, Mpm_Par_t * pPars ) { Mig_Man_t * p; Gia_Man_t * pNew; assert( pPars->pLib->LutMax <= MPM_VAR_MAX ); assert( pPars->nNumCuts <= MPM_CUT_MAX ); if ( pPars->fUseGates ) { pGia = Gia_ManDupMuxes( pGia, 2 ); p = Mig_ManCreate( pGia ); Gia_ManStop( pGia ); } else p = Mig_ManCreate( pGia ); pNew = Mpm_ManPerformLutMapping( p, pPars ); Mig_ManStop( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmDsd.c000066400000000000000000001664031300674244400230040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [DSD manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmDsd.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Mpm_Dsd_t s_DsdClass6[595] = { { 0, 0, 1, ABC_CONST(0x0000000000000000), "0" }, // 0 { 1, 0, 2, ABC_CONST(0xAAAAAAAAAAAAAAAA), "a" }, // 1 { 2, 1, 3, ABC_CONST(0x8888888888888888), "(ab)" }, // 2 { 2, 3, 4, ABC_CONST(0x6666666666666666), "[ab]" }, // 3 { 3, 2, 4, ABC_CONST(0x8080808080808080), "(abc)" }, // 4 { 3, 2, 4, ABC_CONST(0x7070707070707070), "(!(ab)c)" }, // 5 { 3, 4, 6, ABC_CONST(0x7878787878787878), "[(ab)c]" }, // 6 { 3, 4, 5, ABC_CONST(0x6060606060606060), "([ab]c)" }, // 7 { 3, 6, 8, ABC_CONST(0x9696969696969696), "[abc]" }, // 8 { 3, 3, 4, ABC_CONST(0xCACACACACACACACA), "" }, // 9 { 4, 3, 5, ABC_CONST(0x8000800080008000), "(abcd)" }, // 10 { 4, 3, 5, ABC_CONST(0x7F007F007F007F00), "(!(abc)d)" }, // 11 { 4, 5, 8, ABC_CONST(0x7F807F807F807F80), "[(abc)d]" }, // 12 { 4, 3, 5, ABC_CONST(0x7000700070007000), "(!(ab)cd)" }, // 13 { 4, 3, 5, ABC_CONST(0x8F008F008F008F00), "(!(!(ab)c)d)" }, // 14 { 4, 5, 8, ABC_CONST(0x8F708F708F708F70), "[(!(ab)c)d]" }, // 15 { 4, 5, 7, ABC_CONST(0x7800780078007800), "([(ab)c]d)" }, // 16 { 4, 7, 12, ABC_CONST(0x8778877887788778), "[(ab)cd]" }, // 17 { 4, 5, 6, ABC_CONST(0x6000600060006000), "([ab]cd)" }, // 18 { 4, 5, 6, ABC_CONST(0x9F009F009F009F00), "(!([ab]c)d)" }, // 19 { 4, 7, 10, ABC_CONST(0x9F609F609F609F60), "[([ab]c)d]" }, // 20 { 4, 7, 9, ABC_CONST(0x9600960096009600), "([abc]d)" }, // 21 { 4, 9, 16, ABC_CONST(0x6996699669966996), "[abcd]" }, // 22 { 4, 4, 5, ABC_CONST(0xCA00CA00CA00CA00), "(d)" }, // 23 { 4, 6, 8, ABC_CONST(0x35CA35CA35CA35CA), "[d]" }, // 24 { 4, 3, 6, ABC_CONST(0x0777077707770777), "(!(ab)!(cd))" }, // 25 { 4, 5, 9, ABC_CONST(0x7888788878887888), "[(ab)(cd)]" }, // 26 { 4, 5, 7, ABC_CONST(0x0666066606660666), "([ab]!(cd))" }, // 27 { 4, 7, 8, ABC_CONST(0x0660066006600660), "([ab][cd])" }, // 28 { 4, 4, 6, ABC_CONST(0xCAAACAAACAAACAAA), "" }, // 29 { 4, 6, 8, ABC_CONST(0xACCAACCAACCAACCA), "" }, // 30 { 4, 4, 5, ABC_CONST(0xF088F088F088F088), "<(ab)cd>" }, // 31 { 4, 6, 6, ABC_CONST(0xF066F066F066F066), "<[ab]cd>" }, // 32 { 5, 4, 6, ABC_CONST(0x8000000080000000), "(abcde)" }, // 33 { 5, 4, 6, ABC_CONST(0x7FFF00007FFF0000), "(!(abcd)e)" }, // 34 { 5, 6, 10, ABC_CONST(0x7FFF80007FFF8000), "[(abcd)e]" }, // 35 { 5, 4, 6, ABC_CONST(0x7F0000007F000000), "(!(abc)de)" }, // 36 { 5, 4, 6, ABC_CONST(0x80FF000080FF0000), "(!(!(abc)d)e)" }, // 37 { 5, 6, 10, ABC_CONST(0x80FF7F0080FF7F00), "[(!(abc)d)e]" }, // 38 { 5, 6, 9, ABC_CONST(0x7F8000007F800000), "([(abc)d]e)" }, // 39 { 5, 8, 16, ABC_CONST(0x807F7F80807F7F80), "[(abc)de]" }, // 40 { 5, 4, 6, ABC_CONST(0x7000000070000000), "(!(ab)cde)" }, // 41 { 5, 4, 6, ABC_CONST(0x8FFF00008FFF0000), "(!(!(ab)cd)e)" }, // 42 { 5, 6, 10, ABC_CONST(0x8FFF70008FFF7000), "[(!(ab)cd)e]" }, // 43 { 5, 4, 6, ABC_CONST(0x8F0000008F000000), "(!(!(ab)c)de)" }, // 44 { 5, 4, 6, ABC_CONST(0x70FF000070FF0000), "(!(!(!(ab)c)d)e)" }, // 45 { 5, 6, 10, ABC_CONST(0x70FF8F0070FF8F00), "[(!(!(ab)c)d)e]" }, // 46 { 5, 6, 9, ABC_CONST(0x8F7000008F700000), "([(!(ab)c)d]e)" }, // 47 { 5, 8, 16, ABC_CONST(0x708F8F70708F8F70), "[(!(ab)c)de]" }, // 48 { 5, 6, 8, ABC_CONST(0x7800000078000000), "([(ab)c]de)" }, // 49 { 5, 6, 8, ABC_CONST(0x87FF000087FF0000), "(!([(ab)c]d)e)" }, // 50 { 5, 8, 14, ABC_CONST(0x87FF780087FF7800), "[([(ab)c]d)e]" }, // 51 { 5, 8, 13, ABC_CONST(0x8778000087780000), "([(ab)cd]e)" }, // 52 { 5, 10, 24, ABC_CONST(0x7887877878878778), "[(ab)cde]" }, // 53 { 5, 6, 7, ABC_CONST(0x6000000060000000), "([ab]cde)" }, // 54 { 5, 6, 7, ABC_CONST(0x9FFF00009FFF0000), "(!([ab]cd)e)" }, // 55 { 5, 8, 12, ABC_CONST(0x9FFF60009FFF6000), "[([ab]cd)e]" }, // 56 { 5, 6, 7, ABC_CONST(0x9F0000009F000000), "(!([ab]c)de)" }, // 57 { 5, 6, 7, ABC_CONST(0x60FF000060FF0000), "(!(!([ab]c)d)e)" }, // 58 { 5, 8, 12, ABC_CONST(0x60FF9F0060FF9F00), "[(!([ab]c)d)e]" }, // 59 { 5, 8, 11, ABC_CONST(0x9F6000009F600000), "([([ab]c)d]e)" }, // 60 { 5, 10, 20, ABC_CONST(0x609F9F60609F9F60), "[([ab]c)de]" }, // 61 { 5, 8, 10, ABC_CONST(0x9600000096000000), "([abc]de)" }, // 62 { 5, 8, 10, ABC_CONST(0x69FF000069FF0000), "(!([abc]d)e)" }, // 63 { 5, 10, 18, ABC_CONST(0x69FF960069FF9600), "[([abc]d)e]" }, // 64 { 5, 10, 17, ABC_CONST(0x6996000069960000), "([abcd]e)" }, // 65 { 5, 12, 32, ABC_CONST(0x9669699696696996), "[abcde]" }, // 66 { 5, 5, 6, ABC_CONST(0xCA000000CA000000), "(de)" }, // 67 { 5, 5, 6, ABC_CONST(0x35FF000035FF0000), "(!(d)e)" }, // 68 { 5, 7, 10, ABC_CONST(0x35FFCA0035FFCA00), "[(d)e]" }, // 69 { 5, 7, 9, ABC_CONST(0x35CA000035CA0000), "([d]e)" }, // 70 { 5, 9, 16, ABC_CONST(0xCA3535CACA3535CA), "[de]" }, // 71 { 5, 4, 7, ABC_CONST(0x0777000007770000), "(!(ab)!(cd)e)" }, // 72 { 5, 4, 7, ABC_CONST(0xF8880000F8880000), "(!(!(ab)!(cd))e)" }, // 73 { 5, 6, 12, ABC_CONST(0xF8880777F8880777), "[(!(ab)!(cd))e]" }, // 74 { 5, 6, 10, ABC_CONST(0x7888000078880000), "([(ab)(cd)]e)" }, // 75 { 5, 6, 10, ABC_CONST(0x8777000087770000), "(![(ab)(cd)]e)" }, // 76 { 5, 8, 18, ABC_CONST(0x8777788887777888), "[(ab)(cd)e]" }, // 77 { 5, 6, 8, ABC_CONST(0x0666000006660000), "([ab]!(cd)e)" }, // 78 { 5, 6, 8, ABC_CONST(0xF9990000F9990000), "(!([ab]!(cd))e)" }, // 79 { 5, 8, 14, ABC_CONST(0xF9990666F9990666), "[([ab]!(cd))e]" }, // 80 { 5, 8, 9, ABC_CONST(0x0660000006600000), "([ab][cd]e)" }, // 81 { 5, 8, 9, ABC_CONST(0xF99F0000F99F0000), "(!([ab][cd])e)" }, // 82 { 5, 10, 16, ABC_CONST(0xF99F0660F99F0660), "[([ab][cd])e]" }, // 83 { 5, 5, 7, ABC_CONST(0xCAAA0000CAAA0000), "(e)" }, // 84 { 5, 7, 12, ABC_CONST(0x3555CAAA3555CAAA), "[e]" }, // 85 { 5, 7, 9, ABC_CONST(0xACCA0000ACCA0000), "(e)" }, // 86 { 5, 9, 16, ABC_CONST(0x5335ACCA5335ACCA), "[e]" }, // 87 { 5, 5, 6, ABC_CONST(0xF0880000F0880000), "(<(ab)cd>e)" }, // 88 { 5, 5, 6, ABC_CONST(0x0F7700000F770000), "(!<(ab)cd>e)" }, // 89 { 5, 7, 10, ABC_CONST(0x0F77F0880F77F088), "[<(ab)cd>e]" }, // 90 { 5, 7, 7, ABC_CONST(0xF0660000F0660000), "(<[ab]cd>e)" }, // 91 { 5, 9, 12, ABC_CONST(0x0F99F0660F99F066), "[<[ab]cd>e]" }, // 92 { 5, 4, 8, ABC_CONST(0x007F7F7F007F7F7F), "(!(abc)!(de))" }, // 93 { 5, 6, 12, ABC_CONST(0x7F8080807F808080), "[(abc)(de)]" }, // 94 { 5, 4, 7, ABC_CONST(0x008F8F8F008F8F8F), "(!(!(ab)c)!(de))" }, // 95 { 5, 6, 12, ABC_CONST(0x8F7070708F707070), "[(!(ab)c)(de)]" }, // 96 { 5, 6, 10, ABC_CONST(0x0078787800787878), "([(ab)c]!(de))" }, // 97 { 5, 6, 9, ABC_CONST(0x009F9F9F009F9F9F), "(!([ab]c)!(de))" }, // 98 { 5, 8, 15, ABC_CONST(0x9F6060609F606060), "[([ab]c)(de)]" }, // 99 { 5, 8, 13, ABC_CONST(0x0096969600969696), "([abc]!(de))" }, // 100 { 5, 5, 7, ABC_CONST(0x00CACACA00CACACA), "(!(de))" }, // 101 { 5, 7, 12, ABC_CONST(0x35CACACA35CACACA), "[(de)]" }, // 102 { 5, 6, 9, ABC_CONST(0x007F7F00007F7F00), "(!(abc)[de])" }, // 103 { 5, 6, 8, ABC_CONST(0x008F8F00008F8F00), "(!(!(ab)c)[de])" }, // 104 { 5, 8, 11, ABC_CONST(0x0078780000787800), "([(ab)c][de])" }, // 105 { 5, 8, 10, ABC_CONST(0x009F9F00009F9F00), "(!([ab]c)[de])" }, // 106 { 5, 10, 14, ABC_CONST(0x0096960000969600), "([abc][de])" }, // 107 { 5, 7, 8, ABC_CONST(0x00CACA0000CACA00), "([de])" }, // 108 { 5, 5, 8, ABC_CONST(0xCAAAAAAACAAAAAAA), "" }, // 109 { 5, 5, 8, ABC_CONST(0xACCCAAAAACCCAAAA), "" }, // 110 { 5, 7, 12, ABC_CONST(0xACCCCAAAACCCCAAA), "" }, // 111 { 5, 7, 10, ABC_CONST(0xACCAAAAAACCAAAAA), "" }, // 112 { 5, 9, 16, ABC_CONST(0xCAACACCACAACACCA), "" }, // 113 { 5, 6, 8, ABC_CONST(0xCCAACACACCAACACA), ">" }, // 114 { 5, 5, 7, ABC_CONST(0xC0AAAAAAC0AAAAAA), "" }, // 115 { 5, 7, 8, ABC_CONST(0x3CAAAAAA3CAAAAAA), "" }, // 116 { 5, 5, 8, ABC_CONST(0xF0888888F0888888), "<(ab)c(de)>" }, // 117 { 5, 7, 10, ABC_CONST(0x88F0F08888F0F088), "<(ab)c[de]>" }, // 118 { 5, 7, 10, ABC_CONST(0xF0666666F0666666), "<[ab]c(de)>" }, // 119 { 5, 9, 12, ABC_CONST(0x66F0F06666F0F066), "<[ab]c[de]>" }, // 120 { 5, 5, 6, ABC_CONST(0xF0008888F0008888), "<(ab)(cd)e>" }, // 121 { 5, 5, 6, ABC_CONST(0xF0007777F0007777), "" }, // 122 { 5, 7, 7, ABC_CONST(0xF0006666F0006666), "<[ab](cd)e>" }, // 123 { 5, 9, 8, ABC_CONST(0x0FF066660FF06666), "<[ab][cd]e>" }, // 124 { 5, 5, 6, ABC_CONST(0xFF008080FF008080), "<(abc)de>" }, // 125 { 5, 5, 6, ABC_CONST(0xFF007070FF007070), "<(!(ab)c)de>" }, // 126 { 5, 7, 8, ABC_CONST(0xFF007878FF007878), "<[(ab)c]de>" }, // 127 { 5, 7, 7, ABC_CONST(0xFF006060FF006060), "<([ab]c)de>" }, // 128 { 5, 9, 10, ABC_CONST(0xFF009696FF009696), "<[abc]de>" }, // 129 { 5, 6, 6, ABC_CONST(0xFF00CACAFF00CACA), "<de>" }, // 130 { 6, 5, 7, ABC_CONST(0x8000000000000000), "(abcdef)" }, // 131 { 6, 5, 7, ABC_CONST(0x7FFFFFFF00000000), "(!(abcde)f)" }, // 132 { 6, 7, 12, ABC_CONST(0x7FFFFFFF80000000), "[(abcde)f]" }, // 133 { 6, 5, 7, ABC_CONST(0x7FFF000000000000), "(!(abcd)ef)" }, // 134 { 6, 5, 7, ABC_CONST(0x8000FFFF00000000), "(!(!(abcd)e)f)" }, // 135 { 6, 7, 12, ABC_CONST(0x8000FFFF7FFF0000), "[(!(abcd)e)f]" }, // 136 { 6, 7, 11, ABC_CONST(0x7FFF800000000000), "([(abcd)e]f)" }, // 137 { 6, 9, 20, ABC_CONST(0x80007FFF7FFF8000), "[(abcd)ef]" }, // 138 { 6, 5, 7, ABC_CONST(0x7F00000000000000), "(!(abc)def)" }, // 139 { 6, 5, 7, ABC_CONST(0x80FFFFFF00000000), "(!(!(abc)de)f)" }, // 140 { 6, 7, 12, ABC_CONST(0x80FFFFFF7F000000), "[(!(abc)de)f]" }, // 141 { 6, 5, 7, ABC_CONST(0x80FF000000000000), "(!(!(abc)d)ef)" }, // 142 { 6, 5, 7, ABC_CONST(0x7F00FFFF00000000), "(!(!(!(abc)d)e)f)" }, // 143 { 6, 7, 12, ABC_CONST(0x7F00FFFF80FF0000), "[(!(!(abc)d)e)f]" }, // 144 { 6, 7, 11, ABC_CONST(0x80FF7F0000000000), "([(!(abc)d)e]f)" }, // 145 { 6, 9, 20, ABC_CONST(0x7F0080FF80FF7F00), "[(!(abc)d)ef]" }, // 146 { 6, 7, 10, ABC_CONST(0x7F80000000000000), "([(abc)d]ef)" }, // 147 { 6, 7, 10, ABC_CONST(0x807FFFFF00000000), "(!([(abc)d]e)f)" }, // 148 { 6, 9, 18, ABC_CONST(0x807FFFFF7F800000), "[([(abc)d]e)f]" }, // 149 { 6, 9, 17, ABC_CONST(0x807F7F8000000000), "([(abc)de]f)" }, // 150 { 6, 11, 32, ABC_CONST(0x7F80807F807F7F80), "[(abc)def]" }, // 151 { 6, 5, 7, ABC_CONST(0x7000000000000000), "(!(ab)cdef)" }, // 152 { 6, 5, 7, ABC_CONST(0x8FFFFFFF00000000), "(!(!(ab)cde)f)" }, // 153 { 6, 7, 12, ABC_CONST(0x8FFFFFFF70000000), "[(!(ab)cde)f]" }, // 154 { 6, 5, 7, ABC_CONST(0x8FFF000000000000), "(!(!(ab)cd)ef)" }, // 155 { 6, 5, 7, ABC_CONST(0x7000FFFF00000000), "(!(!(!(ab)cd)e)f)" }, // 156 { 6, 7, 12, ABC_CONST(0x7000FFFF8FFF0000), "[(!(!(ab)cd)e)f]" }, // 157 { 6, 7, 11, ABC_CONST(0x8FFF700000000000), "([(!(ab)cd)e]f)" }, // 158 { 6, 9, 20, ABC_CONST(0x70008FFF8FFF7000), "[(!(ab)cd)ef]" }, // 159 { 6, 5, 7, ABC_CONST(0x8F00000000000000), "(!(!(ab)c)def)" }, // 160 { 6, 5, 7, ABC_CONST(0x70FFFFFF00000000), "(!(!(!(ab)c)de)f)" }, // 161 { 6, 7, 12, ABC_CONST(0x70FFFFFF8F000000), "[(!(!(ab)c)de)f]" }, // 162 { 6, 5, 7, ABC_CONST(0x70FF000000000000), "(!(!(!(ab)c)d)ef)" }, // 163 { 6, 5, 7, ABC_CONST(0x8F00FFFF00000000), "(!(!(!(!(ab)c)d)e)f)" }, // 164 { 6, 7, 12, ABC_CONST(0x8F00FFFF70FF0000), "[(!(!(!(ab)c)d)e)f]" }, // 165 { 6, 7, 11, ABC_CONST(0x70FF8F0000000000), "([(!(!(ab)c)d)e]f)" }, // 166 { 6, 9, 20, ABC_CONST(0x8F0070FF70FF8F00), "[(!(!(ab)c)d)ef]" }, // 167 { 6, 7, 10, ABC_CONST(0x8F70000000000000), "([(!(ab)c)d]ef)" }, // 168 { 6, 7, 10, ABC_CONST(0x708FFFFF00000000), "(!([(!(ab)c)d]e)f)" }, // 169 { 6, 9, 18, ABC_CONST(0x708FFFFF8F700000), "[([(!(ab)c)d]e)f]" }, // 170 { 6, 9, 17, ABC_CONST(0x708F8F7000000000), "([(!(ab)c)de]f)" }, // 171 { 6, 11, 32, ABC_CONST(0x8F70708F708F8F70), "[(!(ab)c)def]" }, // 172 { 6, 7, 9, ABC_CONST(0x7800000000000000), "([(ab)c]def)" }, // 173 { 6, 7, 9, ABC_CONST(0x87FFFFFF00000000), "(!([(ab)c]de)f)" }, // 174 { 6, 9, 16, ABC_CONST(0x87FFFFFF78000000), "[([(ab)c]de)f]" }, // 175 { 6, 7, 9, ABC_CONST(0x87FF000000000000), "(!([(ab)c]d)ef)" }, // 176 { 6, 7, 9, ABC_CONST(0x7800FFFF00000000), "(!(!([(ab)c]d)e)f)" }, // 177 { 6, 9, 16, ABC_CONST(0x7800FFFF87FF0000), "[(!([(ab)c]d)e)f]" }, // 178 { 6, 9, 15, ABC_CONST(0x87FF780000000000), "([([(ab)c]d)e]f)" }, // 179 { 6, 11, 28, ABC_CONST(0x780087FF87FF7800), "[([(ab)c]d)ef]" }, // 180 { 6, 9, 14, ABC_CONST(0x8778000000000000), "([(ab)cd]ef)" }, // 181 { 6, 9, 14, ABC_CONST(0x7887FFFF00000000), "(!([(ab)cd]e)f)" }, // 182 { 6, 11, 26, ABC_CONST(0x7887FFFF87780000), "[([(ab)cd]e)f]" }, // 183 { 6, 11, 25, ABC_CONST(0x7887877800000000), "([(ab)cde]f)" }, // 184 { 6, 13, 48, ABC_CONST(0x8778788778878778), "[(ab)cdef]" }, // 185 { 6, 7, 8, ABC_CONST(0x6000000000000000), "([ab]cdef)" }, // 186 { 6, 7, 8, ABC_CONST(0x9FFFFFFF00000000), "(!([ab]cde)f)" }, // 187 { 6, 9, 14, ABC_CONST(0x9FFFFFFF60000000), "[([ab]cde)f]" }, // 188 { 6, 7, 8, ABC_CONST(0x9FFF000000000000), "(!([ab]cd)ef)" }, // 189 { 6, 7, 8, ABC_CONST(0x6000FFFF00000000), "(!(!([ab]cd)e)f)" }, // 190 { 6, 9, 14, ABC_CONST(0x6000FFFF9FFF0000), "[(!([ab]cd)e)f]" }, // 191 { 6, 9, 13, ABC_CONST(0x9FFF600000000000), "([([ab]cd)e]f)" }, // 192 { 6, 11, 24, ABC_CONST(0x60009FFF9FFF6000), "[([ab]cd)ef]" }, // 193 { 6, 7, 8, ABC_CONST(0x9F00000000000000), "(!([ab]c)def)" }, // 194 { 6, 7, 8, ABC_CONST(0x60FFFFFF00000000), "(!(!([ab]c)de)f)" }, // 195 { 6, 9, 14, ABC_CONST(0x60FFFFFF9F000000), "[(!([ab]c)de)f]" }, // 196 { 6, 7, 8, ABC_CONST(0x60FF000000000000), "(!(!([ab]c)d)ef)" }, // 197 { 6, 7, 8, ABC_CONST(0x9F00FFFF00000000), "(!(!(!([ab]c)d)e)f)" }, // 198 { 6, 9, 14, ABC_CONST(0x9F00FFFF60FF0000), "[(!(!([ab]c)d)e)f]" }, // 199 { 6, 9, 13, ABC_CONST(0x60FF9F0000000000), "([(!([ab]c)d)e]f)" }, // 200 { 6, 11, 24, ABC_CONST(0x9F0060FF60FF9F00), "[(!([ab]c)d)ef]" }, // 201 { 6, 9, 12, ABC_CONST(0x9F60000000000000), "([([ab]c)d]ef)" }, // 202 { 6, 9, 12, ABC_CONST(0x609FFFFF00000000), "(!([([ab]c)d]e)f)" }, // 203 { 6, 11, 22, ABC_CONST(0x609FFFFF9F600000), "[([([ab]c)d]e)f]" }, // 204 { 6, 11, 21, ABC_CONST(0x609F9F6000000000), "([([ab]c)de]f)" }, // 205 { 6, 13, 40, ABC_CONST(0x9F60609F609F9F60), "[([ab]c)def]" }, // 206 { 6, 9, 11, ABC_CONST(0x9600000000000000), "([abc]def)" }, // 207 { 6, 9, 11, ABC_CONST(0x69FFFFFF00000000), "(!([abc]de)f)" }, // 208 { 6, 11, 20, ABC_CONST(0x69FFFFFF96000000), "[([abc]de)f]" }, // 209 { 6, 9, 11, ABC_CONST(0x69FF000000000000), "(!([abc]d)ef)" }, // 210 { 6, 9, 11, ABC_CONST(0x9600FFFF00000000), "(!(!([abc]d)e)f)" }, // 211 { 6, 11, 20, ABC_CONST(0x9600FFFF69FF0000), "[(!([abc]d)e)f]" }, // 212 { 6, 11, 19, ABC_CONST(0x69FF960000000000), "([([abc]d)e]f)" }, // 213 { 6, 13, 36, ABC_CONST(0x960069FF69FF9600), "[([abc]d)ef]" }, // 214 { 6, 11, 18, ABC_CONST(0x6996000000000000), "([abcd]ef)" }, // 215 { 6, 11, 18, ABC_CONST(0x9669FFFF00000000), "(!([abcd]e)f)" }, // 216 { 6, 13, 34, ABC_CONST(0x9669FFFF69960000), "[([abcd]e)f]" }, // 217 { 6, 13, 33, ABC_CONST(0x9669699600000000), "([abcde]f)" }, // 218 { 6, 15, 64, ABC_CONST(0x6996966996696996), "[abcdef]" }, // 219 { 6, 6, 7, ABC_CONST(0xCA00000000000000), "(def)" }, // 220 { 6, 6, 7, ABC_CONST(0x35FFFFFF00000000), "(!(de)f)" }, // 221 { 6, 8, 12, ABC_CONST(0x35FFFFFFCA000000), "[(de)f]" }, // 222 { 6, 6, 7, ABC_CONST(0x35FF000000000000), "(!(d)ef)" }, // 223 { 6, 6, 7, ABC_CONST(0xCA00FFFF00000000), "(!(!(d)e)f)" }, // 224 { 6, 8, 12, ABC_CONST(0xCA00FFFF35FF0000), "[(!(d)e)f]" }, // 225 { 6, 8, 11, ABC_CONST(0x35FFCA0000000000), "([(d)e]f)" }, // 226 { 6, 10, 20, ABC_CONST(0xCA0035FF35FFCA00), "[(d)ef]" }, // 227 { 6, 8, 10, ABC_CONST(0x35CA000000000000), "([d]ef)" }, // 228 { 6, 8, 10, ABC_CONST(0xCA35FFFF00000000), "(!([d]e)f)" }, // 229 { 6, 10, 18, ABC_CONST(0xCA35FFFF35CA0000), "[([d]e)f]" }, // 230 { 6, 10, 17, ABC_CONST(0xCA3535CA00000000), "([de]f)" }, // 231 { 6, 12, 32, ABC_CONST(0x35CACA35CA3535CA), "[def]" }, // 232 { 6, 5, 8, ABC_CONST(0x0777000000000000), "(!(ab)!(cd)ef)" }, // 233 { 6, 5, 8, ABC_CONST(0xF888FFFF00000000), "(!(!(ab)!(cd)e)f)" }, // 234 { 6, 7, 14, ABC_CONST(0xF888FFFF07770000), "[(!(ab)!(cd)e)f]" }, // 235 { 6, 5, 8, ABC_CONST(0xF888000000000000), "(!(!(ab)!(cd))ef)" }, // 236 { 6, 5, 8, ABC_CONST(0x0777FFFF00000000), "(!(!(!(ab)!(cd))e)f)" }, // 237 { 6, 7, 14, ABC_CONST(0x0777FFFFF8880000), "[(!(!(ab)!(cd))e)f]" }, // 238 { 6, 7, 13, ABC_CONST(0xF888077700000000), "([(!(ab)!(cd))e]f)" }, // 239 { 6, 9, 24, ABC_CONST(0x0777F888F8880777), "[(!(ab)!(cd))ef]" }, // 240 { 6, 7, 11, ABC_CONST(0x7888000000000000), "([(ab)(cd)]ef)" }, // 241 { 6, 7, 11, ABC_CONST(0x8777FFFF00000000), "(!([(ab)(cd)]e)f)" }, // 242 { 6, 9, 20, ABC_CONST(0x8777FFFF78880000), "[([(ab)(cd)]e)f]" }, // 243 { 6, 7, 11, ABC_CONST(0x8777000000000000), "(![(ab)(cd)]ef)" }, // 244 { 6, 7, 11, ABC_CONST(0x7888FFFF00000000), "(!(![(ab)(cd)]e)f)" }, // 245 { 6, 9, 20, ABC_CONST(0x7888FFFF87770000), "[(![(ab)(cd)]e)f]" }, // 246 { 6, 9, 19, ABC_CONST(0x8777788800000000), "([(ab)(cd)e]f)" }, // 247 { 6, 11, 36, ABC_CONST(0x7888877787777888), "[(ab)(cd)ef]" }, // 248 { 6, 7, 9, ABC_CONST(0x0666000000000000), "([ab]!(cd)ef)" }, // 249 { 6, 7, 9, ABC_CONST(0xF999FFFF00000000), "(!([ab]!(cd)e)f)" }, // 250 { 6, 9, 16, ABC_CONST(0xF999FFFF06660000), "[([ab]!(cd)e)f]" }, // 251 { 6, 7, 9, ABC_CONST(0xF999000000000000), "(!([ab]!(cd))ef)" }, // 252 { 6, 7, 9, ABC_CONST(0x0666FFFF00000000), "(!(!([ab]!(cd))e)f)" }, // 253 { 6, 9, 16, ABC_CONST(0x0666FFFFF9990000), "[(!([ab]!(cd))e)f]" }, // 254 { 6, 9, 15, ABC_CONST(0xF999066600000000), "([([ab]!(cd))e]f)" }, // 255 { 6, 11, 28, ABC_CONST(0x0666F999F9990666), "[([ab]!(cd))ef]" }, // 256 { 6, 9, 10, ABC_CONST(0x0660000000000000), "([ab][cd]ef)" }, // 257 { 6, 9, 10, ABC_CONST(0xF99FFFFF00000000), "(!([ab][cd]e)f)" }, // 258 { 6, 11, 18, ABC_CONST(0xF99FFFFF06600000), "[([ab][cd]e)f]" }, // 259 { 6, 9, 10, ABC_CONST(0xF99F000000000000), "(!([ab][cd])ef)" }, // 260 { 6, 9, 10, ABC_CONST(0x0660FFFF00000000), "(!(!([ab][cd])e)f)" }, // 261 { 6, 11, 18, ABC_CONST(0x0660FFFFF99F0000), "[(!([ab][cd])e)f]" }, // 262 { 6, 11, 17, ABC_CONST(0xF99F066000000000), "([([ab][cd])e]f)" }, // 263 { 6, 13, 32, ABC_CONST(0x0660F99FF99F0660), "[([ab][cd])ef]" }, // 264 { 6, 6, 8, ABC_CONST(0xCAAA000000000000), "(ef)" }, // 265 { 6, 6, 8, ABC_CONST(0x3555FFFF00000000), "(!(e)f)" }, // 266 { 6, 8, 14, ABC_CONST(0x3555FFFFCAAA0000), "[(e)f]" }, // 267 { 6, 8, 13, ABC_CONST(0x3555CAAA00000000), "([e]f)" }, // 268 { 6, 10, 24, ABC_CONST(0xCAAA35553555CAAA), "[ef]" }, // 269 { 6, 8, 10, ABC_CONST(0xACCA000000000000), "(ef)" }, // 270 { 6, 8, 10, ABC_CONST(0x5335FFFF00000000), "(!(e)f)" }, // 271 { 6, 10, 18, ABC_CONST(0x5335FFFFACCA0000), "[(e)f]" }, // 272 { 6, 10, 17, ABC_CONST(0x5335ACCA00000000), "([e]f)" }, // 273 { 6, 12, 32, ABC_CONST(0xACCA53355335ACCA), "[ef]" }, // 274 { 6, 6, 7, ABC_CONST(0xF088000000000000), "(<(ab)cd>ef)" }, // 275 { 6, 6, 7, ABC_CONST(0x0F77FFFF00000000), "(!(<(ab)cd>e)f)" }, // 276 { 6, 8, 12, ABC_CONST(0x0F77FFFFF0880000), "[(<(ab)cd>e)f]" }, // 277 { 6, 6, 7, ABC_CONST(0x0F77000000000000), "(!<(ab)cd>ef)" }, // 278 { 6, 6, 7, ABC_CONST(0xF088FFFF00000000), "(!(!<(ab)cd>e)f)" }, // 279 { 6, 8, 12, ABC_CONST(0xF088FFFF0F770000), "[(!<(ab)cd>e)f]" }, // 280 { 6, 8, 11, ABC_CONST(0x0F77F08800000000), "([<(ab)cd>e]f)" }, // 281 { 6, 10, 20, ABC_CONST(0xF0880F770F77F088), "[<(ab)cd>ef]" }, // 282 { 6, 8, 8, ABC_CONST(0xF066000000000000), "(<[ab]cd>ef)" }, // 283 { 6, 8, 8, ABC_CONST(0x0F99FFFF00000000), "(!(<[ab]cd>e)f)" }, // 284 { 6, 10, 14, ABC_CONST(0x0F99FFFFF0660000), "[(<[ab]cd>e)f]" }, // 285 { 6, 10, 13, ABC_CONST(0x0F99F06600000000), "([<[ab]cd>e]f)" }, // 286 { 6, 12, 24, ABC_CONST(0xF0660F990F99F066), "[<[ab]cd>ef]" }, // 287 { 6, 5, 9, ABC_CONST(0x007F7F7F00000000), "(!(abc)!(de)f)" }, // 288 { 6, 5, 9, ABC_CONST(0xFF80808000000000), "(!(!(abc)!(de))f)" }, // 289 { 6, 7, 16, ABC_CONST(0xFF808080007F7F7F), "[(!(abc)!(de))f]" }, // 290 { 6, 7, 13, ABC_CONST(0x7F80808000000000), "([(abc)(de)]f)" }, // 291 { 6, 7, 13, ABC_CONST(0x807F7F7F00000000), "(![(abc)(de)]f)" }, // 292 { 6, 9, 24, ABC_CONST(0x807F7F7F7F808080), "[(abc)(de)f]" }, // 293 { 6, 5, 8, ABC_CONST(0x008F8F8F00000000), "(!(!(ab)c)!(de)f)" }, // 294 { 6, 5, 8, ABC_CONST(0xFF70707000000000), "(!(!(!(ab)c)!(de))f)" }, // 295 { 6, 7, 14, ABC_CONST(0xFF707070008F8F8F), "[(!(!(ab)c)!(de))f]" }, // 296 { 6, 7, 13, ABC_CONST(0x8F70707000000000), "([(!(ab)c)(de)]f)" }, // 297 { 6, 7, 13, ABC_CONST(0x708F8F8F00000000), "(![(!(ab)c)(de)]f)" }, // 298 { 6, 9, 24, ABC_CONST(0x708F8F8F8F707070), "[(!(ab)c)(de)f]" }, // 299 { 6, 7, 11, ABC_CONST(0x0078787800000000), "([(ab)c]!(de)f)" }, // 300 { 6, 7, 11, ABC_CONST(0xFF87878700000000), "(!([(ab)c]!(de))f)" }, // 301 { 6, 9, 20, ABC_CONST(0xFF87878700787878), "[([(ab)c]!(de))f]" }, // 302 { 6, 7, 10, ABC_CONST(0x009F9F9F00000000), "(!([ab]c)!(de)f)" }, // 303 { 6, 7, 10, ABC_CONST(0xFF60606000000000), "(!(!([ab]c)!(de))f)" }, // 304 { 6, 9, 18, ABC_CONST(0xFF606060009F9F9F), "[(!([ab]c)!(de))f]" }, // 305 { 6, 9, 16, ABC_CONST(0x9F60606000000000), "([([ab]c)(de)]f)" }, // 306 { 6, 9, 16, ABC_CONST(0x609F9F9F00000000), "(![([ab]c)(de)]f)" }, // 307 { 6, 11, 30, ABC_CONST(0x609F9F9F9F606060), "[([ab]c)(de)f]" }, // 308 { 6, 9, 14, ABC_CONST(0x0096969600000000), "([abc]!(de)f)" }, // 309 { 6, 9, 14, ABC_CONST(0xFF69696900000000), "(!([abc]!(de))f)" }, // 310 { 6, 11, 26, ABC_CONST(0xFF69696900969696), "[([abc]!(de))f]" }, // 311 { 6, 6, 8, ABC_CONST(0x00CACACA00000000), "(!(de)f)" }, // 312 { 6, 6, 8, ABC_CONST(0xFF35353500000000), "(!(!(de))f)" }, // 313 { 6, 8, 14, ABC_CONST(0xFF35353500CACACA), "[(!(de))f]" }, // 314 { 6, 8, 13, ABC_CONST(0x35CACACA00000000), "([(de)]f)" }, // 315 { 6, 10, 24, ABC_CONST(0xCA35353535CACACA), "[(de)f]" }, // 316 { 6, 7, 10, ABC_CONST(0x007F7F0000000000), "(!(abc)[de]f)" }, // 317 { 6, 7, 10, ABC_CONST(0xFF8080FF00000000), "(!(!(abc)[de])f)" }, // 318 { 6, 9, 18, ABC_CONST(0xFF8080FF007F7F00), "[(!(abc)[de])f]" }, // 319 { 6, 7, 9, ABC_CONST(0x008F8F0000000000), "(!(!(ab)c)[de]f)" }, // 320 { 6, 7, 9, ABC_CONST(0xFF7070FF00000000), "(!(!(!(ab)c)[de])f)" }, // 321 { 6, 9, 16, ABC_CONST(0xFF7070FF008F8F00), "[(!(!(ab)c)[de])f]" }, // 322 { 6, 9, 12, ABC_CONST(0x0078780000000000), "([(ab)c][de]f)" }, // 323 { 6, 9, 12, ABC_CONST(0xFF8787FF00000000), "(!([(ab)c][de])f)" }, // 324 { 6, 11, 22, ABC_CONST(0xFF8787FF00787800), "[([(ab)c][de])f]" }, // 325 { 6, 9, 11, ABC_CONST(0x009F9F0000000000), "(!([ab]c)[de]f)" }, // 326 { 6, 9, 11, ABC_CONST(0xFF6060FF00000000), "(!(!([ab]c)[de])f)" }, // 327 { 6, 11, 20, ABC_CONST(0xFF6060FF009F9F00), "[(!([ab]c)[de])f]" }, // 328 { 6, 11, 15, ABC_CONST(0x0096960000000000), "([abc][de]f)" }, // 329 { 6, 11, 15, ABC_CONST(0xFF6969FF00000000), "(!([abc][de])f)" }, // 330 { 6, 13, 28, ABC_CONST(0xFF6969FF00969600), "[([abc][de])f]" }, // 331 { 6, 8, 9, ABC_CONST(0x00CACA0000000000), "([de]f)" }, // 332 { 6, 8, 9, ABC_CONST(0xFF3535FF00000000), "(!([de])f)" }, // 333 { 6, 10, 16, ABC_CONST(0xFF3535FF00CACA00), "[([de])f]" }, // 334 { 6, 6, 9, ABC_CONST(0xCAAAAAAA00000000), "(f)" }, // 335 { 6, 8, 16, ABC_CONST(0x35555555CAAAAAAA), "[f]" }, // 336 { 6, 6, 9, ABC_CONST(0xACCCAAAA00000000), "(f)" }, // 337 { 6, 8, 16, ABC_CONST(0x53335555ACCCAAAA), "[f]" }, // 338 { 6, 8, 13, ABC_CONST(0xACCCCAAA00000000), "(f)" }, // 339 { 6, 10, 24, ABC_CONST(0x53333555ACCCCAAA), "[f]" }, // 340 { 6, 8, 11, ABC_CONST(0xACCAAAAA00000000), "(f)" }, // 341 { 6, 10, 20, ABC_CONST(0x53355555ACCAAAAA), "[f]" }, // 342 { 6, 10, 17, ABC_CONST(0xCAACACCA00000000), "(f)" }, // 343 { 6, 12, 32, ABC_CONST(0x35535335CAACACCA), "[f]" }, // 344 { 6, 7, 9, ABC_CONST(0xCCAACACA00000000), "(>f)" }, // 345 { 6, 9, 16, ABC_CONST(0x33553535CCAACACA), "[>f]" }, // 346 { 6, 6, 8, ABC_CONST(0xC0AAAAAA00000000), "(f)" }, // 347 { 6, 6, 8, ABC_CONST(0x3F55555500000000), "(!f)" }, // 348 { 6, 8, 14, ABC_CONST(0x3F555555C0AAAAAA), "[f]" }, // 349 { 6, 8, 9, ABC_CONST(0x3CAAAAAA00000000), "(f)" }, // 350 { 6, 10, 16, ABC_CONST(0xC35555553CAAAAAA), "[f]" }, // 351 { 6, 6, 9, ABC_CONST(0xF088888800000000), "(<(ab)c(de)>f)" }, // 352 { 6, 6, 9, ABC_CONST(0x0F77777700000000), "(!<(ab)c(de)>f)" }, // 353 { 6, 8, 16, ABC_CONST(0x0F777777F0888888), "[<(ab)c(de)>f]" }, // 354 { 6, 8, 11, ABC_CONST(0x88F0F08800000000), "(<(ab)c[de]>f)" }, // 355 { 6, 8, 11, ABC_CONST(0x770F0F7700000000), "(!<(ab)c[de]>f)" }, // 356 { 6, 10, 20, ABC_CONST(0x770F0F7788F0F088), "[<(ab)c[de]>f]" }, // 357 { 6, 8, 11, ABC_CONST(0xF066666600000000), "(<[ab]c(de)>f)" }, // 358 { 6, 10, 20, ABC_CONST(0x0F999999F0666666), "[<[ab]c(de)>f]" }, // 359 { 6, 10, 13, ABC_CONST(0x66F0F06600000000), "(<[ab]c[de]>f)" }, // 360 { 6, 12, 24, ABC_CONST(0x990F0F9966F0F066), "[<[ab]c[de]>f]" }, // 361 { 6, 6, 7, ABC_CONST(0xF000888800000000), "(<(ab)(cd)e>f)" }, // 362 { 6, 6, 7, ABC_CONST(0x0FFF777700000000), "(!<(ab)(cd)e>f)" }, // 363 { 6, 8, 12, ABC_CONST(0x0FFF7777F0008888), "[<(ab)(cd)e>f]" }, // 364 { 6, 6, 7, ABC_CONST(0xF000777700000000), "(f)" }, // 365 { 6, 8, 12, ABC_CONST(0x0FFF8888F0007777), "[f]" }, // 366 { 6, 8, 8, ABC_CONST(0xF000666600000000), "(<[ab](cd)e>f)" }, // 367 { 6, 8, 8, ABC_CONST(0x0FFF999900000000), "(!<[ab](cd)e>f)" }, // 368 { 6, 10, 14, ABC_CONST(0x0FFF9999F0006666), "[<[ab](cd)e>f]" }, // 369 { 6, 10, 9, ABC_CONST(0x0FF0666600000000), "(<[ab][cd]e>f)" }, // 370 { 6, 12, 16, ABC_CONST(0xF00F99990FF06666), "[<[ab][cd]e>f]" }, // 371 { 6, 6, 7, ABC_CONST(0xFF00808000000000), "(<(abc)de>f)" }, // 372 { 6, 6, 7, ABC_CONST(0x00FF7F7F00000000), "(!<(abc)de>f)" }, // 373 { 6, 8, 12, ABC_CONST(0x00FF7F7FFF008080), "[<(abc)de>f]" }, // 374 { 6, 6, 7, ABC_CONST(0xFF00707000000000), "(<(!(ab)c)de>f)" }, // 375 { 6, 6, 7, ABC_CONST(0x00FF8F8F00000000), "(!<(!(ab)c)de>f)" }, // 376 { 6, 8, 12, ABC_CONST(0x00FF8F8FFF007070), "[<(!(ab)c)de>f]" }, // 377 { 6, 8, 9, ABC_CONST(0xFF00787800000000), "(<[(ab)c]de>f)" }, // 378 { 6, 10, 16, ABC_CONST(0x00FF8787FF007878), "[<[(ab)c]de>f]" }, // 379 { 6, 8, 8, ABC_CONST(0xFF00606000000000), "(<([ab]c)de>f)" }, // 380 { 6, 8, 8, ABC_CONST(0x00FF9F9F00000000), "(!<([ab]c)de>f)" }, // 381 { 6, 10, 14, ABC_CONST(0x00FF9F9FFF006060), "[<([ab]c)de>f]" }, // 382 { 6, 10, 11, ABC_CONST(0xFF00969600000000), "(<[abc]de>f)" }, // 383 { 6, 12, 20, ABC_CONST(0x00FF6969FF009696), "[<[abc]de>f]" }, // 384 { 6, 7, 7, ABC_CONST(0xFF00CACA00000000), "(<de>f)" }, // 385 { 6, 9, 12, ABC_CONST(0x00FF3535FF00CACA), "[<de>f]" }, // 386 { 6, 5, 10, ABC_CONST(0x00007FFF7FFF7FFF), "(!(abcd)!(ef))" }, // 387 { 6, 7, 15, ABC_CONST(0x7FFF800080008000), "[(abcd)(ef)]" }, // 388 { 6, 5, 8, ABC_CONST(0x000080FF80FF80FF), "(!(!(abc)d)!(ef))" }, // 389 { 6, 7, 15, ABC_CONST(0x80FF7F007F007F00), "[(!(abc)d)(ef)]" }, // 390 { 6, 7, 13, ABC_CONST(0x00007F807F807F80), "([(abc)d]!(ef))" }, // 391 { 6, 5, 9, ABC_CONST(0x00008FFF8FFF8FFF), "(!(!(ab)cd)!(ef))" }, // 392 { 6, 7, 15, ABC_CONST(0x8FFF700070007000), "[(!(ab)cd)(ef)]" }, // 393 { 6, 5, 9, ABC_CONST(0x000070FF70FF70FF), "(!(!(!(ab)c)d)!(ef))" }, // 394 { 6, 7, 15, ABC_CONST(0x70FF8F008F008F00), "[(!(!(ab)c)d)(ef)]" }, // 395 { 6, 7, 13, ABC_CONST(0x00008F708F708F70), "([(!(ab)c)d]!(ef))" }, // 396 { 6, 7, 12, ABC_CONST(0x000087FF87FF87FF), "(!([(ab)c]d)!(ef))" }, // 397 { 6, 9, 21, ABC_CONST(0x87FF780078007800), "[([(ab)c]d)(ef)]" }, // 398 { 6, 9, 19, ABC_CONST(0x0000877887788778), "([(ab)cd]!(ef))" }, // 399 { 6, 7, 11, ABC_CONST(0x00009FFF9FFF9FFF), "(!([ab]cd)!(ef))" }, // 400 { 6, 9, 18, ABC_CONST(0x9FFF600060006000), "[([ab]cd)(ef)]" }, // 401 { 6, 7, 10, ABC_CONST(0x000060FF60FF60FF), "(!(!([ab]c)d)!(ef))" }, // 402 { 6, 9, 18, ABC_CONST(0x60FF9F009F009F00), "[(!([ab]c)d)(ef)]" }, // 403 { 6, 9, 16, ABC_CONST(0x00009F609F609F60), "([([ab]c)d]!(ef))" }, // 404 { 6, 9, 15, ABC_CONST(0x000069FF69FF69FF), "(!([abc]d)!(ef))" }, // 405 { 6, 11, 27, ABC_CONST(0x69FF960096009600), "[([abc]d)(ef)]" }, // 406 { 6, 11, 25, ABC_CONST(0x0000699669966996), "([abcd]!(ef))" }, // 407 { 6, 6, 9, ABC_CONST(0x000035FF35FF35FF), "(!(d)!(ef))" }, // 408 { 6, 8, 15, ABC_CONST(0x35FFCA00CA00CA00), "[(d)(ef)]" }, // 409 { 6, 8, 13, ABC_CONST(0x000035CA35CA35CA), "([d]!(ef))" }, // 410 { 6, 5, 11, ABC_CONST(0x0000077707770777), "(!(ab)!(cd)!(ef))" }, // 411 { 6, 5, 9, ABC_CONST(0x0000F888F888F888), "(!(!(ab)!(cd))!(ef))" }, // 412 { 6, 7, 18, ABC_CONST(0xF888077707770777), "[(!(ab)!(cd))(ef)]" }, // 413 { 6, 7, 14, ABC_CONST(0x0000788878887888), "([(ab)(cd)]!(ef))" }, // 414 { 6, 7, 15, ABC_CONST(0x0000877787778777), "(![(ab)(cd)]!(ef))" }, // 415 { 6, 9, 27, ABC_CONST(0x8777788878887888), "[(ab)(cd)(ef)]" }, // 416 { 6, 7, 12, ABC_CONST(0x0000066606660666), "([ab]!(cd)!(ef))" }, // 417 { 6, 7, 11, ABC_CONST(0x0000F999F999F999), "(!([ab]!(cd))!(ef))" }, // 418 { 6, 9, 21, ABC_CONST(0xF999066606660666), "[([ab]!(cd))(ef)]" }, // 419 { 6, 9, 13, ABC_CONST(0x0000066006600660), "([ab][cd]!(ef))" }, // 420 { 6, 9, 13, ABC_CONST(0x0000F99FF99FF99F), "(!([ab][cd])!(ef))" }, // 421 { 6, 11, 24, ABC_CONST(0xF99F066006600660), "[([ab][cd])(ef)]" }, // 422 { 6, 6, 10, ABC_CONST(0x0000CAAACAAACAAA), "(!(ef))" }, // 423 { 6, 8, 18, ABC_CONST(0x3555CAAACAAACAAA), "[(ef)]" }, // 424 { 6, 8, 13, ABC_CONST(0x0000ACCAACCAACCA), "(!(ef))" }, // 425 { 6, 10, 24, ABC_CONST(0x5335ACCAACCAACCA), "[(ef)]" }, // 426 { 6, 6, 8, ABC_CONST(0x0000F088F088F088), "(<(ab)cd>!(ef))" }, // 427 { 6, 6, 9, ABC_CONST(0x00000F770F770F77), "(!<(ab)cd>!(ef))" }, // 428 { 6, 8, 15, ABC_CONST(0x0F77F088F088F088), "[<(ab)cd>(ef)]" }, // 429 { 6, 8, 10, ABC_CONST(0x0000F066F066F066), "(<[ab]cd>!(ef))" }, // 430 { 6, 10, 18, ABC_CONST(0x0F99F066F066F066), "[<[ab]cd>(ef)]" }, // 431 { 6, 7, 11, ABC_CONST(0x00007FFF7FFF0000), "(!(abcd)[ef])" }, // 432 { 6, 7, 9, ABC_CONST(0x000080FF80FF0000), "(!(!(abc)d)[ef])" }, // 433 { 6, 9, 14, ABC_CONST(0x00007F807F800000), "([(abc)d][ef])" }, // 434 { 6, 7, 10, ABC_CONST(0x00008FFF8FFF0000), "(!(!(ab)cd)[ef])" }, // 435 { 6, 7, 10, ABC_CONST(0x000070FF70FF0000), "(!(!(!(ab)c)d)[ef])" }, // 436 { 6, 9, 14, ABC_CONST(0x00008F708F700000), "([(!(ab)c)d][ef])" }, // 437 { 6, 9, 13, ABC_CONST(0x000087FF87FF0000), "(!([(ab)c]d)[ef])" }, // 438 { 6, 11, 20, ABC_CONST(0x0000877887780000), "([(ab)cd][ef])" }, // 439 { 6, 9, 12, ABC_CONST(0x00009FFF9FFF0000), "(!([ab]cd)[ef])" }, // 440 { 6, 9, 11, ABC_CONST(0x000060FF60FF0000), "(!(!([ab]c)d)[ef])" }, // 441 { 6, 11, 17, ABC_CONST(0x00009F609F600000), "([([ab]c)d][ef])" }, // 442 { 6, 11, 16, ABC_CONST(0x000069FF69FF0000), "(!([abc]d)[ef])" }, // 443 { 6, 13, 26, ABC_CONST(0x0000699669960000), "([abcd][ef])" }, // 444 { 6, 8, 10, ABC_CONST(0x000035FF35FF0000), "(!(d)[ef])" }, // 445 { 6, 10, 14, ABC_CONST(0x000035CA35CA0000), "([d][ef])" }, // 446 { 6, 7, 10, ABC_CONST(0x0000F888F8880000), "(!(!(ab)!(cd))[ef])" }, // 447 { 6, 9, 15, ABC_CONST(0x0000788878880000), "([(ab)(cd)][ef])" }, // 448 { 6, 9, 16, ABC_CONST(0x0000877787770000), "(![(ab)(cd)][ef])" }, // 449 { 6, 9, 12, ABC_CONST(0x0000F999F9990000), "(!([ab]!(cd))[ef])" }, // 450 { 6, 11, 14, ABC_CONST(0x0000066006600000), "([ab][cd][ef])" }, // 451 { 6, 11, 14, ABC_CONST(0x0000F99FF99F0000), "(!([ab][cd])[ef])" }, // 452 { 6, 8, 11, ABC_CONST(0x0000CAAACAAA0000), "([ef])" }, // 453 { 6, 10, 14, ABC_CONST(0x0000ACCAACCA0000), "([ef])" }, // 454 { 6, 8, 9, ABC_CONST(0x0000F088F0880000), "(<(ab)cd>[ef])" }, // 455 { 6, 8, 10, ABC_CONST(0x00000F770F770000), "(!<(ab)cd>[ef])" }, // 456 { 6, 10, 11, ABC_CONST(0x0000F066F0660000), "(<[ab]cd>[ef])" }, // 457 { 6, 5, 11, ABC_CONST(0x007F7F7F7F7F7F7F), "(!(abc)!(def))" }, // 458 { 6, 7, 16, ABC_CONST(0x7F80808080808080), "[(abc)(def)]" }, // 459 { 6, 5, 9, ABC_CONST(0x008F8F8F8F8F8F8F), "(!(!(ab)c)!(def))" }, // 460 { 6, 7, 16, ABC_CONST(0x8F70707070707070), "[(!(ab)c)(def)]" }, // 461 { 6, 7, 13, ABC_CONST(0x0078787878787878), "([(ab)c]!(def))" }, // 462 { 6, 7, 12, ABC_CONST(0x009F9F9F9F9F9F9F), "(!([ab]c)!(def))" }, // 463 { 6, 9, 20, ABC_CONST(0x9F60606060606060), "[([ab]c)(def)]" }, // 464 { 6, 9, 17, ABC_CONST(0x0096969696969696), "([abc]!(def))" }, // 465 { 6, 6, 9, ABC_CONST(0x00CACACACACACACA), "(!(def))" }, // 466 { 6, 8, 16, ABC_CONST(0x35CACACACACACACA), "[(def)]" }, // 467 { 6, 5, 8, ABC_CONST(0x8F0000008F8F8F8F), "(!(!(ab)c)!(!(de)f))" }, // 468 { 6, 7, 16, ABC_CONST(0x708F8F8F70707070), "[(!(ab)c)(!(de)f)]" }, // 469 { 6, 7, 11, ABC_CONST(0x7800000078787878), "([(ab)c]!(!(de)f))" }, // 470 { 6, 7, 10, ABC_CONST(0x9F0000009F9F9F9F), "(!([ab]c)!(!(de)f))" }, // 471 { 6, 9, 20, ABC_CONST(0x609F9F9F60606060), "[([ab]c)(!(de)f)]" }, // 472 { 6, 9, 14, ABC_CONST(0x9600000096969696), "([abc]!(!(de)f))" }, // 473 { 6, 6, 8, ABC_CONST(0xCA000000CACACACA), "(!(!(de)f))" }, // 474 { 6, 8, 16, ABC_CONST(0xCA353535CACACACA), "[(!(de)f)]" }, // 475 { 6, 9, 15, ABC_CONST(0x0078787878000000), "([(ab)c][(de)f])" }, // 476 { 6, 9, 14, ABC_CONST(0x009F9F9F9F000000), "(!([ab]c)[(de)f])" }, // 477 { 6, 11, 19, ABC_CONST(0x0096969696000000), "([abc][(de)f])" }, // 478 { 6, 8, 11, ABC_CONST(0x00CACACACA000000), "([(de)f])" }, // 479 { 6, 9, 13, ABC_CONST(0x9F00009F9F9F9F9F), "(!([ab]c)!([de]f))" }, // 480 { 6, 11, 25, ABC_CONST(0x609F9F6060606060), "[([ab]c)([de]f)]" }, // 481 { 6, 11, 18, ABC_CONST(0x9600009696969696), "([abc]!([de]f))" }, // 482 { 6, 8, 10, ABC_CONST(0xCA0000CACACACACA), "(!([de]f))" }, // 483 { 6, 10, 20, ABC_CONST(0xCA3535CACACACACA), "[([de]f)]" }, // 484 { 6, 13, 24, ABC_CONST(0x9600009600969600), "([abc][def])" }, // 485 { 6, 10, 14, ABC_CONST(0xCA0000CA00CACA00), "([def])" }, // 486 { 6, 7, 8, ABC_CONST(0xCACA0000CA00CA00), "()" }, // 487 { 6, 9, 16, ABC_CONST(0x3535CACA35CA35CA), "[]" }, // 488 { 6, 6, 10, ABC_CONST(0xCAAAAAAAAAAAAAAA), "" }, // 489 { 6, 6, 10, ABC_CONST(0xACCCCCCCAAAAAAAA), "" }, // 490 { 6, 8, 16, ABC_CONST(0xACCCCCCCCAAAAAAA), "" }, // 491 { 6, 6, 10, ABC_CONST(0xACCCAAAAAAAAAAAA), "" }, // 492 { 6, 6, 10, ABC_CONST(0xCAAACCCCAAAAAAAA), "" }, // 493 { 6, 8, 16, ABC_CONST(0xCAAACCCCACCCAAAA), "" }, // 494 { 6, 8, 14, ABC_CONST(0xACCCCAAAAAAAAAAA), "" }, // 495 { 6, 10, 24, ABC_CONST(0xCAAAACCCACCCCAAA), "" }, // 496 { 6, 8, 12, ABC_CONST(0xACCAAAAAAAAAAAAA), "" }, // 497 { 6, 8, 12, ABC_CONST(0xCAACCCCCAAAAAAAA), "" }, // 498 { 6, 10, 20, ABC_CONST(0xCAACCCCCACCAAAAA), "" }, // 499 { 6, 10, 18, ABC_CONST(0xCAACACCAAAAAAAAA), "" }, // 500 { 6, 12, 32, ABC_CONST(0xACCACAACCAACACCA), "" }, // 501 { 6, 7, 10, ABC_CONST(0xCCAACACAAAAAAAAA), "f)>" }, // 502 { 6, 9, 16, ABC_CONST(0xAACCACACCCAACACA), "f]>" }, // 503 { 6, 6, 12, ABC_CONST(0xAAAAACCCACCCACCC), "" }, // 504 { 6, 8, 18, ABC_CONST(0xACCCCAAACAAACAAA), "" }, // 505 { 6, 8, 14, ABC_CONST(0xAAAAACCAACCAACCA), "" }, // 506 { 6, 10, 16, ABC_CONST(0xAAAAACCAACCAAAAA), "" }, // 507 { 6, 7, 12, ABC_CONST(0xCCAACACACACACACA), ">" }, // 508 { 6, 9, 16, ABC_CONST(0xCACACCAACCAACACA), ">" }, // 509 { 6, 7, 10, ABC_CONST(0xCCCCAAAACAAACAAA), ">" }, // 510 { 6, 9, 12, ABC_CONST(0xCCCCAAAAACCAACCA), ">" }, // 511 { 6, 6, 9, ABC_CONST(0xC0AAAAAAAAAAAAAA), "" }, // 512 { 6, 6, 10, ABC_CONST(0xAAC0C0C0AAAAAAAA), "" }, // 513 { 6, 8, 12, ABC_CONST(0xAAC0C0AAAAAAAAAA), "" }, // 514 { 6, 8, 10, ABC_CONST(0x3CAAAAAAAAAAAAAA), "" }, // 515 { 6, 8, 12, ABC_CONST(0xAA3C3C3CAAAAAAAA), "" }, // 516 { 6, 10, 14, ABC_CONST(0xAA3C3CAAAAAAAAAA), "" }, // 517 { 6, 6, 8, ABC_CONST(0xC000AAAAAAAAAAAA), "" }, // 518 { 6, 6, 8, ABC_CONST(0x3F00AAAAAAAAAAAA), "" }, // 519 { 6, 8, 10, ABC_CONST(0x3FC0AAAAAAAAAAAA), "" }, // 520 { 6, 8, 9, ABC_CONST(0x3C00AAAAAAAAAAAA), "" }, // 521 { 6, 10, 12, ABC_CONST(0xC33CAAAAAAAAAAAA), "" }, // 522 { 6, 7, 8, ABC_CONST(0xF0CCAAAAAAAAAAAA), "(ef)>" }, // 523 { 6, 6, 11, ABC_CONST(0xF088888888888888), "<(ab)c(def)>" }, // 524 { 6, 6, 10, ABC_CONST(0x88F0F0F088888888), "<(ab)c(!(de)f)>" }, // 525 { 6, 8, 15, ABC_CONST(0x88F0F0F0F0888888), "<(ab)c[(de)f]>" }, // 526 { 6, 8, 13, ABC_CONST(0x88F0F08888888888), "<(ab)c([de]f)>" }, // 527 { 6, 10, 20, ABC_CONST(0xF08888F088F0F088), "<(ab)c[def]>" }, // 528 { 6, 7, 10, ABC_CONST(0xF0F08888F088F088), "<(ab)c>" }, // 529 { 6, 8, 14, ABC_CONST(0xF066666666666666), "<[ab]c(def)>" }, // 530 { 6, 8, 12, ABC_CONST(0x66F0F0F066666666), "<[ab]c(!(de)f)>" }, // 531 { 6, 10, 18, ABC_CONST(0x66F0F0F0F0666666), "<[ab]c[(de)f]>" }, // 532 { 6, 10, 16, ABC_CONST(0x66F0F06666666666), "<[ab]c([de]f)>" }, // 533 { 6, 12, 24, ABC_CONST(0xF06666F066F0F066), "<[ab]c[def]>" }, // 534 { 6, 9, 12, ABC_CONST(0xF0F06666F066F066), "<[ab]c>" }, // 535 { 6, 6, 9, ABC_CONST(0xF000888888888888), "<(ab)(cd)(ef)>" }, // 536 { 6, 6, 9, ABC_CONST(0xF000777777777777), "" }, // 537 { 6, 8, 12, ABC_CONST(0x8888F000F0008888), "<(ab)(cd)[ef]>" }, // 538 { 6, 8, 12, ABC_CONST(0x7777F000F0007777), "" }, // 539 { 6, 8, 10, ABC_CONST(0x0FF0888888888888), "<(ab)[cd](ef)>" }, // 540 { 6, 8, 11, ABC_CONST(0xF000666666666666), "<[ab](cd)(ef)>" }, // 541 { 6, 10, 14, ABC_CONST(0x6666F000F0006666), "<[ab](cd)[ef]>" }, // 542 { 6, 10, 12, ABC_CONST(0x0FF0666666666666), "<[ab][cd](ef)>" }, // 543 { 6, 12, 16, ABC_CONST(0x66660FF00FF06666), "<[ab][cd][ef]>" }, // 544 { 6, 6, 10, ABC_CONST(0xFF00808080808080), "<(abc)d(ef)>" }, // 545 { 6, 8, 12, ABC_CONST(0x8080FF00FF008080), "<(abc)d[ef]>" }, // 546 { 6, 6, 10, ABC_CONST(0xFF00707070707070), "<(!(ab)c)d(ef)>" }, // 547 { 6, 8, 12, ABC_CONST(0x7070FF00FF007070), "<(!(ab)c)d[ef]>" }, // 548 { 6, 8, 14, ABC_CONST(0xFF00787878787878), "<[(ab)c]d(ef)>" }, // 549 { 6, 10, 16, ABC_CONST(0x7878FF00FF007878), "<[(ab)c]d[ef]>" }, // 550 { 6, 8, 12, ABC_CONST(0xFF00606060606060), "<([ab]c)d(ef)>" }, // 551 { 6, 10, 14, ABC_CONST(0x6060FF00FF006060), "<([ab]c)d[ef]>" }, // 552 { 6, 10, 18, ABC_CONST(0xFF00969696969696), "<[abc]d(ef)>" }, // 553 { 6, 12, 20, ABC_CONST(0x9696FF00FF009696), "<[abc]d[ef]>" }, // 554 { 6, 7, 10, ABC_CONST(0xFF00CACACACACACA), "<d(ef)>" }, // 555 { 6, 9, 12, ABC_CONST(0xCACAFF00FF00CACA), "<d[ef]>" }, // 556 { 6, 6, 7, ABC_CONST(0xFF00000080808080), "<(abc)(de)f>" }, // 557 { 6, 6, 7, ABC_CONST(0xFF0000007F7F7F7F), "" }, // 558 { 6, 8, 8, ABC_CONST(0x00FFFF0080808080), "<(abc)[de]f>" }, // 559 { 6, 6, 7, ABC_CONST(0xFF00000070707070), "<(!(ab)c)(de)f>" }, // 560 { 6, 6, 7, ABC_CONST(0xFF0000008F8F8F8F), "" }, // 561 { 6, 8, 8, ABC_CONST(0x00FFFF0070707070), "<(!(ab)c)[de]f>" }, // 562 { 6, 8, 9, ABC_CONST(0xFF00000078787878), "<[(ab)c](de)f>" }, // 563 { 6, 10, 10, ABC_CONST(0x00FFFF0078787878), "<[(ab)c][de]f>" }, // 564 { 6, 8, 8, ABC_CONST(0xFF00000060606060), "<([ab]c)(de)f>" }, // 565 { 6, 8, 8, ABC_CONST(0xFF0000009F9F9F9F), "" }, // 566 { 6, 10, 9, ABC_CONST(0x00FFFF0060606060), "<([ab]c)[de]f>" }, // 567 { 6, 10, 11, ABC_CONST(0xFF00000096969696), "<[abc](de)f>" }, // 568 { 6, 12, 12, ABC_CONST(0x00FFFF0096969696), "<[abc][de]f>" }, // 569 { 6, 7, 7, ABC_CONST(0xFF000000CACACACA), "<(de)f>" }, // 570 { 6, 9, 8, ABC_CONST(0x00FFFF00CACACACA), "<[de]f>" }, // 571 { 6, 6, 7, ABC_CONST(0xFFFF000080008000), "<(abcd)ef>" }, // 572 { 6, 6, 7, ABC_CONST(0xFFFF00007F007F00), "<(!(abc)d)ef>" }, // 573 { 6, 8, 10, ABC_CONST(0xFFFF00007F807F80), "<[(abc)d]ef>" }, // 574 { 6, 6, 7, ABC_CONST(0xFFFF000070007000), "<(!(ab)cd)ef>" }, // 575 { 6, 6, 7, ABC_CONST(0xFFFF00008F008F00), "<(!(!(ab)c)d)ef>" }, // 576 { 6, 8, 10, ABC_CONST(0xFFFF00008F708F70), "<[(!(ab)c)d]ef>" }, // 577 { 6, 8, 9, ABC_CONST(0xFFFF000078007800), "<([(ab)c]d)ef>" }, // 578 { 6, 10, 14, ABC_CONST(0xFFFF000087788778), "<[(ab)cd]ef>" }, // 579 { 6, 8, 8, ABC_CONST(0xFFFF000060006000), "<([ab]cd)ef>" }, // 580 { 6, 8, 8, ABC_CONST(0xFFFF00009F009F00), "<(!([ab]c)d)ef>" }, // 581 { 6, 10, 12, ABC_CONST(0xFFFF00009F609F60), "<[([ab]c)d]ef>" }, // 582 { 6, 10, 11, ABC_CONST(0xFFFF000096009600), "<([abc]d)ef>" }, // 583 { 6, 12, 18, ABC_CONST(0xFFFF000069966996), "<[abcd]ef>" }, // 584 { 6, 7, 7, ABC_CONST(0xFFFF0000CA00CA00), "<(d)ef>" }, // 585 { 6, 9, 10, ABC_CONST(0xFFFF000035CA35CA), "<[d]ef>" }, // 586 { 6, 6, 8, ABC_CONST(0xFFFF000007770777), "<(!(ab)!(cd))ef>" }, // 587 { 6, 8, 11, ABC_CONST(0xFFFF000078887888), "<[(ab)(cd)]ef>" }, // 588 { 6, 8, 9, ABC_CONST(0xFFFF000006660666), "<([ab]!(cd))ef>" }, // 589 { 6, 10, 10, ABC_CONST(0xFFFF000006600660), "<([ab][cd])ef>" }, // 590 { 6, 7, 8, ABC_CONST(0xFFFF0000CAAACAAA), "<ef>" }, // 591 { 6, 9, 10, ABC_CONST(0xFFFF0000ACCAACCA), "<ef>" }, // 592 { 6, 7, 7, ABC_CONST(0xFFFF0000F088F088), "<<(ab)cd>ef>" }, // 593 { 6, 9, 8, ABC_CONST(0xFFFF0000F066F066), "<<[ab]cd>ef>" } // 594 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Mpm_ManGetTruthWithCnf( int Limit ) { Vec_Wrd_t * vRes = Vec_WrdAlloc( 1000 ); int i; for ( i = 0; i < 595; i++ ) if ( s_DsdClass6[i].nClauses <= Limit ) Vec_WrdPush( vRes, s_DsdClass6[i].uTruth ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mpm_ManPrintDsdStats( Mpm_Man_t * p ) { int i, Absent = 0; for ( i = 0; i < 595; i++ ) { if ( p->nCountDsd[i] == 0 ) { Absent++; continue; } if ( p->pPars->fVeryVerbose ) { printf( "%5d : ", i ); printf( "%-20s ", p->pDsd6[i].pStr ); printf( "%8d ", p->nCountDsd[i] ); printf( "\n" ); } } printf( "Unused classes = %d (%.2f %%). ", Absent, 100.0 * Absent / 595 ); printf( "Non-DSD cuts = %d (%.2f %%). ", p->nNonDsd, 100.0 * p->nNonDsd / p->nCutsMergedAll ); printf( "No-match cuts = %d (%.2f %%).\n", p->nNoMatch, 100.0 * p->nNoMatch / p->nCutsMergedAll ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hsh_IntMan_t * Mpm_ManBuildHashTable( Vec_Int_t ** pvConfgRes ) { FILE * pFile; char * pFileName = "dsdfuncs6.dat"; int RetValue, size = Extra_FileSize( pFileName ) / 12; // 2866420 Vec_Wrd_t * vTruthRes = Vec_WrdAlloc( size ); Vec_Int_t * vConfgRes = Vec_IntAlloc( size ); Hsh_IntMan_t * pHash; pFile = fopen( pFileName, "rb" ); RetValue = fread( Vec_WrdArray(vTruthRes), sizeof(word), size, pFile ); RetValue = fread( Vec_IntArray(vConfgRes), sizeof(int), size, pFile ); vTruthRes->nSize = size; vConfgRes->nSize = size; // create hash table pHash = Hsh_WrdManHashArrayStart( vTruthRes, 1 ); // cleanup if ( pvConfgRes ) *pvConfgRes = vConfgRes; else Vec_IntFree( vConfgRes ); Vec_WrdFree( vTruthRes ); // Hsh_IntManStop( pHash ); return pHash; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mpm_ManPrintPerm( unsigned s ) { int i; for ( i = 0; i < 6; i++ ) printf( "%d ", (s >> (3*i)) & 7 ); printf( " " ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mpm_ManPrecomputePerms( Mpm_Man_t * p ) { int nVars = 6; // 0(1:1) 1(2:1) 2(4:2) 3(10:6) 4(33:23) 5(131:98) 6(595:464) int nClasses[7] = { 1, 2, 4, 10, 33, 131, 595 }; int nPerms = Extra_Factorial( nVars ); // int nSwaps = (1 << nVars); int * pComp, * pPerm; int i, k, x, One, OneCopy, Num; Vec_Int_t * vVars; abctime clk = Abc_Clock(); assert( p->pDsd6 == NULL ); p->pDsd6 = s_DsdClass6; // precompute schedules pComp = Extra_GreyCodeSchedule( nVars ); pPerm = Extra_PermSchedule( nVars ); // map numbers into perms p->vMap2Perm = Vec_IntStartFull( (1<<(3*nVars)) ); // store permutations One = 0; for ( x = 0; x < nVars; x++ ) { p->Perm6[0][x] = (char)x; One |= (x << (3*x)); } // Vec_IntWriteEntry( p->vMap2Perm, One, 0 ); OneCopy = One; for ( k = 0; k < nPerms; k++ ) { if ( k > 0 ) for ( x = 0; x < nVars; x++ ) p->Perm6[k][x] = p->Perm6[k-1][x]; ABC_SWAP( char, p->Perm6[k][pPerm[k]], p->Perm6[k][pPerm[k]+1] ); Num = ( (One >> (3*(pPerm[k] ))) ^ (One >> (3*(pPerm[k]+1))) ) & 7; One ^= (Num << (3*(pPerm[k] ))); One ^= (Num << (3*(pPerm[k]+1))); Vec_IntWriteEntry( p->vMap2Perm, One, k ); // Mpm_ManPrintPerm( One ); // for ( x = 0; x < nVars; x++ ) // printf( "%d ", p->Perm6[k][x] ); // printf( "\n" ); } assert( OneCopy == One ); // fill in the gaps vVars = Vec_IntAlloc( 6 ); Vec_IntForEachEntry( p->vMap2Perm, Num, i ) { // mark used variables int Count = 0; One = i; Vec_IntFill( vVars, 6, 0 ); for ( k = 0; k < nVars; k++ ) { int iVar = ((One >> (3*k)) & 7); if ( iVar >= nVars && iVar < 7 ) break; if ( iVar != 7 ) { if ( Vec_IntEntry( vVars, iVar ) == 1 ) break; Vec_IntWriteEntry( vVars, iVar, 1 ); Count++; } } // skip ones with dups and complete if ( k < nVars || Count == nVars ) continue; // find unused variables for ( x = k = 0; k < 6; k++ ) if ( Vec_IntEntry(vVars, k) == 0 ) Vec_IntWriteEntry( vVars, x++, k ); Vec_IntShrink( vVars, x ); // fill in used variables x = 0; for ( k = 0; k < nVars; k++ ) { int iVar = ((One >> (3*k)) & 7); if ( iVar == 7 ) One ^= ((Vec_IntEntry(vVars, x++) ^ 7) << (3*k)); } assert( x == Vec_IntSize(vVars) ); // save this one assert( Vec_IntEntry( p->vMap2Perm, One ) != -1 ); Vec_IntWriteEntry( p->vMap2Perm, i, Vec_IntEntry(p->vMap2Perm, One) ); /* // mapping Mpm_ManPrintPerm( i ); printf( "-> " ); Mpm_ManPrintPerm( One ); printf( "\n" ); */ } Vec_IntFree( vVars ); // store permuted truth tables assert( p->vPerm6 == NULL ); p->vPerm6 = Vec_WrdAlloc( nPerms * 595 ); for ( i = 0; i < nClasses[nVars]; i++ ) { word uTruth = s_DsdClass6[i].uTruth; for ( k = 0; k < nPerms; k++ ) { uTruth = Abc_Tt6SwapAdjacent( uTruth, pPerm[k] ); Vec_WrdPush( p->vPerm6, uTruth ); } assert( uTruth == s_DsdClass6[i].uTruth ); } ABC_FREE( pPerm ); ABC_FREE( pComp ); // build hash table p->pHash = Mpm_ManBuildHashTable( &p->vConfgRes ); Abc_PrintTime( 1, "Setting up DSD information", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Mpm_CutTruthFromDsd( Mpm_Man_t * pMan, Mpm_Cut_t * pCut, int iClass ) { int i; word uTruth = pMan->pDsd6[iClass].uTruth; assert( pMan->pDsd6[iClass].nVars == (int)pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) if ( Abc_LitIsCompl(pCut->pLeaves[i]) ) uTruth = Abc_Tt6Flip( uTruth, i ); return uTruth; } /**Function************************************************************* Synopsis [Checks hash table for DSD class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mpm_CutCheckDsd6( Mpm_Man_t * p, word t ) { int fCompl, Entry, Config; if ( (fCompl = (t & 1)) ) t = ~t; Entry = *Hsh_IntManLookup( p->pHash, (unsigned *)&t ); if ( Entry == -1 ) return -1; Config = Vec_IntEntry( p->vConfgRes, Entry ); if ( fCompl ) Config ^= (1 << 16); return Config; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mpm_CutComputeDsd6( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type ) { int fVerbose = 0; int i, Config, iClass, fCompl; int pLeavesNew[6] = { -1, -1, -1, -1, -1, -1 }; word t = 0; if ( pCutC == NULL ) { word t0, t1; int iClass0 = Abc_Lit2Var(pCut0->iFunc); int iClass1 = Abc_Lit2Var(pCut1->iFunc); word Truth0 = p->pDsd6[iClass0].uTruth; int Perm1 = Vec_IntEntry( p->vMap2Perm, p->uPermMask[1] ); word Truth1p = Vec_WrdEntry( p->vPerm6, iClass1 * 720 + Perm1 ); if ( p->uComplMask[1] ) { for ( i = 0; i < 6; i++ ) if ( (p->uComplMask[1] >> i) & 1 ) Truth1p = Abc_Tt6Flip( Truth1p, i ); } t0 = (fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iFunc)) ? ~Truth0 : Truth0; t1 = (fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iFunc)) ? ~Truth1p : Truth1p; if ( Type == 1 ) t = t0 & t1; else if ( Type == 2 ) t = t0 ^ t1; else assert( 0 ); if ( fVerbose ) { Mpm_ManPrintPerm( p->uPermMask[1] ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&Truth0, 6 ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&Truth1p, 6 ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ); printf( "\n" ); } } else { word t0, t1, tC; int iClass0 = Abc_Lit2Var(pCut0->iFunc); int iClass1 = Abc_Lit2Var(pCut1->iFunc); int iClassC = Abc_Lit2Var(pCutC->iFunc); word Truth0 = p->pDsd6[iClass0].uTruth; int Perm1 = Vec_IntEntry( p->vMap2Perm, p->uPermMask[1] ); int PermC = Vec_IntEntry( p->vMap2Perm, p->uPermMask[2] ); word Truth1p = Vec_WrdEntry( p->vPerm6, iClass1 * 720 + Perm1 ); word TruthCp = Vec_WrdEntry( p->vPerm6, iClassC * 720 + PermC ); if ( p->uComplMask[1] ) { for ( i = 0; i < 6; i++ ) if ( (p->uComplMask[1] >> i) & 1 ) Truth1p = Abc_Tt6Flip( Truth1p, i ); } if ( p->uComplMask[2] ) { for ( i = 0; i < 6; i++ ) if ( (p->uComplMask[2] >> i) & 1 ) TruthCp = Abc_Tt6Flip( TruthCp, i ); } t0 = (fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iFunc)) ? ~Truth0 : Truth0; t1 = (fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iFunc)) ? ~Truth1p : Truth1p; tC = (fComplC ^ pCutC->fCompl ^ Abc_LitIsCompl(pCutC->iFunc)) ? ~TruthCp : TruthCp; t = (tC & t1) | (~tC & t0); } // find configuration Config = Mpm_CutCheckDsd6( p, t ); if ( Config == -1 ) { p->nNonDsd++; return 0; } // get the class iClass = Config >> 17; fCompl = (Config >> 16) & 1; Config &= 0xFFFF; // check if the gate exists if ( p->pPars->fMap4Gates ) { if ( Vec_IntSize(Vec_WecEntry(p->vNpnConfigs, iClass)) == 0 ) { p->nNoMatch++; return 0; } } // set the function pCut->iFunc = Abc_Var2Lit( iClass, fCompl ); if ( fVerbose ) { Mpm_CutPrint( pCut0 ); Mpm_CutPrint( pCut1 ); Mpm_CutPrint( pCut ); } // update cut assert( (Config >> 6) < 720 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) pLeavesNew[(int)(p->Perm6[Config >> 6][i])] = Abc_LitNotCond( pCut->pLeaves[i], (Config >> i) & 1 ); pCut->nLeaves = p->pDsd6[iClass].nVars; for ( i = 0; i < (int)pCut->nLeaves; i++ ) assert( pLeavesNew[i] != -1 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) pCut->pLeaves[i] = pLeavesNew[i]; p->nCountDsd[iClass]++; p->nSmallSupp += (int)(pCut->nLeaves < 2); if ( fVerbose ) { printf( "Computed " ); Mpm_CutPrint( pCut ); printf( "\n" ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmGates.c000066400000000000000000000233711300674244400233310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmGates.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Standard-cell mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmGates.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "map/scl/sclSize.h" #include "map/scl/sclTime.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Finds matches fore each DSD class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Mpm_ManFindDsdMatches( Mpm_Man_t * p, void * pScl ) { int fVerbose = p->pPars->fVeryVerbose; SC_Lib * pLib = (SC_Lib *)pScl; Vec_Wec_t * vClasses; Vec_Int_t * vClass; SC_Cell * pRepr; int i, Config, iClass; word Truth; vClasses = Vec_WecStart( 600 ); SC_LibForEachCellClass( pLib, pRepr, i ) { if ( pRepr->n_inputs > 6 || pRepr->n_outputs > 1 ) { if ( fVerbose ) printf( "Skipping cell %s with %d inputs and %d outputs\n", pRepr->pName, pRepr->n_inputs, pRepr->n_outputs ); continue; } Truth = *Vec_WrdArray( &SC_CellPin(pRepr, pRepr->n_inputs)->vFunc ); Config = Mpm_CutCheckDsd6( p, Truth ); if ( Config == -1 ) { if ( fVerbose ) printf( "Skipping cell %s with non-DSD function\n", pRepr->pName ); continue; } iClass = Config >> 17; Config = (pRepr->Id << 17) | (Config & 0x1FFFF); // write gate and NPN config for this DSD class vClass = Vec_WecEntry( vClasses, iClass ); Vec_IntPush( vClass, Config ); if ( !fVerbose ) continue; printf( "Gate %5d %-30s : ", pRepr->Id, pRepr->pName ); printf( "Class %3d ", iClass ); printf( "Area %10.3f ", pRepr->area ); Extra_PrintBinary( stdout, (unsigned *)&Config, 17 ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned *)&Truth, pRepr->n_inputs ); printf( "\n" ); } return vClasses; } /**Function************************************************************* Synopsis [Find mapping of DSD classes into Genlib library cells.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Mpm_ManFindCells( Mio_Library_t * pMio, SC_Lib * pScl, Vec_Wec_t * vNpnConfigs ) { Vec_Ptr_t * vNpnGatesMio; Vec_Int_t * vClass; Mio_Gate_t * pMioGate; SC_Cell * pCell; int Config, iClass; vNpnGatesMio = Vec_PtrStart( Vec_WecSize(vNpnConfigs) ); Vec_WecForEachLevel( vNpnConfigs, vClass, iClass ) { if ( Vec_IntSize(vClass) == 0 ) continue; Config = Vec_IntEntry(vClass, 0); pCell = SC_LibCell( pScl, (Config >> 17) ); pMioGate = Mio_LibraryReadGateByName( pMio, pCell->pName, NULL ); if ( pMioGate == NULL ) { Vec_PtrFree( vNpnGatesMio ); return NULL; } assert( pMioGate != NULL ); Vec_PtrWriteEntry( vNpnGatesMio, iClass, pMioGate ); } return vNpnGatesMio; } /**Function************************************************************* Synopsis [Derive mapped network as an ABC network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Mpm_ManFindMappedNodes( Mpm_Man_t * p ) { Vec_Int_t * vNodes; Mig_Obj_t * pObj; vNodes = Vec_IntAlloc( 1000 ); Mig_ManForEachObj( p->pMig, pObj ) if ( Mig_ObjIsNode(pObj) && Mpm_ObjMapRef(p, pObj) ) Vec_IntPush( vNodes, Mig_ObjId(pObj) ); return vNodes; } Abc_Obj_t * Mpm_ManGetAbcNode( Abc_Ntk_t * pNtk, Vec_Int_t * vCopy, int iMigLit ) { Abc_Obj_t * pObj; int iObjId = Vec_IntEntry( vCopy, iMigLit ); if ( iObjId >= 0 ) return Abc_NtkObj( pNtk, iObjId ); iObjId = Vec_IntEntry( vCopy, Abc_LitNot(iMigLit) ); assert( iObjId >= 0 ); pObj = Abc_NtkCreateNodeInv( pNtk, Abc_NtkObj(pNtk, iObjId) ); Vec_IntWriteEntry( vCopy, iMigLit, Abc_ObjId(pObj) ); return pObj; } Abc_Ntk_t * Mpm_ManDeriveMappedAbcNtk( Mpm_Man_t * p, Mio_Library_t * pMio ) { Abc_Ntk_t * pNtk; Vec_Ptr_t * vNpnGatesMio; Vec_Int_t * vNodes, * vCopy, * vClass; Abc_Obj_t * pObj, * pFanin; Mig_Obj_t * pNode; Mpm_Cut_t * pCutBest; int i, k, iNode, iMigLit, fCompl, Config; // find mapping of SCL cells into MIO cells vNpnGatesMio = Mpm_ManFindCells( pMio, (SC_Lib *)p->pPars->pScl, p->vNpnConfigs ); if ( vNpnGatesMio == NULL ) { printf( "Genlib library does not match SCL library.\n" ); return NULL; } // create mapping for each phase of each node vCopy = Vec_IntStartFull( 2 * Mig_ManObjNum(p->pMig) ); // get internal nodes vNodes = Mpm_ManFindMappedNodes( p ); // start the network pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_MAP, 1 ); pNtk->pName = Extra_UtilStrsav( p->pMig->pName ); pNtk->pManFunc = pMio; // create primary inputs Mig_ManForEachCi( p->pMig, pNode, i ) { pObj = Abc_NtkCreatePi(pNtk); Vec_IntWriteEntry( vCopy, Abc_Var2Lit( Mig_ObjId(pNode), 0 ), Abc_ObjId(pObj) ); } Abc_NtkAddDummyPiNames( pNtk ); // create constant nodes Mig_ManForEachCo( p->pMig, pNode, i ) if ( Mig_ObjFaninLit(pNode, 0) == 0 ) { pObj = Abc_NtkCreateNodeConst0(pNtk); Vec_IntWriteEntry( vCopy, Abc_Var2Lit( 0, 0 ), Abc_ObjId(pObj) ); break; } Mig_ManForEachCo( p->pMig, pNode, i ) if ( Mig_ObjFaninLit(pNode, 0) == 1 ) { pObj = Abc_NtkCreateNodeConst1(pNtk); Vec_IntWriteEntry( vCopy, Abc_Var2Lit( 0, 1 ), Abc_ObjId(pObj) ); break; } // create internal nodes Vec_IntForEachEntry( vNodes, iNode, i ) { pCutBest = Mpm_ObjCutBestP( p, Mig_ManObj(p->pMig, iNode) ); vClass = Vec_WecEntry( p->vNpnConfigs, Abc_Lit2Var(pCutBest->iFunc) ); Config = Vec_IntEntry( vClass, 0 ); pObj = Abc_NtkCreateNode( pNtk ); pObj->pData = Vec_PtrEntry( vNpnGatesMio, Abc_Lit2Var(pCutBest->iFunc) ); assert( pObj->pData != NULL ); fCompl = pCutBest->fCompl ^ Abc_LitIsCompl(pCutBest->iFunc) ^ ((Config >> 16) & 1); Config &= 0xFFFF; for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) { assert( (Config >> 6) < 720 ); iMigLit = pCutBest->pLeaves[ (int)(p->Perm6[Config >> 6][k]) ]; pFanin = Mpm_ManGetAbcNode( pNtk, vCopy, Abc_LitNotCond(iMigLit, (Config >> k) & 1) ); Abc_ObjAddFanin( pObj, pFanin ); } Vec_IntWriteEntry( vCopy, Abc_Var2Lit(iNode, fCompl), Abc_ObjId(pObj) ); } // create primary outputs Mig_ManForEachCo( p->pMig, pNode, i ) { pObj = Abc_NtkCreatePo(pNtk); pFanin = Mpm_ManGetAbcNode( pNtk, vCopy, Mig_ObjFaninLit(pNode, 0) ); Abc_ObjAddFanin( pObj, pFanin ); } Abc_NtkAddDummyPoNames( pNtk ); // clean up Vec_PtrFree( vNpnGatesMio ); Vec_IntFree( vNodes ); Vec_IntFree( vCopy ); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Mpm_ManPerformCellMapping( Mig_Man_t * pMig, Mpm_Par_t * pPars, Mio_Library_t * pMio ) { Abc_Ntk_t * pNew; Mpm_Man_t * p; assert( pPars->fMap4Gates ); p = Mpm_ManStart( pMig, pPars ); if ( p->pPars->fVerbose ) Mpm_ManPrintStatsInit( p ); p->vNpnConfigs = Mpm_ManFindDsdMatches( p, p->pPars->pScl ); Mpm_ManPrepare( p ); Mpm_ManPerform( p ); if ( p->pPars->fVerbose ) Mpm_ManPrintStats( p ); pNew = Mpm_ManDeriveMappedAbcNtk( p, pMio ); Mpm_ManStop( p ); return pNew; } Abc_Ntk_t * Mpm_ManCellMapping( Gia_Man_t * pGia, Mpm_Par_t * pPars, void * pMio ) { Mig_Man_t * p; Abc_Ntk_t * pNew; assert( pMio != NULL ); assert( pPars->pLib->LutMax <= MPM_VAR_MAX ); assert( pPars->nNumCuts <= MPM_CUT_MAX ); if ( pPars->fUseGates ) { pGia = Gia_ManDupMuxes( pGia, 2 ); p = Mig_ManCreate( pGia ); Gia_ManStop( pGia ); } else p = Mig_ManCreate( pGia ); pNew = Mpm_ManPerformCellMapping( p, pPars, (Mio_Library_t *)pMio ); Mig_ManStop( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmInt.h000066400000000000000000000357311300674244400230300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Interal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmInt.h,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__mpm_Int_h #define ABC__map__mpm_Int_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include //#include "misc/tim/tim.h" #include "misc/mem/mem2.h" #include "misc/vec/vec.h" #include "misc/vec/vecMem.h" #include "misc/vec/vecHsh.h" #include "misc/vec/vecWec.h" #include "misc/util/utilTruth.h" #include "mpmMig.h" #include "mpm.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #define MPM_CUT_MAX 32 #define MPM_UNIT_TIME 1 #define MPM_UNIT_AREA 20 #define MPM_UNIT_EDGE 50 #define MPM_UNIT_REFS 100 //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Mpm_Cut_t_ Mpm_Cut_t; // 8 bytes + NLeaves * 4 bytes struct Mpm_Cut_t_ { int hNext; // next cut unsigned iFunc : 25; // function unsigned fCompl : 1; unsigned fUseless : 1; // internal flag unsigned nLeaves : 5; // leaves int pLeaves[1]; // leaves }; typedef struct Mpm_Uni_t_ Mpm_Uni_t; // 48 bytes struct Mpm_Uni_t_ { int mTime; // arrival time int mArea; // area (flow) int mEdge; // edge (flow) int mAveRefs; // area references word uSign; // cut signature int Cost; // user cost Mpm_Cut_t pCut; // new cut int Data[MPM_VAR_MAX-1]; // padding }; typedef struct Mpm_Dsd_t_ Mpm_Dsd_t; struct Mpm_Dsd_t_ { int nVars; // support size int nAnds; // the number of AND gates int nClauses; // the number of CNF clauses word uTruth; // truth table char * pStr; // description }; typedef struct Mpm_Man_t_ Mpm_Man_t; struct Mpm_Man_t_ { Mig_Man_t * pMig; // AIG manager Mpm_Par_t * pPars; // mapping parameters // mapping parameters int nLutSize; // LUT size int nNumCuts; // cut count int nTruWords; // words in the truth table Mpm_LibLut_t * pLibLut; // LUT library // mapping attributes int fMainRun; // after preprocessing is finished int GloRequired; // global arrival time word GloArea; // total area word GloEdge; // total edge // cut management Mmr_Step_t * pManCuts; // cut memory // temporary cut storage int nCutStore; // number of cuts in storage Mpm_Uni_t * pCutStore[MPM_CUT_MAX+1]; // storage for cuts Mpm_Uni_t pCutUnits[MPM_CUT_MAX+1]; // cut info units Vec_Ptr_t vFreeUnits; // free cut info units Vec_Ptr_t * vTemp; // storage for cuts // cut comparison int (* pCutCmp) (Mpm_Uni_t *, Mpm_Uni_t *);// procedure to compare cuts // fanin cuts/signatures int nCuts[3]; // fanin cut counts Mpm_Cut_t * pCuts[3][MPM_CUT_MAX+1]; // fanin cuts word pSigns[3][MPM_CUT_MAX+1]; // fanin cut signatures // truth tables Vec_Mem_t * vTtMem; // truth table memory and hash table int funcCst0; // constant 0 int funcVar0; // variable 0 word Truth0[(1 << ((MPM_VAR_MAX)-6))]; word Truth1[(1 << ((MPM_VAR_MAX)-6))]; word TruthC[(1 << ((MPM_VAR_MAX)-6))]; word Truth[(1 << ((MPM_VAR_MAX)-6))]; // DSD Mpm_Dsd_t * pDsd6; // NPN class information Hsh_IntMan_t * pHash; // maps DSD functions into NPN classes Vec_Int_t * vConfgRes; // configurations Vec_Wrd_t * vPerm6; // permutations of DSD classes char Perm6[720][6]; // permutations Vec_Int_t * vMap2Perm; // maps number into its permutation unsigned uPermMask[3]; unsigned uComplMask[3]; Vec_Wec_t * vNpnConfigs; // mapping attributes Vec_Int_t vCutBests; // cut best Vec_Int_t vCutLists; // cut list Vec_Int_t vMigRefs; // original references Vec_Int_t vMapRefs; // exact mapping references Vec_Int_t vEstRefs; // estimated mapping references Vec_Int_t vRequireds; // required time Vec_Int_t vTimes; // arrival time Vec_Int_t vAreas; // area Vec_Int_t vEdges; // edge int nCountDsd[600]; int nNonDsd; int nNoMatch; // statistics int nCutsMerged; int nCutsMergedAll; int nSmallSupp; abctime timeDerive; abctime timeMerge; abctime timeEval; abctime timeCompare; abctime timeStore; abctime timeOther; abctime timeTotal; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Mpm_ObjCutBest( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vCutBests, Mig_ObjId(pObj)); } static inline void Mpm_ObjSetCutBest( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Vec_IntWriteEntry(&p->vCutBests, Mig_ObjId(pObj), i); } static inline int Mpm_CutWordNum( int nLeaves ) { return ((sizeof(Mpm_Cut_t) + (nLeaves << 2)) >> 3); } static inline Mpm_Cut_t * Mpm_CutFetch( Mpm_Man_t * p, int h ) { Mpm_Cut_t * pCut = (Mpm_Cut_t *)Mmr_StepEntry( p->pManCuts, h ); assert( Mpm_CutWordNum(pCut->nLeaves) == (h & p->pManCuts->uMask) ); return pCut; } static inline Mpm_Cut_t * Mpm_ObjCutBestP( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Mpm_CutFetch( p, Mpm_ObjCutBest(p, pObj) ); } static inline int Mpm_ObjCutList( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vCutLists, Mig_ObjId(pObj)); } static inline int * Mpm_ObjCutListP( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntryP(&p->vCutLists, Mig_ObjId(pObj)); } static inline void Mpm_ObjSetCutList( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Vec_IntWriteEntry(&p->vCutLists, Mig_ObjId(pObj), i); } static inline int Mpm_CutLeafNum( Mpm_Cut_t * pCut ) { return pCut->nLeaves; } static inline word * Mpm_CutTruth( Mpm_Man_t * p, int iFunc ) { return Vec_MemReadEntry(p->vTtMem, iFunc); } static inline int Mig_ObjMigRefNum( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vMigRefs, Mig_ObjId(pObj)); } static inline int Mig_ObjMigRefDec( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntAddToEntry(&p->vMigRefs, Mig_ObjId(pObj), -1); } static inline void Mpm_ManCleanMapRefs( Mpm_Man_t * p ) { Vec_IntFill( &p->vMapRefs, Mig_ManObjNum(p->pMig), 0 ); } static inline int Mpm_ObjMapRef( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vMapRefs, Mig_ObjId(pObj)); } static inline void Mpm_ObjSetMapRef( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Vec_IntWriteEntry(&p->vMapRefs, Mig_ObjId(pObj), i); } static inline int Mpm_ObjEstRef( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vEstRefs, Mig_ObjId(pObj)); } static inline void Mpm_ObjSetEstRef( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Vec_IntWriteEntry(&p->vEstRefs, Mig_ObjId(pObj), i); } static inline void Mpm_ManCleanRequired( Mpm_Man_t * p ) { Vec_IntFill(&p->vRequireds,Mig_ManObjNum(p->pMig),ABC_INFINITY);} static inline int Mpm_ObjRequired( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vRequireds, Mig_ObjId(pObj)); } static inline void Mpm_ObjSetRequired( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Vec_IntWriteEntry(&p->vRequireds, Mig_ObjId(pObj), i); } static inline int Mpm_ObjTime( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vTimes, Mig_ObjId(pObj)); } static inline void Mpm_ObjSetTime( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Vec_IntWriteEntry(&p->vTimes, Mig_ObjId(pObj), i); } static inline int Mpm_ObjArea( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vAreas, Mig_ObjId(pObj)); } static inline void Mpm_ObjSetArea( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Vec_IntWriteEntry(&p->vAreas, Mig_ObjId(pObj), i); } static inline int Mpm_ObjEdge( Mpm_Man_t * p, Mig_Obj_t * pObj ) { return Vec_IntEntry(&p->vEdges, Mig_ObjId(pObj)); } static inline void Mpm_ObjSetEdge( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Vec_IntWriteEntry(&p->vEdges, Mig_ObjId(pObj), i); } static inline void Mpm_VarsClear( int * V2P, int * P2V, int nVars ) { int i; for ( i = 0; i < nVars; i++ ) V2P[i] = P2V[i] = i; } static inline void Mpm_VarsSwap( int * V2P, int * P2V, int iVar, int jVar ) { V2P[P2V[iVar]] = jVar; V2P[P2V[jVar]] = iVar; P2V[iVar] ^= P2V[jVar]; P2V[jVar] ^= P2V[iVar]; P2V[iVar] ^= P2V[jVar]; } // iterators over object cuts #define Mpm_ObjForEachCut( p, pObj, hCut, pCut ) \ for ( hCut = Mpm_ObjCutList(p, pObj); hCut && (pCut = Mpm_CutFetch(p, hCut)); hCut = pCut->hNext ) #define Mpm_ObjForEachCutSafe( p, pObj, hCut, pCut, hNext ) \ for ( hCut = Mpm_ObjCutList(p, pObj); hCut && (pCut = Mpm_CutFetch(p, hCut)) && ((hNext = pCut->hNext), 1); hCut = hNext ) // iterators over cut leaves #define Mpm_CutForEachLeafId( pCut, iLeafId, i ) \ for ( i = 0; i < (int)pCut->nLeaves && ((iLeafId = Abc_Lit2Var(pCut->pLeaves[i])), 1); i++ ) #define Mpm_CutForEachLeafLit( pCut, iLeafLit, i ) \ for ( i = 0; i < (int)pCut->nLeaves && ((iLeafLit = pCut->pLeaves[i]), 1); i++ ) #define Mpm_CutForEachLeaf( p, pCut, pLeaf, i ) \ for ( i = 0; i < (int)pCut->nLeaves && (pLeaf = Mig_ManObj(p, Abc_Lit2Var(pCut->pLeaves[i]))); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== mpmAbc.c ===========================================================*/ extern Mig_Man_t * Mig_ManCreate( void * pGia ); extern void * Mpm_ManFromIfLogic( Mpm_Man_t * pMan ); /*=== mpmMan.c ===========================================================*/ extern Mpm_Man_t * Mpm_ManStart( Mig_Man_t * pMig, Mpm_Par_t * pPars ); extern void Mpm_ManStop( Mpm_Man_t * p ); extern void Mpm_ManPrintStatsInit( Mpm_Man_t * p ); extern void Mpm_ManPrintStats( Mpm_Man_t * p ); /*=== mpmDsd.c ===========================================================*/ extern void Mpm_ManPrintDsdStats( Mpm_Man_t * p ); extern void Mpm_ManPrintPerm( unsigned s ); extern void Mpm_ManPrecomputePerms( Mpm_Man_t * p ); extern word Mpm_CutTruthFromDsd( Mpm_Man_t * pMan, Mpm_Cut_t * pCut, int iDsdLit ); extern int Mpm_CutCheckDsd6( Mpm_Man_t * p, word t ); extern int Mpm_CutComputeDsd6( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type ); /*=== mpmGates.c ===========================================================*/ extern Vec_Wec_t * Mpm_ManFindDsdMatches( Mpm_Man_t * p, void * pScl ); /*=== mpmLib.c ===========================================================*/ extern Mpm_LibLut_t * Mpm_LibLutSetSimple( int nLutSize ); extern void Mpm_LibLutFree( Mpm_LibLut_t * pLib ); /*=== mpmMap.c ===========================================================*/ extern void Mpm_CutPrint( Mpm_Cut_t * pCut ); extern void Mpm_ManPrepare( Mpm_Man_t * p ); extern void Mpm_ManPerform( Mpm_Man_t * p ); /*=== mpmTruth.c ===========================================================*/ extern int Mpm_CutComputeTruth( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type ); extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmLib.c000066400000000000000000000040321300674244400227650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmLib.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [DSD manipulation for 6-input functions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmLib.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mpm_LibLut_t * Mpm_LibLutSetSimple( int nLutSize ) { Mpm_LibLut_t * pLib; int i, k; assert( nLutSize <= MPM_VAR_MAX ); pLib = ABC_CALLOC( Mpm_LibLut_t, 1 ); pLib->LutMax = nLutSize; for ( i = 1; i <= pLib->LutMax; i++ ) { pLib->pLutAreas[i] = MPM_UNIT_AREA; for ( k = 0; k < i; k++ ) pLib->pLutDelays[i][k] = MPM_UNIT_TIME; } return pLib; } void Mpm_LibLutFree( Mpm_LibLut_t * pLib ) { if ( pLib == NULL ) return; ABC_FREE( pLib->pName ); ABC_FREE( pLib ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmMan.c000066400000000000000000000164001300674244400227740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpm.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mpm_Man_t * Mpm_ManStart( Mig_Man_t * pMig, Mpm_Par_t * pPars ) { Mpm_Man_t * p; int i; assert( sizeof(Mpm_Uni_t) % sizeof(word) == 0 ); // aligned info to word boundary assert( pPars->nNumCuts <= MPM_CUT_MAX ); assert( !pPars->fUseTruth || pPars->pLib->LutMax <= 16 ); assert( !pPars->fUseDsd || pPars->pLib->LutMax <= 6 ); Mig_ManSetRefs( pMig ); // alloc p = ABC_CALLOC( Mpm_Man_t, 1 ); p->pMig = pMig; p->pPars = pPars; p->pLibLut = pPars->pLib; p->nLutSize = pPars->pLib->LutMax; p->nTruWords = pPars->fUseTruth ? Abc_Truth6WordNum(p->nLutSize) : 0; p->nNumCuts = pPars->nNumCuts; // cuts assert( Mpm_CutWordNum(32) < 32 ); // using 5 bits for word count p->pManCuts = Mmr_StepStart( 13, Abc_Base2Log(Mpm_CutWordNum(p->nLutSize) + 1) ); Vec_PtrGrow( &p->vFreeUnits, p->nNumCuts + 1 ); for ( i = p->nNumCuts; i >= 0; i-- ) Vec_PtrPush( &p->vFreeUnits, p->pCutUnits + i ); p->vTemp = Vec_PtrAlloc( 1000 ); // mapping attributes Vec_IntFill( &p->vCutBests, Mig_ManObjNum(pMig), 0 ); Vec_IntFill( &p->vCutLists, Mig_ManObjNum(pMig), 0 ); Vec_IntFill( &p->vMigRefs, Mig_ManObjNum(pMig), 0 ); Vec_IntFill( &p->vMapRefs, Mig_ManObjNum(pMig), 0 ); Vec_IntFill( &p->vEstRefs, Mig_ManObjNum(pMig), 0 ); Vec_IntFill( &p->vRequireds, Mig_ManObjNum(pMig), ABC_INFINITY ); Vec_IntFill( &p->vTimes, Mig_ManObjNum(pMig), 0 ); Vec_IntFill( &p->vAreas, Mig_ManObjNum(pMig), 0 ); Vec_IntFill( &p->vEdges, Mig_ManObjNum(pMig), 0 ); // start DSD manager assert( !p->pPars->fUseTruth || !p->pPars->fUseDsd ); if ( p->pPars->fUseTruth ) { p->vTtMem = Vec_MemAlloc( p->nTruWords, 12 ); // 32 KB/page for 6-var functions Vec_MemHashAlloc( p->vTtMem, 10000 ); p->funcCst0 = Vec_MemHashInsert( p->vTtMem, p->Truth ); Abc_TtUnit( p->Truth, p->nTruWords, 0 ); p->funcVar0 = Vec_MemHashInsert( p->vTtMem, p->Truth ); } else if ( p->pPars->fUseDsd ) { Mpm_ManPrecomputePerms( p ); p->funcVar0 = 1; } // finish p->timeTotal = Abc_Clock(); pMig->pMan = p; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mpm_ManStop( Mpm_Man_t * p ) { if ( p->pPars->fUseTruth && p->pPars->fVeryVerbose ) { char * pFileName = "truths.txt"; FILE * pFile = fopen( pFileName, "wb" ); Vec_MemDump( pFile, p->vTtMem ); fclose( pFile ); printf( "Dumped %d %d-var truth tables into file \"%s\" (%.2f MB).\n", Vec_MemEntryNum(p->vTtMem), p->nLutSize, pFileName, (16.0 * p->nTruWords + 1.0) * Vec_MemEntryNum(p->vTtMem) / (1 << 20) ); } if ( p->pPars->fUseDsd && p->pPars->fVerbose ) Mpm_ManPrintDsdStats( p ); if ( p->vTtMem ) { Vec_MemHashFree( p->vTtMem ); Vec_MemFree( p->vTtMem ); } if ( p->pHash ) { Vec_WrdFree( p->vPerm6 ); Vec_IntFree( p->vMap2Perm ); Vec_IntFree( p->vConfgRes ); Vec_IntFree( p->pHash->vData ); Hsh_IntManStop( p->pHash ); } Vec_WecFreeP( &p->vNpnConfigs ); Vec_PtrFree( p->vTemp ); Mmr_StepStop( p->pManCuts ); ABC_FREE( p->vFreeUnits.pArray ); // mapping attributes ABC_FREE( p->vCutBests.pArray ); ABC_FREE( p->vCutLists.pArray ); ABC_FREE( p->vMigRefs.pArray ); ABC_FREE( p->vMapRefs.pArray ); ABC_FREE( p->vEstRefs.pArray ); ABC_FREE( p->vRequireds.pArray ); ABC_FREE( p->vTimes.pArray ); ABC_FREE( p->vAreas.pArray ); ABC_FREE( p->vEdges.pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mpm_ManPrintStatsInit( Mpm_Man_t * p ) { printf( "K = %d. C = %d. Cand = %d. XOR = %d. MUX = %d. Choice = %d. CutMin = %d. Truth = %d. DSD = %d.\n", p->nLutSize, p->nNumCuts, Mig_ManCandNum(p->pMig), Mig_ManXorNum(p->pMig), Mig_ManMuxNum(p->pMig), p->pMig->nChoices, p->pPars->fCutMin, p->pPars->fUseTruth, p->pPars->fUseDsd ); } void Mpm_ManPrintStats( Mpm_Man_t * p ) { printf( "Memory usage: Mig = %.2f MB Map = %.2f MB Cut = %.2f MB Total = %.2f MB. ", 1.0 * Mig_ManObjNum(p->pMig) * sizeof(Mig_Obj_t) / (1 << 20), 1.0 * Mig_ManObjNum(p->pMig) * 48 / (1 << 20), 1.0 * Mmr_StepMemory(p->pManCuts) / (1 << 17), 1.0 * Mig_ManObjNum(p->pMig) * sizeof(Mig_Obj_t) / (1 << 20) + 1.0 * Mig_ManObjNum(p->pMig) * 48 / (1 << 20) + 1.0 * Mmr_StepMemory(p->pManCuts) / (1 << 17) ); if ( p->timeDerive ) { printf( "\n" ); p->timeTotal = Abc_Clock() - p->timeTotal; p->timeOther = p->timeTotal - p->timeDerive; Abc_Print( 1, "Runtime breakdown:\n" ); ABC_PRTP( "Complete cut computation ", p->timeDerive , p->timeTotal ); ABC_PRTP( "- Merging cuts ", p->timeMerge , p->timeTotal ); ABC_PRTP( "- Evaluting cut parameters ", p->timeEval , p->timeTotal ); ABC_PRTP( "- Checking cut containment ", p->timeCompare, p->timeTotal ); ABC_PRTP( "- Adding cuts to storage ", p->timeStore , p->timeTotal ); ABC_PRTP( "Other ", p->timeOther , p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal , p->timeTotal ); } else Abc_PrintTime( 1, "Time", Abc_Clock() - p->timeTotal ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmMap.c000066400000000000000000000715121300674244400230030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmMap.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Mapping algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmMap.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //#define MIG_RUNTIME //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Cut manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mpm_CutAlloc( Mpm_Man_t * p, int nLeaves, Mpm_Cut_t ** ppCut ) { int hHandle = Mmr_StepFetch( p->pManCuts, Mpm_CutWordNum(nLeaves) ); *ppCut = (Mpm_Cut_t *)Mmr_StepEntry( p->pManCuts, hHandle ); (*ppCut)->nLeaves = nLeaves; (*ppCut)->hNext = 0; (*ppCut)->fUseless = 0; (*ppCut)->fCompl = 0; return hHandle; } static inline int Mpm_CutCreateZero( Mpm_Man_t * p ) { Mpm_Cut_t * pCut; int hCut = Mpm_CutAlloc( p, 0, &pCut ); pCut->iFunc = 0; // const0 return hCut; } static inline int Mpm_CutCreateUnit( Mpm_Man_t * p, int Id ) { Mpm_Cut_t * pCut; int hCut = Mpm_CutAlloc( p, 1, &pCut ); pCut->iFunc = Abc_Var2Lit( p->funcVar0, 0 ); // var pCut->pLeaves[0] = Abc_Var2Lit( Id, 0 ); return hCut; } static inline int Mpm_CutCreate( Mpm_Man_t * p, Mpm_Cut_t * pUni, Mpm_Cut_t ** ppCut ) { int hCutNew = Mpm_CutAlloc( p, pUni->nLeaves, ppCut ); (*ppCut)->iFunc = pUni->iFunc; (*ppCut)->fCompl = pUni->fCompl; (*ppCut)->fUseless = pUni->fUseless; (*ppCut)->nLeaves = pUni->nLeaves; memcpy( (*ppCut)->pLeaves, pUni->pLeaves, sizeof(int) * pUni->nLeaves ); return hCutNew; } static inline int Mpm_CutDup( Mpm_Man_t * p, Mpm_Cut_t * pCut, int fCompl ) { Mpm_Cut_t * pCutNew; int hCutNew = Mpm_CutAlloc( p, pCut->nLeaves, &pCutNew ); pCutNew->iFunc = Abc_LitNotCond( pCut->iFunc, fCompl ); pCutNew->fUseless = pCut->fUseless; pCutNew->nLeaves = pCut->nLeaves; memcpy( pCutNew->pLeaves, pCut->pLeaves, sizeof(int) * pCut->nLeaves ); return hCutNew; } static inline int Mpm_CutCopySet( Mpm_Man_t * p, Mig_Obj_t * pObj, int fCompl ) { Mpm_Cut_t * pCut; int hCut, iList = 0, * pList = &iList; Mpm_ObjForEachCut( p, pObj, hCut, pCut ) { *pList = Mpm_CutDup( p, pCut, fCompl ); pList = &Mpm_CutFetch( p, *pList )->hNext; } *pList = 0; return iList; } void Mpm_CutPrint( Mpm_Cut_t * pCut ) { int i; printf( "%d : { ", pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) printf( "%d ", pCut->pLeaves[i] ); printf( "}\n" ); } static inline void Mpm_CutPrintAll( Mpm_Man_t * p ) { int i; for ( i = 0; i < p->nCutStore; i++ ) { printf( "%2d : ", i ); Mpm_CutPrint( &p->pCutStore[i]->pCut ); } } static inline int Mpm_CutFindLeaf( Mpm_Cut_t * pNew, int iObj ) { int i; for ( i = 0; i < (int)pNew->nLeaves; i++ ) if ( Abc_Lit2Var(pNew->pLeaves[i]) == iObj ) return i; return i; } static inline int Mpm_CutIsContained( Mpm_Man_t * p, Mpm_Cut_t * pBase, Mpm_Cut_t * pCut ) // check if pCut is contained pBase { int i; for ( i = 0; i < (int)pCut->nLeaves; i++ ) if ( Mpm_CutFindLeaf( pBase, Abc_Lit2Var(pCut->pLeaves[i]) ) == (int)pBase->nLeaves ) return 0; return 1; } /**Function************************************************************* Synopsis [Cut attibutes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mpm_CutGetArea( Mpm_Man_t * p, Mpm_Cut_t * pCut ) { if ( p->pPars->fMap4Cnf ) return MPM_UNIT_AREA * p->pDsd6[Abc_Lit2Var(pCut->iFunc)].nClauses; if ( p->pPars->fMap4Aig ) return MPM_UNIT_AREA * p->pDsd6[Abc_Lit2Var(pCut->iFunc)].nAnds; if ( p->pPars->fMap4Gates ) return MPM_UNIT_AREA * 1; return p->pLibLut->pLutAreas[pCut->nLeaves]; } static inline word Mpm_CutGetSign( Mpm_Cut_t * pCut ) { int i, iLeaf; word uSign = 0; Mpm_CutForEachLeafId( pCut, iLeaf, i ) uSign |= ((word)1 << (iLeaf & 0x3F)); return uSign; } static inline int Mpm_CutGetArrTime( Mpm_Man_t * p, Mpm_Cut_t * pCut ) { int * pmTimes = Vec_IntArray( &p->vTimes ); int * pDelays = p->pLibLut->pLutDelays[pCut->nLeaves]; int i, iLeaf, ArrTime = 0; Mpm_CutForEachLeafId( pCut, iLeaf, i ) ArrTime = Abc_MaxInt( ArrTime, pmTimes[iLeaf] + pDelays[i] ); return ArrTime; } static inline Mpm_Uni_t * Mpm_CutSetupInfo( Mpm_Man_t * p, Mpm_Cut_t * pCut, int ArrTime ) { int * pMigRefs = Vec_IntArray( &p->vMigRefs ); int * pMapRefs = Vec_IntArray( &p->vMapRefs ); int * pEstRefs = Vec_IntArray( &p->vEstRefs ); int * pmArea = Vec_IntArray( &p->vAreas ); int * pmEdge = Vec_IntArray( &p->vEdges ); int i, iLeaf; Mpm_Uni_t * pUnit = (Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits); assert( &pUnit->pCut == pCut ); pUnit->mTime = ArrTime; pUnit->mArea = Mpm_CutGetArea( p, pCut ); pUnit->mEdge = MPM_UNIT_EDGE * pCut->nLeaves; pUnit->mAveRefs = 0; pUnit->Cost = 0; pUnit->uSign = 0; Mpm_CutForEachLeafId( pCut, iLeaf, i ) { if ( p->fMainRun && pMapRefs[iLeaf] == 0 ) // not used in the mapping { pUnit->mArea += pmArea[iLeaf]; pUnit->mEdge += pmEdge[iLeaf]; } else { assert( pEstRefs[iLeaf] > 0 ); pUnit->mArea += MPM_UNIT_REFS * pmArea[iLeaf] / pEstRefs[iLeaf]; pUnit->mEdge += MPM_UNIT_REFS * pmEdge[iLeaf] / pEstRefs[iLeaf]; pUnit->mAveRefs += p->fMainRun ? pMapRefs[iLeaf] : pMigRefs[iLeaf]; } pUnit->uSign |= ((word)1 << (iLeaf & 0x3F)); } pUnit->mAveRefs = pUnit->mAveRefs * MPM_UNIT_EDGE / Abc_MaxInt(pCut->nLeaves, 1); assert( pUnit->mTime <= 0x3FFFFFFF ); assert( pUnit->mArea <= 0x3FFFFFFF ); assert( pUnit->mEdge <= 0x3FFFFFFF ); return pUnit; } /**Function************************************************************* Synopsis [Compares cut against those present in the store.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mpm_ObjAddCutToStore( Mpm_Man_t * p, Mpm_Cut_t * pCut, int ArrTime ) { int fEnableContainment = 1; Mpm_Uni_t * pUnit, * pUnitNew; int k, iPivot, last; // create new unit #ifdef MIG_RUNTIME abctime clk; clk = Abc_Clock(); #endif pUnitNew = Mpm_CutSetupInfo( p, pCut, ArrTime ); #ifdef MIG_RUNTIME p->timeEval += Abc_Clock() - clk; #endif // special case when the cut store is empty if ( p->nCutStore == 0 ) { p->pCutStore[p->nCutStore++] = pUnitNew; Vec_PtrPop( &p->vFreeUnits ); return 1; } // special case when the cut store is full and last cut is better than new cut if ( p->nCutStore == p->nNumCuts-1 && p->pCutCmp(pUnitNew, p->pCutStore[p->nCutStore-1]) > 0 ) return 0; // find place of the given cut in the store assert( p->nCutStore <= p->nNumCuts ); for ( iPivot = p->nCutStore - 1; iPivot >= 0; iPivot-- ) if ( p->pCutCmp(pUnitNew, p->pCutStore[iPivot]) > 0 ) // iPivot-th cut is better than new cut break; if ( fEnableContainment ) { #ifdef MIG_RUNTIME clk = Abc_Clock(); #endif // filter this cut using other cuts for ( k = 0; k <= iPivot; k++ ) { pUnit = p->pCutStore[k]; if ( pUnitNew->pCut.nLeaves >= pUnit->pCut.nLeaves && (pUnitNew->uSign & pUnit->uSign) == pUnit->uSign && Mpm_CutIsContained(p, &pUnitNew->pCut, &pUnit->pCut) ) { #ifdef MIG_RUNTIME p->timeCompare += Abc_Clock() - clk; #endif return 0; } } } // special case when the best cut is useless while the new cut is not if ( p->pCutStore[0]->pCut.fUseless && !pUnitNew->pCut.fUseless ) iPivot = -1; // add the cut to storage assert( pUnitNew == (Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits) ); Vec_PtrPop( &p->vFreeUnits ); // insert this cut at location iPivot iPivot++; for ( k = p->nCutStore++; k > iPivot; k-- ) p->pCutStore[k] = p->pCutStore[k-1]; p->pCutStore[iPivot] = pUnitNew; if ( fEnableContainment ) { // filter other cuts using this cut for ( k = last = iPivot+1; k < p->nCutStore; k++ ) { pUnit = p->pCutStore[k]; if ( pUnitNew->pCut.nLeaves <= pUnit->pCut.nLeaves && (pUnitNew->uSign & pUnit->uSign) == pUnitNew->uSign && Mpm_CutIsContained(p, &pUnit->pCut, &pUnitNew->pCut) ) { Vec_PtrPush( &p->vFreeUnits, pUnit ); continue; } p->pCutStore[last++] = p->pCutStore[k]; } p->nCutStore = last; #ifdef MIG_RUNTIME p->timeCompare += Abc_Clock() - clk; #endif } // remove the last cut if too many if ( p->nCutStore == p->nNumCuts ) Vec_PtrPush( &p->vFreeUnits, p->pCutStore[--p->nCutStore] ); assert( p->nCutStore < p->nNumCuts ); return 1; } /**Function************************************************************* Synopsis [Cut enumeration.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Mpm_Cut_t * Mpm_ManMergeCuts( Mpm_Man_t * p, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCut2 ) { Mpm_Cut_t * pTemp, * pCut = &((Mpm_Uni_t *)Vec_PtrEntryLast(&p->vFreeUnits))->pCut; int i, c, iPlace; // base cut memcpy( pCut->pLeaves, pCut0->pLeaves, sizeof(int) * pCut0->nLeaves ); pCut->nLeaves = pCut0->nLeaves; // remaining cuts if ( p->pPars->fUseDsd ) { for ( c = 1; c < 3; c++ ) { pTemp = (c == 1) ? pCut1 : pCut2; if ( pTemp == NULL ) break; p->uPermMask[c] = 0x3FFFF; // 18 bits p->uComplMask[c] = 0; for ( i = 0; i < (int)pTemp->nLeaves; i++ ) { iPlace = Mpm_CutFindLeaf( pCut, Abc_Lit2Var(pTemp->pLeaves[i]) ); if ( iPlace == (int)pCut->nLeaves ) { if ( (int)pCut->nLeaves == p->nLutSize ) return NULL; pCut->pLeaves[pCut->nLeaves++] = pTemp->pLeaves[i]; } p->uPermMask[c] ^= (((i & 7) ^ 7) << (3*iPlace)); if ( pTemp->pLeaves[i] != pCut->pLeaves[iPlace] ) p->uComplMask[c] |= (1 << iPlace); } } } else { for ( c = 1; c < 3; c++ ) { pTemp = (c == 1) ? pCut1 : pCut2; if ( pTemp == NULL ) break; for ( i = 0; i < (int)pTemp->nLeaves; i++ ) { iPlace = Mpm_CutFindLeaf( pCut, Abc_Lit2Var(pTemp->pLeaves[i]) ); if ( iPlace == (int)pCut->nLeaves ) { if ( (int)pCut->nLeaves == p->nLutSize ) return NULL; pCut->pLeaves[pCut->nLeaves++] = pTemp->pLeaves[i]; } } } } if ( pCut1 == NULL ) { pCut->hNext = 0; pCut->iFunc = pCut0->iFunc; pCut->fUseless = pCut0->fUseless; pCut->fCompl = pCut0->fCompl; } else { pCut->hNext = 0; pCut->iFunc = 0; pCut->iFunc = ~pCut->iFunc; pCut->fUseless = 0; pCut->fCompl = 0; } p->nCutsMerged++; p->nCutsMergedAll++; if ( p->pPars->fUseTruth ) Vec_IntSelectSort( pCut->pLeaves, pCut->nLeaves ); return pCut; } static inline int Mpm_ManExploreNewCut( Mpm_Man_t * p, Mig_Obj_t * pObj, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCut2, int Required ) { Mpm_Cut_t * pCut; int ArrTime; #ifdef MIG_RUNTIME abctime clk = clock(); #endif if ( pCut0->nLeaves >= pCut1->nLeaves ) { pCut = Mpm_ManMergeCuts( p, pCut0, pCut1, pCut2 ); #ifdef MIG_RUNTIME p->timeMerge += clock() - clk; #endif if ( pCut == NULL ) return 1; if ( p->pPars->fUseTruth ) Mpm_CutComputeTruth( p, pCut, pCut0, pCut1, pCut2, Mig_ObjFaninC0(pObj), Mig_ObjFaninC1(pObj), Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ); else if ( p->pPars->fUseDsd ) { if ( !Mpm_CutComputeDsd6( p, pCut, pCut0, pCut1, pCut2, Mig_ObjFaninC0(pObj), Mig_ObjFaninC1(pObj), Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ) ) return 1; } } else { pCut = Mpm_ManMergeCuts( p, pCut1, pCut0, pCut2 ); #ifdef MIG_RUNTIME p->timeMerge += clock() - clk; #endif if ( pCut == NULL ) return 1; if ( p->pPars->fUseTruth ) Mpm_CutComputeTruth( p, pCut, pCut1, pCut0, pCut2, Mig_ObjFaninC1(pObj), Mig_ObjFaninC0(pObj), 1 ^ Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ); else if ( p->pPars->fUseDsd ) { if ( !Mpm_CutComputeDsd6( p, pCut, pCut1, pCut0, pCut2, Mig_ObjFaninC1(pObj), Mig_ObjFaninC0(pObj), 1 ^ Mig_ObjFaninC2(pObj), Mig_ObjNodeType(pObj) ) ) return 1; } } #ifdef MIG_RUNTIME clk = clock(); #endif ArrTime = Mpm_CutGetArrTime( p, pCut ); #ifdef MIG_RUNTIME p->timeEval += clock() - clk; #endif if ( p->fMainRun && ArrTime > Required ) return 1; #ifdef MIG_RUNTIME clk = Abc_Clock(); #endif Mpm_ObjAddCutToStore( p, pCut, ArrTime ); #ifdef MIG_RUNTIME p->timeStore += Abc_Clock() - clk; #endif /* // return 0 if const or buffer cut is derived - reset all cuts to contain only one --- does not work // if ( pCut->nLeaves < 2 && p->nCutStore == 1 ) // return 0; if ( pCut->nLeaves < 2 ) { int i; assert( p->nCutStore >= 1 ); for ( i = 1; i < p->nCutStore; i++ ) Vec_PtrPush( &p->vFreeUnits, p->pCutStore[i] ); p->nCutStore = 1; return 0; } */ return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Mpm_ObjRecycleCuts( Mpm_Man_t * p, Mig_Obj_t * pObj ) { Mpm_Cut_t * pCut; int hCut, hNext; Mpm_ObjForEachCutSafe( p, pObj, hCut, pCut, hNext ) Mmr_StepRecycle( p->pManCuts, hCut ); Mpm_ObjSetCutList( p, pObj, 0 ); } static inline void Mpm_ObjDerefFaninCuts( Mpm_Man_t * p, Mig_Obj_t * pObj ) { Mig_Obj_t * pFanin; int i; Mig_ObjForEachFanin( pObj, pFanin, i ) if ( Mig_ObjIsNode(pFanin) && Mig_ObjMigRefDec(p, pFanin) == 0 ) Mpm_ObjRecycleCuts( p, pFanin ); pFanin = Mig_ObjSibl(pObj); if ( pFanin && Mig_ObjMigRefDec(p, pFanin) == 0 ) Mpm_ObjRecycleCuts( p, pFanin ); if ( Mig_ObjMigRefNum(p, pObj) == 0 ) Mpm_ObjRecycleCuts( p, pObj ); } static inline void Mpm_ObjCollectFaninsAndSigns( Mpm_Man_t * p, Mig_Obj_t * pObj, int i ) { Mpm_Cut_t * pCut; int hCut, nCuts = 0; Mpm_ObjForEachCut( p, pObj, hCut, pCut ) { p->pCuts[i][nCuts] = pCut; p->pSigns[i][nCuts++] = Mpm_CutGetSign( pCut ); } p->nCuts[i] = nCuts; } static inline void Mpm_ObjPrepareFanins( Mpm_Man_t * p, Mig_Obj_t * pObj ) { Mig_Obj_t * pFanin; int i; Mig_ObjForEachFanin( pObj, pFanin, i ) Mpm_ObjCollectFaninsAndSigns( p, pFanin, i ); } // create storage from cuts at the node void Mpm_ObjAddChoiceCutsToStore( Mpm_Man_t * p, Mig_Obj_t * pRoot, Mig_Obj_t * pObj, int ReqTime ) { Mpm_Cut_t * pCut; int hCut, hNext, ArrTime; int fCompl = Mig_ObjPhase(pRoot) ^ Mig_ObjPhase(pObj); Mpm_ObjForEachCutSafe( p, pObj, hCut, pCut, hNext ) { if ( Abc_Lit2Var(pCut->pLeaves[0]) == Mig_ObjId(pObj) ) continue; ArrTime = Mpm_CutGetArrTime( p, pCut ); if ( ArrTime > ReqTime ) continue; pCut->fCompl ^= fCompl; pCut = Mpm_ManMergeCuts( p, pCut, NULL, NULL ); Mpm_ObjAddCutToStore( p, pCut, ArrTime ); } } // create cuts at the node from storage void Mpm_ObjTranslateCutsFromStore( Mpm_Man_t * p, Mig_Obj_t * pObj ) { Mpm_Cut_t * pCut = NULL; Mpm_Uni_t * pUnit; int i, *pList = Mpm_ObjCutListP( p, pObj ); assert( p->nCutStore > 0 && p->nCutStore <= p->nNumCuts ); assert( *pList == 0 ); // translate cuts for ( i = 0; i < p->nCutStore; i++ ) { pUnit = p->pCutStore[i]; *pList = Mpm_CutCreate( p, &pUnit->pCut, &pCut ); pList = &pCut->hNext; Vec_PtrPush( &p->vFreeUnits, pUnit ); } assert( Vec_PtrSize(&p->vFreeUnits) == p->nNumCuts + 1 ); if ( p->nCutStore == 1 && pCut->nLeaves < 2 ) *pList = 0; else *pList = Mpm_CutCreateUnit( p, Mig_ObjId(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mpm_ManDeriveCuts( Mpm_Man_t * p, Mig_Obj_t * pObj ) { Mpm_Cut_t * pCut0, * pCut1, * pCut2; int Required = Mpm_ObjRequired( p, pObj ); int hCutBest = Mpm_ObjCutBest( p, pObj ); int c0, c1, c2; #ifdef MIG_RUNTIME abctime clk; #endif assert( Vec_PtrSize( &p->vFreeUnits ) == p->nNumCuts + 1 ); assert( Mpm_ObjCutList(p, pObj) == 0 ); p->nCutStore = 0; if ( hCutBest > 0 ) // cut list is assigned { Mpm_Cut_t * pCut = Mpm_ObjCutBestP( p, pObj ); int Times = Mpm_CutGetArrTime( p, pCut ); assert( pCut->hNext == 0 ); if ( Times > Required ) printf( "Arrival time (%d) exceeds required time (%d) at object %d.\n", Times, Required, Mig_ObjId(pObj) ); if ( p->fMainRun ) Mpm_ObjAddCutToStore( p, Mpm_ManMergeCuts(p, pCut, NULL, NULL), Times ); else Mpm_ObjSetTime( p, pObj, Times ); } // start storage with choice cuts if ( Mig_ManChoiceNum(p->pMig) && Mig_ObjSiblId(pObj) ) Mpm_ObjAddChoiceCutsToStore( p, pObj, Mig_ObjSibl(pObj), Required ); #ifdef MIG_RUNTIME clk = Abc_Clock(); #endif Mpm_ObjPrepareFanins( p, pObj ); if ( Mig_ObjIsNode2(pObj) ) { // go through cut pairs for ( c0 = 0; c0 < p->nCuts[0] && (pCut0 = p->pCuts[0][c0]); c0++ ) for ( c1 = 0; c1 < p->nCuts[1] && (pCut1 = p->pCuts[1][c1]); c1++ ) if ( Abc_TtCountOnes(p->pSigns[0][c0] | p->pSigns[1][c1]) <= p->nLutSize ) if ( !Mpm_ManExploreNewCut( p, pObj, pCut0, pCut1, NULL, Required ) ) goto finish; } else if ( Mig_ObjIsNode3(pObj) ) { // go through cut triples for ( c0 = 0; c0 < p->nCuts[0] && (pCut0 = p->pCuts[0][c0]); c0++ ) for ( c1 = 0; c1 < p->nCuts[1] && (pCut1 = p->pCuts[1][c1]); c1++ ) for ( c2 = 0; c2 < p->nCuts[2] && (pCut2 = p->pCuts[2][c2]); c2++ ) if ( Abc_TtCountOnes(p->pSigns[0][c0] | p->pSigns[1][c1] | p->pSigns[2][c2]) <= p->nLutSize ) if ( !Mpm_ManExploreNewCut( p, pObj, pCut0, pCut1, pCut2, Required ) ) goto finish; } else assert( 0 ); #ifdef MIG_RUNTIME p->timeDerive += Abc_Clock() - clk; #endif finish: // save best cut assert( p->nCutStore > 0 ); if ( p->pCutStore[0]->mTime <= Required ) { Mpm_Cut_t * pCut; if ( hCutBest ) Mmr_StepRecycle( p->pManCuts, hCutBest ); hCutBest = Mpm_CutCreate( p, &p->pCutStore[0]->pCut, &pCut ); Mpm_ObjSetCutBest( p, pObj, hCutBest ); Mpm_ObjSetTime( p, pObj, p->pCutStore[0]->mTime ); Mpm_ObjSetArea( p, pObj, p->pCutStore[0]->mArea ); Mpm_ObjSetEdge( p, pObj, p->pCutStore[0]->mEdge ); } else assert( !p->fMainRun ); assert( hCutBest > 0 ); // transform internal storage into regular cuts Mpm_ObjTranslateCutsFromStore( p, pObj ); // dereference fanin cuts and reference node Mpm_ObjDerefFaninCuts( p, pObj ); return 1; } /**Function************************************************************* Synopsis [Required times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mpm_ManFindArrivalMax( Mpm_Man_t * p ) { int * pmTimes = Vec_IntArray( &p->vTimes ); Mig_Obj_t * pObj; int i, ArrMax = 0; Mig_ManForEachCo( p->pMig, pObj, i ) ArrMax = Abc_MaxInt( ArrMax, pmTimes[ Mig_ObjFaninId0(pObj) ] ); return ArrMax; } static inline void Mpm_ManFinalizeRound( Mpm_Man_t * p ) { int * pMapRefs = Vec_IntArray( &p->vMapRefs ); int * pRequired = Vec_IntArray( &p->vRequireds ); Mig_Obj_t * pObj; Mpm_Cut_t * pCut; int * pDelays; int i, iLeaf; p->GloArea = 0; p->GloEdge = 0; p->GloRequired = Mpm_ManFindArrivalMax(p); if ( p->pPars->DelayTarget != -1 ) p->GloRequired = Abc_MaxInt( p->GloRequired, p->pPars->DelayTarget ); Mpm_ManCleanMapRefs( p ); Mpm_ManCleanRequired( p ); Mig_ManForEachObjReverse( p->pMig, pObj ) { if ( Mig_ObjIsCo(pObj) ) { pRequired[Mig_ObjFaninId0(pObj)] = p->GloRequired; pMapRefs [Mig_ObjFaninId0(pObj)]++; } else if ( Mig_ObjIsNode(pObj) ) { int Required = pRequired[Mig_ObjId(pObj)]; assert( Required > 0 ); if ( pMapRefs[Mig_ObjId(pObj)] > 0 ) { pCut = Mpm_ObjCutBestP( p, pObj ); pDelays = p->pLibLut->pLutDelays[pCut->nLeaves]; Mpm_CutForEachLeafId( pCut, iLeaf, i ) { pRequired[iLeaf] = Abc_MinInt( pRequired[iLeaf], Required - pDelays[i] ); pMapRefs [iLeaf]++; } p->GloArea += Mpm_CutGetArea( p, pCut ); p->GloEdge += pCut->nLeaves; } } else if ( Mig_ObjIsBuf(pObj) ) { } } p->GloArea /= MPM_UNIT_AREA; } static inline void Mpm_ManComputeEstRefs( Mpm_Man_t * p ) { int * pMapRefs = Vec_IntArray( &p->vMapRefs ); int * pEstRefs = Vec_IntArray( &p->vEstRefs ); int i; assert( p->fMainRun ); // pObj->EstRefs = (float)((2.0 * pObj->EstRefs + pObj->nRefs) / 3.0); for ( i = 0; i < Mig_ManObjNum(p->pMig); i++ ) pEstRefs[i] = (1 * pEstRefs[i] + MPM_UNIT_REFS * pMapRefs[i]) / 2; } /**Function************************************************************* Synopsis [Cut comparison.] Description [Returns positive number if new one is better than old one.] SideEffects [] SeeAlso [] ***********************************************************************/ int Mpm_CutCompareDelay( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew ) { if ( pOld->mTime != pNew->mTime ) return pOld->mTime - pNew->mTime; if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves; if ( pOld->mArea != pNew->mArea ) return pOld->mArea - pNew->mArea; if ( pOld->mEdge != pNew->mEdge ) return pOld->mEdge - pNew->mEdge; return 0; } int Mpm_CutCompareDelay2( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew ) { if ( pOld->mTime != pNew->mTime ) return pOld->mTime - pNew->mTime; if ( pOld->mArea != pNew->mArea ) return pOld->mArea - pNew->mArea; if ( pOld->mEdge != pNew->mEdge ) return pOld->mEdge - pNew->mEdge; if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves; return 0; } int Mpm_CutCompareArea( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew ) { if ( pOld->mArea != pNew->mArea ) return pOld->mArea - pNew->mArea; if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves; if ( pOld->mEdge != pNew->mEdge ) return pOld->mEdge - pNew->mEdge; if ( pOld->mAveRefs != pNew->mAveRefs ) return pOld->mAveRefs - pNew->mAveRefs; if ( pOld->mTime != pNew->mTime ) return pOld->mTime - pNew->mTime; return 0; } int Mpm_CutCompareArea2( Mpm_Uni_t * pOld, Mpm_Uni_t * pNew ) { if ( pOld->mArea != pNew->mArea ) return pOld->mArea - pNew->mArea; if ( pOld->mEdge != pNew->mEdge ) return pOld->mEdge - pNew->mEdge; if ( pOld->mAveRefs != pNew->mAveRefs ) return pOld->mAveRefs - pNew->mAveRefs; if ( pOld->pCut.nLeaves != pNew->pCut.nLeaves ) return pOld->pCut.nLeaves - pNew->pCut.nLeaves; if ( pOld->mTime != pNew->mTime ) return pOld->mTime - pNew->mTime; return 0; } /**Function************************************************************* Synopsis [Technology mapping experiment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mpm_ManPrepare( Mpm_Man_t * p ) { Mig_Obj_t * pObj; int i, hCut; Mig_ManForEachCi( p->pMig, pObj, i ) { hCut = Mpm_CutCreateUnit( p, Mig_ObjId(pObj) ); Mpm_ObjSetCutBest( p, pObj, hCut ); Mpm_ObjSetCutList( p, pObj, hCut ); } Mig_ManForEachCand( p->pMig, pObj ) Mpm_ObjSetEstRef( p, pObj, MPM_UNIT_REFS * Mig_ObjRefNum(pObj) ); } void Mpm_ManPerformRound( Mpm_Man_t * p ) { Mig_Obj_t * pObj; abctime clk = Abc_Clock(); int i; // copy references assert( Vec_IntSize(&p->vMigRefs) == Vec_IntSize(&p->pMig->vRefs) ); memcpy( Vec_IntArray(&p->vMigRefs), Vec_IntArray(&p->pMig->vRefs), sizeof(int) * Mig_ManObjNum(p->pMig) ); Mig_ManForEachCo( p->pMig, pObj, i ) Mig_ObjMigRefDec( p, Mig_ObjFanin0(pObj) ); // derive cuts p->nCutsMerged = 0; Mig_ManForEachNode( p->pMig, pObj ) Mpm_ManDeriveCuts( p, pObj ); assert( Mig_ManCandNum(p->pMig) == p->pManCuts->nEntries ); Mpm_ManFinalizeRound( p ); // report results if ( p->pPars->fVerbose ) { printf( "Del =%5d. Ar =%8d. Edge =%8d. Cut =%10d. Max =%8d. Tru =%8d. Small =%6d. ", p->GloRequired, (int)p->GloArea, (int)p->GloEdge, p->nCutsMerged, p->pManCuts->nEntriesMax, p->vTtMem ? p->vTtMem->nEntries : 0, p->nSmallSupp ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } } void Mpm_ManPerform( Mpm_Man_t * p ) { if ( p->pPars->fMap4Cnf ) { p->pCutCmp = Mpm_CutCompareArea; Mpm_ManPerformRound( p ); } else { p->pCutCmp = Mpm_CutCompareDelay; Mpm_ManPerformRound( p ); if ( p->pPars->fOneRound ) return; p->pCutCmp = Mpm_CutCompareDelay2; Mpm_ManPerformRound( p ); p->pCutCmp = Mpm_CutCompareArea; Mpm_ManPerformRound( p ); p->fMainRun = 1; p->pCutCmp = Mpm_CutCompareArea; Mpm_ManComputeEstRefs( p ); Mpm_ManPerformRound( p ); p->pCutCmp = Mpm_CutCompareArea2; Mpm_ManComputeEstRefs( p ); Mpm_ManPerformRound( p ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmMig.c000066400000000000000000000132461300674244400230020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmMig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Subject graph data structure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmMig.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mig_Man_t * Mig_ManStart() { Mig_Man_t * p; assert( sizeof(Mig_Obj_t) >= 16 ); assert( (1 << MIG_BASE) == MIG_MASK + 1 ); p = ABC_CALLOC( Mig_Man_t, 1 ); Vec_IntGrow( &p->vCis, 1024 ); Vec_IntGrow( &p->vCos, 1024 ); Mig_ManAppendObj( p ); // const0 return p; } void Mig_ManStop( Mig_Man_t * p ) { if ( 0 ) printf( "Subject graph uses %d pages of %d objects with %d entries. Total memory = %.2f MB.\n", Vec_PtrSize(&p->vPages), MIG_MASK + 1, p->nObjs, 1.0 * Vec_PtrSize(&p->vPages) * (MIG_MASK + 1) * 16 / (1 << 20) ); // attributes ABC_FREE( p->vTravIds.pArray ); ABC_FREE( p->vCopies.pArray ); ABC_FREE( p->vLevels.pArray ); ABC_FREE( p->vRefs.pArray ); ABC_FREE( p->vSibls.pArray ); // pages Vec_PtrForEachEntry( Mig_Obj_t *, &p->vPages, p->pPage, p->iPage ) --p->pPage, ABC_FREE( p->pPage ); // objects ABC_FREE( p->vPages.pArray ); ABC_FREE( p->vCis.pArray ); ABC_FREE( p->vCos.pArray ); ABC_FREE( p->pName ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mig_ManTypeNum( Mig_Man_t * p, int Type ) { Mig_Obj_t * pObj; int Counter = 0; Mig_ManForEachNode( p, pObj ) Counter += (Mig_ObjNodeType(pObj) == Type); return Counter; } int Mig_ManAndNum( Mig_Man_t * p ) { return Mig_ManTypeNum(p, 1); } int Mig_ManXorNum( Mig_Man_t * p ) { return Mig_ManTypeNum(p, 2); } int Mig_ManMuxNum( Mig_Man_t * p ) { return Mig_ManTypeNum(p, 3); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mig_ManSetRefs( Mig_Man_t * p ) { Mig_Obj_t * pObj; int i, iFanin; // increment references Vec_IntFill( &p->vRefs, Mig_ManObjNum(p), 0 ); Mig_ManForEachObj( p, pObj ) { Mig_ObjForEachFaninId( pObj, iFanin, i ) Vec_IntAddToEntry( &p->vRefs, iFanin, 1 ); if ( Mig_ObjSiblId(pObj) ) Vec_IntAddToEntry( &p->vRefs, Mig_ObjSiblId(pObj), 1 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mig_ManSuppSize_rec( Mig_Obj_t * pObj ) { if ( pObj == NULL ) return 0; if ( Mig_ObjIsTravIdCurrent(pObj) ) return 0; Mig_ObjSetTravIdCurrent(pObj); if ( Mig_ObjIsCi(pObj) ) return 1; assert( Mig_ObjIsNode(pObj) ); return Mig_ManSuppSize_rec( Mig_ObjFanin0(pObj) ) + Mig_ManSuppSize_rec( Mig_ObjFanin1(pObj) ) + Mig_ManSuppSize_rec( Mig_ObjFanin2(pObj) ); } int Mig_ManSuppSize2_rec( Mig_Man_t * p, int iObj ) { Mig_Obj_t * pObj; if ( iObj == MIG_NONE ) return 0; if ( Mig_ObjIsTravIdCurrentId(p, iObj) ) return 0; Mig_ObjSetTravIdCurrentId(p, iObj); pObj = Mig_ManObj( p, iObj ); if ( Mig_ObjIsCi(pObj) ) return 1; assert( Mig_ObjIsNode(pObj) ); return Mig_ManSuppSize2_rec( p, Mig_ObjFaninId0(pObj) ) + Mig_ManSuppSize2_rec( p, Mig_ObjFaninId1(pObj) ) + Mig_ManSuppSize2_rec( p, Mig_ObjFaninId2(pObj) ); } int Mig_ManSuppSizeOne( Mig_Obj_t * pObj ) { Mig_ObjIncrementTravId( pObj ); // return Mig_ManSuppSize_rec( pObj ); return Mig_ManSuppSize2_rec( Mig_ObjMan(pObj), Mig_ObjId(pObj) ); } int Mig_ManSuppSizeTest( Mig_Man_t * p ) { Mig_Obj_t * pObj; int Counter = 0; abctime clk = Abc_Clock(); Mig_ManForEachObj( p, pObj ) if ( Mig_ObjIsNode(pObj) ) Counter += (Mig_ManSuppSizeOne(pObj) <= 16); printf( "Nodes with small support %d (out of %d)\n", Counter, Mig_ManNodeNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmMig.h000066400000000000000000000610671300674244400230130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmMig.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmMig.h,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__mpm__mig__h #define ABC__map__mpm__mig__h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/vec/vec.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #define MIG_NONE 0x7FFFFFFF //#define MIG_MASK 0x0000FFFF //#define MIG_BASE 16 #define MIG_MASK 0x0000FFF #define MIG_BASE 12 //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Mig_Fan_t_ Mig_Fan_t; struct Mig_Fan_t_ { unsigned fCompl : 1; // the complemented attribute unsigned Id : 31; // fanin ID }; typedef struct Mig_Obj_t_ Mig_Obj_t; struct Mig_Obj_t_ { Mig_Fan_t pFans[4]; // fanins }; typedef struct Mig_Man_t_ Mig_Man_t; struct Mig_Man_t_ { char * pName; // name int nObjs; // number of objects int nRegs; // number of flops int nChoices; // number of choices Vec_Ptr_t vPages; // memory pages Vec_Int_t vCis; // CI IDs Vec_Int_t vCos; // CO IDs // object iterator Mig_Obj_t * pPage; // current page int iPage; // current page index // attributes int nTravIds; // traversal ID counter Vec_Int_t vTravIds; // traversal IDs Vec_Int_t vLevels; // levels Vec_Int_t vSibls; // choice nodes Vec_Int_t vRefs; // ref counters Vec_Int_t vCopies; // copies void * pMan; // mapping manager }; /* Usage of fanin atrributes -------------------------------------------------------------------------------------------------------------- Const0 Terminal CI CO Buf Node Node2 Node3 And2 XOR2 MUX MAJ Sentinel -------------------------------------------------------------------------------------------------------------- 0 - -/fanin0 - fanin0 fanin0 fanin0 fanin0 fanin0 fanin0 fanin1 fanin0 fanin1 - 1 - - - - - fanin1 fanin1 fanin1 fanin1 fanin0 fanin1 fanin0 - 2 - CIO ID CIO ID CIO ID - -/fanin2 - fanin2 - - fanin2 fanin2 - 3 0 ID ID ID ID ID ID ID ID ID ID ID - -------------------------------------------------------------------------------------------------------------- One memory page contain 2^MIG_BASE+2 16-byte objects. - the first object contains the pointer to the manager (8 bytes) - the next 2^MIG_BASE are potentially used as objects - the last object is a sentinel to signal the end of the page */ static inline int Mig_IdPage( int v ) { return v >> MIG_BASE; } static inline int Mig_IdCell( int v ) { return v & MIG_MASK; } static inline char * Mig_ManName( Mig_Man_t * p ) { return p->pName; } static inline int Mig_ManCiNum( Mig_Man_t * p ) { return Vec_IntSize(&p->vCis); } static inline int Mig_ManCoNum( Mig_Man_t * p ) { return Vec_IntSize(&p->vCos); } static inline int Mig_ManPiNum( Mig_Man_t * p ) { return Vec_IntSize(&p->vCis) - p->nRegs; } static inline int Mig_ManPoNum( Mig_Man_t * p ) { return Vec_IntSize(&p->vCos) - p->nRegs; } static inline int Mig_ManRegNum( Mig_Man_t * p ) { return p->nRegs; } static inline int Mig_ManObjNum( Mig_Man_t * p ) { return p->nObjs; } static inline int Mig_ManNodeNum( Mig_Man_t * p ) { return p->nObjs - Vec_IntSize(&p->vCis) - Vec_IntSize(&p->vCos) - 1; } static inline int Mig_ManCandNum( Mig_Man_t * p ) { return Mig_ManCiNum(p) + Mig_ManNodeNum(p); } static inline int Mig_ManChoiceNum( Mig_Man_t * p ) { return p->nChoices; } static inline void Mig_ManSetRegNum( Mig_Man_t * p, int v ) { p->nRegs = v; } static inline Mig_Obj_t * Mig_ManPage( Mig_Man_t * p, int v ) { return (Mig_Obj_t *)Vec_PtrEntry(&p->vPages, Mig_IdPage(v)); } static inline Mig_Obj_t * Mig_ManObj( Mig_Man_t * p, int v ) { assert(v >= 0 && v < p->nObjs); return Mig_ManPage(p, v) + Mig_IdCell(v); } static inline Mig_Obj_t * Mig_ManCi( Mig_Man_t * p, int v ) { return Mig_ManObj( p, Vec_IntEntry(&p->vCis,v) ); } static inline Mig_Obj_t * Mig_ManCo( Mig_Man_t * p, int v ) { return Mig_ManObj( p, Vec_IntEntry(&p->vCos,v) ); } static inline Mig_Obj_t * Mig_ManPi( Mig_Man_t * p, int v ) { assert( v < Mig_ManPiNum(p) ); return Mig_ManCi( p, v ); } static inline Mig_Obj_t * Mig_ManPo( Mig_Man_t * p, int v ) { assert( v < Mig_ManPoNum(p) ); return Mig_ManCo( p, v ); } static inline Mig_Obj_t * Mig_ManRo( Mig_Man_t * p, int v ) { assert( v < Mig_ManRegNum(p) ); return Mig_ManCi( p, Mig_ManPiNum(p)+v ); } static inline Mig_Obj_t * Mig_ManRi( Mig_Man_t * p, int v ) { assert( v < Mig_ManRegNum(p) ); return Mig_ManCo( p, Mig_ManPoNum(p)+v ); } static inline Mig_Obj_t * Mig_ManConst0( Mig_Man_t * p ) { return Mig_ManObj(p, 0); } static inline int Mig_FanCompl( Mig_Obj_t * p, int i ) { return p->pFans[i].fCompl; } static inline int Mig_FanId( Mig_Obj_t * p, int i ) { return p->pFans[i].Id; } static inline int Mig_FanIsNone( Mig_Obj_t * p, int i ) { return p->pFans[i].Id == MIG_NONE; } static inline int Mig_FanSetCompl( Mig_Obj_t * p, int i, int v ) { assert( !(v >> 1) ); return p->pFans[i].fCompl = v; } static inline int Mig_FanSetId( Mig_Obj_t * p, int i, int v ) { assert(v >= 0 && v < MIG_NONE); return p->pFans[i].Id = v; } static inline int Mig_ObjIsNone( Mig_Obj_t * p ) { return Mig_FanIsNone( p, 3 ); } static inline int Mig_ObjIsConst0( Mig_Obj_t * p ) { return Mig_FanId( p, 3 ) == 0; } static inline int Mig_ObjIsTerm( Mig_Obj_t * p ) { return Mig_FanIsNone( p, 1 ) && !Mig_FanIsNone( p, 2 ); } static inline int Mig_ObjIsCi( Mig_Obj_t * p ) { return Mig_ObjIsTerm(p) && Mig_FanIsNone( p, 0 ); } static inline int Mig_ObjIsCo( Mig_Obj_t * p ) { return Mig_ObjIsTerm(p) && !Mig_FanIsNone( p, 0 ); } static inline int Mig_ObjIsBuf( Mig_Obj_t * p ) { return Mig_FanIsNone( p, 1 ) && Mig_FanIsNone( p, 2 ) && !Mig_FanIsNone( p, 0 ); } static inline int Mig_ObjIsNode( Mig_Obj_t * p ) { return!Mig_FanIsNone( p, 1 ); } static inline int Mig_ObjIsNode2( Mig_Obj_t * p ) { return Mig_ObjIsNode( p ) && Mig_FanIsNone( p, 2 ); } static inline int Mig_ObjIsNode3( Mig_Obj_t * p ) { return Mig_ObjIsNode( p ) && !Mig_FanIsNone( p, 2 ); } static inline int Mig_ObjIsAnd( Mig_Obj_t * p ) { return Mig_ObjIsNode2( p ) && Mig_FanId(p, 0) < Mig_FanId(p, 1); } static inline int Mig_ObjIsXor( Mig_Obj_t * p ) { return Mig_ObjIsNode2( p ) && Mig_FanId(p, 0) > Mig_FanId(p, 1); } static inline int Mig_ObjIsMux( Mig_Obj_t * p ) { return Mig_ObjIsNode3( p ); } static inline int Mig_ObjIsCand( Mig_Obj_t * p ) { return Mig_ObjIsNode(p) || Mig_ObjIsCi(p); } static inline int Mig_ObjNodeType( Mig_Obj_t * p ) { return Mig_ObjIsAnd(p) ? 1 : (Mig_ObjIsXor(p) ? 2 : 3); } static inline int Mig_ObjId( Mig_Obj_t * p ) { return Mig_FanId( p, 3 ); } static inline void Mig_ObjSetId( Mig_Obj_t * p, int v ) { Mig_FanSetId( p, 3, v ); } static inline int Mig_ObjCioId( Mig_Obj_t * p ) { assert( Mig_ObjIsTerm(p) ); return Mig_FanId( p, 2 ); } static inline void Mig_ObjSetCioId( Mig_Obj_t * p, int v ) { assert( Mig_FanIsNone(p, 1) ); Mig_FanSetId( p, 2, v ); } static inline int Mig_ObjPhase( Mig_Obj_t * p ) { return Mig_FanCompl( p, 3 ); } static inline void Mig_ObjSetPhase( Mig_Obj_t * p, int v ) { Mig_FanSetCompl( p, 3, v ); } static inline Mig_Man_t * Mig_ObjMan( Mig_Obj_t * p ) { return *((Mig_Man_t**)(p - Mig_IdCell(Mig_ObjId(p)) - 1)); } //static inline Mig_Obj_t ** Mig_ObjPageP( Mig_Obj_t * p ) { return *((Mig_Obj_t***)(p - Mig_IdCell(Mig_ObjId(p))) - 1);} static inline Mig_Obj_t * Mig_ObjObj( Mig_Obj_t * p, int i ) { return Mig_ManObj( Mig_ObjMan(p), i ); } static inline int Mig_ManIdToCioId( Mig_Man_t * p, int Id ) { return Mig_ObjCioId( Mig_ManObj(p, Id) ); } static inline int Mig_ManCiIdToId( Mig_Man_t * p, int CiId ) { return Mig_ObjId( Mig_ManCi(p, CiId) ); } static inline int Mig_ManCoIdToId( Mig_Man_t * p, int CoId ) { return Mig_ObjId( Mig_ManCo(p, CoId) ); } static inline int Mig_ObjIsPi( Mig_Obj_t * p ) { return Mig_ObjIsCi(p) && Mig_ObjCioId(p) < Mig_ManPiNum(Mig_ObjMan(p)); } static inline int Mig_ObjIsPo( Mig_Obj_t * p ) { return Mig_ObjIsCo(p) && Mig_ObjCioId(p) < Mig_ManPoNum(Mig_ObjMan(p)); } static inline int Mig_ObjIsRo( Mig_Obj_t * p ) { return Mig_ObjIsCi(p) && Mig_ObjCioId(p) >= Mig_ManPiNum(Mig_ObjMan(p)); } static inline int Mig_ObjIsRi( Mig_Obj_t * p ) { return Mig_ObjIsCo(p) && Mig_ObjCioId(p) >= Mig_ManPoNum(Mig_ObjMan(p)); } static inline Mig_Obj_t * Mig_ObjRoToRi( Mig_Obj_t * p ) { Mig_Man_t * pMan = Mig_ObjMan(p); assert( Mig_ObjIsRo(p) ); return Mig_ManCo(pMan, Mig_ManCoNum(pMan) - Mig_ManCiNum(pMan) + Mig_ObjCioId(p)); } static inline Mig_Obj_t * Mig_ObjRiToRo( Mig_Obj_t * p ) { Mig_Man_t * pMan = Mig_ObjMan(p); assert( Mig_ObjIsRi(p) ); return Mig_ManCi(pMan, Mig_ManCiNum(pMan) - Mig_ManCoNum(pMan) + Mig_ObjCioId(p)); } static inline int Mig_ObjHasFanin( Mig_Obj_t * p, int i ) { return i < 3 && Mig_FanId(p, i) != MIG_NONE; } static inline int Mig_ObjFaninId( Mig_Obj_t * p, int i ) { assert( i < 3 && Mig_FanId(p, i) < Mig_ObjId(p) ); return Mig_FanId( p, i ); } static inline int Mig_ObjFaninId0( Mig_Obj_t * p ) { return Mig_FanId( p, 0 ); } static inline int Mig_ObjFaninId1( Mig_Obj_t * p ) { return Mig_FanId( p, 1 ); } static inline int Mig_ObjFaninId2( Mig_Obj_t * p ) { return Mig_FanId( p, 2 ); } static inline Mig_Obj_t * Mig_ObjFanin( Mig_Obj_t * p, int i ) { return Mig_ManObj( Mig_ObjMan(p), Mig_ObjFaninId(p, i) ); } //static inline Mig_Obj_t * Mig_ObjFanin( Mig_Obj_t * p, int i ) { return Mig_ObjPageP(p)[Mig_IdPage(Mig_ObjFaninId(p, i))] + Mig_IdCell(Mig_ObjFaninId(p, i)); } static inline Mig_Obj_t * Mig_ObjFanin0( Mig_Obj_t * p ) { return Mig_FanIsNone(p, 0) ? NULL: Mig_ObjFanin(p, 0); } static inline Mig_Obj_t * Mig_ObjFanin1( Mig_Obj_t * p ) { return Mig_FanIsNone(p, 1) ? NULL: Mig_ObjFanin(p, 1); } static inline Mig_Obj_t * Mig_ObjFanin2( Mig_Obj_t * p ) { return Mig_FanIsNone(p, 2) ? NULL: Mig_ObjFanin(p, 2); } static inline int Mig_ObjFaninC( Mig_Obj_t * p, int i ) { assert( i < 3 ); return Mig_FanCompl(p, i); } static inline int Mig_ObjFaninC0( Mig_Obj_t * p ) { return Mig_FanCompl(p, 0); } static inline int Mig_ObjFaninC1( Mig_Obj_t * p ) { return Mig_FanCompl(p, 1); } static inline int Mig_ObjFaninC2( Mig_Obj_t * p ) { return Mig_FanCompl(p, 2); } static inline int Mig_ObjFaninLit( Mig_Obj_t * p, int i ) { return Abc_Var2Lit( Mig_FanId(p, i), Mig_FanCompl(p, i) ); } static inline void Mig_ObjFlipFaninC( Mig_Obj_t * p, int i ) { Mig_FanSetCompl( p, i, !Mig_FanCompl(p, i) ); } static inline int Mig_ObjWhatFanin( Mig_Obj_t * p, int i ) { if (Mig_FanId(p, 0) == i) return 0; if (Mig_FanId(p, 1) == i) return 1; if (Mig_FanId(p, 2) == i) return 2; return -1; } static inline void Mig_ObjSetFaninLit( Mig_Obj_t * p, int i, int l ) { assert( l >= 0 && (l >> 1) < Mig_ObjId(p) ); Mig_FanSetId(p, i, Abc_Lit2Var(l)); Mig_FanSetCompl(p, i, Abc_LitIsCompl(l)); } static inline int Mig_ObjSiblId( Mig_Obj_t * p ) { return Vec_IntSize(&Mig_ObjMan(p)->vSibls) == 0 ? 0: Vec_IntEntry(&Mig_ObjMan(p)->vSibls, Mig_ObjId(p)); } static inline void Mig_ObjSetSiblId( Mig_Obj_t * p, int s ) { assert( s > 0 && Mig_ObjId(p) > s ); Vec_IntWriteEntry( &Mig_ObjMan(p)->vSibls, Mig_ObjId(p), s ); } static inline Mig_Obj_t * Mig_ObjSibl( Mig_Obj_t * p ) { return Mig_ObjSiblId(p) == 0 ? NULL: Mig_ObjObj(p, Mig_ObjSiblId(p)); } static inline int Mig_ObjRefNum( Mig_Obj_t * p ) { return Vec_IntEntry(&Mig_ObjMan(p)->vRefs, Mig_ObjId(p)); } static inline void Mig_ManCleanCopy( Mig_Man_t * p ) { if ( p->vCopies.pArray == NULL ) Vec_IntFill( &p->vCopies, Mig_ManObjNum(p), -1 ); } static inline int Mig_ObjCopy( Mig_Obj_t * p ) { return Vec_IntSize(&Mig_ObjMan(p)->vCopies) == 0 ? -1: Vec_IntEntry(&Mig_ObjMan(p)->vCopies, Mig_ObjId(p)); } static inline void Mig_ObjSetCopy( Mig_Obj_t * p, int i ) { assert( Vec_IntSize(&Mig_ObjMan(p)->vCopies) != 0 ); Vec_IntWriteEntry(&Mig_ObjMan(p)->vCopies, Mig_ObjId(p), i); } static inline void Mig_ManIncrementTravId( Mig_Man_t * p ) { if ( p->vTravIds.pArray == NULL ) Vec_IntFill( &p->vTravIds, Mig_ManObjNum(p)+500, 0 ); p->nTravIds++; } static inline void Mig_ObjIncrementTravId( Mig_Obj_t * p ) { if ( Mig_ObjMan(p)->vTravIds.pArray == NULL ) Vec_IntFill( &Mig_ObjMan(p)->vTravIds, Mig_ManObjNum(Mig_ObjMan(p))+500, 0 ); Mig_ObjMan(p)->nTravIds++; } static inline void Mig_ObjSetTravIdCurrent( Mig_Obj_t * p ) { Vec_IntSetEntry(&Mig_ObjMan(p)->vTravIds, Mig_ObjId(p), Mig_ObjMan(p)->nTravIds ); } static inline void Mig_ObjSetTravIdPrevious( Mig_Obj_t * p ) { Vec_IntSetEntry(&Mig_ObjMan(p)->vTravIds, Mig_ObjId(p), Mig_ObjMan(p)->nTravIds-1 ); } static inline int Mig_ObjIsTravIdCurrent( Mig_Obj_t * p ) { return (Vec_IntGetEntry(&Mig_ObjMan(p)->vTravIds, Mig_ObjId(p)) == Mig_ObjMan(p)->nTravIds); } static inline int Mig_ObjIsTravIdPrevious( Mig_Obj_t * p ) { return (Vec_IntGetEntry(&Mig_ObjMan(p)->vTravIds, Mig_ObjId(p)) == Mig_ObjMan(p)->nTravIds-1); } static inline void Mig_ObjSetTravIdCurrentId( Mig_Man_t * p, int Id ) { Vec_IntSetEntry(&p->vTravIds, Id, p->nTravIds ); } static inline int Mig_ObjIsTravIdCurrentId( Mig_Man_t * p, int Id ) { return (Vec_IntGetEntry(&p->vTravIds, Id) == p->nTravIds); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Mig_Obj_t * Mig_ManAppendObj( Mig_Man_t * p ) { Mig_Obj_t * pObj; assert( p->nObjs < MIG_NONE ); if ( p->nObjs >= (Vec_PtrSize(&p->vPages) << MIG_BASE) ) { Mig_Obj_t * pPage;// int i; assert( p->nObjs == (Vec_PtrSize(&p->vPages) << MIG_BASE) ); pPage = ABC_FALLOC( Mig_Obj_t, MIG_MASK + 3 ); // 1 for mask, 1 for prefix, 1 for sentinel *((void **)pPage) = p; // *((void ***)(pPage + 1) - 1) = Vec_PtrArray(&p->vPages); Vec_PtrPush( &p->vPages, pPage + 1 ); // if ( *((void ***)(pPage + 1) - 1) != Vec_PtrArray(&p->vPages) ) // Vec_PtrForEachEntry( Mig_Obj_t *, &p->vPages, pPage, i ) // *((void ***)pPage - 1) = Vec_PtrArray(&p->vPages); } pObj = Mig_ManObj( p, p->nObjs++ ); assert( Mig_ObjIsNone(pObj) ); Mig_ObjSetId( pObj, p->nObjs-1 ); return pObj; } static inline int Mig_ManAppendCi( Mig_Man_t * p ) { Mig_Obj_t * pObj = Mig_ManAppendObj( p ); Mig_ObjSetCioId( pObj, Vec_IntSize(&p->vCis) ); Vec_IntPush( &p->vCis, Mig_ObjId(pObj) ); return Mig_ObjId(pObj) << 1; } static inline int Mig_ManAppendCo( Mig_Man_t * p, int iLit0 ) { Mig_Obj_t * pObj; assert( !Mig_ObjIsCo(Mig_ManObj(p, Abc_Lit2Var(iLit0))) ); pObj = Mig_ManAppendObj( p ); Mig_ObjSetFaninLit( pObj, 0, iLit0 ); Mig_ObjSetCioId( pObj, Vec_IntSize(&p->vCos) ); Vec_IntPush( &p->vCos, Mig_ObjId(pObj) ); return Mig_ObjId( pObj ) << 1; } static inline int Mig_ManAppendBuf( Mig_Man_t * p, int iLit0 ) { Mig_Obj_t * pObj; pObj = Mig_ManAppendObj( p ); Mig_ObjSetFaninLit( pObj, 0, iLit0 ); return Mig_ObjId( pObj ) << 1; } static inline int Mig_ManAppendAnd( Mig_Man_t * p, int iLit0, int iLit1 ) { Mig_Obj_t * pObj = Mig_ManAppendObj( p ); assert( iLit0 != iLit1 ); Mig_ObjSetFaninLit( pObj, 0, iLit0 < iLit1 ? iLit0 : iLit1 ); Mig_ObjSetFaninLit( pObj, 1, iLit0 < iLit1 ? iLit1 : iLit0 ); return Mig_ObjId( pObj ) << 1; } static inline int Mig_ManAppendXor( Mig_Man_t * p, int iLit0, int iLit1 ) { Mig_Obj_t * pObj = Mig_ManAppendObj( p ); assert( iLit0 != iLit1 ); assert( !Abc_LitIsCompl(iLit0) && !Abc_LitIsCompl(iLit1) ); Mig_ObjSetFaninLit( pObj, 0, iLit0 < iLit1 ? iLit1 : iLit0 ); Mig_ObjSetFaninLit( pObj, 1, iLit0 < iLit1 ? iLit0 : iLit1 ); return Mig_ObjId( pObj ) << 1; } static inline int Mig_ManAppendMux( Mig_Man_t * p, int iLit0, int iLit1, int iCtrl ) { Mig_Obj_t * pObj = Mig_ManAppendObj( p ); assert( iLit0 != iLit1 && iLit0 != iCtrl && iLit1 != iCtrl ); assert( !Abc_LitIsCompl(iLit0) || !Abc_LitIsCompl(iLit1) ); Mig_ObjSetFaninLit( pObj, 0, iLit0 < iLit1 ? iLit0 : iLit1 ); Mig_ObjSetFaninLit( pObj, 1, iLit0 < iLit1 ? iLit1 : iLit0 ); Mig_ObjSetFaninLit( pObj, 2, iLit0 < iLit1 ? iCtrl : Abc_LitNot(iCtrl) ); return Mig_ObjId( pObj ) << 1; } static inline int Mig_ManAppendMaj( Mig_Man_t * p, int iLit0, int iLit1, int iLit2 ) { Mig_Obj_t * pObj = Mig_ManAppendObj( p ); assert( iLit0 != iLit1 && iLit0 != iLit2 && iLit1 != iLit2 ); Mig_ObjSetFaninLit( pObj, 0, iLit0 < iLit1 ? iLit1 : iLit0 ); Mig_ObjSetFaninLit( pObj, 1, iLit0 < iLit1 ? iLit0 : iLit1 ); Mig_ObjSetFaninLit( pObj, 2, iLit2 ); return Mig_ObjId( pObj ) << 1; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // iterators over objects #define Mig_ManForEachObj( p, pObj ) \ for ( p->iPage = 0; p->iPage < Vec_PtrSize(&p->vPages) && \ ((p->pPage) = (Mig_Obj_t *)Vec_PtrEntry(&p->vPages, p->iPage)); p->iPage++ ) \ for ( pObj = p->pPage; !Mig_ObjIsNone(pObj); pObj++ ) #define Mig_ManForEachObj1( p, pObj ) \ for ( p->iPage = 0; p->iPage < Vec_PtrSize(&p->vPages) && \ ((p->pPage) = (Mig_Obj_t *)Vec_PtrEntry(&p->vPages, p->iPage)); p->iPage++ ) \ for ( pObj = p->pPage + (p->iPage == 0); !Mig_ObjIsNone(pObj); pObj++ ) #define Mig_ManForEachObjReverse( p, pObj ) \ for ( p->iPage = Vec_PtrSize(&p->vPages) - 1; p->iPage >= 0 && \ ((p->pPage) = (Mig_Obj_t *)Vec_PtrEntry(&p->vPages, p->iPage)); p->iPage-- ) \ for ( pObj = (p->iPage == Vec_PtrSize(&p->vPages) - 1) ? \ Mig_ManObj(p, Mig_ManObjNum(p)-1) : p->pPage + MIG_MASK; \ pObj - p->pPage >= 0; pObj-- ) #define Mig_ManForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Mig_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) #define Mig_ManForEachNode( p, pObj ) \ Mig_ManForEachObj( p, pObj ) if ( !Mig_ObjIsNode(pObj) ) {} else #define Mig_ManForEachCand( p, pObj ) \ Mig_ManForEachObj( p, pObj ) if ( !Mig_ObjIsCand(pObj) ) {} else #define Mig_ManForEachCi( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vCis)) && ((pObj) = Mig_ManCi(p, i)); i++ ) #define Mig_ManForEachCo( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vCos)) && ((pObj) = Mig_ManCo(p, i)); i++ ) // iterators over fanins #define Mig_ObjForEachFaninId( p, iFanin, i ) \ for ( i = 0; Mig_ObjHasFanin(p, i) && ((iFanin) = Mig_ObjFaninId(p, i)); i++ ) #define Mig_ObjForEachFanin( p, pFanin, i ) \ for ( i = 0; Mig_ObjHasFanin(p, i) && ((pFanin) = Mig_ObjFanin(p, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== mpmMig.c ===========================================================*/ extern Mig_Man_t * Mig_ManStart(); extern void Mig_ManStop( Mig_Man_t * p ); extern void Mig_ManSetRefs( Mig_Man_t * p ); extern int Mig_ManAndNum( Mig_Man_t * p ); extern int Mig_ManXorNum( Mig_Man_t * p ); extern int Mig_ManMuxNum( Mig_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmPre.c000066400000000000000000001037151300674244400230150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmPre.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [DSD-related precomputations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmPre.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "misc/vec/vecHsh.h" #include "misc/extra/extra.h" #include "bool/kit/kit.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Ifd_Obj_t_ Ifd_Obj_t; struct Ifd_Obj_t_ { unsigned nFreq : 18; // frequency unsigned nAnds : 6; // number of AND gates unsigned nSupp : 5; // support size unsigned Type : 2; // type unsigned fWay : 1; // transparent edge unsigned pFans[3]; // fanins }; typedef struct Ifd_Man_t_ Ifd_Man_t; struct Ifd_Man_t_ { Ifd_Obj_t * pObjs; int nObjs; int nObjsAlloc; // hashing operations Vec_Int_t * vArgs; // iDsd1 op iDsdC Vec_Int_t * vRes; // result of operation Hsh_IntMan_t * vHash; // hash table Vec_Int_t * vMarks; // marks where given N begins Vec_Wrd_t * vTruths; // truth tables Vec_Int_t * vClauses; // truth tables // other data Vec_Int_t * vSuper; }; static inline int Ifd_ObjIsVar( Ifd_Obj_t * p ) { return p->Type == 0; } static inline int Ifd_ObjIsAnd( Ifd_Obj_t * p ) { return p->Type == 1; } static inline int Ifd_ObjIsXor( Ifd_Obj_t * p ) { return p->Type == 2; } static inline int Ifd_ObjIsMux( Ifd_Obj_t * p ) { return p->Type == 3; } static inline Ifd_Obj_t * Ifd_ManObj( Ifd_Man_t * p, int i ) { assert( i >= 0 && i < p->nObjs ); return p->pObjs + i; } static inline Ifd_Obj_t * Ifd_ManObjFromLit( Ifd_Man_t * p, int iLit ) { return Ifd_ManObj( p, Abc_Lit2Var(iLit) ); } static inline int Ifd_ObjId( Ifd_Man_t * p, Ifd_Obj_t * pObj ) { assert( pObj - p->pObjs >= 0 && pObj - p->pObjs < p->nObjs ); return pObj - p->pObjs; } static inline int Ifd_LitSuppSize( Ifd_Man_t * p, int iLit ) { return iLit > 0 ? Ifd_ManObjFromLit(p, iLit)->nSupp : 0; } static inline int Ifd_LitNumAnds( Ifd_Man_t * p, int iLit ) { return iLit > 0 ? Ifd_ManObjFromLit(p, iLit)->nAnds : 0; } #define Ifd_ManForEachNodeWithSupp( p, nVars, pLeaf, i ) \ for ( i = Vec_IntEntry(p->vMarks, nVars); (i < Vec_IntEntry(p->vMarks, nVars+1)) && (pLeaf = Ifd_ManObj(p, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ifd_Man_t * Ifd_ManStart() { Ifd_Man_t * p; p = ABC_CALLOC( Ifd_Man_t, 1 ); p->nObjsAlloc = Abc_PrimeCudd( 50000000 ); p->nObjs = 2; p->pObjs = ABC_CALLOC( Ifd_Obj_t, p->nObjsAlloc ); memset( p->pObjs, 0xFF, sizeof(Ifd_Obj_t) ); // const node (p->pObjs + 1)->nSupp = 1; // variable (p->pObjs + 1)->fWay = 1; // variable // hashing operations p->vArgs = Vec_IntAlloc( 4000 ); p->vRes = Vec_IntAlloc( 1000 ); p->vHash = Hsh_IntManStart( p->vArgs, 4, 1000 ); p->vMarks = Vec_IntAlloc( 100 ); Vec_IntPush( p->vMarks, 0 ); Vec_IntPush( p->vMarks, 1 ); Vec_IntPush( p->vMarks, p->nObjs ); // other data p->vSuper = Vec_IntAlloc( 1000 ); p->vTruths = Vec_WrdAlloc( 1000 ); p->vClauses = Vec_IntAlloc( 1000 ); return p; } void Ifd_ManStop( Ifd_Man_t * p ) { int i, This, Prev = 0; Vec_IntForEachEntryStart( p->vMarks, This, i, 1 ) { printf( "%d(%d:%d) ", i-1, This, This - Prev ); Prev = This; } printf( "\n" ); Vec_IntFreeP( &p->vArgs ); Vec_IntFreeP( &p->vRes ); Vec_WrdFreeP( &p->vTruths ); Vec_IntFreeP( &p->vClauses ); Vec_IntFreeP( &p->vMarks ); Hsh_IntManStop( p->vHash ); Vec_IntFreeP( &p->vSuper ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Printing structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ifd_ObjPrint_rec( Ifd_Man_t * p, int iLit, int * pCounter, int DiffType ) { char Symb[2][4] = { {'?','(','[','<'}, {'?',')',']','>'} }; Ifd_Obj_t * pDsd; if ( Abc_LitIsCompl(iLit) ) printf( "!" ), iLit = Abc_LitNot(iLit); if ( iLit == 2 ) { printf( "%c", 'a' + (*pCounter)++ ); return; } pDsd = Ifd_ManObjFromLit( p, iLit ); if ( DiffType ) printf( "%c", Symb[0][pDsd->Type] ); Ifd_ObjPrint_rec( p, pDsd->pFans[0], pCounter, pDsd->Type == 3 || Abc_LitIsCompl(pDsd->pFans[0]) || pDsd->Type != Ifd_ManObjFromLit(p, pDsd->pFans[0])->Type ); Ifd_ObjPrint_rec( p, pDsd->pFans[1], pCounter, pDsd->Type == 3 || Abc_LitIsCompl(pDsd->pFans[1]) || pDsd->Type != Ifd_ManObjFromLit(p, pDsd->pFans[1])->Type ); if ( pDsd->pFans[2] != -1 ) Ifd_ObjPrint_rec( p, pDsd->pFans[2], pCounter, pDsd->Type == 3 || Abc_LitIsCompl(pDsd->pFans[2]) || pDsd->Type != Ifd_ManObjFromLit(p, pDsd->pFans[2])->Type ); if ( DiffType ) printf( "%c", Symb[1][pDsd->Type] ); } void Ifd_ObjPrint( Ifd_Man_t * p, int iLit ) { int Counter = 0; if ( iLit == 0 ) { printf( "0" ); return; } if ( iLit == 1 ) { printf( "1" ); return; } Ifd_ObjPrint_rec( p, iLit, &Counter, 1 ); } void Ifd_ManPrint2( Ifd_Man_t * p ) { int i; for ( i = 0; i < p->nObjs; i++ ) { printf( "%4d : ", i ); Ifd_ObjPrint( p, Abc_Var2Lit( i, 0 ) ); printf( "\n" ); } } void Ifd_ManPrint( Ifd_Man_t * p ) { int i; for ( i = 0; i < p->nObjs; i++ ) { word Fun = Vec_WrdEntry( p->vTruths, i ); printf( " { " ); printf( "%d, ", Extra_TruthSupportSize((unsigned *)&Fun, 6) ); printf( "%2d, ", Ifd_LitNumAnds(p, Abc_Var2Lit(i, 0)) ); printf( "%2d, ", Vec_IntEntry(p->vClauses, i) ); printf( "ABC_CONST(" ); Extra_PrintHex( stdout, (unsigned *)&Fun, 6 ); printf( "), \"" ); Ifd_ObjPrint( p, Abc_Var2Lit( i, 0 ) ); printf( "\" }, // %4d \n", i ); } } /**Function************************************************************* Synopsis [Computing truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Ifd_ObjTruth_rec( Ifd_Man_t * p, int iLit, int * pCounter ) { static word s_Truths6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; Ifd_Obj_t * pDsd; word Fun0, Fun1, Fun2 = 0; assert( !Abc_LitIsCompl(iLit) ); if ( iLit == 2 ) return s_Truths6[(*pCounter)++]; pDsd = Ifd_ManObjFromLit( p, iLit ); Fun0 = Ifd_ObjTruth_rec( p, Abc_LitRegular(pDsd->pFans[0]), pCounter ); Fun1 = Ifd_ObjTruth_rec( p, Abc_LitRegular(pDsd->pFans[1]), pCounter ); if ( pDsd->pFans[2] != -1 ) Fun2 = Ifd_ObjTruth_rec( p, Abc_LitRegular(pDsd->pFans[2]), pCounter ); Fun0 = Abc_LitIsCompl(pDsd->pFans[0]) ? ~Fun0 : Fun0; Fun1 = Abc_LitIsCompl(pDsd->pFans[1]) ? ~Fun1 : Fun1; if ( pDsd->pFans[2] != -1 ) Fun2 = Abc_LitIsCompl(pDsd->pFans[2]) ? ~Fun2 : Fun2; if ( pDsd->Type == 1 ) return Fun0 & Fun1; if ( pDsd->Type == 2 ) return Fun0 ^ Fun1; if ( pDsd->Type == 3 ) return (Fun2 & Fun1) | (~Fun2 & Fun0); assert( 0 ); return -1; } word Ifd_ObjTruth( Ifd_Man_t * p, int iLit ) { word Fun; int Counter = 0; if ( iLit == 0 ) return 0; if ( iLit == 1 ) return ~(word)0; Fun = Ifd_ObjTruth_rec( p, Abc_LitRegular(iLit), &Counter ); return Abc_LitIsCompl(iLit) ? ~Fun : Fun; } void Ifd_ManTruthAll( Ifd_Man_t * p ) { word Fun; int i; assert( Vec_WrdSize(p->vTruths) == 0 ); for ( i = 0; i < p->nObjs; i++ ) { Fun = Ifd_ObjTruth( p, Abc_Var2Lit( i, 0 ) ); Vec_WrdPush( p->vTruths, Fun ); // Extra_PrintHex( stdout, (unsigned *)&Fun, 6 ); printf( " " ); // Kit_DsdPrintFromTruth( (unsigned *)&Fun, 6 ); printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mpm_ComputeCnfSizeOne( word Truth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vCnf ) { Vec_StrClear( vCnf ); if ( Truth == 0 || ~Truth == 0 ) { // assert( nVars == 0 ); Vec_StrPush( vCnf, (char)(Truth == 0) ); Vec_StrPush( vCnf, (char)-1 ); return 1; } else { int i, k, c, RetValue, Literal, Cube, nCubes = 0; assert( nVars > 0 ); for ( c = 0; c < 2; c ++ ) { Truth = c ? ~Truth : Truth; RetValue = Kit_TruthIsop( (unsigned *)&Truth, nVars, vCover, 0 ); assert( RetValue == 0 ); nCubes += Vec_IntSize( vCover ); Vec_IntForEachEntry( vCover, Cube, i ) { for ( k = 0; k < nVars; k++ ) { Literal = 3 & (Cube >> (k << 1)); if ( Literal == 1 ) // '0' -> pos lit Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 0) ); else if ( Literal == 2 ) // '1' -> neg lit Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 1) ); else if ( Literal != 0 ) assert( 0 ); } Vec_StrPush( vCnf, (char)Abc_Var2Lit(nVars, c) ); Vec_StrPush( vCnf, (char)-1 ); } } return nCubes; } } void Mpm_ComputeCnfSizeAll( Ifd_Man_t * p ) { Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); Vec_Str_t * vCnf = Vec_StrAlloc( 1000 ); word Truth; int i; assert( Vec_IntSize(p->vClauses) == 0 ); Vec_WrdForEachEntry( p->vTruths, Truth, i ) Vec_IntPush( p->vClauses, Mpm_ComputeCnfSizeOne(Truth, 6, vCover, vCnf) ); Vec_IntFree( vCover ); Vec_StrFree( vCnf ); } /**Function************************************************************* Synopsis [Canonicizing DSD structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ifd_ManHashLookup( Ifd_Man_t * p, int iDsd0, int iDsd1, int iDsdC, int Type ) { int pData[4]; assert( iDsdC != -1 || iDsd0 >= iDsd1 ); assert( iDsdC == -1 || !Abc_LitIsCompl(iDsd1) ); pData[0] = iDsd0; pData[1] = iDsd1; pData[2] = iDsdC; pData[3] = Type; return *Hsh_IntManLookup( p->vHash, (unsigned *)pData ); } void Ifd_ManHashInsert( Ifd_Man_t * p, int iDsd0, int iDsd1, int iDsdC, int Type, int Res ) { int iObj; assert( iDsdC != -1 || iDsd0 >= iDsd1 ); assert( iDsdC == -1 || !Abc_LitIsCompl(iDsd1) ); Vec_IntPush( p->vArgs, iDsd0 ); Vec_IntPush( p->vArgs, iDsd1 ); Vec_IntPush( p->vArgs, iDsdC ); Vec_IntPush( p->vArgs, Type ); iObj = Hsh_IntManAdd( p->vHash, Vec_IntSize(p->vRes) ); assert( iObj == Vec_IntSize(p->vRes) ); Vec_IntPush( p->vRes, Res ); assert( 4 * Vec_IntSize(p->vRes) == Vec_IntSize(p->vArgs) ); } int Ifd_ManHashFindOrAdd( Ifd_Man_t * p, int iDsd0, int iDsd1, int iDsdC, int Type ) { Ifd_Obj_t * pObj; int iObj, Value; assert( iDsdC != -1 || iDsd0 >= iDsd1 ); assert( iDsdC == -1 || !Abc_LitIsCompl(iDsd1) ); Vec_IntPush( p->vArgs, iDsd0 ); Vec_IntPush( p->vArgs, iDsd1 ); Vec_IntPush( p->vArgs, iDsdC ); Vec_IntPush( p->vArgs, Type ); Value = Hsh_IntManAdd( p->vHash, Vec_IntSize(p->vRes) ); if ( Value < Vec_IntSize(p->vRes) ) { iObj = Vec_IntEntry(p->vRes, Value); Vec_IntShrink( p->vArgs, Vec_IntSize(p->vArgs) - 4 ); pObj = Ifd_ManObj( p, iObj ); // pObj->nFreq++; assert( (int)pObj->Type == Type ); assert( (int)pObj->nSupp == Ifd_LitSuppSize(p, iDsd0) + Ifd_LitSuppSize(p, iDsd1) + Ifd_LitSuppSize(p, iDsdC) ); } else { if ( p->nObjs == p->nObjsAlloc ) printf( "The number of nodes is more than %d\n", p->nObjs ); assert( p->nObjs < p->nObjsAlloc ); iObj = p->nObjs; pObj = Ifd_ManObj( p, p->nObjs++ ); // pObj->nFreq = 1; pObj->nSupp = Ifd_LitSuppSize(p, iDsd0) + Ifd_LitSuppSize(p, iDsd1) + Ifd_LitSuppSize(p, iDsdC); pObj->nAnds = Ifd_LitNumAnds(p, iDsd0) + Ifd_LitNumAnds(p, iDsd1) + Ifd_LitNumAnds(p, iDsdC) + ((Type == 1) ? 1 : 3); pObj->Type = Type; if ( Type == 1 ) pObj->fWay = 0; else if ( Type == 2 ) pObj->fWay = Ifd_ManObjFromLit(p, iDsd0)->fWay || Ifd_ManObjFromLit(p, iDsd1)->fWay; else if ( Type == 3 ) // pObj->fWay = (Ifd_ManObjFromLit(p, iDsd0)->fWay && Ifd_ManObjFromLit(p, iDsd1)->fWay) || (Abc_Lit2Var(iDsd0) == Abc_Lit2Var(iDsd1) && Ifd_ManObjFromLit(p, iDsdC)->fWay); pObj->fWay = (Ifd_ManObjFromLit(p, iDsd0)->fWay && Ifd_ManObjFromLit(p, iDsd1)->fWay) || (iDsd0 == Abc_LitNot(iDsd1) && Ifd_ManObjFromLit(p, iDsdC)->fWay); else assert( 0 ); pObj->pFans[0] = iDsd0; pObj->pFans[1] = iDsd1; pObj->pFans[2] = iDsdC; Vec_IntPush( p->vRes, iObj ); } assert( 4 * Vec_IntSize(p->vRes) == Vec_IntSize(p->vArgs) ); return iObj; } void Ifd_ManOperSuper_rec( Ifd_Man_t * p, int iLit, int Type, Vec_Int_t * vObjs ) { Ifd_Obj_t * pDsd = Ifd_ManObjFromLit( p, iLit ); if ( Abc_LitIsCompl(iLit) || (int)pDsd->Type != Type ) Vec_IntPush( vObjs, iLit ); else { Ifd_ManOperSuper_rec( p, pDsd->pFans[0], Type, vObjs ); Ifd_ManOperSuper_rec( p, pDsd->pFans[1], Type, vObjs ); } } int Ifd_ManOper( Ifd_Man_t * p, int iDsd0, int iDsd1, int iDsdC, int Type ) { int i, iLit0, iLit1, iThis, fCompl = 0; if ( Type == 1 ) // AND { if ( iDsd0 == 0 || iDsd1 == 0 ) return 0; if ( iDsd0 == 1 || iDsd1 == 1 ) return (iDsd0 == 1) ? iDsd1 : iDsd0; } else if ( Type == 2 ) // XOR { if ( iDsd0 < 2 ) return Abc_LitNotCond( iDsd1, iDsd0 ); if ( iDsd1 < 2 ) return Abc_LitNotCond( iDsd0, iDsd1 ); if ( Abc_LitIsCompl(iDsd0) ) fCompl ^= 1, iDsd0 = Abc_LitNot(iDsd0); if ( Abc_LitIsCompl(iDsd1) ) fCompl ^= 1, iDsd1 = Abc_LitNot(iDsd1); } else if ( Type == 3 ) { if ( Abc_LitIsCompl(iDsdC) ) { ABC_SWAP( int, iDsd0, iDsd1 ); iDsdC = Abc_LitNot(iDsdC); } if ( Abc_LitIsCompl(iDsd1) ) fCompl ^= 1, iDsd0 = Abc_LitNot(iDsd0), iDsd1 = Abc_LitNot(iDsd1); } assert( iDsd0 > 1 && iDsd1 > 1 && Type >= 1 && Type <= 3 ); /* // check cache iThis = Ifd_ManHashLookup( p, iDsd0, iDsd1, iDsdC, Type ); if ( iThis != -1 ) return Abc_Var2Lit( iThis, fCompl ); */ // create new entry if ( Type == 3 ) { iThis = Ifd_ManHashFindOrAdd( p, iDsd0, iDsd1, iDsdC, Type ); return Abc_Var2Lit( iThis, fCompl ); } assert( iDsdC == -1 ); Vec_IntClear( p->vSuper ); Ifd_ManOperSuper_rec( p, iDsd0, Type, p->vSuper ); Ifd_ManOperSuper_rec( p, iDsd1, Type, p->vSuper ); Vec_IntSort( p->vSuper, 1 ); iLit0 = Vec_IntEntry( p->vSuper, 0 ); Vec_IntForEachEntryStart( p->vSuper, iLit1, i, 1 ) iLit0 = Abc_Var2Lit( Ifd_ManHashFindOrAdd(p, iLit0, iLit1, -1, Type), 0 ); assert( !Abc_LitIsCompl(iLit0) ); // insert into cache // if ( Vec_IntSize(p->vSuper) > 2 ) // Ifd_ManHashInsert( p, iDsd0, iDsd1, iDsdC, Type, iLit0 ); return Abc_LitNotCond( iLit0, fCompl ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ifd_ManFindDsd_rec( Ifd_Man_t * pMan, char * pStr, char ** p, int * pMatches ) { int fCompl = 0; if ( **p == '!' ) (*p)++, fCompl = 1; if ( **p >= 'a' && **p <= 'f' ) // var { assert( **p - 'a' >= 0 && **p - 'a' < 6 ); return Abc_Var2Lit( 1, fCompl ); } if ( **p == '(' ) // and/or { char * q = pStr + pMatches[ *p - pStr ]; int Lit, Res = 1; assert( **p == '(' && *q == ')' ); for ( (*p)++; *p < q; (*p)++ ) { Lit = Ifd_ManFindDsd_rec( pMan, pStr, p, pMatches ); Res = Ifd_ManOper( pMan, Res, Lit, 0, 1 ); } assert( *p == q ); return Abc_LitNotCond( Res, fCompl ); } if ( **p == '[' ) // xor { char * q = pStr + pMatches[ *p - pStr ]; int Lit, Res = 0; assert( **p == '[' && *q == ']' ); for ( (*p)++; *p < q; (*p)++ ) { Lit = Ifd_ManFindDsd_rec( pMan, pStr, p, pMatches ); Res = Ifd_ManOper( pMan, Res, Lit, 0, 2 ); } assert( *p == q ); return Abc_LitNotCond( Res, fCompl ); } if ( **p == '<' ) // mux { int Temp[3], * pTemp = Temp, Res; char * q = pStr + pMatches[ *p - pStr ]; assert( **p == '<' && *q == '>' ); // derive MAX components for ( (*p)++; *p < q; (*p)++ ) *pTemp++ = Ifd_ManFindDsd_rec( pMan, pStr, p, pMatches ); assert( pTemp == Temp + 3 ); assert( *p == q ); // Res = (Temp[0] & Temp[1]) | (~Temp[0] & Temp[2]); Res = Ifd_ManOper( pMan, Temp[2], Temp[1], Temp[0], 3 ); return Abc_LitNotCond( Res, fCompl ); } assert( 0 ); return 0; } #define IFM_MAX_STR 100 #define IFM_MAX_VAR 16 int * Ifd_ManComputeMatches( char * p ) { static int pMatches[IFM_MAX_STR]; int pNested[IFM_MAX_VAR]; int v, nNested = 0; for ( v = 0; p[v]; v++ ) { assert( v < IFM_MAX_STR ); pMatches[v] = 0; if ( p[v] == '(' || p[v] == '[' || p[v] == '<' || p[v] == '{' ) pNested[nNested++] = v; else if ( p[v] == ')' || p[v] == ']' || p[v] == '>' || p[v] == '}' ) pMatches[pNested[--nNested]] = v; assert( nNested < IFM_MAX_VAR ); } assert( nNested == 0 ); return pMatches; } int Ifd_ManFindDsd( Ifd_Man_t * pMan, char * p ) { int Res; if ( *p == '0' && *(p+1) == 0 ) Res = 0; else if ( *p == '1' && *(p+1) == 0 ) Res = 1; else Res = Ifd_ManFindDsd_rec( pMan, p, &p, Ifd_ManComputeMatches(p) ); assert( *++p == 0 ); return Res; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ifd_ManDsdTest2() { char * p = "(abc)"; // char * q = "(a[bc])"; // char * r = "[(def)]"; Ifd_Man_t * pMan = Ifd_ManStart(); int iLit = Ifd_ManFindDsd( pMan, p ); Ifd_ObjPrint( pMan, iLit ); Ifd_ManStop( pMan ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Ifd_ManDsdTruths( int nVars ) { int fUseMux = 1; Vec_Wrd_t * vTruths; Ifd_Man_t * pMan = Ifd_ManStart(); Ifd_Obj_t * pLeaf0, * pLeaf1, * pLeaf2; int v, i, j, k, c0, c1, c2; for ( v = 2; v <= nVars; v++ ) { // create ANDs/XORs for ( i = 1; i < v; i++ ) for ( j = 1; j < v; j++ ) if ( i + j == v ) { Ifd_ManForEachNodeWithSupp( pMan, i, pLeaf0, c0 ) Ifd_ManForEachNodeWithSupp( pMan, j, pLeaf1, c1 ) { assert( (int)pLeaf0->nSupp == i ); assert( (int)pLeaf1->nSupp == j ); Ifd_ManOper( pMan, Abc_Var2Lit(c0, 0), Abc_Var2Lit(c1, 0), -1, 1 ); if ( !pLeaf1->fWay ) Ifd_ManOper( pMan, Abc_Var2Lit(c0, 0), Abc_Var2Lit(c1, 1), -1, 1 ); if ( !pLeaf0->fWay ) Ifd_ManOper( pMan, Abc_Var2Lit(c0, 1), Abc_Var2Lit(c1, 0), -1, 1 ); if ( !pLeaf0->fWay && !pLeaf1->fWay ) Ifd_ManOper( pMan, Abc_Var2Lit(c0, 1), Abc_Var2Lit(c1, 1), -1, 1 ); Ifd_ManOper( pMan, Abc_Var2Lit(c0, 0), Abc_Var2Lit(c1, 0), -1, 2 ); } } // create MUX if ( fUseMux ) for ( i = 1; i < v-1; i++ ) for ( j = 1; j < v-1; j++ ) for ( k = 1; k < v-1; k++ ) if ( i + j + k == v ) { Ifd_ManForEachNodeWithSupp( pMan, i, pLeaf0, c0 ) Ifd_ManForEachNodeWithSupp( pMan, j, pLeaf1, c1 ) Ifd_ManForEachNodeWithSupp( pMan, k, pLeaf2, c2 ) { assert( (int)pLeaf0->nSupp == i ); assert( (int)pLeaf1->nSupp == j ); assert( (int)pLeaf2->nSupp == k ); //printf( "%d %d %d ", i, j, k ); //printf( "%d %d %d\n", Ifd_ObjId(pMan, pLeaf0), Ifd_ObjId(pMan, pLeaf1), Ifd_ObjId(pMan, pLeaf2) ); if ( pLeaf2->fWay && c0 < c1 ) continue; Ifd_ManOper( pMan, Abc_Var2Lit(c0, 0), Abc_Var2Lit(c1, 0), Abc_Var2Lit(c2, 0), 3 ); if ( !pLeaf0->fWay && !pLeaf1->fWay ) Ifd_ManOper( pMan, Abc_Var2Lit(c0, 1), Abc_Var2Lit(c1, 0), Abc_Var2Lit(c2, 0), 3 ); } } // bookmark Vec_IntPush( pMan->vMarks, pMan->nObjs ); } Ifd_ManTruthAll( pMan ); Mpm_ComputeCnfSizeAll( pMan ); // Ifd_ManPrint( pMan ); vTruths = pMan->vTruths; pMan->vTruths = NULL; Ifd_ManStop( pMan ); return vTruths; } /**Function************************************************************* Synopsis [Generating the guided array for minimal permutations.] Description [http://icodesnip.com/search/johnson%20trotter/] SideEffects [] SeeAlso [] ***********************************************************************/ void Ifd_ManDsdPermPrint( int * perm, int size ) { int i; for ( i = 0; i < size; i++ ) printf( "%d", perm[i] ); printf( "\n" ); } Vec_Int_t * Ifd_ManDsdPermJT( int n ) { Vec_Int_t * vGuide = Vec_IntAlloc( 100 ); int *array, *dir, tmp, tmp2, i, max; array = (int*)malloc(sizeof(int) * n); dir = (int*)calloc(n, sizeof(int)); for (i = 0; i < n; i++) array[i] = i; max = n - 1; if (n != 1) do { // Ifd_ManDsdPermPrint(array, n); tmp = array[max]; tmp2 = dir[max]; i = !dir[max] ? max - 1 : max + 1; array[max] = array[i]; array[i] = tmp; Vec_IntPush( vGuide, Abc_MinInt(max, i) ); dir[max] = dir[i]; dir[i] = tmp2; for (i = 0; i < n; i++) if (array[i] > tmp) dir[i] = !dir[i]; max = n; for (i = 0; i < n; i++) if (((!dir[i] && i != 0 && array[i] > array[i-1]) || (dir[i] && i != n-1 && array[i] > array[i+1])) && (array[i] > array[max] || max == n)) max = i; } while (max < n); // Ifd_ManDsdPermPrint(array,n); Vec_IntPush( vGuide, 0 ); free(dir); free(array); return vGuide; } int Ifd_ManDsdTest4() { int pPerm[6] = { 0, 1, 2, 3, 4, 5 }; Vec_Int_t * vGuide = Ifd_ManDsdPermJT( 6 ); int i, Entry; Vec_IntForEachEntry( vGuide, Entry, i ) { ABC_SWAP( int, pPerm[Entry], pPerm[Entry+1] ); Ifd_ManDsdPermPrint( pPerm, 6 ); } Vec_IntFree( vGuide ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Extra_Truth6SwapAdjacent( word t, int iVar ) { // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; assert( iVar < 5 ); return (t & PMasks[iVar][0]) | ((t & PMasks[iVar][1]) << (1 << iVar)) | ((t & PMasks[iVar][2]) >> (1 << iVar)); } static inline word Extra_Truth6ChangePhase( word t, int iVar) { // elementary truth tables static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; assert( iVar < 6 ); return ((t & ~Truth6[iVar]) << (1 << iVar)) | ((t & Truth6[iVar]) >> (1 << iVar)); } Vec_Wrd_t * Extra_Truth6AllConfigs2( word t, int * pComp, int * pPerm, int nVars ) { int nPerms = Extra_Factorial( nVars ); int nSwaps = (1 << nVars); Vec_Wrd_t * vTruths = Vec_WrdStart( nPerms * (1 << (nVars+1)) ); word tCur, tTemp1, tTemp2; int i, p, c; for ( i = 0; i < 2; i++ ) { tCur = i ? t : ~t; tTemp1 = tCur; for ( p = 0; p < nPerms; p++ ) { tTemp2 = tCur; for ( c = 0; c < nSwaps; c++ ) { Vec_WrdWriteEntry( vTruths, (p << (nVars+1))|(i << nVars)|c, tCur ); tCur = Extra_Truth6ChangePhase( tCur, pComp[c] ); } assert( tTemp2 == tCur ); tCur = Extra_Truth6SwapAdjacent( tCur, pPerm[p] ); } assert( tTemp1 == tCur ); } if ( t ) { int i; word Truth; Vec_WrdForEachEntry( vTruths, Truth, i ) assert( Truth ); } return vTruths; } Vec_Wrd_t * Extra_Truth6AllConfigs( word t, int * pComp, int * pPerm, int nVars ) { int nPerms = Extra_Factorial( nVars ); int nSwaps = (1 << nVars); Vec_Wrd_t * vTruths = Vec_WrdStart( nPerms * nSwaps ); word tCur = t, tTemp1, tTemp2; int p, c, Config; tTemp1 = tCur; for ( p = 0; p < nPerms; p++ ) { tCur = Extra_Truth6SwapAdjacent( tCur, pPerm[p] ); Config = 0; tTemp2 = tCur; for ( c = 0; c < nSwaps; c++ ) { Vec_WrdWriteEntry( vTruths, (p << nVars)|Config, tCur ); tCur = Extra_Truth6ChangePhase( tCur, pComp[c] ); Config ^= (1 << pComp[c]); } assert( Config == 0 ); assert( tTemp2 == tCur ); } assert( tTemp1 == tCur ); if ( t ) { int i; word Truth; Vec_WrdForEachEntry( vTruths, Truth, i ) assert( Truth ); } return vTruths; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ifd_ComputeSignature( word uTruth, int pCounts[6] ) { int v, Pos, Neg, Xor; for ( v = 0; v < 6; v++ ) { Neg = Abc_TtCountOnes( Abc_Tt6Cofactor0(uTruth, v) ) / 2; Pos = Abc_TtCountOnes( Abc_Tt6Cofactor1(uTruth, v) ) / 2; Xor = Abc_TtCountOnes( Abc_Tt6Cofactor0(uTruth, v) ^ Abc_Tt6Cofactor1(uTruth, v) ) / 2; if ( Pos <= Neg ) pCounts[v] = (Pos << 20) | (Neg << 10) | Xor; else pCounts[v] = (Neg << 20) | (Pos << 10) | Xor; } Vec_IntSelectSort( pCounts, 6 ); } int Ifd_ManDsdTest33() { int nVars = 6; Vec_Wrd_t * vTruths = Ifd_ManDsdTruths( nVars ); int i, v, pCounts[6]; word uTruth; Vec_WrdForEachEntry( vTruths, uTruth, i ) { Ifd_ComputeSignature( uTruth, pCounts ); // print printf( "%5d : ", i ); for ( v = 0; v < 6; v++ ) printf( "%2d %2d %2d ", (pCounts[v] >> 20) & 0xFF, (pCounts[v] >> 10) & 0xFF, (pCounts[v] >> 0) & 0xFF ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned *)&uTruth, nVars ); printf( "\n" ); } Vec_WrdFree( vTruths ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ifd_ManDsdTest() { int nVars = 6; FILE * pFile; char pFileName[32]; Vec_Wrd_t * vTruths = Ifd_ManDsdTruths( nVars ); Vec_Wrd_t * vVariants; Vec_Int_t * vUniques; Vec_Int_t * vCompls; Vec_Wrd_t * vTruthRes = Vec_WrdAlloc( 4000000 ); Vec_Int_t * vConfgRes = Vec_IntAlloc( 4000000 ); int * pComp, * pPerm; word Truth, Variant; int i, k, Uniq, Runner, Counter = 0; assert( nVars >= 3 && nVars <= 6 ); assert( Vec_WrdSize(vTruths) < (1<<10) ); vCompls = Vec_IntAlloc( 720 * 64 ); pComp = Extra_GreyCodeSchedule( nVars ); pPerm = Extra_PermSchedule( nVars ); Vec_WrdForEachEntry( vTruths, Truth, i ) { vVariants = Extra_Truth6AllConfigs( Truth, pComp, pPerm, nVars ); // save compl bits Vec_IntClear( vCompls ); Vec_WrdForEachEntry( vVariants, Variant, k ) { Vec_IntPush( vCompls, (int)(Variant & 1) ); Vec_WrdWriteEntry( vVariants, k, Variant & 1 ? ~Variant : Variant ); } // uniqify vUniques = Hsh_WrdManHashArray( vVariants, 1 ); Runner = 0; Vec_IntForEachEntry( vUniques, Uniq, k ) if ( Runner == Uniq ) { Variant = Vec_WrdEntry(vVariants, k); assert( (Variant & 1) == 0 ); Vec_WrdPush( vTruthRes, Variant ); Vec_IntPush( vConfgRes, (i << 17)|(Vec_IntEntry(vCompls, k) << 16)|k ); Runner++; } Vec_IntUniqify( vUniques ); assert( Runner == Vec_IntSize(vUniques) ); Counter += Vec_IntSize(vUniques); //printf( "%5d : ", i ); Kit_DsdPrintFromTruth( &Truth, nVars ), printf( " " ), Vec_IntPrint( vUniques ), printf( "\n" ); Vec_IntFree( vUniques ); Vec_WrdFree( vVariants ); } Vec_IntFree( vCompls ); Vec_WrdFree( vTruths ); ABC_FREE( pPerm ); ABC_FREE( pComp ); printf( "Total = %d.\n", Counter ); assert( Vec_WrdSize(vTruthRes) == Counter ); // write the data into a file sprintf( pFileName, "dsdfuncs%d.dat", nVars ); pFile = fopen( pFileName, "wb" ); fwrite( Vec_WrdArray(vTruthRes), sizeof(word), Vec_WrdSize(vTruthRes), pFile ); fwrite( Vec_IntArray(vConfgRes), sizeof(int), Vec_IntSize(vConfgRes), pFile ); fclose( pFile ); printf( "File \"%s\" with %d 6-input functions has been written out.\n", pFileName, Vec_IntSize(vConfgRes) ); Vec_WrdFree( vTruthRes ); Vec_IntFree( vConfgRes ); return 1; } int Ifd_ManDsdTest55() { abctime clk = Abc_Clock(); FILE * pFile; char * pFileName = "dsdfuncs6.dat"; int RetValue, size = Extra_FileSize( pFileName ) / 12; // 2866420 Vec_Wrd_t * vTruthRes = Vec_WrdAlloc( size + 1 ); Vec_Int_t * vConfgRes = Vec_IntAlloc( size ); Hsh_IntMan_t * pHash; pFile = fopen( pFileName, "rb" ); RetValue = fread( Vec_WrdArray(vTruthRes), sizeof(word), size, pFile ); RetValue = fread( Vec_IntArray(vConfgRes), sizeof(int), size, pFile ); vTruthRes->nSize = size; vConfgRes->nSize = size; // create hash table pHash = Hsh_WrdManHashArrayStart( vTruthRes, 1 ); // experiment with functions // cleanup Hsh_IntManStop( pHash ); Vec_WrdFree( vTruthRes ); Vec_IntFree( vConfgRes ); Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmTruth.c000066400000000000000000000207061300674244400233730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmTruth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Truth table manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmTruth.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //#define MPM_TRY_NEW //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Unifies variable order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Mpm_TruthStretch( word * pTruth, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, int nLimit ) { int i, k; for ( i = (int)pCut->nLeaves - 1, k = (int)pCut0->nLeaves - 1; i >= 0 && k >= 0; i-- ) { if ( pCut0->pLeaves[k] < pCut->pLeaves[i] ) continue; assert( pCut0->pLeaves[k] == pCut->pLeaves[i] ); if ( k < i ) Abc_TtSwapVars( pTruth, nLimit, k, i ); k--; } } /**Function************************************************************* Synopsis [Performs truth table support minimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mpm_CutTruthMinimize6( Mpm_Man_t * p, Mpm_Cut_t * pCut ) { unsigned uSupport; int i, k, nSuppSize; // compute the support of the cut's function word t = *Mpm_CutTruth( p, Abc_Lit2Var(pCut->iFunc) ); uSupport = Abc_Tt6SupportAndSize( t, Mpm_CutLeafNum(pCut), &nSuppSize ); if ( nSuppSize == Mpm_CutLeafNum(pCut) ) return 0; p->nSmallSupp += (int)(nSuppSize < 2); // update leaves and signature for ( i = k = 0; i < Mpm_CutLeafNum(pCut); i++ ) { if ( ((uSupport >> i) & 1) ) { if ( k < i ) { pCut->pLeaves[k] = pCut->pLeaves[i]; Abc_TtSwapVars( &t, p->nLutSize, k, i ); } k++; } } assert( k == nSuppSize ); pCut->nLeaves = nSuppSize; assert( nSuppSize == Abc_TtSupportSize(&t, 6) ); // save the result pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert(p->vTtMem, &t), Abc_LitIsCompl(pCut->iFunc) ); return 1; } static inline int Mpm_CutTruthMinimize7( Mpm_Man_t * p, Mpm_Cut_t * pCut ) { unsigned uSupport; int i, k, nSuppSize; // compute the support of the cut's function word * pTruth = Mpm_CutTruth( p, Abc_Lit2Var(pCut->iFunc) ); uSupport = Abc_TtSupportAndSize( pTruth, Mpm_CutLeafNum(pCut), &nSuppSize ); if ( nSuppSize == Mpm_CutLeafNum(pCut) ) return 0; p->nSmallSupp += (int)(nSuppSize < 2); // update leaves and signature Abc_TtCopy( p->Truth, pTruth, p->nTruWords, 0 ); for ( i = k = 0; i < Mpm_CutLeafNum(pCut); i++ ) { if ( ((uSupport >> i) & 1) ) { if ( k < i ) { pCut->pLeaves[k] = pCut->pLeaves[i]; Abc_TtSwapVars( p->Truth, p->nLutSize, k, i ); } k++; } } assert( k == nSuppSize ); assert( nSuppSize == Abc_TtSupportSize(p->Truth, Mpm_CutLeafNum(pCut)) ); pCut->nLeaves = nSuppSize; // save the result pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert(p->vTtMem, p->Truth), Abc_LitIsCompl(pCut->iFunc) ); return 1; } /**Function************************************************************* Synopsis [Performs truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mpm_CutComputeTruth6( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type ) { word * pTruth0 = Mpm_CutTruth( p, Abc_Lit2Var(pCut0->iFunc) ); word * pTruth1 = Mpm_CutTruth( p, Abc_Lit2Var(pCut1->iFunc) ); word * pTruthC = NULL; word t0 = (fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iFunc)) ? ~*pTruth0 : *pTruth0; word t1 = (fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iFunc)) ? ~*pTruth1 : *pTruth1; word tC = 0, t = 0; Mpm_TruthStretch( &t0, pCut, pCut0, p->nLutSize ); Mpm_TruthStretch( &t1, pCut, pCut1, p->nLutSize ); if ( pCutC ) { pTruthC = Mpm_CutTruth( p, Abc_Lit2Var(pCutC->iFunc) ); tC = (fComplC ^ pCutC->fCompl ^ Abc_LitIsCompl(pCutC->iFunc)) ? ~*pTruthC : *pTruthC; Mpm_TruthStretch( &tC, pCut, pCutC, p->nLutSize ); } assert( p->nLutSize <= 6 ); if ( Type == 1 ) t = t0 & t1; else if ( Type == 2 ) t = t0 ^ t1; else if ( Type == 3 ) t = (tC & t1) | (~tC & t0); else assert( 0 ); // save the result if ( t & 1 ) { t = ~t; pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert( p->vTtMem, &t ), 1 ); } else pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert( p->vTtMem, &t ), 0 ); if ( p->pPars->fCutMin ) return Mpm_CutTruthMinimize6( p, pCut ); return 1; } static inline int Mpm_CutComputeTruth7( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type ) { word * pTruth0 = Mpm_CutTruth( p, Abc_Lit2Var(pCut0->iFunc) ); word * pTruth1 = Mpm_CutTruth( p, Abc_Lit2Var(pCut1->iFunc) ); word * pTruthC = NULL; Abc_TtCopy( p->Truth0, pTruth0, p->nTruWords, fCompl0 ^ pCut0->fCompl ^ Abc_LitIsCompl(pCut0->iFunc) ); Abc_TtCopy( p->Truth1, pTruth1, p->nTruWords, fCompl1 ^ pCut1->fCompl ^ Abc_LitIsCompl(pCut1->iFunc) ); Mpm_TruthStretch( p->Truth0, pCut, pCut0, p->nLutSize ); Mpm_TruthStretch( p->Truth1, pCut, pCut1, p->nLutSize ); if ( pCutC ) { pTruthC = Mpm_CutTruth( p, Abc_Lit2Var(pCutC->iFunc) ); Abc_TtCopy( p->TruthC, pTruthC, p->nTruWords, fComplC ^ pCutC->fCompl ^ Abc_LitIsCompl(pCutC->iFunc) ); Mpm_TruthStretch( p->TruthC, pCut, pCutC, p->nLutSize ); } if ( Type == 1 ) Abc_TtAnd( p->Truth, p->Truth0, p->Truth1, p->nTruWords, 0 ); else if ( Type == 2 ) Abc_TtXor( p->Truth, p->Truth0, p->Truth1, p->nTruWords, 0 ); else if ( Type == 3 ) Abc_TtMux( p->Truth, p->TruthC, p->Truth1, p->Truth0, p->nTruWords ); else assert( 0 ); // save the result if ( p->Truth[0] & 1 ) { Abc_TtNot( p->Truth, p->nTruWords ); pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert( p->vTtMem, p->Truth ), 1 ); } else pCut->iFunc = Abc_Var2Lit( Vec_MemHashInsert( p->vTtMem, p->Truth ), 0 ); if ( p->pPars->fCutMin ) return Mpm_CutTruthMinimize7( p, pCut ); return 1; } int Mpm_CutComputeTruth( Mpm_Man_t * p, Mpm_Cut_t * pCut, Mpm_Cut_t * pCut0, Mpm_Cut_t * pCut1, Mpm_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, int Type ) { int RetValue; if ( p->nLutSize <= 6 ) RetValue = Mpm_CutComputeTruth6( p, pCut, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, Type ); else RetValue = Mpm_CutComputeTruth7( p, pCut, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, Type ); #ifdef MPM_TRY_NEW { extern unsigned Abc_TtCanonicize( word * pTruth, int nVars, char * pCanonPerm ); char pCanonPerm[16]; memcpy( p->Truth0, p->Truth, sizeof(word) * p->nTruWords ); Abc_TtCanonicize( p->Truth0, pCut->nLimit, pCanonPerm ); } #endif return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/mpm/mpmUtil.c000066400000000000000000000027071300674244400232030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mpmUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Configurable technology mapper.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 1, 2013.] Revision [$Id: mpmUtil.c,v 1.00 2013/06/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mpmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/000077500000000000000000000000001300674244400213725ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/module.make000066400000000000000000000004451300674244400235210ustar00rootroot00000000000000SRC += src/map/scl/scl.c \ src/map/scl/sclBuffer.c \ src/map/scl/sclBufSize.c \ src/map/scl/sclDnsize.c \ src/map/scl/sclLiberty.c \ src/map/scl/sclLibScl.c \ src/map/scl/sclLibUtil.c \ src/map/scl/sclLoad.c \ src/map/scl/sclSize.c \ src/map/scl/sclUpsize.c \ src/map/scl/sclUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/scl.c000066400000000000000000002106461300674244400223300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [scl.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Relevant command handlers.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: scl.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclSize.h" #include "base/main/mainInt.h" #include "misc/util/utilNam.h" #include "sclCon.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Scl_CommandReadLib ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandWriteLib ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandReadScl ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandWriteScl ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandPrintLib ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandLeak2Area ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandDumpGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandPrintGS ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandStime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandTopo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandUnBuffer ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandBuffer ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandBufferOld ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandMinsize ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandMaxsize ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandUpsize ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandDnsize ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandPrintBuf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandReadConstr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandWriteConstr( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandPrintConstr( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Scl_CommandResetConstr( Abc_Frame_t * pAbc, int argc, char ** argv ); static inline Scl_Con_t * Scl_ConGetMan( Abc_Frame_t * pAbc ) { return (Scl_Con_t *)pAbc->pAbcCon; } static inline void Scl_ConFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcCon ) Scl_ConFree(Scl_ConGetMan(pAbc)); } static inline void Scl_ConUpdateMan( Abc_Frame_t * pAbc, Scl_Con_t * p ) { Scl_ConFreeMan(pAbc); pAbc->pAbcCon = p; } Scl_Con_t * Scl_ConReadMan() { return Scl_ConGetMan( Abc_FrameGetGlobalFrame() ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Updating library in the frameframe.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclLoad( SC_Lib * pLib, SC_Lib ** ppScl ) { if ( *ppScl ) { Abc_SclLibFree( *ppScl ); *ppScl = NULL; } assert( *ppScl == NULL ); if ( pLib ) *(SC_Lib **)ppScl = pLib; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Scl_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "SCL mapping", "read_lib", Scl_CommandReadLib, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "write_lib", Scl_CommandWriteLib, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "print_lib", Scl_CommandPrintLib, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "leak2area", Scl_CommandLeak2Area, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "read_scl", Scl_CommandReadScl, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "write_scl", Scl_CommandWriteScl, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "dump_genlib", Scl_CommandDumpGen, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "print_gs", Scl_CommandPrintGS, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "stime", Scl_CommandStime, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "topo", Scl_CommandTopo, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "unbuffer", Scl_CommandUnBuffer, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "buffer", Scl_CommandBuffer, 1 ); // Cmd_CommandAdd( pAbc, "SCL mapping", "_buffer", Scl_CommandBufferOld, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "minsize", Scl_CommandMinsize, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "maxsize", Scl_CommandMaxsize, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "upsize", Scl_CommandUpsize, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "dnsize", Scl_CommandDnsize, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "print_buf", Scl_CommandPrintBuf, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "read_constr", Scl_CommandReadConstr, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "write_constr", Scl_CommandWriteConstr, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "print_constr", Scl_CommandPrintConstr, 0 ); Cmd_CommandAdd( pAbc, "SCL mapping", "reset_constr", Scl_CommandResetConstr, 0 ); } void Scl_End( Abc_Frame_t * pAbc ) { Abc_SclLoad( NULL, (SC_Lib **)&pAbc->pLibScl ); Scl_ConUpdateMan( pAbc, NULL ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileName; FILE * pFile; SC_Lib * pLib; int c, fDump = 0; float Slew = 0; float Gain = 0; int nGatesMin = 0; int fShortNames = 0; int fVerbose = 1; int fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "SGMdnvwh" ) ) != EOF ) { switch ( c ) { 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 'd': fDump ^= 1; break; case 'n': fShortNames ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "rb" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName ); return 1; } fclose( pFile ); // read new library pLib = Abc_SclReadLiberty( pFileName, fVerbose, fVeryVerbose ); if ( pLib == NULL ) { fprintf( pAbc->Err, "Reading SCL library from file \"%s\" has failed. \n", pFileName ); return 1; } if ( Abc_SclLibClassNum(pLib) < 3 ) { fprintf( pAbc->Err, "Library with only %d cell classes cannot be used.\n", Abc_SclLibClassNum(pLib) ); Abc_SclLibFree(pLib); return 0; } Abc_SclLoad( pLib, (SC_Lib **)&pAbc->pLibScl ); // convert the library if needed if ( fShortNames ) Abc_SclShortNames( pLib ); // dump the resulting library if ( fDump && pAbc->pLibScl ) Abc_SclWriteLiberty( Extra_FileNameGenericAppend(pFileName, "_temp.lib"), (SC_Lib *)pAbc->pLibScl ); // extract genlib library if ( pAbc->pLibScl ) { Abc_SclInstallGenlib( pAbc->pLibScl, Slew, Gain, nGatesMin ); Mio_LibraryTransferCellIds(); } return 0; usage: fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnvwh] \n" ); fprintf( pAbc->Err, "\t reads Liberty library from file\n" ); fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); fprintf( pAbc->Err, "\t-M num : skip gate classes whose size is less than this [default = %d]\n", nGatesMin ); fprintf( pAbc->Err, "\t-d : toggle dumping the parsed library into file \"*_temp.lib\" [default = %s]\n", fDump? "yes": "no" ); fprintf( pAbc->Err, "\t-n : toggle replacing gate/pin names by short strings [default = %s]\n", fShortNames? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandWriteLib( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; 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; if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); return 1; } // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "wb" )) == NULL ) { fprintf( pAbc->Err, "Cannot open output file \"%s\". \n", pFileName ); return 1; } fclose( pFile ); // save current library Abc_SclWriteLiberty( pFileName, (SC_Lib *)pAbc->pLibScl ); return 0; usage: fprintf( pAbc->Err, "usage: write_lib [-h] \n" ); fprintf( pAbc->Err, "\t write current Liberty library into file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\t : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandPrintLib( Abc_Frame_t * pAbc, int argc, char **argv ) { float Slew = 0; // use library float Gain = 100; int fInvOnly = 0; int fShort = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "SGish" ) ) != EOF ) { switch ( c ) { 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 'i': fInvOnly ^= 1; break; case 's': fShort ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); return 1; } // save current library Abc_SclPrintCells( (SC_Lib *)pAbc->pLibScl, Slew, Gain, fInvOnly, fShort ); return 0; usage: fprintf( pAbc->Err, "usage: print_lib [-SG float] [-ish]\n" ); fprintf( pAbc->Err, "\t prints statistics of Liberty library\n" ); fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); fprintf( pAbc->Err, "\t-i : toggle printing invs/bufs only [default = %s]\n", fInvOnly? "yes": "no" ); fprintf( pAbc->Err, "\t-s : toggle printing in short format [default = %s]\n", fShort? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandLeak2Area( Abc_Frame_t * pAbc, int argc, char **argv ) { float A = 1, B = 1; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ABvh" ) ) != EOF ) { switch ( c ) { case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by a floating point number.\n" ); goto usage; } A = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( A <= 0.0 ) goto usage; break; case 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by a floating point number.\n" ); goto usage; } B = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( B <= 0.0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); return 1; } // update the current library Abc_SclConvertLeakageIntoArea( (SC_Lib *)pAbc->pLibScl, A, B ); return 0; usage: fprintf( pAbc->Err, "usage: leak2area [-AB float] [-v]\n" ); fprintf( pAbc->Err, "\t converts leakage into area: Area = A * Area + B * Leakage\n" ); fprintf( pAbc->Err, "\t-A float : the multiplicative coefficient to transform area [default = %.2f]\n", A ); fprintf( pAbc->Err, "\t-B float : the multiplicative coefficient to transform leakage [default = %.2f]\n", B ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandReadScl( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; SC_Lib * pLib; char * pFileName; int c, fDump = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { case 'd': fDump ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "rb" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName ); return 1; } fclose( pFile ); // read new library pLib = Abc_SclReadFromFile( pFileName ); if ( pLib == NULL ) { fprintf( pAbc->Err, "Reading SCL library from file \"%s\" has failed. \n", pFileName ); return 1; } Abc_SclLoad( pLib, (SC_Lib **)&pAbc->pLibScl ); if ( fDump ) Abc_SclWriteLiberty( Extra_FileNameGenericAppend(pFileName, "_temp.lib"), (SC_Lib *)pAbc->pLibScl ); // extract genlib library if ( pAbc->pLibScl ) { Abc_SclInstallGenlib( pAbc->pLibScl, 0, 0, 0 ); Mio_LibraryTransferCellIds(); } return 0; usage: fprintf( pAbc->Err, "usage: read_scl [-dh] \n" ); fprintf( pAbc->Err, "\t reads extracted Liberty library from file\n" ); fprintf( pAbc->Err, "\t-d : toggle dumping the parsed library into file \"*_temp.lib\" [default = %s]\n", fDump? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandWriteScl( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; 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; if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); return 1; } // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "wb" )) == NULL ) { fprintf( pAbc->Err, "Cannot open output file \"%s\". \n", pFileName ); return 1; } fclose( pFile ); // save current library Abc_SclWriteScl( pFileName, (SC_Lib *)pAbc->pLibScl ); return 0; usage: fprintf( pAbc->Err, "usage: write_scl [-h] \n" ); fprintf( pAbc->Err, "\t write extracted Liberty library into file\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); fprintf( pAbc->Err, "\t : the name of the file to write\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandDumpGen( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pFileName = NULL; float Slew = 0; // use the library float Gain = 200; int nGatesMin = 4; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "SGMvh" ) ) != EOF ) { switch ( c ) { 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 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); goto usage; } if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; Abc_SclDumpGenlib( pFileName, (SC_Lib *)pAbc->pLibScl, Slew, Gain, nGatesMin ); return 0; usage: fprintf( pAbc->Err, "usage: dump_genlib [-SG float] [-M num] [-vh] \n" ); fprintf( pAbc->Err, "\t writes GENLIB file for SCL library\n" ); fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); fprintf( pAbc->Err, "\t-M num : skip gate classes whose size is less than this [default = %d]\n", nGatesMin ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); fprintf( pAbc->Err, "\t : optional GENLIB file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandPrintGS( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( Abc_FrameReadNtk(pAbc) == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) { fprintf( pAbc->Err, "The current network is not mapped.\n" ); return 1; } if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); return 1; } // save current library Abc_SclPrintGateSizes( (SC_Lib *)pAbc->pLibScl, Abc_FrameReadNtk(pAbc) ); return 0; usage: fprintf( pAbc->Err, "usage: print_gs [-h]\n" ); fprintf( pAbc->Err, "\t prints gate sizes in the current mapping\n" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandStime( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; int fShowAll = 0; int fUseWireLoads = 0; int fPrintPath = 0; int fDumpStats = 0; int nTreeCRatio = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Xcapdh" ) ) != EOF ) { switch ( c ) { case 'X': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" ); goto usage; } nTreeCRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTreeCRatio < 0 ) goto usage; break; case 'c': fUseWireLoads ^= 1; break; case 'a': fShowAll ^= 1; break; case 'p': fPrintPath ^= 1; break; case 'd': fDumpStats ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( Abc_FrameReadNtk(pAbc) == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) { fprintf( pAbc->Err, "The current network is not mapped.\n" ); return 1; } if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) { fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); return 1; } if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); return 1; } Abc_SclTimePerform( (SC_Lib *)pAbc->pLibScl, Abc_FrameReadNtk(pAbc), nTreeCRatio, fUseWireLoads, fShowAll, fPrintPath, fDumpStats ); return 0; usage: fprintf( pAbc->Err, "usage: stime [-X num] [-capdth]\n" ); fprintf( pAbc->Err, "\t performs STA using Liberty library\n" ); fprintf( pAbc->Err, "\t-X : min Cout/Cave ratio for tree estimations [default = %d]\n", nTreeCRatio ); fprintf( pAbc->Err, "\t-c : toggle using wire-loads if specified [default = %s]\n", fUseWireLoads? "yes": "no" ); fprintf( pAbc->Err, "\t-a : display timing information for all nodes [default = %s]\n", fShowAll? "yes": "no" ); fprintf( pAbc->Err, "\t-p : display timing information for critical path [default = %s]\n", fPrintPath? "yes": "no" ); fprintf( pAbc->Err, "\t-d : toggle dumping statistics into a file [default = %s]\n", fDumpStats? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the help massage\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandTopo( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Ntk_t * pNtkRes; 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_NtkIsLogic(pNtk) ) { Abc_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } // modify the current network pNtkRes = Abc_NtkDupDfs( 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: fprintf( pAbc->Err, "usage: topo [-vh]\n" ); fprintf( pAbc->Err, "\t rearranges nodes to be in a topological order\n" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandUnBuffer( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc); int c, fRemInv = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ivh" ) ) != EOF ) { switch ( c ) { case 'i': fRemInv ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { fprintf( pAbc->Err, "The current network is not a logic network.\n" ); return 1; } if ( fRemInv ) pNtkRes = Abc_SclUnBufferPhase( pNtk, fVerbose ); else pNtkRes = Abc_SclUnBufferPerform( pNtk, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "The command has failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: fprintf( pAbc->Err, "usage: unbuffer [-ivh]\n" ); fprintf( pAbc->Err, "\t collapses buffer/inverter trees\n" ); fprintf( pAbc->Err, "\t-i : toggle removing interters [default = %s]\n", fRemInv? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandBuffer( Abc_Frame_t * pAbc, int argc, char ** argv ) { SC_BusPars Pars, * pPars = &Pars; Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc); int c; memset( pPars, 0, sizeof(SC_BusPars) ); pPars->GainRatio = 300; pPars->Slew = pAbc->pLibScl ? Abc_SclComputeAverageSlew((SC_Lib *)pAbc->pLibScl) : 100; pPars->nDegree = 10; pPars->fSizeOnly = 0; pPars->fAddBufs = 1; pPars->fBufPis = 0; pPars->fUseWireLoads = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "GSNsbpcvwh" ) ) != EOF ) { switch ( c ) { case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer.\n" ); goto usage; } pPars->GainRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->GainRatio < 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; } pPars->Slew = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->Slew < 0 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } pPars->nDegree = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nDegree < 0 ) goto usage; break; case 's': pPars->fSizeOnly ^= 1; break; case 'b': pPars->fAddBufs ^= 1; break; case 'p': pPars->fBufPis ^= 1; break; case 'c': pPars->fUseWireLoads ^= 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->fSizeOnly && !pPars->fAddBufs && pNtk->vPhases == NULL ) { Abc_Print( -1, "Fanin phase information is not avaiable.\n" ); return 1; } if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) ) { Abc_Print( -1, "Library delay info is not available.\n" ); return 1; } // modify the current network pNtkRes = Abc_SclBufferingPerform( pNtk, (SC_Lib *)pAbc->pLibScl, pPars ); if ( pNtkRes == NULL ) { Abc_Print( -1, "The command has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: fprintf( pAbc->Err, "usage: buffer [-GSN num] [-sbpcvwh]\n" ); fprintf( pAbc->Err, "\t performs buffering and sizing and mapped network\n" ); fprintf( pAbc->Err, "\t-G : target gain percentage [default = %d]\n", pPars->GainRatio ); fprintf( pAbc->Err, "\t-S : target slew in pisoseconds [default = %d]\n", pPars->Slew ); fprintf( pAbc->Err, "\t-N : the maximum fanout count [default = %d]\n", pPars->nDegree ); fprintf( pAbc->Err, "\t-s : toggle performing only sizing [default = %s]\n", pPars->fSizeOnly? "yes": "no" ); fprintf( pAbc->Err, "\t-b : toggle using buffers instead of inverters [default = %s]\n", pPars->fAddBufs? "yes": "no" ); fprintf( pAbc->Err, "\t-p : toggle buffering primary inputs [default = %s]\n", pPars->fBufPis? "yes": "no" ); fprintf( pAbc->Err, "\t-c : toggle using wire-loads if specified [default = %s]\n", pPars->fUseWireLoads? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-w : toggle printing more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandBufferOld( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Ntk_t * pNtkRes; int FanMin, FanMax, FanMaxR, fAddInvs, fUseInvs, fBufPis, fSkipDup; int c, fVerbose; int fOldAlgo = 0; FanMin = 6; FanMax = 14; FanMaxR = 0; fAddInvs = 0; fUseInvs = 0; fBufPis = 0; fSkipDup = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NMRaixpdvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } FanMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( FanMin < 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; } FanMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( FanMax < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); goto usage; } FanMaxR = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( FanMaxR < 0 ) goto usage; break; case 'a': fOldAlgo ^= 1; break; case 'i': fAddInvs ^= 1; break; case 'x': fUseInvs ^= 1; break; case 'p': fBufPis ^= 1; break; case 'd': fSkipDup ^= 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; } if ( fAddInvs && pNtk->vPhases == NULL ) { Abc_Print( -1, "Fanin phase information is not avaiable.\n" ); return 1; } if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) ) { Abc_Print( -1, "Library delay info is not available.\n" ); return 1; } // modify the current network if ( fAddInvs ) pNtkRes = Abc_SclBufferPhase( pNtk, fVerbose ); else if ( fOldAlgo ) pNtkRes = Abc_SclPerformBuffering( pNtk, FanMaxR, FanMax, fUseInvs, fVerbose ); else pNtkRes = Abc_SclBufPerform( pNtk, FanMin, FanMax, fBufPis, fSkipDup, 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: fprintf( pAbc->Err, "usage: _buffer [-NMR num] [-aixpdvh]\n" ); fprintf( pAbc->Err, "\t performs buffering of the mapped network\n" ); fprintf( pAbc->Err, "\t-N : the min fanout considered by the algorithm [default = %d]\n", FanMin ); fprintf( pAbc->Err, "\t-M : the max allowed fanout count of node/buffer [default = %d]\n", FanMax ); fprintf( pAbc->Err, "\t-R : the max allowed fanout count of root node [default = %d]\n", FanMaxR ); fprintf( pAbc->Err, "\t-a : toggle using old algorithm [default = %s]\n", fOldAlgo? "yes": "no" ); fprintf( pAbc->Err, "\t-i : toggle adding interters instead of buffering [default = %s]\n", fAddInvs? "yes": "no" ); fprintf( pAbc->Err, "\t-x : toggle using interters instead of buffers [default = %s]\n", fUseInvs? "yes": "no" ); fprintf( pAbc->Err, "\t-p : toggle buffering primary inputs [default = %s]\n", fBufPis? "yes": "no" ); fprintf( pAbc->Err, "\t-d : toggle disabling gate duplication [default = %s]\n", fSkipDup? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandMinsize( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); 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 ( Abc_FrameReadNtk(pAbc) == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) { fprintf( pAbc->Err, "The current network is not mapped.\n" ); return 1; } if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) { fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); return 1; } if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); return 1; } Abc_SclMinsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, 0, fVerbose ); return 0; usage: fprintf( pAbc->Err, "usage: minsize [-vh]\n" ); fprintf( pAbc->Err, "\t downsizes all gates to their minimum size\n" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandMaxsize( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); 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 ( Abc_FrameReadNtk(pAbc) == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) { fprintf( pAbc->Err, "The current network is not mapped.\n" ); return 1; } if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) { fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); return 1; } if ( pAbc->pLibScl == NULL ) { fprintf( pAbc->Err, "There is no Liberty library available.\n" ); return 1; } Abc_SclMinsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, 1, fVerbose ); return 0; usage: fprintf( pAbc->Err, "usage: maxsize [-vh]\n" ); fprintf( pAbc->Err, "\t upsizes all gates to their maximum size\n" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandUpsize( Abc_Frame_t * pAbc, int argc, char **argv ) { SC_SizePars Pars, * pPars = &Pars; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; memset( pPars, 0, sizeof(SC_SizePars) ); pPars->nIters = 1000; pPars->nIterNoChange = 50; pPars->Window = 1; pPars->Ratio = 10; pPars->Notches = 1000; pPars->DelayUser = 0; pPars->DelayGap = 0; pPars->TimeOut = 0; pPars->BuffTreeEst = 0; pPars->BypassFreq = 0; pPars->fUseDept = 1; pPars->fUseWireLoads = 0; pPars->fDumpStats = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IJWRNDGTXBcsdvwh" ) ) != 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; } pPars->nIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIters < 0 ) goto usage; break; case 'J': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-J\" should be followed by a positive integer.\n" ); goto usage; } pPars->nIterNoChange = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIterNoChange < 0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by a positive integer.\n" ); goto usage; } pPars->Window = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->Window < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); goto usage; } pPars->Ratio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->Ratio < 0 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } pPars->Notches = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->Notches < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); goto usage; } pPars->DelayUser = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayUser < 0 ) goto usage; break; case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer.\n" ); goto usage; } pPars->DelayGap = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); goto usage; } pPars->TimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOut < 0 ) goto usage; break; case 'X': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" ); goto usage; } pPars->BuffTreeEst = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->BuffTreeEst < 0 ) goto usage; break; case 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by a positive integer.\n" ); goto usage; } pPars->BypassFreq = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->BypassFreq < 0 ) goto usage; break; case 'c': pPars->fUseWireLoads ^= 1; break; case 's': pPars->fUseDept ^= 1; break; case 'd': pPars->fDumpStats ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( Abc_FrameReadNtk(pAbc) == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) { fprintf( pAbc->Err, "The current network is not mapped.\n" ); return 1; } if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) { fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); return 1; } if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) ) { Abc_Print( -1, "Library delay info is not available.\n" ); return 1; } Abc_SclUpsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars ); return 0; usage: fprintf( pAbc->Err, "usage: upsize [-IJWRNDGTXB num] [-csdvwh]\n" ); fprintf( pAbc->Err, "\t selectively increases gate sizes on the critical path\n" ); fprintf( pAbc->Err, "\t-I : the number of upsizing iterations to perform [default = %d]\n", pPars->nIters ); fprintf( pAbc->Err, "\t-J : the number of iterations without improvement to stop [default = %d]\n", pPars->nIterNoChange ); fprintf( pAbc->Err, "\t-W : delay window (in percent) of near-critical COs [default = %d]\n", pPars->Window ); fprintf( pAbc->Err, "\t-R : ratio of critical nodes (in percent) to update [default = %d]\n", pPars->Ratio ); fprintf( pAbc->Err, "\t-N : limit on discrete upsizing steps at a node [default = %d]\n", pPars->Notches ); fprintf( pAbc->Err, "\t-D : delay target set by the user, in picoseconds [default = %d]\n", pPars->DelayUser ); fprintf( pAbc->Err, "\t-G : delay gap during updating, in picoseconds [default = %d]\n", pPars->DelayGap ); fprintf( pAbc->Err, "\t-T : approximate timeout in seconds [default = %d]\n", pPars->TimeOut ); fprintf( pAbc->Err, "\t-X : ratio for buffer tree estimation [default = %d]\n", pPars->BuffTreeEst ); fprintf( pAbc->Err, "\t-B : frequency of bypass transforms [default = %d]\n", pPars->BypassFreq ); fprintf( pAbc->Err, "\t-c : toggle using wire-loads if specified [default = %s]\n", pPars->fUseWireLoads? "yes": "no" ); fprintf( pAbc->Err, "\t-s : toggle using slack based on departure times [default = %s]\n", pPars->fUseDept? "yes": "no" ); fprintf( pAbc->Err, "\t-d : toggle dumping statistics into a file [default = %s]\n", pPars->fDumpStats? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-w : toggle printing more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandDnsize( Abc_Frame_t * pAbc, int argc, char **argv ) { SC_SizePars Pars, * pPars = &Pars; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; memset( pPars, 0, sizeof(SC_SizePars) ); pPars->nIters = 5; pPars->nIterNoChange = 50; pPars->Notches = 1000; pPars->DelayUser = 0; pPars->DelayGap = 1000; pPars->TimeOut = 0; pPars->BuffTreeEst = 0; pPars->fUseDept = 1; pPars->fUseWireLoads = 0; pPars->fDumpStats = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IJNDGTXcsdvwh" ) ) != 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; } pPars->nIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIters < 0 ) goto usage; break; case 'J': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-J\" should be followed by a positive integer.\n" ); goto usage; } pPars->nIterNoChange = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIterNoChange < 0 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } pPars->Notches = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->Notches < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); goto usage; } pPars->DelayUser = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelayUser < 0 ) goto usage; break; case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by a positive integer.\n" ); goto usage; } pPars->DelayGap = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); goto usage; } pPars->TimeOut = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->TimeOut < 0 ) goto usage; break; case 'X': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" ); goto usage; } pPars->BuffTreeEst = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->BuffTreeEst < 0 ) goto usage; break; case 'c': pPars->fUseWireLoads ^= 1; break; case 's': pPars->fUseDept ^= 1; break; case 'd': pPars->fDumpStats ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( Abc_FrameReadNtk(pAbc) == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) { fprintf( pAbc->Err, "The current network is not mapped.\n" ); return 1; } if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) { fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); return 1; } if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) ) { Abc_Print( -1, "Library delay info is not available.\n" ); return 1; } Abc_SclDnsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars ); return 0; usage: fprintf( pAbc->Err, "usage: dnsize [-IJNDGTX num] [-csdvwh]\n" ); fprintf( pAbc->Err, "\t selectively decreases gate sizes while maintaining delay\n" ); fprintf( pAbc->Err, "\t-I : the number of upsizing iterations to perform [default = %d]\n", pPars->nIters ); fprintf( pAbc->Err, "\t-J : the number of iterations without improvement to stop [default = %d]\n", pPars->nIterNoChange ); fprintf( pAbc->Err, "\t-N : limit on discrete upsizing steps at a node [default = %d]\n", pPars->Notches ); fprintf( pAbc->Err, "\t-D : delay target set by the user, in picoseconds [default = %d]\n", pPars->DelayUser ); fprintf( pAbc->Err, "\t-G : delay gap during updating, in picoseconds [default = %d]\n", pPars->DelayGap ); fprintf( pAbc->Err, "\t-T : approximate timeout in seconds [default = %d]\n", pPars->TimeOut ); fprintf( pAbc->Err, "\t-X : ratio for buffer tree estimation [default = %d]\n", pPars->BuffTreeEst ); fprintf( pAbc->Err, "\t-c : toggle using wire-loads if specified [default = %s]\n", pPars->fUseWireLoads? "yes": "no" ); fprintf( pAbc->Err, "\t-s : toggle using slack based on departure times [default = %s]\n", pPars->fUseDept? "yes": "no" ); fprintf( pAbc->Err, "\t-d : toggle dumping statistics into a file [default = %s]\n", pPars->fDumpStats? "yes": "no" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-w : toggle printing more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandPrintBuf( Abc_Frame_t * pAbc, int argc, char **argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); 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 ( Abc_FrameReadNtk(pAbc) == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) { fprintf( pAbc->Err, "The current network is not mapped.\n" ); return 1; } if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) { fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); return 1; } if ( !pAbc->pLibScl || !Abc_SclHasDelayInfo(pAbc->pLibScl) ) { Abc_Print( -1, "Library delay info is not available.\n" ); return 1; } Abc_SclPrintBuffers( (SC_Lib *)pAbc->pLibScl, pNtk, fVerbose ); return 0; usage: fprintf( pAbc->Err, "usage: print_buf [-vh]\n" ); fprintf( pAbc->Err, "\t prints buffers trees of the current design\n" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandReadConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Nam_t * Abc_NtkNameMan( Abc_Ntk_t * p, int fOuts ); extern void Abc_SclReadTimingConstr( Abc_Frame_t * pAbc, char * pFileName, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); FILE * pFile; 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 ) goto usage; // get the input file name pFileName = argv[globalUtilOptind]; if ( (pFile = fopen( pFileName, "rb" )) == NULL ) { fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName ); return 1; } fclose( pFile ); // Abc_SclReadTimingConstr( pAbc, pFileName, fVerbose ); if ( pNtk == NULL ) { fprintf( pAbc->Err, "There is no current network.\n" ); return 1; } // input constraint manager if ( pNtk ) { Scl_Con_t * pCon = Scl_ConRead( pFileName, Abc_NtkNameMan(pNtk, 0), Abc_NtkNameMan(pNtk, 1) ); if ( pCon ) Scl_ConUpdateMan( pAbc, pCon ); } return 0; usage: fprintf( pAbc->Err, "usage: read_constr [-vh] \n" ); fprintf( pAbc->Err, "\t read file with timing constraints for standard-cell designs\n" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandWriteConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Scl_Con_t * pCon = Scl_ConGetMan( pAbc ); 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 ( pCon == NULL ) { Abc_Print( 1, "Scl_CommandWriteConstr(): There is no constraint manager.\n" ); return 0; } if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; else if ( argc == globalUtilOptind && pCon ) pFileName = Extra_FileNameGenericAppend( pCon->pFileName, "_out.constr" ); else { printf( "Output file name should be given on the command line.\n" ); return 0; } // perform writing if ( !strcmp( Extra_FileNameExtension(pFileName), "constr" ) ) Scl_ConWrite( pCon, pFileName ); else { printf( "Scl_CommandWriteConstr(): Unrecognized output file extension.\n" ); return 0; } return 0; usage: fprintf( pAbc->Err, "usage: write_constr [-vh] \n" ); fprintf( pAbc->Err, "\t writes current timing constraints into a file\n" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandPrintConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Scl_Con_t * pCon = Scl_ConGetMan( pAbc ); 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; } } //printf( "Primary input driving cell = %s\n", Abc_FrameReadDrivingCell() ); //printf( "Primary output maximum load = %f\n", Abc_FrameReadMaxLoad() ); if ( pCon ) Scl_ConWrite( pCon, NULL ); return 0; usage: fprintf( pAbc->Err, "usage: print_constr [-vh] \n" ); fprintf( pAbc->Err, "\t prints current timing constraints\n" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_CommandResetConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) { 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; } } Abc_FrameSetDrivingCell( NULL ); Abc_FrameSetMaxLoad( 0 ); Scl_ConUpdateMan( pAbc, NULL ); return 0; usage: fprintf( pAbc->Err, "usage: reset_constr [-vh] \n" ); fprintf( pAbc->Err, "\t removes current timing constraints\n" ); fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); fprintf( pAbc->Err, "\t : the name of a file to read\n" ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/scl.h000066400000000000000000000042411300674244400223250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [scl.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [External declarations.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: scl.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__scl__scl_h #define ABC__map__scl__scl_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclBufSize.c000066400000000000000000000500501300674244400236070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclBufSize.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Buffering and sizing combined.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclBufSize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclSize.h" #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Bus_Man_t_ Bus_Man_t; struct Bus_Man_t_ { // user data SC_BusPars * pPars; // parameters Abc_Ntk_t * pNtk; // user's network SC_Cell * pPiDrive; // PI driver // library SC_Lib * pLib; // cell library SC_Cell * pInv; // base interter (largest/average/???) SC_WireLoad * pWLoadUsed; // name of the used WireLoad model Vec_Flt_t * vWireCaps; // estimated wire loads // internal Vec_Flt_t * vCins; // input cap for fanouts Vec_Flt_t * vETimes; // fanout edge departures Vec_Flt_t * vLoads; // loads for all nodes Vec_Flt_t * vDepts; // departure times Vec_Ptr_t * vFanouts; // fanout array }; static inline Bus_Man_t * Bus_SclObjMan( Abc_Obj_t * p ) { return (Bus_Man_t *)p->pNtk->pBSMan; } static inline float Bus_SclObjCin( Abc_Obj_t * p ) { return Vec_FltEntry( Bus_SclObjMan(p)->vCins, Abc_ObjId(p) ); } static inline void Bus_SclObjSetCin( Abc_Obj_t * p, float cap ) { Vec_FltWriteEntry( Bus_SclObjMan(p)->vCins, Abc_ObjId(p), cap ); } static inline float Bus_SclObjETime( Abc_Obj_t * p ) { return Vec_FltEntry( Bus_SclObjMan(p)->vETimes, Abc_ObjId(p) ); } static inline void Bus_SclObjSetETime( Abc_Obj_t * p, float time ) { Vec_FltWriteEntry( Bus_SclObjMan(p)->vETimes, Abc_ObjId(p), time ); } static inline float Bus_SclObjLoad( Abc_Obj_t * p ) { return Vec_FltEntry( Bus_SclObjMan(p)->vLoads, Abc_ObjId(p) ); } static inline void Bus_SclObjSetLoad( Abc_Obj_t * p, float cap ) { Vec_FltWriteEntry( Bus_SclObjMan(p)->vLoads, Abc_ObjId(p), cap ); } static inline float Bus_SclObjDept( Abc_Obj_t * p ) { return Vec_FltEntry( Bus_SclObjMan(p)->vDepts, Abc_ObjId(p) ); } static inline void Bus_SclObjUpdateDept( Abc_Obj_t * p, float time ) { float *q = Vec_FltEntryP( Bus_SclObjMan(p)->vDepts, Abc_ObjId(p) ); if (*q < time) *q = time; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bus_Man_t * Bus_ManStart( Abc_Ntk_t * pNtk, SC_Lib * pLib, SC_BusPars * pPars ) { Bus_Man_t * p; p = ABC_CALLOC( Bus_Man_t, 1 ); p->pPars = pPars; p->pNtk = pNtk; p->pLib = pLib; p->pInv = Abc_SclFindInvertor(pLib, pPars->fAddBufs)->pRepr->pPrev;//->pAve; if ( pPars->fUseWireLoads ) { if ( pNtk->pWLoadUsed == NULL ) { p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(pNtk) ); if ( p->pWLoadUsed ) pNtk->pWLoadUsed = Abc_UtilStrsav( p->pWLoadUsed->pName ); } else p->pWLoadUsed = Abc_SclFetchWireLoadModel( pLib, pNtk->pWLoadUsed ); } if ( p->pWLoadUsed ) p->vWireCaps = Abc_SclFindWireCaps( p->pWLoadUsed, Abc_NtkGetFanoutMax(pNtk) ); p->vFanouts = Vec_PtrAlloc( 100 ); p->vCins = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 ); p->vETimes = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 ); p->vLoads = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 ); p->vDepts = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 ); Vec_FltFill( p->vCins, Abc_NtkObjNumMax(pNtk), 0 ); Vec_FltFill( p->vETimes, Abc_NtkObjNumMax(pNtk), 0 ); Vec_FltFill( p->vLoads, Abc_NtkObjNumMax(pNtk), 0 ); Vec_FltFill( p->vDepts, Abc_NtkObjNumMax(pNtk), 0 ); pNtk->pBSMan = p; return p; } void Bus_ManStop( Bus_Man_t * p ) { Vec_PtrFreeP( &p->vFanouts ); Vec_FltFreeP( &p->vWireCaps ); Vec_FltFreeP( &p->vCins ); Vec_FltFreeP( &p->vETimes ); Vec_FltFreeP( &p->vLoads ); Vec_FltFreeP( &p->vDepts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bus_ManReadInOutLoads( Bus_Man_t * p ) { if ( Abc_FrameReadMaxLoad() ) { Abc_Obj_t * pObj; int i; float MaxLoad = Abc_FrameReadMaxLoad(); Abc_NtkForEachCo( p->pNtk, pObj, i ) Bus_SclObjSetCin( pObj, MaxLoad ); // printf( "Default output load is specified (%f ff).\n", MaxLoad ); } if ( Abc_FrameReadDrivingCell() ) { int iCell = Abc_SclCellFind( p->pLib, Abc_FrameReadDrivingCell() ); if ( iCell == -1 ) printf( "Cannot find the default PI driving cell (%s) in the library.\n", Abc_FrameReadDrivingCell() ); else { // printf( "Default PI driving cell is specified (%s).\n", Abc_FrameReadDrivingCell() ); p->pPiDrive = SC_LibCell( p->pLib, iCell ); assert( p->pPiDrive != NULL ); assert( p->pPiDrive->n_inputs == 1 ); // printf( "Default input driving cell is specified (%s).\n", p->pPiDrive->pName ); } } } /**Function************************************************************* Synopsis [Compute load and departure times of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Abc_NtkComputeEdgeDept( Abc_Obj_t * pFanout, int iFanin, float Slew ) { float Load = Bus_SclObjLoad( pFanout ); float Dept = Bus_SclObjDept( pFanout ); float Edge = Scl_LibPinArrivalEstimate( Abc_SclObjCell(pFanout), iFanin, Slew, Load ); assert( Edge > 0 ); return Dept + Edge; } float Abc_NtkComputeNodeDeparture( Abc_Obj_t * pObj, float Slew ) { Abc_Obj_t * pFanout; int i; assert( Bus_SclObjDept(pObj) == 0 ); Abc_ObjForEachFanout( pObj, pFanout, i ) { if ( Abc_ObjIsBarBuf(pFanout) ) Bus_SclObjUpdateDept( pObj, Bus_SclObjDept(pFanout) ); else if ( !Abc_ObjIsCo(pFanout) ) // add required times here Bus_SclObjUpdateDept( pObj, Abc_NtkComputeEdgeDept(pFanout, Abc_NodeFindFanin(pFanout, pObj), Slew) ); } return Bus_SclObjDept( pObj ); } void Abc_NtkComputeFanoutInfo( Abc_Obj_t * pObj, float Slew ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) { if ( Abc_ObjIsBarBuf(pFanout) ) { Bus_SclObjSetETime( pFanout, Bus_SclObjDept(pFanout) ); Bus_SclObjSetCin( pFanout, Bus_SclObjLoad(pFanout) ); } else if ( !Abc_ObjIsCo(pFanout) ) { int iFanin = Abc_NodeFindFanin(pFanout, pObj); Bus_SclObjSetETime( pFanout, Abc_NtkComputeEdgeDept(pFanout, iFanin, Slew) ); Bus_SclObjSetCin( pFanout, SC_CellPinCap( Abc_SclObjCell(pFanout), iFanin ) ); } } } float Abc_NtkComputeNodeLoad( Bus_Man_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Load; int i; assert( Bus_SclObjLoad(pObj) == 0 ); Load = Abc_SclFindWireLoad( p->vWireCaps, Abc_ObjFanoutNum(pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) Load += Bus_SclObjCin( pFanout ); Bus_SclObjSetLoad( pObj, Load ); return Load; } float Abc_NtkComputeFanoutLoad( Bus_Man_t * p, Vec_Ptr_t * vFanouts ) { Abc_Obj_t * pFanout; float Load; int i; Load = Abc_SclFindWireLoad( p->vWireCaps, Vec_PtrSize(vFanouts) ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i ) Load += Bus_SclObjCin( pFanout ); return Load; } void Abc_NtkPrintFanoutProfile( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; printf( "Obj %6d fanouts (%d):\n", Abc_ObjId(pObj), Abc_ObjFanoutNum(pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) { printf( "%3d : time = %7.2f ps load = %7.2f ff ", i, Bus_SclObjETime(pFanout), Bus_SclObjCin(pFanout) ); printf( "%s\n", Abc_ObjFaninPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) ) ? "*" : " " ); } printf( "\n" ); } void Abc_NtkPrintFanoutProfileVec( Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts ) { Abc_Obj_t * pFanout; int i; printf( "Fanout profile (%d):\n", Vec_PtrSize(vFanouts) ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i ) { printf( "%3d : time = %7.2f ps load = %7.2f ff ", i, Bus_SclObjETime(pFanout), Bus_SclObjCin(pFanout) ); if ( pObj->pNtk->vPhases ) printf( "%s", (pObj && Abc_ObjFanoutNum(pObj) == Vec_PtrSize(vFanouts) && Abc_ObjFaninPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) )) ? "*" : " " ); printf( "\n" ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Compare two fanouts by their departure times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bus_SclCompareFanouts( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { float Espilon = 0;//10; // 10 ps if ( Bus_SclObjETime(*pp1) < Bus_SclObjETime(*pp2) - Espilon ) return -1; if ( Bus_SclObjETime(*pp1) > Bus_SclObjETime(*pp2) + Espilon ) return 1; if ( Bus_SclObjCin(*pp1) > Bus_SclObjCin(*pp2) ) return -1; if ( Bus_SclObjCin(*pp1) < Bus_SclObjCin(*pp2) ) return 1; return -1; } void Bus_SclInsertFanout( Vec_Ptr_t * vFanouts, Abc_Obj_t * pObj ) { Abc_Obj_t * pCur; int i, k; // compact array for ( i = k = 0; i < Vec_PtrSize(vFanouts); i++ ) if ( Vec_PtrEntry(vFanouts, i) != NULL ) Vec_PtrWriteEntry( vFanouts, k++, Vec_PtrEntry(vFanouts, i) ); Vec_PtrShrink( vFanouts, k ); // insert new entry Vec_PtrPush( vFanouts, pObj ); for ( i = Vec_PtrSize(vFanouts) - 1; i > 0; i-- ) { pCur = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i-1); pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i); if ( Bus_SclCompareFanouts( &pCur, &pObj ) == -1 ) break; ABC_SWAP( void *, Vec_PtrArray(vFanouts)[i-1], Vec_PtrArray(vFanouts)[i] ); } } void Bus_SclCheckSortedFanout( Vec_Ptr_t * vFanouts ) { Abc_Obj_t * pObj, * pNext; int i; for ( i = 0; i < Vec_PtrSize(vFanouts) - 1; i++ ) { pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i); pNext = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i+1); if ( Bus_SclCompareFanouts( &pObj, &pNext ) != -1 ) { printf( "Fanouts %d and %d are out of order.\n", i, i+1 ); Abc_NtkPrintFanoutProfileVec( NULL, vFanouts ); return; } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclOneNodePrint( Bus_Man_t * p, Abc_Obj_t * pObj ) { SC_Cell * pCell = Abc_SclObjCell(pObj); printf( "%s%7d : ", (Abc_ObjFaninNum(pObj) == 0) ? " Inv" : "Node", Abc_ObjId(pObj) ); printf( "%d/%2d ", Abc_ObjFaninNum(pObj) ? Abc_ObjFaninNum(pObj) : 1, Abc_ObjFanoutNum(pObj) ); printf( "%12s ", pCell->pName ); printf( "(%2d/%2d) ", pCell->Order, pCell->nGates ); printf( "gain =%5d ", (int)(100.0 * Bus_SclObjLoad(pObj) / SC_CellPinCapAve(pCell)) ); printf( "dept =%7.0f ps ", Bus_SclObjDept(pObj) ); printf( "\n" ); } Abc_Obj_t * Abc_SclAddOneInv( Bus_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts, float Gain ) { SC_Cell * pCellNew; Abc_Obj_t * pFanout, * pInv; float Target = SC_CellPinCap(p->pInv, 0) * Gain; float LoadWirePrev, LoadWireThis, LoadNew, Load = 0; int Limit = Abc_MinInt( p->pPars->nDegree, Vec_PtrSize(vFanouts) ); int i, iStop; Bus_SclCheckSortedFanout( vFanouts ); Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, iStop, Limit ) { LoadWirePrev = Abc_SclFindWireLoad( p->vWireCaps, iStop ); LoadWireThis = Abc_SclFindWireLoad( p->vWireCaps, iStop+1 ); Load += Bus_SclObjCin( pFanout ) - LoadWirePrev + LoadWireThis; if ( Load > Target ) { iStop++; break; } } // create inverter if ( p->pPars->fAddBufs ) pInv = Abc_NtkCreateNodeBuf( p->pNtk, NULL ); else pInv = Abc_NtkCreateNodeInv( p->pNtk, NULL ); assert( (int)Abc_ObjId(pInv) == Vec_FltSize(p->vCins) ); Vec_FltPush( p->vCins, 0 ); Vec_FltPush( p->vETimes, 0 ); Vec_FltPush( p->vLoads, 0 ); Vec_FltPush( p->vDepts, 0 ); Limit = Abc_MinInt( Abc_MaxInt(iStop, 2), Vec_PtrSize(vFanouts) ); Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, i, Limit ) { Vec_PtrWriteEntry( vFanouts, i, NULL ); if ( Abc_ObjFaninNum(pFanout) == 0 ) Abc_ObjAddFanin( pFanout, pInv ); else Abc_ObjPatchFanin( pFanout, pObj, pInv ); } // set the gate pCellNew = Abc_SclFindSmallestGate( p->pInv, Load / Gain ); Vec_IntSetEntry( p->pNtk->vGates, Abc_ObjId(pInv), pCellNew->Id ); // set departure and load Abc_NtkComputeNodeDeparture( pInv, p->pPars->Slew ); LoadNew = Abc_NtkComputeNodeLoad( p, pInv ); assert( LoadNew - Load < 1 && Load - LoadNew < 1 ); // set fanout info for the inverter Bus_SclObjSetCin( pInv, SC_CellPinCap(pCellNew, 0) ); Bus_SclObjSetETime( pInv, Abc_NtkComputeEdgeDept(pInv, 0, p->pPars->Slew) ); // update phases if ( p->pNtk->vPhases && Abc_SclIsInv(pInv) ) Abc_NodeInvUpdateFanPolarity( pInv ); return pInv; } void Abc_SclBufSize( Bus_Man_t * p, float Gain ) { SC_Cell * pCell, * pCellNew; Abc_Obj_t * pObj, * pFanout; abctime clk = Abc_Clock(); int i, k, nObjsOld = Abc_NtkObjNumMax(p->pNtk); float GainGate, GainInv, Load, LoadNew, Cin, DeptMax = 0; GainGate = p->pPars->fAddBufs ? pow( Gain, 2.0 ) : Gain; GainInv = p->pPars->fAddBufs ? pow( Gain, 2.0 ) : Gain; Abc_NtkForEachObjReverse( p->pNtk, pObj, i ) { if ( !((Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) > 0) || (Abc_ObjIsCi(pObj) && p->pPiDrive)) ) continue; if ( 2 * nObjsOld < Abc_NtkObjNumMax(p->pNtk) ) { printf( "Buffering could not be completed because the gain value (%d) is too low.\n", p->pPars->GainRatio ); break; } // compute load Abc_NtkComputeFanoutInfo( pObj, p->pPars->Slew ); Load = Abc_NtkComputeNodeLoad( p, pObj ); // consider the gate if ( Abc_ObjIsCi(pObj) || Abc_ObjIsBarBuf(pObj) ) { pCell = p->pPiDrive; // if PI driver is not given, assume Cin to be equal to Load // this way, buffering of the PIs is performed Cin = pCell ? SC_CellPinCapAve(pCell) : Load; } else { pCell = Abc_SclObjCell( pObj ); Cin = SC_CellPinCapAve( pCell->pAve ); // Cin = SC_CellPinCapAve( pCell->pRepr->pNext ); } // consider buffering this gate if ( !p->pPars->fSizeOnly && (Abc_ObjFanoutNum(pObj) > p->pPars->nDegree || Load > GainGate * Cin) ) { // add one or more inverters // Abc_NtkPrintFanoutProfile( pObj ); Abc_NodeCollectFanouts( pObj, p->vFanouts ); Vec_PtrSort( p->vFanouts, (int(*)(void))Bus_SclCompareFanouts ); do { Abc_Obj_t * pInv; if ( p->pPars->fVeryVerbose )//|| Vec_PtrSize(p->vFanouts) == Abc_ObjFanoutNum(pObj) ) Abc_NtkPrintFanoutProfileVec( pObj, p->vFanouts ); pInv = Abc_SclAddOneInv( p, pObj, p->vFanouts, GainInv ); if ( p->pPars->fVeryVerbose ) Abc_SclOneNodePrint( p, pInv ); Bus_SclInsertFanout( p->vFanouts, pInv ); Load = Abc_NtkComputeFanoutLoad( p, p->vFanouts ); } while ( Vec_PtrSize(p->vFanouts) > p->pPars->nDegree || (Vec_PtrSize(p->vFanouts) > 1 && Load > GainGate * Cin) ); // update node fanouts Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanouts, pFanout, k ) if ( Abc_ObjFaninNum(pFanout) == 0 ) Abc_ObjAddFanin( pFanout, pObj ); Bus_SclObjSetLoad( pObj, 0 ); LoadNew = Abc_NtkComputeNodeLoad( p, pObj ); assert( LoadNew - Load < 1 && Load - LoadNew < 1 ); } if ( Abc_ObjIsCi(pObj) ) continue; Abc_NtkComputeNodeDeparture( pObj, p->pPars->Slew ); if ( Abc_ObjIsBarBuf(pObj) ) continue; // create cell pCellNew = Abc_SclFindSmallestGate( pCell, Load / GainGate ); Abc_SclObjSetCell( pObj, pCellNew ); if ( p->pPars->fVeryVerbose ) Abc_SclOneNodePrint( p, pObj ); assert( p->pPars->fSizeOnly || Abc_ObjFanoutNum(pObj) <= p->pPars->nDegree ); } // compute departure time of the PI if ( i < 0 ) // finished buffering Abc_NtkForEachCi( p->pNtk, pObj, i ) { float DeptCur = Abc_NtkComputeNodeDeparture(pObj, p->pPars->Slew); if ( p->pPiDrive ) { float Load = Bus_SclObjLoad( pObj ); SC_Pair ArrOut, SlewOut, LoadIn = { Load, Load }; Scl_LibHandleInputDriver( p->pPiDrive, &LoadIn, &ArrOut, &SlewOut ); DeptCur += 0.5 * ArrOut.fall + 0.5 * ArrOut.rise; } DeptMax = Abc_MaxFloat( DeptMax, DeptCur ); } if ( p->pPars->fVerbose ) { printf( "WireLoads = %d Degree = %d Target slew =%4d ps Gain2 =%5d Buf = %6d Delay =%7.0f ps ", p->pPars->fUseWireLoads, p->pPars->nDegree, p->pPars->Slew, p->pPars->GainRatio, Abc_NtkObjNumMax(p->pNtk) - nObjsOld, DeptMax ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } } Abc_Ntk_t * Abc_SclBufferingPerform( Abc_Ntk_t * pNtk, SC_Lib * pLib, SC_BusPars * pPars ) { Abc_Ntk_t * pNtkNew; Bus_Man_t * p; if ( !Abc_SclCheckNtk( pNtk, 0 ) ) return NULL; Abc_SclReportDupFanins( pNtk ); Abc_SclMioGates2SclGates( pLib, pNtk ); p = Bus_ManStart( pNtk, pLib, pPars ); Bus_ManReadInOutLoads( p ); Abc_SclBufSize( p, 0.01 * pPars->GainRatio ); Bus_ManStop( p ); Abc_SclSclGates2MioGates( pLib, pNtk ); if ( pNtk->vPhases ) Vec_IntFillExtra( pNtk->vPhases, Abc_NtkObjNumMax(pNtk), 0 ); pNtkNew = Abc_NtkDupDfs( pNtk ); return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclBuffer.c000066400000000000000000001112031300674244400234470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclBuffer.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Buffering algorithms.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclBuffer.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclSize.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define BUF_SCALE 1000 typedef struct Buf_Man_t_ Buf_Man_t; struct Buf_Man_t_ { // parameters int nFanMin; // the smallest fanout count to consider int nFanMax; // the largest fanout count allowed off CP int fBufPis; // enables buffing of the combinational inputs // internal deta Abc_Ntk_t * pNtk; // logic network Vec_Int_t * vOffsets; // offsets into edge delays Vec_Int_t * vEdges; // edge delays Vec_Int_t * vArr; // arrival times Vec_Int_t * vDep; // departure times Vec_Flt_t * vCounts; // fanout counts Vec_Que_t * vQue; // queue by fanout count int nObjStart; // the number of starting objects int nObjAlloc; // the number of allocated objects int DelayMax; // maximum delay (percentage of inverter delay) float DelayInv; // inverter delay // sorting fanouts Vec_Int_t * vOrder; // ordering of fanouts Vec_Int_t * vDelays; // fanout delays Vec_Int_t * vNonCrit; // non-critical fanouts Vec_Int_t * vTfCone; // TFI/TFO cone of the node including the node Vec_Ptr_t * vFanouts; // temp storage for fanouts // statistics int nSeparate; int nDuplicate; int nBranch0; int nBranch1; int nBranchCrit; }; static inline int Abc_BufNodeArr( Buf_Man_t * p, Abc_Obj_t * pObj ) { return Vec_IntEntry( p->vArr, Abc_ObjId(pObj) ); } static inline int Abc_BufNodeDep( Buf_Man_t * p, Abc_Obj_t * pObj ) { return Vec_IntEntry( p->vDep, Abc_ObjId(pObj) ); } static inline void Abc_BufSetNodeArr( Buf_Man_t * p, Abc_Obj_t * pObj, int f ) { Vec_IntWriteEntry( p->vArr, Abc_ObjId(pObj), f ); } static inline void Abc_BufSetNodeDep( Buf_Man_t * p, Abc_Obj_t * pObj, int f ) { Vec_IntWriteEntry( p->vDep, Abc_ObjId(pObj), f ); } static inline int Abc_BufEdgeDelay( Buf_Man_t * p, Abc_Obj_t * pObj, int i ) { return Vec_IntEntry( p->vEdges, Vec_IntEntry(p->vOffsets, Abc_ObjId(pObj)) + i ); } static inline void Abc_BufSetEdgeDelay( Buf_Man_t * p, Abc_Obj_t * pObj, int i, int f ) { Vec_IntWriteEntry( p->vEdges, Vec_IntEntry(p->vOffsets, Abc_ObjId(pObj)) + i, f ); } static inline int Abc_BufNodeSlack( Buf_Man_t * p, Abc_Obj_t * pObj ) { return p->DelayMax - Abc_BufNodeArr(p, pObj) - Abc_BufNodeDep(p, pObj); } static inline int Abc_BufEdgeSlack( Buf_Man_t * p, Abc_Obj_t * pObj, Abc_Obj_t * pFan ) { return p->DelayMax - Abc_BufNodeArr(p, pObj) - Abc_BufNodeDep(p, pFan) - Abc_BufEdgeDelay(p, pFan, Abc_NodeFindFanin(pFan, pObj)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Make sure fanins of gates are not duplicated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclReportDupFanins( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFanin, * pFanin2; int i, k, k2; Abc_NtkForEachNode( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjForEachFanin( pObj, pFanin2, k2 ) if ( k != k2 && pFanin == pFanin2 ) printf( "Node %d has dup fanin %d.\n", i, Abc_ObjId(pFanin) ); } /**Function************************************************************* Synopsis [Removes buffers and inverters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_SclObjIsBufInv( Abc_Obj_t * pObj ) { return Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) == 1; } int Abc_SclIsInv( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return Mio_GateReadTruth((Mio_Gate_t *)pObj->pData) == ABC_CONST(0x5555555555555555); } int Abc_SclGetRealFaninLit( Abc_Obj_t * pObj ) { int iLit; if ( !Abc_SclObjIsBufInv(pObj) ) return Abc_Var2Lit( Abc_ObjId(pObj), 0 ); iLit = Abc_SclGetRealFaninLit( Abc_ObjFanin0(pObj) ); return Abc_LitNotCond( iLit, Abc_SclIsInv(pObj) ); } Abc_Ntk_t * Abc_SclUnBufferPerform( Abc_Ntk_t * pNtk, int fVerbose ) { Vec_Int_t * vLits; Abc_Obj_t * pObj, * pFanin, * pFaninNew; int i, k, iLit, nNodesOld = Abc_NtkObjNumMax(pNtk); // assign inverters vLits = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) if ( Abc_SclIsInv(pObj) && !Abc_SclObjIsBufInv(Abc_ObjFanin0(pObj)) ) Vec_IntWriteEntry( vLits, Abc_ObjFaninId0(pObj), Abc_ObjId(pObj) ); // transfer fanins Abc_NtkForEachNodeCo( pNtk, pObj, i ) { if ( i >= nNodesOld ) break; Abc_ObjForEachFanin( pObj, pFanin, k ) { if ( !Abc_SclObjIsBufInv(pFanin) ) continue; iLit = Abc_SclGetRealFaninLit( pFanin ); pFaninNew = Abc_NtkObj( pNtk, Abc_Lit2Var(iLit) ); if ( Abc_LitIsCompl(iLit) ) { if ( Vec_IntEntry( vLits, Abc_Lit2Var(iLit) ) == -1 ) { pFaninNew = Abc_NtkCreateNodeInv( pNtk, pFaninNew ); Vec_IntWriteEntry( vLits, Abc_Lit2Var(iLit), Abc_ObjId(pFaninNew) ); } else pFaninNew = Abc_NtkObj( pNtk, Vec_IntEntry( vLits, Abc_Lit2Var(iLit) ) ); assert( Abc_ObjFaninNum(pFaninNew) == 1 ); } if ( pFanin != pFaninNew ) Abc_ObjPatchFanin( pObj, pFanin, pFaninNew ); } } Vec_IntFree( vLits ); // duplicate network in topo order return Abc_NtkDupDfs( pNtk ); } /**Function************************************************************* Synopsis [Removes buffers and inverters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclCountMaxPhases( Abc_Ntk_t * pNtk ) { Vec_Int_t * vPhLevel; Abc_Obj_t * pObj, * pFanin; int i, k, Max = 0, MaxAll = 0; vPhLevel = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNodeCo( pNtk, pObj, i ) { Max = 0; Abc_ObjForEachFanin( pObj, pFanin, k ) Max = Abc_MaxInt( Max, Vec_IntEntry(vPhLevel, Abc_ObjId(pFanin)) + Abc_ObjFaninPhase(pObj, k) ); Vec_IntWriteEntry( vPhLevel, i, Max ); MaxAll = Abc_MaxInt( MaxAll, Max ); } Vec_IntFree( vPhLevel ); return MaxAll; } Abc_Ntk_t * Abc_SclBufferPhase( Abc_Ntk_t * pNtk, int fVerbose ) { Abc_Ntk_t * pNtkNew; Vec_Int_t * vInvs; Abc_Obj_t * pObj, * pFanin, * pFaninNew; int nNodesOld = Abc_NtkObjNumMax(pNtk); int i, k, Counter = 0, Counter2 = 0, Total = 0; assert( pNtk->vPhases != NULL ); vInvs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNodeCo( pNtk, pObj, i ) { if ( i >= nNodesOld ) break; Abc_ObjForEachFanin( pObj, pFanin, k ) { Total++; if ( !Abc_ObjFaninPhase(pObj, k) ) continue; if ( Vec_IntEntry(vInvs, Abc_ObjId(pFanin)) == 0 || Abc_ObjIsCi(pFanin) ) // allow PIs to have high fanout - to be fixed later { pFaninNew = Abc_NtkCreateNodeInv( pNtk, pFanin ); Vec_IntWriteEntry( vInvs, Abc_ObjId(pFanin), Abc_ObjId(pFaninNew) ); Counter++; } pFaninNew = Abc_NtkObj( pNtk, Vec_IntEntry(vInvs, Abc_ObjId(pFanin)) ); Abc_ObjPatchFanin( pObj, pFanin, pFaninNew ); Counter2++; } } if ( fVerbose ) printf( "Added %d inverters (%.2f %% fanins) (%.2f %% compl fanins).\n", Counter, 100.0 * Counter / Total, 100.0 * Counter2 / Total ); Vec_IntFree( vInvs ); Vec_IntFillExtra( pNtk->vPhases, Abc_NtkObjNumMax(pNtk), 0 ); // duplicate network in topo order vInvs = pNtk->vPhases; pNtk->vPhases = NULL; pNtkNew = Abc_NtkDupDfs( pNtk ); pNtk->vPhases = vInvs; return pNtkNew; } Abc_Ntk_t * Abc_SclUnBufferPhase( Abc_Ntk_t * pNtk, int fVerbose ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin, * pFaninNew; int i, k, iLit, Counter = 0, Total = 0; assert( pNtk->vPhases == NULL ); pNtk->vPhases = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNodeCo( pNtk, pObj, i ) { if ( Abc_SclObjIsBufInv(pObj) ) continue; Abc_ObjForEachFanin( pObj, pFanin, k ) { Total++; iLit = Abc_SclGetRealFaninLit( pFanin ); pFaninNew = Abc_NtkObj( pNtk, Abc_Lit2Var(iLit) ); if ( pFaninNew == pFanin ) continue; // skip fanins which are already fanins of the node if ( Abc_NodeFindFanin( pObj, pFaninNew ) >= 0 ) continue; Abc_ObjPatchFanin( pObj, pFanin, pFaninNew ); if ( Abc_LitIsCompl(iLit) ) Abc_ObjFaninFlipPhase( pObj, k ), Counter++; } } if ( fVerbose ) printf( "Saved %d (%.2f %%) fanin phase bits. ", Counter, 100.0 * Counter / Total ); // duplicate network in topo order pNtkNew = Abc_NtkDupDfs( pNtk ); if ( fVerbose ) printf( "Max depth = %d.\n", Abc_SclCountMaxPhases(pNtkNew) ); Abc_SclReportDupFanins( pNtkNew ); return pNtkNew; } /**Function************************************************************* Synopsis [Make sure the network is in topo order without dangling nodes.] Description [Returns 1 iff the network is fine.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose ) { Abc_Obj_t * pObj, * pFanin; int i, k, fFlag = 1; Abc_NtkIncrementTravId( p ); Abc_NtkForEachCi( p, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); Abc_NtkForEachNode( p, pObj, i ) { Abc_ObjForEachFanin( pObj, pFanin, k ) if ( !Abc_NodeIsTravIdCurrent( pFanin ) ) printf( "obj %d and its fanin %d are not in the topo order\n", Abc_ObjId(pObj), Abc_ObjId(pFanin) ), fFlag = 0; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsBarBuf(pObj) ) continue; if ( Abc_ObjFanoutNum(pObj) == 0 ) printf( "node %d has no fanout\n", Abc_ObjId(pObj) ), fFlag = 0; if ( !fFlag ) break; } if ( fFlag && fVerbose ) printf( "The network is in topo order and no dangling nodes.\n" ); return fFlag; } /**Function************************************************************* Synopsis [Performs buffering of the mapped network (old code).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeInvUpdateFanPolarity( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; assert( Abc_ObjFaninNum(pObj) == 0 || Abc_SclObjIsBufInv(pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) { assert( Abc_ObjFaninNum(pFanout) > 0 ); if ( Abc_SclObjIsBufInv(pFanout) ) Abc_NodeInvUpdateFanPolarity( pFanout ); else Abc_ObjFaninFlipPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) ); } } void Abc_NodeInvUpdateObjFanoutPolarity( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { if ( Abc_SclObjIsBufInv(pFanout) ) Abc_NodeInvUpdateFanPolarity( pFanout ); else Abc_ObjFaninFlipPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) ); } int Abc_NodeCompareLevels( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { int Diff = Abc_ObjLevel(*pp1) - Abc_ObjLevel(*pp2); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; Diff = (*pp1)->Id - (*pp2)->Id; // needed to make qsort() platform-infependent if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } int Abc_SclComputeReverseLevel( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, Level = 0; Abc_ObjForEachFanout( pObj, pFanout, i ) Level = Abc_MaxInt( Level, pFanout->Level ); return Level + 1; } Abc_Obj_t * Abc_SclPerformBufferingOne( Abc_Obj_t * pObj, int Degree, int fUseInvs, int fVerbose ) { Vec_Ptr_t * vFanouts; Abc_Obj_t * pBuffer, * pFanout; int i, Degree0 = Degree; assert( Abc_ObjFanoutNum(pObj) > Degree ); // collect fanouts and sort by reverse level vFanouts = Vec_PtrAlloc( Abc_ObjFanoutNum(pObj) ); Abc_NodeCollectFanouts( pObj, vFanouts ); Vec_PtrSort( vFanouts, (int (*)(void))Abc_NodeCompareLevels ); // select the first Degree fanouts if ( fUseInvs ) pBuffer = Abc_NtkCreateNodeInv( pObj->pNtk, NULL ); else pBuffer = Abc_NtkCreateNodeBuf( pObj->pNtk, NULL ); // check if it is possible to not increase level if ( Vec_PtrSize(vFanouts) < 2 * Degree ) { Abc_Obj_t * pFanPrev = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, Vec_PtrSize(vFanouts)-1-Degree); Abc_Obj_t * pFanThis = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, Degree-1); Abc_Obj_t * pFanLast = (Abc_Obj_t *)Vec_PtrEntryLast(vFanouts); if ( Abc_ObjLevel(pFanThis) == Abc_ObjLevel(pFanLast) && Abc_ObjLevel(pFanPrev) < Abc_ObjLevel(pFanThis) ) { // find the first one whose level is the same as last Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i ) if ( Abc_ObjLevel(pFanout) == Abc_ObjLevel(pFanLast) ) break; assert( i < Vec_PtrSize(vFanouts) ); if ( i > 1 ) Degree = i; } // make the last two more well-balanced if ( Degree == Degree0 && Degree > Vec_PtrSize(vFanouts) - Degree ) Degree = Vec_PtrSize(vFanouts)/2 + (Vec_PtrSize(vFanouts) & 1); assert( Degree <= Degree0 ); } // select fanouts Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, i, Degree ) Abc_ObjPatchFanin( pFanout, pObj, pBuffer ); if ( fVerbose ) { printf( "%5d : ", Abc_ObjId(pObj) ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i ) printf( "%d%s ", Abc_ObjLevel(pFanout), i == Degree-1 ? " " : "" ); printf( "\n" ); } Vec_PtrFree( vFanouts ); Abc_ObjAddFanin( pBuffer, pObj ); pBuffer->Level = Abc_SclComputeReverseLevel( pBuffer ); if ( fUseInvs ) Abc_NodeInvUpdateFanPolarity( pBuffer ); return pBuffer; } void Abc_SclPerformBuffering_rec( Abc_Obj_t * pObj, int DegreeR, int Degree, int fUseInvs, int fVerbose ) { Vec_Ptr_t * vFanouts; Abc_Obj_t * pBuffer; Abc_Obj_t * pFanout; int i, nOldFanNum; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); pObj->Level = 0; if ( Abc_ObjIsCo(pObj) ) return; assert( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ); // buffer fanouts and collect reverse levels Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_SclPerformBuffering_rec( pFanout, DegreeR, Degree, fUseInvs, fVerbose ); // perform buffering as long as needed nOldFanNum = Abc_ObjFanoutNum(pObj); while ( Abc_ObjFanoutNum(pObj) > Degree ) Abc_SclPerformBufferingOne( pObj, Degree, fUseInvs, fVerbose ); // add yet another level of buffers if ( DegreeR && nOldFanNum > DegreeR ) { if ( fUseInvs ) pBuffer = Abc_NtkCreateNodeInv( pObj->pNtk, NULL ); else pBuffer = Abc_NtkCreateNodeBuf( pObj->pNtk, NULL ); vFanouts = Vec_PtrAlloc( Abc_ObjFanoutNum(pObj) ); Abc_NodeCollectFanouts( pObj, vFanouts ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i ) Abc_ObjPatchFanin( pFanout, pObj, pBuffer ); Vec_PtrFree( vFanouts ); Abc_ObjAddFanin( pBuffer, pObj ); pBuffer->Level = Abc_SclComputeReverseLevel( pBuffer ); if ( fUseInvs ) Abc_NodeInvUpdateFanPolarity( pBuffer ); } // compute the new level of the node pObj->Level = Abc_SclComputeReverseLevel( pObj ); } Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int DegreeR, int Degree, int fUseInvs, int fVerbose ) { Vec_Int_t * vCiLevs; Abc_Ntk_t * pNew; Abc_Obj_t * pObj; int i; assert( Abc_NtkHasMapping(p) ); if ( fUseInvs ) { printf( "Warning!!! Using inverters instead of buffers.\n" ); if ( p->vPhases == NULL ) printf( "The phases are not given. The result will not verify.\n" ); } // remember CI levels vCiLevs = Vec_IntAlloc( Abc_NtkCiNum(p) ); Abc_NtkForEachCi( p, pObj, i ) Vec_IntPush( vCiLevs, Abc_ObjLevel(pObj) ); // perform buffering Abc_NtkIncrementTravId( p ); Abc_NtkForEachCi( p, pObj, i ) Abc_SclPerformBuffering_rec( pObj, DegreeR, Degree, fUseInvs, fVerbose ); // recompute logic levels Abc_NtkForEachCi( p, pObj, i ) pObj->Level = Vec_IntEntry( vCiLevs, i ); Abc_NtkForEachNode( p, pObj, i ) Abc_ObjLevelNew( pObj ); Vec_IntFree( vCiLevs ); // if phases are present if ( p->vPhases ) Vec_IntFillExtra( p->vPhases, Abc_NtkObjNumMax(p), 0 ); // duplication in topo order pNew = Abc_NtkDupDfs( p ); Abc_SclCheckNtk( pNew, fVerbose ); // Abc_NtkDelete( pNew ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_BufComputeArr( Buf_Man_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; float DelayF, Delay = -ABC_INFINITY; Abc_ObjForEachFanin( pObj, pFanin, i ) { if ( Vec_IntEntry(p->vOffsets, Abc_ObjId(pObj)) == -ABC_INFINITY ) continue; DelayF = Abc_BufNodeArr(p, pFanin) + Abc_BufEdgeDelay(p, pObj, i); if ( Delay < DelayF ) Delay = DelayF; } Abc_BufSetNodeArr( p, pObj, Delay ); return Delay; } float Abc_BufComputeDep( Buf_Man_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; float DelayF, Delay = -ABC_INFINITY; Abc_ObjForEachFanout( pObj, pFanout, i ) { if ( Vec_IntEntry(p->vOffsets, Abc_ObjId(pFanout)) == -ABC_INFINITY ) continue; DelayF = Abc_BufNodeDep(p, pFanout) + Abc_BufEdgeDelay(p, pFanout, Abc_NodeFindFanin(pFanout, pObj)); if ( Delay < DelayF ) Delay = DelayF; } Abc_BufSetNodeDep( p, pObj, Delay ); return Delay; } void Abc_BufUpdateGlobal( Buf_Man_t * p ) { Abc_Obj_t * pObj; int i; p->DelayMax = 0; Abc_NtkForEachCo( p->pNtk, pObj, i ) p->DelayMax = Abc_MaxInt( p->DelayMax, Abc_BufNodeArr(p, Abc_ObjFanin0(pObj)) ); } void Abc_BufCreateEdges( Buf_Man_t * p, Abc_Obj_t * pObj ) { int k; Mio_Gate_t * pGate = Abc_ObjIsCo(pObj) ? NULL : (Mio_Gate_t *)pObj->pData; Vec_IntWriteEntry( p->vOffsets, Abc_ObjId(pObj), Vec_IntSize(p->vEdges) ); for ( k = 0; k < Abc_ObjFaninNum(pObj); k++ ) Vec_IntPush( p->vEdges, pGate ? (int)(1.0 * BUF_SCALE * Mio_GateReadPinDelay(pGate, k) / p->DelayInv) : 0 ); } void Abc_BufAddToQue( Buf_Man_t * p, Abc_Obj_t * pObj ) { if ( Abc_ObjFanoutNum(pObj) < p->nFanMin || (!p->fBufPis && Abc_ObjIsCi(pObj)) ) return; Vec_FltWriteEntry( p->vCounts, Abc_ObjId(pObj), Abc_ObjFanoutNum(pObj) ); if ( Vec_QueIsMember(p->vQue, Abc_ObjId(pObj)) ) Vec_QueUpdate( p->vQue, Abc_ObjId(pObj) ); else Vec_QuePush( p->vQue, Abc_ObjId(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_BufCollectTfoCone_rec( Abc_Obj_t * pNode, Vec_Int_t * vNodes ) { Abc_Obj_t * pNext; int i; if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; Abc_NodeSetTravIdCurrent( pNode ); if ( Abc_ObjIsCo(pNode) ) return; assert( Abc_ObjIsCi(pNode) || Abc_ObjIsNode(pNode) ); Abc_ObjForEachFanout( pNode, pNext, i ) Abc_BufCollectTfoCone_rec( pNext, vNodes ); if ( Abc_ObjIsNode(pNode) ) Vec_IntPush( vNodes, Abc_ObjId(pNode) ); } void Abc_BufCollectTfoCone( Buf_Man_t * p, Abc_Obj_t * pObj ) { Vec_IntClear( p->vTfCone ); Abc_NtkIncrementTravId( p->pNtk ); Abc_BufCollectTfoCone_rec( pObj, p->vTfCone ); } void Abc_BufUpdateArr( Buf_Man_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pNext; int i, Delay; // assert( Abc_ObjIsNode(pObj) ); Abc_BufCollectTfoCone( p, pObj ); Vec_IntReverseOrder( p->vTfCone ); Abc_NtkForEachObjVec( p->vTfCone, p->pNtk, pNext, i ) { Delay = Abc_BufComputeArr( p, pNext ); p->DelayMax = Abc_MaxInt( p->DelayMax, Delay ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_BufCollectTfiCone_rec( Abc_Obj_t * pNode, Vec_Int_t * vNodes ) { Abc_Obj_t * pNext; int i; if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; Abc_NodeSetTravIdCurrent( pNode ); if ( Abc_ObjIsCi(pNode) ) return; assert( Abc_ObjIsNode(pNode) ); Abc_ObjForEachFanin( pNode, pNext, i ) Abc_BufCollectTfiCone_rec( pNext, vNodes ); Vec_IntPush( vNodes, Abc_ObjId(pNode) ); } void Abc_BufCollectTfiCone( Buf_Man_t * p, Abc_Obj_t * pObj ) { Vec_IntClear( p->vTfCone ); Abc_NtkIncrementTravId( p->pNtk ); Abc_BufCollectTfiCone_rec( pObj, p->vTfCone ); } void Abc_BufUpdateDep( Buf_Man_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pNext; int i, Delay; // assert( Abc_ObjIsNode(pObj) ); Abc_BufCollectTfiCone( p, pObj ); Vec_IntReverseOrder( p->vTfCone ); Abc_NtkForEachObjVec( p->vTfCone, p->pNtk, pNext, i ) { Delay = Abc_BufComputeDep( p, pNext ); p->DelayMax = Abc_MaxInt( p->DelayMax, Delay ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Buf_Man_t * Buf_ManStart( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fBufPis ) { Buf_Man_t * p; Abc_Obj_t * pObj; Vec_Ptr_t * vNodes; int i; p = ABC_CALLOC( Buf_Man_t, 1 ); p->pNtk = pNtk; p->nFanMin = FanMin; p->nFanMax = FanMax; p->fBufPis = fBufPis; // allocate arrays p->nObjStart = Abc_NtkObjNumMax(p->pNtk); p->nObjAlloc = (6 * Abc_NtkObjNumMax(p->pNtk) / 3) + 100; p->vOffsets = Vec_IntAlloc( p->nObjAlloc ); p->vArr = Vec_IntAlloc( p->nObjAlloc ); p->vDep = Vec_IntAlloc( p->nObjAlloc ); p->vCounts = Vec_FltAlloc( p->nObjAlloc ); p->vQue = Vec_QueAlloc( p->nObjAlloc ); Vec_IntFill( p->vOffsets, p->nObjAlloc, -ABC_INFINITY ); Vec_IntFill( p->vArr, p->nObjAlloc, 0 ); Vec_IntFill( p->vDep, p->nObjAlloc, 0 ); Vec_FltFill( p->vCounts, p->nObjAlloc, -ABC_INFINITY ); Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vCounts) ); // collect edge delays p->DelayInv = Mio_GateReadPinDelay( Mio_LibraryReadInv((Mio_Library_t *)pNtk->pManFunc), 0 ); p->vEdges = Vec_IntAlloc( 1000 ); // create edges vNodes = Abc_NtkDfs( p->pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_BufCreateEdges( p, pObj ); Abc_NtkForEachCo( p->pNtk, pObj, i ) Abc_BufCreateEdges( p, pObj ); // derive delays Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_BufComputeArr( p, pObj ); Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i ) Abc_BufComputeDep( p, pObj ); Abc_BufUpdateGlobal( p ); // Abc_NtkForEachNode( p->pNtk, pObj, i ) // printf( "%4d : %4d %4d\n", i, Abc_BufNodeArr(p, pObj), Abc_BufNodeDep(p, pObj) ); // create fanout queue // Abc_NtkForEachCi( p->pNtk, pObj, i ) // Abc_BufAddToQue( p, pObj ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_BufAddToQue( p, pObj ); Vec_PtrFree( vNodes ); p->vDelays = Vec_IntAlloc( 100 ); p->vOrder = Vec_IntAlloc( 100 ); p->vNonCrit = Vec_IntAlloc( 100 ); p->vTfCone = Vec_IntAlloc( 100 ); p->vFanouts = Vec_PtrAlloc( 100 ); return p; } void Buf_ManStop( Buf_Man_t * p ) { printf( "Sep = %d. Dup = %d. Br0 = %d. Br1 = %d. BrC = %d. ", p->nSeparate, p->nDuplicate, p->nBranch0, p->nBranch1, p->nBranchCrit ); printf( "Orig = %d. Add = %d. Rem = %d.\n", p->nObjStart, Abc_NtkObjNumMax(p->pNtk) - p->nObjStart, p->nObjAlloc - Abc_NtkObjNumMax(p->pNtk) ); Vec_PtrFree( p->vFanouts ); Vec_IntFree( p->vTfCone ); Vec_IntFree( p->vNonCrit ); Vec_IntFree( p->vDelays ); Vec_IntFree( p->vOrder ); Vec_IntFree( p->vOffsets ); Vec_IntFree( p->vEdges ); Vec_IntFree( p->vArr ); Vec_IntFree( p->vDep ); // Vec_QueCheck( p->vQue ); Vec_QueFree( p->vQue ); Vec_FltFree( p->vCounts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_BufSortByDelay( Buf_Man_t * p, int iPivot ) { Abc_Obj_t * pObj, * pFanout; int i, Slack, * pOrder; Vec_IntClear( p->vDelays ); pObj = Abc_NtkObj( p->pNtk, iPivot ); Abc_ObjForEachFanout( pObj, pFanout, i ) { Slack = Abc_BufEdgeSlack(p, pObj, pFanout); assert( Slack >= 0 ); Vec_IntPush( p->vDelays, Abc_MaxInt(0, Slack) ); } pOrder = Abc_QuickSortCost( Vec_IntArray(p->vDelays), Vec_IntSize(p->vDelays), 0 ); Vec_IntClear( p->vOrder ); for ( i = 0; i < Vec_IntSize(p->vDelays); i++ ) Vec_IntPush( p->vOrder, Abc_ObjId(Abc_ObjFanout(pObj, pOrder[i])) ); ABC_FREE( pOrder ); // for ( i = 0; i < Vec_IntSize(p->vDelays); i++ ) // printf( "%5d - %5d ", Vec_IntEntry(p->vOrder, i), Abc_BufEdgeSlack(p, pObj, Abc_NtkObj(p->pNtk, Vec_IntEntry(p->vOrder, i))) ); return p->vOrder; } void Abc_BufPrintOne( Buf_Man_t * p, int iPivot ) { Abc_Obj_t * pObj, * pFanout; Vec_Int_t * vOrder; int i, Slack; pObj = Abc_NtkObj( p->pNtk, iPivot ); vOrder = Abc_BufSortByDelay( p, iPivot ); printf( "Node %5d Fi = %d Fo = %3d Lev = %3d : {", iPivot, Abc_ObjFaninNum(pObj), Abc_ObjFanoutNum(pObj), Abc_ObjLevel(pObj) ); Abc_NtkForEachObjVec( vOrder, p->pNtk, pFanout, i ) { Slack = Abc_BufEdgeSlack( p, pObj, pFanout ); printf( " %d(%d)", Abc_ObjId(pFanout), Slack ); } printf( " }\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_BufReplaceBufsByInvs( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pInv; int i, Counter = 0; Abc_NtkForEachNode( pNtk, pObj, i ) { if ( !Abc_NodeIsBuf(pObj) ) continue; assert( pObj->pData == Mio_LibraryReadBuf((Mio_Library_t *)pNtk->pManFunc) ); pObj->pData = Mio_LibraryReadInv((Mio_Library_t *)pNtk->pManFunc); pInv = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanin0(pObj) ); Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pInv ); Counter++; } printf( "Replaced %d buffers by invertor pairs.\n", Counter ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_BufComputeAverage( Buf_Man_t * p, int iPivot, Vec_Int_t * vOrder ) { Abc_Obj_t * pObj, * pFanout; int i, Average = 0; pObj = Abc_NtkObj( p->pNtk, iPivot ); Abc_NtkForEachObjVec( vOrder, p->pNtk, pFanout, i ) Average += Abc_BufEdgeSlack( p, pObj, pFanout ); return Average / Vec_IntSize(vOrder); } Abc_Obj_t * Abc_BufFindNonBuffDriver( Buf_Man_t * p, Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NodeIsBuf(pObj)) ? Abc_BufFindNonBuffDriver(p, Abc_ObjFanin0(pObj)) : pObj; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_BufCountNonCritical( Buf_Man_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; Vec_IntClear( p->vNonCrit ); Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_BufEdgeSlack( p, pObj, pFanout ) > 7*BUF_SCALE/2 ) Vec_IntPush( p->vNonCrit, Abc_ObjId(pFanout) ); return Vec_IntSize(p->vNonCrit); } void Abc_BufPerformOne( Buf_Man_t * p, int iPivot, int fSkipDup, int fVerbose ) { Abc_Obj_t * pObj, * pFanout; int i, j, nCrit, nNonCrit; // int DelayMax = p->DelayMax; assert( Abc_NtkObjNumMax(p->pNtk) + 30 < p->nObjAlloc ); pObj = Abc_NtkObj( p->pNtk, iPivot ); // assert( Vec_FltEntry(p->vCounts, iPivot) == (float)Abc_ObjFanoutNum(pObj) ); nNonCrit = Abc_BufCountNonCritical( p, pObj ); nCrit = Abc_ObjFanoutNum(pObj) - nNonCrit; if ( fVerbose ) { //Abc_BufPrintOne( p, iPivot ); printf( "ObjId = %6d : %-10s FI = %d. FO =%4d. Crit =%4d. ", Abc_ObjId(pObj), Mio_GateReadName((Mio_Gate_t *)pObj->pData), Abc_ObjFaninNum(pObj), Abc_ObjFanoutNum(pObj), nCrit ); } // consider three cases if ( nCrit > 0 && nNonCrit > 1 ) { // (1) both critical and non-critical are present - split them by adding buffer Abc_Obj_t * pBuffer = Abc_NtkCreateNodeBuf( p->pNtk, pObj ); Abc_NtkForEachObjVec( p->vNonCrit, p->pNtk, pFanout, i ) Abc_ObjPatchFanin( pFanout, pObj, pBuffer ); // update timing Abc_BufCreateEdges( p, pBuffer ); Abc_BufUpdateArr( p, pBuffer ); Abc_BufUpdateDep( p, pBuffer ); Abc_BufAddToQue( p, pObj ); Abc_BufAddToQue( p, pBuffer ); Abc_SclTimeIncUpdateLevel( pBuffer ); p->nSeparate++; if ( fVerbose ) printf( "Adding buffer\n" ); } else if ( !fSkipDup && nCrit > 0 && Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > p->nFanMin )//&& Abc_ObjLevel(pObj) < 4 )//&& Abc_ObjFaninNum(pObj) < 2 ) { // (2) only critical are present - duplicate Abc_Obj_t * pClone = Abc_NtkDupObj( p->pNtk, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanout, i ) Abc_ObjAddFanin( pClone, pFanout ); Abc_NodeCollectFanouts( pObj, p->vFanouts ); Vec_PtrForEachEntryStop( Abc_Obj_t *, p->vFanouts, pFanout, i, Vec_PtrSize(p->vFanouts)/2 ) Abc_ObjPatchFanin( pFanout, pObj, pClone ); // update timing Abc_BufCreateEdges( p, pClone ); Abc_BufSetNodeArr( p, pClone, Abc_BufNodeArr(p, pObj) ); Abc_BufUpdateDep( p, pObj ); Abc_BufUpdateDep( p, pClone ); Abc_BufAddToQue( p, pObj ); Abc_BufAddToQue( p, pClone ); Abc_ObjForEachFanin( pObj, pFanout, i ) Abc_BufAddToQue( p, pFanout ); Abc_SclTimeIncUpdateLevel( pClone ); p->nDuplicate++; // printf( "Duplicating %s on level %d\n", Mio_GateReadName((Mio_Gate_t *)pObj->pData), Abc_ObjLevel(pObj) ); if ( fVerbose ) printf( "Duplicating node\n" ); } else if ( (nCrit > 0 && Abc_ObjFanoutNum(pObj) > 8) || Abc_ObjFanoutNum(pObj) > p->nFanMax ) { // (2) only critical or only non-critical - add buffer/inverter tree int nDegree, n1Degree, n1Number, nFirst; int iFirstBuf = Abc_NtkObjNumMax( p->pNtk ); // nDegree = Abc_MinInt( 3, (int)pow(Abc_ObjFanoutNum(pObj), 0.34) ); nDegree = Abc_MinInt( 10, (int)pow(Abc_ObjFanoutNum(pObj), 0.5) ); n1Degree = Abc_ObjFanoutNum(pObj) / nDegree + 1; n1Number = Abc_ObjFanoutNum(pObj) % nDegree; nFirst = n1Degree * n1Number; p->nBranchCrit += (nCrit > 0); // create inverters Abc_NodeCollectFanouts( pObj, p->vFanouts ); if ( Abc_ObjIsNode(pObj) && Abc_NodeIsBuf(pObj) ) { p->nBranch0++; pObj->pData = Mio_LibraryReadInv((Mio_Library_t *)p->pNtk->pManFunc); Abc_BufSetEdgeDelay( p, pObj, 0, BUF_SCALE ); assert( Abc_NodeIsInv(pObj) ); for ( i = 0; i < nDegree; i++ ) Abc_NtkCreateNodeInv( p->pNtk, pObj ); if ( fVerbose ) printf( "Adding %d inverters\n", nDegree ); } else { p->nBranch1++; for ( i = 0; i < nDegree; i++ ) Abc_NtkCreateNodeBuf( p->pNtk, pObj ); if ( fVerbose ) printf( "Adding %d buffers\n", nDegree ); } // connect inverters Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanouts, pFanout, i ) { j = (i < nFirst) ? i/n1Degree : n1Number + ((i - nFirst)/(n1Degree - 1)); assert( j >= 0 && j < nDegree ); Abc_ObjPatchFanin( pFanout, pObj, Abc_NtkObj(p->pNtk, iFirstBuf + j) ); } // update timing for ( i = 0; i < nDegree; i++ ) Abc_BufCreateEdges( p, Abc_NtkObj(p->pNtk, iFirstBuf + i) ); Abc_BufUpdateArr( p, pObj ); for ( i = 0; i < nDegree; i++ ) Abc_BufComputeDep( p, Abc_NtkObj(p->pNtk, iFirstBuf + i) ); Abc_BufUpdateDep( p, pObj ); for ( i = 0; i < nDegree; i++ ) Abc_BufAddToQue( p, Abc_NtkObj(p->pNtk, iFirstBuf + i) ); for ( i = 0; i < nDegree; i++ ) Abc_SclTimeIncUpdateLevel( Abc_NtkObj(p->pNtk, iFirstBuf + i) ); } else { if ( fVerbose ) printf( "Doing nothing\n" ); } // if ( DelayMax != p->DelayMax ) // printf( "%d (%.2f) ", p->DelayMax, 1.0 * p->DelayMax * p->DelayInv / BUF_SCALE ); } Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fBufPis, int fSkipDup, int fVerbose ) { Abc_Ntk_t * pNew; Buf_Man_t * p = Buf_ManStart( pNtk, FanMin, FanMax, fBufPis ); int i, Limit = ABC_INFINITY; Abc_NtkLevel( pNtk ); // if ( Abc_NtkNodeNum(pNtk) < 1000 ) // fSkipDup = 1; for ( i = 0; i < Limit && Vec_QueSize(p->vQue); i++ ) Abc_BufPerformOne( p, Vec_QuePop(p->vQue), fSkipDup, fVerbose ); Buf_ManStop( p ); // Abc_BufReplaceBufsByInvs( pNtk ); // duplicate network in topo order pNew = Abc_NtkDupDfs( pNtk ); Abc_SclCheckNtk( pNew, fVerbose ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclCon.h000066400000000000000000000375531300674244400230010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclCon.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Constraint manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclCon.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__scl_Con__h #define ABC__scl_Con__h ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Scl_Con_t_ Scl_Con_t; struct Scl_Con_t_ { char * pFileName; // constraint file name char * pModelName; // current design name char * pInCellDef; // default input driving gate int tInArrDef; // default input arrival time int tInSlewDef; // default input slew int tInLoadDef; // default input load int tOutReqDef; // default output required time int tOutLoadDef; // default output load Vec_Ptr_t vInCells; // input driving gate names Vec_Ptr_t vInCellsPtr; // input driving gates Vec_Int_t vInArrs; // input arrival times Vec_Int_t vInSlews; // input slews Vec_Int_t vInLoads; // input loads Vec_Int_t vOutReqs; // output required times Vec_Int_t vOutLoads; // output loads Abc_Nam_t * pNamI; // input names Abc_Nam_t * pNamO; // output names }; #define SCL_INPUT_CELL "input_cell" #define SCL_INPUT_ARR "input_arrival" #define SCL_INPUT_SLEW "input_slew" #define SCL_INPUT_LOAD "input_load" #define SCL_OUTPUT_REQ "output_required" #define SCL_OUTPUT_LOAD "output_load" #define SCL_DIRECTIVE(ITEM) "."ITEM #define SCL_DEF_DIRECTIVE(ITEM) ".default_"ITEM #define SCL_NUM 1000 #define SCL_INFINITY (0x3FFFFFFF) static inline int Scl_Flt2Int( float w ) { return SCL_NUM*w; } static inline float Scl_Int2Flt( int i ) { return (float)i/SCL_NUM; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Manager construction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Scl_Con_t * Scl_ConAlloc( char * pFileName, Abc_Nam_t * pNamI, Abc_Nam_t * pNamO ) { Scl_Con_t * p = ABC_CALLOC( Scl_Con_t, 1 ); p->pFileName = Abc_UtilStrsav( pFileName ); p->pNamI = pNamI; p->pNamO = pNamO; p->pModelName = NULL; p->pInCellDef = NULL; p->tInArrDef = SCL_INFINITY; p->tInSlewDef = SCL_INFINITY; p->tInLoadDef = SCL_INFINITY; p->tOutReqDef = SCL_INFINITY; p->tOutLoadDef = SCL_INFINITY; Vec_PtrFill( &p->vInCells, Abc_NamObjNumMax(pNamI)-1, NULL ); Vec_IntFill( &p->vInArrs, Abc_NamObjNumMax(pNamI)-1, SCL_INFINITY ); Vec_IntFill( &p->vInSlews, Abc_NamObjNumMax(pNamI)-1, SCL_INFINITY ); Vec_IntFill( &p->vInLoads, Abc_NamObjNumMax(pNamI)-1, SCL_INFINITY ); Vec_IntFill( &p->vOutReqs, Abc_NamObjNumMax(pNamO)-1, SCL_INFINITY ); Vec_IntFill( &p->vOutLoads, Abc_NamObjNumMax(pNamO)-1, SCL_INFINITY ); return p; } static inline void Scl_ConFree( Scl_Con_t * p ) { Vec_PtrErase( &p->vInCellsPtr ); Vec_PtrFreeData( &p->vInCells ); Vec_PtrErase( &p->vInCells ); Vec_IntErase( &p->vInArrs ); Vec_IntErase( &p->vInSlews ); Vec_IntErase( &p->vInLoads ); Vec_IntErase( &p->vOutReqs ); Vec_IntErase( &p->vOutLoads ); Abc_NamDeref( p->pNamI ); Abc_NamDeref( p->pNamO ); ABC_FREE( p->pInCellDef ); ABC_FREE( p->pModelName ); ABC_FREE( p->pFileName ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Manager serialization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Scl_ConParse( Scl_Con_t * p, Abc_Nam_t * pNamI, Abc_Nam_t * pNamO ) { char Buffer[1000]; char * pToken, * pToken2, * pToken3, * pName; int i, Num = -1, nLines = 0; int Value; FILE * pFile = fopen( p->pFileName, "rb" ); while ( fgets( Buffer, 1000, pFile ) ) { nLines++; pToken = strtok( Buffer, " \t\r\n" ); if ( pToken == NULL ) continue; pToken2 = strtok( NULL, " \t\r\n" ); if ( pToken2 == NULL ) { printf( "Line %d: Skipping directive \"%s\" without argument.\n", nLines, pToken ); continue; } pToken3 = strtok( NULL, " \t\r\n" ); if ( !strcmp(pToken, ".model") ) p->pModelName = Abc_UtilStrsav(pToken2); else if ( !strcmp(pToken, SCL_DEF_DIRECTIVE(SCL_INPUT_CELL)) ) p->pInCellDef = Abc_UtilStrsav(pToken2); else if ( !strcmp(pToken, SCL_DEF_DIRECTIVE(SCL_INPUT_ARR)) ) p->tInArrDef = Scl_Flt2Int(atof(pToken2)); else if ( !strcmp(pToken, SCL_DEF_DIRECTIVE(SCL_INPUT_SLEW)) ) p->tInSlewDef = Scl_Flt2Int(atof(pToken2)); else if ( !strcmp(pToken, SCL_DEF_DIRECTIVE(SCL_INPUT_LOAD)) ) p->tInLoadDef = Scl_Flt2Int(atof(pToken2)); else if ( !strcmp(pToken, SCL_DEF_DIRECTIVE(SCL_OUTPUT_REQ)) ) p->tOutReqDef = Scl_Flt2Int(atof(pToken2)); else if ( !strcmp(pToken, SCL_DEF_DIRECTIVE(SCL_OUTPUT_LOAD))) p->tOutLoadDef = Scl_Flt2Int(atof(pToken2)); else if ( pToken3 == NULL ) { printf( "Directive %s should be followed by two arguments.\n", pToken ); continue; } else if ( !strcmp(pToken, SCL_DIRECTIVE(SCL_INPUT_CELL)) ) if ( (Num = Abc_NamStrFind(pNamI, pToken2)) > 0 ) Vec_PtrWriteEntry( &p->vInCells, Num-1, Abc_UtilStrsav(pToken3) ); else printf( "Line %d: Cannot find input \"%s\".\n", nLines, pToken2 ); else if ( !strcmp(pToken, SCL_DIRECTIVE(SCL_INPUT_ARR)) ) if ( (Num = Abc_NamStrFind(pNamI, pToken2)) > 0 ) Vec_IntWriteEntry( &p->vInArrs, Num-1, Scl_Flt2Int(atof(pToken3)) ); else printf( "Line %d: Cannot find input \"%s\".\n", nLines, pToken2 ); else if ( !strcmp(pToken, SCL_DIRECTIVE(SCL_INPUT_SLEW)) ) if ( (Num = Abc_NamStrFind(pNamI, pToken2)) > 0 ) Vec_IntWriteEntry( &p->vInSlews, Num-1, Scl_Flt2Int(atof(pToken3)) ); else printf( "Line %d: Cannot find input \"%s\".\n", nLines, pToken2 ); else if ( !strcmp(pToken, SCL_DIRECTIVE(SCL_INPUT_LOAD)) ) if ( (Num = Abc_NamStrFind(pNamI, pToken2)) > 0 ) Vec_IntWriteEntry( &p->vInLoads, Num-1, Scl_Flt2Int(atof(pToken3)) ); else printf( "Line %d: Cannot find input \"%s\".\n", nLines, pToken2 ); else if ( !strcmp(pToken, SCL_DIRECTIVE(SCL_OUTPUT_REQ)) ) if ( (Num = Abc_NamStrFind(pNamO, pToken2)) > 0 ) Vec_IntWriteEntry( &p->vOutReqs, Num-1, Scl_Flt2Int(atof(pToken3)) ); else printf( "Line %d: Cannot find output \"%s\".\n", nLines, pToken2 ); else if ( !strcmp(pToken, SCL_DIRECTIVE(SCL_OUTPUT_LOAD)) ) if ( (Num = Abc_NamStrFind(pNamO, pToken2)) > 0 ) Vec_IntWriteEntry( &p->vOutLoads, Num-1, Scl_Flt2Int(atof(pToken3)) ); else printf( "Line %d: Cannot find output \"%s\".\n", nLines, pToken2 ); else printf( "Line %d: Skipping unrecognized directive \"%s\".\n", nLines, pToken ); } // set missing defaults if ( p->pInCellDef == NULL ) p->pInCellDef = NULL; // consider using buffer from the current library if ( p->tInArrDef == SCL_INFINITY ) p->tInArrDef = 0; if ( p->tInSlewDef == SCL_INFINITY ) p->tInSlewDef = 0; if ( p->tInLoadDef == SCL_INFINITY ) p->tInLoadDef = 0; if ( p->tOutReqDef == SCL_INFINITY ) p->tOutReqDef = 0; if ( p->tOutLoadDef == SCL_INFINITY ) p->tOutLoadDef = 0; // set individual defaults if ( p->pInCellDef ) Vec_PtrForEachEntry(char *, &p->vInCells, pName, i) if ( pName == NULL ) Vec_PtrWriteEntry( &p->vInCells, i, Abc_UtilStrsav(p->pInCellDef) ); Vec_IntForEachEntry( &p->vInArrs, Value, i ) if ( Value == SCL_INFINITY ) Vec_IntWriteEntry( &p->vInArrs, i, p->tInArrDef ); Vec_IntForEachEntry( &p->vInSlews, Value, i ) if ( Value == SCL_INFINITY ) Vec_IntWriteEntry( &p->vInSlews, i, p->tInSlewDef ); Vec_IntForEachEntry( &p->vInLoads, Value, i ) if ( Value == SCL_INFINITY ) Vec_IntWriteEntry( &p->vInLoads, i, p->tInLoadDef ); Vec_IntForEachEntry( &p->vOutReqs, Value, i ) if ( Value == SCL_INFINITY ) Vec_IntWriteEntry( &p->vOutReqs, i, p->tOutReqDef ); Vec_IntForEachEntry( &p->vOutLoads, Value, i ) if ( Value == SCL_INFINITY ) Vec_IntWriteEntry( &p->vOutLoads, i, p->tOutLoadDef ); fclose( pFile ); return 1; } static inline Scl_Con_t * Scl_ConRead( char * pFileName, Abc_Nam_t * pNamI, Abc_Nam_t * pNamO ) { Scl_Con_t * p = Scl_ConAlloc( pFileName, pNamI, pNamO ); if ( Scl_ConParse(p, pNamI, pNamO) ) return p; Scl_ConFree( p ); return NULL; } static inline void Scl_ConWrite( Scl_Con_t * p, char * pFileName ) { char * pName; int Value; int i; FILE * pFile = pFileName ? fopen( pFileName, "wb" ) : stdout; if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } fprintf( pFile, ".model %s\n", p->pModelName ); if ( p->pInCellDef ) fprintf( pFile, ".default_%s %s\n", SCL_INPUT_CELL, p->pInCellDef ); if ( p->tInArrDef != 0 ) fprintf( pFile, ".default_%s %.2f\n", SCL_INPUT_ARR, Scl_Int2Flt(p->tInArrDef) ); if ( p->tInSlewDef != 0 ) fprintf( pFile, ".default_%s %.2f\n", SCL_INPUT_SLEW, Scl_Int2Flt(p->tInSlewDef) ); if ( p->tInLoadDef != 0 ) fprintf( pFile, ".default_%s %.2f\n", SCL_INPUT_LOAD, Scl_Int2Flt(p->tInLoadDef) ); if ( p->tOutReqDef != 0 ) fprintf( pFile, ".default_%s %.2f\n", SCL_OUTPUT_REQ, Scl_Int2Flt(p->tOutReqDef) ); if ( p->tOutLoadDef != 0 ) fprintf( pFile, ".default_%s %.2f\n", SCL_OUTPUT_LOAD, Scl_Int2Flt(p->tOutLoadDef) ); Vec_PtrForEachEntry(char *, &p->vInCells, pName, i) if ( pName && (!p->pInCellDef || strcmp(pName,p->pInCellDef)) ) fprintf( pFile, ".%s %s %s\n", SCL_INPUT_CELL, Abc_NamStr(p->pNamI, i+1), pName ); Vec_IntForEachEntry( &p->vInArrs, Value, i ) if ( Value != p->tInArrDef ) fprintf( pFile, ".%s %s %.2f\n", SCL_INPUT_ARR, Abc_NamStr(p->pNamI, i+1), Scl_Int2Flt(Value) ); Vec_IntForEachEntry( &p->vInSlews, Value, i ) if ( Value != p->tInSlewDef ) fprintf( pFile, ".%s %s %.2f\n", SCL_INPUT_SLEW, Abc_NamStr(p->pNamI, i+1), Scl_Int2Flt(Value) ); Vec_IntForEachEntry( &p->vInLoads, Value, i ) if ( Value != p->tInLoadDef ) fprintf( pFile, ".%s %s %.2f\n", SCL_INPUT_LOAD, Abc_NamStr(p->pNamI, i+1), Scl_Int2Flt(Value) ); Vec_IntForEachEntry( &p->vOutReqs, Value, i ) if ( Value != p->tOutReqDef ) fprintf( pFile, ".%s %s %.2f\n", SCL_OUTPUT_REQ, Abc_NamStr(p->pNamO, i+1), Scl_Int2Flt(Value) ); Vec_IntForEachEntry( &p->vOutLoads, Value, i ) if ( Value != p->tOutLoadDef ) fprintf( pFile, ".%s %s %.2f\n", SCL_OUTPUT_LOAD, Abc_NamStr(p->pNamO, i+1), Scl_Int2Flt(Value) ); if ( pFile != stdout ) fclose ( pFile ); } /**Function************************************************************* Synopsis [Internal APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Scl_ConHasInCells_( Scl_Con_t * p ) { return Vec_PtrCountZero(&p->vInCells) != Vec_PtrSize(&p->vInCells); } static inline int Scl_ConHasInArrs_( Scl_Con_t * p ) { return Vec_IntCountZero(&p->vInArrs) != Vec_IntSize(&p->vInArrs); } static inline int Scl_ConHasInSlews_( Scl_Con_t * p ) { return Vec_IntCountZero(&p->vInSlews) != Vec_IntSize(&p->vInSlews); } static inline int Scl_ConHasInLoads_( Scl_Con_t * p ) { return Vec_IntCountZero(&p->vInLoads) != Vec_IntSize(&p->vInLoads); } static inline int Scl_ConHasOutReqs_( Scl_Con_t * p ) { return Vec_IntCountZero(&p->vOutReqs) != Vec_IntSize(&p->vOutReqs); } static inline int Scl_ConHasOutLoads_( Scl_Con_t * p ) { return Vec_IntCountZero(&p->vOutLoads) != Vec_IntSize(&p->vOutLoads); } static inline char * Scl_ConGetInCell_( Scl_Con_t * p, int i ) { return (char*)Vec_PtrEntry( &p->vInCells, i ); } static inline int Scl_ConGetInArr_( Scl_Con_t * p, int i ) { return Vec_IntEntry( &p->vInArrs, i ); } static inline int Scl_ConGetInSlew_( Scl_Con_t * p, int i ) { return Vec_IntEntry( &p->vInSlews, i ); } static inline int Scl_ConGetInLoad_( Scl_Con_t * p, int i ) { return Vec_IntEntry( &p->vInLoads, i ); } static inline int Scl_ConGetOutReq_( Scl_Con_t * p, int i ) { return Vec_IntEntry( &p->vOutReqs, i ); } static inline int Scl_ConGetOutLoad_( Scl_Con_t * p, int i ) { return Vec_IntEntry( &p->vOutLoads, i ); } /**Function************************************************************* Synopsis [External APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ extern Scl_Con_t * Scl_ConReadMan(); static inline int Scl_ConIsRunning() { return Scl_ConReadMan() != NULL; } static inline int Scl_ConHasInCells() { return Scl_ConHasInCells_ ( Scl_ConReadMan() ); } static inline int Scl_ConHasInArrs() { return Scl_ConHasInArrs_ ( Scl_ConReadMan() ); } static inline int Scl_ConHasInSlews() { return Scl_ConHasInSlews_ ( Scl_ConReadMan() ); } static inline int Scl_ConHasInLoads() { return Scl_ConHasInLoads_ ( Scl_ConReadMan() ); } static inline int Scl_ConHasOutReqs() { return Scl_ConHasOutReqs_ ( Scl_ConReadMan() ); } static inline int Scl_ConHasOutLoads() { return Scl_ConHasOutLoads_( Scl_ConReadMan() ); } static inline char * Scl_ConGetInCell( int i ) { return Scl_ConGetInCell_ ( Scl_ConReadMan(), i ); } static inline int Scl_ConGetInArr( int i ) { return Scl_ConGetInArr_ ( Scl_ConReadMan(), i ); } static inline int Scl_ConGetInSlew( int i ) { return Scl_ConGetInSlew_ ( Scl_ConReadMan(), i ); } static inline int Scl_ConGetInLoad( int i ) { return Scl_ConGetInLoad_ ( Scl_ConReadMan(), i ); } static inline int Scl_ConGetOutReq( int i ) { return Scl_ConGetOutReq_ ( Scl_ConReadMan(), i ); } static inline int Scl_ConGetOutLoad( int i ) { return Scl_ConGetOutLoad_( Scl_ConReadMan(), i ); } static inline float Scl_ConGetInArrFloat( int i ) { return Scl_Int2Flt( Scl_ConGetInArr(i) ); } static inline float Scl_ConGetInSlewFloat( int i ) { return Scl_Int2Flt( Scl_ConGetInSlew(i) ); } static inline float Scl_ConGetInLoadFloat( int i ) { return Scl_Int2Flt( Scl_ConGetInLoad(i) ); } static inline float Scl_ConGetOutReqFloat( int i ) { return Scl_Int2Flt( Scl_ConGetOutReq(i) ); } static inline float Scl_ConGetOutLoadFloat( int i ) { return Scl_Int2Flt( Scl_ConGetOutLoad(i) ); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclDnsize.c000066400000000000000000000325641300674244400235060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclDnsize.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Selective decrease of gate sizes.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclDnsize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclSize.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the array of nodes to be updated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclFindWindow( Abc_Obj_t * pPivot, Vec_Int_t ** pvNodes, Vec_Int_t ** pvEvals ) { Abc_Ntk_t * p = Abc_ObjNtk(pPivot); Abc_Obj_t * pObj, * pNext, * pNext2; Vec_Int_t * vNodes = *pvNodes; Vec_Int_t * vEvals = *pvEvals; int i, k; assert( Abc_ObjIsNode(pPivot) ); // collect fanins, node, and fanouts Vec_IntClear( vNodes ); Abc_ObjForEachFanin( pPivot, pNext, i ) // if ( Abc_ObjIsNode(pNext) && Abc_ObjFaninNum(pNext) > 0 ) if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) > 0 ) Vec_IntPush( vNodes, Abc_ObjId(pNext) ); Vec_IntPush( vNodes, Abc_ObjId(pPivot) ); Abc_ObjForEachFanout( pPivot, pNext, i ) if ( Abc_ObjIsNode(pNext) ) { Vec_IntPush( vNodes, Abc_ObjId(pNext) ); Abc_ObjForEachFanout( pNext, pNext2, k ) if ( Abc_ObjIsNode(pNext2) ) Vec_IntPush( vNodes, Abc_ObjId(pNext2) ); } Vec_IntUniqify( vNodes ); // label nodes Abc_NtkForEachObjVec( vNodes, p, pObj, i ) { assert( pObj->fMarkB == 0 ); pObj->fMarkB = 1; } // collect nodes visible from the critical paths Vec_IntClear( vEvals ); Abc_NtkForEachObjVec( vNodes, p, pObj, i ) Abc_ObjForEachFanout( pObj, pNext, k ) if ( !pNext->fMarkB ) { assert( pObj->fMarkB ); Vec_IntPush( vEvals, Abc_ObjId(pObj) ); break; } assert( Vec_IntSize(vEvals) > 0 ); // label nodes Abc_NtkForEachObjVec( vNodes, p, pObj, i ) pObj->fMarkB = 0; } /**Function************************************************************* Synopsis [Returns 1 if the node can be improved.] Description [Updated the node to have a new gate.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclCheckImprovement( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vNodes, Vec_Int_t * vEvals, int Notches, int DelayGap ) { Abc_Obj_t * pTemp; SC_Cell * pCellOld, * pCellNew; float dGain, dGainBest; int i, k, gateBest; abctime clk; clk = Abc_Clock(); // printf( "%d -> %d\n", Vec_IntSize(vNodes), Vec_IntSize(vEvals) ); // save old gate, timing, fanin load pCellOld = Abc_SclObjCell( pObj ); Abc_SclConeStore( p, vNodes ); Abc_SclEvalStore( p, vEvals ); Abc_SclLoadStore( p, pObj ); // try different gate sizes for this node gateBest = -1; dGainBest = -DelayGap; SC_RingForEachCellRev( pCellOld, pCellNew, i ) { if ( pCellNew->area >= pCellOld->area ) continue; if ( i > Notches ) break; // set new cell Abc_SclObjSetCell( pObj, pCellNew ); Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); // recompute timing Abc_SclTimeCone( p, vNodes ); // set old cell Abc_SclObjSetCell( pObj, pCellOld ); Abc_SclLoadRestore( p, pObj ); // evaluate gain dGain = Abc_SclEvalPerformLegal( p, vEvals, p->MaxDelay0 ); if ( dGain == -1 ) continue; // save best gain if ( dGainBest < dGain ) { dGainBest = dGain; gateBest = pCellNew->Id; } } // put back old cell and timing Abc_SclObjSetCell( pObj, pCellOld ); Abc_SclConeRestore( p, vNodes ); p->timeSize += Abc_Clock() - clk; if ( gateBest >= 0 ) { pCellNew = SC_LibCell( p->pLib, gateBest ); Abc_SclObjSetCell( pObj, pCellNew ); p->SumArea += pCellNew->area - pCellOld->area; // printf( "%f %f -> %f\n", pCellNew->area - pCellOld->area, p->SumArea - (pCellNew->area - pCellOld->area), p->SumArea ); // printf( "%6d %20s -> %20s %f -> %f\n", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName, pCellOld->area, pCellNew->area ); // mark used nodes with the current trav ID Abc_NtkForEachObjVec( vNodes, p->pNtk, pTemp, k ) Abc_NodeSetTravIdCurrent( pTemp ); // update load and timing... Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); Abc_SclTimeIncInsert( p, pObj ); return 1; } return 0; } /**Function************************************************************* Synopsis [Collect nodes by area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectNodesByArea( SC_Man * p, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; assert( Vec_QueSize(p->vNodeByGain) == 0 ); Vec_QueClear( p->vNodeByGain ); Abc_NtkForEachNode( pNtk, pObj, i ) if ( Abc_ObjFaninNum(pObj) > 0 ) { Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pObj), Abc_SclObjCell(pObj)->area ); Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) ); } } int Abc_SclCheckOverlap( Abc_Ntk_t * pNtk, Vec_Int_t * vNodes ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) if ( Abc_NodeIsTravIdCurrent(pObj) ) return 1; return 0; } /**Function************************************************************* Synopsis [Print cumulative statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclDnsizePrint( SC_Man * p, int Iter, int nAttempts, int nOverlaps, int nChanges, int fVerbose ) { if ( Iter == -1 ) printf( "Total : " ); else printf( "%5d : ", Iter ); printf( "Try =%6d ", nAttempts ); printf( "Over =%6d ", nOverlaps ); printf( "Fail =%6d ", nAttempts-nOverlaps-nChanges ); printf( "Win =%6d ", nChanges ); printf( "A: " ); printf( "%.2f ", p->SumArea ); printf( "(%+5.1f %%) ", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 ); printf( "D: " ); printf( "%.2f ps ", p->MaxDelay ); printf( "(%+5.1f %%) ", 100.0 * (p->MaxDelay - p->MaxDelay0)/ p->MaxDelay0 ); printf( "%8.2f sec ", 1.0*(Abc_Clock() - p->timeTotal)/(CLOCKS_PER_SEC) ); printf( "%c", fVerbose ? '\n' : '\r' ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclDnsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) { SC_Man * p; Abc_Obj_t * pObj; Vec_Int_t * vNodes, * vEvals, * vTryLater; abctime clk, nRuntimeLimit = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0; int i, k; if ( pPars->fVerbose ) { printf( "Parameters: " ); printf( "Iters =%5d. ", pPars->nIters ); printf( "UseDept =%2d. ", pPars->fUseDept ); printf( "UseWL =%2d. ", pPars->fUseWireLoads ); printf( "Target =%5d ps. ", pPars->DelayUser ); printf( "DelayGap =%3d ps. ", pPars->DelayGap ); printf( "Timeout =%4d sec", pPars->TimeOut ); printf( "\n" ); } // prepare the manager; collect init stats p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, pPars->DelayUser, pPars->BuffTreeEst ); p->timeTotal = Abc_Clock(); assert( p->vGatesBest == NULL ); p->vGatesBest = Vec_IntDup( p->pNtk->vGates ); // perform upsizing vNodes = Vec_IntAlloc( 1000 ); vEvals = Vec_IntAlloc( 1000 ); vTryLater = Vec_IntAlloc( 1000 ); for ( i = 0; i < pPars->nIters; i++ ) { int nRounds = 0; int nAttemptAll = 0, nOverlapAll = 0, nChangesAll = 0; Abc_NtkCollectNodesByArea( p, pNtk ); while ( Vec_QueSize(p->vNodeByGain) > 0 ) { int nAttempt = 0, nOverlap = 0, nChanges = 0; Vec_IntClear( vTryLater ); Abc_NtkIncrementTravId( pNtk ); while ( Vec_QueSize(p->vNodeByGain) > 0 ) { clk = Abc_Clock(); pObj = Abc_NtkObj( p->pNtk, Vec_QuePop(p->vNodeByGain) ); Abc_SclFindWindow( pObj, &vNodes, &vEvals ); p->timeCone += Abc_Clock() - clk; if ( Abc_SclCheckOverlap( p->pNtk, vNodes ) ) nOverlap++, Vec_IntPush( vTryLater, Abc_ObjId(pObj) ); else nChanges += Abc_SclCheckImprovement( p, pObj, vNodes, vEvals, pPars->Notches, pPars->DelayGap ); nAttempt++; } Abc_NtkForEachObjVec( vTryLater, pNtk, pObj, k ) Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) ); clk = Abc_Clock(); if ( Vec_IntSize(p->vChanged) ) Abc_SclTimeIncUpdate( p ); else Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, pPars->fUseDept, pPars->DelayUser ); p->timeTime += Abc_Clock() - clk; p->MaxDelay = Abc_SclReadMaxDelay( p ); if ( pPars->fUseDept && pPars->DelayUser > 0 && p->MaxDelay < pPars->DelayUser ) p->MaxDelay = pPars->DelayUser; Abc_SclDnsizePrint( p, nRounds++, nAttempt, nOverlap, nChanges, pPars->fVeryVerbose ); nAttemptAll += nAttempt; nOverlapAll += nOverlap; nChangesAll += nChanges; if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit ) break; } // recompute // Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, pPars->fUseDept, pPars->DelayUser ); if ( pPars->fVerbose ) Abc_SclDnsizePrint( p, -1, nAttemptAll, nOverlapAll, nChangesAll, 1 ); if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit ) break; if ( nAttemptAll == 0 ) break; } Vec_IntFree( vNodes ); Vec_IntFree( vEvals ); Vec_IntFree( vTryLater ); if ( !pPars->fVerbose ) printf( " \r" ); // report runtime p->timeTotal = Abc_Clock() - p->timeTotal; if ( pPars->fVerbose ) { p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime; ABC_PRTP( "Runtime: Critical path", p->timeCone, p->timeTotal ); ABC_PRTP( "Runtime: Sizing eval ", p->timeSize, p->timeTotal ); ABC_PRTP( "Runtime: Timing update", p->timeTime, p->timeTotal ); ABC_PRTP( "Runtime: Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "Runtime: TOTAL ", p->timeTotal, p->timeTotal ); } if ( pPars->fDumpStats ) Abc_SclDumpStats( p, "stats2.txt", p->timeTotal ); if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit ) printf( "Gate sizing timed out at %d seconds.\n", pPars->TimeOut ); // save the result and quit Abc_SclSclGates2MioGates( pLib, pNtk ); // updates gate pointers Abc_SclManFree( p ); // Abc_NtkCleanMarkAB( pNtk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) { Abc_Ntk_t * pNtkNew = pNtk; if ( pNtk->nBarBufs2 > 0 ) pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); Abc_SclDnsizePerformInt( pLib, pNtkNew, pPars ); if ( pNtk->nBarBufs2 > 0 ) Abc_SclTransferGates( pNtk, pNtkNew ); if ( pNtk->nBarBufs2 > 0 ) Abc_NtkDelete( pNtkNew ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclLib.h000066400000000000000000000777751300674244400230020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclLib.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Simplified library representation for STA.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclLib.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__scl__sclLib_h #define ABC__map__scl__sclLib_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "misc/vec/vec.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #define ABC_SCL_CUR_VERSION 8 typedef enum { sc_dir_NULL, sc_dir_Input, sc_dir_Output, sc_dir_InOut, sc_dir_Internal, } SC_Dir; typedef enum // -- timing sense, positive-, negative- or non-unate { sc_ts_NULL, sc_ts_Pos, sc_ts_Neg, sc_ts_Non, } SC_TSense; typedef struct SC_Pair_ SC_Pair; struct SC_Pair_ { float rise; float fall; }; typedef struct SC_PairI_ SC_PairI; struct SC_PairI_ { int rise; int fall; }; typedef struct SC_SizePars_ SC_SizePars; struct SC_SizePars_ { int nIters; int nIterNoChange; int Window; // used for upsizing int Ratio; // used for upsizing int Notches; int DelayUser; int DelayGap; int TimeOut; int BuffTreeEst; // ratio for buffer tree estimation int BypassFreq; // frequency to try bypassing int fUseDept; int fDumpStats; int fUseWireLoads; int fVerbose; int fVeryVerbose; }; typedef struct SC_BusPars_ SC_BusPars; struct SC_BusPars_ { int GainRatio; // target gain int Slew; // target slew int nDegree; // max branching factor int fSizeOnly; // perform only sizing int fAddBufs; // add buffers int fBufPis; // use CI buffering int fUseWireLoads; // wire loads int fVerbose; // verbose int fVeryVerbose; // verbose }; //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct SC_WireLoad_ SC_WireLoad; typedef struct SC_WireLoadSel_ SC_WireLoadSel; typedef struct SC_TableTempl_ SC_TableTempl; typedef struct SC_Surface_ SC_Surface; typedef struct SC_Timing_ SC_Timing; typedef struct SC_Timings_ SC_Timings; typedef struct SC_Pin_ SC_Pin; typedef struct SC_Cell_ SC_Cell; typedef struct SC_Lib_ SC_Lib; struct SC_WireLoad_ { char * pName; float cap; // }- multiply estimation in 'fanout_len[].snd' with this value float slope; // used to extrapolate wireload for large fanout count Vec_Int_t vFanout; // Vec > -- pairs '(#fanouts, est-wire-len)' Vec_Flt_t vLen; }; struct SC_WireLoadSel_ { char * pName; Vec_Flt_t vAreaFrom; // Vec > -- triplets '(from-area, upto-area, wire-load-model)'; range is [from, upto[ Vec_Flt_t vAreaTo; Vec_Ptr_t vWireLoadModel; }; struct SC_TableTempl_ { char * pName; Vec_Ptr_t vVars; // Vec -- name of variable (numbered from 0, not 1 as in the Liberty file) Vec_Ptr_t vIndex; // Vec > -- this is the point of measurement in table for the given variable }; struct SC_Surface_ { char * pName; Vec_Flt_t vIndex0; // Vec -- correspondes to "index_1" in the liberty file (for timing: slew) Vec_Flt_t vIndex1; // Vec -- correspondes to "index_2" in the liberty file (for timing: load) Vec_Ptr_t vData; // Vec > -- 'data[i0][i1]' gives value at '(index0[i0], index1[i1])' Vec_Int_t vIndex0I; // Vec -- correspondes to "index_1" in the liberty file (for timing: slew) Vec_Int_t vIndex1I; // Vec -- correspondes to "index_2" in the liberty file (for timing: load) Vec_Ptr_t vDataI; // Vec > -- 'data[i0][i1]' gives value at '(index0[i0], index1[i1])' float approx[3][6]; }; struct SC_Timing_ { char * related_pin; // -- related pin SC_TSense tsense; // -- timing sense (positive_unate, negative_unate, non_unate) char * when_text; // -- logic condition on inputs triggering this delay model for the output (currently not used) SC_Surface pCellRise; // -- Used to compute pin-to-pin delay SC_Surface pCellFall; SC_Surface pRiseTrans; // -- Used to compute output slew SC_Surface pFallTrans; }; struct SC_Timings_ { char * pName; // -- the 'related_pin' field Vec_Ptr_t vTimings; // structures of type SC_Timing }; struct SC_Pin_ { char * pName; SC_Dir dir; float cap; // -- this value is used if 'rise_cap' and 'fall_cap' is missing (copied by 'postProcess()'). (not used) float rise_cap; // }- used for input pins ('cap' too). float fall_cap; // } int rise_capI; // }- used for input pins ('cap' too). int fall_capI; // } float max_out_cap; // } (not used) float max_out_slew; // }- used only for output pins (max values must not be exceeded or else mapping is illegal) (not used) char * func_text; // } Vec_Wrd_t vFunc; // } Vec_Ptr_t vRTimings; // -- for output pins // SC_Timing Timing; // -- for output pins }; struct SC_Cell_ { char * pName; int Id; int fSkip; // skip this cell during genlib computation int seq; // -- set to TRUE by parser if a sequential element int unsupp; // -- set to TRUE by parser if cell contains information we cannot handle float area; float leakage; int areaI; int leakageI; int drive_strength; // -- some library files provide this field (currently unused, but may be a good hint for sizing) (not used) Vec_Ptr_t vPins; // NamedSet int n_inputs; // -- 'pins[0 .. n_inputs-1]' are input pins int n_outputs; // -- 'pins[n_inputs .. n_inputs+n_outputs-1]' are output pins SC_Cell * pNext; // same-functionality cells linked into a ring by area SC_Cell * pPrev; // same-functionality cells linked into a ring by area SC_Cell * pRepr; // representative of the class SC_Cell * pAve; // average size cell of this class int Order; // order of the gate in the list int nGates; // the number of gates in the list }; struct SC_Lib_ { char * pName; char * pFileName; char * default_wire_load; char * default_wire_load_sel; float default_max_out_slew; // -- 'default_max_transition'; this is copied to each output pin where 'max_transition' is not defined (not used) int unit_time; // -- Valid 9..12. Unit is '10^(-val)' seconds (e.g. 9=1ns, 10=100ps, 11=10ps, 12=1ps) float unit_cap_fst; // -- First part is a multiplier, second either 12 or 15 for 'pf' or 'ff'. int unit_cap_snd; Vec_Ptr_t vWireLoads; // NamedSet Vec_Ptr_t vWireLoadSels; // NamedSet Vec_Ptr_t vTempls; // NamedSet Vec_Ptr_t vCells; // NamedSet Vec_Ptr_t vCellClasses; // NamedSet int * pBins; // hashing gateName -> gateId int nBins; }; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline void SC_PairClean( SC_Pair * d ) { d->rise = d->fall = 0; } static inline float SC_PairMax( SC_Pair * d ) { return Abc_MaxFloat(d->rise, d->fall); } static inline float SC_PairMin( SC_Pair * d ) { return Abc_MinFloat(d->rise, d->fall); } static inline float SC_PairAve( SC_Pair * d ) { return 0.5 * d->rise + 0.5 * d->fall; } static inline void SC_PairDup( SC_Pair * d, SC_Pair * s ) { *d = *s; } static inline void SC_PairMove( SC_Pair * d, SC_Pair * s ) { *d = *s; s->rise = s->fall = 0; } static inline void SC_PairAdd( SC_Pair * d, SC_Pair * s ) { d->rise += s->rise; d->fall += s->fall;} static inline int SC_PairEqual( SC_Pair * d, SC_Pair * s ) { return d->rise == s->rise && d->fall == s->fall; } static inline int SC_PairEqualE( SC_Pair * d, SC_Pair * s, float E ) { return d->rise - s->rise < E && s->rise - d->rise < E && d->fall - s->fall < E && s->fall - d->fall < E; } static inline int SC_LibCellNum( SC_Lib * p ) { return Vec_PtrSize(&p->vCells); } static inline SC_Cell * SC_LibCell( SC_Lib * p, int i ) { return (SC_Cell *)Vec_PtrEntry(&p->vCells, i); } static inline SC_Pin * SC_CellPin( SC_Cell * p, int i ) { return (SC_Pin *)Vec_PtrEntry(&p->vPins, i); } static inline Vec_Wrd_t * SC_CellFunc( SC_Cell * p ) { return &SC_CellPin(p, p->n_inputs)->vFunc; } static inline float SC_CellPinCap( SC_Cell * p, int i ) { return 0.5 * SC_CellPin(p, i)->rise_cap + 0.5 * SC_CellPin(p, i)->fall_cap; } static inline float SC_CellPinCapAve( SC_Cell * p ) { int i; float c = 0; for (i = 0; i < p->n_inputs; i++) c += SC_CellPinCap(p, i); return c / Abc_MaxInt(1, p->n_inputs); } static inline char * SC_CellPinOutFunc( SC_Cell * p, int i ) { return SC_CellPin(p, p->n_inputs + i)->func_text; } static inline char * SC_CellPinName( SC_Cell * p, int i ) { return SC_CellPin(p, i)->pName; } #define SC_LibForEachCell( p, pCell, i ) Vec_PtrForEachEntry( SC_Cell *, &p->vCells, pCell, i ) #define SC_LibForEachCellClass( p, pCell, i ) Vec_PtrForEachEntry( SC_Cell *, &p->vCellClasses, pCell, i ) #define SC_LibForEachWireLoad( p, pWL, i ) Vec_PtrForEachEntry( SC_WireLoad *, &p->vWireLoads, pWL, i ) #define SC_LibForEachWireLoadSel( p, pWLS, i ) Vec_PtrForEachEntry( SC_WireLoadSel *, &p->vWireLoadSels, pWLS, i ) #define SC_LibForEachTempl( p, pTempl, i ) Vec_PtrForEachEntry( SC_TableTempl *, &p->vTempls, pTempl, i ) #define SC_CellForEachPin( p, pPin, i ) Vec_PtrForEachEntry( SC_Pin *, &p->vPins, pPin, i ) #define SC_CellForEachPinIn( p, pPin, i ) Vec_PtrForEachEntryStop( SC_Pin *, &p->vPins, pPin, i, p->n_inputs ) #define SC_CellForEachPinOut( p, pPin, i ) Vec_PtrForEachEntryStart( SC_Pin *, &p->vPins, pPin, i, p->n_inputs ) #define SC_RingForEachCell( pRing, pCell, i ) for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pNext, i++ ) #define SC_RingForEachCellRev( pRing, pCell, i ) for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pPrev, i++ ) #define SC_PinForEachRTiming( p, pRTime, i ) Vec_PtrForEachEntry( SC_Timings *, &p->vRTimings, pRTime, i ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Constructors of the library data-structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline SC_WireLoad * Abc_SclWireLoadAlloc() { SC_WireLoad * p; p = ABC_CALLOC( SC_WireLoad, 1 ); return p; } static inline SC_WireLoadSel * Abc_SclWireLoadSelAlloc() { SC_WireLoadSel * p; p = ABC_CALLOC( SC_WireLoadSel, 1 ); return p; } static inline SC_TableTempl * Abc_SclTableTemplAlloc() { SC_TableTempl * p; p = ABC_CALLOC( SC_TableTempl, 1 ); return p; } static inline SC_Surface * Abc_SclSurfaceAlloc() { SC_Surface * p; p = ABC_CALLOC( SC_Surface, 1 ); return p; } static inline SC_Timing * Abc_SclTimingAlloc() { SC_Timing * p; p = ABC_CALLOC( SC_Timing, 1 ); return p; } static inline SC_Timings * Abc_SclTimingsAlloc() { SC_Timings * p; p = ABC_CALLOC( SC_Timings, 1 ); return p; } static inline SC_Pin * Abc_SclPinAlloc() { SC_Pin * p; p = ABC_CALLOC( SC_Pin, 1 ); p->max_out_slew = -1; return p; } static inline SC_Cell * Abc_SclCellAlloc() { SC_Cell * p; p = ABC_CALLOC( SC_Cell, 1 ); return p; } static inline SC_Lib * Abc_SclLibAlloc() { SC_Lib * p; p = ABC_CALLOC( SC_Lib, 1 ); p->default_max_out_slew = -1; p->unit_time = 9; p->unit_cap_fst = 1; p->unit_cap_snd = 12; return p; } /**Function************************************************************* Synopsis [Destructors of the library data-structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_SclWireLoadFree( SC_WireLoad * p ) { Vec_IntErase( &p->vFanout ); Vec_FltErase( &p->vLen ); ABC_FREE( p->pName ); ABC_FREE( p ); } static inline void Abc_SclWireLoadSelFree( SC_WireLoadSel * p ) { Vec_FltErase( &p->vAreaFrom ); Vec_FltErase( &p->vAreaTo ); Vec_PtrFreeData( &p->vWireLoadModel ); ABC_FREE( p->pName ); ABC_FREE( p ); } static inline void Abc_SclTableTemplFree( SC_TableTempl * p ) { Vec_PtrFreeData( &p->vVars ); Vec_VecErase( (Vec_Vec_t *)&p->vIndex ); ABC_FREE( p->pName ); ABC_FREE( p ); } static inline void Abc_SclSurfaceFree( SC_Surface * p ) { Vec_FltErase( &p->vIndex0 ); Vec_FltErase( &p->vIndex1 ); Vec_IntErase( &p->vIndex0I ); Vec_IntErase( &p->vIndex1I ); Vec_VecErase( (Vec_Vec_t *)&p->vData ); Vec_VecErase( (Vec_Vec_t *)&p->vDataI ); ABC_FREE( p->pName ); // ABC_FREE( p ); } static inline void Abc_SclTimingFree( SC_Timing * p ) { Abc_SclSurfaceFree( &p->pCellRise ); Abc_SclSurfaceFree( &p->pCellFall ); Abc_SclSurfaceFree( &p->pRiseTrans ); Abc_SclSurfaceFree( &p->pFallTrans ); ABC_FREE( p->related_pin ); ABC_FREE( p->when_text ); ABC_FREE( p ); } static inline void Abc_SclTimingsFree( SC_Timings * p ) { SC_Timing * pTemp; int i; Vec_PtrForEachEntry( SC_Timing *, &p->vTimings, pTemp, i ) Abc_SclTimingFree( pTemp ); Vec_PtrErase( &p->vTimings ); ABC_FREE( p->pName ); ABC_FREE( p ); } static inline void Abc_SclPinFree( SC_Pin * p ) { SC_Timings * pTemp; int i; SC_PinForEachRTiming( p, pTemp, i ) Abc_SclTimingsFree( pTemp ); Vec_PtrErase( &p->vRTimings ); Vec_WrdErase( &p->vFunc ); ABC_FREE( p->func_text ); ABC_FREE( p->pName ); ABC_FREE( p ); } static inline void Abc_SclCellFree( SC_Cell * p ) { SC_Pin * pTemp; int i; SC_CellForEachPin( p, pTemp, i ) Abc_SclPinFree( pTemp ); Vec_PtrErase( &p->vPins ); ABC_FREE( p->pName ); ABC_FREE( p ); } static inline void Abc_SclLibFree( SC_Lib * p ) { SC_WireLoad * pWL; SC_WireLoadSel * pWLS; SC_TableTempl * pTempl; SC_Cell * pCell; int i; SC_LibForEachWireLoad( p, pWL, i ) Abc_SclWireLoadFree( pWL ); Vec_PtrErase( &p->vWireLoads ); SC_LibForEachWireLoadSel( p, pWLS, i ) Abc_SclWireLoadSelFree( pWLS ); Vec_PtrErase( &p->vWireLoadSels ); SC_LibForEachTempl( p, pTempl, i ) Abc_SclTableTemplFree( pTempl ); Vec_PtrErase( &p->vTempls ); SC_LibForEachCell( p, pCell, i ) Abc_SclCellFree( pCell ); Vec_PtrErase( &p->vCells ); Vec_PtrErase( &p->vCellClasses ); ABC_FREE( p->pName ); ABC_FREE( p->pFileName ); ABC_FREE( p->default_wire_load ); ABC_FREE( p->default_wire_load_sel ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Lookup table delay computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Scl_LibLookup( SC_Surface * p, float slew, float load ) { float * pIndex0, * pIndex1, * pDataS, * pDataS1; float sfrac, lfrac, p0, p1; int s, l; // handle constant table if ( Vec_FltSize(&p->vIndex0) == 1 && Vec_FltSize(&p->vIndex1) == 1 ) { Vec_Flt_t * vTemp = (Vec_Flt_t *)Vec_PtrEntry(&p->vData, 0); assert( Vec_PtrSize(&p->vData) == 1 ); assert( Vec_FltSize(vTemp) == 1 ); return Vec_FltEntry(vTemp, 0); } // Find closest sample points in surface: pIndex0 = Vec_FltArray(&p->vIndex0); for ( s = 1; s < Vec_FltSize(&p->vIndex0)-1; s++ ) if ( pIndex0[s] > slew ) break; s--; pIndex1 = Vec_FltArray(&p->vIndex1); for ( l = 1; l < Vec_FltSize(&p->vIndex1)-1; l++ ) if ( pIndex1[l] > load ) break; l--; // Interpolate (or extrapolate) function value from sample points: sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]); lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]); pDataS = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(&p->vData, s) ); pDataS1 = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(&p->vData, s+1) ); p0 = pDataS [l] + lfrac * (pDataS [l+1] - pDataS [l]); p1 = pDataS1[l] + lfrac * (pDataS1[l+1] - pDataS1[l]); return p0 + sfrac * (p1 - p0); // <<== multiply result with K factor here } static inline void Scl_LibPinArrival( SC_Timing * pTime, SC_Pair * pArrIn, SC_Pair * pSlewIn, SC_Pair * pLoad, SC_Pair * pArrOut, SC_Pair * pSlewOut ) { if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) { pArrOut->rise = Abc_MaxFloat( pArrOut->rise, pArrIn->rise + Scl_LibLookup(&pTime->pCellRise, pSlewIn->rise, pLoad->rise) ); pArrOut->fall = Abc_MaxFloat( pArrOut->fall, pArrIn->fall + Scl_LibLookup(&pTime->pCellFall, pSlewIn->fall, pLoad->fall) ); pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise, Scl_LibLookup(&pTime->pRiseTrans, pSlewIn->rise, pLoad->rise) ); pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall, Scl_LibLookup(&pTime->pFallTrans, pSlewIn->fall, pLoad->fall) ); } if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) { pArrOut->rise = Abc_MaxFloat( pArrOut->rise, pArrIn->fall + Scl_LibLookup(&pTime->pCellRise, pSlewIn->fall, pLoad->rise) ); pArrOut->fall = Abc_MaxFloat( pArrOut->fall, pArrIn->rise + Scl_LibLookup(&pTime->pCellFall, pSlewIn->rise, pLoad->fall) ); pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise, Scl_LibLookup(&pTime->pRiseTrans, pSlewIn->fall, pLoad->rise) ); pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall, Scl_LibLookup(&pTime->pFallTrans, pSlewIn->rise, pLoad->fall) ); } } static inline void Scl_LibPinDeparture( SC_Timing * pTime, SC_Pair * pDepIn, SC_Pair * pSlewIn, SC_Pair * pLoad, SC_Pair * pDepOut ) { if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) { pDepIn->rise = Abc_MaxFloat( pDepIn->rise, pDepOut->rise + Scl_LibLookup(&pTime->pCellRise, pSlewIn->rise, pLoad->rise) ); pDepIn->fall = Abc_MaxFloat( pDepIn->fall, pDepOut->fall + Scl_LibLookup(&pTime->pCellFall, pSlewIn->fall, pLoad->fall) ); } if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) { pDepIn->fall = Abc_MaxFloat( pDepIn->fall, pDepOut->rise + Scl_LibLookup(&pTime->pCellRise, pSlewIn->fall, pLoad->rise) ); pDepIn->rise = Abc_MaxFloat( pDepIn->rise, pDepOut->fall + Scl_LibLookup(&pTime->pCellFall, pSlewIn->rise, pLoad->fall) ); } } /**Function************************************************************* Synopsis [Lookup table delay computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Scl_LibLookupI( SC_Surface * p, int slew, int load ) { int * pIndex0, * pIndex1, * pDataS, * pDataS1; int p0, p1, s, l; iword lFrac0, lFrac1, sFrac; // handle constant table if ( Vec_IntSize(&p->vIndex0I) == 1 && Vec_IntSize(&p->vIndex1I) == 1 ) { Vec_Int_t * vTemp = (Vec_Int_t *)Vec_PtrEntry(&p->vDataI, 0); assert( Vec_PtrSize(&p->vDataI) == 1 ); assert( Vec_IntSize(vTemp) == 1 ); return Vec_IntEntry(vTemp, 0); } // Find closest sample points in surface: pIndex0 = Vec_IntArray(&p->vIndex0I); for ( s = 1; s < Vec_IntSize(&p->vIndex0I)-1; s++ ) if ( pIndex0[s] > slew ) break; s--; pIndex1 = Vec_IntArray(&p->vIndex1I); for ( l = 1; l < Vec_IntSize(&p->vIndex1I)-1; l++ ) if ( pIndex1[l] > load ) break; l--; pDataS = Vec_IntArray( (Vec_Int_t *)Vec_PtrEntry(&p->vDataI, s) ); pDataS1 = Vec_IntArray( (Vec_Int_t *)Vec_PtrEntry(&p->vDataI, s+1) ); // Interpolate (or extrapolate) function value from sample points: // lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]); // sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]); lFrac0 = (iword)(pDataS [l+1] - pDataS [l]) * (iword)(load - pIndex1[l]) / (iword)(pIndex1[l+1] - pIndex1[l]); lFrac1 = (iword)(pDataS1[l+1] - pDataS1[l]) * (iword)(load - pIndex1[l]) / (iword)(pIndex1[l+1] - pIndex1[l]); // p0 = pDataS [l] + lfrac * (pDataS [l+1] - pDataS [l]); // p1 = pDataS1[l] + lfrac * (pDataS1[l+1] - pDataS1[l]); p0 = pDataS [l] + (int)lFrac0; p1 = pDataS1[l] + (int)lFrac1; sFrac = (iword)(p1 - p0) * (iword)(slew - pIndex0[s]) / (iword)(pIndex0[s+1] - pIndex0[s]); // return p0 + sfrac * (p1 - p0); return p0 + (int)sFrac; } static inline void Scl_LibPinArrivalI( SC_Timing * pTime, SC_PairI * pArrIn, SC_PairI * pSlewIn, SC_PairI * pLoad, SC_PairI * pArrOut, SC_PairI * pSlewOut, int * pArray ) { if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) { pArrOut->rise = Abc_MaxInt( pArrOut->rise, pArrIn->rise + (pArray[0] = Scl_LibLookupI(&pTime->pCellRise, pSlewIn->rise, pLoad->rise)) ); pArrOut->fall = Abc_MaxInt( pArrOut->fall, pArrIn->fall + (pArray[1] = Scl_LibLookupI(&pTime->pCellFall, pSlewIn->fall, pLoad->fall)) ); pSlewOut->rise = Abc_MaxInt( pSlewOut->rise, Scl_LibLookupI(&pTime->pRiseTrans, pSlewIn->rise, pLoad->rise) ); pSlewOut->fall = Abc_MaxInt( pSlewOut->fall, Scl_LibLookupI(&pTime->pFallTrans, pSlewIn->fall, pLoad->fall) ); } if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) { pArrOut->rise = Abc_MaxInt( pArrOut->rise, pArrIn->fall + (pArray[2] = Scl_LibLookupI(&pTime->pCellRise, pSlewIn->fall, pLoad->rise)) ); pArrOut->fall = Abc_MaxInt( pArrOut->fall, pArrIn->rise + (pArray[3] = Scl_LibLookupI(&pTime->pCellFall, pSlewIn->rise, pLoad->fall)) ); pSlewOut->rise = Abc_MaxInt( pSlewOut->rise, Scl_LibLookupI(&pTime->pRiseTrans, pSlewIn->fall, pLoad->rise) ); pSlewOut->fall = Abc_MaxInt( pSlewOut->fall, Scl_LibLookupI(&pTime->pFallTrans, pSlewIn->rise, pLoad->fall) ); } } static inline void Scl_LibPinRequiredI( SC_Timing * pTime, SC_PairI * pReqIn, SC_PairI * pReqOut, int * pArray ) { if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) { pReqIn->rise = Abc_MinInt( pReqIn->rise, pReqOut->rise - pArray[0] ); pReqIn->fall = Abc_MinInt( pReqIn->fall, pReqOut->fall - pArray[1] ); } if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) { pReqIn->fall = Abc_MinInt( pReqIn->fall, pReqOut->rise - pArray[2] ); pReqIn->rise = Abc_MinInt( pReqIn->rise, pReqOut->fall - pArray[3] ); } } /**Function************************************************************* Synopsis [Compute one timing edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin ) { SC_Pin * pPin; SC_Timings * pRTime; assert( iPin >= 0 && iPin < pCell->n_inputs ); pPin = SC_CellPin( pCell, pCell->n_inputs ); assert( Vec_PtrSize(&pPin->vRTimings) == pCell->n_inputs ); pRTime = (SC_Timings *)Vec_PtrEntry( &pPin->vRTimings, iPin ); if ( Vec_PtrSize(&pRTime->vTimings) == 0 ) return NULL; assert( Vec_PtrSize(&pRTime->vTimings) == 1 ); return (SC_Timing *)Vec_PtrEntry( &pRTime->vTimings, 0 ); } static inline float Scl_LibPinArrivalEstimate( SC_Cell * pCell, int iPin, float Slew, float Load ) { SC_Pair LoadIn = { Load, Load }; SC_Pair ArrIn = { 0.0, 0.0 }; SC_Pair ArrOut = { 0.0, 0.0 }; SC_Pair SlewIn = { 0.0, 0.0 }; SC_Pair SlewOut = { 0.0, 0.0 }; // Vec_Flt_t * vIndex0 = pTime->pCellRise->vIndex0; // slew // SlewIn.fall = SlewIn.rise = Vec_FltEntry( vIndex0, Vec_FltSize(vIndex0)/2 ); SlewIn.fall = SlewIn.rise = Slew; Scl_LibPinArrival( Scl_CellPinTime(pCell, iPin), &ArrIn, &SlewIn, &LoadIn, &ArrOut, &SlewOut ); return 0.5 * ArrOut.fall + 0.5 * ArrOut.rise; } static inline void Scl_LibHandleInputDriver( SC_Cell * pCell, SC_Pair * pLoadIn, SC_Pair * pArrOut, SC_Pair * pSlewOut ) { SC_Pair LoadIn = { 0.0, 0.0 }; // zero input load SC_Pair ArrIn = { 0.0, 0.0 }; // zero input time SC_Pair SlewIn = { 0.0, 0.0 }; // zero input slew SC_Pair ArrOut0 = { 0.0, 0.0 }; // output time under zero load SC_Pair ArrOut1 = { 0.0, 0.0 }; // output time under given load SC_Pair SlewOut = { 0.0, 0.0 }; // output slew under zero load pSlewOut->fall = pSlewOut->rise = 0; assert( pCell->n_inputs == 1 ); Scl_LibPinArrival( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, &LoadIn, &ArrOut0, &SlewOut ); Scl_LibPinArrival( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, pLoadIn, &ArrOut1, pSlewOut ); pArrOut->fall = ArrOut1.fall - ArrOut0.fall; pArrOut->rise = ArrOut1.rise - ArrOut0.rise; } /**Function************************************************************* Synopsis [Compute one timing edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Scl_LibPinArrivalEstimateI( SC_Cell * pCell, int iPin, int Slew, int Load ) { int Arrray[4]; SC_PairI LoadIn = { Load, Load }; SC_PairI ArrIn = { 0, 0 }; SC_PairI ArrOut = { 0, 0 }; SC_PairI SlewIn = { 0, 0 }; SC_PairI SlewOut = { 0, 0 }; // Vec_Flt_t * vIndex0 = pTime->pCellRise->vIndex0; // slew // SlewIn.fall = SlewIn.rise = Vec_FltEntry( vIndex0, Vec_FltSize(vIndex0)/2 ); SlewIn.fall = SlewIn.rise = Slew; Scl_LibPinArrivalI( Scl_CellPinTime(pCell, iPin), &ArrIn, &SlewIn, &LoadIn, &ArrOut, &SlewOut, Arrray ); return (ArrOut.fall + ArrOut.rise) >> 1; } static inline void Scl_LibHandleInputDriver2( SC_Cell * pCell, SC_PairI * pLoadIn, SC_PairI * pArrOut, SC_PairI * pSlewOut ) { int Arrray[4]; SC_PairI LoadIn = { 0, 0 }; // zero input load SC_PairI ArrIn = { 0, 0 }; // zero input time SC_PairI SlewIn = { 0, 0 }; // zero input slew SC_PairI ArrOut0 = { 0, 0 }; // output time under zero load SC_PairI ArrOut1 = { 0, 0 }; // output time under given load SC_PairI SlewOut = { 0, 0 }; // output slew under zero load pSlewOut->fall = pSlewOut->rise = 0; assert( pCell->n_inputs == 1 ); Scl_LibPinArrivalI( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, &LoadIn, &ArrOut0, &SlewOut, Arrray ); Scl_LibPinArrivalI( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, pLoadIn, &ArrOut1, pSlewOut, Arrray ); pArrOut->fall = ArrOut1.fall - ArrOut0.fall; pArrOut->rise = ArrOut1.rise - ArrOut0.rise; } /*=== sclLiberty.c ===============================================================*/ extern SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose ); /*=== sclLibScl.c ===============================================================*/ extern SC_Lib * Abc_SclReadFromGenlib( void * pLib ); extern SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut ); extern SC_Lib * Abc_SclReadFromFile( char * pFileName ); extern void Abc_SclWriteScl( char * pFileName, SC_Lib * p ); extern void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p ); /*=== sclLibUtil.c ===============================================================*/ extern void Abc_SclHashCells( SC_Lib * p ); extern int Abc_SclCellFind( SC_Lib * p, char * pName ); extern int Abc_SclClassCellNum( SC_Cell * pClass ); extern void Abc_SclShortNames( SC_Lib * p ); extern int Abc_SclLibClassNum( SC_Lib * pLib ); extern void Abc_SclLinkCells( SC_Lib * p ); extern void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain, int fInvOnly, int fShort ); extern void Abc_SclConvertLeakageIntoArea( SC_Lib * p, float A, float B ); extern void Abc_SclLibNormalize( SC_Lib * p ); extern SC_Cell * Abc_SclFindInvertor( SC_Lib * p, int fFindBuff ); extern SC_Cell * Abc_SclFindSmallestGate( SC_Cell * p, float CinMin ); extern SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area ); extern SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pName ); extern int Abc_SclHasDelayInfo( void * pScl ); extern float Abc_SclComputeAverageSlew( SC_Lib * p ); extern void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float Slew, float Gain, int nGatesMin ); extern void Abc_SclInstallGenlib( void * pScl, float Slew, float Gain, int nGatesMin ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclLibScl.c000066400000000000000000000750051300674244400234170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclLibScl.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Liberty abstraction for delay-oriented mapping.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclLibScl.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclLib.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "bool/kit/kit.h" #include "misc/extra/extra.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reading library from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_SclReadSurfaceGenlib( SC_Surface * p ) { Vec_Flt_t * vVec; Vec_Int_t * vVecI; int i, j; Vec_FltPush( &p->vIndex0, 0 ); Vec_IntPush( &p->vIndex0I, Scl_Flt2Int(0) ); Vec_FltPush( &p->vIndex1, 0 ); Vec_IntPush( &p->vIndex1I, Scl_Flt2Int(0) ); for ( i = 0; i < Vec_FltSize(&p->vIndex0); i++ ) { vVec = Vec_FltAlloc( Vec_FltSize(&p->vIndex1) ); Vec_PtrPush( &p->vData, vVec ); vVecI = Vec_IntAlloc( Vec_FltSize(&p->vIndex1) ); Vec_PtrPush( &p->vDataI, vVecI ); for ( j = 0; j < Vec_FltSize(&p->vIndex1); j++ ) { Vec_FltPush( vVec, 1 ); Vec_IntPush( vVecI, Scl_Flt2Int(1) ); } } } static int Abc_SclReadLibraryGenlib( SC_Lib * p, Mio_Library_t * pLib ) { Mio_Gate_t * pGate; Mio_Pin_t * pGatePin; int j, k; // Read non-composite fields: p->pName = Abc_UtilStrsav( Mio_LibraryReadName(pLib) ); p->default_wire_load = 0; p->default_wire_load_sel = 0; p->default_max_out_slew = 0; p->unit_time = 12; p->unit_cap_fst = 1.0; p->unit_cap_snd = 15; Mio_LibraryForEachGate( pLib, pGate ) { SC_Cell * pCell = Abc_SclCellAlloc(); pCell->Id = SC_LibCellNum(p); Vec_PtrPush( &p->vCells, pCell ); pCell->pName = Abc_UtilStrsav( Mio_GateReadName( pGate ) ); pCell->area = Mio_GateReadArea( pGate ); pCell->leakage = 0; pCell->drive_strength = 0; pCell->n_inputs = Mio_GateReadPinNum( pGate ); pCell->n_outputs = 1; pCell->areaI = Scl_Flt2Int(pCell->area); pCell->leakageI = Scl_Flt2Int(pCell->leakage); Mio_GateForEachPin( pGate, pGatePin ) { SC_Pin * pPin = Abc_SclPinAlloc(); Vec_PtrPush( &pCell->vPins, pPin ); pPin->dir = sc_dir_Input; pPin->pName = Abc_UtilStrsav( Mio_PinReadName( pGatePin ) ); pPin->rise_cap = 0; pPin->fall_cap = 0; pPin->rise_capI = Scl_Flt2Int(pPin->rise_cap); pPin->fall_capI = Scl_Flt2Int(pPin->fall_cap); } for ( j = 0; j < pCell->n_outputs; j++ ) { word * pTruth = Mio_GateReadTruthP( pGate ); SC_Pin * pPin = Abc_SclPinAlloc(); Vec_PtrPush( &pCell->vPins, pPin ); pPin->dir = sc_dir_Output; pPin->pName = Abc_UtilStrsav( Mio_GateReadOutName( pGate ) ); pPin->max_out_cap = 0; pPin->max_out_slew = 0; // read function pPin->func_text = Abc_UtilStrsav( Mio_GateReadForm( pGate ) ); Vec_WrdGrow( &pPin->vFunc, Abc_Truth6WordNum(pCell->n_inputs) ); for ( k = 0; k < Vec_WrdCap(&pPin->vFunc); k++ ) Vec_WrdPush( &pPin->vFunc, pTruth[k] ); // read pins Mio_GateForEachPin( pGate, pGatePin ) { Mio_PinPhase_t Value = Mio_PinReadPhase( pGatePin ); SC_Timings * pRTime = Abc_SclTimingsAlloc(); Vec_PtrPush( &pPin->vRTimings, pRTime ); pRTime->pName = Abc_UtilStrsav( Mio_PinReadName( pGatePin ) ); if ( 1 ) { SC_Timing * pTime = Abc_SclTimingAlloc(); Vec_PtrPush( &pRTime->vTimings, pTime ); if ( Value == MIO_PHASE_UNKNOWN ) pTime->tsense = (SC_TSense)sc_ts_Non; else if ( Value == MIO_PHASE_INV ) pTime->tsense = (SC_TSense)sc_ts_Neg; else if ( Value == MIO_PHASE_NONINV ) pTime->tsense = (SC_TSense)sc_ts_Pos; else assert( 0 ); Abc_SclReadSurfaceGenlib( &pTime->pCellRise ); Abc_SclReadSurfaceGenlib( &pTime->pCellFall ); Abc_SclReadSurfaceGenlib( &pTime->pRiseTrans ); Abc_SclReadSurfaceGenlib( &pTime->pFallTrans ); } } } } return 1; } SC_Lib * Abc_SclReadFromGenlib( void * pLib0 ) { Mio_Library_t * pLib = (Mio_Library_t *)pLib0; SC_Lib * p = Abc_SclLibAlloc(); if ( !Abc_SclReadLibraryGenlib( p, pLib ) ) return NULL; // hash gates by name Abc_SclHashCells( p ); Abc_SclLinkCells( p ); return p; } /**Function************************************************************* Synopsis [Reading library from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_SclReadSurface( Vec_Str_t * vOut, int * pPos, SC_Surface * p ) { Vec_Flt_t * vVec; Vec_Int_t * vVecI; int i, j; for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) { float Num = Vec_StrGetF(vOut, pPos); Vec_FltPush( &p->vIndex0, Num ); Vec_IntPush( &p->vIndex0I, Scl_Flt2Int(Num) ); } for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) { float Num = Vec_StrGetF(vOut, pPos); Vec_FltPush( &p->vIndex1, Num ); Vec_IntPush( &p->vIndex1I, Scl_Flt2Int(Num) ); } for ( i = 0; i < Vec_FltSize(&p->vIndex0); i++ ) { vVec = Vec_FltAlloc( Vec_FltSize(&p->vIndex1) ); Vec_PtrPush( &p->vData, vVec ); vVecI = Vec_IntAlloc( Vec_FltSize(&p->vIndex1) ); Vec_PtrPush( &p->vDataI, vVecI ); for ( j = 0; j < Vec_FltSize(&p->vIndex1); j++ ) { float Num = Vec_StrGetF(vOut, pPos); Vec_FltPush( vVec, Num ); Vec_IntPush( vVecI, Scl_Flt2Int(Num) ); } } for ( i = 0; i < 3; i++ ) p->approx[0][i] = Vec_StrGetF( vOut, pPos ); for ( i = 0; i < 4; i++ ) p->approx[1][i] = Vec_StrGetF( vOut, pPos ); for ( i = 0; i < 6; i++ ) p->approx[2][i] = Vec_StrGetF( vOut, pPos ); } static int Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p ) { int i, j, k, n; int version = Vec_StrGetI( vOut, pPos ); if ( version != ABC_SCL_CUR_VERSION ) { Abc_Print( -1, "Wrong version of the SCL file.\n" ); return 0; } assert( version == ABC_SCL_CUR_VERSION ); // wrong version of the file // Read non-composite fields: p->pName = Vec_StrGetS(vOut, pPos); p->default_wire_load = Vec_StrGetS(vOut, pPos); p->default_wire_load_sel = Vec_StrGetS(vOut, pPos); p->default_max_out_slew = Vec_StrGetF(vOut, pPos); p->unit_time = Vec_StrGetI(vOut, pPos); p->unit_cap_fst = Vec_StrGetF(vOut, pPos); p->unit_cap_snd = Vec_StrGetI(vOut, pPos); // Read 'wire_load' vector: for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) { SC_WireLoad * pWL = Abc_SclWireLoadAlloc(); Vec_PtrPush( &p->vWireLoads, pWL ); pWL->pName = Vec_StrGetS(vOut, pPos); pWL->cap = Vec_StrGetF(vOut, pPos); pWL->slope = Vec_StrGetF(vOut, pPos); for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- ) { Vec_IntPush( &pWL->vFanout, Vec_StrGetI(vOut, pPos) ); Vec_FltPush( &pWL->vLen, Vec_StrGetF(vOut, pPos) ); } } // Read 'wire_load_sel' vector: for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) { SC_WireLoadSel * pWLS = Abc_SclWireLoadSelAlloc(); Vec_PtrPush( &p->vWireLoadSels, pWLS ); pWLS->pName = Vec_StrGetS(vOut, pPos); for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- ) { Vec_FltPush( &pWLS->vAreaFrom, Vec_StrGetF(vOut, pPos) ); Vec_FltPush( &pWLS->vAreaTo, Vec_StrGetF(vOut, pPos) ); Vec_PtrPush( &pWLS->vWireLoadModel, Vec_StrGetS(vOut, pPos) ); } } for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) { SC_Cell * pCell = Abc_SclCellAlloc(); pCell->Id = SC_LibCellNum(p); Vec_PtrPush( &p->vCells, pCell ); pCell->pName = Vec_StrGetS(vOut, pPos); pCell->area = Vec_StrGetF(vOut, pPos); pCell->leakage = Vec_StrGetF(vOut, pPos); pCell->drive_strength = Vec_StrGetI(vOut, pPos); pCell->n_inputs = Vec_StrGetI(vOut, pPos); pCell->n_outputs = Vec_StrGetI(vOut, pPos); pCell->areaI = Scl_Flt2Int(pCell->area); pCell->leakageI = Scl_Flt2Int(pCell->leakage); /* printf( "%s\n", pCell->pName ); if ( !strcmp( "XOR3_X4M_A9TL", pCell->pName ) ) { int s = 0; } */ for ( j = 0; j < pCell->n_inputs; j++ ) { SC_Pin * pPin = Abc_SclPinAlloc(); Vec_PtrPush( &pCell->vPins, pPin ); pPin->dir = sc_dir_Input; pPin->pName = Vec_StrGetS(vOut, pPos); pPin->rise_cap = Vec_StrGetF(vOut, pPos); pPin->fall_cap = Vec_StrGetF(vOut, pPos); pPin->rise_capI = Scl_Flt2Int(pPin->rise_cap); pPin->fall_capI = Scl_Flt2Int(pPin->fall_cap); } for ( j = 0; j < pCell->n_outputs; j++ ) { SC_Pin * pPin = Abc_SclPinAlloc(); Vec_PtrPush( &pCell->vPins, pPin ); pPin->dir = sc_dir_Output; pPin->pName = Vec_StrGetS(vOut, pPos); pPin->max_out_cap = Vec_StrGetF(vOut, pPos); pPin->max_out_slew = Vec_StrGetF(vOut, pPos); k = Vec_StrGetI(vOut, pPos); assert( k == pCell->n_inputs ); // read function // (possibly empty) formula is always given assert( version == ABC_SCL_CUR_VERSION ); assert( pPin->func_text == NULL ); pPin->func_text = Vec_StrGetS(vOut, pPos); if ( pPin->func_text[0] == 0 ) { // formula is not given - read truth table ABC_FREE( pPin->func_text ); assert( Vec_WrdSize(&pPin->vFunc) == 0 ); Vec_WrdGrow( &pPin->vFunc, Abc_Truth6WordNum(pCell->n_inputs) ); for ( k = 0; k < Vec_WrdCap(&pPin->vFunc); k++ ) Vec_WrdPush( &pPin->vFunc, Vec_StrGetW(vOut, pPos) ); } else { // formula is given - derive truth table SC_Pin * pPin2; Vec_Ptr_t * vNames; Vec_Wrd_t * vFunc; // collect input names vNames = Vec_PtrAlloc( pCell->n_inputs ); SC_CellForEachPinIn( pCell, pPin2, n ) Vec_PtrPush( vNames, pPin2->pName ); // derive truth table assert( Vec_WrdSize(&pPin->vFunc) == 0 ); Vec_WrdErase( &pPin->vFunc ); vFunc = Mio_ParseFormulaTruth( pPin->func_text, (char **)Vec_PtrArray(vNames), pCell->n_inputs ); pPin->vFunc = *vFunc; ABC_FREE( vFunc ); Vec_PtrFree( vNames ); // skip truth table assert( Vec_WrdSize(&pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) ); for ( k = 0; k < Vec_WrdSize(&pPin->vFunc); k++ ) { word Value = Vec_StrGetW(vOut, pPos); assert( Value == Vec_WrdEntry(&pPin->vFunc, k) ); } } // Read 'rtiming': (pin-to-pin timing tables for this particular output) for ( k = 0; k < pCell->n_inputs; k++ ) { SC_Timings * pRTime = Abc_SclTimingsAlloc(); Vec_PtrPush( &pPin->vRTimings, pRTime ); pRTime->pName = Vec_StrGetS(vOut, pPos); n = Vec_StrGetI(vOut, pPos); assert( n <= 1 ); if ( n == 1 ) { SC_Timing * pTime = Abc_SclTimingAlloc(); Vec_PtrPush( &pRTime->vTimings, pTime ); pTime->tsense = (SC_TSense)Vec_StrGetI(vOut, pPos); Abc_SclReadSurface( vOut, pPos, &pTime->pCellRise ); Abc_SclReadSurface( vOut, pPos, &pTime->pCellFall ); Abc_SclReadSurface( vOut, pPos, &pTime->pRiseTrans ); Abc_SclReadSurface( vOut, pPos, &pTime->pFallTrans ); } else assert( Vec_PtrSize(&pRTime->vTimings) == 0 ); } } } return 1; } SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut ) { SC_Lib * p; int Pos = 0; // read the library p = Abc_SclLibAlloc(); if ( !Abc_SclReadLibrary( vOut, &Pos, p ) ) return NULL; assert( Pos == Vec_StrSize(vOut) ); // hash gates by name Abc_SclHashCells( p ); Abc_SclLinkCells( p ); return p; } SC_Lib * Abc_SclReadFromFile( char * pFileName ) { SC_Lib * p; FILE * pFile; Vec_Str_t * vOut; int nFileSize; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return NULL; } // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); rewind( pFile ); // load the contents vOut = Vec_StrAlloc( nFileSize ); vOut->nSize = vOut->nCap; assert( nFileSize == Vec_StrSize(vOut) ); nFileSize = fread( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); assert( nFileSize == Vec_StrSize(vOut) ); fclose( pFile ); // read the library p = Abc_SclReadFromStr( vOut ); if ( p != NULL ) p->pFileName = Abc_UtilStrsav( pFileName ); if ( p != NULL ) Abc_SclLibNormalize( p ); Vec_StrFree( vOut ); return p; } /**Function************************************************************* Synopsis [Writing library into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_SclWriteSurface( Vec_Str_t * vOut, SC_Surface * p ) { Vec_Flt_t * vVec; float Entry; int i, k; Vec_StrPutI( vOut, Vec_FltSize(&p->vIndex0) ); Vec_FltForEachEntry( &p->vIndex0, Entry, i ) Vec_StrPutF( vOut, Entry ); Vec_StrPutI( vOut, Vec_FltSize(&p->vIndex1) ); Vec_FltForEachEntry( &p->vIndex1, Entry, i ) Vec_StrPutF( vOut, Entry ); Vec_PtrForEachEntry( Vec_Flt_t *, &p->vData, vVec, i ) Vec_FltForEachEntry( vVec, Entry, k ) Vec_StrPutF( vOut, Entry ); for ( i = 0; i < 3; i++ ) Vec_StrPutF( vOut, p->approx[0][i] ); for ( i = 0; i < 4; i++ ) Vec_StrPutF( vOut, p->approx[1][i] ); for ( i = 0; i < 6; i++ ) Vec_StrPutF( vOut, p->approx[2][i] ); } static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p ) { SC_WireLoad * pWL; SC_WireLoadSel * pWLS; SC_Cell * pCell; SC_Pin * pPin; int n_valid_cells; int i, j, k; Vec_StrPutI( vOut, ABC_SCL_CUR_VERSION ); // Write non-composite fields: Vec_StrPutS( vOut, p->pName ); Vec_StrPutS( vOut, p->default_wire_load ); Vec_StrPutS( vOut, p->default_wire_load_sel ); Vec_StrPutF( vOut, p->default_max_out_slew ); assert( p->unit_time >= 0 ); assert( p->unit_cap_snd >= 0 ); Vec_StrPutI( vOut, p->unit_time ); Vec_StrPutF( vOut, p->unit_cap_fst ); Vec_StrPutI( vOut, p->unit_cap_snd ); // Write 'wire_load' vector: Vec_StrPutI( vOut, Vec_PtrSize(&p->vWireLoads) ); SC_LibForEachWireLoad( p, pWL, i ) { Vec_StrPutS( vOut, pWL->pName ); Vec_StrPutF( vOut, pWL->cap ); Vec_StrPutF( vOut, pWL->slope ); Vec_StrPutI( vOut, Vec_IntSize(&pWL->vFanout) ); for ( j = 0; j < Vec_IntSize(&pWL->vFanout); j++ ) { Vec_StrPutI( vOut, Vec_IntEntry(&pWL->vFanout, j) ); Vec_StrPutF( vOut, Vec_FltEntry(&pWL->vLen, j) ); } } // Write 'wire_load_sel' vector: Vec_StrPutI( vOut, Vec_PtrSize(&p->vWireLoadSels) ); SC_LibForEachWireLoadSel( p, pWLS, i ) { Vec_StrPutS( vOut, pWLS->pName ); Vec_StrPutI( vOut, Vec_FltSize(&pWLS->vAreaFrom) ); for ( j = 0; j < Vec_FltSize(&pWLS->vAreaFrom); j++) { Vec_StrPutF( vOut, Vec_FltEntry(&pWLS->vAreaFrom, j) ); Vec_StrPutF( vOut, Vec_FltEntry(&pWLS->vAreaTo, j) ); Vec_StrPutS( vOut, (char *)Vec_PtrEntry(&pWLS->vWireLoadModel, j) ); } } // Write 'cells' vector: n_valid_cells = 0; SC_LibForEachCell( p, pCell, i ) if ( !(pCell->seq || pCell->unsupp) ) n_valid_cells++; Vec_StrPutI( vOut, n_valid_cells ); SC_LibForEachCell( p, pCell, i ) { if ( pCell->seq || pCell->unsupp ) continue; Vec_StrPutS( vOut, pCell->pName ); Vec_StrPutF( vOut, pCell->area ); Vec_StrPutF( vOut, pCell->leakage ); Vec_StrPutI( vOut, pCell->drive_strength ); // Write 'pins': (sorted at this point; first inputs, then outputs) Vec_StrPutI( vOut, pCell->n_inputs); Vec_StrPutI( vOut, pCell->n_outputs); SC_CellForEachPinIn( pCell, pPin, j ) { assert(pPin->dir == sc_dir_Input); Vec_StrPutS( vOut, pPin->pName ); Vec_StrPutF( vOut, pPin->rise_cap ); Vec_StrPutF( vOut, pPin->fall_cap ); } SC_CellForEachPinOut( pCell, pPin, j ) { SC_Timings * pRTime; word uWord; assert(pPin->dir == sc_dir_Output); Vec_StrPutS( vOut, pPin->pName ); Vec_StrPutF( vOut, pPin->max_out_cap ); Vec_StrPutF( vOut, pPin->max_out_slew ); Vec_StrPutI( vOut, pCell->n_inputs ); // write function Vec_StrPutS( vOut, pPin->func_text ? pPin->func_text : (char *)"" ); // write truth table assert( Vec_WrdSize(&pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) ); Vec_WrdForEachEntry( &pPin->vFunc, uWord, k ) // -- 'size = 1u << (n_vars - 6)' Vec_StrPutW( vOut, uWord ); // -- 64-bit number, written uncompressed (low-byte first) // Write 'rtiming': (pin-to-pin timing tables for this particular output) assert( Vec_PtrSize(&pPin->vRTimings) == pCell->n_inputs ); SC_PinForEachRTiming( pPin, pRTime, k ) { Vec_StrPutS( vOut, pRTime->pName ); Vec_StrPutI( vOut, Vec_PtrSize(&pRTime->vTimings) ); // -- NOTE! After post-processing, the size of the 'rtiming[k]' vector is either // 0 or 1 (in static timing, we have merged all tables to get the worst case). // The case with size 0 should only occur for multi-output gates. if ( Vec_PtrSize(&pRTime->vTimings) == 1 ) { SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( &pRTime->vTimings, 0 ); // -- NOTE! We don't need to save 'related_pin' string because we have sorted // the elements on input pins. Vec_StrPutI( vOut, (int)pTime->tsense); Abc_SclWriteSurface( vOut, &pTime->pCellRise ); Abc_SclWriteSurface( vOut, &pTime->pCellFall ); Abc_SclWriteSurface( vOut, &pTime->pRiseTrans ); Abc_SclWriteSurface( vOut, &pTime->pFallTrans ); } else assert( Vec_PtrSize(&pRTime->vTimings) == 0 ); } } } } void Abc_SclWriteScl( char * pFileName, SC_Lib * p ) { Vec_Str_t * vOut; vOut = Vec_StrAlloc( 10000 ); Abc_SclWriteLibrary( vOut, p ); if ( Vec_StrSize(vOut) > 0 ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); fclose( pFile ); } } Vec_StrFree( vOut ); } /**Function************************************************************* Synopsis [Writing library into text file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_SclWriteSurfaceText( FILE * s, SC_Surface * p ) { Vec_Flt_t * vVec; float Entry; int i, k; fprintf( s, " index_1(\"" ); Vec_FltForEachEntry( &p->vIndex0, Entry, i ) fprintf( s, "%f%s", Entry, i == Vec_FltSize(&p->vIndex0)-1 ? "":", " ); fprintf( s, "\");\n" ); fprintf( s, " index_2(\"" ); Vec_FltForEachEntry( &p->vIndex1, Entry, i ) fprintf( s, "%f%s", Entry, i == Vec_FltSize(&p->vIndex1)-1 ? "":", " ); fprintf( s, "\");\n" ); fprintf( s, " values (\"" ); Vec_PtrForEachEntry( Vec_Flt_t *, &p->vData, vVec, i ) { Vec_FltForEachEntry( vVec, Entry, k ) fprintf( s, "%f%s", Entry, i == Vec_PtrSize(&p->vData)-1 && k == Vec_FltSize(vVec)-1 ? "\");":", " ); if ( i == Vec_PtrSize(&p->vData)-1 ) fprintf( s, "\n" ); else { fprintf( s, "\\\n" ); fprintf( s, " " ); } } /* fprintf( s, " approximations: \n" ); fprintf( s, " " ); for ( i = 0; i < 3; i++ ) fprintf( s, "%f ", p->approx[0][i] ); fprintf( s, "\n" ); fprintf( s, " " ); for ( i = 0; i < 4; i++ ) fprintf( s, "%f ", p->approx[1][i] ); fprintf( s, "\n" ); fprintf( s, " " ); for ( i = 0; i < 6; i++ ) fprintf( s, "%f ", p->approx[2][i] ); fprintf( s, "\n" ); fprintf( s, " \n" ); */ } static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p ) { SC_WireLoad * pWL; SC_WireLoadSel * pWLS; SC_Cell * pCell; SC_Pin * pPin; int n_valid_cells; int i, j, k; fprintf( s, "/* This Liberty file was generated by ABC on %s */\n", Extra_TimeStamp() ); fprintf( s, "/* The original unabridged library came from file \"%s\".*/\n\n", p->pFileName ); // fprintf( s, "%d", ABC_SCL_CUR_VERSION ); fprintf( s, "library(%s) {\n\n", p->pName ); if ( p->default_wire_load && strlen(p->default_wire_load) ) fprintf( s, " default_wire_load : \"%s\";\n", p->default_wire_load ); if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) ) fprintf( s, " default_wire_load_selection : \"%s\";\n", p->default_wire_load_sel ); if ( p->default_max_out_slew != -1 ) fprintf( s, " default_max_transition : %f;\n", p->default_max_out_slew ); if ( p->unit_time == 9 ) fprintf( s, " time_unit : \"1ns\";\n" ); else if ( p->unit_time == 10 ) fprintf( s, " time_unit : \"100ps\";\n" ); else if ( p->unit_time == 11 ) fprintf( s, " time_unit : \"10ps\";\n" ); else if ( p->unit_time == 12 ) fprintf( s, " time_unit : \"1ps\";\n" ); else assert( 0 ); fprintf( s, " capacitive_load_unit(%.1f,%s);\n", p->unit_cap_fst, p->unit_cap_snd == 12 ? "pf" : "ff" ); fprintf( s, "\n" ); // Write 'wire_load' vector: SC_LibForEachWireLoad( p, pWL, i ) { fprintf( s, " wire_load(\"%s\") {\n", pWL->pName ); fprintf( s, " capacitance : %f;\n", pWL->cap ); fprintf( s, " slope : %f;\n", pWL->slope ); for ( j = 0; j < Vec_IntSize(&pWL->vFanout); j++ ) fprintf( s, " fanout_length( %d, %f );\n", Vec_IntEntry(&pWL->vFanout, j), Vec_FltEntry(&pWL->vLen, j) ); fprintf( s, " }\n\n" ); } // Write 'wire_load_sel' vector: SC_LibForEachWireLoadSel( p, pWLS, i ) { fprintf( s, " wire_load_selection(\"%s\") {\n", pWLS->pName ); for ( j = 0; j < Vec_FltSize(&pWLS->vAreaFrom); j++) fprintf( s, " wire_load_from_area( %f, %f, %s );\n", Vec_FltEntry(&pWLS->vAreaFrom, j), Vec_FltEntry(&pWLS->vAreaTo, j), (char *)Vec_PtrEntry(&pWLS->vWireLoadModel, j) ); fprintf( s, " }\n\n" ); } // Write 'cells' vector: n_valid_cells = 0; SC_LibForEachCell( p, pCell, i ) if ( !(pCell->seq || pCell->unsupp) ) n_valid_cells++; SC_LibForEachCell( p, pCell, i ) { if ( pCell->seq || pCell->unsupp ) continue; fprintf( s, "\n" ); fprintf( s, " cell(%s) {\n", pCell->pName ); fprintf( s, " /* n_inputs = %d n_outputs = %d */\n", pCell->n_inputs, pCell->n_outputs ); fprintf( s, " area : %f;\n", pCell->area ); fprintf( s, " cell_leakage_power : %f;\n", pCell->leakage ); fprintf( s, " drive_strength : %d;\n", pCell->drive_strength ); SC_CellForEachPinIn( pCell, pPin, j ) { assert(pPin->dir == sc_dir_Input); fprintf( s, " pin(%s) {\n", pPin->pName ); fprintf( s, " direction : %s;\n", "input" ); fprintf( s, " fall_capacitance : %f;\n", pPin->fall_cap ); fprintf( s, " rise_capacitance : %f;\n", pPin->rise_cap ); fprintf( s, " }\n" ); } SC_CellForEachPinOut( pCell, pPin, j ) { SC_Timings * pRTime; // word uWord; assert(pPin->dir == sc_dir_Output); fprintf( s, " pin(%s) {\n", pPin->pName ); fprintf( s, " direction : %s;\n", "output" ); fprintf( s, " max_capacitance : %f;\n", pPin->max_out_cap ); fprintf( s, " max_transition : %f;\n", pPin->max_out_slew ); fprintf( s, " function : \"%s\";\n", pPin->func_text ? pPin->func_text : "?" ); fprintf( s, " /* truth table = " ); Extra_PrintHex( s, (unsigned *)Vec_WrdArray(&pPin->vFunc), pCell->n_inputs ); fprintf( s, " */\n" ); // Write 'rtiming': (pin-to-pin timing tables for this particular output) assert( Vec_PtrSize(&pPin->vRTimings) == pCell->n_inputs ); SC_PinForEachRTiming( pPin, pRTime, k ) { if ( Vec_PtrSize(&pRTime->vTimings) == 1 ) { SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( &pRTime->vTimings, 0 ); fprintf( s, " timing() {\n" ); fprintf( s, " related_pin : \"%s\"\n", pRTime->pName ); if ( pTime->tsense == sc_ts_Pos ) fprintf( s, " timing_sense : positive_unate;\n" ); else if ( pTime->tsense == sc_ts_Neg ) fprintf( s, " timing_sense : negative_unate;\n" ); else if ( pTime->tsense == sc_ts_Non ) fprintf( s, " timing_sense : non_unate;\n" ); else assert( 0 ); fprintf( s, " cell_rise() {\n" ); Abc_SclWriteSurfaceText( s, &pTime->pCellRise ); fprintf( s, " }\n" ); fprintf( s, " cell_fall() {\n" ); Abc_SclWriteSurfaceText( s, &pTime->pCellFall ); fprintf( s, " }\n" ); fprintf( s, " rise_transition() {\n" ); Abc_SclWriteSurfaceText( s, &pTime->pRiseTrans ); fprintf( s, " }\n" ); fprintf( s, " fall_transition() {\n" ); Abc_SclWriteSurfaceText( s, &pTime->pFallTrans ); fprintf( s, " }\n" ); fprintf( s, " }\n" ); } else assert( Vec_PtrSize(&pRTime->vTimings) == 0 ); } fprintf( s, " }\n" ); } fprintf( s, " }\n" ); } fprintf( s, "}\n\n" ); } void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open text file \"%s\" for writing.\n", pFileName ); else { Abc_SclWriteLibraryText( pFile, p ); fclose( pFile ); printf( "Dumped internal library into Liberty file \"%s\".\n", pFileName ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclLibUtil.c000066400000000000000000001112071300674244400236060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclLibUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Various library utilities.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclLibUtil.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclLib.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reading library from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static unsigned Abc_SclHashString( char * pName, int TableSize ) { static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; unsigned i, Key = 0; for ( i = 0; pName[i] != '\0'; i++ ) Key += s_Primes[i%10]*pName[i]*pName[i]; return Key % TableSize; } int * Abc_SclHashLookup( SC_Lib * p, char * pName ) { int i; for ( i = Abc_SclHashString(pName, p->nBins); i < p->nBins; i = (i + 1) % p->nBins ) if ( p->pBins[i] == -1 || !strcmp(pName, SC_LibCell(p, p->pBins[i])->pName) ) return p->pBins + i; assert( 0 ); return NULL; } void Abc_SclHashCells( SC_Lib * p ) { SC_Cell * pCell; int i, * pPlace; assert( p->nBins == 0 ); p->nBins = Abc_PrimeCudd( 5 * SC_LibCellNum(p) ); p->pBins = ABC_FALLOC( int, p->nBins ); SC_LibForEachCell( p, pCell, i ) { pPlace = Abc_SclHashLookup( p, pCell->pName ); assert( *pPlace == -1 ); *pPlace = i; } } int Abc_SclCellFind( SC_Lib * p, char * pName ) { int *pPlace = Abc_SclHashLookup( p, pName ); return pPlace ? *pPlace : -1; } int Abc_SclClassCellNum( SC_Cell * pClass ) { SC_Cell * pCell; int i, Count = 0; SC_RingForEachCell( pClass, pCell, i ) if ( !pCell->fSkip ) Count++; return Count; } int Abc_SclLibClassNum( SC_Lib * pLib ) { SC_Cell * pRepr; int i, Count = 0; SC_LibForEachCellClass( pLib, pRepr, i ) Count++; return Count; } /**Function************************************************************* Synopsis [Change cell names and pin names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_SclIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } static inline int Abc_SclIsName( char c ) { return Abc_SclIsChar(c) || (c >= '0' && c <= '9'); } static inline char * Abc_SclFindLimit( char * pName ) { assert( Abc_SclIsChar(*pName) ); while ( Abc_SclIsName(*pName) ) pName++; return pName; } static inline int Abc_SclAreEqual( char * pBase, char * pName, char * pLimit ) { return !strncmp( pBase, pName, pLimit - pName ); } void Abc_SclShortFormula( SC_Cell * pCell, char * pForm, char * pBuffer ) { SC_Pin * pPin; int i; char * pTemp, * pLimit; for ( pTemp = pForm; *pTemp; ) { if ( !Abc_SclIsChar(*pTemp) ) { *pBuffer++ = *pTemp++; continue; } pLimit = Abc_SclFindLimit( pTemp ); SC_CellForEachPinIn( pCell, pPin, i ) if ( Abc_SclAreEqual( pPin->pName, pTemp, pLimit ) ) { *pBuffer++ = 'a' + i; break; } assert( i < pCell->n_inputs ); pTemp = pLimit; } *pBuffer++ = 0; } static inline void Abc_SclTimingUpdate( SC_Cell * pCell, SC_Timing * p, char * Buffer ) { SC_Pin * pPin; int i; SC_CellForEachPinIn( pCell, pPin, i ) if ( p->related_pin && !strcmp(p->related_pin, pPin->pName) ) { ABC_FREE( p->related_pin ); sprintf( Buffer, "%c", 'a'+i ); p->related_pin = Abc_UtilStrsav( Buffer ); } } static inline void Abc_SclTimingsUpdate( SC_Cell * pCell, SC_Timings * p, char * Buffer ) { SC_Timing * pTemp; int i; Vec_PtrForEachEntry( SC_Timing *, &p->vTimings, pTemp, i ) Abc_SclTimingUpdate( pCell, pTemp, Buffer ); } static inline void Abc_SclPinUpdate( SC_Cell * pCell, SC_Pin * p, char * Buffer ) { // update pin names in the timing SC_Timings * pTemp; int i; SC_PinForEachRTiming( p, pTemp, i ) { SC_Pin * pPin; int k; Abc_SclTimingsUpdate( pCell, pTemp, Buffer ); SC_CellForEachPinIn( pCell, pPin, k ) if ( pTemp->pName && !strcmp(pTemp->pName, pPin->pName) ) { ABC_FREE( pTemp->pName ); sprintf( Buffer, "%c", 'a'+k ); pTemp->pName = Abc_UtilStrsav( Buffer ); } } // update formula Abc_SclShortFormula( pCell, p->func_text, Buffer ); ABC_FREE( p->func_text ); p->func_text = Abc_UtilStrsav( Buffer ); } void Abc_SclShortNames( SC_Lib * p ) { char Buffer[10000]; SC_Cell * pClass, * pCell; SC_Pin * pPin; int i, k, n, nClasses = Abc_SclLibClassNum(p); int nDigits = Abc_Base10Log( nClasses ); // itereate through classes SC_LibForEachCellClass( p, pClass, i ) { int nDigits2 = Abc_Base10Log( Abc_SclClassCellNum(pClass) ); SC_RingForEachCell( pClass, pCell, k ) { ABC_FREE( pCell->pName ); sprintf( Buffer, "g%0*d_%0*d", nDigits, i, nDigits2, k ); pCell->pName = Abc_UtilStrsav( Buffer ); // formula SC_CellForEachPinOut( pCell, pPin, n ) Abc_SclPinUpdate( pCell, pPin, Buffer ); // pin names SC_CellForEachPinIn( pCell, pPin, n ) { ABC_FREE( pPin->pName ); sprintf( Buffer, "%c", 'a'+n ); pPin->pName = Abc_UtilStrsav( Buffer ); } SC_CellForEachPinOut( pCell, pPin, n ) { ABC_FREE( pPin->pName ); sprintf( Buffer, "%c", 'z'-n+pCell->n_inputs ); pPin->pName = Abc_UtilStrsav( Buffer ); } } } p->nBins = 0; ABC_FREE( p->pBins ); Abc_SclHashCells( p ); // update library name printf( "Renaming library \"%s\" into \"%s%d\".\n", p->pName, "lib", SC_LibCellNum(p) ); ABC_FREE( p->pName ); sprintf( Buffer, "lib%d", SC_LibCellNum(p) ); p->pName = Abc_UtilStrsav( Buffer ); } /**Function************************************************************* Synopsis [Links equal gates into rings while sorting them by area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Abc_SclCompareCells( SC_Cell ** pp1, SC_Cell ** pp2 ) { if ( (*pp1)->n_inputs < (*pp2)->n_inputs ) return -1; if ( (*pp1)->n_inputs > (*pp2)->n_inputs ) return 1; // if ( (*pp1)->area < (*pp2)->area ) // return -1; // if ( (*pp1)->area > (*pp2)->area ) // return 1; if ( SC_CellPinCapAve(*pp1) < SC_CellPinCapAve(*pp2) ) return -1; if ( SC_CellPinCapAve(*pp1) > SC_CellPinCapAve(*pp2) ) return 1; return strcmp( (*pp1)->pName, (*pp2)->pName ); } void Abc_SclLinkCells( SC_Lib * p ) { Vec_Ptr_t * vList; SC_Cell * pCell, * pRepr = NULL; int i, k; assert( Vec_PtrSize(&p->vCellClasses) == 0 ); SC_LibForEachCell( p, pCell, i ) { // find gate with the same function SC_LibForEachCellClass( p, pRepr, k ) if ( pCell->n_inputs == pRepr->n_inputs && pCell->n_outputs == pRepr->n_outputs && Vec_WrdEqual(SC_CellFunc(pCell), SC_CellFunc(pRepr)) ) break; if ( k == Vec_PtrSize(&p->vCellClasses) ) { Vec_PtrPush( &p->vCellClasses, pCell ); pCell->pNext = pCell->pPrev = pCell; continue; } // add it to the list before the cell pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr; pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell; } // sort cells by size then by name qsort( (void *)Vec_PtrArray(&p->vCellClasses), Vec_PtrSize(&p->vCellClasses), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells ); // sort cell lists vList = Vec_PtrAlloc( 100 ); SC_LibForEachCellClass( p, pRepr, k ) { Vec_PtrClear( vList ); SC_RingForEachCell( pRepr, pCell, i ) Vec_PtrPush( vList, pCell ); qsort( (void *)Vec_PtrArray(vList), Vec_PtrSize(vList), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells ); // create new representative pRepr = (SC_Cell *)Vec_PtrEntry( vList, 0 ); pRepr->pNext = pRepr->pPrev = pRepr; pRepr->pRepr = pRepr; pRepr->pAve = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 ); pRepr->Order = 0; pRepr->nGates = Vec_PtrSize(vList); // relink cells Vec_PtrForEachEntryStart( SC_Cell *, vList, pCell, i, 1 ) { pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr; pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell; pCell->pRepr = pRepr; pCell->pAve = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 ); pCell->Order = i; pCell->nGates = Vec_PtrSize(vList); } // update list Vec_PtrWriteEntry( &p->vCellClasses, k, pRepr ); } Vec_PtrFree( vList ); } /**Function************************************************************* Synopsis [Returns the largest inverter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ SC_Cell * Abc_SclFindInvertor( SC_Lib * p, int fFindBuff ) { SC_Cell * pCell = NULL; word Truth = fFindBuff ? ABC_CONST(0xAAAAAAAAAAAAAAAA) : ABC_CONST(0x5555555555555555); int k; SC_LibForEachCellClass( p, pCell, k ) if ( pCell->n_inputs == 1 && Vec_WrdEntry(&SC_CellPin(pCell, 1)->vFunc, 0) == Truth ) break; // take representative return pCell ? pCell->pRepr : NULL; } SC_Cell * Abc_SclFindSmallestGate( SC_Cell * p, float CinMin ) { SC_Cell * pRes = NULL; int i; SC_RingForEachCell( p->pRepr, pRes, i ) if ( SC_CellPinCapAve(pRes) > CinMin ) return pRes; // take the largest gate return p->pRepr->pPrev; } /**Function************************************************************* Synopsis [Returns the wireload model for the given area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pWLoadUsed ) { SC_WireLoad * pWL = NULL; int i; // Get the actual table and reformat it for 'wire_cap' output: assert( pWLoadUsed != NULL ); SC_LibForEachWireLoad( p, pWL, i ) if ( !strcmp(pWL->pName, pWLoadUsed) ) break; if ( i == Vec_PtrSize(&p->vWireLoads) ) { Abc_Print( -1, "Cannot find wire load model \"%s\".\n", pWLoadUsed ); exit(1); } // printf( "Using wireload model \"%s\".\n", pWL->pName ); return pWL; } SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area ) { char * pWLoadUsed = NULL; int i; if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) ) { SC_WireLoadSel * pWLS = NULL; SC_LibForEachWireLoadSel( p, pWLS, i ) if ( !strcmp(pWLS->pName, p->default_wire_load_sel) ) break; if ( i == Vec_PtrSize(&p->vWireLoadSels) ) { Abc_Print( -1, "Cannot find wire load selection model \"%s\".\n", p->default_wire_load_sel ); exit(1); } for ( i = 0; i < Vec_FltSize(&pWLS->vAreaFrom); i++) if ( Area >= Vec_FltEntry(&pWLS->vAreaFrom, i) && Area < Vec_FltEntry(&pWLS->vAreaTo, i) ) { pWLoadUsed = (char *)Vec_PtrEntry(&pWLS->vWireLoadModel, i); break; } if ( i == Vec_FltSize(&pWLS->vAreaFrom) ) pWLoadUsed = (char *)Vec_PtrEntryLast(&pWLS->vWireLoadModel); } else if ( p->default_wire_load && strlen(p->default_wire_load) ) pWLoadUsed = p->default_wire_load; else { // Abc_Print( 0, "No wire model given.\n" ); return NULL; } return Abc_SclFetchWireLoadModel( p, pWLoadUsed ); } /**Function************************************************************* Synopsis [Returns 1 if the library has delay info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclHasDelayInfo( void * pScl ) { SC_Lib * p = (SC_Lib *)pScl; SC_Cell * pCell; SC_Timing * pTime; pCell = Abc_SclFindInvertor(p, 0); if ( pCell == NULL ) return 0; pTime = Scl_CellPinTime( pCell, 0 ); if ( pTime == NULL ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns "average" slew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_SclComputeAverageSlew( SC_Lib * p ) { SC_Cell * pCell; SC_Timing * pTime; Vec_Flt_t * vIndex; pCell = Abc_SclFindInvertor(p, 0); if ( pCell == NULL ) return 0; pTime = Scl_CellPinTime( pCell, 0 ); if ( pTime == NULL ) return 0; vIndex = &pTime->pCellRise.vIndex0; // slew return Vec_FltEntry( vIndex, Vec_FltSize(vIndex)/3 ); } /**Function************************************************************* Synopsis [Compute delay parameters of pin/cell/class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclComputeParametersPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float * pLD, float * pPD ) { SC_Pair Load0, Load1, Load2; SC_Pair ArrIn = { 0.0, 0.0 }; SC_Pair SlewIn = { Slew, Slew }; SC_Pair ArrOut0 = { 0.0, 0.0 }; SC_Pair ArrOut1 = { 0.0, 0.0 }; SC_Pair ArrOut2 = { 0.0, 0.0 }; SC_Pair SlewOut = { 0.0, 0.0 }; SC_Timing * pTime = Scl_CellPinTime( pCell, iPin ); Vec_Flt_t * vIndex = pTime ? &pTime->pCellRise.vIndex1 : NULL; // capacitance if ( vIndex == NULL ) return 0; // handle constant table if ( Vec_FltSize(vIndex) == 1 ) { *pLD = 0; *pPD = Vec_FltEntry( (Vec_Flt_t *)Vec_PtrEntry(&pTime->pCellRise.vData, 0), 0 ); return 1; } // get load points Load0.rise = Load0.fall = 0.0; Load1.rise = Load1.fall = Vec_FltEntry( vIndex, 0 ); Load2.rise = Load2.fall = Vec_FltEntry( vIndex, Vec_FltSize(vIndex) - 2 ); // compute delay Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load0, &ArrOut0, &SlewOut ); Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load1, &ArrOut1, &SlewOut ); Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load2, &ArrOut2, &SlewOut ); ArrOut0.rise = 0.5 * ArrOut0.rise + 0.5 * ArrOut0.fall; ArrOut1.rise = 0.5 * ArrOut1.rise + 0.5 * ArrOut1.fall; ArrOut2.rise = 0.5 * ArrOut2.rise + 0.5 * ArrOut2.fall; // get tangent *pLD = (ArrOut2.rise - ArrOut1.rise) / ((Load2.rise - Load1.rise) / SC_CellPinCap(pCell, iPin)); // get constant *pPD = ArrOut0.rise; return 1; } int Abc_SclComputeParametersCell( SC_Lib * p, SC_Cell * pCell, float Slew, float * pLD, float * pPD ) { SC_Pin * pPin; float LD, PD, ld, pd; int i; LD = PD = ld = pd = 0; SC_CellForEachPinIn( pCell, pPin, i ) { if ( !Abc_SclComputeParametersPin( p, pCell, i, Slew, &ld, &pd ) ) return 0; LD += ld; PD += pd; } *pLD = LD / Abc_MaxInt(1, pCell->n_inputs); *pPD = PD / Abc_MaxInt(1, pCell->n_inputs); return 1; } void Abc_SclComputeParametersClass( SC_Lib * p, SC_Cell * pRepr, float Slew, float * pLD, float * pPD ) { SC_Cell * pCell; float LD, PD, ld, pd; int i, Count = 0; LD = PD = ld = pd = 0; SC_RingForEachCell( pRepr, pCell, i ) { Abc_SclComputeParametersCell( p, pCell, Slew, &ld, &pd ); LD += ld; PD += pd; Count++; } *pLD = LD / Abc_MaxInt(1, Count); *pPD = PD / Abc_MaxInt(1, Count); } void Abc_SclComputeParametersClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float * pLD, float * pPD ) { SC_Cell * pCell; float LD, PD, ld, pd; int i, Count = 0; LD = PD = ld = pd = 0; SC_RingForEachCell( pRepr, pCell, i ) { Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &ld, &pd ); LD += ld; PD += pd; Count++; } *pLD = LD / Abc_MaxInt(1, Count); *pPD = PD / Abc_MaxInt(1, Count); } float Abc_SclComputeDelayCellPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float Gain ) { float LD = 0, PD = 0; Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &LD, &PD ); return 0.01 * LD * Gain + PD; } float Abc_SclComputeDelayClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float Gain ) { SC_Cell * pCell; float Delay = 0; int i, Count = 0; SC_RingForEachCell( pRepr, pCell, i ) { if ( pCell->fSkip ) continue; // if ( pRepr == pCell ) // skip the first gate // continue; Delay += Abc_SclComputeDelayCellPin( p, pCell, iPin, Slew, Gain ); Count++; } return Delay / Abc_MaxInt(1, Count); } float Abc_SclComputeAreaClass( SC_Cell * pRepr ) { SC_Cell * pCell; float Area = 0; int i, Count = 0; SC_RingForEachCell( pRepr, pCell, i ) { if ( pCell->fSkip ) continue; Area += pCell->area; Count++; } return Area / Abc_MaxInt(1, Count); } /**Function************************************************************* Synopsis [Print cells] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclMarkSkippedCells( SC_Lib * p ) { char FileName[1000]; char Buffer[1000], * pName; SC_Cell * pCell; FILE * pFile; int CellId, nSkipped = 0; sprintf( FileName, "%s.skip", p->pName ); pFile = fopen( FileName, "rb" ); if ( pFile == NULL ) return; while ( fgets( Buffer, 999, pFile ) != NULL ) { pName = strtok( Buffer, "\r\n\t " ); if ( pName == NULL ) continue; CellId = Abc_SclCellFind( p, pName ); if ( CellId == -1 ) { printf( "Cannot find cell \"%s\" in the library \"%s\".\n", pName, p->pName ); continue; } pCell = SC_LibCell( p, CellId ); pCell->fSkip = 1; nSkipped++; } fclose( pFile ); printf( "Marked %d cells for skipping in the library \"%s\".\n", nSkipped, p->pName ); } void Abc_SclPrintCells( SC_Lib * p, float SlewInit, float Gain, int fInvOnly, int fShort ) { SC_Cell * pCell, * pRepr; SC_Pin * pPin; int i, j, k, nLength = 0; float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit; float LD = 0, PD = 0; assert( Vec_PtrSize(&p->vCellClasses) > 0 ); printf( "Library \"%s\" ", p->pName ); printf( "has %d cells in %d classes. ", Vec_PtrSize(&p->vCells), Vec_PtrSize(&p->vCellClasses) ); if ( !fShort ) printf( "Delay estimate is based on slew %.2f ps and gain %.2f.", Slew, Gain ); printf( "\n" ); Abc_SclMarkSkippedCells( p ); // find the longest name SC_LibForEachCellClass( p, pRepr, k ) SC_RingForEachCell( pRepr, pCell, i ) nLength = Abc_MaxInt( nLength, strlen(pRepr->pName) ); // print cells SC_LibForEachCellClass( p, pRepr, k ) { if ( fInvOnly && pRepr->n_inputs != 1 ) continue; SC_CellForEachPinOut( pRepr, pPin, i ) { if ( i == pRepr->n_inputs ) { printf( "Class%4d : ", k ); printf( "Cells =%3d ", Abc_SclClassCellNum(pRepr) ); printf( "Ins =%2d ", pRepr->n_inputs ); printf( "Outs =%2d ", pRepr->n_outputs ); } else printf( " " ); if ( pPin->func_text ) printf( "%-30s", pPin->func_text ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned *)Vec_WrdArray(&pPin->vFunc), pRepr->n_inputs ); printf( "\n" ); if ( fShort ) continue; SC_RingForEachCell( pRepr, pCell, j ) { printf( " %3d ", j+1 ); printf( "%s", pCell->fSkip ? "s" : " " ); printf( " : " ); printf( "%-*s ", nLength, pCell->pName ); printf( "%2d ", pCell->drive_strength ); printf( "A =%8.2f ", pCell->area ); printf( "L =%8.2f ", pCell->leakage ); if ( pCell->n_outputs == 1 ) { if ( Abc_SclComputeParametersCell( p, pCell, Slew, &LD, &PD ) ) { printf( "D =%6.1f ps ", 0.01 * Gain * LD + PD ); printf( "LD =%6.1f ps ", LD ); printf( "PD =%6.1f ps ", PD ); printf( "C =%5.1f ff ", SC_CellPinCapAve(pCell) ); printf( "Cm =%5.0f ff ", SC_CellPin(pCell, pCell->n_inputs)->max_out_cap ); printf( "Sm =%5.1f ps ", SC_CellPin(pCell, pCell->n_inputs)->max_out_slew ); } } printf( "\n" ); } break; } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclConvertLeakageIntoArea( SC_Lib * p, float A, float B ) { SC_Cell * pCell; int i; SC_LibForEachCell( p, pCell, i ) pCell->area = A * pCell->area + B * pCell->leakage; } /**Function************************************************************* Synopsis [Print cells] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclLibNormalizeSurface( SC_Surface * p, float Time, float Load ) { Vec_Flt_t * vArray; int i, k; float Entry; Vec_FltForEachEntry( &p->vIndex0, Entry, i ) // slew Vec_FltWriteEntry( &p->vIndex0, i, Time * Entry ); Vec_FltForEachEntry( &p->vIndex1, Entry, i ) // load Vec_FltWriteEntry( &p->vIndex1, i, Load * Entry ); Vec_PtrForEachEntry( Vec_Flt_t *, &p->vData, vArray, k ) Vec_FltForEachEntry( vArray, Entry, i ) // delay/slew Vec_FltWriteEntry( vArray, i, Time * Entry ); } void Abc_SclLibNormalize( SC_Lib * p ) { SC_WireLoad * pWL; SC_Cell * pCell; SC_Pin * pPin; SC_Timings * pTimings; SC_Timing * pTiming; int i, k, m, n; float Time = 1.0 * pow(10.0, 12 - p->unit_time); float Load = p->unit_cap_fst * pow(10.0, 15 - p->unit_cap_snd); if ( Time == 1 && Load == 1 ) return; p->unit_time = 12; p->unit_cap_fst = 1; p->unit_cap_snd = 15; p->default_max_out_slew *= Time; SC_LibForEachWireLoad( p, pWL, i ) pWL->cap *= Load; SC_LibForEachCell( p, pCell, i ) SC_CellForEachPin( pCell, pPin, k ) { pPin->cap *= Load; pPin->rise_cap *= Load; pPin->fall_cap *= Load; pPin->max_out_cap *= Load; pPin->max_out_slew *= Time; SC_PinForEachRTiming( pPin, pTimings, m ) Vec_PtrForEachEntry( SC_Timing *, &pTimings->vTimings, pTiming, n ) { Abc_SclLibNormalizeSurface( &pTiming->pCellRise, Time, Load ); Abc_SclLibNormalizeSurface( &pTiming->pCellFall, Time, Load ); Abc_SclLibNormalizeSurface( &pTiming->pRiseTrans, Time, Load ); Abc_SclLibNormalizeSurface( &pTiming->pFallTrans, Time, Load ); } } } /**Function************************************************************* Synopsis [Derives simple GENLIB library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Abc_SclProduceGenlibStrSimple( SC_Lib * p ) { char Buffer[200]; Vec_Str_t * vStr; SC_Cell * pCell; SC_Pin * pPin, * pPinOut; int i, j, k, Count = 2; // mark skipped cells // Abc_SclMarkSkippedCells( p ); vStr = Vec_StrAlloc( 1000 ); Vec_StrPrintStr( vStr, "GATE _const0_ 0.00 z=CONST0;\n" ); Vec_StrPrintStr( vStr, "GATE _const1_ 0.00 z=CONST1;\n" ); SC_LibForEachCell( p, pCell, i ) { if ( pCell->n_inputs == 0 ) continue; assert( strlen(pCell->pName) < 200 ); SC_CellForEachPinOut( pCell, pPinOut, j ) { Vec_StrPrintStr( vStr, "GATE " ); sprintf( Buffer, "%-16s", pCell->pName ); Vec_StrPrintStr( vStr, Buffer ); Vec_StrPrintStr( vStr, " " ); sprintf( Buffer, "%7.2f", pCell->area ); Vec_StrPrintStr( vStr, Buffer ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, pPinOut->pName ); Vec_StrPrintStr( vStr, "=" ); Vec_StrPrintStr( vStr, pPinOut->func_text ? pPinOut->func_text : "?" ); Vec_StrPrintStr( vStr, ";\n" ); SC_CellForEachPinIn( pCell, pPin, k ) { Vec_StrPrintStr( vStr, " PIN " ); sprintf( Buffer, "%-4s", pPin->pName ); Vec_StrPrintStr( vStr, Buffer ); sprintf( Buffer, " UNKNOWN 1 999 1.00 0.00 1.00 0.00\n" ); Vec_StrPrintStr( vStr, Buffer ); } Count++; } } Vec_StrPrintStr( vStr, "\n.end\n" ); Vec_StrPush( vStr, '\0' ); // printf( "GENLIB library with %d gates is produced:\n", Count ); // printf( "%s", Vec_StrArray(vStr) ); return vStr; } Mio_Library_t * Abc_SclDeriveGenlibSimple( void * pScl ) { SC_Lib * p = (SC_Lib *)pScl; Vec_Str_t * vStr = Abc_SclProduceGenlibStrSimple( p ); Mio_Library_t * pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0 ); Vec_StrFree( vStr ); if ( pLib ) printf( "Derived GENLIB library \"%s\" with %d gates.\n", p->pName, SC_LibCellNum(p) ); else printf( "Reading library has filed.\n" ); return pLib; } /**Function************************************************************* Synopsis [Derive GENLIB library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Abc_SclProduceGenlibStr( SC_Lib * p, float Slew, float Gain, int nGatesMin, int * pnCellCount ) { char Buffer[200]; Vec_Str_t * vStr; SC_Cell * pRepr; SC_Pin * pPin; int i, k, Count = 2, nClassMax = 0; // find the largest number of cells in a class SC_LibForEachCellClass( p, pRepr, i ) if ( pRepr->n_outputs == 1 ) nClassMax = Abc_MaxInt( nClassMax, Abc_SclClassCellNum(pRepr) ); // update the number if ( nGatesMin && nGatesMin >= nClassMax ) nGatesMin = 0; // mark skipped cells Abc_SclMarkSkippedCells( p ); vStr = Vec_StrAlloc( 1000 ); Vec_StrPrintStr( vStr, "GATE _const0_ 0.00 z=CONST0;\n" ); Vec_StrPrintStr( vStr, "GATE _const1_ 0.00 z=CONST1;\n" ); SC_LibForEachCellClass( p, pRepr, i ) { if ( pRepr->n_inputs == 0 ) continue; if ( pRepr->n_outputs > 1 ) continue; if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin ) continue; assert( strlen(pRepr->pName) < 200 ); Vec_StrPrintStr( vStr, "GATE " ); sprintf( Buffer, "%-16s", pRepr->pName ); Vec_StrPrintStr( vStr, Buffer ); Vec_StrPrintStr( vStr, " " ); // sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) ); sprintf( Buffer, "%7.2f", pRepr->area ); Vec_StrPrintStr( vStr, Buffer ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) ); Vec_StrPrintStr( vStr, "=" ); Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) ? SC_CellPinOutFunc(pRepr, 0) : "?" ); Vec_StrPrintStr( vStr, ";\n" ); SC_CellForEachPinIn( pRepr, pPin, k ) { float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain ); assert( Delay > 0 ); Vec_StrPrintStr( vStr, " PIN " ); sprintf( Buffer, "%-4s", pPin->pName ); Vec_StrPrintStr( vStr, Buffer ); sprintf( Buffer, " UNKNOWN 1 999 %7.2f 0.00 %7.2f 0.00\n", Delay, Delay ); Vec_StrPrintStr( vStr, Buffer ); } Count++; } Vec_StrPrintStr( vStr, "\n.end\n" ); Vec_StrPush( vStr, '\0' ); // printf( "GENLIB library with %d gates is produced:\n", Count ); // printf( "%s", Vec_StrArray(vStr) ); if ( pnCellCount ) *pnCellCount = Count; return vStr; } Vec_Str_t * Abc_SclProduceGenlibStrProfile( SC_Lib * p, Mio_Library_t * pLib, float Slew, float Gain, int nGatesMin, int * pnCellCount ) { char Buffer[200]; Vec_Str_t * vStr; SC_Cell * pRepr; SC_Pin * pPin; int i, k, Count = 2, nClassMax = 0; // find the largest number of cells in a class SC_LibForEachCellClass( p, pRepr, i ) if ( pRepr->n_outputs == 1 ) nClassMax = Abc_MaxInt( nClassMax, Abc_SclClassCellNum(pRepr) ); // update the number if ( nGatesMin && nGatesMin >= nClassMax ) nGatesMin = 0; // mark skipped cells Abc_SclMarkSkippedCells( p ); vStr = Vec_StrAlloc( 1000 ); Vec_StrPrintStr( vStr, "GATE _const0_ 0.00 z=CONST0;\n" ); Vec_StrPrintStr( vStr, "GATE _const1_ 0.00 z=CONST1;\n" ); SC_LibForEachCell( p, pRepr, i ) { if ( pRepr->n_inputs == 0 ) continue; if ( pRepr->n_outputs > 1 ) continue; if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin ) continue; // check if the gate is in the profile if ( pRepr->n_inputs > 1 ) { Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pRepr->pName, NULL ); if ( pGate == NULL || Mio_GateReadProfile(pGate) == 0 ) continue; } // process gate assert( strlen(pRepr->pName) < 200 ); Vec_StrPrintStr( vStr, "GATE " ); sprintf( Buffer, "%-16s", pRepr->pName ); Vec_StrPrintStr( vStr, Buffer ); Vec_StrPrintStr( vStr, " " ); // sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) ); sprintf( Buffer, "%7.2f", pRepr->area ); Vec_StrPrintStr( vStr, Buffer ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) ); Vec_StrPrintStr( vStr, "=" ); Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) ? SC_CellPinOutFunc(pRepr, 0) : "?" ); Vec_StrPrintStr( vStr, ";\n" ); SC_CellForEachPinIn( pRepr, pPin, k ) { float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain ); assert( Delay > 0 ); Vec_StrPrintStr( vStr, " PIN " ); sprintf( Buffer, "%-4s", pPin->pName ); Vec_StrPrintStr( vStr, Buffer ); sprintf( Buffer, " UNKNOWN 1 999 %7.2f 0.00 %7.2f 0.00\n", Delay, Delay ); Vec_StrPrintStr( vStr, Buffer ); } Count++; } Vec_StrPrintStr( vStr, "\n.end\n" ); Vec_StrPush( vStr, '\0' ); // printf( "GENLIB library with %d gates is produced:\n", Count ); // printf( "%s", Vec_StrArray(vStr) ); if ( pnCellCount ) *pnCellCount = Count; return vStr; } void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float SlewInit, float Gain, int nGatesMin ) { int nCellCount = 0; char FileName[1000]; float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit; Vec_Str_t * vStr; FILE * pFile; if ( pFileName == NULL ) sprintf( FileName, "%s_s%03d_g%03d_m%d.genlib", p->pName, (int)Slew, (int)Gain, nGatesMin ); else sprintf( FileName, "%s", pFileName ); pFile = fopen( FileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", FileName ); return; } vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount ); fprintf( pFile, "%s", Vec_StrArray(vStr) ); Vec_StrFree( vStr ); fclose( pFile ); printf( "Written GENLIB library with %d gates into file \"%s\".\n", nCellCount, FileName ); } Mio_Library_t * Abc_SclDeriveGenlib( void * pScl, void * pMio, float SlewInit, float Gain, int nGatesMin, int fVerbose ) { int nCellCount = 0; SC_Lib * p = (SC_Lib *)pScl; float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit; Vec_Str_t * vStr; Mio_Library_t * pLib; if ( pMio == NULL ) vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount ); else vStr = Abc_SclProduceGenlibStrProfile( p, (Mio_Library_t *)pMio, Slew, Gain, nGatesMin, &nCellCount ); pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0 ); Vec_StrFree( vStr ); if ( !pLib ) printf( "Reading library has filed.\n" ); else if ( fVerbose ) printf( "Derived GENLIB library \"%s\" with %d gates using slew %.2f ps and gain %.2f.\n", p->pName, nCellCount, Slew, Gain ); return pLib; } /**Function************************************************************* Synopsis [Install library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclInstallGenlib( void * pScl, float SlewInit, float Gain, int nGatesMin ) { SC_Lib * p = (SC_Lib *)pScl; Vec_Str_t * vStr, * vStr2; float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit; int RetValue, nGateCount = SC_LibCellNum(p); if ( Gain == 0 ) vStr = Abc_SclProduceGenlibStrSimple(p); else vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nGateCount ); vStr2 = Vec_StrDup( vStr ); RetValue = Mio_UpdateGenlib2( vStr, vStr2, p->pName, 0 ); Vec_StrFree( vStr ); Vec_StrFree( vStr2 ); if ( !RetValue ) printf( "Reading library has filed.\n" ); else if ( Gain != 0 ) printf( "Derived GENLIB library \"%s\" with %d gates using slew %.2f ps and gain %.2f.\n", p->pName, nGateCount, Slew, Gain ); // else // printf( "Derived unit-delay GENLIB library \"%s\" with %d gates.\n", p->pName, nGateCount ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclLiberty.c000066400000000000000000001775351300674244400236740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclLiberty.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Liberty parser.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclLiberty.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclLib.h" #include "misc/st/st.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_MAX_LIB_STR_LEN 5000 // entry types typedef enum { SCL_LIBERTY_NONE = 0, // 0: unknown SCL_LIBERTY_PROC, // 1: procedure : key(head){body} SCL_LIBERTY_EQUA, // 2: equation : key:head; SCL_LIBERTY_LIST // 3: list : key(head) } Scl_LibertyType_t; typedef struct Scl_Pair_t_ Scl_Pair_t; struct Scl_Pair_t_ { int Beg; // item beginning int End; // item end }; typedef struct Scl_Item_t_ Scl_Item_t; struct Scl_Item_t_ { int Type; // Scl_LibertyType_t int iLine; // file line where the item's spec begins Scl_Pair_t Key; // key part Scl_Pair_t Head; // head part Scl_Pair_t Body; // body part int Next; // next item in the list int Child; // first child item }; typedef struct Scl_Tree_t_ Scl_Tree_t; struct Scl_Tree_t_ { char * pFileName; // input Liberty file name char * pContents; // file contents int nContents; // file size int nLines; // line counter int nItems; // number of items int nItermAlloc; // number of items allocated Scl_Item_t * pItems; // the items char * pError; // the error string abctime clkStart; // beginning time }; static inline Scl_Item_t * Scl_LibertyRoot( Scl_Tree_t * p ) { return p->pItems; } static inline Scl_Item_t * Scl_LibertyItem( Scl_Tree_t * p, int v ) { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v; } static inline int Scl_LibertyCompare( Scl_Tree_t * p, Scl_Pair_t Pair, char * pStr ) { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ) || ((int)strlen(pStr) != Pair.End-Pair.Beg); } static inline void Scl_PrintWord( FILE * pFile, Scl_Tree_t * p, Scl_Pair_t Pair ) { char * pBeg = p->pContents+Pair.Beg, * pEnd = p->pContents+Pair.End; while ( pBeg < pEnd ) fputc( *pBeg++, pFile ); } static inline void Scl_PrintSpace( FILE * pFile, int nOffset ) { int i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile); } static inline int Scl_LibertyItemId( Scl_Tree_t * p, Scl_Item_t * pItem ) { return pItem - p->pItems; } #define Scl_ItemForEachChild( p, pItem, pChild ) \ for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) ) #define Scl_ItemForEachChildName( p, pItem, pChild, pName ) \ for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) ) if ( Scl_LibertyCompare(p, pChild->Key, pName) ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prints parse tree in Liberty format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Scl_LibertyParseDumpItem( FILE * pFile, Scl_Tree_t * p, Scl_Item_t * pItem, int nOffset ) { if ( pItem->Type == SCL_LIBERTY_PROC ) { Scl_PrintSpace( pFile, nOffset ); Scl_PrintWord( pFile, p, pItem->Key ); fprintf( pFile, "(" ); Scl_PrintWord( pFile, p, pItem->Head ); fprintf( pFile, ") {\n" ); if ( Scl_LibertyItem(p, pItem->Child) ) Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyItem(p, pItem->Child), nOffset + 2 ); Scl_PrintSpace( pFile, nOffset ); fprintf( pFile, "}\n" ); } else if ( pItem->Type == SCL_LIBERTY_EQUA ) { Scl_PrintSpace( pFile, nOffset ); Scl_PrintWord( pFile, p, pItem->Key ); fprintf( pFile, " : " ); Scl_PrintWord( pFile, p, pItem->Head ); fprintf( pFile, ";\n" ); } else if ( pItem->Type == SCL_LIBERTY_LIST ) { Scl_PrintSpace( pFile, nOffset ); Scl_PrintWord( pFile, p, pItem->Key ); fprintf( pFile, "(" ); Scl_PrintWord( pFile, p, pItem->Head ); fprintf( pFile, ");\n" ); } else assert( 0 ); if ( Scl_LibertyItem(p, pItem->Next) ) Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyItem(p, pItem->Next), nOffset ); } int Scl_LibertyParseDump( Scl_Tree_t * p, char * pFileName ) { FILE * pFile; if ( pFileName == NULL ) pFile = stdout; else { pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Scl_LibertyParseDump(): The output file is unavailable (absent or open).\n" ); return 0; } } Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyRoot(p), 0 ); if ( pFile != stdout ) fclose( pFile ); return 1; } /**Function************************************************************* Synopsis [Gets the name to write.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_LibertyCountItems( char * pBeg, char * pEnd ) { int Counter = 0; for ( ; pBeg < pEnd; pBeg++ ) Counter += (*pBeg == '(' || *pBeg == ':'); return Counter; } // removes C-style comments /* void Scl_LibertyWipeOutComments( char * pBeg, char * pEnd ) { char * pCur, * pStart; for ( pCur = pBeg; pCur < pEnd; pCur++ ) if ( pCur[0] == '/' && pCur[1] == '*' ) for ( pStart = pCur; pCur < pEnd; pCur++ ) if ( pCur[0] == '*' && pCur[1] == '/' ) { for ( ; pStart < pCur + 2; pStart++ ) if ( *pStart != '\n' ) *pStart = ' '; break; } } */ void Scl_LibertyWipeOutComments( char * pBeg, char * pEnd ) { char * pCur, * pStart; for ( pCur = pBeg; pCur < pEnd-1; pCur++ ) if ( pCur[0] == '/' && pCur[1] == '*' ) { for ( pStart = pCur; pCur < pEnd-1; pCur++ ) if ( pCur[0] == '*' && pCur[1] == '/' ) { for ( ; pStart < pCur + 2; pStart++ ) if ( *pStart != '\n' ) *pStart = ' '; break; } } else if ( pCur[0] == '/' && pCur[1] == '/' ) { for ( pStart = pCur; pCur < pEnd; pCur++ ) if ( pCur[0] == '\n' || pCur == pEnd-1 ) { for ( ; pStart < pCur; pStart++ ) *pStart = ' '; break; } } } static inline int Scl_LibertyCharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\'; } static inline int Scl_LibertySkipSpaces( Scl_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine ) { char * pPos = *ppPos; for ( ; pPos < pEnd; pPos++ ) { if ( *pPos == '\n' ) { p->nLines++; if ( fStopAtNewLine ) break; } if ( !Scl_LibertyCharIsSpace(*pPos) ) break; } *ppPos = pPos; return pPos == pEnd; } // skips entry delimited by " :;(){}" and returns 1 if reached the end static inline int Scl_LibertySkipEntry( char ** ppPos, char * pEnd ) { char * pPos = *ppPos; if ( *pPos == '\"' ) { for ( pPos++; pPos < pEnd; pPos++ ) if ( *pPos == '\"' ) { pPos++; break; } } else { for ( ; pPos < pEnd; pPos++ ) if ( *pPos == ' ' || *pPos == '\r' || *pPos == '\n' || *pPos == '\t' || *pPos == ':' || *pPos == ';' || *pPos == '(' || *pPos == ')' || *pPos == '{' || *pPos == '}' ) break; } *ppPos = pPos; return pPos == pEnd; } // finds the matching closing symbol static inline char * Scl_LibertyFindMatch( char * pPos, char * pEnd ) { int Counter = 0; assert( *pPos == '(' || *pPos == '{' ); if ( *pPos == '(' ) { for ( ; pPos < pEnd; pPos++ ) { if ( *pPos == '(' ) Counter++; if ( *pPos == ')' ) Counter--; if ( Counter == 0 ) break; } } else { for ( ; pPos < pEnd; pPos++ ) { if ( *pPos == '{' ) Counter++; if ( *pPos == '}' ) Counter--; if ( Counter == 0 ) break; } } assert( *pPos == ')' || *pPos == '}' ); return pPos; } // trims spaces around the head static inline Scl_Pair_t Scl_LibertyUpdateHead( Scl_Tree_t * p, Scl_Pair_t Head ) { Scl_Pair_t Res; char * pBeg = p->pContents + Head.Beg; char * pEnd = p->pContents + Head.End; char * pFirstNonSpace = NULL; char * pLastNonSpace = NULL; char * pChar; for ( pChar = pBeg; pChar < pEnd; pChar++ ) { if ( *pChar == '\n' ) p->nLines++; if ( Scl_LibertyCharIsSpace(*pChar) ) continue; pLastNonSpace = pChar; if ( pFirstNonSpace == NULL ) pFirstNonSpace = pChar; } if ( pFirstNonSpace == NULL || pLastNonSpace == NULL ) return Head; assert( pFirstNonSpace && pLastNonSpace ); Res.Beg = pFirstNonSpace - p->pContents; Res.End = pLastNonSpace - p->pContents + 1; return Res; } // returns new item static inline Scl_Item_t * Scl_LibertyNewItem( Scl_Tree_t * p, int Type ) { p->pItems[p->nItems].iLine = p->nLines; p->pItems[p->nItems].Type = Type; p->pItems[p->nItems].Child = -1; p->pItems[p->nItems].Next = -1; return p->pItems + p->nItems++; } /**Function************************************************************* Synopsis [Gets the name to write.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Scl_LibertyReadString( Scl_Tree_t * p, Scl_Pair_t Pair ) { static char Buffer[ABC_MAX_LIB_STR_LEN]; assert( Pair.End-Pair.Beg < ABC_MAX_LIB_STR_LEN ); strncpy( Buffer, p->pContents+Pair.Beg, Pair.End-Pair.Beg ); if ( Pair.Beg < Pair.End && Buffer[0] == '\"' ) { assert( Buffer[Pair.End-Pair.Beg-1] == '\"' ); Buffer[Pair.End-Pair.Beg-1] = 0; return Buffer + 1; } Buffer[Pair.End-Pair.Beg] = 0; return Buffer; } int Scl_LibertyItemNum( Scl_Tree_t * p, Scl_Item_t * pRoot, char * pName ) { Scl_Item_t * pItem; int Counter = 0; Scl_ItemForEachChildName( p, pRoot, pItem, pName ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Returns free item.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_LibertyBuildItem( Scl_Tree_t * p, char ** ppPos, char * pEnd ) { Scl_Item_t * pItem; Scl_Pair_t Key, Head, Body; char * pNext, * pStop; Key.End = 0; if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) return -2; Key.Beg = *ppPos - p->pContents; if ( Scl_LibertySkipEntry( ppPos, pEnd ) ) goto exit; Key.End = *ppPos - p->pContents; if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) goto exit; pNext = *ppPos; if ( *pNext == ':' ) { *ppPos = pNext + 1; if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) goto exit; Head.Beg = *ppPos - p->pContents; if ( Scl_LibertySkipEntry( ppPos, pEnd ) ) goto exit; Head.End = *ppPos - p->pContents; if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 1 ) ) goto exit; pNext = *ppPos; if ( *pNext != ';' && *pNext != '\n' ) goto exit; *ppPos = pNext + 1; // end of equation pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_EQUA ); pItem->Key = Key; pItem->Head = Scl_LibertyUpdateHead( p, Head ); pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd ); if ( pItem->Next == -1 ) goto exit; return Scl_LibertyItemId( p, pItem ); } if ( *pNext == '(' ) { pStop = Scl_LibertyFindMatch( pNext, pEnd ); Head.Beg = pNext - p->pContents + 1; Head.End = pStop - p->pContents; *ppPos = pStop + 1; if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) { // end of list pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_LIST ); pItem->Key = Key; pItem->Head = Scl_LibertyUpdateHead( p, Head ); return Scl_LibertyItemId( p, pItem ); } pNext = *ppPos; if ( *pNext == '{' ) // beginning of body { pStop = Scl_LibertyFindMatch( pNext, pEnd ); Body.Beg = pNext - p->pContents + 1; Body.End = pStop - p->pContents; // end of body pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_PROC ); pItem->Key = Key; pItem->Head = Scl_LibertyUpdateHead( p, Head ); pItem->Body = Body; *ppPos = pNext + 1; pItem->Child = Scl_LibertyBuildItem( p, ppPos, pStop ); if ( pItem->Child == -1 ) goto exit; *ppPos = pStop + 1; pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd ); if ( pItem->Next == -1 ) goto exit; return Scl_LibertyItemId( p, pItem ); } // end of list if ( *pNext == ';' ) *ppPos = pNext + 1; pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_LIST ); pItem->Key = Key; pItem->Head = Scl_LibertyUpdateHead( p, Head ); pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd ); if ( pItem->Next == -1 ) goto exit; return Scl_LibertyItemId( p, pItem ); } if ( *pNext == ';' ) { *ppPos = pNext + 1; return Scl_LibertyBuildItem(p, ppPos, pEnd); } exit: if ( p->pError == NULL ) { p->pError = ABC_ALLOC( char, 1000 ); sprintf( p->pError, "File \"%s\". Line %6d. Failed to parse entry \"%s\".\n", p->pFileName, p->nLines, Scl_LibertyReadString(p, Key) ); } return -1; } /**Function************************************************************* Synopsis [File management.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Scl_LibertyFixFileName( char * pFileName ) { char * pHead; for ( pHead = pFileName; *pHead; pHead++ ) if ( *pHead == '>' ) *pHead = '\\'; } int Scl_LibertyFileSize( char * pFileName ) { FILE * pFile; int nFileSize; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Scl_LibertyFileSize(): The input file is unavailable (absent or open).\n" ); return 0; } fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); fclose( pFile ); return nFileSize; } char * Scl_LibertyFileContents( char * pFileName, int nContents ) { FILE * pFile = fopen( pFileName, "rb" ); char * pContents = ABC_ALLOC( char, nContents+1 ); int RetValue; RetValue = fread( pContents, nContents, 1, pFile ); fclose( pFile ); pContents[nContents] = 0; return pContents; } void Scl_LibertyStringDump( char * pFileName, Vec_Str_t * vStr ) { FILE * pFile = fopen( pFileName, "wb" ); int RetValue; if ( pFile == NULL ) { printf( "Scl_LibertyStringDump(): The output file is unavailable.\n" ); return; } RetValue = fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); fclose( pFile ); } /**Function************************************************************* Synopsis [Starts the parsing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Scl_Tree_t * Scl_LibertyStart( char * pFileName ) { Scl_Tree_t * p; int RetValue; // read the file into the buffer Scl_LibertyFixFileName( pFileName ); RetValue = Scl_LibertyFileSize( pFileName ); if ( RetValue == 0 ) return NULL; // start the manager p = ABC_ALLOC( Scl_Tree_t, 1 ); memset( p, 0, sizeof(Scl_Tree_t) ); p->clkStart = Abc_Clock(); p->nContents = RetValue; p->pContents = Scl_LibertyFileContents( pFileName, p->nContents ); // other p->pFileName = Abc_UtilStrsav( pFileName ); p->nItermAlloc = 10 + Scl_LibertyCountItems( p->pContents, p->pContents+p->nContents ); p->pItems = ABC_CALLOC( Scl_Item_t, p->nItermAlloc ); p->nItems = 0; p->nLines = 1; return p; } void Scl_LibertyStop( Scl_Tree_t * p, int fVerbose ) { if ( fVerbose ) { printf( "Memory = %7.2f MB. ", 1.0 * (p->nContents + p->nItermAlloc * sizeof(Scl_Item_t))/(1<<20) ); ABC_PRT( "Time", Abc_Clock() - p->clkStart ); } ABC_FREE( p->pFileName ); ABC_FREE( p->pContents ); ABC_FREE( p->pItems ); ABC_FREE( p->pError ); ABC_FREE( p ); } Scl_Tree_t * Scl_LibertyParse( char * pFileName, int fVerbose ) { Scl_Tree_t * p; char * pPos; if ( (p = Scl_LibertyStart(pFileName)) == NULL ) return NULL; pPos = p->pContents; Scl_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents ); if ( !Scl_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 ) { if ( p->pError ) printf( "%s", p->pError ); printf( "Parsing failed. " ); Abc_PrintTime( 1, "Parsing time", Abc_Clock() - p->clkStart ); } else if ( fVerbose ) { printf( "Parsing finished successfully. " ); Abc_PrintTime( 1, "Parsing time", Abc_Clock() - p->clkStart ); } return p; } /**Function************************************************************* Synopsis [Fetching attributes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Scl_LibertyReadCellIsFlop( Scl_Tree_t * p, Scl_Item_t * pCell ) { Scl_Item_t * pAttr; Scl_ItemForEachChild( p, pCell, pAttr ) if ( !Scl_LibertyCompare(p, pAttr->Key, "ff") || !Scl_LibertyCompare(p, pAttr->Key, "latch") ) return 1; return 0; } char * Scl_LibertyReadCellArea( Scl_Tree_t * p, Scl_Item_t * pCell ) { Scl_Item_t * pArea; Scl_ItemForEachChildName( p, pCell, pArea, "area" ) return Scl_LibertyReadString(p, pArea->Head); return 0; } char * Scl_LibertyReadCellLeakage( Scl_Tree_t * p, Scl_Item_t * pCell ) { Scl_Item_t * pItem, * pChild; Scl_ItemForEachChildName( p, pCell, pItem, "cell_leakage_power" ) return Scl_LibertyReadString(p, pItem->Head); // look for another type Scl_ItemForEachChildName( p, pCell, pItem, "leakage_power" ) { Scl_ItemForEachChildName( p, pItem, pChild, "when" ) break; if ( pChild && !Scl_LibertyCompare(p, pChild->Key, "when") ) continue; Scl_ItemForEachChildName( p, pItem, pChild, "value" ) return Scl_LibertyReadString(p, pChild->Head); } return 0; } char * Scl_LibertyReadPinFormula( Scl_Tree_t * p, Scl_Item_t * pPin ) { Scl_Item_t * pFunc; Scl_ItemForEachChildName( p, pPin, pFunc, "function" ) return Scl_LibertyReadString(p, pFunc->Head); return NULL; } int Scl_LibertyReadCellIsThreeState( Scl_Tree_t * p, Scl_Item_t * pCell ) { Scl_Item_t * pPin, * pItem; Scl_ItemForEachChildName( p, pCell, pPin, "pin" ) Scl_ItemForEachChildName( p, pPin, pItem, "three_state" ) return 1; return 0; } int Scl_LibertyReadCellOutputNum( Scl_Tree_t * p, Scl_Item_t * pCell ) { Scl_Item_t * pPin; int Counter = 0; Scl_ItemForEachChildName( p, pCell, pPin, "pin" ) if ( Scl_LibertyReadPinFormula(p, pPin) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Parses the standard cell library in Liberty format.] Description [Writes the resulting file in Genlib format.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Scl_LibertyReadGenlibStr( Scl_Tree_t * p, int fVerbose ) { Vec_Str_t * vStr; Scl_Item_t * pCell, * pOutput, * pInput; char * pFormula; vStr = Vec_StrAlloc( 1000 ); Vec_StrPrintStr( vStr, "GATE _const0_ 0.000000 z=CONST0;\n" ); Vec_StrPrintStr( vStr, "GATE _const1_ 0.000000 z=CONST1;\n" ); Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" ) { if ( Scl_LibertyReadCellIsFlop(p, pCell) ) { if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) ); continue; } if ( Scl_LibertyReadCellIsThreeState(p, pCell) ) { if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) ); continue; } if ( Scl_LibertyReadCellOutputNum(p, pCell) == 0 ) { if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" without logic function.\n", Scl_LibertyReadString(p, pCell->Head) ); continue; } // iterate through output pins Scl_ItemForEachChildName( p, pCell, pOutput, "pin" ) { if ( (pFormula = Scl_LibertyReadPinFormula(p, pOutput)) ) continue; if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1") ) { if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Scl_LibertyReadString(p, pCell->Head), pFormula ); break; } Vec_StrPrintStr( vStr, "GATE " ); Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pCell->Head) ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Scl_LibertyReadCellArea(p, pCell) ); Vec_StrPrintStr( vStr, " " ); Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pOutput->Head) ); Vec_StrPrintStr( vStr, "=" ); Vec_StrPrintStr( vStr, pFormula ); Vec_StrPrintStr( vStr, ";\n" ); // iterate through input pins Scl_ItemForEachChildName( p, pCell, pInput, "pin" ) { if ( Scl_LibertyReadPinFormula(p, pInput) == NULL ) continue; Vec_StrPrintStr( vStr, " PIN " ); Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pInput->Head) ); Vec_StrPrintStr( vStr, " UNKNOWN 1 999 1.00 0.00 1.00 0.00\n" ); } } } Vec_StrPrintStr( vStr, "\n.end\n" ); Vec_StrPush( vStr, '\0' ); // printf( "%s", Vec_StrArray(vStr) ); return vStr; } Vec_Str_t * Scl_LibertyParseGenlibStr( char * pFileName, int fVerbose ) { Scl_Tree_t * p; Vec_Str_t * vStr; p = Scl_LibertyParse( pFileName, fVerbose ); if ( p == NULL ) return NULL; // Scl_LibertyRead( p, "temp_.lib" ); vStr = Scl_LibertyReadGenlibStr( p, fVerbose ); Scl_LibertyStop( p, fVerbose ); // Scl_LibertyStringDump( "test_genlib.lib", vStr ); return vStr; } /**Function************************************************************* Synopsis [Enabling debug output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //#define SCL_DEBUG #ifdef SCL_DEBUG static inline void Vec_StrPutI_( Vec_Str_t * vOut, int Val ) { printf( "%d ", Val ); Vec_StrPutI( vOut, Val ); } static inline void Vec_StrPutW_( Vec_Str_t * vOut, word Val ) { printf( "%lu ", Val ); Vec_StrPutW( vOut, Val ); } static inline void Vec_StrPutF_( Vec_Str_t * vOut, float Val ) { printf( "%f ", Val ); Vec_StrPutF( vOut, Val ); } static inline void Vec_StrPutS_( Vec_Str_t * vOut, char * Val ) { printf( "%s ", Val ); Vec_StrPutS( vOut, Val ); } static inline void Vec_StrPut_( Vec_Str_t * vOut ) { printf( "\n" ); } #else static inline void Vec_StrPutI_( Vec_Str_t * vOut, int Val ) { Vec_StrPutI( vOut, Val ); } static inline void Vec_StrPutW_( Vec_Str_t * vOut, word Val ) { Vec_StrPutW( vOut, Val ); } static inline void Vec_StrPutF_( Vec_Str_t * vOut, float Val ) { Vec_StrPutF( vOut, Val ); } static inline void Vec_StrPutS_( Vec_Str_t * vOut, char * Val ) { Vec_StrPutS( vOut, Val ); } static inline void Vec_StrPut_( Vec_Str_t * vOut ) { } #endif /**Function************************************************************* Synopsis [Parsing Liberty into internal data representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Scl_LibertyReadDefaultWireLoad( Scl_Tree_t * p ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_wire_load" ) return Scl_LibertyReadString(p, pItem->Head); return ""; } char * Scl_LibertyReadDefaultWireLoadSel( Scl_Tree_t * p ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_wire_load_selection" ) return Scl_LibertyReadString(p, pItem->Head); return ""; } float Scl_LibertyReadDefaultMaxTrans( Scl_Tree_t * p ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_max_transition" ) return atof(Scl_LibertyReadString(p, pItem->Head)); return 0; } int Scl_LibertyReadTimeUnit( Scl_Tree_t * p ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "time_unit" ) { char * pUnit = Scl_LibertyReadString(p, pItem->Head); // 9=1ns, 10=100ps, 11=10ps, 12=1ps if ( !strcmp(pUnit, "1ns") ) return 9; if ( !strcmp(pUnit, "100ps") ) return 10; if ( !strcmp(pUnit, "10ps") ) return 11; if ( !strcmp(pUnit, "1ps") ) return 12; break; } printf( "Libery parser cannot read \"time_unit\". Assuming time_unit : \"1ns\".\n" ); return 9; } void Scl_LibertyReadLoadUnit( Scl_Tree_t * p, Vec_Str_t * vOut ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "capacitive_load_unit" ) { // expecting (1.00,ff) or (1, pf) ... 12 or 15 for 'pf' or 'ff' char * pHead = Scl_LibertyReadString(p, pItem->Head); float First = atof(strtok(pHead, " \t\n\r\\\",")); char * pSecond = strtok(NULL, " \t\n\r\\\","); Vec_StrPutF_( vOut, First ); if ( pSecond && !strcmp(pSecond, "pf") ) Vec_StrPutI_( vOut, 12 ); else if ( pSecond && !strcmp(pSecond, "ff") ) Vec_StrPutI_( vOut, 15 ); else break; return; } printf( "Libery parser cannot read \"capacitive_load_unit\". Assuming capacitive_load_unit(1, pf).\n" ); Vec_StrPutF_( vOut, 1.0 ); Vec_StrPutI_( vOut, 12 ); } void Scl_LibertyReadWireLoad( Scl_Tree_t * p, Vec_Str_t * vOut ) { Scl_Item_t * pItem, * pChild; Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, Scl_LibertyRoot(p), "wire_load") ); Vec_StrPut_( vOut ); Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "wire_load" ) { Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pItem->Head) ); Scl_ItemForEachChildName( p, pItem, pChild, "capacitance" ) Vec_StrPutF_( vOut, atof(Scl_LibertyReadString(p, pChild->Head)) ); Scl_ItemForEachChildName( p, pItem, pChild, "slope" ) Vec_StrPutF_( vOut, atof(Scl_LibertyReadString(p, pChild->Head)) ); Vec_StrPut_( vOut ); Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pItem, "fanout_length") ); Vec_StrPut_( vOut ); Scl_ItemForEachChildName( p, pItem, pChild, "fanout_length" ) { char * pHead = Scl_LibertyReadString(p, pChild->Head); int First = atoi( strtok(pHead, " ,") ); float Second = atof( strtok(NULL, " ") ); Vec_StrPutI_( vOut, First ); Vec_StrPutF_( vOut, Second ); Vec_StrPut_( vOut ); } Vec_StrPut_( vOut ); } Vec_StrPut_( vOut ); } void Scl_LibertyReadWireLoadSelect( Scl_Tree_t * p, Vec_Str_t * vOut ) { Scl_Item_t * pItem, * pChild; Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, Scl_LibertyRoot(p), "wire_load_selection") ); Vec_StrPut_( vOut ); Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "wire_load_selection" ) { Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pItem->Head) ); Vec_StrPut_( vOut ); Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pItem, "wire_load_from_area") ); Vec_StrPut_( vOut ); Scl_ItemForEachChildName( p, pItem, pChild, "wire_load_from_area" ) { char * pHead = Scl_LibertyReadString(p, pChild->Head); float First = atof( strtok(pHead, " ,") ); float Second = atof( strtok(NULL, " ,") ); char * pThird = strtok(NULL, " "); if ( pThird[0] == '\"' ) assert(pThird[strlen(pThird)-1] == '\"'), pThird[strlen(pThird)-1] = 0, pThird++; Vec_StrPutF_( vOut, First ); Vec_StrPutF_( vOut, Second ); Vec_StrPutS_( vOut, pThird ); Vec_StrPut_( vOut ); } Vec_StrPut_( vOut ); } Vec_StrPut_( vOut ); } int Scl_LibertyReadDeriveStrength( Scl_Tree_t * p, Scl_Item_t * pCell ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, pCell, pItem, "drive_strength" ) return atoi(Scl_LibertyReadString(p, pItem->Head)); return 0; } int Scl_LibertyReadPinDirection( Scl_Tree_t * p, Scl_Item_t * pPin ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, pPin, pItem, "direction" ) { char * pToken = Scl_LibertyReadString(p, pItem->Head); if ( !strcmp(pToken, "input") ) return 0; if ( !strcmp(pToken, "output") ) return 1; break; } return -1; } float Scl_LibertyReadPinCap( Scl_Tree_t * p, Scl_Item_t * pPin, char * pName ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, pPin, pItem, pName ) return atof(Scl_LibertyReadString(p, pItem->Head)); return 0; } Scl_Item_t * Scl_LibertyReadPinTiming( Scl_Tree_t * p, Scl_Item_t * pPinOut, char * pNameIn ) { Scl_Item_t * pTiming, * pPinIn; Scl_ItemForEachChildName( p, pPinOut, pTiming, "timing" ) Scl_ItemForEachChildName( p, pTiming, pPinIn, "related_pin" ) if ( !strcmp(Scl_LibertyReadString(p, pPinIn->Head), pNameIn) ) return pTiming; return NULL; } Vec_Ptr_t * Scl_LibertyReadPinTimingAll( Scl_Tree_t * p, Scl_Item_t * pPinOut, char * pNameIn ) { Vec_Ptr_t * vTimings; Scl_Item_t * pTiming, * pPinIn; vTimings = Vec_PtrAlloc( 16 ); Scl_ItemForEachChildName( p, pPinOut, pTiming, "timing" ) Scl_ItemForEachChildName( p, pTiming, pPinIn, "related_pin" ) if ( !strcmp(Scl_LibertyReadString(p, pPinIn->Head), pNameIn) ) Vec_PtrPush( vTimings, pTiming ); return vTimings; } int Scl_LibertyReadTimingSense( Scl_Tree_t * p, Scl_Item_t * pPin ) { Scl_Item_t * pItem; Scl_ItemForEachChildName( p, pPin, pItem, "timing_sense" ) { char * pToken = Scl_LibertyReadString(p, pItem->Head); if ( !strcmp(pToken, "positive_unate") ) return sc_ts_Pos; if ( !strcmp(pToken, "negative_unate") ) return sc_ts_Neg; if ( !strcmp(pToken, "non_unate") ) return sc_ts_Non; break; } return sc_ts_Non; } Vec_Flt_t * Scl_LibertyReadFloatVec( char * pName ) { char * pToken; Vec_Flt_t * vValues = Vec_FltAlloc( 100 ); for ( pToken = strtok(pName, " \t\n\r\\\","); pToken; pToken = strtok(NULL, " \t\n\r\\\",") ) Vec_FltPush( vValues, atof(pToken) ); return vValues; } void Scl_LibertyDumpTables( Vec_Str_t * vOut, Vec_Flt_t * vInd1, Vec_Flt_t * vInd2, Vec_Flt_t * vValues ) { int i; float Entry; // write entries Vec_StrPutI_( vOut, Vec_FltSize(vInd1) ); Vec_FltForEachEntry( vInd1, Entry, i ) Vec_StrPutF_( vOut, Entry ); Vec_StrPut_( vOut ); // write entries Vec_StrPutI_( vOut, Vec_FltSize(vInd2) ); Vec_FltForEachEntry( vInd2, Entry, i ) Vec_StrPutF_( vOut, Entry ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // write entries assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) ); Vec_FltForEachEntry( vValues, Entry, i ) { Vec_StrPutF_( vOut, Entry ); if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 ) Vec_StrPut_( vOut ); } // dump approximations Vec_StrPut_( vOut ); for ( i = 0; i < 3; i++ ) Vec_StrPutF_( vOut, 0 ); for ( i = 0; i < 4; i++ ) Vec_StrPutF_( vOut, 0 ); for ( i = 0; i < 6; i++ ) Vec_StrPutF_( vOut, 0 ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); } int Scl_LibertyScanTable( Scl_Tree_t * p, Vec_Ptr_t * vOut, Scl_Item_t * pTiming, char * pName, Vec_Ptr_t * vTemples ) { Vec_Flt_t * vIndex1 = NULL; Vec_Flt_t * vIndex2 = NULL; Vec_Flt_t * vValues = NULL; Vec_Flt_t * vInd1, * vInd2; Scl_Item_t * pItem, * pTable = NULL; char * pThis, * pTempl = NULL; int iPlace, i; float Entry; // find the table Scl_ItemForEachChildName( p, pTiming, pTable, pName ) break; if ( pTable == NULL ) return 0; // find the template pTempl = Scl_LibertyReadString(p, pTable->Head); if ( pTempl == NULL || pTempl[0] == 0 ) { // read the numbers Scl_ItemForEachChild( p, pTable, pItem ) { if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") ) assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") ) assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "values") ) assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); } if ( vIndex1 == NULL || vIndex2 == NULL || vValues == NULL ) { printf( "Incomplete table specification\n" ); return 0; } // dump the table vInd1 = vIndex1; vInd2 = vIndex2; // write entries Vec_PtrPush( vOut, vInd1 ); Vec_PtrPush( vOut, vInd2 ); Vec_PtrPush( vOut, vValues ); } else if ( !strcmp(pTempl, "scalar") ) { Scl_ItemForEachChild( p, pTable, pItem ) if ( !Scl_LibertyCompare(p, pItem->Key, "values") ) { assert(vValues == NULL); vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); assert( Vec_FltSize(vValues) == 1 ); // write entries Vec_PtrPush( vOut, Vec_IntStart(1) ); Vec_PtrPush( vOut, Vec_IntStart(1) ); Vec_PtrPush( vOut, vValues ); break; } else { printf( "Cannot read \"scalar\" template\n" ); return 0; } } else { // fetch the template iPlace = -1; Vec_PtrForEachEntry( char *, vTemples, pThis, i ) if ( i % 4 == 0 && !strcmp(pTempl, pThis) ) { iPlace = i; break; } if ( iPlace == -1 ) { printf( "Template cannot be found in the template library\n" ); return 0; } // read the numbers Scl_ItemForEachChild( p, pTable, pItem ) { if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") ) assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") ) assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "values") ) assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); } // check the template style vInd1 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 2 ); // slew vInd2 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 3 ); // load if ( Vec_PtrEntry(vTemples, iPlace + 1) == NULL ) // normal order (vIndex1 is slew; vIndex2 is load) { assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) ); assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd2) ); vInd1 = vIndex1 ? vIndex1 : vInd1; vInd2 = vIndex2 ? vIndex2 : vInd2; // write entries Vec_PtrPush( vOut, Vec_FltDup(vInd1) ); Vec_PtrPush( vOut, Vec_FltDup(vInd2) ); Vec_PtrPush( vOut, Vec_FltDup(vValues) ); } else // reverse order (vIndex2 is slew; vIndex1 is load) { Vec_Flt_t * vValues2 = Vec_FltAlloc( Vec_FltSize(vValues) ); assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd1) ); assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd2) ); vInd1 = vIndex2 ? vIndex2 : vInd1; vInd2 = vIndex1 ? vIndex1 : vInd2; // write entries -- transpose assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) ); Vec_FltForEachEntry( vValues, Entry, i ) { int x = i % Vec_FltSize(vInd2); int y = i / Vec_FltSize(vInd2); Entry = Vec_FltEntry( vValues, x * Vec_FltSize(vInd1) + y ); Vec_FltPush( vValues2, Entry ); } assert( Vec_FltSize(vValues) == Vec_FltSize(vValues2) ); // write entries Vec_PtrPush( vOut, Vec_FltDup(vInd1) ); Vec_PtrPush( vOut, Vec_FltDup(vInd2) ); Vec_PtrPush( vOut, vValues2 ); } Vec_FltFreeP( &vIndex1 ); Vec_FltFreeP( &vIndex2 ); Vec_FltFreeP( &vValues ); } return 1; } int Scl_LibertyComputeWorstCase( Vec_Ptr_t * vTables, Vec_Flt_t ** pvInd0, Vec_Flt_t ** pvInd1, Vec_Flt_t ** pvValues ) { Vec_Flt_t * vInd0, * vInd1, * vValues; Vec_Flt_t * vind0, * vind1, * vvalues; int i, k, nTriples = Vec_PtrSize(vTables) / 3; float Entry; assert( Vec_PtrSize(vTables) > 0 && Vec_PtrSize(vTables) % 3 == 0 ); if ( nTriples == 1 ) { *pvInd0 = (Vec_Flt_t *)Vec_PtrEntry(vTables, 0); *pvInd1 = (Vec_Flt_t *)Vec_PtrEntry(vTables, 1); *pvValues = (Vec_Flt_t *)Vec_PtrEntry(vTables, 2); Vec_PtrShrink( vTables, 0 ); return 1; } vInd0 = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 0) ); vInd1 = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 1) ); vValues = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 2) ); for ( i = 1; i < nTriples; i++ ) { vind0 = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+0); vind1 = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+1); vvalues = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+2); // check equality of indexes if ( !Vec_FltEqual(vind0, vInd0) ) continue;//return 0; if ( !Vec_FltEqual(vind1, vInd1) ) continue;//return 0; // Vec_FltForEachEntry( vvalues, Entry, k ) // Vec_FltAddToEntry( vValues, k, Entry ); Vec_FltForEachEntry( vvalues, Entry, k ) if ( Vec_FltEntry(vValues, k) < Entry ) Vec_FltWriteEntry( vValues, k, Entry ); } // Vec_FltForEachEntry( vValues, Entry, k ) // Vec_FltWriteEntry( vValues, k, Entry/nTriples ); // return the result *pvInd0 = vInd0; *pvInd1 = vInd1; *pvValues = vValues; return 1; } int Scl_LibertyReadTable( Scl_Tree_t * p, Vec_Str_t * vOut, Scl_Item_t * pTiming, char * pName, Vec_Ptr_t * vTemples ) { Vec_Flt_t * vIndex1 = NULL; Vec_Flt_t * vIndex2 = NULL; Vec_Flt_t * vValues = NULL; Vec_Flt_t * vInd1, * vInd2; Scl_Item_t * pItem, * pTable = NULL; char * pThis, * pTempl = NULL; int iPlace, i; float Entry; // find the table Scl_ItemForEachChildName( p, pTiming, pTable, pName ) break; if ( pTable == NULL ) return 0; // find the template pTempl = Scl_LibertyReadString(p, pTable->Head); if ( pTempl == NULL || pTempl[0] == 0 ) { // read the numbers Scl_ItemForEachChild( p, pTable, pItem ) { if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") ) assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") ) assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "values") ) assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); } if ( vIndex1 == NULL || vIndex2 == NULL || vValues == NULL ) { printf( "Incomplete table specification\n" ); return 0; } // dump the table vInd1 = vIndex1; vInd2 = vIndex2; // write entries Vec_StrPutI_( vOut, Vec_FltSize(vInd1) ); Vec_FltForEachEntry( vInd1, Entry, i ) Vec_StrPutF_( vOut, Entry ); Vec_StrPut_( vOut ); // write entries Vec_StrPutI_( vOut, Vec_FltSize(vInd2) ); Vec_FltForEachEntry( vInd2, Entry, i ) Vec_StrPutF_( vOut, Entry ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // write entries assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) ); Vec_FltForEachEntry( vValues, Entry, i ) { Vec_StrPutF_( vOut, Entry ); if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 ) Vec_StrPut_( vOut ); } } else { // fetch the template iPlace = -1; Vec_PtrForEachEntry( char *, vTemples, pThis, i ) if ( i % 4 == 0 && !strcmp(pTempl, pThis) ) { iPlace = i; break; } if ( iPlace == -1 ) { printf( "Template cannot be found in the template library\n" ); return 0; } // read the numbers Scl_ItemForEachChild( p, pTable, pItem ) { if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") ) assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") ) assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "values") ) assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); } // check the template style vInd1 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 2 ); // slew vInd2 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 3 ); // load if ( Vec_PtrEntry(vTemples, iPlace + 1) == NULL ) // normal order (vIndex1 is slew; vIndex2 is load) { assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) ); assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd2) ); vInd1 = vIndex1 ? vIndex1 : vInd1; vInd2 = vIndex2 ? vIndex2 : vInd2; // write entries Vec_StrPutI_( vOut, Vec_FltSize(vInd1) ); Vec_FltForEachEntry( vInd1, Entry, i ) Vec_StrPutF_( vOut, Entry ); Vec_StrPut_( vOut ); // write entries Vec_StrPutI_( vOut, Vec_FltSize(vInd2) ); Vec_FltForEachEntry( vInd2, Entry, i ) Vec_StrPutF_( vOut, Entry ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // write entries assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) ); Vec_FltForEachEntry( vValues, Entry, i ) { Vec_StrPutF_( vOut, Entry ); if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 ) Vec_StrPut_( vOut ); } } else // reverse order (vIndex2 is slew; vIndex1 is load) { assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd1) ); assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd2) ); vInd1 = vIndex2 ? vIndex2 : vInd1; vInd2 = vIndex1 ? vIndex1 : vInd2; // write entries Vec_StrPutI_( vOut, Vec_FltSize(vInd1) ); Vec_FltForEachEntry( vInd1, Entry, i ) Vec_StrPutF_( vOut, Entry ); Vec_StrPut_( vOut ); // write entries Vec_StrPutI_( vOut, Vec_FltSize(vInd2) ); Vec_FltForEachEntry( vInd2, Entry, i ) Vec_StrPutF_( vOut, Entry ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // write entries -- transpose assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) ); Vec_FltForEachEntry( vValues, Entry, i ) { int x = i % Vec_FltSize(vInd2); int y = i / Vec_FltSize(vInd2); Entry = Vec_FltEntry( vValues, x * Vec_FltSize(vInd1) + y ); Vec_StrPutF_( vOut, Entry ); if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 ) Vec_StrPut_( vOut ); } } } Vec_StrPut_( vOut ); for ( i = 0; i < 3; i++ ) Vec_StrPutF_( vOut, 0 ); for ( i = 0; i < 4; i++ ) Vec_StrPutF_( vOut, 0 ); for ( i = 0; i < 6; i++ ) Vec_StrPutF_( vOut, 0 ); Vec_FltFreeP( &vIndex1 ); Vec_FltFreeP( &vIndex2 ); Vec_FltFreeP( &vValues ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); return 1; } void Scl_LibertyPrintTemplates( Vec_Ptr_t * vRes ) { Vec_Flt_t * vArray; int i; assert( Vec_PtrSize(vRes) % 4 == 0 ); printf( "There are %d slew/load templates\n", Vec_PtrSize(vRes) % 4 ); Vec_PtrForEachEntry( Vec_Flt_t *, vRes, vArray, i ) { if ( i % 4 == 0 ) printf( "%s\n", (char *)vArray ); else if ( i % 4 == 1 ) printf( "%d\n", (int)(vArray != NULL) ); else if ( i % 4 == 2 || i % 4 == 3 ) Vec_FltPrint( vArray ); if ( i % 4 == 3 ) printf( "\n" ); } } Vec_Ptr_t * Scl_LibertyReadTemplates( Scl_Tree_t * p ) { Vec_Ptr_t * vRes = NULL; Vec_Flt_t * vIndex1, * vIndex2; Scl_Item_t * pTempl, * pItem; char * pVar1, * pVar2; int fFlag0, fFlag1; vRes = Vec_PtrAlloc( 100 ); Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pTempl, "lu_table_template" ) { pVar1 = pVar2 = NULL; vIndex1 = vIndex2 = NULL; Scl_ItemForEachChild( p, pTempl, pItem ) { if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") ) assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") ) assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_1") ) assert(pVar1 == NULL), pVar1 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) ); else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_2") ) assert(pVar2 == NULL), pVar2 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) ); } if ( pVar1 == NULL || pVar2 == NULL ) { ABC_FREE( pVar1 ); ABC_FREE( pVar2 ); Vec_FltFreeP( &vIndex1 ); Vec_FltFreeP( &vIndex2 ); continue; } assert( pVar1 != NULL && pVar2 != NULL ); fFlag0 = (!strcmp(pVar1, "input_net_transition") && !strcmp(pVar2, "total_output_net_capacitance")); fFlag1 = (!strcmp(pVar2, "input_net_transition") && !strcmp(pVar1, "total_output_net_capacitance")); ABC_FREE( pVar1 ); ABC_FREE( pVar2 ); if ( !fFlag0 && !fFlag1 ) { Vec_FltFreeP( &vIndex1 ); Vec_FltFreeP( &vIndex2 ); continue; } Vec_PtrPush( vRes, Abc_UtilStrsav( Scl_LibertyReadString(p, pTempl->Head) ) ); Vec_PtrPush( vRes, fFlag0 ? NULL : (void *)(ABC_PTRINT_T)1 ); Vec_PtrPush( vRes, fFlag0 ? vIndex1 : vIndex2 ); Vec_PtrPush( vRes, fFlag0 ? vIndex2 : vIndex1 ); } if ( Vec_PtrSize(vRes) == 0 ) Abc_Print( 0, "Templates are not defined.\n" ); // print templates // printf( "Found %d templates\n", Vec_PtrSize(vRes)/4 ); // Scl_LibertyPrintTemplates( vRes ); return vRes; } Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbose ) { int fUseFirstTable = 0; Vec_Str_t * vOut; Vec_Ptr_t * vNameIns, * vTemples = NULL; Scl_Item_t * pCell, * pPin, * pTiming; Vec_Wrd_t * vTruth; char * pFormula, * pName; int i, k, Counter, nOutputs, nCells; int nSkipped[3] = {0}; // read delay-table templates vTemples = Scl_LibertyReadTemplates( p ); // start the library vOut = Vec_StrAlloc( 10000 ); Vec_StrPutI_( vOut, ABC_SCL_CUR_VERSION ); // top level information Vec_StrPut_( vOut ); Vec_StrPutS_( vOut, Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head) ); Vec_StrPutS_( vOut, Scl_LibertyReadDefaultWireLoad(p) ); Vec_StrPutS_( vOut, Scl_LibertyReadDefaultWireLoadSel(p) ); Vec_StrPutF_( vOut, Scl_LibertyReadDefaultMaxTrans(p) ); Vec_StrPutI_( vOut, Scl_LibertyReadTimeUnit(p) ); Scl_LibertyReadLoadUnit( p, vOut ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // read wire loads Scl_LibertyReadWireLoad( p, vOut ); Scl_LibertyReadWireLoadSelect( p, vOut ); // count cells nCells = 0; Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" ) { if ( Scl_LibertyReadCellIsFlop(p, pCell) ) { if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) ); nSkipped[0]++; continue; } if ( Scl_LibertyReadCellIsThreeState(p, pCell) ) { if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) ); nSkipped[1]++; continue; } if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 ) { if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" without logic function.\n", Scl_LibertyReadString(p, pCell->Head) ); nSkipped[2]++; continue; } nCells++; } // read cells Vec_StrPutI_( vOut, nCells ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" ) { if ( Scl_LibertyReadCellIsFlop(p, pCell) ) continue; if ( Scl_LibertyReadCellIsThreeState(p, pCell) ) continue; if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 ) continue; // top level information Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pCell->Head) ); pName = Scl_LibertyReadCellArea(p, pCell); Vec_StrPutF_( vOut, pName ? atof(pName) : 1 ); pName = Scl_LibertyReadCellLeakage(p, pCell); Vec_StrPutF_( vOut, pName ? atof(pName) : 0 ); Vec_StrPutI_( vOut, Scl_LibertyReadDeriveStrength(p, pCell) ); // pin count nOutputs = Scl_LibertyReadCellOutputNum( p, pCell ); Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pCell, "pin") - nOutputs ); Vec_StrPutI_( vOut, nOutputs ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // input pins vNameIns = Vec_PtrAlloc( 16 ); Scl_ItemForEachChildName( p, pCell, pPin, "pin" ) { float CapOne, CapRise, CapFall; if ( Scl_LibertyReadPinFormula(p, pPin) != NULL ) // skip output pin continue; assert( Scl_LibertyReadPinDirection(p, pPin) == 0 ); pName = Scl_LibertyReadString(p, pPin->Head); Vec_PtrPush( vNameIns, Abc_UtilStrsav(pName) ); Vec_StrPutS_( vOut, pName ); CapOne = Scl_LibertyReadPinCap( p, pPin, "capacitance" ); CapRise = Scl_LibertyReadPinCap( p, pPin, "rise_capacitance" ); CapFall = Scl_LibertyReadPinCap( p, pPin, "fall_capacitance" ); if ( CapRise == 0 ) CapRise = CapOne; if ( CapFall == 0 ) CapFall = CapOne; Vec_StrPutF_( vOut, CapRise ); Vec_StrPutF_( vOut, CapFall ); Vec_StrPut_( vOut ); } Vec_StrPut_( vOut ); // output pins Scl_ItemForEachChildName( p, pCell, pPin, "pin" ) { if ( !Scl_LibertyReadPinFormula(p, pPin) ) // skip input pin continue; assert( Scl_LibertyReadPinDirection(p, pPin) == 1 ); pName = Scl_LibertyReadString(p, pPin->Head); Vec_StrPutS_( vOut, pName ); Vec_StrPutF_( vOut, Scl_LibertyReadPinCap( p, pPin, "max_capacitance" ) ); Vec_StrPutF_( vOut, Scl_LibertyReadPinCap( p, pPin, "max_transition" ) ); Vec_StrPutI_( vOut, Vec_PtrSize(vNameIns) ); pFormula = Scl_LibertyReadPinFormula(p, pPin); Vec_StrPutS_( vOut, pFormula ); // write truth table vTruth = Mio_ParseFormulaTruth( pFormula, (char **)Vec_PtrArray(vNameIns), Vec_PtrSize(vNameIns) ); if ( vTruth == NULL ) return NULL; for ( i = 0; i < Abc_Truth6WordNum(Vec_PtrSize(vNameIns)); i++ ) Vec_StrPutW_( vOut, Vec_WrdEntry(vTruth, i) ); Vec_WrdFree( vTruth ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // write the delay tables if ( fUseFirstTable ) { Vec_PtrForEachEntry( char *, vNameIns, pName, i ) { pTiming = Scl_LibertyReadPinTiming( p, pPin, pName ); Vec_StrPutS_( vOut, pName ); Vec_StrPutI_( vOut, (int)(pTiming != NULL) ); if ( pTiming == NULL ) // output does not depend on input continue; Vec_StrPutI_( vOut, Scl_LibertyReadTimingSense(p, pTiming) ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // some cells only have 'rise' or 'fall' but not both - here we work around this if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_rise", vTemples ) ) if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_fall", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_fall", vTemples ) ) if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_rise", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } if ( !Scl_LibertyReadTable( p, vOut, pTiming, "rise_transition", vTemples ) ) if ( !Scl_LibertyReadTable( p, vOut, pTiming, "fall_transition", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } if ( !Scl_LibertyReadTable( p, vOut, pTiming, "fall_transition", vTemples ) ) if ( !Scl_LibertyReadTable( p, vOut, pTiming, "rise_transition", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } } continue; } // write the timing tables Vec_PtrForEachEntry( char *, vNameIns, pName, i ) { Vec_Ptr_t * vTables[4]; Vec_Ptr_t * vTimings; vTimings = Scl_LibertyReadPinTimingAll( p, pPin, pName ); Vec_StrPutS_( vOut, pName ); Vec_StrPutI_( vOut, (int)(Vec_PtrSize(vTimings) != 0) ); if ( Vec_PtrSize(vTimings) == 0 ) // output does not depend on input { Vec_PtrFree( vTimings ); continue; } Vec_StrPutI_( vOut, Scl_LibertyReadTimingSense(p, (Scl_Item_t *)Vec_PtrEntry(vTimings, 0)) ); Vec_StrPut_( vOut ); Vec_StrPut_( vOut ); // collect the timing tables for ( k = 0; k < 4; k++ ) vTables[k] = Vec_PtrAlloc( 16 ); Vec_PtrForEachEntry( Scl_Item_t *, vTimings, pTiming, k ) { // some cells only have 'rise' or 'fall' but not both - here we work around this if ( !Scl_LibertyScanTable( p, vTables[0], pTiming, "cell_rise", vTemples ) ) if ( !Scl_LibertyScanTable( p, vTables[0], pTiming, "cell_fall", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } if ( !Scl_LibertyScanTable( p, vTables[1], pTiming, "cell_fall", vTemples ) ) if ( !Scl_LibertyScanTable( p, vTables[1], pTiming, "cell_rise", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } if ( !Scl_LibertyScanTable( p, vTables[2], pTiming, "rise_transition", vTemples ) ) if ( !Scl_LibertyScanTable( p, vTables[2], pTiming, "fall_transition", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } if ( !Scl_LibertyScanTable( p, vTables[3], pTiming, "fall_transition", vTemples ) ) if ( !Scl_LibertyScanTable( p, vTables[3], pTiming, "rise_transition", vTemples ) ) { printf( "Table cannot be found\n" ); return NULL; } } Vec_PtrFree( vTimings ); // compute worse case of the tables for ( k = 0; k < 4; k++ ) { Vec_Flt_t * vInd0, * vInd1, * vValues; if ( !Scl_LibertyComputeWorstCase( vTables[k], &vInd0, &vInd1, &vValues ) ) { printf( "Table indexes have different values\n" ); return NULL; } Vec_VecFree( (Vec_Vec_t *)vTables[k] ); Scl_LibertyDumpTables( vOut, vInd0, vInd1, vValues ); Vec_FltFree( vInd0 ); Vec_FltFree( vInd1 ); Vec_FltFree( vValues ); } } } Vec_StrPut_( vOut ); Vec_PtrFreeFree( vNameIns ); } // free templates if ( vTemples ) { Vec_Flt_t * vArray; assert( Vec_PtrSize(vTemples) % 4 == 0 ); Vec_PtrForEachEntry( Vec_Flt_t *, vTemples, vArray, i ) if ( i % 4 == 0 ) ABC_FREE( vArray ); else if ( i % 4 == 2 || i % 4 == 3 ) Vec_FltFree( vArray ); Vec_PtrFree( vTemples ); } if ( fVerbose ) { printf( "Library \"%s\" from \"%s\" has %d cells ", Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head), p->pFileName, nCells ); printf( "(%d skipped: %d seq; %d tri-state; %d no func). ", nSkipped[0]+nSkipped[1]+nSkipped[2], nSkipped[0], nSkipped[1], nSkipped[2] ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } return vOut; } SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose ) { SC_Lib * pLib; Scl_Tree_t * p; Vec_Str_t * vStr; p = Scl_LibertyParse( pFileName, fVeryVerbose ); if ( p == NULL ) return NULL; // Scl_LibertyParseDump( p, "temp_.lib" ); // collect relevant data vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose ); Scl_LibertyStop( p, fVeryVerbose ); if ( vStr == NULL ) return NULL; // construct SCL data-structure pLib = Abc_SclReadFromStr( vStr ); if ( pLib == NULL ) return NULL; pLib->pFileName = Abc_UtilStrsav( pFileName ); Abc_SclLibNormalize( pLib ); Vec_StrFree( vStr ); // printf( "Average slew = %.2f ps\n", Abc_SclComputeAverageSlew(pLib) ); return pLib; } /**Function************************************************************* Synopsis [Experiments with Liberty parsing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Scl_LibertyTest() { char * pFileName = "bwrc.lib"; int fVerbose = 1; int fVeryVerbose = 0; Scl_Tree_t * p; Vec_Str_t * vStr; // return; p = Scl_LibertyParse( pFileName, fVeryVerbose ); if ( p == NULL ) return; // Scl_LibertyParseDump( p, "temp_.lib" ); vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose ); Scl_LibertyStringDump( "test_scl.lib", vStr ); Vec_StrFree( vStr ); Scl_LibertyStop( p, fVerbose ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclLoad.c000066400000000000000000000174511300674244400231270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclLoad.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Wire/gate load computations.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclLoad.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclSize.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns estimated wire capacitances for each fanout count.] Description [] SideEffects []` SeeAlso [] ***********************************************************************/ Vec_Flt_t * Abc_SclFindWireCaps( SC_WireLoad * pWL, int nFanoutMax ) { Vec_Flt_t * vCaps = NULL; float EntryPrev, EntryCur, Slope; int i, iPrev, k, Entry, EntryMax; assert( pWL != NULL ); // find the biggest fanout count EntryMax = 0; Vec_IntForEachEntry( &pWL->vFanout, Entry, i ) EntryMax = Abc_MaxInt( EntryMax, Entry ); // create the array vCaps = Vec_FltStart( Abc_MaxInt(nFanoutMax, EntryMax) + 1 ); Vec_IntForEachEntry( &pWL->vFanout, Entry, i ) Vec_FltWriteEntry( vCaps, Entry, Vec_FltEntry(&pWL->vLen, i) * pWL->cap ); if ( Vec_FltEntry(vCaps, 1) == 0 ) return vCaps; // interpolate between the values assert( Vec_FltEntry(vCaps, 1) != 0 ); iPrev = 1; EntryPrev = Vec_FltEntry(vCaps, 1); Vec_FltForEachEntryStart( vCaps, EntryCur, i, 2 ) { if ( EntryCur == 0 ) continue; Slope = (EntryCur - EntryPrev) / (i - iPrev); for ( k = iPrev + 1; k < i; k++ ) Vec_FltWriteEntry( vCaps, k, EntryPrev + Slope * (k - iPrev) ); EntryPrev = EntryCur; iPrev = i; } // extrapolate after the largest value Slope = pWL->cap * pWL->slope; for ( k = iPrev + 1; k < i; k++ ) Vec_FltWriteEntry( vCaps, k, EntryPrev + Slope * (k - iPrev) ); // show // Vec_FltForEachEntry( vCaps, EntryCur, i ) // printf( "%3d : %f\n", i, EntryCur ); return vCaps; } /**Function************************************************************* Synopsis [Computes load for all nodes in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_SclFindWireLoad( Vec_Flt_t * vWireCaps, int nFans ) { if ( vWireCaps == NULL ) return 0; return Vec_FltEntry( vWireCaps, Abc_MinInt(nFans, Vec_FltSize(vWireCaps)-1) ); } void Abc_SclAddWireLoad( SC_Man * p, Abc_Obj_t * pObj, int fSubtr ) { float Load = Abc_SclFindWireLoad( p->vWireCaps, Abc_ObjFanoutNum(pObj) ); Abc_SclObjLoad(p, pObj)->rise += fSubtr ? -Load : Load; Abc_SclObjLoad(p, pObj)->fall += fSubtr ? -Load : Load; } void Abc_SclComputeLoad( SC_Man * p ) { Abc_Obj_t * pObj, * pFanin; int i, k; // clear load storage Abc_NtkForEachObj( p->pNtk, pObj, i ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); if ( !Abc_ObjIsPo(pObj) ) pLoad->rise = pLoad->fall = 0.0; } // add cell load Abc_NtkForEachNode1( p->pNtk, pObj, i ) { SC_Cell * pCell = Abc_SclObjCell( pObj ); Abc_ObjForEachFanin( pObj, pFanin, k ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pFanin ); SC_Pin * pPin = SC_CellPin( pCell, k ); pLoad->rise += pPin->rise_cap; pLoad->fall += pPin->fall_cap; } } // add PO load Abc_NtkForEachCo( p->pNtk, pObj, i ) { SC_Pair * pLoadPo = Abc_SclObjLoad( p, pObj ); SC_Pair * pLoad = Abc_SclObjLoad( p, Abc_ObjFanin0(pObj) ); pLoad->rise += pLoadPo->rise; pLoad->fall += pLoadPo->fall; } // add wire load if ( p->pWLoadUsed != NULL ) { if ( p->vWireCaps == NULL ) p->vWireCaps = Abc_SclFindWireCaps( p->pWLoadUsed, Abc_NtkGetFanoutMax(p->pNtk) ); Abc_NtkForEachNode1( p->pNtk, pObj, i ) Abc_SclAddWireLoad( p, pObj, 0 ); Abc_NtkForEachPi( p->pNtk, pObj, i ) Abc_SclAddWireLoad( p, pObj, 0 ); } // check input loads if ( p->vInDrive != NULL ) { Abc_NtkForEachPi( p->pNtk, pObj, i ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); if ( Abc_SclObjInDrive(p, pObj) != 0 && (pLoad->rise > Abc_SclObjInDrive(p, pObj) || pLoad->fall > Abc_SclObjInDrive(p, pObj)) ) printf( "Maximum input drive strength is exceeded at primary input %d.\n", i ); } } /* // transfer load from barbufs Abc_NtkForEachBarBuf( p->pNtk, pObj, i ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pLoadF = Abc_SclObjLoad( p, Abc_ObjFanin(pObj, 0) ); SC_PairAdd( pLoadF, pLoad ); } */ // calculate average load // if ( p->EstLoadMax ) { double TotalLoad = 0; int nObjs = 0; Abc_NtkForEachNode1( p->pNtk, pObj, i ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); TotalLoad += 0.5 * pLoad->fall + 0.5 * pLoad->rise; nObjs++; } Abc_NtkForEachPi( p->pNtk, pObj, i ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); TotalLoad += 0.5 * pLoad->fall + 0.5 * pLoad->rise; nObjs++; } p->EstLoadAve = (float)(TotalLoad / nObjs); // printf( "Average load = %.2f\n", p->EstLoadAve ); } } /**Function************************************************************* Synopsis [Updates load of the node's fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclUpdateLoad( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pOld, SC_Cell * pNew ) { Abc_Obj_t * pFanin; int k; Abc_ObjForEachFanin( pObj, pFanin, k ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pFanin ); SC_Pin * pPinOld = SC_CellPin( pOld, k ); SC_Pin * pPinNew = SC_CellPin( pNew, k ); pLoad->rise += pPinNew->rise_cap - pPinOld->rise_cap; pLoad->fall += pPinNew->fall_cap - pPinOld->fall_cap; } } void Abc_SclUpdateLoadSplit( SC_Man * p, Abc_Obj_t * pBuffer, Abc_Obj_t * pFanout ) { SC_Pin * pPin; SC_Pair * pLoad; int iFanin = Abc_NodeFindFanin( pFanout, pBuffer ); assert( iFanin >= 0 ); assert( Abc_ObjFaninNum(pBuffer) == 1 ); pPin = SC_CellPin( Abc_SclObjCell(pFanout), iFanin ); // update load of the buffer pLoad = Abc_SclObjLoad( p, pBuffer ); pLoad->rise -= pPin->rise_cap; pLoad->fall -= pPin->fall_cap; // update load of the fanin pLoad = Abc_SclObjLoad( p, Abc_ObjFanin0(pBuffer) ); pLoad->rise += pPin->rise_cap; pLoad->fall += pPin->fall_cap; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclSize.c000066400000000000000000001002021300674244400231450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclSize.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Core timing analysis used in gate-sizing.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclSize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclSize.h" #include "map/mio/mio.h" #include "misc/vec/vecWec.h" #include "base/main/main.h" #ifdef WIN32 #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Finding most critical objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_SclFindCriticalCo( SC_Man * p, int * pfRise ) { Abc_Obj_t * pObj, * pPivot = NULL; float fMaxArr = 0; int i; assert( Abc_NtkPoNum(p->pNtk) > 0 ); Abc_NtkForEachCo( p->pNtk, pObj, i ) { SC_Pair * pArr = Abc_SclObjTime( p, pObj ); if ( fMaxArr < pArr->rise ) fMaxArr = pArr->rise, *pfRise = 1, pPivot = pObj; if ( fMaxArr < pArr->fall ) fMaxArr = pArr->fall, *pfRise = 0, pPivot = pObj; } if ( fMaxArr == 0 ) pPivot = Abc_NtkPo(p->pNtk, 0); assert( pPivot != NULL ); return pPivot; } // assumes that slacks are not available (uses arrival times) Abc_Obj_t * Abc_SclFindMostCriticalFanin2( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin, * pPivot = NULL; float fMaxArr = 0; int i; Abc_ObjForEachFanin( pNode, pFanin, i ) { SC_Pair * pArr = Abc_SclObjTime( p, pFanin ); if ( fMaxArr < pArr->rise ) fMaxArr = pArr->rise, *pfRise = 1, pPivot = pFanin; if ( fMaxArr < pArr->fall ) fMaxArr = pArr->fall, *pfRise = 0, pPivot = pFanin; } return pPivot; } // assumes that slack are available Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin, * pPivot = NULL; float fMinSlack = ABC_INFINITY; SC_Pair * pArr; int i; *pfRise = 0; // find min-slack node Abc_ObjForEachFanin( pNode, pFanin, i ) if ( fMinSlack > Abc_SclObjGetSlack( p, pFanin, p->MaxDelay0 ) ) { fMinSlack = Abc_SclObjGetSlack( p, pFanin, p->MaxDelay0 ); pPivot = pFanin; } if ( pPivot == NULL ) return NULL; // find its leading phase pArr = Abc_SclObjTime( p, pPivot ); *pfRise = (pArr->rise >= pArr->fall); return pPivot; } /**Function************************************************************* Synopsis [Printing timing information for the node/network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_SclTimeNodePrint( SC_Man * p, Abc_Obj_t * pObj, int fRise, int Length, float maxDelay ) { SC_Cell * pCell = Abc_ObjIsNode(pObj) ? Abc_SclObjCell(pObj) : NULL; printf( "%8d : ", Abc_ObjId(pObj) ); printf( "%d ", Abc_ObjFaninNum(pObj) ); printf( "%4d ", Abc_ObjFanoutNum(pObj) ); printf( "%-*s ", Length, pCell ? pCell->pName : "pi" ); printf( "A =%7.2f ", pCell ? pCell->area : 0.0 ); printf( "D%s =", fRise ? "r" : "f" ); printf( "%6.1f", Abc_SclObjTimeMax(p, pObj) ); printf( "%7.1f ps ", -Abc_AbsFloat(Abc_SclObjTimeOne(p, pObj, 0) - Abc_SclObjTimeOne(p, pObj, 1)) ); printf( "S =%6.1f ps ", Abc_SclObjSlewMax(p, pObj) ); printf( "Cin =%5.1f ff ", pCell ? SC_CellPinCapAve(pCell) : 0.0 ); printf( "Cout =%6.1f ff ", Abc_SclObjLoadMax(p, pObj) ); printf( "Cmax =%6.1f ff ", pCell ? SC_CellPin(pCell, pCell->n_inputs)->max_out_cap : 0.0 ); printf( "G =%5d ", pCell ? (int)(100.0 * Abc_SclObjLoadAve(p, pObj) / SC_CellPinCapAve(pCell)) : 0 ); // printf( "SL =%6.1f ps", Abc_SclObjSlackMax(p, pObj, p->MaxDelay0) ); printf( "\n" ); } void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath ) { int fReversePath = 1; int i, nLength = 0, fRise = 0; Abc_Obj_t * pObj, * pPivot = Abc_SclFindCriticalCo( p, &fRise ); float maxDelay = Abc_SclObjTimeOne( p, pPivot, fRise ); p->ReportDelay = maxDelay; #ifdef WIN32 printf( "WireLoad = \"%s\" ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 14 ); // yellow printf( "Gates =%7d ", Abc_NtkNodeNum(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal printf( "(%5.1f %%) ", 100.0 * Abc_SclGetBufInvCount(p->pNtk) / Abc_NtkNodeNum(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 10 ); // green printf( "Cap =%5.1f ff ", p->EstLoadAve ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal printf( "(%5.1f %%) ", Abc_SclGetAverageSize(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 11 ); // blue printf( "Area =%12.2f ", Abc_SclGetTotalArea(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal printf( "(%5.1f %%) ", 100.0 * Abc_SclCountMinSize(p->pLib, p->pNtk, 0) / Abc_NtkNodeNum(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 13 ); // magenta printf( "Delay =%9.2f ps ", maxDelay ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal printf( "(%5.1f %%) ", 100.0 * Abc_SclCountNearCriticalNodes(p) / Abc_NtkNodeNum(p->pNtk) ); printf( " \n" ); #else Abc_Print( 1, "WireLoad = \"%s\" ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" ); Abc_Print( 1, "%sGates =%7d%s ", "\033[1;33m", Abc_NtkNodeNum(p->pNtk), "\033[0m" ); // yellow Abc_Print( 1, "(%5.1f %%) ", 100.0 * Abc_SclGetBufInvCount(p->pNtk) / Abc_NtkNodeNum(p->pNtk) ); Abc_Print( 1, "%sCap =%5.1f ff%s ", "\033[1;32m", p->EstLoadAve, "\033[0m" ); // green Abc_Print( 1, "(%5.1f %%) ", Abc_SclGetAverageSize(p->pNtk) ); Abc_Print( 1, "%sArea =%12.2f%s ", "\033[1;36m", Abc_SclGetTotalArea(p->pNtk), "\033[0m" ); // blue Abc_Print( 1, "(%5.1f %%) ", 100.0 * Abc_SclCountMinSize(p->pLib, p->pNtk, 0) / Abc_NtkNodeNum(p->pNtk) ); Abc_Print( 1, "%sDelay =%9.2f ps%s ", "\033[1;35m", maxDelay, "\033[0m" ); // magenta Abc_Print( 1, "(%5.1f %%) ", 100.0 * Abc_SclCountNearCriticalNodes(p) / Abc_NtkNodeNum(p->pNtk) ); Abc_Print( 1, " \n" ); #endif if ( fShowAll ) { // printf( "Timing information for all nodes: \n" ); // find the longest cell name Abc_NtkForEachNodeReverse( p->pNtk, pObj, i ) if ( Abc_ObjFaninNum(pObj) > 0 ) nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(pObj)->pName) ); // print timing Abc_NtkForEachNodeReverse( p->pNtk, pObj, i ) if ( Abc_ObjFaninNum(pObj) > 0 ) Abc_SclTimeNodePrint( p, pObj, -1, nLength, maxDelay ); } if ( fPrintPath ) { Abc_Obj_t * pTemp, * pPrev = NULL; int iStart = -1, iEnd = -1; Vec_Ptr_t * vPath; // printf( "Critical path: \n" ); // find the longest cell name pObj = Abc_ObjFanin0(pPivot); i = 0; while ( pObj && Abc_ObjIsNode(pObj) ) { i++; nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(pObj)->pName) ); pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); } // print timing if ( !fReversePath ) { // print timing pObj = Abc_ObjFanin0(pPivot); while ( pObj )//&& Abc_ObjIsNode(pObj) ) { printf( "Path%3d --", i-- ); Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay ); pPrev = pObj; pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); } } else { // collect path nodes vPath = Vec_PtrAlloc( 100 ); Vec_PtrPush( vPath, pPivot ); pObj = Abc_ObjFanin0(pPivot); while ( pObj )//&& Abc_ObjIsNode(pObj) ) { Vec_PtrPush( vPath, pObj ); pPrev = pObj; pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); } Vec_PtrForEachEntryReverse( Abc_Obj_t *, vPath, pObj, i ) { printf( "Path%3d --", Vec_PtrSize(vPath)-1-i ); Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay ); if ( i == 1 ) break; } Vec_PtrFree( vPath ); } // print start-point and end-point Abc_NtkForEachPi( p->pNtk, pTemp, iStart ) if ( pTemp == pPrev ) break; Abc_NtkForEachPo( p->pNtk, pTemp, iEnd ) if ( pTemp == pPivot ) break; printf( "Start-point = pi%0*d. End-point = po%0*d.\n", Abc_Base10Log( Abc_NtkPiNum(p->pNtk) ), iStart, Abc_Base10Log( Abc_NtkPoNum(p->pNtk) ), iEnd ); } } /**Function************************************************************* Synopsis [Timing computation for pin/gate/cone/network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) { SC_Pair * pArrIn = Abc_SclObjTime( p, pFanin ); SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pArrOut = Abc_SclObjTime( p, pObj ); // modified SC_Pair * pSlewOut = Abc_SclObjSlew( p, pObj ); // modified Scl_LibPinArrival( pTime, pArrIn, pSlewIn, pLoad, pArrOut, pSlewOut ); } static inline void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) { SC_Pair * pDepIn = Abc_SclObjDept( p, pFanin ); // modified SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); Scl_LibPinDeparture( pTime, pDepIn, pSlewIn, pLoad, pDepOut ); } static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj ) { SC_Timing * pTime; Abc_Obj_t * pFanout; int i; SC_PairClean( Abc_SclObjDept(p, pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) { if ( Abc_ObjIsCo(pFanout) || Abc_ObjIsLatch(pFanout) ) continue; pTime = Scl_CellPinTime( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj) ); Abc_SclDeptFanin( p, pTime, pFanout, pObj ); } } static inline float Abc_SclObjLoadValue( SC_Man * p, Abc_Obj_t * pObj ) { // float Value = Abc_MaxFloat(pLoad->fall, pLoad->rise) / (p->EstLoadAve * p->EstLoadMax); return (0.5 * Abc_SclObjLoad(p, pObj)->fall + 0.5 * Abc_SclObjLoad(p, pObj)->rise) / (p->EstLoadAve * p->EstLoadMax); } static inline void Abc_SclTimeCi( SC_Man * p, Abc_Obj_t * pObj ) { if ( p->pPiDrive != NULL ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pTime = Abc_SclObjTime( p, pObj ); SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); Scl_LibHandleInputDriver( p->pPiDrive, pLoad, pTime, pSlew ); } } void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept ) { SC_Timing * pTime; SC_Cell * pCell; int k; SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); float LoadRise = pLoad->rise; float LoadFall = pLoad->fall; float DeptRise = 0; float DeptFall = 0; float Value = p->EstLoadMax ? Abc_SclObjLoadValue( p, pObj ) : 0; Abc_Obj_t * pFanin; if ( Abc_ObjIsCi(pObj) ) { assert( !fDept ); Abc_SclTimeCi( p, pObj ); return; } if ( Abc_ObjIsCo(pObj) ) { if ( !fDept ) { Abc_SclObjDupFanin( p, pObj ); Vec_FltWriteEntry( p->vTimesOut, pObj->iData, Abc_SclObjTimeMax(p, pObj) ); Vec_QueUpdate( p->vQue, pObj->iData ); } return; } assert( Abc_ObjIsNode(pObj) ); // if ( !(Abc_ObjFaninNum(pObj) == 1 && Abc_ObjIsPi(Abc_ObjFanin0(pObj))) && p->EstLoadMax && Value > 1 ) if ( p->EstLoadMax && Value > 1 ) { pLoad->rise = p->EstLoadAve * p->EstLoadMax; pLoad->fall = p->EstLoadAve * p->EstLoadMax; if ( fDept ) { SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); float EstDelta = p->EstLinear * log( Value ); DeptRise = pDepOut->rise; DeptFall = pDepOut->fall; pDepOut->rise += EstDelta; pDepOut->fall += EstDelta; } p->nEstNodes++; } // get the library cell pCell = Abc_SclObjCell( pObj ); // compute for each fanin Abc_ObjForEachFanin( pObj, pFanin, k ) { pTime = Scl_CellPinTime( pCell, k ); if ( fDept ) Abc_SclDeptFanin( p, pTime, pObj, pFanin ); else Abc_SclTimeFanin( p, pTime, pObj, pFanin ); } if ( p->EstLoadMax && Value > 1 ) { pLoad->rise = LoadRise; pLoad->fall = LoadFall; if ( fDept ) { SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); pDepOut->rise = DeptRise; pDepOut->fall = DeptFall; } else { SC_Pair * pArrOut = Abc_SclObjTime( p, pObj ); float EstDelta = p->EstLinear * log( Value ); pArrOut->rise += EstDelta; pArrOut->fall += EstDelta; } } } void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone ) { int fVerbose = 0; Abc_Obj_t * pObj; int i; Abc_SclConeClean( p, vCone ); Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) { if ( fVerbose && Abc_ObjIsNode(pObj) ) printf( " Updating node %d with gate %s\n", Abc_ObjId(pObj), Abc_SclObjCell(pObj)->pName ); if ( fVerbose && Abc_ObjIsNode(pObj) ) printf( " before (%6.1f ps %6.1f ps) ", Abc_SclObjTimeOne(p, pObj, 1), Abc_SclObjTimeOne(p, pObj, 0) ); Abc_SclTimeNode( p, pObj, 0 ); if ( fVerbose && Abc_ObjIsNode(pObj) ) printf( "after (%6.1f ps %6.1f ps)\n", Abc_SclObjTimeOne(p, pObj, 1), Abc_SclObjTimeOne(p, pObj, 0) ); } } void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser ) { Abc_Obj_t * pObj; float D; int i; Abc_SclComputeLoad( p ); Abc_SclManCleanTime( p ); p->nEstNodes = 0; Abc_NtkForEachCi( p->pNtk, pObj, i ) Abc_SclTimeNode( p, pObj, 0 ); Abc_NtkForEachNode1( p->pNtk, pObj, i ) Abc_SclTimeNode( p, pObj, 0 ); Abc_NtkForEachCo( p->pNtk, pObj, i ) Abc_SclTimeNode( p, pObj, 0 ); D = Abc_SclReadMaxDelay( p ); if ( fReverse && DUser > 0 && D < DUser ) D = DUser; if ( pArea ) *pArea = Abc_SclGetTotalArea(p->pNtk); if ( pDelay ) *pDelay = D; if ( fReverse ) { p->nEstNodes = 0; Abc_NtkForEachNodeReverse1( p->pNtk, pObj, i ) Abc_SclTimeNode( p, pObj, 1 ); } } /**Function************************************************************* Synopsis [Incremental timing update.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_SclTimeIncUpdateClean( SC_Man * p ) { Vec_Int_t * vLevel; Abc_Obj_t * pObj; int i, k; Vec_WecForEachLevel( p->vLevels, vLevel, i ) { Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k ) { assert( pObj->fMarkC == 1 ); pObj->fMarkC = 0; } Vec_IntClear( vLevel ); } } static inline void Abc_SclTimeIncAddNode( SC_Man * p, Abc_Obj_t * pObj ) { assert( !Abc_ObjIsLatch(pObj) ); assert( pObj->fMarkC == 0 ); pObj->fMarkC = 1; Vec_IntPush( Vec_WecEntry(p->vLevels, Abc_ObjLevel(pObj)), Abc_ObjId(pObj) ); p->nIncUpdates++; } static inline void Abc_SclTimeIncAddFanins( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; Abc_ObjForEachFanin( pObj, pFanin, i ) // if ( !pFanin->fMarkC && Abc_ObjIsNode(pFanin) ) if ( !pFanin->fMarkC && !Abc_ObjIsLatch(pFanin) ) Abc_SclTimeIncAddNode( p, pFanin ); } static inline void Abc_SclTimeIncAddFanouts( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) if ( !pFanout->fMarkC && !Abc_ObjIsLatch(pFanout) ) Abc_SclTimeIncAddNode( p, pFanout ); } static inline void Abc_SclTimeIncUpdateArrival( SC_Man * p ) { Vec_Int_t * vLevel; SC_Pair ArrOut, SlewOut; SC_Pair * pArrOut, *pSlewOut; Abc_Obj_t * pObj; float E = (float)0.1; int i, k; Vec_WecForEachLevel( p->vLevels, vLevel, i ) { Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k ) { if ( Abc_ObjIsCo(pObj) ) { Abc_SclObjDupFanin( p, pObj ); Vec_FltWriteEntry( p->vTimesOut, pObj->iData, Abc_SclObjTimeMax(p, pObj) ); Vec_QueUpdate( p->vQue, pObj->iData ); continue; } pArrOut = Abc_SclObjTime( p, pObj ); pSlewOut = Abc_SclObjSlew( p, pObj ); SC_PairMove( &ArrOut, pArrOut ); SC_PairMove( &SlewOut, pSlewOut ); Abc_SclTimeNode( p, pObj, 0 ); // if ( !SC_PairEqual(&ArrOut, pArrOut) || !SC_PairEqual(&SlewOut, pSlewOut) ) if ( !SC_PairEqualE(&ArrOut, pArrOut, E) || !SC_PairEqualE(&SlewOut, pSlewOut, E) ) Abc_SclTimeIncAddFanouts( p, pObj ); } } p->MaxDelay = Abc_SclReadMaxDelay( p ); } static inline void Abc_SclTimeIncUpdateDeparture( SC_Man * p ) { Vec_Int_t * vLevel; SC_Pair DepOut, * pDepOut; Abc_Obj_t * pObj; float E = (float)0.1; int i, k; Vec_WecForEachLevelReverse( p->vLevels, vLevel, i ) { Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k ) { pDepOut = Abc_SclObjDept( p, pObj ); SC_PairMove( &DepOut, pDepOut ); Abc_SclDeptObj( p, pObj ); // if ( !SC_PairEqual(&DepOut, pDepOut) ) if ( !SC_PairEqualE(&DepOut, pDepOut, E) ) Abc_SclTimeIncAddFanins( p, pObj ); } } p->MaxDelay = Abc_SclReadMaxDelay( p ); } void Abc_SclTimeIncCheckLevel( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) if ( (int)pObj->Level != Abc_ObjLevelNew(pObj) ) printf( "Level of node %d is out of date!\n", i ); } int Abc_SclTimeIncUpdate( SC_Man * p ) { Abc_Obj_t * pObj; int i, RetValue; if ( Vec_IntSize(p->vChanged) == 0 ) return 0; // Abc_SclTimeIncCheckLevel( p->pNtk ); Abc_NtkForEachObjVec( p->vChanged, p->pNtk, pObj, i ) { Abc_SclTimeIncAddFanins( p, pObj ); if ( pObj->fMarkC ) continue; Abc_SclTimeIncAddNode( p, pObj ); } Vec_IntClear( p->vChanged ); Abc_SclTimeIncUpdateArrival( p ); Abc_SclTimeIncUpdateDeparture( p ); Abc_SclTimeIncUpdateClean( p ); RetValue = p->nIncUpdates; p->nIncUpdates = 0; return RetValue; } void Abc_SclTimeIncInsert( SC_Man * p, Abc_Obj_t * pObj ) { Vec_IntPush( p->vChanged, Abc_ObjId(pObj) ); } void Abc_SclTimeIncUpdateLevel_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, LevelNew = Abc_ObjLevelNew(pObj); if ( LevelNew == (int)pObj->Level && Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) > 0 ) return; pObj->Level = LevelNew; Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_SclTimeIncUpdateLevel_rec( pFanout ); } void Abc_SclTimeIncUpdateLevel( Abc_Obj_t * pObj ) { Abc_SclTimeIncUpdateLevel_rec( pObj ); } /**Function************************************************************* Synopsis [Read input slew and output load.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclManReadSlewAndLoad( SC_Man * p, Abc_Ntk_t * pNtk ) { if ( Abc_FrameReadMaxLoad() ) { Abc_Obj_t * pObj; int i; float MaxLoad = Abc_FrameReadMaxLoad(); // printf( "Default output load is specified (%.2f ff).\n", MaxLoad ); Abc_NtkForEachPo( pNtk, pObj, i ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); pLoad->rise = pLoad->fall = MaxLoad; } } if ( Abc_FrameReadDrivingCell() ) { int iCell = Abc_SclCellFind( p->pLib, Abc_FrameReadDrivingCell() ); if ( iCell == -1 ) printf( "Cannot find the default PI driving cell (%s) in the library.\n", Abc_FrameReadDrivingCell() ); else { // printf( "Default PI driving cell is specified (%s).\n", Abc_FrameReadDrivingCell() ); p->pPiDrive = SC_LibCell( p->pLib, iCell ); assert( p->pPiDrive != NULL ); assert( p->pPiDrive->n_inputs == 1 ); } } } /**Function************************************************************* Synopsis [Prepare timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser, int nTreeCRatio ) { SC_Man * p = Abc_SclManAlloc( pLib, pNtk ); if ( nTreeCRatio ) { p->EstLoadMax = 0.01 * nTreeCRatio; // max ratio of Cout/Cave when the estimation is used p->EstLinear = 100; // linear coefficient } Abc_SclMioGates2SclGates( pLib, pNtk ); Abc_SclManReadSlewAndLoad( p, pNtk ); if ( fUseWireLoads ) { if ( pNtk->pWLoadUsed == NULL ) { p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(p->pNtk) ); if ( p->pWLoadUsed ) pNtk->pWLoadUsed = Abc_UtilStrsav( p->pWLoadUsed->pName ); } else p->pWLoadUsed = Abc_SclFetchWireLoadModel( pLib, pNtk->pWLoadUsed ); } Abc_SclTimeNtkRecompute( p, &p->SumArea0, &p->MaxDelay0, fDept, DUser ); p->SumArea = p->SumArea0; p->MaxDelay = p->MaxDelay0; return p; } /**Function************************************************************* Synopsis [Printing out timing information for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclTimePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats ) { SC_Man * p; p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0, nTreeCRatio ); Abc_SclTimeNtkPrint( p, fShowAll, fPrintPath ); if ( fDumpStats ) Abc_SclDumpStats( p, "stats.txt", 0 ); Abc_SclManFree( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats ) { Abc_Ntk_t * pNtkNew = pNtk; if ( pNtk->nBarBufs2 > 0 ) pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); Abc_SclTimePerformInt( pLib, pNtkNew, nTreeCRatio, fUseWireLoads, fShowAll, fPrintPath, fDumpStats ); if ( pNtk->nBarBufs2 > 0 ) Abc_NtkDelete( pNtkNew ); } /**Function************************************************************* Synopsis [Printing out fanin information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclCheckCommonInputs( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) { Abc_Obj_t * pTemp; int i; Abc_ObjForEachFanin( pObj, pTemp, i ) if ( Abc_NodeFindFanin( pFanin, pTemp ) >= 0 ) { printf( "Node %d and its fanin %d have common fanin %d.\n", Abc_ObjId(pObj), Abc_ObjId(pFanin), Abc_ObjId(pTemp) ); printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pObj->pData) ); Abc_ObjPrint( stdout, pObj ); printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pFanin->pData) ); Abc_ObjPrint( stdout, pFanin ); if ( pTemp->pData ) printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pTemp->pData) ); Abc_ObjPrint( stdout, pTemp ); return 1; } return 0; } void Abc_SclPrintFaninPairs( SC_Man * p, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFanin; int i, k; Abc_NtkForEachNode( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) Abc_SclCheckCommonInputs( pObj, pFanin ); } /**Function************************************************************* Synopsis [Printing out buffer information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_ObjIsBuffer( Abc_Obj_t * pObj ) { return Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) == 1; } int Abc_SclHasBufferFanout( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_ObjIsBuffer(pFanout) ) return 1; return 0; } int Abc_SclCountBufferFanoutsInt( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, Counter = 0; Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_ObjIsBuffer(pFanout) ) Counter += Abc_SclCountBufferFanoutsInt( pFanout ); return Counter + Abc_ObjIsBuffer(pObj); } int Abc_SclCountBufferFanouts( Abc_Obj_t * pObj ) { return Abc_SclCountBufferFanoutsInt(pObj) - Abc_ObjIsBuffer(pObj); } int Abc_SclCountNonBufferFanoutsInt( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, Counter = 0; if ( !Abc_ObjIsBuffer(pObj) ) return 1; Abc_ObjForEachFanout( pObj, pFanout, i ) Counter += Abc_SclCountNonBufferFanoutsInt( pFanout ); return Counter; } int Abc_SclCountNonBufferFanouts( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, Counter = 0; Abc_ObjForEachFanout( pObj, pFanout, i ) Counter += Abc_SclCountNonBufferFanoutsInt( pFanout ); return Counter; } float Abc_SclCountNonBufferDelayInt( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Delay = 0; int i; if ( !Abc_ObjIsBuffer(pObj) ) return Abc_SclObjTimeMax(p, pObj); Abc_ObjForEachFanout( pObj, pFanout, i ) Delay += Abc_SclCountNonBufferDelayInt( p, pFanout ); return Delay; } float Abc_SclCountNonBufferDelay( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Delay = 0; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) Delay += Abc_SclCountNonBufferDelayInt( p, pFanout ); return Delay; } float Abc_SclCountNonBufferLoadInt( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Load = 0; int i; if ( !Abc_ObjIsBuffer(pObj) ) return 0; Abc_ObjForEachFanout( pObj, pFanout, i ) Load += Abc_SclCountNonBufferLoadInt( p, pFanout ); Load += 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall; Load -= 0.5 * SC_CellPin(Abc_SclObjCell(pObj), 0)->rise_cap + 0.5 * SC_CellPin(Abc_SclObjCell(pObj), 0)->fall_cap; return Load; } float Abc_SclCountNonBufferLoad( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Load = 0; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) Load += Abc_SclCountNonBufferLoadInt( p, pFanout ); Load += 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall; return Load; } void Abc_SclPrintBuffersOne( SC_Man * p, Abc_Obj_t * pObj, int nOffset ) { int i; for ( i = 0; i < nOffset; i++ ) printf( " " ); printf( "%6d: %-16s (%2d:%3d:%3d) ", Abc_ObjId(pObj), Abc_ObjIsPi(pObj) ? "pi" : Mio_GateReadName((Mio_Gate_t *)pObj->pData), Abc_ObjFanoutNum(pObj), Abc_SclCountBufferFanouts(pObj), Abc_SclCountNonBufferFanouts(pObj) ); for ( ; i < 4; i++ ) printf( " " ); printf( "a =%5.2f ", Abc_ObjIsPi(pObj) ? 0 : Abc_SclObjCell(pObj)->area ); printf( "d = (" ); printf( "%6.0f ps; ", Abc_SclObjTimeOne(p, pObj, 1) ); printf( "%6.0f ps) ", Abc_SclObjTimeOne(p, pObj, 0) ); printf( "l =%5.0f ff ", Abc_SclObjLoadMax(p, pObj) ); printf( "s =%5.0f ps ", Abc_SclObjSlewMax(p, pObj) ); printf( "sl =%5.0f ps ", Abc_SclObjSlackMax(p, pObj, p->MaxDelay0) ); if ( nOffset == 0 ) { printf( "L =%5.0f ff ", Abc_SclCountNonBufferLoad(p, pObj) ); printf( "Lx =%5.0f ff ", 100.0*Abc_SclCountNonBufferLoad(p, pObj)/p->EstLoadAve ); printf( "Dx =%5.0f ps ", Abc_SclCountNonBufferDelay(p, pObj)/Abc_SclCountNonBufferFanouts(pObj) - Abc_SclObjTimeOne(p, pObj, 1) ); printf( "Cx =%5.0f ps", (Abc_SclCountNonBufferDelay(p, pObj)/Abc_SclCountNonBufferFanouts(pObj) - Abc_SclObjTimeOne(p, pObj, 1))/log(Abc_SclCountNonBufferLoad(p, pObj)/p->EstLoadAve) ); } printf( "\n" ); } void Abc_SclPrintBuffersInt( SC_Man * p, Abc_Obj_t * pObj, int nOffset ) { Abc_Obj_t * pFanout; int i; Abc_SclPrintBuffersOne( p, pObj, nOffset ); assert( Abc_ObjIsBuffer(pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_ObjIsBuffer(pFanout) ) Abc_SclPrintBuffersInt( p, pFanout, nOffset + 1 ); } void Abc_SclPrintBufferTrees( SC_Man * p, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFanout; int i, k; Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !Abc_ObjIsBuffer(pObj) && Abc_SclCountBufferFanouts(pObj) > 3 ) { Abc_SclPrintBuffersOne( p, pObj, 0 ); Abc_ObjForEachFanout( pObj, pFanout, k ) if ( Abc_ObjIsBuffer(pFanout) ) Abc_SclPrintBuffersInt( p, pFanout, 1 ); printf( "\n" ); } } } void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ) { int fUseWireLoads = 0; SC_Man * p; assert( Abc_NtkIsMappedLogic(pNtk) ); p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0, 10000 ); Abc_SclPrintBufferTrees( p, pNtk ); // Abc_SclPrintFaninPairs( p, pNtk ); Abc_SclManFree( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclSize.h000066400000000000000000000625341300674244400231710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclSize.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Timing/gate-sizing manager.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclSize.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__scl__sclSize_h #define ABC__map__scl__sclSize_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecWec.h" #include "sclLib.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct SC_Man_ SC_Man; struct SC_Man_ { SC_Lib * pLib; // library Abc_Ntk_t * pNtk; // network int nObjs; // allocated size // get assignment Vec_Int_t * vGatesBest; // best gate sizes found so far Vec_Int_t * vUpdates; // sizing updates in this round Vec_Int_t * vUpdates2; // sizing updates in this round // timing information SC_WireLoad * pWLoadUsed; // name of the used WireLoad model Vec_Flt_t * vWireCaps; // wire capacitances SC_Pair * pLoads; // loads for each gate SC_Pair * pDepts; // departures for each gate SC_Pair * pTimes; // arrivals for each gate SC_Pair * pSlews; // slews for each gate Vec_Flt_t * vInDrive; // maximum input drive strength Vec_Flt_t * vTimesOut; // output arrival times Vec_Que_t * vQue; // outputs by their time SC_Cell * pPiDrive; // cell driving primary inputs // backup information Vec_Flt_t * vLoads2; // backup storage for loads Vec_Flt_t * vLoads3; // backup storage for loads Vec_Flt_t * vTimes2; // backup storage for times Vec_Flt_t * vTimes3; // backup storage for slews // buffer trees float EstLoadMax; // max ratio of Cout/Cin when this kicks in float EstLoadAve; // average load of the gate float EstLinear; // linear coefficient int nEstNodes; // the number of estimations // intermediate data Vec_Que_t * vNodeByGain; // nodes by gain Vec_Flt_t * vNode2Gain; // mapping node into its gain Vec_Int_t * vNode2Gate; // mapping node into its best gate Vec_Int_t * vNodeIter; // the last iteration the node was upsized Vec_Int_t * vBestFans; // best fanouts // incremental timing update Vec_Wec_t * vLevels; Vec_Int_t * vChanged; int nIncUpdates; // optimization parameters float SumArea; // total area float MaxDelay; // max delay float SumArea0; // total area at the begining float MaxDelay0; // max delay at the begining float BestDelay; // best delay in the middle float ReportDelay; // delay to report // runtime statistics abctime timeTotal; // starting/total time abctime timeCone; // critical path selection abctime timeSize; // incremental sizing abctime timeTime; // timing update abctime timeOther; // everything else }; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline SC_Lib * Abc_SclObjLib( Abc_Obj_t * p ) { return (SC_Lib *)p->pNtk->pSCLib; } static inline int Abc_SclObjCellId( Abc_Obj_t * p ) { return Vec_IntEntry( p->pNtk->vGates, Abc_ObjId(p) ); } static inline SC_Cell * Abc_SclObjCell( Abc_Obj_t * p ) { int c = Abc_SclObjCellId(p); return c == -1 ? NULL:SC_LibCell(Abc_SclObjLib(p), c); } static inline void Abc_SclObjSetCell( Abc_Obj_t * p, SC_Cell * pCell ) { Vec_IntWriteEntry( p->pNtk->vGates, Abc_ObjId(p), pCell->Id ); } static inline SC_Pair * Abc_SclObjLoad( SC_Man * p, Abc_Obj_t * pObj ) { return p->pLoads + Abc_ObjId(pObj); } static inline SC_Pair * Abc_SclObjDept( SC_Man * p, Abc_Obj_t * pObj ) { return p->pDepts + Abc_ObjId(pObj); } static inline SC_Pair * Abc_SclObjTime( SC_Man * p, Abc_Obj_t * pObj ) { return p->pTimes + Abc_ObjId(pObj); } static inline SC_Pair * Abc_SclObjSlew( SC_Man * p, Abc_Obj_t * pObj ) { return p->pSlews + Abc_ObjId(pObj); } static inline double Abc_SclObjLoadMax( SC_Man * p, Abc_Obj_t * pObj ) { return Abc_MaxFloat(Abc_SclObjLoad(p, pObj)->rise, Abc_SclObjLoad(p, pObj)->fall); } static inline float Abc_SclObjLoadAve( SC_Man * p, Abc_Obj_t * pObj ) { return 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall; } static inline double Abc_SclObjTimeOne( SC_Man * p, Abc_Obj_t * pObj, int fRise ){ return fRise ? Abc_SclObjTime(p, pObj)->rise : Abc_SclObjTime(p, pObj)->fall; } static inline float Abc_SclObjTimeMax( SC_Man * p, Abc_Obj_t * pObj ) { return Abc_MaxFloat(Abc_SclObjTime(p, pObj)->rise, Abc_SclObjTime(p, pObj)->fall); } static inline double Abc_SclObjSlewMax( SC_Man * p, Abc_Obj_t * pObj ) { return Abc_MaxFloat(Abc_SclObjSlew(p, pObj)->rise, Abc_SclObjSlew(p, pObj)->fall); } static inline float Abc_SclObjGetSlackR( SC_Man * p, Abc_Obj_t * pObj, float D ){ return D - (Abc_SclObjTime(p, pObj)->rise + Abc_SclObjDept(p, pObj)->rise); } static inline float Abc_SclObjGetSlackF( SC_Man * p, Abc_Obj_t * pObj, float D ){ return D - (Abc_SclObjTime(p, pObj)->fall + Abc_SclObjDept(p, pObj)->fall); } static inline float Abc_SclObjGetSlack( SC_Man * p, Abc_Obj_t * pObj, float D ) { return D - Abc_MaxFloat(Abc_SclObjTime(p, pObj)->rise + Abc_SclObjDept(p, pObj)->rise, Abc_SclObjTime(p, pObj)->fall + Abc_SclObjDept(p, pObj)->fall); } static inline double Abc_SclObjSlackMax( SC_Man * p, Abc_Obj_t * pObj, float D ) { return Abc_SclObjGetSlack(p, pObj, D); } static inline void Abc_SclObjDupFanin( SC_Man * p, Abc_Obj_t * pObj ) { assert( Abc_ObjIsCo(pObj) ); *Abc_SclObjTime(p, pObj) = *Abc_SclObjTime(p, Abc_ObjFanin0(pObj)); } static inline float Abc_SclObjInDrive( SC_Man * p, Abc_Obj_t * pObj ) { return Vec_FltEntry( p->vInDrive, pObj->iData ); } static inline void Abc_SclObjSetInDrive( SC_Man * p, Abc_Obj_t * pObj, float c){ Vec_FltWriteEntry( p->vInDrive, pObj->iData, c ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Constructor/destructor of STA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline SC_Man * Abc_SclManAlloc( SC_Lib * pLib, Abc_Ntk_t * pNtk ) { SC_Man * p; Abc_Obj_t * pObj; int i; assert( pLib->unit_time == 12 ); assert( pLib->unit_cap_snd == 15 ); assert( Abc_NtkHasMapping(pNtk) ); p = ABC_CALLOC( SC_Man, 1 ); p->pLib = pLib; p->pNtk = pNtk; p->nObjs = Abc_NtkObjNumMax(pNtk); p->pLoads = ABC_CALLOC( SC_Pair, p->nObjs ); p->pDepts = ABC_CALLOC( SC_Pair, p->nObjs ); p->pTimes = ABC_CALLOC( SC_Pair, p->nObjs ); p->pSlews = ABC_CALLOC( SC_Pair, p->nObjs ); p->vBestFans = Vec_IntStart( p->nObjs ); p->vTimesOut = Vec_FltStart( Abc_NtkCoNum(pNtk) ); p->vQue = Vec_QueAlloc( Abc_NtkCoNum(pNtk) ); Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vTimesOut) ); for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) Vec_QuePush( p->vQue, i ); p->vUpdates = Vec_IntAlloc( 1000 ); p->vUpdates2 = Vec_IntAlloc( 1000 ); p->vLoads2 = Vec_FltAlloc( 1000 ); p->vLoads3 = Vec_FltAlloc( 1000 ); p->vTimes2 = Vec_FltAlloc( 1000 ); p->vTimes3 = Vec_FltAlloc( 1000 ); // intermediate data p->vNode2Gain = Vec_FltStart( p->nObjs ); p->vNode2Gate = Vec_IntStart( p->nObjs ); p->vNodeByGain = Vec_QueAlloc( p->nObjs ); Vec_QueSetPriority( p->vNodeByGain, Vec_FltArrayP(p->vNode2Gain) ); p->vNodeIter = Vec_IntStartFull( p->nObjs ); p->vLevels = Vec_WecStart( 2 * Abc_NtkLevel(pNtk) + 1 ); p->vChanged = Vec_IntAlloc( 100 ); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->Level = Abc_ObjFanin0(pObj)->Level + 1; // set CI/CO ids Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iData = i; Abc_NtkForEachCo( pNtk, pObj, i ) pObj->iData = i; return p; } static inline void Abc_SclManFree( SC_Man * p ) { Abc_Obj_t * pObj; int i; // set CI/CO ids Abc_NtkForEachCi( p->pNtk, pObj, i ) pObj->iData = 0; Abc_NtkForEachCo( p->pNtk, pObj, i ) pObj->iData = 0; // other p->pNtk->pSCLib = NULL; Vec_IntFreeP( &p->pNtk->vGates ); Vec_IntFreeP( &p->vNodeIter ); Vec_QueFreeP( &p->vNodeByGain ); Vec_FltFreeP( &p->vNode2Gain ); Vec_IntFreeP( &p->vNode2Gate ); // intermediate data Vec_FltFreeP( &p->vLoads2 ); Vec_FltFreeP( &p->vLoads3 ); Vec_FltFreeP( &p->vTimes2 ); Vec_FltFreeP( &p->vTimes3 ); Vec_IntFreeP( &p->vUpdates ); Vec_IntFreeP( &p->vUpdates2 ); Vec_IntFreeP( &p->vGatesBest ); Vec_WecFreeP( &p->vLevels ); Vec_IntFreeP( &p->vChanged ); // Vec_QuePrint( p->vQue ); Vec_QueCheck( p->vQue ); Vec_QueFreeP( &p->vQue ); Vec_FltFreeP( &p->vTimesOut ); Vec_IntFreeP( &p->vBestFans ); Vec_FltFreeP( &p->vInDrive ); Vec_FltFreeP( &p->vWireCaps ); ABC_FREE( p->pLoads ); ABC_FREE( p->pDepts ); ABC_FREE( p->pTimes ); ABC_FREE( p->pSlews ); ABC_FREE( p ); } /* static inline void Abc_SclManCleanTime( SC_Man * p ) { Vec_Flt_t * vSlews; Abc_Obj_t * pObj; int i; vSlews = Vec_FltAlloc( 2 * Abc_NtkPiNum(p->pNtk) ); Abc_NtkForEachPi( p->pNtk, pObj, i ) { SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); Vec_FltPush( vSlews, pSlew->rise ); Vec_FltPush( vSlews, pSlew->fall ); } memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs ); memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs ); memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs ); Abc_NtkForEachPi( p->pNtk, pObj, i ) { SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); pSlew->rise = Vec_FltEntry( vSlews, 2 * i + 0 ); pSlew->fall = Vec_FltEntry( vSlews, 2 * i + 1 ); } Vec_FltFree( vSlews ); } */ static inline void Abc_SclManCleanTime( SC_Man * p ) { memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs ); memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs ); memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs ); /* if ( p->pPiDrive != NULL ) { SC_Pair * pSlew, * pTime, * pLoad; Abc_Obj_t * pObj; int i; Abc_NtkForEachPi( p->pNtk, pObj, i ) { pLoad = Abc_SclObjLoad( p, pObj ); pTime = Abc_SclObjTime( p, pObj ); pSlew = Abc_SclObjSlew( p, pObj ); Scl_LibHandleInputDriver( p->pPiDrive, pLoad, pTime, pSlew ); } } */ } /**Function************************************************************* Synopsis [Stores/retrivies information for the logic cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_SclLoadStore( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; Vec_FltClear( p->vLoads2 ); Abc_ObjForEachFanin( pObj, pFanin, i ) { Vec_FltPush( p->vLoads2, Abc_SclObjLoad(p, pFanin)->rise ); Vec_FltPush( p->vLoads2, Abc_SclObjLoad(p, pFanin)->fall ); } } static inline void Abc_SclLoadRestore( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i, k = 0; Abc_ObjForEachFanin( pObj, pFanin, i ) { Abc_SclObjLoad(p, pFanin)->rise = Vec_FltEntry(p->vLoads2, k++); Abc_SclObjLoad(p, pFanin)->fall = Vec_FltEntry(p->vLoads2, k++); } assert( Vec_FltSize(p->vLoads2) == k ); } static inline void Abc_SclLoadStore3( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; Vec_FltClear( p->vLoads3 ); Vec_FltPush( p->vLoads3, Abc_SclObjLoad(p, pObj)->rise ); Vec_FltPush( p->vLoads3, Abc_SclObjLoad(p, pObj)->fall ); Abc_ObjForEachFanin( pObj, pFanin, i ) { Vec_FltPush( p->vLoads3, Abc_SclObjLoad(p, pFanin)->rise ); Vec_FltPush( p->vLoads3, Abc_SclObjLoad(p, pFanin)->fall ); } } static inline void Abc_SclLoadRestore3( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i, k = 0; Abc_SclObjLoad(p, pObj)->rise = Vec_FltEntry(p->vLoads3, k++); Abc_SclObjLoad(p, pObj)->fall = Vec_FltEntry(p->vLoads3, k++); Abc_ObjForEachFanin( pObj, pFanin, i ) { Abc_SclObjLoad(p, pFanin)->rise = Vec_FltEntry(p->vLoads3, k++); Abc_SclObjLoad(p, pFanin)->fall = Vec_FltEntry(p->vLoads3, k++); } assert( Vec_FltSize(p->vLoads3) == k ); } static inline void Abc_SclConeStore( SC_Man * p, Vec_Int_t * vCone ) { Abc_Obj_t * pObj; int i; Vec_FltClear( p->vTimes2 ); Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) { Vec_FltPush( p->vTimes2, Abc_SclObjTime(p, pObj)->rise ); Vec_FltPush( p->vTimes2, Abc_SclObjTime(p, pObj)->fall ); Vec_FltPush( p->vTimes2, Abc_SclObjSlew(p, pObj)->rise ); Vec_FltPush( p->vTimes2, Abc_SclObjSlew(p, pObj)->fall ); } } static inline void Abc_SclConeRestore( SC_Man * p, Vec_Int_t * vCone ) { Abc_Obj_t * pObj; int i, k = 0; Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) { Abc_SclObjTime(p, pObj)->rise = Vec_FltEntry(p->vTimes2, k++); Abc_SclObjTime(p, pObj)->fall = Vec_FltEntry(p->vTimes2, k++); Abc_SclObjSlew(p, pObj)->rise = Vec_FltEntry(p->vTimes2, k++); Abc_SclObjSlew(p, pObj)->fall = Vec_FltEntry(p->vTimes2, k++); } assert( Vec_FltSize(p->vTimes2) == k ); } static inline void Abc_SclEvalStore( SC_Man * p, Vec_Int_t * vCone ) { Abc_Obj_t * pObj; int i; Vec_FltClear( p->vTimes3 ); Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) { Vec_FltPush( p->vTimes3, Abc_SclObjTime(p, pObj)->rise ); Vec_FltPush( p->vTimes3, Abc_SclObjTime(p, pObj)->fall ); } } static inline float Abc_SclEvalPerform( SC_Man * p, Vec_Int_t * vCone ) { Abc_Obj_t * pObj; float Diff, Multi = 1.5, Eval = 0; int i, k = 0; Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) { Diff = (Vec_FltEntry(p->vTimes3, k++) - Abc_SclObjTime(p, pObj)->rise); Diff += (Vec_FltEntry(p->vTimes3, k++) - Abc_SclObjTime(p, pObj)->fall); Eval += 0.5 * (Diff > 0 ? Diff : Multi * Diff); } assert( Vec_FltSize(p->vTimes3) == k ); return Eval / Vec_IntSize(vCone); } static inline float Abc_SclEvalPerformLegal( SC_Man * p, Vec_Int_t * vCone, float D ) { Abc_Obj_t * pObj; float Rise, Fall, Multi = 1.0, Eval = 0; int i, k = 0; Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) { Rise = Vec_FltEntry(p->vTimes3, k++) - Abc_SclObjTime(p, pObj)->rise; Fall = Vec_FltEntry(p->vTimes3, k++) - Abc_SclObjTime(p, pObj)->fall; if ( Rise + Multi * Abc_SclObjGetSlackR(p, pObj, D) < 0 || Fall + Multi * Abc_SclObjGetSlackF(p, pObj, D) < 0 ) return -1; Eval += 0.5 * Rise + 0.5 * Fall; } assert( Vec_FltSize(p->vTimes3) == k ); return Eval / Vec_IntSize(vCone); } static inline void Abc_SclConeClean( SC_Man * p, Vec_Int_t * vCone ) { SC_Pair Zero = { 0.0, 0.0 }; Abc_Obj_t * pObj; int i; Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) { *Abc_SclObjTime(p, pObj) = Zero; *Abc_SclObjSlew(p, pObj) = Zero; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_SclGetBufInvCount( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i, Count = 0; Abc_NtkForEachNodeNotBarBuf1( pNtk, pObj, i ) Count += (Abc_ObjFaninNum(pObj) == 1); return Count; } static inline float Abc_SclGetAverageSize( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; double Total = 0; int i, Count = 0; Abc_NtkForEachNodeNotBarBuf1( pNtk, pObj, i ) Count++, Total += 100.0*Abc_SclObjCell(pObj)->Order/Abc_SclObjCell(pObj)->nGates; return (float)(Total / Count); } static inline float Abc_SclGetTotalArea( Abc_Ntk_t * pNtk ) { double Area = 0; Abc_Obj_t * pObj; int i; Abc_NtkForEachNodeNotBarBuf1( pNtk, pObj, i ) Area += Abc_SclObjCell(pObj)->area; return Area; } static inline float Abc_SclGetMaxDelay( SC_Man * p ) { float fMaxArr = 0; Abc_Obj_t * pObj; int i; Abc_NtkForEachCo( p->pNtk, pObj, i ) fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) ); return fMaxArr; } static inline float Abc_SclGetMaxDelayNodeFanins( SC_Man * p, Abc_Obj_t * pNode ) { float fMaxArr = 0; Abc_Obj_t * pObj; int i; assert( Abc_ObjIsNode(pNode) ); Abc_ObjForEachFanin( pNode, pObj, i ) fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) ); return fMaxArr; } static inline float Abc_SclReadMaxDelay( SC_Man * p ) { return Abc_SclObjTimeMax( p, Abc_NtkCo(p->pNtk, Vec_QueTop(p->vQue)) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline SC_Cell * Abc_SclObjResiable( SC_Man * p, Abc_Obj_t * pObj, int fUpsize ) { SC_Cell * pOld = Abc_SclObjCell(pObj); if ( fUpsize ) return pOld->pNext->Order > pOld->Order ? pOld->pNext : NULL; else return pOld->pPrev->Order < pOld->Order ? pOld->pPrev : NULL; } /**Function************************************************************* Synopsis [Dumps timing results into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_SclDumpStats( SC_Man * p, char * pFileName, abctime Time ) { static char FileNameOld[1000] = {0}; static int nNodesOld, nAreaOld, nDelayOld; static abctime clk = 0; FILE * pTable; pTable = fopen( pFileName, "a+" ); if ( strcmp( FileNameOld, p->pNtk->pName ) ) { sprintf( FileNameOld, "%s", p->pNtk->pName ); fprintf( pTable, "\n" ); fprintf( pTable, "%s ", Extra_FileNameWithoutPath(p->pNtk->pName) ); fprintf( pTable, "%d ", Abc_NtkPiNum(p->pNtk) ); fprintf( pTable, "%d ", Abc_NtkPoNum(p->pNtk) ); fprintf( pTable, "%d ", (nNodesOld = Abc_NtkNodeNum(p->pNtk)) ); fprintf( pTable, "%d ", (nAreaOld = (int)p->SumArea) ); fprintf( pTable, "%d ", (nDelayOld = (int)p->ReportDelay) ); clk = Abc_Clock(); } else { fprintf( pTable, " " ); fprintf( pTable, "%.1f ", 100.0 * Abc_NtkNodeNum(p->pNtk) / nNodesOld ); fprintf( pTable, "%.1f ", 100.0 * (int)p->SumArea / nAreaOld ); fprintf( pTable, "%.1f ", 100.0 * (int)p->ReportDelay / nDelayOld ); fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC ); } fclose( pTable ); } /*=== sclBuffer.c ===============================================================*/ extern Abc_Ntk_t * Abc_SclBufferingPerform( Abc_Ntk_t * pNtk, SC_Lib * pLib, SC_BusPars * pPars ); /*=== sclBufferOld.c ===============================================================*/ extern int Abc_SclIsInv( Abc_Obj_t * pObj ); extern void Abc_NodeInvUpdateFanPolarity( Abc_Obj_t * pObj ); extern void Abc_NodeInvUpdateObjFanoutPolarity( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ); extern void Abc_SclReportDupFanins( Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_SclUnBufferPerform( Abc_Ntk_t * pNtk, int fVerbose ); extern Abc_Ntk_t * Abc_SclUnBufferPhase( Abc_Ntk_t * pNtk, int fVerbose ); extern Abc_Ntk_t * Abc_SclBufferPhase( Abc_Ntk_t * pNtk, int fVerbose ); extern int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose ); extern Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int DegreeR, int Degree, int fUseInvs, int fVerbose ); extern Abc_Ntk_t * Abc_SclBufPerform( Abc_Ntk_t * pNtk, int FanMin, int FanMax, int fBufPis, int fSkipDup, int fVerbose ); /*=== sclDnsize.c ===============================================================*/ extern void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); /*=== sclLoad.c ===============================================================*/ extern Vec_Flt_t * Abc_SclFindWireCaps( SC_WireLoad * pWL, int nFanoutMax ); extern float Abc_SclFindWireLoad( Vec_Flt_t * vWireCaps, int nFans ); extern void Abc_SclAddWireLoad( SC_Man * p, Abc_Obj_t * pObj, int fSubtr ); extern void Abc_SclComputeLoad( SC_Man * p ); extern void Abc_SclUpdateLoad( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pOld, SC_Cell * pNew ); extern void Abc_SclUpdateLoadSplit( SC_Man * p, Abc_Obj_t * pBuffer, Abc_Obj_t * pFanout ); /*=== sclSize.c ===============================================================*/ extern Abc_Obj_t * Abc_SclFindCriticalCo( SC_Man * p, int * pfRise ); extern Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ); extern void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath ); extern SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser, int nTreeCRatio ); extern void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone ); extern void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser ); extern int Abc_SclTimeIncUpdate( SC_Man * p ); extern void Abc_SclTimeIncInsert( SC_Man * p, Abc_Obj_t * pObj ); extern void Abc_SclTimeIncUpdateLevel( Abc_Obj_t * pObj ); extern void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats ); extern void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ); /*=== sclUpsize.c ===============================================================*/ extern int Abc_SclCountNearCriticalNodes( SC_Man * p ); extern void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); /*=== sclUtil.c ===============================================================*/ extern void Abc_SclMioGates2SclGates( SC_Lib * pLib, Abc_Ntk_t * p ); extern void Abc_SclSclGates2MioGates( SC_Lib * pLib, Abc_Ntk_t * p ); extern void Abc_SclTransferGates( Abc_Ntk_t * pOld, Abc_Ntk_t * pNew ); extern void Abc_SclPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p ); extern void Abc_SclMinsizePerform( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax, int fVerbose ); extern int Abc_SclCountMinSize( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax ); extern Vec_Int_t * Abc_SclExtractBarBufs( Abc_Ntk_t * pNtk ); extern void Abc_SclInsertBarBufs( Abc_Ntk_t * pNtk, Vec_Int_t * vBufs ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclTime.h000066400000000000000000000242061300674244400231470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclTime.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Timing/gate-sizing manager.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclTime.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__scl__sclTime_h #define ABC__map__scl__sclTime_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/vec/vec.h" #include "sclLib.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct SC_Time_ SC_Time; struct SC_Time_ { SC_Lib * pLib; // library Vec_Int_t * vCis; // comb inputs Vec_Int_t * vCos; // comb outputs int nObjs; // allocated size // get assignment Vec_Int_t * vGates; // mapping of objId into gateId // timing information SC_Pair * pLoads; // loads for each gate SC_Pair * pLoads2; // loads for each gate SC_Pair * pDepts; // departures for each gate SC_Pair * pTimes; // arrivals for each gate SC_Pair * pSlews; // slews for each gate SC_Pair * pTimes2; // arrivals for each gate SC_Pair * pSlews2; // slews for each gate float * pSlack; // slacks for each gate SC_WireLoad * pWLoadUsed; // name of the used WireLoad model // optimization parameters float SumArea; // total area float MaxDelay; // max delay float SumArea0; // total area at the begining float MaxDelay0; // max delay at the begining float BestDelay; // best delay in the middle }; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline SC_Cell * Scl_ObjCell( SC_Time * p, int i ) { return SC_LibCell( p->pLib, Vec_IntEntry(p->vGates, i) ); } static inline void Scl_ObjSetCell( SC_Time * p, int i, SC_Cell * pCell ) { Vec_IntWriteEntry( p->vGates, i, pCell->Id ); } static inline SC_Pair * Scl_ObjLoad( SC_Time * p, int i ) { return p->pLoads + i; } static inline SC_Pair * Scl_ObjLoad2( SC_Time * p, int i ) { return p->pLoads2 + i; } static inline SC_Pair * Scl_ObjDept( SC_Time * p, int i ) { return p->pDepts + i; } static inline SC_Pair * Scl_ObjTime( SC_Time * p, int i ) { return p->pTimes + i; } static inline SC_Pair * Scl_ObjSlew( SC_Time * p, int i ) { return p->pSlews + i; } static inline SC_Pair * Scl_ObjTime2( SC_Time * p, int i ) { return p->pTimes2 + i; } static inline SC_Pair * Scl_ObjSlew2( SC_Time * p, int i ) { return p->pSlews2 + i; } static inline float Scl_ObjTimeMax( SC_Time * p, int i ) { return Abc_MaxFloat(Scl_ObjTime(p, i)->rise, Scl_ObjTime(p, i)->fall); } static inline float Scl_ObjDepthMax( SC_Time * p, int i ) { return Abc_MaxFloat(Scl_ObjDept(p, i)->rise, Scl_ObjDept(p, i)->fall); } static inline float Scl_ObjGetSlack( SC_Time * p, int i, float D ) { return D - Abc_MaxFloat(Scl_ObjTime(p, i)->rise + Scl_ObjDept(p, i)->rise, Scl_ObjTime(p, i)->fall + Scl_ObjDept(p, i)->fall); } static inline float Scl_ObjGetSlackR( SC_Time * p, int i, float D ) { return D - (Scl_ObjTime(p, i)->rise + Scl_ObjDept(p, i)->rise); } static inline float Scl_ObjGetSlackF( SC_Time * p, int i, float D ) { return D - (Scl_ObjTime(p, i)->fall + Scl_ObjDept(p, i)->fall); } static inline float Scl_ObjSlack( SC_Time * p, int i ) { return p->pSlack[i]; } static inline void Scl_ObjDupFanin( SC_Time * p, int i, int iFanin ) { *Scl_ObjTime(p, i) = *Scl_ObjTime(p, iFanin); } static inline float Scl_ObjGain( SC_Time * p, int i ) { return 0.5*((Scl_ObjTime2(p, i)->rise - Scl_ObjTime(p, i)->rise) + (Scl_ObjTime2(p, i)->fall - Scl_ObjTime(p, i)->fall)); } static inline int Scl_ObjLegal( SC_Time * p, int i, float D ) { return Scl_ObjTime(p, i)->rise <= Scl_ObjTime2(p, i)->rise + Scl_ObjGetSlackR(p, i, D) && Scl_ObjTime(p, i)->fall <= Scl_ObjTime2(p, i)->fall + Scl_ObjGetSlackF(p, i, D); } static inline double Scl_ObjLoadFf( SC_Time * p, int i, int fRise ) { return fRise ? Scl_ObjLoad(p, i)->rise : Scl_ObjLoad(p, i)->fall; } static inline double Scl_ObjTimePs( SC_Time * p, int i, int fRise ) { return fRise ? Scl_ObjTime(p, i)->rise : Scl_ObjTime(p, i)->fall; } static inline double Scl_ObjSlewPs( SC_Time * p, int i, int fRise ) { return fRise ? Scl_ObjSlew(p, i)->rise : Scl_ObjSlew(p, i)->fall; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Constructor/destructor of STA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline SC_Time * Scl_ManAlloc( SC_Lib * pLib, Vec_Int_t * vCis, Vec_Int_t * vCos, int nObjs ) { SC_Time * p; p = ABC_CALLOC( SC_Time, 1 ); p->pLib = pLib; p->vCis = vCis; p->vCos = vCos; p->nObjs = nObjs; p->pLoads = ABC_CALLOC( SC_Pair, p->nObjs ); p->pLoads2 = ABC_CALLOC( SC_Pair, p->nObjs ); p->pDepts = ABC_CALLOC( SC_Pair, p->nObjs ); p->pTimes = ABC_CALLOC( SC_Pair, p->nObjs ); p->pSlews = ABC_CALLOC( SC_Pair, p->nObjs ); p->pTimes2 = ABC_CALLOC( SC_Pair, p->nObjs ); p->pSlews2 = ABC_CALLOC( SC_Pair, p->nObjs ); p->pSlack = ABC_FALLOC( float, p->nObjs ); return p; } static inline void Scl_ManFree( SC_Time * p ) { Vec_IntFreeP( &p->vGates ); ABC_FREE( p->pLoads ); ABC_FREE( p->pLoads2 ); ABC_FREE( p->pDepts ); ABC_FREE( p->pTimes ); ABC_FREE( p->pSlews ); ABC_FREE( p->pTimes2 ); ABC_FREE( p->pSlews2 ); ABC_FREE( p->pSlack ); ABC_FREE( p ); } static inline void Scl_ManCleanTime( SC_Time * p ) { memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs ); memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs ); memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs ); } /**Function************************************************************* Synopsis [Stores/retrieves timing information for the logic cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Scl_ConeStore( SC_Time * p, Vec_Int_t * vCone ) { int i, iObj; Vec_IntForEachEntry( vCone, iObj, i ) { *Scl_ObjTime2(p, iObj) = *Scl_ObjTime(p, iObj); *Scl_ObjSlew2(p, iObj) = *Scl_ObjSlew(p, iObj); } } static inline void Scl_ConeRestore( SC_Time * p, Vec_Int_t * vCone ) { int i, iObj; Vec_IntForEachEntry( vCone, iObj, i ) { *Scl_ObjTime(p, iObj) = *Scl_ObjTime2(p, iObj); *Scl_ObjSlew(p, iObj) = *Scl_ObjSlew2(p, iObj); } } static inline void Scl_ConeClear( SC_Time * p, Vec_Int_t * vCone ) { SC_Pair Zero = { 0.0, 0.0 }; int i, iObj; Vec_IntForEachEntry( vCone, iObj, i ) { *Scl_ObjTime(p, iObj) = Zero; *Scl_ObjSlew(p, iObj) = Zero; } } /**Function************************************************************* Synopsis [Timing computation for pin/gate/cone/network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Scl_PinTimeArrival( SC_Time * p, SC_Timing * pTime, int iObj, int iFanin ) { SC_Pair * pArrIn = Scl_ObjTime( p, iFanin ); SC_Pair * pSlewIn = Scl_ObjSlew( p, iFanin ); SC_Pair * pLoad = Scl_ObjLoad( p, iObj ); SC_Pair * pArrOut = Scl_ObjTime( p, iObj ); // modified SC_Pair * pSlewOut = Scl_ObjSlew( p, iObj ); // modified Scl_LibPinArrival( pTime, pArrIn, pSlewIn, pLoad, pArrOut, pSlewOut ); } static inline void Scl_PinTimeDeparture( SC_Time * p, SC_Timing * pTime, int iObj, int iFanin ) { SC_Pair * pDepIn = Scl_ObjDept( p, iFanin ); // modified SC_Pair * pSlewIn = Scl_ObjSlew( p, iFanin ); SC_Pair * pLoad = Scl_ObjLoad( p, iObj ); SC_Pair * pDepOut = Scl_ObjDept( p, iObj ); Scl_LibPinDeparture( pTime, pDepIn, pSlewIn, pLoad, pDepOut ); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclUpsize.c000066400000000000000000001134471300674244400235310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclUpsize.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Selective increase of gate sizes.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclUpsize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclSize.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collect TFO of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclFindTFO_rec( Abc_Obj_t * pObj, Vec_Int_t * vNodes, Vec_Int_t * vCos ) { Abc_Obj_t * pNext; int i; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsCo(pObj) ) { Vec_IntPush( vCos, Abc_ObjId(pObj) ); return; } assert( Abc_ObjIsNode(pObj) ); Abc_ObjForEachFanout( pObj, pNext, i ) Abc_SclFindTFO_rec( pNext, vNodes, vCos ); if ( Abc_ObjFaninNum(pObj) > 0 ) Vec_IntPush( vNodes, Abc_ObjId(pObj) ); } Vec_Int_t * Abc_SclFindTFO( Abc_Ntk_t * p, Vec_Int_t * vPath ) { Vec_Int_t * vNodes, * vCos; Abc_Obj_t * pObj, * pFanin; int i, k; assert( Vec_IntSize(vPath) > 0 ); vCos = Vec_IntAlloc( 100 ); vNodes = Vec_IntAlloc( 100 ); // collect nodes in the TFO Abc_NtkIncrementTravId( p ); Abc_NtkForEachObjVec( vPath, p, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( Abc_ObjIsNode(pFanin) ) Abc_SclFindTFO_rec( pFanin, vNodes, vCos ); // reverse order Vec_IntReverseOrder( vNodes ); // Vec_IntSort( vNodes, 0 ); //Vec_IntPrint( vNodes ); //Vec_IntPrint( vCos ); Vec_IntAppend( vNodes, vCos ); Vec_IntFree( vCos ); return vNodes; } /**Function************************************************************* Synopsis [Collect near-critical COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_SclFindCriticalCoWindow( SC_Man * p, int Window ) { float fMaxArr = Abc_SclReadMaxDelay( p ) * (100.0 - Window) / 100.0; Vec_Int_t * vPivots; Abc_Obj_t * pObj; int i; vPivots = Vec_IntAlloc( 100 ); Abc_NtkForEachCo( p->pNtk, pObj, i ) if ( Abc_SclObjTimeMax(p, pObj) >= fMaxArr ) Vec_IntPush( vPivots, Abc_ObjId(pObj) ); assert( Vec_IntSize(vPivots) > 0 ); return vPivots; } /**Function************************************************************* Synopsis [Collect near-critical internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclFindCriticalNodeWindow_rec( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vPath, float fSlack, int fDept ) { Abc_Obj_t * pNext; float fArrMax, fSlackFan; int i; if ( Abc_ObjIsCi(pObj) ) return; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); assert( Abc_ObjIsNode(pObj) ); // compute the max arrival time of the fanins if ( fDept ) // fArrMax = p->pSlack[Abc_ObjId(pObj)]; fArrMax = Abc_SclObjGetSlack(p, pObj, p->MaxDelay); else fArrMax = Abc_SclGetMaxDelayNodeFanins( p, pObj ); // assert( fArrMax >= -1 ); fArrMax = Abc_MaxFloat( fArrMax, 0 ); // traverse all fanins whose arrival times are within a window Abc_ObjForEachFanin( pObj, pNext, i ) { if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) == 0 ) continue; assert( Abc_ObjIsNode(pNext) ); if ( fDept ) // fSlackFan = fSlack - (p->pSlack[Abc_ObjId(pNext)] - fArrMax); fSlackFan = fSlack - (Abc_SclObjGetSlack(p, pNext, p->MaxDelay) - fArrMax); else fSlackFan = fSlack - (fArrMax - Abc_SclObjTimeMax(p, pNext)); if ( fSlackFan >= 0 ) Abc_SclFindCriticalNodeWindow_rec( p, pNext, vPath, fSlackFan, fDept ); } if ( Abc_ObjFaninNum(pObj) > 0 ) Vec_IntPush( vPath, Abc_ObjId(pObj) ); } Vec_Int_t * Abc_SclFindCriticalNodeWindow( SC_Man * p, Vec_Int_t * vPathCos, int Window, int fDept ) { float fMaxArr = Abc_SclReadMaxDelay( p ); float fSlackMax = fMaxArr * Window / 100.0; Vec_Int_t * vPath = Vec_IntAlloc( 100 ); Abc_Obj_t * pObj; int i; Abc_NtkIncrementTravId( p->pNtk ); Abc_NtkForEachObjVec( vPathCos, p->pNtk, pObj, i ) { float fSlackThis = fSlackMax - (fMaxArr - Abc_SclObjTimeMax(p, pObj)); if ( fSlackThis >= 0 ) Abc_SclFindCriticalNodeWindow_rec( p, Abc_ObjFanin0(pObj), vPath, fSlackThis, fDept ); } // label critical nodes Abc_NtkForEachObjVec( vPathCos, p->pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachObjVec( vPath, p->pNtk, pObj, i ) pObj->fMarkA = 1; return vPath; } void Abc_SclUnmarkCriticalNodeWindow( SC_Man * p, Vec_Int_t * vPath ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObjVec( vPath, p->pNtk, pObj, i ) pObj->fMarkA = 0; } int Abc_SclCountNearCriticalNodes( SC_Man * p ) { int RetValue; Vec_Int_t * vPathPos, * vPathNodes; vPathPos = Abc_SclFindCriticalCoWindow( p, 5 ); vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, 5, 0 ); RetValue = Vec_IntSize(vPathNodes); Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes ); Abc_SclUnmarkCriticalNodeWindow( p, vPathPos ); Vec_IntFree( vPathPos ); Vec_IntFree( vPathNodes ); return RetValue; } /**Function************************************************************* Synopsis [Find the array of nodes to be updated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvNodes, Vec_Int_t ** pvEvals, Abc_Obj_t * pExtra ) { Abc_Ntk_t * p = Abc_ObjNtk(pPivot); Abc_Obj_t * pObj, * pNext, * pNext2; Vec_Int_t * vNodes = *pvNodes; Vec_Int_t * vEvals = *pvEvals; int i, k; assert( Abc_ObjIsNode(pPivot) ); assert( pPivot->fMarkA ); // collect fanins, node, and fanouts Vec_IntClear( vNodes ); Abc_ObjForEachFanin( pPivot, pNext, i ) // if ( Abc_ObjIsNode(pNext) && Abc_ObjFaninNum(pNext) > 0 ) if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) > 0 ) Vec_IntPush( vNodes, Abc_ObjId(pNext) ); Vec_IntPush( vNodes, Abc_ObjId(pPivot) ); if ( pExtra ) Vec_IntPush( vNodes, Abc_ObjId(pExtra) ); Abc_ObjForEachFanout( pPivot, pNext, i ) if ( Abc_ObjIsNode(pNext) && pNext->fMarkA ) { Vec_IntPush( vNodes, Abc_ObjId(pNext) ); Abc_ObjForEachFanout( pNext, pNext2, k ) if ( Abc_ObjIsNode(pNext2) && pNext2->fMarkA ) Vec_IntPush( vNodes, Abc_ObjId(pNext2) ); } Vec_IntUniqify( vNodes ); // label nodes Abc_NtkForEachObjVec( vNodes, p, pObj, i ) { assert( pObj->fMarkB == 0 ); pObj->fMarkB = 1; } // collect nodes visible from the critical paths Vec_IntClear( vEvals ); Abc_NtkForEachObjVec( vNodes, p, pObj, i ) Abc_ObjForEachFanout( pObj, pNext, k ) if ( pNext->fMarkA && !pNext->fMarkB ) // if ( !pNext->fMarkB ) { assert( pObj->fMarkB ); Vec_IntPush( vEvals, Abc_ObjId(pObj) ); break; } assert( Vec_IntSize(vEvals) > 0 ); // label nodes Abc_NtkForEachObjVec( vNodes, p, pObj, i ) pObj->fMarkB = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclFindBestCell( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vRecalcs, Vec_Int_t * vEvals, int Notches, int DelayGap, float * pGainBest ) { SC_Cell * pCellOld, * pCellNew; float dGain, dGainBest; int k, gateBest, NoChange = 0; // save old gate, timing, fanin load pCellOld = Abc_SclObjCell( pObj ); Abc_SclConeStore( p, vRecalcs ); Abc_SclEvalStore( p, vEvals ); Abc_SclLoadStore( p, pObj ); // try different gate sizes for this node gateBest = -1; dGainBest = -DelayGap; SC_RingForEachCell( pCellOld, pCellNew, k ) { if ( pCellNew == pCellOld ) continue; if ( k > Notches ) break; // set new cell Abc_SclObjSetCell( pObj, pCellNew ); Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); // recompute timing Abc_SclTimeCone( p, vRecalcs ); // set old cell Abc_SclObjSetCell( pObj, pCellOld ); Abc_SclLoadRestore( p, pObj ); // save best gain dGain = Abc_SclEvalPerform( p, vEvals ); if ( dGainBest < dGain ) { dGainBest = dGain; gateBest = pCellNew->Id; NoChange = 1; } else if ( NoChange ) NoChange++; if ( NoChange == 4 ) break; // printf( "%.2f ", dGain ); } // printf( "Best = %.2f ", dGainBest ); // printf( "\n" ); // put back old cell and timing Abc_SclObjSetCell( pObj, pCellOld ); Abc_SclConeRestore( p, vRecalcs ); *pGainBest = dGainBest; return gateBest; } /**Function************************************************************* Synopsis [Computes the set of gates to upsize.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclFindBypasses( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notches, int iIter, int DelayGap, int fVeryVerbose ) { SC_Cell * pCellOld, * pCellNew; Vec_Ptr_t * vFanouts; Vec_Int_t * vRecalcs, * vEvals; Abc_Obj_t * pBuf, * pFanin, * pFanout, * pExtra; int i, j, iNode, gateBest, gateBest2, fanBest, Counter = 0; float dGainBest, dGainBest2; // compute savings due to bypassing buffers vFanouts = Vec_PtrAlloc( 100 ); vRecalcs = Vec_IntAlloc( 100 ); vEvals = Vec_IntAlloc( 100 ); Vec_QueClear( p->vNodeByGain ); Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pBuf, i ) { assert( pBuf->fMarkB == 0 ); if ( Abc_ObjFaninNum(pBuf) != 1 ) continue; pFanin = Abc_ObjFanin0(pBuf); if ( !Abc_ObjIsNode(pFanin) ) continue; pExtra = NULL; if ( p->pNtk->vPhases == NULL ) { if ( Abc_SclIsInv(pBuf) ) { if ( !Abc_SclIsInv(pFanin) ) continue; pFanin = Abc_ObjFanin0(pFanin); if ( !Abc_ObjIsNode(pFanin) ) continue; pExtra = pBuf; // we make pBuf and pFanin are in the same phase and pFanin is a node } } // here we have pBuf and its fanin pFanin, which is a logic node // compute nodes to recalculate timing and nodes to evaluate afterwards Abc_SclFindNodesToUpdate( pFanin, &vRecalcs, &vEvals, pExtra ); assert( Vec_IntSize(vEvals) > 0 ); // consider fanouts of this node fanBest = -1; gateBest2 = -1; dGainBest2 = 0; Abc_NodeCollectFanouts( pBuf, vFanouts ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, j ) { // skip COs if ( Abc_ObjIsCo(pFanout) ) continue; // skip non-critical fanouts if ( !pFanout->fMarkA ) continue; // skip if fanin already has fanout as a fanout if ( Abc_NodeFindFanin(pFanout, pFanin) >= 0 ) continue; // skip if fanin already has fanout as a fanout if ( pExtra && Abc_NodeFindFanin(pFanout, pExtra) >= 0 ) continue; // prepare Abc_SclLoadStore3( p, pBuf ); Abc_SclUpdateLoadSplit( p, pBuf, pFanout ); Abc_ObjPatchFanin( pFanout, pBuf, pFanin ); // size the fanin gateBest = Abc_SclFindBestCell( p, pFanin, vRecalcs, vEvals, Notches, DelayGap, &dGainBest ); // unprepare Abc_SclLoadRestore3( p, pBuf ); Abc_ObjPatchFanin( pFanout, pFanin, pBuf ); if ( gateBest == -1 ) continue; // compare gain if ( dGainBest2 < dGainBest ) { dGainBest2 = dGainBest; gateBest2 = gateBest; fanBest = Abc_ObjId(pFanout); } } // remember savings if ( gateBest2 >= 0 ) { assert( dGainBest2 > 0.0 ); Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pBuf), dGainBest2 ); Vec_IntWriteEntry( p->vNode2Gate, Abc_ObjId(pBuf), gateBest2 ); Vec_QuePush( p->vNodeByGain, Abc_ObjId(pBuf) ); Vec_IntWriteEntry( p->vBestFans, Abc_ObjId(pBuf), fanBest ); } // if ( ++Counter == 17 ) // break; } Vec_PtrFree( vFanouts ); Vec_IntFree( vRecalcs ); Vec_IntFree( vEvals ); if ( Vec_QueSize(p->vNodeByGain) == 0 ) return 0; if ( fVeryVerbose ) printf( "\n" ); // accept changes for that are half above the average and do not overlap Counter = 0; dGainBest2 = -1; vFanouts = Vec_PtrAlloc( 100 ); while ( Vec_QueSize(p->vNodeByGain) ) { iNode = Vec_QuePop(p->vNodeByGain); pFanout = Abc_NtkObj( p->pNtk, Vec_IntEntry(p->vBestFans, iNode) ); pBuf = Abc_NtkObj( p->pNtk, iNode ); pFanin = Abc_ObjFanin0(pBuf); if ( pFanout->fMarkB || pBuf->fMarkB ) continue; if ( p->pNtk->vPhases == NULL ) { // update fanin if ( Abc_SclIsInv(pBuf) ) { if ( !Abc_SclIsInv(pFanin) ) { assert( 0 ); continue; } pFanin = Abc_ObjFanin0(pFanin); if ( !Abc_ObjIsNode(pFanin) ) { assert( 0 ); continue; } } } if ( pFanin->fMarkB ) continue; pFanout->fMarkB = 1; pBuf->fMarkB = 1; pFanin->fMarkB = 1; Vec_PtrPush( vFanouts, pFanout ); Vec_PtrPush( vFanouts, pBuf ); Vec_PtrPush( vFanouts, pFanin ); // remember gain if ( dGainBest2 == -1 ) dGainBest2 = Vec_FltEntry(p->vNode2Gain, iNode); // else if ( dGainBest2 > 2*Vec_FltEntry(p->vNode2Gain, iNode) ) // break; // redirect Abc_SclUpdateLoadSplit( p, pBuf, pFanout ); Abc_SclAddWireLoad( p, pBuf, 1 ); Abc_SclAddWireLoad( p, pFanin, 1 ); Abc_ObjPatchFanin( pFanout, pBuf, pFanin ); Abc_SclAddWireLoad( p, pBuf, 0 ); Abc_SclAddWireLoad( p, pFanin, 0 ); Abc_SclTimeIncUpdateLevel( pFanout ); // remember Vec_IntPush( p->vUpdates2, Abc_ObjId(pFanout) ); Vec_IntPush( p->vUpdates2, Abc_ObjId(pFanin) ); Vec_IntPush( p->vUpdates2, Abc_ObjId(pBuf) ); // update cell pCellOld = Abc_SclObjCell( pFanin ); pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, iNode) ); p->SumArea += pCellNew->area - pCellOld->area; Abc_SclObjSetCell( pFanin, pCellNew ); Abc_SclUpdateLoad( p, pFanin, pCellOld, pCellNew ); // record the update Vec_IntPush( p->vUpdates, Abc_ObjId(pFanin) ); Vec_IntPush( p->vUpdates, pCellNew->Id ); Abc_SclTimeIncInsert( p, pFanout ); Abc_SclTimeIncInsert( p, pBuf ); Abc_SclTimeIncInsert( p, pFanin ); // remember when this node was upsized Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pFanout), -1 ); Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pBuf), -1 ); Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pFanin), -1 ); // update polarity if ( p->pNtk->vPhases && Abc_SclIsInv(pBuf) ) Abc_NodeInvUpdateObjFanoutPolarity( pFanin, pFanout ); // report if ( fVeryVerbose ) { printf( "Node %6d Redir fanout %6d to fanin %6d. Gain = %7.1f ps. ", Abc_ObjId(pBuf), Abc_ObjId(pFanout), Abc_ObjId(pFanin), Vec_FltEntry(p->vNode2Gain, iNode) ); printf( "Gate %12s (%2d/%2d) -> %12s (%2d/%2d) \n", pCellOld->pName, pCellOld->Order, pCellOld->nGates, pCellNew->pName, pCellNew->Order, pCellNew->nGates ); } /* // check if the node became useless if ( Abc_ObjFanoutNum(pBuf) == 0 ) { pCellOld = Abc_SclObjCell( pBuf ); p->SumArea -= pCellOld->area; Abc_NtkDeleteObj_rec( pBuf, 1 ); printf( "Removed node %d.\n", iNode ); } */ Counter++; } Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, j ) pFanout->fMarkB = 0; Vec_PtrFree( vFanouts ); return Counter; } /**Function************************************************************* Synopsis [Check marked fanin/fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclObjCheckMarkedFanFans( Abc_Obj_t * pObj ) { Abc_Obj_t * pNext; int i; if ( pObj->fMarkB ) return 1; Abc_ObjForEachFanin( pObj, pNext, i ) if ( pNext->fMarkB ) return 1; Abc_ObjForEachFanout( pObj, pNext, i ) if ( pNext->fMarkB ) return 1; return 0; } void Abc_SclObjMarkFanFans( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) { // Abc_Obj_t * pNext; // int i; if ( pObj->fMarkB == 0 ) { Vec_PtrPush( vNodes, pObj ); pObj->fMarkB = 1; } /* Abc_ObjForEachFanin( pObj, pNext, i ) if ( pNext->fMarkB == 0 ) { Vec_PtrPush( vNodes, pNext ); pNext->fMarkB = 1; } Abc_ObjForEachFanout( pObj, pNext, i ) if ( pNext->fMarkB == 0 ) { Vec_PtrPush( vNodes, pNext ); pNext->fMarkB = 1; } */ } /**Function************************************************************* Synopsis [Computes the set of gates to upsize.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notches, int iIter, int DelayGap, int fMoreConserf ) { SC_Cell * pCellOld, * pCellNew; Vec_Int_t * vRecalcs, * vEvals; Vec_Ptr_t * vFanouts; Abc_Obj_t * pObj; float dGainBest, dGainBest2; int i, gateBest, Limit, Counter, iIterLast; // compute savings due to upsizing each node vRecalcs = Vec_IntAlloc( 100 ); vEvals = Vec_IntAlloc( 100 ); Vec_QueClear( p->vNodeByGain ); Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pObj, i ) { assert( pObj->fMarkB == 0 ); iIterLast = Vec_IntEntry(p->vNodeIter, Abc_ObjId(pObj)); if ( iIterLast >= 0 && iIterLast + 5 > iIter ) continue; // compute nodes to recalculate timing and nodes to evaluate afterwards Abc_SclFindNodesToUpdate( pObj, &vRecalcs, &vEvals, NULL ); assert( Vec_IntSize(vEvals) > 0 ); //printf( "%d -> %d\n", Vec_IntSize(vRecalcs), Vec_IntSize(vEvals) ); gateBest = Abc_SclFindBestCell( p, pObj, vRecalcs, vEvals, Notches, DelayGap, &dGainBest ); // remember savings if ( gateBest >= 0 ) { assert( dGainBest > 0.0 ); Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pObj), dGainBest ); Vec_IntWriteEntry( p->vNode2Gate, Abc_ObjId(pObj), gateBest ); Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) ); } } Vec_IntFree( vRecalcs ); Vec_IntFree( vEvals ); if ( Vec_QueSize(p->vNodeByGain) == 0 ) return 0; /* Limit = Abc_MinInt( Vec_QueSize(p->vNodeByGain), Abc_MaxInt((int)(0.01 * Ratio * Vec_IntSize(vPathNodes)), 1) ); //printf( "\nSelecting %d out of %d\n", Limit, Vec_QueSize(p->vNodeByGain) ); for ( i = 0; i < Limit; i++ ) { // get the object pObj = Abc_NtkObj( p->pNtk, Vec_QuePop(p->vNodeByGain) ); assert( pObj->fMarkA ); // find old and new gates pCellOld = Abc_SclObjCell( pObj ); pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, Abc_ObjId(pObj)) ); assert( pCellNew != NULL ); //printf( "%6d %20s -> %20s ", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName ); //printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) ); // update gate Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); p->SumArea += pCellNew->area - pCellOld->area; Abc_SclObjSetCell( pObj, pCellNew ); // record the update Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) ); Vec_IntPush( p->vUpdates, pCellNew->Id ); Abc_SclTimeIncInsert( p, pObj ); // remember when this node was upsized Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pObj), iIter ); } return Limit; */ Limit = Abc_MinInt( Vec_QueSize(p->vNodeByGain), Abc_MaxInt((int)(0.01 * Ratio * Vec_IntSize(vPathNodes)), 1) ); dGainBest2 = -1; Counter = 0; vFanouts = Vec_PtrAlloc( 100 ); while ( Vec_QueSize(p->vNodeByGain) ) { int iNode = Vec_QuePop(p->vNodeByGain); Abc_Obj_t * pObj = Abc_NtkObj( p->pNtk, iNode ); assert( pObj->fMarkA ); if ( Abc_SclObjCheckMarkedFanFans( pObj ) ) continue; Abc_SclObjMarkFanFans( pObj, vFanouts ); // remember gain if ( dGainBest2 == -1 ) dGainBest2 = Vec_FltEntry(p->vNode2Gain, iNode); // else if ( dGainBest2 > 3*Vec_FltEntry(p->vNode2Gain, iNode) ) // break; // printf( "%.1f ", Vec_FltEntry(p->vNode2Gain, iNode) ); // find old and new gates pCellOld = Abc_SclObjCell( pObj ); pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, Abc_ObjId(pObj)) ); assert( pCellNew != NULL ); //printf( "%6d %20s -> %20s ", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName ); //printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) ); // if ( pCellOld->Order > 0 ) // printf( "%.2f %d -> %d(%d) ", Vec_FltEntry(p->vNode2Gain, iNode), pCellOld->Order, pCellNew->Order, pCellNew->nGates ); // update gate p->SumArea += pCellNew->area - pCellOld->area; Abc_SclObjSetCell( pObj, pCellNew ); Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); // record the update Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) ); Vec_IntPush( p->vUpdates, pCellNew->Id ); Abc_SclTimeIncInsert( p, pObj ); // remember when this node was upsized Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pObj), iIter ); Counter++; if ( Counter == Limit ) break; } // printf( "\n" ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pObj, i ) pObj->fMarkB = 0; Vec_PtrFree( vFanouts ); return Counter; } void Abc_SclApplyUpdateToBest( Vec_Int_t * vGatesBest, Vec_Int_t * vGates, Vec_Int_t * vUpdate ) { int i, ObjId, GateId, GateId2; Vec_IntForEachEntryDouble( vUpdate, ObjId, GateId, i ) Vec_IntWriteEntry( vGatesBest, ObjId, GateId ); Vec_IntClear( vUpdate ); Vec_IntForEachEntryTwo( vGatesBest, vGates, GateId, GateId2, i ) assert( GateId == GateId2 ); // Vec_IntClear( vGatesBest ); // Vec_IntAppend( vGatesBest, vGates ); } void Abc_SclUndoRecentChanges( Abc_Ntk_t * pNtk, Vec_Int_t * vTrans ) { int i; assert( Vec_IntSize(vTrans) % 3 == 0 ); for ( i = Vec_IntSize(vTrans)/3 - 1; i >= 0; i-- ) { Abc_Obj_t * pFanout = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+0) ); Abc_Obj_t * pFanin = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+1) ); Abc_Obj_t * pObj = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+2) ); // we do not update load here because times will be recomputed Abc_ObjPatchFanin( pFanout, pFanin, pObj ); Abc_SclTimeIncUpdateLevel( pFanout ); // printf( "Node %6d Redir fanout %6d from fanin %6d. \n", // Abc_ObjId(pObj), Abc_ObjId(pFanout), Abc_ObjId(pFanin) ); // update polarity if ( pNtk->vPhases && Abc_SclIsInv(pObj) ) Abc_NodeInvUpdateObjFanoutPolarity( pObj, pFanout ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclUpsizePrintDiffs( SC_Man * p, SC_Lib * pLib, Abc_Ntk_t * pNtk ) { float fDiff = (float)0.001; int k; Abc_Obj_t * pObj; SC_Pair * pTimes = ABC_ALLOC( SC_Pair, p->nObjs ); SC_Pair * pSlews = ABC_ALLOC( SC_Pair, p->nObjs ); SC_Pair * pLoads = ABC_ALLOC( SC_Pair, p->nObjs ); memcpy( pTimes, p->pTimes, sizeof(SC_Pair) * p->nObjs ); memcpy( pSlews, p->pSlews, sizeof(SC_Pair) * p->nObjs ); memcpy( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs ); Abc_SclTimeNtkRecompute( p, NULL, NULL, 0, 0 ); Abc_NtkForEachNode( pNtk, pObj, k ) { if ( Abc_AbsFloat(p->pLoads[k].rise - pLoads[k].rise) > fDiff ) printf( "%6d : load rise differs %12.6f %f %f\n", k, p->pLoads[k].rise-pLoads[k].rise, p->pLoads[k].rise, pLoads[k].rise ); if ( Abc_AbsFloat(p->pLoads[k].fall - pLoads[k].fall) > fDiff ) printf( "%6d : load fall differs %12.6f %f %f\n", k, p->pLoads[k].fall-pLoads[k].fall, p->pLoads[k].fall, pLoads[k].fall ); if ( Abc_AbsFloat(p->pSlews[k].rise - pSlews[k].rise) > fDiff ) printf( "%6d : slew rise differs %12.6f %f %f\n", k, p->pSlews[k].rise-pSlews[k].rise, p->pSlews[k].rise, pSlews[k].rise ); if ( Abc_AbsFloat(p->pSlews[k].fall - pSlews[k].fall) > fDiff ) printf( "%6d : slew fall differs %12.6f %f %f\n", k, p->pSlews[k].fall-pSlews[k].fall, p->pSlews[k].fall, pSlews[k].fall ); if ( Abc_AbsFloat(p->pTimes[k].rise - pTimes[k].rise) > fDiff ) printf( "%6d : time rise differs %12.6f %f %f\n", k, p->pTimes[k].rise-pTimes[k].rise, p->pTimes[k].rise, pTimes[k].rise ); if ( Abc_AbsFloat(p->pTimes[k].fall - pTimes[k].fall) > fDiff ) printf( "%6d : time fall differs %12.6f %f %f\n", k, p->pTimes[k].fall-pTimes[k].fall, p->pTimes[k].fall, pTimes[k].fall ); } /* if ( memcmp( pTimes, p->pTimes, sizeof(SC_Pair) * p->nObjs ) ) printf( "Times differ!\n" ); if ( memcmp( pSlews, p->pSlews, sizeof(SC_Pair) * p->nObjs ) ) printf( "Slews differ!\n" ); if ( memcmp( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs ) ) printf( "Loads differ!\n" ); */ ABC_FREE( pTimes ); ABC_FREE( pSlews ); ABC_FREE( pLoads ); } /**Function************************************************************* Synopsis [Print cumulative statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclUpsizePrint( SC_Man * p, int Iter, int win, int nPathPos, int nPathNodes, int nUpsizes, int nTFOs, int fVerbose ) { printf( "%4d ", Iter ); printf( "Win:%3d. ", win ); printf( "PO:%6d. ", nPathPos ); printf( "Path:%7d. ", nPathNodes ); printf( "Gate:%5d. ", nUpsizes ); printf( "TFO:%7d. ", nTFOs ); printf( "A: " ); printf( "%.2f ", p->SumArea ); printf( "(%+5.1f %%) ", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 ); printf( "D: " ); printf( "%.2f ps ", p->MaxDelay ); printf( "(%+5.1f %%) ", 100.0 * (p->MaxDelay - p->MaxDelay0)/ p->MaxDelay0 ); printf( "B: " ); printf( "%.2f ps ", p->BestDelay ); printf( "(%+5.1f %%)", 100.0 * (p->BestDelay - p->MaxDelay0)/ p->MaxDelay0 ); printf( "%8.2f sec ", 1.0*(Abc_Clock() - p->timeTotal)/(CLOCKS_PER_SEC) ); printf( "%c", fVerbose ? '\n' : '\r' ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclUpsizeRemoveDangling( SC_Man * p, Abc_Ntk_t * pNtk ) { SC_Cell * pCell; Abc_Obj_t * pObj; int i; Abc_NtkForEachNodeNotBarBuf( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) == 0 ) { pCell = Abc_SclObjCell( pObj ); p->SumArea -= pCell->area; Abc_NtkDeleteObj_rec( pObj, 1 ); // printf( "Removed node %d.\n", i ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclUpsizePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) { SC_Man * p; Vec_Int_t * vPathPos = NULL; // critical POs Vec_Int_t * vPathNodes = NULL; // critical nodes and PIs abctime clk, nRuntimeLimit = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0; int i = 0, win, nUpsizes = -1, nFramesNoChange = 0, nConeSize = 0; int nAllPos, nAllNodes, nAllTfos, nAllUpsizes; if ( pPars->fVerbose ) { printf( "Parameters: " ); printf( "Iters =%5d. ", pPars->nIters ); printf( "Time win =%3d %%. ", pPars->Window ); printf( "Update ratio =%3d %%. ", pPars->Ratio ); printf( "UseDept =%2d. ", pPars->fUseDept ); printf( "UseWL =%2d. ", pPars->fUseWireLoads ); printf( "Target =%5d ps. ", pPars->DelayUser ); printf( "DelayGap =%3d ps. ", pPars->DelayGap ); printf( "Timeout =%4d sec", pPars->TimeOut ); printf( "\n" ); } // increase window for larger networks if ( pPars->Window == 1 ) pPars->Window += (Abc_NtkNodeNum(pNtk) > 40000); // prepare the manager; collect init stats p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, 0, pPars->BuffTreeEst ); p->timeTotal = Abc_Clock(); assert( p->vGatesBest == NULL ); p->vGatesBest = Vec_IntDup( p->pNtk->vGates ); p->BestDelay = p->MaxDelay0; // perform upsizing nAllPos = nAllNodes = nAllTfos = nAllUpsizes = 0; if ( p->BestDelay <= pPars->DelayUser ) printf( "Current delay (%.2f ps) does not exceed the target delay (%.2f ps). Upsizing is not performed.\n", p->BestDelay, (float)pPars->DelayUser ); else for ( i = 0; i < pPars->nIters; i++ ) { for ( win = pPars->Window + ((i % 7) == 6); win <= 100; win *= 2 ) { // detect critical path clk = Abc_Clock(); vPathPos = Abc_SclFindCriticalCoWindow( p, win ); vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, win, pPars->fUseDept ); p->timeCone += Abc_Clock() - clk; // selectively upsize the nodes clk = Abc_Clock(); if ( pPars->BypassFreq && i && (i % pPars->BypassFreq) == 0 ) nUpsizes = Abc_SclFindBypasses( p, vPathNodes, pPars->Ratio, pPars->Notches, i, pPars->DelayGap, pPars->fVeryVerbose ); else nUpsizes = Abc_SclFindUpsizes( p, vPathNodes, pPars->Ratio, pPars->Notches, i, pPars->DelayGap, (pPars->BypassFreq > 0) ); p->timeSize += Abc_Clock() - clk; // unmark critical path clk = Abc_Clock(); Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes ); Abc_SclUnmarkCriticalNodeWindow( p, vPathPos ); p->timeCone += Abc_Clock() - clk; if ( nUpsizes > 0 ) break; Vec_IntFree( vPathPos ); Vec_IntFree( vPathNodes ); } if ( nUpsizes == 0 ) break; // update timing information clk = Abc_Clock(); if ( pPars->fUseDept ) { if ( Vec_IntSize(p->vChanged) && !(pPars->BypassFreq && i && (i % pPars->BypassFreq) == 0) ) nConeSize = Abc_SclTimeIncUpdate( p ); else Abc_SclTimeNtkRecompute( p, NULL, NULL, pPars->fUseDept, 0 ); } else { Vec_Int_t * vTFO = Abc_SclFindTFO( p->pNtk, vPathNodes ); Abc_SclTimeCone( p, vTFO ); nConeSize = Vec_IntSize( vTFO ); Vec_IntFree( vTFO ); } p->timeTime += Abc_Clock() - clk; // Abc_SclUpsizePrintDiffs( p, pLib, pNtk ); // save the best network p->MaxDelay = Abc_SclReadMaxDelay( p ); if ( p->BestDelay > p->MaxDelay ) { p->BestDelay = p->MaxDelay; Abc_SclApplyUpdateToBest( p->vGatesBest, p->pNtk->vGates, p->vUpdates ); Vec_IntClear( p->vUpdates2 ); nFramesNoChange = 0; } else nFramesNoChange++; // report and cleanup Abc_SclUpsizePrint( p, i, win, Vec_IntSize(vPathPos), Vec_IntSize(vPathNodes), nUpsizes, nConeSize, pPars->fVeryVerbose || (pPars->fVerbose && nFramesNoChange == 0) ); //|| (i == nIters-1) ); nAllPos += Vec_IntSize(vPathPos); nAllNodes += Vec_IntSize(vPathNodes); nAllTfos += nConeSize; nAllUpsizes += nUpsizes; Vec_IntFree( vPathPos ); Vec_IntFree( vPathNodes ); // check timeout if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit ) break; // check no change if ( nFramesNoChange > pPars->nIterNoChange ) break; // check best delay if ( p->BestDelay <= pPars->DelayUser ) break; } // update for best gates and recompute timing ABC_SWAP( Vec_Int_t *, p->vGatesBest, p->pNtk->vGates ); if ( pPars->BypassFreq != 0 ) Abc_SclUndoRecentChanges( p->pNtk, p->vUpdates2 ); if ( pPars->BypassFreq != 0 ) Abc_SclUpsizeRemoveDangling( p, pNtk ); Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, 0, 0 ); if ( pPars->fVerbose ) Abc_SclUpsizePrint( p, i, pPars->Window, nAllPos/(i?i:1), nAllNodes/(i?i:1), nAllUpsizes/(i?i:1), nAllTfos/(i?i:1), 1 ); else printf( " \r" ); // report runtime p->timeTotal = Abc_Clock() - p->timeTotal; if ( pPars->fVerbose ) { p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime; ABC_PRTP( "Runtime: Critical path", p->timeCone, p->timeTotal ); ABC_PRTP( "Runtime: Sizing eval ", p->timeSize, p->timeTotal ); ABC_PRTP( "Runtime: Timing update", p->timeTime, p->timeTotal ); ABC_PRTP( "Runtime: Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "Runtime: TOTAL ", p->timeTotal, p->timeTotal ); } if ( pPars->fDumpStats ) Abc_SclDumpStats( p, "stats2.txt", p->timeTotal ); if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit ) printf( "Gate sizing timed out at %d seconds.\n", pPars->TimeOut ); // save the result and quit Abc_SclSclGates2MioGates( pLib, pNtk ); // updates gate pointers Abc_SclManFree( p ); // Abc_NtkCleanMarkAB( pNtk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ) { Abc_Ntk_t * pNtkNew = pNtk; if ( pNtk->nBarBufs2 > 0 ) pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); Abc_SclUpsizePerformInt( pLib, pNtkNew, pPars ); if ( pNtk->nBarBufs2 > 0 ) Abc_SclTransferGates( pNtk, pNtkNew ); if ( pNtk->nBarBufs2 > 0 ) Abc_NtkDelete( pNtkNew ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/scl/sclUtil.c000066400000000000000000000237451300674244400231700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sclUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Standard-cell library representation.] Synopsis [Various utilities.] Author [Alan Mishchenko, Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 24, 2012.] Revision [$Id: sclUtil.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sclSize.h" #include "map/mio/mio.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converts pNode->pData gates into array of SC_Lit gate IDs and back.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclMioGates2SclGates( SC_Lib * pLib, Abc_Ntk_t * p ) { Abc_Obj_t * pObj; int i, gateId, bufferId; // find buffer if ( Mio_LibraryReadBuf((Mio_Library_t *)p->pManFunc) == NULL ) { printf( "Cannot find buffer in the current library. Quitting.\n" ); return; } bufferId = Abc_SclCellFind( pLib, Mio_GateReadName(Mio_LibraryReadBuf((Mio_Library_t *)p->pManFunc)) ); assert( bufferId >= 0 ); // remap cells assert( p->vGates == NULL ); p->vGates = Vec_IntStartFull( Abc_NtkObjNumMax(p) ); Abc_NtkForEachNodeNotBarBuf1( p, pObj, i ) { gateId = Abc_SclCellFind( pLib, Mio_GateReadName((Mio_Gate_t *)pObj->pData) ); assert( gateId >= 0 ); Vec_IntWriteEntry( p->vGates, i, gateId ); } p->pSCLib = pLib; } void Abc_SclSclGates2MioGates( SC_Lib * pLib, Abc_Ntk_t * p ) { Abc_Obj_t * pObj; SC_Cell * pCell; int i, Counter = 0, CounterAll = 0; assert( p->vGates != NULL ); Abc_NtkForEachNodeNotBarBuf1( p, pObj, i ) { pCell = Abc_SclObjCell(pObj); assert( pCell->n_inputs == Abc_ObjFaninNum(pObj) ); pObj->pData = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pManFunc, pCell->pName, NULL ); Counter += (pObj->pData == NULL); assert( pObj->fMarkA == 0 && pObj->fMarkB == 0 ); CounterAll++; } if ( Counter ) printf( "Could not find %d (out of %d) gates in the current library.\n", Counter, CounterAll ); Vec_IntFreeP( &p->vGates ); p->pSCLib = NULL; } /**Function************************************************************* Synopsis [Transfer gate sizes from AIG without barbufs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclTransferGates( Abc_Ntk_t * pOld, Abc_Ntk_t * pNew ) { Abc_Obj_t * pObj; int i; assert( pOld->nBarBufs2 > 0 ); assert( pNew->nBarBufs2 == 0 ); Abc_NtkForEachNodeNotBarBuf( pOld, pObj, i ) { if ( pObj->pCopy == NULL ) continue; assert( Abc_ObjNtk(pObj->pCopy) == pNew ); pObj->pData = pObj->pCopy->pData; } } /**Function************************************************************* Synopsis [Reports percentage of gates of each size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define ABC_SCL_MAX_SIZE 64 void Abc_SclManPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p, Vec_Int_t * vGates ) { Abc_Obj_t * pObj; SC_Cell * pCell; int i, nGates = 0, Counters[ABC_SCL_MAX_SIZE] = {0}; double TotArea = 0, Areas[ABC_SCL_MAX_SIZE] = {0}; Abc_NtkForEachNodeNotBarBuf1( p, pObj, i ) { pCell = SC_LibCell( pLib, Vec_IntEntry(vGates, Abc_ObjId(pObj)) ); assert( pCell->Order < ABC_SCL_MAX_SIZE ); Counters[pCell->Order]++; Areas[pCell->Order] += pCell->area; TotArea += pCell->area; nGates++; } printf( "Total gates = %d. Total area = %.1f\n", nGates, TotArea ); for ( i = 0; i < ABC_SCL_MAX_SIZE; i++ ) { if ( Counters[i] == 0 ) continue; printf( "Cell size = %d. ", i ); printf( "Count = %6d ", Counters[i] ); printf( "(%5.1f %%) ", 100.0 * Counters[i] / nGates ); printf( "Area = %12.1f ", Areas[i] ); printf( "(%5.1f %%) ", 100.0 * Areas[i] / TotArea ); printf( "\n" ); } } void Abc_SclPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p ) { Abc_SclMioGates2SclGates( pLib, p ); Abc_SclManPrintGateSizes( pLib, p, p->vGates ); Abc_SclSclGates2MioGates( pLib, p ); Vec_IntFreeP( &p->vGates ); p->pSCLib = NULL; } /**Function************************************************************* Synopsis [Downsizes each gate to its minimium size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ SC_Cell * Abc_SclFindMaxAreaCell( SC_Cell * pRepr ) { SC_Cell * pCell, * pBest = pRepr; float AreaBest = pRepr->area; int i; SC_RingForEachCell( pRepr, pCell, i ) if ( AreaBest < pCell->area ) { AreaBest = pCell->area; pBest = pCell; } return pBest; } Vec_Int_t * Abc_SclFindMinAreas( SC_Lib * pLib, int fUseMax ) { Vec_Int_t * vMinCells; SC_Cell * pCell, * pRepr = NULL, * pBest = NULL; int i, k; // map each gate in the library into its min/max-size prototype vMinCells = Vec_IntStartFull( Vec_PtrSize(&pLib->vCells) ); SC_LibForEachCellClass( pLib, pRepr, i ) { pBest = fUseMax ? Abc_SclFindMaxAreaCell(pRepr) : pRepr; SC_RingForEachCell( pRepr, pCell, k ) Vec_IntWriteEntry( vMinCells, pCell->Id, pBest->Id ); } return vMinCells; } void Abc_SclMinsizePerform( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax, int fVerbose ) { Vec_Int_t * vMinCells; Abc_Obj_t * pObj; int i, gateId; vMinCells = Abc_SclFindMinAreas( pLib, fUseMax ); Abc_SclMioGates2SclGates( pLib, p ); Abc_NtkForEachNodeNotBarBuf1( p, pObj, i ) { gateId = Vec_IntEntry( p->vGates, i ); assert( gateId >= 0 && gateId < Vec_PtrSize(&pLib->vCells) ); gateId = Vec_IntEntry( vMinCells, gateId ); assert( gateId >= 0 && gateId < Vec_PtrSize(&pLib->vCells) ); Vec_IntWriteEntry( p->vGates, i, gateId ); } Abc_SclSclGates2MioGates( pLib, p ); Vec_IntFree( vMinCells ); } int Abc_SclCountMinSize( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax ) { Vec_Int_t * vMinCells; Abc_Obj_t * pObj; int i, gateId, Counter = 0; vMinCells = Abc_SclFindMinAreas( pLib, fUseMax ); Abc_NtkForEachNodeNotBarBuf1( p, pObj, i ) { gateId = Vec_IntEntry( p->vGates, i ); Counter += ( gateId == Vec_IntEntry(vMinCells, gateId) ); } Vec_IntFree( vMinCells ); return Counter; } /**Function************************************************************* Synopsis [Reads timing constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclReadTimingConstr( Abc_Frame_t * pAbc, char * pFileName, int fVerbose ) { char Buffer[1000], * pToken; FILE * pFile = fopen( pFileName, "rb" ); while ( fgets( Buffer, 1000, pFile ) ) { pToken = strtok( Buffer, " \t\r\n" ); if ( pToken == NULL ) continue; // if ( !strcmp(pToken, "set_driving_cell") ) if ( !strcmp(pToken, "default_input_cell") ) { Abc_FrameSetDrivingCell( Abc_UtilStrsav(strtok(NULL, " \t\r\n")) ); if ( fVerbose ) printf( "Setting driving cell to be \"%s\".\n", Abc_FrameReadDrivingCell() ); } // else if ( !strcmp(pToken, "set_load") ) else if ( !strcmp(pToken, "default_output_load") ) { Abc_FrameSetMaxLoad( atof(strtok(NULL, " \t\r\n")) ); if ( fVerbose ) printf( "Setting driving cell to be %f.\n", Abc_FrameReadMaxLoad() ); } // else printf( "Unrecognized token \"%s\".\n", pToken ); } fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_SclExtractBarBufs( Abc_Ntk_t * pNtk ) { Vec_Int_t * vBufs; Mio_Gate_t * pBuffer; Abc_Obj_t * pObj; int i; pBuffer = Mio_LibraryReadBuf( (Mio_Library_t *)pNtk->pManFunc ); if ( pBuffer == NULL ) { printf( "Cannot find buffer in the current library. Quitting.\n" ); return NULL; } vBufs = Vec_IntAlloc( 100 ); Abc_NtkForEachBarBuf( pNtk, pObj, i ) { assert( pObj->pData == NULL ); pObj->pData = pBuffer; Vec_IntPush( vBufs, i ); } return vBufs; } void Abc_SclInsertBarBufs( Abc_Ntk_t * pNtk, Vec_Int_t * vBufs ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObjVec( vBufs, pNtk, pObj, i ) pObj->pData = NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/000077500000000000000000000000001300674244400217475ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/module.make000066400000000000000000000001271300674244400240730ustar00rootroot00000000000000SRC += src/map/super/super.c \ src/map/super/superAnd.c \ src/map/super/superGate.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/super.c000066400000000000000000000263751300674244400232660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [super.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Pre-computation of supergates.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 18, 2003.] Revision [$Id: super.c,v 1.6 2004/10/30 20:51:11 satrajit Exp $] ***********************************************************************/ #include "superInt.h" #include "base/main/mainInt.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Super_CommandSupergates ( Abc_Frame_t * pAbc, int argc, char **argv ); static int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "SC mapping", "super", Super_CommandSupergates, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "super2", Super_CommandSupergatesAnd, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_End( Abc_Frame_t * pAbc ) { } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pOut, * pErr; int nVarsMax, nLevels; int fVerbose; int c; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults nVarsMax = 4; nLevels = 3; fVerbose = 0; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "ILvh")) != EOF ) { switch (c) { case 'I': nVarsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVarsMax < 0 ) goto usage; break; case 'L': nLevels = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLevels < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } Super2_Precompute( nVarsMax, nLevels, fVerbose ); return 0; usage: fprintf( pErr, "usage: super2 [-IL num] [-vh]\n"); fprintf( pErr, "\t precomputes the supergates composed of AND2s and INVs\n" ); fprintf( pErr, "\t-I num : the max number of inputs to the supergate [default = %d]\n", nVarsMax ); fprintf( pErr, "\t-L num : the max number of logic levels of gates [default = %d]\n", nLevels ); fprintf( pErr, "\t-v : enable verbose output\n"); fprintf( pErr, "\t-h : print the help message\n"); return 1; /* error exit */ } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) { FILE * pFile; FILE * pOut, * pErr; Mio_Library_t * pLib; char * FileName, * ExcludeFile; float DelayLimit; float AreaLimit; int fSkipInvs; int fWriteOldFormat; int nVarsMax, nLevels, nGatesMax, TimeLimit; int fVerbose; int c; pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set the defaults nVarsMax = 5; nLevels = 2; DelayLimit = 0; AreaLimit = 0; nGatesMax = 0; TimeLimit = 0; fSkipInvs = 1; fVerbose = 0; fWriteOldFormat = 0; ExcludeFile = 0; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "ILNTDAEsovh")) != EOF ) { switch (c) { case 'I': nVarsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVarsMax < 0 ) goto usage; break; case 'L': nLevels = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLevels < 0 ) goto usage; break; case 'N': nGatesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nGatesMax < 0 ) goto usage; break; case 'T': TimeLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( TimeLimit < 0 ) goto usage; break; case 'D': DelayLimit = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( DelayLimit <= 0.0 ) goto usage; break; case 'A': AreaLimit = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( AreaLimit <= 0.0 ) goto usage; break; case 'E': ExcludeFile = argv[globalUtilOptind]; if ( ExcludeFile == 0 ) goto usage; globalUtilOptind++; break; case 's': fSkipInvs ^= 1; break; case 'o': fWriteOldFormat ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { fprintf( pErr, "The genlib library file should be given on the command line.\n" ); goto usage; } if ( nVarsMax < 2 || nVarsMax > 6 ) { fprintf( pErr, "The max number of variables (%d) should be more than 1 and less than 7.\n", nVarsMax ); goto usage; } // get the input file name FileName = argv[globalUtilOptind]; if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) // if ( (pFile = fopen( FileName, "r" )) == NULL ) { fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); if (( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) )) fprintf( pErr, "Did you mean \"%s\"?", FileName ); fprintf( pErr, "\n" ); return 1; } fclose( pFile ); // set the new network pLib = Mio_LibraryRead( FileName, NULL, ExcludeFile, fVerbose ); if ( pLib == NULL ) { fprintf( pErr, "Reading library has failed.\n" ); goto usage; } // compute the gates FileName = Extra_FileNameGenericAppend(Mio_LibraryReadName(pLib), ".super"); Super_Precompute( pLib, nVarsMax, nLevels, nGatesMax, DelayLimit, AreaLimit, TimeLimit, fSkipInvs, fVerbose, FileName ); // delete the library Mio_LibraryDelete( pLib ); return 0; usage: fprintf( pErr, "usage: super [-ILNT num] [-DA float] [-E file] [-sovh] \n"); fprintf( pErr, "\t precomputes the supergates for the given genlib library\n" ); fprintf( pErr, "\t-I num : the max number of supergate inputs [default = %d]\n", nVarsMax ); fprintf( pErr, "\t-L num : the max number of levels of gates [default = %d]\n", nLevels ); fprintf( pErr, "\t-N num : the limit on the number of considered supergates [default = %d]\n", nGatesMax ); fprintf( pErr, "\t-T num : the approximate runtime limit in seconds [default = %d]\n", TimeLimit ); fprintf( pErr, "\t-D float : the max delay of the supergates [default = %.2f]\n", DelayLimit ); fprintf( pErr, "\t-A float : the max area of the supergates [default = %.2f]\n", AreaLimit ); fprintf( pErr, "\t-E file : file contains list of genlib gates to exclude\n" ); fprintf( pErr, "\t-s : toggle the use of inverters at the inputs [default = %s]\n", (fSkipInvs? "no": "yes") ); fprintf( pErr, "\t-o : toggle dumping the supergate library in old format [default = %s]\n", (fWriteOldFormat? "yes": "no") ); fprintf( pErr, "\t-v : enable verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); fprintf( pErr, "\t-h : print the help message\n"); fprintf( pErr, "\n"); fprintf( pErr, "\tHere is a piece of advice on precomputing supergate libraries:\n"); fprintf( pErr, "\t\n"); fprintf( pErr, "\tStart with the number of inputs equal to 5 (-I 5), the number of \n"); fprintf( pErr, "\tlevels equal to 2 (-L 2), the delay equal to 2-3 delays of inverter, \n"); fprintf( pErr, "\tthe area equal to 2-3 areas of two input NAND, and runtime limit equal \n"); fprintf( pErr, "\tto 10 seconds (-T 10). Run precomputation and learn from the result.\n"); fprintf( pErr, "\tDetermine what parameter is most constraining and try to increase \n"); fprintf( pErr, "\tthe value of that parameter. The goal is to have a well-balanced\n"); fprintf( pErr, "\tset of constraints and the resulting supergate library containing\n"); fprintf( pErr, "\tapproximately 5K-20K supergates. Typically, it is better to increase\n"); fprintf( pErr, "\tdelay limit rather than area limit, because having large-area supergates\n"); fprintf( pErr, "\tmay result in a considerable increase in area.\n"); fprintf( pErr, "\t\n"); fprintf( pErr, "\tNote that a good supergate library for experiments typically can be \n"); fprintf( pErr, "\tprecomputed in 30 sec or less. Increasing runtime limit makes sense when\n"); fprintf( pErr, "\tother parameters are well-balanced and it is needed to enumerate more\n"); fprintf( pErr, "\tchoices to have a good result. In the end, to compute the final library\n"); fprintf( pErr, "\tthe runtime can be set to 300 sec to ensure the ultimate quality.\n"); fprintf( pErr, "\tIn some cases, the runtime has to be reduced if the supergate library\n"); fprintf( pErr, "\tcontains too many supergates (> 500K).\n"); fprintf( pErr, "\t\n"); fprintf( pErr, "\tWhen precomputing libraries of 6 inputs (-i 6), start with even more \n"); fprintf( pErr, "\trestricted parameters and gradually increase them until the goal is met.\n"); fprintf( pErr, "\t\n"); return 1; /* error exit */ } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/super.h000066400000000000000000000053721300674244400232650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [super.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Pre-computation of supergates (delay-limited gate combinations).] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: super.h,v 1.3 2004/06/28 14:20:25 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__super__super_h #define ABC__map__super__super_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== superAnd.c =============================================================*/ extern void Super2_Precompute( int nInputs, int nLevels, int fVerbose ); /*=== superGate.c =============================================================*/ extern Vec_Str_t * Super_PrecomputeStr( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose ); extern void Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose, char * pFileName ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/superAnd.c000066400000000000000000000537651300674244400237140ustar00rootroot00000000000000/**CFile**************************************************************** FileName [superAnd.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Pre-computation of supergates.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: superAnd.c,v 1.3 2004/06/28 14:20:25 alanmi Exp $] ***********************************************************************/ #include "superInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the bit masks #define SUPER_MASK(n) ((~((unsigned)0)) >> (32-n)) #define SUPER_FULL (~((unsigned)0)) // data structure for AND2 subgraph precomputation typedef struct Super2_ManStruct_t_ Super2_Man_t; // manager typedef struct Super2_LibStruct_t_ Super2_Lib_t; // library typedef struct Super2_GateStruct_t_ Super2_Gate_t; // supergate struct Super2_ManStruct_t_ { Extra_MmFixed_t * pMem; // memory manager for all supergates stmm_table * tTable; // mapping of truth tables into gates int nTried; // the total number of tried }; struct Super2_LibStruct_t_ { int i; // used to iterate through the table int k; // used to iterate through the table int nInputs; // the number of inputs int nMints; // the number of minterms int nLevels; // the number of logic levels int nGates; // the number of gates in the library int nGatesAlloc; // the number of allocated places Super2_Gate_t ** pGates; // the gates themselves unsigned uMaskBit; // the mask used to determine the compl bit }; struct Super2_GateStruct_t_ { unsigned uTruth; // the truth table of this supergate Super2_Gate_t * pOne; // the left wing Super2_Gate_t * pTwo; // the right wing Super2_Gate_t * pNext; // the next gate in the table }; // manipulation of complemented attributes #define Super2_IsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01))) #define Super2_Regular(p) ((Super2_Gate_t *)((ABC_PTRUINT_T)(p) & ~01)) #define Super2_Not(p) ((Super2_Gate_t *)((ABC_PTRUINT_T)(p) ^ 01)) #define Super2_NotCond(p,c) ((Super2_Gate_t *)((ABC_PTRUINT_T)(p) ^ (c))) // iterating through the gates in the library #define Super2_LibForEachGate( Lib, Gate ) \ for ( Lib->i = 0; \ Lib->i < Lib->nGates && (Gate = Lib->pGates[Lib->i]); \ Lib->i++ ) #define Super2_LibForEachGate2( Lib, Gate2 ) \ for ( Lib->k = 0; \ Lib->k < Lib->i && (Gate2 = Lib->pGates[Lib->k]); \ Lib->k++ ) // static functions static Super2_Man_t * Super2_ManStart(); static void Super2_ManStop( Super2_Man_t * pMan ); static Super2_Lib_t * Super2_LibStart(); static Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib ); static void Super2_LibStop( Super2_Lib_t * pLib ); static void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate ); static Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs ); static Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib ); static void Super2_LibWrite( Super2_Lib_t * pLib ); static void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate ); static char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level ); static int Super2_LibWriteCompare( char * pStr1, char * pStr2 ); static int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Precomputes the library of AND2 gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super2_Precompute( int nInputs, int nLevels, int fVerbose ) { Super2_Man_t * pMan; Super2_Lib_t * pLibCur, * pLibNext; int Level; abctime clk; assert( nInputs < 6 ); // start the manager pMan = Super2_ManStart(); // get the starting supergates pLibCur = Super2_LibFirst( pMan, nInputs ); // perform the computation of supergates printf( "Computing supergates for %d inputs and %d levels:\n", nInputs, nLevels ); for ( Level = 1; Level <= nLevels; Level++ ) { clk = Abc_Clock(); pLibNext = Super2_LibCompute( pMan, pLibCur ); pLibNext->nLevels = Level; Super2_LibStop( pLibCur ); pLibCur = pLibNext; printf( "Level %d: Tried = %7d. Computed = %7d. ", Level, pMan->nTried, pLibCur->nGates ); ABC_PRT( "Runtime", Abc_Clock() - clk ); fflush( stdout ); } printf( "Writing the output file...\n" ); fflush( stdout ); // write them into a file Super2_LibWrite( pLibCur ); Super2_LibStop( pLibCur ); // stop the manager Super2_ManStop( pMan ); } /**Function************************************************************* Synopsis [Starts the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Super2_Man_t * Super2_ManStart() { Super2_Man_t * pMan; pMan = ABC_ALLOC( Super2_Man_t, 1 ); memset( pMan, 0, sizeof(Super2_Man_t) ); pMan->pMem = Extra_MmFixedStart( sizeof(Super2_Gate_t) ); pMan->tTable = stmm_init_table( st__ptrcmp, st__ptrhash ); return pMan; } /**Function************************************************************* Synopsis [Stops the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super2_ManStop( Super2_Man_t * pMan ) { Extra_MmFixedStop( pMan->pMem ); stmm_free_table( pMan->tTable ); ABC_FREE( pMan ); } /**Function************************************************************* Synopsis [Starts the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Super2_Lib_t * Super2_LibStart() { Super2_Lib_t * pLib; pLib = ABC_ALLOC( Super2_Lib_t, 1 ); memset( pLib, 0, sizeof(Super2_Lib_t) ); return pLib; } /**Function************************************************************* Synopsis [Duplicates the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib ) { Super2_Lib_t * pLibNew; pLibNew = Super2_LibStart(); pLibNew->nInputs = pLib->nInputs; pLibNew->nMints = pLib->nMints; pLibNew->nLevels = pLib->nLevels; pLibNew->nGates = pLib->nGates; pLibNew->uMaskBit = pLib->uMaskBit; pLibNew->nGatesAlloc = 1000 + pLib->nGatesAlloc; pLibNew->pGates = ABC_ALLOC( Super2_Gate_t *, pLibNew->nGatesAlloc ); memcpy( pLibNew->pGates, pLib->pGates, pLibNew->nGates * sizeof(Super2_Gate_t *) ); return pLibNew; } /**Function************************************************************* Synopsis [Add gate to the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate ) { if ( pLib->nGates == pLib->nGatesAlloc ) { pLib->pGates = ABC_REALLOC( Super2_Gate_t *, pLib->pGates, 3 * pLib->nGatesAlloc ); pLib->nGatesAlloc *= 3; } pLib->pGates[ pLib->nGates++ ] = pGate; } /**Function************************************************************* Synopsis [Stops the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super2_LibStop( Super2_Lib_t * pLib ) { ABC_FREE( pLib->pGates ); ABC_FREE( pLib ); } /**Function************************************************************* Synopsis [Derives the starting supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs ) { Super2_Lib_t * pLib; int v, m; // start the library pLib = Super2_LibStart(); // create the starting supergates pLib->nInputs = nInputs; pLib->nMints = (1 << nInputs); pLib->nLevels = 0; pLib->nGates = nInputs + 1; pLib->nGatesAlloc = nInputs + 1; pLib->uMaskBit = (1 << (pLib->nMints-1)); pLib->pGates = ABC_ALLOC( Super2_Gate_t *, nInputs + 1 ); // add the constant 0 pLib->pGates[0] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); memset( pLib->pGates[0], 0, sizeof(Super2_Gate_t) ); // add the elementary gates for ( v = 0; v < nInputs; v++ ) { pLib->pGates[v+1] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); memset( pLib->pGates[v+1], 0, sizeof(Super2_Gate_t) ); pLib->pGates[v+1]->pTwo = (Super2_Gate_t *)(ABC_PTRUINT_T)v; } // set up their truth tables for ( m = 0; m < pLib->nMints; m++ ) for ( v = 0; v < nInputs; v++ ) if ( m & (1 << v) ) pLib->pGates[v+1]->uTruth |= (1 << m); return pLib; } /**Function************************************************************* Synopsis [Precomputes one level of supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib ) { Super2_Lib_t * pLibNew; Super2_Gate_t * pGate1, * pGate2, * pGateNew; Super2_Gate_t ** ppGate; unsigned Mask = SUPER_MASK(pLib->nMints); unsigned uTruth, uTruthR, uTruth1, uTruth2, uTruth1c, uTruth2c; // start the new library pLibNew = Super2_LibDup( pLib ); // reset the hash table stmm_free_table( pMan->tTable ); pMan->tTable = stmm_init_table( st__ptrcmp, st__ptrhash ); // set the starting things into the hash table Super2_LibForEachGate( pLibNew, pGate1 ) { uTruthR = ((pGate1->uTruth & pLibNew->uMaskBit)? Mask & ~pGate1->uTruth : pGate1->uTruth); if ( stmm_lookup( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char **)&pGate2 ) ) { printf( "New gate:\n" ); Super2_LibWriteGate( stdout, pLibNew, pGate1 ); printf( "Gate in the table:\n" ); Super2_LibWriteGate( stdout, pLibNew, pGate2 ); assert( 0 ); } stmm_insert( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char *)(ABC_PTRUINT_T)pGate1 ); } // set the number of gates tried pMan->nTried = pLibNew->nGates; // go through the gate pairs Super2_LibForEachGate( pLib, pGate1 ) { if ( pLib->i && pLib->i % 300 == 0 ) { printf( "Tried %5d first gates...\n", pLib->i ); fflush( stdout ); } Super2_LibForEachGate2( pLib, pGate2 ) { uTruth1 = pGate1->uTruth; uTruth2 = pGate2->uTruth; uTruth1c = Mask & ~uTruth1; uTruth2c = Mask & ~uTruth2; // none complemented uTruth = uTruth1 & uTruth2; uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); if ( !stmm_find_or_add( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char ***)&ppGate ) ) { pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); pGateNew->pOne = pGate1; pGateNew->pTwo = pGate2; pGateNew->uTruth = uTruth; *ppGate = pGateNew; Super2_LibAddGate( pLibNew, pGateNew ); } // one complemented uTruth = uTruth1c & uTruth2; uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); if ( !stmm_find_or_add( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char ***)&ppGate ) ) { pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); pGateNew->pOne = Super2_Not(pGate1); pGateNew->pTwo = pGate2; pGateNew->uTruth = uTruth; *ppGate = pGateNew; Super2_LibAddGate( pLibNew, pGateNew ); } // another complemented uTruth = uTruth1 & uTruth2c; uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); if ( !stmm_find_or_add( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char ***)&ppGate ) ) { pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); pGateNew->pOne = pGate1; pGateNew->pTwo = Super2_Not(pGate2); pGateNew->uTruth = uTruth; *ppGate = pGateNew; Super2_LibAddGate( pLibNew, pGateNew ); } // both complemented uTruth = uTruth1c & uTruth2c; uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); if ( !stmm_find_or_add( pMan->tTable, (char *)(ABC_PTRUINT_T)uTruthR, (char ***)&ppGate ) ) { pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); pGateNew->pOne = Super2_Not(pGate1); pGateNew->pTwo = Super2_Not(pGate2); pGateNew->uTruth = uTruth; *ppGate = pGateNew; Super2_LibAddGate( pLibNew, pGateNew ); } pMan->nTried += 4; } } return pLibNew; } static unsigned s_uMaskBit; static unsigned s_uMaskAll; /**Function************************************************************* Synopsis [Writes the library into the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super2_LibWrite( Super2_Lib_t * pLib ) { Super2_Gate_t * pGate; FILE * pFile; char FileName[100]; abctime clk; if ( pLib->nLevels > 5 ) { printf( "Cannot write file for %d levels.\n", pLib->nLevels ); return; } clk = Abc_Clock(); // sort the supergates by truth table s_uMaskBit = pLib->uMaskBit; s_uMaskAll = SUPER_MASK(pLib->nMints); qsort( (void *)pLib->pGates, pLib->nGates, sizeof(Super2_Gate_t *), (int (*)(const void *, const void *)) Super2_LibCompareGates ); assert( Super2_LibCompareGates( pLib->pGates, pLib->pGates + pLib->nGates - 1 ) < 0 ); ABC_PRT( "Sorting", Abc_Clock() - clk ); // start the file sprintf( FileName, "superI%dL%d", pLib->nInputs, pLib->nLevels ); pFile = fopen( FileName, "w" ); fprintf( pFile, "# AND2/INV supergates derived on %s.\n", Extra_TimeStamp() ); fprintf( pFile, "# Command line: \"super2 -i %d -l %d\".\n", pLib->nInputs, pLib->nLevels ); fprintf( pFile, "# The number of inputs = %6d.\n", pLib->nInputs ); fprintf( pFile, "# The number of levels = %6d.\n", pLib->nLevels ); fprintf( pFile, "# The number of supergates = %6d.\n", pLib->nGates ); fprintf( pFile, "# The total functions = %6d.\n", (1<<(pLib->nMints-1)) ); fprintf( pFile, "\n" ); fprintf( pFile, "%6d\n", pLib->nGates ); // print the gates Super2_LibForEachGate( pLib, pGate ) Super2_LibWriteGate( pFile, pLib, pGate ); fclose( pFile ); printf( "The supergates are written into file \"%s\" ", FileName ); printf( "(%0.2f MB).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); } /**Function************************************************************* Synopsis [Writes the gate into the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 ) { Super2_Gate_t * pG1 = *ppG1; Super2_Gate_t * pG2 = *ppG2; unsigned uTruth1, uTruth2; uTruth1 = (pG1->uTruth & s_uMaskBit)? s_uMaskAll & ~pG1->uTruth : pG1->uTruth; uTruth2 = (pG2->uTruth & s_uMaskBit)? s_uMaskAll & ~pG2->uTruth : pG2->uTruth; if ( uTruth1 < uTruth2 ) return -1; return 1; } /**Function************************************************************* Synopsis [Writes the gate into the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate ) { // unsigned uTruthR; unsigned uTruth; int fInv; // check whether the gate need complementation fInv = (int)(pGate->uTruth & pLib->uMaskBit); uTruth = (fInv? ~pGate->uTruth : pGate->uTruth); /* // reverse the truth table uTruthR = 0; for ( m = 0; m < pLib->nMints; m++ ) if ( uTruth & (1 << m) ) uTruthR |= (1 << (pLib->nMints-1-m)); */ // write the truth table Extra_PrintBinary( pFile, &uTruth, pLib->nMints ); fprintf( pFile, " " ); // write the symbolic expression fprintf( pFile, "%s", Super2_LibWriteGate_rec( pGate, fInv, pLib->nLevels ) ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Recursively writes the gate into the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level ) { static char Buff01[ 3], Buff02[ 3]; // Max0 = 1 static char Buff11[ 6], Buff12[ 6]; // Max1 = 2*Max0 + 2 = 4 static char Buff21[ 12], Buff22[ 12]; // Max2 = 2*Max1 + 2 = 10 static char Buff31[ 25], Buff32[ 25]; // Max3 = 2*Max2 + 2 = 22 static char Buff41[ 50], Buff42[ 50]; // Max4 = 2*Max3 + 2 = 46 static char Buff51[100], Buff52[100]; // Max5 = 2*Max4 + 2 = 94 static char * pBuffs1[6] = { Buff01, Buff11, Buff21, Buff31, Buff41, Buff51 }; static char * pBuffs2[6] = { Buff02, Buff12, Buff22, Buff32, Buff42, Buff52 }; char * pBranch; char * pBuffer1 = pBuffs1[Level]; char * pBuffer2 = pBuffs2[Level]; Super2_Gate_t * pGateNext1, * pGateNext2; int fInvNext1, fInvNext2; int RetValue; // consider the last level assert( Level >= 0 ); if ( pGate->pOne == NULL ) { if ( pGate->uTruth == 0 ) { pBuffer1[0] = (fInv? '1': '0'); pBuffer1[1] = '$'; pBuffer1[2] = 0; } else { pBuffer1[0] = (fInv? 'A' + ((int)(ABC_PTRUINT_T)pGate->pTwo): 'a' + ((int)(ABC_PTRUINT_T)pGate->pTwo)); pBuffer1[1] = 0; } return pBuffer1; } assert( Level > 0 ); // get the left branch pGateNext1 = Super2_Regular(pGate->pOne); fInvNext1 = Super2_IsComplement(pGate->pOne); pBranch = Super2_LibWriteGate_rec(pGateNext1, fInvNext1, Level - 1); // copy into Buffer1 strcpy( pBuffer1, pBranch ); // get the right branch pGateNext2 = Super2_Regular(pGate->pTwo); fInvNext2 = Super2_IsComplement(pGate->pTwo); pBranch = Super2_LibWriteGate_rec(pGateNext2, fInvNext2, Level - 1); // consider the case when comparison is not necessary if ( fInvNext1 ^ fInvNext2 ) { if ( fInvNext1 > fInvNext2 ) sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') ); else sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') ); } else { // compare the two branches RetValue = Super2_LibWriteCompare( pBuffer1, pBranch ); if ( RetValue == 1 ) sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') ); else // if ( RetValue == -1 ) { sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') ); if ( RetValue == 0 ) printf( "Strange!\n" ); } } return pBuffer2; } /**Function************************************************************* Synopsis [Compares the two branches of the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Super2_LibWriteCompare( char * pStr1, char * pStr2 ) { while ( 1 ) { // skip extra symbols while ( *pStr1 && *pStr1 < 'A' ) pStr1++; while ( *pStr2 && *pStr2 < 'A' ) pStr2++; // check if any one is finished if ( *pStr1 == 0 || *pStr2 == 0 ) { if ( *pStr2 ) return 1; return -1; } // compare if ( *pStr1 == *pStr2 ) { pStr1++; pStr2++; } else { if ( *pStr1 < *pStr2 ) return 1; return -1; } } return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/superGENERIC.c000066400000000000000000000026461300674244400242560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [super__.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Pre-computation of supergates.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: super__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "superInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/superGate.c000066400000000000000000001612051300674244400240570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [superGate.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Pre-computation of supergates.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: superGate.c,v 1.7 2004/08/03 00:11:40 satrajit Exp $] ***********************************************************************/ #include #include "superInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the bit masks #define SUPER_MASK(n) ((~((unsigned)0)) >> (32-(n))) #define SUPER_FULL (~((unsigned)0)) #define SUPER_NO_VAR (-9999.0) #define SUPER_EPSILON (0.001) // data structure for supergate precomputation typedef struct Super_ManStruct_t_ Super_Man_t; // manager typedef struct Super_GateStruct_t_ Super_Gate_t; // supergate struct Super_ManStruct_t_ { // parameters char * pName; // the original genlib file name int nVarsMax; // the number of inputs int nMints; // the number of minterms int nLevels; // the number of logic levels int nGatesMax; // the number of gates computed float tDelayMax; // the max delay of the supergates in the library float tAreaMax; // the max area of the supergates in the library int fSkipInv; // the flag says about skipping inverters int fWriteOldFormat; // in addition, writes the file in the old format int fVerbose; // supergates Super_Gate_t * pInputs[10]; // the input supergates int nGates; // the number of gates in the library Super_Gate_t ** pGates; // the gates themselves stmm_table * tTable; // mapping of truth tables into gates // memory managers Extra_MmFixed_t * pMem; // memory manager for the supergates Extra_MmFlex_t * pMemFlex; // memory manager for the fanin arrays // statistics int nTried; // the total number of tried int nAdded; // the number of entries added int nRemoved; // the number of entries removed int nClasses; // the number of gate classes int nUnique; // the number of unique gates int nLookups; // the number of hash table lookups int nAliases; // the number of hash table lookups thrown away due to aliasing // runtime abctime Time; // the runtime of the generation procedure int TimeLimit; // the runtime limit (in seconds) int TimeSec; // the time passed (in seconds) abctime TimeStop; // the time to stop computation (in miliseconds) abctime TimePrint; // the time to print message }; struct Super_GateStruct_t_ { Mio_Gate_t * pRoot; // the root gate for this supergate unsigned fVar : 1; // the flag signaling the elementary variable unsigned fSuper : 1; // the flag signaling the elementary variable unsigned nFanins : 6; // the number of fanin gates unsigned Number : 24; // the number assigned in the process unsigned uTruth[2]; // the truth table of this supergate Super_Gate_t * pFanins[6]; // the fanins of the gate float Area; // the area of this gate float ptDelays[6]; // the pin-to-pin delays for all inputs float tDelayMax; // the maximum delay Super_Gate_t * pNext; // the next gate in the table }; // iterating through the gates in the library #define Super_ManForEachGate( GateArray, Limit, Index, Gate ) \ for ( Index = 0; \ Index < Limit && (Gate = GateArray[Index]); \ Index++ ) // static functions static Super_Man_t * Super_ManStart(); static void Super_ManStop( Super_Man_t * pMan ); static void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate ); static void Super_First( Super_Man_t * pMan, int nVarsMax ); static Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, int nGatesMax, int fSkipInv ); static Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins ); static int Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins ); static int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); static int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); static void Super_TranferGatesToArray( Super_Man_t * pMan ); static int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan ); static Vec_Str_t * Super_Write( Super_Man_t * pMan ); static int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); static void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile ); static void Super_WriteLibrary( Super_Man_t * pMan ); static void Super_WriteLibraryTreeFile( Super_Man_t * pMan ); static Vec_Str_t * Super_WriteLibraryTreeStr( Super_Man_t * pMan ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Precomputes the library of supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose, char * pFileName ) { Vec_Str_t * vStr; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } vStr = Super_PrecomputeStr( pLibGen, nVarsMax, nLevels, nGatesMax, tDelayMax, tAreaMax, TimeLimit, fSkipInv, fVerbose ); fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); fclose( pFile ); Vec_StrFree( vStr ); // report the result of writing if ( fVerbose ) { printf( "The supergates are written using new format \"%s\" ", pFileName ); printf( "(%0.3f MB).\n", ((double)Extra_FileSize(pFileName))/(1<<20) ); } } /**Function************************************************************* Synopsis [Precomputes the library of supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Super_PrecomputeStr( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, int nGatesMax, float tDelayMax, float tAreaMax, int TimeLimit, int fSkipInv, int fVerbose ) { Vec_Str_t * vStr; Super_Man_t * pMan; Mio_Gate_t ** ppGates; int nGates, Level; abctime clk, clockStart; assert( nVarsMax < 7 ); if ( nGatesMax && nGatesMax < nVarsMax ) { fprintf( stderr, "Erro! The number of supergates requested (%d) in less than the number of variables (%d).\n", nGatesMax, nVarsMax ); fprintf( stderr, "The library cannot be computed.\n" ); return NULL; } // get the root gates ppGates = Mio_CollectRoots( pLibGen, nVarsMax, tDelayMax, 0, &nGates, fVerbose ); if ( nGatesMax && nGates >= nGatesMax ) { fprintf( stdout, "Warning! Genlib library contains more gates than can be computed.\n"); fprintf( stdout, "Only one-gate supergates are included in the supergate library.\n" ); } // start the manager pMan = Super_ManStart(); pMan->pName = Mio_LibraryReadName(pLibGen); pMan->nGatesMax = nGatesMax; pMan->fSkipInv = fSkipInv; pMan->tDelayMax = tDelayMax; pMan->tAreaMax = tAreaMax; pMan->TimeLimit = TimeLimit; // in seconds pMan->TimeStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; // in CPU ticks pMan->fVerbose = fVerbose; if ( nGates == 0 ) { fprintf( stderr, "Error: No genlib gates satisfy the limits criteria. Stop.\n"); fprintf( stderr, "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n", pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit ); // stop the manager Super_ManStop( pMan ); ABC_FREE( ppGates ); return NULL; } // get the starting supergates Super_First( pMan, nVarsMax ); // perform the computation of supergates clockStart = Abc_Clock(); if ( fVerbose ) { printf( "Computing supergates with %d inputs, %d levels, and %d max gates.\n", pMan->nVarsMax, nLevels, nGatesMax ); printf( "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n", pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit ); } for ( Level = 1; Level <= nLevels; Level++ ) { if ( pMan->TimeStop && Abc_Clock() > pMan->TimeStop ) break; clk = Abc_Clock(); Super_Compute( pMan, ppGates, nGates, nGatesMax, fSkipInv ); pMan->nLevels = Level; if ( fVerbose ) { printf( "Lev %d: Try =%12d. Add =%6d. Rem =%5d. Save =%6d. Lookups =%12d. Aliases =%12d. ", Level, pMan->nTried, pMan->nAdded, pMan->nRemoved, pMan->nAdded - pMan->nRemoved, pMan->nLookups, pMan->nAliases ); ABC_PRT( "Time", Abc_Clock() - clk ); fflush( stdout ); } } pMan->Time = Abc_Clock() - clockStart; if ( fVerbose ) { printf( "Writing the output file...\n" ); fflush( stdout ); } // write them into a file vStr = Super_Write( pMan ); // stop the manager Super_ManStop( pMan ); ABC_FREE( ppGates ); return vStr; } /**Function************************************************************* Synopsis [Derives the starting supergates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_First( Super_Man_t * pMan, int nVarsMax ) { Super_Gate_t * pSuper; int nMintLimit, nVarLimit; int v, m; // set the parameters pMan->nVarsMax = nVarsMax; pMan->nMints = (1 << nVarsMax); pMan->nLevels = 0; // allocate room for the gates pMan->nGates = nVarsMax; pMan->pGates = ABC_ALLOC( Super_Gate_t *, nVarsMax + 2 ); // create the gates corresponding to the elementary variables for ( v = 0; v < nVarsMax; v++ ) { // get a new gate pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); memset( pSuper, 0, sizeof(Super_Gate_t) ); // assign the elementary variable, the truth table, and the delays pSuper->fVar = 1; pSuper->Number = v; for ( m = 0; m < nVarsMax; m++ ) pSuper->ptDelays[m] = SUPER_NO_VAR; pSuper->ptDelays[v] = 0.0; // set the gate pMan->pGates[v] = pSuper; Super_AddGateToTable( pMan, pSuper ); pMan->pInputs[v] = pSuper; } // set up their truth tables nVarLimit = (nVarsMax >= 5)? 5 : nVarsMax; nMintLimit = (1 << nVarLimit); for ( m = 0; m < nMintLimit; m++ ) for ( v = 0; v < nVarLimit; v++ ) if ( m & (1 << v) ) pMan->pGates[v]->uTruth[0] |= (1 << m); // make adjustments for the case of 6 variables if ( nVarsMax == 6 ) { for ( v = 0; v < 5; v++ ) pMan->pGates[v]->uTruth[1] = pMan->pGates[v]->uTruth[0]; pMan->pGates[5]->uTruth[0] = 0; pMan->pGates[5]->uTruth[1] = ~((unsigned)0); } else { for ( v = 0; v < nVarsMax; v++ ) pMan->pGates[v]->uTruth[1] = 0; } } /**Function************************************************************* Synopsis [Precomputes one level of supergates.] Description [This procedure computes the set of supergates that can be derived from the given set of root gates (from genlib library) by composing the root gates with the currently available supergates. This procedure is smart in the sense that it tries to avoid useless emuration by imposing tight bounds by area and delay. Only the supergates and are guaranteed to have smaller area and delay are enumereated. See comments below for details.] SideEffects [] SeeAlso [] ***********************************************************************/ Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, int nGatesMax, int fSkipInv ) { Super_Gate_t * pSupers[6], * pGate0, * pGate1, * pGate2, * pGate3, * pGate4, * pGate5, * pGateNew; float tPinDelaysRes[6], * ptPinDelays[6], tPinDelayMax, tDelayMio; float Area = 0.0; // Suppress "might be used uninitialized" float Area0, Area1, Area2, Area3, Area4, AreaMio; unsigned uTruth[2], uTruths[6][2]; int i0, i1, i2, i3, i4, i5; Super_Gate_t ** ppGatesLimit; int nFanins, nGatesLimit, k, s, t; ProgressBar * pProgress; int fTimeOut; int fPrune = 1; // Shall we prune? int iPruneLimit = 3; // Each of the gates plugged into the root gate will have // less than these many fanins int iPruneLimitRoot = 4; // The root gate may have only less than these many fanins // put the gates from the unique table into the array // the gates from the array will be used to compose other gates // the gates in tbe table are used to check uniqueness of collected gates Super_TranferGatesToArray( pMan ); // sort the gates in the increasing order of maximum delay if ( pMan->nGates > 10000 ) { printf( "Sorting array of %d supergates...\r", pMan->nGates ); fflush( stdout ); } qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), (int (*)(const void *, const void *)) Super_DelayCompare ); assert( Super_DelayCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 ); if ( pMan->nGates > 10000 ) { printf( " \r" ); } pProgress = Extra_ProgressBarStart( stdout, pMan->TimeLimit ); pMan->TimePrint = Abc_Clock() + CLOCKS_PER_SEC; ppGatesLimit = ABC_ALLOC( Super_Gate_t *, pMan->nGates ); // go through the root gates // the root gates are sorted in the increasing gelay fTimeOut = 0; for ( k = 0; k < nGates; k++ ) { if ( fTimeOut ) break; if ( fPrune ) { if ( pMan->nLevels >= 1 ) // First level gates have been computed { if ( Mio_GateReadPinNum(ppGates[k]) >= iPruneLimitRoot ) continue; } } /* if ( strcmp(Mio_GateReadName(ppGates[k]), "MUX2IX0") == 0 ) { int s = 0; } */ // select the subset of gates to be considered with this root gate // all the gates past this point will lead to delay larger than the limit tDelayMio = (float)Mio_GateReadDelayMax(ppGates[k]); for ( s = 0, t = 0; s < pMan->nGates; s++ ) { if ( fPrune && ( pMan->nLevels >= 1 ) && ( ((int)pMan->pGates[s]->nFanins) >= iPruneLimit )) continue; ppGatesLimit[t] = pMan->pGates[s]; if ( ppGatesLimit[t++]->tDelayMax + tDelayMio > pMan->tDelayMax && pMan->tDelayMax > 0.0 ) break; } nGatesLimit = t; if ( pMan->fVerbose ) { printf ("Trying %d choices for %d inputs\r", t, Mio_GateReadPinNum(ppGates[k]) ); } // resort part of this range by area // now we can prune the search by going up in the list until we reach the limit on area // all the gates beyond this point can be skipped because their area can be only larger if ( nGatesLimit > 10000 ) printf( "Sorting array of %d supergates...\r", nGatesLimit ); qsort( (void *)ppGatesLimit, nGatesLimit, sizeof(Super_Gate_t *), (int (*)(const void *, const void *)) Super_AreaCompare ); assert( Super_AreaCompare( ppGatesLimit, ppGatesLimit + nGatesLimit - 1 ) <= 0 ); if ( nGatesLimit > 10000 ) printf( " \r" ); // consider the combinations of gates with the root gate on top AreaMio = (float)Mio_GateReadArea(ppGates[k]); nFanins = Mio_GateReadPinNum(ppGates[k]); switch ( nFanins ) { case 0: // should not happen assert( 0 ); break; case 1: // interter root Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) { if ( fTimeOut ) break; fTimeOut = Super_CheckTimeout( pProgress, pMan ); // skip the inverter as the root gate before the elementary variable // as a result, the supergates will not have inverters on the input side // but inverters still may occur at the output of or inside complex supergates if ( fSkipInv && pGate0->tDelayMax == 0 ) continue; // compute area Area = AreaMio + pGate0->Area; if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) break; pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) continue; // create a new gate pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); Super_AddGateToTable( pMan, pGateNew ); if ( nGatesMax && pMan->nClasses > nGatesMax ) goto done; } break; case 2: // two-input root gate Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) { Area0 = AreaMio + pGate0->Area; if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) break; pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) if ( i1 != i0 ) { if ( fTimeOut ) goto done; fTimeOut = Super_CheckTimeout( pProgress, pMan ); // compute area Area = Area0 + pGate1->Area; if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) break; pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) continue; // create a new gate pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); Super_AddGateToTable( pMan, pGateNew ); if ( nGatesMax && pMan->nClasses > nGatesMax ) goto done; } } break; case 3: // three-input root gate Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) { Area0 = AreaMio + pGate0->Area; if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) break; pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) if ( i1 != i0 ) { Area1 = Area0 + pGate1->Area; if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax ) break; pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) if ( i2 != i0 && i2 != i1 ) { if ( fTimeOut ) goto done; fTimeOut = Super_CheckTimeout( pProgress, pMan ); // compute area Area = Area1 + pGate2->Area; if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) break; pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) continue; // create a new gate pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); Super_AddGateToTable( pMan, pGateNew ); if ( nGatesMax && pMan->nClasses > nGatesMax ) goto done; } } } break; case 4: // four-input root gate Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) { Area0 = AreaMio + pGate0->Area; if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) break; pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) if ( i1 != i0 ) { Area1 = Area0 + pGate1->Area; if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax ) break; pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) if ( i2 != i0 && i2 != i1 ) { Area2 = Area1 + pGate2->Area; if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax ) break; pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) if ( i3 != i0 && i3 != i1 && i3 != i2 ) { if ( fTimeOut ) goto done; fTimeOut = Super_CheckTimeout( pProgress, pMan ); // compute area Area = Area2 + pGate3->Area; if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) break; pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) continue; // create a new gate pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); Super_AddGateToTable( pMan, pGateNew ); if ( nGatesMax && pMan->nClasses > nGatesMax ) goto done; } } } } break; case 5: // five-input root gate Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) { Area0 = AreaMio + pGate0->Area; if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) break; pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) if ( i1 != i0 ) { Area1 = Area0 + pGate1->Area; if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax ) break; pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) if ( i2 != i0 && i2 != i1 ) { Area2 = Area1 + pGate2->Area; if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax ) break; pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) if ( i3 != i0 && i3 != i1 && i3 != i2 ) { Area3 = Area2 + pGate3->Area; if ( pMan->tAreaMax > 0.0 && Area3 > pMan->tAreaMax ) break; pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 ) if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 ) { if ( fTimeOut ) goto done; fTimeOut = Super_CheckTimeout( pProgress, pMan ); // compute area Area = Area3 + pGate4->Area; if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) break; pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays; Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) continue; // create a new gate pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); Super_AddGateToTable( pMan, pGateNew ); if ( nGatesMax && pMan->nClasses > nGatesMax ) goto done; } } } } } break; case 6: // six-input root gate Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) { Area0 = AreaMio + pGate0->Area; if ( pMan->tAreaMax > 0.0 && Area0 > pMan->tAreaMax ) break; pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) if ( i1 != i0 ) { Area1 = Area0 + pGate1->Area; if ( pMan->tAreaMax > 0.0 && Area1 > pMan->tAreaMax ) break; pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) if ( i2 != i0 && i2 != i1 ) { Area2 = Area1 + pGate2->Area; if ( pMan->tAreaMax > 0.0 && Area2 > pMan->tAreaMax ) break; pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) if ( i3 != i0 && i3 != i1 && i3 != i2 ) { Area3 = Area2 + pGate3->Area; if ( pMan->tAreaMax > 0.0 && Area3 > pMan->tAreaMax ) break; pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 ) if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 ) { if ( fTimeOut ) break; fTimeOut = Super_CheckTimeout( pProgress, pMan ); // compute area Area4 = Area3 + pGate4->Area; if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) break; pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays; Super_ManForEachGate( ppGatesLimit, nGatesLimit, i5, pGate5 ) if ( i5 != i0 && i5 != i1 && i5 != i2 && i5 != i3 && i5 != i4 ) { if ( fTimeOut ) goto done; fTimeOut = Super_CheckTimeout( pProgress, pMan ); // compute area Area = Area4 + pGate5->Area; if ( pMan->tAreaMax > 0.0 && Area > pMan->tAreaMax ) break; pSupers[5] = pGate5; uTruths[5][0] = pGate5->uTruth[0]; uTruths[5][1] = pGate5->uTruth[1]; ptPinDelays[5] = pGate5->ptDelays; Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) continue; // create a new gate pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); Super_AddGateToTable( pMan, pGateNew ); if ( nGatesMax && pMan->nClasses > nGatesMax ) goto done; } } } } } } break; default : assert( 0 ); break; } } done: Extra_ProgressBarStop( pProgress ); ABC_FREE( ppGatesLimit ); return pMan; } /**Function************************************************************* Synopsis [Transfers gates from table into the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan ) { abctime TimeNow = Abc_Clock(); if ( TimeNow > pMan->TimePrint ) { Extra_ProgressBarUpdate( pPro, ++pMan->TimeSec, NULL ); pMan->TimePrint = Abc_Clock() + CLOCKS_PER_SEC; } if ( pMan->TimeStop && TimeNow > pMan->TimeStop ) { printf ("Timeout!\n"); return 1; } pMan->nTried++; return 0; } /**Function************************************************************* Synopsis [Transfers gates from table into the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_TranferGatesToArray( Super_Man_t * pMan ) { stmm_generator * gen; Super_Gate_t * pGate, * pList; ABC_PTRUINT_T Key; // put the gates fron the table into the array ABC_FREE( pMan->pGates ); pMan->pGates = ABC_ALLOC( Super_Gate_t *, pMan->nAdded ); pMan->nGates = 0; stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pList ) { for ( pGate = pList; pGate; pGate = pGate->pNext ) pMan->pGates[ pMan->nGates++ ] = pGate; } // assert( pMan->nGates == pMan->nAdded - pMan->nRemoved ); } /**Function************************************************************* Synopsis [Adds one supergate into the unique table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate ) { Super_Gate_t ** ppList; ABC_PTRUINT_T Key; // Key = pGate->uTruth[0] + 2003 * pGate->uTruth[1]; Key = pGate->uTruth[0] ^ pGate->uTruth[1]; if ( !stmm_find_or_add( pMan->tTable, (char *)Key, (char ***)&ppList ) ) { *ppList = NULL; pMan->nClasses++; } pGate->pNext = *ppList; *ppList = pGate; pMan->nAdded++; } /**Function************************************************************* Synopsis [Check the manager's unique table for comparable gates.] Description [Returns 0 if the gate is dominated by others. Returns 1 if the gate is new or is better than the available ones. In this case, cleans the table by removing the gates that are worse than the given one.] SideEffects [] SeeAlso [] ***********************************************************************/ int Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins ) { Super_Gate_t ** ppList, * pPrev, * pGate, * pGate2; int i, fNewIsBetter, fGateIsBetter; ABC_PTRUINT_T Key; // skip constant functions if ( pMan->nVarsMax < 6 ) { if ( uTruth[0] == 0 || ~uTruth[0] == 0 ) return 0; } else { if ( ( uTruth[0] == 0 && uTruth[1] == 0 ) || ( ~uTruth[0] == 0 && ~uTruth[1] == 0 ) ) return 0; } // get hold of the place where the entry is stored // Key = uTruth[0] + 2003 * uTruth[1]; Key = uTruth[0] ^ uTruth[1]; if ( !stmm_find( pMan->tTable, (char *)Key, (char ***)&ppList ) ) return 1; // the entry with this truth table is found pPrev = NULL; for ( pGate = *ppList, pGate2 = pGate? pGate->pNext: NULL; pGate; pGate = pGate2, pGate2 = pGate? pGate->pNext: NULL ) { pMan->nLookups++; if ( pGate->uTruth[0] != uTruth[0] || pGate->uTruth[1] != uTruth[1] ) { pMan->nAliases++; continue; } fGateIsBetter = 0; fNewIsBetter = 0; if ( pGate->Area + SUPER_EPSILON < Area ) fGateIsBetter = 1; else if ( pGate->Area > Area + SUPER_EPSILON ) fNewIsBetter = 1; for ( i = 0; i < nPins; i++ ) { if ( pGate->ptDelays[i] == SUPER_NO_VAR || tPinDelaysRes[i] == SUPER_NO_VAR ) continue; if ( pGate->ptDelays[i] + SUPER_EPSILON < tPinDelaysRes[i] ) fGateIsBetter = 1; else if ( pGate->ptDelays[i] > tPinDelaysRes[i] + SUPER_EPSILON ) fNewIsBetter = 1; if ( fGateIsBetter && fNewIsBetter ) break; } // consider 4 cases if ( fGateIsBetter && fNewIsBetter ) // Pareto points; save both pPrev = pGate; else if ( fNewIsBetter ) // gate is worse; remove the gate { if ( pPrev == NULL ) *ppList = pGate->pNext; else pPrev->pNext = pGate->pNext; Extra_MmFixedEntryRecycle( pMan->pMem, (char *)pGate ); pMan->nRemoved++; } else if ( fGateIsBetter ) // new is worse, already dominated no need to see others return 0; else // if ( !fGateIsBetter && !fNewIsBetter ) // they are identical, no need to see others return 0; } return 1; } /**Function************************************************************* Synopsis [Create a new supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins ) { Super_Gate_t * pSuper; pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); memset( pSuper, 0, sizeof(Super_Gate_t) ); pSuper->pRoot = pRoot; pSuper->uTruth[0] = uTruth[0]; pSuper->uTruth[1] = uTruth[1]; memcpy( pSuper->ptDelays, tPinDelaysRes, sizeof(float) * nPins ); pSuper->Area = Area; pSuper->nFanins = nSupers; memcpy( pSuper->pFanins, pSupers, sizeof(Super_Gate_t *) * nSupers ); pSuper->pNext = NULL; pSuper->tDelayMax = tDelayMax; return pSuper; } /**Function************************************************************* Synopsis [Starts the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Super_Man_t * Super_ManStart() { Super_Man_t * pMan; pMan = ABC_CALLOC( Super_Man_t, 1 ); pMan->pMem = Extra_MmFixedStart( sizeof(Super_Gate_t) ); pMan->tTable = stmm_init_table( st__ptrcmp, st__ptrhash ); return pMan; } /**Function************************************************************* Synopsis [Stops the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_ManStop( Super_Man_t * pMan ) { Extra_MmFixedStop( pMan->pMem ); if ( pMan->tTable ) stmm_free_table( pMan->tTable ); ABC_FREE( pMan->pGates ); ABC_FREE( pMan ); } /**Function************************************************************* Synopsis [Writes the supergate library into the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Super_Write( Super_Man_t * pMan ) { Vec_Str_t * vStr; Super_Gate_t * pGateRoot, * pGate; stmm_generator * gen; int fZeroFound, v; abctime clk; ABC_PTRUINT_T Key; if ( pMan->nGates < 1 ) { printf( "The generated library is empty. No output file written.\n" ); return NULL; } // Filters the supergates by removing those that have fewer inputs than // the given limit, provided that the inputs are not consequtive. // For example, NAND2(a,c) is removed, but NAND2(a,b) is left, // because a and b are consequtive. ABC_FREE( pMan->pGates ); pMan->pGates = ABC_ALLOC( Super_Gate_t *, pMan->nAdded ); pMan->nGates = 0; stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pGateRoot ) { for ( pGate = pGateRoot; pGate; pGate = pGate->pNext ) { // skip the elementary variables if ( pGate->pRoot == NULL ) continue; // skip the non-consequtive gates fZeroFound = 0; for ( v = 0; v < pMan->nVarsMax; v++ ) if ( pGate->ptDelays[v] < SUPER_NO_VAR + SUPER_EPSILON ) fZeroFound = 1; else if ( fZeroFound ) break; if ( v < pMan->nVarsMax ) continue; // save the unique gate pMan->pGates[ pMan->nGates++ ] = pGate; } } clk = Abc_Clock(); // sort the supergates by truth table qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), (int (*)(const void *, const void *)) Super_WriteCompare ); assert( Super_WriteCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 ); if ( pMan->fVerbose ) { ABC_PRT( "Sorting", Abc_Clock() - clk ); } // write library in the old format clk = Abc_Clock(); if ( pMan->fWriteOldFormat ) Super_WriteLibrary( pMan ); if ( pMan->fVerbose ) { ABC_PRT( "Writing old format", Abc_Clock() - clk ); } // write the tree-like structure of supergates clk = Abc_Clock(); vStr = Super_WriteLibraryTreeStr( pMan ); if ( pMan->fVerbose ) { ABC_PRT( "Writing new format", Abc_Clock() - clk ); } return vStr; } /**Function************************************************************* Synopsis [Writes the file header.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile ) { fprintf( pFile, "#\n" ); fprintf( pFile, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() ); fprintf( pFile, "#\n" ); fprintf( pFile, "# Command line: \"super -I %d -L %d -N %d -T %d -D %.2f -A %.2f %s %s\".\n", pMan->nVarsMax, pMan->nLevels, pMan->nGatesMax, pMan->TimeLimit, pMan->tDelayMax, pMan->tAreaMax, (pMan->fSkipInv? "" : "-s"), pMan->pName ); fprintf( pFile, "#\n" ); fprintf( pFile, "# The number of inputs = %10d.\n", pMan->nVarsMax ); fprintf( pFile, "# The number of levels = %10d.\n", pMan->nLevels ); fprintf( pFile, "# The maximum delay = %10.2f.\n", pMan->tDelayMax ); fprintf( pFile, "# The maximum area = %10.2f.\n", pMan->tAreaMax ); fprintf( pFile, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit ); fprintf( pFile, "#\n" ); fprintf( pFile, "# The number of attempts = %10d.\n", pMan->nTried ); fprintf( pFile, "# The number of supergates = %10d.\n", pMan->nGates ); fprintf( pFile, "# The number of functions = %10d.\n", pMan->nUnique ); fprintf( pFile, "# The total functions = %.0f (2^%d).\n", pow((double)2,pMan->nMints), pMan->nMints ); fprintf( pFile, "#\n" ); fprintf( pFile, "# Generation time = %10.2f sec.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) ); fprintf( pFile, "#\n" ); fprintf( pFile, "%s\n", pMan->pName ); fprintf( pFile, "%d\n", pMan->nVarsMax ); fprintf( pFile, "%d\n", pMan->nGates ); } void Super_WriteFileHeaderStr( Super_Man_t * pMan, Vec_Str_t * vStr ) { char pBuffer[1000]; sprintf( pBuffer, "#\n" ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "#\n" ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# Command line: \"super -I %d -L %d -N %d -T %d -D %.2f -A %.2f %s %s\".\n", pMan->nVarsMax, pMan->nLevels, pMan->nGatesMax, pMan->TimeLimit, pMan->tDelayMax, pMan->tAreaMax, (pMan->fSkipInv? "" : "-s"), pMan->pName ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "#\n" ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The number of inputs = %10d.\n", pMan->nVarsMax ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The number of levels = %10d.\n", pMan->nLevels ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The maximum delay = %10.2f.\n", pMan->tDelayMax ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The maximum area = %10.2f.\n", pMan->tAreaMax ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "#\n" ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The number of attempts = %10d.\n", pMan->nTried ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The number of supergates = %10d.\n", pMan->nGates ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The number of functions = %10d.\n", pMan->nUnique ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# The total functions = %.0f (2^%d).\n", pow((double)2,pMan->nMints), pMan->nMints ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "#\n" ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "# Generation time = %10.2f sec.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "#\n" ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "%s\n", pMan->pName ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "%d\n", pMan->nVarsMax ); Vec_StrPrintStr( vStr, pBuffer ); sprintf( pBuffer, "%d\n", pMan->nGates ); Vec_StrPrintStr( vStr, pBuffer ); } /**Function************************************************************* Synopsis [Compares two gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) { unsigned * pTruth1 = (*ppG1)->uTruth; unsigned * pTruth2 = (*ppG2)->uTruth; if ( pTruth1[1] < pTruth2[1] ) return -1; if ( pTruth1[1] > pTruth2[1] ) return 1; if ( pTruth1[0] < pTruth2[0] ) return -1; if ( pTruth1[0] > pTruth2[0] ) return 1; return 0; } int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) { if ( (*ppG1)->tDelayMax < (*ppG2)->tDelayMax ) return -1; if ( (*ppG1)->tDelayMax > (*ppG2)->tDelayMax ) return 1; return 0; } int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) { if ( (*ppG1)->Area < (*ppG2)->Area ) return -1; if ( (*ppG1)->Area > (*ppG2)->Area ) return 1; return 0; } /**Function************************************************************* Synopsis [Writes the gates into the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer ) { char Buffer[10]; int i; if ( pGate->pRoot == NULL ) { sprintf( Buffer, "%c", 'a' + pGate->Number ); strcat( pBuffer, Buffer ); return; } strcat( pBuffer, Mio_GateReadName(pGate->pRoot) ); strcat( pBuffer, "(" ); for ( i = 0; i < (int)pGate->nFanins; i++ ) { if ( i ) strcat( pBuffer, "," ); Super_WriteLibraryGateName_rec( pGate->pFanins[i], pBuffer ); } strcat( pBuffer, ")" ); } char * Super_WriteLibraryGateName( Super_Gate_t * pGate ) { static char Buffer[2000]; Buffer[0] = 0; Super_WriteLibraryGateName_rec( pGate, Buffer ); return Buffer; } void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num ) { int i; fprintf( pFile, "%04d ", Num ); // the number Extra_PrintBinary( pFile, pGate->uTruth, pMan->nMints ); // the truth table fprintf( pFile, " %5.2f", pGate->tDelayMax ); // the max delay fprintf( pFile, " " ); for ( i = 0; i < pMan->nVarsMax; i++ ) // the pin-to-pin delays fprintf( pFile, " %5.2f", pGate->ptDelays[i]==SUPER_NO_VAR? 0.0 : pGate->ptDelays[i] ); fprintf( pFile, " %5.2f", pGate->Area ); // the area fprintf( pFile, " " ); fprintf( pFile, "%s", Super_WriteLibraryGateName(pGate) ); // the symbolic expression fprintf( pFile, "\n" ); } void Super_WriteLibrary( Super_Man_t * pMan ) { Super_Gate_t * pGate, * pGateNext; FILE * pFile; char * FileName; char * pNameGeneric; int i, Counter; FileName = ABC_ALLOC( char, 10000 ); // get the file name pNameGeneric = Extra_FileNameGeneric( pMan->pName ); sprintf( FileName, "%s.super_old", pNameGeneric ); ABC_FREE( pNameGeneric ); // count the number of unique functions pMan->nUnique = 1; Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate ) { if ( i == pMan->nGates - 1 ) break; // print the newline if this gate is different from the following one pGateNext = pMan->pGates[i+1]; if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] ) pMan->nUnique++; } // start the file pFile = fopen( FileName, "w" ); Super_WriteFileHeader( pMan, pFile ); // print the gates Counter = 0; Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate ) { Super_WriteLibraryGate( pFile, pMan, pGate, ++Counter ); if ( i == pMan->nGates - 1 ) break; // print the newline if this gate is different from the following one pGateNext = pMan->pGates[i+1]; if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] ) fprintf( pFile, "\n" ); } assert( Counter == pMan->nGates ); fclose( pFile ); if ( pMan->fVerbose ) { printf( "The supergates are written using old format \"%s\" ", FileName ); printf( "(%0.3f MB).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); } ABC_FREE( FileName ); } /**Function************************************************************* Synopsis [Recursively writes the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_WriteLibraryTreeFile_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter ) { int nFanins, i; // skip an elementary variable and a gate that was already written if ( pSuper->fVar || pSuper->Number > 0 ) return; // write the fanins nFanins = Mio_GateReadPinNum(pSuper->pRoot); for ( i = 0; i < nFanins; i++ ) Super_WriteLibraryTreeFile_rec( pFile, pMan, pSuper->pFanins[i], pCounter ); // finally write the gate pSuper->Number = (*pCounter)++; fprintf( pFile, "%s", pSuper->fSuper? "* " : "" ); fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) ); for ( i = 0; i < nFanins; i++ ) fprintf( pFile, " %d", pSuper->pFanins[i]->Number ); // write the formula // this step is optional, the resulting library will work in any case // however, it may be helpful to for debugging to compare the same library // written in the old format and written in the new format with formulas // fprintf( pFile, " # %s", Super_WriteLibraryGateName( pSuper ) ); fprintf( pFile, "\n" ); } void Super_WriteLibraryTreeFile( Super_Man_t * pMan ) { Super_Gate_t * pSuper; FILE * pFile; char * FileName; char * pNameGeneric; int i, Counter; int posStart; FileName = ABC_ALLOC( char, 10000 ); // get the file name pNameGeneric = Extra_FileNameGeneric( pMan->pName ); sprintf( FileName, "%s.super", pNameGeneric ); ABC_FREE( pNameGeneric ); // write the elementary variables pFile = fopen( FileName, "wb" ); Super_WriteFileHeader( pMan, pFile ); // write the place holder for the number of lines posStart = ftell( pFile ); fprintf( pFile, " \n" ); // mark the real supergates Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) pSuper->fSuper = 1; // write the supergates Counter = pMan->nVarsMax; Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) Super_WriteLibraryTreeFile_rec( pFile, pMan, pSuper, &Counter ); fclose( pFile ); // write the number of lines pFile = fopen( FileName, "rb+" ); fseek( pFile, posStart, SEEK_SET ); fprintf( pFile, "%d", Counter ); fclose( pFile ); if ( pMan->fVerbose ) { printf( "The supergates are written using new format \"%s\" ", FileName ); printf( "(%0.3f MB).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); } ABC_FREE( FileName ); } /**Function************************************************************* Synopsis [Recursively writes the gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Super_WriteLibraryTreeStr_rec( Vec_Str_t * vStr, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter ) { int nFanins, i; // skip an elementary variable and a gate that was already written if ( pSuper->fVar || pSuper->Number > 0 ) return; // write the fanins nFanins = Mio_GateReadPinNum(pSuper->pRoot); for ( i = 0; i < nFanins; i++ ) Super_WriteLibraryTreeStr_rec( vStr, pMan, pSuper->pFanins[i], pCounter ); // finally write the gate pSuper->Number = (*pCounter)++; // fprintf( pFile, "%s", pSuper->fSuper? "* " : "" ); // fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) ); // for ( i = 0; i < nFanins; i++ ) // fprintf( pFile, " %d", pSuper->pFanins[i]->Number ); Vec_StrPrintStr( vStr, pSuper->fSuper? "* " : "" ); Vec_StrPrintStr( vStr, Mio_GateReadName(pSuper->pRoot) ); for ( i = 0; i < nFanins; i++ ) { Vec_StrPrintStr( vStr, " " ); Vec_StrPrintNum( vStr, pSuper->pFanins[i]->Number ); } // write the formula // this step is optional, the resulting library will work in any case // however, it may be helpful to for debugging to compare the same library // written in the old format and written in the new format with formulas // fprintf( pFile, " # %s", Super_WriteLibraryGateName( pSuper ) ); // fprintf( pFile, "\n" ); Vec_StrPrintStr( vStr, "\n" ); } Vec_Str_t * Super_WriteLibraryTreeStr( Super_Man_t * pMan ) { char pInsert[16]; Vec_Str_t * vStr; Super_Gate_t * pSuper; int i, Counter; int posStart; // write the elementary variables vStr = Vec_StrAlloc( 1000 ); Super_WriteFileHeaderStr( pMan, vStr ); // write the place holder for the number of lines posStart = Vec_StrSize( vStr ); for ( i = 0; i < 9; i++ ) Vec_StrPush( vStr, ' ' ); Vec_StrPush( vStr, '\n' ); // mark the real supergates Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) pSuper->fSuper = 1; // write the supergates Counter = pMan->nVarsMax; Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) Super_WriteLibraryTreeStr_rec( vStr, pMan, pSuper, &Counter ); Vec_StrPush( vStr, 0 ); // write the number of lines sprintf( pInsert, "%d", Counter ); for ( i = 0; i < (int)strlen(pInsert); i++ ) Vec_StrWriteEntry( vStr, posStart + i, pInsert[i] ); return vStr; } void Super_WriteLibraryTree( Super_Man_t * pMan ) { Vec_Str_t * vStr; char * pFileName = Extra_FileNameGenericAppend( pMan->pName, ".super" ); FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } vStr = Super_WriteLibraryTreeStr( pMan ); fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); fclose( pFile ); Vec_StrFree( vStr ); // report the result of writing if ( pMan->fVerbose ) { printf( "The supergates are written using new format \"%s\" ", pFileName ); printf( "(%0.3f MB).\n", ((double)Extra_FileSize(pFileName))/(1<<20) ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/superInt.h000066400000000000000000000044041300674244400237330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [superInt.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Pre-computation of supergates.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: superInt.h,v 1.4 2004/07/06 04:55:59 alanmi Exp $] ***********************************************************************/ #ifndef ABC__map__super__superInt_h #define ABC__map__super__superInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" #include "base/main/mainInt.h" #include "misc/mvc/mvc.h" #include "map/mio/mio.h" #include "misc/st/stmm.h" #include "super.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/map/super/superWrite.c000066400000000000000000000055451300674244400242750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [superWrite.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Pre-computation of supergates.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: superWrite.c,v 1.1 2004/04/03 01:36:45 alanmi Exp $] ***********************************************************************/ #include "superInt.h" ABC_NAMESPACE_IMPL_START /* One record in the supergate library file consists of: is a zero-based integer is a string of 2^n bits representing the value of the function for each minterm is the maximum delay of the gate is the array of n double values is a floating point value is the string representing the gate in the following format: GATENAME1( GATENAME2( a, c ), GATENAME3( a, d ), ... ) The gate names (GATENAME1, etc) are the names as they appear in the .genlib library. The primary inputs of the gates are denoted by lowercase chars 'a', 'b', etc. The parentheses are mandatory for each gate, except for the wire. The wire name can be omitted, so that "a" can be used instead of "**wire**( a )". The spaces are optional in any position of this string. The supergates are generated exhaustively from all gate combinations that have the max delay lower than the delay given by the user, or until the specified time limit is reached. The supergates are stored in supergate classes by their functionality. Among the gates with the equivalent functionaly only those are dropped, which are dominated by at least one other gate in the class in terms of both delay and area. For the definition of gate dominance see pliGenCheckDominance(). */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/000077500000000000000000000000001300674244400207675ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/avl/000077500000000000000000000000001300674244400215515ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/avl/avl.c000066400000000000000000000266621300674244400225130ustar00rootroot00000000000000/* * Revision Control Information * * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.c,v $ * $Author: sis $ * $Revision: 1.3 $ * $Date: 1994/07/15 23:00:40 $ * */ /* LINTLIBRARY */ #include #include #include "avl.h" ABC_NAMESPACE_IMPL_START #define HEIGHT(node) (node == NIL(avl_node) ? -1 : (node)->height) #define BALANCE(node) (HEIGHT((node)->right) - HEIGHT((node)->left)) #define compute_height(node) { \ int x=HEIGHT(node->left), y=HEIGHT(node->right); \ (node)->height = MAX(x,y) + 1; \ } #define COMPARE(key, nodekey, compare) \ ((compare == avl_numcmp) ? \ (int) key - (int) nodekey : \ (*compare)(key, nodekey)) #define STACK_SIZE 50 static avl_node *new_node (); static avl_node *find_rightmost (); static void do_rebalance (); static rotate_left (); static rotate_right (); static int do_check_tree (); avl_tree * avl_init_table (compar) int (*compar) (); { avl_tree *tree; tree = ALLOC (avl_tree, 1); tree->root = NIL (avl_node); tree->compar = compar; tree->num_entries = 0; return tree; } avl_lookup (tree, key, value_p) avl_tree *tree; register char *key; char **value_p; { register avl_node *node; register int (*compare) () = tree->compar, diff; node = tree->root; while (node != NIL (avl_node)) { diff = COMPARE (key, node->key, compare); if (diff == 0) { /* got a match */ if (value_p != NIL (char *)) *value_p = node->value; return 1; } node = (diff < 0) ? node->left : node->right; } return 0; } avl_first (tree, key_p, value_p) avl_tree *tree; char **key_p; char **value_p; { register avl_node *node; if (tree->root == 0) { return 0; /* no entries */ } else { /* walk down the tree; stop at leftmost leaf */ for (node = tree->root; node->left != 0; node = node->left) { } if (key_p != NIL (char *)) *key_p = node->key; if (value_p != NIL (char *)) *value_p = node->value; return 1; } } avl_last (tree, key_p, value_p) avl_tree *tree; char **key_p; char **value_p; { register avl_node *node; if (tree->root == 0) { return 0; /* no entries */ } else { /* walk down the tree; stop at rightmost leaf */ for (node = tree->root; node->right != 0; node = node->right) { } if (key_p != NIL (char *)) *key_p = node->key; if (value_p != NIL (char *)) *value_p = node->value; return 1; } } avl_insert (tree, key, value) avl_tree *tree; char *key; char *value; { register avl_node **node_p, *node; register int stack_n = 0; register int (*compare) () = tree->compar; avl_node **stack_nodep[STACK_SIZE]; int diff, status; node_p = &tree->root; /* walk down the tree (saving the path); stop at insertion point */ status = 0; while ((node = *node_p) != NIL (avl_node)) { stack_nodep[stack_n++] = node_p; diff = COMPARE (key, node->key, compare); if (diff == 0) status = 1; node_p = (diff < 0) ? &node->left : &node->right; } /* insert the item and re-balance the tree */ *node_p = new_node (key, value); do_rebalance (stack_nodep, stack_n); tree->num_entries++; tree->modified = 1; return status; } avl_find_or_add (tree, key, slot_p) avl_tree *tree; char *key; char ***slot_p; { register avl_node **node_p, *node; register int stack_n = 0; register int (*compare) () = tree->compar; avl_node **stack_nodep[STACK_SIZE]; int diff; node_p = &tree->root; /* walk down the tree (saving the path); stop at insertion point */ while ((node = *node_p) != NIL (avl_node)) { stack_nodep[stack_n++] = node_p; diff = COMPARE (key, node->key, compare); if (diff == 0) { if (slot_p != 0) *slot_p = &node->value; return 1; /* found */ } node_p = (diff < 0) ? &node->left : &node->right; } /* insert the item and re-balance the tree */ *node_p = new_node (key, NIL (char)); if (slot_p != 0) *slot_p = &(*node_p)->value; do_rebalance (stack_nodep, stack_n); tree->num_entries++; tree->modified = 1; return 0; /* not already in tree */ } avl_delete (tree, key_p, value_p) avl_tree *tree; char **key_p; char **value_p; { register avl_node **node_p, *node, *rightmost; register int stack_n = 0; char *key = *key_p; int (*compare) () = tree->compar, diff; avl_node **stack_nodep[STACK_SIZE]; node_p = &tree->root; /* Walk down the tree saving the path; return if not found */ while ((node = *node_p) != NIL (avl_node)) { diff = COMPARE (key, node->key, compare); if (diff == 0) goto delete_item; stack_nodep[stack_n++] = node_p; node_p = (diff < 0) ? &node->left : &node->right; } return 0; /* not found */ /* prepare to delete node and replace it with rightmost of left tree */ delete_item: *key_p = node->key; if (value_p != 0) *value_p = node->value; if (node->left == NIL (avl_node)) { *node_p = node->right; } else { rightmost = find_rightmost (&node->left); rightmost->left = node->left; rightmost->right = node->right; rightmost->height = -2; /* mark bogus height for do_rebal */ *node_p = rightmost; stack_nodep[stack_n++] = node_p; } FREE (node); /* work our way back up, re-balancing the tree */ do_rebalance (stack_nodep, stack_n); tree->num_entries--; tree->modified = 1; return 1; } static void avl_record_gen_forward (node, gen) avl_node *node; avl_generator *gen; { if (node != NIL (avl_node)) { avl_record_gen_forward (node->left, gen); gen->nodelist[gen->count++] = node; avl_record_gen_forward (node->right, gen); } } static void avl_record_gen_backward (node, gen) avl_node *node; avl_generator *gen; { if (node != NIL (avl_node)) { avl_record_gen_backward (node->right, gen); gen->nodelist[gen->count++] = node; avl_record_gen_backward (node->left, gen); } } avl_generator * avl_init_gen (tree, dir) avl_tree *tree; int dir; { avl_generator *gen; /* what a hack */ gen = ALLOC (avl_generator, 1); gen->tree = tree; gen->nodelist = ALLOC (avl_node *, avl_count (tree)); gen->count = 0; if (dir == AVL_FORWARD) { avl_record_gen_forward (tree->root, gen); } else { avl_record_gen_backward (tree->root, gen); } gen->count = 0; /* catch any attempt to modify the tree while we generate */ tree->modified = 0; return gen; } avl_gen (gen, key_p, value_p) avl_generator *gen; char **key_p; char **value_p; { avl_node *node; if (gen->count == gen->tree->num_entries) { return 0; } else { node = gen->nodelist[gen->count++]; if (key_p != NIL (char *)) *key_p = node->key; if (value_p != NIL (char *)) *value_p = node->value; return 1; } } void avl_free_gen (gen) avl_generator *gen; { FREE (gen->nodelist); FREE (gen); } static avl_node * find_rightmost (node_p) register avl_node **node_p; { register avl_node *node; register int stack_n = 0; avl_node **stack_nodep[STACK_SIZE]; node = *node_p; while (node->right != NIL (avl_node)) { stack_nodep[stack_n++] = node_p; node_p = &node->right; node = *node_p; } *node_p = node->left; do_rebalance (stack_nodep, stack_n); return node; } static void do_rebalance (stack_nodep, stack_n) register avl_node ***stack_nodep; register int stack_n; { register avl_node **node_p, *node; register int hl, hr; int height; /* work our way back up, re-balancing the tree */ while (--stack_n >= 0) { node_p = stack_nodep[stack_n]; node = *node_p; hl = HEIGHT (node->left); /* watch for NIL */ hr = HEIGHT (node->right); /* watch for NIL */ if ((hr - hl) < -1) { rotate_right (node_p); } else if ((hr - hl) > 1) { rotate_left (node_p); } else { height = MAX (hl, hr) + 1; if (height == node->height) break; node->height = height; } } } static rotate_left (node_p) register avl_node **node_p; { register avl_node *old_root = *node_p, *new_root, *new_right; if (BALANCE (old_root->right) >= 0) { *node_p = new_root = old_root->right; old_root->right = new_root->left; new_root->left = old_root; } else { new_right = old_root->right; *node_p = new_root = new_right->left; old_root->right = new_root->left; new_right->left = new_root->right; new_root->right = new_right; new_root->left = old_root; compute_height (new_right); } compute_height (old_root); compute_height (new_root); } static rotate_right (node_p) avl_node **node_p; { register avl_node *old_root = *node_p, *new_root, *new_left; if (BALANCE (old_root->left) <= 0) { *node_p = new_root = old_root->left; old_root->left = new_root->right; new_root->right = old_root; } else { new_left = old_root->left; *node_p = new_root = new_left->right; old_root->left = new_root->right; new_left->right = new_root->left; new_root->left = new_left; new_root->right = old_root; compute_height (new_left); } compute_height (old_root); compute_height (new_root); } static void avl_walk_forward (node, func) avl_node *node; void (*func) (); { if (node != NIL (avl_node)) { avl_walk_forward (node->left, func); (*func) (node->key, node->value); avl_walk_forward (node->right, func); } } static void avl_walk_backward (node, func) avl_node *node; void (*func) (); { if (node != NIL (avl_node)) { avl_walk_backward (node->right, func); (*func) (node->key, node->value); avl_walk_backward (node->left, func); } } void avl_foreach (tree, func, direction) avl_tree *tree; void (*func) (); int direction; { if (direction == AVL_FORWARD) { avl_walk_forward (tree->root, func); } else { avl_walk_backward (tree->root, func); } } static void free_entry (node, key_free, value_free) avl_node *node; void (*key_free) (); void (*value_free) (); { if (node != NIL (avl_node)) { free_entry (node->left, key_free, value_free); free_entry (node->right, key_free, value_free); if (key_free != 0) (*key_free) (node->key); if (value_free != 0) (*value_free) (node->value); FREE (node); } } void avl_free_table (tree, key_free, value_free) avl_tree *tree; void (*key_free) (); void (*value_free) (); { free_entry (tree->root, key_free, value_free); FREE (tree); } int avl_count (tree) avl_tree *tree; { return tree->num_entries; } static avl_node * new_node (key, value) char *key; char *value; { register avl_node *new; new = ALLOC (avl_node, 1); new->key = key; new->value = value; new->height = 0; new->left = new->right = NIL (avl_node); return new; } int avl_numcmp (x, y) char *x, *y; { return (int) x - (int) y; } int avl_check_tree (tree) avl_tree *tree; { int error = 0; (void) do_check_tree (tree->root, tree->compar, &error); return error; } static int do_check_tree (node, compar, error) avl_node *node; int (*compar) (); int *error; { int l_height, r_height, comp_height, bal; if (node == NIL (avl_node)) { return -1; } r_height = do_check_tree (node->right, compar, error); l_height = do_check_tree (node->left, compar, error); comp_height = MAX (l_height, r_height) + 1; bal = r_height - l_height; if (comp_height != node->height) { (void) printf ("Bad height for 0x%08x: computed=%d stored=%d\n", node, comp_height, node->height); ++*error; } if (bal > 1 || bal < -1) { (void) printf ("Out of balance at node 0x%08x, balance = %d\n", node, bal); ++*error; } if (node->left != NIL (avl_node) && (*compar) (node->left->key, node->key) > 0) { (void) printf ("Bad ordering between 0x%08x and 0x%08x", node, node->left); ++*error; } if (node->right != NIL (avl_node) && (*compar) (node->key, node->right->key) > 0) { (void) printf ("Bad ordering between 0x%08x and 0x%08x", node, node->right); ++*error; } return comp_height; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/avl/avl.doc000066400000000000000000000103301300674244400230170ustar00rootroot00000000000000/* * Revision Control Information * * /projects/hsis/CVS/utilities/avl/avl.doc,v * rajeev * 1.3 * 1995/08/08 22:36:22 * */ avl_tree * avl_init_table(compare) int (*compare)(); Initialize and return a new avl_tree. Use the function `compare' to compare items in the tree. `compare' should be of the form: int compare(a,b) char *a, *b; and return a number < 0, == 0, > 0 depending on whether a < b, a == b, or a > b, respectively. void avl_free_table(tree, key_delete_func, value_delete_func) avl_tree *tree; void (*key_delete_func)(); void (*value_delete_func)(); Delete all storage associated with `tree'. The functions key_delete_func and value_delete_func, if non-null, are called to free each (key, value) pair. They are declared as: void key_delete_func(key) char *key; {} void value_delete_func(value) char *value; {} The C-library function free is often suitable as a free function. avl_first(tree, key_p, value_p) avl_tree *tree; char **key_p; char **value_p; Retrieves the smallest element in the tree. Returns 0 if there are no elements in the tree. avl_last(tree, key_p, value_p) avl_tree *tree; char **key_p; char **value_p; Retrieves the largest element in the tree. Returns 0 if there are no elements in the tree. avl_lookup(tree, key, value_p) avl_tree *tree; char *key; char **value_p; Search for an entry matching `key'. If found, set `value_p' to the associated value field and return 1. If not found, return 0 and leave `value_p' unchanged. avl_insert(tree, key, value); avl_tree *tree; char *key; char *value; Insert the value `value' under the key `key'. Multiple items are allowed with the same value; all are inserted. avl_delete(tree, key_p, value_p) avl_tree *tree; char **key_p; char **value_p; Search for the item with key `*key_p' in `tree'. If found, set `key_p' and `value_p' to point to the key and value of item, delete the item and return 1. Otherwise return 0 and leave `key_p' and `value_p' unchanged. WARNING: This interface is buggy; in particular, if identical keys are in the table, it is not possible to delete a particular (key, value) pair. This will be fixed either with 'handles' or a separate delete function. avl_find_or_add(tree, key, slot_p) avl_tree *tree; char *key; char ***slot_p; Search for an entry matching key; if not found, insert key and return the address of the value slot for this entry. If found, do not insert key, and return the address of the value slot for the existing entry. slot_p can be used to associate a value with the key. void avl_foreach(tree, func, direction) avl_tree *tree; int (*func)(); int direction; Apply `func' to each item in the tree `tree' in turn. If direction is AVL_FORWARD, the tree is traversed from smallest to largest. Otherwise it is traversed from largest to smallest. func should be of the form: void func(key, value) char *key; char *value; where `key' is the key the item was stored under, and `value' the value of the item. avl_count(tree) avl_tree *tree; Returns the number of entries in the avl tree. avl_generator * avl_init_gen(tree, direction) avl_tree *tree; int direction; Start up a generator on an avl-tree. direction is either AVL_FORWARD or AVL_BACKWARD indicating the direction of generation. avl_gen(gen, key_p, value_p) avl_generator *gen; char **key_p; char **value_p; Generate the next item from the avl-tree. Returns 0 if there are no more items in the tree. Deletion of last generated item (via avl_delete) is supported. Insertion of items during generation will result in these items never being generated (until the next avl_init_gen()). Excercise for the interested student: how does one write an avl generator ? void avl_free_gen(gen) avl_generator *gen; Free a generator. avl_foreach_item(tree, gen, direction, key_p, value_p) avl_tree *tree; avl_generator *gen; int direction; char **key_p; char **value_p; Generate over all items in an avl-tree. This macro iterator combines avl_init_gen(), avl_gen(), and avl_free_gen() into a single statement iterator. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/avl/avl.h000066400000000000000000000042341300674244400225070ustar00rootroot00000000000000/* * Revision Control Information * * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/avl/RCS/avl.h,v $ * $Author: sis $ * $Revision: 1.3 $ * $Date: 1994/07/15 23:00:40 $ * */ #ifndef ABC__misc__avl__avl_h #define ABC__misc__avl__avl_h ABC_NAMESPACE_HEADER_START #define EXTERN #ifndef ARGS #define ARGS(protos) protos #endif #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define NIL(type) \ ((type *) 0) #define ALLOC(type, num) \ ((type *) malloc(sizeof(type) * (num))) #define REALLOC(type, obj, num) \ ((type *) realloc((char *) obj, sizeof(type) * (num))) #define FREE(obj) \ free((char *) (obj)) typedef struct avl_node_struct avl_node; struct avl_node_struct { avl_node *left, *right; char *key; char *value; int height; }; typedef struct avl_tree_struct avl_tree; struct avl_tree_struct { avl_node *root; int (*compar)(); int num_entries; int modified; }; typedef struct avl_generator_struct avl_generator; struct avl_generator_struct { avl_tree *tree; avl_node **nodelist; int count; }; #define AVL_FORWARD 0 #define AVL_BACKWARD 1 EXTERN avl_tree *avl_init_table ARGS((int (*)())); EXTERN int avl_delete ARGS((avl_tree *, char **, char **)); EXTERN int avl_insert ARGS((avl_tree *, char *, char *)); EXTERN int avl_lookup ARGS((avl_tree *, char *, char **)); EXTERN int avl_first ARGS((avl_tree *, char **, char **)); EXTERN int avl_last ARGS((avl_tree *, char **, char **)); EXTERN int avl_find_or_add ARGS((avl_tree *, char *, char ***)); EXTERN int avl_count ARGS((avl_tree *)); EXTERN int avl_numcmp ARGS((char *, char *)); EXTERN int avl_gen ARGS((avl_generator *, char **, char **)); EXTERN void avl_foreach ARGS((avl_tree *, void (*)(), int)); EXTERN void avl_free_table ARGS((avl_tree *, void (*)(), void (*)())); EXTERN void avl_free_gen ARGS((avl_generator *)); EXTERN avl_generator *avl_init_gen ARGS((avl_tree *, int)); #define avl_is_member(tree, key) avl_lookup(tree, key, (char **) 0) #define avl_foreach_item(table, gen, dir, key_p, value_p) \ for(gen = avl_init_gen(table, dir); \ avl_gen(gen, key_p, value_p) || (avl_free_gen(gen),0);) ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bar/000077500000000000000000000000001300674244400215335ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bar/bar.c000066400000000000000000000123431300674244400224460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bar.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Progress bar.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bar.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include "misc/util/abc_global.h" #include "base/main/main.h" #include "bar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Bar_Progress_t_ { int nItemsNext; // the number of items for the next update of the progress bar int nItemsTotal; // the total number of items int posTotal; // the total number of positions int posCur; // the current position FILE * pFile; // the output stream }; static void Bar_ProgressShow( Bar_Progress_t * p, char * pString ); static void Bar_ProgressClean( Bar_Progress_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the progress bar.] Description [The first parameter is the output stream (pFile), where the progress is printed. The current printing position should be the first one on the given line. The second parameters is the total number of items that correspond to 100% position of the progress bar.] SideEffects [] SeeAlso [] ***********************************************************************/ Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal ) { Bar_Progress_t * p; Abc_Frame_t * pFrame; pFrame = Abc_FrameReadGlobalFrame(); if ( pFrame == NULL ) return NULL; if ( !Abc_FrameShowProgress(pFrame) ) return NULL; p = ABC_ALLOC( Bar_Progress_t, 1 ); memset( p, 0, sizeof(Bar_Progress_t) ); p->pFile = pFile; p->nItemsTotal = nItemsTotal; p->posTotal = 78; p->posCur = 1; p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); Bar_ProgressShow( p, NULL ); return p; } /**Function************************************************************* Synopsis [Updates the progress bar.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString ) { if ( p == NULL ) return; if ( nItemsCur < p->nItemsNext ) return; if ( nItemsCur >= p->nItemsTotal ) { p->posCur = 78; p->nItemsNext = 0x7FFFFFFF; } else { p->posCur += 7; p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); } Bar_ProgressShow( p, pString ); } /**Function************************************************************* Synopsis [Stops the progress bar.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bar_ProgressStop( Bar_Progress_t * p ) { if ( p == NULL ) return; Bar_ProgressClean( p ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the progress bar of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bar_ProgressShow( Bar_Progress_t * p, char * pString ) { int i; if ( p == NULL ) return; if ( Abc_FrameIsBatchMode() ) return; if ( pString ) fprintf( p->pFile, "%s ", pString ); for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ ) fprintf( p->pFile, "-" ); if ( i == p->posCur ) fprintf( p->pFile, ">" ); for ( i++ ; i <= p->posTotal; i++ ) fprintf( p->pFile, " " ); fprintf( p->pFile, "\r" ); fflush( stdout ); } /**Function************************************************************* Synopsis [Cleans the progress bar before quitting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bar_ProgressClean( Bar_Progress_t * p ) { int i; if ( p == NULL ) return; if ( Abc_FrameIsBatchMode() ) return; for ( i = 0; i <= p->posTotal; i++ ) fprintf( p->pFile, " " ); fprintf( p->pFile, "\r" ); fflush( stdout ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bar/bar.h000066400000000000000000000051101300674244400224450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bar.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Progress bar.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bar.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__bar__bar_h #define ABC__aig__bar__bar_h #ifdef _WIN32 #define inline __inline // compatible with MS VS 6.0 #endif //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define BAR_PROGRESS_USE 1 //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Bar_Progress_t_ Bar_Progress_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== bar.c ==========================================================*/ extern Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal ); extern void Bar_ProgressStop( Bar_Progress_t * p ); extern void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString ); static inline void Bar_ProgressUpdate( Bar_Progress_t * p, int nItemsCur, char * pString ) { if ( BAR_PROGRESS_USE && p && (nItemsCur < *((int*)p)) ) return; Bar_ProgressUpdate_int(p, nItemsCur, pString); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bar/module.make000066400000000000000000000000331300674244400236530ustar00rootroot00000000000000SRC += src/misc/bar/bar.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bbl/000077500000000000000000000000001300674244400215265ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bbl/bblif.c000066400000000000000000001247321300674244400227610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bblif.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Binary BLIF representation for logic networks.] Synopsis [Main implementation module.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 28, 2009.] Revision [$Id: bblif.c,v 1.00 2009/02/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/util/abc_global.h" #include "bblif.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // vector of integers typedef struct Vec_Int_t_ Vec_Int_t; struct Vec_Int_t_ { int nCap; int nSize; int * pArray; }; // vector of characters typedef struct Vec_Str_t_ Vec_Str_t; struct Vec_Str_t_ { int nCap; int nSize; char * pArray; }; // network object struct Bbl_Obj_t_ { int Id; // user ID int Fnc; // functionality unsigned fCi : 1; // combinational input unsigned fCo : 1; // combinational output unsigned fBox : 1; // subcircuit unsigned fMark : 1; // temporary mark unsigned nFanins : 28; // fanin number int pFanins[0]; // fanin array }; // object function typedef struct Bbl_Fnc_t_ Bbl_Fnc_t; struct Bbl_Fnc_t_ { int nWords; // word number int pWords[0]; // word array }; // object function typedef struct Bbl_Ent_t_ Bbl_Ent_t; struct Bbl_Ent_t_ { int iFunc; // function handle int iNext; // next entry handle }; // data manager struct Bbl_Man_t_ { // data pool Vec_Str_t * pName; // design name Vec_Str_t * pObjs; // vector of objects Vec_Str_t * pFncs; // vector of functions // construction Vec_Int_t * vId2Obj; // mapping user IDs into objects Vec_Int_t * vObj2Id; // mapping objects into user IDs Vec_Int_t * vFaninNums; // mapping user IDs into fanin number // file contents int nFileSize; // file size char * pFileData; // file contents // other data Vec_Str_t * pEnts; // vector of entries int SopMap[17][17]; // mapping vars x cubes into entry handles }; static inline int Bbl_ObjIsCi( Bbl_Obj_t * pObj ) { return pObj->fCi; } static inline int Bbl_ObjIsCo( Bbl_Obj_t * pObj ) { return pObj->fCo; } static inline int Bbl_ObjIsNode( Bbl_Obj_t * pObj ) { return!pObj->fCi && !pObj->fCo; } static inline int Bbl_ObjFaninNum( Bbl_Obj_t * pObj ) { return pObj->nFanins; } static inline Bbl_Obj_t * Bbl_ObjFanin( Bbl_Obj_t * pObj, int i ) { return (Bbl_Obj_t *)(((char *)pObj) - pObj->pFanins[i]); } static inline int Bbl_ObjSize( Bbl_Obj_t * pObj ) { return sizeof(Bbl_Obj_t) + sizeof(int) * pObj->nFanins; } static inline int Bbl_FncSize( Bbl_Fnc_t * pFnc ) { return sizeof(Bbl_Fnc_t) + sizeof(int) * pFnc->nWords; } static inline Bbl_Obj_t * Bbl_VecObj( Vec_Str_t * p, int h ) { return (Bbl_Obj_t *)(p->pArray + h); } static inline Bbl_Fnc_t * Bbl_VecFnc( Vec_Str_t * p, int h ) { return (Bbl_Fnc_t *)(p->pArray + h); } static inline Bbl_Ent_t * Bbl_VecEnt( Vec_Str_t * p, int h ) { return (Bbl_Ent_t *)(p->pArray + h); } static inline char * Bbl_ManSop( Bbl_Man_t * p, int h ) { return (char *)Bbl_VecFnc(p->pFncs, h)->pWords; } static inline Bbl_Obj_t * Bbl_ManObj( Bbl_Man_t * p, int Id ) { return Bbl_VecObj(p->pObjs, p->vId2Obj->pArray[Id]); } #define Bbl_ManForEachObj_int( p, pObj, h ) \ for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecObj(p,h)); h += Bbl_ObjSize(pObj) ) #define Bbl_ManForEachFnc_int( p, pObj, h ) \ for ( h = 0; (h < p->nSize) && (pObj = Bbl_VecFnc(p,h)); h += Bbl_FncSize(pObj) ) #define Bbl_ObjForEachFanin_int( pObj, pFanin, i ) \ for ( i = 0; (i < (int)pObj->nFanins) && (pFanin = Bbl_ObjFanin(pObj,i)); i++ ) #define BBLIF_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) #define BBLIF_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) #define BBLIF_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) #define BBLIF_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) #define BBLIF_REALLOC(type, obj, num) \ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ ((type *) malloc(sizeof(type) * (num)))) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntAlloc( int nCap ) { Vec_Int_t * p; p = BBLIF_ALLOC( Vec_Int_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? BBLIF_ALLOC( int, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntStart( int nSize ) { Vec_Int_t * p; p = Vec_IntAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0, sizeof(int) * nSize ); return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntStartNatural( int nSize ) { Vec_Int_t * p; int i; p = Vec_IntAlloc( nSize ); p->nSize = nSize; for ( i = 0; i < nSize; i++ ) p->pArray[i] = i; return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize ) { Vec_Int_t * p; p = BBLIF_ALLOC( Vec_Int_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = pArray; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntFree( Vec_Int_t * p ) { BBLIF_FREE( p->pArray ); BBLIF_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntSize( Vec_Int_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntEntry( Vec_Int_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] += Addition; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntEntryLast( Vec_Int_t * p ) { assert( p->nSize > 0 ); return p->pArray[p->nSize-1]; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = BBLIF_REALLOC( int, p->pArray, nCapMin ); assert( p->pArray ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Fill ) { int i; Vec_IntGrow( p, nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Fill ) { int i; if ( p->nSize >= nSize ) return; if ( nSize > 2 * p->nCap ) Vec_IntGrow( p, nSize ); else if ( nSize > p->nCap ) Vec_IntGrow( p, 2 * p->nCap ); for ( i = p->nSize; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } /**Function************************************************************* Synopsis [Returns the entry even if the place not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntGetEntry( Vec_Int_t * p, int i ) { Vec_IntFillExtra( p, i + 1, 0 ); return Vec_IntEntry( p, i ); } /**Function************************************************************* Synopsis [Inserts the entry even if the place does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntSetEntry( Vec_Int_t * p, int i, int Entry ) { Vec_IntFillExtra( p, i + 1, 0 ); Vec_IntWriteEntry( p, i, Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntClear( Vec_Int_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_IntGrow( p, 16 ); else Vec_IntGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Str_t * Vec_StrAlloc( int nCap ) { Vec_Str_t * p; p = BBLIF_ALLOC( Vec_Str_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? BBLIF_ALLOC( char, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Creates the vector from an array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize ) { Vec_Str_t * p; p = BBLIF_ALLOC( Vec_Str_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = pArray; return p; } /**Fnction************************************************************* Synopsis [Returns a piece of memory.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Vec_StrFetch( Vec_Str_t * p, int nBytes ) { while ( p->nSize + nBytes > p->nCap ) { p->pArray = BBLIF_REALLOC( char, p->pArray, 3 * p->nCap ); p->nCap *= 3; } p->nSize += nBytes; return p->pArray + p->nSize - nBytes; } /**Fnction************************************************************* Synopsis [Write vector into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vec_StrWrite( FILE * pFile, Vec_Str_t * p ) { fwrite( &p->nSize, sizeof(int), 1, pFile ); fwrite( p->pArray, sizeof(char), p->nSize, pFile ); } /**Fnction************************************************************* Synopsis [Write vector into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Vec_StrRead( char ** ppStr ) { Vec_Str_t * p; char * pStr = *ppStr; p = Vec_StrAlloc( 0 ); p->nSize = *(int *)pStr; p->pArray = pStr + sizeof(int); *ppStr = pStr + sizeof(int) + p->nSize * sizeof(char); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_StrSize( Vec_Str_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrFree( Vec_Str_t * p ) { BBLIF_FREE( p->pArray ); BBLIF_FREE( p ); } /**Fnction************************************************************* Synopsis [Returns the file size.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbl_ManFileSize( char * pFileName ) { FILE * pFile; int nFileSize; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Bbl_ManFileSize(): The file is unavailable (absent or open).\n" ); return 0; } fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); fclose( pFile ); return nFileSize; } /**Fnction************************************************************* Synopsis [Read data from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Bbl_ManFileRead( char * pFileName ) { FILE * pFile; char * pContents; int nFileSize; int RetValue; nFileSize = Bbl_ManFileSize( pFileName ); pFile = fopen( pFileName, "rb" ); pContents = BBLIF_ALLOC( char, nFileSize ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); return pContents; } /**Fnction************************************************************* Synopsis [Writes data into file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName ) { FILE * pFile; pFile = fopen( pFileName, "wb" ); Vec_StrWrite( pFile, p->pName ); Vec_StrWrite( pFile, p->pObjs ); Vec_StrWrite( pFile, p->pFncs ); fclose( pFile ); } /**Fnction************************************************************* Synopsis [Creates manager after reading.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName ) { Bbl_Man_t * p; Bbl_Obj_t * pObj; char * pBuffer; int h; p = BBLIF_ALLOC( Bbl_Man_t, 1 ); memset( p, 0, sizeof(Bbl_Man_t) ); p->nFileSize = Bbl_ManFileSize( pFileName ); p->pFileData = Bbl_ManFileRead( pFileName ); // extract three managers pBuffer = p->pFileData; p->pName = Vec_StrRead( &pBuffer ); p->pObjs = Vec_StrRead( &pBuffer ); p->pFncs = Vec_StrRead( &pBuffer ); assert( pBuffer - p->pFileData == p->nFileSize ); // remember original IDs in the objects p->vObj2Id = Vec_IntAlloc( 1000 ); Bbl_ManForEachObj_int( p->pObjs, pObj, h ) { Vec_IntPush( p->vObj2Id, pObj->Id ); pObj->Id = Vec_IntSize(p->vObj2Id) - 1; } return p; } /**Fnction************************************************************* Synopsis [Prints stats of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManPrintStats( Bbl_Man_t * p ) { Bbl_Obj_t * pObj; Bbl_Fnc_t * pFnc; int h, nFuncs = 0, nNodes = 0, nObjs = 0; Bbl_ManForEachObj_int( p->pObjs, pObj, h ) nObjs++, nNodes += Bbl_ObjIsNode(pObj); Bbl_ManForEachFnc_int( p->pFncs, pFnc, h ) nFuncs++; printf( "Total objects = %7d. Total nodes = %7d. Unique functions = %7d.\n", nObjs, nNodes, nFuncs ); printf( "Name manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pName)/(1 << 20) ); printf( "Objs manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pObjs)/(1 << 20) ); printf( "Fncs manager = %5.2f MB\n", 1.0*Vec_StrSize(p->pFncs)/(1 << 20) ); } /**Fnction************************************************************* Synopsis [Deletes the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManStop( Bbl_Man_t * p ) { if ( p->vId2Obj ) Vec_IntFree( p->vId2Obj ); if ( p->vObj2Id ) Vec_IntFree( p->vObj2Id ); if ( p->vFaninNums ) Vec_IntFree( p->vFaninNums ); if ( p->pFileData ) { BBLIF_FREE( p->pFileData ); p->pName->pArray = NULL; p->pObjs->pArray = NULL; p->pFncs->pArray = NULL; } if ( p->pEnts ) Vec_StrFree( p->pEnts ); Vec_StrFree( p->pName ); Vec_StrFree( p->pObjs ); Vec_StrFree( p->pFncs ); BBLIF_FREE( p ); } /**Fnction************************************************************* Synopsis [Creates manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbl_Man_t * Bbl_ManStart( char * pName ) { Bbl_Man_t * p; int nLength; p = BBLIF_ALLOC( Bbl_Man_t, 1 ); memset( p, 0, sizeof(Bbl_Man_t) ); nLength = pName? 4 * ((strlen(pName) + 1) / 4 + 1) : 0; p->pName = Vec_StrAlloc( nLength ); p->pName->nSize = p->pName->nCap; if ( pName ) strcpy( p->pName->pArray, pName ); p->pObjs = Vec_StrAlloc( 1 << 16 ); p->pFncs = Vec_StrAlloc( 1 << 16 ); p->pEnts = Vec_StrAlloc( 1 << 16 ); p->pEnts->nSize = 1; p->vId2Obj = Vec_IntStart( 1 << 10 ); p->vFaninNums = Vec_IntStart( 1 << 10 ); return p; } /**Function************************************************************* Synopsis [Performs selection sort on the array of cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManSortCubes( char ** pCubes, int nCubes, int nVars ) { char * pTemp; int i, j, best_i; for ( i = 0; i < nCubes-1; i++ ) { best_i = i; for (j = i+1; j < nCubes; j++) if ( memcmp( pCubes[j], pCubes[best_i], nVars ) < 0 ) best_i = j; pTemp = pCubes[i]; pCubes[i] = pCubes[best_i]; pCubes[best_i] = pTemp; } } /**Function************************************************************* Synopsis [Sorts the cubes in the SOP to uniqify them to some extent.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Bbl_ManSortSop( char * pSop, int nVars ) { char ** pCubes, * pSopNew; int c, Length, nCubes; Length = strlen(pSop); assert( Length % (nVars + 3) == 0 ); nCubes = Length / (nVars + 3); if ( nCubes < 2 ) { pSopNew = BBLIF_ALLOC( char, Length + 1 ); memcpy( pSopNew, pSop, Length + 1 ); return pSopNew; } pCubes = BBLIF_ALLOC( char *, nCubes ); for ( c = 0; c < nCubes; c++ ) pCubes[c] = pSop + c * (nVars + 3); if ( nCubes < 300 ) Bbl_ManSortCubes( pCubes, nCubes, nVars ); pSopNew = BBLIF_ALLOC( char, Length + 1 ); for ( c = 0; c < nCubes; c++ ) memcpy( pSopNew + c * (nVars + 3), pCubes[c], nVars + 3 ); BBLIF_FREE( pCubes ); pSopNew[nCubes * (nVars + 3)] = 0; return pSopNew; } /**Fnction************************************************************* Synopsis [Saves one entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbl_ManCreateEntry( Bbl_Man_t * p, int iFunc, int iNext ) { Bbl_Ent_t * pEnt; pEnt = (Bbl_Ent_t *)Vec_StrFetch( p->pEnts, 2 * sizeof(int) ); pEnt->iFunc = iFunc; pEnt->iNext = iNext; return (char *)pEnt - p->pEnts->pArray; } /**Function************************************************************* Synopsis [Sorts the cubes in the SOP to uniqify them to some extent.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbl_ManSopCheckUnique( Bbl_Man_t * p, char * pSop, int nVars, int nCubes, int iFunc ) { Bbl_Fnc_t * pFnc; Bbl_Ent_t * pEnt; int h, Length = strlen(pSop) + 1; int nWords = (Length / 4 + (Length % 4 > 0)); if ( nVars > 16 ) nVars = 16; if ( nCubes > 16 ) nCubes = 16; // if ( nVars == 16 && nCubes == 16 ) // return iFunc; for ( h = p->SopMap[nVars][nCubes]; h; h = pEnt->iNext ) { pEnt = Bbl_VecEnt( p->pEnts, h ); pFnc = Bbl_VecFnc( p->pFncs, pEnt->iFunc ); assert( nVars == 16 || nCubes == 16 || pFnc->nWords == nWords ); if ( pFnc->nWords == nWords && memcmp( pFnc->pWords, pSop, Length ) == 0 ) return pEnt->iFunc; } p->SopMap[nVars][nCubes] = Bbl_ManCreateEntry( p, iFunc, p->SopMap[nVars][nCubes] ); return iFunc; } /**Fnction************************************************************* Synopsis [Saves one SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbl_ManSaveSop( Bbl_Man_t * p, char * pSop, int nVars ) { Bbl_Fnc_t * pFnc; char * pSopNew; int iFunc, Length = strlen(pSop) + 1; int nWords = Length / 4 + (Length % 4 > 0); // reorder cubes to semi-canicize SOPs pSopNew = Bbl_ManSortSop( pSop, nVars ); // get the candidate location iFunc = Bbl_ManSopCheckUnique( p, pSopNew, nVars, Length / (nVars + 3), Vec_StrSize(p->pFncs) ); // iFunc = Vec_StrSize(p->pFncs); if ( iFunc == Vec_StrSize(p->pFncs) ) { // store this SOP pFnc = (Bbl_Fnc_t *)Vec_StrFetch( p->pFncs, sizeof(Bbl_Fnc_t) + nWords * sizeof(int) ); pFnc->pWords[nWords-1] = 0; pFnc->nWords = nWords; strcpy( (char *)pFnc->pWords, pSopNew ); assert( iFunc == (char *)pFnc - p->pFncs->pArray ); } BBLIF_FREE( pSopNew ); return iFunc; } /**Fnction************************************************************* Synopsis [Adds one object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop ) { Bbl_Obj_t * pObj; if ( Type == BBL_OBJ_CI && nFanins != 0 ) { printf( "Attempting to create a combinational input with %d fanins (should be 0).\n", nFanins ); return; } if ( Type == BBL_OBJ_CO && nFanins != 1 ) { printf( "Attempting to create a combinational output with %d fanins (should be 1).\n", nFanins ); return; } pObj = (Bbl_Obj_t *)Vec_StrFetch( p->pObjs, sizeof(Bbl_Obj_t) + nFanins * sizeof(int) ); memset( pObj, 0, sizeof(Bbl_Obj_t) ); Vec_IntSetEntry( p->vId2Obj, ObjId, (char *)pObj - p->pObjs->pArray ); Vec_IntSetEntry( p->vFaninNums, ObjId, 0 ); pObj->fCi = (Type == BBL_OBJ_CI); pObj->fCo = (Type == BBL_OBJ_CO); pObj->Id = ObjId; pObj->Fnc = pSop? Bbl_ManSaveSop(p, pSop, nFanins) : -1; pObj->nFanins = nFanins; } /**Fnction************************************************************* Synopsis [Creates fanin/fanout relationship between two objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId ) { Bbl_Obj_t * pObj, * pFanin; int iFanin; pObj = Bbl_ManObj( p, ObjId ); if ( Bbl_ObjIsCi(pObj) ) { printf( "Bbl_ManAddFanin(): Cannot add fanin of the combinational input (Id = %d).\n", ObjId ); return; } pFanin = Bbl_ManObj( p, FaninId ); if ( Bbl_ObjIsCo(pFanin) ) { printf( "Bbl_ManAddFanin(): Cannot add fanout of the combinational output (Id = %d).\n", FaninId ); return; } iFanin = Vec_IntEntry( p->vFaninNums, ObjId ); if ( iFanin >= (int)pObj->nFanins ) { printf( "Bbl_ManAddFanin(): Trying to add more fanins to object (Id = %d) than declared (%d).\n", ObjId, pObj->nFanins ); return; } assert( iFanin < (int)pObj->nFanins ); Vec_IntWriteEntry( p->vFaninNums, ObjId, iFanin+1 ); pObj->pFanins[iFanin] = (char *)pObj - (char *)pFanin; } /**Fnction************************************************************* Synopsis [Returns 1 if the manager was created correctly.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbl_ManCheck( Bbl_Man_t * p ) { Bbl_Obj_t * pObj; int h, RetValue = 1; Bbl_ManForEachObj_int( p->pObjs, pObj, h ) { if ( Bbl_ObjIsNode(pObj) && pObj->Fnc == -1 ) RetValue = 0, printf( "Bbl_ManCheck(): Node %d does not have function specified.\n", pObj->Id ); if ( Bbl_ObjIsCi(pObj) && pObj->Fnc != -1 ) RetValue = 0, printf( "Bbl_ManCheck(): CI with %d has function specified.\n", pObj->Id ); if ( Bbl_ObjIsCo(pObj) && pObj->Fnc != -1 ) RetValue = 0, printf( "Bbl_ManCheck(): CO with %d has function specified.\n", pObj->Id ); if ( Vec_IntEntry(p->vFaninNums, pObj->Id) != (int)pObj->nFanins ) RetValue = 0, printf( "Bbl_ManCheck(): Object %d has less fanins (%d) than declared (%d).\n", pObj->Id, Vec_IntEntry(p->vFaninNums, pObj->Id), pObj->nFanins ); } return RetValue; } /**Fnction************************************************************* Synopsis [Misc APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbl_ObjIsInput( Bbl_Obj_t * p ) { return Bbl_ObjIsCi(p); } int Bbl_ObjIsOutput( Bbl_Obj_t * p ) { return Bbl_ObjIsCo(p); } int Bbl_ObjIsLut( Bbl_Obj_t * p ) { return Bbl_ObjIsNode(p); } int Bbl_ObjId( Bbl_Obj_t * p ) { return p->Id; } int Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { assert(0); return Vec_IntEntry(pMan->vObj2Id, p->Id); } int Bbl_ObjFaninNumber( Bbl_Obj_t * p ) { return Bbl_ObjFaninNum(p); } char * Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p ) { return Bbl_ManSop(pMan, p->Fnc); } int Bbl_ObjIsMarked( Bbl_Obj_t * p ) { return p->fMark; } void Bbl_ObjMark( Bbl_Obj_t * p ) { p->fMark = 1; } int Bbl_ObjFncHandle( Bbl_Obj_t * p ) { return p->Fnc; } /**Fnction************************************************************* Synopsis [Returns the name of the design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Bbl_ManName( Bbl_Man_t * p ) { return p->pName->pArray; } /**Fnction************************************************************* Synopsis [Returns the maximum handle of the SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bbl_ManFncSize( Bbl_Man_t * p ) { return p->pFncs->nSize; } /**Fnction************************************************************* Synopsis [Returns the first object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p ) { return Bbl_VecObj( p->pObjs, 0 ); } /**Fnction************************************************************* Synopsis [Returns the next object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj ) { char * pNext = (char *)pObj + Bbl_ObjSize(pObj); char * pEdge = p->pObjs->pArray + p->pObjs->nSize; return (Bbl_Obj_t *)(pNext < pEdge ? pNext : NULL); } /**Fnction************************************************************* Synopsis [Returns the first fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p ) { return Bbl_ObjFaninNum(p) ? Bbl_ObjFanin( p, 0 ) : NULL; } /**Fnction************************************************************* Synopsis [Returns the next fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev ) { Bbl_Obj_t * pFanin; int i; Bbl_ObjForEachFanin_int( p, pFanin, i ) if ( pFanin == pPrev ) break; return i < Bbl_ObjFaninNum(p) - 1 ? Bbl_ObjFanin( p, i+1 ) : NULL; } /**Fnction************************************************************* Synopsis [Drives text BLIF file for debugging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName ) { FILE * pFile; Bbl_Obj_t * pObj, * pFanin; pFile = fopen( pFileName, "w" ); fprintf( pFile, "# Test file written by Bbl_ManDumpBlif() in ABC.\n" ); fprintf( pFile, ".model %s\n", Bbl_ManName(p) ); // write objects Bbl_ManForEachObj( p, pObj ) { if ( Bbl_ObjIsInput(pObj) ) fprintf( pFile, ".inputs %d\n", Bbl_ObjId(pObj) ); else if ( Bbl_ObjIsOutput(pObj) ) fprintf( pFile, ".outputs %d\n", Bbl_ObjId(pObj) ); else if ( Bbl_ObjIsLut(pObj) ) { fprintf( pFile, ".names" ); Bbl_ObjForEachFanin( pObj, pFanin ) fprintf( pFile, " %d", Bbl_ObjId(pFanin) ); fprintf( pFile, " %d\n", Bbl_ObjId(pObj) ); fprintf( pFile, "%s", Bbl_ObjSop(p, pObj) ); } else assert( 0 ); } // write output drivers Bbl_ManForEachObj( p, pObj ) { if ( !Bbl_ObjIsOutput(pObj) ) continue; fprintf( pFile, ".names" ); Bbl_ObjForEachFanin( pObj, pFanin ) fprintf( pFile, " %d", Bbl_ObjId(pFanin) ); fprintf( pFile, " %d\n", Bbl_ObjId(pObj) ); fprintf( pFile, "1 1\n" ); } fprintf( pFile, ".end\n" ); fclose( pFile ); } /**Fnction************************************************************* Synopsis [Converting truth table into an SOP.] Description [The truth table is given as a bit-string pTruth composed of 2^nVars bits. The result is an SOP derived by collecting minterms appearing in the truth table. The SOP is represented as a C-string, as documented in file "bblif.h". It is recommended to limit the use of this procedure to Boolean functions up to 6 inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Bbl_ManTruthToSop( unsigned * pTruth, int nVars ) { char * pResult, * pTemp; int nMints, nOnes, b, v; assert( nVars >= 0 && nVars <= 16 ); nMints = (1 << nVars); // count the number of ones nOnes = 0; for ( b = 0; b < nMints; b++ ) nOnes += ((pTruth[b>>5] >> (b&31)) & 1); // handle constants if ( nOnes == 0 || nOnes == nMints ) { pResult = pTemp = BBLIF_ALLOC( char, nVars + 4 ); for ( v = 0; v < nVars; v++ ) *pTemp++ = '-'; *pTemp++ = ' '; *pTemp++ = nOnes? '1' : '0'; *pTemp++ = '\n'; *pTemp++ = 0; assert( pTemp - pResult == nVars + 4 ); return pResult; } pResult = pTemp = BBLIF_ALLOC( char, nOnes * (nVars + 3) + 1 ); for ( b = 0; b < nMints; b++ ) { if ( ((pTruth[b>>5] >> (b&31)) & 1) == 0 ) continue; for ( v = 0; v < nVars; v++ ) *pTemp++ = ((b >> v) & 1)? '1' : '0'; *pTemp++ = ' '; *pTemp++ = '1'; *pTemp++ = '\n'; } *pTemp++ = 0; assert( pTemp - pResult == nOnes * (nVars + 3) + 1 ); return pResult; } /**Function************************************************************* Synopsis [Allocates the array of truth tables for the given number of vars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Bbl_ManSopToTruthElem( int nVars, unsigned ** pVars ) { unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; int i, k, nWords; nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); for ( i = 0; i < nVars; i++ ) { if ( i < 5 ) { for ( k = 0; k < nWords; k++ ) pVars[i][k] = Masks[i]; } else { for ( k = 0; k < nWords; k++ ) if ( k & (1 << (i-5)) ) pVars[i][k] = ~(unsigned)0; else pVars[i][k] = 0; } } } /**Fnction************************************************************* Synopsis [Converting SOP into a truth table.] Description [The SOP is represented as a C-string, as documented in file "bblif.h". The truth table is returned as a bit-string composed of 2^nVars bits. For functions of less than 6 variables, the full machine word is returned. (The truth table looks as if the function had 5 variables.) The use of this procedure should be limited to Boolean functions with no more than 16 inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Bbl_ManSopToTruth( char * pSop, int nVars ) { unsigned * pTruth, * pCube, * pVars[16]; int nWords = nVars <= 5 ? 1 : (1 << (nVars - 5)); int v, c, w, nCubes, fCompl = 0; if ( pSop == NULL ) return NULL; if ( strlen(pSop) % (nVars + 3) != 0 ) { printf( "Bbl_ManSopToTruth(): SOP is represented incorrectly.\n" ); return NULL; } // create storage for TTs of the result, elementary variables and the temp cube pTruth = BBLIF_ALLOC( unsigned, nWords ); pVars[0] = BBLIF_ALLOC( unsigned, nWords * (nVars+1) ); for ( v = 1; v < nVars; v++ ) pVars[v] = pVars[v-1] + nWords; pCube = pVars[v-1] + nWords; Bbl_ManSopToTruthElem( nVars, pVars ); // iterate through the cubes memset( pTruth, 0, sizeof(unsigned) * nWords ); nCubes = strlen(pSop) / (nVars + 3); for ( c = 0; c < nCubes; c++ ) { fCompl = (pSop[nVars+1] == '0'); memset( pCube, 0xff, sizeof(unsigned) * nWords ); // iterate through the literals of the cube for ( v = 0; v < nVars; v++ ) if ( pSop[v] == '1' ) for ( w = 0; w < nWords; w++ ) pCube[w] &= pVars[v][w]; else if ( pSop[v] == '0' ) for ( w = 0; w < nWords; w++ ) pCube[w] &= ~pVars[v][w]; // add cube to storage for ( w = 0; w < nWords; w++ ) pTruth[w] |= pCube[w]; // go to the next cube pSop += (nVars + 3); } BBLIF_FREE( pVars[0] ); if ( fCompl ) for ( w = 0; w < nWords; w++ ) pTruth[w] = ~pTruth[w]; return pTruth; } /**Fnction************************************************************* Synopsis [Checks the truth table computation.] Description [We construct the logic network for the half-adder represnted using the BLIF file below] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManTestTruth( char * pSop, int nVars ) { unsigned * pTruth; char * pSopNew; pTruth = Bbl_ManSopToTruth( pSop, nVars ); pSopNew = Bbl_ManTruthToSop( pTruth, nVars ); printf( "Old SOP:\n%s\n", pSop ); printf( "New SOP:\n%s\n", pSopNew ); BBLIF_FREE( pSopNew ); BBLIF_FREE( pTruth ); } /**Fnction************************************************************* Synopsis [This demo shows using the internal to construct a half-adder.] Description [We construct the logic network for the half-adder represnted using the BLIF file below] SideEffects [] SeeAlso [] ***********************************************************************/ void Bbl_ManSimpleDemo() { /* # There are contents of a BLIF file representing a half-adder: .model hadder .inputs a // ID = 1 .inputs b // ID = 2 .inputs cin // ID = 3 .outputs s // ID = 4 .outputs cout // ID = 5 .names a b cin s_driver // ID = 6 100 1 010 1 001 1 111 1 .names a b cin cout_driver // ID = 7 -11 1 1-1 1 11- 1 .names s_driver s 1 1 .names cout_driver cout 1 1 .end */ Bbl_Man_t * p; // start the data manager p = Bbl_ManStart( "hadder" ); // create CIs Bbl_ManCreateObject( p, BBL_OBJ_CI, 1, 0, NULL ); // a Bbl_ManCreateObject( p, BBL_OBJ_CI, 2, 0, NULL ); // b Bbl_ManCreateObject( p, BBL_OBJ_CI, 3, 0, NULL ); // cin // create COs Bbl_ManCreateObject( p, BBL_OBJ_CO, 4, 1, NULL ); // s Bbl_ManCreateObject( p, BBL_OBJ_CO, 5, 1, NULL ); // cout // create internal nodes Bbl_ManCreateObject( p, BBL_OBJ_NODE, 6, 3, "100 1\n010 1\n001 1\n111 1\n" ); // s_driver Bbl_ManCreateObject( p, BBL_OBJ_NODE, 7, 3, "-11 1\n1-1 1\n11- 1\n" ); // cout_driver // add fanins of node 6 Bbl_ManAddFanin( p, 6, 1 ); // s_driver <- a Bbl_ManAddFanin( p, 6, 2 ); // s_driver <- b Bbl_ManAddFanin( p, 6, 3 ); // s_driver <- cin // add fanins of node 7 Bbl_ManAddFanin( p, 7, 1 ); // cout_driver <- a Bbl_ManAddFanin( p, 7, 2 ); // cout_driver <- b Bbl_ManAddFanin( p, 7, 3 ); // cout_driver <- cin // add fanins of COs Bbl_ManAddFanin( p, 4, 6 ); // s <- s_driver Bbl_ManAddFanin( p, 5, 7 ); // cout <- cout_driver // sanity check Bbl_ManCheck( p ); // write BLIF file as a sanity check Bbl_ManDumpBlif( p, "hadder.blif" ); // write binary BLIF file Bbl_ManDumpBinaryBlif( p, "hadder.bblif" ); // remove the manager Bbl_ManStop( p ); // Bbl_ManTestTruth( "100 1\n010 1\n001 1\n111 1\n", 3 ); // Bbl_ManTestTruth( "-11 0\n1-1 0\n11- 0\n", 3 ); // Bbl_ManTestTruth( "--- 1\n", 3 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bbl/bblif.h000066400000000000000000000331031300674244400227550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bblif.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Binary BLIF representation for logic networks.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 28, 2009.] Revision [$Id: bblif.h,v 1.00 2009/02/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__bbl__bblif_h #define ABC__aig__bbl__bblif_h /* This file (taken together with "bblif.c") implements a stand-alone interface between ABC and an application that uses ABC. The interface is designed to pass a combinational logic network from the calling application to ABC using a binary BLIF format (BBLIF) and return the network after synthesis/mapping/verification in ABC back to the caller. The interface can do the following: (1) accept a combinational logic network via a set of APIs (2) write the logic network into a binary BLIF file readable by ABC (3) read a binary BLIF file with a mapped network produced by ABC (4) return the mapped network to the caller through a set of APIs It should be noted that the BBLIF interface can be used to pass the network from the calling application into ABC without writing it into a file. In this case, ABC should be compiled as a library and linked to the calling application. The BBLIF manager can be given directly to the procedure Bbl_ManToAbc() to convert it into an AIG. Similarly, the resulting mapped network can be converted into BBLIF manager and passed back after the call to Bbl_ManFromAbc(). Here these steps are described in more detail: (1) The BBLIF manager is allocated by calling Bbl_ManStart() and deallocated by calling Bbl_ManStop(). The combinational network is composed of three types of objects: (a) combinational inputs (CIs), (b) combinational outputs (COs), (c) internal logic nodes represented using Sum-of-Products (SOPs) similar to the way logic nodes are represented in SIS. Sequential elements (flops) are currently not supported. A CI has no fanins. A CO has exactly one fanin and no fanouts. Internal nodes can have any number of fanins and fanouts. Only an internal node can have a logic function. Before constructing the BBLIF manager, each object should be assigned a unique non-negative (0-based) integer ID. The sequence of ID numbers may have gaps in it (for example, 0, 1, 2, 5, 6, etc) but care should be taken that the ID numbers do not grow too large because internally they are used to index the objects. So if the largest given ID has value N, an array of 4*N bytes will be allocated internally by the BBLIF manager. Obviously if N = 1M, the array will use 4Mb, but if N = 100M, it will use 0.4Gb. This object ID (called also "the original ID of the object") is given to Bbl_ManCreateObject(), which construct the BBLIF objects and to the procedure Bbl_ManAddFanin(), which creates fanin/fanout relations between two objects. The exact number of fanins of an object should be declared when calling Bbl_ManCreateObject(). Later on, each node should be assigned as many fanins using Bbl_ManAddFanin(). The order/number of fanins corresponds to the order/number of variables in the SOP of the logic function of the node. The declared and actual number of fanins should be the same. otherwise the interface will not function correctly. This is checked by the procedure Bbl_ManCheck(), which should be called when constructing all objects and their fanins is finished. The SOP representation of the logic function should be given to every internal node. It is given as a C-string, showing the SOP as it would appear in a BLIF or PLA file. Each cube is composed of characters '0', '1', and '-', and ended by a seqence of three characters: space ' ', followed by '0' or '1' (depending on whether on- or off-set is used), followed by the new line character '\n'. For example, a two-input OR has the following SOP representation: "1- 1\n-1 1\n", or equivalently, "00 0\n". The SOP for a constant function with no fanins is represented as " 0\n" (constant 0) and " 1\n" (constant 1). SOP for a constant node with some fanins may also be represented. For example, constant 0 node with three fanins will have SOP representation as follows: "--- 0\n". The objects can be added to the BBLIF manager in any order, but by the time the fanin/fanout connections are created, corresponding objects should be already created. The number of objects is limited by 2^31. The number of fanins of one object is restricted to 2^28. The SOP representation can have arbitrary many products (cubes), as long as memory is enough to represent them in the C-string form, as described above. (2) To write the manager into a file, call procedure Bbl_ManDumpBinaryBlif(). It is recommended to use files with extension ".bblif" because it will allow ABC to call the approapriate reader in command "read". (3) To read the network from file, call procedure Bbl_ManReadBinaryBlif(). (4) It is assumed that ABC will return the network after mapping. This network will arrive in a BBLIF file, from which the BBLIF manager is created by the call to Bbl_ManReadBinaryBlif(). The following APIs are useful to extract the mapped network from the manager: Iterator Bbl_ManForEachObj() iterates through the pointers to the BBLIF objects, which are guaranteed to be in a topological order. For each object, the following APIs can be used: Bbl_ObjIsInput() returns 1 if the object is a CI Bbl_ObjIsOutput() returns 1 if the object is a CO Bbl_ObjIsLut() returns 1 if the object is a logic node (lookup table) Bbl_ObjFaninNumber() returns the number of fanins of the node Bbl_ObjSop() returns the SOP representation of the node, as described above. A special attention should be given to the representation of object IDs after mapping. Recall that when the outgoing BBLIF network is constructed, the IDs of objects are assigned by the calling application and given to the BBLIF manager when procedure Bbl_ManCreateObject() is called. We refer to these object IDs as "original IDs of the objects". When the network has been given to ABC, mapped, and returned to the calling application in the incoming BBLIF file, only CIs and COs are guaranteed to preserve their "original IDs". Other objects may be created during synthesis/mapping. The original IDs of these objects are set to -1. The following two APIs are used to return the IDs of objects after mapping: Bbl_ObjId() returns the new ID (useful to construct network after mapping) Bbl_ObjIdOriginal() returns the original ID (or -1 if this is a new object). !!!***!!! Note: The original ID currently cannot be returned by Bbl_ObjIdOriginal(). It is recommended to use the work-around described below. !!!***!!! The original ID is useful to map CIs/COs after mapping into CIs/COs before mapping. However, the order of CIs/COs after mapping in the incoming network is the same as the order of their creation by the calling application in the outgoing network. This allows for a workaround that does not have the need for the original IDs. We can simply iterate through the objects after mapping, and create CIs and COs in the order of their appearance, and this order is guaranteed to be the same as the order of their construction by the calling application. It is also worth noting that currently the internal node names are not preserved by ABC during synthesis. This may change in the future. and then some of the internal nodes will preserve their IDs, which may allow the calling application to reconstruct the names of some of the nodes after synthesis/mapping in ABC using their original IDs whenever available. Finally, iterator Bbl_ObjForEachFanin() can be used to iterate through the fanins of each mapped object. For CIs, there will be no fanins. For COs, there will be exactly one fanin. For the internal nodes (LUTs) the number of fanins is the number of inputs of these nodes. A demo of using this interface is included at the bottom of file "bblif.c" in procedure Bbl_ManSimpleDemo(). Additional examples can be found in the files "abc\src\base\io\ioReadBblif.c" and "abc\src\base\io\ioWriteBblif.c". These files illustrate how an ABC network is created from the BBLIF data manager and how the data manager is created from the ABC network. Note that only the files "bblif.h" and "bblif.c" are needed for interfacing the user's application with ABC, while other files should not be compiled as part of the application code. Finally, a warning regarding endianness. The interface may not work if the BBLIF file is produced on a machine whose engianness is different from the machine, which is reading this file. */ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #ifdef _WIN32 #define inline __inline #endif //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // object types typedef enum { BBL_OBJ_NONE, // 0: non-existent object BBL_OBJ_CI, // 1: primary input BBL_OBJ_CO, // 2: primary output BBL_OBJ_NODE, // 3: buffer node BBL_OBJ_VOID // 4: unused object } Bbl_Type_t; // data manager typedef struct Bbl_Man_t_ Bbl_Man_t; // data object typedef struct Bbl_Obj_t_ Bbl_Obj_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // (1) creating the data manager in the application code extern Bbl_Man_t * Bbl_ManStart( char * pName ); extern void Bbl_ManCreateObject( Bbl_Man_t * p, Bbl_Type_t Type, int ObjId, int nFanins, char * pSop ); extern void Bbl_ManAddFanin( Bbl_Man_t * p, int ObjId, int FaninId ); extern int Bbl_ManCheck( Bbl_Man_t * p ); extern void Bbl_ManPrintStats( Bbl_Man_t * p ); extern void Bbl_ManStop( Bbl_Man_t * p ); // (2) writing the data manager into file extern void Bbl_ManDumpBinaryBlif( Bbl_Man_t * p, char * pFileName ); // (3) reading the data manager from file extern Bbl_Man_t * Bbl_ManReadBinaryBlif( char * pFileName ); // (4) returning the mapped network after reading the data manaager from file extern char * Bbl_ManName( Bbl_Man_t * p ); extern int Bbl_ObjIsInput( Bbl_Obj_t * p ); extern int Bbl_ObjIsOutput( Bbl_Obj_t * p ); extern int Bbl_ObjIsLut( Bbl_Obj_t * p ); extern int Bbl_ObjId( Bbl_Obj_t * p ); extern int Bbl_ObjIdOriginal( Bbl_Man_t * pMan, Bbl_Obj_t * p ); extern int Bbl_ObjFaninNumber( Bbl_Obj_t * p ); extern char * Bbl_ObjSop( Bbl_Man_t * pMan, Bbl_Obj_t * p ); // for the use in iterators only extern Bbl_Obj_t * Bbl_ManObjFirst( Bbl_Man_t * p ); extern Bbl_Obj_t * Bbl_ManObjNext( Bbl_Man_t * p, Bbl_Obj_t * pObj ); extern Bbl_Obj_t * Bbl_ObjFaninFirst( Bbl_Obj_t * p ); extern Bbl_Obj_t * Bbl_ObjFaninNext( Bbl_Obj_t * p, Bbl_Obj_t * pPrev ); // iterator through the objects #define Bbl_ManForEachObj( p, pObj ) \ for ( pObj = Bbl_ManObjFirst(p); pObj; pObj = Bbl_ManObjNext(p, pObj) ) // iterator through the fanins fo the an object #define Bbl_ObjForEachFanin( pObj, pFanin ) \ for ( pFanin = Bbl_ObjFaninFirst(pObj); pFanin; pFanin = Bbl_ObjFaninNext(pObj, pFanin) ) // these additional procedures are provided to transform truth tables into SOPs, and vice versa extern char * Bbl_ManTruthToSop( unsigned * pTruth, int nVars ); extern unsigned * Bbl_ManSopToTruth( char * pSop, int nVars ); // write text BLIF file for debugging extern void Bbl_ManDumpBlif( Bbl_Man_t * p, char * pFileName ); // a simple demo procedure extern void Bbl_ManSimpleDemo(); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bbl/module.make000066400000000000000000000000351300674244400236500ustar00rootroot00000000000000SRC += src/misc/bbl/bblif.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/000077500000000000000000000000001300674244400220715ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/CHANGES000066400000000000000000000257671300674244400231050ustar00rootroot00000000000000 ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ 0.9.0 ~~~~~ First version. 0.9.0a ~~~~~~ Removed 'ranlib' from Makefile, since most modern Unix-es don't need it, or even know about it. 0.9.0b ~~~~~~ Fixed a problem with error reporting in bzip2.c. This does not effect the library in any way. Problem is: versions 0.9.0 and 0.9.0a (of the program proper) compress and decompress correctly, but give misleading error messages (internal panics) when an I/O error occurs, instead of reporting the problem correctly. This shouldn't give any data loss (as far as I can see), but is confusing. Made the inline declarations disappear for non-GCC compilers. 0.9.0c ~~~~~~ Fixed some problems in the library pertaining to some boundary cases. This makes the library behave more correctly in those situations. The fixes apply only to features (calls and parameters) not used by bzip2.c, so the non-fixedness of them in previous versions has no effect on reliability of bzip2.c. In bzlib.c: * made zero-length BZ_FLUSH work correctly in bzCompress(). * fixed bzWrite/bzRead to ignore zero-length requests. * fixed bzread to correctly handle read requests after EOF. * wrong parameter order in call to bzDecompressInit in bzBuffToBuffDecompress. Fixed. In compress.c: * changed setting of nGroups in sendMTFValues() so as to do a bit better on small files. This _does_ effect bzip2.c. 0.9.5a ~~~~~~ Major change: add a fallback sorting algorithm (blocksort.c) to give reasonable behaviour even for very repetitive inputs. Nuked --repetitive-best and --repetitive-fast since they are no longer useful. Minor changes: mostly a whole bunch of small changes/ bugfixes in the driver (bzip2.c). Changes pertaining to the user interface are: allow decompression of symlink'd files to stdout decompress/test files even without .bz2 extension give more accurate error messages for I/O errors when compressing/decompressing to stdout, don't catch control-C read flags from BZIP2 and BZIP environment variables decline to break hard links to a file unless forced with -f allow -c flag even with no filenames preserve file ownerships as far as possible make -s -1 give the expected block size (100k) add a flag -q --quiet to suppress nonessential warnings stop decoding flags after --, so files beginning in - can be handled resolved inconsistent naming: bzcat or bz2cat ? bzip2 --help now returns 0 Programming-level changes are: fixed syntax error in GET_LL4 for Borland C++ 5.02 let bzBuffToBuffDecompress return BZ_DATA_ERROR{_MAGIC} fix overshoot of mode-string end in bzopen_or_bzdopen wrapped bzlib.h in #ifdef __cplusplus ... extern "C" { ... } close file handles under all error conditions added minor mods so it compiles with DJGPP out of the box fixed Makefile so it doesn't give problems with BSD make fix uninitialised memory reads in dlltest.c 0.9.5b ~~~~~~ Open stdin/stdout in binary mode for DJGPP. 0.9.5c ~~~~~~ Changed BZ_N_OVERSHOOT to be ... + 2 instead of ... + 1. The + 1 version could cause the sorted order to be wrong in some extremely obscure cases. Also changed setting of quadrant in blocksort.c. 0.9.5d ~~~~~~ The only functional change is to make bzlibVersion() in the library return the correct string. This has no effect whatsoever on the functioning of the bzip2 program or library. Added a couple of casts so the library compiles without warnings at level 3 in MS Visual Studio 6.0. Included a Y2K statement in the file Y2K_INFO. All other changes are minor documentation changes. 1.0 ~~~ Several minor bugfixes and enhancements: * Large file support. The library uses 64-bit counters to count the volume of data passing through it. bzip2.c is now compiled with -D_FILE_OFFSET_BITS=64 to get large file support from the C library. -v correctly prints out file sizes greater than 4 gigabytes. All these changes have been made without assuming a 64-bit platform or a C compiler which supports 64-bit ints, so, except for the C library aspect, they are fully portable. * Decompression robustness. The library/program should be robust to any corruption of compressed data, detecting and handling _all_ corruption, instead of merely relying on the CRCs. What this means is that the program should never crash, given corrupted data, and the library should always return BZ_DATA_ERROR. * Fixed an obscure race-condition bug only ever observed on Solaris, in which, if you were very unlucky and issued control-C at exactly the wrong time, both input and output files would be deleted. * Don't run out of file handles on test/decompression when large numbers of files have invalid magic numbers. * Avoid library namespace pollution. Prefix all exported symbols with BZ2_. * Minor sorting enhancements from my DCC2000 paper. * Advance the version number to 1.0, so as to counteract the (false-in-this-case) impression some people have that programs with version numbers less than 1.0 are in some way, experimental, pre-release versions. * Create an initial Makefile-libbz2_so to build a shared library. Yes, I know I should really use libtool et al ... * Make the program exit with 2 instead of 0 when decompression fails due to a bad magic number (ie, an invalid bzip2 header). Also exit with 1 (as the manual claims :-) whenever a diagnostic message would have been printed AND the corresponding operation is aborted, for example bzip2: Output file xx already exists. When a diagnostic message is printed but the operation is not aborted, for example bzip2: Can't guess original name for wurble -- using wurble.out then the exit value 0 is returned, unless some other problem is also detected. I think it corresponds more closely to what the manual claims now. 1.0.1 ~~~~~ * Modified dlltest.c so it uses the new BZ2_ naming scheme. * Modified makefile-msc to fix minor build probs on Win2k. * Updated README.COMPILATION.PROBLEMS. There are no functionality changes or bug fixes relative to version 1.0.0. This is just a documentation update + a fix for minor Win32 build problems. For almost everyone, upgrading from 1.0.0 to 1.0.1 is utterly pointless. Don't bother. 1.0.2 ~~~~~ A bug fix release, addressing various minor issues which have appeared in the 18 or so months since 1.0.1 was released. Most of the fixes are to do with file-handling or documentation bugs. To the best of my knowledge, there have been no data-loss-causing bugs reported in the compression/decompression engine of 1.0.0 or 1.0.1. Note that this release does not improve the rather crude build system for Unix platforms. The general plan here is to autoconfiscate/ libtoolise 1.0.2 soon after release, and release the result as 1.1.0 or perhaps 1.2.0. That, however, is still just a plan at this point. Here are the changes in 1.0.2. Bug-reporters and/or patch-senders in parentheses. * Fix an infinite segfault loop in 1.0.1 when a directory is encountered in -f (force) mode. (Trond Eivind Glomsrod, Nicholas Nethercote, Volker Schmidt) * Avoid double fclose() of output file on certain I/O error paths. (Solar Designer) * Don't fail with internal error 1007 when fed a long stream (> 48MB) of byte 251. Also print useful message suggesting that 1007s may be caused by bad memory. (noticed by Juan Pedro Vallejo, fixed by me) * Fix uninitialised variable silly bug in demo prog dlltest.c. (Jorj Bauer) * Remove 512-MB limitation on recovered file size for bzip2recover on selected platforms which support 64-bit ints. At the moment all GCC supported platforms, and Win32. (me, Alson van der Meulen) * Hard-code header byte values, to give correct operation on platforms using EBCDIC as their native character set (IBM's OS/390). (Leland Lucius) * Copy file access times correctly. (Marty Leisner) * Add distclean and check targets to Makefile. (Michael Carmack) * Parameterise use of ar and ranlib in Makefile. Also add $(LDFLAGS). (Rich Ireland, Bo Thorsen) * Pass -p (create parent dirs as needed) to mkdir during make install. (Jeremy Fusco) * Dereference symlinks when copying file permissions in -f mode. (Volker Schmidt) * Majorly simplify implementation of uInt64_qrm10. (Bo Lindbergh) * Check the input file still exists before deleting the output one, when aborting in cleanUpAndFail(). (Joerg Prante, Robert Linden, Matthias Krings) Also a bunch of patches courtesy of Philippe Troin, the Debian maintainer of bzip2: * Wrapper scripts (with manpages): bzdiff, bzgrep, bzmore. * Spelling changes and minor enhancements in bzip2.1. * Avoid race condition between creating the output file and setting its interim permissions safely, by using fopen_output_safely(). No changes to bzip2recover since there is no issue with file permissions there. * do not print senseless report with -v when compressing an empty file. * bzcat -f works on non-bzip2 files. * do not try to escape shell meta-characters on unix (the shell takes care of these). * added --fast and --best aliases for -1 -9 for gzip compatibility. 1.0.3 (15 Feb 05) ~~~~~~~~~~~~~~~~~ Fixes some minor bugs since the last version, 1.0.2. * Further robustification against corrupted compressed data. There are currently no known bitstreams which can cause the decompressor to crash, loop or access memory which does not belong to it. If you are using bzip2 or the library to decompress bitstreams from untrusted sources, an upgrade to 1.0.3 is recommended. This fixes CAN-2005-1260. * The documentation has been converted to XML, from which html and pdf can be derived. * Various minor bugs in the documentation have been fixed. * Fixes for various compilation warnings with newer versions of gcc, and on 64-bit platforms. * The BZ_NO_STDIO cpp symbol was not properly observed in 1.0.2. This has been fixed. 1.0.4 (20 Dec 06) ~~~~~~~~~~~~~~~~~ Fixes some minor bugs since the last version, 1.0.3. * Fix file permissions race problem (CAN-2005-0953). * Avoid possible segfault in BZ2_bzclose. From Coverity's NetBSD scan. * 'const'/prototype cleanups in the C code. * Change default install location to /usr/local, and handle multiple 'make install's without error. * Sanitise file names more carefully in bzgrep. Fixes CAN-2005-0758 to the extent that applies to bzgrep. * Use 'mktemp' rather than 'tempfile' in bzdiff. * Tighten up a couple of assertions in blocksort.c following automated analysis. * Fix minor doc/comment bugs. 1.0.5 (10 Dec 07) ~~~~~~~~~~~~~~~~~ Security fix only. Fixes CERT-FI 20469 as it applies to bzip2. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/LICENSE000066400000000000000000000035551300674244400231060ustar00rootroot00000000000000 -------------------------------------------------------------------------- This program, "bzip2", the associated library "libbzip2", and all documentation, are copyright (C) 1996-2007 Julian R Seward. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Julian Seward, jseward@bzip.org bzip2/libbzip2 version 1.0.5 of 10 December 2007 -------------------------------------------------------------------------- berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/blocksort.c000066400000000000000000000740301300674244400242430ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Block sorting machinery ---*/ /*--- blocksort.c ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ #include "bzlib_private.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------*/ /*--- Fallback O(N log(N)^2) sorting ---*/ /*--- algorithm, for repetitive blocks ---*/ /*---------------------------------------------*/ /*---------------------------------------------*/ static __inline__ void fallbackSimpleSort ( UInt32* fmap, UInt32* eclass, Int32 lo, Int32 hi ) { Int32 i, j, tmp; UInt32 ec_tmp; if (lo == hi) return; if (hi - lo > 3) { for ( i = hi-4; i >= lo; i-- ) { tmp = fmap[i]; ec_tmp = eclass[tmp]; for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) fmap[j-4] = fmap[j]; fmap[j-4] = tmp; } } for ( i = hi-1; i >= lo; i-- ) { tmp = fmap[i]; ec_tmp = eclass[tmp]; for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) fmap[j-1] = fmap[j]; fmap[j-1] = tmp; } } /*---------------------------------------------*/ #define fswap(zz1, zz2) \ { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } #define fvswap(zzp1, zzp2, zzn) \ { \ Int32 yyp1 = (zzp1); \ Int32 yyp2 = (zzp2); \ Int32 yyn = (zzn); \ while (yyn > 0) { \ fswap(fmap[yyp1], fmap[yyp2]); \ yyp1++; yyp2++; yyn--; \ } \ } #define fmin(a,b) ((a) < (b)) ? (a) : (b) #define fpush(lz,hz) { stackLo[sp] = lz; \ stackHi[sp] = hz; \ sp++; } #define fpop(lz,hz) { sp--; \ lz = stackLo[sp]; \ hz = stackHi[sp]; } #define FALLBACK_QSORT_SMALL_THRESH 10 #define FALLBACK_QSORT_STACK_SIZE 100 static void fallbackQSort3 ( UInt32* fmap, UInt32* eclass, Int32 loSt, Int32 hiSt ) { Int32 unLo, unHi, ltLo, gtHi, n, m; Int32 sp, lo, hi; UInt32 med, r, r3; Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; r = 0; sp = 0; fpush ( loSt, hiSt ); while (sp > 0) { AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 ); fpop ( lo, hi ); if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { fallbackSimpleSort ( fmap, eclass, lo, hi ); continue; } /* Random partitioning. Median of 3 sometimes fails to avoid bad cases. Median of 9 seems to help but looks rather expensive. This too seems to work but is cheaper. Guidance for the magic constants 7621 and 32768 is taken from Sedgewick's algorithms book, chapter 35. */ r = ((r * 7621) + 1) % 32768; r3 = r % 3; if (r3 == 0) med = eclass[fmap[lo]]; else if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else med = eclass[fmap[hi]]; unLo = ltLo = lo; unHi = gtHi = hi; while (1) { while (1) { if (unLo > unHi) break; n = (Int32)eclass[fmap[unLo]] - (Int32)med; if (n == 0) { fswap(fmap[unLo], fmap[ltLo]); ltLo++; unLo++; continue; }; if (n > 0) break; unLo++; } while (1) { if (unLo > unHi) break; n = (Int32)eclass[fmap[unHi]] - (Int32)med; if (n == 0) { fswap(fmap[unHi], fmap[gtHi]); gtHi--; unHi--; continue; }; if (n < 0) break; unHi--; } if (unLo > unHi) break; fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; } AssertD ( unHi == unLo-1, "fallbackQSort3(2)" ); if (gtHi < ltLo) continue; n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); n = lo + unLo - ltLo - 1; m = hi - (gtHi - unHi) + 1; if (n - lo > hi - m) { fpush ( lo, n ); fpush ( m, hi ); } else { fpush ( m, hi ); fpush ( lo, n ); } } } #undef fmin #undef fpush #undef fpop #undef fswap #undef fvswap #undef FALLBACK_QSORT_SMALL_THRESH #undef FALLBACK_QSORT_STACK_SIZE /*---------------------------------------------*/ /* Pre: nblock > 0 eclass exists for [0 .. nblock-1] ((UChar*)eclass) [0 .. nblock-1] holds block ptr exists for [0 .. nblock-1] Post: ((UChar*)eclass) [0 .. nblock-1] holds block All other areas of eclass destroyed fmap [0 .. nblock-1] holds sorted order bhtab [ 0 .. 2+(nblock/32) ] destroyed */ #define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) #define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) #define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) #define WORD_BH(zz) bhtab[(zz) >> 5] #define UNALIGNED_BH(zz) ((zz) & 0x01f) static void fallbackSort ( UInt32* fmap, UInt32* eclass, UInt32* bhtab, Int32 nblock, Int32 verb ) { Int32 ftab[257]; Int32 ftabCopy[256]; Int32 H, i, j, k, l, r, cc, cc1; Int32 nNotDone; Int32 nBhtab; UChar* eclass8 = (UChar*)eclass; /*-- Initial 1-char radix sort to generate initial fmap and initial BH bits. --*/ if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" ); for (i = 0; i < 257; i++) ftab[i] = 0; for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; for (i = 0; i < nblock; i++) { j = eclass8[i]; k = ftab[j] - 1; ftab[j] = k; fmap[k] = i; } nBhtab = 2 + (nblock / 32); for (i = 0; i < nBhtab; i++) bhtab[i] = 0; for (i = 0; i < 256; i++) SET_BH(ftab[i]); /*-- Inductively refine the buckets. Kind-of an "exponential radix sort" (!), inspired by the Manber-Myers suffix array construction algorithm. --*/ /*-- set sentinel bits for block-end detection --*/ for (i = 0; i < 32; i++) { SET_BH(nblock + 2*i); CLEAR_BH(nblock + 2*i + 1); } /*-- the log(N) loop --*/ H = 1; while (1) { if (verb >= 4) VPrintf1 ( " depth %6d has ", H ); j = 0; for (i = 0; i < nblock; i++) { if (ISSET_BH(i)) j = i; k = fmap[i] - H; if (k < 0) k += nblock; eclass[k] = j; } nNotDone = 0; r = -1; while (1) { /*-- find the next non-singleton bucket --*/ k = r + 1; while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; if (ISSET_BH(k)) { while (WORD_BH(k) == 0xffffffff) k += 32; while (ISSET_BH(k)) k++; } l = k - 1; if (l >= nblock) break; while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; if (!ISSET_BH(k)) { while (WORD_BH(k) == 0x00000000) k += 32; while (!ISSET_BH(k)) k++; } r = k - 1; if (r >= nblock) break; /*-- now [l, r] bracket current bucket --*/ if (r > l) { nNotDone += (r - l + 1); fallbackQSort3 ( fmap, eclass, l, r ); /*-- scan bucket and generate header bits-- */ cc = -1; for (i = l; i <= r; i++) { cc1 = eclass[fmap[i]]; if (cc != cc1) { SET_BH(i); cc = cc1; }; } } } if (verb >= 4) VPrintf1 ( "%6d unresolved strings\n", nNotDone ); H *= 2; if (H > nblock || nNotDone == 0) break; } /*-- Reconstruct the original block in eclass8 [0 .. nblock-1], since the previous phase destroyed it. --*/ if (verb >= 4) VPrintf0 ( " reconstructing block ...\n" ); j = 0; for (i = 0; i < nblock; i++) { while (ftabCopy[j] == 0) j++; ftabCopy[j]--; eclass8[fmap[i]] = (UChar)j; } AssertH ( j < 256, 1005 ); } #undef SET_BH #undef CLEAR_BH #undef ISSET_BH #undef WORD_BH #undef UNALIGNED_BH /*---------------------------------------------*/ /*--- The main, O(N^2 log(N)) sorting ---*/ /*--- algorithm. Faster for "normal" ---*/ /*--- non-repetitive blocks. ---*/ /*---------------------------------------------*/ /*---------------------------------------------*/ static __inline__ Bool mainGtU ( UInt32 i1, UInt32 i2, UChar* block, UInt16* quadrant, UInt32 nblock, Int32* budget ) { Int32 k; UChar c1, c2; UInt16 s1, s2; AssertD ( i1 != i2, "mainGtU" ); /* 1 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 2 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 3 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 4 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 5 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 6 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 7 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 8 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 9 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 10 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 11 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; /* 12 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); i1++; i2++; k = nblock + 8; do { /* 1 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); s1 = quadrant[i1]; s2 = quadrant[i2]; if (s1 != s2) return (s1 > s2); i1++; i2++; /* 2 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); s1 = quadrant[i1]; s2 = quadrant[i2]; if (s1 != s2) return (s1 > s2); i1++; i2++; /* 3 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); s1 = quadrant[i1]; s2 = quadrant[i2]; if (s1 != s2) return (s1 > s2); i1++; i2++; /* 4 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); s1 = quadrant[i1]; s2 = quadrant[i2]; if (s1 != s2) return (s1 > s2); i1++; i2++; /* 5 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); s1 = quadrant[i1]; s2 = quadrant[i2]; if (s1 != s2) return (s1 > s2); i1++; i2++; /* 6 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); s1 = quadrant[i1]; s2 = quadrant[i2]; if (s1 != s2) return (s1 > s2); i1++; i2++; /* 7 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); s1 = quadrant[i1]; s2 = quadrant[i2]; if (s1 != s2) return (s1 > s2); i1++; i2++; /* 8 */ c1 = block[i1]; c2 = block[i2]; if (c1 != c2) return (c1 > c2); s1 = quadrant[i1]; s2 = quadrant[i2]; if (s1 != s2) return (s1 > s2); i1++; i2++; if (i1 >= nblock) i1 -= nblock; if (i2 >= nblock) i2 -= nblock; k -= 8; (*budget)--; } while (k >= 0); return False; } /*---------------------------------------------*/ /*-- Knuth's increments seem to work better than Incerpi-Sedgewick here. Possibly because the number of elems to sort is usually small, typically <= 20. --*/ static Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484 }; static void mainSimpleSort ( UInt32* ptr, UChar* block, UInt16* quadrant, Int32 nblock, Int32 lo, Int32 hi, Int32 d, Int32* budget ) { Int32 i, j, h, bigN, hp; UInt32 v; bigN = hi - lo + 1; if (bigN < 2) return; hp = 0; while (incs[hp] < bigN) hp++; hp--; for (; hp >= 0; hp--) { h = incs[hp]; i = lo + h; while (True) { /*-- copy 1 --*/ if (i > hi) break; v = ptr[i]; j = i; while ( mainGtU ( ptr[j-h]+d, v+d, block, quadrant, nblock, budget ) ) { ptr[j] = ptr[j-h]; j = j - h; if (j <= (lo + h - 1)) break; } ptr[j] = v; i++; /*-- copy 2 --*/ if (i > hi) break; v = ptr[i]; j = i; while ( mainGtU ( ptr[j-h]+d, v+d, block, quadrant, nblock, budget ) ) { ptr[j] = ptr[j-h]; j = j - h; if (j <= (lo + h - 1)) break; } ptr[j] = v; i++; /*-- copy 3 --*/ if (i > hi) break; v = ptr[i]; j = i; while ( mainGtU ( ptr[j-h]+d, v+d, block, quadrant, nblock, budget ) ) { ptr[j] = ptr[j-h]; j = j - h; if (j <= (lo + h - 1)) break; } ptr[j] = v; i++; if (*budget < 0) return; } } } /*---------------------------------------------*/ /*-- The following is an implementation of an elegant 3-way quicksort for strings, described in a paper "Fast Algorithms for Sorting and Searching Strings", by Robert Sedgewick and Jon L. Bentley. --*/ #define mswap(zz1, zz2) \ { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } #define mvswap(zzp1, zzp2, zzn) \ { \ Int32 yyp1 = (zzp1); \ Int32 yyp2 = (zzp2); \ Int32 yyn = (zzn); \ while (yyn > 0) { \ mswap(ptr[yyp1], ptr[yyp2]); \ yyp1++; yyp2++; yyn--; \ } \ } static __inline__ UChar mmed3 ( UChar a, UChar b, UChar c ) { UChar t; if (a > b) { t = a; a = b; b = t; }; if (b > c) { b = c; if (a > b) b = a; } return b; } #define mmin(a,b) ((a) < (b)) ? (a) : (b) #define mpush(lz,hz,dz) { stackLo[sp] = lz; \ stackHi[sp] = hz; \ stackD [sp] = dz; \ sp++; } #define mpop(lz,hz,dz) { sp--; \ lz = stackLo[sp]; \ hz = stackHi[sp]; \ dz = stackD [sp]; } #define mnextsize(az) (nextHi[az]-nextLo[az]) #define mnextswap(az,bz) \ { Int32 tz; \ tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } #define MAIN_QSORT_SMALL_THRESH 20 #define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) #define MAIN_QSORT_STACK_SIZE 100 static void mainQSort3 ( UInt32* ptr, UChar* block, UInt16* quadrant, Int32 nblock, Int32 loSt, Int32 hiSt, Int32 dSt, Int32* budget ) { Int32 unLo, unHi, ltLo, gtHi, n, m, med; Int32 sp, lo, hi, d; Int32 stackLo[MAIN_QSORT_STACK_SIZE]; Int32 stackHi[MAIN_QSORT_STACK_SIZE]; Int32 stackD [MAIN_QSORT_STACK_SIZE]; Int32 nextLo[3]; Int32 nextHi[3]; Int32 nextD [3]; sp = 0; mpush ( loSt, hiSt, dSt ); while (sp > 0) { AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 ); mpop ( lo, hi, d ); if (hi - lo < MAIN_QSORT_SMALL_THRESH || d > MAIN_QSORT_DEPTH_THRESH) { mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); if (*budget < 0) return; continue; } med = (Int32) mmed3 ( block[ptr[ lo ]+d], block[ptr[ hi ]+d], block[ptr[ (lo+hi)>>1 ]+d] ); unLo = ltLo = lo; unHi = gtHi = hi; while (True) { while (True) { if (unLo > unHi) break; n = ((Int32)block[ptr[unLo]+d]) - med; if (n == 0) { mswap(ptr[unLo], ptr[ltLo]); ltLo++; unLo++; continue; }; if (n > 0) break; unLo++; } while (True) { if (unLo > unHi) break; n = ((Int32)block[ptr[unHi]+d]) - med; if (n == 0) { mswap(ptr[unHi], ptr[gtHi]); gtHi--; unHi--; continue; }; if (n < 0) break; unHi--; } if (unLo > unHi) break; mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; } AssertD ( unHi == unLo-1, "mainQSort3(2)" ); if (gtHi < ltLo) { mpush(lo, hi, d+1 ); continue; } n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); n = lo + unLo - ltLo - 1; m = hi - (gtHi - unHi) + 1; nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" ); AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" ); mpush (nextLo[0], nextHi[0], nextD[0]); mpush (nextLo[1], nextHi[1], nextD[1]); mpush (nextLo[2], nextHi[2], nextD[2]); } } #undef mswap #undef mvswap #undef mpush #undef mpop #undef mmin #undef mnextsize #undef mnextswap #undef MAIN_QSORT_SMALL_THRESH #undef MAIN_QSORT_DEPTH_THRESH #undef MAIN_QSORT_STACK_SIZE /*---------------------------------------------*/ /* Pre: nblock > N_OVERSHOOT block32 exists for [0 .. nblock-1 +N_OVERSHOOT] ((UChar*)block32) [0 .. nblock-1] holds block ptr exists for [0 .. nblock-1] Post: ((UChar*)block32) [0 .. nblock-1] holds block All other areas of block32 destroyed ftab [0 .. 65536 ] destroyed ptr [0 .. nblock-1] holds sorted order if (*budget < 0), sorting was abandoned */ #define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8]) #define SETMASK (1 << 21) #define CLEARMASK (~(SETMASK)) static void mainSort ( UInt32* ptr, UChar* block, UInt16* quadrant, UInt32* ftab, Int32 nblock, Int32 verb, Int32* budget ) { Int32 i, j, k, ss, sb; Int32 runningOrder[256]; Bool bigDone[256]; Int32 copyStart[256]; Int32 copyEnd [256]; UChar c1; Int32 numQSorted; UInt16 s; if (verb >= 4) VPrintf0 ( " main sort initialise ...\n" ); /*-- set up the 2-byte frequency table --*/ for (i = 65536; i >= 0; i--) ftab[i] = 0; j = block[0] << 8; i = nblock-1; for (; i >= 3; i -= 4) { quadrant[i] = 0; j = (j >> 8) | ( ((UInt16)block[i]) << 8); ftab[j]++; quadrant[i-1] = 0; j = (j >> 8) | ( ((UInt16)block[i-1]) << 8); ftab[j]++; quadrant[i-2] = 0; j = (j >> 8) | ( ((UInt16)block[i-2]) << 8); ftab[j]++; quadrant[i-3] = 0; j = (j >> 8) | ( ((UInt16)block[i-3]) << 8); ftab[j]++; } for (; i >= 0; i--) { quadrant[i] = 0; j = (j >> 8) | ( ((UInt16)block[i]) << 8); ftab[j]++; } /*-- (emphasises close relationship of block & quadrant) --*/ for (i = 0; i < BZ_N_OVERSHOOT; i++) { block [nblock+i] = block[i]; quadrant[nblock+i] = 0; } if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" ); /*-- Complete the initial radix sort --*/ for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1]; s = block[0] << 8; i = nblock-1; for (; i >= 3; i -= 4) { s = (s >> 8) | (block[i] << 8); j = ftab[s] -1; ftab[s] = j; ptr[j] = i; s = (s >> 8) | (block[i-1] << 8); j = ftab[s] -1; ftab[s] = j; ptr[j] = i-1; s = (s >> 8) | (block[i-2] << 8); j = ftab[s] -1; ftab[s] = j; ptr[j] = i-2; s = (s >> 8) | (block[i-3] << 8); j = ftab[s] -1; ftab[s] = j; ptr[j] = i-3; } for (; i >= 0; i--) { s = (s >> 8) | (block[i] << 8); j = ftab[s] -1; ftab[s] = j; ptr[j] = i; } /*-- Now ftab contains the first loc of every small bucket. Calculate the running order, from smallest to largest big bucket. --*/ for (i = 0; i <= 255; i++) { bigDone [i] = False; runningOrder[i] = i; } { Int32 vv; Int32 h = 1; do h = 3 * h + 1; while (h <= 256); do { h = h / 3; for (i = h; i <= 255; i++) { vv = runningOrder[i]; j = i; while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) { runningOrder[j] = runningOrder[j-h]; j = j - h; if (j <= (h - 1)) goto zero; } zero: runningOrder[j] = vv; } } while (h != 1); } /*-- The main sorting loop. --*/ numQSorted = 0; for (i = 0; i <= 255; i++) { /*-- Process big buckets, starting with the least full. Basically this is a 3-step process in which we call mainQSort3 to sort the small buckets [ss, j], but also make a big effort to avoid the calls if we can. --*/ ss = runningOrder[i]; /*-- Step 1: Complete the big bucket [ss] by quicksorting any unsorted small buckets [ss, j], for j != ss. Hopefully previous pointer-scanning phases have already completed many of the small buckets [ss, j], so we don't have to sort them at all. --*/ for (j = 0; j <= 255; j++) { if (j != ss) { sb = (ss << 8) + j; if ( ! (ftab[sb] & SETMASK) ) { Int32 lo = ftab[sb] & CLEARMASK; Int32 hi = (ftab[sb+1] & CLEARMASK) - 1; if (hi > lo) { if (verb >= 4) VPrintf4 ( " qsort [0x%x, 0x%x] " "done %d this %d\n", ss, j, numQSorted, hi - lo + 1 ); mainQSort3 ( ptr, block, quadrant, nblock, lo, hi, BZ_N_RADIX, budget ); numQSorted += (hi - lo + 1); if (*budget < 0) return; } } ftab[sb] |= SETMASK; } } AssertH ( !bigDone[ss], 1006 ); /*-- Step 2: Now scan this big bucket [ss] so as to synthesise the sorted order for small buckets [t, ss] for all t, including, magically, the bucket [ss,ss] too. This will avoid doing Real Work in subsequent Step 1's. --*/ { for (j = 0; j <= 255; j++) { copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK; copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; } for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { k = ptr[j]-1; if (k < 0) k += nblock; c1 = block[k]; if (!bigDone[c1]) ptr[ copyStart[c1]++ ] = k; } for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { k = ptr[j]-1; if (k < 0) k += nblock; c1 = block[k]; if (!bigDone[c1]) ptr[ copyEnd[c1]-- ] = k; } } AssertH ( (copyStart[ss]-1 == copyEnd[ss]) || /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1. Necessity for this case is demonstrated by compressing a sequence of approximately 48.5 million of character 251; 1.0.0/1.0.1 will then die here. */ (copyStart[ss] == 0 && copyEnd[ss] == nblock-1), 1007 ) for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; /*-- Step 3: The [ss] big bucket is now done. Record this fact, and update the quadrant descriptors. Remember to update quadrants in the overshoot area too, if necessary. The "if (i < 255)" test merely skips this updating for the last bucket processed, since updating for the last bucket is pointless. The quadrant array provides a way to incrementally cache sort orderings, as they appear, so as to make subsequent comparisons in fullGtU() complete faster. For repetitive blocks this makes a big difference (but not big enough to be able to avoid the fallback sorting mechanism, exponential radix sort). The precise meaning is: at all times: for 0 <= i < nblock and 0 <= j <= nblock if block[i] != block[j], then the relative values of quadrant[i] and quadrant[j] are meaningless. else { if quadrant[i] < quadrant[j] then the string starting at i lexicographically precedes the string starting at j else if quadrant[i] > quadrant[j] then the string starting at j lexicographically precedes the string starting at i else the relative ordering of the strings starting at i and j has not yet been determined. } --*/ bigDone[ss] = True; if (i < 255) { Int32 bbStart = ftab[ss << 8] & CLEARMASK; Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; Int32 shifts = 0; while ((bbSize >> shifts) > 65534) shifts++; for (j = bbSize-1; j >= 0; j--) { Int32 a2update = ptr[bbStart + j]; UInt16 qVal = (UInt16)(j >> shifts); quadrant[a2update] = qVal; if (a2update < BZ_N_OVERSHOOT) quadrant[a2update + nblock] = qVal; } AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 ); } } if (verb >= 4) VPrintf3 ( " %d pointers, %d sorted, %d scanned\n", nblock, numQSorted, nblock - numQSorted ); } #undef BIGFREQ #undef SETMASK #undef CLEARMASK /*---------------------------------------------*/ /* Pre: nblock > 0 arr2 exists for [0 .. nblock-1 +N_OVERSHOOT] ((UChar*)arr2) [0 .. nblock-1] holds block arr1 exists for [0 .. nblock-1] Post: ((UChar*)arr2) [0 .. nblock-1] holds block All other areas of block destroyed ftab [ 0 .. 65536 ] destroyed arr1 [0 .. nblock-1] holds sorted order */ void BZ2_blockSort ( EState* s ) { UInt32* ptr = s->ptr; UChar* block = s->block; UInt32* ftab = s->ftab; Int32 nblock = s->nblock; Int32 verb = s->verbosity; Int32 wfact = s->workFactor; UInt16* quadrant; Int32 budget; Int32 budgetInit; Int32 i; if (nblock < 10000) { fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); } else { /* Calculate the location for quadrant, remembering to get the alignment right. Assumes that &(block[0]) is at least 2-byte aligned -- this should be ok since block is really the first section of arr2. */ i = nblock+BZ_N_OVERSHOOT; if (i & 1) i++; quadrant = (UInt16*)(&(block[i])); /* (wfact-1) / 3 puts the default-factor-30 transition point at very roughly the same place as with v0.1 and v0.9.0. Not that it particularly matters any more, since the resulting compressed stream is now the same regardless of whether or not we use the main sort or fallback sort. */ if (wfact < 1 ) wfact = 1; if (wfact > 100) wfact = 100; budgetInit = nblock * ((wfact-1) / 3); budget = budgetInit; mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget ); if (verb >= 3) VPrintf3 ( " %d work, %d block, ratio %5.2f\n", budgetInit - budget, nblock, (float)(budgetInit - budget) / (float)(nblock==0 ? 1 : nblock) ); if (budget < 0) { if (verb >= 2) VPrintf0 ( " too repetitive; using fallback" " sorting algorithm\n" ); fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); } } s->origPtr = -1; for (i = 0; i < s->nblock; i++) if (ptr[i] == 0) { s->origPtr = i; break; }; AssertH( s->origPtr != -1, 1003 ); } /*-------------------------------------------------------------*/ /*--- end blocksort.c ---*/ /*-------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/bzip2.txt000066400000000000000000000450541300674244400236700ustar00rootroot00000000000000 NAME bzip2, bunzip2 - a block-sorting file compressor, v1.0.4 bzcat - decompresses files to stdout bzip2recover - recovers data from damaged bzip2 files SYNOPSIS bzip2 [ -cdfkqstvzVL123456789 ] [ filenames ... ] bunzip2 [ -fkvsVL ] [ filenames ... ] bzcat [ -s ] [ filenames ... ] bzip2recover filename DESCRIPTION bzip2 compresses files using the Burrows-Wheeler block sorting text compression algorithm, and Huffman coding. Compression is generally considerably better than that achieved by more conventional LZ77/LZ78-based compressors, and approaches the performance of the PPM family of sta- tistical compressors. The command-line options are deliberately very similar to those of GNU gzip, but they are not identical. bzip2 expects a list of file names to accompany the com- mand-line flags. Each file is replaced by a compressed version of itself, with the name "original_name.bz2". Each compressed file has the same modification date, per- missions, and, when possible, ownership as the correspond- ing original, so that these properties can be correctly restored at decompression time. File name handling is naive in the sense that there is no mechanism for preserv- ing original file names, permissions, ownerships or dates in filesystems which lack these concepts, or have serious file name length restrictions, such as MS-DOS. bzip2 and bunzip2 will by default not overwrite existing files. If you want this to happen, specify the -f flag. If no file names are specified, bzip2 compresses from standard input to standard output. In this case, bzip2 will decline to write compressed output to a terminal, as this would be entirely incomprehensible and therefore pointless. bunzip2 (or bzip2 -d) decompresses all specified files. Files which were not created by bzip2 will be detected and ignored, and a warning issued. bzip2 attempts to guess the filename for the decompressed file from that of the compressed file as follows: filename.bz2 becomes filename filename.bz becomes filename filename.tbz2 becomes filename.tar filename.tbz becomes filename.tar anyothername becomes anyothername.out If the file does not end in one of the recognised endings, .bz2, .bz, .tbz2 or .tbz, bzip2 complains that it cannot guess the name of the original file, and uses the original name with .out appended. As with compression, supplying no filenames causes decom- pression from standard input to standard output. bunzip2 will correctly decompress a file which is the con- catenation of two or more compressed files. The result is the concatenation of the corresponding uncompressed files. Integrity testing (-t) of concatenated compressed files is also supported. You can also compress or decompress files to the standard output by giving the -c flag. Multiple files may be com- pressed and decompressed like this. The resulting outputs are fed sequentially to stdout. Compression of multiple files in this manner generates a stream containing multi- ple compressed file representations. Such a stream can be decompressed correctly only by bzip2 version 0.9.0 or later. Earlier versions of bzip2 will stop after decom- pressing the first file in the stream. bzcat (or bzip2 -dc) decompresses all specified files to the standard output. bzip2 will read arguments from the environment variables BZIP2 and BZIP, in that order, and will process them before any arguments read from the command line. This gives a convenient way to supply default arguments. Compression is always performed, even if the compressed file is slightly larger than the original. Files of less than about one hundred bytes tend to get larger, since the compression mechanism has a constant overhead in the region of 50 bytes. Random data (including the output of most file compressors) is coded at about 8.05 bits per byte, giving an expansion of around 0.5%. As a self-check for your protection, bzip2 uses 32-bit CRCs to make sure that the decompressed version of a file is identical to the original. This guards against corrup- tion of the compressed data, and against undetected bugs in bzip2 (hopefully very unlikely). The chances of data corruption going undetected is microscopic, about one chance in four billion for each file processed. Be aware, though, that the check occurs upon decompression, so it can only tell you that something is wrong. It can't help you recover the original uncompressed data. You can use bzip2recover to try to recover data from damaged files. Return values: 0 for a normal exit, 1 for environmental problems (file not found, invalid flags, I/O errors, &c), 2 to indicate a corrupt compressed file, 3 for an internal consistency error (eg, bug) which caused bzip2 to panic. OPTIONS -c --stdout Compress or decompress to standard output. -d --decompress Force decompression. bzip2, bunzip2 and bzcat are really the same program, and the decision about what actions to take is done on the basis of which name is used. This flag overrides that mechanism, and forces bzip2 to decompress. -z --compress The complement to -d: forces compression, regardless of the invocation name. -t --test Check integrity of the specified file(s), but don't decompress them. This really performs a trial decompression and throws away the result. -f --force Force overwrite of output files. Normally, bzip2 will not overwrite existing output files. Also forces bzip2 to break hard links to files, which it otherwise wouldn't do. bzip2 normally declines to decompress files which don't have the correct magic header bytes. If forced (-f), however, it will pass such files through unmodified. This is how GNU gzip behaves. -k --keep Keep (don't delete) input files during compression or decompression. -s --small Reduce memory usage, for compression, decompression and testing. Files are decompressed and tested using a modified algorithm which only requires 2.5 bytes per block byte. This means any file can be decompressed in 2300k of memory, albeit at about half the normal speed. During compression, -s selects a block size of 200k, which limits memory use to around the same figure, at the expense of your compression ratio. In short, if your machine is low on memory (8 megabytes or less), use -s for everything. See MEMORY MANAGEMENT below. -q --quiet Suppress non-essential warning messages. Messages pertaining to I/O errors and other critical events will not be suppressed. -v --verbose Verbose mode -- show the compression ratio for each file processed. Further -v's increase the ver- bosity level, spewing out lots of information which is primarily of interest for diagnostic purposes. -L --license -V --version Display the software version, license terms and conditions. -1 (or --fast) to -9 (or --best) Set the block size to 100 k, 200 k .. 900 k when compressing. Has no effect when decompressing. See MEMORY MANAGEMENT below. The --fast and --best aliases are primarily for GNU gzip compatibility. In particular, --fast doesn't make things signifi- cantly faster. And --best merely selects the default behaviour. -- Treats all subsequent arguments as file names, even if they start with a dash. This is so you can han- dle files with names beginning with a dash, for example: bzip2 -- -myfilename. --repetitive-fast --repetitive-best These flags are redundant in versions 0.9.5 and above. They provided some coarse control over the behaviour of the sorting algorithm in earlier ver- sions, which was sometimes useful. 0.9.5 and above have an improved algorithm which renders these flags irrelevant. MEMORY MANAGEMENT bzip2 compresses large files in blocks. The block size affects both the compression ratio achieved, and the amount of memory needed for compression and decompression. The flags -1 through -9 specify the block size to be 100,000 bytes through 900,000 bytes (the default) respec- tively. At decompression time, the block size used for compression is read from the header of the compressed file, and bunzip2 then allocates itself just enough memory to decompress the file. Since block sizes are stored in compressed files, it follows that the flags -1 to -9 are irrelevant to and so ignored during decompression. Compression and decompression requirements, in bytes, can be estimated as: Compression: 400k + ( 8 x block size ) Decompression: 100k + ( 4 x block size ), or 100k + ( 2.5 x block size ) Larger block sizes give rapidly diminishing marginal returns. Most of the compression comes from the first two or three hundred k of block size, a fact worth bearing in mind when using bzip2 on small machines. It is also important to appreciate that the decompression memory requirement is set at compression time by the choice of block size. For files compressed with the default 900k block size, bunzip2 will require about 3700 kbytes to decompress. To support decompression of any file on a 4 megabyte machine, bunzip2 has an option to decompress using approximately half this amount of memory, about 2300 kbytes. Decompres- sion speed is also halved, so you should use this option only where necessary. The relevant flag is -s. In general, try and use the largest block size memory con- straints allow, since that maximises the compression achieved. Compression and decompression speed are virtu- ally unaffected by block size. Another significant point applies to files which fit in a single block -- that means most files you'd encounter using a large block size. The amount of real memory touched is proportional to the size of the file, since the file is smaller than a block. For example, compressing a file 20,000 bytes long with the flag -9 will cause the compressor to allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560 kbytes of it. Similarly, the decompressor will allocate 3700k but only touch 100k + 20000 * 4 = 180 kbytes. Here is a table which summarises the maximum memory usage for different block sizes. Also recorded is the total compressed size for 14 files of the Calgary Text Compres- sion Corpus totalling 3,141,622 bytes. This column gives some feel for how compression varies with block size. These figures tend to understate the advantage of larger block sizes for larger files, since the Corpus is domi- nated by smaller files. Compress Decompress Decompress Corpus Flag usage usage -s usage Size -1 1200k 500k 350k 914704 -2 2000k 900k 600k 877703 -3 2800k 1300k 850k 860338 -4 3600k 1700k 1100k 846899 -5 4400k 2100k 1350k 845160 -6 5200k 2500k 1600k 838626 -7 6100k 2900k 1850k 834096 -8 6800k 3300k 2100k 828642 -9 7600k 3700k 2350k 828642 RECOVERING DATA FROM DAMAGED FILES bzip2 compresses files in blocks, usually 900kbytes long. Each block is handled independently. If a media or trans- mission error causes a multi-block .bz2 file to become damaged, it may be possible to recover data from the undamaged blocks in the file. The compressed representation of each block is delimited by a 48-bit pattern, which makes it possible to find the block boundaries with reasonable certainty. Each block also carries its own 32-bit CRC, so damaged blocks can be distinguished from undamaged ones. bzip2recover is a simple program whose purpose is to search for blocks in .bz2 files, and write each block out into its own .bz2 file. You can then use bzip2 -t to test the integrity of the resulting files, and decompress those which are undamaged. bzip2recover takes a single argument, the name of the dam- aged file, and writes a number of files "rec00001file.bz2", "rec00002file.bz2", etc, containing the extracted blocks. The output filenames are designed so that the use of wildcards in subsequent pro- cessing -- for example, "bzip2 -dc rec*file.bz2 > recov- ered_data" -- processes the files in the correct order. bzip2recover should be of most use dealing with large .bz2 files, as these will contain many blocks. It is clearly futile to use it on damaged single-block files, since a damaged block cannot be recovered. If you wish to min- imise any potential data loss through media or transmis- sion errors, you might consider compressing with a smaller block size. PERFORMANCE NOTES The sorting phase of compression gathers together similar strings in the file. Because of this, files containing very long runs of repeated symbols, like "aabaabaabaab ..." (repeated several hundred times) may compress more slowly than normal. Versions 0.9.5 and above fare much better than previous versions in this respect. The ratio between worst-case and average-case compression time is in the region of 10:1. For previous versions, this figure was more like 100:1. You can use the -vvvv option to mon- itor progress in great detail, if you want. Decompression speed is unaffected by these phenomena. bzip2 usually allocates several megabytes of memory to operate in, and then charges all over it in a fairly ran- dom fashion. This means that performance, both for com- pressing and decompressing, is largely determined by the speed at which your machine can service cache misses. Because of this, small changes to the code to reduce the miss rate have been observed to give disproportionately large performance improvements. I imagine bzip2 will per- form best on machines with very large caches. CAVEATS I/O error messages are not as helpful as they could be. bzip2 tries hard to detect I/O errors and exit cleanly, but the details of what the problem is sometimes seem rather misleading. This manual page pertains to version 1.0.4 of bzip2. Com- pressed data created by this version is entirely forwards and backwards compatible with the previous public releases, versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1, 1.0.2 and 1.0.3, but with the following exception: 0.9.0 and above can correctly decompress multiple concatenated compressed files. 0.1pl2 cannot do this; it will stop after decompressing just the first file in the stream. bzip2recover versions prior to 1.0.2 used 32-bit integers to represent bit positions in compressed files, so they could not handle compressed files more than 512 megabytes long. Versions 1.0.2 and above use 64-bit ints on some platforms which support them (GNU supported targets, and Windows). To establish whether or not bzip2recover was built with such a limitation, run it without arguments. In any event you can build yourself an unlimited version if you can recompile it with MaybeUInt64 set to be an unsigned 64-bit integer. AUTHOR Julian Seward, jsewardbzip.org. http://www.bzip.org The ideas embodied in bzip2 are due to (at least) the fol- lowing people: Michael Burrows and David Wheeler (for the block sorting transformation), David Wheeler (again, for the Huffman coder), Peter Fenwick (for the structured cod- ing model in the original bzip, and many refinements), and Alistair Moffat, Radford Neal and Ian Witten (for the arithmetic coder in the original bzip). I am much indebted for their help, support and advice. See the man- ual in the source distribution for pointers to sources of documentation. Christian von Roques encouraged me to look for faster sorting algorithms, so as to speed up compres- sion. Bela Lubkin encouraged me to improve the worst-case compression performance. Donna Robinson XMLised the docu- mentation. The bz* scripts are derived from those of GNU gzip. Many people sent patches, helped with portability problems, lent machines, gave advice and were generally helpful. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/bzlib.c000066400000000000000000001324061300674244400233450ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Library top-level functions. ---*/ /*--- bzlib.c ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ /* CHANGES 0.9.0 -- original version. 0.9.0a/b -- no changes in this file. 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). fixed bzWrite/bzRead to ignore zero-length requests. fixed bzread to correctly handle read requests after EOF. wrong parameter order in call to bzDecompressInit in bzBuffToBuffDecompress. Fixed. */ #include "bzlib_private.h" #ifdef WIN32 #pragma warning(disable : 4996) #endif ABC_NAMESPACE_IMPL_START #ifdef _WIN32 #define fileno _fileno #define fdopen _fdopen #define setmode _setmode #endif /*---------------------------------------------------*/ /*--- Compression stuff ---*/ /*---------------------------------------------------*/ /*---------------------------------------------------*/ #ifndef BZ_NO_STDIO void BZ2_bz__AssertH__fail ( int errcode ) { fprintf(stderr, "\n\nbzip2/libbzip2: internal error number %d.\n" "This is a bug in bzip2/libbzip2, %s.\n" "Please report it to me at: jseward@bzip.org. If this happened\n" "when you were using some program which uses libbzip2 as a\n" "component, you should also report this bug to the author(s)\n" "of that program. Please make an effort to report this bug;\n" "timely and accurate bug reports eventually lead to higher\n" "quality software. Thanks. Julian Seward, 10 December 2007.\n\n", errcode, BZ2_bzlibVersion() ); if (errcode == 1007) { fprintf(stderr, "\n*** A special note about internal error number 1007 ***\n" "\n" "Experience suggests that a common cause of i.e. 1007\n" "is unreliable memory or other hardware. The 1007 assertion\n" "just happens to cross-check the results of huge numbers of\n" "memory reads/writes, and so acts (unintendedly) as a stress\n" "test of your memory system.\n" "\n" "I suggest the following: try compressing the file again,\n" "possibly monitoring progress in detail with the -vv flag.\n" "\n" "* If the error cannot be reproduced, and/or happens at different\n" " points in compression, you may have a flaky memory system.\n" " Try a memory-test program. I have used Memtest86\n" " (www.memtest86.com). At the time of writing it is free (GPLd).\n" " Memtest86 tests memory much more thorougly than your BIOSs\n" " power-on test, and may find failures that the BIOS doesn't.\n" "\n" "* If the error can be repeatably reproduced, this is a bug in\n" " bzip2, and I would very much like to hear about it. Please\n" " let me know, and, ideally, save a copy of the file causing the\n" " problem -- without which I will be unable to investigate it.\n" "\n" ); } exit(3); } #endif /*---------------------------------------------------*/ static int bz_config_ok ( void ) { if (sizeof(int) != 4) return 0; if (sizeof(short) != 2) return 0; if (sizeof(char) != 1) return 0; return 1; } /*---------------------------------------------------*/ static void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) { void* v = malloc ( items * size ); return v; } static void default_bzfree ( void* opaque, void* addr ) { if (addr != NULL) free ( addr ); } /*---------------------------------------------------*/ static void prepare_new_block ( EState* s ) { Int32 i; s->nblock = 0; s->numZ = 0; s->state_out_pos = 0; BZ_INITIALISE_CRC ( s->blockCRC ); for (i = 0; i < 256; i++) s->inUse[i] = False; s->blockNo++; } /*---------------------------------------------------*/ static void init_RL ( EState* s ) { s->state_in_ch = 256; s->state_in_len = 0; } static Bool isempty_RL ( EState* s ) { if (s->state_in_ch < 256 && s->state_in_len > 0) return False; else return True; } /*---------------------------------------------------*/ int BZ_API(BZ2_bzCompressInit) ( bz_stream* strm, int blockSize100k, int verbosity, int workFactor ) { Int32 n; EState* s; if (!bz_config_ok()) return BZ_CONFIG_ERROR; if (strm == NULL || blockSize100k < 1 || blockSize100k > 9 || workFactor < 0 || workFactor > 250) return BZ_PARAM_ERROR; if (workFactor == 0) workFactor = 30; if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; if (strm->bzfree == NULL) strm->bzfree = default_bzfree; s = (EState *)BZALLOC( sizeof(EState) ); if (s == NULL) return BZ_MEM_ERROR; s->strm = strm; s->arr1 = NULL; s->arr2 = NULL; s->ftab = NULL; n = 100000 * blockSize100k; s->arr1 = (unsigned *)BZALLOC( n * sizeof(UInt32) ); s->arr2 = (unsigned *)BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); s->ftab = (unsigned *)BZALLOC( 65537 * sizeof(UInt32) ); if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { if (s->arr1 != NULL) BZFREE(s->arr1); if (s->arr2 != NULL) BZFREE(s->arr2); if (s->ftab != NULL) BZFREE(s->ftab); if (s != NULL) BZFREE(s); return BZ_MEM_ERROR; } s->blockNo = 0; s->state = BZ_S_INPUT; s->mode = BZ_M_RUNNING; s->combinedCRC = 0; s->blockSize100k = blockSize100k; s->nblockMAX = 100000 * blockSize100k - 19; s->verbosity = verbosity; s->workFactor = workFactor; s->block = (UChar*)s->arr2; s->mtfv = (UInt16*)s->arr1; s->zbits = NULL; s->ptr = (UInt32*)s->arr1; strm->state = s; strm->total_in_lo32 = 0; strm->total_in_hi32 = 0; strm->total_out_lo32 = 0; strm->total_out_hi32 = 0; init_RL ( s ); prepare_new_block ( s ); return BZ_OK; } /*---------------------------------------------------*/ static void add_pair_to_block ( EState* s ) { Int32 i; UChar ch = (UChar)(s->state_in_ch); for (i = 0; i < s->state_in_len; i++) { BZ_UPDATE_CRC( s->blockCRC, ch ); } s->inUse[s->state_in_ch] = True; switch (s->state_in_len) { case 1: s->block[s->nblock] = (UChar)ch; s->nblock++; break; case 2: s->block[s->nblock] = (UChar)ch; s->nblock++; s->block[s->nblock] = (UChar)ch; s->nblock++; break; case 3: s->block[s->nblock] = (UChar)ch; s->nblock++; s->block[s->nblock] = (UChar)ch; s->nblock++; s->block[s->nblock] = (UChar)ch; s->nblock++; break; default: s->inUse[s->state_in_len-4] = True; s->block[s->nblock] = (UChar)ch; s->nblock++; s->block[s->nblock] = (UChar)ch; s->nblock++; s->block[s->nblock] = (UChar)ch; s->nblock++; s->block[s->nblock] = (UChar)ch; s->nblock++; s->block[s->nblock] = ((UChar)(s->state_in_len-4)); s->nblock++; break; } } /*---------------------------------------------------*/ static void flush_RL ( EState* s ) { if (s->state_in_ch < 256) add_pair_to_block ( s ); init_RL ( s ); } /*---------------------------------------------------*/ #define ADD_CHAR_TO_BLOCK(zs,zchh0) \ { \ UInt32 zchh = (UInt32)(zchh0); \ /*-- fast track the common case --*/ \ if (zchh != zs->state_in_ch && \ zs->state_in_len == 1) { \ UChar ch = (UChar)(zs->state_in_ch); \ BZ_UPDATE_CRC( zs->blockCRC, ch ); \ zs->inUse[zs->state_in_ch] = True; \ zs->block[zs->nblock] = (UChar)ch; \ zs->nblock++; \ zs->state_in_ch = zchh; \ } \ else \ /*-- general, uncommon cases --*/ \ if (zchh != zs->state_in_ch || \ zs->state_in_len == 255) { \ if (zs->state_in_ch < 256) \ add_pair_to_block ( zs ); \ zs->state_in_ch = zchh; \ zs->state_in_len = 1; \ } else { \ zs->state_in_len++; \ } \ } /*---------------------------------------------------*/ static Bool copy_input_until_stop ( EState* s ) { Bool progress_in = False; if (s->mode == BZ_M_RUNNING) { /*-- fast track the common case --*/ while (True) { /*-- block full? --*/ if (s->nblock >= s->nblockMAX) break; /*-- no input? --*/ if (s->strm->avail_in == 0) break; progress_in = True; ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); s->strm->next_in++; s->strm->avail_in--; s->strm->total_in_lo32++; if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; } } else { /*-- general, uncommon case --*/ while (True) { /*-- block full? --*/ if (s->nblock >= s->nblockMAX) break; /*-- no input? --*/ if (s->strm->avail_in == 0) break; /*-- flush/finish end? --*/ if (s->avail_in_expect == 0) break; progress_in = True; ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); s->strm->next_in++; s->strm->avail_in--; s->strm->total_in_lo32++; if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; s->avail_in_expect--; } } return progress_in; } /*---------------------------------------------------*/ static Bool copy_output_until_stop ( EState* s ) { Bool progress_out = False; while (True) { /*-- no output space? --*/ if (s->strm->avail_out == 0) break; /*-- block done? --*/ if (s->state_out_pos >= s->numZ) break; progress_out = True; *(s->strm->next_out) = s->zbits[s->state_out_pos]; s->state_out_pos++; s->strm->avail_out--; s->strm->next_out++; s->strm->total_out_lo32++; if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; } return progress_out; } /*---------------------------------------------------*/ static Bool handle_compress ( bz_stream* strm ) { Bool progress_in = False; Bool progress_out = False; EState* s = (EState *)strm->state; while (True) { if (s->state == BZ_S_OUTPUT) { progress_out |= copy_output_until_stop ( s ); if (s->state_out_pos < s->numZ) break; if (s->mode == BZ_M_FINISHING && s->avail_in_expect == 0 && isempty_RL(s)) break; prepare_new_block ( s ); s->state = BZ_S_INPUT; if (s->mode == BZ_M_FLUSHING && s->avail_in_expect == 0 && isempty_RL(s)) break; } if (s->state == BZ_S_INPUT) { progress_in |= copy_input_until_stop ( s ); if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { flush_RL ( s ); BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); s->state = BZ_S_OUTPUT; } else if (s->nblock >= s->nblockMAX) { BZ2_compressBlock ( s, False ); s->state = BZ_S_OUTPUT; } else if (s->strm->avail_in == 0) { break; } } } return progress_in || progress_out; } /*---------------------------------------------------*/ int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) { Bool progress; EState* s; if (strm == NULL) return BZ_PARAM_ERROR; s = (EState *)strm->state; if (s == NULL) return BZ_PARAM_ERROR; if (s->strm != strm) return BZ_PARAM_ERROR; preswitch: switch (s->mode) { case BZ_M_IDLE: return BZ_SEQUENCE_ERROR; case BZ_M_RUNNING: if (action == BZ_RUN) { progress = handle_compress ( strm ); return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; } else if (action == BZ_FLUSH) { s->avail_in_expect = strm->avail_in; s->mode = BZ_M_FLUSHING; goto preswitch; } else if (action == BZ_FINISH) { s->avail_in_expect = strm->avail_in; s->mode = BZ_M_FINISHING; goto preswitch; } else return BZ_PARAM_ERROR; case BZ_M_FLUSHING: if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; if (s->avail_in_expect != s->strm->avail_in) return BZ_SEQUENCE_ERROR; progress = handle_compress ( strm ); if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ) return BZ_FLUSH_OK; s->mode = BZ_M_RUNNING; return BZ_RUN_OK; case BZ_M_FINISHING: if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; if (s->avail_in_expect != s->strm->avail_in) return BZ_SEQUENCE_ERROR; progress = handle_compress ( strm ); if (!progress) return BZ_SEQUENCE_ERROR; if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ) return BZ_FINISH_OK; s->mode = BZ_M_IDLE; return BZ_STREAM_END; } return BZ_OK; /*--not reached--*/ } /*---------------------------------------------------*/ int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) { EState* s; if (strm == NULL) return BZ_PARAM_ERROR; s = (EState *)strm->state; if (s == NULL) return BZ_PARAM_ERROR; if (s->strm != strm) return BZ_PARAM_ERROR; if (s->arr1 != NULL) BZFREE(s->arr1); if (s->arr2 != NULL) BZFREE(s->arr2); if (s->ftab != NULL) BZFREE(s->ftab); BZFREE(strm->state); strm->state = NULL; return BZ_OK; } /*---------------------------------------------------*/ /*--- Decompression stuff ---*/ /*---------------------------------------------------*/ /*---------------------------------------------------*/ int BZ_API(BZ2_bzDecompressInit) ( bz_stream* strm, int verbosity, int small ) { DState* s; if (!bz_config_ok()) return BZ_CONFIG_ERROR; if (strm == NULL) return BZ_PARAM_ERROR; if (small != 0 && small != 1) return BZ_PARAM_ERROR; if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; if (strm->bzfree == NULL) strm->bzfree = default_bzfree; s = (DState *)BZALLOC( sizeof(DState) ); if (s == NULL) return BZ_MEM_ERROR; s->strm = strm; strm->state = s; s->state = BZ_X_MAGIC_1; s->bsLive = 0; s->bsBuff = 0; s->calculatedCombinedCRC = 0; strm->total_in_lo32 = 0; strm->total_in_hi32 = 0; strm->total_out_lo32 = 0; strm->total_out_hi32 = 0; s->smallDecompress = (Bool)small; s->ll4 = NULL; s->ll16 = NULL; s->tt = NULL; s->currBlockNo = 0; s->verbosity = verbosity; return BZ_OK; } /*---------------------------------------------------*/ /* Return True iff data corruption is discovered. Returns False if there is no problem. */ static Bool unRLE_obuf_to_output_FAST ( DState* s ) { UChar k1; if (s->blockRandomised) { while (True) { /* try to finish existing run */ while (True) { if (s->strm->avail_out == 0) return False; if (s->state_out_len == 0) break; *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); s->state_out_len--; s->strm->next_out++; s->strm->avail_out--; s->strm->total_out_lo32++; if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; } /* can a new run be started? */ if (s->nblock_used == s->save_nblock+1) return False; /* Only caused by corrupt data stream? */ if (s->nblock_used > s->save_nblock+1) return True; s->state_out_len = 1; s->state_out_ch = s->k0; BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; k1 ^= BZ_RAND_MASK; s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; s->state_out_len = 2; BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; k1 ^= BZ_RAND_MASK; s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; s->state_out_len = 3; BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; k1 ^= BZ_RAND_MASK; s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; k1 ^= BZ_RAND_MASK; s->nblock_used++; s->state_out_len = ((Int32)k1) + 4; BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; s->nblock_used++; } } else { /* restore */ UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; UChar c_state_out_ch = s->state_out_ch; Int32 c_state_out_len = s->state_out_len; Int32 c_nblock_used = s->nblock_used; Int32 c_k0 = s->k0; UInt32* c_tt = s->tt; UInt32 c_tPos = s->tPos; char* cs_next_out = s->strm->next_out; unsigned int cs_avail_out = s->strm->avail_out; Int32 ro_blockSize100k = s->blockSize100k; /* end restore */ UInt32 avail_out_INIT = cs_avail_out; Int32 s_save_nblockPP = s->save_nblock+1; unsigned int total_out_lo32_old; while (True) { /* try to finish existing run */ if (c_state_out_len > 0) { while (True) { if (cs_avail_out == 0) goto return_notr; if (c_state_out_len == 1) break; *( (UChar*)(cs_next_out) ) = c_state_out_ch; BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); c_state_out_len--; cs_next_out++; cs_avail_out--; } s_state_out_len_eq_one: { if (cs_avail_out == 0) { c_state_out_len = 1; goto return_notr; }; *( (UChar*)(cs_next_out) ) = c_state_out_ch; BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); cs_next_out++; cs_avail_out--; } } /* Only caused by corrupt data stream? */ if (c_nblock_used > s_save_nblockPP) return True; /* can a new run be started? */ if (c_nblock_used == s_save_nblockPP) { c_state_out_len = 0; goto return_notr; }; c_state_out_ch = c_k0; BZ_GET_FAST_C(k1); c_nblock_used++; if (k1 != c_k0) { c_k0 = k1; goto s_state_out_len_eq_one; }; if (c_nblock_used == s_save_nblockPP) goto s_state_out_len_eq_one; c_state_out_len = 2; BZ_GET_FAST_C(k1); c_nblock_used++; if (c_nblock_used == s_save_nblockPP) continue; if (k1 != c_k0) { c_k0 = k1; continue; }; c_state_out_len = 3; BZ_GET_FAST_C(k1); c_nblock_used++; if (c_nblock_used == s_save_nblockPP) continue; if (k1 != c_k0) { c_k0 = k1; continue; }; BZ_GET_FAST_C(k1); c_nblock_used++; c_state_out_len = ((Int32)k1) + 4; BZ_GET_FAST_C(c_k0); c_nblock_used++; } return_notr: total_out_lo32_old = s->strm->total_out_lo32; s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); if (s->strm->total_out_lo32 < total_out_lo32_old) s->strm->total_out_hi32++; /* save */ s->calculatedBlockCRC = c_calculatedBlockCRC; s->state_out_ch = c_state_out_ch; s->state_out_len = c_state_out_len; s->nblock_used = c_nblock_used; s->k0 = c_k0; s->tt = c_tt; s->tPos = c_tPos; s->strm->next_out = cs_next_out; s->strm->avail_out = cs_avail_out; /* end save */ } return False; } /*---------------------------------------------------*/ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) { Int32 nb, na, mid; nb = 0; na = 256; do { mid = (nb + na) >> 1; if (indx >= cftab[mid]) nb = mid; else na = mid; } while (na - nb != 1); return nb; } /*---------------------------------------------------*/ /* Return True iff data corruption is discovered. Returns False if there is no problem. */ static Bool unRLE_obuf_to_output_SMALL ( DState* s ) { UChar k1; if (s->blockRandomised) { while (True) { /* try to finish existing run */ while (True) { if (s->strm->avail_out == 0) return False; if (s->state_out_len == 0) break; *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); s->state_out_len--; s->strm->next_out++; s->strm->avail_out--; s->strm->total_out_lo32++; if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; } /* can a new run be started? */ if (s->nblock_used == s->save_nblock+1) return False; /* Only caused by corrupt data stream? */ if (s->nblock_used > s->save_nblock+1) return True; s->state_out_len = 1; s->state_out_ch = s->k0; BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; k1 ^= BZ_RAND_MASK; s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; s->state_out_len = 2; BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; k1 ^= BZ_RAND_MASK; s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; s->state_out_len = 3; BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; k1 ^= BZ_RAND_MASK; s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; k1 ^= BZ_RAND_MASK; s->nblock_used++; s->state_out_len = ((Int32)k1) + 4; BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; s->nblock_used++; } } else { while (True) { /* try to finish existing run */ while (True) { if (s->strm->avail_out == 0) return False; if (s->state_out_len == 0) break; *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); s->state_out_len--; s->strm->next_out++; s->strm->avail_out--; s->strm->total_out_lo32++; if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; } /* can a new run be started? */ if (s->nblock_used == s->save_nblock+1) return False; /* Only caused by corrupt data stream? */ if (s->nblock_used > s->save_nblock+1) return True; s->state_out_len = 1; s->state_out_ch = s->k0; BZ_GET_SMALL(k1); s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; s->state_out_len = 2; BZ_GET_SMALL(k1); s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; s->state_out_len = 3; BZ_GET_SMALL(k1); s->nblock_used++; if (s->nblock_used == s->save_nblock+1) continue; if (k1 != s->k0) { s->k0 = k1; continue; }; BZ_GET_SMALL(k1); s->nblock_used++; s->state_out_len = ((Int32)k1) + 4; BZ_GET_SMALL(s->k0); s->nblock_used++; } } } /*---------------------------------------------------*/ int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) { Bool corrupt; DState* s; if (strm == NULL) return BZ_PARAM_ERROR; s = (DState *)strm->state; if (s == NULL) return BZ_PARAM_ERROR; if (s->strm != strm) return BZ_PARAM_ERROR; while (True) { if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; if (s->state == BZ_X_OUTPUT) { if (s->smallDecompress) corrupt = unRLE_obuf_to_output_SMALL ( s ); else corrupt = unRLE_obuf_to_output_FAST ( s ); if (corrupt) return BZ_DATA_ERROR; if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { BZ_FINALISE_CRC ( s->calculatedBlockCRC ); if (s->verbosity >= 3) VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, s->calculatedBlockCRC ); if (s->verbosity >= 2) VPrintf0 ( "]" ); if (s->calculatedBlockCRC != s->storedBlockCRC) return BZ_DATA_ERROR; s->calculatedCombinedCRC = (s->calculatedCombinedCRC << 1) | (s->calculatedCombinedCRC >> 31); s->calculatedCombinedCRC ^= s->calculatedBlockCRC; s->state = BZ_X_BLKHDR_1; } else { return BZ_OK; } } if (s->state >= BZ_X_MAGIC_1) { Int32 r = BZ2_decompress ( s ); if (r == BZ_STREAM_END) { if (s->verbosity >= 3) VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", s->storedCombinedCRC, s->calculatedCombinedCRC ); if (s->calculatedCombinedCRC != s->storedCombinedCRC) return BZ_DATA_ERROR; return r; } if (s->state != BZ_X_OUTPUT) return r; } } AssertH ( 0, 6001 ); return 0; /*NOTREACHED*/ } /*---------------------------------------------------*/ int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) { DState* s; if (strm == NULL) return BZ_PARAM_ERROR; s = (DState *)strm->state; if (s == NULL) return BZ_PARAM_ERROR; if (s->strm != strm) return BZ_PARAM_ERROR; if (s->tt != NULL) BZFREE(s->tt); if (s->ll16 != NULL) BZFREE(s->ll16); if (s->ll4 != NULL) BZFREE(s->ll4); BZFREE(strm->state); strm->state = NULL; return BZ_OK; } #ifndef BZ_NO_STDIO /*---------------------------------------------------*/ /*--- File I/O stuff ---*/ /*---------------------------------------------------*/ #define BZ_SETERR(eee) \ { \ if (bzerror != NULL) *bzerror = eee; \ if (bzf != NULL) bzf->lastErr = eee; \ } typedef struct { FILE* handle; Char buf[BZ_MAX_UNUSED]; Int32 bufN; Bool writing; bz_stream strm; Int32 lastErr; Bool initialisedOk; } bzFile; /*---------------------------------------------*/ static Bool myfeof ( FILE* f ) { Int32 c = fgetc ( f ); if (c == EOF) return True; ungetc ( c, f ); return False; } /*---------------------------------------------------*/ BZFILE* BZ_API(BZ2_bzWriteOpen) ( int* bzerror, FILE* f, int blockSize100k, int verbosity, int workFactor ) { Int32 ret; bzFile* bzf = NULL; BZ_SETERR(BZ_OK); if (f == NULL || (blockSize100k < 1 || blockSize100k > 9) || (workFactor < 0 || workFactor > 250) || (verbosity < 0 || verbosity > 4)) { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; if (ferror(f)) { BZ_SETERR(BZ_IO_ERROR); return NULL; }; bzf = (bzFile *)malloc ( sizeof(bzFile) ); if (bzf == NULL) { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; BZ_SETERR(BZ_OK); bzf->initialisedOk = False; bzf->bufN = 0; bzf->handle = f; bzf->writing = True; bzf->strm.bzalloc = NULL; bzf->strm.bzfree = NULL; bzf->strm.opaque = NULL; if (workFactor == 0) workFactor = 30; ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, verbosity, workFactor ); if (ret != BZ_OK) { BZ_SETERR(ret); free(bzf); return NULL; }; bzf->strm.avail_in = 0; bzf->initialisedOk = True; return bzf; } /*---------------------------------------------------*/ void BZ_API(BZ2_bzWrite) ( int* bzerror, BZFILE* b, void* buf, int len ) { Int32 n, n2, ret; bzFile* bzf = (bzFile*)b; BZ_SETERR(BZ_OK); if (bzf == NULL || buf == NULL || len < 0) { BZ_SETERR(BZ_PARAM_ERROR); return; }; if (!(bzf->writing)) { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; if (ferror(bzf->handle)) { BZ_SETERR(BZ_IO_ERROR); return; }; if (len == 0) { BZ_SETERR(BZ_OK); return; }; bzf->strm.avail_in = len; bzf->strm.next_in = (char *)buf; while (True) { bzf->strm.avail_out = BZ_MAX_UNUSED; bzf->strm.next_out = bzf->buf; ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); if (ret != BZ_RUN_OK) { BZ_SETERR(ret); return; }; if (bzf->strm.avail_out < BZ_MAX_UNUSED) { n = BZ_MAX_UNUSED - bzf->strm.avail_out; n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), n, bzf->handle ); if (n != n2 || ferror(bzf->handle)) { BZ_SETERR(BZ_IO_ERROR); return; }; } if (bzf->strm.avail_in == 0) { BZ_SETERR(BZ_OK); return; }; } } /*---------------------------------------------------*/ void BZ_API(BZ2_bzWriteClose) ( int* bzerror, BZFILE* b, int abandon, unsigned int* nbytes_in, unsigned int* nbytes_out ) { BZ2_bzWriteClose64 ( bzerror, b, abandon, nbytes_in, NULL, nbytes_out, NULL ); } void BZ_API(BZ2_bzWriteClose64) ( int* bzerror, BZFILE* b, int abandon, unsigned int* nbytes_in_lo32, unsigned int* nbytes_in_hi32, unsigned int* nbytes_out_lo32, unsigned int* nbytes_out_hi32 ) { Int32 n, n2, ret; bzFile* bzf = (bzFile*)b; if (bzf == NULL) { BZ_SETERR(BZ_OK); return; }; if (!(bzf->writing)) { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; if (ferror(bzf->handle)) { BZ_SETERR(BZ_IO_ERROR); return; }; if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; if ((!abandon) && bzf->lastErr == BZ_OK) { while (True) { bzf->strm.avail_out = BZ_MAX_UNUSED; bzf->strm.next_out = bzf->buf; ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) { BZ_SETERR(ret); return; }; if (bzf->strm.avail_out < BZ_MAX_UNUSED) { n = BZ_MAX_UNUSED - bzf->strm.avail_out; n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), n, bzf->handle ); if (n != n2 || ferror(bzf->handle)) { BZ_SETERR(BZ_IO_ERROR); return; }; } if (ret == BZ_STREAM_END) break; } } if ( !abandon && !ferror ( bzf->handle ) ) { fflush ( bzf->handle ); if (ferror(bzf->handle)) { BZ_SETERR(BZ_IO_ERROR); return; }; } if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = bzf->strm.total_in_lo32; if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = bzf->strm.total_in_hi32; if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = bzf->strm.total_out_lo32; if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = bzf->strm.total_out_hi32; BZ_SETERR(BZ_OK); BZ2_bzCompressEnd ( &(bzf->strm) ); free ( bzf ); } /*---------------------------------------------------*/ BZFILE* BZ_API(BZ2_bzReadOpen) ( int* bzerror, FILE* f, int verbosity, int small, void* unused, int nUnused ) { bzFile* bzf = NULL; int ret; BZ_SETERR(BZ_OK); if (f == NULL || (small != 0 && small != 1) || (verbosity < 0 || verbosity > 4) || (unused == NULL && nUnused != 0) || (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; if (ferror(f)) { BZ_SETERR(BZ_IO_ERROR); return NULL; }; bzf = (bzFile *)malloc ( sizeof(bzFile) ); if (bzf == NULL) { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; BZ_SETERR(BZ_OK); bzf->initialisedOk = False; bzf->handle = f; bzf->bufN = 0; bzf->writing = False; bzf->strm.bzalloc = NULL; bzf->strm.bzfree = NULL; bzf->strm.opaque = NULL; while (nUnused > 0) { bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; unused = ((void*)( 1 + ((UChar*)(unused)) )); nUnused--; } ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); if (ret != BZ_OK) { BZ_SETERR(ret); free(bzf); return NULL; }; bzf->strm.avail_in = bzf->bufN; bzf->strm.next_in = bzf->buf; bzf->initialisedOk = True; return bzf; } /*---------------------------------------------------*/ void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) { bzFile* bzf = (bzFile*)b; BZ_SETERR(BZ_OK); if (bzf == NULL) { BZ_SETERR(BZ_OK); return; }; if (bzf->writing) { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; if (bzf->initialisedOk) (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); free ( bzf ); } /*---------------------------------------------------*/ int BZ_API(BZ2_bzRead) ( int* bzerror, BZFILE* b, void* buf, int len ) { Int32 n, ret; bzFile* bzf = (bzFile*)b; BZ_SETERR(BZ_OK); if (bzf == NULL || buf == NULL || len < 0) { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; if (bzf->writing) { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; if (len == 0) { BZ_SETERR(BZ_OK); return 0; }; bzf->strm.avail_out = len; bzf->strm.next_out = (char *)buf; while (True) { if (ferror(bzf->handle)) { BZ_SETERR(BZ_IO_ERROR); return 0; }; if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { n = fread ( bzf->buf, sizeof(UChar), BZ_MAX_UNUSED, bzf->handle ); if (ferror(bzf->handle)) { BZ_SETERR(BZ_IO_ERROR); return 0; }; bzf->bufN = n; bzf->strm.avail_in = bzf->bufN; bzf->strm.next_in = bzf->buf; } ret = BZ2_bzDecompress ( &(bzf->strm) ); if (ret != BZ_OK && ret != BZ_STREAM_END) { BZ_SETERR(ret); return 0; }; if (ret == BZ_OK && myfeof(bzf->handle) && bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; if (ret == BZ_STREAM_END) { BZ_SETERR(BZ_STREAM_END); return len - bzf->strm.avail_out; }; if (bzf->strm.avail_out == 0) { BZ_SETERR(BZ_OK); return len; }; } return 0; /*not reached*/ } /*---------------------------------------------------*/ void BZ_API(BZ2_bzReadGetUnused) ( int* bzerror, BZFILE* b, void** unused, int* nUnused ) { bzFile* bzf = (bzFile*)b; if (bzf == NULL) { BZ_SETERR(BZ_PARAM_ERROR); return; }; if (bzf->lastErr != BZ_STREAM_END) { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; if (unused == NULL || nUnused == NULL) { BZ_SETERR(BZ_PARAM_ERROR); return; }; BZ_SETERR(BZ_OK); *nUnused = bzf->strm.avail_in; *unused = bzf->strm.next_in; } #endif /*---------------------------------------------------*/ /*--- Misc convenience stuff ---*/ /*---------------------------------------------------*/ /*---------------------------------------------------*/ int BZ_API(BZ2_bzBuffToBuffCompress) ( char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int blockSize100k, int verbosity, int workFactor ) { bz_stream strm; int ret; if (dest == NULL || destLen == NULL || source == NULL || blockSize100k < 1 || blockSize100k > 9 || verbosity < 0 || verbosity > 4 || workFactor < 0 || workFactor > 250) return BZ_PARAM_ERROR; if (workFactor == 0) workFactor = 30; strm.bzalloc = NULL; strm.bzfree = NULL; strm.opaque = NULL; ret = BZ2_bzCompressInit ( &strm, blockSize100k, verbosity, workFactor ); if (ret != BZ_OK) return ret; strm.next_in = source; strm.next_out = dest; strm.avail_in = sourceLen; strm.avail_out = *destLen; ret = BZ2_bzCompress ( &strm, BZ_FINISH ); if (ret == BZ_FINISH_OK) goto output_overflow; if (ret != BZ_STREAM_END) goto errhandler; /* normal termination */ *destLen -= strm.avail_out; BZ2_bzCompressEnd ( &strm ); return BZ_OK; output_overflow: BZ2_bzCompressEnd ( &strm ); return BZ_OUTBUFF_FULL; errhandler: BZ2_bzCompressEnd ( &strm ); return ret; } /*---------------------------------------------------*/ int BZ_API(BZ2_bzBuffToBuffDecompress) ( char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int small, int verbosity ) { bz_stream strm; int ret; if (dest == NULL || destLen == NULL || source == NULL || (small != 0 && small != 1) || verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; strm.bzalloc = NULL; strm.bzfree = NULL; strm.opaque = NULL; ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); if (ret != BZ_OK) return ret; strm.next_in = source; strm.next_out = dest; strm.avail_in = sourceLen; strm.avail_out = *destLen; ret = BZ2_bzDecompress ( &strm ); if (ret == BZ_OK) goto output_overflow_or_eof; if (ret != BZ_STREAM_END) goto errhandler; /* normal termination */ *destLen -= strm.avail_out; BZ2_bzDecompressEnd ( &strm ); return BZ_OK; output_overflow_or_eof: if (strm.avail_out > 0) { BZ2_bzDecompressEnd ( &strm ); return BZ_UNEXPECTED_EOF; } else { BZ2_bzDecompressEnd ( &strm ); return BZ_OUTBUFF_FULL; }; errhandler: BZ2_bzDecompressEnd ( &strm ); return ret; } /*---------------------------------------------------*/ /*-- Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) to support better zlib compatibility. This code is not _officially_ part of libbzip2 (yet); I haven't tested it, documented it, or considered the threading-safeness of it. If this code breaks, please contact both Yoshioka and me. --*/ /*---------------------------------------------------*/ /*---------------------------------------------------*/ /*-- return version like "0.9.5d, 4-Sept-1999". --*/ const char * BZ_API(BZ2_bzlibVersion)(void) { return BZ_VERSION; } #ifndef BZ_NO_STDIO /*---------------------------------------------------*/ #if defined(_WIN32) || defined(OS2) || defined(MSDOS) # include # include # define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) #else # define SET_BINARY_MODE(file) #endif static BZFILE * bzopen_or_bzdopen ( const char *path, /* no use when bzdopen */ int fd, /* no use when bzdopen */ const char *mode, int open_mode) /* bzopen: 0, bzdopen:1 */ { int bzerr; char unused[BZ_MAX_UNUSED]; int blockSize100k = 9; int writing = 0; char mode2[10] = ""; FILE *fp = NULL; BZFILE *bzfp = NULL; int verbosity = 0; int workFactor = 30; int smallMode = 0; int nUnused = 0; if (mode == NULL) return NULL; while (*mode) { switch (*mode) { case 'r': writing = 0; break; case 'w': writing = 1; break; case 's': smallMode = 1; break; default: if (isdigit((int)(*mode))) { blockSize100k = *mode-BZ_HDR_0; } } mode++; } strcat(mode2, writing ? "w" : "r" ); strcat(mode2,"b"); /* binary mode */ if (open_mode==0) { if (path==NULL || strcmp(path,"")==0) { fp = (writing ? stdout : stdin); SET_BINARY_MODE(fp); } else { fp = fopen(path,mode2); } } else { #ifdef BZ_STRICT_ANSI fp = NULL; #else fp = (FILE *)fdopen(fd,mode2); #endif } if (fp == NULL) return NULL; if (writing) { /* Guard against total chaos and anarchy -- JRS */ if (blockSize100k < 1) blockSize100k = 1; if (blockSize100k > 9) blockSize100k = 9; bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, verbosity,workFactor); } else { bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, unused,nUnused); } if (bzfp == NULL) { if (fp != stdin && fp != stdout) fclose(fp); return NULL; } return bzfp; } /*---------------------------------------------------*/ /*-- open file for read or write. ex) bzopen("file","w9") case path="" or NULL => use stdin or stdout. --*/ BZFILE * BZ_API(BZ2_bzopen) ( const char *path, const char *mode ) { return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); } /*---------------------------------------------------*/ BZFILE * BZ_API(BZ2_bzdopen) ( int fd, const char *mode ) { return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); } /*---------------------------------------------------*/ int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) { int bzerr, nread; if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; nread = BZ2_bzRead(&bzerr,b,buf,len); if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { return nread; } else { return -1; } } /*---------------------------------------------------*/ int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) { int bzerr; BZ2_bzWrite(&bzerr,b,buf,len); if(bzerr == BZ_OK){ return len; }else{ return -1; } } /*---------------------------------------------------*/ int BZ_API(BZ2_bzflush) (BZFILE *b) { /* do nothing now... */ return 0; } /*---------------------------------------------------*/ void BZ_API(BZ2_bzclose) (BZFILE* b) { int bzerr; FILE *fp; if (b==NULL) {return;} fp = ((bzFile *)b)->handle; if(((bzFile*)b)->writing){ BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); if(bzerr != BZ_OK){ BZ2_bzWriteClose(NULL,b,1,NULL,NULL); } }else{ BZ2_bzReadClose(&bzerr,b); } if(fp!=stdin && fp!=stdout){ fclose(fp); } } /*---------------------------------------------------*/ /*-- return last error code --*/ static const char *bzerrorstrings[] = { "OK" ,"SEQUENCE_ERROR" ,"PARAM_ERROR" ,"MEM_ERROR" ,"DATA_ERROR" ,"DATA_ERROR_MAGIC" ,"IO_ERROR" ,"UNEXPECTED_EOF" ,"OUTBUFF_FULL" ,"CONFIG_ERROR" ,"???" /* for future */ ,"???" /* for future */ ,"???" /* for future */ ,"???" /* for future */ ,"???" /* for future */ ,"???" /* for future */ }; const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) { int err = ((bzFile *)b)->lastErr; if(err>0) err = 0; *errnum = err; return bzerrorstrings[err*-1]; } #endif /*-------------------------------------------------------------*/ /*--- end bzlib.c ---*/ /*-------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/bzlib.h000066400000000000000000000143531300674244400233520ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Public header file for the library. ---*/ /*--- bzlib.h ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ #ifdef _WIN32 #ifdef __STDC__ #undef __STDC__ #endif #endif #ifndef ABC__misc__bzlib__bzlib_h #define ABC__misc__bzlib__bzlib_h #define BZ_RUN 0 #define BZ_FLUSH 1 #define BZ_FINISH 2 #define BZ_OK 0 #define BZ_RUN_OK 1 #define BZ_FLUSH_OK 2 #define BZ_FINISH_OK 3 #define BZ_STREAM_END 4 #define BZ_SEQUENCE_ERROR (-1) #define BZ_PARAM_ERROR (-2) #define BZ_MEM_ERROR (-3) #define BZ_DATA_ERROR (-4) #define BZ_DATA_ERROR_MAGIC (-5) #define BZ_IO_ERROR (-6) #define BZ_UNEXPECTED_EOF (-7) #define BZ_OUTBUFF_FULL (-8) #define BZ_CONFIG_ERROR (-9) typedef struct { char *next_in; unsigned int avail_in; unsigned int total_in_lo32; unsigned int total_in_hi32; char *next_out; unsigned int avail_out; unsigned int total_out_lo32; unsigned int total_out_hi32; void *state; void *(*bzalloc)(void *,int,int); void (*bzfree)(void *,void *); void *opaque; } bz_stream; #ifndef BZ_IMPORT #define BZ_EXPORT #endif #ifndef BZ_NO_STDIO /* Need a definitition for FILE */ #include #endif #ifdef _WIN32 # include # ifdef small /* windows.h define small to char */ # undef small # endif # ifdef BZ_EXPORT # define BZ_API(func) WINAPI func # define BZ_EXTERN extern # else /* import windows dll dynamically */ # define BZ_API(func) (WINAPI * func) # define BZ_EXTERN # endif #else # define BZ_API(func) func # define BZ_EXTERN extern #endif #include #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START /*-- Core (low-level) library functions --*/ BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( bz_stream* strm, int blockSize100k, int verbosity, int workFactor ); BZ_EXTERN int BZ_API(BZ2_bzCompress) ( bz_stream* strm, int action ); BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( bz_stream* strm ); BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( bz_stream *strm, int verbosity, int small ); BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( bz_stream* strm ); BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ); /*-- High(er) level library functions --*/ #ifndef BZ_NO_STDIO #define BZ_MAX_UNUSED 5000 typedef void BZFILE; BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( int* bzerror, FILE* f, int verbosity, int small, void* unused, int nUnused ); BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( int* bzerror, BZFILE* b ); BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( int* bzerror, BZFILE* b, void** unused, int* nUnused ); BZ_EXTERN int BZ_API(BZ2_bzRead) ( int* bzerror, BZFILE* b, void* buf, int len ); BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( int* bzerror, FILE* f, int blockSize100k, int verbosity, int workFactor ); BZ_EXTERN void BZ_API(BZ2_bzWrite) ( int* bzerror, BZFILE* b, void* buf, int len ); BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( int* bzerror, BZFILE* b, int abandon, unsigned int* nbytes_in, unsigned int* nbytes_out ); BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( int* bzerror, BZFILE* b, int abandon, unsigned int* nbytes_in_lo32, unsigned int* nbytes_in_hi32, unsigned int* nbytes_out_lo32, unsigned int* nbytes_out_hi32 ); #endif /*-- Utility functions --*/ BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int blockSize100k, int verbosity, int workFactor ); BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int small, int verbosity ); /*-- Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) to support better zlib compatibility. This code is not _officially_ part of libbzip2 (yet); I haven't tested it, documented it, or considered the threading-safeness of it. If this code breaks, please contact both Yoshioka and me. --*/ BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) ( void ); #ifndef BZ_NO_STDIO BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) ( const char *path, const char *mode ); BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) ( int fd, const char *mode ); BZ_EXTERN int BZ_API(BZ2_bzread) ( BZFILE* b, void* buf, int len ); BZ_EXTERN int BZ_API(BZ2_bzwrite) ( BZFILE* b, void* buf, int len ); BZ_EXTERN int BZ_API(BZ2_bzflush) ( BZFILE* b ); BZ_EXTERN void BZ_API(BZ2_bzclose) ( BZFILE* b ); BZ_EXTERN const char * BZ_API(BZ2_bzerror) ( BZFILE *b, int *errnum ); #endif ABC_NAMESPACE_HEADER_END #endif /*-------------------------------------------------------------*/ /*--- end bzlib.h ---*/ /*-------------------------------------------------------------*/ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/bzlib_private.h000066400000000000000000000320141300674244400250760ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Private header file for the library. ---*/ /*--- bzlib_private.h ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ #ifndef ABC__misc__bzlib__bzlib_private_h #define ABC__misc__bzlib__bzlib_private_h #include #ifndef BZ_NO_STDIO #include #include #include #endif #include "bzlib.h" ABC_NAMESPACE_HEADER_START /*-- General stuff. --*/ #define BZ_VERSION "1.0.5, 10-Dec-2007" typedef char Char; typedef unsigned char Bool; typedef unsigned char UChar; typedef int Int32; typedef unsigned int UInt32; typedef short Int16; typedef unsigned short UInt16; #define True ((Bool)1) #define False ((Bool)0) #ifndef __GNUC__ #define __inline__ /* */ #endif #ifndef BZ_NO_STDIO extern void BZ2_bz__AssertH__fail ( int errcode ); #define AssertH(cond,errcode) \ { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); } #if BZ_DEBUG #define AssertD(cond,msg) \ { if (!(cond)) { \ fprintf ( stderr, \ "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\ exit(1); \ }} #else #define AssertD(cond,msg) /* */ #endif #define VPrintf0(zf) \ fprintf(stderr,zf) #define VPrintf1(zf,za1) \ fprintf(stderr,zf,za1) #define VPrintf2(zf,za1,za2) \ fprintf(stderr,zf,za1,za2) #define VPrintf3(zf,za1,za2,za3) \ fprintf(stderr,zf,za1,za2,za3) #define VPrintf4(zf,za1,za2,za3,za4) \ fprintf(stderr,zf,za1,za2,za3,za4) #define VPrintf5(zf,za1,za2,za3,za4,za5) \ fprintf(stderr,zf,za1,za2,za3,za4,za5) #else extern void bz_internal_error ( int errcode ); #define AssertH(cond,errcode) \ { if (!(cond)) bz_internal_error ( errcode ); } #define AssertD(cond,msg) do { } while (0) #define VPrintf0(zf) do { } while (0) #define VPrintf1(zf,za1) do { } while (0) #define VPrintf2(zf,za1,za2) do { } while (0) #define VPrintf3(zf,za1,za2,za3) do { } while (0) #define VPrintf4(zf,za1,za2,za3,za4) do { } while (0) #define VPrintf5(zf,za1,za2,za3,za4,za5) do { } while (0) #endif #define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1) #define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp)) /*-- Header bytes. --*/ #define BZ_HDR_B 0x42 /* 'B' */ #define BZ_HDR_Z 0x5a /* 'Z' */ #define BZ_HDR_h 0x68 /* 'h' */ #define BZ_HDR_0 0x30 /* '0' */ /*-- Constants for the back end. --*/ #define BZ_MAX_ALPHA_SIZE 258 #define BZ_MAX_CODE_LEN 23 #define BZ_RUNA 0 #define BZ_RUNB 1 #define BZ_N_GROUPS 6 #define BZ_G_SIZE 50 #define BZ_N_ITERS 4 #define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE)) /*-- Stuff for randomising repetitive blocks. --*/ extern Int32 BZ2_rNums[512]; #define BZ_RAND_DECLS \ Int32 rNToGo; \ Int32 rTPos \ #define BZ_RAND_INIT_MASK \ s->rNToGo = 0; \ s->rTPos = 0 \ #define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0) #define BZ_RAND_UPD_MASK \ if (s->rNToGo == 0) { \ s->rNToGo = BZ2_rNums[s->rTPos]; \ s->rTPos++; \ if (s->rTPos == 512) s->rTPos = 0; \ } \ s->rNToGo--; /*-- Stuff for doing CRCs. --*/ extern UInt32 BZ2_crc32Table[256]; #define BZ_INITIALISE_CRC(crcVar) \ { \ crcVar = 0xffffffffL; \ } #define BZ_FINALISE_CRC(crcVar) \ { \ crcVar = ~(crcVar); \ } #define BZ_UPDATE_CRC(crcVar,cha) \ { \ crcVar = (crcVar << 8) ^ \ BZ2_crc32Table[(crcVar >> 24) ^ \ ((UChar)cha)]; \ } /*-- States and modes for compression. --*/ #define BZ_M_IDLE 1 #define BZ_M_RUNNING 2 #define BZ_M_FLUSHING 3 #define BZ_M_FINISHING 4 #define BZ_S_OUTPUT 1 #define BZ_S_INPUT 2 #define BZ_N_RADIX 2 #define BZ_N_QSORT 12 #define BZ_N_SHELL 18 #define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2) /*-- Structure holding all the compression-side stuff. --*/ typedef struct { /* pointer back to the struct bz_stream */ bz_stream* strm; /* mode this stream is in, and whether inputting */ /* or outputting data */ Int32 mode; Int32 state; /* remembers avail_in when flush/finish requested */ UInt32 avail_in_expect; /* for doing the block sorting */ UInt32* arr1; UInt32* arr2; UInt32* ftab; Int32 origPtr; /* aliases for arr1 and arr2 */ UInt32* ptr; UChar* block; UInt16* mtfv; UChar* zbits; /* for deciding when to use the fallback sorting algorithm */ Int32 workFactor; /* run-length-encoding of the input */ UInt32 state_in_ch; Int32 state_in_len; BZ_RAND_DECLS; /* input and output limits and current posns */ Int32 nblock; Int32 nblockMAX; Int32 numZ; Int32 state_out_pos; /* map of bytes used in block */ Int32 nInUse; Bool inUse[256]; UChar unseqToSeq[256]; /* the buffer for bit stream creation */ UInt32 bsBuff; Int32 bsLive; /* block and combined CRCs */ UInt32 blockCRC; UInt32 combinedCRC; /* misc administratium */ Int32 verbosity; Int32 blockNo; Int32 blockSize100k; /* stuff for coding the MTF values */ Int32 nMTF; Int32 mtfFreq [BZ_MAX_ALPHA_SIZE]; UChar selector [BZ_MAX_SELECTORS]; UChar selectorMtf[BZ_MAX_SELECTORS]; UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; /* second dimension: only 3 needed; 4 makes index calculations faster */ UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4]; } EState; /*-- externs for compression. --*/ extern void BZ2_blockSort ( EState* ); extern void BZ2_compressBlock ( EState*, Bool ); extern void BZ2_bsInitWrite ( EState* ); extern void BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 ); extern void BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 ); /*-- states for decompression. --*/ #define BZ_X_IDLE 1 #define BZ_X_OUTPUT 2 #define BZ_X_MAGIC_1 10 #define BZ_X_MAGIC_2 11 #define BZ_X_MAGIC_3 12 #define BZ_X_MAGIC_4 13 #define BZ_X_BLKHDR_1 14 #define BZ_X_BLKHDR_2 15 #define BZ_X_BLKHDR_3 16 #define BZ_X_BLKHDR_4 17 #define BZ_X_BLKHDR_5 18 #define BZ_X_BLKHDR_6 19 #define BZ_X_BCRC_1 20 #define BZ_X_BCRC_2 21 #define BZ_X_BCRC_3 22 #define BZ_X_BCRC_4 23 #define BZ_X_RANDBIT 24 #define BZ_X_ORIGPTR_1 25 #define BZ_X_ORIGPTR_2 26 #define BZ_X_ORIGPTR_3 27 #define BZ_X_MAPPING_1 28 #define BZ_X_MAPPING_2 29 #define BZ_X_SELECTOR_1 30 #define BZ_X_SELECTOR_2 31 #define BZ_X_SELECTOR_3 32 #define BZ_X_CODING_1 33 #define BZ_X_CODING_2 34 #define BZ_X_CODING_3 35 #define BZ_X_MTF_1 36 #define BZ_X_MTF_2 37 #define BZ_X_MTF_3 38 #define BZ_X_MTF_4 39 #define BZ_X_MTF_5 40 #define BZ_X_MTF_6 41 #define BZ_X_ENDHDR_2 42 #define BZ_X_ENDHDR_3 43 #define BZ_X_ENDHDR_4 44 #define BZ_X_ENDHDR_5 45 #define BZ_X_ENDHDR_6 46 #define BZ_X_CCRC_1 47 #define BZ_X_CCRC_2 48 #define BZ_X_CCRC_3 49 #define BZ_X_CCRC_4 50 /*-- Constants for the fast MTF decoder. --*/ #define MTFA_SIZE 4096 #define MTFL_SIZE 16 /*-- Structure holding all the decompression-side stuff. --*/ typedef struct { /* pointer back to the struct bz_stream */ bz_stream* strm; /* state indicator for this stream */ Int32 state; /* for doing the final run-length decoding */ UChar state_out_ch; Int32 state_out_len; Bool blockRandomised; BZ_RAND_DECLS; /* the buffer for bit stream reading */ UInt32 bsBuff; Int32 bsLive; /* misc administratium */ Int32 blockSize100k; Bool smallDecompress; Int32 currBlockNo; Int32 verbosity; /* for undoing the Burrows-Wheeler transform */ Int32 origPtr; UInt32 tPos; Int32 k0; Int32 unzftab[256]; Int32 nblock_used; Int32 cftab[257]; Int32 cftabCopy[257]; /* for undoing the Burrows-Wheeler transform (FAST) */ UInt32 *tt; /* for undoing the Burrows-Wheeler transform (SMALL) */ UInt16 *ll16; UChar *ll4; /* stored and calculated CRCs */ UInt32 storedBlockCRC; UInt32 storedCombinedCRC; UInt32 calculatedBlockCRC; UInt32 calculatedCombinedCRC; /* map of bytes used in block */ Int32 nInUse; Bool inUse[256]; Bool inUse16[16]; UChar seqToUnseq[256]; /* for decoding the MTF values */ UChar mtfa [MTFA_SIZE]; Int32 mtfbase[256 / MTFL_SIZE]; UChar selector [BZ_MAX_SELECTORS]; UChar selectorMtf[BZ_MAX_SELECTORS]; UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; Int32 minLens[BZ_N_GROUPS]; /* save area for scalars in the main decompress code */ Int32 save_i; Int32 save_j; Int32 save_t; Int32 save_alphaSize; Int32 save_nGroups; Int32 save_nSelectors; Int32 save_EOB; Int32 save_groupNo; Int32 save_groupPos; Int32 save_nextSym; Int32 save_nblockMAX; Int32 save_nblock; Int32 save_es; Int32 save_N; Int32 save_curr; Int32 save_zt; Int32 save_zn; Int32 save_zvec; Int32 save_zj; Int32 save_gSel; Int32 save_gMinlen; Int32* save_gLimit; Int32* save_gBase; Int32* save_gPerm; } DState; /*-- Macros for decompression. --*/ #define BZ_GET_FAST(cccc) \ /* c_tPos is unsigned, hence test < 0 is pointless. */ \ if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \ s->tPos = s->tt[s->tPos]; \ cccc = (UChar)(s->tPos & 0xff); \ s->tPos >>= 8; #define BZ_GET_FAST_C(cccc) \ /* c_tPos is unsigned, hence test < 0 is pointless. */ \ if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) return True; \ c_tPos = c_tt[c_tPos]; \ cccc = (UChar)(c_tPos & 0xff); \ c_tPos >>= 8; #define SET_LL4(i,n) \ { if (((i) & 0x1) == 0) \ s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \ s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \ } #define GET_LL4(i) \ ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF) #define SET_LL(i,n) \ { s->ll16[i] = (UInt16)(n & 0x0000ffff); \ SET_LL4(i, n >> 16); \ } #define GET_LL(i) \ (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16)) #define BZ_GET_SMALL(cccc) \ /* c_tPos is unsigned, hence test < 0 is pointless. */ \ if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \ cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \ s->tPos = GET_LL(s->tPos); /*-- externs for decompression. --*/ Int32 BZ2_indexIntoF ( Int32, Int32* ); extern Int32 BZ2_decompress ( DState* ); extern void BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*, Int32, Int32, Int32 ); #endif /*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/ #ifdef BZ_NO_STDIO #ifndef NULL #define NULL 0 #endif #endif ABC_NAMESPACE_HEADER_END /*-------------------------------------------------------------*/ /*--- end bzlib_private.h ---*/ /*-------------------------------------------------------------*/ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/compress.c000066400000000000000000000502041300674244400240710ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Compression machinery (not incl block sorting) ---*/ /*--- compress.c ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ /* CHANGES 0.9.0 -- original version. 0.9.0a/b -- no changes in this file. 0.9.0c -- changed setting of nGroups in sendMTFValues() so as to do a bit better on small files */ #include "bzlib_private.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------*/ /*--- Bit stream I/O ---*/ /*---------------------------------------------------*/ /*---------------------------------------------------*/ void BZ2_bsInitWrite ( EState* s ) { s->bsLive = 0; s->bsBuff = 0; } /*---------------------------------------------------*/ static void bsFinishWrite ( EState* s ) { while (s->bsLive > 0) { s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24); s->numZ++; s->bsBuff <<= 8; s->bsLive -= 8; } } /*---------------------------------------------------*/ #define bsNEEDW(nz) \ { \ while (s->bsLive >= 8) { \ s->zbits[s->numZ] \ = (UChar)(s->bsBuff >> 24); \ s->numZ++; \ s->bsBuff <<= 8; \ s->bsLive -= 8; \ } \ } /*---------------------------------------------------*/ static __inline__ void bsW ( EState* s, Int32 n, UInt32 v ) { bsNEEDW ( n ); s->bsBuff |= (v << (32 - s->bsLive - n)); s->bsLive += n; } /*---------------------------------------------------*/ static void bsPutUInt32 ( EState* s, UInt32 u ) { bsW ( s, 8, (u >> 24) & 0xffL ); bsW ( s, 8, (u >> 16) & 0xffL ); bsW ( s, 8, (u >> 8) & 0xffL ); bsW ( s, 8, u & 0xffL ); } /*---------------------------------------------------*/ static void bsPutUChar ( EState* s, UChar c ) { bsW( s, 8, (UInt32)c ); } /*---------------------------------------------------*/ /*--- The back end proper ---*/ /*---------------------------------------------------*/ /*---------------------------------------------------*/ static void makeMaps_e ( EState* s ) { Int32 i; s->nInUse = 0; for (i = 0; i < 256; i++) if (s->inUse[i]) { s->unseqToSeq[i] = s->nInUse; s->nInUse++; } } /*---------------------------------------------------*/ static void generateMTFValues ( EState* s ) { UChar yy[256]; Int32 i, j; Int32 zPend; Int32 wr; Int32 EOB; /* After sorting (eg, here), s->arr1 [ 0 .. s->nblock-1 ] holds sorted order, and ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] holds the original block data. The first thing to do is generate the MTF values, and put them in ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ]. Because there are strictly fewer or equal MTF values than block values, ptr values in this area are overwritten with MTF values only when they are no longer needed. The final compressed bitstream is generated into the area starting at (UChar*) (&((UChar*)s->arr2)[s->nblock]) These storage aliases are set up in bzCompressInit(), except for the last one, which is arranged in compressBlock(). */ UInt32* ptr = s->ptr; UChar* block = s->block; UInt16* mtfv = s->mtfv; makeMaps_e ( s ); EOB = s->nInUse+1; for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0; wr = 0; zPend = 0; for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i; for (i = 0; i < s->nblock; i++) { UChar ll_i; AssertD ( wr <= i, "generateMTFValues(1)" ); j = ptr[i]-1; if (j < 0) j += s->nblock; ll_i = s->unseqToSeq[block[j]]; AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" ); if (yy[0] == ll_i) { zPend++; } else { if (zPend > 0) { zPend--; while (True) { if (zPend & 1) { mtfv[wr] = BZ_RUNB; wr++; s->mtfFreq[BZ_RUNB]++; } else { mtfv[wr] = BZ_RUNA; wr++; s->mtfFreq[BZ_RUNA]++; } if (zPend < 2) break; zPend = (zPend - 2) / 2; }; zPend = 0; } { register UChar rtmp; register UChar* ryy_j; register UChar rll_i; rtmp = yy[1]; yy[1] = yy[0]; ryy_j = &(yy[1]); rll_i = ll_i; while ( rll_i != rtmp ) { register UChar rtmp2; ryy_j++; rtmp2 = rtmp; rtmp = *ryy_j; *ryy_j = rtmp2; }; yy[0] = rtmp; j = ryy_j - &(yy[0]); mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++; } } } if (zPend > 0) { zPend--; while (True) { if (zPend & 1) { mtfv[wr] = BZ_RUNB; wr++; s->mtfFreq[BZ_RUNB]++; } else { mtfv[wr] = BZ_RUNA; wr++; s->mtfFreq[BZ_RUNA]++; } if (zPend < 2) break; zPend = (zPend - 2) / 2; }; zPend = 0; } mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++; s->nMTF = wr; } /*---------------------------------------------------*/ #define BZ_LESSER_ICOST 0 #define BZ_GREATER_ICOST 15 static void sendMTFValues ( EState* s ) { Int32 v, t, i, j, gs, ge, totc, bt, bc, iter; Int32 nSelectors, alphaSize, minLen, maxLen, selCtr; Int32 nGroups, nBytes; /*-- UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; is a global since the decoder also needs it. Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; are also globals only used in this proc. Made global to keep stack frame size small. --*/ UInt16 cost[BZ_N_GROUPS]; Int32 fave[BZ_N_GROUPS]; UInt16* mtfv = s->mtfv; if (s->verbosity >= 3) VPrintf3( " %d in block, %d after MTF & 1-2 coding, " "%d+2 syms in use\n", s->nblock, s->nMTF, s->nInUse ); alphaSize = s->nInUse+2; for (t = 0; t < BZ_N_GROUPS; t++) for (v = 0; v < alphaSize; v++) s->len[t][v] = BZ_GREATER_ICOST; /*--- Decide how many coding tables to use ---*/ AssertH ( s->nMTF > 0, 3001 ); if (s->nMTF < 200) nGroups = 2; else if (s->nMTF < 600) nGroups = 3; else if (s->nMTF < 1200) nGroups = 4; else if (s->nMTF < 2400) nGroups = 5; else nGroups = 6; /*--- Generate an initial set of coding tables ---*/ { Int32 nPart, remF, tFreq, aFreq; nPart = nGroups; remF = s->nMTF; gs = 0; while (nPart > 0) { tFreq = remF / nPart; ge = gs-1; aFreq = 0; while (aFreq < tFreq && ge < alphaSize-1) { ge++; aFreq += s->mtfFreq[ge]; } if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups-nPart) % 2 == 1)) { aFreq -= s->mtfFreq[ge]; ge--; } if (s->verbosity >= 3) VPrintf5( " initial group %d, [%d .. %d], " "has %d syms (%4.1f%%)\n", nPart, gs, ge, aFreq, (100.0 * (float)aFreq) / (float)(s->nMTF) ); for (v = 0; v < alphaSize; v++) if (v >= gs && v <= ge) s->len[nPart-1][v] = BZ_LESSER_ICOST; else s->len[nPart-1][v] = BZ_GREATER_ICOST; nPart--; gs = ge+1; remF -= aFreq; } } /*--- Iterate up to BZ_N_ITERS times to improve the tables. ---*/ for (iter = 0; iter < BZ_N_ITERS; iter++) { for (t = 0; t < nGroups; t++) fave[t] = 0; for (t = 0; t < nGroups; t++) for (v = 0; v < alphaSize; v++) s->rfreq[t][v] = 0; /*--- Set up an auxiliary length table which is used to fast-track the common case (nGroups == 6). ---*/ if (nGroups == 6) { for (v = 0; v < alphaSize; v++) { s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v]; s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v]; s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v]; } } nSelectors = 0; totc = 0; gs = 0; while (True) { /*--- Set group start & end marks. --*/ if (gs >= s->nMTF) break; ge = gs + BZ_G_SIZE - 1; if (ge >= s->nMTF) ge = s->nMTF-1; /*-- Calculate the cost of this group as coded by each of the coding tables. --*/ for (t = 0; t < nGroups; t++) cost[t] = 0; if (nGroups == 6 && 50 == ge-gs+1) { /*--- fast track the common case ---*/ register UInt32 cost01, cost23, cost45; register UInt16 icv; cost01 = cost23 = cost45 = 0; # define BZ_ITER(nn) \ icv = mtfv[gs+(nn)]; \ cost01 += s->len_pack[icv][0]; \ cost23 += s->len_pack[icv][1]; \ cost45 += s->len_pack[icv][2]; \ BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4); BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9); BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14); BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19); BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24); BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29); BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34); BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39); BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44); BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49); # undef BZ_ITER cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16; cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16; cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16; } else { /*--- slow version which correctly handles all situations ---*/ for (i = gs; i <= ge; i++) { UInt16 icv = mtfv[i]; for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv]; } } /*-- Find the coding table which is best for this group, and record its identity in the selector table. --*/ bc = 999999999; bt = -1; for (t = 0; t < nGroups; t++) if (cost[t] < bc) { bc = cost[t]; bt = t; }; totc += bc; fave[bt]++; s->selector[nSelectors] = bt; nSelectors++; /*-- Increment the symbol frequencies for the selected table. --*/ if (nGroups == 6 && 50 == ge-gs+1) { /*--- fast track the common case ---*/ # define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++ BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4); BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9); BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14); BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19); BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24); BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29); BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34); BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39); BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44); BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49); # undef BZ_ITUR } else { /*--- slow version which correctly handles all situations ---*/ for (i = gs; i <= ge; i++) s->rfreq[bt][ mtfv[i] ]++; } gs = ge+1; } if (s->verbosity >= 3) { VPrintf2 ( " pass %d: size is %d, grp uses are ", iter+1, totc/8 ); for (t = 0; t < nGroups; t++) VPrintf1 ( "%d ", fave[t] ); VPrintf0 ( "\n" ); } /*-- Recompute the tables based on the accumulated frequencies. --*/ /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See comment in huffman.c for details. */ for (t = 0; t < nGroups; t++) BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), alphaSize, 17 /*20*/ ); } AssertH( nGroups < 8, 3002 ); AssertH( nSelectors < 32768 && nSelectors <= (2 + (900000 / BZ_G_SIZE)), 3003 ); /*--- Compute MTF values for the selectors. ---*/ { UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp; for (i = 0; i < nGroups; i++) pos[i] = i; for (i = 0; i < nSelectors; i++) { ll_i = s->selector[i]; j = 0; tmp = pos[j]; while ( ll_i != tmp ) { j++; tmp2 = tmp; tmp = pos[j]; pos[j] = tmp2; }; pos[0] = tmp; s->selectorMtf[i] = j; } }; /*--- Assign actual codes for the tables. --*/ for (t = 0; t < nGroups; t++) { minLen = 32; maxLen = 0; for (i = 0; i < alphaSize; i++) { if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; if (s->len[t][i] < minLen) minLen = s->len[t][i]; } AssertH ( !(maxLen > 17 /*20*/ ), 3004 ); AssertH ( !(minLen < 1), 3005 ); BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), minLen, maxLen, alphaSize ); } /*--- Transmit the mapping table. ---*/ { Bool inUse16[16]; for (i = 0; i < 16; i++) { inUse16[i] = False; for (j = 0; j < 16; j++) if (s->inUse[i * 16 + j]) inUse16[i] = True; } nBytes = s->numZ; for (i = 0; i < 16; i++) if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0); for (i = 0; i < 16; i++) if (inUse16[i]) for (j = 0; j < 16; j++) { if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0); } if (s->verbosity >= 3) VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes ); } /*--- Now the selectors. ---*/ nBytes = s->numZ; bsW ( s, 3, nGroups ); bsW ( s, 15, nSelectors ); for (i = 0; i < nSelectors; i++) { for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1); bsW(s,1,0); } if (s->verbosity >= 3) VPrintf1( "selectors %d, ", s->numZ-nBytes ); /*--- Now the coding tables. ---*/ nBytes = s->numZ; for (t = 0; t < nGroups; t++) { Int32 curr = s->len[t][0]; bsW ( s, 5, curr ); for (i = 0; i < alphaSize; i++) { while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ }; while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ }; bsW ( s, 1, 0 ); } } if (s->verbosity >= 3) VPrintf1 ( "code lengths %d, ", s->numZ-nBytes ); /*--- And finally, the block data proper ---*/ nBytes = s->numZ; selCtr = 0; gs = 0; while (True) { if (gs >= s->nMTF) break; ge = gs + BZ_G_SIZE - 1; if (ge >= s->nMTF) ge = s->nMTF-1; AssertH ( s->selector[selCtr] < nGroups, 3006 ); if (nGroups == 6 && 50 == ge-gs+1) { /*--- fast track the common case ---*/ UInt16 mtfv_i; UChar* s_len_sel_selCtr = &(s->len[s->selector[selCtr]][0]); Int32* s_code_sel_selCtr = &(s->code[s->selector[selCtr]][0]); # define BZ_ITAH(nn) \ mtfv_i = mtfv[gs+(nn)]; \ bsW ( s, \ s_len_sel_selCtr[mtfv_i], \ s_code_sel_selCtr[mtfv_i] ) BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4); BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9); BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14); BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19); BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24); BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29); BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34); BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39); BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44); BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49); # undef BZ_ITAH } else { /*--- slow version which correctly handles all situations ---*/ for (i = gs; i <= ge; i++) { bsW ( s, s->len [s->selector[selCtr]] [mtfv[i]], s->code [s->selector[selCtr]] [mtfv[i]] ); } } gs = ge+1; selCtr++; } AssertH( selCtr == nSelectors, 3007 ); if (s->verbosity >= 3) VPrintf1( "codes %d\n", s->numZ-nBytes ); } /*---------------------------------------------------*/ void BZ2_compressBlock ( EState* s, Bool is_last_block ) { if (s->nblock > 0) { BZ_FINALISE_CRC ( s->blockCRC ); s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31); s->combinedCRC ^= s->blockCRC; if (s->blockNo > 1) s->numZ = 0; if (s->verbosity >= 2) VPrintf4( " block %d: crc = 0x%08x, " "combined CRC = 0x%08x, size = %d\n", s->blockNo, s->blockCRC, s->combinedCRC, s->nblock ); BZ2_blockSort ( s ); } s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]); /*-- If this is the first block, create the stream header. --*/ if (s->blockNo == 1) { BZ2_bsInitWrite ( s ); bsPutUChar ( s, BZ_HDR_B ); bsPutUChar ( s, BZ_HDR_Z ); bsPutUChar ( s, BZ_HDR_h ); bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) ); } if (s->nblock > 0) { bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 ); bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 ); bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 ); /*-- Now the block's CRC, so it is in a known place. --*/ bsPutUInt32 ( s, s->blockCRC ); /*-- Now a single bit indicating (non-)randomisation. As of version 0.9.5, we use a better sorting algorithm which makes randomisation unnecessary. So always set the randomised bit to 'no'. Of course, the decoder still needs to be able to handle randomised blocks so as to maintain backwards compatibility with older versions of bzip2. --*/ bsW(s,1,0); bsW ( s, 24, s->origPtr ); generateMTFValues ( s ); sendMTFValues ( s ); } /*-- If this is the last block, add the stream trailer. --*/ if (is_last_block) { bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 ); bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 ); bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 ); bsPutUInt32 ( s, s->combinedCRC ); if (s->verbosity >= 2) VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC ); bsFinishWrite ( s ); } } /*-------------------------------------------------------------*/ /*--- end compress.c ---*/ /*-------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/crctable.c000066400000000000000000000114051300674244400240150ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Table for doing CRCs ---*/ /*--- crctable.c ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ #include "bzlib_private.h" ABC_NAMESPACE_IMPL_START /*-- I think this is an implementation of the AUTODIN-II, Ethernet & FDDI 32-bit CRC standard. Vaguely derived from code by Rob Warnock, in Section 51 of the comp.compression FAQ. --*/ UInt32 BZ2_crc32Table[256] = { /*-- Ugly, innit? --*/ 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L }; /*-------------------------------------------------------------*/ /*--- end crctable.c ---*/ /*-------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/decompress.c000066400000000000000000000472401300674244400244100ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Decompression machinery ---*/ /*--- decompress.c ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ #include "bzlib_private.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------*/ static void makeMaps_d ( DState* s ) { Int32 i; s->nInUse = 0; for (i = 0; i < 256; i++) if (s->inUse[i]) { s->seqToUnseq[s->nInUse] = i; s->nInUse++; } } /*---------------------------------------------------*/ #define RETURN(rrr) \ { retVal = rrr; goto save_state_and_return; }; #define GET_BITS(lll,vvv,nnn) \ case lll: s->state = lll; \ while (True) { \ if (s->bsLive >= nnn) { \ UInt32 v; \ v = (s->bsBuff >> \ (s->bsLive-nnn)) & ((1 << nnn)-1); \ s->bsLive -= nnn; \ vvv = v; \ break; \ } \ if (s->strm->avail_in == 0) RETURN(BZ_OK); \ s->bsBuff \ = (s->bsBuff << 8) | \ ((UInt32) \ (*((UChar*)(s->strm->next_in)))); \ s->bsLive += 8; \ s->strm->next_in++; \ s->strm->avail_in--; \ s->strm->total_in_lo32++; \ if (s->strm->total_in_lo32 == 0) \ s->strm->total_in_hi32++; \ } #define GET_UCHAR(lll,uuu) \ GET_BITS(lll,uuu,8) #define GET_BIT(lll,uuu) \ GET_BITS(lll,uuu,1) /*---------------------------------------------------*/ #define GET_MTF_VAL(label1,label2,lval) \ { \ if (groupPos == 0) { \ groupNo++; \ if (groupNo >= nSelectors) \ RETURN(BZ_DATA_ERROR); \ groupPos = BZ_G_SIZE; \ gSel = s->selector[groupNo]; \ gMinlen = s->minLens[gSel]; \ gLimit = &(s->limit[gSel][0]); \ gPerm = &(s->perm[gSel][0]); \ gBase = &(s->base[gSel][0]); \ } \ groupPos--; \ zn = gMinlen; \ GET_BITS(label1, zvec, zn); \ while (1) { \ if (zn > 20 /* the longest code */) \ RETURN(BZ_DATA_ERROR); \ if (zvec <= gLimit[zn]) break; \ zn++; \ GET_BIT(label2, zj); \ zvec = (zvec << 1) | zj; \ }; \ if (zvec - gBase[zn] < 0 \ || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \ RETURN(BZ_DATA_ERROR); \ lval = gPerm[zvec - gBase[zn]]; \ } /*---------------------------------------------------*/ Int32 BZ2_decompress ( DState* s ) { UChar uc; Int32 retVal; Int32 minLen, maxLen; bz_stream* strm = s->strm; /* stuff that needs to be saved/restored */ Int32 i; Int32 j; Int32 t; Int32 alphaSize; Int32 nGroups; Int32 nSelectors; Int32 EOB; Int32 groupNo; Int32 groupPos; Int32 nextSym; Int32 nblockMAX; Int32 nblock; Int32 es; Int32 N; Int32 curr; Int32 zt; Int32 zn; Int32 zvec; Int32 zj; Int32 gSel; Int32 gMinlen; Int32* gLimit; Int32* gBase; Int32* gPerm; if (s->state == BZ_X_MAGIC_1) { /*initialise the save area*/ s->save_i = 0; s->save_j = 0; s->save_t = 0; s->save_alphaSize = 0; s->save_nGroups = 0; s->save_nSelectors = 0; s->save_EOB = 0; s->save_groupNo = 0; s->save_groupPos = 0; s->save_nextSym = 0; s->save_nblockMAX = 0; s->save_nblock = 0; s->save_es = 0; s->save_N = 0; s->save_curr = 0; s->save_zt = 0; s->save_zn = 0; s->save_zvec = 0; s->save_zj = 0; s->save_gSel = 0; s->save_gMinlen = 0; s->save_gLimit = NULL; s->save_gBase = NULL; s->save_gPerm = NULL; } /*restore from the save area*/ i = s->save_i; j = s->save_j; t = s->save_t; alphaSize = s->save_alphaSize; nGroups = s->save_nGroups; nSelectors = s->save_nSelectors; EOB = s->save_EOB; groupNo = s->save_groupNo; groupPos = s->save_groupPos; nextSym = s->save_nextSym; nblockMAX = s->save_nblockMAX; nblock = s->save_nblock; es = s->save_es; N = s->save_N; curr = s->save_curr; zt = s->save_zt; zn = s->save_zn; zvec = s->save_zvec; zj = s->save_zj; gSel = s->save_gSel; gMinlen = s->save_gMinlen; gLimit = s->save_gLimit; gBase = s->save_gBase; gPerm = s->save_gPerm; retVal = BZ_OK; switch (s->state) { GET_UCHAR(BZ_X_MAGIC_1, uc); if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC); GET_UCHAR(BZ_X_MAGIC_2, uc); if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC); GET_UCHAR(BZ_X_MAGIC_3, uc) if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC); GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8) if (s->blockSize100k < (BZ_HDR_0 + 1) || s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC); s->blockSize100k -= BZ_HDR_0; if (s->smallDecompress) { s->ll16 = (unsigned short *)BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) ); s->ll4 = (unsigned char *)BZALLOC( ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) ); if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR); } else { s->tt = (unsigned *)BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) ); if (s->tt == NULL) RETURN(BZ_MEM_ERROR); } GET_UCHAR(BZ_X_BLKHDR_1, uc); if (uc == 0x17) goto endhdr_2; if (uc != 0x31) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_BLKHDR_2, uc); if (uc != 0x41) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_BLKHDR_3, uc); if (uc != 0x59) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_BLKHDR_4, uc); if (uc != 0x26) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_BLKHDR_5, uc); if (uc != 0x53) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_BLKHDR_6, uc); if (uc != 0x59) RETURN(BZ_DATA_ERROR); s->currBlockNo++; if (s->verbosity >= 2) VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo ); s->storedBlockCRC = 0; GET_UCHAR(BZ_X_BCRC_1, uc); s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); GET_UCHAR(BZ_X_BCRC_2, uc); s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); GET_UCHAR(BZ_X_BCRC_3, uc); s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); GET_UCHAR(BZ_X_BCRC_4, uc); s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1); s->origPtr = 0; GET_UCHAR(BZ_X_ORIGPTR_1, uc); s->origPtr = (s->origPtr << 8) | ((Int32)uc); GET_UCHAR(BZ_X_ORIGPTR_2, uc); s->origPtr = (s->origPtr << 8) | ((Int32)uc); GET_UCHAR(BZ_X_ORIGPTR_3, uc); s->origPtr = (s->origPtr << 8) | ((Int32)uc); if (s->origPtr < 0) RETURN(BZ_DATA_ERROR); if (s->origPtr > 10 + 100000*s->blockSize100k) RETURN(BZ_DATA_ERROR); /*--- Receive the mapping table ---*/ for (i = 0; i < 16; i++) { GET_BIT(BZ_X_MAPPING_1, uc); if (uc == 1) s->inUse16[i] = True; else s->inUse16[i] = False; } for (i = 0; i < 256; i++) s->inUse[i] = False; for (i = 0; i < 16; i++) if (s->inUse16[i]) for (j = 0; j < 16; j++) { GET_BIT(BZ_X_MAPPING_2, uc); if (uc == 1) s->inUse[i * 16 + j] = True; } makeMaps_d ( s ); if (s->nInUse == 0) RETURN(BZ_DATA_ERROR); alphaSize = s->nInUse+2; /*--- Now the selectors ---*/ GET_BITS(BZ_X_SELECTOR_1, nGroups, 3); if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR); GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15); if (nSelectors < 1) RETURN(BZ_DATA_ERROR); for (i = 0; i < nSelectors; i++) { j = 0; while (True) { GET_BIT(BZ_X_SELECTOR_3, uc); if (uc == 0) break; j++; if (j >= nGroups) RETURN(BZ_DATA_ERROR); } s->selectorMtf[i] = j; } /*--- Undo the MTF values for the selectors. ---*/ { UChar pos[BZ_N_GROUPS], tmp, v; for (v = 0; v < nGroups; v++) pos[v] = v; for (i = 0; i < nSelectors; i++) { v = s->selectorMtf[i]; tmp = pos[v]; while (v > 0) { pos[v] = pos[v-1]; v--; } pos[0] = tmp; s->selector[i] = tmp; } } /*--- Now the coding tables ---*/ for (t = 0; t < nGroups; t++) { GET_BITS(BZ_X_CODING_1, curr, 5); for (i = 0; i < alphaSize; i++) { while (True) { if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR); GET_BIT(BZ_X_CODING_2, uc); if (uc == 0) break; GET_BIT(BZ_X_CODING_3, uc); if (uc == 0) curr++; else curr--; } s->len[t][i] = curr; } } /*--- Create the Huffman decoding tables ---*/ for (t = 0; t < nGroups; t++) { minLen = 32; maxLen = 0; for (i = 0; i < alphaSize; i++) { if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; if (s->len[t][i] < minLen) minLen = s->len[t][i]; } BZ2_hbCreateDecodeTables ( &(s->limit[t][0]), &(s->base[t][0]), &(s->perm[t][0]), &(s->len[t][0]), minLen, maxLen, alphaSize ); s->minLens[t] = minLen; } /*--- Now the MTF values ---*/ EOB = s->nInUse+1; nblockMAX = 100000 * s->blockSize100k; groupNo = -1; groupPos = 0; for (i = 0; i <= 255; i++) s->unzftab[i] = 0; /*-- MTF init --*/ { Int32 ii, jj, kk; kk = MTFA_SIZE-1; for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) { for (jj = MTFL_SIZE-1; jj >= 0; jj--) { s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj); kk--; } s->mtfbase[ii] = kk + 1; } } /*-- end MTF init --*/ nblock = 0; GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym); while (True) { if (nextSym == EOB) break; if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { es = -1; N = 1; do { if (nextSym == BZ_RUNA) es = es + (0+1) * N; else if (nextSym == BZ_RUNB) es = es + (1+1) * N; N = N * 2; GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym); } while (nextSym == BZ_RUNA || nextSym == BZ_RUNB); es++; uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ]; s->unzftab[uc] += es; if (s->smallDecompress) while (es > 0) { if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); s->ll16[nblock] = (UInt16)uc; nblock++; es--; } else while (es > 0) { if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); s->tt[nblock] = (UInt32)uc; nblock++; es--; }; continue; } else { if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); /*-- uc = MTF ( nextSym-1 ) --*/ { Int32 ii, jj, kk, pp, lno, off; UInt32 nn; nn = (UInt32)(nextSym - 1); if (nn < MTFL_SIZE) { /* avoid general-case expense */ pp = s->mtfbase[0]; uc = s->mtfa[pp+nn]; while (nn > 3) { Int32 z = pp+nn; s->mtfa[(z) ] = s->mtfa[(z)-1]; s->mtfa[(z)-1] = s->mtfa[(z)-2]; s->mtfa[(z)-2] = s->mtfa[(z)-3]; s->mtfa[(z)-3] = s->mtfa[(z)-4]; nn -= 4; } while (nn > 0) { s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; }; s->mtfa[pp] = uc; } else { /* general case */ lno = nn / MTFL_SIZE; off = nn % MTFL_SIZE; pp = s->mtfbase[lno] + off; uc = s->mtfa[pp]; while (pp > s->mtfbase[lno]) { s->mtfa[pp] = s->mtfa[pp-1]; pp--; }; s->mtfbase[lno]++; while (lno > 0) { s->mtfbase[lno]--; s->mtfa[s->mtfbase[lno]] = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1]; lno--; } s->mtfbase[0]--; s->mtfa[s->mtfbase[0]] = uc; if (s->mtfbase[0] == 0) { kk = MTFA_SIZE-1; for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) { for (jj = MTFL_SIZE-1; jj >= 0; jj--) { s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj]; kk--; } s->mtfbase[ii] = kk + 1; } } } } /*-- end uc = MTF ( nextSym-1 ) --*/ s->unzftab[s->seqToUnseq[uc]]++; if (s->smallDecompress) s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]); nblock++; GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym); continue; } } /* Now we know what nblock is, we can do a better sanity check on s->origPtr. */ if (s->origPtr < 0 || s->origPtr >= nblock) RETURN(BZ_DATA_ERROR); /*-- Set up cftab to facilitate generation of T^(-1) --*/ s->cftab[0] = 0; for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; for (i = 0; i <= 256; i++) { if (s->cftab[i] < 0 || s->cftab[i] > nblock) { /* s->cftab[i] can legitimately be == nblock */ RETURN(BZ_DATA_ERROR); } } s->state_out_len = 0; s->state_out_ch = 0; BZ_INITIALISE_CRC ( s->calculatedBlockCRC ); s->state = BZ_X_OUTPUT; if (s->verbosity >= 2) VPrintf0 ( "rt+rld" ); if (s->smallDecompress) { /*-- Make a copy of cftab, used in generation of T --*/ for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i]; /*-- compute the T vector --*/ for (i = 0; i < nblock; i++) { uc = (UChar)(s->ll16[i]); SET_LL(i, s->cftabCopy[uc]); s->cftabCopy[uc]++; } /*-- Compute T^(-1) by pointer reversal on T --*/ i = s->origPtr; j = GET_LL(i); do { Int32 tmp = GET_LL(j); SET_LL(j, i); i = j; j = tmp; } while (i != s->origPtr); s->tPos = s->origPtr; s->nblock_used = 0; if (s->blockRandomised) { BZ_RAND_INIT_MASK; BZ_GET_SMALL(s->k0); s->nblock_used++; BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; } else { BZ_GET_SMALL(s->k0); s->nblock_used++; } } else { /*-- compute the T^(-1) vector --*/ for (i = 0; i < nblock; i++) { uc = (UChar)(s->tt[i] & 0xff); s->tt[s->cftab[uc]] |= (i << 8); s->cftab[uc]++; } s->tPos = s->tt[s->origPtr] >> 8; s->nblock_used = 0; if (s->blockRandomised) { BZ_RAND_INIT_MASK; BZ_GET_FAST(s->k0); s->nblock_used++; BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; } else { BZ_GET_FAST(s->k0); s->nblock_used++; } } RETURN(BZ_OK); endhdr_2: GET_UCHAR(BZ_X_ENDHDR_2, uc); if (uc != 0x72) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_ENDHDR_3, uc); if (uc != 0x45) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_ENDHDR_4, uc); if (uc != 0x38) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_ENDHDR_5, uc); if (uc != 0x50) RETURN(BZ_DATA_ERROR); GET_UCHAR(BZ_X_ENDHDR_6, uc); if (uc != 0x90) RETURN(BZ_DATA_ERROR); s->storedCombinedCRC = 0; GET_UCHAR(BZ_X_CCRC_1, uc); s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); GET_UCHAR(BZ_X_CCRC_2, uc); s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); GET_UCHAR(BZ_X_CCRC_3, uc); s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); GET_UCHAR(BZ_X_CCRC_4, uc); s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); s->state = BZ_X_IDLE; RETURN(BZ_STREAM_END); default: AssertH ( False, 4001 ); } AssertH ( False, 4002 ); save_state_and_return: s->save_i = i; s->save_j = j; s->save_t = t; s->save_alphaSize = alphaSize; s->save_nGroups = nGroups; s->save_nSelectors = nSelectors; s->save_EOB = EOB; s->save_groupNo = groupNo; s->save_groupPos = groupPos; s->save_nextSym = nextSym; s->save_nblockMAX = nblockMAX; s->save_nblock = nblock; s->save_es = es; s->save_N = N; s->save_curr = curr; s->save_zt = zt; s->save_zn = zn; s->save_zvec = zvec; s->save_zj = zj; s->save_gSel = gSel; s->save_gMinlen = gMinlen; s->save_gLimit = gLimit; s->save_gBase = gBase; s->save_gPerm = gPerm; return retVal; } /*-------------------------------------------------------------*/ /*--- end decompress.c ---*/ /*-------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/huffman.c000066400000000000000000000156021300674244400236650ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Huffman coding low-level stuff ---*/ /*--- huffman.c ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ #include "bzlib_private.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------*/ #define WEIGHTOF(zz0) ((zz0) & 0xffffff00) #define DEPTHOF(zz1) ((zz1) & 0x000000ff) #define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3)) #define ADDWEIGHTS(zw1,zw2) \ (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \ (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2))) #define UPHEAP(z) \ { \ Int32 zz, tmp; \ zz = z; tmp = heap[zz]; \ while (weight[tmp] < weight[heap[zz >> 1]]) { \ heap[zz] = heap[zz >> 1]; \ zz >>= 1; \ } \ heap[zz] = tmp; \ } #define DOWNHEAP(z) \ { \ Int32 zz, yy, tmp; \ zz = z; tmp = heap[zz]; \ while (True) { \ yy = zz << 1; \ if (yy > nHeap) break; \ if (yy < nHeap && \ weight[heap[yy+1]] < weight[heap[yy]]) \ yy++; \ if (weight[tmp] < weight[heap[yy]]) break; \ heap[zz] = heap[yy]; \ zz = yy; \ } \ heap[zz] = tmp; \ } /*---------------------------------------------------*/ void BZ2_hbMakeCodeLengths ( UChar *len, Int32 *freq, Int32 alphaSize, Int32 maxLen ) { /*-- Nodes and heap entries run from 1. Entry 0 for both the heap and nodes is a sentinel. --*/ Int32 nNodes, nHeap, n1, n2, i, j, k; Bool tooLong; Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ]; Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ]; Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; for (i = 0; i < alphaSize; i++) weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; while (True) { nNodes = alphaSize; nHeap = 0; heap[0] = 0; weight[0] = 0; parent[0] = -2; for (i = 1; i <= alphaSize; i++) { parent[i] = -1; nHeap++; heap[nHeap] = i; UPHEAP(nHeap); } AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 ); while (nHeap > 1) { n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); nNodes++; parent[n1] = parent[n2] = nNodes; weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]); parent[nNodes] = -1; nHeap++; heap[nHeap] = nNodes; UPHEAP(nHeap); } AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 ); tooLong = False; for (i = 1; i <= alphaSize; i++) { j = 0; k = i; while (parent[k] >= 0) { k = parent[k]; j++; } len[i-1] = j; if (j > maxLen) tooLong = True; } if (! tooLong) break; /* 17 Oct 04: keep-going condition for the following loop used to be 'i < alphaSize', which missed the last element, theoretically leading to the possibility of the compressor looping. However, this count-scaling step is only needed if one of the generated Huffman code words is longer than maxLen, which up to and including version 1.0.2 was 20 bits, which is extremely unlikely. In version 1.0.3 maxLen was changed to 17 bits, which has minimal effect on compression ratio, but does mean this scaling step is used from time to time, enough to verify that it works. This means that bzip2-1.0.3 and later will only produce Huffman codes with a maximum length of 17 bits. However, in order to preserve backwards compatibility with bitstreams produced by versions pre-1.0.3, the decompressor must still handle lengths of up to 20. */ for (i = 1; i <= alphaSize; i++) { j = weight[i] >> 8; j = 1 + (j / 2); weight[i] = j << 8; } } } /*---------------------------------------------------*/ void BZ2_hbAssignCodes ( Int32 *code, UChar *length, Int32 minLen, Int32 maxLen, Int32 alphaSize ) { Int32 n, vec, i; vec = 0; for (n = minLen; n <= maxLen; n++) { for (i = 0; i < alphaSize; i++) if (length[i] == n) { code[i] = vec; vec++; }; vec <<= 1; } } /*---------------------------------------------------*/ void BZ2_hbCreateDecodeTables ( Int32 *limit, Int32 *base, Int32 *perm, UChar *length, Int32 minLen, Int32 maxLen, Int32 alphaSize ) { Int32 pp, i, j, vec; pp = 0; for (i = minLen; i <= maxLen; i++) for (j = 0; j < alphaSize; j++) if (length[j] == i) { perm[pp] = j; pp++; }; for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0; for (i = 0; i < alphaSize; i++) base[length[i]+1]++; for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1]; for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0; vec = 0; for (i = minLen; i <= maxLen; i++) { vec += (base[i+1] - base[i]); limit[i] = vec-1; vec <<= 1; } for (i = minLen + 1; i <= maxLen; i++) base[i] = ((limit[i-1] + 1) << 1) - base[i]; } /*-------------------------------------------------------------*/ /*--- end huffman.c ---*/ /*-------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/link.txt000066400000000000000000000001111300674244400235600ustar00rootroot00000000000000http://www.bzip.org http://gnuwin32.sourceforge.net/packages/bzip2.htm berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/manual.html000066400000000000000000003710361300674244400242460ustar00rootroot00000000000000 bzip2 and libbzip2, version 1.0.5

        bzip2 and libbzip2, version 1.0.5

        A program and library for data compression

        Julian Seward

        http://www.bzip.org

        Version 1.0.5 of 10 December 2007

        This program, bzip2, the associated library libbzip2, and all documentation, are copyright © 1996-2007 Julian Seward. All rights reserved.

        Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

        • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

        • The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.

        • Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.

        • The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.

        THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

        PATENTS: To the best of my knowledge, bzip2 and libbzip2 do not use any patented algorithms. However, I do not have the resources to carry out a patent search. Therefore I cannot give any guarantee of the above statement.


        1. Introduction

        bzip2 compresses files using the Burrows-Wheeler block-sorting text compression algorithm, and Huffman coding. Compression is generally considerably better than that achieved by more conventional LZ77/LZ78-based compressors, and approaches the performance of the PPM family of statistical compressors.

        bzip2 is built on top of libbzip2, a flexible library for handling compressed data in the bzip2 format. This manual describes both how to use the program and how to work with the library interface. Most of the manual is devoted to this library, not the program, which is good news if your interest is only in the program.

        • How to use bzip2 describes how to use bzip2; this is the only part you need to read if you just want to know how to operate the program.

        • Programming with libbzip2 describes the programming interfaces in detail, and

        • Miscellanea records some miscellaneous notes which I thought ought to be recorded somewhere.

        2. How to use bzip2

        This chapter contains a copy of the bzip2 man page, and nothing else.

        2.1. NAME

        • bzip2, bunzip2 - a block-sorting file compressor, v1.0.4

        • bzcat - decompresses files to stdout

        • bzip2recover - recovers data from damaged bzip2 files

        2.2. SYNOPSIS

        • bzip2 [ -cdfkqstvzVL123456789 ] [ filenames ... ]

        • bunzip2 [ -fkvsVL ] [ filenames ... ]

        • bzcat [ -s ] [ filenames ... ]

        • bzip2recover filename

        2.3. DESCRIPTION

        bzip2 compresses files using the Burrows-Wheeler block sorting text compression algorithm, and Huffman coding. Compression is generally considerably better than that achieved by more conventional LZ77/LZ78-based compressors, and approaches the performance of the PPM family of statistical compressors.

        The command-line options are deliberately very similar to those of GNU gzip, but they are not identical.

        bzip2 expects a list of file names to accompany the command-line flags. Each file is replaced by a compressed version of itself, with the name original_name.bz2. Each compressed file has the same modification date, permissions, and, when possible, ownership as the corresponding original, so that these properties can be correctly restored at decompression time. File name handling is naive in the sense that there is no mechanism for preserving original file names, permissions, ownerships or dates in filesystems which lack these concepts, or have serious file name length restrictions, such as MS-DOS.

        bzip2 and bunzip2 will by default not overwrite existing files. If you want this to happen, specify the -f flag.

        If no file names are specified, bzip2 compresses from standard input to standard output. In this case, bzip2 will decline to write compressed output to a terminal, as this would be entirely incomprehensible and therefore pointless.

        bunzip2 (or bzip2 -d) decompresses all specified files. Files which were not created by bzip2 will be detected and ignored, and a warning issued. bzip2 attempts to guess the filename for the decompressed file from that of the compressed file as follows:

        • filename.bz2 becomes filename

        • filename.bz becomes filename

        • filename.tbz2 becomes filename.tar

        • filename.tbz becomes filename.tar

        • anyothername becomes anyothername.out

        If the file does not end in one of the recognised endings, .bz2, .bz, .tbz2 or .tbz, bzip2 complains that it cannot guess the name of the original file, and uses the original name with .out appended.

        As with compression, supplying no filenames causes decompression from standard input to standard output.

        bunzip2 will correctly decompress a file which is the concatenation of two or more compressed files. The result is the concatenation of the corresponding uncompressed files. Integrity testing (-t) of concatenated compressed files is also supported.

        You can also compress or decompress files to the standard output by giving the -c flag. Multiple files may be compressed and decompressed like this. The resulting outputs are fed sequentially to stdout. Compression of multiple files in this manner generates a stream containing multiple compressed file representations. Such a stream can be decompressed correctly only by bzip2 version 0.9.0 or later. Earlier versions of bzip2 will stop after decompressing the first file in the stream.

        bzcat (or bzip2 -dc) decompresses all specified files to the standard output.

        bzip2 will read arguments from the environment variables BZIP2 and BZIP, in that order, and will process them before any arguments read from the command line. This gives a convenient way to supply default arguments.

        Compression is always performed, even if the compressed file is slightly larger than the original. Files of less than about one hundred bytes tend to get larger, since the compression mechanism has a constant overhead in the region of 50 bytes. Random data (including the output of most file compressors) is coded at about 8.05 bits per byte, giving an expansion of around 0.5%.

        As a self-check for your protection, bzip2 uses 32-bit CRCs to make sure that the decompressed version of a file is identical to the original. This guards against corruption of the compressed data, and against undetected bugs in bzip2 (hopefully very unlikely). The chances of data corruption going undetected is microscopic, about one chance in four billion for each file processed. Be aware, though, that the check occurs upon decompression, so it can only tell you that something is wrong. It can't help you recover the original uncompressed data. You can use bzip2recover to try to recover data from damaged files.

        Return values: 0 for a normal exit, 1 for environmental problems (file not found, invalid flags, I/O errors, etc.), 2 to indicate a corrupt compressed file, 3 for an internal consistency error (eg, bug) which caused bzip2 to panic.

        2.4. OPTIONS

        -c --stdout

        Compress or decompress to standard output.

        -d --decompress

        Force decompression. bzip2, bunzip2 and bzcat are really the same program, and the decision about what actions to take is done on the basis of which name is used. This flag overrides that mechanism, and forces bzip2 to decompress.

        -z --compress

        The complement to -d: forces compression, regardless of the invokation name.

        -t --test

        Check integrity of the specified file(s), but don't decompress them. This really performs a trial decompression and throws away the result.

        -f --force

        Force overwrite of output files. Normally, bzip2 will not overwrite existing output files. Also forces bzip2 to break hard links to files, which it otherwise wouldn't do.

        bzip2 normally declines to decompress files which don't have the correct magic header bytes. If forced (-f), however, it will pass such files through unmodified. This is how GNU gzip behaves.

        -k --keep

        Keep (don't delete) input files during compression or decompression.

        -s --small

        Reduce memory usage, for compression, decompression and testing. Files are decompressed and tested using a modified algorithm which only requires 2.5 bytes per block byte. This means any file can be decompressed in 2300k of memory, albeit at about half the normal speed.

        During compression, -s selects a block size of 200k, which limits memory use to around the same figure, at the expense of your compression ratio. In short, if your machine is low on memory (8 megabytes or less), use -s for everything. See MEMORY MANAGEMENT below.

        -q --quiet

        Suppress non-essential warning messages. Messages pertaining to I/O errors and other critical events will not be suppressed.

        -v --verbose

        Verbose mode -- show the compression ratio for each file processed. Further -v's increase the verbosity level, spewing out lots of information which is primarily of interest for diagnostic purposes.

        -L --license -V --version

        Display the software version, license terms and conditions.

        -1 (or --fast) to -9 (or -best)

        Set the block size to 100 k, 200 k ... 900 k when compressing. Has no effect when decompressing. See MEMORY MANAGEMENT below. The --fast and --best aliases are primarily for GNU gzip compatibility. In particular, --fast doesn't make things significantly faster. And --best merely selects the default behaviour.

        --

        Treats all subsequent arguments as file names, even if they start with a dash. This is so you can handle files with names beginning with a dash, for example: bzip2 -- -myfilename.

        --repetitive-fast, --repetitive-best

        These flags are redundant in versions 0.9.5 and above. They provided some coarse control over the behaviour of the sorting algorithm in earlier versions, which was sometimes useful. 0.9.5 and above have an improved algorithm which renders these flags irrelevant.

        2.5. MEMORY MANAGEMENT

        bzip2 compresses large files in blocks. The block size affects both the compression ratio achieved, and the amount of memory needed for compression and decompression. The flags -1 through -9 specify the block size to be 100,000 bytes through 900,000 bytes (the default) respectively. At decompression time, the block size used for compression is read from the header of the compressed file, and bunzip2 then allocates itself just enough memory to decompress the file. Since block sizes are stored in compressed files, it follows that the flags -1 to -9 are irrelevant to and so ignored during decompression.

        Compression and decompression requirements, in bytes, can be estimated as:

        Compression:   400k + ( 8 x block size )
        
        Decompression: 100k + ( 4 x block size ), or
                       100k + ( 2.5 x block size )

        Larger block sizes give rapidly diminishing marginal returns. Most of the compression comes from the first two or three hundred k of block size, a fact worth bearing in mind when using bzip2 on small machines. It is also important to appreciate that the decompression memory requirement is set at compression time by the choice of block size.

        For files compressed with the default 900k block size, bunzip2 will require about 3700 kbytes to decompress. To support decompression of any file on a 4 megabyte machine, bunzip2 has an option to decompress using approximately half this amount of memory, about 2300 kbytes. Decompression speed is also halved, so you should use this option only where necessary. The relevant flag is -s.

        In general, try and use the largest block size memory constraints allow, since that maximises the compression achieved. Compression and decompression speed are virtually unaffected by block size.

        Another significant point applies to files which fit in a single block -- that means most files you'd encounter using a large block size. The amount of real memory touched is proportional to the size of the file, since the file is smaller than a block. For example, compressing a file 20,000 bytes long with the flag -9 will cause the compressor to allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560 kbytes of it. Similarly, the decompressor will allocate 3700k but only touch 100k + 20000 * 4 = 180 kbytes.

        Here is a table which summarises the maximum memory usage for different block sizes. Also recorded is the total compressed size for 14 files of the Calgary Text Compression Corpus totalling 3,141,622 bytes. This column gives some feel for how compression varies with block size. These figures tend to understate the advantage of larger block sizes for larger files, since the Corpus is dominated by smaller files.

                Compress   Decompress   Decompress   Corpus
        Flag     usage      usage       -s usage     Size
        
         -1      1200k       500k         350k      914704
         -2      2000k       900k         600k      877703
         -3      2800k      1300k         850k      860338
         -4      3600k      1700k        1100k      846899
         -5      4400k      2100k        1350k      845160
         -6      5200k      2500k        1600k      838626
         -7      6100k      2900k        1850k      834096
         -8      6800k      3300k        2100k      828642
         -9      7600k      3700k        2350k      828642

        2.6. RECOVERING DATA FROM DAMAGED FILES

        bzip2 compresses files in blocks, usually 900kbytes long. Each block is handled independently. If a media or transmission error causes a multi-block .bz2 file to become damaged, it may be possible to recover data from the undamaged blocks in the file.

        The compressed representation of each block is delimited by a 48-bit pattern, which makes it possible to find the block boundaries with reasonable certainty. Each block also carries its own 32-bit CRC, so damaged blocks can be distinguished from undamaged ones.

        bzip2recover is a simple program whose purpose is to search for blocks in .bz2 files, and write each block out into its own .bz2 file. You can then use bzip2 -t to test the integrity of the resulting files, and decompress those which are undamaged.

        bzip2recover takes a single argument, the name of the damaged file, and writes a number of files rec0001file.bz2, rec0002file.bz2, etc, containing the extracted blocks. The output filenames are designed so that the use of wildcards in subsequent processing -- for example, bzip2 -dc rec*file.bz2 > recovered_data -- lists the files in the correct order.

        bzip2recover should be of most use dealing with large .bz2 files, as these will contain many blocks. It is clearly futile to use it on damaged single-block files, since a damaged block cannot be recovered. If you wish to minimise any potential data loss through media or transmission errors, you might consider compressing with a smaller block size.

        2.7. PERFORMANCE NOTES

        The sorting phase of compression gathers together similar strings in the file. Because of this, files containing very long runs of repeated symbols, like "aabaabaabaab ..." (repeated several hundred times) may compress more slowly than normal. Versions 0.9.5 and above fare much better than previous versions in this respect. The ratio between worst-case and average-case compression time is in the region of 10:1. For previous versions, this figure was more like 100:1. You can use the -vvvv option to monitor progress in great detail, if you want.

        Decompression speed is unaffected by these phenomena.

        bzip2 usually allocates several megabytes of memory to operate in, and then charges all over it in a fairly random fashion. This means that performance, both for compressing and decompressing, is largely determined by the speed at which your machine can service cache misses. Because of this, small changes to the code to reduce the miss rate have been observed to give disproportionately large performance improvements. I imagine bzip2 will perform best on machines with very large caches.

        2.8. CAVEATS

        I/O error messages are not as helpful as they could be. bzip2 tries hard to detect I/O errors and exit cleanly, but the details of what the problem is sometimes seem rather misleading.

        This manual page pertains to version 1.0.5 of bzip2. Compressed data created by this version is entirely forwards and backwards compatible with the previous public releases, versions 0.1pl2, 0.9.0 and 0.9.5, 1.0.0, 1.0.1, 1.0.2 and 1.0.3, but with the following exception: 0.9.0 and above can correctly decompress multiple concatenated compressed files. 0.1pl2 cannot do this; it will stop after decompressing just the first file in the stream.

        bzip2recover versions prior to 1.0.2 used 32-bit integers to represent bit positions in compressed files, so it could not handle compressed files more than 512 megabytes long. Versions 1.0.2 and above use 64-bit ints on some platforms which support them (GNU supported targets, and Windows). To establish whether or not bzip2recover was built with such a limitation, run it without arguments. In any event you can build yourself an unlimited version if you can recompile it with MaybeUInt64 set to be an unsigned 64-bit integer.

        2.9. AUTHOR

        Julian Seward, jseward@bzip.org

        The ideas embodied in bzip2 are due to (at least) the following people: Michael Burrows and David Wheeler (for the block sorting transformation), David Wheeler (again, for the Huffman coder), Peter Fenwick (for the structured coding model in the original bzip, and many refinements), and Alistair Moffat, Radford Neal and Ian Witten (for the arithmetic coder in the original bzip). I am much indebted for their help, support and advice. See the manual in the source distribution for pointers to sources of documentation. Christian von Roques encouraged me to look for faster sorting algorithms, so as to speed up compression. Bela Lubkin encouraged me to improve the worst-case compression performance. Donna Robinson XMLised the documentation. Many people sent patches, helped with portability problems, lent machines, gave advice and were generally helpful.

        3.  Programming with libbzip2

        This chapter describes the programming interface to libbzip2.

        For general background information, particularly about memory use and performance aspects, you'd be well advised to read How to use bzip2 as well.

        3.1. Top-level structure

        libbzip2 is a flexible library for compressing and decompressing data in the bzip2 data format. Although packaged as a single entity, it helps to regard the library as three separate parts: the low level interface, and the high level interface, and some utility functions.

        The structure of libbzip2's interfaces is similar to that of Jean-loup Gailly's and Mark Adler's excellent zlib library.

        All externally visible symbols have names beginning BZ2_. This is new in version 1.0. The intention is to minimise pollution of the namespaces of library clients.

        To use any part of the library, you need to #include <bzlib.h> into your sources.

        3.1.1. Low-level summary

        This interface provides services for compressing and decompressing data in memory. There's no provision for dealing with files, streams or any other I/O mechanisms, just straight memory-to-memory work. In fact, this part of the library can be compiled without inclusion of stdio.h, which may be helpful for embedded applications.

        The low-level part of the library has no global variables and is therefore thread-safe.

        Six routines make up the low level interface: BZ2_bzCompressInit, BZ2_bzCompress, and BZ2_bzCompressEnd for compression, and a corresponding trio BZ2_bzDecompressInit, BZ2_bzDecompress and BZ2_bzDecompressEnd for decompression. The *Init functions allocate memory for compression/decompression and do other initialisations, whilst the *End functions close down operations and release memory.

        The real work is done by BZ2_bzCompress and BZ2_bzDecompress. These compress and decompress data from a user-supplied input buffer to a user-supplied output buffer. These buffers can be any size; arbitrary quantities of data are handled by making repeated calls to these functions. This is a flexible mechanism allowing a consumer-pull style of activity, or producer-push, or a mixture of both.

        3.1.2. High-level summary

        This interface provides some handy wrappers around the low-level interface to facilitate reading and writing bzip2 format files (.bz2 files). The routines provide hooks to facilitate reading files in which the bzip2 data stream is embedded within some larger-scale file structure, or where there are multiple bzip2 data streams concatenated end-to-end.

        For reading files, BZ2_bzReadOpen, BZ2_bzRead, BZ2_bzReadClose and BZ2_bzReadGetUnused are supplied. For writing files, BZ2_bzWriteOpen, BZ2_bzWrite and BZ2_bzWriteFinish are available.

        As with the low-level library, no global variables are used so the library is per se thread-safe. However, if I/O errors occur whilst reading or writing the underlying compressed files, you may have to consult errno to determine the cause of the error. In that case, you'd need a C library which correctly supports errno in a multithreaded environment.

        To make the library a little simpler and more portable, BZ2_bzReadOpen and BZ2_bzWriteOpen require you to pass them file handles (FILE*s) which have previously been opened for reading or writing respectively. That avoids portability problems associated with file operations and file attributes, whilst not being much of an imposition on the programmer.

        3.1.3. Utility functions summary

        For very simple needs, BZ2_bzBuffToBuffCompress and BZ2_bzBuffToBuffDecompress are provided. These compress data in memory from one buffer to another buffer in a single function call. You should assess whether these functions fulfill your memory-to-memory compression/decompression requirements before investing effort in understanding the more general but more complex low-level interface.

        Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) has contributed some functions to give better zlib compatibility. These functions are BZ2_bzopen, BZ2_bzread, BZ2_bzwrite, BZ2_bzflush, BZ2_bzclose, BZ2_bzerror and BZ2_bzlibVersion. You may find these functions more convenient for simple file reading and writing, than those in the high-level interface. These functions are not (yet) officially part of the library, and are minimally documented here. If they break, you get to keep all the pieces. I hope to document them properly when time permits.

        Yoshioka also contributed modifications to allow the library to be built as a Windows DLL.

        3.2. Error handling

        The library is designed to recover cleanly in all situations, including the worst-case situation of decompressing random data. I'm not 100% sure that it can always do this, so you might want to add a signal handler to catch segmentation violations during decompression if you are feeling especially paranoid. I would be interested in hearing more about the robustness of the library to corrupted compressed data.

        Version 1.0.3 more robust in this respect than any previous version. Investigations with Valgrind (a tool for detecting problems with memory management) indicate that, at least for the few files I tested, all single-bit errors in the decompressed data are caught properly, with no segmentation faults, no uses of uninitialised data, no out of range reads or writes, and no infinite looping in the decompressor. So it's certainly pretty robust, although I wouldn't claim it to be totally bombproof.

        The file bzlib.h contains all definitions needed to use the library. In particular, you should definitely not include bzlib_private.h.

        In bzlib.h, the various return values are defined. The following list is not intended as an exhaustive description of the circumstances in which a given value may be returned -- those descriptions are given later. Rather, it is intended to convey the rough meaning of each return value. The first five actions are normal and not intended to denote an error situation.

        BZ_OK

        The requested action was completed successfully.

        BZ_RUN_OK, BZ_FLUSH_OK, BZ_FINISH_OK

        In BZ2_bzCompress, the requested flush/finish/nothing-special action was completed successfully.

        BZ_STREAM_END

        Compression of data was completed, or the logical stream end was detected during decompression.

        The following return values indicate an error of some kind.

        BZ_CONFIG_ERROR

        Indicates that the library has been improperly compiled on your platform -- a major configuration error. Specifically, it means that sizeof(char), sizeof(short) and sizeof(int) are not 1, 2 and 4 respectively, as they should be. Note that the library should still work properly on 64-bit platforms which follow the LP64 programming model -- that is, where sizeof(long) and sizeof(void*) are 8. Under LP64, sizeof(int) is still 4, so libbzip2, which doesn't use the long type, is OK.

        BZ_SEQUENCE_ERROR

        When using the library, it is important to call the functions in the correct sequence and with data structures (buffers etc) in the correct states. libbzip2 checks as much as it can to ensure this is happening, and returns BZ_SEQUENCE_ERROR if not. Code which complies precisely with the function semantics, as detailed below, should never receive this value; such an event denotes buggy code which you should investigate.

        BZ_PARAM_ERROR

        Returned when a parameter to a function call is out of range or otherwise manifestly incorrect. As with BZ_SEQUENCE_ERROR, this denotes a bug in the client code. The distinction between BZ_PARAM_ERROR and BZ_SEQUENCE_ERROR is a bit hazy, but still worth making.

        BZ_MEM_ERROR

        Returned when a request to allocate memory failed. Note that the quantity of memory needed to decompress a stream cannot be determined until the stream's header has been read. So BZ2_bzDecompress and BZ2_bzRead may return BZ_MEM_ERROR even though some of the compressed data has been read. The same is not true for compression; once BZ2_bzCompressInit or BZ2_bzWriteOpen have successfully completed, BZ_MEM_ERROR cannot occur.

        BZ_DATA_ERROR

        Returned when a data integrity error is detected during decompression. Most importantly, this means when stored and computed CRCs for the data do not match. This value is also returned upon detection of any other anomaly in the compressed data.

        BZ_DATA_ERROR_MAGIC

        As a special case of BZ_DATA_ERROR, it is sometimes useful to know when the compressed stream does not start with the correct magic bytes ('B' 'Z' 'h').

        BZ_IO_ERROR

        Returned by BZ2_bzRead and BZ2_bzWrite when there is an error reading or writing in the compressed file, and by BZ2_bzReadOpen and BZ2_bzWriteOpen for attempts to use a file for which the error indicator (viz, ferror(f)) is set. On receipt of BZ_IO_ERROR, the caller should consult errno and/or perror to acquire operating-system specific information about the problem.

        BZ_UNEXPECTED_EOF

        Returned by BZ2_bzRead when the compressed file finishes before the logical end of stream is detected.

        BZ_OUTBUFF_FULL

        Returned by BZ2_bzBuffToBuffCompress and BZ2_bzBuffToBuffDecompress to indicate that the output data will not fit into the output buffer provided.

        3.3. Low-level interface

        3.3.1. BZ2_bzCompressInit

        typedef struct {
          char *next_in;
          unsigned int avail_in;
          unsigned int total_in_lo32;
          unsigned int total_in_hi32;
        
          char *next_out;
          unsigned int avail_out;
          unsigned int total_out_lo32;
          unsigned int total_out_hi32;
        
          void *state;
        
          void *(*bzalloc)(void *,int,int);
          void (*bzfree)(void *,void *);
          void *opaque;
        } bz_stream;
        
        int BZ2_bzCompressInit ( bz_stream *strm, 
                                 int blockSize100k, 
                                 int verbosity,
                                 int workFactor );

        Prepares for compression. The bz_stream structure holds all data pertaining to the compression activity. A bz_stream structure should be allocated and initialised prior to the call. The fields of bz_stream comprise the entirety of the user-visible data. state is a pointer to the private data structures required for compression.

        Custom memory allocators are supported, via fields bzalloc, bzfree, and opaque. The value opaque is passed to as the first argument to all calls to bzalloc and bzfree, but is otherwise ignored by the library. The call bzalloc ( opaque, n, m ) is expected to return a pointer p to n * m bytes of memory, and bzfree ( opaque, p ) should free that memory.

        If you don't want to use a custom memory allocator, set bzalloc, bzfree and opaque to NULL, and the library will then use the standard malloc / free routines.

        Before calling BZ2_bzCompressInit, fields bzalloc, bzfree and opaque should be filled appropriately, as just described. Upon return, the internal state will have been allocated and initialised, and total_in_lo32, total_in_hi32, total_out_lo32 and total_out_hi32 will have been set to zero. These four fields are used by the library to inform the caller of the total amount of data passed into and out of the library, respectively. You should not try to change them. As of version 1.0, 64-bit counts are maintained, even on 32-bit platforms, using the _hi32 fields to store the upper 32 bits of the count. So, for example, the total amount of data in is (total_in_hi32 << 32) + total_in_lo32.

        Parameter blockSize100k specifies the block size to be used for compression. It should be a value between 1 and 9 inclusive, and the actual block size used is 100000 x this figure. 9 gives the best compression but takes most memory.

        Parameter verbosity should be set to a number between 0 and 4 inclusive. 0 is silent, and greater numbers give increasingly verbose monitoring/debugging output. If the library has been compiled with -DBZ_NO_STDIO, no such output will appear for any verbosity setting.

        Parameter workFactor controls how the compression phase behaves when presented with worst case, highly repetitive, input data. If compression runs into difficulties caused by repetitive data, the library switches from the standard sorting algorithm to a fallback algorithm. The fallback is slower than the standard algorithm by perhaps a factor of three, but always behaves reasonably, no matter how bad the input.

        Lower values of workFactor reduce the amount of effort the standard algorithm will expend before resorting to the fallback. You should set this parameter carefully; too low, and many inputs will be handled by the fallback algorithm and so compress rather slowly, too high, and your average-to-worst case compression times can become very large. The default value of 30 gives reasonable behaviour over a wide range of circumstances.

        Allowable values range from 0 to 250 inclusive. 0 is a special case, equivalent to using the default value of 30.

        Note that the compressed output generated is the same regardless of whether or not the fallback algorithm is used.

        Be aware also that this parameter may disappear entirely in future versions of the library. In principle it should be possible to devise a good way to automatically choose which algorithm to use. Such a mechanism would render the parameter obsolete.

        Possible return values:

        BZ_CONFIG_ERROR
          if the library has been mis-compiled
        BZ_PARAM_ERROR
          if strm is NULL 
          or blockSize < 1 or blockSize > 9
          or verbosity < 0 or verbosity > 4
          or workFactor < 0 or workFactor > 250
        BZ_MEM_ERROR 
          if not enough memory is available
        BZ_OK 
          otherwise

        Allowable next actions:

        BZ2_bzCompress
          if BZ_OK is returned
          no specific action needed in case of error

        3.3.2. BZ2_bzCompress

        int BZ2_bzCompress ( bz_stream *strm, int action );

        Provides more input and/or output buffer space for the library. The caller maintains input and output buffers, and calls BZ2_bzCompress to transfer data between them.

        Before each call to BZ2_bzCompress, next_in should point at the data to be compressed, and avail_in should indicate how many bytes the library may read. BZ2_bzCompress updates next_in, avail_in and total_in to reflect the number of bytes it has read.

        Similarly, next_out should point to a buffer in which the compressed data is to be placed, with avail_out indicating how much output space is available. BZ2_bzCompress updates next_out, avail_out and total_out to reflect the number of bytes output.

        You may provide and remove as little or as much data as you like on each call of BZ2_bzCompress. In the limit, it is acceptable to supply and remove data one byte at a time, although this would be terribly inefficient. You should always ensure that at least one byte of output space is available at each call.

        A second purpose of BZ2_bzCompress is to request a change of mode of the compressed stream.

        Conceptually, a compressed stream can be in one of four states: IDLE, RUNNING, FLUSHING and FINISHING. Before initialisation (BZ2_bzCompressInit) and after termination (BZ2_bzCompressEnd), a stream is regarded as IDLE.

        Upon initialisation (BZ2_bzCompressInit), the stream is placed in the RUNNING state. Subsequent calls to BZ2_bzCompress should pass BZ_RUN as the requested action; other actions are illegal and will result in BZ_SEQUENCE_ERROR.

        At some point, the calling program will have provided all the input data it wants to. It will then want to finish up -- in effect, asking the library to process any data it might have buffered internally. In this state, BZ2_bzCompress will no longer attempt to read data from next_in, but it will want to write data to next_out. Because the output buffer supplied by the user can be arbitrarily small, the finishing-up operation cannot necessarily be done with a single call of BZ2_bzCompress.

        Instead, the calling program passes BZ_FINISH as an action to BZ2_bzCompress. This changes the stream's state to FINISHING. Any remaining input (ie, next_in[0 .. avail_in-1]) is compressed and transferred to the output buffer. To do this, BZ2_bzCompress must be called repeatedly until all the output has been consumed. At that point, BZ2_bzCompress returns BZ_STREAM_END, and the stream's state is set back to IDLE. BZ2_bzCompressEnd should then be called.

        Just to make sure the calling program does not cheat, the library makes a note of avail_in at the time of the first call to BZ2_bzCompress which has BZ_FINISH as an action (ie, at the time the program has announced its intention to not supply any more input). By comparing this value with that of avail_in over subsequent calls to BZ2_bzCompress, the library can detect any attempts to slip in more data to compress. Any calls for which this is detected will return BZ_SEQUENCE_ERROR. This indicates a programming mistake which should be corrected.

        Instead of asking to finish, the calling program may ask BZ2_bzCompress to take all the remaining input, compress it and terminate the current (Burrows-Wheeler) compression block. This could be useful for error control purposes. The mechanism is analogous to that for finishing: call BZ2_bzCompress with an action of BZ_FLUSH, remove output data, and persist with the BZ_FLUSH action until the value BZ_RUN is returned. As with finishing, BZ2_bzCompress detects any attempt to provide more input data once the flush has begun.

        Once the flush is complete, the stream returns to the normal RUNNING state.

        This all sounds pretty complex, but isn't really. Here's a table which shows which actions are allowable in each state, what action will be taken, what the next state is, and what the non-error return values are. Note that you can't explicitly ask what state the stream is in, but nor do you need to -- it can be inferred from the values returned by BZ2_bzCompress.

        IDLE/any
          Illegal.  IDLE state only exists after BZ2_bzCompressEnd or
          before BZ2_bzCompressInit.
          Return value = BZ_SEQUENCE_ERROR
        
        RUNNING/BZ_RUN
          Compress from next_in to next_out as much as possible.
          Next state = RUNNING
          Return value = BZ_RUN_OK
        
        RUNNING/BZ_FLUSH
          Remember current value of next_in. Compress from next_in
          to next_out as much as possible, but do not accept any more input.
          Next state = FLUSHING
          Return value = BZ_FLUSH_OK
        
        RUNNING/BZ_FINISH
          Remember current value of next_in. Compress from next_in
          to next_out as much as possible, but do not accept any more input.
          Next state = FINISHING
          Return value = BZ_FINISH_OK
        
        FLUSHING/BZ_FLUSH
          Compress from next_in to next_out as much as possible, 
          but do not accept any more input.
          If all the existing input has been used up and all compressed
          output has been removed
            Next state = RUNNING; Return value = BZ_RUN_OK
          else
            Next state = FLUSHING; Return value = BZ_FLUSH_OK
        
        FLUSHING/other     
          Illegal.
          Return value = BZ_SEQUENCE_ERROR
        
        FINISHING/BZ_FINISH
          Compress from next_in to next_out as much as possible,
          but to not accept any more input.  
          If all the existing input has been used up and all compressed
          output has been removed
            Next state = IDLE; Return value = BZ_STREAM_END
          else
            Next state = FINISHING; Return value = BZ_FINISH_OK
        
        FINISHING/other
          Illegal.
          Return value = BZ_SEQUENCE_ERROR

        That still looks complicated? Well, fair enough. The usual sequence of calls for compressing a load of data is:

        1. Get started with BZ2_bzCompressInit.

        2. Shovel data in and shlurp out its compressed form using zero or more calls of BZ2_bzCompress with action = BZ_RUN.

        3. Finish up. Repeatedly call BZ2_bzCompress with action = BZ_FINISH, copying out the compressed output, until BZ_STREAM_END is returned.

        4. Close up and go home. Call BZ2_bzCompressEnd.

        If the data you want to compress fits into your input buffer all at once, you can skip the calls of BZ2_bzCompress ( ..., BZ_RUN ) and just do the BZ2_bzCompress ( ..., BZ_FINISH ) calls.

        All required memory is allocated by BZ2_bzCompressInit. The compression library can accept any data at all (obviously). So you shouldn't get any error return values from the BZ2_bzCompress calls. If you do, they will be BZ_SEQUENCE_ERROR, and indicate a bug in your programming.

        Trivial other possible return values:

        BZ_PARAM_ERROR
          if strm is NULL, or strm->s is NULL

        3.3.3. BZ2_bzCompressEnd

        int BZ2_bzCompressEnd ( bz_stream *strm );

        Releases all memory associated with a compression stream.

        Possible return values:

        BZ_PARAM_ERROR  if strm is NULL or strm->s is NULL
        BZ_OK           otherwise

        3.3.4. BZ2_bzDecompressInit

        int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small );

        Prepares for decompression. As with BZ2_bzCompressInit, a bz_stream record should be allocated and initialised before the call. Fields bzalloc, bzfree and opaque should be set if a custom memory allocator is required, or made NULL for the normal malloc / free routines. Upon return, the internal state will have been initialised, and total_in and total_out will be zero.

        For the meaning of parameter verbosity, see BZ2_bzCompressInit.

        If small is nonzero, the library will use an alternative decompression algorithm which uses less memory but at the cost of decompressing more slowly (roughly speaking, half the speed, but the maximum memory requirement drops to around 2300k). See How to use bzip2 for more information on memory management.

        Note that the amount of memory needed to decompress a stream cannot be determined until the stream's header has been read, so even if BZ2_bzDecompressInit succeeds, a subsequent BZ2_bzDecompress could fail with BZ_MEM_ERROR.

        Possible return values:

        BZ_CONFIG_ERROR
          if the library has been mis-compiled
        BZ_PARAM_ERROR
          if ( small != 0 && small != 1 )
          or (verbosity <; 0 || verbosity > 4)
        BZ_MEM_ERROR
          if insufficient memory is available

        Allowable next actions:

        BZ2_bzDecompress
          if BZ_OK was returned
          no specific action required in case of error

        3.3.5. BZ2_bzDecompress

        int BZ2_bzDecompress ( bz_stream *strm );

        Provides more input and/out output buffer space for the library. The caller maintains input and output buffers, and uses BZ2_bzDecompress to transfer data between them.

        Before each call to BZ2_bzDecompress, next_in should point at the compressed data, and avail_in should indicate how many bytes the library may read. BZ2_bzDecompress updates next_in, avail_in and total_in to reflect the number of bytes it has read.

        Similarly, next_out should point to a buffer in which the uncompressed output is to be placed, with avail_out indicating how much output space is available. BZ2_bzCompress updates next_out, avail_out and total_out to reflect the number of bytes output.

        You may provide and remove as little or as much data as you like on each call of BZ2_bzDecompress. In the limit, it is acceptable to supply and remove data one byte at a time, although this would be terribly inefficient. You should always ensure that at least one byte of output space is available at each call.

        Use of BZ2_bzDecompress is simpler than BZ2_bzCompress.

        You should provide input and remove output as described above, and repeatedly call BZ2_bzDecompress until BZ_STREAM_END is returned. Appearance of BZ_STREAM_END denotes that BZ2_bzDecompress has detected the logical end of the compressed stream. BZ2_bzDecompress will not produce BZ_STREAM_END until all output data has been placed into the output buffer, so once BZ_STREAM_END appears, you are guaranteed to have available all the decompressed output, and BZ2_bzDecompressEnd can safely be called.

        If case of an error return value, you should call BZ2_bzDecompressEnd to clean up and release memory.

        Possible return values:

        BZ_PARAM_ERROR
          if strm is NULL or strm->s is NULL
          or strm->avail_out < 1
        BZ_DATA_ERROR
          if a data integrity error is detected in the compressed stream
        BZ_DATA_ERROR_MAGIC
          if the compressed stream doesn't begin with the right magic bytes
        BZ_MEM_ERROR
          if there wasn't enough memory available
        BZ_STREAM_END
          if the logical end of the data stream was detected and all
          output in has been consumed, eg s-->avail_out > 0
        BZ_OK
          otherwise

        Allowable next actions:

        BZ2_bzDecompress
          if BZ_OK was returned
        BZ2_bzDecompressEnd
          otherwise

        3.3.6. BZ2_bzDecompressEnd

        int BZ2_bzDecompressEnd ( bz_stream *strm );

        Releases all memory associated with a decompression stream.

        Possible return values:

        BZ_PARAM_ERROR
          if strm is NULL or strm->s is NULL
        BZ_OK
          otherwise

        Allowable next actions:

          None.

        3.4. High-level interface

        This interface provides functions for reading and writing bzip2 format files. First, some general points.

        • All of the functions take an int* first argument, bzerror. After each call, bzerror should be consulted first to determine the outcome of the call. If bzerror is BZ_OK, the call completed successfully, and only then should the return value of the function (if any) be consulted. If bzerror is BZ_IO_ERROR, there was an error reading/writing the underlying compressed file, and you should then consult errno / perror to determine the cause of the difficulty. bzerror may also be set to various other values; precise details are given on a per-function basis below.

        • If bzerror indicates an error (ie, anything except BZ_OK and BZ_STREAM_END), you should immediately call BZ2_bzReadClose (or BZ2_bzWriteClose, depending on whether you are attempting to read or to write) to free up all resources associated with the stream. Once an error has been indicated, behaviour of all calls except BZ2_bzReadClose (BZ2_bzWriteClose) is undefined. The implication is that (1) bzerror should be checked after each call, and (2) if bzerror indicates an error, BZ2_bzReadClose (BZ2_bzWriteClose) should then be called to clean up.

        • The FILE* arguments passed to BZ2_bzReadOpen / BZ2_bzWriteOpen should be set to binary mode. Most Unix systems will do this by default, but other platforms, including Windows and Mac, will not. If you omit this, you may encounter problems when moving code to new platforms.

        • Memory allocation requests are handled by malloc / free. At present there is no facility for user-defined memory allocators in the file I/O functions (could easily be added, though).

        3.4.1. BZ2_bzReadOpen

        typedef void BZFILE;
        
        BZFILE *BZ2_bzReadOpen( int *bzerror, FILE *f, 
                                int verbosity, int small,
                                void *unused, int nUnused );

        Prepare to read compressed data from file handle f. f should refer to a file which has been opened for reading, and for which the error indicator (ferror(f))is not set. If small is 1, the library will try to decompress using less memory, at the expense of speed.

        For reasons explained below, BZ2_bzRead will decompress the nUnused bytes starting at unused, before starting to read from the file f. At most BZ_MAX_UNUSED bytes may be supplied like this. If this facility is not required, you should pass NULL and 0 for unused and nUnused respectively.

        For the meaning of parameters small and verbosity, see BZ2_bzDecompressInit.

        The amount of memory needed to decompress a file cannot be determined until the file's header has been read. So it is possible that BZ2_bzReadOpen returns BZ_OK but a subsequent call of BZ2_bzRead will return BZ_MEM_ERROR.

        Possible assignments to bzerror:

        BZ_CONFIG_ERROR
          if the library has been mis-compiled
        BZ_PARAM_ERROR
          if f is NULL
          or small is neither 0 nor 1
          or ( unused == NULL && nUnused != 0 )
          or ( unused != NULL && !(0 <= nUnused <= BZ_MAX_UNUSED) )
        BZ_IO_ERROR
          if ferror(f) is nonzero
        BZ_MEM_ERROR
          if insufficient memory is available
        BZ_OK
          otherwise.

        Possible return values:

        Pointer to an abstract BZFILE
          if bzerror is BZ_OK
        NULL
          otherwise

        Allowable next actions:

        BZ2_bzRead
          if bzerror is BZ_OK
        BZ2_bzClose
          otherwise

        3.4.2. BZ2_bzRead

        int BZ2_bzRead ( int *bzerror, BZFILE *b, void *buf, int len );

        Reads up to len (uncompressed) bytes from the compressed file b into the buffer buf. If the read was successful, bzerror is set to BZ_OK and the number of bytes read is returned. If the logical end-of-stream was detected, bzerror will be set to BZ_STREAM_END, and the number of bytes read is returned. All other bzerror values denote an error.

        BZ2_bzRead will supply len bytes, unless the logical stream end is detected or an error occurs. Because of this, it is possible to detect the stream end by observing when the number of bytes returned is less than the number requested. Nevertheless, this is regarded as inadvisable; you should instead check bzerror after every call and watch out for BZ_STREAM_END.

        Internally, BZ2_bzRead copies data from the compressed file in chunks of size BZ_MAX_UNUSED bytes before decompressing it. If the file contains more bytes than strictly needed to reach the logical end-of-stream, BZ2_bzRead will almost certainly read some of the trailing data before signalling BZ_SEQUENCE_END. To collect the read but unused data once BZ_SEQUENCE_END has appeared, call BZ2_bzReadGetUnused immediately before BZ2_bzReadClose.

        Possible assignments to bzerror:

        BZ_PARAM_ERROR
          if b is NULL or buf is NULL or len < 0
        BZ_SEQUENCE_ERROR
          if b was opened with BZ2_bzWriteOpen
        BZ_IO_ERROR
          if there is an error reading from the compressed file
        BZ_UNEXPECTED_EOF
          if the compressed file ended before 
          the logical end-of-stream was detected
        BZ_DATA_ERROR
          if a data integrity error was detected in the compressed stream
        BZ_DATA_ERROR_MAGIC
          if the stream does not begin with the requisite header bytes 
          (ie, is not a bzip2 data file).  This is really 
          a special case of BZ_DATA_ERROR.
        BZ_MEM_ERROR
          if insufficient memory was available
        BZ_STREAM_END
          if the logical end of stream was detected.
        BZ_OK
          otherwise.

        Possible return values:

        number of bytes read
          if bzerror is BZ_OK or BZ_STREAM_END
        undefined
          otherwise

        Allowable next actions:

        collect data from buf, then BZ2_bzRead or BZ2_bzReadClose
          if bzerror is BZ_OK
        collect data from buf, then BZ2_bzReadClose or BZ2_bzReadGetUnused
          if bzerror is BZ_SEQUENCE_END
        BZ2_bzReadClose
          otherwise

        3.4.3. BZ2_bzReadGetUnused

        void BZ2_bzReadGetUnused( int* bzerror, BZFILE *b, 
                                  void** unused, int* nUnused );

        Returns data which was read from the compressed file but was not needed to get to the logical end-of-stream. *unused is set to the address of the data, and *nUnused to the number of bytes. *nUnused will be set to a value between 0 and BZ_MAX_UNUSED inclusive.

        This function may only be called once BZ2_bzRead has signalled BZ_STREAM_END but before BZ2_bzReadClose.

        Possible assignments to bzerror:

        BZ_PARAM_ERROR
          if b is NULL
          or unused is NULL or nUnused is NULL
        BZ_SEQUENCE_ERROR
          if BZ_STREAM_END has not been signalled
          or if b was opened with BZ2_bzWriteOpen
        BZ_OK
          otherwise

        Allowable next actions:

        BZ2_bzReadClose

        3.4.4. BZ2_bzReadClose

        void BZ2_bzReadClose ( int *bzerror, BZFILE *b );

        Releases all memory pertaining to the compressed file b. BZ2_bzReadClose does not call fclose on the underlying file handle, so you should do that yourself if appropriate. BZ2_bzReadClose should be called to clean up after all error situations.

        Possible assignments to bzerror:

        BZ_SEQUENCE_ERROR
          if b was opened with BZ2_bzOpenWrite
        BZ_OK
          otherwise

        Allowable next actions:

        none

        3.4.5. BZ2_bzWriteOpen

        BZFILE *BZ2_bzWriteOpen( int *bzerror, FILE *f, 
                                 int blockSize100k, int verbosity,
                                 int workFactor );

        Prepare to write compressed data to file handle f. f should refer to a file which has been opened for writing, and for which the error indicator (ferror(f))is not set.

        For the meaning of parameters blockSize100k, verbosity and workFactor, see BZ2_bzCompressInit.

        All required memory is allocated at this stage, so if the call completes successfully, BZ_MEM_ERROR cannot be signalled by a subsequent call to BZ2_bzWrite.

        Possible assignments to bzerror:

        BZ_CONFIG_ERROR
          if the library has been mis-compiled
        BZ_PARAM_ERROR
          if f is NULL
          or blockSize100k < 1 or blockSize100k > 9
        BZ_IO_ERROR
          if ferror(f) is nonzero
        BZ_MEM_ERROR
          if insufficient memory is available
        BZ_OK
          otherwise

        Possible return values:

        Pointer to an abstract BZFILE
          if bzerror is BZ_OK
        NULL
          otherwise

        Allowable next actions:

        BZ2_bzWrite
          if bzerror is BZ_OK
          (you could go directly to BZ2_bzWriteClose, but this would be pretty pointless)
        BZ2_bzWriteClose
          otherwise

        3.4.6. BZ2_bzWrite

        void BZ2_bzWrite ( int *bzerror, BZFILE *b, void *buf, int len );

        Absorbs len bytes from the buffer buf, eventually to be compressed and written to the file.

        Possible assignments to bzerror:

        BZ_PARAM_ERROR
          if b is NULL or buf is NULL or len < 0
        BZ_SEQUENCE_ERROR
          if b was opened with BZ2_bzReadOpen
        BZ_IO_ERROR
          if there is an error writing the compressed file.
        BZ_OK
          otherwise

        3.4.7. BZ2_bzWriteClose

        void BZ2_bzWriteClose( int *bzerror, BZFILE* f,
                               int abandon,
                               unsigned int* nbytes_in,
                               unsigned int* nbytes_out );
        
        void BZ2_bzWriteClose64( int *bzerror, BZFILE* f,
                                 int abandon,
                                 unsigned int* nbytes_in_lo32,
                                 unsigned int* nbytes_in_hi32,
                                 unsigned int* nbytes_out_lo32,
                                 unsigned int* nbytes_out_hi32 );

        Compresses and flushes to the compressed file all data so far supplied by BZ2_bzWrite. The logical end-of-stream markers are also written, so subsequent calls to BZ2_bzWrite are illegal. All memory associated with the compressed file b is released. fflush is called on the compressed file, but it is not fclose'd.

        If BZ2_bzWriteClose is called to clean up after an error, the only action is to release the memory. The library records the error codes issued by previous calls, so this situation will be detected automatically. There is no attempt to complete the compression operation, nor to fflush the compressed file. You can force this behaviour to happen even in the case of no error, by passing a nonzero value to abandon.

        If nbytes_in is non-null, *nbytes_in will be set to be the total volume of uncompressed data handled. Similarly, nbytes_out will be set to the total volume of compressed data written. For compatibility with older versions of the library, BZ2_bzWriteClose only yields the lower 32 bits of these counts. Use BZ2_bzWriteClose64 if you want the full 64 bit counts. These two functions are otherwise absolutely identical.

        Possible assignments to bzerror:

        BZ_SEQUENCE_ERROR
          if b was opened with BZ2_bzReadOpen
        BZ_IO_ERROR
          if there is an error writing the compressed file
        BZ_OK
          otherwise

        3.4.8. Handling embedded compressed data streams

        The high-level library facilitates use of bzip2 data streams which form some part of a surrounding, larger data stream.

        • For writing, the library takes an open file handle, writes compressed data to it, fflushes it but does not fclose it. The calling application can write its own data before and after the compressed data stream, using that same file handle.

        • Reading is more complex, and the facilities are not as general as they could be since generality is hard to reconcile with efficiency. BZ2_bzRead reads from the compressed file in blocks of size BZ_MAX_UNUSED bytes, and in doing so probably will overshoot the logical end of compressed stream. To recover this data once decompression has ended, call BZ2_bzReadGetUnused after the last call of BZ2_bzRead (the one returning BZ_STREAM_END) but before calling BZ2_bzReadClose.

        This mechanism makes it easy to decompress multiple bzip2 streams placed end-to-end. As the end of one stream, when BZ2_bzRead returns BZ_STREAM_END, call BZ2_bzReadGetUnused to collect the unused data (copy it into your own buffer somewhere). That data forms the start of the next compressed stream. To start uncompressing that next stream, call BZ2_bzReadOpen again, feeding in the unused data via the unused / nUnused parameters. Keep doing this until BZ_STREAM_END return coincides with the physical end of file (feof(f)). In this situation BZ2_bzReadGetUnused will of course return no data.

        This should give some feel for how the high-level interface can be used. If you require extra flexibility, you'll have to bite the bullet and get to grips with the low-level interface.

        3.4.9. Standard file-reading/writing code

        Here's how you'd write data to a compressed file:

        FILE*   f;
        BZFILE* b;
        int     nBuf;
        char    buf[ /* whatever size you like */ ];
        int     bzerror;
        int     nWritten;
        
        f = fopen ( "myfile.bz2", "w" );
        if ( !f ) {
         /* handle error */
        }
        b = BZ2_bzWriteOpen( &bzerror, f, 9 );
        if (bzerror != BZ_OK) {
         BZ2_bzWriteClose ( b );
         /* handle error */
        }
        
        while ( /* condition */ ) {
         /* get data to write into buf, and set nBuf appropriately */
         nWritten = BZ2_bzWrite ( &bzerror, b, buf, nBuf );
         if (bzerror == BZ_IO_ERROR) { 
           BZ2_bzWriteClose ( &bzerror, b );
           /* handle error */
         }
        }
        
        BZ2_bzWriteClose( &bzerror, b );
        if (bzerror == BZ_IO_ERROR) {
         /* handle error */
        }

        And to read from a compressed file:

        FILE*   f;
        BZFILE* b;
        int     nBuf;
        char    buf[ /* whatever size you like */ ];
        int     bzerror;
        int     nWritten;
        
        f = fopen ( "myfile.bz2", "r" );
        if ( !f ) {
          /* handle error */
        }
        b = BZ2_bzReadOpen ( &bzerror, f, 0, NULL, 0 );
        if ( bzerror != BZ_OK ) {
          BZ2_bzReadClose ( &bzerror, b );
          /* handle error */
        }
        
        bzerror = BZ_OK;
        while ( bzerror == BZ_OK && /* arbitrary other conditions */) {
          nBuf = BZ2_bzRead ( &bzerror, b, buf, /* size of buf */ );
          if ( bzerror == BZ_OK ) {
            /* do something with buf[0 .. nBuf-1] */
          }
        }
        if ( bzerror != BZ_STREAM_END ) {
           BZ2_bzReadClose ( &bzerror, b );
           /* handle error */
        } else {
           BZ2_bzReadClose ( &bzerror, b );
        }

        3.5. Utility functions

        3.5.1. BZ2_bzBuffToBuffCompress

        int BZ2_bzBuffToBuffCompress( char*         dest,
                                      unsigned int* destLen,
                                      char*         source,
                                      unsigned int  sourceLen,
                                      int           blockSize100k,
                                      int           verbosity,
                                      int           workFactor );

        Attempts to compress the data in source[0 .. sourceLen-1] into the destination buffer, dest[0 .. *destLen-1]. If the destination buffer is big enough, *destLen is set to the size of the compressed data, and BZ_OK is returned. If the compressed data won't fit, *destLen is unchanged, and BZ_OUTBUFF_FULL is returned.

        Compression in this manner is a one-shot event, done with a single call to this function. The resulting compressed data is a complete bzip2 format data stream. There is no mechanism for making additional calls to provide extra input data. If you want that kind of mechanism, use the low-level interface.

        For the meaning of parameters blockSize100k, verbosity and workFactor, see BZ2_bzCompressInit.

        To guarantee that the compressed data will fit in its buffer, allocate an output buffer of size 1% larger than the uncompressed data, plus six hundred extra bytes.

        BZ2_bzBuffToBuffDecompress will not write data at or beyond dest[*destLen], even in case of buffer overflow.

        Possible return values:

        BZ_CONFIG_ERROR
          if the library has been mis-compiled
        BZ_PARAM_ERROR
          if dest is NULL or destLen is NULL
          or blockSize100k < 1 or blockSize100k > 9
          or verbosity < 0 or verbosity > 4
          or workFactor < 0 or workFactor > 250
        BZ_MEM_ERROR
          if insufficient memory is available 
        BZ_OUTBUFF_FULL
          if the size of the compressed data exceeds *destLen
        BZ_OK
          otherwise

        3.5.2. BZ2_bzBuffToBuffDecompress

        int BZ2_bzBuffToBuffDecompress( char*         dest,
                                        unsigned int* destLen,
                                        char*         source,
                                        unsigned int  sourceLen,
                                        int           small,
                                        int           verbosity );

        Attempts to decompress the data in source[0 .. sourceLen-1] into the destination buffer, dest[0 .. *destLen-1]. If the destination buffer is big enough, *destLen is set to the size of the uncompressed data, and BZ_OK is returned. If the compressed data won't fit, *destLen is unchanged, and BZ_OUTBUFF_FULL is returned.

        source is assumed to hold a complete bzip2 format data stream. BZ2_bzBuffToBuffDecompress tries to decompress the entirety of the stream into the output buffer.

        For the meaning of parameters small and verbosity, see BZ2_bzDecompressInit.

        Because the compression ratio of the compressed data cannot be known in advance, there is no easy way to guarantee that the output buffer will be big enough. You may of course make arrangements in your code to record the size of the uncompressed data, but such a mechanism is beyond the scope of this library.

        BZ2_bzBuffToBuffDecompress will not write data at or beyond dest[*destLen], even in case of buffer overflow.

        Possible return values:

        BZ_CONFIG_ERROR
          if the library has been mis-compiled
        BZ_PARAM_ERROR
          if dest is NULL or destLen is NULL
          or small != 0 && small != 1
          or verbosity < 0 or verbosity > 4
        BZ_MEM_ERROR
          if insufficient memory is available 
        BZ_OUTBUFF_FULL
          if the size of the compressed data exceeds *destLen
        BZ_DATA_ERROR
          if a data integrity error was detected in the compressed data
        BZ_DATA_ERROR_MAGIC
          if the compressed data doesn't begin with the right magic bytes
        BZ_UNEXPECTED_EOF
          if the compressed data ends unexpectedly
        BZ_OK
          otherwise

        3.6. zlib compatibility functions

        Yoshioka Tsuneo has contributed some functions to give better zlib compatibility. These functions are BZ2_bzopen, BZ2_bzread, BZ2_bzwrite, BZ2_bzflush, BZ2_bzclose, BZ2_bzerror and BZ2_bzlibVersion. These functions are not (yet) officially part of the library. If they break, you get to keep all the pieces. Nevertheless, I think they work ok.

        typedef void BZFILE;
        
        const char * BZ2_bzlibVersion ( void );

        Returns a string indicating the library version.

        BZFILE * BZ2_bzopen  ( const char *path, const char *mode );
        BZFILE * BZ2_bzdopen ( int        fd,    const char *mode );

        Opens a .bz2 file for reading or writing, using either its name or a pre-existing file descriptor. Analogous to fopen and fdopen.

        int BZ2_bzread  ( BZFILE* b, void* buf, int len );
        int BZ2_bzwrite ( BZFILE* b, void* buf, int len );

        Reads/writes data from/to a previously opened BZFILE. Analogous to fread and fwrite.

        int  BZ2_bzflush ( BZFILE* b );
        void BZ2_bzclose ( BZFILE* b );

        Flushes/closes a BZFILE. BZ2_bzflush doesn't actually do anything. Analogous to fflush and fclose.

        const char * BZ2_bzerror ( BZFILE *b, int *errnum )

        Returns a string describing the more recent error status of b, and also sets *errnum to its numerical value.

        3.7. Using the library in a stdio-free environment

        3.7.1. Getting rid of stdio

        In a deeply embedded application, you might want to use just the memory-to-memory functions. You can do this conveniently by compiling the library with preprocessor symbol BZ_NO_STDIO defined. Doing this gives you a library containing only the following eight functions:

        BZ2_bzCompressInit, BZ2_bzCompress, BZ2_bzCompressEnd BZ2_bzDecompressInit, BZ2_bzDecompress, BZ2_bzDecompressEnd BZ2_bzBuffToBuffCompress, BZ2_bzBuffToBuffDecompress

        When compiled like this, all functions will ignore verbosity settings.

        3.7.2. Critical error handling

        libbzip2 contains a number of internal assertion checks which should, needless to say, never be activated. Nevertheless, if an assertion should fail, behaviour depends on whether or not the library was compiled with BZ_NO_STDIO set.

        For a normal compile, an assertion failure yields the message:

        bzip2/libbzip2: internal error number N.

        This is a bug in bzip2/libbzip2, 1.0.5 of 10 December 2007. Please report it to me at: jseward@bzip.org. If this happened when you were using some program which uses libbzip2 as a component, you should also report this bug to the author(s) of that program. Please make an effort to report this bug; timely and accurate bug reports eventually lead to higher quality software. Thanks. Julian Seward, 10 December 2007.

        where N is some error code number. If N == 1007, it also prints some extra text advising the reader that unreliable memory is often associated with internal error 1007. (This is a frequently-observed-phenomenon with versions 1.0.0/1.0.1).

        exit(3) is then called.

        For a stdio-free library, assertion failures result in a call to a function declared as:

        extern void bz_internal_error ( int errcode );

        The relevant code is passed as a parameter. You should supply such a function.

        In either case, once an assertion failure has occurred, any bz_stream records involved can be regarded as invalid. You should not attempt to resume normal operation with them.

        You may, of course, change critical error handling to suit your needs. As I said above, critical errors indicate bugs in the library and should not occur. All "normal" error situations are indicated via error return codes from functions, and can be recovered from.

        3.8. Making a Windows DLL

        Everything related to Windows has been contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp), so you should send your queries to him (but perhaps Cc: me, jseward@bzip.org).

        My vague understanding of what to do is: using Visual C++ 5.0, open the project file libbz2.dsp, and build. That's all.

        If you can't open the project file for some reason, make a new one, naming these files: blocksort.c, bzlib.c, compress.c, crctable.c, decompress.c, huffman.c, randtable.c and libbz2.def. You will also need to name the header files bzlib.h and bzlib_private.h.

        If you don't use VC++, you may need to define the proprocessor symbol _WIN32.

        Finally, dlltest.c is a sample program using the DLL. It has a project file, dlltest.dsp.

        If you just want a makefile for Visual C, have a look at makefile.msc.

        Be aware that if you compile bzip2 itself on Win32, you must set BZ_UNIX to 0 and BZ_LCCWIN32 to 1, in the file bzip2.c, before compiling. Otherwise the resulting binary won't work correctly.

        I haven't tried any of this stuff myself, but it all looks plausible.

        4. Miscellanea

        These are just some random thoughts of mine. Your mileage may vary.

        4.1. Limitations of the compressed file format

        bzip2-1.0.X, 0.9.5 and 0.9.0 use exactly the same file format as the original version, bzip2-0.1. This decision was made in the interests of stability. Creating yet another incompatible compressed file format would create further confusion and disruption for users.

        Nevertheless, this is not a painless decision. Development work since the release of bzip2-0.1 in August 1997 has shown complexities in the file format which slow down decompression and, in retrospect, are unnecessary. These are:

        • The run-length encoder, which is the first of the compression transformations, is entirely irrelevant. The original purpose was to protect the sorting algorithm from the very worst case input: a string of repeated symbols. But algorithm steps Q6a and Q6b in the original Burrows-Wheeler technical report (SRC-124) show how repeats can be handled without difficulty in block sorting.

        • The randomisation mechanism doesn't really need to be there. Udi Manber and Gene Myers published a suffix array construction algorithm a few years back, which can be employed to sort any block, no matter how repetitive, in O(N log N) time. Subsequent work by Kunihiko Sadakane has produced a derivative O(N (log N)^2) algorithm which usually outperforms the Manber-Myers algorithm.

          I could have changed to Sadakane's algorithm, but I find it to be slower than bzip2's existing algorithm for most inputs, and the randomisation mechanism protects adequately against bad cases. I didn't think it was a good tradeoff to make. Partly this is due to the fact that I was not flooded with email complaints about bzip2-0.1's performance on repetitive data, so perhaps it isn't a problem for real inputs.

          Probably the best long-term solution, and the one I have incorporated into 0.9.5 and above, is to use the existing sorting algorithm initially, and fall back to a O(N (log N)^2) algorithm if the standard algorithm gets into difficulties.

        • The compressed file format was never designed to be handled by a library, and I have had to jump though some hoops to produce an efficient implementation of decompression. It's a bit hairy. Try passing decompress.c through the C preprocessor and you'll see what I mean. Much of this complexity could have been avoided if the compressed size of each block of data was recorded in the data stream.

        • An Adler-32 checksum, rather than a CRC32 checksum, would be faster to compute.

        It would be fair to say that the bzip2 format was frozen before I properly and fully understood the performance consequences of doing so.

        Improvements which I was able to incorporate into 0.9.0, despite using the same file format, are:

        • Single array implementation of the inverse BWT. This significantly speeds up decompression, presumably because it reduces the number of cache misses.

        • Faster inverse MTF transform for large MTF values. The new implementation is based on the notion of sliding blocks of values.

        • bzip2-0.9.0 now reads and writes files with fread and fwrite; version 0.1 used putc and getc. Duh! Well, you live and learn.

        Further ahead, it would be nice to be able to do random access into files. This will require some careful design of compressed file formats.

        4.2. Portability issues

        After some consideration, I have decided not to use GNU autoconf to configure 0.9.5 or 1.0.

        autoconf, admirable and wonderful though it is, mainly assists with portability problems between Unix-like platforms. But bzip2 doesn't have much in the way of portability problems on Unix; most of the difficulties appear when porting to the Mac, or to Microsoft's operating systems. autoconf doesn't help in those cases, and brings in a whole load of new complexity.

        Most people should be able to compile the library and program under Unix straight out-of-the-box, so to speak, especially if you have a version of GNU C available.

        There are a couple of __inline__ directives in the code. GNU C (gcc) should be able to handle them. If you're not using GNU C, your C compiler shouldn't see them at all. If your compiler does, for some reason, see them and doesn't like them, just #define __inline__ to be /* */. One easy way to do this is to compile with the flag -D__inline__=, which should be understood by most Unix compilers.

        If you still have difficulties, try compiling with the macro BZ_STRICT_ANSI defined. This should enable you to build the library in a strictly ANSI compliant environment. Building the program itself like this is dangerous and not supported, since you remove bzip2's checks against compressing directories, symbolic links, devices, and other not-really-a-file entities. This could cause filesystem corruption!

        One other thing: if you create a bzip2 binary for public distribution, please consider linking it statically (gcc -static). This avoids all sorts of library-version issues that others may encounter later on.

        If you build bzip2 on Win32, you must set BZ_UNIX to 0 and BZ_LCCWIN32 to 1, in the file bzip2.c, before compiling. Otherwise the resulting binary won't work correctly.

        4.3. Reporting bugs

        I tried pretty hard to make sure bzip2 is bug free, both by design and by testing. Hopefully you'll never need to read this section for real.

        Nevertheless, if bzip2 dies with a segmentation fault, a bus error or an internal assertion failure, it will ask you to email me a bug report. Experience from years of feedback of bzip2 users indicates that almost all these problems can be traced to either compiler bugs or hardware problems.

        • Recompile the program with no optimisation, and see if it works. And/or try a different compiler. I heard all sorts of stories about various flavours of GNU C (and other compilers) generating bad code for bzip2, and I've run across two such examples myself.

          2.7.X versions of GNU C are known to generate bad code from time to time, at high optimisation levels. If you get problems, try using the flags -O2 -fomit-frame-pointer -fno-strength-reduce. You should specifically not use -funroll-loops.

          You may notice that the Makefile runs six tests as part of the build process. If the program passes all of these, it's a pretty good (but not 100%) indication that the compiler has done its job correctly.

        • If bzip2 crashes randomly, and the crashes are not repeatable, you may have a flaky memory subsystem. bzip2 really hammers your memory hierarchy, and if it's a bit marginal, you may get these problems. Ditto if your disk or I/O subsystem is slowly failing. Yup, this really does happen.

          Try using a different machine of the same type, and see if you can repeat the problem.

        • This isn't really a bug, but ... If bzip2 tells you your file is corrupted on decompression, and you obtained the file via FTP, there is a possibility that you forgot to tell FTP to do a binary mode transfer. That absolutely will cause the file to be non-decompressible. You'll have to transfer it again.

        If you've incorporated libbzip2 into your own program and are getting problems, please, please, please, check that the parameters you are passing in calls to the library, are correct, and in accordance with what the documentation says is allowable. I have tried to make the library robust against such problems, but I'm sure I haven't succeeded.

        Finally, if the above comments don't help, you'll have to send me a bug report. Now, it's just amazing how many people will send me a bug report saying something like:

        bzip2 crashed with segmentation fault on my machine

        and absolutely nothing else. Needless to say, a such a report is totally, utterly, completely and comprehensively 100% useless; a waste of your time, my time, and net bandwidth. With no details at all, there's no way I can possibly begin to figure out what the problem is.

        The rules of the game are: facts, facts, facts. Don't omit them because "oh, they won't be relevant". At the bare minimum:

        Machine type.  Operating system version.  
        Exact version of bzip2 (do bzip2 -V).  
        Exact version of the compiler used.  
        Flags passed to the compiler.

        However, the most important single thing that will help me is the file that you were trying to compress or decompress at the time the problem happened. Without that, my ability to do anything more than speculate about the cause, is limited.

        4.4. Did you get the right package?

        bzip2 is a resource hog. It soaks up large amounts of CPU cycles and memory. Also, it gives very large latencies. In the worst case, you can feed many megabytes of uncompressed data into the library before getting any compressed output, so this probably rules out applications requiring interactive behaviour.

        These aren't faults of my implementation, I hope, but more an intrinsic property of the Burrows-Wheeler transform (unfortunately). Maybe this isn't what you want.

        If you want a compressor and/or library which is faster, uses less memory but gets pretty good compression, and has minimal latency, consider Jean-loup Gailly's and Mark Adler's work, zlib-1.2.1 and gzip-1.2.4. Look for them at http://www.zlib.org and http://www.gzip.org respectively.

        For something faster and lighter still, you might try Markus F X J Oberhumer's LZO real-time compression/decompression library, at http://www.oberhumer.com/opensource.

        4.5. Further Reading

        bzip2 is not research work, in the sense that it doesn't present any new ideas. Rather, it's an engineering exercise based on existing ideas.

        Four documents describe essentially all the ideas behind bzip2:

        Michael Burrows and D. J. Wheeler:
          "A block-sorting lossless data compression algorithm"
           10th May 1994. 
           Digital SRC Research Report 124.
           ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.gz
           If you have trouble finding it, try searching at the
           New Zealand Digital Library, http://www.nzdl.org.

        Daniel S. Hirschberg and Debra A. LeLewer
          "Efficient Decoding of Prefix Codes"
           Communications of the ACM, April 1990, Vol 33, Number 4.
           You might be able to get an electronic copy of this
           from the ACM Digital Library.

        David J. Wheeler
           Program bred3.c and accompanying document bred3.ps.
           This contains the idea behind the multi-table Huffman coding scheme.
           ftp://ftp.cl.cam.ac.uk/users/djw3/

        Jon L. Bentley and Robert Sedgewick
          "Fast Algorithms for Sorting and Searching Strings"
           Available from Sedgewick's web page,
           www.cs.princeton.edu/~rs

        The following paper gives valuable additional insights into the algorithm, but is not immediately the basis of any code used in bzip2.

        Peter Fenwick:
           Block Sorting Text Compression
           Proceedings of the 19th Australasian Computer Science Conference,
             Melbourne, Australia.  Jan 31 - Feb 2, 1996.
           ftp://ftp.cs.auckland.ac.nz/pub/peter-f/ACSC96paper.ps

        Kunihiko Sadakane's sorting algorithm, mentioned above, is available from:

        http://naomi.is.s.u-tokyo.ac.jp/~sada/papers/Sada98b.ps.gz

        The Manber-Myers suffix array construction algorithm is described in a paper available from:

        http://www.cs.arizona.edu/people/gene/PAPERS/suffix.ps

        Finally, the following papers document some investigations I made into the performance of sorting and decompression algorithms:

        Julian Seward
           On the Performance of BWT Sorting Algorithms
           Proceedings of the IEEE Data Compression Conference 2000
             Snowbird, Utah.  28-30 March 2000.

        Julian Seward
           Space-time Tradeoffs in the Inverse B-W Transform
           Proceedings of the IEEE Data Compression Conference 2001
             Snowbird, Utah.  27-29 March 2001.

        berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/module.make000066400000000000000000000003171300674244400242160ustar00rootroot00000000000000SRC += src/misc/bzlib/blocksort.c \ src/misc/bzlib/bzlib.c \ src/misc/bzlib/compress.c \ src/misc/bzlib/crctable.c \ src/misc/bzlib/decompress.c \ src/misc/bzlib/huffman.c \ src/misc/bzlib/randtable.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/bzlib/randtable.c000066400000000000000000000075071300674244400242020ustar00rootroot00000000000000 /*-------------------------------------------------------------*/ /*--- Table for randomising repetitive blocks ---*/ /*--- randtable.c ---*/ /*-------------------------------------------------------------*/ /* ------------------------------------------------------------------ This file is part of bzip2/libbzip2, a program and library for lossless, block-sorting data compression. bzip2/libbzip2 version 1.0.5 of 10 December 2007 Copyright (C) 1996-2007 Julian Seward Please read the WARNING, DISCLAIMER and PATENTS sections in the README file. This program is released under the terms of the license contained in the file LICENSE. ------------------------------------------------------------------ */ #include "bzlib_private.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------*/ Int32 BZ2_rNums[512] = { 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 936, 638 }; /*-------------------------------------------------------------*/ /*--- end randtable.c ---*/ /*-------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/000077500000000000000000000000001300674244400226325ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/cofactor.c000066400000000000000000000246671300674244400246150ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* The cofactor of a cover against a cube "c" is a cover formed by the cofactor of each cube in the cover against c. The cofactor of two cubes is null if they are distance 1 or more apart. If they are distance zero apart, the cofactor is the restriction of the cube to the minterms of c. The cube list contains the following information: T[0] = pointer to a cube identifying the variables that have been cofactored against T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case) T[2] . . = pointers to cubes . T[n-2] T[n-1] = NULL pointer (sentinel) Cofactoring involves repeated application of "cdist0" to check if a cube of the cover intersects the cofactored cube. This can be slow, especially for the recursive descent of the espresso routines. Therefore, a special cofactor routine "scofactor" is provided which assumes the cofactor is only in a single variable. */ /* cofactor -- compute the cofactor of a cover with respect to a cube */ pcube *cofactor(T, c) IN pcube *T; IN register pcube c; { pcube temp = cube.temp[0], *Tc_save, *Tc, *T1; register pcube p; int listlen; listlen = CUBELISTSIZE(T) + 5; /* Allocate a new list of cube pointers (max size is previous size) */ Tc_save = Tc = ALLOC(pcube, listlen); /* pass on which variables have been cofactored against */ *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c)); Tc++; /* Loop for each cube in the list, determine suitability, and save */ for(T1 = T+2; (p = *T1++) != NULL; ) { if (p != c) { #ifdef NO_INLINE if (! cdist0(p, c)) goto false; #else {register int w,last;register unsigned int x;if((last=cube.inword)!=-1) {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w>1)&DISJOINT)goto false;}}}{register int w,var,last; register pcube mask;for(var=cube.num_binary_vars;var= 0; i--) count[i] = 0; } /* Count the number of zeros in each column */ { register int i, *cnt; register unsigned int val; register pcube p, cof = T[0], full = cube.fullset; for(T1 = T+2; (p = *T1++) != NULL; ) for(i = LOOP(p); i > 0; i--) if ((val = full[i] & ~ (p[i] | cof[i]))) { cnt = count + ((i-1) << LOGBPI); #if BPI == 32 if (val & 0xFF000000) { if (val & 0x80000000) cnt[31]++; if (val & 0x40000000) cnt[30]++; if (val & 0x20000000) cnt[29]++; if (val & 0x10000000) cnt[28]++; if (val & 0x08000000) cnt[27]++; if (val & 0x04000000) cnt[26]++; if (val & 0x02000000) cnt[25]++; if (val & 0x01000000) cnt[24]++; } if (val & 0x00FF0000) { if (val & 0x00800000) cnt[23]++; if (val & 0x00400000) cnt[22]++; if (val & 0x00200000) cnt[21]++; if (val & 0x00100000) cnt[20]++; if (val & 0x00080000) cnt[19]++; if (val & 0x00040000) cnt[18]++; if (val & 0x00020000) cnt[17]++; if (val & 0x00010000) cnt[16]++; } #endif if (val & 0xFF00) { if (val & 0x8000) cnt[15]++; if (val & 0x4000) cnt[14]++; if (val & 0x2000) cnt[13]++; if (val & 0x1000) cnt[12]++; if (val & 0x0800) cnt[11]++; if (val & 0x0400) cnt[10]++; if (val & 0x0200) cnt[ 9]++; if (val & 0x0100) cnt[ 8]++; } if (val & 0x00FF) { if (val & 0x0080) cnt[ 7]++; if (val & 0x0040) cnt[ 6]++; if (val & 0x0020) cnt[ 5]++; if (val & 0x0010) cnt[ 4]++; if (val & 0x0008) cnt[ 3]++; if (val & 0x0004) cnt[ 2]++; if (val & 0x0002) cnt[ 1]++; if (val & 0x0001) cnt[ 0]++; } } } /* * Perform counts for each variable: * cdata.var_zeros[var] = number of zeros in the variable * cdata.parts_active[var] = number of active parts for each variable * cdata.vars_active = number of variables which are active * cdata.vars_unate = number of variables which are active and unate * * best -- the variable which is best for splitting based on: * mostactive -- most # active parts in any variable * mostzero -- most # zeros in any variable * mostbalanced -- minimum over the maximum # zeros / part / variable */ { register int var, i, lastbit, active, maxactive; int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000; cdata.vars_unate = cdata.vars_active = 0; for(var = 0; var < cube.num_vars; var++) { if (var < cube.num_binary_vars) { /* special hack for binary vars */ i = count[var*2]; lastbit = count[var*2 + 1]; active = (i > 0) + (lastbit > 0); cdata.var_zeros[var] = i + lastbit; maxactive = MAX(i, lastbit); } else { maxactive = active = cdata.var_zeros[var] = 0; lastbit = cube.last_part[var]; for(i = cube.first_part[var]; i <= lastbit; i++) { cdata.var_zeros[var] += count[i]; active += (count[i] > 0); if (active > maxactive) maxactive = active; } } /* first priority is to maximize the number of active parts */ /* for binary case, this will usually select the output first */ if (active > mostactive) best = var, mostactive = active, mostzero = cdata.var_zeros[best], mostbalanced = maxactive; else if (active == mostactive) { /* secondary condition is to maximize the number zeros */ /* for binary variables, this is the same as minimum # of 2's */ if (cdata.var_zeros[var] > mostzero) best = var, mostzero = cdata.var_zeros[best], mostbalanced = maxactive; else if (cdata.var_zeros[var] == mostzero) /* third condition is to pick a balanced variable */ /* for binary vars, this means roughly equal # 0's and 1's */ if (maxactive < mostbalanced) best = var, mostbalanced = maxactive; } cdata.parts_active[var] = active; cdata.is_unate[var] = (active == 1); cdata.vars_active += (active > 0); cdata.vars_unate += (active == 1); } cdata.best = best; } } int binate_split_select(T, cleft, cright, debug_flag) IN pcube *T; IN register pcube cleft, cright; IN int debug_flag; { int best = cdata.best; register int i, lastbit = cube.last_part[best], halfbit = 0; register pcube cof=T[0]; /* Create the cubes to cofactor against */ (void) set_diff(cleft, cube.fullset, cube.var_mask[best]); (void) set_diff(cright, cube.fullset, cube.var_mask[best]); for(i = cube.first_part[best]; i <= lastbit; i++) if (! is_in_set(cof,i)) halfbit++; for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++) if (! is_in_set(cof,i)) halfbit--, set_insert(cleft, i); for(; i <= lastbit; i++) if (! is_in_set(cof,i)) set_insert(cright, i); if (debug & debug_flag) { (void) printf("BINATE_SPLIT_SELECT: split against %d\n", best); if (verbose_debug) (void) printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright)); } return best; } pcube *cube1list(A) pcover A; { register pcube last, p, *plist, *list; list = plist = ALLOC(pcube, A->count + 3); *plist++ = new_cube(); plist++; foreach_set(A, last, p) { *plist++ = p; } *plist++ = NULL; /* sentinel */ list[1] = (pcube) plist; return list; } pcube *cube2list(A, B) pcover A, B; { register pcube last, p, *plist, *list; list = plist = ALLOC(pcube, A->count + B->count + 3); *plist++ = new_cube(); plist++; foreach_set(A, last, p) { *plist++ = p; } foreach_set(B, last, p) { *plist++ = p; } *plist++ = NULL; list[1] = (pcube) plist; return list; } pcube *cube3list(A, B, C) pcover A, B, C; { register pcube last, p, *plist, *list; plist = ALLOC(pcube, A->count + B->count + C->count + 3); list = plist; *plist++ = new_cube(); plist++; foreach_set(A, last, p) { *plist++ = p; } foreach_set(B, last, p) { *plist++ = p; } foreach_set(C, last, p) { *plist++ = p; } *plist++ = NULL; list[1] = (pcube) plist; return list; } pcover cubeunlist(A1) pcube *A1; { register int i; register pcube p, pdest, cof = A1[0]; register pcover A; A = new_cover(CUBELISTSIZE(A1)); for(i = 2; (p = A1[i]) != NULL; i++) { pdest = GETSET(A, i-2); INLINEset_or(pdest, p, cof); } A->count = CUBELISTSIZE(A1); return A; } void simplify_cubelist(T) pcube *T; { register pcube *Tdest; register int i, ncubes; (void) set_copy(cube.temp[0], T[0]); /* retrieve cofactor */ ncubes = CUBELISTSIZE(T); qsort((char *) (T+2), ncubes, sizeof(pset), (int (*)()) d1_order); Tdest = T+2; /* *Tdest++ = T[2]; */ for(i = 3; i < ncubes; i++) { if (d1_order(&T[i-1], &T[i]) != 0) { *Tdest++ = T[i]; } } *Tdest++ = NULL; /* sentinel */ Tdest[1] = (pcube) Tdest; /* save pointer to last */ } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/cols.c000066400000000000000000000133321300674244400237400ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ //#include "port.h" #include "sparse_int.h" ABC_NAMESPACE_IMPL_START /* * allocate a new col vector */ sm_col * sm_col_alloc() { register sm_col *pcol; #ifdef FAST_AND_LOOSE if (sm_col_freelist == NIL(sm_col)) { pcol = ALLOC(sm_col, 1); } else { pcol = sm_col_freelist; sm_col_freelist = pcol->next_col; } #else pcol = ALLOC(sm_col, 1); #endif pcol->col_num = 0; pcol->length = 0; pcol->first_row = pcol->last_row = NIL(sm_element); pcol->next_col = pcol->prev_col = NIL(sm_col); pcol->flag = 0; pcol->user_word = NIL(char); /* for our user ... */ return pcol; } /* * free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols; * however, freeing a rowumn must still walk down the rowumn discarding * the elements one-by-one; that is the only use for the extra '-DCOLS' * compile flag ... */ void sm_col_free(pcol) register sm_col *pcol; { #if defined(FAST_AND_LOOSE) && ! defined(COLS) if (pcol->first_row != NIL(sm_element)) { /* Add the linked list of col items to the free list */ pcol->last_row->next_row = sm_element_freelist; sm_element_freelist = pcol->first_row; } /* Add the col to the free list of cols */ pcol->next_col = sm_col_freelist; sm_col_freelist = pcol; #else register sm_element *p, *pnext; for(p = pcol->first_row; p != 0; p = pnext) { pnext = p->next_row; sm_element_free(p); } FREE(pcol); #endif } /* * duplicate an existing col */ sm_col * sm_col_dup(pcol) register sm_col *pcol; { register sm_col *pnew; register sm_element *p; pnew = sm_col_alloc(); for(p = pcol->first_row; p != 0; p = p->next_row) { (void) sm_col_insert(pnew, p->row_num); } return pnew; } /* * insert an element into a col vector */ sm_element * sm_col_insert(pcol, row) register sm_col *pcol; register int row; { register sm_element *test, *element; /* get a new item, save its address */ sm_element_alloc(element); test = element; sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length, next_row, prev_row, row_num, row, test); /* if item was not used, free it */ if (element != test) { sm_element_free(element); } /* either way, return the current new value */ return test; } /* * remove an element from a col vector */ void sm_col_remove(pcol, row) register sm_col *pcol; register int row; { register sm_element *p; for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row) ; if (p != 0 && p->row_num == row) { dll_unlink(p, pcol->first_row, pcol->last_row, next_row, prev_row, pcol->length); sm_element_free(p); } } /* * find an element (if it is in the col vector) */ sm_element * sm_col_find(pcol, row) sm_col *pcol; int row; { register sm_element *p; for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row) ; if (p != 0 && p->row_num == row) { return p; } else { return NIL(sm_element); } } /* * return 1 if col p2 contains col p1; 0 otherwise */ int sm_col_contains(p1, p2) sm_col *p1, *p2; { register sm_element *q1, *q2; q1 = p1->first_row; q2 = p2->first_row; while (q1 != 0) { if (q2 == 0 || q1->row_num < q2->row_num) { return 0; } else if (q1->row_num == q2->row_num) { q1 = q1->next_row; q2 = q2->next_row; } else { q2 = q2->next_row; } } return 1; } /* * return 1 if col p1 and col p2 share an element in common */ int sm_col_intersects(p1, p2) sm_col *p1, *p2; { register sm_element *q1, *q2; q1 = p1->first_row; q2 = p2->first_row; if (q1 == 0 || q2 == 0) return 0; for(;;) { if (q1->row_num < q2->row_num) { if ((q1 = q1->next_row) == 0) { return 0; } } else if (q1->row_num > q2->row_num) { if ((q2 = q2->next_row) == 0) { return 0; } } else { return 1; } } } /* * compare two cols, lexical ordering */ int sm_col_compare(p1, p2) sm_col *p1, *p2; { register sm_element *q1, *q2; q1 = p1->first_row; q2 = p2->first_row; while(q1 != 0 && q2 != 0) { if (q1->row_num != q2->row_num) { return q1->row_num - q2->row_num; } q1 = q1->next_row; q2 = q2->next_row; } if (q1 != 0) { return 1; } else if (q2 != 0) { return -1; } else { return 0; } } /* * return the intersection */ sm_col * sm_col_and(p1, p2) sm_col *p1, *p2; { register sm_element *q1, *q2; register sm_col *result; result = sm_col_alloc(); q1 = p1->first_row; q2 = p2->first_row; if (q1 == 0 || q2 == 0) return result; for(;;) { if (q1->row_num < q2->row_num) { if ((q1 = q1->next_row) == 0) { return result; } } else if (q1->row_num > q2->row_num) { if ((q2 = q2->next_row) == 0) { return result; } } else { (void) sm_col_insert(result, q1->row_num); if ((q1 = q1->next_row) == 0) { return result; } if ((q2 = q2->next_row) == 0) { return result; } } } } int sm_col_hash(pcol, modulus) sm_col *pcol; int modulus; { register int sum; register sm_element *p; sum = 0; for(p = pcol->first_row; p != 0; p = p->next_row) { sum = (sum*17 + p->row_num) % modulus; } return sum; } /* * remove an element from a col vector (given a pointer to the element) */ void sm_col_remove_element(pcol, p) register sm_col *pcol; register sm_element *p; { dll_unlink(p, pcol->first_row, pcol->last_row, next_row, prev_row, pcol->length); sm_element_free(p); } void sm_col_print(fp, pcol) FILE *fp; sm_col *pcol; { sm_element *p; for(p = pcol->first_row; p != 0; p = p->next_row) { (void) fprintf(fp, " %d", p->row_num); } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/compl.c000066400000000000000000000417601300674244400241200ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* * module: compl.c * purpose: compute the complement of a multiple-valued function * * The "unate recursive paradigm" is used. After a set of special * cases are examined, the function is split on the "most active * variable". These two halves are complemented recursively, and then * the results are merged. * * Changes (from Version 2.1 to Version 2.2) * 1. Minor bug in compl_lifting -- cubes in the left half were * not marked as active, so that when merging a leaf from the left * hand side, the active flags were essentially random. This led * to minor impredictability problem, but never affected the * accuracy of the results. */ #include "espresso.h" ABC_NAMESPACE_IMPL_START #define USE_COMPL_LIFT 0 #define USE_COMPL_LIFT_ONSET 1 #define USE_COMPL_LIFT_ONSET_COMPLEX 2 #define NO_LIFTING 3 static bool compl_special_cases(); static pcover compl_merge(); static void compl_d1merge(); static pcover compl_cube(); static void compl_lift(); static void compl_lift_onset(); static void compl_lift_onset_complex(); static bool simp_comp_special_cases(); static bool simplify_special_cases(); /* complement -- compute the complement of T */ pcover complement(T) pcube *T; /* T will be disposed of */ { register pcube cl, cr; register int best; pcover Tbar, Tl, Tr; int lifting; static int compl_level = 0; if (debug & COMPL) debug_print(T, "COMPLEMENT", compl_level++); if (compl_special_cases(T, &Tbar) == MAYBE) { /* Allocate space for the partition cubes */ cl = new_cube(); cr = new_cube(); best = binate_split_select(T, cl, cr, COMPL); /* Complement the left and right halves */ Tl = complement(scofactor(T, cl, best)); Tr = complement(scofactor(T, cr, best)); if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) { lifting = USE_COMPL_LIFT_ONSET; } else { lifting = USE_COMPL_LIFT; } Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting); free_cube(cl); free_cube(cr); free_cubelist(T); } if (debug & COMPL) debug1_print(Tbar, "exit COMPLEMENT", --compl_level); return Tbar; } static bool compl_special_cases(T, Tbar) pcube *T; /* will be disposed if answer is determined */ pcover *Tbar; /* returned only if answer determined */ { register pcube *T1, p, ceil, cof=T[0]; pcover A, ceil_compl; /* Check for no cubes in the cover */ if (T[2] == NULL) { *Tbar = sf_addset(new_cover(1), cube.fullset); free_cubelist(T); return TRUE; } /* Check for only a single cube in the cover */ if (T[3] == NULL) { *Tbar = compl_cube(set_or(cof, cof, T[2])); free_cubelist(T); return TRUE; } /* Check for a row of all 1's (implies complement is null) */ for(T1 = T+2; (p = *T1++) != NULL; ) { if (full_row(p, cof)) { *Tbar = new_cover(0); free_cubelist(T); return TRUE; } } /* Check for a column of all 0's which can be factored out */ ceil = set_save(cof); for(T1 = T+2; (p = *T1++) != NULL; ) { INLINEset_or(ceil, ceil, p); } if (! setp_equal(ceil, cube.fullset)) { ceil_compl = compl_cube(ceil); (void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil)); set_free(ceil); *Tbar = sf_append(complement(T), ceil_compl); return TRUE; } set_free(ceil); /* Collect column counts, determine unate variables, etc. */ massive_count(T); /* If single active variable not factored out above, then tautology ! */ if (cdata.vars_active == 1) { *Tbar = new_cover(0); free_cubelist(T); return TRUE; /* Check for unate cover */ } else if (cdata.vars_unate == cdata.vars_active) { A = map_cover_to_unate(T); free_cubelist(T); A = unate_compl(A); *Tbar = map_unate_to_cover(A); sf_free(A); return TRUE; /* Not much we can do about it */ } else { return MAYBE; } } /* * compl_merge -- merge the two cofactors around the splitting * variable * * The merge operation involves intersecting each cube of the left * cofactor with cl, and intersecting each cube of the right cofactor * with cr. The union of these two covers is the merged result. * * In order to reduce the number of cubes, a distance-1 merge is * performed (note that two cubes can only combine distance-1 in the * splitting variable). Also, a simple expand is performed in the * splitting variable (simple implies the covering check for the * expansion is not full containment, but single-cube containment). */ static pcover compl_merge(T1, L, R, cl, cr, var, lifting) pcube *T1; /* Original ON-set */ pcover L, R; /* Complement from each recursion branch */ register pcube cl, cr; /* cubes used for cofactoring */ int var; /* splitting variable */ int lifting; /* whether to perform lifting or not */ { register pcube p, last, pt; pcover T, Tbar; pcube *L1, *R1; if (debug & COMPL) { (void) printf("compl_merge: left %d, right %d\n", L->count, R->count); (void) printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr)); cprint(L); (void) printf("Right is\n"); cprint(R); } /* Intersect each cube with the cofactored cube */ foreach_set(L, last, p) { INLINEset_and(p, p, cl); SET(p, ACTIVE); } foreach_set(R, last, p) { INLINEset_and(p, p, cr); SET(p, ACTIVE); } /* Sort the arrays for a distance-1 merge */ (void) set_copy(cube.temp[0], cube.var_mask[var]); qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), (int (*)()) d1_order); qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), (int (*)()) d1_order); /* Perform distance-1 merge */ compl_d1merge(L1, R1); /* Perform lifting */ switch(lifting) { case USE_COMPL_LIFT_ONSET: T = cubeunlist(T1); compl_lift_onset(L1, T, cr, var); compl_lift_onset(R1, T, cl, var); free_cover(T); break; case USE_COMPL_LIFT_ONSET_COMPLEX: T = cubeunlist(T1); compl_lift_onset_complex(L1, T, var); compl_lift_onset_complex(R1, T, var); free_cover(T); break; case USE_COMPL_LIFT: compl_lift(L1, R1, cr, var); compl_lift(R1, L1, cl, var); break; case NO_LIFTING: break; default: ; } FREE(L1); FREE(R1); /* Re-create the merged cover */ Tbar = new_cover(L->count + R->count); pt = Tbar->data; foreach_set(L, last, p) { INLINEset_copy(pt, p); Tbar->count++; pt += Tbar->wsize; } foreach_active_set(R, last, p) { INLINEset_copy(pt, p); Tbar->count++; pt += Tbar->wsize; } if (debug & COMPL) { (void) printf("Result %d\n", Tbar->count); if (verbose_debug) cprint(Tbar); } free_cover(L); free_cover(R); return Tbar; } /* * compl_lift_simple -- expand in the splitting variable using single * cube containment against the other recursion branch to check * validity of the expansion, and expanding all (or none) of the * splitting variable. */ static void compl_lift(A1, B1, bcube, var) pcube *A1, *B1, bcube; int var; { register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5]; pcube mask = cube.var_mask[var]; (void) set_and(liftor, bcube, mask); /* for each cube in the first array ... */ for(; (a = *A1++) != NULL; ) { if (TESTP(a, ACTIVE)) { /* create a lift of this cube in the merging coord */ (void) set_merge(lift, bcube, a, mask); /* for each cube in the second array */ for(B2 = B1; (b = *B2++) != NULL; ) { INLINEsetp_implies(lift, b, /* when_false => */ continue); /* when_true => fall through to next statement */ /* cube of A1 was contained by some cube of B1, so raise */ INLINEset_or(a, a, liftor); break; } } } } /* * compl_lift_onset -- expand in the splitting variable using a * distance-1 check against the original on-set; expand all (or * none) of the splitting variable. Each cube of A1 is expanded * against the original on-set T. */ static void compl_lift_onset(A1, T, bcube, var) pcube *A1; pcover T; pcube bcube; int var; { register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var]; /* for each active cube from one branch of the complement */ for(; (a = *A1++) != NULL; ) { if (TESTP(a, ACTIVE)) { /* create a lift of this cube in the merging coord */ INLINEset_and(lift, bcube, mask); /* isolate parts to raise */ INLINEset_or(lift, a, lift); /* raise these parts in a */ /* for each cube in the ON-set, check for intersection */ foreach_set(T, last, p) { if (cdist0(p, lift)) { goto nolift; } } INLINEset_copy(a, lift); /* save the raising */ SET(a, ACTIVE); nolift : ; } } } /* * compl_lift_complex -- expand in the splitting variable, but expand all * parts which can possibly expand. * T is the original ON-set * A1 is either the left or right cofactor */ static void compl_lift_onset_complex(A1, T, var) pcube *A1; /* array of pointers to new result */ pcover T; /* original ON-set */ int var; /* which variable we split on */ { register int dist; register pcube last, p, a, xlower; /* for each cube in the complement */ xlower = new_cube(); for(; (a = *A1++) != NULL; ) { if (TESTP(a, ACTIVE)) { /* Find which parts of the splitting variable are forced low */ INLINEset_clear(xlower, cube.size); foreach_set(T, last, p) { if ((dist = cdist01(p, a)) < 2) { if (dist == 0) { fatal("compl: ON-set and OFF-set are not orthogonal"); } else { (void) force_lower(xlower, p, a); } } } (void) set_diff(xlower, cube.var_mask[var], xlower); (void) set_or(a, a, xlower); free_cube(xlower); } } } /* * compl_d1merge -- distance-1 merge in the splitting variable */ static void compl_d1merge(L1, R1) register pcube *L1, *R1; { register pcube pl, pr; /* Find equal cubes between the two cofactors */ for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); ) switch (d1_order(L1, R1)) { case 1: pr = *(++R1); break; /* advance right pointer */ case -1: pl = *(++L1); break; /* advance left pointer */ case 0: RESET(pr, ACTIVE); INLINEset_or(pl, pl, pr); pr = *(++R1); default: ; } } /* compl_cube -- return the complement of a single cube (De Morgan's law) */ static pcover compl_cube(p) register pcube p; { register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset; int var; pcover R; /* Allocate worst-case size cover (to avoid checking overflow) */ R = new_cover(cube.num_vars); /* Compute bit-wise complement of the cube */ INLINEset_diff(diff, full, p); for(var = 0; var < cube.num_vars; var++) { mask = cube.var_mask[var]; /* If the bit-wise complement is not empty in var ... */ if (! setp_disjoint(diff, mask)) { pdest = GETSET(R, R->count++); INLINEset_merge(pdest, diff, full, mask); } } return R; } /* simp_comp -- quick simplification of T */ void simp_comp(T, Tnew, Tbar) pcube *T; /* T will be disposed of */ pcover *Tnew; pcover *Tbar; { register pcube cl, cr; register int best; pcover Tl, Tr, Tlbar, Trbar; int lifting; static int simplify_level = 0; if (debug & COMPL) debug_print(T, "SIMPCOMP", simplify_level++); if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) { /* Allocate space for the partition cubes */ cl = new_cube(); cr = new_cube(); best = binate_split_select(T, cl, cr, COMPL); /* Complement the left and right halves */ simp_comp(scofactor(T, cl, best), &Tl, &Tlbar); simp_comp(scofactor(T, cr, best), &Tr, &Trbar); lifting = USE_COMPL_LIFT; *Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting); lifting = USE_COMPL_LIFT; *Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting); /* All of this work for nothing ? Let's hope not ... */ if ((*Tnew)->count > CUBELISTSIZE(T)) { sf_free(*Tnew); *Tnew = cubeunlist(T); } free_cube(cl); free_cube(cr); free_cubelist(T); } if (debug & COMPL) { debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level); debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level); simplify_level--; } } static bool simp_comp_special_cases(T, Tnew, Tbar) pcube *T; /* will be disposed if answer is determined */ pcover *Tnew; /* returned only if answer determined */ pcover *Tbar; /* returned only if answer determined */ { register pcube *T1, p, ceil, cof=T[0]; pcube last; pcover A; /* Check for no cubes in the cover (function is empty) */ if (T[2] == NULL) { *Tnew = new_cover(1); *Tbar = sf_addset(new_cover(1), cube.fullset); free_cubelist(T); return TRUE; } /* Check for only a single cube in the cover */ if (T[3] == NULL) { (void) set_or(cof, cof, T[2]); *Tnew = sf_addset(new_cover(1), cof); *Tbar = compl_cube(cof); free_cubelist(T); return TRUE; } /* Check for a row of all 1's (function is a tautology) */ for(T1 = T+2; (p = *T1++) != NULL; ) { if (full_row(p, cof)) { *Tnew = sf_addset(new_cover(1), cube.fullset); *Tbar = new_cover(1); free_cubelist(T); return TRUE; } } /* Check for a column of all 0's which can be factored out */ ceil = set_save(cof); for(T1 = T+2; (p = *T1++) != NULL; ) { INLINEset_or(ceil, ceil, p); } if (! setp_equal(ceil, cube.fullset)) { p = new_cube(); (void) set_diff(p, cube.fullset, ceil); (void) set_or(cof, cof, p); set_free(p); simp_comp(T, Tnew, Tbar); /* Adjust the ON-set */ A = *Tnew; foreach_set(A, last, p) { INLINEset_and(p, p, ceil); } /* Compute the new complement */ *Tbar = sf_append(*Tbar, compl_cube(ceil)); set_free(ceil); return TRUE; } set_free(ceil); /* Collect column counts, determine unate variables, etc. */ massive_count(T); /* If single active variable not factored out above, then tautology ! */ if (cdata.vars_active == 1) { *Tnew = sf_addset(new_cover(1), cube.fullset); *Tbar = new_cover(1); free_cubelist(T); return TRUE; /* Check for unate cover */ } else if (cdata.vars_unate == cdata.vars_active) { /* Make the cover minimum by single-cube containment */ A = cubeunlist(T); *Tnew = sf_contain(A); /* Now form a minimum representation of the complement */ A = map_cover_to_unate(T); A = unate_compl(A); *Tbar = map_unate_to_cover(A); sf_free(A); free_cubelist(T); return TRUE; /* Not much we can do about it */ } else { return MAYBE; } } /* simplify -- quick simplification of T */ pcover simplify(T) pcube *T; /* T will be disposed of */ { register pcube cl, cr; register int best; pcover Tbar, Tl, Tr; int lifting; static int simplify_level = 0; if (debug & COMPL) { debug_print(T, "SIMPLIFY", simplify_level++); } if (simplify_special_cases(T, &Tbar) == MAYBE) { /* Allocate space for the partition cubes */ cl = new_cube(); cr = new_cube(); best = binate_split_select(T, cl, cr, COMPL); /* Complement the left and right halves */ Tl = simplify(scofactor(T, cl, best)); Tr = simplify(scofactor(T, cr, best)); lifting = USE_COMPL_LIFT; Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting); /* All of this work for nothing ? Let's hope not ... */ if (Tbar->count > CUBELISTSIZE(T)) { sf_free(Tbar); Tbar = cubeunlist(T); } free_cube(cl); free_cube(cr); free_cubelist(T); } if (debug & COMPL) { debug1_print(Tbar, "exit SIMPLIFY", --simplify_level); } return Tbar; } static bool simplify_special_cases(T, Tnew) pcube *T; /* will be disposed if answer is determined */ pcover *Tnew; /* returned only if answer determined */ { register pcube *T1, p, ceil, cof=T[0]; pcube last; pcover A; /* Check for no cubes in the cover */ if (T[2] == NULL) { *Tnew = new_cover(0); free_cubelist(T); return TRUE; } /* Check for only a single cube in the cover */ if (T[3] == NULL) { *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2])); free_cubelist(T); return TRUE; } /* Check for a row of all 1's (implies function is a tautology) */ for(T1 = T+2; (p = *T1++) != NULL; ) { if (full_row(p, cof)) { *Tnew = sf_addset(new_cover(1), cube.fullset); free_cubelist(T); return TRUE; } } /* Check for a column of all 0's which can be factored out */ ceil = set_save(cof); for(T1 = T+2; (p = *T1++) != NULL; ) { INLINEset_or(ceil, ceil, p); } if (! setp_equal(ceil, cube.fullset)) { p = new_cube(); (void) set_diff(p, cube.fullset, ceil); (void) set_or(cof, cof, p); free_cube(p); A = simplify(T); foreach_set(A, last, p) { INLINEset_and(p, p, ceil); } *Tnew = A; set_free(ceil); return TRUE; } set_free(ceil); /* Collect column counts, determine unate variables, etc. */ massive_count(T); /* If single active variable not factored out above, then tautology ! */ if (cdata.vars_active == 1) { *Tnew = sf_addset(new_cover(1), cube.fullset); free_cubelist(T); return TRUE; /* Check for unate cover */ } else if (cdata.vars_unate == cdata.vars_active) { A = cubeunlist(T); *Tnew = sf_contain(A); free_cubelist(T); return TRUE; /* Not much we can do about it */ } else { return MAYBE; } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/contain.c000066400000000000000000000302261300674244400244340ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* contain.c -- set containment routines These are complex routines for performing containment over a family of sets, but they have the advantage of being much faster than a straightforward n*n routine. First the cubes are sorted by size, and as a secondary key they are sorted so that if two cubes are equal they end up adjacent. We can than quickly remove equal cubes from further consideration by comparing each cube to its neighbor. Finally, because the cubes are sorted by size, we need only check cubes which are larger (or smaller) than a given cube for containment. */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* sf_contain -- perform containment on a set family (delete sets which are contained by some larger set in the family). No assumptions are made about A, and the result will be returned in decreasing order of set size. */ pset_family sf_contain(A) INOUT pset_family A; /* disposes of A */ { int cnt; pset *A1; pset_family R; A1 = sf_sort(A, descend); /* sort into descending order */ cnt = rm_equal(A1, descend); /* remove duplicates */ cnt = rm_contain(A1); /* remove contained sets */ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ sf_free(A); return R; } /* sf_rev_contain -- perform containment on a set family (delete sets which contain some smaller set in the family). No assumptions are made about A, and the result will be returned in increasing order of set size */ pset_family sf_rev_contain(A) INOUT pset_family A; /* disposes of A */ { int cnt; pset *A1; pset_family R; A1 = sf_sort(A, ascend); /* sort into ascending order */ cnt = rm_equal(A1, ascend); /* remove duplicates */ cnt = rm_rev_contain(A1); /* remove containing sets */ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ sf_free(A); return R; } /* sf_ind_contain -- perform containment on a set family (delete sets which are contained by some larger set in the family). No assumptions are made about A, and the result will be returned in decreasing order of set size. Also maintains a set of row_indices to track which rows disappear and how the rows end up permuted. */ pset_family sf_ind_contain(A, row_indices) INOUT pset_family A; /* disposes of A */ INOUT int *row_indices; /* updated with the new values */ { int cnt; pset *A1; pset_family R; A1 = sf_sort(A, descend); /* sort into descending order */ cnt = rm_equal(A1, descend); /* remove duplicates */ cnt = rm_contain(A1); /* remove contained sets */ R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data); sf_free(A); return R; } /* sf_dupl -- delete duplicate sets in a set family */ pset_family sf_dupl(A) INOUT pset_family A; /* disposes of A */ { register int cnt; register pset *A1; pset_family R; A1 = sf_sort(A, descend); /* sort the set family */ cnt = rm_equal(A1, descend); /* remove duplicates */ R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ sf_free(A); return R; } /* sf_union -- form the contained union of two set families (delete sets which are contained by some larger set in the family). A and B are assumed already sorted in decreasing order of set size (and the SIZE field is assumed to contain the set size), and the result will be returned sorted likewise. */ pset_family sf_union(A, B) INOUT pset_family A, B; /* disposes of A and B */ { int cnt; pset_family R; pset *A1 = sf_list(A), *B1 = sf_list(B), *E1; E1 = ALLOC(pset, MAX(A->count, B->count) + 1); cnt = rm2_equal(A1, B1, E1, descend); cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1); R = sf_merge(A1, B1, E1, cnt, A->sf_size); sf_free(A); sf_free(B); return R; } /* dist_merge -- consider all sets to be "or"-ed with "mask" and then delete duplicates from the set family. */ pset_family dist_merge(A, mask) INOUT pset_family A; /* disposes of A */ IN pset mask; /* defines variables to mask out */ { pset *A1; int cnt; pset_family R; (void) set_copy(cube.temp[0], mask); A1 = sf_sort(A, d1_order); cnt = d1_rm_equal(A1, d1_order); R = sf_unlist(A1, cnt, A->sf_size); sf_free(A); return R; } /* d1merge -- perform an efficient distance-1 merge of cubes of A */ pset_family d1merge(A, var) INOUT pset_family A; /* disposes of A */ IN int var; { return dist_merge(A, cube.var_mask[var]); } /* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */ int d1_rm_equal(A1, compare) register pset *A1; /* array of set pointers */ int (*compare)(); /* comparison function */ { register int i, j, dest; dest = 0; if (A1[0] != (pcube) NULL) { for(i = 0, j = 1; A1[j] != (pcube) NULL; j++) if ( (*compare)(&A1[i], &A1[j]) == 0) { /* if sets are equal (under the mask) merge them */ (void) set_or(A1[i], A1[i], A1[j]); } else { /* sets are unequal, so save the set i */ A1[dest++] = A1[i]; i = j; } A1[dest++] = A1[i]; } A1[dest] = (pcube) NULL; return dest; } /* rm_equal -- scan a sorted array of set pointers for duplicate sets */ int rm_equal(A1, compare) INOUT pset *A1; /* updated in place */ IN int (*compare)(); { register pset *p, *pdest = A1; if (*A1 != NULL) { /* If more than one set */ for(p = A1+1; *p != NULL; p++) if ((*compare)(p, p-1) != 0) *pdest++ = *(p-1); *pdest++ = *(p-1); *pdest = NULL; } return pdest - A1; } /* rm_contain -- perform containment over a sorted array of set pointers */ int rm_contain(A1) INOUT pset *A1; /* updated in place */ { register pset *pa, *pb; register pset *pcheck = NULL; // Suppress "might be used uninitialized" register pset a, b; pset *pdest = A1; int last_size = -1; /* Loop for all cubes of A1 */ for(pa = A1; (a = *pa++) != NULL; ) { /* Update the check pointer if the size has changed */ if (SIZE(a) != last_size) last_size = SIZE(a), pcheck = pdest; for(pb = A1; pb != pcheck; ) { b = *pb++; INLINEsetp_implies(a, b, /* when_false => */ continue); goto lnext1; } /* set a was not contained by some larger set, so save it */ *pdest++ = a; lnext1: ; } *pdest = NULL; return pdest - A1; } /* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */ int rm_rev_contain(A1) INOUT pset *A1; /* updated in place */ { register pset *pa, *pb; register pset *pcheck = NULL; // Suppress "might be used uninitialized" register pset a, b; pset *pdest = A1; int last_size = -1; /* Loop for all cubes of A1 */ for(pa = A1; (a = *pa++) != NULL; ) { /* Update the check pointer if the size has changed */ if (SIZE(a) != last_size) last_size = SIZE(a), pcheck = pdest; for(pb = A1; pb != pcheck; ) { b = *pb++; INLINEsetp_implies(b, a, /* when_false => */ continue); goto lnext1; } /* the set a did not contain some smaller set, so save it */ *pdest++ = a; lnext1: ; } *pdest = NULL; return pdest - A1; } /* rm2_equal -- check two sorted arrays of set pointers for equal cubes */ int rm2_equal(A1, B1, E1, compare) INOUT register pset *A1, *B1; /* updated in place */ OUT pset *E1; IN int (*compare)(); { register pset *pda = A1, *pdb = B1, *pde = E1; /* Walk through the arrays advancing pointer to larger cube */ for(; *A1 != NULL && *B1 != NULL; ) switch((*compare)(A1, B1)) { case -1: /* "a" comes before "b" */ *pda++ = *A1++; break; case 0: /* equal cubes */ *pde++ = *A1++; B1++; break; case 1: /* "a" is to follow "b" */ *pdb++ = *B1++; break; } /* Finish moving down the pointers of A and B */ while (*A1 != NULL) *pda++ = *A1++; while (*B1 != NULL) *pdb++ = *B1++; *pda = *pdb = *pde = NULL; return pde - E1; } /* rm2_contain -- perform containment between two arrays of set pointers */ int rm2_contain(A1, B1) INOUT pset *A1; /* updated in place */ IN pset *B1; /* unchanged */ { register pset *pa, *pb, a, b, *pdest = A1; /* for each set in the first array ... */ for(pa = A1; (a = *pa++) != NULL; ) { /* for each set in the second array which is larger ... */ for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) { INLINEsetp_implies(a, b, /* when_false => */ continue); /* set was contained in some set of B, so don't save pointer */ goto lnext1; } /* set wasn't contained in any set of B, so save the pointer */ *pdest++ = a; lnext1: ; } *pdest = NULL; /* sentinel */ return pdest - A1; /* # elements in A1 */ } /* sf_sort -- sort the sets of A */ pset *sf_sort(A, compare) IN pset_family A; IN int (*compare)(); { register pset p, last, *pdest, *A1; /* Create a single array pointing to each cube of A */ pdest = A1 = ALLOC(pset, A->count + 1); foreach_set(A, last, p) { PUTSIZE(p, set_ord(p)); /* compute the set size */ *pdest++ = p; /* save the pointer */ } *pdest = NULL; /* Sentinel -- never seen by sort */ /* Sort cubes by size */ qsort((char *) A1, A->count, sizeof(pset), compare); return A1; } /* sf_list -- make a list of pointers to the sets in a set family */ pset *sf_list(A) IN register pset_family A; { register pset p, last, *pdest, *A1; /* Create a single array pointing to each cube of A */ pdest = A1 = ALLOC(pset, A->count + 1); foreach_set(A, last, p) *pdest++ = p; /* save the pointer */ *pdest = NULL; /* Sentinel */ return A1; } /* sf_unlist -- make a set family out of a list of pointers to sets */ pset_family sf_unlist(A1, totcnt, size) IN pset *A1; IN int totcnt, size; { register pset pr, p, *pa; pset_family R = sf_new(totcnt, size); R->count = totcnt; for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize) INLINEset_copy(pr, p); FREE(A1); return R; } /* sf_ind_unlist -- make a set family out of a list of pointers to sets */ pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst) IN pset *A1; IN int totcnt, size; INOUT int *row_indices; IN register pset pfirst; { register pset pr, p, *pa; register int i, *new_row_indices; pset_family R = sf_new(totcnt, size); R->count = totcnt; new_row_indices = ALLOC(int, totcnt); for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) { INLINEset_copy(pr, p); new_row_indices[i] = row_indices[(p - pfirst)/R->wsize]; } for(i = 0; i < totcnt; i++) row_indices[i] = new_row_indices[i]; FREE(new_row_indices); FREE(A1); return R; } /* sf_merge -- merge three sorted lists of set pointers */ pset_family sf_merge(A1, B1, E1, totcnt, size) INOUT pset *A1, *B1, *E1; /* will be disposed of */ IN int totcnt, size; { register pset pr, ps, *pmin, *pmid, *pmax; pset_family R; pset *temp[3], *swap; int i, j, n; /* Allocate the result set_family */ R = sf_new(totcnt, size); R->count = totcnt; pr = R->data; /* Quick bubble sort to order the top member of the three arrays */ n = 3; temp[0] = A1; temp[1] = B1; temp[2] = E1; for(i = 0; i < n-1; i++) for(j = i+1; j < n; j++) if (desc1(*temp[i], *temp[j]) > 0) { swap = temp[j]; temp[j] = temp[i]; temp[i] = swap; } pmin = temp[0]; pmid = temp[1]; pmax = temp[2]; /* Save the minimum element, then update pmin, pmid, pmax */ while (*pmin != (pset) NULL) { ps = *pmin++; INLINEset_copy(pr, ps); pr += R->wsize; if (desc1(*pmin, *pmax) > 0) { swap = pmax; pmax = pmin; pmin = pmid; pmid = swap; } else if (desc1(*pmin, *pmid) > 0) { swap = pmin; pmin = pmid; pmid = swap; } } FREE(A1); FREE(B1); FREE(E1); return R; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/cubehack.c000066400000000000000000000055151300674244400245510ustar00rootroot00000000000000/* * Revision Control Information * * $Source: /vol/opua/opua2/sis/sis-1.1/common/src/sis/node/RCS/cubehack.c,v $ * $Author: sis $ * $Revision: 1.2 $ * $Date: 1992/05/06 18:57:41 $ * */ /* #include "sis.h" #include "node_int.h" #ifdef lint struct cube_struct cube; bool summary; bool trace; bool remove_essential; bool force_irredundant; bool unwrap_onset; bool single_expand; bool pos; bool recompute_onset; bool use_super_gasp; bool use_random_order; #endif */ #include "espresso.h" ABC_NAMESPACE_IMPL_START void cautious_define_cube_size(n) int n; { if (cube.fullset != 0 && cube.num_binary_vars == n) return; if (cube.fullset != 0) { setdown_cube(); FREE(cube.part_size); } cube.num_binary_vars = cube.num_vars = n; cube.part_size = ALLOC(int, n); cube_setup(); } void define_cube_size(n) int n; { register int q, i; static int called_before = 0; /* check if the cube is already just the right size */ if (cube.fullset != 0 && cube.num_binary_vars == n && cube.num_vars == n) return; /* We can't handle more than 100 inputs */ if (n > 100) { cautious_define_cube_size(n); called_before = 0; return; } if (cube.fullset == 0 || ! called_before) { cautious_define_cube_size(100); called_before = 1; } cube.num_vars = n; cube.num_binary_vars = n; cube.num_mv_vars = 0; cube.output = -1; cube.size = n * 2; /* first_part, last_part, first_word, last_word, part_size OKAY */ /* cube.sparse is OKAY */ /* need to completely re-make cube.fullset and cube.binary_mask */ (void) set_fill(cube.fullset, n*2); (void) set_fill(cube.binary_mask, n*2); /* need to resize each set in cube.var_mask and cube.temp */ q = cube.fullset[0]; for(i = 0; i < cube.num_vars; i++) cube.var_mask[i][0] = q; for(i = 0; i < CUBE_TEMP; i++) cube.temp[i][0] = q; /* need to resize cube.emptyset and cube.mv_mask */ cube.emptyset[0] = q; cube.mv_mask[0] = q; /* need to reset the inword and inmask */ if (cube.num_binary_vars != 0) { cube.inword = cube.last_word[cube.num_binary_vars - 1]; cube.inmask = cube.binary_mask[cube.inword] & DISJOINT; } else { cube.inword = -1; cube.inmask = 0; } /* cdata (entire structure) is OKAY */ } void undefine_cube_size() { if (cube.num_binary_vars > 100) { if (cube.fullset != 0) { setdown_cube(); FREE(cube.part_size); } } else { cube.num_vars = cube.num_binary_vars = 100; if (cube.fullset != 0) { setdown_cube(); FREE(cube.part_size); } } } void set_espresso_flags() { summary = FALSE; trace = FALSE; remove_essential = TRUE; force_irredundant = TRUE; unwrap_onset = TRUE; single_expand = FALSE; pos = FALSE; recompute_onset = FALSE; use_super_gasp = FALSE; use_random_order = FALSE; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/cubestr.c000066400000000000000000000106011300674244400244430ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* Module: cubestr.c -- routines for managing the global cube structure */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* cube_setup -- assume that the fields "num_vars", "num_binary_vars", and part_size[num_binary_vars .. num_vars-1] are setup, and initialize the rest of cube and cdata. If a part_size is < 0, then the field size is abs(part_size) and the field read from the input is symbolic. */ void cube_setup() { register int i, var; register pcube p; if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars) fatal("cube size is silly, error in .i/.o or .mv"); cube.num_mv_vars = cube.num_vars - cube.num_binary_vars; cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1; cube.size = 0; cube.first_part = ALLOC(int, cube.num_vars); cube.last_part = ALLOC(int, cube.num_vars); cube.first_word = ALLOC(int, cube.num_vars); cube.last_word = ALLOC(int, cube.num_vars); for(var = 0; var < cube.num_vars; var++) { if (var < cube.num_binary_vars) cube.part_size[var] = 2; cube.first_part[var] = cube.size; cube.first_word[var] = WHICH_WORD(cube.size); cube.size += ABS(cube.part_size[var]); cube.last_part[var] = cube.size - 1; cube.last_word[var] = WHICH_WORD(cube.size - 1); } cube.var_mask = ALLOC(pset, cube.num_vars); cube.sparse = ALLOC(int, cube.num_vars); cube.binary_mask = new_cube(); cube.mv_mask = new_cube(); for(var = 0; var < cube.num_vars; var++) { p = cube.var_mask[var] = new_cube(); for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) set_insert(p, i); if (var < cube.num_binary_vars) { INLINEset_or(cube.binary_mask, cube.binary_mask, p); cube.sparse[var] = 0; } else { INLINEset_or(cube.mv_mask, cube.mv_mask, p); cube.sparse[var] = 1; } } if (cube.num_binary_vars == 0) cube.inword = -1; else { cube.inword = cube.last_word[cube.num_binary_vars - 1]; cube.inmask = cube.binary_mask[cube.inword] & DISJOINT; } cube.temp = ALLOC(pset, CUBE_TEMP); for(i = 0; i < CUBE_TEMP; i++) cube.temp[i] = new_cube(); cube.fullset = set_fill(new_cube(), cube.size); cube.emptyset = new_cube(); cdata.part_zeros = ALLOC(int, cube.size); cdata.var_zeros = ALLOC(int, cube.num_vars); cdata.parts_active = ALLOC(int, cube.num_vars); cdata.is_unate = ALLOC(int, cube.num_vars); } /* setdown_cube -- free memory allocated for the cube/cdata structs (free's all but the part_size array) (I wanted to call this cube_setdown, but that violates the 8-character external routine limit on the IBM !) */ void setdown_cube() { register int i, var; FREE(cube.first_part); FREE(cube.last_part); FREE(cube.first_word); FREE(cube.last_word); FREE(cube.sparse); free_cube(cube.binary_mask); free_cube(cube.mv_mask); free_cube(cube.fullset); free_cube(cube.emptyset); for(var = 0; var < cube.num_vars; var++) free_cube(cube.var_mask[var]); FREE(cube.var_mask); for(i = 0; i < CUBE_TEMP; i++) free_cube(cube.temp[i]); FREE(cube.temp); FREE(cdata.part_zeros); FREE(cdata.var_zeros); FREE(cdata.parts_active); FREE(cdata.is_unate); cube.first_part = cube.last_part = (int *) NULL; cube.first_word = cube.last_word = (int *) NULL; cube.sparse = (int *) NULL; cube.binary_mask = cube.mv_mask = (pcube) NULL; cube.fullset = cube.emptyset = (pcube) NULL; cube.var_mask = cube.temp = (pcube *) NULL; cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL; cdata.is_unate = (bool *) NULL; } void save_cube_struct() { temp_cube_save = cube; /* structure copy ! */ temp_cdata_save = cdata; /* "" */ cube.first_part = cube.last_part = (int *) NULL; cube.first_word = cube.last_word = (int *) NULL; cube.part_size = (int *) NULL; cube.binary_mask = cube.mv_mask = (pcube) NULL; cube.fullset = cube.emptyset = (pcube) NULL; cube.var_mask = cube.temp = (pcube *) NULL; cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL; cdata.is_unate = (bool *) NULL; } void restore_cube_struct() { cube = temp_cube_save; /* structure copy ! */ cdata = temp_cdata_save; /* "" */ } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/cvrin.c000066400000000000000000000523021300674244400241210ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* module: cvrin.c purpose: cube and cover input routines */ #include #include "espresso.h" ABC_NAMESPACE_IMPL_START static bool line_length_error; static int lineno; void skip_line(fpin, fpout, echo) register FILE *fpin, *fpout; register bool echo; { register int ch; while ((ch=getc(fpin)) != EOF && ch != '\n') if (echo) putc(ch, fpout); if (echo) putc('\n', fpout); lineno++; } char *get_word(fp, word) register FILE *fp; register char *word; { register int ch, i = 0; while ((ch = getc(fp)) != EOF && isspace(ch)) ; word[i++] = ch; while ((ch = getc(fp)) != EOF && ! isspace(ch)) word[i++] = ch; word[i++] = '\0'; return word; } /* * Yes, I know this routine is a mess */ void read_cube(fp, PLA) register FILE *fp; pPLA PLA; { register int var, i; pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2]; bool savef = FALSE, saved = FALSE, saver = FALSE; char token[256]; /* for kiss read hack */ int varx, first, last, offset; /* for kiss read hack */ set_clear(cf, cube.size); /* Loop and read binary variables */ for(var = 0; var < cube.num_binary_vars; var++) switch(getc(fp)) { case EOF: goto bad_char; case '\n': if (! line_length_error) (void) fprintf(stderr, "product term(s) %s\n", "span more than one line (warning only)"); line_length_error = TRUE; lineno++; var--; break; case ' ': case '|': case '\t': var--; break; case '2': case '-': set_insert(cf, var*2+1); case '0': set_insert(cf, var*2); break; case '1': set_insert(cf, var*2+1); break; case '?': break; default: goto bad_char; } /* Loop for the all but one of the multiple-valued variables */ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) /* Read a symbolic multiple-valued variable */ if (cube.part_size[var] < 0) { (void) fscanf(fp, "%s", token); if (equal(token, "-") || equal(token, "ANY")) { if (kiss && var == cube.num_vars - 2) { /* leave it empty */ } else { /* make it full */ set_or(cf, cf, cube.var_mask[var]); } } else if (equal(token, "~")) { ; /* leave it empty ... (?) */ } else { if (kiss && var == cube.num_vars - 2) varx = var - 1, offset = ABS(cube.part_size[var-1]); else varx = var, offset = 0; /* Find the symbolic label in the label table */ first = cube.first_part[varx]; last = cube.last_part[varx]; for(i = first; i <= last; i++) if (PLA->label[i] == (char *) NULL) { PLA->label[i] = util_strsav(token); /* add new label */ set_insert(cf, i+offset); break; } else if (equal(PLA->label[i], token)) { set_insert(cf, i+offset); /* use column i */ break; } if (i > last) { (void) fprintf(stderr, "declared size of variable %d (counting from variable 0) is too small\n", var); exit(-1); } } } else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) switch (getc(fp)) { case EOF: goto bad_char; case '\n': if (! line_length_error) (void) fprintf(stderr, "product term(s) %s\n", "span more than one line (warning only)"); line_length_error = TRUE; lineno++; i--; break; case ' ': case '|': case '\t': i--; break; case '1': set_insert(cf, i); case '0': break; default: goto bad_char; } /* Loop for last multiple-valued variable */ if (kiss) { saver = savef = TRUE; (void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]); } else set_copy(cr, cf); set_copy(cd, cf); for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) switch (getc(fp)) { case EOF: goto bad_char; case '\n': if (! line_length_error) (void) fprintf(stderr, "product term(s) %s\n", "span more than one line (warning only)"); line_length_error = TRUE; lineno++; i--; break; case ' ': case '|': case '\t': i--; break; case '4': case '1': if (PLA->pla_type & F_type) set_insert(cf, i), savef = TRUE; break; case '3': case '0': if (PLA->pla_type & R_type) set_insert(cr, i), saver = TRUE; break; case '2': case '-': if (PLA->pla_type & D_type) set_insert(cd, i), saved = TRUE; case '~': break; default: goto bad_char; } if (savef) PLA->F = sf_addset(PLA->F, cf); if (saved) PLA->D = sf_addset(PLA->D, cd); if (saver) PLA->R = sf_addset(PLA->R, cr); return; bad_char: (void) fprintf(stderr, "(warning): input line #%d ignored\n", lineno); skip_line(fp, stdout, TRUE); return; } void parse_pla(fp, PLA) IN FILE *fp; INOUT pPLA PLA; { int i, var, ch, np, last; char word[256]; lineno = 1; line_length_error = FALSE; loop: switch(ch = getc(fp)) { case EOF: return; case '\n': lineno++; case ' ': case '\t': case '\f': case '\r': break; case '#': (void) ungetc(ch, fp); skip_line(fp, stdout, echo_comments); break; case '.': /* .i gives the cube input size (binary-functions only) */ if (equal(get_word(fp, word), "i")) { if (cube.fullset != NULL) { (void) fprintf(stderr, "extra .i ignored\n"); skip_line(fp, stdout, /* echo */ FALSE); } else { if (fscanf(fp, "%d", &cube.num_binary_vars) != 1) fatal("error reading .i"); cube.num_vars = cube.num_binary_vars + 1; cube.part_size = ALLOC(int, cube.num_vars); } /* .o gives the cube output size (binary-functions only) */ } else if (equal(word, "o")) { if (cube.fullset != NULL) { (void) fprintf(stderr, "extra .o ignored\n"); skip_line(fp, stdout, /* echo */ FALSE); } else { if (cube.part_size == NULL) fatal(".o cannot appear before .i"); if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1) fatal("error reading .o"); cube_setup(); PLA_labels(PLA); } /* .mv gives the cube size for a multiple-valued function */ } else if (equal(word, "mv")) { if (cube.fullset != NULL) { (void) fprintf(stderr, "extra .mv ignored\n"); skip_line(fp, stdout, /* echo */ FALSE); } else { if (cube.part_size != NULL) fatal("cannot mix .i and .mv"); if (fscanf(fp,"%d %d", &cube.num_vars,&cube.num_binary_vars) != 2) fatal("error reading .mv"); if (cube.num_binary_vars < 0) fatal("num_binary_vars (second field of .mv) cannot be negative"); if (cube.num_vars < cube.num_binary_vars) fatal( "num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)"); cube.part_size = ALLOC(int, cube.num_vars); for(var=cube.num_binary_vars; var < cube.num_vars; var++) if (fscanf(fp, "%d", &(cube.part_size[var])) != 1) fatal("error reading .mv"); cube_setup(); PLA_labels(PLA); } /* .p gives the number of product terms -- we ignore it */ } else if (equal(word, "p")) (void) fscanf(fp, "%d", &np); /* .e and .end specify the end of the file */ else if (equal(word, "e") || equal(word,"end")) { if (cube.fullset == NULL) { /* fatal("unknown PLA size, need .i/.o or .mv");*/ } else if (PLA->F == NULL) { PLA->F = new_cover(10); PLA->D = new_cover(10); PLA->R = new_cover(10); } return; } /* .kiss turns on the kiss-hack option */ else if (equal(word, "kiss")) kiss = TRUE; /* .type specifies a logical type for the PLA */ else if (equal(word, "type")) { (void) get_word(fp, word); for(i = 0; pla_types[i].key != 0; i++) if (equal(pla_types[i].key + 1, word)) { PLA->pla_type = pla_types[i].value; break; } if (pla_types[i].key == 0) fatal("unknown type in .type command"); /* parse the labels */ } else if (equal(word, "ilb")) { if (cube.fullset == NULL) fatal("PLA size must be declared before .ilb or .ob"); if (PLA->label == NULL) PLA_labels(PLA); for(var = 0; var < cube.num_binary_vars; var++) { (void) get_word(fp, word); i = cube.first_part[var]; PLA->label[i+1] = util_strsav(word); PLA->label[i] = ALLOC(char, strlen(word) + 6); (void) sprintf(PLA->label[i], "%s.bar", word); } } else if (equal(word, "ob")) { if (cube.fullset == NULL) fatal("PLA size must be declared before .ilb or .ob"); if (PLA->label == NULL) PLA_labels(PLA); var = cube.num_vars - 1; for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { (void) get_word(fp, word); PLA->label[i] = util_strsav(word); } /* .label assigns labels to multiple-valued variables */ } else if (equal(word, "label")) { if (cube.fullset == NULL) fatal("PLA size must be declared before .label"); if (PLA->label == NULL) PLA_labels(PLA); if (fscanf(fp, "var=%d", &var) != 1) fatal("Error reading labels"); for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { (void) get_word(fp, word); PLA->label[i] = util_strsav(word); } } else if (equal(word, "symbolic")) { symbolic_t *newlist, *p1; if (read_symbolic(fp, PLA, word, &newlist)) { if (PLA->symbolic == NIL(symbolic_t)) { PLA->symbolic = newlist; } else { for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t); p1=p1->next){ } p1->next = newlist; } } else { fatal("error reading .symbolic"); } } else if (equal(word, "symbolic-output")) { symbolic_t *newlist, *p1; if (read_symbolic(fp, PLA, word, &newlist)) { if (PLA->symbolic_output == NIL(symbolic_t)) { PLA->symbolic_output = newlist; } else { for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t); p1=p1->next){ } p1->next = newlist; } } else { fatal("error reading .symbolic-output"); } /* .phase allows a choice of output phases */ } else if (equal(word, "phase")) { if (cube.fullset == NULL) fatal("PLA size must be declared before .phase"); if (PLA->phase != NULL) { (void) fprintf(stderr, "extra .phase ignored\n"); skip_line(fp, stdout, /* echo */ FALSE); } else { do ch = getc(fp); while (ch == ' ' || ch == '\t'); (void) ungetc(ch, fp); PLA->phase = set_save(cube.fullset); last = cube.last_part[cube.num_vars - 1]; for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++) if ((ch = getc(fp)) == '0') set_remove(PLA->phase, i); else if (ch != '1') fatal("only 0 or 1 allowed in phase description"); } /* .pair allows for bit-pairing input variables */ } else if (equal(word, "pair")) { int j; if (PLA->pair != NULL) { (void) fprintf(stderr, "extra .pair ignored\n"); } else { ppair pair; PLA->pair = pair = ALLOC(pair_t, 1); if (fscanf(fp, "%d", &(pair->cnt)) != 1) fatal("syntax error in .pair"); pair->var1 = ALLOC(int, pair->cnt); pair->var2 = ALLOC(int, pair->cnt); for(i = 0; i < pair->cnt; i++) { (void) get_word(fp, word); if (word[0] == '(') (void) strcpy(word, word+1); if (label_index(PLA, word, &var, &j)) { pair->var1[i] = var+1; } else { fatal("syntax error in .pair"); } (void) get_word(fp, word); if (word[strlen(word)-1] == ')') { word[strlen(word)-1]='\0'; } if (label_index(PLA, word, &var, &j)) { pair->var2[i] = var+1; } else { fatal("syntax error in .pair"); } } } } else { if (echo_unknown_commands) printf("%c%s ", ch, word); skip_line(fp, stdout, echo_unknown_commands); } break; default: (void) ungetc(ch, fp); if (cube.fullset == NULL) { /* fatal("unknown PLA size, need .i/.o or .mv");*/ if (echo_comments) putchar('#'); skip_line(fp, stdout, echo_comments); break; } if (PLA->F == NULL) { PLA->F = new_cover(10); PLA->D = new_cover(10); PLA->R = new_cover(10); } read_cube(fp, PLA); } goto loop; } /* read_pla -- read a PLA from a file Input stops when ".e" is encountered in the input file, or upon reaching end of file. Returns the PLA in the variable PLA after massaging the "symbolic" representation into a positional cube notation of the ON-set, OFF-set, and the DC-set. needs_dcset and needs_offset control the computation of the OFF-set and DC-set (i.e., if either needs to be computed, then it will be computed via complement only if the corresponding option is TRUE.) pla_type specifies the interpretation to be used when reading the PLA. The phase of the output functions is adjusted according to the global option "pos" or according to an imbedded .phase option in the input file. Note that either phase option implies that the OFF-set be computed regardless of whether the caller needs it explicitly or not. Bit pairing of the binary variables is performed according to an imbedded .pair option in the input file. The global cube structure also reflects the sizes of the PLA which was just read. If these fields have already been set, then any subsequent PLA must conform to these sizes. The global flags trace and summary control the output produced during the read. Returns a status code as a result: EOF (-1) : End of file reached before any data was read > 0 : Operation successful */ int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return) IN FILE *fp; IN bool needs_dcset, needs_offset; IN int pla_type; OUT pPLA *PLA_return; { pPLA PLA; int i, second, third; long time; cost_t cost; /* Allocate and initialize the PLA structure */ PLA = *PLA_return = new_PLA(); PLA->pla_type = pla_type; /* Read the pla */ time = ptime(); parse_pla(fp, PLA); /* Check for nothing on the file -- implies reached EOF */ if (PLA->F == NULL) { return EOF; } /* This hack merges the next-state field with the outputs */ for(i = 0; i < cube.num_vars; i++) { cube.part_size[i] = ABS(cube.part_size[i]); } if (kiss) { third = cube.num_vars - 3; second = cube.num_vars - 2; if (cube.part_size[third] != cube.part_size[second]) { (void) fprintf(stderr," with .kiss option, third to last and second\n"); (void) fprintf(stderr, "to last variables must be the same size.\n"); return EOF; } for(i = 0; i < cube.part_size[second]; i++) { PLA->label[i + cube.first_part[second]] = util_strsav(PLA->label[i + cube.first_part[third]]); } cube.part_size[second] += cube.part_size[cube.num_vars-1]; cube.num_vars--; setdown_cube(); cube_setup(); } if (trace) { totals(time, READ_TIME, PLA->F, &cost); } /* Decide how to break PLA into ON-set, OFF-set and DC-set */ time = ptime(); if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) { needs_offset = TRUE; } if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) { free_cover(PLA->R); PLA->R = complement(cube2list(PLA->F, PLA->D)); } else if (needs_dcset && PLA->pla_type == FR_type) { pcover X; free_cover(PLA->D); /* hack, why not? */ X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1); PLA->D = complement(cube1list(X)); free_cover(X); } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) { free_cover(PLA->F); PLA->F = complement(cube2list(PLA->D, PLA->R)); } if (trace) { totals(time, COMPL_TIME, PLA->R, &cost); } /* Check for phase rearrangement of the functions */ if (pos) { pcover onset = PLA->F; PLA->F = PLA->R; PLA->R = onset; PLA->phase = new_cube(); set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]); } else if (PLA->phase != NULL) { (void) set_phase(PLA); } /* Setup minimization for two-bit decoders */ if (PLA->pair != (ppair) NULL) { set_pair(PLA); } if (PLA->symbolic != NIL(symbolic_t)) { EXEC(map_symbolic(PLA), "MAP-INPUT ", PLA->F); } if (PLA->symbolic_output != NIL(symbolic_t)) { EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F); if (needs_offset) { free_cover(PLA->R); EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost); } } return 1; } void PLA_summary(PLA) pPLA PLA; { int var, i; symbolic_list_t *p2; symbolic_t *p1; printf("# PLA is %s", PLA->filename); if (cube.num_binary_vars == cube.num_vars - 1) printf(" with %d inputs and %d outputs\n", cube.num_binary_vars, cube.part_size[cube.num_vars - 1]); else { printf(" with %d variables (%d binary, mv sizes", cube.num_vars, cube.num_binary_vars); for(var = cube.num_binary_vars; var < cube.num_vars; var++) printf(" %d", cube.part_size[var]); printf(")\n"); } printf("# ON-set cost is %s\n", print_cost(PLA->F)); printf("# OFF-set cost is %s\n", print_cost(PLA->R)); printf("# DC-set cost is %s\n", print_cost(PLA->D)); if (PLA->phase != NULL) printf("# phase is %s\n", pc1(PLA->phase)); if (PLA->pair != NULL) { printf("# two-bit decoders:"); for(i = 0; i < PLA->pair->cnt; i++) printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]); printf("\n"); } if (PLA->symbolic != NIL(symbolic_t)) { for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { printf("# symbolic: "); for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { printf(" %d", p2->variable); } printf("\n"); } } if (PLA->symbolic_output != NIL(symbolic_t)) { for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) { printf("# output symbolic: "); for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { printf(" %d", p2->pos); } printf("\n"); } } (void) fflush(stdout); } pPLA new_PLA() { pPLA PLA; PLA = ALLOC(PLA_t, 1); PLA->F = PLA->D = PLA->R = (pcover) NULL; PLA->phase = (pcube) NULL; PLA->pair = (ppair) NULL; PLA->label = (char **) NULL; PLA->filename = (char *) NULL; PLA->pla_type = 0; PLA->symbolic = NIL(symbolic_t); PLA->symbolic_output = NIL(symbolic_t); return PLA; } void PLA_labels(PLA) pPLA PLA; { int i; PLA->label = ALLOC(char *, cube.size); for(i = 0; i < cube.size; i++) PLA->label[i] = (char *) NULL; } void free_PLA(PLA) pPLA PLA; { symbolic_list_t *p2, *p2next; symbolic_t *p1, *p1next; int i; if (PLA->F != (pcover) NULL) free_cover(PLA->F); if (PLA->R != (pcover) NULL) free_cover(PLA->R); if (PLA->D != (pcover) NULL) free_cover(PLA->D); if (PLA->phase != (pcube) NULL) free_cube(PLA->phase); if (PLA->pair != (ppair) NULL) { FREE(PLA->pair->var1); FREE(PLA->pair->var2); FREE(PLA->pair); } if (PLA->label != NULL) { for(i = 0; i < cube.size; i++) if (PLA->label[i] != NULL) FREE(PLA->label[i]); FREE(PLA->label); } if (PLA->filename != NULL) { FREE(PLA->filename); } for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) { for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) { p2next = p2->next; FREE(p2); } p1next = p1->next; FREE(p1); } PLA->symbolic = NIL(symbolic_t); for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) { for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) { p2next = p2->next; FREE(p2); } p1next = p1->next; FREE(p1); } PLA->symbolic_output = NIL(symbolic_t); FREE(PLA); } int read_symbolic(fp, PLA, word, retval) FILE *fp; pPLA PLA; char *word; /* scratch string for words */ symbolic_t **retval; { symbolic_list_t *listp, *prev_listp; symbolic_label_t *labelp, *prev_labelp; symbolic_t *newlist; int i, var; newlist = ALLOC(symbolic_t, 1); newlist->next = NIL(symbolic_t); newlist->symbolic_list = NIL(symbolic_list_t); newlist->symbolic_list_length = 0; newlist->symbolic_label = NIL(symbolic_label_t); newlist->symbolic_label_length = 0; prev_listp = NIL(symbolic_list_t); prev_labelp = NIL(symbolic_label_t); for(;;) { (void) get_word(fp, word); if (equal(word, ";")) break; if (label_index(PLA, word, &var, &i)) { listp = ALLOC(symbolic_list_t, 1); listp->variable = var; listp->pos = i; listp->next = NIL(symbolic_list_t); if (prev_listp == NIL(symbolic_list_t)) { newlist->symbolic_list = listp; } else { prev_listp->next = listp; } prev_listp = listp; newlist->symbolic_list_length++; } else { return FALSE; } } for(;;) { (void) get_word(fp, word); if (equal(word, ";")) break; labelp = ALLOC(symbolic_label_t, 1); labelp->label = util_strsav(word); labelp->next = NIL(symbolic_label_t); if (prev_labelp == NIL(symbolic_label_t)) { newlist->symbolic_label = labelp; } else { prev_labelp->next = labelp; } prev_labelp = labelp; newlist->symbolic_label_length++; } *retval = newlist; return TRUE; } int label_index(PLA, word, varp, ip) pPLA PLA; char *word; int *varp; int *ip; { int var, i; if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) { if (sscanf(word, "%d", varp) == 1) { *ip = *varp; return TRUE; } } else { for(var = 0; var < cube.num_vars; var++) { for(i = 0; i < cube.part_size[var]; i++) { if (equal(PLA->label[cube.first_part[var]+i], word)) { *varp = var; *ip = i; return TRUE; } } } } return FALSE; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/cvrm.c000066400000000000000000000300331300674244400237440ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* module: cvrm.c Purpose: miscellaneous cover manipulation a) verify two covers are equal, check consistency of a cover b) unravel a multiple-valued cover into minterms c) sort covers */ #include "espresso.h" ABC_NAMESPACE_IMPL_START static void cb_unravel(c, start, end, startbase, B1) IN register pcube c; IN int start, end; IN pcube startbase; INOUT pcover B1; { pcube base = cube.temp[0], p, last; int expansion, place, skip, var, size, offset; register int i, j, k, n; /* Determine how many cubes it will blow up into, and create a mask for those parts that have only a single coordinate */ expansion = 1; (void) set_copy(base, startbase); for(var = start; var <= end; var++) { if ((size = set_dist(c, cube.var_mask[var])) < 2) { (void) set_or(base, base, cube.var_mask[var]); } else { expansion *= size; } } (void) set_and(base, c, base); /* Add the unravelled sets starting at the last element of B1 */ offset = B1->count; B1->count += expansion; foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) { INLINEset_copy(p, base); } place = expansion; for(var = start; var <= end; var++) { if ((size = set_dist(c, cube.var_mask[var])) > 1) { skip = place; place = place / size; n = 0; for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { if (is_in_set(c, i)) { for(j = n; j < expansion; j += skip) { for(k = 0; k < place; k++) { p = GETSET(B1, j+k+offset); (void) set_insert(p, i); } } n += place; } } } } } pcover unravel_range(B, start, end) IN pcover B; IN int start, end; { pcover B1; int var, total_size, expansion, size; register pcube p, last, startbase = cube.temp[1]; /* Create the starting base for those variables not being unravelled */ (void) set_copy(startbase, cube.emptyset); for(var = 0; var < start; var++) (void) set_or(startbase, startbase, cube.var_mask[var]); for(var = end+1; var < cube.num_vars; var++) (void) set_or(startbase, startbase, cube.var_mask[var]); /* Determine how many cubes it will blow up into */ total_size = 0; foreach_set(B, last, p) { expansion = 1; for(var = start; var <= end; var++) if ((size = set_dist(p, cube.var_mask[var])) >= 2) if ((expansion *= size) > 1000000) fatal("unreasonable expansion in unravel"); total_size += expansion; } /* We can now allocate a cover of exactly the correct size */ B1 = new_cover(total_size); foreach_set(B, last, p) { cb_unravel(p, start, end, startbase, B1); } free_cover(B); return B1; } pcover unravel(B, start) IN pcover B; IN int start; { return unravel_range(B, start, cube.num_vars-1); } /* lex_sort -- sort cubes in a standard lexical fashion */ pcover lex_sort(T) pcover T; { pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size); free_cover(T); return T1; } /* size_sort -- sort cubes by their size */ pcover size_sort(T) pcover T; { pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size); free_cover(T); return T1; } /* mini_sort -- sort cubes according to the heuristics of mini */ pcover mini_sort(F, compare) pcover F; int (*compare)(); { register int *count, cnt, n = cube.size, i; register pcube p, last; pcover F_sorted; pcube *F1; /* Perform a column sum over the set family */ count = sf_count(F); /* weight is "inner product of the cube and the column sums" */ foreach_set(F, last, p) { cnt = 0; for(i = 0; i < n; i++) if (is_in_set(p, i)) cnt += count[i]; PUTSIZE(p, cnt); } FREE(count); /* use qsort to sort the array */ qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare); F_sorted = sf_unlist(F1, F->count, F->sf_size); free_cover(F); return F_sorted; } /* sort_reduce -- Espresso strategy for ordering the cubes before reduction */ pcover sort_reduce(T) IN pcover T; { register pcube p, last, largest = NULL; register int bestsize = -1, size, n = cube.num_vars; pcover T_sorted; pcube *T1; if (T->count == 0) return T; /* find largest cube */ foreach_set(T, last, p) if ((size = set_ord(p)) > bestsize) largest = p, bestsize = size; foreach_set(T, last, p) PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127)); qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), (int (*)()) descend); T_sorted = sf_unlist(T1, T->count, T->sf_size); free_cover(T); return T_sorted; } pcover random_order(F) register pcover F; { pset temp; register int i, k; #ifdef RANDOM long random(); #endif temp = set_new(F->sf_size); for(i = F->count - 1; i > 0; i--) { /* Choose a random number between 0 and i */ #ifdef RANDOM k = random() % i; #else /* this is not meant to be really used; just provides an easy "out" if random() and srandom() aren't around */ k = (i*23 + 997) % i; #endif /* swap sets i and k */ (void) set_copy(temp, GETSET(F, k)); (void) set_copy(GETSET(F, k), GETSET(F, i)); (void) set_copy(GETSET(F, i), temp); } set_free(temp); return F; } /* * cubelist_partition -- take a cubelist T and see if it has any components; * if so, return cubelist's of the two partitions A and B; the return value * is the size of the partition; if not, A and B * are undefined and the return value is 0 */ int cubelist_partition(T, A, B, comp_debug) pcube *T; /* a list of cubes */ pcube **A, **B; /* cubelist of partition and remainder */ unsigned int comp_debug; { register pcube *T1, p, seed, cof; pcube *A1, *B1; bool change; int count, numcube; numcube = CUBELISTSIZE(T); /* Mark all cubes -- covered cubes belong to the partition */ for(T1 = T+2; (p = *T1++) != NULL; ) { RESET(p, COVERED); } /* * Extract a partition from the cubelist T; start with the first cube as a * seed, and then pull in all cubes which share a variable with the seed; * iterate until no new cubes are brought into the partition. */ seed = set_save(T[2]); cof = T[0]; SET(T[2], COVERED); count = 1; do { change = FALSE; for(T1 = T+2; (p = *T1++) != NULL; ) { if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) { INLINEset_and(seed, seed, p); SET(p, COVERED); change = TRUE; count++; } } } while (change); set_free(seed); if (comp_debug) { (void) printf("COMPONENT_REDUCTION: split into %d %d\n", count, numcube - count); } if (count != numcube) { /* Allocate and setup the cubelist's for the two partitions */ *A = A1 = ALLOC(pcube, numcube+3); *B = B1 = ALLOC(pcube, numcube+3); (*A)[0] = set_save(T[0]); (*B)[0] = set_save(T[0]); A1 = *A + 2; B1 = *B + 2; /* Loop over the cubes in T and distribute to A and B */ for(T1 = T+2; (p = *T1++) != NULL; ) { if (TESTP(p, COVERED)) { *A1++ = p; } else { *B1++ = p; } } /* Stuff needed at the end of the cubelist's */ *A1++ = NULL; (*A)[1] = (pcube) A1; *B1++ = NULL; (*B)[1] = (pcube) B1; } return numcube - count; } /* * quick cofactor against a single output function */ pcover cof_output(T, i) pcover T; register int i; { pcover T1; register pcube p, last, pdest, mask; mask = cube.var_mask[cube.output]; T1 = new_cover(T->count); foreach_set(T, last, p) { if (is_in_set(p, i)) { pdest = GETSET(T1, T1->count++); INLINEset_or(pdest, p, mask); RESET(pdest, PRIME); } } return T1; } /* * quick intersection against a single output function */ pcover uncof_output(T, i) pcover T; int i; { register pcube p, last, mask; if (T == NULL) { return T; } mask = cube.var_mask[cube.output]; foreach_set(T, last, p) { INLINEset_diff(p, p, mask); set_insert(p, i); } return T; } /* * A generic routine to perform an operation for each output function * * func() is called with a PLA for each output function (with the output * part effectively removed). * func1() is called after reforming the equivalent output function * * Each function returns TRUE if process is to continue */ void foreach_output_function(PLA, func, func1) pPLA PLA; int (*func)(); int (*func1)(); { pPLA PLA1; int i; /* Loop for each output function */ for(i = 0; i < cube.part_size[cube.output]; i++) { /* cofactor on the output part */ PLA1 = new_PLA(); PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]); PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]); PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]); /* Call a routine to do something with the cover */ if ((*func)(PLA1, i) == 0) { free_PLA(PLA1); return; } /* intersect with the particular output part again */ PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]); PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]); PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]); /* Call a routine to do something with the final result */ if ((*func1)(PLA1, i) == 0) { free_PLA(PLA1); return; } /* Cleanup for next go-around */ free_PLA(PLA1); } } static pcover Fmin; static pcube phase; /* * minimize each output function individually */ void so_espresso(PLA, strategy) pPLA PLA; int strategy; { Fmin = new_cover(PLA->F->count); if (strategy == 0) { foreach_output_function(PLA, so_do_espresso, so_save); } else { foreach_output_function(PLA, so_do_exact, so_save); } sf_free(PLA->F); PLA->F = Fmin; } /* * minimize each output function, choose function or complement based on the * one with the fewer number of terms */ void so_both_espresso(PLA, strategy) pPLA PLA; int strategy; { phase = set_save(cube.fullset); Fmin = new_cover(PLA->F->count); if (strategy == 0) { foreach_output_function(PLA, so_both_do_espresso, so_both_save); } else { foreach_output_function(PLA, so_both_do_exact, so_both_save); } sf_free(PLA->F); PLA->F = Fmin; PLA->phase = phase; } int so_do_espresso(PLA, i) pPLA PLA; int i; { char word[32]; /* minimize the single-output function (on-set) */ skip_make_sparse = 1; (void) sprintf(word, "ESPRESSO-POS(%d)", i); EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F); return 1; } int so_do_exact(PLA, i) pPLA PLA; int i; { char word[32]; /* minimize the single-output function (on-set) */ skip_make_sparse = 1; (void) sprintf(word, "EXACT-POS(%d)", i); EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F); return 1; } /*ARGSUSED*/ int so_save(PLA, i) pPLA PLA; int i; { Fmin = sf_append(Fmin, PLA->F); /* disposes of PLA->F */ PLA->F = NULL; return 1; } int so_both_do_espresso(PLA, i) pPLA PLA; int i; { char word[32]; /* minimize the single-output function (on-set) */ (void) sprintf(word, "ESPRESSO-POS(%d)", i); skip_make_sparse = 1; EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F); /* minimize the single-output function (off-set) */ (void) sprintf(word, "ESPRESSO-NEG(%d)", i); skip_make_sparse = 1; EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R); return 1; } int so_both_do_exact(PLA, i) pPLA PLA; int i; { char word[32]; /* minimize the single-output function (on-set) */ (void) sprintf(word, "EXACT-POS(%d)", i); skip_make_sparse = 1; EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F); /* minimize the single-output function (off-set) */ (void) sprintf(word, "EXACT-NEG(%d)", i); skip_make_sparse = 1; EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R); return 1; } int so_both_save(PLA, i) pPLA PLA; int i; { if (PLA->F->count > PLA->R->count) { sf_free(PLA->F); PLA->F = PLA->R; PLA->R = NULL; i += cube.first_part[cube.output]; set_remove(phase, i); } else { sf_free(PLA->R); PLA->R = NULL; } Fmin = sf_append(Fmin, PLA->F); PLA->F = NULL; return 1; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/cvrmisc.c000066400000000000000000000062671300674244400244570ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* cost -- compute the cost of a cover */ void cover_cost(F, cost) IN pcover F; INOUT pcost cost; { register pcube p, last; pcube *T; int var; /* use the routine used by cofactor to decide splitting variables */ massive_count(T = cube1list(F)); free_cubelist(T); cost->cubes = F->count; cost->total = cost->in = cost->out = cost->mv = cost->primes = 0; /* Count transistors (zeros) for each binary variable (inputs) */ for(var = 0; var < cube.num_binary_vars; var++) cost->in += cdata.var_zeros[var]; /* Count transistors for each mv variable based on sparse/dense */ for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) if (cube.sparse[var]) cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var]; else cost->mv += cdata.var_zeros[var]; /* Count the transistors (ones) for the output variable */ if (cube.num_binary_vars != cube.num_vars) { var = cube.num_vars - 1; cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var]; } /* Count the number of nonprime cubes */ foreach_set(F, last, p) cost->primes += TESTP(p, PRIME) != 0; /* Count the total number of literals */ cost->total = cost->in + cost->out + cost->mv; } /* fmt_cost -- return a string which reports the "cost" of a cover */ char *fmt_cost(cost) IN pcost cost; { static char s[200]; if (cube.num_binary_vars == cube.num_vars - 1) (void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d", cost->cubes, cost->cubes - cost->primes, cost->in, cost->out, cost->total); else (void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d", cost->cubes, cost->cubes - cost->primes, cost->in, cost->mv, cost->out); return s; } char *print_cost(F) IN pcover F; { cost_t cost; cover_cost(F, &cost); return fmt_cost(&cost); } /* copy_cost -- copy a cost function from s to d */ void copy_cost(s, d) pcost s, d; { d->cubes = s->cubes; d->in = s->in; d->out = s->out; d->mv = s->mv; d->total = s->total; d->primes = s->primes; } /* size_stamp -- print single line giving the size of a cover */ void size_stamp(T, name) IN pcover T; IN char *name; { (void) printf("# %s\tCost is %s\n", name, print_cost(T)); (void) fflush(stdout); } /* print_trace -- print a line reporting size and time after a function */ void print_trace(T, name, time) pcover T; char *name; long time; { (void) printf("# %s\tTime was %s, cost is %s\n", name, print_time(time), print_cost(T)); (void) fflush(stdout); } /* totals -- add time spent in the function into the totals */ void totals(time, i, T, cost) long time; int i; pcover T; pcost cost; { time = ptime() - time; total_time[i] += time; total_calls[i]++; cover_cost(T, cost); if (trace) { (void) printf("# %s\tTime was %s, cost is %s\n", total_name[i], print_time(time), fmt_cost(cost)); (void) fflush(stdout); } } /* fatal -- report fatal error message and take a dive */ void fatal(s) char *s; { (void) fprintf(stderr, "espresso: %s\n", s); exit(1); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/cvrout.c000066400000000000000000000336671300674244400243370ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* module: cvrout.c purpose: cube and cover output routines */ #include "espresso.h" ABC_NAMESPACE_IMPL_START void fprint_pla(fp, PLA, output_type) INOUT FILE *fp; IN pPLA PLA; IN int output_type; { int num; register pcube last, p; if ((output_type & CONSTRAINTS_type) != 0) { output_symbolic_constraints(fp, PLA, 0); output_type &= ~ CONSTRAINTS_type; if (output_type == 0) { return; } } if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) { output_symbolic_constraints(fp, PLA, 1); output_type &= ~ SYMBOLIC_CONSTRAINTS_type; if (output_type == 0) { return; } } if (output_type == PLEASURE_type) { pls_output(PLA); } else if (output_type == EQNTOTT_type) { eqn_output(PLA); } else if (output_type == KISS_type) { kiss_output(fp, PLA); } else { fpr_header(fp, PLA, output_type); num = 0; if (output_type & F_type) num += (PLA->F)->count; if (output_type & D_type) num += (PLA->D)->count; if (output_type & R_type) num += (PLA->R)->count; (void) fprintf(fp, ".p %d\n", num); /* quick patch 01/17/85 to support TPLA ! */ if (output_type == F_type) { foreach_set(PLA->F, last, p) { print_cube(fp, p, "01"); } (void) fprintf(fp, ".e\n"); } else { if (output_type & F_type) { foreach_set(PLA->F, last, p) { print_cube(fp, p, "~1"); } } if (output_type & D_type) { foreach_set(PLA->D, last, p) { print_cube(fp, p, "~2"); } } if (output_type & R_type) { foreach_set(PLA->R, last, p) { print_cube(fp, p, "~0"); } } (void) fprintf(fp, ".end\n"); } } } void fpr_header(fp, PLA, output_type) FILE *fp; pPLA PLA; int output_type; { register int i, var; int first, last; /* .type keyword gives logical type */ if (output_type != F_type) { (void) fprintf(fp, ".type "); if (output_type & F_type) putc('f', fp); if (output_type & D_type) putc('d', fp); if (output_type & R_type) putc('r', fp); putc('\n', fp); } /* Check for binary or multiple-valued labels */ if (cube.num_mv_vars <= 1) { (void) fprintf(fp, ".i %d\n", cube.num_binary_vars); if (cube.output != -1) (void) fprintf(fp, ".o %d\n", cube.part_size[cube.output]); } else { (void) fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars); for(var = cube.num_binary_vars; var < cube.num_vars; var++) (void) fprintf(fp, " %d", cube.part_size[var]); (void) fprintf(fp, "\n"); } /* binary valued labels */ if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char) && cube.num_binary_vars > 0) { (void) fprintf(fp, ".ilb"); for(var = 0; var < cube.num_binary_vars; var++) /* see (NIL) OUTLABELS comment below */ if(INLABEL(var) == NIL(char)){ (void) fprintf(fp, " (null)"); } else{ (void) fprintf(fp, " %s", INLABEL(var)); } putc('\n', fp); } /* output-part (last multiple-valued variable) labels */ if (PLA->label != NIL(char *) && PLA->label[cube.first_part[cube.output]] != NIL(char) && cube.output != -1) { (void) fprintf(fp, ".ob"); for(i = 0; i < cube.part_size[cube.output]; i++) /* (NIL) OUTLABELS caused espresso to segfault under solaris */ if(OUTLABEL(i) == NIL(char)){ (void) fprintf(fp, " (null)"); } else{ (void) fprintf(fp, " %s", OUTLABEL(i)); } putc('\n', fp); } /* multiple-valued labels */ for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) { first = cube.first_part[var]; last = cube.last_part[var]; if (PLA->label != NULL && PLA->label[first] != NULL) { (void) fprintf(fp, ".label var=%d", var); for(i = first; i <= last; i++) { (void) fprintf(fp, " %s", PLA->label[i]); } putc('\n', fp); } } if (PLA->phase != (pcube) NULL) { first = cube.first_part[cube.output]; last = cube.last_part[cube.output]; (void) fprintf(fp, "#.phase "); for(i = first; i <= last; i++) putc(is_in_set(PLA->phase,i) ? '1' : '0', fp); (void) fprintf(fp, "\n"); } } void pls_output(PLA) IN pPLA PLA; { register pcube last, p; (void) printf(".option unmerged\n"); makeup_labels(PLA); pls_label(PLA, stdout); pls_group(PLA, stdout); (void) printf(".p %d\n", PLA->F->count); foreach_set(PLA->F, last, p) { print_expanded_cube(stdout, p, PLA->phase); } (void) printf(".end\n"); } void pls_group(PLA, fp) pPLA PLA; FILE *fp; { int var, i, col, len; (void) fprintf(fp, "\n.group"); col = 6; for(var = 0; var < cube.num_vars-1; var++) { (void) fprintf(fp, " ("), col += 2; for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { len = strlen(PLA->label[i]); if (col + len > 75) (void) fprintf(fp, " \\\n"), col = 0; else if (i != 0) putc(' ', fp), col += 1; (void) fprintf(fp, "%s", PLA->label[i]), col += len; } (void) fprintf(fp, ")"), col += 1; } (void) fprintf(fp, "\n"); } void pls_label(PLA, fp) pPLA PLA; FILE *fp; { int var, i, col, len; (void) fprintf(fp, ".label"); col = 6; for(var = 0; var < cube.num_vars; var++) for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { len = strlen(PLA->label[i]); if (col + len > 75) (void) fprintf(fp, " \\\n"), col = 0; else putc(' ', fp), col += 1; (void) fprintf(fp, "%s", PLA->label[i]), col += len; } } /* eqntott output mode -- output algebraic equations */ void eqn_output(PLA) pPLA PLA; { register pcube p, last; register int i, var, col, len; int x; bool firstand, firstor; if (cube.output == -1) fatal("Cannot have no-output function for EQNTOTT output mode"); if (cube.num_mv_vars != 1) fatal("Must have binary-valued function for EQNTOTT output mode"); makeup_labels(PLA); /* Write a single equation for each output */ for(i = 0; i < cube.part_size[cube.output]; i++) { (void) printf("%s = ", OUTLABEL(i)); col = strlen(OUTLABEL(i)) + 3; firstor = TRUE; /* Write product terms for each cube in this output */ foreach_set(PLA->F, last, p) if (is_in_set(p, i + cube.first_part[cube.output])) { if (firstor) (void) printf("("), col += 1; else (void) printf(" | ("), col += 4; firstor = FALSE; firstand = TRUE; /* print out a product term */ for(var = 0; var < cube.num_binary_vars; var++) if ((x=GETINPUT(p, var)) != DASH) { len = strlen(INLABEL(var)); if (col+len > 72) (void) printf("\n "), col = 4; if (! firstand) (void) printf("&"), col += 1; firstand = FALSE; if (x == ZERO) (void) printf("!"), col += 1; (void) printf("%s", INLABEL(var)), col += len; } (void) printf(")"), col += 1; } (void) printf(";\n\n"); } } char *fmt_cube(c, out_map, s) register pcube c; register char *out_map, *s; { register int i, var, last, len = 0; for(var = 0; var < cube.num_binary_vars; var++) { s[len++] = "?01-" [GETINPUT(c, var)]; } for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { s[len++] = ' '; for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { s[len++] = "01" [is_in_set(c, i) != 0]; } } if (cube.output != -1) { last = cube.last_part[cube.output]; s[len++] = ' '; for(i = cube.first_part[cube.output]; i <= last; i++) { s[len++] = out_map [is_in_set(c, i) != 0]; } } s[len] = '\0'; return s; } void print_cube(fp, c, out_map) register FILE *fp; register pcube c; register char *out_map; { register int i, var, ch; int last; for(var = 0; var < cube.num_binary_vars; var++) { ch = "?01-" [GETINPUT(c, var)]; putc(ch, fp); } for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { putc(' ', fp); for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { ch = "01" [is_in_set(c, i) != 0]; putc(ch, fp); } } if (cube.output != -1) { last = cube.last_part[cube.output]; putc(' ', fp); for(i = cube.first_part[cube.output]; i <= last; i++) { ch = out_map [is_in_set(c, i) != 0]; putc(ch, fp); } } putc('\n', fp); } void print_expanded_cube(fp, c, phase) register FILE *fp; register pcube c; pcube phase; { register int i, var, ch; char *out_map; for(var = 0; var < cube.num_binary_vars; var++) { for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { ch = "~1" [is_in_set(c, i) != 0]; putc(ch, fp); } } for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { ch = "1~" [is_in_set(c, i) != 0]; putc(ch, fp); } } if (cube.output != -1) { var = cube.num_vars - 1; putc(' ', fp); for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { if (phase == (pcube) NULL || is_in_set(phase, i)) { out_map = "~1"; } else { out_map = "~0"; } ch = out_map[is_in_set(c, i) != 0]; putc(ch, fp); } } putc('\n', fp); } char *pc1(c) pcube c; {static char s1[256];return fmt_cube(c, "01", s1);} char *pc2(c) pcube c; {static char s2[256];return fmt_cube(c, "01", s2);} void debug_print(T, name, level) pcube *T; char *name; int level; { register pcube *T1, p, temp; register int cnt; cnt = CUBELISTSIZE(T); temp = new_cube(); if (verbose_debug && level == 0) (void) printf("\n"); (void) printf("%s[%d]: ord(T)=%d\n", name, level, cnt); if (verbose_debug) { (void) printf("cofactor=%s\n", pc1(T[0])); for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++) (void) printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0]))); } free_cube(temp); } void debug1_print(T, name, num) pcover T; char *name; int num; { register int cnt = 1; register pcube p, last; if (verbose_debug && num == 0) (void) printf("\n"); (void) printf("%s[%d]: ord(T)=%d\n", name, num, T->count); if (verbose_debug) foreach_set(T, last, p) (void) printf("%4d. %s\n", cnt++, pc1(p)); } void cprint(T) pcover T; { register pcube p, last; foreach_set(T, last, p) (void) printf("%s\n", pc1(p)); } void makeup_labels(PLA) pPLA PLA; { int var, i, ind; if (PLA->label == (char **) NULL) PLA_labels(PLA); for(var = 0; var < cube.num_vars; var++) for(i = 0; i < cube.part_size[var]; i++) { ind = cube.first_part[var] + i; if (PLA->label[ind] == (char *) NULL) { PLA->label[ind] = ALLOC(char, 15); if (var < cube.num_binary_vars) if ((i % 2) == 0) (void) sprintf(PLA->label[ind], "v%d.bar", var); else (void) sprintf(PLA->label[ind], "v%d", var); else (void) sprintf(PLA->label[ind], "v%d.%d", var, i); } } } void kiss_output(fp, PLA) FILE *fp; pPLA PLA; { register pset last, p; foreach_set(PLA->F, last, p) { kiss_print_cube(fp, PLA, p, "~1"); } foreach_set(PLA->D, last, p) { kiss_print_cube(fp, PLA, p, "~2"); } } void kiss_print_cube(fp, PLA, p, out_string) FILE *fp; pPLA PLA; pcube p; char *out_string; { register int i, var; int part, x; for(var = 0; var < cube.num_binary_vars; var++) { x = "?01-" [GETINPUT(p, var)]; putc(x, fp); } for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { putc(' ', fp); if (setp_implies(cube.var_mask[var], p)) { putc('-', fp); } else { part = -1; for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { if (is_in_set(p, i)) { if (part != -1) { fatal("more than 1 part in a symbolic variable\n"); } part = i; } } if (part == -1) { putc('~', fp); /* no parts, hope its an output ... */ } else { (void) fputs(PLA->label[part], fp); } } } if ((var = cube.output) != -1) { putc(' ', fp); for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { x = out_string [is_in_set(p, i) != 0]; putc(x, fp); } } putc('\n', fp); } void output_symbolic_constraints(fp, PLA, output_symbolic) FILE *fp; pPLA PLA; int output_symbolic; { pset_family A; register int i, j; int size, var, npermute, *permute, *weight, noweight; if ((cube.num_vars - cube.num_binary_vars) <= 1) { return; } makeup_labels(PLA); for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) { /* pull out the columns for variable "var" */ npermute = cube.part_size[var]; permute = ALLOC(int, npermute); for(i=0; i < npermute; i++) { permute[i] = cube.first_part[var] + i; } A = sf_permute(sf_save(PLA->F), permute, npermute); FREE(permute); /* Delete the singletons and the full sets */ noweight = 0; for(i = 0; i < A->count; i++) { size = set_ord(GETSET(A,i)); if (size == 1 || size == A->sf_size) { sf_delset(A, i--); noweight++; } } /* Count how many times each is duplicated */ weight = ALLOC(int, A->count); for(i = 0; i < A->count; i++) { RESET(GETSET(A, i), COVERED); } for(i = 0; i < A->count; i++) { weight[i] = 0; if (! TESTP(GETSET(A,i), COVERED)) { weight[i] = 1; for(j = i+1; j < A->count; j++) { if (setp_equal(GETSET(A,i), GETSET(A,j))) { weight[i]++; SET(GETSET(A,j), COVERED); } } } } /* Print out the constraints */ if (! output_symbolic) { (void) fprintf(fp, "# Symbolic constraints for variable %d (Numeric form)\n", var); (void) fprintf(fp, "# unconstrained weight = %d\n", noweight); (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]); for(i = 0; i < A->count; i++) { if (weight[i] > 0) { (void) fprintf(fp, "weight=%d: ", weight[i]); for(j = 0; j < A->sf_size; j++) { if (is_in_set(GETSET(A,i), j)) { (void) fprintf(fp, " %d", j); } } (void) fprintf(fp, "\n"); } } } else { (void) fprintf(fp, "# Symbolic constraints for variable %d (Symbolic form)\n", var); for(i = 0; i < A->count; i++) { if (weight[i] > 0) { (void) fprintf(fp, "# w=%d: (", weight[i]); for(j = 0; j < A->sf_size; j++) { if (is_in_set(GETSET(A,i), j)) { (void) fprintf(fp, " %s", PLA->label[cube.first_part[var]+j]); } } (void) fprintf(fp, " )\n"); } } FREE(weight); } } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/dominate.c000066400000000000000000000045441300674244400246050ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "mincov_int.h" ABC_NAMESPACE_IMPL_START int sm_row_dominance(A) sm_matrix *A; { register sm_row *prow, *prow1; register sm_col *pcol, *least_col; register sm_element *p, *pnext; int rowcnt; rowcnt = A->nrows; /* Check each row against all other rows */ for(prow = A->first_row; prow != 0; prow = prow->next_row) { /* Among all columns with a 1 in this row, choose smallest */ least_col = sm_get_col(A, prow->first_col->col_num); for(p = prow->first_col->next_col; p != 0; p = p->next_col) { pcol = sm_get_col(A, p->col_num); if (pcol->length < least_col->length) { least_col = pcol; } } /* Only check for containment against rows in this column */ for(p = least_col->first_row; p != 0; p = pnext) { pnext = p->next_row; prow1 = sm_get_row(A, p->row_num); if ((prow1->length > prow->length) || (prow1->length == prow->length && prow1->row_num > prow->row_num)) { if (sm_row_contains(prow, prow1)) { sm_delrow(A, prow1->row_num); } } } } return rowcnt - A->nrows; } int sm_col_dominance(A, weight) sm_matrix *A; int *weight; { register sm_row *prow; register sm_col *pcol, *pcol1; register sm_element *p; sm_row *least_row; sm_col *next_col; int colcnt; colcnt = A->ncols; /* Check each column against all other columns */ for(pcol = A->first_col; pcol != 0; pcol = next_col) { next_col = pcol->next_col; /* Check all rows to find the one with fewest elements */ least_row = sm_get_row(A, pcol->first_row->row_num); for(p = pcol->first_row->next_row; p != 0; p = p->next_row) { prow = sm_get_row(A, p->row_num); if (prow->length < least_row->length) { least_row = prow; } } /* Only check for containment against columns in this row */ for(p = least_row->first_col; p != 0; p = p->next_col) { pcol1 = sm_get_col(A, p->col_num); if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num]) continue; if ((pcol1->length > pcol->length) || (pcol1->length == pcol->length && pcol1->col_num > pcol->col_num)) { if (sm_col_contains(pcol, pcol1)) { sm_delcol(A, pcol->col_num); break; } } } } return colcnt - A->ncols; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/equiv.c000066400000000000000000000042411300674244400241300ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START void find_equiv_outputs(PLA) pPLA PLA; { int i, j, ipart, jpart, some_equiv; pcover *R, *F; some_equiv = FALSE; makeup_labels(PLA); F = ALLOC(pcover, cube.part_size[cube.output]); R = ALLOC(pcover, cube.part_size[cube.output]); for(i = 0; i < cube.part_size[cube.output]; i++) { ipart = cube.first_part[cube.output] + i; R[i] = cof_output(PLA->R, ipart); F[i] = complement(cube1list(R[i])); } for(i = 0; i < cube.part_size[cube.output]-1; i++) { for(j = i+1; j < cube.part_size[cube.output]; j++) { ipart = cube.first_part[cube.output] + i; jpart = cube.first_part[cube.output] + j; if (check_equiv(F[i], F[j])) { (void) printf("# Outputs %d and %d (%s and %s) are equivalent\n", i, j, PLA->label[ipart], PLA->label[jpart]); some_equiv = TRUE; } else if (check_equiv(F[i], R[j])) { (void) printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n", i, j, PLA->label[ipart], PLA->label[jpart]); some_equiv = TRUE; } else if (check_equiv(R[i], F[j])) { (void) printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n", i, j, PLA->label[ipart], PLA->label[jpart]); some_equiv = TRUE; } else if (check_equiv(R[i], R[j])) { (void) printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n", i, j, PLA->label[ipart], PLA->label[jpart]); some_equiv = TRUE; } } } if (! some_equiv) { (void) printf("# No outputs are equivalent\n"); } for(i = 0; i < cube.part_size[cube.output]; i++) { free_cover(F[i]); free_cover(R[i]); } FREE(F); FREE(R); } int check_equiv(f1, f2) pcover f1, f2; { register pcube *f1list, *f2list; register pcube p, last; f1list = cube1list(f1); foreach_set(f2, last, p) { if (! cube_is_covered(f1list, p)) { return FALSE; } } free_cubelist(f1list); f2list = cube1list(f2); foreach_set(f1, last, p) { if (! cube_is_covered(f2list, p)) { return FALSE; } } free_cubelist(f2list); return TRUE; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/espresso.c000066400000000000000000000070171300674244400246460ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* * Module: espresso.c * Purpose: The main espresso algorithm * * Returns a minimized version of the ON-set of a function * * The following global variables affect the operation of Espresso: * * MISCELLANEOUS: * trace * print trace information as the minimization progresses * * remove_essential * remove essential primes * * single_expand * if true, stop after first expand/irredundant * * LAST_GASP or SUPER_GASP strategy: * use_super_gasp * uses the super_gasp strategy rather than last_gasp * * SETUP strategy: * recompute_onset * recompute onset using the complement before starting * * unwrap_onset * unwrap the function output part before first expand * * MAKE_SPARSE strategy: * force_irredundant * iterates make_sparse to force a minimal solution (used * indirectly by make_sparse) * * skip_make_sparse * skip the make_sparse step (used by opo only) */ #include "espresso.h" ABC_NAMESPACE_IMPL_START pcover espresso(F, D1, R) pcover F, D1, R; { pcover E, D, Fsave; pset last, p; cost_t cost, best_cost; begin: Fsave = sf_save(F); /* save original function */ D = sf_save(D1); /* make a scratch copy of D */ /* Setup has always been a problem */ if (recompute_onset) { EXEC(E = simplify(cube1list(F)), "SIMPLIFY ", E); free_cover(F); F = E; } cover_cost(F, &cost); if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1) && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1]) && (cost.out < 5000)) EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP ", F); /* Initial expand and irredundant */ foreach_set(F, last, p) { RESET(p, PRIME); } EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost); EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost); if (! single_expand) { if (remove_essential) { EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost); } else { E = new_cover(0); } cover_cost(F, &cost); do { /* Repeat inner loop until solution becomes "stable" */ do { copy_cost(&cost, &best_cost); EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost); EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost); EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost); } while (cost.cubes < best_cost.cubes); /* Perturb solution to see if we can continue to iterate */ copy_cost(&cost, &best_cost); if (use_super_gasp) { F = super_gasp(F, D, R, &cost); if (cost.cubes >= best_cost.cubes) break; } else { F = last_gasp(F, D, R, &cost); } } while (cost.cubes < best_cost.cubes || (cost.cubes == best_cost.cubes && cost.total < best_cost.total)); /* Append the essential cubes to F */ F = sf_append(F, E); /* disposes of E */ if (trace) size_stamp(F, "ADJUST "); } /* Free the D which we used */ free_cover(D); /* Attempt to make the PLA matrix sparse */ if (! skip_make_sparse) { F = make_sparse(F, D1, R); } /* * Check to make sure function is actually smaller !! * This can only happen because of the initial unravel. If we fail, * then run the whole thing again without the unravel. */ if (Fsave->count < F->count) { free_cover(F); F = Fsave; unwrap_onset = FALSE; goto begin; } else { free_cover(Fsave); } return F; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/espresso.h000066400000000000000000000722011300674244400246500ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* * espresso.h -- header file for Espresso-mv */ //#include "port.h" //#include "utility.h" #include "sparse.h" #include "mincov.h" #include "util_hack.h" // added #define ABC__misc__espresso__espresso_h #define print_time(t) util_print_time(t) #ifdef IBM_WATC #define void int #include "short.h" #endif #ifdef IBMPC /* set default options for IBM/PC */ #define NO_INLINE #define BPI 16 #endif /*-----THIS USED TO BE set.h----- */ /* * set.h -- definitions for packed arrays of bits * * This header file describes the data structures which comprise a * facility for efficiently implementing packed arrays of bits * (otherwise known as sets, cf. Pascal). * * A set is a vector of bits and is implemented here as an array of * unsigned integers. The low order bits of set[0] give the index of * the last word of set data. The higher order bits of set[0] are * used to store data associated with the set. The set data is * contained in elements set[1] ... set[LOOP(set)] as a packed bit * array. * * A family of sets is a two-dimensional matrix of bits and is * implemented with the data type "set_family". * * BPI == 32 and BPI == 16 have been tested and work. */ /* Define host machine characteristics of "unsigned int" */ #ifndef ABC__misc__espresso__espresso_h #define BPI ABC_NAMESPACE_HEADER_START 32 /* # bits per integer */ #endif #if BPI == 32 #define LOGBPI 5 /* log(BPI)/log(2) */ #else #define LOGBPI 4 /* log(BPI)/log(2) */ #endif /* Define the set type */ typedef unsigned int *pset; /* Define the set family type -- an array of sets */ typedef struct set_family { int wsize; /* Size of each set in 'ints' */ int sf_size; /* User declared set size */ int capacity; /* Number of sets allocated */ int count; /* The number of sets in the family */ int active_count; /* Number of "active" sets */ pset data; /* Pointer to the set data */ struct set_family *next; /* For garbage collection */ } set_family_t, *pset_family; /* Macros to set and test single elements */ #define WHICH_WORD(element) (((element) >> LOGBPI) + 1) #define WHICH_BIT(element) ((element) & (BPI-1)) /* # of ints needed to allocate a set with "size" elements */ #if BPI == 32 #define SET_SIZE(size) ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1)) #else #define SET_SIZE(size) ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2)) #endif /* * Three fields are maintained in the first word of the set * LOOP is the index of the last word used for set data * LOOPCOPY is the index of the last word in the set * SIZE is available for general use (e.g., recording # elements in set) * NELEM retrieves the number of elements in the set */ #define LOOP(set) (set[0] & 0x03ff) #define PUTLOOP(set, i) (set[0] &= ~0x03ff, set[0] |= (i)) #if BPI == 32 #define LOOPCOPY(set) LOOP(set) #define SIZE(set) (set[0] >> 16) #define PUTSIZE(set, size) (set[0] &= 0xffff, set[0] |= ((size) << 16)) #else #define LOOPCOPY(set) (LOOP(set) + 1) #define SIZE(set) (set[LOOP(set)+1]) #define PUTSIZE(set, size) ((set[LOOP(set)+1]) = (size)) #endif #define NELEM(set) (BPI * LOOP(set)) #define LOOPINIT(size) ((size <= BPI) ? 1 : WHICH_WORD((size)-1)) /* * FLAGS store general information about the set */ #define SET(set, flag) (set[0] |= (flag)) #define RESET(set, flag) (set[0] &= ~ (flag)) #define TESTP(set, flag) (set[0] & (flag)) /* Flag definitions are ... */ #define PRIME 0x8000 /* cube is prime */ #define NONESSEN 0x4000 /* cube cannot be essential prime */ #define ACTIVE 0x2000 /* cube is still active */ #define REDUND 0x1000 /* cube is redundant(at this point) */ #define COVERED 0x0800 /* cube has been covered */ #define RELESSEN 0x0400 /* cube is relatively essential */ /* Most efficient way to look at all members of a set family */ #define foreach_set(R, last, p)\ for(p=R->data,last=p+R->count*R->wsize;pwsize) #define foreach_remaining_set(R, last, pfirst, p)\ for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;pwsize) #define foreach_active_set(R, last, p)\ foreach_set(R,last,p) if (TESTP(p, ACTIVE)) /* Another way that also keeps the index of the current set member in i */ #define foreachi_set(R, i, p)\ for(p=R->data,i=0;icount;p+=R->wsize,i++) #define foreachi_active_set(R, i, p)\ foreachi_set(R,i,p) if (TESTP(p, ACTIVE)) /* Looping over all elements in a set: * foreach_set_element(pset p, int i, unsigned val, int base) { * . * . * . * } */ #define foreach_set_element(p, i, val, base) \ for(i = LOOP(p); i > 0; ) \ for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) \ if (val & 1) /* Return a pointer to a given member of a set family */ #define GETSET(family, index) ((family)->data + (family)->wsize * (index)) /* Allocate and deallocate sets */ #define set_new(size) set_clear(ALLOC(unsigned int, SET_SIZE(size)), size) #define set_full(size) set_fill(ALLOC(unsigned int, SET_SIZE(size)), size) #define set_save(r) set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r) #define set_free(r) FREE(r) /* Check for set membership, remove set element and insert set element */ #define is_in_set(set, e) (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e))) #define set_remove(set, e) (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e))) #define set_insert(set, e) (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e)) /* Inline code substitution for those places that REALLY need it on a VAX */ #ifdef NO_INLINE #define INLINEset_copy(r, a) (void) set_copy(r,a) #define INLINEset_clear(r, size) (void) set_clear(r, size) #define INLINEset_fill(r, size) (void) set_fill(r, size) #define INLINEset_and(r, a, b) (void) set_and(r, a, b) #define INLINEset_or(r, a, b) (void) set_or(r, a, b) #define INLINEset_diff(r, a, b) (void) set_diff(r, a, b) #define INLINEset_ndiff(r, a, b, f) (void) set_ndiff(r, a, b, f) #define INLINEset_xor(r, a, b) (void) set_xor(r, a, b) #define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f) #define INLINEset_merge(r, a, b, mask) (void) set_merge(r, a, b, mask) #define INLINEsetp_implies(a, b, when_false) \ if (! setp_implies(a,b)) when_false #define INLINEsetp_disjoint(a, b, when_false) \ if (! setp_disjoint(a,b)) when_false #define INLINEsetp_equal(a, b, when_false) \ if (! setp_equal(a,b)) when_false #else #define INLINEset_copy(r, a)\ {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);} #define INLINEset_clear(r, size)\ {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);} #define INLINEset_fill(r, size)\ {register int i_=LOOPINIT(size); *r=i_; \ r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;} #define INLINEset_and(r, a, b)\ {register int i_=LOOP(a); PUTLOOP(r,i_);\ do r[i_] = a[i_] & b[i_]; while (--i_>0);} #define INLINEset_or(r, a, b)\ {register int i_=LOOP(a); PUTLOOP(r,i_);\ do r[i_] = a[i_] | b[i_]; while (--i_>0);} #define INLINEset_diff(r, a, b)\ {register int i_=LOOP(a); PUTLOOP(r,i_);\ do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);} #define INLINEset_ndiff(r, a, b, fullset)\ {register int i_=LOOP(a); PUTLOOP(r,i_);\ do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);} #ifdef IBM_WATC #define INLINEset_xor(r, a, b) (void) set_xor(r, a, b) #define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f) #else #define INLINEset_xor(r, a, b)\ {register int i_=LOOP(a); PUTLOOP(r,i_);\ do r[i_] = a[i_] ^ b[i_]; while (--i_>0);} #define INLINEset_xnor(r, a, b, fullset)\ {register int i_=LOOP(a); PUTLOOP(r,i_);\ do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);} #endif #define INLINEset_merge(r, a, b, mask)\ {register int i_=LOOP(a); PUTLOOP(r,i_);\ do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);} #define INLINEsetp_implies(a, b, when_false)\ {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\ if (i_ != 0) when_false;} #define INLINEsetp_disjoint(a, b, when_false)\ {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\ if (i_ != 0) when_false;} #define INLINEsetp_equal(a, b, when_false)\ {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\ if (i_ != 0) when_false;} #endif #if BPI == 32 #define count_ones(v)\ (bit_count[v & 255] + bit_count[(v >> 8) & 255]\ + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255]) #else #define count_ones(v) (bit_count[v & 255] + bit_count[(v >> 8) & 255]) #endif /* Table for efficient bit counting */ extern int bit_count[256]; /*----- END OF set.h ----- */ /* Define a boolean type */ #define bool int #define FALSE 0 #define TRUE 1 #define MAYBE 2 #define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE")) /* Map many cube/cover types/routines into equivalent set types/routines */ #define pcube pset #define new_cube() set_new(cube.size) #define free_cube(r) set_free(r) #define pcover pset_family #define new_cover(i) sf_new(i, cube.size) #define free_cover(r) sf_free(r) #define free_cubelist(T) FREE(T[0]); FREE(T); /* cost_t describes the cost of a cover */ typedef struct cost_struct { int cubes; /* number of cubes in the cover */ int in; /* transistor count, binary-valued variables */ int out; /* transistor count, output part */ int mv; /* transistor count, multiple-valued vars */ int total; /* total number of transistors */ int primes; /* number of prime cubes */ } cost_t, *pcost; /* pair_t describes bit-paired variables */ typedef struct pair_struct { int cnt; int *var1; int *var2; } pair_t, *ppair; /* symbolic_list_t describes a single ".symbolic" line */ typedef struct symbolic_list_struct { int variable; int pos; struct symbolic_list_struct *next; } symbolic_list_t; /* symbolic_list_t describes a single ".symbolic" line */ typedef struct symbolic_label_struct { char *label; struct symbolic_label_struct *next; } symbolic_label_t; /* symbolic_t describes a linked list of ".symbolic" lines */ typedef struct symbolic_struct { symbolic_list_t *symbolic_list; /* linked list of items */ int symbolic_list_length; /* length of symbolic_list list */ symbolic_label_t *symbolic_label; /* linked list of new names */ int symbolic_label_length; /* length of symbolic_label list */ struct symbolic_struct *next; } symbolic_t; /* PLA_t stores the logical representation of a PLA */ typedef struct { pcover F, D, R; /* on-set, off-set and dc-set */ char *filename; /* filename */ int pla_type; /* logical PLA format */ pcube phase; /* phase to split into on-set and off-set */ ppair pair; /* how to pair variables */ char **label; /* labels for the columns */ symbolic_t *symbolic; /* allow binary->symbolic mapping */ symbolic_t *symbolic_output;/* allow symbolic output mapping */ } PLA_t, *pPLA; #define equal(a,b) (strcmp(a,b) == 0) /* This is a hack which I wish I hadn't done, but too painful to change */ #define CUBELISTSIZE(T) (((pcube *) T[1] - T) - 3) /* For documentation purposes */ #define IN #define OUT #define INOUT /* The pla_type field describes the input and output format of the PLA */ #define F_type 1 #define D_type 2 #define R_type 4 #define PLEASURE_type 8 /* output format */ #define EQNTOTT_type 16 /* output format algebraic eqns */ #define KISS_type 128 /* output format kiss */ #define CONSTRAINTS_type 256 /* output the constraints (numeric) */ #define SYMBOLIC_CONSTRAINTS_type 512 /* output the constraints (symbolic) */ #define FD_type (F_type | D_type) #define FR_type (F_type | R_type) #define DR_type (D_type | R_type) #define FDR_type (F_type | D_type | R_type) /* Definitions for the debug variable */ #define COMPL 0x0001 #define ESSEN 0x0002 #define EXPAND 0x0004 #define EXPAND1 0x0008 #define GASP 0x0010 #define IRRED 0x0020 #define REDUCE 0x0040 #define REDUCE1 0x0080 #define SPARSE 0x0100 #define TAUT 0x0200 #define EXACT 0x0400 #define MINCOV 0x0800 #define MINCOV1 0x1000 #define SHARP 0x2000 #define IRRED1 0x4000 #define VERSION\ "UC Berkeley, Espresso Version #2.3, Release date 01/31/88" /* Define constants used for recording program statistics */ #define TIME_COUNT 16 #define READ_TIME 0 #define COMPL_TIME 1 #define ONSET_TIME 2 #define ESSEN_TIME 3 #define EXPAND_TIME 4 #define IRRED_TIME 5 #define REDUCE_TIME 6 #define GEXPAND_TIME 7 #define GIRRED_TIME 8 #define GREDUCE_TIME 9 #define PRIMES_TIME 10 #define MINCOV_TIME 11 #define MV_REDUCE_TIME 12 #define RAISE_IN_TIME 13 #define VERIFY_TIME 14 #define WRITE_TIME 15 /* For those who like to think about PLAs, macros to get at inputs/outputs */ #define NUMINPUTS cube.num_binary_vars #define NUMOUTPUTS cube.part_size[cube.num_vars - 1] #define POSITIVE_PHASE(pos)\ (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0) #define INLABEL(var) PLA->label[cube.first_part[var] + 1] #define OUTLABEL(pos) PLA->label[cube.first_part[cube.output] + pos] #define GETINPUT(c, pos)\ ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3) #define GETOUTPUT(c, pos)\ (is_in_set(c, cube.first_part[cube.output] + pos) != 0) #define PUTINPUT(c, pos, value)\ c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\ | (value << WHICH_BIT(2*pos)) #define PUTOUTPUT(c, pos, value)\ c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & ~(1 << WHICH_BIT(pos)))\ | (value << WHICH_BIT(pos)) #define TWO 3 #define DASH 3 #define ONE 2 #define ZERO 1 #define EXEC(fct, name, S)\ {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);} #define EXEC_S(fct, name, S)\ {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);} #define EXECUTE(fct,i,S,cost)\ {long t=ptime();fct;totals(t,i,S,&(cost));} /* * Global Variable Declarations */ extern unsigned int debug; /* debug parameter */ extern bool verbose_debug; /* -v: whether to print a lot */ extern char *total_name[TIME_COUNT]; /* basic function names */ extern long total_time[TIME_COUNT]; /* time spent in basic fcts */ extern int total_calls[TIME_COUNT]; /* # calls to each fct */ extern bool echo_comments; /* turned off by -eat option */ extern bool echo_unknown_commands; /* always true ?? */ extern bool force_irredundant; /* -nirr command line option */ extern bool skip_make_sparse; extern bool kiss; /* -kiss command line option */ extern bool pos; /* -pos command line option */ extern bool print_solution; /* -x command line option */ extern bool recompute_onset; /* -onset command line option */ extern bool remove_essential; /* -ness command line option */ extern bool single_expand; /* -fast command line option */ extern bool summary; /* -s command line option */ extern bool trace; /* -t command line option */ extern bool unwrap_onset; /* -nunwrap command line option */ extern bool use_random_order; /* -random command line option */ extern bool use_super_gasp; /* -strong command line option */ extern char *filename; /* filename PLA was read from */ extern bool debug_exact_minimization; /* dumps info for -do exact */ /* * pla_types are the input and output types for reading/writing a PLA */ struct pla_types_struct { char *key; int value; }; /* * The cube structure is a global structure which contains information * on how a set maps into a cube -- i.e., number of parts per variable, * number of variables, etc. Also, many fields are pre-computed to * speed up various primitive operations. */ #define CUBE_TEMP 10 struct cube_struct { int size; /* set size of a cube */ int num_vars; /* number of variables in a cube */ int num_binary_vars; /* number of binary variables */ int *first_part; /* first element of each variable */ int *last_part; /* first element of each variable */ int *part_size; /* number of elements in each variable */ int *first_word; /* first word for each variable */ int *last_word; /* last word for each variable */ pset binary_mask; /* Mask to extract binary variables */ pset mv_mask; /* mask to get mv parts */ pset *var_mask; /* mask to extract a variable */ pset *temp; /* an array of temporary sets */ pset fullset; /* a full cube */ pset emptyset; /* an empty cube */ unsigned int inmask; /* mask to get odd word of binary part */ int inword; /* which word number for above */ int *sparse; /* should this variable be sparse? */ int num_mv_vars; /* number of multiple-valued variables */ int output; /* which variable is "output" (-1 if none) */ }; struct cdata_struct { int *part_zeros; /* count of zeros for each element */ int *var_zeros; /* count of zeros for each variable */ int *parts_active; /* number of "active" parts for each var */ bool *is_unate; /* indicates given var is unate */ int vars_active; /* number of "active" variables */ int vars_unate; /* number of unate variables */ int best; /* best "binate" variable */ }; extern struct pla_types_struct pla_types[]; extern struct cube_struct cube, temp_cube_save; extern struct cdata_struct cdata, temp_cdata_save; #ifdef lint #define DISJOINT 0x5555 #else #if BPI == 32 #define DISJOINT 0x55555555 #else #define DISJOINT 0x5555 #endif ABC_NAMESPACE_HEADER_END #endif /* function declarations */ /* cofactor.c */ extern int binate_split_select(); /* cofactor.c */ extern pcover cubeunlist(); /* cofactor.c */ extern pcube *cofactor(); /* cofactor.c */ extern pcube *cube1list(); /* cofactor.c */ extern pcube *cube2list(); /* cofactor.c */ extern pcube *cube3list(); /* cofactor.c */ extern pcube *scofactor(); /* cofactor.c */ extern void massive_count(); /* compl.c */ extern pcover complement(); /* compl.c */ extern pcover simplify(); /* compl.c */ extern void simp_comp(); /* contain.c */ extern int d1_rm_equal(); /* contain.c */ extern int rm2_contain(); /* contain.c */ extern int rm2_equal(); /* contain.c */ extern int rm_contain(); /* contain.c */ extern int rm_equal(); /* contain.c */ extern int rm_rev_contain(); /* contain.c */ extern pset *sf_list(); /* contain.c */ extern pset *sf_sort(); /* contain.c */ extern pset_family d1merge(); /* contain.c */ extern pset_family dist_merge(); /* contain.c */ extern pset_family sf_contain(); /* contain.c */ extern pset_family sf_dupl(); /* contain.c */ extern pset_family sf_ind_contain(); /* contain.c */ extern pset_family sf_ind_unlist(); /* contain.c */ extern pset_family sf_merge(); /* contain.c */ extern pset_family sf_rev_contain(); /* contain.c */ extern pset_family sf_union(); /* contain.c */ extern pset_family sf_unlist(); /* cubestr.c */ extern void cube_setup(); /* cubestr.c */ extern void restore_cube_struct(); /* cubestr.c */ extern void save_cube_struct(); /* cubestr.c */ extern void setdown_cube(); /* cvrin.c */ extern void PLA_labels(); /* cvrin.c */ extern char *get_word(); /* cvrin.c */ extern int label_index(); /* cvrin.c */ extern int read_pla(); /* cvrin.c */ extern int read_symbolic(); /* cvrin.c */ extern pPLA new_PLA(); /* cvrin.c */ extern void PLA_summary(); /* cvrin.c */ extern void free_PLA(); /* cvrin.c */ extern void parse_pla(); /* cvrin.c */ extern void read_cube(); /* cvrin.c */ extern void skip_line(); /* cvrm.c */ extern void foreach_output_function(); /* cvrm.c */ extern int cubelist_partition(); /* cvrm.c */ extern int so_both_do_espresso(); /* cvrm.c */ extern int so_both_do_exact(); /* cvrm.c */ extern int so_both_save(); /* cvrm.c */ extern int so_do_espresso(); /* cvrm.c */ extern int so_do_exact(); /* cvrm.c */ extern int so_save(); /* cvrm.c */ extern pcover cof_output(); /* cvrm.c */ extern pcover lex_sort(); /* cvrm.c */ extern pcover mini_sort(); /* cvrm.c */ extern pcover random_order(); /* cvrm.c */ extern pcover size_sort(); /* cvrm.c */ extern pcover sort_reduce(); /* cvrm.c */ extern pcover uncof_output(); /* cvrm.c */ extern pcover unravel(); /* cvrm.c */ extern pcover unravel_range(); /* cvrm.c */ extern void so_both_espresso(); /* cvrm.c */ extern void so_espresso(); /* cvrmisc.c */ extern char *fmt_cost(); /* cvrmisc.c */ extern char *print_cost(); /* cvrmisc.c */ extern char *strsav(); /* cvrmisc.c */ extern void copy_cost(); /* cvrmisc.c */ extern void cover_cost(); /* cvrmisc.c */ extern void fatal(); /* cvrmisc.c */ extern void print_trace(); /* cvrmisc.c */ extern void size_stamp(); /* cvrmisc.c */ extern void totals(); /* cvrout.c */ extern char *fmt_cube(); /* cvrout.c */ extern char *fmt_expanded_cube(); /* cvrout.c */ extern char *pc1(); /* cvrout.c */ extern char *pc2(); /* cvrout.c */ extern char *pc3(); /* cvrout.c */ extern void makeup_labels(); /* cvrout.c */ extern void kiss_output(); /* cvrout.c */ extern void kiss_print_cube(); /* cvrout.c */ extern void output_symbolic_constraints(); /* cvrout.c */ extern void cprint(); /* cvrout.c */ extern void debug1_print(); /* cvrout.c */ extern void debug_print(); /* cvrout.c */ extern void eqn_output(); /* cvrout.c */ extern void fpr_header(); /* cvrout.c */ extern void fprint_pla(); /* cvrout.c */ extern void pls_group(); /* cvrout.c */ extern void pls_label(); /* cvrout.c */ extern void pls_output(); /* cvrout.c */ extern void print_cube(); /* cvrout.c */ extern void print_expanded_cube(); /* cvrout.c */ extern void sf_debug_print(); /* equiv.c */ extern void find_equiv_outputs(); /* equiv.c */ extern int check_equiv(); /* espresso.c */ extern pcover espresso(); /* essen.c */ extern bool essen_cube(); /* essen.c */ extern pcover cb_consensus(); /* essen.c */ extern pcover cb_consensus_dist0(); /* essen.c */ extern pcover essential(); /* exact.c */ extern pcover minimize_exact(); /* exact.c */ extern pcover minimize_exact_literals(); /* expand.c */ extern bool feasibly_covered(); /* expand.c */ extern int most_frequent(); /* expand.c */ extern pcover all_primes(); /* expand.c */ extern pcover expand(); /* expand.c */ extern pcover find_all_primes(); /* expand.c */ extern void elim_lowering(); /* expand.c */ extern void essen_parts(); /* expand.c */ extern void essen_raising(); /* expand.c */ extern void expand1(); /* expand.c */ extern void mincov(); /* expand.c */ extern void select_feasible(); /* expand.c */ extern void setup_BB_CC(); /* gasp.c */ extern pcover expand_gasp(); /* gasp.c */ extern pcover irred_gasp(); /* gasp.c */ extern pcover last_gasp(); /* gasp.c */ extern pcover super_gasp(); /* gasp.c */ extern void expand1_gasp(); /* getopt.c */ extern int util_getopt(); /* hack.c */ extern void find_dc_inputs(); /* hack.c */ extern void find_inputs(); /* hack.c */ extern void form_bitvector(); /* hack.c */ extern void map_dcset(); /* hack.c */ extern void map_output_symbolic(); /* hack.c */ extern void map_symbolic(); /* hack.c */ extern pcover map_symbolic_cover(); /* hack.c */ extern void symbolic_hack_labels(); /* irred.c */ extern bool cube_is_covered(); /* irred.c */ extern bool taut_special_cases(); /* irred.c */ extern bool tautology(); /* irred.c */ extern pcover irredundant(); /* irred.c */ extern void mark_irredundant(); /* irred.c */ extern void irred_split_cover(); /* irred.c */ extern sm_matrix *irred_derive_table(); /* map.c */ extern pset minterms(); /* map.c */ extern void explode(); /* map.c */ extern void map(); /* opo.c */ extern void output_phase_setup(); /* opo.c */ extern pPLA set_phase(); /* opo.c */ extern pcover opo(); /* opo.c */ extern pcube find_phase(); /* opo.c */ extern pset_family find_covers(); /* opo.c */ extern pset_family form_cover_table(); /* opo.c */ extern pset_family opo_leaf(); /* opo.c */ extern pset_family opo_recur(); /* opo.c */ extern void opoall(); /* opo.c */ extern void phase_assignment(); /* opo.c */ extern void repeated_phase_assignment(); /* pair.c */ extern void generate_all_pairs(); /* pair.c */ extern int **find_pairing_cost(); /* pair.c */ extern void find_best_cost(); /* pair.c */ extern int greedy_best_cost(); /* pair.c */ extern void minimize_pair(); /* pair.c */ extern void pair_free(); /* pair.c */ extern void pair_all(); /* pair.c */ extern pcover delvar(); /* pair.c */ extern pcover pairvar(); /* pair.c */ extern ppair pair_best_cost(); /* pair.c */ extern ppair pair_new(); /* pair.c */ extern ppair pair_save(); /* pair.c */ extern void print_pair(); /* pair.c */ extern void find_optimal_pairing(); /* pair.c */ extern void set_pair(); /* pair.c */ extern void set_pair1(); /* primes.c */ extern pcover primes_consensus(); /* reduce.c */ extern bool sccc_special_cases(); /* reduce.c */ extern pcover reduce(); /* reduce.c */ extern pcube reduce_cube(); /* reduce.c */ extern pcube sccc(); /* reduce.c */ extern pcube sccc_cube(); /* reduce.c */ extern pcube sccc_merge(); /* set.c */ extern bool set_andp(); /* set.c */ extern bool set_orp(); /* set.c */ extern bool setp_disjoint(); /* set.c */ extern bool setp_empty(); /* set.c */ extern bool setp_equal(); /* set.c */ extern bool setp_full(); /* set.c */ extern bool setp_implies(); /* set.c */ extern char *pbv1(); /* set.c */ extern char *ps1(); /* set.c */ extern int *sf_count(); /* set.c */ extern int *sf_count_restricted(); /* set.c */ extern int bit_index(); /* set.c */ extern int set_dist(); /* set.c */ extern int set_ord(); /* set.c */ extern void set_adjcnt(); /* set.c */ extern pset set_and(); /* set.c */ extern pset set_clear(); /* set.c */ extern pset set_copy(); /* set.c */ extern pset set_diff(); /* set.c */ extern pset set_fill(); /* set.c */ extern pset set_merge(); /* set.c */ extern pset set_or(); /* set.c */ extern pset set_xor(); /* set.c */ extern pset sf_and(); /* set.c */ extern pset sf_or(); /* set.c */ extern pset_family sf_active(); /* set.c */ extern pset_family sf_addcol(); /* set.c */ extern pset_family sf_addset(); /* set.c */ extern pset_family sf_append(); /* set.c */ extern pset_family sf_bm_read(); /* set.c */ extern pset_family sf_compress(); /* set.c */ extern pset_family sf_copy(); /* set.c */ extern pset_family sf_copy_col(); /* set.c */ extern pset_family sf_delc(); /* set.c */ extern pset_family sf_delcol(); /* set.c */ extern pset_family sf_inactive(); /* set.c */ extern pset_family sf_join(); /* set.c */ extern pset_family sf_new(); /* set.c */ extern pset_family sf_permute(); /* set.c */ extern pset_family sf_read(); /* set.c */ extern pset_family sf_save(); /* set.c */ extern pset_family sf_transpose(); /* set.c */ extern void set_write(); /* set.c */ extern void sf_bm_print(); /* set.c */ extern void sf_cleanup(); /* set.c */ extern void sf_delset(); /* set.c */ extern void sf_free(); /* set.c */ extern void sf_print(); /* set.c */ extern void sf_write(); /* setc.c */ extern bool ccommon(); /* setc.c */ extern bool cdist0(); /* setc.c */ extern bool full_row(); /* setc.c */ extern int ascend(); /* setc.c */ extern int cactive(); /* setc.c */ extern int cdist(); /* setc.c */ extern int cdist01(); /* setc.c */ extern int cvolume(); /* setc.c */ extern int d1_order(); /* setc.c */ extern int d1_order_size(); /* setc.c */ extern int desc1(); /* setc.c */ extern int descend(); /* setc.c */ extern int lex_order(); /* setc.c */ extern int lex_order1(); /* setc.c */ extern pset force_lower(); /* setc.c */ extern void consensus(); /* sharp.c */ extern pcover cb1_dsharp(); /* sharp.c */ extern pcover cb_dsharp(); /* sharp.c */ extern pcover cb_recur_dsharp(); /* sharp.c */ extern pcover cb_recur_sharp(); /* sharp.c */ extern pcover cb_sharp(); /* sharp.c */ extern pcover cv_dsharp(); /* sharp.c */ extern pcover cv_intersect(); /* sharp.c */ extern pcover cv_sharp(); /* sharp.c */ extern pcover dsharp(); /* sharp.c */ extern pcover make_disjoint(); /* sharp.c */ extern pcover sharp(); /* sminterf.c */pset do_sm_minimum_cover(); /* sparse.c */ extern pcover make_sparse(); /* sparse.c */ extern pcover mv_reduce(); /* unate.c */ extern pcover find_all_minimal_covers_petrick(); /* unate.c */ extern pcover map_cover_to_unate(); /* unate.c */ extern pcover map_unate_to_cover(); /* unate.c */ extern pset_family exact_minimum_cover(); /* unate.c */ extern pset_family gen_primes(); /* unate.c */ extern pset_family unate_compl(); /* unate.c */ extern pset_family unate_complement(); /* unate.c */ extern pset_family unate_intersect(); /* verify.c */ extern void PLA_permute(); /* verify.c */ extern bool PLA_verify(); /* verify.c */ extern bool check_consistency(); /* verify.c */ extern bool verify(); berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/essen.c000066400000000000000000000104771300674244400241240ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* module: essen.c purpose: Find essential primes in a multiple-valued function */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* essential -- return a cover consisting of the cubes of F which are essential prime implicants (with respect to F u D); Further, remove these cubes from the ON-set F, and add them to the OFF-set D. Sometimes EXPAND can determine that a cube is not an essential prime. If so, it will set the "NONESSEN" flag in the cube. We count on IRREDUNDANT to have set the flag RELESSEN to indicate that a prime was relatively essential (i.e., covers some minterm not contained in any other prime in the current cover), or to have reset the flag to indicate that a prime was relatively redundant (i.e., all minterms covered by other primes in the current cover). Of course, after executing irredundant, all of the primes in the cover are relatively essential, but we can mark the primes which were redundant at the start of irredundant and avoid an extra check on these primes for essentiality. */ pcover essential(Fp, Dp) IN pcover *Fp, *Dp; { register pcube last, p; pcover E, F = *Fp, D = *Dp; /* set all cubes in F active */ (void) sf_active(F); /* Might as well start out with some cubes in E */ E = new_cover(10); foreach_set(F, last, p) { /* don't test a prime which EXPAND says is nonessential */ if (! TESTP(p, NONESSEN)) { /* only test a prime which was relatively essential */ if (TESTP(p, RELESSEN)) { /* Check essentiality */ if (essen_cube(F, D, p)) { if (debug & ESSEN) printf("ESSENTIAL: %s\n", pc1(p)); E = sf_addset(E, p); RESET(p, ACTIVE); F->active_count--; } } } } *Fp = sf_inactive(F); /* delete the inactive cubes from F */ *Dp = sf_join(D, E); /* add the essentials to D */ sf_free(D); return E; } /* essen_cube -- check if a single cube is essential or not The prime c is essential iff consensus((F u D) # c, c) u D does not contain c. */ bool essen_cube(F, D, c) IN pcover F, D; IN pcube c; { pcover H, FD; pcube *H1; bool essen; /* Append F and D together, and take the sharp-consensus with c */ FD = sf_join(F, D); H = cb_consensus(FD, c); free_cover(FD); /* Add the don't care set, and see if this covers c */ H1 = cube2list(H, D); essen = ! cube_is_covered(H1, c); free_cubelist(H1); free_cover(H); return essen; } /* * cb_consensus -- compute consensus(T # c, c) */ pcover cb_consensus(T, c) register pcover T; register pcube c; { register pcube temp, last, p; register pcover R; R = new_cover(T->count*2); temp = new_cube(); foreach_set(T, last, p) { if (p != c) { switch (cdist01(p, c)) { case 0: /* distance-0 needs special care */ R = cb_consensus_dist0(R, p, c); break; case 1: /* distance-1 is easy because no sharping required */ consensus(temp, p, c); R = sf_addset(R, temp); break; } } } set_free(temp); return R; } /* * form the sharp-consensus for p and c when they intersect * What we are forming is consensus(p # c, c). */ pcover cb_consensus_dist0(R, p, c) pcover R; register pcube p, c; { int var; bool got_one; register pcube temp, mask; register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1]; /* If c contains p, then this gives us no information for essential test */ if (setp_implies(p, c)) { return R; } /* For the multiple-valued variables */ temp = new_cube(); got_one = FALSE; INLINEset_diff(p_diff_c, p, c); INLINEset_and(p_and_c, p, c); for(var = cube.num_binary_vars; var < cube.num_vars; var++) { /* Check if c(var) is contained in p(var) -- if so, no news */ mask = cube.var_mask[var]; if (! setp_disjoint(p_diff_c, mask)) { INLINEset_merge(temp, c, p_and_c, mask); R = sf_addset(R, temp); got_one = TRUE; } } /* if no cube so far, add one for the intersection */ if (! got_one && cube.num_binary_vars > 0) { /* Add a single cube for the intersection of p and c */ INLINEset_and(temp, p, c); R = sf_addset(R, temp); } set_free(temp); return R; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/exact.c000066400000000000000000000102111300674244400240750ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START static void dump_irredundant(); static pcover do_minimize(); /* * minimize_exact -- main entry point for exact minimization * * Global flags which affect this routine are: * * debug * skip_make_sparse */ pcover minimize_exact(F, D, R, exact_cover) pcover F, D, R; int exact_cover; { return do_minimize(F, D, R, exact_cover, /*weighted*/ 0); } pcover minimize_exact_literals(F, D, R, exact_cover) pcover F, D, R; int exact_cover; { return do_minimize(F, D, R, exact_cover, /*weighted*/ 1); } static pcover do_minimize(F, D, R, exact_cover, weighted) pcover F, D, R; int exact_cover; int weighted; { pcover newF, E, Rt, Rp; pset p, last; int heur, level, *weights, i; sm_matrix *table; sm_row *cover; sm_element *pe; int debug_save = debug; if (debug & EXACT) { debug |= (IRRED | MINCOV); } #if defined(sun) || defined(bsd4_2) /* hack ... */ if (debug & MINCOV) { setlinebuf(stdout); } #endif level = (debug & MINCOV) ? 4 : 0; heur = ! exact_cover; /* Generate all prime implicants */ EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES ", F); /* Setup the prime implicant table */ EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E); EXEC(table = irred_derive_table(D, E, Rp), "PI-TABLE ", Rp); /* Solve either a weighted or nonweighted covering problem */ if (weighted) { /* correct only for all 2-valued variables */ weights = ALLOC(int, F->count); foreach_set(Rp, last, p) { weights[SIZE(p)] = cube.size - set_ord(p); /* We have added the 0's in the output part instead of the 1's. This loop corrects the literal count. */ for (i = cube.first_part[cube.output]; i <= cube.last_part[cube.output]; i++) { is_in_set(p, i) ? weights[SIZE(p)]++ : weights[SIZE(p)]--; } } } else { weights = NIL(int); } EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV ", F); if (weights != 0) { FREE(weights); } if (debug & EXACT) { dump_irredundant(E, Rt, Rp, table); } /* Form the result cover */ newF = new_cover(100); foreach_set(E, last, p) { newF = sf_addset(newF, p); } sm_foreach_row_element(cover, pe) { newF = sf_addset(newF, GETSET(F, pe->col_num)); } free_cover(E); free_cover(Rt); free_cover(Rp); sm_free(table); sm_row_free(cover); free_cover(F); /* Attempt to make the results more sparse */ debug &= ~ (IRRED | SHARP | MINCOV); if (! skip_make_sparse && R != 0) { newF = make_sparse(newF, D, R); } debug = debug_save; return newF; } static void dump_irredundant(E, Rt, Rp, table) pcover E, Rt, Rp; sm_matrix *table; { FILE *fp_pi_table, *fp_primes; pPLA PLA; pset last, p; char *file; if (filename == 0 || strcmp(filename, "(stdin)") == 0) { fp_pi_table = fp_primes = stdout; } else { file = ALLOC(char, strlen(filename)+20); (void) sprintf(file, "%s.primes", filename); if ((fp_primes = fopen(file, "w")) == NULL) { (void) fprintf(stderr, "espresso: Unable to open %s\n", file); fp_primes = stdout; } (void) sprintf(file, "%s.pi", filename); if ((fp_pi_table = fopen(file, "w")) == NULL) { (void) fprintf(stderr, "espresso: Unable to open %s\n", file); fp_pi_table = stdout; } FREE(file); } PLA = new_PLA(); PLA_labels(PLA); fpr_header(fp_primes, PLA, F_type); free_PLA(PLA); (void) fprintf(fp_primes, "# Essential primes are\n"); foreach_set(E, last, p) { (void) fprintf(fp_primes, "%s\n", pc1(p)); } (void) fprintf(fp_primes, "# Totally redundant primes are\n"); foreach_set(Rt, last, p) { (void) fprintf(fp_primes, "%s\n", pc1(p)); } (void) fprintf(fp_primes, "# Partially redundant primes are\n"); foreach_set(Rp, last, p) { (void) fprintf(fp_primes, "%s\n", pc1(p)); } if (fp_primes != stdout) { (void) fclose(fp_primes); } sm_write(fp_pi_table, table); if (fp_pi_table != stdout) { (void) fclose(fp_pi_table); } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/expand.c000066400000000000000000000505651300674244400242700ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* module: expand.c purpose: Perform the Espresso-II Expansion Step The idea is to take each nonprime cube of the on-set and expand it into a prime implicant such that we can cover as many other cubes of the on-set. If no cube of the on-set can be covered, then we expand each cube into a large prime implicant by transforming the problem into a minimum covering problem which is solved by the heuristics of minimum_cover. These routines revolve around having a representation of the OFF-set. (In contrast to the Espresso-II manuscript, we do NOT require an "unwrapped" version of the OFF-set). Some conventions on variable names: SUPER_CUBE is the supercube of all cubes which can be covered by an expansion of the cube being expanded OVEREXPANDED_CUBE is the cube which would result from expanding all parts which can expand individually of the cube being expanded RAISE is the current expansion of the current cube FREESET is the set of parts which haven't been raised or lowered yet. INIT_LOWER is a set of parts to be removed from the free parts before starting the expansion */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* expand -- expand each nonprime cube of F into a prime implicant If nonsparse is true, only the non-sparse variables will be expanded; this is done by forcing all of the sparse variables out of the free set. */ pcover expand(F, R, nonsparse) INOUT pcover F; IN pcover R; IN bool nonsparse; /* expand non-sparse variables only */ { register pcube last, p; pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE; int var, num_covered; bool change; /* Order the cubes according to "chewing-away from the edges" of mini */ if (use_random_order) F = random_order(F); else F = mini_sort(F, ascend); /* Allocate memory for variables needed by expand1() */ RAISE = new_cube(); FREESET = new_cube(); INIT_LOWER = new_cube(); SUPER_CUBE = new_cube(); OVEREXPANDED_CUBE = new_cube(); /* Setup the initial lowering set (differs only for nonsparse) */ if (nonsparse) for(var = 0; var < cube.num_vars; var++) if (cube.sparse[var]) (void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]); /* Mark all cubes as not covered, and maybe essential */ foreach_set(F, last, p) { RESET(p, COVERED); RESET(p, NONESSEN); } /* Try to expand each nonprime and noncovered cube */ foreach_set(F, last, p) { /* do not expand if PRIME or if covered by previous expansion */ if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) { /* expand the cube p, result is RAISE */ expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE, INIT_LOWER, &num_covered, p); if (debug & EXPAND) printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered); (void) set_copy(p, RAISE); SET(p, PRIME); RESET(p, COVERED); /* not really necessary */ /* See if we generated an inessential prime */ if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) { SET(p, NONESSEN); } } } /* Delete any cubes of F which became covered during the expansion */ F->active_count = 0; change = FALSE; foreach_set(F, last, p) { if (TESTP(p, COVERED)) { RESET(p, ACTIVE); change = TRUE; } else { SET(p, ACTIVE); F->active_count++; } } if (change) F = sf_inactive(F); free_cube(RAISE); free_cube(FREESET); free_cube(INIT_LOWER); free_cube(SUPER_CUBE); free_cube(OVEREXPANDED_CUBE); return F; } /* expand1 -- Expand a single cube against the OFF-set */ void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE, INIT_LOWER, num_covered, c) pcover BB; /* Blocking matrix (OFF-set) */ pcover CC; /* Covering matrix (ON-set) */ pcube RAISE; /* The current parts which have been raised */ pcube FREESET; /* The current parts which are free */ pcube OVEREXPANDED_CUBE; /* Overexpanded cube of c */ pcube SUPER_CUBE; /* Supercube of all cubes of CC we cover */ pcube INIT_LOWER; /* Parts to initially remove from FREESET */ int *num_covered; /* Number of cubes of CC which are covered */ pcube c; /* The cube to be expanded */ { int bestindex; if (debug & EXPAND1) printf("\nEXPAND1: \t%s\n", pc1(c)); /* initialize BB and CC */ SET(c, PRIME); /* don't try to cover ourself */ setup_BB_CC(BB, CC); /* initialize count of # cubes covered, and the supercube of them */ *num_covered = 0; (void) set_copy(SUPER_CUBE, c); /* Initialize the lowering, raising and unassigned sets */ (void) set_copy(RAISE, c); (void) set_diff(FREESET, cube.fullset, RAISE); /* If some parts are forced into lowering set, remove them */ if (! setp_empty(INIT_LOWER)) { (void) set_diff(FREESET, FREESET, INIT_LOWER); elim_lowering(BB, CC, RAISE, FREESET); } /* Determine what can be raised, and return the over-expanded cube */ essen_parts(BB, CC, RAISE, FREESET); (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET); /* While there are still cubes which can be covered, cover them ! */ if (CC->active_count > 0) { select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered); } /* While there are still cubes covered by the overexpanded cube ... */ while (CC->active_count > 0) { bestindex = most_frequent(CC, FREESET); set_insert(RAISE, bestindex); set_remove(FREESET, bestindex); essen_parts(BB, CC, RAISE, FREESET); } /* Finally, when all else fails, choose the largest possible prime */ /* We will loop only if we decide unravelling OFF-set is too expensive */ while (BB->active_count > 0) { mincov(BB, RAISE, FREESET); } /* Raise any remaining free coordinates */ (void) set_or(RAISE, RAISE, FREESET); } /* essen_parts -- determine which parts are forced into the lowering set to insure that the cube be orthognal to the OFF-set. If any cube of the OFF-set is distance 1 from the raising cube, then we must lower all parts of the conflicting variable. (If the cube is distance 0, we detect this error here.) If there are essentially lowered parts, we can remove from consideration any cubes of the OFF-set which are more than distance 1 from the overexpanded cube of RAISE. */ void essen_parts(BB, CC, RAISE, FREESET) pcover BB, CC; pcube RAISE, FREESET; { register pcube p, r = RAISE; pcube lastp, xlower = cube.temp[0]; int dist; (void) set_copy(xlower, cube.emptyset); foreach_active_set(BB, lastp, p) { #ifdef NO_INLINE if ((dist = cdist01(p, r)) > 1) goto exit_if; #else {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1) {x=p[last]&r[last];if((x=~(x|x>>1)&cube.inmask))if((dist=count_ones(x))>1)goto exit_if;for(w=1;w>1)&DISJOINT))if(dist==1||( dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube mask;for(var=cube.num_binary_vars;var1)goto exit_if;nextvar:;}} #endif if (dist == 0) { fatal("ON-set and OFF-set are not orthogonal"); } else { (void) force_lower(xlower, p, r); BB->active_count--; RESET(p, ACTIVE); } exit_if: ; } if (! setp_empty(xlower)) { (void) set_diff(FREESET, FREESET, xlower);/* remove from free set */ elim_lowering(BB, CC, RAISE, FREESET); } if (debug & EXPAND1) printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); } /* essen_raising -- determine which parts may always be added to the raising set without restricting further expansions General rule: if some part is not blocked by any cube of BB, then this part can always be raised. */ void essen_raising(BB, RAISE, FREESET) register pcover BB; pcube RAISE, FREESET; { register pcube last, p, xraise = cube.temp[0]; /* Form union of all cubes of BB, and then take complement wrt FREESET */ (void) set_copy(xraise, cube.emptyset); foreach_active_set(BB, last, p) INLINEset_or(xraise, xraise, p); (void) set_diff(xraise, FREESET, xraise); (void) set_or(RAISE, RAISE, xraise); /* add to raising set */ (void) set_diff(FREESET, FREESET, xraise); /* remove from free set */ if (debug & EXPAND1) printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); } /* elim_lowering -- after removing parts from FREESET, we can reduce the size of both BB and CC. We mark as inactive any cube of BB which does not intersect the overexpanded cube (i.e., RAISE + FREESET). Likewise, we remove from CC any cube which is not covered by the overexpanded cube. */ void elim_lowering(BB, CC, RAISE, FREESET) pcover BB, CC; pcube RAISE, FREESET; { register pcube p, r = set_or(cube.temp[0], RAISE, FREESET); pcube last; /* * Remove sets of BB which are orthogonal to future expansions */ foreach_active_set(BB, last, p) { #ifdef NO_INLINE if (! cdist0(p, r)) #else {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[ lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register pcube mask;for(var=cube.num_binary_vars;varactive_count--, RESET(p, ACTIVE); } /* * Remove sets of CC which cannot be covered by future expansions */ if (CC != (pcover) NULL) { foreach_active_set(CC, last, p) { #ifdef NO_INLINE if (! setp_implies(p, r)) #else INLINEsetp_implies(p, r, /* when false => */ goto false1); /* when true => go to end of loop */ continue; false1: #endif CC->active_count--, RESET(p, ACTIVE); } } } /* most_frequent -- When all else fails, select a reasonable part to raise The active cubes of CC are the cubes which are covered by the overexpanded cube of the original cube (however, we know that none of them can actually be covered by a feasible expansion of the original cube). We resort to the MINI strategy of selecting to raise the part which will cover the same part in the most cubes of CC. */ int most_frequent(CC, FREESET) pcover CC; pcube FREESET; { register int i, best_part, best_count, *count; register pset p, last; /* Count occurences of each variable */ count = ALLOC(int, cube.size); for(i = 0; i < cube.size; i++) count[i] = 0; if (CC != (pcover) NULL) foreach_active_set(CC, last, p) set_adjcnt(p, count, 1); /* Now find which free part occurs most often */ best_count = best_part = -1; for(i = 0; i < cube.size; i++) if (is_in_set(FREESET,i) && count[i] > best_count) { best_part = i; best_count = count[i]; } FREE(count); if (debug & EXPAND1) printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET)); return best_part; } /* setup_BB_CC -- set up the blocking and covering set families; Note that the blocking family is merely the set of cubes of R, and that CC is the set of cubes of F which might possibly be covered (i.e., nonprime cubes, and cubes not already covered) */ void setup_BB_CC(BB, CC) register pcover BB, CC; { register pcube p, last; /* Create the block and cover set families */ BB->active_count = BB->count; foreach_set(BB, last, p) SET(p, ACTIVE); if (CC != (pcover) NULL) { CC->active_count = CC->count; foreach_set(CC, last, p) if (TESTP(p, COVERED) || TESTP(p, PRIME)) CC->active_count--, RESET(p, ACTIVE); else SET(p, ACTIVE); } } /* select_feasible -- Determine if there are cubes which can be covered, and if so, raise those parts necessary to cover as many as possible. We really don't check to maximize the number that can be covered; instead, we check, for each fcc, how many other fcc remain fcc after expanding to cover the fcc. (Essentially one-level lookahead). */ void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered) pcover BB, CC; pcube RAISE, FREESET, SUPER_CUBE; int *num_covered; { register pcube p, last; register pcube bestfeas = NULL; // Suppress "might be used uninitialized" register pcube *feas; register int i, j; pcube *feas_new_lower; int bestcount, bestsize, count, size, numfeas, lastfeas; pcover new_lower; /* Start out with all cubes covered by the over-expanded cube as * the "possibly" feasibly-covered cubes (pfcc) */ feas = ALLOC(pcube, CC->active_count); numfeas = 0; foreach_active_set(CC, last, p) feas[numfeas++] = p; /* Setup extra cubes to record parts forced low after a covering */ feas_new_lower = ALLOC(pcube, CC->active_count); new_lower = new_cover(numfeas); for(i = 0; i < numfeas; i++) feas_new_lower[i] = GETSET(new_lower, i); loop: /* Find the essentially raised parts -- this might cover some cubes for us, without having to find out if they are fcc or not */ essen_raising(BB, RAISE, FREESET); /* Now check all "possibly" feasibly covered cubes to check feasibility */ lastfeas = numfeas; numfeas = 0; for(i = 0; i < lastfeas; i++) { p = feas[i]; /* Check active because essen_parts might have removed it */ if (TESTP(p, ACTIVE)) { /* See if the cube is already covered by RAISE -- * this can happen because of essen_raising() or because of * the previous "loop" */ if (setp_implies(p, RAISE)) { (*num_covered) += 1; (void) set_or(SUPER_CUBE, SUPER_CUBE, p); CC->active_count--; RESET(p, ACTIVE); SET(p, COVERED); /* otherwise, test if it is feasibly covered */ } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) { feas[numfeas] = p; /* save the fcc */ numfeas++; } } } if (debug & EXPAND1) printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n", lastfeas, numfeas); /* Exit here if there are no feasibly covered cubes */ if (numfeas == 0) { FREE(feas); FREE(feas_new_lower); free_cover(new_lower); return; } /* Now find which is the best feasibly covered cube */ bestcount = 0; bestsize = 9999; for(i = 0; i < numfeas; i++) { size = set_dist(feas[i], FREESET); /* # of newly raised parts */ count = 0; /* # of other cubes which remain fcc after raising */ #define NEW #ifdef NEW for(j = 0; j < numfeas; j++) if (setp_disjoint(feas_new_lower[i], feas[j])) count++; #else for(j = 0; j < numfeas; j++) if (setp_implies(feas[j], feas[i])) count++; #endif if (count > bestcount) { bestcount = count; bestfeas = feas[i]; bestsize = size; } else if (count == bestcount && size < bestsize) { bestfeas = feas[i]; bestsize = size; } } /* Add the necessary parts to the raising set */ (void) set_or(RAISE, RAISE, bestfeas); (void) set_diff(FREESET, FREESET, RAISE); if (debug & EXPAND1) printf("FEASIBLE: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); essen_parts(BB, CC, RAISE, FREESET); goto loop; /* NOTREACHED */ } /* feasibly_covered -- determine if the cube c is feasibly covered (i.e., if it is possible to raise all of the necessary variables while still insuring orthogonality with R). Also, if c is feasibly covered, then compute the new set of parts which are forced into the lowering set. */ bool feasibly_covered(BB, c, RAISE, new_lower) pcover BB; pcube c, RAISE, new_lower; { register pcube p, r = set_or(cube.temp[0], RAISE, c); int dist; pcube lastp; set_copy(new_lower, cube.emptyset); foreach_active_set(BB, lastp, p) { #ifdef NO_INLINE if ((dist = cdist01(p, r)) > 1) goto exit_if; #else {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1) {x=p[last]&r[last];if((x=~(x|x>>1)&cube.inmask))if((dist=count_ones(x))>1)goto exit_if;for(w=1;w>1)&DISJOINT))if(dist==1||( dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube mask;for(var=cube.num_binary_vars;var1)goto exit_if;nextvar:;}} #endif if (dist == 0) return FALSE; else (void) force_lower(new_lower, p, r); exit_if: ; } return TRUE; } /* mincov -- transform the problem of expanding a cube to a maximally- large prime implicant into the problem of selecting a minimum cardinality cover over a family of sets. When we get to this point, we must unravel the remaining off-set. This may be painful. */ void mincov(BB, RAISE, FREESET) pcover BB; pcube RAISE, FREESET; { int expansion, nset, var, dist; pset_family B; register pcube xraise=cube.temp[0], xlower, p, last, plower; #ifdef RANDOM_MINCOV #if defined(_POSIX_SOURCE) || defined(__SVR4) dist = rand() % set_ord(FREESET); #else dist = random() % set_ord(FREESET); #endif for(var = 0; var < cube.size && dist >= 0; var++) { if (is_in_set(FREESET, var)) { dist--; } } set_insert(RAISE, var); set_remove(FREESET, var); (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET); #else /* Create B which are those cubes which we must avoid intersecting */ B = new_cover(BB->active_count); foreach_active_set(BB, last, p) { plower = set_copy(GETSET(B, B->count++), cube.emptyset); (void) force_lower(plower, p, RAISE); } /* Determine how many sets it will blow up into after the unravel */ nset = 0; foreach_set(B, last, p) { expansion = 1; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { if ((dist=set_dist(p, cube.var_mask[var])) > 1) { expansion *= dist; if (expansion > 500) goto heuristic_mincov; } } nset += expansion; if (nset > 500) goto heuristic_mincov; } B = unravel(B, cube.num_binary_vars); xlower = do_sm_minimum_cover(B); /* Add any remaining free parts to the raising set */ (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower)); (void) set_copy(FREESET, cube.emptyset); /* free set is empty */ BB->active_count = 0; /* BB satisfied */ if (debug & EXPAND1) { printf("MINCOV: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); } sf_free(B); set_free(xlower); return; heuristic_mincov: sf_free(B); /* most_frequent will pick first free part */ set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET)); (void) set_diff(FREESET, FREESET, RAISE); essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET); return; #endif } /* find_all_primes -- find all of the primes which cover the currently reduced BB */ pcover find_all_primes(BB, RAISE, FREESET) pcover BB; register pcube RAISE, FREESET; { register pset last, p, plower; pset_family B, B1; if (BB->active_count == 0) { B1 = new_cover(1); p = GETSET(B1, B1->count++); (void) set_copy(p, RAISE); SET(p, PRIME); } else { B = new_cover(BB->active_count); foreach_active_set(BB, last, p) { plower = set_copy(GETSET(B, B->count++), cube.emptyset); (void) force_lower(plower, p, RAISE); } B = sf_rev_contain(unravel(B, cube.num_binary_vars)); B1 = exact_minimum_cover(B); foreach_set(B1, last, p) { INLINEset_diff(p, FREESET, p); INLINEset_or(p, p, RAISE); SET(p, PRIME); } free_cover(B); } return B1; } /* all_primes -- foreach cube in F, generate all of the primes which cover the cube. */ pcover all_primes(F, R) pcover F, R; { register pcube last, p, RAISE, FREESET; pcover Fall_primes, B1; FREESET = new_cube(); RAISE = new_cube(); Fall_primes = new_cover(F->count); foreach_set(F, last, p) { if (TESTP(p, PRIME)) { Fall_primes = sf_addset(Fall_primes, p); } else { /* Setup for call to essential parts */ (void) set_copy(RAISE, p); (void) set_diff(FREESET, cube.fullset, RAISE); setup_BB_CC(R, /* CC */ (pcover) NULL); essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET); /* Find all of the primes, and add them to the prime set */ B1 = find_all_primes(R, RAISE, FREESET); Fall_primes = sf_append(Fall_primes, B1); } } set_free(RAISE); set_free(FREESET); return Fall_primes; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/gasp.c000066400000000000000000000140111300674244400237250ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* module: gasp.c The "last_gasp" heuristic computes the reduction of each cube in the cover (without replacement) and then performs an expansion of these cubes. The cubes which expand to cover some other cube are added to the original cover and irredundant finds a minimal subset. If one of the reduced cubes expands to cover some other reduced cube, then the new prime thus generated is a candidate for reducing the size of the cover. super_gasp is a variation on this strategy which extracts a minimal subset from the set of all prime implicants which cover all maximally reduced cubes. */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* * reduce_gasp -- compute the maximal reduction of each cube of F * * If a cube does not reduce, it remains prime; otherwise, it is marked * as nonprime. If the cube is redundant (should NEVER happen here) we * just crap out ... * * A cover with all of the cubes of F is returned. Those that did * reduce are marked "NONPRIME"; those that reduced are marked "PRIME". * The cubes are in the same order as in F. */ static pcover reduce_gasp(F, D) pcover F, D; { pcube p, last, cunder, *FD; pcover G; G = new_cover(F->count); FD = cube2list(F, D); /* Reduce cubes of F without replacement */ foreach_set(F, last, p) { cunder = reduce_cube(FD, p); if (setp_empty(cunder)) { fatal("empty reduction in reduce_gasp, shouldn't happen"); } else if (setp_equal(cunder, p)) { SET(cunder, PRIME); /* just to make sure */ G = sf_addset(G, p); /* it did not reduce ... */ } else { RESET(cunder, PRIME); /* it reduced ... */ G = sf_addset(G, cunder); } if (debug & GASP) { printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder)); } free_cube(cunder); } free_cubelist(FD); return G; } /* * expand_gasp -- expand each nonprime cube of F into a prime implicant * * The gasp strategy differs in that only those cubes which expand to * cover some other cube are saved; also, all cubes are expanded * regardless of whether they become covered or not. */ pcover expand_gasp(F, D, R, Foriginal) INOUT pcover F; IN pcover D; IN pcover R; IN pcover Foriginal; { int c1index; pcover G; /* Try to expand each nonprime and noncovered cube */ G = new_cover(10); for(c1index = 0; c1index < F->count; c1index++) { expand1_gasp(F, D, R, Foriginal, c1index, &G); } G = sf_dupl(G); G = expand(G, R, /*nonsparse*/ FALSE); /* Make them prime ! */ return G; } /* * expand1 -- Expand a single cube against the OFF-set, using the gasp strategy */ void expand1_gasp(F, D, R, Foriginal, c1index, G) pcover F; /* reduced cubes of ON-set */ pcover D; /* DC-set */ pcover R; /* OFF-set */ pcover Foriginal; /* ON-set before reduction (same order as F) */ int c1index; /* which index of F (or Freduced) to be checked */ pcover *G; { register int c2index; register pcube p, last, c2under; pcube RAISE, FREESET, temp, *FD, c2essential; pcover F1; if (debug & EXPAND1) { printf("\nEXPAND1_GASP: \t%s\n", pc1(GETSET(F, c1index))); } RAISE = new_cube(); FREESET = new_cube(); temp = new_cube(); /* Initialize the OFF-set */ R->active_count = R->count; foreach_set(R, last, p) { SET(p, ACTIVE); } /* Initialize the reduced ON-set, all nonprime cubes become active */ F->active_count = F->count; foreachi_set(F, c2index, c2under) { if (c1index == c2index || TESTP(c2under, PRIME)) { F->active_count--; RESET(c2under, ACTIVE); } else { SET(c2under, ACTIVE); } } /* Initialize the raising and unassigned sets */ (void) set_copy(RAISE, GETSET(F, c1index)); (void) set_diff(FREESET, cube.fullset, RAISE); /* Determine parts which must be lowered */ essen_parts(R, F, RAISE, FREESET); /* Determine parts which can always be raised */ essen_raising(R, RAISE, FREESET); /* See which, if any, of the reduced cubes we can cover */ foreachi_set(F, c2index, c2under) { if (TESTP(c2under, ACTIVE)) { /* See if this cube can be covered by an expansion */ if (setp_implies(c2under, RAISE) || feasibly_covered(R, c2under, RAISE, temp)) { /* See if c1under can expanded to cover c2 reduced against * (F - c1) u c1under; if so, c2 can definitely be removed ! */ /* Copy F and replace c1 with c1under */ F1 = sf_save(Foriginal); (void) set_copy(GETSET(F1, c1index), GETSET(F, c1index)); /* Reduce c2 against ((F - c1) u c1under) */ FD = cube2list(F1, D); c2essential = reduce_cube(FD, GETSET(F1, c2index)); free_cubelist(FD); sf_free(F1); /* See if c2essential is covered by an expansion of c1under */ if (feasibly_covered(R, c2essential, RAISE, temp)) { (void) set_or(temp, RAISE, c2essential); RESET(temp, PRIME); /* cube not prime */ *G = sf_addset(*G, temp); } set_free(c2essential); } } } free_cube(RAISE); free_cube(FREESET); free_cube(temp); } /* irred_gasp -- Add new primes to F and find an irredundant subset */ pcover irred_gasp(F, D, G) pcover F, D, G; /* G is disposed of */ { if (G->count != 0) F = irredundant(sf_append(F, G), D); else free_cover(G); return F; } /* last_gasp */ pcover last_gasp(F, D, R, cost) pcover F, D, R; cost_t *cost; { pcover G, G1; EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost); EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost); free_cover(G); EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost); return F; } /* super_gasp */ pcover super_gasp(F, D, R, cost) pcover F, D, R; cost_t *cost; { pcover G, G1; EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost); EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost); free_cover(G); EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G); EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost); return F; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/gimpel.c000066400000000000000000000047171300674244400242640ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "mincov_int.h" ABC_NAMESPACE_IMPL_START /* * check for: * * c1 c2 rest * -- -- --- * 1 1 0 0 0 0 <-- primary row * 1 0 S1 <-- secondary row * 0 1 T1 * 0 1 T2 * 0 1 Tn * 0 0 R */ int gimpel_reduce(A, select, weight, lb, bound, depth, stats, best) sm_matrix *A; solution_t *select; int *weight; int lb; int bound; int depth; stats_t *stats; solution_t **best; { register sm_row *prow, *save_sec; register sm_col *c1 = NULL, *c2 = NULL; // Suppress "might be used uninitialized" register sm_element *p, *p1; int c1_col_num, c2_col_num; int primary_row_num = -1, secondary_row_num = -1; // Suppress "might be used uninitialized" int reduce_it; reduce_it = 0; for(prow = A->first_row; prow != 0; prow = prow->next_row) { if (prow->length == 2) { c1 = sm_get_col(A, prow->first_col->col_num); c2 = sm_get_col(A, prow->last_col->col_num); if (c1->length == 2) { reduce_it = 1; } else if (c2->length == 2) { c1 = sm_get_col(A, prow->last_col->col_num); c2 = sm_get_col(A, prow->first_col->col_num); reduce_it = 1; } if (reduce_it) { primary_row_num = prow->row_num; secondary_row_num = c1->first_row->row_num; if (secondary_row_num == primary_row_num) { secondary_row_num = c1->last_row->row_num; } break; } } } if (reduce_it) { c1_col_num = c1->col_num; c2_col_num = c2->col_num; save_sec = sm_row_dup(sm_get_row(A, secondary_row_num)); sm_row_remove(save_sec, c1_col_num); for(p = c2->first_row; p != 0; p = p->next_row) { if (p->row_num != primary_row_num) { /* merge rows S1 and T */ for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) { (void) sm_insert(A, p->row_num, p1->col_num); } } } sm_delcol(A, c1_col_num); sm_delcol(A, c2_col_num); sm_delrow(A, primary_row_num); sm_delrow(A, secondary_row_num); stats->gimpel_count++; stats->gimpel++; *best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats); stats->gimpel--; if (*best != NIL(solution_t)) { /* is secondary row covered ? */ if (sm_row_intersects(save_sec, (*best)->row)) { /* yes, actually select c2 */ solution_add(*best, weight, c2_col_num); } else { solution_add(*best, weight, c1_col_num); } } sm_row_free(save_sec); return 1; } else { return 0; } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/globals.c000066400000000000000000000053531300674244400244270ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* * Global Variable Declarations */ unsigned int debug; /* debug parameter */ bool verbose_debug; /* -v: whether to print a lot */ char *total_name[TIME_COUNT]; /* basic function names */ long total_time[TIME_COUNT]; /* time spent in basic fcts */ int total_calls[TIME_COUNT]; /* # calls to each fct */ bool echo_comments; /* turned off by -eat option */ bool echo_unknown_commands; /* always true ?? */ bool force_irredundant; /* -nirr command line option */ bool skip_make_sparse; bool kiss; /* -kiss command line option */ bool pos; /* -pos command line option */ bool print_solution; /* -x command line option */ bool recompute_onset; /* -onset command line option */ bool remove_essential; /* -ness command line option */ bool single_expand; /* -fast command line option */ bool summary; /* -s command line option */ bool trace; /* -t command line option */ bool unwrap_onset; /* -nunwrap command line option */ bool use_random_order; /* -random command line option */ bool use_super_gasp; /* -strong command line option */ char *filename; /* filename PLA was read from */ struct pla_types_struct pla_types[] = { {"-f", F_type}, {"-r", R_type}, {"-d", D_type}, {"-fd", FD_type}, {"-fr", FR_type}, {"-dr", DR_type}, {"-fdr", FDR_type}, {"-fc", F_type | CONSTRAINTS_type}, {"-rc", R_type | CONSTRAINTS_type}, {"-dc", D_type | CONSTRAINTS_type}, {"-fdc", FD_type | CONSTRAINTS_type}, {"-frc", FR_type | CONSTRAINTS_type}, {"-drc", DR_type | CONSTRAINTS_type}, {"-fdrc", FDR_type | CONSTRAINTS_type}, {"-pleasure", PLEASURE_type}, {"-eqn", EQNTOTT_type}, {"-eqntott", EQNTOTT_type}, {"-kiss", KISS_type}, {"-cons", CONSTRAINTS_type}, {"-scons", SYMBOLIC_CONSTRAINTS_type}, {0, 0} }; struct cube_struct cube, temp_cube_save; struct cdata_struct cdata, temp_cdata_save; int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/hack.c000066400000000000000000000430511300674244400237070ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START void map_dcset(PLA) pPLA PLA; { int var, i; pcover Tplus, Tminus, Tplusbar, Tminusbar; pcover newf, term1, term2, dcset, dcsetbar; pcube cplus, cminus, last, p; if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) return; /* try to find a binary variable named "DONT_CARE" */ var = -1; for(i = 0; i < cube.num_binary_vars * 2; i++) { if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 || strncmp(PLA->label[i], "DONTCARE", 8) == 0 || strncmp(PLA->label[i], "dont_care", 9) == 0 || strncmp(PLA->label[i], "dontcare", 8) == 0) { var = i/2; break; } } if (var == -1) { return; } /* form the cofactor cubes for the don't-care variable */ cplus = set_save(cube.fullset); cminus = set_save(cube.fullset); set_remove(cplus, var*2); set_remove(cminus, var*2 + 1); /* form the don't-care set */ EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar), "simpcomp+", Tplus); EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar), "simpcomp-", Tminus); EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1 ", term1); EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2 ", term2); EXEC(dcset = sf_union(term1, term2), "union ", dcset); EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D); EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate ", PLA->F); free_cover(PLA->F); PLA->F = newf; free_cover(Tplus); free_cover(Tminus); free_cover(Tplusbar); free_cover(Tminusbar); free_cover(dcsetbar); /* remove any cubes dependent on the DONT_CARE variable */ (void) sf_active(PLA->F); foreach_set(PLA->F, last, p) { if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) { RESET(p, ACTIVE); } } PLA->F = sf_inactive(PLA->F); /* resize the cube and delete the don't-care variable */ setdown_cube(); for(i = 2*var+2; i < cube.size; i++) { PLA->label[i-2] = PLA->label[i]; } for(i = var+1; i < cube.num_vars; i++) { cube.part_size[i-1] = cube.part_size[i]; } cube.num_binary_vars--; cube.num_vars--; cube_setup(); PLA->F = sf_delc(PLA->F, 2*var, 2*var+1); PLA->D = sf_delc(PLA->D, 2*var, 2*var+1); } void map_output_symbolic(PLA) pPLA PLA; { pset_family newF, newD; pset compress; symbolic_t *p1; symbolic_list_t *p2; int i, bit, tot_size, base, old_size; /* Remove the DC-set from the ON-set (is this necessary ??) */ if (PLA->D->count > 0) { sf_free(PLA->F); PLA->F = complement(cube2list(PLA->D, PLA->R)); } /* tot_size = width added for all symbolic variables */ tot_size = 0; for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) { fatal("symbolic-output index out of range"); /* } else if (p2->variable != cube.output) { fatal("symbolic-output label must be an output");*/ } } tot_size += 1 << p1->symbolic_list_length; } /* adjust the indices to skip over new outputs */ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { p2->pos += tot_size; } } /* resize the cube structure -- add enough for the one-hot outputs */ old_size = cube.size; cube.part_size[cube.output] += tot_size; setdown_cube(); cube_setup(); /* insert space in the output part for the one-hot output */ base = cube.first_part[cube.output]; PLA->F = sf_addcol(PLA->F, base, tot_size); PLA->D = sf_addcol(PLA->D, base, tot_size); PLA->R = sf_addcol(PLA->R, base, tot_size); /* do the real work */ for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { newF = new_cover(100); newD = new_cover(100); find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0, &newF, &newD); /* * Not sure what this means find_dc_inputs(PLA, p1->symbolic_list, base, 1 << p1->symbolic_list_length, &newF, &newD); */ free_cover(PLA->F); PLA->F = newF; /* * retain OLD DC-set -- but we've lost the don't-care arc information * (it defaults to branch to the zero state) free_cover(PLA->D); PLA->D = newD; */ free_cover(newD); base += 1 << p1->symbolic_list_length; } /* delete the old outputs, and resize the cube */ compress = set_full(newF->sf_size); for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { bit = cube.first_part[cube.output] + p2->pos; set_remove(compress, bit); } } cube.part_size[cube.output] -= newF->sf_size - set_ord(compress); setdown_cube(); cube_setup(); PLA->F = sf_compress(PLA->F, compress); PLA->D = sf_compress(PLA->D, compress); if (cube.size != PLA->F->sf_size) fatal("error"); /* Quick minimization */ PLA->F = sf_contain(PLA->F); PLA->D = sf_contain(PLA->D); for(i = 0; i < cube.num_vars; i++) { PLA->F = d1merge(PLA->F, i); PLA->D = d1merge(PLA->D, i); } PLA->F = sf_contain(PLA->F); PLA->D = sf_contain(PLA->D); free_cover(PLA->R); PLA->R = new_cover(0); symbolic_hack_labels(PLA, PLA->symbolic_output, compress, cube.size, old_size, tot_size); set_free(compress); } void find_inputs(A, PLA, list, base, value, newF, newD) pcover A; pPLA PLA; symbolic_list_t *list; int base, value; pcover *newF, *newD; { pcover S, S1; register pset last, p; /* * A represents th 'input' values for which the outputs assume * the integer value 'value */ if (list == NIL(symbolic_list_t)) { /* * Simulate these inputs against the on-set; then, insert into the * new on-set a 1 in the proper position */ S = cv_intersect(A, PLA->F); foreach_set(S, last, p) { set_insert(p, base + value); } *newF = sf_append(*newF, S); /* * 'simulate' these inputs against the don't-care set S = cv_intersect(A, PLA->D); *newD = sf_append(*newD, S); */ } else { /* intersect and recur with the OFF-set */ S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos); if (A != NIL(set_family_t)) { S1 = cv_intersect(A, S); free_cover(S); S = S1; } find_inputs(S, PLA, list->next, base, value*2, newF, newD); free_cover(S); /* intersect and recur with the ON-set */ S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos); if (A != NIL(set_family_t)) { S1 = cv_intersect(A, S); free_cover(S); S = S1; } find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD); free_cover(S); } } #if 0 find_dc_inputs(PLA, list, base, maxval, newF, newD) pPLA PLA; symbolic_list_t *list; int base, maxval; pcover *newF, *newD; { pcover A, S, S1; symbolic_list_t *p2; register pset p, last; register int i; /* painfully find the points for which the symbolic output is dc */ A = NIL(set_family_t); for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) { S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos); if (A == NIL(set_family_t)) { A = S; } else { S1 = cv_intersect(A, S); free_cover(S); free_cover(A); A = S1; } } S = cv_intersect(A, PLA->F); *newF = sf_append(*newF, S); S = cv_intersect(A, PLA->D); foreach_set(S, last, p) { for(i = base; i < base + maxval; i++) { set_insert(p, i); } } *newD = sf_append(*newD, S); free_cover(A); } #endif void map_symbolic(PLA) pPLA PLA; { symbolic_t *p1; symbolic_list_t *p2; int var, base, num_vars, num_binary_vars, *new_part_size; int new_size, size_added, num_deleted_vars, num_added_vars, newvar; pset compress; /* Verify legal values are in the symbolic lists */ for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { if (p2->variable < 0 || p2->variable >= cube.num_binary_vars) { fatal(".symbolic requires binary variables"); } } } /* * size_added = width added for all symbolic variables * num_deleted_vars = # binary variables to be deleted * num_added_vars = # new mv variables * compress = a cube which will be used to compress the set families */ size_added = 0; num_added_vars = 0; for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { size_added += 1 << p1->symbolic_list_length; num_added_vars++; } compress = set_full(PLA->F->sf_size + size_added); for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { set_remove(compress, p2->variable*2); set_remove(compress, p2->variable*2+1); } } num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2; /* compute the new cube constants */ num_vars = cube.num_vars - num_deleted_vars + num_added_vars; num_binary_vars = cube.num_binary_vars - num_deleted_vars; new_size = cube.size - num_deleted_vars*2 + size_added; new_part_size = ALLOC(int, num_vars); new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1]; for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) { new_part_size[var-num_deleted_vars] = cube.part_size[var]; } /* re-size the covers, opening room for the new mv variables */ base = cube.first_part[cube.output]; PLA->F = sf_addcol(PLA->F, base, size_added); PLA->D = sf_addcol(PLA->D, base, size_added); PLA->R = sf_addcol(PLA->R, base, size_added); /* compute the values for the new mv variables */ newvar = (cube.num_vars - 1) - num_deleted_vars; for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base); PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base); PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base); base += 1 << p1->symbolic_list_length; new_part_size[newvar++] = 1 << p1->symbolic_list_length; } /* delete the binary variables which disappear */ PLA->F = sf_compress(PLA->F, compress); PLA->D = sf_compress(PLA->D, compress); PLA->R = sf_compress(PLA->R, compress); symbolic_hack_labels(PLA, PLA->symbolic, compress, new_size, cube.size, size_added); setdown_cube(); FREE(cube.part_size); cube.num_vars = num_vars; cube.num_binary_vars = num_binary_vars; cube.part_size = new_part_size; cube_setup(); set_free(compress); } pcover map_symbolic_cover(T, list, base) pcover T; symbolic_list_t *list; int base; { pset last, p; foreach_set(T, last, p) { form_bitvector(p, base, 0, list); } return T; } void form_bitvector(p, base, value, list) pset p; /* old cube, looking at binary variables */ int base; /* where in mv cube the new variable starts */ int value; /* current value for this recursion */ symbolic_list_t *list; /* current place in the symbolic list */ { if (list == NIL(symbolic_list_t)) { set_insert(p, base + value); } else { switch(GETINPUT(p, list->variable)) { case ZERO: form_bitvector(p, base, value*2, list->next); break; case ONE: form_bitvector(p, base, value*2+1, list->next); break; case TWO: form_bitvector(p, base, value*2, list->next); form_bitvector(p, base, value*2+1, list->next); break; default: fatal("bad cube in form_bitvector"); } } } void symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added) pPLA PLA; symbolic_t *list; pset compress; int new_size, old_size, size_added; { int i, base; char **oldlabel; symbolic_t *p1; symbolic_label_t *p3; /* hack with the labels */ if ((oldlabel = PLA->label) == NIL(char *)) return; PLA->label = ALLOC(char *, new_size); for(i = 0; i < new_size; i++) { PLA->label[i] = NIL(char); } /* copy the binary variable labels and unchanged mv variable labels */ base = 0; for(i = 0; i < cube.first_part[cube.output]; i++) { if (is_in_set(compress, i)) { PLA->label[base++] = oldlabel[i]; } else { if (oldlabel[i] != NIL(char)) { FREE(oldlabel[i]); } } } /* add the user-defined labels for the symbolic outputs */ for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) { p3 = p1->symbolic_label; for(i = 0; i < (1 << p1->symbolic_list_length); i++) { if (p3 == NIL(symbolic_label_t)) { PLA->label[base+i] = ALLOC(char, 10); (void) sprintf(PLA->label[base+i], "X%d", i); } else { PLA->label[base+i] = p3->label; p3 = p3->next; } } base += 1 << p1->symbolic_list_length; } /* copy the labels for the binary outputs which remain */ for(i = cube.first_part[cube.output]; i < old_size; i++) { if (is_in_set(compress, i + size_added)) { PLA->label[base++] = oldlabel[i]; } else { if (oldlabel[i] != NIL(char)) { FREE(oldlabel[i]); } } } FREE(oldlabel); } static pcover fsm_simplify(F) pcover F; { pcover D, R; D = new_cover(0); R = complement(cube1list(F)); F = espresso(F, D, R); free_cover(D); free_cover(R); return F; } void disassemble_fsm(PLA, verbose_mode) pPLA PLA; int verbose_mode; { int nin, nstates, nout; int before, after, present_state, next_state, i, j; pcube next_state_mask, present_state_mask, state_mask, p, p1, last; pcover go_nowhere, F, tF; /* We make the DISGUSTING assumption that the first 'n' outputs have * been created by .symbolic-output, and represent a one-hot encoding * of the next state. 'n' is the size of the second-to-last multiple- * valued variable (i.e., before the outputs */ if (cube.num_vars - cube.num_binary_vars != 2) { (void) fprintf(stderr, "use .symbolic and .symbolic-output to specify\n"); (void) fprintf(stderr, "the present state and next state field information\n"); fatal("disassemble_pla: need two multiple-valued variables\n"); } nin = cube.num_binary_vars; nstates = cube.part_size[cube.num_binary_vars]; nout = cube.part_size[cube.num_vars - 1]; if (nout < nstates) { (void) fprintf(stderr, "use .symbolic and .symbolic-output to specify\n"); (void) fprintf(stderr, "the present state and next state field information\n"); fatal("disassemble_pla: # outputs < # states\n"); } present_state = cube.first_part[cube.num_binary_vars]; present_state_mask = new_cube(); for(i = 0; i < nstates; i++) { set_insert(present_state_mask, i + present_state); } next_state = cube.first_part[cube.num_binary_vars+1]; next_state_mask = new_cube(); for(i = 0; i < nstates; i++) { set_insert(next_state_mask, i + next_state); } state_mask = set_or(new_cube(), next_state_mask, present_state_mask); F = new_cover(10); /* * check for arcs which go from ANY state to state #i */ for(i = 0; i < nstates; i++) { tF = new_cover(10); foreach_set(PLA->F, last, p) { if (setp_implies(present_state_mask, p)) { /* from any state ! */ if (is_in_set(p, next_state + i)) { tF = sf_addset(tF, p); } } } before = tF->count; if (before > 0) { tF = fsm_simplify(tF); /* don't allow the next state to disappear ... */ foreach_set(tF, last, p) { set_insert(p, next_state + i); } after = tF->count; F = sf_append(F, tF); if (verbose_mode) { printf("# state EVERY to %d, before=%d after=%d\n", i, before, after); } } } /* * some 'arcs' may NOT have a next state -- handle these * we must unravel the present state part */ go_nowhere = new_cover(10); foreach_set(PLA->F, last, p) { if (setp_disjoint(p, next_state_mask)) { /* no next state !! */ go_nowhere = sf_addset(go_nowhere, p); } } before = go_nowhere->count; go_nowhere = unravel_range(go_nowhere, cube.num_binary_vars, cube.num_binary_vars); after = go_nowhere->count; F = sf_append(F, go_nowhere); if (verbose_mode) { printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after); } /* * minimize cover for all arcs from state #i to state #j */ for(i = 0; i < nstates; i++) { for(j = 0; j < nstates; j++) { tF = new_cover(10); foreach_set(PLA->F, last, p) { /* not EVERY state */ if (! setp_implies(present_state_mask, p)) { if (is_in_set(p, present_state + i)) { if (is_in_set(p, next_state + j)) { p1 = set_save(p); set_diff(p1, p1, state_mask); set_insert(p1, present_state + i); set_insert(p1, next_state + j); tF = sf_addset(tF, p1); set_free(p1); } } } } before = tF->count; if (before > 0) { tF = fsm_simplify(tF); /* don't allow the next state to disappear ... */ foreach_set(tF, last, p) { set_insert(p, next_state + j); } after = tF->count; F = sf_append(F, tF); if (verbose_mode) { printf("# state %d to %d, before=%d after=%d\n", i, j, before, after); } } } } free_cube(state_mask); free_cube(present_state_mask); free_cube(next_state_mask); free_cover(PLA->F); PLA->F = F; free_cover(PLA->D); PLA->D = new_cover(0); setdown_cube(); FREE(cube.part_size); cube.num_binary_vars = nin; cube.num_vars = nin + 3; cube.part_size = ALLOC(int, cube.num_vars); cube.part_size[cube.num_binary_vars] = nstates; cube.part_size[cube.num_binary_vars+1] = nstates; cube.part_size[cube.num_binary_vars+2] = nout - nstates; cube_setup(); foreach_set(PLA->F, last, p) { kiss_print_cube(stdout, PLA, p, "~1"); } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/indep.c000066400000000000000000000060251300674244400241000ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "mincov_int.h" ABC_NAMESPACE_IMPL_START static sm_matrix *build_intersection_matrix(); #if 0 /* * verify that all rows in 'indep' are actually independent ! */ static int verify_indep_set(A, indep) sm_matrix *A; sm_row *indep; { register sm_row *prow, *prow1; register sm_element *p, *p1; for(p = indep->first_col; p != 0; p = p->next_col) { prow = sm_get_row(A, p->col_num); for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) { prow1 = sm_get_row(A, p1->col_num); if (sm_row_intersects(prow, prow1)) { return 0; } } } return 1; } #endif solution_t * sm_maximal_independent_set(A, weight) sm_matrix *A; int *weight; { register sm_row *best_row, *prow; register sm_element *p; int least_weight; sm_row *save; sm_matrix *B; solution_t *indep; indep = solution_alloc(); B = build_intersection_matrix(A); while (B->nrows > 0) { /* Find the row which is disjoint from a maximum number of rows */ best_row = B->first_row; for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) { if (prow->length < best_row->length) { best_row = prow; } } /* Find which element in this row has least weight */ if (weight == NIL(int)) { least_weight = 1; } else { prow = sm_get_row(A, best_row->row_num); least_weight = weight[prow->first_col->col_num]; for(p = prow->first_col->next_col; p != 0; p = p->next_col) { if (weight[p->col_num] < least_weight) { least_weight = weight[p->col_num]; } } } indep->cost += least_weight; (void) sm_row_insert(indep->row, best_row->row_num); /* Discard the rows which intersect this row */ save = sm_row_dup(best_row); for(p = save->first_col; p != 0; p = p->next_col) { sm_delrow(B, p->col_num); sm_delcol(B, p->col_num); } sm_row_free(save); } sm_free(B); /* if (! verify_indep_set(A, indep->row)) { fail("sm_maximal_independent_set: row set is not independent"); } */ return indep; } static sm_matrix * build_intersection_matrix(A) sm_matrix *A; { register sm_row *prow, *prow1; register sm_element *p, *p1; register sm_col *pcol; sm_matrix *B; /* Build row-intersection matrix */ B = sm_alloc(); for(prow = A->first_row; prow != 0; prow = prow->next_row) { /* Clear flags on all rows we can reach from row 'prow' */ for(p = prow->first_col; p != 0; p = p->next_col) { pcol = sm_get_col(A, p->col_num); for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) { prow1 = sm_get_row(A, p1->row_num); prow1->flag = 0; } } /* Now record which rows can be reached */ for(p = prow->first_col; p != 0; p = p->next_col) { pcol = sm_get_col(A, p->col_num); for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) { prow1 = sm_get_row(A, p1->row_num); if (! prow1->flag) { prow1->flag = 1; (void) sm_insert(B, prow->row_num, prow1->row_num); } } } } return B; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/irred.c000066400000000000000000000244151300674244400241110ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START static void fcube_is_covered(); static void ftautology(); static bool ftaut_special_cases(); static int Rp_current; /* * irredundant -- Return a minimal subset of F */ pcover irredundant(F, D) pcover F, D; { mark_irredundant(F, D); return sf_inactive(F); } /* * mark_irredundant -- find redundant cubes, and mark them "INACTIVE" */ void mark_irredundant(F, D) pcover F, D; { pcover E, Rt, Rp; pset p, p1, last; sm_matrix *table; sm_row *cover; sm_element *pe; /* extract a minimum cover */ irred_split_cover(F, D, &E, &Rt, &Rp); table = irred_derive_table(D, E, Rp); cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0); /* mark the cubes for the result */ foreach_set(F, last, p) { RESET(p, ACTIVE); RESET(p, RELESSEN); } foreach_set(E, last, p) { p1 = GETSET(F, SIZE(p)); assert(setp_equal(p1, p)); SET(p1, ACTIVE); SET(p1, RELESSEN); /* for essen(), mark as rel. ess. */ } sm_foreach_row_element(cover, pe) { p1 = GETSET(F, pe->col_num); SET(p1, ACTIVE); } if (debug & IRRED) { printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n", F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count, cover->length, E->count + cover->length, 0); } free_cover(E); free_cover(Rt); free_cover(Rp); sm_free(table); sm_row_free(cover); } /* * irred_split_cover -- find E, Rt, and Rp from the cover F, D * * E -- relatively essential cubes * Rt -- totally redundant cubes * Rp -- partially redundant cubes */ void irred_split_cover(F, D, E, Rt, Rp) pcover F, D; pcover *E, *Rt, *Rp; { register pcube p, last; register int index; pcover R; pcube *FD, *ED; /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */ index = 0; foreach_set(F, last, p) { PUTSIZE(p, index); index++; } *E = new_cover(10); *Rt = new_cover(10); *Rp = new_cover(10); R = new_cover(10); /* Split F into E and R */ FD = cube2list(F, D); foreach_set(F, last, p) { if (cube_is_covered(FD, p)) { R = sf_addset(R, p); } else { *E = sf_addset(*E, p); } if (debug & IRRED1) { (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n", R->count, (*E)->count, F->count - (R->count + (*E)->count), print_time(ptime())); } } free_cubelist(FD); /* Split R into Rt and Rp */ ED = cube2list(*E, D); foreach_set(R, last, p) { if (cube_is_covered(ED, p)) { *Rt = sf_addset(*Rt, p); } else { *Rp = sf_addset(*Rp, p); } if (debug & IRRED1) { (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n", (*Rp)->count, (*Rt)->count, R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime())); } } free_cubelist(ED); free_cover(R); } /* * irred_derive_table -- given the covers D, E and the set of * partially redundant primes Rp, build a covering table showing * possible selections of primes to cover Rp. */ sm_matrix * irred_derive_table(D, E, Rp) pcover D, E, Rp; { register pcube last, p, *list; sm_matrix *table; int size_last_dominance, i; /* Mark each cube in DE as not part of the redundant set */ foreach_set(D, last, p) { RESET(p, REDUND); } foreach_set(E, last, p) { RESET(p, REDUND); } /* Mark each cube in Rp as partially redundant */ foreach_set(Rp, last, p) { SET(p, REDUND); /* belongs to redundant set */ } /* For each cube in Rp, find ways to cover its minterms */ list = cube3list(D, E, Rp); table = sm_alloc(); size_last_dominance = 0; i = 0; foreach_set(Rp, last, p) { Rp_current = SIZE(p); fcube_is_covered(list, p, table); RESET(p, REDUND); /* can now consider this cube redundant */ if (debug & IRRED1) { (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n", i, Rp->count, Rp->count - i, table->nrows, table->ncols, print_time(ptime())); } /* try to keep memory limits down by reducing table as we go along */ if (table->nrows - size_last_dominance > 1000) { (void) sm_row_dominance(table); size_last_dominance = table->nrows; if (debug & IRRED1) { (void) printf("IRRED1: delete redundant rows, now %dx%d\n", table->nrows, table->ncols); } } i++; } free_cubelist(list); return table; } /* cube_is_covered -- determine if a cubelist "covers" a single cube */ bool cube_is_covered(T, c) pcube *T, c; { return tautology(cofactor(T,c)); } /* tautology -- answer the tautology question for T */ bool tautology(T) pcube *T; /* T will be disposed of */ { register pcube cl, cr; register int best, result; static int taut_level = 0; if (debug & TAUT) { debug_print(T, "TAUTOLOGY", taut_level++); } if ((result = taut_special_cases(T)) == MAYBE) { cl = new_cube(); cr = new_cube(); best = binate_split_select(T, cl, cr, TAUT); result = tautology(scofactor(T, cl, best)) && tautology(scofactor(T, cr, best)); free_cubelist(T); free_cube(cl); free_cube(cr); } if (debug & TAUT) { printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result)); } return result; } /* * taut_special_cases -- check special cases for tautology */ bool taut_special_cases(T) pcube *T; /* will be disposed if answer is determined */ { register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1]; pcube *A, *B; int var; /* Check for a row of all 1's which implies tautology */ for(T1 = T+2; (p = *T1++) != NULL; ) { if (full_row(p, T[0])) { free_cubelist(T); return TRUE; } } /* Check for a column of all 0's which implies no tautology */ start: INLINEset_copy(ceil, T[0]); for(T1 = T+2; (p = *T1++) != NULL; ) { INLINEset_or(ceil, ceil, p); } if (! setp_equal(ceil, cube.fullset)) { free_cubelist(T); return FALSE; } /* Collect column counts, determine unate variables, etc. */ massive_count(T); /* If function is unate (and no row of all 1's), then no tautology */ if (cdata.vars_unate == cdata.vars_active) { free_cubelist(T); return FALSE; /* If active in a single variable (and no column of 0's) then tautology */ } else if (cdata.vars_active == 1) { free_cubelist(T); return TRUE; /* Check for unate variables, and reduce cover if there are any */ } else if (cdata.vars_unate != 0) { /* Form a cube "ceil" with full variables in the unate variables */ (void) set_copy(ceil, cube.emptyset); for(var = 0; var < cube.num_vars; var++) { if (cdata.is_unate[var]) { INLINEset_or(ceil, ceil, cube.var_mask[var]); } } /* Save only those cubes that are "full" in all unate variables */ for(Tsave = T1 = T+2; (p = *T1++) != 0; ) { if (setp_implies(ceil, set_or(temp, p, T[0]))) { *Tsave++ = p; } } *Tsave++ = NULL; T[1] = (pcube) Tsave; if (debug & TAUT) { printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n", (int)cdata.vars_unate, (int)CUBELISTSIZE(T)); } goto start; /* Check for component reduction */ } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) { if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) { return MAYBE; } else { free_cubelist(T); if (tautology(A)) { free_cubelist(B); return TRUE; } else { return tautology(B); } } } /* We tried as hard as we could, but must recurse from here on */ return MAYBE; } /* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */ static void fcube_is_covered(T, c, table) pcube *T, c; sm_matrix *table; { ftautology(cofactor(T,c), table); } /* ftautology -- find ways to make a tautology */ static void ftautology(T, table) pcube *T; /* T will be disposed of */ sm_matrix *table; { register pcube cl, cr; register int best; static int ftaut_level = 0; if (debug & TAUT) { debug_print(T, "FIND_TAUTOLOGY", ftaut_level++); } if (ftaut_special_cases(T, table) == MAYBE) { cl = new_cube(); cr = new_cube(); best = binate_split_select(T, cl, cr, TAUT); ftautology(scofactor(T, cl, best), table); ftautology(scofactor(T, cr, best), table); free_cubelist(T); free_cube(cl); free_cube(cr); } if (debug & TAUT) { (void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n", --ftaut_level, table->nrows, table->ncols); } } static bool ftaut_special_cases(T, table) pcube *T; /* will be disposed if answer is determined */ sm_matrix *table; { register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1]; int var, rownum; /* Check for a row of all 1's in the essential cubes */ for(T1 = T+2; (p = *T1++) != 0; ) { if (! TESTP(p, REDUND)) { if (full_row(p, T[0])) { /* subspace is covered by essentials -- no new rows for table */ free_cubelist(T); return TRUE; } } } /* Collect column counts, determine unate variables, etc. */ start: massive_count(T); /* If function is unate, find the rows of all 1's */ if (cdata.vars_unate == cdata.vars_active) { /* find which nonessentials cover this subspace */ rownum = table->last_row ? table->last_row->row_num+1 : 0; (void) sm_insert(table, rownum, Rp_current); for(T1 = T+2; (p = *T1++) != 0; ) { if (TESTP(p, REDUND)) { /* See if a redundant cube covers this leaf */ if (full_row(p, T[0])) { (void) sm_insert(table, rownum, (int) SIZE(p)); } } } free_cubelist(T); return TRUE; /* Perform unate reduction if there are any unate variables */ } else if (cdata.vars_unate != 0) { /* Form a cube "ceil" with full variables in the unate variables */ (void) set_copy(ceil, cube.emptyset); for(var = 0; var < cube.num_vars; var++) { if (cdata.is_unate[var]) { INLINEset_or(ceil, ceil, cube.var_mask[var]); } } /* Save only those cubes that are "full" in all unate variables */ for(Tsave = T1 = T+2; (p = *T1++) != 0; ) { if (setp_implies(ceil, set_or(temp, p, T[0]))) { *Tsave++ = p; } } *Tsave++ = 0; T[1] = (pcube) Tsave; if (debug & TAUT) { printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n", (int)cdata.vars_unate, (int)CUBELISTSIZE(T)); } goto start; } /* Not much we can do about it */ return MAYBE; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/main.c000066400000000000000000000456001300674244400237270ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* * Main driver for espresso * * Old style -do xxx, -out xxx, etc. are still supported. */ #include "espresso.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START /* table definitions for options */ static FILE *last_fp; static int input_type = FD_type; main(argc, argv) int argc; char *argv[]; { int i, j, first, last, strategy, out_type, option; pPLA PLA, PLA1; pcover F, Fold, Dold; pset last1, p; cost_t cost; bool error, exact_cover; long start; extern char *util_optarg; extern int util_optind; start = ptime(); error = FALSE; init_runtime(); #ifdef RANDOM srandom(314973); #endif option = 0; /* default -D: ESPRESSO */ out_type = F_type; /* default -o: default is ON-set only */ debug = 0; /* default -d: no debugging info */ verbose_debug = FALSE; /* default -v: not verbose */ print_solution = TRUE; /* default -x: print the solution (!) */ summary = FALSE; /* default -s: no summary */ trace = FALSE; /* default -t: no trace information */ strategy = 0; /* default -S: strategy number */ first = -1; /* default -R: select range */ last = -1; remove_essential = TRUE; /* default -e: */ force_irredundant = TRUE; unwrap_onset = TRUE; single_expand = FALSE; pos = FALSE; recompute_onset = FALSE; use_super_gasp = FALSE; use_random_order = FALSE; kiss = FALSE; echo_comments = TRUE; echo_unknown_commands = TRUE; exact_cover = FALSE; /* for -qm option, the default */ backward_compatibility_hack(&argc, argv, &option, &out_type); /* parse command line options*/ while ((i = util_getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) { switch(i) { case 'D': /* -Dcommand invokes a subcommand */ for(j = 0; option_table[j].name != 0; j++) { if (strcmp(util_optarg, option_table[j].name) == 0) { option = j; break; } } if (option_table[j].name == 0) { (void) fprintf(stderr, "%s: bad subcommand \"%s\"\n", argv[0], util_optarg); exit(1); } break; case 'o': /* -ooutput selects and output option */ for(j = 0; pla_types[j].key != 0; j++) { if (strcmp(util_optarg, pla_types[j].key+1) == 0) { out_type = pla_types[j].value; break; } } if (pla_types[j].key == 0) { (void) fprintf(stderr, "%s: bad output type \"%s\"\n", argv[0], util_optarg); exit(1); } break; case 'e': /* -eespresso selects an option for espresso */ for(j = 0; esp_opt_table[j].name != 0; j++) { if (strcmp(util_optarg, esp_opt_table[j].name) == 0) { *(esp_opt_table[j].variable) = esp_opt_table[j].value; break; } } if (esp_opt_table[j].name == 0) { (void) fprintf(stderr, "%s: bad espresso option \"%s\"\n", argv[0], util_optarg); exit(1); } break; case 'd': /* -d turns on (softly) all debug switches */ debug = debug_table[0].value; trace = TRUE; summary = TRUE; break; case 'v': /* -vdebug invokes a debug option */ verbose_debug = TRUE; for(j = 0; debug_table[j].name != 0; j++) { if (strcmp(util_optarg, debug_table[j].name) == 0) { debug |= debug_table[j].value; break; } } if (debug_table[j].name == 0) { (void) fprintf(stderr, "%s: bad debug type \"%s\"\n", argv[0], util_optarg); exit(1); } break; case 't': trace = TRUE; break; case 's': summary = TRUE; break; case 'x': /* -x suppress printing of results */ print_solution = FALSE; break; case 'S': /* -S sets a strategy for several cmds */ strategy = atoi(util_optarg); break; case 'r': /* -r selects range (outputs or vars) */ if (sscanf(util_optarg, "%d-%d", &first, &last) < 2) { (void) fprintf(stderr, "%s: bad output range \"%s\"\n", argv[0], util_optarg); exit(1); } break; default: usage(); exit(1); } } /* provide version information and summaries */ if (summary || trace) { /* echo command line and arguments */ printf("#"); for(i = 0; i < argc; i++) { printf(" %s", argv[i]); } printf("\n"); printf("# %s\n", VERSION); } /* the remaining arguments are argv[util_optind ... argc-1] */ PLA = PLA1 = NIL(PLA_t); switch(option_table[option].num_plas) { case 2: if (util_optind+2 < argc) fatal("trailing arguments on command line"); getPLA(util_optind++, argc, argv, option, &PLA, out_type); getPLA(util_optind++, argc, argv, option, &PLA1, out_type); break; case 1: if (util_optind+1 < argc) fatal("trailing arguments on command line"); getPLA(util_optind++, argc, argv, option, &PLA, out_type); break; } if (util_optind < argc) fatal("trailing arguments on command line"); if (summary || trace) { if (PLA != NIL(PLA_t)) PLA_summary(PLA); if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1); } /* * Now a case-statement to decide what to do */ switch(option_table[option].key) { /******************** Espresso operations ********************/ case KEY_ESPRESSO: Fold = sf_save(PLA->F); PLA->F = espresso(PLA->F, PLA->D, PLA->R); EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost); if (error) { print_solution = FALSE; PLA->F = Fold; (void) check_consistency(PLA); } else { free_cover(Fold); } break; case KEY_MANY_ESPRESSO: { int pla_type; do { EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F); if (print_solution) { fprint_pla(stdout, PLA, out_type); (void) fflush(stdout); } pla_type = PLA->pla_type; free_PLA(PLA); setdown_cube(); FREE(cube.part_size); } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF); exit(0); } case KEY_simplify: EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY ", PLA->F); break; case KEY_so: /* minimize all functions as single-output */ if (strategy < 0 || strategy > 1) { strategy = 0; } so_espresso(PLA, strategy); break; case KEY_so_both: /* minimize all functions as single-output */ if (strategy < 0 || strategy > 1) { strategy = 0; } so_both_espresso(PLA, strategy); break; case KEY_expand: /* execute expand */ EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost); break; case KEY_irred: /* extract minimal irredundant subset */ EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost); break; case KEY_reduce: /* perform reduction */ EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost); break; case KEY_essen: /* check for essential primes */ foreach_set(PLA->F, last1, p) { SET(p, RELESSEN); RESET(p, NONESSEN); } EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost); free_cover(F); break; case KEY_super_gasp: PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost); break; case KEY_gasp: PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost); break; case KEY_make_sparse: /* make_sparse step of Espresso */ PLA->F = make_sparse(PLA->F, PLA->D, PLA->R); break; case KEY_exact: exact_cover = TRUE; case KEY_qm: Fold = sf_save(PLA->F); PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover); EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost); if (error) { print_solution = FALSE; PLA->F = Fold; (void) check_consistency(PLA); } free_cover(Fold); break; case KEY_primes: /* generate all prime implicants */ EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)), "PRIMES ", PLA->F); break; case KEY_map: /* print out a Karnaugh map of function */ map(PLA->F); print_solution = FALSE; break; /******************** Output phase and bit pairing ********************/ case KEY_opo: /* sasao output phase assignment */ phase_assignment(PLA, strategy); break; case KEY_opoall: /* try all phase assignments (!) */ if (first < 0 || first >= cube.part_size[cube.output]) { first = 0; } if (last < 0 || last >= cube.part_size[cube.output]) { last = cube.part_size[cube.output] - 1; } opoall(PLA, first, last, strategy); break; case KEY_pair: /* find an optimal pairing */ find_optimal_pairing(PLA, strategy); break; case KEY_pairall: /* try all pairings !! */ pair_all(PLA, strategy); break; /******************** Simple cover operations ********************/ case KEY_echo: /* echo the PLA */ break; case KEY_taut: /* tautology check */ printf("ON-set is%sa tautology\n", tautology(cube1list(PLA->F)) ? " " : " not "); print_solution = FALSE; break; case KEY_contain: /* single cube containment */ PLA->F = sf_contain(PLA->F); break; case KEY_intersect: /* cover intersection */ PLA->F = cv_intersect(PLA->F, PLA1->F); break; case KEY_union: /* cover union */ PLA->F = sf_union(PLA->F, PLA1->F); break; case KEY_disjoint: /* make cover disjoint */ PLA->F = make_disjoint(PLA->F); break; case KEY_dsharp: /* cover disjoint-sharp */ PLA->F = cv_dsharp(PLA->F, PLA1->F); break; case KEY_sharp: /* cover sharp */ PLA->F = cv_sharp(PLA->F, PLA1->F); break; case KEY_lexsort: /* lexical sort order */ PLA->F = lex_sort(PLA->F); break; case KEY_stats: /* print info on size */ if (! summary) PLA_summary(PLA); print_solution = FALSE; break; case KEY_minterms: /* explode into minterms */ if (first < 0 || first >= cube.num_vars) { first = 0; } if (last < 0 || last >= cube.num_vars) { last = cube.num_vars - 1; } PLA->F = sf_dupl(unravel_range(PLA->F, first, last)); break; case KEY_d1merge: /* distance-1 merge */ if (first < 0 || first >= cube.num_vars) { first = 0; } if (last < 0 || last >= cube.num_vars) { last = cube.num_vars - 1; } for(i = first; i <= last; i++) { PLA->F = d1merge(PLA->F, i); } break; case KEY_d1merge_in: /* distance-1 merge inputs only */ for(i = 0; i < cube.num_binary_vars; i++) { PLA->F = d1merge(PLA->F, i); } break; case KEY_PLA_verify: /* check two PLAs for equivalence */ EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost); if (error) { printf("PLA comparison failed; the PLA's are not equivalent\n"); exit(1); } else { printf("PLA's compared equal\n"); exit(0); } break; /* silly */ case KEY_verify: /* check two covers for equivalence */ Fold = PLA->F; Dold = PLA->D; F = PLA1->F; EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost); if (error) { printf("PLA comparison failed; the PLA's are not equivalent\n"); exit(1); } else { printf("PLA's compared equal\n"); exit(0); } break; /* silly */ case KEY_check: /* check consistency */ (void) check_consistency(PLA); print_solution = FALSE; break; case KEY_mapdc: /* compute don't care set */ map_dcset(PLA); out_type = FD_type; break; case KEY_equiv: find_equiv_outputs(PLA); print_solution = FALSE; break; case KEY_separate: /* remove PLA->D from PLA->F */ PLA->F = complement(cube2list(PLA->D, PLA->R)); break; case KEY_xor: { pcover T1 = cv_intersect(PLA->F, PLA1->R); pcover T2 = cv_intersect(PLA1->F, PLA->R); free_cover(PLA->F); PLA->F = sf_contain(sf_join(T1, T2)); free_cover(T1); free_cover(T2); break; } case KEY_fsm: { disassemble_fsm(PLA, summary); print_solution = FALSE; break; } case KEY_test: { pcover T, E; T = sf_join(PLA->D, PLA->R); E = new_cover(10); sf_free(PLA->F); EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost); EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost); EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost); sf_free(T); T = sf_join(PLA->F, PLA->R); EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost); EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost); sf_free(T); sf_free(E); break; } } /* Print a runtime summary if trace mode enabled */ if (trace) { runtime(); } /* Print total runtime */ if (summary || trace) { print_trace(PLA->F, option_table[option].name, ptime()-start); } /* Output the solution */ if (print_solution) { EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost); } /* Crash and burn if there was a verify error */ if (error) { fatal("cover verification failed"); } /* cleanup all used memory */ free_PLA(PLA); FREE(cube.part_size); setdown_cube(); /* free the cube/cdata structure data */ sf_cleanup(); /* free unused set structures */ sm_cleanup(); /* sparse matrix cleanup */ exit(0); } getPLA(opt, argc, argv, option, PLA, out_type) int opt; int argc; char *argv[]; int option; pPLA *PLA; int out_type; { FILE *fp; int needs_dcset, needs_offset; char *fname; if (opt >= argc) { fp = stdin; fname = "(stdin)"; } else { fname = argv[opt]; if (strcmp(fname, "-") == 0) { fp = stdin; } else if ((fp = fopen(argv[opt], "r")) == NULL) { (void) fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname); exit(1); } } if (option_table[option].key == KEY_echo) { needs_dcset = (out_type & D_type) != 0; needs_offset = (out_type & R_type) != 0; } else { needs_dcset = option_table[option].needs_dcset; needs_offset = option_table[option].needs_offset; } if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) { (void) fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname); exit(1); } (*PLA)->filename = util_strsav(fname); filename = (*PLA)->filename; /* (void) fclose(fp);*/ /* hackto support -Dmany */ last_fp = fp; } runtime() { int i; long total = 1, temp; for(i = 0; i < TIME_COUNT; i++) { total += total_time[i]; } for(i = 0; i < TIME_COUNT; i++) { if (total_calls[i] != 0) { temp = 100 * total_time[i]; printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n", total_name[i], total_calls[i], print_time(total_time[i]), temp/total, (10 * (temp%total)) / total); } } } init_runtime() { total_name[READ_TIME] = "READ "; total_name[WRITE_TIME] = "WRITE "; total_name[COMPL_TIME] = "COMPL "; total_name[REDUCE_TIME] = "REDUCE "; total_name[EXPAND_TIME] = "EXPAND "; total_name[ESSEN_TIME] = "ESSEN "; total_name[IRRED_TIME] = "IRRED "; total_name[GREDUCE_TIME] = "REDUCE_GASP"; total_name[GEXPAND_TIME] = "EXPAND_GASP"; total_name[GIRRED_TIME] = "IRRED_GASP "; total_name[MV_REDUCE_TIME] ="MV_REDUCE "; total_name[RAISE_IN_TIME] = "RAISE_IN "; total_name[VERIFY_TIME] = "VERIFY "; total_name[PRIMES_TIME] = "PRIMES "; total_name[MINCOV_TIME] = "MINCOV "; } subcommands() { int i, col; printf(" "); col = 16; for(i = 0; option_table[i].name != 0; i++) { if ((col + strlen(option_table[i].name) + 1) > 76) { printf(",\n "); col = 16; } else if (i != 0) { printf(", "); } printf("%s", option_table[i].name); col += strlen(option_table[i].name) + 2; } printf("\n"); } usage() { printf("%s\n\n", VERSION); printf("SYNOPSIS: espresso [options] [file]\n\n"); printf(" -d Enable debugging\n"); printf(" -e[opt] Select espresso option:\n"); printf(" fast, ness, nirr, nunwrap, onset, pos, strong,\n"); printf(" eat, eatdots, kiss, random\n"); printf(" -o[type] Select output format:\n"); printf(" f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n"); printf(" -rn-m Select range for subcommands:\n"); printf(" d1merge: first and last variables (0 ... m-1)\n"); printf(" minterms: first and last variables (0 ... m-1)\n"); printf(" opoall: first and last outputs (0 ... m-1)\n"); printf(" -s Provide short execution summary\n"); printf(" -t Provide longer execution trace\n"); printf(" -x Suppress printing of solution\n"); printf(" -v[type] Verbose debugging detail (-v '' for all)\n"); printf(" -D[cmd] Execute subcommand 'cmd':\n"); subcommands(); printf(" -Sn Select strategy for subcommands:\n"); printf(" opo: bit2=exact bit1=repeated bit0=skip sparse\n"); printf(" opoall: 0=minimize, 1=exact\n"); printf(" pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n"); printf(" pairall: 0=minimize, 1=exact, 2=opo\n"); printf(" so_espresso: 0=minimize, 1=exact\n"); printf(" so_both: 0=minimize, 1=exact\n"); } /* * Hack for backward compatibility (ACK! ) */ backward_compatibility_hack(argc, argv, option, out_type) int *argc; char **argv; int *option; int *out_type; { int i, j; /* Scan the argument list for something to do (default is ESPRESSO) */ *option = 0; for(i = 1; i < (*argc)-1; i++) { if (strcmp(argv[i], "-do") == 0) { for(j = 0; option_table[j].name != 0; j++) if (strcmp(argv[i+1], option_table[j].name) == 0) { *option = j; delete_arg(argc, argv, i+1); delete_arg(argc, argv, i); break; } if (option_table[j].name == 0) { (void) fprintf(stderr, "espresso: bad keyword \"%s\" following -do\n",argv[i+1]); exit(1); } break; } } for(i = 1; i < (*argc)-1; i++) { if (strcmp(argv[i], "-out") == 0) { for(j = 0; pla_types[j].key != 0; j++) if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) { *out_type = pla_types[j].value; delete_arg(argc, argv, i+1); delete_arg(argc, argv, i); break; } if (pla_types[j].key == 0) { (void) fprintf(stderr, "espresso: bad keyword \"%s\" following -out\n",argv[i+1]); exit(1); } break; } } for(i = 1; i < (*argc); i++) { if (argv[i][0] == '-') { for(j = 0; esp_opt_table[j].name != 0; j++) { if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) { delete_arg(argc, argv, i); *(esp_opt_table[j].variable) = esp_opt_table[j].value; break; } } } } if (check_arg(argc, argv, "-fdr")) input_type = FDR_type; if (check_arg(argc, argv, "-fr")) input_type = FR_type; if (check_arg(argc, argv, "-f")) input_type = F_type; } /* delete_arg -- delete an argument from the argument list */ delete_arg(argc, argv, num) int *argc, num; register char *argv[]; { register int i; (*argc)--; for(i = num; i < *argc; i++) { argv[i] = argv[i+1]; } } /* check_arg -- scan argv for an argument, and return TRUE if found */ bool check_arg(argc, argv, s) int *argc; register char *argv[], *s; { register int i; for(i = 1; i < *argc; i++) { if (strcmp(argv[i], s) == 0) { delete_arg(argc, argv, i); return TRUE; } } return FALSE; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/main.h000066400000000000000000000076521300674244400237410ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ enum keys { KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge, KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand, KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse, KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall, KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp, KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut, KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO, KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm, KEY_unknown }; /* Lookup table for program options */ struct { char *name; enum keys key; int num_plas; bool needs_offset; bool needs_dcset; } option_table [] = { /* ways to minimize functions */ "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE, /* must be first */ "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE, "exact", KEY_exact, 1, TRUE, TRUE, "qm", KEY_qm, 1, TRUE, TRUE, "single_output", KEY_so, 1, TRUE, TRUE, "so", KEY_so, 1, TRUE, TRUE, "so_both", KEY_so_both, 1, TRUE, TRUE, "simplify", KEY_simplify, 1, FALSE, FALSE, "echo", KEY_echo, 1, FALSE, FALSE, /* output phase assignment and assignment of inputs to two-bit decoders */ "opo", KEY_opo, 1, TRUE, TRUE, "opoall", KEY_opoall, 1, TRUE, TRUE, "pair", KEY_pair, 1, TRUE, TRUE, "pairall", KEY_pairall, 1, TRUE, TRUE, /* Ways to check covers */ "check", KEY_check, 1, TRUE, TRUE, "stats", KEY_stats, 1, FALSE, FALSE, "verify", KEY_verify, 2, FALSE, TRUE, "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE, /* hacks */ "equiv", KEY_equiv, 1, TRUE, TRUE, "map", KEY_map, 1, FALSE, FALSE, "mapdc", KEY_mapdc, 1, FALSE, FALSE, "fsm", KEY_fsm, 1, FALSE, TRUE, /* the basic boolean operations on covers */ "contain", KEY_contain, 1, FALSE, FALSE, "d1merge", KEY_d1merge, 1, FALSE, FALSE, "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE, "disjoint", KEY_disjoint, 1, TRUE, FALSE, "dsharp", KEY_dsharp, 2, FALSE, FALSE, "intersect", KEY_intersect, 2, FALSE, FALSE, "minterms", KEY_minterms, 1, FALSE, FALSE, "primes", KEY_primes, 1, FALSE, TRUE, "separate", KEY_separate, 1, TRUE, TRUE, "sharp", KEY_sharp, 2, FALSE, FALSE, "union", KEY_union, 2, FALSE, FALSE, "xor", KEY_xor, 2, TRUE, TRUE, /* debugging only -- call each step of the espresso algorithm */ "essen", KEY_essen, 1, FALSE, TRUE, "expand", KEY_expand, 1, TRUE, FALSE, "gasp", KEY_gasp, 1, TRUE, TRUE, "irred", KEY_irred, 1, FALSE, TRUE, "make_sparse", KEY_make_sparse, 1, TRUE, TRUE, "reduce", KEY_reduce, 1, FALSE, TRUE, "taut", KEY_taut, 1, FALSE, FALSE, "super_gasp", KEY_super_gasp, 1, TRUE, TRUE, "lexsort", KEY_lexsort, 1, FALSE, FALSE, "test", KEY_test, 1, TRUE, TRUE, 0, KEY_unknown, 0, FALSE, FALSE /* must be last */ }; struct { char *name; int value; } debug_table[] = { "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV, "compl", COMPL, "essen", ESSEN, "expand", EXPAND, "expand1", EXPAND1|EXPAND, "irred", IRRED, "irred1", IRRED1|IRRED, "reduce", REDUCE, "reduce1", REDUCE1|REDUCE, "mincov", MINCOV, "mincov1", MINCOV1|MINCOV, "sparse", SPARSE, "sharp", SHARP, "taut", TAUT, "gasp", GASP, "exact", EXACT, 0, }; struct { char *name; int *variable; int value; } esp_opt_table[] = { "eat", &echo_comments, FALSE, "eatdots", &echo_unknown_commands, FALSE, "fast", &single_expand, TRUE, "kiss", &kiss, TRUE, "ness", &remove_essential, FALSE, "nirr", &force_irredundant, FALSE, "nunwrap", &unwrap_onset, FALSE, "onset", &recompute_onset, TRUE, "pos", &pos, TRUE, "random", &use_random_order, TRUE, "strong", &use_super_gasp, TRUE, 0, }; berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/map.c000066400000000000000000000062141300674244400235560ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START static pcube Gcube; static pset Gminterm; pset minterms(T) pcover T; { int size, var; register pcube last; size = 1; for(var = 0; var < cube.num_vars; var++) size *= cube.part_size[var]; Gminterm = set_new(size); foreach_set(T, last, Gcube) explode(cube.num_vars-1, 0); return Gminterm; } void explode(var, z) int var, z; { int i, last = cube.last_part[var]; for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++) if (is_in_set(Gcube, i)) { if (var == 0) set_insert(Gminterm, z); else explode(var-1, z); } } static int mapindex[16][16] = { { 0, 1, 3, 2, 16, 17, 19, 18, 80, 81, 83, 82, 64, 65, 67, 66}, { 4, 5, 7, 6, 20, 21, 23, 22, 84, 85, 87, 86, 68, 69, 71, 70}, { 12, 13, 15, 14, 28, 29, 31, 30, 92, 93, 95, 94, 76, 77, 79, 78}, { 8, 9, 11, 10, 24, 25, 27, 26, 88, 89, 91, 90, 72, 73, 75, 74}, { 32, 33, 35, 34, 48, 49, 51, 50, 112,113,115,114, 96, 97, 99, 98}, { 36, 37, 39, 38, 52, 53, 55, 54, 116,117,119,118, 100,101,103,102}, { 44, 45, 47, 46, 60, 61, 63, 62, 124,125,127,126, 108,109,111,110}, { 40, 41, 43, 42, 56, 57, 59, 58, 120,121,123,122, 104,105,107,106}, {160,161,163,162, 176,177,179,178, 240,241,243,242, 224,225,227,226}, {164,165,167,166, 180,181,183,182, 244,245,247,246, 228,229,231,230}, {172,173,175,174, 188,189,191,190, 252,253,255,254, 236,237,239,238}, {168,169,171,170, 184,185,187,186, 248,249,251,250, 232,233,235,234}, {128,129,131,130, 144,145,147,146, 208,209,211,210, 192,193,195,194}, {132,133,135,134, 148,149,151,150, 212,213,215,214, 196,197,199,198}, {140,141,143,142, 156,157,159,158, 220,221,223,222, 204,205,207,206}, {136,137,139,138, 152,153,155,154, 216,217,219,218, 200,201,203,202} }; #define POWER2(n) (1 << n) void map(T) pcover T; { int j, k, l, other_input_offset, output_offset, outnum, ind; int largest_input_ind, numout; char c; pset m; bool some_output; m = minterms(T); largest_input_ind = POWER2(cube.num_binary_vars); numout = cube.part_size[cube.num_vars-1]; for(outnum = 0; outnum < numout; outnum++) { output_offset = outnum * largest_input_ind; printf("\n\nOutput space # %d\n", outnum); for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) { other_input_offset = l * 256; for(k = 0; k < 16; k++) { some_output = FALSE; for(j = 0; j < 16; j++) { ind = mapindex[k][j] + other_input_offset; if (ind < largest_input_ind) { c = is_in_set(m, ind+output_offset) ? '1' : '.'; putchar(c); some_output = TRUE; } if ((j+1)%4 == 0) putchar(' '); if ((j+1)%8 == 0) printf(" "); } if (some_output) putchar('\n'); if ((k+1)%4 == 0) { if (k != 15 && mapindex[k+1][0] >= largest_input_ind) break; putchar('\n'); } if ((k+1)%8 == 0) putchar('\n'); } } } set_free(m); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/matrix.c000066400000000000000000000273271300674244400243150ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ //#include "port.h" #include "sparse_int.h" ABC_NAMESPACE_IMPL_START /* * free-lists are only used if 'FAST_AND_LOOSE' is set; this is because * we lose the debugging capability of libmm_t which trashes objects when * they are free'd. However, FAST_AND_LOOSE is much faster if matrices * are created and freed frequently. */ #ifdef FAST_AND_LOOSE sm_element *sm_element_freelist; sm_row *sm_row_freelist; sm_col *sm_col_freelist; #endif sm_matrix * sm_alloc() { register sm_matrix *A; A = ALLOC(sm_matrix, 1); A->rows = NIL(sm_row *); A->cols = NIL(sm_col *); A->nrows = A->ncols = 0; A->rows_size = A->cols_size = 0; A->first_row = A->last_row = NIL(sm_row); A->first_col = A->last_col = NIL(sm_col); A->user_word = NIL(char); /* for our user ... */ return A; } sm_matrix * sm_alloc_size(row, col) int row, col; { register sm_matrix *A; A = sm_alloc(); sm_resize(A, row, col); return A; } void sm_free(A) sm_matrix *A; { #ifdef FAST_AND_LOOSE register sm_row *prow; if (A->first_row != 0) { for(prow = A->first_row; prow != 0; prow = prow->next_row) { /* add the elements to the free list of elements */ prow->last_col->next_col = sm_element_freelist; sm_element_freelist = prow->first_col; } /* Add the linked list of rows to the row-free-list */ A->last_row->next_row = sm_row_freelist; sm_row_freelist = A->first_row; /* Add the linked list of cols to the col-free-list */ A->last_col->next_col = sm_col_freelist; sm_col_freelist = A->first_col; } #else register sm_row *prow, *pnext_row; register sm_col *pcol, *pnext_col; for(prow = A->first_row; prow != 0; prow = pnext_row) { pnext_row = prow->next_row; sm_row_free(prow); } for(pcol = A->first_col; pcol != 0; pcol = pnext_col) { pnext_col = pcol->next_col; pcol->first_row = pcol->last_row = NIL(sm_element); sm_col_free(pcol); } #endif /* Free the arrays to map row/col numbers into pointers */ FREE(A->rows); FREE(A->cols); FREE(A); } sm_matrix * sm_dup(A) sm_matrix *A; { register sm_row *prow; register sm_element *p; register sm_matrix *B; B = sm_alloc(); if (A->last_row != 0) { sm_resize(B, A->last_row->row_num, A->last_col->col_num); for(prow = A->first_row; prow != 0; prow = prow->next_row) { for(p = prow->first_col; p != 0; p = p->next_col) { (void) sm_insert(B, p->row_num, p->col_num); } } } return B; } void sm_resize(A, row, col) register sm_matrix *A; int row, col; { register int i, new_size; if (row >= A->rows_size) { new_size = MAX(A->rows_size*2, row+1); A->rows = REALLOC(sm_row *, A->rows, new_size); for(i = A->rows_size; i < new_size; i++) { A->rows[i] = NIL(sm_row); } A->rows_size = new_size; } if (col >= A->cols_size) { new_size = MAX(A->cols_size*2, col+1); A->cols = REALLOC(sm_col *, A->cols, new_size); for(i = A->cols_size; i < new_size; i++) { A->cols[i] = NIL(sm_col); } A->cols_size = new_size; } } /* * insert -- insert a value into the matrix */ sm_element * sm_insert(A, row, col) register sm_matrix *A; register int row, col; { register sm_row *prow; register sm_col *pcol; register sm_element *element; sm_element *save_element; if (row >= A->rows_size || col >= A->cols_size) { sm_resize(A, row, col); } prow = A->rows[row]; if (prow == NIL(sm_row)) { prow = A->rows[row] = sm_row_alloc(); prow->row_num = row; sorted_insert(sm_row, A->first_row, A->last_row, A->nrows, next_row, prev_row, row_num, row, prow); } pcol = A->cols[col]; if (pcol == NIL(sm_col)) { pcol = A->cols[col] = sm_col_alloc(); pcol->col_num = col; sorted_insert(sm_col, A->first_col, A->last_col, A->ncols, next_col, prev_col, col_num, col, pcol); } /* get a new item, save its address */ sm_element_alloc(element); save_element = element; /* insert it into the row list */ sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length, next_col, prev_col, col_num, col, element); /* if it was used, also insert it into the column list */ if (element == save_element) { sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length, next_row, prev_row, row_num, row, element); } else { /* otherwise, it was already in matrix -- free element we allocated */ sm_element_free(save_element); } return element; } sm_element * sm_find(A, rownum, colnum) sm_matrix *A; int rownum, colnum; { sm_row *prow; sm_col *pcol; prow = sm_get_row(A, rownum); if (prow == NIL(sm_row)) { return NIL(sm_element); } else { pcol = sm_get_col(A, colnum); if (pcol == NIL(sm_col)) { return NIL(sm_element); } if (prow->length < pcol->length) { return sm_row_find(prow, colnum); } else { return sm_col_find(pcol, rownum); } } } void sm_remove(A, rownum, colnum) sm_matrix *A; int rownum, colnum; { sm_remove_element(A, sm_find(A, rownum, colnum)); } void sm_remove_element(A, p) register sm_matrix *A; register sm_element *p; { register sm_row *prow; register sm_col *pcol; if (p == 0) return; /* Unlink the element from its row */ prow = sm_get_row(A, p->row_num); dll_unlink(p, prow->first_col, prow->last_col, next_col, prev_col, prow->length); /* if no more elements in the row, discard the row header */ if (prow->first_col == NIL(sm_element)) { sm_delrow(A, p->row_num); } /* Unlink the element from its column */ pcol = sm_get_col(A, p->col_num); dll_unlink(p, pcol->first_row, pcol->last_row, next_row, prev_row, pcol->length); /* if no more elements in the column, discard the column header */ if (pcol->first_row == NIL(sm_element)) { sm_delcol(A, p->col_num); } sm_element_free(p); } void sm_delrow(A, i) sm_matrix *A; int i; { register sm_element *p, *pnext; sm_col *pcol; sm_row *prow; prow = sm_get_row(A, i); if (prow != NIL(sm_row)) { /* walk across the row */ for(p = prow->first_col; p != 0; p = pnext) { pnext = p->next_col; /* unlink the item from the column (and delete it) */ pcol = sm_get_col(A, p->col_num); sm_col_remove_element(pcol, p); /* discard the column if it is now empty */ if (pcol->first_row == NIL(sm_element)) { sm_delcol(A, pcol->col_num); } } /* discard the row -- we already threw away the elements */ A->rows[i] = NIL(sm_row); dll_unlink(prow, A->first_row, A->last_row, next_row, prev_row, A->nrows); prow->first_col = prow->last_col = NIL(sm_element); sm_row_free(prow); } } void sm_delcol(A, i) sm_matrix *A; int i; { register sm_element *p, *pnext; sm_row *prow; sm_col *pcol; pcol = sm_get_col(A, i); if (pcol != NIL(sm_col)) { /* walk down the column */ for(p = pcol->first_row; p != 0; p = pnext) { pnext = p->next_row; /* unlink the element from the row (and delete it) */ prow = sm_get_row(A, p->row_num); sm_row_remove_element(prow, p); /* discard the row if it is now empty */ if (prow->first_col == NIL(sm_element)) { sm_delrow(A, prow->row_num); } } /* discard the column -- we already threw away the elements */ A->cols[i] = NIL(sm_col); dll_unlink(pcol, A->first_col, A->last_col, next_col, prev_col, A->ncols); pcol->first_row = pcol->last_row = NIL(sm_element); sm_col_free(pcol); } } void sm_copy_row(dest, dest_row, prow) register sm_matrix *dest; int dest_row; sm_row *prow; { register sm_element *p; for(p = prow->first_col; p != 0; p = p->next_col) { (void) sm_insert(dest, dest_row, p->col_num); } } void sm_copy_col(dest, dest_col, pcol) register sm_matrix *dest; int dest_col; sm_col *pcol; { register sm_element *p; for(p = pcol->first_row; p != 0; p = p->next_row) { (void) sm_insert(dest, dest_col, p->row_num); } } sm_row * sm_longest_row(A) sm_matrix *A; { register sm_row *large_row, *prow; register int max_length; max_length = 0; large_row = NIL(sm_row); for(prow = A->first_row; prow != 0; prow = prow->next_row) { if (prow->length > max_length) { max_length = prow->length; large_row = prow; } } return large_row; } sm_col * sm_longest_col(A) sm_matrix *A; { register sm_col *large_col, *pcol; register int max_length; max_length = 0; large_col = NIL(sm_col); for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { if (pcol->length > max_length) { max_length = pcol->length; large_col = pcol; } } return large_col; } int sm_num_elements(A) sm_matrix *A; { register sm_row *prow; register int num; num = 0; sm_foreach_row(A, prow) { num += prow->length; } return num; } int sm_read(fp, A) FILE *fp; sm_matrix **A; { int i, j, err; *A = sm_alloc(); while (! feof(fp)) { err = fscanf(fp, "%d %d", &i, &j); if (err == EOF) { return 1; } else if (err != 2) { return 0; } (void) sm_insert(*A, i, j); } return 1; } int sm_read_compressed(fp, A) FILE *fp; sm_matrix **A; { int i, j, k, nrows, ncols; unsigned long x; *A = sm_alloc(); if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) { return 0; } sm_resize(*A, nrows, ncols); for(i = 0; i < nrows; i++) { if (fscanf(fp, "%lx", &x) != 1) { return 0; } for(j = 0; j < ncols; j += 32) { if (fscanf(fp, "%lx", &x) != 1) { return 0; } for(k = j; x != 0; x >>= 1, k++) { if (x & 1) { (void) sm_insert(*A, i, k); } } } } return 1; } void sm_write(fp, A) FILE *fp; sm_matrix *A; { register sm_row *prow; register sm_element *p; for(prow = A->first_row; prow != 0; prow = prow->next_row) { for(p = prow->first_col; p != 0; p = p->next_col) { (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num); } } } void sm_print(fp, A) FILE *fp; sm_matrix *A; { register sm_row *prow; register sm_col *pcol; int c; if (A->last_col->col_num >= 100) { (void) fprintf(fp, " "); for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { (void) fprintf(fp, "%d", (pcol->col_num / 100)%10); } putc('\n', fp); } if (A->last_col->col_num >= 10) { (void) fprintf(fp, " "); for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { (void) fprintf(fp, "%d", (pcol->col_num / 10)%10); } putc('\n', fp); } (void) fprintf(fp, " "); for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { (void) fprintf(fp, "%d", pcol->col_num % 10); } putc('\n', fp); (void) fprintf(fp, " "); for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { (void) fprintf(fp, "-"); } putc('\n', fp); for(prow = A->first_row; prow != 0; prow = prow->next_row) { (void) fprintf(fp, "%3d:", prow->row_num); for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { c = sm_row_find(prow, pcol->col_num) ? '1' : '.'; putc(c, fp); } putc('\n', fp); } } void sm_dump(A, s, max) sm_matrix *A; char *s; int max; { FILE *fp = stdout; (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols); if (A->nrows < max) { sm_print(fp, A); } } void sm_cleanup() { #ifdef FAST_AND_LOOSE register sm_element *p, *pnext; register sm_row *prow, *pnextrow; register sm_col *pcol, *pnextcol; for(p = sm_element_freelist; p != 0; p = pnext) { pnext = p->next_col; FREE(p); } sm_element_freelist = 0; for(prow = sm_row_freelist; prow != 0; prow = pnextrow) { pnextrow = prow->next_row; FREE(prow); } sm_row_freelist = 0; for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) { pnextcol = pcol->next_col; FREE(pcol); } sm_col_freelist = 0; #endif } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/mincov.c000066400000000000000000000233761300674244400243040ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "mincov_int.h" ABC_NAMESPACE_IMPL_START /* * mincov.c */ #define USE_GIMPEL #define USE_INDEP_SET static int select_column(); static void select_essential(); static int verify_cover(); #define fail(why) {\ (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ __FILE__, __LINE__, why);\ (void) fflush(stdout);\ abort();\ } sm_row * sm_minimum_cover(A, weight, heuristic, debug_level) sm_matrix *A; int *weight; int heuristic; /* set to 1 for a heuristic covering */ int debug_level; /* how deep in the recursion to provide info */ { stats_t stats; solution_t *best, *select; sm_row *prow, *sol; sm_col *pcol; sm_matrix *dup_A; int nelem, bound; double sparsity; /* Avoid sillyness */ if (A->nrows <= 0) { return sm_row_alloc(); /* easy to cover */ } /* Initialize debugging structure */ stats.start_time = util_cpu_time(); stats.debug = debug_level > 0; stats.max_print_depth = debug_level; stats.max_depth = -1; stats.nodes = 0; stats.component = stats.comp_count = 0; stats.gimpel = stats.gimpel_count = 0; stats.no_branching = heuristic != 0; stats.lower_bound = -1; /* Check the matrix sparsity */ nelem = 0; sm_foreach_row(A, prow) { nelem += prow->length; } sparsity = (double) nelem / (double) (A->nrows * A->ncols); /* Determine an upper bound on the solution */ bound = 1; sm_foreach_col(A, pcol) { bound += WEIGHT(weight, pcol->col_num); } /* Perform the covering */ select = solution_alloc(); dup_A = sm_dup(A); best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats); sm_free(dup_A); solution_free(select); if (stats.debug) { if (stats.no_branching) { (void) printf("**** heuristic covering ...\n"); (void) printf("lower bound = %d\n", stats.lower_bound); } (void) printf("matrix = %d by %d with %d elements (%4.3f%%)\n", A->nrows, A->ncols, nelem, sparsity * 100.0); (void) printf("cover size = %d elements\n", best->row->length); (void) printf("cover cost = %d\n", best->cost); (void) printf("time = %s\n", util_print_time(util_cpu_time() - stats.start_time)); (void) printf("components = %d\n", stats.comp_count); (void) printf("gimpel = %d\n", stats.gimpel_count); (void) printf("nodes = %d\n", stats.nodes); (void) printf("max_depth = %d\n", stats.max_depth); } sol = sm_row_dup(best->row); if (! verify_cover(A, sol)) { fail("mincov: internal error -- cover verification failed\n"); } solution_free(best); return sol; } /* * Find the best cover for 'A' (given that 'select' already selected); * * - abort search if a solution cannot be found which beats 'bound' * * - if any solution meets 'lower_bound', then it is the optimum solution * and can be returned without further work. */ solution_t * sm_mincov(A, select, weight, lb, bound, depth, stats) sm_matrix *A; solution_t *select; int *weight; int lb; int bound; int depth; stats_t *stats; { sm_matrix *A1, *A2, *L, *R; sm_element *p; solution_t *select1, *select2, *best, *best1, *best2, *indep; int pick, lb_new, debug; /* Start out with some debugging information */ stats->nodes++; if (depth > stats->max_depth) stats->max_depth = depth; debug = stats->debug && (depth <= stats->max_print_depth); /* Apply row dominance, column dominance, and select essentials */ select_essential(A, select, weight, bound); if (select->cost >= bound) { return NIL(solution_t); } /* See if gimpel's reduction technique applies ... */ #ifdef USE_GIMPEL if ( weight == NIL(int)) { /* hack until we fix it */ if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) { return best; } } #endif #ifdef USE_INDEP_SET /* Determine bound from here to final solution using independent-set */ indep = sm_maximal_independent_set(A, weight); /* make sure the lower bound is monotonically increasing */ lb_new = MAX(select->cost + indep->cost, lb); pick = select_column(A, weight, indep); solution_free(indep); #else lb_new = select->cost + (A->nrows > 0); pick = select_column(A, weight, NIL(solution_t)); #endif if (depth == 0) { stats->lower_bound = lb_new + stats->gimpel; } if (debug) { (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " "); (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ", A->nrows, A->ncols, select->cost + stats->gimpel, bound + stats->gimpel, lb_new + stats->gimpel, util_print_time(util_cpu_time()-stats->start_time)); } /* Check for bounding based on no better solution possible */ if (lb_new >= bound) { if (debug) (void) printf("bounded\n"); best = NIL(solution_t); /* Check for new best solution */ } else if (A->nrows == 0) { best = solution_dup(select); if (debug) (void) printf("BEST\n"); if (stats->debug && stats->component == 0) { (void) printf("new 'best' solution %d at level %d (time is %s)\n", best->cost + stats->gimpel, depth, util_print_time(util_cpu_time() - stats->start_time)); } /* Check for a partition of the problem */ } else if (sm_block_partition(A, &L, &R)) { /* Make L the smaller problem */ if (L->ncols > R->ncols) { A1 = L; L = R; R = A1; } if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows); stats->comp_count++; /* Solve problem for L */ select1 = solution_alloc(); stats->component++; best1 = sm_mincov(L, select1, weight, 0, bound-select->cost, depth+1, stats); stats->component--; solution_free(select1); sm_free(L); /* Add best solution to the selected set */ if (best1 == NIL(solution_t)) { best = NIL(solution_t); } else { for(p = best1->row->first_col; p != 0; p = p->next_col) { solution_add(select, weight, p->col_num); } solution_free(best1); /* recur for the remaining block */ best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats); } sm_free(R); /* We've tried as hard as possible, but now we must split and recur */ } else { if (debug) (void) printf("pick=%d\n", pick); /* Assume we choose this column to be in the covering set */ A1 = sm_dup(A); select1 = solution_dup(select); solution_accept(select1, A1, weight, pick); best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats); solution_free(select1); sm_free(A1); /* Update the upper bound if we found a better solution */ if (best1 != NIL(solution_t) && bound > best1->cost) { bound = best1->cost; } /* See if this is a heuristic covering (no branching) */ if (stats->no_branching) { return best1; } /* Check for reaching lower bound -- if so, don't actually branch */ if (best1 != NIL(solution_t) && best1->cost == lb_new) { return best1; } /* Now assume we cannot have that column */ A2 = sm_dup(A); select2 = solution_dup(select); solution_reject(select2, A2, weight, pick); best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats); solution_free(select2); sm_free(A2); best = solution_choose_best(best1, best2); } return best; } static int select_column(A, weight, indep) sm_matrix *A; int *weight; solution_t *indep; { register sm_col *pcol; register sm_row *prow, *indep_cols; register sm_element *p, *p1; double w, best; int best_col; indep_cols = sm_row_alloc(); if (indep != NIL(solution_t)) { /* Find which columns are in the independent sets */ for(p = indep->row->first_col; p != 0; p = p->next_col) { prow = sm_get_row(A, p->col_num); for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) { (void) sm_row_insert(indep_cols, p1->col_num); } } } else { /* select out of all columns */ sm_foreach_col(A, pcol) { (void) sm_row_insert(indep_cols, pcol->col_num); } } /* Find the best column */ best_col = -1; best = -1; /* Consider only columns which are in some independent row */ sm_foreach_row_element(indep_cols, p1) { pcol = sm_get_col(A, p1->col_num); /* Compute the total 'value' of all things covered by the column */ w = 0.0; for(p = pcol->first_row; p != 0; p = p->next_row) { prow = sm_get_row(A, p->row_num); w += 1.0 / ((double) prow->length - 1.0); } /* divide this by the relative cost of choosing this column */ w = w / (double) WEIGHT(weight, pcol->col_num); /* maximize this ratio */ if (w > best) { best_col = pcol->col_num; best = w; } } sm_row_free(indep_cols); return best_col; } static void select_essential(A, select, weight, bound) sm_matrix *A; solution_t *select; int *weight; int bound; /* must beat this solution */ { register sm_element *p; register sm_row *prow, *essen; int delcols, delrows, essen_count; do { /* Check for dominated columns */ delcols = sm_col_dominance(A, weight); /* Find the rows with only 1 element (the essentials) */ essen = sm_row_alloc(); sm_foreach_row(A, prow) { if (prow->length == 1) { (void) sm_row_insert(essen, prow->first_col->col_num); } } /* Select all of the elements */ sm_foreach_row_element(essen, p) { solution_accept(select, A, weight, p->col_num); /* Make sure solution still looks good */ if (select->cost >= bound) { sm_row_free(essen); return; } } essen_count = essen->length; sm_row_free(essen); /* Check for dominated rows */ delrows = sm_row_dominance(A); } while (delcols > 0 || delrows > 0 || essen_count > 0); } static int verify_cover(A, cover) sm_matrix *A; sm_row *cover; { sm_row *prow; sm_foreach_row(A, prow) { if (! sm_row_intersects(prow, cover)) { return 0; } } return 1; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/mincov.h000066400000000000000000000002171300674244400242760ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* exported */ extern sm_row *sm_minimum_cover(); berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/mincov_int.h000066400000000000000000000024661300674244400251600ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ //#include "port.h" //#include "utility.h" #include "sparse.h" #include "mincov.h" #include "util_hack.h" // added typedef struct stats_struct stats_t; struct stats_struct { int debug; /* 1 if debugging is enabled */ int max_print_depth; /* dump stats for levels up to this level */ int max_depth; /* deepest the recursion has gone */ int nodes; /* total nodes visited */ int component; /* currently solving a component */ int comp_count; /* number of components detected */ int gimpel_count; /* number of times Gimpel reduction applied */ int gimpel; /* currently inside Gimpel reduction */ long start_time; /* cpu time when the covering started */ int no_branching; int lower_bound; }; typedef struct solution_struct solution_t; struct solution_struct { sm_row *row; int cost; }; extern solution_t *solution_alloc(); extern void solution_free(); extern solution_t *solution_dup(); extern void solution_accept(); extern void solution_reject(); extern void solution_add(); extern solution_t *solution_choose_best(); extern solution_t *sm_maximal_independent_set(); extern solution_t *sm_mincov(); extern int gimpel_reduce(); #define ABC__misc__espresso__mincov_int_h berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/module.make000066400000000000000000000022531300674244400247600ustar00rootroot00000000000000SRC += src/misc/espresso/cofactor.c \ src/misc/espresso/cols.c \ src/misc/espresso/compl.c \ src/misc/espresso/contain.c \ src/misc/espresso/cubehack.c \ src/misc/espresso/cubestr.c \ src/misc/espresso/cvrin.c \ src/misc/espresso/cvrm.c \ src/misc/espresso/cvrmisc.c \ src/misc/espresso/cvrout.c \ src/misc/espresso/dominate.c \ src/misc/espresso/equiv.c \ src/misc/espresso/espresso.c \ src/misc/espresso/essen.c \ src/misc/espresso/exact.c \ src/misc/espresso/expand.c \ src/misc/espresso/gasp.c \ src/misc/espresso/gimpel.c \ src/misc/espresso/globals.c \ src/misc/espresso/hack.c \ src/misc/espresso/indep.c \ src/misc/espresso/irred.c \ src/misc/espresso/map.c \ src/misc/espresso/matrix.c \ src/misc/espresso/mincov.c \ src/misc/espresso/opo.c \ src/misc/espresso/pair.c \ src/misc/espresso/part.c \ src/misc/espresso/primes.c \ src/misc/espresso/reduce.c \ src/misc/espresso/rows.c \ src/misc/espresso/set.c \ src/misc/espresso/setc.c \ src/misc/espresso/sharp.c \ src/misc/espresso/sminterf.c \ src/misc/espresso/solution.c \ src/misc/espresso/sparse.c \ src/misc/espresso/unate.c \ src/misc/espresso/verify.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/opo.c000066400000000000000000000401451300674244400235770ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* * Phase assignment technique (T. Sasao): * * 1. create a function with 2*m outputs which implements the * original function and its complement for each output * * 2. minimize this function * * 3. choose the minimum number of prime implicants from the * result of step 2 which are needed to realize either a function * or its complement for each output * * Step 3 is performed in a rather crude way -- by simply multiplying * out a large expression of the form: * * I = (ab + cdef)(acd + bgh) ... * * which is a product of m expressions where each expression has two * product terms -- one representing which primes are needed for the * function, and one representing which primes are needed for the * complement. The largest product term resulting shows which primes * to keep to implement one function or the other for each output. * For problems with many outputs, this may grind to a * halt. * * Untried: form complement of I and use unate_complement ... * * I have unsuccessfully tried several modifications to the basic * algorithm. The first is quite simple: use Sasao's technique, but * only commit to a single output at a time (rather than all * outputs). The goal would be that the later minimizations can "take * into account" the partial assignment at each step. This is * expensive (m+1 minimizations rather than 2), and the results are * discouraging. * * The second modification is rather complicated. The result from the * minimization in step 2 is guaranteed to be minimal. Hence, for * each output, the set of primes with a 1 in that output are both * necessary and sufficient to implement the function. Espresso * achieves the minimality using the routine MAKE_SPARSE. The * modification is to prevent MAKE_SPARSE from running. Hence, there * are potentially many subsets of the set of primes with a 1 in a * column which can be used to implement that output. We use * IRREDUNDANT to enumerate all possible subsets and then proceed as * before. */ static int opo_no_make_sparse; static int opo_repeated; static int opo_exact; static void minimize(); void phase_assignment(PLA, opo_strategy) pPLA PLA; int opo_strategy; { opo_no_make_sparse = opo_strategy % 2; skip_make_sparse = opo_no_make_sparse; opo_repeated = (opo_strategy / 2) % 2; opo_exact = (opo_strategy / 4) % 2; /* Determine a phase assignment */ if (PLA->phase != NULL) { FREE(PLA->phase); } if (opo_repeated) { PLA->phase = set_save(cube.fullset); repeated_phase_assignment(PLA); } else { PLA->phase = find_phase(PLA, 0, (pcube) NULL); } /* Now minimize with this assignment */ skip_make_sparse = FALSE; (void) set_phase(PLA); minimize(PLA); } /* * repeated_phase_assignment -- an alternate strategy which commits * to a single phase assignment a step at a time. Performs m + 1 * minimizations ! */ void repeated_phase_assignment(PLA) pPLA PLA; { int i; pcube phase; for(i = 0; i < cube.part_size[cube.output]; i++) { /* Find best assignment for all undecided outputs */ phase = find_phase(PLA, i, PLA->phase); /* Commit for only a single output ... */ if (! is_in_set(phase, cube.first_part[cube.output] + i)) { set_remove(PLA->phase, cube.first_part[cube.output] + i); } if (trace || summary) { printf("\nOPO loop for output #%d\n", i); printf("PLA->phase is %s\n", pc1(PLA->phase)); printf("phase is %s\n", pc1(phase)); } set_free(phase); } } /* * find_phase -- find a phase assignment for the PLA for all outputs starting * with output number first_output. */ pcube find_phase(PLA, first_output, phase1) pPLA PLA; int first_output; pcube phase1; { pcube phase; pPLA PLA1; phase = set_save(cube.fullset); /* setup the double-phase characteristic function, resize the cube */ PLA1 = new_PLA(); PLA1->F = sf_save(PLA->F); PLA1->R = sf_save(PLA->R); PLA1->D = sf_save(PLA->D); if (phase1 != NULL) { PLA1->phase = set_save(phase1); (void) set_phase(PLA1); } EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F); /* minimize the double-phase function */ minimize(PLA1); /* set the proper phases according to what gives a minimum solution */ EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output), "OPO ", PLA1->F); free_PLA(PLA1); /* set the cube structure to reflect the old size */ setdown_cube(); cube.part_size[cube.output] -= (cube.part_size[cube.output] - first_output) / 2; cube_setup(); return phase; } /* * opo -- multiply the expression out to determine a minimum subset of * primes. */ /*ARGSUSED*/ pcover opo(phase, T, D, R, first_output) pcube phase; pcover T, D, R; int first_output; { int offset, output, i, last_output, ind; pset pdest, select, p, p1, last, last1, not_covered, tmp; pset_family temp, T1, T2; /* must select all primes for outputs [0 .. first_output-1] */ select = set_full(T->count); for(output = 0; output < first_output; output++) { ind = cube.first_part[cube.output] + output; foreachi_set(T, i, p) { if (is_in_set(p, ind)) { set_remove(select, i); } } } /* Recursively perform the intersections */ offset = (cube.part_size[cube.output] - first_output) / 2; last_output = first_output + offset - 1; temp = opo_recur(T, D, select, offset, first_output, last_output); /* largest set is on top -- select primes which are inferred from it */ pdest = temp->data; T1 = new_cover(T->count); foreachi_set(T, i, p) { if (! is_in_set(pdest, i)) { T1 = sf_addset(T1, p); } } set_free(select); sf_free(temp); /* finding phases is difficult -- see which functions are not covered */ T2 = complement(cube1list(T1)); not_covered = new_cube(); tmp = new_cube(); foreach_set(T, last, p) { foreach_set(T2, last1, p1) { if (cdist0(p, p1)) { (void) set_or(not_covered, not_covered, set_and(tmp, p, p1)); } } } free_cover(T); free_cover(T2); set_free(tmp); /* Now reflect the phase choice in a single cube */ for(output = first_output; output <= last_output; output++) { ind = cube.first_part[cube.output] + output; if (is_in_set(not_covered, ind)) { if (is_in_set(not_covered, ind + offset)) { fatal("error in output phase assignment"); } else { set_remove(phase, ind); } } } set_free(not_covered); return T1; } pset_family opo_recur(T, D, select, offset, first, last) pcover T, D; pcube select; int offset, first, last; { static int level = 0; int middle; pset_family sl, sr, temp; level++; if (first == last) { #if 0 if (opo_no_make_sparse) { temp = form_cover_table(T, D, select, first, first + offset); } else { temp = opo_leaf(T, select, first, first + offset); } #else temp = opo_leaf(T, select, first, first + offset); #endif } else { middle = (first + last) / 2; sl = opo_recur(T, D, select, offset, first, middle); sr = opo_recur(T, D, select, offset, middle+1, last); temp = unate_intersect(sl, sr, level == 1); if (trace) { printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1, temp->count, sl->count, sr->count, print_time(ptime())); (void) fflush(stdout); } free_cover(sl); free_cover(sr); } level--; return temp; } pset_family opo_leaf(T, select, out1, out2) register pcover T; pset select; int out1, out2; { register pset_family temp; register pset p, pdest; register int i; out1 += cube.first_part[cube.output]; out2 += cube.first_part[cube.output]; /* Allocate space for the result */ temp = sf_new(2, T->count); /* Find which primes are needed for the ON-set of this fct */ pdest = GETSET(temp, temp->count++); (void) set_copy(pdest, select); foreachi_set(T, i, p) { if (is_in_set(p, out1)) { set_remove(pdest, i); } } /* Find which primes are needed for the OFF-set of this fct */ pdest = GETSET(temp, temp->count++); (void) set_copy(pdest, select); foreachi_set(T, i, p) { if (is_in_set(p, out2)) { set_remove(pdest, i); } } return temp; } #if 0 pset_family form_cover_table(F, D, select, f, fbar) pcover F, D; pset select; int f, fbar; /* indices of f and fbar in the output part */ { register int i; register pcube p; pset_family f_table, fbar_table; /* setup required for fcube_is_covered */ Rp_size = F->count; Rp_start = set_new(Rp_size); foreachi_set(F, i, p) { PUTSIZE(p, i); } foreachi_set(D, i, p) { RESET(p, REDUND); } f_table = find_covers(F, D, select, f); fbar_table = find_covers(F, D, select, fbar); f_table = sf_append(f_table, fbar_table); set_free(Rp_start); return f_table; } pset_family find_covers(F, D, select, n) pcover F, D; register pset select; int n; { register pset p, last, new; pcover F1; pcube *Flist; pset_family f_table, table; int i; n += cube.first_part[cube.output]; /* save cubes in this output, and remove the output variable */ F1 = new_cover(F->count); foreach_set(F, last, p) if (is_in_set(p, n)) { new = GETSET(F1, F1->count++); set_or(new, p, cube.var_mask[cube.output]); PUTSIZE(new, SIZE(p)); SET(new, REDUND); } /* Find ways (sop form) to fail to cover output indexed by n */ Flist = cube2list(F1, D); table = sf_new(10, Rp_size); foreach_set(F1, last, p) { set_fill(Rp_start, Rp_size); set_remove(Rp_start, SIZE(p)); table = sf_append(table, fcube_is_covered(Flist, p)); RESET(p, REDUND); } set_fill(Rp_start, Rp_size); foreach_set(table, last, p) { set_diff(p, Rp_start, p); } /* complement this to get possible ways to cover the function */ for(i = 0; i < Rp_size; i++) { if (! is_in_set(select, i)) { p = set_new(Rp_size); set_insert(p, i); table = sf_addset(table, p); set_free(p); } } f_table = unate_compl(table); /* what a pain, but we need bitwise complement of this */ set_fill(Rp_start, Rp_size); foreach_set(f_table, last, p) { set_diff(p, Rp_start, p); } free_cubelist(Flist); sf_free(F1); return f_table; } #endif /* * Take a PLA (ON-set, OFF-set and DC-set) and create the * "double-phase characteristic function" which is merely a new * function which has twice as many outputs and realizes both the * function and the complement. * * The cube structure is assumed to represent the PLA upon entering. * It will be modified to represent the double-phase function upon * exit. * * Only the outputs numbered starting with "first_output" are * duplicated in the output part */ void output_phase_setup(PLA, first_output) INOUT pPLA PLA; int first_output; { pcover F, R, D; pcube mask, mask1, last; int first_part, offset; bool save; register pcube p, pr, pf; register int i, last_part; if (cube.output == -1) fatal("output_phase_setup: must have an output"); F = PLA->F; D = PLA->D; R = PLA->R; first_part = cube.first_part[cube.output] + first_output; last_part = cube.last_part[cube.output]; offset = cube.part_size[cube.output] - first_output; /* Change the output size, setup the cube structure */ setdown_cube(); cube.part_size[cube.output] += offset; cube_setup(); /* Create a mask to select that part of the cube which isn't changing */ mask = set_save(cube.fullset); for(i = first_part; i < cube.size; i++) set_remove(mask, i); mask1 = set_save(mask); for(i = cube.first_part[cube.output]; i < first_part; i++) { set_remove(mask1, i); } PLA->F = new_cover(F->count + R->count); PLA->R = new_cover(F->count + R->count); PLA->D = new_cover(D->count); foreach_set(F, last, p) { pf = GETSET(PLA->F, (PLA->F)->count++); pr = GETSET(PLA->R, (PLA->R)->count++); INLINEset_and(pf, mask, p); INLINEset_and(pr, mask1, p); for(i = first_part; i <= last_part; i++) if (is_in_set(p, i)) set_insert(pf, i); save = FALSE; for(i = first_part; i <= last_part; i++) if (is_in_set(p, i)) save = TRUE, set_insert(pr, i+offset); if (! save) PLA->R->count--; } foreach_set(R, last, p) { pf = GETSET(PLA->F, (PLA->F)->count++); pr = GETSET(PLA->R, (PLA->R)->count++); INLINEset_and(pf, mask1, p); INLINEset_and(pr, mask, p); save = FALSE; for(i = first_part; i <= last_part; i++) if (is_in_set(p, i)) save = TRUE, set_insert(pf, i+offset); if (! save) PLA->F->count--; for(i = first_part; i <= last_part; i++) if (is_in_set(p, i)) set_insert(pr, i); } foreach_set(D, last, p) { pf = GETSET(PLA->D, (PLA->D)->count++); INLINEset_and(pf, mask, p); for(i = first_part; i <= last_part; i++) if (is_in_set(p, i)) { set_insert(pf, i); set_insert(pf, i+offset); } } free_cover(F); free_cover(D); free_cover(R); set_free(mask); set_free(mask1); } /* * set_phase -- given a "cube" which describes which phases of the output * are to be implemented, compute the appropriate on-set and off-set */ pPLA set_phase(PLA) INOUT pPLA PLA; { pcover F1, R1; register pcube last, p, outmask; register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1]; outmask = cube.var_mask[cube.num_vars - 1]; set_diff(phase1, outmask, phase); set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1); F1 = new_cover((PLA->F)->count + (PLA->R)->count); R1 = new_cover((PLA->F)->count + (PLA->R)->count); foreach_set(PLA->F, last, p) { if (! setp_disjoint(set_and(temp, p, phase), outmask)) set_copy(GETSET(F1, F1->count++), temp); if (! setp_disjoint(set_and(temp, p, phase1), outmask)) set_copy(GETSET(R1, R1->count++), temp); } foreach_set(PLA->R, last, p) { if (! setp_disjoint(set_and(temp, p, phase), outmask)) set_copy(GETSET(R1, R1->count++), temp); if (! setp_disjoint(set_and(temp, p, phase1), outmask)) set_copy(GETSET(F1, F1->count++), temp); } free_cover(PLA->F); free_cover(PLA->R); PLA->F = F1; PLA->R = R1; return PLA; } #define POW2(x) (1 << (x)) void opoall(PLA, first_output, last_output, opo_strategy) pPLA PLA; int first_output, last_output; int opo_strategy; { pcover F, D, R, best_F, best_D, best_R; int i, j, ind, num; pcube bestphase; opo_exact = opo_strategy; if (PLA->phase != NULL) { set_free(PLA->phase); } bestphase = set_save(cube.fullset); best_F = sf_save(PLA->F); best_D = sf_save(PLA->D); best_R = sf_save(PLA->R); for(i = 0; i < POW2(last_output - first_output + 1); i++) { /* save the initial PLA covers */ F = sf_save(PLA->F); D = sf_save(PLA->D); R = sf_save(PLA->R); /* compute the phase cube for this iteration */ PLA->phase = set_save(cube.fullset); num = i; for(j = last_output; j >= first_output; j--) { if (num % 2 == 0) { ind = cube.first_part[cube.output] + j; set_remove(PLA->phase, ind); } num /= 2; } /* set the phase and minimize */ (void) set_phase(PLA); printf("# phase is %s\n", pc1(PLA->phase)); summary = TRUE; minimize(PLA); /* see if this is the best so far */ if (PLA->F->count < best_F->count) { /* save new best solution */ set_copy(bestphase, PLA->phase); sf_free(best_F); sf_free(best_D); sf_free(best_R); best_F = PLA->F; best_D = PLA->D; best_R = PLA->R; } else { /* throw away the solution */ free_cover(PLA->F); free_cover(PLA->D); free_cover(PLA->R); } set_free(PLA->phase); /* restore the initial PLA covers */ PLA->F = F; PLA->D = D; PLA->R = R; } /* one more minimization to restore the best answer */ PLA->phase = bestphase; sf_free(PLA->F); sf_free(PLA->D); sf_free(PLA->R); PLA->F = best_F; PLA->D = best_D; PLA->R = best_R; } static void minimize(PLA) pPLA PLA; { if (opo_exact) { EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F); } else { EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO ",PLA->F); } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/pair.c000066400000000000000000000431561300674244400237420ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START void set_pair(PLA) pPLA PLA; { set_pair1(PLA, TRUE); } void set_pair1(PLA, adjust_labels) pPLA PLA; bool adjust_labels; { int i, var, *paired, newvar; int old_num_vars, old_num_binary_vars, old_size, old_mv_start; int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start; ppair pair = PLA->pair; char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar; if (adjust_labels) makeup_labels(PLA); /* Check the pair structure for valid entries and see which binary variables are left unpaired */ paired = ALLOC(bool, cube.num_binary_vars); for(var = 0; var < cube.num_binary_vars; var++) paired[var] = FALSE; for(i = 0; i < pair->cnt; i++) if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) && (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) { paired[pair->var1[i]-1] = TRUE; paired[pair->var2[i]-1] = TRUE; } else fatal("can only pair binary-valued variables"); PLA->F = delvar(pairvar(PLA->F, pair), paired); PLA->R = delvar(pairvar(PLA->R, pair), paired); PLA->D = delvar(pairvar(PLA->D, pair), paired); /* Now painfully adjust the cube size */ old_size = cube.size; old_num_vars = cube.num_vars; old_num_binary_vars = cube.num_binary_vars; old_mv_start = cube.first_part[cube.num_binary_vars]; /* Create the new cube.part_size vector and setup the cube structure */ new_num_binary_vars = 0; for(var = 0; var < old_num_binary_vars; var++) new_num_binary_vars += (paired[var] == FALSE); new_num_vars = new_num_binary_vars + pair->cnt; new_num_vars += old_num_vars - old_num_binary_vars; new_part_size = ALLOC(int, new_num_vars); for(var = 0; var < pair->cnt; var++) new_part_size[new_num_binary_vars + var] = 4; for(var = 0; var < old_num_vars - old_num_binary_vars; var++) new_part_size[new_num_binary_vars + pair->cnt + var] = cube.part_size[old_num_binary_vars + var]; setdown_cube(); FREE(cube.part_size); cube.num_vars = new_num_vars; cube.num_binary_vars = new_num_binary_vars; cube.part_size = new_part_size; cube_setup(); /* hack with the labels to get them correct */ if (adjust_labels) { oldlabel = PLA->label; PLA->label = ALLOC(char *, cube.size); for(var = 0; var < pair->cnt; var++) { newvar = cube.num_binary_vars*2 + var*4; var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1]; var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1]; var1bar = oldlabel[ (pair->var1[var]-1) * 2]; var2bar = oldlabel[ (pair->var2[var]-1) * 2]; (void) sprintf(scratch, "%s+%s", var1bar, var2bar); PLA->label[newvar] = util_strsav(scratch); (void) sprintf(scratch, "%s+%s", var1bar, var2); PLA->label[newvar+1] = util_strsav(scratch); (void) sprintf(scratch, "%s+%s", var1, var2bar); PLA->label[newvar+2] = util_strsav(scratch); (void) sprintf(scratch, "%s+%s", var1, var2); PLA->label[newvar+3] = util_strsav(scratch); } /* Copy the old labels for the unpaired binary vars */ i = 0; for(var = 0; var < old_num_binary_vars; var++) { if (paired[var] == FALSE) { PLA->label[2*i] = oldlabel[2*var]; PLA->label[2*i+1] = oldlabel[2*var+1]; oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL; i++; } } /* Copy the old labels for the remaining unpaired vars */ new_mv_start = cube.num_binary_vars*2 + pair->cnt*4; for(i = old_mv_start; i < old_size; i++) { PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i]; oldlabel[i] = (char *) NULL; } /* free remaining entries in oldlabel */ for(i = 0; i < old_size; i++) if (oldlabel[i] != (char *) NULL) FREE(oldlabel[i]); FREE(oldlabel); } /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/ for(var = 0; var < pair->cnt; var++) cube.sparse[cube.num_binary_vars + var] = 0; FREE(paired); } pcover pairvar(A, pair) pcover A; ppair pair; { register pcube last, p; register int val, p1, p2, b1, b0; int insert_col, pairnum; insert_col = cube.first_part[cube.num_vars - 1]; /* stretch the cover matrix to make room for the paired variables */ A = sf_delcol(A, insert_col, -4*pair->cnt); /* compute the paired values */ foreach_set(A, last, p) { for(pairnum = 0; pairnum < pair->cnt; pairnum++) { p1 = cube.first_part[pair->var1[pairnum] - 1]; p2 = cube.first_part[pair->var2[pairnum] - 1]; b1 = is_in_set(p, p2+1); b0 = is_in_set(p, p2); val = insert_col + pairnum * 4; if (/* a0 */ is_in_set(p, p1)) { if (b0) set_insert(p, val + 3); if (b1) set_insert(p, val + 2); } if (/* a1 */ is_in_set(p, p1+1)) { if (b0) set_insert(p, val + 1); if (b1) set_insert(p, val); } } } return A; } /* delvar -- delete variables from A, minimize the number of column shifts */ pcover delvar(A, paired) pcover A; bool paired[]; { bool run; int first_run = 0; // Suppress "might be used uninitialized" int run_length, var, offset = 0; run = FALSE; run_length = 0; for(var = 0; var < cube.num_binary_vars; var++) if (paired[var]) if (run) run_length += cube.part_size[var]; else { run = TRUE; first_run = cube.first_part[var]; run_length = cube.part_size[var]; } else if (run) { A = sf_delcol(A, first_run-offset, run_length); run = FALSE; offset += run_length; } if (run) A = sf_delcol(A, first_run-offset, run_length); return A; } /* find_optimal_pairing -- find which binary variables should be paired to maximally reduce the number of terms This is essentially the technique outlined by T. Sasao in the Trans. on Comp., Oct 1984. We estimate the cost of pairing each pair individually using 1 of 4 strategies: (1) algebraic division of F by the pair (exactly T. Sasao technique); (2) strong division of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from espresso); (3) full minimization using espresso; (4) exact minimization. These are in order of both increasing accuracy and increasing difficulty (!) Once the n squared pairs have been evaluated, T. Sasao proposes a graph covering of nodes by disjoint edges. For now, I solve this problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n variables when n is even). Note that solving this problem exactly is the same as evaluating the cost function for all possible pairings. n pairs 1, 2 1 3, 4 3 5, 6 15 7, 8 105 9,10 945 11,12 10,395 13,14 135,135 15,16 2,027,025 17,18 34,459,425 19,20 654,729,075 */ void find_optimal_pairing(PLA, strategy) pPLA PLA; int strategy; { int i, j, **cost_array; cost_array = find_pairing_cost(PLA, strategy); if (summary) { printf(" "); for(i = 0; i < cube.num_binary_vars; i++) printf("%3d ", i+1); printf("\n"); for(i = 0; i < cube.num_binary_vars; i++) { printf("%3d ", i+1); for(j = 0; j < cube.num_binary_vars; j++) printf("%3d ", cost_array[i][j]); printf("\n"); } } if (cube.num_binary_vars <= 14) { PLA->pair = pair_best_cost(cost_array); } else { (void) greedy_best_cost(cost_array, &(PLA->pair)); } printf("# "); print_pair(PLA->pair); for(i = 0; i < cube.num_binary_vars; i++) FREE(cost_array[i]); FREE(cost_array); set_pair(PLA); EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F); } int **find_pairing_cost(PLA, strategy) pPLA PLA; int strategy; { int var1, var2, **cost_array; int i, j; int xnum_binary_vars = 0, xnum_vars = 0, *xpart_size = NULL, cost = 0; // Suppress "might be used uninitialized" pcover T; pcover Fsave = NULL, Dsave = NULL, Rsave = NULL; // Suppress "might be used uninitialized" pset mask; /* char *s;*/ /* data is returned in the cost array */ cost_array = ALLOC(int *, cube.num_binary_vars); for(i = 0; i < cube.num_binary_vars; i++) cost_array[i] = ALLOC(int, cube.num_binary_vars); for(i = 0; i < cube.num_binary_vars; i++) for(j = 0; j < cube.num_binary_vars; j++) cost_array[i][j] = 0; /* Setup the pair structure for pairing variables together */ PLA->pair = pair_new(1); PLA->pair->cnt = 1; for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) { for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) { /* if anything but simple strategy, perform setup */ if (strategy > 0) { /* save the original covers */ Fsave = sf_save(PLA->F); Dsave = sf_save(PLA->D); Rsave = sf_save(PLA->R); /* save the original cube structure */ xnum_binary_vars = cube.num_binary_vars; xnum_vars = cube.num_vars; xpart_size = ALLOC(int, cube.num_vars); for(i = 0; i < cube.num_vars; i++) xpart_size[i] = cube.part_size[i]; /* pair two variables together */ PLA->pair->var1[0] = var1 + 1; PLA->pair->var2[0] = var2 + 1; set_pair1(PLA, /* adjust_labels */ FALSE); } /* decide how to best estimate worth of this pairing */ switch(strategy) { case 3: /*s = "exact minimization";*/ PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1); cost = Fsave->count - PLA->F->count; break; case 2: /*s = "full minimization";*/ PLA->F = espresso(PLA->F, PLA->D, PLA->R); cost = Fsave->count - PLA->F->count; break; case 1: /*s = "strong division";*/ PLA->F = reduce(PLA->F, PLA->D); PLA->F = expand(PLA->F, PLA->R, FALSE); PLA->F = irredundant(PLA->F, PLA->D); cost = Fsave->count - PLA->F->count; break; case 0: /*s = "weak division";*/ mask = new_cube(); set_or(mask, cube.var_mask[var1], cube.var_mask[var2]); T = dist_merge(sf_save(PLA->F), mask); cost = PLA->F->count - T->count; sf_free(T); set_free(mask); } cost_array[var1][var2] = cost; if (strategy > 0) { /* restore the original cube structure -- free the new ones */ setdown_cube(); FREE(cube.part_size); cube.num_binary_vars = xnum_binary_vars; cube.num_vars = xnum_vars; cube.part_size = xpart_size; cube_setup(); /* restore the original cover(s) -- free the new ones */ sf_free(PLA->F); sf_free(PLA->D); sf_free(PLA->R); PLA->F = Fsave; PLA->D = Dsave; PLA->R = Rsave; } } } pair_free(PLA->pair); PLA->pair = NULL; return cost_array; } static int best_cost; static int **cost_array; static ppair best_pair; static pset best_phase; static pPLA global_PLA; static pcover best_F, best_D, best_R; static int pair_minim_strategy; void print_pair(pair) ppair pair; { int i; printf("pair is"); for(i = 0; i < pair->cnt; i++) printf (" (%d %d)", pair->var1[i], pair->var2[i]); printf("\n"); } int greedy_best_cost(cost_array_local, pair_p) int **cost_array_local; ppair *pair_p; { int i, j; int besti = 0, bestj = 0; int maxcost, total_cost; pset cand; ppair pair; pair = pair_new(cube.num_binary_vars); cand = set_full(cube.num_binary_vars); total_cost = 0; while (set_ord(cand) >= 2) { maxcost = -1; for(i = 0; i < cube.num_binary_vars; i++) { if (is_in_set(cand, i)) { for(j = i+1; j < cube.num_binary_vars; j++) { if (is_in_set(cand, j)) { if (cost_array_local[i][j] > maxcost) { maxcost = cost_array_local[i][j]; besti = i; bestj = j; } } } } } pair->var1[pair->cnt] = besti+1; pair->var2[pair->cnt] = bestj+1; pair->cnt++; set_remove(cand, besti); set_remove(cand, bestj); total_cost += maxcost; } set_free(cand); *pair_p = pair; return total_cost; } ppair pair_best_cost(cost_array_local) int **cost_array_local; { ppair pair; pset candidate; best_cost = -1; best_pair = NULL; cost_array = cost_array_local; pair = pair_new(cube.num_binary_vars); candidate = set_full(cube.num_binary_vars); generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost); pair_free(pair); set_free(candidate); return best_pair; } void find_best_cost(pair) register ppair pair; { register int i, cost; cost = 0; for(i = 0; i < pair->cnt; i++) cost += cost_array[pair->var1[i]-1][pair->var2[i]-1]; if (cost > best_cost) { best_cost = cost; best_pair = pair_save(pair, pair->cnt); } if ((debug & MINCOV) && trace) { printf("cost is %d ", cost); print_pair(pair); } } /* pair_all: brute-force approach to try all possible pairings pair_strategy is: 2) for espresso 3) for minimize_exact 4) for phase assignment */ void pair_all(PLA, pair_strategy) pPLA PLA; int pair_strategy; { ppair pair; pset candidate; global_PLA = PLA; pair_minim_strategy = pair_strategy; best_cost = PLA->F->count + 1; best_pair = NULL; best_phase = NULL; best_F = best_D = best_R = NULL; pair = pair_new(cube.num_binary_vars); candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars); generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair); pair_free(pair); set_free(candidate); PLA->pair = best_pair; PLA->phase = best_phase; /* not really necessary if (phase != NULL) (void) set_phase(PLA->phase); */ set_pair(PLA); printf("# "); print_pair(PLA->pair); sf_free(PLA->F); sf_free(PLA->D); sf_free(PLA->R); PLA->F = best_F; PLA->D = best_D; PLA->R = best_R; } /* * minimize_pair -- called as each pair is generated */ void minimize_pair(pair) ppair pair; { pcover Fsave, Dsave, Rsave; int i, xnum_binary_vars, xnum_vars, *xpart_size; /* save the original covers */ Fsave = sf_save(global_PLA->F); Dsave = sf_save(global_PLA->D); Rsave = sf_save(global_PLA->R); /* save the original cube structure */ xnum_binary_vars = cube.num_binary_vars; xnum_vars = cube.num_vars; xpart_size = ALLOC(int, cube.num_vars); for(i = 0; i < cube.num_vars; i++) xpart_size[i] = cube.part_size[i]; /* setup the paired variables */ global_PLA->pair = pair; set_pair1(global_PLA, /* adjust_labels */ FALSE); /* call the minimizer */ if (summary) print_pair(pair); switch(pair_minim_strategy) { case 2: EXEC_S(phase_assignment(global_PLA,0), "OPO ", global_PLA->F); if (summary) printf("# phase is %s\n", pc1(global_PLA->phase)); break; case 1: EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D, global_PLA->R, 1), "EXACT ", global_PLA->F); break; case 0: EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D, global_PLA->R), "ESPRESSO ", global_PLA->F); break; default: break; } /* see if we have a new best solution */ if (global_PLA->F->count < best_cost) { best_cost = global_PLA->F->count; best_pair = pair_save(pair, pair->cnt); best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL; if (best_F != NULL) sf_free(best_F); if (best_D != NULL) sf_free(best_D); if (best_R != NULL) sf_free(best_R); best_F = sf_save(global_PLA->F); best_D = sf_save(global_PLA->D); best_R = sf_save(global_PLA->R); } /* restore the original cube structure -- free the new ones */ setdown_cube(); FREE(cube.part_size); cube.num_binary_vars = xnum_binary_vars; cube.num_vars = xnum_vars; cube.part_size = xpart_size; cube_setup(); /* restore the original cover(s) -- free the new ones */ sf_free(global_PLA->F); sf_free(global_PLA->D); sf_free(global_PLA->R); global_PLA->F = Fsave; global_PLA->D = Dsave; global_PLA->R = Rsave; global_PLA->pair = NULL; global_PLA->phase = NULL; } void generate_all_pairs(pair, n, candidate, action) ppair pair; int n; pset candidate; int (*action)(); { int i, j; pset recur_candidate; ppair recur_pair; if (set_ord(candidate) < 2) { (*action)(pair); return; } recur_pair = pair_save(pair, n); recur_candidate = set_save(candidate); /* Find first variable still in the candidate set */ for(i = 0; i < n; i++) if (is_in_set(candidate, i)) break; /* Try all pairs of i with other variables */ for(j = i+1; j < n; j++) if (is_in_set(candidate, j)) { /* pair (i j) -- remove from candidate set for future pairings */ set_remove(recur_candidate, i); set_remove(recur_candidate, j); /* add to the pair array */ recur_pair->var1[recur_pair->cnt] = i+1; recur_pair->var2[recur_pair->cnt] = j+1; recur_pair->cnt++; /* recur looking for the end ... */ generate_all_pairs(recur_pair, n, recur_candidate, action); /* now break this pair, and restore candidate set */ recur_pair->cnt--; set_insert(recur_candidate, i); set_insert(recur_candidate, j); } /* if odd, generate all pairs which do NOT include i */ if ((set_ord(candidate) % 2) == 1) { set_remove(recur_candidate, i); generate_all_pairs(recur_pair, n, recur_candidate, action); } pair_free(recur_pair); set_free(recur_candidate); } ppair pair_new(n) register int n; { register ppair pair1; pair1 = ALLOC(pair_t, 1); pair1->cnt = 0; pair1->var1 = ALLOC(int, n); pair1->var2 = ALLOC(int, n); return pair1; } ppair pair_save(pair, n) register ppair pair; register int n; { register int k; register ppair pair1; pair1 = pair_new(n); pair1->cnt = pair->cnt; for(k = 0; k < pair->cnt; k++) { pair1->var1[k] = pair->var1[k]; pair1->var2[k] = pair->var2[k]; } return pair1; } void pair_free(pair) register ppair pair; { FREE(pair->var1); FREE(pair->var2); FREE(pair); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/part.c000066400000000000000000000043241300674244400237470ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "mincov_int.h" ABC_NAMESPACE_IMPL_START static int visit_col(); static void copy_row(A, prow) register sm_matrix *A; register sm_row *prow; { register sm_element *p; for(p = prow->first_col; p != 0; p = p->next_col) { (void) sm_insert(A, p->row_num, p->col_num); } } static int visit_row(A, prow, rows_visited, cols_visited) sm_matrix *A; sm_row *prow; int *rows_visited; int *cols_visited; { sm_element *p; sm_col *pcol; if (! prow->flag) { prow->flag = 1; (*rows_visited)++; if (*rows_visited == A->nrows) { return 1; } for(p = prow->first_col; p != 0; p = p->next_col) { pcol = sm_get_col(A, p->col_num); if (! pcol->flag) { if (visit_col(A, pcol, rows_visited, cols_visited)) { return 1; } } } } return 0; } static int visit_col(A, pcol, rows_visited, cols_visited) sm_matrix *A; sm_col *pcol; int *rows_visited; int *cols_visited; { sm_element *p; sm_row *prow; if (! pcol->flag) { pcol->flag = 1; (*cols_visited)++; if (*cols_visited == A->ncols) { return 1; } for(p = pcol->first_row; p != 0; p = p->next_row) { prow = sm_get_row(A, p->row_num); if (! prow->flag) { if (visit_row(A, prow, rows_visited, cols_visited)) { return 1; } } } } return 0; } int sm_block_partition(A, L, R) sm_matrix *A; sm_matrix **L, **R; { int cols_visited, rows_visited; register sm_row *prow; register sm_col *pcol; /* Avoid the trivial case */ if (A->nrows == 0) { return 0; } /* Reset the visited flags for each row and column */ for(prow = A->first_row; prow != 0; prow = prow->next_row) { prow->flag = 0; } for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { pcol->flag = 0; } cols_visited = rows_visited = 0; if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) { /* we found all of the rows */ return 0; } else { *L = sm_alloc(); *R = sm_alloc(); for(prow = A->first_row; prow != 0; prow = prow->next_row) { if (prow->flag) { copy_row(*L, prow); } else { copy_row(*R, prow); } } return 1; } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/primes.c000066400000000000000000000071351300674244400243030ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START static bool primes_consensus_special_cases(); static pcover primes_consensus_merge(); static pcover and_with_cofactor(); /* primes_consensus -- generate primes using consensus */ pcover primes_consensus(T) pcube *T; /* T will be disposed of */ { register pcube cl, cr; register int best; pcover Tnew, Tl, Tr; if (primes_consensus_special_cases(T, &Tnew) == MAYBE) { cl = new_cube(); cr = new_cube(); best = binate_split_select(T, cl, cr, COMPL); Tl = primes_consensus(scofactor(T, cl, best)); Tr = primes_consensus(scofactor(T, cr, best)); Tnew = primes_consensus_merge(Tl, Tr, cl, cr); free_cube(cl); free_cube(cr); free_cubelist(T); } return Tnew; } static bool primes_consensus_special_cases(T, Tnew) pcube *T; /* will be disposed if answer is determined */ pcover *Tnew; /* returned only if answer determined */ { register pcube *T1, p, ceil, cof=T[0]; pcube last; pcover A; /* Check for no cubes in the cover */ if (T[2] == NULL) { *Tnew = new_cover(0); free_cubelist(T); return TRUE; } /* Check for only a single cube in the cover */ if (T[3] == NULL) { *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2])); free_cubelist(T); return TRUE; } /* Check for a row of all 1's (implies function is a tautology) */ for(T1 = T+2; (p = *T1++) != NULL; ) { if (full_row(p, cof)) { *Tnew = sf_addset(new_cover(1), cube.fullset); free_cubelist(T); return TRUE; } } /* Check for a column of all 0's which can be factored out */ ceil = set_save(cof); for(T1 = T+2; (p = *T1++) != NULL; ) { INLINEset_or(ceil, ceil, p); } if (! setp_equal(ceil, cube.fullset)) { p = new_cube(); (void) set_diff(p, cube.fullset, ceil); (void) set_or(cof, cof, p); free_cube(p); A = primes_consensus(T); foreach_set(A, last, p) { INLINEset_and(p, p, ceil); } *Tnew = A; set_free(ceil); return TRUE; } set_free(ceil); /* Collect column counts, determine unate variables, etc. */ massive_count(T); /* If single active variable not factored out above, then tautology ! */ if (cdata.vars_active == 1) { *Tnew = sf_addset(new_cover(1), cube.fullset); free_cubelist(T); return TRUE; /* Check for unate cover */ } else if (cdata.vars_unate == cdata.vars_active) { A = cubeunlist(T); *Tnew = sf_contain(A); free_cubelist(T); return TRUE; /* Not much we can do about it */ } else { return MAYBE; } } static pcover primes_consensus_merge(Tl, Tr, cl, cr) pcover Tl, Tr; pcube cl, cr; { register pcube pl, pr, lastl, lastr, pt; pcover T, Tsave; Tl = and_with_cofactor(Tl, cl); Tr = and_with_cofactor(Tr, cr); T = sf_new(500, Tl->sf_size); pt = T->data; Tsave = sf_contain(sf_join(Tl, Tr)); foreach_set(Tl, lastl, pl) { foreach_set(Tr, lastr, pr) { if (cdist01(pl, pr) == 1) { consensus(pt, pl, pr); if (++T->count >= T->capacity) { Tsave = sf_union(Tsave, sf_contain(T)); T = sf_new(500, Tl->sf_size); pt = T->data; } else { pt += T->wsize; } } } } free_cover(Tl); free_cover(Tr); Tsave = sf_union(Tsave, sf_contain(T)); return Tsave; } static pcover and_with_cofactor(A, cof) pset_family A; register pset cof; { register pset last, p; foreach_set(A, last, p) { INLINEset_and(p, p, cof); if (cdist(p, cube.fullset) > 0) { RESET(p, ACTIVE); } else { SET(p, ACTIVE); } } return sf_inactive(A); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/reduce.c000066400000000000000000000161321300674244400242500ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* module: reduce.c purpose: Perform the Espresso-II reduction step Reduction is a technique used to explore larger regions of the optimization space. We replace each cube of F with a smaller cube while still maintaining a cover of the same logic function. */ #include "espresso.h" ABC_NAMESPACE_IMPL_START static bool toggle = TRUE; /* reduce -- replace each cube in F with its reduction The reduction of a cube is the smallest cube contained in the cube which can replace the cube in the original cover without changing the cover. This is equivalent to the super cube of all of the essential points in the cube. This can be computed directly. The problem is that the order in which the cubes are reduced can greatly affect the final result. We alternate between two ordering strategies: (1) Order the cubes in ascending order of distance from the largest cube breaking ties by ordering cubes of equal distance in descending order of size (sort_reduce) (2) Order the cubes in descending order of the inner-product of the cube and the column sums (mini_sort) The real workhorse of this section is the routine SCCC which is used to find the Smallest Cube Containing the Complement of a cover. Reduction as proposed by Espresso-II takes a cube and computes its maximal reduction as the intersection between the cube and the smallest cube containing the complement of (F u D - {c}) cofactored against c. As usual, the unate-recursive paradigm is used to compute SCCC. The SCCC of a unate cover is trivial to compute, and thus we perform Shannon Cofactor expansion attempting to drive the cover to be unate as fast as possible. */ pcover reduce(F, D) INOUT pcover F; IN pcover D; { register pcube last, p, cunder, *FD; /* Order the cubes */ if (use_random_order) F = random_order(F); else { F = toggle ? sort_reduce(F) : mini_sort(F, descend); toggle = ! toggle; } /* Try to reduce each cube */ FD = cube2list(F, D); foreach_set(F, last, p) { cunder = reduce_cube(FD, p); /* reduce the cube */ if (setp_equal(cunder, p)) { /* see if it actually did */ SET(p, ACTIVE); /* cube remains active */ SET(p, PRIME); /* cube remains prime ? */ } else { if (debug & REDUCE) { printf("REDUCE: %s to %s %s\n", pc1(p), pc2(cunder), print_time(ptime())); } set_copy(p, cunder); /* save reduced version */ RESET(p, PRIME); /* cube is no longer prime */ if (setp_empty(cunder)) RESET(p, ACTIVE); /* if null, kill the cube */ else SET(p, ACTIVE); /* cube is active */ } free_cube(cunder); } free_cubelist(FD); /* Delete any cubes of F which reduced to the empty cube */ return sf_inactive(F); } /* reduce_cube -- find the maximal reduction of a cube */ pcube reduce_cube(FD, p) IN pcube *FD, p; { pcube cunder; cunder = sccc(cofactor(FD, p)); return set_and(cunder, cunder, p); } /* sccc -- find Smallest Cube Containing the Complement of a cover */ pcube sccc(T) INOUT pcube *T; /* T will be disposed of */ { pcube r; register pcube cl, cr; register int best; static int sccc_level = 0; if (debug & REDUCE1) { debug_print(T, "SCCC", sccc_level++); } if (sccc_special_cases(T, &r) == MAYBE) { cl = new_cube(); cr = new_cube(); best = binate_split_select(T, cl, cr, REDUCE1); r = sccc_merge(sccc(scofactor(T, cl, best)), sccc(scofactor(T, cr, best)), cl, cr); free_cubelist(T); } if (debug & REDUCE1) printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r)); return r; } pcube sccc_merge(left, right, cl, cr) INOUT register pcube left, right; /* will be disposed of ... */ INOUT register pcube cl, cr; /* will be disposed of ... */ { INLINEset_and(left, left, cl); INLINEset_and(right, right, cr); INLINEset_or(left, left, right); free_cube(right); free_cube(cl); free_cube(cr); return left; } /* sccc_cube -- find the smallest cube containing the complement of a cube By DeMorgan's law and the fact that the smallest cube containing a cover is the "or" of the positional cubes, it is simple to see that the SCCC is the universe if the cube has more than two active variables. If there is only a single active variable, then the SCCC is merely the bitwise complement of the cube in that variable. A last special case is no active variables, in which case the SCCC is empty. This is "anded" with the incoming cube result. */ pcube sccc_cube(result, p) register pcube result, p; { register pcube temp=cube.temp[0], mask; int var; if ((var = cactive(p)) >= 0) { mask = cube.var_mask[var]; INLINEset_xor(temp, p, mask); INLINEset_and(result, result, temp); } return result; } /* * sccc_special_cases -- check the special cases for sccc */ bool sccc_special_cases(T, result) INOUT pcube *T; /* will be disposed if answer is determined */ OUT pcube *result; /* returned only if answer determined */ { register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0]; pcube *A, *B; /* empty cover => complement is universe => SCCC is universe */ if (T[2] == NULL) { *result = set_save(cube.fullset); free_cubelist(T); return TRUE; } /* row of 1's => complement is empty => SCCC is empty */ for(T1 = T+2; (p = *T1++) != NULL; ) { if (full_row(p, cof)) { *result = new_cube(); free_cubelist(T); return TRUE; } } /* Collect column counts, determine unate variables, etc. */ massive_count(T); /* If cover is unate (or single cube), apply simple rules to find SCCCU */ if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) { *result = set_save(cube.fullset); for(T1 = T+2; (p = *T1++) != NULL; ) { (void) sccc_cube(*result, set_or(temp, p, cof)); } free_cubelist(T); return TRUE; } /* Check for column of 0's (which can be easily factored( */ ceil = set_save(cof); for(T1 = T+2; (p = *T1++) != NULL; ) { INLINEset_or(ceil, ceil, p); } if (! setp_equal(ceil, cube.fullset)) { *result = sccc_cube(set_save(cube.fullset), ceil); if (setp_equal(*result, cube.fullset)) { free_cube(ceil); } else { *result = sccc_merge(sccc(cofactor(T,ceil)), set_save(cube.fullset), ceil, *result); } free_cubelist(T); return TRUE; } free_cube(ceil); /* Single active column at this point => tautology => SCCC is empty */ if (cdata.vars_active == 1) { *result = new_cube(); free_cubelist(T); return TRUE; } /* Check for components */ if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) { if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) { return MAYBE; } else { free_cubelist(T); *result = sccc(A); ceil = sccc(B); (void) set_and(*result, *result, ceil); set_free(ceil); return TRUE; } } /* Not much we can do about it */ return MAYBE; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/rows.c000066400000000000000000000133321300674244400237720ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ //#include "port.h" #include "sparse_int.h" ABC_NAMESPACE_IMPL_START /* * allocate a new row vector */ sm_row * sm_row_alloc() { register sm_row *prow; #ifdef FAST_AND_LOOSE if (sm_row_freelist == NIL(sm_row)) { prow = ALLOC(sm_row, 1); } else { prow = sm_row_freelist; sm_row_freelist = prow->next_row; } #else prow = ALLOC(sm_row, 1); #endif prow->row_num = 0; prow->length = 0; prow->first_col = prow->last_col = NIL(sm_element); prow->next_row = prow->prev_row = NIL(sm_row); prow->flag = 0; prow->user_word = NIL(char); /* for our user ... */ return prow; } /* * free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows; * however, freeing a column must still walk down the column discarding * the elements one-by-one; that is the only use for the extra '-DCOLS' * compile flag ... */ void sm_row_free(prow) register sm_row *prow; { #if defined(FAST_AND_LOOSE) && ! defined(COLS) if (prow->first_col != NIL(sm_element)) { /* Add the linked list of row items to the free list */ prow->last_col->next_col = sm_element_freelist; sm_element_freelist = prow->first_col; } /* Add the row to the free list of rows */ prow->next_row = sm_row_freelist; sm_row_freelist = prow; #else register sm_element *p, *pnext; for(p = prow->first_col; p != 0; p = pnext) { pnext = p->next_col; sm_element_free(p); } FREE(prow); #endif } /* * duplicate an existing row */ sm_row * sm_row_dup(prow) register sm_row *prow; { register sm_row *pnew; register sm_element *p; pnew = sm_row_alloc(); for(p = prow->first_col; p != 0; p = p->next_col) { (void) sm_row_insert(pnew, p->col_num); } return pnew; } /* * insert an element into a row vector */ sm_element * sm_row_insert(prow, col) register sm_row *prow; register int col; { register sm_element *test, *element; /* get a new item, save its address */ sm_element_alloc(element); test = element; sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length, next_col, prev_col, col_num, col, test); /* if item was not used, free it */ if (element != test) { sm_element_free(element); } /* either way, return the current new value */ return test; } /* * remove an element from a row vector */ void sm_row_remove(prow, col) register sm_row *prow; register int col; { register sm_element *p; for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col) ; if (p != 0 && p->col_num == col) { dll_unlink(p, prow->first_col, prow->last_col, next_col, prev_col, prow->length); sm_element_free(p); } } /* * find an element (if it is in the row vector) */ sm_element * sm_row_find(prow, col) sm_row *prow; int col; { register sm_element *p; for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col) ; if (p != 0 && p->col_num == col) { return p; } else { return NIL(sm_element); } } /* * return 1 if row p2 contains row p1; 0 otherwise */ int sm_row_contains(p1, p2) sm_row *p1, *p2; { register sm_element *q1, *q2; q1 = p1->first_col; q2 = p2->first_col; while (q1 != 0) { if (q2 == 0 || q1->col_num < q2->col_num) { return 0; } else if (q1->col_num == q2->col_num) { q1 = q1->next_col; q2 = q2->next_col; } else { q2 = q2->next_col; } } return 1; } /* * return 1 if row p1 and row p2 share an element in common */ int sm_row_intersects(p1, p2) sm_row *p1, *p2; { register sm_element *q1, *q2; q1 = p1->first_col; q2 = p2->first_col; if (q1 == 0 || q2 == 0) return 0; for(;;) { if (q1->col_num < q2->col_num) { if ((q1 = q1->next_col) == 0) { return 0; } } else if (q1->col_num > q2->col_num) { if ((q2 = q2->next_col) == 0) { return 0; } } else { return 1; } } } /* * compare two rows, lexical ordering */ int sm_row_compare(p1, p2) sm_row *p1, *p2; { register sm_element *q1, *q2; q1 = p1->first_col; q2 = p2->first_col; while(q1 != 0 && q2 != 0) { if (q1->col_num != q2->col_num) { return q1->col_num - q2->col_num; } q1 = q1->next_col; q2 = q2->next_col; } if (q1 != 0) { return 1; } else if (q2 != 0) { return -1; } else { return 0; } } /* * return the intersection */ sm_row * sm_row_and(p1, p2) sm_row *p1, *p2; { register sm_element *q1, *q2; register sm_row *result; result = sm_row_alloc(); q1 = p1->first_col; q2 = p2->first_col; if (q1 == 0 || q2 == 0) return result; for(;;) { if (q1->col_num < q2->col_num) { if ((q1 = q1->next_col) == 0) { return result; } } else if (q1->col_num > q2->col_num) { if ((q2 = q2->next_col) == 0) { return result; } } else { (void) sm_row_insert(result, q1->col_num); if ((q1 = q1->next_col) == 0) { return result; } if ((q2 = q2->next_col) == 0) { return result; } } } } int sm_row_hash(prow, modulus) sm_row *prow; int modulus; { register int sum; register sm_element *p; sum = 0; for(p = prow->first_col; p != 0; p = p->next_col) { sum = (sum*17 + p->col_num) % modulus; } return sum; } /* * remove an element from a row vector (given a pointer to the element) */ void sm_row_remove_element(prow, p) register sm_row *prow; register sm_element *p; { dll_unlink(p, prow->first_col, prow->last_col, next_col, prev_col, prow->length); sm_element_free(p); } void sm_row_print(fp, prow) FILE *fp; sm_row *prow; { sm_element *p; for(p = prow->first_col; p != 0; p = p->next_col) { (void) fprintf(fp, " %d", p->col_num); } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/set.c000066400000000000000000000425251300674244400236010ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* * set.c -- routines for maniuplating sets and set families */ /* LINTLIBRARY */ #include "espresso.h" ABC_NAMESPACE_IMPL_START static pset_family set_family_garbage = NULL; static void intcpy(d, s, n) register unsigned int *d, *s; register long n; { register int i; for(i = 0; i < n; i++) { *d++ = *s++; } } /* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */ int bit_index(a) register unsigned int a; { register int i; if (a == 0) return -1; for(i = 0; (a & 1) == 0; a >>= 1, i++) ; return i; } /* set_ord -- count number of elements in a set */ int set_ord(a) register pset a; { register int i, sum = 0; register unsigned int val; for(i = LOOP(a); i > 0; i--) if ((val = a[i]) != 0) sum += count_ones(val); return sum; } /* set_dist -- distance between two sets (# elements in common) */ int set_dist(a, b) register pset a, b; { register int i, sum = 0; register unsigned int val; for(i = LOOP(a); i > 0; i--) if ((val = a[i] & b[i]) != 0) sum += count_ones(val); return sum; } /* set_clear -- make "r" the empty set of "size" elements */ pset set_clear(r, size) register pset r; int size; { register int i = LOOPINIT(size); *r = i; do r[i] = 0; while (--i > 0); return r; } /* set_fill -- make "r" the universal set of "size" elements */ pset set_fill(r, size) register pset r; register int size; { register int i = LOOPINIT(size); *r = i; r[i] = ~ (unsigned) 0; r[i] >>= i * BPI - size; while (--i > 0) r[i] = ~ (unsigned) 0; return r; } /* set_copy -- copy set a into set r */ pset set_copy(r, a) register pset r, a; { register int i = LOOPCOPY(a); do r[i] = a[i]; while (--i >= 0); return r; } /* set_and -- compute intersection of sets "a" and "b" */ pset set_and(r, a, b) register pset r, a, b; { register int i = LOOP(a); PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0); return r; } /* set_or -- compute union of sets "a" and "b" */ pset set_or(r, a, b) register pset r, a, b; { register int i = LOOP(a); PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0); return r; } /* set_diff -- compute difference of sets "a" and "b" */ pset set_diff(r, a, b) register pset r, a, b; { register int i = LOOP(a); PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0); return r; } /* set_xor -- compute exclusive-or of sets "a" and "b" */ pset set_xor(r, a, b) register pset r, a, b; { register int i = LOOP(a); #ifdef IBM_WATC PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0); #else PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0); #endif return r; } /* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */ pset set_merge(r, a, b, mask) register pset r, a, b, mask; { register int i = LOOP(a); PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0); return r; } /* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */ bool set_andp(r, a, b) register pset r, a, b; { register int i = LOOP(a); register unsigned int x = 0; PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0); return x != 0; } /* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */ bool set_orp(r, a, b) register pset r, a, b; { register int i = LOOP(a); register unsigned int x = 0; PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0); return x != 0; } /* setp_empty -- check if the set "a" is empty */ bool setp_empty(a) register pset a; { register int i = LOOP(a); do if (a[i]) return FALSE; while (--i > 0); return TRUE; } /* setp_full -- check if the set "a" is the full set of "size" elements */ bool setp_full(a, size) register pset a; register int size; { register int i = LOOP(a); register unsigned int test; test = ~ (unsigned) 0; test >>= i * BPI - size; if (a[i] != test) return FALSE; while (--i > 0) if (a[i] != (~(unsigned) 0)) return FALSE; return TRUE; } /* setp_equal -- check if the set "a" equals set "b" */ bool setp_equal(a, b) register pset a, b; { register int i = LOOP(a); do if (a[i] != b[i]) return FALSE; while (--i > 0); return TRUE; } /* setp_disjoint -- check if intersection of "a" and "b" is empty */ bool setp_disjoint(a, b) register pset a, b; { register int i = LOOP(a); do if (a[i] & b[i]) return FALSE; while (--i > 0); return TRUE; } /* setp_implies -- check if "a" implies "b" ("b" contains "a") */ bool setp_implies(a, b) register pset a, b; { register int i = LOOP(a); do if (a[i] & ~b[i]) return FALSE; while (--i > 0); return TRUE; } /* sf_or -- form the "or" of all sets in a set family */ pset sf_or(A) pset_family A; { register pset or, last, p; or = set_new(A->sf_size); foreach_set(A, last, p) INLINEset_or(or, or, p); return or; } /* sf_and -- form the "and" of all sets in a set family */ pset sf_and(A) pset_family A; { register pset and, last, p; and = set_fill(set_new(A->sf_size), A->sf_size); foreach_set(A, last, p) INLINEset_and(and, and, p); return and; } /* sf_active -- make all members of the set family active */ pset_family sf_active(A) pset_family A; { register pset p, last; foreach_set(A, last, p) { SET(p, ACTIVE); } A->active_count = A->count; return A; } /* sf_inactive -- remove all inactive cubes in a set family */ pset_family sf_inactive(A) pset_family A; { register pset p, last, pdest; pdest = A->data; foreach_set(A, last, p) { if (TESTP(p, ACTIVE)) { if (pdest != p) { INLINEset_copy(pdest, p); } pdest += A->wsize; } else { A->count--; } } return A; } /* sf_copy -- copy a set family */ pset_family sf_copy(R, A) pset_family R, A; { R->sf_size = A->sf_size; R->wsize = A->wsize; /*R->capacity = A->count;*/ /*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/ R->count = A->count; R->active_count = A->active_count; intcpy(R->data, A->data, (long) A->wsize * A->count); return R; } /* sf_join -- join A and B into a single set_family */ pset_family sf_join(A, B) pset_family A, B; { pset_family R; long asize = A->count * A->wsize; long bsize = B->count * B->wsize; if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch"); R = sf_new(A->count + B->count, A->sf_size); R->count = A->count + B->count; R->active_count = A->active_count + B->active_count; intcpy(R->data, A->data, asize); intcpy(R->data + asize, B->data, bsize); return R; } /* sf_append -- append the sets of B to the end of A, and dispose of B */ pset_family sf_append(A, B) pset_family A, B; { long asize = A->count * A->wsize; long bsize = B->count * B->wsize; if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch"); A->capacity = A->count + B->count; A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize); intcpy(A->data + asize, B->data, bsize); A->count += B->count; A->active_count += B->active_count; sf_free(B); return A; } /* sf_new -- allocate "num" sets of "size" elements each */ pset_family sf_new(num, size) int num, size; { pset_family A; if (set_family_garbage == NULL) { A = ALLOC(set_family_t, 1); } else { A = set_family_garbage; set_family_garbage = A->next; } A->sf_size = size; A->wsize = SET_SIZE(size); A->capacity = num; A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize); A->count = 0; A->active_count = 0; return A; } /* sf_save -- create a duplicate copy of a set family */ pset_family sf_save(A) register pset_family A; { return sf_copy(sf_new(A->count, A->sf_size), A); } /* sf_free -- free the storage allocated for a set family */ void sf_free(A) pset_family A; { FREE(A->data); A->next = set_family_garbage; set_family_garbage = A; } /* sf_cleanup -- free all of the set families from the garbage list */ void sf_cleanup() { register pset_family p, pnext; for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) { pnext = p->next; FREE(p); } set_family_garbage = (pset_family) NULL; } /* sf_addset -- add a set to the end of a set family */ pset_family sf_addset(A, s) pset_family A; pset s; { register pset p; if (A->count >= A->capacity) { A->capacity = A->capacity + A->capacity/2 + 1; A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize); } p = GETSET(A, A->count++); INLINEset_copy(p, s); return A; } /* sf_delset -- delete a set from a set family */ void sf_delset(A, i) pset_family A; int i; { (void) set_copy(GETSET(A,i), GETSET(A, --A->count));} /* sf_print -- print a set_family as a set (list the element numbers) */ void sf_print(A) pset_family A; { char *ps1(); register pset p; register int i; foreachi_set(A, i, p) printf("A[%d] = %s\n", i, ps1(p)); } /* sf_bm_print -- print a set_family as a bit-matrix */ void sf_bm_print(A) pset_family A; { char *pbv1(); register pset p; register int i; foreachi_set(A, i, p) printf("[%4d] %s\n", i, pbv1(p, A->sf_size)); } /* sf_write -- output a set family in an unintelligable manner */ void sf_write(fp, A) FILE *fp; pset_family A; { register pset p, last; (void) fprintf(fp, "%d %d\n", A->count, A->sf_size); foreach_set(A, last, p) set_write(fp, p); (void) fflush(fp); } /* sf_read -- read a set family written by sf_write */ pset_family sf_read(fp) FILE *fp; { int i, j; register pset p, last; pset_family A; (void) fscanf(fp, "%d %d\n", &i, &j); A = sf_new(i, j); A->count = i; foreach_set(A, last, p) { (void) fscanf(fp, "%x", p); for(j = 1; j <= LOOP(p); j++) (void) fscanf(fp, "%x", p+j); } return A; } /* set_write -- output a set in an unintelligable manner */ void set_write(fp, a) register FILE *fp; register pset a; { register int n = LOOP(a), j; for(j = 0; j <= n; j++) { (void) fprintf(fp, "%x ", a[j]); if ((j+1) % 8 == 0 && j != n) (void) fprintf(fp, "\n\t"); } (void) fprintf(fp, "\n"); } /* sf_bm_read -- read a set family written by sf_bm_print (almost) */ pset_family sf_bm_read(fp) FILE *fp; { int i, j, rows, cols; register pset pdest; pset_family A; (void) fscanf(fp, "%d %d\n", &rows, &cols); A = sf_new(rows, cols); for(i = 0; i < rows; i++) { pdest = GETSET(A, A->count++); (void) set_clear(pdest, A->sf_size); for(j = 0; j < cols; j++) { switch(getc(fp)) { case '0': break; case '1': set_insert(pdest, j); break; default: fatal("Error reading set family"); } } if (getc(fp) != '\n') { fatal("Error reading set family (at end of line)"); } } return A; } /* ps1 -- convert a set into a printable string */ #define largest_string 120 static char s1[largest_string]; char *ps1(a) register pset a; { register int i, num, l, len = 0, n = NELEM(a); char temp[20]; bool first = TRUE; s1[len++] = '['; for(i = 0; i < n; i++) if (is_in_set(a,i)) { if (! first) s1[len++] = ','; first = FALSE; num = i; /* Generate digits (reverse order) */ l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0); /* Copy them back in correct order */ do s1[len++] = temp[--l]; while (l > 0); if (len > largest_string-15) { s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.'; break; } } s1[len++] = ']'; s1[len++] = '\0'; return s1; } /* pbv1 -- print bit-vector */ char *pbv1(s, n) pset s; int n; { register int i; for(i = 0; i < n; i++) s1[i] = is_in_set(s,i) ? '1' : '0'; s1[n] = '\0'; return s1; } /* set_adjcnt -- adjust the counts for a set by "weight" */ void set_adjcnt(a, count, weight) register pset a; register int *count, weight; { register int i, base; register unsigned int val; for(i = LOOP(a); i > 0; ) { for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) { if (val & 1) { count[base] += weight; } } } } /* sf_count -- perform a column sum over a set family */ int *sf_count(A) pset_family A; { register pset p, last; register int i, base, *count; register unsigned int val; count = ALLOC(int, A->sf_size); for(i = A->sf_size - 1; i >= 0; i--) { count[i] = 0; } foreach_set(A, last, p) { for(i = LOOP(p); i > 0; ) { for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) { if (val & 1) { count[base]++; } } } } return count; } /* sf_count_restricted -- perform a column sum over a set family, restricting * to only the columns which are in r; also, the columns are weighted by the * number of elements which are in each row */ int *sf_count_restricted(A, r) pset_family A; register pset r; { register pset p; register int i, base, *count; register unsigned int val; int weight; pset last; count = ALLOC(int, A->sf_size); for(i = A->sf_size - 1; i >= 0; i--) { count[i] = 0; } /* Loop for each set */ foreach_set(A, last, p) { weight = 1024 / (set_ord(p) - 1); for(i = LOOP(p); i > 0; ) { for(val=p[i]&r[i], base= --i<>= 1) { if (val & 1) { count[base] += weight; } } } } return count; } /* * sf_delc -- delete columns first ... last of A */ pset_family sf_delc(A, first, last) pset_family A; int first, last; { return sf_delcol(A, first, last-first + 1); } /* * sf_addcol -- add columns to a set family; includes a quick check to see * if there is already enough room (and hence, can avoid copying) */ pset_family sf_addcol(A, firstcol, n) pset_family A; int firstcol, n; { int maxsize; /* Check if adding columns at the end ... */ if (firstcol == A->sf_size) { /* If so, check if there is already enough room */ maxsize = BPI * LOOPINIT(A->sf_size); if ((A->sf_size + n) <= maxsize) { A->sf_size += n; return A; } } return sf_delcol(A, firstcol, -n); } /* * sf_delcol -- add/delete columns to/from a set family * * if n > 0 then n columns starting from firstcol are deleted if n < 0 * then n blank columns are inserted starting at firstcol * (i.e., the first new column number is firstcol) * * This is done by copying columns in the array which is a relatively * slow operation. */ pset_family sf_delcol(A, firstcol, n) pset_family A; register int firstcol, n; { register pset p, last, pdest; register int i; pset_family B; B = sf_new(A->count, A->sf_size - n); foreach_set(A, last, p) { pdest = GETSET(B, B->count++); INLINEset_clear(pdest, B->sf_size); for(i = 0; i < firstcol; i++) if (is_in_set(p, i)) set_insert(pdest, i); for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++) if (is_in_set(p, i)) set_insert(pdest, i - n); } sf_free(A); return B; } /* * sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst" */ pset_family sf_copy_col(dst, dstcol, src, srccol) pset_family dst, src; int dstcol, srccol; { register pset last, p, pdest; register int word_test, word_set; unsigned int bit_set, bit_test; /* CHEAT! form these constants outside the loop */ word_test = WHICH_WORD(srccol); bit_test = 1 << WHICH_BIT(srccol); word_set = WHICH_WORD(dstcol); bit_set = 1 << WHICH_BIT(dstcol); pdest = dst->data; foreach_set(src, last, p) { if ((p[word_test] & bit_test) != 0) pdest[word_set] |= bit_set; /* * equivalent code for this is ... * if (is_in_set(p, srccol)) set_insert(pdest, destcol); */ pdest += dst->wsize; } return dst; } /* * sf_compress -- delete columns from a matrix */ pset_family sf_compress(A, c) pset_family A; /* will be freed */ register pset c; { register pset p; register int i, bcol; pset_family B; /* create a clean set family for the result */ B = sf_new(A->count, set_ord(c)); for(i = 0; i < A->count; i++) { p = GETSET(B, B->count++); INLINEset_clear(p, B->sf_size); } /* copy each column of A which has a 1 in c */ bcol = 0; for(i = 0; i < A->sf_size; i++) { if (is_in_set(c, i)) { (void) sf_copy_col(B, bcol++, A, i); } } sf_free(A); return B; } /* * sf_transpose -- transpose a bit matrix * * There are trickier ways of doing this, but this works. */ pset_family sf_transpose(A) pset_family A; { pset_family B; register pset p; register int i, j; B = sf_new(A->sf_size, A->count); B->count = A->sf_size; foreachi_set(B, i, p) { INLINEset_clear(p, B->sf_size); } foreachi_set(A, i, p) { for(j = 0; j < A->sf_size; j++) { if (is_in_set(p, j)) { set_insert(GETSET(B, j), i); } } } sf_free(A); return B; } /* * sf_permute -- permute the columns of a set_family * * permute is an array of integers containing column numbers of A which * are to be retained. */ pset_family sf_permute(A, permute, npermute) pset_family A; register int *permute, npermute; { pset_family B; register pset p, last, pdest; register int j; B = sf_new(A->count, npermute); B->count = A->count; foreach_set(B, last, p) INLINEset_clear(p, npermute); pdest = B->data; foreach_set(A, last, p) { for(j = 0; j < npermute; j++) if (is_in_set(p, permute[j])) set_insert(pdest, j); pdest += B->wsize; } sf_free(A); return B; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/setc.c000066400000000000000000000301031300674244400237310ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* setc.c -- massive bit-hacking for performing special "cube"-type operations on a set The basic trick used for binary valued variables is the following: If a[w] and b[w] contain a full word of binary variables, then: 1) to get the full word of their intersection, we use x = a[w] & b[w]; 2) to see if the intersection is null in any variables, we examine x = ~(x | x >> 1) & DISJOINT; this will have a single 1 in each binary variable for which the intersection is null. In particular, if this is zero, then there are no disjoint variables; or, if this is nonzero, then there is at least one disjoint variable. A "count_ones" over x will tell in how many variables they have an null intersection. 3) to get a mask which selects the disjoint variables, we use (x | x << 1) this provides a selector which can be used to see where they have an null intersection cdist return distance between two cubes cdist0 return true if two cubes are distance 0 apart cdist01 return distance, or 2 if distance exceeds 1 consensus compute consensus of two cubes distance 1 apart force_lower expand hack (for now), related to consensus */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* see if the cube has a full row of 1's (with respect to cof) */ bool full_row(p, cof) IN register pcube p, cof; { register int i = LOOP(p); do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0); return TRUE; } /* cdist0 -- return TRUE if a and b are distance 0 apart */ bool cdist0(a, b) register pcube a, b; { { /* Check binary variables */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] & b[last]; if (~(x | x >> 1) & cube.inmask) return FALSE; /* disjoint in some variable */ /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] & b[w]; if (~(x | x >> 1) & DISJOINT) return FALSE; /* disjoint in some variable */ } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (a[w] & b[w] & mask[w]) goto nextvar; return FALSE; /* disjoint in this variable */ nextvar: ; } } return TRUE; } /* cdist01 -- return the "distance" between two cubes (defined as the number of null variables in their intersection). If the distance exceeds 1, the value 2 is returned. */ int cdist01(a, b) register pset a, b; { int dist = 0; { /* Check binary variables */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] & b[last]; if ((x = ~ (x | x >> 1) & cube.inmask)) if ((dist = count_ones(x)) > 1) return 2; /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] & b[w]; if ((x = ~ (x | x >> 1) & DISJOINT)) if (dist == 1 || (dist += count_ones(x)) > 1) return 2; } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (a[w] & b[w] & mask[w]) goto nextvar; if (++dist > 1) return 2; nextvar: ; } } return dist; } /* cdist -- return the "distance" between two cubes (defined as the number of null variables in their intersection). */ int cdist(a, b) register pset a, b; { int dist = 0; { /* Check binary variables */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] & b[last]; if ((x = ~ (x | x >> 1) & cube.inmask)) dist = count_ones(x); /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] & b[w]; if ((x = ~ (x | x >> 1) & DISJOINT)) dist += count_ones(x); } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (a[w] & b[w] & mask[w]) goto nextvar; dist++; nextvar: ; } } return dist; } /* force_lower -- Determine which variables of a do not intersect b. */ pset force_lower(xlower, a, b) INOUT pset xlower; IN register pset a, b; { { /* Check binary variables (if any) */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] & b[last]; if ((x = ~(x | x >> 1) & cube.inmask)) xlower[last] |= (x | (x << 1)) & a[last]; /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] & b[w]; if ((x = ~(x | x >> 1) & DISJOINT)) xlower[w] |= (x | (x << 1)) & a[w]; } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (a[w] & b[w] & mask[w]) goto nextvar; for(w = cube.first_word[var]; w <= last; w++) xlower[w] |= a[w] & mask[w]; nextvar: ; } } return xlower; } /* consensus -- multiple-valued consensus Although this looks very messy, the idea is to compute for r the "and" of the cubes a and b for each variable, unless the "and" is null in a variable, in which case the "or" of a and b is computed for this variable. Because we don't check how many variables are null in the intersection of a and b, the returned value for r really only represents the consensus when a and b are distance 1 apart. */ void consensus(r, a, b) INOUT pcube r; IN register pcube a, b; { INLINEset_clear(r, cube.size); { /* Check binary variables (if any) */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ r[last] = x = a[last] & b[last]; if ((x = ~(x | x >> 1) & cube.inmask)) r[last] |= (x | (x << 1)) & (a[last] | b[last]); /* Check the full words of binary variables */ for(w = 1; w < last; w++) { r[w] = x = a[w] & b[w]; if ((x = ~(x | x >> 1) & DISJOINT)) r[w] |= (x | (x << 1)) & (a[w] | b[w]); } } } { /* Check the multiple-valued variables */ bool empty; int var; unsigned int x; register int w, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; empty = TRUE; for(w = cube.first_word[var]; w <= last; w++) if ((x = a[w] & b[w] & mask[w])) empty = FALSE, r[w] |= x; if (empty) for(w = cube.first_word[var]; w <= last; w++) r[w] |= mask[w] & (a[w] | b[w]); } } } /* cactive -- return the index of the single active variable in the cube, or return -1 if there are none or more than 2. */ int cactive(a) register pcube a; { int active = -1, dist = 0, bit_index(); { /* Check binary variables */ register int w, last; register unsigned int x; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last]; if ((x = ~ (x & x >> 1) & cube.inmask)) { if ((dist = count_ones(x)) > 1) return -1; /* more than 2 active variables */ active = (last-1)*(BPI/2) + bit_index(x) / 2; } /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w]; if ((x = ~ (x & x >> 1) & DISJOINT)) { if ((dist += count_ones(x)) > 1) return -1; /* more than 2 active variables */ active = (w-1)*(BPI/2) + bit_index(x) / 2; } } } } { /* Check the multiple-valued variables */ register int w, var, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; for(w = cube.first_word[var]; w <= last; w++) if (mask[w] & ~ a[w]) { if (++dist > 1) return -1; active = var; break; } } } return active; } /* ccommon -- return TRUE if a and b are share "active" variables active variables include variables that are empty; */ bool ccommon(a, b, cof) register pcube a, b, cof; { { /* Check binary variables */ int last; register int w; register unsigned int x, y; if ((last = cube.inword) != -1) { /* Check the partial word of binary variables */ x = a[last] | cof[last]; y = b[last] | cof[last]; if (~(x & x>>1) & ~(y & y>>1) & cube.inmask) return TRUE; /* Check the full words of binary variables */ for(w = 1; w < last; w++) { x = a[w] | cof[w]; y = b[w] | cof[w]; if (~(x & x>>1) & ~(y & y>>1) & DISJOINT) return TRUE; } } } { /* Check the multiple-valued variables */ int var; register int w, last; register pcube mask; for(var = cube.num_binary_vars; var < cube.num_vars; var++) { mask = cube.var_mask[var]; last = cube.last_word[var]; /* Check for some part missing from a */ for(w = cube.first_word[var]; w <= last; w++) if (mask[w] & ~a[w] & ~cof[w]) { /* If so, check for some part missing from b */ for(w = cube.first_word[var]; w <= last; w++) if (mask[w] & ~b[w] & ~cof[w]) return TRUE; /* both active */ break; } } } return FALSE; } /* These routines compare two sets (cubes) for the qsort() routine and return: -1 if set a is to precede set b 0 if set a and set b are equal 1 if set a is to follow set b Usually the SIZE field of the set is assumed to contain the size of the set (which will save recomputing the set size during the sort). For distance-1 merging, the global variable cube.temp[0] is a mask which mask's-out the merging variable. */ /* descend -- comparison for descending sort on set size */ int descend(a, b) pset *a, *b; { register pset a1 = *a, b1 = *b; if (SIZE(a1) > SIZE(b1)) return -1; else if (SIZE(a1) < SIZE(b1)) return 1; else { register int i = LOOP(a1); do if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; while (--i > 0); } return 0; } /* ascend -- comparison for ascending sort on set size */ int ascend(a, b) pset *a, *b; { register pset a1 = *a, b1 = *b; if (SIZE(a1) > SIZE(b1)) return 1; else if (SIZE(a1) < SIZE(b1)) return -1; else { register int i = LOOP(a1); do if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1; while (--i > 0); } return 0; } /* lex_order -- comparison for "lexical" ordering of cubes */ int lex_order(a, b) pset *a, *b; { register pset a1 = *a, b1 = *b; register int i = LOOP(a1); do if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; while (--i > 0); return 0; } /* d1_order -- comparison for distance-1 merge routine */ int d1_order(a, b) pset *a, *b; { register pset a1 = *a, b1 = *b, c1 = cube.temp[0]; register int i = LOOP(a1); register unsigned int x1, x2; do if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1; else if (x1 < x2) return 1; while (--i > 0); return 0; } /* desc1 -- comparison (without indirection) for descending sort */ /* also has effect of handling NULL pointers,and a NULL pointer has smallest order */ int desc1(a, b) register pset a, b; { if (a == (pset) NULL) return (b == (pset) NULL) ? 0 : 1; else if (b == (pset) NULL) return -1; if (SIZE(a) > SIZE(b)) return -1; else if (SIZE(a) < SIZE(b)) return 1; else { register int i = LOOP(a); do if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1; while (--i > 0); } return 0; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/sharp.c000066400000000000000000000117531300674244400241220ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* sharp.c -- perform sharp, disjoint sharp, and intersection */ #include "espresso.h" ABC_NAMESPACE_IMPL_START long start_time; /* cv_sharp -- form the sharp product between two covers */ pcover cv_sharp(A, B) pcover A, B; { pcube last, p; pcover T; T = new_cover(0); foreach_set(A, last, p) T = sf_union(T, cb_sharp(p, B)); return T; } /* cb_sharp -- form the sharp product between a cube and a cover */ pcover cb_sharp(c, T) pcube c; pcover T; { if (T->count == 0) { T = sf_addset(new_cover(1), c); } else { start_time = ptime(); T = cb_recur_sharp(c, T, 0, T->count-1, 0); } return T; } /* recursive formulation to provide balanced merging */ pcover cb_recur_sharp(c, T, first, last, level) pcube c; pcover T; int first, last, level; { pcover temp, left, right; int middle; if (first == last) { temp = sharp(c, GETSET(T, first)); } else { middle = (first + last) / 2; left = cb_recur_sharp(c, T, first, middle, level+1); right = cb_recur_sharp(c, T, middle+1, last, level+1); temp = cv_intersect(left, right); if ((debug & SHARP) && level < 4) { printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n", level, temp->count, left->count, right->count, print_time(ptime() - start_time)); (void) fflush(stdout); } free_cover(left); free_cover(right); } return temp; } /* sharp -- form the sharp product between two cubes */ pcover sharp(a, b) pcube a, b; { register int var; register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2]; pcover r = new_cover(cube.num_vars); if (cdist0(a, b)) { set_diff(d, a, b); for(var = 0; var < cube.num_vars; var++) { if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) { set_diff(temp1, a, cube.var_mask[var]); set_or(GETSET(r, r->count++), temp, temp1); } } } else { r = sf_addset(r, a); } return r; } pcover make_disjoint(A) pcover A; { pcover R, new; register pset last, p; R = new_cover(0); foreach_set(A, last, p) { new = cb_dsharp(p, R); R = sf_append(R, new); } return R; } /* cv_dsharp -- disjoint-sharp product between two covers */ pcover cv_dsharp(A, B) pcover A, B; { register pcube last, p; pcover T; T = new_cover(0); foreach_set(A, last, p) { T = sf_union(T, cb_dsharp(p, B)); } return T; } /* cb1_dsharp -- disjoint-sharp product between a cover and a cube */ pcover cb1_dsharp(T, c) pcover T; pcube c; { pcube last, p; pcover R; R = new_cover(T->count); foreach_set(T, last, p) { R = sf_union(R, dsharp(p, c)); } return R; } /* cb_dsharp -- disjoint-sharp product between a cube and a cover */ pcover cb_dsharp(c, T) pcube c; pcover T; { pcube last, p; pcover Y, Y1; if (T->count == 0) { Y = sf_addset(new_cover(1), c); } else { Y = new_cover(T->count); set_copy(GETSET(Y,Y->count++), c); foreach_set(T, last, p) { Y1 = cb1_dsharp(Y, p); free_cover(Y); Y = Y1; } } return Y; } /* dsharp -- form the disjoint-sharp product between two cubes */ pcover dsharp(a, b) pcube a, b; { register pcube mask, diff, and, temp, temp1 = cube.temp[0]; int var; pcover r; r = new_cover(cube.num_vars); if (cdist0(a, b)) { diff = set_diff(new_cube(), a, b); and = set_and(new_cube(), a, b); mask = new_cube(); for(var = 0; var < cube.num_vars; var++) { /* check if position var of "a and not b" is not empty */ if (! setp_disjoint(diff, cube.var_mask[var])) { /* coordinate var equals the difference between a and b */ temp = GETSET(r, r->count++); (void) set_and(temp, diff, cube.var_mask[var]); /* coordinates 0 ... var-1 equal the intersection */ INLINEset_and(temp1, and, mask); INLINEset_or(temp, temp, temp1); /* coordinates var+1 .. cube.num_vars equal a */ set_or(mask, mask, cube.var_mask[var]); INLINEset_diff(temp1, a, mask); INLINEset_or(temp, temp, temp1); } } free_cube(diff); free_cube(and); free_cube(mask); } else { r = sf_addset(r, a); } return r; } /* cv_intersect -- form the intersection of two covers */ #define MAGIC 500 /* save 500 cubes before containment */ pcover cv_intersect(A, B) pcover A, B; { register pcube pi, pj, lasti, lastj, pt; pcover T, Tsave = NULL; /* How large should each temporary result cover be ? */ T = new_cover(MAGIC); pt = T->data; /* Form pairwise intersection of each cube of A with each cube of B */ foreach_set(A, lasti, pi) { foreach_set(B, lastj, pj) { if (cdist0(pi, pj)) { (void) set_and(pt, pi, pj); if (++T->count >= T->capacity) { if (Tsave == NULL) Tsave = sf_contain(T); else Tsave = sf_union(Tsave, sf_contain(T)); T = new_cover(MAGIC); pt = T->data; } else pt += T->wsize; } } } if (Tsave == NULL) Tsave = sf_contain(T); else Tsave = sf_union(Tsave, sf_contain(T)); return Tsave; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/sminterf.c000066400000000000000000000014311300674244400246240ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "espresso.h" ABC_NAMESPACE_IMPL_START pset do_sm_minimum_cover(A) pset_family A; { sm_matrix *M; sm_row *sparse_cover; sm_element *pe; pset cover; register int i, base, rownum; register unsigned val; register pset last, p; M = sm_alloc(); rownum = 0; foreach_set(A, last, p) { foreach_set_element(p, i, val, base) { (void) sm_insert(M, rownum, base); } rownum++; } sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0); sm_free(M); cover = set_new(A->sf_size); sm_foreach_row_element(sparse_cover, pe) { set_insert(cover, pe->col_num); } sm_row_free(sparse_cover); return cover; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/solution.c000066400000000000000000000033501300674244400246530ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #include "mincov_int.h" ABC_NAMESPACE_IMPL_START solution_t * solution_alloc() { solution_t *sol; sol = ALLOC(solution_t, 1); sol->cost = 0; sol->row = sm_row_alloc(); return sol; } void solution_free(sol) solution_t *sol; { sm_row_free(sol->row); FREE(sol); } solution_t * solution_dup(sol) solution_t *sol; { solution_t *new_sol; new_sol = ALLOC(solution_t, 1); new_sol->cost = sol->cost; new_sol->row = sm_row_dup(sol->row); return new_sol; } void solution_add(sol, weight, col) solution_t *sol; int *weight; int col; { (void) sm_row_insert(sol->row, col); sol->cost += WEIGHT(weight, col); } void solution_accept(sol, A, weight, col) solution_t *sol; sm_matrix *A; int *weight; int col; { register sm_element *p, *pnext; sm_col *pcol; solution_add(sol, weight, col); /* delete rows covered by this column */ pcol = sm_get_col(A, col); for(p = pcol->first_row; p != 0; p = pnext) { pnext = p->next_row; /* grab it before it disappears */ sm_delrow(A, p->row_num); } } /* ARGSUSED */ void solution_reject(sol, A, weight, col) solution_t *sol; sm_matrix *A; int *weight; int col; { sm_delcol(A, col); } solution_t * solution_choose_best(best1, best2) solution_t *best1, *best2; { if (best1 != NIL(solution_t)) { if (best2 != NIL(solution_t)) { if (best1->cost <= best2->cost) { solution_free(best2); return best1; } else { solution_free(best1); return best2; } } else { return best1; } } else { if (best2 != NIL(solution_t)) { return best2; } else { return NIL(solution_t); } } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/sparse.c000066400000000000000000000065671300674244400243110ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* module: sparse.c make_sparse is a last-step cleanup to reduce the total number of literals in the cover. This is done by reducing the "sparse" variables (using a modified version of irredundant rather than reduce), followed by expanding the "dense" variables (using modified version of expand). */ #include "espresso.h" ABC_NAMESPACE_IMPL_START pcover make_sparse(F, D, R) pcover F, D, R; { cost_t cost, best_cost; cover_cost(F, &best_cost); do { EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost); if (cost.total == best_cost.total) break; copy_cost(&cost, &best_cost); EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost); if (cost.total == best_cost.total) break; copy_cost(&cost, &best_cost); } while (force_irredundant); return F; } /* mv_reduce -- perform an "optimal" reduction of the variables which we desire to be sparse This could be done using "reduce" and then saving just the desired part of the reduction. Instead, this version uses IRRED to find which cubes of an output are redundant. Note that this gets around the cube-ordering problem. In normal use, it is expected that the cover is irredundant and hence no cubes will be reduced to the empty cube (however, this is checked for and such cubes will be deleted) */ pcover mv_reduce(F, D) pcover F, D; { register int i, var; register pcube p, p1, last; int index; pcover F1, D1; pcube *F_cube_table; /* loop for each multiple-valued variable */ for(var = 0; var < cube.num_vars; var++) { if (cube.sparse[var]) { /* loop for each part of the variable */ for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { /* remember mapping of F1 cubes back to F cubes */ F_cube_table = ALLOC(pcube, F->count); /* 'cofactor' against part #i of variable #var */ F1 = new_cover(F->count); foreach_set(F, last, p) { if (is_in_set(p, i)) { F_cube_table[F1->count] = p; p1 = GETSET(F1, F1->count++); (void) set_diff(p1, p, cube.var_mask[var]); set_insert(p1, i); } } /* 'cofactor' against part #i of variable #var */ /* not really necessary -- just more efficient ? */ D1 = new_cover(D->count); foreach_set(D, last, p) { if (is_in_set(p, i)) { p1 = GETSET(D1, D1->count++); (void) set_diff(p1, p, cube.var_mask[var]); set_insert(p1, i); } } mark_irredundant(F1, D1); /* now remove part i from cubes which are redundant */ index = 0; foreach_set(F1, last, p1) { if (! TESTP(p1, ACTIVE)) { p = F_cube_table[index]; /* don't reduce a variable which is full * (unless it is the output variable) */ if (var == cube.num_vars-1 || ! setp_implies(cube.var_mask[var], p)) { set_remove(p, i); } RESET(p, PRIME); } index++; } free_cover(F1); free_cover(D1); FREE(F_cube_table); } } } /* Check if any cubes disappeared */ (void) sf_active(F); for(var = 0; var < cube.num_vars; var++) { if (cube.sparse[var]) { foreach_active_set(F, last, p) { if (setp_disjoint(p, cube.var_mask[var])) { RESET(p, ACTIVE); F->active_count--; } } } } if (F->count != F->active_count) { F = sf_inactive(F); } return F; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/sparse.h000066400000000000000000000103521300674244400243010ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ #ifndef ABC__misc__espresso__sparse_h #define ABC__misc__espresso__sparse_h ABC_NAMESPACE_HEADER_START /* * sparse.h -- sparse matrix package header file */ typedef struct sm_element_struct sm_element; typedef struct sm_row_struct sm_row; typedef struct sm_col_struct sm_col; typedef struct sm_matrix_struct sm_matrix; /* * sparse matrix element */ struct sm_element_struct { int row_num; /* row number of this element */ int col_num; /* column number of this element */ sm_element *next_row; /* next row in this column */ sm_element *prev_row; /* previous row in this column */ sm_element *next_col; /* next column in this row */ sm_element *prev_col; /* previous column in this row */ char *user_word; /* user-defined word */ }; /* * row header */ struct sm_row_struct { int row_num; /* the row number */ int length; /* number of elements in this row */ int flag; /* user-defined word */ sm_element *first_col; /* first element in this row */ sm_element *last_col; /* last element in this row */ sm_row *next_row; /* next row (in sm_matrix linked list) */ sm_row *prev_row; /* previous row (in sm_matrix linked list) */ char *user_word; /* user-defined word */ }; /* * column header */ struct sm_col_struct { int col_num; /* the column number */ int length; /* number of elements in this column */ int flag; /* user-defined word */ sm_element *first_row; /* first element in this column */ sm_element *last_row; /* last element in this column */ sm_col *next_col; /* next column (in sm_matrix linked list) */ sm_col *prev_col; /* prev column (in sm_matrix linked list) */ char *user_word; /* user-defined word */ }; /* * A sparse matrix */ struct sm_matrix_struct { sm_row **rows; /* pointer to row headers (by row #) */ int rows_size; /* alloc'ed size of above array */ sm_col **cols; /* pointer to column headers (by col #) */ int cols_size; /* alloc'ed size of above array */ sm_row *first_row; /* first row (linked list of all rows) */ sm_row *last_row; /* last row (linked list of all rows) */ int nrows; /* number of rows */ sm_col *first_col; /* first column (linked list of columns) */ sm_col *last_col; /* last column (linked list of columns) */ int ncols; /* number of columns */ char *user_word; /* user-defined word */ }; #define sm_get_col(A, colnum) \ (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \ (A)->cols[colnum] : (sm_col *) 0) #define sm_get_row(A, rownum) \ (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \ (A)->rows[rownum] : (sm_row *) 0) #define sm_foreach_row(A, prow) \ for(prow = A->first_row; prow != 0; prow = prow->next_row) #define sm_foreach_col(A, pcol) \ for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) #define sm_foreach_row_element(prow, p) \ for(p = prow->first_col; p != 0; p = p->next_col) #define sm_foreach_col_element(pcol, p) \ for(p = pcol->first_row; p != 0; p = p->next_row) #define sm_put(x, val) \ (x->user_word = (char *) val) #define sm_get(type, x) \ ((type) (x->user_word)) extern sm_matrix *sm_alloc(), *sm_alloc_size(), *sm_dup(); extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize(); extern void sm_write(), sm_print(), sm_dump(), sm_cleanup(); extern void sm_copy_row(), sm_copy_col(); extern void sm_remove(), sm_remove_element(); extern sm_element *sm_insert(), *sm_find(); extern sm_row *sm_longest_row(); extern sm_col *sm_longest_col(); extern int sm_read(), sm_read_compressed(); extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and(); extern void sm_row_free(), sm_row_remove(), sm_row_print(); extern sm_element *sm_row_insert(), *sm_row_find(); extern int sm_row_contains(), sm_row_intersects(); extern int sm_row_compare(), sm_row_hash(); extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and(); extern void sm_col_free(), sm_col_remove(), sm_col_print(); extern sm_element *sm_col_insert(), *sm_col_find(); extern int sm_col_contains(), sm_col_intersects(); extern int sm_col_compare(), sm_col_hash(); extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition(); ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/sparse_int.h000066400000000000000000000046051300674244400251570ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ //#include "port.h" //#include "utility.h" #include "sparse.h" #include "util_hack.h" // added /* * sorted, double-linked list insertion * * type: object type * * first, last: fields (in header) to head and tail of the list * count: field (in header) of length of the list * * next, prev: fields (in object) to link next and previous objects * value: field (in object) which controls the order * * newval: value field for new object * e: an object to use if insertion needed (set to actual value used) */ #define ABC__misc__espresso__sparse_int_h if (last == 0) { \ e->value = newval; \ first = e; \ last = e; \ e->next = 0; \ e->prev = 0; \ count++; \ } else if (last->value < newval) { \ e->value = newval; \ last->next = e; \ e->prev = last; \ last = e; \ e->next = 0; \ count++; \ } else if (first->value > newval) { \ e->value = newval; \ first->prev = e; \ e->next = first; \ first = e; \ e->prev = 0; \ count++; \ } else { \ type *p; \ for(p = first; p->value < newval; p = p->next) \ ; \ if (p->value > newval) { \ e->value = newval; \ p = p->prev; \ p->next->prev = e; \ e->next = p->next; \ p->next = e; \ e->prev = p; \ count++; \ } else { \ e = p; \ } \ } /* * double linked-list deletion */ #define dll_unlink(p, first, last, next, prev, count) { \ if (p->prev == 0) { \ first = p->next; \ } else { \ p->prev->next = p->next; \ } \ if (p->next == 0) { \ last = p->prev; \ } else { \ p->next->prev = p->prev; \ } \ count--; \ } #ifdef FAST_AND_LOOSE extern sm_element *sm_element_freelist; extern sm_row *sm_row_freelist; extern sm_col *sm_col_freelist; #define sm_element_alloc(newobj) \ if (sm_element_freelist == NIL(sm_element)) { \ newobj = ALLOC(sm_element, 1); \ } else { \ newobj = sm_element_freelist; \ sm_element_freelist = sm_element_freelist->next_col; \ } \ newobj->user_word = NIL(char); \ #define sm_element_free(e) \ (e->next_col = sm_element_freelist, sm_element_freelist = e) #else #define sm_element_alloc(newobj) \ newobj = ALLOC(sm_element, 1); \ newobj->user_word = NIL(char); #define sm_element_free(e) \ FREE(e) #endif extern void sm_row_remove_element(); extern void sm_col_remove_element(); /* LINTLIBRARY */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/unate.c000066400000000000000000000237201300674244400241160ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* * unate.c -- routines for dealing with unate functions */ #include "espresso.h" ABC_NAMESPACE_IMPL_START static pset_family abs_covered(); static pset_family abs_covered_many(); static int abs_select_restricted(); pcover map_cover_to_unate(T) pcube *T; { register unsigned int word_test, word_set, bit_test, bit_set; register pcube p, pA; pset_family A; pcube *T1; int ncol, i; A = sf_new(CUBELISTSIZE(T), cdata.vars_unate); A->count = CUBELISTSIZE(T); foreachi_set(A, i, p) { (void) set_clear(p, A->sf_size); } ncol = 0; for(i = 0; i < cube.size; i++) { if (cdata.part_zeros[i] > 0) { assert(ncol <= cdata.vars_unate); /* Copy a column from T to A */ word_test = WHICH_WORD(i); bit_test = 1 << WHICH_BIT(i); word_set = WHICH_WORD(ncol); bit_set = 1 << WHICH_BIT(ncol); pA = A->data; for(T1 = T+2; (p = *T1++) != 0; ) { if ((p[word_test] & bit_test) == 0) { pA[word_set] |= bit_set; } pA += A->wsize; } ncol++; } } return A; } pcover map_unate_to_cover(A) pset_family A; { register int i, ncol, lp; register pcube p, pB; int var, nunate, *unate; pcube last; pset_family B; B = sf_new(A->count, cube.size); B->count = A->count; /* Find the unate variables */ unate = ALLOC(int, cube.num_vars); nunate = 0; for(var = 0; var < cube.num_vars; var++) { if (cdata.is_unate[var]) { unate[nunate++] = var; } } /* Loop for each set of A */ pB = B->data; foreach_set(A, last, p) { /* Initialize this set of B */ INLINEset_fill(pB, cube.size); /* Now loop for the unate variables; if the part is in A, * then this variable of B should be a single 1 in the unate * part. */ for(ncol = 0; ncol < nunate; ncol++) { if (is_in_set(p, ncol)) { lp = cube.last_part[unate[ncol]]; for(i = cube.first_part[unate[ncol]]; i <= lp; i++) { if (cdata.part_zeros[i] == 0) { set_remove(pB, i); } } } } pB += B->wsize; } FREE(unate); return B; } /* * unate_compl */ pset_family unate_compl(A) pset_family A; { register pset p, last; /* Make sure A is single-cube containment minimal */ /* A = sf_rev_contain(A);*/ foreach_set(A, last, p) { PUTSIZE(p, set_ord(p)); } /* Recursively find the complement */ A = unate_complement(A); /* Now, we can guarantee a minimal result by containing the result */ A = sf_rev_contain(A); return A; } /* * Assume SIZE(p) records the size of each set */ pset_family unate_complement(A) pset_family A; /* disposes of A */ { pset_family Abar; register pset p, p1, restrict; register int i; int max_i, min_set_ord, j; /* Check for no sets in the matrix -- complement is the universe */ if (A->count == 0) { sf_free(A); Abar = sf_new(1, A->sf_size); (void) set_clear(GETSET(Abar, Abar->count++), A->sf_size); /* Check for a single set in the maxtrix -- compute de Morgan complement */ } else if (A->count == 1) { p = A->data; Abar = sf_new(A->sf_size, A->sf_size); for(i = 0; i < A->sf_size; i++) { if (is_in_set(p, i)) { p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size); set_insert(p1, i); } } sf_free(A); } else { /* Select splitting variable as the variable which belongs to a set * of the smallest size, and which has greatest column count */ restrict = set_new(A->sf_size); min_set_ord = A->sf_size + 1; foreachi_set(A, i, p) { if (SIZE(p) < min_set_ord) { set_copy(restrict, p); min_set_ord = SIZE(p); } else if (SIZE(p) == min_set_ord) { set_or(restrict, restrict, p); } } /* Check for no data (shouldn't happen ?) */ if (min_set_ord == 0) { A->count = 0; Abar = A; /* Check for "essential" columns */ } else if (min_set_ord == 1) { Abar = unate_complement(abs_covered_many(A, restrict)); sf_free(A); foreachi_set(Abar, i, p) { set_or(p, p, restrict); } /* else, recur as usual */ } else { max_i = abs_select_restricted(A, restrict); /* Select those rows of A which are not covered by max_i, * recursively find all minimal covers of these rows, and * then add back in max_i */ Abar = unate_complement(abs_covered(A, max_i)); foreachi_set(Abar, i, p) { set_insert(p, max_i); } /* Now recur on A with all zero's on column max_i */ foreachi_set(A, i, p) { if (is_in_set(p, max_i)) { set_remove(p, max_i); j = SIZE(p) - 1; PUTSIZE(p, j); } } Abar = sf_append(Abar, unate_complement(A)); } set_free(restrict); } return Abar; } pset_family exact_minimum_cover(T) IN pset_family T; { register pset p, last, p1; register int i, n; int lev, lvl; pset nlast; pset_family temp; long start = ptime(); struct { pset_family sf; int level; } stack[32]; /* 32 suffices for 2 ** 32 cubes ! */ if (T->count <= 0) return sf_new(1, T->sf_size); for(n = T->count, lev = 0; n != 0; n >>= 1, lev++) ; /* A simple heuristic ordering */ T = lex_sort(sf_save(T)); /* Push a full set on the stack to get things started */ n = 1; stack[0].sf = sf_new(1, T->sf_size); stack[0].level = lev; set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size); nlast = GETSET(T, T->count - 1); foreach_set(T, last, p) { /* "unstack" the set into a family */ temp = sf_new(set_ord(p), T->sf_size); for(i = 0; i < T->sf_size; i++) if (is_in_set(p, i)) { p1 = set_fill(GETSET(temp, temp->count++), T->sf_size); set_remove(p1, i); } stack[n].sf = temp; stack[n++].level = lev; /* Pop the stack and perform (leveled) intersections */ while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) { temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE); lvl = MIN(stack[n-1].level, stack[n-2].level) - 1; if (debug & MINCOV && lvl < 10) { printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n", lvl, temp->count, stack[n-1].sf->count, stack[n-2].sf->count, print_time(ptime() - start)); (void) fflush(stdout); } sf_free(stack[n-2].sf); sf_free(stack[n-1].sf); stack[n-2].sf = temp; stack[n-2].level = lvl; n--; } } temp = stack[0].sf; p1 = set_fill(set_new(T->sf_size), T->sf_size); foreach_set(temp, last, p) INLINEset_diff(p, p1, p); set_free(p1); if (debug & MINCOV1) { printf("MINCOV: family of all minimal coverings is\n"); sf_print(temp); } sf_free(T); /* this is the copy of T we made ... */ return temp; } /* * unate_intersect -- intersect two unate covers * * If largest_only is TRUE, then only the largest cube(s) are returned */ #define MAGIC 500 /* save 500 cubes before containment */ pset_family unate_intersect(A, B, largest_only) pset_family A, B; bool largest_only; { register pset pi, pj, lasti, lastj, pt; pset_family T, Tsave; bool save; int maxord, ord; /* How large should each temporary result cover be ? */ T = sf_new(MAGIC, A->sf_size); Tsave = NULL; maxord = 0; pt = T->data; /* Form pairwise intersection of each set of A with each cube of B */ foreach_set(A, lasti, pi) { foreach_set(B, lastj, pj) { save = set_andp(pt, pi, pj); /* Check if we want the largest only */ if (save && largest_only) { if ((ord = set_ord(pt)) > maxord) { /* discard Tsave and T */ if (Tsave != NULL) { sf_free(Tsave); Tsave = NULL; } pt = T->data; T->count = 0; /* Re-create pt (which was just thrown away) */ (void) set_and(pt, pi, pj); maxord = ord; } else if (ord < maxord) { save = FALSE; } } if (save) { if (++T->count >= T->capacity) { T = sf_contain(T); Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T); T = sf_new(MAGIC, A->sf_size); pt = T->data; } else { pt += T->wsize; } } } } /* Contain the final result and merge it into Tsave */ T = sf_contain(T); Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T); return Tsave; } /* * abs_covered -- after selecting a new column for the selected set, * create a new matrix which is only those rows which are still uncovered */ static pset_family abs_covered(A, pick) pset_family A; register int pick; { register pset last, p, pdest; register pset_family Aprime; Aprime = sf_new(A->count, A->sf_size); pdest = Aprime->data; foreach_set(A, last, p) if (! is_in_set(p, pick)) { INLINEset_copy(pdest, p); Aprime->count++; pdest += Aprime->wsize; } return Aprime; } /* * abs_covered_many -- after selecting many columns for ther selected set, * create a new matrix which is only those rows which are still uncovered */ static pset_family abs_covered_many(A, pick_set) pset_family A; register pset pick_set; { register pset last, p, pdest; register pset_family Aprime; Aprime = sf_new(A->count, A->sf_size); pdest = Aprime->data; foreach_set(A, last, p) if (setp_disjoint(p, pick_set)) { INLINEset_copy(pdest, p); Aprime->count++; pdest += Aprime->wsize; } return Aprime; } /* * abs_select_restricted -- select the column of maximum column count which * also belongs to the set "restrict"; weight each column of a set as * 1 / (set_ord(p) - 1). */ static int abs_select_restricted(A, restrict) pset_family A; pset restrict; { register int i, best_var, best_count, *count; /* Sum the elements in these columns */ count = sf_count_restricted(A, restrict); /* Find which variable has maximum weight */ best_var = -1; best_count = 0; for(i = 0; i < A->sf_size; i++) { if (count[i] > best_count) { best_var = i; best_count = count[i]; } } FREE(count); if (best_var == -1) fatal("abs_select_restricted: should not have best_var == -1"); return best_var; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/util_old.h000066400000000000000000000171741300674244400246300ustar00rootroot00000000000000/* * Revision Control Information * * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/util/RCS/util.h,v $ * $Author: sis $ * $Revision: 1.9 $ * $Date: 1993/06/07 21:04:07 $ * */ #ifndef ABC__misc__espresso__util_old_h #define ABC__misc__espresso__util_old_h #if defined(_IBMR2) #ifndef _POSIX_SOURCE #define _POSIX_SOURCE /* Argh! IBM strikes again */ #endif #ifndef _ALL_SOURCE #define _ALL_SOURCE /* Argh! IBM strikes again */ #endif #ifndef _ANSI_C_SOURCE #define _ANSI_C_SOURCE /* Argh! IBM strikes again */ #endif #endif #if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) #include #endif #if defined(_IBMR2) && !defined(__STDC__) #define _BSD #endif #include "ansi.h" /* since some files don't include sis.h */ /* This was taken out and defined at compile time in the SIS Makefile that uses the OctTools. When the OctTools are used, USE_MM is defined, because the OctTools contain libmm.a. Otherwise, USE_MM is not defined, since the mm package is not distributed with SIS, only with Oct. */ /* #define USE_MM */ /* choose libmm.a as the memory allocator */ #define NIL(type) ((type *) 0) #ifdef USE_MM /* * assumes the memory manager is libmm.a * - allows malloc(0) or realloc(obj, 0) * - catches out of memory (and calls MMout_of_memory()) * - catch free(0) and realloc(0, size) in the macros */ #define ALLOC(type, num) \ ((type *) malloc(sizeof(type) * (num))) #define REALLOC(type, obj, num) \ (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ ((type *) malloc(sizeof(type) * (num))) #define FREE(obj) \ ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) #else /* * enforce strict semantics on the memory allocator * - when in doubt, delete the '#define USE_MM' above */ #define ALLOC(type, num) \ ((type *) MMalloc((long) sizeof(type) * (long) (num))) #define REALLOC(type, obj, num) \ ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num))) #define FREE(obj) \ ((obj) ? (free((void *) (obj)), (obj) = 0) : 0) #endif /* Ultrix (and SABER) have 'fixed' certain functions which used to be int */ #if defined(ultrix) || defined(SABER) || defined(aiws) || defined(__hpux) || defined(__STDC__) || defined(apollo) #define VOID_HACK void #else #define VOID_HACK int #endif /* No machines seem to have much of a problem with these */ #include #include /* Some machines fail to define some functions in stdio.h */ #if !defined(__STDC__) && !defined(sprite) && !defined(_IBMR2) && !defined(__osf__) extern FILE *popen(), *tmpfile(); extern int pclose(); #ifndef clearerr /* is a macro on many machines, but not all */ extern VOID_HACK clearerr(); #endif #ifndef rewind extern VOID_HACK rewind(); #endif #endif #ifndef PORT_H #include #include #if defined(ultrix) #if defined(_SIZE_T_) #define ultrix4 #else #if defined(SIGLOST) #define ultrix3 #else #define ultrix2 #endif #endif #endif #endif /* most machines don't give us a header file for these */ #if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) || defined(sunos4) || defined(__hpux) #include #if defined(__hpux) #include /* For perror() defininition */ #endif /* __hpux */ #else extern VOID_HACK abort(), free(), exit(), perror(); extern char *getenv(); #ifdef ultrix4 extern void *malloc(), *realloc(), *calloc(); #else extern char *malloc(), *realloc(), *calloc(); #endif #if defined(aiws) extern int sprintf(); #else #ifndef _IBMR2 extern char *sprintf(); #endif #endif extern int system(); extern double atof(); #endif #ifndef PORT_H #if defined(ultrix3) || defined(sunos4) || defined(_IBMR2) || defined(__STDC__) #define SIGNAL_FN void #else /* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */ #define SIGNAL_FN int #endif #endif /* some call it strings.h, some call it string.h; others, also have memory.h */ #if defined(__STDC__) || defined(sprite) #include #else #if defined(ultrix4) || defined(__hpux) #include #else #if defined(_IBMR2) || defined(__osf__) #include #include #else /* ANSI C string.h -- 1/11/88 Draft Standard */ /* ugly, awful hack */ #ifndef PORT_H extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror(); extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr(); extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn(); extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset(); extern int memcmp(), strcmp(); #endif #endif #endif #endif /* a few extras */ #if defined(__hpux) #define random() lrand48() #define srandom(a) srand48(a) #define bzero(a,b) memset(a, 0, b) #else #if !defined(__osf__) && !defined(linux) /* these are defined as macros in stdlib.h */ extern VOID_HACK srandom(); extern long random(); #endif #endif /* code from sis-1.3 commented out below #if defined(__STDC__) || defined(sprite) #include #else #ifndef NDEBUG #define assert(ex) {\ if (! (ex)) {\ (void) fprintf(stderr,\ "Assertion failed: file %s, line %d\n\"%s\"\n",\ __FILE__, __LINE__, "ex");\ (void) fflush(stdout);\ abort();\ }\ } #else #define assert(ex) {ex;} #endif #endif */ /* Sunil 5/3/97: sis-1.4: dont let the assert call go to the OS, since much of the code in SIS has actual computation done in the assert function. %$#$@@#! The OS version of assert will do nothing if NDEBUG is set. We cant let that happen... */ # ifdef NDEBUG # define assert(ex) {ex;} # else # define assert(ex) {\ if (! (ex)) {\ (void) fprintf(stderr,\ "Assertion failed: file %s, line %d\n\"%s\"\n",\ __FILE__, __LINE__, "ex");\ (void) fflush(stdout);\ abort();\ }\ } # endif #define fail(why) {\ (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ __FILE__, __LINE__, why);\ (void) fflush(stdout);\ abort();\ } #ifdef lint #undef putc /* correct lint '_flsbuf' bug */ #undef ALLOC /* allow for lint -h flag */ #undef REALLOC #define ALLOC(type, num) (((type *) 0) + (num)) #define REALLOC(type, obj, num) ((obj) + (num)) #endif /* #if !defined(__osf__) #define MAXPATHLEN 1024 #endif */ /* These arguably do NOT belong in util.h */ #ifndef ABS #define ABS(a) ((a) < 0 ? -(a) : (a)) #endif #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef USE_MM EXTERN void MMout_of_memory ARGS((long)); EXTERN char *MMalloc ARGS((long)); EXTERN char *MMrealloc ARGS((char *, long)); EXTERN void MMfree ARGS((char *)); #endif EXTERN void util_print_cpu_stats ARGS((FILE *)); EXTERN long util_cpu_time ARGS((void)); EXTERN void util_getopt_reset ARGS((void)); EXTERN int util_getopt ARGS((int, char **, char *)); EXTERN char *util_path_search ARGS((char *)); EXTERN char *util_file_search ARGS((char *, char *, char *)); EXTERN int util_pipefork ARGS((char **, FILE **, FILE **, int *)); EXTERN char *util_print_time ARGS((long)); EXTERN int util_save_image ARGS((char *, char *)); EXTERN char *util_strsav ARGS((char *)); EXTERN int util_do_nothing ARGS((void)); EXTERN char *util_tilde_expand ARGS((char *)); EXTERN char *util_tempnam ARGS((char *, char *)); EXTERN FILE *util_tmpfile ARGS((void)); EXTERN long getSoftDataLimit(); #define ptime() util_cpu_time() #define print_time(t) util_print_time(t) /* util_getopt() global variables (ack !) */ extern int util_optind; extern char *util_optarg; #include #ifndef HUGE_VAL #ifndef HUGE #define HUGE 8.9884656743115790e+307 #endif #define HUGE_VAL HUGE #endif #ifndef MAXINT #define MAXINT (1 << 30) #endif #include ABC_NAMESPACE_HEADER_START ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/espresso/verify.c000066400000000000000000000110641300674244400243040ustar00rootroot00000000000000/* * Revision Control Information * * $Source$ * $Author$ * $Revision$ * $Date$ * */ /* */ #include "espresso.h" ABC_NAMESPACE_IMPL_START /* * verify -- check that all minterms of F are contained in (Fold u Dold) * and that all minterms of Fold are contained in (F u Dold). */ bool verify(F, Fold, Dold) pcover F, Fold, Dold; { pcube p, last, *FD; bool verify_error = FALSE; /* Make sure the function didn't grow too large */ FD = cube2list(Fold, Dold); foreach_set(F, last, p) if (! cube_is_covered(FD, p)) { printf("some minterm in F is not covered by Fold u Dold\n"); verify_error = TRUE; if (verbose_debug) printf("%s\n", pc1(p)); else break; } free_cubelist(FD); /* Make sure minimized function covers the original function */ FD = cube2list(F, Dold); foreach_set(Fold, last, p) if (! cube_is_covered(FD, p)) { printf("some minterm in Fold is not covered by F u Dold\n"); verify_error = TRUE; if (verbose_debug) printf("%s\n", pc1(p)); else break; } free_cubelist(FD); return verify_error; } /* * PLA_verify -- verify that two PLA's are identical * * If names are given, row and column permutations are done to make * the comparison meaningful. * */ bool PLA_verify(PLA1, PLA2) pPLA PLA1, PLA2; { /* Check if both have names given; if so, attempt to permute to * match the names */ if (PLA1->label != NULL && PLA1->label[0] != NULL && PLA2->label != NULL && PLA2->label[0] != NULL) { PLA_permute(PLA1, PLA2); } else { (void) fprintf(stderr, "Warning: cannot permute columns without names\n"); return TRUE; } if (PLA1->F->sf_size != PLA2->F->sf_size) { (void) fprintf(stderr, "PLA_verify: PLA's are not the same size\n"); return TRUE; } return verify(PLA2->F, PLA1->F, PLA1->D); } /* * Permute the columns of PLA1 so that they match the order of PLA2 * Discard any columns of PLA1 which are not in PLA2 * Association is strictly by the names of the columns of the cover. */ void PLA_permute(PLA1, PLA2) pPLA PLA1, PLA2; { register int i, j, *permute, npermute; register char *labi; char **label; /* determine which columns of PLA1 to save, and place these in the list * "permute"; the order in this list is the final output order */ npermute = 0; permute = ALLOC(int, PLA2->F->sf_size); for(i = 0; i < PLA2->F->sf_size; i++) { labi = PLA2->label[i]; for(j = 0; j < PLA1->F->sf_size; j++) { if (strcmp(labi, PLA1->label[j]) == 0) { permute[npermute++] = j; break; } } } /* permute columns */ if (PLA1->F != NULL) { PLA1->F = sf_permute(PLA1->F, permute, npermute); } if (PLA1->R != NULL) { PLA1->R = sf_permute(PLA1->R, permute, npermute); } if (PLA1->D != NULL) { PLA1->D = sf_permute(PLA1->D, permute, npermute); } /* permute the labels */ label = ALLOC(char *, cube.size); for(i = 0; i < npermute; i++) { label[i] = PLA1->label[permute[i]]; } for(i = npermute; i < cube.size; i++) { label[i] = NULL; } FREE(PLA1->label); PLA1->label = label; FREE(permute); } /* * check_consistency -- test that the ON-set, OFF-set and DC-set form * a partition of the boolean space. */ bool check_consistency(PLA) pPLA PLA; { bool verify_error = FALSE; pcover T; T = cv_intersect(PLA->F, PLA->D); if (T->count == 0) printf("ON-SET and DC-SET are disjoint\n"); else { printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n"); if (verbose_debug) cprint(T); verify_error = TRUE; } (void) fflush(stdout); free_cover(T); T = cv_intersect(PLA->F, PLA->R); if (T->count == 0) printf("ON-SET and OFF-SET are disjoint\n"); else { printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n"); if (verbose_debug) cprint(T); verify_error = TRUE; } (void) fflush(stdout); free_cover(T); T = cv_intersect(PLA->D, PLA->R); if (T->count == 0) printf("DC-SET and OFF-SET are disjoint\n"); else { printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n"); if (verbose_debug) cprint(T); verify_error = TRUE; } (void) fflush(stdout); free_cover(T); if (tautology(cube3list(PLA->F, PLA->D, PLA->R))) printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n"); else { T = complement(cube3list(PLA->F, PLA->D, PLA->R)); printf("There are minterms left unspecified !\n"); if (verbose_debug) cprint(T); verify_error = TRUE; free_cover(T); } (void) fflush(stdout); return verify_error; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/000077500000000000000000000000001300674244400221125ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extra.h000066400000000000000000000471171300674244400234200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extra.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Various reusable software utilities.] Description [This library contains a number of operators and traversal routines developed to extend the functionality of CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/) To compile your code with the library, #include "extra.h" in your source files and link your project to CUDD and this library. Use the library at your own risk and with caution. Note that debugging of some operators still continues.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extra.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__extra__extra_h #define ABC__misc__extra__extra_h #ifdef _WIN32 #define inline __inline // compatible with MS VS 6.0 #endif /*---------------------------------------------------------------------------*/ /* Nested includes */ /*---------------------------------------------------------------------------*/ #include #include #include #include #include "misc/st/st.h" ABC_NAMESPACE_HEADER_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; /*===========================================================================*/ /* Various Utilities */ /*===========================================================================*/ /*=== extraUtilBitMatrix.c ================================================================*/ typedef struct Extra_BitMat_t_ Extra_BitMat_t; extern Extra_BitMat_t * Extra_BitMatrixStart( int nSize ); extern void Extra_BitMatrixClean( Extra_BitMat_t * p ); extern void Extra_BitMatrixStop( Extra_BitMat_t * p ); extern void Extra_BitMatrixPrint( Extra_BitMat_t * p ); extern int Extra_BitMatrixReadSize( Extra_BitMat_t * p ); extern void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k ); extern int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k ); extern void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k ); extern void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k ); extern int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k ); extern void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k ); extern void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo ); extern void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j ); extern int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p ); extern int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 ); extern int Extra_BitMatrixIsClique( Extra_BitMat_t * p ); /*=== extraUtilFile.c ========================================================*/ extern char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 ); extern char * Extra_FileNameExtension( char * FileName ); extern char * Extra_FileNameAppend( char * pBase, char * pSuffix ); extern char * Extra_FileNameGeneric( char * FileName ); extern char * Extra_FileNameGenericAppend( char * pBase, char * pSuffix ); extern void Extra_FileNameCorrectPath( char * FileName ); extern char * Extra_FileNameWithoutPath( char * FileName ); extern char * Extra_FilePathWithoutName( char * FileName ); extern char * Extra_FileDesignName( char * pFileName ); extern int Extra_FileCheck( char * pFileName ); extern int Extra_FileSize( char * pFileName ); extern char * Extra_FileRead( FILE * pFile ); extern char * Extra_FileRead2( FILE * pFile, FILE * pFile2 ); extern char * Extra_FileReadContents( char * pFileName ); extern char * Extra_FileReadContents2( char * pFileName, char * pFileName2 ); extern int Extra_FileIsType( char * pFileName, char * pS1, char * pS2, char * pS3 ); extern char * Extra_TimeStamp(); extern char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ); extern void Extra_StringClean( char * pStrGiven, char * pCharKeep ); extern unsigned Extra_ReadBinary( char * Buffer ); extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ); extern int Extra_ReadHex( unsigned Sign[], char * pString, int nDigits ); extern int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars ); extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ); extern void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars ); extern void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars ); extern void Extra_PrintHexReverse( FILE * pFile, unsigned * pTruth, int nVars ); extern void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine ); /*=== extraUtilReader.c ========================================================*/ typedef struct Extra_FileReader_t_ Extra_FileReader_t; extern Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, char * pCharsComment, char * pCharsStop, char * pCharsClean ); extern void Extra_FileReaderFree( Extra_FileReader_t * p ); extern char * Extra_FileReaderGetFileName( Extra_FileReader_t * p ); extern int Extra_FileReaderGetFileSize( Extra_FileReader_t * p ); extern int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p ); extern void * Extra_FileReaderGetTokens( Extra_FileReader_t * p ); extern int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken ); /*=== extraUtilMemory.c ========================================================*/ typedef struct Extra_MmFixed_t_ Extra_MmFixed_t; typedef struct Extra_MmFlex_t_ Extra_MmFlex_t; typedef struct Extra_MmStep_t_ Extra_MmStep_t; // fixed-size-block memory manager extern Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize ); extern void Extra_MmFixedStop( Extra_MmFixed_t * p ); extern char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p ); extern void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry ); extern void Extra_MmFixedRestart( Extra_MmFixed_t * p ); extern int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p ); extern int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p ); // flexible-size-block memory manager extern Extra_MmFlex_t * Extra_MmFlexStart(); extern void Extra_MmFlexStop( Extra_MmFlex_t * p ); extern void Extra_MmFlexPrint( Extra_MmFlex_t * p ); extern char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes ); extern int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p ); // hierarchical memory manager extern Extra_MmStep_t * Extra_MmStepStart( int nSteps ); extern void Extra_MmStepStop( Extra_MmStep_t * p ); extern char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes ); extern void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes ); extern int Extra_MmStepReadMemUsage( Extra_MmStep_t * p ); /*=== extraUtilMisc.c ========================================================*/ /* finds the smallest integer larger or equal than the logarithm */ extern int Extra_Base2LogDouble( double Num ); /* returns the power of two as a double */ extern double Extra_Power2( int Num ); extern int Extra_Power3( int Num ); /* the number of combinations of k elements out of n */ extern int Extra_NumCombinations( int k, int n ); extern int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits ); /* counts the number of 1s in the bitstring */ extern int Extra_CountOnes( unsigned char * pBytes, int nBytes ); /* the factorial of number */ extern int Extra_Factorial( int n ); /* the permutation of the given number of elements */ extern char ** Extra_Permutations( int n ); /* permutation and complementation of a truth table */ unsigned Extra_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse ); unsigned Extra_TruthPolarize( unsigned uTruth, int Polarity, int nVars ); /* canonical forms of a truth table */ extern unsigned Extra_TruthCanonN( unsigned uTruth, int nVars ); extern unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars ); extern unsigned Extra_TruthCanonP( unsigned uTruth, int nVars ); extern unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars ); extern unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars ); /* canonical forms of 4-variable functions */ extern void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ); extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax ); /* permutation mapping */ extern unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase ); extern unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase ); extern void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes ); extern void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR ); /* precomputing tables for permutation mapping */ extern void ** Extra_ArrayAlloc( int nCols, int nRows, int Size ); extern unsigned short ** Extra_TruthPerm43(); extern unsigned ** Extra_TruthPerm53(); extern unsigned ** Extra_TruthPerm54(); /* bubble sort for small number of entries */ extern void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing ); /* complementation/permutation generation */ extern int * Extra_GreyCodeSchedule( int n ); extern int * Extra_PermSchedule( int n ); extern word Extra_Truth6MinimumExact( word t, int * pComp, int * pPerm ); extern word Extra_Truth6MinimumHeuristic( word t ); /*=== extraUtilCanon.c ========================================================*/ /* fast computation of N-canoninical form up to 6 inputs */ extern int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ); /*=== extraUtilDsd.c ========================================================*/ typedef struct Sdm_Man_t_ Sdm_Man_t; extern int Sdm_ManCanRead(); extern Sdm_Man_t * Sdm_ManRead(); extern void Sdm_ManQuit(); extern int Sdm_ManComputeFunc( Sdm_Man_t * p, int iDsdLit0, int iDsdLit1, int * pCut, int uMask, int fXor ); extern void Sdm_ManPrintDsdStats( Sdm_Man_t * p, int fVerbose ); extern int Sdm_ManReadDsdVarNum( Sdm_Man_t * p, int iDsd ); extern int Sdm_ManReadDsdAndNum( Sdm_Man_t * p, int iDsd ); extern int Sdm_ManReadDsdClauseNum( Sdm_Man_t * p, int iDsd ); extern word Sdm_ManReadDsdTruth( Sdm_Man_t * p, int iDsd ); extern char * Sdm_ManReadDsdStr( Sdm_Man_t * p, int iDsd ); extern void Sdm_ManReadCnfCosts( Sdm_Man_t * p, int * pCosts, int nCosts ); /*=== extraUtilProgress.c ================================================================*/ typedef struct ProgressBarStruct ProgressBar; extern ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ); extern void Extra_ProgressBarStop( ProgressBar * p ); extern void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ); static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char * pString ) { if ( p && nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); } /*=== extraUtilTruth.c ================================================================*/ static inline int Extra_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); } static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } static inline void Extra_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); } static inline void Extra_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); } static inline int Extra_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; } static inline int Extra_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 Extra_TruthCountOnes( unsigned * pIn, int nVars ) { int w, Counter = 0; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) Counter += Extra_WordCountOnes(pIn[w]); return Counter; } static inline int Extra_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn0[w] != pIn1[w] ) return 0; return 1; } static inline int Extra_TruthIsConst0( unsigned * pIn, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn[w] ) return 0; return 1; } static inline int Extra_TruthIsConst1( unsigned * pIn, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn[w] != ~(unsigned)0 ) return 0; return 1; } static inline int Extra_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn1[w] & ~pIn2[w] ) return 0; return 1; } static inline void Extra_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn[w]; } static inline void Extra_TruthClear( unsigned * pOut, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = 0; } static inline void Extra_TruthFill( unsigned * pOut, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(unsigned)0; } static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn[w]; } static inline void Extra_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & pIn1[w]; } static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] | pIn1[w]; } static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & ~pIn1[w]; } static inline void Extra_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(pIn0[w] & pIn1[w]); } static inline void Extra_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 ) { int w; if ( fCompl0 && fCompl1 ) { for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(pIn0[w] | pIn1[w]); } else if ( fCompl0 && !fCompl1 ) { for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn0[w] & pIn1[w]; } else if ( !fCompl0 && fCompl1 ) { for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & ~pIn1[w]; } else // if ( !fCompl0 && !fCompl1 ) { for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & pIn1[w]; } } extern unsigned ** Extra_TruthElementary( int nVars ); extern void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start ); extern void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ); extern void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ); extern int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ); extern int Extra_TruthSupportSize( unsigned * pTruth, int nVars ); extern int Extra_TruthSupport( unsigned * pTruth, int nVars ); extern void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ); extern void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ); extern void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar ); extern void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar ); extern void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ); extern void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ); extern int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ); extern void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ); extern unsigned Extra_TruthHash( unsigned * pIn, int nWords ); extern unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ); /*=== extraUtilUtil.c ================================================================*/ extern abctime Extra_CpuTime(); extern double Extra_CpuTimeDouble(); extern int Extra_GetSoftDataLimit(); extern ABC_DLL void Extra_UtilGetoptReset(); extern int Extra_UtilGetopt( int argc, char *argv[], const char *optstring ); extern char * Extra_UtilPrintTime( long t ); extern char * Extra_UtilStrsav( const char *s ); extern char * Extra_UtilTildeExpand( char *fname ); extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); extern void (*Extra_UtilMMoutOfMemory)( long size ); extern const char * globalUtilOptarg; extern int globalUtilOptind; /**AutomaticEnd***************************************************************/ ABC_NAMESPACE_HEADER_END #endif /* __EXTRA_H__ */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilBitMatrix.c000066400000000000000000000273731300674244400260770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilBitMatrix.c] PackageName [extra] Synopsis [Various reusable software utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2003.] Revision [$Id: extraUtilBitMatrix.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "extra.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ struct Extra_BitMat_t_ { unsigned ** ppData; // bit data int nSize; // the number of bits in one dimension int nWords; // the number of words in one dimension int nBitShift; // the number of bits to shift to get words unsigned uMask; // the mask to get the number of bits in the word int nLookups; // the number of lookups int nInserts; // the number of inserts int nDeletes; // the number of deletions }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Starts the bit matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_BitMat_t * Extra_BitMatrixStart( int nSize ) { Extra_BitMat_t * p; int i; p = ABC_ALLOC( Extra_BitMat_t, 1 ); memset( p, 0, sizeof(Extra_BitMat_t) ); p->nSize = nSize; p->nBitShift = (sizeof(unsigned) == 4) ? 5: 6; p->uMask = (sizeof(unsigned) == 4) ? 31: 63; p->nWords = nSize / (8 * sizeof(unsigned)) + ((nSize % (8 * sizeof(unsigned))) > 0); p->ppData = ABC_ALLOC( unsigned *, nSize ); p->ppData[0] = ABC_ALLOC( unsigned, nSize * p->nWords ); memset( p->ppData[0], 0, sizeof(unsigned) * nSize * p->nWords ); for ( i = 1; i < nSize; i++ ) p->ppData[i] = p->ppData[i-1] + p->nWords; return p; } /**Function************************************************************* Synopsis [Stops the bit matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixClean( Extra_BitMat_t * p ) { memset( p->ppData[0], 0, sizeof(unsigned) * p->nSize * p->nWords ); } /**Function************************************************************* Synopsis [Stops the bit matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixStop( Extra_BitMat_t * p ) { ABC_FREE( p->ppData[0] ); ABC_FREE( p->ppData ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the bit-matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixPrint( Extra_BitMat_t * pMat ) { int i, k, nVars; printf( "\n" ); nVars = Extra_BitMatrixReadSize( pMat ); for ( i = 0; i < nVars; i++ ) { for ( k = 0; k <= i; k++ ) printf( " " ); for ( k = i+1; k < nVars; k++ ) if ( Extra_BitMatrixLookup1( pMat, i, k ) ) printf( "1" ); else printf( "." ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Reads the matrix size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_BitMatrixReadSize( Extra_BitMat_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [Inserts the element into the upper part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k ) { p->nInserts++; if ( i < k ) p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask)); else p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask)); } /**Function************************************************************* Synopsis [Inserts the element into the upper part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k ) { p->nLookups++; if ( i < k ) return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0); else return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0); } /**Function************************************************************* Synopsis [Inserts the element into the upper part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k ) { p->nDeletes++; if ( i < k ) p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask)); else p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask)); } /**Function************************************************************* Synopsis [Inserts the element into the upper part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k ) { p->nInserts++; if ( i > k ) p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask)); else p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask)); } /**Function************************************************************* Synopsis [Inserts the element into the upper part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k ) { p->nLookups++; if ( i > k ) return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0); else return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0); } /**Function************************************************************* Synopsis [Inserts the element into the upper part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k ) { p->nDeletes++; if ( i > k ) p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask)); else p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask)); } /**Function************************************************************* Synopsis [Inserts the element into the upper part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo ) { int w; for ( w = 0; w < p->nWords; w++ ) p->ppData[i][w] |= pInfo[w]; } /**Function************************************************************* Synopsis [Inserts the element into the upper part.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j ) { int w; for ( w = 0; w < p->nWords; w++ ) p->ppData[i][w] = p->ppData[j][w] = (p->ppData[i][w] | p->ppData[j][w]); } /**Function************************************************************* Synopsis [Counts the number of 1's in the upper rectangle.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p ) { int i, k, nTotal = 0; for ( i = 0; i < p->nSize; i++ ) for ( k = i + 1; k < p->nSize; k++ ) nTotal += ( (p->ppData[i][k>>5] & (1 << (k&31))) > 0 ); return nTotal; } /**Function************************************************************* Synopsis [Returns 1 if the matrices have no entries in common.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 ) { int i, w; assert( p1->nSize == p2->nSize ); for ( i = 0; i < p1->nSize; i++ ) for ( w = 0; w < p1->nWords; w++ ) if ( p1->ppData[i][w] & p2->ppData[i][w] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if the matrix is a set of cliques.] Description [For example pairwise symmetry info should satisfy this property.] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_BitMatrixIsClique( Extra_BitMat_t * pMat ) { int v, u, i; for ( v = 0; v < pMat->nSize; v++ ) for ( u = v+1; u < pMat->nSize; u++ ) { if ( !Extra_BitMatrixLookup1( pMat, v, u ) ) continue; // v and u are symmetric for ( i = 0; i < pMat->nSize; i++ ) { if ( i == v || i == u ) continue; // i is neither v nor u // the symmetry status of i is the same w.r.t. to v and u if ( Extra_BitMatrixLookup1( pMat, i, v ) != Extra_BitMatrixLookup1( pMat, i, u ) ) return 0; } } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilCanon.c000066400000000000000000000527521300674244400252310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilMisc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Computing canonical forms of Boolean functions using truth tables.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "extra.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ static unsigned s_Truths3[256] = { 0x00000000, 0x01010101, 0x01010101, 0x03030303, 0x01010101, 0x05050505, 0x06060606, 0x07070707, 0x01010101, 0x06060606, 0x05050505, 0x07070707, 0x03030303, 0x07070707, 0x07070707, 0x0f0f0f0f, 0x01010101, 0x11111111, 0x12121212, 0x13131313, 0x14141414, 0x15151515, 0x16161616, 0x17171717, 0x18181818, 0x19191919, 0x1a1a1a1a, 0x1b1b1b1b, 0x1c1c1c1c, 0x1d1d1d1d, 0x1e1e1e1e, 0x1f1f1f1f, 0x01010101, 0x12121212, 0x11111111, 0x13131313, 0x18181818, 0x1a1a1a1a, 0x19191919, 0x1b1b1b1b, 0x14141414, 0x16161616, 0x15151515, 0x17171717, 0x1c1c1c1c, 0x1e1e1e1e, 0x1d1d1d1d, 0x1f1f1f1f, 0x03030303, 0x13131313, 0x13131313, 0x33333333, 0x1c1c1c1c, 0x35353535, 0x36363636, 0x37373737, 0x1c1c1c1c, 0x36363636, 0x35353535, 0x37373737, 0x3c3c3c3c, 0x3d3d3d3d, 0x3d3d3d3d, 0x3f3f3f3f, 0x01010101, 0x14141414, 0x18181818, 0x1c1c1c1c, 0x11111111, 0x15151515, 0x19191919, 0x1d1d1d1d, 0x12121212, 0x16161616, 0x1a1a1a1a, 0x1e1e1e1e, 0x13131313, 0x17171717, 0x1b1b1b1b, 0x1f1f1f1f, 0x05050505, 0x15151515, 0x1a1a1a1a, 0x35353535, 0x15151515, 0x55555555, 0x56565656, 0x57575757, 0x1a1a1a1a, 0x56565656, 0x5a5a5a5a, 0x5b5b5b5b, 0x35353535, 0x57575757, 0x5b5b5b5b, 0x5f5f5f5f, 0x06060606, 0x16161616, 0x19191919, 0x36363636, 0x19191919, 0x56565656, 0x66666666, 0x67676767, 0x16161616, 0x69696969, 0x56565656, 0x6b6b6b6b, 0x36363636, 0x6b6b6b6b, 0x67676767, 0x6f6f6f6f, 0x07070707, 0x17171717, 0x1b1b1b1b, 0x37373737, 0x1d1d1d1d, 0x57575757, 0x67676767, 0x77777777, 0x1e1e1e1e, 0x6b6b6b6b, 0x5b5b5b5b, 0x7b7b7b7b, 0x3d3d3d3d, 0x7d7d7d7d, 0x7e7e7e7e, 0x7f7f7f7f, 0x01010101, 0x18181818, 0x14141414, 0x1c1c1c1c, 0x12121212, 0x1a1a1a1a, 0x16161616, 0x1e1e1e1e, 0x11111111, 0x19191919, 0x15151515, 0x1d1d1d1d, 0x13131313, 0x1b1b1b1b, 0x17171717, 0x1f1f1f1f, 0x06060606, 0x19191919, 0x16161616, 0x36363636, 0x16161616, 0x56565656, 0x69696969, 0x6b6b6b6b, 0x19191919, 0x66666666, 0x56565656, 0x67676767, 0x36363636, 0x67676767, 0x6b6b6b6b, 0x6f6f6f6f, 0x05050505, 0x1a1a1a1a, 0x15151515, 0x35353535, 0x1a1a1a1a, 0x5a5a5a5a, 0x56565656, 0x5b5b5b5b, 0x15151515, 0x56565656, 0x55555555, 0x57575757, 0x35353535, 0x5b5b5b5b, 0x57575757, 0x5f5f5f5f, 0x07070707, 0x1b1b1b1b, 0x17171717, 0x37373737, 0x1e1e1e1e, 0x5b5b5b5b, 0x6b6b6b6b, 0x7b7b7b7b, 0x1d1d1d1d, 0x67676767, 0x57575757, 0x77777777, 0x3d3d3d3d, 0x7e7e7e7e, 0x7d7d7d7d, 0x7f7f7f7f, 0x03030303, 0x1c1c1c1c, 0x1c1c1c1c, 0x3c3c3c3c, 0x13131313, 0x35353535, 0x36363636, 0x3d3d3d3d, 0x13131313, 0x36363636, 0x35353535, 0x3d3d3d3d, 0x33333333, 0x37373737, 0x37373737, 0x3f3f3f3f, 0x07070707, 0x1d1d1d1d, 0x1e1e1e1e, 0x3d3d3d3d, 0x17171717, 0x57575757, 0x6b6b6b6b, 0x7d7d7d7d, 0x1b1b1b1b, 0x67676767, 0x5b5b5b5b, 0x7e7e7e7e, 0x37373737, 0x77777777, 0x7b7b7b7b, 0x7f7f7f7f, 0x07070707, 0x1e1e1e1e, 0x1d1d1d1d, 0x3d3d3d3d, 0x1b1b1b1b, 0x5b5b5b5b, 0x67676767, 0x7e7e7e7e, 0x17171717, 0x6b6b6b6b, 0x57575757, 0x7d7d7d7d, 0x37373737, 0x7b7b7b7b, 0x77777777, 0x7f7f7f7f, 0x0f0f0f0f, 0x1f1f1f1f, 0x1f1f1f1f, 0x3f3f3f3f, 0x1f1f1f1f, 0x5f5f5f5f, 0x6f6f6f6f, 0x7f7f7f7f, 0x1f1f1f1f, 0x6f6f6f6f, 0x5f5f5f5f, 0x7f7f7f7f, 0x3f3f3f3f, 0x7f7f7f7f, 0x7f7f7f7f, 0xffffffff }; static char s_Phases3[256][9] = { /* 0 */ { 8, 0, 1, 2, 3, 4, 5, 6, 7 }, /* 1 */ { 1, 0 }, /* 2 */ { 1, 1 }, /* 3 */ { 2, 0, 1 }, /* 4 */ { 1, 2 }, /* 5 */ { 2, 0, 2 }, /* 6 */ { 2, 0, 3 }, /* 7 */ { 1, 0 }, /* 8 */ { 1, 3 }, /* 9 */ { 2, 1, 2 }, /* 10 */ { 2, 1, 3 }, /* 11 */ { 1, 1 }, /* 12 */ { 2, 2, 3 }, /* 13 */ { 1, 2 }, /* 14 */ { 1, 3 }, /* 15 */ { 4, 0, 1, 2, 3 }, /* 16 */ { 1, 4 }, /* 17 */ { 2, 0, 4 }, /* 18 */ { 2, 0, 5 }, /* 19 */ { 1, 0 }, /* 20 */ { 2, 0, 6 }, /* 21 */ { 1, 0 }, /* 22 */ { 1, 0 }, /* 23 */ { 1, 0 }, /* 24 */ { 2, 0, 7 }, /* 25 */ { 1, 0 }, /* 26 */ { 1, 0 }, /* 27 */ { 1, 0 }, /* 28 */ { 1, 0 }, /* 29 */ { 1, 0 }, /* 30 */ { 1, 0 }, /* 31 */ { 1, 0 }, /* 32 */ { 1, 5 }, /* 33 */ { 2, 1, 4 }, /* 34 */ { 2, 1, 5 }, /* 35 */ { 1, 1 }, /* 36 */ { 2, 1, 6 }, /* 37 */ { 1, 1 }, /* 38 */ { 1, 1 }, /* 39 */ { 1, 1 }, /* 40 */ { 2, 1, 7 }, /* 41 */ { 1, 1 }, /* 42 */ { 1, 1 }, /* 43 */ { 1, 1 }, /* 44 */ { 1, 1 }, /* 45 */ { 1, 1 }, /* 46 */ { 1, 1 }, /* 47 */ { 1, 1 }, /* 48 */ { 2, 4, 5 }, /* 49 */ { 1, 4 }, /* 50 */ { 1, 5 }, /* 51 */ { 4, 0, 1, 4, 5 }, /* 52 */ { 1, 6 }, /* 53 */ { 1, 0 }, /* 54 */ { 1, 0 }, /* 55 */ { 1, 0 }, /* 56 */ { 1, 7 }, /* 57 */ { 1, 1 }, /* 58 */ { 1, 1 }, /* 59 */ { 1, 1 }, /* 60 */ { 4, 0, 1, 6, 7 }, /* 61 */ { 1, 0 }, /* 62 */ { 1, 1 }, /* 63 */ { 2, 0, 1 }, /* 64 */ { 1, 6 }, /* 65 */ { 2, 2, 4 }, /* 66 */ { 2, 2, 5 }, /* 67 */ { 1, 2 }, /* 68 */ { 2, 2, 6 }, /* 69 */ { 1, 2 }, /* 70 */ { 1, 2 }, /* 71 */ { 1, 2 }, /* 72 */ { 2, 2, 7 }, /* 73 */ { 1, 2 }, /* 74 */ { 1, 2 }, /* 75 */ { 1, 2 }, /* 76 */ { 1, 2 }, /* 77 */ { 1, 2 }, /* 78 */ { 1, 2 }, /* 79 */ { 1, 2 }, /* 80 */ { 2, 4, 6 }, /* 81 */ { 1, 4 }, /* 82 */ { 1, 5 }, /* 83 */ { 1, 4 }, /* 84 */ { 1, 6 }, /* 85 */ { 4, 0, 2, 4, 6 }, /* 86 */ { 1, 0 }, /* 87 */ { 1, 0 }, /* 88 */ { 1, 7 }, /* 89 */ { 1, 2 }, /* 90 */ { 4, 0, 2, 5, 7 }, /* 91 */ { 1, 0 }, /* 92 */ { 1, 6 }, /* 93 */ { 1, 2 }, /* 94 */ { 1, 2 }, /* 95 */ { 2, 0, 2 }, /* 96 */ { 2, 4, 7 }, /* 97 */ { 1, 4 }, /* 98 */ { 1, 5 }, /* 99 */ { 1, 4 }, /* 100 */ { 1, 6 }, /* 101 */ { 1, 4 }, /* 102 */ { 4, 0, 3, 4, 7 }, /* 103 */ { 1, 0 }, /* 104 */ { 1, 7 }, /* 105 */ { 4, 0, 3, 5, 6 }, /* 106 */ { 1, 7 }, /* 107 */ { 1, 0 }, /* 108 */ { 1, 7 }, /* 109 */ { 1, 3 }, /* 110 */ { 1, 3 }, /* 111 */ { 2, 0, 3 }, /* 112 */ { 1, 4 }, /* 113 */ { 1, 4 }, /* 114 */ { 1, 5 }, /* 115 */ { 1, 4 }, /* 116 */ { 1, 6 }, /* 117 */ { 1, 4 }, /* 118 */ { 1, 4 }, /* 119 */ { 2, 0, 4 }, /* 120 */ { 1, 7 }, /* 121 */ { 1, 5 }, /* 122 */ { 1, 5 }, /* 123 */ { 2, 0, 5 }, /* 124 */ { 1, 6 }, /* 125 */ { 2, 0, 6 }, /* 126 */ { 2, 0, 7 }, /* 127 */ { 1, 0 }, /* 128 */ { 1, 7 }, /* 129 */ { 2, 3, 4 }, /* 130 */ { 2, 3, 5 }, /* 131 */ { 1, 3 }, /* 132 */ { 2, 3, 6 }, /* 133 */ { 1, 3 }, /* 134 */ { 1, 3 }, /* 135 */ { 1, 3 }, /* 136 */ { 2, 3, 7 }, /* 137 */ { 1, 3 }, /* 138 */ { 1, 3 }, /* 139 */ { 1, 3 }, /* 140 */ { 1, 3 }, /* 141 */ { 1, 3 }, /* 142 */ { 1, 3 }, /* 143 */ { 1, 3 }, /* 144 */ { 2, 5, 6 }, /* 145 */ { 1, 4 }, /* 146 */ { 1, 5 }, /* 147 */ { 1, 5 }, /* 148 */ { 1, 6 }, /* 149 */ { 1, 6 }, /* 150 */ { 4, 1, 2, 4, 7 }, /* 151 */ { 1, 1 }, /* 152 */ { 1, 7 }, /* 153 */ { 4, 1, 2, 5, 6 }, /* 154 */ { 1, 5 }, /* 155 */ { 1, 1 }, /* 156 */ { 1, 6 }, /* 157 */ { 1, 2 }, /* 158 */ { 1, 2 }, /* 159 */ { 2, 1, 2 }, /* 160 */ { 2, 5, 7 }, /* 161 */ { 1, 4 }, /* 162 */ { 1, 5 }, /* 163 */ { 1, 5 }, /* 164 */ { 1, 6 }, /* 165 */ { 4, 1, 3, 4, 6 }, /* 166 */ { 1, 3 }, /* 167 */ { 1, 1 }, /* 168 */ { 1, 7 }, /* 169 */ { 1, 1 }, /* 170 */ { 4, 1, 3, 5, 7 }, /* 171 */ { 1, 1 }, /* 172 */ { 1, 7 }, /* 173 */ { 1, 3 }, /* 174 */ { 1, 3 }, /* 175 */ { 2, 1, 3 }, /* 176 */ { 1, 5 }, /* 177 */ { 1, 4 }, /* 178 */ { 1, 5 }, /* 179 */ { 1, 5 }, /* 180 */ { 1, 6 }, /* 181 */ { 1, 4 }, /* 182 */ { 1, 4 }, /* 183 */ { 2, 1, 4 }, /* 184 */ { 1, 7 }, /* 185 */ { 1, 5 }, /* 186 */ { 1, 5 }, /* 187 */ { 2, 1, 5 }, /* 188 */ { 1, 7 }, /* 189 */ { 2, 1, 6 }, /* 190 */ { 2, 1, 7 }, /* 191 */ { 1, 1 }, /* 192 */ { 2, 6, 7 }, /* 193 */ { 1, 4 }, /* 194 */ { 1, 5 }, /* 195 */ { 4, 2, 3, 4, 5 }, /* 196 */ { 1, 6 }, /* 197 */ { 1, 2 }, /* 198 */ { 1, 3 }, /* 199 */ { 1, 2 }, /* 200 */ { 1, 7 }, /* 201 */ { 1, 2 }, /* 202 */ { 1, 3 }, /* 203 */ { 1, 3 }, /* 204 */ { 4, 2, 3, 6, 7 }, /* 205 */ { 1, 2 }, /* 206 */ { 1, 3 }, /* 207 */ { 2, 2, 3 }, /* 208 */ { 1, 6 }, /* 209 */ { 1, 4 }, /* 210 */ { 1, 5 }, /* 211 */ { 1, 4 }, /* 212 */ { 1, 6 }, /* 213 */ { 1, 6 }, /* 214 */ { 1, 7 }, /* 215 */ { 2, 2, 4 }, /* 216 */ { 1, 7 }, /* 217 */ { 1, 6 }, /* 218 */ { 1, 7 }, /* 219 */ { 2, 2, 5 }, /* 220 */ { 1, 6 }, /* 221 */ { 2, 2, 6 }, /* 222 */ { 2, 2, 7 }, /* 223 */ { 1, 2 }, /* 224 */ { 1, 7 }, /* 225 */ { 1, 4 }, /* 226 */ { 1, 5 }, /* 227 */ { 1, 5 }, /* 228 */ { 1, 6 }, /* 229 */ { 1, 6 }, /* 230 */ { 1, 7 }, /* 231 */ { 2, 3, 4 }, /* 232 */ { 1, 7 }, /* 233 */ { 1, 6 }, /* 234 */ { 1, 7 }, /* 235 */ { 2, 3, 5 }, /* 236 */ { 1, 7 }, /* 237 */ { 2, 3, 6 }, /* 238 */ { 2, 3, 7 }, /* 239 */ { 1, 3 }, /* 240 */ { 4, 4, 5, 6, 7 }, /* 241 */ { 1, 4 }, /* 242 */ { 1, 5 }, /* 243 */ { 2, 4, 5 }, /* 244 */ { 1, 6 }, /* 245 */ { 2, 4, 6 }, /* 246 */ { 2, 4, 7 }, /* 247 */ { 1, 4 }, /* 248 */ { 1, 7 }, /* 249 */ { 2, 5, 6 }, /* 250 */ { 2, 5, 7 }, /* 251 */ { 1, 5 }, /* 252 */ { 2, 6, 7 }, /* 253 */ { 1, 6 }, /* 254 */ { 1, 7 }, /* 255 */ { 8, 0, 1, 2, 3, 4, 5, 6, 7 } }; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ static int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag ); /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Computes the N-canonical form of the Boolean function up to 6 inputs.] Description [The N-canonical form is defined as the truth table with the minimum integer value. This function exhaustively enumerates through the complete set of 2^N phase assignments. Returns pointers to the static storage to the truth table and phases. This data should be used before the function is called again.] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ) { static unsigned uTruthStore6[2]; int RetValue; assert( nVarsMax <= 6 ); assert( nVarsReal <= nVarsMax ); RetValue = Extra_TruthCanonN_rec( nVarsReal <= 3? 3: nVarsReal, (unsigned char *)pt, pptRes, ppfRes, 0 ); if ( nVarsMax == 6 && nVarsReal < nVarsMax ) { uTruthStore6[0] = **pptRes; uTruthStore6[1] = **pptRes; *pptRes = uTruthStore6; } return RetValue; } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Recursive implementation of the above.] Description [] SideEffects [This procedure has a bug, which shows on Solaris. Most likely has something to do with the casts, i.g *((unsigned *)pt0)] SeeAlso [] ***********************************************************************/ int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag ) { static unsigned uTruthStore[7][2][2]; static char uPhaseStore[7][2][64]; unsigned char * pt0, * pt1; unsigned * ptRes0, * ptRes1, * ptRes; unsigned uInit0, uInit1, uTruth0, uTruth1, uTemp; char * pfRes0, * pfRes1, * pfRes; int nf0, nf1, nfRes, i, nVarsN; // table lookup for three vars if ( nVars == 3 ) { *pptRes = &s_Truths3[*pt]; *ppfRes = s_Phases3[*pt]+1; return s_Phases3[*pt][0]; } // number of vars for the next call nVarsN = nVars-1; // truth table for the next call pt0 = pt; pt1 = pt + (1 << nVarsN) / 8; // 5-var truth tables for this call // uInit0 = *((unsigned *)pt0); // uInit1 = *((unsigned *)pt1); if ( nVarsN == 3 ) { uInit0 = (pt0[0] << 24) | (pt0[0] << 16) | (pt0[0] << 8) | pt0[0]; uInit1 = (pt1[0] << 24) | (pt1[0] << 16) | (pt1[0] << 8) | pt1[0]; } else if ( nVarsN == 4 ) { uInit0 = (pt0[1] << 24) | (pt0[0] << 16) | (pt0[1] << 8) | pt0[0]; uInit1 = (pt1[1] << 24) | (pt1[0] << 16) | (pt1[1] << 8) | pt1[0]; } else { uInit0 = (pt0[3] << 24) | (pt0[2] << 16) | (pt0[1] << 8) | pt0[0]; uInit1 = (pt1[3] << 24) | (pt1[2] << 16) | (pt1[1] << 8) | pt1[0]; } // storage for truth tables and phases ptRes = uTruthStore[nVars][Flag]; pfRes = uPhaseStore[nVars][Flag]; // solve trivial cases if ( uInit1 == 0 ) { nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 ); uTruth1 = uInit1; uTruth0 = *ptRes0; nfRes = 0; for ( i = 0; i < nf0; i++ ) pfRes[nfRes++] = pfRes0[i]; goto finish; } if ( uInit0 == 0 ) { nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 ); uTruth1 = uInit0; uTruth0 = *ptRes1; nfRes = 0; for ( i = 0; i < nf1; i++ ) pfRes[nfRes++] = pfRes1[i] | (1< uTemp ) { nfRes = 0; uTruth0 = uTemp; pfRes[nfRes++] = pfRes1[i]; } else if ( uTruth0 == uTemp ) pfRes[nfRes++] = pfRes1[i]; } uTruth1 = *ptRes1; } else if ( *ptRes1 > *ptRes0 ) { uTruth0 = 0xFFFFFFFF; nfRes = 0; for ( i = 0; i < nf0; i++ ) { uTemp = Extra_TruthPolarize( uInit1, pfRes0[i], nVarsN ); if ( uTruth0 > uTemp ) { nfRes = 0; uTruth0 = uTemp; pfRes[nfRes++] = pfRes0[i] | (1< #include #include #include #include "misc/vec/vec.h" #include "misc/vec/vecHsh.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline void Abc_StatePush( Vec_Int_t * vData, char * pState, int k ) { int i; for ( i = 0; i < 6; i++ ) Vec_IntWriteEntry(vData, 6*k+i, ((int*)pState)[i]); } static inline void Abc_StatePerm( char * pState, char * pPerm, char * pRes ) { int i; for ( i = 0; i < 24; i++ ) pRes[i] = pState[(int)pPerm[i]]; } static inline void Abc_StatePrint( char * pState ) { int i; for ( i = 0; i < 24; i++ ) printf(" %2d", pState[i]); printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_EnumerateCubeStates2() { int pXYZ[3][9][2] = { { {3, 5}, {3,17}, {3,15}, {1, 6}, {1,16}, {1,14}, {2, 4}, {2,18}, {2,13} }, { {2,14}, {2,24}, {2,12}, {3,13}, {3,23}, {3,10}, {1,15}, {1,22}, {1,11} }, { {1,10}, {1, 7}, {1, 4}, {3,12}, {3, 9}, {3, 6}, {2,11}, {2, 8}, {2, 5} } }; Vec_Int_t * vData = Vec_IntStart( 6 * (1 << 22) ); // 96 MB Hsh_IntMan_t * vHash = Hsh_IntManStart( vData, 6, 1 << 22 ); // 32 MB int i, k, v, RetValue, Beg, End, Counter = 0; char pStart[24], pFirst[9][24]; abctime clk = Abc_Clock(); printf( "Enumerating states of 2x2x2 cube.\n" ); // init state for ( v = 0; v < 24; v++ ) pStart[v] = v; Abc_StatePush( vData, pStart, Counter ); RetValue = Hsh_IntManAdd( vHash, Counter ); assert( RetValue == Counter ); Counter++; // first nine states for ( i = 0; i < 3; i++ ) { memcpy( pFirst[i], pStart, 24 ); for ( v = 0; v < 9; v++ ) ABC_SWAP( char, pFirst[i][pXYZ[i][v][0]-1], pFirst[i][pXYZ[i][v][1]-1] ); Abc_StatePush( vData, pFirst[i], Counter ); RetValue = Hsh_IntManAdd( vHash, Counter ); assert( RetValue == Counter ); Counter++; //Abc_StatePrint( pFirst[i] ); memcpy( pFirst[3+i], pFirst[i], 24 ); for ( v = 0; v < 9; v++ ) ABC_SWAP( char, pFirst[3+i][pXYZ[i][v][0]-1], pFirst[3+i][pXYZ[i][v][1]-1] ); Abc_StatePush( vData, pFirst[3+i], Counter ); RetValue = Hsh_IntManAdd( vHash, Counter ); assert( RetValue == Counter ); Counter++; //Abc_StatePrint( pFirst[3+i] ); memcpy( pFirst[6+i], pFirst[3+i], 24 ); for ( v = 0; v < 9; v++ ) ABC_SWAP( char, pFirst[6+i][pXYZ[i][v][0]-1], pFirst[6+i][pXYZ[i][v][1]-1] ); Abc_StatePush( vData, pFirst[6+i], Counter ); RetValue = Hsh_IntManAdd( vHash, Counter ); assert( RetValue == Counter ); Counter++; //Abc_StatePrint( pFirst[6+i] ); } printf( "Iter %2d -> %8d ", 0, 1 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); printf( "Iter %2d -> %8d ", 1, Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Beg = 1; End = 10; for ( i = 2; i <= 100; i++ ) { if ( Beg == End ) break; for ( k = Beg; k < End; k++ ) for ( v = 0; v < 9; v++ ) { Abc_StatePerm( (char *)Vec_IntEntryP(vData, 6*k), pFirst[v], (char *)Vec_IntEntryP(vData, 6*Counter) ); RetValue = Hsh_IntManAdd( vHash, Counter ); if ( RetValue == Counter ) Counter++; if ( Counter == (1<<22) ) { printf( "Did not converge. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return; } } Beg = End; End = Counter; printf( "Iter %2d -> %8d ", i, Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } Hsh_IntManStop( vHash ); Vec_IntFree( vData ); } /* Enumerating states of 2x2x2 cube. Iter 0 -> 1 Time = 0.00 sec Iter 1 -> 10 Time = 0.00 sec Iter 2 -> 64 Time = 0.00 sec Iter 3 -> 385 Time = 0.00 sec Iter 4 -> 2232 Time = 0.00 sec Iter 5 -> 12224 Time = 0.00 sec Iter 6 -> 62360 Time = 0.02 sec Iter 7 -> 289896 Time = 0.09 sec Iter 8 -> 1159968 Time = 0.90 sec Iter 9 -> 3047716 Time = 11.62 sec Iter 10 -> 3671516 Time = 52.00 sec Iter 11 -> 3674160 Time = 70.38 sec Iter 12 -> 3674160 Time = 70.48 sec */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_DataHasBit( word * p, word i ) { return (p[(i)>>6] & (1<<((i) & 63))) > 0; } static inline void Abc_DataXorBit( word * p, word i ) { p[(i)>>6] ^= (1<<((i) & 63)); } static inline int Abc_DataGetCube( word w, int i ) { return (w >> (5*i)) & 31; } static inline word Abc_DataXorCube( word w, int i, int c ) { return w ^ (((word)c) << (5*i)); } static inline word Abc_CubeGenerateSign( char * pState ) { static int Var2Cor[24] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, -1, -1, -1, 6, 6, 6 }; static int Var2Per[24] = { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, -1, -1, -1, 0, 1, 2 }; word Res = 0; Res = Abc_DataXorCube( Res, 0, (Var2Cor[(int)pState[ 0]] << 2) | Var2Per[(int)pState[ 0]] ); Res = Abc_DataXorCube( Res, 1, (Var2Cor[(int)pState[ 3]] << 2) | Var2Per[(int)pState[ 3]] ); Res = Abc_DataXorCube( Res, 2, (Var2Cor[(int)pState[ 6]] << 2) | Var2Per[(int)pState[ 6]] ); Res = Abc_DataXorCube( Res, 3, (Var2Cor[(int)pState[ 9]] << 2) | Var2Per[(int)pState[ 9]] ); Res = Abc_DataXorCube( Res, 4, (Var2Cor[(int)pState[12]] << 2) | Var2Per[(int)pState[12]] ); Res = Abc_DataXorCube( Res, 5, (Var2Cor[(int)pState[15]] << 2) | Var2Per[(int)pState[15]] ); Res = Abc_DataXorCube( Res, 6, (Var2Cor[(int)pState[21]] << 2) | Var2Per[(int)pState[21]] ); return Res; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_EnumerateCubeStates() { int pXYZ[3][9][2] = { { {3, 5}, {3,17}, {3,15}, {1, 6}, {1,16}, {1,14}, {2, 4}, {2,18}, {2,13} }, { {2,14}, {2,24}, {2,12}, {3,13}, {3,23}, {3,10}, {1,15}, {1,22}, {1,11} }, { {1,10}, {1, 7}, {1, 4}, {3,12}, {3, 9}, {3, 6}, {2,11}, {2, 8}, {2, 5} } }; Vec_Int_t * vData = Vec_IntStart( 6 * (1 << 22) ); // 96 MB word State, * pHash = ABC_CALLOC( word, 1 << 29 ); // 4 GB int i, k, v, Beg, End, Counter = 0; char * pPrev, * pState, pStart[24], pFirst[9][24]; abctime clk = Abc_Clock(); printf( "Enumerating states of 2x2x2 cube.\n" ); // init state for ( v = 0; v < 24; v++ ) pStart[v] = v; Abc_StatePush( vData, pStart, Counter ); Abc_DataXorBit( pHash, Abc_CubeGenerateSign(pStart) ); Counter++; // first nine states for ( i = 0; i < 3; i++ ) { memcpy( pFirst[i], pStart, 24 ); for ( v = 0; v < 9; v++ ) ABC_SWAP( char, pFirst[i][pXYZ[i][v][0]-1], pFirst[i][pXYZ[i][v][1]-1] ); Abc_StatePush( vData, pFirst[i], Counter ); Abc_DataXorBit( pHash, Abc_CubeGenerateSign(pFirst[i]) ); Counter++; //Abc_StatePrint( pFirst[i] ); memcpy( pFirst[3+i], pFirst[i], 24 ); for ( v = 0; v < 9; v++ ) ABC_SWAP( char, pFirst[3+i][pXYZ[i][v][0]-1], pFirst[3+i][pXYZ[i][v][1]-1] ); Abc_StatePush( vData, pFirst[3+i], Counter ); Abc_DataXorBit( pHash, Abc_CubeGenerateSign(pFirst[3+i]) ); Counter++; //Abc_StatePrint( pFirst[3+i] ); memcpy( pFirst[6+i], pFirst[3+i], 24 ); for ( v = 0; v < 9; v++ ) ABC_SWAP( char, pFirst[6+i][pXYZ[i][v][0]-1], pFirst[6+i][pXYZ[i][v][1]-1] ); Abc_StatePush( vData, pFirst[6+i], Counter ); Abc_DataXorBit( pHash, Abc_CubeGenerateSign(pFirst[6+i]) ); Counter++; //Abc_StatePrint( pFirst[6+i] ); } printf( "Iter %2d -> %8d ", 0, 1 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); printf( "Iter %2d -> %8d ", 1, Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Beg = 1; End = 10; for ( i = 2; i <= 100; i++ ) { if ( Beg == End ) break; for ( k = Beg; k < End; k++ ) { pPrev = (char *)Vec_IntEntryP(vData, 6*k); for ( v = 0; v < 9; v++ ) { pState = (char *)Vec_IntEntryP(vData, 6*Counter); Abc_StatePerm( pPrev, pFirst[v], pState ); State = Abc_CubeGenerateSign( pState ); if ( !Abc_DataHasBit(pHash, State) ) Abc_DataXorBit(pHash, State), Counter++; if ( Counter == (1<<22) ) { printf( "Did not converge. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return; } } } Beg = End; End = Counter; printf( "Iter %2d -> %8d ", i, Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } Vec_IntFree( vData ); ABC_FREE( pHash ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilDsd.c000066400000000000000000002012601300674244400246730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [File management utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "extra.h" #include "misc/vec/vec.h" #include "misc/vec/vecHsh.h" #include "misc/util/utilTruth.h" #include "bool/rsb/rsb.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Sdm_Dsd_t_ Sdm_Dsd_t; struct Sdm_Dsd_t_ { int nVars; // support size int nAnds; // the number of AND gates int nClauses; // the number of CNF clauses word uTruth; // truth table char * pStr; // description }; #define DSD_CLASS_NUM 595 static Sdm_Dsd_t s_DsdClass6[DSD_CLASS_NUM] = { { 0, 0, 1, ABC_CONST(0x0000000000000000), "0" }, // 0 { 1, 0, 2, ABC_CONST(0xAAAAAAAAAAAAAAAA), "a" }, // 1 { 2, 1, 3, ABC_CONST(0x8888888888888888), "(ab)" }, // 2 { 2, 3, 4, ABC_CONST(0x6666666666666666), "[ab]" }, // 3 { 3, 2, 4, ABC_CONST(0x8080808080808080), "(abc)" }, // 4 { 3, 2, 4, ABC_CONST(0x7070707070707070), "(!(ab)c)" }, // 5 { 3, 4, 6, ABC_CONST(0x7878787878787878), "[(ab)c]" }, // 6 { 3, 4, 5, ABC_CONST(0x6060606060606060), "([ab]c)" }, // 7 { 3, 6, 8, ABC_CONST(0x9696969696969696), "[abc]" }, // 8 { 3, 3, 4, ABC_CONST(0xCACACACACACACACA), "" }, // 9 { 4, 3, 5, ABC_CONST(0x8000800080008000), "(abcd)" }, // 10 { 4, 3, 5, ABC_CONST(0x7F007F007F007F00), "(!(abc)d)" }, // 11 { 4, 5, 8, ABC_CONST(0x7F807F807F807F80), "[(abc)d]" }, // 12 { 4, 3, 5, ABC_CONST(0x7000700070007000), "(!(ab)cd)" }, // 13 { 4, 3, 5, ABC_CONST(0x8F008F008F008F00), "(!(!(ab)c)d)" }, // 14 { 4, 5, 8, ABC_CONST(0x8F708F708F708F70), "[(!(ab)c)d]" }, // 15 { 4, 5, 7, ABC_CONST(0x7800780078007800), "([(ab)c]d)" }, // 16 { 4, 7, 12, ABC_CONST(0x8778877887788778), "[(ab)cd]" }, // 17 { 4, 5, 6, ABC_CONST(0x6000600060006000), "([ab]cd)" }, // 18 { 4, 5, 6, ABC_CONST(0x9F009F009F009F00), "(!([ab]c)d)" }, // 19 { 4, 7, 10, ABC_CONST(0x9F609F609F609F60), "[([ab]c)d]" }, // 20 { 4, 7, 9, ABC_CONST(0x9600960096009600), "([abc]d)" }, // 21 { 4, 9, 16, ABC_CONST(0x6996699669966996), "[abcd]" }, // 22 { 4, 4, 5, ABC_CONST(0xCA00CA00CA00CA00), "(d)" }, // 23 { 4, 6, 8, ABC_CONST(0x35CA35CA35CA35CA), "[d]" }, // 24 { 4, 3, 6, ABC_CONST(0x0777077707770777), "(!(ab)!(cd))" }, // 25 { 4, 5, 9, ABC_CONST(0x7888788878887888), "[(ab)(cd)]" }, // 26 { 4, 5, 7, ABC_CONST(0x0666066606660666), "([ab]!(cd))" }, // 27 { 4, 7, 8, ABC_CONST(0x0660066006600660), "([ab][cd])" }, // 28 { 4, 4, 6, ABC_CONST(0xCAAACAAACAAACAAA), "" }, // 29 { 4, 6, 8, ABC_CONST(0xACCAACCAACCAACCA), "" }, // 30 { 4, 4, 5, ABC_CONST(0xF088F088F088F088), "<(ab)cd>" }, // 31 { 4, 6, 6, ABC_CONST(0xF066F066F066F066), "<[ab]cd>" }, // 32 { 5, 4, 6, ABC_CONST(0x8000000080000000), "(abcde)" }, // 33 { 5, 4, 6, ABC_CONST(0x7FFF00007FFF0000), "(!(abcd)e)" }, // 34 { 5, 6, 10, ABC_CONST(0x7FFF80007FFF8000), "[(abcd)e]" }, // 35 { 5, 4, 6, ABC_CONST(0x7F0000007F000000), "(!(abc)de)" }, // 36 { 5, 4, 6, ABC_CONST(0x80FF000080FF0000), "(!(!(abc)d)e)" }, // 37 { 5, 6, 10, ABC_CONST(0x80FF7F0080FF7F00), "[(!(abc)d)e]" }, // 38 { 5, 6, 9, ABC_CONST(0x7F8000007F800000), "([(abc)d]e)" }, // 39 { 5, 8, 16, ABC_CONST(0x807F7F80807F7F80), "[(abc)de]" }, // 40 { 5, 4, 6, ABC_CONST(0x7000000070000000), "(!(ab)cde)" }, // 41 { 5, 4, 6, ABC_CONST(0x8FFF00008FFF0000), "(!(!(ab)cd)e)" }, // 42 { 5, 6, 10, ABC_CONST(0x8FFF70008FFF7000), "[(!(ab)cd)e]" }, // 43 { 5, 4, 6, ABC_CONST(0x8F0000008F000000), "(!(!(ab)c)de)" }, // 44 { 5, 4, 6, ABC_CONST(0x70FF000070FF0000), "(!(!(!(ab)c)d)e)" }, // 45 { 5, 6, 10, ABC_CONST(0x70FF8F0070FF8F00), "[(!(!(ab)c)d)e]" }, // 46 { 5, 6, 9, ABC_CONST(0x8F7000008F700000), "([(!(ab)c)d]e)" }, // 47 { 5, 8, 16, ABC_CONST(0x708F8F70708F8F70), "[(!(ab)c)de]" }, // 48 { 5, 6, 8, ABC_CONST(0x7800000078000000), "([(ab)c]de)" }, // 49 { 5, 6, 8, ABC_CONST(0x87FF000087FF0000), "(!([(ab)c]d)e)" }, // 50 { 5, 8, 14, ABC_CONST(0x87FF780087FF7800), "[([(ab)c]d)e]" }, // 51 { 5, 8, 13, ABC_CONST(0x8778000087780000), "([(ab)cd]e)" }, // 52 { 5, 10, 24, ABC_CONST(0x7887877878878778), "[(ab)cde]" }, // 53 { 5, 6, 7, ABC_CONST(0x6000000060000000), "([ab]cde)" }, // 54 { 5, 6, 7, ABC_CONST(0x9FFF00009FFF0000), "(!([ab]cd)e)" }, // 55 { 5, 8, 12, ABC_CONST(0x9FFF60009FFF6000), "[([ab]cd)e]" }, // 56 { 5, 6, 7, ABC_CONST(0x9F0000009F000000), "(!([ab]c)de)" }, // 57 { 5, 6, 7, ABC_CONST(0x60FF000060FF0000), "(!(!([ab]c)d)e)" }, // 58 { 5, 8, 12, ABC_CONST(0x60FF9F0060FF9F00), "[(!([ab]c)d)e]" }, // 59 { 5, 8, 11, ABC_CONST(0x9F6000009F600000), "([([ab]c)d]e)" }, // 60 { 5, 10, 20, ABC_CONST(0x609F9F60609F9F60), "[([ab]c)de]" }, // 61 { 5, 8, 10, ABC_CONST(0x9600000096000000), "([abc]de)" }, // 62 { 5, 8, 10, ABC_CONST(0x69FF000069FF0000), "(!([abc]d)e)" }, // 63 { 5, 10, 18, ABC_CONST(0x69FF960069FF9600), "[([abc]d)e]" }, // 64 { 5, 10, 17, ABC_CONST(0x6996000069960000), "([abcd]e)" }, // 65 { 5, 12, 32, ABC_CONST(0x9669699696696996), "[abcde]" }, // 66 { 5, 5, 6, ABC_CONST(0xCA000000CA000000), "(de)" }, // 67 { 5, 5, 6, ABC_CONST(0x35FF000035FF0000), "(!(d)e)" }, // 68 { 5, 7, 10, ABC_CONST(0x35FFCA0035FFCA00), "[(d)e]" }, // 69 { 5, 7, 9, ABC_CONST(0x35CA000035CA0000), "([d]e)" }, // 70 { 5, 9, 16, ABC_CONST(0xCA3535CACA3535CA), "[de]" }, // 71 { 5, 4, 7, ABC_CONST(0x0777000007770000), "(!(ab)!(cd)e)" }, // 72 { 5, 4, 7, ABC_CONST(0xF8880000F8880000), "(!(!(ab)!(cd))e)" }, // 73 { 5, 6, 12, ABC_CONST(0xF8880777F8880777), "[(!(ab)!(cd))e]" }, // 74 { 5, 6, 10, ABC_CONST(0x7888000078880000), "([(ab)(cd)]e)" }, // 75 { 5, 6, 10, ABC_CONST(0x8777000087770000), "(![(ab)(cd)]e)" }, // 76 { 5, 8, 18, ABC_CONST(0x8777788887777888), "[(ab)(cd)e]" }, // 77 { 5, 6, 8, ABC_CONST(0x0666000006660000), "([ab]!(cd)e)" }, // 78 { 5, 6, 8, ABC_CONST(0xF9990000F9990000), "(!([ab]!(cd))e)" }, // 79 { 5, 8, 14, ABC_CONST(0xF9990666F9990666), "[([ab]!(cd))e]" }, // 80 { 5, 8, 9, ABC_CONST(0x0660000006600000), "([ab][cd]e)" }, // 81 { 5, 8, 9, ABC_CONST(0xF99F0000F99F0000), "(!([ab][cd])e)" }, // 82 { 5, 10, 16, ABC_CONST(0xF99F0660F99F0660), "[([ab][cd])e]" }, // 83 { 5, 5, 7, ABC_CONST(0xCAAA0000CAAA0000), "(e)" }, // 84 { 5, 7, 12, ABC_CONST(0x3555CAAA3555CAAA), "[e]" }, // 85 { 5, 7, 9, ABC_CONST(0xACCA0000ACCA0000), "(e)" }, // 86 { 5, 9, 16, ABC_CONST(0x5335ACCA5335ACCA), "[e]" }, // 87 { 5, 5, 6, ABC_CONST(0xF0880000F0880000), "(<(ab)cd>e)" }, // 88 { 5, 5, 6, ABC_CONST(0x0F7700000F770000), "(!<(ab)cd>e)" }, // 89 { 5, 7, 10, ABC_CONST(0x0F77F0880F77F088), "[<(ab)cd>e]" }, // 90 { 5, 7, 7, ABC_CONST(0xF0660000F0660000), "(<[ab]cd>e)" }, // 91 { 5, 9, 12, ABC_CONST(0x0F99F0660F99F066), "[<[ab]cd>e]" }, // 92 { 5, 4, 8, ABC_CONST(0x007F7F7F007F7F7F), "(!(abc)!(de))" }, // 93 { 5, 6, 12, ABC_CONST(0x7F8080807F808080), "[(abc)(de)]" }, // 94 { 5, 4, 7, ABC_CONST(0x008F8F8F008F8F8F), "(!(!(ab)c)!(de))" }, // 95 { 5, 6, 12, ABC_CONST(0x8F7070708F707070), "[(!(ab)c)(de)]" }, // 96 { 5, 6, 10, ABC_CONST(0x0078787800787878), "([(ab)c]!(de))" }, // 97 { 5, 6, 9, ABC_CONST(0x009F9F9F009F9F9F), "(!([ab]c)!(de))" }, // 98 { 5, 8, 15, ABC_CONST(0x9F6060609F606060), "[([ab]c)(de)]" }, // 99 { 5, 8, 13, ABC_CONST(0x0096969600969696), "([abc]!(de))" }, // 100 { 5, 5, 7, ABC_CONST(0x00CACACA00CACACA), "(!(de))" }, // 101 { 5, 7, 12, ABC_CONST(0x35CACACA35CACACA), "[(de)]" }, // 102 { 5, 6, 9, ABC_CONST(0x007F7F00007F7F00), "(!(abc)[de])" }, // 103 { 5, 6, 8, ABC_CONST(0x008F8F00008F8F00), "(!(!(ab)c)[de])" }, // 104 { 5, 8, 11, ABC_CONST(0x0078780000787800), "([(ab)c][de])" }, // 105 { 5, 8, 10, ABC_CONST(0x009F9F00009F9F00), "(!([ab]c)[de])" }, // 106 { 5, 10, 14, ABC_CONST(0x0096960000969600), "([abc][de])" }, // 107 { 5, 7, 8, ABC_CONST(0x00CACA0000CACA00), "([de])" }, // 108 { 5, 5, 8, ABC_CONST(0xCAAAAAAACAAAAAAA), "" }, // 109 { 5, 5, 8, ABC_CONST(0xACCCAAAAACCCAAAA), "" }, // 110 { 5, 7, 12, ABC_CONST(0xACCCCAAAACCCCAAA), "" }, // 111 { 5, 7, 10, ABC_CONST(0xACCAAAAAACCAAAAA), "" }, // 112 { 5, 9, 16, ABC_CONST(0xCAACACCACAACACCA), "" }, // 113 { 5, 6, 8, ABC_CONST(0xCCAACACACCAACACA), ">" }, // 114 { 5, 5, 7, ABC_CONST(0xC0AAAAAAC0AAAAAA), "" }, // 115 { 5, 7, 8, ABC_CONST(0x3CAAAAAA3CAAAAAA), "" }, // 116 { 5, 5, 8, ABC_CONST(0xF0888888F0888888), "<(ab)c(de)>" }, // 117 { 5, 7, 10, ABC_CONST(0x88F0F08888F0F088), "<(ab)c[de]>" }, // 118 { 5, 7, 10, ABC_CONST(0xF0666666F0666666), "<[ab]c(de)>" }, // 119 { 5, 9, 12, ABC_CONST(0x66F0F06666F0F066), "<[ab]c[de]>" }, // 120 { 5, 5, 6, ABC_CONST(0xF0008888F0008888), "<(ab)(cd)e>" }, // 121 { 5, 5, 6, ABC_CONST(0xF0007777F0007777), "" }, // 122 { 5, 7, 7, ABC_CONST(0xF0006666F0006666), "<[ab](cd)e>" }, // 123 { 5, 9, 8, ABC_CONST(0x0FF066660FF06666), "<[ab][cd]e>" }, // 124 { 5, 5, 6, ABC_CONST(0xFF008080FF008080), "<(abc)de>" }, // 125 { 5, 5, 6, ABC_CONST(0xFF007070FF007070), "<(!(ab)c)de>" }, // 126 { 5, 7, 8, ABC_CONST(0xFF007878FF007878), "<[(ab)c]de>" }, // 127 { 5, 7, 7, ABC_CONST(0xFF006060FF006060), "<([ab]c)de>" }, // 128 { 5, 9, 10, ABC_CONST(0xFF009696FF009696), "<[abc]de>" }, // 129 { 5, 6, 6, ABC_CONST(0xFF00CACAFF00CACA), "<de>" }, // 130 { 6, 5, 7, ABC_CONST(0x8000000000000000), "(abcdef)" }, // 131 { 6, 5, 7, ABC_CONST(0x7FFFFFFF00000000), "(!(abcde)f)" }, // 132 { 6, 7, 12, ABC_CONST(0x7FFFFFFF80000000), "[(abcde)f]" }, // 133 { 6, 5, 7, ABC_CONST(0x7FFF000000000000), "(!(abcd)ef)" }, // 134 { 6, 5, 7, ABC_CONST(0x8000FFFF00000000), "(!(!(abcd)e)f)" }, // 135 { 6, 7, 12, ABC_CONST(0x8000FFFF7FFF0000), "[(!(abcd)e)f]" }, // 136 { 6, 7, 11, ABC_CONST(0x7FFF800000000000), "([(abcd)e]f)" }, // 137 { 6, 9, 20, ABC_CONST(0x80007FFF7FFF8000), "[(abcd)ef]" }, // 138 { 6, 5, 7, ABC_CONST(0x7F00000000000000), "(!(abc)def)" }, // 139 { 6, 5, 7, ABC_CONST(0x80FFFFFF00000000), "(!(!(abc)de)f)" }, // 140 { 6, 7, 12, ABC_CONST(0x80FFFFFF7F000000), "[(!(abc)de)f]" }, // 141 { 6, 5, 7, ABC_CONST(0x80FF000000000000), "(!(!(abc)d)ef)" }, // 142 { 6, 5, 7, ABC_CONST(0x7F00FFFF00000000), "(!(!(!(abc)d)e)f)" }, // 143 { 6, 7, 12, ABC_CONST(0x7F00FFFF80FF0000), "[(!(!(abc)d)e)f]" }, // 144 { 6, 7, 11, ABC_CONST(0x80FF7F0000000000), "([(!(abc)d)e]f)" }, // 145 { 6, 9, 20, ABC_CONST(0x7F0080FF80FF7F00), "[(!(abc)d)ef]" }, // 146 { 6, 7, 10, ABC_CONST(0x7F80000000000000), "([(abc)d]ef)" }, // 147 { 6, 7, 10, ABC_CONST(0x807FFFFF00000000), "(!([(abc)d]e)f)" }, // 148 { 6, 9, 18, ABC_CONST(0x807FFFFF7F800000), "[([(abc)d]e)f]" }, // 149 { 6, 9, 17, ABC_CONST(0x807F7F8000000000), "([(abc)de]f)" }, // 150 { 6, 11, 32, ABC_CONST(0x7F80807F807F7F80), "[(abc)def]" }, // 151 { 6, 5, 7, ABC_CONST(0x7000000000000000), "(!(ab)cdef)" }, // 152 { 6, 5, 7, ABC_CONST(0x8FFFFFFF00000000), "(!(!(ab)cde)f)" }, // 153 { 6, 7, 12, ABC_CONST(0x8FFFFFFF70000000), "[(!(ab)cde)f]" }, // 154 { 6, 5, 7, ABC_CONST(0x8FFF000000000000), "(!(!(ab)cd)ef)" }, // 155 { 6, 5, 7, ABC_CONST(0x7000FFFF00000000), "(!(!(!(ab)cd)e)f)" }, // 156 { 6, 7, 12, ABC_CONST(0x7000FFFF8FFF0000), "[(!(!(ab)cd)e)f]" }, // 157 { 6, 7, 11, ABC_CONST(0x8FFF700000000000), "([(!(ab)cd)e]f)" }, // 158 { 6, 9, 20, ABC_CONST(0x70008FFF8FFF7000), "[(!(ab)cd)ef]" }, // 159 { 6, 5, 7, ABC_CONST(0x8F00000000000000), "(!(!(ab)c)def)" }, // 160 { 6, 5, 7, ABC_CONST(0x70FFFFFF00000000), "(!(!(!(ab)c)de)f)" }, // 161 { 6, 7, 12, ABC_CONST(0x70FFFFFF8F000000), "[(!(!(ab)c)de)f]" }, // 162 { 6, 5, 7, ABC_CONST(0x70FF000000000000), "(!(!(!(ab)c)d)ef)" }, // 163 { 6, 5, 7, ABC_CONST(0x8F00FFFF00000000), "(!(!(!(!(ab)c)d)e)f)" }, // 164 { 6, 7, 12, ABC_CONST(0x8F00FFFF70FF0000), "[(!(!(!(ab)c)d)e)f]" }, // 165 { 6, 7, 11, ABC_CONST(0x70FF8F0000000000), "([(!(!(ab)c)d)e]f)" }, // 166 { 6, 9, 20, ABC_CONST(0x8F0070FF70FF8F00), "[(!(!(ab)c)d)ef]" }, // 167 { 6, 7, 10, ABC_CONST(0x8F70000000000000), "([(!(ab)c)d]ef)" }, // 168 { 6, 7, 10, ABC_CONST(0x708FFFFF00000000), "(!([(!(ab)c)d]e)f)" }, // 169 { 6, 9, 18, ABC_CONST(0x708FFFFF8F700000), "[([(!(ab)c)d]e)f]" }, // 170 { 6, 9, 17, ABC_CONST(0x708F8F7000000000), "([(!(ab)c)de]f)" }, // 171 { 6, 11, 32, ABC_CONST(0x8F70708F708F8F70), "[(!(ab)c)def]" }, // 172 { 6, 7, 9, ABC_CONST(0x7800000000000000), "([(ab)c]def)" }, // 173 { 6, 7, 9, ABC_CONST(0x87FFFFFF00000000), "(!([(ab)c]de)f)" }, // 174 { 6, 9, 16, ABC_CONST(0x87FFFFFF78000000), "[([(ab)c]de)f]" }, // 175 { 6, 7, 9, ABC_CONST(0x87FF000000000000), "(!([(ab)c]d)ef)" }, // 176 { 6, 7, 9, ABC_CONST(0x7800FFFF00000000), "(!(!([(ab)c]d)e)f)" }, // 177 { 6, 9, 16, ABC_CONST(0x7800FFFF87FF0000), "[(!([(ab)c]d)e)f]" }, // 178 { 6, 9, 15, ABC_CONST(0x87FF780000000000), "([([(ab)c]d)e]f)" }, // 179 { 6, 11, 28, ABC_CONST(0x780087FF87FF7800), "[([(ab)c]d)ef]" }, // 180 { 6, 9, 14, ABC_CONST(0x8778000000000000), "([(ab)cd]ef)" }, // 181 { 6, 9, 14, ABC_CONST(0x7887FFFF00000000), "(!([(ab)cd]e)f)" }, // 182 { 6, 11, 26, ABC_CONST(0x7887FFFF87780000), "[([(ab)cd]e)f]" }, // 183 { 6, 11, 25, ABC_CONST(0x7887877800000000), "([(ab)cde]f)" }, // 184 { 6, 13, 48, ABC_CONST(0x8778788778878778), "[(ab)cdef]" }, // 185 { 6, 7, 8, ABC_CONST(0x6000000000000000), "([ab]cdef)" }, // 186 { 6, 7, 8, ABC_CONST(0x9FFFFFFF00000000), "(!([ab]cde)f)" }, // 187 { 6, 9, 14, ABC_CONST(0x9FFFFFFF60000000), "[([ab]cde)f]" }, // 188 { 6, 7, 8, ABC_CONST(0x9FFF000000000000), "(!([ab]cd)ef)" }, // 189 { 6, 7, 8, ABC_CONST(0x6000FFFF00000000), "(!(!([ab]cd)e)f)" }, // 190 { 6, 9, 14, ABC_CONST(0x6000FFFF9FFF0000), "[(!([ab]cd)e)f]" }, // 191 { 6, 9, 13, ABC_CONST(0x9FFF600000000000), "([([ab]cd)e]f)" }, // 192 { 6, 11, 24, ABC_CONST(0x60009FFF9FFF6000), "[([ab]cd)ef]" }, // 193 { 6, 7, 8, ABC_CONST(0x9F00000000000000), "(!([ab]c)def)" }, // 194 { 6, 7, 8, ABC_CONST(0x60FFFFFF00000000), "(!(!([ab]c)de)f)" }, // 195 { 6, 9, 14, ABC_CONST(0x60FFFFFF9F000000), "[(!([ab]c)de)f]" }, // 196 { 6, 7, 8, ABC_CONST(0x60FF000000000000), "(!(!([ab]c)d)ef)" }, // 197 { 6, 7, 8, ABC_CONST(0x9F00FFFF00000000), "(!(!(!([ab]c)d)e)f)" }, // 198 { 6, 9, 14, ABC_CONST(0x9F00FFFF60FF0000), "[(!(!([ab]c)d)e)f]" }, // 199 { 6, 9, 13, ABC_CONST(0x60FF9F0000000000), "([(!([ab]c)d)e]f)" }, // 200 { 6, 11, 24, ABC_CONST(0x9F0060FF60FF9F00), "[(!([ab]c)d)ef]" }, // 201 { 6, 9, 12, ABC_CONST(0x9F60000000000000), "([([ab]c)d]ef)" }, // 202 { 6, 9, 12, ABC_CONST(0x609FFFFF00000000), "(!([([ab]c)d]e)f)" }, // 203 { 6, 11, 22, ABC_CONST(0x609FFFFF9F600000), "[([([ab]c)d]e)f]" }, // 204 { 6, 11, 21, ABC_CONST(0x609F9F6000000000), "([([ab]c)de]f)" }, // 205 { 6, 13, 40, ABC_CONST(0x9F60609F609F9F60), "[([ab]c)def]" }, // 206 { 6, 9, 11, ABC_CONST(0x9600000000000000), "([abc]def)" }, // 207 { 6, 9, 11, ABC_CONST(0x69FFFFFF00000000), "(!([abc]de)f)" }, // 208 { 6, 11, 20, ABC_CONST(0x69FFFFFF96000000), "[([abc]de)f]" }, // 209 { 6, 9, 11, ABC_CONST(0x69FF000000000000), "(!([abc]d)ef)" }, // 210 { 6, 9, 11, ABC_CONST(0x9600FFFF00000000), "(!(!([abc]d)e)f)" }, // 211 { 6, 11, 20, ABC_CONST(0x9600FFFF69FF0000), "[(!([abc]d)e)f]" }, // 212 { 6, 11, 19, ABC_CONST(0x69FF960000000000), "([([abc]d)e]f)" }, // 213 { 6, 13, 36, ABC_CONST(0x960069FF69FF9600), "[([abc]d)ef]" }, // 214 { 6, 11, 18, ABC_CONST(0x6996000000000000), "([abcd]ef)" }, // 215 { 6, 11, 18, ABC_CONST(0x9669FFFF00000000), "(!([abcd]e)f)" }, // 216 { 6, 13, 34, ABC_CONST(0x9669FFFF69960000), "[([abcd]e)f]" }, // 217 { 6, 13, 33, ABC_CONST(0x9669699600000000), "([abcde]f)" }, // 218 { 6, 15, 64, ABC_CONST(0x6996966996696996), "[abcdef]" }, // 219 { 6, 6, 7, ABC_CONST(0xCA00000000000000), "(def)" }, // 220 { 6, 6, 7, ABC_CONST(0x35FFFFFF00000000), "(!(de)f)" }, // 221 { 6, 8, 12, ABC_CONST(0x35FFFFFFCA000000), "[(de)f]" }, // 222 { 6, 6, 7, ABC_CONST(0x35FF000000000000), "(!(d)ef)" }, // 223 { 6, 6, 7, ABC_CONST(0xCA00FFFF00000000), "(!(!(d)e)f)" }, // 224 { 6, 8, 12, ABC_CONST(0xCA00FFFF35FF0000), "[(!(d)e)f]" }, // 225 { 6, 8, 11, ABC_CONST(0x35FFCA0000000000), "([(d)e]f)" }, // 226 { 6, 10, 20, ABC_CONST(0xCA0035FF35FFCA00), "[(d)ef]" }, // 227 { 6, 8, 10, ABC_CONST(0x35CA000000000000), "([d]ef)" }, // 228 { 6, 8, 10, ABC_CONST(0xCA35FFFF00000000), "(!([d]e)f)" }, // 229 { 6, 10, 18, ABC_CONST(0xCA35FFFF35CA0000), "[([d]e)f]" }, // 230 { 6, 10, 17, ABC_CONST(0xCA3535CA00000000), "([de]f)" }, // 231 { 6, 12, 32, ABC_CONST(0x35CACA35CA3535CA), "[def]" }, // 232 { 6, 5, 8, ABC_CONST(0x0777000000000000), "(!(ab)!(cd)ef)" }, // 233 { 6, 5, 8, ABC_CONST(0xF888FFFF00000000), "(!(!(ab)!(cd)e)f)" }, // 234 { 6, 7, 14, ABC_CONST(0xF888FFFF07770000), "[(!(ab)!(cd)e)f]" }, // 235 { 6, 5, 8, ABC_CONST(0xF888000000000000), "(!(!(ab)!(cd))ef)" }, // 236 { 6, 5, 8, ABC_CONST(0x0777FFFF00000000), "(!(!(!(ab)!(cd))e)f)" }, // 237 { 6, 7, 14, ABC_CONST(0x0777FFFFF8880000), "[(!(!(ab)!(cd))e)f]" }, // 238 { 6, 7, 13, ABC_CONST(0xF888077700000000), "([(!(ab)!(cd))e]f)" }, // 239 { 6, 9, 24, ABC_CONST(0x0777F888F8880777), "[(!(ab)!(cd))ef]" }, // 240 { 6, 7, 11, ABC_CONST(0x7888000000000000), "([(ab)(cd)]ef)" }, // 241 { 6, 7, 11, ABC_CONST(0x8777FFFF00000000), "(!([(ab)(cd)]e)f)" }, // 242 { 6, 9, 20, ABC_CONST(0x8777FFFF78880000), "[([(ab)(cd)]e)f]" }, // 243 { 6, 7, 11, ABC_CONST(0x8777000000000000), "(![(ab)(cd)]ef)" }, // 244 { 6, 7, 11, ABC_CONST(0x7888FFFF00000000), "(!(![(ab)(cd)]e)f)" }, // 245 { 6, 9, 20, ABC_CONST(0x7888FFFF87770000), "[(![(ab)(cd)]e)f]" }, // 246 { 6, 9, 19, ABC_CONST(0x8777788800000000), "([(ab)(cd)e]f)" }, // 247 { 6, 11, 36, ABC_CONST(0x7888877787777888), "[(ab)(cd)ef]" }, // 248 { 6, 7, 9, ABC_CONST(0x0666000000000000), "([ab]!(cd)ef)" }, // 249 { 6, 7, 9, ABC_CONST(0xF999FFFF00000000), "(!([ab]!(cd)e)f)" }, // 250 { 6, 9, 16, ABC_CONST(0xF999FFFF06660000), "[([ab]!(cd)e)f]" }, // 251 { 6, 7, 9, ABC_CONST(0xF999000000000000), "(!([ab]!(cd))ef)" }, // 252 { 6, 7, 9, ABC_CONST(0x0666FFFF00000000), "(!(!([ab]!(cd))e)f)" }, // 253 { 6, 9, 16, ABC_CONST(0x0666FFFFF9990000), "[(!([ab]!(cd))e)f]" }, // 254 { 6, 9, 15, ABC_CONST(0xF999066600000000), "([([ab]!(cd))e]f)" }, // 255 { 6, 11, 28, ABC_CONST(0x0666F999F9990666), "[([ab]!(cd))ef]" }, // 256 { 6, 9, 10, ABC_CONST(0x0660000000000000), "([ab][cd]ef)" }, // 257 { 6, 9, 10, ABC_CONST(0xF99FFFFF00000000), "(!([ab][cd]e)f)" }, // 258 { 6, 11, 18, ABC_CONST(0xF99FFFFF06600000), "[([ab][cd]e)f]" }, // 259 { 6, 9, 10, ABC_CONST(0xF99F000000000000), "(!([ab][cd])ef)" }, // 260 { 6, 9, 10, ABC_CONST(0x0660FFFF00000000), "(!(!([ab][cd])e)f)" }, // 261 { 6, 11, 18, ABC_CONST(0x0660FFFFF99F0000), "[(!([ab][cd])e)f]" }, // 262 { 6, 11, 17, ABC_CONST(0xF99F066000000000), "([([ab][cd])e]f)" }, // 263 { 6, 13, 32, ABC_CONST(0x0660F99FF99F0660), "[([ab][cd])ef]" }, // 264 { 6, 6, 8, ABC_CONST(0xCAAA000000000000), "(ef)" }, // 265 { 6, 6, 8, ABC_CONST(0x3555FFFF00000000), "(!(e)f)" }, // 266 { 6, 8, 14, ABC_CONST(0x3555FFFFCAAA0000), "[(e)f]" }, // 267 { 6, 8, 13, ABC_CONST(0x3555CAAA00000000), "([e]f)" }, // 268 { 6, 10, 24, ABC_CONST(0xCAAA35553555CAAA), "[ef]" }, // 269 { 6, 8, 10, ABC_CONST(0xACCA000000000000), "(ef)" }, // 270 { 6, 8, 10, ABC_CONST(0x5335FFFF00000000), "(!(e)f)" }, // 271 { 6, 10, 18, ABC_CONST(0x5335FFFFACCA0000), "[(e)f]" }, // 272 { 6, 10, 17, ABC_CONST(0x5335ACCA00000000), "([e]f)" }, // 273 { 6, 12, 32, ABC_CONST(0xACCA53355335ACCA), "[ef]" }, // 274 { 6, 6, 7, ABC_CONST(0xF088000000000000), "(<(ab)cd>ef)" }, // 275 { 6, 6, 7, ABC_CONST(0x0F77FFFF00000000), "(!(<(ab)cd>e)f)" }, // 276 { 6, 8, 12, ABC_CONST(0x0F77FFFFF0880000), "[(<(ab)cd>e)f]" }, // 277 { 6, 6, 7, ABC_CONST(0x0F77000000000000), "(!<(ab)cd>ef)" }, // 278 { 6, 6, 7, ABC_CONST(0xF088FFFF00000000), "(!(!<(ab)cd>e)f)" }, // 279 { 6, 8, 12, ABC_CONST(0xF088FFFF0F770000), "[(!<(ab)cd>e)f]" }, // 280 { 6, 8, 11, ABC_CONST(0x0F77F08800000000), "([<(ab)cd>e]f)" }, // 281 { 6, 10, 20, ABC_CONST(0xF0880F770F77F088), "[<(ab)cd>ef]" }, // 282 { 6, 8, 8, ABC_CONST(0xF066000000000000), "(<[ab]cd>ef)" }, // 283 { 6, 8, 8, ABC_CONST(0x0F99FFFF00000000), "(!(<[ab]cd>e)f)" }, // 284 { 6, 10, 14, ABC_CONST(0x0F99FFFFF0660000), "[(<[ab]cd>e)f]" }, // 285 { 6, 10, 13, ABC_CONST(0x0F99F06600000000), "([<[ab]cd>e]f)" }, // 286 { 6, 12, 24, ABC_CONST(0xF0660F990F99F066), "[<[ab]cd>ef]" }, // 287 { 6, 5, 9, ABC_CONST(0x007F7F7F00000000), "(!(abc)!(de)f)" }, // 288 { 6, 5, 9, ABC_CONST(0xFF80808000000000), "(!(!(abc)!(de))f)" }, // 289 { 6, 7, 16, ABC_CONST(0xFF808080007F7F7F), "[(!(abc)!(de))f]" }, // 290 { 6, 7, 13, ABC_CONST(0x7F80808000000000), "([(abc)(de)]f)" }, // 291 { 6, 7, 13, ABC_CONST(0x807F7F7F00000000), "(![(abc)(de)]f)" }, // 292 { 6, 9, 24, ABC_CONST(0x807F7F7F7F808080), "[(abc)(de)f]" }, // 293 { 6, 5, 8, ABC_CONST(0x008F8F8F00000000), "(!(!(ab)c)!(de)f)" }, // 294 { 6, 5, 8, ABC_CONST(0xFF70707000000000), "(!(!(!(ab)c)!(de))f)" }, // 295 { 6, 7, 14, ABC_CONST(0xFF707070008F8F8F), "[(!(!(ab)c)!(de))f]" }, // 296 { 6, 7, 13, ABC_CONST(0x8F70707000000000), "([(!(ab)c)(de)]f)" }, // 297 { 6, 7, 13, ABC_CONST(0x708F8F8F00000000), "(![(!(ab)c)(de)]f)" }, // 298 { 6, 9, 24, ABC_CONST(0x708F8F8F8F707070), "[(!(ab)c)(de)f]" }, // 299 { 6, 7, 11, ABC_CONST(0x0078787800000000), "([(ab)c]!(de)f)" }, // 300 { 6, 7, 11, ABC_CONST(0xFF87878700000000), "(!([(ab)c]!(de))f)" }, // 301 { 6, 9, 20, ABC_CONST(0xFF87878700787878), "[([(ab)c]!(de))f]" }, // 302 { 6, 7, 10, ABC_CONST(0x009F9F9F00000000), "(!([ab]c)!(de)f)" }, // 303 { 6, 7, 10, ABC_CONST(0xFF60606000000000), "(!(!([ab]c)!(de))f)" }, // 304 { 6, 9, 18, ABC_CONST(0xFF606060009F9F9F), "[(!([ab]c)!(de))f]" }, // 305 { 6, 9, 16, ABC_CONST(0x9F60606000000000), "([([ab]c)(de)]f)" }, // 306 { 6, 9, 16, ABC_CONST(0x609F9F9F00000000), "(![([ab]c)(de)]f)" }, // 307 { 6, 11, 30, ABC_CONST(0x609F9F9F9F606060), "[([ab]c)(de)f]" }, // 308 { 6, 9, 14, ABC_CONST(0x0096969600000000), "([abc]!(de)f)" }, // 309 { 6, 9, 14, ABC_CONST(0xFF69696900000000), "(!([abc]!(de))f)" }, // 310 { 6, 11, 26, ABC_CONST(0xFF69696900969696), "[([abc]!(de))f]" }, // 311 { 6, 6, 8, ABC_CONST(0x00CACACA00000000), "(!(de)f)" }, // 312 { 6, 6, 8, ABC_CONST(0xFF35353500000000), "(!(!(de))f)" }, // 313 { 6, 8, 14, ABC_CONST(0xFF35353500CACACA), "[(!(de))f]" }, // 314 { 6, 8, 13, ABC_CONST(0x35CACACA00000000), "([(de)]f)" }, // 315 { 6, 10, 24, ABC_CONST(0xCA35353535CACACA), "[(de)f]" }, // 316 { 6, 7, 10, ABC_CONST(0x007F7F0000000000), "(!(abc)[de]f)" }, // 317 { 6, 7, 10, ABC_CONST(0xFF8080FF00000000), "(!(!(abc)[de])f)" }, // 318 { 6, 9, 18, ABC_CONST(0xFF8080FF007F7F00), "[(!(abc)[de])f]" }, // 319 { 6, 7, 9, ABC_CONST(0x008F8F0000000000), "(!(!(ab)c)[de]f)" }, // 320 { 6, 7, 9, ABC_CONST(0xFF7070FF00000000), "(!(!(!(ab)c)[de])f)" }, // 321 { 6, 9, 16, ABC_CONST(0xFF7070FF008F8F00), "[(!(!(ab)c)[de])f]" }, // 322 { 6, 9, 12, ABC_CONST(0x0078780000000000), "([(ab)c][de]f)" }, // 323 { 6, 9, 12, ABC_CONST(0xFF8787FF00000000), "(!([(ab)c][de])f)" }, // 324 { 6, 11, 22, ABC_CONST(0xFF8787FF00787800), "[([(ab)c][de])f]" }, // 325 { 6, 9, 11, ABC_CONST(0x009F9F0000000000), "(!([ab]c)[de]f)" }, // 326 { 6, 9, 11, ABC_CONST(0xFF6060FF00000000), "(!(!([ab]c)[de])f)" }, // 327 { 6, 11, 20, ABC_CONST(0xFF6060FF009F9F00), "[(!([ab]c)[de])f]" }, // 328 { 6, 11, 15, ABC_CONST(0x0096960000000000), "([abc][de]f)" }, // 329 { 6, 11, 15, ABC_CONST(0xFF6969FF00000000), "(!([abc][de])f)" }, // 330 { 6, 13, 28, ABC_CONST(0xFF6969FF00969600), "[([abc][de])f]" }, // 331 { 6, 8, 9, ABC_CONST(0x00CACA0000000000), "([de]f)" }, // 332 { 6, 8, 9, ABC_CONST(0xFF3535FF00000000), "(!([de])f)" }, // 333 { 6, 10, 16, ABC_CONST(0xFF3535FF00CACA00), "[([de])f]" }, // 334 { 6, 6, 9, ABC_CONST(0xCAAAAAAA00000000), "(f)" }, // 335 { 6, 8, 16, ABC_CONST(0x35555555CAAAAAAA), "[f]" }, // 336 { 6, 6, 9, ABC_CONST(0xACCCAAAA00000000), "(f)" }, // 337 { 6, 8, 16, ABC_CONST(0x53335555ACCCAAAA), "[f]" }, // 338 { 6, 8, 13, ABC_CONST(0xACCCCAAA00000000), "(f)" }, // 339 { 6, 10, 24, ABC_CONST(0x53333555ACCCCAAA), "[f]" }, // 340 { 6, 8, 11, ABC_CONST(0xACCAAAAA00000000), "(f)" }, // 341 { 6, 10, 20, ABC_CONST(0x53355555ACCAAAAA), "[f]" }, // 342 { 6, 10, 17, ABC_CONST(0xCAACACCA00000000), "(f)" }, // 343 { 6, 12, 32, ABC_CONST(0x35535335CAACACCA), "[f]" }, // 344 { 6, 7, 9, ABC_CONST(0xCCAACACA00000000), "(>f)" }, // 345 { 6, 9, 16, ABC_CONST(0x33553535CCAACACA), "[>f]" }, // 346 { 6, 6, 8, ABC_CONST(0xC0AAAAAA00000000), "(f)" }, // 347 { 6, 6, 8, ABC_CONST(0x3F55555500000000), "(!f)" }, // 348 { 6, 8, 14, ABC_CONST(0x3F555555C0AAAAAA), "[f]" }, // 349 { 6, 8, 9, ABC_CONST(0x3CAAAAAA00000000), "(f)" }, // 350 { 6, 10, 16, ABC_CONST(0xC35555553CAAAAAA), "[f]" }, // 351 { 6, 6, 9, ABC_CONST(0xF088888800000000), "(<(ab)c(de)>f)" }, // 352 { 6, 6, 9, ABC_CONST(0x0F77777700000000), "(!<(ab)c(de)>f)" }, // 353 { 6, 8, 16, ABC_CONST(0x0F777777F0888888), "[<(ab)c(de)>f]" }, // 354 { 6, 8, 11, ABC_CONST(0x88F0F08800000000), "(<(ab)c[de]>f)" }, // 355 { 6, 8, 11, ABC_CONST(0x770F0F7700000000), "(!<(ab)c[de]>f)" }, // 356 { 6, 10, 20, ABC_CONST(0x770F0F7788F0F088), "[<(ab)c[de]>f]" }, // 357 { 6, 8, 11, ABC_CONST(0xF066666600000000), "(<[ab]c(de)>f)" }, // 358 { 6, 10, 20, ABC_CONST(0x0F999999F0666666), "[<[ab]c(de)>f]" }, // 359 { 6, 10, 13, ABC_CONST(0x66F0F06600000000), "(<[ab]c[de]>f)" }, // 360 { 6, 12, 24, ABC_CONST(0x990F0F9966F0F066), "[<[ab]c[de]>f]" }, // 361 { 6, 6, 7, ABC_CONST(0xF000888800000000), "(<(ab)(cd)e>f)" }, // 362 { 6, 6, 7, ABC_CONST(0x0FFF777700000000), "(!<(ab)(cd)e>f)" }, // 363 { 6, 8, 12, ABC_CONST(0x0FFF7777F0008888), "[<(ab)(cd)e>f]" }, // 364 { 6, 6, 7, ABC_CONST(0xF000777700000000), "(f)" }, // 365 { 6, 8, 12, ABC_CONST(0x0FFF8888F0007777), "[f]" }, // 366 { 6, 8, 8, ABC_CONST(0xF000666600000000), "(<[ab](cd)e>f)" }, // 367 { 6, 8, 8, ABC_CONST(0x0FFF999900000000), "(!<[ab](cd)e>f)" }, // 368 { 6, 10, 14, ABC_CONST(0x0FFF9999F0006666), "[<[ab](cd)e>f]" }, // 369 { 6, 10, 9, ABC_CONST(0x0FF0666600000000), "(<[ab][cd]e>f)" }, // 370 { 6, 12, 16, ABC_CONST(0xF00F99990FF06666), "[<[ab][cd]e>f]" }, // 371 { 6, 6, 7, ABC_CONST(0xFF00808000000000), "(<(abc)de>f)" }, // 372 { 6, 6, 7, ABC_CONST(0x00FF7F7F00000000), "(!<(abc)de>f)" }, // 373 { 6, 8, 12, ABC_CONST(0x00FF7F7FFF008080), "[<(abc)de>f]" }, // 374 { 6, 6, 7, ABC_CONST(0xFF00707000000000), "(<(!(ab)c)de>f)" }, // 375 { 6, 6, 7, ABC_CONST(0x00FF8F8F00000000), "(!<(!(ab)c)de>f)" }, // 376 { 6, 8, 12, ABC_CONST(0x00FF8F8FFF007070), "[<(!(ab)c)de>f]" }, // 377 { 6, 8, 9, ABC_CONST(0xFF00787800000000), "(<[(ab)c]de>f)" }, // 378 { 6, 10, 16, ABC_CONST(0x00FF8787FF007878), "[<[(ab)c]de>f]" }, // 379 { 6, 8, 8, ABC_CONST(0xFF00606000000000), "(<([ab]c)de>f)" }, // 380 { 6, 8, 8, ABC_CONST(0x00FF9F9F00000000), "(!<([ab]c)de>f)" }, // 381 { 6, 10, 14, ABC_CONST(0x00FF9F9FFF006060), "[<([ab]c)de>f]" }, // 382 { 6, 10, 11, ABC_CONST(0xFF00969600000000), "(<[abc]de>f)" }, // 383 { 6, 12, 20, ABC_CONST(0x00FF6969FF009696), "[<[abc]de>f]" }, // 384 { 6, 7, 7, ABC_CONST(0xFF00CACA00000000), "(<de>f)" }, // 385 { 6, 9, 12, ABC_CONST(0x00FF3535FF00CACA), "[<de>f]" }, // 386 { 6, 5, 10, ABC_CONST(0x00007FFF7FFF7FFF), "(!(abcd)!(ef))" }, // 387 { 6, 7, 15, ABC_CONST(0x7FFF800080008000), "[(abcd)(ef)]" }, // 388 { 6, 5, 8, ABC_CONST(0x000080FF80FF80FF), "(!(!(abc)d)!(ef))" }, // 389 { 6, 7, 15, ABC_CONST(0x80FF7F007F007F00), "[(!(abc)d)(ef)]" }, // 390 { 6, 7, 13, ABC_CONST(0x00007F807F807F80), "([(abc)d]!(ef))" }, // 391 { 6, 5, 9, ABC_CONST(0x00008FFF8FFF8FFF), "(!(!(ab)cd)!(ef))" }, // 392 { 6, 7, 15, ABC_CONST(0x8FFF700070007000), "[(!(ab)cd)(ef)]" }, // 393 { 6, 5, 9, ABC_CONST(0x000070FF70FF70FF), "(!(!(!(ab)c)d)!(ef))" }, // 394 { 6, 7, 15, ABC_CONST(0x70FF8F008F008F00), "[(!(!(ab)c)d)(ef)]" }, // 395 { 6, 7, 13, ABC_CONST(0x00008F708F708F70), "([(!(ab)c)d]!(ef))" }, // 396 { 6, 7, 12, ABC_CONST(0x000087FF87FF87FF), "(!([(ab)c]d)!(ef))" }, // 397 { 6, 9, 21, ABC_CONST(0x87FF780078007800), "[([(ab)c]d)(ef)]" }, // 398 { 6, 9, 19, ABC_CONST(0x0000877887788778), "([(ab)cd]!(ef))" }, // 399 { 6, 7, 11, ABC_CONST(0x00009FFF9FFF9FFF), "(!([ab]cd)!(ef))" }, // 400 { 6, 9, 18, ABC_CONST(0x9FFF600060006000), "[([ab]cd)(ef)]" }, // 401 { 6, 7, 10, ABC_CONST(0x000060FF60FF60FF), "(!(!([ab]c)d)!(ef))" }, // 402 { 6, 9, 18, ABC_CONST(0x60FF9F009F009F00), "[(!([ab]c)d)(ef)]" }, // 403 { 6, 9, 16, ABC_CONST(0x00009F609F609F60), "([([ab]c)d]!(ef))" }, // 404 { 6, 9, 15, ABC_CONST(0x000069FF69FF69FF), "(!([abc]d)!(ef))" }, // 405 { 6, 11, 27, ABC_CONST(0x69FF960096009600), "[([abc]d)(ef)]" }, // 406 { 6, 11, 25, ABC_CONST(0x0000699669966996), "([abcd]!(ef))" }, // 407 { 6, 6, 9, ABC_CONST(0x000035FF35FF35FF), "(!(d)!(ef))" }, // 408 { 6, 8, 15, ABC_CONST(0x35FFCA00CA00CA00), "[(d)(ef)]" }, // 409 { 6, 8, 13, ABC_CONST(0x000035CA35CA35CA), "([d]!(ef))" }, // 410 { 6, 5, 11, ABC_CONST(0x0000077707770777), "(!(ab)!(cd)!(ef))" }, // 411 { 6, 5, 9, ABC_CONST(0x0000F888F888F888), "(!(!(ab)!(cd))!(ef))" }, // 412 { 6, 7, 18, ABC_CONST(0xF888077707770777), "[(!(ab)!(cd))(ef)]" }, // 413 { 6, 7, 14, ABC_CONST(0x0000788878887888), "([(ab)(cd)]!(ef))" }, // 414 { 6, 7, 15, ABC_CONST(0x0000877787778777), "(![(ab)(cd)]!(ef))" }, // 415 { 6, 9, 27, ABC_CONST(0x8777788878887888), "[(ab)(cd)(ef)]" }, // 416 { 6, 7, 12, ABC_CONST(0x0000066606660666), "([ab]!(cd)!(ef))" }, // 417 { 6, 7, 11, ABC_CONST(0x0000F999F999F999), "(!([ab]!(cd))!(ef))" }, // 418 { 6, 9, 21, ABC_CONST(0xF999066606660666), "[([ab]!(cd))(ef)]" }, // 419 { 6, 9, 13, ABC_CONST(0x0000066006600660), "([ab][cd]!(ef))" }, // 420 { 6, 9, 13, ABC_CONST(0x0000F99FF99FF99F), "(!([ab][cd])!(ef))" }, // 421 { 6, 11, 24, ABC_CONST(0xF99F066006600660), "[([ab][cd])(ef)]" }, // 422 { 6, 6, 10, ABC_CONST(0x0000CAAACAAACAAA), "(!(ef))" }, // 423 { 6, 8, 18, ABC_CONST(0x3555CAAACAAACAAA), "[(ef)]" }, // 424 { 6, 8, 13, ABC_CONST(0x0000ACCAACCAACCA), "(!(ef))" }, // 425 { 6, 10, 24, ABC_CONST(0x5335ACCAACCAACCA), "[(ef)]" }, // 426 { 6, 6, 8, ABC_CONST(0x0000F088F088F088), "(<(ab)cd>!(ef))" }, // 427 { 6, 6, 9, ABC_CONST(0x00000F770F770F77), "(!<(ab)cd>!(ef))" }, // 428 { 6, 8, 15, ABC_CONST(0x0F77F088F088F088), "[<(ab)cd>(ef)]" }, // 429 { 6, 8, 10, ABC_CONST(0x0000F066F066F066), "(<[ab]cd>!(ef))" }, // 430 { 6, 10, 18, ABC_CONST(0x0F99F066F066F066), "[<[ab]cd>(ef)]" }, // 431 { 6, 7, 11, ABC_CONST(0x00007FFF7FFF0000), "(!(abcd)[ef])" }, // 432 { 6, 7, 9, ABC_CONST(0x000080FF80FF0000), "(!(!(abc)d)[ef])" }, // 433 { 6, 9, 14, ABC_CONST(0x00007F807F800000), "([(abc)d][ef])" }, // 434 { 6, 7, 10, ABC_CONST(0x00008FFF8FFF0000), "(!(!(ab)cd)[ef])" }, // 435 { 6, 7, 10, ABC_CONST(0x000070FF70FF0000), "(!(!(!(ab)c)d)[ef])" }, // 436 { 6, 9, 14, ABC_CONST(0x00008F708F700000), "([(!(ab)c)d][ef])" }, // 437 { 6, 9, 13, ABC_CONST(0x000087FF87FF0000), "(!([(ab)c]d)[ef])" }, // 438 { 6, 11, 20, ABC_CONST(0x0000877887780000), "([(ab)cd][ef])" }, // 439 { 6, 9, 12, ABC_CONST(0x00009FFF9FFF0000), "(!([ab]cd)[ef])" }, // 440 { 6, 9, 11, ABC_CONST(0x000060FF60FF0000), "(!(!([ab]c)d)[ef])" }, // 441 { 6, 11, 17, ABC_CONST(0x00009F609F600000), "([([ab]c)d][ef])" }, // 442 { 6, 11, 16, ABC_CONST(0x000069FF69FF0000), "(!([abc]d)[ef])" }, // 443 { 6, 13, 26, ABC_CONST(0x0000699669960000), "([abcd][ef])" }, // 444 { 6, 8, 10, ABC_CONST(0x000035FF35FF0000), "(!(d)[ef])" }, // 445 { 6, 10, 14, ABC_CONST(0x000035CA35CA0000), "([d][ef])" }, // 446 { 6, 7, 10, ABC_CONST(0x0000F888F8880000), "(!(!(ab)!(cd))[ef])" }, // 447 { 6, 9, 15, ABC_CONST(0x0000788878880000), "([(ab)(cd)][ef])" }, // 448 { 6, 9, 16, ABC_CONST(0x0000877787770000), "(![(ab)(cd)][ef])" }, // 449 { 6, 9, 12, ABC_CONST(0x0000F999F9990000), "(!([ab]!(cd))[ef])" }, // 450 { 6, 11, 14, ABC_CONST(0x0000066006600000), "([ab][cd][ef])" }, // 451 { 6, 11, 14, ABC_CONST(0x0000F99FF99F0000), "(!([ab][cd])[ef])" }, // 452 { 6, 8, 11, ABC_CONST(0x0000CAAACAAA0000), "([ef])" }, // 453 { 6, 10, 14, ABC_CONST(0x0000ACCAACCA0000), "([ef])" }, // 454 { 6, 8, 9, ABC_CONST(0x0000F088F0880000), "(<(ab)cd>[ef])" }, // 455 { 6, 8, 10, ABC_CONST(0x00000F770F770000), "(!<(ab)cd>[ef])" }, // 456 { 6, 10, 11, ABC_CONST(0x0000F066F0660000), "(<[ab]cd>[ef])" }, // 457 { 6, 5, 11, ABC_CONST(0x007F7F7F7F7F7F7F), "(!(abc)!(def))" }, // 458 { 6, 7, 16, ABC_CONST(0x7F80808080808080), "[(abc)(def)]" }, // 459 { 6, 5, 9, ABC_CONST(0x008F8F8F8F8F8F8F), "(!(!(ab)c)!(def))" }, // 460 { 6, 7, 16, ABC_CONST(0x8F70707070707070), "[(!(ab)c)(def)]" }, // 461 { 6, 7, 13, ABC_CONST(0x0078787878787878), "([(ab)c]!(def))" }, // 462 { 6, 7, 12, ABC_CONST(0x009F9F9F9F9F9F9F), "(!([ab]c)!(def))" }, // 463 { 6, 9, 20, ABC_CONST(0x9F60606060606060), "[([ab]c)(def)]" }, // 464 { 6, 9, 17, ABC_CONST(0x0096969696969696), "([abc]!(def))" }, // 465 { 6, 6, 9, ABC_CONST(0x00CACACACACACACA), "(!(def))" }, // 466 { 6, 8, 16, ABC_CONST(0x35CACACACACACACA), "[(def)]" }, // 467 { 6, 5, 8, ABC_CONST(0x8F0000008F8F8F8F), "(!(!(ab)c)!(!(de)f))" }, // 468 { 6, 7, 16, ABC_CONST(0x708F8F8F70707070), "[(!(ab)c)(!(de)f)]" }, // 469 { 6, 7, 11, ABC_CONST(0x7800000078787878), "([(ab)c]!(!(de)f))" }, // 470 { 6, 7, 10, ABC_CONST(0x9F0000009F9F9F9F), "(!([ab]c)!(!(de)f))" }, // 471 { 6, 9, 20, ABC_CONST(0x609F9F9F60606060), "[([ab]c)(!(de)f)]" }, // 472 { 6, 9, 14, ABC_CONST(0x9600000096969696), "([abc]!(!(de)f))" }, // 473 { 6, 6, 8, ABC_CONST(0xCA000000CACACACA), "(!(!(de)f))" }, // 474 { 6, 8, 16, ABC_CONST(0xCA353535CACACACA), "[(!(de)f)]" }, // 475 { 6, 9, 15, ABC_CONST(0x0078787878000000), "([(ab)c][(de)f])" }, // 476 { 6, 9, 14, ABC_CONST(0x009F9F9F9F000000), "(!([ab]c)[(de)f])" }, // 477 { 6, 11, 19, ABC_CONST(0x0096969696000000), "([abc][(de)f])" }, // 478 { 6, 8, 11, ABC_CONST(0x00CACACACA000000), "([(de)f])" }, // 479 { 6, 9, 13, ABC_CONST(0x9F00009F9F9F9F9F), "(!([ab]c)!([de]f))" }, // 480 { 6, 11, 25, ABC_CONST(0x609F9F6060606060), "[([ab]c)([de]f)]" }, // 481 { 6, 11, 18, ABC_CONST(0x9600009696969696), "([abc]!([de]f))" }, // 482 { 6, 8, 10, ABC_CONST(0xCA0000CACACACACA), "(!([de]f))" }, // 483 { 6, 10, 20, ABC_CONST(0xCA3535CACACACACA), "[([de]f)]" }, // 484 { 6, 13, 24, ABC_CONST(0x9600009600969600), "([abc][def])" }, // 485 { 6, 10, 14, ABC_CONST(0xCA0000CA00CACA00), "([def])" }, // 486 { 6, 7, 8, ABC_CONST(0xCACA0000CA00CA00), "()" }, // 487 { 6, 9, 16, ABC_CONST(0x3535CACA35CA35CA), "[]" }, // 488 { 6, 6, 10, ABC_CONST(0xCAAAAAAAAAAAAAAA), "" }, // 489 { 6, 6, 10, ABC_CONST(0xACCCCCCCAAAAAAAA), "" }, // 490 { 6, 8, 16, ABC_CONST(0xACCCCCCCCAAAAAAA), "" }, // 491 { 6, 6, 10, ABC_CONST(0xACCCAAAAAAAAAAAA), "" }, // 492 { 6, 6, 10, ABC_CONST(0xCAAACCCCAAAAAAAA), "" }, // 493 { 6, 8, 16, ABC_CONST(0xCAAACCCCACCCAAAA), "" }, // 494 { 6, 8, 14, ABC_CONST(0xACCCCAAAAAAAAAAA), "" }, // 495 { 6, 10, 24, ABC_CONST(0xCAAAACCCACCCCAAA), "" }, // 496 { 6, 8, 12, ABC_CONST(0xACCAAAAAAAAAAAAA), "" }, // 497 { 6, 8, 12, ABC_CONST(0xCAACCCCCAAAAAAAA), "" }, // 498 { 6, 10, 20, ABC_CONST(0xCAACCCCCACCAAAAA), "" }, // 499 { 6, 10, 18, ABC_CONST(0xCAACACCAAAAAAAAA), "" }, // 500 { 6, 12, 32, ABC_CONST(0xACCACAACCAACACCA), "" }, // 501 { 6, 7, 10, ABC_CONST(0xCCAACACAAAAAAAAA), "f)>" }, // 502 { 6, 9, 16, ABC_CONST(0xAACCACACCCAACACA), "f]>" }, // 503 { 6, 6, 12, ABC_CONST(0xAAAAACCCACCCACCC), "" }, // 504 { 6, 8, 18, ABC_CONST(0xACCCCAAACAAACAAA), "" }, // 505 { 6, 8, 14, ABC_CONST(0xAAAAACCAACCAACCA), "" }, // 506 { 6, 10, 16, ABC_CONST(0xAAAAACCAACCAAAAA), "" }, // 507 { 6, 7, 12, ABC_CONST(0xCCAACACACACACACA), ">" }, // 508 { 6, 9, 16, ABC_CONST(0xCACACCAACCAACACA), ">" }, // 509 { 6, 7, 10, ABC_CONST(0xCCCCAAAACAAACAAA), ">" }, // 510 { 6, 9, 12, ABC_CONST(0xCCCCAAAAACCAACCA), ">" }, // 511 { 6, 6, 9, ABC_CONST(0xC0AAAAAAAAAAAAAA), "" }, // 512 { 6, 6, 10, ABC_CONST(0xAAC0C0C0AAAAAAAA), "" }, // 513 { 6, 8, 12, ABC_CONST(0xAAC0C0AAAAAAAAAA), "" }, // 514 { 6, 8, 10, ABC_CONST(0x3CAAAAAAAAAAAAAA), "" }, // 515 { 6, 8, 12, ABC_CONST(0xAA3C3C3CAAAAAAAA), "" }, // 516 { 6, 10, 14, ABC_CONST(0xAA3C3CAAAAAAAAAA), "" }, // 517 { 6, 6, 8, ABC_CONST(0xC000AAAAAAAAAAAA), "" }, // 518 { 6, 6, 8, ABC_CONST(0x3F00AAAAAAAAAAAA), "" }, // 519 { 6, 8, 10, ABC_CONST(0x3FC0AAAAAAAAAAAA), "" }, // 520 { 6, 8, 9, ABC_CONST(0x3C00AAAAAAAAAAAA), "" }, // 521 { 6, 10, 12, ABC_CONST(0xC33CAAAAAAAAAAAA), "" }, // 522 { 6, 7, 8, ABC_CONST(0xF0CCAAAAAAAAAAAA), "(ef)>" }, // 523 { 6, 6, 11, ABC_CONST(0xF088888888888888), "<(ab)c(def)>" }, // 524 { 6, 6, 10, ABC_CONST(0x88F0F0F088888888), "<(ab)c(!(de)f)>" }, // 525 { 6, 8, 15, ABC_CONST(0x88F0F0F0F0888888), "<(ab)c[(de)f]>" }, // 526 { 6, 8, 13, ABC_CONST(0x88F0F08888888888), "<(ab)c([de]f)>" }, // 527 { 6, 10, 20, ABC_CONST(0xF08888F088F0F088), "<(ab)c[def]>" }, // 528 { 6, 7, 10, ABC_CONST(0xF0F08888F088F088), "<(ab)c>" }, // 529 { 6, 8, 14, ABC_CONST(0xF066666666666666), "<[ab]c(def)>" }, // 530 { 6, 8, 12, ABC_CONST(0x66F0F0F066666666), "<[ab]c(!(de)f)>" }, // 531 { 6, 10, 18, ABC_CONST(0x66F0F0F0F0666666), "<[ab]c[(de)f]>" }, // 532 { 6, 10, 16, ABC_CONST(0x66F0F06666666666), "<[ab]c([de]f)>" }, // 533 { 6, 12, 24, ABC_CONST(0xF06666F066F0F066), "<[ab]c[def]>" }, // 534 { 6, 9, 12, ABC_CONST(0xF0F06666F066F066), "<[ab]c>" }, // 535 { 6, 6, 9, ABC_CONST(0xF000888888888888), "<(ab)(cd)(ef)>" }, // 536 { 6, 6, 9, ABC_CONST(0xF000777777777777), "" }, // 537 { 6, 8, 12, ABC_CONST(0x8888F000F0008888), "<(ab)(cd)[ef]>" }, // 538 { 6, 8, 12, ABC_CONST(0x7777F000F0007777), "" }, // 539 { 6, 8, 10, ABC_CONST(0x0FF0888888888888), "<(ab)[cd](ef)>" }, // 540 { 6, 8, 11, ABC_CONST(0xF000666666666666), "<[ab](cd)(ef)>" }, // 541 { 6, 10, 14, ABC_CONST(0x6666F000F0006666), "<[ab](cd)[ef]>" }, // 542 { 6, 10, 12, ABC_CONST(0x0FF0666666666666), "<[ab][cd](ef)>" }, // 543 { 6, 12, 16, ABC_CONST(0x66660FF00FF06666), "<[ab][cd][ef]>" }, // 544 { 6, 6, 10, ABC_CONST(0xFF00808080808080), "<(abc)d(ef)>" }, // 545 { 6, 8, 12, ABC_CONST(0x8080FF00FF008080), "<(abc)d[ef]>" }, // 546 { 6, 6, 10, ABC_CONST(0xFF00707070707070), "<(!(ab)c)d(ef)>" }, // 547 { 6, 8, 12, ABC_CONST(0x7070FF00FF007070), "<(!(ab)c)d[ef]>" }, // 548 { 6, 8, 14, ABC_CONST(0xFF00787878787878), "<[(ab)c]d(ef)>" }, // 549 { 6, 10, 16, ABC_CONST(0x7878FF00FF007878), "<[(ab)c]d[ef]>" }, // 550 { 6, 8, 12, ABC_CONST(0xFF00606060606060), "<([ab]c)d(ef)>" }, // 551 { 6, 10, 14, ABC_CONST(0x6060FF00FF006060), "<([ab]c)d[ef]>" }, // 552 { 6, 10, 18, ABC_CONST(0xFF00969696969696), "<[abc]d(ef)>" }, // 553 { 6, 12, 20, ABC_CONST(0x9696FF00FF009696), "<[abc]d[ef]>" }, // 554 { 6, 7, 10, ABC_CONST(0xFF00CACACACACACA), "<d(ef)>" }, // 555 { 6, 9, 12, ABC_CONST(0xCACAFF00FF00CACA), "<d[ef]>" }, // 556 { 6, 6, 7, ABC_CONST(0xFF00000080808080), "<(abc)(de)f>" }, // 557 { 6, 6, 7, ABC_CONST(0xFF0000007F7F7F7F), "" }, // 558 { 6, 8, 8, ABC_CONST(0x00FFFF0080808080), "<(abc)[de]f>" }, // 559 { 6, 6, 7, ABC_CONST(0xFF00000070707070), "<(!(ab)c)(de)f>" }, // 560 { 6, 6, 7, ABC_CONST(0xFF0000008F8F8F8F), "" }, // 561 { 6, 8, 8, ABC_CONST(0x00FFFF0070707070), "<(!(ab)c)[de]f>" }, // 562 { 6, 8, 9, ABC_CONST(0xFF00000078787878), "<[(ab)c](de)f>" }, // 563 { 6, 10, 10, ABC_CONST(0x00FFFF0078787878), "<[(ab)c][de]f>" }, // 564 { 6, 8, 8, ABC_CONST(0xFF00000060606060), "<([ab]c)(de)f>" }, // 565 { 6, 8, 8, ABC_CONST(0xFF0000009F9F9F9F), "" }, // 566 { 6, 10, 9, ABC_CONST(0x00FFFF0060606060), "<([ab]c)[de]f>" }, // 567 { 6, 10, 11, ABC_CONST(0xFF00000096969696), "<[abc](de)f>" }, // 568 { 6, 12, 12, ABC_CONST(0x00FFFF0096969696), "<[abc][de]f>" }, // 569 { 6, 7, 7, ABC_CONST(0xFF000000CACACACA), "<(de)f>" }, // 570 { 6, 9, 8, ABC_CONST(0x00FFFF00CACACACA), "<[de]f>" }, // 571 { 6, 6, 7, ABC_CONST(0xFFFF000080008000), "<(abcd)ef>" }, // 572 { 6, 6, 7, ABC_CONST(0xFFFF00007F007F00), "<(!(abc)d)ef>" }, // 573 { 6, 8, 10, ABC_CONST(0xFFFF00007F807F80), "<[(abc)d]ef>" }, // 574 { 6, 6, 7, ABC_CONST(0xFFFF000070007000), "<(!(ab)cd)ef>" }, // 575 { 6, 6, 7, ABC_CONST(0xFFFF00008F008F00), "<(!(!(ab)c)d)ef>" }, // 576 { 6, 8, 10, ABC_CONST(0xFFFF00008F708F70), "<[(!(ab)c)d]ef>" }, // 577 { 6, 8, 9, ABC_CONST(0xFFFF000078007800), "<([(ab)c]d)ef>" }, // 578 { 6, 10, 14, ABC_CONST(0xFFFF000087788778), "<[(ab)cd]ef>" }, // 579 { 6, 8, 8, ABC_CONST(0xFFFF000060006000), "<([ab]cd)ef>" }, // 580 { 6, 8, 8, ABC_CONST(0xFFFF00009F009F00), "<(!([ab]c)d)ef>" }, // 581 { 6, 10, 12, ABC_CONST(0xFFFF00009F609F60), "<[([ab]c)d]ef>" }, // 582 { 6, 10, 11, ABC_CONST(0xFFFF000096009600), "<([abc]d)ef>" }, // 583 { 6, 12, 18, ABC_CONST(0xFFFF000069966996), "<[abcd]ef>" }, // 584 { 6, 7, 7, ABC_CONST(0xFFFF0000CA00CA00), "<(d)ef>" }, // 585 { 6, 9, 10, ABC_CONST(0xFFFF000035CA35CA), "<[d]ef>" }, // 586 { 6, 6, 8, ABC_CONST(0xFFFF000007770777), "<(!(ab)!(cd))ef>" }, // 587 { 6, 8, 11, ABC_CONST(0xFFFF000078887888), "<[(ab)(cd)]ef>" }, // 588 { 6, 8, 9, ABC_CONST(0xFFFF000006660666), "<([ab]!(cd))ef>" }, // 589 { 6, 10, 10, ABC_CONST(0xFFFF000006600660), "<([ab][cd])ef>" }, // 590 { 6, 7, 8, ABC_CONST(0xFFFF0000CAAACAAA), "<ef>" }, // 591 { 6, 9, 10, ABC_CONST(0xFFFF0000ACCAACCA), "<ef>" }, // 592 { 6, 7, 7, ABC_CONST(0xFFFF0000F088F088), "<<(ab)cd>ef>" }, // 593 { 6, 9, 8, ABC_CONST(0xFFFF0000F066F066), "<<[ab]cd>ef>" } // 594 }; struct Sdm_Man_t_ { Sdm_Dsd_t * pDsd6; // NPN class information Hsh_IntMan_t * pHash; // maps DSD functions into NPN classes Vec_Int_t * vConfgRes; // configurations Vec_Wrd_t * vPerm6; // permutations of DSD classes Vec_Int_t * vMap2Perm; // maps number into its permutation char Perm6[720][6]; // permutations int nCountDsd[DSD_CLASS_NUM]; int nNonDsd; int nAllDsd; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sdm_ManPrintDsdStats( Sdm_Man_t * p, int fVerbose ) { int i, Absent = 0; for ( i = 0; i < DSD_CLASS_NUM; i++ ) { if ( p->nCountDsd[i] == 0 ) { Absent++; continue; } if ( fVerbose ) { printf( "%5d : ", i ); printf( "%-20s ", p->pDsd6[i].pStr ); printf( "%8d ", p->nCountDsd[i] ); printf( "\n" ); } } printf( "Unused classes = %d (%.2f %%). ", Absent, 100.0 * Absent / DSD_CLASS_NUM ); printf( "Non-DSD cuts = %d (%.2f %%). ", p->nNonDsd, 100.0 * p->nNonDsd / Abc_MaxInt(1, p->nAllDsd) ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hsh_IntMan_t * Sdm_ManBuildHashTable( Vec_Int_t ** pvConfgRes ) { FILE * pFile; char * pFileName = "dsdfuncs6.dat"; int RetValue, size = Extra_FileSize( pFileName ) / 12; // 2866420 Vec_Wrd_t * vTruthRes = Vec_WrdAlloc( size ); Vec_Int_t * vConfgRes = Vec_IntAlloc( size ); Hsh_IntMan_t * pHash; pFile = fopen( pFileName, "rb" ); RetValue = fread( Vec_WrdArray(vTruthRes), sizeof(word), size, pFile ); RetValue = fread( Vec_IntArray(vConfgRes), sizeof(int), size, pFile ); vTruthRes->nSize = size; vConfgRes->nSize = size; // create hash table pHash = Hsh_WrdManHashArrayStart( vTruthRes, 1 ); // cleanup if ( pvConfgRes ) *pvConfgRes = vConfgRes; else Vec_IntFree( vConfgRes ); Vec_WrdFree( vTruthRes ); // Hsh_IntManStop( pHash ); return pHash; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sdm_ManPrecomputePerms( Sdm_Man_t * p ) { int nVars = 6; // 0(1:1) 1(2:1) 2(4:2) 3(10:6) 4(33:23) 5(131:98) 6(595:464) int nClasses[7] = { 1, 2, 4, 10, 33, 131, 595 }; int nPerms = Extra_Factorial( nVars ); // int nSwaps = (1 << nVars); int * pComp, * pPerm; int i, k, x, One, OneCopy, Num; Vec_Int_t * vVars; abctime clk = Abc_Clock(); assert( p->pDsd6 == NULL ); p->pDsd6 = s_DsdClass6; // precompute schedules pComp = Extra_GreyCodeSchedule( nVars ); pPerm = Extra_PermSchedule( nVars ); // map numbers into perms p->vMap2Perm = Vec_IntStartFull( (1<<(3*nVars)) ); // store permutations One = 0; for ( x = 0; x < nVars; x++ ) { p->Perm6[0][x] = (char)x; One |= (x << (3*x)); } // Vec_IntWriteEntry( p->vMap2Perm, One, 0 ); OneCopy = One; for ( k = 0; k < nPerms; k++ ) { if ( k > 0 ) for ( x = 0; x < nVars; x++ ) p->Perm6[k][x] = p->Perm6[k-1][x]; ABC_SWAP( char, p->Perm6[k][pPerm[k]], p->Perm6[k][pPerm[k]+1] ); Num = ( (One >> (3*(pPerm[k] ))) ^ (One >> (3*(pPerm[k]+1))) ) & 7; One ^= (Num << (3*(pPerm[k] ))); One ^= (Num << (3*(pPerm[k]+1))); Vec_IntWriteEntry( p->vMap2Perm, One, k ); // Sdm_ManPrintPerm( One ); // for ( x = 0; x < nVars; x++ ) // printf( "%d ", p->Perm6[k][x] ); // printf( "\n" ); } assert( OneCopy == One ); // fill in the gaps vVars = Vec_IntAlloc( 6 ); Vec_IntForEachEntry( p->vMap2Perm, Num, i ) { // mark used variables int Count = 0; One = i; Vec_IntFill( vVars, 6, 0 ); for ( k = 0; k < nVars; k++ ) { int iVar = ((One >> (3*k)) & 7); if ( iVar >= nVars && iVar < 7 ) break; if ( iVar != 7 ) { if ( Vec_IntEntry( vVars, iVar ) == 1 ) break; Vec_IntWriteEntry( vVars, iVar, 1 ); Count++; } } // skip ones with dups and complete if ( k < nVars || Count == nVars ) continue; // find unused variables for ( x = k = 0; k < 6; k++ ) if ( Vec_IntEntry(vVars, k) == 0 ) Vec_IntWriteEntry( vVars, x++, k ); Vec_IntShrink( vVars, x ); // fill in used variables x = 0; for ( k = 0; k < nVars; k++ ) { int iVar = ((One >> (3*k)) & 7); if ( iVar == 7 ) One ^= ((Vec_IntEntry(vVars, x++) ^ 7) << (3*k)); } assert( x == Vec_IntSize(vVars) ); // save this one assert( Vec_IntEntry( p->vMap2Perm, One ) != -1 ); Vec_IntWriteEntry( p->vMap2Perm, i, Vec_IntEntry(p->vMap2Perm, One) ); /* // mapping Sdm_ManPrintPerm( i ); printf( "-> " ); Sdm_ManPrintPerm( One ); printf( "\n" ); */ } Vec_IntFree( vVars ); // store permuted truth tables assert( p->vPerm6 == NULL ); p->vPerm6 = Vec_WrdAlloc( nPerms * DSD_CLASS_NUM ); for ( i = 0; i < nClasses[nVars]; i++ ) { word uTruth = s_DsdClass6[i].uTruth; for ( k = 0; k < nPerms; k++ ) { uTruth = Abc_Tt6SwapAdjacent( uTruth, pPerm[k] ); Vec_WrdPush( p->vPerm6, uTruth ); } assert( uTruth == s_DsdClass6[i].uTruth ); } ABC_FREE( pPerm ); ABC_FREE( pComp ); // build hash table p->pHash = Sdm_ManBuildHashTable( &p->vConfgRes ); Abc_PrintTime( 1, "Setting up DSD information", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sdm_ManPrintPerm( unsigned s ) { int i; for ( i = 0; i < 6; i++ ) printf( "%d ", (s >> (3*i)) & 7 ); printf( " " ); } /**Function************************************************************* Synopsis [Checks hash table for DSD class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sdm_ManCheckDsd6( Sdm_Man_t * p, word t ) { int fCompl, Entry, Config; if ( (fCompl = (t & 1)) ) t = ~t; Entry = *Hsh_IntManLookup( p->pHash, (unsigned *)&t ); if ( Entry == -1 ) return -1; Config = Vec_IntEntry( p->vConfgRes, Entry ); if ( fCompl ) Config ^= (1 << 16); return Config; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sdm_ManComputeFunc( Sdm_Man_t * p, int iDsdLit0, int iDsdLit1, int * pCut, int uMask, int fXor ) { // int fVerbose = 0; int i, Config, iClass, fCompl, Res; int PermMask = uMask & 0x3FFFF; int ComplMask = uMask >> 18; word Truth0, Truth1p, t0, t1, t; p->nAllDsd++; assert( uMask > 1 ); assert( iDsdLit0 < DSD_CLASS_NUM * 2 ); assert( iDsdLit1 < DSD_CLASS_NUM * 2 ); Truth0 = p->pDsd6[Abc_Lit2Var(iDsdLit0)].uTruth; Truth1p = Vec_WrdEntry( p->vPerm6, Abc_Lit2Var(iDsdLit1) * 720 + Vec_IntEntry(p->vMap2Perm, PermMask ) ); if ( ComplMask ) for ( i = 0; i < 6; i++ ) if ( (ComplMask >> i) & 1 ) Truth1p = Abc_Tt6Flip( Truth1p, i ); t0 = Abc_LitIsCompl(iDsdLit0) ? ~Truth0 : Truth0; t1 = Abc_LitIsCompl(iDsdLit1) ? ~Truth1p : Truth1p; t = fXor ? t0 ^ t1 : t0 & t1; /* if ( fVerbose ) { Sdm_ManPrintPerm( PermMask ); printf( "\n" ); Extra_PrintBinary( stdout, &ComplMask, 6 ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&Truth0, 6 ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&Truth1p, 6 ); printf( "\n" ); Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ); printf( "\n" ); } */ // find configuration Config = Sdm_ManCheckDsd6( p, t ); if ( Config == -1 ) { p->nNonDsd++; return -1; } // get the class iClass = Config >> 17; fCompl = (Config >> 16) & 1; Config &= 0xFFFF; // set the function Res = Abc_Var2Lit( iClass, fCompl ); // update cut assert( (Config >> 6) < 720 ); if ( pCut ) { int pLeavesNew[6] = { -1, -1, -1, -1, -1, -1 }; assert( pCut[0] <= 6 ); for ( i = 0; i < pCut[0]; i++ ) pLeavesNew[(int)(p->Perm6[Config >> 6][i])] = Abc_LitNotCond( pCut[i+1], (Config >> i) & 1 ); pCut[0] = p->pDsd6[iClass].nVars; for ( i = 0; i < pCut[0]; i++ ) assert( pLeavesNew[i] != -1 ); for ( i = 0; i < pCut[0]; i++ ) pCut[i+1] = pLeavesNew[i]; } assert( iClass < DSD_CLASS_NUM ); p->nCountDsd[iClass]++; return Res; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sdm_ManReadDsdVarNum( Sdm_Man_t * p, int iDsd ) { return p->pDsd6[iDsd].nVars; } int Sdm_ManReadDsdAndNum( Sdm_Man_t * p, int iDsd ) { return p->pDsd6[iDsd].nAnds; } int Sdm_ManReadDsdClauseNum( Sdm_Man_t * p, int iDsd ) { return p->pDsd6[iDsd].nClauses; } word Sdm_ManReadDsdTruth( Sdm_Man_t * p, int iDsd ) { return p->pDsd6[iDsd].uTruth; } char * Sdm_ManReadDsdStr( Sdm_Man_t * p, int iDsd ) { return p->pDsd6[iDsd].pStr; } void Sdm_ManReadCnfCosts( Sdm_Man_t * p, int * pCosts, int nCosts ) { int i; assert( nCosts == DSD_CLASS_NUM ); pCosts[0] = pCosts[1] = 0; for ( i = 2; i < DSD_CLASS_NUM; i++ ) pCosts[i] = Sdm_ManReadDsdClauseNum( p, i ); } /**Function************************************************************* Synopsis [Manager manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sdm_Man_t * Sdm_ManAlloc() { Sdm_Man_t * p; p = ABC_CALLOC( Sdm_Man_t, 1 ); Sdm_ManPrecomputePerms( p ); return p; } void Sdm_ManFree( Sdm_Man_t * p ) { Vec_WrdFree( p->vPerm6 ); Vec_IntFree( p->vMap2Perm ); Vec_IntFree( p->vConfgRes ); Vec_IntFree( p->pHash->vData ); Hsh_IntManStop( p->pHash ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Sdm_Man_t * s_SdmMan = NULL; Sdm_Man_t * Sdm_ManRead() { if ( s_SdmMan == NULL ) s_SdmMan = Sdm_ManAlloc(); memset( s_SdmMan->nCountDsd, 0, sizeof(int) * DSD_CLASS_NUM ); return s_SdmMan; } void Sdm_ManQuit() { if ( s_SdmMan != NULL ) Sdm_ManFree( s_SdmMan ); s_SdmMan = NULL; } int Sdm_ManCanRead() { char * pFileName = "dsdfuncs6.dat"; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) return 0; fclose( pFile ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sdm_ManTest() { Sdm_Man_t * p; int iDsd0 = 4; int iDsd1 = 6; int iDsd; int uMask = 0x3FFFF ^ ((7 ^ 0) << 6) ^ ((7 ^ 1) << 9); int pCut[7] = { 4, 10, 20, 30, 40 }; // Sdm_ManPrintPerm( uMask ); p = Sdm_ManAlloc(); iDsd = Sdm_ManComputeFunc( p, iDsd0, iDsd1, pCut, uMask, 0 ); Sdm_ManFree( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* void Sdm_ManCompareCnfSizes() { Vec_Int_t * vMemory; word uTruth; int i, nSop0, nSop1, nVars, nCla, RetValue; vMemory = Vec_IntAlloc( 1 << 16 ); for ( i = 1; i < DSD_CLASS_NUM; i++ ) { uTruth = Sdm_ManReadDsdTruth( s_SdmMan, i ); nVars = Sdm_ManReadDsdVarNum( s_SdmMan, i ); nCla = Sdm_ManReadDsdClauseNum( s_SdmMan, i ); RetValue = Kit_TruthIsop( &uTruth, nVars, vMemory, 0 ); nSop0 = Vec_IntSize(vMemory); uTruth = ~uTruth; RetValue = Kit_TruthIsop( &uTruth, nVars, vMemory, 0 ); nSop1 = Vec_IntSize(vMemory); if ( nSop0 + nSop1 != nCla ) printf( "Class %4d : %d + %d != %d\n", i, nSop0, nSop1, nCla ); else printf( "Class %4d : %d + %d == %d\n", i, nSop0, nSop1, nCla ); } Vec_IntFree( vMemory ); } */ /**Function************************************************************* Synopsis [Collect DSD divisors of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sdm_ManDivCollect_rec( word t, Vec_Wrd_t ** pvDivs ) { int i, Config, Counter = 0; // check if function is decomposable Config = Sdm_ManCheckDsd6( s_SdmMan, t ); if ( Config != -1 && (Config >> 17) < 2 ) return; for ( i = 0; i < 6; i++ ) { if ( !Abc_Tt6HasVar( t, i ) ) continue; Sdm_ManDivCollect_rec( Abc_Tt6Cofactor0(t, i), pvDivs ); Sdm_ManDivCollect_rec( Abc_Tt6Cofactor1(t, i), pvDivs ); Counter++; } if ( Config != -1 && Counter >= 2 && Counter <= 4 ) { Vec_WrdPush( pvDivs[Counter], (t & 1) ? ~t : t ); // Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ); printf( "\n" ); } } void Sdm_ManDivTest() { // word u, t0, t1, t = ABC_CONST(0xB0F0BBFFB0F0BAFE); // word u, t0, t1, t = ABC_CONST(0x3F1F3F13FFDFFFD3); word u, t0, t1, t = ABC_CONST(0x3F3FFFFF37003700); Rsb_Man_t * pManRsb = Rsb_ManAlloc( 6, 200, 3, 1 ); Vec_Wrd_t * pvDivs[7] = { NULL }; Vec_Wrd_t * vDivs = Vec_WrdAlloc( 100 ); int i, RetValue; // collect divisors for ( i = 2; i <= 4; i++ ) pvDivs[i] = Vec_WrdAlloc( 100 ); Sdm_ManDivCollect_rec( t, pvDivs ); for ( i = 2; i <= 4; i++ ) Vec_WrdUniqify( pvDivs[i] ); // prepare the set vDivs = Vec_WrdAlloc( 100 ); for ( i = 0; i < 6; i++ ) Vec_WrdPush( vDivs, s_Truths6[i] ); for ( i = 2; i <= 4; i++ ) Vec_WrdAppend( vDivs, pvDivs[i] ); for ( i = 2; i <= 4; i++ ) Vec_WrdFree( pvDivs[i] ); Vec_WrdForEachEntry( vDivs, u, i ) { printf( "%2d : ", i ); // Kit_DsdPrintFromTruth( (unsigned *)&u, 6 ); printf( "\n" ); } RetValue = Rsb_ManPerformResub6( pManRsb, 6, t, vDivs, &t0, &t1, 1 ); if ( RetValue ) { // Kit_DsdPrintFromTruth( (unsigned *)&t0, 6 ); printf( "\n" ); // Kit_DsdPrintFromTruth( (unsigned *)&t1, 6 ); printf( "\n" ); printf( "Decomposition exits.\n" ); } Vec_WrdFree( vDivs ); Rsb_ManFree( pManRsb ); } /**Function************************************************************* Synopsis [Generation of node test.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* #include "bool/kit/kit.h" void Sdm_ManNodeGenTest() { extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); Sdm_Man_t * p = s_SdmMan; Vec_Int_t * vCover; Kit_Graph_t * pGraph; int i; vCover = Vec_IntAlloc( 1 << 16 ); for ( i = 2; i < DSD_CLASS_NUM; i++ ) { pGraph = Kit_TruthToGraph( (unsigned *)&p->pDsd6[i].uTruth, p->pDsd6[i].nVars, vCover ); printf( "%d %s %d %d ", i, p->pDsd6[i].pStr, Kit_GraphNodeNum(pGraph), p->pDsd6[i].nAnds ); } printf( "\n" ); } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilEnum.c000066400000000000000000000517201300674244400250710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilEnum.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Function enumeration.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilEnum.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "misc/vec/vecHsh.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GetFirst( int * pnVars, int * pnMints, int * pnFuncs, unsigned * pVars, unsigned * pMints, unsigned * pFuncs ) { int nVars = 8; int nMints = 16; int nFuncs = 8; char * pMintStrs[16] = { "1-1-1-1-", "1-1--11-", "1-1-1--1", "1-1--1-1", "-11-1-1-", "-11--11-", "-11-1--1", "-11--1-1", "1--11-1-", "1--1-11-", "1--11--1", "1--1-1-1", "-1-11-1-", "-1-1-11-", "-1-11--1", "-1-1-1-1" }; char * pFuncStrs[8] = { "1111101011111010", "0000010100000101", "1111110010101001", "0000001101010110", "1111111111001101", "0000000000110010", "1111111111111110", "0000000000000001", }; int i, k; *pnVars = nVars; *pnMints = nMints; *pnFuncs = nFuncs; // extract mints for ( i = 0; i < nMints; i++ ) for ( k = 0; k < nVars; k++ ) if ( pMintStrs[i][k] == '1' ) pMints[i] |= (1 << k), pVars[k] |= (1 << i); // extract funcs for ( i = 0; i < nFuncs; i++ ) for ( k = 0; k < nMints; k++ ) if ( pFuncStrs[i][k] == '1' ) pFuncs[i] |= (1 << k); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GetSecond( int * pnVars, int * pnMints, int * pnFuncs, unsigned * pVars, unsigned * pMints, unsigned * pFuncs ) { int nVars = 10; int nMints = 32; int nFuncs = 7; char * pMintStrs[32] = { "1-1---1---", "1-1----1--", "1-1-----1-", "1-1------1", "1--1--1---", "1--1---1--", "1--1----1-", "1--1-----1", "1---1-1---", "1---1--1--", "1---1---1-", "1---1----1", "1----11---", "1----1-1--", "1----1--1-", "1----1---1", "-11---1---", "-11----1--", "-11-----1-", "-11------1", "-1-1--1---", "-1-1---1--", "-1-1----1-", "-1-1-----1", "-1--1-1---", "-1--1--1--", "-1--1---1-", "-1--1----1", "-1---11---", "-1---1-1--", "-1---1--1-", "-1---1---1" }; char * pFuncStrs[7] = { "11111110110010001110110010000000", "00000001001101110001001101111111", "10000001001001000001001001001000", "01001000000100101000000100100100", "00100100100000010100100000010010", "00010010010010000010010010000001", "11111111111111111111000000000000" }; int i, k; *pnVars = nVars; *pnMints = nMints; *pnFuncs = nFuncs; // extract mints for ( i = 0; i < nMints; i++ ) for ( k = 0; k < nVars; k++ ) if ( pMintStrs[i][k] == '1' ) pMints[i] |= (1 << k), pVars[k] |= (1 << i); // extract funcs for ( i = 0; i < nFuncs; i++ ) for ( k = 0; k < nMints; k++ ) if ( pFuncStrs[i][k] == '1' ) pFuncs[i] |= (1 << k); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GetThird( int * pnVars, int * pnMints, int * pnFuncs, unsigned * pVars, unsigned * pMints, unsigned * pFuncs ) { int nVars = 8; int nMints = 16; int nFuncs = 7; char * pMintStrs[16] = { "1---1---", "1----1--", "1-----1-", "1------1", "-1--1---", "-1---1--", "-1----1-", "-1-----1", "--1-1---", "--1--1--", "--1---1-", "--1----1", "---11---", "---1-1--", "---1--1-", "---1---1" }; char * pFuncStrs[7] = { "1111111011001000", "0000000100110111", "1000000100100100", "0100100000010010", "0010010010000001", "0001001001001000", "1111111111111111" }; int i, k; *pnVars = nVars; *pnMints = nMints; *pnFuncs = nFuncs; // extract mints for ( i = 0; i < nMints; i++ ) for ( k = 0; k < nVars; k++ ) if ( pMintStrs[i][k] == '1' ) pMints[i] |= (1 << k), pVars[k] |= (1 << i); // extract funcs for ( i = 0; i < nFuncs; i++ ) for ( k = 0; k < nMints; k++ ) if ( pFuncStrs[i][k] == '1' ) pFuncs[i] |= (1 << k); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_EnumPrint_rec( Vec_Int_t * vGates, int i, int nVars ) { int Fan0 = Vec_IntEntry(vGates, 2*i); int Fan1 = Vec_IntEntry(vGates, 2*i+1); char * pOper = (char*)(Fan0 < Fan1 ? "" : "+"); if ( Fan0 > Fan1 ) ABC_SWAP( int, Fan0, Fan1 ); if ( Fan0 < nVars ) printf( "%c", 'a'+Fan0 ); else { printf( "(" ); Abc_EnumPrint_rec( vGates, Fan0, nVars ); printf( ")" ); } printf( "%s", pOper ); if ( Fan1 < nVars ) printf( "%c", 'a'+Fan1 ); else { printf( "(" ); Abc_EnumPrint_rec( vGates, Fan1, nVars ); printf( ")" ); } } void Abc_EnumPrint( Vec_Int_t * vGates, int i, int nVars ) { assert( 2*i < Vec_IntSize(vGates) ); Abc_EnumPrint_rec( vGates, i, nVars ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_DataHasBit( word * p, word i ) { return (p[(i)>>6] & (1<<((i) & 63))) > 0; } static inline void Abc_DataXorBit( word * p, word i ) { p[(i)>>6] ^= (1<<((i) & 63)); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_EnumerateFunctions( int nDecMax ) { int nVars; int nMints; int nFuncs; unsigned pVars[100] = {0}; unsigned pMints[100] = {0}; unsigned pFuncs[100] = {0}; unsigned Truth; int FuncDone[100] = {0}, nFuncDone = 0; int GateCount[100] = {0}; int i, k, n, a, b, v; abctime clk = Abc_Clock(); Vec_Int_t * vGates = Vec_IntAlloc( 100000 ); Vec_Int_t * vTruths = Vec_IntAlloc( 100000 ); // Vec_Int_t * vHash = Vec_IntStartFull( 1 << 16 ); word * pHash; // extract data // Abc_GetFirst( &nVars, &nMints, &nFuncs, pVars, pMints, pFuncs ); Abc_GetSecond( &nVars, &nMints, &nFuncs, pVars, pMints, pFuncs ); // Abc_GetThird( &nVars, &nMints, &nFuncs, pVars, pMints, pFuncs ); // create hash table assert( nMints == 16 || nMints == 32 ); pHash = (word *)ABC_CALLOC( char, 1 << (nMints-3) ); // create elementary gates for ( k = 0; k < nVars; k++ ) { // Vec_IntWriteEntry( vHash, pVars[k], k ); Abc_DataXorBit( pHash, pVars[k] ); Vec_IntPush( vTruths, pVars[k] ); Vec_IntPush( vGates, -1 ); Vec_IntPush( vGates, -1 ); } // go through different number of variables GateCount[0] = 0; GateCount[1] = nVars; assert( Vec_IntSize(vTruths) == nVars ); for ( n = 0; n < nDecMax && nFuncDone < nFuncs; n++ ) { for ( a = 0; a <= n; a++ ) for ( b = a; b <= n; b++ ) if ( a + b == n ) { printf( "Trying %d + %d + 1 = %d\n", a, b, n+1 ); for ( i = GateCount[a]; i < GateCount[a+1]; i++ ) for ( k = GateCount[b]; k < GateCount[b+1]; k++ ) if ( i < k ) { Truth = Vec_IntEntry(vTruths, i) & Vec_IntEntry(vTruths, k); // if ( Vec_IntEntry(vHash, Truth) == -1 ) if ( !Abc_DataHasBit(pHash, Truth) ) { // Vec_IntWriteEntry( vHash, Truth, Vec_IntSize(vTruths) ); Abc_DataXorBit( pHash, Truth ); Vec_IntPush( vTruths, Truth ); Vec_IntPush( vGates, i ); Vec_IntPush( vGates, k ); for ( v = 0; v < nFuncs; v++ ) if ( !FuncDone[v] && Truth == pFuncs[v] ) { printf( "Found function %d with %d gates: ", v, n+1 ); Abc_EnumPrint( vGates, Vec_IntSize(vTruths)-1, nVars ); FuncDone[v] = 1; nFuncDone++; } } Truth = Vec_IntEntry(vTruths, i) | Vec_IntEntry(vTruths, k); // if ( Vec_IntEntry(vHash, Truth) == -1 ) if ( !Abc_DataHasBit(pHash, Truth) ) { // Vec_IntWriteEntry( vHash, Truth, Vec_IntSize(vTruths) ); Abc_DataXorBit( pHash, Truth ); Vec_IntPush( vTruths, Truth ); Vec_IntPush( vGates, k ); Vec_IntPush( vGates, i ); for ( v = 0; v < nFuncs; v++ ) if ( !FuncDone[v] && Truth == pFuncs[v] ) { printf( "Found function %d with %d gates: ", v, n+1 ); Abc_EnumPrint( vGates, Vec_IntSize(vTruths)-1, nVars ); FuncDone[v] = 1; nFuncDone++; } } } } GateCount[n+2] = Vec_IntSize(vTruths); printf( "Finished %d gates. Truths = %10d. ", n+1, Vec_IntSize(vTruths) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } ABC_FREE( pHash ); // Vec_IntFree( vHash ); Vec_IntFree( vGates ); Vec_IntFree( vTruths ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define ABC_ENUM_MAX 16 static word s_Truths6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; typedef struct Abc_EnuMan_t_ Abc_EnuMan_t; struct Abc_EnuMan_t_ { int nVars; // support size int nVarsFree; // number of PIs used int fVerbose; // verbose flag int fUseXor; // using XOR gate int nNodeMax; // the max number of nodes int nNodes; // current number of gates int nTops; // the number of fanoutless gates int pFans0[ABC_ENUM_MAX]; // fanins int pFans1[ABC_ENUM_MAX]; // fanins int fCompl0[ABC_ENUM_MAX]; // complements int fCompl1[ABC_ENUM_MAX]; // complements int Polar[ABC_ENUM_MAX]; // polarity int pRefs[ABC_ENUM_MAX]; // references int pLevel[ABC_ENUM_MAX]; // level word pTruths[ABC_ENUM_MAX]; // truth tables word nTries; // attempts to build a gate word nBuilds; // actually built gates word nFinished; // finished structures }; static inline void Abc_EnumRef( Abc_EnuMan_t * p, int i ) { assert( p->pRefs[i] >= 0 ); if ( p->pRefs[i]++ == 0 ) p->nTops--; } static inline void Abc_EnumDeref( Abc_EnuMan_t * p, int i ) { if ( --p->pRefs[i] == 0 ) p->nTops++; assert( p->pRefs[i] >= 0 ); } static inline void Abc_EnumRefNode( Abc_EnuMan_t * p, int i ) { Abc_EnumRef( p, p->pFans0[i] ); Abc_EnumRef( p, p->pFans1[i] ); p->nTops++; p->nNodes++; assert( i < p->nNodes ); } static inline void Abc_EnumDerefNode( Abc_EnuMan_t * p, int i ) { assert( i < p->nNodes ); Abc_EnumDeref( p, p->pFans0[i] ); Abc_EnumDeref( p, p->pFans1[i] ); p->nTops--; p->nNodes--; } static inline void Abc_EnumPrintOne( Abc_EnuMan_t * p ) { int i; Kit_DsdPrintFromTruth( (unsigned *)(p->pTruths + p->nNodes - 1), p->nVars ); for ( i = p->nVars; i < p->nNodes; i++ ) if ( p->Polar[i] == 4 ) printf( " %c=%c+%c", 'a'+i, 'a'+p->pFans0[i], 'a'+p->pFans1[i] ); else printf( " %c=%s%c%s%c", 'a'+i, p->fCompl0[i]?"!":"", 'a'+p->pFans0[i], p->fCompl1[i]?"!":"", 'a'+p->pFans1[i] ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_EnumEquiv( word a, word b ) { return a == b || a == ~b; } static inline int Abc_EnumerateFilter( Abc_EnuMan_t * p ) { int fUseFull = 1; int n = p->nNodes; int i = p->pFans0[n]; int k = p->pFans1[n], t; word * pTruths = p->pTruths; word uTruth = pTruths[n]; assert( i < k ); // skip constants if ( Abc_EnumEquiv(uTruth, 0) ) return 1; // skip equal ones for ( t = 0; t < n; t++ ) if ( Abc_EnumEquiv(uTruth, pTruths[t]) ) return 1; if ( fUseFull ) { // skip those that can be derived by any pair int a, b; for ( a = 0; a <= i; a++ ) for ( b = a + 1; b <= k; b++ ) { if ( a == i && b == k ) continue; if ( Abc_EnumEquiv(uTruth, pTruths[a] & pTruths[b]) ) return 1; if ( Abc_EnumEquiv(uTruth, pTruths[a] & ~pTruths[b]) ) return 1; if ( Abc_EnumEquiv(uTruth, ~pTruths[a] & pTruths[b]) ) return 1; if ( Abc_EnumEquiv(uTruth, ~pTruths[a] & ~pTruths[b]) ) return 1; if ( p->fUseXor && Abc_EnumEquiv(uTruth, pTruths[a] ^ pTruths[b]) ) return 1; } } else { // skip those that can be derived by fanin and any other one in the cone int uTruthI = p->fCompl0[n] ? ~pTruths[i] : pTruths[i]; int uTruthK = p->fCompl1[n] ? ~pTruths[k] : pTruths[k]; assert( p->fUseXor == 0 ); for ( t = 0; t < k; t++ ) if ( Abc_EnumEquiv(uTruth, pTruths[t] & uTruthI) || Abc_EnumEquiv(uTruth, ~pTruths[t] & uTruthI) ) return 1; for ( t = 0; t < i; t++ ) if ( Abc_EnumEquiv(uTruth, pTruths[t] & uTruthK) || Abc_EnumEquiv(uTruth, ~pTruths[t] & uTruthK) ) return 1; } return 0; } void Abc_EnumerateFuncs_rec( Abc_EnuMan_t * p, int fNew, int iNode1st ) // the first node on the last level { if ( p->nNodes == p->nNodeMax ) { assert( p->nTops == 1 ); if ( p->fVerbose ) Abc_EnumPrintOne( p ); p->nFinished++; return; } { int i, k, c, cLim = 4 + p->fUseXor, n = p->nNodes; int nRefedFans = p->nNodeMax - n + 1 - p->nTops; int high0 = fNew ? iNode1st : p->pFans1[n-1]; int high1 = fNew ? n : iNode1st; int low0 = fNew ? 0 : p->pFans0[n-1]; int c0 = fNew ? 0 : p->Polar[n-1]; int Level = p->pLevel[high0]; assert( p->nTops > 0 && p->nTops <= p->nNodeMax - n + 1 ); // go through nodes for ( k = high0; k < high1; k++ ) { if ( nRefedFans == 0 && p->pRefs[k] > 0 ) continue; if ( p->pRefs[k] > 0 ) nRefedFans--; assert( nRefedFans >= 0 ); // try second fanin for ( i = (k == high0) ? low0 : 0; i < k; i++ ) { if ( nRefedFans == 0 && p->pRefs[i] > 0 ) continue; if ( Level == 0 && p->pRefs[i] == 0 && p->pRefs[k] == 0 && (i+1 != k || (i > 0 && p->pRefs[i-1] == 0)) ) // NPN continue; if ( p->pLevel[k] == 0 && p->pRefs[k] == 0 && p->pRefs[i] != 0 && k > 0 && p->pRefs[k-1] == 0 ) // NPN continue; // if ( p->pLevel[i] == 0 && p->pRefs[i] == 0 && p->pRefs[k] != 0 && i > 0 && p->pRefs[i-1] == 0 ) // NPN // continue; // try four polarities for ( c = (k == high0 && i == low0 && !fNew) ? c0 + 1 : 0; c < cLim; c++ ) { if ( p->pLevel[i] == 0 && p->pRefs[i] == 0 && (c & 1) == 1 ) // NPN continue; if ( p->pLevel[k] == 0 && p->pRefs[k] == 0 && (c & 2) == 2 ) // NPN continue; p->nTries++; // create node assert( i < k ); p->pFans0[n] = i; p->pFans1[n] = k; p->fCompl0[n] = c & 1; p->fCompl1[n] = (c >> 1) & 1; p->Polar[n] = c; if ( c == 4 ) p->pTruths[n] = p->pTruths[i] ^ p->pTruths[k]; else p->pTruths[n] = ((c & 1) ? ~p->pTruths[i] : p->pTruths[i]) & ((c & 2) ? ~p->pTruths[k] : p->pTruths[k]); if ( Abc_EnumerateFilter(p) ) continue; p->nBuilds++; assert( Level == Abc_MaxInt(p->pLevel[i], p->pLevel[k]) ); p->pLevel[n] = Level + 1; Abc_EnumRefNode( p, n ); Abc_EnumerateFuncs_rec( p, 0, fNew ? n : iNode1st ); Abc_EnumDerefNode( p, n ); assert( n == p->nNodes ); } } if ( p->pRefs[k] > 0 ) nRefedFans++; } if ( fNew ) return; // start a new level Abc_EnumerateFuncs_rec( p, 1, iNode1st ); } } void Abc_EnumerateFuncs( int nVars, int nGates, int fVerbose ) { abctime clk = Abc_Clock(); Abc_EnuMan_t P, * p = &P; int i; if ( nVars > nGates + 1 ) { printf( "The gate count %d is not enough to have functions with %d inputs.\n", nGates, nVars ); return; } assert( nVars >= 2 && nVars <= 6 ); assert( nGates > 0 && nVars + nGates < ABC_ENUM_MAX ); memset( p, 0, sizeof(Abc_EnuMan_t) ); p->fVerbose = fVerbose; p->fUseXor = 0; p->nVars = nVars; p->nNodeMax = nVars + nGates; p->nNodes = nVars; p->nTops = nVars; for ( i = 0; i < nVars; i++ ) p->pTruths[i] = s_Truths6[i]; Abc_EnumerateFuncs_rec( p, 1, 0 ); assert( p->nNodes == nVars ); assert( p->nTops == nVars ); // report statistics printf( "Vars = %d. Gates = %d. Tries = %u. Builds = %u. Finished = %d. ", nVars, nGates, (unsigned)p->nTries, (unsigned)p->nBuilds, (unsigned)p->nFinished ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilFile.c000066400000000000000000000605161300674244400250470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilFile.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [File management utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilFile.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "extra.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Tries to find a file name with a different extension.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 ) { FILE * pFile; char * pFileNameOther; char * pFileGen; if ( pS1 == NULL ) return NULL; // get the generic file name pFileGen = Extra_FileNameGeneric( pFileNameWrong ); pFileNameOther = Extra_FileNameAppend( pFileGen, pS1 ); pFile = fopen( pFileNameOther, "r" ); if ( pFile == NULL && pS2 ) { // try one more pFileNameOther = Extra_FileNameAppend( pFileGen, pS2 ); pFile = fopen( pFileNameOther, "r" ); if ( pFile == NULL && pS3 ) { // try one more pFileNameOther = Extra_FileNameAppend( pFileGen, pS3 ); pFile = fopen( pFileNameOther, "r" ); if ( pFile == NULL && pS4 ) { // try one more pFileNameOther = Extra_FileNameAppend( pFileGen, pS4 ); pFile = fopen( pFileNameOther, "r" ); if ( pFile == NULL && pS5 ) { // try one more pFileNameOther = Extra_FileNameAppend( pFileGen, pS5 ); pFile = fopen( pFileNameOther, "r" ); } } } } ABC_FREE( pFileGen ); if ( pFile ) { fclose( pFile ); return pFileNameOther; } // did not find :( return NULL; } /**Function************************************************************* Synopsis [Returns the pointer to the file extension.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileNameExtension( char * FileName ) { char * pDot; // find the last "dot" in the file name, if it is present for ( pDot = FileName + strlen(FileName)-1; pDot >= FileName; pDot-- ) if ( *pDot == '.' ) return pDot + 1; return FileName; } /**Function************************************************************* Synopsis [Returns the composite name of the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileNameAppend( char * pBase, char * pSuffix ) { static char Buffer[500]; assert( strlen(pBase) + strlen(pSuffix) < 500 ); sprintf( Buffer, "%s%s", pBase, pSuffix ); return Buffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileNameGeneric( char * FileName ) { char * pDot, * pRes; pRes = Extra_UtilStrsav( FileName ); if ( (pDot = strrchr( pRes, '.' )) ) *pDot = 0; return pRes; } /**Function************************************************************* Synopsis [Returns the composite name of the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileNameGenericAppend( char * pBase, char * pSuffix ) { static char Buffer[1000]; char * pDot; assert( strlen(pBase) + strlen(pSuffix) < 1000 ); strcpy( Buffer, pBase ); if ( (pDot = strrchr( Buffer, '.' )) ) *pDot = 0; strcat( Buffer, pSuffix ); return Buffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_FileNameCorrectPath( char * FileName ) { char * pStart; if ( FileName ) for ( pStart = FileName; *pStart; pStart++ ) if ( *pStart == '>' || *pStart == '\\' ) *pStart = '/'; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileNameWithoutPath( char * FileName ) { char * pRes; for ( pRes = FileName + strlen(FileName) - 1; pRes >= FileName; pRes-- ) if ( *pRes == '\\' || *pRes == '/' ) return pRes + 1; return FileName; } char * Extra_FilePathWithoutName( char * FileName ) { char * pRes; FileName = Abc_UtilStrsav( FileName ); for ( pRes = FileName + strlen(FileName) - 1; pRes >= FileName; pRes-- ) if ( *pRes == '\\' || *pRes == '/' ) { *pRes = 0; Extra_FileNameCorrectPath( FileName ); return FileName; } ABC_FREE( FileName ); return NULL; } char * Extra_FileDesignName( char * pFileName ) { char * pBeg, * pEnd, * pStore, * pCur; // find the first dot for ( pEnd = pFileName; *pEnd; pEnd++ ) if ( *pEnd == '.' ) break; // find the first char for ( pBeg = pEnd - 1; pBeg >= pFileName; pBeg-- ) if ( !((*pBeg >= 'a' && *pBeg <= 'z') || (*pBeg >= 'A' && *pBeg <= 'Z') || (*pBeg >= '0' && *pBeg <= '9') || *pBeg == '_') ) break; pBeg++; // fill up storage pStore = ABC_ALLOC( char, pEnd - pBeg + 1 ); for ( pCur = pStore; pBeg < pEnd; pBeg++, pCur++ ) *pCur = *pBeg; *pCur = 0; return pStore; } /**Function************************************************************* Synopsis [Returns the file size.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileCheck( char * pFileName ) { FILE * pFile; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Extra_FileCheck(): File \"%s\" does not exist.\n", pFileName ); return 0; } fseek( pFile, 0, SEEK_END ); if ( ftell( pFile ) == 0 ) printf( "Extra_FileCheck(): File \"%s\" is empty.\n", pFileName ); fclose( pFile ); return 1; } /**Function************************************************************* Synopsis [Returns the file size.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileSize( char * pFileName ) { FILE * pFile; int nFileSize; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Extra_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 [Read the file into the internal buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileRead( FILE * pFile ) { int nFileSize; char * pBuffer; int RetValue; // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nFileSize + 3 ); RetValue = fread( pBuffer, nFileSize, 1, pFile ); // terminate the string with '\0' pBuffer[ nFileSize + 0] = '\n'; pBuffer[ nFileSize + 1] = '\0'; return pBuffer; } char * Extra_FileRead2( FILE * pFile, FILE * pFile2 ) { char * pBuffer; int nSize, nSize2; int RetValue; // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nSize = ftell( pFile ); rewind( pFile ); // get the file size, in bytes fseek( pFile2, 0, SEEK_END ); nSize2 = ftell( pFile2 ); rewind( pFile2 ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nSize + nSize2 + 3 ); RetValue = fread( pBuffer, nSize, 1, pFile ); RetValue = fread( pBuffer + nSize, nSize2, 1, pFile2 ); // terminate the string with '\0' pBuffer[ nSize + nSize2 + 0] = '\n'; pBuffer[ nSize + nSize2 + 1] = '\0'; return pBuffer; } /**Function************************************************************* Synopsis [Read the file into the internal buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileReadContents( char * pFileName ) { FILE * pFile; char * pBuffer; pFile = fopen( pFileName, "rb" ); pBuffer = pFile ? Extra_FileRead( pFile ) : NULL; if ( pFile ) fclose( pFile ); return pBuffer; } char * Extra_FileReadContents2( char * pFileName, char * pFileName2 ) { FILE * pFile, * pFile2; char * pBuffer; pFile = fopen( pFileName, "rb" ); pFile2 = fopen( pFileName2, "rb" ); pBuffer = (pFile && pFile2) ? Extra_FileRead2( pFile, pFile2 ) : NULL; if ( pFile ) fclose( pFile ); if ( pFile2 ) fclose( pFile2 ); return pBuffer; } /**Function************************************************************* Synopsis [Returns one if the file has a given extension.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileIsType( char * pFileName, char * pS1, char * pS2, char * pS3 ) { int lenS, lenF = strlen(pFileName); lenS = pS1 ? strlen(pS1) : 0; if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS1, lenS ) ) return 1; lenS = pS2 ? strlen(pS2) : 0; if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS2, lenS ) ) return 1; lenS = pS3 ? strlen(pS3) : 0; if ( lenS && lenF > lenS && !strncmp( pFileName+lenF-lenS, pS3, lenS ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns the time stamp.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_ReadBinary( char * Buffer ) { unsigned Result; int i; Result = 0; for ( i = 0; Buffer[i]; i++ ) if ( Buffer[i] == '0' || Buffer[i] == '1' ) Result = Result * 2 + Buffer[i] - '0'; else { assert( 0 ); } return Result; } /**Function************************************************************* Synopsis [Prints the bit string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ) { int Remainder, nWords; int w, i; Remainder = (nBits%(sizeof(unsigned)*8)); nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); for ( w = nWords-1; w >= 0; w-- ) for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1< 0) ); // fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Reads the hex unsigned into the bit-string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_ReadHex( unsigned Sign[], char * pString, int nDigits ) { int Digit, k, c; for ( k = 0; k < nDigits; k++ ) { c = nDigits-1-k; if ( pString[c] >= '0' && pString[c] <= '9' ) Digit = pString[c] - '0'; else if ( pString[c] >= 'A' && pString[c] <= 'F' ) Digit = pString[c] - 'A' + 10; else if ( pString[c] >= 'a' && pString[c] <= 'f' ) Digit = pString[c] - 'a' + 10; else { assert( 0 ); return 0; } Sign[k/8] |= ( (Digit & 15) << ((k%8) * 4) ); } return 1; } int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars ) { int nWords, nDigits, k; nWords = Extra_TruthWordNum( nVars ); for ( k = 0; k < nWords; k++ ) Sign[k] = 0; // read the number from the string nDigits = (1 << nVars) / 4; if ( nDigits == 0 ) nDigits = 1; Extra_ReadHex( Sign, pString, nDigits ); return 1; } /**Function************************************************************* Synopsis [Prints the hex unsigned into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ) { int nDigits, Digit, k; // write the number into the file nDigits = (1 << nVars) / 4; for ( k = nDigits - 1; k >= 0; k-- ) { Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); if ( Digit < 10 ) fprintf( pFile, "%d", Digit ); else fprintf( pFile, "%c", 'a' + Digit-10 ); } // fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Prints the hex unsigned into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars ) { int nDigits, Digit, k; // write the number into the file nDigits = (1 << nVars) / 4; for ( k = nDigits - 1; k >= 0; k-- ) { Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); if ( Digit < 10 ) *pString++ = '0' + Digit; else *pString++ = 'a' + Digit-10; } // fprintf( pFile, "\n" ); *pString = 0; } /**Function************************************************************* Synopsis [Prints the hex unsigned into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars ) { int nMints, nDigits, Digit, k; // write the number into the file fprintf( pFile, "0x" ); nMints = (1 << nVars); nDigits = nMints / 4 + ((nMints % 4) > 0); for ( k = nDigits - 1; k >= 0; k-- ) { Digit = ((pTruth[k/8] >> (k * 4)) & 15); if ( Digit < 10 ) fprintf( pFile, "%d", Digit ); else fprintf( pFile, "%c", 'A' + Digit-10 ); } // fprintf( pFile, "\n" ); } void Extra_PrintHexReverse( FILE * pFile, unsigned * pTruth, int nVars ) { int nMints, nDigits, Digit, k; // write the number into the file fprintf( pFile, "0x" ); nMints = (1 << nVars); nDigits = nMints / 4 + ((nMints % 4) > 0); for ( k = 0; k < nDigits; k++ ) { Digit = ((pTruth[k/8] >> (k * 4)) & 15); if ( Digit < 10 ) fprintf( pFile, "%d", Digit ); else fprintf( pFile, "%c", 'A' + Digit-10 ); } // fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Returns the composite name of the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine ) { int i; for ( i = 0; i < nTimes; i++ ) printf( "%c", Char ); if ( fPrintNewLine ) printf( "\n" ); } /**Function************************************************************* Synopsis [Appends the string.] Description [Assumes that the given string (pStrGiven) has been allocated before using malloc(). The additional string has not been allocated. Allocs more root, appends the additional part, frees the old given string.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ) { char * pTemp; if ( pStrGiven ) { pTemp = ABC_ALLOC( char, strlen(pStrGiven) + strlen(pStrAdd) + 2 ); sprintf( pTemp, "%s%s", pStrGiven, pStrAdd ); ABC_FREE( pStrGiven ); } else pTemp = Extra_UtilStrsav( pStrAdd ); return pTemp; } /**Function************************************************************* Synopsis [Only keep characters belonging to the second string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_StringClean( char * pStrGiven, char * pCharKeep ) { char * pTemp, * pChar, * pSave = pStrGiven; for ( pTemp = pStrGiven; *pTemp; pTemp++ ) { for ( pChar = pCharKeep; *pChar; pChar++ ) if ( *pTemp == *pChar ) break; if ( *pChar == 0 ) continue; *pSave++ = *pTemp; } *pSave = 0; } /**Function************************************************************* Synopsis [String comparison procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_StringCompare( const char * pp1, const char * pp2 ) { return strcmp(*(char **)pp1, *(char **)pp2); } /**Function************************************************************* Synopsis [Sorts lines in the file alphabetically.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_FileSort( char * pFileName, char * pFileNameOut ) { FILE * pFile; char * pContents; char ** pLines; int i, nLines, Begin; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Extra_FileSort(): Cannot open file \"%s\".\n", pFileName ); return; } pContents = Extra_FileRead( pFile ); fclose( pFile ); if ( pContents == NULL ) { printf( "Extra_FileSort(): Cannot read contents of file \"%s\".\n", pFileName ); return; } // count end of lines for ( nLines = 0, i = 0; pContents[i]; i++ ) nLines += (pContents[i] == '\n'); // break the file into lines pLines = (char **)malloc( sizeof(char *) * nLines ); Begin = 0; for ( nLines = 0, i = 0; pContents[i]; i++ ) if ( pContents[i] == '\n' ) { pContents[i] = 0; pLines[nLines++] = pContents + Begin; Begin = i + 1; } // sort the lines qsort( pLines, nLines, sizeof(char *), (int(*)(const void *,const void *))Extra_StringCompare ); // write a new file pFile = fopen( pFileNameOut, "wb" ); for ( i = 0; i < nLines; i++ ) if ( pLines[i][0] ) fprintf( pFile, "%s\n", pLines[i] ); fclose( pFile ); // cleanup free( pLines ); free( pContents ); // report the result printf( "The file after sorting is \"%s\".\n", pFileNameOut ); } /**Function************************************************************* Synopsis [Appends line number in the end.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_FileLineNumAdd( char * pFileName, char * pFileNameOut ) { char Buffer[1000]; FILE * pFile; FILE * pFile2; int iLine; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Extra_FileLineNumAdd(): Cannot open file \"%s\".\n", pFileName ); return; } pFile2 = fopen( pFileNameOut, "wb" ); if ( pFile2 == NULL ) { fclose( pFile ); printf( "Extra_FileLineNumAdd(): Cannot open file \"%s\".\n", pFileNameOut ); return; } for ( iLine = 0; fgets( Buffer, 1000, pFile ); iLine++ ) { sprintf( Buffer + strlen(Buffer) - 2, "%03d\n%c", iLine, 0 ); fputs( Buffer, pFile2 ); } fclose( pFile ); fclose( pFile2 ); // report the result printf( "The resulting file is \"%s\".\n", pFileNameOut ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* int main( int argc, char ** argv ) { if ( argc == 2 ) Extra_FileSort( argv[1], Extra_FileNameAppend(argv[1], "_sorted") ); else printf( "%s: Wrong number of command line arguments.\n", argv[0] ); return 1; } */ /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static Functions */ /*---------------------------------------------------------------------------*/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilMemory.c000066400000000000000000000450021300674244400254310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilMemory.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Memory managers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilMemory.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "extra.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ struct Extra_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 Extra_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 Extra_MmStep_t_ { int nMems; // the number of fixed memory managers employed Extra_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc int nMapSize; // the size of the memory array Extra_MmFixed_t ** pMap; // maps the number of bytes into its memory manager int nLargeChunksAlloc; // the maximum number of large memory chunks int nLargeChunks; // the current number of large memory chunks void ** pLargeChunks; // the allocated large memory chunks }; /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**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 [] ***********************************************************************/ Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize ) { Extra_MmFixed_t * p; p = ABC_ALLOC( Extra_MmFixed_t, 1 ); memset( p, 0, sizeof(Extra_MmFixed_t) ); p->nEntrySize = nEntrySize; p->nEntriesAlloc = 0; p->nEntriesUsed = 0; p->pEntriesFree = NULL; if ( nEntrySize * (1 << 10) < (1<<16) ) p->nChunkSize = (1 << 10); else p->nChunkSize = (1<<16) / nEntrySize; 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 Extra_MmFixedPrint( Extra_MmFixed_t * p ) { 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 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_MmFixedStop( Extra_MmFixed_t * p ) { int i; if ( p == NULL ) return; 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 * Extra_MmFixedEntryFetch( Extra_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 Extra_MmFixedEntryRecycle( Extra_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 Extra_MmFixedRestart( Extra_MmFixed_t * p ) { int i; char * pTemp; // 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 Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p ) { return p->nMemoryAlloc; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_MmFixedReadMaxEntriesUsed( Extra_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 [] ***********************************************************************/ Extra_MmFlex_t * Extra_MmFlexStart() { Extra_MmFlex_t * p; //printf( "allocing flex\n" ); p = ABC_ALLOC( Extra_MmFlex_t, 1 ); memset( p, 0, sizeof(Extra_MmFlex_t) ); p->nEntriesUsed = 0; p->pCurrent = NULL; p->pEnd = NULL; p->nChunkSize = (1 << 12); 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 Extra_MmFlexPrint( Extra_MmFlex_t * p ) { 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 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_MmFlexStop( Extra_MmFlex_t * p ) { int i; if ( p == NULL ) return; //printf( "deleting flex\n" ); 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 * Extra_MmFlexEntryFetch( Extra_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 [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p ) { return p->nMemoryAlloc; } /**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 [] ***********************************************************************/ Extra_MmStep_t * Extra_MmStepStart( int nSteps ) { Extra_MmStep_t * p; int i, k; p = ABC_ALLOC( Extra_MmStep_t, 1 ); memset( p, 0, sizeof(Extra_MmStep_t) ); p->nMems = nSteps; // start the fixed memory managers p->pMems = ABC_ALLOC( Extra_MmFixed_t *, p->nMems ); for ( i = 0; i < p->nMems; i++ ) p->pMems[i] = Extra_MmFixedStart( (8<nMapSize = (4<nMems); p->pMap = ABC_ALLOC( Extra_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 ); return p; } /**Function************************************************************* Synopsis [Stops the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_MmStepStop( Extra_MmStep_t * p ) { int i; for ( i = 0; i < p->nMems; i++ ) Extra_MmFixedStop( p->pMems[i] ); if ( p->pLargeChunks ) { for ( i = 0; i < p->nLargeChunks; i++ ) ABC_FREE( p->pLargeChunks[i] ); ABC_FREE( p->pLargeChunks ); } ABC_FREE( p->pMems ); ABC_FREE( p->pMap ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes ) { if ( nBytes == 0 ) return NULL; if ( nBytes > p->nMapSize ) { // printf( "Allocating %d bytes.\n", nBytes ); // return ABC_ALLOC( char, nBytes ); if ( p->nLargeChunks == p->nLargeChunksAlloc ) { if ( p->nLargeChunksAlloc == 0 ) p->nLargeChunksAlloc = 32; p->nLargeChunksAlloc *= 2; p->pLargeChunks = ABC_REALLOC( void *, p->pLargeChunks, p->nLargeChunksAlloc ); } p->pLargeChunks[ p->nLargeChunks++ ] = ABC_ALLOC( char, nBytes ); return (char *)p->pLargeChunks[ p->nLargeChunks - 1 ]; } return Extra_MmFixedEntryFetch( p->pMap[nBytes] ); } /**Function************************************************************* Synopsis [Recycles the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes ) { if ( nBytes == 0 ) return; if ( nBytes > p->nMapSize ) { // ABC_FREE( pEntry ); return; } Extra_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_MmStepReadMemUsage( Extra_MmStep_t * p ) { int i, nMemTotal = 0; for ( i = 0; i < p->nMems; i++ ) nMemTotal += p->pMems[i]->nMemoryAlloc; return nMemTotal; } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilMisc.c000066400000000000000000002325721300674244400250660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilMisc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Misc procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "extra.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ static void Extra_Permutations_rec( char ** pRes, int nFact, int n, char Array[] ); /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Finds the smallest integer larger of equal than the logarithm.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Extra_Base2LogDouble( double Num ) { double Res; int ResInt; Res = log(Num)/log(2.0); ResInt = (int)Res; if ( ResInt == Res ) return ResInt; else return ResInt+1; } /**Function******************************************************************** Synopsis [Returns the power of two as a double.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ double Extra_Power2( int Degree ) { double Res; assert( Degree >= 0 ); if ( Degree < 32 ) return (double)(01<>= Shift; uTruth = uCof0 | uCof1; } return uTruth; } /**Function************************************************************* Synopsis [Computes N-canonical form using brute-force methods.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_TruthCanonN( unsigned uTruth, int nVars ) { unsigned uTruthMin, uPhase; int nMints, i; nMints = (1 << nVars); uTruthMin = 0xFFFFFFFF; for ( i = 0; i < nMints; i++ ) { uPhase = Extra_TruthPolarize( uTruth, i, nVars ); if ( uTruthMin > uPhase ) uTruthMin = uPhase; } return uTruthMin; } /**Function************************************************************* Synopsis [Computes NN-canonical form using brute-force methods.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars ) { unsigned uTruthMin, uTruthC, uPhase; int nMints, i; nMints = (1 << nVars); uTruthC = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) ); uTruthMin = 0xFFFFFFFF; for ( i = 0; i < nMints; i++ ) { uPhase = Extra_TruthPolarize( uTruth, i, nVars ); if ( uTruthMin > uPhase ) uTruthMin = uPhase; uPhase = Extra_TruthPolarize( uTruthC, i, nVars ); if ( uTruthMin > uPhase ) uTruthMin = uPhase; } return uTruthMin; } /**Function************************************************************* Synopsis [Computes P-canonical form using brute-force methods.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_TruthCanonP( unsigned uTruth, int nVars ) { static int nVarsOld, nPerms; static char ** pPerms = NULL; unsigned uTruthMin, uPerm; int k; if ( pPerms == NULL ) { nPerms = Extra_Factorial( nVars ); pPerms = Extra_Permutations( nVars ); nVarsOld = nVars; } else if ( nVarsOld != nVars ) { ABC_FREE( pPerms ); nPerms = Extra_Factorial( nVars ); pPerms = Extra_Permutations( nVars ); nVarsOld = nVars; } uTruthMin = 0xFFFFFFFF; for ( k = 0; k < nPerms; k++ ) { uPerm = Extra_TruthPermute( uTruth, pPerms[k], nVars, 0 ); if ( uTruthMin > uPerm ) uTruthMin = uPerm; } return uTruthMin; } /**Function************************************************************* Synopsis [Computes NP-canonical form using brute-force methods.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars ) { static int nVarsOld, nPerms; static char ** pPerms = NULL; unsigned uTruthMin, uPhase, uPerm; int nMints, k, i; if ( pPerms == NULL ) { nPerms = Extra_Factorial( nVars ); pPerms = Extra_Permutations( nVars ); nVarsOld = nVars; } else if ( nVarsOld != nVars ) { ABC_FREE( pPerms ); nPerms = Extra_Factorial( nVars ); pPerms = Extra_Permutations( nVars ); nVarsOld = nVars; } nMints = (1 << nVars); uTruthMin = 0xFFFFFFFF; for ( i = 0; i < nMints; i++ ) { uPhase = Extra_TruthPolarize( uTruth, i, nVars ); for ( k = 0; k < nPerms; k++ ) { uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); if ( uTruthMin > uPerm ) uTruthMin = uPerm; } } return uTruthMin; } /**Function************************************************************* Synopsis [Computes NPN-canonical form using brute-force methods.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars ) { static int nVarsOld, nPerms; static char ** pPerms = NULL; unsigned uTruthMin, uTruthC, uPhase, uPerm; int nMints, k, i; if ( pPerms == NULL ) { nPerms = Extra_Factorial( nVars ); pPerms = Extra_Permutations( nVars ); nVarsOld = nVars; } else if ( nVarsOld != nVars ) { ABC_FREE( pPerms ); nPerms = Extra_Factorial( nVars ); pPerms = Extra_Permutations( nVars ); nVarsOld = nVars; } nMints = (1 << nVars); uTruthC = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) ); uTruthMin = 0xFFFFFFFF; for ( i = 0; i < nMints; i++ ) { uPhase = Extra_TruthPolarize( uTruth, i, nVars ); for ( k = 0; k < nPerms; k++ ) { uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); if ( uTruthMin > uPerm ) uTruthMin = uPerm; } uPhase = Extra_TruthPolarize( uTruthC, i, nVars ); for ( k = 0; k < nPerms; k++ ) { uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); if ( uTruthMin > uPerm ) uTruthMin = uPerm; } } return uTruthMin; } /**Function************************************************************* Synopsis [Computes NPN canonical forms for 4-variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ) { unsigned short * uCanons; unsigned char * uMap; unsigned uTruth, uPhase, uPerm; char ** pPerms4, * uPhases, * uPerms; int nFuncs, nClasses; int i, k; nFuncs = (1 << 16); uCanons = ABC_ALLOC( unsigned short, nFuncs ); uPhases = ABC_ALLOC( char, nFuncs ); uPerms = ABC_ALLOC( char, nFuncs ); uMap = ABC_ALLOC( unsigned char, nFuncs ); memset( uCanons, 0, sizeof(unsigned short) * nFuncs ); memset( uPhases, 0, sizeof(char) * nFuncs ); memset( uPerms, 0, sizeof(char) * nFuncs ); memset( uMap, 0, sizeof(unsigned char) * nFuncs ); pPerms4 = Extra_Permutations( 4 ); nClasses = 1; nFuncs = (1 << 15); for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ ) { // skip already assigned if ( uCanons[uTruth] ) { assert( uTruth > uCanons[uTruth] ); uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]]; continue; } uMap[uTruth] = nClasses++; for ( i = 0; i < 16; i++ ) { uPhase = Extra_TruthPolarize( uTruth, i, 4 ); for ( k = 0; k < 24; k++ ) { uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 ); if ( uCanons[uPerm] == 0 ) { uCanons[uPerm] = uTruth; uPhases[uPerm] = i; uPerms[uPerm] = k; uPerm = ~uPerm & 0xFFFF; uCanons[uPerm] = uTruth; uPhases[uPerm] = i | 16; uPerms[uPerm] = k; } else assert( uCanons[uPerm] == uTruth ); } uPhase = Extra_TruthPolarize( ~uTruth & 0xFFFF, i, 4 ); for ( k = 0; k < 24; k++ ) { uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 ); if ( uCanons[uPerm] == 0 ) { uCanons[uPerm] = uTruth; uPhases[uPerm] = i; uPerms[uPerm] = k; uPerm = ~uPerm & 0xFFFF; uCanons[uPerm] = uTruth; uPhases[uPerm] = i | 16; uPerms[uPerm] = k; } else assert( uCanons[uPerm] == uTruth ); } } } uPhases[(1<<16)-1] = 16; assert( nClasses == 222 ); ABC_FREE( pPerms4 ); if ( puCanons ) *puCanons = uCanons; else ABC_FREE( uCanons ); if ( puPhases ) *puPhases = uPhases; else ABC_FREE( uPhases ); if ( puPerms ) *puPerms = uPerms; else ABC_FREE( uPerms ); if ( puMap ) *puMap = uMap; else ABC_FREE( uMap ); } /**Function************************************************************* Synopsis [Computes NPN canonical forms for 4-variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters ) { int nPhasesMax = 8; unsigned * uCanons; unsigned uTruth, uPhase, uTruth32; char ** uPhases, * pCounters; int nFuncs, nClasses, i; nFuncs = (1 << 8); uCanons = ABC_ALLOC( unsigned, nFuncs ); memset( uCanons, 0, sizeof(unsigned) * nFuncs ); pCounters = ABC_ALLOC( char, nFuncs ); memset( pCounters, 0, sizeof(char) * nFuncs ); uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) ); nClasses = 0; for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ ) { // skip already assigned uTruth32 = ((uTruth << 24) | (uTruth << 16) | (uTruth << 8) | uTruth); if ( uCanons[uTruth] ) { assert( uTruth32 > uCanons[uTruth] ); continue; } nClasses++; for ( i = 0; i < 8; i++ ) { uPhase = Extra_TruthPolarize( uTruth, i, 3 ); if ( uCanons[uPhase] == 0 && (uTruth || i==0) ) { uCanons[uPhase] = uTruth32; uPhases[uPhase][0] = i; pCounters[uPhase] = 1; } else { assert( uCanons[uPhase] == uTruth32 ); if ( pCounters[uPhase] < nPhasesMax ) uPhases[uPhase][ (int)pCounters[uPhase]++ ] = i; } } } if ( puCanons ) *puCanons = uCanons; else ABC_FREE( uCanons ); if ( puPhases ) *puPhases = uPhases; else ABC_FREE( uPhases ); if ( ppCounters ) *ppCounters = pCounters; else ABC_FREE( pCounters ); // printf( "The number of 3N-classes = %d.\n", nClasses ); } /**Function************************************************************* Synopsis [Computes NPN canonical forms for 4-variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax ) { unsigned short * uCanons; unsigned uTruth, uPhase; char ** uPhases, * pCounters; int nFuncs, nClasses, i; nFuncs = (1 << 16); uCanons = ABC_ALLOC( unsigned short, nFuncs ); memset( uCanons, 0, sizeof(unsigned short) * nFuncs ); pCounters = ABC_ALLOC( char, nFuncs ); memset( pCounters, 0, sizeof(char) * nFuncs ); uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) ); nClasses = 0; for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ ) { // skip already assigned if ( uCanons[uTruth] ) { assert( uTruth > uCanons[uTruth] ); continue; } nClasses++; for ( i = 0; i < 16; i++ ) { uPhase = Extra_TruthPolarize( uTruth, i, 4 ); if ( uCanons[uPhase] == 0 && (uTruth || i==0) ) { uCanons[uPhase] = uTruth; uPhases[uPhase][0] = i; pCounters[uPhase] = 1; } else { assert( uCanons[uPhase] == uTruth ); if ( pCounters[uPhase] < nPhasesMax ) uPhases[uPhase][ (int)pCounters[uPhase]++ ] = i; } } } if ( puCanons ) *puCanons = uCanons; else ABC_FREE( uCanons ); if ( puPhases ) *puPhases = uPhases; else ABC_FREE( uPhases ); if ( ppCounters ) *ppCounters = pCounters; else ABC_FREE( pCounters ); // printf( "The number of 4N-classes = %d.\n", nClasses ); } /**Function************************************************************* Synopsis [Allocated one-memory-chunk array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void ** Extra_ArrayAlloc( int nCols, int nRows, int Size ) { void ** pRes; char * pBuffer; int i; assert( nCols > 0 && nRows > 0 && Size > 0 ); pBuffer = ABC_ALLOC( char, nCols * (sizeof(void *) + nRows * Size) ); pRes = (void **)pBuffer; pRes[0] = pBuffer + nCols * sizeof(void *); for ( i = 1; i < nCols; i++ ) pRes[i] = (void *)((char *)pRes[0] + i * nRows * Size); return pRes; } /**Function************************************************************* Synopsis [Computes a phase of the 3-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase ) { // cases static unsigned short Cases[16] = { 0, // 0000 - skip 0, // 0001 - skip 0xCCCC, // 0010 - single var 0, // 0011 - skip 0xF0F0, // 0100 - single var 1, // 0101 1, // 0110 0, // 0111 - skip 0xFF00, // 1000 - single var 1, // 1001 1, // 1010 1, // 1011 1, // 1100 1, // 1101 1, // 1110 0 // 1111 - skip }; // permutations static int Perms[16][4] = { { 0, 0, 0, 0 }, // 0000 - skip { 0, 0, 0, 0 }, // 0001 - skip { 0, 0, 0, 0 }, // 0010 - single var { 0, 0, 0, 0 }, // 0011 - skip { 0, 0, 0, 0 }, // 0100 - single var { 0, 2, 1, 3 }, // 0101 { 2, 0, 1, 3 }, // 0110 { 0, 0, 0, 0 }, // 0111 - skip { 0, 0, 0, 0 }, // 1000 - single var { 0, 2, 3, 1 }, // 1001 { 2, 0, 3, 1 }, // 1010 { 0, 1, 3, 2 }, // 1011 { 2, 3, 0, 1 }, // 1100 { 0, 3, 1, 2 }, // 1101 { 3, 0, 1, 2 }, // 1110 { 0, 0, 0, 0 } // 1111 - skip }; int i, k, iRes; unsigned uTruthRes; assert( Phase >= 0 && Phase < 16 ); if ( Cases[Phase] == 0 ) return uTruth; if ( Cases[Phase] > 1 ) return Cases[Phase]; uTruthRes = 0; for ( i = 0; i < 16; i++ ) if ( uTruth & (1 << i) ) { for ( iRes = 0, k = 0; k < 4; k++ ) if ( i & (1 << Perms[Phase][k]) ) iRes |= (1 << k); uTruthRes |= (1 << iRes); } return uTruthRes; } /**Function************************************************************* Synopsis [Computes a phase of the 3-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase ) { // cases static unsigned Cases[32] = { 0, // 00000 - skip 0, // 00001 - skip 0xCCCCCCCC, // 00010 - single var 0, // 00011 - skip 0xF0F0F0F0, // 00100 - single var 1, // 00101 1, // 00110 0, // 00111 - skip 0xFF00FF00, // 01000 - single var 1, // 01001 1, // 01010 1, // 01011 1, // 01100 1, // 01101 1, // 01110 0, // 01111 - skip 0xFFFF0000, // 10000 - skip 1, // 10001 1, // 10010 1, // 10011 1, // 10100 1, // 10101 1, // 10110 1, // 10111 - four var 1, // 11000 1, // 11001 1, // 11010 1, // 11011 - four var 1, // 11100 1, // 11101 - four var 1, // 11110 - four var 0 // 11111 - skip }; // permutations static int Perms[32][5] = { { 0, 0, 0, 0, 0 }, // 00000 - skip { 0, 0, 0, 0, 0 }, // 00001 - skip { 0, 0, 0, 0, 0 }, // 00010 - single var { 0, 0, 0, 0, 0 }, // 00011 - skip { 0, 0, 0, 0, 0 }, // 00100 - single var { 0, 2, 1, 3, 4 }, // 00101 { 2, 0, 1, 3, 4 }, // 00110 { 0, 0, 0, 0, 0 }, // 00111 - skip { 0, 0, 0, 0, 0 }, // 01000 - single var { 0, 2, 3, 1, 4 }, // 01001 { 2, 0, 3, 1, 4 }, // 01010 { 0, 1, 3, 2, 4 }, // 01011 { 2, 3, 0, 1, 4 }, // 01100 { 0, 3, 1, 2, 4 }, // 01101 { 3, 0, 1, 2, 4 }, // 01110 { 0, 0, 0, 0, 0 }, // 01111 - skip { 0, 0, 0, 0, 0 }, // 10000 - single var { 0, 4, 2, 3, 1 }, // 10001 { 4, 0, 2, 3, 1 }, // 10010 { 0, 1, 3, 4, 2 }, // 10011 { 2, 3, 0, 4, 1 }, // 10100 { 0, 3, 1, 4, 2 }, // 10101 { 3, 0, 1, 4, 2 }, // 10110 { 0, 1, 2, 4, 3 }, // 10111 - four var { 2, 3, 4, 0, 1 }, // 11000 { 0, 3, 4, 1, 2 }, // 11001 { 3, 0, 4, 1, 2 }, // 11010 { 0, 1, 4, 2, 3 }, // 11011 - four var { 3, 4, 0, 1, 2 }, // 11100 { 0, 4, 1, 2, 3 }, // 11101 - four var { 4, 0, 1, 2, 3 }, // 11110 - four var { 0, 0, 0, 0, 0 } // 11111 - skip }; int i, k, iRes; unsigned uTruthRes; assert( Phase >= 0 && Phase < 32 ); if ( Cases[Phase] == 0 ) return uTruth; if ( Cases[Phase] > 1 ) return Cases[Phase]; uTruthRes = 0; for ( i = 0; i < 32; i++ ) if ( uTruth & (1 << i) ) { for ( iRes = 0, k = 0; k < 5; k++ ) if ( i & (1 << Perms[Phase][k]) ) iRes |= (1 << k); uTruthRes |= (1 << iRes); } return uTruthRes; } /**Function************************************************************* Synopsis [Computes a phase of the 3-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes ) { // cases static unsigned Cases[64] = { 0, // 000000 - skip 0, // 000001 - skip 0xCCCCCCCC, // 000010 - single var 0, // 000011 - skip 0xF0F0F0F0, // 000100 - single var 1, // 000101 1, // 000110 0, // 000111 - skip 0xFF00FF00, // 001000 - single var 1, // 001001 1, // 001010 1, // 001011 1, // 001100 1, // 001101 1, // 001110 0, // 001111 - skip 0xFFFF0000, // 010000 - skip 1, // 010001 1, // 010010 1, // 010011 1, // 010100 1, // 010101 1, // 010110 1, // 010111 - four var 1, // 011000 1, // 011001 1, // 011010 1, // 011011 - four var 1, // 011100 1, // 011101 - four var 1, // 011110 - four var 0, // 011111 - skip 0xFFFFFFFF, // 100000 - single var 1, // 100001 1, // 100010 1, // 100011 1, // 100100 1, // 100101 1, // 100110 1, // 100111 1, // 101000 1, // 101001 1, // 101010 1, // 101011 1, // 101100 1, // 101101 1, // 101110 1, // 101111 1, // 110000 1, // 110001 1, // 110010 1, // 110011 1, // 110100 1, // 110101 1, // 110110 1, // 110111 1, // 111000 1, // 111001 1, // 111010 1, // 111011 1, // 111100 1, // 111101 1, // 111110 0 // 111111 - skip }; // permutations static int Perms[64][6] = { { 0, 0, 0, 0, 0, 0 }, // 000000 - skip { 0, 0, 0, 0, 0, 0 }, // 000001 - skip { 0, 0, 0, 0, 0, 0 }, // 000010 - single var { 0, 0, 0, 0, 0, 0 }, // 000011 - skip { 0, 0, 0, 0, 0, 0 }, // 000100 - single var { 0, 2, 1, 3, 4, 5 }, // 000101 { 2, 0, 1, 3, 4, 5 }, // 000110 { 0, 0, 0, 0, 0, 0 }, // 000111 - skip { 0, 0, 0, 0, 0, 0 }, // 001000 - single var { 0, 2, 3, 1, 4, 5 }, // 001001 { 2, 0, 3, 1, 4, 5 }, // 001010 { 0, 1, 3, 2, 4, 5 }, // 001011 { 2, 3, 0, 1, 4, 5 }, // 001100 { 0, 3, 1, 2, 4, 5 }, // 001101 { 3, 0, 1, 2, 4, 5 }, // 001110 { 0, 0, 0, 0, 0, 0 }, // 001111 - skip { 0, 0, 0, 0, 0, 0 }, // 010000 - skip { 0, 4, 2, 3, 1, 5 }, // 010001 { 4, 0, 2, 3, 1, 5 }, // 010010 { 0, 1, 3, 4, 2, 5 }, // 010011 { 2, 3, 0, 4, 1, 5 }, // 010100 { 0, 3, 1, 4, 2, 5 }, // 010101 { 3, 0, 1, 4, 2, 5 }, // 010110 { 0, 1, 2, 4, 3, 5 }, // 010111 - four var { 2, 3, 4, 0, 1, 5 }, // 011000 { 0, 3, 4, 1, 2, 5 }, // 011001 { 3, 0, 4, 1, 2, 5 }, // 011010 { 0, 1, 4, 2, 3, 5 }, // 011011 - four var { 3, 4, 0, 1, 2, 5 }, // 011100 { 0, 4, 1, 2, 3, 5 }, // 011101 - four var { 4, 0, 1, 2, 3, 5 }, // 011110 - four var { 0, 0, 0, 0, 0, 0 }, // 011111 - skip { 0, 0, 0, 0, 0, 0 }, // 100000 - single var { 0, 2, 3, 4, 5, 1 }, // 100001 { 2, 0, 3, 4, 5, 1 }, // 100010 { 0, 1, 3, 4, 5, 2 }, // 100011 { 2, 3, 0, 4, 5, 1 }, // 100100 { 0, 3, 1, 4, 5, 2 }, // 100101 { 3, 0, 1, 4, 5, 2 }, // 100110 { 0, 1, 2, 4, 5, 3 }, // 100111 { 2, 3, 4, 0, 5, 1 }, // 101000 { 0, 3, 4, 1, 5, 2 }, // 101001 { 3, 0, 4, 1, 5, 2 }, // 101010 { 0, 1, 4, 2, 5, 3 }, // 101011 { 3, 4, 0, 1, 5, 2 }, // 101100 { 0, 4, 1, 2, 5, 3 }, // 101101 { 4, 0, 1, 2, 5, 3 }, // 101110 { 0, 1, 2, 3, 5, 4 }, // 101111 { 2, 3, 4, 5, 0, 1 }, // 110000 { 0, 3, 4, 5, 1, 2 }, // 110001 { 3, 0, 4, 5, 1, 2 }, // 110010 { 0, 1, 4, 5, 2, 3 }, // 110011 { 3, 4, 0, 5, 1, 2 }, // 110100 { 0, 4, 1, 5, 2, 3 }, // 110101 { 4, 0, 1, 5, 2, 3 }, // 110110 { 0, 1, 2, 5, 3, 4 }, // 110111 { 3, 4, 5, 0, 1, 2 }, // 111000 { 0, 4, 5, 1, 2, 3 }, // 111001 { 4, 0, 5, 1, 2, 3 }, // 111010 { 0, 1, 5, 2, 3, 4 }, // 111011 { 4, 5, 0, 1, 2, 3 }, // 111100 { 0, 5, 1, 2, 3, 4 }, // 111101 { 5, 0, 1, 2, 3, 4 }, // 111110 { 0, 0, 0, 0, 0, 0 } // 111111 - skip }; int i, k, iRes; assert( Phase >= 0 && Phase < 64 ); if ( Cases[Phase] == 0 ) { uTruthRes[0] = uTruth[0]; uTruthRes[1] = uTruth[1]; return; } if ( Cases[Phase] > 1 ) { if ( Phase == 32 ) { uTruthRes[0] = 0x00000000; uTruthRes[1] = 0xFFFFFFFF; } else { uTruthRes[0] = Cases[Phase]; uTruthRes[1] = Cases[Phase]; } return; } uTruthRes[0] = 0; uTruthRes[1] = 0; for ( i = 0; i < 64; i++ ) { if ( i < 32 ) { if ( uTruth[0] & (1 << i) ) { for ( iRes = 0, k = 0; k < 6; k++ ) if ( i & (1 << Perms[Phase][k]) ) iRes |= (1 << k); if ( iRes < 32 ) uTruthRes[0] |= (1 << iRes); else uTruthRes[1] |= (1 << (iRes-32)); } } else { if ( uTruth[1] & (1 << (i-32)) ) { for ( iRes = 0, k = 0; k < 6; k++ ) if ( i & (1 << Perms[Phase][k]) ) iRes |= (1 << k); if ( iRes < 32 ) uTruthRes[0] |= (1 << iRes); else uTruthRes[1] |= (1 << (iRes-32)); } } } } /**Function************************************************************* Synopsis [Computes a phase of the 8-var function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR ) { // elementary truth tables static unsigned uTruths[8][8] = { { 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 } }; static char Cases[256] = { 0, // 00000000 0, // 00000001 1, // 00000010 0, // 00000011 2, // 00000100 -1, // 00000101 -1, // 00000110 0, // 00000111 3, // 00001000 -1, // 00001001 -1, // 00001010 -1, // 00001011 -1, // 00001100 -1, // 00001101 -1, // 00001110 0, // 00001111 4, // 00010000 -1, // 00010001 -1, // 00010010 -1, // 00010011 -1, // 00010100 -1, // 00010101 -1, // 00010110 -1, // 00010111 -1, // 00011000 -1, // 00011001 -1, // 00011010 -1, // 00011011 -1, // 00011100 -1, // 00011101 -1, // 00011110 0, // 00011111 5, // 00100000 -1, // 00100001 -1, // 00100010 -1, // 00100011 -1, // 00100100 -1, // 00100101 -1, // 00100110 -1, // 00100111 -1, // 00101000 -1, // 00101001 -1, // 00101010 -1, // 00101011 -1, // 00101100 -1, // 00101101 -1, // 00101110 -1, // 00101111 -1, // 00110000 -1, // 00110001 -1, // 00110010 -1, // 00110011 -1, // 00110100 -1, // 00110101 -1, // 00110110 -1, // 00110111 -1, // 00111000 -1, // 00111001 -1, // 00111010 -1, // 00111011 -1, // 00111100 -1, // 00111101 -1, // 00111110 0, // 00111111 6, // 01000000 -1, // 01000001 -1, // 01000010 -1, // 01000011 -1, // 01000100 -1, // 01000101 -1, // 01000110 -1, // 01000111 -1, // 01001000 -1, // 01001001 -1, // 01001010 -1, // 01001011 -1, // 01001100 -1, // 01001101 -1, // 01001110 -1, // 01001111 -1, // 01010000 -1, // 01010001 -1, // 01010010 -1, // 01010011 -1, // 01010100 -1, // 01010101 -1, // 01010110 -1, // 01010111 -1, // 01011000 -1, // 01011001 -1, // 01011010 -1, // 01011011 -1, // 01011100 -1, // 01011101 -1, // 01011110 -1, // 01011111 -1, // 01100000 -1, // 01100001 -1, // 01100010 -1, // 01100011 -1, // 01100100 -1, // 01100101 -1, // 01100110 -1, // 01100111 -1, // 01101000 -1, // 01101001 -1, // 01101010 -1, // 01101011 -1, // 01101100 -1, // 01101101 -1, // 01101110 -1, // 01101111 -1, // 01110000 -1, // 01110001 -1, // 01110010 -1, // 01110011 -1, // 01110100 -1, // 01110101 -1, // 01110110 -1, // 01110111 -1, // 01111000 -1, // 01111001 -1, // 01111010 -1, // 01111011 -1, // 01111100 -1, // 01111101 -1, // 01111110 0, // 01111111 7, // 10000000 -1, // 10000001 -1, // 10000010 -1, // 10000011 -1, // 10000100 -1, // 10000101 -1, // 10000110 -1, // 10000111 -1, // 10001000 -1, // 10001001 -1, // 10001010 -1, // 10001011 -1, // 10001100 -1, // 10001101 -1, // 10001110 -1, // 10001111 -1, // 10010000 -1, // 10010001 -1, // 10010010 -1, // 10010011 -1, // 10010100 -1, // 10010101 -1, // 10010110 -1, // 10010111 -1, // 10011000 -1, // 10011001 -1, // 10011010 -1, // 10011011 -1, // 10011100 -1, // 10011101 -1, // 10011110 -1, // 10011111 -1, // 10100000 -1, // 10100001 -1, // 10100010 -1, // 10100011 -1, // 10100100 -1, // 10100101 -1, // 10100110 -1, // 10100111 -1, // 10101000 -1, // 10101001 -1, // 10101010 -1, // 10101011 -1, // 10101100 -1, // 10101101 -1, // 10101110 -1, // 10101111 -1, // 10110000 -1, // 10110001 -1, // 10110010 -1, // 10110011 -1, // 10110100 -1, // 10110101 -1, // 10110110 -1, // 10110111 -1, // 10111000 -1, // 10111001 -1, // 10111010 -1, // 10111011 -1, // 10111100 -1, // 10111101 -1, // 10111110 -1, // 10111111 -1, // 11000000 -1, // 11000001 -1, // 11000010 -1, // 11000011 -1, // 11000100 -1, // 11000101 -1, // 11000110 -1, // 11000111 -1, // 11001000 -1, // 11001001 -1, // 11001010 -1, // 11001011 -1, // 11001100 -1, // 11001101 -1, // 11001110 -1, // 11001111 -1, // 11010000 -1, // 11010001 -1, // 11010010 -1, // 11010011 -1, // 11010100 -1, // 11010101 -1, // 11010110 -1, // 11010111 -1, // 11011000 -1, // 11011001 -1, // 11011010 -1, // 11011011 -1, // 11011100 -1, // 11011101 -1, // 11011110 -1, // 11011111 -1, // 11100000 -1, // 11100001 -1, // 11100010 -1, // 11100011 -1, // 11100100 -1, // 11100101 -1, // 11100110 -1, // 11100111 -1, // 11101000 -1, // 11101001 -1, // 11101010 -1, // 11101011 -1, // 11101100 -1, // 11101101 -1, // 11101110 -1, // 11101111 -1, // 11110000 -1, // 11110001 -1, // 11110010 -1, // 11110011 -1, // 11110100 -1, // 11110101 -1, // 11110110 -1, // 11110111 -1, // 11111000 -1, // 11111001 -1, // 11111010 -1, // 11111011 -1, // 11111100 -1, // 11111101 -1, // 11111110 0 // 11111111 }; static char Perms[256][8] = { { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000000 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000001 { 1, 0, 2, 3, 4, 5, 6, 7 }, // 00000010 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000011 { 1, 2, 0, 3, 4, 5, 6, 7 }, // 00000100 { 0, 2, 1, 3, 4, 5, 6, 7 }, // 00000101 { 2, 0, 1, 3, 4, 5, 6, 7 }, // 00000110 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000111 { 1, 2, 3, 0, 4, 5, 6, 7 }, // 00001000 { 0, 2, 3, 1, 4, 5, 6, 7 }, // 00001001 { 2, 0, 3, 1, 4, 5, 6, 7 }, // 00001010 { 0, 1, 3, 2, 4, 5, 6, 7 }, // 00001011 { 2, 3, 0, 1, 4, 5, 6, 7 }, // 00001100 { 0, 3, 1, 2, 4, 5, 6, 7 }, // 00001101 { 3, 0, 1, 2, 4, 5, 6, 7 }, // 00001110 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00001111 { 1, 2, 3, 4, 0, 5, 6, 7 }, // 00010000 { 0, 2, 3, 4, 1, 5, 6, 7 }, // 00010001 { 2, 0, 3, 4, 1, 5, 6, 7 }, // 00010010 { 0, 1, 3, 4, 2, 5, 6, 7 }, // 00010011 { 2, 3, 0, 4, 1, 5, 6, 7 }, // 00010100 { 0, 3, 1, 4, 2, 5, 6, 7 }, // 00010101 { 3, 0, 1, 4, 2, 5, 6, 7 }, // 00010110 { 0, 1, 2, 4, 3, 5, 6, 7 }, // 00010111 { 2, 3, 4, 0, 1, 5, 6, 7 }, // 00011000 { 0, 3, 4, 1, 2, 5, 6, 7 }, // 00011001 { 3, 0, 4, 1, 2, 5, 6, 7 }, // 00011010 { 0, 1, 4, 2, 3, 5, 6, 7 }, // 00011011 { 3, 4, 0, 1, 2, 5, 6, 7 }, // 00011100 { 0, 4, 1, 2, 3, 5, 6, 7 }, // 00011101 { 4, 0, 1, 2, 3, 5, 6, 7 }, // 00011110 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00011111 { 1, 2, 3, 4, 5, 0, 6, 7 }, // 00100000 { 0, 2, 3, 4, 5, 1, 6, 7 }, // 00100001 { 2, 0, 3, 4, 5, 1, 6, 7 }, // 00100010 { 0, 1, 3, 4, 5, 2, 6, 7 }, // 00100011 { 2, 3, 0, 4, 5, 1, 6, 7 }, // 00100100 { 0, 3, 1, 4, 5, 2, 6, 7 }, // 00100101 { 3, 0, 1, 4, 5, 2, 6, 7 }, // 00100110 { 0, 1, 2, 4, 5, 3, 6, 7 }, // 00100111 { 2, 3, 4, 0, 5, 1, 6, 7 }, // 00101000 { 0, 3, 4, 1, 5, 2, 6, 7 }, // 00101001 { 3, 0, 4, 1, 5, 2, 6, 7 }, // 00101010 { 0, 1, 4, 2, 5, 3, 6, 7 }, // 00101011 { 3, 4, 0, 1, 5, 2, 6, 7 }, // 00101100 { 0, 4, 1, 2, 5, 3, 6, 7 }, // 00101101 { 4, 0, 1, 2, 5, 3, 6, 7 }, // 00101110 { 0, 1, 2, 3, 5, 4, 6, 7 }, // 00101111 { 2, 3, 4, 5, 0, 1, 6, 7 }, // 00110000 { 0, 3, 4, 5, 1, 2, 6, 7 }, // 00110001 { 3, 0, 4, 5, 1, 2, 6, 7 }, // 00110010 { 0, 1, 4, 5, 2, 3, 6, 7 }, // 00110011 { 3, 4, 0, 5, 1, 2, 6, 7 }, // 00110100 { 0, 4, 1, 5, 2, 3, 6, 7 }, // 00110101 { 4, 0, 1, 5, 2, 3, 6, 7 }, // 00110110 { 0, 1, 2, 5, 3, 4, 6, 7 }, // 00110111 { 3, 4, 5, 0, 1, 2, 6, 7 }, // 00111000 { 0, 4, 5, 1, 2, 3, 6, 7 }, // 00111001 { 4, 0, 5, 1, 2, 3, 6, 7 }, // 00111010 { 0, 1, 5, 2, 3, 4, 6, 7 }, // 00111011 { 4, 5, 0, 1, 2, 3, 6, 7 }, // 00111100 { 0, 5, 1, 2, 3, 4, 6, 7 }, // 00111101 { 5, 0, 1, 2, 3, 4, 6, 7 }, // 00111110 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00111111 { 1, 2, 3, 4, 5, 6, 0, 7 }, // 01000000 { 0, 2, 3, 4, 5, 6, 1, 7 }, // 01000001 { 2, 0, 3, 4, 5, 6, 1, 7 }, // 01000010 { 0, 1, 3, 4, 5, 6, 2, 7 }, // 01000011 { 2, 3, 0, 4, 5, 6, 1, 7 }, // 01000100 { 0, 3, 1, 4, 5, 6, 2, 7 }, // 01000101 { 3, 0, 1, 4, 5, 6, 2, 7 }, // 01000110 { 0, 1, 2, 4, 5, 6, 3, 7 }, // 01000111 { 2, 3, 4, 0, 5, 6, 1, 7 }, // 01001000 { 0, 3, 4, 1, 5, 6, 2, 7 }, // 01001001 { 3, 0, 4, 1, 5, 6, 2, 7 }, // 01001010 { 0, 1, 4, 2, 5, 6, 3, 7 }, // 01001011 { 3, 4, 0, 1, 5, 6, 2, 7 }, // 01001100 { 0, 4, 1, 2, 5, 6, 3, 7 }, // 01001101 { 4, 0, 1, 2, 5, 6, 3, 7 }, // 01001110 { 0, 1, 2, 3, 5, 6, 4, 7 }, // 01001111 { 2, 3, 4, 5, 0, 6, 1, 7 }, // 01010000 { 0, 3, 4, 5, 1, 6, 2, 7 }, // 01010001 { 3, 0, 4, 5, 1, 6, 2, 7 }, // 01010010 { 0, 1, 4, 5, 2, 6, 3, 7 }, // 01010011 { 3, 4, 0, 5, 1, 6, 2, 7 }, // 01010100 { 0, 4, 1, 5, 2, 6, 3, 7 }, // 01010101 { 4, 0, 1, 5, 2, 6, 3, 7 }, // 01010110 { 0, 1, 2, 5, 3, 6, 4, 7 }, // 01010111 { 3, 4, 5, 0, 1, 6, 2, 7 }, // 01011000 { 0, 4, 5, 1, 2, 6, 3, 7 }, // 01011001 { 4, 0, 5, 1, 2, 6, 3, 7 }, // 01011010 { 0, 1, 5, 2, 3, 6, 4, 7 }, // 01011011 { 4, 5, 0, 1, 2, 6, 3, 7 }, // 01011100 { 0, 5, 1, 2, 3, 6, 4, 7 }, // 01011101 { 5, 0, 1, 2, 3, 6, 4, 7 }, // 01011110 { 0, 1, 2, 3, 4, 6, 5, 7 }, // 01011111 { 2, 3, 4, 5, 6, 0, 1, 7 }, // 01100000 { 0, 3, 4, 5, 6, 1, 2, 7 }, // 01100001 { 3, 0, 4, 5, 6, 1, 2, 7 }, // 01100010 { 0, 1, 4, 5, 6, 2, 3, 7 }, // 01100011 { 3, 4, 0, 5, 6, 1, 2, 7 }, // 01100100 { 0, 4, 1, 5, 6, 2, 3, 7 }, // 01100101 { 4, 0, 1, 5, 6, 2, 3, 7 }, // 01100110 { 0, 1, 2, 5, 6, 3, 4, 7 }, // 01100111 { 3, 4, 5, 0, 6, 1, 2, 7 }, // 01101000 { 0, 4, 5, 1, 6, 2, 3, 7 }, // 01101001 { 4, 0, 5, 1, 6, 2, 3, 7 }, // 01101010 { 0, 1, 5, 2, 6, 3, 4, 7 }, // 01101011 { 4, 5, 0, 1, 6, 2, 3, 7 }, // 01101100 { 0, 5, 1, 2, 6, 3, 4, 7 }, // 01101101 { 5, 0, 1, 2, 6, 3, 4, 7 }, // 01101110 { 0, 1, 2, 3, 6, 4, 5, 7 }, // 01101111 { 3, 4, 5, 6, 0, 1, 2, 7 }, // 01110000 { 0, 4, 5, 6, 1, 2, 3, 7 }, // 01110001 { 4, 0, 5, 6, 1, 2, 3, 7 }, // 01110010 { 0, 1, 5, 6, 2, 3, 4, 7 }, // 01110011 { 4, 5, 0, 6, 1, 2, 3, 7 }, // 01110100 { 0, 5, 1, 6, 2, 3, 4, 7 }, // 01110101 { 5, 0, 1, 6, 2, 3, 4, 7 }, // 01110110 { 0, 1, 2, 6, 3, 4, 5, 7 }, // 01110111 { 4, 5, 6, 0, 1, 2, 3, 7 }, // 01111000 { 0, 5, 6, 1, 2, 3, 4, 7 }, // 01111001 { 5, 0, 6, 1, 2, 3, 4, 7 }, // 01111010 { 0, 1, 6, 2, 3, 4, 5, 7 }, // 01111011 { 5, 6, 0, 1, 2, 3, 4, 7 }, // 01111100 { 0, 6, 1, 2, 3, 4, 5, 7 }, // 01111101 { 6, 0, 1, 2, 3, 4, 5, 7 }, // 01111110 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 01111111 { 1, 2, 3, 4, 5, 6, 7, 0 }, // 10000000 { 0, 2, 3, 4, 5, 6, 7, 1 }, // 10000001 { 2, 0, 3, 4, 5, 6, 7, 1 }, // 10000010 { 0, 1, 3, 4, 5, 6, 7, 2 }, // 10000011 { 2, 3, 0, 4, 5, 6, 7, 1 }, // 10000100 { 0, 3, 1, 4, 5, 6, 7, 2 }, // 10000101 { 3, 0, 1, 4, 5, 6, 7, 2 }, // 10000110 { 0, 1, 2, 4, 5, 6, 7, 3 }, // 10000111 { 2, 3, 4, 0, 5, 6, 7, 1 }, // 10001000 { 0, 3, 4, 1, 5, 6, 7, 2 }, // 10001001 { 3, 0, 4, 1, 5, 6, 7, 2 }, // 10001010 { 0, 1, 4, 2, 5, 6, 7, 3 }, // 10001011 { 3, 4, 0, 1, 5, 6, 7, 2 }, // 10001100 { 0, 4, 1, 2, 5, 6, 7, 3 }, // 10001101 { 4, 0, 1, 2, 5, 6, 7, 3 }, // 10001110 { 0, 1, 2, 3, 5, 6, 7, 4 }, // 10001111 { 2, 3, 4, 5, 0, 6, 7, 1 }, // 10010000 { 0, 3, 4, 5, 1, 6, 7, 2 }, // 10010001 { 3, 0, 4, 5, 1, 6, 7, 2 }, // 10010010 { 0, 1, 4, 5, 2, 6, 7, 3 }, // 10010011 { 3, 4, 0, 5, 1, 6, 7, 2 }, // 10010100 { 0, 4, 1, 5, 2, 6, 7, 3 }, // 10010101 { 4, 0, 1, 5, 2, 6, 7, 3 }, // 10010110 { 0, 1, 2, 5, 3, 6, 7, 4 }, // 10010111 { 3, 4, 5, 0, 1, 6, 7, 2 }, // 10011000 { 0, 4, 5, 1, 2, 6, 7, 3 }, // 10011001 { 4, 0, 5, 1, 2, 6, 7, 3 }, // 10011010 { 0, 1, 5, 2, 3, 6, 7, 4 }, // 10011011 { 4, 5, 0, 1, 2, 6, 7, 3 }, // 10011100 { 0, 5, 1, 2, 3, 6, 7, 4 }, // 10011101 { 5, 0, 1, 2, 3, 6, 7, 4 }, // 10011110 { 0, 1, 2, 3, 4, 6, 7, 5 }, // 10011111 { 2, 3, 4, 5, 6, 0, 7, 1 }, // 10100000 { 0, 3, 4, 5, 6, 1, 7, 2 }, // 10100001 { 3, 0, 4, 5, 6, 1, 7, 2 }, // 10100010 { 0, 1, 4, 5, 6, 2, 7, 3 }, // 10100011 { 3, 4, 0, 5, 6, 1, 7, 2 }, // 10100100 { 0, 4, 1, 5, 6, 2, 7, 3 }, // 10100101 { 4, 0, 1, 5, 6, 2, 7, 3 }, // 10100110 { 0, 1, 2, 5, 6, 3, 7, 4 }, // 10100111 { 3, 4, 5, 0, 6, 1, 7, 2 }, // 10101000 { 0, 4, 5, 1, 6, 2, 7, 3 }, // 10101001 { 4, 0, 5, 1, 6, 2, 7, 3 }, // 10101010 { 0, 1, 5, 2, 6, 3, 7, 4 }, // 10101011 { 4, 5, 0, 1, 6, 2, 7, 3 }, // 10101100 { 0, 5, 1, 2, 6, 3, 7, 4 }, // 10101101 { 5, 0, 1, 2, 6, 3, 7, 4 }, // 10101110 { 0, 1, 2, 3, 6, 4, 7, 5 }, // 10101111 { 3, 4, 5, 6, 0, 1, 7, 2 }, // 10110000 { 0, 4, 5, 6, 1, 2, 7, 3 }, // 10110001 { 4, 0, 5, 6, 1, 2, 7, 3 }, // 10110010 { 0, 1, 5, 6, 2, 3, 7, 4 }, // 10110011 { 4, 5, 0, 6, 1, 2, 7, 3 }, // 10110100 { 0, 5, 1, 6, 2, 3, 7, 4 }, // 10110101 { 5, 0, 1, 6, 2, 3, 7, 4 }, // 10110110 { 0, 1, 2, 6, 3, 4, 7, 5 }, // 10110111 { 4, 5, 6, 0, 1, 2, 7, 3 }, // 10111000 { 0, 5, 6, 1, 2, 3, 7, 4 }, // 10111001 { 5, 0, 6, 1, 2, 3, 7, 4 }, // 10111010 { 0, 1, 6, 2, 3, 4, 7, 5 }, // 10111011 { 5, 6, 0, 1, 2, 3, 7, 4 }, // 10111100 { 0, 6, 1, 2, 3, 4, 7, 5 }, // 10111101 { 6, 0, 1, 2, 3, 4, 7, 5 }, // 10111110 { 0, 1, 2, 3, 4, 5, 7, 6 }, // 10111111 { 2, 3, 4, 5, 6, 7, 0, 1 }, // 11000000 { 0, 3, 4, 5, 6, 7, 1, 2 }, // 11000001 { 3, 0, 4, 5, 6, 7, 1, 2 }, // 11000010 { 0, 1, 4, 5, 6, 7, 2, 3 }, // 11000011 { 3, 4, 0, 5, 6, 7, 1, 2 }, // 11000100 { 0, 4, 1, 5, 6, 7, 2, 3 }, // 11000101 { 4, 0, 1, 5, 6, 7, 2, 3 }, // 11000110 { 0, 1, 2, 5, 6, 7, 3, 4 }, // 11000111 { 3, 4, 5, 0, 6, 7, 1, 2 }, // 11001000 { 0, 4, 5, 1, 6, 7, 2, 3 }, // 11001001 { 4, 0, 5, 1, 6, 7, 2, 3 }, // 11001010 { 0, 1, 5, 2, 6, 7, 3, 4 }, // 11001011 { 4, 5, 0, 1, 6, 7, 2, 3 }, // 11001100 { 0, 5, 1, 2, 6, 7, 3, 4 }, // 11001101 { 5, 0, 1, 2, 6, 7, 3, 4 }, // 11001110 { 0, 1, 2, 3, 6, 7, 4, 5 }, // 11001111 { 3, 4, 5, 6, 0, 7, 1, 2 }, // 11010000 { 0, 4, 5, 6, 1, 7, 2, 3 }, // 11010001 { 4, 0, 5, 6, 1, 7, 2, 3 }, // 11010010 { 0, 1, 5, 6, 2, 7, 3, 4 }, // 11010011 { 4, 5, 0, 6, 1, 7, 2, 3 }, // 11010100 { 0, 5, 1, 6, 2, 7, 3, 4 }, // 11010101 { 5, 0, 1, 6, 2, 7, 3, 4 }, // 11010110 { 0, 1, 2, 6, 3, 7, 4, 5 }, // 11010111 { 4, 5, 6, 0, 1, 7, 2, 3 }, // 11011000 { 0, 5, 6, 1, 2, 7, 3, 4 }, // 11011001 { 5, 0, 6, 1, 2, 7, 3, 4 }, // 11011010 { 0, 1, 6, 2, 3, 7, 4, 5 }, // 11011011 { 5, 6, 0, 1, 2, 7, 3, 4 }, // 11011100 { 0, 6, 1, 2, 3, 7, 4, 5 }, // 11011101 { 6, 0, 1, 2, 3, 7, 4, 5 }, // 11011110 { 0, 1, 2, 3, 4, 7, 5, 6 }, // 11011111 { 3, 4, 5, 6, 7, 0, 1, 2 }, // 11100000 { 0, 4, 5, 6, 7, 1, 2, 3 }, // 11100001 { 4, 0, 5, 6, 7, 1, 2, 3 }, // 11100010 { 0, 1, 5, 6, 7, 2, 3, 4 }, // 11100011 { 4, 5, 0, 6, 7, 1, 2, 3 }, // 11100100 { 0, 5, 1, 6, 7, 2, 3, 4 }, // 11100101 { 5, 0, 1, 6, 7, 2, 3, 4 }, // 11100110 { 0, 1, 2, 6, 7, 3, 4, 5 }, // 11100111 { 4, 5, 6, 0, 7, 1, 2, 3 }, // 11101000 { 0, 5, 6, 1, 7, 2, 3, 4 }, // 11101001 { 5, 0, 6, 1, 7, 2, 3, 4 }, // 11101010 { 0, 1, 6, 2, 7, 3, 4, 5 }, // 11101011 { 5, 6, 0, 1, 7, 2, 3, 4 }, // 11101100 { 0, 6, 1, 2, 7, 3, 4, 5 }, // 11101101 { 6, 0, 1, 2, 7, 3, 4, 5 }, // 11101110 { 0, 1, 2, 3, 7, 4, 5, 6 }, // 11101111 { 4, 5, 6, 7, 0, 1, 2, 3 }, // 11110000 { 0, 5, 6, 7, 1, 2, 3, 4 }, // 11110001 { 5, 0, 6, 7, 1, 2, 3, 4 }, // 11110010 { 0, 1, 6, 7, 2, 3, 4, 5 }, // 11110011 { 5, 6, 0, 7, 1, 2, 3, 4 }, // 11110100 { 0, 6, 1, 7, 2, 3, 4, 5 }, // 11110101 { 6, 0, 1, 7, 2, 3, 4, 5 }, // 11110110 { 0, 1, 2, 7, 3, 4, 5, 6 }, // 11110111 { 5, 6, 7, 0, 1, 2, 3, 4 }, // 11111000 { 0, 6, 7, 1, 2, 3, 4, 5 }, // 11111001 { 6, 0, 7, 1, 2, 3, 4, 5 }, // 11111010 { 0, 1, 7, 2, 3, 4, 5, 6 }, // 11111011 { 6, 7, 0, 1, 2, 3, 4, 5 }, // 11111100 { 0, 7, 1, 2, 3, 4, 5, 6 }, // 11111101 { 7, 0, 1, 2, 3, 4, 5, 6 }, // 11111110 { 0, 1, 2, 3, 4, 5, 6, 7 } // 11111111 }; assert( uPhase > 0 && uPhase < (unsigned)(1 << nVars) ); // the same function if ( Cases[uPhase] == 0 ) { int i; for ( i = 0; i < nWords; i++ ) puTruthR[i] = puTruth[i]; return; } // an elementary variable if ( Cases[uPhase] > 0 ) { int i; for ( i = 0; i < nWords; i++ ) puTruthR[i] = uTruths[(int)Cases[uPhase]][i]; return; } // truth table takes one word if ( nWords == 1 ) { int i, k, nMints, iRes; char * pPerm = Perms[uPhase]; puTruthR[0] = 0; nMints = (1 << nVars); for ( i = 0; i < nMints; i++ ) if ( puTruth[0] & (1 << i) ) { for ( iRes = 0, k = 0; k < nVars; k++ ) if ( i & (1 << pPerm[k]) ) iRes |= (1 << k); puTruthR[0] |= (1 << iRes); } return; } else if ( nWords == 2 ) { int i, k, iRes; char * pPerm = Perms[uPhase]; puTruthR[0] = puTruthR[1] = 0; for ( i = 0; i < 32; i++ ) { if ( puTruth[0] & (1 << i) ) { for ( iRes = 0, k = 0; k < 6; k++ ) if ( i & (1 << pPerm[k]) ) iRes |= (1 << k); if ( iRes < 32 ) puTruthR[0] |= (1 << iRes); else puTruthR[1] |= (1 << (iRes-32)); } } for ( ; i < 64; i++ ) { if ( puTruth[1] & (1 << (i-32)) ) { for ( iRes = 0, k = 0; k < 6; k++ ) if ( i & (1 << pPerm[k]) ) iRes |= (1 << k); if ( iRes < 32 ) puTruthR[0] |= (1 << iRes); else puTruthR[1] |= (1 << (iRes-32)); } } } // truth table takes more than one word else { int i, k, nMints, iRes; char * pPerm = Perms[uPhase]; for ( i = 0; i < nWords; i++ ) puTruthR[i] = 0; nMints = (1 << nVars); for ( i = 0; i < nMints; i++ ) if ( puTruth[i>>5] & (1 << (i&31)) ) { for ( iRes = 0, k = 0; k < 5; k++ ) if ( i & (1 << pPerm[k]) ) iRes |= (1 << k); puTruthR[iRes>>5] |= (1 << (iRes&31)); } } } /**Function************************************************************* Synopsis [Allocated lookup table for truth table permutation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned short ** Extra_TruthPerm43() { unsigned short ** pTable; unsigned uTruth; int i, k; pTable = (unsigned short **)Extra_ArrayAlloc( 256, 16, 2 ); for ( i = 0; i < 256; i++ ) { uTruth = (i << 8) | i; for ( k = 0; k < 16; k++ ) pTable[i][k] = Extra_TruthPerm4One( uTruth, k ); } return pTable; } /**Function************************************************************* Synopsis [Allocated lookup table for truth table permutation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned ** Extra_TruthPerm53() { unsigned ** pTable; unsigned uTruth; int i, k; pTable = (unsigned **)Extra_ArrayAlloc( 256, 32, 4 ); for ( i = 0; i < 256; i++ ) { uTruth = (i << 24) | (i << 16) | (i << 8) | i; for ( k = 0; k < 32; k++ ) pTable[i][k] = Extra_TruthPerm5One( uTruth, k ); } return pTable; } /**Function************************************************************* Synopsis [Allocated lookup table for truth table permutation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned ** Extra_TruthPerm54() { unsigned ** pTable; unsigned uTruth; int i; pTable = (unsigned **)Extra_ArrayAlloc( 256*256, 4, 4 ); for ( i = 0; i < 256*256; i++ ) { uTruth = (i << 16) | i; pTable[i][0] = Extra_TruthPerm5One( uTruth, 31-8 ); pTable[i][1] = Extra_TruthPerm5One( uTruth, 31-4 ); pTable[i][2] = Extra_TruthPerm5One( uTruth, 31-2 ); pTable[i][3] = Extra_TruthPerm5One( uTruth, 31-1 ); } return pTable; } /**Function************************************************************* Synopsis [Allocated lookup table for truth table permutation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned ** Extra_TruthPerm63() { unsigned ** pTable; unsigned uTruth[2]; int i, k; pTable = (unsigned **)Extra_ArrayAlloc( 256, 64, 8 ); for ( i = 0; i < 256; i++ ) { uTruth[0] = (i << 24) | (i << 16) | (i << 8) | i; uTruth[1] = uTruth[0]; for ( k = 0; k < 64; k++ ) Extra_TruthPerm6One( uTruth, k, &pTable[i][k] ); } return pTable; } /**Function************************************************************* Synopsis [Returns the pointer to the elementary truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned ** Extra_Truths8() { static unsigned uTruths[8][8] = { { 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 } }; static unsigned * puResult[8] = { uTruths[0], uTruths[1], uTruths[2], uTruths[3], uTruths[4], uTruths[5], uTruths[6], uTruths[7] }; return (unsigned **)puResult; } /**Function************************************************************* Synopsis [Bubble-sorts components by scores in increasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing ) { int i, Temp, fChanges; assert( nSize < 1000 ); for ( i = 0; i < nSize; i++ ) Order[i] = i; if ( fIncreasing ) { do { fChanges = 0; for ( i = 0; i < nSize - 1; i++ ) { if ( Costs[Order[i]] <= Costs[Order[i+1]] ) continue; Temp = Order[i]; Order[i] = Order[i+1]; Order[i+1] = Temp; fChanges = 1; } } while ( fChanges ); } else { do { fChanges = 0; for ( i = 0; i < nSize - 1; i++ ) { if ( Costs[Order[i]] >= Costs[Order[i+1]] ) continue; Temp = Order[i]; Order[i] = Order[i+1]; Order[i+1] = Temp; fChanges = 1; } } while ( fChanges ); } } /*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Definition of static Functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Computes the permutation table for 8 variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthExpandGeneratePermTable() { int i, k, nOnes, Last1, First0; int iOne, iZero; printf( "\nstatic char Cases[256] = {\n" ); for ( i = 0; i < 256; i++ ) { nOnes = 0; Last1 = First0 = -1; for ( k = 0; k < 8; k++ ) { if ( i & (1 << k) ) { nOnes++; Last1 = k; } else if ( First0 == -1 ) First0 = k; } if ( Last1 + 1 == First0 || i == 255 ) printf( " %d%s", 0, (i==255? " ":",") ); else if ( nOnes == 1 ) printf( " %d,", Last1 ); else printf( " -%d,", 1 ); printf( " // " ); Extra_PrintBinary( stdout, (unsigned*)&i, 8 ); printf( "\n" ); } printf( "};\n" ); printf( "\nstatic char Perms[256][8] = {\n" ); for ( i = 0; i < 256; i++ ) { printf( " {" ); nOnes = 0; for ( k = 0; k < 8; k++ ) if ( i & (1 << k) ) nOnes++; iOne = 0; iZero = nOnes; for ( k = 0; k < 8; k++ ) if ( i & (1 << k) ) printf( "%s %d", (k==0? "":","), iOne++ ); else printf( "%s %d", (k==0? "":","), iZero++ ); assert( iOne + iZero == 8 ); printf( " }%s // ", (i==255? " ":",") ); Extra_PrintBinary( stdout, (unsigned*)&i, 8 ); printf( "\n" ); } printf( "};\n" ); } /**Function************************************************************* Synopsis [Computes complementation schedule for 2^n Grey codes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Extra_GreyCodeSchedule( int n ) { int * pRes = ABC_ALLOC( int, (1< 0 ); if ( n == 1 ) { pRes[0] = 0; return pRes; } if ( n == 2 ) { pRes[0] = pRes[1] = 0; return pRes; } pRes0 = Extra_PermSchedule( n-1 ); for ( k = 0; k < nGroups; k++ ) { for ( i = n-1; i > 0; i-- ) pRes[b++] = i-1; pRes[b++] = pRes0[2*k]+1; for ( i = 0; i < n-1; i++ ) pRes[b++] = i; pRes[b++] = pRes0[2*k+1]; } ABC_FREE( pRes0 ); assert( b == nFact ); if ( 0 ) { int Perm[16]; for ( i = 0; i < n; i++ ) Perm[i] = i; for ( b = 0; b < nFact; b++ ) { ABC_SWAP( int, Perm[pRes[b]], Perm[pRes[b]+1] ); printf( "%3d %3d ", b, pRes[b] ); for ( i = 0; i < n; i++ ) printf( "%d", Perm[i] ); printf( "\n" ); } } return pRes; } /**Function************************************************************* Synopsis [Finds minimum form of a 6-input function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Extra_Truth6SwapAdjacent( word t, int v ) { // variable swapping code static word PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; assert( v < 5 ); return (t & PMasks[v][0]) | ((t & PMasks[v][1]) << (1 << v)) | ((t & PMasks[v][2]) >> (1 << v)); } static inline word Extra_Truth6ChangePhase( word t, int v ) { // elementary truth tables static word Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; assert( v < 6 ); return ((t & ~Truth6[v]) << (1 << v)) | ((t & Truth6[v]) >> (1 << v)); } word Extra_Truth6MinimumExact( word t, int * pComp, int * pPerm ) { word tMin = ~(word)0; word tCur, tTemp1, tTemp2; int i, p, c; for ( i = 0; i < 2; i++ ) { tCur = i ? ~t : t; tTemp1 = tCur; for ( p = 0; p < 720; p++ ) { // printf( "Trying perm %d:\n", p ); // Kit_DsdPrintFromTruth( &tCur, 6 ), printf( "\n" );; tTemp2 = tCur; for ( c = 0; c < 64; c++ ) { tMin = Abc_MinWord( tMin, tCur ); tCur = Extra_Truth6ChangePhase( tCur, pComp[c] ); } assert( tTemp2 == tCur ); tCur = Extra_Truth6SwapAdjacent( tCur, pPerm[p] ); } assert( tTemp1 == tCur ); } return tMin; } /**Function************************************************************* Synopsis [Perform heuristic TT minimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Extra_Truth6Ones( word t ) { t = (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555)); t = (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333)); t = (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F)); t = (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF)); t = (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF)); return (t & ABC_CONST(0x00000000FFFFFFFF)) + (t>>32); } static inline word Extra_Truth6MinimumRoundOne( word t, int v ) { word tCur, tMin = t; // ab assert( v >= 0 && v < 5 ); tCur = Extra_Truth6ChangePhase( t, v ); // !ab tMin = Abc_MinWord( tMin, tCur ); tCur = Extra_Truth6ChangePhase( t, v+1 ); // a!b tMin = Abc_MinWord( tMin, tCur ); tCur = Extra_Truth6ChangePhase( tCur, v ); // !a!b tMin = Abc_MinWord( tMin, tCur ); t = Extra_Truth6SwapAdjacent( t, v ); // ba tMin = Abc_MinWord( tMin, t ); tCur = Extra_Truth6ChangePhase( t, v ); // !ba tMin = Abc_MinWord( tMin, tCur ); tCur = Extra_Truth6ChangePhase( t, v+1 ); // b!a tMin = Abc_MinWord( tMin, tCur ); tCur = Extra_Truth6ChangePhase( tCur, v ); // !b!a tMin = Abc_MinWord( tMin, tCur ); return tMin; } static inline word Extra_Truth6MinimumRoundMany( word t ) { int i, k, Limit = 10; word tCur, tMin = t; for ( i = 0; i < Limit; i++ ) { word tMin0 = tMin; for ( k = 4; k >= 0; k-- ) { tCur = Extra_Truth6MinimumRoundOne( tMin, k ); tMin = Abc_MinWord( tMin, tCur ); } if ( tMin0 == tMin ) break; } return tMin; } word Extra_Truth6MinimumHeuristic( word t ) { word tMin1, tMin2; int nOnes = Extra_Truth6Ones( t ); if ( nOnes < 32 ) return Extra_Truth6MinimumRoundMany( t ); if ( nOnes > 32 ) return Extra_Truth6MinimumRoundMany( ~t ); tMin1 = Extra_Truth6MinimumRoundMany( t ); tMin2 = Extra_Truth6MinimumRoundMany( ~t ); return Abc_MinWord( tMin1, tMin2 ); } void Extra_Truth6MinimumHeuristicTest() { word t = ABC_CONST(0x5555555555555555) & ~(ABC_CONST(0x3333333333333333) & ABC_CONST(0x0F0F0F0F0F0F0F0F)); Extra_Truth6MinimumRoundMany( t ); t = 0; } /**Function************************************************************* Synopsis [Reads functions from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word * Extra_NpnRead( char * pFileName, int nFuncs ) { FILE * pFile; word * pFuncs; char pBuffer[100]; int i = 0; pFuncs = ABC_CALLOC( word, nFuncs ); pFile = fopen( pFileName, "rb" ); while ( fgets( pBuffer, 100, pFile ) ) Extra_ReadHex( (unsigned *)(pFuncs + i++), (pBuffer[1] == 'x' ? pBuffer+2 : pBuffer), 16 ); fclose( pFile ); assert( i == nFuncs ); for ( i = 0; i < Abc_MinInt(nFuncs, 10); i++ ) { printf( "Line %d : ", i ); Extra_PrintHex( stdout, (unsigned *)(pFuncs + i), 6 ), printf( "\n" ); } return pFuncs; } /**Function************************************************************* Synopsis [Comparison for words.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int CompareWords( void * p1, void * p2 ) { word Word1 = *(word *)p1; word Word2 = *(word *)p2; if ( Word1 < Word2 ) return -1; if ( Word1 > Word2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Computes the permutation table for 8 variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_NpnTest1() { int * pComp; pComp = Extra_PermSchedule( 5 ); // pComp = Extra_GreyCodeSchedule( 5 ); ABC_FREE( pComp ); } void Extra_NpnTest2() { int * pComp, * pPerm; word tMin, t = ABC_CONST(0xa2222aaa08888000); pComp = Extra_GreyCodeSchedule( 6 ); pPerm = Extra_PermSchedule( 6 ); tMin = Extra_Truth6MinimumExact( t, pComp, pPerm ); ABC_FREE( pPerm ); ABC_FREE( pComp ); Extra_PrintHex( stdout, (unsigned *)&t, 6 ), printf( "\n" ); Extra_PrintHex( stdout, (unsigned *)&tMin, 6 ), printf( "\n" ); } void Extra_NpnTest() { // int nFuncs = 5687661; // int nFuncs = 400777; int nFuncs = 10; abctime clk = Abc_Clock(); word * pFuncs; int * pComp, * pPerm; int i;//, k, nUnique = 0; /* // read functions pFuncs = Extra_NpnRead( "C:\\_projects\\abc\\_TEST\\allan\\lib6var5M.txt", nFuncs ); // pFuncs = Extra_NpnRead( "C:\\_projects\\abc\\_TEST\\allan\\lib6var5M_out_Total_minimal.txt", nFuncs ); qsort( (void *)pFuncs, nFuncs, sizeof(word), (int(*)(const void *,const void *))CompareWords ); // count unique k = 1; for ( i = 1; i < nFuncs; i++ ) if ( pFuncs[i] != pFuncs[i-1] ) pFuncs[k++] = pFuncs[i]; nFuncs = k; printf( "Total number of unique functions = %d\n", nFuncs ); */ // pFuncs = Extra_NpnRead( "C:\\_projects\\abc\\_TEST\\allan\\lib6var5M_out_Total_minimal.txt", nFuncs ); pFuncs = Extra_NpnRead( "C:\\_projects\\abc\\_TEST\\allan\\test.txt", nFuncs ); pComp = Extra_GreyCodeSchedule( 6 ); pPerm = Extra_PermSchedule( 6 ); // compute minimum forms for ( i = 0; i < nFuncs; i++ ) { pFuncs[i] = Extra_Truth6MinimumExact( pFuncs[i], pComp, pPerm ); if ( i % 10000 == 0 ) printf( "%d\n", i ); } printf( "Finished deriving minimum form\n" ); /* // sort them by value qsort( (void *)pFuncs, nFuncs, sizeof(word), (int(*)(const void *,const void *))CompareWords ); // count unique nUnique = nFuncs; for ( i = 1; i < nFuncs; i++ ) if ( pFuncs[i] == pFuncs[i-1] ) nUnique--; printf( "Total number of unique ones = %d\n", nUnique ); */ for ( i = 0; i < Abc_MinInt(nFuncs, 10); i++ ) { printf( "Line %d : ", i ); Extra_PrintHex( stdout, (unsigned *)(pFuncs + i), 6 ), printf( "\n" ); } ABC_FREE( pPerm ); ABC_FREE( pComp ); ABC_FREE( pFuncs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_NtkPrintBin( word * pT, int nBits ) { int i; for ( i = nBits - 1; i >= 0; i-- ) printf( "%d", (int)((*pT >> i) & 1) ); } void Extra_NtkPowerTest() { int i, j, k, n = 4; for ( i = 0; i < (1< #include #include #include #include "misc/vec/vec.h" #include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef enum { ABC_ZDD_OPER_NONE, ABC_ZDD_OPER_DIFF, ABC_ZDD_OPER_UNION, ABC_ZDD_OPER_MIN_UNION, ABC_ZDD_OPER_INTER, ABC_ZDD_OPER_PERM, ABC_ZDD_OPER_PERM_PROD, ABC_ZDD_OPER_COF0, ABC_ZDD_OPER_COF1, ABC_ZDD_OPER_THRESH, ABC_ZDD_OPER_DOT_PROD, ABC_ZDD_OPER_DOT_PROD_6, ABC_ZDD_OPER_INSERT, ABC_ZDD_OPER_PATHS, ABC_ZDD_OPER_NODES, ABC_ZDD_OPER_ITE } Abc_ZddOper; typedef struct Abc_ZddObj_ Abc_ZddObj; struct Abc_ZddObj_ { unsigned Var : 31; unsigned Mark : 1; unsigned True; unsigned False; }; typedef struct Abc_ZddEnt_ Abc_ZddEnt; struct Abc_ZddEnt_ { int Arg0; int Arg1; int Arg2; int Res; }; typedef struct Abc_ZddMan_ Abc_ZddMan; struct Abc_ZddMan_ { int nVars; int nObjs; int nObjsAlloc; int nPermSize; unsigned nUniqueMask; unsigned nCacheMask; int * pUnique; int * pNexts; Abc_ZddEnt * pCache; Abc_ZddObj * pObjs; int nCacheLookups; int nCacheMisses; word nMemory; int * pV2TI; int * pV2TJ; int * pT2V; }; static inline int Abc_ZddIthVar( int i ) { return i + 2; } static inline unsigned Abc_ZddHash( int Arg0, int Arg1, int Arg2 ) { return 12582917 * Arg0 + 4256249 * Arg1 + 741457 * Arg2; } static inline Abc_ZddObj * Abc_ZddNode( Abc_ZddMan * p, int i ) { return p->pObjs + i; } static inline int Abc_ZddObjId( Abc_ZddMan * p, Abc_ZddObj * pObj ) { return pObj - p->pObjs; } static inline int Abc_ZddObjVar( Abc_ZddMan * p, int i ) { return Abc_ZddNode(p, i)->Var; } static inline void Abc_ZddSetVarIJ( Abc_ZddMan * p, int i, int j, int v ) { assert( i < j ); p->pT2V[i * p->nPermSize + j] = v; } static inline int Abc_ZddVarIJ( Abc_ZddMan * p, int i, int j ) { assert( i < j ); return p->pT2V[i * p->nPermSize + j]; } static inline int Abc_ZddVarsClash( Abc_ZddMan * p, int v0, int v1 ) { return p->pV2TI[v0] == p->pV2TI[v1] || p->pV2TJ[v0] == p->pV2TJ[v1] || p->pV2TI[v0] == p->pV2TJ[v1] || p->pV2TJ[v0] == p->pV2TI[v1]; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_ZddCacheLookup( Abc_ZddMan * p, int Arg0, int Arg1, int Arg2 ) { Abc_ZddEnt * pEnt = p->pCache + (Abc_ZddHash(Arg0, Arg1, Arg2) & p->nCacheMask); p->nCacheLookups++; return (pEnt->Arg0 == Arg0 && pEnt->Arg1 == Arg1 && pEnt->Arg2 == Arg2) ? pEnt->Res : -1; } static inline int Abc_ZddCacheInsert( Abc_ZddMan * p, int Arg0, int Arg1, int Arg2, int Res ) { Abc_ZddEnt * pEnt = p->pCache + (Abc_ZddHash(Arg0, Arg1, Arg2) & p->nCacheMask); pEnt->Arg0 = Arg0; pEnt->Arg1 = Arg1; pEnt->Arg2 = Arg2; pEnt->Res = Res; p->nCacheMisses++; assert( Res >= 0 ); return Res; } static inline int Abc_ZddUniqueLookup( Abc_ZddMan * p, int Var, int True, int False ) { int *q = p->pUnique + (Abc_ZddHash(Var, True, False) & p->nUniqueMask); for ( ; *q; q = p->pNexts + *q ) if ( p->pObjs[*q].Var == (unsigned)Var && p->pObjs[*q].True == (unsigned)True && p->pObjs[*q].False == (unsigned)False ) return *q; return 0; } static inline int Abc_ZddUniqueCreate( Abc_ZddMan * p, int Var, int True, int False ) { assert( Var >= 0 && Var < p->nVars ); assert( Var < Abc_ZddObjVar(p, True) ); assert( Var < Abc_ZddObjVar(p, False) ); if ( True == 0 ) return False; { int *q = p->pUnique + (Abc_ZddHash(Var, True, False) & p->nUniqueMask); for ( ; *q; q = p->pNexts + *q ) if ( p->pObjs[*q].Var == (unsigned)Var && p->pObjs[*q].True == (unsigned)True && p->pObjs[*q].False == (unsigned)False ) return *q; if ( p->nObjs == p->nObjsAlloc ) printf( "Aborting because the number of nodes exceeded %d.\n", p->nObjsAlloc ), fflush(stdout); assert( p->nObjs < p->nObjsAlloc ); *q = p->nObjs++; p->pObjs[*q].Var = Var; p->pObjs[*q].True = True; p->pObjs[*q].False = False; // printf( "Added node %3d: Var = %3d. True = %3d. False = %3d\n", *q, Var, True, False ); return *q; } } int Abc_ZddBuildSet( Abc_ZddMan * p, int * pSet, int Size ) { int i, Res = 1; Vec_IntSelectSort( pSet, Size ); for ( i = Size - 1; i >= 0; i-- ) Res = Abc_ZddUniqueCreate( p, pSet[i], Res, 0 ); return Res; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_ZddMan * Abc_ZddManAlloc( int nVars, int nObjs ) { Abc_ZddMan * p; int i; p = ABC_CALLOC( Abc_ZddMan, 1 ); p->nVars = nVars; p->nObjsAlloc = nObjs; p->nUniqueMask = (1 << Abc_Base2Log(nObjs)) - 1; p->nCacheMask = (1 << Abc_Base2Log(nObjs)) - 1; p->pUnique = ABC_CALLOC( int, p->nUniqueMask + 1 ); p->pNexts = ABC_CALLOC( int, p->nObjsAlloc ); p->pCache = ABC_CALLOC( Abc_ZddEnt, p->nCacheMask + 1 ); p->pObjs = ABC_CALLOC( Abc_ZddObj, p->nObjsAlloc ); p->nObjs = 2; memset( p->pObjs, 0xff, sizeof(Abc_ZddObj) * 2 ); p->pObjs[0].Var = nVars; p->pObjs[1].Var = nVars; for ( i = 0; i < nVars; i++ ) Abc_ZddUniqueCreate( p, i, 1, 0 ); assert( p->nObjs == nVars + 2 ); p->nMemory = sizeof(Abc_ZddMan)/4 + p->nUniqueMask + 1 + p->nObjsAlloc + (p->nCacheMask + 1) * sizeof(Abc_ZddEnt)/4 + p->nObjsAlloc * sizeof(Abc_ZddObj)/4; return p; } void Abc_ZddManCreatePerms( Abc_ZddMan * p, int nPermSize ) { int i, j, v = 0; assert( 2 * p->nVars == nPermSize * (nPermSize - 1) ); assert( p->nPermSize == 0 ); p->nPermSize = nPermSize; p->pV2TI = ABC_FALLOC( int, p->nVars ); p->pV2TJ = ABC_FALLOC( int, p->nVars ); p->pT2V = ABC_FALLOC( int, p->nPermSize * p->nPermSize ); for ( i = 0; i < nPermSize; i++ ) for ( j = i + 1; j < nPermSize; j++ ) { p->pV2TI[v] = i; p->pV2TJ[v] = j; Abc_ZddSetVarIJ( p, i, j, v++ ); } assert( v == p->nVars ); } void Abc_ZddManFree( Abc_ZddMan * p ) { printf( "ZDD stats: Var = %d Obj = %d Alloc = %d Hit = %d Miss = %d ", p->nVars, p->nObjs, p->nObjsAlloc, p->nCacheLookups-p->nCacheMisses, p->nCacheMisses ); printf( "Mem = %.2f MB\n", 4.0*(int)(p->nMemory/(1<<20)) ); ABC_FREE( p->pT2V ); ABC_FREE( p->pV2TI ); ABC_FREE( p->pV2TJ ); ABC_FREE( p->pUnique ); ABC_FREE( p->pNexts ); ABC_FREE( p->pCache ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ZddDiff( Abc_ZddMan * p, int a, int b ) { Abc_ZddObj * A, * B; int r0, r1, r; if ( a == 0 ) return 0; if ( b == 0 ) return a; if ( a == b ) return 0; if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_DIFF)) >= 0 ) return r; A = Abc_ZddNode( p, a ); B = Abc_ZddNode( p, b ); if ( A->Var < B->Var ) r0 = Abc_ZddDiff( p, A->False, b ), r = Abc_ZddUniqueCreate( p, A->Var, A->True, r0 ); else if ( A->Var > B->Var ) r = Abc_ZddDiff( p, a, B->False ); else r0 = Abc_ZddDiff( p, A->False, B->False ), r1 = Abc_ZddDiff( p, A->True, B->True ), r = Abc_ZddUniqueCreate( p, A->Var, A->True, r0 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_DIFF, r ); } int Abc_ZddUnion( Abc_ZddMan * p, int a, int b ) { Abc_ZddObj * A, * B; int r0, r1, r; if ( a == 0 ) return b; if ( b == 0 ) return a; if ( a == b ) return a; if ( a > b ) return Abc_ZddUnion( p, b, a ); if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_UNION)) >= 0 ) return r; A = Abc_ZddNode( p, a ); B = Abc_ZddNode( p, b ); if ( A->Var < B->Var ) r0 = Abc_ZddUnion( p, A->False, b ), r1 = A->True; else if ( A->Var > B->Var ) r0 = Abc_ZddUnion( p, a, B->False ), r1 = B->True; else r0 = Abc_ZddUnion( p, A->False, B->False ), r1 = Abc_ZddUnion( p, A->True, B->True ); r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_UNION, r ); } int Abc_ZddMinUnion( Abc_ZddMan * p, int a, int b ) { Abc_ZddObj * A, * B; int r0, r1, r; if ( a == 0 ) return b; if ( b == 0 ) return a; if ( a == b ) return a; if ( a > b ) return Abc_ZddMinUnion( p, b, a ); if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_MIN_UNION)) >= 0 ) return r; A = Abc_ZddNode( p, a ); B = Abc_ZddNode( p, b ); if ( A->Var < B->Var ) r0 = Abc_ZddMinUnion( p, A->False, b ), r1 = A->True; else if ( A->Var > B->Var ) r0 = Abc_ZddMinUnion( p, a, B->False ), r1 = B->True; else r0 = Abc_ZddMinUnion( p, A->False, B->False ), r1 = Abc_ZddMinUnion( p, A->True, B->True ); r1 = Abc_ZddDiff( p, r1, r0 ); // assume args are minimal r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_MIN_UNION, r ); } int Abc_ZddIntersect( Abc_ZddMan * p, int a, int b ) { Abc_ZddObj * A, * B; int r0, r1, r; if ( a == 0 ) return 0; if ( b == 0 ) return 0; if ( a == b ) return a; if ( a > b ) return Abc_ZddIntersect( p, b, a ); if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_INTER)) >= 0 ) return r; A = Abc_ZddNode( p, a ); B = Abc_ZddNode( p, b ); if ( A->Var < B->Var ) r0 = Abc_ZddIntersect( p, A->False, b ), r1 = A->True; else if ( A->Var > B->Var ) r0 = Abc_ZddIntersect( p, a, B->False ), r1 = B->True; else r0 = Abc_ZddIntersect( p, A->False, B->False ), r1 = Abc_ZddIntersect( p, A->True, B->True ); r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_INTER, r ); } int Abc_ZddCof0( Abc_ZddMan * p, int a, int Var ) { Abc_ZddObj * A; int r0, r1, r; if ( a < 2 ) return a; A = Abc_ZddNode( p, a ); if ( (int)A->Var > Var ) return a; if ( (r = Abc_ZddCacheLookup(p, a, Var, ABC_ZDD_OPER_COF0)) >= 0 ) return r; if ( (int)A->Var < Var ) r0 = Abc_ZddCof0( p, A->False, Var ), r1 = Abc_ZddCof0( p, A->True, Var ), r = Abc_ZddUniqueCreate( p, A->Var, r1, r0 ); else r = Abc_ZddCof0( p, A->False, Var ); return Abc_ZddCacheInsert( p, a, Var, ABC_ZDD_OPER_COF0, r ); } int Abc_ZddCof1( Abc_ZddMan * p, int a, int Var ) { Abc_ZddObj * A; int r0, r1, r; if ( a < 2 ) return a; A = Abc_ZddNode( p, a ); if ( (int)A->Var > Var ) return a; if ( (r = Abc_ZddCacheLookup(p, a, Var, ABC_ZDD_OPER_COF1)) >= 0 ) return r; if ( (int)A->Var < Var ) r0 = Abc_ZddCof1( p, A->False, Var ), r1 = Abc_ZddCof1( p, A->True, Var ); else r0 = 0, r1 = Abc_ZddCof1( p, A->True, Var ); r = Abc_ZddUniqueCreate( p, A->Var, r1, r0 ); return Abc_ZddCacheInsert( p, a, Var, ABC_ZDD_OPER_COF1, r ); } int Abc_ZddCountPaths( Abc_ZddMan * p, int a ) { Abc_ZddObj * A; int r; if ( a < 2 ) return a; if ( (r = Abc_ZddCacheLookup(p, a, 0, ABC_ZDD_OPER_PATHS)) >= 0 ) return r; A = Abc_ZddNode( p, a ); r = Abc_ZddCountPaths( p, A->False ) + Abc_ZddCountPaths( p, A->True ); return Abc_ZddCacheInsert( p, a, 0, ABC_ZDD_OPER_PATHS, r ); } /* int Abc_ZddCountNodes( Abc_ZddMan * p, int a ) { Abc_ZddObj * A; int r; if ( a < 2 ) return 0; if ( (r = Abc_ZddCacheLookup(p, a, 0, ABC_ZDD_OPER_NODES)) >= 0 ) return r; A = Abc_ZddNode( p, a ); r = 1 + Abc_ZddCountNodes( p, A->False ) + Abc_ZddCountNodes( p, A->True ); return Abc_ZddCacheInsert( p, a, 0, ABC_ZDD_OPER_NODES, r ); } */ int Abc_ZddCount_rec( Abc_ZddMan * p, int i ) { Abc_ZddObj * A; if ( i < 2 ) return 0; A = Abc_ZddNode( p, i ); if ( A->Mark ) return 0; A->Mark = 1; return 1 + Abc_ZddCount_rec(p, A->False) + Abc_ZddCount_rec(p, A->True); } void Abc_ZddUnmark_rec( Abc_ZddMan * p, int i ) { Abc_ZddObj * A; if ( i < 2 ) return; A = Abc_ZddNode( p, i ); if ( !A->Mark ) return; A->Mark = 0; Abc_ZddUnmark_rec( p, A->False ); Abc_ZddUnmark_rec( p, A->True ); } int Abc_ZddCountNodes( Abc_ZddMan * p, int i ) { int Count = Abc_ZddCount_rec( p, i ); Abc_ZddUnmark_rec( p, i ); return Count; } int Abc_ZddCountNodesArray( Abc_ZddMan * p, Vec_Int_t * vNodes ) { int i, Id, Count = 0; Vec_IntForEachEntry( vNodes, Id, i ) Count += Abc_ZddCount_rec( p, Id ); Vec_IntForEachEntry( vNodes, Id, i ) Abc_ZddUnmark_rec( p, Id ); return Count; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ZddThresh( Abc_ZddMan * p, int a, int b ) { Abc_ZddObj * A; int r0, r1, r; if ( a < 2 ) return a; if ( b == 0 ) return 0; if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_THRESH)) >= 0 ) return r; A = Abc_ZddNode( p, a ); r0 = Abc_ZddThresh( p, A->False, b ), r1 = Abc_ZddThresh( p, A->True, b-1 ); r = Abc_ZddUniqueCreate( p, A->Var, r1, r0 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_THRESH, r ); } int Abc_ZddDotProduct( Abc_ZddMan * p, int a, int b ) { Abc_ZddObj * A, * B; int r0, r1, b2, t1, t2, r; if ( a == 0 ) return 0; if ( b == 0 ) return 0; if ( a == 1 ) return b; if ( b == 1 ) return a; if ( a > b ) return Abc_ZddDotProduct( p, b, a ); if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_DOT_PROD)) >= 0 ) return r; A = Abc_ZddNode( p, a ); B = Abc_ZddNode( p, b ); if ( A->Var < B->Var ) r0 = Abc_ZddDotProduct( p, A->False, b ), r1 = Abc_ZddDotProduct( p, A->True, b ); else if ( A->Var > B->Var ) r0 = Abc_ZddDotProduct( p, a, B->False ), r1 = Abc_ZddDotProduct( p, a, B->True ); else r0 = Abc_ZddDotProduct( p, A->False, B->False ), b2 = Abc_ZddUnion( p, B->False, B->True ), t1 = Abc_ZddDotProduct( p, A->True, b2 ), t2 = Abc_ZddDotProduct( p, A->False, B->True ), r1 = Abc_ZddUnion( p, t1, t2 ); r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_DOT_PROD, r ); } int Abc_ZddDotMinProduct6( Abc_ZddMan * p, int a, int b ) { Abc_ZddObj * A, * B; int r0, r1, b2, t1, t2, r; if ( a == 0 ) return 0; if ( b == 0 ) return 0; if ( a == 1 ) return b; if ( b == 1 ) return a; if ( a > b ) return Abc_ZddDotMinProduct6( p, b, a ); if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_DOT_PROD_6)) >= 0 ) return r; A = Abc_ZddNode( p, a ); B = Abc_ZddNode( p, b ); if ( A->Var < B->Var ) r0 = Abc_ZddDotMinProduct6( p, A->False, b ), r1 = Abc_ZddDotMinProduct6( p, A->True, b ); else if ( A->Var > B->Var ) r0 = Abc_ZddDotMinProduct6( p, a, B->False ), r1 = Abc_ZddDotMinProduct6( p, a, B->True ); else r0 = Abc_ZddDotMinProduct6( p, A->False, B->False ), b2 = Abc_ZddMinUnion( p, B->False, B->True ), t1 = Abc_ZddDotMinProduct6( p, A->True, b2 ), t2 = Abc_ZddDotMinProduct6( p, A->False, B->True ), r1 = Abc_ZddMinUnion( p, t1, t2 ); r1 = Abc_ZddThresh( p, r1, 5 ), r1 = Abc_ZddDiff( p, r1, r0 ); r = Abc_ZddUniqueCreate( p, Abc_MinInt(A->Var, B->Var), r1, r0 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_DOT_PROD_6, r ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ZddPerm( Abc_ZddMan * p, int a, int Var ) { Abc_ZddObj * A; int r0, r1, r; assert( Var < p->nVars ); if ( a == 0 ) return 0; if ( a == 1 ) return Abc_ZddIthVar(Var); if ( (r = Abc_ZddCacheLookup(p, a, Var, ABC_ZDD_OPER_PERM)) >= 0 ) return r; A = Abc_ZddNode( p, a ); if ( p->pV2TI[A->Var] > p->pV2TI[Var] ) // Ai > Bi r = Abc_ZddUniqueCreate( p, Var, a, 0 ); else if ( (int)A->Var == Var ) // Ai == Bi && Aj == Bj r0 = Abc_ZddPerm( p, A->False, Var ), r = Abc_ZddUnion( p, r0, A->True ); else { int VarPerm, VarTop; int Ai = p->pV2TI[A->Var]; int Aj = p->pV2TJ[A->Var]; int Bi = p->pV2TI[Var]; int Bj = p->pV2TJ[Var]; assert( Ai < Aj && Bi < Bj && Ai <= Bi ); if ( Aj == Bi ) VarPerm = Var, VarTop = Abc_ZddVarIJ(p, Ai, Bj); else if ( Aj == Bj ) VarPerm = Var, VarTop = Abc_ZddVarIJ(p, Ai, Bi); else if ( Ai == Bi ) VarPerm = Abc_ZddVarIJ(p, Abc_MinInt(Aj, Bj), Abc_MaxInt(Aj, Bj)), VarTop = A->Var; else // no clash VarPerm = Var, VarTop = A->Var; assert( p->pV2TI[VarPerm] > p->pV2TI[VarTop] ); r0 = Abc_ZddPerm( p, A->False, Var ); r1 = Abc_ZddPerm( p, A->True, VarPerm ); assert( Abc_ZddObjVar(p, r1) > VarTop ); if ( Abc_ZddObjVar(p, r0) > VarTop ) r = Abc_ZddUniqueCreate( p, VarTop, r1, r0 ); else r1 = Abc_ZddUniqueCreate( p, VarTop, r1, 0 ), r = Abc_ZddUnion( p, r0, r1 ); } return Abc_ZddCacheInsert( p, a, Var, ABC_ZDD_OPER_PERM, r ); } int Abc_ZddPermProduct( Abc_ZddMan * p, int a, int b ) { Abc_ZddObj * B; int r0, r1, r; if ( a == 0 ) return 0; if ( a == 1 ) return b; if ( b == 0 ) return 0; if ( b == 1 ) return a; if ( (r = Abc_ZddCacheLookup(p, a, b, ABC_ZDD_OPER_PERM_PROD)) >= 0 ) return r; B = Abc_ZddNode( p, b ); r0 = Abc_ZddPermProduct( p, a, B->False ); r1 = Abc_ZddPermProduct( p, a, B->True ); r1 = Abc_ZddPerm( p, r1, B->Var ); r = Abc_ZddUnion( p, r0, r1 ); return Abc_ZddCacheInsert( p, a, b, ABC_ZDD_OPER_PERM_PROD, r ); } /**Function************************************************************* Synopsis [Printing permutations and transpositions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ZddPermPrint( int * pPerm, int Size ) { int i; printf( "{" ); for ( i = 0; i < Size; i++ ) printf( " %2d", pPerm[i] ); printf( " }\n" ); } void Abc_ZddCombPrint( int * pComb, int nTrans ) { int i; if ( nTrans == 0 ) printf( "Empty set" ); for ( i = 0; i < nTrans; i++ ) printf( "(%d %d)", pComb[i] >> 16, pComb[i] & 0xffff ); printf( "\n" ); } int Abc_ZddPerm2Comb( int * pPerm, int Size, int * pComb ) { int i, j, nTrans = 0; for ( i = 0; i < Size; i++ ) if ( i != pPerm[i] ) { for ( j = i+1; j < Size; j++ ) if ( i == pPerm[j] ) break; pComb[nTrans++] = (i << 16) | j; ABC_SWAP( int, pPerm[i], pPerm[j] ); assert( i == pPerm[i] ); } return nTrans; } void Abc_ZddComb2Perm( int * pComb, int nTrans, int * pPerm, int Size ) { int v; for ( v = 0; v < Size; v++ ) pPerm[v] = v; for ( v = nTrans-1; v >= 0; v-- ) ABC_SWAP( int, pPerm[pComb[v] >> 16], pPerm[pComb[v] & 0xffff] ); } void Abc_ZddPermCombTest() { int Size = 10; int pPerm[10] = { 6, 5, 7, 0, 3, 2, 1, 8, 9, 4 }; int pComb[10], nTrans; Abc_ZddPermPrint( pPerm, Size ); nTrans = Abc_ZddPerm2Comb( pPerm, Size, pComb ); Abc_ZddCombPrint( pComb, nTrans ); Abc_ZddComb2Perm( pComb, nTrans, pPerm, Size ); Abc_ZddPermPrint( pPerm, Size ); Size = 0; } /**Function************************************************************* Synopsis [Printing ZDDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ZddPrint_rec( Abc_ZddMan * p, int a, int * pPath, int Size ) { Abc_ZddObj * A; if ( a == 0 ) return; // if ( a == 1 ) { Abc_ZddPermPrint( pPath, Size ); return; } if ( a == 1 ) { int pPerm[24], pComb[24], i; assert( p->nPermSize <= 24 ); for ( i = 0; i < Size; i++ ) pComb[i] = (p->pV2TI[pPath[i]] << 16) | p->pV2TJ[pPath[i]]; Abc_ZddCombPrint( pComb, Size ); Abc_ZddComb2Perm( pComb, Size, pPerm, p->nPermSize ); Abc_ZddPermPrint( pPerm, p->nPermSize ); return; } A = Abc_ZddNode( p, a ); Abc_ZddPrint_rec( p, A->False, pPath, Size ); pPath[Size] = A->Var; Abc_ZddPrint_rec( p, A->True, pPath, Size + 1 ); } void Abc_ZddPrint( Abc_ZddMan * p, int a ) { int * pPath = ABC_CALLOC( int, p->nVars ); Abc_ZddPrint_rec( p, a, pPath, 0 ); ABC_FREE( pPath ); } void Abc_ZddPrintTest( Abc_ZddMan * p ) { // int nSets = 2; // int Size = 2; // int pSets[2][2] = { {5, 0}, {3, 11} }; int nSets = 3; int Size = 5; int pSets[3][5] = { {5, 0, 2, 10, 7}, {3, 11, 10, 7, 2}, {0, 2, 5, 10, 7} }; int i, Set, Union = 0; for ( i = 0; i < nSets; i++ ) { Abc_ZddPermPrint( pSets[i], Size ); Set = Abc_ZddBuildSet( p, pSets[i], Size ); Union = Abc_ZddUnion( p, Union, Set ); } printf( "Resulting set:\n" ); Abc_ZddPrint( p, Union ); printf( "\n" ); printf( "Nodes = %d. Path = %d.\n", Abc_ZddCountNodes(p, Union), Abc_ZddCountPaths(p, Union) ); Size = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ZddGiaTest( Gia_Man_t * pGia ) { Abc_ZddMan * p; Gia_Obj_t * pObj; Vec_Int_t * vNodes; int i, r, Paths = 0; p = Abc_ZddManAlloc( Gia_ManObjNum(pGia), 1 << 24 ); // 576 MB (36 B/node) Gia_ManFillValue( pGia ); Gia_ManForEachCi( pGia, pObj, i ) pObj->Value = Abc_ZddIthVar( Gia_ObjId(pGia, pObj) ); vNodes = Vec_IntAlloc( Gia_ManAndNum(pGia) ); Gia_ManForEachAnd( pGia, pObj, i ) { r = Abc_ZddDotMinProduct6( p, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); r = Abc_ZddUnion( p, r, Abc_ZddIthVar(i) ); pObj->Value = r; Vec_IntPush( vNodes, r ); // print // printf( "Node %d:\n", i ); // Abc_ZddPrint( p, r ); // printf( "Node %d ZddNodes = %d\n", i, Abc_ZddCountNodes(p, r) ); } Gia_ManForEachAnd( pGia, pObj, i ) Paths += Abc_ZddCountPaths(p, pObj->Value); printf( "Paths = %d. Shared nodes = %d.\n", Paths, Abc_ZddCountNodesArray(p, vNodes) ); Vec_IntFree( vNodes ); Abc_ZddManFree( p ); } /* abc 01> &r pj1.aig; &ps; &test pj1 : i/o = 1769/ 1063 and = 16285 lev = 156 (12.91) mem = 0.23 MB Paths = 839934. Shared nodes = 770999. ZDD stats: Var = 19118 Obj = 11578174 All = 16777216 Hits = 25617277 Miss = 40231476 Mem = 576.00 MB */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ZddPermTestInt( Abc_ZddMan * p ) { int nPerms = 3; int Size = 5; int pPerms[3][5] = { {1, 0, 2, 4, 3}, {1, 2, 4, 0, 3}, {0, 3, 2, 1, 4} }; int pComb[5], nTrans; int i, k, Set, Union = 0, iPivot; for ( i = 0; i < nPerms; i++ ) Abc_ZddPermPrint( pPerms[i], Size ); for ( i = 0; i < nPerms; i++ ) { printf( "Perm %d:\n", i ); Abc_ZddPermPrint( pPerms[i], Size ); nTrans = Abc_ZddPerm2Comb( pPerms[i], Size, pComb ); Abc_ZddCombPrint( pComb, nTrans ); for ( k = 0; k < nTrans; k++ ) pComb[k] = Abc_ZddVarIJ( p, pComb[k] >> 16, pComb[k] & 0xFFFF ); Abc_ZddPermPrint( pComb, nTrans ); // add to ZDD Set = Abc_ZddBuildSet( p, pComb, nTrans ); Union = Abc_ZddUnion( p, Union, Set ); } printf( "\nResulting set of permutations:\n" ); Abc_ZddPrint( p, Union ); printf( "Nodes = %d. Path = %d.\n", Abc_ZddCountNodes(p, Union), Abc_ZddCountPaths(p, Union) ); iPivot = Abc_ZddVarIJ( p, 3, 4 ); Union = Abc_ZddPerm( p, Union, iPivot ); printf( "\nResulting set of permutations:\n" ); Abc_ZddPrint( p, Union ); printf( "Nodes = %d. Path = %d.\n", Abc_ZddCountNodes(p, Union), Abc_ZddCountPaths(p, Union) ); printf( "\n" ); } void Abc_ZddPermTest() { Abc_ZddMan * p; p = Abc_ZddManAlloc( 10, 1 << 20 ); Abc_ZddManCreatePerms( p, 5 ); Abc_ZddPermTestInt( p ); Abc_ZddManFree( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_EnumerateCubeStatesZdd() { int pXYZ[3][9][2] = { { {3, 5}, {3,17}, {3,15}, {1, 6}, {1,16}, {1,14}, {2, 4}, {2,18}, {2,13} }, { {2,14}, {2,24}, {2,12}, {3,13}, {3,23}, {3,10}, {1,15}, {1,22}, {1,11} }, { {1,10}, {1, 7}, {1, 4}, {3,12}, {3, 9}, {3, 6}, {2,11}, {2, 8}, {2, 5} } }; #ifdef WIN32 int LogObj = 24; #else int LogObj = 27; #endif Abc_ZddMan * p; int i, k, pComb[9], pPerm[24], nSize; int ZddTurn1, ZddTurn2, ZddTurn3, ZddTurns, ZddAll; abctime clk = Abc_Clock(); printf( "Enumerating states of 2x2x2 cube.\n" ); p = Abc_ZddManAlloc( 24 * 23 / 2, 1 << LogObj ); // finished with 2^27 (4 GB) Abc_ZddManCreatePerms( p, 24 ); // init state printf( "Iter %2d -> %8d Nodes = %7d Used = %10d ", 0, 1, 0, 2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // first 9 states ZddTurns = 1; for ( i = 0; i < 3; i++ ) { for ( k = 0; k < 24; k++ ) pPerm[k] = k; for ( k = 0; k < 9; k++ ) ABC_SWAP( int, pPerm[pXYZ[i][k][0]-1], pPerm[pXYZ[i][k][1]-1] ); nSize = Abc_ZddPerm2Comb( pPerm, 24, pComb ); assert( nSize == 9 ); for ( k = 0; k < 9; k++ ) pComb[k] = Abc_ZddVarIJ( p, pComb[k] >> 16, pComb[k] & 0xffff ); // add first turn ZddTurn1 = Abc_ZddBuildSet( p, pComb, 9 ); ZddTurns = Abc_ZddUnion( p, ZddTurns, ZddTurn1 ); //Abc_ZddPrint( p, ZddTurn1 ); // add second turn ZddTurn2 = Abc_ZddPermProduct( p, ZddTurn1, ZddTurn1 ); ZddTurns = Abc_ZddUnion( p, ZddTurns, ZddTurn2 ); //Abc_ZddPrint( p, ZddTurn2 ); // add third turn ZddTurn3 = Abc_ZddPermProduct( p, ZddTurn2, ZddTurn1 ); ZddTurns = Abc_ZddUnion( p, ZddTurns, ZddTurn3 ); //Abc_ZddPrint( p, ZddTurn3 ); //printf( "\n" ); } //Abc_ZddPrint( p, ZddTurns ); printf( "Iter %2d -> %8d Nodes = %7d Used = %10d ", 1, Abc_ZddCountPaths(p, ZddTurns), Abc_ZddCountNodes(p, ZddTurns), p->nObjs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // other states ZddAll = ZddTurns; for ( i = 2; i <= 100; i++ ) { int ZddAllPrev = ZddAll; ZddAll = Abc_ZddPermProduct( p, ZddAll, ZddTurns ); printf( "Iter %2d -> %8d Nodes = %7d Used = %10d ", i, Abc_ZddCountPaths(p, ZddAll), Abc_ZddCountNodes(p, ZddAll), p->nObjs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( ZddAllPrev == ZddAll ) break; } Abc_ZddManFree( p ); } /* Enumerating states of 2x2x2 cube. Iter 0 -> 1 Nodes = 0 Used = 2 Time = 0.00 sec Iter 1 -> 10 Nodes = 63 Used = 577 Time = 0.00 sec Iter 2 -> 64 Nodes = 443 Used = 4349 Time = 0.03 sec Iter 3 -> 385 Nodes = 2018 Used = 26654 Time = 0.14 sec Iter 4 -> 2232 Nodes = 7451 Used = 119442 Time = 0.45 sec Iter 5 -> 12224 Nodes = 25178 Used = 490038 Time = 1.10 sec Iter 6 -> 62360 Nodes = 83955 Used = 1919750 Time = 1.79 sec Iter 7 -> 289896 Nodes = 290863 Used = 7182932 Time = 3.15 sec Iter 8 -> 1159968 Nodes = 614845 Used = 25301123 Time = 8.03 sec Iter 9 -> 3047716 Nodes = 585664 Used = 66228369 Time = 20.22 sec Iter 10 -> 3671516 Nodes = 19430 Used = 102292452 Time = 33.41 sec Iter 11 -> 3674160 Nodes = 511 Used = 103545878 Time = 33.92 sec Iter 12 -> 3674160 Nodes = 511 Used = 103566266 Time = 33.93 sec ZDD stats: Var = 276 Obj = 103566266 Alloc = 134217728 Hit = 63996630 Miss = 141768893 Mem = 4608.00 MB */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilPrime.c000066400000000000000000000532351300674244400252440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilPrime.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Function enumeration.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilPrime.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "misc/vec/vecHsh.h" #include "bool/kit/kit.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenCountDump( Vec_Int_t * vPrimes, int nVars, char * pFileName ) { FILE * pFile; int i, k, Prime; pFile = fopen( pFileName, "wb" ); fprintf( pFile, "# %d prime numbers up to 2^%d generated by ABC on %s\n", Vec_IntSize(vPrimes), nVars, Extra_TimeStamp() ); fprintf( pFile, ".i %d\n", nVars ); fprintf( pFile, ".o %d\n", 1 ); fprintf( pFile, ".p %d\n", Vec_IntSize(vPrimes) ); Vec_IntForEachEntry( vPrimes, Prime, i ) for ( k = nVars-1; k >= 0; k-- ) fprintf( pFile, "%d%s", (Prime >> k)&1, k ? "" : " 1\n" ); fprintf( pFile, ".e\n\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_GenCountHits1( Vec_Bit_t * vMap, Vec_Int_t * vPrimes, int nVars ) { abctime clk = Abc_Clock(); int i, k, Prime, Count = 0; Vec_IntForEachEntry( vPrimes, Prime, i ) { for ( k = 0; k < nVars; k++ ) if ( !Vec_BitEntry(vMap, Prime ^ (1< cube + lit + lit) int Degree; // degree of 2 larger than log2(nCubes) int Mask; // table size (2^Degree) int nEnts; // number of entries }; struct Tab_Ent_t_ { int Table; int Cube; unsigned VarA : 16; unsigned VarB : 16; int Next; }; static inline int * Tab_ManCube( Tab_Man_t * p, int i ) { assert(i >= 0 && i < p->nCubes); return p->pCubes + i * (p->nVars + 1); } static inline Tab_Ent_t * Tab_ManEnt( Tab_Man_t * p, int i ) { assert(i >= -1 && i < p->nTable); return i >= 0 ? p->pTable + i : NULL; } static inline int Tab_ManValue( Tab_Man_t * p, int a ) { assert( a >= 0 && a < 256 ); return s_256Primes[a]; } static inline int Tab_ManFinal( Tab_Man_t * p, int a ) { return a & p->Mask; } static inline word Tab_ManHashValue( Tab_Man_t * p, int * pCube ) { word Value = 0; int i; for ( i = 1; i <= pCube[0]; i++ ) Value += Tab_ManValue( p, pCube[i] ); return Value; } static inline word Tab_ManHashValueWithoutVar( Tab_Man_t * p, int * pCube, int iVar ) { word Value = 0; int i; for ( i = 1; i <= pCube[0]; i++ ) if ( i != iVar ) Value += Tab_ManValue( p, pCube[i] ); return Value; } static inline unsigned Tab_ManHashValueCube( Tab_Man_t * p, int c, int iVar ) { if ( iVar == 0xFFFF ) return (unsigned)(p->pValues[c] % p->nTable); return (unsigned)((p->pValues[c] - Tab_ManValue(p, Tab_ManCube(p, c)[iVar+1])) % p->nTable); } static inline void Tab_ManPrintCube( Tab_Man_t * p, int c, int Var ) { int i, * pCube = Tab_ManCube( p, c ); for ( i = 1; i <= pCube[0]; i++ ) // if ( i == Var + 1 ) // printf( "-" ); // else printf( "%d", !Abc_LitIsCompl(pCube[i]) ); } static inline void Tab_ManHashAdd( Tab_Man_t * p, int Value, int Cube, int VarA, int VarB ) { Tab_Ent_t * pCell = p->pTable + p->nEnts; Tab_Ent_t * pBin = p->pTable + Value; /* printf( "Adding cube " ); Tab_ManPrintCube( p, Cube, VarA ); printf( " with var %d and value %d\n", VarA, Value ); */ if ( pBin->Table >= 0 ) pCell->Next = pBin->Table; pBin->Table = p->nEnts++; pCell->Cube = Cube; pCell->VarA = VarA; pCell->VarB = VarB; } static inline void Tab_ManPrintEntry( Tab_Man_t * p, int e ) { printf( "Entry %10d : ", e ); printf( "Cube %6d ", p->pTable[e].Cube ); printf( "Value %12u ", Tab_ManHashValueCube(p, p->pTable[e].Cube, p->pTable[e].VarA) % p->nTable ); Tab_ManPrintCube( p, p->pTable[e].Cube, p->pTable[e].VarA ); printf( " " ); if ( p->pTable[e].VarA != 0xFFFF ) printf( "%2d ", p->pTable[e].VarA ); else printf( " " ); if ( p->pTable[e].VarB != 0xFFFF ) printf( "%2d ", p->pTable[e].VarB ); else printf( " " ); printf( "\n" ); } static inline void Tab_ManHashCollectBin( Tab_Man_t * p, int Bin, Vec_Int_t * vBin ) { Tab_Ent_t * pEnt = p->pTable + Bin; Vec_IntClear( vBin ); for ( pEnt = Tab_ManEnt(p, pEnt->Table); pEnt; pEnt = Tab_ManEnt(p, pEnt->Next) ) { Vec_IntPush( vBin, pEnt - p->pTable ); //Tab_ManPrintEntry( p, pEnt - p->pTable ); } //printf( "\n" ); } #define Tab_ManForEachCube( p, pCube, c ) \ for ( c = 0; c < p->nCubes && (pCube = Tab_ManCube(p, c)); c++ ) \ if ( pCube[0] == -1 ) {} else #define Tab_ManForEachCubeReverse( p, pCube, c ) \ for ( c = p->nCubes - 1; c >= 0 && (pCube = Tab_ManCube(p, c)); c-- ) \ if ( pCube[0] == -1 ) {} else /**Function************************************************************* Synopsis [Manager manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tab_Man_t * Tab_ManAlloc( int nVars, int nCubes ) { Tab_Man_t * p = ABC_CALLOC( Tab_Man_t, 1 ); p->nVars = nVars; p->nCubes = nCubes; p->Degree = Abc_Base2Log((p->nVars + 1) * p->nCubes + 1) + 3; p->Mask = (1 << p->Degree) - 1; //p->nEnts = 1; p->pCubes = ABC_CALLOC( int, p->nCubes * (p->nVars + 1) ); p->pValues = ABC_CALLOC( word, p->nCubes ); // p->pTable = ABC_CALLOC( Tab_Ent_t, (p->Mask + 1) ); printf( "Allocated %.2f MB for cube structure.\n", 4.0 * p->nCubes * (p->nVars + 2) / (1 << 20) ); return p; } void Tab_ManFree( Tab_Man_t * p ) { ABC_FREE( p->pCubes ); ABC_FREE( p->pValues ); ABC_FREE( p->pTable ); ABC_FREE( p ); } void Tab_ManStart( Tab_Man_t * p, Vec_Int_t * vCubes ) { int * pCube, Cube, c, v; p->nLits = 0; Tab_ManForEachCube( p, pCube, c ) { Cube = Vec_IntEntry( vCubes, c ); pCube[0] = p->nVars; for ( v = 0; v < p->nVars; v++ ) pCube[v+1] = Abc_Var2Lit( v, !((Cube >> v) & 1) ); p->pValues[c] = Tab_ManHashValue( p, pCube ); p->nLits += pCube[0]; } } /**Function************************************************************* Synopsis [Find a cube-free divisor of the two cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tab_ManCubeFree( int * pCube1, int * pCube2, Vec_Int_t * vCubeFree ) { int * pBeg1 = pCube1 + 1; // skip variable ID int * pBeg2 = pCube2 + 1; // skip variable ID int * pEnd1 = pBeg1 + pCube1[0]; int * pEnd2 = pBeg2 + pCube2[0]; int Counter = 0, fAttr0 = 0, fAttr1 = 1; Vec_IntClear( vCubeFree ); while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) pBeg1++, pBeg2++, Counter++; else if ( *pBeg1 < *pBeg2 ) Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) ); else { if ( Vec_IntSize(vCubeFree) == 0 ) fAttr0 = 1, fAttr1 = 0; Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) ); } } while ( pBeg1 < pEnd1 ) Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg1++, fAttr0) ); while ( pBeg2 < pEnd2 ) Vec_IntPush( vCubeFree, Abc_Var2Lit(*pBeg2++, fAttr1) ); if ( Vec_IntSize(vCubeFree) == 0 ) printf( "The SOP has duplicated cubes.\n" ); else if ( Vec_IntSize(vCubeFree) == 1 ) printf( "The SOP has contained cubes.\n" ); // else if ( Vec_IntSize(vCubeFree) == 2 && Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 0))) == Abc_Lit2Var(Abc_Lit2Var(Vec_IntEntry(vCubeFree, 1))) ) // printf( "The SOP has distance-1 cubes or it is not a prime cover. Please make sure the result verifies.\n" ); assert( !Abc_LitIsCompl(Vec_IntEntry(vCubeFree, 0)) ); return Counter; } int Tab_ManCheckEqual2( int * pCube1, int * pCube2, int Var1, int Var2 ) { int i1, i2; for ( i1 = i2 = 1; ; i1++, i2++ ) { if ( i1 == Var1 ) i1++; if ( i2 == Var2 ) i2++; if ( i1 > pCube1[0] || i2 > pCube2[0] ) return 0; if ( pCube1[i1] != pCube2[i2] ) return 0; if ( i1 == pCube1[0] && i2 == pCube2[0] ) return 1; } } int Tab_ManCheckEqual( int * pCube1, int * pCube2, int Var1, int Var2 ) { int Cube1[32], Cube2[32]; int i, k, nVars1, nVars2; assert( pCube1[0] <= 32 ); assert( pCube2[0] <= 32 ); for ( i = 1, k = 0; i <= pCube1[0]; i++ ) if ( i != Var1 ) Cube1[k++] = pCube1[i]; nVars1 = k; for ( i = 1, k = 0; i <= pCube2[0]; i++ ) if ( i != Var2 ) Cube2[k++] = pCube2[i]; nVars2 = k; if ( nVars1 != nVars2 ) return 0; for ( i = 0; i < nVars1; i++ ) if ( Cube1[i] != Cube2[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Collecting distance-1 pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tab_ManCountItems( Tab_Man_t * p, int Dist2, Vec_Int_t ** pvStarts ) { Vec_Int_t * vStarts = Vec_IntAlloc( p->nCubes ); int * pCube, c, Count = 0; Tab_ManForEachCube( p, pCube, c ) { Vec_IntPush( vStarts, Count ); Count += 1 + pCube[0]; if ( Dist2 ) Count += pCube[0] * pCube[0] / 2; } assert( Vec_IntSize(vStarts) == p->nCubes ); if ( pvStarts ) *pvStarts = vStarts; return Count; } Vec_Int_t * Tab_ManCollectDist1( Tab_Man_t * p, int Dist2 ) { Vec_Int_t * vStarts = NULL; // starting mark for each cube int nItems = Tab_ManCountItems( p, Dist2, &vStarts ); // item count int nBits = Abc_Base2Log( nItems ) + 6; // hash table size Vec_Bit_t * vPres = Vec_BitStart( 1 << nBits ); // hash table Vec_Bit_t * vMarks = Vec_BitStart( nItems ); // collisions Vec_Int_t * vUseful = Vec_IntAlloc( 1000 ); // useful pairs Vec_Int_t * vBin = Vec_IntAlloc( 100 ); Vec_Int_t * vCubeFree = Vec_IntAlloc( 100 ); word Value; unsigned Mask = (1 << nBits) - 1; int * pCube, c, a, b, nMarks = 0, nUseful, Entry1, Entry2; // iterate forward Tab_ManForEachCube( p, pCube, c ) { // cube if ( Vec_BitAddEntry(vPres, (int)p->pValues[c] & Mask) ) Vec_BitWriteEntry( vMarks, nMarks, 1 ); nMarks++; // dist1 for ( a = 1; a <= pCube[0]; a++, nMarks++ ) if ( Vec_BitAddEntry(vPres, (int)(p->pValues[c] - Tab_ManValue(p, pCube[a])) & Mask) ) Vec_BitWriteEntry( vMarks, nMarks, 1 ); // dist2 if ( Dist2 ) for ( a = 1; a <= pCube[0]; a++ ) { Value = p->pValues[c] - Tab_ManValue(p, pCube[a]); for ( b = a + 1; b <= pCube[0]; b++, nMarks++ ) if ( Vec_BitAddEntry(vPres, (int)(Value - Tab_ManValue(p, pCube[b])) & Mask) ) Vec_BitWriteEntry( vMarks, nMarks, 1 ); } } assert( nMarks == nItems ); Vec_BitReset( vPres ); // iterate backward nMarks--; Tab_ManForEachCubeReverse( p, pCube, c ) { Value = p->pValues[c]; // dist2 if ( Dist2 ) for ( a = pCube[0]; a >= 1; a-- ) { Value = p->pValues[c] - Tab_ManValue(p, pCube[a]); for ( b = pCube[0]; b >= a + 1; b--, nMarks-- ) if ( Vec_BitAddEntry(vPres, (int)(Value - Tab_ManValue(p, pCube[b])) & Mask) ) Vec_BitWriteEntry( vMarks, nMarks, 1 ); } // dist1 for ( a = pCube[0]; a >= 1; a--, nMarks-- ) if ( Vec_BitAddEntry(vPres, (int)(p->pValues[c] - Tab_ManValue(p, pCube[a])) & Mask) ) Vec_BitWriteEntry( vMarks, nMarks, 1 ); // cube if ( Vec_BitAddEntry(vPres, (int)p->pValues[c] & Mask) ) Vec_BitWriteEntry( vMarks, nMarks, 1 ); nMarks--; } nMarks++; assert( nMarks == 0 ); Vec_BitFree( vPres ); // count useful nUseful = Vec_BitCount( vMarks ); printf( "Items = %d. Bits = %d. Useful = %d. \n", nItems, nBits, nUseful ); // add to the hash table p->nTable = Abc_PrimeCudd(nUseful); p->pTable = ABC_FALLOC( Tab_Ent_t, p->nTable ); printf( "Table %d\n", p->nTable ); Tab_ManForEachCube( p, pCube, c ) { // cube if ( Vec_BitEntry(vMarks, nMarks++) ) Tab_ManHashAdd( p, (int)(p->pValues[c] % p->nTable), c, TAB_UNUSED, TAB_UNUSED ); // dist1 for ( a = 1; a <= pCube[0]; a++, nMarks++ ) if ( Vec_BitEntry(vMarks, nMarks) ) Tab_ManHashAdd( p, (int)((p->pValues[c] - Tab_ManValue(p, pCube[a])) % p->nTable), c, a-1, TAB_UNUSED ); // dist2 if ( Dist2 ) for ( a = 1; a <= pCube[0]; a++ ) { Value = p->pValues[c] - Tab_ManValue(p, pCube[a]); for ( b = a + 1; b <= pCube[0]; b++, nMarks++ ) if ( Vec_BitEntry(vMarks, nMarks) ) Tab_ManHashAdd( p, (int)((Value - Tab_ManValue(p, pCube[b])) % p->nTable), c, a-1, b-1 ); } } assert( nMarks == nItems ); // collect entries for ( c = 0; c < p->nTable; c++ ) { Tab_ManHashCollectBin( p, c, vBin ); //printf( "%d ", Vec_IntSize(vBin) ); //if ( c > 100 ) // break; Vec_IntForEachEntry( vBin, Entry1, a ) Vec_IntForEachEntryStart( vBin, Entry2, b, a + 1 ) { Tab_Ent_t * pEntA = Tab_ManEnt( p, Entry1 ); Tab_Ent_t * pEntB = Tab_ManEnt( p, Entry2 ); int * pCubeA = Tab_ManCube( p, pEntA->Cube ); int * pCubeB = Tab_ManCube( p, pEntB->Cube ); // int Base = Tab_ManCubeFree( pCubeA, pCubeB, vCubeFree ); // if ( Vec_IntSize(vCubeFree) == 2 ) if ( Tab_ManCheckEqual(pCubeA, pCubeB, pEntA->VarA+1, pEntB->VarA+1) ) { Vec_IntPushTwo( vUseful, pEntA->Cube, pEntB->Cube ); } } } //printf( "\n" ); ABC_FREE( p->pTable ); Vec_IntFree( vCubeFree ); Vec_IntFree( vBin ); Vec_BitFree( vMarks ); return vUseful; } /**Function************************************************************* Synopsis [Table decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tab_DecomposeTest() { int nVars = 20;// no more than 13 abctime clk = Abc_Clock(); Vec_Int_t * vPairs; Vec_Int_t * vPrimes = Abc_GenPrimes( nVars ); Tab_Man_t * p = Tab_ManAlloc( nVars, Vec_IntSize(vPrimes) ); Tab_ManStart( p, vPrimes ); printf( "Created %d cubes dependent on %d variables with %d literals.\n", p->nCubes, p->nVars ); vPairs = Tab_ManCollectDist1( p, 0 ); printf( "Collected %d pairs.\n", Vec_IntSize(vPairs)/2 ); Vec_IntFree( vPairs ); Tab_ManFree( p ); Vec_IntFree( vPrimes ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilProgress.c000066400000000000000000000121551300674244400257700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilProgress.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Progress bar.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilProgress.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "extra.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct ProgressBarStruct { int nItemsNext; // the number of items for the next update of the progress bar int nItemsTotal; // the total number of items int posTotal; // the total number of positions int posCur; // the current position FILE * pFile; // the output stream }; static void Extra_ProgressBarShow( ProgressBar * p, char * pString ); static void Extra_ProgressBarClean( ProgressBar * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the progress bar.] Description [The first parameter is the output stream (pFile), where the progress is printed. The current printing position should be the first one on the given line. The second parameters is the total number of items that correspond to 100% position of the progress bar.] SideEffects [] SeeAlso [] ***********************************************************************/ ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ) { ProgressBar * p; if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL; p = ABC_ALLOC( ProgressBar, 1 ); memset( p, 0, sizeof(ProgressBar) ); p->pFile = pFile; p->nItemsTotal = nItemsTotal; p->posTotal = 78; p->posCur = 1; p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); Extra_ProgressBarShow( p, NULL ); return p; } /**Function************************************************************* Synopsis [Updates the progress bar.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ) { if ( p == NULL ) return; if ( nItemsCur < p->nItemsNext ) return; if ( nItemsCur >= p->nItemsTotal ) { p->posCur = 78; p->nItemsNext = 0x7FFFFFFF; } else { p->posCur += 7; p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); } Extra_ProgressBarShow( p, pString ); } /**Function************************************************************* Synopsis [Stops the progress bar.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ProgressBarStop( ProgressBar * p ) { if ( p == NULL ) return; Extra_ProgressBarClean( p ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the progress bar of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ProgressBarShow( ProgressBar * p, char * pString ) { int i; if ( p == NULL ) return; if ( Abc_FrameIsBatchMode() ) return; if ( pString ) fprintf( p->pFile, "%s ", pString ); for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ ) fprintf( p->pFile, "-" ); if ( i == p->posCur ) fprintf( p->pFile, ">" ); for ( i++ ; i <= p->posTotal; i++ ) fprintf( p->pFile, " " ); fprintf( p->pFile, "\r" ); fflush( stdout ); } /**Function************************************************************* Synopsis [Cleans the progress bar before quitting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_ProgressBarClean( ProgressBar * p ) { int i; if ( p == NULL ) return; if ( Abc_FrameIsBatchMode() ) return; for ( i = 0; i <= p->posTotal; i++ ) fprintf( p->pFile, " " ); fprintf( p->pFile, "\r" ); fflush( stdout ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilReader.c000066400000000000000000000306451300674244400253720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilReader.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [File reading utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilReader.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "extra.h" #include "misc/vec/vec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define EXTRA_BUFFER_SIZE 4*1048576 // 1M - size of the data chunk stored in memory #define EXTRA_OFFSET_SIZE 4096 // 4K - load new data when less than this is left #define EXTRA_MINIMUM(a,b) (((a) < (b))? (a) : (b)) struct Extra_FileReader_t_ { // the input file char * pFileName; // the input file name FILE * pFile; // the input file pointer int nFileSize; // the total number of bytes in the file int nFileRead; // the number of bytes currently read from file // info about processing different types of input chars char pCharMap[256]; // the character map // temporary storage for data char * pBuffer; // the buffer int nBufferSize; // the size of the buffer char * pBufferCur; // the current reading position char * pBufferEnd; // the first position not used by currently loaded data char * pBufferStop; // the position where loading new data will be done // tokens given to the user Vec_Ptr_t * vTokens; // the vector of tokens returned to the user Vec_Int_t * vLines; // the vector of line numbers for each token int nLineCounter; // the counter of lines processed // status of the parser int fStop; // this flag goes high when the end of file is reached }; // character types typedef enum { EXTRA_CHAR_COMMENT, // a character that begins the comment EXTRA_CHAR_NORMAL, // a regular character EXTRA_CHAR_STOP, // a character that delimits a series of tokens EXTRA_CHAR_CLEAN // a character that should be cleaned } Extra_CharType_t; // the static functions static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ); static void Extra_FileReaderReload( Extra_FileReader_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, char * pCharsComment, char * pCharsStop, char * pCharsClean ) { Extra_FileReader_t * p; FILE * pFile; char * pChar; int nCharsToRead; int RetValue; // check if the file can be opened pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Extra_FileReaderAlloc(): Cannot open input file \"%s\".\n", pFileName ); return NULL; } // start the file reader p = ABC_ALLOC( Extra_FileReader_t, 1 ); memset( p, 0, sizeof(Extra_FileReader_t) ); p->pFileName = pFileName; p->pFile = pFile; // set the character map memset( p->pCharMap, EXTRA_CHAR_NORMAL, 256 ); for ( pChar = pCharsComment; *pChar; pChar++ ) p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_COMMENT; for ( pChar = pCharsStop; *pChar; pChar++ ) p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_STOP; for ( pChar = pCharsClean; *pChar; pChar++ ) p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_CLEAN; // get the file size, in bytes fseek( pFile, 0, SEEK_END ); p->nFileSize = ftell( pFile ); rewind( pFile ); // allocate the buffer p->pBuffer = ABC_ALLOC( char, EXTRA_BUFFER_SIZE+1 ); p->nBufferSize = EXTRA_BUFFER_SIZE; p->pBufferCur = p->pBuffer; // determine how many chars to read nCharsToRead = EXTRA_MINIMUM(p->nFileSize, EXTRA_BUFFER_SIZE); // load the first part into the buffer RetValue = fread( p->pBuffer, nCharsToRead, 1, p->pFile ); p->nFileRead = nCharsToRead; // set the ponters to the end and the stopping point p->pBufferEnd = p->pBuffer + nCharsToRead; p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE; // start the arrays p->vTokens = Vec_PtrAlloc( 100 ); p->vLines = Vec_IntAlloc( 100 ); p->nLineCounter = 1; // 1-based line counting return p; } /**Function************************************************************* Synopsis [Stops the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_FileReaderFree( Extra_FileReader_t * p ) { if ( p->pFile ) fclose( p->pFile ); ABC_FREE( p->pBuffer ); Vec_PtrFree( p->vTokens ); Vec_IntFree( p->vLines ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the file size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileReaderGetFileName( Extra_FileReader_t * p ) { return p->pFileName; } /**Function************************************************************* Synopsis [Returns the file size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileReaderGetFileSize( Extra_FileReader_t * p ) { return p->nFileSize; } /**Function************************************************************* Synopsis [Returns the current reading position.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p ) { return p->nFileRead - (p->pBufferEnd - p->pBufferCur); } /**Function************************************************************* Synopsis [Returns the line number for the given token.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken ) { assert( iToken >= 0 && iToken < p->vTokens->nSize ); return p->vLines->pArray[iToken]; } /**Function************************************************************* Synopsis [Returns the next set of tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Extra_FileReaderGetTokens( Extra_FileReader_t * p ) { Vec_Ptr_t * vTokens; while ( (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens_int( p )) ) if ( vTokens->nSize > 0 ) break; return vTokens; } /**Function************************************************************* Synopsis [Returns the next set of tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ) { char * pChar; int fTokenStarted, MapValue; if ( p->fStop ) return NULL; // reset the token info p->vTokens->nSize = 0; p->vLines->nSize = 0; fTokenStarted = 0; // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Extra_FileReaderReload( p ); // printf( "%d\n", p->pBufferEnd - p->pBufferCur ); // process the string starting from the current position for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) { // count the lines if ( *pChar == '\n' ) p->nLineCounter++; // switch depending on the character MapValue = p->pCharMap[(int)*pChar]; // printf( "Char value = %d. Map value = %d.\n", *pChar, MapValue ); switch ( MapValue ) { case EXTRA_CHAR_COMMENT: if ( *pChar != '/' || *(pChar+1) == '/' ) { // dealing with the need to have // as a comment // if the token was being written, stop it if ( fTokenStarted ) fTokenStarted = 0; // eraze the comment till the end of line while ( *pChar != '\n' ) { *pChar++ = 0; if ( pChar == p->pBufferEnd ) { // this failure is due to the fact the comment continued // through EXTRA_OFFSET_SIZE chars till the end of the buffer printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName ); return NULL; } } pChar--; break; } // otherwise it is a normal character case EXTRA_CHAR_NORMAL: if ( !fTokenStarted ) { Vec_PtrPush( p->vTokens, pChar ); Vec_IntPush( p->vLines, p->nLineCounter ); fTokenStarted = 1; } break; case EXTRA_CHAR_STOP: if ( fTokenStarted ) fTokenStarted = 0; *pChar = 0; // prepare before leaving p->pBufferCur = pChar + 1; return p->vTokens; case EXTRA_CHAR_CLEAN: if ( fTokenStarted ) fTokenStarted = 0; *pChar = 0; break; default: assert( 0 ); } } // the file is finished or the last part continued // through EXTRA_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { *pChar = 0; p->fStop = 1; return p->vTokens; } printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName ); /* { int i; for ( i = 0; i < p->vTokens->nSize; i++ ) printf( "%s ", p->vTokens->pArray[i] ); printf( "\n" ); } */ return NULL; } /**Function************************************************************* Synopsis [Loads new data into the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_FileReaderReload( Extra_FileReader_t * p ) { int nCharsUsed, nCharsToRead; int RetValue; assert( !p->fStop ); assert( p->pBufferCur > p->pBufferStop ); assert( p->pBufferCur < p->pBufferEnd ); // figure out how many chars are still not processed nCharsUsed = p->pBufferEnd - p->pBufferCur; // move the remaining data to the beginning of the buffer memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); p->pBufferCur = p->pBuffer; // determine how many chars we will read nCharsToRead = EXTRA_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); // read the chars RetValue = fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); p->nFileRead += nCharsToRead; // set the ponters to the end and the stopping point p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilSupp.c000066400000000000000000000412771300674244400251220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilSupp.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Support minimization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilSupp.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "misc/vec/vecWec.h" #include "extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Generate m-out-of-n vectors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_SuppCountOnes( unsigned i ) { i = i - ((i >> 1) & 0x55555555); i = (i & 0x33333333) + ((i >> 2) & 0x33333333); i = ((i + (i >> 4)) & 0x0F0F0F0F); return (i*(0x01010101))>>24; } Vec_Wrd_t * Abc_SuppGen( int m, int n ) { Vec_Wrd_t * vRes = Vec_WrdAlloc( 1000 ); int i, Size = (1 << n); for ( i = 0; i < Size; i++ ) if ( Abc_SuppCountOnes(i) == m ) Vec_WrdPush( vRes, i ); return vRes; } /**Function************************************************************* Synopsis [Perform verification.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SuppVerify( Vec_Wrd_t * p, word * pMatrix, int nVars, int nVarsMin ) { Vec_Wrd_t * pNew; word * pLimit, * pEntry1, * pEntry2; word Entry, EntryNew; int i, k, v, Value, Counter = 0; pNew = Vec_WrdAlloc( Vec_WrdSize(p) ); Vec_WrdForEachEntry( p, Entry, i ) { EntryNew = 0; for ( v = 0; v < nVarsMin; v++ ) { Value = 0; for ( k = 0; k < nVars; k++ ) if ( ((pMatrix[v] >> k) & 1) && ((Entry >> k) & 1) ) Value ^= 1; if ( Value ) EntryNew |= (((word)1) << v); } Vec_WrdPush( pNew, EntryNew ); } // check that they are disjoint pLimit = Vec_WrdLimit(pNew); pEntry1 = Vec_WrdArray(pNew); for ( ; pEntry1 < pLimit; pEntry1++ ) for ( pEntry2 = pEntry1 + 1; pEntry2 < pLimit; pEntry2++ ) if ( *pEntry1 == *pEntry2 ) Counter++; if ( Counter ) printf( "The total of %d pairs fail verification.\n", Counter ); else printf( "Verification successful.\n" ); Vec_WrdFree( pNew ); } /**Function************************************************************* Synopsis [Generate pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Abc_SuppGenPairs( Vec_Wrd_t * p, int nBits ) { Vec_Wrd_t * vRes = Vec_WrdAlloc( 1000 ); unsigned * pMap = ABC_CALLOC( unsigned, 1 << Abc_MaxInt(0,nBits-5) ); word * pLimit = Vec_WrdLimit(p); word * pEntry1 = Vec_WrdArray(p); word * pEntry2, Value; for ( ; pEntry1 < pLimit; pEntry1++ ) for ( pEntry2 = pEntry1 + 1; pEntry2 < pLimit; pEntry2++ ) { Value = *pEntry1 ^ *pEntry2; if ( Abc_InfoHasBit(pMap, (int)Value) ) continue; Abc_InfoXorBit( pMap, (int)Value ); Vec_WrdPush( vRes, Value ); } ABC_FREE( pMap ); return vRes; } Vec_Wrd_t * Abc_SuppGenPairs2( int nOnes, int nBits ) { Vec_Wrd_t * vRes = Vec_WrdAlloc( 1000 ); int i, k, Size = (1 << nBits), Value; for ( i = 0; i < Size; i++ ) { Value = Abc_SuppCountOnes(i); for ( k = 1; k <= nOnes; k++ ) if ( Value == 2*k ) break; if ( k <= nOnes ) Vec_WrdPush( vRes, i ); } return vRes; } /**Function************************************************************* Synopsis [Select variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SuppPrintMask( word uMask, int nBits ) { int i; for ( i = 0; i < nBits; i++ ) printf( "%d", (int)((uMask >> i) & 1) ); printf( "\n" ); } void Abc_SuppGenProfile( Vec_Wrd_t * p, int nBits, int * pCounts ) { word Ent; int i, k, b; Vec_WrdForEachEntry( p, Ent, i ) for ( b = ((Ent >> nBits) & 1), k = 0; k < nBits; k++ ) pCounts[k] += ((Ent >> k) & 1) ^ b; } void Abc_SuppPrintProfile( Vec_Wrd_t * p, int nBits ) { int k, Counts[64] = {0}; Abc_SuppGenProfile( p, nBits, Counts ); for ( k = 0; k < nBits; k++ ) printf( "%2d : %6d %6.2f %%\n", k, Counts[k], 100.0 * Counts[k] / Vec_WrdSize(p) ); } int Abc_SuppGenFindBest( Vec_Wrd_t * p, int nBits, int * pMerit ) { int k, kBest = 0, Counts[64] = {0}; Abc_SuppGenProfile( p, nBits, Counts ); for ( k = 1; k < nBits; k++ ) if ( Counts[kBest] < Counts[k] ) kBest = k; *pMerit = Counts[kBest]; return kBest; } void Abc_SuppGenSelectVar( Vec_Wrd_t * p, int nBits, int iVar ) { word * pEntry = Vec_WrdArray(p); word * pLimit = Vec_WrdLimit(p); for ( ; pEntry < pLimit; pEntry++ ) if ( (*pEntry >> iVar) & 1 ) *pEntry ^= (((word)1) << nBits); } void Abc_SuppGenFilter( Vec_Wrd_t * p, int nBits ) { word Ent; int i, k = 0; Vec_WrdForEachEntry( p, Ent, i ) if ( ((Ent >> nBits) & 1) == 0 ) Vec_WrdWriteEntry( p, k++, Ent ); Vec_WrdShrink( p, k ); } word Abc_SuppFindOne( Vec_Wrd_t * p, int nBits ) { word uMask = 0; int Prev = -1, This, Var; while ( 1 ) { Var = Abc_SuppGenFindBest( p, nBits, &This ); if ( Prev >= This ) break; Prev = This; Abc_SuppGenSelectVar( p, nBits, Var ); uMask |= (((word)1) << Var); } return uMask; } int Abc_SuppMinimize( word * pMatrix, Vec_Wrd_t * p, int nBits, int fVerbose ) { int i; for ( i = 0; Vec_WrdSize(p) > 0; i++ ) { // Abc_SuppPrintProfile( p, nBits ); pMatrix[i] = Abc_SuppFindOne( p, nBits ); Abc_SuppGenFilter( p, nBits ); if ( !fVerbose ) continue; // print stats printf( "%2d : ", i ); printf( "%6d ", Vec_WrdSize(p) ); Abc_SuppPrintMask( pMatrix[i], nBits ); // printf( "\n" ); } return i; } /**Function************************************************************* Synopsis [Create representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SuppTest( int nOnes, int nVars, int fUseSimple, int fCheck, int fVerbose ) { int nVarsMin; word Matrix[64]; abctime clk = Abc_Clock(); // create the problem Vec_Wrd_t * vRes = Abc_SuppGen( nOnes, nVars ); Vec_Wrd_t * vPairs = fUseSimple ? Abc_SuppGenPairs2( nOnes, nVars ) : Abc_SuppGenPairs( vRes, nVars ); assert( nVars < 100 ); printf( "M = %2d N = %2d : ", nOnes, nVars ); printf( "K = %6d ", Vec_WrdSize(vRes) ); printf( "Total = %12.0f ", 0.5 * Vec_WrdSize(vRes) * (Vec_WrdSize(vRes) - 1) ); printf( "Distinct = %8d ", Vec_WrdSize(vPairs) ); Abc_PrintTime( 1, "Reduction time", Abc_Clock() - clk ); // solve the problem clk = Abc_Clock(); nVarsMin = Abc_SuppMinimize( Matrix, vPairs, nVars, fVerbose ); printf( "Solution with %d variables found. ", nVarsMin ); Abc_PrintTime( 1, "Covering time", Abc_Clock() - clk ); if ( fCheck ) Abc_SuppVerify( vRes, Matrix, nVars, nVarsMin ); Vec_WrdFree( vPairs ); Vec_WrdFree( vRes ); } /**Function************************************************************* Synopsis [Reads the input part of the cubes specified in MIN format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Abc_SuppReadMin( char * pFileName, int * pnVars ) { Vec_Wrd_t * vRes; word uCube; int nCubes = 0, nVars = -1, iVar; char * pCur, * pToken, * pStart = "INPUT F-COVER"; char * pStr = Extra_FileReadContents( pFileName ); if ( pStr == NULL ) { printf( "Cannot open input file (%s).\n", pFileName ); return NULL; } pCur = strstr( pStr, pStart ); if ( pCur == NULL ) { printf( "Cannot find beginning of cube cover (%s).\n", pStart ); return NULL; } pToken = strtok( pCur + strlen(pStart), " \t\r\n," ); nCubes = atoi( pToken ); if ( nCubes < 1 || nCubes > 1000000 ) { printf( "The number of cubes in not in the range [1; 1000000].\n" ); return NULL; } vRes = Vec_WrdAlloc( 1000 ); uCube = 0; iVar = 0; while ( (pToken = strtok(NULL, " \t\r\n,")) != NULL ) { if ( strlen(pToken) > 2 ) { if ( !strncmp(pToken, "INPUT", strlen("INPUT")) ) break; if ( iVar > 64 ) { printf( "The number of inputs (%d) is too high.\n", iVar ); Vec_WrdFree(vRes); return NULL; } if ( nVars == -1 ) nVars = iVar; else if ( nVars != iVar ) { printf( "The number of inputs (%d) does not match declaration (%d).\n", nVars, iVar ); Vec_WrdFree(vRes); return NULL; } Vec_WrdPush( vRes, uCube ); uCube = 0; iVar = 0; continue; } if ( pToken[1] == '0' && pToken[0] == '1' ) // value 1 uCube |= (((word)1) << iVar); else if ( pToken[1] != '1' || pToken[0] != '0' ) // value 0 { printf( "Strange literal representation (%s) of cube %d.\n", pToken, nCubes ); Vec_WrdFree(vRes); return NULL; } iVar++; } ABC_FREE( pStr ); if ( Vec_WrdSize(vRes) != nCubes ) { printf( "The number of cubes (%d) does not match declaration (%d).\n", Vec_WrdSize(vRes), nCubes ); Vec_WrdFree(vRes); return NULL; } else printf( "Successfully parsed function with %d inputs and %d cubes.\n", nVars, nCubes ); *pnVars = nVars; return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Abc_SuppDiffMatrix( Vec_Wrd_t * vCubes ) { abctime clk = Abc_Clock(); word * pEnt2, * pEnt = Vec_WrdArray( vCubes ); word * pLimit = Vec_WrdLimit( vCubes ); Vec_Wrd_t * vRes, * vPairs = Vec_WrdAlloc( Vec_WrdSize(vCubes) * (Vec_WrdSize(vCubes) - 1) / 2 ); word * pStore = Vec_WrdArray( vPairs ); for ( ; pEnt < pLimit; pEnt++ ) for ( pEnt2 = pEnt+1; pEnt2 < pLimit; pEnt2++ ) *pStore++ = *pEnt ^ *pEnt2; vPairs->nSize = Vec_WrdCap(vPairs); assert( pStore == Vec_WrdLimit(vPairs) ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // vRes = Vec_WrdUniqifyHash( vPairs, 1 ); vRes = Vec_WrdDup( vPairs ); printf( "Successfully generated diff matrix with %10d rows (%6.2f %%). ", Vec_WrdSize(vRes), 100.0 * Vec_WrdSize(vRes) / Vec_WrdSize(vPairs) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Vec_WrdFree( vPairs ); return vRes; } /**Function************************************************************* Synopsis [Solve difference matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_SuppCountOnes64( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } int Abc_SuppFindVar( Vec_Wec_t * pS, Vec_Wec_t * pD, int nVars ) { int v, vBest = -1, dBest = -1; for ( v = 0; v < nVars; v++ ) { if ( Vec_WecLevelSize(pS, v) ) continue; if ( vBest == -1 || dBest > Vec_WecLevelSize(pD, v) ) vBest = v, dBest = Vec_WecLevelSize(pD, v); } return vBest; } void Abc_SuppRemove( Vec_Wrd_t * p, int * pCounts, Vec_Wec_t * pS, Vec_Wec_t * pD, int iVar, int nVars ) { word Entry; int i, v; assert( Vec_WecLevelSize(pS, iVar) == 0 ); Vec_IntClear( Vec_WecEntry(pD, iVar) ); Vec_WrdForEachEntry( p, Entry, i ) { if ( ((Entry >> iVar) & 1) == 0 ) continue; pCounts[i]--; if ( pCounts[i] == 1 ) { for ( v = 0; v < nVars; v++ ) if ( (Entry >> v) & 1 ) { Vec_IntRemove( Vec_WecEntry(pD, v), i ); Vec_WecPush( pS, v, i ); } } else if ( pCounts[i] == 2 ) { for ( v = 0; v < nVars; v++ ) if ( (Entry >> v) & 1 ) Vec_WecPush( pD, v, i ); } } } void Abc_SuppProfile( Vec_Wec_t * pS, Vec_Wec_t * pD, int nVars ) { int v; for ( v = 0; v < nVars; v++ ) printf( "%2d : S = %3d D = %3d\n", v, Vec_WecLevelSize(pS, v), Vec_WecLevelSize(pD, v) ); } int Abc_SuppSolve( Vec_Wrd_t * p, int nVars ) { abctime clk = Abc_Clock(); Vec_Wrd_t * pNew = Vec_WrdDup( p ); Vec_Wec_t * vSingles = Vec_WecStart( 64 ); Vec_Wec_t * vDoubles = Vec_WecStart( 64 ); word Entry; int i, v, iVar, nVarsNew = nVars; int * pCounts = ABC_ALLOC( int, Vec_WrdSize(p) ); Vec_WrdForEachEntry( p, Entry, i ) { pCounts[i] = Abc_SuppCountOnes64( Entry ); if ( pCounts[i] == 1 ) { for ( v = 0; v < nVars; v++ ) if ( (Entry >> v) & 1 ) Vec_WecPush( vSingles, v, i ); } else if ( pCounts[i] == 2 ) { for ( v = 0; v < nVars; v++ ) if ( (Entry >> v) & 1 ) Vec_WecPush( vDoubles, v, i ); } } Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // Abc_SuppProfile( vSingles, vDoubles, nVars ); // find variable in 0 singles and the smallest doubles while ( 1 ) { iVar = Abc_SuppFindVar( vSingles, vDoubles, nVars ); if ( iVar == -1 ) break; // printf( "Selected variable %d.\n", iVar ); Abc_SuppRemove( pNew, pCounts, vSingles, vDoubles, iVar, nVars ); // Abc_SuppProfile( vSingles, vDoubles, nVars ); nVarsNew--; } // printf( "Result = %d (out of %d)\n", nVarsNew, nVars ); Vec_WecFree( vSingles ); Vec_WecFree( vDoubles ); Vec_WrdFree( pNew ); ABC_FREE( pCounts ); return nVarsNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SuppReadMinTest( char * pFileName ) { // int fVerbose = 0; abctime clk = Abc_Clock(); // word Matrix[64]; int nVars, nVarsMin; Vec_Wrd_t * vPairs, * vCubes; vCubes = Abc_SuppReadMin( pFileName, &nVars ); if ( vCubes == NULL ) return; vPairs = Abc_SuppDiffMatrix( vCubes ); Vec_WrdFreeP( &vCubes ); // solve the problem clk = Abc_Clock(); // nVarsMin = Abc_SuppMinimize( Matrix, vPairs, nVars, fVerbose ); nVarsMin = Abc_SuppSolve( vPairs, nVars ); printf( "Solution with %d variables found. ", nVarsMin ); Abc_PrintTime( 1, "Covering time", Abc_Clock() - clk ); Vec_WrdFreeP( &vPairs ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilTruth.c000066400000000000000000001163151300674244400252750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilMisc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Various procedures for truth table manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "extra.h" ABC_NAMESPACE_IMPL_START /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ static unsigned s_VarMasks[5][2] = { { 0x33333333, 0xAAAAAAAA }, { 0x55555555, 0xCCCCCCCC }, { 0x0F0F0F0F, 0xF0F0F0F0 }, { 0x00FF00FF, 0xFF00FF00 }, { 0x0000FFFF, 0xFFFF0000 } }; /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function************************************************************* Synopsis [Derive elementary truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned ** Extra_TruthElementary( int nVars ) { unsigned ** pRes; int i, k, nWords; nWords = Extra_TruthWordNum(nVars); pRes = (unsigned **)Extra_ArrayAlloc( nVars, nWords, 4 ); for ( i = 0; i < nVars; i++ ) { if ( i < 5 ) { for ( k = 0; k < nWords; k++ ) pRes[i][k] = s_VarMasks[i][1]; } else { for ( k = 0; k < nWords; k++ ) if ( k & (1 << (i-5)) ) pRes[i][k] = ~(unsigned)0; else pRes[i][k] = 0; } } return pRes; } /**Function************************************************************* Synopsis [Swaps two adjacent variables in the truth table.] Description [Swaps var number Start and var number Start+1 (0-based numbers). The input truth table is pIn. The output truth table is pOut.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) { static unsigned PMasks[4][3] = { { 0x99999999, 0x22222222, 0x44444444 }, { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } }; int nWords = Extra_TruthWordNum( nVars ); int i, k, Step, Shift; assert( iVar < nVars - 1 ); if ( iVar < 4 ) { Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); } else if ( iVar > 4 ) { Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 4*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pIn[i]; for ( i = 0; i < Step; i++ ) pOut[Step+i] = pIn[2*Step+i]; for ( i = 0; i < Step; i++ ) pOut[2*Step+i] = pIn[Step+i]; for ( i = 0; i < Step; i++ ) pOut[3*Step+i] = pIn[3*Step+i]; pIn += 4*Step; pOut += 4*Step; } } else // if ( iVar == 4 ) { for ( i = 0; i < nWords; i += 2 ) { pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); } } } /**Function************************************************************* Synopsis [Swaps two adjacent variables in the truth table.] Description [Swaps var number Start and var number Start+1 (0-based numbers). The input truth table is pIn. The output truth table is pOut.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start ) { int nWords = (nVars <= 5)? 1 : (1 << (nVars-5)); int i, k, Step; assert( Start < nVars - 1 ); switch ( Start ) { case 0: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1); return; case 1: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2); return; case 2: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4); return; case 3: for ( i = 0; i < nWords; i++ ) pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8); return; case 4: for ( i = 0; i < nWords; i += 2 ) { pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); } return; default: Step = (1 << (Start - 5)); for ( k = 0; k < nWords; k += 4*Step ) { for ( i = 0; i < Step; i++ ) pOut[i] = pIn[i]; for ( i = 0; i < Step; i++ ) pOut[Step+i] = pIn[2*Step+i]; for ( i = 0; i < Step; i++ ) pOut[2*Step+i] = pIn[Step+i]; for ( i = 0; i < Step; i++ ) pOut[3*Step+i] = pIn[3*Step+i]; pIn += 4*Step; pOut += 4*Step; } return; } } /**Function************************************************************* Synopsis [Expands the truth table according to the phase.] Description [The input and output truth tables are in pIn/pOut. The current number of variables is nVars. The total number of variables in nVarsAll. The last argument (Phase) contains shows where the variables should go.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) { unsigned * pTemp; int i, k, Var = nVars - 1, Counter = 0; for ( i = nVarsAll - 1; i >= 0; i-- ) if ( Phase & (1 << i) ) { for ( k = Var; k < i; k++ ) { Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); pTemp = pIn; pIn = pOut; pOut = pTemp; Counter++; } Var--; } assert( Var == -1 ); // swap if it was moved an even number of times if ( !(Counter & 1) ) Extra_TruthCopy( pOut, pIn, nVarsAll ); } /**Function************************************************************* Synopsis [Shrinks the truth table according to the phase.] Description [The input and output truth tables are in pIn/pOut. The current number of variables is nVars. The total number of variables in nVarsAll. The last argument (Phase) contains shows what variables should remain.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) { unsigned * pTemp; int i, k, Var = 0, Counter = 0; for ( i = 0; i < nVarsAll; i++ ) if ( Phase & (1 << i) ) { for ( k = i-1; k >= Var; k-- ) { Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); pTemp = pIn; pIn = pOut; pOut = pTemp; Counter++; } Var++; } assert( Var == nVars ); // swap if it was moved an even number of times if ( !(Counter & 1) ) Extra_TruthCopy( pOut, pIn, nVarsAll ); } /**Function************************************************************* Synopsis [Returns 1 if TT depends on the given variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) { int nWords = Extra_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) ) return 1; return 0; case 1: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) ) return 1; return 0; case 2: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) ) return 1; return 0; case 3: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) ) return 1; return 0; case 4: for ( i = 0; i < nWords; i++ ) if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) ) return 1; return 0; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) if ( pTruth[i] != pTruth[Step+i] ) return 1; pTruth += 2*Step; } return 0; } } /**Function************************************************************* Synopsis [Returns the number of support vars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_TruthSupportSize( unsigned * pTruth, int nVars ) { int i, Counter = 0; for ( i = 0; i < nVars; i++ ) Counter += Extra_TruthVarInSupport( pTruth, nVars, i ); return Counter; } /**Function************************************************************* Synopsis [Returns support of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_TruthSupport( unsigned * pTruth, int nVars ) { int i, Support = 0; for ( i = 0; i < nVars; i++ ) if ( Extra_TruthVarInSupport( pTruth, nVars, i ) ) Support |= (1 << i); return Support; } /**Function************************************************************* Synopsis [Computes positive cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ) { int nWords = Extra_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) pTruth[i] = pTruth[Step+i]; pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Computes negative cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ) { int nWords = Extra_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) pTruth[Step+i] = pTruth[i]; pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Existentially quantifies the variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar ) { int nWords = Extra_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] |= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pTruth[i] |= pTruth[Step+i]; pTruth[Step+i] = pTruth[i]; } pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Existentially quantifies the variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar ) { int nWords = Extra_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] &= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pTruth[i] &= pTruth[Step+i]; pTruth[Step+i] = pTruth[i]; } pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Computes negative cofactor of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ) { int nWords = Extra_TruthWordNum( nVars ); int i, k, Step; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); return; case 1: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); return; case 2: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); return; case 3: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); return; case 4: for ( i = 0; i < nWords; i++ ) pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { pOut[i] = pCof0[i]; pOut[Step+i] = pCof1[Step+i]; } pOut += 2*Step; } return; } } /**Function************************************************************* Synopsis [Checks symmetry of two variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) { static unsigned uTemp0[16], uTemp1[16]; assert( nVars <= 9 ); // compute Cof01 Extra_TruthCopy( uTemp0, pTruth, nVars ); Extra_TruthCofactor0( uTemp0, nVars, iVar0 ); Extra_TruthCofactor1( uTemp0, nVars, iVar1 ); // compute Cof10 Extra_TruthCopy( uTemp1, pTruth, nVars ); Extra_TruthCofactor1( uTemp1, nVars, iVar0 ); Extra_TruthCofactor0( uTemp1, nVars, iVar1 ); // compare return Extra_TruthIsEqual( uTemp0, uTemp1, nVars ); } /**Function************************************************************* Synopsis [Checks antisymmetry of two variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) { static unsigned uTemp0[16], uTemp1[16]; assert( nVars <= 9 ); // compute Cof00 Extra_TruthCopy( uTemp0, pTruth, nVars ); Extra_TruthCofactor0( uTemp0, nVars, iVar0 ); Extra_TruthCofactor0( uTemp0, nVars, iVar1 ); // compute Cof11 Extra_TruthCopy( uTemp1, pTruth, nVars ); Extra_TruthCofactor1( uTemp1, nVars, iVar0 ); Extra_TruthCofactor1( uTemp1, nVars, iVar1 ); // compare return Extra_TruthIsEqual( uTemp0, uTemp1, nVars ); } /**Function************************************************************* Synopsis [Changes phase of the function w.r.t. one variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ) { int nWords = Extra_TruthWordNum( nVars ); int i, k, Step; unsigned Temp; assert( iVar < nVars ); switch ( iVar ) { case 0: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1); return; case 1: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2); return; case 2: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4); return; case 3: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8); return; case 4: for ( i = 0; i < nWords; i++ ) pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16); return; default: Step = (1 << (iVar - 5)); for ( k = 0; k < nWords; k += 2*Step ) { for ( i = 0; i < Step; i++ ) { Temp = pTruth[i]; pTruth[i] = pTruth[Step+i]; pTruth[Step+i] = Temp; } pTruth += 2*Step; } return; } } /**Function************************************************************* Synopsis [Computes minimum overlap in supports of cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ) { static unsigned uCofactor[16]; int i, ValueCur, ValueMin, VarMin; unsigned uSupp0, uSupp1; int nVars0, nVars1; assert( nVars <= 9 ); ValueMin = 32; VarMin = -1; for ( i = 0; i < nVars; i++ ) { // get negative cofactor Extra_TruthCopy( uCofactor, pTruth, nVars ); Extra_TruthCofactor0( uCofactor, nVars, i ); uSupp0 = Extra_TruthSupport( uCofactor, nVars ); nVars0 = Extra_WordCountOnes( uSupp0 ); //Extra_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" ); // get positive cofactor Extra_TruthCopy( uCofactor, pTruth, nVars ); Extra_TruthCofactor1( uCofactor, nVars, i ); uSupp1 = Extra_TruthSupport( uCofactor, nVars ); nVars1 = Extra_WordCountOnes( uSupp1 ); //Extra_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" ); // get the number of common vars ValueCur = Extra_WordCountOnes( uSupp0 & uSupp1 ); if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 ) { ValueMin = ValueCur; VarMin = i; } if ( ValueMin == 0 ) break; } if ( pVarMin ) *pVarMin = VarMin; return ValueMin; } /**Function************************************************************* Synopsis [Counts the number of 1's in each cofactor.] Description [The resulting numbers are stored in the array of shorts, whose length is 2*nVars. The number of 1's is counted in a different space than the original function. For example, if the function depends on k variables, the cofactors are assumed to depend on k-1 variables.] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ) { int nWords = Extra_TruthWordNum( nVars ); int i, k, Counter; memset( pStore, 0, sizeof(short) * 2 * nVars ); if ( nVars <= 5 ) { if ( nVars > 0 ) { pStore[2*0+0] = Extra_WordCountOnes( pTruth[0] & 0x55555555 ); pStore[2*0+1] = Extra_WordCountOnes( pTruth[0] & 0xAAAAAAAA ); } if ( nVars > 1 ) { pStore[2*1+0] = Extra_WordCountOnes( pTruth[0] & 0x33333333 ); pStore[2*1+1] = Extra_WordCountOnes( pTruth[0] & 0xCCCCCCCC ); } if ( nVars > 2 ) { pStore[2*2+0] = Extra_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); pStore[2*2+1] = Extra_WordCountOnes( pTruth[0] & 0xF0F0F0F0 ); } if ( nVars > 3 ) { pStore[2*3+0] = Extra_WordCountOnes( pTruth[0] & 0x00FF00FF ); pStore[2*3+1] = Extra_WordCountOnes( pTruth[0] & 0xFF00FF00 ); } if ( nVars > 4 ) { pStore[2*4+0] = Extra_WordCountOnes( pTruth[0] & 0x0000FFFF ); pStore[2*4+1] = Extra_WordCountOnes( pTruth[0] & 0xFFFF0000 ); } return; } // nVars >= 6 // count 1's for all other variables for ( k = 0; k < nWords; k++ ) { Counter = Extra_WordCountOnes( pTruth[k] ); for ( i = 5; i < nVars; i++ ) if ( k & (1 << (i-5)) ) pStore[2*i+1] += Counter; else pStore[2*i+0] += Counter; } // count 1's for the first five variables for ( k = 0; k < nWords/2; k++ ) { pStore[2*0+0] += Extra_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); pStore[2*0+1] += Extra_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) ); pStore[2*1+0] += Extra_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); pStore[2*1+1] += Extra_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) ); pStore[2*2+0] += Extra_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); pStore[2*2+1] += Extra_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) ); pStore[2*3+0] += Extra_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); pStore[2*3+1] += Extra_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) ); pStore[2*4+0] += Extra_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); pStore[2*4+1] += Extra_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) ); pTruth += 2; } } /**Function************************************************************* Synopsis [Canonicize the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_TruthHash( unsigned * pIn, int nWords ) { // The 1,024 smallest prime numbers used to compute the hash value // http://www.math.utah.edu/~alfeld/math/primelist.html static int HashPrimes[1024] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161 }; int i; unsigned uHashKey; assert( nWords <= 1024 ); uHashKey = 0; for ( i = 0; i < nWords; i++ ) uHashKey ^= HashPrimes[i] * pIn[i]; return uHashKey; } /**Function************************************************************* Synopsis [Canonicize the truth table.] Description [Returns the phase. ] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ) { unsigned * pIn = pInOut, * pOut = pAux, * pTemp; int nWords = Extra_TruthWordNum( nVars ); int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit; unsigned uCanonPhase; // canonicize output uCanonPhase = 0; nOnes = Extra_TruthCountOnes(pIn, nVars); if ( (nOnes > nWords * 16) || ((nOnes == nWords * 16) && (pIn[0] & 1)) ) { uCanonPhase |= (1 << nVars); Extra_TruthNot( pIn, pIn, nVars ); } // collect the minterm counts Extra_TruthCountOnesInCofs( pIn, nVars, pStore ); // canonicize phase for ( i = 0; i < nVars; i++ ) { if ( pStore[2*i+0] <= pStore[2*i+1] ) continue; uCanonPhase |= (1 << i); Temp = pStore[2*i+0]; pStore[2*i+0] = pStore[2*i+1]; pStore[2*i+1] = Temp; Extra_TruthChangePhase( pIn, nVars, i ); } // Extra_PrintHexadecimal( stdout, pIn, nVars ); // printf( "\n" ); // permute Counter = 0; do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[2*i] <= pStore[2*(i+1)] ) continue; Counter++; fChange = 1; Temp = pCanonPerm[i]; pCanonPerm[i] = pCanonPerm[i+1]; pCanonPerm[i+1] = Temp; Temp = pStore[2*i]; pStore[2*i] = pStore[2*(i+1)]; pStore[2*(i+1)] = Temp; Temp = pStore[2*i+1]; pStore[2*i+1] = pStore[2*(i+1)+1]; pStore[2*(i+1)+1] = Temp; Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; } } while ( fChange ); /* Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " ); for ( i = 0; i < nVars; i++ ) printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] ); printf( " C = %d\n", Counter ); Extra_PrintHexadecimal( stdout, pIn, nVars ); printf( "\n" ); */ /* // process symmetric variable groups uSymms = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric continue; if ( pStore[2*i] != pStore[2*i+1] ) continue; if ( Extra_TruthVarsSymm( pIn, nVars, i, i+1 ) ) continue; if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) ) Extra_TruthChangePhase( pIn, nVars, i+1 ); } */ /* // process symmetric variable groups uSymms = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric continue; // i and i+1 can be symmetric // find the end of this group for ( k = i+1; k < nVars; k++ ) if ( pStore[2*i] != pStore[2*k] ) break; Limit = k; assert( i < Limit-1 ); // go through the variables in this group for ( j = i + 1; j < Limit; j++ ) { // check symmetry if ( Extra_TruthVarsSymm( pIn, nVars, i, j ) ) { uSymms |= (1 << j); continue; } // they are phase-unknown if ( pStore[2*i] == pStore[2*i+1] ) { if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, j ) ) { Extra_TruthChangePhase( pIn, nVars, j ); uCanonPhase ^= (1 << j); uSymms |= (1 << j); continue; } } // they are not symmetric - move j as far as it goes in the group for ( k = j; k < Limit-1; k++ ) { Counter++; Temp = pCanonPerm[k]; pCanonPerm[k] = pCanonPerm[k+1]; pCanonPerm[k+1] = Temp; assert( pStore[2*k] == pStore[2*(k+1)] ); Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, k ); pTemp = pIn; pIn = pOut; pOut = pTemp; } Limit--; j--; } i = Limit - 1; } */ // swap if it was moved an even number of times if ( Counter & 1 ) Extra_TruthCopy( pOut, pIn, nVars ); return uCanonPhase; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraUtilUtil.c000066400000000000000000000226671300674244400251120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraUtilUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [Old SIS utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilUtil.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include "extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define EXTRA_RLIMIT_DATA_DEFAULT 67108864 // assume 64MB by default /* File : getopt.c * Author : Henry Spencer, University of Toronto * Updated: 28 April 1984 * * Changes: (R Rudell) * changed index() to strchr(); * added getopt_reset() to reset the getopt argument parsing * * Purpose: get option letter from argv. */ const char * globalUtilOptarg; // Global argument pointer (util_optarg) int globalUtilOptind = 0; // Global argv index (util_optind) static const char *pScanStr; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [getSoftDataLimit()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_GetSoftDataLimit() { return EXTRA_RLIMIT_DATA_DEFAULT; } /**Function************************************************************* Synopsis [util_getopt_reset()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_UtilGetoptReset() { globalUtilOptarg = 0; globalUtilOptind = 0; pScanStr = 0; } /**Function************************************************************* Synopsis [util_getopt()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_UtilGetopt( int argc, char *argv[], const char *optstring ) { register int c; register const char *place; globalUtilOptarg = NULL; if (pScanStr == NULL || *pScanStr == '\0') { if (globalUtilOptind == 0) globalUtilOptind++; if (globalUtilOptind >= argc) return EOF; place = argv[globalUtilOptind]; if (place[0] != '-' || place[1] == '\0') return EOF; globalUtilOptind++; if (place[1] == '-' && place[2] == '\0') return EOF; pScanStr = place+1; } c = *pScanStr++; place = strchr(optstring, c); if (place == NULL || c == ':') { (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c); return '?'; } if (*++place == ':') { if (*pScanStr != '\0') { globalUtilOptarg = pScanStr; pScanStr = NULL; } else { if (globalUtilOptind >= argc) { (void) fprintf(stderr, "%s: %c requires an argument\n", argv[0], c); return '?'; } globalUtilOptarg = argv[globalUtilOptind]; globalUtilOptind++; } } return c; } /**Function************************************************************* Synopsis [util_print_time()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_UtilPrintTime( long t ) { static char s[40]; (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10); return s; } /**Function************************************************************* Synopsis [Extra_UtilStrsav()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_UtilStrsav( const char *s ) { if(s == NULL) { /* added 7/95, for robustness */ return NULL; } else { return strcpy(ABC_ALLOC(char, strlen(s)+1), s); } } /**Function************************************************************* Synopsis [util_tilde_expand()] Description [The code contributed by Niklas Sorensson.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_UtilTildeExpand( char *fname ) { return Extra_UtilStrsav( fname ); /* int n_tildes = 0; const char* home; char* expanded; int length; int i, j, k; for (i = 0; i < (int)strlen(fname); i++) if (fname[i] == '~') n_tildes++; home = getenv("HOME"); length = n_tildes * strlen(home) + strlen(fname); expanded = ABC_ALLOC(char, length + 1); j = 0; for (i = 0; i < (int)strlen(fname); i++){ if (fname[i] == '~'){ for (k = 0; k < (int)strlen(home); k++) expanded[j++] = home[k]; }else expanded[j++] = fname[i]; } expanded[j] = '\0'; return expanded; */ } /**Function************************************************************* Synopsis [check_file()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_UtilCheckFile(char *filename, const char *mode) { FILE *fp; int got_file; if (strcmp(mode, "x") == 0) { mode = "r"; } fp = fopen(filename, mode); got_file = (fp != 0); if (fp != 0) { (void) fclose(fp); } return got_file; } /**Function************************************************************* Synopsis [util_file_search()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_UtilFileSearch(char *file, char *path, char *mode) //char *file; // file we're looking for //char *path; // search path, colon separated //char *mode; // "r", "w", or "x" { int quit; char *buffer, *filename, *save_path, *cp; if (path == 0 || strcmp(path, "") == 0) { path = "."; /* just look in the current directory */ } save_path = path = Extra_UtilStrsav(path); quit = 0; do { cp = strchr(path, ':'); if (cp != 0) { *cp = '\0'; } else { quit = 1; } /* cons up the filename out of the path and file name */ if (strcmp(path, ".") == 0) { buffer = Extra_UtilStrsav(file); } else { buffer = ABC_ALLOC(char, strlen(path) + strlen(file) + 4); (void) sprintf(buffer, "%s/%s", path, file); } filename = Extra_UtilTildeExpand(buffer); ABC_FREE(buffer); /* see if we can access it */ if (Extra_UtilCheckFile(filename, mode)) { ABC_FREE(save_path); return filename; } ABC_FREE(filename); path = ++cp; } while (! quit); ABC_FREE(save_path); return 0; } /**Function************************************************************* Synopsis [MMout_of_memory()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* MMout_of_memory -- out of memory for lazy people, flush and exit */ void Extra_UtilMMout_Of_Memory( long size ) { (void) fflush(stdout); (void) fprintf(stderr, "\nout of memory allocating %u bytes\n", (unsigned) size); assert( 0 ); exit(1); } /**Function************************************************************* Synopsis [MMoutOfMemory()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void (*Extra_UtilMMoutOfMemory)( long size ) = (void (*)( long size ))Extra_UtilMMout_Of_Memory; /**Function************************************************************* Synopsis [util_cpu_time()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ abctime Extra_CpuTime() { return Abc_Clock(); } /**Function************************************************************* Synopsis [util_cpu_time()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #if defined(NT) || defined(NT64) || defined(WIN32) double Extra_CpuTimeDouble() { return 1.0*Abc_Clock()/CLOCKS_PER_SEC; } #else ABC_NAMESPACE_IMPL_END #include #include #include ABC_NAMESPACE_IMPL_START double Extra_CpuTimeDouble() { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } #endif /**Function************************************************************* Synopsis [Testing memory leaks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_MemTest() { // ABC_ALLOC( char, 1002 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/extraZddTrunc.c000066400000000000000000000263741300674244400250730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [extraZddTrunc.c] PackageName [extra] Synopsis [Procedure to truncate a ZDD using variable probabilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - September 1, 2003.] Revision [$Id: extraZddTrunc.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/st/st.h" #include "bdd/cudd/cuddInt.h" #ifdef _WIN32 #define inline __inline // compatible with MS VS 6.0 #endif ABC_NAMESPACE_IMPL_START #define TEST_VAR_MAX 10 #define TEST_SET_MAX 10 /*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/ /**AutomaticStart*************************************************************/ /*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/ // dynamic vector of intergers typedef struct Vec_Int_t_ Vec_Int_t; struct Vec_Int_t_ { int nCap; int nSize; int * pArray; }; static inline Vec_Int_t * Vec_IntAlloc( int nCap ) { Vec_Int_t * p; p = ABC_ALLOC( Vec_Int_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL; return p; } static inline void Vec_IntFree( Vec_Int_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } static inline int * Vec_IntReleaseArray( Vec_Int_t * p ) { int * pArray = p->pArray; p->nCap = 0; p->nSize = 0; p->pArray = NULL; return pArray; } static inline int Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i] += Addition; } static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); assert( p->pArray ); p->nCap = nCapMin; } static inline int Vec_IntPop( Vec_Int_t * p ) { assert( p->nSize > 0 ); return p->pArray[--p->nSize]; } static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_IntGrow( p, 16 ); else Vec_IntGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } static inline void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 ) { int i; for ( i = 0; i < vVec2->nSize; i++ ) Vec_IntPush( vVec1, vVec2->pArray[i] ); } /**AutomaticEnd***************************************************************/ /*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/ /**Function******************************************************************** Synopsis [Compute the set of subsets whose probability is more than ProbLimit.] Description [The resulting array has the following form: The first integer entry is the number of resulting subsets. The following integer entries in the array contain as many subsets. Each subset is an array of integers followed by -1. See how subsets are printed in the included test procedure below.] SideEffects [] SeeAlso [] ******************************************************************************/ void Extra_zddTruncate_rec( DdManager * dd, DdNode * zFunc, // zFunc is the ZDD to be truncated double * pVarProbs, // pVarProbs is probabilities of each variable (should have at least dd->sizeZ entries) double ProbLimit, // ProbLimit is the limit on the probabilities (only those more than this will be collected) double ProbThis, // current path probability Vec_Int_t * vSubset, // current subset under construction Vec_Int_t * vResult ) // resulting subsets to be returned to the user { // quit if probability of the path is less then the limit if ( ProbThis < ProbLimit ) return; // quit if there is no subsets if ( zFunc == Cudd_ReadZero(dd) ) return; // quit and save a new subset if there is one if ( zFunc == Cudd_ReadOne(dd) ) { Vec_IntAddToEntry( vResult, 0, 1 ); Vec_IntAppend( vResult, vSubset ); Vec_IntPush( vResult, -1 ); return; } // call recursively for the set without the given variable Extra_zddTruncate_rec( dd, cuddE(zFunc), pVarProbs, ProbLimit, ProbThis, vSubset, vResult ); // call recursively for the set with the given variable Vec_IntPush( vSubset, Cudd_NodeReadIndex(zFunc) ); Extra_zddTruncate_rec( dd, cuddT(zFunc), pVarProbs, ProbLimit, ProbThis * pVarProbs[Cudd_NodeReadIndex(zFunc)], vSubset, vResult ); Vec_IntPop( vSubset ); } int * Extra_zddTruncate( DdManager * dd, DdNode * zFunc, // zFunc is the ZDD to be truncated double * pVarProbs, // pVarProbs is probabilities of each variable (should have at least dd->sizeZ entries) double ProbLimit ) // ProbLimit is the limit on the probabilities (only those more than this will be collected) { Vec_Int_t * vSubset, * vResult; int i, sizeZ = Cudd_ReadZddSize(dd); int * pResult; // check that probabilities are reasonable assert( ProbLimit > 0 && ProbLimit <= 1 ); for ( i = 0; i < sizeZ; i++ ) assert( pVarProbs[i] > 0 && pVarProbs[i] <= 1 ); // enumerate assignments satisfying the probability limit vSubset = Vec_IntAlloc( sizeZ ); vResult = Vec_IntAlloc( 10 * sizeZ ); Vec_IntPush( vResult, 0 ); Extra_zddTruncate_rec( dd, zFunc, pVarProbs, ProbLimit, 1, vSubset, vResult ); Vec_IntFree( vSubset ); pResult = Vec_IntReleaseArray( vResult ); Vec_IntFree( vResult ); return pResult; } // end of Extra_zddTruncate /**Function************************************************************* Synopsis [Creates the combination composed of a single ZDD variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_zddVariable( DdManager * dd, int iVar ) { DdNode * zRes; do { dd->reordered = 0; zRes = cuddZddGetNode( dd, iVar, Cudd_ReadOne(dd), Cudd_ReadZero(dd) ); } while (dd->reordered == 1); return zRes; } /**Function******************************************************************** Synopsis [Creates ZDD representing a given set of subsets.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * Extra_zddCreateSubsets( DdManager * dd, int pSubsets[][TEST_VAR_MAX+1], int nSubsets ) { int i, k; DdNode * zOne, * zVar, * zRes, * zTemp; zRes = Cudd_ReadZero(dd); Cudd_Ref( zRes ); for ( i = 0; i < nSubsets; i++ ) { zOne = Cudd_ReadOne(dd); Cudd_Ref( zOne ); for ( k = 0; pSubsets[i][k] != -1; k++ ) { assert( pSubsets[i][k] < TEST_VAR_MAX ); zVar = Extra_zddVariable( dd, pSubsets[i][k] ); zOne = Cudd_zddUnateProduct( dd, zTemp = zOne, zVar ); Cudd_Ref( zOne ); Cudd_RecursiveDerefZdd( dd, zTemp ); } zRes = Cudd_zddUnion( dd, zRes, zOne ); Cudd_Ref( zRes ); Cudd_RecursiveDerefZdd( dd, zOne ); } Cudd_Deref( zRes ); return zRes; } /**Function******************************************************************** Synopsis [Prints a set of subsets represented using as an array.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Extra_zddPrintSubsets( int * pSubsets ) { int i, k, Counter = 0; printf( "The set contains %d subsets:\n", pSubsets[0] ); for ( i = k = 0; i < pSubsets[0]; i++ ) { printf( "Subset %3d : {", Counter ); for ( k++; pSubsets[k] != -1; k++ ) printf( " %d", pSubsets[k] ); printf( " }\n" ); Counter++; } } /**Function******************************************************************** Synopsis [Testbench for the above truncation procedure.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Extra_zddTruncateTest() { // input data int nSubsets = 5; int pSubsets[TEST_SET_MAX][TEST_VAR_MAX+1] = { {0, 3, 5, -1}, {1, 2, 3, 6, 9, -1}, {1, 5, 7, 8, -1}, {2, 4, -1}, {0, 5, 6, 9, -1} }; // varible probabilities double pVarProbs[TEST_VAR_MAX] = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 }; double ProbLimit = 0.001; // output data int * pOutput; // start the manager and create ZDD representing the input subsets DdManager * dd = Cudd_Init( 0, TEST_VAR_MAX, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS , 0 ); DdNode * zFunc = Extra_zddCreateSubsets( dd, pSubsets, nSubsets ); Cudd_Ref( zFunc ); assert( nSubsets <= TEST_SET_MAX ); // print the input ZDD printf( "The initial ZDD representing %d subsets:\n", nSubsets ); Cudd_zddPrintMinterm( dd, zFunc ); // compute the result of truncation pOutput = Extra_zddTruncate( dd, zFunc, pVarProbs, ProbLimit ); // print the resulting ZDD printf( "The resulting ZDD representing %d subsets:\n", pOutput[0] ); // print the resulting subsets Extra_zddPrintSubsets( pOutput ); // cleanup ABC_FREE( pOutput ); Cudd_RecursiveDerefZdd( dd, zFunc ); Cudd_Quit( dd ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/extra/module.make000066400000000000000000000007561300674244400242460ustar00rootroot00000000000000SRC += src/misc/extra/extraUtilBitMatrix.c \ src/misc/extra/extraUtilCanon.c \ src/misc/extra/extraUtilCube.c \ src/misc/extra/extraUtilDsd.c \ src/misc/extra/extraUtilEnum.c \ src/misc/extra/extraUtilFile.c \ src/misc/extra/extraUtilMemory.c \ src/misc/extra/extraUtilMisc.c \ src/misc/extra/extraUtilPerm.c \ src/misc/extra/extraUtilProgress.c \ src/misc/extra/extraUtilReader.c \ src/misc/extra/extraUtilSupp.c \ src/misc/extra/extraUtilTruth.c \ src/misc/extra/extraUtilUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/hash/000077500000000000000000000000001300674244400217125ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/hash/hash.h000066400000000000000000000042461300674244400230140ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hash.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hash map.] Synopsis [External declarations.] Author [Aaron P. Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 16, 2005.] Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] ***********************************************************************/ #ifndef ABC__misc__hash__hash_h #define ABC__misc__hash__hash_h #ifdef _WIN32 #define inline __inline // compatible with MS VS 6.0 #endif //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/util/abc_global.h" #include "hashInt.h" #include "hashFlt.h" #include "hashPtr.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// int Hash_DefaultHashFunc(int key, int nBins) { return Abc_AbsInt( ( (key+11)*(key)*7+3 ) % nBins ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/hash/hashFlt.h000066400000000000000000000201461300674244400234570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hashFlt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hash maps.] Synopsis [Hash maps.] Author [Aaron P. Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 16, 2006.] Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] ***********************************************************************/ #ifndef ABC__misc__hash__hashFlt_h #define ABC__misc__hash__hashFlt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "misc/extra/extra.h" ABC_NAMESPACE_HEADER_START extern int Hash_DefaultHashFunc(int key, int nBins); //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Hash_Flt_t_ Hash_Flt_t; typedef struct Hash_Flt_Entry_t_ Hash_Flt_Entry_t; struct Hash_Flt_Entry_t_ { int key; float data; struct Hash_Flt_Entry_t_ * pNext; }; struct Hash_Flt_t_ { int nSize; int nBins; int (* fHash)(int key, int nBins); Hash_Flt_Entry_t ** pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Hash_FltForEachEntry( pHash, pEntry, bin) \ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ if (pEntry) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a hash map with the given number of bins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hash_Flt_t * Hash_FltAlloc( int nBins ) { Hash_Flt_t * p; int i; assert(nBins > 0); p = ABC_ALLOC( Hash_Flt_t, 1); p->nBins = nBins; p->fHash = Hash_DefaultHashFunc; p->nSize = 0; p->pArray = ABC_ALLOC( Hash_Flt_Entry_t *, nBins ); for(i=0; ipArray[i] = NULL; return p; } /**Function************************************************************* Synopsis [Returns 1 if a key already exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hash_FltExists( Hash_Flt_t *p, int key ) { int bin; Hash_Flt_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) { return 1; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } return 0; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key and writes value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_FltWriteEntry( Hash_Flt_t *p, int key, float data ) { int bin; Hash_Flt_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) { pEntry->data = data; return; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Flt_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = data; return; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key.] Description [fCreate specifies whether new entries should be created.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Hash_FltEntry( Hash_Flt_t *p, int key, int fCreate ) { int bin; Hash_Flt_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) return pEntry->data; pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist if (fCreate) { // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Flt_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = 0.0; return pEntry->data; } return 0.0; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key and returns the pointer to it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float* Hash_FltEntryPtr( Hash_Flt_t *p, int key ) { int bin; Hash_Flt_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) return &(pEntry->data); pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Flt_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = 0.0; return &(pEntry->data); } /**Function************************************************************* Synopsis [Deletes an entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_FltRemove( Hash_Flt_t *p, int key ) { int bin; Hash_Flt_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) { p->nSize--; *pLast = pEntry->pNext; ABC_FREE( pEntry ); return; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // could not find key return; } /**Function************************************************************* Synopsis [Frees the hash.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_FltFree( Hash_Flt_t *p ) { int bin; Hash_Flt_Entry_t *pEntry, *pTemp; // free bins for(bin = 0; bin < p->nBins; bin++) { pEntry = p->pArray[bin]; while(pEntry) { pTemp = pEntry; pEntry = pEntry->pNext; ABC_FREE( pTemp ); } } // free hash ABC_FREE( p->pArray ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/hash/hashGen.h000066400000000000000000000220621300674244400234420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecGen.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hash maps.] Synopsis [Hash maps.] Author [Aaron P. Hurst, Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Jan 26, 2011.] Revision [$Id: vecGen.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] ***********************************************************************/ #ifndef ABC__misc__hash__hashGen_h #define ABC__misc__hash__hashGen_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "misc/extra/extra.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Hash_Gen_t_ Hash_Gen_t; typedef struct Hash_Gen_Entry_t_ Hash_Gen_Entry_t; struct Hash_Gen_Entry_t_ { char * key; void * data; struct Hash_Gen_Entry_t_ * pNext; }; typedef int (*Hash_GenHashFunction_t)(void* key, int nBins); typedef int (*Hash_GenCompFunction_t)(void* key, void* data); struct Hash_Gen_t_ { int nSize; int nBins; Hash_GenHashFunction_t fHash; Hash_GenCompFunction_t fComp; int fFreeKey; Hash_Gen_Entry_t ** pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Hash_GenForEachEntry( pHash, pEntry, bin ) \ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ if (pEntry) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Default hash function for strings.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Hash_DefaultHashFuncStr( void * key, int nBins ) { const char* p = (const char*)key; int h=0; for( ; *p ; ++p ) h += h*5 + *p; return (unsigned)h % nBins; } static int Hash_DefaultCmpFuncStr( void * key1, void * key2 ) { return strcmp((const char*)key1, (const char*) key2); } /**Function************************************************************* Synopsis [Default hash function for (long) integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Hash_DefaultHashFuncInt( void * key, int nBins ) { return (long)key % nBins; } /**Function************************************************************* Synopsis [Default comparison function for (long) integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Hash_DefaultCmpFuncInt( void * key1, void* key2 ) { return (long)key1 - (long)key2; } /**Function************************************************************* Synopsis [Allocates a hash map with the given number of bins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hash_Gen_t * Hash_GenAlloc( int nBins, int (*Hash_FuncHash)(void *, int), int (*Hash_FuncComp)(void *, void *), int fFreeKey) { Hash_Gen_t * p; assert(nBins > 0); p = ABC_CALLOC( Hash_Gen_t, 1 ); p->nBins = nBins; p->fHash = Hash_FuncHash? Hash_FuncHash : (int (*)(void *, int))Hash_DefaultHashFuncStr; p->fComp = Hash_FuncComp? Hash_FuncComp : (int (*)(void *, void *))Hash_DefaultCmpFuncStr; p->fFreeKey = fFreeKey; p->nSize = 0; p->pArray = ABC_CALLOC( Hash_Gen_Entry_t *, nBins ); return p; } /**Function************************************************************* Synopsis [Returns 1 if a key already exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hash_GenExists( Hash_Gen_t *p, void * key ) { int bin; Hash_Gen_Entry_t *pEntry; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pEntry = p->pArray[bin]; while(pEntry) { if ( !p->fComp(pEntry->key,key) ) { return 1; } pEntry = pEntry->pNext; } return 0; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key and writes value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_GenWriteEntry( Hash_Gen_t *p, void * key, void * data ) { int bin; Hash_Gen_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if ( !p->fComp(pEntry->key,key) ) { pEntry->data = data; return; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Gen_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = (char *)key; pEntry->data = data; return; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key.] Description [fCreate specifies whether a new entry should be created.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hash_Gen_Entry_t * Hash_GenEntry( Hash_Gen_t *p, void * key, int fCreate ) { int bin; Hash_Gen_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if ( !p->fComp(pEntry->key,key) ) return pEntry; pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist if (fCreate) { // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Gen_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = (char *)key; pEntry->data = NULL; return pEntry; } return NULL; } /**Function************************************************************* Synopsis [Deletes an entry.] Description [Returns data, if there was any.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void* Hash_GenRemove( Hash_Gen_t *p, void * key ) { int bin; void * data; Hash_Gen_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if ( !p->fComp(pEntry->key,key) ) { p->nSize--; data = pEntry->data; *pLast = pEntry->pNext; if (p->fFreeKey) ABC_FREE(pEntry->key); ABC_FREE(pEntry); return data; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // could not find key return NULL; } /**Function************************************************************* Synopsis [Frees the hash.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_GenFree( Hash_Gen_t *p ) { int bin; Hash_Gen_Entry_t *pEntry, *pTemp; // free bins for(bin = 0; bin < p->nBins; bin++) { pEntry = p->pArray[bin]; while(pEntry) { pTemp = pEntry; if( p->fFreeKey ) ABC_FREE(pTemp->key); pEntry = pEntry->pNext; ABC_FREE( pTemp ); } } // free hash ABC_FREE( p->pArray ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/hash/hashInt.h000066400000000000000000000165241300674244400234710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hashInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hash maps.] Synopsis [Hash maps.] Author [Aaron P. Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 16, 2006.] Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] ***********************************************************************/ #ifndef ABC__misc__hash__hashInt_h #define ABC__misc__hash__hashInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "misc/extra/extra.h" ABC_NAMESPACE_HEADER_START extern int Hash_DefaultHashFunc(int key, int nBins); //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Hash_Int_t_ Hash_Int_t; typedef struct Hash_Int_Entry_t_ Hash_Int_Entry_t; struct Hash_Int_Entry_t_ { int key; int data; struct Hash_Int_Entry_t_ * pNext; }; struct Hash_Int_t_ { int nSize; int nBins; int (* fHash)(int key, int nBins); Hash_Int_Entry_t ** pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Hash_IntForEachEntry( pHash, pEntry, bin) \ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ if (pEntry) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a hash map with the given number of bins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hash_Int_t * Hash_IntAlloc( int nBins ) { Hash_Int_t * p; int i; assert(nBins > 0); p = ABC_ALLOC( Hash_Int_t, 1); p->nBins = nBins; p->fHash = Hash_DefaultHashFunc; p->nSize = 0; p->pArray = ABC_ALLOC( Hash_Int_Entry_t *, nBins+1 ); for(i=0; ipArray[i] = NULL; return p; } /**Function************************************************************* Synopsis [Returns 1 if a key already exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hash_IntExists( Hash_Int_t *p, int key) { int bin; Hash_Int_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) { return 1; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } return 0; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key and writes value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_IntWriteEntry( Hash_Int_t *p, int key, int data ) { int bin; Hash_Int_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) { pEntry->data = data; return; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Int_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = data; return; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key.] Description [fCreate specifies whether new entries will be created.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hash_IntEntry( Hash_Int_t *p, int key, int fCreate ) { int bin; Hash_Int_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) return pEntry->data; pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist if (fCreate) { // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Int_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = 0; return pEntry->data; } return 0; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key and returns the pointer to it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int* Hash_IntEntryPtr( Hash_Int_t *p, int key ) { int bin; Hash_Int_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) return &(pEntry->data); pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Int_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = 0; return &(pEntry->data); } /**Function************************************************************* Synopsis [Frees the hash.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_IntFree( Hash_Int_t *p ) { int bin; Hash_Int_Entry_t *pEntry, *pTemp; // free bins for(bin = 0; bin < p->nBins; bin++) { pEntry = p->pArray[bin]; while(pEntry) { pTemp = pEntry; pEntry = pEntry->pNext; ABC_FREE( pTemp ); } } // free hash ABC_FREE( p->pArray ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/hash/hashPtr.h000066400000000000000000000201431300674244400234740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hashFlt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hash maps.] Synopsis [Hash maps.] Author [Aaron P. Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 16, 2006.] Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] ***********************************************************************/ #ifndef ABC__misc__hash__hashPtr_h #define ABC__misc__hash__hashPtr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "misc/extra/extra.h" ABC_NAMESPACE_HEADER_START extern int Hash_DefaultHashFunc(int key, int nBins); //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Hash_Ptr_t_ Hash_Ptr_t; typedef struct Hash_Ptr_Entry_t_ Hash_Ptr_Entry_t; struct Hash_Ptr_Entry_t_ { int key; void * data; struct Hash_Ptr_Entry_t_ * pNext; }; struct Hash_Ptr_t_ { int nSize; int nBins; int (* fHash)(int key, int nBins); Hash_Ptr_Entry_t ** pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Hash_PtrForEachEntry( pHash, pEntry, bin ) \ for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ if (pEntry) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a hash map with the given number of bins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hash_Ptr_t * Hash_PtrAlloc( int nBins ) { Hash_Ptr_t * p; int i; assert(nBins > 0); p = ABC_ALLOC( Hash_Ptr_t, 1); p->nBins = nBins; p->fHash = Hash_DefaultHashFunc; p->nSize = 0; p->pArray = ABC_ALLOC( Hash_Ptr_Entry_t *, nBins ); for(i=0; ipArray[i] = NULL; return p; } /**Function************************************************************* Synopsis [Returns 1 if a key already exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hash_PtrExists( Hash_Ptr_t *p, int key ) { int bin; Hash_Ptr_Entry_t *pEntry; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) { return 1; } pEntry = pEntry->pNext; } return 0; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key and writes value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_PtrWriteEntry( Hash_Ptr_t *p, int key, void * data ) { int bin; Hash_Ptr_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) { pEntry->data = data; return; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Ptr_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = data; return; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key.] Description [fCreate specifies whether a new entry should be created.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Hash_PtrEntry( Hash_Ptr_t *p, int key, int fCreate ) { int bin; Hash_Ptr_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) return pEntry->data; pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist if (fCreate) { // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Ptr_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = NULL; return pEntry->data; } return NULL; } /**Function************************************************************* Synopsis [Finds or creates an entry with a key and returns the pointer to it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void** Hash_PtrEntryPtr( Hash_Ptr_t *p, int key ) { int bin; Hash_Ptr_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) return &(pEntry->data); pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // this key does not currently exist // create a new entry and add to bin p->nSize++; (*pLast) = pEntry = ABC_ALLOC( Hash_Ptr_Entry_t, 1 ); pEntry->pNext = NULL; pEntry->key = key; pEntry->data = NULL; return &(pEntry->data); } /**Function************************************************************* Synopsis [Deletes an entry.] Description [Returns data, if there was any.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void* Hash_PtrRemove( Hash_Ptr_t *p, int key ) { int bin; void * data; Hash_Ptr_Entry_t *pEntry, **pLast; // find the bin where this key would live bin = (*(p->fHash))(key, p->nBins); // search for key pLast = &(p->pArray[bin]); pEntry = p->pArray[bin]; while(pEntry) { if (pEntry->key == key) { p->nSize--; data = pEntry->data; *pLast = pEntry->pNext; return data; } pLast = &(pEntry->pNext); pEntry = pEntry->pNext; } // could not find key return NULL; } /**Function************************************************************* Synopsis [Frees the hash.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_PtrFree( Hash_Ptr_t *p ) { int bin; Hash_Ptr_Entry_t *pEntry, *pTemp; // free bins for(bin = 0; bin < p->nBins; bin++) { pEntry = p->pArray[bin]; while(pEntry) { pTemp = pEntry; pEntry = pEntry->pNext; ABC_FREE( pTemp ); } } // free hash ABC_FREE( p->pArray ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/hash/module.make000066400000000000000000000000101300674244400240250ustar00rootroot00000000000000SRC += berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mem/000077500000000000000000000000001300674244400215455ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mem/mem.c000066400000000000000000000420451300674244400224740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [esopMem.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Cover manipulation package.] Synopsis [Memory managers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: esopMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "mem.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Mem_Fixed_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 Mem_Flex_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 Mem_Step_t_ { int nMems; // the number of fixed memory managers employed Mem_Fixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc int nMapSize; // the size of the memory array Mem_Fixed_t ** pMap; // maps the number of bytes into its memory manager int nLargeChunksAlloc; // the maximum number of large memory chunks int nLargeChunks; // the current number of large memory chunks void ** pLargeChunks; // the allocated large memory chunks }; //////////////////////////////////////////////////////////////////////// /// 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 [] ***********************************************************************/ Mem_Fixed_t * Mem_FixedStart( int nEntrySize ) { Mem_Fixed_t * p; p = ABC_ALLOC( Mem_Fixed_t, 1 ); memset( p, 0, sizeof(Mem_Fixed_t) ); p->nEntrySize = nEntrySize; p->nEntriesAlloc = 0; p->nEntriesUsed = 0; p->pEntriesFree = NULL; if ( nEntrySize * (1 << 10) < (1<<16) ) p->nChunkSize = (1 << 10); else p->nChunkSize = (1<<16) / nEntrySize; 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 Mem_FixedStop( Mem_Fixed_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 * Mem_FixedEntryFetch( Mem_Fixed_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 Mem_FixedEntryRecycle( Mem_Fixed_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 Mem_FixedRestart( Mem_Fixed_t * p ) { int i; char * pTemp; // 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 Mem_FixedReadMemUsage( Mem_Fixed_t * p ) { return p->nMemoryAlloc; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_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 [] ***********************************************************************/ Mem_Flex_t * Mem_FlexStart() { Mem_Flex_t * p; p = ABC_ALLOC( Mem_Flex_t, 1 ); memset( p, 0, sizeof(Mem_Flex_t) ); p->nEntriesUsed = 0; p->pCurrent = NULL; p->pEnd = NULL; p->nChunkSize = (1 << 12); 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 Mem_FlexStop( Mem_Flex_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 * Mem_FlexEntryFetch( Mem_Flex_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 Mem_FlexRestart( Mem_Flex_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 Mem_FlexReadMemUsage( Mem_Flex_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 [] ***********************************************************************/ Mem_Step_t * Mem_StepStart( int nSteps ) { Mem_Step_t * p; int i, k; p = ABC_ALLOC( Mem_Step_t, 1 ); memset( p, 0, sizeof(Mem_Step_t) ); p->nMems = nSteps; // start the fixed memory managers p->pMems = ABC_ALLOC( Mem_Fixed_t *, p->nMems ); for ( i = 0; i < p->nMems; i++ ) p->pMems[i] = Mem_FixedStart( (8<nMapSize = (4<nMems); p->pMap = ABC_ALLOC( Mem_Fixed_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 ); return p; } /**Function************************************************************* Synopsis [Stops the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mem_StepStop( Mem_Step_t * p, int fVerbose ) { int i; for ( i = 0; i < p->nMems; i++ ) Mem_FixedStop( p->pMems[i], fVerbose ); if ( p->pLargeChunks ) { for ( i = 0; i < p->nLargeChunks; i++ ) ABC_FREE( p->pLargeChunks[i] ); ABC_FREE( p->pLargeChunks ); } ABC_FREE( p->pMems ); ABC_FREE( p->pMap ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ) { if ( nBytes == 0 ) return NULL; if ( nBytes > p->nMapSize ) { // printf( "Allocating %d bytes.\n", nBytes ); // return ABC_ALLOC( char, nBytes ); if ( p->nLargeChunks == p->nLargeChunksAlloc ) { if ( p->nLargeChunksAlloc == 0 ) p->nLargeChunksAlloc = 32; p->nLargeChunksAlloc *= 2; p->pLargeChunks = (void **)ABC_REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); } p->pLargeChunks[ p->nLargeChunks++ ] = ABC_ALLOC( char, nBytes ); return (char *)p->pLargeChunks[ p->nLargeChunks - 1 ]; } return Mem_FixedEntryFetch( p->pMap[nBytes] ); } /**Function************************************************************* Synopsis [Recycles the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ) { if ( nBytes == 0 ) return; if ( nBytes > p->nMapSize ) { // ABC_FREE( pEntry ); return; } Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mem_StepReadMemUsage( Mem_Step_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 berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mem/mem.h000066400000000000000000000052441300674244400225010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mem.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Memory management.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__mem__mem_h #define ABC__aig__mem__mem_h #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Mem_Fixed_t_ Mem_Fixed_t; typedef struct Mem_Flex_t_ Mem_Flex_t; typedef struct Mem_Step_t_ Mem_Step_t; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mem.c ===========================================================*/ // fixed-size-block memory manager extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize ); extern void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ); extern char * Mem_FixedEntryFetch( Mem_Fixed_t * p ); extern void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ); extern void Mem_FixedRestart( Mem_Fixed_t * p ); extern int Mem_FixedReadMemUsage( Mem_Fixed_t * p ); extern int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p ); // flexible-size-block memory manager extern Mem_Flex_t * Mem_FlexStart(); extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ); extern char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ); extern void Mem_FlexRestart( Mem_Flex_t * p ); extern int Mem_FlexReadMemUsage( Mem_Flex_t * p ); // hierarchical memory manager extern Mem_Step_t * Mem_StepStart( int nSteps ); extern void Mem_StepStop( Mem_Step_t * p, int fVerbose ); extern char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ); extern void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ); extern int Mem_StepReadMemUsage( Mem_Step_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mem/mem2.h000066400000000000000000000213501300674244400225570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mem2.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Memory management.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mem2.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__mem__mem2_h #define ABC__aig__mem__mem2_h #include "misc/vec/vec.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Mmr_Flex_t_ Mmr_Flex_t; typedef struct Mmr_Fixed_t_ Mmr_Fixed_t; typedef struct Mmr_Step_t_ Mmr_Step_t; struct Mmr_Flex_t_ { int nPageBase; // log2 page size in words int PageMask; // page mask int nEntries; // entries allocated int nEntriesMax; // max number of enries used int iNext; // next word to be used Vec_Ptr_t vPages; // memory pages }; struct Mmr_Fixed_t_ { int nPageBase; // log2 page size in words int PageMask; // page mask int nEntryWords; // entry size in words int nEntries; // entries allocated int nEntriesMax; // max number of enries used Vec_Ptr_t vPages; // memory pages Vec_Int_t vFrees; // free entries }; struct Mmr_Step_t_ { int nBits; // the number of bits int uMask; // the number of managers minus 1 int nEntries; // the number of entries int nEntriesMax; // the max number of entries int nEntriesAll; // the total number of entries Mmr_Fixed_t pMems[0]; // memory managers: 2^0 words, 2^1 words, etc }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Mmr_Flex_t * Mmr_FlexStart( int nPageBase ) { Mmr_Flex_t * p; p = ABC_CALLOC( Mmr_Flex_t, 1 ); p->nPageBase = nPageBase; p->PageMask = (1 << nPageBase) - 1; p->iNext = (1 << nPageBase); return p; } static inline void Mmr_FlexStop( Mmr_Flex_t * p ) { word * pPage; int i; if ( 0 && Vec_PtrSize(&p->vPages) ) printf( "Using %3d pages of %6d words each with %6d entries (max = %6d). Total memory = %5.2f MB.\n", Vec_PtrSize(&p->vPages), p->nPageBase ? 1 << p->nPageBase : 0, p->nEntries, p->nEntriesMax, 1.0 * Vec_PtrSize(&p->vPages) * (1 << p->nPageBase) * 8 / (1 << 20) ); Vec_PtrForEachEntry( word *, &p->vPages, pPage, i ) ABC_FREE( pPage ); ABC_FREE( p->vPages.pArray ); ABC_FREE( p ); } static inline word * Mmr_FlexEntry( Mmr_Flex_t * p, int h ) { assert( h > 0 && h < p->iNext ); return (word *)Vec_PtrEntry(&p->vPages, (h >> p->nPageBase)) + (h & p->PageMask); } static inline int Mmr_FlexFetch( Mmr_Flex_t * p, int nWords ) { int hEntry; assert( nWords > 0 && nWords < p->PageMask ); if ( p->iNext + nWords >= p->PageMask ) { Vec_PtrPush( &p->vPages, ABC_FALLOC( word, p->PageMask + 1 ) ); p->iNext = 1; } hEntry = ((Vec_PtrSize(&p->vPages) - 1) << p->nPageBase) | p->iNext; p->iNext += nWords; p->nEntries++; p->nEntriesMax = Abc_MaxInt( p->nEntriesMax, p->nEntries ); return hEntry; } static inline void Mmr_FlexRelease( Mmr_Flex_t * p, int h ) { assert( h > 0 && h < p->iNext ); if ( (h >> p->nPageBase) && Vec_PtrEntry(&p->vPages, (h >> p->nPageBase) - 1) ) { word * pPage = (word *)Vec_PtrEntry(&p->vPages, (h >> p->nPageBase) - 1); Vec_PtrWriteEntry( &p->vPages, (h >> p->nPageBase) - 1, NULL ); ABC_FREE( pPage ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Mmr_FixedCreate( Mmr_Fixed_t * p, int nPageBase, int nEntryWords ) { assert( nEntryWords > 0 && nEntryWords < (1 << nPageBase) ); p->nPageBase = nPageBase; p->PageMask = (1 << nPageBase) - 1; p->nEntryWords = nEntryWords; } static inline Mmr_Fixed_t * Mmr_FixedStart( int nPageBase, int nEntryWords ) { Mmr_Fixed_t * p = ABC_CALLOC( Mmr_Fixed_t, 1 ); Mmr_FixedCreate( p, nPageBase, nEntryWords ); return p; } static inline void Mmr_FixedStop( Mmr_Fixed_t * p, int fFreeLast ) { word * pPage; int i; if ( 0 && Vec_PtrSize(&p->vPages) ) printf( "Using %3d pages of %6d words each with %6d entries (max = %6d) of size %d. Total memory = %5.2f MB.\n", Vec_PtrSize(&p->vPages), p->nPageBase ? 1 << p->nPageBase : 0, p->nEntries, p->nEntriesMax, p->nEntryWords, 1.0 * Vec_PtrSize(&p->vPages) * (1 << p->nPageBase) * 8 / (1 << 20) ); Vec_PtrForEachEntry( word *, &p->vPages, pPage, i ) ABC_FREE( pPage ); ABC_FREE( p->vPages.pArray ); ABC_FREE( p->vFrees.pArray ); if ( fFreeLast ) ABC_FREE( p ); } static inline word * Mmr_FixedEntry( Mmr_Fixed_t * p, int h ) { assert( h > 0 && h < (Vec_PtrSize(&p->vPages) << p->nPageBase) ); return (word *)Vec_PtrEntry(&p->vPages, (h >> p->nPageBase)) + (h & p->PageMask); } static inline int Mmr_FixedFetch( Mmr_Fixed_t * p ) { if ( Vec_IntSize(&p->vFrees) == 0 ) { int i, hEntry = Vec_PtrSize(&p->vPages) << p->nPageBase; Vec_PtrPush( &p->vPages, ABC_FALLOC( word, p->PageMask + 1 ) ); for ( i = 1; i + p->nEntryWords <= p->PageMask; i += p->nEntryWords ) Vec_IntPush( &p->vFrees, hEntry | i ); Vec_IntReverseOrder( &p->vFrees ); } p->nEntries++; p->nEntriesMax = Abc_MaxInt( p->nEntriesMax, p->nEntries ); return Vec_IntPop( &p->vFrees ); } static inline void Mmr_FixedRecycle( Mmr_Fixed_t * p, int h ) { p->nEntries--; memset( Mmr_FixedEntry(p, h), 0xFF, sizeof(word) * p->nEntryWords ); Vec_IntPush( &p->vFrees, h ); } static inline int Mmr_FixedMemory( Mmr_Fixed_t * p ) { return Vec_PtrSize(&p->vPages) * (p->PageMask + 1); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Mmr_Step_t * Mmr_StepStart( int nPageBase, int nWordBase ) { char * pMemory = ABC_CALLOC( char, sizeof(Mmr_Step_t) + sizeof(Mmr_Fixed_t) * (1 << nWordBase) ); Mmr_Step_t * p = (Mmr_Step_t *)pMemory; int i; p->nBits = nWordBase; p->uMask = (1 << nWordBase) - 1; for ( i = 1; i <= p->uMask; i++ ) Mmr_FixedCreate( p->pMems + i, nPageBase, i ); return p; } static inline void Mmr_StepStop( Mmr_Step_t * p ) { int i; for ( i = 0; i <= p->uMask; i++ ) Mmr_FixedStop( p->pMems + i, 0 ); ABC_FREE( p ); } static inline word * Mmr_StepEntry( Mmr_Step_t * p, int h ) { assert( (h & p->uMask) > 0 ); return Mmr_FixedEntry( p->pMems + (h & p->uMask), (h >> p->nBits) ); } static inline int Mmr_StepFetch( Mmr_Step_t * p, int nWords ) { assert( nWords > 0 && nWords <= p->uMask ); p->nEntries++; p->nEntriesAll++; p->nEntriesMax = Abc_MaxInt( p->nEntriesMax, p->nEntries ); return (Mmr_FixedFetch(p->pMems + nWords) << p->nBits) | nWords; } static inline void Mmr_StepRecycle( Mmr_Step_t * p, int h ) { p->nEntries--; Mmr_FixedRecycle( p->pMems + (h & p->uMask), (h >> p->nBits) ); } static inline int Mmr_StepMemory( Mmr_Step_t * p ) { int i, Mem = 0; for ( i = 1; i <= p->uMask; i++ ) Mem += Mmr_FixedMemory( p->pMems + i ); return Mem; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mem/module.make000066400000000000000000000000331300674244400236650ustar00rootroot00000000000000SRC += src/misc/mem/mem.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/000077500000000000000000000000001300674244400215545ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/module.make000066400000000000000000000006321300674244400237010ustar00rootroot00000000000000SRC += src/misc/mvc/mvcApi.c \ src/misc/mvc/mvcCompare.c \ src/misc/mvc/mvcContain.c \ src/misc/mvc/mvcCover.c \ src/misc/mvc/mvcCube.c \ src/misc/mvc/mvcDivide.c \ src/misc/mvc/mvcDivisor.c \ src/misc/mvc/mvcList.c \ src/misc/mvc/mvcLits.c \ src/misc/mvc/mvcMan.c \ src/misc/mvc/mvcOpAlg.c \ src/misc/mvc/mvcOpBool.c \ src/misc/mvc/mvcPrint.c \ src/misc/mvc/mvcSort.c \ src/misc/mvc/mvcUtils.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvc.c000066400000000000000000000025721300674244400225130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvc.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvc.c,v 1.3 2003/03/19 19:50:26 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvc.h000066400000000000000000001116701300674244400225200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvc.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Data structure for MV cube/cover manipulation.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvc.h,v 1.10 2003/05/02 23:23:59 wjiang Exp $] ***********************************************************************/ #ifndef ABC__misc__mvc__mvc_h #define ABC__misc__mvc__mvc_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "misc/extra/extra.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // this is the only part of Mvc package, which should be modified // when compiling the package for other platforms // these parameters can be computed but setting them manually makes it faster #define BITS_PER_WORD 32 // sizeof(Mvc_CubeWord_t) * 8 #define BITS_PER_WORD_MINUS 31 // the same minus 1 #define BITS_PER_WORD_LOG 5 // log2(sizeof(Mvc_CubeWord_t) * 8) #define BITS_DISJOINT ((Mvc_CubeWord_t)0x55555555) // the mask of the type "01010101" #define BITS_FULL ((Mvc_CubeWord_t)0xffffffff) // the mask of the type "11111111" // uncomment this macro to switch to standard memory management //#define USE_SYSTEM_MEMORY_MANAGEMENT //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // cube/list/cover/data typedef unsigned int Mvc_CubeWord_t; typedef struct MvcCubeStruct Mvc_Cube_t; typedef struct MvcListStruct Mvc_List_t; typedef struct MvcCoverStruct Mvc_Cover_t; typedef struct MvcDataStruct Mvc_Data_t; typedef struct MvcManagerStruct Mvc_Manager_t; // the cube data structure struct MvcCubeStruct { Mvc_Cube_t * pNext; // the next cube in the linked list unsigned iLast : 24; // the index of the last word unsigned nUnused : 6; // the number of unused bits in the last word unsigned fPrime : 1; // marks the prime cube unsigned fEssen : 1; // marks the essential cube unsigned nOnes; // the number of 1's in the bit data Mvc_CubeWord_t pData[1]; // the first Mvc_CubeWord_t filled with bit data }; // the single-linked list of cubes in the cover struct MvcListStruct { Mvc_Cube_t * pHead; // the first cube in the list Mvc_Cube_t * pTail; // the last cube in the list int nItems; // the number of cubes in the list }; // the cover data structure struct MvcCoverStruct { int nWords; // the number of machine words int nUnused; // the number of unused bits in the last word int nBits; // the number of used data bits in the cube Mvc_List_t lCubes; // the single-linked list of cubes Mvc_Cube_t ** pCubes; // the array of cubes (for sorting) int nCubesAlloc; // the size of allocated storage int * pLits; // the counter of lit occurrances in cubes Mvc_Cube_t * pMask; // the multipurpose mask Mvc_Manager_t * pMem; // the memory manager }; // data structure to store information about MV variables struct MvcDataStruct { Mvc_Manager_t * pMan; // the memory manager // Vm_VarMap_t * pVm; // the MV variable data int nBinVars; // the number of binary variables Mvc_Cube_t * pMaskBin; // the mask to select the binary bits only Mvc_Cube_t ** ppMasks; // the mask to select each MV variable Mvc_Cube_t * ppTemp[3]; // the temporary cubes }; // the manager of covers and cubes (as of today, only managing memory) struct MvcManagerStruct { Extra_MmFixed_t * pManC; // the manager for covers Extra_MmFixed_t * pMan1; // the manager for 1-word cubes Extra_MmFixed_t * pMan2; // the manager for 2-word cubes Extra_MmFixed_t * pMan4; // the manager for 3-word cubes }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // reading data from the header of the cube #define Mvc_CubeReadNext(Cube) ((Cube)->pNext) #define Mvc_CubeReadNextP(Cube) (&(Cube)->pNext) #define Mvc_CubeReadLast(Cube) ((Cube)->iLast) #define Mvc_CubeReadSize(Cube) ((Cube)->nOnes) // setting data to the header of the cube #define Mvc_CubeSetNext(Cube,Next) ((Cube)->pNext = (Next)) #define Mvc_CubeSetLast(Cube,Last) ((Cube)->iLast = (Last)) #define Mvc_CubeSetSize(Cube,Size) ((Cube)->nOnes = (Size)) // checking the number of words #define Mvc_Cube1Words(Cube) ((Cube)->iLast == 0) #define Mvc_Cube2Words(Cube) ((Cube)->iLast == 1) #define Mvc_CubeNWords(Cube) ((Cube)->iLast > 1) // getting one data bit #define Mvc_CubeWhichWord(Bit) ((Bit) >> BITS_PER_WORD_LOG) #define Mvc_CubeWhichBit(Bit) ((Bit) & BITS_PER_WORD_MINUS) // accessing individual bits #define Mvc_CubeBitValue(Cube, Bit) (((Cube)->pData[Mvc_CubeWhichWord(Bit)] & (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) > 0) #define Mvc_CubeBitInsert(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] |= (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) #define Mvc_CubeBitRemove(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] &= ~(((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) // accessing values of the binary variables #define Mvc_CubeVarValue(Cube, Var) (((Cube)->pData[Mvc_CubeWhichWord(2*(Var))] >> (Mvc_CubeWhichBit(2*(Var)))) & ((Mvc_CubeWord_t)3)) // various macros // cleaning the data bits of the cube #define Mvc_Cube1BitClean( Cube )\ ((Cube)->pData[0] = 0) #define Mvc_Cube2BitClean( Cube )\ (((Cube)->pData[0] = 0),\ ((Cube)->pData[1] = 0)) #define Mvc_CubeNBitClean( Cube )\ {\ int _i_;\ for( _i_ = (Cube)->iLast; _i_ >= 0; _i_--)\ (Cube)->pData[_i_] = 0;\ } // cleaning the unused part of the lat word #define Mvc_CubeBitCleanUnused( Cube )\ ((Cube)->pData[(Cube)->iLast] &= (BITS_FULL >> (Cube)->nUnused)) // filling the used data bits with 1's #define Mvc_Cube1BitFill( Cube )\ (Cube)->pData[0] = (BITS_FULL >> (Cube)->nUnused); #define Mvc_Cube2BitFill( Cube )\ (((Cube)->pData[0] = BITS_FULL),\ ((Cube)->pData[1] = (BITS_FULL >> (Cube)->nUnused))) #define Mvc_CubeNBitFill( Cube )\ {\ int _i_;\ (Cube)->pData[(Cube)->iLast] = (BITS_FULL >> (Cube)->nUnused);\ for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\ (Cube)->pData[_i_] = BITS_FULL;\ } // complementing the data bits #define Mvc_Cube1BitNot( Cube )\ ((Cube)->pData[0] ^= (BITS_FULL >> (Cube)->nUnused)) #define Mvc_Cube2BitNot( Cube )\ (((Cube)->pData[0] ^= BITS_FULL),\ ((Cube)->pData[1] ^= (BITS_FULL >> (Cube)->nUnused))) #define Mvc_CubeNBitNot( Cube )\ {\ int _i_;\ (Cube)->pData[(Cube)->iLast] ^= (BITS_FULL >> (Cube)->nUnused);\ for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\ (Cube)->pData[_i_] ^= BITS_FULL;\ } #define Mvc_Cube1BitCopy( Cube1, Cube2 )\ (((Cube1)->pData[0]) = ((Cube2)->pData[0])) #define Mvc_Cube2BitCopy( Cube1, Cube2 )\ ((((Cube1)->pData[0]) = ((Cube2)->pData[0])),\ (((Cube1)->pData[1])= ((Cube2)->pData[1]))) #define Mvc_CubeNBitCopy( Cube1, Cube2 )\ {\ int _i_;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ ((Cube1)->pData[_i_]) = ((Cube2)->pData[_i_]);\ } #define Mvc_Cube1BitOr( CubeR, Cube1, Cube2 )\ (((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0])) #define Mvc_Cube2BitOr( CubeR, Cube1, Cube2 )\ ((((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0])),\ (((CubeR)->pData[1]) = ((Cube1)->pData[1] | (Cube2)->pData[1]))) #define Mvc_CubeNBitOr( CubeR, Cube1, Cube2 )\ {\ int _i_;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] | (Cube2)->pData[_i_]));\ } #define Mvc_Cube1BitExor( CubeR, Cube1, Cube2 )\ (((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0])) #define Mvc_Cube2BitExor( CubeR, Cube1, Cube2 )\ ((((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0])),\ (((CubeR)->pData[1]) = ((Cube1)->pData[1] ^ (Cube2)->pData[1]))) #define Mvc_CubeNBitExor( CubeR, Cube1, Cube2 )\ {\ int _i_;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] ^ (Cube2)->pData[_i_]));\ } #define Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 )\ (((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0])) #define Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 )\ ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0])),\ (((CubeR)->pData[1]) = ((Cube1)->pData[1] & (Cube2)->pData[1]))) #define Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 )\ {\ int _i_;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & (Cube2)->pData[_i_]));\ } #define Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 )\ (((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0]))) #define Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 )\ ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0]))),\ (((CubeR)->pData[1]) = ((Cube1)->pData[1] & ~((Cube2)->pData[1])))) #define Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 )\ {\ int _i_;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & ~(Cube2)->pData[_i_]));\ } #define Mvc_Cube1BitEmpty( Res, Cube )\ (Res = ((Cube)->pData[0] == 0)) #define Mvc_Cube2BitEmpty( Res, Cube )\ (Res = ((Cube)->pData[0] == 0 && (Cube)->pData[1] == 0)) #define Mvc_CubeNBitEmpty( Res, Cube )\ {\ int _i_; Res = 1;\ for (_i_ = (Cube)->iLast; _i_ >= 0; _i_--)\ if ( (Cube)->pData[_i_] )\ { Res = 0; break; }\ } #define Mvc_Cube1BitEqual( Res, Cube1, Cube2 )\ (Res = (((Cube1)->pData[0]) == ((Cube2)->pData[0]))) #define Mvc_Cube2BitEqual( Res, Cube1, Cube2 )\ (Res = ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) &&\ (((Cube1)->pData[1]) == ((Cube2)->pData[1])))) #define Mvc_CubeNBitEqual( Res, Cube1, Cube2 )\ {\ int _i_; Res = 1;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if (((Cube1)->pData[_i_]) != ((Cube2)->pData[_i_]))\ { Res = 0; break; }\ } #define Mvc_Cube1BitLess( Res, Cube1, Cube2 )\ (Res = (((Cube1)->pData[0]) < ((Cube2)->pData[0]))) #define Mvc_Cube2BitLess( Res, Cube1, Cube2 )\ (Res = ((((Cube1)->pData[0]) < ((Cube2)->pData[0])) ||\ ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) < ((Cube2)->pData[1]))))) #define Mvc_CubeNBitLess( Res, Cube1, Cube2 )\ {\ int _i_; Res = 1;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if (((Cube1)->pData[_i_]) >= ((Cube2)->pData[_i_]))\ { Res = 0; break; }\ } #define Mvc_Cube1BitMore( Res, Cube1, Cube2 )\ (Res = (((Cube1)->pData[0]) > ((Cube2)->pData[0]))) #define Mvc_Cube2BitMore( Res, Cube1, Cube2 )\ (Res = ((((Cube1)->pData[0]) > ((Cube2)->pData[0])) ||\ ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) > ((Cube2)->pData[1]))))) #define Mvc_CubeNBitMore( Res, Cube1, Cube2 )\ {\ int _i_; Res = 1;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if (((Cube1)->pData[_i_]) <= ((Cube2)->pData[_i_]))\ { Res = 0; break; }\ } #define Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 )\ (Res = (((Cube1)->pData[0]) & ~((Cube2)->pData[0]))) #define Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 )\ (Res = ((((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\ (((Cube1)->pData[1]) & ~((Cube2)->pData[1])))) #define Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 )\ {\ int _i_; Res = 0;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if (((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\ { Res = 1; break; }\ } #define Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 )\ (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0])) == 0 )) #define Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 )\ (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0])) == 0 ) &&\ ((((Cube1)->pData[1]) & ((Cube2)->pData[1])) == 0 ))) #define Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 )\ {\ int _i_; Res = 1;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]))\ { Res = 0; break; }\ } #define Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask )\ (Res = ((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0])))) #define Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask )\ (Res = (((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0]))) &&\ ((((Cube1)->pData[1]) & ((Mask)->pData[1])) == (((Cube2)->pData[1]) & ((Mask)->pData[1]))))) #define Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask )\ {\ int _i_; Res = 1;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if ((((Cube1)->pData[_i_]) & ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) & ((Mask)->pData[_i_])))\ { Res = 0; break; }\ } #define Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ (Res = ((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0])))) #define Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ (Res = (((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0]))) &&\ ((((Cube1)->pData[1]) | ((Mask)->pData[1])) == (((Cube2)->pData[1]) | ((Mask)->pData[1]))))) #define Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ {\ int _i_; Res = 1;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if ((((Cube1)->pData[_i_]) | ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) | ((Mask)->pData[_i_])))\ { Res = 0; break; }\ } #define Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0)) #define Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0) ||\ ((((Cube1)->pData[1]) & ((Cube2)->pData[1]) & ((Mask)->pData[1])) > 0))) #define Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ {\ int _i_; Res = 0;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]) & ((Mask)->pData[_i_]))\ { Res = 1; break; }\ } #define Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ (Res = (((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0]))) #define Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ (Res = ((((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\ (((Mask)->pData[1]) & ((Cube1)->pData[1]) & ~((Cube2)->pData[1])))) #define Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ {\ int _i_; Res = 0;\ for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ if (((Mask)->pData[_i_]) & ((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\ { Res = 1; break; }\ } // the following macros make no assumption about the cube's bitset size #define Mvc_CubeBitClean( Cube )\ if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitClean( Cube ); }\ else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitClean( Cube ); }\ else { Mvc_CubeNBitClean( Cube ); } #define Mvc_CubeBitFill( Cube )\ if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitFill( Cube ); }\ else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitFill( Cube ); }\ else { Mvc_CubeNBitFill( Cube ); } #define Mvc_CubeBitNot( Cube )\ if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitNot( Cube ); }\ else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitNot( Cube ); }\ else { Mvc_CubeNBitNot( Cube ); } #define Mvc_CubeBitCopy( Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitCopy( Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitCopy( Cube1, Cube2 ); }\ else { Mvc_CubeNBitCopy( Cube1, Cube2 ); } #define Mvc_CubeBitOr( CubeR, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitOr( CubeR, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitOr( CubeR, Cube1, Cube2 ); }\ else { Mvc_CubeNBitOr( CubeR, Cube1, Cube2 ); } #define Mvc_CubeBitExor( CubeR, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitExor( CubeR, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitExor( CubeR, Cube1, Cube2 ); }\ else { Mvc_CubeNBitExor( CubeR, Cube1, Cube2 ); } #define Mvc_CubeBitAnd( CubeR, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 ); }\ else { Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 ); } #define Mvc_CubeBitSharp( CubeR, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 ); }\ else { Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 ); } #define Mvc_CubeBitEmpty( Res, Cube )\ if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitEmpty( Res, Cube ); }\ else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitEmpty( Res, Cube ); }\ else { Mvc_CubeNBitEmpty( Res, Cube ); } #define Mvc_CubeBitEqual( Res, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqual( Res, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqual( Res, Cube1, Cube2 ); }\ else { Mvc_CubeNBitEqual( Res, Cube1, Cube2 ); } #define Mvc_CubeBitLess( Res, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitLess( Res, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitLess( Res, Cube1, Cube2 ); }\ else { Mvc_CubeNBitLess( Res, Cube1, Cube2 ); } #define Mvc_CubeBitMore( Res, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitMore( Res, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitMore( Res, Cube1, Cube2 ); }\ else { Mvc_CubeNBitMore( Res, Cube1, Cube2 ); } #define Mvc_CubeBitNotImpl( Res, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 ); }\ else { Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 ); } #define Mvc_CubeBitDisjoint( Res, Cube1, Cube2 )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 ); }\ else { Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 ); } #define Mvc_CubeBitEqualUnderMask( Res, Cube1, Cube2, Mask )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\ else { Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask ); } #define Mvc_CubeBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\ else { Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask ); } #define Mvc_CubeBitIntersectUnderMask( Res, Cube1, Cube2, Mask )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\ else { Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask ); } #define Mvc_CubeBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\ else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\ else { Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask ); } // managing linked lists #define Mvc_ListAddCubeHead( pList, pCube )\ {\ if ( pList->pHead == NULL )\ {\ Mvc_CubeSetNext( pCube, NULL );\ pList->pHead = pCube;\ pList->pTail = pCube;\ }\ else\ {\ Mvc_CubeSetNext( pCube, pList->pHead );\ pList->pHead = pCube;\ }\ pList->nItems++;\ } #define Mvc_ListAddCubeTail( pList, pCube )\ {\ if ( pList->pHead == NULL )\ pList->pHead = pCube;\ else\ Mvc_CubeSetNext( pList->pTail, pCube );\ pList->pTail = pCube;\ Mvc_CubeSetNext( pCube, NULL );\ pList->nItems++;\ } #define Mvc_ListDeleteCube( pList, pPrev, pCube )\ {\ if ( pPrev == NULL )\ pList->pHead = pCube->pNext;\ else\ pPrev->pNext = pCube->pNext;\ if ( pList->pTail == pCube )\ {\ assert( pCube->pNext == NULL );\ pList->pTail = pPrev;\ }\ pList->nItems--;\ } // managing linked lists inside the cover #define Mvc_CoverAddCubeHead( pCover, pCube )\ {\ Mvc_List_t * pList = &pCover->lCubes;\ Mvc_ListAddCubeHead( pList, pCube );\ } #define Mvc_CoverAddCubeTail( pCover, pCube )\ {\ Mvc_List_t * pList = &pCover->lCubes;\ Mvc_ListAddCubeTail( pList, pCube );\ } #define Mvc_CoverDeleteCube( pCover, pPrev, pCube )\ {\ Mvc_List_t * pList = &pCover->lCubes;\ Mvc_ListDeleteCube( pList, pPrev, pCube );\ } // iterator through the cubes in the cube list #define Mvc_ListForEachCube( List, Cube )\ for ( Cube = List->pHead;\ Cube;\ Cube = Cube->pNext ) #define Mvc_ListForEachCubeSafe( List, Cube, Cube2 )\ for ( Cube = List->pHead, Cube2 = (Cube? Cube->pNext: NULL);\ Cube;\ Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) // iterator through cubes in the cover #define Mvc_CoverForEachCube( Cover, Cube )\ for ( Cube = (Cover)->lCubes.pHead;\ Cube;\ Cube = Cube->pNext ) #define Mvc_CoverForEachCubeWithIndex( Cover, Cube, Index )\ for ( Index = 0, Cube = (Cover)->lCubes.pHead;\ Cube;\ Index++, Cube = Cube->pNext ) #define Mvc_CoverForEachCubeSafe( Cover, Cube, Cube2 )\ for ( Cube = (Cover)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\ Cube;\ Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) // iterator which starts from the given cube #define Mvc_CoverForEachCubeStart( Start, Cube )\ for ( Cube = Start;\ Cube;\ Cube = Cube->pNext ) #define Mvc_CoverForEachCubeStartSafe( Start, Cube, Cube2 )\ for ( Cube = Start, Cube2 = (Cube? Cube->pNext: NULL);\ Cube;\ Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) // iterator through literals of the cube #define Mvc_CubeForEachBit( Cover, Cube, iBit, Value )\ for ( iBit = 0;\ iBit < Cover->nBits && ((Value = Mvc_CubeBitValue(Cube,iBit)), 1);\ iBit++ ) // iterator through values of binary variables #define Mvc_CubeForEachVarValue( Cover, Cube, iVar, Value )\ for ( iVar = 0;\ iVar < Cover->nBits/2 && (Value = Mvc_CubeVarValue(Cube,iVar));\ iVar++ ) // macros which work with memory // MEM_ALLOC: allocate the given number (Size) of items of type (Type) // MEM_FREE: deallocate the pointer (Pointer) to the given number (Size) of items of type (Type) #define MEM_ALLOC( Manager, Type, Size ) ((Type *)ABC_ALLOC( char, (Size) * sizeof(Type) )) #define MEM_FREE( Manager, Type, Size, Pointer ) if ( Pointer ) { ABC_FREE(Pointer); Pointer = NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== mvcApi.c ====================================================*/ extern int Mvc_CoverReadWordNum( Mvc_Cover_t * pCover ); extern int Mvc_CoverReadBitNum( Mvc_Cover_t * pCover ); extern int Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover ); extern Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover ); extern Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover ); extern Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover ); extern int Mvc_ListReadCubeNum( Mvc_List_t * pList ); extern Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList ); extern Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList ); extern void Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems ); extern void Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList ); extern int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover ); extern int Mvc_CoverIsTautology( Mvc_Cover_t * pCover ); extern int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover ); extern void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover ); extern void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover ); extern Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover ); extern Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover ); /*=== mvcCover.c ====================================================*/ extern Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits ); extern Mvc_Cover_t * Mvc_CoverCreateConst( Mvc_Manager_t * pMem, int nBits, int Phase ); extern Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * pCover ); extern Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * pCover ); extern void Mvc_CoverFree( Mvc_Cover_t * pCover ); extern void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover ); extern void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover ); extern void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover ); extern void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover ); extern void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover ); /*=== mvcCube.c ====================================================*/ extern Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover ); extern Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube ); /*=== mvcCompare.c ====================================================*/ extern int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); extern int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); extern int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); extern int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); extern int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); /*=== mvcDd.c ====================================================*/ /* extern DdNode * Mvc_CoverConvertToBdd( DdManager * dd, Mvc_Cover_t * pCover ); extern DdNode * Mvc_CoverConvertToZdd( DdManager * dd, Mvc_Cover_t * pCover ); extern DdNode * Mvc_CoverConvertToZdd2( DdManager * dd, Mvc_Cover_t * pCover ); extern DdNode * Mvc_CubeConvertToBdd( DdManager * dd, Mvc_Cube_t * pCube ); extern DdNode * Mvc_CubeConvertToZdd( DdManager * dd, Mvc_Cube_t * pCube ); extern DdNode * Mvc_CubeConvertToZdd2( DdManager * dd, Mvc_Cube_t * pCube ); */ /*=== mvcDivisor.c ====================================================*/ extern Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover ); /*=== mvcDivide.c ====================================================*/ extern void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); extern void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); extern void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); extern void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); extern void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit ); /*=== mvcList.c ====================================================*/ // these functions are available as macros extern void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube ); extern void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube ); extern void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ); extern void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ); extern void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); // other functions extern void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CoverList2Array( Mvc_Cover_t * pCover ); extern void Mvc_CoverArray2List( Mvc_Cover_t * pCover ); extern Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead ); /*=== mvcPrint.c ====================================================*/ extern void Mvc_CoverPrint( Mvc_Cover_t * pCover ); extern void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); extern void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover ); extern void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); /*=== mvcSort.c ====================================================*/ extern void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); /*=== mvcUtils.c ====================================================*/ extern void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ); extern int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover ); extern int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar ); extern void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube ); extern int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover ); extern void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover ); extern Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover ); extern int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); extern int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover ); extern int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube ); extern int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] ); extern Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * pCover, int * pVarsRem, int nVarsRem ); extern void Mvc_CoverInverse( Mvc_Cover_t * pCover ); extern Mvc_Cover_t * Mvc_CoverRemoveDontCareLits( Mvc_Cover_t * pCover ); extern Mvc_Cover_t * Mvc_CoverCofactor( Mvc_Cover_t * pCover, int iValue, int iValueOther ); extern Mvc_Cover_t * Mvc_CoverFlipVar( Mvc_Cover_t * pCover, int iValue0, int iValue1 ); extern Mvc_Cover_t * Mvc_CoverUnivQuantify( Mvc_Cover_t * p, int iValueA0, int iValueA1, int iValueB0, int iValueB1 ); extern Mvc_Cover_t ** Mvc_CoverCofactors( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar ); extern int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue ); //extern Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew ); extern Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover ); extern int Mvc_UtilsCheckUnusedZeros( Mvc_Cover_t * pCover ); /*=== mvcLits.c ====================================================*/ extern int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); extern int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); extern int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); extern Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ); extern int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover ); extern int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover ); extern int Mvc_CoverIsOneLiteral( Mvc_Cover_t * pCover ); /*=== mvcOpAlg.c ====================================================*/ extern Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); extern Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); extern int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); /*=== mvcOpBool.c ====================================================*/ extern Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); extern Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); extern int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); /*=== mvcContain.c ====================================================*/ extern int Mvc_CoverContain( Mvc_Cover_t * pCover ); /*=== mvcTau.c ====================================================*/ extern int Mvc_CoverTautology( Mvc_Data_t * p, Mvc_Cover_t * pCover ); /*=== mvcCompl.c ====================================================*/ extern Mvc_Cover_t * Mvc_CoverComplement( Mvc_Data_t * p, Mvc_Cover_t * pCover ); /*=== mvcSharp.c ====================================================*/ extern Mvc_Cover_t * Mvc_CoverSharp( Mvc_Data_t * p, Mvc_Cover_t * pA, Mvc_Cover_t * pB ); extern int Mvc_CoverDist0Cubes( Mvc_Data_t * pData, Mvc_Cube_t * pA, Mvc_Cube_t * pB ); extern void Mvc_CoverIntersectCubes( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); extern int Mvc_CoverIsIntersecting( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); extern void Mvc_CoverAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); extern void Mvc_CoverCopyAndAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); extern void Mvc_CoverRemoveCubes( Mvc_Cover_t * pC ); /*=== mvcReshape.c ====================================================*/ extern void Mvc_CoverMinimizeByReshape( Mvc_Data_t * pData, Mvc_Cover_t * pCover ); /*=== mvcMerge.c ====================================================*/ extern void Mvc_CoverDist1Merge( Mvc_Data_t * p, Mvc_Cover_t * pCover ); /*=== mvcData.c ====================================================*/ //extern Mvc_Data_t * Mvc_CoverDataAlloc( Vm_VarMap_t * pVm, Mvc_Cover_t * pCover ); //extern void Mvc_CoverDataFree( Mvc_Data_t * p, Mvc_Cover_t * pCover ); /*=== mvcMan.c ====================================================*/ extern void Mvc_ManagerFree( Mvc_Manager_t * p ); extern Mvc_Manager_t * Mvc_ManagerStart(); extern Mvc_Manager_t * Mvc_ManagerAllocCover(); extern Mvc_Manager_t * Mvc_ManagerAllocCube( int nWords ); extern Mvc_Manager_t * Mvc_ManagerFreeCover( Mvc_Cover_t * pCover ); extern Mvc_Manager_t * Mvc_ManagerFreeCube( Mvc_Cover_t * pCube, int nWords ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcApi.c000066400000000000000000000147271300674244400231520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcApi.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcApi.c,v 1.4 2003/04/03 06:31:48 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverReadWordNum( Mvc_Cover_t * pCover ) { return pCover->nWords; } int Mvc_CoverReadBitNum( Mvc_Cover_t * pCover ) { return pCover->nBits; } int Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover ) { return pCover->lCubes.nItems; } Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover ) { return pCover->lCubes.pHead; } Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover ) { return pCover->lCubes.pTail; } Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover ) { return &pCover->lCubes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_ListReadCubeNum( Mvc_List_t * pList ) { return pList->nItems; } Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList ) { return pList->pHead; } Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList ) { return pList->pTail; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems ) { pCover->lCubes.nItems = nItems; } void Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pHead = pCube; } void Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pTail = pCube; } void Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList ) { pCover->lCubes = *pList; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover ) { return Mvc_CoverReadCubeNum(pCover) == 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverIsTautology( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; int iBit, Value; if ( Mvc_CoverReadCubeNum(pCover) != 1 ) return 0; pCube = Mvc_CoverReadCubeHead( pCover ); Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) if ( Value == 0 ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if the cover is a binary buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; if ( pCover->nBits != 2 ) return 0; if ( Mvc_CoverReadCubeNum(pCover) != 1 ) return 0; pCube = pCover->lCubes.pHead; if ( Mvc_CubeBitValue(pCube, 0) == 0 && Mvc_CubeBitValue(pCube, 1) == 1 ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube, * pCube2; Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 ) Mvc_CubeFree( pCover, pCube ); pCover->lCubes.nItems = 0; pCover->lCubes.pHead = NULL; pCover->lCubes.pTail = NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCubeNew; Mvc_CoverMakeEmpty( pCover ); pCubeNew = Mvc_CubeAlloc( pCover ); Mvc_CubeBitFill( pCubeNew ); Mvc_CoverAddCubeTail( pCover, pCubeNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover ) { Mvc_Cover_t * pCoverNew; pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); return pCoverNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCubeNew; Mvc_Cover_t * pCoverNew; pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); pCubeNew = Mvc_CubeAlloc( pCoverNew ); Mvc_CubeBitFill( pCubeNew ); Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); return pCoverNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcCompare.c000066400000000000000000000240571300674244400240240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcCompare.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Various cube comparison functions.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcCompare.c,v 1.5 2003/04/03 23:25:41 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Compares two cubes according to their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) { if ( Mvc_Cube1Words(pC1) ) { if ( pC1->pData[0] < pC2->pData[0] ) return -1; if ( pC1->pData[0] > pC2->pData[0] ) return 1; return 0; } else if ( Mvc_Cube2Words(pC1) ) { if ( pC1->pData[1] < pC2->pData[1] ) return -1; if ( pC1->pData[1] > pC2->pData[1] ) return 1; if ( pC1->pData[0] < pC2->pData[0] ) return -1; if ( pC1->pData[0] > pC2->pData[0] ) return 1; return 0; } else { int i = Mvc_CubeReadLast(pC1); for(; i >= 0; i--) { if ( pC1->pData[i] < pC2->pData[i] ) return -1; if ( pC1->pData[i] > pC2->pData[i] ) return 1; } return 0; } } /**Function************************************************************* Synopsis [Compares the cubes (1) by size, (2) by integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) { // compare the cubes by size if ( Mvc_CubeReadSize( pC1 ) < Mvc_CubeReadSize( pC2 ) ) return 1; if ( Mvc_CubeReadSize( pC1 ) > Mvc_CubeReadSize( pC2 ) ) return -1; // the cubes have the same size // compare the cubes as integers if ( Mvc_Cube1Words( pC1 ) ) { if ( pC1->pData[0] < pC2->pData[0] ) return -1; if ( pC1->pData[0] > pC2->pData[0] ) return 1; return 0; } else if ( Mvc_Cube2Words( pC1 ) ) { if ( pC1->pData[1] < pC2->pData[1] ) return -1; if ( pC1->pData[1] > pC2->pData[1] ) return 1; if ( pC1->pData[0] < pC2->pData[0] ) return -1; if ( pC1->pData[0] > pC2->pData[0] ) return 1; return 0; } else { int i = Mvc_CubeReadLast( pC1 ); for(; i >= 0; i--) { if ( pC1->pData[i] < pC2->pData[i] ) return -1; if ( pC1->pData[i] > pC2->pData[i] ) return 1; } return 0; } } /**Function************************************************************* Synopsis [Compares two cubes under the mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) { unsigned uBits1, uBits2; // compare the cubes under the mask if ( Mvc_Cube1Words(pC1) ) { uBits1 = pC1->pData[0] & pMask->pData[0]; uBits2 = pC2->pData[0] & pMask->pData[0]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; // cubes are equal return 0; } else if ( Mvc_Cube2Words(pC1) ) { uBits1 = pC1->pData[1] & pMask->pData[1]; uBits2 = pC2->pData[1] & pMask->pData[1]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; uBits1 = pC1->pData[0] & pMask->pData[0]; uBits2 = pC2->pData[0] & pMask->pData[0]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; return 0; } else { int i = Mvc_CubeReadLast(pC1); for(; i >= 0; i--) { uBits1 = pC1->pData[i] & pMask->pData[i]; uBits2 = pC2->pData[i] & pMask->pData[i]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; } return 0; } } /**Function************************************************************* Synopsis [Compares two cubes under the mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) { unsigned uBits1, uBits2; // compare the cubes under the mask if ( Mvc_Cube1Words(pC1) ) { uBits1 = pC1->pData[0] | pMask->pData[0]; uBits2 = pC2->pData[0] | pMask->pData[0]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; // cubes are equal return 0; } else if ( Mvc_Cube2Words(pC1) ) { uBits1 = pC1->pData[1] | pMask->pData[1]; uBits2 = pC2->pData[1] | pMask->pData[1]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; uBits1 = pC1->pData[0] | pMask->pData[0]; uBits2 = pC2->pData[0] | pMask->pData[0]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; return 0; } else { int i = Mvc_CubeReadLast(pC1); for(; i >= 0; i--) { uBits1 = pC1->pData[i] | pMask->pData[i]; uBits2 = pC2->pData[i] | pMask->pData[i]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; } return 0; } } /**Function************************************************************* Synopsis [Compares the cubes (1) outside the mask, (2) under the mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) { unsigned uBits1, uBits2; if ( Mvc_Cube1Words(pC1) ) { // compare the cubes outside the mask uBits1 = pC1->pData[0] & ~(pMask->pData[0]); uBits2 = pC2->pData[0] & ~(pMask->pData[0]); if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; // compare the cubes under the mask uBits1 = pC1->pData[0] & pMask->pData[0]; uBits2 = pC2->pData[0] & pMask->pData[0]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; // cubes are equal // should never happen assert( 0 ); return 0; } else if ( Mvc_Cube2Words(pC1) ) { // compare the cubes outside the mask uBits1 = pC1->pData[1] & ~(pMask->pData[1]); uBits2 = pC2->pData[1] & ~(pMask->pData[1]); if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; uBits1 = pC1->pData[0] & ~(pMask->pData[0]); uBits2 = pC2->pData[0] & ~(pMask->pData[0]); if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; // compare the cubes under the mask uBits1 = pC1->pData[1] & pMask->pData[1]; uBits2 = pC2->pData[1] & pMask->pData[1]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; uBits1 = pC1->pData[0] & pMask->pData[0]; uBits2 = pC2->pData[0] & pMask->pData[0]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; // cubes are equal // should never happen assert( 0 ); return 0; } else { int i; // compare the cubes outside the mask for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- ) { uBits1 = pC1->pData[i] & ~(pMask->pData[i]); uBits2 = pC2->pData[i] & ~(pMask->pData[i]); if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; } // compare the cubes under the mask for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- ) { uBits1 = pC1->pData[i] & pMask->pData[i]; uBits2 = pC2->pData[i] & pMask->pData[i]; if ( uBits1 < uBits2 ) return -1; if ( uBits1 > uBits2 ) return 1; } /* { Mvc_Cover_t * pCover; pCover = Mvc_CoverAlloc( NULL, 96 ); Mvc_CubePrint( pCover, pC1 ); Mvc_CubePrint( pCover, pC2 ); Mvc_CubePrint( pCover, pMask ); } */ // cubes are equal // should never happen assert( 0 ); return 0; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcContain.c000066400000000000000000000131421300674244400240220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcContain.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Making the cover single-cube containment ABC_FREE.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcContain.c,v 1.4 2003/04/03 23:25:42 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover ); static void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Removes the contained cubes.] Description [Returns 1 if the cover has been changed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverContain( Mvc_Cover_t * pCover ) { int nCubes; nCubes = Mvc_CoverReadCubeNum( pCover ); if ( nCubes < 2 ) return 0; Mvc_CoverSetCubeSizes(pCover); Mvc_CoverSort( pCover, NULL, Mvc_CubeCompareSizeAndInt ); Mvc_CoverRemoveDuplicates( pCover ); if ( nCubes > 1 ) Mvc_CoverRemoveContained( pCover ); return (nCubes != Mvc_CoverReadCubeNum(pCover)); } /**Function************************************************************* Synopsis [Removes adjacent duplicated cubes from the cube list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pPrev, * pCube, * pCube2; int fEqual; // set the first cube of the cover pPrev = Mvc_CoverReadCubeHead(pCover); // go through all the cubes after this one Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pPrev), pCube, pCube2 ) { // compare the current cube with the prev cube Mvc_CubeBitEqual( fEqual, pPrev, pCube ); if ( fEqual ) { // they are equal - remove the current cube Mvc_CoverDeleteCube( pCover, pPrev, pCube ); Mvc_CubeFree( pCover, pCube ); // don't change the previous cube cube } else { // they are not equal - update the previous cube pPrev = pCube; } } } /**Function************************************************************* Synopsis [Removes contained cubes from the sorted cube list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCubeBeg, * pCubeEnd, * pCubeLarge; Mvc_Cube_t * pCube, * pCube2, * pPrev; unsigned sizeCur; int Result; // since the cubes are sorted by size, it is sufficient // to compare each cube with other cubes that have larger sizes // if the given cube implies a larger cube, the larger cube is removed pCubeBeg = Mvc_CoverReadCubeHead(pCover); do { // get the current cube size sizeCur = Mvc_CubeReadSize(pCubeBeg); // initialize the end of the given size group pCubeEnd = pCubeBeg; // find the beginning of the next size group Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCubeBeg), pCube ) { if ( sizeCur == Mvc_CubeReadSize(pCube) ) pCubeEnd = pCube; else // pCube is the first cube in the new size group break; } // if we could not find the next size group // the containment check is finished if ( pCube == NULL ) break; // otherwise, pCubeBeg/pCubeEnd are the first/last cubes of the group // go through all the cubes between pCubeBeg and pCubeEnd, inclusive, // and for each of them, try removing cubes after pCubeEnd Mvc_CoverForEachCubeStart( pCubeBeg, pCubeLarge ) { pPrev = pCubeEnd; Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pCubeEnd), pCube, pCube2 ) { // check containment Mvc_CubeBitNotImpl( Result, pCube, pCubeLarge ); if ( !Result ) { // pCubeLarge implies pCube - remove pCube Mvc_CoverDeleteCube( pCover, pPrev, pCube ); Mvc_CubeFree( pCover, pCube ); // don't update the previous cube } else { // update the previous cube pPrev = pCube; } } // quit, if the main cube was the last one of this size if ( pCubeLarge == pCubeEnd ) break; } // set the beginning of the next group pCubeBeg = Mvc_CubeReadNext(pCubeEnd); } while ( pCubeBeg ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcCover.c000066400000000000000000000151121300674244400235040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcCover.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Basic procedures to manipulate unate cube covers.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcCover.c,v 1.5 2003/04/09 18:02:05 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits ) { Mvc_Cover_t * p; int nBitsInUnsigned; nBitsInUnsigned = 8 * sizeof(Mvc_CubeWord_t); #ifdef USE_SYSTEM_MEMORY_MANAGEMENT p = (Mvc_Cover_t *)ABC_ALLOC( char, sizeof(Mvc_Cover_t) ); #else p = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( pMem->pManC ); #endif p->pMem = pMem; p->nBits = nBits; p->nWords = nBits / nBitsInUnsigned + (int)(nBits % nBitsInUnsigned > 0); p->nUnused = p->nWords * nBitsInUnsigned - p->nBits; p->lCubes.nItems = 0; p->lCubes.pHead = NULL; p->lCubes.pTail = NULL; p->nCubesAlloc = 0; p->pCubes = NULL; p->pMask = NULL; p->pLits = NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * p ) { Mvc_Cover_t * pCover; #ifdef USE_SYSTEM_MEMORY_MANAGEMENT pCover = (Mvc_Cover_t *)ABC_ALLOC( char, sizeof(Mvc_Cover_t) ); #else pCover = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( p->pMem->pManC ); #endif pCover->pMem = p->pMem; pCover->nBits = p->nBits; pCover->nWords = p->nWords; pCover->nUnused = p->nUnused; pCover->lCubes.nItems = 0; pCover->lCubes.pHead = NULL; pCover->lCubes.pTail = NULL; pCover->nCubesAlloc = 0; pCover->pCubes = NULL; pCover->pMask = NULL; pCover->pLits = NULL; return pCover; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * p ) { Mvc_Cover_t * pCover; Mvc_Cube_t * pCube, * pCubeCopy; // clone the cover pCover = Mvc_CoverClone( p ); // copy the cube list Mvc_CoverForEachCube( p, pCube ) { pCubeCopy = Mvc_CubeDup( p, pCube ); Mvc_CoverAddCubeTail( pCover, pCubeCopy ); } return pCover; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverFree( Mvc_Cover_t * p ) { Mvc_Cube_t * pCube, * pCube2; // recycle cube list Mvc_CoverForEachCubeSafe( p, pCube, pCube2 ) Mvc_CubeFree( p, pCube ); // recycle other pointers Mvc_CubeFree( p, p->pMask ); MEM_FREE( p->pMem, Mvc_Cube_t *, p->nCubesAlloc, p->pCubes ); MEM_FREE( p->pMem, int, p->nBits, p->pLits ); #ifdef USE_SYSTEM_MEMORY_MANAGEMENT ABC_FREE( p ); #else Extra_MmFixedEntryRecycle( p->pMem->pManC, (char *)p ); #endif } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover ) { if ( pCover->pMask == NULL ) pCover->pMask = Mvc_CubeAlloc( pCover ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover ) { if ( pCover->pLits == NULL ) pCover->pLits = MEM_ALLOC( pCover->pMem, int, pCover->nBits ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover ) { if ( pCover->nCubesAlloc < pCover->lCubes.nItems ) { if ( pCover->nCubesAlloc > 0 ) MEM_FREE( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc, pCover->pCubes ); pCover->nCubesAlloc = pCover->lCubes.nItems; pCover->pCubes = MEM_ALLOC( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover ) { Mvc_CubeFree( pCover, pCover->pMask ); pCover->pMask = NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover ) { if ( pCover->pLits ) { MEM_FREE( pCover->pMem, int, pCover->nBits, pCover->pLits ); pCover->pLits = NULL; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcCube.c000066400000000000000000000113261300674244400233070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcCube.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Manipulating unate cubes.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcCube.c,v 1.4 2003/04/03 06:31:49 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; assert( pCover->nWords >= 0 ); // allocate the cube #ifdef USE_SYSTEM_MEMORY_MANAGEMENT if ( pCover->nWords == 0 ) pCube = (Mvc_Cube_t *)ABC_ALLOC( char, sizeof(Mvc_Cube_t) ); else pCube = (Mvc_Cube_t *)ABC_ALLOC( char, sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) ); #else switch( pCover->nWords ) { case 0: case 1: pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan1 ); break; case 2: pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan2 ); break; case 3: case 4: pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan4 ); break; default: pCube = (Mvc_Cube_t *)ABC_ALLOC( char, sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) ); break; } #endif // set the parameters charactering this cube if ( pCover->nWords == 0 ) pCube->iLast = pCover->nWords; else pCube->iLast = pCover->nWords - 1; pCube->nUnused = pCover->nUnused; return pCube; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { Mvc_Cube_t * pCubeCopy; pCubeCopy = Mvc_CubeAlloc( pCover ); Mvc_CubeBitCopy( pCubeCopy, pCube ); return pCubeCopy; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { if ( pCube == NULL ) return; // verify the parameters charactering this cube assert( pCube->iLast == 0 || ((int)pCube->iLast) == pCover->nWords - 1 ); assert( ((int)pCube->nUnused) == pCover->nUnused ); // deallocate the cube #ifdef USE_SYSTEM_MEMORY_MANAGEMENT ABC_FREE( pCube ); #else switch( pCover->nWords ) { case 0: case 1: Extra_MmFixedEntryRecycle( pCover->pMem->pMan1, (char *)pCube ); break; case 2: Extra_MmFixedEntryRecycle( pCover->pMem->pMan2, (char *)pCube ); break; case 3: case 4: Extra_MmFixedEntryRecycle( pCover->pMem->pMan4, (char *)pCube ); break; default: ABC_FREE( pCube ); break; } #endif } /**Function************************************************************* Synopsis [Removes the don't-care variable from the cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube ) { unsigned Mask; int i; for ( i = Mvc_CubeReadLast(pCube); i >= 0; i-- ) { // detect those variables that are different (not DCs) Mask = (pCube->pData[i] ^ (pCube->pData[i] >> 1)) & BITS_DISJOINT; // create the mask of all that are different Mask |= (Mask << 1); // remove other bits from the set pCube->pData[i] &= Mask; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcDivide.c000066400000000000000000000330021300674244400236300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcDivide.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Procedures for algebraic division.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcDivide.c,v 1.5 2003/04/26 20:41:36 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem ); int s_fVerbose = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) { // check the number of cubes if ( Mvc_CoverReadCubeNum( pCover ) < Mvc_CoverReadCubeNum( pDiv ) ) { *ppQuo = NULL; *ppRem = NULL; return; } // make sure that support of pCover contains that of pDiv if ( !Mvc_CoverCheckSuppContainment( pCover, pDiv ) ) { *ppQuo = NULL; *ppRem = NULL; return; } // perform the general division Mvc_CoverDivideInternal( pCover, pDiv, ppQuo, ppRem ); } /**Function************************************************************* Synopsis [Merge the cubes inside the groups.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) { Mvc_Cover_t * pQuo, * pRem; Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy; Mvc_Cube_t * pCube1, * pCube2; int * pGroups, nGroups; // the cube groups int nCubesC, nCubesD, nMerges, iCubeC, iCubeD; int iMerge = -1; // Suppress "might be used uninitialized" int fSkipG, GroupSize, g, c, RetValue; int nCubes; // get cover sizes nCubesD = Mvc_CoverReadCubeNum( pDiv ); nCubesC = Mvc_CoverReadCubeNum( pCover ); // check trivial cases if ( nCubesD == 1 ) { if ( Mvc_CoverIsOneLiteral( pDiv ) ) Mvc_CoverDivideByLiteral( pCover, pDiv, ppQuo, ppRem ); else Mvc_CoverDivideByCube( pCover, pDiv, ppQuo, ppRem ); return; } // create the divisor and the remainder pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); // get the support of the divisor Mvc_CoverAllocateMask( pDiv ); Mvc_CoverSupport( pDiv, pDiv->pMask ); // sort the cubes of the divisor Mvc_CoverSort( pDiv, NULL, Mvc_CubeCompareInt ); // sort the cubes of the cover Mvc_CoverSort( pCover, pDiv->pMask, Mvc_CubeCompareIntOutsideAndUnderMask ); // allocate storage for cube groups pGroups = MEM_ALLOC( pCover->pMem, int, nCubesC + 1 ); // mask contains variables in the support of Div // split the cubes into groups using the mask Mvc_CoverList2Array( pCover ); Mvc_CoverList2Array( pDiv ); pGroups[0] = 0; nGroups = 1; for ( c = 1; c < nCubesC; c++ ) { // get the cubes pCube1 = pCover->pCubes[c-1]; pCube2 = pCover->pCubes[c ]; // compare the cubes Mvc_CubeBitEqualOutsideMask( RetValue, pCube1, pCube2, pDiv->pMask ); if ( !RetValue ) pGroups[nGroups++] = c; } // finish off the last group pGroups[nGroups] = nCubesC; // consider each group separately and decide // whether it can produce a quotient cube nCubes = 0; for ( g = 0; g < nGroups; g++ ) { // if the group has less than nCubesD cubes, // there is no way it can produce the quotient cube // copy the cubes to the remainder GroupSize = pGroups[g+1] - pGroups[g]; if ( GroupSize < nCubesD ) { for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) { pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] ); Mvc_CoverAddCubeTail( pRem, pCubeCopy ); nCubes++; } continue; } // mark the cubes as those that should be added to the remainder for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) Mvc_CubeSetSize( pCover->pCubes[c], 1 ); // go through the cubes in the group and at the same time // go through the cubes in the divisor iCubeD = 0; iCubeC = 0; pCubeD = pDiv->pCubes[iCubeD++]; pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; fSkipG = 0; nMerges = 0; while ( 1 ) { // compare the topmost cubes in F and in D RetValue = Mvc_CubeCompareIntUnderMask( pCubeC, pCubeD, pDiv->pMask ); // cube are ordered in increasing order of their int value if ( RetValue == -1 ) // pCubeC is above pCubeD { // cube in C should be added to the remainder // check that there is enough cubes in the group if ( GroupSize - iCubeC < nCubesD - nMerges ) { fSkipG = 1; break; } // get the next cube in the cover pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; continue; } if ( RetValue == 1 ) // pCubeD is above pCubeC { // given cube in D does not have a corresponding cube in the cover fSkipG = 1; break; } // mark the cube as the one that should NOT be added to the remainder Mvc_CubeSetSize( pCubeC, 0 ); // remember this merged cube iMerge = iCubeC-1; nMerges++; // stop if we considered the last cube of the group if ( iCubeD == nCubesD ) break; // advance the cube of the divisor assert( iCubeD < nCubesD ); pCubeD = pDiv->pCubes[iCubeD++]; // advance the cube of the group assert( pGroups[g]+iCubeC < nCubesC ); pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; } if ( fSkipG ) { // the group has failed, add all the cubes to the remainder for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) { pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] ); Mvc_CoverAddCubeTail( pRem, pCubeCopy ); nCubes++; } continue; } // the group has worked, add left-over cubes to the remainder for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) { pCubeC = pCover->pCubes[c]; if ( Mvc_CubeReadSize(pCubeC) ) { pCubeCopy = Mvc_CubeDup( pRem, pCubeC ); Mvc_CoverAddCubeTail( pRem, pCubeCopy ); nCubes++; } } // create the quotient cube pCube1 = Mvc_CubeAlloc( pQuo ); Mvc_CubeBitSharp( pCube1, pCover->pCubes[pGroups[g]+iMerge], pDiv->pMask ); // add the cube to the quotient Mvc_CoverAddCubeTail( pQuo, pCube1 ); nCubes += nCubesD; } assert( nCubes == nCubesC ); // deallocate the memory MEM_FREE( pCover->pMem, int, nCubesC + 1, pGroups ); // return the results *ppRem = pRem; *ppQuo = pQuo; // Mvc_CoverVerifyDivision( pCover, pDiv, pQuo, pRem ); } /**Function************************************************************* Synopsis [Divides the cover by a cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) { Mvc_Cover_t * pQuo, * pRem; Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy; int CompResult; // get the only cube of D assert( Mvc_CoverReadCubeNum(pDiv) == 1 ); // start the quotient and the remainder pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); // get the first and only cube of the divisor pCubeD = Mvc_CoverReadCubeHead( pDiv ); // iterate through the cubes in the cover Mvc_CoverForEachCube( pCover, pCubeC ) { // check the containment of literals from pCubeD in pCube Mvc_Cube2BitNotImpl( CompResult, pCubeD, pCubeC ); if ( !CompResult ) { // this cube belongs to the quotient // alloc the cube pCubeCopy = Mvc_CubeAlloc( pQuo ); // clean the support of D Mvc_CubeBitSharp( pCubeCopy, pCubeC, pCubeD ); // add the cube to the quotient Mvc_CoverAddCubeTail( pQuo, pCubeCopy ); } else { // copy the cube pCubeCopy = Mvc_CubeDup( pRem, pCubeC ); // add the cube to the remainder Mvc_CoverAddCubeTail( pRem, pCubeCopy ); } } // return the results *ppRem = pRem; *ppQuo = pQuo; } /**Function************************************************************* Synopsis [Divides the cover by a literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) { Mvc_Cover_t * pQuo, * pRem; Mvc_Cube_t * pCubeC, * pCubeCopy; int iLit; // get the only cube of D assert( Mvc_CoverReadCubeNum(pDiv) == 1 ); // start the quotient and the remainder pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); // get the first and only literal in the divisor cube iLit = Mvc_CoverFirstCubeFirstLit( pDiv ); // iterate through the cubes in the cover Mvc_CoverForEachCube( pCover, pCubeC ) { // copy the cube pCubeCopy = Mvc_CubeDup( pCover, pCubeC ); // add the cube to the quotient or to the remainder depending on the literal if ( Mvc_CubeBitValue( pCubeCopy, iLit ) ) { // remove the literal Mvc_CubeBitRemove( pCubeCopy, iLit ); // add the cube ot the quotient Mvc_CoverAddCubeTail( pQuo, pCubeCopy ); } else { // add the cube ot the remainder Mvc_CoverAddCubeTail( pRem, pCubeCopy ); } } // return the results *ppRem = pRem; *ppQuo = pQuo; } /**Function************************************************************* Synopsis [Derives the quotient of division by literal.] Description [Reduces the cover to be the equal to the result of division of the given cover by the literal.] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit ) { Mvc_Cube_t * pCube, * pCube2, * pPrev; // delete those cubes that do not have this literal // remove this literal from other cubes pPrev = NULL; Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 ) { if ( Mvc_CubeBitValue( pCube, iLit ) == 0 ) { // delete the cube from the cover Mvc_CoverDeleteCube( pCover, pPrev, pCube ); Mvc_CubeFree( pCover, pCube ); // don't update the previous cube } else { // delete this literal from the cube Mvc_CubeBitRemove( pCube, iLit ); // update the previous cube pPrev = pCube; } } } /**Function************************************************************* Synopsis [Verifies that the result of algebraic division is correct.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem ) { Mvc_Cover_t * pProd; Mvc_Cover_t * pDiff; pProd = Mvc_CoverAlgebraicMultiply( pDiv, pQuo ); pDiff = Mvc_CoverAlgebraicSubtract( pCover, pProd ); if ( Mvc_CoverAlgebraicEqual( pDiff, pRem ) ) printf( "Verification OKAY!\n" ); else { printf( "Verification FAILED!\n" ); printf( "pCover:\n" ); Mvc_CoverPrint( pCover ); printf( "pDiv:\n" ); Mvc_CoverPrint( pDiv ); printf( "pRem:\n" ); Mvc_CoverPrint( pRem ); printf( "pQuo:\n" ); Mvc_CoverPrint( pQuo ); } Mvc_CoverFree( pProd ); Mvc_CoverFree( pDiff ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcDivisor.c000066400000000000000000000056711300674244400240560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcDivisor.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Procedures for compute the quick divisor.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcDivisor.c,v 1.1 2003/04/03 15:34:08 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the quick divisor of the cover.] Description [Returns NULL, if there is not divisor other than trivial.] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover ) { Mvc_Cover_t * pKernel; if ( Mvc_CoverReadCubeNum(pCover) <= 1 ) return NULL; // allocate the literal array and count literals if ( Mvc_CoverAnyLiteral( pCover, NULL ) == -1 ) return NULL; // duplicate the cover pKernel = Mvc_CoverDup(pCover); // perform the kerneling Mvc_CoverDivisorZeroKernel( pKernel ); assert( Mvc_CoverReadCubeNum(pKernel) ); return pKernel; } /**Function************************************************************* Synopsis [Computes a level-zero kernel.] Description [Modifies the cover to contain one level-zero kernel.] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover ) { int iLit; // find any literal that occurs at least two times // iLit = Mvc_CoverAnyLiteral( pCover, NULL ); iLit = Mvc_CoverWorstLiteral( pCover, NULL ); // iLit = Mvc_CoverBestLiteral( pCover, NULL ); if ( iLit == -1 ) return; // derive the cube-free quotient Mvc_CoverDivideByLiteralQuo( pCover, iLit ); // the same cover Mvc_CoverMakeCubeFree( pCover ); // the same cover // call recursively Mvc_CoverDivisorZeroKernel( pCover ); // the same cover } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcList.c000066400000000000000000000216401300674244400233440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcList.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Manipulating list of cubes in the cover.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcList.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube ) { if ( pList->pHead == NULL ) { Mvc_CubeSetNext( pCube, NULL ); pList->pHead = pCube; pList->pTail = pCube; } else { Mvc_CubeSetNext( pCube, pList->pHead ); pList->pHead = pCube; } pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube ) { if ( pList->pHead == NULL ) pList->pHead = pCube; else Mvc_CubeSetNext( pList->pTail, pCube ); pList->pTail = pCube; Mvc_CubeSetNext( pCube, NULL ); pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ) { if ( pPrev == NULL ) // deleting the head cube pList->pHead = Mvc_CubeReadNext(pCube); else pPrev->pNext = pCube->pNext; if ( pList->pTail == pCube ) // deleting the tail cube { assert( Mvc_CubeReadNext(pCube) == NULL ); pList->pTail = pPrev; } pList->nItems--; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { Mvc_List_t * pList = &pCover->lCubes; if ( pList->pHead == NULL ) { Mvc_CubeSetNext( pCube, NULL ); pList->pHead = pCube; pList->pTail = pCube; } else { Mvc_CubeSetNext( pCube, pList->pHead ); pList->pHead = pCube; } pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { Mvc_List_t * pList = &pCover->lCubes; if ( pList->pHead == NULL ) pList->pHead = pCube; else Mvc_CubeSetNext( pList->pTail, pCube ); pList->pTail = pCube; Mvc_CubeSetNext( pCube, NULL ); pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ) { Mvc_List_t * pList = &pCover->lCubes; if ( pPrev == NULL ) // deleting the head cube pList->pHead = Mvc_CubeReadNext(pCube); else pPrev->pNext = pCube->pNext; if ( pList->pTail == pCube ) // deleting the tail cube { assert( Mvc_CubeReadNext(pCube) == NULL ); pList->pTail = pPrev; } pList->nItems--; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { Mvc_Cube_t * pCubeNew; pCubeNew = Mvc_CubeAlloc( pCover ); Mvc_CubeBitCopy( pCubeNew, pCube ); Mvc_CoverAddCubeHead( pCover, pCubeNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { Mvc_Cube_t * pCubeNew; // copy the cube as part of this cover pCubeNew = Mvc_CubeAlloc( pCover ); Mvc_CubeBitCopy( pCubeNew, pCube ); // clean the last bits of the new cube // pCubeNew->pData[pCubeNew->iLast] &= (BITS_FULL >> pCubeNew->nUnused); // add the cube at the end Mvc_CoverAddCubeTail( pCover, pCubeNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { // int iBit, Value; // assert( pCover->pLits ); // Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) // if ( Value ) // pCover->pLits[iBit] += Value; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { // int iBit, Value; // assert( pCover->pLits ); // Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) // if ( Value ) // pCover->pLits[iBit] -= Value; } /**Function************************************************************* Synopsis [Transfers the cubes from the list into the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverList2Array( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; int Counter; // resize storage if necessary Mvc_CoverAllocateArrayCubes( pCover ); // iterate through the cubes Counter = 0; Mvc_CoverForEachCube( pCover, pCube ) pCover->pCubes[ Counter++ ] = pCube; assert( Counter == Mvc_CoverReadCubeNum(pCover) ); } /**Function************************************************************* Synopsis [Transfers the cubes from the array into list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverArray2List( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; int nCubes, i; assert( pCover->pCubes ); nCubes = Mvc_CoverReadCubeNum(pCover); if ( nCubes == 0 ) return; if ( nCubes == 1 ) { pCube = pCover->pCubes[0]; pCube->pNext = NULL; pCover->lCubes.pHead = pCover->lCubes.pTail = pCube; return; } // set up the first cube pCube = pCover->pCubes[0]; pCover->lCubes.pHead = pCube; // set up the last cube pCube = pCover->pCubes[nCubes-1]; pCube->pNext = NULL; pCover->lCubes.pTail = pCube; // link all cubes starting from the first one for ( i = 0; i < nCubes - 1; i++ ) pCover->pCubes[i]->pNext = pCover->pCubes[i+1]; } /**Function************************************************************* Synopsis [Returns the tail of the linked list given by the head.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead ) { Mvc_Cube_t * pCube, * pTail; for ( pTail = pCube = pHead; pCube; pTail = pCube, pCube = Mvc_CubeReadNext(pCube) ); return pTail; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcLits.c000066400000000000000000000227541300674244400233530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcLits.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Literal counting/updating procedures.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcLits.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the any literal that occurs more than once.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) { Mvc_Cube_t * pCube; int nWord, nBit, i; int nLitsCur; int fUseFirst = 0; // go through each literal if ( fUseFirst ) { for ( i = 0; i < pCover->nBits; i++ ) if ( !pMask || Mvc_CubeBitValue(pMask,i) ) { // get the word and bit of this literal nWord = Mvc_CubeWhichWord(i); nBit = Mvc_CubeWhichBit(i); // go through all the cubes nLitsCur = 0; Mvc_CoverForEachCube( pCover, pCube ) if ( pCube->pData[nWord] & (1< 1 ) return i; } } } else { for ( i = pCover->nBits - 1; i >=0; i-- ) if ( !pMask || Mvc_CubeBitValue(pMask,i) ) { // get the word and bit of this literal nWord = Mvc_CubeWhichWord(i); nBit = Mvc_CubeWhichBit(i); // go through all the cubes nLitsCur = 0; Mvc_CoverForEachCube( pCover, pCube ) if ( pCube->pData[nWord] & (1< 1 ) return i; } } } return -1; } /**Function************************************************************* Synopsis [Find the most often occurring literal.] Description [Find the most often occurring literal among those that occur more than once.] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) { Mvc_Cube_t * pCube; int nWord, nBit; int i, iMax, nLitsMax, nLitsCur; int fUseFirst = 1; // go through each literal iMax = -1; nLitsMax = -1; for ( i = 0; i < pCover->nBits; i++ ) if ( !pMask || Mvc_CubeBitValue(pMask,i) ) { // get the word and bit of this literal nWord = Mvc_CubeWhichWord(i); nBit = Mvc_CubeWhichBit(i); // go through all the cubes nLitsCur = 0; Mvc_CoverForEachCube( pCover, pCube ) if ( pCube->pData[nWord] & (1< 1 ) return iMax; return -1; } /**Function************************************************************* Synopsis [Find the most often occurring literal.] Description [Find the most often occurring literal among those that occur more than once.] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) { Mvc_Cube_t * pCube; int nWord, nBit; int i, iMin, nLitsMin, nLitsCur; int fUseFirst = 1; // go through each literal iMin = -1; nLitsMin = 1000000; for ( i = 0; i < pCover->nBits; i++ ) if ( !pMask || Mvc_CubeBitValue(pMask,i) ) { // get the word and bit of this literal nWord = Mvc_CubeWhichWord(i); nBit = Mvc_CubeWhichBit(i); // go through all the cubes nLitsCur = 0; Mvc_CoverForEachCube( pCover, pCube ) if ( pCube->pData[nWord] & (1< nLitsCur ) { nLitsMin = nLitsCur; iMin = i; } } else { if ( nLitsMin >= nLitsCur ) { nLitsMin = nLitsCur; iMin = i; } } } if ( nLitsMin < 1000000 ) return iMin; return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) { Mvc_Cover_t * pCoverNew; Mvc_Cube_t * pCubeNew; Mvc_Cube_t * pCubeS; int iLitBest; // create the new cover pCoverNew = Mvc_CoverClone( pCover ); // get the new cube pCubeNew = Mvc_CubeAlloc( pCoverNew ); // clean the cube Mvc_CubeBitClean( pCubeNew ); // get the first cube of pSimple assert( Mvc_CoverReadCubeNum(pSimple) == 1 ); pCubeS = Mvc_CoverReadCubeHead( pSimple ); // find the best literal among those of pCubeS iLitBest = Mvc_CoverBestLiteral( pCover, pCubeS ); // insert this literal into the cube Mvc_CubeBitInsert( pCubeNew, iLitBest ); // add the cube to the cover Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); return pCoverNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; int iBit, Value; // get the first cube pCube = Mvc_CoverReadCubeHead( pCover ); // get the first literal Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) if ( Value ) return iBit; return -1; } /**Function************************************************************* Synopsis [Returns the number of literals in the cover.] Description [Allocates storage for literal counters and fills it up using the current information.] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; int nWord, nBit; int i, CounterTot, CounterCur; // allocate/clean the storage for literals // Mvc_CoverAllocateArrayLits( pCover ); // memset( pCover->pLits, 0, pCover->nBits * sizeof(int) ); // go through each literal CounterTot = 0; for ( i = 0; i < pCover->nBits; i++ ) { // get the word and bit of this literal nWord = Mvc_CubeWhichWord(i); nBit = Mvc_CubeWhichBit(i); // go through all the cubes CounterCur = 0; Mvc_CoverForEachCube( pCover, pCube ) if ( pCube->pData[nWord] & (1< #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Manager_t * Mvc_ManagerStart() { Mvc_Manager_t * p; p = ABC_ALLOC( Mvc_Manager_t, 1 ); memset( p, 0, sizeof(Mvc_Manager_t) ); p->pMan1 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) ); p->pMan2 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) ); p->pMan4 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + 3 * sizeof(Mvc_CubeWord_t) ); p->pManC = Extra_MmFixedStart( sizeof(Mvc_Cover_t) ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_ManagerFree( Mvc_Manager_t * p ) { Extra_MmFixedStop( p->pMan1 ); Extra_MmFixedStop( p->pMan2 ); Extra_MmFixedStop( p->pMan4 ); Extra_MmFixedStop( p->pManC ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcOpAlg.c000066400000000000000000000112641300674244400234340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcOperAlg.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Miscellaneous operations on covers.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcOpAlg.c,v 1.4 2003/04/26 20:41:36 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Multiplies two disjoint-support covers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) { Mvc_Cover_t * pCover; Mvc_Cube_t * pCube1, * pCube2, * pCube; int CompResult; // covers should be the same base assert( pCover1->nBits == pCover2->nBits ); // make sure that supports do not overlap Mvc_CoverAllocateMask( pCover1 ); Mvc_CoverAllocateMask( pCover2 ); Mvc_CoverSupport( pCover1, pCover1->pMask ); Mvc_CoverSupport( pCover2, pCover2->pMask ); // check if the cubes are bit-wise disjoint Mvc_CubeBitDisjoint( CompResult, pCover1->pMask, pCover2->pMask ); if ( !CompResult ) printf( "Mvc_CoverMultiply(): Cover supports are not disjoint!\n" ); // iterate through the cubes pCover = Mvc_CoverClone( pCover1 ); Mvc_CoverForEachCube( pCover1, pCube1 ) Mvc_CoverForEachCube( pCover2, pCube2 ) { // create the product cube pCube = Mvc_CubeAlloc( pCover ); // set the product cube equal to the product of the two cubes Mvc_CubeBitOr( pCube, pCube1, pCube2 ); // add the cube to the cover Mvc_CoverAddCubeTail( pCover, pCube ); } return pCover; } /**Function************************************************************* Synopsis [Subtracts the second cover from the first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) { Mvc_Cover_t * pCover; Mvc_Cube_t * pCube1, * pCube2, * pCube; int fFound; int CompResult; // covers should be the same base assert( pCover1->nBits == pCover2->nBits ); // iterate through the cubes pCover = Mvc_CoverClone( pCover1 ); Mvc_CoverForEachCube( pCover1, pCube1 ) { fFound = 0; Mvc_CoverForEachCube( pCover2, pCube2 ) { Mvc_CubeBitEqual( CompResult, pCube1, pCube2 ); if ( CompResult ) { fFound = 1; break; } } if ( !fFound ) { // create the copy of the cube pCube = Mvc_CubeDup( pCover, pCube1 ); // add the cube copy to the cover Mvc_CoverAddCubeTail( pCover, pCube ); } } return pCover; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) { Mvc_Cube_t * pCube1, * pCube2; int fFound; int CompResult; // covers should be the same base assert( pCover1->nBits == pCover2->nBits ); // iterate through the cubes Mvc_CoverForEachCube( pCover1, pCube1 ) { fFound = 0; Mvc_CoverForEachCube( pCover2, pCube2 ) { Mvc_CubeBitEqual( CompResult, pCube1, pCube2 ); if ( CompResult ) { fFound = 1; break; } } if ( !fFound ) return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcOpBool.c000066400000000000000000000104351300674244400236230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcProc.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Various boolean procedures working with covers.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcOpBool.c,v 1.4 2003/04/16 01:55:37 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) { Mvc_Cover_t * pCover; Mvc_Cube_t * pCube, * pCubeCopy; // make sure the covers are compatible assert( pCover1->nBits == pCover2->nBits ); // clone the cover pCover = Mvc_CoverClone( pCover1 ); // create the cubes by making pair-wise products // of cubes in pCover1 and pCover2 Mvc_CoverForEachCube( pCover1, pCube ) { pCubeCopy = Mvc_CubeDup( pCover, pCube ); Mvc_CoverAddCubeTail( pCover, pCubeCopy ); } Mvc_CoverForEachCube( pCover2, pCube ) { pCubeCopy = Mvc_CubeDup( pCover, pCube ); Mvc_CoverAddCubeTail( pCover, pCubeCopy ); } return pCover; } #if 0 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) { Mvc_Cover_t * pCover; Mvc_Cube_t * pCube1, * pCube2, * pCubeCopy; // make sure the covers are compatible assert( pCover1->nBits == pCover2->nBits ); // clone the cover pCover = Mvc_CoverClone( pCover1 ); // create the cubes by making pair-wise products // of cubes in pCover1 and pCover2 Mvc_CoverForEachCube( pCover1, pCube1 ) { Mvc_CoverForEachCube( pCover2, pCube2 ) { if ( Mvc_CoverDist0Cubes( p, pCube1, pCube2 ) ) { pCubeCopy = Mvc_CubeAlloc( pCover ); Mvc_CubeBitAnd( pCubeCopy, pCube1, pCube2 ); Mvc_CoverAddCubeTail( pCover, pCubeCopy ); } } // if the number of cubes in the new cover is too large // try compressing them if ( Mvc_CoverReadCubeNum( pCover ) > 500 ) Mvc_CoverContain( pCover ); } return pCover; } /**Function************************************************************* Synopsis [Returns 1 if the two covers are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) { Mvc_Cover_t * pSharp; pSharp = Mvc_CoverSharp( p, pCover1, pCover2 ); if ( Mvc_CoverReadCubeNum( pSharp ) ) { Mvc_CoverContain( pSharp ); printf( "Sharp \n" ); Mvc_CoverPrint( pSharp ); Mvc_CoverFree( pSharp ); return 0; } Mvc_CoverFree( pSharp ); pSharp = Mvc_CoverSharp( p, pCover2, pCover1 ); if ( Mvc_CoverReadCubeNum( pSharp ) ) { Mvc_CoverContain( pSharp ); printf( "Sharp \n" ); Mvc_CoverPrint( pSharp ); Mvc_CoverFree( pSharp ); return 0; } Mvc_CoverFree( pSharp ); return 1; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcPrint.c000066400000000000000000000132671300674244400235330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcPrint.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Printing cubes and covers.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcPrint.c,v 1.6 2003/04/09 18:02:06 alanmi Exp $] ***********************************************************************/ #include "mvc.h" //#include "vm.h" //#include "vmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverPrint( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; int i; // print general statistics printf( "The cover contains %d cubes (%d bits and %d words)\n", pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); // iterate through the cubes Mvc_CoverForEachCube( pCover, pCube ) Mvc_CubePrint( pCover, pCube ); if ( pCover->pLits ) { for ( i = 0; i < pCover->nBits; i++ ) printf( " %d", pCover->pLits[i] ); printf( "\n" ); } printf( "End of cover printout\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { int iBit, Value; // iterate through the literals // printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) printf( "%c", '0' + Value ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverPrintBinary( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; int i; // print general statistics printf( "The cover contains %d cubes (%d bits and %d words)\n", pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); // iterate through the cubes Mvc_CoverForEachCube( pCover, pCube ) Mvc_CubePrintBinary( pCover, pCube ); if ( pCover->pLits ) { for ( i = 0; i < pCover->nBits; i++ ) printf( " %d", pCover->pLits[i] ); printf( "\n" ); } printf( "End of cover printout\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { int iVar, Value; // iterate through the literals // printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); Mvc_CubeForEachVarValue( pCover, pCube, iVar, Value ) { assert( Value != 0 ); if ( Value == 3 ) printf( "-" ); else if ( Value == 1 ) printf( "0" ); else printf( "1" ); } printf( "\n" ); } #if 0 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; int i; // print general statistics printf( "The cover contains %d cubes (%d bits and %d words)\n", pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); // iterate through the cubes Mvc_CoverForEachCube( pCover, pCube ) Mvc_CubePrintMv( pData, pCover, pCube ); if ( pCover->pLits ) { for ( i = 0; i < pCover->nBits; i++ ) printf( " %d", pCover->pLits[i] ); printf( "\n" ); } printf( "End of cover printout\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { int iLit, iVar; // iterate through the literals printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); iVar = 0; for ( iLit = 0; iLit < pData->pVm->nValuesIn; iLit++ ) { if ( iLit == pData->pVm->pValuesFirst[iVar+1] ) { printf( " " ); iVar++; } if ( Mvc_CubeBitValue( pCube, iLit ) ) printf( "%c", '0' + iLit - pData->pVm->pValuesFirst[iVar] ); else printf( "-" ); } printf( "\n" ); } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcSort.c000066400000000000000000000107241300674244400233610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcSort.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Sorting cubes in the cover with the mask.] Author [MVSIS Group] Affiliation [uC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcSort.c,v 1.5 2003/04/27 01:03:45 wjiang Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); //////////////////////////////////////////////////////////////////////// /// FuNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sorts cubes using the given cost function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) { Mvc_Cube_t * pHead; int nCubes; // one cube does not need sorting nCubes = Mvc_CoverReadCubeNum(pCover); if ( nCubes <= 1 ) return; // sort the cubes pHead = Mvc_CoverSort_rec( Mvc_CoverReadCubeHead(pCover), nCubes, pMask, pCompareFunc ); // insert the sorted list into the cover Mvc_CoverSetCubeHead( pCover, pHead ); Mvc_CoverSetCubeTail( pCover, Mvc_ListGetTailFromHead(pHead) ); // make sure that the list is sorted in the increasing order assert( pCompareFunc( Mvc_CoverReadCubeHead(pCover), Mvc_CoverReadCubeTail(pCover), pMask ) <= 0 ); } /**Function************************************************************* Synopsis [Recursive part of Mvc_CoverSort()] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) { Mvc_Cube_t * pList1, * pList2; int nItems1, nItems2, i; // trivial case if ( nItems == 1 ) { Mvc_CubeSetNext( pList, NULL ); return pList; } // select the new sizes nItems1 = nItems/2; nItems2 = nItems - nItems1; // set the new beginnings pList1 = pList2 = pList; for ( i = 0; i < nItems1; i++ ) pList2 = Mvc_CubeReadNext( pList2 ); // solve recursively pList1 = Mvc_CoverSort_rec( pList1, nItems1, pMask, pCompareFunc ); pList2 = Mvc_CoverSort_rec( pList2, nItems2, pMask, pCompareFunc ); // merge return Mvc_CoverSortMerge( pList1, pList2, pMask, pCompareFunc ); } /**Function************************************************************* Synopsis [Merges two NULL-terminated linked lists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) { Mvc_Cube_t * pList = NULL, ** ppTail = &pList; Mvc_Cube_t * pCube; while ( pList1 && pList2 ) { if ( pCompareFunc( pList1, pList2, pMask ) < 0 ) { pCube = pList1; pList1 = Mvc_CubeReadNext(pList1); } else { pCube = pList2; pList2 = Mvc_CubeReadNext(pList2); } *ppTail = pCube; ppTail = Mvc_CubeReadNextP(pCube); } *ppTail = pList1? pList1: pList2; return pList; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/mvc/mvcUtils.c000066400000000000000000000644501300674244400235370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mvcUtils.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Various cover handling utilities.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: mvcUtils.c,v 1.7 2003/04/26 20:41:36 alanmi Exp $] ***********************************************************************/ #include "mvc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; static void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, int iColOld, int iColNew ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ) { Mvc_Cube_t * pCube; // clean the support Mvc_CubeBitClean( pSupp ); // collect the support Mvc_CoverForEachCube( pCover, pCube ) Mvc_CubeBitOr( pSupp, pSupp, pCube ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverSupportAnd( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ) { Mvc_Cube_t * pCube; // clean the support Mvc_CubeBitFill( pSupp ); // collect the support Mvc_CoverForEachCube( pCover, pCube ) Mvc_CubeBitAnd( pSupp, pSupp, pCube ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pSupp; int Counter, i, v0, v1; // compute the support pSupp = Mvc_CubeAlloc( pCover ); Mvc_CoverSupportAnd( pCover, pSupp ); Counter = pCover->nBits/2; for ( i = 0; i < pCover->nBits/2; i++ ) { v0 = Mvc_CubeBitValue( pSupp, 2*i ); v1 = Mvc_CubeBitValue( pSupp, 2*i+1 ); if ( v0 && v1 ) Counter--; } Mvc_CubeFree( pCover, pSupp ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar ) { Mvc_Cube_t * pSupp; int RetValue, v0, v1; // compute the support pSupp = Mvc_CubeAlloc( pCover ); Mvc_CoverSupportAnd( pCover, pSupp ); v0 = Mvc_CubeBitValue( pSupp, 2*iVar ); v1 = Mvc_CubeBitValue( pSupp, 2*iVar+1 ); RetValue = (int)( !v0 || !v1 ); Mvc_CubeFree( pCover, pSupp ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube ) { Mvc_Cube_t * pCube; // clean the support Mvc_CubeBitFill( pComCube ); // collect the support Mvc_CoverForEachCube( pCover, pCube ) Mvc_CubeBitAnd( pComCube, pComCube, pCube ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover ) { int Result; // get the common cube Mvc_CoverAllocateMask( pCover ); Mvc_CoverCommonCube( pCover, pCover->pMask ); // check whether the common cube is empty Mvc_CubeBitEmpty( Result, pCover->pMask ); return Result; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; // get the common cube Mvc_CoverAllocateMask( pCover ); Mvc_CoverCommonCube( pCover, pCover->pMask ); // remove this cube from the cubes in the cover Mvc_CoverForEachCube( pCover, pCube ) Mvc_CubeBitSharp( pCube, pCube, pCover->pMask ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover ) { Mvc_Cover_t * pRes; Mvc_Cube_t * pCube; // create the new cover pRes = Mvc_CoverClone( pCover ); // get the new cube pCube = Mvc_CubeAlloc( pRes ); // get the common cube Mvc_CoverCommonCube( pCover, pCube ); // add the cube to the cover Mvc_CoverAddCubeTail( pRes, pCube ); return pRes; } /**Function************************************************************* Synopsis [Returns 1 if the support of cover2 is contained in the support of cover1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) { int Result; assert( pCover1->nBits == pCover2->nBits ); // set the supports Mvc_CoverAllocateMask( pCover1 ); Mvc_CoverSupport( pCover1, pCover1->pMask ); Mvc_CoverAllocateMask( pCover2 ); Mvc_CoverSupport( pCover2, pCover2->pMask ); // check the containment Mvc_CubeBitNotImpl( Result, pCover2->pMask, pCover1->pMask ); return !Result; } /**Function************************************************************* Synopsis [Counts the cube sizes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover ) { Mvc_Cube_t * pCube; unsigned char * pByte, * pByteStart, * pByteStop; int nBytes, nOnes; // get the number of unsigned chars in the cube's bit strings nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); // iterate through the cubes Mvc_CoverForEachCube( pCover, pCube ) { // clean the counter of ones nOnes = 0; // set the starting and stopping positions pByteStart = (unsigned char *)pCube->pData; pByteStop = pByteStart + nBytes; // iterate through the positions for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) nOnes += bit_count[*pByte]; // set the nOnes Mvc_CubeSetSize( pCube, nOnes ); } return 1; } /**Function************************************************************* Synopsis [Counts the cube sizes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube ) { unsigned char * pByte, * pByteStart, * pByteStop; int nOnes, nBytes, nBits; // get the number of unsigned chars in the cube's bit strings nBits = (pCube->iLast + 1) * sizeof(Mvc_CubeWord_t) * 8 - pCube->nUnused; nBytes = nBits / (8 * sizeof(unsigned char)) + (int)(nBits % (8 * sizeof(unsigned char)) > 0); // clean the counter of ones nOnes = 0; // set the starting and stopping positions pByteStart = (unsigned char *)pCube->pData; pByteStop = pByteStart + nBytes; // iterate through the positions for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) nOnes += bit_count[*pByte]; return nOnes; } /**Function************************************************************* Synopsis [Counts the differences in each cube pair in the cover.] Description [Takes the cover (pCover) and the array where the diff counters go (pDiffs). The array pDiffs should have as many entries as there are different pairs of cubes in the cover: n(n-1)/2. Fills out the array pDiffs with the following info: For each cube pair, included in the array is the number of literals in both cubes after they are made cube ABC_FREE.] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] ) { Mvc_Cube_t * pCube1; Mvc_Cube_t * pCube2; Mvc_Cube_t * pMask; unsigned char * pByte, * pByteStart, * pByteStop; int nBytes, nOnes; int nCubePairs; // allocate a temporary mask pMask = Mvc_CubeAlloc( pCover ); // get the number of unsigned chars in the cube's bit strings nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); // iterate through the cubes nCubePairs = 0; Mvc_CoverForEachCube( pCover, pCube1 ) { Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCube1), pCube2 ) { // find the bit-wise exor of cubes Mvc_CubeBitExor( pMask, pCube1, pCube2 ); // set the starting and stopping positions pByteStart = (unsigned char *)pMask->pData; pByteStop = pByteStart + nBytes; // clean the counter of ones nOnes = 0; // iterate through the positions for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) nOnes += bit_count[*pByte]; // set the nOnes pDiffs[nCubePairs++] = nOnes; } } // deallocate the mask Mvc_CubeFree( pCover, pMask ); return 1; } /**Function************************************************************* Synopsis [Creates a new cover containing some literals of the old cover.] Description [Creates the new cover containing the given number (nVarsRem) literals of the old cover. All the bits of the new cover are initialized to "1". The selected bits from the old cover are copied on top. The numbers of the selected bits to copy are given in the array pVarsRem. The i-set entry in this array is the index of the bit in the old cover which goes to the i-th place in the new cover. If the i-th entry in pVarsRem is -1, it means that the i-th bit does not change (remains composed of all 1's). This is a useful feature to speed up remapping covers, which are known to depend only on a subset of input variables.] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * p, int * pVarsRem, int nVarsRem ) { Mvc_Cover_t * pCover; Mvc_Cube_t * pCube, * pCubeCopy; int i; // clone the cover pCover = Mvc_CoverAlloc( p->pMem, nVarsRem ); // copy the cube list Mvc_CoverForEachCube( p, pCube ) { pCubeCopy = Mvc_CubeAlloc( pCover ); //Mvc_CubeBitClean( pCubeCopy ); //changed by wjiang Mvc_CubeBitFill( pCubeCopy ); //changed by wjiang Mvc_CoverAddCubeTail( pCover, pCubeCopy ); } // copy the corresponding columns for ( i = 0; i < nVarsRem; i++ ) { if (pVarsRem[i] < 0) continue; //added by wjiang assert( pVarsRem[i] >= 0 && pVarsRem[i] < p->nBits ); Mvc_CoverCopyColumn( p, pCover, pVarsRem[i], i ); } return pCover; } /**Function************************************************************* Synopsis [Copies a column from the old cover to the new cover.] Description [Copies the column (iColOld) of the old cover (pCoverOld) into the column (iColNew) of the new cover (pCoverNew). Assumes that the number of cubes is the same in both covers. Makes no assuptions about the current contents of the column in the new cover.] SideEffects [] SeeAlso [] ***********************************************************************/ void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, int iColOld, int iColNew ) { Mvc_Cube_t * pCubeOld, * pCubeNew; int iWordOld, iWordNew, iBitOld, iBitNew; assert( Mvc_CoverReadCubeNum(pCoverOld) == Mvc_CoverReadCubeNum(pCoverNew) ); // get the place of the old and new columns iWordOld = Mvc_CubeWhichWord(iColOld); iBitOld = Mvc_CubeWhichBit(iColOld); iWordNew = Mvc_CubeWhichWord(iColNew); iBitNew = Mvc_CubeWhichBit(iColNew); // go through the cubes of both covers pCubeNew = Mvc_CoverReadCubeHead(pCoverNew); Mvc_CoverForEachCube( pCoverOld, pCubeOld ) { if ( pCubeOld->pData[iWordOld] & (1<pData[iWordNew] |= (1<pData[iWordNew] &= ~(1<pVm, iVar); nValues = Vm_VarMapReadValues(pData->pVm, iVar); ppCofs = ABC_ALLOC( Mvc_Cover_t *, nValues + 1 ); for ( i = 0; i <= nValues; i++ ) ppCofs[i] = Mvc_CoverClone( pCover ); // go through the cubes Mvc_CoverForEachCube( pCover, pCube ) { // if the literal if a full literal, add it to last "cofactor" Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] ); if ( Res ) { pCubeNew = Mvc_CubeDup(pCover, pCube); Mvc_CoverAddCubeTail( ppCofs[nValues], pCubeNew ); continue; } // otherwise, add it to separate values for ( i = 0; i < nValues; i++ ) if ( Mvc_CubeBitValue( pCube, iValueFirst + i ) ) { pCubeNew = Mvc_CubeDup(pCover, pCube); Mvc_CubeBitOr( pCubeNew, pCubeNew, pData->ppMasks[iVar] ); Mvc_CoverAddCubeTail( ppCofs[i], pCubeNew ); } } return ppCofs; } /**Function************************************************************* Synopsis [Count the cubes with non-trivial literals with the given value.] Description [The data and the cover are given (pData, pCover). Also given are the variable number and the number of a value of this variable. This procedure returns the number of cubes having a non-trivial literal of this variable that have the given value present.] SideEffects [] SeeAlso [] ***********************************************************************/ int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue ) { Mvc_Cube_t * pCube; int iValueFirst, Res, Counter; Counter = 0; iValueFirst = Vm_VarMapReadValuesFirst( pData->pVm, iVar ); Mvc_CoverForEachCube( pCover, pCube ) { // check if the given literal is the full literal Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] ); if ( Res ) continue; // this literal is not a full literal; check if it has this value Counter += Mvc_CubeBitValue( pCube, iValueFirst + iValue ); } return Counter; } /**Function************************************************************* Synopsis [Creates the expanded cover.] Description [The original cover is expanded by adding some variables. These variables are the additional variables in pVmNew, compared to pCvr->pVm. The resulting cover is the same as the original one, except that it contains the additional variables present as full literals in every cube.] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew ) { Mvc_Cover_t * pCoverNew; Mvc_Cube_t * pCube, * pCubeNew; int i, iLast, iLastNew; // create the new cover pCoverNew = Mvc_CoverAlloc( pCover->pMem, Vm_VarMapReadValuesInNum(pVmNew) ); // get the cube composed of extra bits Mvc_CoverAllocateMask( pCoverNew ); Mvc_CubeBitClean( pCoverNew->pMask ); for ( i = pCover->nBits; i < pCoverNew->nBits; i++ ) Mvc_CubeBitInsert( pCoverNew->pMask, i ); // get the indexes of the last words in both covers iLast = pCover->nWords? pCover->nWords - 1: 0; iLastNew = pCoverNew->nWords? pCoverNew->nWords - 1: 0; // create the cubes of the new cover Mvc_CoverForEachCube( pCover, pCube ) { pCubeNew = Mvc_CubeAlloc( pCoverNew ); Mvc_CubeBitClean( pCubeNew ); // copy the bits (cannot immediately use Mvc_CubeBitCopy, // because covers have different numbers of bits) Mvc_CubeSetLast( pCubeNew, iLast ); Mvc_CubeBitCopy( pCubeNew, pCube ); Mvc_CubeSetLast( pCubeNew, iLastNew ); // add the extra bits Mvc_CubeBitOr( pCubeNew, pCubeNew, pCoverNew->pMask ); // add the cube to the new cover Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); } return pCoverNew; } #endif /**Function************************************************************* Synopsis [Transposes the cube cover.] Description [Returns the cube cover that looks like a transposed matrix, compared to the matrix derived from the original cover.] SideEffects [] SeeAlso [] ***********************************************************************/ Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover ) { Mvc_Cover_t * pRes; Mvc_Cube_t * pCubeRes, * pCube; int nWord, nBit, i, iCube; pRes = Mvc_CoverAlloc( pCover->pMem, Mvc_CoverReadCubeNum(pCover) ); for ( i = 0; i < pCover->nBits; i++ ) { // get the word and bit of this literal nWord = Mvc_CubeWhichWord(i); nBit = Mvc_CubeWhichBit(i); // get the transposed cube pCubeRes = Mvc_CubeAlloc( pRes ); Mvc_CubeBitClean( pCubeRes ); iCube = 0; Mvc_CoverForEachCube( pCover, pCube ) { if ( pCube->pData[nWord] & (1<nUnused == 0 ) continue; Unsigned = ( pCube->pData[pCube->iLast] & (BITS_FULL << (32-pCube->nUnused)) ); if( Unsigned ) { printf( "Cube %2d out of %2d contains dirty bits.\n", nCubes, Mvc_CoverReadCubeNum(pCover) ); } nCubes++; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/nm/000077500000000000000000000000001300674244400214015ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/nm/module.make000066400000000000000000000000651300674244400235260ustar00rootroot00000000000000SRC += src/misc/nm/nmApi.c \ src/misc/nm/nmTable.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/nm/nm.h000066400000000000000000000072331300674244400221710ustar00rootroot00000000000000/**CFilextern e**************************************************************** FileName [nm.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Name manager.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nm.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__nm__nm_h #define ABC__misc__nm__nm_h /* This manager is designed to store ID-to-name and name-to-ID mapping for Boolean networks and And-Inverter Graphs. In a netlist, net names are unique. In this case, there is a one-to-one mapping between IDs and names. In a logic network, which do not have nets, several objects may have the same name. For example, a latch output and a primary output. Another example, a primary input and an input to a black box. In this case, for each ID on an object there is only one name, but for each name may be several IDs of objects having this name. The name manager maps ID-to-name uniquely but it allows one name to be mapped into several IDs. When a query to find an ID of the object by its name is submitted, it is possible to specify the object type, which will help select one of several IDs. If the type is -1, and there is more than one object with the given name, any object with the given name is returned. */ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Nm_Man_t_ Nm_Man_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== nmApi.c ==========================================================*/ extern Nm_Man_t * Nm_ManCreate( int nSize ); extern void Nm_ManFree( Nm_Man_t * p ); extern int Nm_ManNumEntries( Nm_Man_t * p ); extern char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix ); extern void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId ); extern char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId ); extern char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId ); extern int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type ); extern int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 ); extern Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/nm/nmApi.c000066400000000000000000000200251300674244400226100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nmApi.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Name manager.] Synopsis [APIs of the name manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nmApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the name manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nm_Man_t * Nm_ManCreate( int nSize ) { Nm_Man_t * p; // allocate the table p = ABC_ALLOC( Nm_Man_t, 1 ); memset( p, 0, sizeof(Nm_Man_t) ); // set the parameters p->nSizeFactor = 2; // determined the limit on the grow of data before the table resizes p->nGrowthFactor = 3; // determined how much the table grows after resizing // allocate and clean the bins p->nBins = Abc_PrimeCudd(nSize); p->pBinsI2N = ABC_ALLOC( Nm_Entry_t *, p->nBins ); p->pBinsN2I = ABC_ALLOC( Nm_Entry_t *, p->nBins ); memset( p->pBinsI2N, 0, sizeof(Nm_Entry_t *) * p->nBins ); memset( p->pBinsN2I, 0, sizeof(Nm_Entry_t *) * p->nBins ); // start the memory manager p->pMem = Extra_MmFlexStart(); return p; } /**Function************************************************************* Synopsis [Deallocates the name manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nm_ManFree( Nm_Man_t * p ) { Extra_MmFlexStop( p->pMem ); ABC_FREE( p->pBinsI2N ); ABC_FREE( p->pBinsN2I ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the number of objects with names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nm_ManNumEntries( Nm_Man_t * p ) { return p->nEntries; } /**Function************************************************************* Synopsis [Creates a new entry in the name manager.] Description [Returns 1 if the entry with the given object ID already exists in the name manager.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix ) { Nm_Entry_t * pEntry; int RetValue, nEntrySize; // check if the object with this ID is already stored if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) ) { printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" ); return NULL; } // create a new entry nEntrySize = sizeof(Nm_Entry_t) + strlen(pName) + (pSuffix?strlen(pSuffix):0) + 1; // nEntrySize = (nEntrySize / 4 + ((nEntrySize % 4) > 0)) * 4; nEntrySize = (nEntrySize / sizeof(char*) + ((nEntrySize % sizeof(char*)) > 0)) * sizeof(char*); // added by Saurabh on Sep 3, 2009 pEntry = (Nm_Entry_t *)Extra_MmFlexEntryFetch( p->pMem, nEntrySize ); pEntry->pNextI2N = pEntry->pNextN2I = pEntry->pNameSake = NULL; pEntry->ObjId = ObjId; pEntry->Type = Type; sprintf( pEntry->Name, "%s%s", pName, pSuffix? pSuffix : "" ); // add the entry to the hash table RetValue = Nm_ManTableAdd( p, pEntry ); assert( RetValue == 1 ); return pEntry->Name; } /**Function************************************************************* Synopsis [Creates a new entry in the name manager.] Description [Returns 1 if the entry with the given object ID already exists in the name manager.] SideEffects [] SeeAlso [] ***********************************************************************/ void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId ) { Nm_Entry_t * pEntry; pEntry = Nm_ManTableLookupId(p, ObjId); if ( pEntry == NULL ) { printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" ); return; } // remove entry from the table Nm_ManTableDelete( p, ObjId ); } /**Function************************************************************* Synopsis [Finds a unique name for the node.] Description [If the name exists, tries appending numbers to it until it becomes unique. The name is not added to the table.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId ) { static char NameStr[1000]; Nm_Entry_t * pEntry; int i; if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) ) return pEntry->Name; sprintf( NameStr, "n%d", ObjId ); for ( i = 1; Nm_ManTableLookupName(p, NameStr, -1); i++ ) sprintf( NameStr, "n%d_%d", ObjId, i ); return NameStr; } /**Function************************************************************* Synopsis [Returns name of the object if the ID is known.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId ) { Nm_Entry_t * pEntry; if ( (pEntry = Nm_ManTableLookupId(p, ObjId)) ) return pEntry->Name; return NULL; } /**Function************************************************************* Synopsis [Returns ID of the object if its name is known.] Description [This procedure may return two IDs because POs and latches may have the same name (the only allowed case of name duplication).] SideEffects [] SeeAlso [] ***********************************************************************/ int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type ) { Nm_Entry_t * pEntry; if ( (pEntry = Nm_ManTableLookupName(p, pName, Type)) ) return pEntry->ObjId; return -1; } /**Function************************************************************* Synopsis [Returns ID of the object if its name is known.] Description [This procedure may return two IDs because POs and latches may have the same name (the only allowed case of name duplication).] SideEffects [] SeeAlso [] ***********************************************************************/ int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 ) { int iNodeId; iNodeId = Nm_ManFindIdByName( p, pName, Type1 ); if ( iNodeId == -1 ) iNodeId = Nm_ManFindIdByName( p, pName, Type2 ); if ( iNodeId == -1 ) return -1; return iNodeId; } /**Function************************************************************* Synopsis [Return the IDs of objects with names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p ) { Vec_Int_t * vNameIds; int i; vNameIds = Vec_IntAlloc( p->nEntries ); for ( i = 0; i < p->nBins; i++ ) if ( p->pBinsI2N[i] ) Vec_IntPush( vNameIds, p->pBinsI2N[i]->ObjId ); return vNameIds; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/nm/nmInt.h000066400000000000000000000064671300674244400226540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nmInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Name manager.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nmInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__nm__nmInt_h #define ABC__misc__nm__nmInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/extra/extra.h" #include "misc/vec/vec.h" #include "nm.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Nm_Entry_t_ Nm_Entry_t; struct Nm_Entry_t_ { unsigned Type; // object type unsigned ObjId; // object ID Nm_Entry_t * pNextI2N; // the next entry in the ID hash table Nm_Entry_t * pNextN2I; // the next entry in the name hash table Nm_Entry_t * pNameSake; // the next entry with the same name char Name[0]; // name of the object }; struct Nm_Man_t_ { Nm_Entry_t ** pBinsI2N; // mapping IDs into names Nm_Entry_t ** pBinsN2I; // mapping names into IDs int nBins; // the number of bins in tables int nEntries; // the number of entries int nSizeFactor; // determined how much larger the table should be int nGrowthFactor; // determined how much the table grows after resizing Extra_MmFlex_t * pMem; // memory manager for entries (and names) }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== nmTable.c ==========================================================*/ extern int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry ); extern int Nm_ManTableDelete( Nm_Man_t * p, int ObjId ); extern Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId ); extern Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/nm/nmTable.c000066400000000000000000000226451300674244400231400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nmTable.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Name manager.] Synopsis [Hash table for the name manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nmTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // hashing for integers static unsigned Nm_HashNumber( int Num, int TableSize ) { unsigned Key = 0; Key ^= ( Num & 0xFF) * 7937; Key ^= ((Num >> 8) & 0xFF) * 2971; Key ^= ((Num >> 16) & 0xFF) * 911; Key ^= ((Num >> 24) & 0xFF) * 353; return Key % TableSize; } // hashing for strings static unsigned Nm_HashString( char * pName, int TableSize ) { static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; unsigned i, Key = 0; for ( i = 0; pName[i] != '\0'; i++ ) Key ^= s_Primes[i%10]*pName[i]*pName[i]; return Key % TableSize; } static void Nm_ManResize( Nm_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds an entry to two hash tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry ) { Nm_Entry_t ** ppSpot, * pOther; // resize the tables if needed if ( p->nEntries > p->nBins * p->nSizeFactor ) Nm_ManResize( p ); // add the entry to the table Id->Name assert( Nm_ManTableLookupId(p, pEntry->ObjId) == NULL ); ppSpot = p->pBinsI2N + Nm_HashNumber(pEntry->ObjId, p->nBins); pEntry->pNextI2N = *ppSpot; *ppSpot = pEntry; // check if an entry with the same name already exists if ( (pOther = Nm_ManTableLookupName(p, pEntry->Name, -1)) ) { // entry with the same name already exists - add it to the ring pEntry->pNameSake = pOther->pNameSake? pOther->pNameSake : pOther; pOther->pNameSake = pEntry; } else { // entry with the same name does not exist - add it to the table ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins); pEntry->pNextN2I = *ppSpot; *ppSpot = pEntry; } // report successfully added entry p->nEntries++; return 1; } /**Function************************************************************* Synopsis [Deletes the entry from two hash tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nm_ManTableDelete( Nm_Man_t * p, int ObjId ) { Nm_Entry_t ** ppSpot, * pEntry, * pPrev; int fRemoved; p->nEntries--; // remove the entry from the table Id->Name assert( Nm_ManTableLookupId(p, ObjId) != NULL ); ppSpot = p->pBinsI2N + Nm_HashNumber(ObjId, p->nBins); while ( (*ppSpot)->ObjId != (unsigned)ObjId ) ppSpot = &(*ppSpot)->pNextI2N; pEntry = *ppSpot; *ppSpot = (*ppSpot)->pNextI2N; // remove the entry from the table Name->Id ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins); while ( *ppSpot && *ppSpot != pEntry ) ppSpot = &(*ppSpot)->pNextN2I; // remember if we found this one in the list fRemoved = (*ppSpot != NULL); if ( *ppSpot ) { assert( *ppSpot == pEntry ); *ppSpot = (*ppSpot)->pNextN2I; } // quit if this entry has no namesakes if ( pEntry->pNameSake == NULL ) { assert( fRemoved ); return 1; } // remove entry from the ring of namesakes assert( pEntry->pNameSake != pEntry ); for ( pPrev = pEntry; pPrev->pNameSake != pEntry; pPrev = pPrev->pNameSake ); assert( !strcmp(pPrev->Name, pEntry->Name) ); assert( pPrev->pNameSake == pEntry ); if ( pEntry->pNameSake == pPrev ) // two entries in the ring pPrev->pNameSake = NULL; else pPrev->pNameSake = pEntry->pNameSake; // reinsert the ring back if we removed its connection with the list in the table if ( fRemoved ) { assert( pPrev->pNextN2I == NULL ); pPrev->pNextN2I = *ppSpot; *ppSpot = pPrev; } return 1; } /**Function************************************************************* Synopsis [Looks up the entry by ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId ) { Nm_Entry_t * pEntry; for ( pEntry = p->pBinsI2N[ Nm_HashNumber(ObjId, p->nBins) ]; pEntry; pEntry = pEntry->pNextI2N ) if ( pEntry->ObjId == (unsigned)ObjId ) return pEntry; return NULL; } /**Function************************************************************* Synopsis [Looks up the entry by name and type.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type ) { Nm_Entry_t * pEntry, * pTemp; for ( pEntry = p->pBinsN2I[ Nm_HashString(pName, p->nBins) ]; pEntry; pEntry = pEntry->pNextN2I ) { // check the entry itself if ( !strcmp(pEntry->Name, pName) && (Type == -1 || pEntry->Type == (unsigned)Type) ) return pEntry; // if there is no namesakes, continue if ( pEntry->pNameSake == NULL ) continue; // check the list of namesakes for ( pTemp = pEntry->pNameSake; pTemp != pEntry; pTemp = pTemp->pNameSake ) if ( !strcmp(pTemp->Name, pName) && (Type == -1 || pTemp->Type == (unsigned)Type) ) return pTemp; } return NULL; } /**Function************************************************************* Synopsis [Profiles hash tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nm_ManProfile( Nm_Man_t * p ) { Nm_Entry_t * pEntry; int Counter, e; printf( "I2N table: " ); for ( e = 0; e < p->nBins; e++ ) { Counter = 0; for ( pEntry = p->pBinsI2N[e]; pEntry; pEntry = pEntry->pNextI2N ) Counter++; printf( "%d ", Counter ); } printf( "\n" ); printf( "N2I table: " ); for ( e = 0; e < p->nBins; e++ ) { Counter = 0; for ( pEntry = p->pBinsN2I[e]; pEntry; pEntry = pEntry->pNextN2I ) Counter++; printf( "%d ", Counter ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Resizes the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nm_ManResize( Nm_Man_t * p ) { Nm_Entry_t ** pBinsNewI2N, ** pBinsNewN2I, * pEntry, * pEntry2, ** ppSpot; int nBinsNew, Counter, e; abctime clk; clk = Abc_Clock(); // get the new table size nBinsNew = Abc_PrimeCudd( p->nGrowthFactor * p->nBins ); // allocate a new array pBinsNewI2N = ABC_ALLOC( Nm_Entry_t *, nBinsNew ); pBinsNewN2I = ABC_ALLOC( Nm_Entry_t *, nBinsNew ); memset( pBinsNewI2N, 0, sizeof(Nm_Entry_t *) * nBinsNew ); memset( pBinsNewN2I, 0, sizeof(Nm_Entry_t *) * nBinsNew ); // rehash entries in Id->Name table Counter = 0; for ( e = 0; e < p->nBins; e++ ) for ( pEntry = p->pBinsI2N[e], pEntry2 = pEntry? pEntry->pNextI2N : NULL; pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextI2N : NULL ) { ppSpot = pBinsNewI2N + Nm_HashNumber(pEntry->ObjId, nBinsNew); pEntry->pNextI2N = *ppSpot; *ppSpot = pEntry; Counter++; } // rehash entries in Name->Id table for ( e = 0; e < p->nBins; e++ ) for ( pEntry = p->pBinsN2I[e], pEntry2 = pEntry? pEntry->pNextN2I : NULL; pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextN2I : NULL ) { ppSpot = pBinsNewN2I + Nm_HashString(pEntry->Name, nBinsNew); pEntry->pNextN2I = *ppSpot; *ppSpot = pEntry; } assert( Counter == p->nEntries ); // printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew ); // ABC_PRT( "Time", Abc_Clock() - clk ); // replace the table and the parameters ABC_FREE( p->pBinsI2N ); ABC_FREE( p->pBinsN2I ); p->pBinsI2N = pBinsNewI2N; p->pBinsN2I = pBinsNewN2I; p->nBins = nBinsNew; // Nm_ManProfile( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/parse/000077500000000000000000000000001300674244400221015ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/parse/module.make000066400000000000000000000001011300674244400242150ustar00rootroot00000000000000SRC += src/misc/parse/parseEqn.c \ src/misc/parse/parseStack.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/parse/parse.h000066400000000000000000000045361300674244400233740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [parse.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Parsing symbolic Boolean formulas into BDDs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: parse.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__bdd__parse__parse_h #define ABC__bdd__parse__parse_h ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== parseCore.c =============================================================*/ extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks, char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/parse/parseCore.c000066400000000000000000000444521300674244400242010ustar00rootroot00000000000000/**CFile**************************************************************** FileNameIn [parseCore.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Boolean formula parser.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: parseCore.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ /* Some aspects of Boolean Formula Parser: 1) The names in the boolean formulas can be any strings of symbols that start with char or underscore and contain chars, digits and underscores: For example: 1) a&b <+> c'&d => a + b; 2) a1 b2 c3' dummy' + (a2+b2')c3 dummy 2) Constant values 0 and 1 can be used just like normal variables 3) Any boolean operator (listed below) and parentheses can be used any number of times provided there are equal number of opening and closing parentheses. 4) By default, absence of an operator between vars and before and after parentheses is taken for AND. 5) Both complementation prefix and complementation suffix can be used at the same time (but who needs this?) 6) Spaces (tabs, end-of-lines) may be inserted anywhere, except between characters of the operations: <=>, =>, <=, <+> 7) The stack size is defined by macro STACKSIZE and is used by the stack constructor. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #include "parseInt.h" ABC_NAMESPACE_IMPL_START // the list of operation symbols to be used in expressions #define PARSE_SYM_OPEN '(' // opening parenthesis #define PARSE_SYM_CLOSE ')' // closing parenthesis #define PARSE_SYM_LOWER '[' // shifts one rank down #define PARSE_SYM_RAISE ']' // shifts one rank up #define PARSE_SYM_CONST0 '0' // constant 0 #define PARSE_SYM_CONST1 '1' // constant 1 #define PARSE_SYM_NEGBEF1 '!' // negation before the variable #define PARSE_SYM_NEGBEF2 '~' // negation before the variable #define PARSE_SYM_NEGAFT '\'' // negation after the variable #define PARSE_SYM_AND1 '&' // logic AND #define PARSE_SYM_AND2 '*' // logic AND #define PARSE_SYM_XOR1 '<' // logic EXOR (the 1st symbol) #define PARSE_SYM_XOR2 '+' // logic EXOR (the 2nd symbol) #define PARSE_SYM_XOR3 '>' // logic EXOR (the 3rd symbol) #define PARSE_SYM_XOR '^' // logic XOR #define PARSE_SYM_OR1 '+' // logic OR #define PARSE_SYM_OR2 '|' // logic OR #define PARSE_SYM_EQU1 '<' // equvalence (the 1st symbol) #define PARSE_SYM_EQU2 '=' // equvalence (the 2nd symbol) #define PARSE_SYM_EQU3 '>' // equvalence (the 3rd symbol) #define PARSE_SYM_FLR1 '=' // implication (the 1st symbol) #define PARSE_SYM_FLR2 '>' // implication (the 2nd symbol) #define PARSE_SYM_FLL1 '<' // backward imp (the 1st symbol) #define PARSE_SYM_FLL2 '=' // backward imp (the 2nd symbol) // PARSE_SYM_FLR1 and PARSE_SYM_FLR2 should be the same as PARSE_SYM_EQU2 and PARSE_SYM_EQU3! // the list of opcodes (also specifying operation precedence) #define PARSE_OPER_NEG 10 // negation #define PARSE_OPER_AND 9 // logic AND #define PARSE_OPER_XOR 8 // logic EXOR (a'b | ab') #define PARSE_OPER_OR 7 // logic OR #define PARSE_OPER_EQU 6 // equvalence (a'b'| ab ) #define PARSE_OPER_FLR 5 // implication ( a' | b ) #define PARSE_OPER_FLL 4 // backward imp ( 'b | a ) #define PARSE_OPER_MARK 1 // OpStack token standing for an opening parenthesis // these are values of the internal Flag #define PARSE_FLAG_START 1 // after the opening parenthesis #define PARSE_FLAG_VAR 2 // after operation is received #define PARSE_FLAG_OPER 3 // after operation symbol is received #define PARSE_FLAG_ERROR 4 // when error is detected #define STACKSIZE 1000 static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the BDD corresponding to the formula in language L.] Description [Takes the stream to output messages, the formula, the number variables and the rank in the formula. The array of variable names is also given. The BDD manager and the elementary 0-rank variable are the last two arguments. The manager should have at least as many variables as nVars * (nRanks + 1). The 0-rank variables should have numbers larger than the variables of other ranks.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormulaInit, int nVars, int nRanks, char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ) { char * pFormula; Parse_StackFn_t * pStackFn; Parse_StackOp_t * pStackOp; DdNode * bFunc, * bTemp; char * pTemp; int nParans, fFound, Flag; int Oper, Oper1, Oper2; int i, fLower; int v = -1; // Suppress "might be used uninitialized" // make sure that the number of vars and ranks is correct if ( nVars * (nRanks + 1) > dd->size ) { printf( "Parse_FormulaParser(): The BDD manager does not have enough variables.\n" ); return NULL; } // make sure that the number of opening and closing parentheses is the same nParans = 0; for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) if ( *pTemp == '(' ) nParans++; else if ( *pTemp == ')' ) nParans--; if ( nParans != 0 ) { fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing parentheses ().\n" ); return NULL; } nParans = 0; for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) if ( *pTemp == '[' ) nParans++; else if ( *pTemp == ']' ) nParans--; if ( nParans != 0 ) { fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing brackets [].\n" ); return NULL; } // copy the formula pFormula = ABC_ALLOC( char, strlen(pFormulaInit) + 3 ); sprintf( pFormula, "(%s)", pFormulaInit ); // start the stacks pStackFn = Parse_StackFnStart( STACKSIZE ); pStackOp = Parse_StackOpStart( STACKSIZE ); Flag = PARSE_FLAG_START; fLower = 0; for ( pTemp = pFormula; *pTemp; pTemp++ ) { switch ( *pTemp ) { // skip all spaces, tabs, and end-of-lines case ' ': case '\t': case '\r': case '\n': continue; // treat Constant 0 as a variable case PARSE_SYM_CONST0: Parse_StackFnPush( pStackFn, b0 ); Cudd_Ref( b0 ); if ( Flag == PARSE_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 0.\n" ); Flag = PARSE_FLAG_ERROR; break; } Flag = PARSE_FLAG_VAR; break; // the same for Constant 1 case PARSE_SYM_CONST1: Parse_StackFnPush( pStackFn, b1 ); Cudd_Ref( b1 ); if ( Flag == PARSE_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 1.\n" ); Flag = PARSE_FLAG_ERROR; break; } Flag = PARSE_FLAG_VAR; break; case PARSE_SYM_NEGBEF1: case PARSE_SYM_NEGBEF2: if ( Flag == PARSE_FLAG_VAR ) {// if NEGBEF follows a variable, AND is assumed Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); Flag = PARSE_FLAG_OPER; } Parse_StackOpPush( pStackOp, PARSE_OPER_NEG ); break; case PARSE_SYM_NEGAFT: if ( Flag != PARSE_FLAG_VAR ) {// if there is no variable before NEGAFT, it is an error fprintf( pOutput, "Parse_FormulaParser(): No variable is specified before the negation suffix.\n" ); Flag = PARSE_FLAG_ERROR; break; } else // if ( Flag == PARSE_FLAG_VAR ) Parse_StackFnPush( pStackFn, Cudd_Not( Parse_StackFnPop(pStackFn) ) ); break; case PARSE_SYM_AND1: case PARSE_SYM_AND2: case PARSE_SYM_OR1: case PARSE_SYM_OR2: case PARSE_SYM_XOR: if ( Flag != PARSE_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR.\n" ); Flag = PARSE_FLAG_ERROR; break; } if ( *pTemp == PARSE_SYM_AND1 || *pTemp == PARSE_SYM_AND2 ) Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); else if ( *pTemp == PARSE_SYM_OR1 || *pTemp == PARSE_SYM_OR2 ) Parse_StackOpPush( pStackOp, PARSE_OPER_OR ); else //if ( Str[Pos] == PARSE_SYM_XOR ) Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); Flag = PARSE_FLAG_OPER; break; case PARSE_SYM_EQU1: if ( Flag != PARSE_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Equivalence or Implication\n" ); Flag = PARSE_FLAG_ERROR; break; } if ( pTemp[1] == PARSE_SYM_EQU2 ) { // check what is the next symbol in the string pTemp++; if ( pTemp[1] == PARSE_SYM_EQU3 ) { pTemp++; Parse_StackOpPush( pStackOp, PARSE_OPER_EQU ); } else { Parse_StackOpPush( pStackOp, PARSE_OPER_FLL ); } } else if ( pTemp[1] == PARSE_SYM_XOR2 ) { pTemp++; if ( pTemp[1] == PARSE_SYM_XOR3 ) { pTemp++; Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); } else { fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c%c\"\n", PARSE_SYM_EQU1, PARSE_SYM_XOR2 ); Flag = PARSE_FLAG_ERROR; break; } } else { fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU1 ); Flag = PARSE_FLAG_ERROR; break; } Flag = PARSE_FLAG_OPER; break; case PARSE_SYM_EQU2: if ( Flag != PARSE_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Reverse Implication\n" ); Flag = PARSE_FLAG_ERROR; break; } if ( pTemp[1] == PARSE_SYM_EQU3 ) { pTemp++; Parse_StackOpPush( pStackOp, PARSE_OPER_FLR ); } else { fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU2 ); Flag = PARSE_FLAG_ERROR; break; } Flag = PARSE_FLAG_OPER; break; case PARSE_SYM_LOWER: case PARSE_SYM_OPEN: if ( Flag == PARSE_FLAG_VAR ) Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); Parse_StackOpPush( pStackOp, PARSE_OPER_MARK ); // after an opening bracket, it feels like starting over again Flag = PARSE_FLAG_START; break; case PARSE_SYM_RAISE: fLower = 1; case PARSE_SYM_CLOSE: if ( !Parse_StackOpIsEmpty( pStackOp ) ) { while ( 1 ) { if ( Parse_StackOpIsEmpty( pStackOp ) ) { fprintf( pOutput, "Parse_FormulaParser(): There is no opening parenthesis\n" ); Flag = PARSE_FLAG_ERROR; break; } Oper = Parse_StackOpPop( pStackOp ); if ( Oper == PARSE_OPER_MARK ) break; // perform the given operation if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper ) == NULL ) { fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); ABC_FREE( pFormula ); return NULL; } } if ( fLower ) { bFunc = (DdNode *)Parse_StackFnPop( pStackFn ); bFunc = Extra_bddMove( dd, bTemp = bFunc, -nVars ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); Parse_StackFnPush( pStackFn, bFunc ); } } else { fprintf( pOutput, "Parse_FormulaParser(): There is no opening parenthesis\n" ); Flag = PARSE_FLAG_ERROR; break; } if ( Flag != PARSE_FLAG_ERROR ) Flag = PARSE_FLAG_VAR; fLower = 0; break; default: // scan the next name /* fFound = 0; for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n'; i++ ) { for ( v = 0; v < nVars; v++ ) if ( strncmp( pTemp, ppVarNames[v], i+1 ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i+1) ) { pTemp += i; fFound = 1; break; } if ( fFound ) break; } */ // bug fix by SV (9/11/08) fFound = 0; for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && pTemp[i] != PARSE_SYM_AND1 && pTemp[i] != PARSE_SYM_AND2 && pTemp[i] != PARSE_SYM_XOR1 && pTemp[i] != PARSE_SYM_XOR2 && pTemp[i] != PARSE_SYM_XOR3 && pTemp[i] != PARSE_SYM_XOR && pTemp[i] != PARSE_SYM_OR1 && pTemp[i] != PARSE_SYM_OR2 && pTemp[i] != PARSE_SYM_CLOSE && pTemp[i] != PARSE_SYM_NEGAFT; i++ ) {} for ( v = 0; v < nVars; v++ ) { if ( strncmp( pTemp, ppVarNames[v], i ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i) ) { pTemp += i-1; fFound = 1; break; } } if ( !fFound ) { fprintf( pOutput, "Parse_FormulaParser(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); Flag = PARSE_FLAG_ERROR; break; } // assume operation AND, if vars follow one another if ( Flag == PARSE_FLAG_VAR ) Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); Parse_StackFnPush( pStackFn, pbVars[v] ); Cudd_Ref( pbVars[v] ); Flag = PARSE_FLAG_VAR; break; } if ( Flag == PARSE_FLAG_ERROR ) break; // error exit else if ( Flag == PARSE_FLAG_START ) continue; // go on parsing else if ( Flag == PARSE_FLAG_VAR ) while ( 1 ) { // check if there are negations in the OpStack if ( Parse_StackOpIsEmpty(pStackOp) ) break; Oper = Parse_StackOpPop( pStackOp ); if ( Oper != PARSE_OPER_NEG ) { Parse_StackOpPush( pStackOp, Oper ); break; } else { Parse_StackFnPush( pStackFn, Cudd_Not(Parse_StackFnPop(pStackFn)) ); } } else // if ( Flag == PARSE_FLAG_OPER ) while ( 1 ) { // execute all the operations in the OpStack // with precedence higher or equal than the last one Oper1 = Parse_StackOpPop( pStackOp ); // the last operation if ( Parse_StackOpIsEmpty(pStackOp) ) { // if it is the only operation, push it back Parse_StackOpPush( pStackOp, Oper1 ); break; } Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one if ( Oper2 >= Oper1 ) { // if Oper2 precedence is higher or equal, execute it // Parse_StackPush( pStackFn, Operation( FunStack.Pop(), FunStack.Pop(), Oper2 ) ); if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper2 ) == NULL ) { fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); ABC_FREE( pFormula ); return NULL; } Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back } else { // if Oper2 precedence is lower, push them back and done Parse_StackOpPush( pStackOp, Oper2 ); Parse_StackOpPush( pStackOp, Oper1 ); break; } } } if ( Flag != PARSE_FLAG_ERROR ) { if ( !Parse_StackFnIsEmpty(pStackFn) ) { bFunc = (DdNode *)Parse_StackFnPop(pStackFn); if ( Parse_StackFnIsEmpty(pStackFn) ) if ( Parse_StackOpIsEmpty(pStackOp) ) { Parse_StackFnFree(pStackFn); Parse_StackOpFree(pStackOp); Cudd_Deref( bFunc ); ABC_FREE( pFormula ); return bFunc; } else fprintf( pOutput, "Parse_FormulaParser(): Something is left in the operation stack\n" ); else fprintf( pOutput, "Parse_FormulaParser(): Something is left in the function stack\n" ); } else fprintf( pOutput, "Parse_FormulaParser(): The input string is empty\n" ); } ABC_FREE( pFormula ); return NULL; } /**Function************************************************************* Synopsis [Performs the operation on the top entries in the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ) { DdNode * bArg1, * bArg2, * bFunc; // perform the given operation bArg2 = (DdNode *)Parse_StackFnPop( pStackFn ); bArg1 = (DdNode *)Parse_StackFnPop( pStackFn ); if ( Oper == PARSE_OPER_AND ) bFunc = Cudd_bddAnd( dd, bArg1, bArg2 ); else if ( Oper == PARSE_OPER_XOR ) bFunc = Cudd_bddXor( dd, bArg1, bArg2 ); else if ( Oper == PARSE_OPER_OR ) bFunc = Cudd_bddOr( dd, bArg1, bArg2 ); else if ( Oper == PARSE_OPER_EQU ) bFunc = Cudd_bddXnor( dd, bArg1, bArg2 ); else if ( Oper == PARSE_OPER_FLR ) bFunc = Cudd_bddOr( dd, Cudd_Not(bArg1), bArg2 ); else if ( Oper == PARSE_OPER_FLL ) bFunc = Cudd_bddOr( dd, Cudd_Not(bArg2), bArg1 ); else return NULL; Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bArg1 ); Cudd_RecursiveDeref( dd, bArg2 ); Parse_StackFnPush( pStackFn, bFunc ); return bFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/parse/parseEqn.c000066400000000000000000000301231300674244400240220ustar00rootroot00000000000000/**CFile**************************************************************** FileNameIn [parseEqn.c] PackageName [ABC: Logic synthesis and verification system.] Synopsis [Boolean formula parser.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - December 18, 2006.] Revision [$Id: parseEqn.c,v 1.0 2006/12/18 00:00:00 alanmi Exp $] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #include "parseInt.h" ABC_NAMESPACE_IMPL_START // the list of operation symbols to be used in expressions #define PARSE_EQN_SYM_OPEN '(' // opening parenthesis #define PARSE_EQN_SYM_CLOSE ')' // closing parenthesis #define PARSE_EQN_SYM_CONST0 '0' // constant 0 #define PARSE_EQN_SYM_CONST1 '1' // constant 1 #define PARSE_EQN_SYM_NEG '!' // negation before the variable #define PARSE_EQN_SYM_AND '*' // logic AND #define PARSE_EQN_SYM_OR '+' // logic OR // the list of opcodes (also specifying operation precedence) #define PARSE_EQN_OPER_NEG 10 // negation #define PARSE_EQN_OPER_AND 9 // logic AND #define PARSE_EQN_OPER_OR 7 // logic OR #define PARSE_EQN_OPER_MARK 1 // OpStack token standing for an opening parenthesis // these are values of the internal Flag #define PARSE_EQN_FLAG_START 1 // after the opening parenthesis #define PARSE_EQN_FLAG_VAR 2 // after operation is received #define PARSE_EQN_FLAG_OPER 3 // after operation symbol is received #define PARSE_EQN_FLAG_ERROR 4 // when error is detected #define PARSE_EQN_STACKSIZE 1000 static Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the AIG corresponding to the equation.] Description [Takes the stream to output messages, the formula, the vector of variable names and the AIG manager.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ) { char * pFormula; Parse_StackFn_t * pStackFn; Parse_StackOp_t * pStackOp; Hop_Obj_t * gFunc; char * pTemp, * pName; int nParans, fFound, Flag; int Oper, Oper1, Oper2; int i, v; // make sure that the number of opening and closing parentheses is the same nParans = 0; for ( pTemp = pFormInit; *pTemp; pTemp++ ) if ( *pTemp == '(' ) nParans++; else if ( *pTemp == ')' ) nParans--; if ( nParans != 0 ) { fprintf( pOutput, "Parse_FormulaParserEqn(): Different number of opening and closing parentheses ().\n" ); return NULL; } // copy the formula pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 ); sprintf( pFormula, "(%s)", pFormInit ); // start the stacks pStackFn = Parse_StackFnStart( PARSE_EQN_STACKSIZE ); pStackOp = Parse_StackOpStart( PARSE_EQN_STACKSIZE ); Flag = PARSE_EQN_FLAG_START; for ( pTemp = pFormula; *pTemp; pTemp++ ) { switch ( *pTemp ) { // skip all spaces, tabs, and end-of-lines case ' ': case '\t': case '\r': case '\n': continue; case PARSE_EQN_SYM_CONST0: Parse_StackFnPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 ); if ( Flag == PARSE_EQN_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 0.\n" ); Flag = PARSE_EQN_FLAG_ERROR; break; } Flag = PARSE_EQN_FLAG_VAR; break; case PARSE_EQN_SYM_CONST1: Parse_StackFnPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 ); if ( Flag == PARSE_EQN_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 1.\n" ); Flag = PARSE_EQN_FLAG_ERROR; break; } Flag = PARSE_EQN_FLAG_VAR; break; case PARSE_EQN_SYM_NEG: if ( Flag == PARSE_EQN_FLAG_VAR ) {// if NEGBEF follows a variable, AND is assumed Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); Flag = PARSE_EQN_FLAG_OPER; } Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_NEG ); break; case PARSE_EQN_SYM_AND: case PARSE_EQN_SYM_OR: if ( Flag != PARSE_EQN_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParserEqn(): There is no variable before AND, EXOR, or OR.\n" ); Flag = PARSE_EQN_FLAG_ERROR; break; } if ( *pTemp == PARSE_EQN_SYM_AND ) Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); else //if ( *pTemp == PARSE_EQN_SYM_OR ) Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_OR ); Flag = PARSE_EQN_FLAG_OPER; break; case PARSE_EQN_SYM_OPEN: if ( Flag == PARSE_EQN_FLAG_VAR ) { // Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); fprintf( pOutput, "Parse_FormulaParserEqn(): An opening parenthesis follows a var without operation sign.\n" ); Flag = PARSE_EQN_FLAG_ERROR; break; } Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_MARK ); // after an opening bracket, it feels like starting over again Flag = PARSE_EQN_FLAG_START; break; case PARSE_EQN_SYM_CLOSE: if ( !Parse_StackOpIsEmpty( pStackOp ) ) { while ( 1 ) { if ( Parse_StackOpIsEmpty( pStackOp ) ) { fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening parenthesis\n" ); Flag = PARSE_EQN_FLAG_ERROR; break; } Oper = Parse_StackOpPop( pStackOp ); if ( Oper == PARSE_EQN_OPER_MARK ) break; // perform the given operation if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper ) == NULL ) { Parse_StackFnFree( pStackFn ); Parse_StackOpFree( pStackOp ); fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); ABC_FREE( pFormula ); return NULL; } } } else { fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening parenthesis\n" ); Flag = PARSE_EQN_FLAG_ERROR; break; } if ( Flag != PARSE_EQN_FLAG_ERROR ) Flag = PARSE_EQN_FLAG_VAR; break; default: // scan the next name for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && pTemp[i] != PARSE_EQN_SYM_AND && pTemp[i] != PARSE_EQN_SYM_OR && pTemp[i] != PARSE_EQN_SYM_CLOSE; i++ ) { if ( pTemp[i] == PARSE_EQN_SYM_NEG || pTemp[i] == PARSE_EQN_SYM_OPEN ) { fprintf( pOutput, "Parse_FormulaParserEqn(): The negation sign or an opening parenthesis inside the variable name.\n" ); Flag = PARSE_EQN_FLAG_ERROR; break; } } // variable name is found fFound = 0; Vec_PtrForEachEntry( char *, vVarNames, pName, v ) if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) { pTemp += i-1; fFound = 1; break; } if ( !fFound ) { fprintf( pOutput, "Parse_FormulaParserEqn(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); Flag = PARSE_EQN_FLAG_ERROR; break; } if ( Flag == PARSE_EQN_FLAG_VAR ) { fprintf( pOutput, "Parse_FormulaParserEqn(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); Flag = PARSE_EQN_FLAG_ERROR; break; } Parse_StackFnPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] ); Flag = PARSE_EQN_FLAG_VAR; break; } if ( Flag == PARSE_EQN_FLAG_ERROR ) break; // error exit else if ( Flag == PARSE_EQN_FLAG_START ) continue; // go on parsing else if ( Flag == PARSE_EQN_FLAG_VAR ) while ( 1 ) { // check if there are negations in the OpStack if ( Parse_StackOpIsEmpty(pStackOp) ) break; Oper = Parse_StackOpPop( pStackOp ); if ( Oper != PARSE_EQN_OPER_NEG ) { Parse_StackOpPush( pStackOp, Oper ); break; } else { Parse_StackFnPush( pStackFn, Hop_Not((Hop_Obj_t *)Parse_StackFnPop(pStackFn)) ); } } else // if ( Flag == PARSE_EQN_FLAG_OPER ) while ( 1 ) { // execute all the operations in the OpStack // with precedence higher or equal than the last one Oper1 = Parse_StackOpPop( pStackOp ); // the last operation if ( Parse_StackOpIsEmpty(pStackOp) ) { // if it is the only operation, push it back Parse_StackOpPush( pStackOp, Oper1 ); break; } Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one if ( Oper2 >= Oper1 ) { // if Oper2 precedence is higher or equal, execute it if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper2 ) == NULL ) { fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); ABC_FREE( pFormula ); Parse_StackFnFree( pStackFn ); Parse_StackOpFree( pStackOp ); return NULL; } Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back } else { // if Oper2 precedence is lower, push them back and done Parse_StackOpPush( pStackOp, Oper2 ); Parse_StackOpPush( pStackOp, Oper1 ); break; } } } if ( Flag != PARSE_EQN_FLAG_ERROR ) { if ( !Parse_StackFnIsEmpty(pStackFn) ) { gFunc = (Hop_Obj_t *)Parse_StackFnPop(pStackFn); if ( Parse_StackFnIsEmpty(pStackFn) ) if ( Parse_StackOpIsEmpty(pStackOp) ) { Parse_StackFnFree(pStackFn); Parse_StackOpFree(pStackOp); // Cudd_Deref( gFunc ); ABC_FREE( pFormula ); return gFunc; } else fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the operation stack\n" ); else fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the function stack\n" ); } else fprintf( pOutput, "Parse_FormulaParserEqn(): The input string is empty\n" ); } ABC_FREE( pFormula ); return NULL; } /**Function************************************************************* Synopsis [Performs the operation on the top entries in the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ) { Hop_Obj_t * gArg1, * gArg2, * gFunc; // perform the given operation gArg2 = (Hop_Obj_t *)Parse_StackFnPop( pStackFn ); gArg1 = (Hop_Obj_t *)Parse_StackFnPop( pStackFn ); if ( Oper == PARSE_EQN_OPER_AND ) gFunc = Hop_And( pMan, gArg1, gArg2 ); else if ( Oper == PARSE_EQN_OPER_OR ) gFunc = Hop_Or( pMan, gArg1, gArg2 ); else return NULL; // Cudd_Ref( gFunc ); // Cudd_RecursiveDeref( dd, gArg1 ); // Cudd_RecursiveDeref( dd, gArg2 ); Parse_StackFnPush( pStackFn, gFunc ); return gFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/parse/parseInt.h000066400000000000000000000061601300674244400240420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [parseInt.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Parsing symbolic Boolean formulas into BDDs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 8, 2003.] Revision [$Id: parseInt.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__bdd__parse__parseInt_h #define ABC__bdd__parse__parseInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/hop/hop.h" #include "misc/vec/vec.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct ParseStackFnStruct Parse_StackFn_t; // the function stack typedef struct ParseStackOpStruct Parse_StackOp_t; // the operation stack //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== parseStack.c =============================================================*/ extern Parse_StackFn_t * Parse_StackFnStart ( int nDepth ); extern int Parse_StackFnIsEmpty( Parse_StackFn_t * p ); extern void Parse_StackFnPush ( Parse_StackFn_t * p, void * bFunc ); extern void * Parse_StackFnPop ( Parse_StackFn_t * p ); extern void Parse_StackFnFree ( Parse_StackFn_t * p ); extern Parse_StackOp_t * Parse_StackOpStart ( int nDepth ); extern int Parse_StackOpIsEmpty( Parse_StackOp_t * p ); extern void Parse_StackOpPush ( Parse_StackOp_t * p, int Oper ); extern int Parse_StackOpPop ( Parse_StackOp_t * p ); extern void Parse_StackOpFree ( Parse_StackOp_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/parse/parseStack.c000066400000000000000000000134651300674244400243560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [parseStack.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Stacks used by the formula parser.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 18, 2003.] Revision [$Id: parseStack.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "parseInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct ParseStackFnStruct { void ** pData; // the array of elements int Top; // the index int Size; // the stack size }; struct ParseStackOpStruct { int * pData; // the array of elements int Top; // the index int Size; // the stack size }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Parse_StackFn_t * Parse_StackFnStart( int nDepth ) { Parse_StackFn_t * p; p = ABC_ALLOC( Parse_StackFn_t, 1 ); memset( p, 0, sizeof(Parse_StackFn_t) ); p->pData = ABC_ALLOC( void *, nDepth ); p->Size = nDepth; return p; } /**Function************************************************************* Synopsis [Checks whether the stack is empty.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Parse_StackFnIsEmpty( Parse_StackFn_t * p ) { return (int)(p->Top == 0); } /**Function************************************************************* Synopsis [Pushes an entry into the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc ) { if ( p->Top >= p->Size ) { printf( "Parse_StackFnPush(): Stack size is too small!\n" ); return; } p->pData[ p->Top++ ] = bFunc; } /**Function************************************************************* Synopsis [Pops an entry out of the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Parse_StackFnPop( Parse_StackFn_t * p ) { if ( p->Top == 0 ) { printf( "Parse_StackFnPush(): Trying to extract data from the empty stack!\n" ); return NULL; } return p->pData[ --p->Top ]; } /**Function************************************************************* Synopsis [Deletes the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Parse_StackFnFree( Parse_StackFn_t * p ) { ABC_FREE( p->pData ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Starts the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Parse_StackOp_t * Parse_StackOpStart( int nDepth ) { Parse_StackOp_t * p; p = ABC_ALLOC( Parse_StackOp_t, 1 ); memset( p, 0, sizeof(Parse_StackOp_t) ); p->pData = ABC_ALLOC( int, nDepth ); p->Size = nDepth; return p; } /**Function************************************************************* Synopsis [Checks whether the stack is empty.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Parse_StackOpIsEmpty( Parse_StackOp_t * p ) { return (int)(p->Top == 0); } /**Function************************************************************* Synopsis [Pushes an entry into the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Parse_StackOpPush( Parse_StackOp_t * p, int Oper ) { if ( p->Top >= p->Size ) { printf( "Parse_StackOpPush(): Stack size is too small!\n" ); return; } p->pData[ p->Top++ ] = Oper; } /**Function************************************************************* Synopsis [Pops an entry out of the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Parse_StackOpPop( Parse_StackOp_t * p ) { if ( p->Top == 0 ) { printf( "Parse_StackOpPush(): Trying to extract data from the empty stack!\n" ); return -1; } return p->pData[ --p->Top ]; } /**Function************************************************************* Synopsis [Deletes the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Parse_StackOpFree( Parse_StackOp_t * p ) { ABC_FREE( p->pData ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/st/000077500000000000000000000000001300674244400214155ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/st/module.make000066400000000000000000000000571300674244400235430ustar00rootroot00000000000000SRC += src/misc/st/st.c \ src/misc/st/stmm.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/st/st.c000066400000000000000000000311541300674244400222130ustar00rootroot00000000000000/* * Revision Control Information * * /projects/hsis/CVS/utilities/st/st.c,v * serdar * 1.1 * 1993/07/29 01:00:13 * */ #include #include #include #include "st.h" ABC_NAMESPACE_IMPL_START #define st__NUMCMP(x,y) ((x) != (y)) #define st__NUMHASH(x,size) (Abc_AbsInt((long)x)%(size)) //#define st__PTRHASH(x,size) ((int)((ABC_PTRUINT_T)(x)>>2)%size) // 64-bit bug fix 9/17/2007 #define st__PTRHASH(x,size) ((int)(((ABC_PTRUINT_T)(x)>>2)%size)) #define EQUAL(func, x, y) \ ((((func) == st__numcmp) || ((func) == st__ptrcmp)) ?\ (st__NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0)) #define do_hash(key, table)\ ((table->hash == st__ptrhash) ? st__PTRHASH((key),(table)->num_bins) :\ (table->hash == st__numhash) ? st__NUMHASH((key), (table)->num_bins) :\ (*table->hash)((key), (table)->num_bins)) static int rehash( st__table *table); int st__numhash(const char*, int); int st__ptrhash(const char*, int); int st__numcmp(const char*, const char*); int st__ptrcmp(const char*, const char*); st__table * st__init_table_with_params( st__compare_func_type compare, st__hash_func_type hash, int size, int density, double grow_factor, int reorder_flag) { int i; st__table *newTable; newTable = ABC_ALLOC( st__table, 1); if (newTable == NULL) { return NULL; } newTable->compare = compare; newTable->hash = hash; newTable->num_entries = 0; newTable->max_density = density; newTable->grow_factor = grow_factor; newTable->reorder_flag = reorder_flag; if (size <= 0) { size = 1; } newTable->num_bins = size; newTable->bins = ABC_ALLOC( st__table_entry *, size); if (newTable->bins == NULL) { ABC_FREE(newTable); return NULL; } for(i = 0; i < size; i++) { newTable->bins[i] = 0; } return newTable; } st__table * st__init_table( st__compare_func_type compare, st__hash_func_type hash) { return st__init_table_with_params(compare, hash, st__DEFAULT_INIT_TABLE_SIZE, st__DEFAULT_MAX_DENSITY, st__DEFAULT_GROW_FACTOR, st__DEFAULT_REORDER_FLAG); } void st__free_table( st__table *table) { st__table_entry *ptr, *next; int i; for(i = 0; i < table->num_bins ; i++) { ptr = table->bins[i]; while (ptr != NULL) { next = ptr->next; ABC_FREE(ptr); ptr = next; } } ABC_FREE(table->bins); ABC_FREE(table); } #define PTR_NOT_EQUAL(table, ptr, user_key)\ (ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) #define FIND_ENTRY(table, hash_val, key, ptr, last) \ (last) = &(table)->bins[hash_val];\ (ptr) = *(last);\ while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ (last) = &(ptr)->next; (ptr) = *(last);\ }\ if ((ptr) != NULL && (table)->reorder_flag) {\ *(last) = (ptr)->next;\ (ptr)->next = (table)->bins[hash_val];\ (table)->bins[hash_val] = (ptr);\ } int st__lookup( st__table *table, const char *key, char **value) { int hash_val; st__table_entry *ptr, **last; hash_val = do_hash(key, table); FIND_ENTRY(table, hash_val, key, ptr, last); if (ptr == NULL) { return 0; } else { if (value != NULL) { *value = ptr->record; } return 1; } } int st__lookup_int( st__table *table, char *key, int *value) { int hash_val; st__table_entry *ptr, **last; hash_val = do_hash(key, table); FIND_ENTRY(table, hash_val, key, ptr, last); if (ptr == NULL) { return 0; } else { if (value != 0) { *value = (long) ptr->record; } return 1; } } /* This macro does not check if memory allocation fails. Use at you own risk */ #define ADD_DIRECT(table, key, value, hash_val, new)\ {\ if (table->num_entries/table->num_bins >= table->max_density) {\ rehash(table);\ hash_val = do_hash(key,table);\ }\ \ new = ABC_ALLOC( st__table_entry, 1);\ \ new->key = key;\ new->record = value;\ new->next = table->bins[hash_val];\ table->bins[hash_val] = new;\ table->num_entries++;\ } int st__insert( st__table *table, const char *key, char *value) { int hash_val; st__table_entry *newEntry; st__table_entry *ptr, **last; hash_val = do_hash(key, table); FIND_ENTRY(table, hash_val, key, ptr, last); if (ptr == NULL) { if (table->num_entries/table->num_bins >= table->max_density) { if (rehash(table) == st__OUT_OF_MEM) { return st__OUT_OF_MEM; } hash_val = do_hash(key, table); } newEntry = ABC_ALLOC( st__table_entry, 1); if (newEntry == NULL) { return st__OUT_OF_MEM; } newEntry->key = (char *)key; newEntry->record = value; newEntry->next = table->bins[hash_val]; table->bins[hash_val] = newEntry; table->num_entries++; return 0; } else { ptr->record = value; return 1; } } int st__add_direct( st__table *table, char *key, char *value) { int hash_val; st__table_entry *newEntry; hash_val = do_hash(key, table); if (table->num_entries / table->num_bins >= table->max_density) { if (rehash(table) == st__OUT_OF_MEM) { return st__OUT_OF_MEM; } } hash_val = do_hash(key, table); newEntry = ABC_ALLOC( st__table_entry, 1); if (newEntry == NULL) { return st__OUT_OF_MEM; } newEntry->key = key; newEntry->record = value; newEntry->next = table->bins[hash_val]; table->bins[hash_val] = newEntry; table->num_entries++; return 1; } int st__find_or_add( st__table *table, char *key, char ***slot) { int hash_val; st__table_entry *newEntry, *ptr, **last; hash_val = do_hash(key, table); FIND_ENTRY(table, hash_val, key, ptr, last); if (ptr == NULL) { if (table->num_entries / table->num_bins >= table->max_density) { if (rehash(table) == st__OUT_OF_MEM) { return st__OUT_OF_MEM; } hash_val = do_hash(key, table); } newEntry = ABC_ALLOC( st__table_entry, 1); if (newEntry == NULL) { return st__OUT_OF_MEM; } newEntry->key = key; newEntry->record = (char *) 0; newEntry->next = table->bins[hash_val]; table->bins[hash_val] = newEntry; table->num_entries++; if (slot != NULL) *slot = &newEntry->record; return 0; } else { if (slot != NULL) *slot = &ptr->record; return 1; } } int st__find( st__table *table, char *key, char ***slot) { int hash_val; st__table_entry *ptr, **last; hash_val = do_hash(key, table); FIND_ENTRY(table, hash_val, key, ptr, last); if (ptr == NULL) { return 0; } else { if (slot != NULL) { *slot = &ptr->record; } return 1; } } static int rehash( st__table *table) { st__table_entry *ptr, *next, **old_bins; int i, old_num_bins, hash_val, old_num_entries; /* save old values */ old_bins = table->bins; old_num_bins = table->num_bins; old_num_entries = table->num_entries; /* rehash */ table->num_bins = (int)(table->grow_factor * old_num_bins); if (table->num_bins % 2 == 0) { table->num_bins += 1; } table->num_entries = 0; table->bins = ABC_ALLOC( st__table_entry *, table->num_bins); if (table->bins == NULL) { table->bins = old_bins; table->num_bins = old_num_bins; table->num_entries = old_num_entries; return st__OUT_OF_MEM; } /* initialize */ for (i = 0; i < table->num_bins; i++) { table->bins[i] = 0; } /* copy data over */ for (i = 0; i < old_num_bins; i++) { ptr = old_bins[i]; while (ptr != NULL) { next = ptr->next; hash_val = do_hash(ptr->key, table); ptr->next = table->bins[hash_val]; table->bins[hash_val] = ptr; table->num_entries++; ptr = next; } } ABC_FREE(old_bins); return 1; } st__table * st__copy( st__table *old_table) { st__table *newEntry_table; st__table_entry *ptr, *newEntryptr, *next, *newEntry; int i, j, num_bins = old_table->num_bins; newEntry_table = ABC_ALLOC( st__table, 1); if (newEntry_table == NULL) { return NULL; } *newEntry_table = *old_table; newEntry_table->bins = ABC_ALLOC( st__table_entry *, num_bins); if (newEntry_table->bins == NULL) { ABC_FREE(newEntry_table); return NULL; } for(i = 0; i < num_bins ; i++) { newEntry_table->bins[i] = NULL; ptr = old_table->bins[i]; while (ptr != NULL) { newEntry = ABC_ALLOC( st__table_entry, 1); if (newEntry == NULL) { for (j = 0; j <= i; j++) { newEntryptr = newEntry_table->bins[j]; while (newEntryptr != NULL) { next = newEntryptr->next; ABC_FREE(newEntryptr); newEntryptr = next; } } ABC_FREE(newEntry_table->bins); ABC_FREE(newEntry_table); return NULL; } *newEntry = *ptr; newEntry->next = newEntry_table->bins[i]; newEntry_table->bins[i] = newEntry; ptr = ptr->next; } } return newEntry_table; } int st__delete( st__table *table, const char **keyp, char **value) { int hash_val; const char *key = *keyp; st__table_entry *ptr, **last; hash_val = do_hash(key, table); FIND_ENTRY(table, hash_val, key, ptr ,last); if (ptr == NULL) { return 0; } *last = ptr->next; if (value != NULL) *value = ptr->record; *keyp = ptr->key; ABC_FREE(ptr); table->num_entries--; return 1; } int st__delete_int( st__table *table, long *keyp, char **value) { int hash_val; char *key = (char *) *keyp; st__table_entry *ptr, **last; hash_val = do_hash(key, table); FIND_ENTRY(table, hash_val, key, ptr ,last); if (ptr == NULL) { return 0; } *last = ptr->next; if (value != NULL) *value = ptr->record; *keyp = (long) ptr->key; ABC_FREE(ptr); table->num_entries--; return 1; } int st__foreach( st__table *table, enum st__retval (*func)(char *, char *, char *), char *arg) { st__table_entry *ptr, **last; enum st__retval retval; int i; for(i = 0; i < table->num_bins; i++) { last = &table->bins[i]; ptr = *last; while (ptr != NULL) { retval = (*func)(ptr->key, ptr->record, arg); switch (retval) { case st__CONTINUE: last = &ptr->next; ptr = *last; break; case st__STOP: return 0; case st__DELETE: *last = ptr->next; table->num_entries--; /* cstevens@ic */ ABC_FREE(ptr); ptr = *last; } } } return 1; } int st__strhash(const char *string, int modulus) { unsigned char * ustring = (unsigned char *)string; unsigned c, val = 0; assert( modulus > 0 ); while ((c = *ustring++) != '\0') { val = val*997 + c; } return (int)(val%modulus); } int st__numhash(const char *x, int size) { return st__NUMHASH(x, size); } int st__ptrhash(const char *x, int size) { return st__PTRHASH(x, size); } int st__numcmp(const char *x, const char *y) { return st__NUMCMP(x, y); } int st__ptrcmp(const char *x, const char *y) { return st__NUMCMP(x, y); } st__generator * st__init_gen( st__table *table) { st__generator *gen; gen = ABC_ALLOC( st__generator, 1); if (gen == NULL) { return NULL; } gen->table = table; gen->entry = NULL; gen->index = 0; return gen; } int st__gen( st__generator *gen, const char **key_p, char **value_p) { int i; if (gen->entry == NULL) { /* try to find next entry */ for(i = gen->index; i < gen->table->num_bins; i++) { if (gen->table->bins[i] != NULL) { gen->index = i+1; gen->entry = gen->table->bins[i]; break; } } if (gen->entry == NULL) { return 0; /* that's all folks ! */ } } *key_p = gen->entry->key; if (value_p != 0) { *value_p = gen->entry->record; } gen->entry = gen->entry->next; return 1; } int st__gen_int( st__generator *gen, const char **key_p, long *value_p) { int i; if (gen->entry == NULL) { /* try to find next entry */ for(i = gen->index; i < gen->table->num_bins; i++) { if (gen->table->bins[i] != NULL) { gen->index = i+1; gen->entry = gen->table->bins[i]; break; } } if (gen->entry == NULL) { return 0; /* that's all folks ! */ } } *key_p = gen->entry->key; if (value_p != 0) { *value_p = (long) gen->entry->record; } gen->entry = gen->entry->next; return 1; } void st__free_gen( st__generator *gen) { ABC_FREE(gen); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/st/st.h000066400000000000000000000065431300674244400222240ustar00rootroot00000000000000/* * Revision Control Information * * /projects/hsis/CVS/utilities/st/st.h,v * serdar * 1.1 * 1993/07/29 01:00:21 * */ /* LINTLIBRARY */ /* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ #ifndef ABC__misc__st__st_h #define ABC__misc__st__st_h #define st__INCLUDED #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START /* These are potential duplicates. */ #ifndef EXTERN # ifdef __cplusplus # ifdef ABC_NAMESPACE # define EXTERN extern # else # define EXTERN extern "C" # endif # else # define EXTERN extern # endif #endif #ifndef ARGS #define ARGS(protos) protos #endif typedef int (* st__compare_func_type)(const char*, const char*); typedef int (* st__hash_func_type)(const char*, int); typedef struct st__table_entry st__table_entry; struct st__table_entry { char *key; char *record; st__table_entry *next; }; typedef struct st__table st__table; struct st__table { st__compare_func_type compare; st__hash_func_type hash; int num_bins; int num_entries; int max_density; int reorder_flag; double grow_factor; st__table_entry **bins; }; typedef struct st__generator st__generator; struct st__generator { st__table *table; st__table_entry *entry; int index; }; #define st__is_member(table,key) st__lookup(table,key,(char **) 0) #define st__count(table) ((table)->num_entries) enum st__retval { st__CONTINUE, st__STOP, st__DELETE}; typedef enum st__retval (* st__PFSR)(char *, char *, char *); typedef int (* st__PFI)(); extern st__table * st__init_table_with_params ( st__compare_func_type compare, st__hash_func_type hash, int size, int density, double grow_factor, int reorder_flag); extern st__table * st__init_table ( st__compare_func_type, st__hash_func_type); extern void st__free_table ( st__table *); extern int st__lookup ( st__table *, const char *, char **); extern int st__lookup_int ( st__table *, char *, int *); extern int st__insert ( st__table *, const char *, char *); extern int st__add_direct ( st__table *, char *, char *); extern int st__find_or_add ( st__table *, char *, char ***); extern int st__find ( st__table *, char *, char ***); extern st__table * st__copy ( st__table *); extern int st__delete ( st__table *, const char **, char **); extern int st__delete_int ( st__table *, long *, char **); extern int st__foreach ( st__table *, st__PFSR, char *); extern int st__strhash (const char *, int); extern int st__numhash (const char *, int); extern int st__ptrhash (const char *, int); extern int st__numcmp (const char *, const char *); extern int st__ptrcmp (const char *, const char *); extern st__generator * st__init_gen ( st__table *); extern int st__gen ( st__generator *, const char **, char **); extern int st__gen_int ( st__generator *, const char **, long *); extern void st__free_gen ( st__generator *); #define st__DEFAULT_MAX_DENSITY 5 #define st__DEFAULT_INIT_TABLE_SIZE 11 #define st__DEFAULT_GROW_FACTOR 2.0 #define st__DEFAULT_REORDER_FLAG 0 #define st__foreach_item(table, gen, key, value) \ for(gen= st__init_gen(table); st__gen(gen,key,value) || ( st__free_gen(gen),0);) #define st__foreach_item_int(table, gen, key, value) \ for(gen= st__init_gen(table); st__gen_int(gen,key,value) || ( st__free_gen(gen),0);) #define st__OUT_OF_MEM -10000 ABC_NAMESPACE_HEADER_END #endif /* st__INCLUDED */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/st/stmm.c000066400000000000000000000346561300674244400225570ustar00rootroot00000000000000/* * Revision Control Information * * /projects/hsis/CVS/utilities/st/st.c,v * serdar * 1.1 * 1993/07/29 01:00:13 * */ #include #include "misc/extra/extra.h" #include "stmm.h" ABC_NAMESPACE_IMPL_START #define STMM_NUMCMP(x,y) ((x) != (y)) #define STMM_NUMHASH(x,size) (Abc_AbsInt((long)x)%(size)) //#define STMM_PTRHASH(x,size) ((int)((ABC_PTRUINT_T)(x)>>2)%size) // 64-bit bug fix 9/17/2007 #define STMM_PTRHASH(x,size) ((int)(((ABC_PTRUINT_T)(x)>>2)%size)) #define EQUAL(func, x, y) \ ((((func) == stmm_numcmp) || ((func) == stmm_ptrcmp)) ?\ (STMM_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0)) #define do_hash(key, table)\ ((table->hash == stmm_ptrhash) ? STMM_PTRHASH((key),(table)->num_bins) :\ (table->hash == stmm_numhash) ? STMM_NUMHASH((key), (table)->num_bins) :\ (*table->hash)((key), (table)->num_bins)) static int rehash (stmm_table *table); //int stmm_numhash (), stmm_ptrhash (), stmm_numcmp (), stmm_ptrcmp (); stmm_table * stmm_init_table_with_params (stmm_compare_func_type compare, stmm_hash_func_type hash, int size, int density, double grow_factor, int reorder_flag) { int i; stmm_table *newTable; newTable = ABC_ALLOC(stmm_table, 1); if (newTable == NULL) { return NULL; } newTable->compare = compare; newTable->hash = hash; newTable->num_entries = 0; newTable->max_density = density; newTable->grow_factor = grow_factor; newTable->reorder_flag = reorder_flag; if (size <= 0) { size = 1; } newTable->num_bins = size; newTable->bins = ABC_ALLOC(stmm_table_entry *, size); if (newTable->bins == NULL) { ABC_FREE(newTable); return NULL; } for (i = 0; i < size; i++) { newTable->bins[i] = 0; } // added by alanmi newTable->pMemMan = Extra_MmFixedStart(sizeof (stmm_table_entry)); return newTable; } stmm_table * stmm_init_table (stmm_compare_func_type compare, stmm_hash_func_type hash) { return stmm_init_table_with_params (compare, hash, STMM_DEFAULT_INIT_TABLE_SIZE, STMM_DEFAULT_MAX_DENSITY, STMM_DEFAULT_GROW_FACTOR, STMM_DEFAULT_REORDER_FLAG); } void stmm_free_table (stmm_table *table) { /* stmm_table_entry *ptr, *next; int i; for ( i = 0; i < table->num_bins; i++ ) { ptr = table->bins[i]; while ( ptr != NULL ) { next = ptr->next; ABC_FREE( ptr ); ptr = next; } } */ // no need to deallocate entries because they are in the memory manager now // added by alanmi if ( table->pMemMan ) Extra_MmFixedStop ((Extra_MmFixed_t *)table->pMemMan); ABC_FREE(table->bins); ABC_FREE(table); } // this function recycles all the bins void stmm_clean (stmm_table *table) { int i; // clean the bins for (i = 0; i < table->num_bins; i++) table->bins[i] = NULL; // reset the parameters table->num_entries = 0; // restart the memory manager Extra_MmFixedRestart ((Extra_MmFixed_t *)table->pMemMan); } #define PTR_NOT_EQUAL(table, ptr, user_key)\ (ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) #define FIND_ENTRY(table, hash_val, key, ptr, last) \ (last) = &(table)->bins[hash_val];\ (ptr) = *(last);\ while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ (last) = &(ptr)->next; (ptr) = *(last);\ }\ if ((ptr) != NULL && (table)->reorder_flag) {\ *(last) = (ptr)->next;\ (ptr)->next = (table)->bins[hash_val];\ (table)->bins[hash_val] = (ptr);\ } int stmm_lookup (stmm_table *table, char *key, char **value) { int hash_val; stmm_table_entry *ptr, **last; hash_val = do_hash (key, table); FIND_ENTRY (table, hash_val, key, ptr, last); if (ptr == NULL) { return 0; } else { if (value != NULL) { *value = ptr->record; } return 1; } } int stmm_lookup_int (stmm_table *table, char *key, int *value) { int hash_val; stmm_table_entry *ptr, **last; hash_val = do_hash (key, table); FIND_ENTRY (table, hash_val, key, ptr, last); if (ptr == NULL) { return 0; } else { if (value != 0) { *value = (long) ptr->record; } return 1; } } // This macro contained a line // new = ABC_ALLOC(stmm_table_entry, 1); // which was modified by alanmi /* This macro does not check if memory allocation fails. Use at you own risk */ #define ADD_DIRECT(table, key, value, hash_val, new)\ {\ if (table->num_entries/table->num_bins >= table->max_density) {\ rehash(table);\ hash_val = do_hash(key,table);\ }\ \ new = (stmm_table_entry *)Extra_MmFixedEntryFetch( (Extra_MmFixed_t *)table->pMemMan );\ \ new->key = key;\ new->record = value;\ new->next = table->bins[hash_val];\ table->bins[hash_val] = new;\ table->num_entries++;\ } int stmm_insert (stmm_table *table, char *key, char *value) { int hash_val; stmm_table_entry *newEntry; stmm_table_entry *ptr, **last; hash_val = do_hash (key, table); FIND_ENTRY (table, hash_val, key, ptr, last); if (ptr == NULL) { if (table->num_entries / table->num_bins >= table->max_density) { if (rehash (table) == STMM_OUT_OF_MEM) { return STMM_OUT_OF_MEM; } hash_val = do_hash (key, table); } // newEntry = ABC_ALLOC( stmm_table_entry, 1 ); newEntry = (stmm_table_entry *) Extra_MmFixedEntryFetch ((Extra_MmFixed_t *)table->pMemMan); if (newEntry == NULL) { return STMM_OUT_OF_MEM; } newEntry->key = key; newEntry->record = value; newEntry->next = table->bins[hash_val]; table->bins[hash_val] = newEntry; table->num_entries++; return 0; } else { ptr->record = value; return 1; } } int stmm_add_direct (stmm_table *table, char *key, char *value) { int hash_val; stmm_table_entry *newEntry; hash_val = do_hash (key, table); if (table->num_entries / table->num_bins >= table->max_density) { if (rehash (table) == STMM_OUT_OF_MEM) { return STMM_OUT_OF_MEM; } } hash_val = do_hash (key, table); // newEntry = ABC_ALLOC( stmm_table_entry, 1 ); newEntry = (stmm_table_entry *) Extra_MmFixedEntryFetch ((Extra_MmFixed_t *)table->pMemMan); if (newEntry == NULL) { return STMM_OUT_OF_MEM; } newEntry->key = key; newEntry->record = value; newEntry->next = table->bins[hash_val]; table->bins[hash_val] = newEntry; table->num_entries++; return 1; } int stmm_find_or_add (stmm_table *table, char *key, char ***slot) { int hash_val; stmm_table_entry *newEntry, *ptr, **last; hash_val = do_hash (key, table); FIND_ENTRY (table, hash_val, key, ptr, last); if (ptr == NULL) { if (table->num_entries / table->num_bins >= table->max_density) { if (rehash (table) == STMM_OUT_OF_MEM) { return STMM_OUT_OF_MEM; } hash_val = do_hash (key, table); } // newEntry = ABC_ALLOC( stmm_table_entry, 1 ); newEntry = (stmm_table_entry *) Extra_MmFixedEntryFetch ((Extra_MmFixed_t *)table->pMemMan); if (newEntry == NULL) { return STMM_OUT_OF_MEM; } newEntry->key = key; newEntry->record = (char *) 0; newEntry->next = table->bins[hash_val]; table->bins[hash_val] = newEntry; table->num_entries++; if (slot != NULL) *slot = &newEntry->record; return 0; } else { if (slot != NULL) *slot = &ptr->record; return 1; } } int stmm_find (stmm_table *table, char *key, char ***slot) { int hash_val; stmm_table_entry *ptr, **last; hash_val = do_hash (key, table); FIND_ENTRY (table, hash_val, key, ptr, last); if (ptr == NULL) { return 0; } else { if (slot != NULL) { *slot = &ptr->record; } return 1; } } static int rehash (stmm_table *table) { stmm_table_entry *ptr, *next, **old_bins; int i, old_num_bins, hash_val, old_num_entries; /* save old values */ old_bins = table->bins; old_num_bins = table->num_bins; old_num_entries = table->num_entries; /* rehash */ table->num_bins = (int) (table->grow_factor * old_num_bins); if (table->num_bins % 2 == 0) { table->num_bins += 1; } table->num_entries = 0; table->bins = ABC_ALLOC(stmm_table_entry *, table->num_bins); if (table->bins == NULL) { table->bins = old_bins; table->num_bins = old_num_bins; table->num_entries = old_num_entries; return STMM_OUT_OF_MEM; } /* initialize */ for (i = 0; i < table->num_bins; i++) { table->bins[i] = 0; } /* copy data over */ for (i = 0; i < old_num_bins; i++) { ptr = old_bins[i]; while (ptr != NULL) { next = ptr->next; hash_val = do_hash (ptr->key, table); ptr->next = table->bins[hash_val]; table->bins[hash_val] = ptr; table->num_entries++; ptr = next; } } ABC_FREE(old_bins); return 1; } stmm_table * stmm_copy (stmm_table *old_table) { stmm_table *newEntry_table; stmm_table_entry *ptr, /* *newEntryptr, *next, */ *newEntry; int i, /*j, */ num_bins = old_table->num_bins; newEntry_table = ABC_ALLOC(stmm_table, 1); if (newEntry_table == NULL) { return NULL; } *newEntry_table = *old_table; newEntry_table->bins = ABC_ALLOC(stmm_table_entry *, num_bins); if (newEntry_table->bins == NULL) { ABC_FREE(newEntry_table); return NULL; } // allocate the memory manager for the newEntry table newEntry_table->pMemMan = Extra_MmFixedStart (sizeof (stmm_table_entry)); for (i = 0; i < num_bins; i++) { newEntry_table->bins[i] = NULL; ptr = old_table->bins[i]; while (ptr != NULL) { // newEntry = ABC_ALLOC( stmm_table_entry, 1 ); newEntry = (stmm_table_entry *)Extra_MmFixedEntryFetch ((Extra_MmFixed_t *)newEntry_table->pMemMan); if (newEntry == NULL) { /* for ( j = 0; j <= i; j++ ) { newEntryptr = newEntry_table->bins[j]; while ( newEntryptr != NULL ) { next = newEntryptr->next; ABC_FREE( newEntryptr ); newEntryptr = next; } } */ Extra_MmFixedStop ((Extra_MmFixed_t *)newEntry_table->pMemMan); ABC_FREE(newEntry_table->bins); ABC_FREE(newEntry_table); return NULL; } *newEntry = *ptr; newEntry->next = newEntry_table->bins[i]; newEntry_table->bins[i] = newEntry; ptr = ptr->next; } } return newEntry_table; } int stmm_delete (stmm_table *table, char **keyp, char **value) { int hash_val; char *key = *keyp; stmm_table_entry *ptr, **last; hash_val = do_hash (key, table); FIND_ENTRY (table, hash_val, key, ptr, last); if (ptr == NULL) { return 0; } *last = ptr->next; if (value != NULL) *value = ptr->record; *keyp = ptr->key; // ABC_FREE( ptr ); Extra_MmFixedEntryRecycle ((Extra_MmFixed_t *)table->pMemMan, (char *) ptr); table->num_entries--; return 1; } int stmm_delete_int (stmm_table *table, long *keyp, char **value) { int hash_val; char *key = (char *) *keyp; stmm_table_entry *ptr, **last; hash_val = do_hash (key, table); FIND_ENTRY (table, hash_val, key, ptr, last); if (ptr == NULL) { return 0; } *last = ptr->next; if (value != NULL) *value = ptr->record; *keyp = (long) ptr->key; // ABC_FREE( ptr ); Extra_MmFixedEntryRecycle ((Extra_MmFixed_t *)table->pMemMan, (char *) ptr); table->num_entries--; return 1; } int stmm_foreach (stmm_table *table, enum stmm_retval (*func) (char *, char *, char *), char *arg) { stmm_table_entry *ptr, **last; enum stmm_retval retval; int i; for (i = 0; i < table->num_bins; i++) { last = &table->bins[i]; ptr = *last; while (ptr != NULL) { retval = (*func) (ptr->key, ptr->record, arg); switch (retval) { case STMM_CONTINUE: last = &ptr->next; ptr = *last; break; case STMM_STOP: return 0; case STMM_DELETE: *last = ptr->next; table->num_entries--; /* cstevens@ic */ // ABC_FREE( ptr ); Extra_MmFixedEntryRecycle ((Extra_MmFixed_t *)table->pMemMan, (char *) ptr); ptr = *last; } } } return 1; } int stmm_strhash (const char *string, int modulus) { int val = 0; int c; while ((c = *string++) != '\0') { val = val * 997 + c; } return ((val < 0) ? -val : val) % modulus; } int stmm_numhash (const char *x, int size) { return STMM_NUMHASH (x, size); } int stmm_ptrhash (const char *x, int size) { return STMM_PTRHASH (x, size); } int stmm_numcmp (const char *x, const char *y) { return STMM_NUMCMP (x, y); } int stmm_ptrcmp (const char *x, const char *y) { return STMM_NUMCMP (x, y); } stmm_generator * stmm_init_gen (stmm_table *table) { stmm_generator *gen; gen = ABC_ALLOC(stmm_generator, 1); if (gen == NULL) { return NULL; } gen->table = table; gen->entry = NULL; gen->index = 0; return gen; } int stmm_gen (stmm_generator *gen, char **key_p, char **value_p) { int i; if (gen->entry == NULL) { /* try to find next entry */ for (i = gen->index; i < gen->table->num_bins; i++) { if (gen->table->bins[i] != NULL) { gen->index = i + 1; gen->entry = gen->table->bins[i]; break; } } if (gen->entry == NULL) { return 0; /* that's all folks ! */ } } *key_p = gen->entry->key; if (value_p != 0) { *value_p = gen->entry->record; } gen->entry = gen->entry->next; return 1; } int stmm_gen_int (stmm_generator *gen, char **key_p, long *value_p) { int i; if (gen->entry == NULL) { /* try to find next entry */ for (i = gen->index; i < gen->table->num_bins; i++) { if (gen->table->bins[i] != NULL) { gen->index = i + 1; gen->entry = gen->table->bins[i]; break; } } if (gen->entry == NULL) { return 0; /* that's all folks ! */ } } *key_p = gen->entry->key; if (value_p != 0) { *value_p = (long) gen->entry->record; } gen->entry = gen->entry->next; return 1; } void stmm_free_gen (stmm_generator *gen) { ABC_FREE(gen); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/st/stmm.h000066400000000000000000000103111300674244400225420ustar00rootroot00000000000000/* * Revision Control Information * * /projects/hsis/CVS/utilities/st/st.h,v * serdar * 1.1 * 1993/07/29 01:00:21 * */ /* LINTLIBRARY */ /* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ #ifndef ABC__misc__st__stmm_h #define ABC__misc__st__stmm_h #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START /* These are potential duplicates. */ #ifndef EXTERN # ifdef __cplusplus # ifdef ABC_NAMESPACE # define EXTERN extern # else # define EXTERN extern "C" # endif # else # define EXTERN extern # endif #endif #ifndef ARGS #define ARGS(protos) protos #endif typedef int (*stmm_compare_func_type)(const char*, const char*); typedef int (*stmm_hash_func_type)(const char*, int); typedef struct stmm_table_entry stmm_table_entry; typedef struct stmm_table stmm_table; typedef struct stmm_generator stmm_generator; struct stmm_table_entry { char *key; char *record; stmm_table_entry *next; }; struct stmm_table { stmm_compare_func_type compare; stmm_hash_func_type hash; int num_bins; int num_entries; int max_density; int reorder_flag; double grow_factor; stmm_table_entry **bins; // memory manager to improve runtime and prevent memory fragmentation // added by alanmi - January 16, 2003 void * pMemMan; }; struct stmm_generator { stmm_table *table; stmm_table_entry *entry; int index; }; #define stmm_is_member(table,key) stmm_lookup(table,key,(char **) 0) #define stmm_count(table) ((table)->num_entries) enum stmm_retval { STMM_CONTINUE, STMM_STOP, STMM_DELETE }; typedef enum stmm_retval (*STMM_PFSR) (char *, char *, char *); EXTERN stmm_table *stmm_init_table_with_params ARGS ((stmm_compare_func_type compare, stmm_hash_func_type hash, int size, int density, double grow_factor, int reorder_flag)); EXTERN stmm_table *stmm_init_table ARGS ((stmm_compare_func_type, stmm_hash_func_type)); EXTERN void stmm_free_table ARGS ((stmm_table *)); EXTERN int stmm_lookup ARGS ((stmm_table *, char *, char **)); EXTERN int stmm_lookup_int ARGS ((stmm_table *, char *, int *)); EXTERN int stmm_insert ARGS ((stmm_table *, char *, char *)); EXTERN int stmm_add_direct ARGS ((stmm_table *, char *, char *)); EXTERN int stmm_find_or_add ARGS ((stmm_table *, char *, char ***)); EXTERN int stmm_find ARGS ((stmm_table *, char *, char ***)); EXTERN stmm_table *stmm_copy ARGS ((stmm_table *)); EXTERN int stmm_delete ARGS ((stmm_table *, char **, char **)); EXTERN int stmm_delete_int ARGS ((stmm_table *, long *, char **)); EXTERN int stmm_foreach ARGS ((stmm_table *, STMM_PFSR, char *)); EXTERN int stmm_strhash ARGS ((const char *, int)); EXTERN int stmm_numhash ARGS ((const char *, int)); EXTERN int stmm_ptrhash ARGS ((const char *, int)); EXTERN int stmm_numcmp ARGS ((const char *, const char *)); EXTERN int stmm_ptrcmp ARGS ((const char *, const char *)); EXTERN stmm_generator *stmm_init_gen ARGS ((stmm_table *)); EXTERN int stmm_gen ARGS ((stmm_generator *, char **, char **)); EXTERN int stmm_gen_int ARGS ((stmm_generator *, char **, long *)); EXTERN void stmm_free_gen ARGS ((stmm_generator *)); // additional functions EXTERN void stmm_clean ARGS ((stmm_table *)); #define STMM_DEFAULT_MAX_DENSITY 5 #define STMM_DEFAULT_INIT_TABLE_SIZE 11 #define STMM_DEFAULT_GROW_FACTOR 2.0 #define STMM_DEFAULT_REORDER_FLAG 0 // added by Zhihong: no need for memory allocation #define stmm_foreach_item2(tb, /* stmm_generator */gen, key, value) \ for(gen.table=(tb), gen.entry=NULL, gen.index=0; \ stmm_gen(&(gen),key,value);) #define stmm_foreach_item(table, gen, key, value) \ for(gen=stmm_init_gen(table); stmm_gen(gen,key,value) || (stmm_free_gen(gen),0);) #define stmm_foreach_item_int(table, gen, key, value) \ for(gen=stmm_init_gen(table); stmm_gen_int(gen,key,value) || (stmm_free_gen(gen),0);) #define STMM_OUT_OF_MEM -10000 /* // consider adding these other other similar definitions #define st__table stmm_table #define st__insert stmm_insert #define st__delete stmm_delete #define st__lookup stmm_lookup #define st__init_table stmm_init_table #define st__free_table stmm_free_table */ ABC_NAMESPACE_HEADER_END #endif /* STMM_INCLUDED */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/000077500000000000000000000000001300674244400215605ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/module.make000066400000000000000000000002041300674244400237000ustar00rootroot00000000000000SRC += src/misc/tim/timBox.c \ src/misc/tim/timDump.c \ src/misc/tim/timMan.c \ src/misc/tim/timTime.c \ src/misc/tim/timTrav.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/tim.c000066400000000000000000000023421300674244400225160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [tim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchy/timing manager.] Synopsis [Representation of timing information.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: tim.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "timInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/tim.h000066400000000000000000000236141300674244400225300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [tim.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchy/timing manager.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: tim.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__tim__tim_h #define ABC__aig__tim__tim_h /* The data-structure Tim_Man_t implemented in this package stores two types of information: (1) hierarchical information about the connectivity of a combinational logic network with combinational logic node and combinational white boxes (2) timing information about input-to-output delays of each combinational white box. This data-structure is closely coupled with the AIG manager extracted from the same combinational logic network. The AIG manager represents combinational logic surrounding white boxes, and contains additional PIs/POs corresponding to the outputs/inputs of the white boxes. The manager Tim_Man_t is created by a call to Tim_ManStart(). The arguments of this call are the total number of all combinational inputs/output in the extracted AIG. (Note that this number is different from the number of inputs/outputs of the combinational logic network, because the extracted AIG will have additional inputs/output due to white boxes.) The extracted AIG and the corresponding Tim_Man_t may be created at the same time or at separate times. The following guideline assumes concurrent creation. First, PIs of the AIG are created in 1-to-1 correspondence with the PIs of the original network. Next, all nodes (logic nodes and white boxes) of the network are traversed in a topologic order. When a white box is encountered, the TFI cone of box inputs are tranversed and all new logic nodes encoutered added to the AIG. Then, the white box is created by the call to Tim_ManCreateBox(). Then, new POs of the AIG are created in 1-to-1 correspondence with box inputs. Then, new PIs of the AIG are created in 1-to-1 correspondence with box outputs. Finally, the TFO cone of the POs is traversed and all new logic nodes encountered added to the AIG. In the end, the POs of the AIG is constructed in 1-to-1 correspondence with the PIs of the original combinational logic network. Delay tables representing input-to-output delays of each type of white box should be computed in advance and given to the timing manager in one array through the API Tim_ManSetDelayTables(). When each box is constructed, the delay table ID of this box (which is the index of the table in the above array) is given as the last argument 'iDelayTable' in Tim_ManCreateBox(). A delay table is a one-dimensional array of floats whose size is: 3 + nInputs * nOutputs. The first entry is the delay table ID used by the boxes to refer to the table. The second and third entries are nInputs and nOutputs. The following 'nInputs * nOutputs' entries are delay numbers for each output, that is, the first set of nInputs entries give delay of the first output. the second set of nInputs entries give delay of the second output, etc. The Tim_Man_t is typically associated with the AIG manager (pGia) using pointer (pGia->pManTime). It is automatically deallocated when the host AIG manager is deleted. */ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Tim_Man_t_ Tim_Man_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define TIM_ETERNITY 1000000000 //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// SEQUENTIAL ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== timBox.c ===========================================================*/ extern void Tim_ManCreateBox( Tim_Man_t * p, int firstIn, int nIns, int firstOut, int nOuts, int iDelayTable, int fBlack ); extern int Tim_ManBoxForCi( Tim_Man_t * p, int iCo ); extern int Tim_ManBoxForCo( Tim_Man_t * p, int iCi ); extern int Tim_ManBoxInputFirst( Tim_Man_t * p, int iBox ); extern int Tim_ManBoxInputLast( Tim_Man_t * p, int iBox ); extern int Tim_ManBoxOutputFirst( Tim_Man_t * p, int iBox ); extern int Tim_ManBoxOutputLast( Tim_Man_t * p, int iBox ); extern int Tim_ManBoxInputNum( Tim_Man_t * p, int iBox ); extern int Tim_ManBoxOutputNum( Tim_Man_t * p, int iBox ); extern int Tim_ManBoxDelayTableId( Tim_Man_t * p, int iBox ); extern float * Tim_ManBoxDelayTable( Tim_Man_t * p, int iBox ); extern int Tim_ManBoxIsBlack( Tim_Man_t * p, int iBox ); extern int Tim_ManBoxCopy( Tim_Man_t * p, int iBox ); extern void Tim_ManBoxSetCopy( Tim_Man_t * p, int iBox, int iCopy ); extern int Tim_ManBoxFindFromCiNum( Tim_Man_t * p, int iCiNum ); /*=== timDump.c ===========================================================*/ extern Vec_Str_t * Tim_ManSave( Tim_Man_t * p, int fHieOnly ); extern Tim_Man_t * Tim_ManLoad( Vec_Str_t * p, int fHieOnly ); /*=== timMan.c ===========================================================*/ extern Tim_Man_t * Tim_ManStart( int nCis, int nCos ); extern Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fUnitDelay ); extern Tim_Man_t * Tim_ManTrim( Tim_Man_t * p, Vec_Int_t * vBoxPres ); extern Tim_Man_t * Tim_ManReduce( Tim_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff ); extern Vec_Int_t * Tim_ManAlignTwo( Tim_Man_t * pSpec, Tim_Man_t * pImpl ); extern void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs ); extern float * Tim_ManGetArrTimes( Tim_Man_t * p ); extern float * Tim_ManGetReqTimes( Tim_Man_t * p ); extern void Tim_ManStop( Tim_Man_t * p ); extern void Tim_ManStopP( Tim_Man_t ** p ); extern void Tim_ManPrint( Tim_Man_t * p ); extern void Tim_ManPrintStats( Tim_Man_t * p, int nAnd2Delay ); extern int Tim_ManCiNum( Tim_Man_t * p ); extern int Tim_ManCoNum( Tim_Man_t * p ); extern int Tim_ManPiNum( Tim_Man_t * p ); extern int Tim_ManPoNum( Tim_Man_t * p ); extern int Tim_ManBoxNum( Tim_Man_t * p ); extern int Tim_ManBlackBoxNum( Tim_Man_t * p ); extern void Tim_ManBlackBoxIoNum( Tim_Man_t * p, int * pnBbIns, int * pnBbOuts ); extern int Tim_ManDelayTableNum( Tim_Man_t * p ); extern void Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables ); extern void Tim_ManTravIdDisable( Tim_Man_t * p ); extern void Tim_ManTravIdEnable( Tim_Man_t * p ); /*=== timTime.c ===========================================================*/ extern void Tim_ManInitPiArrival( Tim_Man_t * p, int iPi, float Delay ); extern void Tim_ManInitPoRequired( Tim_Man_t * p, int iPo, float Delay ); extern void Tim_ManInitPiArrivalAll( Tim_Man_t * p, float Delay ); extern void Tim_ManInitPoRequiredAll( Tim_Man_t * p, float Delay ); extern void Tim_ManSetCoArrival( Tim_Man_t * p, int iCo, float Delay ); extern void Tim_ManSetCiRequired( Tim_Man_t * p, int iCi, float Delay ); extern void Tim_ManSetCoRequired( Tim_Man_t * p, int iCo, float Delay ); extern float Tim_ManGetCiArrival( Tim_Man_t * p, int iCi ); extern float Tim_ManGetCoRequired( Tim_Man_t * p, int iCo ); /*=== timTrav.c ===========================================================*/ extern void Tim_ManIncrementTravId( Tim_Man_t * p ); extern void Tim_ManSetCurrentTravIdBoxInputs( Tim_Man_t * p, int iBox ); extern void Tim_ManSetCurrentTravIdBoxOutputs( Tim_Man_t * p, int iBox ); extern void Tim_ManSetPreviousTravIdBoxInputs( Tim_Man_t * p, int iBox ); extern void Tim_ManSetPreviousTravIdBoxOutputs( Tim_Man_t * p, int iBox ); extern int Tim_ManIsCiTravIdCurrent( Tim_Man_t * p, int iCi ); extern int Tim_ManIsCoTravIdCurrent( Tim_Man_t * p, int iCo ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/timBox.c000066400000000000000000000207521300674244400231740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [timBox.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchy/timing manager.] Synopsis [Manipulation of timing boxes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: timBox.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "timInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the new timing box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManCreateBox( Tim_Man_t * p, int firstIn, int nIns, int firstOut, int nOuts, int iDelayTable, int fBlack ) { Tim_Box_t * pBox; int i; if ( p->vBoxes == NULL ) p->vBoxes = Vec_PtrAlloc( 100 ); pBox = (Tim_Box_t *)Mem_FlexEntryFetch( p->pMemObj, sizeof(Tim_Box_t) + sizeof(int) * (nIns+nOuts) ); memset( pBox, 0, sizeof(Tim_Box_t) ); pBox->iBox = Vec_PtrSize( p->vBoxes ); Vec_PtrPush( p->vBoxes, pBox ); pBox->iDelayTable = iDelayTable; pBox->nInputs = nIns; pBox->nOutputs = nOuts; pBox->fBlack = fBlack; for ( i = 0; i < nIns; i++ ) { assert( firstIn+i < p->nCos ); pBox->Inouts[i] = firstIn+i; p->pCos[firstIn+i].iObj2Box = pBox->iBox; p->pCos[firstIn+i].iObj2Num = i; } for ( i = 0; i < nOuts; i++ ) { assert( firstOut+i < p->nCis ); pBox->Inouts[nIns+i] = firstOut+i; p->pCis[firstOut+i].iObj2Box = pBox->iBox; p->pCis[firstOut+i].iObj2Num = i; } // if ( pBox->iBox < 20 ) // printf( "%4d %4d %4d %4d \n", firstIn, nIns, firstOut, nOuts ); } /**Function************************************************************* Synopsis [Returns the box number for the given input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxForCi( Tim_Man_t * p, int iCi ) { if ( iCi >= p->nCis ) return -1; return p->pCis[iCi].iObj2Box; } /**Function************************************************************* Synopsis [Returns the box number for the given output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxForCo( Tim_Man_t * p, int iCo ) { if ( iCo >= p->nCos ) return -1; return p->pCos[iCo].iObj2Box; } /**Function************************************************************* Synopsis [Returns the first input of the box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxInputFirst( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->Inouts[0]; } /**Function************************************************************* Synopsis [Returns the last input of the box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxInputLast( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->Inouts[0] + Tim_ManBoxInputNum(p, iBox) - 1; } /**Function************************************************************* Synopsis [Returns the first output of the box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxOutputFirst( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->Inouts[Tim_ManBox(p, iBox)->nInputs]; } /**Function************************************************************* Synopsis [Returns the last output of the box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxOutputLast( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->Inouts[Tim_ManBox(p, iBox)->nInputs] + Tim_ManBoxOutputNum(p, iBox) - 1; } /**Function************************************************************* Synopsis [Returns the number of box inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxInputNum( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->nInputs; } /**Function************************************************************* Synopsis [Returns the number of box outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxOutputNum( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->nOutputs; } /**Function************************************************************* Synopsis [Return the delay table id.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxDelayTableId( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->iDelayTable; } /**Function************************************************************* Synopsis [Return the delay table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float * Tim_ManBoxDelayTable( Tim_Man_t * p, int iBox ) { float * pTable; Tim_Box_t * pBox = Tim_ManBox(p, iBox); if ( pBox->iDelayTable < 0 ) return NULL; pTable = (float *)Vec_PtrEntry( p->vDelayTables, pBox->iDelayTable ); assert( (int)pTable[1] == pBox->nInputs ); assert( (int)pTable[2] == pBox->nOutputs ); return pTable; } /**Function************************************************************* Synopsis [Return 1 if the box is black.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxIsBlack( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->fBlack; } /**Function************************************************************* Synopsis [Returns the copy of the box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxCopy( Tim_Man_t * p, int iBox ) { return Tim_ManBox(p, iBox)->iCopy; } /**Function************************************************************* Synopsis [Sets the copy of the box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManBoxSetCopy( Tim_Man_t * p, int iBox, int iCopy ) { Tim_ManBox(p, iBox)->iCopy = iCopy; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManBoxFindFromCiNum( Tim_Man_t * p, int iCiNum ) { Tim_Box_t * pBox; int i; assert( iCiNum >= 0 && iCiNum < Tim_ManCiNum(p) ); if ( iCiNum < Tim_ManPiNum(p) ) return -1; Tim_ManForEachBox( p, pBox, i ) if ( iCiNum < Tim_ManBoxOutputFirst(p, i) ) return i - 1; return -2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/timDump.c000066400000000000000000000156251300674244400233540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [timDump.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchy/timing manager.] Synopsis [Saving and loading the hierarchy timing manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: timDump.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "timInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define TIM_DUMP_VER_NUM 1 //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transform the timing manager into the char stream.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Tim_ManSave( Tim_Man_t * p, int fHieOnly ) { Tim_Box_t * pBox; Tim_Obj_t * pObj; Vec_Str_t * vStr; float * pDelayTable; int i, k, TableSize; // create output stream vStr = Vec_StrAlloc( 10000 ); // dump version number Vec_StrPutI_ne( vStr, TIM_DUMP_VER_NUM ); // save CI/CO counts Vec_StrPutI_ne( vStr, Tim_ManCiNum(p) ); Vec_StrPutI_ne( vStr, Tim_ManCoNum(p) ); // save PI/PO counts Vec_StrPutI_ne( vStr, Tim_ManPiNum(p) ); Vec_StrPutI_ne( vStr, Tim_ManPoNum(p) ); // save number of boxes Vec_StrPutI_ne( vStr, Tim_ManBoxNum(p) ); // for each box, save num_inputs, num_outputs, delay table ID, and copy field if ( Tim_ManBoxNum(p) > 0 ) Tim_ManForEachBox( p, pBox, i ) { Vec_StrPutI_ne( vStr, Tim_ManBoxInputNum(p, pBox->iBox) ); Vec_StrPutI_ne( vStr, Tim_ManBoxOutputNum(p, pBox->iBox) ); Vec_StrPutI_ne( vStr, Tim_ManBoxDelayTableId(p, pBox->iBox) ); // can be -1 if delay table is not given Vec_StrPutI_ne( vStr, Tim_ManBoxCopy(p, pBox->iBox) ); // can be -1 if the copy is node defined //Vec_StrPutI_ne( vStr, Tim_ManBoxIsBlack(p, pBox->iBox) ); } if ( fHieOnly ) return vStr; // save the number of delay tables Vec_StrPutI_ne( vStr, Tim_ManDelayTableNum(p) ); // save the delay tables if ( Tim_ManDelayTableNum(p) > 0 ) Tim_ManForEachTable( p, pDelayTable, i ) { assert( (int)pDelayTable[0] == i ); // save table ID and dimensions (inputs x outputs) Vec_StrPutI_ne( vStr, (int)pDelayTable[0] ); Vec_StrPutI_ne( vStr, (int)pDelayTable[1] ); Vec_StrPutI_ne( vStr, (int)pDelayTable[2] ); // save table contents TableSize = (int)pDelayTable[1] * (int)pDelayTable[2]; for ( k = 0; k < TableSize; k++ ) Vec_StrPutF( vStr, pDelayTable[k+3] ); } // save PI arrival times Tim_ManForEachPi( p, pObj, i ) Vec_StrPutF( vStr, Tim_ManGetCiArrival(p, pObj->Id) ); // save PO required times Tim_ManForEachPo( p, pObj, i ) Vec_StrPutF( vStr, Tim_ManGetCoRequired(p, pObj->Id) ); return vStr; } /**Function************************************************************* Synopsis [Restores the timing manager from the char stream.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tim_Man_t * Tim_ManLoad( Vec_Str_t * p, int fHieOnly ) { Tim_Man_t * pMan; Tim_Obj_t * pObj; int VerNum, nCis, nCos, nPis, nPos; int nBoxes, nBoxIns, nBoxOuts, CopyBox, fBlack; int TableId, nTables, TableSize, TableX, TableY; int i, k, curPi, curPo, iStr = 0; float * pDelayTable; // get version number VerNum = Vec_StrGetI_ne( p, &iStr ); assert( VerNum == TIM_DUMP_VER_NUM ); // get the number of CIs/COs nCis = Vec_StrGetI_ne( p, &iStr ); nCos = Vec_StrGetI_ne( p, &iStr ); // get the number of PIs/POs nPis = Vec_StrGetI_ne( p, &iStr ); nPos = Vec_StrGetI_ne( p, &iStr ); // start the timing manager pMan = Tim_ManStart( nCis, nCos ); // start boxes nBoxes = Vec_StrGetI_ne( p, &iStr ); assert( pMan->vBoxes == NULL ); if ( nBoxes > 0 ) pMan->vBoxes = Vec_PtrAlloc( nBoxes ); // create boxes curPi = nPis; curPo = 0; for ( i = 0; i < nBoxes; i++ ) { nBoxIns = Vec_StrGetI_ne( p, &iStr ); nBoxOuts = Vec_StrGetI_ne( p, &iStr ); TableId = Vec_StrGetI_ne( p, &iStr ); CopyBox = Vec_StrGetI_ne( p, &iStr ); fBlack = 0;//Vec_StrGetI_ne( p, &iStr ); Tim_ManCreateBox( pMan, curPo, nBoxIns, curPi, nBoxOuts, TableId, fBlack ); Tim_ManBoxSetCopy( pMan, i, CopyBox ); curPi += nBoxOuts; curPo += nBoxIns; } curPo += nPos; assert( curPi == nCis ); assert( curPo == nCos ); if ( fHieOnly ) return pMan; // create delay tables nTables = Vec_StrGetI_ne( p, &iStr ); assert( pMan->vDelayTables == NULL ); if ( nTables > 0 ) pMan->vDelayTables = Vec_PtrAlloc( nTables ); // read delay tables for ( i = 0; i < nTables; i++ ) { // read table ID and dimensions TableId = Vec_StrGetI_ne( p, &iStr ); TableX = Vec_StrGetI_ne( p, &iStr ); TableY = Vec_StrGetI_ne( p, &iStr ); assert( TableId == i ); // create new table TableSize = TableX * TableY; pDelayTable = ABC_ALLOC( float, TableSize + 3 ); pDelayTable[0] = TableId; pDelayTable[1] = TableX; pDelayTable[2] = TableY; // read table contents for ( k = 0; k < TableSize; k++ ) pDelayTable[k+3] = Vec_StrGetF( p, &iStr ); assert( Vec_PtrSize(pMan->vDelayTables) == TableId ); Vec_PtrPush( pMan->vDelayTables, pDelayTable ); } assert( Tim_ManDelayTableNum(pMan) == nTables ); // read PI arrival times Tim_ManForEachPi( pMan, pObj, i ) Tim_ManInitPiArrival( pMan, i, Vec_StrGetF(p, &iStr) ); // read PO required times Tim_ManForEachPo( pMan, pObj, i ) Tim_ManInitPoRequired( pMan, i, Vec_StrGetF(p, &iStr) ); assert( Vec_StrSize(p) == iStr ); // Tim_ManPrint( pMan ); return pMan; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/timInt.h000066400000000000000000000151761300674244400232070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [timInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchy/timing manager.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: timInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__tim__timInt_h #define ABC__aig__tim__timInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "misc/mem/mem.h" #include "tim.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Tim_Box_t_ Tim_Box_t; typedef struct Tim_Obj_t_ Tim_Obj_t; // timing manager struct Tim_Man_t_ { Vec_Ptr_t * vBoxes; // the timing boxes Vec_Ptr_t * vDelayTables; // pointers to the delay tables Mem_Flex_t * pMemObj; // memory manager for boxes int nTravIds; // traversal ID of the manager int fUseTravId; // enables the use of traversal ID int nCis; // the number of PIs int nCos; // the number of POs Tim_Obj_t * pCis; // timing info for the PIs Tim_Obj_t * pCos; // timing info for the POs }; // timing box struct Tim_Box_t_ { int iBox; // the unique ID of this box int TravId; // traversal ID of this box int nInputs; // the number of box inputs (POs) int nOutputs; // the number of box outputs (PIs) int iDelayTable; // index of the delay table int iCopy; // copy of this box int fBlack; // this is black box int Inouts[0]; // the int numbers of PIs and POs }; // timing object struct Tim_Obj_t_ { int Id; // the ID of this object int TravId; // traversal ID of this object int iObj2Box; // mapping of the object into its box int iObj2Num; // mapping of the object into its number in the box float timeArr; // arrival time of the object float timeReq; // required time of the object }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline Tim_Obj_t * Tim_ManCi( Tim_Man_t * p, int i ) { assert( i < p->nCis ); return p->pCis + i; } static inline Tim_Obj_t * Tim_ManCo( Tim_Man_t * p, int i ) { assert( i < p->nCos ); return p->pCos + i; } static inline Tim_Box_t * Tim_ManBox( Tim_Man_t * p, int i ) { return (Tim_Box_t *)Vec_PtrEntry(p->vBoxes, i); } static inline Tim_Box_t * Tim_ManCiBox( Tim_Man_t * p, int i ) { return Tim_ManCi(p,i)->iObj2Box < 0 ? NULL : (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, Tim_ManCi(p,i)->iObj2Box ); } static inline Tim_Box_t * Tim_ManCoBox( Tim_Man_t * p, int i ) { return Tim_ManCo(p,i)->iObj2Box < 0 ? NULL : (Tim_Box_t *)Vec_PtrEntry( p->vBoxes, Tim_ManCo(p,i)->iObj2Box ); } static inline Tim_Obj_t * Tim_ManBoxInput( Tim_Man_t * p, Tim_Box_t * pBox, int i ) { assert( i < pBox->nInputs ); return p->pCos + pBox->Inouts[i]; } static inline Tim_Obj_t * Tim_ManBoxOutput( Tim_Man_t * p, Tim_Box_t * pBox, int i ) { assert( i < pBox->nOutputs ); return p->pCis + pBox->Inouts[pBox->nInputs+i]; } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// #define Tim_ManForEachCi( p, pObj, i ) \ for ( i = 0; (i < (p)->nCis) && ((pObj) = (p)->pCis + i); i++ ) #define Tim_ManForEachCo( p, pObj, i ) \ for ( i = 0; (i < (p)->nCos) && ((pObj) = (p)->pCos + i); i++ ) #define Tim_ManForEachPi( p, pObj, i ) \ Tim_ManForEachCi( p, pObj, i ) if ( pObj->iObj2Box >= 0 ) {} else #define Tim_ManForEachPo( p, pObj, i ) \ Tim_ManForEachCo( p, pObj, i ) if ( pObj->iObj2Box >= 0 ) {} else #define Tim_ManForEachBox( p, pBox, i ) \ Vec_PtrForEachEntry( Tim_Box_t *, p->vBoxes, pBox, i ) #define Tim_ManBoxForEachInput( p, pBox, pObj, i ) \ for ( i = 0; (i < (pBox)->nInputs) && ((pObj) = Tim_ManBoxInput(p, pBox, i)); i++ ) #define Tim_ManBoxForEachOutput( p, pBox, pObj, i ) \ for ( i = 0; (i < (pBox)->nOutputs) && ((pObj) = Tim_ManBoxOutput(p, pBox, i)); i++ ) #define Tim_ManForEachTable( p, pTable, i ) \ Vec_PtrForEachEntry( float *, p->vDelayTables, pTable, i ) //////////////////////////////////////////////////////////////////////// /// SEQUENTIAL ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== time.c ===========================================================*/ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/timMan.c000066400000000000000000000642471300674244400231660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [timMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchy/timing manager.] Synopsis [Manipulation of manager data-structure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: timMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "timInt.h" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tim_Man_t * Tim_ManStart( int nCis, int nCos ) { Tim_Man_t * p; Tim_Obj_t * pObj; int i; p = ABC_ALLOC( Tim_Man_t, 1 ); memset( p, 0, sizeof(Tim_Man_t) ); p->pMemObj = Mem_FlexStart(); p->nCis = nCis; p->nCos = nCos; p->pCis = ABC_ALLOC( Tim_Obj_t, nCis ); memset( p->pCis, 0, sizeof(Tim_Obj_t) * nCis ); p->pCos = ABC_ALLOC( Tim_Obj_t, nCos ); memset( p->pCos, 0, sizeof(Tim_Obj_t) * nCos ); Tim_ManForEachCi( p, pObj, i ) { pObj->Id = i; pObj->iObj2Box = pObj->iObj2Num = -1; pObj->timeReq = TIM_ETERNITY; } Tim_ManForEachCo( p, pObj, i ) { pObj->Id = i; pObj->iObj2Box = pObj->iObj2Num = -1; pObj->timeReq = TIM_ETERNITY; } p->fUseTravId = 1; return p; } /**Function************************************************************* Synopsis [Duplicates the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fUnitDelay ) { Tim_Man_t * pNew; Tim_Box_t * pBox; Tim_Obj_t * pObj; float * pDelayTable, * pDelayTableNew; int i, k, nInputs, nOutputs; // clear traversal IDs Tim_ManForEachCi( p, pObj, i ) pObj->TravId = 0; Tim_ManForEachCo( p, pObj, i ) pObj->TravId = 0; // create new manager pNew = Tim_ManStart( p->nCis, p->nCos ); // copy box connectivity information memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * p->nCis ); memcpy( pNew->pCos, p->pCos, sizeof(Tim_Obj_t) * p->nCos ); if ( fUnitDelay ) { // discretize PI arrival times // Tim_ManForEachPi( pNew, pObj, k ) // pObj->timeArr = (int)pObj->timeArr; // discretize PO required times // Tim_ManForEachPo( pNew, pObj, k ) // pObj->timeReq = 1 + (int)pObj->timeReq; // clear PI arrival and PO required Tim_ManInitPiArrivalAll( p, 0.0 ); Tim_ManInitPoRequiredAll( p, (float)TIM_ETERNITY ); } // duplicate delay tables if ( Tim_ManDelayTableNum(p) > 0 ) { pNew->vDelayTables = Vec_PtrStart( Vec_PtrSize(p->vDelayTables) ); Tim_ManForEachTable( p, pDelayTable, i ) { if ( pDelayTable == NULL ) continue; assert( i == (int)pDelayTable[0] ); nInputs = (int)pDelayTable[1]; nOutputs = (int)pDelayTable[2]; pDelayTableNew = ABC_ALLOC( float, 3 + nInputs * nOutputs ); pDelayTableNew[0] = (int)pDelayTable[0]; pDelayTableNew[1] = (int)pDelayTable[1]; pDelayTableNew[2] = (int)pDelayTable[2]; for ( k = 0; k < nInputs * nOutputs; k++ ) if ( pDelayTable[3+k] == -ABC_INFINITY ) pDelayTableNew[3+k] = -ABC_INFINITY; else pDelayTableNew[3+k] = fUnitDelay ? (float)fUnitDelay : pDelayTable[3+k]; // assert( (int)pDelayTableNew[0] == Vec_PtrSize(pNew->vDelayTables) ); assert( Vec_PtrEntry(pNew->vDelayTables, i) == NULL ); Vec_PtrWriteEntry( pNew->vDelayTables, i, pDelayTableNew ); //printf( "Finished duplicating delay table %d.\n", i ); } } // duplicate boxes if ( Tim_ManBoxNum(p) > 0 ) { pNew->vBoxes = Vec_PtrAlloc( Tim_ManBoxNum(p) ); Tim_ManForEachBox( p, pBox, i ) { Tim_ManCreateBox( pNew, pBox->Inouts[0], pBox->nInputs, pBox->Inouts[pBox->nInputs], pBox->nOutputs, pBox->iDelayTable, pBox->fBlack ); Tim_ManBoxSetCopy( pNew, i, pBox->iCopy ); } } return pNew; } /**Function************************************************************* Synopsis [Trims the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tim_Man_t * Tim_ManTrim( Tim_Man_t * p, Vec_Int_t * vBoxPres ) { Tim_Man_t * pNew; Tim_Box_t * pBox; Tim_Obj_t * pObj; float * pDelayTable, * pDelayTableNew; int i, k, nNewCis, nNewCos, nInputs, nOutputs; assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(p) ); // count the number of CIs and COs in the trimmed manager nNewCis = Tim_ManPiNum(p); nNewCos = Tim_ManPoNum(p); if ( Tim_ManBoxNum(p) ) Tim_ManForEachBox( p, pBox, i ) if ( Vec_IntEntry(vBoxPres, i) ) { nNewCis += pBox->nOutputs; nNewCos += pBox->nInputs; } if ( nNewCis == Tim_ManCiNum(p) && nNewCos == Tim_ManCoNum(p) ) return Tim_ManDup( p, 0 ); assert( nNewCis < Tim_ManCiNum(p) ); assert( nNewCos < Tim_ManCoNum(p) ); // clear traversal IDs Tim_ManForEachCi( p, pObj, i ) pObj->TravId = 0; Tim_ManForEachCo( p, pObj, i ) pObj->TravId = 0; // create new manager pNew = Tim_ManStart( nNewCis, nNewCos ); // copy box connectivity information memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * Tim_ManPiNum(p) ); memcpy( pNew->pCos + nNewCos - Tim_ManPoNum(p), p->pCos + Tim_ManCoNum(p) - Tim_ManPoNum(p), sizeof(Tim_Obj_t) * Tim_ManPoNum(p) ); // duplicate delay tables if ( Tim_ManDelayTableNum(p) > 0 ) { pNew->vDelayTables = Vec_PtrStart( Vec_PtrSize(p->vDelayTables) ); Tim_ManForEachTable( p, pDelayTable, i ) { if ( pDelayTable == NULL ) continue; assert( i == (int)pDelayTable[0] ); nInputs = (int)pDelayTable[1]; nOutputs = (int)pDelayTable[2]; pDelayTableNew = ABC_ALLOC( float, 3 + nInputs * nOutputs ); pDelayTableNew[0] = (int)pDelayTable[0]; pDelayTableNew[1] = (int)pDelayTable[1]; pDelayTableNew[2] = (int)pDelayTable[2]; for ( k = 0; k < nInputs * nOutputs; k++ ) pDelayTableNew[3+k] = pDelayTable[3+k]; // assert( (int)pDelayTableNew[0] == Vec_PtrSize(pNew->vDelayTables) ); assert( Vec_PtrEntry(pNew->vDelayTables, i) == NULL ); Vec_PtrWriteEntry( pNew->vDelayTables, i, pDelayTableNew ); } } // duplicate boxes if ( Tim_ManBoxNum(p) > 0 ) { int curPi = Tim_ManPiNum(p); int curPo = 0; pNew->vBoxes = Vec_PtrAlloc( Tim_ManBoxNum(p) ); Tim_ManForEachBox( p, pBox, i ) if ( Vec_IntEntry(vBoxPres, i) ) { Tim_ManCreateBox( pNew, curPo, pBox->nInputs, curPi, pBox->nOutputs, pBox->iDelayTable, pBox->fBlack ); Tim_ManBoxSetCopy( pNew, Tim_ManBoxNum(pNew) - 1, Tim_ManBoxCopy(p, i) == -1 ? i : Tim_ManBoxCopy(p, i) ); curPi += pBox->nOutputs; curPo += pBox->nInputs; } curPo += Tim_ManPoNum(p); assert( curPi == Tim_ManCiNum(pNew) ); assert( curPo == Tim_ManCoNum(pNew) ); } return pNew; } /**Function************************************************************* Synopsis [Reduces the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tim_Man_t * Tim_ManReduce( Tim_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff ) { Tim_Man_t * pNew; Tim_Box_t * pBox; Tim_Obj_t * pObj; float * pDelayTable, * pDelayTableNew; int i, k, iBox, nNewCis, nNewCos, nInputs, nOutputs; int nNewPiNum = Tim_ManPiNum(p) - nTermsDiff; int nNewPoNum = Tim_ManPoNum(p) - nTermsDiff; assert( Vec_IntSize(vBoxesLeft) <= Tim_ManBoxNum(p) ); // count the number of CIs and COs in the trimmed manager nNewCis = nNewPiNum; nNewCos = nNewPoNum; Vec_IntForEachEntry( vBoxesLeft, iBox, i ) { pBox = Tim_ManBox( p, iBox ); nNewCis += pBox->nOutputs; nNewCos += pBox->nInputs; } assert( nNewCis <= Tim_ManCiNum(p) - nTermsDiff ); assert( nNewCos <= Tim_ManCoNum(p) - nTermsDiff ); // clear traversal IDs Tim_ManForEachCi( p, pObj, i ) pObj->TravId = 0; Tim_ManForEachCo( p, pObj, i ) pObj->TravId = 0; // create new manager pNew = Tim_ManStart( nNewCis, nNewCos ); // copy box connectivity information memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * nNewPiNum ); memcpy( pNew->pCos + nNewCos - nNewPoNum, p->pCos + Tim_ManCoNum(p) - Tim_ManPoNum(p), sizeof(Tim_Obj_t) * nNewPoNum ); // duplicate delay tables if ( Tim_ManDelayTableNum(p) > 0 ) { int fWarning = 0; pNew->vDelayTables = Vec_PtrStart( Vec_PtrSize(p->vDelayTables) ); Tim_ManForEachTable( p, pDelayTable, i ) { if ( pDelayTable == NULL ) continue; if ( i != (int)pDelayTable[0] && fWarning == 0 ) { printf( "Warning: Mismatch in delay-table number between the manager and the box.\n" ); fWarning = 1; } //assert( i == (int)pDelayTable[0] ); nInputs = (int)pDelayTable[1]; nOutputs = (int)pDelayTable[2]; pDelayTableNew = ABC_ALLOC( float, 3 + nInputs * nOutputs ); pDelayTableNew[0] = i;//(int)pDelayTable[0]; pDelayTableNew[1] = (int)pDelayTable[1]; pDelayTableNew[2] = (int)pDelayTable[2]; for ( k = 0; k < nInputs * nOutputs; k++ ) pDelayTableNew[3+k] = pDelayTable[3+k]; // assert( (int)pDelayTableNew[0] == Vec_PtrSize(pNew->vDelayTables) ); assert( Vec_PtrEntry(pNew->vDelayTables, i) == NULL ); Vec_PtrWriteEntry( pNew->vDelayTables, i, pDelayTableNew ); } } // duplicate boxes if ( Tim_ManBoxNum(p) > 0 ) { int curPi = nNewPiNum; int curPo = 0; pNew->vBoxes = Vec_PtrAlloc( Tim_ManBoxNum(p) ); Vec_IntForEachEntry( vBoxesLeft, iBox, i ) { pBox = Tim_ManBox( p, iBox ); Tim_ManCreateBox( pNew, curPo, pBox->nInputs, curPi, pBox->nOutputs, pBox->iDelayTable, pBox->fBlack ); Tim_ManBoxSetCopy( pNew, Tim_ManBoxNum(pNew) - 1, Tim_ManBoxCopy(p, iBox) == -1 ? iBox : Tim_ManBoxCopy(p, iBox) ); curPi += pBox->nOutputs; curPo += pBox->nInputs; } curPo += nNewPoNum; assert( curPi == Tim_ManCiNum(pNew) ); assert( curPo == Tim_ManCoNum(pNew) ); } return pNew; } /**Function************************************************************* Synopsis [Aligns two sets of boxes using the copy field.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Tim_ManAlignTwo( Tim_Man_t * pSpec, Tim_Man_t * pImpl ) { Vec_Int_t * vBoxPres; Tim_Box_t * pBox; int i; assert( Tim_ManBoxNum(pSpec) > Tim_ManBoxNum(pImpl) ); // check if boxes of pImpl can be aligned Tim_ManForEachBox( pImpl, pBox, i ) if ( pBox->iCopy < 0 || pBox->iCopy >= Tim_ManBoxNum(pSpec) ) return NULL; // map dropped boxes into 1, others into 0 vBoxPres = Vec_IntStart( Tim_ManBoxNum(pSpec) ); Tim_ManForEachBox( pImpl, pBox, i ) { assert( !Vec_IntEntry(vBoxPres, pBox->iCopy) ); Vec_IntWriteEntry( vBoxPres, pBox->iCopy, 1 ); } return vBoxPres; } /**Function************************************************************* Synopsis [Stops the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManStop( Tim_Man_t * p ) { Vec_PtrFreeFree( p->vDelayTables ); Vec_PtrFreeP( &p->vBoxes ); Mem_FlexStop( p->pMemObj, 0 ); ABC_FREE( p->pCis ); ABC_FREE( p->pCos ); ABC_FREE( p ); } void Tim_ManStopP( Tim_Man_t ** p ) { if ( *p == NULL ) return; Tim_ManStop( *p ); *p = NULL; } /**Function************************************************************* Synopsis [Creates manager using hierarchy / box library / delay info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs ) { If_LibBox_t * pLibBox = (If_LibBox_t *)pLib; If_Box_t * pIfBox; Tim_Box_t * pBox; Tim_Obj_t * pObj; float * pTable; int i, k; assert( p->vDelayTables == NULL ); p->vDelayTables = pLibBox ? Vec_PtrStart( Vec_PtrSize(pLibBox->vBoxes) ) : Vec_PtrAlloc( 100 ); if ( p->vBoxes ) Tim_ManForEachBox( p, pBox, i ) { if ( pBox->iDelayTable == -1 || pLibBox == NULL ) { // create table with constants pTable = ABC_ALLOC( float, 3 + pBox->nInputs * pBox->nOutputs ); pTable[0] = pBox->iDelayTable; pTable[1] = pBox->nInputs; pTable[2] = pBox->nOutputs; for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ ) pTable[3 + k] = 1.0; // save table pBox->iDelayTable = Vec_PtrSize(p->vDelayTables); Vec_PtrPush( p->vDelayTables, pTable ); continue; } assert( pBox->iDelayTable >= 0 && pBox->iDelayTable < Vec_PtrSize(pLibBox->vBoxes) ); pIfBox = (If_Box_t *)Vec_PtrEntry( pLibBox->vBoxes, pBox->iDelayTable ); assert( pIfBox != NULL ); assert( pIfBox->nPis == pBox->nInputs ); assert( pIfBox->nPos == pBox->nOutputs ); pBox->fBlack = pIfBox->fBlack; if ( Vec_PtrEntry( p->vDelayTables, pBox->iDelayTable ) != NULL ) continue; // create table of boxes pTable = ABC_ALLOC( float, 3 + pBox->nInputs * pBox->nOutputs ); pTable[0] = pBox->iDelayTable; pTable[1] = pBox->nInputs; pTable[2] = pBox->nOutputs; for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ ) pTable[3 + k] = pIfBox->pDelays[k]; // save table Vec_PtrWriteEntry( p->vDelayTables, pBox->iDelayTable, pTable ); } // create arrival times if ( vInArrs ) { assert( Vec_FltSize(vInArrs) == Tim_ManPiNum(p) ); Tim_ManForEachPi( p, pObj, i ) pObj->timeArr = Vec_FltEntry(vInArrs, i); } // create required times if ( vOutReqs ) { k = 0; assert( Vec_FltSize(vOutReqs) == Tim_ManPoNum(p) ); Tim_ManForEachPo( p, pObj, i ) pObj->timeReq = Vec_FltEntry(vOutReqs, k++); assert( k == Tim_ManPoNum(p) ); } } /**Function************************************************************* Synopsis [Get arrival and required times if they are non-trivial.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float * Tim_ManGetArrTimes( Tim_Man_t * p ) { float * pTimes; Tim_Obj_t * pObj; int i; Tim_ManForEachPi( p, pObj, i ) if ( pObj->timeArr != 0.0 ) break; if ( i == Tim_ManPiNum(p) ) return NULL; pTimes = ABC_FALLOC( float, Tim_ManCiNum(p) ); Tim_ManForEachPi( p, pObj, i ) pTimes[i] = pObj->timeArr; return pTimes; } float * Tim_ManGetReqTimes( Tim_Man_t * p ) { float * pTimes; Tim_Obj_t * pObj; int i, k = 0; Tim_ManForEachPo( p, pObj, i ) if ( pObj->timeReq != TIM_ETERNITY ) break; if ( i == Tim_ManPoNum(p) ) return NULL; pTimes = ABC_FALLOC( float, Tim_ManCoNum(p) ); Tim_ManForEachPo( p, pObj, i ) pTimes[k++] = pObj->timeArr; assert( k == Tim_ManPoNum(p) ); return pTimes; } /**Function************************************************************* Synopsis [Prints the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManPrint( Tim_Man_t * p ) { Tim_Box_t * pBox; Tim_Obj_t * pObj, * pPrev; float * pTable; int i, j, k, TableX, TableY; if ( p == NULL ) return; printf( "TIMING MANAGER:\n" ); printf( "PI = %d. CI = %d. PO = %d. CO = %d. Box = %d.\n", Tim_ManPiNum(p), Tim_ManCiNum(p), Tim_ManPoNum(p), Tim_ManCoNum(p), Tim_ManBoxNum(p) ); // print CI info pPrev = p->pCis; Tim_ManForEachPi( p, pObj, i ) if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq ) break; if ( i == Tim_ManCiNum(p) ) printf( "All PIs : arrival = %5.3f required = %5.3f\n", pPrev->timeArr, pPrev->timeReq ); else Tim_ManForEachPi( p, pObj, i ) printf( "PI%5d : arrival = %5.3f required = %5.3f\n", i, pObj->timeArr, pObj->timeReq ); // print CO info pPrev = p->pCos; Tim_ManForEachPo( p, pObj, i ) if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq ) break; if ( i == Tim_ManCoNum(p) ) printf( "All POs : arrival = %5.3f required = %5.3f\n", pPrev->timeArr, pPrev->timeReq ); else { int k = 0; Tim_ManForEachPo( p, pObj, i ) printf( "PO%5d : arrival = %5.3f required = %5.3f\n", k++, pObj->timeArr, pObj->timeReq ); } // print box info if ( Tim_ManBoxNum(p) > 0 ) Tim_ManForEachBox( p, pBox, i ) { printf( "*** Box %5d : I =%4d. O =%4d. I1 =%6d. O1 =%6d. Table =%4d\n", i, pBox->nInputs, pBox->nOutputs, Tim_ManBoxInputFirst(p, i), Tim_ManBoxOutputFirst(p, i), pBox->iDelayTable ); // print box inputs pPrev = Tim_ManBoxInput( p, pBox, 0 ); Tim_ManBoxForEachInput( p, pBox, pObj, k ) if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq ) break; if ( k == Tim_ManBoxInputNum(p, pBox->iBox) ) printf( "Box inputs : arrival = %5.3f required = %5.3f\n", pPrev->timeArr, pPrev->timeReq ); else Tim_ManBoxForEachInput( p, pBox, pObj, k ) printf( "box-in%4d : arrival = %5.3f required = %5.3f\n", k, pObj->timeArr, pObj->timeReq ); // print box outputs pPrev = Tim_ManBoxOutput( p, pBox, 0 ); Tim_ManBoxForEachOutput( p, pBox, pObj, k ) if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq ) break; if ( k == Tim_ManBoxOutputNum(p, pBox->iBox) ) printf( "Box outputs : arrival = %5.3f required = %5.3f\n", pPrev->timeArr, pPrev->timeReq ); else Tim_ManBoxForEachOutput( p, pBox, pObj, k ) printf( "box-out%3d : arrival = %5.3f required = %5.3f\n", k, pObj->timeArr, pObj->timeReq ); if ( i > 2 ) break; } // print delay tables if ( Tim_ManDelayTableNum(p) > 0 ) Tim_ManForEachTable( p, pTable, i ) { if ( pTable == NULL ) continue; printf( "Delay table %d:\n", i ); assert( i == (int)pTable[0] ); TableX = (int)pTable[1]; TableY = (int)pTable[2]; for ( j = 0; j < TableY; j++, printf( "\n" ) ) for ( k = 0; k < TableX; k++ ) if ( pTable[3+j*TableX+k] == -ABC_INFINITY ) printf( "%5s", "-" ); else printf( "%5.0f", pTable[3+j*TableX+k] ); } printf( "\n" ); } void Tim_ManPrintBoxCopy( Tim_Man_t * p ) { Tim_Box_t * pBox; int i; if ( p == NULL ) return; printf( "TIMING MANAGER:\n" ); printf( "PI = %d. CI = %d. PO = %d. CO = %d. Box = %d.\n", Tim_ManPiNum(p), Tim_ManCiNum(p), Tim_ManPoNum(p), Tim_ManCoNum(p), Tim_ManBoxNum(p) ); if ( Tim_ManBoxNum(p) > 0 ) Tim_ManForEachBox( p, pBox, i ) printf( "%d ", pBox->iCopy ); printf( "\n" ); } /**Function************************************************************* Synopsis [Prints statistics of the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManPrintStats( Tim_Man_t * p, int nAnd2Delay ) { Tim_Box_t * pBox; Vec_Int_t * vCounts; Vec_Ptr_t * vBoxes; int i, Count, IdMax; if ( p == NULL ) return; Abc_Print( 1, "Hierarchy : " ); printf( "PI/CI = %d/%d PO/CO = %d/%d Box = %d ", Tim_ManPiNum(p), Tim_ManCiNum(p), Tim_ManPoNum(p), Tim_ManCoNum(p), Tim_ManBoxNum(p) ); if ( nAnd2Delay ) printf( "delay(AND2) = %d", nAnd2Delay ); printf( "\n" ); if ( Tim_ManBoxNum(p) == 0 ) return; IdMax = 0; Tim_ManForEachBox( p, pBox, i ) IdMax = Abc_MaxInt( IdMax, pBox->iDelayTable ); vCounts = Vec_IntStart( IdMax+1 ); vBoxes = Vec_PtrStart( IdMax+1 ); Tim_ManForEachBox( p, pBox, i ) { Vec_IntAddToEntry( vCounts, pBox->iDelayTable, 1 ); Vec_PtrWriteEntry( vBoxes, pBox->iDelayTable, pBox ); } // print statistics about boxes Vec_IntForEachEntry( vCounts, Count, i ) { if ( Count == 0 ) continue; pBox = (Tim_Box_t *)Vec_PtrEntry( vBoxes, i ); printf( " Box %4d ", i ); printf( "Num = %4d ", Count ); printf( "Ins = %4d ", pBox->nInputs ); printf( "Outs = %4d", pBox->nOutputs ); printf( "\n" ); } Vec_IntFree( vCounts ); Vec_PtrFree( vBoxes ); } /**Function************************************************************* Synopsis [Read parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManCiNum( Tim_Man_t * p ) { return p->nCis; } int Tim_ManCoNum( Tim_Man_t * p ) { return p->nCos; } int Tim_ManPiNum( Tim_Man_t * p ) { if ( Tim_ManBoxNum(p) == 0 ) return Tim_ManCiNum(p); return Tim_ManBoxOutputFirst(p, 0); } int Tim_ManPoNum( Tim_Man_t * p ) { int iLastBoxId; if ( Tim_ManBoxNum(p) == 0 ) return Tim_ManCoNum(p); iLastBoxId = Tim_ManBoxNum(p) - 1; return Tim_ManCoNum(p) - (Tim_ManBoxInputFirst(p, iLastBoxId) + Tim_ManBoxInputNum(p, iLastBoxId)); } int Tim_ManBoxNum( Tim_Man_t * p ) { return p->vBoxes ? Vec_PtrSize(p->vBoxes) : 0; } int Tim_ManBlackBoxNum( Tim_Man_t * p ) { Tim_Box_t * pBox; int i, Counter = 0; if ( Tim_ManBoxNum(p) ) Tim_ManForEachBox( p, pBox, i ) Counter += pBox->fBlack; return Counter; } void Tim_ManBlackBoxIoNum( Tim_Man_t * p, int * pnBbIns, int * pnBbOuts ) { Tim_Box_t * pBox; int i; *pnBbIns = *pnBbOuts = 0; if ( Tim_ManBoxNum(p) ) Tim_ManForEachBox( p, pBox, i ) { if ( !pBox->fBlack ) continue; *pnBbIns += Tim_ManBoxInputNum( p, i ); *pnBbOuts += Tim_ManBoxOutputNum( p, i ); } } int Tim_ManDelayTableNum( Tim_Man_t * p ) { return p->vDelayTables ? Vec_PtrSize(p->vDelayTables) : 0; } /**Function************************************************************* Synopsis [Sets the vector of timing tables associated with the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables ) { assert( p->vDelayTables == NULL ); p->vDelayTables = vDelayTables; } /**Function************************************************************* Synopsis [Disables the use of the traversal ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManTravIdDisable( Tim_Man_t * p ) { p->fUseTravId = 0; } /**Function************************************************************* Synopsis [Enables the use of the traversal ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManTravIdEnable( Tim_Man_t * p ) { p->fUseTravId = 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/timTime.c000066400000000000000000000175601300674244400233450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [timTime.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchy/timing manager.] Synopsis [Setting and resetting timing information of the boxes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: timTime.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "timInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Initializes arrival time of the PI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManInitPiArrival( Tim_Man_t * p, int iPi, float Delay ) { assert( iPi < p->nCis ); p->pCis[iPi].timeArr = Delay; } /**Function************************************************************* Synopsis [Initializes required time of the PO.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManInitPoRequired( Tim_Man_t * p, int iPo, float Delay ) { assert( iPo < p->nCos ); p->pCos[iPo].timeReq = Delay; } /**Function************************************************************* Synopsis [Sets arrival times of all PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManInitPiArrivalAll( Tim_Man_t * p, float Delay ) { Tim_Obj_t * pObj; int i; Tim_ManForEachPi( p, pObj, i ) Tim_ManInitPiArrival( p, i, Delay ); } /**Function************************************************************* Synopsis [Sets required times of all POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManInitPoRequiredAll( Tim_Man_t * p, float Delay ) { Tim_Obj_t * pObj; int i; Tim_ManForEachPo( p, pObj, i ) Tim_ManSetCoRequired( p, i, Delay ); } /**Function************************************************************* Synopsis [Updates arrival time of the CO.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManSetCoArrival( Tim_Man_t * p, int iCo, float Delay ) { assert( iCo < p->nCos ); assert( !p->fUseTravId || p->pCos[iCo].TravId != p->nTravIds ); p->pCos[iCo].timeArr = Delay; p->pCos[iCo].TravId = p->nTravIds; } /**Function************************************************************* Synopsis [Updates required time of the CI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManSetCiRequired( Tim_Man_t * p, int iCi, float Delay ) { assert( iCi < p->nCis ); assert( !p->fUseTravId || p->pCis[iCi].TravId != p->nTravIds ); p->pCis[iCi].timeReq = Delay; p->pCis[iCi].TravId = p->nTravIds; } /**Function************************************************************* Synopsis [Updates required time of the CO.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManSetCoRequired( Tim_Man_t * p, int iCo, float Delay ) { assert( iCo < p->nCos ); assert( !p->fUseTravId || !p->nTravIds || p->pCos[iCo].TravId != p->nTravIds ); p->pCos[iCo].timeReq = Delay; p->pCos[iCo].TravId = p->nTravIds; } /**Function************************************************************* Synopsis [Returns CO arrival time.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Tim_ManGetCiArrival( Tim_Man_t * p, int iCi ) { Tim_Box_t * pBox; Tim_Obj_t * pObjThis, * pObj, * pObjRes; float * pTable, * pDelays, DelayBest; int i, k; // consider the already processed PI pObjThis = Tim_ManCi( p, iCi ); if ( p->fUseTravId && pObjThis->TravId == p->nTravIds ) return pObjThis->timeArr; pObjThis->TravId = p->nTravIds; // consider the main PI pBox = Tim_ManCiBox( p, iCi ); if ( pBox == NULL ) return pObjThis->timeArr; // update box timing pBox->TravId = p->nTravIds; // get the arrival times of the inputs of the box (POs) if ( p->fUseTravId ) Tim_ManBoxForEachInput( p, pBox, pObj, i ) if ( pObj->TravId != p->nTravIds ) printf( "Tim_ManGetCiArrival(): Input arrival times of the box are not up to date!\n" ); // compute the arrival times for each output of the box (PIs) pTable = Tim_ManBoxDelayTable( p, pBox->iBox ); Tim_ManBoxForEachOutput( p, pBox, pObjRes, i ) { pDelays = pTable + 3 + i * pBox->nInputs; DelayBest = -TIM_ETERNITY; Tim_ManBoxForEachInput( p, pBox, pObj, k ) if ( pDelays[k] != -ABC_INFINITY ) DelayBest = Abc_MaxInt( DelayBest, pObj->timeArr + pDelays[k] ); pObjRes->timeArr = DelayBest; pObjRes->TravId = p->nTravIds; } return pObjThis->timeArr; } /**Function************************************************************* Synopsis [Returns CO required time.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Tim_ManGetCoRequired( Tim_Man_t * p, int iCo ) { Tim_Box_t * pBox; Tim_Obj_t * pObjThis, * pObj, * pObjRes; float * pTable, * pDelays, DelayBest; int i, k; // consider the already processed PO pObjThis = Tim_ManCo( p, iCo ); if ( p->fUseTravId && pObjThis->TravId == p->nTravIds ) return pObjThis->timeReq; pObjThis->TravId = p->nTravIds; // consider the main PO pBox = Tim_ManCoBox( p, iCo ); if ( pBox == NULL ) return pObjThis->timeReq; // update box timing pBox->TravId = p->nTravIds; // get the required times of the outputs of the box (PIs) if ( p->fUseTravId ) Tim_ManBoxForEachOutput( p, pBox, pObj, i ) if ( pObj->TravId != p->nTravIds ) printf( "Tim_ManGetCoRequired(): Output required times of output %d the box %d are not up to date!\n", i, pBox->iBox ); // compute the required times for each input of the box (POs) pTable = Tim_ManBoxDelayTable( p, pBox->iBox ); Tim_ManBoxForEachInput( p, pBox, pObjRes, i ) { DelayBest = TIM_ETERNITY; Tim_ManBoxForEachOutput( p, pBox, pObj, k ) { pDelays = pTable + 3 + k * pBox->nInputs; if ( pDelays[k] != -ABC_INFINITY ) DelayBest = Abc_MinFloat( DelayBest, pObj->timeReq - pDelays[i] ); } pObjRes->timeReq = DelayBest; pObjRes->TravId = p->nTravIds; } return pObjThis->timeReq; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/tim/timTrav.c000066400000000000000000000113751300674244400233610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [timTrav.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchy/timing manager.] Synopsis [Manipulation of traversal IDs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: timTrav.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "timInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Increments the trav ID of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManIncrementTravId( Tim_Man_t * p ) { int i; if ( p->nTravIds >= (1<<30)-1 ) { p->nTravIds = 0; for ( i = 0; i < p->nCis; i++ ) p->pCis[i].TravId = 0; for ( i = 0; i < p->nCos; i++ ) p->pCos[i].TravId = 0; } assert( p->nTravIds < (1<<30)-1 ); p->nTravIds++; } /**Function************************************************************* Synopsis [Label box inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManSetCurrentTravIdBoxInputs( Tim_Man_t * p, int iBox ) { Tim_Box_t * pBox; Tim_Obj_t * pObj; int i; pBox = Tim_ManBox( p, iBox ); Tim_ManBoxForEachInput( p, pBox, pObj, i ) pObj->TravId = p->nTravIds; } /**Function************************************************************* Synopsis [Label box outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManSetCurrentTravIdBoxOutputs( Tim_Man_t * p, int iBox ) { Tim_Box_t * pBox; Tim_Obj_t * pObj; int i; pBox = Tim_ManBox( p, iBox ); Tim_ManBoxForEachOutput( p, pBox, pObj, i ) pObj->TravId = p->nTravIds; } /**Function************************************************************* Synopsis [Label box inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManSetPreviousTravIdBoxInputs( Tim_Man_t * p, int iBox ) { Tim_Box_t * pBox; Tim_Obj_t * pObj; int i; pBox = Tim_ManBox( p, iBox ); Tim_ManBoxForEachInput( p, pBox, pObj, i ) pObj->TravId = p->nTravIds - 1; } /**Function************************************************************* Synopsis [Label box outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tim_ManSetPreviousTravIdBoxOutputs( Tim_Man_t * p, int iBox ) { Tim_Box_t * pBox; Tim_Obj_t * pObj; int i; pBox = Tim_ManBox( p, iBox ); Tim_ManBoxForEachOutput( p, pBox, pObj, i ) pObj->TravId = p->nTravIds - 1; } /**Function************************************************************* Synopsis [Updates required time of the CI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManIsCiTravIdCurrent( Tim_Man_t * p, int iCi ) { assert( iCi < p->nCis ); assert( p->fUseTravId ); return p->pCis[iCi].TravId == p->nTravIds; } /**Function************************************************************* Synopsis [Updates required time of the CO.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tim_ManIsCoTravIdCurrent( Tim_Man_t * p, int iCo ) { assert( iCo < p->nCos ); assert( p->fUseTravId ); return p->pCos[iCo].TravId == p->nTravIds; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/000077500000000000000000000000001300674244400217445ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/abc_global.h000066400000000000000000000403701300674244400241660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abc_global.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Global declarations.] Synopsis [Global declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Jan 30, 2009.] Revision [$Id: abc_global.h,v 1.00 2009/01/30 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__util__abc_global_h #define ABC__misc__util__abc_global_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #ifdef _WIN32 #ifndef __MINGW32__ #define inline __inline // compatible with MS VS 6.0 #pragma warning(disable : 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression #pragma warning(disable : 4200) // warning C4200: nonstandard extension used : zero-sized array in struct/union #pragma warning(disable : 4244) // warning C4244: '+=' : conversion from 'int ' to 'unsigned short ', possible loss of data #pragma warning(disable : 4514) // warning C4514: 'Vec_StrPop' : unreferenced inline function has been removed #pragma warning(disable : 4710) // warning C4710: function 'Vec_PtrGrow' not inlined //#pragma warning( disable : 4273 ) #endif #endif #ifdef WIN32 #ifdef WIN32_NO_DLL #define ABC_DLLEXPORT #define ABC_DLLIMPORT #else #define ABC_DLLEXPORT __declspec(dllexport) #define ABC_DLLIMPORT __declspec(dllimport) #endif #else /* defined(WIN32) */ #define ABC_DLLIMPORT #endif /* defined(WIN32) */ #ifndef ABC_DLL #define ABC_DLL ABC_DLLIMPORT #endif #if !defined(___unused) #if defined(__GNUC__) #define ___unused __attribute__ ((__unused__)) #else #define ___unused #endif #endif /* #ifdef __cplusplus #error "C++ code" #else #error "C code" #endif */ #include #include #include #include #include #include // catch memory leaks in Visual Studio #ifdef WIN32 #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC #include #endif #endif #include "abc_namespaces.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// /** * Pointer difference type; replacement for ptrdiff_t. * This is a signed integral type that is the same size as a pointer. * NOTE: This type may be different sizes on different platforms. */ #if defined(__ccdoc__) typedef platform_dependent_type ABC_PTRDIFF_T; #elif defined(LIN64) typedef long ABC_PTRDIFF_T; #elif defined(NT64) typedef long long ABC_PTRDIFF_T; #elif defined(NT) || defined(LIN) || defined(WIN32) typedef int ABC_PTRDIFF_T; #else #error unknown platform #endif /* defined(PLATFORM) */ /** * Unsigned integral type that can contain a pointer. * This is an unsigned integral type that is the same size as a pointer. * NOTE: This type may be different sizes on different platforms. */ #if defined(__ccdoc__) typedef platform_dependent_type ABC_PTRUINT_T; #elif defined(LIN64) typedef unsigned long ABC_PTRUINT_T; #elif defined(NT64) typedef unsigned long long ABC_PTRUINT_T; #elif defined(NT) || defined(LIN) || defined(WIN32) typedef unsigned int ABC_PTRUINT_T; #else #error unknown platform #endif /* defined(PLATFORM) */ /** * Signed integral type that can contain a pointer. * This is a signed integral type that is the same size as a pointer. * NOTE: This type may be different sizes on different platforms. */ #if defined(__ccdoc__) typedef platform_dependent_type ABC_PTRINT_T; #elif defined(LIN64) typedef long ABC_PTRINT_T; #elif defined(NT64) typedef long long ABC_PTRINT_T; #elif defined(NT) || defined(LIN) || defined(WIN32) typedef int ABC_PTRINT_T; #else #error unknown platform #endif /* defined(PLATFORM) */ /** * 64-bit signed integral type. */ #if defined(__ccdoc__) typedef platform_dependent_type ABC_INT64_T; #elif defined(LIN64) typedef long ABC_INT64_T; #elif defined(NT64) || defined(LIN) typedef long long ABC_INT64_T; #elif defined(WIN32) || defined(NT) typedef signed __int64 ABC_INT64_T; #else #error unknown platform #endif /* defined(PLATFORM) */ /** * 64-bit unsigned integral type. */ #if defined(__ccdoc__) typedef platform_dependent_type ABC_UINT64_T; #elif defined(LIN64) typedef unsigned long ABC_UINT64_T; #elif defined(NT64) || defined(LIN) typedef unsigned long long ABC_UINT64_T; #elif defined(WIN32) || defined(NT) typedef unsigned __int64 ABC_UINT64_T; #else #error unknown platform #endif /* defined(PLATFORM) */ #ifdef LIN #define ABC_CONST(number) number ## ULL #else // LIN64 and windows #define ABC_CONST(number) number #endif typedef ABC_UINT64_T word; typedef ABC_INT64_T iword; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_INFINITY (1000000000) #define ABC_SWAP(Type, a, b) { Type t = a; a = b; b = t; } #define ABC_PRT(a,t) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%9.2f sec\n", 1.0*(t)/(CLOCKS_PER_SEC))) #define ABC_PRTr(a,t) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%9.2f sec\r", 1.0*(t)/(CLOCKS_PER_SEC))) #define ABC_PRTn(a,t) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%9.2f sec ", 1.0*(t)/(CLOCKS_PER_SEC))) #define ABC_PRTP(a,t,T) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%9.2f sec (%6.2f %%)\n", 1.0*(t)/(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0)) #define ABC_PRM(a,f) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%10.3f MB\n", 1.0*(f)/(1<<20))) #define ABC_PRMr(a,f) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%10.3f MB\r", 1.0*(f)/(1<<20))) #define ABC_PRMn(a,f) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%10.3f MB ", 1.0*(f)/(1<<20))) #define ABC_PRMP(a,f,F) (Abc_Print(1, "%s =", (a)), Abc_Print(1, "%10.3f MB (%6.2f %%)\n", (1.0*(f)/(1<<20)), ((F)? 100.0*(f)/(F) : 0.0) ) ) #define ABC_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) #define ABC_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) #define ABC_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) #define ABC_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) #define ABC_REALLOC(type, obj, num) \ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ ((type *) malloc(sizeof(type) * (num)))) static inline int Abc_AbsInt( int a ) { return a < 0 ? -a : a; } static inline int Abc_MaxInt( int a, int b ) { return a > b ? a : b; } static inline int Abc_MinInt( int a, int b ) { return a < b ? a : b; } static inline word Abc_MaxWord( word a, word b ) { return a > b ? a : b; } static inline word Abc_MinWord( word a, word b ) { return a < b ? a : b; } static inline float Abc_AbsFloat( float a ) { return a < 0 ? -a : a; } static inline float Abc_MaxFloat( float a, float b ) { return a > b ? a : b; } static inline float Abc_MinFloat( float a, float b ) { return a < b ? a : b; } static inline double Abc_AbsDouble( double a ) { return a < 0 ? -a : a; } static inline double Abc_MaxDouble( double a, double b ) { return a > b ? a : b; } static inline double Abc_MinDouble( double a, double b ) { return a < b ? a : b; } static inline int Abc_Float2Int( float Val ) { union { int x; float y; } v; v.y = Val; return v.x; } static inline float Abc_Int2Float( int Num ) { union { int x; float y; } v; v.x = Num; return v.y; } static inline int Abc_Base2Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ) {}; return r; } static inline int Abc_Base10Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ) {}; return r; } static inline int Abc_Base16Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 16, r++ ) {}; return r; } static inline char * Abc_UtilStrsav( char * s ) { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL; } static inline int Abc_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } static inline int Abc_Bit6WordNum( int nBits ) { return (nBits>>6) + ((nBits&63) > 0); } static inline int Abc_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } static inline int Abc_Truth6WordNum( int nVars ) { return nVars <= 6 ? 1 : (1 << (nVars - 6)); } static inline int Abc_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } static inline void Abc_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } static inline void Abc_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } static inline unsigned Abc_InfoMask( int nVar ) { return (~(unsigned)0) >> (32-nVar); } static inline int Abc_Var2Lit( int Var, int c ) { assert(Var >= 0 && !(c >> 1)); return Var + Var + c; } static inline int Abc_Lit2Var( int Lit ) { assert(Lit >= 0); return Lit >> 1; } static inline int Abc_LitIsCompl( int Lit ) { assert(Lit >= 0); return Lit & 1; } static inline int Abc_LitNot( int Lit ) { assert(Lit >= 0); return Lit ^ 1; } static inline int Abc_LitNotCond( int Lit, int c ) { assert(Lit >= 0); return Lit ^ (int)(c > 0); } static inline int Abc_LitRegular( int Lit ) { assert(Lit >= 0); return Lit & ~01; } static inline int Abc_Lit2LitV( int * pMap, int Lit ) { assert(Lit >= 0); return Abc_Var2Lit( pMap[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit) ); } static inline int Abc_Lit2LitL( int * pMap, int Lit ) { assert(Lit >= 0); return Abc_LitNotCond( pMap[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit) ); } static inline int Abc_Ptr2Int( void * p ) { return (int)(ABC_PTRINT_T)p; } static inline void * Abc_Int2Ptr( int i ) { return (void *)(ABC_PTRINT_T)i; } static inline word Abc_Ptr2Wrd( void * p ) { return (word)(ABC_PTRUINT_T)p; } static inline void * Abc_Wrd2Ptr( word i ) { return (void *)(ABC_PTRUINT_T)i; } static inline int Abc_Var2Lit2( int Var, int Att ) { assert(!(Att >> 2)); return (Var << 2) + Att; } static inline int Abc_Lit2Var2( int Lit ) { assert(Lit >= 0); return Lit >> 2; } static inline int Abc_Lit2Att2( int Lit ) { assert(Lit >= 0); return Lit & 3; } static inline int Abc_Var2Lit3( int Var, int Att ) { assert(!(Att >> 3)); return (Var << 3) + Att; } static inline int Abc_Lit2Var3( int Lit ) { assert(Lit >= 0); return Lit >> 3; } static inline int Abc_Lit2Att3( int Lit ) { assert(Lit >= 0); return Lit & 7; } static inline int Abc_Var2Lit4( int Var, int Att ) { assert(!(Att >> 4)); return (Var << 4) + Att; } static inline int Abc_Lit2Var4( int Lit ) { assert(Lit >= 0); return Lit >> 4; } static inline int Abc_Lit2Att4( int Lit ) { assert(Lit >= 0); return Lit & 15; } // time counting typedef ABC_INT64_T abctime; static inline abctime Abc_Clock() { #if (defined(LIN) || defined(LIN64)) && !(__APPLE__ & __MACH__) && !defined(__MINGW32__) struct timespec ts; if ( clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) < 0 ) return (abctime)-1; abctime res = ((abctime) ts.tv_sec) * CLOCKS_PER_SEC; res += (((abctime) ts.tv_nsec) * CLOCKS_PER_SEC) / 1000000000; return res; #else return (abctime) clock(); #endif } // bridge communication #define BRIDGE_NETLIST 106 #define BRIDGE_ABS_NETLIST 107 extern int Gia_ManToBridgeText( FILE * pFile, int Size, unsigned char * pBuffer ); extern int Gia_ManToBridgeAbsNetlist( FILE * pFile, void * p, int pkg_type ); // string printing extern char * vnsprintf(const char* format, va_list args); extern char * nsprintf(const char* format, ...); // misc printing procedures enum Abc_VerbLevel { ABC_PROMPT = -2, ABC_ERROR = -1, ABC_WARNING = 0, ABC_STANDARD = 1, ABC_VERBOSE = 2 }; static inline void Abc_Print( int level, const char * format, ... ) { extern ABC_DLL int Abc_FrameIsBridgeMode(); va_list args; if ( ! Abc_FrameIsBridgeMode() ){ if ( level == ABC_ERROR ) printf( "Error: " ); else if ( level == ABC_WARNING ) printf( "Warning: " ); }else{ if ( level == ABC_ERROR ) Gia_ManToBridgeText( stdout, strlen("Error: "), (unsigned char*)"Error: " ); else if ( level == ABC_WARNING ) Gia_ManToBridgeText( stdout, strlen("Warning: "), (unsigned char*)"Warning: " ); } va_start( args, format ); if ( Abc_FrameIsBridgeMode() ) { char * tmp = vnsprintf( format, args ); Gia_ManToBridgeText( stdout, strlen(tmp), (unsigned char*)tmp ); free( tmp ); } else vprintf( format, args ); va_end( args ); } static inline void Abc_PrintInt( int i ) { double v3 = (double)i/1000; double v6 = (double)i/1000000; Abc_Print( 1, " " ); if ( i > -1000 && i < 1000 ) Abc_Print( 1, " %4d", i ); else if ( v3 > -9.995 && v3 < 9.995 ) Abc_Print( 1, "%4.2fk", v3 ); else if ( v3 > -99.95 && v3 < 99.95 ) Abc_Print( 1, "%4.1fk", v3 ); else if ( v3 > -999.5 && v3 < 999.5 ) Abc_Print( 1, "%4.0fk", v3 ); else if ( v6 > -9.995 && v6 < 9.995 ) Abc_Print( 1, "%4.2fm", v6 ); else if ( v6 > -99.95 && v6 < 99.95 ) Abc_Print( 1, "%4.1fm", v6 ); else if ( v6 > -999.5 && v6 < 999.5 ) Abc_Print( 1, "%4.0fm", v6 ); } static inline void Abc_PrintTime( int level, const char * pStr, abctime time ) { ABC_PRT( pStr, time ); } static inline void Abc_PrintTimeP( int level, const char * pStr, abctime time, abctime Time ) { ABC_PRTP( pStr, time, Time ); } static inline void Abc_PrintMemoryP( int level, const char * pStr, int mem, int Mem ) { ABC_PRMP( pStr, mem, Mem ); } // Returns the next prime >= p static inline int Abc_PrimeCudd( unsigned int p ) { int i,pn; p--; do { p++; if (p&1) { pn = 1; i = 3; while ((unsigned) (i * i) <= p) { if (p % i == 0) { pn = 0; break; } i += 2; } } else pn = 0; } while (!pn); return(p); } // end of Cudd_Prime // sorting extern void Abc_MergeSort( int * pInput, int nSize ); extern int * Abc_MergeSortCost( int * pCosts, int nSize ); extern void Abc_QuickSort1( word * pData, int nSize, int fDecrease ); extern void Abc_QuickSort2( word * pData, int nSize, int fDecrease ); extern void Abc_QuickSort3( word * pData, int nSize, int fDecrease ); extern void Abc_QuickSortCostData( int * pCosts, int nSize, int fDecrease, word * pData, int * pResult ); extern int * Abc_QuickSortCost( int * pCosts, int nSize, int fDecrease ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/abc_namespaces.h000066400000000000000000000035541300674244400250500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abc_namespaces.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Namespace logic.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Nov 20, 2015.] Revision [] ***********************************************************************/ #ifndef ABC__misc__util__abc_namespaces_h #define ABC__misc__util__abc_namespaces_h //////////////////////////////////////////////////////////////////////// /// NAMESPACES /// //////////////////////////////////////////////////////////////////////// #ifdef __cplusplus # ifdef ABC_NAMESPACE # define ABC_NAMESPACE_HEADER_START namespace ABC_NAMESPACE { # define ABC_NAMESPACE_HEADER_END } # define ABC_NAMESPACE_IMPL_START namespace ABC_NAMESPACE { # define ABC_NAMESPACE_IMPL_END } # define ABC_NAMESPACE_PREFIX ABC_NAMESPACE:: # define ABC_NAMESPACE_USING_NAMESPACE using namespace ABC_NAMESPACE; # else # define ABC_NAMESPACE_HEADER_START extern "C" { # define ABC_NAMESPACE_HEADER_END } # define ABC_NAMESPACE_IMPL_START # define ABC_NAMESPACE_IMPL_END # define ABC_NAMESPACE_PREFIX # define ABC_NAMESPACE_USING_NAMESPACE # endif // #ifdef ABC_NAMESPACE #else # define ABC_NAMESPACE_HEADER_START # define ABC_NAMESPACE_HEADER_END # define ABC_NAMESPACE_IMPL_START # define ABC_NAMESPACE_IMPL_END # define ABC_NAMESPACE_PREFIX # define ABC_NAMESPACE_USING_NAMESPACE #endif // #ifdef __cplusplus #endif // #ifndef ABC__misc__util__abc_namespaces_h //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/module.make000066400000000000000000000003501300674244400240660ustar00rootroot00000000000000SRC += src/misc/util/utilBridge.c \ src/misc/util/utilCex.c \ src/misc/util/utilColor.c \ src/misc/util/utilFile.c \ src/misc/util/utilIsop.c \ src/misc/util/utilNam.c \ src/misc/util/utilSignal.c \ src/misc/util/utilSort.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilBridge.c000066400000000000000000000356621300674244400242160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilBridge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: utilBridge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #if defined(LIN) || defined(LIN64) #include #endif #include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define BRIDGE_TEXT_MESSAGE 999996 #define BRIDGE_ABORT 5 #define BRIDGE_PROGRESS 3 #define BRIDGE_RESULTS 101 #define BRIDGE_BAD_ABS 105 //#define BRIDGE_NETLIST 106 //#define BRIDGE_ABS_NETLIST 107 #define BRIDGE_VALUE_X 0 #define BRIDGE_VALUE_0 2 #define BRIDGE_VALUE_1 3 //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Gia_ManToBridgeVec( Gia_Man_t * p ) { Vec_Str_t * vStr; Gia_Obj_t * pObj; int i, uLit0, uLit1, nNodes; assert( Gia_ManPoNum(p) > 0 ); // start with const1 node (number 1) nNodes = 1; // assign literals(!!!) to the value field Gia_ManConst0(p)->Value = Abc_Var2Lit( nNodes++, 1 ); Gia_ManForEachCi( p, pObj, i ) pObj->Value = Abc_Var2Lit( nNodes++, 0 ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Abc_Var2Lit( nNodes++, 0 ); // write header vStr = Vec_StrAlloc( 1000 ); Gia_AigerWriteUnsigned( vStr, Gia_ManPiNum(p) ); Gia_AigerWriteUnsigned( vStr, Gia_ManRegNum(p) ); Gia_AigerWriteUnsigned( vStr, Gia_ManAndNum(p) ); // write the nodes Gia_ManForEachAnd( p, pObj, i ) { uLit0 = Gia_ObjFanin0Copy( pObj ); uLit1 = Gia_ObjFanin1Copy( pObj ); assert( uLit0 != uLit1 ); Gia_AigerWriteUnsigned( vStr, uLit0 << 1 ); Gia_AigerWriteUnsigned( vStr, uLit1 ); } // write latch drivers Gia_ManForEachRi( p, pObj, i ) { uLit0 = Gia_ObjFanin0Copy( pObj ); Gia_AigerWriteUnsigned( vStr, (uLit0 << 2) | BRIDGE_VALUE_0 ); } // write PO drivers Gia_AigerWriteUnsigned( vStr, Gia_ManPoNum(p) ); Gia_ManForEachPo( p, pObj, i ) { uLit0 = Gia_ObjFanin0Copy( pObj ); // complement property output!!! Gia_AigerWriteUnsigned( vStr, Abc_LitNot(uLit0) ); } return vStr; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_CreateHeader( FILE * pFile, int Type, int Size, unsigned char * pBuffer ) { fprintf( pFile, "%.6d", Type ); fprintf( pFile, " " ); fprintf( pFile, "%.16d", Size ); fprintf( pFile, " " ); #if !defined(LIN) && !defined(LIN64) { int RetValue; RetValue = fwrite( pBuffer, Size, 1, pFile ); assert( RetValue == 1 || Size == 0); fflush( pFile ); } #else fflush(pFile); int fd = fileno(pFile); ssize_t bytes_written = 0; while (bytes_written < Size){ ssize_t n = write(fd, &pBuffer[bytes_written], Size - bytes_written); if (n < 0){ fprintf(stderr, "BridgeMode: failed to send package; aborting\n"); fflush(stderr); _exit(255); } bytes_written += n; } #endif } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManToBridgeText( FILE * pFile, int Size, unsigned char * pBuffer ) { Gia_CreateHeader( pFile, BRIDGE_TEXT_MESSAGE, Size, pBuffer ); return 1; } int Gia_ManToBridgeAbort( FILE * pFile, int Size, unsigned char * pBuffer ) { Gia_CreateHeader( pFile, BRIDGE_ABORT, Size, pBuffer ); return 1; } int Gia_ManToBridgeProgress( FILE * pFile, int Size, unsigned char * pBuffer ) { Gia_CreateHeader( pFile, BRIDGE_PROGRESS, Size, pBuffer ); return 1; } int Gia_ManToBridgeAbsNetlist( FILE * pFile, void * p, int pkg_type ) { Vec_Str_t * vBuffer; vBuffer = Gia_ManToBridgeVec( (Gia_Man_t *)p ); Gia_CreateHeader( pFile, pkg_type, Vec_StrSize(vBuffer), (unsigned char *)Vec_StrArray(vBuffer) ); Vec_StrFree( vBuffer ); return 1; } int Gia_ManToBridgeBadAbs( FILE * pFile ) { Gia_CreateHeader( pFile, BRIDGE_BAD_ABS, 0, NULL ); return 1; } static int aigerNumSize( unsigned x ) { int sz = 1; while (x & ~0x7f) { sz++; x >>= 7; } return sz; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFromBridgeHolds( FILE * pFile, int iPoProved ) { fprintf( pFile, "%.6d", 101 /*message type = Result*/); fprintf( pFile, " " ); fprintf( pFile, "%.16d", 3 + aigerNumSize(iPoProved) /*size in bytes*/); fprintf( pFile, " " ); fputc( (char)BRIDGE_VALUE_1, pFile ); // true fputc( (char)1, pFile ); // size of vector (Armin's encoding) Gia_AigerWriteUnsignedFile( pFile, iPoProved ); // number of the property (Armin's encoding) fputc( (char)0, pFile ); // no invariant fflush(pFile); } void Gia_ManFromBridgeUnknown( FILE * pFile, int iPoUnknown ) { fprintf( pFile, "%.6d", 101 /*message type = Result*/); fprintf( pFile, " " ); fprintf( pFile, "%.16d", 2 + aigerNumSize(iPoUnknown) /*size in bytes*/); fprintf( pFile, " " ); fputc( (char)BRIDGE_VALUE_X, pFile ); // undef fputc( (char)1, pFile ); // size of vector (Armin's encoding) Gia_AigerWriteUnsignedFile( pFile, iPoUnknown ); // number of the property (Armin's encoding) fflush(pFile); } void Gia_ManFromBridgeCex( FILE * pFile, Abc_Cex_t * pCex ) { int i, f, iBit;//, RetValue; Vec_Str_t * vStr = Vec_StrAlloc( 1000 ); Vec_StrPush( vStr, (char)BRIDGE_VALUE_0 ); // false Vec_StrPush( vStr, (char)1 ); // size of vector (Armin's encoding) Gia_AigerWriteUnsigned( vStr, pCex->iPo ); // number of the property (Armin's encoding) Vec_StrPush( vStr, (char)1 ); // size of vector (Armin's encoding) Gia_AigerWriteUnsigned( vStr, pCex->iFrame ); // depth Gia_AigerWriteUnsigned( vStr, 1 ); // concrete Gia_AigerWriteUnsigned( vStr, pCex->iFrame + 1 ); // number of frames (1 more than depth) iBit = pCex->nRegs; for ( f = 0; f <= pCex->iFrame; f++ ) { Gia_AigerWriteUnsigned( vStr, pCex->nPis ); // num of inputs for ( i = 0; i < pCex->nPis; i++, iBit++ ) Vec_StrPush( vStr, (char)(Abc_InfoHasBit(pCex->pData, iBit) ? BRIDGE_VALUE_1:BRIDGE_VALUE_0) ); // value } assert( iBit == pCex->nBits ); Vec_StrPush( vStr, (char)1 ); // the number of frames (for a concrete counter-example) Gia_AigerWriteUnsigned( vStr, pCex->nRegs ); // num of flops for ( i = 0; i < pCex->nRegs; i++ ) Vec_StrPush( vStr, (char)BRIDGE_VALUE_0 ); // always zero!!! // RetValue = fwrite( Vec_StrArray(vStr), Vec_StrSize(vStr), 1, pFile ); Gia_CreateHeader(pFile, 101/*type=Result*/, Vec_StrSize(vStr), (unsigned char*)Vec_StrArray(vStr)); Vec_StrFree( vStr ); fflush(pFile); } int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved ) { if ( Result == 0 ) // sat Gia_ManFromBridgeCex( pFile, pCex ); else if ( Result == 1 ) // unsat Gia_ManFromBridgeHolds( pFile, iPoProved ); else if ( Result == -1 ) // undef Gia_ManFromBridgeUnknown( pFile, iPoProved ); else assert( 0 ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFromBridgeReadBody( int Size, unsigned char * pBuffer, Vec_Int_t ** pvInits ) { int fHash = 0; Vec_Int_t * vLits, * vInits; Gia_Man_t * p = NULL; unsigned char * pBufferPivot, * pBufferEnd = pBuffer + Size; int i, nInputs, nFlops, nGates, nProps; unsigned iFan0, iFan1; nInputs = Gia_AigerReadUnsigned( &pBuffer ); nFlops = Gia_AigerReadUnsigned( &pBuffer ); nGates = Gia_AigerReadUnsigned( &pBuffer ); vLits = Vec_IntAlloc( 1000 ); Vec_IntPush( vLits, -999 ); Vec_IntPush( vLits, 1 ); // start the AIG package p = Gia_ManStart( nInputs + nFlops * 2 + nGates + 1 + 1 ); // PI+FO+FI+AND+PO+1 p->pName = Abc_UtilStrsav( "temp" ); // create PIs for ( i = 0; i < nInputs; i++ ) Vec_IntPush( vLits, Gia_ManAppendCi( p ) ); // create flop outputs for ( i = 0; i < nFlops; i++ ) Vec_IntPush( vLits, Gia_ManAppendCi( p ) ); // create nodes if ( fHash ) Gia_ManHashAlloc( p ); for ( i = 0; i < nGates; i++ ) { iFan0 = Gia_AigerReadUnsigned( &pBuffer ); iFan1 = Gia_AigerReadUnsigned( &pBuffer ); assert( !(iFan0 & 1) ); iFan0 >>= 1; iFan0 = Abc_LitNotCond( Vec_IntEntry(vLits, iFan0 >> 1), iFan0 & 1 ); iFan1 = Abc_LitNotCond( Vec_IntEntry(vLits, iFan1 >> 1), iFan1 & 1 ); if ( fHash ) Vec_IntPush( vLits, Gia_ManHashAnd(p, iFan0, iFan1) ); else Vec_IntPush( vLits, Gia_ManAppendAnd(p, iFan0, iFan1) ); } if ( fHash ) Gia_ManHashStop( p ); // remember where flops begin pBufferPivot = pBuffer; // scroll through flops for ( i = 0; i < nFlops; i++ ) Gia_AigerReadUnsigned( &pBuffer ); // create POs nProps = Gia_AigerReadUnsigned( &pBuffer ); // assert( nProps == 1 ); for ( i = 0; i < nProps; i++ ) { iFan0 = Gia_AigerReadUnsigned( &pBuffer ); iFan0 = Abc_LitNotCond( Vec_IntEntry(vLits, iFan0 >> 1), iFan0 & 1 ); // complement property output!!! Gia_ManAppendCo( p, Abc_LitNot(iFan0) ); } // make sure the end of buffer is reached assert( pBufferEnd == pBuffer ); // resetting to flops pBuffer = pBufferPivot; vInits = Vec_IntAlloc( nFlops ); for ( i = 0; i < nFlops; i++ ) { iFan0 = Gia_AigerReadUnsigned( &pBuffer ); assert( (iFan0 & 3) == BRIDGE_VALUE_0 ); Vec_IntPush( vInits, iFan0 & 3 ); // 0 = X value; 1 = not used; 2 = false; 3 = true iFan0 >>= 2; iFan0 = Abc_LitNotCond( Vec_IntEntry(vLits, iFan0 >> 1), iFan0 & 1 ); Gia_ManAppendCo( p, iFan0 ); } Gia_ManSetRegNum( p, nFlops ); Vec_IntFree( vLits ); // remove wholes in the node list if ( fHash ) { Gia_Man_t * pTemp; p = Gia_ManCleanup( pTemp = p ); Gia_ManStop( pTemp ); } // return if ( pvInits ) *pvInits = vInits; else Vec_IntFree( vInits ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFromBridgeReadPackage( FILE * pFile, int * pType, int * pSize, unsigned char ** ppBuffer ) { char Temp[24]; int RetValue; RetValue = fread( Temp, 24, 1, pFile ); if ( RetValue != 1 ) { printf( "Gia_ManFromBridgeReadPackage(); Error 1: Something is wrong!\n" ); return 0; } Temp[6] = 0; Temp[23]= 0; *pType = atoi( Temp ); *pSize = atoi( Temp + 7 ); *ppBuffer = ABC_ALLOC( unsigned char, *pSize ); RetValue = fread( *ppBuffer, *pSize, 1, pFile ); if ( RetValue != 1 && *pSize != 0 ) { ABC_FREE( *ppBuffer ); printf( "Gia_ManFromBridgeReadPackage(); Error 2: Something is wrong!\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFromBridge( FILE * pFile, Vec_Int_t ** pvInit ) { unsigned char * pBuffer; int Type, Size, RetValue; Gia_Man_t * p = NULL; RetValue = Gia_ManFromBridgeReadPackage( pFile, &Type, &Size, &pBuffer ); ABC_FREE( pBuffer ); if ( !RetValue ) return NULL; RetValue = Gia_ManFromBridgeReadPackage( pFile, &Type, &Size, &pBuffer ); if ( !RetValue ) return NULL; p = Gia_ManFromBridgeReadBody( Size, pBuffer, pvInit ); ABC_FREE( pBuffer ); if ( p == NULL ) return NULL; RetValue = Gia_ManFromBridgeReadPackage( pFile, &Type, &Size, &pBuffer ); ABC_FREE( pBuffer ); if ( !RetValue ) return NULL; return p; } /* { extern void Gia_ManFromBridgeTest( char * pFileName ); Gia_ManFromBridgeTest( "C:\\_projects\\abc\\_TEST\\bug\\65\\par.dump" ); } */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManToBridgeAbsNetlistTest( char * pFileName, Gia_Man_t * p, int msg_type ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } Gia_ManToBridgeAbsNetlist( pFile, p, msg_type ); fclose ( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFromBridgeTest( char * pFileName ) { Gia_Man_t * p; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return; } p = Gia_ManFromBridge( pFile, NULL ); fclose ( pFile ); Gia_ManPrintStats( p, NULL ); Gia_AigerWrite( p, "temp.aig", 0, 0 ); Gia_ManToBridgeAbsNetlistTest( "par_.dump", p, BRIDGE_ABS_NETLIST ); Gia_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilCex.c000066400000000000000000000417711300674244400235370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilCex.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Handling counter-examples.] Synopsis [Handling counter-examples.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Feburary 13, 2011.] Revision [$Id: utilCex.c,v 1.00 2011/02/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "utilCex.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexAlloc( int nRegs, int nRealPis, int nFrames ) { Abc_Cex_t * pCex; int nWords = Abc_BitWordNum( nRegs + nRealPis * nFrames ); pCex = (Abc_Cex_t *)ABC_ALLOC( char, sizeof(Abc_Cex_t) + sizeof(unsigned) * nWords ); memset( pCex, 0, sizeof(Abc_Cex_t) + sizeof(unsigned) * nWords ); pCex->nRegs = nRegs; pCex->nPis = nRealPis; pCex->nBits = nRegs + nRealPis * nFrames; return pCex; } Abc_Cex_t * Abc_CexAllocFull( int nRegs, int nRealPis, int nFrames ) { Abc_Cex_t * pCex; int nWords = Abc_BitWordNum( nRegs + nRealPis * nFrames ); pCex = (Abc_Cex_t *)ABC_ALLOC( char, sizeof(Abc_Cex_t) + sizeof(unsigned) * nWords ); memset( pCex, 0xFF, sizeof(Abc_Cex_t) + sizeof(unsigned) * nWords ); pCex->nRegs = nRegs; pCex->nPis = nRealPis; pCex->nBits = nRegs + nRealPis * nFrames; return pCex; } /**Function************************************************************* Synopsis [Make the trivial counter-example for the trivially asserted output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexMakeTriv( int nRegs, int nTruePis, int nTruePos, int iFrameOut ) { Abc_Cex_t * pCex; int iPo, iFrame; assert( nRegs > 0 ); iPo = iFrameOut % nTruePos; iFrame = iFrameOut / nTruePos; // allocate the counter example pCex = Abc_CexAlloc( nRegs, nTruePis, iFrame + 1 ); pCex->iPo = iPo; pCex->iFrame = iFrame; return pCex; } /**Function************************************************************* Synopsis [Derives the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexCreate( int nRegs, int nPis, int * pArray, int iFrame, int iPo, int fSkipRegs ) { Abc_Cex_t * pCex; int i; pCex = Abc_CexAlloc( nRegs, nPis, iFrame+1 ); pCex->iPo = iPo; pCex->iFrame = iFrame; if ( pArray == NULL ) return pCex; if ( fSkipRegs ) { for ( i = nRegs; i < pCex->nBits; i++ ) if ( pArray[i-nRegs] ) Abc_InfoSetBit( pCex->pData, i ); } else { for ( i = 0; i < pCex->nBits; i++ ) if ( pArray[i] ) Abc_InfoSetBit( pCex->pData, i ); } return pCex; } /**Function************************************************************* Synopsis [Make the trivial counter-example for the trivially asserted output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexDup( Abc_Cex_t * p, int nRegsNew ) { Abc_Cex_t * pCex; int i; if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 ) return p; if ( nRegsNew == -1 ) nRegsNew = p->nRegs; pCex = Abc_CexAlloc( nRegsNew, p->nPis, p->iFrame+1 ); pCex->iPo = p->iPo; pCex->iFrame = p->iFrame; for ( i = p->nRegs; i < p->nBits; i++ ) if ( Abc_InfoHasBit(p->pData, i) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + i - p->nRegs ); return pCex; } /**Function************************************************************* Synopsis [Derives CEX from comb model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexDeriveFromCombModel( int * pModel, int nPis, int nRegs, int iPo ) { Abc_Cex_t * pCex; int i; pCex = Abc_CexAlloc( nRegs, nPis, 1 ); pCex->iPo = iPo; pCex->iFrame = 0; for ( i = 0; i < nPis; i++ ) if ( pModel[i] ) pCex->pData[i>>5] |= (1<<(i & 31)); return pCex; } /**Function************************************************************* Synopsis [Derives CEX from comb model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexMerge( Abc_Cex_t * pCex, Abc_Cex_t * pPart, int iFrBeg, int iFrEnd ) { Abc_Cex_t * pNew; int nFramesGain; int i, f, iBit; if ( iFrBeg < 0 ) { printf( "Starting frame is less than 0.\n" ); return NULL; } if ( iFrEnd < 0 ) { printf( "Stopping frame is less than 0.\n" ); return NULL; } if ( iFrBeg > pCex->iFrame ) { printf( "Starting frame is more than the last frame of CEX (%d).\n", pCex->iFrame ); return NULL; } if ( iFrEnd > pCex->iFrame ) { printf( "Stopping frame is more than the last frame of CEX (%d).\n", pCex->iFrame ); return NULL; } if ( iFrBeg > iFrEnd ) { printf( "Starting frame (%d) should be less than stopping frame (%d).\n", iFrBeg, iFrEnd ); return NULL; } assert( iFrBeg >= 0 && iFrBeg <= pCex->iFrame ); assert( iFrEnd >= 0 && iFrEnd <= pCex->iFrame ); assert( iFrBeg <= iFrEnd ); assert( pCex->nPis == pPart->nPis ); assert( iFrEnd - iFrBeg + pPart->iPo >= pPart->iFrame ); nFramesGain = iFrEnd - iFrBeg + pPart->iPo - pPart->iFrame; pNew = Abc_CexAlloc( pCex->nRegs, pCex->nPis, pCex->iFrame + 1 - nFramesGain ); pNew->iPo = pCex->iPo; pNew->iFrame = pCex->iFrame - nFramesGain; for ( iBit = 0; iBit < pCex->nRegs; iBit++ ) if ( Abc_InfoHasBit(pCex->pData, iBit) ) Abc_InfoSetBit( pNew->pData, iBit ); for ( f = 0; f < iFrBeg; f++ ) for ( i = 0; i < pCex->nPis; i++, iBit++ ) if ( Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) ) Abc_InfoSetBit( pNew->pData, iBit ); for ( f = 0; f < pPart->iFrame; f++ ) for ( i = 0; i < pCex->nPis; i++, iBit++ ) if ( Abc_InfoHasBit(pPart->pData, pPart->nRegs + pCex->nPis * f + i) ) Abc_InfoSetBit( pNew->pData, iBit ); for ( f = iFrEnd; f <= pCex->iFrame; f++ ) for ( i = 0; i < pCex->nPis; i++, iBit++ ) if ( Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) ) Abc_InfoSetBit( pNew->pData, iBit ); assert( iBit == pNew->nBits ); return pNew; } /**Function************************************************************* Synopsis [Prints out the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_CexPrintStats( Abc_Cex_t * p ) { int k, Counter = 0; if ( p == NULL ) { printf( "The counter example is NULL.\n" ); return; } if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 ) { printf( "The counter example is present but not available (pointer has value \"1\").\n" ); return; } for ( k = 0; k < p->nBits; k++ ) Counter += Abc_InfoHasBit(p->pData, k); printf( "CEX: Po =%4d Frame =%4d FF = %d PI = %d Bit =%8d 1s =%8d (%5.2f %%)\n", p->iPo, p->iFrame, p->nRegs, p->nPis, p->nBits, Counter, 100.0 * Counter / (p->nBits - p->nRegs) ); } void Abc_CexPrintStatsInputs( Abc_Cex_t * p, int nInputs ) { int k, Counter = 0, Counter2 = 0; if ( p == NULL ) { printf( "The counter example is NULL.\n" ); return; } if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 ) { printf( "The counter example is present but not available (pointer has value \"1\").\n" ); return; } for ( k = 0; k < p->nBits; k++ ) { Counter += Abc_InfoHasBit(p->pData, k); if ( (k - p->nRegs) % p->nPis < nInputs ) Counter2 += Abc_InfoHasBit(p->pData, k); } printf( "CEX: Po =%4d Frame =%4d FF = %d PI = %d Bit =%8d 1s =%8d (%5.2f %%) 1sIn =%8d (%5.2f %%)\n", p->iPo, p->iFrame, p->nRegs, p->nPis, p->nBits, Counter, 100.0 * Counter / (p->nBits - p->nRegs), Counter2, 100.0 * Counter2 / (p->nBits - p->nRegs - (p->iFrame + 1) * (p->nPis - nInputs)) ); } /**Function************************************************************* Synopsis [Prints out the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_CexPrint( Abc_Cex_t * p ) { int i, f, k; if ( p == NULL ) { printf( "The counter example is NULL.\n" ); return; } if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 ) { printf( "The counter example is present but not available (pointer has value \"1\").\n" ); return; } Abc_CexPrintStats( p ); printf( "State : " ); for ( k = 0; k < p->nRegs; k++ ) printf( "%d", Abc_InfoHasBit(p->pData, k) ); printf( "\n" ); for ( f = 0; f <= p->iFrame; f++ ) { printf( "Frame %3d : ", f ); for ( i = 0; i < p->nPis; i++ ) printf( "%d", Abc_InfoHasBit(p->pData, k++) ); printf( "\n" ); } assert( k == p->nBits ); } /**Function************************************************************* Synopsis [Frees the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_CexFreeP( Abc_Cex_t ** p ) { if ( *p == NULL ) return; if ( *p == (Abc_Cex_t *)(ABC_PTRINT_T)1 ) *p = NULL; else ABC_FREE( *p ); } /**Function************************************************************* Synopsis [Frees the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_CexFree( Abc_Cex_t * p ) { if ( p == (Abc_Cex_t *)(ABC_PTRINT_T)1 ) return; ABC_FREE( p ); } /**Function************************************************************* Synopsis [Transform CEX after phase abstraction with nFrames frames.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexTransformPhase( Abc_Cex_t * p, int nPisOld, int nPosOld, int nRegsOld ) { Abc_Cex_t * pCex; int nFrames = p->nPis / nPisOld; int nPosNew = nPosOld * nFrames; assert( p->nPis % nPisOld == 0 ); assert( p->iPo < nPosNew ); pCex = Abc_CexDup( p, nRegsOld ); pCex->nPis = nPisOld; pCex->iPo = -1; pCex->iFrame = (p->iFrame + 1) * nFrames - 1; pCex->nBits = p->nBits; return pCex; } /**Function************************************************************* Synopsis [Transform CEX after phase temporal decomposition with nFrames frames.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexTransformTempor( Abc_Cex_t * p, int nPisOld, int nPosOld, int nRegsOld ) { Abc_Cex_t * pCex; int i, k, iBit = nRegsOld, nFrames = p->nPis / nPisOld - 1; assert( p->iFrame > 0 ); // otherwise tempor did not properly check for failures in the prefix assert( p->nPis % nPisOld == 0 ); pCex = Abc_CexAlloc( nRegsOld, nPisOld, nFrames + p->iFrame + 1 ); pCex->iPo = p->iPo; pCex->iFrame = nFrames + p->iFrame; for ( i = 0; i < nFrames; i++ ) for ( k = 0; k < nPisOld; k++, iBit++ ) if ( Abc_InfoHasBit(p->pData, p->nRegs + (i+1)*nPisOld + k) ) Abc_InfoSetBit( pCex->pData, iBit ); for ( i = 0; i <= p->iFrame; i++ ) for ( k = 0; k < nPisOld; k++, iBit++ ) if ( Abc_InfoHasBit(p->pData, p->nRegs + i*p->nPis + k) ) Abc_InfoSetBit( pCex->pData, iBit ); assert( iBit == pCex->nBits ); return pCex; } /**Function************************************************************* Synopsis [Transform CEX after "logic; undc; st; zero".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexTransformUndc( Abc_Cex_t * p, char * pInit ) { Abc_Cex_t * pCex; int nFlops = strlen(pInit); int i, f, iBit, iAddPi = 0, nAddPis = 0; // count how many flops got a new PI for ( i = 0; i < nFlops; i++ ) nAddPis += (int)(pInit[i] == 'x'); // create new CEX pCex = Abc_CexAlloc( nFlops, p->nPis - nAddPis, p->iFrame + 1 ); pCex->iPo = p->iPo; pCex->iFrame = p->iFrame; for ( iBit = 0; iBit < nFlops; iBit++ ) { if ( pInit[iBit] == '1' || (pInit[iBit] == 'x' && Abc_InfoHasBit(p->pData, p->nRegs + p->nPis - nAddPis + iAddPi)) ) Abc_InfoSetBit( pCex->pData, iBit ); iAddPi += (int)(pInit[iBit] == 'x'); } assert( iAddPi == nAddPis ); // add timeframes for ( f = 0; f <= p->iFrame; f++ ) for ( i = 0; i < pCex->nPis; i++, iBit++ ) if ( Abc_InfoHasBit(p->pData, p->nRegs + p->nPis * f + i) ) Abc_InfoSetBit( pCex->pData, iBit ); assert( iBit == pCex->nBits ); return pCex; } /**Function************************************************************* Synopsis [Derives permuted CEX using permutation of its inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexPermute( Abc_Cex_t * p, Vec_Int_t * vMapOld2New ) { Abc_Cex_t * pCex; int i, iNew; assert( Vec_IntSize(vMapOld2New) == p->nPis ); pCex = Abc_CexAlloc( p->nRegs, p->nPis, p->iFrame+1 ); pCex->iPo = p->iPo; pCex->iFrame = p->iFrame; for ( i = p->nRegs; i < p->nBits; i++ ) if ( Abc_InfoHasBit(p->pData, i) ) { iNew = p->nRegs + p->nPis * ((i - p->nRegs) / p->nPis) + Vec_IntEntry( vMapOld2New, (i - p->nRegs) % p->nPis ); Abc_InfoSetBit( pCex->pData, iNew ); } return pCex; } /**Function************************************************************* Synopsis [Derives permuted CEX using two canonical permutations.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Abc_CexPermuteTwo( Abc_Cex_t * p, Vec_Int_t * vPermOld, Vec_Int_t * vPermNew ) { Abc_Cex_t * pCex; Vec_Int_t * vPerm; int i, eOld, eNew; assert( Vec_IntSize(vPermOld) == p->nPis ); assert( Vec_IntSize(vPermNew) == p->nPis ); vPerm = Vec_IntStartFull( p->nPis ); Vec_IntForEachEntryTwo( vPermOld, vPermNew, eOld, eNew, i ) Vec_IntWriteEntry( vPerm, eOld, eNew ); pCex = Abc_CexPermute( p, vPerm ); Vec_IntFree( vPerm ); return pCex; } /**Function************************************************************* Synopsis [Count the number of 1s in the CEX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_CexOnes32( unsigned i ) { i = i - ((i >> 1) & 0x55555555); i = (i & 0x33333333) + ((i >> 2) & 0x33333333); i = ((i + (i >> 4)) & 0x0F0F0F0F); return (i*(0x01010101))>>24; } int Abc_CexCountOnes( Abc_Cex_t * p ) { int nWords = Abc_BitWordNum( p->nBits ); int i, Count = 0; for ( i = 0; i < nWords; i++ ) Count += Abc_CexOnes32( p->pData[i] ); return Count; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilCex.h000066400000000000000000000100251300674244400235300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilCex.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Handling sequential counter-examples.] Synopsis [Handling sequential counter-examples.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Feburary 13, 2011.] Revision [$Id: utilCex.h,v 1.00 2011/02/11 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__util__utilCex_h #define ABC__misc__util__utilCex_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // sequential counter-example typedef struct Abc_Cex_t_ Abc_Cex_t; struct Abc_Cex_t_ { int iPo; // the zero-based number of PO, for which verification failed int iFrame; // the zero-based number of the time-frame, for which verificaiton failed int nRegs; // the number of registers in the miter int nPis; // the number of primary inputs in the miter int nBits; // the number of words of bit data used unsigned pData[0]; // the cex bit data (the number of bits: nRegs + (iFrame+1) * nPis) }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== utilCex.c ===========================================================*/ extern Abc_Cex_t * Abc_CexAlloc( int nRegs, int nTruePis, int nFrames ); extern Abc_Cex_t * Abc_CexAllocFull( int nRegs, int nTruePis, int nFrames ); extern Abc_Cex_t * Abc_CexMakeTriv( int nRegs, int nTruePis, int nTruePos, int iFrameOut ); extern Abc_Cex_t * Abc_CexCreate( int nRegs, int nTruePis, int * pArray, int iFrame, int iPo, int fSkipRegs ); extern Abc_Cex_t * Abc_CexDup( Abc_Cex_t * p, int nRegsNew ); extern Abc_Cex_t * Abc_CexDeriveFromCombModel( int * pModel, int nPis, int nRegs, int iPo ); extern Abc_Cex_t * Abc_CexMerge( Abc_Cex_t * pCex, Abc_Cex_t * pPart, int iFrBeg, int iFrEnd ); extern void Abc_CexPrintStats( Abc_Cex_t * p ); extern void Abc_CexPrintStatsInputs( Abc_Cex_t * p, int nInputs ); extern void Abc_CexPrint( Abc_Cex_t * p ); extern void Abc_CexFreeP( Abc_Cex_t ** p ); extern void Abc_CexFree( Abc_Cex_t * p ); extern Abc_Cex_t * Abc_CexTransformPhase( Abc_Cex_t * p, int nPisOld, int nPosOld, int nRegsOld ); extern Abc_Cex_t * Abc_CexTransformTempor( Abc_Cex_t * p, int nPisOld, int nPosOld, int nRegsOld ); extern Abc_Cex_t * Abc_CexTransformUndc( Abc_Cex_t * p, char * pInit ); extern Abc_Cex_t * Abc_CexPermute( Abc_Cex_t * p, Vec_Int_t * vMapOld2New ); extern Abc_Cex_t * Abc_CexPermuteTwo( Abc_Cex_t * p, Vec_Int_t * vPermOld, Vec_Int_t * vPermNew ); extern int Abc_CexCountOnes( Abc_Cex_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilColor.c000066400000000000000000000073751300674244400241000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilColor.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Handling counter-examples.] Synopsis [Handling counter-examples.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Feburary 13, 2011.] Revision [$Id: utilColor.c,v 1.00 2011/02/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include "misc/util/abc_global.h" #ifdef WIN32 #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ColorTest() { #ifdef WIN32 int x, y; HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); printf( "Background 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15\n" ); for ( y = 0; y < 16; y++ ) { printf( "Foreground %02d", y ); for ( x = 0; x < 16; x++ ) { printf( " " ); SetConsoleTextAttribute( hConsole, (WORD)(16 * x + y) ); printf( " Hi " ); SetConsoleTextAttribute( hConsole, 7 ); } printf( "\n" ); } #else /* fg[Default] = '[0m'; fg[DefaultBold] = '[1m' fg[Black] = '[0;30m'; fg[DarkGray] = '[1;30m' fg[Blue] = '[0;34m'; fg[LightBlue] = '[1;34m' fg[Green] = '[0;32m'; fg[LightGreen] = '[1;32m' fg[Cyan] = '[0;36m'; fg[LightCyan] = '[1;36m' fg[Red] = '[0;31m'; fg[LightRed] = '[1;31m' fg[Purple] = '[0;35m'; fg[LightPurple] = '[1;35m' fg[Brown] = '[0;33m'; fg[Yellow] = '[1;33m' fg[LightGray] = '[0;37m'; fg[White] = '[1;37m' bg[Black] = '[0;40m'; hi[Underlined] = '[4m' bg[Blue] = '[0;44m'; hi[Blinking] = '[5m' bg[Green] = '[0;42m'; hi[Inverted] = '[7m' bg[Cyan] = '[0;46m'; hi[Concealed] = '[8m' bg[Red] = '[0;41m' bg[Purple] = '[0;45m' bg[Brown] = '[0;43m' bg[LightGray] = '[0;47m' */ int x, y; printf( "Background " ); for ( x = 0; x < 8; x++ ) printf( " [1;4%dm", x ); printf( "\n" ); for ( y = 0; y < 2; y++ ) { printf( "Foreground [%dm ", y ); for ( x = 0; x < 8; x++ ) printf( " \033[%d;3%dm\033[%dm Hi \033[0m", y&1, y>>1, x ); printf( "\n" ); } for ( y = 0; y < 16; y++ ) { printf( "Foreground [%d;3%dm", y&1, y>>1 ); for ( x = 0; x < 8; x++ ) printf( " \033[%d;3%dm\033[1;4%dm Hi \033[0m", y&1, y>>1, x ); printf( "\n" ); } printf( "\033[4mUnderlined\033[0m\n" ); printf( "\033[5mBlinking \033[0m\n" ); printf( "\033[7mInverted \033[0m\n" ); printf( "\033[8mConcealed \033[0m\n" ); #endif } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilFile.c000066400000000000000000000130061300674244400236650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilFile.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Temporary file utilities.] Synopsis [Temporary file utilities.] Author [Niklas Een] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 29, 2010.] Revision [$Id: utilFile.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include #include #if defined(_MSC_VER) || defined(__MINGW32__) #include #include #include #else #include #endif #include "abc_global.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static ABC_UINT64_T realTimeAbs() // -- absolute time in nano-seconds { #if defined(_MSC_VER) LARGE_INTEGER f, t; double realTime_freq; int ok; ok = QueryPerformanceFrequency(&f); assert(ok); realTime_freq = 1.0 / (__int64)(((ABC_UINT64_T)f.LowPart) | ((ABC_UINT64_T)f.HighPart << 32)); ok = QueryPerformanceCounter(&t); assert(ok); return (ABC_UINT64_T)(__int64)(((__int64)(((ABC_UINT64_T)t.LowPart | ((ABC_UINT64_T)t.HighPart << 32))) * realTime_freq * 1000000000)); #else return 0; #endif } /**Function************************************************************* Synopsis [Opens a temporary file.] Description [Opens a temporary file with given prefix and returns file descriptor (-1 on failure) and a string containing the name of the file (to be freed by caller).] SideEffects [] SeeAlso [] ***********************************************************************/ int tmpFile(const char* prefix, const char* suffix, char** out_name) { #if defined(_MSC_VER) || defined(__MINGW32__) int i, fd; *out_name = (char*)malloc(strlen(prefix) + strlen(suffix) + 27); for (i = 0; i < 10; i++){ sprintf(*out_name, "%s%I64X%d%s", prefix, realTimeAbs(), _getpid(), suffix); fd = _open(*out_name, O_CREAT | O_EXCL | O_BINARY | O_RDWR, _S_IREAD | _S_IWRITE); if (fd == -1){ free(*out_name); *out_name = NULL; } return fd; } assert(0); // -- could not open temporary file return 0; #else int fd; *out_name = (char*)malloc(strlen(prefix) + strlen(suffix) + 7); assert(*out_name != NULL); sprintf(*out_name, "%sXXXXXX", prefix); fd = mkstemp(*out_name); if (fd == -1){ free(*out_name); *out_name = NULL; }else{ // Kludge: close(fd); unlink(*out_name); strcat(*out_name, suffix); fd = open(*out_name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE); if (fd == -1){ free(*out_name); *out_name = NULL; } } return fd; #endif } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* int main(int argc, char** argv) { char* tmp_filename; int fd = tmpFile("__abctmp_", &tmp_filename); FILE* out = fdopen(fd, "wb"); fprintf(out, "This file contains important information.\n"); fclose(out); printf("Created: %s\n", tmp_filename); free(tmp_filename); return 0; } */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char* vnsprintf(const char* format, va_list args) { unsigned n; char* ret; va_list args_copy; static FILE* dummy_file = NULL; if (!dummy_file) { #if !defined(_MSC_VER) && !defined(__MINGW32) dummy_file = fopen("/dev/null", "wb"); #else dummy_file = fopen("NUL", "wb"); #endif } #if defined(__va_copy) __va_copy(args_copy, args); #else #if defined(va_copy) va_copy(args_copy, args); #else args_copy = args; #endif #endif n = vfprintf(dummy_file, format, args); ret = ABC_ALLOC( char, n + 1 ); ret[n] = (char)255; args = args_copy; vsprintf(ret, format, args); #if !defined(__va_copy) && defined(va_copy) va_end(args_copy); #endif assert(ret[n] == 0); return ret; } char* nsprintf(const char* format, ...) { char* ret; va_list args; va_start(args, format); ret = vnsprintf(format, args); va_end(args); return ret; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilIsop.c000066400000000000000000001307771300674244400237370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilIsop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [ISOP computation.] Synopsis [ISOP computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 4, 2014.] Revision [$Id: utilIsop.c,v 1.00 2014/10/04 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_ISOP_MAX_VAR 16 #define ABC_ISOP_MAX_WORD (ABC_ISOP_MAX_VAR > 6 ? (1 << (ABC_ISOP_MAX_VAR-6)) : 1) #define ABC_ISOP_MAX_CUBE 0xFFFF typedef word FUNC_ISOP( word *, word *, word *, word, int * ); static FUNC_ISOP Abc_Isop7Cover; static FUNC_ISOP Abc_Isop8Cover; static FUNC_ISOP Abc_Isop9Cover; static FUNC_ISOP Abc_Isop10Cover; static FUNC_ISOP Abc_Isop11Cover; static FUNC_ISOP Abc_Isop12Cover; static FUNC_ISOP Abc_Isop13Cover; static FUNC_ISOP Abc_Isop14Cover; static FUNC_ISOP Abc_Isop15Cover; static FUNC_ISOP Abc_Isop16Cover; static FUNC_ISOP * s_pFuncIsopCover[17] = { NULL, // 0 NULL, // 1 NULL, // 2 NULL, // 3 NULL, // 4 NULL, // 5 NULL, // 6 Abc_Isop7Cover, // 7 Abc_Isop8Cover, // 8 Abc_Isop9Cover, // 9 Abc_Isop10Cover, // 10 Abc_Isop11Cover, // 11 Abc_Isop12Cover, // 12 Abc_Isop13Cover, // 13 Abc_Isop14Cover, // 14 Abc_Isop15Cover, // 15 Abc_Isop16Cover // 16 }; extern word Abc_IsopCheck( word * pOn, word * pOnDc, word * pRes, int nVars, word CostLim, int * pCover ); extern word Abc_EsopCheck( word * pOn, int nVars, word CostLim, int * pCover ); static inline word Abc_Cube2Cost( int nCubes ) { return (word)nCubes << 32; } static inline int Abc_CostCubes( word Cost ) { return (int)(Cost >> 32); } static inline int Abc_CostLits( word Cost ) { return (int)(Cost & 0xFFFFFFFF); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [These procedures assume that function has exact support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_IsopAddLits( int * pCover, word Cost0, word Cost1, int Var ) { if ( pCover ) { int c, nCubes0, nCubes1; nCubes0 = Abc_CostCubes( Cost0 ); nCubes1 = Abc_CostCubes( Cost1 ); for ( c = 0; c < nCubes0; c++ ) pCover[c] |= (1 << Abc_Var2Lit(Var,0)); for ( c = 0; c < nCubes1; c++ ) pCover[nCubes0+c] |= (1 << Abc_Var2Lit(Var,1)); } } word Abc_Isop6Cover( word uOn, word uOnDc, word * pRes, int nVars, word CostLim, int * pCover ) { word uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2; word Cost0, Cost1, Cost2; int Var; assert( nVars <= 6 ); assert( (uOn & ~uOnDc) == 0 ); if ( uOn == 0 ) { pRes[0] = 0; return 0; } if ( uOnDc == ~(word)0 ) { pRes[0] = ~(word)0; if ( pCover ) pCover[0] = 0; return Abc_Cube2Cost(1); } assert( nVars > 0 ); // find the topmost var for ( Var = nVars-1; Var >= 0; Var-- ) if ( Abc_Tt6HasVar( uOn, Var ) || Abc_Tt6HasVar( uOnDc, Var ) ) break; assert( Var >= 0 ); // cofactor uOn0 = Abc_Tt6Cofactor0( uOn, Var ); uOn1 = Abc_Tt6Cofactor1( uOn , Var ); uOnDc0 = Abc_Tt6Cofactor0( uOnDc, Var ); uOnDc1 = Abc_Tt6Cofactor1( uOnDc, Var ); // solve for cofactors Cost0 = Abc_Isop6Cover( uOn0 & ~uOnDc1, uOnDc0, &uRes0, Var, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; Cost1 = Abc_Isop6Cover( uOn1 & ~uOnDc0, uOnDc1, &uRes1, Var, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; Cost2 = Abc_Isop6Cover( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, &uRes2, Var, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table *pRes = uRes2 | (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); assert( (uOn & ~*pRes) == 0 && (*pRes & ~uOnDc) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, Var ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop7Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn0, uOn1, uOn2, uOnDc2, uRes0, uRes1, uRes2; word Cost0, Cost1, Cost2; int nVars = 6; assert( (pOn[0] & ~pOnDc[0]) == 0 ); assert( (pOn[1] & ~pOnDc[1]) == 0 ); // cofactor uOn0 = pOn[0] & ~pOnDc[1]; uOn1 = pOn[1] & ~pOnDc[0]; // solve for cofactors Cost0 = Abc_IsopCheck( &uOn0, pOnDc, &uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; Cost1 = Abc_IsopCheck( &uOn1, pOnDc+1, &uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; uOn2 = (pOn[0] & ~uRes0) | (pOn[1] & ~uRes1); uOnDc2 = pOnDc[0] & pOnDc[1]; Cost2 = Abc_IsopCheck( &uOn2, &uOnDc2, &uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table pRes[0] = uRes2 | uRes0; pRes[1] = uRes2 | uRes1; assert( (pOn[0] & ~pRes[0]) == 0 && (pRes[0] & ~pOnDc[0]) == 0 ); assert( (pOn[1] & ~pRes[1]) == 0 && (pRes[1] & ~pOnDc[1]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop8Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[2], uOnDc2[2], uRes0[2], uRes1[2], uRes2[2]; word Cost0, Cost1, Cost2; int nVars = 7; // negative cofactor uOn2[0] = pOn[0] & ~pOnDc[2]; uOn2[1] = pOn[1] & ~pOnDc[3]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor uOn2[0] = pOn[2] & ~pOnDc[0]; uOn2[1] = pOn[3] & ~pOnDc[1]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+2, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor uOn2[0] = (pOn[0] & ~uRes0[0]) | (pOn[2] & ~uRes1[0]); uOnDc2[0] = pOnDc[0] & pOnDc[2]; uOn2[1] = (pOn[1] & ~uRes0[1]) | (pOn[3] & ~uRes1[1]); uOnDc2[1] = pOnDc[1] & pOnDc[3]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table pRes[0] = uRes2[0] | uRes0[0]; pRes[1] = uRes2[1] | uRes0[1]; pRes[2] = uRes2[0] | uRes1[0]; pRes[3] = uRes2[1] | uRes1[1]; assert( (pOn[0] & ~pRes[0]) == 0 && (pOn[1] & ~pRes[1]) == 0 && (pOn[2] & ~pRes[2]) == 0 && (pOn[3] & ~pRes[3]) == 0 ); assert( (pRes[0] & ~pOnDc[0])==0 && (pRes[1] & ~pOnDc[1])==0 && (pRes[2] & ~pOnDc[2])==0 && (pRes[3] & ~pOnDc[3])==0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop9Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[4], uOnDc2[4], uRes0[4], uRes1[4], uRes2[4]; word Cost0, Cost1, Cost2; int c, nVars = 8, nWords = 4; // negative cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c] & ~pOnDc[c+nWords]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c+nWords] & ~pOnDc[c]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+nWords, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = (pOn[c] & ~uRes0[c]) | (pOn[c+nWords] & ~uRes1[c]), uOnDc2[c] = pOnDc[c] & pOnDc[c+nWords]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table for ( c = 0; c < nWords; c++ ) pRes[c] = uRes2[c] | uRes0[c], pRes[c+nWords] = uRes2[c] | uRes1[c]; // verify for ( c = 0; c < (nWords<<1); c++ ) assert( (pOn[c] & ~pRes[c] ) == 0 && (pRes[c] & ~pOnDc[c]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop10Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[8], uOnDc2[8], uRes0[8], uRes1[8], uRes2[8]; word Cost0, Cost1, Cost2; int c, nVars = 9, nWords = 8; // negative cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c] & ~pOnDc[c+nWords]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c+nWords] & ~pOnDc[c]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+nWords, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = (pOn[c] & ~uRes0[c]) | (pOn[c+nWords] & ~uRes1[c]), uOnDc2[c] = pOnDc[c] & pOnDc[c+nWords]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table for ( c = 0; c < nWords; c++ ) pRes[c] = uRes2[c] | uRes0[c], pRes[c+nWords] = uRes2[c] | uRes1[c]; // verify for ( c = 0; c < (nWords<<1); c++ ) assert( (pOn[c] & ~pRes[c] ) == 0 && (pRes[c] & ~pOnDc[c]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop11Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[16], uOnDc2[16], uRes0[16], uRes1[16], uRes2[16]; word Cost0, Cost1, Cost2; int c, nVars = 10, nWords = 16; // negative cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c] & ~pOnDc[c+nWords]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c+nWords] & ~pOnDc[c]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+nWords, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = (pOn[c] & ~uRes0[c]) | (pOn[c+nWords] & ~uRes1[c]), uOnDc2[c] = pOnDc[c] & pOnDc[c+nWords]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table for ( c = 0; c < nWords; c++ ) pRes[c] = uRes2[c] | uRes0[c], pRes[c+nWords] = uRes2[c] | uRes1[c]; // verify for ( c = 0; c < (nWords<<1); c++ ) assert( (pOn[c] & ~pRes[c] ) == 0 && (pRes[c] & ~pOnDc[c]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop12Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[32], uOnDc2[32], uRes0[32], uRes1[32], uRes2[32]; word Cost0, Cost1, Cost2; int c, nVars = 11, nWords = 32; // negative cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c] & ~pOnDc[c+nWords]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c+nWords] & ~pOnDc[c]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+nWords, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = (pOn[c] & ~uRes0[c]) | (pOn[c+nWords] & ~uRes1[c]), uOnDc2[c] = pOnDc[c] & pOnDc[c+nWords]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table for ( c = 0; c < nWords; c++ ) pRes[c] = uRes2[c] | uRes0[c], pRes[c+nWords] = uRes2[c] | uRes1[c]; // verify for ( c = 0; c < (nWords<<1); c++ ) assert( (pOn[c] & ~pRes[c] ) == 0 && (pRes[c] & ~pOnDc[c]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop13Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[64], uOnDc2[64], uRes0[64], uRes1[64], uRes2[64]; word Cost0, Cost1, Cost2; int c, nVars = 12, nWords = 64; // negative cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c] & ~pOnDc[c+nWords]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c+nWords] & ~pOnDc[c]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+nWords, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = (pOn[c] & ~uRes0[c]) | (pOn[c+nWords] & ~uRes1[c]), uOnDc2[c] = pOnDc[c] & pOnDc[c+nWords]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table for ( c = 0; c < nWords; c++ ) pRes[c] = uRes2[c] | uRes0[c], pRes[c+nWords] = uRes2[c] | uRes1[c]; // verify for ( c = 0; c < (nWords<<1); c++ ) assert( (pOn[c] & ~pRes[c] ) == 0 && (pRes[c] & ~pOnDc[c]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop14Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[128], uOnDc2[128], uRes0[128], uRes1[128], uRes2[128]; word Cost0, Cost1, Cost2; int c, nVars = 13, nWords = 128; // negative cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c] & ~pOnDc[c+nWords]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c+nWords] & ~pOnDc[c]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+nWords, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = (pOn[c] & ~uRes0[c]) | (pOn[c+nWords] & ~uRes1[c]), uOnDc2[c] = pOnDc[c] & pOnDc[c+nWords]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table for ( c = 0; c < nWords; c++ ) pRes[c] = uRes2[c] | uRes0[c], pRes[c+nWords] = uRes2[c] | uRes1[c]; // verify for ( c = 0; c < (nWords<<1); c++ ) assert( (pOn[c] & ~pRes[c] ) == 0 && (pRes[c] & ~pOnDc[c]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop15Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[256], uOnDc2[256], uRes0[256], uRes1[256], uRes2[256]; word Cost0, Cost1, Cost2; int c, nVars = 14, nWords = 256; // negative cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c] & ~pOnDc[c+nWords]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c+nWords] & ~pOnDc[c]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+nWords, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = (pOn[c] & ~uRes0[c]) | (pOn[c+nWords] & ~uRes1[c]), uOnDc2[c] = pOnDc[c] & pOnDc[c+nWords]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table for ( c = 0; c < nWords; c++ ) pRes[c] = uRes2[c] | uRes0[c], pRes[c+nWords] = uRes2[c] | uRes1[c]; // verify for ( c = 0; c < (nWords<<1); c++ ) assert( (pOn[c] & ~pRes[c] ) == 0 && (pRes[c] & ~pOnDc[c]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_Isop16Cover( word * pOn, word * pOnDc, word * pRes, word CostLim, int * pCover ) { word uOn2[512], uOnDc2[512], uRes0[512], uRes1[512], uRes2[512]; word Cost0, Cost1, Cost2; int c, nVars = 15, nWords = 512; // negative cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c] & ~pOnDc[c+nWords]; Cost0 = Abc_IsopCheck( uOn2, pOnDc, uRes0, nVars, CostLim, pCover ); if ( Cost0 >= CostLim ) return CostLim; // positive cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = pOn[c+nWords] & ~pOnDc[c]; Cost1 = Abc_IsopCheck( uOn2, pOnDc+nWords, uRes1, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); if ( Cost0 + Cost1 >= CostLim ) return CostLim; // middle cofactor for ( c = 0; c < nWords; c++ ) uOn2[c] = (pOn[c] & ~uRes0[c]) | (pOn[c+nWords] & ~uRes1[c]), uOnDc2[c] = pOnDc[c] & pOnDc[c+nWords]; Cost2 = Abc_IsopCheck( uOn2, uOnDc2, uRes2, nVars, CostLim, pCover ? pCover + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1) : NULL ); if ( Cost0 + Cost1 + Cost2 >= CostLim ) return CostLim; // derive the final truth table for ( c = 0; c < nWords; c++ ) pRes[c] = uRes2[c] | uRes0[c], pRes[c+nWords] = uRes2[c] | uRes1[c]; // verify for ( c = 0; c < (nWords<<1); c++ ) assert( (pOn[c] & ~pRes[c] ) == 0 && (pRes[c] & ~pOnDc[c]) == 0 ); Abc_IsopAddLits( pCover, Cost0, Cost1, nVars ); return Cost0 + Cost1 + Cost2 + Abc_CostCubes(Cost0) + Abc_CostCubes(Cost1); } word Abc_IsopCheck( word * pOn, word * pOnDc, word * pRes, int nVars, word CostLim, int * pCover ) { int nVarsNew; word Cost; if ( nVars <= 6 ) return Abc_Isop6Cover( *pOn, *pOnDc, pRes, nVars, CostLim, pCover ); for ( nVarsNew = nVars; nVarsNew > 6; nVarsNew-- ) if ( Abc_TtHasVar( pOn, nVars, nVarsNew-1 ) || Abc_TtHasVar( pOnDc, nVars, nVarsNew-1 ) ) break; if ( nVarsNew == 6 ) Cost = Abc_Isop6Cover( *pOn, *pOnDc, pRes, nVarsNew, CostLim, pCover ); else Cost = s_pFuncIsopCover[nVarsNew]( pOn, pOnDc, pRes, CostLim, pCover ); Abc_TtStretch6( pRes, nVarsNew, nVars ); return Cost; } /**Function************************************************************* Synopsis [Create truth table for the given cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word ** Abc_IsopTtElems() { static word TtElems[ABC_ISOP_MAX_VAR+1][ABC_ISOP_MAX_WORD], * pTtElems[ABC_ISOP_MAX_VAR+1] = {NULL}; if ( pTtElems[0] == NULL ) { int v; for ( v = 0; v <= ABC_ISOP_MAX_VAR; v++ ) pTtElems[v] = TtElems[v]; Abc_TtElemInit( pTtElems, ABC_ISOP_MAX_VAR ); } return pTtElems; } void Abc_IsopBuildTruth( Vec_Int_t * vCover, int nVars, word * pRes, int fXor, int fCompl ) { word ** pTtElems = Abc_IsopTtElems(); word pCube[ABC_ISOP_MAX_WORD]; int nWords = Abc_TtWordNum( nVars ); int c, v, Cube; assert( nVars <= ABC_ISOP_MAX_VAR ); Abc_TtClear( pRes, nWords ); Vec_IntForEachEntry( vCover, Cube, c ) { Abc_TtFill( pCube, nWords ); for ( v = 0; v < nVars; v++ ) if ( ((Cube >> (v << 1)) & 3) == 1 ) Abc_TtSharp( pCube, pCube, pTtElems[v], nWords ); else if ( ((Cube >> (v << 1)) & 3) == 2 ) Abc_TtAnd( pCube, pCube, pTtElems[v], nWords, 0 ); if ( fXor ) Abc_TtXor( pRes, pRes, pCube, nWords, 0 ); else Abc_TtOr( pRes, pRes, pCube, nWords ); } if ( fCompl ) Abc_TtNot( pRes, nWords ); } static inline void Abc_IsopVerify( word * pFunc, int nVars, word * pRes, Vec_Int_t * vCover, int fXor, int fCompl ) { Abc_IsopBuildTruth( vCover, nVars, pRes, fXor, fCompl ); if ( !Abc_TtEqual( pFunc, pRes, Abc_TtWordNum(nVars) ) ) printf( "Verification failed.\n" ); // else // printf( "Verification succeeded.\n" ); } /**Function************************************************************* Synopsis [This procedure assumes that function has exact support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_Isop( word * pFunc, int nVars, int nCubeLim, Vec_Int_t * vCover, int fTryBoth ) { word pRes[ABC_ISOP_MAX_WORD]; word Cost0, Cost1, Cost, CostInit = Abc_Cube2Cost(nCubeLim); assert( nVars <= ABC_ISOP_MAX_VAR ); Vec_IntGrow( vCover, 1 << (nVars-1) ); if ( fTryBoth ) { Cost0 = Abc_IsopCheck( pFunc, pFunc, pRes, nVars, CostInit, NULL ); Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); Cost1 = Abc_IsopCheck( pFunc, pFunc, pRes, nVars, Cost0, NULL ); Cost = Abc_MinWord( Cost0, Cost1 ); if ( Cost == CostInit ) { Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); return -1; } if ( Cost == Cost0 ) { Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); Abc_IsopCheck( pFunc, pFunc, pRes, nVars, CostInit, Vec_IntArray(vCover) ); } else // if ( Cost == Cost1 ) { Abc_IsopCheck( pFunc, pFunc, pRes, nVars, CostInit, Vec_IntArray(vCover) ); Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); } } else { Cost = Cost0 = Abc_IsopCheck( pFunc, pFunc, pRes, nVars, CostInit, Vec_IntArray(vCover) ); if ( Cost == CostInit ) return -1; } vCover->nSize = Abc_CostCubes(Cost); assert( vCover->nSize <= vCover->nCap ); // Abc_IsopVerify( pFunc, nVars, pRes, vCover, 0, Cost != Cost0 ); return Cost != Cost0; } /**Function************************************************************* Synopsis [Compute CNF assuming it does not exceed the limit.] Description [Please note that pCover should have at least 32 extra entries!] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_IsopCnf( word * pFunc, int nVars, int nCubeLim, int * pCover ) { word pRes[ABC_ISOP_MAX_WORD]; word Cost0, Cost1, CostInit = Abc_Cube2Cost(nCubeLim); int c, nCubes0, nCubes1; assert( nVars <= ABC_ISOP_MAX_VAR ); assert( Abc_TtHasVar( pFunc, nVars, nVars - 1 ) ); if ( nVars > 6 ) Cost0 = s_pFuncIsopCover[nVars]( pFunc, pFunc, pRes, CostInit, pCover ); else Cost0 = Abc_Isop6Cover( *pFunc, *pFunc, pRes, nVars, CostInit, pCover ); if ( Cost0 >= CostInit ) return CostInit; Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); if ( nVars > 6 ) Cost1 = s_pFuncIsopCover[nVars]( pFunc, pFunc, pRes, CostInit, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); else Cost1 = Abc_Isop6Cover( *pFunc, *pFunc, pRes, nVars, CostInit, pCover ? pCover + Abc_CostCubes(Cost0) : NULL ); Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); if ( Cost0 + Cost1 >= CostInit ) return CostInit; nCubes0 = Abc_CostCubes(Cost0); nCubes1 = Abc_CostCubes(Cost1); if ( pCover ) { for ( c = 0; c < nCubes0; c++ ) pCover[c] |= (1 << Abc_Var2Lit(nVars, 0)); for ( c = 0; c < nCubes1; c++ ) pCover[c+nCubes0] |= (1 << Abc_Var2Lit(nVars, 1)); } return nCubes0 + nCubes1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_IsopCountLits( Vec_Int_t * vCover, int nVars ) { int i, k, Entry, Literal, nLits = 0; if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0) ) return 0; Vec_IntForEachEntry( vCover, Entry, i ) { for ( k = 0; k < nVars; k++ ) { Literal = 3 & (Entry >> (k << 1)); if ( Literal == 1 ) // neg literal nLits++; else if ( Literal == 2 ) // pos literal nLits++; else if ( Literal != 0 ) assert( 0 ); } } return nLits; } void Abc_IsopPrintCover( Vec_Int_t * vCover, int nVars, int fCompl ) { int i, k, Entry, Literal; if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0) ) { printf( "Constant %d\n", Vec_IntSize(vCover) ); return; } Vec_IntForEachEntry( vCover, Entry, i ) { for ( k = 0; k < nVars; k++ ) { Literal = 3 & (Entry >> (k << 1)); if ( Literal == 1 ) // neg literal printf( "0" ); else if ( Literal == 2 ) // pos literal printf( "1" ); else if ( Literal == 0 ) printf( "-" ); else assert( 0 ); } printf( " %d\n", !fCompl ); } } void Abc_IsopPrint( word * t, int nVars, Vec_Int_t * vCover, int fTryBoth ) { int fCompl = Abc_Isop( t, nVars, ABC_ISOP_MAX_CUBE, vCover, fTryBoth ); Abc_IsopPrintCover( vCover, nVars, fCompl ); } /**Function************************************************************* Synopsis [These procedures assume that function has exact support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_EsopAddLits( int * pCover, word r0, word r1, word r2, word Max, int Var ) { int i, c0, c1, c2; if ( Max == r0 ) { c2 = Abc_CostCubes(r2); if ( pCover ) { c0 = Abc_CostCubes(r0); c1 = Abc_CostCubes(r1); for ( i = 0; i < c1; i++ ) pCover[i] = pCover[c0+i]; for ( i = 0; i < c2; i++ ) pCover[c1+i] = pCover[c0+c1+i] | (1 << Abc_Var2Lit(Var,0)); } return c2; } else if ( Max == r1 ) { c2 = Abc_CostCubes(r2); if ( pCover ) { c0 = Abc_CostCubes(r0); c1 = Abc_CostCubes(r1); for ( i = 0; i < c2; i++ ) pCover[c0+i] = pCover[c0+c1+i] | (1 << Abc_Var2Lit(Var,1)); } return c2; } else { c0 = Abc_CostCubes(r0); c1 = Abc_CostCubes(r1); if ( pCover ) { c2 = Abc_CostCubes(r2); for ( i = 0; i < c0; i++ ) pCover[i] |= (1 << Abc_Var2Lit(Var,0)); for ( i = 0; i < c1; i++ ) pCover[c0+i] |= (1 << Abc_Var2Lit(Var,1)); } return c0 + c1; } } word Abc_Esop6Cover( word t, int nVars, word CostLim, int * pCover ) { word c0, c1; word r0, r1, r2, Max; int Var; assert( nVars <= 6 ); if ( t == 0 ) return 0; if ( t == ~(word)0 ) { if ( pCover ) *pCover = 0; return Abc_Cube2Cost(1); } assert( nVars > 0 ); // find the topmost var for ( Var = nVars-1; Var >= 0; Var-- ) if ( Abc_Tt6HasVar( t, Var ) ) break; assert( Var >= 0 ); // cofactor c0 = Abc_Tt6Cofactor0( t, Var ); c1 = Abc_Tt6Cofactor1( t, Var ); // call recursively r0 = Abc_Esop6Cover( c0, Var, CostLim, pCover ? pCover : NULL ); if ( r0 >= CostLim ) return CostLim; r1 = Abc_Esop6Cover( c1, Var, CostLim, pCover ? pCover + Abc_CostCubes(r0) : NULL ); if ( r1 >= CostLim ) return CostLim; r2 = Abc_Esop6Cover( c0 ^ c1, Var, CostLim, pCover ? pCover + Abc_CostCubes(r0) + Abc_CostCubes(r1) : NULL ); if ( r2 >= CostLim ) return CostLim; Max = Abc_MaxWord( r0, Abc_MaxWord(r1, r2) ); if ( r0 + r1 + r2 - Max >= CostLim ) return CostLim; return r0 + r1 + r2 - Max + Abc_EsopAddLits( pCover, r0, r1, r2, Max, Var ); } word Abc_EsopCover( word * pOn, int nVars, word CostLim, int * pCover ) { word r0, r1, r2, Max; int c, nWords = (1 << (nVars - 7)); assert( nVars > 6 ); assert( Abc_TtHasVar( pOn, nVars, nVars - 1 ) ); r0 = Abc_EsopCheck( pOn, nVars-1, CostLim, pCover ); if ( r0 >= CostLim ) return CostLim; r1 = Abc_EsopCheck( pOn+nWords, nVars-1, CostLim, pCover ? pCover + Abc_CostCubes(r0) : NULL ); if ( r1 >= CostLim ) return CostLim; for ( c = 0; c < nWords; c++ ) pOn[c] ^= pOn[nWords+c]; r2 = Abc_EsopCheck( pOn, nVars-1, CostLim, pCover ? pCover + Abc_CostCubes(r0) + Abc_CostCubes(r1) : NULL ); for ( c = 0; c < nWords; c++ ) pOn[c] ^= pOn[nWords+c]; if ( r2 >= CostLim ) return CostLim; Max = Abc_MaxWord( r0, Abc_MaxWord(r1, r2) ); if ( r0 + r1 + r2 - Max >= CostLim ) return CostLim; return r0 + r1 + r2 - Max + Abc_EsopAddLits( pCover, r0, r1, r2, Max, nVars-1 ); } word Abc_EsopCheck( word * pOn, int nVars, word CostLim, int * pCover ) { int nVarsNew; word Cost; if ( nVars <= 6 ) return Abc_Esop6Cover( *pOn, nVars, CostLim, pCover ); for ( nVarsNew = nVars; nVarsNew > 6; nVarsNew-- ) if ( Abc_TtHasVar( pOn, nVars, nVarsNew-1 ) ) break; if ( nVarsNew == 6 ) Cost = Abc_Esop6Cover( *pOn, nVarsNew, CostLim, pCover ); else Cost = Abc_EsopCover( pOn, nVarsNew, CostLim, pCover ); return Cost; } /**Function************************************************************* Synopsis [Perform ISOP computation by subtracting cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtIntersect2( word * pIn1, word * pIn2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( pIn1[w] & pIn2[w] ) return 1; return 0; } static inline int Abc_TtCheckWithCubePos2Neg( word * t, word * c, int nWords, int iVar ) { if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) if ( t[i] & (c[i] >> Shift) ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( t[Step+i] & c[i] ) return 0; return 1; } } static inline int Abc_TtCheckWithCubeNeg2Pos( word * t, word * c, int nWords, int iVar ) { if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) if ( t[i] & (c[i] << Shift) ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( t[i] & c[Step+i] ) return 0; return 1; } } static inline void Abc_TtExpandCubePos2Neg( word * t, int nWords, int iVar ) { if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) t[i] |= (t[i] >> Shift); } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) t[i] = t[Step+i]; } } static inline void Abc_TtExpandCubeNeg2Pos( word * t, int nWords, int iVar ) { if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) t[i] |= (t[i] << Shift); } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) t[Step+i] = t[i]; } } word Abc_IsopNew( word * pOn, word * pOnDc, word * pRes, int nVars, word CostLim, int * pCover ) { word pCube[ABC_ISOP_MAX_WORD]; word pOnset[ABC_ISOP_MAX_WORD]; word pOffset[ABC_ISOP_MAX_WORD]; int pBlocks[16], nBlocks, vTwo, uTwo; int nWords = Abc_TtWordNum(nVars); int c, v, u, iMint, Cube, nLits = 0; assert( nVars <= ABC_ISOP_MAX_VAR ); Abc_TtClear( pRes, nWords ); Abc_TtCopy( pOnset, pOn, nWords, 0 ); Abc_TtCopy( pOffset, pOnDc, nWords, 1 ); if ( nVars < 6 ) pOnset[0] >>= (64 - (1 << nVars)); for ( c = 0; !Abc_TtIsConst0(pOnset, nWords); c++ ) { // pick one minterm iMint = Abc_TtFindFirstBit(pOnset, nVars); for ( Cube = v = 0; v < nVars; v++ ) Cube |= (1 << Abc_Var2Lit(v, (iMint >> v) & 1)); // check expansion for the minterm nBlocks = 0; for ( v = 0; v < nVars; v++ ) if ( (pBlocks[v] = Abc_TtGetBit(pOffset, iMint ^ (1 << v))) ) nBlocks++; // check second step if ( nBlocks == nVars ) // cannot expand { Abc_TtSetBit( pRes, iMint ); Abc_TtXorBit( pOnset, iMint ); pCover[c] = Cube; nLits += nVars; continue; } // check dual expansion vTwo = uTwo = -1; if ( nBlocks < nVars - 1 ) { for ( v = 0; v < nVars && vTwo == -1; v++ ) if ( !pBlocks[v] ) for ( u = v + 1; u < nVars; u++ ) if ( !pBlocks[u] ) { if ( Abc_TtGetBit( pOffset, iMint ^ (1 << v) ^ (1 << u) ) ) continue; // can expand both directions vTwo = v; uTwo = u; break; } } if ( vTwo == -1 ) // can expand only one { for ( v = 0; v < nVars; v++ ) if ( !pBlocks[v] ) break; Abc_TtSetBit( pRes, iMint ); Abc_TtSetBit( pRes, iMint ^ (1 << v) ); Abc_TtXorBit( pOnset, iMint ); if ( Abc_TtGetBit(pOnset, iMint ^ (1 << v)) ) Abc_TtXorBit( pOnset, iMint ^ (1 << v) ); pCover[c] = Cube & ~(3 << Abc_Var2Lit(v, 0)); nLits += nVars - 1; continue; } if ( nBlocks == nVars - 2 && vTwo >= 0 ) // can expand only these two { Abc_TtSetBit( pRes, iMint ); Abc_TtSetBit( pRes, iMint ^ (1 << vTwo) ); Abc_TtSetBit( pRes, iMint ^ (1 << uTwo) ); Abc_TtSetBit( pRes, iMint ^ (1 << vTwo) ^ (1 << uTwo) ); Abc_TtXorBit( pOnset, iMint ); if ( Abc_TtGetBit(pOnset, iMint ^ (1 << vTwo)) ) Abc_TtXorBit( pOnset, iMint ^ (1 << vTwo) ); if ( Abc_TtGetBit(pOnset, iMint ^ (1 << uTwo)) ) Abc_TtXorBit( pOnset, iMint ^ (1 << uTwo) ); if ( Abc_TtGetBit(pOnset, iMint ^ (1 << vTwo) ^ (1 << uTwo)) ) Abc_TtXorBit( pOnset, iMint ^ (1 << vTwo) ^ (1 << uTwo) ); pCover[c] = Cube & ~(3 << Abc_Var2Lit(vTwo, 0)) & ~(3 << Abc_Var2Lit(uTwo, 0)); nLits += nVars - 2; continue; } // can expand others as well Abc_TtClear( pCube, nWords ); Abc_TtSetBit( pCube, iMint ); Abc_TtSetBit( pCube, iMint ^ (1 << vTwo) ); Abc_TtSetBit( pCube, iMint ^ (1 << uTwo) ); Abc_TtSetBit( pCube, iMint ^ (1 << vTwo) ^ (1 << uTwo) ); Cube &= ~(3 << Abc_Var2Lit(vTwo, 0)) & ~(3 << Abc_Var2Lit(uTwo, 0)); assert( !Abc_TtIntersect2(pCube, pOffset, nWords) ); // expand against offset for ( v = 0; v < nVars; v++ ) if ( v != vTwo && v != uTwo ) { int Shift = Abc_Var2Lit( v, 0 ); if ( (Cube >> Shift) == 2 && Abc_TtCheckWithCubePos2Neg(pOffset, pCube, nWords, v) ) // pos literal { Abc_TtExpandCubePos2Neg( pCube, nWords, v ); Cube &= ~(3 << Shift); } else if ( (Cube >> Shift) == 1 && Abc_TtCheckWithCubeNeg2Pos(pOffset, pCube, nWords, v) ) // neg literal { Abc_TtExpandCubeNeg2Pos( pCube, nWords, v ); Cube &= ~(3 << Shift); } else nLits++; } // add cube to solution Abc_TtOr( pRes, pRes, pCube, nWords ); Abc_TtSharp( pOnset, pOnset, pCube, nWords ); pCover[c] = Cube; } pRes[0] = Abc_Tt6Stretch( pRes[0], nVars ); return Abc_Cube2Cost(c) | nLits; } void Abc_IsopTestNew() { int nVars = 4; Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); word r, t = (s_Truths6[0] & s_Truths6[1]) ^ (s_Truths6[2] & s_Truths6[3]), copy = t; // word r, t = ~s_Truths6[0] | (s_Truths6[1] & s_Truths6[2] & s_Truths6[3]), copy = t; // word r, t = 0xABCDABCDABCDABCD, copy = t; // word r, t = 0x6996000000006996, copy = t; // word Cost = Abc_IsopNew( &t, &t, &r, nVars, Abc_Cube2Cost(ABC_ISOP_MAX_CUBE), Vec_IntArray(vCover) ); word Cost = Abc_EsopCheck( &t, nVars, Abc_Cube2Cost(ABC_ISOP_MAX_CUBE), Vec_IntArray(vCover) ); vCover->nSize = Abc_CostCubes(Cost); assert( vCover->nSize <= vCover->nCap ); printf( "Cubes = %d. Lits = %d.\n", Abc_CostCubes(Cost), Abc_CostLits(Cost) ); Abc_IsopPrintCover( vCover, nVars, 0 ); Abc_IsopVerify( ©, nVars, &r, vCover, 1, 0 ); Vec_IntFree( vCover ); } /**Function************************************************************* Synopsis [Compute CNF assuming it does not exceed the limit.] Description [Please note that pCover should have at least 32 extra entries!] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_IsopTest( word * pFunc, int nVars, Vec_Int_t * vCover ) { int fVerbose = 0; static word TotalCost[6] = {0}; static abctime TotalTime[6] = {0}; static int Counter; word pRes[ABC_ISOP_MAX_WORD]; word Cost; abctime clk; Counter++; if ( Counter == 9999 ) { Abc_PrintTime( 1, "0", TotalTime[0] ); Abc_PrintTime( 1, "1", TotalTime[1] ); Abc_PrintTime( 1, "2", TotalTime[2] ); Abc_PrintTime( 1, "3", TotalTime[3] ); Abc_PrintTime( 1, "4", TotalTime[4] ); Abc_PrintTime( 1, "5", TotalTime[5] ); } assert( nVars <= ABC_ISOP_MAX_VAR ); // if ( fVerbose ) // Dau_DsdPrintFromTruth( pFunc, nVars ), printf( " " ); clk = Abc_Clock(); Cost = Abc_IsopCheck( pFunc, pFunc, pRes, nVars, Abc_Cube2Cost(ABC_ISOP_MAX_CUBE), Vec_IntArray(vCover) ); vCover->nSize = Abc_CostCubes(Cost); assert( vCover->nSize <= vCover->nCap ); if ( fVerbose ) printf( "%5d %7d ", Abc_CostCubes(Cost), Abc_CostLits(Cost) ); // Abc_IsopVerify( pFunc, nVars, pRes, vCover, 0, 0 ); TotalCost[0] += Abc_CostCubes(Cost); TotalTime[0] += Abc_Clock() - clk; clk = Abc_Clock(); Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); Cost = Abc_IsopCheck( pFunc, pFunc, pRes, nVars, Abc_Cube2Cost(ABC_ISOP_MAX_CUBE), Vec_IntArray(vCover) ); Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); vCover->nSize = Abc_CostCubes(Cost); assert( vCover->nSize <= vCover->nCap ); if ( fVerbose ) printf( "%5d %7d ", Abc_CostCubes(Cost), Abc_CostLits(Cost) ); // Abc_IsopVerify( pFunc, nVars, pRes, vCover, 0, 1 ); TotalCost[1] += Abc_CostCubes(Cost); TotalTime[1] += Abc_Clock() - clk; /* clk = Abc_Clock(); Cost = Abc_EsopCheck( pFunc, nVars, Abc_Cube2Cost(ABC_ISOP_MAX_CUBE), Vec_IntArray(vCover) ); vCover->nSize = Abc_CostCubes(Cost); assert( vCover->nSize <= vCover->nCap ); if ( fVerbose ) printf( "%5d %7d ", Abc_CostCubes(Cost), Abc_CostLits(Cost) ); // Abc_IsopVerify( pFunc, nVars, pRes, vCover, 1, 0 ); TotalCost[2] += Abc_CostCubes(Cost); TotalTime[2] += Abc_Clock() - clk; clk = Abc_Clock(); Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); Cost = Abc_EsopCheck( pFunc, nVars, Abc_Cube2Cost(ABC_ISOP_MAX_CUBE), Vec_IntArray(vCover) ); Abc_TtNot( pFunc, Abc_TtWordNum(nVars) ); vCover->nSize = Abc_CostCubes(Cost); assert( vCover->nSize <= vCover->nCap ); if ( fVerbose ) printf( "%5d %7d ", Abc_CostCubes(Cost), Abc_CostLits(Cost) ); // Abc_IsopVerify( pFunc, nVars, pRes, vCover, 1, 1 ); TotalCost[3] += Abc_CostCubes(Cost); TotalTime[3] += Abc_Clock() - clk; */ /* // try new computation clk = Abc_Clock(); Cost = Abc_IsopNew( pFunc, pFunc, pRes, nVars, Abc_Cube2Cost(ABC_ISOP_MAX_CUBE), Vec_IntArray(vCover) ); vCover->nSize = Abc_CostCubes(Cost); assert( vCover->nSize <= vCover->nCap ); if ( fVerbose ) printf( "%5d %7d ", Abc_CostCubes(Cost), Abc_CostLits(Cost) ); Abc_IsopVerify( pFunc, nVars, pRes, vCover, 0, 0 ); TotalCost[4] += Abc_CostCubes(Cost); TotalTime[4] += Abc_Clock() - clk; */ /* // try old computation clk = Abc_Clock(); Cost = Kit_TruthIsop( (unsigned *)pFunc, nVars, vCover, 1 ); vCover->nSize = Vec_IntSize(vCover); assert( vCover->nSize <= vCover->nCap ); if ( fVerbose ) printf( "%5d %7d ", Vec_IntSize(vCover), Abc_IsopCountLits(vCover, nVars) ); TotalCost[4] += Vec_IntSize(vCover); TotalTime[4] += Abc_Clock() - clk; */ clk = Abc_Clock(); Cost = Abc_Isop( pFunc, nVars, ABC_ISOP_MAX_CUBE, vCover, 1 ); if ( fVerbose ) printf( "%5d %7d ", Vec_IntSize(vCover), Abc_IsopCountLits(vCover, nVars) ); TotalCost[5] += Vec_IntSize(vCover); TotalTime[5] += Abc_Clock() - clk; if ( fVerbose ) printf( " | %8d %8d %8d %8d %8d %8d", (int)TotalCost[0], (int)TotalCost[1], (int)TotalCost[2], (int)TotalCost[3], (int)TotalCost[4], (int)TotalCost[5] ); if ( fVerbose ) printf( "\n" ); //Abc_IsopPrintCover( vCover, nVars, 0 ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilMem.c000066400000000000000000000213161300674244400235270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilMem.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Memory recycling utilities.] Synopsis [Memory recycling utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: utilMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "abc_global.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Mem_t_ Vec_Mem_t; struct Vec_Mem_t_ { int nCap; int nSize; void ** pArray; }; void * s_vAllocs = NULL; void * s_vFrees = NULL; int s_fInterrupt = 0; #define ABC_MEM_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) #define ABC_MEM_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) #define ABC_MEM_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) #define ABC_MEM_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) #define ABC_MEM_REALLOC(type, obj, num) \ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ ((type *) malloc(sizeof(type) * (num)))) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Mem_t * Vec_MemAlloc( int nCap ) { Vec_Mem_t * p; p = ABC_MEM_ALLOC( Vec_Mem_t, 1 ); if ( nCap > 0 && nCap < 8 ) nCap = 8; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_MEM_ALLOC( void *, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Frees the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_MemFree( Vec_Mem_t * p ) { ABC_MEM_FREE( p->pArray ); ABC_MEM_FREE( p ); } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_MemGrow( Vec_Mem_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_MEM_REALLOC( void *, p->pArray, nCapMin ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_MemPush( Vec_Mem_t * p, void * Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_MemGrow( p, 16 ); else Vec_MemGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Vec_MemSort( Vec_Mem_t * p, int (*Vec_MemSortCompare)() ) { if ( p->nSize < 2 ) return; qsort( (void *)p->pArray, p->nSize, sizeof(void *), (int (*)(const void *, const void *)) Vec_MemSortCompare ); } /**Function************************************************************* Synopsis [Remembers an allocated pointer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Util_MemRecAlloc( void * pMem ) { if ( s_vAllocs ) Vec_MemPush( (Vec_Mem_t *)s_vAllocs, pMem ); return pMem; } /**Function************************************************************* Synopsis [Remembers a deallocated pointer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Util_MemRecFree( void * pMem ) { if ( s_vFrees ) Vec_MemPush( (Vec_Mem_t *)s_vFrees, pMem ); return pMem; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Util_ComparePointers( void ** pp1, void ** pp2 ) { if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Finds entries that do not appear in both lists.] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Mem_t * Vec_MemTwoMerge( Vec_Mem_t * vArr1, Vec_Mem_t * vArr2 ) { Vec_Mem_t * vArr = Vec_MemAlloc( vArr1->nSize + vArr2->nSize ); void ** pBeg = vArr->pArray; void ** pBeg1 = vArr1->pArray; void ** pBeg2 = vArr2->pArray; void ** pEnd1 = vArr1->pArray + vArr1->nSize; void ** pEnd2 = vArr2->pArray + vArr2->nSize; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) pBeg1++, pBeg2++; else if ( *pBeg1 < *pBeg2 ) { free( *pBeg1 ); *pBeg++ = *pBeg1++; } else assert( 0 ); // *pBeg++ = *pBeg2++; } while ( pBeg1 < pEnd1 ) *pBeg++ = *pBeg1++; // while ( pBeg2 < pEnd2 ) // *pBeg++ = *pBeg2++; assert( pBeg2 >= pEnd2 ); vArr->nSize = pBeg - vArr->pArray; assert( vArr->nSize <= vArr->nCap ); assert( vArr->nSize >= vArr1->nSize ); assert( vArr->nSize >= vArr2->nSize ); return vArr; } /**Function************************************************************* Synopsis [Recycles the accumulated memory.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Util_MemRecRecycle() { Vec_Mem_t * vMerge; assert( s_vAllocs == NULL ); assert( s_vFrees == NULL ); Vec_MemSort( (Vec_Mem_t *)s_vAllocs, (int (*)())Util_ComparePointers ); Vec_MemSort( (Vec_Mem_t *)s_vFrees, (int (*)())Util_ComparePointers ); vMerge = (Vec_Mem_t *)Vec_MemTwoMerge( (Vec_Mem_t *)s_vAllocs, (Vec_Mem_t *)s_vFrees ); Vec_MemFree( vMerge ); } /**Function************************************************************* Synopsis [Starts memory structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Util_MemRecStart() { assert( s_vAllocs == NULL && s_vFrees == NULL ); s_vAllocs = Vec_MemAlloc( 1000 ); s_vFrees = Vec_MemAlloc( 1000 ); } /**Function************************************************************* Synopsis [Quits memory structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Util_MemRecQuit() { assert( s_vAllocs != NULL && s_vFrees != NULL ); Vec_MemFree( (Vec_Mem_t *)s_vAllocs ); Vec_MemFree( (Vec_Mem_t *)s_vFrees ); } /**Function************************************************************* Synopsis [Starts memory structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Util_MemRecIsSet() { return s_vAllocs != NULL && s_vFrees != NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilMem.h000066400000000000000000000047011300674244400235330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Memory recycling utilities.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: utilInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__util__utilMem_h #define ABC__misc__util__utilMem_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START extern void * s_vAllocs; // storage of allocated pointers extern void * s_vFrees; // storage of deallocated pointers extern int s_fInterrupt; // set to 1 when it is time to backout //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== utilMem.c ==========================================================*/ extern void * Util_MemRecAlloc( void * pMem ); extern void * Util_MemRecFree( void * pMem ); extern void Util_MemStart(); extern void Util_MemQuit(); extern void Util_MemRecycle(); extern int Util_MemRecIsSet(); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilNam.c000066400000000000000000000436771300674244400235420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilNam.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Manager for character strings.] Synopsis [Manager for character strings.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: utilNam.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "abc_global.h" #include "misc/vec/vec.h" #include "utilNam.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // this package maps non-empty character strings into natural numbers and back // name manager struct Abc_Nam_t_ { // info storage for names int nStore; // the size of allocated storage int iHandle; // the current free handle char * pStore; // storage for name objects // internal number mappings Vec_Int_t vInt2Handle; // mapping integers into handles Vec_Int_t vInt2Next; // mapping integers into nexts // hash table for names int * pBins; // the hash table bins int nBins; // the number of bins // manager recycling int nRefs; // reference counter for the manager // internal buffer Vec_Str_t vBuffer; }; static inline char * Abc_NamHandleToStr( Abc_Nam_t * p, int h ) { return (char *)(p->pStore + h); } static inline int Abc_NamIntToHandle( Abc_Nam_t * p, int i ) { return Vec_IntEntry(&p->vInt2Handle, i); } static inline char * Abc_NamIntToStr( Abc_Nam_t * p, int i ) { return Abc_NamHandleToStr(p, Abc_NamIntToHandle(p,i)); } static inline int Abc_NamIntToNext( Abc_Nam_t * p, int i ) { return Vec_IntEntry(&p->vInt2Next, i); } static inline int * Abc_NamIntToNextP( Abc_Nam_t * p, int i ) { return Vec_IntEntryP(&p->vInt2Next, i); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Nam_t * Abc_NamStart( int nObjs, int nAveSize ) { Abc_Nam_t * p; if ( nObjs == 0 ) nObjs = 16; p = ABC_CALLOC( Abc_Nam_t, 1 ); p->nStore = ((nObjs * (nAveSize + 1) + 16) / 4) * 4; p->pStore = ABC_ALLOC( char, p->nStore ); p->nBins = Abc_PrimeCudd( nObjs ); p->pBins = ABC_CALLOC( int, p->nBins ); // 0th object is unused Vec_IntGrow( &p->vInt2Handle, nObjs ); Vec_IntPush( &p->vInt2Handle, -1 ); Vec_IntGrow( &p->vInt2Next, nObjs ); Vec_IntPush( &p->vInt2Next, -1 ); p->iHandle = 4; memset( p->pStore, 0, 4 ); //Abc_Print( 1, "Starting nam with %d bins.\n", p->nBins ); // start reference counting p->nRefs = 1; return p; } /**Function************************************************************* Synopsis [Deletes manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NamStop( Abc_Nam_t * p ) { //Abc_Print( 1, "Starting nam with %d bins.\n", p->nBins ); Vec_StrErase( &p->vBuffer ); Vec_IntErase( &p->vInt2Handle ); Vec_IntErase( &p->vInt2Next ); ABC_FREE( p->pStore ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NamPrint( Abc_Nam_t * p ) { int h, i; Vec_IntForEachEntryStart( &p->vInt2Handle, h, i, 1 ) Abc_Print( 1, "%d=\n%s\n", i, Abc_NamHandleToStr(p, h) ); } /**Function************************************************************* Synopsis [References the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Nam_t * Abc_NamRef( Abc_Nam_t * p ) { p->nRefs++; return p; } /**Function************************************************************* Synopsis [Dereferences the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NamDeref( Abc_Nam_t * p ) { if ( p == NULL ) return; if ( --p->nRefs == 0 ) Abc_NamStop( p ); } /**Function************************************************************* Synopsis [Returns the number of used entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NamObjNumMax( Abc_Nam_t * p ) { return Vec_IntSize(&p->vInt2Handle); } /**Function************************************************************* Synopsis [Reports memory usage of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NamMemUsed( Abc_Nam_t * p ) { if ( p == NULL ) return 0; return sizeof(Abc_Nam_t) + p->iHandle + sizeof(int) * p->nBins + sizeof(int) * (p->vInt2Handle.nSize + p->vInt2Next.nSize); } /**Function************************************************************* Synopsis [Reports memory usage of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NamMemAlloc( Abc_Nam_t * p ) { if ( p == NULL ) return 0; return sizeof(Abc_Nam_t) + p->nStore + sizeof(int) * p->nBins + sizeof(int) * (p->vInt2Handle.nCap + p->vInt2Next.nCap); } /**Function************************************************************* Synopsis [Computes hash value of the C-string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NamStrHash( const char * pStr, const char * pLim, 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 i, uHash; if ( pLim ) { for ( uHash = 0, i = 0; pStr+i < pLim; i++ ) if ( i & 1 ) uHash *= pStr[i] * s_FPrimes[i & 0x7F]; else uHash ^= pStr[i] * s_FPrimes[i & 0x7F]; } else { for ( uHash = 0, i = 0; pStr[i]; i++ ) if ( i & 1 ) uHash *= pStr[i] * s_FPrimes[i & 0x7F]; else uHash ^= pStr[i] * s_FPrimes[i & 0x7F]; } return uHash % nTableSize; } /**Function************************************************************* Synopsis [Returns place where this string is, or should be.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_NamStrcmp( char * pStr, char * pLim, char * pThis ) { if ( pLim ) { while ( pStr < pLim ) if ( *pStr++ != *pThis++ ) return 1; return *pThis != '\0'; } else { while ( *pStr ) if ( *pStr++ != *pThis++ ) return 1; return *pThis != '\0'; } } static inline int * Abc_NamStrHashFind( Abc_Nam_t * p, const char * pStr, const char * pLim ) { char * pThis; int * pPlace = (int *)(p->pBins + Abc_NamStrHash( pStr, pLim, p->nBins )); assert( *pStr ); for ( pThis = (*pPlace)? Abc_NamIntToStr(p, *pPlace) : NULL; pThis; pPlace = Abc_NamIntToNextP(p, *pPlace), pThis = (*pPlace)? Abc_NamIntToStr(p, *pPlace) : NULL ) if ( !Abc_NamStrcmp( (char *)pStr, (char *)pLim, pThis ) ) break; return pPlace; } /**Function************************************************************* Synopsis [Resizes the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NamStrHashResize( Abc_Nam_t * p ) { Vec_Int_t vInt2HandleOld; char * pThis; int * piPlace, * pBinsOld, iHandleOld, i;//, clk = Abc_Clock(); assert( p->pBins != NULL ); // Abc_Print( 1, "Resizing names manager hash table from %6d to %6d. ", p->nBins, Abc_PrimeCudd( 3 * p->nBins ) ); // replace the table pBinsOld = p->pBins; p->nBins = Abc_PrimeCudd( 3 * p->nBins ); p->pBins = ABC_CALLOC( int, p->nBins ); // replace the handles array vInt2HandleOld = p->vInt2Handle; Vec_IntZero( &p->vInt2Handle ); Vec_IntGrow( &p->vInt2Handle, 2 * Vec_IntSize(&vInt2HandleOld) ); Vec_IntPush( &p->vInt2Handle, -1 ); Vec_IntClear( &p->vInt2Next ); Vec_IntPush( &p->vInt2Next, -1 ); // rehash the entries from the old table Vec_IntForEachEntryStart( &vInt2HandleOld, iHandleOld, i, 1 ) { pThis = Abc_NamHandleToStr( p, iHandleOld ); piPlace = Abc_NamStrHashFind( p, pThis, NULL ); assert( *piPlace == 0 ); *piPlace = Vec_IntSize( &p->vInt2Handle ); assert( Vec_IntSize( &p->vInt2Handle ) == i ); Vec_IntPush( &p->vInt2Handle, iHandleOld ); Vec_IntPush( &p->vInt2Next, 0 ); } Vec_IntErase( &vInt2HandleOld ); ABC_FREE( pBinsOld ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Returns the index of the string in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NamStrFind( Abc_Nam_t * p, char * pStr ) { return *Abc_NamStrHashFind( p, pStr, NULL ); } int Abc_NamStrFindLim( Abc_Nam_t * p, char * pStr, char * pLim ) { return *Abc_NamStrHashFind( p, pStr, pLim ); } /**Function************************************************************* Synopsis [Finds or adds the given name to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NamStrFindOrAdd( Abc_Nam_t * p, char * pStr, int * pfFound ) { int i, iHandleNew; int *piPlace; if ( !(pStr[0] != '\\' || pStr[strlen(pStr)-1] == ' ') ) { for ( i = strlen(pStr) - 1; i >= 0; i-- ) if ( *pStr == ' ' ) break; assert( i < (int)strlen(pStr) ); } piPlace = Abc_NamStrHashFind( p, pStr, NULL ); if ( *piPlace ) { if ( pfFound ) *pfFound = 1; return *piPlace; } if ( pfFound ) *pfFound = 0; iHandleNew = p->iHandle + strlen(pStr) + 1; while ( p->nStore < iHandleNew ) { p->nStore *= 3; p->nStore /= 2; p->pStore = ABC_REALLOC( char, p->pStore, p->nStore ); } assert( p->nStore >= iHandleNew ); // create new handle *piPlace = Vec_IntSize( &p->vInt2Handle ); strcpy( Abc_NamHandleToStr( p, p->iHandle ), pStr ); Vec_IntPush( &p->vInt2Handle, p->iHandle ); Vec_IntPush( &p->vInt2Next, 0 ); p->iHandle = iHandleNew; // extend the hash table if ( Vec_IntSize(&p->vInt2Handle) > 2 * p->nBins ) Abc_NamStrHashResize( p ); return Vec_IntSize(&p->vInt2Handle) - 1; } int Abc_NamStrFindOrAddLim( Abc_Nam_t * p, char * pStr, char * pLim, int * pfFound ) { int iHandleNew; int *piPlace; char * pStore; assert( pStr < pLim ); piPlace = Abc_NamStrHashFind( p, pStr, pLim ); if ( *piPlace ) { if ( pfFound ) *pfFound = 1; return *piPlace; } if ( pfFound ) *pfFound = 0; iHandleNew = p->iHandle + (pLim - pStr) + 1; while ( p->nStore < iHandleNew ) { p->nStore *= 3; p->nStore /= 2; p->pStore = ABC_REALLOC( char, p->pStore, p->nStore ); } assert( p->nStore >= iHandleNew ); // create new handle *piPlace = Vec_IntSize( &p->vInt2Handle ); pStore = Abc_NamHandleToStr( p, p->iHandle ); strncpy( pStore, pStr, pLim - pStr ); pStore[pLim - pStr] = 0; Vec_IntPush( &p->vInt2Handle, p->iHandle ); Vec_IntPush( &p->vInt2Next, 0 ); p->iHandle = iHandleNew; // extend the hash table if ( Vec_IntSize(&p->vInt2Handle) > 2 * p->nBins ) Abc_NamStrHashResize( p ); return Vec_IntSize(&p->vInt2Handle) - 1; } int Abc_NamStrFindOrAddF( Abc_Nam_t * p, const char * format, ... ) { int nAdded, nSize = 1000; va_list args; va_start( args, format ); Vec_StrGrow( &p->vBuffer, Vec_StrSize(&p->vBuffer) + nSize ); nAdded = vsnprintf( Vec_StrLimit(&p->vBuffer), nSize, format, args ); if ( nAdded > nSize ) { Vec_StrGrow( &p->vBuffer, Vec_StrSize(&p->vBuffer) + nAdded + nSize ); nSize = vsnprintf( Vec_StrLimit(&p->vBuffer), nAdded, format, args ); assert( nSize == nAdded ); } va_end( args ); return Abc_NamStrFindOrAddLim( p, Vec_StrLimit(&p->vBuffer), Vec_StrLimit(&p->vBuffer) + nAdded, NULL ); } /**Function************************************************************* Synopsis [Returns name from name ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_NamStr( Abc_Nam_t * p, int NameId ) { return NameId > 0 ? Abc_NamIntToStr(p, NameId) : NULL; } /**Function************************************************************* Synopsis [Returns internal buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Abc_NamBuffer( Abc_Nam_t * p ) { Vec_StrClear(&p->vBuffer); return &p->vBuffer; } /**Function************************************************************* Synopsis [For each ID of the first manager, gives ID of the second one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NamComputeIdMap( Abc_Nam_t * p1, Abc_Nam_t * p2 ) { Vec_Int_t * vMap; char * pThis; int * piPlace, iHandle1, i; if ( p1 == p2 ) return Vec_IntStartNatural( Abc_NamObjNumMax(p1) ); vMap = Vec_IntStart( Abc_NamObjNumMax(p1) ); Vec_IntForEachEntryStart( &p1->vInt2Handle, iHandle1, i, 1 ) { pThis = Abc_NamHandleToStr( p1, iHandle1 ); piPlace = Abc_NamStrHashFind( p2, pThis, NULL ); Vec_IntWriteEntry( vMap, i, *piPlace ); // Abc_Print( 1, "%d->%d ", i, *piPlace ); } return vMap; } /**Function************************************************************* Synopsis [Returns the number of common names in the array.] Description [The array contains name IDs in the first manager. The procedure returns the number of entries that correspond to names in the first manager that appear in the second manager.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NamReportCommon( Vec_Int_t * vNameIds1, Abc_Nam_t * p1, Abc_Nam_t * p2 ) { int i, Entry, Counter = 0; Vec_IntForEachEntry( vNameIds1, Entry, i ) { assert( Entry > 0 && Entry < Abc_NamObjNumMax(p1) ); Counter += (Abc_NamStrFind(p2, Abc_NamStr(p1, Entry)) > 0); // if ( Abc_NamStrFind(p2, Abc_NamStr(p1, Entry)) == 0 ) // Abc_Print( 1, "unique name <%s>\n", Abc_NamStr(p1, Entry) ); } return Counter; } /**Function************************************************************* Synopsis [Returns the name that appears in p1 does not appear in p2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_NamReportUnique( Vec_Int_t * vNameIds1, Abc_Nam_t * p1, Abc_Nam_t * p2 ) { int i, Entry; Vec_IntForEachEntry( vNameIds1, Entry, i ) { assert( Entry > 0 && Entry < Abc_NamObjNumMax(p1) ); if ( Abc_NamStrFind(p2, Abc_NamStr(p1, Entry)) == 0 ) return Abc_NamStr(p1, Entry); } return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilNam.h000066400000000000000000000066721300674244400235410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilNam.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Memory recycling utilities.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: utilNam.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__util__utilNam_h #define ABC__misc__util__utilNam_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Abc_Nam_t_ Abc_Nam_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Abc_NamManForEachObj( p, pStr, i ) \ for ( i = 1; (i < Abc_NamObjNumMax(p)) && ((pStr) = Abc_NamStr(p, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== utilNam.c ===============================================================*/ extern Abc_Nam_t * Abc_NamStart( int nObjs, int nAveSize ); extern void Abc_NamStop( Abc_Nam_t * p ); extern void Abc_NamPrint( Abc_Nam_t * p ); extern Abc_Nam_t * Abc_NamRef( Abc_Nam_t * p ); extern void Abc_NamDeref( Abc_Nam_t * p ); extern int Abc_NamObjNumMax( Abc_Nam_t * p ); extern int Abc_NamMemUsed( Abc_Nam_t * p ); extern int Abc_NamMemAlloc( Abc_Nam_t * p ); extern int Abc_NamStrFind( Abc_Nam_t * p, char * pStr ); extern int Abc_NamStrFindLim( Abc_Nam_t * p, char * pStr, char * pLim ); extern int Abc_NamStrFindOrAdd( Abc_Nam_t * p, char * pStr, int * pfFound ); extern int Abc_NamStrFindOrAddLim( Abc_Nam_t * p, char * pStr, char * pLim, int * pfFound ); extern int Abc_NamStrFindOrAddF( Abc_Nam_t * p, const char * format, ... ); extern char * Abc_NamStr( Abc_Nam_t * p, int id ); extern Vec_Str_t * Abc_NamBuffer( Abc_Nam_t * p ); extern Vec_Int_t * Abc_NamComputeIdMap( Abc_Nam_t * p1, Abc_Nam_t * p2 ); extern int Abc_NamReportCommon( Vec_Int_t * vNameIds1, Abc_Nam_t * p1, Abc_Nam_t * p2 ); extern char * Abc_NamReportUnique( Vec_Int_t * vNameIds1, Abc_Nam_t * p1, Abc_Nam_t * p2 ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilSignal.c000066400000000000000000000033271300674244400242300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilSignal.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [] Synopsis [] Author [Baruch Sterin] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2011.] Revision [$Id: utilSignal.c,v 1.00 2011/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include "abc_global.h" #include "utilSignal.h" #ifdef _MSC_VER #define unlink _unlink #else #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// int Util_SignalSystem(const char* cmd) { return system(cmd); } int tmpFile(const char* prefix, const char* suffix, char** out_name); int Util_SignalTmpFile(const char* prefix, const char* suffix, char** out_name) { return tmpFile(prefix, suffix, out_name); } void Util_SignalTmpFileRemove(const char* fname, int fLeave) { if (! fLeave) { unlink(fname); } } ABC_NAMESPACE_IMPL_END //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilSignal.h000066400000000000000000000043531300674244400242350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilSignal.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Signal handling utilities.] Synopsis [Signal handling utilities.] Author [Baruch Sterin] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2011.] Revision [$Id: utilSignal.h,v 1.00 2011/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__util__utilSignal_h #define ABC__misc__util__utilSignal_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== utilSignal.c ==========================================================*/ extern int Util_SignalTmpFile(const char* prefix, const char* suffix, char** out_name); extern void Util_SignalTmpFileRemove(const char* fname, int fLeave); extern int Util_SignalSystem(const char* cmd); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilSort.c000066400000000000000000000533171300674244400237460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilSort.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Merge sort with user-specified cost.] Synopsis [Merge sort with user-specified cost.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Feburary 13, 2011.] Revision [$Id: utilSort.c,v 1.00 2011/02/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "abc_global.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Merging two lists of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SortMerge( int * p1Beg, int * p1End, int * p2Beg, int * p2End, int * pOut ) { int nEntries = (p1End - p1Beg) + (p2End - p2Beg); int * pOutBeg = pOut; while ( p1Beg < p1End && p2Beg < p2End ) { if ( *p1Beg == *p2Beg ) *pOut++ = *p1Beg++, *pOut++ = *p2Beg++; else if ( *p1Beg < *p2Beg ) *pOut++ = *p1Beg++; else // if ( *p1Beg > *p2Beg ) *pOut++ = *p2Beg++; } while ( p1Beg < p1End ) *pOut++ = *p1Beg++; while ( p2Beg < p2End ) *pOut++ = *p2Beg++; assert( pOut - pOutBeg == nEntries ); } /**Function************************************************************* Synopsis [Recursive sorting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_Sort_rec( int * pInBeg, int * pInEnd, int * pOutBeg ) { int nSize = pInEnd - pInBeg; assert( nSize > 0 ); if ( nSize == 1 ) return; if ( nSize == 2 ) { if ( pInBeg[0] > pInBeg[1] ) { pInBeg[0] ^= pInBeg[1]; pInBeg[1] ^= pInBeg[0]; pInBeg[0] ^= pInBeg[1]; } } else if ( nSize < 8 ) { int temp, i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pInBeg[j] < pInBeg[best_i] ) best_i = j; temp = pInBeg[i]; pInBeg[i] = pInBeg[best_i]; pInBeg[best_i] = temp; } } else { Abc_Sort_rec( pInBeg, pInBeg + nSize/2, pOutBeg ); Abc_Sort_rec( pInBeg + nSize/2, pInEnd, pOutBeg + nSize/2 ); Abc_SortMerge( pInBeg, pInBeg + nSize/2, pInBeg + nSize/2, pInEnd, pOutBeg ); memcpy( pInBeg, pOutBeg, sizeof(int) * nSize ); } } /**Function************************************************************* Synopsis [Returns the sorted array of integers.] Description [This procedure is about 10% faster than qsort().] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MergeSort( int * pInput, int nSize ) { int * pOutput; if ( nSize < 2 ) return; pOutput = (int *) malloc( sizeof(int) * nSize ); Abc_Sort_rec( pInput, pInput + nSize, pOutput ); free( pOutput ); } /**Function************************************************************* Synopsis [Merging two lists of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MergeSortCostMerge( int * p1Beg, int * p1End, int * p2Beg, int * p2End, int * pOut ) { int nEntries = (p1End - p1Beg) + (p2End - p2Beg); int * pOutBeg = pOut; while ( p1Beg < p1End && p2Beg < p2End ) { if ( p1Beg[1] == p2Beg[1] ) *pOut++ = *p1Beg++, *pOut++ = *p1Beg++, *pOut++ = *p2Beg++, *pOut++ = *p2Beg++; else if ( p1Beg[1] < p2Beg[1] ) *pOut++ = *p1Beg++, *pOut++ = *p1Beg++; else // if ( p1Beg[1] > p2Beg[1] ) *pOut++ = *p2Beg++, *pOut++ = *p2Beg++; } while ( p1Beg < p1End ) *pOut++ = *p1Beg++, *pOut++ = *p1Beg++; while ( p2Beg < p2End ) *pOut++ = *p2Beg++, *pOut++ = *p2Beg++; assert( pOut - pOutBeg == nEntries ); } /**Function************************************************************* Synopsis [Recursive sorting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MergeSortCost_rec( int * pInBeg, int * pInEnd, int * pOutBeg ) { int nSize = (pInEnd - pInBeg)/2; assert( nSize > 0 ); if ( nSize == 1 ) return; if ( nSize == 2 ) { if ( pInBeg[1] > pInBeg[3] ) { pInBeg[1] ^= pInBeg[3]; pInBeg[3] ^= pInBeg[1]; pInBeg[1] ^= pInBeg[3]; pInBeg[0] ^= pInBeg[2]; pInBeg[2] ^= pInBeg[0]; pInBeg[0] ^= pInBeg[2]; } } else if ( nSize < 8 ) { int temp, i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pInBeg[2*j+1] < pInBeg[2*best_i+1] ) best_i = j; temp = pInBeg[2*i]; pInBeg[2*i] = pInBeg[2*best_i]; pInBeg[2*best_i] = temp; temp = pInBeg[2*i+1]; pInBeg[2*i+1] = pInBeg[2*best_i+1]; pInBeg[2*best_i+1] = temp; } } else { Abc_MergeSortCost_rec( pInBeg, pInBeg + 2*(nSize/2), pOutBeg ); Abc_MergeSortCost_rec( pInBeg + 2*(nSize/2), pInEnd, pOutBeg + 2*(nSize/2) ); Abc_MergeSortCostMerge( pInBeg, pInBeg + 2*(nSize/2), pInBeg + 2*(nSize/2), pInEnd, pOutBeg ); memcpy( pInBeg, pOutBeg, sizeof(int) * 2 * nSize ); } } /**Function************************************************************* Synopsis [Sorting procedure.] Description [Returns permutation for the non-decreasing order of costs.] SideEffects [] SeeAlso [] ***********************************************************************/ int * Abc_MergeSortCost( int * pCosts, int nSize ) { int i, * pResult, * pInput, * pOutput; pResult = (int *) calloc( sizeof(int), nSize ); if ( nSize < 2 ) return pResult; pInput = (int *) malloc( sizeof(int) * 2 * nSize ); pOutput = (int *) malloc( sizeof(int) * 2 * nSize ); for ( i = 0; i < nSize; i++ ) pInput[2*i] = i, pInput[2*i+1] = pCosts[i]; Abc_MergeSortCost_rec( pInput, pInput + 2*nSize, pOutput ); for ( i = 0; i < nSize; i++ ) pResult[i] = pInput[2*i]; free( pOutput ); free( pInput ); return pResult; } // this implementation uses 3x less memory but is 30% slower due to cache misses #if 0 /**Function************************************************************* Synopsis [Merging two lists of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MergeSortCostMerge( int * p1Beg, int * p1End, int * p2Beg, int * p2End, int * pOut, int * pCost ) { int nEntries = (p1End - p1Beg) + (p2End - p2Beg); int * pOutBeg = pOut; while ( p1Beg < p1End && p2Beg < p2End ) { if ( pCost[*p1Beg] == pCost[*p2Beg] ) *pOut++ = *p1Beg++, *pOut++ = *p2Beg++; else if ( pCost[*p1Beg] < pCost[*p2Beg] ) *pOut++ = *p1Beg++; else // if ( pCost[*p1Beg] > pCost[*p2Beg] ) *pOut++ = *p2Beg++; } while ( p1Beg < p1End ) *pOut++ = *p1Beg++; while ( p2Beg < p2End ) *pOut++ = *p2Beg++; assert( pOut - pOutBeg == nEntries ); } /**Function************************************************************* Synopsis [Recursive sorting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MergeSortCost_rec( int * pInBeg, int * pInEnd, int * pOutBeg, int * pCost ) { int nSize = pInEnd - pInBeg; assert( nSize > 0 ); if ( nSize == 1 ) return; if ( nSize == 2 ) { if ( pCost[pInBeg[0]] > pCost[pInBeg[1]] ) { pInBeg[0] ^= pInBeg[1]; pInBeg[1] ^= pInBeg[0]; pInBeg[0] ^= pInBeg[1]; } } else if ( nSize < 8 ) { int temp, i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pCost[pInBeg[j]] < pCost[pInBeg[best_i]] ) best_i = j; temp = pInBeg[i]; pInBeg[i] = pInBeg[best_i]; pInBeg[best_i] = temp; } } else { Abc_MergeSortCost_rec( pInBeg, pInBeg + nSize/2, pOutBeg, pCost ); Abc_MergeSortCost_rec( pInBeg + nSize/2, pInEnd, pOutBeg + nSize/2, pCost ); Abc_MergeSortCostMerge( pInBeg, pInBeg + nSize/2, pInBeg + nSize/2, pInEnd, pOutBeg, pCost ); memcpy( pInBeg, pOutBeg, sizeof(int) * nSize ); } } /**Function************************************************************* Synopsis [Sorting procedure.] Description [Returns permutation for the non-decreasing order of costs.] SideEffects [] SeeAlso [] ***********************************************************************/ int * Abc_MergeSortCost( int * pCosts, int nSize ) { int i, * pInput, * pOutput; pInput = (int *) malloc( sizeof(int) * nSize ); for ( i = 0; i < nSize; i++ ) pInput[i] = i; if ( nSize < 2 ) return pInput; pOutput = (int *) malloc( sizeof(int) * nSize ); Abc_MergeSortCost_rec( pInput, pInput + nSize, pOutput, pCosts ); free( pOutput ); return pInput; } #endif /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SortNumCompare( int * pNum1, int * pNum2 ) { return *pNum1 - *pNum2; } /**Function************************************************************* Synopsis [Testing the sorting procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SortTest() { int fUseNew = 0; int i, nSize = 50000000; int * pArray = (int *)malloc( sizeof(int) * nSize ); int * pPerm; abctime clk; // generate numbers srand( 1000 ); for ( i = 0; i < nSize; i++ ) pArray[i] = rand(); // try sorting if ( fUseNew ) { int fUseCost = 1; if ( fUseCost ) { clk = Abc_Clock(); pPerm = Abc_MergeSortCost( pArray, nSize ); Abc_PrintTime( 1, "New sort", Abc_Clock() - clk ); // check for ( i = 1; i < nSize; i++ ) assert( pArray[pPerm[i-1]] <= pArray[pPerm[i]] ); free( pPerm ); } else { clk = Abc_Clock(); Abc_MergeSort( pArray, nSize ); Abc_PrintTime( 1, "New sort", Abc_Clock() - clk ); // check for ( i = 1; i < nSize; i++ ) assert( pArray[i-1] <= pArray[i] ); } } else { clk = Abc_Clock(); qsort( (void *)pArray, nSize, sizeof(int), (int (*)(const void *, const void *)) Abc_SortNumCompare ); Abc_PrintTime( 1, "Old sort", Abc_Clock() - clk ); // check for ( i = 1; i < nSize; i++ ) assert( pArray[i-1] <= pArray[i] ); } free( pArray ); } /**Function************************************************************* Synopsis [QuickSort algorithm as implemented by qsort().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_QuickSort1CompareInc( word * p1, word * p2 ) { if ( (unsigned)(*p1) < (unsigned)(*p2) ) return -1; if ( (unsigned)(*p1) > (unsigned)(*p2) ) return 1; return 0; } int Abc_QuickSort1CompareDec( word * p1, word * p2 ) { if ( (unsigned)(*p1) > (unsigned)(*p2) ) return -1; if ( (unsigned)(*p1) < (unsigned)(*p2) ) return 1; return 0; } void Abc_QuickSort1( word * pData, int nSize, int fDecrease ) { int i, fVerify = 0; if ( fDecrease ) { qsort( (void *)pData, nSize, sizeof(word), (int (*)(const void *, const void *))Abc_QuickSort1CompareDec ); if ( fVerify ) for ( i = 1; i < nSize; i++ ) assert( (unsigned)pData[i-1] >= (unsigned)pData[i] ); } else { qsort( (void *)pData, nSize, sizeof(word), (int (*)(const void *, const void *))Abc_QuickSort1CompareInc ); if ( fVerify ) for ( i = 1; i < nSize; i++ ) assert( (unsigned)pData[i-1] <= (unsigned)pData[i] ); } } /**Function************************************************************* Synopsis [QuickSort algorithm based on 2/3-way partitioning.] Description [This code is based on the online presentation "QuickSort is Optimal" by Robert Sedgewick and Jon Bentley. http://www.sorting-algorithms.com/static/QuicksortIsOptimal.pdf The first 32-bits of the input data contain values to be compared. The last 32-bits contain the user's data. When sorting is finished, the 64-bit words are ordered in the increasing order of their value ] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_SelectSortInc( word * pData, 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 ( (unsigned)pData[j] < (unsigned)pData[best_i] ) best_i = j; ABC_SWAP( word, pData[i], pData[best_i] ); } } static inline void Abc_SelectSortDec( word * pData, 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 ( (unsigned)pData[j] > (unsigned)pData[best_i] ) best_i = j; ABC_SWAP( word, pData[i], pData[best_i] ); } } void Abc_QuickSort2Inc_rec( word * pData, int l, int r ) { word v = pData[r]; int i = l-1, j = r; if ( l >= r ) return; assert( l < r ); if ( r - l < 10 ) { Abc_SelectSortInc( pData + l, r - l + 1 ); return; } while ( 1 ) { while ( (unsigned)pData[++i] < (unsigned)v ); while ( (unsigned)v < (unsigned)pData[--j] ) if ( j == l ) break; if ( i >= j ) break; ABC_SWAP( word, pData[i], pData[j] ); } ABC_SWAP( word, pData[i], pData[r] ); Abc_QuickSort2Inc_rec( pData, l, i-1 ); Abc_QuickSort2Inc_rec( pData, i+1, r ); } void Abc_QuickSort2Dec_rec( word * pData, int l, int r ) { word v = pData[r]; int i = l-1, j = r; if ( l >= r ) return; assert( l < r ); if ( r - l < 10 ) { Abc_SelectSortDec( pData + l, r - l + 1 ); return; } while ( 1 ) { while ( (unsigned)pData[++i] > (unsigned)v ); while ( (unsigned)v > (unsigned)pData[--j] ) if ( j == l ) break; if ( i >= j ) break; ABC_SWAP( word, pData[i], pData[j] ); } ABC_SWAP( word, pData[i], pData[r] ); Abc_QuickSort2Dec_rec( pData, l, i-1 ); Abc_QuickSort2Dec_rec( pData, i+1, r ); } void Abc_QuickSort3Inc_rec( word * pData, int l, int r ) { word v = pData[r]; int k, i = l-1, j = r, p = l-1, q = r; if ( l >= r ) return; assert( l < r ); if ( r - l < 10 ) { Abc_SelectSortInc( pData + l, r - l + 1 ); return; } while ( 1 ) { while ( (unsigned)pData[++i] < (unsigned)v ); while ( (unsigned)v < (unsigned)pData[--j] ) if ( j == l ) break; if ( i >= j ) break; ABC_SWAP( word, pData[i], pData[j] ); if ( (unsigned)pData[i] == (unsigned)v ) { p++; ABC_SWAP( word, pData[p], pData[i] ); } if ( (unsigned)v == (unsigned)pData[j] ) { q--; ABC_SWAP( word, pData[j], pData[q] ); } } ABC_SWAP( word, pData[i], pData[r] ); j = i-1; i = i+1; for ( k = l; k < p; k++, j-- ) ABC_SWAP( word, pData[k], pData[j] ); for ( k = r-1; k > q; k--, i++ ) ABC_SWAP( word, pData[i], pData[k] ); Abc_QuickSort3Inc_rec( pData, l, j ); Abc_QuickSort3Inc_rec( pData, i, r ); } void Abc_QuickSort3Dec_rec( word * pData, int l, int r ) { word v = pData[r]; int k, i = l-1, j = r, p = l-1, q = r; if ( l >= r ) return; assert( l < r ); if ( r - l < 10 ) { Abc_SelectSortDec( pData + l, r - l + 1 ); return; } while ( 1 ) { while ( (unsigned)pData[++i] > (unsigned)v ); while ( (unsigned)v > (unsigned)pData[--j] ) if ( j == l ) break; if ( i >= j ) break; ABC_SWAP( word, pData[i], pData[j] ); if ( (unsigned)pData[i] == (unsigned)v ) { p++; ABC_SWAP( word, pData[p], pData[i] ); } if ( (unsigned)v == (unsigned)pData[j] ) { q--; ABC_SWAP( word, pData[j], pData[q] ); } } ABC_SWAP( word, pData[i], pData[r] ); j = i-1; i = i+1; for ( k = l; k < p; k++, j-- ) ABC_SWAP( word, pData[k], pData[j] ); for ( k = r-1; k > q; k--, i++ ) ABC_SWAP( word, pData[i], pData[k] ); Abc_QuickSort3Dec_rec( pData, l, j ); Abc_QuickSort3Dec_rec( pData, i, r ); } void Abc_QuickSort2( word * pData, int nSize, int fDecrease ) { int i, fVerify = 0; if ( fDecrease ) { Abc_QuickSort2Dec_rec( pData, 0, nSize - 1 ); if ( fVerify ) for ( i = 1; i < nSize; i++ ) assert( (unsigned)pData[i-1] >= (unsigned)pData[i] ); } else { Abc_QuickSort2Inc_rec( pData, 0, nSize - 1 ); if ( fVerify ) for ( i = 1; i < nSize; i++ ) assert( (unsigned)pData[i-1] <= (unsigned)pData[i] ); } } void Abc_QuickSort3( word * pData, int nSize, int fDecrease ) { int i, fVerify = 1; if ( fDecrease ) { Abc_QuickSort2Dec_rec( pData, 0, nSize - 1 ); if ( fVerify ) for ( i = 1; i < nSize; i++ ) assert( (unsigned)pData[i-1] >= (unsigned)pData[i] ); } else { Abc_QuickSort2Inc_rec( pData, 0, nSize - 1 ); if ( fVerify ) for ( i = 1; i < nSize; i++ ) assert( (unsigned)pData[i-1] <= (unsigned)pData[i] ); } } /**Function************************************************************* Synopsis [Wrapper around QuickSort to sort entries based on cost.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_QuickSortCostData( int * pCosts, int nSize, int fDecrease, word * pData, int * pResult ) { int i; for ( i = 0; i < nSize; i++ ) pData[i] = ((word)i << 32) | pCosts[i]; Abc_QuickSort3( pData, nSize, fDecrease ); for ( i = 0; i < nSize; i++ ) pResult[i] = (int)(pData[i] >> 32); } int * Abc_QuickSortCost( int * pCosts, int nSize, int fDecrease ) { word * pData = ABC_ALLOC( word, nSize ); int * pResult = ABC_ALLOC( int, nSize ); Abc_QuickSortCostData( pCosts, nSize, fDecrease, pData, pResult ); ABC_FREE( pData ); return pResult; } // extern void Abc_QuickSortTest(); // Abc_QuickSortTest(); /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_QuickSortTest() { int nSize = 1000000; int fVerbose = 0; word * pData1, * pData2; int i; abctime clk = Abc_Clock(); // generate numbers pData1 = ABC_ALLOC( word, nSize ); pData2 = ABC_ALLOC( word, nSize ); srand( 1111 ); for ( i = 0; i < nSize; i++ ) pData2[i] = pData1[i] = ((word)i << 32) | rand(); Abc_PrintTime( 1, "Prepare ", Abc_Clock() - clk ); // perform sorting clk = Abc_Clock(); Abc_QuickSort3( pData1, nSize, 1 ); Abc_PrintTime( 1, "Sort new", Abc_Clock() - clk ); // print the result if ( fVerbose ) { for ( i = 0; i < nSize; i++ ) printf( "(%d,%d) ", (int)(pData1[i] >> 32), (int)pData1[i] ); printf( "\n" ); } // create new numbers clk = Abc_Clock(); Abc_QuickSort1( pData2, nSize, 1 ); Abc_PrintTime( 1, "Sort old", Abc_Clock() - clk ); // print the result if ( fVerbose ) { for ( i = 0; i < nSize; i++ ) printf( "(%d,%d) ", (int)(pData2[i] >> 32), (int)pData2[i] ); printf( "\n" ); } ABC_FREE( pData1 ); ABC_FREE( pData2 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/utilTruth.h000066400000000000000000002641211300674244400241270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [utilTruth.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Truth table manipulation.] Synopsis [Truth table manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 28, 2012.] Revision [$Id: utilTruth.h,v 1.00 2012/10/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__util__utilTruth_h #define ABC__misc__util__utilTruth_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// static word s_Truths6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; static word s_Truths6Neg[6] = { ABC_CONST(0x5555555555555555), ABC_CONST(0x3333333333333333), ABC_CONST(0x0F0F0F0F0F0F0F0F), ABC_CONST(0x00FF00FF00FF00FF), ABC_CONST(0x0000FFFF0000FFFF), ABC_CONST(0x00000000FFFFFFFF) }; static word s_TruthXors[6] = { ABC_CONST(0x0000000000000000), ABC_CONST(0x6666666666666666), ABC_CONST(0x6969696969696969), ABC_CONST(0x6996699669966996), ABC_CONST(0x6996966969969669), ABC_CONST(0x6996966996696996) }; static word s_PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; static word s_PPMasks[5][6][3] = { { { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 0 0 { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, // 0 1 { ABC_CONST(0xA5A5A5A5A5A5A5A5), ABC_CONST(0x0A0A0A0A0A0A0A0A), ABC_CONST(0x5050505050505050) }, // 0 2 { ABC_CONST(0xAA55AA55AA55AA55), ABC_CONST(0x00AA00AA00AA00AA), ABC_CONST(0x5500550055005500) }, // 0 3 { ABC_CONST(0xAAAA5555AAAA5555), ABC_CONST(0x0000AAAA0000AAAA), ABC_CONST(0x5555000055550000) }, // 0 4 { ABC_CONST(0xAAAAAAAA55555555), ABC_CONST(0x00000000AAAAAAAA), ABC_CONST(0x5555555500000000) } // 0 5 }, { { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 1 0 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 1 1 { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, // 1 2 { ABC_CONST(0xCC33CC33CC33CC33), ABC_CONST(0x00CC00CC00CC00CC), ABC_CONST(0x3300330033003300) }, // 1 3 { ABC_CONST(0xCCCC3333CCCC3333), ABC_CONST(0x0000CCCC0000CCCC), ABC_CONST(0x3333000033330000) }, // 1 4 { ABC_CONST(0xCCCCCCCC33333333), ABC_CONST(0x00000000CCCCCCCC), ABC_CONST(0x3333333300000000) } // 1 5 }, { { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 2 0 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 2 1 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 2 2 { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, // 2 3 { ABC_CONST(0xF0F00F0FF0F00F0F), ABC_CONST(0x0000F0F00000F0F0), ABC_CONST(0x0F0F00000F0F0000) }, // 2 4 { ABC_CONST(0xF0F0F0F00F0F0F0F), ABC_CONST(0x00000000F0F0F0F0), ABC_CONST(0x0F0F0F0F00000000) } // 2 5 }, { { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 3 0 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 3 1 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 3 2 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 3 3 { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, // 3 4 { ABC_CONST(0xFF00FF0000FF00FF), ABC_CONST(0x00000000FF00FF00), ABC_CONST(0x00FF00FF00000000) } // 3 5 }, { { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 0 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 1 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 2 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 3 { ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000), ABC_CONST(0x0000000000000000) }, // 4 4 { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } // 4 5 } }; // the bit count for the first 256 integer numbers static int Abc_TtBitCount8[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; static inline int Abc_TtBitCount16( int i ) { return Abc_TtBitCount8[i & 0xFF] + Abc_TtBitCount8[i >> 8]; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // read/write/flip i-th bit of a bit string table: static inline int Abc_TtGetBit( word * p, int i ) { return (int)(p[i>>6] >> (i & 63)) & 1; } static inline void Abc_TtSetBit( word * p, int i ) { p[i>>6] |= (((word)1)<<(i & 63)); } static inline void Abc_TtXorBit( word * p, int i ) { p[i>>6] ^= (((word)1)<<(i & 63)); } // read/write k-th digit d of a quaternary number: static inline int Abc_TtGetQua( word * p, int k ) { return (int)(p[k>>5] >> ((k<<1) & 63)) & 3; } static inline void Abc_TtSetQua( word * p, int k, int d ) { p[k>>5] |= (((word)d)<<((k<<1) & 63)); } static inline void Abc_TtXorQua( word * p, int k, int d ) { p[k>>5] ^= (((word)d)<<((k<<1) & 63)); } // read/write k-th digit d of a hexadecimal number: static inline int Abc_TtGetHex( word * p, int k ) { return (int)(p[k>>4] >> ((k<<2) & 63)) & 15; } static inline void Abc_TtSetHex( word * p, int k, int d ) { p[k>>4] |= (((word)d)<<((k<<2) & 63)); } static inline void Abc_TtXorHex( word * p, int k, int d ) { p[k>>4] ^= (((word)d)<<((k<<2) & 63)); } // read/write k-th digit d of a 256-base number: static inline int Abc_TtGet256( word * p, int k ) { return (int)(p[k>>3] >> ((k<<3) & 63)) & 255; } static inline void Abc_TtSet256( word * p, int k, int d ) { p[k>>3] |= (((word)d)<<((k<<3) & 63)); } static inline void Abc_TtXor256( word * p, int k, int d ) { p[k>>3] ^= (((word)d)<<((k<<3) & 63)); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtWordNum( int nVars ) { return nVars <= 6 ? 1 : 1 << (nVars-6); } static inline int Abc_TtByteNum( int nVars ) { return nVars <= 3 ? 1 : 1 << (nVars-3); } static inline int Abc_TtHexDigitNum( int nVars ) { return nVars <= 2 ? 1 : 1 << (nVars-2); } /**Function************************************************************* Synopsis [Bit mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6Mask( int nBits ) { assert( nBits >= 0 && nBits <= 64 ); return (~(word)0) >> (64-nBits); } static inline void Abc_TtMask( word * pTruth, int nWords, int nBits ) { int w; assert( nBits >= 0 && nBits <= nWords * 64 ); for ( w = 0; w < nWords; w++ ) if ( nBits >= (w + 1) * 64 ) pTruth[w] = ~(word)0; else if ( nBits > w * 64 ) pTruth[w] = Abc_Tt6Mask( nBits - w * 64 ); else pTruth[w] = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtConst( word * pOut, int nWords, int fConst1 ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = fConst1 ? ~(word)0 : 0; } static inline void Abc_TtClear( word * pOut, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = 0; } static inline void Abc_TtFill( word * pOut, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = ~(word)0; } static inline void Abc_TtUnit( word * pOut, int nWords, int fCompl ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = fCompl ? ~s_Truths6[0] : s_Truths6[0]; } static inline void Abc_TtNot( word * pOut, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = ~pOut[w]; } static inline void Abc_TtCopy( word * pOut, word * pIn, int nWords, int fCompl ) { int w; if ( fCompl ) for ( w = 0; w < nWords; w++ ) pOut[w] = ~pIn[w]; else for ( w = 0; w < nWords; w++ ) pOut[w] = pIn[w]; } static inline void Abc_TtAnd( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl ) { int w; if ( fCompl ) for ( w = 0; w < nWords; w++ ) pOut[w] = ~(pIn1[w] & pIn2[w]); else for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] & pIn2[w]; } static inline void Abc_TtAndSharp( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl ) { int w; if ( fCompl ) for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] & ~pIn2[w]; else for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] & pIn2[w]; } static inline void Abc_TtSharp( word * pOut, word * pIn1, word * pIn2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] & ~pIn2[w]; } static inline void Abc_TtOr( word * pOut, word * pIn1, word * pIn2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] | pIn2[w]; } static inline void Abc_TtXor( word * pOut, word * pIn1, word * pIn2, int nWords, int fCompl ) { int w; if ( fCompl ) for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] ^ ~pIn2[w]; else for ( w = 0; w < nWords; w++ ) pOut[w] = pIn1[w] ^ pIn2[w]; } static inline void Abc_TtMux( word * pOut, word * pCtrl, word * pIn1, word * pIn0, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pOut[w] = (pCtrl[w] & pIn1[w]) | (~pCtrl[w] & pIn0[w]); } static inline int Abc_TtIntersect( word * pIn1, word * pIn2, int nWords, int fCompl ) { int w; if ( fCompl ) { for ( w = 0; w < nWords; w++ ) if ( ~pIn1[w] & pIn2[w] ) return 1; } else { for ( w = 0; w < nWords; w++ ) if ( pIn1[w] & pIn2[w] ) return 1; } return 0; } static inline int Abc_TtEqual( word * pIn1, word * pIn2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( pIn1[w] != pIn2[w] ) return 0; return 1; } static inline int Abc_TtOpposite( word * pIn1, word * pIn2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( pIn1[w] != ~pIn2[w] ) return 0; return 1; } static inline int Abc_TtImply( word * pIn1, word * pIn2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( (pIn1[w] & pIn2[w]) != pIn1[w] ) return 0; return 1; } static inline int Abc_TtCompare( word * pIn1, word * pIn2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( pIn1[w] != pIn2[w] ) return (pIn1[w] < pIn2[w]) ? -1 : 1; return 0; } static inline int Abc_TtCompareRev( word * pIn1, word * pIn2, int nWords ) { int w; for ( w = nWords - 1; w >= 0; w-- ) if ( pIn1[w] != pIn2[w] ) return (pIn1[w] < pIn2[w]) ? -1 : 1; return 0; } static inline int Abc_TtIsConst0( word * pIn1, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( pIn1[w] ) return 0; return 1; } static inline int Abc_TtIsConst1( word * pIn1, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( ~pIn1[w] ) return 0; return 1; } static inline void Abc_TtConst0( word * pIn1, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pIn1[w] = 0; } static inline void Abc_TtConst1( word * pIn1, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pIn1[w] = ~(word)0; } /**Function************************************************************* Synopsis [Compute elementary truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtElemInit( word ** pTtElems, int nVars ) { int i, k, nWords = Abc_TtWordNum( nVars ); for ( i = 0; i < nVars; i++ ) if ( i < 6 ) for ( k = 0; k < nWords; k++ ) pTtElems[i][k] = s_Truths6[i]; else for ( k = 0; k < nWords; k++ ) pTtElems[i][k] = (k & (1 << (i-6))) ? ~(word)0 : 0; } static inline void Abc_TtElemInit2( word * pTtElems, int nVars ) { int i, k, nWords = Abc_TtWordNum( nVars ); for ( i = 0; i < nVars; i++ ) { word * pTruth = pTtElems + i * nWords; if ( i < 6 ) for ( k = 0; k < nWords; k++ ) pTruth[k] = s_Truths6[i]; else for ( k = 0; k < nWords; k++ ) pTruth[k] = (k & (1 << (i-6))) ? ~(word)0 : 0; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6Cofactor0( word t, int iVar ) { assert( iVar >= 0 && iVar < 6 ); return (t &s_Truths6Neg[iVar]) | ((t &s_Truths6Neg[iVar]) << (1<= 0 && iVar < 6 ); return (t & s_Truths6[iVar]) | ((t & s_Truths6[iVar]) >> (1< 5 ) { word * pLimit = pIn + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pIn < pLimit; pIn += 2*iStep, pOut += 2*iStep ) for ( i = 0; i < iStep; i++ ) { pOut[i] = pIn[i]; pOut[i + iStep] = pIn[i]; } } } static inline void Abc_TtCofactor1p( word * pOut, word * pIn, int nWords, int iVar ) { if ( nWords == 1 ) pOut[0] = (pIn[0] & s_Truths6[iVar]) | ((pIn[0] & s_Truths6[iVar]) >> (1 << iVar)); else if ( iVar <= 5 ) { int w, shift = (1 << iVar); for ( w = 0; w < nWords; w++ ) pOut[w] = (pIn[w] & s_Truths6[iVar]) | ((pIn[w] & s_Truths6[iVar]) >> shift); } else // if ( iVar > 5 ) { word * pLimit = pIn + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pIn < pLimit; pIn += 2*iStep, pOut += 2*iStep ) for ( i = 0; i < iStep; i++ ) { pOut[i] = pIn[i + iStep]; pOut[i + iStep] = pIn[i + iStep]; } } } static inline void Abc_TtCofactor0( word * pTruth, int nWords, int iVar ) { if ( nWords == 1 ) pTruth[0] = ((pTruth[0] & s_Truths6Neg[iVar]) << (1 << iVar)) | (pTruth[0] & s_Truths6Neg[iVar]); else if ( iVar <= 5 ) { int w, shift = (1 << iVar); for ( w = 0; w < nWords; w++ ) pTruth[w] = ((pTruth[w] & s_Truths6Neg[iVar]) << shift) | (pTruth[w] & s_Truths6Neg[iVar]); } else // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pTruth < pLimit; pTruth += 2*iStep ) for ( i = 0; i < iStep; i++ ) pTruth[i + iStep] = pTruth[i]; } } static inline void Abc_TtCofactor1( word * pTruth, int nWords, int iVar ) { if ( nWords == 1 ) pTruth[0] = (pTruth[0] & s_Truths6[iVar]) | ((pTruth[0] & s_Truths6[iVar]) >> (1 << iVar)); else if ( iVar <= 5 ) { int w, shift = (1 << iVar); for ( w = 0; w < nWords; w++ ) pTruth[w] = (pTruth[w] & s_Truths6[iVar]) | ((pTruth[w] & s_Truths6[iVar]) >> shift); } else // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pTruth < pLimit; pTruth += 2*iStep ) for ( i = 0; i < iStep; i++ ) pTruth[i] = pTruth[i + iStep]; } } /**Function************************************************************* Synopsis [Checks pairs of cofactors w.r.t. two variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCheckEqualCofs( word * pTruth, int nWords, int iVar, int jVar, int Num1, int Num2 ) { assert( Num1 < Num2 && Num2 < 4 ); assert( iVar < jVar ); if ( nWords == 1 ) { word Mask = s_Truths6Neg[jVar] & s_Truths6Neg[iVar]; int shift1 = (Num1 >> 1) * (1 << jVar) + (Num1 & 1) * (1 << iVar); int shift2 = (Num2 >> 1) * (1 << jVar) + (Num2 & 1) * (1 << iVar); return ((pTruth[0] >> shift1) & Mask) == ((pTruth[0] >> shift2) & Mask); } if ( jVar <= 5 ) { word Mask = s_Truths6Neg[jVar] & s_Truths6Neg[iVar]; int shift1 = (Num1 >> 1) * (1 << jVar) + (Num1 & 1) * (1 << iVar); int shift2 = (Num2 >> 1) * (1 << jVar) + (Num2 & 1) * (1 << iVar); int w; for ( w = 0; w < nWords; w++ ) if ( ((pTruth[w] >> shift1) & Mask) != ((pTruth[w] >> shift2) & Mask) ) return 0; return 1; } if ( iVar <= 5 && jVar > 5 ) { word * pLimit = pTruth + nWords; int j, jStep = Abc_TtWordNum(jVar); int shift1 = (Num1 & 1) * (1 << iVar); int shift2 = (Num2 & 1) * (1 << iVar); int Offset1 = (Num1 >> 1) * jStep; int Offset2 = (Num2 >> 1) * jStep; for ( ; pTruth < pLimit; pTruth += 2*jStep ) for ( j = 0; j < jStep; j++ ) if ( ((pTruth[j + Offset1] >> shift1) & s_Truths6Neg[iVar]) != ((pTruth[j + Offset2] >> shift2) & s_Truths6Neg[iVar]) ) return 0; return 1; } { word * pLimit = pTruth + nWords; int j, jStep = Abc_TtWordNum(jVar); int i, iStep = Abc_TtWordNum(iVar); int Offset1 = (Num1 >> 1) * jStep + (Num1 & 1) * iStep; int Offset2 = (Num2 >> 1) * jStep + (Num2 & 1) * iStep; for ( ; pTruth < pLimit; pTruth += 2*jStep ) for ( i = 0; i < jStep; i += 2*iStep ) for ( j = 0; j < iStep; j++ ) if ( pTruth[Offset1 + i + j] != pTruth[Offset2 + i + j] ) return 0; return 1; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_Tt6Cof0IsConst0( word t, int iVar ) { return (t & s_Truths6Neg[iVar]) == 0; } static inline int Abc_Tt6Cof0IsConst1( word t, int iVar ) { return (t & s_Truths6Neg[iVar]) == s_Truths6Neg[iVar]; } static inline int Abc_Tt6Cof1IsConst0( word t, int iVar ) { return (t & s_Truths6[iVar]) == 0; } static inline int Abc_Tt6Cof1IsConst1( word t, int iVar ) { return (t & s_Truths6[iVar]) == s_Truths6[iVar]; } static inline int Abc_Tt6CofsOpposite( word t, int iVar ) { return (~t & s_Truths6Neg[iVar]) == ((t >> (1 << iVar)) & s_Truths6Neg[iVar]); } static inline int Abc_Tt6Cof0EqualCof1( word t1, word t2, int iVar ) { return (t1 & s_Truths6Neg[iVar]) == ((t2 >> (1 << iVar)) & s_Truths6Neg[iVar]); } static inline int Abc_Tt6Cof0EqualCof0( word t1, word t2, int iVar ) { return (t1 & s_Truths6Neg[iVar]) == (t2 & s_Truths6Neg[iVar]); } static inline int Abc_Tt6Cof1EqualCof1( word t1, word t2, int iVar ) { return (t1 & s_Truths6[iVar]) == (t2 & s_Truths6[iVar]); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtTruthIsConst0( word * p, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( p[w] != 0 ) return 0; return 1; } static inline int Abc_TtTruthIsConst1( word * p, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( p[w] != ~(word)0 ) return 0; return 1; } static inline int Abc_TtCof0IsConst0( word * t, int nWords, int iVar ) { if ( iVar < 6 ) { int i; for ( i = 0; i < nWords; i++ ) if ( t[i] & s_Truths6Neg[iVar] ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( t[i] ) return 0; return 1; } } static inline int Abc_TtCof0IsConst1( word * t, int nWords, int iVar ) { if ( iVar < 6 ) { int i; for ( i = 0; i < nWords; i++ ) if ( (t[i] & s_Truths6Neg[iVar]) != s_Truths6Neg[iVar] ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( ~t[i] ) return 0; return 1; } } static inline int Abc_TtCof1IsConst0( word * t, int nWords, int iVar ) { if ( iVar < 6 ) { int i; for ( i = 0; i < nWords; i++ ) if ( t[i] & s_Truths6[iVar] ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( t[i+Step] ) return 0; return 1; } } static inline int Abc_TtCof1IsConst1( word * t, int nWords, int iVar ) { if ( iVar < 6 ) { int i; for ( i = 0; i < nWords; i++ ) if ( (t[i] & s_Truths6[iVar]) != s_Truths6[iVar] ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( ~t[i+Step] ) return 0; return 1; } } static inline int Abc_TtCofsOpposite( word * t, int nWords, int iVar ) { if ( iVar < 6 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) if ( ((t[i] << Shift) & s_Truths6[iVar]) != (~t[i] & s_Truths6[iVar]) ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + nWords; for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( t[i] != ~t[i+Step] ) return 0; return 1; } } /**Function************************************************************* Synopsis [Stretch truthtable to have more input variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtStretch5( unsigned * pInOut, int nVarS, int nVarB ) { int w, i, step, nWords; if ( nVarS == nVarB ) return; assert( nVarS < nVarB ); step = Abc_TruthWordNum(nVarS); nWords = Abc_TruthWordNum(nVarB); if ( step == nWords ) return; assert( step < nWords ); for ( w = 0; w < nWords; w += step ) for ( i = 0; i < step; i++ ) pInOut[w + i] = pInOut[i]; } static inline void Abc_TtStretch6( word * pInOut, int nVarS, int nVarB ) { int w, i, step, nWords; if ( nVarS == nVarB ) return; assert( nVarS < nVarB ); step = Abc_Truth6WordNum(nVarS); nWords = Abc_Truth6WordNum(nVarB); if ( step == nWords ) return; assert( step < nWords ); for ( w = 0; w < nWords; w += step ) for ( i = 0; i < step; i++ ) pInOut[w + i] = pInOut[i]; } static inline word Abc_Tt6Stretch( word t, int nVars ) { assert( nVars >= 0 ); if ( nVars == 0 ) nVars++, t = (t & 0x1) | ((t & 0x1) << 1); if ( nVars == 1 ) nVars++, t = (t & 0x3) | ((t & 0x3) << 2); if ( nVars == 2 ) nVars++, t = (t & 0xF) | ((t & 0xF) << 4); if ( nVars == 3 ) nVars++, t = (t & 0xFF) | ((t & 0xFF) << 8); if ( nVars == 4 ) nVars++, t = (t & 0xFFFF) | ((t & 0xFFFF) << 16); if ( nVars == 5 ) nVars++, t = (t & 0xFFFFFFFF) | ((t & 0xFFFFFFFF) << 32); assert( nVars == 6 ); return t; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtIsHexDigit( char HexChar ) { return (HexChar >= '0' && HexChar <= '9') || (HexChar >= 'A' && HexChar <= 'F') || (HexChar >= 'a' && HexChar <= 'f'); } static inline char Abc_TtPrintDigit( int Digit ) { assert( Digit >= 0 && Digit < 16 ); if ( Digit < 10 ) return '0' + Digit; return 'A' + Digit-10; } static inline char Abc_TtPrintDigitLower( int Digit ) { assert( Digit >= 0 && Digit < 16 ); if ( Digit < 10 ) return '0' + Digit; return 'a' + Digit-10; } static inline int Abc_TtReadHexDigit( char HexChar ) { if ( HexChar >= '0' && HexChar <= '9' ) return HexChar - '0'; if ( HexChar >= 'A' && HexChar <= 'F' ) return HexChar - 'A' + 10; if ( HexChar >= 'a' && HexChar <= 'f' ) return HexChar - 'a' + 10; assert( 0 ); // not a hexadecimal symbol return -1; // return value which makes no sense } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtPrintHex( word * pTruth, int nVars ) { word * pThis, * pLimit = pTruth + Abc_TtWordNum(nVars); int k; assert( nVars >= 2 ); for ( pThis = pTruth; pThis < pLimit; pThis++ ) for ( k = 0; k < 16; k++ ) printf( "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); printf( "\n" ); } static inline void Abc_TtPrintHexRev( FILE * pFile, word * pTruth, int nVars ) { word * pThis; int k, StartK = nVars >= 6 ? 16 : (1 << (nVars - 2)); assert( nVars >= 2 ); for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) for ( k = StartK - 1; k >= 0; k-- ) fprintf( pFile, "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); // printf( "\n" ); } static inline void Abc_TtPrintHexSpecial( word * pTruth, int nVars ) { word * pThis; int k; assert( nVars >= 2 ); for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) for ( k = 0; k < 16; k++ ) printf( "%c", Abc_TtPrintDigit((int)(pThis[0] >> (k << 2)) & 15) ); printf( "\n" ); } static inline int Abc_TtWriteHexRev( char * pStr, word * pTruth, int nVars ) { word * pThis; char * pStrInit = pStr; int k, StartK = nVars >= 6 ? 16 : (1 << (nVars - 2)); assert( nVars >= 2 ); for ( pThis = pTruth + Abc_TtWordNum(nVars) - 1; pThis >= pTruth; pThis-- ) for ( k = StartK - 1; k >= 0; k-- ) *pStr++ = Abc_TtPrintDigit( (int)(pThis[0] >> (k << 2)) & 15 ); return pStr - pStrInit; } static inline void Abc_TtPrintHexArrayRev( FILE * pFile, word * pTruth, int nDigits ) { int k; for ( k = nDigits - 1; k >= 0; k-- ) fprintf( pFile, "%c", Abc_TtPrintDigitLower( Abc_TtGetHex(pTruth, k) ) ); } /**Function************************************************************* Synopsis [Reads hex truth table from a string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtReadHex( word * pTruth, char * pString ) { int k, nVars, Digit, nDigits; // skip the first 2 symbols if they are "0x" if ( pString[0] == '0' && pString[1] == 'x' ) pString += 2; // count the number of hex digits nDigits = 0; for ( k = 0; Abc_TtIsHexDigit(pString[k]); k++ ) nDigits++; if ( nDigits == 1 ) { if ( pString[0] == '0' || pString[0] == 'F' ) { pTruth[0] = (pString[0] == '0') ? 0 : ~(word)0; return 0; } if ( pString[0] == '5' || pString[0] == 'A' ) { pTruth[0] = (pString[0] == '5') ? s_Truths6Neg[0] : s_Truths6[0]; return 1; } } // determine the number of variables nVars = 2 + Abc_Base2Log( nDigits ); // clean storage for ( k = Abc_TtWordNum(nVars) - 1; k >= 0; k-- ) pTruth[k] = 0; // read hexadecimal digits in the reverse order // (the last symbol in the string is the least significant digit) for ( k = 0; k < nDigits; k++ ) { Digit = Abc_TtReadHexDigit( pString[nDigits - 1 - k] ); assert( Digit >= 0 && Digit < 16 ); Abc_TtSetHex( pTruth, k, Digit ); } if ( nVars < 6 ) pTruth[0] = Abc_Tt6Stretch( pTruth[0], nVars ); return nVars; } static inline int Abc_TtReadHexNumber( word * pTruth, char * pString ) { // count the number of hex digits int k, Digit, nDigits = 0; for ( k = 0; Abc_TtIsHexDigit(pString[k]); k++ ) nDigits++; // read hexadecimal digits in the reverse order // (the last symbol in the string is the least significant digit) for ( k = 0; k < nDigits; k++ ) { Digit = Abc_TtReadHexDigit( pString[nDigits - 1 - k] ); assert( Digit >= 0 && Digit < 16 ); Abc_TtSetHex( pTruth, k, Digit ); } return nDigits; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtPrintBinary( word * pTruth, int nVars ) { word * pThis, * pLimit = pTruth + Abc_TtWordNum(nVars); int k, Limit = Abc_MinInt( 64, (1 << nVars) ); assert( nVars >= 2 ); for ( pThis = pTruth; pThis < pLimit; pThis++ ) for ( k = 0; k < Limit; k++ ) printf( "%d", Abc_InfoHasBit( (unsigned *)pThis, k ) ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtSuppFindFirst( int Supp ) { int i; assert( Supp > 0 ); for ( i = 0; i < 32; i++ ) if ( Supp & (1 << i) ) return i; return -1; } static inline int Abc_TtSuppOnlyOne( int Supp ) { if ( Supp == 0 ) return 0; return (Supp & (Supp-1)) == 0; } static inline int Abc_TtSuppIsMinBase( int Supp ) { assert( Supp > 0 ); return (Supp & (Supp+1)) == 0; } static inline int Abc_Tt6HasVar( word t, int iVar ) { return ((t >> (1<> Shift) & s_Truths6Neg[iVar]) != (t[i] & s_Truths6Neg[iVar]) ) return 1; return 0; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + Abc_TtWordNum( nVars ); for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( t[i] != t[Step+i] ) return 1; return 0; } } static inline int Abc_TtSupport( word * t, int nVars ) { int v, Supp = 0; for ( v = 0; v < nVars; v++ ) if ( Abc_TtHasVar( t, nVars, v ) ) Supp |= (1 << v); return Supp; } static inline int Abc_TtSupportSize( word * t, int nVars ) { int v, SuppSize = 0; for ( v = 0; v < nVars; v++ ) if ( Abc_TtHasVar( t, nVars, v ) ) SuppSize++; return SuppSize; } static inline int Abc_TtSupportAndSize( word * t, int nVars, int * pSuppSize ) { int v, Supp = 0; *pSuppSize = 0; for ( v = 0; v < nVars; v++ ) if ( Abc_TtHasVar( t, nVars, v ) ) Supp |= (1 << v), (*pSuppSize)++; return Supp; } static inline int Abc_Tt6SupportAndSize( word t, int nVars, int * pSuppSize ) { int v, Supp = 0; *pSuppSize = 0; assert( nVars <= 6 ); for ( v = 0; v < nVars; v++ ) if ( Abc_Tt6HasVar( t, v ) ) Supp |= (1 << v), (*pSuppSize)++; return Supp; } /**Function************************************************************* Synopsis [Checks if there is a var whose both cofs have supp <= nSuppLim.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCheckCondDep2( word * pTruth, int nVars, int nSuppLim ) { int v, d, nWords = Abc_TtWordNum(nVars); if ( nVars <= nSuppLim + 1 ) return 0; for ( v = 0; v < nVars; v++ ) { int nDep0 = 0, nDep1 = 0; for ( d = 0; d < nVars; d++ ) { if ( v == d ) continue; if ( v < d ) { nDep0 += !Abc_TtCheckEqualCofs( pTruth, nWords, v, d, 0, 2 ); nDep1 += !Abc_TtCheckEqualCofs( pTruth, nWords, v, d, 1, 3 ); } else // if ( v > d ) { nDep0 += !Abc_TtCheckEqualCofs( pTruth, nWords, d, v, 0, 1 ); nDep1 += !Abc_TtCheckEqualCofs( pTruth, nWords, d, v, 2, 3 ); } if ( nDep0 > nSuppLim || nDep1 > nSuppLim ) break; } if ( d == nVars ) return v; } return nVars; } static inline int Abc_TtCheckCondDep( word * pTruth, int nVars, int nSuppLim ) { int nVarsMax = 13; word Cof0[128], Cof1[128]; // pow( 2, nVarsMax-6 ) int v, d, nWords = Abc_TtWordNum(nVars); assert( nVars <= nVarsMax ); if ( nVars <= nSuppLim + 1 ) return 0; for ( v = 0; v < nVars; v++ ) { int nDep0 = 0, nDep1 = 0; Abc_TtCofactor0p( Cof0, pTruth, nWords, v ); Abc_TtCofactor1p( Cof1, pTruth, nWords, v ); for ( d = 0; d < nVars; d++ ) { if ( v == d ) continue; nDep0 += Abc_TtHasVar( Cof0, nVars, d ); nDep1 += Abc_TtHasVar( Cof1, nVars, d ); if ( nDep0 > nSuppLim || nDep1 > nSuppLim ) break; } if ( d == nVars ) return v; } return nVars; } /**Function************************************************************* Synopsis [Detecting elementary functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtOnlyOneOne( word t ) { if ( t == 0 ) return 0; return (t & (t-1)) == 0; } static inline int Abc_Tt6IsAndType( word t, int nVars ) { return Abc_TtOnlyOneOne( t & Abc_Tt6Mask(1 << nVars) ); } static inline int Abc_Tt6IsOrType( word t, int nVars ) { return Abc_TtOnlyOneOne( ~t & Abc_Tt6Mask(1 << nVars) ); } static inline int Abc_Tt6IsXorType( word t, int nVars ) { return ((((t & 1) ? ~t : t) ^ s_TruthXors[nVars]) & Abc_Tt6Mask(1 << nVars)) == 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6Flip( word Truth, int iVar ) { return Truth = ((Truth << (1 << iVar)) & s_Truths6[iVar]) | ((Truth & s_Truths6[iVar]) >> (1 << iVar)); } static inline void Abc_TtFlip( word * pTruth, int nWords, int iVar ) { if ( nWords == 1 ) pTruth[0] = ((pTruth[0] << (1 << iVar)) & s_Truths6[iVar]) | ((pTruth[0] & s_Truths6[iVar]) >> (1 << iVar)); else if ( iVar <= 5 ) { int w, shift = (1 << iVar); for ( w = 0; w < nWords; w++ ) pTruth[w] = ((pTruth[w] << shift) & s_Truths6[iVar]) | ((pTruth[w] & s_Truths6[iVar]) >> shift); } else // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pTruth < pLimit; pTruth += 2*iStep ) for ( i = 0; i < iStep; i++ ) ABC_SWAP( word, pTruth[i], pTruth[i + iStep] ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6Permute_rec( word t, int * pPerm, int nVars ) { word uRes0, uRes1; int Var; if ( t == 0 ) return 0; if ( ~t == 0 ) return ~(word)0; for ( Var = nVars-1; Var >= 0; Var-- ) if ( Abc_Tt6HasVar( t, Var ) ) break; assert( Var >= 0 ); uRes0 = Abc_Tt6Permute_rec( Abc_Tt6Cofactor0(t, Var), pPerm, Var ); uRes1 = Abc_Tt6Permute_rec( Abc_Tt6Cofactor1(t, Var), pPerm, Var ); return (uRes0 & s_Truths6Neg[pPerm[Var]]) | (uRes1 & s_Truths6[pPerm[Var]]); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6SwapAdjacent( word Truth, int iVar ) { return (Truth & s_PMasks[iVar][0]) | ((Truth & s_PMasks[iVar][1]) << (1 << iVar)) | ((Truth & s_PMasks[iVar][2]) >> (1 << iVar)); } static inline void Abc_TtSwapAdjacent( word * pTruth, int nWords, int iVar ) { if ( iVar < 5 ) { int i, Shift = (1 << iVar); for ( i = 0; i < nWords; i++ ) pTruth[i] = (pTruth[i] & s_PMasks[iVar][0]) | ((pTruth[i] & s_PMasks[iVar][1]) << Shift) | ((pTruth[i] & s_PMasks[iVar][2]) >> Shift); } else if ( iVar == 5 ) { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); for ( ; pTruthU < pLimitU; pTruthU += 4 ) ABC_SWAP( unsigned, pTruthU[1], pTruthU[2] ); } else // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pTruth < pLimit; pTruth += 4*iStep ) for ( i = 0; i < iStep; i++ ) ABC_SWAP( word, pTruth[i + iStep], pTruth[i + 2*iStep] ); } } static inline word Abc_Tt6SwapVars( word t, int iVar, int jVar ) { word * s_PMasks = s_PPMasks[iVar][jVar]; int shift = (1 << jVar) - (1 << iVar); assert( iVar < jVar ); return (t & s_PMasks[0]) | ((t & s_PMasks[1]) << shift) | ((t & s_PMasks[2]) >> shift); } static inline void Abc_TtSwapVars( word * pTruth, int nVars, int iVar, int jVar ) { if ( iVar == jVar ) return; if ( jVar < iVar ) ABC_SWAP( int, iVar, jVar ); assert( iVar < jVar && jVar < nVars ); if ( nVars <= 6 ) { pTruth[0] = Abc_Tt6SwapVars( pTruth[0], iVar, jVar ); return; } if ( jVar <= 5 ) { word * s_PMasks = s_PPMasks[iVar][jVar]; int nWords = Abc_TtWordNum(nVars); int w, shift = (1 << jVar) - (1 << iVar); for ( w = 0; w < nWords; w++ ) pTruth[w] = (pTruth[w] & s_PMasks[0]) | ((pTruth[w] & s_PMasks[1]) << shift) | ((pTruth[w] & s_PMasks[2]) >> shift); return; } if ( iVar <= 5 && jVar > 5 ) { word low2High, high2Low; word * pLimit = pTruth + Abc_TtWordNum(nVars); int j, jStep = Abc_TtWordNum(jVar); int shift = 1 << iVar; for ( ; pTruth < pLimit; pTruth += 2*jStep ) for ( j = 0; j < jStep; j++ ) { low2High = (pTruth[j] & s_Truths6[iVar]) >> shift; high2Low = (pTruth[j+jStep] << shift) & s_Truths6[iVar]; pTruth[j] = (pTruth[j] & ~s_Truths6[iVar]) | high2Low; pTruth[j+jStep] = (pTruth[j+jStep] & s_Truths6[iVar]) | low2High; } return; } { word * pLimit = pTruth + Abc_TtWordNum(nVars); int i, iStep = Abc_TtWordNum(iVar); int j, jStep = Abc_TtWordNum(jVar); for ( ; pTruth < pLimit; pTruth += 2*jStep ) for ( i = 0; i < jStep; i += 2*iStep ) for ( j = 0; j < iStep; j++ ) ABC_SWAP( word, pTruth[iStep + i + j], pTruth[jStep + i + j] ); return; } } // moves one var (v) to the given position (p) static inline void Abc_TtMoveVar( word * pF, int nVars, int * V2P, int * P2V, int v, int p ) { int iVar = V2P[v], jVar = p; if ( iVar == jVar ) return; Abc_TtSwapVars( pF, nVars, iVar, jVar ); V2P[P2V[iVar]] = jVar; V2P[P2V[jVar]] = iVar; P2V[iVar] ^= P2V[jVar]; P2V[jVar] ^= P2V[iVar]; P2V[iVar] ^= P2V[jVar]; } /**Function************************************************************* Synopsis [Support minimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtShrink( word * pF, int nVars, int nVarsAll, unsigned Phase ) { int i, k, Var = 0; assert( nVarsAll <= 16 ); for ( i = 0; i < nVarsAll; i++ ) if ( Phase & (1 << i) ) { for ( k = i-1; k >= Var; k-- ) Abc_TtSwapAdjacent( pF, Abc_TtWordNum(nVarsAll), k ); Var++; } assert( Var == nVars ); } static inline int Abc_TtMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ) { int v, iVar = 0, uSupp = 0; assert( nVarsAll <= 16 ); for ( v = 0; v < nVarsAll; v++ ) if ( Abc_TtHasVar( t, nVarsAll, v ) ) { uSupp |= (1 << v); if ( pSupp ) pSupp[iVar] = pSupp[v]; iVar++; } if ( pnVars ) *pnVars = iVar; if ( uSupp == 0 || Abc_TtSuppIsMinBase( uSupp ) ) return 0; Abc_TtShrink( t, iVar, nVarsAll, uSupp ); return 1; } /**Function************************************************************* Synopsis [Cut minimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6Expand( word t, int * pCut0, int nCutSize0, int * pCut, int nCutSize ) { int i, k; for ( i = nCutSize - 1, k = nCutSize0 - 1; i >= 0 && k >= 0; i-- ) { if ( pCut[i] > pCut0[k] ) continue; assert( pCut[i] == pCut0[k] ); if ( k < i ) t = Abc_Tt6SwapVars( t, k, i ); k--; } assert( k == -1 ); return t; } static inline void Abc_TtExpand( word * pTruth0, int nVars, int * pCut0, int nCutSize0, int * pCut, int nCutSize ) { int i, k; for ( i = nCutSize - 1, k = nCutSize0 - 1; i >= 0 && k >= 0; i-- ) { if ( pCut[i] > pCut0[k] ) continue; assert( pCut[i] == pCut0[k] ); if ( k < i ) Abc_TtSwapVars( pTruth0, nVars, k, i ); k--; } assert( k == -1 ); } static inline int Abc_Tt6MinBase( word * pTruth, int * pVars, int nVars ) { word t = *pTruth; int i, k; for ( i = k = 0; i < nVars; i++ ) { if ( !Abc_Tt6HasVar( t, i ) ) continue; if ( k < i ) { if ( pVars ) pVars[k] = pVars[i]; t = Abc_Tt6SwapVars( t, k, i ); } k++; } if ( k == nVars ) return k; assert( k < nVars ); *pTruth = t; return k; } static inline int Abc_TtMinBase( word * pTruth, int * pVars, int nVars, int nVarsAll ) { int i, k; assert( nVars <= nVarsAll ); for ( i = k = 0; i < nVars; i++ ) { if ( !Abc_TtHasVar( pTruth, nVarsAll, i ) ) continue; if ( k < i ) { if ( pVars ) pVars[k] = pVars[i]; Abc_TtSwapVars( pTruth, nVarsAll, k, i ); } k++; } if ( k == nVars ) return k; assert( k < nVars ); // assert( k == Abc_TtSupportSize(pTruth, nVars) ); return k; } /**Function************************************************************* Synopsis [Implemeting given NPN config.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtImplementNpnConfig( word * pTruth, int nVars, char * pCanonPerm, unsigned uCanonPhase ) { int i, k, nWords = Abc_TtWordNum( nVars ); if ( (uCanonPhase >> nVars) & 1 ) Abc_TtNot( pTruth, nWords ); for ( i = 0; i < nVars; i++ ) if ( (uCanonPhase >> i) & 1 ) Abc_TtFlip( pTruth, nWords, i ); if ( pCanonPerm ) for ( i = 0; i < nVars; i++ ) { for ( k = i; k < nVars; k++ ) if ( pCanonPerm[k] == i ) break; assert( k < nVars ); if ( i == k ) continue; Abc_TtSwapVars( pTruth, nVars, i, k ); ABC_SWAP( int, pCanonPerm[i], pCanonPerm[k] ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCountOnesSlow( word t ) { t = (t & ABC_CONST(0x5555555555555555)) + ((t>> 1) & ABC_CONST(0x5555555555555555)); t = (t & ABC_CONST(0x3333333333333333)) + ((t>> 2) & ABC_CONST(0x3333333333333333)); t = (t & ABC_CONST(0x0F0F0F0F0F0F0F0F)) + ((t>> 4) & ABC_CONST(0x0F0F0F0F0F0F0F0F)); t = (t & ABC_CONST(0x00FF00FF00FF00FF)) + ((t>> 8) & ABC_CONST(0x00FF00FF00FF00FF)); t = (t & ABC_CONST(0x0000FFFF0000FFFF)) + ((t>>16) & ABC_CONST(0x0000FFFF0000FFFF)); return (t & ABC_CONST(0x00000000FFFFFFFF)) + (t>>32); } static inline int Abc_TtCountOnes( word x ) { x = x - ((x >> 1) & ABC_CONST(0x5555555555555555)); x = (x & ABC_CONST(0x3333333333333333)) + ((x >> 2) & ABC_CONST(0x3333333333333333)); x = (x + (x >> 4)) & ABC_CONST(0x0F0F0F0F0F0F0F0F); x = x + (x >> 8); x = x + (x >> 16); x = x + (x >> 32); return (int)(x & 0xFF); } static inline int Abc_TtCountOnesVec( word * x, int nWords ) { int w, Count = 0; for ( w = 0; w < nWords; w++ ) Count += Abc_TtCountOnes( x[w] ); return Count; } static inline int Abc_TtCountOnesVecMask( word * x, word * pMask, int nWords, int fCompl ) { int w, Count = 0; if ( fCompl ) for ( w = 0; w < nWords; w++ ) Count += Abc_TtCountOnes( pMask[w] & ~x[w] ); else for ( w = 0; w < nWords; w++ ) Count += Abc_TtCountOnes( pMask[w] & x[w] ); return Count; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_Tt6FirstBit( word t ) { int n = 0; if ( t == 0 ) return -1; if ( (t & ABC_CONST(0x00000000FFFFFFFF)) == 0 ) { n += 32; t >>= 32; } if ( (t & ABC_CONST(0x000000000000FFFF)) == 0 ) { n += 16; t >>= 16; } if ( (t & ABC_CONST(0x00000000000000FF)) == 0 ) { n += 8; t >>= 8; } if ( (t & ABC_CONST(0x000000000000000F)) == 0 ) { n += 4; t >>= 4; } if ( (t & ABC_CONST(0x0000000000000003)) == 0 ) { n += 2; t >>= 2; } if ( (t & ABC_CONST(0x0000000000000001)) == 0 ) { n++; } return n; } static inline int Abc_Tt6LastBit( word t ) { int n = 0; if ( t == 0 ) return -1; if ( (t & ABC_CONST(0xFFFFFFFF00000000)) == 0 ) { n += 32; t <<= 32; } if ( (t & ABC_CONST(0xFFFF000000000000)) == 0 ) { n += 16; t <<= 16; } if ( (t & ABC_CONST(0xFF00000000000000)) == 0 ) { n += 8; t <<= 8; } if ( (t & ABC_CONST(0xF000000000000000)) == 0 ) { n += 4; t <<= 4; } if ( (t & ABC_CONST(0xC000000000000000)) == 0 ) { n += 2; t <<= 2; } if ( (t & ABC_CONST(0x8000000000000000)) == 0 ) { n++; } return 63-n; } static inline int Abc_TtFindFirstBit( word * pIn, int nVars ) { int w, nWords = Abc_TtWordNum(nVars); for ( w = 0; w < nWords; w++ ) if ( pIn[w] ) return 64*w + Abc_Tt6FirstBit(pIn[w]); return -1; } static inline int Abc_TtFindFirstZero( word * pIn, int nVars ) { int w, nWords = Abc_TtWordNum(nVars); for ( w = 0; w < nWords; w++ ) if ( ~pIn[w] ) return 64*w + Abc_Tt6FirstBit(~pIn[w]); return -1; } static inline int Abc_TtFindLastBit( word * pIn, int nVars ) { int w, nWords = Abc_TtWordNum(nVars); for ( w = nWords - 1; w >= 0; w-- ) if ( pIn[w] ) return 64*w + Abc_Tt6LastBit(pIn[w]); return -1; } static inline int Abc_TtFindLastZero( word * pIn, int nVars ) { int w, nWords = Abc_TtWordNum(nVars); for ( w = nWords - 1; w >= 0; w-- ) if ( ~pIn[w] ) return 64*w + Abc_Tt6LastBit(~pIn[w]); return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtReverseVars( word * pTruth, int nVars ) { int k; for ( k = 0; k < nVars/2 ; k++ ) Abc_TtSwapVars( pTruth, nVars, k, nVars - 1 - k ); } static inline void Abc_TtReverseBits( word * pTruth, int nVars ) { static unsigned char pMirror[256] = { 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; unsigned char Temp, * pTruthC = (unsigned char *)pTruth; int i, nBytes = (nVars > 6) ? (1 << (nVars - 3)) : 8; for ( i = 0; i < nBytes/2; i++ ) { Temp = pMirror[pTruthC[i]]; pTruthC[i] = pMirror[pTruthC[nBytes-1-i]]; pTruthC[nBytes-1-i] = Temp; } } /**Function************************************************************* Synopsis [Checks unateness of a function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_Tt6PosVar( word t, int iVar ) { return ((t >> (1<> Shift) & t[i] & s_Truths6Neg[iVar]) != (t[i] & s_Truths6Neg[iVar]) ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + Abc_TtWordNum( nVars ); for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( t[i] != (t[i] & t[Step+i]) ) return 0; return 1; } } static inline int Abc_TtNegVar( word * t, int nVars, int iVar ) { assert( iVar < nVars ); if ( nVars <= 6 ) return Abc_Tt6NegVar( t[0], iVar ); if ( iVar < 6 ) { int i, Shift = (1 << iVar); int nWords = Abc_TtWordNum( nVars ); for ( i = 0; i < nWords; i++ ) if ( ((t[i] << Shift) & t[i] & s_Truths6[iVar]) != (t[i] & s_Truths6[iVar]) ) return 0; return 1; } else { int i, Step = (1 << (iVar - 6)); word * tLimit = t + Abc_TtWordNum( nVars ); for ( ; t < tLimit; t += 2*Step ) for ( i = 0; i < Step; i++ ) if ( (t[i] & t[Step+i]) != t[Step+i] ) return 0; return 1; } } static inline int Abc_TtIsUnate( word * t, int nVars ) { int i; for ( i = 0; i < nVars; i++ ) if ( !Abc_TtNegVar(t, nVars, i) && !Abc_TtPosVar(t, nVars, i) ) return 0; return 1; } static inline int Abc_TtIsPosUnate( word * t, int nVars ) { int i; for ( i = 0; i < nVars; i++ ) if ( !Abc_TtPosVar(t, nVars, i) ) return 0; return 1; } static inline void Abc_TtMakePosUnate( word * t, int nVars ) { int i, nWords = Abc_TtWordNum(nVars); for ( i = 0; i < nVars; i++ ) if ( Abc_TtNegVar(t, nVars, i) ) Abc_TtFlip( t, nWords, i ); else assert( Abc_TtPosVar(t, nVars, i) ); } /**Function************************************************************* Synopsis [Computes ISOP for 6 variables or less.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6Isop( word uOn, word uOnDc, int nVars, int * pnCubes ) { word uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2; int Var; assert( nVars <= 6 ); assert( (uOn & ~uOnDc) == 0 ); if ( uOn == 0 ) return 0; if ( uOnDc == ~(word)0 ) { (*pnCubes)++; return ~(word)0; } assert( nVars > 0 ); // find the topmost var for ( Var = nVars-1; Var >= 0; Var-- ) if ( Abc_Tt6HasVar( uOn, Var ) || Abc_Tt6HasVar( uOnDc, Var ) ) break; assert( Var >= 0 ); // cofactor uOn0 = Abc_Tt6Cofactor0( uOn, Var ); uOn1 = Abc_Tt6Cofactor1( uOn , Var ); uOnDc0 = Abc_Tt6Cofactor0( uOnDc, Var ); uOnDc1 = Abc_Tt6Cofactor1( uOnDc, Var ); // solve for cofactors uRes0 = Abc_Tt6Isop( uOn0 & ~uOnDc1, uOnDc0, Var, pnCubes ); uRes1 = Abc_Tt6Isop( uOn1 & ~uOnDc0, uOnDc1, Var, pnCubes ); uRes2 = Abc_Tt6Isop( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pnCubes ); // derive the final truth table uRes2 |= (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); assert( (uOn & ~uRes2) == 0 ); assert( (uRes2 & ~uOnDc) == 0 ); return uRes2; } static inline int Abc_Tt7Isop( word uOn[2], word uOnDc[2], int nVars, word uRes[2] ) { int nCubes = 0; if ( nVars <= 6 || (uOn[0] == uOn[1] && uOnDc[0] == uOnDc[1]) ) uRes[0] = uRes[1] = Abc_Tt6Isop( uOn[0], uOnDc[0], Abc_MinInt(nVars, 6), &nCubes ); else { word uRes0, uRes1, uRes2; assert( nVars == 7 ); // solve for cofactors uRes0 = Abc_Tt6Isop( uOn[0] & ~uOnDc[1], uOnDc[0], 6, &nCubes ); uRes1 = Abc_Tt6Isop( uOn[1] & ~uOnDc[0], uOnDc[1], 6, &nCubes ); uRes2 = Abc_Tt6Isop( (uOn[0] & ~uRes0) | (uOn[1] & ~uRes1), uOnDc[0] & uOnDc[1], 6, &nCubes ); // derive the final truth table uRes[0] = uRes2 | uRes0; uRes[1] = uRes2 | uRes1; assert( (uOn[0] & ~uRes[0]) == 0 && (uOn[1] & ~uRes[1]) == 0 ); assert( (uRes[0] & ~uOnDc[0])==0 && (uRes[1] & ~uOnDc[1])==0 ); } return nCubes; } static inline int Abc_Tt8Isop( word uOn[4], word uOnDc[4], int nVars, word uRes[4] ) { int nCubes = 0; if ( nVars <= 6 ) uRes[0] = uRes[1] = uRes[2] = uRes[3] = Abc_Tt6Isop( uOn[0], uOnDc[0], nVars, &nCubes ); else if ( nVars == 7 || (uOn[0] == uOn[2] && uOn[1] == uOn[3] && uOnDc[0] == uOnDc[2] && uOnDc[1] == uOnDc[3]) ) { nCubes = Abc_Tt7Isop( uOn, uOnDc, 7, uRes ); uRes[2] = uRes[0]; uRes[3] = uRes[1]; } else { word uOn0[2], uOn1[2], uOn2[2], uOnDc2[2], uRes0[2], uRes1[2], uRes2[2]; assert( nVars == 8 ); // cofactor uOn0[0] = uOn[0] & ~uOnDc[2]; uOn0[1] = uOn[1] & ~uOnDc[3]; uOn1[0] = uOn[2] & ~uOnDc[0]; uOn1[1] = uOn[3] & ~uOnDc[1]; uOnDc2[0] = uOnDc[0] & uOnDc[2]; uOnDc2[1] = uOnDc[1] & uOnDc[3]; // solve for cofactors nCubes += Abc_Tt7Isop( uOn0, uOnDc+0, 7, uRes0 ); nCubes += Abc_Tt7Isop( uOn1, uOnDc+2, 7, uRes1 ); uOn2[0] = (uOn[0] & ~uRes0[0]) | (uOn[2] & ~uRes1[0]); uOn2[1] = (uOn[1] & ~uRes0[1]) | (uOn[3] & ~uRes1[1]); nCubes += Abc_Tt7Isop( uOn2, uOnDc2, 7, uRes2 ); // derive the final truth table uRes[0] = uRes2[0] | uRes0[0]; uRes[1] = uRes2[1] | uRes0[1]; uRes[2] = uRes2[0] | uRes1[0]; uRes[3] = uRes2[1] | uRes1[1]; assert( (uOn[0] & ~uRes[0]) == 0 && (uOn[1] & ~uRes[1]) == 0 && (uOn[2] & ~uRes[2]) == 0 && (uOn[3] & ~uRes[3]) == 0 ); assert( (uRes[0] & ~uOnDc[0])==0 && (uRes[1] & ~uOnDc[1])==0 && (uRes[2] & ~uOnDc[2])==0 && (uRes[3] & ~uOnDc[3])==0 ); } return nCubes; } /**Function************************************************************* Synopsis [Computes CNF size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_Tt6CnfSize( word t, int nVars ) { int nCubes = 0; Abc_Tt6Isop( t, t, nVars, &nCubes ); Abc_Tt6Isop( ~t, ~t, nVars, &nCubes ); assert( nCubes <= 64 ); return nCubes; } static inline int Abc_Tt8CnfSize( word t[4], int nVars ) { word uRes[4], tc[4] = {~t[0], ~t[1], ~t[2], ~t[3]}; int nCubes = 0; nCubes += Abc_Tt8Isop( t, t, nVars, uRes ); nCubes += Abc_Tt8Isop( tc, tc, nVars, uRes ); assert( nCubes <= 256 ); return nCubes; } /**Function************************************************************* Synopsis [Derives ISOP cover for the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6IsopCover( word uOn, word uOnDc, int nVars, int * pCover, int * pnCubes ) { word uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2; int c, Var, nBeg0, nEnd0, nEnd1; assert( nVars <= 6 ); assert( (uOn & ~uOnDc) == 0 ); if ( uOn == 0 ) return 0; if ( uOnDc == ~(word)0 ) { pCover[(*pnCubes)++] = 0; return ~(word)0; } assert( nVars > 0 ); // find the topmost var for ( Var = nVars-1; Var >= 0; Var-- ) if ( Abc_Tt6HasVar( uOn, Var ) || Abc_Tt6HasVar( uOnDc, Var ) ) break; assert( Var >= 0 ); // cofactor uOn0 = Abc_Tt6Cofactor0( uOn, Var ); uOn1 = Abc_Tt6Cofactor1( uOn , Var ); uOnDc0 = Abc_Tt6Cofactor0( uOnDc, Var ); uOnDc1 = Abc_Tt6Cofactor1( uOnDc, Var ); // solve for cofactors nBeg0 = *pnCubes; uRes0 = Abc_Tt6IsopCover( uOn0 & ~uOnDc1, uOnDc0, Var, pCover, pnCubes ); nEnd0 = *pnCubes; uRes1 = Abc_Tt6IsopCover( uOn1 & ~uOnDc0, uOnDc1, Var, pCover, pnCubes ); nEnd1 = *pnCubes; uRes2 = Abc_Tt6IsopCover( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pCover, pnCubes ); // derive the final truth table uRes2 |= (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); for ( c = nBeg0; c < nEnd0; c++ ) pCover[c] |= (1 << (2*Var+0)); for ( c = nEnd0; c < nEnd1; c++ ) pCover[c] |= (1 << (2*Var+1)); assert( (uOn & ~uRes2) == 0 ); assert( (uRes2 & ~uOnDc) == 0 ); return uRes2; } static inline void Abc_Tt7IsopCover( word uOn[2], word uOnDc[2], int nVars, word uRes[2], int * pCover, int * pnCubes ) { if ( nVars <= 6 || (uOn[0] == uOn[1] && uOnDc[0] == uOnDc[1]) ) uRes[0] = uRes[1] = Abc_Tt6IsopCover( uOn[0], uOnDc[0], Abc_MinInt(nVars, 6), pCover, pnCubes ); else { word uRes0, uRes1, uRes2; int c, nBeg0, nEnd0, nEnd1; assert( nVars == 7 ); // solve for cofactors nBeg0 = *pnCubes; uRes0 = Abc_Tt6IsopCover( uOn[0] & ~uOnDc[1], uOnDc[0], 6, pCover, pnCubes ); nEnd0 = *pnCubes; uRes1 = Abc_Tt6IsopCover( uOn[1] & ~uOnDc[0], uOnDc[1], 6, pCover, pnCubes ); nEnd1 = *pnCubes; uRes2 = Abc_Tt6IsopCover( (uOn[0] & ~uRes0) | (uOn[1] & ~uRes1), uOnDc[0] & uOnDc[1], 6, pCover, pnCubes ); // derive the final truth table uRes[0] = uRes2 | uRes0; uRes[1] = uRes2 | uRes1; for ( c = nBeg0; c < nEnd0; c++ ) pCover[c] |= (1 << (2*6+0)); for ( c = nEnd0; c < nEnd1; c++ ) pCover[c] |= (1 << (2*6+1)); assert( (uOn[0] & ~uRes[0]) == 0 && (uOn[1] & ~uRes[1]) == 0 ); assert( (uRes[0] & ~uOnDc[0])==0 && (uRes[1] & ~uOnDc[1])==0 ); } } static inline void Abc_Tt8IsopCover( word uOn[4], word uOnDc[4], int nVars, word uRes[4], int * pCover, int * pnCubes ) { if ( nVars <= 6 ) uRes[0] = uRes[1] = uRes[2] = uRes[3] = Abc_Tt6IsopCover( uOn[0], uOnDc[0], nVars, pCover, pnCubes ); else if ( nVars == 7 || (uOn[0] == uOn[2] && uOn[1] == uOn[3] && uOnDc[0] == uOnDc[2] && uOnDc[1] == uOnDc[3]) ) { Abc_Tt7IsopCover( uOn, uOnDc, 7, uRes, pCover, pnCubes ); uRes[2] = uRes[0]; uRes[3] = uRes[1]; } else { word uOn0[2], uOn1[2], uOn2[2], uOnDc2[2], uRes0[2], uRes1[2], uRes2[2]; int c, nBeg0, nEnd0, nEnd1; assert( nVars == 8 ); // cofactor uOn0[0] = uOn[0] & ~uOnDc[2]; uOn0[1] = uOn[1] & ~uOnDc[3]; uOn1[0] = uOn[2] & ~uOnDc[0]; uOn1[1] = uOn[3] & ~uOnDc[1]; uOnDc2[0] = uOnDc[0] & uOnDc[2]; uOnDc2[1] = uOnDc[1] & uOnDc[3]; // solve for cofactors nBeg0 = *pnCubes; Abc_Tt7IsopCover( uOn0, uOnDc+0, 7, uRes0, pCover, pnCubes ); nEnd0 = *pnCubes; Abc_Tt7IsopCover( uOn1, uOnDc+2, 7, uRes1, pCover, pnCubes ); nEnd1 = *pnCubes; uOn2[0] = (uOn[0] & ~uRes0[0]) | (uOn[2] & ~uRes1[0]); uOn2[1] = (uOn[1] & ~uRes0[1]) | (uOn[3] & ~uRes1[1]); Abc_Tt7IsopCover( uOn2, uOnDc2, 7, uRes2, pCover, pnCubes ); // derive the final truth table uRes[0] = uRes2[0] | uRes0[0]; uRes[1] = uRes2[1] | uRes0[1]; uRes[2] = uRes2[0] | uRes1[0]; uRes[3] = uRes2[1] | uRes1[1]; for ( c = nBeg0; c < nEnd0; c++ ) pCover[c] |= (1 << (2*7+0)); for ( c = nEnd0; c < nEnd1; c++ ) pCover[c] |= (1 << (2*7+1)); assert( (uOn[0] & ~uRes[0]) == 0 && (uOn[1] & ~uRes[1]) == 0 && (uOn[2] & ~uRes[2]) == 0 && (uOn[3] & ~uRes[3]) == 0 ); assert( (uRes[0] & ~uOnDc[0])==0 && (uRes[1] & ~uOnDc[1])==0 && (uRes[2] & ~uOnDc[2])==0 && (uRes[3] & ~uOnDc[3])==0 ); } } /**Function************************************************************* Synopsis [Computes CNF for the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_Tt6Cnf( word t, int nVars, int * pCover ) { int c, nCubes = 0; Abc_Tt6IsopCover( t, t, nVars, pCover, &nCubes ); for ( c = 0; c < nCubes; c++ ) pCover[c] |= (1 << (2*nVars+0)); Abc_Tt6IsopCover( ~t, ~t, nVars, pCover, &nCubes ); for ( ; c < nCubes; c++ ) pCover[c] |= (1 << (2*nVars+1)); assert( nCubes <= 64 ); return nCubes; } static inline int Abc_Tt8Cnf( word t[4], int nVars, int * pCover ) { word uRes[4], tc[4] = {~t[0], ~t[1], ~t[2], ~t[3]}; int c, nCubes = 0; Abc_Tt8IsopCover( t, t, nVars, uRes, pCover, &nCubes ); for ( c = 0; c < nCubes; c++ ) pCover[c] |= (1 << (2*nVars+0)); Abc_Tt8IsopCover( tc, tc, nVars, uRes, pCover, &nCubes ); for ( ; c < nCubes; c++ ) pCover[c] |= (1 << (2*nVars+1)); assert( nCubes <= 256 ); return nCubes; } /**Function************************************************************* Synopsis [Computes ISOP for 6 variables or less.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_Tt6Esop( word t, int nVars, int * pCover ) { word c0, c1; int Var, r0, r1, r2, Max, i; assert( nVars <= 6 ); if ( t == 0 ) return 0; if ( t == ~(word)0 ) { if ( pCover ) *pCover = 0; return 1; } assert( nVars > 0 ); // find the topmost var for ( Var = nVars-1; Var >= 0; Var-- ) if ( Abc_Tt6HasVar( t, Var ) ) break; assert( Var >= 0 ); // cofactor c0 = Abc_Tt6Cofactor0( t, Var ); c1 = Abc_Tt6Cofactor1( t, Var ); // call recursively r0 = Abc_Tt6Esop( c0, Var, pCover ? pCover : NULL ); r1 = Abc_Tt6Esop( c1, Var, pCover ? pCover + r0 : NULL ); r2 = Abc_Tt6Esop( c0 ^ c1, Var, pCover ? pCover + r0 + r1 : NULL ); Max = Abc_MaxInt( r0, Abc_MaxInt(r1, r2) ); // add literals if ( pCover ) { if ( Max == r0 ) { for ( i = 0; i < r1; i++ ) pCover[i] = pCover[r0+i]; for ( i = 0; i < r2; i++ ) pCover[r1+i] = pCover[r0+r1+i] | (1 << (2*Var+0)); } else if ( Max == r1 ) { for ( i = 0; i < r2; i++ ) pCover[r0+i] = pCover[r0+r1+i] | (1 << (2*Var+1)); } else { for ( i = 0; i < r0; i++ ) pCover[i] |= (1 << (2*Var+0)); for ( i = 0; i < r1; i++ ) pCover[r0+i] |= (1 << (2*Var+1)); } } return r0 + r1 + r2 - Max; } static inline word Abc_Tt6EsopBuild( int nVars, int * pCover, int nCubes ) { word p, t = 0; int c, v; for ( c = 0; c < nCubes; c++ ) { p = ~(word)0; for ( v = 0; v < nVars; v++ ) if ( ((pCover[c] >> (v << 1)) & 3) == 1 ) p &= ~s_Truths6[v]; else if ( ((pCover[c] >> (v << 1)) & 3) == 2 ) p &= s_Truths6[v]; t ^= p; } return t; } static inline int Abc_Tt6EsopVerify( word t, int nVars ) { int pCover[64]; int nCubes = Abc_Tt6Esop( t, nVars, pCover ); word t2 = Abc_Tt6EsopBuild( nVars, pCover, nCubes ); if ( t != t2 ) printf( "Verification failed.\n" ); return nCubes; } /**Function************************************************************* Synopsis [Check if the function is decomposable with the given pair.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCheckDsdAnd( word t, int i, int j, word * pOut ) { word c0 = Abc_Tt6Cofactor0( t, i ); word c1 = Abc_Tt6Cofactor1( t, i ); word c00 = Abc_Tt6Cofactor0( c0, j ); word c01 = Abc_Tt6Cofactor1( c0, j ); word c10 = Abc_Tt6Cofactor0( c1, j ); word c11 = Abc_Tt6Cofactor1( c1, j ); if ( c00 == c01 && c00 == c10 ) // i * j { if ( pOut ) *pOut = (~s_Truths6[i] & c00) | (s_Truths6[i] & c11); return 0; } if ( c11 == c00 && c11 == c10 ) // i * !j { if ( pOut ) *pOut = (~s_Truths6[i] & c11) | (s_Truths6[i] & c01); return 1; } if ( c11 == c00 && c11 == c01 ) // !i * j { if ( pOut ) *pOut = (~s_Truths6[i] & c11) | (s_Truths6[i] & c10); return 2; } if ( c11 == c01 && c11 == c10 ) // !i * !j { if ( pOut ) *pOut = (~s_Truths6[i] & c11) | (s_Truths6[i] & c00); return 3; } if ( c00 == c11 && c01 == c10 ) { if ( pOut ) *pOut = (~s_Truths6[i] & c11) | (s_Truths6[i] & c10); return 4; } return -1; } static inline int Abc_TtCheckDsdMux( word t, int i, word * pOut ) { word c0 = Abc_Tt6Cofactor0( t, i ); word c1 = Abc_Tt6Cofactor1( t, i ); word c00, c01, c10, c11; int k, fPres0, fPres1, iVar0 = -1, iVar1 = -1; for ( k = 0; k < 6; k++ ) { if ( k == i ) continue; fPres0 = Abc_Tt6HasVar( c0, k ); fPres1 = Abc_Tt6HasVar( c1, k ); if ( fPres0 && !fPres1 ) { if ( iVar0 >= 0 ) return -1; iVar0 = k; } if ( !fPres0 && fPres1 ) { if ( iVar1 >= 0 ) return -1; iVar1 = k; } } if ( iVar0 == -1 || iVar1 == -1 ) return -1; c00 = Abc_Tt6Cofactor0( c0, iVar0 ); c01 = Abc_Tt6Cofactor1( c0, iVar0 ); c10 = Abc_Tt6Cofactor0( c1, iVar1 ); c11 = Abc_Tt6Cofactor1( c1, iVar1 ); if ( c00 == c10 && c01 == c11 ) // ITE(i, iVar1, iVar0) { if ( pOut ) *pOut = (~s_Truths6[i] & c10) | (s_Truths6[i] & c11); return (Abc_Var2Lit(iVar1, 0) << 16) | Abc_Var2Lit(iVar0, 0); } if ( c00 == ~c10 && c01 == ~c11 ) // ITE(i, iVar1, !iVar0) { if ( pOut ) *pOut = (~s_Truths6[i] & c10) | (s_Truths6[i] & c11); return (Abc_Var2Lit(iVar1, 0) << 16) | Abc_Var2Lit(iVar0, 1); } return -1; } static inline void Unm_ManCheckTest2() { word t, t1, Out, Var0, Var1, Var0_, Var1_; int iVar0, iVar1, i, Res; for ( iVar0 = 0; iVar0 < 6; iVar0++ ) for ( iVar1 = 0; iVar1 < 6; iVar1++ ) { if ( iVar0 == iVar1 ) continue; Var0 = s_Truths6[iVar0]; Var1 = s_Truths6[iVar1]; for ( i = 0; i < 5; i++ ) { Var0_ = ((i >> 0) & 1) ? ~Var0 : Var0; Var1_ = ((i >> 1) & 1) ? ~Var1 : Var1; t = Var0_ & Var1_; if ( i == 4 ) t = ~(Var0_ ^ Var1_); // Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ), printf( "\n" ); Res = Abc_TtCheckDsdAnd( t, iVar0, iVar1, &Out ); if ( Res == -1 ) { printf( "No decomposition\n" ); continue; } Var0_ = s_Truths6[iVar0]; Var0_ = ((Res >> 0) & 1) ? ~Var0_ : Var0_; Var1_ = s_Truths6[iVar1]; Var1_ = ((Res >> 1) & 1) ? ~Var1_ : Var1_; t1 = Var0_ & Var1_; if ( Res == 4 ) t1 = Var0_ ^ Var1_; t1 = (~t1 & Abc_Tt6Cofactor0(Out, iVar0)) | (t1 & Abc_Tt6Cofactor1(Out, iVar0)); // Kit_DsdPrintFromTruth( (unsigned *)&t1, 6 ), printf( "\n" ); if ( t1 != t ) printf( "Verification failed.\n" ); else printf( "Verification succeeded.\n" ); } } } static inline void Unm_ManCheckTest() { word t, t1, Out, Ctrl, Var0, Var1, Ctrl_, Var0_, Var1_; int iVar0, iVar1, iCtrl, i, Res; for ( iCtrl = 0; iCtrl < 6; iCtrl++ ) for ( iVar0 = 0; iVar0 < 6; iVar0++ ) for ( iVar1 = 0; iVar1 < 6; iVar1++ ) { if ( iCtrl == iVar0 || iCtrl == iVar1 || iVar0 == iVar1 ) continue; Ctrl = s_Truths6[iCtrl]; Var0 = s_Truths6[iVar0]; Var1 = s_Truths6[iVar1]; for ( i = 0; i < 8; i++ ) { Ctrl_ = ((i >> 0) & 1) ? ~Ctrl : Ctrl; Var0_ = ((i >> 1) & 1) ? ~Var0 : Var0; Var1_ = ((i >> 2) & 1) ? ~Var1 : Var1; t = (~Ctrl_ & Var0_) | (Ctrl_ & Var1_); // Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ), printf( "\n" ); Res = Abc_TtCheckDsdMux( t, iCtrl, &Out ); if ( Res == -1 ) { printf( "No decomposition\n" ); continue; } // Kit_DsdPrintFromTruth( (unsigned *)&Out, 6 ), printf( "\n" ); Ctrl_ = s_Truths6[iCtrl]; Var0_ = s_Truths6[Abc_Lit2Var(Res & 0xFFFF)]; Var0_ = Abc_LitIsCompl(Res & 0xFFFF) ? ~Var0_ : Var0_; Res >>= 16; Var1_ = s_Truths6[Abc_Lit2Var(Res & 0xFFFF)]; Var1_ = Abc_LitIsCompl(Res & 0xFFFF) ? ~Var1_ : Var1_; t1 = (~Ctrl_ & Var0_) | (Ctrl_ & Var1_); // Kit_DsdPrintFromTruth( (unsigned *)&t1, 6 ), printf( "\n" ); // Kit_DsdPrintFromTruth( (unsigned *)&Out, 6 ), printf( "\n" ); t1 = (~t1 & Abc_Tt6Cofactor0(Out, iCtrl)) | (t1 & Abc_Tt6Cofactor1(Out, iCtrl)); // Kit_DsdPrintFromTruth( (unsigned *)&t1, 6 ), printf( "\n" ); if ( t1 != t ) printf( "Verification failed.\n" ); else printf( "Verification succeeded.\n" ); } } } /**Function************************************************************* Synopsis [Checks existence of bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtComputeGraph( word * pTruth, int v, int nVars, int * pGraph ) { word Cof0[64], Cof1[64]; // pow( 2, nVarsMax-6 ) word Cof00[64], Cof01[64], Cof10[64], Cof11[64]; word CofXor, CofAndTest; int i, w, nWords = Abc_TtWordNum(nVars); pGraph[v] |= (1 << v); if ( v == nVars - 1 ) return; assert( v < nVars - 1 ); Abc_TtCofactor0p( Cof0, pTruth, nWords, v ); Abc_TtCofactor1p( Cof1, pTruth, nWords, v ); for ( i = v + 1; i < nVars; i++ ) { Abc_TtCofactor0p( Cof00, Cof0, nWords, i ); Abc_TtCofactor1p( Cof01, Cof0, nWords, i ); Abc_TtCofactor0p( Cof10, Cof1, nWords, i ); Abc_TtCofactor1p( Cof11, Cof1, nWords, i ); for ( w = 0; w < nWords; w++ ) { CofXor = Cof00[w] ^ Cof01[w] ^ Cof10[w] ^ Cof11[w]; CofAndTest = (Cof00[w] & Cof01[w]) | (Cof10[w] & Cof11[w]); if ( CofXor & CofAndTest ) { pGraph[v] |= (1 << i); pGraph[i] |= (1 << v); } else if ( CofXor & ~CofAndTest ) { pGraph[v] |= (1 << (16+i)); pGraph[i] |= (1 << (16+v)); } } } } static inline void Abc_TtPrintVarSet( int Mask, int nVars ) { int i; for ( i = 0; i < nVars; i++ ) if ( (Mask >> i) & 1 ) printf( "1" ); else printf( "." ); } static inline void Abc_TtPrintBiDec( word * pTruth, int nVars ) { int v, pGraph[12] = {0}; assert( nVars <= 12 ); for ( v = 0; v < nVars; v++ ) { Abc_TtComputeGraph( pTruth, v, nVars, pGraph ); Abc_TtPrintVarSet( pGraph[v], nVars ); printf( " " ); Abc_TtPrintVarSet( pGraph[v] >> 16, nVars ); printf( "\n" ); } } static inline int Abc_TtVerifyBiDec( word * pTruth, int nVars, int This, int That, int nSuppLim, word wThis, word wThat ) { int pVarsThis[12], pVarsThat[12], pVarsAll[12]; int nThis = Abc_TtBitCount16(This); int nThat = Abc_TtBitCount16(That); int i, k, nWords = Abc_TtWordNum(nVars); word pThis[64] = {wThis}, pThat[64] = {wThat}; assert( nVars <= 12 ); for ( i = 0; i < nVars; i++ ) pVarsAll[i] = i; for ( i = k = 0; i < nVars; i++ ) if ( (This >> i) & 1 ) pVarsThis[k++] = i; assert( k == nThis ); for ( i = k = 0; i < nVars; i++ ) if ( (That >> i) & 1 ) pVarsThat[k++] = i; assert( k == nThat ); Abc_TtStretch6( pThis, nThis, nVars ); Abc_TtStretch6( pThat, nThat, nVars ); Abc_TtExpand( pThis, nVars, pVarsThis, nThis, pVarsAll, nVars ); Abc_TtExpand( pThat, nVars, pVarsThat, nThat, pVarsAll, nVars ); for ( k = 0; k < nWords; k++ ) if ( pTruth[k] != (pThis[k] & pThat[k]) ) return 0; return 1; } static inline void Abc_TtExist( word * pTruth, int iVar, int nWords ) { word Cof0[64], Cof1[64]; Abc_TtCofactor0p( Cof0, pTruth, nWords, iVar ); Abc_TtCofactor1p( Cof1, pTruth, nWords, iVar ); Abc_TtOr( pTruth, Cof0, Cof1, nWords ); } static inline int Abc_TtCheckBiDec( word * pTruth, int nVars, int This, int That ) { int VarMask[2] = {This & ~That, That & ~This}; int v, c, nWords = Abc_TtWordNum(nVars); word pTempR[2][64]; for ( c = 0; c < 2; c++ ) { Abc_TtCopy( pTempR[c], pTruth, nWords, 0 ); for ( v = 0; v < nVars; v++ ) if ( ((VarMask[c] >> v) & 1) ) Abc_TtExist( pTempR[c], v, nWords ); } for ( v = 0; v < nWords; v++ ) if ( ~pTruth[v] & pTempR[0][v] & pTempR[1][v] ) return 0; return 1; } static inline word Abc_TtDeriveBiDecOne( word * pTruth, int nVars, int This ) { word pTemp[64]; int nThis = Abc_TtBitCount16(This); int v, nWords = Abc_TtWordNum(nVars); Abc_TtCopy( pTemp, pTruth, nWords, 0 ); for ( v = 0; v < nVars; v++ ) if ( !((This >> v) & 1) ) Abc_TtExist( pTemp, v, nWords ); Abc_TtShrink( pTemp, nThis, nVars, This ); return Abc_Tt6Stretch( pTemp[0], nThis ); } static inline void Abc_TtDeriveBiDec( word * pTruth, int nVars, int This, int That, int nSuppLim, word * pThis, word * pThat ) { assert( Abc_TtBitCount16(This) <= nSuppLim ); assert( Abc_TtBitCount16(That) <= nSuppLim ); pThis[0] = Abc_TtDeriveBiDecOne( pTruth, nVars, This ); pThat[0] = Abc_TtDeriveBiDecOne( pTruth, nVars, That ); if ( !Abc_TtVerifyBiDec(pTruth, nVars, This, That, nSuppLim, pThis[0], pThat[0] ) ) printf( "Bi-decomposition verification failed.\n" ); } // detect simple case of decomposition with topmost AND gate static inline int Abc_TtCheckBiDecSimple( word * pTruth, int nVars, int nSuppLim ) { word Cof0[64], Cof1[64]; int v, Res = 0, nDecVars = 0, nWords = Abc_TtWordNum(nVars); for ( v = 0; v < nVars; v++ ) { Abc_TtCofactor0p( Cof0, pTruth, nWords, v ); Abc_TtCofactor1p( Cof1, pTruth, nWords, v ); if ( !Abc_TtIsConst0(Cof0, nWords) && !Abc_TtIsConst0(Cof1, nWords) ) continue; nDecVars++; Res |= 1 << v; if ( nDecVars >= nVars - nSuppLim ) return ((Res ^ (int)Abc_Tt6Mask(nVars)) << 16) | Res; } return 0; } static inline int Abc_TtProcessBiDecInt( word * pTruth, int nVars, int nSuppLim ) { int i, v, Res, nSupp, CountShared = 0, pGraph[12] = {0}; assert( nSuppLim < nVars && nVars <= 2 * nSuppLim && nVars <= 12 ); assert( 2 <= nSuppLim && nSuppLim <= 6 ); Res = Abc_TtCheckBiDecSimple( pTruth, nVars, nSuppLim ); if ( Res ) return Res; for ( v = 0; v < nVars; v++ ) { Abc_TtComputeGraph( pTruth, v, nVars, pGraph ); nSupp = Abc_TtBitCount16(pGraph[v] & 0xFFFF); if ( nSupp > nSuppLim ) { // this variable is shared - check if the limit is exceeded if ( ++CountShared > 2*nSuppLim - nVars ) return 0; } else if ( nVars - nSupp <= nSuppLim ) { int This = pGraph[v] & 0xFFFF; int That = This ^ (int)Abc_Tt6Mask(nVars); // find the other component int Graph = That; for ( i = 0; i < nVars; i++ ) if ( (That >> i) & 1 ) Graph |= pGraph[i] & 0xFFFF; // check if this can be done if ( Abc_TtBitCount16(Graph) > nSuppLim ) continue; // try decomposition if ( Abc_TtCheckBiDec(pTruth, nVars, This, Graph) ) return (Graph << 16) | This; } } return 0; } static inline int Abc_TtProcessBiDec( word * pTruth, int nVars, int nSuppLim ) { word pFunc[64]; int Res, nWords = Abc_TtWordNum(nVars); Abc_TtCopy( pFunc, pTruth, nWords, 0 ); Res = Abc_TtProcessBiDecInt( pFunc, nVars, nSuppLim ); if ( Res ) return Res; Abc_TtCopy( pFunc, pTruth, nWords, 1 ); Res = Abc_TtProcessBiDecInt( pFunc, nVars, nSuppLim ); if ( Res ) return Res | (1 << 30); return 0; } /**Function************************************************************* Synopsis [Tests decomposition procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtProcessBiDecTest( word * pTruth, int nVars, int nSuppLim ) { word This, That, pTemp[64]; int Res, resThis, resThat, nThis, nThat; int nWords = Abc_TtWordNum(nVars); Abc_TtCopy( pTemp, pTruth, nWords, 0 ); Res = Abc_TtProcessBiDec( pTemp, nVars, nSuppLim ); if ( Res == 0 ) { //Dau_DsdPrintFromTruth( pTemp, nVars ); //printf( "Non_dec\n\n" ); return; } resThis = Res & 0xFFFF; resThat = Res >> 16; Abc_TtDeriveBiDec( pTemp, nVars, resThis, resThat, nSuppLim, &This, &That ); return; //if ( !(resThis & resThat) ) // return; // Dau_DsdPrintFromTruth( pTemp, nVars ); nThis = Abc_TtBitCount16(resThis); nThat = Abc_TtBitCount16(resThat); printf( "Variable sets: " ); Abc_TtPrintVarSet( resThis, nVars ); printf( " " ); Abc_TtPrintVarSet( resThat, nVars ); printf( "\n" ); Abc_TtDeriveBiDec( pTemp, nVars, resThis, resThat, nSuppLim, &This, &That ); // Dau_DsdPrintFromTruth( &This, nThis ); // Dau_DsdPrintFromTruth( &That, nThat ); printf( "\n" ); } static inline void Abc_TtProcessBiDecExperiment() { int nVars = 3; int nSuppLim = 2; int Res, resThis, resThat; word This, That; // word t = ABC_CONST(0x8000000000000000); // word t = (s_Truths6[0] | s_Truths6[1]) & (s_Truths6[2] | s_Truths6[3] | s_Truths6[4] | s_Truths6[5]); // word t = ((s_Truths6[0] & s_Truths6[1]) | (~s_Truths6[1] & s_Truths6[2])); word t = ((s_Truths6[0] | s_Truths6[1]) & (s_Truths6[1] | s_Truths6[2])); Abc_TtPrintBiDec( &t, nVars ); Res = Abc_TtProcessBiDec( &t, nVars, nSuppLim ); resThis = Res & 0xFFFF; resThat = Res >> 16; Abc_TtDeriveBiDec( &t, nVars, resThis, resThat, nSuppLim, &This, &That ); // Dau_DsdPrintFromTruth( &This, Abc_TtBitCount16(resThis) ); // Dau_DsdPrintFromTruth( &That, Abc_TtBitCount16(resThat) ); nVars = nSuppLim; } /**Function************************************************************* Synopsis [Truth table checking procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_Tt4Equal3( int c0, int c1, int c2, int c3 ) { if ( c0 == c1 && c0 == c2 ) return 3; if ( c0 == c1 && c0 == c3 ) return 2; if ( c0 == c3 && c0 == c2 ) return 1; if ( c3 == c1 && c3 == c2 ) return 0; return -1; } static inline int Abc_Tt4Check2( int t, int i, int j, int * f, int * r ) { int c0 = t & r[j]; int c1 = (t & f[j]) >> (1 << j); int c00 = c0 & r[i]; int c01 = (c0 & f[i]) >> (1 << i); int c10 = c1 & r[i]; int c11 = (c1 & f[i]) >> (1 << i); return Abc_Tt4Equal3( c00, c01, c10, c11 ); } static inline int Abc_Tt4CheckTwoLevel( int t ) { int pair1, pair2; int f[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 }; int r[4] = { 0x5555, 0x3333, 0x0F0F, 0x00FF }; if ( (pair1 = Abc_Tt4Check2(t, 0, 1, f, r)) >= 0 && (pair2 = Abc_Tt4Check2(t, 2, 3, f, r)) >= 0 ) return (1 << 4) | (pair2 << 2) | pair1; if ( (pair1 = Abc_Tt4Check2(t, 0, 2, f, r)) >= 0 && (pair2 = Abc_Tt4Check2(t, 1, 3, f, r)) >= 0 ) return (2 << 4) | (pair2 << 2) | pair1; if ( (pair1 = Abc_Tt4Check2(t, 0, 3, f, r)) >= 0 && (pair2 = Abc_Tt4Check2(t, 1, 2, f, r)) >= 0 ) return (3 << 4) | (pair2 << 2) | pair1; return -1; } static inline int Abc_Tt4CountOnes( int t ) { t = (t & (0x5555)) + ((t >> 1) & (0x5555)); t = (t & (0x3333)) + ((t >> 2) & (0x3333)); t = (t & (0x0f0f)) + ((t >> 4) & (0x0f0f)); t = (t & (0x00ff)) + ((t >> 8) & (0x00ff)); return t; } static inline int Abc_Tt4FirstBit( int t ) { int n = 0; if ( t == 0 ) return -1; if ( (t & 0x00FF) == 0 ) { n += 8; t >>= 8; } if ( (t & 0x000F) == 0 ) { n += 4; t >>= 4; } if ( (t & 0x0003) == 0 ) { n += 2; t >>= 2; } if ( (t & 0x0001) == 0 ) { n++; } return n; } static inline int Abc_Tt4Check( int t ) { int Count, tn = 0xFFFF & ~t; if ( t == 0x6996 || tn == 0x6996 ) return 1; if ( (t & (t-1)) == 0 ) return 1; if ( (tn & (tn-1)) == 0 ) return 1; Count = Abc_Tt4CountOnes( t ); if ( Count == 7 && Abc_Tt4CheckTwoLevel(t) > 0 ) return 1; if ( Count == 9 && Abc_Tt4CheckTwoLevel(tn) > 0 ) return 1; return 0; } /*=== utilTruth.c ===========================================================*/ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/util/util_hack.h000066400000000000000000000022321300674244400240570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [util_hack.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [This file is used to simulate the presence of "util.h".] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: util_hack.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__util__util_hack_h #define ABC__misc__util__util_hack_h #include #include #include #include #include #include "abc_global.h" ABC_NAMESPACE_HEADER_START #define NIL(type) ((type *) 0) #define util_cpu_time Extra_CpuTime #define getSoftDataLimit Extra_GetSoftDataLimit #define MMoutOfMemory Extra_UtilMMoutOfMemory extern abctime Extra_CpuTime(); extern int Extra_GetSoftDataLimit(); extern void (*Extra_UtilMMoutOfMemory)( long size ); ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/000077500000000000000000000000001300674244400215445ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/module.make000066400000000000000000000000101300674244400236570ustar00rootroot00000000000000SRC += berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vec.h000066400000000000000000000042071300674244400224750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vec.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vec_h #define ABC__misc__vec__vec_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/util/abc_global.h" #include "vecInt.h" #include "vecFlt.h" #include "vecStr.h" #include "vecPtr.h" #include "vecVec.h" #include "vecAtt.h" #include "vecWrd.h" #include "vecBit.h" #include "vecMem.h" #include "vecWec.h" //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecAtt.h000066400000000000000000000204601300674244400231450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecAtt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Array of user-specified attiributes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecAtt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecAtt_h #define ABC__misc__vec__vecAtt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // various attributes typedef enum { VEC_ATTR_NONE = 0, // 0 VEC_ATTR_COPY, // 1 VEC_ATTR_LOCAL_AIG, // 2 VEC_ATTR_LOCAL_SOP, // 3 VEC_ATTR_LOCAL_BDD, // 4 VEC_ATTR_GLOBAL_AIG, // 5 VEC_ATTR_GLOBAL_SOP, // 6 VEC_ATTR_GLOBAL_BDD, // 7 VEC_ATTR_LEVEL, // 8 VEC_ATTR_LEVEL_REV, // 9 VEC_ATTR_RETIME_LAG, // 10 VEC_ATTR_FRAIG, // 11 VEC_ATTR_MVVAR, // 12 VEC_ATTR_DATA1, // 13 VEC_ATTR_DATA2, // 14 VEC_ATTR_TOTAL_NUM // 15 } Vec_AttrType_t; //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Att_t_ Vec_Att_t; struct Vec_Att_t_ { // storage for attributes int nCap; // the size of array allocated // Removed pArrayInt as it's not 64-bit safe, it generates compiler // warnings, and it's unused. void ** pArrayPtr; // the pointer attribute array // attribute specific info void * pMan; // the manager for this attribute void (*pFuncFreeMan) (void *); // the procedure to free the manager void*(*pFuncStartObj)(void *); // the procedure to start one attribute void (*pFuncFreeObj) (void *, void *); // the procedure to free one attribute }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Att_t * Vec_AttAlloc( int nSize, void * pMan, void (*pFuncFreeMan) (void *), void*(*pFuncStartObj)(void *), void (*pFuncFreeObj) (void *, void *) ) { Vec_Att_t * p; p = ABC_ALLOC( Vec_Att_t, 1 ); memset( p, 0, sizeof(Vec_Att_t) ); p->pMan = pMan; p->pFuncFreeMan = pFuncFreeMan; p->pFuncStartObj = pFuncStartObj; p->pFuncFreeObj = pFuncFreeObj; p->nCap = nSize? nSize : 16; p->pArrayPtr = ABC_ALLOC( void *, p->nCap ); memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap ); return p; } /**Function************************************************************* Synopsis [Frees the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Vec_AttFree( Vec_Att_t * p, int fFreeMan ) { void * pMan; if ( p == NULL ) return NULL; // free the attributes of objects if ( p->pFuncFreeObj ) { int i; for ( i = 0; i < p->nCap; i++ ) if ( p->pArrayPtr[i] ) p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] ); } // free the memory manager pMan = fFreeMan? NULL : p->pMan; if ( p->pMan && fFreeMan ) p->pFuncFreeMan( p->pMan ); ABC_FREE( p->pArrayPtr ); ABC_FREE( p ); return pMan; } /**Function************************************************************* Synopsis [Clears the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_AttClear( Vec_Att_t * p ) { // free the attributes of objects if ( p->pFuncFreeObj ) { int i; if ( p->pFuncFreeObj ) for ( i = 0; i < p->nCap; i++ ) if ( p->pArrayPtr[i] ) p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] ); } memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap ); } /**Function************************************************************* Synopsis [Deletes one entry from the attribute manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_AttFreeEntry( Vec_Att_t * p, int i ) { if ( i >= p->nCap ) return; if ( p->pMan ) { if ( p->pArrayPtr[i] && p->pFuncFreeObj ) p->pFuncFreeObj( p->pMan, (void *)p->pArrayPtr[i] ); } p->pArrayPtr[i] = NULL; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_AttGrow( Vec_Att_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArrayPtr = ABC_REALLOC( void *, p->pArrayPtr, nCapMin ); memset( p->pArrayPtr + p->nCap, 0, sizeof(void *) * (nCapMin - p->nCap) ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [Writes the entry into its place.] Description [Only works if the manager is not defined.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_AttWriteEntry( Vec_Att_t * p, int i, void * pEntry ) { assert( p->pArrayPtr ); assert( p->pFuncStartObj == NULL ); if ( i >= p->nCap ) Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); p->pArrayPtr[i] = pEntry; } /**Function************************************************************* Synopsis [Returns the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Vec_AttEntry( Vec_Att_t * p, int i ) { assert( p->pArrayPtr ); if ( i >= p->nCap ) Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); if ( p->pArrayPtr[i] == NULL && p->pFuncStartObj ) p->pArrayPtr[i] = p->pFuncStartObj( p->pMan ); return p->pArrayPtr[i]; } /**Function************************************************************* Synopsis [Returns the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Vec_AttMan( Vec_Att_t * p ) { return p->pMan; } /**Function************************************************************* Synopsis [Returns the array of attributes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void ** Vec_AttArray( Vec_Att_t * p ) { return p->pArrayPtr; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecBit.h000066400000000000000000000377531300674244400231500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecBit.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable arrays of bits.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecBit.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecBit_h #define ABC__misc__vec__vecBit_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Bit_t_ Vec_Bit_t; struct Vec_Bit_t_ { int nCap; int nSize; int * pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Vec_BitForEachEntry( vVec, Entry, i ) \ for ( i = 0; (i < Vec_BitSize(vVec)) && (((Entry) = Vec_BitEntry(vVec, i)), 1); i++ ) #define Vec_BitForEachEntryStart( vVec, Entry, i, Start ) \ for ( i = Start; (i < Vec_BitSize(vVec)) && (((Entry) = Vec_BitEntry(vVec, i)), 1); i++ ) #define Vec_BitForEachEntryStop( vVec, Entry, i, Stop ) \ for ( i = 0; (i < Stop) && (((Entry) = Vec_BitEntry(vVec, i)), 1); i++ ) #define Vec_BitForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ for ( i = Start; (i < Stop) && (((Entry) = Vec_BitEntry(vVec, i)), 1); i++ ) #define Vec_BitForEachEntryReverse( vVec, pEntry, i ) \ for ( i = Vec_BitSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_BitEntry(vVec, i)), 1); i-- ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Bit_t * Vec_BitAlloc( int nCap ) { Vec_Bit_t * p; nCap = (nCap >> 5) + ((nCap & 31) > 0); p = ABC_ALLOC( Vec_Bit_t, 1 ); p->nSize = 0; p->nCap = nCap * 32; p->pArray = nCap? ABC_ALLOC( int, nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Bit_t * Vec_BitStart( int nSize ) { Vec_Bit_t * p; nSize = (nSize >> 5) + ((nSize & 31) > 0); p = Vec_BitAlloc( nSize * 32 ); p->nSize = nSize * 32; memset( p->pArray, 0, sizeof(int) * nSize ); return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Bit_t * Vec_BitStartFull( int nSize ) { Vec_Bit_t * p; nSize = (nSize >> 5) + ((nSize & 31) > 0); p = Vec_BitAlloc( nSize * 32 ); p->nSize = nSize * 32; memset( p->pArray, 0xff, sizeof(int) * nSize ); return p; } /**Function************************************************************* Synopsis [Duplicates the integer array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Bit_t * Vec_BitDup( Vec_Bit_t * pVec ) { Vec_Bit_t * p; assert( (pVec->nSize & 31) == 0 ); p = ABC_ALLOC( Vec_Bit_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nSize; p->pArray = p->nCap? ABC_ALLOC( int, p->nCap >> 5 ) : NULL; memcpy( p->pArray, pVec->pArray, sizeof(int) * (p->nCap >> 5) ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitFree( Vec_Bit_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitFreeP( Vec_Bit_t ** p ) { if ( *p == NULL ) return; ABC_FREE( (*p)->pArray ); ABC_FREE( (*p) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Vec_BitReleaseArray( Vec_Bit_t * p ) { int * pArray = p->pArray; p->nCap = 0; p->nSize = 0; p->pArray = NULL; return pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Vec_BitArray( Vec_Bit_t * p ) { return p->pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_BitSize( Vec_Bit_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_BitCap( Vec_Bit_t * p ) { return p->nCap; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_BitMemory( Vec_Bit_t * p ) { return !p ? 0.0 : 1.0 * sizeof(int) * p->nCap + sizeof(Vec_Bit_t); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_BitEntry( Vec_Bit_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return (p->pArray[i >> 5] >> (i & 31)) & 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitWriteEntry( Vec_Bit_t * p, int i, int Entry ) { assert( i >= 0 && i < p->nSize ); if ( Entry == 1 ) p->pArray[i >> 5] |= (1 << (i & 31)); else if ( Entry == 0 ) p->pArray[i >> 5] &= ~(1 << (i & 31)); else assert(0); } static inline int Vec_BitAddEntry( Vec_Bit_t * p, int i ) { if ( Vec_BitEntry(p, i) ) return 1; Vec_BitWriteEntry( p, i, 1 ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_BitEntryLast( Vec_Bit_t * p ) { assert( p->nSize > 0 ); return Vec_BitEntry( p, p->nSize-1 ); } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitGrow( Vec_Bit_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; nCapMin = (nCapMin >> 5) + ((nCapMin & 31) > 0); p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); assert( p->pArray ); p->nCap = nCapMin * 32; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitFill( Vec_Bit_t * p, int nSize, int Fill ) { int i; Vec_BitGrow( p, nSize ); nSize = (nSize >> 5) + ((nSize & 31) > 0); if ( Fill == 0 ) { for ( i = 0; i < nSize; i++ ) p->pArray[i] = 0; } else if ( Fill == 1 ) { for ( i = 0; i < nSize; i++ ) p->pArray[i] = ~0; } else assert( 0 ); p->nSize = nSize * 32; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitFillExtra( Vec_Bit_t * p, int nSize, int Fill ) { int i; if ( nSize <= p->nSize ) return; if ( nSize > 2 * p->nCap ) Vec_BitGrow( p, nSize ); else if ( nSize > p->nCap ) Vec_BitGrow( p, 2 * p->nCap ); assert( p->nSize < nSize ); if ( (p->nSize >> 5) == (nSize >> 5) ) { unsigned Mask = (~(~0 << (nSize-p->nSize)) << p->nSize); if ( Fill == 1 ) p->pArray[nSize >> 5] |= Mask; else if ( Fill == 0 ) p->pArray[nSize >> 5] &= ~Mask; else assert( 0 ); } else { unsigned Mask1 = (p->nSize & 31) ? ~0 << (p->nSize & 31) : 0; unsigned Mask2 = (nSize & 31) ? ~(~0 << (nSize & 31)) : 0; int w1 = (p->nSize >> 5); int w2 = (nSize >> 5); if ( Fill == 1 ) { p->pArray[w1] |= Mask1; p->pArray[w2] |= Mask2; for ( i = w1 + 1; i < w2; i++ ) p->pArray[i] = ~0; } else if ( Fill == 0 ) { p->pArray[w1] &= ~Mask1; p->pArray[w2] &= ~Mask2; for ( i = w1 + 1; i < w2; i++ ) p->pArray[i] = 0; } else assert( 0 ); } p->nSize = nSize; } /**Function************************************************************* Synopsis [Returns the entry even if the place not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_BitGetEntry( Vec_Bit_t * p, int i ) { Vec_BitFillExtra( p, i + 1, 0 ); return Vec_BitEntry( p, i ); } /**Function************************************************************* Synopsis [Inserts the entry even if the place does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitSetEntry( Vec_Bit_t * p, int i, int Entry ) { Vec_BitFillExtra( p, i + 1, 0 ); Vec_BitWriteEntry( p, i, Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitShrink( Vec_Bit_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitClear( Vec_Bit_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitPush( Vec_Bit_t * p, int Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_BitGrow( p, 16 ); else Vec_BitGrow( p, 2 * p->nCap ); } if ( Entry == 1 ) p->pArray[p->nSize >> 5] |= (1 << (p->nSize & 31)); else if ( Entry == 0 ) p->pArray[p->nSize >> 5] &= ~(1 << (p->nSize & 31)); else assert( 0 ); p->nSize++; } /**Function************************************************************* Synopsis [Returns the last entry and removes it from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_BitPop( Vec_Bit_t * p ) { int Entry; assert( p->nSize > 0 ); Entry = Vec_BitEntryLast( p ); p->nSize--; return Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_BitCountWord( 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); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_BitCount( Vec_Bit_t * p ) { unsigned * pArray = (unsigned *)p->pArray; int nWords = (p->nSize >> 5) + ((p->nSize & 31) > 0); int i, Counter = 0; if ( p->nSize & 31 ) { assert( nWords > 0 ); for ( i = 0; i < nWords-1; i++ ) Counter += Vec_BitCountWord( pArray[i] ); Counter += Vec_BitCountWord( pArray[i] & ~(~0 << (p->nSize & 31)) ); } else { for ( i = 0; i < nWords; i++ ) Counter += Vec_BitCountWord( pArray[i] ); } return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_BitReset( Vec_Bit_t * p ) { int i, nWords = (p->nSize >> 5) + ((p->nSize & 31) > 0); for ( i = 0; i < nWords; i++ ) p->pArray[i] = 0; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecFlt.h000066400000000000000000000474231300674244400231520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecFlt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable arrays of floats.] Author [Aaron P. Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecFlt_h #define ABC__misc__vec__vecFlt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Flt_t_ Vec_Flt_t; struct Vec_Flt_t_ { int nCap; int nSize; float * pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Vec_FltForEachEntry( vVec, Entry, i ) \ for ( i = 0; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) #define Vec_FltForEachEntryStart( vVec, Entry, i, Start ) \ for ( i = Start; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) #define Vec_FltForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ for ( i = Start; (i < Stop) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) #define Vec_FltForEachEntryReverse( vVec, pEntry, i ) \ for ( i = Vec_FltSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_FltEntry(vVec, i)), 1); i-- ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Flt_t * Vec_FltAlloc( int nCap ) { Vec_Flt_t * p; p = ABC_ALLOC( Vec_Flt_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( float, p->nCap ) : NULL; return p; } static inline Vec_Flt_t * Vec_FltAllocExact( int nCap ) { Vec_Flt_t * p; assert( nCap >= 0 ); p = ABC_ALLOC( Vec_Flt_t, 1 ); p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( float, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Flt_t * Vec_FltStart( int nSize ) { Vec_Flt_t * p; p = Vec_FltAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0, sizeof(float) * nSize ); return p; } static inline Vec_Flt_t * Vec_FltStartFull( int nSize ) { Vec_Flt_t * p; p = Vec_FltAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0xFF, sizeof(float) * nSize ); return p; } /**Function************************************************************* Synopsis [Creates the vector from a float array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Flt_t * Vec_FltAllocArray( float * pArray, int nSize ) { Vec_Flt_t * p; p = ABC_ALLOC( Vec_Flt_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = pArray; return p; } /**Function************************************************************* Synopsis [Creates the vector from a float array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Flt_t * Vec_FltAllocArrayCopy( float * pArray, int nSize ) { Vec_Flt_t * p; p = ABC_ALLOC( Vec_Flt_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = ABC_ALLOC( float, nSize ); memcpy( p->pArray, pArray, sizeof(float) * nSize ); return p; } /**Function************************************************************* Synopsis [Duplicates the float array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Flt_t * Vec_FltDup( Vec_Flt_t * pVec ) { Vec_Flt_t * p; p = ABC_ALLOC( Vec_Flt_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = p->nCap? ABC_ALLOC( float, p->nCap ) : NULL; memcpy( p->pArray, pVec->pArray, sizeof(float) * pVec->nSize ); return p; } /**Function************************************************************* Synopsis [Transfers the array into another vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Flt_t * Vec_FltDupArray( Vec_Flt_t * pVec ) { Vec_Flt_t * p; p = ABC_ALLOC( Vec_Flt_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = pVec->pArray; pVec->nSize = 0; pVec->nCap = 0; pVec->pArray = NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltZero( Vec_Flt_t * p ) { p->pArray = NULL; p->nSize = 0; p->nCap = 0; } static inline void Vec_FltErase( Vec_Flt_t * p ) { ABC_FREE( p->pArray ); p->nSize = 0; p->nCap = 0; } static inline void Vec_FltFree( Vec_Flt_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltFreeP( Vec_Flt_t ** p ) { if ( *p == NULL ) return; ABC_FREE( (*p)->pArray ); ABC_FREE( (*p) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float * Vec_FltReleaseArray( Vec_Flt_t * p ) { float * pArray = p->pArray; p->nCap = 0; p->nSize = 0; p->pArray = NULL; return pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float * Vec_FltArray( Vec_Flt_t * p ) { return p->pArray; } static inline float ** Vec_FltArrayP( Vec_Flt_t * p ) { return &p->pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_FltSize( Vec_Flt_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_FltCap( Vec_Flt_t * p ) { return p->nCap; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_FltMemory( Vec_Flt_t * p ) { return !p ? 0.0 : 1.0 * sizeof(float) * p->nCap + sizeof(Vec_Flt_t); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Vec_FltEntry( Vec_Flt_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } static inline float * Vec_FltEntryP( Vec_Flt_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray + i; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltWriteEntry( Vec_Flt_t * p, int i, float Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltAddToEntry( Vec_Flt_t * p, int i, float Addition ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] += Addition; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltUpdateEntry( Vec_Flt_t * p, int i, float Value ) { if ( Vec_FltEntry( p, i ) < Value ) Vec_FltWriteEntry( p, i, Value ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Vec_FltEntryLast( Vec_Flt_t * p ) { return p->pArray[p->nSize-1]; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltGrow( Vec_Flt_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( float, p->pArray, nCapMin ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltFill( Vec_Flt_t * p, int nSize, float Entry ) { int i; Vec_FltGrow( p, nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = Entry; p->nSize = nSize; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltFillExtra( Vec_Flt_t * p, int nSize, float Fill ) { int i; if ( nSize <= p->nSize ) return; if ( nSize > 2 * p->nCap ) Vec_FltGrow( p, nSize ); else if ( nSize > p->nCap ) Vec_FltGrow( p, 2 * p->nCap ); for ( i = p->nSize; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltShrink( Vec_Flt_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltClear( Vec_Flt_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltPush( Vec_Flt_t * p, float Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_FltGrow( p, 16 ); else Vec_FltGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltPushOrder( Vec_Flt_t * p, float Entry ) { int i; if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_FltGrow( p, 16 ); else Vec_FltGrow( p, 2 * p->nCap ); } p->nSize++; for ( i = p->nSize-2; i >= 0; i-- ) if ( p->pArray[i] > Entry ) p->pArray[i+1] = p->pArray[i]; else break; p->pArray[i+1] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_FltPushUnique( Vec_Flt_t * p, float Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Vec_FltPush( p, Entry ); return 0; } /**Function************************************************************* Synopsis [Returns the last entry and removes it from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Vec_FltPop( Vec_Flt_t * p ) { assert( p->nSize > 0 ); return p->pArray[--p->nSize]; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_FltFind( Vec_Flt_t * p, float Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return i; return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_FltRemove( Vec_Flt_t * p, float Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) break; if ( i == p->nSize ) return 0; assert( i < p->nSize ); for ( i++; i < p->nSize; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; return 1; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Vec_FltFindMax( Vec_Flt_t * p ) { int i; float Best; if ( p->nSize == 0 ) return 0; Best = p->pArray[0]; for ( i = 1; i < p->nSize; i++ ) if ( Best < p->pArray[i] ) Best = p->pArray[i]; return Best; } static inline float Vec_FltFindMin( Vec_Flt_t * p ) { int i; float Best; if ( p->nSize == 0 ) return 0; Best = p->pArray[0]; for ( i = 1; i < p->nSize; i++ ) if ( Best > p->pArray[i] ) Best = p->pArray[i]; return Best; } /**Function************************************************************* Synopsis [Checks if two vectors are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_FltEqual( Vec_Flt_t * p1, Vec_Flt_t * p2 ) { int i; if ( p1->nSize != p2->nSize ) return 0; for ( i = 0; i < p1->nSize; i++ ) if ( p1->pArray[i] != p2->pArray[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltPrint( Vec_Flt_t * vVec ) { int i; float Entry; printf( "Vector has %d entries: {", Vec_FltSize(vVec) ); Vec_FltForEachEntry( vVec, Entry, i ) printf( " %f", Entry ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Comparison procedure for two floats.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_FltSortCompare1( float * pp1, float * pp2 ) { // for some reason commenting out lines (as shown) led to crashing of the release version if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) // return 1; return 0; // } /**Function************************************************************* Synopsis [Comparison procedure for two floats.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_FltSortCompare2( float * pp1, float * pp2 ) { // for some reason commenting out lines (as shown) led to crashing of the release version if ( *pp1 > *pp2 ) return -1; if ( *pp1 < *pp2 ) // return 1; return 0; // } /**Function************************************************************* Synopsis [Sorting the entries by their value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_FltSort( Vec_Flt_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(float), (int (*)(const void *, const void *)) Vec_FltSortCompare2 ); else qsort( (void *)p->pArray, p->nSize, sizeof(float), (int (*)(const void *, const void *)) Vec_FltSortCompare1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecHash.h000066400000000000000000000221471300674244400233040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecHash.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Hashing integer pairs/triples into an integer.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecHash.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecHash_h #define ABC__misc__vec__vecHash_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Hash_IntObj_t_ Hash_IntObj_t; struct Hash_IntObj_t_ { int iData0; int iData1; int iData2; int iNext; }; typedef struct Hash_IntMan_t_ Hash_IntMan_t; struct Hash_IntMan_t_ { Vec_Int_t * vTable; // hash table Vec_Int_t * vObjs; // hash objects int nRefs; // reference counter for the manager }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline Hash_IntObj_t * Hash_IntObj( Hash_IntMan_t * p, int i ) { return i ? (Hash_IntObj_t *)Vec_IntEntryP(p->vObjs, 4*i) : NULL; } static inline int Hash_IntObjData0( Hash_IntMan_t * p, int i ) { return Hash_IntObj(p, i)->iData0; } static inline int Hash_IntObjData1( Hash_IntMan_t * p, int i ) { return Hash_IntObj(p, i)->iData1; } static inline int Hash_IntObjData2( Hash_IntMan_t * p, int i ) { return Hash_IntObj(p, i)->iData2; } static inline int Hash_Int2ObjInc( Hash_IntMan_t * p, int i ) { return Hash_IntObj(p, i)->iData2++; } static inline int Hash_Int2ObjDec( Hash_IntMan_t * p, int i ) { return --Hash_IntObj(p, i)->iData2; } static inline void Hash_Int2ObjSetData2( Hash_IntMan_t * p, int i, int d ) { Hash_IntObj(p, i)->iData2 = d; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Hashes pairs of intergers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hash_IntMan_t * Hash_IntManStart( int nSize ) { Hash_IntMan_t * p; nSize += 100; p = ABC_CALLOC( Hash_IntMan_t, 1 ); p->vTable = Vec_IntStart( Abc_PrimeCudd(nSize) ); p->vObjs = Vec_IntAlloc( 4*nSize ); Vec_IntFill( p->vObjs, 4, 0 ); p->nRefs = 1; return p; } static inline void Hash_IntManStop( Hash_IntMan_t * p ) { Vec_IntFree( p->vObjs ); Vec_IntFree( p->vTable ); ABC_FREE( p ); } static inline Hash_IntMan_t * Hash_IntManRef( Hash_IntMan_t * p ) { p->nRefs++; return p; } static inline void Hash_IntManDeref( Hash_IntMan_t * p ) { if ( p == NULL ) return; if ( --p->nRefs == 0 ) Hash_IntManStop( p ); } static inline int Hash_IntManEntryNum( Hash_IntMan_t * p ) { return Vec_IntSize(p->vObjs)/4 - 1; } static inline void Hash_IntManProfile( Hash_IntMan_t * p ) { Hash_IntObj_t * pObj; int i, Count, Entry; Vec_IntForEachEntry( p->vTable, Entry, i ) { Count = 0; for ( pObj = Hash_IntObj( p, Entry ); pObj; pObj = Hash_IntObj( p, pObj->iNext ) ) Count++; printf( "%d ", Count ); } printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hash_Int2ManHash( int iData0, int iData1, int nTableSize ) { return (4177 * (unsigned)iData0 + 7873 * (unsigned)iData1) % (unsigned)nTableSize; } static inline int * Hash_Int2ManLookup( Hash_IntMan_t * p, int iData0, int iData1 ) { Hash_IntObj_t * pObj; int * pPlace = Vec_IntEntryP( p->vTable, Hash_Int2ManHash(iData0, iData1, Vec_IntSize(p->vTable)) ); for ( ; (pObj = Hash_IntObj(p, *pPlace)); pPlace = &pObj->iNext ) if ( pObj->iData0 == iData0 && pObj->iData1 == iData1 ) return pPlace; assert( *pPlace == 0 ); return pPlace; } static inline int Hash_Int2ManInsert( Hash_IntMan_t * p, int iData0, int iData1, int iData2 ) { Hash_IntObj_t * pObj; int i, nObjs, * pPlace; nObjs = Vec_IntSize(p->vObjs)/4; if ( nObjs > Vec_IntSize(p->vTable) ) { // printf( "Resizing...\n" ); Vec_IntFill( p->vTable, Abc_PrimeCudd(2*Vec_IntSize(p->vTable)), 0 ); for ( i = 1; i < nObjs; i++ ) { pObj = Hash_IntObj( p, i ); pObj->iNext = 0; pPlace = Hash_Int2ManLookup( p, pObj->iData0, pObj->iData1 ); assert( *pPlace == 0 ); *pPlace = i; } } pPlace = Hash_Int2ManLookup( p, iData0, iData1 ); if ( *pPlace ) return *pPlace; *pPlace = nObjs; Vec_IntPush( p->vObjs, iData0 ); Vec_IntPush( p->vObjs, iData1 ); Vec_IntPush( p->vObjs, iData2 ); Vec_IntPush( p->vObjs, 0 ); return nObjs; } /**Function************************************************************* Synopsis [Hashes triples of intergers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hsh_Int3ManHash( int iData0, int iData1, int iData2, int nTableSize ) { return (4177 * (unsigned)iData0 + 7873 * (unsigned)iData1 + 1699 * (unsigned)iData2) % (unsigned)nTableSize; } static inline int * Hsh_Int3ManLookup( Hash_IntMan_t * p, int iData0, int iData1, int iData2 ) { Hash_IntObj_t * pObj; int * pPlace = Vec_IntEntryP( p->vTable, Hsh_Int3ManHash(iData0, iData1, iData2, Vec_IntSize(p->vTable)) ); for ( ; (pObj = Hash_IntObj(p, *pPlace)); pPlace = &pObj->iNext ) if ( pObj->iData0 == iData0 && pObj->iData1 == iData1 && pObj->iData2 == iData2 ) return pPlace; assert( *pPlace == 0 ); return pPlace; } static inline int Hsh_Int3ManInsert( Hash_IntMan_t * p, int iData0, int iData1, int iData2 ) { Hash_IntObj_t * pObj; int i, nObjs, * pPlace; nObjs = Vec_IntSize(p->vObjs)/4; if ( nObjs > Vec_IntSize(p->vTable) ) { // printf( "Resizing...\n" ); Vec_IntFill( p->vTable, Abc_PrimeCudd(2*Vec_IntSize(p->vTable)), 0 ); for ( i = 1; i < nObjs; i++ ) { pObj = Hash_IntObj( p, i ); pObj->iNext = 0; pPlace = Hsh_Int3ManLookup( p, pObj->iData0, pObj->iData1, pObj->iData2 ); assert( *pPlace == 0 ); *pPlace = i; } } pPlace = Hsh_Int3ManLookup( p, iData0, iData1, iData2 ); if ( *pPlace ) return *pPlace; *pPlace = nObjs; Vec_IntPush( p->vObjs, iData0 ); Vec_IntPush( p->vObjs, iData1 ); Vec_IntPush( p->vObjs, iData2 ); Vec_IntPush( p->vObjs, 0 ); return nObjs; } /**Function************************************************************* Synopsis [Test procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hash_IntManHashArrayTest() { Hash_IntMan_t * p; int RetValue; p = Hash_IntManStart( 10 ); RetValue = Hash_Int2ManInsert( p, 10, 11, 12 ); assert( RetValue ); RetValue = Hash_Int2ManInsert( p, 20, 21, 22 ); assert( RetValue ); RetValue = Hash_Int2ManInsert( p, 10, 11, 12 ); assert( !RetValue ); Hash_IntManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecHsh.h000066400000000000000000000332221300674244400231370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecHsh.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Hashing vector entries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecHsh.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecHsh_h #define ABC__misc__vec__vecHsh_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Hsh_IntObj_t_ Hsh_IntObj_t; struct Hsh_IntObj_t_ { int iData; int iNext; }; typedef union Hsh_IntObjWord_t_ Hsh_IntObjWord_t; union Hsh_IntObjWord_t_ { Hsh_IntObj_t wObj; word wWord; }; typedef struct Hsh_IntMan_t_ Hsh_IntMan_t; struct Hsh_IntMan_t_ { int nSize; // data size Vec_Int_t * vData; // data storage Vec_Int_t * vTable; // hash table Vec_Wrd_t * vObjs; // hash objects }; typedef struct Hsh_VecObj_t_ Hsh_VecObj_t; struct Hsh_VecObj_t_ { int nSize; int iNext; int pArray[0]; }; typedef struct Hsh_VecMan_t_ Hsh_VecMan_t; struct Hsh_VecMan_t_ { Vec_Int_t * vTable; // hash table Vec_Int_t * vData; // data storage Vec_Int_t * vMap; // mapping entries into data; Vec_Int_t vTemp; // temporary array Vec_Int_t vTemp1; // temporary array Vec_Int_t vTemp2; // temporary array }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned * Hsh_IntData( Hsh_IntMan_t * p, int iData ) { return (unsigned *)Vec_IntEntryP( p->vData, p->nSize * iData ); } static inline Hsh_IntObj_t * Hsh_IntObj( Hsh_IntMan_t * p, int iObj ) { return iObj == -1 ? NULL : (Hsh_IntObj_t *)Vec_WrdEntryP( p->vObjs, iObj ); } static inline word Hsh_IntWord( int iData, int iNext ) { Hsh_IntObjWord_t Obj = { {iData, iNext} }; return Obj.wWord; } static inline Hsh_VecObj_t * Hsh_VecObj( Hsh_VecMan_t * p, int i ) { return i == -1 ? NULL : (Hsh_VecObj_t *)Vec_IntEntryP(p->vData, Vec_IntEntry(p->vMap, i)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Hashing data entries composed of nSize integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hsh_IntMan_t * Hsh_IntManStart( Vec_Int_t * vData, int nSize, int nEntries ) { Hsh_IntMan_t * p; p = ABC_CALLOC( Hsh_IntMan_t, 1 ); p->nSize = nSize; p->vData = vData; p->vTable = Vec_IntStartFull( Abc_PrimeCudd(nEntries) ); p->vObjs = Vec_WrdAlloc( nEntries ); return p; } static inline void Hsh_IntManStop( Hsh_IntMan_t * p ) { Vec_IntFree( p->vTable ); Vec_WrdFree( p->vObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hsh_IntManHash( unsigned * pData, int nSize, int nTableSize ) { static int s_Primes[7] = { 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; unsigned char * pDataC = (unsigned char *)pData; int c, nChars = nSize * 4; unsigned Key = 0; for ( c = 0; c < nChars; c++ ) Key += pDataC[c] * s_Primes[c % 7]; return (int)(Key % nTableSize); } static inline int * Hsh_IntManLookup( Hsh_IntMan_t * p, unsigned * pData ) { Hsh_IntObj_t * pObj; int * pPlace = Vec_IntEntryP( p->vTable, Hsh_IntManHash(pData, p->nSize, Vec_IntSize(p->vTable)) ); for ( ; (pObj = Hsh_IntObj(p, *pPlace)); pPlace = &pObj->iNext ) if ( !memcmp( pData, Hsh_IntData(p, pObj->iData), sizeof(int) * p->nSize ) ) return pPlace; assert( *pPlace == -1 ); return pPlace; } static inline int Hsh_IntManAdd( Hsh_IntMan_t * p, int iData ) { int i, * pPlace; if ( Vec_WrdSize(p->vObjs) > Vec_IntSize(p->vTable) ) { Vec_IntFill( p->vTable, Abc_PrimeCudd(2*Vec_IntSize(p->vTable)), -1 ); for ( i = 0; i < Vec_WrdSize(p->vObjs); i++ ) { pPlace = Vec_IntEntryP( p->vTable, Hsh_IntManHash(Hsh_IntData(p, i), p->nSize, Vec_IntSize(p->vTable)) ); Hsh_IntObj(p, i)->iNext = *pPlace; *pPlace = i; } } pPlace = Hsh_IntManLookup( p, Hsh_IntData(p, iData) ); if ( *pPlace == -1 ) { *pPlace = Vec_WrdSize(p->vObjs); Vec_WrdPush( p->vObjs, Hsh_IntWord(iData, -1) ); return Vec_WrdSize(p->vObjs) - 1; } return (word *)Hsh_IntObj(p, *pPlace) - Vec_WrdArray(p->vObjs); } /**Function************************************************************* Synopsis [Hashes data by value.] Description [Array vData contains data entries, each of 'nSize' integers. The resulting array contains the indexes of unique data entries.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Hsh_IntManHashArray( Vec_Int_t * vData, int nSize ) { Hsh_IntMan_t * p; Vec_Int_t * vRes = Vec_IntAlloc( 100 ); int i, nEntries = Vec_IntSize(vData) / nSize; assert( Vec_IntSize(vData) % nSize == 0 ); p = Hsh_IntManStart( vData, nSize, nEntries ); for ( i = 0; i < nEntries; i++ ) Vec_IntPush( vRes, Hsh_IntManAdd(p, i) ); Hsh_IntManStop( p ); return vRes; } static inline Vec_Int_t * Hsh_WrdManHashArray( Vec_Wrd_t * vDataW, int nSize ) { Hsh_IntMan_t * p; Vec_Int_t Data = { 2*Vec_WrdCap(vDataW), 2*Vec_WrdSize(vDataW), (int *)Vec_WrdArray(vDataW) }; Vec_Int_t * vData = &Data; Vec_Int_t * vRes = Vec_IntAlloc( 100 ); int i, nEntries = Vec_IntSize(vData) / (2*nSize); assert( Vec_IntSize(vData) % (2*nSize) == 0 ); p = Hsh_IntManStart( vData, (2*nSize), nEntries ); for ( i = 0; i < nEntries; i++ ) Vec_IntPush( vRes, Hsh_IntManAdd(p, i) ); Hsh_IntManStop( p ); return vRes; } static inline Hsh_IntMan_t * Hsh_WrdManHashArrayStart( Vec_Wrd_t * vDataW, int nSize ) { Hsh_IntMan_t * p; int i, nEntries = Vec_WrdSize(vDataW) / nSize; Vec_Int_t * vData = Vec_IntAlloc( 2*Vec_WrdSize(vDataW) ); memcpy( Vec_IntArray(vData), Vec_WrdArray(vDataW), sizeof(word)*Vec_WrdSize(vDataW) ); vData->nSize = 2*Vec_WrdSize(vDataW); /* for ( i = 0; i < 30; i++ ) { extern void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars ); Extra_PrintHex( stdout, (unsigned *) Vec_WrdEntryP(vDataW, i), 6 ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned *) Vec_WrdEntryP(vDataW, i), 6 ); printf( "\n" ); } */ assert( Vec_IntSize(vData) % (2*nSize) == 0 ); p = Hsh_IntManStart( vData, (2*nSize), nEntries ); for ( i = 0; i < nEntries; i++ ) Hsh_IntManAdd( p, i ); assert( Vec_WrdSize(p->vObjs) == nEntries ); return p; } /**Function************************************************************* Synopsis [Test procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hsh_IntManHashArrayTest() { Vec_Int_t * vData = Vec_IntAlloc( 10 ); Vec_Int_t * vRes; Vec_IntPush( vData, 12 ); Vec_IntPush( vData, 17 ); Vec_IntPush( vData, 13 ); Vec_IntPush( vData, 12 ); Vec_IntPush( vData, 15 ); Vec_IntPush( vData, 3 ); Vec_IntPush( vData, 16 ); Vec_IntPush( vData, 16 ); Vec_IntPush( vData, 12 ); Vec_IntPush( vData, 17 ); Vec_IntPush( vData, 12 ); Vec_IntPush( vData, 12 ); vRes = Hsh_IntManHashArray( vData, 2 ); Vec_IntPrint( vData ); Vec_IntPrint( vRes ); Vec_IntFree( vData ); Vec_IntFree( vRes ); } /**Function************************************************************* Synopsis [Hashing integer arrays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Hsh_VecMan_t * Hsh_VecManStart( int nEntries ) { Hsh_VecMan_t * p; p = ABC_CALLOC( Hsh_VecMan_t, 1 ); p->vTable = Vec_IntStartFull( Abc_PrimeCudd(nEntries) ); p->vData = Vec_IntAlloc( nEntries * 4 ); p->vMap = Vec_IntAlloc( nEntries ); return p; } static inline void Hsh_VecManStop( Hsh_VecMan_t * p ) { Vec_IntFree( p->vTable ); Vec_IntFree( p->vData ); Vec_IntFree( p->vMap ); ABC_FREE( p ); } static inline int * Hsh_VecReadArray( Hsh_VecMan_t * p, int i ) { return (int*)Hsh_VecObj(p, i) + 2; } static inline Vec_Int_t * Hsh_VecReadEntry( Hsh_VecMan_t * p, int i ) { Hsh_VecObj_t * pObj = Hsh_VecObj( p, i ); p->vTemp.nSize = p->vTemp.nCap = pObj->nSize; p->vTemp.pArray = (int*)pObj + 2; return &p->vTemp; } static inline Vec_Int_t * Hsh_VecReadEntry1( Hsh_VecMan_t * p, int i ) { Hsh_VecObj_t * pObj = Hsh_VecObj( p, i ); p->vTemp1.nSize = p->vTemp1.nCap = pObj->nSize; p->vTemp1.pArray = (int*)pObj + 2; return &p->vTemp1; } static inline Vec_Int_t * Hsh_VecReadEntry2( Hsh_VecMan_t * p, int i ) { Hsh_VecObj_t * pObj = Hsh_VecObj( p, i ); p->vTemp2.nSize = p->vTemp2.nCap = pObj->nSize; p->vTemp2.pArray = (int*)pObj + 2; return &p->vTemp2; } static inline int Hsh_VecSize( Hsh_VecMan_t * p ) { return Vec_IntSize(p->vMap); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hsh_VecManHash( Vec_Int_t * vVec, int nTableSize ) { static unsigned s_Primes[7] = {4177, 5147, 5647, 6343, 7103, 7873, 8147}; unsigned Key = 0; int i, Entry; Vec_IntForEachEntry( vVec, Entry, i ) Key += (unsigned)Entry * s_Primes[i % 7]; return (int)(Key % nTableSize); } static inline int Hsh_VecManAdd( Hsh_VecMan_t * p, Vec_Int_t * vVec ) { Hsh_VecObj_t * pObj; int i, Ent, * pPlace; if ( Vec_IntSize(p->vMap) > Vec_IntSize(p->vTable) ) { Vec_IntFill( p->vTable, Abc_PrimeCudd(2*Vec_IntSize(p->vTable)), -1 ); for ( i = 0; i < Vec_IntSize(p->vMap); i++ ) { pPlace = Vec_IntEntryP( p->vTable, Hsh_VecManHash(Hsh_VecReadEntry(p, i), Vec_IntSize(p->vTable)) ); Hsh_VecObj(p, i)->iNext = *pPlace; *pPlace = i; } } pPlace = Vec_IntEntryP( p->vTable, Hsh_VecManHash(vVec, Vec_IntSize(p->vTable)) ); for ( ; (pObj = Hsh_VecObj(p, *pPlace)); pPlace = &pObj->iNext ) if ( pObj->nSize == Vec_IntSize(vVec) && !memcmp( pObj->pArray, Vec_IntArray(vVec), sizeof(int) * pObj->nSize ) ) return *pPlace; *pPlace = Vec_IntSize(p->vMap); assert( Vec_IntSize(p->vData) % 2 == 0 ); Vec_IntPush( p->vMap, Vec_IntSize(p->vData) ); Vec_IntPush( p->vData, Vec_IntSize(vVec) ); Vec_IntPush( p->vData, -1 ); Vec_IntForEachEntry( vVec, Ent, i ) Vec_IntPush( p->vData, Ent ); if ( Vec_IntSize(vVec) & 1 ) Vec_IntPush( p->vData, -1 ); return Vec_IntSize(p->vMap) - 1; } /**Function************************************************************* Synopsis [Test procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Hsh_VecManHashTest() { Hsh_VecMan_t * p; Vec_Int_t * vTemp; Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); int i; p = Hsh_VecManStart( 5 ); for ( i = 0; i < 20; i++ ) { vTemp = Vec_IntStartNatural( i ); Vec_IntPush( vRes, Hsh_VecManAdd( p, vTemp ) ); Vec_IntFree( vTemp ); } for ( ; i > 0; i-- ) { vTemp = Vec_IntStartNatural( i ); Vec_IntPush( vRes, Hsh_VecManAdd( p, vTemp ) ); Vec_IntFree( vTemp ); } Vec_IntPrint( vRes ); Vec_IntFree( vRes ); Hsh_VecManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecInt.h000066400000000000000000001570151300674244400231560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable arrays of integers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecInt_h #define ABC__misc__vec__vecInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Int_t_ Vec_Int_t; struct Vec_Int_t_ { int nCap; int nSize; int * pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Vec_IntForEachEntry( vVec, Entry, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) #define Vec_IntForEachEntryStart( vVec, Entry, i, Start ) \ for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) #define Vec_IntForEachEntryStop( vVec, Entry, i, Stop ) \ for ( i = 0; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) #define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) #define Vec_IntForEachEntryReverse( vVec, pEntry, i ) \ for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- ) #define Vec_IntForEachEntryTwo( vVec1, vVec2, Entry1, Entry2, i ) \ for ( i = 0; (i < Vec_IntSize(vVec1)) && (((Entry1) = Vec_IntEntry(vVec1, i)), 1) && (((Entry2) = Vec_IntEntry(vVec2, i)), 1); i++ ) #define Vec_IntForEachEntryDouble( vVec, Entry1, Entry2, i ) \ for ( i = 0; (i+1 < Vec_IntSize(vVec)) && (((Entry1) = Vec_IntEntry(vVec, i)), 1) && (((Entry2) = Vec_IntEntry(vVec, i+1)), 1); i += 2 ) #define Vec_IntForEachEntryDoubleStart( vVec, Entry1, Entry2, i, Start ) \ for ( i = Start; (i+1 < Vec_IntSize(vVec)) && (((Entry1) = Vec_IntEntry(vVec, i)), 1) && (((Entry2) = Vec_IntEntry(vVec, i+1)), 1); i += 2 ) #define Vec_IntForEachEntryTriple( vVec, Entry1, Entry2, Entry3, i ) \ for ( i = 0; (i+2 < Vec_IntSize(vVec)) && (((Entry1) = Vec_IntEntry(vVec, i)), 1) && (((Entry2) = Vec_IntEntry(vVec, i+1)), 1) && (((Entry3) = Vec_IntEntry(vVec, i+2)), 1); i += 3 ) #define Vec_IntForEachEntryThisNext( vVec, This, Next, i ) \ for ( i = 0, (This) = (Next) = (Vec_IntSize(vVec) ? Vec_IntEntry(vVec, 0) : -1); (i+1 < Vec_IntSize(vVec)) && (((Next) = Vec_IntEntry(vVec, i+1)), 1); i += 2, (This) = (Next) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntAlloc( int nCap ) { Vec_Int_t * p; p = ABC_ALLOC( Vec_Int_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL; return p; } static inline Vec_Int_t * Vec_IntAllocExact( int nCap ) { Vec_Int_t * p; assert( nCap >= 0 ); p = ABC_ALLOC( Vec_Int_t, 1 ); p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntStart( int nSize ) { Vec_Int_t * p; p = Vec_IntAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0, sizeof(int) * nSize ); return p; } static inline Vec_Int_t * Vec_IntStartFull( int nSize ) { Vec_Int_t * p; p = Vec_IntAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0xff, sizeof(int) * nSize ); return p; } static inline Vec_Int_t * Vec_IntStartRange( int First, int Range ) { Vec_Int_t * p; int i; p = Vec_IntAlloc( Range ); p->nSize = Range; for ( i = 0; i < Range; i++ ) p->pArray[i] = First + i; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntStartNatural( int nSize ) { Vec_Int_t * p; int i; p = Vec_IntAlloc( nSize ); p->nSize = nSize; for ( i = 0; i < nSize; i++ ) p->pArray[i] = i; return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize ) { Vec_Int_t * p; p = ABC_ALLOC( Vec_Int_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = pArray; return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntAllocArrayCopy( int * pArray, int nSize ) { Vec_Int_t * p; p = ABC_ALLOC( Vec_Int_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = ABC_ALLOC( int, nSize ); memcpy( p->pArray, pArray, sizeof(int) * nSize ); return p; } /**Function************************************************************* Synopsis [Duplicates the integer array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec ) { Vec_Int_t * p; p = ABC_ALLOC( Vec_Int_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nSize; p->pArray = p->nCap? ABC_ALLOC( int, p->nCap ) : NULL; memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize ); return p; } /**Function************************************************************* Synopsis [Transfers the array into another vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntDupArray( Vec_Int_t * pVec ) { Vec_Int_t * p; p = ABC_ALLOC( Vec_Int_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = pVec->pArray; pVec->nSize = 0; pVec->nCap = 0; pVec->pArray = NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntZero( Vec_Int_t * p ) { p->pArray = NULL; p->nSize = 0; p->nCap = 0; } static inline void Vec_IntErase( Vec_Int_t * p ) { ABC_FREE( p->pArray ); p->nSize = 0; p->nCap = 0; } static inline void Vec_IntFree( Vec_Int_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntFreeP( Vec_Int_t ** p ) { if ( *p == NULL ) return; ABC_FREE( (*p)->pArray ); ABC_FREE( (*p) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Vec_IntReleaseArray( Vec_Int_t * p ) { int * pArray = p->pArray; p->nCap = 0; p->nSize = 0; p->pArray = NULL; return pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Vec_IntArray( Vec_Int_t * p ) { return p->pArray; } static inline int ** Vec_IntArrayP( Vec_Int_t * p ) { return &p->pArray; } static inline int * Vec_IntLimit( Vec_Int_t * p ) { return p->pArray + p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntSize( Vec_Int_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntCap( Vec_Int_t * p ) { return p->nCap; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_IntMemory( Vec_Int_t * p ) { return !p ? 0.0 : 1.0 * sizeof(int) * p->nCap + sizeof(Vec_Int_t) ; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntEntry( Vec_Int_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Vec_IntEntryP( Vec_Int_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray + i; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i] += Addition; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntUpdateEntry( Vec_Int_t * p, int i, int Value ) { if ( Vec_IntEntry( p, i ) < Value ) Vec_IntWriteEntry( p, i, Value ); } static inline void Vec_IntDowndateEntry( Vec_Int_t * p, int i, int Value ) { if ( Vec_IntEntry( p, i ) > Value ) Vec_IntWriteEntry( p, i, Value ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntEntryLast( Vec_Int_t * p ) { assert( p->nSize > 0 ); return p->pArray[p->nSize-1]; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); assert( p->pArray ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntGrowResize( Vec_Int_t * p, int nCapMin ) { p->nSize = nCapMin; if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( int, p->pArray, nCapMin ); assert( p->pArray ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Fill ) { int i; Vec_IntGrow( p, nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } static inline void Vec_IntFillTwo( Vec_Int_t * p, int nSize, int FillEven, int FillOdd ) { int i; Vec_IntGrow( p, nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = (i & 1) ? FillOdd : FillEven; p->nSize = nSize; } static inline void Vec_IntFillNatural( Vec_Int_t * p, int nSize ) { int i; Vec_IntGrow( p, nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = i; p->nSize = nSize; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Fill ) { int i; if ( nSize <= p->nSize ) return; if ( nSize > 2 * p->nCap ) Vec_IntGrow( p, nSize ); else if ( nSize > p->nCap ) Vec_IntGrow( p, 2 * p->nCap ); for ( i = p->nSize; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } /**Function************************************************************* Synopsis [Returns the entry even if the place not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntGetEntry( Vec_Int_t * p, int i ) { Vec_IntFillExtra( p, i + 1, 0 ); return Vec_IntEntry( p, i ); } static inline int Vec_IntGetEntryFull( Vec_Int_t * p, int i ) { Vec_IntFillExtra( p, i + 1, -1 ); return Vec_IntEntry( p, i ); } /**Function************************************************************* Synopsis [Returns the entry even if the place not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Vec_IntGetEntryP( Vec_Int_t * p, int i ) { Vec_IntFillExtra( p, i + 1, 0 ); return Vec_IntEntryP( p, i ); } /**Function************************************************************* Synopsis [Inserts the entry even if the place does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntSetEntry( Vec_Int_t * p, int i, int Entry ) { Vec_IntFillExtra( p, i + 1, 0 ); Vec_IntWriteEntry( p, i, Entry ); } static inline void Vec_IntSetEntryFull( Vec_Int_t * p, int i, int Entry ) { Vec_IntFillExtra( p, i + 1, -1 ); Vec_IntWriteEntry( p, i, Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntClear( Vec_Int_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_IntGrow( p, 16 ); else Vec_IntGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } static inline void Vec_IntPushTwo( Vec_Int_t * p, int Entry1, int Entry2 ) { Vec_IntPush( p, Entry1 ); Vec_IntPush( p, Entry2 ); } static inline void Vec_IntPushThree( Vec_Int_t * p, int Entry1, int Entry2, int Entry3 ) { Vec_IntPush( p, Entry1 ); Vec_IntPush( p, Entry2 ); Vec_IntPush( p, Entry3 ); } static inline void Vec_IntPushFour( Vec_Int_t * p, int Entry1, int Entry2, int Entry3, int Entry4 ) { Vec_IntPush( p, Entry1 ); Vec_IntPush( p, Entry2 ); Vec_IntPush( p, Entry3 ); Vec_IntPush( p, Entry4 ); } static inline void Vec_IntPushArray( Vec_Int_t * p, int * pEntries, int nEntries ) { int i; for ( i = 0; i < nEntries; i++ ) Vec_IntPush( p, pEntries[i] ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry ) { int i; if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_IntGrow( p, 16 ); else Vec_IntGrow( p, 2 * p->nCap ); } p->nSize++; for ( i = p->nSize - 1; i >= 1; i-- ) p->pArray[i] = p->pArray[i-1]; p->pArray[0] = Entry; } /**Function************************************************************* Synopsis [Inserts the entry while preserving the increasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry ) { int i; if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_IntGrow( p, 16 ); else Vec_IntGrow( p, 2 * p->nCap ); } p->nSize++; for ( i = p->nSize-2; i >= 0; i-- ) if ( p->pArray[i] > Entry ) p->pArray[i+1] = p->pArray[i]; else break; p->pArray[i+1] = Entry; } static inline void Vec_IntPushOrderCost( Vec_Int_t * p, int Entry, Vec_Int_t * vCost ) { int i; if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_IntGrow( p, 16 ); else Vec_IntGrow( p, 2 * p->nCap ); } p->nSize++; for ( i = p->nSize-2; i >= 0; i-- ) if ( Vec_IntEntry(vCost, p->pArray[i]) > Vec_IntEntry(vCost, Entry) ) p->pArray[i+1] = p->pArray[i]; else break; p->pArray[i+1] = Entry; } /**Function************************************************************* Synopsis [Inserts the entry while preserving the increasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntPushOrderReverse( Vec_Int_t * p, int Entry ) { int i; if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_IntGrow( p, 16 ); else Vec_IntGrow( p, 2 * p->nCap ); } p->nSize++; for ( i = p->nSize-2; i >= 0; i-- ) if ( p->pArray[i] < Entry ) p->pArray[i+1] = p->pArray[i]; else break; p->pArray[i+1] = Entry; } /**Function************************************************************* Synopsis [Inserts the entry while preserving the increasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Vec_IntPushOrder( p, Entry ); return 0; } static inline int Vec_IntPushUniqueOrderCost( Vec_Int_t * p, int Entry, Vec_Int_t * vCost ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Vec_IntPushOrderCost( p, Entry, vCost ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Vec_IntPush( p, Entry ); return 0; } /**Function************************************************************* Synopsis [Returns the pointer to the next nWords entries in the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned * Vec_IntFetch( Vec_Int_t * p, int nWords ) { if ( nWords == 0 ) return NULL; assert( nWords > 0 ); p->nSize += nWords; if ( p->nSize > p->nCap ) { // Vec_IntGrow( p, 2 * p->nSize ); return NULL; } return ((unsigned *)p->pArray) + p->nSize - nWords; } /**Function************************************************************* Synopsis [Returns the last entry and removes it from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntPop( Vec_Int_t * p ) { assert( p->nSize > 0 ); return p->pArray[--p->nSize]; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntFind( Vec_Int_t * p, int Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return i; return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntRemove( Vec_Int_t * p, int Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) break; if ( i == p->nSize ) return 0; assert( i < p->nSize ); for ( i++; i < p->nSize; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; return 1; } static inline int Vec_IntRemove1( Vec_Int_t * p, int Entry ) { int i; for ( i = 1; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) break; if ( i >= p->nSize ) return 0; assert( i < p->nSize ); for ( i++; i < p->nSize; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntDrop( Vec_Int_t * p, int i ) { int k; assert( i >= 0 && i < Vec_IntSize(p) ); p->nSize--; for ( k = i; k < p->nSize; k++ ) p->pArray[k] = p->pArray[k+1]; } /**Function************************************************************* Synopsis [Interts entry at the index iHere. Shifts other entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntInsert( Vec_Int_t * p, int iHere, int Entry ) { int i; assert( iHere >= 0 && iHere <= p->nSize ); Vec_IntPush( p, 0 ); for ( i = p->nSize - 1; i > iHere; i-- ) p->pArray[i] = p->pArray[i-1]; p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntFindMax( Vec_Int_t * p ) { int i, Best; if ( p->nSize == 0 ) return 0; Best = p->pArray[0]; for ( i = 1; i < p->nSize; i++ ) if ( Best < p->pArray[i] ) Best = p->pArray[i]; return Best; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntFindMin( Vec_Int_t * p ) { int i, Best; if ( p->nSize == 0 ) return 0; Best = p->pArray[0]; for ( i = 1; i < p->nSize; i++ ) if ( Best > p->pArray[i] ) Best = p->pArray[i]; return Best; } /**Function************************************************************* Synopsis [Reverses the order of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntReverseOrder( Vec_Int_t * p ) { int i, Temp; for ( i = 0; i < p->nSize/2; i++ ) { Temp = p->pArray[i]; p->pArray[i] = p->pArray[p->nSize-1-i]; p->pArray[p->nSize-1-i] = Temp; } } /**Function************************************************************* Synopsis [Removes odd entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntRemoveOdd( Vec_Int_t * p ) { int i; assert( (p->nSize & 1) == 0 ); p->nSize >>= 1; for ( i = 0; i < p->nSize; i++ ) p->pArray[i] = p->pArray[2*i]; } static inline void Vec_IntRemoveEven( Vec_Int_t * p ) { int i; assert( (p->nSize & 1) == 0 ); p->nSize >>= 1; for ( i = 0; i < p->nSize; i++ ) p->pArray[i] = p->pArray[2*i+1]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntInvert( Vec_Int_t * p, int Fill ) { int Entry, i; Vec_Int_t * vRes = Vec_IntAlloc( 0 ); if ( Vec_IntSize(p) == 0 ) return vRes; Vec_IntFill( vRes, Vec_IntFindMax(p) + 1, Fill ); Vec_IntForEachEntry( p, Entry, i ) if ( Entry != Fill ) Vec_IntWriteEntry( vRes, Entry, i ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntCondense( Vec_Int_t * p, int Fill ) { int Entry, i; Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(p) ); Vec_IntForEachEntry( p, Entry, i ) if ( Entry != Fill ) Vec_IntPush( vRes, Entry ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntSum( Vec_Int_t * p ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += p->pArray[i]; return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntCountEntry( Vec_Int_t * p, int Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] == Entry); return Counter; } static inline int Vec_IntCountLarger( Vec_Int_t * p, int Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] > Entry); return Counter; } static inline int Vec_IntCountSmaller( Vec_Int_t * p, int Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] < Entry); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntCountPositive( Vec_Int_t * p ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] > 0); return Counter; } static inline int Vec_IntCountZero( Vec_Int_t * p ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] == 0); return Counter; } /**Function************************************************************* Synopsis [Checks if two vectors are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntEqual( Vec_Int_t * p1, Vec_Int_t * p2 ) { int i; if ( p1->nSize != p2->nSize ) return 0; for ( i = 0; i < p1->nSize; i++ ) if ( p1->pArray[i] != p2->pArray[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Counts the number of common entries.] Description [Assumes that the entries are non-negative integers that are not very large, so inversion of the array can be performed.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntCountCommon( Vec_Int_t * p1, Vec_Int_t * p2 ) { Vec_Int_t * vTemp; int Entry, i, Counter = 0; if ( Vec_IntSize(p1) < Vec_IntSize(p2) ) vTemp = p1, p1 = p2, p2 = vTemp; assert( Vec_IntSize(p1) >= Vec_IntSize(p2) ); vTemp = Vec_IntInvert( p2, -1 ); Vec_IntFillExtra( vTemp, Vec_IntFindMax(p1) + 1, -1 ); Vec_IntForEachEntry( p1, Entry, i ) if ( Vec_IntEntry(vTemp, Entry) >= 0 ) Counter++; Vec_IntFree( vTemp ); return Counter; } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_IntSortCompare1( int * pp1, int * pp2 ) { // for some reason commenting out lines (as shown) led to crashing of the release version if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) // return 1; return 0; // } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_IntSortCompare2( int * pp1, int * pp2 ) { // for some reason commenting out lines (as shown) led to crashing of the release version if ( *pp1 > *pp2 ) return -1; if ( *pp1 < *pp2 ) // return 1; return 0; // } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntSort( Vec_Int_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(int), (int (*)(const void *, const void *)) Vec_IntSortCompare2 ); else qsort( (void *)p->pArray, p->nSize, sizeof(int), (int (*)(const void *, const void *)) Vec_IntSortCompare1 ); } static inline void Vec_IntSortMulti( Vec_Int_t * p, int nMulti, int fReverse ) { assert( Vec_IntSize(p) % nMulti == 0 ); if ( fReverse ) qsort( (void *)p->pArray, p->nSize/nMulti, nMulti*sizeof(int), (int (*)(const void *, const void *)) Vec_IntSortCompare2 ); else qsort( (void *)p->pArray, p->nSize/nMulti, nMulti*sizeof(int), (int (*)(const void *, const void *)) Vec_IntSortCompare1 ); } /**Function************************************************************* Synopsis [Leaves only unique entries.] Description [Returns the number of duplicated entried found.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntUniqify( Vec_Int_t * p ) { int i, k, RetValue; if ( p->nSize < 2 ) return 0; Vec_IntSort( p, 0 ); for ( i = k = 1; i < p->nSize; i++ ) if ( p->pArray[i] != p->pArray[i-1] ) p->pArray[k++] = p->pArray[i]; RetValue = p->nSize - k; p->nSize = k; return RetValue; } static inline int Vec_IntCountDuplicates( Vec_Int_t * p ) { int RetValue; Vec_Int_t * pDup = Vec_IntDup( p ); Vec_IntUniqify( pDup ); RetValue = Vec_IntSize(p) - Vec_IntSize(pDup); Vec_IntFree( pDup ); return RetValue; } static inline int Vec_IntCheckUniqueSmall( Vec_Int_t * p ) { int i, k; for ( i = 0; i < p->nSize; i++ ) for ( k = i+1; k < p->nSize; k++ ) if ( p->pArray[i] == p->pArray[k] ) return 0; return 1; } static inline int Vec_IntCountUnique( Vec_Int_t * p ) { int i, Count = 0, Max = Vec_IntFindMax(p); unsigned char * pPres = ABC_CALLOC( unsigned char, Max+1 ); for ( i = 0; i < p->nSize; i++ ) if ( pPres[p->pArray[i]] == 0 ) pPres[p->pArray[i]] = 1, Count++; ABC_FREE( pPres ); return Count; } /**Function************************************************************* Synopsis [Counts the number of unique pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntUniqifyPairs( Vec_Int_t * p ) { int i, k, RetValue; assert( p->nSize % 2 == 0 ); if ( p->nSize < 4 ) return 0; Vec_IntSortMulti( p, 2, 0 ); for ( i = k = 1; i < p->nSize/2; i++ ) if ( p->pArray[2*i] != p->pArray[2*(i-1)] || p->pArray[2*i+1] != p->pArray[2*(i-1)+1] ) { p->pArray[2*k] = p->pArray[2*i]; p->pArray[2*k+1] = p->pArray[2*i+1]; k++; } RetValue = p->nSize/2 - k; p->nSize = 2*k; return RetValue; } /**Function************************************************************* Synopsis [Counts the number of unique entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Vec_IntUniqueHashKeyDebug( unsigned char * pStr, int nChars, int TableMask ) { static unsigned s_BigPrimes[4] = {12582917, 25165843, 50331653, 100663319}; unsigned Key = 0; int c; for ( c = 0; c < nChars; c++ ) { Key += (unsigned)pStr[c] * s_BigPrimes[c & 3]; printf( "%d : ", c ); printf( "%3d ", pStr[c] ); printf( "%12u ", Key ); printf( "%12u ", Key&TableMask ); printf( "\n" ); } return Key; } static inline void Vec_IntUniqueProfile( Vec_Int_t * vData, int * pTable, int * pNexts, int TableMask, int nIntSize ) { int i, Key, Counter; for ( i = 0; i <= TableMask; i++ ) { Counter = 0; for ( Key = pTable[i]; Key != -1; Key = pNexts[Key] ) Counter++; if ( Counter < 7 ) continue; printf( "%d\n", Counter ); for ( Key = pTable[i]; Key != -1; Key = pNexts[Key] ) { // Extra_PrintBinary( stdout, (unsigned *)Vec_IntEntryP(vData, Key*nIntSize), 40 ), printf( "\n" ); // Vec_IntUniqueHashKeyDebug( (unsigned char *)Vec_IntEntryP(vData, Key*nIntSize), 4*nIntSize, TableMask ); } } printf( "\n" ); } static inline unsigned Vec_IntUniqueHashKey2( unsigned char * pStr, int nChars ) { static unsigned s_BigPrimes[4] = {12582917, 25165843, 50331653, 100663319}; unsigned Key = 0; int c; for ( c = 0; c < nChars; c++ ) Key += (unsigned)pStr[c] * s_BigPrimes[c & 3]; return Key; } static inline unsigned Vec_IntUniqueHashKey( unsigned char * pStr, int nChars ) { static unsigned s_BigPrimes[16] = { 0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55, 0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055 }; static unsigned s_BigPrimes2[16] = { 0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035, 0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10 }; unsigned Key = 0; int c; for ( c = 0; c < nChars; c++ ) Key += s_BigPrimes2[(2*c)&15] * s_BigPrimes[(unsigned)pStr[c] & 15] + s_BigPrimes2[(2*c+1)&15] * s_BigPrimes[(unsigned)pStr[c] >> 4]; return Key; } static inline int * Vec_IntUniqueLookup( Vec_Int_t * vData, int i, int nIntSize, int * pNexts, int * pStart ) { int * pData = Vec_IntEntryP( vData, i*nIntSize ); for ( ; *pStart != -1; pStart = pNexts + *pStart ) if ( !memcmp( pData, Vec_IntEntryP(vData, *pStart*nIntSize), sizeof(int) * nIntSize ) ) return pStart; return pStart; } static inline int Vec_IntUniqueCount( Vec_Int_t * vData, int nIntSize, Vec_Int_t ** pvMap ) { int nEntries = Vec_IntSize(vData) / nIntSize; int TableMask = (1 << Abc_Base2Log(nEntries)) - 1; int * pTable = ABC_FALLOC( int, TableMask+1 ); int * pNexts = ABC_FALLOC( int, TableMask+1 ); int * pClass = ABC_ALLOC( int, nEntries ); int i, Key, * pEnt, nUnique = 0; assert( nEntries * nIntSize == Vec_IntSize(vData) ); for ( i = 0; i < nEntries; i++ ) { pEnt = Vec_IntEntryP( vData, i*nIntSize ); Key = TableMask & Vec_IntUniqueHashKey( (unsigned char *)pEnt, 4*nIntSize ); pEnt = Vec_IntUniqueLookup( vData, i, nIntSize, pNexts, pTable+Key ); if ( *pEnt == -1 ) *pEnt = i, nUnique++; pClass[i] = *pEnt; } // Vec_IntUniqueProfile( vData, pTable, pNexts, TableMask, nIntSize ); ABC_FREE( pTable ); ABC_FREE( pNexts ); if ( pvMap ) *pvMap = Vec_IntAllocArray( pClass, nEntries ); else ABC_FREE( pClass ); return nUnique; } static inline Vec_Int_t * Vec_IntUniqifyHash( Vec_Int_t * vData, int nIntSize ) { Vec_Int_t * vMap, * vUnique; int i, Ent, nUnique = Vec_IntUniqueCount( vData, nIntSize, &vMap ); vUnique = Vec_IntAlloc( nUnique * nIntSize ); Vec_IntForEachEntry( vMap, Ent, i ) { if ( Ent < i ) continue; assert( Ent == i ); Vec_IntPushArray( vUnique, Vec_IntEntryP(vData, i*nIntSize), nIntSize ); } assert( Vec_IntSize(vUnique) == nUnique * nIntSize ); Vec_IntFree( vMap ); return vUnique; } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntSortCompareUnsigned( unsigned * pp1, unsigned * pp2 ) { if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntSortUnsigned( Vec_Int_t * p ) { qsort( (void *)p->pArray, p->nSize, sizeof(int), (int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned ); } /**Function************************************************************* Synopsis [Returns the number of common entries.] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) { int * pBeg1 = vArr1->pArray; int * pBeg2 = vArr2->pArray; int * pEnd1 = vArr1->pArray + vArr1->nSize; int * pEnd2 = vArr2->pArray + vArr2->nSize; int Counter = 0; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) pBeg1++, pBeg2++, Counter++; else if ( *pBeg1 < *pBeg2 ) pBeg1++; else pBeg2++; } return Counter; } /**Function************************************************************* Synopsis [Collects common entries.] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntTwoFindCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr ) { int * pBeg1 = vArr1->pArray; int * pBeg2 = vArr2->pArray; int * pEnd1 = vArr1->pArray + vArr1->nSize; int * pEnd2 = vArr2->pArray + vArr2->nSize; Vec_IntClear( vArr ); while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) Vec_IntPush( vArr, *pBeg1 ), pBeg1++, pBeg2++; else if ( *pBeg1 < *pBeg2 ) pBeg1++; else pBeg2++; } return Vec_IntSize(vArr); } /**Function************************************************************* Synopsis [Collects and removes common entries] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntTwoRemoveCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr ) { int * pBeg1 = vArr1->pArray; int * pBeg2 = vArr2->pArray; int * pEnd1 = vArr1->pArray + vArr1->nSize; int * pEnd2 = vArr2->pArray + vArr2->nSize; int * pBeg1New = vArr1->pArray; int * pBeg2New = vArr2->pArray; Vec_IntClear( vArr ); while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) Vec_IntPush( vArr, *pBeg1 ), pBeg1++, pBeg2++; else if ( *pBeg1 < *pBeg2 ) *pBeg1New++ = *pBeg1++; else *pBeg2New++ = *pBeg2++; } while ( pBeg1 < pEnd1 ) *pBeg1New++ = *pBeg1++; while ( pBeg2 < pEnd2 ) *pBeg2New++ = *pBeg2++; Vec_IntShrink( vArr1, pBeg1New - vArr1->pArray ); Vec_IntShrink( vArr2, pBeg2New - vArr2->pArray ); return Vec_IntSize(vArr); } /**Function************************************************************* Synopsis [Removes entries of the second one from the first one.] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntTwoRemove( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) { int * pBeg1 = vArr1->pArray; int * pBeg2 = vArr2->pArray; int * pEnd1 = vArr1->pArray + vArr1->nSize; int * pEnd2 = vArr2->pArray + vArr2->nSize; int * pBeg1New = vArr1->pArray; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) pBeg1++, pBeg2++; else if ( *pBeg1 < *pBeg2 ) *pBeg1New++ = *pBeg1++; else pBeg2++; } while ( pBeg1 < pEnd1 ) *pBeg1New++ = *pBeg1++; Vec_IntShrink( vArr1, pBeg1New - vArr1->pArray ); return Vec_IntSize(vArr1); } /**Function************************************************************* Synopsis [Returns the result of merging the two vectors.] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntTwoMerge2Int( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr ) { int * pBeg = vArr->pArray; int * pBeg1 = vArr1->pArray; int * pBeg2 = vArr2->pArray; int * pEnd1 = vArr1->pArray + vArr1->nSize; int * pEnd2 = vArr2->pArray + vArr2->nSize; 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++; vArr->nSize = pBeg - vArr->pArray; assert( vArr->nSize <= vArr->nCap ); assert( vArr->nSize >= vArr1->nSize ); assert( vArr->nSize >= vArr2->nSize ); } static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) { Vec_Int_t * vArr = Vec_IntAlloc( vArr1->nSize + vArr2->nSize ); Vec_IntTwoMerge2Int( vArr1, vArr2, vArr ); return vArr; } static inline void Vec_IntTwoMerge2( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr ) { Vec_IntGrow( vArr, Vec_IntSize(vArr1) + Vec_IntSize(vArr2) ); Vec_IntTwoMerge2Int( vArr1, vArr2, vArr ); } /**Function************************************************************* Synopsis [Returns the result of splitting of the two vectors.] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntTwoSplit( Vec_Int_t * vArr1, Vec_Int_t * vArr2, Vec_Int_t * vArr, Vec_Int_t * vArr1n, Vec_Int_t * vArr2n ) { int * pBeg1 = vArr1->pArray; int * pBeg2 = vArr2->pArray; int * pEnd1 = vArr1->pArray + vArr1->nSize; int * pEnd2 = vArr2->pArray + vArr2->nSize; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) Vec_IntPush( vArr, *pBeg1++ ), pBeg2++; else if ( *pBeg1 < *pBeg2 ) Vec_IntPush( vArr1n, *pBeg1++ ); else Vec_IntPush( vArr2n, *pBeg2++ ); } while ( pBeg1 < pEnd1 ) Vec_IntPush( vArr1n, *pBeg1++ ); while ( pBeg2 < pEnd2 ) Vec_IntPush( vArr2n, *pBeg2++ ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntSelectSort( int * pArray, int nSize ) { int temp, i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pArray[j] < pArray[best_i] ) best_i = j; temp = pArray[i]; pArray[i] = pArray[best_i]; pArray[best_i] = temp; } } static inline void Vec_IntSelectSortReverse( int * pArray, int nSize ) { int temp, i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pArray[j] > pArray[best_i] ) best_i = j; temp = pArray[i]; pArray[i] = pArray[best_i]; pArray[best_i] = temp; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntSelectSortCost( int * pArray, int nSize, Vec_Int_t * vCosts ) { 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, pArray[j]) < Vec_IntEntry(vCosts, pArray[best_i]) ) best_i = j; ABC_SWAP( int, pArray[i], pArray[best_i] ); } } static inline void Vec_IntSelectSortCostReverse( int * pArray, int nSize, Vec_Int_t * vCosts ) { 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, pArray[j]) > Vec_IntEntry(vCosts, pArray[best_i]) ) best_i = j; ABC_SWAP( int, pArray[i], pArray[best_i] ); } } static inline void Vec_IntSelectSortCost2( int * pArray, int nSize, int * pCosts ) { int i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pCosts[j] < pCosts[best_i] ) best_i = j; ABC_SWAP( int, pArray[i], pArray[best_i] ); ABC_SWAP( int, pCosts[i], pCosts[best_i] ); } } static inline void Vec_IntSelectSortCost2Reverse( int * pArray, int nSize, int * pCosts ) { int i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pCosts[j] > pCosts[best_i] ) best_i = j; ABC_SWAP( int, pArray[i], pArray[best_i] ); ABC_SWAP( int, pCosts[i], pCosts[best_i] ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntPrint( Vec_Int_t * vVec ) { int i, Entry; printf( "Vector has %d entries: {", Vec_IntSize(vVec) ); Vec_IntForEachEntry( vVec, Entry, i ) printf( " %d", Entry ); printf( " }\n" ); } static inline void Vec_IntPrintBinary( Vec_Int_t * vVec ) { int i, Entry; Vec_IntForEachEntry( vVec, Entry, i ) printf( "%d", (int)(Entry != 0) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntCompareVec( Vec_Int_t * p1, Vec_Int_t * p2 ) { if ( p1 == NULL || p2 == NULL ) return (p1 != NULL) - (p2 != NULL); if ( Vec_IntSize(p1) != Vec_IntSize(p2) ) return Vec_IntSize(p1) - Vec_IntSize(p2); return memcmp( Vec_IntArray(p1), Vec_IntArray(p2), sizeof(int)*Vec_IntSize(p1) ); } /**Function************************************************************* Synopsis [Appends the contents of the second vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 ) { int Entry, i; Vec_IntForEachEntry( vVec2, Entry, i ) Vec_IntPush( vVec1, Entry ); } static inline void Vec_IntAppendSkip( Vec_Int_t * vVec1, Vec_Int_t * vVec2, int iVar ) { int Entry, i; Vec_IntForEachEntry( vVec2, Entry, i ) if ( i != iVar ) Vec_IntPush( vVec1, Entry ); } static inline void Vec_IntAppendMinus( Vec_Int_t * vVec1, Vec_Int_t * vVec2, int fMinus ) { int Entry, i; Vec_IntClear( vVec1 ); Vec_IntForEachEntry( vVec2, Entry, i ) Vec_IntPush( vVec1, fMinus ? -Entry : Entry ); } /**Function************************************************************* Synopsis [Remapping attributes after objects were duplicated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntRemapArray( Vec_Int_t * vOld2New, Vec_Int_t * vOld, Vec_Int_t * vNew, int nNew ) { int iOld, iNew; if ( Vec_IntSize(vOld) == 0 ) return; Vec_IntFill( vNew, nNew, 0 ); Vec_IntForEachEntry( vOld2New, iNew, iOld ) if ( iNew > 0 && iNew < nNew && iOld < Vec_IntSize(vOld) && Vec_IntEntry(vOld, iOld) != 0 ) Vec_IntWriteEntry( vNew, iNew, Vec_IntEntry(vOld, iOld) ); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecMem.h000066400000000000000000000327431300674244400231420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecMem.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable array of memory pieces.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 20, 2012.] Revision [$Id: vecMem.h,v 1.00 2012/07/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecMem_h #define ABC__misc__vec__vecMem_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START /* This vector stores pieces of memory of the given size. It is useful for representing truth tables and any other objects of the fixed size. It is better that Extra_MmFixed because the entry IDs can be used as handles to retrieve memory pieces without the need for an array of pointers from entry IDs into memory pieces (this can save 8(4) bytes per object on a 64(32)-bit platform). */ //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Mem_t_ Vec_Mem_t; struct Vec_Mem_t_ { int nEntrySize; // entry size (in terms of 8-byte words) int nEntries; // number of entries currently used int LogPageSze; // log2 of page size (in terms of entries) int PageMask; // page mask int nPageAlloc; // number of pages currently allocated int iPage; // the number of a page currently used word ** ppPages; // memory pages Vec_Int_t * vTable; // hash table Vec_Int_t * vNexts; // next pointers }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Vec_MemForEachEntry( p, pEntry, i ) \ for ( i = 0; (i < Vec_MemEntryNum(p)) && ((pEntry) = Vec_MemReadEntry(p, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a memory vector.] Description [Entry size is in terms of 8-byte words. Page size is log2 of the number of entries on one page.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_MemAlloc_( Vec_Mem_t * p, int nEntrySize, int LogPageSze ) { memset( p, 0, sizeof(Vec_Mem_t) ); p->nEntrySize = nEntrySize; p->LogPageSze = LogPageSze; p->PageMask = (1 << p->LogPageSze) - 1; p->iPage = -1; } static inline Vec_Mem_t * Vec_MemAlloc( int nEntrySize, int LogPageSze ) { Vec_Mem_t * p; p = ABC_CALLOC( Vec_Mem_t, 1 ); p->nEntrySize = nEntrySize; p->LogPageSze = LogPageSze; p->PageMask = (1 << p->LogPageSze) - 1; p->iPage = -1; return p; } static inline void Vec_MemFree( Vec_Mem_t * p ) { int i; for ( i = 0; i <= p->iPage; i++ ) ABC_FREE( p->ppPages[i] ); ABC_FREE( p->ppPages ); ABC_FREE( p ); } static inline void Vec_MemFreeP( Vec_Mem_t ** p ) { if ( *p == NULL ) return; Vec_MemFree( *p ); *p = NULL; } static inline Vec_Mem_t * Vec_MemDup( Vec_Mem_t * pVec ) { Vec_Mem_t * p = NULL; return p; } /**Function************************************************************* Synopsis [Duplicates the integer array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_MemFill( Vec_Mem_t * pVec, int nEntries ) { } static inline void Vec_MemClean( Vec_Mem_t * pVec, int nEntries ) { } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_MemEntrySize( Vec_Mem_t * p ) { return p->nEntrySize; } static inline int Vec_MemEntryNum( Vec_Mem_t * p ) { return p->nEntries; } static inline int Vec_MemPageSize( Vec_Mem_t * p ) { return p->LogPageSze; } static inline int Vec_MemPageNum( Vec_Mem_t * p ) { return p->iPage+1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_MemMemory( Vec_Mem_t * p ) { return (double)sizeof(word) * p->nEntrySize * (1 << p->LogPageSze) * (p->iPage + 1) + (double)sizeof(word *) * p->nPageAlloc + (double)sizeof(Vec_Mem_t); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Vec_MemReadEntry( Vec_Mem_t * p, int i ) { assert( i >= 0 && i < p->nEntries ); return p->ppPages[i >> p->LogPageSze] + p->nEntrySize * (i & p->PageMask); } static inline word * Vec_MemReadEntryLast( Vec_Mem_t * p ) { assert( p->nEntries > 0 ); return Vec_MemReadEntry( p, p->nEntries-1 ); } static inline void Vec_MemWriteEntry( Vec_Mem_t * p, int i, word * pEntry ) { word * pPlace = Vec_MemReadEntry( p, i ); memmove( pPlace, pEntry, sizeof(word) * p->nEntrySize ); } static inline word * Vec_MemGetEntry( Vec_Mem_t * p, int i ) { assert( i >= 0 ); if ( i >= p->nEntries ) { int k, iPageNew = (i >> p->LogPageSze); if ( p->iPage < iPageNew ) { // realloc page pointers if needed if ( iPageNew >= p->nPageAlloc ) p->ppPages = ABC_REALLOC( word *, p->ppPages, (p->nPageAlloc = p->nPageAlloc ? 2 * p->nPageAlloc : iPageNew + 32) ); // allocate new pages if needed for ( k = p->iPage + 1; k <= iPageNew; k++ ) p->ppPages[k] = ABC_ALLOC( word, p->nEntrySize * (1 << p->LogPageSze) ); // update page counter p->iPage = iPageNew; } // update entry counter p->nEntries = i + 1; } return Vec_MemReadEntry( p, i ); } static inline void Vec_MemSetEntry( Vec_Mem_t * p, int i, word * pEntry ) { word * pPlace = Vec_MemGetEntry( p, i ); memmove( pPlace, pEntry, sizeof(word) * p->nEntrySize ); } static inline void Vec_MemPush( Vec_Mem_t * p, word * pEntry ) { word * pPlace = Vec_MemGetEntry( p, p->nEntries ); memmove( pPlace, pEntry, sizeof(word) * p->nEntrySize ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_MemShrink( Vec_Mem_t * p, int nEntriesNew ) { int i, iPageOld = p->iPage; assert( nEntriesNew <= p->nEntries ); p->nEntries = nEntriesNew; p->iPage = (nEntriesNew >> p->LogPageSze); for ( i = p->iPage + 1; i <= iPageOld; i++ ) ABC_FREE( p->ppPages[i] ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_MemDumpDigit( FILE * pFile, int HexDigit ) { assert( HexDigit >= 0 && HexDigit < 16 ); if ( HexDigit < 10 ) fprintf( pFile, "%d", HexDigit ); else fprintf( pFile, "%c", 'A' + HexDigit-10 ); } static inline void Vec_MemDump( FILE * pFile, Vec_Mem_t * pVec ) { word * pEntry; int i, w, d; if ( pFile == stdout ) printf( "Memory vector has %d entries: \n", Vec_MemEntryNum(pVec) ); Vec_MemForEachEntry( pVec, pEntry, i ) { for ( w = pVec->nEntrySize - 1; w >= 0; w-- ) for ( d = 15; d >= 0; d-- ) Vec_MemDumpDigit( pFile, (int)(pEntry[w] >> (d<<2)) & 15 ); fprintf( pFile, "\n" ); } } /**Function************************************************************* Synopsis [Hashing entries in the memory vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_MemHashAlloc( Vec_Mem_t * p, int nTableSize ) { assert( p->vTable == NULL && p->vNexts == NULL ); p->vTable = Vec_IntStartFull( Abc_PrimeCudd(nTableSize) ); p->vNexts = Vec_IntAlloc( nTableSize ); } static inline void Vec_MemHashFree( Vec_Mem_t * p ) { if ( p == NULL ) return; Vec_IntFreeP( &p->vTable ); Vec_IntFreeP( &p->vNexts ); } static inline unsigned Vec_MemHashKey( Vec_Mem_t * p, word * pEntry ) { static int s_Primes[8] = { 1699, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; int i, nData = 2 * p->nEntrySize; unsigned * pData = (unsigned *)pEntry; unsigned uHash = 0; for ( i = 0; i < nData; i++ ) uHash += pData[i] * s_Primes[i & 0x7]; return uHash % Vec_IntSize(p->vTable); } static int * Vec_MemHashLookup( Vec_Mem_t * p, word * pEntry ) { int * pSpot = Vec_IntEntryP( p->vTable, Vec_MemHashKey(p, pEntry) ); for ( ; *pSpot != -1; pSpot = Vec_IntEntryP(p->vNexts, *pSpot) ) if ( !memcmp( Vec_MemReadEntry(p, *pSpot), pEntry, sizeof(word) * p->nEntrySize ) ) // equal return pSpot; return pSpot; } static void Vec_MemHashResize( Vec_Mem_t * p ) { word * pEntry; int i, * pSpot; Vec_IntFill( p->vTable, Abc_PrimeCudd(2 * Vec_IntSize(p->vTable)), -1 ); Vec_IntClear( p->vNexts ); Vec_MemForEachEntry( p, pEntry, i ) { pSpot = Vec_MemHashLookup( p, pEntry ); assert( *pSpot == -1 ); *pSpot = Vec_IntSize(p->vNexts); Vec_IntPush( p->vNexts, -1 ); } assert( p->nEntries == Vec_IntSize(p->vNexts) ); } static int Vec_MemHashInsert( Vec_Mem_t * p, word * pEntry ) { int * pSpot; if ( p->nEntries > Vec_IntSize(p->vTable) ) Vec_MemHashResize( p ); pSpot = Vec_MemHashLookup( p, pEntry ); if ( *pSpot != -1 ) return *pSpot; *pSpot = Vec_IntSize(p->vNexts); Vec_IntPush( p->vNexts, -1 ); Vec_MemPush( p, pEntry ); assert( p->nEntries == Vec_IntSize(p->vNexts) ); return Vec_IntSize(p->vNexts) - 1; } /**Function************************************************************* Synopsis [Allocates memory vector for storing truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Mem_t * Vec_MemAllocForTT( int nVars, int fCompl ) { int Value, nWords = (nVars <= 6 ? 1 : (1 << (nVars - 6))); word * uTruth = ABC_ALLOC( word, nWords ); Vec_Mem_t * vTtMem = Vec_MemAlloc( nWords, 12 ); Vec_MemHashAlloc( vTtMem, 10000 ); memset( uTruth, 0x00, sizeof(word) * nWords ); Value = Vec_MemHashInsert( vTtMem, uTruth ); assert( Value == 0 ); if ( fCompl ) memset( uTruth, 0x55, sizeof(word) * nWords ); else memset( uTruth, 0xAA, sizeof(word) * nWords ); Value = Vec_MemHashInsert( vTtMem, uTruth ); assert( Value == 1 ); ABC_FREE( uTruth ); return vTtMem; } static inline void Vec_MemAddMuxTT( Vec_Mem_t * p, int nVars ) { int Value, nWords = (nVars <= 6 ? 1 : (1 << (nVars - 6))); word * uTruth = ABC_ALLOC( word, nWords ); memset( uTruth, 0xCA, sizeof(word) * nWords ); Value = Vec_MemHashInsert( p, uTruth ); assert( Value == 2 ); ABC_FREE( uTruth ); } static inline void Vec_MemDumpTruthTables( Vec_Mem_t * p, char * pName, int nLutSize ) { FILE * pFile; char pFileName[1000]; sprintf( pFileName, "tt_%s_%02d.txt", pName ? pName : NULL, nLutSize ); pFile = pName ? fopen( pFileName, "wb" ) : stdout; Vec_MemDump( pFile, p ); if ( pFile != stdout ) fclose( pFile ); printf( "Dumped %d %d-var truth tables into file \"%s\" (%.2f MB).\n", Vec_MemEntryNum(p), nLutSize, pName ? pFileName : "stdout", 8.0 * Vec_MemEntryNum(p) * Vec_MemEntrySize(p) / (1 << 20) ); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecPtr.h000066400000000000000000000744061300674244400231730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecPtr.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable arrays of generic pointers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecPtr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecPtr_h #define ABC__misc__vec__vecPtr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Ptr_t_ Vec_Ptr_t; struct Vec_Ptr_t_ { int nCap; int nSize; void ** pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // iterators through entries #define Vec_PtrForEachEntry( Type, vVec, pEntry, i ) \ for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i++ ) #define Vec_PtrForEachEntryStart( Type, vVec, pEntry, i, Start ) \ for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i++ ) #define Vec_PtrForEachEntryStop( Type, vVec, pEntry, i, Stop ) \ for ( i = 0; (i < Stop) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i++ ) #define Vec_PtrForEachEntryStartStop( Type, vVec, pEntry, i, Start, Stop ) \ for ( i = Start; (i < Stop) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i++ ) #define Vec_PtrForEachEntryReverse( Type, vVec, pEntry, i ) \ for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = (Type)Vec_PtrEntry(vVec, i)), 1); i-- ) #define Vec_PtrForEachEntryTwo( Type1, vVec1, Type2, vVec2, pEntry1, pEntry2, i ) \ for ( i = 0; (i < Vec_PtrSize(vVec1)) && (((pEntry1) = (Type1)Vec_PtrEntry(vVec1, i)), 1) && (((pEntry2) = (Type2)Vec_PtrEntry(vVec2, i)), 1); i++ ) #define Vec_PtrForEachEntryDouble( Type1, Type2, vVec, Entry1, Entry2, i ) \ for ( i = 0; (i+1 < Vec_IntSize(vVec)) && (((Entry1) = (Type1)Vec_PtrEntry(vVec, i)), 1) && (((Entry2) = (Type2)Vec_PtrEntry(vVec, i+1)), 1); i += 2 ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_PtrAlloc( int nCap ) { Vec_Ptr_t * p; p = ABC_ALLOC( Vec_Ptr_t, 1 ); if ( nCap > 0 && nCap < 8 ) nCap = 8; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( void *, p->nCap ) : NULL; return p; } static inline Vec_Ptr_t * Vec_PtrAllocExact( int nCap ) { Vec_Ptr_t * p; assert( nCap >= 0 ); p = ABC_ALLOC( Vec_Ptr_t, 1 ); p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( void *, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_PtrStart( int nSize ) { Vec_Ptr_t * p; p = Vec_PtrAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0, sizeof(void *) * nSize ); return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_PtrAllocArray( void ** pArray, int nSize ) { Vec_Ptr_t * p; p = ABC_ALLOC( Vec_Ptr_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = pArray; return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_PtrAllocArrayCopy( void ** pArray, int nSize ) { Vec_Ptr_t * p; p = ABC_ALLOC( Vec_Ptr_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = ABC_ALLOC( void *, nSize ); memcpy( p->pArray, pArray, sizeof(void *) * nSize ); return p; } /**Function************************************************************* Synopsis [Duplicates the integer array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_PtrDup( Vec_Ptr_t * pVec ) { Vec_Ptr_t * p; p = ABC_ALLOC( Vec_Ptr_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = p->nCap? ABC_ALLOC( void *, p->nCap ) : NULL; memcpy( p->pArray, pVec->pArray, sizeof(void *) * pVec->nSize ); return p; } static inline Vec_Ptr_t * Vec_PtrDupStr( Vec_Ptr_t * pVec ) { int i; Vec_Ptr_t * p = Vec_PtrDup( pVec ); for ( i = 0; i < p->nSize; i++ ) p->pArray[i] = Abc_UtilStrsav( (char *)p->pArray[i] ); return p; } /**Function************************************************************* Synopsis [Transfers the array into another vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_PtrDupArray( Vec_Ptr_t * pVec ) { Vec_Ptr_t * p; p = ABC_ALLOC( Vec_Ptr_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = pVec->pArray; pVec->nSize = 0; pVec->nCap = 0; pVec->pArray = NULL; return p; } /**Function************************************************************* Synopsis [Frees the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrZero( Vec_Ptr_t * p ) { p->pArray = NULL; p->nSize = 0; p->nCap = 0; } static inline void Vec_PtrErase( Vec_Ptr_t * p ) { ABC_FREE( p->pArray ); p->nSize = 0; p->nCap = 0; } static inline void Vec_PtrFree( Vec_Ptr_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrFreeP( Vec_Ptr_t ** p ) { if ( *p == NULL ) return; ABC_FREE( (*p)->pArray ); ABC_FREE( (*p) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void ** Vec_PtrReleaseArray( Vec_Ptr_t * p ) { void ** pArray = p->pArray; p->nCap = 0; p->nSize = 0; p->pArray = NULL; return pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void ** Vec_PtrArray( Vec_Ptr_t * p ) { return p->pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_PtrSize( Vec_Ptr_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_PtrCap( Vec_Ptr_t * p ) { return p->nCap; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_PtrMemory( Vec_Ptr_t * p ) { return !p ? 0.0 : 1.0 * sizeof(void *) * p->nCap + sizeof(Vec_Ptr_t); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_PtrCountZero( Vec_Ptr_t * p ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] == NULL); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void ** Vec_PtrEntryP( Vec_Ptr_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray + i; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p ) { assert( p->nSize > 0 ); return p->pArray[p->nSize-1]; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrGrow( Vec_Ptr_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( void *, p->pArray, nCapMin ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrFill( Vec_Ptr_t * p, int nSize, void * Entry ) { int i; Vec_PtrGrow( p, nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = Entry; p->nSize = nSize; } static inline void Vec_PtrFillTwo( Vec_Ptr_t * p, int nSize, void * EntryEven, void * EntryOdd ) { int i; Vec_PtrGrow( p, nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = (i & 1) ? EntryOdd : EntryEven; p->nSize = nSize; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Fill ) { int i; if ( nSize <= p->nSize ) return; if ( nSize > 2 * p->nCap ) Vec_PtrGrow( p, nSize ); else if ( nSize > p->nCap ) Vec_PtrGrow( p, 2 * p->nCap ); for ( i = p->nSize; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } /**Function************************************************************* Synopsis [Returns the entry even if the place not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Vec_PtrGetEntry( Vec_Ptr_t * p, int i ) { Vec_PtrFillExtra( p, i + 1, NULL ); return Vec_PtrEntry( p, i ); } /**Function************************************************************* Synopsis [Inserts the entry even if the place does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrSetEntry( Vec_Ptr_t * p, int i, void * Entry ) { Vec_PtrFillExtra( p, i + 1, NULL ); Vec_PtrWriteEntry( p, i, Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrShrink( Vec_Ptr_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrClear( Vec_Ptr_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [Deallocates array of memory pointers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrFreeData( Vec_Ptr_t * p ) { void * pTemp; int i; if ( p == NULL ) return; Vec_PtrForEachEntry( void *, p, pTemp, i ) if ( pTemp != (void *)(ABC_PTRINT_T)1 && pTemp != (void *)(ABC_PTRINT_T)2 ) ABC_FREE( pTemp ); } static inline void Vec_PtrFreeFree( Vec_Ptr_t * p ) { if ( p == NULL ) return; Vec_PtrFreeData( p ); Vec_PtrFree( p ); } /**Function************************************************************* Synopsis [Copies the interger array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrCopy( Vec_Ptr_t * pDest, Vec_Ptr_t * pSour ) { pDest->nSize = 0; Vec_PtrGrow( pDest, pSour->nSize ); memcpy( pDest->pArray, pSour->pArray, sizeof(void *) * pSour->nSize ); pDest->nSize = pSour->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrPush( Vec_Ptr_t * p, void * Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_PtrGrow( p, 16 ); else Vec_PtrGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } static inline void Vec_PtrPushTwo( Vec_Ptr_t * p, void * Entry1, void * Entry2 ) { Vec_PtrPush( p, Entry1 ); Vec_PtrPush( p, Entry2 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrPushFirst( Vec_Ptr_t * p, void * Entry ) { int i; if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_PtrGrow( p, 16 ); else Vec_PtrGrow( p, 2 * p->nCap ); } p->nSize++; for ( i = p->nSize - 1; i >= 1; i-- ) p->pArray[i] = p->pArray[i-1]; p->pArray[0] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_PtrPushUnique( Vec_Ptr_t * p, void * Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Vec_PtrPush( p, Entry ); return 0; } /**Function************************************************************* Synopsis [Returns the last entry and removes it from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Vec_PtrPop( Vec_Ptr_t * p ) { assert( p->nSize > 0 ); return p->pArray[--p->nSize]; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return i; return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry ) { int i; // delete assuming that it is closer to the end for ( i = p->nSize - 1; i >= 0; i-- ) if ( p->pArray[i] == Entry ) break; assert( i >= 0 ); /* // delete assuming that it is closer to the beginning for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) break; assert( i < p->nSize ); */ for ( i++; i < p->nSize; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrDrop( Vec_Ptr_t * p, int i ) { int k; assert( i >= 0 && i < Vec_PtrSize(p) ); p->nSize--; for ( k = i; k < p->nSize; k++ ) p->pArray[k] = p->pArray[k+1]; } /**Function************************************************************* Synopsis [Interts entry at the index iHere. Shifts other entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrInsert( Vec_Ptr_t * p, int iHere, void * Entry ) { int i; assert( iHere >= 0 && iHere < p->nSize ); Vec_PtrPush( p, 0 ); for ( i = p->nSize - 1; i > iHere; i-- ) p->pArray[i] = p->pArray[i-1]; p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [Moves the first nItems to the end.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems ) { assert( nItems < p->nSize ); Vec_PtrGrow( p, nItems + p->nSize ); memmove( (char **)p->pArray + p->nSize, p->pArray, nItems * sizeof(void*) ); memmove( p->pArray, (char **)p->pArray + nItems, p->nSize * sizeof(void*) ); } /**Function************************************************************* Synopsis [Reverses the order of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrReverseOrder( Vec_Ptr_t * p ) { void * Temp; int i; for ( i = 0; i < p->nSize/2; i++ ) { Temp = p->pArray[i]; p->pArray[i] = p->pArray[p->nSize-1-i]; p->pArray[p->nSize-1-i] = Temp; } } /**Function************************************************************* Synopsis [Checks if two vectors are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_PtrEqual( Vec_Ptr_t * p1, Vec_Ptr_t * p2 ) { int i; if ( p1->nSize != p2->nSize ) return 0; for ( i = 0; i < p1->nSize; i++ ) if ( p1->pArray[i] != p2->pArray[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_PtrSortComparePtr( void ** pp1, void ** pp2 ) { if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) ___unused; static void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) { if ( p->nSize < 2 ) return; if ( Vec_PtrSortCompare == NULL ) qsort( (void *)p->pArray, p->nSize, sizeof(void *), (int (*)(const void *, const void *)) Vec_PtrSortComparePtr ); else qsort( (void *)p->pArray, p->nSize, sizeof(void *), (int (*)(const void *, const void *)) Vec_PtrSortCompare ); } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) ___unused; static void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) { int i, k; if ( p->nSize < 2 ) return; Vec_PtrSort( p, Vec_PtrSortCompare ); for ( i = k = 1; i < p->nSize; i++ ) if ( p->pArray[i] != p->pArray[i-1] ) p->pArray[k++] = p->pArray[i]; p->nSize = k; } static void Vec_PtrUniqify2( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(void**, void**), void (*Vec_PtrObjFree)(void*), Vec_Int_t * vCounts ) ___unused; static void Vec_PtrUniqify2( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)(void**, void**), void (*Vec_PtrObjFree)(void*), Vec_Int_t * vCounts ) { int i, k; if ( vCounts ) Vec_IntFill( vCounts, 1, 1 ); if ( p->nSize < 2 ) return; Vec_PtrSort( p, (int (*)())Vec_PtrSortCompare ); for ( i = k = 1; i < p->nSize; i++ ) if ( Vec_PtrSortCompare(p->pArray+i, p->pArray+k-1) != 0 ) { p->pArray[k++] = p->pArray[i]; if ( vCounts ) Vec_IntPush( vCounts, 1 ); } else { if ( Vec_PtrObjFree ) Vec_PtrObjFree( p->pArray[i] ); if ( vCounts ) Vec_IntAddToEntry( vCounts, Vec_IntSize(vCounts)-1, 1 ); } p->nSize = k; assert( vCounts == NULL || Vec_IntSize(vCounts) == Vec_PtrSize(p) ); } /**Function************************************************************* Synopsis [Allocates the array of simulation info.] Description [Allocates the array containing given number of entries, each of which contains given number of unsigned words of simulation data. The resulting array can be freed using regular procedure Vec_PtrFree(). It is the responsibility of the user to ensure this array is never grown.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_PtrAllocSimInfo( int nEntries, int nWords ) { void ** pMemory; unsigned * pInfo; int i; pMemory = (void **)ABC_ALLOC( char, (sizeof(void *) + sizeof(unsigned) * nWords) * nEntries ); pInfo = (unsigned *)(pMemory + nEntries); for ( i = 0; i < nEntries; i++ ) pMemory[i] = pInfo + i * nWords; return Vec_PtrAllocArray( pMemory, nEntries ); } /**Function************************************************************* Synopsis [Cleans simulation info of each entry beginning with iWord.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_PtrReadWordsSimInfo( Vec_Ptr_t * p ) { return (unsigned *)Vec_PtrEntry(p,1) - (unsigned *)Vec_PtrEntry(p,0); } /**Function************************************************************* Synopsis [Cleans simulation info of each entry beginning with iWord.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrCleanSimInfo( Vec_Ptr_t * vInfo, int iWord, int nWords ) { int i; for ( i = 0; i < vInfo->nSize; i++ ) memset( (char*)Vec_PtrEntry(vInfo,i) + 4*iWord, 0, 4*(nWords-iWord) ); } /**Function************************************************************* Synopsis [Cleans simulation info of each entry beginning with iWord.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrFillSimInfo( Vec_Ptr_t * vInfo, int iWord, int nWords ) { int i; for ( i = 0; i < vInfo->nSize; i++ ) memset( (char*)Vec_PtrEntry(vInfo,i) + 4*iWord, 0xFF, 4*(nWords-iWord) ); } /**Function************************************************************* Synopsis [Resizes the array of simulation info.] Description [Doubles the number of objects for which siminfo is allocated.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo ) { Vec_Ptr_t * vInfoNew; int nWords; assert( Vec_PtrSize(vInfo) > 1 ); // get the new array nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0); vInfoNew = Vec_PtrAllocSimInfo( 2*Vec_PtrSize(vInfo), nWords ); // copy the simulation info memcpy( Vec_PtrEntry(vInfoNew,0), Vec_PtrEntry(vInfo,0), Vec_PtrSize(vInfo) * nWords * 4 ); // replace the array ABC_FREE( vInfo->pArray ); vInfo->pArray = vInfoNew->pArray; vInfo->nSize *= 2; vInfo->nCap *= 2; // free the old array vInfoNew->pArray = NULL; ABC_FREE( vInfoNew ); } /**Function************************************************************* Synopsis [Resizes the array of simulation info.] Description [Doubles the number of simulation patterns stored for each object.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_PtrReallocSimInfo( Vec_Ptr_t * vInfo ) { Vec_Ptr_t * vInfoNew; int nWords, i; assert( Vec_PtrSize(vInfo) > 1 ); // get the new array nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0); vInfoNew = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), 2*nWords ); // copy the simulation info for ( i = 0; i < vInfo->nSize; i++ ) memcpy( Vec_PtrEntry(vInfoNew,i), Vec_PtrEntry(vInfo,i), nWords * 4 ); // replace the array ABC_FREE( vInfo->pArray ); vInfo->pArray = vInfoNew->pArray; // free the old array vInfoNew->pArray = NULL; ABC_FREE( vInfoNew ); } /**Function************************************************************* Synopsis [Allocates the array of truth tables for the given number of vars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_PtrAllocTruthTables( int nVars ) { Vec_Ptr_t * p; unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; unsigned * pTruth; int i, k, nWords; nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); p = Vec_PtrAllocSimInfo( nVars, nWords ); for ( i = 0; i < nVars; i++ ) { pTruth = (unsigned *)p->pArray[i]; if ( i < 5 ) { for ( k = 0; k < nWords; k++ ) pTruth[k] = Masks[i]; } else { for ( k = 0; k < nWords; k++ ) if ( k & (1 << (i-5)) ) pTruth[k] = ~(unsigned)0; else pTruth[k] = 0; } } return p; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecQue.h000066400000000000000000000243671300674244400231610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecQue.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Priority queue.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecQue.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__Queue_h #define ABC__misc__vec__Queue_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Que_t_ Vec_Que_t; struct Vec_Que_t_ { int nCap; int nSize; int * pHeap; int * pOrder; float ** pCostsFlt; // owned by the caller }; static inline float Vec_QuePrio( Vec_Que_t * p, int v ) { return *p->pCostsFlt ? (*p->pCostsFlt)[v] : v; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Que_t * Vec_QueAlloc( int nCap ) { Vec_Que_t * p; p = ABC_CALLOC( Vec_Que_t, 1 ); if ( nCap < 16 ) nCap = 16; p->nSize = 1; p->nCap = nCap + 1; p->pHeap = ABC_FALLOC( int, p->nCap ); p->pOrder = ABC_FALLOC( int, p->nCap ); return p; } static inline void Vec_QueFree( Vec_Que_t * p ) { ABC_FREE( p->pOrder ); ABC_FREE( p->pHeap ); ABC_FREE( p ); } static inline void Vec_QueFreeP( Vec_Que_t ** p ) { if ( *p ) Vec_QueFree( *p ); *p = NULL; } static inline void Vec_QueSetPriority( Vec_Que_t * p, float ** pCosts ) { assert( p->pCostsFlt == NULL ); p->pCostsFlt = pCosts; } static inline void Vec_QueGrow( Vec_Que_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pHeap = ABC_REALLOC( int, p->pHeap, nCapMin ); p->pOrder = ABC_REALLOC( int, p->pOrder, nCapMin ); memset( p->pHeap + p->nCap, 0xff, (nCapMin - p->nCap) * sizeof(int) ); memset( p->pOrder + p->nCap, 0xff, (nCapMin - p->nCap) * sizeof(int) ); p->nCap = nCapMin; } static inline void Vec_QueClear( Vec_Que_t * p ) { int i; assert( p->pHeap[0] == -1 ); for ( i = 1; i < p->nSize; i++ ) { assert( p->pHeap[i] >= 0 && p->pOrder[p->pHeap[i]] == i ); p->pOrder[p->pHeap[i]] = -1; p->pHeap[i] = -1; } p->nSize = 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_QueSize( Vec_Que_t * p ) { assert( p->nSize > 0 ); return p->nSize - 1; } static inline int Vec_QueTop( Vec_Que_t * p ) { return Vec_QueSize(p) > 0 ? p->pHeap[1] : -1; } static inline float Vec_QueTopPriority( Vec_Que_t * p ) { return Vec_QueSize(p) > 0 ? Vec_QuePrio(p, p->pHeap[1]) : -ABC_INFINITY; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_QueMoveUp( Vec_Que_t * p, int v ) { float Cost = Vec_QuePrio(p, v); int i = p->pOrder[v]; int parent = i >> 1; int fMoved = 0; assert( p->pOrder[v] != -1 ); assert( p->pHeap[i] == v ); while ( i > 1 && Cost > Vec_QuePrio(p, p->pHeap[parent]) ) { p->pHeap[i] = p->pHeap[parent]; p->pOrder[p->pHeap[i]] = i; i = parent; parent = i >> 1; fMoved = 1; } p->pHeap[i] = v; p->pOrder[v] = i; return fMoved; } static inline void Vec_QueMoveDown( Vec_Que_t * p, int v ) { float Cost = Vec_QuePrio(p, v); int i = p->pOrder[v]; int child = i << 1; while ( child < p->nSize ) { if ( child + 1 < p->nSize && Vec_QuePrio(p, p->pHeap[child]) < Vec_QuePrio(p, p->pHeap[child+1]) ) child++; assert( child < p->nSize ); if ( Cost >= Vec_QuePrio(p, p->pHeap[child])) break; p->pHeap[i] = p->pHeap[child]; p->pOrder[p->pHeap[i]] = i; i = child; child = child << 1; } p->pHeap[i] = v; p->pOrder[v] = i; } static inline void Vec_QueUpdate( Vec_Que_t * p, int v ) { if ( !Vec_QueMoveUp( p, v ) ) Vec_QueMoveDown( p, v ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_QueIsMember( Vec_Que_t * p, int v ) { assert( v >= 0 ); return (int)( v < p->nCap && p->pOrder[v] >= 0 ); } static inline void Vec_QuePush( Vec_Que_t * p, int v ) { if ( p->nSize >= p->nCap ) Vec_QueGrow( p, Abc_MaxInt(p->nSize+1, 2*p->nCap) ); if ( v >= p->nCap ) Vec_QueGrow( p, Abc_MaxInt(v+1, 2*p->nCap) ); assert( p->nSize < p->nCap ); assert( p->pOrder[v] == -1 ); assert( p->pHeap[p->nSize] == -1 ); p->pOrder[v] = p->nSize; p->pHeap[p->nSize++] = v; Vec_QueMoveUp( p, v ); } static inline int Vec_QuePop( Vec_Que_t * p ) { int v, Res; assert( p->nSize > 1 ); Res = p->pHeap[1]; p->pOrder[Res] = -1; if ( --p->nSize == 1 ) { p->pHeap[1] = -1; return Res; } v = p->pHeap[p->nSize]; p->pHeap[p->nSize] = -1; p->pHeap[1] = v; p->pOrder[v] = 1; Vec_QueMoveDown( p, v ); return Res; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_QuePrint( Vec_Que_t * p ) { int i, k, m; for ( i = k = 1; i < p->nSize; i += k, k *= 2 ) { for ( m = 0; m < k; m++ ) if ( i+m < p->nSize ) printf( "%-5d", p->pHeap[i+m] ); printf( "\n" ); for ( m = 0; m < k; m++ ) if ( i+m < p->nSize ) printf( "%-5.0f", Vec_QuePrio(p, p->pHeap[i+m]) ); printf( "\n" ); printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_QueCheck( Vec_Que_t * p ) { int i, child; assert( p->nSize > 0 ); assert( p->nSize <= p->nCap ); // check mapping for ( i = 0; i < p->nSize-1; i++ ) assert( p->pOrder[i] > 0 ); for ( ; i < p->nCap; i++ ) assert( p->pOrder[i] == -1 ); // check heap assert( p->pHeap[0] == -1 ); for ( i = 0; i < p->nSize-1; i++ ) assert( p->pHeap[p->pOrder[i]] == i ); for ( i++; i < p->nCap; i++ ) assert( p->pHeap[i] == -1 ); // check heap property for ( i = 1; i < p->nSize; i++ ) { child = i << 1; if ( child < p->nSize ) assert( Vec_QuePrio(p, p->pHeap[i]) >= Vec_QuePrio(p, p->pHeap[child]) ); child++; if ( child < p->nSize ) assert( Vec_QuePrio(p, p->pHeap[i]) >= Vec_QuePrio(p, p->pHeap[child]) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_QueTest( Vec_Flt_t * vCosts ) { Vec_Int_t * vTop; Vec_Que_t * p; int i, Entry; // start the queue p = Vec_QueAlloc( Vec_FltSize(vCosts) ); Vec_QueSetPriority( p, Vec_FltArrayP(vCosts) ); for ( i = 0; i < Vec_FltSize(vCosts); i++ ) Vec_QuePush( p, i ); // Vec_QuePrint( p ); Vec_QueCheck( p ); // find the topmost 10% vTop = Vec_IntAlloc( Vec_FltSize(vCosts) / 10 ); while ( Vec_IntSize(vTop) < Vec_FltSize(vCosts) / 10 ) Vec_IntPush( vTop, Vec_QuePop(p) ); // Vec_IntPrint( vTop ); // Vec_QueCheck( p ); // queque is not ready at this point!!! // put them back Vec_IntForEachEntry( vTop, Entry, i ) Vec_QuePush( p, Entry ); Vec_IntFree( vTop ); Vec_QueCheck( p ); Vec_QueFree( p ); } /* { extern void Vec_QueTest( Vec_Flt_t * p ); Vec_QueTest( p->vTimesOut ); } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecSet.h000066400000000000000000000257631300674244400231630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecSet.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT solvers.] Synopsis [Multi-page dynamic array.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecSet.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__sat__bsat__vecSet_h #define ABC__sat__bsat__vecSet_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // data-structure for logging entries // memory is allocated in 2^nPageSize word-sized pages // the first two 'words' of each page are used for bookkeeping // the first 'word' of bookkeeping data stores the word limit // the second 'word' of bookkeeping data stores the shadow word limit // (the shadow word limit is only used during garbage collection) typedef struct Vec_Set_t_ Vec_Set_t; struct Vec_Set_t_ { int nPageSize; // page size unsigned uPageMask; // page mask int nEntries; // entry count int iPage; // current page int iPageS; // shadow page int nPagesAlloc; // page count allocated word ** pPages; // page pointers }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Vec_SetHandPage( Vec_Set_t * p, int h ) { return h >> p->nPageSize; } static inline int Vec_SetHandShift( Vec_Set_t * p, int h ) { return h & p->uPageMask; } static inline int Vec_SetWordNum( int nSize ) { return (nSize + 1) >> 1; } //static inline word * Vec_SetEntry( Vec_Set_t * p, int h ) { assert(Vec_SetHandPage(p, h) >= 0 && Vec_SetHandPage(p, h) <= p->iPage); assert(Vec_SetHandShift(p, h) >= 2 && Vec_SetHandShift(p, h) < (1 << p->nPageSize)); return p->pPages[Vec_SetHandPage(p, h)] + Vec_SetHandShift(p, h); } static inline word * Vec_SetEntry( Vec_Set_t * p, int h ) { return p->pPages[Vec_SetHandPage(p, h)] + Vec_SetHandShift(p, h); } static inline int Vec_SetEntryNum( Vec_Set_t * p ) { return p->nEntries; } static inline void Vec_SetWriteEntryNum( Vec_Set_t * p, int i){ p->nEntries = i; } static inline int Vec_SetLimit( word * p ) { return p[0]; } static inline int Vec_SetLimitS( word * p ) { return p[1]; } static inline int Vec_SetIncLimit( word * p, int nWords ) { return p[0] += nWords; } static inline int Vec_SetIncLimitS( word * p, int nWords ) { return p[1] += nWords; } static inline void Vec_SetWriteLimit( word * p, int nWords ) { p[0] = nWords; } static inline void Vec_SetWriteLimitS( word * p, int nWords ) { p[1] = nWords; } static inline int Vec_SetHandCurrent( Vec_Set_t * p ) { return (p->iPage << p->nPageSize) + Vec_SetLimit(p->pPages[p->iPage]); } static inline int Vec_SetHandCurrentS( Vec_Set_t * p ) { return (p->iPageS << p->nPageSize) + Vec_SetLimitS(p->pPages[p->iPageS]); } static inline int Vec_SetHandMemory( Vec_Set_t * p, int h ) { return Vec_SetHandPage(p, h) * (1 << (p->nPageSize+3)) + Vec_SetHandShift(p, h) * 8; } static inline int Vec_SetMemory( Vec_Set_t * p ) { return Vec_SetHandMemory(p, Vec_SetHandCurrent(p)); } static inline int Vec_SetMemoryS( Vec_Set_t * p ) { return Vec_SetHandMemory(p, Vec_SetHandCurrentS(p)); } static inline int Vec_SetMemoryAll( Vec_Set_t * p ) { return (p->iPage+1) * (1 << (p->nPageSize+3)); } // Type is the Set type // pVec is vector of set // nSize should be given by the user // pSet is the pointer to the set // p (page) and s (shift) are variables used here #define Vec_SetForEachEntry( Type, pVec, nSize, pSet, p, s ) \ for ( p = 0; p <= pVec->iPage; p++ ) \ for ( s = 2; s < Vec_SetLimit(pVec->pPages[p]) && ((pSet) = (Type)(pVec->pPages[p] + (s))); s += nSize ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocating vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_SetAlloc_( Vec_Set_t * p, int nPageSize ) { assert( nPageSize > 8 ); memset( p, 0, sizeof(Vec_Set_t) ); p->nPageSize = nPageSize; p->uPageMask = (unsigned)((1 << nPageSize) - 1); p->nPagesAlloc = 256; p->pPages = ABC_CALLOC( word *, p->nPagesAlloc ); p->pPages[0] = ABC_ALLOC( word, (1 << p->nPageSize) ); p->pPages[0][0] = ~0; p->pPages[0][1] = ~0; Vec_SetWriteLimit( p->pPages[0], 2 ); } static inline Vec_Set_t * Vec_SetAlloc( int nPageSize ) { Vec_Set_t * p; p = ABC_CALLOC( Vec_Set_t, 1 ); Vec_SetAlloc_( p, nPageSize ); return p; } /**Function************************************************************* Synopsis [Resetting vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_SetRestart( Vec_Set_t * p ) { p->nEntries = 0; p->iPage = 0; p->iPageS = 0; p->pPages[0][0] = ~0; p->pPages[0][1] = ~0; Vec_SetWriteLimit( p->pPages[0], 2 ); } /**Function************************************************************* Synopsis [Freeing vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_SetFree_( Vec_Set_t * p ) { int i; if ( p == NULL ) return; for ( i = 0; i < p->nPagesAlloc; i++ ) ABC_FREE( p->pPages[i] ); ABC_FREE( p->pPages ); } static inline void Vec_SetFree( Vec_Set_t * p ) { if ( p == NULL ) return; Vec_SetFree_( p ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns memory in bytes occupied by the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_ReportMemory( Vec_Set_t * p ) { double Mem = sizeof(Vec_Set_t); Mem += p->nPagesAlloc * sizeof(void *); Mem += sizeof(word) * (1 << p->nPageSize) * (1 + p->iPage); return Mem; } /**Function************************************************************* Synopsis [Appending entries to vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_SetAppend( Vec_Set_t * p, int * pArray, int nSize ) { int nWords = Vec_SetWordNum( nSize ); assert( nWords < (1 << p->nPageSize) ); p->nEntries++; if ( Vec_SetLimit( p->pPages[p->iPage] ) + nWords >= (1 << p->nPageSize) ) { if ( ++p->iPage == p->nPagesAlloc ) { p->pPages = ABC_REALLOC( word *, p->pPages, p->nPagesAlloc * 2 ); memset( p->pPages + p->nPagesAlloc, 0, sizeof(word *) * p->nPagesAlloc ); p->nPagesAlloc *= 2; } if ( p->pPages[p->iPage] == NULL ) p->pPages[p->iPage] = ABC_ALLOC( word, (1 << p->nPageSize) ); Vec_SetWriteLimit( p->pPages[p->iPage], 2 ); p->pPages[p->iPage][1] = ~0; } if ( pArray ) memcpy( p->pPages[p->iPage] + Vec_SetLimit(p->pPages[p->iPage]), pArray, sizeof(int) * nSize ); Vec_SetIncLimit( p->pPages[p->iPage], nWords ); return Vec_SetHandCurrent(p) - nWords; } static inline int Vec_SetAppendS( Vec_Set_t * p, int nSize ) { int nWords = Vec_SetWordNum( nSize ); assert( nWords < (1 << p->nPageSize) ); if ( Vec_SetLimitS( p->pPages[p->iPageS] ) + nWords >= (1 << p->nPageSize) ) Vec_SetWriteLimitS( p->pPages[++p->iPageS], 2 ); Vec_SetIncLimitS( p->pPages[p->iPageS], nWords ); return Vec_SetHandCurrentS(p) - nWords; } static inline int Vec_SetFetchH( Vec_Set_t * p, int nBytes ) { return Vec_SetAppend(p, NULL, (nBytes + 3) >> 2); } static inline void * Vec_SetFetch( Vec_Set_t * p, int nBytes ) { return (void *)Vec_SetEntry( p, Vec_SetFetchH(p, nBytes) ); } static inline char * Vec_SetStrsav( Vec_Set_t * p, char * pName ) { char * pStr = (char *)Vec_SetFetch( p, strlen(pName) + 1 ); strcpy( pStr, pName ); return pStr; } /**Function************************************************************* Synopsis [Shrinking vector size.] Description [] SideEffects [This procedure does not update the number of entries.] SeeAlso [] ***********************************************************************/ static inline void Vec_SetShrink( Vec_Set_t * p, int h ) { assert( h <= Vec_SetHandCurrent(p) ); p->iPage = Vec_SetHandPage(p, h); Vec_SetWriteLimit( p->pPages[p->iPage], Vec_SetHandShift(p, h) ); } static inline void Vec_SetShrinkS( Vec_Set_t * p, int h ) { assert( h <= Vec_SetHandCurrent(p) ); p->iPageS = Vec_SetHandPage(p, h); Vec_SetWriteLimitS( p->pPages[p->iPageS], Vec_SetHandShift(p, h) ); } static inline void Vec_SetShrinkLimits( Vec_Set_t * p ) { int i; for ( i = 0; i <= p->iPage; i++ ) Vec_SetWriteLimit( p->pPages[i], Vec_SetLimitS(p->pPages[i]) ); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecStr.h000066400000000000000000000643601300674244400231740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecStr.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable arrays of characters.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecStr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecStr_h #define ABC__misc__vec__vecStr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Str_t_ Vec_Str_t; struct Vec_Str_t_ { int nCap; int nSize; char * pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Vec_StrForEachEntry( vVec, Entry, i ) \ for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Str_t * Vec_StrAlloc( int nCap ) { Vec_Str_t * p; p = ABC_ALLOC( Vec_Str_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( char, p->nCap ) : NULL; return p; } static inline Vec_Str_t * Vec_StrAllocExact( int nCap ) { Vec_Str_t * p; assert( nCap >= 0 ); p = ABC_ALLOC( Vec_Str_t, 1 ); p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( char, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Str_t * Vec_StrStart( int nSize ) { Vec_Str_t * p; p = Vec_StrAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0, sizeof(char) * nSize ); return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize ) { Vec_Str_t * p; p = ABC_ALLOC( Vec_Str_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = pArray; return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Str_t * Vec_StrAllocArrayCopy( char * pArray, int nSize ) { Vec_Str_t * p; p = ABC_ALLOC( Vec_Str_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = ABC_ALLOC( char, nSize ); memcpy( p->pArray, pArray, sizeof(char) * nSize ); return p; } /**Function************************************************************* Synopsis [Duplicates the integer array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Str_t * Vec_StrDup( Vec_Str_t * pVec ) { Vec_Str_t * p; p = ABC_ALLOC( Vec_Str_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = p->nCap? ABC_ALLOC( char, p->nCap ) : NULL; memcpy( p->pArray, pVec->pArray, sizeof(char) * pVec->nSize ); return p; } /**Function************************************************************* Synopsis [Transfers the array into another vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Str_t * Vec_StrDupArray( Vec_Str_t * pVec ) { Vec_Str_t * p; p = ABC_ALLOC( Vec_Str_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = pVec->pArray; pVec->nSize = 0; pVec->nCap = 0; pVec->pArray = NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrZero( Vec_Str_t * p ) { p->pArray = NULL; p->nSize = 0; p->nCap = 0; } static inline void Vec_StrErase( Vec_Str_t * p ) { ABC_FREE( p->pArray ); p->nSize = 0; p->nCap = 0; } static inline void Vec_StrFree( Vec_Str_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrFreeP( Vec_Str_t ** p ) { if ( *p == NULL ) return; ABC_FREE( (*p)->pArray ); ABC_FREE( (*p) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char * Vec_StrReleaseArray( Vec_Str_t * p ) { char * pArray = p->pArray; p->nCap = 0; p->nSize = 0; p->pArray = NULL; return pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char * Vec_StrArray( Vec_Str_t * p ) { return p->pArray; } static inline char * Vec_StrLimit( Vec_Str_t * p ) { return p->pArray + p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_StrSize( Vec_Str_t * p ) { return p->nSize; } static inline void Vec_StrSetSize( Vec_Str_t * p, int nSize ) { p->nSize = nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_StrCap( Vec_Str_t * p ) { return p->nCap; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_StrMemory( Vec_Str_t * p ) { return !p ? 0.0 : 1.0 * sizeof(char) * p->nCap + sizeof(Vec_Str_t); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char Vec_StrEntry( Vec_Str_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char * Vec_StrEntryP( Vec_Str_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray + i; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char Vec_StrEntryLast( Vec_Str_t * p ) { assert( p->nSize > 0 ); return p->pArray[p->nSize-1]; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrGrow( Vec_Str_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( char, p->pArray, nCapMin ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrFill( Vec_Str_t * p, int nSize, char Fill ) { int i; Vec_StrGrow( p, nSize ); p->nSize = nSize; for ( i = 0; i < p->nSize; i++ ) p->pArray[i] = Fill; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrFillExtra( Vec_Str_t * p, int nSize, char Fill ) { int i; if ( nSize <= p->nSize ) return; if ( nSize > 2 * p->nCap ) Vec_StrGrow( p, nSize ); else if ( nSize > p->nCap ) Vec_StrGrow( p, 2 * p->nCap ); for ( i = p->nSize; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } /**Function************************************************************* Synopsis [Returns the entry even if the place not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char Vec_StrGetEntry( Vec_Str_t * p, int i ) { Vec_StrFillExtra( p, i + 1, 0 ); return Vec_StrEntry( p, i ); } /**Function************************************************************* Synopsis [Inserts the entry even if the place does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrSetEntry( Vec_Str_t * p, int i, char Entry ) { Vec_StrFillExtra( p, i + 1, 0 ); Vec_StrWriteEntry( p, i, Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrShrink( Vec_Str_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrClear( Vec_Str_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrPush( Vec_Str_t * p, char Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_StrGrow( p, 16 ); else Vec_StrGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } static inline void Vec_StrPushBuffer( Vec_Str_t * p, char * pBuffer, int nSize ) { if ( p->nSize + nSize > p->nCap ) Vec_StrGrow( p, 2 * (p->nSize + nSize) ); memcpy( p->pArray + p->nSize, pBuffer, nSize ); p->nSize += nSize; } /**Function************************************************************* Synopsis [Returns the last entry and removes it from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline char Vec_StrPop( Vec_Str_t * p ) { assert( p->nSize > 0 ); return p->pArray[--p->nSize]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrIntPrint( Vec_Str_t * p ) { int i; printf( "Vector has %d entries: {", Vec_StrSize(p) ); for ( i = 0; i < Vec_StrSize(p); i++ ) printf( " %d", (int)Vec_StrEntry(p, i) ); printf( " }\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num ) { int i; char Digits[16]; if ( Num == 0 ) { Vec_StrPush( p, '0' ); return; } if ( Num < 0 ) { Vec_StrPush( p, '-' ); Num = -Num; } for ( i = 0; Num; Num /= 10, i++ ) Digits[i] = Num % 10; for ( i--; i >= 0; i-- ) Vec_StrPush( p, (char)('0' + Digits[i]) ); } static inline void Vec_StrPrintNumStar( Vec_Str_t * p, int Num, int nDigits ) { int i; char Digits[16] = {0}; if ( Num == 0 ) { for ( i = 0; i < nDigits; i++ ) Vec_StrPush( p, '0' ); return; } if ( Num < 0 ) { Vec_StrPush( p, '-' ); Num = -Num; nDigits--; } for ( i = 0; Num; Num /= 10, i++ ) Digits[i] = Num % 10; for ( i = Abc_MaxInt(i, nDigits)-1; i >= 0; i-- ) Vec_StrPush( p, (char)('0' + Digits[i]) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrPrintStr( Vec_Str_t * p, const char * pStr ) { int i, Length = strlen(pStr); for ( i = 0; i < Length; i++ ) Vec_StrPush( p, pStr[i] ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #ifdef WIN32 #define vsnprintf _vsnprintf #endif static inline char * Vec_StrPrintF( Vec_Str_t * p, const char * format, ... ) { int nAdded, nSize = 1000; va_list args; va_start( args, format ); Vec_StrGrow( p, Vec_StrSize(p) + nSize ); nAdded = vsnprintf( Vec_StrLimit(p), nSize, format, args ); if ( nAdded > nSize ) { Vec_StrGrow( p, Vec_StrSize(p) + nAdded + nSize ); nSize = vsnprintf( Vec_StrLimit(p), nAdded, format, args ); assert( nSize == nAdded ); } p->nSize += nAdded; va_end( args ); return Vec_StrLimit(p) - nAdded; } /**Function************************************************************* Synopsis [Appends the string to the char vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrAppend( Vec_Str_t * p, const char * pString ) { Vec_StrPrintStr( p, pString ); } static inline void Vec_StrCopy( Vec_Str_t * p, const char * pString ) { Vec_StrClear( p ); Vec_StrAppend( p, pString ); Vec_StrPush( p, '\0' ); } /**Function************************************************************* Synopsis [Reverses the order of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrReverseOrder( Vec_Str_t * p ) { int i, Temp; for ( i = 0; i < p->nSize/2; i++ ) { Temp = p->pArray[i]; p->pArray[i] = p->pArray[p->nSize-1-i]; p->pArray[p->nSize-1-i] = Temp; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_StrSum( Vec_Str_t * p ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (int)p->pArray[i]; return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_StrCountEntry( Vec_Str_t * p, char Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] == Entry); return Counter; } static inline int Vec_StrCountLarger( Vec_Str_t * p, char Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] > Entry); return Counter; } static inline int Vec_StrCountSmaller( Vec_Str_t * p, char Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] < Entry); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_StrCountEntryLit( Vec_Str_t * p, char Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (Abc_Lit2Var((int)p->pArray[i]) == Entry); return Counter; } static inline int Vec_StrCountLargerLit( Vec_Str_t * p, char Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (Abc_Lit2Var((int)p->pArray[i]) > Entry); return Counter; } static inline int Vec_StrCountSmallerLit( Vec_Str_t * p, char Entry ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (Abc_Lit2Var((int)p->pArray[i]) < Entry); return Counter; } /**Function************************************************************* Synopsis [Compares two strings.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_StrEqual( Vec_Str_t * p1, Vec_Str_t * p2 ) { int i; if ( p1->nSize != p2->nSize ) return 0; for ( i = 0; i < p1->nSize; i++ ) if ( p1->pArray[i] != p2->pArray[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Comparison procedure for two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_StrSortCompare1( char * pp1, char * pp2 ) { // for some reason commenting out lines (as shown) led to crashing of the release version if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) // return 1; return 0; // } /**Function************************************************************* Synopsis [Comparison procedure for two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_StrSortCompare2( char * pp1, char * pp2 ) { // for some reason commenting out lines (as shown) led to crashing of the release version if ( *pp1 > *pp2 ) return -1; if ( *pp1 < *pp2 ) // return 1; return 0; // } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrSort( Vec_Str_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(char), (int (*)(const void *, const void *)) Vec_StrSortCompare2 ); else qsort( (void *)p->pArray, p->nSize, sizeof(char), (int (*)(const void *, const void *)) Vec_StrSortCompare1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_StrCompareVec( Vec_Str_t * p1, Vec_Str_t * p2 ) { if ( p1 == NULL || p2 == NULL ) return (p1 != NULL) - (p2 != NULL); if ( Vec_StrSize(p1) != Vec_StrSize(p2) ) return Vec_StrSize(p1) - Vec_StrSize(p2); return memcmp( Vec_StrArray(p1), Vec_StrArray(p2), Vec_StrSize(p1) ); } /**Function************************************************************* Synopsis [Binary I/O for numbers (int/float/etc) and strings (char *).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrPutI_ne( Vec_Str_t * vOut, int Val ) { int i; // for ( i = 0; i < 4; i++ ) for ( i = 3; i >= 0; i-- ) Vec_StrPush( vOut, (char)(Val >> (8*i)) ); } static inline int Vec_StrGetI_ne( Vec_Str_t * vOut, int * pPos ) { int i; int Val = 0; // for ( i = 0; i < 4; i++ ) for ( i = 3; i >= 0; i-- ) Val |= ((int)(unsigned char)Vec_StrEntry(vOut, (*pPos)++) << (8*i)); return Val; } static inline void Vec_StrPutI( Vec_Str_t * vOut, int Val ) { for ( ; Val >= 0x80; Val >>= 7 ) Vec_StrPush( vOut, (unsigned char)(Val | 0x80) ); Vec_StrPush( vOut, (unsigned char)Val ); } static inline int Vec_StrGetI( Vec_Str_t * vOut, int * pPos ) { unsigned char ch; int i = 0, Val = 0; while ( (ch = Vec_StrEntry(vOut, (*pPos)++)) & 0x80 ) Val |= ((ch & 0x7f) << (7 * i++)); return Val | (ch << (7 * i)); } static inline void Vec_StrPutW( Vec_Str_t * vOut, word Val ) { int i; for ( i = 0; i < 8; i++ ) Vec_StrPush( vOut, (char)(Val >> (8*i)) ); } static inline word Vec_StrGetW( Vec_Str_t * vOut, int * pPos ) { int i; word Val = 0; for ( i = 0; i < 8; i++ ) Val |= ((word)(unsigned char)Vec_StrEntry(vOut, (*pPos)++) << (8*i)); return Val; } static inline void Vec_StrPutF( Vec_Str_t * vOut, float Val ) { union { float num; unsigned char data[4]; } tmp; tmp.num = Val; Vec_StrPush( vOut, tmp.data[0] ); Vec_StrPush( vOut, tmp.data[1] ); Vec_StrPush( vOut, tmp.data[2] ); Vec_StrPush( vOut, tmp.data[3] ); } static inline float Vec_StrGetF( Vec_Str_t * vOut, int * pPos ) { union { float num; unsigned char data[4]; } tmp; tmp.data[0] = Vec_StrEntry( vOut, (*pPos)++ ); tmp.data[1] = Vec_StrEntry( vOut, (*pPos)++ ); tmp.data[2] = Vec_StrEntry( vOut, (*pPos)++ ); tmp.data[3] = Vec_StrEntry( vOut, (*pPos)++ ); return tmp.num; } static inline void Vec_StrPutD( Vec_Str_t * vOut, double Val ) { union { double num; unsigned char data[8]; } tmp; int i, Lim = sizeof(double); tmp.num = Val; for ( i = 0; i < Lim; i++ ) Vec_StrPush( vOut, tmp.data[i] ); } static inline double Vec_StrGetD( Vec_Str_t * vOut, int * pPos ) { union { double num; unsigned char data[8]; } tmp; int i, Lim = sizeof(double); for ( i = 0; i < Lim; i++ ) tmp.data[i] = Vec_StrEntry( vOut, (*pPos)++ ); return tmp.num; } static inline void Vec_StrPutS( Vec_Str_t * vOut, char * pStr ) { while ( *pStr ) Vec_StrPush( vOut, *pStr++ ); Vec_StrPush( vOut, (char)0 ); } static inline char * Vec_StrGetS( Vec_Str_t * vOut, int * pPos ) { char * pStr = Vec_StrEntryP( vOut, *pPos ); while ( Vec_StrEntry(vOut, (*pPos)++) ); return Abc_UtilStrsav(pStr); } static inline void Vec_StrPutC( Vec_Str_t * vOut, char c ) { Vec_StrPush( vOut, c ); } static inline char Vec_StrGetC( Vec_Str_t * vOut, int * pPos ) { return Vec_StrEntry(vOut, (*pPos)++); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecVec.h000066400000000000000000000512101300674244400231270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecVec.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable vector of resizable vectors.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecVec_h #define ABC__misc__vec__vecVec_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Vec_t_ Vec_Vec_t; struct Vec_Vec_t_ { int nCap; int nSize; void ** pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // iterators through levels #define Vec_VecForEachLevel( vGlob, vVec, i ) \ for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \ for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelStop( vGlob, vVec, i, LevelStop ) \ for ( i = 0; (i < LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ for ( i = LevelStart; (i < LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \ for ( i = Vec_VecSize(vGlob)-1; (i >= 0) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i-- ) #define Vec_VecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ for ( i = LevelStart-1; (i >= LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i-- ) #define Vec_VecForEachLevelTwo( vGlob1, vGlob2, vVec1, vVec2, i ) \ for ( i = 0; (i < Vec_VecSize(vGlob1)) && (((vVec1) = Vec_VecEntry(vGlob1, i)), 1) && (((vVec2) = Vec_VecEntry(vGlob2, i)), 1); i++ ) // iterators through levels #define Vec_VecForEachLevelInt( vGlob, vVec, i ) \ for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelIntStart( vGlob, vVec, i, LevelStart ) \ for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelIntStop( vGlob, vVec, i, LevelStop ) \ for ( i = 0; (i < LevelStop) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelIntStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ for ( i = LevelStart; (i < LevelStop) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i++ ) #define Vec_VecForEachLevelIntReverse( vGlob, vVec, i ) \ for ( i = Vec_VecSize(vGlob)-1; (i >= 0) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i-- ) #define Vec_VecForEachLevelIntReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ for ( i = LevelStart-1; (i >= LevelStop) && (((vVec) = Vec_VecEntryInt(vGlob, i)), 1); i-- ) #define Vec_VecForEachLevelIntTwo( vGlob1, vGlob2, vVec1, vVec2, i ) \ for ( i = 0; (i < Vec_VecSize(vGlob1)) && (((vVec1) = Vec_VecEntryInt(vGlob1, i)), 1) && (((vVec2) = Vec_VecEntryInt(vGlob2, i)), 1); i++ ) // iteratores through entries #define Vec_VecForEachEntry( Type, vGlob, pEntry, i, k ) \ for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, i), pEntry, k ) #define Vec_VecForEachEntryLevel( Type, vGlob, pEntry, i, Level ) \ Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, Level), pEntry, i ) #define Vec_VecForEachEntryStart( Type, vGlob, pEntry, i, k, LevelStart ) \ for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \ Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, i), pEntry, k ) #define Vec_VecForEachEntryStartStop( Type, vGlob, pEntry, i, k, LevelStart, LevelStop ) \ for ( i = LevelStart; i < LevelStop; i++ ) \ Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, i), pEntry, k ) #define Vec_VecForEachEntryReverse( Type, vGlob, pEntry, i, k ) \ for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ Vec_PtrForEachEntryReverse( Type, Vec_VecEntry(vGlob, i), pEntry, k ) #define Vec_VecForEachEntryReverseReverse( Type, vGlob, pEntry, i, k ) \ for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \ Vec_PtrForEachEntryReverse( Type, Vec_VecEntry(vGlob, i), pEntry, k ) #define Vec_VecForEachEntryReverseStart( Type, vGlob, pEntry, i, k, LevelStart ) \ for ( i = LevelStart-1; i >= 0; i-- ) \ Vec_PtrForEachEntry( Type, Vec_VecEntry(vGlob, i), pEntry, k ) // iteratores through entries #define Vec_VecForEachEntryInt( vGlob, Entry, i, k ) \ for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, i), Entry, k ) #define Vec_VecForEachEntryIntLevel( vGlob, Entry, i, Level ) \ Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, Level), Entry, i ) #define Vec_VecForEachEntryIntStart( vGlob, Entry, i, k, LevelStart ) \ for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \ Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, i), Entry, k ) #define Vec_VecForEachEntryIntStartStop( vGlob, Entry, i, k, LevelStart, LevelStop ) \ for ( i = LevelStart; i < LevelStop; i++ ) \ Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, i), Entry, k ) #define Vec_VecForEachEntryIntReverse( vGlob, Entry, i, k ) \ for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ Vec_IntForEachEntryReverse( Vec_VecEntryInt(vGlob, i), Entry, k ) #define Vec_VecForEachEntryIntReverseReverse( vGlob, Entry, i, k ) \ for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \ Vec_IntForEachEntryReverse( Vec_VecEntryInt(vGlob, i), Entry, k ) #define Vec_VecForEachEntryIntReverseStart( vGlob, Entry, i, k, LevelStart ) \ for ( i = LevelStart-1; i >= 0; i-- ) \ Vec_IntForEachEntry( Vec_VecEntryInt(vGlob, i), Entry, k ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Vec_t * Vec_VecAlloc( int nCap ) { Vec_Vec_t * p; p = ABC_ALLOC( Vec_Vec_t, 1 ); if ( nCap > 0 && nCap < 8 ) nCap = 8; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( void *, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Vec_t * Vec_VecStart( int nSize ) { Vec_Vec_t * p; int i; p = Vec_VecAlloc( nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = Vec_PtrAlloc( 0 ); p->nSize = nSize; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecExpand( Vec_Vec_t * p, int Level ) { int i; if ( p->nSize >= Level + 1 ) return; Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); for ( i = p->nSize; i <= Level; i++ ) p->pArray[i] = Vec_PtrAlloc( 0 ); p->nSize = Level + 1; } static inline void Vec_VecExpandInt( Vec_Vec_t * p, int Level ) { int i; if ( p->nSize >= Level + 1 ) return; Vec_IntGrow( (Vec_Int_t *)p, Level + 1 ); for ( i = p->nSize; i <= Level; i++ ) p->pArray[i] = Vec_PtrAlloc( 0 ); p->nSize = Level + 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_VecSize( Vec_Vec_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_VecCap( Vec_Vec_t * p ) { return p->nCap; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_VecLevelSize( Vec_Vec_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return Vec_PtrSize( (Vec_Ptr_t *)p->pArray[i] ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_VecEntry( Vec_Vec_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return (Vec_Ptr_t *)p->pArray[i]; } static inline Vec_Int_t * Vec_VecEntryInt( Vec_Vec_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return (Vec_Int_t *)p->pArray[i]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_VecMemory( Vec_Vec_t * p ) { int i; double Mem; if ( p == NULL ) return 0.0; Mem = Vec_PtrMemory( (Vec_Ptr_t *)p ); for ( i = 0; i < p->nSize; i++ ) if ( Vec_VecEntry(p, i) ) Mem += Vec_PtrMemory( Vec_VecEntry(p, i) ); return Mem; } static inline double Vec_VecMemoryInt( Vec_Vec_t * p ) { int i; double Mem; if ( p == NULL ) return 0.0; Mem = Vec_PtrMemory( (Vec_Ptr_t *)p ); for ( i = 0; i < p->nSize; i++ ) if ( Vec_VecEntry(p, i) ) Mem += Vec_IntMemory( Vec_VecEntryInt(p, i) ); return Mem; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Vec_VecEntryEntry( Vec_Vec_t * p, int i, int k ) { return Vec_PtrEntry( Vec_VecEntry(p, i), k ); } static inline int Vec_VecEntryEntryInt( Vec_Vec_t * p, int i, int k ) { return Vec_IntEntry( Vec_VecEntryInt(p, i), k ); } /**Function************************************************************* Synopsis [Frees the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecFree( Vec_Vec_t * p ) { Vec_Ptr_t * vVec; int i; Vec_VecForEachLevel( p, vVec, i ) if ( vVec ) Vec_PtrFree( vVec ); Vec_PtrFree( (Vec_Ptr_t *)p ); } static inline void Vec_VecErase( Vec_Vec_t * p ) { Vec_Ptr_t * vVec; int i; Vec_VecForEachLevel( p, vVec, i ) if ( vVec ) Vec_PtrFree( vVec ); Vec_PtrErase( (Vec_Ptr_t *)p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecFreeP( Vec_Vec_t ** p ) { if ( *p == NULL ) return; Vec_VecFree( *p ); *p = NULL; } /**Function************************************************************* Synopsis [Frees the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Vec_t * Vec_VecDup( Vec_Vec_t * p ) { Vec_Ptr_t * vNew, * vVec; int i; vNew = Vec_PtrAlloc( Vec_VecSize(p) ); Vec_VecForEachLevel( p, vVec, i ) Vec_PtrPush( vNew, Vec_PtrDup(vVec) ); return (Vec_Vec_t *)vNew; } static inline Vec_Vec_t * Vec_VecDupInt( Vec_Vec_t * p ) { Vec_Ptr_t * vNew; Vec_Int_t * vVec; int i; vNew = Vec_PtrAlloc( Vec_VecSize(p) ); Vec_VecForEachLevelInt( p, vVec, i ) Vec_PtrPush( vNew, Vec_IntDup(vVec) ); return (Vec_Vec_t *)vNew; } /**Function************************************************************* Synopsis [Frees the vector of vectors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_VecSizeSize( Vec_Vec_t * p ) { Vec_Ptr_t * vVec; int i, Counter = 0; Vec_VecForEachLevel( p, vVec, i ) Counter += vVec->nSize; return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecClear( Vec_Vec_t * p ) { Vec_Ptr_t * vVec; int i; Vec_VecForEachLevel( p, vVec, i ) Vec_PtrClear( vVec ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry ) { if ( p->nSize < Level + 1 ) { int i; Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); for ( i = p->nSize; i < Level + 1; i++ ) p->pArray[i] = Vec_PtrAlloc( 0 ); p->nSize = Level + 1; } Vec_PtrPush( Vec_VecEntry(p, Level), Entry ); } static inline void Vec_VecPushInt( Vec_Vec_t * p, int Level, int Entry ) { if ( p->nSize < Level + 1 ) { int i; Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); for ( i = p->nSize; i < Level + 1; i++ ) p->pArray[i] = Vec_IntAlloc( 0 ); p->nSize = Level + 1; } Vec_IntPush( Vec_VecEntryInt(p, Level), Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry ) { if ( p->nSize < Level + 1 ) Vec_VecPush( p, Level, Entry ); else Vec_PtrPushUnique( Vec_VecEntry(p, Level), Entry ); } static inline void Vec_VecPushUniqueInt( Vec_Vec_t * p, int Level, int Entry ) { if ( p->nSize < Level + 1 ) Vec_VecPushInt( p, Level, Entry ); else Vec_IntPushUnique( Vec_VecEntryInt(p, Level), Entry ); } /**Function************************************************************* Synopsis [Comparison procedure for two arrays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) { if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) return -1; if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) return 1; return 0; } static int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) { if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) return -1; if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(void *), (int (*)(const void *, const void *)) Vec_VecSortCompare2 ); else qsort( (void *)p->pArray, p->nSize, sizeof(void *), (int (*)(const void *, const void *)) Vec_VecSortCompare1 ); } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_VecSortCompare3( Vec_Int_t ** pp1, Vec_Int_t ** pp2 ) { if ( Vec_IntEntry(*pp1,0) < Vec_IntEntry(*pp2,0) ) return -1; if ( Vec_IntEntry(*pp1,0) > Vec_IntEntry(*pp2,0) ) return 1; return 0; } static int Vec_VecSortCompare4( Vec_Int_t ** pp1, Vec_Int_t ** pp2 ) { if ( Vec_IntEntry(*pp1,0) > Vec_IntEntry(*pp2,0) ) return -1; if ( Vec_IntEntry(*pp1,0) < Vec_IntEntry(*pp2,0) ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecSortByFirstInt( Vec_Vec_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(void *), (int (*)(const void *, const void *)) Vec_VecSortCompare4 ); else qsort( (void *)p->pArray, p->nSize, sizeof(void *), (int (*)(const void *, const void *)) Vec_VecSortCompare3 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_VecPrintInt( Vec_Vec_t * p, int fSkipSingles ) { int i, k, Entry; Vec_VecForEachEntryInt( p, Entry, i, k ) { if ( fSkipSingles && Vec_VecLevelSize(p, i) == 1 ) break; if ( k == 0 ) printf( " %4d : {", i ); printf( " %d", Entry ); if ( k == Vec_VecLevelSize(p, i) - 1 ) printf( " }\n" ); } } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecWec.h000066400000000000000000000466661300674244400231530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecWec.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable vector of resizable vectors.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecWec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecWec_h #define ABC__misc__vec__vecWec_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Wec_t_ Vec_Wec_t; struct Vec_Wec_t_ { int nCap; int nSize; Vec_Int_t * pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // iterators through levels #define Vec_WecForEachLevel( vGlob, vVec, i ) \ for ( i = 0; (i < Vec_WecSize(vGlob)) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i++ ) #define Vec_WecForEachLevelVec( vLevels, vGlob, vVec, i ) \ for ( i = 0; (i < Vec_IntSize(vLevels)) && (((vVec) = Vec_WecEntry(vGlob, Vec_IntEntry(vLevels, i))), 1); i++ ) #define Vec_WecForEachLevelStart( vGlob, vVec, i, LevelStart ) \ for ( i = LevelStart; (i < Vec_WecSize(vGlob)) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i++ ) #define Vec_WecForEachLevelStop( vGlob, vVec, i, LevelStop ) \ for ( i = 0; (i < LevelStop) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i++ ) #define Vec_WecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ for ( i = LevelStart; (i < LevelStop) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i++ ) #define Vec_WecForEachLevelReverse( vGlob, vVec, i ) \ for ( i = Vec_WecSize(vGlob)-1; (i >= 0) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i-- ) #define Vec_WecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ for ( i = LevelStart-1; (i >= LevelStop) && (((vVec) = Vec_WecEntry(vGlob, i)), 1); i-- ) #define Vec_WecForEachLevelTwo( vGlob1, vGlob2, vVec1, vVec2, i ) \ for ( i = 0; (i < Vec_WecSize(vGlob1)) && (((vVec1) = Vec_WecEntry(vGlob1, i)), 1) && (((vVec2) = Vec_WecEntry(vGlob2, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wec_t * Vec_WecAlloc( int nCap ) { Vec_Wec_t * p; p = ABC_ALLOC( Vec_Wec_t, 1 ); if ( nCap > 0 && nCap < 8 ) nCap = 8; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_CALLOC( Vec_Int_t, p->nCap ) : NULL; return p; } static inline Vec_Wec_t * Vec_WecAllocExact( int nCap ) { Vec_Wec_t * p; assert( nCap >= 0 ); p = ABC_ALLOC( Vec_Wec_t, 1 ); p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_CALLOC( Vec_Int_t, p->nCap ) : NULL; return p; } static inline Vec_Wec_t * Vec_WecStart( int nSize ) { Vec_Wec_t * p; p = Vec_WecAlloc( nSize ); p->nSize = nSize; return p; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WecGrow( Vec_Wec_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( Vec_Int_t, p->pArray, nCapMin ); memset( p->pArray + p->nCap, 0, sizeof(Vec_Int_t) * (nCapMin - p->nCap) ); p->nCap = nCapMin; } static inline void Vec_WecInit( Vec_Wec_t * p, int nSize ) { Vec_WecGrow( p, nSize ); p->nSize = nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_WecEntry( Vec_Wec_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray + i; } static inline Vec_Int_t * Vec_WecEntryLast( Vec_Wec_t * p ) { assert( p->nSize > 0 ); return p->pArray + p->nSize - 1; } static inline int Vec_WecEntryEntry( Vec_Wec_t * p, int i, int k ) { return Vec_IntEntry( Vec_WecEntry(p, i), k ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_WecArray( Vec_Wec_t * p ) { return p->pArray; } static inline int Vec_WecLevelId( Vec_Wec_t * p, Vec_Int_t * vLevel ) { assert( p->pArray <= vLevel && vLevel < p->pArray + p->nSize ); return vLevel - p->pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WecCap( Vec_Wec_t * p ) { return p->nCap; } static inline int Vec_WecSize( Vec_Wec_t * p ) { return p->nSize; } static inline int Vec_WecLevelSize( Vec_Wec_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return Vec_IntSize( p->pArray + i ); } static inline int Vec_WecSizeSize( Vec_Wec_t * p ) { Vec_Int_t * vVec; int i, Counter = 0; Vec_WecForEachLevel( p, vVec, i ) Counter += Vec_IntSize(vVec); return Counter; } static inline int Vec_WecSizeUsed( Vec_Wec_t * p ) { Vec_Int_t * vVec; int i, Counter = 0; Vec_WecForEachLevel( p, vVec, i ) Counter += (int)(Vec_IntSize(vVec) > 0); return Counter; } static inline int Vec_WecSizeUsedLimits( Vec_Wec_t * p, int iStart, int iStop ) { Vec_Int_t * vVec; int i, Counter = 0; Vec_WecForEachLevelStartStop( p, vVec, i, iStart, iStop ) Counter += (int)(Vec_IntSize(vVec) > 0); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WecShrink( Vec_Wec_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WecClear( Vec_Wec_t * p ) { Vec_Int_t * vVec; int i; Vec_WecForEachLevel( p, vVec, i ) Vec_IntClear( vVec ); p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WecPush( Vec_Wec_t * p, int Level, int Entry ) { if ( p->nSize < Level + 1 ) { Vec_WecGrow( p, Abc_MaxInt(2*p->nSize, Level + 1) ); p->nSize = Level + 1; } Vec_IntPush( Vec_WecEntry(p, Level), Entry ); } static inline Vec_Int_t * Vec_WecPushLevel( Vec_Wec_t * p ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_WecGrow( p, 16 ); else Vec_WecGrow( p, 2 * p->nCap ); } ++p->nSize; return Vec_WecEntryLast( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_WecMemory( Vec_Wec_t * p ) { int i; double Mem; if ( p == NULL ) return 0.0; Mem = sizeof(Vec_Int_t) * Vec_WecCap(p); for ( i = 0; i < p->nSize; i++ ) Mem += sizeof(int) * Vec_IntCap( Vec_WecEntry(p, i) ); return Mem; } /**Function************************************************************* Synopsis [Frees the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WecZero( Vec_Wec_t * p ) { p->pArray = NULL; p->nSize = 0; p->nCap = 0; } static inline void Vec_WecErase( Vec_Wec_t * p ) { int i; for ( i = 0; i < p->nCap; i++ ) ABC_FREE( p->pArray[i].pArray ); ABC_FREE( p->pArray ); p->nSize = 0; p->nCap = 0; } static inline void Vec_WecFree( Vec_Wec_t * p ) { Vec_WecErase( p ); ABC_FREE( p ); } static inline void Vec_WecFreeP( Vec_Wec_t ** p ) { if ( *p == NULL ) return; Vec_WecFree( *p ); *p = NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WecPushUnique( Vec_Wec_t * p, int Level, int Entry ) { if ( p->nSize < Level + 1 ) Vec_WecPush( p, Level, Entry ); else Vec_IntPushUnique( Vec_WecEntry(p, Level), Entry ); } /**Function************************************************************* Synopsis [Frees the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wec_t * Vec_WecDup( Vec_Wec_t * p ) { Vec_Wec_t * vNew; Vec_Int_t * vVec; int i, k, Entry; vNew = Vec_WecAlloc( Vec_WecSize(p) ); Vec_WecForEachLevel( p, vVec, i ) Vec_IntForEachEntry( vVec, Entry, k ) Vec_WecPush( vNew, i, Entry ); return vNew; } /**Function************************************************************* Synopsis [Sorting by array size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_WecSortCompare1( Vec_Int_t * p1, Vec_Int_t * p2 ) { if ( Vec_IntSize(p1) < Vec_IntSize(p2) ) return -1; if ( Vec_IntSize(p1) > Vec_IntSize(p2) ) return 1; return 0; } static int Vec_WecSortCompare2( Vec_Int_t * p1, Vec_Int_t * p2 ) { if ( Vec_IntSize(p1) > Vec_IntSize(p2) ) return -1; if ( Vec_IntSize(p1) < Vec_IntSize(p2) ) return 1; return 0; } static inline void Vec_WecSort( Vec_Wec_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), (int (*)(const void *, const void *)) Vec_WecSortCompare2 ); else qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), (int (*)(const void *, const void *)) Vec_WecSortCompare1 ); } /**Function************************************************************* Synopsis [Sorting by the first entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_WecSortCompare3( Vec_Int_t * p1, Vec_Int_t * p2 ) { if ( Vec_IntEntry(p1,0) < Vec_IntEntry(p2,0) ) return -1; if ( Vec_IntEntry(p1,0) > Vec_IntEntry(p2,0) ) return 1; return 0; } static int Vec_WecSortCompare4( Vec_Int_t * p1, Vec_Int_t * p2 ) { if ( Vec_IntEntry(p1,0) > Vec_IntEntry(p2,0) ) return -1; if ( Vec_IntEntry(p1,0) < Vec_IntEntry(p2,0) ) return 1; return 0; } static inline void Vec_WecSortByFirstInt( Vec_Wec_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), (int (*)(const void *, const void *)) Vec_WecSortCompare4 ); else qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), (int (*)(const void *, const void *)) Vec_WecSortCompare3 ); } /**Function************************************************************* Synopsis [Sorting by the last entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_WecSortCompare5( Vec_Int_t * p1, Vec_Int_t * p2 ) { if ( Vec_IntEntryLast(p1) < Vec_IntEntryLast(p2) ) return -1; if ( Vec_IntEntryLast(p1) > Vec_IntEntryLast(p2) ) return 1; return 0; } static int Vec_WecSortCompare6( Vec_Int_t * p1, Vec_Int_t * p2 ) { if ( Vec_IntEntryLast(p1) > Vec_IntEntryLast(p2) ) return -1; if ( Vec_IntEntryLast(p1) < Vec_IntEntryLast(p2) ) return 1; return 0; } static inline void Vec_WecSortByLastInt( Vec_Wec_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), (int (*)(const void *, const void *)) Vec_WecSortCompare6 ); else qsort( (void *)p->pArray, p->nSize, sizeof(Vec_Int_t), (int (*)(const void *, const void *)) Vec_WecSortCompare5 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WecPrint( Vec_Wec_t * p, int fSkipSingles ) { Vec_Int_t * vVec; int i, k, Entry; Vec_WecForEachLevel( p, vVec, i ) { if ( fSkipSingles && Vec_IntSize(vVec) == 1 ) continue; printf( " %4d : {", i ); Vec_IntForEachEntry( vVec, Entry, k ) printf( " %d", Entry ); printf( " }\n" ); } } /**Function************************************************************* Synopsis [Derives the set of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wec_t * Vec_WecCreateClasses( Vec_Int_t * vMap ) { Vec_Wec_t * vClasses; int i, Entry; vClasses = Vec_WecStart( Vec_IntFindMax(vMap) + 1 ); Vec_IntForEachEntry( vMap, Entry, i ) Vec_WecPush( vClasses, Entry, i ); return vClasses; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WecCountNonTrivial( Vec_Wec_t * p, int * pnUsed ) { Vec_Int_t * vClass; int i, nClasses = 0; *pnUsed = 0; Vec_WecForEachLevel( p, vClass, i ) { if ( Vec_IntSize(vClass) < 2 ) continue; nClasses++; (*pnUsed) += Vec_IntSize(vClass); } return nClasses; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_WecCollectFirsts( Vec_Wec_t * p ) { Vec_Int_t * vFirsts, * vLevel; int i; vFirsts = Vec_IntAlloc( Vec_WecSize(p) ); Vec_WecForEachLevel( p, vLevel, i ) if ( Vec_IntSize(vLevel) > 0 ) Vec_IntPush( vFirsts, Vec_IntEntry(vLevel, 0) ); return vFirsts; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Ptr_t * Vec_WecConvertToVecPtr( Vec_Wec_t * p ) { Vec_Ptr_t * vCopy; Vec_Int_t * vLevel; int i; vCopy = Vec_PtrAlloc( Vec_WecSize(p) ); Vec_WecForEachLevel( p, vLevel, i ) Vec_PtrPush( vCopy, Vec_IntDup(vLevel) ); return vCopy; } /**Function************************************************************* Synopsis [Temporary vector marking.] Description [The vector should be static when the marking is used.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WecIntHasMark( Vec_Int_t * vVec ) { return (vVec->nCap >> 30) & 1; } static inline void Vec_WecIntSetMark( Vec_Int_t * vVec ) { vVec->nCap |= (1<<30); } static inline void Vec_WecIntXorMark( Vec_Int_t * vVec ) { vVec->nCap ^= (1<<30); } static inline void Vec_WecMarkLevels( Vec_Wec_t * vCubes, Vec_Int_t * vLevels ) { Vec_Int_t * vCube; int i; Vec_WecForEachLevelVec( vLevels, vCubes, vCube, i ) { assert( !Vec_WecIntHasMark( vCube ) ); Vec_WecIntXorMark( vCube ); } } static inline void Vec_WecUnmarkLevels( Vec_Wec_t * vCubes, Vec_Int_t * vLevels ) { Vec_Int_t * vCube; int i; Vec_WecForEachLevelVec( vLevels, vCubes, vCube, i ) { assert( Vec_WecIntHasMark( vCube ) ); Vec_WecIntXorMark( vCube ); } } /**Function************************************************************* Synopsis [Removes 0-size vectors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WecRemoveEmpty( Vec_Wec_t * vCubes ) { Vec_Int_t * vCube; int i, k = 0; Vec_WecForEachLevel( vCubes, vCube, i ) if ( Vec_IntSize(vCube) > 0 ) vCubes->pArray[k++] = *vCube; else ABC_FREE( vCube->pArray ); for ( i = k; i < Vec_WecSize(vCubes); i++ ) Vec_IntZero( Vec_WecEntry(vCubes, i) ); Vec_WecShrink( vCubes, k ); // Vec_WecSortByFirstInt( vCubes, 0 ); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/vec/vecWrd.h000066400000000000000000000720341300674244400231550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [vecWrd.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resizable arrays.] Synopsis [Resizable arrays of long unsigned integers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: vecWrd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__misc__vec__vecWrd_h #define ABC__misc__vec__vecWrd_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Vec_Wrd_t_ Vec_Wrd_t; struct Vec_Wrd_t_ { int nCap; int nSize; word * pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Vec_WrdForEachEntry( vVec, Entry, i ) \ for ( i = 0; (i < Vec_WrdSize(vVec)) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ ) #define Vec_WrdForEachEntryStart( vVec, Entry, i, Start ) \ for ( i = Start; (i < Vec_WrdSize(vVec)) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ ) #define Vec_WrdForEachEntryStop( vVec, Entry, i, Stop ) \ for ( i = 0; (i < Stop) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ ) #define Vec_WrdForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ for ( i = Start; (i < Stop) && (((Entry) = Vec_WrdEntry(vVec, i)), 1); i++ ) #define Vec_WrdForEachEntryReverse( vVec, pEntry, i ) \ for ( i = Vec_WrdSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_WrdEntry(vVec, i)), 1); i-- ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdAlloc( int nCap ) { Vec_Wrd_t * p; p = ABC_ALLOC( Vec_Wrd_t, 1 ); if ( nCap > 0 && nCap < 16 ) nCap = 16; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( word, p->nCap ) : NULL; return p; } static inline Vec_Wrd_t * Vec_WrdAllocExact( int nCap ) { Vec_Wrd_t * p; assert( nCap >= 0 ); p = ABC_ALLOC( Vec_Wrd_t, 1 ); p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( word, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdStart( int nSize ) { Vec_Wrd_t * p; p = Vec_WrdAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0, sizeof(word) * nSize ); return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdStartFull( int nSize ) { Vec_Wrd_t * p; p = Vec_WrdAlloc( nSize ); p->nSize = nSize; memset( p->pArray, 0xff, sizeof(word) * nSize ); return p; } /**Function************************************************************* Synopsis [Allocates a vector with the given size and cleans it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdStartNatural( int nSize ) { Vec_Wrd_t * p; int i; p = Vec_WrdAlloc( nSize ); p->nSize = nSize; for ( i = 0; i < nSize; i++ ) p->pArray[i] = i; return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdAllocArray( word * pArray, int nSize ) { Vec_Wrd_t * p; p = ABC_ALLOC( Vec_Wrd_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = pArray; return p; } /**Function************************************************************* Synopsis [Creates the vector from an integer array of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdAllocArrayCopy( word * pArray, int nSize ) { Vec_Wrd_t * p; p = ABC_ALLOC( Vec_Wrd_t, 1 ); p->nSize = nSize; p->nCap = nSize; p->pArray = ABC_ALLOC( word, nSize ); memcpy( p->pArray, pArray, sizeof(word) * nSize ); return p; } /**Function************************************************************* Synopsis [Duplicates the integer array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdDup( Vec_Wrd_t * pVec ) { Vec_Wrd_t * p; p = ABC_ALLOC( Vec_Wrd_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nSize; p->pArray = p->nCap? ABC_ALLOC( word, p->nCap ) : NULL; memcpy( p->pArray, pVec->pArray, sizeof(word) * pVec->nSize ); return p; } /**Function************************************************************* Synopsis [Transfers the array into another vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdDupArray( Vec_Wrd_t * pVec ) { Vec_Wrd_t * p; p = ABC_ALLOC( Vec_Wrd_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = pVec->pArray; pVec->nSize = 0; pVec->nCap = 0; pVec->pArray = NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdErase( Vec_Wrd_t * p ) { ABC_FREE( p->pArray ); p->nSize = 0; p->nCap = 0; } static inline void Vec_WrdFree( Vec_Wrd_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdFreeP( Vec_Wrd_t ** p ) { if ( *p == NULL ) return; ABC_FREE( (*p)->pArray ); ABC_FREE( (*p) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Vec_WrdReleaseArray( Vec_Wrd_t * p ) { word * pArray = p->pArray; p->nCap = 0; p->nSize = 0; p->pArray = NULL; return pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Vec_WrdArray( Vec_Wrd_t * p ) { return p->pArray; } static inline word * Vec_WrdLimit( Vec_Wrd_t * p ) { return p->pArray + p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdSize( Vec_Wrd_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdCap( Vec_Wrd_t * p ) { return p->nCap; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline double Vec_WrdMemory( Vec_Wrd_t * p ) { return !p ? 0.0 : 1.0 * sizeof(word) * p->nCap + sizeof(Vec_Wrd_t); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Vec_WrdEntry( Vec_Wrd_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Vec_WrdEntryP( Vec_Wrd_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray + i; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdWriteEntry( Vec_Wrd_t * p, int i, word Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Vec_WrdAddToEntry( Vec_Wrd_t * p, int i, word Addition ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i] += Addition; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Vec_WrdEntryLast( Vec_Wrd_t * p ) { assert( p->nSize > 0 ); return p->pArray[p->nSize-1]; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdGrow( Vec_Wrd_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( word, p->pArray, nCapMin ); assert( p->pArray ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdFill( Vec_Wrd_t * p, int nSize, word Fill ) { int i; Vec_WrdGrow( p, nSize ); for ( i = 0; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } /**Function************************************************************* Synopsis [Fills the vector with given number of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdFillExtra( Vec_Wrd_t * p, int nSize, word Fill ) { int i; if ( nSize <= p->nSize ) return; if ( nSize > 2 * p->nCap ) Vec_WrdGrow( p, nSize ); else if ( nSize > p->nCap ) Vec_WrdGrow( p, 2 * p->nCap ); for ( i = p->nSize; i < nSize; i++ ) p->pArray[i] = Fill; p->nSize = nSize; } /**Function************************************************************* Synopsis [Returns the entry even if the place not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Vec_WrdGetEntry( Vec_Wrd_t * p, int i ) { Vec_WrdFillExtra( p, i + 1, 0 ); return Vec_WrdEntry( p, i ); } /**Function************************************************************* Synopsis [Returns the entry even if the place not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Vec_WrdGetEntryP( Vec_Wrd_t * p, int i ) { Vec_WrdFillExtra( p, i + 1, 0 ); return Vec_WrdEntryP( p, i ); } /**Function************************************************************* Synopsis [Inserts the entry even if the place does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdSetEntry( Vec_Wrd_t * p, int i, word Entry ) { Vec_WrdFillExtra( p, i + 1, 0 ); Vec_WrdWriteEntry( p, i, Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdShrink( Vec_Wrd_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdClear( Vec_Wrd_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdPush( Vec_Wrd_t * p, word Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_WrdGrow( p, 16 ); else Vec_WrdGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdPushFirst( Vec_Wrd_t * p, word Entry ) { int i; if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_WrdGrow( p, 16 ); else Vec_WrdGrow( p, 2 * p->nCap ); } p->nSize++; for ( i = p->nSize - 1; i >= 1; i-- ) p->pArray[i] = p->pArray[i-1]; p->pArray[0] = Entry; } /**Function************************************************************* Synopsis [Inserts the entry while preserving the increasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdPushOrder( Vec_Wrd_t * p, word Entry ) { int i; if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Vec_WrdGrow( p, 16 ); else Vec_WrdGrow( p, 2 * p->nCap ); } p->nSize++; for ( i = p->nSize-2; i >= 0; i-- ) if ( p->pArray[i] > Entry ) p->pArray[i+1] = p->pArray[i]; else break; p->pArray[i+1] = Entry; } /**Function************************************************************* Synopsis [Inserts the entry while preserving the increasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdPushUniqueOrder( Vec_Wrd_t * p, word Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Vec_WrdPushOrder( p, Entry ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdPushUnique( Vec_Wrd_t * p, word Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Vec_WrdPush( p, Entry ); return 0; } /**Function************************************************************* Synopsis [Returns the pointer to the next nWords entries in the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Vec_WrdFetch( Vec_Wrd_t * p, int nWords ) { if ( nWords == 0 ) return NULL; assert( nWords > 0 ); p->nSize += nWords; if ( p->nSize > p->nCap ) { // Vec_WrdGrow( p, 2 * p->nSize ); return NULL; } return p->pArray + p->nSize - nWords; } /**Function************************************************************* Synopsis [Returns the last entry and removes it from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Vec_WrdPop( Vec_Wrd_t * p ) { assert( p->nSize > 0 ); return p->pArray[--p->nSize]; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdFind( Vec_Wrd_t * p, word Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return i; return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdRemove( Vec_Wrd_t * p, word Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) break; if ( i == p->nSize ) return 0; assert( i < p->nSize ); for ( i++; i < p->nSize; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; return 1; } /**Function************************************************************* Synopsis [Interts entry at the index iHere. Shifts other entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdInsert( Vec_Wrd_t * p, int iHere, word Entry ) { int i; assert( iHere >= 0 && iHere < p->nSize ); Vec_WrdPush( p, 0 ); for ( i = p->nSize - 1; i > iHere; i-- ) p->pArray[i] = p->pArray[i-1]; p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Vec_WrdFindMax( Vec_Wrd_t * p ) { word Best; int i; if ( p->nSize == 0 ) return 0; Best = p->pArray[0]; for ( i = 1; i < p->nSize; i++ ) if ( Best < p->pArray[i] ) Best = p->pArray[i]; return Best; } /**Function************************************************************* Synopsis [Find entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Vec_WrdFindMin( Vec_Wrd_t * p ) { word Best; int i; if ( p->nSize == 0 ) return 0; Best = p->pArray[0]; for ( i = 1; i < p->nSize; i++ ) if ( Best > p->pArray[i] ) Best = p->pArray[i]; return Best; } /**Function************************************************************* Synopsis [Reverses the order of entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdReverseOrder( Vec_Wrd_t * p ) { word Temp; int i; for ( i = 0; i < p->nSize/2; i++ ) { Temp = p->pArray[i]; p->pArray[i] = p->pArray[p->nSize-1-i]; p->pArray[p->nSize-1-i] = Temp; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Wrd_t * Vec_WrdInvert( Vec_Wrd_t * p, word Fill ) { int i; word Entry; Vec_Wrd_t * vRes = Vec_WrdAlloc( 0 ); Vec_WrdFill( vRes, Vec_WrdFindMax(p) + 1, Fill ); Vec_WrdForEachEntry( p, Entry, i ) if ( Entry != Fill ) Vec_WrdWriteEntry( vRes, Entry, i ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Vec_WrdSum( Vec_Wrd_t * p ) { word Counter = 0; int i; for ( i = 0; i < p->nSize; i++ ) Counter += p->pArray[i]; return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdCountZero( Vec_Wrd_t * p ) { int i, Counter = 0; for ( i = 0; i < p->nSize; i++ ) Counter += (p->pArray[i] == 0); return Counter; } /**Function************************************************************* Synopsis [Checks if two vectors are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdEqual( Vec_Wrd_t * p1, Vec_Wrd_t * p2 ) { int i; if ( p1->nSize != p2->nSize ) return 0; for ( i = 0; i < p1->nSize; i++ ) if ( p1->pArray[i] != p2->pArray[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Counts the number of common entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_WrdCountCommon( Vec_Wrd_t * p1, Vec_Wrd_t * p2 ) { Vec_Wrd_t * vTemp; word Entry; int i, Counter = 0; if ( Vec_WrdSize(p1) < Vec_WrdSize(p2) ) vTemp = p1, p1 = p2, p2 = vTemp; assert( Vec_WrdSize(p1) >= Vec_WrdSize(p2) ); vTemp = Vec_WrdInvert( p2, -1 ); Vec_WrdFillExtra( vTemp, Vec_WrdFindMax(p1) + 1, ~((word)0) ); Vec_WrdForEachEntry( p1, Entry, i ) if ( Vec_WrdEntry(vTemp, Entry) != ~((word)0) ) Counter++; Vec_WrdFree( vTemp ); return Counter; } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_WrdSortCompare1( word * pp1, word * pp2 ) { // for some reason commenting out lines (as shown) led to crashing of the release version if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) // return 1; return 0; // } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_WrdSortCompare2( word * pp1, word * pp2 ) { // for some reason commenting out lines (as shown) led to crashing of the release version if ( *pp1 > *pp2 ) return -1; if ( *pp1 < *pp2 ) // return 1; return 0; // } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdSort( Vec_Wrd_t * p, int fReverse ) { if ( fReverse ) qsort( (void *)p->pArray, p->nSize, sizeof(word), (int (*)(const void *, const void *)) Vec_WrdSortCompare2 ); else qsort( (void *)p->pArray, p->nSize, sizeof(word), (int (*)(const void *, const void *)) Vec_WrdSortCompare1 ); } /**Function************************************************************* Synopsis [Leaves only unique entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdUniqify( Vec_Wrd_t * p ) { int i, k; if ( p->nSize < 2 ) return; Vec_WrdSort( p, 0 ); for ( i = k = 1; i < p->nSize; i++ ) if ( p->pArray[i] != p->pArray[i-1] ) p->pArray[k++] = p->pArray[i]; p->nSize = k; } static inline int Vec_WrdUniqueCount( Vec_Wrd_t * vData, int nWordSize, Vec_Int_t ** pvMap ) { int Result; Vec_Int_t * vDataInt = (Vec_Int_t *)vData; vDataInt->nSize *= 2; vDataInt->nCap *= 2; Result = Vec_IntUniqueCount( vDataInt, 2 * nWordSize, pvMap ); vDataInt->nSize /= 2; vDataInt->nCap /= 2; return Result; } static inline Vec_Wrd_t * Vec_WrdUniqifyHash( Vec_Wrd_t * vData, int nWordSize ) { Vec_Int_t * vResInt; Vec_Int_t * vDataInt = (Vec_Int_t *)vData; vDataInt->nSize *= 2; vDataInt->nCap *= 2; vResInt = Vec_IntUniqifyHash( vDataInt, 2 * nWordSize ); vDataInt->nSize /= 2; vDataInt->nCap /= 2; vResInt->nSize /= 2; vResInt->nCap /= 2; return (Vec_Wrd_t *)vResInt; } /**Function************************************************************* Synopsis [Comparison procedure for two integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Vec_WrdSortCompareUnsigned( word * pp1, word * pp2 ) { if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdSortUnsigned( Vec_Wrd_t * p ) { qsort( (void *)p->pArray, p->nSize, sizeof(word), (int (*)(const void *, const void *)) Vec_WrdSortCompareUnsigned ); } /**Function************************************************************* Synopsis [Appends the contents of the second vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_WrdAppend( Vec_Wrd_t * vVec1, Vec_Wrd_t * vVec2 ) { word Entry; int i; Vec_WrdForEachEntry( vVec2, Entry, i ) Vec_WrdPush( vVec1, Entry ); } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/000077500000000000000000000000001300674244400217275ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/README000066400000000000000000000121201300674244400226030ustar00rootroot00000000000000ZLIB DATA COMPRESSION LIBRARY zlib 1.2.5 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). All functions of the compression library are documented in the file zlib.h (volunteer to write man pages welcome, contact zlib@gzip.org). A usage example of the library is given in the file example.c which also tests that the library is working correctly. Another example is given in the file minigzip.c. The compression library itself is composed of all source files except example.c and minigzip.c. To compile all files and run the test program, follow the instructions given at the top of Makefile.in. In short "./configure; make test", and if that goes well, "make install" should work for most flavors of Unix. For Windows, use one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use make_vms.com. Questions about zlib should be sent to , or to Gilles Vollant for the Windows DLL version. The zlib home page is http://zlib.net/ . Before reporting a problem, please check this site to verify that you have the latest version of zlib; otherwise get the latest version and check whether the problem still exists or not. PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at http://marknelson.us/1997/01/01/zlib-engine/ . The changes made in version 1.2.5 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . zlib is available in Java using the java.util.zip package, documented at http://java.sun.com/developer/technicalArticles/Programming/compression/ . A Perl interface to zlib written by Paul Marquess is available at CPAN (Comprehensive Perl Archive Network) sites, including http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see http://www.python.org/doc/lib/module-zlib.html . zlib is built into tcl: http://wiki.tcl.tk/4610 . An experimental package to read and write files in .zip format, written on top of zlib by Gilles Vollant , is available in the contrib/minizip directory of zlib. Notes for some targets: - For Windows DLL versions, please see win32/DLL_FAQ.txt - For 64-bit Irix, deflate.c must be compiled without any optimization. With -O, one libpng test fails. The test works in 32 bit mode (with the -n32 compiler flag). The compiler bug has been reported to SGI. - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works when compiled with cc. - On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is necessary to get gzprintf working correctly. This is done by configure. - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with other compilers. Use "make test" to check your compiler. - gzdopen is not supported on RISCOS or BEOS. - For PalmOs, see http://palmzlib.sourceforge.net/ Acknowledgments: The deflate format used by zlib was defined by Phil Katz. The deflate and zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in zlib; they are too numerous to cite here. Copyright notice: (C) 1995-2010 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/adler32.c000066400000000000000000000117071300674244400233350ustar00rootroot00000000000000/* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2007 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include #include #include #include "misc/util/abc_global.h" #include "zutil.h" ABC_NAMESPACE_IMPL_START #define local static local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); #define BASE 65521UL /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* use NO_DIVIDE if your processor does not do division in hardware */ #ifdef NO_DIVIDE # define MOD(a) \ do { \ if (a >= (BASE << 16)) a -= (BASE << 16); \ if (a >= (BASE << 15)) a -= (BASE << 15); \ if (a >= (BASE << 14)) a -= (BASE << 14); \ if (a >= (BASE << 13)) a -= (BASE << 13); \ if (a >= (BASE << 12)) a -= (BASE << 12); \ if (a >= (BASE << 11)) a -= (BASE << 11); \ if (a >= (BASE << 10)) a -= (BASE << 10); \ if (a >= (BASE << 9)) a -= (BASE << 9); \ if (a >= (BASE << 8)) a -= (BASE << 8); \ if (a >= (BASE << 7)) a -= (BASE << 7); \ if (a >= (BASE << 6)) a -= (BASE << 6); \ if (a >= (BASE << 5)) a -= (BASE << 5); \ if (a >= (BASE << 4)) a -= (BASE << 4); \ if (a >= (BASE << 3)) a -= (BASE << 3); \ if (a >= (BASE << 2)) a -= (BASE << 2); \ if (a >= (BASE << 1)) a -= (BASE << 1); \ if (a >= BASE) a -= BASE; \ } while (0) # define MOD4(a) \ do { \ if (a >= (BASE << 4)) a -= (BASE << 4); \ if (a >= (BASE << 3)) a -= (BASE << 3); \ if (a >= (BASE << 2)) a -= (BASE << 2); \ if (a >= (BASE << 1)) a -= (BASE << 1); \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE # define MOD4(a) a %= BASE #endif /* ========================================================================= */ uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) { unsigned long sum2; unsigned n; /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; /* in case user likes doing a byte at a time, keep it fast */ if (len == 1) { adler += buf[0]; if (adler >= BASE) adler -= BASE; sum2 += adler; if (sum2 >= BASE) sum2 -= BASE; return adler | (sum2 << 16); } /* initial Adler-32 value (deferred check for len == 1 speed) */ if (buf == Z_NULL) return 1L; /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { while (len--) { adler += *buf++; sum2 += adler; } if (adler >= BASE) adler -= BASE; MOD4(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } /* do length NMAX blocks -- requires just one modulo operation */ while (len >= NMAX) { len -= NMAX; n = NMAX / 16; /* NMAX is divisible by 16 */ do { DO16(buf); /* 16 sums unrolled */ buf += 16; } while (--n); MOD(adler); MOD(sum2); } /* do remaining bytes (less than NMAX, still just one modulo) */ if (len) { /* avoid modulos if none remaining */ while (len >= 16) { len -= 16; DO16(buf); buf += 16; } while (len--) { adler += *buf++; sum2 += adler; } MOD(adler); MOD(sum2); } /* return recombined sums */ return adler | (sum2 << 16); } /* ========================================================================= */ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) { unsigned long sum1; unsigned long sum2; unsigned rem; /* the derivation of this formula is left as an exercise for the reader */ rem = (unsigned)(len2 % BASE); sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); sum1 += (adler2 & 0xffff) + BASE - 1; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) { return adler32_combine_(adler1, adler2, len2); } uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) { return adler32_combine_(adler1, adler2, len2); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/algorithm.txt000066400000000000000000000225111300674244400244570ustar00rootroot000000000000001. Compression algorithm (deflate) The deflation algorithm used by gzip (also zip and zlib) is a variation of LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in the input data. The second occurrence of a string is replaced by a pointer to the previous string, in the form of a pair (distance, length). Distances are limited to 32K bytes, and lengths are limited to 258 bytes. When a string does not occur anywhere in the previous 32K bytes, it is emitted as a sequence of literal bytes. (In this description, `string' must be taken as an arbitrary sequence of bytes, and is not restricted to printable characters.) Literals or match lengths are compressed with one Huffman tree, and match distances are compressed with another tree. The trees are stored in a compact form at the start of each block. The blocks can have any size (except that the compressed data for one block must fit in available memory). A block is terminated when deflate() determines that it would be useful to start another block with fresh trees. (This is somewhat similar to the behavior of LZW-based _compress_.) Duplicated strings are found using a hash table. All input strings of length 3 are inserted in the hash table. A hash index is computed for the next 3 bytes. If the hash chain for this index is not empty, all strings in the chain are compared with the current input string, and the longest match is selected. The hash chains are searched starting with the most recent strings, to favor small distances and thus take advantage of the Huffman encoding. The hash chains are singly linked. There are no deletions from the hash chains, the algorithm simply discards matches that are too old. To avoid a worst-case situation, very long hash chains are arbitrarily truncated at a certain length, determined by a runtime option (level parameter of deflateInit). So deflate() does not always find the longest possible match but generally finds a match which is long enough. deflate() also defers the selection of matches with a lazy evaluation mechanism. After a match of length N has been found, deflate() searches for a longer match at the next input byte. If a longer match is found, the previous match is truncated to a length of one (thus producing a single literal byte) and the process of lazy evaluation begins again. Otherwise, the original match is kept, and the next match search is attempted only N steps later. The lazy match evaluation is also subject to a runtime parameter. If the current match is long enough, deflate() reduces the search for a longer match, thus speeding up the whole process. If compression ratio is more important than speed, deflate() attempts a complete second search even if the first match is already long enough. The lazy match evaluation is not performed for the fastest compression modes (level parameter 1 to 3). For these fast modes, new strings are inserted in the hash table only when no match was found, or when the match is not too long. This degrades the compression ratio but saves time since there are both fewer insertions and fewer searches. 2. Decompression algorithm (inflate) 2.1 Introduction The key question is how to represent a Huffman code (or any prefix code) so that you can decode fast. The most important characteristic is that shorter codes are much more common than longer codes, so pay attention to decoding the short codes fast, and let the long codes take longer to decode. inflate() sets up a first level table that covers some number of bits of input less than the length of longest code. It gets that many bits from the stream, and looks it up in the table. The table will tell if the next code is that many bits or less and how many, and if it is, it will tell the value, else it will point to the next level table for which inflate() grabs more bits and tries to decode a longer code. How many bits to make the first lookup is a tradeoff between the time it takes to decode and the time it takes to build the table. If building the table took no time (and if you had infinite memory), then there would only be a first level table to cover all the way to the longest code. However, building the table ends up taking a lot longer for more bits since short codes are replicated many times in such a table. What inflate() does is simply to make the number of bits in the first table a variable, and then to set that variable for the maximum speed. For inflate, which has 286 possible codes for the literal/length tree, the size of the first table is nine bits. Also the distance trees have 30 possible values, and the size of the first table is six bits. Note that for each of those cases, the table ended up one bit longer than the ``average'' code length, i.e. the code length of an approximately flat code which would be a little more than eight bits for 286 symbols and a little less than five bits for 30 symbols. 2.2 More details on the inflate table lookup Ok, you want to know what this cleverly obfuscated inflate tree actually looks like. You are correct that it's not a Huffman tree. It is simply a lookup table for the first, let's say, nine bits of a Huffman symbol. The symbol could be as short as one bit or as long as 15 bits. If a particular symbol is shorter than nine bits, then that symbol's translation is duplicated in all those entries that start with that symbol's bits. For example, if the symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a symbol is nine bits long, it appears in the table once. If the symbol is longer than nine bits, then that entry in the table points to another similar table for the remaining bits. Again, there are duplicated entries as needed. The idea is that most of the time the symbol will be short and there will only be one table look up. (That's whole idea behind data compression in the first place.) For the less frequent long symbols, there will be two lookups. If you had a compression method with really long symbols, you could have as many levels of lookups as is efficient. For inflate, two is enough. So a table entry either points to another table (in which case nine bits in the above example are gobbled), or it contains the translation for the symbol and the number of bits to gobble. Then you start again with the next ungobbled bit. You may wonder: why not just have one lookup table for how ever many bits the longest symbol is? The reason is that if you do that, you end up spending more time filling in duplicate symbol entries than you do actually decoding. At least for deflate's output that generates new trees every several 10's of kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code would take too long if you're only decoding several thousand symbols. At the other extreme, you could make a new table for every bit in the code. In fact, that's essentially a Huffman tree. But then you spend two much time traversing the tree while decoding, even for short symbols. So the number of bits for the first lookup table is a trade of the time to fill out the table vs. the time spent looking at the second level and above of the table. Here is an example, scaled down: The code being decoded, with 10 symbols, from 1 to 6 bits long: A: 0 B: 10 C: 1100 D: 11010 E: 11011 F: 11100 G: 11101 H: 11110 I: 111110 J: 111111 Let's make the first table three bits long (eight entries): 000: A,1 001: A,1 010: A,1 011: A,1 100: B,2 101: B,2 110: -> table X (gobble 3 bits) 111: -> table Y (gobble 3 bits) Each entry is what the bits decode as and how many bits that is, i.e. how many bits to gobble. Or the entry points to another table, with the number of bits to gobble implicit in the size of the table. Table X is two bits long since the longest code starting with 110 is five bits long: 00: C,1 01: C,1 10: D,2 11: E,2 Table Y is three bits long since the longest code starting with 111 is six bits long: 000: F,2 001: F,2 010: G,2 011: G,2 100: H,2 101: H,2 110: I,3 111: J,3 So what we have here are three tables with a total of 20 entries that had to be constructed. That's compared to 64 entries for a single table. Or compared to 16 entries for a Huffman tree (six two entry tables and one four entry table). Assuming that the code ideally represents the probability of the symbols, it takes on the average 1.25 lookups per symbol. That's compared to one lookup for the single table, or 1.66 lookups per symbol for the Huffman tree. There, I think that gives you a picture of what's going on. For inflate, the meaning of a particular symbol is often more than just a letter. It can be a byte (a "literal"), or it can be either a length or a distance which indicates a base value and a number of bits to fetch after the code that is added to the base value. Or it might be the special end-of-block code. The data structures created in inftrees.c try to encode all that information compactly in the tables. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu References: [LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, pp. 337-343. ``DEFLATE Compressed Data Format Specification'' available in http://www.ietf.org/rfc/rfc1951.txt berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/compress_.c000066400000000000000000000046161300674244400240740ustar00rootroot00000000000000/* compress.c -- compress a memory buffer * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL #include "zlib.h" ABC_NAMESPACE_IMPL_START /* =========================================================================== Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) { z_stream stream; int err; stream.next_in = (Bytef*)source; stream.avail_in = (uInt)sourceLen; #ifdef MAXSEG_64K /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; #endif stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = deflateInit(&stream, level); if (err != Z_OK) return err; err = deflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { deflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err; } *destLen = stream.total_out; err = deflateEnd(&stream); return err; } /* =========================================================================== */ int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } /* =========================================================================== If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ uLong ZEXPORT compressBound (uLong sourceLen) { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/crc32.c000066400000000000000000000325751300674244400230230ustar00rootroot00000000000000/* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995-2006, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing * tables for updating the shift register in one step with three exclusive-ors * instead of four steps with four exclusive-ors. This results in about a * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ /* @(#) $Id$ */ /* Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore protection on the static variables used to control the first-use generation of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). */ #ifdef MAKECRCH # include # ifndef DYNAMIC_CRC_TABLE # define DYNAMIC_CRC_TABLE # endif /* !DYNAMIC_CRC_TABLE */ #endif /* MAKECRCH */ #include #include #include #include "misc/util/abc_global.h" #include "zutil.h" /* for STDC and FAR definitions */ ABC_NAMESPACE_IMPL_START #define local static /* Find a four-byte integer type for crc32_little() and crc32_big(). */ #ifndef NOBYFOUR # ifdef STDC /* need ANSI C limits.h to determine sizes */ ABC_NAMESPACE_IMPL_END # include ABC_NAMESPACE_IMPL_START # define BYFOUR # if (UINT_MAX == 0xffffffffUL) typedef unsigned int u4; # else # if (ULONG_MAX == 0xffffffffUL) typedef unsigned long u4; # else # if (USHRT_MAX == 0xffffffffUL) typedef unsigned short u4; # else # undef BYFOUR /* can't find a four-byte integer type! */ # endif # endif # endif # endif /* STDC */ #endif /* !NOBYFOUR */ /* Definitions for doing the crc four data bytes at a time. */ #ifdef BYFOUR # define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ (((w)&0xff00)<<8)+(((w)&0xff)<<24)) local unsigned long crc32_little OF((unsigned long, const unsigned char FAR *, unsigned)); local unsigned long crc32_big OF((unsigned long, const unsigned char FAR *, unsigned)); # define TBLS 8 #else # define TBLS 1 #endif /* BYFOUR */ /* Local functions for crc concatenation */ local unsigned long gf2_matrix_times OF((unsigned long *mat, unsigned long vec)); local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); #ifdef DYNAMIC_CRC_TABLE local volatile int crc_table_empty = 1; local unsigned long FAR crc_table[TBLS][256]; local void make_crc_table OF((void)); #ifdef MAKECRCH local void write_table OF((FILE *, const unsigned long FAR *)); #endif /* MAKECRCH */ /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The first table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRCs on data a byte at a time for all combinations of CRC register values and incoming bytes. The remaining tables allow for word-at-a-time CRC calculation for both big-endian and little- endian machines, where a word is four bytes. */ local void make_crc_table() { unsigned long c; int n, k; unsigned long poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static volatile int first = 1; /* flag to limit concurrent making */ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* See if another task is already doing this (not thread-safe, but better than nothing -- significantly reduces duration of vulnerability in case the advice about DYNAMIC_CRC_TABLE is ignored) */ if (first) { first = 0; /* make exclusive-or pattern from polynomial (0xedb88320UL) */ poly = 0UL; for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) poly |= 1UL << (31 - p[n]); /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { c = (unsigned long)n; for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1; crc_table[0][n] = c; } #ifdef BYFOUR /* generate crc for each value followed by one, two, and three zeros, and then the byte reversal of those as well as the first table */ for (n = 0; n < 256; n++) { c = crc_table[0][n]; crc_table[4][n] = REV(c); for (k = 1; k < 4; k++) { c = crc_table[0][c & 0xff] ^ (c >> 8); crc_table[k][n] = c; crc_table[k + 4][n] = REV(c); } } #endif /* BYFOUR */ crc_table_empty = 0; } else { /* not first */ /* wait for the other guy to finish (not efficient, but rare) */ while (crc_table_empty) ; } #ifdef MAKECRCH /* write out CRC tables to crc32.h */ { FILE *out; out = fopen("crc32.h", "w"); if (out == NULL) return; fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); fprintf(out, "local const unsigned long FAR "); fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); write_table(out, crc_table[0]); # ifdef BYFOUR fprintf(out, "#ifdef BYFOUR\n"); for (k = 1; k < 8; k++) { fprintf(out, " },\n {\n"); write_table(out, crc_table[k]); } fprintf(out, "#endif\n"); # endif /* BYFOUR */ fprintf(out, " }\n};\n"); fclose(out); } #endif /* MAKECRCH */ } #ifdef MAKECRCH local void write_table(FILE *out, const unsigned long FAR *table) { int n; for (n = 0; n < 256; n++) fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); } #endif /* MAKECRCH */ #else /* !DYNAMIC_CRC_TABLE */ /* ======================================================================== * Tables of CRC-32s of all single-byte values, made by make_crc_table(). */ ABC_NAMESPACE_IMPL_END #include "crc32.h" ABC_NAMESPACE_IMPL_START #endif /* DYNAMIC_CRC_TABLE */ /* ========================================================================= * This function can be used by asm versions of crc32() */ const unsigned long FAR * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ return (const unsigned long FAR *)crc_table; } /* ========================================================================= */ #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 /* ========================================================================= */ unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len) { if (buf == Z_NULL) return 0UL; #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ #ifdef BYFOUR if (sizeof(void *) == sizeof(ptrdiff_t)) { u4 endian; endian = 1; if (*((unsigned char *)(&endian))) return crc32_little(crc, buf, len); else return crc32_big(crc, buf, len); } #endif /* BYFOUR */ crc = crc ^ 0xffffffffUL; while (len >= 8) { DO8; len -= 8; } if (len) do { DO1; } while (--len); return crc ^ 0xffffffffUL; } #ifdef BYFOUR /* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 /* ========================================================================= */ local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, unsigned len) { register u4 c; register const u4 FAR *buf4; c = (u4)crc; c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); len--; } buf4 = (const u4 FAR *)(const void FAR *)buf; while (len >= 32) { DOLIT32; len -= 32; } while (len >= 4) { DOLIT4; len -= 4; } buf = (const unsigned char FAR *)buf4; if (len) do { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); } while (--len); c = ~c; return (unsigned long)c; } /* ========================================================================= */ #define DOBIG4 c ^= *++buf4; \ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 /* ========================================================================= */ local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf, unsigned len) { register u4 c; register const u4 FAR *buf4; c = REV((u4)crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); len--; } buf4 = (const u4 FAR *)(const void FAR *)buf; buf4--; while (len >= 32) { DOBIG32; len -= 32; } while (len >= 4) { DOBIG4; len -= 4; } buf4++; buf = (const unsigned char FAR *)buf4; if (len) do { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); } while (--len); c = ~c; return (unsigned long)(REV(c)); } #endif /* BYFOUR */ #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ /* ========================================================================= */ local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec) { unsigned long sum; sum = 0; while (vec) { if (vec & 1) sum ^= *mat; vec >>= 1; mat++; } return sum; } /* ========================================================================= */ local void gf2_matrix_square(unsigned long *square, unsigned long *mat) { int n; for (n = 0; n < GF2_DIM; n++) square[n] = gf2_matrix_times(mat, mat[n]); } /* ========================================================================= */ local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2) { int n; unsigned long row; unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ /* degenerate case (also disallow negative lengths) */ if (len2 <= 0) return crc1; /* put operator for one zero bit in odd */ odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ row = 1; for (n = 1; n < GF2_DIM; n++) { odd[n] = row; row <<= 1; } /* put operator for two zero bits in even */ gf2_matrix_square(even, odd); /* put operator for four zero bits in odd */ gf2_matrix_square(odd, even); /* apply len2 zeros to crc1 (first square will put the operator for one zero byte, eight zero bits, in even) */ do { /* apply zeros operator for this bit of len2 */ gf2_matrix_square(even, odd); if (len2 & 1) crc1 = gf2_matrix_times(even, crc1); len2 >>= 1; /* if no more bits set, then done */ if (len2 == 0) break; /* another iteration of the loop with odd and even swapped */ gf2_matrix_square(odd, even); if (len2 & 1) crc1 = gf2_matrix_times(odd, crc1); len2 >>= 1; /* if no more bits set, then done */ } while (len2 != 0); /* return combined crc */ crc1 ^= crc2; return crc1; } /* ========================================================================= */ uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) { return crc32_combine_(crc1, crc2, len2); } uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) { return crc32_combine_(crc1, crc2, len2); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/crc32.h000066400000000000000000000736361300674244400230330ustar00rootroot00000000000000/* crc32.h -- tables for rapid CRC calculation * Generated automatically by crc32.c */ ABC_NAMESPACE_HEADER_START local const unsigned long FAR crc_table[TBLS][256] = { { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 0x2d02ef8dUL #ifdef BYFOUR }, { 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, 0x9324fd72UL }, { 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, 0xbe9834edUL }, { 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, 0xde0506f1UL }, { 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, 0x8def022dUL }, { 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, 0x72fd2493UL }, { 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, 0xed3498beUL }, { 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, 0xf10605deUL #endif } }; ABC_NAMESPACE_HEADER_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/deflate.c000066400000000000000000002034421300674244400235040ustar00rootroot00000000000000/* deflate.c -- compress data using the deflation algorithm * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in http://www.ietf.org/rfc/rfc1951.txt * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ /* @(#) $Id$ */ #include #include #include #include "misc/util/abc_global.h" #include "deflate.h" ABC_NAMESPACE_IMPL_START const char deflate_copyright[] = " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* =========================================================================== * Function prototypes. */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); #ifndef FASTEST local block_state deflate_slow OF((deflate_state *s, int flush)); #endif local block_state deflate_rle OF((deflate_state *s, int flush)); local block_state deflate_huff OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV void match_init OF((void)); /* asm code initialization */ uInt longest_match OF((deflate_state *s, IPos cur_match)); #else local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif #ifdef DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif /* =========================================================================== * Local data */ #define NIL 0 /* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; } config; #ifdef FASTEST local const config configuration_table[2] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ #else local const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, /* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ #endif /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ #define EQUAL 0 /* result of memcmp for equal strings */ #ifndef NO_DUMMY_DECL struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ #endif /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. * IN assertion: all calls to to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size) { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size) { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; ushf *overlay; /* We overlay pending_buf and d_buf+l_buf. This works since the average * output size for (length,distance) codes is <= 24 bits. */ if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { strm->zalloc = zcalloc; strm->opaque = (voidpf)0; } if (strm->zfree == (free_func)0) strm->zfree = zcfree; #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; windowBits = -windowBits; } #ifdef GZIP else if (windowBits > 15) { wrap = 2; /* write gzip wrapper instead */ windowBits -= 16; } #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; s->wrap = wrap; s->gzhead = Z_NULL; s->w_bits = windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; s->hash_bits = memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->high_water = 0; /* nothing written to s->window yet */ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); s->pending_buf = (uchf *) overlay; s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } s->d_buf = overlay + s->lit_bufsize/sizeof(ush); s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; s->level = level; s->strategy = strategy; s->method = (Byte)method; return deflateReset(strm); } /* ========================================================================= */ int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength) { deflate_state *s; uInt length = dictLength; uInt n; IPos hash_head = 0; if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || strm->state->wrap == 2 || (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) return Z_STREAM_ERROR; s = strm->state; if (s->wrap) strm->adler = adler32(strm->adler, dictionary, dictLength); if (length < MIN_MATCH) return Z_OK; if (length > s->w_size) { length = s->w_size; dictionary += dictLength - length; /* use the tail of the dictionary */ } zmemcpy(s->window, dictionary, length); s->strstart = length; s->block_start = (long)length; /* Insert all strings in the hash table (except for the last two bytes). * s->lookahead stays null, so s->ins_h will be recomputed at the next * call of fill_window. */ s->ins_h = s->window[0]; UPDATE_HASH(s, s->ins_h, s->window[1]); for (n = 0; n <= length - MIN_MATCH; n++) { INSERT_STRING(s, n, hash_head); } if (hash_head) hash_head = 0; /* to make compiler happy */ return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateReset (z_streamp strm) { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { return Z_STREAM_ERROR; } strm->total_in = strm->total_out = 0; strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ strm->data_type = Z_UNKNOWN; s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } s->status = s->wrap ? INIT_STATE : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); s->last_flush = Z_NO_FLUSH; _tr_init(s); lm_init(s); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateSetHeader (z_streamp strm, gz_headerp head) { if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflatePrime (z_streamp strm, int bits, int value) { if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; strm->state->bi_valid = bits; strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) { deflate_state *s; compress_func func; int err = Z_OK; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && strm->total_in != 0) { /* Flush the last buffer: */ err = deflate(strm, Z_BLOCK); } if (s->level != level) { s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; s->nice_match = configuration_table[level].nice_length; s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; return err; } /* ========================================================================= */ int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain) { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; s->good_match = good_length; s->max_lazy_match = max_lazy; s->nice_match = nice_length; s->max_chain_length = max_chain; return Z_OK; } /* ========================================================================= * For the default windowBits of 15 and memLevel of 8, this function returns * a close to exact, as well as small, upper bound on the compressed size. * They are coded as constants here for a reason--if the #define's are * changed, then this function needs to be changed as well. The return * value for 15 and 8 only works for those exact settings. * * For any setting other than those defaults for windowBits and memLevel, * the value returned is a conservative worst case for the maximum expansion * resulting from using fixed blocks instead of stored blocks, which deflate * can emit on compressed data for some combinations of the parameters. * * This function could be more sophisticated to provide closer upper bounds for * every combination of windowBits and memLevel. But even the conservative * upper bound of about 14% expansion does not seem onerous for output buffer * allocation. */ uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { deflate_state *s; uLong complen, wraplen; Bytef *str; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ if (strm == Z_NULL || strm->state == Z_NULL) return complen + 6; /* compute wrapper length */ s = strm->state; switch (s->wrap) { case 0: /* raw deflate */ wraplen = 0; break; case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; if (str != Z_NULL) do { wraplen++; } while (*str++); str = s->gzhead->comment; if (str != Z_NULL) do { wraplen++; } while (*str++); if (s->gzhead->hcrc) wraplen += 2; } break; default: /* for compiler happiness */ wraplen = 6; } /* if not default parameters, return conservative bound */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) return complen + wraplen; /* default settings: return tight bound for that case */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ local void putShortMSB (deflate_state *s, uInt b) { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= * Flush as much pending output as possible. All deflate() output goes * through this function so some applications may wish to modify it * to avoid allocating a large strm->next_out buffer and copying into it. * (See also read_buf()). */ local void flush_pending(z_streamp strm) { unsigned len = strm->state->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; zmemcpy(strm->next_out, strm->state->pending_out, len); strm->next_out += len; strm->state->pending_out += len; strm->total_out += len; strm->avail_out -= len; strm->state->pending -= len; if (strm->state->pending == 0) { strm->state->pending_out = strm->state->pending_buf; } } /* ========================================================================= */ int ZEXPORT deflate (z_streamp strm, int flush) { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; /* Write the header */ if (s->status == INIT_STATE) { #ifdef GZIP if (s->wrap == 2) { strm->adler = crc32(0L, Z_NULL, 0); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); if (s->gzhead == Z_NULL) { put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, OS_CODE); s->status = BUSY_STATE; } else { put_byte(s, (s->gzhead->text ? 1 : 0) + (s->gzhead->hcrc ? 2 : 0) + (s->gzhead->extra == Z_NULL ? 0 : 4) + (s->gzhead->name == Z_NULL ? 0 : 8) + (s->gzhead->comment == Z_NULL ? 0 : 16) ); put_byte(s, (Byte)(s->gzhead->time & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, s->gzhead->os & 0xff); if (s->gzhead->extra != Z_NULL) { put_byte(s, s->gzhead->extra_len & 0xff); put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); } if (s->gzhead->hcrc) strm->adler = crc32(strm->adler, s->pending_buf, s->pending); s->gzindex = 0; s->status = EXTRA_STATE; } } else #endif { uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) level_flags = 0; else if (s->level < 6) level_flags = 1; else if (s->level == 6) level_flags = 2; else level_flags = 3; header |= (level_flags << 6); if (s->strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); s->status = BUSY_STATE; putShortMSB(s, header); /* Save the adler32 of the preset dictionary: */ if (s->strstart != 0) { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } strm->adler = adler32(0L, Z_NULL, 0); } } #ifdef GZIP if (s->status == EXTRA_STATE) { if (s->gzhead->extra != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) break; } put_byte(s, s->gzhead->extra[s->gzindex]); s->gzindex++; } if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (s->gzindex == s->gzhead->extra_len) { s->gzindex = 0; s->status = NAME_STATE; } } else s->status = NAME_STATE; } if (s->status == NAME_STATE) { if (s->gzhead->name != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) { val = 1; break; } } val = s->gzhead->name[s->gzindex++]; put_byte(s, val); } while (val != 0); if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (val == 0) { s->gzindex = 0; s->status = COMMENT_STATE; } } else s->status = COMMENT_STATE; } if (s->status == COMMENT_STATE) { if (s->gzhead->comment != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) { val = 1; break; } } val = s->gzhead->comment[s->gzindex++]; put_byte(s, val); } while (val != 0); if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (val == 0) s->status = HCRC_STATE; } else s->status = HCRC_STATE; } if (s->status == HCRC_STATE) { if (s->gzhead->hcrc) { if (s->pending + 2 > s->pending_buf_size) flush_pending(strm); if (s->pending + 2 <= s->pending_buf_size) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); strm->adler = crc32(0L, Z_NULL, 0); s->status = BUSY_STATE; } } else s->status = BUSY_STATE; } #endif /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ s->last_flush = -1; return Z_OK; } /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ } else if (strm->avail_in == 0 && flush <= old_flush && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } /* User must not provide more input after the first FINISH: */ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : (s->strategy == Z_RLE ? deflate_rle(s, flush) : (*(configuration_table[s->level].func))(s, flush)); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; } if (bstate == need_more || bstate == finish_started) { if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ } return Z_OK; /* If flush != Z_NO_FLUSH && avail_out == 0, the next call * of deflate should use the same flush parameter to make sure * that the flush is complete. So we don't have to output an * empty block here, this will be done at next call. This also * ensures that for a very small output buffer, we emit at most * one empty block. */ } if (bstate == block_done) { if (flush == Z_PARTIAL_FLUSH) { _tr_align(s); } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ _tr_stored_block(s, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(s); /* forget history */ if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; } } } flush_pending(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; } } } Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; /* Write the trailer */ #ifdef GZIP if (s->wrap == 2) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); put_byte(s, (Byte)(strm->total_in & 0xff)); put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); } else #endif { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ return s->pending != 0 ? Z_OK : Z_STREAM_END; } /* ========================================================================= */ int ZEXPORT deflateEnd (z_streamp strm) { int status; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; status = strm->state->status; if (status != INIT_STATE && status != EXTRA_STATE && status != NAME_STATE && status != COMMENT_STATE && status != HCRC_STATE && status != BUSY_STATE && status != FINISH_STATE) { return Z_STREAM_ERROR; } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } /* ========================================================================= * Copy the source state to the destination state. * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ int ZEXPORT deflateCopy (z_streamp dest, z_streamp source) { #ifdef MAXSEG_64K return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; ushf *overlay; if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { return Z_STREAM_ERROR; } ss = source->state; zmemcpy(dest, source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; zmemcpy(ds, ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); ds->pending_buf = (uchf *) overlay; if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; ds->bl_desc.dyn_tree = ds->bl_tree; return Z_OK; #endif /* MAXSEG_64K */ } /* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. All deflate() input goes through * this function so some applications may wish to modify it to avoid * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ local int read_buf(z_streamp strm, Bytef *buf, unsigned size) { unsigned len = strm->avail_in; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; if (strm->state->wrap == 1) { strm->adler = adler32(strm->adler, strm->next_in, len); } #ifdef GZIP else if (strm->state->wrap == 2) { strm->adler = crc32(strm->adler, strm->next_in, len); } #endif zmemcpy(buf, strm->next_in, len); strm->next_in += len; strm->total_in += len; return (int)len; } /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ local void lm_init (deflate_state *s) { s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; #ifndef FASTEST #ifdef ASMV match_init(); /* initialize the asm code */ #endif #endif } #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ #ifndef ASMV /* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */ local uInt longest_match(deflate_state *s, IPos cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask; #ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan+best_len-1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len-1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2. Note that the checks below * for insufficient lookahead only occur occasionally for performance * reasons. Therefore uninitialized memory will be accessed, and * conditional jumps will be made that depend on those values. * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match+best_len-1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at * strstart+3, +5, ... up to strstart+257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window+strstart+257 */ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ushf*)(scan+best_len-1); #else scan_end1 = scan[best_len-1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } #endif /* ASMV */ #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ local uInt longest_match(deflate_state *s, IPos cur_match) { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; } #endif /* FASTEST */ #ifdef DEBUG /* =========================================================================== * Check that the match at match_start is indeed a match. */ local void check_match(deflate_state *s, IPos start, IPos match, int length) { /* check that the match is indeed a match */ if (zmemcmp(s->window + match, s->window + start, length) != EQUAL) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); do { fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); } while (--length != 0); z_error("invalid match"); } if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start-match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) #endif /* DEBUG */ /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. * * IN assertion: lookahead < MIN_LOOKAHEAD * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD * At least one byte has been read, or avail_in == 0; reads are * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ local void fill_window(deflate_state *s) { register unsigned n, m; register Posf *p; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); /* Deal with !@#$% 64K limit: */ if (sizeof(int) <= 2) { if (more == 0 && s->strstart == 0 && s->lookahead == 0) { more = wsize; } else if (more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if * strstart == 0 && lookahead == 1 (input done a byte at time) */ more--; } } /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ if (s->strstart >= wsize+MAX_DIST(s)) { zmemcpy(s->window, s->window+wsize, (unsigned)wsize); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; /* Slide the hash table (could be avoided with 32 bit values at the expense of memory usage). We slide even when level == 0 to keep the hash table consistent if we switch back to level > 0 later. (Using level 0 permanently is not an optimal usage of zlib, so we don't care about this pathological case.) */ n = s->hash_size; p = &s->head[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); } while (--n); n = wsize; #ifndef FASTEST p = &s->prev[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); /* If n is not on any hash chain, prev[n] is garbage but * its value will never be used. */ } while (--n); #endif more += wsize; } if (s->strm->avail_in == 0) return; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && * more == window_size - lookahead - strstart * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) * => more >= window_size - 2*WSIZE + 2 * In the BIG_MEM or MMAP case (not yet supported), * window_size == input_size + MIN_LOOKAHEAD && * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. * Otherwise, window_size == 2*WSIZE so more >= 2. * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ if (s->lookahead >= MIN_MATCH) { s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); /* If the WIN_INIT bytes after the end of the current data have never been * written, then zero those bytes in order to avoid memory check reports of * the use of uninitialized (or uninitialised as Julian writes) bytes by * the longest match routines. Update the high water mark for the next * time through here. WIN_INIT is set to MAX_MATCH since the longest match * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. */ if (s->high_water < s->window_size) { ulg curr = s->strstart + (ulg)(s->lookahead); ulg init; if (s->high_water < curr) { /* Previous high water mark below current data -- zero WIN_INIT * bytes or up to end of window, whichever is less. */ init = s->window_size - curr; if (init > WIN_INIT) init = WIN_INIT; zmemzero(s->window + curr, (unsigned)init); s->high_water = curr + init; } else if (s->high_water < (ulg)curr + WIN_INIT) { /* High water mark at or above current data, but below current data * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up * to end of window, whichever is less. */ init = (ulg)curr + WIN_INIT - s->high_water; if (init > s->window_size - s->high_water) init = s->window_size - s->high_water; zmemzero(s->window + s->high_water, (unsigned)init); s->high_water += init; } } } /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK_ONLY(s, last) { \ _tr_flush_block(s, (s->block_start >= 0L ? \ (charf *)&s->window[(unsigned)s->block_start] : \ (charf *)Z_NULL), \ (ulg)((long)s->strstart - s->block_start), \ (last)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } /* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, last) { \ FLUSH_BLOCK_ONLY(s, last); \ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. * This function does not insert new strings in the dictionary since * uncompressible data is probably not useful. This function is used * only for the level=0 compression option. * NOTE: this function should be optimized to avoid extra copying from * window to pending_buf. */ local block_state deflate_stored(deflate_state *s, int flush) { /* Stored blocks are limited to 0xffff bytes, pending_buf is limited * to pending_buf_size, and each stored block has a 5 byte header: */ ulg max_block_size = 0xffff; ulg max_start; if (max_block_size > s->pending_buf_size - 5) { max_block_size = s->pending_buf_size - 5; } /* Copy as much as possible from input to output: */ for (;;) { /* Fill the window as much as possible: */ if (s->lookahead <= 1) { Assert(s->strstart < s->w_size+MAX_DIST(s) || s->block_start >= (long)s->w_size, "slide too late"); fill_window(s); if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; if (s->lookahead == 0) break; /* flush the current block */ } Assert(s->block_start >= 0L, "block gone"); s->strstart += s->lookahead; s->lookahead = 0; /* Emit a stored block if pending_buf will be full: */ max_start = s->block_start + max_block_size; if (s->strstart == 0 || (ulg)s->strstart >= max_start) { /* strstart == 0 is possible when wraparound on 16-bit machine */ s->lookahead = (uInt)(s->strstart - max_start); s->strstart = (uInt)max_start; FLUSH_BLOCK(s, 0); } /* Flush if we may have to slide, otherwise block_start may become * negative and the data will be gone: */ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { FLUSH_BLOCK(s, 0); } } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } /* =========================================================================== * Compress as much as possible from the input stream, return the current * block state. * This function does not perform lazy evaluation of matches and inserts * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ local block_state deflate_fast(deflate_state *s, int flush) { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ #ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in table */ do { s->strstart++; INSERT_STRING(s, s->strstart, hash_head); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ } while (--s->match_length != 0); s->strstart++; } else #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } #ifndef FASTEST /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ local block_state deflate_slow(deflate_state *s, int flush) { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. */ s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED #if TOO_FAR <= 32767 || (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) #endif )) { /* If prev_match is also MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ s->match_length = MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart-1, s->prev_match, s->prev_length); _tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ s->lookahead -= s->prev_length-1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } } while (--s->prev_length != 0); s->match_available = 0; s->match_length = MIN_MATCH-1; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; if (s->strm->avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ s->match_available = 1; s->strstart++; s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } #endif /* FASTEST */ /* =========================================================================== * For Z_RLE, simply look for runs of bytes, generate matches only of distance * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ local block_state deflate_rle(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ uInt prev; /* byte at distance one to match */ Bytef *scan, *strend; /* scan goes up to strend for length of run */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the longest encodable run. */ if (s->lookahead < MAX_MATCH) { fill_window(s); if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* See how many times the previous byte repeats */ s->match_length = 0; if (s->lookahead >= MIN_MATCH && s->strstart > 0) { scan = s->window + s->strstart - 1; prev = *scan; if (prev == *++scan && prev == *++scan && prev == *++scan) { strend = s->window + s->strstart + MAX_MATCH; do { } while (prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); s->match_length = MAX_MATCH - (int)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->strstart - 1, s->match_length); _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; s->strstart += s->match_length; s->match_length = 0; } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } /* =========================================================================== * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ local block_state deflate_huff(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we have a literal to write. */ if (s->lookahead == 0) { fill_window(s); if (s->lookahead == 0) { if (flush == Z_NO_FLUSH) return need_more; break; /* flush the current block */ } } /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/deflate.h000066400000000000000000000306661300674244400235170ustar00rootroot00000000000000/* deflate.h -- internal compression state * Copyright (C) 1995-2010 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef DEFLATE_H #define DEFLATE_H #include "zutil.h" ABC_NAMESPACE_HEADER_START /* define NO_GZIP when compiling if you want to disable gzip header and trailer creation by deflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip encoding should be left enabled. */ #ifndef NO_GZIP # define GZIP #endif /* =========================================================================== * Internal compression state. */ #define LENGTH_CODES 29 /* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 /* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 /* number of distance codes */ #define BL_CODES 19 /* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ #define INIT_STATE 42 #define EXTRA_STATE 69 #define NAME_STATE 73 #define COMMENT_STATE 91 #define HCRC_STATE 103 #define BUSY_STATE 113 #define FINISH_STATE 666 /* Stream status */ /* Data structure describing a single value and its code string. */ typedef struct ct_data_s { union { ush freq; /* frequency count */ ush code; /* bit string */ } fc; union { ush dad; /* father node in Huffman tree */ ush len; /* length of bit string */ } dl; } FAR ct_data; #define Freq fc.freq #define Code fc.code #define Dad dl.dad #define Len dl.len typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; typedef Pos FAR Posf; typedef unsigned IPos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ uInt pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ uInt gzindex; /* where in extra, name, or comment */ Byte method; /* STORED (for zip only) or DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ uInt w_mask; /* w_size - 1 */ Bytef *window; /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of * wSize-MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. */ ulg window_size; /* Actual size of window: 2*wSize, except when the user input buffer * is directly used as sliding window. */ Posf *prev; /* Link to older string with same hash index. To limit the size of this * array to 64K, this link is maintained only for the last 32K strings. * An index in this array is thus a window index modulo 32K. */ Posf *head; /* Heads of the hash chains or NIL. */ uInt ins_h; /* hash index of string to be inserted */ uInt hash_size; /* number of elements in hash table */ uInt hash_bits; /* log2(hash_size) */ uInt hash_mask; /* hash_size-1 */ uInt hash_shift; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * hash_shift * MIN_MATCH >= hash_bits */ long block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ uInt match_length; /* length of best match */ IPos prev_match; /* previous match */ int match_available; /* set if previous match exists */ uInt strstart; /* start of string to insert */ uInt match_start; /* start of matching string */ uInt lookahead; /* number of valid bytes ahead in window */ uInt prev_length; /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ uInt max_chain_length; /* To speed up deflation, hash chains are never searched beyond this * length. A higher limit improves compression ratio but degrades the * speed. */ uInt max_lazy_match; /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ # define max_insert_length max_lazy_match /* Insert new strings in the hash table only if the match length is not * greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ uInt good_match; /* Use a faster search when the previous match is longer than this */ int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ /* Didn't use ct_data typedef below to supress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ struct tree_desc_s l_desc; /* desc. for literal tree */ struct tree_desc_s d_desc; /* desc. for distance tree */ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ int heap_len; /* number of elements in the heap */ int heap_max; /* element of largest frequency */ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. * The same heap array is used to build all trees. */ uch depth[2*L_CODES+1]; /* Depth of each subtree used as tie breaker for trees of equal frequency */ uchf *l_buf; /* buffer for literals or lengths */ uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for * limiting lit_bufsize to 64K: * - frequencies can be kept in 16 bit counters * - if compression is not successful for the first block, all input * data is still in the window so we can still emit a stored block even * when input comes from standard input. (This can also be done for * all blocks if lit_bufsize is not greater than 32K.) * - if compression is not successful for a file smaller than 64K, we can * even emit a stored file instead of a stored block (saving 5 bytes). * This is applicable only for zip (not gzip or zlib). * - creating new Huffman trees less frequently may not provide fast * adaptation to changes in the input data statistics. (Take for * example a binary file with poorly compressible code followed by * a highly compressible string table.) Smaller buffer sizes give * fast adaptation but have of course the overhead of transmitting * trees more frequently. * - I can't count above 4 */ uInt last_lit; /* running index in l_buf */ ushf *d_buf; /* Buffer for distances. To simplify the code, d_buf and l_buf have * the same number of elements. To use different lengths, an extra flag * array would be necessary. */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ int last_eob_len; /* bit length of EOB code for last block */ #ifdef DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif ush bi_buf; /* Output buffer. bits are inserted starting at the bottom (least * significant bits). */ int bi_valid; /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ ulg high_water; /* High water mark offset in window for initialized bytes -- bytes above * this are set to zero in order to avoid memory check warnings when * longest match routines access bytes past the input. This is then * updated to the new high water mark. */ } FAR deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ #define WIN_INIT MAX_MATCH /* Number of bytes after end of data in window to initialize in order to avoid memory checker errors from longest match routines */ /* in trees.c */ void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, int last)); void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, int last)); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never * used. */ #ifndef DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) extern uch ZLIB_INTERNAL _length_code[]; extern uch ZLIB_INTERNAL _dist_code[]; #else extern const uch ZLIB_INTERNAL _length_code[]; extern const uch ZLIB_INTERNAL _dist_code[]; #endif # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->d_buf[s->last_lit] = 0; \ s->l_buf[s->last_lit++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (length); \ ush dist = (distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif ABC_NAMESPACE_HEADER_END #endif /* DEFLATE_H */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/gzclose.c000066400000000000000000000014541300674244400235450ustar00rootroot00000000000000/* gzclose.c -- zlib gzclose() function * Copyright (C) 2004, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include #include #include "misc/util/abc_global.h" #include "gzguts.h" ABC_NAMESPACE_IMPL_START /* gzclose() is in a separate file so that it is linked in only if it is used. That way the other gzclose functions can be used instead to avoid linking in unneeded compression or decompression routines. */ int ZEXPORT gzclose(gzFile file) { #ifndef NO_GZCOMPRESS gz_statep state; if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); #else return gzclose_r(file); #endif } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/gzguts.h000066400000000000000000000114561300674244400234320ustar00rootroot00000000000000/* gzguts.h -- zlib internal header definitions for gz* operations * Copyright (C) 2004, 2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #ifdef _LARGEFILE64_SOURCE # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif # ifdef _FILE_OFFSET_BITS # undef _FILE_OFFSET_BITS # endif #endif #if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include #include "zlib.h" #ifdef STDC # include # include # include #endif #include #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif #ifdef _MSC_VER # include # define vsnprintf _vsnprintf #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ /* gz* functions always use library allocation functions */ #ifndef STDC extern voidp malloc OF((uInt size)); extern void free OF((voidpf ptr)); #endif /* get errno and strerror definition */ #if defined UNDER_CE # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else # ifdef STDC # include # define zstrerror() strerror(errno) # else # define zstrerror() "stdio error (consult errno)" # endif #endif #include #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START #ifdef _WIN32 #define open _open #define close _close #define lseek _lseek #define read _read #define write _write #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); #endif /* default i/o buffer size -- double this for output when reading */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ #define GZ_NONE 0 #define GZ_READ 7247 #define GZ_WRITE 31153 #define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ /* values for gz_state how */ #define LOOK 0 /* look for a gzip header */ #define COPY 1 /* copy input directly */ #define GZIP 2 /* decompress a gzip stream */ /* internal gzip file state data structure */ typedef struct { /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ z_off64_t pos; /* current position in uncompressed data */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ unsigned char *in; /* input buffer */ unsigned char *out; /* output buffer (double-sized when reading) */ unsigned char *next; /* next output data to deliver or write */ /* just for reading */ unsigned have; /* amount of output data unused at next */ int eof; /* true if end of input file reached */ z_off64_t start; /* where the gzip data started, for rewinding */ z_off64_t raw; /* where the raw data started, for seeking */ int how; /* 0: get header, 1: copy, 2: decompress */ int direct; /* true if last read direct, false if gzip */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ /* seek request */ z_off64_t skip; /* amount to skip (already rewound if backwards) */ int seek; /* true if seek request pending */ /* error information */ int err; /* error code */ char *msg; /* error message */ /* zlib inflate or deflate stream */ z_stream strm; /* stream structure in-place (not a pointer) */ } gz_state; typedef gz_state FAR *gz_statep; /* shared functions */ void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); #if defined UNDER_CE char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ #ifdef INT_MAX # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) #else unsigned ZLIB_INTERNAL gz_intmax OF((void)); # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) #endif ABC_NAMESPACE_HEADER_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/gzlib.c000066400000000000000000000331561300674244400232120ustar00rootroot00000000000000/* gzlib.c -- zlib functions common to reading and writing gzip files * Copyright (C) 2004, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include #include #include "misc/util/abc_global.h" #include "gzguts.h" ABC_NAMESPACE_IMPL_START #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif /* Local functions */ local void gz_reset OF((gz_statep)); local gzFile gz_open OF((const char *, int, const char *)); #if defined UNDER_CE /* Map the Windows error number in ERROR to a locale-dependent error message string and return a pointer to it. Typically, the values for ERROR come from GetLastError. The string pointed to shall not be modified by the application, but may be overwritten by a subsequent call to gz_strwinerror The gz_strwinerror function does not change the current setting of GetLastError. */ char ZLIB_INTERNAL *gz_strwinerror (DWORD error) { static char buf[1024]; wchar_t *msgbuf; DWORD lasterr = GetLastError(); DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, 0, /* Default language */ (LPVOID)&msgbuf, 0, NULL); if (chars != 0) { /* If there is an \r\n appended, zap it. */ if (chars >= 2 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { chars -= 2; msgbuf[chars] = 0; } if (chars > sizeof (buf) - 1) { chars = sizeof (buf) - 1; msgbuf[chars] = 0; } wcstombs(buf, msgbuf, chars + 1); LocalFree(msgbuf); } else { sprintf(buf, "unknown win32 error (%ld)", error); } SetLastError(lasterr); return buf; } #endif /* UNDER_CE */ /* Reset gzip file state */ local void gz_reset(gz_statep state) { if (state->mode == GZ_READ) { /* for reading ... */ state->have = 0; /* no output data available */ state->eof = 0; /* not at end of file */ state->how = LOOK; /* look for gzip header */ state->direct = 1; /* default for empty file */ } state->seek = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ state->pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ } /* Open a gzip file either by name or file descriptor. */ local gzFile gz_open(const char *path, int fd, const char *mode) { gz_statep state; /* allocate gzFile structure to return */ state = (gz_statep)malloc(sizeof(gz_state)); if (state == NULL) return NULL; state->size = 0; /* no buffers allocated yet */ state->want = GZBUFSIZE; /* requested buffer size */ state->msg = NULL; /* no error message yet */ /* interpret mode */ state->mode = GZ_NONE; state->level = Z_DEFAULT_COMPRESSION; state->strategy = Z_DEFAULT_STRATEGY; while (*mode) { if (*mode >= '0' && *mode <= '9') state->level = *mode - '0'; else switch (*mode) { case 'r': state->mode = GZ_READ; break; #ifndef NO_GZCOMPRESS case 'w': state->mode = GZ_WRITE; break; case 'a': state->mode = GZ_APPEND; break; #endif case '+': /* can't read and write at the same time */ free(state); return NULL; case 'b': /* ignore -- will request binary anyway */ break; case 'f': state->strategy = Z_FILTERED; break; case 'h': state->strategy = Z_HUFFMAN_ONLY; break; case 'R': state->strategy = Z_RLE; break; case 'F': state->strategy = Z_FIXED; default: /* could consider as an error, but just ignore */ ; } mode++; } /* must provide an "r", "w", or "a" */ if (state->mode == GZ_NONE) { free(state); return NULL; } /* save the path name for error messages */ state->path = (char *)malloc(strlen(path) + 1); if (state->path == NULL) { free(state); return NULL; } strcpy(state->path, path); /* open the file with the appropriate mode (or just use fd) */ state->fd = fd != -1 ? fd : open(path, #ifdef O_LARGEFILE O_LARGEFILE | #endif #ifdef O_BINARY O_BINARY | #endif (state->mode == GZ_READ ? O_RDONLY : (O_WRONLY | O_CREAT | ( state->mode == GZ_WRITE ? O_TRUNC : O_APPEND))), 0666); if (state->fd == -1) { free(state->path); free(state); return NULL; } if (state->mode == GZ_APPEND) state->mode = GZ_WRITE; /* simplify later checks */ /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { state->start = LSEEK(state->fd, 0, SEEK_CUR); if (state->start == -1) state->start = 0; } /* initialize stream */ gz_reset(state); /* return stream */ return (gzFile)state; } /* -- see zlib.h -- */ gzFile ZEXPORT gzopen(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ gzFile ZEXPORT gzopen64(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ gzFile ZEXPORT gzdopen(int fd, const char *mode) { char *path; /* identifier for error messages */ gzFile gz; if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; sprintf(path, "", fd); /* for debugging */ gz = gz_open(path, fd, mode); free(path); return gz; } /* -- see zlib.h -- */ int ZEXPORT gzbuffer(gzFile file, unsigned size) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* make sure we haven't already allocated memory */ if (state->size != 0) return -1; /* check and set requested size */ if (size == 0) return -1; state->want = size; return 0; } /* -- see zlib.h -- */ int ZEXPORT gzrewind(gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no error */ if (state->mode != GZ_READ || state->err != Z_OK) return -1; /* back up and start over */ if (LSEEK(state->fd, state->start, SEEK_SET) == -1) return -1; gz_reset(state); return 0; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) { unsigned n; z_off64_t ret; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* check that there's no error */ if (state->err != Z_OK) return -1; /* can only seek from start or relative to current position */ if (whence != SEEK_SET && whence != SEEK_CUR) return -1; /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) offset -= state->pos; else if (state->seek) offset += state->skip; state->seek = 0; /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && state->pos + offset >= state->raw) { ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); if (ret == -1) return -1; state->have = 0; state->eof = 0; state->seek = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; state->pos += offset; return state->pos; } /* calculate skip amount, rewinding if needed for back seek when reading */ if (offset < 0) { if (state->mode != GZ_READ) /* writing -- can't go backwards */ return -1; offset += state->pos; if (offset < 0) /* before start of file! */ return -1; if (gzrewind(file) == -1) /* rewind, then skip to offset */ return -1; } /* if reading, skip what's in output buffer (one less gzgetc() check) */ if (state->mode == GZ_READ) { n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? (unsigned)offset : state->have; state->have -= n; state->next += n; state->pos += n; offset -= n; } /* request skip (if not zero) */ if (offset) { state->seek = 1; state->skip = offset; } return state->pos + offset; } /* -- see zlib.h -- */ z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) { z_off64_t ret; ret = gzseek64(file, (z_off64_t)offset, whence); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gztell64(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* return position */ return state->pos + (state->seek ? state->skip : 0); } /* -- see zlib.h -- */ z_off_t ZEXPORT gztell(gzFile file) { z_off64_t ret; ret = gztell64(file); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gzoffset64(gzFile file) { z_off64_t offset; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* compute and return effective offset in file */ offset = LSEEK(state->fd, 0, SEEK_CUR); if (offset == -1) return -1; if (state->mode == GZ_READ) /* reading */ offset -= state->strm.avail_in; /* don't count buffered input */ return offset; } /* -- see zlib.h -- */ z_off_t ZEXPORT gzoffset(gzFile file) { z_off64_t ret; ret = gzoffset64(file); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ int ZEXPORT gzeof(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return 0; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return 0; /* return end-of-file state */ return state->mode == GZ_READ ? (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; } /* -- see zlib.h -- */ const char * ZEXPORT gzerror(gzFile file, int *errnum) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return NULL; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return NULL; /* return error information */ if (errnum != NULL) *errnum = state->err; return state->msg == NULL ? "" : state->msg; } /* -- see zlib.h -- */ void ZEXPORT gzclearerr(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return; /* clear error and end-of-file */ if (state->mode == GZ_READ) state->eof = 0; gz_error(state, Z_OK, NULL); } /* Create an error message in allocated memory and set state->err and state->msg accordingly. Free any previous error message already there. Do not try to free or allocate space if the error is Z_MEM_ERROR (out of memory). Simply save the error message as a static string. If there is an allocation failure constructing the error message, then convert the error to out of memory. */ void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) { /* free previously allocated message and clear */ if (state->msg != NULL) { if (state->err != Z_MEM_ERROR) free(state->msg); state->msg = NULL; } /* set error code, and if no message, then done */ state->err = err; if (msg == NULL) return; /* for an out of memory error, save as static string */ if (err == Z_MEM_ERROR) { state->msg = (char *)msg; return; } /* construct error message with path */ if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { state->err = Z_MEM_ERROR; state->msg = (char *)"out of memory"; return; } strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); return; } #ifndef INT_MAX /* portably return maximum value for an int (when limits.h presumed not available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ unsigned ZLIB_INTERNAL gz_intmax() { unsigned p, q; p = 1; do { q = p; p <<= 1; p++; } while (p > q); return q >> 1; } #endif ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/gzread.c000066400000000000000000000501431300674244400233520ustar00rootroot00000000000000/* gzread.c -- zlib functions for reading gzip files * Copyright (C) 2004, 2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include #include #include "misc/util/abc_global.h" #include "gzguts.h" ABC_NAMESPACE_IMPL_START /* Local functions */ local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); local int gz_avail OF((gz_statep)); local int gz_next4 OF((gz_statep, unsigned long *)); local int gz_head OF((gz_statep)); local int gz_decomp OF((gz_statep)); local int gz_make OF((gz_statep)); local int gz_skip OF((gz_statep, z_off64_t)); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. This function needs to loop on read(), since read() is not guaranteed to read the number of bytes requested, depending on the type of descriptor. */ local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have) { int ret; *have = 0; do { ret = read(state->fd, buf + *have, len - *have); if (ret <= 0) break; *have += ret; } while (*have < len); if (ret < 0) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } if (ret == 0) state->eof = 1; return 0; } /* Load up input buffer and set eof flag if last data loaded -- return -1 on error, 0 otherwise. Note that the eof flag is set when the end of the input file is reached, even though there may be unused data in the buffer. Once that data has been used, no more attempts will be made to read the file. gz_avail() assumes that strm->avail_in == 0. */ local int gz_avail(gz_statep state) { z_streamp strm = &(state->strm); if (state->err != Z_OK) return -1; if (state->eof == 0) { if (gz_load(state, state->in, state->size, (unsigned *)&(strm->avail_in)) == -1) return -1; strm->next_in = state->in; } return 0; } /* Get next byte from input, or -1 if end or error. */ #define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ (strm->avail_in == 0 ? -1 : \ (strm->avail_in--, *(strm->next_in)++))) /* Get a four-byte little-endian integer and return 0 on success and the value in *ret. Otherwise -1 is returned and *ret is not modified. */ local int gz_next4(gz_statep state, unsigned long *ret) { int ch; unsigned long val; z_streamp strm = &(state->strm); val = NEXT(); val += (unsigned)NEXT() << 8; val += (unsigned long)NEXT() << 16; ch = NEXT(); if (ch == -1) return -1; val += (unsigned long)ch << 24; *ret = val; return 0; } /* Look for gzip header, set up for inflate or copy. state->have must be zero. If this is the first time in, allocate required memory. state->how will be left unchanged if there is no more input data available, will be set to COPY if there is no gzip header and direct copying will be performed, or it will be set to GZIP for decompression, and the gzip header will be skipped so that the next available input data is the raw deflate stream. If direct copying, then leftover input data from the input buffer will be copied to the output buffer. In that case, all further file reads will be directly to either the output buffer or a user buffer. If decompressing, the inflate state and the check value will be initialized. gz_head() will return 0 on success or -1 on failure. Failures may include read errors or gzip header errors. */ local int gz_head(gz_statep state) { z_streamp strm = &(state->strm); int flags; unsigned len; /* allocate read buffers and inflate memory */ if (state->size == 0) { /* allocate buffers */ state->in = (unsigned char *)malloc(state->want); state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { if (state->out != NULL) free(state->out); if (state->in != NULL) free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } state->size = state->want; /* allocate inflate memory */ state->strm.zalloc = Z_NULL; state->strm.zfree = Z_NULL; state->strm.opaque = Z_NULL; state->strm.avail_in = 0; state->strm.next_in = Z_NULL; if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ free(state->out); free(state->in); state->size = 0; gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } } /* get some data in the input buffer */ if (strm->avail_in == 0) { if (gz_avail(state) == -1) return -1; if (strm->avail_in == 0) return 0; } /* look for the gzip magic header bytes 31 and 139 */ if (strm->next_in[0] == 31) { strm->avail_in--; strm->next_in++; if (strm->avail_in == 0 && gz_avail(state) == -1) return -1; if (strm->avail_in && strm->next_in[0] == 139) { /* we have a gzip header, woo hoo! */ strm->avail_in--; strm->next_in++; /* skip rest of header */ if (NEXT() != 8) { /* compression method */ gz_error(state, Z_DATA_ERROR, "unknown compression method"); return -1; } flags = NEXT(); if (flags & 0xe0) { /* reserved flag bits */ gz_error(state, Z_DATA_ERROR, "unknown header flags set"); return -1; } NEXT(); /* modification time */ NEXT(); NEXT(); NEXT(); NEXT(); /* extra flags */ NEXT(); /* operating system */ if (flags & 4) { /* extra field */ len = (unsigned)NEXT(); len += (unsigned)NEXT() << 8; while (len--) if (NEXT() < 0) break; } if (flags & 8) /* file name */ while (NEXT() > 0) ; if (flags & 16) /* comment */ while (NEXT() > 0) ; if (flags & 2) { /* header crc */ NEXT(); NEXT(); } /* an unexpected end of file is not checked for here -- it will be noticed on the first request for uncompressed data */ /* set up for decompression */ inflateReset(strm); strm->adler = crc32(0L, Z_NULL, 0); state->how = GZIP; state->direct = 0; return 0; } else { /* not a gzip file -- save first byte (31) and fall to raw i/o */ state->out[0] = 31; state->have = 1; } } /* doing raw i/o, save start of raw data for seeking, copy any leftover input to output -- this assumes that the output buffer is larger than the input buffer, which also assures space for gzungetc() */ state->raw = state->pos; state->next = state->out; if (strm->avail_in) { memcpy(state->next + state->have, strm->next_in, strm->avail_in); state->have += strm->avail_in; strm->avail_in = 0; } state->how = COPY; state->direct = 1; return 0; } /* Decompress from input to the provided next_out and avail_out in the state. If the end of the compressed data is reached, then verify the gzip trailer check value and length (modulo 2^32). state->have and state->next are set to point to the just decompressed data, and the crc is updated. If the trailer is verified, state->how is reset to LOOK to look for the next gzip stream or raw data, once state->have is depleted. Returns 0 on success, -1 on failure. Failures may include invalid compressed data or a failed gzip trailer verification. */ local int gz_decomp(gz_statep state) { int ret; unsigned had; unsigned long crc, len; z_streamp strm = &(state->strm); /* fill output buffer up to end of deflate stream */ had = strm->avail_out; do { /* get more input for inflate() */ if (strm->avail_in == 0 && gz_avail(state) == -1) return -1; if (strm->avail_in == 0) { gz_error(state, Z_DATA_ERROR, "unexpected end of file"); return -1; } /* decompress and handle errors */ ret = inflate(strm, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { gz_error(state, Z_STREAM_ERROR, "internal error: inflate stream corrupt"); return -1; } if (ret == Z_MEM_ERROR) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ gz_error(state, Z_DATA_ERROR, strm->msg == NULL ? "compressed data error" : strm->msg); return -1; } } while (strm->avail_out && ret != Z_STREAM_END); /* update available output and crc check value */ state->have = had - strm->avail_out; state->next = strm->next_out - state->have; strm->adler = crc32(strm->adler, state->next, state->have); /* check gzip trailer if at end of deflate stream */ if (ret == Z_STREAM_END) { if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { gz_error(state, Z_DATA_ERROR, "unexpected end of file"); return -1; } if (crc != strm->adler) { gz_error(state, Z_DATA_ERROR, "incorrect data check"); return -1; } if (len != (strm->total_out & 0xffffffffL)) { gz_error(state, Z_DATA_ERROR, "incorrect length check"); return -1; } state->how = LOOK; /* ready for next stream, once have is 0 (leave state->direct unchanged to remember how) */ } /* good decompression */ return 0; } /* Make data and put in the output buffer. Assumes that state->have == 0. Data is either copied from the input file or decompressed from the input file depending on state->how. If state->how is LOOK, then a gzip header is looked for (and skipped if found) to determine wither to copy or decompress. Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY or GZIP unless the end of the input file has been reached and all data has been processed. */ local int gz_make(gz_statep state) { z_streamp strm = &(state->strm); if (state->how == LOOK) { /* look for gzip header */ if (gz_head(state) == -1) return -1; if (state->have) /* got some data from gz_head() */ return 0; } if (state->how == COPY) { /* straight copy */ if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) return -1; state->next = state->out; } else if (state->how == GZIP) { /* decompress */ strm->avail_out = state->size << 1; strm->next_out = state->out; if (gz_decomp(state) == -1) return -1; } return 0; } /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ local int gz_skip(gz_statep state, z_off64_t len) { unsigned n; /* skip over len bytes or reach end-of-file, whichever comes first */ while (len) /* skip over whatever is in output buffer */ if (state->have) { n = GT_OFF(state->have) || (z_off64_t)state->have > len ? (unsigned)len : state->have; state->have -= n; state->next += n; state->pos += n; len -= n; } /* output buffer empty -- return if we're at the end of the input */ else if (state->eof && state->strm.avail_in == 0) break; /* need more data to skip -- load up output buffer */ else { /* get more output, looking for header if required */ if (gz_make(state) == -1) return -1; } return 0; } /* -- see zlib.h -- */ int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { unsigned got, n; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're reading and that there's no error */ if (state->mode != GZ_READ || state->err != Z_OK) return -1; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); return -1; } /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return -1; } /* get len bytes to buf, or less than len if at the end */ got = 0; do { /* first just try copying data from the output buffer */ if (state->have) { n = state->have > len ? len : state->have; memcpy(buf, state->next, n); state->next += n; state->have -= n; } /* output buffer empty -- return if we're at the end of the input */ else if (state->eof && strm->avail_in == 0) break; /* need output data -- for small len or new stream load up our output buffer */ else if (state->how == LOOK || len < (state->size << 1)) { /* get more output, looking for header if required */ if (gz_make(state) == -1) return -1; continue; /* no progress yet -- go back to memcpy() above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ } /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ if (gz_load(state, (unsigned char *)buf, len, &n) == -1) return -1; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ strm->avail_out = len; strm->next_out = (unsigned char *)buf; if (gz_decomp(state) == -1) return -1; n = state->have; state->have = 0; } /* update progress */ len -= n; buf = (char *)buf + n; got += n; state->pos += n; } while (len); /* return number of bytes read into user buffer (will fit in int) */ return (int)got; } /* -- see zlib.h -- */ int ZEXPORT gzgetc(gzFile file) { int ret; unsigned char buf[1]; gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no error */ if (state->mode != GZ_READ || state->err != Z_OK) return -1; /* try output buffer (no need to check for skip request) */ if (state->have) { state->have--; state->pos++; return *(state->next)++; } /* nothing there -- try gzread() */ ret = gzread(file, buf, 1); return ret < 1 ? -1 : buf[0]; } /* -- see zlib.h -- */ int ZEXPORT gzungetc(int c, gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no error */ if (state->mode != GZ_READ || state->err != Z_OK) return -1; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return -1; } /* can't push EOF */ if (c < 0) return -1; /* if output buffer empty, put byte at end (allows more pushing) */ if (state->have == 0) { state->have = 1; state->next = state->out + (state->size << 1) - 1; state->next[0] = c; state->pos--; return c; } /* if no room, give up (must have already done a gzungetc()) */ if (state->have == (state->size << 1)) { gz_error(state, Z_BUF_ERROR, "out of room to push characters"); return -1; } /* slide output data if needed and insert byte before existing data */ if (state->next == state->out) { unsigned char *src = state->out + state->have; unsigned char *dest = state->out + (state->size << 1); while (src > state->out) *--dest = *--src; state->next = dest; } state->have++; state->next--; state->next[0] = c; state->pos--; return c; } /* -- see zlib.h -- */ char * ZEXPORT gzgets(gzFile file, char *buf, int len) { unsigned left, n; char *str; unsigned char *eol; gz_statep state; /* check parameters and get internal structure */ if (file == NULL || buf == NULL || len < 1) return NULL; state = (gz_statep)file; /* check that we're reading and that there's no error */ if (state->mode != GZ_READ || state->err != Z_OK) return NULL; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return NULL; } /* copy output bytes up to new line or len - 1, whichever comes first -- append a terminating zero to the string (we don't check for a zero in the contents, let the user worry about that) */ str = buf; left = (unsigned)len - 1; if (left) do { /* assure that something is in the output buffer */ if (state->have == 0) { if (gz_make(state) == -1) return NULL; /* error */ if (state->have == 0) { /* end of file */ if (buf == str) /* got bupkus */ return NULL; break; /* got something -- return it */ } } /* look for end-of-line in current output buffer */ n = state->have > left ? left : state->have; eol = (unsigned char *)memchr(state->next, '\n', n); if (eol != NULL) n = (unsigned)(eol - state->next) + 1; /* copy through end-of-line, or remainder if not found */ memcpy(buf, state->next, n); state->have -= n; state->next += n; state->pos += n; left -= n; buf += n; } while (left && eol == NULL); /* found end-of-line or out of space -- terminate string and return it */ buf[0] = 0; return str; } /* -- see zlib.h -- */ int ZEXPORT gzdirect(gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; /* check that we're reading */ if (state->mode != GZ_READ) return 0; /* if the state is not known, but we can find out, then do so (this is mainly for right after a gzopen() or gzdopen()) */ if (state->how == LOOK && state->have == 0) (void)gz_head(state); /* return 1 if reading direct, 0 if decompressing a gzip stream */ return state->direct; } /* -- see zlib.h -- */ int ZEXPORT gzclose_r(gzFile file) { int ret; gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're reading */ if (state->mode != GZ_READ) return Z_STREAM_ERROR; /* free memory and close file */ if (state->size) { inflateEnd(&(state->strm)); free(state->out); free(state->in); } gz_error(state, Z_OK, NULL); free(state->path); ret = close(state->fd); free(state); return ret ? Z_ERRNO : Z_OK; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/gzwrite.c000066400000000000000000000343471300674244400236010ustar00rootroot00000000000000/* gzwrite.c -- zlib functions for writing gzip files * Copyright (C) 2004, 2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include #include #include "misc/util/abc_global.h" #include "gzguts.h" ABC_NAMESPACE_IMPL_START /* Local functions */ local int gz_init OF((gz_statep)); local int gz_comp OF((gz_statep, int)); local int gz_zero OF((gz_statep, z_off64_t)); /* Initialize state for writing a gzip file. Mark initialization by setting state->size to non-zero. Return -1 on failure or 0 on success. */ local int gz_init(gz_statep state) { int ret; z_streamp strm = &(state->strm); /* allocate input and output buffers */ state->in = (unsigned char *)malloc(state->want); state->out = (unsigned char *)malloc(state->want); if (state->in == NULL || state->out == NULL) { if (state->out != NULL) free(state->out); if (state->in != NULL) free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } /* allocate deflate memory, set up for gzip compression */ strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; ret = deflateInit2(strm, state->level, Z_DEFLATED, 15 + 16, 8, state->strategy); if (ret != Z_OK) { free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } /* mark state as initialized */ state->size = state->want; /* initialize write buffer */ strm->avail_out = state->size; strm->next_out = state->out; state->next = strm->next_out; return 0; } /* Compress whatever is at avail_in and next_in and write to the output file. Return -1 if there is an error writing to the output file, otherwise 0. flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, then the deflate() state is reset to start a new gzip stream. */ local int gz_comp(gz_statep state, int flush) { int ret, got; unsigned have; z_streamp strm = &(state->strm); /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return -1; /* run deflate() on provided input until it produces no more output */ ret = Z_OK; do { /* write out current buffer contents if full, or if flushing, but if doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { have = (unsigned)(strm->next_out - state->next); if (have && ((got = write(state->fd, state->next, have)) < 0 || (unsigned)got != have)) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } if (strm->avail_out == 0) { strm->avail_out = state->size; strm->next_out = state->out; } state->next = strm->next_out; } /* compress */ have = strm->avail_out; ret = deflate(strm, flush); if (ret == Z_STREAM_ERROR) { gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt"); return -1; } have -= strm->avail_out; } while (have); /* if that completed a deflate stream, allow another to start */ if (flush == Z_FINISH) deflateReset(strm); /* all done, no errors */ return 0; } /* Compress len zeros to output. Return -1 on error, 0 on success. */ local int gz_zero(gz_statep state, z_off64_t len) { int first; unsigned n; z_streamp strm = &(state->strm); /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return -1; /* compress len zeros (len guaranteed > 0) */ first = 1; while (len) { n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size; if (first) { memset(state->in, 0, n); first = 0; } strm->avail_in = n; strm->next_in = state->in; state->pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return -1; len -= n; } return 0; } /* -- see zlib.h -- */ int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) { unsigned put = len; unsigned n; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); return 0; } /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* for small len, copy to input buffer, otherwise compress directly */ if (len < state->size) { /* copy to input buffer, compress when full */ do { if (strm->avail_in == 0) strm->next_in = state->in; n = state->size - strm->avail_in; if (n > len) n = len; memcpy(strm->next_in + strm->avail_in, buf, n); strm->avail_in += n; state->pos += n; buf = (char *)buf + n; len -= n; if (len && gz_comp(state, Z_NO_FLUSH) == -1) return 0; } while (len); } else { /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* directly compress user buffer to file */ strm->avail_in = len; strm->next_in = (unsigned char *)(voidp)buf; state->pos += len; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; } /* input was all buffered or compressed (put will fit in int) */ return (int)put; } /* -- see zlib.h -- */ int ZEXPORT gzputc(gzFile file, int c) { unsigned char buf[1]; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return -1; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ if (strm->avail_in < state->size) { if (strm->avail_in == 0) strm->next_in = state->in; strm->next_in[strm->avail_in++] = c; state->pos++; return c; } /* no room in buffer or not initialized, use gz_write() */ buf[0] = c; if (gzwrite(file, buf, 1) != 1) return -1; return c; } /* -- see zlib.h -- */ int ZEXPORT gzputs(gzFile file, const char *str) { int ret; unsigned len; /* write string */ len = (unsigned)strlen(str); ret = gzwrite(file, str, len); return ret == 0 && len != 0 ? -1 : ret; } #ifdef STDC #include /* -- see zlib.h -- */ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) { int size, len; gz_statep state; z_streamp strm; va_list va; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* do the printf() into the input buffer, put length in len */ size = (int)(state->size); state->in[size - 1] = 0; va_start(va, format); #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void (void)vsprintf(state->in, format, va); va_end(va); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else len = vsprintf(state->in, format, va); va_end(va); # endif #else # ifdef HAS_vsnprintf_void (void)vsnprintf(state->in, size, format, va); va_end(va); len = strlen(state->in); # else len = vsnprintf((char *)(state->in), size, format, va); va_end(va); # endif #endif /* check that printf() results fit in buffer */ if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) return 0; /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; state->pos += len; return len; } #else /* !STDC */ /* -- see zlib.h -- */ int ZEXPORTVA gzprintf (gzFile file, const char *format, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20) { int size, len; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* do the printf() into the input buffer, put length in len */ size = (int)(state->size); state->in[size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); len = strlen(state->in); # else len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #endif /* check that printf() results fit in buffer */ if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) return 0; /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; state->pos += len; return len; } #endif /* -- see zlib.h -- */ int ZEXPORT gzflush(gzFile file, int flush) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* check flush parameter */ if (flush < 0 || flush > Z_FINISH) return Z_STREAM_ERROR; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* compress remaining data with requested flush */ gz_comp(state, flush); return state->err; } /* -- see zlib.h -- */ int ZEXPORT gzsetparams(gzFile file, int level, int strategy) { gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* if no change is requested, then do nothing */ if (level == state->level && strategy == state->strategy) return Z_OK; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* change compression parameters for subsequent input */ if (state->size) { /* flush previous input with previous parameters before changing */ if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) return state->err; deflateParams(strm, level, strategy); } state->level = level; state->strategy = strategy; return Z_OK; } /* -- see zlib.h -- */ int ZEXPORT gzclose_w(gzFile file) { int ret = 0; gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're writing */ if (state->mode != GZ_WRITE) return Z_STREAM_ERROR; /* check for seek request */ if (state->seek) { state->seek = 0; ret += gz_zero(state, state->skip); } /* flush, free memory, and close file */ ret += gz_comp(state, Z_FINISH); (void)deflateEnd(&(state->strm)); free(state->out); free(state->in); gz_error(state, Z_OK, NULL); free(state->path); ret += close(state->fd); free(state); return ret ? Z_ERRNO : Z_OK; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/infback.c000066400000000000000000000542211300674244400234740ustar00rootroot00000000000000/* infback.c -- inflate using a call-back interface * Copyright (C) 1995-2009 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* This code is largely copied from inflate.c. Normally either infback.o or inflate.o would be linked into an application--not both. The interface with inffast.c is retained so that optimized assembler-coded versions of inflate_fast() can be used with either inflate.c or infback.c. */ #include #include #include #include "misc/util/abc_global.h" #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" ABC_NAMESPACE_IMPL_START /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); /* strm provides memory allocation functions in zalloc and zfree, or Z_NULL to use the library memory allocation functions. windowBits is in the range 8..15, and window is a user-supplied window and output buffer that is 2**windowBits bytes. */ int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size) { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL || window == Z_NULL || windowBits < 8 || windowBits > 15) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { strm->zalloc = zcalloc; strm->opaque = (voidpf)0; } if (strm->zfree == (free_func)0) strm->zfree = zcfree; state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; state->wbits = windowBits; state->wsize = 1U << windowBits; state->window = window; state->wnext = 0; state->whave = 0; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } /* Macros for inflateBack(): */ /* Load returned state from inflate_fast() */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Set state from registers for inflate_fast() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Assure that some input is available. If input is requested, but denied, then return a Z_BUF_ERROR from inflateBack(). */ #define PULL() \ do { \ if (have == 0) { \ have = in(in_desc, &next); \ if (have == 0) { \ next = Z_NULL; \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflateBack() with an error if there is no input available. */ #define PULLBYTE() \ do { \ PULL(); \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflateBack() with an error. */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* Assure that some output space is available, by writing out the window if it's full. If the write fails, return from inflateBack() with a Z_BUF_ERROR. */ #define ROOM() \ do { \ if (left == 0) { \ put = state->window; \ left = state->wsize; \ state->whave = left; \ if (out(out_desc, put, left)) { \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* strm provides the memory allocation functions and window buffer on input, and provides information on the unused input on return. For Z_DATA_ERROR returns, strm will also provide an error message. in() and out() are the call-back input and output functions. When inflateBack() needs more input, it calls in(). When inflateBack() has filled the window with output, or when it completes with data in the window, it calls out() to write out the data. The application must not change the provided input until in() is called again or inflateBack() returns. The application must not change the window/output buffer until inflateBack() returns. in() and out() are called with a descriptor parameter provided in the inflateBack() call. This parameter can be a structure that provides the information required to do the read or write, as well as accumulated information on the input and output such as totals and check values. in() should return zero on failure. out() should return non-zero on failure. If either in() or out() fails, than inflateBack() returns a Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it was in() or out() that caused in the error. Otherwise, inflateBack() returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format error, or Z_MEM_ERROR if it could not allocate memory for the state. inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc) { struct inflate_state FAR *state; unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* Check that the strm exists and that the state was initialized */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* Reset the state */ strm->msg = Z_NULL; state->mode = TYPE; state->last = 0; state->whave = 0; next = strm->next_in; have = next != Z_NULL ? strm->avail_in : 0; hold = 0; bits = 0; put = state->window; left = state->wsize; /* Inflate until end of block marked as last */ for (;;) switch (state->mode) { case TYPE: /* determine and dispatch block type */ if (state->last) { BYTEBITS(); state->mode = DONE; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN; /* decode codes */ break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: /* get and verify stored block length */ BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); /* copy stored block from input to output */ while (state->length != 0) { copy = state->length; PULL(); ROOM(); if (copy > have) copy = have; if (copy > left) copy = left; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: /* get dynamic table entries descriptor */ NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); /* get code length code lengths (not a typo) */ state->have = 0; while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); /* get length and distance code code lengths */ state->have = 0; while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = (unsigned)(state->lens[state->have - 1]); copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (code const FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; case LEN: /* use inflate_fast() if we have enough input and output */ if (have >= 6 && left >= 258) { RESTORE(); if (state->whave < state->wsize) state->whave = state->wsize - left; inflate_fast(strm, state->wsize); LOAD(); break; } /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); state->length = (unsigned)here.val; /* process literal */ if (here.op == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); ROOM(); *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; } /* process end of block */ if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } /* invalid code */ if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } /* length code -- get extra bits, if any */ state->extra = (unsigned)(here.op) & 15; if (state->extra != 0) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); } Tracevv((stderr, "inflate: length %u\n", state->length)); /* get distance code */ for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; /* get distance extra bits, if any */ state->extra = (unsigned)(here.op) & 15; if (state->extra != 0) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); } if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } Tracevv((stderr, "inflate: distance %u\n", state->offset)); /* copy match from window to output */ do { ROOM(); copy = state->wsize - state->offset; if (copy < left) { from = put + copy; copy = left - copy; } else { from = put - state->offset; copy = left; } if (copy > state->length) copy = state->length; state->length -= copy; left -= copy; do { *put++ = *from++; } while (--copy); } while (state->length != 0); break; case DONE: /* inflate stream terminated properly -- write leftover output */ ret = Z_STREAM_END; if (left < state->wsize) { if (out(out_desc, state->window, state->wsize - left)) ret = Z_BUF_ERROR; } goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; default: /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } /* Return unused input */ inf_leave: strm->next_in = next; strm->avail_in = have; return ret; } int ZEXPORT inflateBackEnd(z_streamp strm) { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/inffast.c000066400000000000000000000324001300674244400235240ustar00rootroot00000000000000/* inffast.c -- fast decoding * Copyright (C) 1995-2008, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include #include #include "misc/util/abc_global.h" #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" ABC_NAMESPACE_IMPL_START #ifndef ASMINF /* Allow machine dependent optimization for post-increment or pre-increment. Based on testing to date, Pre-increment preferred for: - PowerPC G3 (Adler) - MIPS R5000 (Randers-Pehrson) Post-increment preferred for: - none No measurable difference: - Pentium III (Anderson) - M68060 (Nikl) */ #ifdef POSTINC # define OFF 0 # define PUP(a) *(a)++ #else # define OFF 1 # define PUP(a) *++(a) #endif /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; unsigned char FAR *in; /* local strm->next_in */ unsigned char FAR *last; /* while in < last, enough input available */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ unsigned long hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ code const FAR *lcode; /* local strm->lencode */ code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ code here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char FAR *from; /* where to copy match from */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; in = strm->next_in - OFF; last = in + (strm->avail_in - 5); out = strm->next_out - OFF; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT dmax = state->dmax; #endif wsize = state->wsize; whave = state->whave; wnext = state->wnext; window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; dcode = state->distcode; lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if (bits < 15) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; hold += (unsigned long)(PUP(in)) << bits; bits += 8; } here = lcode[hold & lmask]; dolen: op = (unsigned)(here.bits); hold >>= op; bits -= op; op = (unsigned)(here.op); if (op == 0) { /* literal */ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); PUP(out) = (unsigned char)(here.val); } else if (op & 16) { /* length base */ len = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; hold += (unsigned long)(PUP(in)) << bits; bits += 8; } here = dcode[hold & dmask]; dodist: op = (unsigned)(here.bits); hold >>= op; bits -= op; op = (unsigned)(here.op); if (op & 16) { /* distance base */ dist = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; } } dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif hold >>= op; bits -= op; Tracevv((stderr, "inflate: distance %u\n", dist)); op = (unsigned)(out - beg); /* max distance in output */ if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { PUP(out) = 0; } while (--len); continue; } len -= op - whave; do { PUP(out) = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { PUP(out) = PUP(from); } while (--len); continue; } #endif } from = window - OFF; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } else if (wnext < op) { /* wrap around window */ from += wsize + wnext - op; op -= wnext; if (op < len) { /* some from end of window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = window - OFF; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ from += wnext - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } while (len > 2); if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode[here.val + (hold & ((1U << op) - 1))]; goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ here = lcode[here.val + (hold & ((1U << op) - 1))]; goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } else { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } } while (in < last && out < end); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; in -= len; bits -= len << 3; hold &= (1U << bits) - 1; /* update state and return */ strm->next_in = in + OFF; strm->next_out = out + OFF; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); state->hold = hold; state->bits = bits; return; } /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - Three separate decoding do-loops for direct, window, and wnext == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes - Swapping literal/length else - Swapping window/direct else - Larger unrolled copy loops (three is about right) - Moving len -= 3 statement into middle of loop */ #endif /* !ASMINF */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/inffast.h000066400000000000000000000007411300674244400235340ustar00rootroot00000000000000/* inffast.h -- header to use inffast.c * Copyright (C) 1995-2003, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ ABC_NAMESPACE_HEADER_START void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); ABC_NAMESPACE_HEADER_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/inffixed.h000066400000000000000000000144011300674244400236740ustar00rootroot00000000000000 /* inffixed.h -- table for decoding fixed codes * Generated automatically by makefixed(). */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ //ABC_NAMESPACE_HEADER_START static const code lenfix[512] = { {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, {0,9,255} }; static const code distfix[32] = { {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, {22,5,193},{64,5,0} }; //ABC_NAMESPACE_HEADER_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/inflate.c000066400000000000000000001464441300674244400235320ustar00rootroot00000000000000/* inflate.c -- zlib decompression * Copyright (C) 1995-2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * Change history: * * 1.2.beta0 24 Nov 2002 * - First version -- complete rewrite of inflate to simplify code, avoid * creation of window when not needed, minimize use of window when it is * needed, make inffast.c even faster, implement gzip decoding, and to * improve code readability and style over the previous zlib inflate code * * 1.2.beta1 25 Nov 2002 * - Use pointers for available input and output checking in inffast.c * - Remove input and output counters in inffast.c * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 * - Remove unnecessary second byte pull from length extra in inffast.c * - Unroll direct copy to three copies per loop in inffast.c * * 1.2.beta2 4 Dec 2002 * - Change external routine names to reduce potential conflicts * - Correct filename to inffixed.h for fixed tables in inflate.c * - Make hbuf[] unsigned char to match parameter type in inflate.c * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) * to avoid negation problem on Alphas (64 bit) in inflate.c * * 1.2.beta3 22 Dec 2002 * - Add comments on state->bits assertion in inffast.c * - Add comments on op field in inftrees.h * - Fix bug in reuse of allocated window after inflateReset() * - Remove bit fields--back to byte structure for speed * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths * - Change post-increments to pre-increments in inflate_fast(), PPC biased? * - Add compile time option, POSTINC, to use post-increments instead (Intel?) * - Make MATCH copy in inflate() much faster for when inflate_fast() not used * - Use local copies of stream next and avail values, as well as local bit * buffer and bit count in inflate()--for speed when inflate_fast() not used * * 1.2.beta4 1 Jan 2003 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings * - Move a comment on output buffer sizes from inffast.c to inflate.c * - Add comments in inffast.c to introduce the inflate_fast() routine * - Rearrange window copies in inflate_fast() for speed and simplification * - Unroll last copy for window match in inflate_fast() * - Use local copies of window variables in inflate_fast() for speed * - Pull out common wnext == 0 case for speed in inflate_fast() * - Make op and len in inflate_fast() unsigned for consistency * - Add FAR to lcode and dcode declarations in inflate_fast() * - Simplified bad distance check in inflate_fast() * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new * source file infback.c to provide a call-back interface to inflate for * programs like gzip and unzip -- uses window as output buffer to avoid * window copying * * 1.2.beta5 1 Jan 2003 * - Improved inflateBack() interface to allow the caller to provide initial * input in strm. * - Fixed stored blocks bug in inflateBack() * * 1.2.beta6 4 Jan 2003 * - Added comments in inffast.c on effectiveness of POSTINC * - Typecasting all around to reduce compiler warnings * - Changed loops from while (1) or do {} while (1) to for (;;), again to * make compilers happy * - Changed type of window in inflateBackInit() to unsigned char * * * 1.2.beta7 27 Jan 2003 * - Changed many types to unsigned or unsigned short to avoid warnings * - Added inflateCopy() function * * 1.2.0 9 Mar 2003 * - Changed inflateBack() interface to provide separate opaque descriptors * for the in() and out() functions * - Changed inflateBack() argument and in_func typedef to swap the length * and buffer address return values for the input function * - Check next_in and next_out for Z_NULL on entry to inflate() * * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. */ #include #include #include #include "misc/util/abc_global.h" #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" ABC_NAMESPACE_IMPL_START #ifdef MAKEFIXED # ifndef BUILDFIXED # define BUILDFIXED # endif #endif /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, unsigned out)); #ifdef BUILDFIXED void makefixed OF((void)); #endif local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, unsigned len)); int ZEXPORT inflateReset(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; strm->adler = 1; /* to support ill-conceived Java test suite */ state->mode = HEAD; state->last = 0; state->havedict = 0; state->dmax = 32768U; state->head = Z_NULL; state->wsize = 0; state->whave = 0; state->wnext = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; state->sane = 1; state->back = -1; Tracev((stderr, "inflate: reset\n")); return Z_OK; } int ZEXPORT inflateReset2(z_streamp strm, int windowBits) { int wrap; struct inflate_state FAR *state; /* get the state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { wrap = 0; windowBits = -windowBits; } else { wrap = (windowBits >> 4) + 1; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; #endif } /* set number of window bits, free window if different */ if (windowBits && (windowBits < 8 || windowBits > 15)) return Z_STREAM_ERROR; if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { ZFREE(strm, state->window); state->window = Z_NULL; } /* update state and reset the rest of it */ state->wrap = wrap; state->wbits = (unsigned)windowBits; return inflateReset(strm); } int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) { int ret; struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { strm->zalloc = zcalloc; strm->opaque = (voidpf)0; } if (strm->zfree == (free_func)0) strm->zfree = zcfree; state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->window = Z_NULL; ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); strm->state = Z_NULL; } return ret; } int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; state->hold += value << state->bits; state->bits += bits; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } #ifdef MAKEFIXED #include /* Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also defines BUILDFIXED, so the tables are built on the fly. makefixed() writes those tables to stdout, which would be piped to inffixed.h. A small program can simply call makefixed to do this: void makefixed(void); int main(void) { makefixed(); return 0; } Then that can be linked with zlib built with MAKEFIXED defined and run: a.out > inffixed.h */ void makefixed() { unsigned low, size; struct inflate_state state; fixedtables(&state); puts(" /* inffixed.h -- table for decoding fixed codes"); puts(" * Generated automatically by makefixed()."); puts(" */"); puts(""); puts(" /* WARNING: this file should *not* be used by applications."); puts(" It is part of the implementation of this library and is"); puts(" subject to change. Applications should only use zlib.h."); puts(" */"); puts(""); size = 1U << 9; printf(" static const code lenfix[%u] = {", size); low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); size = 1U << 5; printf("\n static const code distfix[%u] = {", size); low = 0; for (;;) { if ((low % 6) == 0) printf("\n "); printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, state.distcode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); } #endif /* MAKEFIXED */ /* Update the window with the last wsize (normally 32K) bytes written before returning. If window does not exist yet, create it. This is only called when a window is already in use, or when output has been written during this inflate call, but the end of the deflate stream has not been reached yet. It is also called to create a window for dictionary data when a dictionary is loaded. Providing output buffers larger than 32K to inflate() should provide a speed advantage, since only the last 32K of output is copied to the sliding window upon return from inflate(), and since all distances after the first 32K of output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ local int updatewindow(z_streamp strm, unsigned out) { struct inflate_state FAR *state; unsigned copy, dist; state = (struct inflate_state FAR *)strm->state; /* if it hasn't been done already, allocate space for the window */ if (state->window == Z_NULL) { state->window = (unsigned char FAR *) ZALLOC(strm, 1U << state->wbits, sizeof(unsigned char)); if (state->window == Z_NULL) return 1; } /* if window not in use yet, initialize */ if (state->wsize == 0) { state->wsize = 1U << state->wbits; state->wnext = 0; state->whave = 0; } /* copy state->wsize or less output bytes into the circular window */ copy = out - strm->avail_out; if (copy >= state->wsize) { zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); copy -= dist; if (copy) { zmemcpy(state->window, strm->next_out - copy, copy); state->wnext = copy; state->whave = state->wsize; } else { state->wnext += dist; if (state->wnext == state->wsize) state->wnext = 0; if (state->whave < state->wsize) state->whave += dist; } } return 0; } /* Macros for inflate(): */ /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP # define UPDATE(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else # define UPDATE(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ check = crc32(check, hbuf, 2); \ } while (0) # define CRC4(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ hbuf[2] = (unsigned char)((word) >> 16); \ hbuf[3] = (unsigned char)((word) >> 24); \ check = crc32(check, hbuf, 4); \ } while (0) #endif /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ #define PULLBYTE() \ do { \ if (have == 0) goto inf_leave; \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflate(). */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* Reverse the bytes in a 32-bit value */ #define REVERSE(q) \ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is structured roughly as follows: for (;;) switch (state) { ... case STATEn: if (not enough input data or output space to make progress) return; ... make progress ... state = STATEm; break; ... } so when inflate() is called again, the same case is attempted again, and if the appropriate resources are provided, the machine proceeds to the next state. The NEEDBITS() macro is usually the way the state evaluates whether it can proceed or should return. NEEDBITS() does the return if the requested bits are not available. The typical use of the BITS macros is: NEEDBITS(n); ... do something with BITS(n) ... DROPBITS(n); where NEEDBITS(n) either returns from inflate() if there isn't enough input left to load n bits into the accumulator, or it continues. BITS(n) gives the low n bits in the accumulator. When done, DROPBITS(n) drops the low n bits off the accumulator. INITBITS() clears the accumulator and sets the number of available bits to zero. BYTEBITS() discards just enough bits to put the accumulator on a byte boundary. After BYTEBITS() and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return if there is no input available. The decoding of variable length codes uses PULLBYTE() directly in order to pull just enough bytes to decode the next code, and no more. Some states loop until they get enough input, making sure that enough state information is maintained to continue the loop where it left off if NEEDBITS() returns in the loop. For example, want, need, and keep would all have to actually be part of the saved state in case NEEDBITS() returns: case STATEw: while (want < need) { NEEDBITS(n); keep[want++] = BITS(n); DROPBITS(n); } state = STATEx; case STATEx: As shown above, if the next state is also the next case, then the break is omitted. A state may also return if there is not enough output space available to complete that state. Those states are copying stored data, writing a literal byte, and copying a matching string. When returning, a "goto inf_leave" is used to update the total counters, update the check value, and determine whether any progress has been made during that inflate() call in order to return the proper return code. Progress is defined as a change in either strm->avail_in or strm->avail_out. When there is a window, goto inf_leave will update the window with the last output written. If a goto inf_leave occurs in the middle of decompression and there is no window currently, goto inf_leave will create one and copy output to the window for the next call of inflate(). In this implementation, the flush parameter of inflate() only affects the return code (per zlib.h). inflate() always writes as much as possible to strm->next_out, given the space available and the provided input--the effect documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers the allocation of and copying into a sliding window until necessary, which provides the effect documented in zlib.h for Z_FINISH when the entire input stream available. So the only thing the flush parameter actually does is: when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it will return Z_BUF_ERROR if it has not reached the end of the stream. */ int ZEXPORT inflate(z_streamp strm, int flush) { struct inflate_state FAR *state; unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ #ifdef GUNZIP unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ LOAD(); in = have; out = left; ret = Z_OK; for (;;) switch (state->mode) { case HEAD: if (state->wrap == 0) { state->mode = TYPEDO; break; } NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; break; } state->flags = 0; /* expect zlib header */ if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { strm->msg = (char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; else if (len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } state->dmax = 1U << len; Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); break; #ifdef GUNZIP case FLAGS: NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { strm->msg = (char *)"unknown header flags set"; state->mode = BAD; break; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; if (state->flags & 0x0200) CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: NEEDBITS(16); if (state->head != Z_NULL) { state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && state->head->extra != Z_NULL) { len = state->head->extra_len - state->length; zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; state->length -= copy; } if (state->length) goto inf_leave; } state->length = 0; state->mode = NAME; case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) state->head->name[state->length++] = len; } while (len && copy < have); if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) state->head->comment[state->length++] = len; } while (len && copy < have); if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); if (hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; } INITBITS(); } if (state->head != Z_NULL) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; #endif case DICTID: NEEDBITS(32); strm->adler = state->check = REVERSE(hold); INITBITS(); state->mode = DICT; case DICT: if (state->havedict == 0) { RESTORE(); return Z_NEED_DICT; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; case TYPEDO: if (state->last) { BYTEBITS(); state->mode = CHECK; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN_; /* decode codes */ if (flush == Z_TREES) { DROPBITS(2); goto inf_leave; } break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); state->mode = COPY_; if (flush == Z_TREES) goto inf_leave; case COPY_: state->mode = COPY; case COPY: copy = state->length; if (copy) { if (copy > have) copy = have; if (copy > left) copy = left; if (copy == 0) goto inf_leave; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; break; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = state->lens[state->have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (code const FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN_; if (flush == Z_TREES) goto inf_leave; case LEN_: state->mode = LEN; case LEN: if (have >= 6 && left >= 258) { RESTORE(); inflate_fast(strm, out); LOAD(); if (state->mode == TYPE) state->back = -1; break; } state->back = 0; for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; state->length = (unsigned)here.val; if ((int)(here.op) == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); state->mode = LIT; break; } if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->back = -1; state->mode = TYPE; break; } if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; case LENEXT: if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } Tracevv((stderr, "inflate: length %u\n", state->length)); state->was = state->length; state->mode = DIST; case DIST: for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; case DISTEXT: if (state->extra) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; case MATCH: if (left == 0) goto inf_leave; copy = out - left; if (state->offset > copy) { /* copy from window */ copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state->whave; if (copy > state->length) copy = state->length; if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = 0; } while (--copy); if (state->length == 0) state->mode = LEN; break; #endif } if (copy > state->wnext) { copy -= state->wnext; from = state->window + (state->wsize - copy); } else from = state->window + (state->wnext - copy); if (copy > state->length) copy = state->length; } else { /* copy from output */ from = put - state->offset; copy = state->length; } if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = *from++; } while (--copy); if (state->length == 0) state->mode = LEN; break; case LIT: if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; case CHECK: if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; if (out) strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; if (( #ifdef GUNZIP state->flags ? hold : #endif REVERSE(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state->mode = LENGTH; case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); if (hold != (state->total & 0xffffffffUL)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state->mode = DONE; case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: default: return Z_STREAM_ERROR; } /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) if (updatewindow(strm, out)) { state->mode = MEM; return Z_MEM_ERROR; } in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; if (state->wrap && out) strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); strm->data_type = state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } int ZEXPORT inflateEnd(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) { struct inflate_state FAR *state; unsigned long id; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; /* check for correct dictionary id */ if (state->mode == DICT) { id = adler32(0L, Z_NULL, 0); id = adler32(id, dictionary, dictLength); if (id != state->check) return Z_DATA_ERROR; } /* copy dictionary to window */ if (updatewindow(strm, strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } if (dictLength > state->wsize) { zmemcpy(state->window, dictionary + dictLength - state->wsize, state->wsize); state->whave = state->wsize; } else { zmemcpy(state->window + state->wsize - dictLength, dictionary, dictLength); state->whave = dictLength; } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) { struct inflate_state FAR *state; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; /* save header structure */ state->head = head; head->done = 0; return Z_OK; } /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes found in order so far, in 0..3. On return *have is updated to the new state. If on return *have equals four, then the pattern was found and the return value is how many bytes were read including the last byte of the pattern. If *have is less than four, then the pattern has not been found yet and the return value is len. In the latter case, syncsearch() can be called again with more data and the *have state. *have is initialized to zero for the first call. */ local unsigned syncsearch(unsigned FAR *have, unsigned char FAR *buf, unsigned len) { unsigned got; unsigned next; got = *have; next = 0; while (next < len && got < 4) { if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) got++; else if (buf[next]) got = 0; else got = 4 - got; next++; } *have = got; return next; } int ZEXPORT inflateSync(z_streamp strm) { unsigned len; /* number of bytes to look at or looked at */ unsigned long in, out; /* temporary to save total_in and total_out */ unsigned char buf[4]; /* to restore bit buffer to byte string */ struct inflate_state FAR *state; /* check parameters */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; state->hold <<= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { buf[len++] = (unsigned char)(state->hold); state->hold >>= 8; state->bits -= 8; } state->have = 0; syncsearch(&(state->have), buf, len); } /* search available input */ len = syncsearch(&(state->have), strm->next_in, strm->avail_in); strm->avail_in -= len; strm->next_in += len; strm->total_in += len; /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; state->mode = TYPE; return Z_OK; } /* Returns true if inflate is currently at the end of a block generated by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ int ZEXPORT inflateSyncPoint(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; unsigned wsize; /* check input */ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; /* allocate space */ copy = (struct inflate_state FAR *) ZALLOC(source, 1, sizeof(struct inflate_state)); if (copy == Z_NULL) return Z_MEM_ERROR; window = Z_NULL; if (state->window != Z_NULL) { window = (unsigned char FAR *) ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); if (window == Z_NULL) { ZFREE(source, copy); return Z_MEM_ERROR; } } /* copy state */ zmemcpy(dest, source, sizeof(z_stream)); zmemcpy(copy, state, sizeof(struct inflate_state)); if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); if (window != Z_NULL) { wsize = 1U << state->wbits; zmemcpy(window, state->window, wsize); } copy->window = window; dest->state = (struct internal_state FAR *)copy; return Z_OK; } int ZEXPORT inflateUndermine(z_streamp strm, int subvert) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->sane = !subvert; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR return Z_OK; #else state->sane = 1; return Z_DATA_ERROR; #endif } long ZEXPORT inflateMark(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; state = (struct inflate_state FAR *)strm->state; return ((long)(state->back) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/inflate.h000066400000000000000000000144651300674244400235340ustar00rootroot00000000000000/* inflate.h -- internal inflate state definition * Copyright (C) 1995-2009 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ ABC_NAMESPACE_HEADER_START /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ #ifndef NO_GZIP # define GUNZIP #endif /* Possible inflate modes between inflate() calls */ typedef enum { HEAD, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ EXLEN, /* i: waiting for extra length (gzip) */ EXTRA, /* i: waiting for extra bytes (gzip) */ NAME, /* i: waiting for end of file name (gzip) */ COMMENT, /* i: waiting for end of comment (gzip) */ HCRC, /* i: waiting for header crc (gzip) */ DICTID, /* i: waiting for dictionary check value */ DICT, /* waiting for inflateSetDictionary() call */ TYPE, /* i: waiting for type bits, including last-flag bit */ TYPEDO, /* i: same, but skip check to exit inflate on new block */ STORED, /* i: waiting for stored size (length and complement) */ COPY_, /* i/o: same as COPY below, but only first time in */ COPY, /* i/o: waiting for input or output to copy stored block */ TABLE, /* i: waiting for dynamic block table lengths */ LENLENS, /* i: waiting for code length code lengths */ CODELENS, /* i: waiting for length/lit and distance code lengths */ LEN_, /* i: same as LEN below, but only first time in */ LEN, /* i: waiting for length/lit/eob code */ LENEXT, /* i: waiting for length extra bits */ DIST, /* i: waiting for distance code */ DISTEXT, /* i: waiting for distance extra bits */ MATCH, /* o: waiting for output space to copy string */ LIT, /* o: waiting for output space to write literal */ CHECK, /* i: waiting for 32-bit check value */ LENGTH, /* i: waiting for 32-bit length (gzip) */ DONE, /* finished check, done -- remain here until reset */ BAD, /* got a data error -- remain here until reset */ MEM, /* got an inflate() memory error -- remain here until reset */ SYNC /* looking for synchronization bytes to restart inflate() */ } inflate_mode; /* State transitions between above modes - (most modes can go to BAD or MEM on error -- not shown for clarity) Process header: HEAD -> (gzip) or (zlib) or (raw) (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> HCRC -> TYPE (zlib) -> DICTID or TYPE DICTID -> DICT -> TYPE (raw) -> TYPEDO Read deflate blocks: TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK STORED -> COPY_ -> COPY -> TYPE TABLE -> LENLENS -> CODELENS -> LEN_ LEN_ -> LEN Read deflate codes in fixed or dynamic block: LEN -> LENEXT or LIT or TYPE LENEXT -> DIST -> DISTEXT -> MATCH -> LEN LIT -> LEN Process trailer: CHECK -> LENGTH -> DONE */ /* state maintained between inflate() calls. Approximately 10K bytes. */ struct inflate_state { inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ /* for table and code decoding */ unsigned extra; /* extra bits needed */ /* fixed and dynamic code tables */ code const FAR *lencode; /* starting table for length/literal codes */ code const FAR *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code FAR *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ int sane; /* if false, allow invalid distance too far */ int back; /* bits back of last unprocessed length/lit */ unsigned was; /* initial length of match */ }; ABC_NAMESPACE_HEADER_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/inftrees.c000066400000000000000000000330671300674244400237230ustar00rootroot00000000000000/* inftrees.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include #include #include "misc/util/abc_global.h" #include "zutil.h" #include "inftrees.h" ABC_NAMESPACE_IMPL_START #define MAXBITS 15 const char inflate_copyright[] = " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, CODES, LENS, or DISTS. On return, zero is success, -1 is an invalid code, and +1 means that ENOUGH isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work) { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ unsigned root; /* number of index bits for root table */ unsigned curr; /* number of index bits for current table */ unsigned drop; /* code bits to drop for sub-table */ int left; /* number of prefix codes available */ unsigned used; /* code entries in table used */ unsigned huff; /* Huffman code */ unsigned incr; /* for incrementing code, index */ unsigned fill; /* index for replicating entries */ unsigned low; /* low bits for current root entry */ unsigned mask; /* mask for low root bits */ code here; /* table entry for duplication */ code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ int end; /* use base and extra for symbol > end */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..MAXBITS. The caller must assure this. 1..MAXBITS is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ for (len = 0; len <= MAXBITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; here.val = (unsigned short)0; *(*table)++ = here; /* make a table to force an error */ *(*table)++ = here; *bits = 1; return 0; /* no symbols, but wait for decoding to report error */ } for (min = 1; min < max; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= MAXBITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ } if (left > 0 && (type == CODES || max != 1)) return -1; /* incomplete set */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked for LENS and DIST tables against the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in the initial root table size constants. See the comments in inftrees.h for more information. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case CODES: base = extra = work; /* dummy value--not used */ end = 19; break; case LENS: base = lbase; base -= 257; extra = lext; extra -= 257; end = 256; break; default: /* DISTS */ base = dbase; extra = dext; end = -1; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ /* check available table space */ if ((type == LENS && used >= ENOUGH_LENS) || (type == DISTS && used >= ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); if ((int)(work[sym]) < end) { here.op = (unsigned char)0; here.val = work[sym]; } else if ((int)(work[sym]) > end) { here.op = (unsigned char)(extra[work[sym]]); here.val = base[work[sym]]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ here.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = here; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if ((type == LENS && used >= ENOUGH_LENS) || (type == DISTS && used >= ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (unsigned char)curr; (*table)[low].bits = (unsigned char)root; (*table)[low].val = (unsigned short)(next - *table); } } /* Fill in rest of table for incomplete codes. This loop is similar to the loop above in incrementing huff for table indices. It is assumed that len is equal to curr + drop, so there is no loop needed to increment through high index bits. When the current sub-table is filled, the loop drops back to the root table to fill in any remaining entries there. */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)(len - drop); here.val = (unsigned short)0; while (huff != 0) { /* when done with sub-table, drop back to root table */ if (drop != 0 && (huff & mask) != low) { drop = 0; len = root; next = *table; here.bits = (unsigned char)len; } /* put invalid code marker in table */ next[huff >> drop] = here; /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; } /* set return parameters */ *table += used; *bits = root; return 0; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/inftrees.h000066400000000000000000000056461300674244400237320ustar00rootroot00000000000000/* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ ABC_NAMESPACE_HEADER_START /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. */ typedef struct { unsigned char op; /* operation, extra bits, table bits */ unsigned char bits; /* bits in this part of the code */ unsigned short val; /* offset in table or code value */ } code; /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 0001eeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ #define ENOUGH_LENS 852 #define ENOUGH_DISTS 592 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) /* Type of code to build for inflate_table() */ typedef enum { CODES, LENS, DISTS } codetype; int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work)); ABC_NAMESPACE_HEADER_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/license000066400000000000000000000030321300674244400232720ustar00rootroot00000000000000Copyright notice: (C) 1995-2010 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/link.txt000066400000000000000000000000261300674244400234230ustar00rootroot00000000000000http://www.zlib.net/ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/module.make000066400000000000000000000006231300674244400240540ustar00rootroot00000000000000SRC += src/misc/zlib/adler32.c \ src/misc/zlib/compress_.c \ src/misc/zlib/crc32.c \ src/misc/zlib/deflate.c \ src/misc/zlib/gzclose.c \ src/misc/zlib/gzlib.c \ src/misc/zlib/gzread.c \ src/misc/zlib/gzwrite.c \ src/misc/zlib/infback.c \ src/misc/zlib/inffast.c \ src/misc/zlib/inflate.c \ src/misc/zlib/inftrees.c \ src/misc/zlib/trees.c \ src/misc/zlib/uncompr.c \ src/misc/zlib/zutil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/trees.c000066400000000000000000001261761300674244400232320ustar00rootroot00000000000000/* trees.c -- output deflated data using Huffman coding * Copyright (C) 1995-2010 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process uses several Huffman trees. The more * common source values are represented by shorter bit sequences. * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * REFERENCES * * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc * * Storer, James A. * Data Compression: Methods and Theory, pp. 49-50. * Computer Science Press, 1988. ISBN 0-7167-8156-5. * * Sedgewick, R. * Algorithms, p290. * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ /* @(#) $Id$ */ /* #define GEN_TREES_H */ #include #include #include #include "misc/util/abc_global.h" #include "deflate.h" #ifdef DEBUG # include #endif ABC_NAMESPACE_IMPL_START /* =========================================================================== * Constants */ #define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 /* end of block literal code */ #define REP_3_6 16 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ #define REPZ_3_10 17 /* repeat a zero length 3-10 times (3 bits of repeat count) */ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; local const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. */ #define Buf_size (8 * 2*sizeof(char)) /* Number of bits used within bi_buf. (bi_buf might be implemented on * more than 16 bits on some systems.) */ /* =========================================================================== * Local data. These are initialized only once. */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) || !defined(STDC) /* non ANSI compilers may not accept trees.h */ local ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see _tr_init * below). */ local ct_data static_dtree[D_CODES]; /* The static distance tree. (Actually a trivial tree since all codes use * 5 bits.) */ uch _dist_code[DIST_CODE_LEN]; /* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ uch _length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; /* First normalized length for each code (0 = MIN_MATCH) */ local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else ABC_NAMESPACE_IMPL_END # include "trees.h" ABC_NAMESPACE_IMPL_START #endif /* GEN_TREES_H */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ }; local static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; local static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Local (static) routines in this file. */ local void tr_static_init OF((void)); local void init_block OF((deflate_state *s)); local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); local void build_tree OF((deflate_state *s, tree_desc *desc)); local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); local void compress_block OF((deflate_state *s, ct_data *ltree, ct_data *dtree)); local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); local void bi_flush OF((deflate_state *s)); local void copy_block OF((deflate_state *s, charf *buf, unsigned len, int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); #endif #ifndef DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. */ #define put_short(s, w) { \ put_byte(s, (uch)((w) & 0xff)); \ put_byte(s, (uch)((ush)(w) >> 8)); \ } /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef DEBUG local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits(deflate_state *s, int value, int length) { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { s->bi_buf |= (ush)value << s->bi_valid; put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_valid += length - Buf_size; } else { s->bi_buf |= (ush)value << s->bi_valid; s->bi_valid += length; } } #else /* !DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ int val = value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ s->bi_valid += len - Buf_size;\ } else {\ s->bi_buf |= (ush)(value) << s->bi_valid;\ s->bi_valid += len;\ }\ } #endif /* DEBUG */ /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ local void tr_static_init() { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ if (static_init_done) return; /* For some embedded targets, global variables are not initialized: */ #ifdef NO_INIT_GLOBAL_POINTERS static_l_desc.static_tree = static_ltree; static_l_desc.extra_bits = extra_lbits; static_d_desc.static_tree = static_dtree; static_d_desc.extra_bits = extra_dbits; static_bl_desc.extra_bits = extra_blbits; #endif /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256+dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; # ifdef GEN_TREES_H gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } /* =========================================================================== * Genererate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef DEBUG ABC_NAMESPACE_IMPL_END # include ABC_NAMESPACE_IMPL_START # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width)-1 ? ",\n" : ", ")) void gen_trees_header() { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, "/* header created automatically with -DGEN_TREES_H */\n\n"); fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); for (i = 0; i < L_CODES+2; i++) { fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); } fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } fprintf(header, "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); } fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); for (i = 0; i < LENGTH_CODES; i++) { fprintf(header, "%1u%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); } fprintf(header, "local const int base_dist[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "%5u%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); } fclose(header); } #endif /* GEN_TREES_H */ /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ void ZLIB_INTERNAL _tr_init(deflate_state *s) { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.stat_desc = &static_l_desc; s->d_desc.dyn_tree = s->dyn_dtree; s->d_desc.stat_desc = &static_d_desc; s->bl_desc.dyn_tree = s->bl_tree; s->bl_desc.stat_desc = &static_bl_desc; s->bi_buf = 0; s->bi_valid = 0; s->last_eob_len = 8; /* enough lookahead for inflate */ #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif /* Initialize the first block of the first file: */ init_block(s); } /* =========================================================================== * Initialize a new block. */ local void init_block(deflate_state *s) { int n; /* iterates over tree elements */ /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; s->last_lit = s->matches = 0; } #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ /* =========================================================================== * Remove the smallest element from the heap and recreate the heap with * one less element. Updates heap and heap_len. */ #define pqremove(s, tree, top) \ {\ top = s->heap[SMALLEST]; \ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ pqdownheap(s, tree, SMALLEST); \ } /* =========================================================================== * Compares to subtrees, using the tree depth as tie breaker when * the subtrees have equal frequency. This minimizes the worst case length. */ #define smaller(tree, n, m, depth) \ (tree[n].Freq < tree[m].Freq || \ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping * when the heap property is re-established (each father smaller than its * two sons). */ local void pqdownheap(deflate_state *s, ct_data *tree, int k) { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s->heap[j], s->depth)) break; /* Exchange v with the smallest son */ s->heap[k] = s->heap[j]; k = j; /* And continue down the tree, setting j to the left son of k */ j <<= 1; } s->heap[k] = v; } /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. * IN assertion: the fields freq and dad are set, heap[heap_max] and * above are the tree nodes sorted by increasing frequency. * OUT assertions: the field len is set to the optimal bit length, the * array bl_count contains the frequencies for each bit length. * The length opt_len is updated; static_len is also updated if stree is * not null. */ local void gen_bitlen(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; const intf *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ int xbits; /* extra bits */ ush f; /* frequency */ int overflow = 0; /* number of elements with bit length too large */ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; s->opt_len += (ulg)f * (bits + xbits); if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); } if (overflow == 0) return; Trace((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { bits = max_length-1; while (s->bl_count[bits] == 0) bits--; s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while (overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for (bits = max_length; bits != 0; bits--) { n = s->bl_count[bits]; while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((long)bits - (long)tree[m].Len) *(long)tree[m].Freq; tree[m].Len = (ush)bits; } n--; } } } /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). * IN assertion: the array bl_count contains the bit length statistics for * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non * zero code length. */ local void gen_codes (ct_data *tree, int max_code, ushf *bl_count) /* the tree to decorate */ /* largest code with non zero frequency */ /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ ush code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ /* The distribution counts are first used to generate the code values * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { next_code[bits] = code = (code + bl_count[bits-1]) << 1; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { s->heap[++(s->heap_len)] = max_code = n; s->depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (s->heap_len < 2) { node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); tree[node].Freq = 1; s->depth[node] = 0; s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(s, tree, n); /* n = node of least frequency */ m = s->heap[SMALLEST]; /* m = node of next least frequency */ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ s->heap[--(s->heap_max)] = m; /* Create a new node father of n and m */ tree[node].Freq = tree[n].Freq + tree[m].Freq; s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? s->depth[n] : s->depth[m]) + 1); tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE if (tree == s->bl_tree) { fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); } #endif /* and insert the new node in the heap */ s->heap[SMALLEST] = node++; pqdownheap(s, tree, SMALLEST); } while (s->heap_len >= 2); s->heap[--(s->heap_max)] = s->heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen(s, (tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data *)tree, max_code, s->bl_count); } /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ local void scan_tree (deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code+1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; } else if (count <= 10) { s->bl_tree[REPZ_3_10].Freq++; } else { s->bl_tree[REPZ_11_138].Freq++; } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ local void send_tree (deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ /* tree[max_code+1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); } else if (count <= 10) { send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); } else { send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ local int build_bl_tree(deflate_state *s) { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); /* opt_len now includes the length of the tree representations, except * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ s->opt_len += 3*(max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, dcodes-1, 5); send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last) { send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ #ifdef DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; #endif copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. * The current inflate code requires 9 bits of lookahead. If the * last two codes for the previous block (real code plus EOB) were coded * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode * the last real code. In this case we send two empty static blocks instead * of one. (There are no problems if the previous block is stored or fixed.) * To simplify the code, we assume the worst case of last real code encoded * on one bit only. */ void ZLIB_INTERNAL _tr_align(deflate_state *s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); /* Of the 10 bits for the empty block, we have already sent * (10 - bi_valid) bits. The lookahead for the last real code (before * the EOB of the previous block) was thus at least one plus the length * of the EOB plus what we have just sent of the empty static block. */ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; #endif bi_flush(s); } s->last_eob_len = 7; } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. */ void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last) { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { /* Check if the file is binary or text */ if (s->strm->data_type == Z_UNKNOWN) s->strm->data_type = detect_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ opt_lenb = (s->opt_len+3+7)>>3; static_lenb = (s->static_len+3+7)>>3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->last_lit)); if (static_lenb <= opt_lenb) opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else if (stored_len+4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ _tr_stored_block(s, buf, stored_len, last); #ifdef FORCE_STATIC } else if (static_lenb >= 0) { /* force static trees */ #else } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+last, 3); compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif } else { send_bits(s, (DYN_TREES<<1)+last, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif } Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. */ init_block(s); if (last) { bi_windup(s); #ifdef DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, s->compressed_len-7*last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ int ZLIB_INTERNAL _tr_tally (deflate_state *s, unsigned dist, unsigned lc) { s->d_buf[s->last_lit] = (ush)dist; s->l_buf[s->last_lit++] = (uch)lc; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } #ifdef TRUNCATE_BLOCK /* Try to guess if it is profitable to stop the current block here */ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { /* Compute an upper bound for the compressed length */ ulg out_length = (ulg)s->last_lit*8L; ulg in_length = (ulg)((long)s->strstart - s->block_start); int dcode; for (dcode = 0; dcode < D_CODES; dcode++) { out_length += (ulg)s->dyn_dtree[dcode].Freq * (5L+extra_dbits[dcode]); } out_length >>= 3; Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", s->last_lit, in_length, out_length, 100L - out_length*100L/in_length)); if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; } #endif return (s->last_lit == s->lit_bufsize-1); /* We avoid equality with lit_bufsize because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */ } /* =========================================================================== * Send the block data compressed using the given Huffman trees */ local void compress_block(deflate_state *s, ct_data *ltree, ct_data *dtree) { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned lx = 0; /* running index in l_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->last_lit != 0) do { dist = s->d_buf[lx]; lc = s->l_buf[lx++]; if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; send_code(s, code+LITERALS+1, ltree); /* send the length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); Assert (code < D_CODES, "bad d_code"); send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { dist -= base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, "pendingBuf overflow"); } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); s->last_eob_len = ltree[END_BLOCK].Len; } /* =========================================================================== * Check if the data type is TEXT or BINARY, using the following algorithm: * - TEXT if the two conditions below are satisfied: * a) There are no non-portable control characters belonging to the * "black list" (0..6, 14..25, 28..31). * b) There is at least one printable character belonging to the * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). * - BINARY otherwise. * - The following partially-portable control characters form a * "gray list" that is ignored in this detection algorithm: * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). * IN assertion: the fields Freq of dyn_ltree are set. */ local int detect_data_type(deflate_state *s) { /* black_mask is the bit mask of black-listed bytes * set bits 0..6, 14..25, and 28..31 * 0xf3ffc07f = binary 11110011111111111100000001111111 */ unsigned long black_mask = 0xf3ffc07fUL; int n; /* Check for non-textual ("black-listed") bytes. */ for (n = 0; n <= 31; n++, black_mask >>= 1) if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) return Z_BINARY; /* Check for textual ("white-listed") bytes. */ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 || s->dyn_ltree[13].Freq != 0) return Z_TEXT; for (n = 32; n < LITERALS; n++) if (s->dyn_ltree[n].Freq != 0) return Z_TEXT; /* There are no "black-listed" or "white-listed" bytes: * this stream either is empty or has tolerated ("gray-listed") bytes only. */ return Z_BINARY; } /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) * IN assertion: 1 <= len <= 15 */ local unsigned bi_reverse(unsigned code, int len) { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } /* =========================================================================== * Flush the bit buffer, keeping at most 7 bits in it. */ local void bi_flush(deflate_state *s) { if (s->bi_valid == 16) { put_short(s, s->bi_buf); s->bi_buf = 0; s->bi_valid = 0; } else if (s->bi_valid >= 8) { put_byte(s, (Byte)s->bi_buf); s->bi_buf >>= 8; s->bi_valid -= 8; } } /* =========================================================================== * Flush the bit buffer and align the output on a byte boundary */ local void bi_windup(deflate_state *s) { if (s->bi_valid > 8) { put_short(s, s->bi_buf); } else if (s->bi_valid > 0) { put_byte(s, (Byte)s->bi_buf); } s->bi_buf = 0; s->bi_valid = 0; #ifdef DEBUG s->bits_sent = (s->bits_sent+7) & ~7; #endif } /* =========================================================================== * Copy a stored block, storing first the length and its * one's complement if requested. */ local void copy_block(deflate_state *s, charf *buf, unsigned len, int header) { bi_windup(s); /* align on byte boundary */ s->last_eob_len = 8; /* enough lookahead for inflate */ if (header) { put_short(s, (ush)len); put_short(s, (ush)~len); #ifdef DEBUG s->bits_sent += 2*16; #endif } #ifdef DEBUG s->bits_sent += (ulg)len<<3; #endif while (len--) { put_byte(s, *buf++); } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/trees.h000066400000000000000000000205161300674244400232260ustar00rootroot00000000000000/* header created automatically with -DGEN_TREES_H */ ABC_NAMESPACE_HEADER_START local const ct_data static_ltree[L_CODES+2] = { {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, {{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, {{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, {{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, {{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, {{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, {{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, {{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, {{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, {{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, {{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, {{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, {{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, {{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, {{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, {{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, {{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, {{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, {{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, {{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, {{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, {{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, {{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, {{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, {{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, {{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, {{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, {{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, {{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, {{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, {{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, {{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, {{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, {{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, {{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, {{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, {{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, {{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, {{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, {{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, {{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, {{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, {{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, {{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, {{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, {{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, {{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, {{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, {{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, {{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, {{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, {{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, {{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, {{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, {{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, {{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, {{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} }; local const ct_data static_dtree[D_CODES] = { {{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, {{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, {{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, {{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, {{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} }; const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 }; local const int base_length[LENGTH_CODES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 }; local const int base_dist[D_CODES] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; ABC_NAMESPACE_HEADER_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/uncompr.c000066400000000000000000000040531300674244400235600ustar00rootroot00000000000000/* uncompr.c -- decompress a memory buffer * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include #include #include #include "misc/util/abc_global.h" #define ZLIB_INTERNAL #include "zlib.h" ABC_NAMESPACE_IMPL_START /* =========================================================================== Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the compressed buffer. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted. */ int ZEXPORT uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { z_stream stream; int err; stream.next_in = (Bytef*)source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; err = inflateInit(&stream); if (err != Z_OK) return err; err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { inflateEnd(&stream); if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) return Z_DATA_ERROR; return err; } *destLen = stream.total_out; err = inflateEnd(&stream); return err; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/zconf.h000066400000000000000000000321651300674244400232260ustar00rootroot00000000000000/* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2010 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ /* all linked symbols */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block # define _tr_tally z__tr_tally # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 # define compress z_compress # define compress2 z_compress2 # define compressBound z_compressBound # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table # define gz_error z_gz_error # define gz_intmax z_gz_intmax # define gz_strwinerror z_gz_strwinerror # define gzbuffer z_gzbuffer # define gzclearerr z_gzclearerr # define gzclose z_gzclose # define gzclose_r z_gzclose_r # define gzclose_w z_gzclose_w # define gzdirect z_gzdirect # define gzdopen z_gzdopen # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush # define gzgetc z_gzgetc # define gzgets z_gzgets # define gzoffset z_gzoffset # define gzoffset64 z_gzoffset64 # define gzopen z_gzopen # define gzopen64 z_gzopen64 # define gzprintf z_gzprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread # define gzrewind z_gzrewind # define gzseek z_gzseek # define gzseek64 z_gzseek64 # define gzsetparams z_gzsetparams # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc # define gzwrite z_gzwrite # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd # define inflateBackInit_ z_inflateBackInit_ # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd # define inflateGetHeader z_inflateGetHeader # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # define uncompress z_uncompress # define zError z_zError # define zcalloc z_zcalloc # define zcfree z_zcfree # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte # define Bytef z_Bytef # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func # define gzFile z_gzFile # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func # define intf z_intf # define out_func z_out_func # define uInt z_uInt # define uIntf z_uIntf # define uLong z_uLong # define uLongf z_uLongf # define voidp z_voidp # define voidpc z_voidpc # define voidpf z_voidpf /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s z_gz_header_s # define internal_state z_internal_state #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif #ifdef STDC # include /* for off_t */ #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even * though the former does not conform to the LFS document), but considering * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ #if -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif #if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) # include /* for SEEK_* and off_t */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t # define z_off_t off_t # endif #endif ABC_NAMESPACE_HEADER_START #ifndef SEEK_SET # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define z_off64_t off64_t #else # define z_off64_t z_off_t #endif #if defined(__OS400__) # define NO_vsnprintf #endif #if defined(__MVS__) # define NO_vsnprintf #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") #pragma map(deflateInit2_,"DEIN2") #pragma map(deflateEnd,"DEEND") #pragma map(deflateBound,"DEBND") #pragma map(inflateInit_,"ININ") #pragma map(inflateInit2_,"ININ2") #pragma map(inflateEnd,"INEND") #pragma map(inflateSync,"INSY") #pragma map(inflateSetDictionary,"INSEDI") #pragma map(compressBound,"CMBND") #pragma map(inflate_table,"INTABL") #pragma map(inflate_fast,"INFA") #pragma map(inflate_copyright,"INCOPY") #endif ABC_NAMESPACE_HEADER_END #endif /* ZCONF_H */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/zlib.h000066400000000000000000002335061300674244400230510ustar00rootroot00000000000000/* zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.5, April 19th, 2010 Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). */ #ifndef ZLIB_H #define ZLIB_H #include #include #include #ifndef WIN32 #include #endif #include "misc/util/abc_global.h" #include "zconf.h" ABC_NAMESPACE_HEADER_START #define ZLIB_VERSION "1.2.5" #define ZLIB_VERNUM 0x1250 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 #define ZLIB_VER_REVISION 5 #define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough, or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The compressed data format used by default by the in-memory functions is the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped around a deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. This library can optionally read and write gzip streams in memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total nb of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total nb of bytes output so far */ char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* gzip header information passed to and from zlib routines. See RFC 1952 for more details on the meanings of these fields. */ typedef struct gz_header_s { int text; /* true if compressed data believed to be text */ uLong time; /* modification time */ int xflags; /* extra flags (not used when writing a gzip file) */ int os; /* operating system */ Bytef *extra; /* pointer to extra field or Z_NULL if none */ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ uInt extra_max; /* space at extra (only when reading header) */ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ uInt name_max; /* space at name (only when reading header) */ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ uInt comm_max; /* space at comment (only when reading header) */ int hcrc; /* true if there was or will be a header crc */ int done; /* true when done reading gzip header (not used when writing a gzip file) */ } gz_header; typedef gz_header FAR *gz_headerp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use in the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative values * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field (though see inflate()) */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff). If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the output buffer, but the output is not aligned to a byte boundary. All of the input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output in order for the decompressor to finish the block before the empty fixed code block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to seven bits of the current block are held to be written as the next byte after the next deflate block is completed. In this case, the decompressor may not be provided enough bits at this point in order to complete decompression of the data provided so far to the compressor. It may need to wait for the next block to be emitted. This is for advanced applications that need to control the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out is greater than six to avoid repeated flush markers due to avail_out == 0 on return. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space; if deflate returns with Z_OK, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least the value returned by deflateBound (see below). If deflate does not return Z_STREAM_END, then it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). deflate() may update strm->data_type if it can make a good guess about the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and deflate() can be called again with more input and more output space to continue compressing. */ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. If next_in is not Z_NULL and avail_in is large enough (the exact value depends on the compression method), inflateInit determines the compression method from the zlib header and allocates all data structures accordingly; otherwise the allocation will be deferred to the first call of inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in is updated and processing will resume at this point for the next call of inflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause inflate() to return immediately after the header and before the first block. When doing a raw inflate, inflate() will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. Also to assist in this, on return inflate() will set strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to strm->next_out. The number of unused bits may in general be greater than seven, except when bit 7 of data_type is set, in which case the number of unused bits will be less than eight. data_type is set as noted here every time inflate() returns for all flush options, and so can be used to determine the amount of currently consumed input in bits. The Z_TREES option behaves as Z_BLOCK does, but it also returns when the end of each deflate block header is reached, before any actual data in that block is decoded. This allows the caller to determine the length of the deflate block header for later use in random access within a deflate block. 256 is added to the value of strm->data_type when inflate() returns immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all the uncompressed data. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The next operation on this stream must be inflateEnd to deallocate the decompression state. The use of Z_FINISH is never required, but can be used to inform inflate that a faster approach may be used for the single inflate() call. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the only effect of the flush parameter in this implementation is on the return value of inflate(), as noted below, or when it returns early because Z_BLOCK or Z_TREES is used. If a preset dictionary is needed after this call (see inflateSetDictionary below), inflate sets strm->adler to the adler32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the adler32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip header is not retained, so applications that need that information should instead use raw inflate, see inflateInit2() below, or inflateBack() and perform their own processing of the gzip header and trailer. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value), Z_STREAM_ERROR if the stream structure was inconsistent (for example next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress is possible or if there was not enough room in the output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial recovery of the data is desired. */ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent. In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); This is another version of deflateInit with more compression options. The fields next_in, zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data with no zlib header or trailer, and will not compute an adler32 check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to 255 (unknown). If a gzip stream is being written, strm->adler is a crc32 instead of an adler32. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no string match), or Z_RLE to limit match distances to one (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. This function must be called immediately after deflateInit, deflateInit2 or deflateReset, before any call of deflate. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size provided in deflateInit or deflateInit2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the adler32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The adler32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the adler32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream or if the compression method is bsort). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate all the internal compression state. The stream will keep the same compression level and any other attributes that may have been set by deflateInit2. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy)); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2. This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression level is changed, the input available so far is compressed with the old level (and may be flushed); the new level will take effect only at the next call of deflate(). Before the call of deflateParams, the stream state must be set as for a call of deflate(), since the currently available input may have to be compressed and flushed. In particular, strm->avail_out must be non-zero. deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if strm->avail_out was zero. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, uLong sourceLen)); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). */ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value)); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first deflate() call after a deflateInit2() or deflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output. deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gz_headerp head)); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information in the provided gz_header structure are written to the gzip header (xflag is ignored -- the extra flags are set according to the compression level). The caller must assure that, if not Z_NULL, name and comment are terminated with a zero byte, and that if extra is not Z_NULL, that extra_len bytes are available there. If hcrc is true, a gzip header crc is included. Note that the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, the time set to zero, and os set to 255, with no extra, name, or comment fields. The gzip header is returned to the default state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing, or it must be equal to 15 if deflateInit2() was not used. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. windowBits can also be zero to request that inflate use the window size in the zlib header of the compressed stream. windowBits can also be -8..-15 for raw inflate. In this case, -windowBits determines the window size. inflate() will then process raw deflate data, not looking for a zlib or gzip header, not generating a check value, and not looking for any check values for comparison at the end of the stream. This is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is recommended that a check value such as an adler32 or a crc32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a crc32 instead of an adler32. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the adler32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called immediately after inflateInit2() or inflateReset() and before any call of inflate() to set the dictionary. The application must insure that the dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect adler32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* Skips invalid compressed data until a full flush point (see above the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, allowing restarting inflate at those points when randomly accessing the stream. inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate all the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, int windowBits)); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted the same as it is for inflateInit2. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, int bits, int value)); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and should be used before the first inflate() call after inflateInit2() or inflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input. If bits is negative, then the input stream bit buffer is emptied. Then inflatePrime() can be called again to put bits in the buffer. This is used to clear out bits leftover after feeding inflate a block description prior to feeding inflate codes. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits. If the upper value is -1 and the lower value is zero, then inflate() is currently decoding information outside of a block. If the upper value is -1 and the lower value is non-zero, then inflate is in the middle of a stored block, with the lower value equaling the number of bytes from the input remaining to copy. If the upper value is not -1, then it is the number of bits back from the current bit position in the input of the code (literal or length/distance pair) currently being processed. In that case the lower value is the number of bytes already emitted for that code. A code is being processed if inflate is waiting for more input to complete decoding of the code, or if it has completed decoding but is waiting for more output space to write the literal or match data. inflateMark() is used to mark locations in the input data for random access, which may be at bit positions, and to note those cases where the output of a code may span boundaries of random access blocks. The current location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. inflateMark returns the value noted above or -1 << 16 if the provided source stream state was inconsistent. */ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, gz_headerp head)); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header is completed, at which time head->done is set to one. If a zlib stream is being decoded, then head->done is set to -1 to indicate that there will be no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be used to force inflate() to return immediately after header processing is complete and before any actual data is decompressed. The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC was valid if done is set to one.) If extra is not Z_NULL, then extra_max contains the maximum number of bytes to write to extra. Once done is true, extra_len contains the actual extra field length, and extra contains the extra field, or that field truncated if extra_max is less than extra_len. If name is not Z_NULL, then up to name_max characters are written there, terminated with a zero unless the length is greater than name_max. If comment is not Z_NULL, then up to comm_max characters are written there, terminated with a zero unless the length is greater than comm_max. When any of extra, name, or comment are not Z_NULL and the respective field is not present in the header, then that field is set to Z_NULL to signal its absence. This allows the use of deflateSetHeader() with the returned structure to duplicate the header. However if those fields are set to allocated memory, then the application will need to save those pointers elsewhere so that they can be eventually freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present. inflateReset() will reset the process to discard the header information. The application would need to call inflateGetHeader() again to retrieve the header from the next gzip stream. inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, unsigned char FAR *window)); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two logarithm of the window size, in the range 8..15. window is a caller supplied buffer of that size. Except for special applications where it is assured that deflate was used with small window sizes, windowBits must be 15 and a 32K byte window must be supplied to be able to decompress general deflate streams. See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the paramaters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is more efficient than inflate() for file i/o applications in that it avoids copying between the output and the sliding window by simply making the window itself the output buffer. This function trusts the application to not change the output buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. inflateBack() may then be used multiple times to inflate a complete, raw deflate stream with each call. inflateBackEnd() is then called to free the allocated state. A raw deflate stream is one with no zlib or gzip header or trailer. This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only the raw deflate stream to decompress. This is different from the normal behavior of inflate(), which expects either a zlib or gzip header and trailer around the deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those routines until it reads a complete deflate stream and writes out all of the uncompressed data, or until it encounters an error. The function's parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If there is no input available, in() must return zero--buf is ignored in that case--and inflateBack() will return a buffer error. inflateBack() will call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() should return zero on success, or non-zero on failure. If out() returns non-zero, inflateBack() will return with an error. Neither in() nor out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). For convenience, inflateBack() can be provided input on the first call by setting strm->next_in and strm->avail_in. If that input is exhausted, then in() will be called. Therefore strm->next_in must be initialized before calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in must also be initialized, and then if strm->avail_in is not zero, input will initially be taken from strm->next_in[0 .. strm->avail_in - 1]. The in_desc and out_desc parameters of inflateBack() is passed as the first parameter of in() and out() respectively when they are called. These descriptors can be optionally used to pass any information that the caller- supplied in() and out() functions need to do their job. On return, inflateBack() will set strm->next_in and strm->avail_in to pass back any unused input that was provided by the last in() call. The return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR if in() or out() returned an error, Z_DATA_ERROR if there was a format error in the deflate stream (in which case strm->msg is set to indicate the nature of the error), or Z_STREAM_ERROR if the stream was not properly initialized. In the case of Z_BUF_ERROR, an input or output error can be distinguished using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong 5.4: size of voidpf (pointer) 7.6: size of z_off_t Compiler, assembler, and debug options: 8: DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) One-time table building (smaller code, but not thread-safe if true): 12: BUILDFIXED -- build static block decoding tables when needed 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed 14,15: 0 (reserved) Library content (indicates missing functionality): 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking deflate code when not needed) 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) 18-19: 0 (reserved) Operation variations (changes in library functionality): 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) The sprintf variant used by gzprintf (zero is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned Remainder: 27-31: 0 (reserved) */ /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if you need special options. */ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the uncompressed buffer. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. */ /* gzip file access functions */ /* This library supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio, using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. */ typedef voidp gzFile; /* opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); Opens a gzip (.gz) file for reading or writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of deflateInit2 for more information about the strategy parameter.) Also "a" can be used instead of "w" to request that the gzip stream that will be written be appended to the file. "+" will result in an error, since reading and writing to the same gzip file is not supported. gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the file could not be opened. */ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); /* gzdopen associates a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since gzdopen does not close fd if it fails. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided), or if fd is -1. The file descriptor is not used until the next gz* read, write, seek, or close operation, so gzdopen will not detect if fd is invalid (unless fd is -1). */ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); /* Set the internal buffer size used by this library's functions. The default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or write. Two buffers are allocated, either both of the specified size when writing, or one of the specified size and the other twice that size when reading. A larger buffer size of, for example, 64K or 128K bytes will noticeably increase the speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). gzbuffer() returns 0 on success, or -1 on failure, such as being called too late. */ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level or strategy. See the description of deflateInit2 for the meaning of these parameters. gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not opened for writing. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Reads the given number of uncompressed bytes from the compressed file. If the input file was not in gzip format, gzread copies the given number of bytes into the buffer. After reaching the end of a gzip stream in the input, gzread will continue to read, looking for another gzip stream, or failing that, reading the rest of the input file directly without decompression. The entire input file will be read if gzread is called until it returns less than the requested len. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); /* Writes the given number of uncompressed bytes into the compressed file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of uncompressed bytes actually written, or 0 in case of error. The number of uncompressed bytes written is limited to 8191, or one less than the buffer size given to gzbuffer(). The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if zlib was compiled with the insecure functions sprintf() or vsprintf() because the secure snprintf() or vsnprintf() functions were not available. This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); /* Writes the given null-terminated string to the compressed file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); /* Reads bytes from the compressed file until len-1 characters are read, or a newline character is read and transferred to buf, or an end-of-file condition is encountered. If any characters are read or if len == 1, the string is terminated with a null character. If no characters are read due to an end-of-file or len < 1, then the buffer is left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL for end-of-file or in case of error. If there was an error, the contents at buf are indeterminate. */ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); /* Writes c, converted to an unsigned char, into the compressed file. gzputc returns the value that was written, or -1 in case of error. */ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Reads one byte from the compressed file. gzgetc returns this byte or -1 in case of end of file or error. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); /* Push one character back onto the stream to be read as the first character on the next read. At least one character of push-back is allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); /* Flushes all pending output into the compressed file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such concatented gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence)); Sets the starting position for the next gzread or gzwrite on the given compressed file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* Rewinds the given file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) */ /* ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); Returns the starting position for the next gzread or gzwrite on the given compressed file. This position represents a number of bytes in the uncompressed data stream, and is zero when starting, even if appending or reading a gzip stream from the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); Returns the current offset in the file being read or written. This offset includes the count of bytes that precede the gzip stream, for example when appending or when using gzdopen() for reading. When reading, the offset does not include as yet unused buffered input. This information can be used for a progress indicator. On error, gzoffset() returns -1. */ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); /* Returns true (1) if the end-of-file indicator has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set only if the read tried to go past the end of the input, but came up short. Therefore, just like feof(), gzeof() may return false even if there is no more data to read, in the event that the last read request was for the exact number of bytes remaining in the input file. This will happen if the input file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Returns true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. This state can change from false to true while reading the input file if the end of a gzip stream is reached, but is followed by data that is not another gzip stream. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. If gzdirect() is used immediately after gzopen() or gzdopen() it will cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* Flushes all pending output if necessary, closes the compressed file and deallocates the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a file operation error, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to using these instead of gzclose() is that they avoid linking in zlib compression or decompression code that is not used when only reading or only writing respectively. If gzclose() is used, then both compression and decompression code will be included the application when linking to a static zlib library. */ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); /* Returns the error message for the last error which occurred on the given compressed file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is closed, then the string previously returned by gzerror will no longer be available. gzerror() should be used to distinguish errors from end-of-file for those functions above that do not distinguish those cases in their return values. */ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); /* Clears the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. If buf is Z_NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. If buf is Z_NULL, this function returns the required initial value for the for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, const char *version, int stream_size)); ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); #define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) #define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, sizeof(z_stream)) /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if * both are true, the application gets the *64 functions, and the regular * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); #endif #if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 # define gzopen gzopen64 # define gzseek gzseek64 # define gztell gztell64 # define gzoffset gzoffset64 # define adler32_combine adler32_combine64 # define crc32_combine crc32_combine64 # ifdef _LARGEFILE64_SOURCE ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); # endif #else ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); #endif /* hack for buggy compilers */ #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; #endif /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); ABC_NAMESPACE_HEADER_END #endif /* ZLIB_H */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/zutil.c000066400000000000000000000162341300674244400232500ustar00rootroot00000000000000/* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include #include #include #include "misc/util/abc_global.h" #include "zutil.h" ABC_NAMESPACE_IMPL_START #ifndef NO_DUMMY_DECL struct internal_state {int dummy;}; /* for buggy compilers */ #endif const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ "file error", /* Z_ERRNO (-1) */ "stream error", /* Z_STREAM_ERROR (-2) */ "data error", /* Z_DATA_ERROR (-3) */ "insufficient memory", /* Z_MEM_ERROR (-4) */ "buffer error", /* Z_BUF_ERROR (-5) */ "incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; const char * ZEXPORT zlibVersion() { return ZLIB_VERSION; } uLong ZEXPORT zlibCompileFlags() { uLong flags; flags = 0; switch ((int)(sizeof(uInt))) { case 2: break; case 4: flags += 1; break; case 8: flags += 2; break; default: flags += 3; } switch ((int)(sizeof(uLong))) { case 2: break; case 4: flags += 1 << 2; break; case 8: flags += 2 << 2; break; default: flags += 3 << 2; } switch ((int)(sizeof(voidpf))) { case 2: break; case 4: flags += 1 << 4; break; case 8: flags += 2 << 4; break; default: flags += 3 << 4; } switch ((int)(sizeof(z_off_t))) { case 2: break; case 4: flags += 1 << 6; break; case 8: flags += 2 << 6; break; default: flags += 3 << 6; } #ifdef DEBUG flags += 1 << 8; #endif #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif #ifdef ZLIB_WINAPI flags += 1 << 10; #endif #ifdef BUILDFIXED flags += 1 << 12; #endif #ifdef DYNAMIC_CRC_TABLE flags += 1 << 13; #endif #ifdef NO_GZCOMPRESS flags += 1L << 16; #endif #ifdef NO_GZIP flags += 1L << 17; #endif #ifdef PKZIP_BUG_WORKAROUND flags += 1L << 20; #endif #ifdef FASTEST flags += 1L << 21; #endif #ifdef STDC # ifdef NO_vsnprintf flags += 1L << 25; # ifdef HAS_vsprintf_void flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void flags += 1L << 26; # endif # endif #else flags += 1L << 24; # ifdef NO_snprintf flags += 1L << 25; # ifdef HAS_sprintf_void flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void flags += 1L << 26; # endif # endif #endif return flags; } #ifdef DEBUG # ifndef verbose # define verbose 0 # endif int ZLIB_INTERNAL z_verbose = verbose; void ZLIB_INTERNAL z_error (m) char *m; { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char * ZEXPORT zError(int err) { return ERR_MSG(err); } #if defined(_WIN32_WCE) /* The Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ int errno = 0; #endif #ifndef HAVE_MEMCPY void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) { uInt j; for (j = 0; j < len; j++) { if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; } return 0; } void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } #endif #ifdef SYS16BIT #ifdef __TURBOC__ /* Turbo C in 16-bit mode */ # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with an offset of 8, so we * must fix the pointer. Warning: the pointer must be put back to its * original form in order to free it, use zcfree(). */ #define MAX_PTR 10 /* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { voidpf org_ptr; voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; /* This table is used to remember the original form of pointers * to large buffers (64K). Such pointers are normalized with a zero offset. * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { voidpf buf = opaque; /* just to make some compilers happy */ ulg bsize = (ulg)items*size; /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ if (bsize < 65520L) { buf = farmalloc(bsize); if (*(ush*)&buf != 0) return buf; } else { buf = farmalloc(bsize + 16L); } if (buf == NULL || next_ptr >= MAX_PTR) return NULL; table[next_ptr].org_ptr = buf; /* Normalize the pointer to seg:0 */ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { int n; if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; } /* Find the original pointer */ for (n = 0; n < next_ptr; n++) { if (ptr != table[n].new_ptr) continue; farfree(table[n].org_ptr); while (++n < next_ptr) { table[n-1] = table[n]; } next_ptr--; return; } ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } #endif /* __TURBOC__ */ #ifdef M_I86 /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) { if (opaque) opaque = 0; /* to make compiler happy */ return _halloc((long)items, size); } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { if (opaque) opaque = 0; /* to make compiler happy */ _hfree(ptr); } #endif /* M_I86 */ #endif /* SYS16BIT */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC extern voidp malloc OF((uInt size)); extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { if (opaque) items += size - size; /* make compiler happy */ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { free(ptr); if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/misc/zlib/zutil.h000066400000000000000000000164561300674244400232630ustar00rootroot00000000000000/* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2010 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef ZUTIL_H #define ZUTIL_H #if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include "zlib.h" #ifdef STDC # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif # include # include #endif ABC_NAMESPACE_HEADER_START #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ typedef unsigned char uch; typedef uch FAR uchf; typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ return (strm->msg = (char*)ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 # if defined(__TURBOC__) || defined(__BORLANDC__) # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) /* Allow compilation with ANSI keywords only enabled */ void _Cdecl farfree( void *block ); void *_Cdecl farmalloc( unsigned long nbytes ); # else ABC_NAMESPACE_HEADER_END # include ABC_NAMESPACE_HEADER_START # endif # else /* MSC or DJGPP */ ABC_NAMESPACE_HEADER_END # include ABC_NAMESPACE_HEADER_START # endif #endif #ifdef AMIGA # define OS_CODE 0x01 #endif #if defined(VAXC) || defined(VMS) # define OS_CODE 0x02 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #if defined(ATARI) || defined(atarist) # define OS_CODE 0x05 #endif #ifdef OS2 # define OS_CODE 0x06 # ifdef M_I86 ABC_NAMESPACE_HEADER_END # include ABC_NAMESPACE_HEADER_START # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os ABC_NAMESPACE_HEADER_END # include /* for fdopen */ ABC_NAMESPACE_HEADER_START # else # ifndef fdopen # define fdopen(fd,mode) NULL /* No fdopen() */ # endif # endif #endif #ifdef TOPS20 # define OS_CODE 0x0a #endif #ifdef WIN32 # ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ # define OS_CODE 0x0b # endif #endif #ifdef __50SERIES /* Prime/PRIMOS */ # define OS_CODE 0x0f #endif #if defined(_BEOS_) || defined(RISCOS) # define fdopen(fd,mode) NULL /* No fdopen() */ #endif #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX # if defined(_WIN32_WCE) # define fdopen(fd,mode) NULL /* No fdopen() */ # ifndef _PTRDIFF_T_DEFINED typedef int ptrdiff_t; # define _PTRDIFF_T_DEFINED # endif # else # define fdopen(fd,type) _fdopen(fd,type) # endif #endif #if defined(__BORLANDC__) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); #endif /* common defaults */ #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ #if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(__CYGWIN__) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #ifndef HAVE_VSNPRINTF # ifdef MSDOS /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), but for now we just assume it doesn't. */ # define NO_vsnprintf # endif # ifdef __TURBOC__ # define NO_vsnprintf # endif # ifdef WIN32 /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ # if !defined(vsnprintf) && !defined(NO_vsnprintf) # if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) # define vsnprintf _vsnprintf # endif # endif # endif # ifdef __SASC # define NO_vsnprintf # endif #endif #ifdef VMS # define NO_vsnprintf #endif #if defined(pyr) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) # define HAVE_MEMCPY #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp # define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); #endif /* Diagnostic functions */ #ifdef DEBUG ABC_NAMESPACE_HEADER_END # include ABC_NAMESPACE_HEADER_START extern int ZLIB_INTERNAL z_verbose; extern void ZLIB_INTERNAL z_error OF((char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, unsigned size)); void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} ABC_NAMESPACE_HEADER_END #endif /* ZUTIL_H */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/000077500000000000000000000000001300674244400206365ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/000077500000000000000000000000001300674244400214135ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/cgt.h000066400000000000000000000064371300674244400223530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cgt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Clock gating package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cgt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__cgt__cgt_h #define ABC__aig__cgt__cgt_h /* The algorithm implemented in this package is based on the paper: A. Hurst. "Automatic synthesis of clock gating logic with controlled netlist perturbation", DAC 2008. */ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Cgt_Par_t_ Cgt_Par_t; struct Cgt_Par_t_ { int nLevelMax; // the max number of levels to look for clock-gates int nCandMax; // the max number of candidates at each node int nOdcMax; // the max number of ODC levels to consider int nConfMax; // the max number of conflicts at a node int nVarsMin; // the min number of variables to recycle the SAT solver int nFlopsMin; // the min number of flops needed to recycle the SAT solver int fAreaOnly; // derive clock gating to minimize area int fVerbose; // verbosity flag int fVeryVerbose; // verbosity flag }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cgtCore.c ==========================================================*/ extern void Cgt_SetDefaultParams( Cgt_Par_t * p ); extern Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful ); extern Vec_Vec_t * Cgt_ClockGatingInt( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful ); extern Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/cgtAig.c000066400000000000000000000512001300674244400227530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cgtAig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Clock gating package.] Synopsis [Creates AIG to compute clock-gating.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cgtAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cgtInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes transitive fanout cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsNode(pObj) ) { Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin0(pObj), nLevelMax, vCands ); Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin1(pObj), nLevelMax, vCands ); } if ( Aig_ObjLevel(pObj) <= nLevelMax && (vUseful == NULL || Vec_IntEntry(vUseful, Aig_ObjId(pObj))) ) Vec_PtrPush( vCands, pObj ); } /**Function************************************************************* Synopsis [Computes transitive fanout cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) { Vec_PtrClear( vCands ); if ( !Aig_ObjIsNode(pObj) ) return; Aig_ManIncrementTravId( pAig ); Cgt_ManDetectCandidates_rec( pAig, vUseful, pObj, nLevelMax, vCands ); } /**Function************************************************************* Synopsis [Computes transitive fanout cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManDetectFanout_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout ) { Aig_Obj_t * pFanout; int f, iFanout = -1; if ( Aig_ObjIsCo(pObj) || Aig_ObjLevel(pObj) > nOdcMax ) return; if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); Vec_PtrPush( vFanout, pObj ); Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) Cgt_ManDetectFanout_rec( pAig, pFanout, nOdcMax, vFanout ); } /**Function************************************************************* Synopsis [Computes transitive fanout cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout ) { Aig_Obj_t * pFanout; int i, k, f, iFanout = -1; // collect visited nodes Vec_PtrClear( vFanout ); Aig_ManIncrementTravId( pAig ); Cgt_ManDetectFanout_rec( pAig, pObj, nOdcMax, vFanout ); // remove those nodes whose fanout is included k = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) { // go through the fanouts of this node Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) ) break; if ( f == Aig_ObjRefs(pObj) ) // all fanouts are included continue; Vec_PtrWriteEntry( vFanout, k++, pObj ); } Vec_PtrShrink( vFanout, k ); Vec_PtrSort( vFanout, (int (*)(void))Aig_ObjCompareIdIncrease ); assert( Vec_PtrSize(vFanout) > 0 ); } /**Function************************************************************* Synopsis [Computes visited nodes in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited ) { if ( Aig_ObjIsCi(pObj) ) return; if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); assert( Aig_ObjIsNode(pObj) ); Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited ); Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited ); Vec_PtrPush( vVisited, pObj ); } /**Function************************************************************* Synopsis [Computes visited nodes in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited ) { Aig_Obj_t * pObj; int i; Vec_PtrClear( vVisited ); Aig_ManIncrementTravId( pAig ); Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) Cgt_ManCollectVisited_rec( pAig, pObj, vVisited ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t * Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) { return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj)); } static inline Aig_Obj_t * Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) { return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj)); } /**Function************************************************************* Synopsis [Derives miter for clock-gating.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Cgt_ManConstructCareCondition( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo, Vec_Ptr_t * vCopy0, Vec_Ptr_t * vCopy1 ) { Aig_Obj_t * pMiter, * pObj, * pTemp; int i; assert( Aig_ObjIsCi(pObjLo) ); // detect nodes and their cone Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout ); Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited ); // add new variables if the observability condition depends on PI variables Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i ) { assert( Aig_ObjIsNode(pObj) ); if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL ) { pTemp = Aig_ObjCreateCi( pNew ); Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp ); Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp ); } if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL ) { pTemp = Aig_ObjCreateCi( pNew ); Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp ); Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp ); } } // construct AIGs for the nodes Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i ) { pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) ); Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp ); pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) ); Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp ); } // construct the care miter pMiter = Aig_ManConst0( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanout, pObj, i ) { pTemp = Aig_Exor( pNew, (Aig_Obj_t *)Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), (Aig_Obj_t *)Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) ); pMiter = Aig_Or( pNew, pMiter, pTemp ); } return pMiter; } /**Function************************************************************* Synopsis [Derives AIG for clock-gating.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter; Vec_Ptr_t * vCopy0, * vCopy1; int i; assert( Aig_ManRegNum(p->pAig) ); pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) ); pNew->pName = Abc_UtilStrsav( "CG_miter" ); // build the first frame Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p->pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); Aig_ManForEachNode( p->pAig, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // Saig_ManForEachPo( p->pAig, pObj, i ) // pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); if ( p->pPars->nOdcMax > 0 ) { // create storage for observability conditions vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); // initialize register outputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); } // compute observability condition for each latch output Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { // set the constants Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) ); Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) ); // compute condition pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 ); // restore the values Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); // compute the miter pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); pMiter = Aig_And( pNew, pMiter, pCare ); pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter ); } Vec_PtrFree( vCopy0 ); Vec_PtrFree( vCopy1 ); } else { // construct clock-gating miters for each register input Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter ); } } Aig_ManCleanup( pNew ); Aig_ManSetCioIds( pNew ); return pNew; } /**Function************************************************************* Synopsis [Adds relevant constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew ) { Aig_Obj_t * pObj0, * pObj1; if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) ) return (Aig_Obj_t *)pObj->pData; Aig_ObjSetTravIdCurrent( pCare, pObj ); if ( Aig_ObjIsCi(pObj) ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew ); if ( pObj0 == NULL ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew ); if ( pObj1 == NULL ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) ); pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, pObj0, pObj1 )); } /**Function************************************************************* Synopsis [Builds constraints belonging to the given partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves ) { Vec_Int_t * vOuts; Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig; int i, k, iOut; // go through the PIs of the partition // label the corresponding PIs of the care set Aig_ManIncrementTravId( pCare ); Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i ) { pPi = Aig_ManCi( pCare, Aig_ObjCioId(pLeaf) ); Aig_ObjSetTravIdCurrent( pCare, pPi ); pPi->pData = pLeaf->pData; } // construct the constraints Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i ) { vOuts = Vec_VecEntryInt( vSuppsInv, Aig_ObjCioId(pLeaf) ); Vec_IntForEachEntry( vOuts, iOut, k ) { pPo = Aig_ManCo( pCare, iOut ); if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) ) continue; Aig_ObjSetTravIdCurrent( pCare, pPo ); if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) ) continue; pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew ); if ( pObjAig == NULL ) continue; pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); Aig_ObjCreateCo( pNew, pObjAig ); } } } /**Function************************************************************* Synopsis [Duplicates the AIG recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return (Aig_Obj_t *)pObj->pData; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsCi(pObj) ) { pObj->pData = Aig_ObjCreateCi( pNew ); Vec_PtrPush( vLeaves, pObj ); return (Aig_Obj_t *)pObj->pData; } Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves ); Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj), vLeaves ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); } /**Function************************************************************* Synopsis [Duplicates register outputs starting from the given one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pFrame, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ) { Vec_Ptr_t * vRoots, * vLeaves, * vPos; Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( Aig_ManRegNum(pFrame) == 0 ); vRoots = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); vPos = Vec_PtrAlloc( 100 ); pNew = Aig_ManStart( nVarsMin ); pNew->pName = Abc_UtilStrsav( "partition" ); Aig_ManIncrementTravId( pFrame ); Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew); Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) ); for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManCoNum(pFrame); i++ ) { pObj = Aig_ManCo( pFrame, i ); Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); Vec_PtrPush( vPos, pObj ); } for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManCoNum(pFrame); i++ ) { pObj = Aig_ManCo( pFrame, i ); Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); Vec_PtrPush( vPos, pObj ); } assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin ); // create constaints if ( pCare ) Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves ); // create POs Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i ) pObj->pData = (Aig_Obj_t *)Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vRoots, i) ); if ( pnOutputs != NULL ) *pnOutputs = Vec_PtrSize( vPos ); Vec_PtrFree( vRoots ); Vec_PtrFree( vLeaves ); Vec_PtrFree( vPos ); return pNew; } /**Function************************************************************* Synopsis [Implements one clock-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates ) { Aig_Obj_t * pGate, * pTotal; int i; assert( Vec_PtrSize(vGates) > 0 ); pTotal = Aig_ManConst0(pNew); Vec_PtrForEachEntry( Aig_Obj_t *, vGates, pGate, i ) { if ( Aig_Regular(pGate)->pNext ) pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) ); else pGate = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); pTotal = Aig_Or( pNew, pTotal, pGate ); } return pTotal; } /**Function************************************************************* Synopsis [Derives AIG after clock-gating.] Description [The array contains, for each flop, its gate if present.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew; Vec_Ptr_t * vOne; int i, k; Aig_ManCleanNext( pAig ); // label nodes Vec_VecForEachEntry( Aig_Obj_t *, vGates, pObj, i, k ) { if ( Aig_IsComplement(pObj) ) Aig_Regular(pObj)->fMarkB = 1; else Aig_Regular(pObj)->fMarkA = 1; } // construct AIG assert( Aig_ManRegNum(pAig) ); pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pNew->pName = Abc_UtilStrsav( pAig->pName ); pNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); if ( fReduce ) { Aig_ManForEachNode( pAig, pObj, i ) { assert( !(pObj->fMarkA && pObj->fMarkB) ); pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); if ( pObj->fMarkA ) { pObj->pNext = (Aig_Obj_t *)pObj->pData; pObj->pData = Aig_ManConst0(pNew); } else if ( pObj->fMarkB ) { pObj->pNext = (Aig_Obj_t *)pObj->pData; pObj->pData = Aig_ManConst1(pNew); } } } else { Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } if ( pnUsedNodes != NULL ) *pnUsedNodes = Aig_ManNodeNum(pNew); Saig_ManForEachPo( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { vOne = Vec_VecEntry( vGates, i ); if ( Vec_PtrSize(vOne) == 0 ) pObjNew = Aig_ObjChild0Copy(pObjLi); else { // pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); pGateNew = Cgt_ManBuildClockGate( pNew, vOne ); pObjNew = Aig_Mux( pNew, pGateNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); } pObjLi->pData = Aig_ObjCreateCo( pNew, pObjNew ); } Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) ); // unlabel nodes Aig_ManCleanMarkAB( pAig ); Aig_ManCleanNext( pAig ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/cgtCore.c000066400000000000000000000255561300674244400231620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cgtCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Clock gating package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cgtCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cgtInt.h" #include "misc/bar/bar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_SetDefaultParams( Cgt_Par_t * p ) { memset( p, 0, sizeof(Cgt_Par_t) ); p->nLevelMax = 25; // the max number of levels to look for clock-gates p->nCandMax = 1000; // the max number of candidates at each node p->nOdcMax = 0; // the max number of ODC levels to consider p->nConfMax = 10; // the max number of conflicts at a node p->nVarsMin = 1000; // the min number of vars to recycle the SAT solver p->nFlopsMin = 10; // the min number of flops to recycle the SAT solver p->fAreaOnly = 0; // derive clock-gating to minimize area p->fVerbose = 0; // verbosity flag } /**Function************************************************************* Synopsis [Returns 1 if simulation does not filter out this candidate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart ) { unsigned * pInfoCand, * pInfoMiter; int w, nWords = Abc_BitWordNum( p->nPatts ); pInfoCand = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) ); pInfoMiter = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) ); // C => !M -- true is the same as C & M -- false if ( !Aig_IsComplement(pCandPart) ) { for ( w = 0; w < nWords; w++ ) if ( pInfoCand[w] & pInfoMiter[w] ) return 0; } else { for ( w = 0; w < nWords; w++ ) if ( ~pInfoCand[w] & pInfoMiter[w] ) return 0; } return 1; } /**Function************************************************************* Synopsis [Saves one simulation pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_SimulationRecord( Cgt_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p->pPart, pObj, i ) if ( sat_solver_var_value( p->pSat, p->pCnf->pVarNums[i] ) ) Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPatts, i), p->nPatts ); p->nPatts++; if ( p->nPatts == 32 * p->nPattWords ) { Vec_PtrReallocSimInfo( p->vPatts ); Vec_PtrCleanSimInfo( p->vPatts, p->nPattWords, 2 * p->nPattWords ); p->nPattWords *= 2; } } /**Function************************************************************* Synopsis [Performs clock-gating for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart, int nOutputs ) { Vec_Ptr_t * vNodes = p->vFanout; Aig_Obj_t * pMiter, * pCand, * pMiterFrame, * pCandFrame, * pMiterPart, * pCandPart; int i, k, RetValue, nCalls; assert( Vec_VecSize(p->vGatesAll) == Aig_ManCoNum(p->pFrame) ); // go through all the registers inputs of this range for ( i = iStart; i < iStart + nOutputs; i++ ) { nCalls = p->nCalls; pMiter = Saig_ManLi( p->pAig, i ); Cgt_ManDetectCandidates( p->pAig, p->vUseful, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes ); // go through the candidates of this PO Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pCand, k ) { // get the corresponding nodes from the frames pCandFrame = (Aig_Obj_t *)pCand->pData; pMiterFrame = (Aig_Obj_t *)pMiter->pData; // get the corresponding nodes from the part pCandPart = (Aig_Obj_t *)pCandFrame->pData; pMiterPart = (Aig_Obj_t *)pMiterFrame->pData; // try direct polarity if ( Cgt_SimulationFilter( p, pCandPart, pMiterPart ) ) { RetValue = Cgt_CheckImplication( p, pCandPart, pMiterPart ); if ( RetValue == 1 ) { Vec_VecPush( p->vGatesAll, i, pCand ); continue; } if ( RetValue == 0 ) Cgt_SimulationRecord( p ); } else p->nCallsFiltered++; // try reverse polarity if ( Cgt_SimulationFilter( p, Aig_Not(pCandPart), pMiterPart ) ) { RetValue = Cgt_CheckImplication( p, Aig_Not(pCandPart), pMiterPart ); if ( RetValue == 1 ) { Vec_VecPush( p->vGatesAll, i, Aig_Not(pCand) ); continue; } if ( RetValue == 0 ) Cgt_SimulationRecord( p ); } else p->nCallsFiltered++; } if ( p->pPars->fVerbose ) { // printf( "Flop %3d : Cand = %4d. Gate = %4d. SAT calls = %3d.\n", // i, Vec_PtrSize(vNodes), Vec_PtrSize(Vec_VecEntry(p->vGatesAll, i)), p->nCalls-nCalls ); } } } /**Function************************************************************* Synopsis [Performs clock-gating for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart ) { int nOutputs, iStop; abctime clk, clkTotal = Abc_Clock(); int nCallsUnsat = p->nCallsUnsat; int nCallsSat = p->nCallsSat; int nCallsUndec = p->nCallsUndec; int nCallsFiltered = p->nCallsFiltered; clk = Abc_Clock(); p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart, p->pCare, p->vSuppsInv, &nOutputs ); p->pCnf = Cnf_DeriveSimple( p->pPart, nOutputs ); p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); sat_solver_compress( p->pSat ); p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), p->nPattWords ); Vec_PtrCleanSimInfo( p->vPatts, 0, p->nPattWords ); p->timePrepare += Abc_Clock() - clk; Cgt_ClockGatingRangeCheck( p, iStart, nOutputs ); iStop = iStart + nOutputs; if ( p->pPars->fVeryVerbose ) { printf( "%5d : D =%4d. C =%5d. Var =%6d. Pr =%5d. Cex =%5d. F =%4d. Saved =%6d. ", iStart, iStop-iStart, Aig_ManCoNum(p->pPart)-nOutputs, p->pSat->size, p->nCallsUnsat-nCallsUnsat, p->nCallsSat -nCallsSat, p->nCallsUndec-nCallsUndec, p->nCallsFiltered-nCallsFiltered ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } Cgt_ManClean( p ); p->nRecycles++; return iStop; } /**Function************************************************************* Synopsis [Performs clock-gating for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful ) { Bar_Progress_t * pProgress = NULL; Cgt_Par_t Pars; Cgt_Man_t * p; Vec_Vec_t * vGatesAll; int iStart; abctime clk = Abc_Clock(), clkTotal = Abc_Clock(); // reset random numbers Aig_ManRandom( 1 ); if ( pPars == NULL ) Cgt_SetDefaultParams( pPars = &Pars ); p = Cgt_ManCreate( pAig, pCare, pPars ); p->vUseful = vUseful; p->pFrame = Cgt_ManDeriveAigForGating( p ); p->timeAig += Abc_Clock() - clk; assert( Aig_ManCoNum(p->pFrame) == Saig_ManRegNum(p->pAig) ); pProgress = Bar_ProgressStart( stdout, Aig_ManCoNum(p->pFrame) ); for ( iStart = 0; iStart < Aig_ManCoNum(p->pFrame); ) { Bar_ProgressUpdate( pProgress, iStart, NULL ); iStart = Cgt_ClockGatingRange( p, iStart ); } Bar_ProgressStop( pProgress ); vGatesAll = p->vGatesAll; p->vGatesAll = NULL; p->timeTotal = Abc_Clock() - clkTotal; Cgt_ManStop( p ); return vGatesAll; } /**Function************************************************************* Synopsis [Performs clock-gating for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Cgt_ClockGatingInt( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful ) { Vec_Vec_t * vGatesAll, * vGates; vGatesAll = Cgt_ClockGatingCandidates( pAig, pCare, pPars, vUseful ); if ( pPars->fAreaOnly ) vGates = Cgt_ManDecideArea( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose ); else vGates = Cgt_ManDecideSimple( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose ); Vec_VecFree( vGatesAll ); return vGates; } Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) { Aig_Man_t * pGated; Vec_Vec_t * vGates = Cgt_ClockGatingInt( pAig, pCare, pPars, NULL ); int nNodesUsed; if ( pPars->fVerbose ) { // printf( "Before CG: " ); // Aig_ManPrintStats( pAig ); } pGated = Cgt_ManDeriveGatedAig( pAig, vGates, pPars->fAreaOnly, &nNodesUsed ); if ( pPars->fVerbose ) { // printf( "After CG: " ); // Aig_ManPrintStats( pGated ); printf( "Nodes: Before CG = %6d. After CG = %6d. (%6.2f %%). Total after CG = %6d.\n", Aig_ManNodeNum(pAig), nNodesUsed, 100.0*nNodesUsed/Aig_ManNodeNum(pAig), Aig_ManNodeNum(pGated) ); } Vec_VecFree( vGates ); return pGated; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/cgtDecide.c000066400000000000000000000232271300674244400234400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cgtMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Clock gating package.] Synopsis [Decide what gate to use for what flop.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cgtInt.h" #include "proof/ssw/sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); extern int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ); extern int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ); extern int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects POs in the transitive fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManCollectFanoutPos_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) { Aig_Obj_t * pFanout; int f, iFanout = -1; if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsCo(pObj) ) { Vec_PtrPush( vFanout, pObj ); return; } Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) Cgt_ManCollectFanoutPos_rec( pAig, pFanout, vFanout ); } /**Function************************************************************* Synopsis [Collects POs in the transitive fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManCollectFanoutPos( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) { Vec_PtrClear( vFanout ); Aig_ManIncrementTravId( pAig ); Cgt_ManCollectFanoutPos_rec( pAig, pObj, vFanout ); } /**Function************************************************************* Synopsis [Checks if all PO fanouts can be gated by this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cgt_ManCheckGateComplete( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, Aig_Obj_t * pGate, Vec_Ptr_t * vFanout ) { Vec_Ptr_t * vGates; Aig_Obj_t * pObj; int i; Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) { if ( Saig_ObjIsPo(pAig, pObj) ) return 0; vGates = Vec_VecEntry( vGatesAll, Aig_ObjCioId(pObj) - Saig_ManPoNum(pAig) ); if ( Vec_PtrFind( vGates, pGate ) == -1 ) return 0; } return 1; } /**Function************************************************************* Synopsis [Computes the set of complete clock gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Cgt_ManCompleteGates( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) { Vec_Ptr_t * vFanout, * vGatesFull; Aig_Obj_t * pGate, * pGateR; int i, k; vFanout = Vec_PtrAlloc( 100 ); vGatesFull = Vec_PtrAlloc( 100 ); Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) { pGateR = Aig_Regular(pGate); if ( pGateR->fMarkA ) continue; pGateR->fMarkA = 1; Cgt_ManCollectFanoutPos( pAig, pGateR, vFanout ); if ( Cgt_ManCheckGateComplete( pAig, vGatesAll, pGate, vFanout ) ) Vec_PtrPush( vGatesFull, pGate ); } Vec_PtrFree( vFanout ); Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) Aig_Regular(pGate)->fMarkA = 0; return vGatesFull; } /**Function************************************************************* Synopsis [Calculates coverage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Cgt_ManComputeCoverage( Aig_Man_t * pAig, Vec_Vec_t * vGates ) { int nFrames = 32; int nWords = 1; Ssw_Sml_t * pSml; Vec_Ptr_t * vOne; int i, nTransSaved = 0; pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); Vec_VecForEachLevel( vGates, vOne, i ) nTransSaved += Ssw_SmlNodeCountOnesRealVec( pSml, vOne ); Ssw_SmlStop( pSml ); return (float)100.0*nTransSaved/32/nFrames/nWords/Vec_VecSize(vGates); } /**Function************************************************************* Synopsis [Chooses what clock-gate to use for this register.] Description [Currently uses the naive approach: For each register, choose the clock gate, which covers most of the transitions.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) { int nFrames = 32; int nWords = 1; Ssw_Sml_t * pSml; Vec_Vec_t * vGates; Vec_Ptr_t * vCands; Aig_Obj_t * pObjLi, * pObjLo, * pCand, * pCandBest; int i, k, nHitsCur, nHitsMax, Counter = 0; abctime clk = Abc_Clock(); int nTransTotal = 0, nTransSaved = 0; vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { nHitsMax = 0; pCandBest = NULL; vCands = Vec_VecEntry( vGatesAll, i ); Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pCand, k ) { // check if this is indeed a clock-gate if ( nOdcMax == 0 && !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) ) printf( "Clock gate candidate is invalid!\n" ); // find its characteristic number nHitsCur = Ssw_SmlNodeCountOnesReal( pSml, pCand ); if ( nHitsMax < nHitsCur ) { nHitsMax = nHitsCur; pCandBest = pCand; } } if ( pCandBest != NULL ) { Vec_VecPush( vGates, i, pCandBest ); Counter++; nTransSaved += nHitsMax; } nTransTotal += 32 * nFrames * nWords; } Ssw_SmlStop( pSml ); if ( fVerbose ) { printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); // printf( "Gated transitions = %5.2f %%. (%5.2f %%.) ", // 100.0*nTransSaved/nTransTotal, Cgt_ManComputeCoverage(pAig, vGates) ); printf( "Gated transitions = %5.2f %%. ", Cgt_ManComputeCoverage(pAig, vGates) ); ABC_PRT( "Time", Abc_Clock() - clk ); } /* { Vec_Ptr_t * vCompletes; vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); printf( "Complete gates = %d. \n", Vec_PtrSize(vCompletes) ); Vec_PtrFree( vCompletes ); } */ return vGates; } /**Function************************************************************* Synopsis [Computes the set of complete clock gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) { Vec_Vec_t * vGates; Vec_Ptr_t * vCompletes, * vOne; Aig_Obj_t * pGate; int i, k, Counter = 0; abctime clk = Abc_Clock(); // derive and label complete gates vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); // label complete gates Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i ) Aig_Regular(pGate)->fMarkA = 1; // select only complete gates vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) if ( Aig_Regular(pGate)->fMarkA ) Vec_VecPush( vGates, i, pGate ); // unlabel complete gates Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i ) Aig_Regular(pGate)->fMarkA = 0; // count the number of gated flops Vec_VecForEachLevel( vGates, vOne, i ) { Counter += (int)(Vec_PtrSize(vOne) > 0); // printf( "%d ", Vec_PtrSize(vOne) ); } // printf( "\n" ); if ( fVerbose ) { printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); printf( "Complete gates = %6d. Gated transitions = %5.2f %%. ", Vec_PtrSize(vCompletes), Cgt_ManComputeCoverage(pAig, vGates) ); ABC_PRT( "Time", Abc_Clock() - clk ); } Vec_PtrFree( vCompletes ); return vGates; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/cgtInt.h000066400000000000000000000123761300674244400230250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cgtInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Clock gating package.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cgtInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__cgt__cgtInt_h #define ABC__aig__cgt__cgtInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/saig/saig.h" #include "sat/bsat/satSolver.h" #include "sat/cnf/cnf.h" #include "cgt.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Cgt_Man_t_ Cgt_Man_t; struct Cgt_Man_t_ { // user's data Cgt_Par_t * pPars; // user's parameters Aig_Man_t * pAig; // user's AIG manager Vec_Int_t * vUseful; // user's candidate nodes // user's constraints Aig_Man_t * pCare; // constraint cones Vec_Vec_t * vSuppsInv; // inverse support of the constraints // result of clock-gating Vec_Vec_t * vGatesAll; // the computed clock-gates Vec_Ptr_t * vGates; // the selected clock-gates // internal data Aig_Man_t * pFrame; // clock gate AIG manager Vec_Ptr_t * vFanout; // temporary storage for fanouts Vec_Ptr_t * vVisited; // temporary storage for visited nodes // SAT solving Aig_Man_t * pPart; // partition Cnf_Dat_t * pCnf; // CNF of the partition sat_solver * pSat; // SAT solver Vec_Ptr_t * vPatts; // simulation patterns int nPatts; // the number of patterns accumulated int nPattWords; // the number of pattern words // statistics int nRecycles; // recycles int nCalls; // total calls int nCallsSat; // satisfiable calls int nCallsUnsat; // unsatisfiable calls int nCallsUndec; // undecided calls int nCallsFiltered; // filtered out calls abctime timeAig; // constructing AIG abctime timePrepare; // partitioning and SAT solving abctime timeSat; // total runtime abctime timeSatSat; // satisfiable runtime abctime timeSatUnsat; // unsatisfiable runtime abctime timeSatUndec; // undecided runtime abctime timeDecision; // making decision about what gates to use abctime timeOther; // other runtime abctime timeTotal; // total runtime }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cgtAig.c ==========================================================*/ extern void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ); extern Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ); extern Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pAig, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ); extern Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ); /*=== cgtDecide.c ==========================================================*/ extern Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ); extern Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ); /*=== cgtMan.c ==========================================================*/ extern Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ); extern void Cgt_ManClean( Cgt_Man_t * p ); extern void Cgt_ManStop( Cgt_Man_t * p ); /*=== cgtSat.c ==========================================================*/ extern int Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pFlop ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/cgtMan.c000066400000000000000000000121111300674244400227640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cgtMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Clock gating package.] Synopsis [Manipulation of clock gating manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cgtInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cgt_Man_t * Cgt_ManCreate( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars ) { Cgt_Man_t * p; // prepare the sequential AIG assert( Saig_ManRegNum(pAig) > 0 ); Aig_ManFanoutStart( pAig ); Aig_ManSetCioIds( pAig ); // create interpolation manager p = ABC_ALLOC( Cgt_Man_t, 1 ); memset( p, 0, sizeof(Cgt_Man_t) ); p->pPars = pPars; p->pAig = pAig; p->vGatesAll = Vec_VecStart( Saig_ManRegNum(pAig) ); p->vFanout = Vec_PtrAlloc( 1000 ); p->vVisited = Vec_PtrAlloc( 1000 ); p->nPattWords = 16; if ( pCare == NULL ) return p; // check out the constraints if ( Aig_ManCiNum(pCare) != Aig_ManCiNum(pAig) ) { printf( "The PI count of care (%d) and AIG (%d) differ. Careset is not used.\n", Aig_ManCiNum(pCare), Aig_ManCiNum(pAig) ); return p; } p->pCare = pCare; p->vSuppsInv = (Vec_Vec_t *)Aig_ManSupportsInverse( p->pCare ); return p; } /**Function************************************************************* Synopsis [Creates the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManClean( Cgt_Man_t * p ) { if ( p->pPart ) { Aig_ManStop( p->pPart ); p->pPart = NULL; } if ( p->pCnf ) { Cnf_DataFree( p->pCnf ); p->pCnf = NULL; } if ( p->pSat ) { sat_solver_delete( p->pSat ); p->pSat = NULL; } if ( p->vPatts ) { Vec_PtrFree( p->vPatts ); p->vPatts = NULL; } } /**Function************************************************************* Synopsis [Prints stats of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManPrintStats( Cgt_Man_t * p ) { printf( "Params: LevMax = %d. CandMax = %d. OdcMax = %d. ConfMax = %d. VarMin = %d. FlopMin = %d.\n", p->pPars->nLevelMax, p->pPars->nCandMax, p->pPars->nOdcMax, p->pPars->nConfMax, p->pPars->nVarsMin, p->pPars->nFlopsMin ); printf( "SAT : Calls = %d. Unsat = %d. Sat = %d. Fails = %d. Recycles = %d. ", p->nCalls, p->nCallsUnsat, p->nCallsSat, p->nCallsUndec, p->nRecycles ); ABC_PRT( "Time", p->timeTotal ); /* p->timeOther = p->timeTotal-p->timeAig-p->timePrepare-p->timeSat-p->timeDecision; ABC_PRTP( "AIG ", p->timeAig, p->timeTotal ); ABC_PRTP( "Prepare ", p->timePrepare, p->timeTotal ); ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); ABC_PRTP( " undecided", p->timeSatUndec, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); */ } /**Function************************************************************* Synopsis [Frees the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cgt_ManStop( Cgt_Man_t * p ) { if ( p->pPars->fVerbose ) Cgt_ManPrintStats( p ); if ( p->pFrame ) Aig_ManStop( p->pFrame ); Cgt_ManClean( p ); Vec_PtrFree( p->vFanout ); Vec_PtrFree( p->vVisited ); if ( p->vGates ) Vec_PtrFree( p->vGates ); if ( p->vGatesAll ) Vec_VecFree( p->vGatesAll ); if ( p->vSuppsInv ) Vec_VecFree( p->vSuppsInv ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/cgtSat.c000066400000000000000000000056001300674244400230050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cgtSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Clock gating package.] Synopsis [Checking implications using SAT.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cgtSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cgtInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Runs equivalence test for the two nodes.] Description [Both nodes should be regular and different from each other.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pMiter ) { int nBTLimit = p->pPars->nConfMax; int pLits[2], RetValue; abctime clk; p->nCalls++; // sanity checks assert( p->pSat && p->pCnf ); assert( !Aig_IsComplement(pMiter) ); assert( Aig_Regular(pGate) != pMiter ); // solve under assumptions // G => !M -- true G & M -- false pLits[0] = toLitCond( p->pCnf->pVarNums[Aig_Regular(pGate)->Id], Aig_IsComplement(pGate) ); pLits[1] = toLitCond( p->pCnf->pVarNums[pMiter->Id], 0 ); clk = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); p->timeSat += Abc_Clock() - clk; if ( RetValue == 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 ); sat_solver_compress( p->pSat ); p->nCallsUnsat++; return 1; } else if ( RetValue == l_True ) { p->timeSatSat += Abc_Clock() - clk; p->nCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nCallsUndec++; return -1; } return -2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cgt/module.make000066400000000000000000000002001300674244400235270ustar00rootroot00000000000000SRC += src/opt/cgt/cgtAig.c \ src/opt/cgt/cgtCore.c \ src/opt/cgt/cgtDecide.c \ src/opt/cgt/cgtMan.c \ src/opt/cgt/cgtSat.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/000077500000000000000000000000001300674244400214325ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/csw.h000066400000000000000000000044351300674244400224050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [csw.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Cut sweeping.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 11, 2007.] Revision [$Id: csw.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__csw__csw_h #define ABC__aig__csw__csw_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cnfCore.c ========================================================*/ extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/cswCore.c000066400000000000000000000063471300674244400232150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cswCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Cut sweeping.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 11, 2007.] Revision [$Id: cswCore.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ) { Csw_Man_t * p; Aig_Man_t * pRes; Aig_Obj_t * pObj, * pObjNew, * pObjRes; int i; abctime clk; clk = Abc_Clock(); // start the manager p = Csw_ManStart( pAig, nCutsMax, nLeafMax, fVerbose ); // set elementary cuts at the PIs Aig_ManForEachCi( p->pManRes, pObj, i ) { Csw_ObjPrepareCuts( p, pObj, 1 ); Csw_ObjAddRefs( p, pObj, Aig_ManCi(p->pManAig,i)->nRefs ); } // process the nodes Aig_ManForEachNode( pAig, pObj, i ) { // create the new node pObjNew = Aig_And( p->pManRes, Csw_ObjChild0Equiv(p, pObj), Csw_ObjChild1Equiv(p, pObj) ); // check if this node can be represented using another node // pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 ); // pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) ); // try recursively if resubsitution is used do { pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 ); pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) ); pObjNew = pObjRes; } while ( Csw_ObjCuts(p, Aig_Regular(pObjNew)) == NULL && !Aig_ObjIsConst1(Aig_Regular(pObjNew)) ); // save the resulting node Csw_ObjSetEquiv( p, pObj, pObjRes ); // add to the reference counter Csw_ObjAddRefs( p, Aig_Regular(pObjRes), pObj->nRefs ); } // add the POs Aig_ManForEachCo( pAig, pObj, i ) Aig_ObjCreateCo( p->pManRes, Csw_ObjChild0Equiv(p, pObj) ); // remove dangling nodes Aig_ManCleanup( p->pManRes ); // return the resulting manager p->timeTotal = Abc_Clock() - clk; p->timeOther = p->timeTotal - p->timeCuts - p->timeHash; pRes = p->pManRes; Csw_ManStop( p ); return pRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/cswCut.c000066400000000000000000000425411300674244400230540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cswCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Cut sweeping.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 11, 2007.] Revision [$Id: cswCut.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Compute the cost of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Csw_CutFindCost( Csw_Man_t * p, Csw_Cut_t * pCut ) { Aig_Obj_t * pLeaf; int i, Cost = 0; assert( pCut->nFanins > 0 ); Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i ) { // Cost += pLeaf->nRefs; Cost += Csw_ObjRefs( p, pLeaf ); // printf( "%d ", pLeaf->nRefs ); } //printf( "\n" ); return Cost * 100 / pCut->nFanins; } /**Function************************************************************* Synopsis [Compute the cost of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Csw_CutFindCost2( Csw_Man_t * p, Csw_Cut_t * pCut ) { Aig_Obj_t * pLeaf; float Cost = 0.0; int i; assert( pCut->nFanins > 0 ); Csw_CutForEachLeaf( p->pManRes, 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 Csw_Cut_t * Csw_CutFindFree( Csw_Man_t * p, Aig_Obj_t * pObj ) { Csw_Cut_t * pCut, * pCutMax; int i; pCutMax = NULL; Csw_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 Cut_TruthPhase( Csw_Cut_t * pCut, Csw_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 * Csw_CutComputeTruth( Csw_Man_t * p, Csw_Cut_t * pCut, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, int fCompl0, int fCompl1 ) { // permute the first table if ( fCompl0 ) Kit_TruthNot( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax ); else Kit_TruthCopy( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax ); Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut0), 0 ); // permute the second table if ( fCompl1 ) Kit_TruthNot( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax ); else Kit_TruthCopy( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax ); Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut1), 0 ); // produce the resulting table Kit_TruthAnd( Csw_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax ); // assert( pCut->nFanins >= Kit_TruthSupportSize( Csw_CutTruth(pCut), p->nLeafMax ) ); return Csw_CutTruth(pCut); } /**Function************************************************************* Synopsis [Performs support minimization for the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Csw_CutSupportMinimize( Csw_Man_t * p, Csw_Cut_t * pCut ) { unsigned * pTruth; int uSupp, nFansNew, i, k; // get truth table pTruth = Csw_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 Csw_CutCheckDominance( Csw_Cut_t * pDom, Csw_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 Csw_CutFilter( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCut ) { Csw_Cut_t * pTemp; int i; // go through the cuts of the node Csw_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 ( Csw_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 ( Csw_CutCheckDominance( pTemp, pCut ) ) { // remove the given pCut->nFanins = 0; return 1; } } } return 0; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Csw_CutMergeOrdered( Csw_Man_t * p, Csw_Cut_t * pC0, Csw_Cut_t * pC1, Csw_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 Csw_CutMerge( Csw_Man_t * p, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, Csw_Cut_t * pCut ) { assert( p->nLeafMax > 0 ); // merge the nodes if ( pCut0->nFanins < pCut1->nFanins ) { if ( !Csw_CutMergeOrdered( p, pCut1, pCut0, pCut ) ) return 0; } else { if ( !Csw_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) return 0; } pCut->uSign = pCut0->uSign | pCut1->uSign; return 1; } /**Function************************************************************* Synopsis [Consider cut with more than 2 fanins having 2 true variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Csw_ObjTwoVarCut( Csw_Man_t * p, Csw_Cut_t * pCut ) { Aig_Obj_t * pRes, * pIn0, * pIn1; int nVars, uTruth, fCompl = 0; assert( pCut->nFanins > 2 ); // minimize support of this cut nVars = Csw_CutSupportMinimize( p, pCut ); assert( nVars == 2 ); // get the fanins pIn0 = Aig_ManObj( p->pManRes, pCut->pFanins[0] ); pIn1 = Aig_ManObj( p->pManRes, pCut->pFanins[1] ); // derive the truth table uTruth = 0xF & *Csw_CutTruth(pCut); if ( uTruth == 14 || uTruth == 13 || uTruth == 11 || uTruth == 7 ) { uTruth = 0xF & ~uTruth; fCompl = 1; } // compute the result pRes = NULL; if ( uTruth == 1 ) // 0001 // 1110 14 pRes = Aig_And( p->pManRes, Aig_Not(pIn0), Aig_Not(pIn1) ); if ( uTruth == 2 ) // 0010 // 1101 13 pRes = Aig_And( p->pManRes, pIn0 , Aig_Not(pIn1) ); if ( uTruth == 4 ) // 0100 // 1011 11 pRes = Aig_And( p->pManRes, Aig_Not(pIn0), pIn1 ); if ( uTruth == 8 ) // 1000 // 0111 7 pRes = Aig_And( p->pManRes, pIn0 , pIn1 ); if ( pRes ) pRes = Aig_NotCond( pRes, fCompl ); return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ) { Csw_Cut_t * pCutSet, * pCut; int i; // create the cutset of the node pCutSet = (Csw_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); Csw_ObjSetCuts( p, pObj, pCutSet ); Csw_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 ); memset( Csw_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords ); } return pCutSet; } /**Function************************************************************* Synopsis [Derives cuts for one node and sweeps this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ) { int fUseResub = 1; Csw_Cut_t * pCut0, * pCut1, * pCut, * pCutSet; Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); Aig_Obj_t * pObjNew; unsigned * pTruth; int i, k, nVars, nFanins, iVar; abctime clk; assert( !Aig_IsComplement(pObj) ); if ( !Aig_ObjIsNode(pObj) ) return pObj; if ( Csw_ObjCuts(p, pObj) ) return pObj; // the node is not processed yet assert( Csw_ObjCuts(p, pObj) == NULL ); assert( Aig_ObjIsNode(pObj) ); // set up the first cut pCutSet = Csw_ObjPrepareCuts( p, pObj, fTriv ); // compute pair-wise cut combinations while checking table Csw_ObjForEachCut( p, pFanin0, pCut0, i ) if ( pCut0->nFanins > 0 ) Csw_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 = Csw_CutFindFree( p, pObj ); clk = Abc_Clock(); // assemble the new cut if ( !Csw_CutMerge( p, pCut0, pCut1, pCut ) ) { assert( pCut->nFanins == 0 ); continue; } // check containment if ( Csw_CutFilter( p, pObj, pCut ) ) { assert( pCut->nFanins == 0 ); continue; } // create its truth table pTruth = Csw_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); // support minimize the truth table nFanins = pCut->nFanins; // nVars = Csw_CutSupportMinimize( p, pCut ); // leads to quality degradation nVars = Kit_TruthSupportSize( pTruth, p->nLeafMax ); p->timeCuts += Abc_Clock() - clk; // check for trivial truth tables if ( nVars == 0 ) { p->nNodesTriv0++; return Aig_NotCond( Aig_ManConst1(p->pManRes), !(pTruth[0] & 1) ); } if ( nVars == 1 ) { p->nNodesTriv1++; iVar = Kit_WordFindFirstBit( Kit_TruthSupport(pTruth, p->nLeafMax) ); assert( iVar < pCut->nFanins ); return Aig_NotCond( Aig_ManObj(p->pManRes, pCut->pFanins[iVar]), (pTruth[0] & 1) ); } if ( nVars == 2 && nFanins > 2 && fUseResub ) { if ( (pObjNew = Csw_ObjTwoVarCut( p, pCut )) ) { p->nNodesTriv2++; return pObjNew; } } // check if an equivalent node with the same cut exists clk = Abc_Clock(); pObjNew = pCut->nFanins > 2 ? Csw_TableCutLookup( p, pCut ) : NULL; p->timeHash += Abc_Clock() - clk; if ( pObjNew ) { p->nNodesCuts++; return pObjNew; } // assign the cost pCut->Cost = Csw_CutFindCost( p, pCut ); assert( pCut->nFanins > 0 ); assert( pCut->Cost > 0 ); } p->nNodesTried++; // load the resulting cuts into the table clk = Abc_Clock(); Csw_ObjForEachCut( p, pObj, pCut, i ) { if ( pCut->nFanins > 2 ) { assert( pCut->Cost > 0 ); Csw_TableCutInsert( p, pCut ); } } p->timeHash += Abc_Clock() - clk; // return the node if could not replace it return pObj; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/cswInt.h000066400000000000000000000172431300674244400230610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cswInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Cut sweeping.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 11, 2007.] Revision [$Id: cswInt.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__csw__cswInt_h #define ABC__aig__csw__cswInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "aig/aig/aig.h" #include "opt/dar/dar.h" #include "bool/kit/kit.h" #include "csw.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Csw_Man_t_ Csw_Man_t; typedef struct Csw_Cut_t_ Csw_Cut_t; // the cut used to represent node in the AIG struct Csw_Cut_t_ { Csw_Cut_t * pNext; // the next cut in the table int Cost; // the cost of the cut // float 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 Csw_Man_t_ { // AIG manager Aig_Man_t * pManAig; // the input AIG manager Aig_Man_t * pManRes; // the output AIG manager Aig_Obj_t ** pEquiv; // the equivalent nodes in the resulting manager Csw_Cut_t ** pCuts; // the cuts for each node in the output manager int * pnRefs; // the number of references of each new node // hash table for cuts Csw_Cut_t ** pTable; // the table composed of cuts int nTableSize; // the size of hash table // parameters int nCutsMax; // the max number of cuts at the node int nLeafMax; // the max number of leaves of a cut 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 // statistics int nNodesTriv0; // the number of trivial nodes int nNodesTriv1; // the number of trivial nodes int nNodesTriv2; // the number of trivial nodes int nNodesCuts; // the number of rewritten nodes int nNodesTried; // the number of nodes tried abctime timeCuts; // time to compute the cut and its truth table abctime timeHash; // time for hashing cuts abctime timeOther; // other time abctime timeTotal; // total time }; static inline int Csw_CutLeaveNum( Csw_Cut_t * pCut ) { return pCut->nFanins; } static inline int * Csw_CutLeaves( Csw_Cut_t * pCut ) { return pCut->pFanins; } static inline unsigned * Csw_CutTruth( Csw_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); } static inline Csw_Cut_t * Csw_CutNext( Csw_Cut_t * pCut ) { return (Csw_Cut_t *)(((char *)pCut) + pCut->nCutSize); } static inline int Csw_ObjRefs( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pnRefs[pObj->Id]; } static inline void Csw_ObjAddRefs( Csw_Man_t * p, Aig_Obj_t * pObj, int nRefs ) { p->pnRefs[pObj->Id] += nRefs; } static inline Csw_Cut_t * Csw_ObjCuts( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } static inline void Csw_ObjSetCuts( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; } static inline Aig_Obj_t * Csw_ObjEquiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquiv[pObj->Id]; } static inline void Csw_ObjSetEquiv( Csw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEquiv ) { p->pEquiv[pObj->Id] = pEquiv; } static inline Aig_Obj_t * Csw_ObjChild0Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Csw_ObjChild1Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // iterator over cuts of the node #define Csw_ObjForEachCut( p, pObj, pCut, i ) \ for ( i = 0, pCut = Csw_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Csw_CutNext(pCut) ) // iterator over leaves of the cut #define Csw_CutForEachLeaf( p, pCut, pLeaf, i ) \ for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cnfCut.c ========================================================*/ extern Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ); extern Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ); /*=== cnfMan.c ========================================================*/ extern Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose ); extern void Csw_ManStop( Csw_Man_t * p ); /*=== cnfTable.c ========================================================*/ extern int Csw_TableCountCuts( Csw_Man_t * p ); extern void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut ); extern Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/cswMan.c000066400000000000000000000110721300674244400230270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cswMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Cut sweeping.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 11, 2007.] Revision [$Id: cswMan.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the cut sweeping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose ) { Csw_Man_t * p; Aig_Obj_t * pObj; int i; assert( nCutsMax >= 2 ); assert( nLeafMax <= 16 ); // allocate the fraiging manager p = ABC_ALLOC( Csw_Man_t, 1 ); memset( p, 0, sizeof(Csw_Man_t) ); p->nCutsMax = nCutsMax; p->nLeafMax = nLeafMax; p->fVerbose = fVerbose; p->pManAig = pMan; // create the new manager p->pManRes = Aig_ManStartFrom( pMan ); assert( Aig_ManCiNum(p->pManAig) == Aig_ManCiNum(p->pManRes) ); // allocate room for cuts and equivalent nodes p->pnRefs = ABC_ALLOC( int, Aig_ManObjNumMax(pMan) ); p->pEquiv = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pMan) ); p->pCuts = ABC_ALLOC( Csw_Cut_t *, Aig_ManObjNumMax(pMan) ); memset( p->pCuts, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pMan) ); memset( p->pnRefs, 0, sizeof(int) * Aig_ManObjNumMax(pMan) ); // allocate memory manager p->nTruthWords = Abc_TruthWordNum(nLeafMax); p->nCutSize = sizeof(Csw_Cut_t) + sizeof(int) * nLeafMax + sizeof(unsigned) * p->nTruthWords; p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 ); // allocate hash table for cuts p->nTableSize = Abc_PrimeCudd( Aig_ManNodeNum(pMan) * p->nCutsMax / 2 ); p->pTable = ABC_ALLOC( Csw_Cut_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); // set the pointers to the available fraig nodes Csw_ObjSetEquiv( p, Aig_ManConst1(p->pManAig), Aig_ManConst1(p->pManRes) ); Aig_ManForEachCi( p->pManAig, pObj, i ) Csw_ObjSetEquiv( p, pObj, Aig_ManCi(p->pManRes, i) ); // room for temporary truth tables 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 Csw_ManStop( Csw_Man_t * p ) { if ( p->fVerbose ) { int nNodesBeg = Aig_ManNodeNum(p->pManAig); int nNodesEnd = Aig_ManNodeNum(p->pManRes); printf( "Beg = %7d. End = %7d. (%6.2f %%) Try = %7d. Cuts = %8d.\n", nNodesBeg, nNodesEnd, 100.0*(nNodesBeg-nNodesEnd)/nNodesBeg, p->nNodesTried, Csw_TableCountCuts( p ) ); printf( "Triv0 = %6d. Triv1 = %6d. Triv2 = %6d. Cut-replace = %6d.\n", p->nNodesTriv0, p->nNodesTriv1, p->nNodesTriv2, p->nNodesCuts ); ABC_PRTP( "Cuts ", p->timeCuts, p->timeTotal ); ABC_PRTP( "Hashing ", p->timeHash, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); } ABC_FREE( p->puTemp[0] ); Aig_MmFixedStop( p->pMemCuts, 0 ); ABC_FREE( p->pnRefs ); ABC_FREE( p->pEquiv ); ABC_FREE( p->pCuts ); ABC_FREE( p->pTable ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/cswTable.c000066400000000000000000000121061300674244400233420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cswTable.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Cut sweeping.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 11, 2007.] Revision [$Id: cswTable.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes hash value of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Csw_CutHash( Csw_Cut_t * pCut ) { 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; assert( pCut->nFanins <= 16 ); uHash = 0; for ( i = 0; i < pCut->nFanins; i++ ) uHash ^= pCut->pFanins[i] * s_FPrimes[i]; return uHash; } /**Function************************************************************* Synopsis [Returns the total number of cuts in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Csw_TableCountCuts( Csw_Man_t * p ) { Csw_Cut_t * pEnt; int i, Counter = 0; for ( i = 0; i < p->nTableSize; i++ ) for ( pEnt = p->pTable[i]; pEnt; pEnt = pEnt->pNext ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Adds the cut to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut ) { int iEntry = Csw_CutHash(pCut) % p->nTableSize; pCut->pNext = p->pTable[iEntry]; p->pTable[iEntry] = pCut; } /**Function************************************************************* Synopsis [Returns an equivalent node if it exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut ) { Aig_Obj_t * pRes = NULL; Csw_Cut_t * pEnt; unsigned * pTruthNew, * pTruthOld; int iEntry = Csw_CutHash(pCut) % p->nTableSize; for ( pEnt = p->pTable[iEntry]; pEnt; pEnt = pEnt->pNext ) { if ( pEnt->nFanins != pCut->nFanins ) continue; if ( pEnt->uSign != pCut->uSign ) continue; if ( memcmp( pEnt->pFanins, pCut->pFanins, sizeof(int) * pCut->nFanins ) ) continue; pTruthOld = Csw_CutTruth(pEnt); pTruthNew = Csw_CutTruth(pCut); if ( (pTruthOld[0] & 1) == (pTruthNew[0] & 1) ) { if ( Kit_TruthIsEqual( pTruthOld, pTruthNew, pCut->nFanins ) ) { pRes = Aig_ManObj( p->pManRes, pEnt->iNode ); assert( pRes->fPhase == Aig_ManObj( p->pManRes, pCut->iNode )->fPhase ); break; } } else { if ( Kit_TruthIsOpposite( pTruthOld, pTruthNew, pCut->nFanins ) ) { pRes = Aig_Not( Aig_ManObj( p->pManRes, pEnt->iNode ) ); assert( Aig_Regular(pRes)->fPhase != Aig_ManObj( p->pManRes, pCut->iNode )->fPhase ); break; } } } return pRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/csw_.c000066400000000000000000000026361300674244400225400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [csw_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Cut sweeping.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 11, 2007.] Revision [$Id: csw_.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/csw/module.make000066400000000000000000000001501300674244400235520ustar00rootroot00000000000000SRC += src/opt/csw/cswCore.c \ src/opt/csw/cswCut.c \ src/opt/csw/cswMan.c \ src/opt/csw/cswTable.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/000077500000000000000000000000001300674244400214315ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/abcCut.c000066400000000000000000000362651300674244400230120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface to cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "cut.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); extern int nTotal, nGood, nEqual; // temporary //Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { return NULL; } Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { Vec_Int_t * vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); int i; Abc_Obj_t * pObj; // Abc_NtkForEachCi( pNtk, pObj, i ) // Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); Abc_NtkForEachObj( pNtk, pObj, i ) { // if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) ) if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) ) Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); } return vAttrs; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) { ProgressBar * pProgress; Cut_Man_t * p; Abc_Obj_t * pObj, * pNode; Vec_Ptr_t * vNodes; Vec_Int_t * vChoices; int i; clock_t clk = clock(); extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); nTotal = nGood = nEqual = 0; assert( Abc_NtkIsStrash(pNtk) ); // start the manager pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); p = Cut_ManStart( pParams ); // compute node attributes if local or global cuts are requested if ( pParams->fGlobal || pParams->fLocal ) { extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) ); } // prepare for cut dropping if ( pParams->fDrop ) Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); // set cuts for PIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( p, pObj->Id ); // compute cuts for internal nodes vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs vChoices = Vec_IntAlloc( 100 ); pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // when we reached a CO, it is time to deallocate the cuts if ( Abc_ObjIsCo(pObj) ) { if ( pParams->fDrop ) Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); continue; } // skip constant node, it has no cuts // if ( Abc_NodeIsConst(pObj) ) // continue; Extra_ProgressBarUpdate( pProgress, i, NULL ); // compute the cuts to the internal node Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); // consider dropping the fanins cuts if ( pParams->fDrop ) { Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); } // add cuts due to choices if ( Abc_AigNodeIsChoice(pObj) ) { Vec_IntClear( vChoices ); for ( pNode = pObj; pNode; pNode = pNode->pData ) Vec_IntPush( vChoices, pNode->Id ); Cut_NodeUnionCuts( p, vChoices ); } } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); Vec_IntFree( vChoices ); PRT( "Total", clock() - clk ); //Abc_NtkPrintCuts( p, pNtk, 0 ); // Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); // temporary printout of stats if ( nTotal ) printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); return p; } /**Function************************************************************* Synopsis [Cut computation using the oracle.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) { Abc_Obj_t * pObj; Vec_Ptr_t * vNodes; int i; clock_t clk = clock(); int fDrop = Cut_OracleReadDrop(p); assert( Abc_NtkIsStrash(pNtk) ); // prepare cut droppping if ( fDrop ) Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); // set cuts for PIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_OracleNodeSetTriv( p, pObj->Id ); // compute cuts for internal nodes vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // when we reached a CO, it is time to deallocate the cuts if ( Abc_ObjIsCo(pObj) ) { if ( fDrop ) Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); continue; } // skip constant node, it has no cuts // if ( Abc_NodeIsConst(pObj) ) // continue; // compute the cuts to the internal node Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); // consider dropping the fanins cuts if ( fDrop ) { Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); } } Vec_PtrFree( vNodes ); //PRT( "Total", clock() - clk ); //Abc_NtkPrintCuts_( p, pNtk, 0 ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) { /* Cut_Man_t * p; Abc_Obj_t * pObj, * pNode; int i, nIters, fStatus; Vec_Int_t * vChoices; clock_t clk = clock(); assert( Abc_NtkIsSeq(pNtk) ); assert( pParams->fSeq ); // assert( Abc_NtkIsDfsOrdered(pNtk) ); // start the manager pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk ); p = Cut_ManStart( pParams ); // set cuts for the constant node and the PIs pObj = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pObj) > 0 ) Cut_NodeSetTriv( p, pObj->Id ); Abc_NtkForEachPi( pNtk, pObj, i ) { //printf( "Setting trivial cut %d.\n", pObj->Id ); Cut_NodeSetTriv( p, pObj->Id ); } // label the cutset nodes and set their number in the array // assign the elementary cuts to the cutset nodes Abc_SeqForEachCutsetNode( pNtk, pObj, i ) { assert( pObj->fMarkC == 0 ); pObj->fMarkC = 1; pObj->pCopy = (Abc_Obj_t *)i; Cut_NodeSetTriv( p, pObj->Id ); //printf( "Setting trivial cut %d.\n", pObj->Id ); } // process the nodes vChoices = Vec_IntAlloc( 100 ); for ( nIters = 0; nIters < 10; nIters++ ) { //printf( "ITERATION %d:\n", nIters ); // compute the cuts for the internal nodes Abc_AigForEachAnd( pNtk, pObj, i ) { Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); // add cuts due to choices if ( Abc_AigNodeIsChoice(pObj) ) { Vec_IntClear( vChoices ); for ( pNode = pObj; pNode; pNode = pNode->pData ) Vec_IntPush( vChoices, pNode->Id ); Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 ); } } // merge the new cuts with the old cuts Abc_NtkForEachPi( pNtk, pObj, i ) Cut_NodeNewMergeWithOld( p, pObj->Id ); Abc_AigForEachAnd( pNtk, pObj, i ) Cut_NodeNewMergeWithOld( p, pObj->Id ); // for the cutset, transfer temp cuts to new cuts fStatus = 0; Abc_SeqForEachCutsetNode( pNtk, pObj, i ) fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i ); if ( fStatus == 0 ) break; } Vec_IntFree( vChoices ); // if the status is not finished, transfer new to old for the cutset Abc_SeqForEachCutsetNode( pNtk, pObj, i ) Cut_NodeNewMergeWithOld( p, pObj->Id ); // transfer the old cuts to the new positions Abc_NtkForEachObj( pNtk, pObj, i ) Cut_NodeOldTransferToNew( p, pObj->Id ); // unlabel the cutset nodes Abc_SeqForEachCutsetNode( pNtk, pObj, i ) pObj->fMarkC = 0; if ( pParams->fVerbose ) { PRT( "Total", clock() - clk ); printf( "Converged after %d iterations.\n", nIters ); } //Abc_NtkPrintCuts( p, pNtk, 1 ); return p; */ } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) { void * pList; if ( pList = Abc_NodeReadCuts( p, pObj ) ) return pList; Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); return Abc_NodeGetCuts( p, pObj, fDag, fTree ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) { Abc_Obj_t * pFanin; int fDagNode, fTriv, TreeCode = 0; // assert( Abc_NtkIsStrash(pObj->pNtk) ); assert( Abc_ObjFaninNum(pObj) == 2 ); // check if the node is a DAG node fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); // increment the counter of DAG nodes if ( fDagNode ) Cut_ManIncrementDagNodes( p ); // add the trivial cut if the node is a DAG node, or if we compute all cuts fTriv = fDagNode || !fDag; // check if fanins are DAG nodes if ( fTree ) { pFanin = Abc_ObjFanin0(pObj); TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); pFanin = Abc_ObjFanin1(pObj); TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); } // changes due to the global/local cut computation { Cut_Params_t * pParams = Cut_ManReadParams(p); if ( pParams->fLocal ) { Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p); fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id ); if ( fDagNode ) Cut_ManIncrementDagNodes( p ); // fTriv = fDagNode || !pParams->fGlobal; fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id ); TreeCode = 0; pFanin = Abc_ObjFanin0(pObj); TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id ); pFanin = Abc_ObjFanin1(pObj); TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1); } } return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) { int CutSetNum; assert( Abc_NtkIsSeq(pObj->pNtk) ); assert( Abc_ObjFaninNum(pObj) == 2 ); fTriv = pObj->fMarkC ? 0 : fTriv; CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) { return Cut_NodeReadCutsNew( p, pObj->Id ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ) { Cut_NodeFreeCuts( p, pObj->Id ); } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ) { Cut_Man_t * pMan = p; Cut_Cut_t * pList; Abc_Obj_t * pObj; int i; printf( "Cuts of the network:\n" ); Abc_NtkForEachObj( pNtk, pObj, i ) { pList = Abc_NodeReadCuts( p, pObj ); printf( "Node %s:\n", Abc_ObjName(pObj) ); Cut_CutPrintList( pList, fSeq ); } } /**Function************************************************************* Synopsis [Computes the cuts for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ) { Cut_Man_t * pMan = p; Cut_Cut_t * pList; Abc_Obj_t * pObj; pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 ); pList = Abc_NodeReadCuts( p, pObj ); printf( "Node %s:\n", Abc_ObjName(pObj) ); Cut_CutPrintList( pList, fSeq ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cut.h000066400000000000000000000221271300674244400224010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cut.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__cut__cut_h #define ABC__opt__cut__cut_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define CUT_SIZE_MIN 3 // the min K of the K-feasible cut computation #define CUT_SIZE_MAX 12 // the max K of the K-feasible cut computation #define CUT_SHIFT 8 // the number of bits for storing latch number in the cut leaves #define CUT_MASK 0xFF // the mask to get the stored latch number //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Cut_ManStruct_t_ Cut_Man_t; typedef struct Cut_OracleStruct_t_ Cut_Oracle_t; typedef struct Cut_CutStruct_t_ Cut_Cut_t; typedef struct Cut_ParamsStruct_t_ Cut_Params_t; struct Cut_ParamsStruct_t_ { int nVarsMax; // the max cut size ("k" of the k-feasible cuts) int nKeepMax; // the max number of cuts kept at a node int nIdsMax; // the max number of IDs of cut objects int nBitShift; // the number of bits used for the latch counter of an edge int nCutSet; // the number of nodes in the cut set int fTruth; // compute truth tables int fFilter; // filter dominated cuts int fSeq; // compute sequential cuts int fDrop; // drop cuts on the fly int fDag; // compute only DAG cuts int fTree; // compute only tree cuts int fGlobal; // compute only global cuts int fLocal; // compute only local cuts int fRecord; // record the cut computation flow int fRecordAig; // record the cut functions int fFancy; // perform fancy computations int fMap; // computes delay of FPGA mapping with cuts int fAdjust; // removed useless fanouts of XORs/MUXes int fNpnSave; // enables dumping 6-input truth tables int fVerbose; // the verbosiness flag }; struct Cut_CutStruct_t_ { unsigned Num0 : 11; // temporary number unsigned Num1 : 11; // temporary number unsigned fSimul : 1; // the value of cut's output at 000.. pattern unsigned fCompl : 1; // the cut is complemented unsigned nVarsMax : 4; // the max number of vars [4-6] unsigned nLeaves : 4; // the number of leaves [4-6] unsigned uSign; // the signature unsigned uCanon0; // the canonical form unsigned uCanon1; // the canonical form Cut_Cut_t * pNext; // the next cut in the list int pLeaves[0]; // the array of leaves }; static inline int Cut_CutReadLeaveNum( Cut_Cut_t * p ) { return p->nLeaves; } static inline int * Cut_CutReadLeaves( Cut_Cut_t * p ) { return p->pLeaves; } static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p ) { return (unsigned *)(p->pLeaves + p->nVarsMax); } static inline void Cut_CutWriteTruth( Cut_Cut_t * p, unsigned * puTruth ) { int i; for ( i = (p->nVarsMax <= 5) ? 0 : ((1 << (p->nVarsMax - 5)) - 1); i >= 0; i-- ) p->pLeaves[p->nVarsMax + i] = (int)puTruth[i]; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cutApi.c ==========================================================*/ extern Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node ); extern Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node ); extern Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node ); extern void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); extern void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); extern void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); extern void Cut_NodeSetTriv( Cut_Man_t * p, int Node ); extern void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node ); extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node ); /*=== cutCut.c ==========================================================*/ extern void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq ); extern void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq ); extern int Cut_CutCountList( Cut_Cut_t * pList ); /*=== cutMan.c ==========================================================*/ extern Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams ); extern void Cut_ManStop( Cut_Man_t * p ); extern void Cut_ManPrintStats( Cut_Man_t * p ); extern void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, abctime TimeTotal ); extern void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts ); extern void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vFanCounts ); extern int Cut_ManReadVarsMax( Cut_Man_t * p ); extern Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p ); extern Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p ); extern void Cut_ManIncrementDagNodes( Cut_Man_t * p ); /*=== cutNode.c ==========================================================*/ extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ); extern Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ); extern Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ); extern int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ); /*=== cutSeq.c ==========================================================*/ extern void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum ); extern void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node ); extern int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum ); extern void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node ); /*=== cutOracle.c ==========================================================*/ extern Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan ); extern void Cut_OracleStop( Cut_Oracle_t * p ); extern void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts ); extern int Cut_OracleReadDrop( Cut_Oracle_t * p ); extern void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node ); extern Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ); extern void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node ); /*=== cutTruth.c ==========================================================*/ extern void Cut_TruthNCanonicize( Cut_Cut_t * pCut ); /*=== cutPre22.c ==========================================================*/ extern void Cut_CellPrecompute(); extern void Cut_CellLoad(); extern int Cut_CellIsRunning(); extern void Cut_CellDumpToFile(); extern int Cut_CellTruthLookup( unsigned * pTruth, int nVars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutApi.c000066400000000000000000000125211300674244400230230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutNode.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Procedures to compute cuts for a node.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the pointer to the linked list of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node ) { if ( Node >= p->vCutsNew->nSize ) return NULL; return (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node ); } /**Function************************************************************* Synopsis [Returns the pointer to the linked list of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node ) { assert( Node < p->vCutsOld->nSize ); return (Cut_Cut_t *)Vec_PtrEntry( p->vCutsOld, Node ); } /**Function************************************************************* Synopsis [Returns the pointer to the linked list of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node ) { assert( Node < p->vCutsTemp->nSize ); return (Cut_Cut_t *)Vec_PtrEntry( p->vCutsTemp, Node ); } /**Function************************************************************* Synopsis [Returns the pointer to the linked list of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) { Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); } /**Function************************************************************* Synopsis [Returns the pointer to the linked list of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) { Vec_PtrWriteEntry( p->vCutsOld, Node, pList ); } /**Function************************************************************* Synopsis [Returns the pointer to the linked list of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) { Vec_PtrWriteEntry( p->vCutsTemp, Node, pList ); } /**Function************************************************************* Synopsis [Sets the trivial cut for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeSetTriv( Cut_Man_t * p, int Node ) { assert( Cut_NodeReadCutsNew(p, Node) == NULL ); Cut_NodeWriteCutsNew( p, Node, Cut_CutCreateTriv(p, Node) ); } /**Function************************************************************* Synopsis [Consider dropping cuts if they are useless by now.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node ) { int nFanouts; assert( p->vFanCounts ); nFanouts = Vec_IntEntry( p->vFanCounts, Node ); assert( nFanouts > 0 ); if ( --nFanouts == 0 ) Cut_NodeFreeCuts( p, Node ); Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts ); } /**Function************************************************************* Synopsis [Deallocates the cuts at the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeFreeCuts( Cut_Man_t * p, int Node ) { Cut_Cut_t * pList, * pCut, * pCut2; pList = Cut_NodeReadCutsNew( p, Node ); if ( pList == NULL ) return; Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); Cut_NodeWriteCutsNew( p, Node, NULL ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutCut.c000066400000000000000000000227071300674244400230540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutNode.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Procedures to compute cuts for a node.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p ) { Cut_Cut_t * pCut; // cut allocation pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); memset( pCut, 0, sizeof(Cut_Cut_t) ); pCut->nVarsMax = p->pParams->nVarsMax; pCut->fSimul = p->fSimul; // statistics p->nCutsAlloc++; p->nCutsCur++; if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc ) p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc; return pCut; } /**Function************************************************************* Synopsis [Recybles the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut ) { p->nCutsDealloc++; p->nCutsCur--; if ( pCut->nLeaves == 1 ) p->nCutsTriv--; Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); } /**Function************************************************************* Synopsis [Compares two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ) { int i; if ( pCut1->nLeaves < pCut2->nLeaves ) return -1; if ( pCut1->nLeaves > pCut2->nLeaves ) return 1; for ( i = 0; i < (int)pCut1->nLeaves; i++ ) { if ( pCut1->pLeaves[i] < pCut2->pLeaves[i] ) return -1; if ( pCut1->pLeaves[i] > pCut2->pLeaves[i] ) return 1; } return 0; } /**Function************************************************************* Synopsis [Duplicates the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList ) { Cut_Cut_t * pHead = NULL, ** ppTail = &pHead; Cut_Cut_t * pTemp, * pCopy; if ( pList == NULL ) return NULL; Cut_ListForEachCut( pList, pTemp ) { pCopy = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); memcpy( pCopy, pTemp, p->EntrySize ); *ppTail = pCopy; ppTail = &pCopy->pNext; } *ppTail = NULL; return pHead; } /**Function************************************************************* Synopsis [Recycles the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList ) { Cut_Cut_t * pCut, * pCut2; Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); } /**Function************************************************************* Synopsis [Counts the number of cuts in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_CutCountList( Cut_Cut_t * pList ) { int Counter = 0; Cut_ListForEachCut( pList, pList ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Merges two NULL-terminated linked lists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 ) { Cut_Cut_t * pList = NULL, ** ppTail = &pList; Cut_Cut_t * pCut; while ( pList1 && pList2 ) { if ( Cut_CutCompare(pList1, pList2) < 0 ) { pCut = pList1; pList1 = pList1->pNext; } else { pCut = pList2; pList2 = pList2->pNext; } *ppTail = pCut; ppTail = &pCut->pNext; } *ppTail = pList1? pList1: pList2; return pList; } /**Function************************************************************* Synopsis [Sets the number of the cuts in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CutNumberList( Cut_Cut_t * pList ) { Cut_Cut_t * pCut; int i = 0; Cut_ListForEachCut( pList, pCut ) pCut->Num0 = i++; } /**Function************************************************************* Synopsis [Creates the trivial cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node ) { Cut_Cut_t * pCut; if ( p->pParams->fSeq ) Node <<= CUT_SHIFT; pCut = Cut_CutAlloc( p ); pCut->nLeaves = 1; pCut->pLeaves[0] = Node; pCut->uSign = Cut_NodeSign( Node ); if ( p->pParams->fTruth ) { /* if ( pCut->nVarsMax == 4 ) Cut_CutWriteTruth( pCut, p->uTruthVars[0] ); else Extra_BitCopy( pCut->nLeaves, p->uTruths[0], (uint8*)Cut_CutReadTruth(pCut) ); */ unsigned * pTruth = Cut_CutReadTruth(pCut); int i; for ( i = 0; i < p->nTruthWords; i++ ) pTruth[i] = 0xAAAAAAAA; } p->nCutsTriv++; return pCut; } /**Function************************************************************* Synopsis [Print the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq ) { int i; assert( pCut->nLeaves > 0 ); printf( "%d : {", pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { if ( fSeq ) { printf( " %d", pCut->pLeaves[i] >> CUT_SHIFT ); if ( pCut->pLeaves[i] & CUT_MASK ) printf( "(%d)", pCut->pLeaves[i] & CUT_MASK ); } else printf( " %d", pCut->pLeaves[i] ); } printf( " }" ); // printf( "\nSign = " ); // Extra_PrintBinary( stdout, &pCut->uSign, 32 ); } /**Function************************************************************* Synopsis [Print the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq ) { Cut_Cut_t * pCut; for ( pCut = pList; pCut; pCut = pCut->pNext ) Cut_CutPrint( pCut, fSeq ), printf( "\n" ); } /**Function************************************************************* Synopsis [Consider dropping cuts if they are useless by now.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { printf( "\n" ); printf( "%d : %5d %5d %5d %5d %5d\n", pCut0->nLeaves, pCut0->nLeaves > 0 ? pCut0->pLeaves[0] : -1, pCut0->nLeaves > 1 ? pCut0->pLeaves[1] : -1, pCut0->nLeaves > 2 ? pCut0->pLeaves[2] : -1, pCut0->nLeaves > 3 ? pCut0->pLeaves[3] : -1, pCut0->nLeaves > 4 ? pCut0->pLeaves[4] : -1 ); printf( "%d : %5d %5d %5d %5d %5d\n", pCut1->nLeaves, pCut1->nLeaves > 0 ? pCut1->pLeaves[0] : -1, pCut1->nLeaves > 1 ? pCut1->pLeaves[1] : -1, pCut1->nLeaves > 2 ? pCut1->pLeaves[2] : -1, pCut1->nLeaves > 3 ? pCut1->pLeaves[3] : -1, pCut1->nLeaves > 4 ? pCut1->pLeaves[4] : -1 ); if ( pCut == NULL ) printf( "Cannot merge\n" ); else printf( "%d : %5d %5d %5d %5d %5d\n", pCut->nLeaves, pCut->nLeaves > 0 ? pCut->pLeaves[0] : -1, pCut->nLeaves > 1 ? pCut->pLeaves[1] : -1, pCut->nLeaves > 2 ? pCut->pLeaves[2] : -1, pCut->nLeaves > 3 ? pCut->pLeaves[3] : -1, pCut->nLeaves > 4 ? pCut->pLeaves[4] : -1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutExpand.c000066400000000000000000000161551300674244400235400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutExpand.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Computes the truth table of the cut after expansion.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutExpand.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define CUT_CELL_MVAR 9 //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) { unsigned uPhase = 0; int i, k; for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) { if ( k == (int)pCut1->nLeaves ) break; if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) continue; assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); uPhase |= (1 << i); k++; } return uPhase; } /**Function************************************************************* Synopsis [Computes the truth table of the composition of cuts.] Description [Inputs are: - a factor cut (truth table is stored inside) - a node in the factor cut - a tree cut to be substituted (truth table is stored inside) - the resulting cut (truth table will be filled in). Note that all cuts, including the resulting one, should be already computed and the nodes should be stored in the ascending order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_TruthCompose( Cut_Cut_t * pCutF, int Node, Cut_Cut_t * pCutT, Cut_Cut_t * pCutRes ) { static unsigned uCof0[1<<(CUT_CELL_MVAR-5)]; static unsigned uCof1[1<<(CUT_CELL_MVAR-5)]; static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; unsigned * pIn, * pOut, * pTemp; unsigned uPhase; int NodeIndex, i, k; // sanity checks assert( pCutF->nVarsMax == pCutT->nVarsMax ); assert( pCutF->nVarsMax == pCutRes->nVarsMax ); assert( pCutF->nVarsMax <= CUT_CELL_MVAR ); // the factor cut (pCutF) should have its nodes sorted in the ascending order assert( pCutF->nLeaves <= pCutF->nVarsMax ); for ( i = 0; i < (int)pCutF->nLeaves - 1; i++ ) assert( pCutF->pLeaves[i] < pCutF->pLeaves[i+1] ); // the tree cut (pCutT) should have its nodes sorted in the ascending order assert( pCutT->nLeaves <= pCutT->nVarsMax ); for ( i = 0; i < (int)pCutT->nLeaves - 1; i++ ) assert( pCutT->pLeaves[i] < pCutT->pLeaves[i+1] ); // the resulting cut (pCutRes) should have its nodes sorted in the ascending order assert( pCutRes->nLeaves <= pCutRes->nVarsMax ); for ( i = 0; i < (int)pCutRes->nLeaves - 1; i++ ) assert( pCutRes->pLeaves[i] < pCutRes->pLeaves[i+1] ); // make sure that every node in pCutF (except Node) appears in pCutRes for ( i = 0; i < (int)pCutF->nLeaves; i++ ) { if ( pCutF->pLeaves[i] == Node ) continue; for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) if ( pCutF->pLeaves[i] == pCutRes->pLeaves[k] ) break; assert( k < (int)pCutRes->nLeaves ); // node i from pCutF is not found in pCutRes!!! } // make sure that every node in pCutT appears in pCutRes for ( i = 0; i < (int)pCutT->nLeaves; i++ ) { for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) if ( pCutT->pLeaves[i] == pCutRes->pLeaves[k] ) break; assert( k < (int)pCutRes->nLeaves ); // node i from pCutT is not found in pCutRes!!! } // find the index of the given node in the factor cut NodeIndex = -1; for ( NodeIndex = 0; NodeIndex < (int)pCutF->nLeaves; NodeIndex++ ) if ( pCutF->pLeaves[NodeIndex] == Node ) break; assert( NodeIndex >= 0 ); // Node should be in pCutF // copy the truth table Extra_TruthCopy( uTemp, Cut_CutReadTruth(pCutF), pCutF->nLeaves ); // bubble-move the NodeIndex variable to be the last one (the most significant one) pIn = uTemp; pOut = uCof0; // uCof0 is used for temporary storage here for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) { Extra_TruthSwapAdjacentVars( pOut, pIn, pCutF->nLeaves, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; } if ( (pCutF->nLeaves - 1 - NodeIndex) & 1 ) Extra_TruthCopy( pOut, pIn, pCutF->nLeaves ); // the result of stretching is in uTemp // cofactor the factor cut with respect to the node Extra_TruthCopy( uCof0, uTemp, pCutF->nLeaves ); Extra_TruthCofactor0( uCof0, pCutF->nLeaves, pCutF->nLeaves-1 ); Extra_TruthCopy( uCof1, uTemp, pCutF->nLeaves ); Extra_TruthCofactor1( uCof1, pCutF->nLeaves, pCutF->nLeaves-1 ); // temporarily shrink the factor cut's variables by removing Node for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) pCutF->pLeaves[i] = pCutF->pLeaves[i+1]; pCutF->nLeaves--; // spread out the cofactors' truth tables to the same var order as the resulting cut uPhase = Cut_TruthPhase(pCutRes, pCutF); assert( Extra_WordCountOnes(uPhase) == (int)pCutF->nLeaves ); Extra_TruthStretch( uTemp, uCof0, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); Extra_TruthCopy( uCof0, uTemp, pCutF->nVarsMax ); Extra_TruthStretch( uTemp, uCof1, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); Extra_TruthCopy( uCof1, uTemp, pCutF->nVarsMax ); // spread out the tree cut's truth table to the same var order as the resulting cut uPhase = Cut_TruthPhase(pCutRes, pCutT); assert( Extra_WordCountOnes(uPhase) == (int)pCutT->nLeaves ); Extra_TruthStretch( uTemp, Cut_CutReadTruth(pCutT), pCutT->nLeaves, pCutT->nVarsMax, uPhase ); // create the resulting truth table pTemp = Cut_CutReadTruth(pCutRes); for ( i = Extra_TruthWordNum(pCutRes->nLeaves)-1; i >= 0; i-- ) pTemp[i] = (uCof0[i] & ~uTemp[i]) | (uCof1[i] & uTemp[i]); // undo the removal of the node from the cut for ( i = (int)pCutF->nLeaves - 1; i >= NodeIndex; --i ) pCutF->pLeaves[i+1] = pCutF->pLeaves[i]; pCutF->pLeaves[NodeIndex] = Node; pCutF->nLeaves++; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutInt.h000066400000000000000000000163471300674244400230630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__cut__cutInt_h #define ABC__opt__cut__cutInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "misc/extra/extra.h" #include "misc/vec/vec.h" #include "cut.h" #include "cutList.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Cut_HashTableStruct_t_ Cut_HashTable_t; struct Cut_ManStruct_t_ { // user preferences Cut_Params_t * pParams; // computation parameters Vec_Int_t * vFanCounts; // the array of fanout counters Vec_Int_t * vNodeAttrs; // node attributes (1 = global; 0 = local) // storage for cuts Vec_Ptr_t * vCutsNew; // new cuts by node ID Vec_Ptr_t * vCutsOld; // old cuts by node ID Vec_Ptr_t * vCutsTemp; // temp cuts for cutset nodes by cutset node number // memory management Extra_MmFixed_t * pMmCuts; int EntrySize; int nTruthWords; // temporary variables Cut_Cut_t * pReady; Vec_Ptr_t * vTemp; int fCompl0; int fCompl1; int fSimul; int nNodeCuts; Cut_Cut_t * pStore0[2]; Cut_Cut_t * pStore1[2]; Cut_Cut_t * pCompareOld; Cut_Cut_t * pCompareNew; unsigned * puTemp[4]; // record of the cut computation Vec_Int_t * vNodeCuts; // the number of cuts for each node Vec_Int_t * vNodeStarts; // the number of the starting cut of each node Vec_Int_t * vCutPairs; // the pairs of parent cuts for each cut // minimum delay mapping with the given cuts Vec_Ptr_t * vCutsMax; Vec_Int_t * vDelays; Vec_Int_t * vDelays2; int nDelayMin; // statistics int nCutsCur; int nCutsAlloc; int nCutsDealloc; int nCutsPeak; int nCutsTriv; int nCutsFilter; int nCutsLimit; int nNodes; int nNodesDag; int nNodesNoCuts; // runtime abctime timeMerge; abctime timeUnion; abctime timeTruth; abctime timeFilter; abctime timeHash; abctime timeMap; }; // iterator through all the cuts of the list #define Cut_ListForEachCut( pList, pCut ) \ for ( pCut = pList; \ pCut; \ pCut = pCut->pNext ) #define Cut_ListForEachCutStop( pList, pCut, pStop ) \ for ( pCut = pList; \ pCut != pStop; \ pCut = pCut->pNext ) #define Cut_ListForEachCutSafe( pList, pCut, pCut2 ) \ for ( pCut = pList, \ pCut2 = pCut? pCut->pNext: NULL; \ pCut; \ pCut = pCut2, \ pCut2 = pCut? pCut->pNext: NULL ) //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // computes signature of the node static inline unsigned Cut_NodeSign( int Node ) { return (1 << (Node % 31)); } static inline int Cut_TruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cutCut.c ==========================================================*/ extern Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p ); extern void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut ); extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ); extern Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList ); extern void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList ); extern Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 ); extern void Cut_CutNumberList( Cut_Cut_t * pList ); extern Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node ); extern void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); /*=== cutMerge.c ==========================================================*/ extern Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); /*=== cutNode.c ==========================================================*/ extern void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ); extern int Cut_CutListVerify( Cut_Cut_t * pList ); /*=== cutTable.c ==========================================================*/ extern Cut_HashTable_t * Cut_TableStart( int Size ); extern void Cut_TableStop( Cut_HashTable_t * pTable ); extern int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t * pCut, int fStore ); extern void Cut_TableClear( Cut_HashTable_t * pTable ); extern int Cut_TableReadTime( Cut_HashTable_t * pTable ); /*=== cutTruth.c ==========================================================*/ extern void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutList.h000066400000000000000000000136651300674244400232440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutList.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Implementation of layered listed list of cuts.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutList.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__cut__cutList_h #define ABC__opt__cut__cutList_h ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Cut_ListStruct_t_ Cut_List_t; struct Cut_ListStruct_t_ { Cut_Cut_t * pHead[CUT_SIZE_MAX+1]; Cut_Cut_t ** ppTail[CUT_SIZE_MAX+1]; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Start the cut list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cut_ListStart( Cut_List_t * p ) { int i; for ( i = 1; i <= CUT_SIZE_MAX; i++ ) { p->pHead[i] = 0; p->ppTail[i] = &p->pHead[i]; } } /**Function************************************************************* Synopsis [Adds one cut to the cut list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut ) { assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX ); *p->ppTail[pCut->nLeaves] = pCut; p->ppTail[pCut->nLeaves] = &pCut->pNext; } /**Function************************************************************* Synopsis [Adds one cut to the cut list while preserving order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cut_ListAdd2( Cut_List_t * p, Cut_Cut_t * pCut ) { extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ); Cut_Cut_t * pTemp, ** ppSpot; assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX ); if ( p->pHead[pCut->nLeaves] != NULL ) { ppSpot = &p->pHead[pCut->nLeaves]; for ( pTemp = p->pHead[pCut->nLeaves]; pTemp; pTemp = pTemp->pNext ) { if ( Cut_CutCompare(pCut, pTemp) < 0 ) { *ppSpot = pCut; pCut->pNext = pTemp; return; } else ppSpot = &pTemp->pNext; } } *p->ppTail[pCut->nLeaves] = pCut; p->ppTail[pCut->nLeaves] = &pCut->pNext; } /**Function************************************************************* Synopsis [Derive the super list from the linked list of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cut_ListDerive( Cut_List_t * p, Cut_Cut_t * pList ) { Cut_Cut_t * pPrev; int nLeaves; Cut_ListStart( p ); while ( pList != NULL ) { nLeaves = pList->nLeaves; p->pHead[nLeaves] = pList; for ( pPrev = pList, pList = pList->pNext; pList; pPrev = pList, pList = pList->pNext ) if ( nLeaves < (int)pList->nLeaves ) break; p->ppTail[nLeaves] = &pPrev->pNext; pPrev->pNext = NULL; } } /**Function************************************************************* Synopsis [Adds the second list to the first list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cut_ListAddList( Cut_List_t * pOld, Cut_List_t * pNew ) { int i; for ( i = 1; i <= CUT_SIZE_MAX; i++ ) { if ( pNew->pHead[i] == NULL ) continue; *pOld->ppTail[i] = pNew->pHead[i]; pOld->ppTail[i] = pNew->ppTail[i]; } } /**Function************************************************************* Synopsis [Returns the cut list linked into one sequence of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cut_Cut_t * Cut_ListFinish( Cut_List_t * p ) { Cut_Cut_t * pHead = NULL, ** ppTail = &pHead; int i; for ( i = 1; i <= CUT_SIZE_MAX; i++ ) { if ( p->pHead[i] == NULL ) continue; *ppTail = p->pHead[i]; ppTail = p->ppTail[i]; } *ppTail = NULL; return pHead; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutMan.c000066400000000000000000000226771300674244400230420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Cut manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern void Npn_StartTruth8( uint8 uTruths[][32] ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the cut manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams ) { Cut_Man_t * p; // extern int nTruthDsd; // nTruthDsd = 0; assert( pParams->nVarsMax >= 3 && pParams->nVarsMax <= CUT_SIZE_MAX ); p = ABC_ALLOC( Cut_Man_t, 1 ); memset( p, 0, sizeof(Cut_Man_t) ); // set and correct parameters p->pParams = pParams; // prepare storage for cuts p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax ); Vec_PtrFill( p->vCutsNew, pParams->nIdsMax, NULL ); // prepare storage for sequential cuts if ( pParams->fSeq ) { p->pParams->fFilter = 1; p->vCutsOld = Vec_PtrAlloc( pParams->nIdsMax ); Vec_PtrFill( p->vCutsOld, pParams->nIdsMax, NULL ); p->vCutsTemp = Vec_PtrAlloc( pParams->nCutSet ); Vec_PtrFill( p->vCutsTemp, pParams->nCutSet, NULL ); if ( pParams->fTruth && pParams->nVarsMax > 5 ) { pParams->fTruth = 0; printf( "Skipping computation of truth tables for sequential cuts with more than 5 inputs.\n" ); } } // entry size p->EntrySize = sizeof(Cut_Cut_t) + pParams->nVarsMax * sizeof(int); if ( pParams->fTruth ) { if ( pParams->nVarsMax > 14 ) { pParams->fTruth = 0; printf( "Skipping computation of truth table for more than %d inputs.\n", 14 ); } else { p->nTruthWords = Cut_TruthWords( pParams->nVarsMax ); p->EntrySize += p->nTruthWords * sizeof(unsigned); } 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; } // enable cut computation recording if ( pParams->fRecord ) { p->vNodeCuts = Vec_IntStart( pParams->nIdsMax ); p->vNodeStarts = Vec_IntStart( pParams->nIdsMax ); p->vCutPairs = Vec_IntAlloc( 0 ); } // allocate storage for delays if ( pParams->fMap && !p->pParams->fSeq ) { p->vDelays = Vec_IntStart( pParams->nIdsMax ); p->vDelays2 = Vec_IntStart( pParams->nIdsMax ); p->vCutsMax = Vec_PtrStart( pParams->nIdsMax ); } // memory for cuts p->pMmCuts = Extra_MmFixedStart( p->EntrySize ); p->vTemp = Vec_PtrAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [Stops the cut manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_ManStop( Cut_Man_t * p ) { if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew ); if ( p->vCutsOld ) Vec_PtrFree( p->vCutsOld ); if ( p->vCutsTemp ) Vec_PtrFree( p->vCutsTemp ); if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts ); if ( p->vTemp ) Vec_PtrFree( p->vTemp ); if ( p->vCutsMax ) Vec_PtrFree( p->vCutsMax ); if ( p->vDelays ) Vec_IntFree( p->vDelays ); if ( p->vDelays2 ) Vec_IntFree( p->vDelays2 ); if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts ); if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts ); if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs ); if ( p->puTemp[0] ) ABC_FREE( p->puTemp[0] ); Extra_MmFixedStop( p->pMmCuts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_ManPrintStats( Cut_Man_t * p ) { if ( p->pReady ) { Cut_CutRecycle( p, p->pReady ); p->pReady = NULL; } printf( "Cut computation statistics:\n" ); printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCutsCur-p->nCutsTriv, p->nCutsTriv ); printf( "Peak cuts = %8d.\n", p->nCutsPeak ); printf( "Total allocated = %8d.\n", p->nCutsAlloc ); printf( "Total deallocated = %8d.\n", p->nCutsDealloc ); printf( "Cuts filtered = %8d.\n", p->nCutsFilter ); printf( "Nodes saturated = %8d. (Max cuts = %d.)\n", p->nCutsLimit, p->pParams->nKeepMax ); printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes ); printf( "The cut size = %8d bytes.\n", p->EntrySize ); printf( "Peak memory = %8.2f MB.\n", (float)p->nCutsPeak * p->EntrySize / (1<<20) ); printf( "Total nodes = %8d.\n", p->nNodes ); if ( p->pParams->fDag || p->pParams->fTree ) { printf( "DAG nodes = %8d.\n", p->nNodesDag ); printf( "Tree nodes = %8d.\n", p->nNodes - p->nNodesDag ); } printf( "Nodes w/o cuts = %8d.\n", p->nNodesNoCuts ); if ( p->pParams->fMap && !p->pParams->fSeq ) printf( "Mapping delay = %8d.\n", p->nDelayMin ); ABC_PRT( "Merge ", p->timeMerge ); ABC_PRT( "Union ", p->timeUnion ); ABC_PRT( "Filter", p->timeFilter ); ABC_PRT( "Truth ", p->timeTruth ); ABC_PRT( "Map ", p->timeMap ); // printf( "Nodes = %d. Multi = %d. Cuts = %d. Multi = %d.\n", // p->nNodes, p->nNodesMulti, p->nCutsCur-p->nCutsTriv, p->nCutsMulti ); // printf( "Count0 = %d. Count1 = %d. Count2 = %d.\n\n", p->Count0, p->Count1, p->Count2 ); } /**Function************************************************************* Synopsis [Prints some interesting stats.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, abctime TimeTotal ) { FILE * pTable; pTable = fopen( "cut_stats.txt", "a+" ); fprintf( pTable, "%-20s ", pFileName ); fprintf( pTable, "%8d ", p->nNodes ); fprintf( pTable, "%6.1f ", ((float)(p->nCutsCur))/p->nNodes ); fprintf( pTable, "%6.2f ", ((float)(100.0 * p->nCutsLimit))/p->nNodes ); fprintf( pTable, "%6.2f ", (float)p->nCutsPeak * p->EntrySize / (1<<20) ); fprintf( pTable, "%6.2f ", (float)(TimeTotal)/(float)(CLOCKS_PER_SEC) ); fprintf( pTable, "\n" ); fclose( pTable ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts ) { p->vFanCounts = vFanCounts; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vNodeAttrs ) { p->vNodeAttrs = vNodeAttrs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_ManReadVarsMax( Cut_Man_t * p ) { return p->pParams->nVarsMax; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p ) { return p->pParams; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p ) { return p->vNodeAttrs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_ManIncrementDagNodes( Cut_Man_t * p ) { p->nNodesDag++; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutMerge.c000066400000000000000000000454041300674244400233570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutMerge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Procedure to merge two cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Merges two cuts.] Description [This procedure works.] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}}; Cut_Cut_t * pRes; int * pRow; int nLeaves0, nLeaves1, Limit; int i, k, Count, nNodes; assert( pCut0->nLeaves >= pCut1->nLeaves ); // the case of the largest cut sizes Limit = p->pParams->nVarsMax; nLeaves0 = pCut0->nLeaves; nLeaves1 = pCut1->nLeaves; if ( nLeaves0 == Limit && nLeaves1 == Limit ) { for ( i = 0; i < nLeaves0; i++ ) if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) return NULL; pRes = Cut_CutAlloc( p ); for ( i = 0; i < nLeaves0; i++ ) pRes->pLeaves[i] = pCut0->pLeaves[i]; pRes->nLeaves = nLeaves0; return pRes; } // the case when one of the cuts is the largest if ( nLeaves0 == Limit ) { for ( i = 0; i < nLeaves1; i++ ) { for ( k = nLeaves0 - 1; k >= 0; k-- ) if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) break; if ( k == -1 ) // did not find return NULL; } pRes = Cut_CutAlloc( p ); for ( i = 0; i < nLeaves0; i++ ) pRes->pLeaves[i] = pCut0->pLeaves[i]; pRes->nLeaves = nLeaves0; return pRes; } // other cases nNodes = nLeaves0; for ( i = 0; i < nLeaves1; i++ ) { for ( k = nLeaves0 - 1; k >= 0; k-- ) { if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] ) continue; if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] ) { pRow = M[k+1]; if ( pRow[0] == 0 ) pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; else if ( pRow[1] == 0 ) pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; else if ( pRow[2] == 0 ) pRow[2] = pCut1->pLeaves[i]; else assert( 0 ); if ( ++nNodes > Limit ) { for ( i = 0; i <= nLeaves0; i++ ) M[i][0] = 0; return NULL; } } break; } if ( k == -1 ) { pRow = M[0]; if ( pRow[0] == 0 ) pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; else if ( pRow[1] == 0 ) pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; else if ( pRow[2] == 0 ) pRow[2] = pCut1->pLeaves[i]; else assert( 0 ); if ( ++nNodes > Limit ) { for ( i = 0; i <= nLeaves0; i++ ) M[i][0] = 0; return NULL; } continue; } } pRes = Cut_CutAlloc( p ); for ( Count = 0, i = 0; i <= nLeaves0; i++ ) { if ( i > 0 ) pRes->pLeaves[Count++] = pCut0->pLeaves[i-1]; pRow = M[i]; if ( pRow[0] ) { pRes->pLeaves[Count++] = pRow[0]; if ( pRow[1] ) { pRes->pLeaves[Count++] = pRow[1]; if ( pRow[2] ) pRes->pLeaves[Count++] = pRow[2]; } pRow[0] = 0; } } assert( Count == nNodes ); pRes->nLeaves = nNodes; return pRes; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { Cut_Cut_t * pRes; int * pLeaves; int Limit, nLeaves0, nLeaves1; int i, k, c; assert( pCut0->nLeaves >= pCut1->nLeaves ); // consider two cuts nLeaves0 = pCut0->nLeaves; nLeaves1 = pCut1->nLeaves; // the case of the largest cut sizes Limit = p->pParams->nVarsMax; if ( nLeaves0 == Limit && nLeaves1 == Limit ) { for ( i = 0; i < nLeaves0; i++ ) if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) return NULL; pRes = Cut_CutAlloc( p ); for ( i = 0; i < nLeaves0; i++ ) pRes->pLeaves[i] = pCut0->pLeaves[i]; pRes->nLeaves = pCut0->nLeaves; return pRes; } // the case when one of the cuts is the largest if ( nLeaves0 == Limit ) { for ( i = 0; i < nLeaves1; i++ ) { for ( k = nLeaves0 - 1; k >= 0; k-- ) if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) break; if ( k == -1 ) // did not find return NULL; } pRes = Cut_CutAlloc( p ); for ( i = 0; i < nLeaves0; i++ ) pRes->pLeaves[i] = pCut0->pLeaves[i]; pRes->nLeaves = pCut0->nLeaves; return pRes; } // prepare the cut if ( p->pReady == NULL ) p->pReady = Cut_CutAlloc( p ); pLeaves = p->pReady->pLeaves; // compare two cuts with different numbers i = k = 0; for ( c = 0; c < Limit; c++ ) { if ( k == nLeaves1 ) { if ( i == nLeaves0 ) { p->pReady->nLeaves = c; pRes = p->pReady; p->pReady = NULL; return pRes; } pLeaves[c] = pCut0->pLeaves[i++]; continue; } if ( i == nLeaves0 ) { if ( k == nLeaves1 ) { p->pReady->nLeaves = c; pRes = p->pReady; p->pReady = NULL; return pRes; } pLeaves[c] = pCut1->pLeaves[k++]; continue; } if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) { pLeaves[c] = pCut0->pLeaves[i++]; continue; } if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) { pLeaves[c] = pCut1->pLeaves[k++]; continue; } pLeaves[c] = pCut0->pLeaves[i++]; k++; } if ( i < nLeaves0 || k < nLeaves1 ) return NULL; p->pReady->nLeaves = c; pRes = p->pReady; p->pReady = NULL; return pRes; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutMergeTwo3( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { Cut_Cut_t * pRes; int * pLeaves; int Limit, nLeaves0, nLeaves1; int i, k, c; assert( pCut0->nLeaves >= pCut1->nLeaves ); // prepare the cut if ( p->pReady == NULL ) p->pReady = Cut_CutAlloc( p ); pLeaves = p->pReady->pLeaves; // consider two cuts Limit = p->pParams->nVarsMax; nLeaves0 = pCut0->nLeaves; nLeaves1 = pCut1->nLeaves; if ( nLeaves0 == Limit ) { // the case when one of the cuts is the largest if ( nLeaves1 == Limit ) { // the case when both cuts are the largest for ( i = 0; i < nLeaves0; i++ ) { pLeaves[i] = pCut0->pLeaves[i]; if ( pLeaves[i] != pCut1->pLeaves[i] ) return NULL; } } else { for ( i = k = 0; i < nLeaves0; i++ ) { pLeaves[i] = pCut0->pLeaves[i]; if ( k == (int)nLeaves1 ) continue; if ( pLeaves[i] < pCut1->pLeaves[k] ) continue; if ( pLeaves[i] == pCut1->pLeaves[k++] ) continue; return NULL; } if ( k < nLeaves1 ) return NULL; } p->pReady->nLeaves = nLeaves0; pRes = p->pReady; p->pReady = NULL; return pRes; } // compare two cuts with different numbers i = k = 0; for ( c = 0; c < Limit; c++ ) { if ( k == nLeaves1 ) { if ( i == nLeaves0 ) { p->pReady->nLeaves = c; pRes = p->pReady; p->pReady = NULL; return pRes; } pLeaves[c] = pCut0->pLeaves[i++]; continue; } if ( i == nLeaves0 ) { if ( k == nLeaves1 ) { p->pReady->nLeaves = c; pRes = p->pReady; p->pReady = NULL; return pRes; } pLeaves[c] = pCut1->pLeaves[k++]; continue; } if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) { pLeaves[c] = pCut0->pLeaves[i++]; continue; } if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) { pLeaves[c] = pCut1->pLeaves[k++]; continue; } pLeaves[c] = pCut0->pLeaves[i++]; k++; } if ( i < nLeaves0 || k < nLeaves1 ) return NULL; p->pReady->nLeaves = c; pRes = p->pReady; p->pReady = NULL; return pRes; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutMergeTwo4( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { Cut_Cut_t * pRes; int * pLeaves; int i, k, min, NodeTemp, Limit, nTotal; assert( pCut0->nLeaves >= pCut1->nLeaves ); // prepare the cut if ( p->pReady == NULL ) p->pReady = Cut_CutAlloc( p ); pLeaves = p->pReady->pLeaves; // consider two cuts Limit = p->pParams->nVarsMax; if ( pCut0->nLeaves == (unsigned)Limit ) { // the case when one of the cuts is the largest if ( pCut1->nLeaves == (unsigned)Limit ) { // the case when both cuts are the largest for ( i = 0; i < (int)pCut0->nLeaves; i++ ) { pLeaves[i] = pCut0->pLeaves[i]; if ( pLeaves[i] != pCut1->pLeaves[i] ) return NULL; } } else { for ( i = k = 0; i < (int)pCut0->nLeaves; i++ ) { pLeaves[i] = pCut0->pLeaves[i]; if ( k == (int)pCut1->nLeaves ) continue; if ( pLeaves[i] < pCut1->pLeaves[k] ) continue; if ( pLeaves[i] == pCut1->pLeaves[k++] ) continue; return NULL; } if ( k < (int)pCut1->nLeaves ) return NULL; } p->pReady->nLeaves = pCut0->nLeaves; pRes = p->pReady; p->pReady = NULL; return pRes; } // count the number of unique entries in pCut1 nTotal = pCut0->nLeaves; for ( i = 0; i < (int)pCut1->nLeaves; i++ ) { // try to find this entry among the leaves of pCut0 for ( k = 0; k < (int)pCut0->nLeaves; k++ ) if ( pCut1->pLeaves[i] == pCut0->pLeaves[k] ) break; if ( k < (int)pCut0->nLeaves ) // found continue; // we found a new entry to add if ( nTotal == Limit ) return NULL; pLeaves[nTotal++] = pCut1->pLeaves[i]; } // we know that the feasible cut exists // add the starting entries for ( k = 0; k < (int)pCut0->nLeaves; k++ ) pLeaves[k] = pCut0->pLeaves[k]; // selection-sort the entries for ( i = 0; i < nTotal - 1; i++ ) { min = i; for ( k = i+1; k < nTotal; k++ ) if ( pLeaves[k] < pLeaves[min] ) min = k; NodeTemp = pLeaves[i]; pLeaves[i] = pLeaves[min]; pLeaves[min] = NodeTemp; } p->pReady->nLeaves = nTotal; pRes = p->pReady; p->pReady = NULL; return pRes; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [This procedure works.] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}}; Cut_Cut_t * pRes; int * pRow; unsigned uSign0, uSign1; int i, k, nNodes, Count; unsigned Limit = p->pParams->nVarsMax; assert( pCut0->nLeaves >= pCut1->nLeaves ); // the case of the largest cut sizes if ( pCut0->nLeaves == Limit && pCut1->nLeaves == Limit ) { for ( i = 0; i < (int)pCut0->nLeaves; i++ ) if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) return NULL; pRes = Cut_CutAlloc( p ); for ( i = 0; i < (int)pCut0->nLeaves; i++ ) pRes->pLeaves[i] = pCut0->pLeaves[i]; pRes->nLeaves = pCut0->nLeaves; return pRes; } // the case when one of the cuts is the largest if ( pCut0->nLeaves == Limit ) { if ( !p->pParams->fTruth ) { for ( i = 0; i < (int)pCut1->nLeaves; i++ ) { for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) break; if ( k == -1 ) // did not find return NULL; } pRes = Cut_CutAlloc( p ); } else { uSign1 = 0; for ( i = 0; i < (int)pCut1->nLeaves; i++ ) { for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) { uSign1 |= (1 << i); break; } if ( k == -1 ) // did not find return NULL; } pRes = Cut_CutAlloc( p ); pRes->Num1 = uSign1; } for ( i = 0; i < (int)pCut0->nLeaves; i++ ) pRes->pLeaves[i] = pCut0->pLeaves[i]; pRes->nLeaves = pCut0->nLeaves; return pRes; } // other cases nNodes = pCut0->nLeaves; for ( i = 0; i < (int)pCut1->nLeaves; i++ ) { for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) { if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] ) continue; if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] ) { pRow = M[k+1]; if ( pRow[0] == 0 ) pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; else if ( pRow[1] == 0 ) pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; else if ( pRow[2] == 0 ) pRow[2] = pCut1->pLeaves[i]; else assert( 0 ); if ( ++nNodes > (int)Limit ) { for ( i = 0; i <= (int)pCut0->nLeaves; i++ ) M[i][0] = 0; return NULL; } } break; } if ( k == -1 ) { pRow = M[0]; if ( pRow[0] == 0 ) pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; else if ( pRow[1] == 0 ) pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; else if ( pRow[2] == 0 ) pRow[2] = pCut1->pLeaves[i]; else assert( 0 ); if ( ++nNodes > (int)Limit ) { for ( i = 0; i <= (int)pCut0->nLeaves; i++ ) M[i][0] = 0; return NULL; } continue; } } pRes = Cut_CutAlloc( p ); if ( !p->pParams->fTruth ) { for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ ) { if ( i > 0 ) pRes->pLeaves[Count++] = pCut0->pLeaves[i-1]; pRow = M[i]; if ( pRow[0] ) { pRes->pLeaves[Count++] = pRow[0]; if ( pRow[1] ) { pRes->pLeaves[Count++] = pRow[1]; if ( pRow[2] ) pRes->pLeaves[Count++] = pRow[2]; } pRow[0] = 0; } } assert( Count == nNodes ); pRes->nLeaves = nNodes; /* // make sure that the cut is correct { for ( i = 1; i < (int)pRes->nLeaves; i++ ) if ( pRes->pLeaves[i-1] >= pRes->pLeaves[i] ) { int v = 0; } } */ return pRes; } uSign0 = uSign1 = 0; for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ ) { if ( i > 0 ) { uSign0 |= (1 << Count); pRes->pLeaves[Count++] = pCut1->pLeaves[i-1]; } pRow = M[i]; if ( pRow[0] ) { uSign1 |= (1 << Count); pRes->pLeaves[Count++] = pRow[0]; if ( pRow[1] ) { uSign1 |= (1 << Count); pRes->pLeaves[Count++] = pRow[1]; if ( pRow[2] ) { uSign1 |= (1 << Count); pRes->pLeaves[Count++] = pRow[2]; } } pRow[0] = 0; } } assert( Count == nNodes ); pRes->nLeaves = nNodes; pRes->Num1 = uSign1; pRes->Num0 = uSign0; return pRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutNode.c000066400000000000000000000772261300674244400232140ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutNode.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Procedures to compute cuts for a node.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ); static int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut ) { int i, k; for ( i = 0; i < (int)pDom->nLeaves; i++ ) { for ( k = 0; k < (int)pCut->nLeaves; k++ ) if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) break; if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut return 0; } // every node in pDom is contained in pCut return 1; } /**Function************************************************************* Synopsis [Filters cuts using dominance.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList ) { Cut_Cut_t * pListR, ** ppListR = &pListR; Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev; // save the first cut *ppListR = pList, ppListR = &pList->pNext; // try to filter out other cuts pPrev = pList; Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 ) { assert( pCut->nLeaves > 1 ); // go through all the previous cuts up to pCut Cut_ListForEachCutStop( pList->pNext, pDom, pCut ) { if ( pDom->nLeaves > pCut->nLeaves ) continue; if ( (pDom->uSign & pCut->uSign) != pDom->uSign ) continue; if ( Cut_CutCheckDominance( pDom, pCut ) ) break; } if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut { // make sure cuts are connected after removing pPrev->pNext = pCut->pNext; // recycle the cut Cut_CutRecycle( p, pCut ); } else // pDom is NOT contained in pCut - save pCut { *ppListR = pCut, ppListR = &pCut->pNext; pPrev = pCut; } } *ppListR = NULL; } /**Function************************************************************* Synopsis [Checks equality of one cut.] Description [Returns 1 if the cut is removed.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cut_CutFilterOneEqual( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut ) { Cut_Cut_t * pTemp; Cut_ListForEachCut( pSuperList->pHead[pCut->nLeaves], pTemp ) { // skip the non-contained cuts if ( pCut->uSign != pTemp->uSign ) continue; // check containment seriously if ( Cut_CutCheckDominance( pTemp, pCut ) ) { p->nCutsFilter++; Cut_CutRecycle( p, pCut ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Checks containment for one cut.] Description [Returns 1 if the cut is removed.] SideEffects [May remove other cuts in the set.] SeeAlso [] ***********************************************************************/ static inline int Cut_CutFilterOne( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut ) { Cut_Cut_t * pTemp, * pTemp2, ** ppTail; int a; // check if this cut is filtered out by smaller cuts for ( a = 2; a <= (int)pCut->nLeaves; a++ ) { Cut_ListForEachCut( pSuperList->pHead[a], pTemp ) { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) continue; // check containment seriously if ( Cut_CutCheckDominance( pTemp, pCut ) ) { p->nCutsFilter++; Cut_CutRecycle( p, pCut ); return 1; } } } // filter out other cuts using this one for ( a = pCut->nLeaves + 1; a <= (int)pCut->nVarsMax; a++ ) { ppTail = pSuperList->pHead + a; Cut_ListForEachCutSafe( pSuperList->pHead[a], pTemp, pTemp2 ) { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) { ppTail = &pTemp->pNext; continue; } // check containment seriously if ( Cut_CutCheckDominance( pCut, pTemp ) ) { p->nCutsFilter++; p->nNodeCuts--; // move the head if ( pSuperList->pHead[a] == pTemp ) pSuperList->pHead[a] = pTemp->pNext; // move the tail if ( pSuperList->ppTail[a] == &pTemp->pNext ) pSuperList->ppTail[a] = ppTail; // skip the given cut in the list *ppTail = pTemp->pNext; // recycle pTemp Cut_CutRecycle( p, pTemp ); } else ppTail = &pTemp->pNext; } assert( ppTail == pSuperList->ppTail[a] ); assert( *ppTail == NULL ); } return 0; } /**Function************************************************************* Synopsis [Checks if the cut is local and can be removed.] Description [Returns 1 if the cut is removed.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cut_CutFilterGlobal( Cut_Man_t * p, Cut_Cut_t * pCut ) { int a; if ( pCut->nLeaves == 1 ) return 0; for ( a = 0; a < (int)pCut->nLeaves; a++ ) if ( Vec_IntEntry( p->vNodeAttrs, pCut->pLeaves[a] ) ) // global return 0; // there is no global nodes, the cut should be removed p->nCutsFilter++; Cut_CutRecycle( p, pCut ); return 1; } /**Function************************************************************* Synopsis [Checks containment for one cut.] Description [Returns 1 if the cut is removed.] SideEffects [May remove other cuts in the set.] SeeAlso [] ***********************************************************************/ static inline int Cut_CutFilterOld( Cut_Man_t * p, Cut_Cut_t * pList, Cut_Cut_t * pCut ) { Cut_Cut_t * pPrev, * pTemp, * pTemp2, ** ppTail; // check if this cut is filtered out by smaller cuts pPrev = NULL; Cut_ListForEachCut( pList, pTemp ) { if ( pTemp->nLeaves > pCut->nLeaves ) break; pPrev = pTemp; // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) continue; // check containment seriously if ( Cut_CutCheckDominance( pTemp, pCut ) ) { p->nCutsFilter++; Cut_CutRecycle( p, pCut ); return 1; } } assert( pPrev->pNext == pTemp ); // filter out other cuts using this one ppTail = &pPrev->pNext; Cut_ListForEachCutSafe( pTemp, pTemp, pTemp2 ) { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) { ppTail = &pTemp->pNext; continue; } // check containment seriously if ( Cut_CutCheckDominance( pCut, pTemp ) ) { p->nCutsFilter++; p->nNodeCuts--; // skip the given cut in the list *ppTail = pTemp->pNext; // recycle pTemp Cut_CutRecycle( p, pTemp ); } else ppTail = &pTemp->pNext; } assert( *ppTail == NULL ); return 0; } /**Function************************************************************* Synopsis [Processes two cuts.] Description [Returns 1 if the limit has been reached.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList ) { Cut_Cut_t * pCut; // merge the cuts if ( pCut0->nLeaves >= pCut1->nLeaves ) pCut = Cut_CutMergeTwo( p, pCut0, pCut1 ); else pCut = Cut_CutMergeTwo( p, pCut1, pCut0 ); if ( pCut == NULL ) return 0; assert( p->pParams->fSeq || pCut->nLeaves > 1 ); // set the signature pCut->uSign = pCut0->uSign | pCut1->uSign; if ( p->pParams->fRecord ) pCut->Num0 = pCut0->Num0, pCut->Num1 = pCut1->Num0; // check containment if ( p->pParams->fFilter ) { if ( Cut_CutFilterOne(p, pSuperList, pCut) ) // if ( Cut_CutFilterOneEqual(p, pSuperList, pCut) ) return 0; if ( p->pParams->fSeq ) { if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) return 0; if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) return 0; } } if ( p->pParams->fGlobal ) { assert( p->vNodeAttrs != NULL ); if ( Cut_CutFilterGlobal( p, pCut ) ) return 0; } // compute the truth table if ( p->pParams->fTruth ) Cut_TruthCompute( p, pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 ); // add to the list Cut_ListAdd( pSuperList, pCut ); // return status (0 if okay; 1 if exceeded the limit) return ++p->nNodeCuts == p->pParams->nKeepMax; } /**Function************************************************************* Synopsis [Computes the cuts by merging cuts at two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ) { Cut_List_t Super, * pSuper = &Super; Cut_Cut_t * pList, * pCut; abctime clk; // start the number of cuts at the node p->nNodes++; p->nNodeCuts = 0; // prepare information for recording if ( p->pParams->fRecord ) { Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node0) ); Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node1) ); } // compute the cuts clk = Abc_Clock(); Cut_ListStart( pSuper ); Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv, TreeCode ); pList = Cut_ListFinish( pSuper ); p->timeMerge += Abc_Clock() - clk; // verify the result of cut computation // Cut_CutListVerify( pList ); // performing the recording if ( p->pParams->fRecord ) { Vec_IntWriteEntry( p->vNodeStarts, Node, Vec_IntSize(p->vCutPairs) ); Cut_ListForEachCut( pList, pCut ) Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) ); Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) ); } if ( p->pParams->fRecordAig ) { extern void Aig_RManRecord( unsigned * pTruth, int nVarsInit ); Cut_ListForEachCut( pList, pCut ) if ( Cut_CutReadLeaveNum(pCut) > 4 ) Aig_RManRecord( Cut_CutReadTruth(pCut), Cut_CutReadLeaveNum(pCut) ); } // check if the node is over the list if ( p->nNodeCuts == p->pParams->nKeepMax ) p->nCutsLimit++; // set the list at the node Vec_PtrFillExtra( p->vCutsNew, Node + 1, NULL ); assert( Cut_NodeReadCutsNew(p, Node) == NULL ); ///// // pList->pNext = NULL; ///// Cut_NodeWriteCutsNew( p, Node, pList ); // filter the cuts //clk = Abc_Clock(); // if ( p->pParams->fFilter ) // Cut_CutFilter( p, pList0 ); //p->timeFilter += Abc_Clock() - clk; // perform mapping of this node with these cuts clk = Abc_Clock(); if ( p->pParams->fMap && !p->pParams->fSeq ) { // int Delay1, Delay2; // Delay1 = Cut_NodeMapping( p, pList, Node, Node0, Node1 ); // Delay2 = Cut_NodeMapping2( p, pList, Node, Node0, Node1 ); // assert( Delay1 >= Delay2 ); Cut_NodeMapping( p, pList, Node, Node0, Node1 ); } p->timeMap += Abc_Clock() - clk; return pList; } /**Function************************************************************* Synopsis [Returns optimum delay mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) { Cut_Cut_t * pCut; int DelayMin, DelayCur, i; if ( pCuts == NULL ) p->nDelayMin = -1; if ( p->nDelayMin == -1 ) return -1; DelayMin = 1000000; Cut_ListForEachCut( pCuts, pCut ) { if ( pCut->nLeaves == 1 ) continue; DelayCur = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) if ( DelayCur < Vec_IntEntry(p->vDelays, pCut->pLeaves[i]) ) DelayCur = Vec_IntEntry(p->vDelays, pCut->pLeaves[i]); if ( DelayMin > DelayCur ) DelayMin = DelayCur; } if ( DelayMin == 1000000 ) { p->nDelayMin = -1; return -1; } DelayMin++; Vec_IntWriteEntry( p->vDelays, Node, DelayMin ); if ( p->nDelayMin < DelayMin ) p->nDelayMin = DelayMin; return DelayMin; } /**Function************************************************************* Synopsis [Returns optimum delay mapping using the largest cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) { Cut_Cut_t * pCut0, * pCut1, * pCut; int Delay0, Delay1, Delay; // get the fanin cuts Delay0 = Vec_IntEntry( p->vDelays2, Node0 ); Delay1 = Vec_IntEntry( p->vDelays2, Node1 ); pCut0 = (Delay0 == 0) ? (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 ) : (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node0 ); pCut1 = (Delay1 == 0) ? (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 ) : (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node1 ); if ( Delay0 == Delay1 ) Delay = (Delay0 == 0) ? Delay0 + 1: Delay0; else if ( Delay0 > Delay1 ) { Delay = Delay0; pCut1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 ); assert( pCut1->nLeaves == 1 ); } else // if ( Delay0 < Delay1 ) { Delay = Delay1; pCut0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 ); assert( pCut0->nLeaves == 1 ); } // merge the cuts if ( pCut0->nLeaves < pCut1->nLeaves ) pCut = Cut_CutMergeTwo( p, pCut1, pCut0 ); else pCut = Cut_CutMergeTwo( p, pCut0, pCut1 ); if ( pCut == NULL ) { Delay++; pCut = Cut_CutAlloc( p ); pCut->nLeaves = 2; pCut->pLeaves[0] = Node0 < Node1 ? Node0 : Node1; pCut->pLeaves[1] = Node0 < Node1 ? Node1 : Node0; } assert( Delay > 0 ); Vec_IntWriteEntry( p->vDelays2, Node, Delay ); Vec_PtrWriteEntry( p->vCutsMax, Node, pCut ); if ( p->nDelayMin < Delay ) p->nDelayMin = Delay; return Delay; } /**Function************************************************************* Synopsis [Computes area after mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ) { Cut_Cut_t * pCut; int i, Counter; if ( p->vCutsMax == NULL ) return 0; pCut = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsMax, Node ); if ( pCut == NULL || pCut->nLeaves == 1 ) return 0; Counter = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) Counter += Cut_ManMappingArea_rec( p, pCut->pLeaves[i] ); Vec_PtrWriteEntry( p->vCutsMax, Node, NULL ); return 1 + Counter; } /**Function************************************************************* Synopsis [Computes the cuts by merging cuts at two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ) { Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1; Cut_Cut_t * pStore0 = NULL, * pStore1 = NULL; // Suppress "might be used uninitialized" int i, nCutsOld, Limit; // start with the elementary cut if ( fTriv ) { // printf( "Creating trivial cut %d.\n", Node ); pTemp0 = Cut_CutCreateTriv( p, Node ); Cut_ListAdd( pSuper, pTemp0 ); p->nNodeCuts++; } // get the cut lists of children if ( pList0 == NULL || pList1 == NULL || (p->pParams->fLocal && TreeCode) ) return; // remember the old number of cuts nCutsOld = p->nCutsCur; Limit = p->pParams->nVarsMax; // get the simultation bit of the node p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul); // set temporary variables p->fCompl0 = fCompl0; p->fCompl1 = fCompl1; // if tree cuts are computed, make sure only the unit cuts propagate over the DAG nodes if ( TreeCode & 1 ) { assert( pList0->nLeaves == 1 ); pStore0 = pList0->pNext; pList0->pNext = NULL; } if ( TreeCode & 2 ) { assert( pList1->nLeaves == 1 ); pStore1 = pList1->pNext; pList1->pNext = NULL; } // find the point in the list where the max-var cuts begin Cut_ListForEachCut( pList0, pStop0 ) if ( pStop0->nLeaves == (unsigned)Limit ) break; Cut_ListForEachCut( pList1, pStop1 ) if ( pStop1->nLeaves == (unsigned)Limit ) break; // small by small Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) { if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) goto Quits; } // small by large Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) Cut_ListForEachCut( pStop1, pTemp1 ) { if ( (pTemp0->uSign & pTemp1->uSign) != pTemp0->uSign ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) goto Quits; } // small by large Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) Cut_ListForEachCut( pStop0, pTemp0 ) { if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) goto Quits; } // large by large Cut_ListForEachCut( pStop0, pTemp0 ) Cut_ListForEachCut( pStop1, pTemp1 ) { assert( pTemp0->nLeaves == (unsigned)Limit && pTemp1->nLeaves == (unsigned)Limit ); if ( pTemp0->uSign != pTemp1->uSign ) continue; for ( i = 0; i < Limit; i++ ) if ( pTemp0->pLeaves[i] != pTemp1->pLeaves[i] ) break; if ( i < Limit ) continue; if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) goto Quits; } if ( p->nNodeCuts == 0 ) p->nNodesNoCuts++; Quits: if ( TreeCode & 1 ) pList0->pNext = pStore0; if ( TreeCode & 2 ) pList1->pNext = pStore1; } /**Function************************************************************* Synopsis [Computes the cuts by unioning cuts at a choice node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ) { Cut_List_t Super, * pSuper = &Super; Cut_Cut_t * pList, * pListStart, * pCut, * pCut2; Cut_Cut_t * pTop = NULL; // Suppress "might be used uninitialized" int i, k, Node, Root, Limit = p->pParams->nVarsMax; abctime clk = Abc_Clock(); // start the new list Cut_ListStart( pSuper ); // remember the root node to save the resulting cuts Root = Vec_IntEntry( vNodes, 0 ); p->nNodeCuts = 1; // collect small cuts first Vec_PtrClear( p->vTemp ); Vec_IntForEachEntry( vNodes, Node, i ) { // get the cuts of this node pList = Cut_NodeReadCutsNew( p, Node ); Cut_NodeWriteCutsNew( p, Node, NULL ); assert( pList ); // remember the starting point pListStart = pList->pNext; pList->pNext = NULL; // save or recycle the elementary cut if ( i == 0 ) Cut_ListAdd( pSuper, pList ), pTop = pList; else Cut_CutRecycle( p, pList ); // save all the cuts that are smaller than the limit Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) { if ( pCut->nLeaves == (unsigned)Limit ) { Vec_PtrPush( p->vTemp, pCut ); break; } // check containment if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) continue; // set the complemented bit by comparing the first cut with the current cut pCut->fCompl = pTop->fSimul ^ pCut->fSimul; pListStart = pCut->pNext; pCut->pNext = NULL; // add to the list Cut_ListAdd( pSuper, pCut ); if ( ++p->nNodeCuts == p->pParams->nKeepMax ) { // recycle the rest of the cuts of this node Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle all cuts of other nodes Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) Cut_NodeFreeCuts( p, Node ); // recycle the saved cuts of other nodes Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, k ) Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); goto finish; } } } // collect larger cuts next Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, i ) { Cut_ListForEachCutSafe( pList, pCut, pCut2 ) { // check containment if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) continue; // set the complemented bit pCut->fCompl = pTop->fSimul ^ pCut->fSimul; pListStart = pCut->pNext; pCut->pNext = NULL; // add to the list Cut_ListAdd( pSuper, pCut ); if ( ++p->nNodeCuts == p->pParams->nKeepMax ) { // recycle the rest of the cuts Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle the saved cuts of other nodes Vec_PtrForEachEntryStart( Cut_Cut_t *, p->vTemp, pList, k, i+1 ) Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); goto finish; } } } finish : // set the cuts at the node assert( Cut_NodeReadCutsNew(p, Root) == NULL ); pList = Cut_ListFinish( pSuper ); Cut_NodeWriteCutsNew( p, Root, pList ); p->timeUnion += Abc_Clock() - clk; // filter the cuts //clk = Abc_Clock(); // if ( p->pParams->fFilter ) // Cut_CutFilter( p, pList ); //p->timeFilter += Abc_Clock() - clk; p->nNodes -= vNodes->nSize - 1; return pList; } /**Function************************************************************* Synopsis [Computes the cuts by unioning cuts at a choice node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ) { Cut_List_t Super, * pSuper = &Super; Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop; int i, k, Node, Root, Limit = p->pParams->nVarsMax; abctime clk = Abc_Clock(); // start the new list Cut_ListStart( pSuper ); // remember the root node to save the resulting cuts Root = Vec_IntEntry( vNodes, 0 ); p->nNodeCuts = 1; // store the original lists for comparison p->pCompareOld = Cut_NodeReadCutsOld( p, Root ); p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL; // get the topmost cut pTop = NULL; if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL ) pTop = Cut_NodeReadCutsNew( p, Root ); assert( pTop != NULL ); // collect small cuts first Vec_PtrClear( p->vTemp ); Vec_IntForEachEntry( vNodes, Node, i ) { // get the cuts of this node if ( i == 0 && CutSetNum >= 0 ) { pList = Cut_NodeReadCutsTemp( p, CutSetNum ); Cut_NodeWriteCutsTemp( p, CutSetNum, NULL ); } else { pList = Cut_NodeReadCutsNew( p, Node ); Cut_NodeWriteCutsNew( p, Node, NULL ); } if ( pList == NULL ) continue; // process the cuts if ( fFirst ) { // remember the starting point pListStart = pList->pNext; pList->pNext = NULL; // save or recycle the elementary cut if ( i == 0 ) Cut_ListAdd( pSuper, pList ); else Cut_CutRecycle( p, pList ); } else pListStart = pList; // save all the cuts that are smaller than the limit Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) { if ( pCut->nLeaves == (unsigned)Limit ) { Vec_PtrPush( p->vTemp, pCut ); break; } // check containment // if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) // continue; if ( p->pParams->fFilter ) { if ( Cut_CutFilterOne(p, pSuper, pCut) ) continue; if ( p->pParams->fSeq ) { if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) continue; if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) continue; } } // set the complemented bit by comparing the first cut with the current cut pCut->fCompl = pTop->fSimul ^ pCut->fSimul; pListStart = pCut->pNext; pCut->pNext = NULL; // add to the list Cut_ListAdd( pSuper, pCut ); if ( ++p->nNodeCuts == p->pParams->nKeepMax ) { // recycle the rest of the cuts of this node Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle all cuts of other nodes Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) Cut_NodeFreeCuts( p, Node ); // recycle the saved cuts of other nodes Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, k ) Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); goto finish; } } } // collect larger cuts next Vec_PtrForEachEntry( Cut_Cut_t *, p->vTemp, pList, i ) { Cut_ListForEachCutSafe( pList, pCut, pCut2 ) { // check containment // if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) // continue; if ( p->pParams->fFilter ) { if ( Cut_CutFilterOne(p, pSuper, pCut) ) continue; if ( p->pParams->fSeq ) { if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) continue; if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) continue; } } // set the complemented bit pCut->fCompl = pTop->fSimul ^ pCut->fSimul; pListStart = pCut->pNext; pCut->pNext = NULL; // add to the list Cut_ListAdd( pSuper, pCut ); if ( ++p->nNodeCuts == p->pParams->nKeepMax ) { // recycle the rest of the cuts Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); // recycle the saved cuts of other nodes Vec_PtrForEachEntryStart( Cut_Cut_t *, p->vTemp, pList, k, i+1 ) Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Cut_CutRecycle( p, pCut ); goto finish; } } } finish : // set the cuts at the node pList = Cut_ListFinish( pSuper ); // set the lists at the node // assert( Cut_NodeReadCutsNew(p, Root) == NULL ); // Cut_NodeWriteCutsNew( p, Root, pList ); if ( CutSetNum >= 0 ) { assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL ); Cut_NodeWriteCutsTemp( p, CutSetNum, pList ); } else { assert( Cut_NodeReadCutsNew(p, Root) == NULL ); Cut_NodeWriteCutsNew( p, Root, pList ); } p->timeUnion += Abc_Clock() - clk; // filter the cuts //clk = Abc_Clock(); // if ( p->pParams->fFilter ) // Cut_CutFilter( p, pList ); //p->timeFilter += Abc_Clock() - clk; // if ( fFirst ) // p->nNodes -= vNodes->nSize - 1; return pList; } /**Function************************************************************* Synopsis [Verifies that the list contains only non-dominated cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_CutListVerify( Cut_Cut_t * pList ) { Cut_Cut_t * pCut, * pDom; Cut_ListForEachCut( pList, pCut ) { Cut_ListForEachCutStop( pList, pDom, pCut ) { if ( Cut_CutCheckDominance( pDom, pCut ) ) { printf( "******************* These are contained cuts:\n" ); Cut_CutPrint( pDom, 1 ); Cut_CutPrint( pDom, 1 ); return 0; } } } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutOracle.c000066400000000000000000000274261300674244400235310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutOracle.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Procedures to compute cuts for a node using the oracle.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutOracle.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Cut_OracleStruct_t_ { // cut comptupatation parameters Cut_Params_t * pParams; Vec_Int_t * vFanCounts; int fSimul; // storage for cuts Vec_Ptr_t * vCutsNew; Vec_Ptr_t * vCuts0; Vec_Ptr_t * vCuts1; // oracle info Vec_Int_t * vNodeCuts; Vec_Int_t * vNodeStarts; Vec_Int_t * vCutPairs; // memory management Extra_MmFixed_t * pMmCuts; int EntrySize; int nTruthWords; // stats abctime timeTotal; int nCuts; int nCutsTriv; }; static Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p ); static Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node ); static Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the cut oracle.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan ) { Cut_Oracle_t * p; assert( pMan->pParams->nVarsMax >= 3 && pMan->pParams->nVarsMax <= CUT_SIZE_MAX ); assert( pMan->pParams->fRecord ); p = ABC_ALLOC( Cut_Oracle_t, 1 ); memset( p, 0, sizeof(Cut_Oracle_t) ); // set and correct parameters p->pParams = pMan->pParams; // transfer the recording info p->vNodeCuts = pMan->vNodeCuts; pMan->vNodeCuts = NULL; p->vNodeStarts = pMan->vNodeStarts; pMan->vNodeStarts = NULL; p->vCutPairs = pMan->vCutPairs; pMan->vCutPairs = NULL; // prepare storage for cuts p->vCutsNew = Vec_PtrAlloc( p->pParams->nIdsMax ); Vec_PtrFill( p->vCutsNew, p->pParams->nIdsMax, NULL ); p->vCuts0 = Vec_PtrAlloc( 100 ); p->vCuts1 = Vec_PtrAlloc( 100 ); // entry size p->EntrySize = sizeof(Cut_Cut_t) + p->pParams->nVarsMax * sizeof(int); if ( p->pParams->fTruth ) { if ( p->pParams->nVarsMax > 8 ) { p->pParams->fTruth = 0; printf( "Skipping computation of truth table for more than 8 inputs.\n" ); } else { p->nTruthWords = Cut_TruthWords( p->pParams->nVarsMax ); p->EntrySize += p->nTruthWords * sizeof(unsigned); } } // memory for cuts p->pMmCuts = Extra_MmFixedStart( p->EntrySize ); return p; } /**Function************************************************************* Synopsis [Stop the cut oracle.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_OracleStop( Cut_Oracle_t * p ) { // if ( p->pParams->fVerbose ) { printf( "Cut computation statistics with oracle:\n" ); printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCuts-p->nCutsTriv, p->nCutsTriv ); ABC_PRT( "Total time ", p->timeTotal ); } if ( p->vCuts0 ) Vec_PtrFree( p->vCuts0 ); if ( p->vCuts1 ) Vec_PtrFree( p->vCuts1 ); if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew ); if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts ); if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts ); if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts ); if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs ); Extra_MmFixedStop( p->pMmCuts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts ) { p->vFanCounts = vFanCounts; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_OracleReadDrop( Cut_Oracle_t * p ) { return p->pParams->fDrop; } /**Function************************************************************* Synopsis [Sets the trivial cut for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node ) { assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL ); Vec_PtrWriteEntry( p->vCutsNew, Node, Cut_CutTriv(p, Node) ); } /**Function************************************************************* Synopsis [Allocates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p ) { Cut_Cut_t * pCut; // cut allocation pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); memset( pCut, 0, sizeof(Cut_Cut_t) ); pCut->nVarsMax = p->pParams->nVarsMax; pCut->fSimul = p->fSimul; p->nCuts++; return pCut; } /**Function************************************************************* Synopsis [Creates the trivial cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node ) { Cut_Cut_t * pCut; pCut = Cut_CutStart( p ); pCut->nLeaves = 1; pCut->pLeaves[0] = Node; if ( p->pParams->fTruth ) { unsigned * pTruth = Cut_CutReadTruth(pCut); int i; for ( i = 0; i < p->nTruthWords; i++ ) pTruth[i] = 0xAAAAAAAA; } p->nCutsTriv++; return pCut; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) { Cut_Cut_t * pCut; int Limit, i, k, c; // create the leaves of the new cut pCut = Cut_CutStart( p ); Limit = p->pParams->nVarsMax; for ( i = k = c = 0; c < Limit; c++ ) { if ( k == (int)pCut1->nLeaves ) { if ( i == (int)pCut0->nLeaves ) { pCut->nLeaves = c; return pCut; } pCut->pLeaves[c] = pCut0->pLeaves[i++]; continue; } if ( i == (int)pCut0->nLeaves ) { if ( k == (int)pCut1->nLeaves ) { pCut->nLeaves = c; return pCut; } pCut->pLeaves[c] = pCut1->pLeaves[k++]; continue; } if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) { pCut->pLeaves[c] = pCut0->pLeaves[i++]; continue; } if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) { pCut->pLeaves[c] = pCut1->pLeaves[k++]; continue; } pCut->pLeaves[c] = pCut0->pLeaves[i++]; k++; } assert( i == (int)pCut0->nLeaves && k == (int)pCut1->nLeaves ); pCut->nLeaves = c; return pCut; } /**Function************************************************************* Synopsis [Reconstruct the cuts of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ) { Cut_Cut_t * pList = NULL, ** ppTail = &pList; Cut_Cut_t * pCut, * pCut0, * pCut1, * pList0, * pList1; int iCutStart, nCuts, i, Entry; abctime clk = Abc_Clock(); // get the cuts of the children pList0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node0 ); pList1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node1 ); assert( pList0 && pList1 ); // get the complemented attribute of the cut p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul); // collect the cuts Vec_PtrClear( p->vCuts0 ); Cut_ListForEachCut( pList0, pCut ) Vec_PtrPush( p->vCuts0, pCut ); Vec_PtrClear( p->vCuts1 ); Cut_ListForEachCut( pList1, pCut ) Vec_PtrPush( p->vCuts1, pCut ); // get the first and last cuts of this node nCuts = Vec_IntEntry(p->vNodeCuts, Node); iCutStart = Vec_IntEntry(p->vNodeStarts, Node); // create trivial cut assert( Vec_IntEntry(p->vCutPairs, iCutStart) == 0 ); pCut = Cut_CutTriv( p, Node ); *ppTail = pCut; ppTail = &pCut->pNext; // create other cuts for ( i = 1; i < nCuts; i++ ) { Entry = Vec_IntEntry( p->vCutPairs, iCutStart + i ); pCut0 = (Cut_Cut_t *)Vec_PtrEntry( p->vCuts0, Entry & 0xFFFF ); pCut1 = (Cut_Cut_t *)Vec_PtrEntry( p->vCuts1, Entry >> 16 ); pCut = Cut_CutMerge( p, pCut0, pCut1 ); *ppTail = pCut; ppTail = &pCut->pNext; // compute the truth table if ( p->pParams->fTruth ) Cut_TruthComputeOld( pCut, pCut0, pCut1, fCompl0, fCompl1 ); } *ppTail = NULL; // write the new cut assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL ); Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); p->timeTotal += Abc_Clock() - clk; return pList; } /**Function************************************************************* Synopsis [Deallocates the cuts at the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_OracleFreeCuts( Cut_Oracle_t * p, int Node ) { Cut_Cut_t * pList, * pCut, * pCut2; pList = (Cut_Cut_t *)Vec_PtrEntry( p->vCutsNew, Node ); if ( pList == NULL ) return; Cut_ListForEachCutSafe( pList, pCut, pCut2 ) Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); } /**Function************************************************************* Synopsis [Consider dropping cuts if they are useless by now.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node ) { int nFanouts; assert( p->vFanCounts ); nFanouts = Vec_IntEntry( p->vFanCounts, Node ); assert( nFanouts > 0 ); if ( --nFanouts == 0 ) Cut_OracleFreeCuts( p, Node ); Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutPre22.c000066400000000000000000001023651300674244400232120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutPre22.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Precomputes truth tables for the 2x2 macro cell.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define CUT_CELL_MVAR 9 typedef struct Cut_Cell_t_ Cut_Cell_t; typedef struct Cut_CMan_t_ Cut_CMan_t; struct Cut_Cell_t_ { Cut_Cell_t * pNext; // pointer to the next cell in the table Cut_Cell_t * pNextVar; // pointer to the next cell of this support size Cut_Cell_t * pParent; // pointer to the cell used to derive this one int nUsed; // the number of times the cell is used char Box[4]; // functions in the boxes unsigned nVars : 4; // the number of variables unsigned CrossBar0 : 4; // the variable set equal unsigned CrossBar1 : 4; // the variable set equal unsigned CrossBarPhase : 2; // the phase of the cross bar (0, 1, or 2) unsigned CanonPhase : 18; // the canonical phase char CanonPerm[CUT_CELL_MVAR+3]; // semicanonical permutation short Store[2*CUT_CELL_MVAR]; // minterm counts in the cofactors unsigned uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table }; struct Cut_CMan_t_ { // storage for canonical cells Extra_MmFixed_t * pMem; st__table * tTable; Cut_Cell_t * pSameVar[CUT_CELL_MVAR+1]; // elementary truth tables unsigned uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)]; // temporary truth tables unsigned uTemp1[22][1<<(CUT_CELL_MVAR-5)]; unsigned uTemp2[22][1<<(CUT_CELL_MVAR-5)]; unsigned uTemp3[22][1<<(CUT_CELL_MVAR-5)]; unsigned uFinal[1<<(CUT_CELL_MVAR-5)]; unsigned puAux[1<<(CUT_CELL_MVAR-5)]; // statistical variables int nTotal; int nGood; int nVarCounts[CUT_CELL_MVAR+1]; int nSymGroups[CUT_CELL_MVAR+1]; int nSymGroupsE[CUT_CELL_MVAR+1]; abctime timeCanon; abctime timeSupp; abctime timeTable; int nCellFound; int nCellNotFound; }; // NP-classes of functions of 3 variables (22) //static char * s_NP3[22] = { // " 0\n", // 00 const 0 // 0 vars // " 1\n", // 01 const 1 // 0 vars // "1 1\n", // 02 a // 1 vars // "11 1\n", // 03 ab // 2 vars // "11 0\n", // 04 (ab)' // 2 vars // "10 1\n01 1\n", // 05 a<+>b // 2 vars // "111 1\n", // 06 0s abc // 3 vars // "111 0\n", // 07 (abc)' // // "11- 1\n1-1 1\n", // 08 1p a(b+c) // // "11- 0\n1-1 0\n", // 09 (a(b+c))' // // "111 1\n100 1\n010 1\n001 1\n", // 10 2s a<+>b<+>c // // "10- 0\n1-0 0\n011 0\n", // 11 3p a<+>bc // // "101 1\n110 1\n", // 12 4p a(b<+>c) // // "101 0\n110 0\n", // 13 (a(b<+>c))' // // "11- 1\n1-1 1\n-11 1\n", // 14 5s ab+bc+ac // // "111 1\n000 1\n", // 15 6s abc+a'b'c' // // "111 0\n000 0\n", // 16 (abc+a'b'c')' // // "11- 1\n-11 1\n0-1 1\n", // 17 7 ab+bc+a'c // // "011 1\n101 1\n110 1\n", // 18 8s a'bc+ab'c+abc' // // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' // // "100 1\n-11 1\n", // 20 9p ab'c'+bc // // "100 0\n-11 0\n" // 21 (ab'c'+bc)' // //}; // NP-classes of functions of 3 variables (22) static char * s_NP3Names[22] = { " const 0 ", " const 1 ", " a ", " ab ", " (ab)' ", " a<+>b ", "0s abc ", " (abc)' ", "1p a(b+c) ", " (a(b+c))' ", "2s a<+>b<+>c ", "3p a<+>bc ", "4p a(b<+>c) ", " (a(b<+>c))' ", "5s ab+bc+ac ", "6s abc+a'b'c' ", " (abc+a'b'c')' ", "7 ab+bc+a'c ", "8s a'bc+ab'c+abc' ", " (a'bc+ab'c+abc')' ", "9p ab'c'+bc ", " (ab'c'+bc)' " }; // the number of variables in each function //static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; // NPN classes of functions of exactly 3 inputs (10) static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 }; // NPN classes of functions of exactly 3 inputs that are symmetric (5) //static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 }; // NPN classes of functions of exactly 3 inputs (4) //static int s_NPNe3p[10] = { 8, 11, 12, 20 }; static Cut_CMan_t * Cut_CManStart(); static void Cut_CManStop( Cut_CMan_t * p ); static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ); static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell ); static int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ); static void Cut_CellSuppMin( Cut_Cell_t * pCell ); static void Cut_CellCrossBar( Cut_Cell_t * pCell ); static Cut_CMan_t * s_pCMan = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Start the precomputation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CellLoad() { FILE * pFile; char * pFileName = "cells22_daomap_iwls.txt"; char pString[1000]; Cut_CMan_t * p; Cut_Cell_t * pCell; int Length; //, i; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return; } // start the manager p = Cut_CManStart(); // load truth tables while ( fgets(pString, 1000, pFile) ) { Length = strlen(pString); pString[Length--] = 0; if ( Length == 0 ) continue; // derive the cell pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); memset( pCell, 0, sizeof(Cut_Cell_t) ); pCell->nVars = Abc_Base2Log(Length*4); pCell->nUsed = 1; // Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars ); Cut_CellSuppMin( pCell ); /* // set the elementary permutation for ( i = 0; i < (int)pCell->nVars; i++ ) pCell->CanonPerm[i] = i; // canonicize pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); */ // add to the table p->nTotal++; // Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" ); // if ( p->nTotal == 500 ) // break; if ( !Cut_CellTableLookup( p, pCell ) ) // new cell p->nGood++; } printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood ); fclose( pFile ); // return p; } /**Function************************************************************* Synopsis [Precomputes truth tables for the 2x2 macro cell.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CellPrecompute() { Cut_CMan_t * p; Cut_Cell_t * pCell, * pTemp; int i1, i2, i3, i, j, k, c; abctime clk = Abc_Clock(); //, clk2 = Abc_Clock(); p = Cut_CManStart(); // precompute truth tables for ( i = 0; i < 22; i++ ) Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i ); for ( i = 0; i < 22; i++ ) Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i ); for ( i = 0; i < 22; i++ ) Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i ); /* if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) ) { Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " ); for ( i = 0; i < pCell->nVars; i++ ) printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" ); } */ /* // go through symmetric roots for ( k = 0; k < 5; k++ ) for ( i1 = 0; i1 < 22; i1++ ) for ( i2 = i1; i2 < 22; i2++ ) for ( i3 = i2; i3 < 22; i3++ ) { // derive the cell pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); memset( pCell, 0, sizeof(Cut_Cell_t) ); pCell->nVars = 9; pCell->Box[0] = s_NPNe3s[k]; pCell->Box[1] = i1; pCell->Box[2] = i2; pCell->Box[3] = i3; // fill in the truth table Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] ); // canonicize Cut_CellCanonicize( pCell ); // add to the table p->nTotal++; if ( Cut_CellTableLookup( p, pCell ) ) // already exists Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); else p->nGood++; } // go through partially symmetric roots for ( k = 0; k < 4; k++ ) for ( i1 = 0; i1 < 22; i1++ ) for ( i2 = 0; i2 < 22; i2++ ) for ( i3 = i2; i3 < 22; i3++ ) { // derive the cell pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); memset( pCell, 0, sizeof(Cut_Cell_t) ); pCell->nVars = 9; pCell->Box[0] = s_NPNe3p[k]; pCell->Box[1] = i1; pCell->Box[2] = i2; pCell->Box[3] = i3; // fill in the truth table Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] ); // canonicize Cut_CellCanonicize( pCell ); // add to the table p->nTotal++; if ( Cut_CellTableLookup( p, pCell ) ) // already exists Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); else p->nGood++; } // go through non-symmetric functions for ( i1 = 0; i1 < 22; i1++ ) for ( i2 = 0; i2 < 22; i2++ ) for ( i3 = 0; i3 < 22; i3++ ) { // derive the cell pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); memset( pCell, 0, sizeof(Cut_Cell_t) ); pCell->nVars = 9; pCell->Box[0] = 17; pCell->Box[1] = i1; pCell->Box[2] = i2; pCell->Box[3] = i3; // fill in the truth table Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 ); // canonicize Cut_CellCanonicize( pCell ); // add to the table p->nTotal++; if ( Cut_CellTableLookup( p, pCell ) ) // already exists Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); else p->nGood++; } */ // go through non-symmetric functions for ( k = 0; k < 10; k++ ) for ( i1 = 0; i1 < 22; i1++ ) for ( i2 = 0; i2 < 22; i2++ ) for ( i3 = 0; i3 < 22; i3++ ) { // derive the cell pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); memset( pCell, 0, sizeof(Cut_Cell_t) ); pCell->nVars = 9; pCell->Box[0] = s_NPNe3[k]; pCell->Box[1] = i1; pCell->Box[2] = i2; pCell->Box[3] = i3; // set the elementary permutation for ( i = 0; i < (int)pCell->nVars; i++ ) pCell->CanonPerm[i] = i; // fill in the truth table Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] ); // minimize the support Cut_CellSuppMin( pCell ); // canonicize pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); // add to the table p->nTotal++; if ( Cut_CellTableLookup( p, pCell ) ) // already exists Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); else { p->nGood++; p->nVarCounts[pCell->nVars]++; if ( pCell->nVars ) for ( i = 0; i < (int)pCell->nVars-1; i++ ) { if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric continue; // i and i+1 can be symmetric // find the end of this group for ( j = i+1; j < (int)pCell->nVars; j++ ) if ( pCell->Store[2*i] != pCell->Store[2*j] ) break; if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) p->nSymGroupsE[j-i]++; else p->nSymGroups[j-i]++; i = j - 1; } /* if ( pCell->nVars == 3 ) { Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); for ( i = 0; i < (int)pCell->nVars; i++ ) printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); printf( "\n" ); } */ } } printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", (int)p->nTotal, (int)p->nGood, (int)sizeof(Cut_Cell_t) ); ABC_PRT( "Time", Abc_Clock() - clk ); printf( "Cells: " ); for ( i = 0; i <= 9; i++ ) printf( "%d=%d ", i, p->nVarCounts[i] ); printf( "\nDiffs: " ); for ( i = 0; i <= 9; i++ ) printf( "%d=%d ", i, p->nSymGroups[i] ); printf( "\nEquals: " ); for ( i = 0; i <= 9; i++ ) printf( "%d=%d ", i, p->nSymGroupsE[i] ); printf( "\n" ); // continue adding new cells using support for ( k = CUT_CELL_MVAR; k > 3; k-- ) { for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) for ( i1 = 0; i1 < k; i1++ ) for ( i2 = i1+1; i2 < k; i2++ ) for ( c = 0; c < 3; c++ ) { // derive the cell pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); memset( pCell, 0, sizeof(Cut_Cell_t) ); pCell->nVars = pTemp->nVars; pCell->pParent = pTemp; // set the elementary permutation for ( i = 0; i < (int)pCell->nVars; i++ ) pCell->CanonPerm[i] = i; // fill in the truth table Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars ); // create the cross-bar pCell->CrossBar0 = i1; pCell->CrossBar1 = i2; pCell->CrossBarPhase = c; Cut_CellCrossBar( pCell ); // minimize the support //clk2 = Abc_Clock(); Cut_CellSuppMin( pCell ); //p->timeSupp += Abc_Clock() - clk2; // canonicize //clk2 = Abc_Clock(); pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); //p->timeCanon += Abc_Clock() - clk2; // add to the table //clk2 = Abc_Clock(); p->nTotal++; if ( Cut_CellTableLookup( p, pCell ) ) // already exists Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); else { p->nGood++; p->nVarCounts[pCell->nVars]++; for ( i = 0; i < (int)pCell->nVars-1; i++ ) { if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric continue; // i and i+1 can be symmetric // find the end of this group for ( j = i+1; j < (int)pCell->nVars; j++ ) if ( pCell->Store[2*i] != pCell->Store[2*j] ) break; if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) p->nSymGroupsE[j-i]++; else p->nSymGroups[j-i]++; i = j - 1; } /* if ( pCell->nVars == 3 ) { Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); for ( i = 0; i < (int)pCell->nVars; i++ ) printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); printf( "\n" ); } */ } //p->timeTable += Abc_Clock() - clk2; } printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, (int)sizeof(Cut_Cell_t) ); ABC_PRT( "Time", Abc_Clock() - clk ); printf( "Cells: " ); for ( i = 0; i <= 9; i++ ) printf( "%d=%d ", i, p->nVarCounts[i] ); printf( "\nDiffs: " ); for ( i = 0; i <= 9; i++ ) printf( "%d=%d ", i, p->nSymGroups[i] ); printf( "\nEquals: " ); for ( i = 0; i <= 9; i++ ) printf( "%d=%d ", i, p->nSymGroupsE[i] ); printf( "\n" ); } // printf( "\n" ); ABC_PRT( "Supp ", p->timeSupp ); ABC_PRT( "Canon", p->timeCanon ); ABC_PRT( "Table", p->timeTable ); // Cut_CManStop( p ); } /**Function************************************************************* Synopsis [Check the table.] Description [Returns 1 if such a truth table already exists.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ) { Cut_Cell_t ** pSlot, * pTemp; unsigned Hash; Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) ); if ( ! st__find_or_add( p->tTable, (char *)(ABC_PTRUINT_T)Hash, (char ***)&pSlot ) ) *pSlot = NULL; for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext ) { if ( pTemp->nVars != pCell->nVars ) continue; if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) return 1; } // the entry is new pCell->pNext = *pSlot; *pSlot = pCell; // add it to the variable support list pCell->pNextVar = p->pSameVar[pCell->nVars]; p->pSameVar[pCell->nVars] = pCell; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CellSuppMin( Cut_Cell_t * pCell ) { static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; unsigned * pIn, * pOut, * pTemp; int i, k, Counter, Temp; // go backward through the support variables and remove redundant for ( k = pCell->nVars - 1; k >= 0; k-- ) if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) ) { // shift all the variables above this one Counter = 0; pIn = pCell->uTruth; pOut = uTemp; for ( i = k; i < (int)pCell->nVars - 1; i++ ) { Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; // swap the support vars Temp = pCell->CanonPerm[i]; pCell->CanonPerm[i] = pCell->CanonPerm[i+1]; pCell->CanonPerm[i+1] = Temp; Counter++; } // return the function back into its place if ( Counter & 1 ) Extra_TruthCopy( pOut, pIn, pCell->nVars ); // remove one variable pCell->nVars--; // Extra_PrintBinary( stdout, pCell->uTruth, (1<nVars) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CellCrossBar( Cut_Cell_t * pCell ) { static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)]; static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)]; Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars ); Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars ); if ( pCell->CanonPhase == 0 ) { Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); } else if ( pCell->CanonPhase == 1 ) { Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 ); Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 ); Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); } else if ( pCell->CanonPhase == 2 ) { Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 ); Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 ); } else assert( 0 ); Extra_TruthMux( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ) { int nWords = Extra_TruthWordNum( nVars ); int i; assert( Type < 22 ); switch ( Type ) { // " 0\n", // 00 const 0 case 0: for ( i = 0; i < nWords; i++ ) pOut[i] = 0; return; // " 1\n", // 01 const 1 case 1: for ( i = 0; i < nWords; i++ ) pOut[i] = 0xFFFFFFFF; return; // "1 1\n", // 02 a case 2: for ( i = 0; i < nWords; i++ ) pOut[i] = InA[i]; return; // "11 1\n", // 03 ab case 3: for ( i = 0; i < nWords; i++ ) pOut[i] = InA[i] & InB[i]; return; // "11 0\n", // 04 (ab)' case 4: for ( i = 0; i < nWords; i++ ) pOut[i] = ~(InA[i] & InB[i]); return; // "10 1\n01 1\n", // 05 a<+>b case 5: for ( i = 0; i < nWords; i++ ) pOut[i] = InA[i] ^ InB[i]; return; // "111 1\n", // 06 + abc case 6: for ( i = 0; i < nWords; i++ ) pOut[i] = InA[i] & InB[i] & InC[i]; return; // "111 0\n", // 07 (abc)' case 7: for ( i = 0; i < nWords; i++ ) pOut[i] = ~(InA[i] & InB[i] & InC[i]); return; // "11- 1\n1-1 1\n", // 08 + a(b+c) case 8: for ( i = 0; i < nWords; i++ ) pOut[i] = InA[i] & (InB[i] | InC[i]); return; // "11- 0\n1-1 0\n", // 09 (a(b+c))' case 9: for ( i = 0; i < nWords; i++ ) pOut[i] = ~(InA[i] & (InB[i] | InC[i])); return; // "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c case 10: for ( i = 0; i < nWords; i++ ) pOut[i] = InA[i] ^ InB[i] ^ InC[i]; return; // "10- 0\n1-0 0\n011 0\n", // 11 + a<+>bc case 11: for ( i = 0; i < nWords; i++ ) pOut[i] = InA[i] ^ (InB[i] & InC[i]); return; // "101 1\n110 1\n", // 12 + a(b<+>c) case 12: for ( i = 0; i < nWords; i++ ) pOut[i] = InA[i] & (InB[i] ^ InC[i]); return; // "101 0\n110 0\n", // 13 (a(b<+>c))' case 13: for ( i = 0; i < nWords; i++ ) pOut[i] = ~(InA[i] & (InB[i] ^ InC[i])); return; // "11- 1\n1-1 1\n-11 1\n", // 14 + ab+bc+ac case 14: for ( i = 0; i < nWords; i++ ) pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]); return; // "111 1\n000 1\n", // 15 + abc+a'b'c' case 15: for ( i = 0; i < nWords; i++ ) pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]); return; // "111 0\n000 0\n", // 16 (abc+a'b'c')' case 16: for ( i = 0; i < nWords; i++ ) pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i])); return; // "11- 1\n-11 1\n0-1 1\n", // 17 + ab+bc+a'c case 17: for ( i = 0; i < nWords; i++ ) pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]); return; // "011 1\n101 1\n110 1\n", // 18 + a'bc+ab'c+abc' case 18: for ( i = 0; i < nWords; i++ ) pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]); return; // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' case 19: for ( i = 0; i < nWords; i++ ) pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i])); return; // "100 1\n-11 1\n", // 20 + ab'c'+bc case 20: for ( i = 0; i < nWords; i++ ) pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]); return; // "100 0\n-11 0\n" // 21 (ab'c'+bc)' case 21: for ( i = 0; i < nWords; i++ ) pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i])); return; } } /**Function************************************************************* Synopsis [Start the precomputation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cut_CMan_t * Cut_CManStart() { Cut_CMan_t * p; int i, k; // start the manager assert( sizeof(unsigned) == 4 ); p = ABC_ALLOC( Cut_CMan_t, 1 ); memset( p, 0, sizeof(Cut_CMan_t) ); // start the table and the memory manager p->tTable = st__init_table( st__ptrcmp, st__ptrhash);; p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) ); // set elementary truth tables for ( k = 0; k < CUT_CELL_MVAR; k++ ) for ( i = 0; i < (1<uInputs[k][i>>5] |= (1 << (i&31)); s_pCMan = p; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CManStop( Cut_CMan_t * p ) { st__free_table( p->tTable ); Extra_MmFixedStop( p->pMem ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_CellIsRunning() { return s_pCMan != NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_CellDumpToFile() { FILE * pFile; Cut_CMan_t * p = s_pCMan; Cut_Cell_t * pTemp; char * pFileName = "celllib22.txt"; int NumUsed[10][5] = {{0}}; int BoxUsed[22][5] = {{0}}; int i, k, Counter; abctime clk = Abc_Clock(); if ( p == NULL ) { printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" ); return; } // count the number of cells used for ( k = CUT_CELL_MVAR; k >= 0; k-- ) { for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) { if ( pTemp->nUsed == 0 ) NumUsed[k][0]++; else if ( pTemp->nUsed < 10 ) NumUsed[k][1]++; else if ( pTemp->nUsed < 100 ) NumUsed[k][2]++; else if ( pTemp->nUsed < 1000 ) NumUsed[k][3]++; else NumUsed[k][4]++; for ( i = 0; i < 4; i++ ) if ( pTemp->nUsed == 0 ) BoxUsed[ (int)pTemp->Box[i] ][0]++; else if ( pTemp->nUsed < 10 ) BoxUsed[ (int)pTemp->Box[i] ][1]++; else if ( pTemp->nUsed < 100 ) BoxUsed[ (int)pTemp->Box[i] ][2]++; else if ( pTemp->nUsed < 1000 ) BoxUsed[ (int)pTemp->Box[i] ][3]++; else BoxUsed[ (int)pTemp->Box[i] ][4]++; } } printf( "Functions found = %10d. Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound ); for ( k = 0; k <= CUT_CELL_MVAR; k++ ) { printf( "%3d : ", k ); for ( i = 0; i < 5; i++ ) printf( "%8d ", NumUsed[k][i] ); printf( "\n" ); } printf( "Box usage:\n" ); for ( k = 0; k < 22; k++ ) { printf( "%3d : ", k ); for ( i = 0; i < 5; i++ ) printf( "%8d ", BoxUsed[k][i] ); printf( " %s", s_NP3Names[k] ); printf( "\n" ); } pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Cut_CellDumpToFile: Cannout open output file.\n" ); return; } Counter = 0; for ( k = 0; k <= CUT_CELL_MVAR; k++ ) { for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) if ( pTemp->nUsed > 0 ) { Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) ); fprintf( pFile, "\n" ); Counter++; } fprintf( pFile, "\n" ); } fclose( pFile ); printf( "Library composed of %d functions is written into file \"%s\". ", Counter, pFileName ); ABC_PRT( "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Looks up if the given function exists in the hash table.] Description [If the function exists, returns 1, meaning that it can be implemented using two levels of 3-input LUTs. If the function does not exist, return 0.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_CellTruthLookup( unsigned * pTruth, int nVars ) { Cut_CMan_t * p = s_pCMan; Cut_Cell_t * pTemp; Cut_Cell_t Cell, * pCell = &Cell; unsigned Hash; int i; // cell manager is not defined if ( p == NULL ) { printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" ); return 0; } // canonicize memset( pCell, 0, sizeof(Cut_Cell_t) ); pCell->nVars = nVars; Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); Cut_CellSuppMin( pCell ); // set the elementary permutation for ( i = 0; i < (int)pCell->nVars; i++ ) pCell->CanonPerm[i] = i; // canonicize pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); // check if the cell exists Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) ); if ( st__lookup( p->tTable, (char *)(ABC_PTRUINT_T)Hash, (char **)&pTemp ) ) { for ( ; pTemp; pTemp = pTemp->pNext ) { if ( pTemp->nVars != pCell->nVars ) continue; if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) { pTemp->nUsed++; p->nCellFound++; return 1; } } } p->nCellNotFound++; return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutSeq.c000066400000000000000000000162661300674244400230540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutSeq.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Sequential cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Shifts all cut leaves of the node by the given number of latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cut_NodeShiftCutLeaves( Cut_Cut_t * pList, int nLat ) { Cut_Cut_t * pTemp; int i; // shift the cuts by as many latches Cut_ListForEachCut( pList, pTemp ) { pTemp->uSign = 0; for ( i = 0; i < (int)pTemp->nLeaves; i++ ) { pTemp->pLeaves[i] += nLat; pTemp->uSign |= Cut_NodeSign( pTemp->pLeaves[i] ); } } } /**Function************************************************************* Synopsis [Computes sequential cuts for the node from its fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum ) { Cut_List_t Super, * pSuper = &Super; Cut_Cut_t * pListNew; abctime clk; // get the number of cuts at the node p->nNodeCuts = Cut_CutCountList( Cut_NodeReadCutsOld(p, Node) ); if ( p->nNodeCuts >= p->pParams->nKeepMax ) return; // count only the first visit if ( p->nNodeCuts == 0 ) p->nNodes++; // store the fanin lists p->pStore0[0] = Cut_NodeReadCutsOld( p, Node0 ); p->pStore0[1] = Cut_NodeReadCutsNew( p, Node0 ); p->pStore1[0] = Cut_NodeReadCutsOld( p, Node1 ); p->pStore1[1] = Cut_NodeReadCutsNew( p, Node1 ); // duplicate the cut lists if fanin nodes are non-standard if ( Node == Node0 || Node == Node1 || Node0 == Node1 ) { p->pStore0[0] = Cut_CutDupList( p, p->pStore0[0] ); p->pStore0[1] = Cut_CutDupList( p, p->pStore0[1] ); p->pStore1[0] = Cut_CutDupList( p, p->pStore1[0] ); p->pStore1[1] = Cut_CutDupList( p, p->pStore1[1] ); } // shift the cuts by as many latches and recompute signatures if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], nLat0 ); if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], nLat0 ); if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], nLat1 ); if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], nLat1 ); // store the original lists for comparison p->pCompareOld = Cut_NodeReadCutsOld( p, Node ); p->pCompareNew = Cut_NodeReadCutsNew( p, Node ); // merge the old and the new clk = Abc_Clock(); Cut_ListStart( pSuper ); Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[0], p->pStore1[1], 0, 0 ); Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[0], 0, 0 ); Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[1], fTriv, 0 ); pListNew = Cut_ListFinish( pSuper ); p->timeMerge += Abc_Clock() - clk; // shift the cuts by as many latches and recompute signatures if ( Node == Node0 || Node == Node1 || Node0 == Node1 ) { Cut_CutRecycleList( p, p->pStore0[0] ); Cut_CutRecycleList( p, p->pStore0[1] ); Cut_CutRecycleList( p, p->pStore1[0] ); Cut_CutRecycleList( p, p->pStore1[1] ); } else { if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], -nLat0 ); if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], -nLat0 ); if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], -nLat1 ); if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], -nLat1 ); } // set the lists at the node if ( CutSetNum >= 0 ) { assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL ); Cut_NodeWriteCutsTemp( p, CutSetNum, pListNew ); } else { assert( Cut_NodeReadCutsNew(p, Node) == NULL ); Cut_NodeWriteCutsNew( p, Node, pListNew ); } // mark the node if we exceeded the number of cuts if ( p->nNodeCuts >= p->pParams->nKeepMax ) p->nCutsLimit++; } /**Function************************************************************* Synopsis [Merges the new cuts with the old cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node ) { Cut_Cut_t * pListOld, * pListNew, * pList; // get the new cuts pListNew = Cut_NodeReadCutsNew( p, Node ); if ( pListNew == NULL ) return; Cut_NodeWriteCutsNew( p, Node, NULL ); // get the old cuts pListOld = Cut_NodeReadCutsOld( p, Node ); if ( pListOld == NULL ) { Cut_NodeWriteCutsOld( p, Node, pListNew ); return; } // merge the lists pList = Cut_CutMergeLists( pListOld, pListNew ); Cut_NodeWriteCutsOld( p, Node, pList ); } /**Function************************************************************* Synopsis [Transfers the temporary cuts to be the new cuts.] Description [Returns 1 if something was transferred.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum ) { Cut_Cut_t * pList; pList = Cut_NodeReadCutsTemp( p, CutSetNum ); Cut_NodeWriteCutsTemp( p, CutSetNum, NULL ); Cut_NodeWriteCutsNew( p, Node, pList ); return pList != NULL; } /**Function************************************************************* Synopsis [Transfers the old cuts to be the new cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node ) { Cut_Cut_t * pList; pList = Cut_NodeReadCutsOld( p, Node ); Cut_NodeWriteCutsOld( p, Node, NULL ); Cut_NodeWriteCutsNew( p, Node, pList ); // Cut_CutListVerify( pList ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/cutTruth.c000066400000000000000000000165101300674244400234220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cutTruth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [K-feasible cut computation package.] Synopsis [Incremental truth table computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cutTruth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cutInt.h" ABC_NAMESPACE_IMPL_START /* Truth tables computed in this package are represented as bit-strings stored in the cut data structure. Cuts of any number of inputs have the truth table with 2^k bits, where k is the max number of cut inputs. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // used in abcCut.c int nTotal = 0; int nGood = 0; int nEqual = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) { unsigned uPhase = 0; int i, k; for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) { if ( k == (int)pCut1->nLeaves ) break; if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) continue; assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); uPhase |= (1 << i); k++; } return uPhase; } /**Function************************************************************* Synopsis [Performs truth table computation.] Description [This procedure cannot be used while recording oracle because it will overwrite Num0 and Num1.] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_TruthNCanonicize( Cut_Cut_t * pCut ) { unsigned uTruth; unsigned * uCanon2; char * pPhases2; assert( pCut->nVarsMax < 6 ); // get the direct truth table uTruth = *Cut_CutReadTruth(pCut); // compute the direct truth table Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); // uCanon[0] = uCanon2[0]; // uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; // uPhases[0] = pPhases2[0]; pCut->uCanon0 = uCanon2[0]; pCut->Num0 = pPhases2[0]; // get the complemented truth table uTruth = ~*Cut_CutReadTruth(pCut); // compute the direct truth table Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); // uCanon[0] = uCanon2[0]; // uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; // uPhases[0] = pPhases2[0]; pCut->uCanon1 = uCanon2[0]; pCut->Num1 = pPhases2[0]; } /**Function************************************************************* Synopsis [Performs truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) { static unsigned uTruth0[8], uTruth1[8]; int nTruthWords = Cut_TruthWords( pCut->nVarsMax ); unsigned * pTruthRes; int i, uPhase; // permute the first table uPhase = Cut_TruthPhase( pCut, pCut0 ); Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut0), uPhase, uTruth0 ); if ( fCompl0 ) { for ( i = 0; i < nTruthWords; i++ ) uTruth0[i] = ~uTruth0[i]; } // permute the second table uPhase = Cut_TruthPhase( pCut, pCut1 ); Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut1), uPhase, uTruth1 ); if ( fCompl1 ) { for ( i = 0; i < nTruthWords; i++ ) uTruth1[i] = ~uTruth1[i]; } // write the resulting table pTruthRes = Cut_CutReadTruth(pCut); if ( pCut->fCompl ) { for ( i = 0; i < nTruthWords; i++ ) pTruthRes[i] = ~(uTruth0[i] & uTruth1[i]); } else { for ( i = 0; i < nTruthWords; i++ ) pTruthRes[i] = uTruth0[i] & uTruth1[i]; } } /**Function************************************************************* Synopsis [Performs truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) { // permute the first table if ( fCompl0 ) Extra_TruthNot( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); else Extra_TruthCopy( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut0) ); // permute the second table if ( fCompl1 ) Extra_TruthNot( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); else Extra_TruthCopy( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut1) ); // produce the resulting table if ( pCut->fCompl ) Extra_TruthNand( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); else Extra_TruthAnd( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); // Ivy_TruthTestOne( *Cut_CutReadTruth(pCut) ); // quit if no fancy computation is needed if ( !p->pParams->fFancy ) return; if ( pCut->nLeaves != 7 ) return; // count the total number of truth tables computed nTotal++; // MAPPING INTO ALTERA 6-2 LOGIC BLOCKS // call this procedure to find the minimum number of common variables in the cofactors // if this number is less or equal than 3, the cut can be implemented using the 6-2 logic block if ( Extra_TruthMinCofSuppOverlap( Cut_CutReadTruth(pCut), pCut->nVarsMax, NULL ) <= 4 ) nGood++; // MAPPING INTO ACTEL 2x2 CELLS // call this procedure to see if a semi-canonical form can be found in the lookup table // (if it exists, then a two-level 3-input LUT implementation of the cut exists) // Before this procedure is called, cell manager should be defined by calling // Cut_CellLoad (make sure file "cells22_daomap_iwls.txt" is available in the working dir) // if ( Cut_CellIsRunning() && pCut->nVarsMax <= 9 ) // nGood += Cut_CellTruthLookup( Cut_CutReadTruth(pCut), pCut->nVarsMax ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/cut/module.make000066400000000000000000000004401300674244400235530ustar00rootroot00000000000000SRC += src/opt/cut/cutApi.c \ src/opt/cut/cutCut.c \ src/opt/cut/cutMan.c \ src/opt/cut/cutMerge.c \ src/opt/cut/cutNode.c \ src/opt/cut/cutOracle.c \ src/opt/cut/cutPre22.c \ src/opt/cut/cutSeq.c \ src/opt/cut/cutTruth.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/000077500000000000000000000000001300674244400214045ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/dar.h000066400000000000000000000122741300674244400223310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dar.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: dar.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__dar__dar_h #define ABC__aig__dar__dar_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Dar_RwrPar_t_ Dar_RwrPar_t; typedef struct Dar_RefPar_t_ Dar_RefPar_t; struct Dar_RwrPar_t_ { int nCutsMax; // the maximum number of cuts to try int nSubgMax; // the maximum number of subgraphs to try int fFanout; // support fanout representation int fUpdateLevel; // update level int fUseZeros; // performs zero-cost replacement int fPower; // enables power-aware rewriting int fRecycle; // enables cut recycling int fVerbose; // enables verbose output int fVeryVerbose; // enables very verbose output }; struct Dar_RefPar_t_ { int nMffcMin; // the min MFFC size for which refactoring is used int nLeafMax; // the max number of leaves of a cut int nCutsMax; // the max number of cuts to consider int fExtend; // extends the cut below MFFC int fUpdateLevel; // updates the level after each move int fUseZeros; // perform zero-cost replacements int fVerbose; // verbosity level int fVeryVerbose; // enables very verbose output }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== darLib.c ========================================================*/ extern void Dar_LibStart(); extern void Dar_LibStop(); extern void Dar_LibPrepare( int nSubgraphs ); extern int Dar_LibReturnClass( unsigned uTruth ); /*=== darBalance.c ========================================================*/ extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ); extern Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose ); extern void Dar_BalancePrintStats( Aig_Man_t * p ); /*=== darCore.c ========================================================*/ extern void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ); extern int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ); extern Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax, int fSkipTtMin, int fVerbose ); /*=== darRefact.c ========================================================*/ extern void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars ); extern int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars ); /*=== darScript.c ========================================================*/ extern Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig ); extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ); extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ); extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darBalance.c000066400000000000000000000617041300674244400235740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darBalance.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Algebraic AIG balancing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darBalance.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" #include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //#define USE_LUTSIZE_BALANCE //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Uniqifies the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ObjCompareLits( 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; } void Dar_BalanceUniqify( Aig_Obj_t * pObj, Vec_Ptr_t * vNodes, int fExor ) { Aig_Obj_t * pTemp, * pTempNext; int i, k; // sort the nodes by their literal Vec_PtrSort( vNodes, (int (*)())Dar_ObjCompareLits ); // remove duplicates k = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pTemp, i ) { if ( i + 1 == Vec_PtrSize(vNodes) ) { Vec_PtrWriteEntry( vNodes, k++, pTemp ); break; } pTempNext = (Aig_Obj_t *)Vec_PtrEntry( vNodes, i+1 ); if ( !fExor && pTemp == Aig_Not(pTempNext) ) // pos_lit & neg_lit = 0 { Vec_PtrClear( vNodes ); return; } if ( pTemp != pTempNext ) // save if different Vec_PtrWriteEntry( vNodes, k++, pTemp ); else if ( fExor ) // in case of XOR, remove identical i++; } Vec_PtrShrink( vNodes, k ); if ( Vec_PtrSize(vNodes) < 2 ) return; // check that there is no duplicates pTemp = (Aig_Obj_t *)Vec_PtrEntry( vNodes, 0 ); Vec_PtrForEachEntryStart( Aig_Obj_t *, vNodes, pTempNext, i, 1 ) { assert( pTemp != pTempNext ); pTemp = pTempNext; } } /**Function************************************************************* Synopsis [Collects the nodes of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) { if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) ) Vec_PtrPush( vSuper, pObj ); else { assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(pObj) ); // go through the branches Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); } } Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) { Vec_Ptr_t * vNodes; assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(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 Dar_BalanceCone_rec( pObj, pObj, vNodes ); // remove duplicates Dar_BalanceUniqify( pObj, vNodes, Aig_ObjIsExor(pObj) ); return vNodes; } /**Function************************************************************* Synopsis [Collects the nodes of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* int Dar_BalanceCone_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)->fMarkB ) { if ( Aig_ObjIsExor(pRoot) ) { assert( !Aig_IsComplement(pObj) ); // check if the node occurs in the same polarity Vec_PtrRemove( vSuper, pObj ); Aig_Regular(pObj)->fMarkB = 0; //printf( " Duplicated EXOR input!!! " ); return 1; } else { // 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_PtrSize(vSuper) > 10000) ) { Vec_PtrPush( vSuper, pObj ); Aig_Regular(pObj)->fMarkB = 1; return 0; } assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(pObj) ); // go through the branches RetValue1 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); RetValue2 = Dar_BalanceCone_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; } Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) { Vec_Ptr_t * vNodes; int RetValue, i; assert( !Aig_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 = Dar_BalanceCone_rec( pObj, pObj, vNodes ); assert( RetValue != 0 || vNodes->nSize > 1 ); // unmark the visited nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Aig_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 Dar_BalanceFindLeft( Vec_Ptr_t * vSuper ) { Aig_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 = (Aig_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 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current ); // if the level of this node is different, quit the loop if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) ) break; } Current++; // get the node, for which the equality holds pObjLeft = (Aig_Obj_t *)Vec_PtrEntry( vSuper, Current ); assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_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 Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) { Aig_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 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); pObj2 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 || Aig_Regular(pObj1) == Aig_Regular(pObj2) ) return; // find the first node that can be shared for ( i = RightBound; i >= LeftBound; i-- ) { pObj3 = (Aig_Obj_t *)Vec_PtrEntry( vSuper, i ); if ( Aig_Regular(pObj3) == p->pConst1 ) { Vec_PtrWriteEntry( vSuper, i, pObj2 ); Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); return; } if ( Aig_Regular(pObj1) == Aig_Regular(pObj3) ) { if ( pObj3 == pObj2 ) return; Vec_PtrWriteEntry( vSuper, i, pObj2 ); Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); return; } pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_OBJ_EXOR : AIG_OBJ_AND ); if ( Aig_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 = Aig_ManRandom(0) % (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 [Procedure used for sorting the nodes in decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) { int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2)); if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; Diff = Aig_ObjId(Aig_Regular(*pp1)) - Aig_ObjId(Aig_Regular(*pp2)); if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Inserts a new node in the order by levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj, int fExor ) { Aig_Obj_t * pObj1, * pObj2; int i; if ( Vec_PtrPushUnique(vStore, pObj) ) { if ( fExor ) Vec_PtrRemove(vStore, pObj); return; } // find the p of the node for ( i = vStore->nSize-1; i > 0; i-- ) { pObj1 = (Aig_Obj_t *)vStore->pArray[i ]; pObj2 = (Aig_Obj_t *)vStore->pArray[i-1]; if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) ) break; vStore->pArray[i ] = pObj2; vStore->pArray[i-1] = pObj1; } } /**Function************************************************************* Synopsis [Builds implication supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ) { Aig_Obj_t * pObj1, * pObj2; int LeftBound; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); // balance the nodes while ( vSuper->nSize > 1 ) { // find the left bound on the node to be paired LeftBound = (!fUpdateLevel)? 0 : Dar_BalanceFindLeft( vSuper ); // find the node that can be shared (if no such node, randomize choice) Dar_BalancePermute( p, vSuper, LeftBound, Type == AIG_OBJ_EXOR ); // pull out the last two nodes pObj1 = (Aig_Obj_t *)Vec_PtrPop(vSuper); pObj2 = (Aig_Obj_t *)Vec_PtrPop(vSuper); Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type), Type == AIG_OBJ_EXOR ); } return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); } /**Function************************************************************* Synopsis [Returns affective support size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_BaseSize( Aig_Man_t * p, Aig_Obj_t * pObj, int nLutSize ) { int nBaseSize; pObj = Aig_Regular(pObj); if ( Aig_ObjIsConst1(pObj) ) return 0; if ( Aig_ObjLevel(pObj) >= nLutSize ) return 1; nBaseSize = Aig_SupportSize( p, pObj ); if ( nBaseSize >= nLutSize ) return 1; return nBaseSize; } /**Function************************************************************* Synopsis [Builds implication supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Dar_BalanceBuildSuperTop( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel, int nLutSize ) { Vec_Ptr_t * vSubset; Aig_Obj_t * pObj; int i, nBaseSizeAll, nBaseSize; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); // add one LUT at a time while ( Vec_PtrSize(vSuper) > 1 ) { // isolate the group of nodes with nLutSize inputs nBaseSizeAll = 0; vSubset = Vec_PtrAlloc( nLutSize ); Vec_PtrForEachEntryReverse( Aig_Obj_t *, vSuper, pObj, i ) { nBaseSize = Aig_BaseSize( p, pObj, nLutSize ); if ( nBaseSizeAll + nBaseSize > nLutSize && Vec_PtrSize(vSubset) > 1 ) break; nBaseSizeAll += nBaseSize; Vec_PtrPush( vSubset, pObj ); } // remove them from vSuper Vec_PtrShrink( vSuper, Vec_PtrSize(vSuper) - Vec_PtrSize(vSubset) ); // create the new supergate pObj = Dar_BalanceBuildSuper( p, vSubset, Type, fUpdateLevel ); Vec_PtrFree( vSubset ); // add the new output Dar_BalancePushUniqueOrderByLevel( vSuper, pObj, Type == AIG_OBJ_EXOR ); } return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); } /**Function************************************************************* Synopsis [Returns the new node constructed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) { Aig_Obj_t * pObjNew; Vec_Ptr_t * vSuper; int i; assert( !Aig_IsComplement(pObjOld) ); assert( !Aig_ObjIsBuf(pObjOld) ); // return if the result is known if ( pObjOld->pData ) return (Aig_Obj_t *)pObjOld->pData; assert( Aig_ObjIsNode(pObjOld) ); // get the implication supergate vSuper = Dar_BalanceCone( pObjOld, vStore, Level ); // check if supergate contains two nodes in the opposite polarity if ( vSuper->nSize == 0 ) return (Aig_Obj_t *)(pObjOld->pData = Aig_ManConst0(pNew)); // for each old node, derive the new well-balanced node for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) { pObjNew = Dar_Balance_rec( pNew, Aig_Regular((Aig_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); if ( pObjNew == NULL ) return NULL; vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement((Aig_Obj_t *)vSuper->pArray[i]) ); } // check for exactly one node if ( vSuper->nSize == 1 ) return (Aig_Obj_t *)Vec_PtrEntry(vSuper, 0); // build the supergate #ifdef USE_LUTSIZE_BALANCE pObjNew = Dar_BalanceBuildSuperTop( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel, 6 ); #else pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel ); #endif if ( pNew->Time2Quit && !(Aig_Regular(pObjNew)->Id & 255) && Abc_Clock() > pNew->Time2Quit ) return NULL; // make sure the balanced node is not assigned // assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level ); assert( pObjOld->pData == NULL ); return (Aig_Obj_t *)(pObjOld->pData = pObjNew); } /**Function************************************************************* Synopsis [Performs algebraic balancing of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pDriver, * pObjNew; Vec_Vec_t * vStore; int i; assert( Aig_ManVerifyTopoOrder(p) ); // 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; pNew->Time2Quit = p->Time2Quit; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // map the PI nodes Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); vStore = Vec_VecAlloc( 50 ); if ( p->pManTime != NULL ) { float arrTime; Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime ); Aig_ManSetCioIds( p ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) continue; if ( Aig_ObjIsCi(pObj) ) { // copy the PI pObjNew = Aig_ObjCreateCi(pNew); pObj->pData = pObjNew; // set the arrival time of the new PI arrTime = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) ); pObjNew->Level = (int)arrTime; } else if ( Aig_ObjIsCo(pObj) ) { // perform balancing pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel ); if ( pObjNew == NULL ) { Vec_VecFree( vStore ); Aig_ManStop( pNew ); return NULL; } pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) ); // save arrival time of the output arrTime = (float)Aig_Regular(pObjNew)->Level; Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj), arrTime ); // create PO pObjNew = Aig_ObjCreateCo( pNew, pObjNew ); } else assert( 0 ); } Aig_ManCleanCioIds( p ); pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); } else { Aig_ManForEachCi( p, pObj, i ) { pObjNew = Aig_ObjCreateCi(pNew); pObjNew->Level = pObj->Level; pObj->pData = pObjNew; } if ( p->nBarBufs == 0 ) { Aig_ManForEachCo( p, pObj, i ) { pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel ); if ( pObjNew == NULL ) { Vec_VecFree( vStore ); Aig_ManStop( pNew ); return NULL; } pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) ); pObjNew = Aig_ObjCreateCo( pNew, pObjNew ); } } else { Vec_Ptr_t * vLits = Vec_PtrStart( Aig_ManCoNum(p) ); Aig_ManForEachCo( p, pObj, i ) { int k = i < p->nBarBufs ? Aig_ManCoNum(p) - p->nBarBufs + i : i - p->nBarBufs; pObj = Aig_ManCo( p, k ); pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel ); if ( pObjNew == NULL ) { Vec_VecFree( vStore ); Aig_ManStop( pNew ); return NULL; } pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) ); Vec_PtrWriteEntry( vLits, k, pObjNew ); if ( i < p->nBarBufs ) Aig_ManCi(pNew, Aig_ManCiNum(p) - p->nBarBufs + i)->Level = Aig_Regular(pObjNew)->Level; } Aig_ManForEachCo( p, pObj, i ) Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vLits, i) ); Vec_PtrFree(vLits); } } Vec_VecFree( vStore ); // remove dangling nodes Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting AIG if ( !Aig_ManCheck(pNew) ) printf( "Dar_ManBalance(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManBalanceXor( Aig_Man_t * pAig, int fExor, int fUpdateLevel, int fVerbose ) { Aig_Man_t * pAigXor, * pRes; if ( fExor ) { pAigXor = Aig_ManDupExor( pAig ); if ( fVerbose ) Dar_BalancePrintStats( pAigXor ); pRes = Dar_ManBalance( pAigXor, fUpdateLevel ); Aig_ManStop( pAigXor ); } else { pRes = Dar_ManBalance( pAig, fUpdateLevel ); } return pRes; } /**Function************************************************************* Synopsis [Inserts a new node in the order by levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_BalancePrintStats( Aig_Man_t * p ) { Vec_Ptr_t * vSuper; Aig_Obj_t * pObj, * pTemp; int i, k; if ( Aig_ManExorNum(p) == 0 ) { printf( "There is no EXOR gates.\n" ); return; } Aig_ManForEachExor( p, pObj, i ) { Aig_ObjFanin0(pObj)->fMarkA = 1; Aig_ObjFanin1(pObj)->fMarkA = 1; assert( !Aig_ObjFaninC0(pObj) ); assert( !Aig_ObjFaninC1(pObj) ); } vSuper = Vec_PtrAlloc( 1000 ); Aig_ManForEachExor( p, pObj, i ) { if ( pObj->fMarkA && pObj->nRefs == 1 ) continue; Vec_PtrClear( vSuper ); Dar_BalanceCone_rec( pObj, pObj, vSuper ); Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) pTemp->fMarkB = 0; if ( Vec_PtrSize(vSuper) < 3 ) continue; printf( " %d(", Vec_PtrSize(vSuper) ); Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) printf( " %d", pTemp->Level ); printf( " )" ); } Vec_PtrFree( vSuper ); Aig_ManForEachObj( p, pObj, i ) pObj->fMarkA = 0; printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darCore.c000066400000000000000000000264341300674244400231400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Core of the rewriting package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // iterator over the nodes in the topological order #define Aig_ManForEachNodeInOrder( p, pObj ) \ for ( assert(p->pOrderData), p->iPrev = 0, p->iNext = p->pOrderData[1]; \ p->iNext && (((pObj) = Aig_ManObj(p, p->iNext)), 1); \ p->iNext = p->pOrderData[2*p->iPrev+1] ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the structure with default assignment of parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ) { memset( pPars, 0, sizeof(Dar_RwrPar_t) ); pPars->nCutsMax = 8; // 8 pPars->nSubgMax = 5; // 5 is a "magic number" pPars->fFanout = 1; pPars->fUpdateLevel = 0; pPars->fUseZeros = 0; pPars->fPower = 0; pPars->fRecycle = 1; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } #define MAX_VAL 10 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) { extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Dar_Man_t * p; // Bar_Progress_t * pProgress; Dar_Cut_t * pCut; Aig_Obj_t * pObj, * pObjNew; int i, k, nNodesOld, nNodeBefore, nNodeAfter, Required; abctime clk = 0, clkStart; int Counter = 0; int nMffcSize;//, nMffcGains[MAX_VAL+1][MAX_VAL+1] = {{0}}; // prepare the library Dar_LibPrepare( pPars->nSubgMax ); // create rewriting manager p = Dar_ManStart( pAig, pPars ); if ( pPars->fPower ) pAig->vProbs = Saig_ManComputeSwitchProbs( pAig, 48, 16, 1 ); // remove dangling nodes Aig_ManCleanup( pAig ); // if updating levels is requested, start fanout and timing if ( p->pPars->fFanout ) Aig_ManFanoutStart( pAig ); if ( p->pPars->fUpdateLevel ) Aig_ManStartReverseLevels( pAig, 0 ); // set elementary cuts for the PIs // Dar_ManCutsStart( p ); // resynthesize each node once clkStart = Abc_Clock(); p->nNodesInit = Aig_ManNodeNum(pAig); nNodesOld = Vec_PtrSize( pAig->vObjs ); // pProgress = Bar_ProgressStart( stdout, nNodesOld ); Aig_ManForEachObj( pAig, pObj, i ) // pProgress = Bar_ProgressStart( stdout, 100 ); // Aig_ManOrderStart( pAig ); // Aig_ManForEachNodeInOrder( pAig, pObj ) { if ( pAig->Time2Quit && !(i & 256) && Abc_Clock() > pAig->Time2Quit ) break; // Bar_ProgressUpdate( pProgress, 100*pAig->nAndPrev/pAig->nAndTotal, NULL ); // Bar_ProgressUpdate( pProgress, i, NULL ); if ( !Aig_ObjIsNode(pObj) ) continue; if ( i > nNodesOld ) // if ( p->pPars->fUseZeros && i > nNodesOld ) break; if ( pPars->fRecycle && ++Counter % 50000 == 0 && Aig_DagSize(pObj) < Vec_PtrSize(p->vCutNodes)/100 ) { // printf( "Counter = %7d. Node = %7d. Dag = %5d. Vec = %5d.\n", // Counter, i, Aig_DagSize(pObj), Vec_PtrSize(p->vCutNodes) ); // fflush( stdout ); Dar_ManCutsRestart( p, pObj ); } // consider freeing the cuts // if ( (i & 0xFFF) == 0 && Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) > 100 ) // Dar_ManCutsStart( p ); // compute cuts for the node p->nNodesTried++; clk = Abc_Clock(); Dar_ObjSetCuts( pObj, NULL ); Dar_ObjComputeCuts_rec( p, pObj ); p->timeCuts += Abc_Clock() - clk; // check if there is a trivial cut Dar_ObjForEachCut( pObj, pCut, k ) if ( pCut->nLeaves == 0 || (pCut->nLeaves == 1 && pCut->pLeaves[0] != pObj->Id && Aig_ManObj(p->pAig, pCut->pLeaves[0])) ) break; if ( k < (int)pObj->nCuts ) { assert( pCut->nLeaves < 2 ); if ( pCut->nLeaves == 0 ) // replace by constant { assert( pCut->uTruth == 0 || pCut->uTruth == 0xFFFF ); pObjNew = Aig_NotCond( Aig_ManConst1(p->pAig), pCut->uTruth==0 ); } else { assert( pCut->uTruth == 0xAAAA || pCut->uTruth == 0x5555 ); pObjNew = Aig_NotCond( Aig_ManObj(p->pAig, pCut->pLeaves[0]), pCut->uTruth==0x5555 ); } // remove the old cuts Dar_ObjSetCuts( pObj, NULL ); // replace the node Aig_ObjReplace( pAig, pObj, pObjNew, p->pPars->fUpdateLevel ); continue; } // evaluate the cuts p->GainBest = -1; nMffcSize = -1; Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : ABC_INFINITY; Dar_ObjForEachCut( pObj, pCut, k ) { int nLeavesOld = pCut->nLeaves; if ( pCut->nLeaves == 3 ) pCut->pLeaves[pCut->nLeaves++] = 0; Dar_LibEval( p, pObj, pCut, Required, &nMffcSize ); pCut->nLeaves = nLeavesOld; } // check the best gain if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) { // Aig_ObjOrderAdvance( pAig ); continue; } // nMffcGains[p->GainBest < MAX_VAL ? p->GainBest : MAX_VAL][nMffcSize < MAX_VAL ? nMffcSize : MAX_VAL]++; // remove the old cuts Dar_ObjSetCuts( pObj, NULL ); // if we end up here, a rewriting step is accepted nNodeBefore = Aig_ManNodeNum( pAig ); pObjNew = Dar_LibBuildBest( p ); // pObjNew can be complemented! pObjNew = Aig_NotCond( pObjNew, Aig_ObjPhaseReal(pObjNew) ^ pObj->fPhase ); assert( (int)Aig_Regular(pObjNew)->Level <= Required ); // replace the node Aig_ObjReplace( pAig, pObj, pObjNew, p->pPars->fUpdateLevel ); // compare the gains nNodeAfter = Aig_ManNodeNum( pAig ); assert( p->GainBest <= nNodeBefore - nNodeAfter ); // count gains of this class p->ClassGains[p->ClassBest] += nNodeBefore - nNodeAfter; } // Aig_ManOrderStop( pAig ); /* printf( "Distribution of gain (row) by MFFC size (column) %s 0-costs:\n", p->pPars->fUseZeros? "with":"without" ); for ( k = 0; k <= MAX_VAL; k++ ) printf( "<%4d> ", k ); printf( "\n" ); for ( i = 0; i <= MAX_VAL; i++ ) { for ( k = 0; k <= MAX_VAL; k++ ) printf( "%6d ", nMffcGains[i][k] ); printf( "\n" ); } */ p->timeTotal = Abc_Clock() - clkStart; p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; // Bar_ProgressStop( pProgress ); Dar_ManCutsFree( p ); // put the nodes into the DFS order and reassign their IDs // Aig_NtkReassignIds( p ); // fix the levels // Aig_ManVerifyLevel( pAig ); if ( p->pPars->fFanout ) Aig_ManFanoutStop( pAig ); if ( p->pPars->fUpdateLevel ) { // Aig_ManVerifyReverseLevel( pAig ); Aig_ManStopReverseLevels( pAig ); } if ( pAig->vProbs ) { Vec_IntFree( pAig->vProbs ); pAig->vProbs = NULL; } // stop the rewriting manager Dar_ManStop( p ); Aig_ManCheckPhase( pAig ); // check if ( !Aig_ManCheck( pAig ) ) { printf( "Aig_ManRewrite: The network check has failed.\n" ); return 0; } return 1; } /**Function************************************************************* Synopsis [Computes the total number of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ManCutCount( Aig_Man_t * pAig, int * pnCutsK ) { Dar_Cut_t * pCut; Aig_Obj_t * pObj; int i, k, nCuts = 0, nCutsK = 0; Aig_ManForEachNode( pAig, pObj, i ) Dar_ObjForEachCut( pObj, pCut, k ) { nCuts++; if ( pCut->nLeaves == 4 ) nCutsK++; } if ( pnCutsK ) *pnCutsK = nCutsK; return nCuts; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax, int fSkipTtMin, int fVerbose ) { Dar_Man_t * p; Dar_RwrPar_t Pars, * pPars = &Pars; Aig_Obj_t * pObj; Aig_MmFixed_t * pMemCuts; int i, nNodes; abctime clk = Abc_Clock(); // remove dangling nodes if ( (nNodes = Aig_ManCleanup( pAig )) ) { // printf( "Removing %d nodes.\n", nNodes ); } // create default parameters Dar_ManDefaultRwrParams( pPars ); pPars->nCutsMax = nCutsMax; // create rewriting manager p = Dar_ManStart( pAig, pPars ); // set elementary cuts for the PIs // Dar_ManCutsStart( p ); Aig_MmFixedRestart( p->pMemCuts ); Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); Aig_ManForEachCi( pAig, pObj, i ) Dar_ObjPrepareCuts( p, pObj ); // compute cuts for each nodes in the topological order Aig_ManForEachNode( pAig, pObj, i ) Dar_ObjComputeCuts( p, pObj, fSkipTtMin ); // print verbose stats if ( fVerbose ) { // Aig_Obj_t * pObj; int nCuts, nCutsK;//, i; nCuts = Dar_ManCutCount( pAig, &nCutsK ); printf( "Nodes = %6d. Total cuts = %6d. 4-input cuts = %6d.\n", Aig_ManObjNum(pAig), nCuts, nCutsK ); printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f MB ", (int)sizeof(Dar_Cut_t), (int)4, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); ABC_PRT( "Runtime", Abc_Clock() - clk ); /* Aig_ManForEachNode( pAig, pObj, i ) if ( i % 300 == 0 ) Dar_ObjCutPrint( pAig, pObj ); */ } // free the cuts pMemCuts = p->pMemCuts; p->pMemCuts = NULL; // Dar_ManCutsFree( p ); // stop the rewriting manager Dar_ManStop( p ); return pMemCuts; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darCut.c000066400000000000000000000557361300674244400230120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Computation of 4-input cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prints one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_CutPrint( Dar_Cut_t * pCut ) { unsigned i; printf( "{" ); for ( i = 0; i < pCut->nLeaves; i++ ) printf( " %d", pCut->pLeaves[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ObjCutPrint( Aig_Man_t * p, Aig_Obj_t * pObj ) { Dar_Cut_t * pCut; int i; printf( "Cuts for node %d:\n", pObj->Id ); Dar_ObjForEachCut( pObj, pCut, i ) Dar_CutPrint( pCut ); // printf( "\n" ); } /**Function************************************************************* Synopsis [Returns the number of 1s in the machine word.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dar_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); } /**Function************************************************************* Synopsis [Compute the cost of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dar_CutFindValue( Dar_Man_t * p, Dar_Cut_t * pCut ) { Aig_Obj_t * pLeaf; int i, Value, nOnes; assert( pCut->fUsed ); Value = 0; nOnes = 0; Dar_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) { if ( pLeaf == NULL ) return 0; assert( pLeaf != NULL ); Value += pLeaf->nRefs; nOnes += (pLeaf->nRefs == 1); } if ( pCut->nLeaves < 2 ) return 1001; // Value = Value * 100 / pCut->nLeaves; if ( Value > 1000 ) Value = 1000; if ( nOnes > 3 ) Value = 5 - nOnes; return Value; } /**Function************************************************************* Synopsis [Returns the next free cut to use.] Description [Uses the cut with the smallest value.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Dar_Cut_t * Dar_CutFindFree( Dar_Man_t * p, Aig_Obj_t * pObj ) { Dar_Cut_t * pCut, * pCutMax; int i; pCutMax = NULL; Dar_ObjForEachCutAll( pObj, pCut, i ) { if ( pCut->fUsed == 0 ) return pCut; if ( pCut->nLeaves < 3 ) continue; if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) pCutMax = pCut; } if ( pCutMax == NULL ) { Dar_ObjForEachCutAll( pObj, pCut, i ) { if ( pCut->nLeaves < 2 ) continue; if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) pCutMax = pCut; } } if ( pCutMax == NULL ) { Dar_ObjForEachCutAll( pObj, pCut, i ) { if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) pCutMax = pCut; } } assert( pCutMax != NULL ); pCutMax->fUsed = 0; return pCutMax; } /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dar_CutCheckDominance( Dar_Cut_t * pDom, Dar_Cut_t * pCut ) { int i, k; assert( pDom->fUsed && pCut->fUsed ); for ( i = 0; i < (int)pDom->nLeaves; i++ ) { for ( k = 0; k < (int)pCut->nLeaves; k++ ) if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) break; if ( k == (int)pCut->nLeaves ) // 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 [] ***********************************************************************/ static inline int Dar_CutFilter( Aig_Obj_t * pObj, Dar_Cut_t * pCut ) { Dar_Cut_t * pTemp; int i; assert( pCut->fUsed ); // go through the cuts of the node Dar_ObjForEachCut( pObj, pTemp, i ) { if ( pTemp == pCut ) continue; if ( pTemp->nLeaves > pCut->nLeaves ) { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) continue; // check containment seriously if ( Dar_CutCheckDominance( pCut, pTemp ) ) { // remove contained cut pTemp->fUsed = 0; } } else { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) continue; // check containment seriously if ( Dar_CutCheckDominance( pTemp, pCut ) ) { // remove the given cut pCut->fUsed = 0; return 1; } } } return 0; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dar_CutMergeOrdered( Dar_Cut_t * pC, Dar_Cut_t * pC0, Dar_Cut_t * pC1 ) { int i, k, c; assert( pC0->nLeaves >= pC1->nLeaves ); // the case of the largest cut sizes if ( pC0->nLeaves == 4 && pC1->nLeaves == 4 ) { if ( pC0->uSign != pC1->uSign ) return 0; for ( i = 0; i < (int)pC0->nLeaves; i++ ) if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) return 0; for ( i = 0; i < (int)pC0->nLeaves; i++ ) pC->pLeaves[i] = pC0->pLeaves[i]; pC->nLeaves = pC0->nLeaves; return 1; } // the case when one of the cuts is the largest if ( pC0->nLeaves == 4 ) { if ( (pC0->uSign & pC1->uSign) != pC1->uSign ) return 0; for ( i = 0; i < (int)pC1->nLeaves; i++ ) { for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- ) if ( pC0->pLeaves[k] == pC1->pLeaves[i] ) break; if ( k == -1 ) // did not find return 0; } for ( i = 0; i < (int)pC0->nLeaves; i++ ) pC->pLeaves[i] = pC0->pLeaves[i]; pC->nLeaves = pC0->nLeaves; return 1; } // compare two cuts with different numbers i = k = 0; for ( c = 0; c < 4; c++ ) { if ( k == (int)pC1->nLeaves ) { if ( i == (int)pC0->nLeaves ) { pC->nLeaves = c; return 1; } pC->pLeaves[c] = pC0->pLeaves[i++]; continue; } if ( i == (int)pC0->nLeaves ) { if ( k == (int)pC1->nLeaves ) { pC->nLeaves = c; return 1; } pC->pLeaves[c] = pC1->pLeaves[k++]; continue; } if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) { pC->pLeaves[c] = pC0->pLeaves[i++]; continue; } if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) { pC->pLeaves[c] = pC1->pLeaves[k++]; continue; } pC->pLeaves[c] = pC0->pLeaves[i++]; k++; } if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves ) return 0; pC->nLeaves = c; return 1; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dar_CutMerge( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1 ) { assert( !pCut->fUsed ); // merge the nodes if ( pCut0->nLeaves <= pCut1->nLeaves ) { if ( !Dar_CutMergeOrdered( pCut, pCut1, pCut0 ) ) return 0; } else { if ( !Dar_CutMergeOrdered( pCut, pCut0, pCut1 ) ) return 0; } pCut->uSign = pCut0->uSign | pCut1->uSign; pCut->fUsed = 1; return 1; } /**Function************************************************************* Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dar_CutTruthPhase( Dar_Cut_t * pCut, Dar_Cut_t * pCut1 ) { unsigned uPhase = 0; int i, k; for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) { if ( k == (int)pCut1->nLeaves ) break; if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) continue; assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); uPhase |= (1 << i); k++; } return uPhase; } /**Function************************************************************* Synopsis [Swaps two advancent variables of the truth table.] Description [Swaps variable iVar and iVar+1.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dar_CutTruthSwapAdjacentVars( unsigned uTruth, int iVar ) { assert( iVar >= 0 && iVar <= 2 ); if ( iVar == 0 ) return (uTruth & 0x99999999) | ((uTruth & 0x22222222) << 1) | ((uTruth & 0x44444444) >> 1); if ( iVar == 1 ) return (uTruth & 0xC3C3C3C3) | ((uTruth & 0x0C0C0C0C) << 2) | ((uTruth & 0x30303030) >> 2); if ( iVar == 2 ) return (uTruth & 0xF00FF00F) | ((uTruth & 0x00F000F0) << 4) | ((uTruth & 0x0F000F00) >> 4); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Swaps polarity of the variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dar_CutTruthSwapPolarity( unsigned uTruth, int iVar ) { assert( iVar >= 0 && iVar <= 3 ); if ( iVar == 0 ) return ((uTruth & 0xAAAA) >> 1) | ((uTruth & 0x5555) << 1); if ( iVar == 1 ) return ((uTruth & 0xCCCC) >> 2) | ((uTruth & 0x3333) << 2); if ( iVar == 2 ) return ((uTruth & 0xF0F0) >> 4) | ((uTruth & 0x0F0F) << 4); if ( iVar == 3 ) return ((uTruth & 0xFF00) >> 8) | ((uTruth & 0x00FF) << 8); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Expands the truth table according to the phase.] Description [The input and output truth tables are in pIn/pOut. The current number of variables is nVars. The total number of variables in nVarsAll. The last argument (Phase) contains shows where the variables should go.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dar_CutTruthStretch( unsigned uTruth, int nVars, unsigned Phase ) { int i, k, Var = nVars - 1; for ( i = 3; i >= 0; i-- ) if ( Phase & (1 << i) ) { for ( k = Var; k < i; k++ ) uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k ); Var--; } assert( Var == -1 ); return uTruth; } /**Function************************************************************* Synopsis [Shrinks the truth table according to the phase.] Description [The input and output truth tables are in pIn/pOut. The current number of variables is nVars. The total number of variables in nVarsAll. The last argument (Phase) contains shows what variables should remain.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dar_CutTruthShrink( unsigned uTruth, int nVars, unsigned Phase ) { int i, k, Var = 0; for ( i = 0; i < 4; i++ ) if ( Phase & (1 << i) ) { for ( k = i-1; k >= Var; k-- ) uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k ); Var++; } return uTruth; } /**Function************************************************************* Synopsis [Sort variables by their ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Dar_CutSortVars( unsigned uTruth, int * pVars ) { int i, Temp, fChange, Counter = 0; // replace -1 by large number for ( i = 0; i < 4; i++ ) { if ( pVars[i] == -1 ) pVars[i] = 0x3FFFFFFF; else if ( Abc_LitIsCompl(pVars[i]) ) { pVars[i] = Abc_LitNot( pVars[i] ); uTruth = Dar_CutTruthSwapPolarity( uTruth, i ); } } // permute variables do { fChange = 0; for ( i = 0; i < 3; i++ ) { if ( pVars[i] <= pVars[i+1] ) continue; Counter++; fChange = 1; Temp = pVars[i]; pVars[i] = pVars[i+1]; pVars[i+1] = Temp; uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, i ); } } while ( fChange ); // replace large number by -1 for ( i = 0; i < 4; i++ ) { if ( pVars[i] == 0x3FFFFFFF ) pVars[i] = -1; // printf( "%d ", pVars[i] ); } // printf( "\n" ); return uTruth; } /**Function************************************************************* Synopsis [Performs truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dar_CutTruth( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1, int fCompl0, int fCompl1 ) { unsigned uTruth0 = fCompl0 ? ~pCut0->uTruth : pCut0->uTruth; unsigned uTruth1 = fCompl1 ? ~pCut1->uTruth : pCut1->uTruth; uTruth0 = Dar_CutTruthStretch( uTruth0, pCut0->nLeaves, Dar_CutTruthPhase(pCut, pCut0) ); uTruth1 = Dar_CutTruthStretch( uTruth1, pCut1->nLeaves, Dar_CutTruthPhase(pCut, pCut1) ); return uTruth0 & uTruth1; } /**Function************************************************************* Synopsis [Minimize support of the cut.] Description [Returns 1 if the node's support has changed] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dar_CutSuppMinimize( Dar_Cut_t * pCut ) { unsigned uMasks[4][2] = { { 0x5555, 0xAAAA }, { 0x3333, 0xCCCC }, { 0x0F0F, 0xF0F0 }, { 0x00FF, 0xFF00 } }; unsigned uPhase = 0, uTruth = 0xFFFF & pCut->uTruth; int i, k, nLeaves; assert( pCut->fUsed ); // compute the support of the cut's function nLeaves = pCut->nLeaves; for ( i = 0; i < (int)pCut->nLeaves; i++ ) if ( (uTruth & uMasks[i][0]) == ((uTruth & uMasks[i][1]) >> (1 << i)) ) nLeaves--; else uPhase |= (1 << i); if ( nLeaves == (int)pCut->nLeaves ) return 0; // shrink the truth table uTruth = Dar_CutTruthShrink( uTruth, pCut->nLeaves, uPhase ); pCut->uTruth = 0xFFFF & uTruth; // update leaves and signature pCut->uSign = 0; for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) { if ( !(uPhase & (1 << i)) ) continue; pCut->pLeaves[k++] = pCut->pLeaves[i]; pCut->uSign |= Aig_ObjCutSign( pCut->pLeaves[i] ); } assert( k == nLeaves ); pCut->nLeaves = nLeaves; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManCutsFree( Dar_Man_t * p ) { if ( p->pMemCuts == NULL ) return; Aig_MmFixedStop( p->pMemCuts, 0 ); p->pMemCuts = NULL; // Aig_ManCleanData( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj ) { Dar_Cut_t * pCutSet, * pCut; int i; assert( Dar_ObjCuts(pObj) == NULL ); pObj->nCuts = p->pPars->nCutsMax; // create the cutset of the node pCutSet = (Dar_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); memset( pCutSet, 0, p->pPars->nCutsMax * sizeof(Dar_Cut_t) ); Dar_ObjSetCuts( pObj, pCutSet ); Dar_ObjForEachCutAll( pObj, pCut, i ) pCut->fUsed = 0; Vec_PtrPush( p->vCutNodes, pObj ); // add unit cut if needed pCut = pCutSet; pCut->fUsed = 1; if ( Aig_ObjIsConst1(pObj) ) { pCut->nLeaves = 0; pCut->uSign = 0; pCut->uTruth = 0xFFFF; } else { pCut->nLeaves = 1; pCut->pLeaves[0] = pObj->Id; pCut->uSign = Aig_ObjCutSign( pObj->Id ); pCut->uTruth = 0xAAAA; } pCut->Value = Dar_CutFindValue( p, pCut ); if ( p->nCutMemUsed < Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ) p->nCutMemUsed = Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20); return pCutSet; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManCutsRestart( Dar_Man_t * p, Aig_Obj_t * pRoot ) { Aig_Obj_t * pObj; int i; Dar_ObjSetCuts( Aig_ManConst1(p->pAig), NULL ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vCutNodes, pObj, i ) if ( !Aig_ObjIsNone(pObj) ) Dar_ObjSetCuts( pObj, NULL ); Vec_PtrClear( p->vCutNodes ); Aig_MmFixedRestart( p->pMemCuts ); Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj, int fSkipTtMin ) { Aig_Obj_t * pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); Aig_Obj_t * pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); Aig_Obj_t * pFaninR0 = Aig_Regular(pFanin0); Aig_Obj_t * pFaninR1 = Aig_Regular(pFanin1); Dar_Cut_t * pCutSet, * pCut0, * pCut1, * pCut; int i, k; assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(pObj) ); assert( Dar_ObjCuts(pObj) == NULL ); assert( Dar_ObjCuts(pFaninR0) != NULL ); assert( Dar_ObjCuts(pFaninR1) != NULL ); // set up the first cut pCutSet = Dar_ObjPrepareCuts( p, pObj ); // make sure fanins cuts are computed Dar_ObjForEachCut( pFaninR0, pCut0, i ) Dar_ObjForEachCut( pFaninR1, pCut1, k ) { p->nCutsAll++; // make sure K-feasible cut exists if ( Dar_WordCountOnes(pCut0->uSign | pCut1->uSign) > 4 ) continue; // get the next cut of this node pCut = Dar_CutFindFree( p, pObj ); // create the new cut if ( !Dar_CutMerge( pCut, pCut0, pCut1 ) ) { assert( !pCut->fUsed ); continue; } p->nCutsTried++; // check dominance if ( Dar_CutFilter( pObj, pCut ) ) { assert( !pCut->fUsed ); continue; } // compute truth table pCut->uTruth = 0xFFFF & Dar_CutTruth( pCut, pCut0, pCut1, Aig_IsComplement(pFanin0), Aig_IsComplement(pFanin1) ); // minimize support of the cut if ( !fSkipTtMin && Dar_CutSuppMinimize( pCut ) ) { int RetValue = Dar_CutFilter( pObj, pCut ); assert( !RetValue ); } // assign the value of the cut pCut->Value = Dar_CutFindValue( p, pCut ); // if the cut contains removed node, do not use it if ( pCut->Value == 0 ) { p->nCutsSkipped++; pCut->fUsed = 0; } else if ( pCut->nLeaves < 2 ) return pCutSet; } // count the number of nontrivial cuts cuts Dar_ObjForEachCut( pObj, pCut, i ) p->nCutsUsed += pCut->fUsed; // discount trivial cut p->nCutsUsed--; return pCutSet; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj ) { if ( Dar_ObjCuts(pObj) ) return Dar_ObjCuts(pObj); if ( Aig_ObjIsCi(pObj) ) return Dar_ObjPrepareCuts( p, pObj ); if ( Aig_ObjIsBuf(pObj) ) return Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) ); Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) ); Dar_ObjComputeCuts_rec( p, Aig_ObjFanin1(pObj) ); return Dar_ObjComputeCuts( p, pObj, 0 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darData.c000066400000000000000000030402041300674244400231130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dar_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Storage for AIG subgraph data.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// const int s_nDataSize1 = 2*43906; unsigned int s_Data1[2*43906] = { 4, 6, 5, 7, 9, 11, 5, 6, 4, 7, 15, 17, 2, 8, 4, 21, 3, 10, 5, 25, 7, 25, 9, 25, 2, 10, 7, 33, 9, 33, 2, 14, 5, 39, 6, 39, 17, 39, 3, 16, 7, 47, 33, 47, 2, 16, 4, 53, 7, 53, 3, 14, 5, 59, 17, 59, 53, 59, 3, 11, 7, 67, 4, 68, 5, 66, 6, 73, 33, 67, 7, 76, 5, 77, 9, 77, 9, 66, 33, 85, 3, 9, 4, 88, 7, 91, 88, 93, 6, 88, 21, 89, 11, 89, 21, 100, 25, 101, 11, 88, 7, 107, 33, 107, 2, 11, 5, 113, 7, 112, 30, 113, 25, 113, 5, 120, 7, 121, 9, 120, 9, 113, 25, 128, 21, 129, 9, 112, 2, 9, 6, 137, 5, 138, 11, 136, 3, 17, 7, 144, 113, 145, 15, 144, 113, 151, 3, 15, 6, 155, 4, 156, 17, 154, 113, 161, 2, 17, 7, 165, 5, 166, 155, 165, 15, 164, 2, 15, 6, 174, 17, 174, 3, 13, 113, 181, 135, 181, 143, 181, 2, 12, 9, 189, 181, 189, 9, 192, 2, 13, 85, 197, 107, 197, 3, 12, 7, 203, 11, 203, 33, 203, 197, 203, 9, 211, 3, 19, 7, 215, 33, 215, 173, 215, 179, 215, 2, 18, 215, 225, 2, 19, 151, 229, 161, 229, 3, 18, 113, 235, 229, 235, 2, 4, 25, 241, 9, 241, 15, 241, 11, 241, 6, 240, 7, 240, 59, 253, 7, 241, 9, 257, 6, 241, 253, 261, 3, 5, 251, 265, 6, 266, 241, 269, 253, 265, 7, 272, 7, 273, 241, 277, 53, 265, 7, 280, 248, 265, 9, 285, 11, 265, 241, 288, 9, 291, 17, 265, 9, 265, 257, 265, 25, 299, 251, 298, 7, 264, 3, 305, 5, 305, 128, 305, 101, 305, 299, 305, 241, 305, 7, 317, 265, 319, 9, 305, 113, 322, 113, 305, 9, 326, 6, 264, 241, 331, 17, 331, 53, 331, 253, 331, 7, 265, 59, 341, 241, 343, 331, 341, 241, 346, 241, 347, 15, 341, 113, 353, 241, 340, 7, 357, 265, 357, 59, 357, 331, 357, 256, 265, 7, 367, 59, 367, 331, 367, 6, 265, 5, 375, 242, 375, 316, 375, 25, 375, 241, 382, 305, 375, 241, 386, 241, 387, 11, 375, 241, 375, 265, 394, 7, 397, 25, 394, 305, 394, 251, 395, 257, 375, 241, 374, 260, 265, 241, 265, 251, 413, 331, 413, 261, 413, 375, 413, 257, 413, 19, 413, 12, 413, 11, 413, 9, 428, 9, 413, 11, 433, 11, 432, 15, 413, 11, 412, 9, 441, 7, 413, 241, 445, 265, 445, 375, 445, 409, 445, 411, 445, 6, 412, 241, 457, 445, 457, 241, 460, 6, 413, 357, 465, 367, 465, 7, 412, 265, 471, 59, 471, 331, 471, 465, 471, 241, 479, 2, 6, 353, 483, 322, 483, 30, 483, 25, 483, 9, 490, 305, 483, 9, 494, 19, 483, 413, 483, 12, 483, 244, 483, 241, 483, 9, 506, 9, 483, 305, 510, 25, 510, 11, 510, 241, 510, 257, 510, 247, 483, 11, 483, 2, 524, 4, 527, 5, 524, 3, 531, 9, 524, 258, 483, 151, 483, 257, 483, 9, 540, 155, 483, 17, 545, 235, 483, 181, 483, 161, 483, 4, 482, 2, 555, 5, 482, 2, 559, 6, 559, 17, 559, 5, 483, 2, 567, 6, 566, 241, 567, 483, 573, 9, 573, 9, 567, 4, 483, 6, 581, 3, 582, 3, 7, 289, 587, 510, 587, 11, 591, 11, 590, 516, 587, 413, 587, 483, 598, 498, 587, 500, 587, 19, 587, 483, 606, 502, 587, 12, 587, 483, 612, 534, 587, 524, 587, 9, 618, 288, 587, 305, 623, 25, 623, 11, 587, 265, 629, 331, 631, 510, 628, 9, 628, 483, 636, 483, 628, 9, 640, 265, 628, 305, 645, 25, 645, 375, 628, 265, 587, 11, 653, 33, 655, 11, 652, 25, 659, 305, 659, 295, 587, 241, 587, 9, 587, 4, 668, 2, 671, 3, 668, 5, 675, 524, 668, 483, 668, 11, 681, 11, 680, 11, 668, 483, 686, 392, 587, 165, 587, 375, 587, 17, 695, 11, 695, 11, 694, 113, 587, 567, 587, 305, 705, 25, 705, 555, 704, 5, 586, 3, 713, 7, 713, 623, 713, 645, 713, 659, 713, 128, 713, 394, 713, 101, 713, 299, 713, 705, 713, 510, 713, 483, 713, 9, 736, 9, 713, 113, 740, 483, 740, 241, 713, 375, 746, 375, 713, 241, 750, 113, 713, 9, 754, 4, 586, 7, 759, 589, 759, 33, 759, 5, 587, 7, 767, 2, 768, 47, 767, 483, 773, 759, 767, 483, 777, 17, 767, 113, 781, 483, 781, 483, 766, 47, 787, 759, 787, 17, 787, 566, 587, 47, 795, 759, 795, 17, 795, 4, 587, 3, 803, 6, 805, 7, 802, 494, 803, 490, 803, 736, 803, 25, 803, 483, 816, 305, 803, 483, 820, 713, 803, 483, 824, 483, 803, 305, 828, 25, 828, 713, 828, 555, 829, 483, 802, 580, 587, 483, 587, 413, 842, 19, 842, 12, 842, 11, 843, 9, 851, 9, 842, 11, 855, 11, 854, 11, 842, 9, 860, 5, 843, 803, 865, 9, 865, 839, 865, 841, 865, 4, 842, 483, 875, 865, 875, 483, 878, 4, 843, 787, 883, 795, 883, 5, 842, 587, 889, 47, 889, 759, 889, 17, 889, 883, 889, 483, 899, 3, 4, 559, 903, 19, 903, 12, 903, 842, 903, 587, 903, 483, 912, 165, 912, 9, 903, 11, 918, 483, 903, 241, 923, 555, 923, 587, 922, 11, 922, 15, 903, 11, 903, 9, 934, 483, 934, 524, 903, 692, 903, 767, 903, 375, 945, 165, 903, 7, 949, 587, 948, 6, 902, 3, 955, 7, 902, 787, 959, 795, 959, 889, 959, 767, 959, 483, 967, 33, 959, 7, 903, 956, 973, 88, 973, 4, 973, 3, 973, 955, 980, 9, 980, 3, 972, 4, 972, 955, 973, 3, 990, 375, 973, 9, 973, 3, 996, 6, 903, 4, 1001, 3, 1001, 3, 1000, 4, 1000, 2, 5, 955, 1011, 914, 1011, 918, 1011, 11, 1017, 11, 1016, 912, 1011, 483, 1022, 920, 1011, 906, 1011, 19, 1011, 903, 1030, 842, 1011, 903, 1034, 908, 1011, 910, 1011, 12, 1011, 903, 1042, 922, 1011, 587, 1046, 928, 1011, 936, 1011, 934, 1011, 9, 1054, 15, 1011, 11, 1011, 918, 1060, 9, 1060, 903, 1064, 903, 1060, 9, 1068, 483, 1011, 912, 1072, 903, 1072, 587, 1076, 587, 1072, 903, 1080, 155, 1072, 587, 1011, 922, 1086, 483, 1086, 903, 1090, 903, 1086, 483, 1094, 11, 1087, 9, 1099, 9, 1086, 11, 1103, 17, 1011, 9, 1011, 934, 1108, 903, 1108, 11, 1113, 11, 1112, 11, 1108, 903, 1118, 587, 1108, 11, 1123, 668, 1011, 11, 1127, 544, 1011, 155, 1011, 483, 1132, 67, 1011, 375, 1137, 7, 1010, 2, 1141, 959, 1141, 85, 1141, 107, 1141, 203, 1141, 67, 1141, 9, 1153, 215, 1141, 47, 1141, 759, 1141, 6, 1010, 2, 1163, 5, 1163, 17, 1163, 7, 1011, 2, 1171, 5, 1171, 2, 1170, 5, 1170, 1163, 1171, 5, 1180, 2, 1181, 483, 1171, 903, 1170, 375, 1189, 972, 1011, 375, 1193, 6, 1011, 2, 1197, 5, 1197, 2, 1196, 5, 1196, 1141, 1197, 2, 1206, 5, 1207, 903, 1196, 1000, 1011, 903, 1011, 19, 1216, 842, 1216, 12, 1216, 11, 1217, 9, 1225, 587, 1216, 483, 1228, 11, 1216, 9, 1232, 9, 1216, 11, 1237, 11, 1236, 15, 1216, 483, 1216, 587, 1244, 7, 1217, 59, 1249, 331, 1249, 1213, 1249, 1215, 1249, 6, 1216, 1249, 1259, 6, 1217, 1189, 1263, 1193, 1263, 7, 1216, 375, 1269, 1263, 1269, 3, 6, 413, 1275, 1216, 1275, 241, 1275, 9, 1281, 11, 1283, 11, 1280, 9, 1287, 17, 1275, 3, 1290, 5, 1293, 4, 1290, 2, 1297, 903, 1291, 1011, 1275, 11, 1275, 241, 1304, 9, 1307, 248, 1275, 9, 1311, 973, 1275, 9, 1315, 341, 1275, 803, 1319, 9, 1319, 5, 1274, 3, 1325, 17, 1325, 357, 1325, 367, 1325, 471, 1325, 341, 1325, 241, 1337, 1249, 1325, 253, 1325, 53, 1325, 5, 1275, 6, 1347, 2, 1348, 918, 1347, 903, 1347, 9, 1354, 9, 1347, 903, 1358, 4, 1275, 6, 1362, 265, 1363, 2, 7, 393, 1369, 334, 1369, 1325, 1369, 1363, 1374, 17, 1374, 62, 1369, 331, 1369, 17, 1382, 59, 1369, 17, 1386, 1328, 1369, 1304, 1369, 9, 1393, 17, 1369, 331, 1396, 241, 1397, 59, 1396, 1325, 1396, 11, 1369, 1275, 1406, 9, 1409, 265, 1369, 241, 1412, 11, 1413, 15, 1369, 5, 1418, 3, 1421, 2, 1418, 4, 1425, 1011, 1419, 107, 1369, 67, 1369, 803, 1433, 9, 1433, 1359, 1369, 203, 1369, 215, 1369, 85, 1369, 5, 1368, 2, 1447, 7, 1447, 47, 1447, 85, 1447, 107, 1447, 203, 1447, 67, 1447, 9, 1461, 215, 1447, 759, 1447, 959, 1447, 4, 1368, 2, 1471, 7, 1471, 265, 1471, 7, 1476, 331, 1471, 59, 1471, 1325, 1471, 5, 1369, 7, 1486, 803, 1487, 1275, 1486, 803, 1493, 9, 1493, 1346, 1369, 803, 1499, 9, 1499, 4, 1369, 7, 1505, 3, 1506, 1060, 1505, 11, 1505, 1011, 1512, 1011, 1505, 7, 1517, 11, 1517, 11, 1516, 1347, 1505, 1275, 1504, 1362, 1369, 1275, 1369, 413, 1531, 19, 1531, 12, 1531, 1216, 1531, 1011, 1531, 903, 1540, 9, 1531, 11, 1545, 11, 1544, 11, 1531, 9, 1550, 903, 1531, 1011, 1554, 11, 1530, 9, 1559, 5, 1531, 959, 1563, 47, 1563, 759, 1563, 17, 1563, 1527, 1563, 1529, 1563, 4, 1530, 1563, 1577, 4, 1531, 1493, 1581, 1499, 1581, 5, 1530, 803, 1587, 9, 1587, 1581, 1587, 1, 974, 1, 975, 1, 982, 1, 983, 0, 204, 0, 195, 0, 881, 0, 463, 0, 212, 0, 900, 0, 480, 0, 194, 0, 880, 0, 462, 0, 213, 0, 901, 0, 481, 0, 205, 0, 216, 0, 217, 1, 446, 0, 448, 0, 415, 0, 421, 1, 92, 0, 92, 1, 94, 1645, 1647, 1, 93, 88, 1650, 1645, 1653, 0, 93, 1, 95, 1657, 1659, 0, 108, 0, 109, 1, 360, 0, 368, 0, 358, 0, 414, 1, 447, 1637, 1675, 0, 449, 1635, 1679, 0, 191, 0, 877, 0, 473, 1, 473, 0, 459, 1, 459, 0, 891, 0, 207, 0, 458, 0, 876, 0, 190, 1, 458, 0, 472, 0, 890, 0, 206, 1, 472, 1, 977, 1, 976, 0, 399, 0, 398, 0, 397, 7, 1722, 0, 275, 0, 269, 241, 1728, 0, 270, 1, 279, 0, 321, 0, 274, 0, 271, 1, 278, 0, 320, 1, 277, 241, 1746, 0, 319, 265, 1750, 1, 276, 0, 318, 1, 926, 0, 1518, 0, 950, 0, 1519, 0, 951, 1, 998, 1, 999, 0, 575, 0, 1478, 0, 282, 0, 1479, 0, 283, 0, 369, 0, 359, 1667, 1785, 0, 420, 1, 422, 1, 927, 1, 1421, 5, 1794, 1419, 1797, 3, 1794, 1799, 1801, 0, 527, 2, 1804, 525, 1807, 4, 1804, 1809, 1811, 1, 671, 4, 1814, 669, 1817, 2, 1814, 1819, 1821, 0, 1293, 3, 1824, 1291, 1827, 5, 1824, 1829, 1831, 1, 1425, 2, 1834, 1419, 1837, 4, 1834, 1839, 1841, 0, 531, 5, 1844, 525, 1847, 3, 1844, 1849, 1851, 1, 675, 3, 1854, 669, 1857, 5, 1854, 1859, 1861, 0, 1297, 4, 1864, 1291, 1867, 2, 1864, 1869, 1871, 1, 1422, 0, 528, 1, 672, 0, 1294, 1, 1426, 0, 532, 1, 676, 0, 1298, 1, 123, 0, 79, 1, 993, 0, 124, 1, 80, 0, 1210, 0, 1184, 0, 125, 1891, 1905, 1, 81, 1893, 1909, 1, 122, 1897, 1913, 0, 78, 1899, 1917, 0, 1208, 0, 1182, 1, 992, 1, 361, 1671, 1927, 0, 574, 1, 984, 1, 985, 1, 114, 9, 1937, 0, 68, 1, 980, 955, 1942, 9, 1942, 0, 568, 9, 1949, 1, 924, 1, 925, 0, 306, 375, 1957, 0, 308, 1413, 1961, 0, 26, 1, 306, 1, 308, 1, 714, 0, 1142, 0, 1448, 0, 1450, 1, 1450, 1413, 1979, 0, 1474, 0, 54, 0, 56, 1, 1472, 0, 1326, 0, 60, 1, 60, 0, 1166, 0, 40, 1, 956, 973, 2001, 973, 2000, 0, 556, 1, 22, 0, 1475, 1, 1165, 1168, 2012, 1169, 2013, 2015, 2017, 1168, 2013, 1169, 2012, 2021, 2023, 1, 1167, 2, 2027, 1197, 2029, 1997, 2031, 0, 57, 1, 957, 0, 1451, 1980, 2039, 1979, 2039, 1413, 2042, 1413, 2039, 1979, 2046, 1, 1449, 5, 2051, 1451, 2053, 1975, 2055, 1, 1451, 1977, 2059, 1413, 2061, 0, 307, 1967, 2065, 375, 2067, 0, 309, 1969, 2071, 1413, 2073, 0, 41, 1, 307, 1958, 2079, 1957, 2079, 375, 2082, 375, 2079, 1957, 2086, 1, 309, 1962, 2091, 1961, 2091, 1413, 2094, 1413, 2091, 1961, 2098, 1, 41, 2, 2103, 43, 2105, 1999, 2107, 1, 1143, 5, 2111, 1171, 2113, 1973, 2115, 1, 561, 564, 2118, 565, 2119, 2121, 2123, 564, 2119, 565, 2118, 2127, 2129, 0, 91, 7, 2132, 0, 569, 1, 981, 9, 2139, 955, 2139, 0, 69, 9, 2145, 1, 115, 0, 432, 0, 500, 0, 1245, 0, 1237, 0, 501, 0, 433, 1, 1415, 1, 348, 1, 388, 1, 826, 1, 126, 1, 1376, 1, 380, 1, 814, 1, 118, 1, 302, 1, 710, 1, 102, 1, 402, 1, 834, 1, 130, 1, 404, 1, 836, 1, 132, 1, 314, 1, 732, 1, 104, 0, 1236, 0, 1244, 1, 1414, 0, 202, 1, 888, 1, 202, 1603, 2215, 0, 106, 1, 106, 1663, 2221, 1, 794, 0, 366, 0, 84, 1, 786, 1, 84, 1941, 2233, 1, 390, 1, 994, 1, 450, 1, 105, 1, 733, 1, 405, 1, 315, 1, 837, 1, 133, 1, 407, 1, 451, 1, 391, 1, 1383, 0, 905, 1, 905, 0, 1477, 1, 1477, 1775, 2269, 6, 2269, 7, 2269, 6, 2268, 2275, 2277, 1983, 2269, 7, 2268, 2273, 2283, 0, 281, 1, 281, 1777, 2289, 6, 2289, 7, 2289, 6, 2288, 2295, 2297, 1987, 2289, 7, 2288, 2293, 2303, 1, 1387, 1, 406, 2227, 2309, 1, 995, 0, 461, 1, 461, 1621, 2317, 1699, 2317, 0, 1261, 1, 1261, 0, 879, 0, 193, 1, 879, 1619, 2331, 1701, 2331, 1, 193, 1617, 2337, 1703, 2337, 0, 1579, 0, 211, 9, 2344, 1, 1579, 1, 211, 1623, 2351, 1711, 2351, 0, 479, 241, 2356, 0, 899, 483, 2360, 0, 227, 1, 479, 1627, 2367, 1707, 2367, 1, 899, 1625, 2373, 1709, 2373, 1, 227, 0, 1273, 0, 1593, 0, 239, 1, 1273, 1, 1593, 1, 239, 0, 478, 2367, 2393, 1, 478, 2359, 2397, 1615, 2397, 2357, 2397, 1687, 2397, 0, 1272, 2387, 2407, 1, 1272, 2381, 2411, 0, 898, 2373, 2415, 0, 210, 2351, 2419, 1, 898, 2363, 2423, 1613, 2423, 2361, 2423, 1695, 2423, 1, 210, 2347, 2433, 1611, 2433, 2345, 2433, 1697, 2433, 0, 1592, 2389, 2443, 0, 192, 9, 2446, 2337, 2449, 2337, 2447, 1, 1592, 2383, 2455, 1, 192, 1605, 2459, 2329, 2459, 1683, 2459, 0, 460, 241, 2466, 2317, 2469, 2317, 2467, 0, 878, 483, 2474, 2331, 2477, 2331, 2475, 0, 238, 2391, 2483, 1, 460, 1609, 2487, 2315, 2487, 1691, 2487, 1, 878, 1607, 2495, 2327, 2495, 1685, 2495, 1, 238, 2385, 2503, 0, 1260, 2325, 2507, 0, 1578, 2349, 2511, 0, 226, 2379, 2515, 1, 1260, 2323, 2519, 1, 1578, 2343, 2523, 1, 226, 2365, 2527, 1, 349, 1, 127, 1, 827, 1, 389, 1, 119, 1, 815, 1, 381, 1, 1377, 1, 131, 1, 835, 1, 303, 1, 403, 1, 711, 1, 103, 1, 1366, 1, 694, 1, 702, 9, 2563, 0, 572, 1, 572, 1931, 2569, 0, 1516, 1, 1516, 1761, 2575, 7, 2575, 6, 2574, 2579, 2581, 6, 2575, 7, 2574, 2585, 2587, 0, 944, 0, 948, 1, 578, 587, 2595, 1, 948, 1763, 2599, 7, 2599, 6, 2598, 2603, 2605, 6, 2599, 7, 2598, 2609, 2611, 1, 1186, 1, 996, 3, 2616, 1, 544, 1, 465, 471, 2622, 1687, 2625, 1, 197, 203, 2628, 1697, 2631, 1, 883, 889, 2634, 1695, 2637, 1, 181, 189, 2640, 1683, 2643, 0, 445, 1693, 2647, 1713, 2647, 265, 2646, 1675, 2653, 2257, 2647, 375, 2647, 457, 2647, 1, 445, 264, 2662, 241, 2662, 1679, 2667, 375, 2662, 457, 2662, 1691, 2673, 1, 865, 875, 2676, 1685, 2679, 0, 215, 7, 2682, 1, 215, 1633, 2687, 1, 1563, 0, 457, 241, 2692, 2317, 2695, 1, 457, 241, 2698, 445, 2699, 445, 2698, 1691, 2705, 0, 875, 483, 2708, 2331, 2711, 1, 875, 865, 2714, 1685, 2717, 0, 189, 9, 2720, 2337, 2723, 1, 189, 181, 2726, 1683, 2729, 0, 203, 7, 2732, 2215, 2735, 11, 2732, 2351, 2739, 0, 471, 7, 2742, 1689, 2745, 265, 2742, 2367, 2749, 0, 889, 587, 2752, 2373, 2755, 1, 203, 1629, 2759, 197, 2758, 1697, 2763, 1, 471, 265, 2766, 2647, 2769, 465, 2766, 1687, 2773, 1, 889, 883, 2776, 1695, 2779, 0, 107, 7, 2782, 2221, 2785, 1, 107, 1665, 2789, 1, 795, 0, 367, 2255, 2795, 375, 2795, 7, 2794, 1, 367, 265, 2802, 1783, 2805, 0, 85, 7, 2808, 2233, 2811, 0, 357, 7, 2814, 1927, 2817, 1, 85, 2145, 2821, 1, 357, 265, 2824, 1785, 2827, 1, 787, 0, 573, 483, 2832, 2569, 2835, 1, 579, 1, 573, 1773, 2841, 1, 997, 1, 545, 1, 1187, 903, 2849, 1, 1367, 0, 949, 7, 2854, 2599, 2857, 0, 945, 483, 2861, 1, 949, 1767, 2865, 0, 1517, 7, 2868, 2575, 2871, 1, 1517, 1765, 2875, 1, 703, 1, 695, 1, 332, 1, 266, 1731, 2885, 1733, 2885, 1, 1012, 1, 30, 113, 2892, 0, 316, 265, 2896, 375, 2897, 0, 272, 7, 2902, 1735, 2903, 1, 736, 803, 2908, 1, 316, 1737, 2913, 375, 2912, 1, 272, 1727, 2919, 241, 2918, 0, 1374, 2545, 2925, 1, 1374, 1363, 2928, 1, 1382, 0, 904, 483, 2934, 2265, 2937, 1, 904, 0, 1476, 7, 2942, 2269, 2945, 1, 1476, 1779, 2949, 2011, 2949, 0, 280, 7, 2954, 2289, 2957, 1, 280, 1781, 2961, 2035, 2961, 1, 1386, 1, 99, 1, 991, 0, 1181, 2, 2972, 0, 347, 2165, 2977, 1, 347, 1, 263, 273, 2983, 272, 2982, 2985, 2987, 272, 2983, 273, 2982, 2991, 2993, 0, 77, 0, 1207, 5, 2998, 1, 77, 5, 3002, 1917, 3005, 9, 3003, 0, 121, 7, 3010, 1913, 3013, 9, 3011, 0, 387, 2259, 3019, 1, 121, 9, 3023, 1, 825, 483, 3027, 1, 387, 241, 3030, 241, 3031, 1, 98, 0, 1206, 2, 3038, 0, 386, 2237, 3043, 3033, 3043, 1, 386, 241, 3048, 1, 824, 483, 3052, 1, 990, 3, 3056, 0, 120, 3023, 3061, 9, 3063, 0, 1180, 5, 3066, 1, 120, 3016, 3071, 5, 3070, 1897, 3075, 3013, 3075, 3011, 3071, 9, 3080, 9, 3070, 9, 3071, 3011, 3086, 0, 76, 3008, 3091, 7, 3090, 1899, 3095, 3005, 3095, 3003, 3091, 9, 3100, 9, 3091, 3003, 3104, 0, 346, 2531, 3109, 1, 76, 2997, 3113, 9, 3115, 1, 776, 1, 346, 241, 3120, 2977, 3123, 1, 21, 2, 3127, 1275, 3129, 9, 3131, 4, 3126, 3133, 3135, 2, 3126, 668, 3139, 3135, 3141, 587, 3139, 9, 3144, 3135, 3147, 9, 3139, 587, 3150, 3135, 3153, 100, 3126, 129, 3126, 129, 3127, 100, 3127, 89, 3127, 11, 3164, 11, 3127, 89, 3169, 89, 3168, 89, 3126, 0, 25, 2243, 3177, 2547, 3177, 2539, 3177, 2533, 3177, 3024, 3177, 3, 3177, 1369, 3189, 11, 3191, 5, 3176, 3193, 3195, 3, 3176, 524, 3199, 3195, 3201, 483, 3199, 11, 3204, 3195, 3207, 11, 3199, 483, 3210, 3195, 3213, 3023, 3177, 9, 3216, 101, 3177, 128, 3177, 113, 3177, 9, 3224, 9, 3177, 3023, 3228, 113, 3228, 1, 33, 5, 3234, 6, 3237, 2997, 3235, 9, 3241, 3177, 3235, 67, 3235, 9, 3247, 67, 3234, 3239, 3251, 1, 25, 128, 3254, 101, 3254, 113, 3255, 9, 3254, 113, 3262, 113, 3254, 9, 3266, 9, 3267, 0, 33, 2759, 3273, 2789, 3273, 2821, 3273, 9, 3273, 67, 3272, 9, 3283, 1, 251, 298, 3286, 395, 3286, 395, 3287, 298, 3287, 257, 3287, 265, 3297, 265, 3296, 265, 3287, 257, 3302, 265, 3286, 0, 305, 2249, 3309, 2553, 3309, 2543, 3309, 2537, 3309, 3034, 3309, 3031, 3309, 241, 3320, 3235, 3309, 299, 3309, 394, 3309, 375, 3309, 241, 3330, 241, 3309, 3031, 3334, 375, 3334, 241, 3308, 375, 3341, 1, 331, 2647, 3345, 413, 3345, 241, 3344, 1369, 3344, 341, 3344, 0, 253, 7, 3356, 265, 3356, 3345, 3357, 1, 555, 923, 3364, 923, 3365, 704, 3364, 829, 3364, 829, 3365, 704, 3365, 0, 713, 2245, 3379, 2549, 3379, 2541, 3379, 2535, 3379, 3028, 3379, 3027, 3379, 483, 3390, 3235, 3379, 705, 3379, 828, 3379, 803, 3379, 483, 3400, 483, 3379, 3027, 3404, 803, 3404, 1, 759, 3, 3410, 6, 3413, 3273, 3411, 767, 3410, 3415, 3419, 0, 559, 0, 251, 413, 3424, 413, 3425, 257, 3425, 413, 3431, 412, 3430, 3433, 3435, 412, 3431, 413, 3430, 3439, 3441, 1, 305, 3, 3445, 375, 3447, 3, 3444, 394, 3444, 299, 3444, 241, 3444, 375, 3456, 375, 3444, 241, 3460, 1, 253, 265, 3464, 0, 555, 4, 3469, 15, 3471, 483, 3473, 2, 3468, 3475, 3477, 4, 3468, 524, 3481, 3477, 3483, 11, 3481, 483, 3486, 3477, 3489, 483, 3481, 11, 3492, 3477, 3495, 1, 713, 5, 3499, 17, 3501, 587, 3503, 3, 3498, 3505, 3507, 5, 3498, 668, 3511, 3507, 3513, 9, 3511, 587, 3516, 3507, 3519, 587, 3511, 9, 3522, 3507, 3525, 828, 3498, 705, 3498, 483, 3498, 803, 3532, 803, 3498, 483, 3536, 1, 559, 903, 3540, 1, 955, 980, 3544, 3, 3544, 973, 3549, 973, 3548, 973, 3545, 2139, 3555, 1011, 3544, 973, 3544, 3, 3560, 0, 1141, 2, 3564, 9, 3565, 3411, 3565, 0, 1447, 9, 3573, 3411, 3573, 1, 1471, 4, 3579, 11, 3581, 1369, 3583, 2, 3578, 3585, 3587, 4, 3578, 1418, 3591, 3587, 3593, 15, 3591, 1369, 3596, 3587, 3599, 1369, 3591, 15, 3602, 3587, 3605, 265, 3578, 2011, 3609, 0, 1325, 5, 3613, 9, 3615, 1275, 3617, 3, 3612, 3619, 3621, 5, 3612, 1290, 3625, 3621, 3627, 17, 3625, 1275, 3630, 3621, 3633, 1275, 3625, 17, 3636, 3621, 3639, 1, 53, 265, 3642, 2035, 3645, 0, 59, 5, 3648, 1, 1141, 3177, 3653, 3379, 3653, 3309, 3653, 0, 1163, 5, 3660, 1, 959, 3565, 3665, 3273, 3665, 3573, 3665, 1, 1447, 3177, 3673, 3309, 3673, 3379, 3673, 0, 1471, 7, 3680, 2269, 3683, 3345, 3681, 1, 1325, 1369, 3688, 3357, 3689, 3681, 3689, 0, 39, 5, 3696, 1, 47, 3565, 3701, 3573, 3701, 3273, 3701, 0, 53, 2, 3709, 587, 3711, 17, 3713, 7, 3708, 2289, 3717, 4, 3708, 3715, 3721, 2, 3708, 1290, 3725, 3721, 3727, 1275, 3725, 17, 3730, 3721, 3733, 17, 3725, 1275, 3736, 3721, 3739, 3345, 3709, 3689, 3709, 1, 59, 3, 3747, 483, 3749, 15, 3751, 5, 3746, 3753, 3755, 3, 3746, 1418, 3759, 3755, 3761, 1369, 3759, 15, 3764, 3755, 3767, 15, 3759, 1369, 3770, 3755, 3773, 1369, 3746, 3681, 3747, 3357, 3747, 3709, 3747, 1, 330, 1369, 3785, 471, 3785, 367, 3785, 357, 3785, 341, 3785, 241, 3795, 0, 1162, 17, 3799, 0, 758, 767, 3803, 0, 32, 2215, 3807, 2221, 3807, 2233, 3807, 3249, 3807, 3246, 3807, 9, 3817, 3235, 3807, 67, 3820, 9, 3823, 67, 3807, 3235, 3826, 9, 3829, 1, 758, 3807, 3833, 1, 32, 3104, 3837, 3284, 3837, 3091, 3837, 9, 3842, 3283, 3837, 9, 3846, 3273, 3837, 67, 3851, 9, 3853, 9, 3837, 3283, 3856, 3091, 3856, 0, 1470, 3785, 3863, 0, 24, 2203, 3867, 3259, 3867, 2191, 3867, 3257, 3867, 2179, 3867, 2895, 3867, 2171, 3867, 3265, 3867, 3269, 3867, 3085, 3867, 3071, 3867, 9, 3889, 3267, 3867, 9, 3893, 2893, 3867, 113, 3897, 3263, 3867, 113, 3901, 3255, 3867, 101, 3905, 128, 3905, 113, 3905, 9, 3910, 9, 3905, 113, 3914, 3837, 3867, 128, 3867, 101, 3867, 9, 3867, 113, 3924, 113, 3867, 9, 3928, 1, 24, 3220, 3933, 3222, 3933, 3232, 3933, 3226, 3933, 3224, 3933, 9, 3942, 3228, 3933, 113, 3946, 3177, 3933, 101, 3950, 128, 3950, 113, 3950, 9, 3956, 9, 3950, 113, 3960, 128, 3933, 3177, 3964, 101, 3933, 3177, 3968, 9, 3933, 3224, 3972, 3177, 3972, 113, 3976, 113, 3972, 3177, 3980, 113, 3933, 3228, 3984, 3177, 3984, 9, 3988, 9, 3984, 3177, 3992, 0, 712, 2201, 3997, 3531, 3997, 2189, 3997, 3529, 3997, 2177, 3997, 2911, 3997, 2169, 3997, 3535, 3997, 3539, 3997, 3055, 3997, 3053, 3997, 483, 4019, 3537, 3997, 483, 4023, 2909, 3997, 803, 4027, 3533, 3997, 803, 4031, 3499, 3997, 705, 4035, 828, 4035, 803, 4035, 483, 4040, 483, 4035, 803, 4044, 3837, 3997, 828, 3997, 705, 3997, 483, 3997, 803, 4054, 803, 3997, 483, 4058, 0, 52, 3785, 4063, 0, 304, 2199, 4067, 3455, 4067, 2187, 4067, 3453, 4067, 2175, 4067, 2917, 4067, 2167, 4067, 3459, 4067, 3463, 4067, 3051, 4067, 3049, 4067, 241, 4089, 3461, 4067, 241, 4093, 2913, 4067, 375, 4097, 3457, 4067, 375, 4101, 3445, 4067, 299, 4105, 394, 4105, 375, 4105, 241, 4110, 241, 4105, 375, 4114, 3837, 4067, 394, 4067, 299, 4067, 241, 4067, 375, 4124, 375, 4067, 241, 4128, 0, 38, 17, 4133, 0, 252, 265, 4137, 3785, 4137, 0, 558, 17, 4143, 1, 712, 3396, 4147, 3398, 4147, 3408, 4147, 3402, 4147, 3400, 4147, 483, 4156, 3404, 4147, 803, 4160, 3379, 4147, 705, 4164, 828, 4164, 803, 4164, 483, 4170, 483, 4164, 803, 4174, 9, 4147, 828, 4147, 3379, 4180, 705, 4147, 3379, 4184, 483, 4147, 3400, 4188, 3379, 4188, 803, 4192, 803, 4188, 3379, 4196, 803, 4147, 3404, 4200, 3379, 4200, 483, 4204, 483, 4200, 3379, 4208, 1, 304, 3326, 4213, 3328, 4213, 3338, 4213, 3332, 4213, 3330, 4213, 241, 4222, 3334, 4213, 375, 4226, 3309, 4213, 299, 4230, 394, 4230, 375, 4230, 241, 4236, 241, 4230, 375, 4240, 9, 4213, 394, 4213, 3309, 4246, 299, 4213, 3309, 4250, 241, 4213, 3330, 4254, 3309, 4254, 375, 4258, 375, 4254, 3309, 4262, 375, 4213, 3334, 4266, 3309, 4266, 241, 4270, 241, 4266, 3309, 4274, 0, 1446, 3833, 4279, 0, 1140, 3833, 4283, 1, 1446, 3867, 4287, 3997, 4287, 4067, 4287, 1, 46, 4279, 4295, 3807, 4295, 4283, 4295, 1, 1140, 3867, 4303, 4067, 4303, 3997, 4303, 1, 58, 1369, 4311, 4063, 4311, 3863, 4311, 4137, 4311, 1, 958, 3807, 4321, 4279, 4321, 4283, 4321, 1, 1324, 1369, 4329, 3863, 4329, 4063, 4329, 4137, 4329, 1, 214, 1631, 4339, 2685, 4339, 0, 214, 1, 1562, 1, 444, 449, 4349, 7, 4349, 265, 4353, 2647, 4355, 2658, 4349, 251, 4349, 2647, 4349, 375, 4362, 375, 4349, 2647, 4366, 0, 444, 2701, 4371, 1689, 4371, 1705, 4371, 447, 4371, 2665, 4371, 2241, 4371, 3785, 4371, 2671, 4371, 265, 4371, 331, 4371, 2663, 4371, 375, 4393, 375, 4371, 1, 510, 257, 4399, 1, 1058, 0, 1396, 0, 1406, 0, 628, 375, 4409, 1, 652, 1, 288, 1, 267, 1741, 4417, 1, 1013, 1, 1375, 1, 333, 2903, 4425, 3361, 4425, 0, 1375, 2931, 4431, 2173, 4431, 1, 273, 2905, 4437, 1739, 4437, 6, 4436, 7, 4437, 4443, 4445, 6, 4437, 3359, 4437, 7, 4436, 4449, 4453, 0, 273, 2883, 4457, 2913, 4457, 3351, 4457, 3457, 4457, 2923, 4457, 1749, 4457, 1743, 4457, 1, 31, 3224, 4473, 3177, 4473, 113, 4476, 113, 4473, 3177, 4480, 1, 737, 3400, 4485, 3379, 4485, 803, 4488, 803, 4485, 3379, 4492, 1, 317, 2903, 4497, 3361, 4497, 2900, 4497, 7, 4497, 265, 4505, 2897, 4507, 1753, 4497, 1745, 4497, 3330, 4497, 2897, 4497, 375, 4516, 3309, 4497, 375, 4520, 375, 4497, 2897, 4524, 3309, 4524, 0, 317, 7, 4530, 2913, 4531, 375, 4535, 375, 4531, 1, 507, 1, 245, 0, 1397, 1, 913, 0, 1407, 1, 653, 11, 4551, 1, 289, 1, 629, 713, 4557, 25, 4557, 305, 4557, 0, 629, 375, 4565, 0, 340, 3785, 4569, 4311, 4569, 4329, 4569, 4555, 4569, 0, 766, 1413, 4579, 922, 4579, 903, 4579, 483, 4584, 483, 4579, 903, 4588, 0, 66, 75, 4593, 7, 4593, 3113, 4593, 9, 4599, 3251, 4593, 9, 4603, 375, 4593, 483, 4593, 9, 4593, 1, 340, 331, 4613, 1, 766, 483, 4616, 2591, 4617, 483, 4621, 1, 66, 5, 4624, 6, 4627, 3248, 4625, 1941, 4625, 9, 4633, 36, 4625, 3247, 4625, 9, 4638, 9, 4624, 1941, 4643, 3807, 4643, 33, 4625, 9, 4648, 9, 4625, 3247, 4652, 33, 4652, 3807, 4625, 9, 4659, 0, 1170, 2615, 4663, 903, 4665, 0, 112, 3972, 4669, 3270, 4669, 3086, 4669, 1938, 4669, 1937, 4669, 9, 4678, 2564, 4669, 3071, 4669, 9, 4684, 3267, 4669, 9, 4688, 2563, 4669, 9, 4692, 9, 4669, 3267, 4696, 3933, 4696, 1937, 4696, 3071, 4696, 2563, 4696, 3933, 4669, 9, 4708, 1, 1170, 1413, 4713, 922, 4713, 483, 4713, 903, 4718, 903, 4713, 483, 4722, 1, 112, 2, 4727, 7, 4729, 3261, 4727, 9, 4733, 25, 4727, 903, 4727, 587, 4727, 9, 4727, 0, 972, 3059, 4745, 1925, 4745, 3563, 4745, 3553, 4745, 3549, 4745, 3547, 4745, 2005, 4745, 2001, 4745, 1595, 4745, 1945, 4745, 1599, 4745, 2239, 4745, 1717, 4745, 2619, 4745, 1769, 4745, 1947, 4745, 1933, 4745, 1943, 4745, 955, 4781, 9, 4781, 0, 802, 807, 4787, 375, 4787, 7, 4787, 805, 4793, 265, 4793, 483, 4787, 0, 144, 483, 4801, 1, 972, 3551, 4805, 2003, 4805, 375, 4805, 955, 4805, 9, 4805, 1011, 4805, 1, 802, 713, 4819, 483, 4819, 1, 144, 0, 256, 2309, 4827, 4437, 4827, 264, 4826, 299, 4833, 264, 4827, 367, 4837, 265, 4826, 2309, 4841, 4805, 4827, 4613, 4827, 375, 4827, 510, 4827, 483, 4827, 9, 4852, 9, 4827, 483, 4856, 0, 1504, 1, 256, 2798, 4863, 7, 4863, 265, 4867, 264, 4862, 264, 4863, 2795, 4863, 375, 4874, 265, 4862, 4873, 4879, 305, 4863, 713, 4863, 25, 4863, 375, 4863, 2795, 4888, 265, 4863, 4871, 4893, 1, 164, 0, 374, 241, 4899, 0, 1346, 9, 4903, 0, 154, 0, 1412, 2853, 4909, 2163, 4909, 0, 1418, 1, 1346, 1, 154, 483, 4919, 1, 1412, 241, 4922, 1, 1290, 4915, 4927, 1, 1280, 1, 246, 0, 566, 2596, 4935, 586, 4934, 705, 4939, 586, 4935, 795, 4943, 2595, 4935, 587, 4946, 587, 4935, 2595, 4950, 0, 1086, 375, 4955, 0, 922, 1759, 4959, 2265, 4959, 3367, 4959, 4421, 4959, 1953, 4959, 1, 566, 5, 4971, 6, 4973, 1950, 4971, 1949, 4971, 9, 4978, 586, 4970, 586, 4971, 587, 4970, 4985, 4987, 4827, 4971, 9, 4971, 1949, 4992, 4745, 4971, 4569, 4971, 587, 4971, 4983, 5001, 1, 1086, 9, 5005, 1, 922, 3369, 5009, 555, 5009, 257, 5009, 1, 932, 0, 88, 3171, 5019, 10, 5018, 101, 5023, 101, 5019, 10, 5019, 107, 5029, 0, 934, 375, 5033, 0, 1108, 587, 5037, 1, 1362, 265, 5041, 1, 88, 93, 5045, 1643, 5047, 93, 5044, 1645, 5051, 1645, 5045, 2135, 5045, 973, 5044, 4745, 5059, 3163, 5045, 3173, 5045, 3167, 5045, 7, 5044, 10, 5044, 10, 5045, 11, 5044, 3807, 5075, 5073, 5075, 33, 5045, 21, 5045, 973, 5045, 4805, 5085, 3807, 5045, 4279, 5045, 4283, 5045, 4745, 5045, 11, 5045, 5071, 5097, 1, 1304, 1, 1108, 973, 5103, 972, 5102, 5105, 5107, 972, 5103, 973, 5102, 5111, 5113, 257, 5103, 0, 260, 0, 580, 0, 136, 0, 668, 1, 260, 4139, 5127, 4138, 5127, 264, 5126, 5131, 5133, 264, 5127, 4137, 5137, 265, 5126, 4137, 5141, 5137, 5142, 5129, 5141, 5138, 5141, 5137, 5141, 4137, 5150, 265, 5127, 4137, 5154, 5133, 5157, 5133, 5155, 4137, 5161, 4137, 5127, 265, 5165, 5137, 5167, 265, 5164, 5133, 5171, 1, 580, 1, 136, 5019, 5177, 1, 524, 5125, 5181, 1, 296, 5019, 5185, 0, 1413, 2559, 5189, 2209, 5189, 4925, 5189, 0, 1419, 5181, 5197, 1, 295, 973, 5201, 972, 5201, 49, 5201, 48, 5201, 972, 5200, 5203, 5211, 973, 5200, 5205, 5215, 48, 5200, 5207, 5219, 49, 5200, 5209, 5223, 1, 1413, 1417, 5227, 1, 1291, 5125, 5231, 5197, 5231, 0, 1087, 375, 5237, 0, 923, 1793, 5241, 2941, 5241, 5012, 5241, 3543, 5241, 3559, 5241, 2891, 5241, 5017, 5241, 1955, 5241, 555, 5241, 5009, 5258, 5009, 5241, 555, 5262, 1, 1087, 5037, 5267, 1, 923, 555, 5270, 4959, 5273, 241, 5270, 4959, 5277, 4959, 5271, 555, 5281, 1, 933, 4959, 5285, 0, 935, 375, 5289, 0, 1109, 5005, 5293, 1, 935, 0, 669, 4927, 5299, 1, 525, 4915, 5303, 5299, 5303, 1, 669, 1, 297, 0, 341, 483, 5313, 3747, 5313, 3689, 5313, 3345, 5313, 4415, 5313, 0, 257, 2255, 5325, 4888, 5325, 4881, 5325, 3467, 5325, 2919, 5325, 4871, 5325, 4893, 5336, 4894, 5325, 7, 5324, 4863, 5343, 4872, 5325, 4879, 5347, 4869, 5325, 4893, 5325, 4871, 5352, 5343, 5353, 3, 5325, 5, 5358, 4862, 5360, 4863, 5361, 5363, 5365, 5343, 5364, 4862, 5361, 4863, 5360, 5371, 5373, 5344, 5361, 5343, 5361, 4863, 5378, 5, 5325, 3, 5382, 4862, 5384, 4863, 5385, 5387, 5389, 5343, 5388, 4862, 5385, 4863, 5384, 5395, 5397, 5344, 5385, 5343, 5385, 4863, 5402, 264, 5325, 4863, 5406, 4879, 5409, 5344, 5407, 5343, 5407, 4863, 5414, 4863, 5407, 4871, 5419, 5343, 5418, 7, 5325, 265, 5425, 4863, 5427, 266, 5325, 375, 5325, 4863, 5432, 510, 5325, 483, 5325, 9, 5438, 9, 5325, 483, 5442, 251, 5325, 265, 5446, 265, 5447, 4892, 5325, 265, 5325, 257, 5454, 1, 5457, 7, 5455, 5459, 5461, 0, 5461, 5457, 5465, 251, 5454, 4863, 5454, 4863, 5325, 3, 5472, 5, 5474, 5, 5472, 3, 5478, 375, 5472, 7, 5473, 5361, 5485, 5385, 5485, 5477, 5485, 5481, 5485, 5407, 5485, 264, 5472, 4879, 5497, 5485, 5497, 264, 5473, 4893, 5503, 265, 5472, 265, 5324, 4417, 5509, 251, 5509, 1, 341, 5325, 5515, 331, 5514, 1, 257, 445, 5521, 265, 5522, 449, 5521, 448, 5521, 414, 5521, 415, 5521, 421, 5521, 420, 5521, 253, 5521, 265, 5538, 340, 5521, 341, 5521, 272, 5520, 241, 5546, 273, 5521, 5549, 5551, 272, 5521, 273, 5520, 412, 5521, 251, 5559, 241, 5520, 265, 5562, 5551, 5565, 272, 5563, 5557, 5569, 500, 5521, 432, 5521, 501, 5521, 413, 5520, 5525, 5579, 5529, 5579, 5533, 5579, 5535, 5579, 5555, 5579, 5541, 5579, 251, 5579, 5559, 5592, 5560, 5579, 5559, 5579, 251, 5598, 5577, 5579, 433, 5521, 5579, 5605, 264, 5520, 5543, 5609, 367, 5609, 264, 5521, 299, 5615, 412, 5520, 5527, 5619, 5531, 5619, 5537, 5619, 5551, 5619, 5573, 5619, 5575, 5619, 413, 5521, 375, 5632, 5619, 5635, 251, 5632, 5619, 5639, 5619, 5633, 251, 5643, 483, 5632, 5619, 5647, 9, 5632, 5619, 5651, 7, 5521, 265, 5654, 5609, 5657, 265, 5655, 5615, 5661, 2227, 5521, 375, 5665, 4841, 5521, 375, 5669, 375, 5520, 2227, 5673, 4841, 5673, 4827, 5673, 375, 5521, 413, 5680, 5619, 5683, 413, 5681, 5559, 5687, 483, 5521, 413, 5690, 5619, 5693, 413, 5691, 5559, 5697, 9, 5521, 413, 5700, 5619, 5703, 413, 5701, 5559, 5707, 251, 5521, 413, 5710, 5619, 5713, 413, 5711, 5559, 5717, 265, 5521, 445, 5720, 5579, 5723, 253, 5720, 5579, 5727, 7, 5720, 5609, 5731, 4827, 5521, 3, 5735, 5, 5736, 5, 5735, 3, 5740, 375, 5735, 7, 5734, 5739, 5747, 5743, 5747, 264, 5735, 5747, 5753, 265, 5735, 265, 5520, 2647, 5759, 5545, 5759, 1783, 5759, 241, 5758, 5551, 5767, 0, 1171, 4714, 5771, 4716, 5771, 4720, 5771, 4724, 5771, 2850, 5771, 1413, 5771, 4713, 5782, 922, 5771, 4713, 5786, 4718, 5771, 903, 5790, 2849, 5771, 903, 5794, 483, 5771, 4722, 5798, 903, 5798, 4713, 5802, 4713, 5798, 903, 5806, 4722, 5771, 483, 5810, 903, 5771, 4718, 5814, 2849, 5814, 483, 5814, 4713, 5820, 4713, 5814, 483, 5824, 4713, 5771, 1413, 5828, 922, 5828, 483, 5828, 903, 5834, 903, 5828, 483, 5838, 0, 973, 1895, 5843, 2037, 5843, 1597, 5843, 1601, 5843, 2142, 5843, 2313, 5843, 4810, 5843, 1715, 5843, 1771, 5843, 1935, 5843, 2140, 5843, 2139, 5843, 955, 5866, 9, 5866, 375, 5843, 4805, 5872, 483, 5843, 9, 5843, 2139, 5878, 955, 5843, 2139, 5882, 1011, 5843, 4805, 5843, 375, 5888, 1, 1171, 3, 5892, 4663, 5895, 903, 5897, 483, 5892, 4663, 5901, 903, 5903, 4663, 5893, 1413, 5907, 922, 5907, 483, 5907, 903, 5912, 903, 5907, 483, 5916, 1, 973, 956, 5920, 4745, 5923, 88, 5920, 4745, 5927, 5, 5920, 4745, 5931, 1011, 5933, 3, 5920, 955, 5936, 4745, 5939, 9, 5936, 4745, 5943, 4745, 5937, 955, 5947, 9, 5947, 375, 5920, 4745, 5953, 955, 5920, 3, 5956, 4745, 5959, 5325, 5921, 9, 5920, 3, 5964, 4745, 5967, 4745, 5921, 375, 5971, 0, 767, 903, 5974, 4617, 5977, 483, 5979, 4617, 5975, 1413, 5983, 922, 5983, 903, 5983, 483, 5988, 483, 5983, 903, 5992, 0, 567, 4989, 5997, 4983, 5997, 5001, 6000, 5002, 5997, 4984, 5997, 4987, 6007, 5001, 5997, 4983, 6010, 3, 5997, 7, 6014, 4970, 6016, 4971, 6017, 6019, 6021, 4970, 6017, 4971, 6016, 6025, 6027, 7, 5997, 3, 6030, 4970, 6032, 4971, 6033, 6035, 6037, 4970, 6033, 4971, 6032, 6041, 6043, 3, 5996, 7, 6047, 2, 5996, 4992, 6051, 6015, 6051, 7, 6055, 4971, 6057, 9, 6051, 4971, 6060, 4971, 6051, 9, 6064, 586, 5997, 4971, 6068, 4987, 6071, 4971, 6069, 4983, 6075, 2, 5997, 6048, 6079, 4971, 6081, 7, 6079, 6047, 6084, 4971, 6087, 4971, 6085, 6047, 6091, 6047, 6079, 7, 6094, 4971, 6097, 4992, 5997, 587, 6101, 2839, 5997, 587, 6105, 9, 5997, 4971, 6108, 587, 6111, 4971, 5997, 2, 6115, 7, 6117, 4975, 6117, 586, 6114, 4987, 6123, 5, 6114, 6, 6127, 6117, 6129, 6119, 6127, 586, 6115, 5001, 6135, 9, 6114, 587, 6139, 587, 6115, 9, 6143, 0, 67, 4636, 6147, 37, 6147, 3008, 6147, 4656, 6147, 4650, 6147, 7, 6146, 4643, 6159, 2233, 6159, 4625, 6159, 9, 6165, 5, 6147, 6, 6169, 36, 6147, 4625, 6172, 3807, 6173, 4648, 6147, 9, 6178, 3003, 6147, 9, 6182, 33, 6146, 6151, 6187, 3856, 6187, 3837, 6187, 9, 6192, 9, 6187, 3837, 6196, 33, 6147, 4652, 6200, 3807, 6201, 9, 6205, 9, 6200, 4625, 6208, 3807, 6209, 4625, 6200, 9, 6214, 4652, 6147, 33, 6218, 9, 6147, 4648, 6222, 3003, 6222, 33, 6222, 4625, 6228, 3807, 6229, 33, 6223, 3837, 6235, 4625, 6222, 33, 6238, 4625, 6147, 75, 6243, 4629, 6243, 7, 6243, 4627, 6249, 6171, 6243, 375, 6243, 36, 6242, 33, 6242, 9, 6258, 9, 6242, 33, 6262, 0, 89, 5079, 6267, 5071, 6267, 5097, 6270, 5098, 6267, 5072, 6267, 5075, 6277, 5097, 6267, 5071, 6280, 107, 6267, 5, 6267, 7, 6286, 5044, 6288, 5045, 6289, 6291, 6293, 5044, 6289, 5045, 6288, 6297, 6299, 7, 6267, 5, 6302, 5044, 6304, 5045, 6305, 6307, 6309, 5044, 6305, 5045, 6304, 6313, 6315, 5, 6266, 7, 6318, 5045, 6321, 7, 6319, 7, 6266, 5, 6326, 5045, 6329, 5075, 6327, 2221, 6327, 5045, 6327, 4, 6266, 6287, 6339, 7, 6341, 5045, 6343, 10, 6266, 5075, 6347, 2221, 6347, 5045, 6347, 10, 6267, 5097, 6355, 5045, 6354, 5075, 6359, 5045, 6355, 5071, 6363, 1274, 6267, 4, 6267, 6324, 6369, 5045, 6371, 7, 6369, 6319, 6374, 5045, 6377, 5044, 6374, 5045, 6375, 6319, 6383, 6381, 6383, 5044, 6375, 5045, 6374, 6389, 6391, 6319, 6369, 7, 6394, 5045, 6397, 6, 6267, 3, 6400, 3, 6267, 6, 6404, 21, 6267, 11, 6409, 5045, 6411, 5045, 6267, 10, 6414, 5075, 6417, 10, 6415, 5097, 6421, 5311, 6267, 11, 6266, 2969, 6427, 5082, 6427, 5045, 6427, 21, 6432, 21, 6427, 5045, 6436, 1, 767, 4580, 6441, 4582, 6441, 4586, 6441, 4590, 6441, 2862, 6441, 1413, 6441, 4579, 6452, 922, 6441, 4579, 6456, 4584, 6441, 483, 6460, 2861, 6441, 483, 6464, 759, 6440, 903, 6441, 4588, 6470, 483, 6470, 4579, 6474, 4579, 6470, 483, 6478, 4588, 6441, 903, 6482, 483, 6441, 4584, 6486, 2861, 6486, 903, 6486, 4579, 6492, 4579, 6486, 903, 6496, 4579, 6441, 1413, 6500, 922, 6500, 903, 6500, 483, 6506, 483, 6500, 903, 6510, 1, 567, 5, 6514, 6, 6517, 4935, 6517, 2137, 6515, 9, 6523, 14, 6515, 2, 6515, 563, 6529, 4935, 6531, 6519, 6529, 4935, 6535, 7, 6529, 6520, 6539, 4935, 6539, 6517, 6542, 6517, 6539, 4935, 6546, 1197, 6529, 4935, 6551, 6, 6515, 5, 6554, 5, 6515, 6, 6558, 5325, 6515, 903, 6515, 9, 6514, 4950, 6567, 587, 6567, 4935, 6570, 4935, 6567, 587, 6574, 241, 6515, 4950, 6515, 9, 6581, 587, 6515, 9, 6585, 4935, 6587, 4935, 6584, 9, 6591, 4935, 6515, 2, 6594, 7, 6597, 5, 6595, 6539, 6601, 6599, 6601, 6, 6601, 6597, 6607, 9, 6595, 587, 6611, 587, 6594, 9, 6615, 5843, 6515, 5313, 6515, 587, 6514, 1, 67, 4594, 6625, 4606, 6625, 3280, 6625, 75, 6625, 4593, 6632, 2146, 6625, 2145, 6625, 9, 6638, 7, 6625, 73, 6643, 4593, 6645, 375, 6625, 4593, 6648, 33, 6624, 4593, 6653, 9, 6655, 9, 6625, 3273, 6658, 2145, 6658, 4593, 6625, 75, 6664, 375, 6664, 36, 6665, 33, 6665, 9, 6672, 9, 6665, 33, 6676, 3273, 6625, 9, 6680, 1, 89, 1657, 6685, 25, 6685, 3565, 6685, 3573, 6685, 3273, 6685, 21, 6684, 483, 6685, 5843, 6685, 11, 6684, 0, 1487, 10, 6705, 7, 6705, 5, 6708, 5, 6705, 7, 6712, 0, 1347, 0, 113, 2149, 6719, 9, 6721, 4736, 6719, 9, 6725, 3023, 6719, 9, 6729, 4740, 6719, 9, 6733, 2879, 6719, 9, 6737, 587, 6719, 4727, 6740, 9, 6743, 25, 6719, 4727, 6746, 9, 6749, 4727, 6719, 5, 6753, 6, 6755, 4731, 6755, 2, 6752, 7, 6761, 6755, 6763, 6757, 6761, 25, 6752, 9, 6769, 587, 6752, 9, 6773, 9, 6753, 25, 6777, 587, 6777, 3255, 6719, 9, 6783, 0, 137, 1, 113, 31, 6788, 2, 6788, 7, 6793, 4669, 6793, 4697, 6789, 14, 6788, 6, 6789, 6, 6788, 5, 6804, 11, 6788, 5, 6808, 5, 6788, 6, 6813, 6, 6812, 4696, 6813, 9, 6813, 4669, 6820, 4669, 6813, 9, 6824, 7, 6788, 6815, 6829, 15, 6788, 6803, 6833, 8, 6788, 8, 6789, 4669, 6839, 1368, 6789, 5, 6789, 35, 6845, 4669, 6847, 6795, 6845, 4669, 6851, 6, 6845, 6796, 6855, 4669, 6855, 6793, 6858, 6793, 6855, 4669, 6862, 1171, 6845, 4669, 6867, 17, 6845, 4669, 6871, 7, 6789, 6811, 6875, 6807, 6875, 6817, 6875, 6801, 6875, 2, 6874, 2, 6789, 7, 6886, 30, 6788, 3867, 6891, 25, 6788, 4696, 6895, 3867, 6895, 9, 6899, 9, 6894, 3867, 6903, 4669, 6895, 9, 6906, 9, 6895, 4669, 6910, 587, 6788, 4696, 6915, 9, 6915, 4669, 6918, 4669, 6915, 9, 6922, 25, 6789, 4473, 6927, 6791, 6927, 3972, 6927, 3933, 6927, 9, 6934, 9, 6927, 3933, 6938, 4696, 6789, 6837, 6943, 25, 6943, 587, 6943, 9, 6789, 6837, 6951, 4669, 6953, 587, 6951, 4669, 6957, 25, 6951, 4669, 6961, 4669, 6950, 25, 6965, 6837, 6965, 587, 6965, 4669, 6789, 5, 6972, 6, 6975, 2, 6973, 6855, 6979, 6977, 6979, 7, 6979, 6975, 6985, 25, 6973, 9, 6989, 587, 6973, 9, 6993, 9, 6972, 6837, 6997, 25, 6997, 587, 6997, 9, 6973, 6839, 7005, 9, 6788, 6799, 7009, 6840, 7009, 6839, 7009, 4669, 7014, 4669, 7009, 6839, 7018, 25, 7008, 3867, 7023, 25, 7009, 3933, 7027, 1, 137, 6267, 7031, 0, 375, 413, 7034, 413, 7035, 241, 7034, 3307, 7041, 2885, 7041, 0, 261, 0, 803, 16, 7049, 7, 7049, 4, 7052, 4, 7049, 7, 7056, 0, 581, 0, 145, 1, 375, 317, 7064, 265, 7065, 256, 7068, 256, 7069, 4901, 7065, 4, 7065, 2, 7077, 265, 7077, 2, 7076, 4899, 7083, 2, 7065, 265, 7087, 4, 7086, 4899, 7091, 2, 7064, 265, 7064, 3, 7064, 7084, 7099, 7092, 7099, 7083, 7099, 4899, 7104, 7091, 7099, 4899, 7108, 7075, 7099, 4899, 7099, 7083, 7114, 7091, 7114, 240, 7064, 240, 7065, 265, 7123, 7, 7125, 7114, 7123, 7099, 7123, 4899, 7130, 4899, 7123, 7099, 7134, 413, 7065, 7, 7138, 3, 7065, 7079, 7143, 4899, 7145, 7081, 7143, 4899, 7149, 5, 7065, 7089, 7153, 4899, 7155, 445, 7065, 4349, 7159, 7121, 7159, 367, 7065, 4863, 7165, 973, 7065, 4805, 7169, 316, 7064, 4067, 7173, 973, 7064, 4745, 7177, 445, 7064, 4371, 7181, 257, 7064, 4841, 7185, 2227, 7185, 4827, 7185, 7071, 7185, 305, 7064, 4067, 7195, 241, 7197, 241, 7194, 4067, 7201, 587, 7064, 257, 7065, 4863, 7207, 7073, 7207, 628, 7065, 587, 7065, 11, 7214, 11, 7065, 587, 7218, 241, 7219, 305, 7065, 4497, 7225, 7067, 7225, 4254, 7225, 4213, 7225, 241, 7232, 241, 7225, 4213, 7236, 4900, 7065, 7121, 7241, 7095, 7241, 7097, 7241, 241, 7065, 7095, 7249, 4899, 7251, 7097, 7249, 4899, 7255, 6, 7249, 7121, 7249, 4899, 7261, 4899, 7248, 7121, 7265, 7095, 7265, 7097, 7265, 4899, 7065, 241, 7272, 7121, 7275, 7095, 7275, 7097, 7275, 241, 7273, 7123, 7283, 241, 7064, 4371, 7287, 7141, 7287, 7127, 7287, 7075, 7287, 7134, 7287, 7123, 7287, 4899, 7298, 4899, 7287, 7123, 7302, 305, 7286, 4067, 7307, 305, 7287, 4213, 7311, 1, 261, 413, 7315, 3357, 7315, 264, 7319, 265, 7318, 7321, 7323, 264, 7318, 265, 7319, 7327, 7329, 1, 803, 737, 7332, 4799, 7333, 1274, 7332, 6, 7333, 2, 7341, 2, 7340, 4787, 7345, 2, 7333, 6, 7348, 4787, 7351, 2, 7332, 6, 7332, 3, 7356, 587, 7332, 3, 7360, 3, 7332, 7346, 7365, 7352, 7365, 7345, 7365, 4787, 7370, 7351, 7365, 4787, 7374, 6, 7365, 6, 7364, 7337, 7365, 4787, 7365, 7345, 7384, 7351, 7384, 7, 7332, 7379, 7391, 1275, 7332, 7341, 7395, 482, 7332, 482, 7333, 7384, 7401, 7365, 7401, 4787, 7404, 4787, 7401, 7365, 7408, 3, 7333, 7343, 7413, 4787, 7415, 7, 7333, 7363, 7419, 7359, 7419, 7381, 7419, 7339, 7419, 736, 7332, 3997, 7429, 713, 7332, 3997, 7433, 483, 7435, 483, 7432, 3997, 7439, 11, 7333, 483, 7443, 713, 7333, 4485, 7447, 7335, 7447, 4188, 7447, 4147, 7447, 483, 7454, 483, 7447, 4147, 7458, 4798, 7333, 7399, 7463, 7355, 7463, 483, 7333, 7355, 7469, 4787, 7471, 7399, 7469, 4787, 7475, 4787, 7468, 7399, 7479, 7355, 7479, 4787, 7333, 483, 7484, 7399, 7487, 7355, 7487, 483, 7485, 7401, 7493, 483, 7332, 7337, 7497, 7408, 7497, 7401, 7497, 4787, 7502, 4787, 7497, 7401, 7506, 713, 7496, 3997, 7511, 713, 7497, 4147, 7515, 1, 145, 586, 7519, 7, 7519, 3, 7522, 3, 7519, 7, 7526, 1, 155, 483, 7530, 0, 175, 482, 7535, 6, 7535, 2, 7538, 2, 7535, 6, 7542, 1, 1505, 1011, 7546, 6, 7549, 7, 7549, 6, 7548, 7553, 7555, 7, 7548, 7551, 7559, 1, 1363, 8, 7563, 6, 7563, 4, 7566, 4, 7563, 6, 7570, 1374, 7563, 4423, 7575, 1374, 7562, 4431, 7579, 265, 7562, 5189, 7583, 1, 165, 903, 7586, 6, 7589, 7, 7589, 6, 7588, 7593, 7595, 7, 7588, 7591, 7599, 1, 175, 44, 7602, 45, 7603, 7605, 7607, 44, 7603, 45, 7602, 7611, 7613, 0, 299, 3289, 7617, 2181, 7617, 3307, 7617, 2885, 7617, 1, 299, 4371, 7627, 2801, 7627, 1669, 7627, 5461, 7627, 3295, 7627, 305, 7626, 4067, 7639, 251, 7627, 305, 7627, 4213, 7645, 0, 705, 3371, 7649, 2183, 7649, 0, 101, 3157, 7655, 2185, 7655, 3175, 7655, 6697, 7655, 3037, 7655, 6685, 7655, 21, 7667, 1, 705, 3377, 7671, 713, 7670, 3997, 7675, 555, 7671, 713, 7671, 4147, 7681, 1, 101, 3163, 7685, 25, 7684, 3867, 7689, 21, 7685, 25, 7685, 3933, 7695, 0, 129, 2253, 7699, 21, 7699, 1, 129, 21, 7704, 0, 395, 2247, 7709, 4417, 7709, 265, 7709, 7, 7715, 251, 7709, 0, 829, 2251, 7721, 555, 7721, 1, 395, 2647, 7727, 1719, 7727, 251, 7726, 1, 829, 555, 7734, 0, 298, 265, 7739, 7, 7741, 7627, 7743, 2551, 7739, 7642, 7739, 4417, 7739, 7627, 7739, 251, 7752, 251, 7739, 7627, 7756, 1, 298, 2647, 7761, 1783, 7761, 251, 7760, 7617, 7767, 7617, 7761, 251, 7771, 0, 704, 2555, 7775, 7678, 7775, 7671, 7775, 555, 7780, 555, 7775, 7671, 7784, 0, 100, 2557, 7789, 7692, 7789, 2969, 7789, 5082, 7789, 5045, 7789, 21, 7798, 7685, 7789, 21, 7802, 21, 7789, 7685, 7806, 5045, 7806, 1, 704, 555, 7812, 7649, 7815, 7649, 7813, 555, 7819, 1, 100, 21, 7822, 7655, 7825, 7655, 7823, 21, 7829, 0, 128, 3159, 7833, 2197, 7833, 7707, 7833, 7705, 7833, 21, 7841, 1, 128, 3161, 7845, 7702, 7845, 25, 7844, 3867, 7851, 21, 7845, 7699, 7854, 7699, 7845, 21, 7858, 25, 7845, 3933, 7863, 0, 394, 3291, 7867, 2193, 7867, 7733, 7867, 2885, 7867, 3307, 7867, 7727, 7867, 251, 7879, 0, 828, 3373, 7883, 2195, 7883, 7737, 7883, 7735, 7883, 555, 7891, 1, 394, 4371, 7895, 3293, 7895, 7718, 7895, 1721, 7895, 1725, 7895, 7717, 7895, 305, 7894, 4067, 7909, 251, 7895, 7709, 7912, 7709, 7895, 251, 7916, 305, 7895, 4213, 7921, 1, 828, 3375, 7925, 7724, 7925, 713, 7924, 3997, 7931, 555, 7925, 7721, 7934, 7721, 7925, 555, 7938, 713, 7925, 4147, 7943, 0, 8, 6, 7947, 3, 7948, 1274, 7947, 113, 7947, 3, 7947, 0, 7957, 6, 7956, 0, 7956, 9, 7963, 11, 7957, 587, 7947, 1, 10, 5081, 7971, 5026, 7971, 7, 7971, 2, 7976, 1368, 7971, 5097, 7971, 931, 7971, 1417, 7971, 939, 7971, 941, 7971, 272, 7971, 1476, 7971, 280, 7971, 949, 7971, 1517, 7971, 4696, 7971, 149, 7971, 631, 7971, 970, 7971, 50, 7971, 764, 7971, 357, 7971, 367, 7971, 471, 7971, 1249, 7971, 5019, 7971, 101, 8022, 128, 7971, 101, 7971, 5019, 8028, 4669, 7971, 9, 8032, 759, 7971, 33, 8036, 1471, 7971, 265, 8040, 959, 7971, 33, 8044, 253, 7971, 265, 8048, 113, 7971, 9, 8052, 375, 7971, 88, 7971, 89, 7971, 2, 7971, 1, 8063, 7, 8062, 1, 8062, 11, 8069, 9, 8063, 3, 7971, 9, 8074, 33, 7971, 959, 8078, 47, 8078, 759, 8078, 25, 7971, 305, 7971, 713, 7971, 2, 7970, 8059, 8093, 8077, 8093, 8075, 8093, 9, 8099, 3867, 8093, 3997, 8093, 4067, 8093, 3, 7970, 4696, 8109, 8061, 8109, 8072, 8109, 8063, 8109, 9, 8116, 4669, 8109, 9, 8120, 9, 8109, 4669, 8124, 8063, 8124, 47, 7971, 33, 8130, 53, 7971, 265, 8134, 265, 7971, 253, 8138, 1471, 8138, 53, 8138, 587, 7971, 483, 7971, 9, 7971, 4669, 8150, 113, 8150, 3, 8150, 8093, 8157, 3, 8151, 8063, 8161, 0, 10, 203, 8165, 107, 8165, 5019, 8169, 85, 8165, 2215, 8165, 2221, 8165, 2233, 8165, 5075, 8165, 4643, 8165, 5045, 8165, 25, 8185, 4551, 8165, 922, 8165, 1413, 8165, 273, 8165, 281, 8165, 1477, 8165, 1516, 8165, 948, 8165, 4625, 8165, 9, 8205, 759, 8165, 959, 8165, 67, 8165, 9, 8213, 1505, 8165, 1011, 8216, 88, 8165, 33, 8221, 89, 8165, 5019, 8225, 3, 8165, 33, 8229, 9, 8231, 8063, 8229, 9, 8228, 33, 8237, 2, 8165, 9, 8241, 33, 8165, 1141, 8165, 1447, 8165, 2, 8164, 2215, 8251, 2221, 8251, 5075, 8251, 2233, 8251, 4643, 8251, 8229, 8251, 4625, 8251, 9, 8265, 4295, 8251, 3833, 8251, 4321, 8251, 5045, 8251, 3, 8164, 8241, 8277, 8093, 8277, 3837, 8277, 4287, 8277, 4303, 8277, 128, 8277, 101, 8277, 113, 8277, 9, 8292, 9, 8277, 113, 8296, 47, 8165, 165, 8165, 903, 8302, 265, 8165, 587, 8165, 1011, 8165, 1505, 8310, 1369, 8165, 483, 8165, 903, 8316, 903, 8165, 483, 8320, 165, 8320, 9, 8165, 3, 8326, 33, 8329, 3, 8327, 113, 8333, 0, 240, 4266, 8337, 4888, 8337, 4892, 8337, 4213, 8337, 375, 8344, 4863, 8337, 375, 8348, 265, 8348, 261, 8337, 3335, 8337, 375, 8357, 347, 8337, 386, 8337, 331, 8337, 305, 8337, 375, 8366, 340, 8337, 331, 8371, 375, 8337, 4213, 8374, 4863, 8374, 305, 8374, 1325, 8337, 59, 8337, 7, 8337, 265, 8387, 4213, 8389, 4863, 8389, 305, 8389, 265, 8386, 331, 8397, 7, 8336, 5141, 8401, 5137, 8402, 5137, 8401, 5141, 8406, 5150, 8401, 5154, 8401, 5133, 8413, 5161, 8401, 5127, 8401, 265, 8419, 5137, 8421, 265, 8418, 5133, 8425, 265, 8401, 5127, 8429, 5141, 8431, 5127, 8428, 5133, 8435, 3785, 8401, 4329, 8401, 4311, 8401, 483, 8337, 9, 8337, 1275, 8337, 15, 8337, 265, 8337, 4863, 8452, 257, 8452, 1, 8457, 6, 8452, 1, 8461, 241, 8462, 241, 8461, 1, 8466, 7, 8452, 331, 8471, 7, 8453, 7895, 8475, 7287, 8475, 8465, 8475, 8469, 8475, 7627, 8475, 8459, 8475, 0, 8475, 8457, 8489, 375, 8475, 1, 264, 3293, 8495, 7718, 8495, 3295, 8495, 3305, 8495, 3301, 8495, 5512, 8495, 5451, 8495, 7756, 8495, 7091, 8495, 4899, 8512, 7083, 8495, 4899, 8516, 7092, 8495, 7084, 8495, 4696, 8495, 7075, 8495, 7123, 8495, 4899, 8528, 7134, 8495, 445, 8495, 4349, 8535, 8386, 8495, 331, 8539, 471, 8495, 367, 8495, 357, 8495, 631, 8495, 1249, 8495, 628, 8495, 8387, 8495, 8401, 8495, 4137, 8495, 3863, 8495, 4063, 8495, 8475, 8495, 4371, 8495, 4549, 8495, 4545, 8495, 407, 8495, 1417, 8495, 665, 8495, 338, 8495, 1480, 8495, 336, 8495, 4745, 8495, 4669, 8495, 9, 8586, 4899, 8495, 7091, 8590, 7083, 8590, 7123, 8590, 4569, 8495, 7709, 8495, 251, 8600, 341, 8495, 4863, 8605, 241, 8605, 253, 8495, 331, 8610, 251, 8495, 7709, 8614, 5509, 8614, 7739, 8614, 256, 8495, 375, 8623, 7739, 8495, 251, 8626, 5509, 8495, 251, 8630, 257, 8495, 305, 8635, 53, 8495, 331, 8638, 1471, 8495, 331, 8642, 6, 8495, 4349, 8647, 4497, 8647, 413, 8647, 4213, 8647, 8109, 8647, 4147, 8647, 3933, 8647, 445, 8647, 316, 8647, 4713, 8647, 4863, 8647, 8337, 8647, 305, 8647, 241, 8672, 241, 8647, 305, 8676, 587, 8647, 8387, 8647, 7, 8495, 3785, 8685, 4329, 8685, 4311, 8685, 8337, 8684, 331, 8693, 331, 8685, 8337, 8697, 15, 8685, 241, 8684, 375, 8703, 331, 8495, 253, 8706, 1471, 8706, 53, 8706, 305, 8495, 6, 8494, 8539, 8717, 8693, 8717, 4371, 8717, 8623, 8717, 8703, 8717, 8685, 8717, 8337, 8729, 241, 8729, 471, 8717, 367, 8717, 357, 8717, 1369, 8717, 341, 8717, 241, 8743, 4569, 8717, 4137, 8717, 4063, 8717, 3863, 8717, 8401, 8717, 7, 8494, 8389, 8757, 8555, 8757, 8374, 8757, 8670, 8757, 8635, 8757, 8676, 8757, 8647, 8757, 8337, 8770, 241, 8770, 8337, 8757, 8647, 8776, 375, 8776, 9, 8757, 375, 8757, 8337, 8784, 241, 8757, 1, 8789, 8647, 8791, 8647, 8788, 587, 8495, 11, 8796, 11, 8495, 587, 8800, 9, 8495, 4669, 8804, 1369, 8495, 17, 8495, 241, 8495, 1, 8813, 7, 8815, 8717, 8817, 7, 8814, 8647, 8821, 7, 8812, 8717, 8825, 375, 8825, 7, 8813, 1, 8830, 8647, 8833, 8647, 8831, 331, 8831, 6, 8813, 8337, 8495, 7, 8842, 8717, 8845, 331, 8845, 483, 8843, 9, 8843, 7, 8843, 8647, 8855, 375, 8855, 0, 264, 3299, 8861, 5431, 8861, 5469, 8861, 5449, 8861, 4888, 8861, 4863, 8861, 375, 8872, 629, 8861, 394, 8861, 299, 8861, 659, 8861, 623, 8861, 645, 8861, 101, 8861, 705, 8861, 128, 8861, 828, 8861, 3345, 8861, 3445, 8861, 375, 8899, 2981, 8861, 3049, 8861, 7195, 8861, 3461, 8861, 4613, 8861, 331, 8910, 4614, 8861, 375, 8861, 4863, 8916, 241, 8916, 803, 8861, 483, 8922, 113, 8861, 9, 8926, 256, 8861, 331, 8931, 5455, 8861, 251, 8935, 7, 8861, 331, 8939, 241, 8941, 241, 8938, 331, 8945, 331, 8861, 4613, 8948, 7, 8860, 3837, 8953, 8093, 8953, 394, 8953, 299, 8953, 375, 8953, 241, 8962, 4303, 8953, 4287, 8953, 241, 8953, 375, 8970, 483, 8861, 803, 8974, 9, 8861, 113, 8978, 17, 8861, 241, 8861, 375, 8984, 7, 8984, 331, 8989, 7, 8985, 375, 8993, 1, 240, 3342, 8997, 2900, 8997, 8672, 8997, 8743, 8997, 3795, 8997, 8770, 8997, 8729, 8997, 2658, 8997, 7159, 8997, 2703, 8997, 2660, 8997, 413, 8997, 8757, 8997, 8647, 9022, 8684, 8997, 8717, 9027, 8605, 8997, 457, 8997, 2647, 9032, 8647, 8997, 305, 9036, 8757, 9036, 8916, 8997, 257, 8997, 2647, 8997, 375, 9046, 457, 9046, 3341, 8997, 375, 9052, 2897, 8997, 375, 9056, 305, 8997, 8647, 9060, 340, 8997, 8717, 9065, 3785, 9065, 8495, 9065, 375, 8997, 3341, 9072, 2897, 9072, 2647, 9072, 8861, 9072, 7, 8997, 413, 9082, 0, 9085, 1, 9083, 264, 9088, 264, 9089, 8495, 9082, 8717, 9095, 8495, 9083, 8757, 9099, 305, 9099, 265, 9083, 2897, 9105, 3341, 9105, 2647, 9105, 9087, 9105, 1, 9105, 9085, 9115, 9093, 9105, 8861, 9105, 265, 9082, 8717, 9123, 3785, 9123, 9091, 9123, 8495, 9123, 483, 8997, 9, 8997, 265, 8997, 7, 9136, 8717, 9139, 3785, 9139, 8495, 9139, 7, 9137, 8647, 9147, 8495, 8997, 7, 9150, 8717, 9153, 7, 9151, 8647, 9157, 8861, 8997, 375, 9160, 0, 482, 6, 9165, 4, 9167, 803, 9165, 5, 9165, 587, 9173, 9, 9173, 5, 9164, 17, 9179, 19, 9165, 12, 9165, 9, 9165, 11, 9186, 11, 9165, 9, 9190, 1, 586, 4795, 9195, 807, 9195, 4787, 9198, 4788, 9195, 4790, 9195, 8374, 9195, 8389, 9195, 4797, 9195, 8086, 9195, 8090, 9195, 8251, 9195, 4283, 9195, 4279, 9195, 3807, 9195, 1491, 9195, 631, 9195, 1160, 9195, 1466, 9195, 764, 9195, 357, 9195, 367, 9195, 471, 9195, 1249, 9195, 8800, 9195, 8647, 9195, 4787, 9195, 807, 9246, 375, 9246, 33, 9195, 759, 9252, 1141, 9195, 759, 9256, 803, 9195, 375, 9195, 4787, 9262, 8337, 9262, 8165, 9195, 265, 9269, 566, 9195, 567, 9195, 7971, 9195, 25, 9276, 713, 9276, 8495, 9195, 11, 9282, 4, 9195, 483, 9287, 5, 9195, 17, 9291, 483, 9290, 759, 9195, 1141, 9296, 1447, 9296, 33, 9296, 713, 9195, 7971, 9304, 25, 9195, 7971, 9308, 8337, 9195, 375, 9312, 4, 9194, 9273, 9317, 9295, 9317, 9291, 9317, 483, 9323, 4279, 9317, 3807, 9317, 4283, 9317, 8251, 9317, 5, 9194, 9275, 9335, 9288, 9335, 9287, 9335, 483, 9340, 8647, 9335, 9, 9335, 483, 9335, 9287, 9348, 1447, 9195, 759, 9352, 11, 9195, 8495, 9357, 8495, 9356, 9, 9195, 1011, 9195, 483, 9195, 5, 9366, 9317, 9369, 5, 9367, 9287, 9373, 0, 586, 7, 9377, 4, 9378, 16, 9377, 8800, 9377, 273, 9377, 1477, 9377, 281, 9377, 948, 9377, 1516, 9377, 750, 9377, 386, 9377, 347, 9377, 510, 9377, 767, 9377, 375, 9377, 305, 9406, 713, 9406, 165, 9377, 903, 9412, 8495, 9377, 11, 9416, 566, 9377, 759, 9421, 5, 9377, 759, 9425, 483, 9427, 483, 9424, 759, 9431, 4, 9377, 0, 9435, 7, 9434, 0, 9434, 587, 9441, 713, 9435, 713, 9377, 375, 9446, 305, 9377, 375, 9450, 4, 9376, 767, 9455, 5, 9376, 3837, 9459, 8093, 9459, 828, 9459, 705, 9459, 803, 9459, 483, 9468, 4287, 9459, 4303, 9459, 483, 9459, 803, 9476, 1505, 9377, 1011, 9480, 11, 9377, 8495, 9484, 903, 9377, 165, 9488, 9, 9377, 483, 9492, 1011, 9377, 1505, 9496, 483, 9377, 9, 9500, 5, 9500, 759, 9505, 5, 9501, 803, 9509, 1, 482, 6, 9513, 5, 9514, 14, 9513, 5, 9513, 1, 9521, 6, 9520, 1, 9520, 483, 9527, 11, 9513, 0, 902, 524, 9533, 1291, 9533, 767, 9533, 7, 9533, 3, 9541, 305, 9533, 375, 9544, 386, 9533, 347, 9533, 375, 9533, 305, 9552, 483, 9533, 11, 9556, 11, 9533, 483, 9560, 1, 1010, 5038, 9565, 5037, 9565, 587, 9568, 668, 9565, 1419, 9565, 8982, 9565, 7, 9564, 3867, 9579, 8277, 9579, 9459, 9579, 8953, 9579, 4067, 9579, 3997, 9579, 375, 9565, 483, 9565, 9, 9565, 587, 9596, 587, 9565, 5037, 9600, 9, 9600, 17, 9565, 8861, 9606, 8861, 9565, 7, 9611, 17, 9610, 0, 1010, 9535, 9617, 9537, 9617, 9559, 9617, 9563, 9617, 5, 9617, 6, 9627, 7, 9627, 5006, 9617, 5005, 9617, 9, 9634, 9362, 9617, 1290, 9617, 9533, 9641, 525, 9617, 9533, 9645, 8804, 9617, 8150, 9617, 922, 9617, 1413, 9617, 7971, 9617, 9, 9656, 6, 9617, 11, 9661, 9195, 9617, 9, 9664, 6, 9616, 17, 9669, 7, 9616, 9195, 9673, 9317, 9673, 4321, 9673, 3833, 9673, 4295, 9673, 5045, 9673, 19, 9617, 12, 9617, 11, 9617, 9, 9690, 483, 9617, 903, 9694, 1275, 9617, 17, 9698, 9533, 9701, 9, 9617, 5005, 9704, 9195, 9704, 7971, 9704, 8495, 9704, 11, 9704, 17, 9617, 1275, 9716, 9533, 9719, 903, 9617, 483, 9722, 8495, 9617, 9, 9726, 1, 902, 9573, 9731, 9575, 9731, 9599, 9731, 9605, 9731, 1418, 9731, 9565, 9741, 669, 9731, 9565, 9745, 8386, 9731, 7, 9731, 8337, 9750, 7, 9730, 9673, 9755, 8251, 9755, 4283, 9755, 3807, 9755, 4279, 9755, 483, 9731, 15, 9731, 1369, 9768, 9565, 9771, 1369, 9731, 15, 9774, 9565, 9777, 1011, 9731, 8337, 9731, 7, 9782, 9617, 9731, 6, 9786, 7, 9786, 6, 9787, 9791, 9793, 7, 9787, 9789, 9797, 0, 1274, 5, 9801, 1, 1368, 4904, 9805, 4903, 9805, 9, 9808, 9484, 9805, 1517, 9805, 1476, 9805, 272, 9805, 280, 9805, 949, 9805, 1197, 9805, 1471, 9805, 265, 9826, 253, 9805, 265, 9830, 53, 9805, 265, 9834, 5, 9804, 3867, 9839, 8277, 9839, 8953, 9839, 9459, 9839, 3997, 9839, 4067, 9839, 11, 9805, 9377, 9852, 9, 9805, 4903, 9856, 265, 9805, 1471, 9860, 253, 9860, 53, 9860, 9377, 9805, 11, 9868, 5, 9869, 0, 1368, 5075, 9875, 2221, 9875, 4643, 9875, 2233, 9875, 2215, 9875, 4339, 9875, 7, 9875, 5, 9888, 4, 9889, 10, 9875, 8714, 9875, 8800, 9875, 4625, 9875, 9, 9901, 47, 9875, 305, 9875, 8495, 9906, 959, 9875, 5045, 9875, 4551, 9875, 1325, 9875, 59, 9875, 331, 9875, 5, 9875, 0, 9923, 7, 9922, 0, 9922, 1369, 9929, 9287, 9923, 4, 9875, 1011, 9935, 8495, 9875, 10, 9938, 10, 9939, 305, 9938, 11, 9938, 9943, 9947, 11, 9939, 9941, 9951, 4, 9874, 8495, 9955, 8717, 9955, 4329, 9955, 4311, 9955, 3785, 9955, 5, 9874, 9195, 9967, 9755, 9967, 9317, 9967, 3833, 9967, 4295, 9967, 4321, 9967, 5045, 9967, 759, 9875, 11, 9875, 8495, 9984, 17, 9875, 903, 9875, 265, 9875, 15, 9875, 9195, 9875, 241, 9997, 1, 1274, 6,10001, 4,10002, 4,10003, 8,10001, 5123,10001, 5,10011, 4,10010, 10013,10015, 4,10011, 5,10010,10019,10021, 341,10001, 4663,10001, 903,10027, 1471,10001, 253,10001, 53,10001, 4,10001, 1,10037, 6,10036, 1,10036, 1275,10043, 5,10001, 9935,10047, 8337,10001, 9,10051, 5,10000, 8685,10055, 1369,10055, 8401,10055, 3863,10055, 4137,10055, 4063,10055, 4569,10055, 9955,10055, 241,10001, 17,10001, 1369,10001, 5,10077, 0, 14, 6,10081, 2,10082, 482,10081, 2,10081, 0,10089, 6,10088, 0,10088, 15,10095, 2,10080, 17,10099, 1369,10081, 17,10081, 1, 16, 7,10107, 3,10108, 586,10107, 8306,10107, 1447,10107, 1141,10107, 9875,10107, 241,10121, 265,10120, 9992,10107, 545,10107, 695,10107, 1382,10107, 1374,10107, 1386,10107, 59,10107, 1369,10138, 154,10107, 483,10143, 1325,10107, 1369,10146, 331,10107, 1369,10150, 3,10107, 1,10155, 7,10154, 1,10154, 17,10161, 8241,10155, 15,10154, 483,10167, 3,10106, 9673,10171, 8251,10171, 3807,10171, 4279,10171, 4283,10171, 9967,10171, 33,10107, 1369,10107, 331,10186, 1325,10186, 59,10186, 1011,10107, 265,10107, 8165,10196, 9875,10196, 1275,10107, 15,10107, 3,10204, 483,10207, 3,10205, 1369,10211, 8165,10107, 265,10214, 0, 16, 4,10219, 3,10220, 3,10221, 7,10219, 2,10226,10225,10229, 2,10227,10223,10233, 1368,10219,10225,10237, 902,10219,10233,10241, 59,10219, 1325,10219, 331,10219, 3,10219, 4,10250,10233,10253, 2,10219, 7,10256,10225,10259, 903,10257, 8495,10219, 587,10265, 10001,10219, 903,10269, 2,10218, 8495,10273, 8717,10273,10055,10273, 4311,10273, 4329,10273, 3785,10273, 265,10219, 1275,10219, 1, 14, 8982,10291, 8861,10291, 17,10294, 4745,10291, 1011,10299, 53,10291, 253,10291, 1471,10291, 2,10291, 3,10291, 483,10311,10257,10311, 59,10291, 17,10316, 62,10291, 1325,10291, 17,10322, 331,10291, 17,10326, 1328,10291, 334,10291, 393,10291, 1359,10291, 1031,10291, 499,10291, 8337,10291, 483,10343, 9875,10291, 1011,10347, 3,10290, 8685,10351, 1369,10351, 8401,10351, 9955,10351, 4063,10351, 4137,10351, 3863,10351, 4569,10351,10273,10351, 241,10291, 1369,10291, 17,10291, 8861,10374, 59,10374, 1325,10374, 331,10374, 1, 11, 340,10385, 341,10385, 264,10385, 375,10391, 1010,10385, 264,10384, 341,10397, 10387,10397, 5,10385, 6,10402, 2,10402, 2,10403, 7,10385, 265,10410,10397,10413, 265,10411,10391,10417, 5,10384, 29,10421, 341,10421, 6,10421, 25,10427, 8262,10385, 9,10431, 8279,10385, 9,10435, 88,10384, 3807,10439, 6347,10439, 6327,10439, 8251,10439, 9875,10439, 8165,10439, 8229,10385, 8251,10452, 9,10455, 9,10453, 8251,10459, 8241,10385, 33,10385, 6685,10465, 9,10465, 6267,10385, 101,10471, 8240,10385, 8296,10475, 8277,10475, 9,10478, 9,10475, 8277,10482, 8228,10385, 6719,10385, 9,10489, 265,10384,10389,10493, 5313,10493, 8251,10385, 8229,10498, 9,10501, 483,10384, 5197,10505, 5125,10505, 1275,10384, 1369,10385, 6685,10513, 9,10513, 1011,10385, 265,10385, 7,10520,10397,10523, 2,10384,10423,10527,10428,10527, 10427,10527, 25,10532,10425,10527, 340,10527,10397,10539,10399,10527, 10392,10527, 375,10527,10391,10546, 7,10527, 265,10550,10397,10553, 265,10551,10391,10557,10391,10527, 375,10560,10463,10527, 9,10565, 10487,10527, 9,10569,10519,10527, 6,10573, 7,10572,10575,10577, 7,10573, 6,10572,10581,10583, 25,10527,10427,10586, 8165,10527, 903,10527, 265,10527, 7,10594,10397,10597, 9,10527, 3,10384, 10482,10603, 5,10602, 6,10607, 5,10603, 6,10611,10475,10613, 10458,10603,10395,10603, 6,10619, 7,10618,10621,10623, 7,10619, 6,10618,10627,10629,10407,10603, 6,10633, 7,10632,10635,10637, 7,10633, 6,10632,10641,10643, 8326,10603,10453,10603, 9,10648, 10475,10603, 9,10652, 9875,10603, 9,10657,10521,10603, 375,10661, 9,10602, 8251,10665, 3807,10665, 9875,10665, 8165,10665, 8165,10603, 9,10674, 9,10675, 3807,10603, 9,10681, 9,10603,10475,10684, 10453,10684, 8165,10684, 8251,10603, 9,10693, 2,10385,10613,10697, 8165,10699,10646,10697, 8327,10697,10690,10697,10676,10697, 5,10696, 10603,10711, 6,10713, 7,10712,10715,10717, 7,10713, 6,10712, 10721,10723, 8326,10697,10603,10726, 8251,10727,10674,10697, 9,10732, 8165,10696,10613,10737,10705,10737, 8296,10737,10684,10737, 8277,10737, 9,10746,10603,10737, 9,10750, 9,10737,10603,10754, 8277,10754, 265,10697, 8165,10697,10684,10762, 8251,10763, 9,10767, 9,10762, 10603,10770, 8251,10771,10603,10762, 9,10776,10684,10697, 8165,10780, 8165,10781, 9,10697,10674,10786, 8165,10786,10603,10790, 8251,10791, 8165,10787,10603,10797, 8277,10797,10603,10786, 8165,10802, 8165,10803, 10603,10697, 8326,10808, 8165,10808, 9,10812, 8165,10809, 9,10817, 9,10808, 8165,10820, 8165,10821, 67,10697,10427,10827, 3,10385, 8225,10831, 8242,10831,10427,10831,10409,10831, 6,10839, 7,10838, 10841,10843, 7,10839, 6,10838,10847,10849, 7,10831,10421,10853, 375,10831,10590,10831, 9,10859, 8165,10830,10527,10863, 9,10865, 8165,10831,10527,10868, 9,10871, 9,10831, 8241,10874,10527,10831, 8326,10879, 8165,10878, 9,10883, 8165,10879, 9,10886, 9,10879, 8165,10890, 8165,10891, 8241,10831, 9,10896, 89,10384, 88,10385, 8225,10903, 8165,10385, 264,10907, 1368,10906,10909,10911, 7,10906, 2,10915, 2,10914,10909,10919, 265,10915, 5,10907, 3,10924, 10919,10927,10911,10927, 3,10925,10917,10933, 1369,10925, 1369,10906, 265,10907,10939,10941, 2,10907,10937,10945, 8229,10945, 9,10949, 10831,10945, 9,10953, 3,10907, 5,10957, 6,10959,10786,10957, 5,10956,10919,10965,10911,10965,10697,10957, 9,10970, 9,10957, 10697,10974, 2,10906,10961,10979,10613,10979, 8296,10979,10974,10979, 10684,10979, 7,10978,10927,10991,10965,10991,10909,10991, 8277,10979, 9,10998,10957,10979, 9,11002,10603,10979, 9,11006, 9,10979, 10603,11010, 8277,11010,10957,11010, 3,10906,10923,11019,10945,11019, 9,11023,10527,11019, 9,11027, 9,10384, 1369,11031, 33,11031, 3,11030, 8251,11037, 3807,11037, 9875,11037, 8165,11037, 3,11031, 8241,11047, 1, 9, 69,11051, 6625,11053, 981,11050, 980,11050, 4745,11059, 7966,11050, 7967,11050, 4,11050, 7,11067, 1275,11067, 7954,11051, 7967,11051,11063,11075, 120,11050, 3867,11079, 112,11050, 11073,11083, 66,11050, 8251,11087, 1941,11087, 6159,11087, 3807,11087, 9875,11087, 8165,11087, 121,11050, 7966,11051,11065,11103, 7957,11051, 11,11106, 1141,11051, 1447,11051, 67,11051, 7,11114,11087,11117, 113,11051,11083,11121, 7947,11123, 7947,11120,11083,11127, 89,11051, 8495,11131, 25,11050, 113,11134, 3867,11137, 3867,11135, 113,11141, 567,11050, 4950,11145, 587,11145, 4935,11148, 4935,11145, 587,11152, 973,11050, 3,11156, 4745,11159, 587,11051, 566,11162, 566,11163, 567,11163,11165,11169, 567,11162,11167,11173, 1011,11051, 1369,11051, 6625,11179, 7956,11051, 7955,11051, 33,11051, 6625,11187, 25,11051, 11101,11191, 3984,11191, 3023,11191, 3933,11191, 113,11198, 113,11191, 3933,11202, 973,11051, 2139,11207,11057,11207, 567,11051, 4971,11213, 587,11215, 257,11051, 483,11219, 483,11050, 257,11223, 1011,11050, 973,11227, 972,11226,11229,11231, 972,11227, 973,11226,11235,11237, 257,11227, 265,11050, 5019,11243, 903,11051, 7,11246, 2,11050, 11187,11251,11073,11251,11127,11251,11207,11251,11113,11251,11111,11251, 11075,11251,11179,11251,11121,11251, 7947,11269, 25,11251, 5019,11251, 3,11050,11068,11276,11069,11277,11279,11281,11068,11277,11069,11276, 11285,11287,11185,11277, 973,11276, 4745,11293,11103,11277,11109,11277, 11249,11277, 10,11276, 10,11277, 11,11276, 8251,11307, 3807,11307, 9875,11307,11305,11307, 8165,11307, 33,11277, 7971,11319, 8165,11277, 25,11323, 7947,11277, 973,11277, 4805,11329, 3807,11277, 8251,11277, 4279,11277, 4283,11277, 9673,11277, 9967,11277, 9875,11277, 4745,11277, 11,11277,11303,11349, 7971,11349, 2,11051,11315,11355,11303,11355, 11349,11358,11350,11355,11304,11355,11307,11365,11349,11355,11303,11368, 5,11355, 7,11372,11276,11374,11277,11375,11377,11379,11276,11375, 11277,11374,11383,11385, 7,11355, 5,11388,11276,11390,11277,11391, 11393,11395,11276,11391,11277,11390,11399,11401, 5,11354, 7,11404, 11277,11407, 7,11405, 7,11354,11087,11413, 5,11412,11277,11417, 11307,11413,11277,11413, 4,11354,11373,11425, 7,11427,11277,11429, 10,11354,11087,11433,11307,11433,11277,11433, 10,11355,11349,11441, 11277,11440,11307,11445,11277,11441,11303,11449, 4,11355,11410,11453, 11277,11455, 7,11453,11405,11458,11277,11461,11276,11458,11277,11459, 11405,11467,11465,11467,11276,11459,11277,11458,11473,11475,11405,11453, 7,11478,11277,11481, 1,11452, 1,11355, 4,11486, 67,11355, 1275,11355, 9,11493,11485,11495,11489,11495, 7947,11355, 11,11501, 11277,11503,11277,11355, 10,11506,11307,11509, 10,11507,11349,11513, 11,11354,11326,11517,11277,11517, 7947,11520, 7947,11517,11277,11524, 3,11051, 8213,11529, 8052,11529, 7971,11529, 113,11534, 113,11529, 7971,11538, 8241,11529, 7947,11528, 483,11529, 112,11051,11326,11549, 11277,11549, 7947,11552, 7947,11549,11277,11556, 67,11050,11187,11561, 11053,11561,11179,11561, 66,11051, 113,11050,11556,11571,11185,11571, 11549,11571, 7947,11576, 25,11570, 3867,11581, 7947,11571,11549,11584, 25,11571, 3933,11589, 7947,11051, 113,11592,11083,11595,11251,11595, 113,11593,11549,11601, 3,11593,11549,11605,11517,11605, 3,11592, 11,11051, 8116,11613, 8099,11613,11272,11613,11561,11613,11491,11613, 11251,11613, 25,11624, 8074,11613, 8093,11629, 25,11613,11251,11632, 8109,11613, 8063,11636, 8063,11613, 8109,11640, 7957,11612,11277,11645, 6625,11613, 113,11613, 2,11613,11183,11653,11545,11653,11611,11653, 11529,11653, 7947,11661, 3,11613, 7971,11664, 8093,11667, 7971,11665, 8109,11671, 2,11612,11605,11675,11326,11675,11277,11675, 7947,11680, 7947,11675,11277,11684, 7971,11613, 3,11688, 8093,11691, 3,11689, 8063,11695, 11,11050,11355,11699, 113,11701, 1369,11699,11251,11705, 33,11699,11251,11709, 3,11698, 8251,11713, 3807,11713,11433,11713, 11413,11713, 9875,11713, 8165,11713, 3,11699, 8241,11727, 0, 11, 8095,11731, 8112,11731, 6688,11731, 6285,11731, 203,11730, 2351,11741, 8159,11731, 8162,11731, 8128,11731, 8114,11731, 8097,11731, 8118,11731, 8100,11731, 5,11730, 1369,11759, 8116,11731, 9,11762, 8099,11731, 9,11766, 181,11731, 98,11731, 5019,11773, 8058,11731, 8093,11777, 8156,11731, 8093,11781, 8076,11731, 8093,11785, 30,11731, 8124,11731, 8063,11790, 8072,11731, 8109,11794, 8063,11731, 8161,11798, 8124,11798, 8109,11798, 9,11804, 9,11798, 8109,11808, 25,11731, 6685,11812, 9,11812, 89,11731, 5019,11819, 21,11821, 21,11818, 5019,11825, 2759,11731, 2789,11731, 2821,11731, 6658,11731, 6685,11731, 25,11836, 4413,11731, 113,11731, 9,11842, 128,11731, 659,11731, 623,11731, 645,11731, 705,11731, 299,11731, 828,11731, 394,11731, 241,11731, 375,11862, 483,11731, 803,11866, 8074,11731, 8093,11871, 9,11873, 9,11870, 8093,11877, 101,11731, 21,11731, 89,11882, 5019,11885, 89,11883, 5045,11889, 8061,11731, 8109,11892, 803,11731, 483,11896, 375,11731, 241,11900, 587,11901, 6625,11731, 9,11906, 6789,11731, 2,11911, 6855,11913, 1369,11730, 587,11730, 375,11919, 8109,11731, 8061,11922, 8072,11922, 8063,11922, 9,11928, 9,11922, 8063,11932, 145,11731, 903,11730, 375,11939, 265,11731, 8161,11731, 8063,11944, 2,11730, 8124,11949, 8804,11949, 3972,11949, 8150,11949, 8495,11949, 9,11958, 7971,11949, 9,11962, 3933,11949, 9,11966, 9,11949, 8109,11970, 8495,11970, 3933,11970, 7971,11970, 8109,11949, 9,11980, 3,11730, 483,11985, 2,11731, 8075,11989, 9,11991, 3,11731, 8151,11994, 5,11995, 6,11999, 0,11998, 0,11995, 5,12004, 8150,11994, 8093,12009, 7971,11994, 8093,12013, 9,12015, 9,12012, 8093,12019, 1369,11995, 11,12023,12003,12025,12007,12025, 7971,11995, 8161,12031,11997,12031, 8124,12031, 8109,12031, 9,12038, 9,12031, 8109,12042, 9,11994, 7971,12046, 8093,12049, 7971,12047, 8109,12053, 89,11730, 5082,12057, 2969,12057, 5045,12057, 21,12062, 21,12057, 5045,12066, 88,11731, 7971,12070, 8093,12073, 7971,12071, 8109,12077, 8150,11731, 3,12080, 8093,12083, 3,12081, 8063,12087, 7971,11731, 1368,12091, 264,12090,12093,12095, 5,12090, 3,12099, 3,12098, 12093,12103, 1369,12099, 7,12091, 2,12108,12103,12111,12095,12111, 2,12109,12101,12117, 265,12109, 265,12090, 1369,12091,12123,12125, 88,12090, 8093,12129, 88,12091, 8061,12133, 2,12091,12001,12137, 7,12136,12103,12141,12095,12141, 9,12137, 3,12091, 8061,12149, 8072,12149,12121,12149, 8063,12149, 9,12156, 9,12149, 8063,12160, 2,12090,12107,12165,12149,12165, 9,12169, 3,12090, 5,12173, 6,12175,12137,12177,12146,12173, 5,12172,12111,12183,12141,12183, 12093,12183, 8093,12173, 9,12191,12137,12173, 9,12194, 9,12172, 8093,12199, 9,12173,12137,12202, 9,12090, 3,12206, 8093,12209, 3,12207, 8063,12213, 9,11731, 8116,12216, 8099,12216, 8074,12216, 8093,12223, 25,12216, 8109,12216, 8063,12228, 8063,12216, 8109,12232, 6625,12216, 113,12216, 3,12216, 7971,12240, 8093,12243, 7971,12241, 8109,12247, 7971,12216, 3,12250, 8093,12253, 3,12251, 8063,12257, 0, 9, 192,12261, 2329,12263, 211,12261, 2419,12267, 211,12260, 2433,12271, 192,12260, 2337,12275, 189,12260, 2337,12279, 4,12261, 7,12282, 413,12260, 413,12261, 1216,12260, 1216,12261, 1086,12261, 9617,12295, 137,12261, 587,12261, 1011,12300, 9617,12303, 1011,12301, 9565,12307, 1011,12261, 9617,12311, 587,12313, 587,12310, 9617,12317, 1011,12260, 5267,12321, 9600,12321, 9565,12321, 587,12326, 587,12321, 9565,12330, 587,12260, 5231,12335, 5181,12335,10505,12335, 1275,12261, 2,12260,10001,12345, 5,12347, 4,12346,12349,12351, 4,12347, 5,12346,12355,12357, 3,12260,11243,12361,11251,12361, 5177,12361, 5185,12361, 2,12261, 3,12261,11355,12373, 1, 265, 471,12376, 2647,12379, 357,12376, 1785,12383, 586,12377, 375,12387, 586,12376, 413,12377, 3,12377, 7,12394, 375,12397, 7,12395, 331,12401, 483,12395, 15,12405, 5,12377, 17,12409, 587,12411, 3,12376, 669,12415, 1418,12415,12413,12415, 1369,12415, 15,12422, 15,12415, 1369,12426, 5,12376,12417,12431, 1419,12431,12415,12435, 668,12431, 12415,12439,12419,12431,12407,12431,12429,12431, 9,12431, 587,12448, 12415,12451,12425,12431, 587,12431, 9,12456,12415,12459, 6719,12377, 9,12463, 7867,12377, 251,12467, 3357,12377, 3681,12377, 3709,12377, 2647,12377, 5843,12377, 4407,12377,11917,12377, 305,12377, 713,12377, 25,12377, 4405,12377, 7041,12377, 251,12493, 1471,12376, 2011,12497, 53,12376, 2035,12501, 257,12377, 253,12376, 5325,12507, 251,12376, 7867,12511, 7617,12511, 7041,12511, 7617,12377, 251,12519, 1363,12376, 5189,12523, 483,12377, 9,12377, 8938,12377, 375,12531, 5313,12377, 7035,12377, 7091,12537, 7083,12537, 7123,12537, 241,12537, 11,12376, 5313,12547, 587,12376,12387,12551,11731,12551, 9,12376, 5019,12557, 12361,12557, 1369,12376, 11,12377, 587,12377,12391,12567, 7,12376, 2,12571, 4,12572,12537,12575, 4,12571, 2,12578,12537,12581, 12545,12571, 240,12571,12537,12587, 8948,12571, 331,12571, 8861,12592, 8861,12571, 331,12596, 4827,12571, 6,12377, 257,12603, 265,12605, 241,12603, 1,12609,12607,12611, 7,12377, 3,12614, 375,12617, 8861,12614, 375,12621, 375,12615, 8861,12625, 241,12614, 375,12629, 257,12376, 2647,12633, 1783,12633, 256,12377, 375,12639, 8861,12377, 261,12643, 260,12643, 256,12643, 6,12643, 241,12650, 7,12643, 241,12654, 331,12655, 6,12642,12645,12661, 7,12642,12647,12665, 12653,12665, 375,12665, 241,12643, 6,12672,12665,12675, 7,12672, 6,12673,12679,12681,12655,12681, 7,12673,12675,12687, 241,12377, 7,12691, 331,12693, 7,12690, 375,12697, 8997,12691, 7,12701, 241,12376, 4457,12705, 374,12705, 5189,12705, 265,12705, 6,12712, 8386,12705, 6,12705, 265,12718, 7,12705, 8337,12722, 8337,12705, 7,12726, 8861,12705, 6,12731, 7,12731, 6,12730,12735,12737, 7,12730,12733,12741, 1, 241, 448,12745, 4349,12747, 445,12744, 1679,12751, 457,12744, 4371,12755, 8461,12744, 8475,12759, 277,12744, 4457,12763, 923,12744, 4959,12767, 8388,12744, 8389,12744, 4,12745, 11,12775, 1369,12777, 2,12745, 1275,12781, 9,12783, 2,12744, 1419,12787, 668,12787,12779,12787, 587,12787, 9,12794, 9,12787, 587,12798, 4,12744,12789,12803, 669,12803,12787,12807, 1418,12803, 12787,12811,12791,12803,12785,12803,12801,12803, 15,12803, 1369,12820, 12787,12823,12797,12803, 1369,12803, 15,12828,12787,12831, 445,12745, 265,12834, 4349,12837, 923,12745, 5009,12841, 8374,12745, 346,12745, 2981,12847, 386,12745, 387,12745, 3049,12853, 347,12745, 8389,12745, 12771,12859, 1412,12745, 5227,12863, 346,12744, 2977,12867,12857,12867, 386,12744, 4067,12873,12853,12873, 1412,12744, 5189,12879, 374,12744, 12845,12883, 387,12744, 3043,12887,12851,12887, 347,12744,12847,12893, 272,12745, 4453,12897, 4437,12897, 1755,12897, 8388,12745, 8495,12905, 12773,12905, 8387,12745, 265,12911, 8861,12913, 265,12910, 8495,12917, 253,12745, 59,12744, 1325,12744, 341,12745, 375,12745,12883,12929, 8337,12931, 8337,12928,12883,12935, 4371,12745, 457,12939, 375,12939, 4531,12745, 375,12945, 8366,12745, 375,12949, 305,12744, 4457,12953, 375,12952, 4067,12957, 4067,12953, 375,12961, 331,12744, 4457,12965, 12927,12965, 8386,12745, 8495,12971, 331,12971, 1325,12971, 59,12971, 265,12971, 8375,12745, 8495,12983, 305,12745,12887,12987, 4266,12987, 3031,12987, 4213,12987, 375,12994, 8337,12986, 375,12999, 375,12987, 4213,13002, 5325,12745, 7,13007, 5361,13009, 5385,13009, 5407,13009, 1275,12744, 15,12744, 8475,12745, 375,13021, 8461,13021, 6,12744, 8429,13027, 8428,13027, 4139,13027, 4138,13027, 3,13026, 5,13036, 5,13026, 3,13040, 264,13026,13031,13045,13035,13045, 264,13027, 8401,13051, 4137,13051, 265,13026, 8401,13057,13051,13058,13029,13057, 13052,13057, 4137,13057,13051,13066,13033,13057,13054,13057,13051,13057, 8401,13074, 4137,13074, 4137,13027, 265,13081,13051,13083, 265,13080, 13045,13087, 341,13027, 265,13027, 8401,13092,13045,13095, 4137,13092, 13045,13099,13045,13093, 8401,13103, 4137,13103, 8401,13027, 265,13109, 13051,13111, 265,13108,13045,13115, 7,12744, 8605,13119, 8374,13119, 8916,13119, 8389,13119, 412,13119, 241,13119, 265,13130, 264,13118, 264,13119, 8452,13119, 8647,13119, 265,13118,13137,13143, 8861,13119, 375,13146, 8337,13119, 375,13150, 265,13150, 305,13119, 713,13119, 25,13119, 375,13119, 8861,13162, 8337,13162, 265,13119, 241,13168, 13135,13169, 8337,13168, 6,12745,12965,13177,13145,13177,13139,13177, 8453,13177,13119,13185,12923,13177,12925,13177,13135,13177,13169,13192, 13172,13177,13136,13177,13143,13199,13175,13177,13155,13177,13169,13177, 13135,13206, 3,13177, 5,13210,13118,13212,13119,13213,13215,13217, 13118,13213,13119,13212,13221,13223, 5,13177, 3,13226,13118,13228, 13119,13229,13231,13233,13118,13229,13119,13228,13237,13239, 264,13177, 13119,13242,13143,13245,13119,13243,13135,13249, 413,13177, 8452,13177, 8861,13255, 305,13177, 8337,13177, 265,13260, 8861,13263, 265,13261, 8495,13267, 265,13177, 8337,13270, 8861,13273, 8861,13271, 8337,13277, 13119,13177, 264,13280,13143,13283, 264,13281,13169,13287, 265,13280, 13287,13291, 265,13281,13283,13295, 8387,13177, 264,13299, 265,13298, 13301,13303, 264,13298, 265,13299,13307,13309, 265,13176, 8842,13313, 8495,13313, 8337,13316, 8337,13313, 8495,13320, 7,12745,13039,13325, 13043,13325,13045,13325, 241,13324, 0,13333, 8717,13325, 8495,13325, 8337,13339, 305,13339, 4311,13325, 4329,13325, 3785,13325,10351,13325, 10055,13325, 8337,13324, 8495,13355, 331,13355, 1325,13355, 59,13355, 265,13355, 59,13325, 8337,13367, 1325,13325, 8337,13371, 331,13325, 8337,13375, 8861,13375, 265,13325,13051,13381,13335,13381, 5325,13381, 1,13381,13333,13389, 8861,13381, 8337,13381,13027,13325, 264,13396, 264,13397, 265,13396,13401,13403, 265,13397,13399,13407, 265,13324, 8717,13411, 3785,13411,13045,13411, 8495,13411, 374,12745, 8842,13421, 8495,13421, 8337,13424, 8337,13421, 8495,13428, 340,12745, 8717,13433, 13045,13433, 3785,13433, 8495,13433, 375,12744, 4371,13443,13428,13443, 12983,13443, 8475,13443,13421,13443, 8337,13452, 305,13442, 4067,13457, 8337,13443,13421,13460, 305,13443, 4213,13465, 8452,12745, 8647,13469, 7,13469, 8495,13473, 8337,12745, 375,13476,12883,13479, 375,13477, 305,13483,13421,13483, 305,13476, 375,13489, 6,13477, 8453,13493, 8452,13492,13495,13497, 8452,13493, 8453,13492,13501,13503, 7,13477, 13213,13507,13229,13507, 375,13507,13243,13507, 265,13507,13177,13517, 6,13476, 3,13521, 5,13522,13507,13525, 5,13521, 3,13528, 13507,13531,13517,13521, 264,13521,13507,13537, 7,13476, 8495,13541, 331,13541, 1325,13541, 59,13541, 265,13541, 265,13476, 8647,13553, 7,13553, 8495,13557, 265,13477,13177,13561,13521,13561, 7,13561, 265,12745, 445,13568, 4349,13571, 445,13569, 4371,13575, 8770,13569, 8729,13569,13027,13569, 375,13583, 8684,13569, 8717,13587, 331,13569, 13177,13591, 8757,13569, 8647,13594, 8647,13569, 8757,13598, 8387,13568, 8495,13603, 6,13569, 7,13569, 8647,13609, 8495,13608, 8717,13613, 8495,13609, 8757,13617, 6,13568, 8842,13621, 8495,13621, 8337,13624, 13609,13621, 8337,13621, 8495,13630, 7,13568, 8717,13635, 3785,13635, 13045,13635, 8495,13635,13607,13635, 8337,13568, 8647,13647, 7,13647, 8495,13651, 8495,13569, 6,13654, 7,13654, 8717,13659, 6,13655, 13659,13663, 7,13655,13657,13667, 8647,13667, 265,12744,13258,13673, 12845,13673,13091,13673,12935,13673,12927,13673,12929,13673, 8337,13685, 13479,13673,12911,13673,13260,13673,12859,13673, 4457,13673, 5189,13673, 13177,13673, 305,13700, 8337,13700, 305,13673,13177,13706, 8386,13673, 7,13673, 8337,13712, 8861,13673, 6,13717, 7,13717, 6,13716, 13721,13723, 7,13716,13719,13727, 8337,13673,13177,13730, 7,13730, 1, 587, 264,13737, 375,13739, 16,13737, 264,13736, 341,13745, 7,13737, 4,13748, 4,13749, 3,13736, 717,13755, 341,13755, 6,13755, 713,13761, 17,13755, 566,13736, 1108,13737, 9565,13769, 11731,13737, 265,13772,11942,13737, 3565,13737, 3573,13737, 3273,13737, 375,13736, 113,13736, 4696,13787, 9,13787, 4669,13790, 4669,13787, 9,13794, 1011,13737, 9565,13799, 9,13801, 9,13798, 9565,13805, 241,13737, 9,13737, 1011,13810, 9565,13813, 1011,13811, 9617,13817, 113,13737, 4727,13821, 9,13823, 7049,13737, 807,13827, 375,13827, 265,13736,11731,13833, 1487,13737, 1011,13736, 5293,13839, 9704,13839, 9617,13839, 9,13844, 9,13839, 9617,13848, 265,13737,11731,13852, 4,13736,13757,13857,13762,13857,13761,13857, 713,13862,13759,13857, 340,13857,13745,13869,13747,13857,13740,13857, 375,13857,13739,13876, 7,13857, 265,13880,13745,13883, 265,13881,13739,13887,13739,13857, 375,13890, 713,13857,13761,13894, 265,13857, 7,13898,13745,13901, 483,13857, 5,13736,13853,13907, 375,13909, 483,13906, 4,13737, 7,13914, 767,13915,13761,13919, 5,13737, 3,13923, 1,13924, 1,13923, 3,13928, 17,13923, 587,13933,13927,13935,13931,13935, 567,13736, 483,13736, 5,13942, 1, 483, 9174,13946, 9175,13946, 2,13947, 7,13952, 2,13946, 7,13957, 6,13946, 9170,13947, 9175,13947,13949,13965, 824,13946, 3997,13969, 802,13946,13963,13973, 766,13946, 825,13946, 9174,13947,13951,13981, 803,13947,13973,13985, 9165,13987, 9165,13984,13973,13991, 713,13946, 803,13994, 3997,13997, 3997,13995, 803,14001, 1171,13946, 4663,14005, 903,14007, 155,13946, 9172,13947, 9171,13947, 713,13947,13979,14017, 4200,14017, 3027,14017, 4147,14017, 803,14024, 803,14017, 4147,14028, 1171,13947, 4722,14033, 903,14033, 4713,14036, 4713,14033, 903,14040, 257,13947, 9,14045, 9,13946, 257,14049, 903,13946, 257,14053, 11,13946, 5197,14057, 5125,14057,12335,14057, 4,13946, 2,14065, 7,14067,14013,14069, 5,13946,13958,14072,13959,14073,14075,14077,13958,14073,13959,14072, 14081,14083, 586,14072, 586,14073, 587,14072,14089,14091, 4827,14073, 9,14073, 4569,14073, 4745,14073, 587,14073,14087,14103, 4,13947, 14093,14107,14087,14107,14103,14110,14104,14107,14088,14107,14091,14117, 14103,14107,14087,14120, 3,14107, 7,14124,14072,14126,14073,14127, 14129,14131,14072,14127,14073,14126,14135,14137, 7,14107, 3,14140, 14072,14142,14073,14143,14145,14147,14072,14143,14073,14142,14151,14153, 3,14106, 7,14157, 2,14106,14125,14161, 7,14163,14073,14165, 586,14107,14073,14168,14091,14171,14073,14169,14087,14175, 2,14107, 14158,14179,14073,14181, 7,14179,14157,14184,14073,14187,14073,14185, 14157,14191,14157,14179, 7,14194,14073,14197,14073,14107, 586,14200, 14091,14203, 586,14201,14103,14207, 5,13947,14069,14211, 9165,14213, 6,14211, 9165,14210,14069,14219, 17,14211, 802,13947, 9165,14225, 803,13946,14226,14229,14015,14229,14225,14229, 9165,14234, 713,14228, 3997,14239, 9165,14229,14225,14242, 713,14229, 4147,14247, 9165,13947, 803,14250,13973,14253, 803,14251,14225,14257, 4,14251, 2,14261, 7,14263, 5,14250,14265,14267,14069,14267, 587,13947, 9340,14273, 9323,14273, 9290,14273, 9317,14279, 9335,14273, 9287,14282, 9287,14273, 9335,14286, 5,14273, 9195,14290, 9317,14293, 9195,14291, 9335,14297, 9195,14273, 5,14300, 9317,14303, 5,14301, 9287,14307, 587,13946, 5,14310, 0, 265, 446,14315, 4371,14317, 445,14314, 1675,14321, 8725,14315, 8766,14315, 471,14314, 2367,14329, 8827,14315, 8836,14315, 319,14314, 4497,14337, 1302,14315, 667,14315, 8794,14315, 8768,14315, 8727,14315, 8774,14315, 8732,14315, 1011,14315, 1275,14354, 3,14315, 1369,14359, 11,14361, 5,14315, 9,14365, 1275,14367, 3,14314, 1291,14371, 524,14371,14369,14371, 483,14371, 11,14378, 11,14371, 483,14382, 5,14314, 525,14387,14371,14389,14373,14387,14375,14387, 1290,14387,14371,14397,14363,14387,14385,14387,14381,14387, 17,14387, 1275,14406,14371,14409, 1275,14387, 17,14412,14371,14415, 8770,14315, 241,14418, 8729,14315, 241,14422, 445,14315, 241,14426, 4371,14429, 1303,14315, 666,14315, 8784,14315, 4266,14315, 8622,14315, 8717,14441, 8824,14315, 8717,14445, 8702,14315, 8717,14449, 256,14314, 7185,14453, 2309,14453, 5673,14453, 5521,14453, 375,14461, 4213,14315, 375,14464, 316,14315, 4533,14469, 1757,14469, 8697,14315, 629,14315, 407,14315, 5325,14479, 3121,14315, 3031,14315, 5519,14315, 3355,14315, 510,14315, 8788,14315, 8647,14492, 8676,14315, 8757,14496, 8647,14315, 8831,14500, 8788,14500, 8757,14500, 241,14506, 241,14500, 8757,14510, 331,14315, 1325,14315, 59,14315, 5521,14315, 375,14521, 375,14315, 4213,14524, 8757,14524, 53,14525, 1471,14525, 253,14525, 253,14314, 4425,14537, 4497,14537, 483,14315, 9,14542, 9,14315, 483,14546, 8684,14315, 8717,14551, 241,14553, 241,14550, 8717,14557, 331,14551, 251,14315, 257,14563, 8495,14565, 8635,14315, 8757,14568, 5515,14315, 331,14573, 8757,14315, 8635,14576, 8676,14576, 8647,14576, 241,14582, 375,14576, 241,14576, 8647,14588, 1369,14314, 2853,14593, 15,14315, 1275,14315, 1011,14598, 587,14315, 241,14602, 8831,14315, 8647,14606, 6,14314, 14341,14611,14343,14611,14601,14611,14357,14611, 8495,14611, 241,14611, 7,14314,14433,14625,14435,14625,14605,14625, 8495,14625, 3785,14625, 10055,14625,10351,14625, 4329,14625, 4311,14625, 4555,14625,14073,14625, 4971,14625, 8717,14625, 7,14315, 8813,14652,14623,14653, 8495,14657, 4,14653, 2,14660,14620,14663, 8495,14663,14611,14666,14611,14663, 8495,14670, 2,14653, 4,14674,14620,14677, 8495,14677,14611,14680, 14611,14677, 8495,14684, 240,14653,14620,14689, 8495,14689,14611,14692, 14611,14689, 8495,14696, 8812,14652, 8717,14701, 8495,14652, 8717,14705, 241,14707, 241,14704, 8717,14711, 331,14705, 15,14653, 483,14717, 1275,14653, 9,14721, 8495,14653, 8831,14725,14655,14725, 8788,14725, 8757,14725, 241,14732, 241,14725, 8757,14736, 375,14653, 8647,14653, 241,14652, 8647,14745, 8495,14744, 8717,14749, 8495,14745, 8757,14753, 257,14314, 8614,14757, 4417,14757, 8495,14757, 251,14762, 251,14757, 8495,14766, 256,14315, 8647,14771, 7207,14771, 5432,14771, 5325,14771, 375,14778, 8495,14770, 8717,14783, 375,14771, 5325,14786, 8495,14771, 8757,14791, 8812,14315, 6,14794, 7,14794, 8717,14799, 6,14795, 14799,14803, 7,14795,14797,14807, 8647,14807, 8495,14315, 261,14812, 260,14812, 256,14812, 8717,14819, 256,14813, 8635,14823, 6,14813, 14815,14827, 7,14813,14817,14831, 8635,14831, 8676,14831, 8647,14831, 241,14838, 375,14831, 241,14831, 8647,14844, 6,14812, 241,14848, 14831,14851, 7,14812, 8717,14855, 241,14857, 241,14854, 8717,14861, 331,14855, 241,14812, 6,14866,14831,14869, 7,14866, 8717,14873, 6,14867,14873,14877,14855,14877, 7,14867,14869,14883, 8647,14883, 241,14315, 445,14888, 4371,14891, 445,14889, 4349,14895, 8770,14888, 8729,14888, 587,14888,14625,14903, 8684,14888, 8717,14907, 8757,14888, 8647,14910, 8387,14889, 8495,14915, 8647,14888, 8757,14918, 6,14889, 8842,14923, 8495,14923, 8337,14926, 8337,14923, 8495,14930, 7,14889, 8717,14935, 3785,14935, 8495,14935, 6,14888,14935,14943, 7,14888, 8647,14947, 8495,14946, 8717,14951,14923,14947, 8495,14947, 8757,14957, 8495,14888, 6,14960, 7,14960, 8717,14965, 6,14961,14965,14969, 7,14961,14963,14973, 8647,14973, 8337,14889, 8647,14979, 7,14979, 8495,14983,12745,14315, 375,14987, 241,14314, 9099,14991, 9036,14991, 8647,14991, 8997,14996, 5521,14991, 375,15001, 375,14991, 9082,14991, 8495,15007, 7,14991, 8495,15011, 8997,15013, 8997,15010, 8495,15017, 8997,14991, 8647,15020, 7,15020, 8495,15025, 0, 241, 460,15029, 2315,15031, 479,15029, 2393,15035, 479,15028, 2397,15039, 460,15028, 2317,15043, 457,15028, 2317,15047, 269,15028, 2885,15051, 464,15029, 16,15029, 413,15029, 6,15058, 4,15029, 7,15062, 7,15063, 15,15063, 483,15069, 2,15029, 587,15073, 17,15075, 2,15028, 525,15079, 1290,15079,15071,15079, 1275,15079, 17,15086, 17,15079, 1275,15090, 4,15028, 1291,15095,15079,15097,15081,15095,15083,15095, 524,15095,15079,15105,15077,15095,15093,15095,15089,15095, 11,15095, 483,15114,15079,15117, 483,15095, 11,15120,15079,15123, 9072,15029, 305,15127, 9105,15029, 305,15131, 9083,15029, 413,15135, 412,15134, 15137,15139, 412,15135, 413,15134,15143,15145, 3445,15029, 375,15149, 12526,15029,12528,15029, 251,15029, 375,15029, 305,15159, 8997,15161, 8997,15158, 305,15165,12614,15029, 375,15169, 7065,15029, 265,15173, 7259,15175, 305,15028, 9105,15179, 9072,15179, 375,15179, 8997,15184, 8997,15179, 375,15188, 9082,15029, 375,15193, 265,15193, 5521,15029, 375,15199, 265,15199, 483,15029,12377,15204, 9,15029,12377,15208, 17,15029,13737,15029, 375,15215, 6,15028, 3,15219, 5,15220, 15193,15223, 5,15219, 3,15226,15193,15229,15197,15219,15057,15219, 3,15235, 2,15234,15237,15239, 2,15235, 3,15234,15243,15245, 15065,15219, 3,15249, 2,15248,15251,15253, 2,15249, 3,15248, 15257,15259, 264,15219,15193,15263, 8997,15219, 7,15028, 4437,15269, 15213,15269, 3,15273, 2,15272,15275,15277, 2,15273, 3,15272, 15281,15283,12571,15269, 4805,15269, 4613,15269,14073,15269, 375,15269, 510,15269, 4971,15269, 483,15269, 9,15300, 9,15269, 483,15304, 6,15029, 9020,15309, 9021,15309,12393,15309,12392,15309, 8337,15309, 265,15318, 8452,15308, 241,15322, 8453,15309,15325,15327, 8452,15309, 8453,15308, 412,15309, 8997,15335, 241,15308, 265,15338,15327,15341, 8452,15339,15333,15345,15067,15309, 3,15349, 2,15348,15351,15353, 2,15349, 3,15348,15357,15359, 413,15308,15313,15363,15315,15363, 15331,15363,15321,15363, 8997,15363,15335,15372,15336,15363,15335,15363, 8997,15378, 412,15308,15311,15383,15317,15383,15327,15383, 413,15309, 12377,15390,15383,15393, 8997,15390,15383,15397,15383,15391, 8997,15401, 12377,15309, 413,15404,15383,15407, 413,15405,15335,15411, 8997,15309, 413,15414,15383,15417, 413,15415,15335,15421, 265,15309, 8337,15424, 15363,15427, 265,15308, 241,15430,15327,15433, 7,15029,15223,15437, 8997,15439,15229,15437, 8997,15443,15263,15437, 8997,15447, 4,15436, 15219,15451, 3,15453, 2,15452,15455,15457, 2,15453, 3,15452, 15461,15463, 264,15436, 264,15437,12377,15436, 375,15471, 8997,15436, 15223,15475,15229,15475, 375,15475,15263,15475, 265,15475,15219,15485, 59,15437, 1325,15437, 331,15437, 1275,15437, 9,15495, 15,15437, 483,15499, 265,15437,15266,15503,15219,15503, 8997,15506,15467,15503, 8997,15503,15219,15512, 305,15503, 265,15436,15469,15519, 331,15519, 375,15028, 3307,15525, 2885,15525,12511,15525,12377,15525, 251,15533, 340,15029, 331,15537, 9136,15029, 7,15541, 8997,15029, 375,15544, 305,15547, 305,15545, 375,15551, 6,15545, 3,15555, 5,15556, 5,15555, 3,15560, 264,15555, 7,15545, 8495,15567, 331,15567, 1325,15567, 59,15567, 265,15567, 7,15544,15559,15579,15563,15579, 15223,15579,15229,15579, 375,15579,15263,15579,15565,15579, 265,15579, 15219,15595,15555,15595, 265,15544,15555,15601, 7,15601, 265,15545, 8647,15607, 7,15607, 8495,15611, 265,15029, 7,15615, 375,15617, 7,15614, 331,15621, 8997,15614, 7,15625,12377,15029,13421,15629, 13313,15629,13621,15629,14923,15629,12721,15629,12715,15629,12709,15629, 375,15629,12705,15645, 7,15629, 331,15649, 483,15628, 9,15628, 7,15628, 375,15657, 265,15028, 9036,15661, 9099,15661, 241,15661, 6,15667,15629,15669, 8647,15661, 8997,15672, 5521,15661, 375,15677, 9082,15661, 8495,15681, 375,15661, 7,15661, 8495,15687, 8997,15689, 8997,15686, 8495,15693, 8997,15661, 8647,15696, 7,15696, 8495,15701, 0, 587, 9319,15705, 9336,15705, 889,15704, 2373,15711, 9371,15705, 9374,15705, 9350,15705, 9338,15705, 9321,15705, 9342,15705, 9324,15705, 578,15705, 3,15705, 6,15730, 7,15705, 567,15735, 9195,15737, 4,15735, 9366,15741, 483,15741, 9195,15744, 9195,15741, 483,15748, 7,15704, 9340,15705, 483,15754, 9323,15705, 483,15758, 579,15705, 9272,15705, 9317,15765, 9368,15705, 9317,15769, 9294,15705, 9317,15773, 566,15704,15729,15777, 9348,15705, 9287,15780, 9288,15705, 9335,15784, 9287,15705, 9373,15788, 9348,15788, 9335,15788, 483,15794, 483,15788, 9335,15798, 567,15705, 9,15802,15777,15805,15777,15803, 9,15809, 12377,15705, 11,15813, 9,15705, 567,15816,15777,15819, 567,15817, 9290,15705, 9317,15825, 483,15827, 483,15824, 9317,15831, 9275,15705, 9335,15834, 375,15705, 11,15839, 11,15704, 375,15843, 9335,15705, 9275,15846, 9288,15846, 9287,15846, 483,15852, 483,15846, 9287,15856, 9,15704, 5231,15861, 5181,15861,10505,15861,14057,15861, 1011,15704, 375,15871, 9373,15705, 9287,15874, 4,15704, 9262,15879, 375,15879, 9195,15882, 7,15879, 265,15887, 9195,15889, 9195,15879, 375,15892, 483,15879, 5,15704, 5,15705, 9367,15900, 9366,15900, 9317,15905, 9195,15900, 9317,15909, 483,15911, 483,15908, 9317,15915, 9195,15901, 9373,15919,15903,15919, 9348,15919, 9335,15919, 483,15926, 483,15919, 9335,15930, 483,15900, 9195,15934, 9317,15937, 9195,15935, 9335,15941, 567,15704,15763,15945, 9,15945, 566,15705,15823,15951,15948,15951, 15945,15951, 9,15956, 9195,15950, 9317,15961, 9195,15951, 9335,15965, 9,15951,15945,15968, 9366,15705, 5,15972, 9317,15975, 5,15973, 9287,15979, 9195,15705, 566,15982, 9317,15985, 566,15983, 9275,15989, 5,15983, 9275,15993, 9288,15993, 9287,15993, 483,15998, 483,15993, 9287,16002, 5,15982, 9317,16007, 483,16009, 483,16006, 9317,16013, 483,15982, 5,16016, 9317,16019, 5,16017, 9287,16023, 483,15705, 9340,16026, 9323,16026, 9290,16026, 9317,16033, 9335,16026, 9287,16036, 9287,16026, 9335,16040, 5,16026, 9195,16044, 9317,16047, 9195,16045, 9335,16051, 9195,16026, 5,16054, 9317,16057, 5,16055, 9287,16061, 0, 483, 878,16065, 2327,16067, 899,16065, 2415,16071, 899,16064, 2423,16075, 878,16064, 2331,16079, 875,16064, 2331,16083, 573,16064, 2569,16087, 2,16064, 15,16091, 413,16064, 413,16065, 573,16065, 2567,16099, 1216,16064, 1216,16065, 904,16065, 2263,16107, 6515,16065, 5,16111, 6539,16113, 903,16064, 4421,16117, 5285,16117, 2265,16117, 4,16064, 5,16064, 4,16065, 2,16129, 7,16131, 0,16130, 0,16129, 2,16136, 15,16129, 483,16141,16135,16143,16139,16143, 9513,16065, 5,16149,16133,16151, 4,16148, 2,16155, 7,16157, 16151,16159, 1, 1011, 996,16162, 14,16162, 5,16163, 6,16169, 9617,16171, 2,16162, 9617,16175,16171,16176,16172,16175,16171,16175, 9617,16182, 7,16175,16169,16187, 9617,16189, 5,16162,16186,16193, 16175,16193, 7,16196, 7,16197,16187,16193, 6,16192,16195,16205, 16199,16205, 7,16192,16203,16211,16175,16211, 3,16211,16162,16217, 3,16193, 7,16221,16162,16222,16162,16221, 7,16226, 7,16227, 16205,16231, 6,16193,16201,16235,16214,16235,16175,16235,16211,16240, 16211,16235,16175,16244,16225,16235,16229,16235,16219,16235, 7,16193, 16175,16254,16205,16257,16205,16255,16175,16261, 9704,16163, 587,16265, 5293,16163, 587,16269, 997,16162, 972,16162,16235,16275, 9,16275, 14652,16163, 973,16163,16273,16283,16278,16283, 9,16283,16275,16288, 16275,16283, 9,16292, 955,16162, 5241,16297, 1505,16162, 6,16301, 7,16300,16303,16305, 7,16301, 6,16300,16309,16311, 67,16162, 16235,16315, 9,16163, 9617,16318, 587,16321, 587,16319, 9617,16325, 15,16162, 257,16163, 9,16331, 9,16162, 973,16335,16275,16337, 973,16334, 257,16335, 587,16162, 5293,16345, 9704,16345, 9617,16345, 9,16350, 9,16345, 9617,16354, 6,16162, 5,16358, 7,16162, 16221,16362,16235,16365,16235,16363, 8647,16363, 903,16362,16235,16373, 6,16163,16329,16377, 7,16163,16167,16381,16205,16381,16361,16381, 8717,16381,14315,16380, 4311,16381, 4329,16381, 3785,16381,10351,16381, 10055,16381, 973,16162, 9,16402, 972,16163,16341,16407,16165,16407, 16405,16407,16403,16407, 9,16415, 9617,16163, 1368,16418, 14,16418, 2,16418, 7,16425,16423,16427, 7,16424, 5,16418, 6,16433, 16431,16435,16421,16435, 6,16432,16427,16441, 2,16419,16435,16445, 16171,16445, 7,16445,16433,16451, 9,16418, 587,16455, 587,16419, 9,16459, 6,16418, 5,16462,16427,16465, 7,16418, 2,16468, 16435,16471,14315,16163, 7,16474, 17,16475, 903,16162, 3,16480, 6,16483, 6,16482, 5241,16481, 1274,16480, 15,16480, 1275,16480, 6,16480, 3,16496, 5,16496, 7,16480,16485,16503,16235,16503, 6,16481,16495,16509,16493,16509, 7,16481,16499,16515,16501,16515, 16487,16515,16205,16515,16361,16515,16491,16515,16167,16515, 1, 903, 9542,16530, 9543,16530, 1274,16530, 3,16530, 9541,16539, 6,16538, 7,16538, 5,16545,16530,16547, 5,16539, 7,16551,16530,16552, 16530,16551, 7,16556, 7,16557,16543,16561, 6,16539, 9533,16565, 16545,16565,16555,16565,16559,16565,16549,16565, 7,16539,16543,16577, 4,16530,16576,16581,16543,16583,16539,16581, 7,16586,16543,16589, 7,16587,16565,16593,16545,16581,16565,16596,16565,16581,16545,16600, 16568,16581,16579,16581, 7,16581,16539,16608,16543,16611,16539,16609, 16545,16615, 1170,16530,16565,16619, 9541,16531,16535,16623, 559,16530, 5241,16627, 767,16530,16565,16631, 165,16530, 6,16635, 7,16634, 16637,16639, 7,16635, 6,16634,16643,16645, 9540,16531,16543,16649, 16533,16649,16539,16649,16537,16649, 1275,16530,16623,16659, 9533,16659, 257,16531, 483,16665, 483,16530, 257,16669, 15,16530, 5241,16673, 6,16530, 3,16676,16649,16679, 7,16530,16541,16683,16566,16683, 16551,16682,16565,16689,16565,16683, 9533,16692, 375,16683, 1011,16682, 16565,16699, 9533,16683,16565,16702,15269,16683, 4827,16683, 6,16531, 16662,16711,16659,16711, 9533,16714, 9533,16711,16659,16718, 7,16531, 16539,16723, 9533,16725,16537,16723, 9533,16729, 1007,16723,16543,16723, 9533,16735,16679,16723, 9533,16739, 331,16723, 1325,16723, 59,16723, 9533,16722,16543,16749,16539,16749,16679,16749,16537,16749, 9533,16531, 1275,16759,16711,16761, 7,16759,16565,16765, 7,16758,16539,16769, 16543,16769,16679,16769,16537,16769,15029,16531, 7,16779, 1011,16530, 5,16782, 6,16785, 6,16784, 5241,16783, 14,16782, 1275,16782, 15,16782, 6,16782, 5,16798, 3,16798, 7,16782,16787,16805, 16565,16805, 6,16783,16797,16811,16795,16811, 7,16783,16801,16817, 16803,16817,16789,16817,16543,16817,16679,16817,16793,16817,16537,16817, 1, 1369, 1010,16833, 16,16833, 2,16833, 5,16838, 5,16839, 16837,16843, 7,16833, 4,16846,16843,16849, 4,16847,16841,16853, 16835,16853, 2,16832, 11,16859,15900,16833, 331,16832, 59,16832, 6717,16833, 9,16869, 1325,16832, 265,16832, 4,16833, 7,16876, 16843,16879, 2,16877, 1,16882, 1,16877, 2,16886, 11,16877, 1369,16891,16885,16893,16889,16893, 5,16833, 2,16898,16853,16901, 15705,16898, 1275,16898, 9,16907, 1346,16833, 9,16911,15705,16833, 11,16915, 5,16914, 1275,16833, 5,16921, 17,16923, 5,16920, 9,16927, 1275,16832, 6717,16931, 9,16933, 1, 1275, 5814,16937, 902,16937, 902,16936, 3,16937, 7,16944, 413,16937, 1216,16937, 6787,16937, 5,16953, 4,16952,16955,16957, 4,16953, 5,16952, 16961,16963, 1505,16937, 5771,16937, 903,16968, 1011,16937, 903,16972, 903,16936,16941,16977, 241,16936, 17,16936, 5299,16983, 4915,16983, 11,16936, 903,16937, 5771,16990,16943,16991, 1011,16990,15208,16937, 9,16937,15029,17000,15029,16937, 9,17004, 4,16936, 265,17009, 5,16936, 4,16937, 1011,17015, 1369,16936, 6717,17019, 9,17021, 1, 17, 4,17025, 6,17026, 113,17025, 1275,17024, 5299,17033, 4915,17033, 241,17025, 2,17024, 3,17024,11731,17025, 265,17045, 1, 15, 5886,17049, 5,17048, 483,17053, 413,17049, 1216,17049, 165,17049, 5843,17049, 1011,17062,14315,17049, 17,17067, 903,17049, 1011,17070, 1011,17048, 241,17048, 903,17048, 5241,17079, 1011,17049, 5843,17082, 903,17082,15204,17049, 483,17049,15029,17090,15029,17049, 483,17094, 3,17048, 483,17099, 2,17049, 3,17049, 5,17105, 1,17106, 1,17105, 5,17110, 483,17105, 15,17115,17109,17117, 17113,17117, 1369,17105, 0, 1011, 2,17125, 7,17127, 9565,17129, 5,17124, 9565,17133,17129,17134,17130,17133,17129,17133, 9565,17140, 6,17133,17127,17145, 9565,17147, 9600,17125, 9,17151, 5267,17125, 9,17155,16722,17125,10385,17125, 9,17161, 587,17125, 9565,17164, 9,17167, 9,17165, 9565,17171, 1275,17125, 903,17175, 9,17125, 375,17125, 587,17181, 9,17124, 5267,17185, 9600,17185, 9565,17185, 587,17190, 587,17185, 9565,17194, 587,17124, 375,17199,13737,17125, 9,17203, 6,17124,17176,17207,17175,17207, 903,17210, 903,17207, 17175,17214, 7,17124,10001,17219, 903,17221, 6,17125, 3,17224, 17219,17227, 903,17229, 7,17125, 88,17233, 89,17233, 265,17233, 264,17232,17239,17241, 264,17233, 3,17233, 9,17246, 3,17232, 17237,17251, 9,17251, 2,17232,17235,17257,17249,17257,17247,17257, 9,17263, 265,17232,17245,17267, 2,17233,17254,17271, 9,17271, 17251,17274,17251,17271, 9,17278,16531,17232, 9,17233, 3,17284, 17257,17287, 3,17285,17271,17291, 903,17233, 9565,17125, 1368,17297, 14,17297, 2,17296, 7,17303, 2,17297, 7,17306, 7,17307, 17301,17311, 5,17297,17305,17315,17129,17315, 6,17314,17311,17321, 6,17315,17309,17325,17303,17325,17299,17325, 587,17296, 9,17333, 9,17297, 587,17337, 6,17297, 5,17340,17311,17343, 7,17297, 2,17346,17325,17349,12377,17125, 9,17353,16531,17125, 6,17357, 7,17357, 6,17356,17361,17363, 7,17356,17359,17367, 0, 903, 767,17370, 4617,17373, 483,17375, 15,17371, 1011,17379, 767,17371, 4588,17383, 483,17383, 4579,17386, 4579,17383, 483,17390, 375,17371, 11,17395, 483,17370, 2265,17399, 4421,17399, 5285,17399, 11,17370, 375,17407, 6,17370,17380,17411,17379,17411, 1011,17414, 1011,17411, 17379,17418, 7,17370, 3549,17423, 2001,17423, 8495,17423,10291,17423, 1011,17431,14073,17423,11277,17423, 4971,17423, 5045,17423, 6,17371, 5,17442,17423,17445, 1011,17447, 7,17371, 1011,17451, 0, 1369, 2789,17455, 2821,17455, 2759,17455, 2687,17455, 6658,17455, 2,17455, 6,17466, 6625,17455, 9,17470,12551,17455, 1347,17455,13808,17455, 6685,17455,13833,17455, 4413,17455,17025,17455, 265,17487, 241,17486, 17038,17455, 903,17455, 9,17455, 6625,17496, 17,17454,12377,17501, 11,17454,12377,17505, 803,17455, 15,17454, 5303,17511, 4927,17511, 17033,17511,16983,17511, 265,17454, 2853,17521,17082,17455, 11,17455, 12377,17526,12564,17455, 241,17455,13737,17532,17025,17532, 1011,17455, 17049,17538,12377,17455, 10,17543, 10,17542, 305,17543, 11,17543, 17547,17551, 11,17542,17545,17555,17049,17455, 1011,17558, 4,17454, 5,17455,13737,17455, 241,17566, 0, 1275, 3,17570, 9,17573, 4,17570, 5,17570, 9856,17579, 9805,17579, 9,17582, 9,17579, 9805,17586, 5,17571, 3,17591, 0,17592, 0,17591, 3,17596, 9,17591, 1275,17601,17595,17603,17599,17603, 17,17591, 9805,17609, 1369,17590, 17,17613, 1486,17571, 17,17617, 1369,17571,17577,17621, 9,17623, 5,17621, 9,17627, 5,17620, 17,17631, 0, 17, 4,17634, 587,17637, 155,17635, 1011,17635, 1369,17634,12377,17645, 16990,17635, 587,17635,12377,17650,12566,17635, 903,17635,16937,17656, 12377,17635, 587,17660,16937,17635, 903,17664, 3,17634, 483,17669, 2,17635, 4,17673, 0,17674, 0,17673, 4,17678, 587,17673, 17,17683,17677,17685,17681,17685, 3,17635, 1369,17691, 0, 15, 5,17695, 7,17696, 1369,17694, 5303,17701, 4927,17701,16983,17701, 17033,17701, 3,17694, 3,17695,10104,17712,10105,17713,17715,17717, 10104,17713,10105,17712,17721,17723, 1, 13, 113,17727, 0, 12, 17727,17731, 9,17732, 2,17735, 2,17734, 137,17732, 136,17732, 2,17733,17741,17745, 3,17733,17739,17749,17743,17749, 2,17732, 9,17754,17749,17757,17749,17755, 3,17732,17737,17763,17745,17763, 0, 13, 1, 12, 1369,17771, 33,17771, 3,17770, 8251,17777, 3807,17777, 9875,17777, 8165,17777, 3,17771, 8241,17787,17769,17771, 9,17791, 2,17792, 2,17793, 137,17791, 136,17791, 2,17791, 9,17802, 3,17791,17797,17807, 2,17790,17807,17811,17799,17811, 3,17790,17805,17817,17795,17817,17803,17817,17801,17817, 1, 413, 4,17826, 2,17826, 5,17826, 6,17833, 6,17832, 3,17826, 6,17839, 6,17838, 2653,17827, 1637,17827,14537,17827,14321,17827, 260,17826, 2903,17827, 1639,17827, 1641,17827, 3361,17827, 331,17826, 17521,17827, 4909,17827,14593,17827, 261,17826, 257,17826, 14,17826, 1274,17826, 2159,17827, 2161,17827, 251,17827, 2647,17827, 331,17885, 15,17826, 1275,17826,14652,17827, 6,17827,17829,17895,17831,17895, 8997,17895,17863,17895,17871,17895,17889,17895,17891,17895, 7,17827, 17833,17911,17839,17911, 8495,17911, 413,17910, 0,17919,17837,17911, 17843,17911, 265,17911,17921,17927, 1,17927,17919,17931, 2647,17927, 8717,17911, 3785,17911,17853,17911,17875,17911,17877,17911,14315,17910, 261,17911, 7,17826,17835,17951,17841,17951, 8647,17951, 251,17951, 6,17826, 5,17960,17911,17963, 3,17960,17911,17967,15029,17827, 265,17971,17895,17973, 7,17971,14315,17827, 6,17978, 7,17978, 6,17979,17983,17985, 7,17979,17981,17989, 0, 412, 9036,17993, 9099,17993,17829,17993,17895,17998,17831,17993,17895,18002,17896,17993, 17898,17993,17913,17993,17915,17993, 446,17993, 4371,18015, 4379,17993, 17900,17993,17917,17993, 4360,17993, 3429,17993,17882,17993, 7039,17993, 17958,17993,17949,17993, 241,17993, 445,18036, 4371,18039, 445,18037, 4349,18043,16097,17993,12289,17993, 8647,17993, 8997,18050, 4349,17993, 251,18054,17951,17993, 251,18058, 251,17993, 4349,18062,17827,18062, 17951,18062,17895,17993,17829,18070,17831,18070, 8997,18070, 5521,17993, 375,18079, 445,17993, 241,18082, 4371,18085, 3,18083, 2,18082, 18089,18091, 2,18083, 3,18082,18095,18097, 465,17993, 5,18101, 4,18100,18103,18105, 4,18101, 5,18100,18109,18111, 9082,17993, 8495,18115,17910,17993,17833,18119,17839,18119, 8495,18119, 375,17993, 7,17993, 8495,18129, 8997,18131,17827,18129,17829,18135,17831,18135, 8997,18135, 8997,18128, 8495,18143,17827,18128,17833,18147,17839,18147, 8495,18147, 8997,17993, 8647,18154,17895,18154, 7,18154, 8495,18161, 17827,17993, 241,18164, 6,18167, 6,18166, 265,18165,17895,18173, 261,18164, 375,18165, 260,18164, 251,18164, 6,18165,18177,18185, 7,18165,18171,18189,18181,18189, 6,18164,18173,18195, 241,18194, 18189,18199,18189,18195, 7,18164,17833,18205,17839,18205,18169,18205, 18185,18205, 8495,18205, 1, 843, 0, 842,18217,18219, 483,18220, 4,18223, 4,18222, 581,18220, 580,18220, 4,18221,18229,18233, 5,18221,18227,18237,18231,18237, 4,18220, 483,18242,18237,18245, 18237,18243, 5,18220,18225,18251,18233,18251, 0, 413,15309,18257, 265,18258,15363,18261,15424,18257,15363,18265,13375,18257,13381,18257, 4888,18257,13162,18257, 251,18256, 375,18256, 265,18257,15309,18281, 15383,18283,15309,18280,15363,18287, 331,18257, 2663,18257, 251,18293, 9,18256, 483,18256, 375,18257, 4863,18300,13119,18300, 4863,18257, 375,18306,13119,18257, 375,18310, 6,18257, 264,18314, 7,18257, 264,18318, 264,18319, 265,18319,18321,18325, 265,18318,18323,18329, 8647,18319, 375,18319, 331,18319, 7,18256, 1689,18339, 1705,18339, 2701,18339,18317,18339, 8717,18339,12755,18339, 7627,18339, 7895,18339, 3785,18339,13443,18339, 7287,18339, 265,18339, 331,18339, 8495,18339, 375,18339,12745,18339, 457,18371, 375,18371, 6,18256,18291,18377, 12745,18257,17895,18381, 8647,18381, 7,18381, 8495,18387, 1, 412, 1679,18391, 448,18391, 4349,18395, 4351,18391, 4390,18391,18300,18391, 4457,18391,18277,18391, 1673,18391,18279,18391, 1789,18391,18364,18391, 18335,18391, 3427,18391, 7037,18391, 265,18391, 445,18422, 4349,18425, 445,18423, 4371,18429,16095,18391,12287,18391, 5189,18391,18299,18391, 18297,18391, 2153,18391, 2151,18391, 4371,18391, 331,18446,18339,18391, 331,18450, 331,18391, 4371,18454,18339,18454, 445,18391, 265,18460, 4349,18463, 5,18461, 4,18460,18467,18469, 4,18461, 5,18460, 18473,18475, 465,18391, 3,18479, 2,18478,18481,18483, 2,18479, 3,18478,18487,18489, 8386,18391,18318,18391, 375,18391,18257,18496, 7,18391, 265,18501,18257,18503, 8337,18500,18257,18500, 8337,18391, 7,18510, 8861,18391, 6,18515, 7,18515, 6,18514,18519,18521, 7,18514,18517,18525,18257,18391, 265,18528, 241,18529, 6,18532, 6,18533, 375,18528, 261,18529, 260,18529, 251,18529, 6,18529, 241,18546,18531,18547, 7,18529, 8495,18553,18537,18553, 6,18528, 18553,18559,18541,18559, 7,18528,18549,18565,18535,18565,18547,18565, 18543,18565, 0, 843, 1, 842, 5,18576,18575,18577, 483,18581, 4,18582, 4,18583, 581,18581, 580,18581, 4,18581, 483,18592, 5,18581,18587,18597, 4,18580,18597,18601,18589,18601, 5,18580, 18595,18607,18585,18607,18593,18607,18591,18607, 1, 1217,16117,18617, 12291,18617,16103,18617, 4959,18617,17399,18617, 2205,18617, 2207,18617, 1269,18617, 5,18633, 4,18632,18635,18637, 4,18633, 5,18632, 18641,18643, 1259,18617, 2,18647, 3,18646,18649,18651, 3,18647, 2,18646,18655,18657, 7,18617, 0, 1216, 9,18662,18617,18665, 483,18662,18617,18669,18660,18663, 7,18663,18617,18674,18617,18663, 6,18679, 7,18679, 6,18678,18683,18685, 7,18678,18681,18689, 1, 1531, 4904,18693,17609,18693,17586,18693, 4903,18693, 9,18700, 17579,18693, 9,18704, 9,18693, 4903,18708,17579,18708, 5,18692, 0, 1530,18693,18717, 4,18719, 5,18719, 4,18718,18723,18725, 5,18718,18721,18729, 1, 19, 1369,18733, 3,18733, 3,18732, 9875,18739, 0, 18,18733,18743, 2,18745, 3,18745, 2,18744, 18749,18751, 3,18744,18747,18755, 0, 1217,12293,18759,16105,18759, 1269,18759, 2,18765, 3,18764,18767,18769, 3,18765, 2,18764, 18773,18775, 1259,18759, 5,18779, 4,18778,18781,18783, 4,18779, 5,18778,18787,18789, 375,18759, 7,18759, 1, 1216, 4,18796, 18759,18799, 3,18796, 6,18803, 6,18802, 5,18796, 6,18809, 6,18808, 2,18796,18759,18815, 5241,18797, 14,18796, 1274,18796, 2157,18797, 2155,18797,18795,18797,18799,18829,18815,18829, 15,18796, 1275,18796, 6,18796, 3,18838, 5,18838, 7,18796,18805,18845, 18811,18845,18794,18797,18803,18851,18809,18851, 6,18797,18800,18857, 18816,18857,18799,18857,18759,18862,18815,18857,18759,18866,18835,18857, 18837,18857,18759,18857,18799,18874,18815,18874, 7,18797,18841,18881, 18843,18881,18803,18881,18759,18887,18809,18881,18759,18891,18807,18881, 18813,18881,18821,18881,18823,18881,18759,18880,18803,18903,18809,18903, 18759,18797, 6,18909, 7,18909, 6,18908,18913,18915, 7,18908, 18803,18919,18809,18919,18911,18919, 0, 1531, 1, 1530, 6717,18929, 9,18931,18927,18929, 4,18935, 5,18935, 4,18934,18939,18941, 5,18934,18937,18945, 0, 19, 1, 18,18949,18951, 2,18953, 3,18953, 2,18952,18957,18959, 3,18952,18955,18963, 0, 2, 11303,18967,11349,18968, 5071,18967, 5097,18972,11350,18967, 5098,18967, 11304,18967,11307,18981, 5072,18967, 5075,18985,11315,18967, 5079,18967, 13961,18967, 581,18993, 4,18992,18995,18997, 5,18992, 580,18993, 19001,19003, 5,18993, 4,18993, 483,19008,19001,19011, 483,18993, 4,19014,19001,19017, 4,19015,19007,19021, 1181,18966, 1206,18966, 3451,18967, 375,19029, 1967,18967, 375,19033, 567,18966, 4992,19037, 9,19037, 4971,19040, 4971,19037, 9,19044, 1141,18966, 555,18966, 981,18967,16129,18966,16143,19055, 9523,18967, 483,19059, 9525,19061, 1007,18967, 1297,18966, 524,18966, 0,19069, 4,19070, 4,19069, 0,19074, 97,18967,11067,18967, 1275,19080, 7947,19083, 1205,18967, 571,18967,11070,18967, 7947,19091,10043,18967, 1275,19094,10041,19097, 10044,18967,10041,19101, 1206,18967, 3001,19105, 1901,19105, 30,18967, 8165,19111, 8150,18967, 33,19115, 1181,18967, 3663,19119, 1997,19119, 3069,19119, 1923,19119, 9769,18967, 3972,18967, 8124,18967, 9357,18967, 9346,18967, 8782,18967, 4244,18967, 4178,18967, 9768,18967, 8804,18967, 8245,18967, 8249,18967, 8247,18967, 6950,18967,12299,18967, 4652,18967, 10684,18967,14096,18967, 4992,18967, 203,18967,11731,19167,17771,18967, 113,19171,14223,18967, 85,18967,11731,19177,11031,18967, 113,19181, 107,18967,11731,19185,11699,18967, 113,19189, 8701,18967, 9293,18967, 3933,18967, 9,19196, 8109,18967, 9,19200, 4213,18967, 9,19204, 4147,18967, 9,19208, 8757,18967, 9,19212, 9335,18967, 9,19216, 10202,18967, 7947,19221,17637,19221, 578,18967, 4935,19227,11349,18967, 11303,19230, 5097,18967, 5071,19234, 8647,18967, 11,19239,10603,18967, 375,19243,10427,19243,10609,19243, 7,19243,10607,19251, 9,19242, 4625,18967, 375,19257, 75,19257, 4629,19257, 7,19257, 4627,19265, 9,19256,11277,18967, 10,19270,11307,19273, 10,19271,11349,19277, 483,19271, 5045,18967, 10,19282, 5075,19285, 10,19283, 5097,19289, 483,19283, 6789,18967, 9,19294, 288,18967, 525,18967,19073,19301, 19077,19301, 1811,19301, 1877,19301, 5,19301,17563,19301, 4861,19301, 1290,18967, 5,19317, 3721,19317, 1985,19317,17563,19317, 4861,19317, 296,18967, 8861,19329, 12,18967, 8165,19333, 18,18967, 25,18967, 9,19338, 8165,19341, 8165,19339, 9,19345, 7971,18967, 9,19348, 33,19351, 33,19349, 9,19355, 47,18967,11731,19359,10107,18967, 1275,19362, 7947,19365,17637,19365, 113,19363, 59,18967,17635,19373, 10291,18967, 165,19377, 375,18967, 510,18967, 11,18967, 8165,19385, 9,19387, 265,19384, 9,19384, 8165,19393, 9,18967, 567,19397, 4971,19399, 6,19397, 25,19396, 8165,19405, 7971,19396, 33,19409, 3933,19396, 8109,19396, 4213,19396, 4147,19396, 9335,19396, 8757,19396, 8495,19396, 6789,19396, 4625,19396,10603,19396, 4971,19396,14073,19396, 567,19396, 4935,19437, 11,19397, 8109,19441, 3933,19441, 8495,19441, 7971,19441, 265,19396, 8861,19451, 11,19396, 8165,19455, 483,19396, 17,18967, 1275,19460, 4861,19463,17563,19463, 3721,19463, 1985,19463, 15,19460, 15,18967, 9731,19474, 1011,19475, 483,19475, 17,19474, 6515,18967, 483,19485, 6527,19487, 6557,19487, 6561,19487,14210,18967, 17,19495, 4971,18967, 9,19498,14073,18967, 9,19502, 5921,18967, 375,19507,10046,18967, 16,18966, 0,19513, 4,19514,19317,19517, 19463,19517, 4,19513, 0,19522,19317,19525,19463,19525, 8495,19513, 10351,19513, 4311,19513, 4329,19513, 8717,19513,10055,19513, 3785,19513, 14,18966, 6,19545, 2,19546, 2,19545, 6,19550, 482,19545, 17,19545, 10,18966,17777,19559, 2215,19559,11307,19559, 5075,19559, 11713,19559, 2221,19559,11087,19559,10439,19559,10665,19559, 4643,19559, 11037,19559, 2233,19559, 9195,19559,11277,19559, 5045,19559,19455,19559, 19333,19559,19393,19559,19385,19559, 9,19597, 9317,19559, 9755,19559, 4321,19559,10171,19559, 4295,19559, 3833,19559,10603,19559, 9,19613, 4625,19559, 9,19617, 8,18967, 11,19621, 14,18967, 9731,19625, 17,19625, 11,18966, 8124,19631, 3972,19631, 8804,19631, 8150,19631, 7971,19631, 9,19640, 3933,19631, 9,19644, 8109,19631, 9,19648, 8495,19631, 9,19652, 9,19631, 8109,19656, 3933,19656, 8495,19656, 7971,19656, 9,18966,10001,19667, 5,19669, 4,19668,19671,19673, 4,19669, 5,19668,19677,19679, 16,18967, 7,19683, 10,18967, 11277,19686,11307,19689, 5045,19686, 5075,19693,11349,19687, 5097,19687, 9195,19687,19656,19687,19441,19687,19631,19687, 9,19706,11277,19687, 11303,19711, 5045,19687, 5071,19715, 9,19687,19631,19718, 19,18967, 13,18967,19631,19725,10385,18967, 101,19729, 128,19729, 9,19729, 113,19734, 483,19729,10081,19739,11759,19739,10405,19739, 113,19729, 9,19746, 67,18967,11613,19751,12216,19751, 9,19751,11731,19756, 11731,19751, 9,19760, 566,18967, 253,19765, 1471,19765, 53,19765, 256,18967, 629,18967, 1413,18967, 1471,19777, 1346,18967, 340,18967, 8165,19783, 567,18967, 4935,19787, 9,19789, 9,19786, 4935,19793, 305,18967, 959,18967,11731,19799, 759,18967,11731,19803, 331,18967, 17635,19807, 1325,18967,17635,19811,10001,18967,10003,19815, 4,19817, 4,19816,10007,19815, 580,19815,10006,19815, 483,19815, 4,19828, 4,19829, 581,19815, 4,19815,10003,19836, 483,19836, 5,19815, 19819,19843,19833,19843, 4,19814,19835,19849,19823,19849,19843,19849, 5,19814,19839,19857,19821,19857,19825,19857,19827,19857,19841,19857, 19831,19857,19837,19857, 9731,18967, 15,19872, 8495,18967, 483,19877, 9,19876, 9195,18967, 113,19883,11731,19883, 241,18967, 7,19888, 483,18967, 9,19892, 17,19893, 903,19897, 5,19892, 253,19901, 1471,19901, 53,19901, 5,19893, 1505,19909, 903,18967, 7,19913, 1275,18967,10043,19916,10041,19919,11067,19916, 7947,19923,17637,19917, 10107,19927, 0,19916, 4,19931, 0,19932,19917,19935, 7,19932, 19937,19939, 7,19931, 4,19942, 16,19931, 6,19916, 4,19949, 6,19950,19917,19953, 1,19950,19955,19957, 1,19949, 4,19960, 8,19916, 4,19965, 1,19966, 1,19965, 4,19970,10107,19916, 7947,19975,17637,19975, 7947,19917,11067,19981,10107,19981, 9,19917, 2009,19987, 3135,19987,19969,19987,19973,19987, 5231,19987,19957,19987, 19963,19987, 0,19987, 5175,19987,14065,19987, 17,19916,19525,20009, 19517,20009, 3721,20009, 1985,20009, 1,20009,19987,20019,20003,20009, 4861,20009,17563,20009, 5,19916, 4,19917, 5,19917, 265,18967, 17635,20035, 5771,20035, 9,20035, 11,20034, 11,20035, 9,20034, 8861,20047, 483,20035, 7,20034, 8165,20053, 7,20035, 8495,20057, 587,18967, 7,20061, 4,20063, 4,20062, 16,20061, 17,20061, 4,20060,20071,20073, 5,20060,20067,20077,20069,20077, 4,20061, 7,20082,20077,20085, 5,20061,20065,20089,13947,18967, 5,20092, 17,20095, 5,20093, 9,20099, 4,18966, 8770,20103, 8729,20103, 8697,20103, 8784,20103, 4266,20103, 9262,20103, 2,20103, 7,20117, 8684,20103, 8717,20121, 331,20121, 8647,20103, 8757,20126, 8757,20103, 8647,20130, 375,20130, 4213,20103, 375,20136, 9750,20103,19687,20103, 347,20103, 386,20103, 340,20103, 331,20149, 375,20103, 8757,20152, 4213,20152, 9195,20152, 305,20152, 9,20103,10291,20103, 483,20165, 59,20103, 15,20103, 9195,20103, 375,20172, 331,20103,10001,20103, 9,20179, 305,20103, 375,20182, 7,20103, 8495,20186, 8717,20189, 331,20189, 8495,20187, 8757,20195, 9731,20186, 265,20187, 8757,20201, 4213,20201, 9195,20201, 305,20201, 265,20186, 331,20211, 8647,20187, 1325,20103, 7,20102, 8495,20219,10351,20219, 4311,20219, 4329,20219, 3785,20219,10055,20219, 8717,20219, 483,20103, 1275,20103, 265,20103, 7,20239, 8495,20241, 375,20241, 7,20238, 331,20247, 9731,20103, 7,20250, 8495,20103, 7,20254, 8717,20257, 331,20257, 483,20255, 9,20255, 7,20255, 8647,20267, 375,20267, 5,18966, 9535,20273, 9537,20273, 2,20273, 6,20278, 9559,20273, 482,20273, 9563,20273, 9362,20273, 922,20273, 1413,20273, 19,20273, 12,20273, 8150,20273, 8804,20273,19385,20273, 1290,20273, 9533,20305, 525,20273, 9533,20309, 7971,20273, 9,20312, 11,20273, 9,20316, 17,20273, 1275,20320, 9533,20323, 9,20273, 9195,20326, 11,20326, 7971,20326, 8495,20326, 9195,20273, 9,20336, 6,20273, 5,20341, 2,20340, 5,20340, 18967,20347, 11,20341, 7,20273, 5,20353, 6,20272, 17,20357, 7,20272, 9195,20361,11277,20361, 5045,20361, 9755,20361, 4295,20361, 10171,20361, 4321,20361, 3833,20361, 9317,20361, 483,20273, 903,20380, 1275,20273, 17,20384, 9533,20387, 903,20273, 483,20390, 8495,20273, 9,20394, 9731,20273, 6,20398, 7,20398, 6,20399,20403,20405, 7,20399,20401,20409, 6,18966,19836,20413,19857,20415,19854,20413, 19871,20413,19815,20413, 4,20423,19843,20425, 4,20422,19857,20429, 19477,20413,19145,20413,19875,20413,19843,20413,19849,20438,19849,20413, 19843,20442,19718,20413,19473,20413,19483,20413,19725,20413, 19,20413, 12,20413,19337,20413,19687,20413, 9,20460,19475,20413, 9731,20465, 17,20465, 9,20413,19687,20470, 11,20470, 11,20413, 9,20476, 8495,20413, 5,20413, 9,20483, 4,20413,19815,20487,19849,20489, 19815,20486,19857,20493, 5,20412, 17,20497, 7,18966,10439,20501, 11087,20501,10665,20501, 4643,20501,11307,20501, 5075,20501,17777,20501, 2215,20501,18739,20501, 4339,20501,11713,20501, 2221,20501,11037,20501, 2233,20501,19626,20501,19129,20501, 0,20501, 4,20534,19301,20537, 19317,20537,19463,20537,20009,20537,10036,20501,19843,20547, 8800,20501, 8714,20501, 5045,20501,11277,20501, 4551,20501,19628,20501,19455,20501, 19393,20501,19723,20501,19333,20501, 305,20501, 8495,20570, 959,20501, 19625,20501, 9731,20576, 17,20576,10603,20501, 9,20583, 4625,20501, 9,20587,19385,20501, 9,20591, 759,20501, 47,20501,10107,20501, 241,20599, 265,20598,10196,20501, 11,20501, 8495,20606, 17,20501, 19625,20610, 59,20501,10291,20501, 1011,20617, 15,20501, 1325,20501, 8495,20501, 10,20624, 10,20625, 305,20624, 11,20624,20629,20633, 11,20625,20627,20637, 9731,20501,19625,20640, 4,20501, 7,20645, 483,20647,18967,20649, 0,20644,19301,20653,19317,20653,19463,20653, 20009,20653,20651,20653, 7,20644,19916,20665,20653,20667, 1275,20665, 18967,20670,20653,20673,18967,20665, 1275,20676,20653,20679,10001,20644, 19843,20683, 1011,20645,10047,20645, 5,20501, 9287,20691, 331,20501, 4,20500, 8495,20697, 4311,20697,10351,20697, 3785,20697, 4329,20697, 8717,20697,10055,20697, 5,20500, 9195,20713,11277,20713, 5045,20713, 4321,20713, 9755,20713, 4295,20713,10171,20713, 9317,20713, 3833,20713, 903,20501, 265,20501,10107,20734, 9195,20501, 241,20739,10001,20501, 4,20742,19843,20745, 5,20742,18967,20748, 4,20743,20751,20753, 19511,20753,19857,20753, 5,20743, 7,18967, 8810,20762, 8811,20762, 2,20763, 1,20768,20483,20763, 8495,20773, 8800,20763,20273,20763, 8495,20763, 11,20780, 8810,20763,20767,20785,10081,20763, 1011,20789, 1010,20788,20791,20793, 1010,20789, 1011,20788,20797,20799, 566,20763, 11,20763, 9731,20805, 8495,20805, 8495,20804, 265,20763,20482,20763, 17,20815, 567,20763, 9195,20819, 9,20763, 8811,20763,20765,20825, 241,20762, 265,20762, 8165,20831, 1011,20763, 375,20763, 4,20762, 20815,20839, 5,20762,11276,20842, 5044,20842,11277,20842,11276,20843, 20849,20851, 5045,20842, 5044,20843,20855,20857,20773,20843,20470,20843, 20103,20843,20413,20843, 9,20866, 9195,20843,11277,20843,20845,20873, 5045,20843,20847,20877, 9,20843,20413,20880, 4,20763,20480,20885, 7,20884,20843,20889, 9366,20885, 1,20885, 3,20894,20842,20896, 20843,20897,20899,20901,20889,20900,20842,20897,20843,20896,20907,20909, 20890,20897,20889,20897,20843,20914, 3,20885, 1,20918,20842,20920, 20843,20921,20923,20925,20889,20924,20842,20921,20843,20920,20931,20933, 20890,20921,20889,20921,20843,20938, 9195,20885, 483,20942,20866,20885, 8495,20885,20413,20948, 483,20885, 9195,20952,20413,20885, 8495,20956, 20843,20956,20843,20885, 1,20962, 3,20964, 3,20962, 1,20968, 7,20963,20897,20973,20921,20973,20967,20973,20971,20973,20413,20962, 5,20763, 7,20985, 17,20985,20413,20989,20413,20984,20839,20993, 17,20993, 483,20984,20839,20985, 1,21001, 3,21002, 3,21001, 1,21006, 7,21000,21005,21011,21009,21011,20413,21001,20413,20763, 5,21019,20885,21021, 9,21021, 5,21018,20839,21027, 17,21027, 483,20763, 5,21032, 5,18967, 0,21037, 3,21038, 9357,21037, 20742,21037,20761,21045,20187,21037, 8495,21049,20501,21037,10001,21036, 20753,21055,20763,21037, 8495,21059,13947,21036, 17,21063, 256,21037, 20186,21037,20885,21037, 7,21071,20897,21073,20921,21073, 9,21037, 1275,21079, 9533,21081,21041,21081, 17,21037, 9195,21087, 7971,21087, 8495,21087, 483,21036, 253,21095, 1471,21095, 53,21095, 1275,21036, 6,21036,20640,21105,20610,21105,21069,21105, 9731,21105,20501,21112, 20501,21105, 9731,21116, 17,21116, 17,21105,20501,21122, 7,21036, 11276,21126, 5044,21126,11277,21126,11276,21127,21133,21135, 5045,21126, 5044,21127,21139,21141, 1,21127, 3,21144,18967,21147, 3,21127, 1,21150,18967,21153,18967,21127,20470,21127,21049,21127,20413,21127, 9,21162,20103,21127, 9195,21127,11277,21127,21129,21171, 5045,21127, 21131,21175, 9,21127,20413,21178, 6,21037,21149,21183,21155,21183, 20254,21183,19243,21183,19257,21183,18967,21183, 1,21183, 3,21196, 21126,21198,21127,21199,21201,21203,21126,21199,21127,21198,21207,21209, 3,21183, 1,21212,21126,21214,21127,21215,21217,21219,21126,21215, 21127,21214,21223,21225, 8495,21183,20103,21228,19687,21183,20843,21183, 21166,21183, 11,21183,20501,21239,20103,21183, 8495,21242,21127,21242, 21127,21183,20103,21248,20763,21183, 9731,21253, 17,21253, 7,21037, 19625,21259, 15,21259,20413,21263,20103,21258,21105,21267, 241,21258, 21105,21259,20103,21273,20103,21037, 7,21277,21199,21279,21215,21279, 11277,21279, 5045,21279,21183,21279, 6,21276, 1,21291, 3,21292, 21279,21295, 3,21291, 1,21298,21279,21301, 7,21276,21105,21305, 241,21037, 483,21309, 7,21308, 4,18967,21183,21315, 0,21314, 20309,21319, 524,21319,20273,21323,20305,21319, 1291,21319,20273,21329, 21081,21319,20323,21319,20387,21319, 11,21319, 483,21338,20273,21341, 483,21319, 11,21344,20273,21347, 165,21315,17635,21315, 1011,21352, 17642,21315,20413,21315, 6,21359, 9,21315,20352,21315,11277,21365, 5045,21365,20985,21315, 11,21315,10075,21315, 483,21315, 1347,21315, 6,21314, 1,21381, 3,21382,21365,21385, 3,21381, 1,21388, 21365,21391,20273,21381, 11,21381, 7,21314, 6,21315, 17,21401, 7,21315,21384,21404,21390,21404,21385,21405,20273,21411,21407,21411, 21391,21405,20273,21417,21409,21417,21385,21404,21384,21405,21423,21425, 21391,21404,21390,21405,21429,21431,11276,21404, 5044,21404,11276,21405, 11277,21404,21439,21441, 5044,21405, 5045,21404,21445,21447, 0,21405, 4,21450, 4,21405, 0,21454, 8495,21405, 5045,21405,20273,21461, 21437,21461,11277,21405,20273,21467,21435,21467, 9,21405,20273,21404, 21385,21475,21391,21475,11277,21475, 5045,21475, 265,21405, 483,21405, 18967,21487,21453,21489,21457,21489,21381,21405,20273,21315, 6,21497, 1,21499, 3,21500, 3,21499, 1,21504, 7,21496,21503,21509, 21507,21509,21385,21509,21391,21509,11277,21509, 5045,21509, 1011,21315, 17635,21522, 6,18967, 2,21526, 11,21529,20103,21527,20690,21527, 9,21535,21259,21527, 9,21539, 17,21527, 4,21526, 11,21545, 5,21526,20640,21549,21259,21549,20610,21549, 9731,21549,20501,21556, 20501,21549, 9731,21560, 17,21560, 17,21549,20501,21566, 4,21527, 15,21571, 5,21527, 482,21575, 2,21575, 6,21578, 6,21575, 2,21582, 9,21575,20501,21587,20501,21574, 9,21591,20501,21527, 5,21595, 17,21597, 5,21594, 9,21601, 1, 3,19718,21604, 19719,21604,19402,21605,20962,21604,20973,21613,21248,21604,21272,21604, 21494,21604,20963,21604,21249,21604,21001,21604,21011,21627,21273,21604, 21495,21604,21178,21604,20880,21604,21179,21604,20881,21604,21049,21604, 20773,21604,21361,21604,15753,21605, 803,21649,14387,21605, 375,21653, 9663,21604, 9177,21604,20351,21604,20485,21604,21360,21604, 990,21604, 4745,21667,19685,21605,21087,21671,21156,21605,21087,21675,21317,21605, 21291,21604,21279,21681,21499,21604,21509,21685, 996,21604, 4745,21689, 21472,21604,21473,21604, 761,21605, 3419,21697, 6469,21697, 3119,21697, 21048,21604,20772,21604, 973,21604, 955,21708, 4745,21711, 9,21708, 4745,21715, 4745,21709, 955,21719, 9,21719, 2077,21605, 7,21725, 14,21724,21727,21729, 6,21725, 15,21724,21733,21735,20350,21604, 20484,21604, 9662,21604, 9176,21604,21380,21604,21104,21604,21126,21604, 21183,21751, 9,21751,20842,21604,20885,21757, 9,21757, 305,21604, 18967,21763, 375,21765, 955,21604, 973,21769, 4805,21771, 973,21768, 4745,21775,17423,21769, 4745,21769, 713,21604,21404,21604,21381,21785, 9,21785,20884,21604,21316,21605,21182,21604,20501,21795,21793,21795, 21405,21604,21381,21800, 9,21800,20885,21604,20843,21806,20890,21807, 20889,21807,20843,21812,20973,21807,21073,21807,20413,21807,20843,21807, 21757,21823,20889,21822,21183,21604,21127,21828,21279,21829,21679,21829, 20103,21829,21127,21829,21751,21839,21105,21604,21381,21604,21365,21845, 21405,21844,20413,21845,21475,21845,21405,21845,21785,21855,20273,21855, 21509,21845,20843,21604,20885,21862, 9,21862,21127,21604,21183,21868, 18967,21869,21183,21873, 9,21868, 1199,21605,13923,21604,13935,21881, 9437,21605, 587,21885, 9439,21887, 1177,21605, 1421,21604, 668,21604, 1,21895, 5,21896, 5,21895, 1,21900, 117,21605,11759,21605, 1369,21906, 7971,21909,11760,21605, 7971,21913, 809,21605, 989,21605, 9929,21605, 1369,21920, 9927,21923, 9930,21605, 9927,21927,19596,21605, 9,21931,19556,21605,20170,21605,19707,21605, 9,21939,20956,21605, 21791,21943,21242,21605,21795,21947,20773,21605,21707,21951,21049,21605, 21705,21955,21373,21605,20464,21605,19557,21605,20499,21605,20359,21605, 9181,21605, 9671,21605, 4145,21605, 3801,21605, 4135,21605,10101,21605, 20577,21605,19656,21605,19441,21605,19332,21605,19392,21605,19454,21605, 21059,21605,19440,21605,19657,21605, 4134,21605,10100,21605,20498,21605, 20358,21605,20142,21605, 9,22007,20576,21605,20864,21605, 9,22013, 21116,21605,21166,21605,21183,22019, 9,22019,21560,21605, 9180,21605, 9670,21605, 3800,21605, 4144,21605,21026,21605,20839,22035,20814,21605, 20839,22039,20992,21605,20839,22043,21359,21605,21845,22047,21647,22047, 21053,21605,21795,22053,20779,21605, 8087,21605, 8091,21605, 8089,21605, 20303,21605, 9,22065,20465,21605,10786,21605,11131,21605, 4696,21605, 11970,21605,19722,21605,19333,21605,19393,21605,19455,21605,20351,21605, 21739,22087,20485,21605,21741,22091, 9663,21605,21743,22095, 9177,21605, 21745,22099,20350,21605,21661,22103,20484,21605,21663,22107, 9662,21605, 21657,22111, 9176,21605,21659,22115,10099,21605, 17,22119, 17,22118, 4133,21605, 17,22125, 17,22124, 8251,21605, 9,22131, 3807,21605, 9,22135, 13,21604,18967,22139, 19,21604,20501,22143, 9875,22143, 12,21604, 8251,22149, 3807,22149,19559,22149,20501,22149, 9875,22149, 8165,22149, 18,21604, 3799,21605, 17,22165, 17,22164, 4143,21605, 17,22171, 17,22170, 4283,21605, 9,22177, 4279,21605, 9,22181, 9669,21605, 17,22185, 17,22184, 9179,21605, 17,22191, 17,22190, 9673,21605, 9,22197, 9967,21605, 9,22201,19624,21605,20501,22205, 17,22205,19686,21605,22149,22211,19441,22211,19656,22211,21607,22211, 19631,22211, 9,22220, 9,22211,19631,22224,19559,21605,19385,22228, 9,22231, 9,22229,19545,21605, 17,22236, 17,22237,10102,21605, 7971,22243,17053,22243, 629,21605,21117,21605,21561,21605,20867,21605, 20885,22255,21167,21605,21183,22259,21548,21605, 17,22263,20501,22263, 21104,21605,21069,22269,21267,22269,21305,22269,21259,22269,20103,22277, 17,22269,20501,22269,20838,21605,20985,22285,20842,21605,21865,22289, 21809,22289,21613,22289,21637,22289,21867,22289,20773,22289,20956,22289, 21863,22289,20885,22305, 9,22305,20885,22289,20413,22310,20413,22289, 20885,22314,21126,21605,21871,22319,21831,22319,21617,22319,21635,22319, 21877,22319,21049,22319,21242,22319,21869,22319,21183,22335, 9,22335, 21183,22319,20103,22340,20103,22319,21183,22344,21020,21605,20885,22349, 21278,21605,21183,22353,21052,21605,21829,22357,21127,22357,21358,21605, 21747,22363,21665,22363,21532,21605,20497,21605, 17,22371, 17,22370, 20361,21605, 9,22377,20713,21605, 9,22381,20357,21605, 17,22385, 17,22384,21048,21605,21643,22391,20772,21605,21645,22395,21509,21605, 21381,22399,21499,22399, 9,22399,21475,21605,21381,22407, 9,22407, 21365,21605,21381,22413, 9,22413,11971,21605, 4697,21605, 8387,21605, 9,22423,11949,21605, 11,22426, 5,22428, 6,22426, 5,22432, 5,22426, 6,22436, 6,22437, 7,22426,22441,22443, 7,22427, 22435,22447,22439,22447,22431,22447, 14,22426,22447,22455, 6,22427, 15,22426,22459,22461, 9,22426, 9,22427, 4669,21605, 11,22468, 5,22470, 6,22468, 5,22474, 5,22468, 6,22478, 6,22479, 7,22468,22483,22485, 7,22469,22477,22489,22481,22489,22473,22489, 14,22468,22489,22497, 6,22469, 15,22468,22501,22503, 9,22468, 9,22469,12345,21605, 5,22510, 4,22510, 12,22510, 13,22511, 22517,22519, 12,22511, 13,22510,22523,22525, 4,22511,22513,22529, 5,22511,22515,22533, 5123,21605, 5,22536, 4,22536, 12,22536, 13,22537,22543,22545, 12,22537, 13,22536,22549,22551, 4,22537, 22539,22555, 5,22537,22541,22559,10697,21605, 9,22562,19385,21605, 19559,22566, 9,22569, 9,22567,19559,22573,19397,21605, 6,22576, 11,22577, 11,22576,19475,21605,20413,22584, 1406,21605, 1396,21605, 525,21605, 903,22593, 934,21605, 9,22597, 1290,21605, 903,22601, 669,21605,21899,22605,21903,22605, 1861,22605, 1887,22605, 4,22605, 17013,22605, 4917,22605,19687,21605,22139,22621,21609,22621, 9,22621, 20103,22620, 9,22629,19625,21605,20501,22632,19384,21605,21087,22637, 20326,22637, 9,22636,20273,22637, 9,22644, 9,22637,20273,22648, 19396,21605, 5,22652, 10,22652,19441,22657, 10,22653,19455,22661, 11,22652,22661,22665, 11,22653,22657,22669,19474,21605,20413,22673, 1418,21605, 4,22677, 3755,22677, 1995,22677,17013,22677, 4917,22677, 12,21605,22139,22689,18967,22688, 18,21605,22143,22695,21252,21605, 21279,21605,21183,22701,21291,22701, 9,22701,20483,21605,20763,22708, 20187,21605,21036,22712,21069,22715,21036,22713,21049,22719,21037,22713, 21037,22712, 9,22713,20353,21605, 5,22729,21315,22729, 33,21605, 8150,22735,17727,22735, 9,22735, 7971,22740, 7971,22735, 9,22744, 17025,22735, 8165,21605, 30,22751, 181,22751, 9,22751, 25,22756, 25,22751, 9,22760, 145,22751, 53,21605,17049,22767,10219,21605, 903,22771, 155,22771,10081,21605, 1369,22776, 7971,22779,17053,22779, 257,21605, 9,22785, 1171,21605, 4722,22789, 4713,22789, 903,22792, 21315,22789, 903,22789, 4713,22798, 628,21605, 9,22803, 11,21605, 766,22807, 767,22807,20984,22807,20762,22806,22813,22815,20985,22807, 20762,22807,22140,22807,19718,22807,19725,22807, 586,22806,22809,22829, 5,22807,20763,22832,22815,22835,20763,22833,22821,22839, 587,22832, 22829,22843, 587,22833, 586,22807,22847,22849, 5515,22807,17043,22807, 4825,22807,17727,22807, 8150,22807,22139,22807,18967,22862,19396,22806, 19397,22806,19396,22807,22869,22871,19397,22807,22867,22875,22653,22875, 20763,22807, 5,22880,22815,22883,19687,22807, 9,22886, 7971,22807, 9,22890,19461,22807, 9,22807,19687,22896, 7971,22896,18967,22896, 18967,22807,22139,22904, 9,22904,20103,22905, 9,22911, 1369,22806, 903,22806, 9,22917, 587,22807, 5,22920,22829,22923,18967,22806, 20326,22927,21087,22927, 9,22926,20273,22927, 9,22934, 9,22927, 20273,22938, 9,22806,18967,22942,20763,22806,22819,22947, 587,22806, 22811,22951, 9,22951, 17,21605,19722,22956,19723,22957,22959,22961, 19723,22956,19722,22957,22965,22967,19396,22956,19396,22957,19397,22956, 22973,22975,19545,22956,20497,22956,20357,22956, 4133,22956,10099,22956, 3799,22956, 4143,22956, 9179,22956, 9669,22956,19475,22957,21315,22957, 19397,22957,22971,23001, 1369,22956, 1275,22956, 903,23007, 587,22957, 903,22957, 15,21605,20103,23014,18967,23015,20501,23019, 1369,23014, 4917,23023,17013,23023, 3755,23023, 1995,23023,18967,23014,20413,23033, 9,21605,19631,23036,19384,23036,19384,23037,22567,23043,19385,23036, 10697,23036, 4669,23036,11949,23036, 11,23037,23047,23055,22567,23055, 18967,23055,18967,23036, 10,23062, 10,23063, 11,23062,23067,23069, 11,23063,23065,23073, 11,23036,18967,23076, 7049,21605, 587,23081, 7051,23083, 7055,23083, 7059,23083,17219,21605, 903,23091, 4663,21605, 903,23095, 4745,21605, 955,23099, 9,23099, 4569,21605,17423,21605, 955,23107, 9,23107,14625,21605, 5997,21605, 7,23114, 5,23114, 6,23119,23117,23121, 6,23118, 6,23114, 5,23126, 7,23115, 23129,23131,23125,23131, 14,23114,23131,23137, 6,23115, 15,23114, 23141,23143,20482,21605,20762,23146,20773,23149,20762,23147,20815,23153, 20839,23147,21399,23147,19683,23147,20763,23147,20843,23163,23149,23163, 20763,23146,20839,23169,23153,23169,20186,21605,21036,23174,21049,23177, 21036,23175,21069,23181, 331,23175, 59,23175, 1325,23175, 265,23175, 20644,21605,20352,21605, 9660,21605, 8386,21605, 59,23199, 331,23199, 1325,23199, 265,23199,21243,21605,21829,23209,20957,21605,21807,23213, 21272,21605,21631,23217,20962,21605, 9,23221,21248,21605,21625,23225, 21549,21605,20501,23228,21105,21605,20501,23232,20843,21605,21758,23237, 21623,23237,21760,23237,21641,23237,20885,23237,21757,23246,20889,23247, 21757,23237,20885,23252, 9,23252,20103,23236, 9,23259, 9,23237, 21757,23262,20885,23236, 9,23267,21127,21605,21752,23271,21625,23271, 21754,23271,21639,23271,18967,23270,21087,23281,21183,23271,21751,23284, 21751,23271,21183,23288, 9,23288,20103,23270,21183,23295, 9,23295, 9,23271,21751,23300,21405,21605,21633,23305,21394,23305,21786,23305, 21381,23305,20273,23312,21785,23312,20326,23305,21087,23305,21695,23305, 21037,23305,21036,23304,23325,23327,21036,23305,21037,23304,23331,23333, 21788,23305,21785,23305,21381,23338, 9,23338, 9,23305,20273,23344, 21785,23344,20273,23305,21381,23350, 9,23350,21259,21605,21843,23357, 20885,21605,20763,23360, 5,23363,18967,23362, 6,23360,18967,23368, 18967,23360, 6,23372, 6,23373, 7,23360,23377,23379, 7,23361, 23365,23383, 4,23383,23363,23387,23371,23383,23375,23383,23367,23383, 21526,23360,23383,23397, 6,23361,21527,23360,23401,23403, 9,23361, 20843,23407,21791,23361,20413,23411,20413,23360,21791,23415,20843,23360, 9,23419,21183,21605,21315,23422,21795,23425,21795,23423,20103,23429, 20103,23422,21795,23433,20763,23422,21249,21605,21617,23439,21001,21605, 9,23443,21273,21605,21619,23447,21371,21605, 9,23451,21253,21605, 8,21604,22363,23457,22053,23457,21983,23457,23039,23457,21985,23457, 22077,23457,22075,23457,22465,23457,22507,23457,23053,23457,23051,23457, 20501,23457,23037,23457,19631,23483,11949,23483, 4669,23483,18967,23457, 10,21604,22870,23493,22869,23493,22867,23493,23041,23493,22583,23493, 21995,23493,22665,23493,21991,23493,19441,23493,22626,23493,21997,23493, 19656,23493,22908,23493,22902,23493,22419,23493,22421,23493,11970,23493, 4696,23493,21987,23493,23069,23493,21989,23493,23079,23493,22643,23493, 22933,23493,22945,23493,22693,23493,22904,23493, 9,23546,22896,23493, 18967,23550,22621,23493, 9,23554,19396,23493,22807,23558, 8647,23493, 22637,23493, 9,23565,23077,23493,18967,23569,22689,23493,18967,23573, 22927,23493, 9,23577,22943,23493,18967,23581,22807,23493,19396,23584, 19396,23585,18967,23584, 9,23590, 9,23584,18967,23594,18967,23585, 9,23598, 9,23585,18967,23602,19631,23493, 9,23606,18967,23493, 22896,23610,22807,23610, 9,23614, 9,23610,22807,23618, 9,23493, 11949,23622, 4669,23622,22621,23622,19631,23622,22904,23622,22807,23622, 18967,23634,18967,23622,22807,23638, 4669,23493, 9,23642,11949,23493, 9,23646, 16,21604,22979,23651,21935,23651,22239,23651,22389,23651, 22375,23651,22001,23651,21999,23651,22005,23651,22003,23651,22123,23651, 22129,23651,22983,23651,22981,23651,22987,23651,22985,23651,22989,23651, 22995,23651,22993,23651,22991,23651,22169,23651,22029,23651,22027,23651, 22175,23651,22031,23651,22189,23651,22195,23651,22033,23651, 7,23651, 3,23706, 3,23651, 7,23710, 586,23651,22957,23651,19545,23717, 20357,23717,20497,23717,10099,23717, 4133,23717, 3799,23717, 9669,23717, 9179,23717, 4143,23717,19559,23651,20713,23651,20361,23651, 9967,23651, 9673,23651, 4283,23651, 3807,23651, 8251,23651, 4279,23651, 14,21604, 23175,23755,23199,23755, 5,23755, 1,23760,22677,23763,23023,23763, 1,23755, 5,23768,22677,23771,23023,23771,16381,23755,14625,23755, 4569,23755,13325,23755, 8685,23755,19513,23755, 1369,23755, 17,23755, 20219,23755, 4063,23755,10273,23755,20697,23755, 4137,23755, 8401,23755, 9955,23755, 3863,23755,19631,21605, 11,23808, 5,23810, 6,23808, 5,23814, 5,23808, 6,23818, 6,23819, 7,23808,23823,23825, 7,23809,23817,23829,23821,23829,23813,23829, 14,23808,23829,23837, 6,23809, 15,23808,23841,23843, 9,23808,23457,23847, 9,23809, 19667,21605, 5,23852, 4,23852, 12,23852, 13,23853,23859,23861, 12,23853, 13,23852,23865,23867, 4,23853,23855,23871, 5,23853, 23857,23875, 8,21605,23646,23879,23642,23879,23606,23879,23851,23879, 22467,23879,22509,23879,19384,23879,19631,23879,23493,23894,23493,23879, 11949,23898, 4669,23898,19631,23898,11949,23879,23493,23906, 4669,23879, 23493,23910,18967,23879, 11,23914, 11,23915,23493,23919, 11,23879, 18967,23922, 14,21605,18967,23926,20501,23929, 17,23929,18967,23927, 20413,23935, 16,21605,22241,23939,22387,23939,22373,23939,22121,23939, 22127,23939,22167,23939,22173,23939,22187,23939,22193,23939,19545,23939, 10099,23939, 4133,23939, 3799,23939, 4143,23939, 9669,23939, 9179,23939, 20357,23939,20497,23939,19625,23939,21549,23939,21105,23939, 11,21604, 23053,23983,23051,23983,23039,23983,21985,23983,22085,23983, 5,23982, 6,23995,21983,23983,22077,23983,22075,23983,22081,23983,22083,23983, 22572,23983,23847,23983,22465,23983,22507,23983,22211,23983, 9,24017, 19396,23983,22567,23983, 9,24022, 8165,23983, 9,24027,23037,23983, 11949,24031, 4669,24031,19631,24031,19559,23983, 9,24039, 8251,23983, 9,24043, 3807,23983, 9,24047, 9875,23983, 9,24051,20501,23983, 9,24055, 9,23982, 8251,24059, 3807,24059,22211,24059,19559,24059, 20501,24059, 9875,24059, 8165,24059, 9,23983,22567,24074,18967,24074, 18967,23983,21183,24081,23997,24081, 375,24081, 7,24081,23995,24089, 9,24080, 9,21604,22869,24095,23894,24095,21997,24095,21365,24095, 21475,24095,21509,24095,21405,24094,22047,24095,22357,24095,23919,24095, 21995,24095,22583,24095,23906,24095,23910,24095,21127,24094,22319,24125, 20843,24094,22289,24129,22419,24095,22421,24095,21279,24095, 973,24094, 4745,24139,19559,24095,20361,24095,20713,24095, 9673,24095, 9967,24095, 4283,24095, 4279,24095, 8251,24095, 3807,24095, 33,24095, 7971,24161, 8165,24095, 25,24165, 9875,24095,20501,24095, 4745,24095,17423,24095, 21405,24095,20273,24177,21785,24177,19631,24095,23879,24182, 4669,24095, 23879,24186,11949,24095,23879,24190, 973,24095, 4805,24195,19687,24095, 23493,24199,23879,24095,19631,24202,11949,24202, 4669,24202,20413,24095, 11,24094, 8251,24213, 3807,24213,22211,24213,19559,24213,20501,24213, 9875,24213, 8165,24213,21127,24095,21751,24229,20843,24095,21757,24233, 11,24095,19687,24237,23610,24237,23493,24237,18967,24242, 7971,24237, 18967,24237,23493,24248,18967,24095, 10,24252,24213,24255, 10,24253, 24237,24259, 483,24253, 10,21605,23893,24265,24020,24265,22581,24265, 22669,24265,19455,24265,23917,24265,19333,24265,23073,24265,19393,24265, 23060,24265,24092,24265,23925,24265,24078,24265,23651,24265, 9755,24265, 9317,24265, 4321,24265, 3833,24265,10171,24265, 4295,24265,22149,24265, 18967,24307,24213,24265,18967,24311,24059,24265,18967,24315,21183,24265, 19396,24265,23983,24320,19559,24321, 922,24265, 1413,24265,19683,24265, 24074,24265,18967,24332,23055,24265,18967,24336,24080,24265, 9,24340, 20839,24265,21399,24265,19385,24265,23879,24349, 9,24349,23983,24265, 19396,24355,19396,24354,18967,24355, 9,24360, 9,24355,18967,24364, 18967,24354, 9,24368, 9,24354,18967,24372,18967,24264,19441,24377, 24213,24377,24059,24377,22149,24377,19656,24377,19631,24377, 9,24388, 23983,24377, 9,24393, 9,24377,19631,24396, 903,24265, 483,24400, 483,24265, 903,24404,18967,24265,23055,24408,24074,24408,19559,24409, 9,24415, 9,24408,23983,24418,19559,24419,23983,24408, 9,24424, 9,24265,24080,24428,18967,24428,19559,24433,23983,24432,23983,24428, 18967,24438,18967,24429,19631,24443, 17,21604,21963,24447,23958,24447, 23972,24447,23974,24447,23960,24447,23962,24447,21979,24447,21977,24447, 21967,24447,21965,24447,23964,24447,23966,24447,23968,24447,23970,24447, 21971,24447,21969,24447,21975,24447,21973,24447,22807,24447,19545,24447, 23939,24486,20357,24447,23939,24490,20497,24447,23939,24494, 9669,24447, 23939,24498, 9179,24447,23939,24502, 3799,24447,23939,24506, 4143,24447, 23939,24510,10099,24447,23939,24514, 4133,24447,23939,24518,23939,24447, 19545,24522,20357,24522,20497,24522,10099,24522, 4133,24522, 3799,24522, 9669,24522, 9179,24522, 4143,24522, 15,24446, 15,21604,23357,24545, 22713,24545,22423,24545, 8337,24545,20103,24545, 17,24544, 483,24545, 19,21605,22163,24561,18967,24560, 13,21605,24080,24567,22149,24567, 23983,24567,18967,24572,18967,24567,23983,24576, 113,21605,10385,24581, 23879,24583, 9,24583,11731,21605, 67,24589,23879,24591, 9,24591, 137,21605,12261,21605, 587,24599,10107,24601,11067,24601,12285,24601, 1346,21605, 1505,24609, 256,21605, 8495,24613,10107,24613, 1486,21605, 803,24619, 1504,21605,20029,24623,21103,24623,19781,24623, 973,21605, 2845,24631, 4812,24631, 955,24631, 4805,24636, 2971,24631, 4814,24631, 9,24631, 4805,24644, 4805,24631, 955,24648, 9,24648, 341,21605, 803,24655,17049,24655,20884,21605,21820,24661,21807,24661,20413,24664, 20413,24661,21807,24668,21182,21605,21195,24673,21836,24673,21829,24673, 20103,24678,20103,24673,21829,24682,20984,21605,20839,24687,20413,24689, 20413,24686,20839,24693,21258,21605,23755,24697,21749,24697,21574,21605, 9,24703,21404,21605,24109,24707,21803,24707,21849,24707,21621,24707, 21693,24707,21805,24707,21801,24707,21381,24721, 9,24721, 1141,21605, 17025,24727, 1447,21605,17025,24731, 253,21605,17049,24735, 1471,21605, 17049,24739,21018,21605, 5,24742,20839,24745, 5,24743,20885,24749, 21276,21605, 7,24753,20413,21605, 6,24756, 4,24759,18967,24760, 18967,24759, 4,24764, 4,24765,21314,24759,21570,24756,21571,24757, 24773,24775, 6,24757,21314,24778,21314,24779,20885,24757,24661,24785, 21571,24756,21570,24757,24789,24791,21315,24757,24783,24795,21381,24757, 20885,24756,21791,24801,19475,24756,20984,24756,20839,24807,21315,24756, 21747,24811,24781,24811,23457,24811, 5,24756,20762,24819,20762,24818, 24763,24819,24767,24819,20839,24819,21399,24819,24771,24819,19683,24819, 20763,24819,20843,24837,24823,24837,20763,24818,24821,24843,20839,24843, 5,24757,24769,24849,20885,24849,24661,24849,20763,24756, 5,24856, 20839,24859, 5,24857,20885,24863,20103,21605,21183,24867,21127,24869, 24673,24869, 15,24866,21183,24866,21795,24877, 15,24867,19687,24866, 9,24883,19625,24866,20843,24866, 9,24889,21549,24866,21127,24866, 21183,24895, 9,24895,21105,24866,20763,24866, 5,24903,21527,24866, 9,24867,19687,24909,20843,24909,21127,24909, 6,24866,21036,24917, 5,24917,18967,24920,18967,24917, 5,24924,21036,24916, 5,24916, 18967,24930,24881,24917,18967,24916, 5,24936, 7,24866,23755,24941, 1325,24941, 331,24941, 59,24941, 265,24941, 7,24867,23929,24953, 22205,24953,24919,24953,24923,24953,24927,24953,24929,24953,24933,24953, 24939,24953,24905,24953, 4,24953,24903,24973,22269,24953,22263,24953, 375,24953,21037,24953,24917,24983, 6,24867, 5,24986,24941,24989, 24901,24987,24893,24987,24887,24987,21037,24866,24987,24999, 7,24999, 20273,21605,21258,25004,21259,25005,25007,25009,21183,25005,21259,25004, 21258,25005,25015,25017, 375,25005, 6,25004, 7,25004, 7,25005, 25023,25027,21315,25027, 6,25005,25025,25033,20501,21605, 7,25036, 4,25039, 4,25038,20885,25037, 7,25037,18967,25047, 5,25049, 5,25048, 5,25047,18967,25054, 5,25046,21036,25047,21037,25037, 22269,25063,21105,25063, 16,25036, 10,25037, 803,25037, 903,25037, 9,25037, 17,25036,19625,25036,21105,25036,21549,25036,21037,25036, 21829,25087,25059,25087,21127,25087,24095,25087,25071,25087, 11,25037, 4,25036, 7,25100,25051,25101, 5,25036,25041,25107,18967,25106, 25099,25111, 5,25037,25103,25115,25043,25115,25087,25115, 7,25114, 25087,25123,25069,25115, 4,25037,25111,25129,25057,25129,25053,25129, 25061,25129,25079,25129, 9165,21605, 9168,25140, 9169,25141,25143,25145, 9169,25140, 9168,25141,25149,25151, 8337,21605, 15,25155, 6,25155, 5,25158, 7,25155, 375,25163, 6,25154,25157,25167, 7,25154, 25161,25171,23755,25171, 59,25171, 331,25171, 1325,25171, 265,25171, 9617,21605, 9630,25184, 9631,25185,25187,25189, 9629,25185, 9631,25184, 9630,25185,25195,25197, 375,25185, 6,25185, 7,25185, 6,25184, 25205,25207, 7,25184,25203,25211, 9875,21605, 7,25214, 4,25216, 4,25217, 9893,25215, 16,25214, 803,25215, 9,25215, 17,25214, 903,25215, 4,25215,25231,25235, 5,25215,25219,25239,25225,25239, 4,25214, 7,25244,25239,25247, 5,25214,25221,25251, 843,21605, 9,25255, 413,21605, 7,25259, 375,25259, 1530,21605, 9,25265, 1216,21605, 7,25269,21497,21605, 7,25273,21277,21605, 7,25276, 21183,25279, 7,25277,21105,25283,21019,21605, 5,25286,20885,25289, 5,25287,20839,25293, 265,21605, 7,25297, 7971,25299, 587,21605, 11,25302, 9,25305, 9,25303, 11,25309, 5,25303,20501,25313, 9875,25313, 903,21605, 9,25319, 11,25321, 11,25318, 9,25325, 7,25319, 1141,25329, 33,25329, 1447,25329, 1011,25318, 7,25337, 1275,21605, 9,25341, 1369,25343, 17,25340, 903,25347, 5,25340, 1505,25351, 5,25341, 253,25355, 53,25355, 1471,25355, 1369,25340, 9,25363, 1011,21605, 7,25367, 959,25369, 47,25369, 759,25369, 903,25366, 7,25377, 1369,21605, 9929,25380, 9927,25383,11759,25380, 7971,25387,17053,25381,10081,25391, 7,25380, 4,25394, 5,25395, 7,25398,25381,25401, 0,25398,25403,25405, 4,25395, 0,25395, 5,25410, 1,25380, 5,25415, 1,25416,25381,25419, 6,25416, 25421,25423, 6,25415, 5,25426, 14,25415, 10,25380, 5,25433, 0,25434, 0,25433, 5,25438, 16,25380,10081,25380, 7971,25445, 17053,25445, 7971,25381,11759,25451,10081,25451, 17,25380, 11,25380, 11,25381, 1965,25461, 3195,25461,25437,25461,25441,25461, 5197,25461, 25405,25461,25413,25461, 1,25461, 4579,25461,15899,25461, 15,25380, 23763,25483,23771,25483, 3755,25483, 1995,25483, 0,25483,25461,25493, 25477,25483, 4917,25483,17013,25483, 4,25380, 7,25502,20029,25503, 19781,25503,21103,25503, 5,25380,25409,25513, 803,25513, 4,25381, 20033,25519,25457,25519, 5,25381,25397,25525,25505,25525,25443,25525, 10219,25525, 959,25525, 47,25525, 759,25525, 1275,25380, 9,25541, 241,21605, 9,25545, 483,25545, 7,25544, 8495,25551,10107,25551, 17571,21605, 7,25557, 4,25558, 4,25559, 16,25557, 17,25557, 4,25556,25567,25569, 5,25556,25561,25573,25565,25573, 4,25557, 7,25578,25573,25581, 5,25557,25563,25585,17371,21605,16711,25589, 7,25589,14315,21605, 5,25594, 6,25596, 6,25597, 14,25594, 15,25594, 6,25594, 5,25606, 7,25594,25601,25611, 6,25595, 25605,25615, 7,25595,25609,25619,25599,25619,25603,25619,15705,21605, 767,25627, 483,25629, 4,25627, 483,25633,21527,21605,20103,25636, 5,25637, 17,25641, 5,25636, 9,25645,21315,21605,21183,25648, 21795,25651,21183,25649,24673,25655,21747,25649,20413,25659,23457,25649, 20413,25663,20413,25648,23457,25667,21747,25667,21037,21605,21829,25673, 20501,25675,21127,25673,20501,25679,21105,25673, 11,25673,20501,25685, 15,25673,20501,25672,24095,25691,21829,25691,21127,25691,20187,25672, 24095,25673,20501,25701, 6,25673, 7,25673, 6,25672,25707,25709, 20103,25709, 7,25672,21749,25715,23755,25715,25705,25715,20103,25672, 7,25723,20763,21605,20482,25726,20839,25729,20483,25726,21183,25726, 4,25727,23147,25737,24819,25737, 5,25727,23383,25743,20956,25743, 20773,25743,24953,25743,20885,25743,20413,25752,20413,25743,20885,25756, 4,25726,21605,25761, 7,25763,25743,25765,24849,25761,20413,25761, 5,25726,20839,25773,20413,25775,20413,25772,20839,25779,20413,25726, 5,25782,20839,25785, 5,25783,20885,25789, 5,21604,25275,25793, 25003,25793,25725,25793,24755,25793,21049,25793,21242,25793,20773,25793, 20956,25793,25699,25793,22725,25793,22391,25793,24682,25793,23209,25793, 25712,25793,25733,25793,22711,25793,22395,25793,24668,25793,23213,25793, 25770,25793,25083,25793,23235,25793,22017,25793,25085,25793,23231,25793, 22025,25793,25087,25793,25691,25793,22357,25793,22047,25793,23455,25793, 15567,25793,12971,25793,13355,25793,13541,25793,22869,25793,22635,25793, 23021,25793,23894,25793,23919,25793,21997,25793,21995,25793,22583,25793, 23906,25793,23910,25793,22419,25793,22421,25793,23034,25793,19656,25793, 19441,25793,11970,25793, 4696,25793,22674,25793,22069,25793,25081,25793, 22011,25793, 9357,25793,25205,25793,25027,25793, 9356,25793,25171,25793, 24941,25793,23199,25793,23175,25793,20606,25793,25593,25793,19396,25793, 11131,25793,21059,25793,23018,25793,20501,25933,20057,25793,22633,25793, 20501,25939,21405,25793, 357,25793, 367,25793, 471,25793, 1249,25793, 628,25793, 4569,25793,14625,25793, 4545,25793,13325,25793, 8337,25961, 4549,25793,23229,25793,20501,25967,23233,25793,20501,25971,25706,25793, 20186,25793, 8386,25793, 9083,25793, 9484,25793, 9984,25793,20187,25793, 8387,25793,19513,25793, 8401,25793,20219,25793, 4137,25793,10273,25793, 4063,25793, 3863,25793,20697,25793, 9955,25793,20353,25793,25709,25793, 20103,26010,25715,25793,24673,25793,20103,26016,24697,25793,21183,25793, 20103,26022,21259,25793, 4745,25793,17423,25793, 9082,25793,22673,25793, 20413,26034,23033,25793,20413,26038,25551,25793,24613,25793,22249,25793, 20326,25793,21087,25793, 9704,25793,23879,25793,19631,26054,11949,26054, 4669,26054,11949,25793,23879,26062, 9,26062, 4669,25793,23879,26068, 9,26068,20805,25793,23015,25793,18967,26076,20501,26079,18967,26077, 20413,26083,19631,25793,23879,26086, 9,26086, 9377,25793, 11,26092, 341,25793, 241,26097, 8165,25793, 256,25793, 257,25793, 11,25793, 9195,26106,20501,26106, 587,26106, 9377,26106, 9875,26106,20763,26106, 20804,25793,10219,25793, 587,26123, 53,25793,20501,25793, 10,26128, 10,26129, 11,26128,26133,26135, 11,26129,26131,26139,20413,25793, 20885,26142,24661,26142,25761,26142,22673,26142,23033,26142,20762,25793, 25761,25793,20413,26156,24661,25793,20413,26160,20885,25793,20413,26164, 17,25793,20762,26168,20762,26169,20763,26169,26171,26175,20763,26168, 26173,26179, 9,25793,11949,26182, 4669,26182,19631,26182,18967,26182, 20273,26182, 9617,26182,20763,25793, 11,26196,25707,25793, 9875,25793, 10,26202, 10,26203, 11,26202,26207,26209, 11,26203,26205,26213, 253,25793, 6,25793,25273,26219,24753,26219,24999,26219,24953,26219, 25005,26219,25723,26219,25707,26219,25185,26219,25163,26219,25589,26219, 24081,26219, 4713,26219,16363,26219, 9195,26219, 4863,26219,13119,26219, 8757,26219, 4213,26219,23493,26219, 8109,26219, 3933,26219, 4147,26219, 9335,26219,20103,26219, 8337,26219,20273,26219, 8997,26219,25673,26219, 241,26219,18967,26219, 11,26279, 11,26219, 587,26219, 8387,26219, 14653,26219,20187,26219, 7,25793, 8717,26293, 3785,26293,25673,26292, 23755,26293,10351,26293, 4311,26293, 4329,26293,10055,26293,20103,26292, 8337,26292, 8997,26292, 15,26293,18967,26317,18967,26292, 241,26292, 9195,25793, 11,26324, 1471,25793, 6,25792,23175,26331,25977,26331, 24941,26331,26311,26331,26299,26331,25975,26331,25715,26331,24697,26331, 26315,26331,23199,26331,25171,26331,25979,26331,26033,26331,26313,26331, 16381,26331,26323,26331,26103,26331,13325,26331, 8685,26331,26155,26331, 26321,26331,26293,26331,20103,26375,25673,26375, 8997,26375, 8337,26375, 241,26375,18967,26375, 17,26331, 1369,26331, 4569,26331,19513,26331, 4063,26331,10273,26331, 3863,26331,20697,26331, 9955,26331, 4137,26331, 20219,26331, 8401,26331,14625,26331, 7,25792,25987,26415,26266,26415, 26201,26415,26274,26415,26272,26415,25989,26415,25981,26415,26268,26415, 21604,26415,18967,26433,26219,26435, 8997,26415,26219,26438,26105,26415, 26276,26415, 8647,26415,19396,26415,26197,26415,26278,26415,26219,26415, 20103,26454,25673,26454, 8997,26454, 8337,26454, 241,26454,18967,26454, 8337,26415,26219,26468,20103,26415,26219,26472, 9,26415,18967,26476, 241,26415, 1,26481,26219,26483,26219,26480,25673,26415,26219,26488, 18967,26415, 9,26492,26219,26492, 587,25793, 11,26498, 1369,25793, 25673,25793,20501,26505, 6,26504, 7,26504,26331,26511, 6,26505, 26511,26515, 7,26505,26509,26519,26219,26519,18967,25793, 9,26524, 23015,26524,20501,26529, 483,26525, 6,26524, 7,26524,26331,26537, 7,26525,26219,26541, 6,26525, 241,25793, 1,26547, 7,26549, 26331,26551, 7,26548,26219,26555, 7,26547, 1,26558,26219,26561, 26219,26559, 7,26546,26331,26567,20273,25793, 9,26570,14315,25793, 8997,25793, 7,26576,26331,26579, 7,26577,26219,26583, 9617,25793, 9,26586, 8337,25793, 7,26590,26331,26593, 483,26591, 9,26591, 7,26591,26219,26601,20103,25793,21183,26604,24673,26604,25709,26604, 7,26604,26331,26613, 483,26605, 9,26605, 7,26605,26219,26621, 4,21604,21955,26625,24877,26625,23433,26625,21947,26625,21951,26625, 24801,26625,23415,26625,21943,26625,22282,26625,22251,26625,22266,26625, 22253,26625,24811,26625,25667,26625,22363,26625,22053,26625,21116,26625, 21560,26625,25735,26625,23437,26625,22699,26625,21253,26625,23930,26625, 22206,26625,24805,26625,23937,26625,22587,26625,23039,26625,23053,26625, 23051,26625,21961,26625,21981,26625,20465,26625,20576,26625,21985,26625, 21983,26625,22077,26625,22075,26625, 9573,26625, 9575,26625,23847,26625, 22465,26625,22507,26625, 3,26625, 7,26712, 9605,26625, 586,26625, 9599,26625,19474,26625,20413,26723,20186,26625,20805,26625,22423,26625, 22713,26625,22205,26625,20501,26734,19625,26625,20501,26738,19687,26625, 23929,26625,20501,26744,23934,26625,20413,26749,22585,26625,20413,26753, 8386,26625,23927,26625,18967,26759,20501,26761,18967,26758,20413,26765, 23037,26625,19631,26769,11949,26769, 4669,26769, 1418,26625, 9565,26777, 669,26625, 9565,26781,22263,26625,20501,26784,22269,26625,20501,26788, 21549,26625,20501,26792,20843,26625,21105,26625,20501,26798,21127,26625, 23423,26625,20103,26805,23357,26625, 7971,26625, 1170,26625,25203,26813, 20501,26625,22269,26816,22263,26816,21105,26816,21549,26816,22205,26816, 23929,26816,19625,26816,20762,26625,26219,26833,23361,26625,20413,26837, 11,26625, 1,26841,18967,26841, 15,26625,18967,26846,20413,26849, 18967,26847,20501,26853, 1369,26846, 9565,26857, 7,26625, 4,26861, 3,26860, 4,26860,21605,26867,20103,26860, 8337,26860,18967,26860, 26219,26875, 1011,26860,25203,26879, 6,26625,21604,26882,20763,26883, 6,26624,24811,26889,22053,26889,22363,26889,25667,26889,20501,26889, 25649,26889,20413,26901,18967,26889, 7,26624,24265,26907,19559,26907, 9673,26907, 8251,26907, 3807,26907, 4283,26907,20361,26907, 4279,26907, 20713,26907, 9967,26907, 483,26625, 1369,26625, 15,26930, 9565,26933, 25649,26625,20413,26937,18967,26625, 15,26940,20413,26943,23927,26940, 20413,26947, 6,26940,21604,26950, 7,26940,26219,26955, 7,26941, 26953,26959,26885,26959,26331,26959,23755,26959, 6,26941, 1011,26625, 7,26971,25207,26973,23197,26973, 7,26970,25203,26979,20103,26625, 7,26982, 8337,26625, 7,26986, 9565,26625, 9617,26625, 6,26992, 7,26992, 6,26993,26997,26999, 7,26993,26995,27003,20273,26625, 6,27006, 7,27006, 6,27007,27011,27013, 7,27007,27009,27017, 7,21604,25987,27021,26266,27021,22732,27021,22733,27021,25087,27021, 25691,27021,22357,27021,22047,27021,26027,27021,25989,27021,26268,27021, 20819,27021,20152,27021, 8374,27021, 8389,27021,20201,27021,20952,27021, 1,27021, 4,27056, 4,27057, 3,27021, 4,27062, 902,27021, 19559,27021,20361,27021, 9673,27021,20713,27021, 9967,27021, 4283,27021, 4279,27021, 8251,27021, 3807,27021,26100,27021,26106,27021,26128,27021, 26202,27021, 8647,27021,20326,27021,25239,27021,25115,27021, 8800,27021, 21087,27021, 357,27021, 367,27021, 471,27021, 1249,27021, 8086,27021, 19687,27021, 9704,27021,25742,27021,20885,27021, 483,27122, 1141,27021, 375,27021,20103,27128, 8337,27128,25673,27021,20501,27135,26219,27021, 20103,27138, 8337,27138, 11,27139, 17,27139, 1447,27021,21127,27021, 20843,27021, 8165,27021,25793,27154, 265,27155, 33,27021, 567,27021, 22729,27021,21315,27164, 11,27021,25793,27169, 8495,27169,25793,27168, 8495,27168,18967,27169,21037,27169,21497,27021,21277,27021,21276,27021, 21496,27021,20273,27021, 9,27190,21315,27190,20103,27021,26219,27196, 375,27196,21037,27196,21314,27021,22729,27205,20273,27205,21036,27021, 25129,27211,20103,27211,21183,27021, 9,27021,20273,27218, 9617,27218, 21315,27021,22729,27224,20273,27224,21037,27021,20103,27230,25743,27021, 25,27021, 7971,27236, 7971,27021, 25,27240, 9617,27021, 9,27244, 8337,27021,26219,27248, 375,27248, 4,27021,25037,27255,25215,27255, 3,27254, 1,27254,25727,27255, 483,27255,20691,27255, 9923,27255, 18967,27255,20103,27273,18967,27254,22729,27277,20273,27277, 5,27021, 27061,27283, 1,27283,25727,27282,18967,27283,22729,27291,20273,27291, 17,27283,18967,27297,18967,27282,25129,27301,20103,27301,25793,27021, 8165,27306, 11,27306,20501,27306, 9875,27306, 9731,27021, 8495,27021, 11,27318, 4,27020, 1,27323,27283,27324,27286,27323,27289,27323, 27121,27323,24265,27323,27225,27323,27290,27323,27211,27323,27301,27323, 27283,27323, 1,27344,25727,27345,18967,27344,18967,27345,19559,27323, 18967,27323,27283,27356, 4283,27323, 9673,27323, 8251,27323, 3807,27323, 20361,27323, 9967,27323,20713,27323, 4279,27323, 5,27020,27059,27377, 27263,27377,27235,27377,27264,27377, 8647,27377,19396,27377,27231,27377, 27272,27377,27205,27377,27277,27377,27255,27377, 1,27399,25727,27398, 18967,27398,18967,27399,26219,27377, 9,27377,18967,27410,25727,27377, 27255,27414,18967,27377, 9,27418,27255,27418, 1011,27021,25727,27021, 5,27426,27323,27429, 5,27427,27255,27433,18967,27021, 7,27437, 21605,27439, 4,27441, 4,27440, 4,27439,21605,27446, 4,27438, 16,27437, 113,27437,11731,27437, 17,27437, 4,27436,22729,27461, 21605,27460,27459,27465,27377,27461,20273,27461, 5,27436,25129,27473, 27443,27473,27323,27473,20103,27473, 5,27437,25101,27483,23193,27483, 7,27483,21605,27489,27461,27491,27449,27483,27445,27483,27461,27483, 27255,27483,21315,27483, 4,27437, 7,27504,27473,27505,27283,27505, 21037,27505, 483,27021,20885,27514,20501,27021, 241,27519,25793,27518, 9875,27021, 241,27525,25793,27524,20413,27021, 6,21604,24811,27533, 25667,27533,22363,27533,22053,27533, 1,27533, 5,27542,22605,27545, 22677,27545,23023,27545,25483,27545,20644,27533,21359,27533,25793,27557, 12345,27533, 5,27561, 4,27560,27563,27565, 4,27561, 5,27560, 27569,27571, 5123,27533, 5,27575, 4,27574,27577,27579, 4,27575, 5,27574,27583,27585,19667,27533, 5,27589, 4,27588,27591,27593, 4,27589, 5,27588,27597,27599, 341,27533,21052,27533,25793,27605, 25649,27533,20413,27609,25673,27533,21183,27613,26861,27533, 9,27617, 26293,27533, 9,27621,17219,27533, 903,27625, 4663,27533, 903,27629, 23195,27533,21315,27633,10219,27533, 903,27637, 53,27533,25025,27533, 21315,27643,20103,27533, 9,27647,21314,27533,24795,27651,26142,27651, 20413,27651,25793,27656,25793,27651,20413,27660,21036,27533,25129,27665, 21259,27533,26625,27669, 17,27533,21315,27673,21037,27533,25793,27677, 20501,27679,20501,27676,25793,27683, 8337,27533, 9,27687, 1471,27533, 5,27533, 6,27693, 587,27695,21605,27697, 1,27692,22605,27701, 22677,27701,23023,27701,25483,27701,27699,27701, 6,27692,25380,27713, 27701,27715, 1369,27713,21605,27718,27701,27721,21605,27713, 1369,27724, 27701,27727, 9,27693,18967,27692,25129,27733, 9935,27693,20645,27693, 4,27533,20501,27740,26524,27741,20501,27745,25793,27741,18967,27748, 20501,27751,18967,27749,20413,27755,18967,27741,25793,27758,20501,27761, 20501,27759,25793,27765,18967,27740,26142,27769,20413,27769,25793,27772, 25793,27769,20413,27776,26940,27533,26969,27781, 253,27533, 4,27532, 24811,27787,22053,27787,22363,27787,25667,27787,20501,27787,25649,27787, 20413,27799,18967,27787, 5,27532,24941,27805,23175,27805,25715,27805, 24697,27805,25171,27805,23199,27805,26959,27805,16381,27805,13325,27805, 8685,27805,26293,27805, 17,27805, 1369,27805, 4569,27805,19513,27805, 4063,27805,10273,27805, 4137,27805,20219,27805, 8401,27805, 3863,27805, 14625,27805,20697,27805, 9955,27805, 241,27533,18967,27533,20486,27857, 20487,27857,20413,27857, 4,27862, 4,27863, 580,27857, 483,27857, 4,27870, 4,27871, 581,27857, 4,27856,27861,27879,26142,27879, 27877,27879,20413,27879,25793,27886,25793,27879,20413,27890, 5,27856, 25129,27895,27859,27895,27865,27895,27869,27895,27873,27895, 5,27857, 25101,27907,27555,27907,23193,27907,27743,27907,27886,27907,27867,27907, 27875,27907,20413,27907,27879,27922,27879,27907,20413,27926, 4,27857, 20413,27930,27895,27933, 483,27930,27895,27937,27895,27931,20413,27941, 1369,27533, 5,27945,20501,27533,21037,27949, 4,27948,27907,27953, 5,27948,18967,27956,21037,27948,25793,27961, 4,27949,27959,27965, 27665,27965,27733,27965,27895,27965, 5,27949,27961,27975, 7,21605, 1,27979, 2,27981, 5,27983, 5,27982, 1010,27981, 5,27981, 2,27990, 3,27978, 9,27995, 4311,27979,10351,27979, 4329,27979, 3785,27979,10055,27979, 8717,27979,26283,27979,26388,27979,23790,27979, 27828,27979,22143,27979,22149,27979,24213,27979,24059,27979, 331,27979, 8337,28027,20103,28027,21036,27978,21049,28033,21242,28033,21183,28033, 20103,28038,20103,28033,21183,28042,26331,27979,20103,28047, 8337,28047, 17,28046,21277,27978,21183,28055,27693,27979,18967,28059,25793,27979, 21127,28063,20843,28063,19687,28063, 8337,28063,20103,28063, 7971,28063, 241,28063, 8495,27979, 241,28079, 8337,27978,26331,28083,27805,28083, 1325,28083, 331,28083, 59,28083,23755,28083,25793,28083, 265,28083, 21037,27979,27665,28101,28033,28101, 11,28101,21315,27979, 1325,27979, 8337,28111,20103,28111, 59,27979, 8337,28117,20103,28117,10291,27979, 483,28123,20273,27978,27533,28127,21315,28129,20103,27978,26331,28133, 27805,28133,23755,28133, 331,28133, 1325,28133, 59,28133,25793,28133, 265,28133,21105,27979, 11,27979,20103,28153, 8337,28153, 17,27979, 26331,28158, 8337,28159,20103,28159,27805,28158,23755,28158,27731,27979, 27692,27979, 9,28173,23755,27979,20103,28177, 8337,28177, 17,28176, 23983,27979, 9,28185, 15,27979, 3,28189,20273,28189, 9617,28189, 27805,27979,20103,28197, 8337,28197, 17,28196, 241,27978,25793,28205, 8495,28205,10107,28205, 265,27979,20103,28213, 8337,28213, 4,27978, 27985,28219,21105,28219,21549,28219,19625,28219,28173,28219,18967,28229, 5,27978,19397,28233,28060,28233,18966,28232,18966,28233, 9,28241, 27323,28233,23651,28233,26907,28233, 9755,28233, 9317,28233, 4321,28233, 3833,28233,10171,28233, 4295,28233,28101,28233,21183,28233, 1413,28233, 922,28233,27856,28233,28059,28233,18967,28272,19396,28233,28239,28277, 19683,28233,18967,28232,28235,28283,28242,28283,28241,28283, 9,28288, 9,28283,28241,28292,27533,28233,18967,28296, 9,28233,18967,28300, 28239,28303,18967,28301,28241,28307,21399,28233,20839,28233, 483,28233, 903,28314, 903,28233, 483,28318,18967,28233,28059,28322,28239,28323, 9,28327,27533,28322, 9,28322,28239,28333, 4,27979,27987,28337, 27993,28337,28270,28337,28330,28337,28298,28337,27989,28337, 586,28337, 3,28337, 7,28352, 7,28337, 3,28356,27856,28337,28233,28360, 21575,28337,28296,28337,18967,28366,27533,28337,28322,28370,18967,28370, 28233,28374,28233,28370,18967,28378,28322,28337,27533,28382,18967,28337, 28296,28386,27533,28386,28233,28390,28233,28386,27533,28394,28233,28337, 27856,28398,27533,28398,18967,28402,18967,28398,27533,28406, 5,27979, 27255,28411, 9287,28411,20885,28411,27533,28410,28219,28419,18967,28421, 9,28419, 241,28411, 483,28427,28219,28411,27856,28431,27533,28431, 18967,28434,18967,28431,27533,28438,18967,28410,28219,28443, 17,28443, 21036,27979,21069,28449,21267,28449,21305,28449,28219,28449,21259,28449, 20103,28459, 17,28449,21037,27978,26331,28465,21749,28465,27805,28465, 23755,28465,28449,28465,25793,28465,10001,27979, 9,28479,27533,27979, 21496,28483,21277,28483,20885,28483,27931,28483, 9,28483, 9731,28483, 21037,28482,21037,28483,21315,28483,20273,28500,21036,28482,28499,28505, 21036,28483,28497,28509,20273,28483,21315,28512, 4,28483, 5,28483, 28386,28519,28337,28519,18967,28522,18967,28519,28337,28526, 17,28519, 4,28482,28519,28533, 5,28482,28517,28537,28219,28537,18967,28541, 9,28537, 1275,27979,20031,28547,20885,28547, 5,28547,18967,27979, 20103,28555, 5,28555,28337,28559, 9,28559, 5,28554,28219,28565, 17,28565,21527,27979,18967,27978,28519,28573, 7,28573, 4,28576, 4,28577,28553,28573,21605,28573, 5,28584,28581,28587, 5,28585, 28579,28591, 16,28573,28591,28595, 11,28573,20273,28573, 567,28573, 5,28572, 4,28573, 7,28606,28591,28609,28483,28607,28547,28607, 483,28607, 5,28573,21605,28618,28581,28621,20762,21605,20803,28625, 7,28625, 4,28628,25743,28631, 4,28629,24687,28635,25773,28635, 21035,28625, 16,28625,25743,28643,20999,28625,20985,28625, 483,28649, 11,28625,20273,28625, 567,28625, 4,28624,20985,28659, 5,28624, 20956,28663,20773,28663,20885,28663,20413,28668,20413,28663,20885,28672, 20482,28625,20839,28677, 4,28625, 7,28680,25743,28683,20843,28681, 483,28681, 5,28625,21605,28690,28635,28693,20839,28691,20413,28697, 20413,28690,20839,28701,20413,28625, 5,28705,20885,28707, 5,28704, 20839,28711, 5,21605,21183,28715,18967,28716,24673,28719,21194,28715, 24673,28723,28573,28714,28581,28727,20620,28714,20621,28714, 9994,28714, 9995,28714, 1,28715, 1,28714,26781,28741, 668,28741,26625,28745, 26777,28741, 1419,28741,26625,28751,26857,28741,26933,28741, 2,28741, 9,28741, 587,28760,26625,28763, 587,28741, 9,28766,26625,28769, 21018,28714,20839,28773,19396,28715,22579,28777,21611,28777,19683,28715, 20413,28783,23490,28715,20413,28787,21526,28714,26816,28791,24953,28791, 17,28791,20501,28791,26625,28798,26625,28791,20501,28802,20762,28714, 20773,28807,20956,28807,20885,28807,20413,28812,20413,28807,20885,28816, 27787,28715,18967,28821,20501,28823,18967,28820,20413,28827,27802,28715, 20413,28831,21019,28714,20885,28835,27856,28715,20413,28839,27931,28715, 20413,28843,26904,28715,20413,28847,26861,28715,18967,28851,20823,28715, 20645,28715, 9935,28715,21362,28715,21376,28715,27533,28715,18967,28865, 20501,28867,18967,28864,20413,28871, 9994,28715,28737,28875,20822,28715, 28807,28879,20763,28715,28835,28883,28816,28883,20866,28883,21021,28883, 20413,28883,28807,28892,20843,28892,28807,28883,20413,28898, 9,28899, 20843,28883,20413,28904, 9,28882,28807,28909, 803,28715, 11,28913, 27979,28715,18967,28917,20621,28715,28731,28921,20413,28714,21399,28925, 20839,28925,25737,28925,19683,28925,20763,28925,20843,28935,28807,28935, 20763,28924,20839,28941,25737,28715,20413,28945,20839,28715,20413,28949, 20620,28715,28733,28953,21399,28715,20413,28957, 483,28715,21315,28960, 26860,28715,28337,28715, 11,28967,23457,28715,18967,28970,20413,28973, 18967,28971,20501,28977, 9,28715,21315,28980,20763,28981,20763,28980, 28807,28987, 17,28715,11949,28991, 4669,28991,19631,28991,18967,28991, 20273,28991, 9617,28991, 9995,28715,28735,29005, 1275,28714, 1505,29009, 26889,28715,18967,29012,20413,29015,18967,29013,20501,29019, 1369,28714, 803,29023, 587,28715, 1505,28715, 6,28714,26940,29031,20413,29033, 28965,29031,18967,29037,18967,29030,26816,29041,24953,29041, 17,29041, 20501,29041,26625,29048,26625,29041,20501,29052,26625,29031,18967,29056, 20413,29059,18967,29057,20501,29063,18967,29031,20413,29067,26625,29069, 26625,29066,20413,29073, 7,28714,19397,29077, 0,29077, 2,29080, 28991,29083, 2,29077, 0,29087, 0,29086,28991,29091,28999,29077, 1,29076,29091,29097,29083,29097,29081,29097, 2,29103, 1,29077, 29089,29107, 2,29107,28852,29077, 0,29076, 2,29115,29107,29116, 29110,29115,29107,29115, 2,29122,18966,29076,18966,29077,29097,29129, 28991,29129, 9,29129,27323,29077,23651,29077,26907,29077, 9755,29077, 9317,29077, 4321,29077, 3833,29077,10171,29077, 4295,29077,21183,29077, 1413,29077, 922,29077,26940,29077,28851,29077,18967,29162,19396,29077, 29127,29167,19683,29077,18967,29076,29079,29173,29134,29173,29129,29173, 9,29178, 9,29173,29129,29182,26625,29077,18967,29186,21399,29077, 9,29077,18967,29192,29127,29195,18967,29193,29129,29199,20839,29077, 483,29077, 903,29204, 903,29077, 483,29208,18967,29077,29115,29213, 28851,29212,29127,29213, 9,29219,26625,29212, 9,29212,29127,29225, 6,28715,29083,29229,29097,29230,29091,29229,29097,29234,29098,29229, 29100,29229,29105,29229,29109,29229,29119,29229,29121,29229,29125,29229, 29111,29229,29115,29253,24907,29229,25639,29229,22369,29229,28600,29229, 28557,29229,28654,29229,22057,29229,29178,29229,29160,29229,19706,29229, 10737,29229,10475,29229,10979,29229,19597,29229,12137,29229,29219,29229, 29215,29229,29130,29229,29222,29229,29129,29229,29173,29294,29097,29294, 29188,29229,29097,29229,29091,29302,29083,29302,29129,29302, 1,29229, 5,29310, 5,29229, 1,29314,29173,29229,29129,29318,19687,29229, 19631,29322,26940,29229,29077,29326,10697,29229, 8165,29331,19631,29229, 19687,29334,21575,29229,20273,29229,28573,29340,28625,29340,29186,29229, 18967,29346,19384,29229,19559,29351,28625,29229,20273,29354,28573,29229, 20273,29358, 11,29229,18967,29362,19559,29365,18967,29363,19631,29369, 587,29229,21605,29373,29313,29375,29317,29375,26625,29229,29212,29380, 18967,29380,29077,29384,29077,29380,18967,29388,29212,29229,29127,29393, 29115,29393,26625,29392,18967,29229,29186,29400,29077,29401,29173,29405, 29097,29405,26625,29400,29077,29410, 11,29401,19687,29415, 11,29400, 19559,29419,29077,29400,29127,29423,26625,29422,29115,29423,29077,29229, 26940,29430,26625,29430,18967,29434,18967,29430,29127,29439,26625,29438, 29115,29439,18967,29431,29129,29447, 7,28715,28791,29451,29041,29451, 19625,29451,21549,29451,21105,29451,26625,29450,29031,29463,18967,29465, 1275,29451, 903,29469,29031,29451,26940,29473,26625,29473,18967,29476, 18967,29473,26625,29480,20763,28714,28635,29485,28855,29485,20839,29485, 20413,29491,20413,29484,20839,29495, 9,29485,20762,28715,28941,29501, 29495,29501,28773,29501,20815,29501,20993,29501,21027,29501,28985,29501, 29498,29501,29485,29501,20413,29519, 9,29518,20985,29501,20413,29525, 9,29501,29485,29528,21527,28714,29229,29533, 9,29533,26940,28715, 20413,29539, 9731,28715, 7,29543,26625,28715,20762,29547, 6,29547, 7,29547,29400,29553,29229,29553,18967,29556,18967,29552,18967,29553, 29229,29562, 6,29546,29553,29567, 7,29546,29551,29571,29031,29571, 18967,29575,18967,29546,20413,29579,18967,29547,20501,29583, 6,29582, 7,29582, 6,29583,29589,29591, 7,29583,29587,29595, 903,28715, 7,29599,18967,28715,21183,29602,24673,29605,21183,29603,21795,29609, 23457,29602,20413,29613,27787,29602,20413,29617,27533,29602,20413,29621, 20413,29603,27787,29625,26889,29625,26625,29625,27533,29625,23457,29625, 26889,29602,20413,29637,26625,29602,20413,29641,21315,28715,21183,29645, 24673,29645,25709,29645, 7,29645, 483,29644, 9,29644,18967,28714, 27965,29659,27948,29659,26816,29659,26898,29659,27796,29659,24953,29659, 20119,29659,25129,29659,29653,29659,26887,29659,23480,29659,25099,29659, 21605,29659, 6,29684,29645,29687,29451,29659,28625,29691,28573,29691, 20187,29659,28625,29659,19683,29659,20839,29659,21399,29659,28573,29659, 27787,29659,20501,29708,20501,29659,27787,29712,26889,29712,26625,29712, 27533,29712,23457,29712,27533,29659,20501,29724, 17,29659, 6,29658, 26816,29731,24953,29731,29451,29731, 17,29731,20501,29731,26625,29740, 26625,29731,20501,29744, 7,29658,29697,29749,20103,29749,20186,29659, 29731,29755, 6,29659,29752,29759,24941,29759,23175,29759,29645,29759, 28133,29759,21605,29758,29645,29771,20103,29759,29749,29774,29077,29759, 29749,29759,20103,29780, 11,29759,20763,29759,26625,29787, 7,29659, 29731,29791,20103,29793,20103,29790,29731,29797,23457,29659,20501,29800, 26889,29659,20501,29804,20103,29659, 7,29809,29759,29811, 7,29808, 29731,29815,26625,29659,20501,29818, 6,29819, 7,29819, 6,29818, 29825,29827, 7,29818,29823,29831,21036,21605,27965,29835,27951,29835, 27948,29835,26816,29835,27796,29835,26898,29835,27216,29835,28151,29835, 28101,29835,26887,29835,21194,29835,24673,29857,24675,29835,21069,29835, 21267,29835,21305,29835,24953,29835,20119,29835,22723,29835,25129,29835, 25063,29835,23480,29835,21796,29835,21795,29835,20501,29882,25099,29835, 18967,29835,21183,29889,21795,29891,21183,29888,24673,29895,21259,29835, 20103,29899,21183,29835,27021,29902,18967,29902,24673,29907,20187,29835, 21127,29911,28573,29835,28625,29835,19683,29835,20839,29835,21399,29835, 27787,29835,20501,29924,27533,29835,20501,29928,27021,29835,21183,29932, 20501,29835,27787,29936,26889,29936,26625,29936,27533,29936,23457,29936, 21795,29936, 17,29835, 6,29834,26816,29953,21069,29953,21267,29953, 24953,29953,21305,29953,25063,29953,21259,29953,20103,29967, 17,29953, 20501,29953,26625,29972,26625,29953,20501,29976, 7,29834,21242,29981, 29911,29981,21049,29981,21183,29981,20103,29988,20103,29981,21183,29992, 20186,29835,29953,29997,21105,29997, 6,29835,28133,30003,21279,30003, 21166,30003,29992,30003,23175,30003,24941,30003,20103,30003,21127,30016, 29981,30016,21127,30003,20103,30022,29981,30003,20103,30026, 11,30003, 20763,30003,26625,30033, 7,29835,21105,30037,20103,30039,29953,30037, 20103,30043,20103,30036,29953,30047,21105,30047,23457,29835,20501,30052, 26889,29835,20501,30056,26625,29835,20501,30060, 6,30061, 7,30061, 6,30060,30067,30069, 7,30060,30065,30073,20103,29835, 7,30077, 30003,30079,21183,30079, 7,30076,29953,30085,21105,30085, 4,21605, 26371,30091,26450,30091,26539,30091,26542,30091,27439,30090,27483,30101, 17048,30091,26496,30091,26452,30091,26373,30091,26466,30091,26386,30091, 586,30091, 803,30117, 586,30090, 767,30121, 1,30091, 15,30124, 2,30124, 7,30124,26219,30131, 7,30125,23755,30135,26331,30135, 27805,30135,25793,30135, 1,30090,26454,30145,26375,30145,26415,30145, 26219,30150,26219,30145,26415,30154,26292,30145,26331,30159,25793,30145, 7,30162,26331,30165, 7,30163,26219,30169, 7,30145,25793,30173, 26415,30175,25793,30172,26331,30179, 3,30090, 767,30183,26454,30091, 18967,30186,26375,30091,18967,30190,28159,30091, 8684,30091, 8647,30091, 26154,30091,26331,30201,26534,30091,26541,30205,26536,30091,26331,30209, 26320,30091,26331,30213,19384,30091,20501,30217,19474,30091,20611,30091, 9989,30091,20762,30090,20985,30227,27436,30091,20501,30231,27507,30231, 27451,30231,27453,30231,26492,30091,26219,30240,26278,30091,26415,30244, 26219,30091,26541,30248,26492,30248,26415,30248,18967,30254,18967,30248, 26415,30258,27021,30091,18967,30263,20413,30265,18967,30262,20501,30269, 21527,30091, 9,30273,21258,30091,21575,30091,20501,30279,20985,30091, 20501,30090,27907,30285,27483,30285, 340,30091, 9,30091, 483,30091, 26292,30091,26331,30297,18967,30299,18967,30296,26331,30303,20413,30091, 20763,30307,25793,30309,26197,30091,26415,30312, 375,30091,24095,30091, 18967,30319,20413,30321,18967,30318,20501,30325,24252,30091,20501,30329, 15,30091, 1,30332,18967,30332, 11,30091,18967,30339,20413,30341, 18967,30338,20501,30345, 1369,30339, 9565,30349,28741,30349,30129,30349, 27979,30339,19631,30357,11949,30357, 4669,30357,26415,30091, 1,30365, 26219,30367,26197,30364,26278,30364,26219,30364,18967,30374,18967,30364, 26219,30378,18967,30365,26219,30383, 1369,30090,20029,30387,19781,30387, 21103,30387,26541,30091,26219,30394, 6,30090,23646,30399,23642,30399, 23606,30399,24349,30399,26086,30399,26062,30399,26068,30399,24583,30399, 24591,30399,19384,30399,24265,30419,25793,30399,19631,30422,11949,30422, 4669,30422,11949,30399,23493,30430,25793,30430, 4669,30399,23493,30436, 25793,30436,19631,30399,23493,30442,25793,30442, 11,30399,18967,30448, 24265,30451,18967,30399, 11,30454,24265,30457, 11,30455,23493,30461, 25793,30461,23493,30399,11949,30466, 4669,30466,19631,30466, 7,30090, 21549,30475,21105,30475,19625,30475, 6,30091,26524,30483,26545,30485, 26524,30482,26541,30489, 7,30091,26525,30492,30455,30493,25793,30497, 2,30493, 0,30500,30422,30503,25793,30503,30399,30506,30399,30503, 25793,30510, 0,30493, 2,30514,30422,30517,25793,30517,30399,30520, 30399,30517,25793,30524, 1,30492,26219,30529,18966,30493,30422,30533, 25793,30533,30399,30536,30399,30533,25793,30540, 8495,30492,21183,30493, 8495,30493,26524,30492,26331,30551,21037,30492,25793,30492,26331,30557, 18967,30559,18967,30556,26331,30563, 265,30492, 265,30493,25793,30493, 26541,30571,30495,30571,26492,30571,26415,30571,18967,30578,18967,30571, 26415,30582,18967,30492,26219,30587,25793,30586,26331,30591,25793,30587, 26415,30595,20763,30090,26142,30599,24849,30599,25793,30599,20413,30604, 20413,30599,25793,30608,20762,30091,26219,30613,20885,30613,25793,30612, 26331,30619,25793,30613,26415,30623,26524,30091,20501,30627, 6,30626, 26541,30631, 7,30626,26331,30635, 6,30627,26537,30639,30635,30639, 7,30627,30631,30645,26219,30645, 8495,30091, 7,30650,25793,30091, 1,30655, 7,30656,26219,30659, 7,30657,26331,30663,20762,30654, 26331,30667,20762,30655,26197,30671,26219,30671, 6,30655, 7,30655, 26197,30679,26278,30679, 1,30678,26219,30685,26219,30679,18967,30688, 18967,30678,26219,30693,18967,30679,26219,30696, 6,30654,30679,30701, 7,30654,26331,30705,18967,30707,30677,30705,18967,30704,26331,30713, 18967,30654,20501,30717, 6,30716, 7,30716,26331,30723, 6,30717, 30723,30727, 7,30717,30721,30731,26219,30731,18967,30655,20413,30737, 7,30736,26219,30741, 7,30737,26331,30745, 265,30091, 0,30748, 6,30751,21605,30752,21605,30751, 6,30756, 6,30757, 7,30748, 30755,30763,30759,30763, 7,30749,30761,30769,18967,30091,26454,30772, 26375,30772,26292,30772,26331,30779, 11,30772,20501,30783, 15,30772, 27021,30772,20501,30789,20501,30773,25793,30793,27021,30793,24095,30793, 26415,30772,26219,30800,20187,30773,25793,30805,26219,30772,26415,30808, 24095,30772,20501,30813, 6,30773,26604,30817,29645,30817,25793,30817, 20103,30822,20103,30817,25793,30826, 7,30773,26331,30831,27805,30831, 23755,30831,25793,30831, 6,30772,30831,30841, 7,30772,26219,30845, 25793,30844,26331,30849,30817,30845,25793,30845,26415,30855,25793,30772, 20501,30859, 6,30858, 7,30858,26331,30865, 6,30859,30865,30869, 7,30859,30863,30873,26219,30873,20103,30773,26219,30879, 7,30879, 25793,30883,21037,30091, 6,30887, 7,30887, 6,30886,30891,30893, 7,30886,30889,30897,18967,30090,27530,30901,26142,30901,26009,30901, 26270,30901,28571,30901,26454,30901,26375,30901,24210,30901,27459,30901, 26219,30901,20273,30920,26415,30920,20413,30901,25793,30926,27021,30926, 24095,30926,27021,30901,20413,30934,20985,30901,24095,30901,20413,30940, 20352,30901,25793,30945,26292,30901,26331,30949, 7,30901,25793,30953, 20273,30955,26415,30955,20273,30952,25793,30961,25793,30952,26331,30965, 26415,30901,26219,30968,20273,30901,26219,30972, 7,30972,25793,30977, 25793,30901,20413,30980, 7,30981,26219,30985, 7,30980,26331,30989, 21314,21605,27530,30993,26142,30993,26270,30993,26009,30993,26454,30993, 26375,30993,28571,30993,24795,30993,24799,30993,24210,30993,21850,30993, 21845,30993,20413,31016,27459,30993,18967,30993, 6,31023,29645,31025, 26219,30993,20273,31028,26415,31028,27021,30993,20413,31034,20413,30993, 25793,31038,27021,31038,24095,31038,21845,31038,20985,30993,24095,30993, 20413,31050,26292,30993,26331,31055,20352,30993,25793,31059, 7,30993, 25793,31063,20273,31065,26415,31065,25793,31062,26331,31071,20273,31062, 25793,31075,26415,30993,26219,31078,25793,30993,20413,31082, 7,31083, 26219,31087, 7,31082,26331,31091,20273,30993,26219,31094, 7,31094, 25793,31099, 6,21605,27347,31103,27401,31103,27378,31103,27327,31103, 27380,31103,27329,31103,27263,31103,27377,31116,27285,31103,27059,31103, 27377,31122,27194,31103,27203,31103,27215,31103,27208,31103,27228,31103, 27233,31103,27188,31103,27187,31103,27184,31103,27183,31103,27294,31103, 27275,31103,27305,31103,27280,31103,27481,31103,27470,31103,27341,31103, 27394,31103,27122,31103,27390,31103,27337,31103,26796,31103,26802,31103, 30939,31103,30229,31103,30616,31103,31049,31103,28681,31103,20843,31180, 28686,31103,22287,31103,28661,31103,28649,31103,27502,31103,27513,31103, 25030,31103,24983,31103,30283,31103,25683,31103,21058,31103,29835,31205, 21195,31103,29835,31209,25629,31103,13894,31103,13919,31103,27498,31103, 27509,31103,27930,31103,27895,31223,27857,31103, 4,31226,27895,31229, 4,31227,27907,31233,27479,31103,27468,31103,27500,31103,27511,31103, 26941,31103, 9457,31103,30118,31103,30185,31103,30123,31103,30105,31103, 26742,31103, 9444,31103, 9435,31103, 713,31260,30751,31102,30763,31265, 30221,31103,19397,31102,28777,31271, 3119,31103, 3027,31103, 3805,31103, 4820,31103, 6469,31103, 3419,31103,27422,31103,27359,31103,27392,31103, 27339,31103,27343,31103,27396,31103,27404,31103,27351,31103,27352,31103, 27407,31103, 9539,31103,24554,31103,29659,31102,29645,31311,17294,31103, 26843,31103,30335,31103,26845,31103,25689,31103,30337,31103,30787,31103, 24552,31103,25157,31103,24881,31103,28387,31103,28386,31102,31335,31337, 28387,31102,28386,31103,31341,31343,27287,31103,27323,31347,30127,31103, 30117,31103, 803,31352, 3,31103, 0,31356,27277,31103,20273,31360, 27377,31360,27461,31103,20273,31366,27483,31366,27377,31366,27205,31103, 20273,31374,27377,31374,27218,31103,27316,31103,27398,31103,18967,31384, 27345,31103,18967,31388, 413,31103,30292,31103,26986,31103,26982,31103, 9287,31103,27224,31103,20273,31402,27323,31403,21276,31103,29835,31409, 21496,31103,27021,31412,27021,31413,21277,31103,27021,31418,27021,31419, 21183,31419, 6441,31103, 759,31427, 4403,31103,17075,31103,16329,31103, 4919,31103,17099,31103, 9362,31103, 5309,31103, 4547,31103,27291,31103, 20273,31446,27323,31447,26810,31103,26990,31103, 777,31103, 824,31103, 244,31103, 4933,31103, 5297,31103,17077,31103,13019,31103,12705,31103, 13673,31103,18391,31103,18617,31103,14597,31103,27210,31103,27323,31481, 27472,31103,27323,31485,27300,31103,27323,31489,26317,31103,26476,31103, 9134,31103, 1216,31103,19687,31103,26625,31500,19397,31103,29659,31505, 29835,31505,22655,31505,23622,31103,27410,31103,22139,31103,22163,31103, 24543,31103,24557,31103, 305,31103,21036,31102,26816,31527,25063,31527, 31245,31527,21069,31527,21267,31527,21305,31527,24953,31527,21259,31527, 20103,31543, 17,31527,20501,31527,26625,31548,26625,31527,20501,31552, 26415,31103, 9,31556,26940,31103,29645,31103,29659,31563,27418,31103, 27255,31566,27272,31103,27377,31570,27255,31103,27483,31574,27418,31574, 27377,31574,18967,31580,18967,31574,27377,31584, 8446,31103, 155,31103, 17049,31103, 1369,31593, 8861,31103,26625,31103,21127,31598,20843,31598, 19687,31598, 8337,31598,20103,31598, 7971,31598, 9565,31598,18967,31598, 9731,31103,27021,31616,30613,31103,20885,31620, 9617,31102,26973,31625, 8337,31103,24545,31628,26625,31628, 9,31628, 4819,31103, 713,31636, 13857,31103, 713,31640, 4543,31103,21372,31103,21315,31103,27190,31648, 27483,31648,25027,31648,27021,31649,20273,31657,27377,31657,27021,31648, 20273,31662,27323,31663,20273,31648,27021,31668,27021,31669, 11,31648, 21037,31103,29835,31677,20103,31679,20763,31676,29835,31683,20103,31676, 29835,31687, 713,31103,13857,31690, 9435,31690, 4819,31690, 803,31690, 25,31103, 7971,31103,26625,31702,20884,31103,29659,31707,29835,31707, 20984,31103,28659,31713,28625,31713,30227,31713,22285,31713,17233,31103, 903,31722,30091,31103, 9,31726,20162,31103,20171,31103,25027,31103, 21315,31734,27190,31103,21315,31738,21127,31103,26625,31742,20843,31103, 26625,31746,28681,31746, 9565,31103,26625,31752, 8997,31103, 9,31756, 766,31103, 9455,31761,30121,31761, 3803,31761, 759,31761, 9,31103, 27021,31770,30091,31770, 9195,31770, 241,31770,26415,31770, 8997,31770, 27377,31770,23493,31770, 8337,31770,20103,31770, 1011,31103, 903,31792, 241,31103, 9,31796,27297,31103,27282,31103,27323,31803,18967,31805, 18967,31802,27323,31809, 17,31803,20103,31103,24545,31814,26625,31814, 21037,31814,29835,31821, 9,31814,21037,31815,25793,31827,20273,31103, 27224,31830,27291,31830,27205,31830,27277,31830,27461,31830,21315,31830, 27021,31842,27021,31843,27021,31830,21315,31848,27231,31103,27377,31852, 803,31103,30117,31856, 713,31856,20885,31103,27021,31862,30613,31862, 23493,31103, 9,31868,24545,31103,20103,31872, 8337,31872, 17,31873, 11,31103,28715,31881,19631,31883,11949,31883, 4669,31883,21315,31880, 8451,31103,27377,31103,27059,31894,27263,31894,27205,31894,27231,31894, 27461,31894,27272,31894,27277,31894,27255,31894,18967,31910, 9,31894, 18967,31894,27255,31916, 903,31103,17233,31920, 1011,31920, 257,31103, 27483,31103,21315,31928,27461,31928,27255,31928, 4,31102,23646,31937, 23642,31937,23606,31937,24349,31937,26086,31937,26062,31937,26068,31937, 24583,31937,24591,31937,19384,31937,24265,31957,25793,31937,19631,31960, 11949,31960, 4669,31960,11949,31937,23493,31968,25793,31968, 4669,31937, 23493,31974,25793,31974,19631,31937,23493,31980,25793,31980, 11,31937, 18967,31986,24265,31989,18967,31937, 11,31992,24265,31995, 11,31993, 23493,31999,25793,31999,23493,31937,11949,32004, 4669,32004,19631,32004, 5,31102,26940,32013,20413,32015,18967,32012,26816,32019,24953,32019, 31245,32019, 17,32019,20501,32019,26625,32028,26625,32019,20501,32032, 26625,32013,18967,32036,20413,32039,18967,32037,20501,32043,18967,32013, 20413,32047,26625,32049,26625,32046,20413,32053, 4,31103,27857,32057, 27879,32059,27857,32056,27895,32063,20763,32056,29835,32067,29659,32067, 28715,32057,29083,32073,29091,32073,19631,32073,11949,32073, 4669,32073, 29129,32073,18967,32073,29077,32087,18967,32056,23147,32091,24819,32091, 28925,32091,28715,32091,20413,32099, 5,31103,27437,32102,19397,32103, 21605,32103,20762,32108,20762,32109, 586,32108, 586,32109,31993,32103, 25793,32119, 2,32103,21605,32123, 0,32122,31960,32127,25793,32127, 31937,32130,31937,32127,25793,32134,32073,32127, 0,32103,21605,32141, 2,32140,31960,32145,25793,32145,31937,32148,31937,32145,25793,32152, 32073,32145, 586,32140, 586,32141,21605,32102,18966,32102,18966,32103, 21605,32167, 7,32169, 9,32167,31960,32167,25793,32167,31937,32176, 31937,32167,25793,32180,32073,32167, 1,32103,32125,32187,31937,32189, 3,32103,32143,32193,31937,32195,28573,32103,28625,32103,20843,32201, 9195,32103,20501,32103,21183,32103,27436,32102,27323,32211, 9377,32103, 713,32215, 9875,32103,19396,32103,32165,32221, 9,32103,18967,32224, 32165,32227,18967,32225,32167,32231,20763,32102,22285,32235,28659,32235, 28625,32235,32111,32235,30227,32235,30772,32103,20501,32247,27021,32102, 27323,32251,18967,32253,18967,32250,27323,32257, 17,32251, 1369,32103, 903,32103, 9,32265, 587,32102, 9455,32269,32159,32269,32115,32269, 3803,32269,30121,32269, 759,32269,25673,32103,20501,32283,20763,32103, 32113,32287,27021,32287,30613,32287, 587,32103,32161,32295,32117,32295, 30117,32295, 713,32295,27021,32103,27483,32305,32105,32305,27418,32305, 27377,32305,18967,32312,18967,32305,27377,32316,31992,32103,32163,32321, 18967,32103,32163,32325,31937,32327,32165,32325, 9,32331, 9,32324, 32165,32335,30091,32324,20501,32339,31937,32324,32163,32343,31937,32103, 18967,32346,32163,32349,30091,32103, 9,32353,18967,32352,20501,32357, 18967,32353,20413,32361,18967,32102,24953,32365,32171,32365,32107,32365, 32172,32365,32167,32365, 9,32374, 9,32365,32167,32378,27021,32364, 27323,32383,27021,32365,27377,32387,21037,31102,26604,32391,31561,32391, 31615,32391,29645,32391,25793,32391,20103,32400,20103,32391,25793,32404, 21314,31103,23147,32409,24819,32409,28925,32409,28715,32409,20413,32417, 21036,31103,25673,32421,20501,32423,25087,32421,25691,32421,22357,32421, 24953,32421,21049,32421,21242,32421,21183,32421,20103,32438,27021,32420, 27323,32443,20103,32421,21183,32446,27021,32421,27377,32451,27436,31103, 5,32454,27323,32457, 5,32455,27255,32461, 9195,31103, 9,32464, 27021,31103,21496,32468,21277,32468,20885,32468, 9,32468, 9731,32468, 21037,32468,21315,32468,20273,32482,27323,32483,21037,32469,21315,32469, 27205,32491,21036,32468,27323,32495,32489,32495,21036,32469,27231,32501, 32481,32501,20273,32468,21315,32506, 4,32469, 5,32469,27231,32513, 27272,32513,27255,32513,18967,32518,18967,32513,27255,32522, 9,32513, 4,32468,32513,32529, 5,32468,27323,32533,18967,32535,32511,32533, 18967,32532,27323,32541, 17,32533,18967,32468, 5,32546,27323,32549, 5,32547,27255,32553, 587,31103,30091,32557, 803,32559, 5,32556, 9455,32563, 3803,32563,30121,32563, 759,32563, 5,32557, 9435,32573, 803,32573,18967,31103,32391,32579,26625,32581,27398,32578,27345,32578, 21605,32578, 7,32589, 4,32591, 4,32590, 4,32589, 7,32596, 16,32589,27282,32578,27323,32603,26625,32578,32391,32607,27377,32578, 27255,32610,20483,32579,25793,32615,27255,32578,27377,32618,21183,32579, 26625,32623, 4,32579,26142,32627,24849,32627,21605,32627, 7,32633, 25793,32627,20413,32636,20413,32627,25793,32640, 5,32579,32593,32645, 4,32578,24819,32649,23147,32649,28925,32649,28715,32649,20413,32657, 5,32578,24953,32661,32595,32661,32599,32661,32635,32661,32601,32661, 27021,32660,27323,32673,27021,32661,27377,32677,27021,32578, 5,32680, 27323,32683, 5,32681,27255,32687,20763,31103,18967,32691, 5,32692, 5,32693,21037,32690,29835,32699,29659,32691,29835,32691,21036,32691, 21037,32691,25793,32709,30091,32691,20885,32713, 4,32691,32697,32717, 5,32691,18967,32720,28681,32721, 4,32690,32723,32727,32695,32727, 29659,32727,29835,32727,32707,32727, 5,32690,28625,32739,22285,32739, 28659,32739,30227,32739,32709,32739,18967,31102, 5,32750,26816,32753, 24953,32753,31245,32753, 17,32753,26625,32753,20501,32762,20501,32753, 26625,32766, 5,32751, 9,32771,30091,32771,20501,32775,21526,21605, 5,32778,26816,32781,24953,32781, 17,32781,26625,32781,20501,32788, 20501,32781,26625,32792, 5,32779, 9,32797,30091,32797,20501,32801, 18967,21605,20355,32804,20354,32804,26415,32805,26219,32810,26454,32805, 26375,32805,21127,32805,21183,32818,21248,32805,21273,32805,20986,32805, 20987,32805,28109,32804,28108,32805,32831,32833,31676,32805,31527,32837, 28109,32805,28108,32804,32841,32843,20352,32805, 4,32847,22729,32849, 22731,32847,32809,32847,20486,32805,26292,32805,26331,32859,19622,32804, 19623,32805,32863,32865,19623,32804,19622,32805,32869,32871, 386,32805, 347,32805,21396,32804,21397,32805,32879,32881,21546,32804,21547,32805, 32885,32887,21397,32804,21396,32805,32891,32893,21547,32804,21546,32805, 32897,32899,20477,32805,27673,32805,20476,32805,27672,32805,21127,32804, 21087,32911,29031,32804,31881,32805,21543,32805,21087,32805,21127,32921, 31880,32805,21542,32805,26219,32805,26415,32928,27283,32805,31103,32933, 20353,32805,32807,32937,20487,32805,21403,32804,21402,32805,32943,32945, 21573,32804,21572,32805,32949,32951,21403,32805,21402,32804,32955,32957, 21573,32805,21572,32804,32961,32963,20985,32804,32829,32967,21401,32804, 32056,32805,29450,32805,29041,32975,28791,32975,29731,32975,29659,32975, 20984,32805,21400,32805,32971,32987,32103,32805, 7,32990,32365,32993, 32057,32805,29451,32805,32915,32999,20984,32804,32827,33003,20985,32805, 31103,33007, 7,33006,33003,33011,21400,32804,21401,32805,33015,33017, 21183,32805,21127,33020,20413,32805, 4,33025, 4,33024, 11,33024, 27533,32805, 17,33032,20273,32805, 7,33037, 7,33036, 15,33037, 25793,32805, 7,33045,26219,33047, 7,33044,26331,33051,21527,32805, 17,33054,31103,32805, 4,33059,21037,33059,32421,33063,21037,33058, 31527,33067, 4,33058, 11,33058,21037,32805,31103,33075,32391,33077, 31103,33074,31527,33081,28715,32805,29031,33085, 7,33085,29759,33089, 21527,33085,29229,33093, 7,33084,29041,33097,29731,33097,29659,33097, 28791,33097, 15,33085, 580,32805, 1170,32805, 256,32805, 629,32805, 1413,32805, 922,32805, 581,32805, 1171,32805, 767,32805,31103,33125, 375,32805, 305,33128, 510,32805, 18,32804, 12,32804,23493,33137, 1291,32805, 525,32805, 13,32805,22807,33145,33137,33145, 19,32805, 33135,33151, 18,32805, 13,32804, 12,32805,33157,33159, 19,32804, 33155,33163, 16,32805,32421,33167,25743,33167,32365,33167,32661,33167, 27533,33167,21037,33167,31103,33179, 10,32805,19333,33183,33137,33183, 31648,33183,19455,33183,24237,33183,22896,33183,19393,33183,19385,33183, 9,33199,22807,33183, 9,33202,20413,33183, 9,33183,22807,33208, 21315,33183,31103,33212,31103,33183,21315,33216, 14,32804,32847,33221, 33041,33221,24953,33221,32975,33221,33097,33221,26816,33221,33167,33221, 33111,33221, 17,33221,20501,33221,26625,33240,26625,33221,20501,33244, 10,32804,22149,33249,19441,33249,24213,33249,24059,33249,19656,33249, 9,33249,19631,33260,19631,33249, 9,33264,23983,33249, 9,33269, 524,32805, 1290,32805, 11,32804,21087,33277,20326,33277,33183,33277, 9,33283, 9,33276,23493,33287,33183,33287,23493,33277, 9,33293, 20273,33277, 9,33296, 9,33277,20273,33300, 9,32804, 11,33304, 23493,33307,33183,33307, 11,33305,24265,33313,33249,33313, 15,32804, 32937,33319,32999,33319,26142,33319,33123,33319,20413,33319,25793,33328, 20273,33319,25793,33319,20413,33334, 11,32805,24567,33339,33157,33339, 24428,33339,20413,33338,31103,33338,33260,33339,33249,33339, 9,33352, 24265,33339, 9,33356, 9,33339,24265,33360,33249,33360, 483,33338, 9,32805,30090,33368,30090,33369,30091,33368,33373,33375, 483,33368, 11,33369,20273,33381,30091,33369,33371,33385,20501,33385, 17,32805, 19474,33390,19475,33391,33393,33395,21314,33390,19474,33391,19475,33390, 33401,33403,21314,33391,21315,33390,33407,33409,27533,33390,21527,33390, 33319,33391, 1275,33390,21315,33391,33399,33421, 305,32805, 375,33424, 1011,32805, 7,33428,33221,33431, 15,33429, 7,33429, 241,32805, 7,33438, 483,32805, 4,33442, 903,33442, 9,33442, 4,33443, 11,33442, 903,32805, 9,33455, 483,33454, 1275,32805, 17,33460, 7,32805,20985,33464,33003,33467,20985,33465,32985,33471,25672,33465, 30772,33465,25673,33465,30773,33465,21036,33465,30090,33465,20273,33464, 33221,33487,25793,33464,26331,33491,28715,33464,29731,33495,29659,33495, 28791,33495,29041,33495,33221,33495,18967,33465, 5,33506,30091,33506, 5,33507,33485,33513, 17,33507,21605,33465, 4,33518,33513,33521, 21037,33518, 4,33519,33509,33527,33483,33527, 11,33519,25793,33465, 26415,33535, 1011,33464,33221,33539, 241,33464, 8495,33465,32103,33465, 20273,33547,32165,33547,21037,33465,21604,33553,21605,33552,33555,33557, 21605,33553,21604,33552,33561,33563,28715,33465,20273,33567,29533,33567, 30091,33465,18967,33572,33221,33465,20273,33577,23927,33465,20273,33581, 29031,33465,20273,33585,32013,33465,20273,33589, 15,33465,29835,33465, 29659,33465,29077,33597,32102,33465, 4,33465,24687,33603,25773,33603, 21605,33602,33513,33609,31830,33603,32645,33603,29485,33603,22729,33603, 31103,33603,20273,33620,20273,33603,31103,33624, 5,33465,18967,33628, 33527,33631,31103,33628,20103,33629,31103,33637, 5,33464,33519,33641, 7,33641,21605,33645,33603,33647,33620,33641,33547,33641,33557,33641, 33475,33641,33525,33641,33481,33641,31648,33641,20413,33641,33603,33641, 31103,33666,21315,33641,31103,33670,31103,33641,33603,33674,21315,33674, 4,33464,33507,33681,25743,33681,33601,33681,32365,33681,32661,33681, 33635,33681,33575,33681,33477,33681,33511,33681,33479,33681,32421,33681, 33221,33681,27533,33681,33629,33681,31103,33709,21037,33681,31103,33713, 31103,33465, 5,33716,33681,33719, 5,33717,33603,33723, 6,32804, 33624,33727,33713,33727,33085,33727,29229,33733,33179,33727,21036,33727, 33681,33739,33167,33739,28714,33727,33567,33745,18967,33727, 5,33749, 33603,33751, 5,33748,33681,33755,33167,33755,20273,33727,33603,33760, 33603,33727,20273,33764,29451,33727, 17,33727, 5,33726,26816,33773, 33681,33773,24953,33773,33487,33773,33041,33773,33495,33773,33097,33773, 32847,33773,32975,33773,33167,33773,33111,33773,33539,33773,33431,33773, 17,33773,33465,33773,20273,33803,26625,33773,20501,33806,20501,33773, 26625,33810, 5,33727,33603,33815,18967,33814,33681,33819,33167,33819, 9,33815,33465,33815,20273,33827,30091,33815,20501,33831,33465,33727, 18967,33834, 4,33837, 4,33836,21315,33834,21314,33834, 4,33835, 33843,33847, 5,33835,33841,33851,33845,33851, 4,33834,18967,33856, 33851,33859,33851,33857, 5,33834,33839,33865,33847,33865, 5,32805, 27953,33871,27743,33871,27555,33871, 2,33870, 0,33870, 3,33870, 1,33870,33609,33871,33521,33871,30285,33871,33485,33871,32717,33871, 25101,33871,33027,33871,33061,33871,23193,33871,33593,33871,33451,33871, 20413,33871,20885,33871,33603,33871,27533,33913,23015,33871,20501,33917, 27741,33871,20501,33921, 9,33871,30492,33871, 6,33871,33879,33929, 33881,33929,20273,33929, 7,33871,33883,33937,33885,33937,25793,33937, 32805,33936, 4,33945,21605,33937,33947,33949, 5,33949,33945,33953, 33603,33949,30091,33936,21527,33937,27533,33937,21315,33963, 7,33870, 31648,33967,20413,33967,31103,33967,21315,33972,21315,33967,31103,33976, 21315,33871,21605,33981,33929,33983,30091,33871,20501,33987, 6,33986, 7,33986, 6,33987,33993,33995, 7,33987,33991,33999, 4,32804, 27530,34003,26142,34003,26270,34003,26009,34003,33879,34003,33929,34012, 33881,34003,33929,34016,33930,34003,33932,34003,33939,34003,33941,34003, 33506,34003,33681,34029,33683,34003,33934,34003,33943,34003,26454,34003, 26375,34003,33769,34003,32937,34003,32999,34003,33664,34003,32941,34003, 33908,34003,32997,34003,28571,34003,33970,34003,33961,34003,18967,34003, 33465,34062,33681,34065,33465,34063,33641,34069,33206,34003,33123,34003, 33121,34003,24210,34003,33413,34003,33415,34003,32903,34003,32909,34003, 33771,34003,32917,34003,32927,34003,33275,34003,33143,34003,27459,34003, 33419,34003,33463,34003,33035,34003,33057,34003,33517,34003,26219,34003, 20273,34110,26415,34110,24265,34003,28233,34003,29077,34003,33183,34003, 20413,34122,33641,34003,20413,34126,33967,34003,20413,34130,33391,34003, 27533,34135,20413,34003,25793,34138,27021,34138,33641,34138,33871,34138, 33967,34138,33183,34138,24095,34138,27021,34003,20413,34154,33929,34003, 33879,34158,33881,34158,20273,34158,20985,34003,31103,34167, 11,34003, 21605,34171,33465,34003,18967,34174,33681,34177,24095,34003,20413,34180, 26292,34003,26331,34185,20352,34003,25793,34189,33936,34003,33883,34193, 33885,34193,25793,34193, 7,34003,25793,34201,20273,34203,26415,34203, 33871,34201,33879,34209,33881,34209,20273,34209,25793,34200,26331,34217, 20273,34200,25793,34221,33871,34200,33883,34225,33885,34225,25793,34225, 26415,34003,26219,34232,20273,34003,26219,34236,33929,34236, 7,34236, 25793,34243,25793,34003,20413,34246, 7,34247,26219,34251, 7,34246, 26331,34255,33871,34003,18967,34258, 6,34261, 6,34260,21605,34259, 33929,34267,21527,34258,31103,34259,21526,34258,20413,34258, 6,34259, 34271,34279, 7,34259,34265,34283,34275,34283, 6,34258,34267,34289, 18967,34288,34283,34293,34283,34289, 7,34258,33883,34299,33885,34299, 34263,34299,34279,34299,25793,34299, 4,32805, 2,34311, 7,34313, 27669,34311,23357,34311,32468,34311,28483,34311,27978,34311,31746,34311, 31742,34311,31500,34311,20413,34310,23014,34311,31103,34310,21605,34311, 7,34338, 7,34339,33773,34343,33221,34343, 15,34338,27021,34311, 31103,34350,28411,34311,33629,34311,20413,34357, 483,34310,31103,34311, 27021,34362,20843,34362,21127,34362,19687,34362,19687,34311,31103,34372, 20843,34311,31103,34376,21127,34311,31103,34380, 15,34311,21605,34384, 375,34311,33727,34311, 9,34391, 7,34311,21605,34394,25793,34395, 265,34395,31103,34395, 7,34310,33755,34405,33819,34405,33773,34405, 33739,34405,25743,34405,32661,34405,32421,34405,32365,34405,33221,34405, 27533,34405,21037,34405,33727,34427,31103,34427,21037,34311,33929,34433, 26219,34433, 7,34433,25793,34439,28715,34311,20413,34443, 5,32804, 27965,34447,27948,34447,26816,34447,27796,34447,26898,34447,20353,34447, 29451,34447,32847,34447,33487,34447,33041,34447,32975,34447,33495,34447, 33097,34447,34343,34447,34315,34447,33527,34447,33518,34447,33641,34481, 33643,34447,24953,34447,20119,34447,33706,34447,34362,34447,32727,34447, 25129,34447,34333,34447,33029,34447,34337,34447,33071,34447,32691,34447, 34424,34447,34403,34447,32067,34447,31707,34447,26887,34447,32857,34447, 32973,34447,21605,34447,33465,34522,33641,34525,33465,34523,33681,34529, 33176,34447,33111,34447,33109,34447,31505,34447,23480,34447,33347,34447, 33349,34447,32905,34447,32907,34447,32919,34447,32925,34447,33273,34447, 33141,34447,25099,34447,33539,34447,34361,34447,33445,34447,33431,34447, 33367,34447,33453,34447,33031,34447,33073,34447,33533,34447,20187,34447, 19683,34447,20839,34447,21399,34447,33167,34447,27533,34586,33681,34447, 27533,34590,34405,34447,27533,34594,28625,34447,28573,34447,33339,34447, 20413,34603, 1171,34447,27787,34447,20501,34608,27533,34447,20501,34612, 33681,34612,34405,34612,33167,34612,20501,34447,27787,34622,26889,34622, 26625,34622,27533,34622,23457,34622,34395,34447, 17,34447,33465,34447, 29077,34639,20273,34639,21605,34638,33641,34645,28233,34639,24265,34639, 11,34639, 6,34446,26816,34655,34405,34655,33041,34655,33097,34655, 34343,34655,33681,34655,32847,34655,33487,34655,32975,34655,33495,34655, 24953,34655,33167,34655,33111,34655,33539,34655,33431,34655, 17,34655, 33465,34655,20273,34689,20501,34655,26625,34692,26625,34655,20501,34696, 7,34446,34635,34701,34579,34701,34311,34701,20103,34701,20186,34447, 34655,34711,34394,34447,34655,34715,31103,34447,34311,34718, 6,34447, 34706,34723,34395,34723,33039,34723,33089,34723,34397,34723,34341,34723, 20273,34723,34708,34723,23175,34723,24941,34723,34325,34723,28133,34723, 33437,34723,20103,34723,34701,34750,34701,34723,34311,34754,20103,34754, 11,34723,34311,34723,34701,34762,20763,34723,26625,34767, 7,34447, 21605,34771,34311,34773,34655,34771,34311,34777,20103,34777,20103,34770, 34655,34783,34311,34770,34655,34787,23457,34447,20501,34790,26889,34447, 20501,34794,20103,34447, 7,34799,34723,34801, 7,34798,34655,34805, 26625,34447,20501,34808, 6,34809, 7,34809, 6,34808,34815,34817, 7,34808,34813,34821,34311,34447,21605,34824,18967,34825, 6,34828, 6,34829,31103,34824,21527,34825,21526,34825,20413,34825, 6,34825, 18967,34842,34827,34843, 7,34825,34723,34849,25793,34849,34833,34849, 6,34824,34849,34857,34837,34857, 7,34824,34655,34863,34845,34863, 34831,34863,34843,34863,34839,34863, 6,32805,34236,34875,34120,34875, 34433,34875,20962,34875,21001,34875,34118,34875,34355,34875,25648,34875, 21314,34874,34891,34893,25649,34875,33087,34875,21314,34875,34116,34875, 23017,34875,34335,34875,21937,34875,34170,34875,34173,34875,21959,34875, 21315,34874,34897,34917,34385,34875,34387,34875,24875,34875,33332,34875, 33435,34875,33043,34875,33107,34875,34349,34875,21605,34875,21315,34936, 34893,34939,21315,34937,34901,34943,20273,34875,34003,34946,33319,34946, 20885,34875,20843,34952,21315,34875,21605,34956,34893,34959,19475,34875, 26625,34963,24265,34875,34003,34966,29077,34875,34003,34970,28233,34875, 34003,34974,20843,34875,20885,34978, 11,34875,34003,34982,33319,34875, 20273,34986,34003,34875,29077,34990,20273,34990,28233,34990,24265,34990, 11,34990,30993,34875,30901,34875,20984,34875,20839,35007, 5,34875, 20763,35011,20843,35013,20763,35010,20839,35017,20763,34875, 5,35020, 20839,35023, 5,35021,20885,35027, 7,32804,34736,35031,34459,35031, 34461,35031,29691,35031,29340,35031,28714,35031,33603,35043,21605,35031, 5,35047,33681,35049,34405,35049,33167,35049, 5,35046,33603,35057, 34607,35031,34637,35031,33924,35031,34447,35031, 11,35031,32103,35031, 29835,35031,29659,35031,20273,35031,34723,35076,29229,35076,35011,35031, 34723,35031,20273,35084, 567,35031,29229,35031,20273,35090, 9,35031, 33871,35094,33871,35031, 9,35098, 4,35030, 5,35030,35083,35105, 34875,35105,35010,35031,35103,35111, 4,35031,35108,35115, 7,35114, 35049,35119,35105,35115,34875,35122,34875,35115,35105,35126, 483,35115, 5,35031,21605,35132,33603,35135,35103,35133,34875,35139,34875,35132, 35103,35143,34875,35031,18967,35147, 4,35148, 4,35149,21315,35147, 21314,35147, 4,35147,18967,35158, 5,35147,35115,35163,35153,35163, 4,35146,35163,35169,35155,35169, 5,35146,35103,35175,35161,35175, 35151,35175,35159,35175,35157,35175, 0, 4,14087,35187,14103,35188, 4983,35187, 5001,35192,14104,35187, 5002,35187,14088,35187,14091,35201, 4984,35187, 4987,35205,14093,35187, 4989,35187,28758,35187,29229,35213, 28741,35187, 2,35216,29229,35219,20501,35186,19463,35223,19317,35223, 19301,35223,20009,35223, 53,35186,19463,35233,20009,35233,19317,35233, 19053,35187, 989,35241, 1201,35187,18967,35245, 1203,35247,17673,35186, 17685,35251,21405,35186,21489,35255,19513,35186,19463,35259,20009,35259, 19317,35259,10157,35187, 17,35267,10159,35269,20343,35187,18967,35273, 20345,35275, 1179,35187, 527,35186,19301,35281,19916,35186, 4,35285, 7,35286, 7,35285, 4,35290, 16,35285,19069,35186,19301,35297, 1290,35186, 0,35301, 2,35302, 2,35301, 0,35306,18966,35301, 21530,35187,20501,35313, 1489,35187,16859,35187, 11,35318, 9875,35321, 21529,35187, 11,35324,20501,35327, 147,35187,16860,35187, 9875,35333, 987,35187, 8069,35187, 11,35338, 8067,35341, 8070,35187, 8067,35345, 27519,35187,27525,35187,26322,35187,26566,35187,26102,35187,26276,35187, 26105,35187,33464,35187,29600,35187,32295,35187,31856,35187,25636,35187, 29229,35371, 9,35371,28555,35187,29229,35377, 9,35377,19301,35187, 20501,35383, 527,35383,19069,35383, 4266,35187, 8056,35187, 8147,35187, 20739,35187, 9997,35187, 8784,35187, 8622,35187, 8824,35187, 8702,35187, 8697,35187, 8676,35187, 8635,35187,20828,35187,19772,35187,19890,35187, 19774,35187,19894,35187,19382,35187,19458,35187,32557,35187, 803,35429, 19463,35187,20501,35433, 53,35433,19513,35433,20009,35187, 53,35441, 20501,35441,19513,35441,19317,35187,20501,35449, 53,35449,19513,35449, 19914,35187,21066,35187,20575,35187,21312,35187,21270,35187, 694,35187, 9377,35467,16920,35187, 9,35471,17621,35187, 9,35475, 4213,35187, 375,35478, 8757,35187, 375,35482, 9530,35187, 9875,35487,16091,35487, 20501,35487,19751,35187, 53,35495, 253,35495, 117,35495, 71,35495, 1471,35495, 1397,35187, 9592,35187,16514,35187,19380,35187,13836,35187, 20595,35187, 9911,35187, 9983,35187, 9905,35187,17566,35187,16816,35187, 17910,35187,18880,35187,14103,35187,14087,35532, 5001,35187, 4983,35536, 20597,35187,26219,35187, 241,35542, 587,35543, 8647,35187, 241,35548, 587,35549,14073,35187, 586,35554,14091,35557, 586,35555,14103,35561, 4971,35187, 586,35564, 4987,35567, 586,35565, 5001,35571, 1291,35187, 35305,35575,35309,35575, 1871,35575, 1889,35575, 3,35575,19667,35575, 12345,35575, 5123,35575,19067,35575,35311,35575,18967,35575, 1297,35597, 35301,35597,19917,35187,35289,35603,35293,35603,19939,35603,19945,35603, 6,35603,19947,35603,35295,35603, 17,35603,19931,35619,35285,35619, 1108,35187, 11,35625,22806,35187, 9,35629, 524,35187, 3,35633, 3477,35633, 2007,35633,19051,35633,19667,35633,12345,35633, 5123,35633, 18967,35633, 555,35649, 713,35187, 1325,35187,17455,35655,10001,35187, 1505,35659, 9513,35187, 11,35662, 9875,35665,16091,35665,20501,35665, 19396,35187, 483,35672,17455,35187,13737,35676, 803,35187,31103,35680, 31103,35187, 803,35684, 113,35187, 375,35187, 587,35691, 9195,35693, 4213,35690, 7971,35690, 8757,35690, 587,35690, 9377,35703, 9565,35690, 18967,35690,19892,35187, 9,35710, 510,35187,18967,35714, 587,35187, 375,35718, 9377,35721, 9377,35719, 375,35725, 483,35187,19396,35728, 587,35729, 11,35728, 5123,35735,12345,35735, 3477,35735, 2007,35735, 19667,35735,19051,35735,18967,35735, 555,35749,18967,35728, 9,35752, 9,35728,18967,35756, 1275,35187,16833,35760, 9,35763, 903,35761, 9,35761,21575,35187,18967,35771,21577,35773,21581,35773,21585,35773, 6685,35187, 7519,35187, 17,35783, 7521,35785, 7525,35785, 7529,35785, 21258,35187, 241,35792,16722,35187,32103,35187, 9,35799,10310,35187, 8684,35187, 241,35804, 331,35805,26292,35187, 241,35810, 482,35186, 2,35815, 0,35816,35633,35819,35735,35819, 0,35815, 2,35824, 35633,35827,35735,35827,35749,35815,35649,35815,18966,35815,35735,35837, 35633,35837, 1368,35186,25793,35843, 8495,35843,23755,35843,10055,35843, 4329,35843, 4311,35843,26331,35843,27805,35843, 3785,35843, 8717,35843, 10351,35843, 586,35186,31761,35867,32563,35867,32269,35867, 7,35867, 4,35874, 4,35867, 7,35878, 16,35867, 767,35867,31103,35885, 482,35187, 587,35889, 1274,35187, 587,35186, 9262,35895, 375,35895, 9195,35898, 7,35895, 265,35903, 9195,35905, 9195,35895, 375,35908, 483,35895, 483,35186, 1369,35186,19463,35917,19301,35917,20009,35917, 19317,35917, 1368,35187, 7,35927, 586,35187,14073,35930,14091,35933, 4971,35930, 4987,35937,31856,35931,32295,35931, 7971,35931,14073,35931, 14087,35947, 4971,35931, 4983,35951,31103,35931, 803,35954, 803,35931, 31103,35958, 483,35931, 1531,35187,13737,35187, 1487,35966,17455,35966, 16833,35187, 1196,35972, 1196,35973, 1197,35972,35977,35979, 1197,35973, 35975,35983, 1275,35972, 9,35987, 767,35187,31103,35991, 1487,35187, 13737,35994,16937,35187, 17,35999, 9377,36001,17573,36001,16947,36001, 1347,35187,18967,36009, 555,36011, 251,36011, 1365,36011, 1351,36011, 21,36011,20762,35187, 241,36022, 256,35187,25793,36026,25793,36027, 8495,36026, 8495,36027,18967,36026,21037,36026, 972,35187, 9377,36041, 629,35187,18967,36044, 340,35187, 9377,36049,27978,35187,28353,36053, 30003,36053,29759,36053,34723,36053,21183,36053, 2,36053,28337,36065, 28189,36065,28191,36053, 959,36053, 759,36053, 47,36053, 66,35187, 89,35187, 7,36080, 973,35187,35895,36085,21527,35187,21605,36088, 29229,36091, 9,36091, 145,35187, 165,35187, 305,35187, 25,35187, 27533,35187, 1505,36105, 331,35187,17455,36109, 59,35187,17455,36113, 29599,35187, 7,36116,26546,35187, 7,36120, 8812,35187, 7,36124, 10291,35187, 3,36129, 3,36128, 9565,35187, 375,36134, 8495,35187, 256,36138, 7,36139, 375,36143, 7,36138, 241,36146, 331,36147, 241,36138, 7,36152, 7971,35187, 375,36156,25793,35187, 256,36160, 7,36160, 241,36164, 241,36160, 7,36168,32805,35187, 7,36172, 19888,35187, 7,36176,18967,35187, 256,36180, 629,36180, 510,36180, 375,36180, 483,36180, 9,36190, 9,36180, 483,36194, 7,36180, 241,36198, 7,36181,25793,36203, 8495,36203, 241,36180, 7,36208, 241,35187,26292,36212,26219,36212, 8684,36212, 8647,36212,20762,36212, 21258,36212, 7,36212,25793,36226,25793,36227, 8495,36226, 8495,36227, 18967,36226,21037,36226,25793,36212, 7,36240, 8495,36212, 7,36244, 18967,36212, 7,36248,21037,36212, 7,36252, 9,35187,19892,36256, 1011,36256, 11,36261,18967,36256, 483,36264, 483,36256,18967,36268, 903,35187, 7,36272, 9377,36275,19913,35187, 6,36279, 7,36279, 6,36278,36283,36285, 7,36278,36281,36289, 15,35187,25381,36293, 483,36293, 2,36293,28189,36299, 1011,35187,16710,36303,16711,36303, 16710,36302,36307,36309, 0,36303, 6,36312,16711,36302,36305,36317, 9,36302, 11,36321, 1275,36302,36315,36325, 11,36303, 9,36329, 6,36302, 3,36332, 6,36303, 0,36336,36325,36339, 7,36303, 25793,36343, 8495,36343,21605,35187,21037,36348,21105,36348,21527,36348, 29229,36355, 9,36355,21549,36348,19625,36348,21526,36348, 5,36364, 922,36349, 918,36349, 1505,36349, 1419,36349, 668,36349, 483,36349, 903,36378, 587,36349, 9,36382, 9,36349, 903,36386, 11,36387, 587,36386, 15,36348, 11,36348, 9,36397, 6,36348,21036,36400, 5,36400,18967,36404,18967,36400, 5,36408, 7,36348,30003,36413, 29759,36413,34723,36413,21183,36413, 959,36413, 47,36413, 759,36413, 6,36349,36353,36429,36361,36429,36351,36429,36363,36429, 7,36349, 36403,36439,31527,36439,22269,36439,28791,36439,22263,36439,32781,36439, 36367,36439,21105,36439,21549,36439,29953,36439,29731,36439,34655,36439, 33773,36439,29835,36439,29659,36439,34447,36439,32753,36439,32019,36439, 29041,36439,23929,36439,22205,36439,19625,36439,33221,36439,36407,36439, 36411,36439,18967,36348, 5,36490, 6,36493,36413,36495, 6,36492, 36439,36499,36439,36493, 14,36490,36439,36505, 6,36491,36395,36509, 6,36490, 5,36512,36439,36515, 903,36349, 7,36519, 9,36518, 483,36518, 265,35187,17455,36527, 5843,36527, 483,36527, 587,36527, 9,36527, 7,36526, 9377,36539, 7,36527, 11,35187, 8069,36544, 8067,36547,16859,36544, 9875,36551,21529,36544,20501,36555,16091,36545, 9513,36559, 7,36544, 2,36563, 7,36564,36545,36567, 1,36564, 36569,36571, 1,36563, 2,36574, 0,36544, 2,36579, 0,36580, 36545,36583, 6,36580,36585,36587, 6,36579, 2,36590, 482,36579, 1368,36544, 2,36597, 1,36598, 1,36597, 2,36602,18966,36544, 2,36607, 6,36608, 6,36607, 2,36612, 482,36607, 9513,36544, 20501,36619, 9875,36619,16091,36619,20501,36545,21529,36627, 9513,36627, 9875,36545,16859,36633, 9513,36633, 1369,36545, 1989,36639, 3587,36639, 36601,36639,36605,36639, 5303,36639,36571,36639,36577,36639, 0,36639, 4897,36639,17041,36639,18967,36545,20281,36661,20345,36661,36611,36661, 36615,36661,36587,36661,36593,36661, 7,36661,20285,36661,36595,36661, 36617,36661, 483,36661,20273,36683,36579,36683,36607,36683,21605,36544, 9,36691, 483,36544,35819,36695,35827,36695, 3477,36695, 2007,36695, 1,36695,36639,36705,36655,36695,19051,36695,19667,36695, 5123,36695, 12345,36695,35837,36695,18967,36695, 555,36721,35815,36721, 3,36544, 3,36545, 375,36729,21308,35187, 7,36732,16481,35187, 7,36736, 21037,35187, 256,36740, 7,36740, 241,36744, 241,36740, 7,36748, 16531,35187, 7,36752, 1011,36753, 7,36757,18797,35187, 7,36760, 17827,35187, 7,36764,16783,35187, 7,36768, 2,35186,27138,36773, 28047,36773,26454,36773, 8770,36773,26375,36773, 8729,36773, 8697,36773, 8784,36773,28197,36773, 4266,36773, 9262,36773,28111,36773,27128,36773, 28027,36773,28117,36773,28177,36773,31872,36773,28063,36773,31598,36773, 24545,36773,31103,36812, 8684,36773, 8717,36817, 331,36817,26292,36773, 26331,36823, 8647,36773, 8757,36826,26219,36773,27021,36830,26415,36830, 26415,36773,26219,36836, 8757,36773, 8647,36840, 375,36840, 4213,36773, 375,36846,28153,36773,26860,36773,28213,36773,35931,36773,28159,36773, 31770,36773, 347,36773, 386,36773, 9750,36773,27978,36773,26331,36869, 27805,36869, 1325,36869, 331,36869, 59,36869,23755,36869,25793,36869, 265,36869, 340,36773, 331,36887,31103,36773,24545,36890,26625,36890, 9,36890, 375,36773, 8757,36898, 4213,36898, 9195,36898,27021,36898, 305,36898, 483,36773, 9195,36773, 375,36912,10001,36773, 9,36917, 1325,36773, 1275,36773, 331,36773,27533,36773, 9,36927, 305,36773, 375,36930,10291,36773, 483,36935,27021,36773,26219,36938, 375,36938, 7,36773,25793,36944,26331,36947, 8495,36944, 8717,36951, 331,36951, 25793,36945,26415,36957,27021,36957, 8495,36945, 8757,36963,26625,36944, 9731,36944,21605,36945,24545,36971,26625,36971, 9,36971, 265,36945, 8757,36979, 4213,36979,27021,36979, 9195,36979, 305,36979,21605,36944, 26331,36991,27805,36991,23755,36991, 59,36991, 331,36991, 1325,36991, 25793,36991, 265,36991, 265,36944, 331,37009, 8647,36945,26219,36945, 59,36773, 7,36772,25793,37019, 8495,37019,23755,37019,10055,37019, 4329,37019, 4311,37019, 3785,37019,27805,37019,10351,37019, 8717,37019, 26331,37019, 9,36773,31103,37042, 15,36773,31103,37047, 9731,36773, 7,37050,21605,36773, 15,37055,31103,37057, 6,37055, 5,37060, 7,37055,26219,37065, 375,37065, 6,37054,37057,37071, 7,37054, 26331,37075,37063,37075,27805,37075,23755,37075, 59,37075, 331,37075, 1325,37075,25793,37075, 265,37075, 265,36773, 7,37095, 8495,37097, 375,37097, 7,37094, 331,37103,26625,36773,31103,37106, 7,37106, 8495,36773, 7,37112, 8717,37115, 331,37115, 9,37113, 483,37113, 7,37113, 8647,37125, 375,37125,25793,36773, 7,37130,26331,37133, 483,37131, 9,37131, 7,37131,26219,37141, 3,35186,20305,37145, 9641,37145,20309,37145, 9645,37145, 4,37145, 7,37154,35603,37157, 9719,37145, 16,37145,35603,37163,35619,37145,21081,37145,20323,37145, 20387,37145, 9701,37145,35719,37145, 524,37145,20273,37179, 9617,37179, 1291,37145, 9617,37185,20273,37185, 305,37145, 375,37190, 386,37145, 347,37145, 767,37145,31103,37199, 483,37145, 11,37202, 9617,37205, 20273,37205, 375,37145, 305,37210, 7,37145, 3,37215,18967,37217, 35187,37219, 4,37214,35603,37223,37221,37223, 3,37214,35187,37229, 11,37145, 483,37232, 9617,37235,20273,37235, 6,35186,19975,37241, 0,37241, 2,37244,35575,37247,35633,37247,35735,37247,36695,37247, 18966,37241,35735,37257,35633,37257,35575,37257,36695,37257,35749,37241, 35649,37241,36721,37241,35597,37241,19365,37241,19221,37241,19917,37241, 10107,37279, 587,37241, 3,37241, 2,37241, 6,37287, 17,37289, 35187,37291, 0,37286,35575,37295,35633,37295,35735,37295,36695,37295, 37293,37295, 6,37286,36544,37307,37295,37309, 11,37307,35187,37312, 37295,37315,35187,37307, 11,37318,37295,37321, 7,35186, 4,37325, 3,37326, 3,37327,35927,37331, 902,37325,25525,37325, 1325,37325, 10001,37325, 903,37341, 1275,37325, 59,37325,25793,37325, 587,37349, 8495,37325, 587,37353, 2,37325, 7,37356,37331,37359, 903,37357, 10311,37357, 3,37325, 4,37366,27533,37325, 903,37371, 331,37325, 2,37324,25793,37377, 8495,37377,23755,37377, 4329,37377,10055,37377, 27805,37377, 3785,37377, 4311,37377,26331,37377, 8717,37377,10351,37377, 21605,37325, 903,37401, 155,37401, 265,37325, 7,35187, 5045,37408, 805,37409, 9195,37413, 4,37408,37279,37417,19916,37417,37241,37421, 1275,37417,18967,37424,37241,37427,18967,37417, 1275,37430,37241,37433, 26546,37408,32805,37408,29599,37408, 652,37409, 9195,37443, 8812,37408, 19888,37408,19913,37408,21308,37408,16481,37408,37285,37409,16783,37408, 17827,37408,18797,37408,26498,37409, 8796,37409, 8495,37408, 241,37468, 331,37469,25793,37408, 241,37474,25793,37409, 241,37479, 587,37478, 8495,37409, 241,37485, 587,37484,21037,37408, 241,37490, 88,37409, 37411,37495,16531,37408, 587,37409, 265,37500, 9195,37503,26625,37501, 25793,37501, 8495,37501,25793,37500, 8495,37500, 9731,37501, 265,37409, 587,37518, 9195,37521, 4213,37519, 7971,37519, 8757,37519, 587,37519, 9377,37531, 9565,37519, 89,37409, 5069,37537, 9195,37537,27021,37537, 483,37409, 1275,37409, 9,37547,26503,37409, 8809,37409,18967,37408, 241,37554, 241,37408,25793,37558,25793,37559, 8495,37558, 8495,37559, 18967,37558,21037,37558, 903,37408, 9377,37573,21605,37408,30003,37577, 29759,37577,34723,37577,21183,37577,37495,37577, 959,37577, 47,37577, 759,37577, 265,37408, 9377,37595, 903,37409,31103,37598,31920,37409, 31103,37409, 903,37604, 375,37409, 2,37408,37331,37611,37495,37611, 3,37408,14072,37616, 4970,37616,14072,37617,14073,37616,37623,37625, 4971,37616, 4970,37617,37629,37631, 7,37617, 4,37635, 1,37616, 37537,37639, 9,37639,36773,37617,37537,37617, 7971,37617,14073,37617, 37619,37651, 4971,37617,37621,37655, 483,37617, 9,37617, 2,37409, 37369,37663,37329,37663,37637,37663, 7,37662,37617,37671,37335,37663, 9362,37663,27218,37663,37642,37663,37639,37663, 9,37682,28189,37663, 1,37663, 5,37688,37616,37690,37617,37691,37693,37695,37671,37694, 37616,37691,37617,37690,37701,37703,37672,37691,37671,37691,37617,37708, 5,37663, 1,37712,37616,37714,37617,37715,37717,37719,37671,37718, 37616,37715,37617,37714,37725,37727,37672,37715,37671,37715,37617,37732, 28337,37663,37660,37663,27021,37663, 9,37740, 9195,37663, 9,37744, 9,37663,37639,37748,27021,37748, 9195,37748,37617,37748,37241,37663, 37617,37663, 1,37760, 5,37762, 5,37760, 1,37766, 7,37761, 37691,37771,37715,37771,37765,37771,37769,37771, 9,37760, 3,37409, 37577,37783, 9,37785, 16,37783, 4,37783, 7,37790, 7,37783, 4,37794,18967,37783,35187,37799,37789,37801,37793,37801,37797,37801, 9,37782,37577,37809,37611,37809,37611,37783, 1,37815, 5,37816, 5,37815, 1,37820, 7,37814,37819,37825,37823,37825, 9,37815, 9,37409, 3,37832,37577,37835,37611,37835, 3,37833,37663,37841, 3,35187,10104,37844,10105,37844, 0,37845, 5,37850, 4,37844, 36773,37855,10104,37845,37849,37859,10105,37845,37847,37863,36945,37845, 37855,37867,10291,37844,36944,37845, 265,37873,37663,37845, 7,37877, 37691,37879,37715,37879, 1369,37845, 11,37885, 9617,37887,37853,37887, 20273,37887, 11,37844, 6,37844, 7,37844,14072,37898, 4970,37898, 14073,37898,14072,37899,37905,37907, 4971,37898, 4970,37899,37911,37913, 35187,37899,36773,37899, 7971,37899,14073,37899,37901,37923, 4971,37899, 37903,37927, 483,37899, 6,37845,37856,37933,37855,37933,36773,37936, 1,37933, 5,37940,37898,37942,37899,37943,37945,37947,37898,37943, 37899,37942,37951,37953, 5,37933, 1,37956,37898,37958,37899,37959, 37961,37963,37898,37959,37899,37958,37967,37969,36773,37933,37855,37972, 37899,37933, 7,37845, 265,37979,36773,37981,35187,37978, 2,37985, 4,37979,37987,37989, 3,37989,37985,37993,37663,37989,36773,37978, 265,37999,37897,37979,36773,37845, 4,38005,37933,38007, 7,38005, 37943,38011,37959,38011,14073,38011, 4971,38011, 6,38004, 1,38021, 5,38022,38011,38025, 5,38021, 1,38028,38011,38031,38007,38021, 7,38004, 265,38037,18967,37845, 4,38041,37933,38043, 256,38041, 7,38041, 241,38048, 241,38041, 7,38052, 2,35187,29229,38057, 28741,38059,28741,38056,29229,38063, 0,38057, 0,38056,28714,38069, 37185,38069, 1290,38069,37145,38075,37179,38069, 525,38069,37145,38081, 37887,38069,37205,38069,37235,38069, 5,38069,21605,38090,21605,38069, 5,38094, 1275,38069, 17,38098,37145,38101, 17,38069, 1275,38104, 37145,38107, 1505,38057,17455,38057, 903,38112,17494,38057, 483,38057, 37214,38057,14073,38121, 4971,38121,37783,38057, 587,38057,10373,38057, 9,38057, 155,38057, 6,38056, 1,38137, 5,38138,38121,38141, 5,38137, 1,38144,38121,38147,37145,38137, 587,38137, 7,38056, 37331,38155, 6,38057, 5,38158,18966,38159, 0,38159, 2,38164, 2,38159, 0,38168, 1369,38159, 17,38159,35187,38175,38163,38177, 38167,38177,38171,38177, 7,38057,38141,38185,37145,38187,38147,38185, 37145,38191,34447,38185,28715,38185,38069,38197,38071,38185,29659,38185, 29835,38185,38093,38185,38097,38185, 4971,38185,37145,38211,14073,38185, 37145,38215,37145,38184,38141,38219,38147,38219,14073,38219, 4971,38219, 21605,38185, 903,38229,37145,38057, 4,38232, 6,38233, 1,38237, 5,38238, 5,38237, 1,38242,38235,38237, 7,38233, 265,38249, 7,38232,38241,38253,38245,38253,38141,38253,38147,38253,14073,38253, 4971,38253, 903,38057,17455,38266, 6,35187, 4,38271, 1,38272, 0,38270, 17,38277,37844,38278,37845,38279,38281,38283,37845,38278, 37844,38279,38287,38289, 1369,38271, 2,38270, 587,38295, 3,38270, 2,38271, 1275,38301, 1, 5,35962,38304,35963,38304,37760,38304, 37771,38311,37976,38304,38002,38304,37761,38304,37977,38304,37815,38304, 37825,38323,38003,38304,37930,38304,37658,38304,37931,38304,37659,38304, 77,38304, 3095,38337, 1917,38337, 120,38304, 3013,38343, 1897,38343, 79,38305, 3113,38349, 125,38305, 3023,38353,35929,38305,37885,38357, 37916,38305,37885,38361,38021,38304,38011,38365,38237,38304,38253,38369, 4597,38305, 6625,38373, 113,38304, 4696,38377, 9,38377, 4669,38380, 4669,38377, 9,38384,37896,38304,37898,38304,37933,38391, 483,38391, 37616,38304,37663,38397, 483,38397, 59,38304,23023,38403,25483,38403, 22677,38403,27533,38304,23023,38411,22677,38411,22605,38411,25483,38411, 37663,38304,37617,38420,37672,38421,37671,38421,37617,38426,37771,38421, 37879,38421,37617,38421,38397,38435,37671,38434,37933,38304,37899,38440, 38011,38441,37899,38441,38391,38447,37897,38304,38137,38304,38121,38453, 38219,38453,38185,38453,37145,38459,38253,38453,37617,38304,37663,38464, 483,38464,37899,38304,37933,38470, 483,38470, 979,38305,21605,38477, 987,38479,21879,38305, 1205,38483,29229,38304,29375,38487,17105,38304, 17117,38491,23755,38304,23023,38495,22677,38495,25483,38495,26863,38305, 21605,38503,26865,38505,10091,38305, 15,38509,10093,38511, 1009,38305, 675,38304,22605,38517, 1418,38304, 1,38521, 3,38522, 3,38521, 1,38526,21604,38521,21895,38304,22605,38533,25380,38304, 5,38537, 6,38538, 6,38537, 5,38542, 14,38537, 1365,38305,17573,38305, 9,38550,10001,38553,27996,38305,27533,38557, 1203,38305,17574,38305, 10001,38563, 177,38305,27995,38305, 9,38568,27533,38571, 7963,38305, 9,38574, 7961,38577, 7964,38305, 7961,38581, 120,38305, 77,38305, 37758,38305,37972,38305,37457,38305,37867,38305,35912,38305,35733,38305, 35732,38305,35913,38305,22605,38305,27533,38605, 675,38605,21895,38605, 36856,38305, 483,38613,37644,38305, 483,38617,37918,38305,37933,38621, 483,38621,37177,38305, 483,38627, 4798,38305,15896,38305,23023,38305, 59,38635,27533,38635,23755,38635,22677,38305,27533,38643, 59,38643, 23755,38643,25483,38305, 59,38651,27533,38651,23755,38651,25368,38305, 30290,38305,27127,38305,30762,38305,30566,38305, 843,38304,35187,38669, 1531,38304, 842,38304, 1530,38304,35930,38305,38675,38679,38307,38679, 9492,38305,10001,38685,13755,38685,27533,38685,24597,38305, 59,38693, 331,38693, 97,38693, 141,38693, 1325,38693, 629,38305,37896,38305, 37610,38305,37783,38709,37616,38305,38467,38713,38423,38713,38311,38713, 38331,38713,38469,38713,38465,38713,37663,38725, 483,38725,37898,38305, 38473,38731,38443,38731,38315,38731,38329,38731,38475,38731,38471,38731, 37933,38743, 483,38743,37866,38305,37456,38305,17508,38305, 9257,38305, 27149,38305, 9353,38305, 9253,38305,38253,38305,38137,38763,38237,38763, 483,38763,38219,38305,38137,38771, 483,38771,38121,38305,38137,38777, 483,38777,15897,38305, 4799,38305,27161,38305,20187,38305, 483,38789, 8387,38305, 483,38793, 9541,38305,15879,38305, 483,38798, 4787,38305, 483,38802,16125,38305, 3,38806, 2,38806, 842,38806, 843,38807, 38813,38815, 842,38807, 843,38806,38819,38821, 2,38807,38809,38825, 3,38807,38811,38829, 5121,38305, 3,38832, 2,38832, 842,38832, 843,38833,38839,38841, 842,38833, 843,38832,38845,38847, 2,38833, 38835,38851, 3,38833,38837,38855,35729,38305, 587,38859, 587,38858, 19384,38305, 483,38865, 669,38305, 1011,38869, 1086,38305, 483,38873, 1418,38305, 1011,38877,25381,38305,38541,38881,38545,38881,25423,38881, 25429,38881, 7,38881,25431,38881,38547,38881, 15,38881,25415,38897, 38537,38897, 1419,38305,38525,38903,38529,38903, 1801,38903, 1875,38903, 2,38903,23983,38903,10603,38903, 4625,38903,21893,38903,38531,38903, 21605,38903, 1421,38925,38521,38925, 1108,38305, 9565,38931, 246,38305, 483,38935, 294,38305, 8495,38939,35931,38305,38669,38943,38309,38943, 483,38943,36773,38942, 483,38951,19396,38305,35718,38305,37885,38957, 37202,38957,37145,38957, 483,38962, 483,38957,37145,38966, 668,38305, 2,38971, 3507,38971, 1971,38971,21783,38971,23983,38971,10603,38971, 4625,38971,21605,38971, 713,38987,20060,38305, 483,38991, 713,38305, 16833,38995,38011,38305,37933,38999,38021,38999, 483,38999,37285,38305, 37409,39006,36945,38305,37845,39011,37845,39010, 483,39011,37215,38305, 3,39019,38057,39019, 9377,38305, 9,39024,10001,39027,13755,39027, 27533,39027, 1471,38305,16937,39035, 9875,38305, 1011,39039, 1347,39039, 555,38305,20763,38305, 566,39046, 566,39047, 567,39046,39051,39053, 567,39047,39049,39057, 257,38305, 483,39061, 973,38305, 4816,39065, 4805,39065, 1011,39068,38057,39065, 1011,39065, 4805,39074, 628,38305, 483,39079, 1406,38305, 587,38305,23584,39085,24355,39085,37782,39085, 37408,39084,39091,39093,37783,39085,37408,39085,38670,39085, 3,39085, 37409,39102,39093,39105,37409,39103,39099,39109,38669,39085,35187,39112, 35728,39084,23493,39085,22807,39118,22807,39085,23493,39122,35729,39084, 35728,39085,39127,39129,35729,39085,39117,39133,37409,39085, 3,39136, 39093,39139, 483,39085,35187,39142,35187,39085,38669,39146, 483,39146, 36773,39147, 483,39153, 1011,39084, 483,39157, 9,39084, 4625,39161, 10603,39161, 3507,39161, 1971,39161,23983,39161,21783,39161,21605,39161, 713,39175,18967,39084, 483,39179,35187,39084,37202,39183,37885,39183, 37145,39183, 483,39188, 483,39183,37145,39192,37409,39084,39097,39197, 11,39084, 483,39201, 1369,38305,35964,39204,35965,39205,39207,39209, 35965,39204,35964,39205,39213,39215,35761,39205,38057,39205, 15,39204, 1011,39223, 11,39205, 1011,39205, 11,39204, 1275,38305, 483,38305, 35895,39234, 4787,39234,15879,39234,21405,38305, 1011,39243, 483,39243, 7535,38305, 15,39249, 7537,39251, 7541,39251, 7545,39251,28337,38305, 21605,39259,28351,39261,28355,39261,28359,39261, 6147,38305, 483,39269, 15269,38305, 483,39273,17423,38305, 1011,39277, 483,39277, 4827,38305, 483,39283, 4745,38305, 1011,39287, 483,39287,17232,38305,30492,38305, 25793,39295, 265,39294, 4569,38305, 483,39301,14625,38305, 483,39305, 7063,38305, 483,39309,37284,38305,37356,38305,17233,38305,30493,38305, 483,39319,37973,38305,37759,38305,38002,38305,38327,39327,37760,38305, 483,39331,37976,38305,38321,39335,37617,38305,38398,39339,38319,39339, 38400,39339,38335,39339,37663,39339,38397,39348,37671,39349,38397,39339, 37663,39354, 483,39354,36773,39338, 483,39361, 483,39339,38397,39364, 37663,39338, 483,39369,37899,38305,38392,39373,38321,39373,38394,39373, 38333,39373,35187,39372,37885,39383,37933,39373,38391,39386,38391,39373, 37933,39390, 483,39390,36773,39372,37933,39397, 483,39397, 483,39373, 38391,39402,38185,38305,38150,39407,38137,39407,37145,39410,37202,39407, 37885,39407, 483,39407,37145,39418,37145,39407,38137,39422, 483,39422, 37979,38305,38451,39429,37663,38305,37409,39432, 3,39435, 7,39433, 39437,39439, 2,39439,39435,39443, 483,39433,37617,39447,37241,39432, 37617,39432, 483,39453,37933,38305,36773,39456,37977,38305,38315,39461, 37815,38305, 483,39465,38003,38305,38317,39469,38127,38305, 483,39473, 482,38304, 5,39477, 6,39478, 6,39477, 5,39482, 14,39477, 586,38304,39122,39489,39128,39489,39127,39489,38863,39489,38601,39489, 38948,39489,38603,39489,39150,39489,39144,39489,38783,39489,38785,39489, 3,39489, 1,39512,38971,39515,39161,39515, 1,39489, 3,39520, 38971,39523,39161,39523,39175,39489,38987,39489,21604,39489,39161,39533, 38971,39533,39146,39489, 483,39538,39142,39489,35187,39542,38943,39489, 483,39546,35728,39489,39085,39550,22807,39489,39085,39554,26219,39489, 8647,39489,19396,39489,39085,39489,22807,39564,35728,39564,35187,39564, 483,39570, 483,39564,35187,39574,35895,39489, 9,39489,18967,39580, 18967,39489, 9,39584,35187,39489,39142,39588,39085,39588, 483,39592, 483,39588,39085,39596, 483,39489,38943,39600,39146,39600,39085,39600, 35187,39606,35187,39600,39085,39610, 4787,39489,15879,39489, 1368,38304, 3867,39619, 8277,39619, 3997,39619, 4067,39619, 9459,39619, 8953,39619, 1274,38304,27979,39633,14625,39633, 4569,39633,16381,39633,13325,39633, 26293,39633, 8685,39633,35843,39633, 1369,39633,19513,39633, 3863,39633, 37019,39633, 9955,39633,37377,39633, 8401,39633,10273,39633,20697,39633, 4137,39633,20219,39633, 4063,39633,35895,38305, 483,39674,35915,38305, 3,39678, 2,39678, 842,39678, 843,39679,39685,39687, 842,39679, 843,39678,39691,39693, 2,39679,39681,39697, 3,39679,39683,39701, 482,38305,39616,39705,39614,39705,39578,39705,35718,39705,35895,39705, 39489,39714,39489,39705,15879,39718, 4787,39718,35895,39718,15879,39705, 39489,39726, 4787,39705,39489,39730,35187,39705, 587,39734, 587,39735, 39489,39739, 587,39705,35187,39742, 1368,38305, 587,38304,39241,39749, 39239,39749,39237,39749,38599,39749,38597,39749,38633,39749,38631,39749, 39677,39749,38801,39749,38805,39749,38679,39749, 483,39771,39235,39749, 15879,39775, 4787,39775,35895,39775, 483,39748,38679,39783, 483,38304, 38121,39787,38219,39787,38253,39787,37899,39786,38731,39795,37617,39786, 38713,39799,38011,39787,38185,39787,37145,39805,14625,39787, 4569,39787, 19396,39787,35931,39787,39489,39815,15269,39787, 4827,39787, 587,39786, 38679,39823,37899,39787,38391,39827,37617,39787,38397,39831,17423,39787, 4745,39787, 9,39787,18967,39838,18967,39787, 9,39842, 587,39787, 39588,39847,39489,39847,35187,39850,35187,39847,39489,39854,35187,39787, 586,39858,39823,39861, 586,39859,39847,39865, 586,38305,39713,39869, 38861,39869,39737,39869,39745,39869,38675,39869,35187,39879,39823,39869, 35187,39883,39783,39869,35187,39887, 1108,39869, 295,39869,35927,39869, 37611,39869,38155,39869,35719,39869,39705,39901,39749,39869,22807,39905, 35728,39905,35187,39905, 483,39910, 483,39905,35187,39914,35187,39868, 39823,39919,39783,39919,38675,39919,39749,39919, 483,39927, 1011,39869, 9,39930, 9,39869, 1011,39934, 1369,38304, 1275,39938, 1275,38304, 39429,39943,23023,39943,22605,39943,25483,39943,22677,39943, 1369,39942, 803,38305,17455,39956,13737,39957,39705,39961, 1505,38305,21605,39965, 713,39967, 305,39967, 1489,39967, 1509,39967, 25,39967,15705,38305, 767,39979,39705,39981,17455,38305, 15,39985, 9513,39987,16859,39987, 17469,39987, 803,39984, 154,38305, 165,39997, 374,38305, 11,40001, 66,38305, 340,38305,30091,40006,27978,38305,39633,40011,23755,40011, 27805,40011,26331,40011,25793,40011, 8495,40011, 511,38305, 11,40025, 935,38305, 483,40029, 1109,38305, 11,40033, 295,38305, 256,38305, 375,40039, 9805,40039,20762,38305, 1141,40045, 1447,40045, 33,40045, 88,38305,11251,40053, 5177,40053, 136,38305,36727,40059,37895,40059, 36079,40059, 144,38305, 113,40067, 341,38305, 113,40071,16937,40071, 27979,38305,38411,40077, 483,40077,39943,40077, 9565,40077, 113,38305, 4727,40087, 9,40089,37662,38305,37241,40093,37932,38305,36773,40097, 37782,38305,37978,38305,39633,40103,38389,40103, 305,38305,16833,40109, 25,38305,16833,40113,20501,38305, 1011,40117, 1347,40117, 253,38305, 16937,40123, 53,38305,16937,40127, 251,38305, 21,38305,38004,38305, 7,40135,37241,38305, 6,40138, 2,40141,35187,40142,35187,40141, 2,40146, 2,40147,38056,40141,37663,40138, 3,40138,40145,40157, 40149,40157,40153,40157, 3,40139,40151,40165,40093,40165,36773,38305, 37933,40171,37899,40173,37933,40170,35931,40170, 483,40179,37617,40170, 483,40183,37899,40170,37933,40187, 483,40187,37409,40170, 3,40193, 483,40171,35931,40197,37617,40197,37899,40197, 6,40170,37844,40205, 3,40205,35187,40208,35187,40205, 3,40212, 7,40171,40207,40217, 40211,40217,40215,40217,40195,40217, 2,40217,40193,40227,37845,40217, 40205,40231,37845,40170, 7,40235,37325,38305, 7,40238, 2,40241, 2,40240, 7,40239,35187,40247, 3,40249, 3,40248, 3,40247, 35187,40254, 3,40246,37844,40247, 1368,40238, 586,40239, 1369,40238, 37845,40238,40259,40269,40265,40269, 587,40239, 2,40238, 7,40276, 40251,40277, 3,40238,40243,40283,35187,40282,40275,40287, 3,40239, 40279,40291,40245,40291,40269,40291, 7,40290,40269,40299,40263,40291, 2,40239,40287,40305,40257,40305,40253,40305,40261,40305,40267,40305, 10219,38305, 7,40316, 2,40318, 2,40319, 1368,40316, 1369,40316, 2,40317,40327,40329, 3,40317,40321,40333,40325,40333, 2,40316, 7,40338,40333,40341, 3,40316,40323,40345, 413,38305, 7,40349, 375,40349, 1217,38305, 483,40355, 1216,38305, 7,40359, 412,38305, 483,40363,36348,38305, 2,40366,36429,40369,38233,38305, 7,40373, 25296,38305, 7,40377, 265,38305,27978,40381,30492,40380, 17,40380, 8495,40387, 6,40380, 11,40391, 7,40380,30091,40394, 7,40381, 27021,40399, 9195,40399,40391,40399,40001,40399,21605,40398, 6,40381, 40395,40411,40007,40411, 17,40411,21605,40381, 7,40418, 17,40419, 241,40380, 483,40425,21605,40380, 7,40429,30091,40380, 7,40432, 11,38305,18967,40436, 483,40439, 587,40436, 483,40443, 1369,40436, 483,40437, 587,40449, 3,40436, 3,40437, 9875,40455,20501,40455, 1011,38305, 483,40461, 587,40463, 587,40460, 483,40467, 9,40460, 9565,40471, 7,40461, 959,40475, 759,40475, 47,40475, 903,40460, 7,40483, 15,38305, 1369,40486, 1011,40489, 241,40486, 483,40493, 3,40486, 165,40497, 3,40487, 253,40501, 1471,40501, 53,40501, 21605,38305,27533,40509, 15,40509,31103,40513, 1275,40509, 7,40508, 23755,40519,39633,40519,27805,40519,26331,40519,25793,40519, 8495,40519, 7,40509,26219,40533, 305,40533, 25,40533, 713,40533, 265,40509, 31103,40543, 265,40508, 7,40547,25367,38305, 6,40551, 7,40551, 6,40550,40555,40557, 7,40550,40553,40561, 17,38305,19917,40565, 587,40565, 265,40564, 8495,40571, 265,40565, 8861,40575, 3,40564, 113,40579, 3,40565,10109,40583,10108,40583,10108,40582,40585,40589, 10109,40582,40587,40593, 1141,40583, 1447,40583, 33,40583, 903,38305, 7,40603, 1141,40605, 1447,40605, 33,40605, 1011,40602, 7,40613, 18967,38305, 1108,40617, 1072,40617, 165,40617, 1291,40617, 524,40617, 9,40617, 1011,40628, 11,40616, 483,40633, 11,40617, 483,40636, 483,40617, 11,40641, 1011,40640, 587,40641, 11,40640, 9,40616, 587,40616, 483,40653, 7,40616, 1141,40657, 1447,40657, 33,40657, 1011,40617,21183,40665, 7,40665, 483,40664, 9,40664, 241,38305, 483,40675, 15,40674, 483,40679, 9,40675, 7,40674, 375,40685, 9805,40685, 7,40675, 265,40691, 59,40691, 331,40691, 1325,40691, 265,40674, 483,40701, 9,38305, 7963,40704, 7961,40707,27995,40704, 27533,40711,17573,40704,10001,40715,13755,40705, 9377,40719, 1,40704, 3,40723, 1,40724,40705,40727, 7,40724,40729,40731, 7,40723, 3,40734, 586,40723, 6,40704, 3,40741, 6,40742,40705,40745, 0,40742,40747,40749, 0,40741, 3,40752,21604,40704, 3,40757, 7,40758, 7,40757, 3,40762, 586,40757, 1274,40704, 3,40769, 0,40770, 0,40769, 3,40774, 9377,40704,27533,40779,10001,40779, 13755,40779,10001,40705,17573,40787, 9377,40787,27533,40705,27995,40793, 9377,40793,21605,40705,26715,40799,26865,40799,40761,40799,40765,40799, 40731,40799,40737,40799, 6,40799,26719,40799,40739,40799,40767,40799, 587,40799,26625,40821,40723,40821,40757,40821, 1275,40705, 1991,40829, 3621,40829,40773,40829,40777,40829, 5299,40829,40749,40829,40755,40829, 1,40829, 4907,40829,17711,40829, 1011,40704, 9565,40851, 587,40704, 39515,40855,39523,40855, 3507,40855, 1971,40855, 0,40855,40829,40865, 40845,40855,21783,40855,23983,40855, 4625,40855,10603,40855,39533,40855, 21605,40855, 713,40881,39489,40881,18967,40704, 1011,40705,18967,40889, 9617,40889, 2,40704,36727,40895,37895,40895,36079,40895, 3,40704, 11251,40903, 5177,40903, 2,40705,36729,40909, 3,40705,11355,40913, 30748,38305, 7,40916,17125,38305, 7,40920,30091,38305, 340,40924, 7,40924,25793,40929, 265,40928, 1011,40925, 7,40935, 265,40925, 7,40939, 265,40924, 7,40942,14315,38305,31103,40947, 375,40947, 7,40947, 8495,40953,37845,38305,37897,40957, 1275,40957,36945,40956, 6,40957, 7,40957, 6,40956,40967,40969,36773,40969, 7,40956, 38389,40975,39633,40975,40965,40975,36773,40956, 7,40983,37409,38305, 37285,40986, 113,40987, 2,40987,39313,40993,40157,40993, 3,40987, 39439,40999,40217,40999, 2,40986,38305,41005, 7,41007,40999,41009, 40165,41005,37241,41005, 3,40986, 3,38304,40375,41019,40237,41019, 40985,41019,40137,41019,40963,41019,39015,41019,38749,41019,40098,41019, 39323,41019,40972,41019,40989,41019,39009,41019,38751,41019,40094,41019, 39325,41019,41014,41019,15567,41019,12971,41019,13355,41019,13541,41019, 21049,41019,21242,41019,39127,41019,39714,41019,39739,41019,38603,41019, 38601,41019,38863,41019,39726,41019,39730,41019,20956,41019,20773,41019, 38783,41019,38785,41019,11970,41019,19441,41019,19656,41019, 4696,41019, 5,41019, 6,41097,27169,41019,27168,41019,33465,41019,40011,41019, 30492,41019,40519,41019,39295,41019,30493,41019,40929,41019, 357,41019, 367,41019, 471,41019, 1249,41019, 628,41019,20057,41019, 4569,41019, 14625,41019, 4545,41019,36203,41019,36343,41019,40953,41019,21183,41019, 20103,41142,13325,41019, 8337,41147, 4549,41019, 9357,41019, 9356,41019, 40966,41019,36026,41019,37558,41019,36226,41019,36944,41019, 8386,41019, 20186,41019, 9083,41019, 9484,41019,36027,41019,37559,41019,36227,41019, 36945,41019, 8387,41019,20187,41019,19513,41019,35843,41019,20219,41019, 8401,41019,37019,41019,20697,41019, 4137,41019, 9955,41019, 3863,41019, 4063,41019,37377,41019,10273,41019,21405,41019,20606,41019, 9984,41019, 37215,41019,40969,41019,36773,41218,40975,41019,40097,41019,36773,41224, 40103,41019,37979,41019,19396,41019,11131,41019,21059,41019, 9082,41019, 28205,41019,25551,41019,24613,41019,20326,41019,21087,41019,39705,41019, 35895,41250,15879,41250, 4787,41250,11949,41019, 9,41258, 4669,41019, 9,41262,15879,41019,39705,41266, 4787,41019,39705,41270,20805,41019, 37501,41019,19631,41019, 9,41278,35895,41019,39705,41282, 9704,41019, 40387,41019,38939,41019,40033,41019,40571,41019,20804,41019, 341,41019, 241,41299,27979,41019, 241,41303, 9377,41019, 11,41306, 256,41019, 35187,41310, 257,41019,35187,41315,20763,41019, 11,41318, 4745,41019, 17423,41019, 587,41019, 11,41326,37409,41326,37500,41019, 9875,41019, 10,41334, 10,41335, 11,41334,41339,41341, 11,41335,41337,41345, 1471,41019,37325,41019, 587,41351,37241,41019,40093,41354,41005,41354, 37408,41019, 241,41360,41005,41019,37241,41364,40093,41019,37241,41368, 20885,41019,20413,41372, 1369,41019,37409,41377,37409,41019, 241,41381, 587,41380,40967,41019, 9195,41019, 11,41388,20413,41019,20885,41392, 10219,41019, 587,41397,20501,41019, 10,41400, 10,41401, 11,41400, 41405,41407, 11,41401,41403,41411, 253,41019, 6,41019,40373,41417, 40135,41417,40235,41417,40983,41417,40967,41417,27021,41417,40533,41417, 30091,41417, 4713,41417,16363,41417, 4863,41417,13119,41417,26415,41417, 8757,41417,23493,41417,27377,41417, 4213,41417, 9195,41417,39489,41417, 9335,41417, 4147,41417, 3933,41417, 8109,41417,36212,41417,36773,41417, 20103,41417, 8337,41417,37145,41417, 8997,41417,40957,41417, 241,41417, 35187,41478,18967,41417, 11,41483,35187,41417, 241,41486, 587,41487, 587,41417, 8387,41417,20187,41417,14653,41417,36945,41417, 7,41019, 30091,41502,26331,41503, 8717,41503,23755,41503,27805,41503, 3785,41503, 40957,41502,36212,41502,39633,41503,10055,41503, 4329,41503, 4311,41503, 10351,41503,36773,41502,20103,41502, 8337,41502, 8997,41502, 1275,41503, 15,41503,18967,41541,35187,41502, 241,41544, 241,41502,35187,41548, 27021,41019, 11,41552, 53,41019, 6,41018,41165,41559,41531,41559, 41517,41559,41157,41559,40975,41559,40103,41559,41537,41559,41169,41559, 41167,41559,41239,41559,41533,41559,41535,41559,40011,41559,27979,41559, 40519,41559,41549,41559,41311,41559,16381,41559,13325,41559,26293,41559, 8685,41559,41361,41559,41545,41559,41503,41559,36773,41607,40957,41607, 8997,41607,20103,41607, 8337,41607, 241,41607,35187,41607, 1369,41559, 4569,41559,35843,41559,19513,41559, 3863,41559, 9955,41559, 4063,41559, 37377,41559,10273,41559,20697,41559, 4137,41559,37019,41559,20219,41559, 8401,41559,14625,41559, 7,41018,41181,41653,41466,41653,41387,41653, 41476,41653,41474,41653,41185,41653,41183,41653,41171,41653,41468,41653, 41470,41653, 8997,41653,41417,41674,41315,41653,41478,41653,26219,41653, 8647,41653,41381,41653,41486,41653,19396,41653,41417,41653,36773,41692, 40957,41692, 8997,41692,20103,41692, 8337,41692, 241,41692,35187,41692, 20103,41653,41417,41708, 8337,41653,41417,41712,36773,41653,41417,41716, 483,41653, 9,41653,18967,41722, 241,41653, 1,41727,41417,41729, 41417,41726,18967,41653, 9,41734,40957,41653,41417,41738,35187,41653, 41417,41742, 11,41019,27021,41746, 587,41746, 9195,41746,20501,41746, 9377,41746, 9875,41746,20763,41746, 9,41019, 4669,41762,11949,41762, 19631,41762,18967,41762,20273,41762, 9617,41762, 17,41019,20762,41776, 20762,41777,20763,41776,41781,41783,20763,41777,41779,41787,40957,41019, 6,41790, 7,41790,41559,41795, 6,41791,41795,41799, 7,41791, 41793,41803,41417,41803, 9617,41019, 9,41808,36212,41019, 7,41812, 35187,41019, 256,41816, 7,41816, 241,41820,41559,41821, 7,41817, 41417,41827, 241,41816, 7,41830, 241,41019, 1,41835, 7,41837, 41559,41839, 7,41836,41417,41843,37408,41834, 7,41835, 1,41848, 41417,41851,41417,41849, 7,41834,41559,41857,35187,41856,35187,41834, 7,41862,18967,41019, 483,41867, 9,41866,30091,41019, 7,41872, 14315,41019, 8997,41019, 7,41878,41559,41881, 7,41879,41417,41885, 20273,41019, 9,41888, 8337,41019, 7,41892,41559,41895, 9,41893, 483,41893, 7,41893,41417,41903,20103,41019,21183,41906, 7,41906, 41559,41911, 9,41907, 483,41907, 7,41907,41417,41919,36773,41019, 40097,41922,40969,41922, 7,41922,41559,41929, 9,41923, 483,41923, 7,41923,41417,41937, 2,38304,38595,41941,40177,41941,39459,41941, 38591,41941,38593,41941,40155,41941,39451,41941,38589,41941,39237,41941, 39241,41941,39239,41941,38599,41941,38597,41941,38633,41941,38631,41941, 26777,41941, 9741,41941,26781,41941, 9745,41941,39677,41941,38801,41941, 38805,41941, 5,41941, 6,41986,38881,41989, 9771,41941, 14,41941, 38881,41995,38897,41941,30349,41941,26857,41941,26933,41941, 9777,41941, 40077,41941,31598,41941,35931,41941,37519,41941,35690,41941,40651,41941, 38955,41941,40887,41941,39235,41941,35895,42025,15879,42025, 4787,42025, 8982,41941, 668,41941,26625,42035, 9731,42035, 1419,41941, 9731,42041, 26625,42041,40471,41941,38931,41941,40037,41941,40851,41941,37617,41941, 37899,41941,39457,41941,36773,42059,39429,41941,27021,41941, 375,41941, 35187,42066,31103,41941,26625,42070, 9195,41941, 483,41941,39433,41941, 37241,42079, 587,41941, 1,42083,35187,42083, 9,42082, 9731,42089, 26625,42089, 6,41941, 2,42095,21605,42097,38305,42099, 5,42094, 38881,42103,42101,42103, 2,42094,38305,42109, 7,41940, 9459,42113, 8953,42113, 3997,42113, 4067,42113, 8277,42113, 3867,42113, 9,41941, 587,42126, 9731,42129,26625,42129, 17,41941, 8861,42134,26625,41941, 31103,42138, 8861,41941, 7,42143, 17,42142,35187,41941, 375,42148, 9731,41941, 7,38304,39023,42155,41231,42155,25445,42155, 1,42155, 2,42162, 3,42162,38903,42167,38971,42167,39161,42167,40855,42167, 18967,42167, 2,42163, 3,42163, 5,42155, 2,42182, 3,42182, 2,42183,42187,42189, 3,42183,42185,42193,21604,42155,18967,42197, 39161,42197,38971,42197,38903,42197,40855,42197,39175,42155,38987,42155, 40881,42155,38925,42155,22779,42155,22243,42155,28063,42155,41303,42155, 31598,42155,25299,42155, 357,42155, 367,42155, 471,42155, 1249,42155, 35690,42155,37519,42155, 272,42155, 1476,42155, 280,42155, 949,42155, 1517,42155,40387,42155,40571,42155,40033,42155,38939,42155,21087,42155, 20326,42155, 9704,42155, 9304,42155,35931,42155,40998,42155, 253,42155, 265,42270, 375,42155,35187,42274,31103,42155,26625,42278,25381,42155, 10081,42283,41417,42155, 1369,42287,26625,42155,31103,42290, 9617,42155, 9,42294, 53,42155, 265,42298,20273,42155, 9,42302,37899,42155, 37617,42155, 1471,42155, 265,42310, 587,42155,35187,42315,38233,42155, 38004,42155,36773,42155,37845,42322,38056,42155,39019,42327,37145,42327, 37844,42155,40305,42333,37933,42155, 483,42155,37845,42155,36773,42340, 40999,42155, 305,42155,21605,42347, 713,42155, 9195,42350,21605,42351, 9195,42155, 713,42356, 2,42155, 1,42360, 8229,42361,40987,42361, 35187,42361,36773,42369,35187,42360,39019,42373,37145,42373, 3,42155, 42179,42379, 1,42379, 7,42379, 15,42385,38305,42387, 1,42378, 38903,42391,38971,42391,39161,42391,40855,42391,18967,42391,42389,42391, 7,42378,40704,42405,42391,42407, 9,42405,38305,42410,42391,42413, 38305,42405, 9,42416,42391,42419,40987,42378, 1369,42379,35187,42378, 40305,42427, 25,42155,21605,42431, 2,42154, 1,42435,42379,42436, 42382,42435,42423,42435,42269,42435,42333,42435,42427,42435,42379,42435, 1,42450,40987,42451,35187,42451, 3997,42435, 4067,42435, 9459,42435, 8953,42435, 8277,42435, 3867,42435, 3,42154,42165,42471,42363,42471, 42345,42471,42366,42471,26219,42471, 8647,42471,42341,42471,42368,42471, 19396,42471,42361,42471, 1,42491,40987,42490,35187,42490,41417,42471, 483,42471,18967,42471, 9,42502, 9,42471,18967,42506,40987,42471, 42361,42510,35187,42471,42361,42514,32805,42155, 265,42155, 253,42520, 1471,42520, 53,42520,40987,42155, 3,42528,42435,42531, 3,42529, 42361,42535,35187,42155, 7,42539,38305,42541, 2,42543, 2,42542, 2,42541,38305,42548, 2,42540, 1368,42539, 375,42538, 1369,42539, 2,42538,39019,42561,38305,42560,42559,42565,37145,42561, 3,42538, 40305,42571,42545,42571,42435,42571, 3,42539,40277,42579,39315,42579, 7,42579,38305,42585,42561,42587,42551,42579,42547,42579,42561,42579, 42361,42579, 2,42539, 7,42598,42571,42599,37845,42599, 9,42155, 20273,42606, 9617,42606, 6,38304,40509,42613,31103,42615,21604,42613, 40471,42613,40851,42613,40037,42613,38931,42613, 8982,42613,27979,42613, 483,42631,41941,42631,40957,42613,37933,42637,41503,42613, 483,42641, 8861,42613, 17,42644,17423,42613, 1011,42649, 4745,42613, 1011,42653, 9875,42613, 1011,42657, 1471,42613,36773,42613, 483,42663,37844,42613, 40305,42667,37979,42613,41941,42671, 1369,42613,38057,42675, 331,42613, 17,42678, 1325,42613, 17,42682, 334,42613, 1328,42613, 8337,42613, 483,42691,20103,42613, 483,42695, 53,42613, 393,42613, 1359,42613, 3,42613, 483,42705,35187,42704,40305,42709,10257,42705,37357,42705, 2,42613, 62,42613, 59,42613, 17,42720,20501,42613, 1011,42725, 253,42613, 3,42612,40975,42731,40103,42731,27979,42731,40519,42731, 40011,42731,16381,42731,13325,42731,26293,42731, 8685,42731,41503,42731, 1369,42731, 4569,42731,35843,42731,19513,42731, 3863,42731, 9955,42731, 20697,42731, 4137,42731,37019,42731, 8401,42731,20219,42731, 4063,42731, 14625,42731,37377,42731,10273,42731,18967,42613, 165,42783, 241,42613, 35187,42613, 3,42788,40305,42791, 3,42789,40277,42795,39315,42795, 17,42613, 8861,42800, 331,42800, 1325,42800, 59,42800, 7,38305, 25004,42810,25005,42810,25184,42810,25185,42810, 264,42811, 5,42811, 0,42822, 3,42822, 1,42810, 4,42829,25004,42811,42815,42833, 25184,42811,42819,42837,25005,42811,42813,42841,25185,42811,42817,42845, 41493,42811,41622,42811,25367,42810,30748,42810,39650,42811,42752,42811, 38673,42811,38675,42811,39823,42811,39783,42811,27533,42811,26625,42869, 331,42811,35187,42873,41559,42811, 1369,42876, 767,42811,18967,42881, 41019,42811,37899,42885,37617,42885,35931,42885,27021,42885,30091,42885, 9195,42885,25793,42811,30091,42899,27021,42899,37845,42811,42667,42905, 59,42811,35187,42909, 1325,42811,35187,42913,37897,42811,17125,42810, 30091,42810,25793,42921,41019,42921, 265,42920, 1369,42811,30091,42929, 41559,42928,20103,42929, 8337,42929,36773,42929,42731,42928,39633,42928, 42707,42811,42704,42811, 483,42947,39633,42811, 1369,42950,39749,42811, 483,42955, 1275,42811, 265,42810,40411,42961,30091,42960,21605,42810, 26331,42967,25793,42967,23755,42967,27805,42967,39633,42967,42731,42967, 41559,42967,41019,42967, 8495,42967,42731,42811, 1369,42986, 241,42810, 375,42991, 9805,42991,18967,42810, 1141,42997, 33,42997, 1447,42997, 265,42811,35187,43005, 9377,43005, 9533,43005,37145,43005,21605,42811, 34311,43015,42619,43015,26625,43015,24545,43015, 9731,43015, 2,42810, 3,42810, 0,43028,43005,43031, 295,43029, 1108,43029,35927,43029, 38155,43029,37611,43029, 9,43029, 1011,43044, 1011,43029, 9,43048, 2,42811,42831,43053, 5,43053,42829,43057,36256,43053, 9,43053, 35187,43062,35187,43053, 9,43066, 3,42811, 5,43070,22807,43071, 37663,43071,42613,43070, 483,43079, 241,43071, 9,43083,37845,42810, 41559,43087,38389,43087,42731,43087,39633,43087,41019,43087,42613,42811, 32805,43099,37845,43098,37845,43099,37844,43098,43105,43107,37844,43099, 43103,43111, 3,43099, 1369,43115, 3,43098, 483,43119, 15,42811, 20273,43123, 9617,43123,35187,42810, 7,43129, 2,43130, 2,43131, 38305,43129, 3,43136,43135,43139, 3,43137,43133,43143, 1368,43129, 43143,43147, 59,43129, 1325,43129, 331,43129, 265,43129, 2,43129, 7,43158,43143,43161, 3,43129,38305,43164,43135,43167,37408,38305, 7,43171, 2,43172,40999,43175, 2,43173,40101,43179,41017,43179, 1368,43171,40999,43185, 59,43171, 1325,43171, 331,43171, 265,43171, 2,43170,37783,43197, 2,43171, 7,43200,40999,43203,37617,43201, 3,43171,38305,43208,43179,43211, 3,38305,43129,43214,43135,43217, 1,43214, 1011,43221,42041,43221, 1418,43221,41941,43227,42035,43221, 669,43221,41941,43233,42089,43221,42129,43221, 1369,43221, 15,43240, 41941,43243, 15,43221, 1369,43246,41941,43249,11989,43215, 9,43253, 13737,43215, 9,43257,37357,43215,10257,43215,38118,43215,38132,43215, 37544,43215,37409,43215, 483,43270, 113,43215, 587,43275,37345,43215, 37241,43214,40993,43281,40993,43215,37241,43285, 9,43215,38057,43288, 483,43215,38057,43292,37409,43292,10289,43215, 15,43214, 165,43301, 11,43214, 9,43214,11251,43307, 5177,43307, 17,43214, 113,43313, 11,43215, 165,43215, 7,43214, 0,43321, 4,43322, 4,43321, 0,43326,35186,43321, 295,43321, 1108,43321,35927,43321,38155,43321, 37611,43321, 9,43321, 1011,43342, 1011,43321, 9,43346, 7,43215, 21604,43351, 1,43351, 3,43354, 3,43351, 1,43358, 15,43351, 38305,43363,43353,43365,43357,43365,43361,43365, 1011,43363,37409,43214, 43179,43375,41941,43215,37408,43379, 7,43379,35187,43382,35187,43379, 6,43386, 7,43386, 6,43387,43391,43393, 7,43387,43389,43397, 1011,43215,37408,43401, 7,43401,35187,43404,35187,43401, 7,43408, 38057,43215,40097,43413,40969,43413, 7,43413, 9,43412, 483,43412, 35187,43214,40305,43425,40275,43425,38305,43425, 6,43430,43413,43433, 6,43425,38305,43436,43413,43439,41941,43425, 6,43443, 7,43443, 6,43442,43447,43449, 7,43442,43445,43453, 1011,43425, 7,43457, 37844,38305,42336,43461,42917,43461,42905,43461,39013,43461,40305,43461, 40275,43461,37933,43461,42155,43474,42155,43461,37933,43478, 6,43460, 41941,43461, 6,43485, 7,43485, 6,43484,43489,43491, 7,43484, 43487,43495, 1011,43461, 7,43499, 2,38305,41603,43503,41686,43503, 41825,43503,41828,43503,42541,43502,42579,43513,16936,43503,36400,43503, 36439,43519,36348,43503, 6,43523,36413,43525, 6,43522,36439,43529, 36439,43523,41744,43503,41688,43503,41605,43503,41706,43503,41620,43503, 1,43503, 1275,43544, 4,43544, 7,43544,41417,43551, 7,43545, 39633,43555,41559,43555,42731,43555,41019,43555, 1,43502,41692,43565, 41607,43565,41653,43565,41417,43570,41417,43565,41653,43574,41502,43565, 41559,43579,41019,43565, 7,43582,41559,43585, 7,43583,41417,43589, 7,43565,41019,43593,41653,43595,41019,43592,41559,43599, 5,43502, 21605,43603,42810,43604,42811,43605,43607,43609,42811,43604,42810,43605, 43613,43615,41692,43503,35187,43618,41607,43503,35187,43622,41360,43503, 41559,43627,41820,43503,41559,43631,41544,43503,41559,43635,35760,43503, 8315,43503,37408,43502,37783,43643,42538,43503,42601,43647,42553,43647, 42555,43647,41742,43503,41417,43654,41486,43503,41653,43658,41417,43503, 41827,43662,41742,43662,41653,43662,35187,43668,35187,43662,41653,43672, 37783,43503,37325,43502,42795,43679,42579,43679,41502,43503,41559,43685, 35187,43687,35187,43684,41559,43691,37241,43503,37409,43695,41019,43697, 41381,43503,41653,43700, 1275,43503, 1,43704,35187,43704, 9,43705, 9731,43711,43221,43711,43549,43711,26625,43711, 587,43503,42811,43721, 35895,43723,15879,43723, 4787,43723,41653,43503, 1,43731,41417,43733, 41381,43730,41486,43730,41417,43730,35187,43740,35187,43730,41417,43744, 9,43502,36727,43749,36079,43749,37895,43749,41827,43503,41417,43756, 6,43502,39616,43761,39614,43761,39578,43761,39901,43761,41282,43761, 41266,43761,41270,43761,39961,43761,39981,43761,35718,43761,39869,43781, 41019,43761,35895,43784,15879,43784, 4787,43784,15879,43761,39489,43792, 41019,43792, 4787,43761,39489,43798,41019,43798,35895,43761,39489,43804, 41019,43804, 587,43761,35187,43810,39869,43813,35187,43761, 587,43816, 39869,43819, 587,43817,39489,43823,41019,43823,39489,43761,15879,43828, 4787,43828,35895,43828, 7,43502, 6,43503,36348,43838,36439,43841, 36348,43839,36429,43845, 7,43503,41817,43848,43817,43849,41019,43853, 4,43849, 0,43856,43784,43859,41019,43859,43761,43862,43761,43859, 41019,43866, 0,43849, 4,43870,43784,43873,41019,43873,43761,43876, 43761,43873,41019,43880, 1,43848,41417,43885,35186,43849,43784,43889, 41019,43889,43761,43892,43761,43889,41019,43896,41816,43848,41559,43901, 41019,43848,41559,43905,35187,43907,35187,43904,41559,43911,41019,43849, 41827,43915,43851,43915,41742,43915,41653,43915,35187,43922,35187,43915, 41653,43926,35187,43848,41417,43931,41019,43930,41559,43935,41019,43931, 41653,43939,37409,43502,41354,43943,40165,43943,41019,43943,37241,43948, 37241,43943,41019,43952,37408,43503,41417,43957,37663,43957,41019,43956, 41559,43963,41019,43957,41653,43967,41816,43503, 6,43970, 7,43970, 41559,43975, 6,43971,43975,43979, 7,43971,43973,43983,41417,43983, 41019,43503, 1,43989, 7,43990,41417,43993, 7,43991,41559,43997, 37408,43988,41559,44001,37408,43989,41381,44005, 7,43989,41381,44009, 41486,44009, 1,44008,41417,44015,41417,44009,35187,44018,35187,44009, 41417,44022, 7,43988,41559,44027,35187,44029,35187,44026,41559,44033, 35187,43988, 6,44036, 7,44036,41559,44041, 6,44037,44041,44045, 7,44037,44039,44049,41417,44049,21605,43503, 7,44055, 265,44057, 35187,43503,41692,44060,41607,44060,41502,44060,41559,44067, 1275,44060, 41653,44060,41417,44072,36945,44061,41019,44077,41417,44060,41653,44080, 6,44061,41922,44085,43413,44085,41019,44085,36773,44090,36773,44085, 41019,44094, 7,44061,41559,44099,42731,44099,39633,44099,41019,44099, 6,44060,44099,44109, 7,44060,41417,44113,41019,44112,41559,44117, 44085,44113,41019,44113,41653,44123,41019,44060, 6,44126, 7,44126, 41559,44131, 6,44127,44131,44135, 7,44127,44129,44139,41417,44139, 36773,44061,41417,44145, 7,44145,41019,44149,35187,43502,41217,44153, 41472,44153,29229,44153,41099,44153,36429,44153,42559,44153,41417,44153, 37145,44166,37783,44153,37214,44153,41019,44173, 7,44153,41019,44177, 37145,44179,37145,44176,41019,44183,37145,44153,41417,44186, 7,44186, 41019,44191,38056,38305,41472,44195,41217,44195,41099,44195,29229,44195, 36429,44195,42559,44195,35187,44195, 6,44209,43413,44211,41417,44195, 37145,44214,37783,44195,37214,44195,41019,44221, 7,44195,41019,44225, 37145,44227,37145,44224,41019,44231,37145,44195,41417,44234, 7,44234, 41019,44239, 6,38305,42453,44243,42493,44243,42472,44243,42439,44243, 42474,44243,42441,44243,42363,44243,42471,44256,42381,44243,42165,44243, 42471,44262,42325,44243,42330,44243,42343,44243,42321,44243,42319,44243, 42371,44243,42376,44243,42568,44243,42447,44243,42484,44243,42054,44243, 42056,44243,44171,44243,43645,44243,43960,44243,44219,44243,43201,44243, 37617,44298,43206,44243,38711,44243,43199,44243,42605,44243,40231,44243, 43677,44243,40959,44243,10586,44243,10827,44243,42594,44243,42603,44243, 42577,44243,42596,44243, 6664,44243, 6243,44243, 9780,44242, 566,44242, 566,44243, 567,44242,44337,44339,43517,44243, 9781,44242,42012,44243, 36303,44242,36303,44243,26970,44242,26971,44242,43639,44243, 4593,44243, 6625,44358, 3113,44243, 3023,44243, 4736,44243, 6653,44243,42518,44243, 3251,44243,42516,44243,42486,44243,42449,44243,42496,44243,42456,44243, 19257,44243,19243,44243,43425,44242,43413,44389,40511,44243,17452,44243, 42085,44243,43707,44243,42087,44243,40961,44243,43709,44243,44071,44243, 36099,44243,36098,44242,44409,44411,36099,44242,36098,44243,44415,44417, 43605,44243,43222,44242,43223,44243,44423,44425,43222,44243,43223,44242, 44429,44431,42199,44243,24081,44243,42181,44243,42383,44243,42435,44441, 42401,44243,42177,44243,43547,44243, 5,44242,42283,44451,25380,44451, 42155,44455, 1369,44451,21605,44458,42155,44461,21605,44451, 1369,44464, 42155,44467,42373,44243,37145,44470,42561,44243,37145,44474,42579,44474, 42327,44243,37145,44480,27514,44243,42490,44243,35187,44486,42451,44243, 35187,44490, 413,44243,32805,44243,42155,44496,28547,44243,42064,44243, 42138,44243,40517,44243,40543,44243,30294,44243,38004,44243,43461,44513, 38232,44243,42155,44517,38005,44243,42155,44521,30749,44243, 9780,44243, 44345,44527,26970,44243,44355,44531, 6625,44243, 4593,44534, 33,44535, 9781,44243,44333,44541,25005,44243,26971,44243,44353,44547,25185,44243, 25589,44243,42074,44243,42152,44243,10831,44243, 77,44243, 120,44243, 506,44243,38041,44243, 5101,44243,16989,44243,10511,44243, 4931,44243, 5267,44243,16981,44243,13017,44243,12705,44243,13673,44243,18391,44243, 18617,44243,14599,44243, 9366,44243,36302,44243,18217,44243,42332,44243, 42435,44599,42570,44243,42435,44603,42426,44243,42435,44607,41539,44243, 41720,44243, 9132,44243, 1216,44243,36302,44242, 3,44618,44351,44621, 30748,44243,30748,44242,44525,44627,30749,44242,44625,44631,16931,44243, 35931,44243,41941,44636,39600,44243,42500,44243,18929,44243,38669,44243, 38677,44243,17019,44243,39941,44243,39955,44243,27021,44243, 483,44656, 41941,44656,37844,44242,44351,44663,41653,44243, 483,44666,43413,44243, 43425,44671,42514,44243,42361,44674,42368,44243,42471,44678,42361,44243, 42579,44682,42514,44682,42471,44682,35187,44688,35187,44682,42471,44692, 20234,44243, 8444,44243, 567,44243,44335,44701,16937,44243, 11,44705, 1369,44705,26625,44243,41941,44710,41941,44243,37899,44714,37617,44714, 35931,44714,27021,44714,26625,44714, 9195,44714, 9731,44714,43957,44243, 37663,44730,20103,44243, 483,44734, 8337,44243, 483,44738, 9533,44243, 4727,44243, 25,44744,10527,44243, 25,44748, 4541,44243,38128,44243, 38057,44243,42155,44757,37145,44759,37145,44756,42155,44763, 587,44756, 37845,44243,43461,44769,36773,44771,36773,44768,43461,44775, 25,44243, 10527,44778, 4727,44778, 113,44778, 9195,44243,41941,44786, 483,44786, 37782,44243,43197,44793,43643,44793,38709,44793,17451,44243, 1011,44800, 35688,44243,36910,44243,36923,44243,37899,44243,41941,44810,37617,44243, 41941,44814,43201,44814, 9731,44243,41941,44820, 8997,44243, 483,44824, 66,44243, 33,44829, 483,44243,27021,44832,30091,44832, 241,44832, 9195,44832,41653,44832, 8997,44832,42471,44832,39489,44832,20103,44832, 8337,44832,36773,44832, 903,44243, 1011,44856,18967,44243, 567,44861, 566,44860,44863,44865, 566,44861, 567,44860,44869,44871, 241,44243, 483,44874,42425,44243,42378,44243,42435,44881,35187,44883,35187,44880, 42435,44887, 1369,44881,36773,44243,37845,44892,43461,44895, 483,44892, 37845,44893,41019,44901,37145,44243,42327,44904,42373,44904,42561,44904, 38057,44904,42155,44913,42341,44243,42471,44916,30091,44243, 483,44920, 113,44243, 25,44924,35187,44924,17125,44243,37663,44243,43957,44932, 39489,44243, 483,44936,39943,44243, 1369,44941, 587,44243,43215,44945, 35895,44947,15879,44947, 4787,44947,38057,44944, 8449,44243,20237,44243, 265,44242,40399,44961, 11,44961,42471,44243,42165,44966,42363,44966, 42341,44966,42368,44966,42361,44966,35187,44976, 483,44966,35187,44966, 42361,44982,20834,44243, 1011,44243,17451,44988,35187,44988, 903,44988, 20763,44988,20763,44243, 1011,44998, 257,44243,42579,44243,42561,45004, 42361,45004, 2,44242,39616,45011,39614,45011,39578,45011,39901,45011, 41282,45011,41266,45011,41270,45011,39961,45011,39981,45011,35718,45011, 39869,45031,41019,45011,35895,45034,15879,45034, 4787,45034,15879,45011, 39489,45042,41019,45042, 4787,45011,39489,45048,41019,45048,35895,45011, 39489,45054,41019,45054, 587,45011,35187,45060,39869,45063,35187,45011, 587,45066,39869,45069, 587,45067,39489,45073,41019,45073,39489,45011, 15879,45078, 4787,45078,35895,45078, 3,44242,36302,45087,44349,45089, 35187,45086,44351,45093, 2,44243, 14,45097, 5,45097, 6,45100, 6,45097, 5,45104,21605,45097,38305,45109,45099,45111,45103,45111, 45107,45111,43215,45097,43325,45119,43329,45119,35895,45119,15879,45119, 4787,45119,43331,45119,35187,45119,43321,45133,35187,45096,39313,45137, 40157,45137,43281,45137,43215,45137,37241,45145, 3,44243,42539,45148, 38305,45149,37408,45152,37408,45153,45067,45149,41019,45159, 4,45149, 0,45163,38305,45163, 0,45162,45034,45169,41019,45169,45011,45172, 45011,45169,41019,45176,45119,45169, 0,45149,38305,45183, 4,45182, 45034,45187,41019,45187,45011,45190,45011,45187,41019,45194,45119,45187, 0,45148,38305,45148, 1,45148,45176,45205,45194,45205,45169,45205, 45011,45210,45187,45205,45011,45214,45159,45205,45011,45205,45169,45220, 45187,45220,35186,45148,35186,45149,38305,45229, 7,45231,45220,45229, 45205,45229,45011,45236,45034,45229,41019,45229,45011,45242,45011,45229, 45205,45246,41019,45246,45119,45229, 1,45149,45165,45255,45011,45257, 45167,45255,45011,45261, 5,45149,45185,45265,45011,45267,43171,45149, 37617,45271,42538,45148,42435,45275,37409,45148,38709,45279,43197,45279, 45155,45279,43643,45279,42155,45148,42435,45289,35187,45291,35187,45288, 42435,45295, 1369,45289, 1011,45149, 483,45301, 11,45148, 33,45305, 37409,45149,45157,45309,43957,45309, 11,45149, 25,45315,35187,45315, 42155,45149,42579,45321,45151,45321,42514,45321,42471,45321,35187,45328, 35187,45321,42471,45332,45066,45149,45201,45337,45203,45337,35187,45149, 45201,45343,45011,45345,45203,45343,45011,45349,45011,45342,45201,45353, 45203,45353,45011,45149,35187,45358,45201,45361,45203,45361,35187,45148, 40217,45367,45233,45367,42155,45366,42435,45373,42155,45367,42471,45377, 37845,44242,41922,45381,43413,45381,44595,45381,44993,45381,41019,45381, 36773,45390,36773,45381,41019,45394,38056,44243,39313,45399,40157,45399, 43281,45399,43215,45399,37241,45407,37844,44243,40217,45411,42155,45410, 42435,45415,42155,45411,42471,45419,42538,44243, 3,45422,42435,45425, 3,45423,42361,45429,42155,44243,32805,45432,37845,45432,37845,45433, 37844,45432,42435,45441,45439,45441,37844,45433,42341,45447,45437,45447, 3,45433,42341,45453,42368,45453,42361,45453,35187,45458,35187,45453, 42361,45462, 483,45453, 3,45432,42435,45469,35187,45471,35187,45468, 42435,45475, 1369,45469,35187,45432, 3,45480,42435,45483, 3,45481, 42361,45487, 11,44243, 8861,45491, 3,45490, 33,45495, 3,45491, 113,45499, 331,45491, 1325,45491, 59,45491,35187,44243,42490,45508, 42451,45508,38305,45508, 7,45515, 2,45517, 2,45516, 2,45515, 7,45522, 1368,45515, 1011,45508,45381,45529,42378,45508,42435,45533, 42471,45508,42361,45536,37285,45509,41019,45541,42361,45508,42471,45544, 113,45508, 2,45509,41354,45551,40165,45551,38305,45551, 7,45557, 41019,45551,37241,45560,37241,45551,41019,45564, 3,45509,45519,45569, 2,45508,40157,45573,39313,45573,43281,45573,43215,45573,37241,45581, 3,45508,40217,45585,45521,45585,45525,45585,45559,45585,45527,45585, 42155,45584,42435,45597,42155,45585,42471,45601,42155,45508, 3,45604, 42435,45607, 3,45605,42361,45611,37409,44243,43503,45615,37663,45617, 3,45615,43201,45621, 3,45614,38709,45625,43197,45625,43643,45625, 35187,44242, 3,45632,44351,45635,35187,38305,37214,45639, 2,45641, 39019,45643,39021,45641,37286,45639,35890,45638,35891,45639,45651,45653, 35891,45638,35890,45639,45657,45659,38152,45638,38153,45639,45663,45665, 38296,45638,38297,45639,45669,45671,38153,45638,38152,45639,45675,45677, 38297,45638,38296,45639,45681,45683,37283,45639,42675,45639,37282,45639, 42674,45639,37899,45638,37885,45695,38293,45639,37885,45639,37899,45701, 44945,45639,38292,45639,44944,45639,37287,45639,38173,45638,38172,45639, 45713,45715,38303,45638,38302,45639,45719,45721,38173,45639,38172,45638, 45725,45727,38303,45639,38302,45638,45731,45733,45096,45639,45149,45639, 7,45738,45367,45741,45097,45639,37241,45639, 2,45747, 2,45746, 587,45746,42613,45639, 1369,45754,38271,45639, 1369,45758,44243,45639, 2,45763, 2,45762, 587,45762, 136,45639, 137,45639, 1530,45638, 842,45638, 669,45639, 1419,45639, 843,45639,39085,45783,45777,45783, 1531,45639,45775,45789, 1530,45639, 843,45638, 842,45639,45795,45797, 1531,45638,45793,45801, 1368,45639,45411,45805,40999,45805,45367,45805, 45585,45805,42613,45805,37845,45805,44243,45817, 586,45639,39847,45821, 39142,45821,39085,45821, 483,45826,37241,45821, 483,45821,39085,45832, 586,45638,38675,45837,39823,45837,39783,45837,39749,45837, 483,45845, 1418,45639, 668,45639, 587,45638,37885,45853,37202,45853,37145,45853, 483,45858, 483,45853,37145,45862, 587,45639,37241,45866,44243,45866, 9,45866, 483,45639, 587,45875,37145,45877, 1369,45639,35760,45880, 35761,45881,45883,45885,35760,45881,35761,45880,45889,45891,42613,45880, 38271,45880, 15,45880, 9,45639, 2,45900, 2,45901, 587,45900, 265,45639, 375,45909, 15,45639, 1369,45912, 7,45639,40956,45917, 44060,45917,40957,45917,44061,45917,43502,45917,37844,45917,35187,45917, 3,45930,43503,45930, 3,45931,45927,45937, 1369,45931,38305,45917, 2,45942,45937,45945,37845,45942, 2,45943,45933,45951,45929,45951, 587,45943,45149,45917,37145,45959,45227,45959,37845,45917,38305,45964, 43503,45917,35187,45968, 375,45917,45148,45917, 2,45917,40101,45977, 41017,45977,38305,45976,45937,45983,44904,45977,45569,45977,43375,45977, 39019,45977,44243,45977,37145,45994,37145,45977,44243,45998, 3,45917, 35187,46002,45951,46005,44243,46002, 3,45916,45943,46011, 7,46011, 38305,46015,45977,46017,45994,46011,45959,46011,45967,46011,45919,46011, 45949,46011,45925,46011,37241,46011,45977,46011,44243,46034,44243,46011, 45977,46038, 2,45916,45931,46043,40999,46043,45975,46043,45367,46043, 45585,46043,46009,46043,45971,46043,45921,46043,45935,46043,45923,46043, 45411,46043,42613,46043,46003,46043,44243,46069,37845,46043,44243,46073, 44243,45917, 3,46076,46043,46079, 3,46077,45977,46083, 6,45638, 45998,46087,46073,46087,45817,46087,37844,46087,46043,46095,45805,46095, 35187,46087, 3,46101,45977,46103, 3,46100,46043,46107,45805,46107, 37145,46087,45977,46112,45977,46087,37145,46116, 3,46087,35187,46120, 46043,46123,45805,46123,45917,46121,37145,46129,45917,46087,35187,46132, 2,46135, 2,46134,38057,46132,38056,46132, 2,46133,46141,46145, 3,46133,46139,46149,46143,46149, 2,46132,35187,46154,46149,46157, 46149,46155, 3,46132,46137,46163,46145,46163, 3,45639, 5,46169, 6,46171, 4,46168, 0,46168, 5,46168, 1,46168,45983,46169, 45945,46169,43679,46169,45927,46169,40277,46169,45749,46169,45765,46169, 39315,46169,45905,46169,37241,46169,45977,46169,42613,46203,43848,46169, 256,46169, 6,46169,46175,46211,46177,46211,37145,46211, 7,46169, 46179,46219,46181,46219,41019,46219,45639,46218, 2,46227,38305,46219, 46229,46231, 3,46231,46227,46235,45977,46231,43503,46218, 241,46218, 38271,46219, 7,46168,37241,46247,38057,46169,38305,46251,46211,46253, 43503,46169, 6,46256, 7,46256, 6,46257,46261,46263, 7,46257, 46259,46267, 241,46169, 7,46270, 2,45638,41472,46275,41217,46275, 46175,46275,46211,46280,46177,46275,46211,46284,46212,46275,46214,46275, 46221,46275,46223,46275,46173,46275,45930,46275,46043,46299,46045,46275, 46216,46275,46225,46275,41099,46275,46032,46275,45711,46275,46200,46275, 45745,46275,46248,46275,46245,46275,35187,46275,45917,46322,46043,46325, 45917,46323,46011,46329,45830,46275,29229,46275,45773,46275,36429,46275, 45895,46275,45897,46275,45687,46275,45693,46275,45705,46275,45707,46275, 45849,46275,45779,46275,42559,46275,45899,46275,45915,46275,45757,46275, 45761,46275,45941,46275,41417,46275,37145,46368,45821,46275,37241,46372, 46011,46275,37241,46376,46247,46275,37241,46380,45881,46275,42613,46385, 37241,46275,46011,46388,46169,46388,46247,46388,45821,46388,46211,46275, 46175,46398,46177,46398,37145,46398,37783,46275,44243,46407,45917,46275, 35187,46410,46043,46413,37214,46275,41019,46417,46218,46275,46179,46421, 46181,46421,41019,46421, 7,46275,41019,46429,37145,46431,46169,46429, 46175,46435,46177,46435,37145,46435,37145,46428,41019,46443,46169,46428, 46179,46447,46181,46447,41019,46447,37145,46275,41417,46454,46211,46454, 7,46454,41019,46461,46169,46275,35187,46464, 6,46467, 6,46466, 38305,46465,46211,46473,38271,46464,44243,46465,38270,46464,37241,46464, 6,46465,46477,46485, 7,46465,46471,46489,46481,46489, 6,46464, 46473,46495,35187,46494,46489,46499,46489,46495, 7,46464,46179,46505, 46181,46505,46469,46505,46485,46505,41019,46505, 2,45639,42671,46517, 39429,46517,44814,46517,44810,46517,44636,46517,37241,46516,40077,46517, 44243,46516,46003,46517,37241,46535, 9,46516,44243,46517,37617,46540, 37899,46540,35931,46540,35931,46517,44243,46548,37617,46517,44243,46552, 37899,46517,44243,46556, 7,46517,44243,46561, 7,46516,46107,46565, 46123,46565,46095,46565,40999,46565,45585,46565,45411,46565,45367,46565, 42613,46565,37845,46565,46087,46583,44243,46583,37845,46517,46211,46589, 41417,46589, 7,46589,41019,46595, 3,45638,45951,46599,45942,46599, 46011,46603,46013,46599,46066,46599,46540,46599,40305,46599,46529,46599, 45751,46599,46533,46599,45767,46599,46580,46599,46563,46599,45649,46599, 45737,46599,38305,46599,45917,46630,46011,46633,45917,46631,46043,46637, 45814,46599,45771,46599,45869,46599,45871,46599,45689,46599,45691,46599, 45699,46599,45709,46599,45851,46599,45781,46599,40275,46599,46539,46599, 45903,46599,45873,46599,45907,46599,45753,46599,45769,46599,45957,46599, 45805,46599,42613,46676,46043,46599,42613,46680,46565,46599,42613,46684, 45867,46599,37241,46689,42613,46599,46043,46692,46565,46692,45805,46692, 45917,46599,38305,46700,46011,46703,46560,46599,44243,46599,46517,46708, 7,46599,38305,46713,46517,46715,46517,46712,41941,46599, 6,46721, 7,46721, 6,46720,46725,46727, 7,46720,46723,46731, 1011,46599, 7,46735,46517,46599,38305,46738,35187,46739, 6,46742, 6,46743, 44243,46738,38271,46739,38270,46739,37241,46739, 6,46739,35187,46756, 46741,46757, 7,46739,41019,46763,46747,46763, 6,46738,46763,46769, 46751,46769, 7,46738,46759,46775,46745,46775,46757,46775,46753,46775, 6,45639, 7,45638,43214,46787,45977,46789,38305,46787, 3,46793, 46043,46795,46565,46795,45805,46795, 3,46792,45977,46803, 59,46787, 1325,46787, 331,46787, 265,46787, 2,46787, 7,46814,46795,46817, 3,46787,38305,46820,45977,46823,46785,46787,35187,46827, 2,46828, 2,46829,38057,46827,38056,46827, 2,46827,35187,46838, 3,46827, 46833,46843, 2,46826,46843,46847,46835,46847, 3,46826,46841,46853, 46831,46853,46839,46853,46837,46853, 0, 6,13135,46863,13169,46864, 4871,46863, 4893,46868,13172,46863, 4894,46863,13136,46863,13143,46877, 4872,46863, 4879,46881,13145,46863, 4881,46863,37417,46863,38056,46888, 38057,46889,46891,46893,38057,46888,38056,46889,46897,46899,17176,46863, 17380,46863,16950,46863,17058,46863,16948,46863,17056,46863,16974,46863, 17072,46863,16996,46863,17086,46863, 3348,46863,18291,46863, 7316,46863, 8455,46863, 8343,46863, 8353,46863,13139,46863,13175,46863,13155,46863, 13517,46863,15197,46863,15485,46863,15512,46863,15595,46863,15203,46863, 5757,46863, 5453,46863, 5471,46863, 5455,46863, 4863,46959, 5507,46863, 12569,46863,12387,46863,12551,46966,12552,46863,16995,46863,16941,46863, 16977,46974,16978,46863,17017,46862,17016,46862,19836,46863,19857,46985, 19815,46863, 4,46988,19857,46991, 4,46989,19843,46995,27930,46863, 27895,46999,27857,46863, 4,47002,27895,47005, 4,47003,27907,47009, 36303,46862,36325,47013,27128,46863, 9136,46863,27266,46863,27163,46863, 34310,46863,34447,47025,46516,46863,46599,47029,33454,46863,33368,46863, 28027,46863,28111,46863,28117,46863,26928,46863,24253,46863,30569,46863, 30316,46863,28213,46863,26525,46863, 9137,46863, 273,46863, 1477,46863, 281,46863,17011,46863, 5043,46863,15503,46863, 8997,47066,24558,46863, 26575,46863,41877,46863, 120,46863, 77,46863,16977,46863,16941,47080, 9262,46863,14813,46863,26605,46863,41923,46863, 8843,46863,37131,46863, 41907,46863,26591,46863,41893,46863,37113,46863,20255,46863, 9288,46863, 8697,46863, 9275,46863, 8784,46863,19877,46863,41867,46863,20043,46863, 21376,46863,21485,46863,19787,46863,19391,46863,19299,46863,19271,46863, 19283,46863,17010,46863, 5042,46863,36518,46863,40664,46863,17017,46863, 46983,47143, 1516,46863, 948,46863,17016,46863,46981,47151,16972,46863, 903,47154,17070,46863, 1011,47158,17175,46863, 903,47162,17379,46863, 1011,47166, 4213,46863, 375,47170, 8757,46863, 375,47174, 4266,46863, 16865,46863,16873,46863,16867,46863,12642,46863, 8896,46863,14740,46863, 8355,46863, 264,47193, 265,47192,47195,47197, 264,47192, 265,47193, 47201,47203,14515,46863,14517,46863,14519,46863,20201,46863,36979,46863, 20152,46863,36898,46863,20239,46863,37095,46863,21522,46863,38266,46863, 17082,46863, 903,47228,16990,46863,16943,47233, 1011,47232,35780,46863, 29644,46863,43412,46863,15628,46863, 9044,46863, 264,47247, 265,47246, 47249,47251, 264,47246, 265,47247,47255,47257,12484,46863,12486,46863, 12488,46863,12551,46863,12387,47266,12547,46863,12633,46863,12507,46863, 12497,46863,12501,46863,13381,46863,13169,46863,13135,47282, 4893,46863, 4871,47286,12563,46863,27255,46863, 483,47292, 9287,46863, 483,47296, 13119,46863, 264,47300,13143,47303, 264,47301,13169,47307, 4863,46863, 264,47310, 4879,47313, 264,47311, 4893,47317, 7315,46863, 413,47320, 264,47320, 264,47321, 265,47320,47327,47329, 265,47321,47325,47333, 14653,46863, 375,47336,16875,46863,12504,46863,19478,46863,35766,46863, 20044,46863,36534,46863,12566,46863,12391,47353,33338,46863,34447,47357, 45866,46863,46599,47361,25545,46863,40675,46863, 1413,46863, 922,46863, 1281,46863, 247,46863,36303,46863,38299,47377,37897,47377,36335,47377, 35893,47377,20035,46863, 11,47387, 11,47386,36527,46863, 587,47392, 24545,46863, 483,47396,35761,46863, 903,47400,19475,46863, 1011,47404, 1086,46863, 934,46863, 1216,46863,17049,47412,16937,47412, 9766,46863, 5519,46863, 8389,46863, 8861,46863, 3345,47424,12377,47424, 8337,46863, 375,47430, 8374,46863, 8365,46863,20169,46863,36921,46863, 8453,46863, 4863,47443,13119,47443, 9072,46863, 9105,46863, 305,46863,12377,47452, 9731,46863, 483,47456, 8997,46863,15503,47460, 265,47460, 265,47461, 257,47460, 264,47469, 265,47468,47471,47473, 264,47468, 265,47469, 47477,47479, 375,47460,15029,46863,12377,47484, 375,46863,27021,47488, 30091,47488, 9195,47488, 8757,47488, 4213,47488,14653,47488,20103,47488, 36773,47488, 8337,47488, 8997,47488, 241,47488, 6578,46863, 394,46863, 828,46863, 128,46863, 299,46863, 705,46863, 101,46863,28715,46863, 21315,47526, 165,46863, 903,47530,43215,46863,38057,47534, 1505,46863, 1011,47538,30091,46863, 375,47542, 113,46863, 25,47546, 9,47546, 803,46863, 483,47552, 518,46863, 504,46863, 508,46863, 645,46863, 623,46863, 659,46863, 510,46863, 241,47568, 506,46863, 9,47572, 244,46863, 483,47576, 265,46863, 8997,47580, 5041,47580,17009,47580, 8861,47581, 241,46863, 265,47591, 6515,47590, 375,47590, 510,47590, 483,47590, 9,47600, 9,47590, 483,47604, 1011,46863,16990,47608, 17070,47608,17379,47608,40617,47608,16937,47608, 903,47618, 1505,47608, 17049,47608, 903,47624,21315,47608,19475,47608, 587,47608, 903,47608, 16937,47634,17049,47634, 903,46863,16937,47641,16977,47643,17082,47640, 16972,47640,17175,47640,32805,47640,36349,47640,17049,47640, 1011,47656, 165,47640,16937,47640,16943,47663, 1011,47662,38057,47640,35761,47640, 483,47640, 11,47640, 1011,47640,17049,47676,16937,47676,10527,47640, 4727,47640, 6515,47640, 6564,46863, 6685,46863,35187,47690, 11,47691, 6515,46863, 241,47696, 903,47696, 587,47697,10761,46863,10592,46863, 4738,46863,13857,46863, 483,47710,10527,46863, 903,47714, 9,47714, 3345,46863, 413,47720, 8861,47720, 1369,47721, 341,47721, 3747,46863, 1369,47731, 3689,46863, 1369,47735,17000,46863,17090,46863, 2691,46863, 2777,46863, 2793,46863, 2831,46863, 6486,46863, 4415,46863,10493,46863, 13941,46863,10901,46863, 4727,46863, 903,47760, 9,47760, 4819,46863, 483,47766, 6703,46863, 6623,46863, 5759,46863, 7823,46863, 7813,46863, 7761,46863, 7705,46863, 7735,46863, 7727,46863,13904,46863,10600,46863, 4742,46863, 4822,46863, 2875,46863, 2865,46863, 2961,46863, 2949,46863, 2919,46863, 3645,46863, 3609,46863, 3467,46863,17102,46863,17104,46863, 1369,47815, 5041,46863, 265,47819, 265,47818, 4919,46863, 483,47824, 17100,46863,17009,46863, 265,47831, 265,47830,17099,46863, 483,47836, 4920,46863, 6441,46863, 483,47842,17123,46863, 3353,46863, 3691,46863, 10154,46863, 3777,46863, 2847,46863, 2881,46863, 2933,46863, 2929,46863, 2967,46863, 5271,46863, 4923,46863, 3355,46863, 3031,46863, 3121,46863, 20819,46863,37537,46863,20952,46863,37748,46863,20885,46863, 483,47884, 37663,46863, 9,47888,11529,46863, 1010,46862,23717,47895,24522,47895, 24447,47895,23939,47900,23939,47895,24447,47904,22956,47895,23651,47909, 21605,47895, 17,47913,23939,47915, 17,47912,23651,47919, 17,47895, 21605,47923,24447,47925,21605,47922,23651,47929, 264,46862,47135,47933, 47823,47933,47835,47933,47137,47933,47587,47933,47585,47933,47465,47933, 47583,47933,47019,47933,47581,47933,17009,47953, 5041,47953, 8997,47953, 265,46862,47063,47961,47065,47961,47055,47961, 8997,47961, 5041,47961, 17009,47961, 8495,47961, 241,47961, 241,46862, 240,46863, 265,47981, 1,47982, 0,47982, 5521,47983, 5520,47982,47989,47991, 5520,47983, 5521,47982,47995,47997, 0,47983,47985,48001, 1,47983,47987,48005, 264,46863,15193,48009,15475,48009,15579,48009,13119,48008,13143,48017, 4863,48008, 4879,48021,47972,48009,47970,48009,47821,48009,47833,48009, 13507,48009,47968,48009,47467,48009, 53,48009, 1471,48009, 8997,48009, 47961,48042, 253,48009,17009,48009,47961,48048, 5041,48009,47961,48052, 15437,48009, 8997,48057,20501,48009,47961,48009,17009,48062, 5041,48062, 8997,48062,20219,48009,37019,48009,19513,48009,35843,48009,20697,48009, 37377,48009,13119,48009,13135,48083, 4863,48009, 4871,48087,18967,48009, 483,48091, 1369,48009, 9875,48009, 8401,48009, 9955,48009,10273,48009, 4137,48009, 3863,48009, 4063,48009, 241,48009, 413,46863, 3345,48112, 7315,48112,17049,48112,16937,48112,12377,46863, 8861,48122,15029,48122, 305,48122, 713,48122, 25,48122, 587,48123,12387,48135, 11,48123, 257,48123, 253,48123, 1471,48123, 53,48123, 1369,48123, 257,48122, 587,48122,12391,48153, 257,46863, 9136,48156, 9137,48156, 264,48157, 48159,48163,17827,48156,48163,48167, 413,48156, 1,48170, 264,48156, 8997,48175, 241,48175, 1,48179, 265,48157, 8997,48183,48175,48184, 4425,48183,48161,48183,48176,48183,48175,48183, 8997,48194, 5579,48183, 17873,48183, 1791,48183,48173,48183,48181,48183, 265,48156, 8997,48208, 48163,48211,48163,48209, 8997,48215, 8997,48156, 265,48218,48163,48221, 265,48219,48175,48225,12377,48156,36925,46863,20177,46863, 8383,46863, 8385,46863, 88,46863, 11,48239,37409,48239, 566,46863,27021,48245, 9195,48245,20501,48245, 9377,48245, 9875,48245, 587,48245,20763,48245, 653,46863, 11,48261, 289,46863, 587,48265,36349,46863, 903,48268, 40617,46863, 1011,48272, 66,46863, 33,48277,20217,46863,37017,46863, 37845,46863,38057,46863, 903,48286,43215,48286, 155,48286,21315,46863, 483,48294, 1011,48294,28715,48294, 1347,48294, 1347,46863,21315,48304, 155,46863,38057,48308,21378,46863,38134,46863,20103,46863, 375,48316, 36773,46863, 375,48320, 713,46863,12377,48324, 25,46863, 113,48328, 12377,48328,26625,46863, 483,48334,10107,46863,38056,48338,38056,48339, 38057,48338,48343,48345,38057,48339,48341,48349, 3,48339, 3,48338, 9195,46863, 375,48356,27021,46863, 375,48360, 19,46863, 59,48365, 32805,46863, 4,48368,34447,48371, 903,48368, 9,48368, 4,48369, 33871,48379, 11,48368,34447,48383,45639,46863, 2,48386,46599,48389, 2,48387,46169,48393, 587,48386,46599,48397,36256,46863,35187,46863, 6685,48402, 9,48402, 483,46863,27255,48408,26625,48408,24545,48408, 9287,48408,21315,48408, 903,48408, 9731,48408,13857,48408, 803,48408, 244,48408,17049,48408, 6441,48408, 4819,48408,17099,48408, 4919,48408, 9,48408, 241,48440, 241,48408, 9,48444,20885,48408, 5,48408, 27021,48451, 9195,48451,20501,48451, 9377,48451, 9875,48451, 587,48451, 20763,48451, 9,46863,32805,48466,10527,48466, 113,48466, 506,48466, 16937,48466, 4727,48466, 483,48466, 241,48480, 241,48466, 483,48484, 37663,48466, 265,48467, 11,48491, 3,48466, 11,48495,37409,48495, 35187,48466,19917,46863,18967,48503, 5,48504, 5,48505,21036,48503, 21037,48503, 4,48503,48509,48515, 5,48503,18967,48518, 4,48502, 48521,48523,48507,48523,48511,48523, 5,48502,48513,48531, 587,46863, 12377,48535,12551,48537,45639,48535,46275,48541,12377,48534,12391,48545, 36527,48534,45639,48534,46599,48551, 265,48535,17827,48555, 1011,48534, 11,46863,32805,48561,34003,48563,20035,48560,32805,48560,34447,48569, 903,48560, 1275,48561, 9,48575, 3,48560, 33,48579, 3,48561, 113,48583,16937,46863, 1216,48586, 413,48586,21036,48586,21037,48586, 21036,48587,48595,48597,21037,48587,48593,48601, 903,48587,16941,48605, 1011,48586, 903,48608, 903,48586,16943,48613, 1011,48612, 9,48586, 17049,46863, 1216,48620, 413,48620, 903,48620, 1011,48626, 1011,48620, 903,48630, 483,48620, 2,48620, 3,48620, 1369,48639, 2,48621, 3,48621, 483,48645, 2,46862, 6,48649, 4,48651, 5,48649, 9,48655,21604,48657,21604,48656,21605,48657,48661,48663,21605,48656, 48659,48667, 5,48648,23717,48671,24522,48671,24447,48671,23939,48676, 23939,48671,24447,48680,22956,48671,23651,48685, 17,48671,21605,48689, 24447,48691,21605,48688,23651,48695,21605,48671, 17,48699,23939,48701, 17,48698,23651,48705, 19,48649, 12,48649, 9,48649, 11,48712, 11,48649, 9,48716,21605,48649,48652,48720,48653,48721,48723,48725, 48653,48720,48652,48721,48729,48731, 3,46862, 5,48735, 4,46862, 19975,48739,19365,48739,19221,48739,19917,48739,10107,48747, 587,48739, 5,46862,25451,48753,42283,48753,19739,48753, 0,48753, 3,48761, 25380,48753, 7971,48765,42155,48765, 164,48753,48353,48771,20763,48753, 1011,48775, 1010,48774,48777,48779, 1010,48775, 1011,48774,48783,48785, 2,48753, 17,48788,48353,48791, 2,48752,23717,48795,24522,48795, 23939,48795,24447,48800,24447,48795,23939,48804,22956,48795,23651,48809, 21605,48795, 17,48813,23939,48815, 17,48812,23651,48819, 17,48795, 21605,48823,24447,48825,21605,48822,23651,48829, 1369,48753,21605,48832, 7971,48835,42155,48835,21605,48753, 1369,48840,42155,48843, 7971,48843, 17,48753,37844,48848,48762,48848,48763,48849,48853,48855,37844,48849, 48763,48848,48762,48849,48861,48863,37845,48848,48859,48867,37845,48849, 48851,48871, 2,48849,48355,48875,47853,48875, 2,48848,48353,48881, 5,46863, 374,48884, 374,48885, 375,48884,48889,48891,19381,48885, 19380,48884,48895,48897,19381,48884,19380,48885,48901,48903,20812,48884, 20813,48884,20812,48885,48909,48911, 1197,48885,21604,48915,21604,48914, 21605,48915,48919,48921,21605,48914,48917,48925, 375,48885,48887,48929, 20813,48885,48907,48933,20501,48885, 1011,48937,27021,48885, 483,48941, 9195,48885, 483,48945, 9377,48885, 483,48949, 9875,48885, 1011,48953, 587,48885, 483,48957, 1369,48885, 1011,48961,38057,48961,20763,48885, 483,48967, 903,48885, 375,48971, 483,48884,27021,48975, 9195,48975, 20501,48975, 9377,48975, 9875,48975, 587,48975,20763,48975,18967,48885, 483,48991, 165,48991, 2,48884,48961,48997, 3,48884,13118,49000, 4862,49000,13118,49001,13119,49000,49007,49009, 4863,49000, 4862,49001, 49013,49015,15193,49001,15475,49001,15579,49001,13507,49001,20501,49001, 253,49001,15437,49001, 8997,49031,20219,49001,37019,49001,19513,49001, 35843,49001,20697,49001,37377,49001,13119,49001,49003,49047, 4863,49001, 49005,49051, 241,49001, 9875,49001, 53,49001, 1471,49001, 8401,49001, 9955,49001,10273,49001, 4137,49001, 3863,49001, 4063,49001, 1369,49001, 18967,49001, 483,49077, 2,48885, 1,49081, 7,49082,49000,49084, 49001,49085,49087,49089,49000,49085,49001,49084,49093,49095, 7,49081, 1,49098,49000,49100,49001,49101,49103,49105,49000,49101,49001,49100, 49109,49111, 1,49080, 7,49115, 7,49080,49001,49119, 0,49080, 49083,49123, 7,49125,49001,49127, 0,49081,49116,49131,49001,49133, 7,49131,49115,49136,49001,49139,49001,49137,49115,49143,49115,49131, 7,49146,49001,49149,49001,49081, 3,48885,37357,49155, 165,49155, 10257,49155, 483,49155,35187,48885, 375,49165, 9,48885, 1,49168, 3,49171,46863,49172,46863,49171, 3,49176, 3,49177,37845,49169, 37845,49168,37844,49168,49183,49187,37844,49169,49185,49191, 2,49168, 49175,49195,49179,49195, 2,49169,49181,49201, 3,46863,49171,49204, 49195,49207, 6,49205, 11,49211, 0,49205, 0,49204,40704,49217, 38305,49217, 9,49220, 9,49217,38305,49224, 6,49204,40705,49229, 49217,49231,49219,49229,18967,49229, 4,49236, 5,49236, 5,49237, 4,49237,46863,49244,49241,49247,46863,49237, 4,49250,49241,49253, 4,49251,49243,49257,49227,49229, 17,49229,49223,49229,37325,49205, 903,49267,10107,49204,48875,49271,10219,49205, 903,49275,17049,49204, 1369,49279, 11,49205, 25,49283, 9,49283, 17,49205, 903,49289, 21315,49289,37409,49205, 9,49295, 1011,49205, 375,49299, 9,49204, 11,49303,37409,49303, 11,49204, 33,49309,35187,49205, 1505,49313, 4,49204,49289,49317, 5,49204,13118,49320, 4862,49320,13118,49321, 13119,49320,49327,49329, 4863,49320, 4862,49321,49333,49335,15193,49321, 15475,49321,15579,49321,13507,49321,20501,49321, 253,49321,15437,49321, 8997,49351,37019,49321,20219,49321,35843,49321,19513,49321,37377,49321, 20697,49321,13119,49321,49323,49367, 4863,49321,49325,49371, 241,49321, 9875,49321, 1471,49321, 53,49321, 8401,49321,10273,49321, 9955,49321, 4137,49321, 4063,49321, 3863,49321, 1369,49321,18967,49321, 483,49397, 4,49205, 1,49401, 7,49402,49320,49404,49321,49405,49407,49409, 49320,49405,49321,49404,49413,49415, 7,49401, 1,49418,49320,49420, 49321,49421,49423,49425,49320,49421,49321,49420,49429,49431, 1,49400, 7,49435, 7,49400,49321,49439, 0,49400,49403,49443, 7,49445, 49321,49447, 0,49401,49436,49451,49321,49453, 7,49451,49435,49456, 49321,49459,49321,49457,49435,49463,49435,49451, 7,49466,49321,49469, 49321,49401, 5,49205,20645,49475, 1505,49475, 9935,49475,18967,49205, 7,49483, 4,49484, 4,49485, 16,49483, 17,49483, 4,49482, 49493,49495, 5,49482,49487,49499,49491,49499, 4,49483, 7,49504, 49499,49507, 5,49483,49489,49511, 2,46863, 6,49515, 17,49517, 35187,49519, 0,49515,38305,49523, 15,49525, 0,49514,36545,49529, 49521,49529, 15,49529, 6,49514,49531,49537,36544,49537,49529,49541, 49527,49537, 11,49537,35187,49546,49529,49549,35187,49537, 11,49552, 49529,49555,45639,49514,46599,49559,45639,49515,46275,49563,17125,49515, 16,49567, 16,49566, 17,49567,49571,49573, 17,49566,49569,49577, 17049,49514, 4,49514, 7,49583, 1,49585, 265,49583, 1,49588, 0,49588,49587,49589,49586,49588,49595,49597,49587,49588,49586,49589, 49601,49603, 0,49589,49591,49607, 1,49589,49593,49611, 4,49515, 1011,49615, 1,49617, 0,49617, 1,49616,49621,49623, 0,49616, 49619,49627, 4,46863,27857,49630,27895,49633,19815,49630,19857,49637, 49237,49631,49239,49641,49237,49630,49241,49645,32805,49630,34447,49649, 32805,49631,34003,49653,27857,49631,27879,49657,19815,49631,19849,49661, 2,49630, 7,49665, 1,49667, 265,49665, 1,49670, 0,49670, 49669,49671,49668,49670,49677,49679,49669,49670,49668,49671,49683,49685, 0,49671,49673,49689, 1,49671,49675,49693, 2,49631, 903,49697, 1,49699, 0,49699, 1,49698,49703,49705, 0,49698,49701,49709, 1, 7, 377,49713,48110,49712,48111,49712,49152,49712,49472,49712, 49153,49712,49473,49712,49374,49712,49054,49712,49375,49712,49055,49712, 704,49712, 100,49712,26502,49712,41376,49712, 8808,49712,47622,49713, 47660,49713,47146,49713,47148,49713,49059,49713,49379,49713,49158,49713, 49478,49713,49061,49713,49381,49713,48998,49713,49318,49713,47224,49713, 47226,49713,48041,49713,48039,49713,47058,49713,47060,49713,47220,49713, 47222,49713,48047,49713,47056,49713,47442,49713,49349,49713,49029,49713, 49121,49713,49441,49713,47628,49713,47668,49713,48962,49713,49290,49713, 22798,49713,39074,49713,31498,49713,44616,49713,31392,49713,44494,49713, 47540,49713,47532,49713,31794,49713,44858,49713,48298,49713,48288,49713, 31924,49713,44994,49713, 8652,49713, 8535,49713,13252,49713,43989,49712, 41417,49843,30655,49712,26219,49847,26503,49712,41377,49712, 8809,49712, 26547,49712,26219,49857,41835,49712,41417,49861, 273,49712,12897,49865, 8813,49712, 8647,49869, 376,49713, 705,49712, 101,49712, 803,49712, 483,49879,30091,49712,26219,49883, 113,49712, 9,49887,43503,49712, 41417,49891,43215,49712, 483,49895,43214,49712, 112,49712, 802,49712, 49320,49712,49401,49905, 241,49905,49000,49712,49081,49911, 241,49911, 49081,49712,49001,49916,49001,49917,49911,49921,49401,49712,49321,49924, 49321,49925,49905,49929,49001,49712,49081,49932, 241,49932,49321,49712, 49401,49938, 241,49938, 414,49713,18391,49945, 420,49713,18391,49949, 449,49713,18391,49953, 8808,49713,49855,49957, 8453,49713,46863,49960, 20239,49713,46863,49964,37095,49713,46863,49968,47976,49713,47593,49713, 26502,49713,49851,49977,31921,49713,47592,49713, 8495,49983, 828,49713, 49903,49987, 128,49713,49901,49991, 705,49713,49737,49995, 101,49713, 49739,49999,47977,49713, 8495,50003,47488,49713,48122,49713,48480,49713, 48440,49713,47568,49713, 1344,49713, 1482,49713, 64,49713, 1484,49713, 336,49713, 1480,49713, 254,49713, 1342,49713, 338,49713, 1123,49713, 931,49713, 665,49713, 1417,49713, 1429,49713, 1301,49713, 1127,49713, 941,49713, 523,49713, 1283,49713, 939,49713, 1103,49713, 171,49713, 1525,49713, 407,49713, 1517,49713, 949,49713, 280,49713, 1476,49713, 272,49713, 1017,49713, 1077,49713, 1047,49713, 1113,49713, 1245,49713, 1237,49713, 501,49713, 433,49713, 929,49713, 591,49713, 915,49713, 681,49713, 1555,49713, 911,49713, 1545,49713, 855,49713,41376,49713, 49853,50107, 4900,49713,14622,49713,48113,49713, 8997,50115, 1382,49713, 695,49713,48286,49713, 903,50122,48294,49713, 1011,50126,26503,49713, 49741,50131,47530,49713, 903,50134,47538,49713, 1011,50138,49289,49713, 49317,50142, 903,50142,48961,49713,48997,50148, 1011,50148,21522,49713, 46863,50154,38266,49713,46863,50158, 394,49713, 299,49713,31792,49713, 903,50166,44856,49713, 1011,50170,22789,49713, 903,50174,39065,49713, 1011,50178, 1386,49713, 545,49713,41377,49713,49743,50187, 413,49712, 8647,50191,18062,50191,17993,50191, 251,50196, 251,50191,17993,50200, 46863,50191, 412,49712,48008,49713,50207,50209,49717,50209, 341,50209, 40381,49713, 17,50217, 913,49713, 483,50221, 289,49713, 8809,49713, 49745,50227,49000,49713,49935,50231,49919,50231,49721,50231,49731,50231, 49937,50231,49933,50231,49081,50243, 241,50243,49320,49713,49941,50249, 49927,50249,49723,50249,49729,50249,49943,50249,49939,50249,49401,50261, 241,50261, 1374,49713, 8672,49713,12534,49713,12921,49713, 264,50273, 265,50272,50275,50277, 264,50272, 265,50273,50281,50283, 8605,49713, 26097,49713,41299,49713,26277,49713,41479,49713,26104,49713,41314,49713, 1477,49713,46863,50300, 281,49713,46863,50304, 1516,49713,46863,50308, 948,49713,46863,50312,44988,49713, 903,50316,31920,49713, 1011,50320, 43293,49713,49895,50325,15156,49713, 264,50329, 265,50328,50331,50333, 264,50328, 265,50329,50337,50339, 8916,49713,14623,49713, 8495,50345, 4901,49713, 8495,50349,14611,49713, 241,50352, 4899,49713, 241,50356, 15219,49713, 412,50360, 413,50361,50363,50365, 412,50361, 413,50360, 50369,50371, 5119,49713, 412,50374, 413,50375,50377,50379, 412,50375, 413,50374,50383,50385,13177,49713, 413,50388, 264,50388, 264,50389, 265,50388,50395,50397, 265,50389,50393,50401, 5313,49713,12377,50404, 47591,49713, 265,50409, 8861,50411, 265,50408, 8495,50415,47641,49713, 43292,49713,49899,50421,15158,49713,39228,49713,23012,49713,40676,49713, 25546,49713, 500,49713,18391,50435, 432,49713,18391,50439, 1244,49713, 18617,50443, 1236,49713,18617,50447, 1109,49713, 903,50451, 1412,49713, 305,50455,44832,49713,31770,49713,25545,49713, 9,50462,40675,49713, 483,50466, 935,49713, 483,50471, 1087,49713, 9,50475, 1413,49713, 295,49713, 1290,49713, 903,50483, 1304,49713, 9,50487,48009,49713, 50191,50491,49719,50491, 241,50491,22957,49713, 903,50498,39205,49713, 1011,50502,47608,49713, 1505,50506,21315,50506,47640,49713, 165,50512, 38057,50512, 510,49713,46863,50518, 922,49713, 1108,49713, 1280,49713, 9,50527, 246,49713, 483,50531, 412,49713,47460,50535, 483,50535, 9,50535, 8997,50535,46863,50542,46863,50535, 8997,50546, 1216,49713, 44243,50550,31103,50550, 483,50550,18617,50557, 9,50550,18617,50561, 8677,49713, 305,49713, 241,50567,16163,50567, 8647,50566, 8495,49713, 257,50574, 1141,49713,16531,50579, 253,49713, 59,50582, 1325,50582, 331,50582, 265,50582, 8634,49713, 8611,49713,41349,49713,26127,49713, 273,49713,12705,50601,13673,50601,18391,50601, 2923,50601,46863,50600, 331,49713, 53,50612, 1471,50612, 253,50612, 1369,50612, 8861,49713, 241,50623, 375,50625, 375,50622, 251,49713, 413,50631,17993,50633, 413,50630,18391,50637,15029,50630, 264,50641, 265,50640,50643,50645, 264,50640, 265,50641,50649,50651,39204,49713, 257,49713, 265,50657, 26625,50657,25793,50657,41019,50657, 8495,50657, 9731,50657,25793,50656, 41019,50656, 8495,50656, 265,50656, 4863,50677,12377,49713,46863,50680, 5313,50680, 341,49713, 241,50687, 298,49713, 4863,50691, 704,49713, 49875,50695, 9195,50695, 100,49713,49877,50701, 395,49713, 829,49713, 49879,50707, 9195,50707, 129,49713,49887,50713, 89,49713,48884,50716, 48884,50717,48885,50717,50719,50723,48885,50716,50721,50727, 11,50716, 567,49713,42155,50733,41941,50733, 7971,50733, 9565,50733, 587,50733, 9377,50743, 587,50732, 9195,50747,38057,49713,47640,50750,46863,50750, 903,50754, 903,50750,46863,50758,21315,49713,47608,50762,46863,50762, 1011,50766, 1011,50762,46863,50770, 628,49713, 1396,49713, 241,50777, 288,49713, 7971,50781, 265,49713,23584,50785,39564,50785,24355,50785, 39905,50785, 5520,50785, 256,50784,50795,50797, 5521,50785, 256,50785, 50204,50785, 10,50784, 1,50785, 257,50808,50797,50811, 257,50809, 50803,50815, 10,50785,50191,50785,46863,50820,47590,50784,23493,50785, 22807,50826,39489,50785,39085,50830,22807,50785,23493,50834,39085,50785, 39489,50838, 1087,50785, 935,50785,47591,50784, 8495,50847,47590,50785, 50847,50851, 4213,50785, 8757,50785,26415,50785,41653,50785,27377,50785, 9335,50785,42471,50785, 8109,50785, 4147,50785, 3933,50785, 53,50784, 1471,50784, 253,50784,47591,50785,50825,50881, 257,50785, 1,50884, 50797,50887,50797,50885, 4827,50885, 305,50785, 8861,50895, 8495,50785, 331,50899,46863,50785,50191,50902, 241,50902, 241,50785,46863,50908, 8337,50909,46863,50913, 1369,50784, 305,50917, 11,50785,50807,50921, 8165,50921, 1369,50921, 241,50784,47460,50929, 483,50929, 9,50929, 8997,50929,46863,50936,46863,50929, 8997,50940, 257,50784,50801,50945, 50803,50945, 4863,50945, 11,50784,50819,50953, 7971,50953, 1011,49713, 31920,50958,48294,50958,44856,50958,47538,50958,48961,50958,39065,50958, 21315,50958,46863,50972,31103,50958, 903,50976, 1505,50958,46863,50980, 44243,50958, 903,50984,39205,50958, 9,50958, 903,50958,31103,50992, 44243,50992,46863,50958,21315,50998, 1505,50998, 903,49713,44988,51004, 48286,51004,31792,51004,47530,51004,49289,51004,22789,51004,38057,51004, 46863,51018,44243,51004, 1011,51022, 165,51004,46863,51026,31103,51004, 1011,51030,22957,51004, 483,51004, 1011,51004,44243,51038,31103,51038, 46863,51004,38057,51044, 165,51044, 241,49713,47961,51050, 4899,51050, 14611,51050, 375,51050,12377,51051, 375,51061, 8997,51051, 375,51065, 265,51065,46863,51069, 1275,51050, 9,51073, 15,51050, 483,51077, 265,51050,47460,51081, 483,51081, 9,51081, 8997,51081,46863,51088, 46863,51081, 8997,51092, 8647,49713, 413,51096, 305,51097, 11,51097, 1369,51097, 341,51097, 305,51096,41417,49713, 11,51111, 1369,51111, 26219,49713, 11,51117, 1369,51117,32102,49713,27021,51123,45148,49713, 11,51127, 1369,51127,31857,49713,44925,49713,32294,49713,45314,49713, 17565,49713,32103,49713, 241,51143, 587,51142,45149,49713, 11,51148, 49317,49713,49289,51152,48997,49713,48961,51156,49001,49713,49912,51161, 49725,51161,49914,51161,49735,51161,49081,51161,49911,51170,49911,51161, 49081,51174, 241,51174, 241,51161,49911,51180,49321,49713,49906,51185, 49727,51185,49908,51185,49733,51185,49401,51185,49905,51194,49905,51185, 49401,51198, 241,51198, 241,51185,49905,51204,49475,49713, 1505,51208, 49155,49713, 165,51212, 240,49712,51059,51217,50163,51217,50165,51217, 51051,51217, 375,51225, 264,49712,49715,51229,50838,51229,50834,51229, 50850,51229,50847,51229,50945,51229,49983,51229,50415,51229,50677,51229, 50691,51229,50496,51229,50003,51229,50906,51229,50910,51229,50345,51229, 50349,51229, 8374,51229, 8389,51229,50705,51229,20152,51229,36898,51229, 20201,51229,36979,51229,50902,51229, 241,51276,50908,51229,46863,51280, 50491,51229, 241,51284,47590,51229,50785,51288,22807,51229,50785,51292, 39085,51229,50785,51296,26219,51229,41417,51229,14524,51229,35690,51229, 50733,51229,37519,51229,50781,51229,50953,51229,50455,51229,50917,51229, 19396,51229, 8647,51229,20103,51229, 375,51324,36773,51229, 375,51328, 8337,51229, 375,51332,50785,51229,39085,51336,22807,51336,47590,51336, 46863,51336, 241,51344, 241,51336,46863,51348,47488,51229,47961,51229, 9,51229,18967,51356, 483,51229,35187,51229, 375,51362,18967,51229, 9,51366,46863,51229,50908,51370,50785,51370, 241,51374, 241,51370, 50785,51378, 375,51370, 241,51229,50491,51384,50902,51384,50785,51384, 46863,51390,46863,51384,50785,51394, 375,51229, 8337,51398,20103,51398, 36773,51398,14315,51398,35187,51398,46863,51398,14315,51229, 375,51412, 4899,51229,14611,51229, 1010,49712, 3867,51421, 8277,51421, 4067,51421, 3997,51421, 8953,51421, 9459,51421, 902,49712,50321,51435,51031,51435, 24265,51435,28233,51435,29077,51435,51005,51435,31103,51447,19559,51435, 4283,51435, 9673,51435, 4279,51435, 3807,51435,20361,51435,20713,51435, 9967,51435, 8251,51435,47961,49713, 241,51468,47979,49713, 412,51472, 413,51473,51475,51477, 412,51473, 413,51472,51481,51483, 240,49713, 340,51487,51398,51487,51418,51487,51416,51487,51354,51487,47974,51487, 47589,51487, 8590,51487,12537,51487,14620,51487, 375,51487,51229,51508, 7,51487, 265,51512, 265,51513,51229,51517,47580,51487, 8861,51521, 47961,51487,51229,51524, 8495,51524,51229,51487, 375,51530,14611,51530, 4899,51530,47961,51530, 8495,51487, 4899,51540,47961,51540,14611,51540, 14611,51487,51229,51548, 8495,51548, 4899,51487,51229,51554, 8495,51554, 46863,51487, 265,51560, 8861,51563, 265,51561, 8495,51567,51229,51567, 265,51487, 7,51572,15309,51573,15308,51572,51577,51579,15308,51573, 15309,51572,51583,51585,46863,51572, 8861,51589, 902,49713,31103,51593, 43053,51593,46863,51593, 1010,49713, 1505,51601, 918,51601, 9,51601, 903,51606, 903,51601, 9,51610, 265,49712,49873,51615,50165,51615, 51059,51615,51057,51615,51055,51615,51053,51615,49975,51615,49973,51615, 50113,51615,50111,51615,50163,51615,51471,51615,50355,51615,50359,51615, 50209,51615, 241,51645, 8948,51615,50225,51615,50479,51615, 331,51615, 8861,51654, 8861,51615, 331,51658, 4827,51615,15269,51615,51051,51615, 375,51667,14611,51667, 4899,51667,47961,51667, 241,51614,50209,51677, 241,49712,18300,51681, 8605,51681, 8916,51681,50945,51681,49321,51680, 50249,51691,49001,51680,50231,51695,50705,51681, 8374,51681,51508,51681, 50691,51681,47443,51681, 8389,51681,50677,51681,51517,51681, 8861,51681, 375,51714,26219,51681,41417,51681, 305,51681,48009,51681,51229,51725, 8647,51681, 8452,51681,46863,51731, 713,51681, 25,51681,18257,51681, 375,51738, 8337,51681, 375,51742, 265,51742,46863,51747, 375,51681, 18257,51750, 8861,51750, 8337,51750,51487,51750,51487,51681, 375,51760, 265,51680,50209,51765,49321,51681,49905,51769,49001,51681,49911,51773, 265,51681,51370,51777,51229,51777,46863,51780,46863,51777,51229,51784, 8337,51776,46863,51789,46863,51681, 264,51792,51765,51795, 264,51793, 51777,51799, 264,49713,51489,51803,51515,51803,51575,51803,51521,51803, 50411,51803,50659,51803,51563,51803, 8471,51803, 8397,51803, 8371,51803, 20149,51803,36887,51803,20211,51803,37009,51803,20247,51803,37103,51803, 51589,51803,50207,51803,46863,51839,51765,51803,46863,51843,51677,51803, 46863,51847,36773,51803,46863,51851,20103,51803,46863,51855, 8337,51803, 46863,51859, 4613,51803,12571,51803,36539,51803,37595,51803,36049,51803, 47581,51803,51487,51873,51615,51803,39085,51877,22807,51877,47590,51877, 46863,51877, 241,51884, 241,51877,46863,51888,46863,51802,51765,51893, 51677,51893,50207,51893,51615,51893, 241,51901, 341,51893, 1369,51803, 341,51803,51487,51909, 8337,51909,20103,51909,36773,51909,35187,51909, 14315,51909,46863,51909,12377,51803, 375,51925, 1011,49712,26219,51929, 41417,51929, 8647,51929, 903,49712,49981,51937,51594,51937, 375,51937, 31103,51937,51593,51944,51593,51937,31103,51948,15269,51937, 4827,51937, 1217,49713, 483,51957, 9,51957, 413,49713, 8647,51962,13177,51962, 251,51962,18391,51969, 375,51962,18391,51973,44243,51962,31103,51962, 18391,51963, 251,51981, 483,51962,18391,51985, 9,51962,18391,51989, 375,49713, 5,51992,51615,51995, 413,51993,17993,51999, 413,51992, 18391,52003, 241,51993,51487,52007,46863,51992, 241,51992,51217,52013, 51615,52013, 8861,51992,12377,51993,51487,52021,15029,51992,14315,49713, 341,52027,51487,52029,15029,49713, 266,52032, 267,52032, 264,52033, 52035,52039, 465,52032,52039,52043, 413,52032, 6,52046, 264,52032, 251,52051, 241,52051, 6,52055, 265,52033, 251,52059,52051,52060, 8841,52059,52037,52059,52052,52059,52051,52059, 251,52070,15363,52059, 15055,52059,15061,52059,52049,52059,52057,52059, 265,52032, 251,52084, 52039,52087,52039,52085, 251,52091, 251,52032, 265,52094,52039,52097, 265,52095,52051,52101, 375,52032, 8639,49713, 8643,49713,26217,49713, 41415,49713, 164,49713,51593,52115, 903,52115, 1504,49713,51601,52121, 144,49713, 113,52125, 802,49713,49880,52129,49879,52129, 483,52132, 9366,52129, 9195,52129, 483,52138, 483,52129,49879,52142, 9195,52142, 31103,52129, 112,49713,49888,52151,49887,52151, 9,52154, 9,52151, 49887,52158,44243,52151, 1486,49713, 803,52165,43214,49713,49896,52169, 49895,52169, 483,52172, 483,52169,49895,52176, 1073,49713, 903,52181, 525,49713, 903,52185, 669,49713, 483,52189, 566,49713,51929,52193, 51615,52193,10107,52193,21036,49713, 17,52201, 88,49713,37611,52205, 36083,52205,38155,52205,35927,52205, 1346,49713, 1505,52215, 154,49713, 483,52219,26329,49713,41557,49713, 165,49713,49155,52226,47640,52226, 46863,52226, 903,52232, 903,52226,46863,52236,43215,52226, 1505,49713, 49475,52242,47608,52242,46863,52242, 1011,52248, 1011,52242,46863,52252, 28715,52242, 803,49713,49903,52259, 483,52261, 483,52258,49903,52265, 113,49713,49901,52269, 9,52271, 9,52268,49901,52275,28715,49713, 1505,52278,43215,49713,49899,52283, 483,52285, 483,52282,49899,52289, 165,52282,29028,49713,43318,49713,25793,49713, 257,52298, 713,49713, 241,52303,16163,52303,41019,49713, 257,52308, 25,49713, 241,52313, 16163,52313, 1447,49713,16531,52319, 33,49713,16531,52323, 1471,49713, 59,52326, 1325,52326, 331,52326, 265,52326, 53,49713, 1325,52336, 59,52336, 331,52336, 265,52336, 1325,49713, 53,52346, 1471,52346, 253,52346, 1369,52346, 59,49713, 1471,52356, 53,52356, 253,52356, 1369,52356,48466,49713, 483,52366,48408,49713, 9,52370, 843,49713, 9,52375, 1530,49713, 9,52379,40436,49713, 113,52383, 587,49713, 28714,52387,36212,52387,30091,52387, 567,52386, 9195,52395, 11,52386, 32103,52386,35187,52387, 241,52402, 241,52387,35187,52406, 4,52386, 9366,52411, 9195,52411, 483,52414, 483,52411, 9195,52418,31103,52411, 5,52387,21605,52424, 9195,52425,27021,52425,21605,52387, 11,52433, 5,52432, 11,49713,32805,52439,19888,52439,19913,52439, 265,52439, 51803,52447,43503,52439, 1275,52438, 9,52453, 89,52438, 587,52438, 265,52438,51229,52461, 7971,52461,45149,52438,18967,52439, 241,52468, 241,52439,18967,52472, 2,52438, 9,52477,44243,52477, 3,52439, 7971,52483,42155,52483, 2,52439,52205,52489,38305,52439, 265,52493, 38305,52438, 113,52497, 1369,49713, 331,52500, 59,52500,40674,52501, 38305,52501, 265,52509, 241,52508, 241,52501,38305,52514, 1325,52500, 265,52500,51229,52521, 305,52521, 17,52500, 241,52527,38305,52500, 35187,52501, 265,52501, 331,52535,51803,52535, 4,52500,51601,52541, 5,52500, 803,52545, 5,52501, 959,52549, 47,52549, 759,52549, 4,52501, 1275,52500, 9,52559, 17,49713, 1275,52562, 903,52565, 1369,52562, 241,52569, 2,52562, 903,52573,51593,52573, 3,52562, 113,52579, 3,52563, 1141,52583, 1447,52583, 33,52583, 2,52563, 265,52591,51803,52591,38305,49713, 1369,52596, 3,52596, 3,52597, 8165,52603,20501,52603, 9875,52603, 11,52603, 11,52596, 113,52613, 15,49713, 1010,52617, 1010,52616, 1011,52616,52619,52623, 1011,52617, 52621,52627, 241,52616, 483,52631, 3,52616, 483,52635, 3,52617, 1369,52639, 1275,49713, 17,52642, 903,52645, 11,52642, 9,52649, 241,52642, 9,52653, 9,52643, 1369,52657, 11,52657, 5,52642, 1505,52663, 5,52643, 53,52667, 1471,52667, 253,52667, 1369,52642, 9,52675,18967,49713, 241,52679, 9,52681, 5,52678, 17,52685, 5,52679, 9,52689, 483,49713, 803,52693,52129,52695,43215,52693, 52169,52699, 1216,52693,18759,52703, 413,52693,17993,52707, 803,52692, 49903,52711,48466,52692,43215,52692,49899,52717,40675,52692, 1216,52692, 18617,52723, 413,52692,18391,52727,44243,52692,38305,52693,46169,52733, 9,52692,46863,52736, 903,52692, 5,52692,10107,52743,51929,52743, 51615,52743, 5,52693,46863,52692, 9,52752, 9,49713, 113,52757, 52151,52759, 4,52756, 7,52763, 2,52765, 2,52764, 2,52763, 7,52770, 1368,52763, 1216,52757,18759,52777, 413,52757,17993,52781, 113,52756,49901,52785,48408,52756,25545,52756, 1216,52756,18617,52793, 413,52756,18391,52797,31103,52756, 483,52756,46863,52802, 1011,52756, 3,52756,52769,52809,52773,52809,37611,52809,38155,52809,35927,52809, 52489,52809,52775,52809, 3,52757,52767,52825,52151,52825,37663,52825, 52477,52825,31103,52825,46863,52756, 483,52836,31103,49713, 1216,52840, 413,52840,21036,52840,21037,52840,21037,52841,52847,52851, 903,52841, 51593,52855, 1011,52840, 903,52858,21036,52841,52849,52863, 903,52840, 51435,52867, 1011,52866, 9,52840, 5,52840,27021,52875,44243,49713, 1216,52878, 413,52878, 903,52878, 1011,52884, 1011,52878, 903,52888, 483,52878, 3,52878, 11,52895, 1369,52895, 3,52879, 483,52901, 49205,49713, 5,52905,48885,49713, 113,52909, 3,52909, 3,49712, 20819,52915,50945,52915,51508,52915,37537,52915,36898,52915,20152,52915, 8374,52915,50695,52915,50701,52915,50707,52915,50713,52915,50691,52915, 50705,52915,37748,52915,20952,52915,52395,52915,52457,52915,52142,52915, 52158,52915, 8389,52915,50677,52915,51517,52915,50747,52915,50731,52915, 52418,52915,52478,52915,36979,52915,20201,52915,26219,52915,26106,52915, 52129,52915, 483,52976,52411,52915, 483,52980,51123,52915,32103,52915, 52875,52915,31770,52915,42885,52915,20885,52915, 483,52994,40399,52915, 44714,52915, 357,52915, 367,52915, 471,52915, 1249,52915, 8800,52915, 8647,52915,47488,52915, 8086,52915,19687,52915,19559,52915,20361,52915, 9673,52915,20713,52915, 9967,52915, 4283,52915, 4279,52915, 3807,52915, 8251,52915,41746,52915,41417,52915,44832,52915, 9704,52915,20326,52915, 21087,52915,52906,52915,48245,52915,48975,52915,48451,52915,52151,52915, 9,53058,52477,52915, 9,53062,51487,52915, 375,53066,50785,52915, 8165,52915, 265,53073, 1447,52915,38305,53077,21127,52915,20843,52915, 52425,52915,37663,52915, 9,53086, 1141,52915,38305,53091, 566,52915, 567,52915,46863,53097,44243,52915,41941,53100, 483,53100, 375,52915, 51487,53106,20103,53106, 8337,53106,36773,53106,46863,53106,41941,52915, 44243,53118, 33,52915,38305,53123, 9617,52915, 9,53126, 8337,52915, 375,53130,48884,52915, 1011,52915,48885,52915, 483,53139,52907,52915, 25,52915, 7971,53144,41019,52915, 11,53148, 305,52915, 8495,52915, 11,53154,20103,52915, 375,53158,20273,52915, 9,53162, 4,52915, 28411,53167,31103,53167,48408,53167,52905,53167, 483,53167,46863,53176, 20691,53167, 9923,53167,46863,53167, 483,53184, 5,52915,52905,53188, 17,53189,18967,53193,46863,53188, 483,53188,25793,52915, 11,53200, 713,52915, 7971,52915, 25,53206,36773,52915, 375,53210, 4,52914, 53191,53215,53051,53215,24265,53215,28233,53215,29077,53215,53135,53215, 53197,53215,53189,53215,52905,53231,46863,53231,19559,53215, 9673,53215, 4283,53215,20361,53215, 9967,53215,20713,53215, 8251,53215, 4279,53215, 3807,53215, 5,52914,53143,53255,53174,53255,50785,53255,53139,53255, 53184,53255,50733,53255,19396,53255,53167,53255,52905,53270,46863,53270, 8647,53255,41417,53255,26219,53255, 9,53255,18967,53282, 483,53255, 18967,53255, 9,53288,52905,53255,53167,53292,46863,53255,53167,53296, 11,52915,25793,53301,25793,53300, 8495,53301, 8495,53300,18967,53301, 41019,53301,41019,53300,21037,53301, 9,52915,52151,53318,37663,53318, 52477,53318,31103,53318,20273,53318, 9617,53318,52905,52915, 5,53332, 53215,53335, 5,53333,53167,53339, 9875,52915,35187,53343, 241,53343, 46863,52915, 375,53348, 5,53348,53215,53353, 5,53349,53167,53357, 483,52915,52129,53360,20885,53360,52411,53360,44243,53360, 5,53361, 5,53360,18967,52915,11731,53375, 113,53375,31103,52915, 9,53380, 20501,52915,35187,53385, 241,53385, 2,49712,52711,53391,52785,53391, 51059,53391,50165,53391,49995,53391,49999,53391,49987,53391,49991,53391, 50163,53391,52013,53391,52265,53391,52275,53391,17609,53391, 4904,53391, 17586,53391,52259,53391, 483,53423, 272,53391, 1476,53391, 280,53391, 949,53391, 1517,53391,52269,53391, 9,53437, 9484,53391,51803,53391, 51051,53391, 375,53445, 4903,53391, 9,53448,17579,53391, 9,53452, 42991,53391,40039,53391,40685,53391, 1197,53391, 265,53391, 253,53464, 1471,53464, 53,53464, 53,53391, 265,53472, 253,53391, 265,53476, 5,53391, 1471,53391, 265,53482, 5,53390, 8953,53487, 9459,53487, 4067,53487, 3997,53487, 8277,53487, 3867,53487, 11,53391, 9377,53500, 9,53391, 4903,53504,17579,53504, 9377,53391, 11,53510, 5,53511, 5,49712,48765,53517,48835,53517,48843,53517,25445,53517,22779,53517, 22243,53517, 7,53517, 2,53531,28063,53517,25299,53517,31598,53517, 53152,53517,50733,53517,35690,53517,37519,53517,50781,53517,52461,53517, 50953,53517, 272,53517, 1476,53517, 280,53517, 949,53517, 1517,53517, 357,53517, 367,53517, 471,53517, 1249,53517, 9304,53517,53204,53517, 53144,53517,35931,53517,52912,53517,20326,53517,21087,53517,20273,53517, 9,53586,50785,53517, 1369,53591,53391,53591,25381,53517,48753,53597, 10081,53597, 9704,53517, 53,53517, 265,53604,37899,53517,37617,53517, 52483,53517, 9617,53517, 9,53614, 253,53517, 265,53618,31103,53517, 26625,53622, 375,53517,35187,53626,26625,53517,31103,53630, 1471,53517, 265,53634, 265,53517, 253,53638, 1471,53638, 53,53638,49204,53517, 49205,53517,52913,53517, 713,53517, 9195,53652,52915,53652,21605,53653, 305,53517,52915,53660,21605,53661, 2,53517, 8229,53667,52909,53667, 46863,53667, 3,53517,52909,53674,53391,53675, 1369,53675,46863,53674, 52915,53517, 305,53684, 713,53684, 25,53684, 25,53517,52915,53692, 21605,53693, 9195,53517, 713,53698, 2,53516,53677,53703,53581,53703, 53647,53703,53683,53703,53675,53703,52909,53713,46863,53713, 4067,53703, 3997,53703, 8953,53703, 9459,53703, 8277,53703, 3867,53703, 3,53516, 53651,53731,53670,53731,50785,53731,50733,53731,53649,53731,53672,53731, 19396,53731,53667,53731,52909,53746,46863,53746, 8647,53731,26219,53731, 41417,53731, 483,53731,18967,53731, 9,53760, 9,53731,18967,53764, 52909,53731,53667,53768,46863,53731,53667,53772, 587,53517,35187,53777, 483,53517,52909,53517, 3,53782,53703,53785, 3,53783,53667,53789, 46863,53517, 3,53792,53703,53795, 3,53793,53667,53799, 9,53517, 20273,53802, 9617,53802,35187,53517, 375,53808, 4,49712,48747,53813, 37279,53813,19981,53813,24601,53813, 7,53813,21605,53823,53071,53813, 52743,53813,52193,53813,50225,53813, 8306,53813, 545,53813, 695,53813, 1382,53813, 1374,53813, 1386,53813,51906,53813,53442,53813,53199,53813, 53373,53813,53095,53813,51803,53813, 1369,53856,53391,53856, 9992,53813, 20734,53813,19916,53813,48739,53867,37241,53867, 7947,53867,28205,53813, 24613,53813,25551,53813,53189,53813, 483,53881, 33,53813, 9875,53813, 265,53886, 241,53887,20501,53813, 265,53892, 241,53893, 1141,53813, 154,53813, 483,53901, 1447,53813, 331,53813, 1369,53906, 265,53813, 8165,53910, 9875,53910,20501,53910, 1011,53813, 59,53813, 1369,53920, 3,53813, 8241,53925, 15,53924, 483,53929,53391,53813,51803,53932, 1325,53813, 1369,53936, 3,53812,24265,53941,28233,53941,29077,53941, 9673,53941,19559,53941, 4283,53941,20361,53941, 8251,53941, 3807,53941, 9967,53941,20713,53941, 4279,53941, 1369,53813, 331,53966, 1325,53966, 59,53966,51803,53966,18967,53813, 1275,53976,48739,53979,37241,53979, 7947,53979, 113,53977, 1275,53813,18967,53988,48739,53991, 7947,53991, 37241,53991, 8165,53813, 265,53998,46863,53813,38056,54002,38056,54003, 38057,54002,54007,54009,38057,54003,54005,54013, 15,53813, 3,54017, 1369,54019, 3,54016, 483,54023, 5,49713, 375,54026,51615,54029, 1368,54027, 7,54027, 2,54034, 2,54035,32805,54027,31103,54041, 20035,54027, 375,54045, 341,54027,18967,54049,12377,54027, 375,54053, 52915,54027,31103,54057,27021,54027,31103,54061,30091,54027,31103,54065, 31103,54026,27021,54069,52915,54069,18967,54027,47608,54075,46863,54075, 1011,54078, 1011,54075,46863,54082,53924,54027,53825,54087, 483,54087, 51929,54027, 483,54093,51615,54027, 375,54097, 483,54097, 1369,54026, 803,54103, 483,54026,53813,54107,10107,54107,51929,54107,51615,54107, 1275,54026, 1505,54117,18967,54026, 17,54121, 1369,54027,51601,54125, 2,54026,54078,54129,54075,54129,46863,54132,52541,54129, 1505,54129, 918,54129,52121,54129,54125,54129, 903,54129, 9,54146, 9,54129, 903,54150,46863,54129,54075,54154, 3,54026,54033,54159,54037,54159, 53966,54159,12571,54159, 4613,54159,51615,54159, 8337,54159,46863,54173, 52591,54159,53932,54159,53391,54159,53813,54180,53813,54159, 1369,54184, 53391,54184,36773,54159,46863,54191,20103,54159,46863,54195, 1369,54159, 53813,54198, 2,54027, 0,54202,54159,54205,46863,54207, 7,54202, 54159,54211, 265,54203, 9,54215,54159,54203, 9,54219,46863,54219, 3,54027,48286,54225,54039,54225,54150,54225,52573,54225,52115,54225, 38057,54225,46863,54236,53813,54224,53825,54241, 483,54241, 9,54225, 54129,54246, 483,54225,53813,54251,54154,54225,46863,54225,38057,54256, 54129,54256,54129,54225, 9,54262,46863,54262,10107,54027, 483,54269, 53813,54027, 483,54273, 3,54273, 1369,54277,53391,54277, 3,54272, 53825,54283, 483,54283, 17,54027,20273,54289, 9617,54289, 3,49713, 16722,54295,16530,54294,54297,54299,16723,54295,16531,54294,54303,54305, 16530,54295, 1,54295,35187,54311, 17,54313, 7,54295,16531,54316, 54299,54319,16531,54317,54309,54323, 15,54317,38305,54327, 1,54294, 40705,54331,54329,54331, 17,54331, 7,54294,54333,54339,40704,54339, 54331,54343,49713,54339, 4,54346, 4,54339,49713,54350,54315,54339, 9,54339,38305,54356,54331,54359,38305,54339, 9,54362,54331,54365, 52489,54295, 9,54369,36527,54295, 375,54373, 341,54295,12377,54295, 9,54379,16531,54295, 7,54382,54299,54385,37611,54295, 9,54389, 8321,54295,35927,54295, 9,54395,38155,54295, 9,54399,43503,54295, 44243,54403, 113,54295,38305,54406,40086,54295, 8241,54295,44243,54294, 11,54415, 1369,54415, 1486,54295,35187,54295,47640,54423,46863,54423, 903,54426, 903,54423,46863,54430,53480,54295,11731,54295,51615,54295, 241,54295, 17,54294, 113,54443,38305,54294, 9,54294,37611,54449, 38155,54449,35927,54449,52489,54449, 15,54294, 483,54459, 11,54295, 44243,54463,38305,54295, 113,54466,38057,54295, 7,54471, 375,54471, 4,54294,54426,54477,54423,54477,46863,54480,52573,54477,54377,54477, 52115,54477,43053,54477,46863,54477,54423,54492, 5,54294,54473,54497, 6,54497,54471,54501,53966,54497,12571,54497, 4613,54497,51615,54497, 8337,54497,46863,54513,52591,54497,53932,54497,53813,54497, 1369,54520, 53391,54520,53391,54497,53813,54526,20103,54497,46863,54531,36773,54497, 46863,54535, 1369,54497,53813,54538, 4,54295, 0,54542,54497,54545, 46863,54547, 5,54295,48294,54551,21315,54551,46863,54554,53391,54550, 1369,54550,46863,54551,21315,54562,53391,54295, 5,54567,53813,54569, 5,54566, 1369,54295, 9893,54575,52129,54575,54353,54575,54349,54575, 20885,54575,52411,54575,44243,54575, 5,54574, 5,54575,53813,54593, 2,49713,53227,54597,53262,54597,53355,54597,53358,54597,53298,54597, 53264,54597,53229,54597,53274,54597,53234,54597,49168,54597, 1,54597, 7,54597, 567,54621,52915,54623, 4,54621,54575,54627,53360,54627, 52915,54627, 483,54632, 483,54627,52915,54636, 9,54621, 1,54596, 36544,54643,35187,54643, 11,54646, 11,54643,35187,54650, 7,54596, 36545,54655,54643,54657,54645,54655,21605,54655,54653,54655,54649,54655, 15,54655,53270,54597,46863,54670,53231,54597,46863,54674,49169,54597, 54097,54597,53134,54597,53215,54683,53352,54597,53215,54687,53196,54597, 53215,54691, 8311,54597,48884,54596,54617,54697,53731,54597,53881,54597, 54283,54597,54241,54597,54087,54597,36256,54597,53296,54597,53167,54712, 53184,54597,53255,54716,53167,54597,53357,54720,53296,54720,53255,54720, 46863,54726,46863,54720,53255,54730,48885,54597, 9,54734,54697,54737, 54697,54735, 9,54741,35187,54597, 9,54744, 9,54597,48885,54748, 54697,54751,48885,54749,35187,54748, 11,54749,52915,54759,53188,54597, 53215,54763,46863,54765,46863,54762,53215,54769,53813,54763,53139,54597, 53255,54774,44243,54597, 11,54779,54225,54597,53813,54783,51229,54597, 265,54597,54027,54789,47961,54791,14611,54791, 4899,54791, 375,54791, 17,54596, 903,54801,51593,54801,54477,54801,54225,54801, 11,54596, 53318,54811,52825,54811,52915,54811, 9,54816, 9,54811,52915,54820, 44243,54811,53255,54597,53139,54826,53184,54826,53167,54826,46863,54832, 46863,54826,53167,54836,53357,54597,53167,54840, 4,54596,51418,54845, 51416,54845,51398,54845,51354,54845,51909,54845, 340,54845,51803,54857, 51873,54845,47974,54845,47589,54845, 8590,54845,14620,54845,12537,54845, 52021,54845,52029,54845,53106,54845, 375,54845,51229,54878,52915,54878, 0,54845, 6,54885, 7,54845, 265,54888,51803,54891, 265,54889, 51229,54895,52915,54895,47580,54845,51803,54901, 8861,54901, 8495,54845, 47961,54906, 4899,54906,14611,54906,52915,54845, 375,54914,14611,54845, 51229,54918, 8495,54918, 4899,54845,51229,54924, 8495,54924,47961,54845, 51229,54930, 8495,54930, 265,54845, 7,54936,51803,54939,54887,54937, 54886,54936,54943,54945,54887,54936,54886,54937,54949,54951,46863,54936, 8861,54955,51803,54955,46863,54845, 265,54960,51803,54963, 8861,54963, 265,54961,51229,54969, 8495,54969,51229,54845, 375,54974,14611,54974, 4899,54974,47961,54974, 5,54596, 1505,54985, 918,54985,52541,54985, 52121,54985,54125,54985, 903,54985, 9,54996, 9,54985, 903,55000, 5,54597,54889,55005,52915,55007,53349,55004, 6,55005,54914,55013, 52915,55013,54845,55016,54845,55013,52915,55020, 53,55005, 1471,55005, 253,55005,52557,55005,53348,55004,53215,55033, 241,55005, 9,55037, 52915,55004,53215,55041,46863,55043,46863,55040,53215,55047,53813,55041, 17,55005,35187,55053,52915,55005,53357,55057,55011,55057,53296,55057, 53255,55057,46863,55064,46863,55057,53255,55068,46863,55004,52915,55072, 53215,55075,52915,55073,53255,55079,48885,54596,54679,55083, 9,55083, 48884,54597,54755,55089,55086,55089,55083,55089, 9,55094,52915,55088, 53215,55099,52915,55089,53255,55103, 9,55089,55083,55106,53348,54597, 5,55110,53215,55113, 5,55111,53167,55117,52915,54597,48884,55120, 53215,55123,48884,55121,53139,55127, 5,55121,53139,55131,53184,55131, 53167,55131,46863,55136,46863,55131,53167,55140, 5,55120,53215,55145, 46863,55147,46863,55144,53215,55151,53813,55145,46863,55120, 5,55156, 53215,55159, 5,55157,53167,55163,21605,54597,54027,55167,31103,55169, 46863,54597,53270,55172,53231,55172,53188,55172,53215,55179,53255,55172, 53167,55182,53167,55172,53255,55186, 5,55172,52915,55190,53215,55193, 52915,55191,53255,55197,52915,55172, 5,55200,53215,55203, 5,55201, 53167,55207, 4,49713,51398,55211, 375,55211,51229,55214,53709,55211, 53740,55211,51909,55211,53797,55211,53800,55211, 340,55211,51803,55229, 54339,55210,54575,55233,53774,55211,53742,55211,53711,55211,53750,55211, 53716,55211,54663,55211,53533,55211, 1368,55211,52205,55251,54449,55251, 52809,55251,54295,55251, 9,55259, 7,55211, 265,55263,51229,55265, 89,55263,52915,55269, 265,55262,51803,55273, 2,55262,52205,55277, 52809,55277,54449,55277,54295,55277, 9,55285, 2,55263,52825,55289, 53318,55289, 9,55289,52915,55294,52915,55289, 9,55298,53746,55211, 46863,55302,53713,55211,46863,55306,31796,55211,25037,55211,25215,55211, 42338,55211,42076,55211,43053,55211,42959,55211,54575,55211,54339,55325, 54786,55211,51360,55211,53780,55211,52751,55211, 8148,55211, 9594,55211, 54377,55211,54439,55211,53758,55211,54700,55211,54826,55211,53286,55211, 53646,55211,53703,55353,53794,55211,53703,55357,53682,55211,53703,55361, 53371,55211, 842,55211, 9377,55367,54591,55211,54421,55211,54561,55211, 53681,55211,53255,55211,54597,55378, 483,55378,53679,55211,54573,55211, 55131,55211,54559,55211,54435,55211,19892,55211,53772,55211,53667,55396, 53672,55211,53731,55400,53667,55211,53799,55404,53772,55404,53731,55404, 46863,55410,46863,55404,53731,55414, 935,55211,20733,55211, 9991,55211, 41941,55211, 483,55424, 9565,55211, 483,55428, 1487,55211,54597,55211, 51229,55434, 53,55435, 1471,55435, 253,55435,53731,55434,53255,55434, 47546,55211, 66,55211, 1369,55451, 241,55211,31103,55454,18967,55211, 483,55458, 483,55211,42155,55462,41941,55462,51229,55462,53517,55462, 7971,55462, 9565,55462,53731,55462,53255,55462, 587,55462, 9377,55481, 18967,55462, 587,55463, 9195,55487,52915,55487,53674,55211,53703,55493, 46863,55495, 1369,55493,46863,55492,53703,55501,53391,55493,53649,55211, 53731,55506,31103,55211, 241,55510, 587,55511, 113,55211,46863,55516, 17455,55211,54551,55211, 1369,55523,53391,55523,51229,55211, 375,55528, 54597,55528, 483,55528, 1011,55211, 8165,55537, 9875,55537,20501,55537, 11,55537, 265,55211, 7,55546,51803,55549,54295,55547,47961,55553, 14611,55553, 4899,55553, 375,55553, 1369,55210,54985,55563,51601,55563, 54129,55563, 587,55210, 9366,55571,54575,55571,53360,55571, 9195,55571, 483,55578,52915,55571, 483,55582, 483,55571, 9195,55586,52915,55586, 31103,55571,53731,55211,53649,55594,53672,55594,53667,55594,46863,55600, 483,55594,54597,55594,46863,55594,53667,55608, 587,55211, 9377,55613, 483,55615, 483,55612, 9377,55619,21605,55211,21526,55622, 6,55623, 21527,55622,55627,55629, 7,55622, 7,55623,55625,55635, 6,55622, 18967,55638,55635,55641,18967,55622, 6,55645,55633,55647, 6,55644, 55635,55651, 1347,55211, 1369,55655,53799,55211,53667,55658, 2,55210, 51418,55663,51416,55663,51398,55663,51354,55663,51909,55663, 340,55663, 51803,55675,51873,55663,47974,55663,47589,55663, 8590,55663,14620,55663, 12537,55663,52021,55663,52029,55663,53106,55663, 375,55663,51229,55696, 52915,55696, 0,55663, 6,55703, 7,55663, 265,55706,51803,55709, 265,55707,51229,55713,52915,55713,47580,55663,51803,55719, 8861,55719, 8495,55663,47961,55724, 4899,55724,14611,55724,52915,55663, 375,55732, 14611,55663,51229,55736, 8495,55736, 4899,55663,51229,55742, 8495,55742, 47961,55663,51229,55748, 8495,55748, 265,55663, 7,55754,51803,55757, 55705,55755,55704,55754,55761,55763,55705,55754,55704,55755,55767,55769, 46863,55754, 8861,55773,51803,55773,46863,55663, 265,55778,51803,55781, 8861,55781, 265,55779,51229,55787, 8495,55787,51229,55663, 375,55792, 14611,55792, 4899,55792,47961,55792, 3,55210,54801,55803,52573,55803, 52115,55803,43053,55803,46863,55803, 2,55211, 7,55814,52205,55817, 52809,55817,54449,55817,54295,55817, 9,55825,54295,55815,54501,55829, 7,55829,54497,55833, 375,55829, 3,55211,55707,55839,52915,55841, 55706,55839,53793,55838,55779,55839, 6,55839,55732,55851,52915,55851, 55663,55854,55663,55851,52915,55858, 0,55851,55829,55851, 0,55850, 55663,55867, 0,55839, 6,55870,55663,55873, 0,55838,49713,55838, 55845,55879, 1,55838,55868,55883,55874,55883,55867,55883,55663,55888, 55873,55883,55663,55892,55849,55883,55663,55883,55867,55898,55873,55898, 46862,55839,55898,55905,55883,55905,55663,55908,55663,55905,55883,55912, 1,55839,55863,55917,55663,55919, 7,55839,55663,55922,55879,55925, 55879,55923,55663,55929,52591,55839,53792,55838,53703,55935,43027,55839, 43837,55839,39747,55839,53517,55838,53703,55945,46863,55947, 1369,55945, 46863,55944,53703,55953,53391,55945, 1369,55839,18967,55959, 11,55838, 1369,55963,18967,55839,46863,55967, 11,55839,46863,55971,53517,55839, 53799,55975,55847,55975,53772,55975,53731,55975,46863,55982,46863,55975, 53731,55986,55778,55839,55877,55991,46863,55839,55877,55995,55663,55997, 55663,55994,55877,56001,55663,55839, 7,56004,55879,56007,46863,56004, 55877,56011,46863,55838,53517,56014,53703,56017,53517,56015,53731,56021, 49204,55211,53517,56024,53703,56027,53517,56025,53731,56031,53792,55211, 3,56034,53703,56037, 3,56035,53667,56041, 7971,55211, 483,56044, 42155,55211, 483,56048,53517,55211, 483,56052,49204,56052,53703,56057, 49204,56053,53649,56061, 3,56053,53649,56065,53672,56065,53667,56065, 46863,56070, 483,56065,54597,56065,46863,56065,53667,56078, 3,56052, 53703,56083,46863,56085, 1369,56083,46863,56082,53703,56091,53391,56083, 46863,56052, 3,56096,53703,56099, 3,56097,53667,56103, 11,55211, 3,56106, 1369,56109, 3,56107, 483,56113,46863,55211,53746,56116, 53713,56116,53674,56116,53703,56123,53731,56116,53667,56126,53667,56116, 53731,56130, 113,56116, 3,56116,53517,56136,53703,56139,53517,56137, 53731,56143,53517,56116, 3,56146,53703,56149, 3,56147,53667,56153, 46863,49713,47982,56156,47983,56157,56159,56161,47983,56156,47982,56157, 56165,56167,49588,56156,49589,56157,56171,56173,49670,56156,49671,56157, 56177,56179,49589,56156,49588,56157,56183,56185,49671,56156,49670,56157, 56189,56191, 8453,56156, 273,56156,21522,56156,38266,56156, 1516,56156, 948,56156,20239,56156,37095,56156, 1477,56156, 281,56156,49617,56156, 49616,56157,56215,56217,49699,56156,49698,56157,56221,56223,49617,56157, 49616,56156,56227,56229,49699,56157,49698,56156,56233,56235, 1216,56156, 412,56156,12377,56156, 375,56156, 510,56156,38057,56156, 903,56248, 165,56156, 903,56252,21315,56156, 1011,56256, 1505,56156, 1011,56260, 413,56157,50785,56265,56241,56265, 1217,56157,56239,56271, 1216,56157, 413,56156, 412,56157,56277,56279, 1217,56156,56275,56283, 264,56157, 51777,56287,50908,56287,50785,56287, 241,56292, 241,56287,50785,56296, 375,56287, 264,56156,50207,56303,51765,56303,51677,56303,51615,56303, 241,56311, 341,56303, 1011,56156, 1505,56316,21315,56316, 903,56156, 165,56322,38057,56322, 483,56156, 9,56328, 9,56156, 483,56332, 5,56157, 4,56156,56337,56339,46863,56340, 2,56343, 2,56342, 49515,56340,49514,56340, 2,56341,56349,56353, 3,56341,56347,56357, 56351,56357, 2,56340,46863,56362,56357,56365,56357,56363, 3,56340, 56345,56371,56353,56371, 3,56157, 375,56377, 2,56156,56337,56381, 1,56383, 0,56382,56385,56387, 0,56383, 1,56382,56391,56393, 56377,56381,46863,56396, 4,56399, 4,56398,49631,56396,49630,56396, 4,56397,56405,56409, 5,56397,56403,56413,56407,56413, 4,56396, 46863,56418,56413,56421,56413,56419, 5,56396,56401,56427,56409,56427, 2,56157, 3,56156,56337,56435, 7,56437, 6,56436,56439,56441, 6,56437, 7,56436,56445,56447,56433,56435,46863,56451, 4,56452, 4,56453,49631,56451,49630,56451, 4,56451,46863,56462, 5,56451, 56457,56467, 4,56450,56467,56471,56459,56471, 5,56450,56465,56477, 56455,56477,56463,56477,56461,56477, 4,56157,56435,56487, 1,56489, 0,56488,56491,56493, 0,56489, 1,56488,56497,56499,56381,56487, 7,56503, 6,56502,56505,56507, 6,56503, 7,56502,56511,56513, 5,56156,56487,56517,46863,56519, 2,56520, 2,56521,49515,56519, 49514,56519, 2,56519,46863,56530, 3,56519,56525,56535, 2,56518, 56535,56539,56527,56539, 3,56518,56533,56545,56523,56545,56531,56545, 56529,56545, 1, 2,11709,56555,11632,56555,11035,56555,10468,56555, 17775,56555,11788,56555,12226,56555,11816,56555,11770,56555,44558,56555, 42181,56555,44243,56576,44438,56555,10856,56555, 3447,56555, 375,56584, 3448,56555,11705,56555,11033,56555,10516,56555,17773,56555,18735,56555, 10427,56555,10831,56600,10836,56555,10855,56555,16623,56555,16711,56555, 9533,56610,16718,56555, 3555,56555, 5882,56555, 9261,56555, 483,56621, 3699,56555, 15,56625, 6,56624,56627,56629, 14,56625, 7,56624, 56633,56635, 1999,56555, 15,56639, 6,56638,56641,56643, 14,56639, 7,56638,56647,56649,29450,56555,29731,56653,29659,56653,28791,56653, 29041,56653,38067,56555, 5,56663,38185,56665,42155,56554,44243,56669, 42471,56670,44966,56669,42471,56669,44243,56676, 1471,56554,36639,56681, 15390,56555,15383,56685,28715,56555,21527,56689,29229,56691, 7,56689, 29759,56695, 7,56688,28791,56699,29041,56699,29731,56699,29659,56699, 1005,56555,16877,56554,16893,56711, 9925,56555, 1369,56715, 9927,56717, 35336,56555, 989,56721,35278,56555, 1177,56725, 987,56555,35187,56728, 989,56731,36563,56554,36639,56735, 671,56554,36597,56554,36639,56741, 1418,56554, 1,56745, 4,56746, 4,56745, 1,56750, 147,56555, 35187,56754, 53,56757,17637,56555, 587,56760,10107,56763,35316,56555, 1471,56767,35330,56555, 53,56771,17638,56555,10107,56775, 1489,56555, 35187,56778, 1471,56781, 1179,56555,35187,56784, 1177,56787,37229,56555, 35187,56790,37223,56793, 9441,56555, 587,56796, 9439,56799,37230,56555, 37223,56803, 9442,56555, 9439,56807,45432,56555,42435,56811, 30,56555, 11731,56814,45433,56555,56669,56819,43099,56555,52259,56555, 483,56825, 44742,56555,44904,56555,52613,56555,52383,56555,52497,56555,39231,56555, 40447,56555,39083,56555,38797,56555,39019,56555,39301,56555,39429,56555, 39305,56555, 386,56555, 347,56555,54492,56555,45508,56555,56116,56555, 55812,56555,40987,56555,52909,56555,51598,56555,50419,56555,56332,56555, 52836,56555,52366,56555,36639,56555, 1471,56881,36563,56881,36597,56881, 181,56555,11731,56888,50579,56555,52319,56555,52323,56555,54436,56555, 54406,56555,52532,56555,52514,56555,55520,56555,44930,56555,39317,56555, 51141,56555,40123,56555,39228,56555,40676,56555,47366,56555,40682,56555, 52599,56555,50655,56555,52531,56555,36538,56555,36048,56555,37594,56555, 42918,56555,40922,56555,39292,56555,11111,56555,11113,56555,11187,56555, 17508,56555,17180,56555, 3280,56555, 3574,56555, 3568,56555,12216,56555, 25,56958,11613,56555, 25,56962,48406,56555,48400,56555,48500,56555, 43292,56555,47534,56555,17494,56555,39065,56555,48961,56555,49162,56555, 17496,56555,11179,56555,47892,56555,11546,56555,11207,56555, 5878,56555, 52446,56555,35506,56555,39035,56555,40087,56555, 9,57003,10513,56555, 9,57006,36102,56555, 253,57011, 53,57011, 117,57011, 1471,57011, 7968,56555,53813,57021,10107,57021,11067,57021,37282,56555,53813,57029, 37417,57029,10107,57029,35652,56555, 253,57037, 1471,57037, 809,57037, 53,57037,38293,56555,53813,57047,37417,57047,38275,57047,10107,57047, 1397,56555,35187,57056,52439,56555, 265,57060,40127,56555,43318,56555, 48750,56555,53813,57069,10107,57069,36100,56555, 253,57075, 53,57075, 1471,57075, 9404,56555, 483,57083, 8053,56555, 9,57087,10465,56555, 9,57090,11936,56555,10119,56555,10185,56555,53885,56555,10117,56555, 45490,56555, 33,57105, 8212,56555, 9,57109,11812,56555, 9,57112, 53899,56555, 6719,56555, 11,57119, 5,57120, 6,57119, 5,57124, 5,57119, 6,57128, 6,57129, 7,57119,57133,57135, 15,57119, 6,57118,57139,57141, 14,57119, 7,57118,57131,57147,57127,57147, 57123,57147,57145,57147, 6787,56555, 5,57157, 4,57157, 12,57157, 13,57156,57163,57165, 13,57157, 12,57156,57169,57171, 5,57156, 57161,57175, 4,57156,57159,57179,10831,56555, 375,57182,44243,57182, 10427,57182, 9,57183,11529,56555,46863,57192, 483,57192,17640,56555, 39226,56555,48572,56555,47410,56555,40568,56555,47374,56555,47674,56555, 17656,56555,47676,56555,47634,56555,48112,56555,47412,56555, 5814,56555, 918,56555,36256,56555,46863,57226,48466,56555,49713,57230,35187,57230, 11,57231,47608,56555, 903,57238,52756,56555,46863,57242,48620,56555, 247,56555,46863,57248, 1419,56555,56749,57253,56753,57253,25519,57253, 1841,57253, 1883,57253,22679,57253, 5,57253,22677,57267,14065,57253, 5175,57253,40565,56555, 587,57274, 922,56555,51593,56555,46863,57280, 47640,56555, 11,57285, 1011,57284, 11,57284,35718,56555, 9439,57293, 37223,57293, 9381,57293,37157,57293,35877,57293,35881,57293, 9383,57293, 37163,57293,35883,57293, 17,57293,37145,57313, 9377,57313,35867,57313, 51051,56555, 375,57321,50959,56555, 9,57325,39205,56555, 10,57329, 10,57328, 11,57329,57333,57335, 1011,57328, 11,57328,57331,57341, 48402,56555, 9,57344,48560,56555, 903,57348,36544,56555, 6,57353, 36661,57355,36675,57353, 8067,57353, 7979,57353, 7981,57353,39747,57353, 43837,57353,43027,57353, 1369,57353, 7971,57373, 934,56555,46863,57376, 668,56555, 5,57381,22605,57383,22615,57381, 3135,57381, 2009,57381, 14065,57381, 5175,57381,53905,56555,55432,56555,10303,56555,42661,56555, 25,56555,11613,57404,12216,57404, 9,57404,11731,57410,35187,57404, 253,57415, 53,57415, 117,57415, 1471,57415,11731,57404, 9,57424, 8165,56555, 67,57428, 9,57431, 7947,56555, 587,57434,53813,57437, 10107,57437,11067,57437,17049,56555,46863,57444, 165,56555,43215,57448, 113,56555,54295,57452, 767,56555, 483,57457, 9377,57459, 9377,57456, 483,57463, 803,56555,17455,57466, 375,56555,10831,57470, 3447,57470, 305,57470,17125,57470, 510,56555, 11,56555, 33,57483,44243,57485, 44243,57482, 33,57489,39205,57482,47640,57482,46863,57482, 903,57496, 35187,57482,43027,57501,43837,57501, 8067,57501, 7979,57501,39747,57501, 7981,57501, 1369,57501, 7971,57515, 903,57482,46863,57518, 9,56555, 10465,57522,11812,57522,10513,57522, 25,57522,11731,57530,56156,57522, 40675,57522, 3565,57522, 3573,57522, 3273,57522,11731,57522, 25,57544, 48402,57522,17455,57522, 5843,57522, 11,57523,46863,57555,49713,57522, 46863,57558, 903,57522,35187,57522,46863,57564,46863,57522,49713,57568, 35187,57568, 11,57569, 587,57522, 5175,57577,14065,57577, 3135,57577, 2009,57577, 483,57522,55839,56555, 483,57589, 5771,56555, 903,57592, 6705,56555, 1369,57597, 6707,57599, 6711,57599, 6715,57599, 3697,56555, 16,57607, 16,57606, 17,57607,57611,57613, 17,57606,57609,57617, 3709,56555, 8075,56555, 9,57623, 3273,56555, 9,57626, 3423,56555, 16,57631, 16,57630, 17,57631,57635,57637, 17,57630,57633,57641, 3661,56555, 16,57645, 16,57644, 17,57645,57649,57651, 17,57644, 57647,57655, 3681,56555, 3357,56555,53675,56555, 9,57663,42379,56555, 9,57667, 3573,56555, 9,57670, 3565,56555, 9,57674,52878,56555, 15436,56555, 375,57681,54550,56555,17232,56555,38305,57686, 4935,56555, 6,57691, 5,57692, 7,57691, 5,57691, 6,57698, 6,57699, 57697,57703, 6,57690, 15,57691,57707,57709, 7,57690,57695,57713, 57701,57713, 14,57691,57713,57719,55803,56555,46863,57722,16127,56555, 6,57727, 5,57728, 7,57727, 5,57727, 6,57734, 6,57735, 57733,57739, 6,57726, 15,57727,57743,57745, 7,57726,57731,57749, 57737,57749, 14,57727,57749,57755,54477,56555,46863,57758,49155,56555, 483,57762, 5843,56555, 955,57766, 9,57766, 5313,56555, 9802,56555, 48736,56555, 9434,56555, 483,57779,15309,56555, 413,57782,15383,57785, 413,57783,15335,57789, 8,56554, 4,57793, 1,57794,57381,57797, 57577,57797, 1,57793, 4,57802,57381,57805,57577,57805, 10,56554, 7,57811, 2,57812,57353,57815,57501,57815, 2,57811, 7,57820, 57353,57823,57501,57823,57515,57811,57373,57811, 1368,57811,57501,57833, 57353,57833, 3867,57811, 8277,57811, 3997,57811, 4067,57811, 9459,57811, 8953,57811,57483,57811, 9,57811, 14,56555,38881,57855, 11,56554, 44778,57859,44243,57859, 25,57862,47640,57859, 25,57859,44243,57868, 48466,57859, 903,57859,46863,57874,46863,57859, 903,57878, 9,57878, 9,57859,46863,57884, 9,56554,40903,57889,40053,57889,43307,57889, 5019,57889,12361,57889, 16,56555,19625,57901,21105,57901,21549,57901, 17591,57901, 17,56554,36639,57911, 10,56555,57859,57915,11731,56555, 30,57918, 181,57918,54295,57918, 9,57918, 25,57926, 145,57918, 25,57918, 9,57932, 67,56555, 9,57937, 8165,57939, 8165,57936, 9,57943,17635,56555, 155,57946, 903,57946, 145,56555,11731,57952, 17695,56555, 1369,57957, 7971,57959,53517,57959,17053,57959,17699,57959, 42155,57959, 155,56555,17635,57970,10305,56555,42699,56555,10307,56555, 566,56555,53813,57981,10107,57981, 256,56555,42810,56555,17125,57988, 1170,56555, 629,56555, 1413,56555,37408,56555,25793,57999,41019,57999, 8495,57999, 265,57998, 1346,56555,48884,56555,27021,58011,52915,58011, 9195,58011,20763,58011, 340,56555, 331,58021,35187,58020,38270,56555, 766,56555,25519,58029, 802,56555, 9366,58033, 9195,58033, 483,58036, 483,58033, 9195,58040,31103,58033,42729,56555, 257,56555,44243,58048, 1487,56555,55211,58052,44243,56555,10831,58056,42181,58056,42155,58057, 42471,58063,42155,58056,42435,58067, 9533,58056,37145,58056, 11,58057, 25,58075,35187,58056,17125,58056, 11,58056, 33,58083,49713,58056, 257,58056,55211,56555,46863,58090,17455,58090, 1487,58090, 1197,56555, 4,58099, 5,58098,58101,58103, 5,58099, 4,58098,58107,58109, 1505,56555,45002,56555,42155,56555,42435,58117,44243,58119,44243,58116, 42435,58123, 305,56555, 375,58126,35187,58126, 253,58131, 1471,58131, 53,58131, 713,56555,35187,58138, 253,58141, 1471,58141, 809,58141, 53,58141,37241,56555, 587,58150,53813,58153,37417,58153,10107,58153, 955,56555, 5843,58160,48739,56555, 587,58164,53813,58167,10107,58167, 40461,56555, 9,58173,52501,56555,35187,58176, 241,58176, 9801,56555, 17,58182, 4,58183,58185,58187, 5,58183,57901,58191, 4,58182, 7,58194,58191,58197, 5,58182,48735,56555, 17,58202, 4,58203, 58205,58207, 5,58203,57901,58211, 4,58202, 7,58214,58211,58217, 5,58202, 9533,56555,16711,58222,44243,58222,37145,56555,44243,58228, 8861,56555, 5,58233, 6,58235, 6,58234, 14,58233, 15,58233, 6,58233, 5,58244, 7,58233,58237,58249, 6,58232,58243,58253, 7,58232,58239,58257,58247,58257,58241,58257, 9377,56555, 767,58264, 483,58267, 4,58264, 483,58271, 1217,56555, 483,58275, 413,56555, 15309,58278,15383,58281,15309,58279,15363,58285,46863,58278, 412,56555, 483,58291, 1216,56555,46863,58294,56156,56555, 9,58298, 1011,56555, 39205,58302,47640,58302,46863,58302, 903,58308, 7,58302, 903,58302, 46863,58314,43215,58302, 7,58319,38305,56555,17232,58322, 7,58322, 17125,58326,17125,58322, 7,58330,49713,56555,48466,58334, 9,58334, 46863,58338,44243,58334,46863,58334, 9,58344, 241,56555,52501,58348, 7,58348, 7,58349, 265,58355, 265,58348, 483,58359, 483,56555, 40675,58362,43215,58362,49155,58362,11529,58362, 903,58362, 9,58362, 5,58362,53813,58377,10107,58377, 5,58363,55211,58383,40675,56555, 7,58387, 9,58386, 483,58386,46863,58386,35187,56555,37229,58396, 37223,58399, 1177,58397, 1179,58403, 989,58397, 987,58407, 1179,58396, 1177,58411, 987,58396, 989,58415, 1489,58396, 1471,58419, 147,58396, 53,58423, 117,58397, 25,58427, 809,58397, 713,58431, 2,58396, 7,58435, 2,58436,58397,58439, 5,58436,58441,58443, 5,58435, 7,58446, 10,58435, 4,58396, 7,58453, 4,58454,58397,58457, 3,58454,58459,58461, 3,58453, 7,58464, 586,58453, 1368,58396, 7,58471, 5,58472, 5,58471, 7,58476, 10,58471, 16,58396, 7,58483, 3,58484, 3,58483, 7,58488, 586,58483,44243,58396, 52501,58396, 340,58396,48466,58396, 1397,58396, 25,58396, 1471,58505, 253,58505, 53,58505, 117,58505, 713,58396, 53,58515, 253,58515, 1471,58515, 809,58515, 53,58397, 147,58525, 305,58525, 713,58525, 25,58525, 1471,58397, 1489,58535, 305,58535, 25,58535, 713,58535, 305,58396, 253,58545, 1471,58545, 53,58545, 253,58397, 305,58553, 25,58553, 713,58553, 9,58396,46863,58560, 1369,58397, 9891,58565, 9927,58565,58475,58565,58479,58565,58443,58565,58449,58565, 4,58565, 9895,58565,19687,58565,20843,58565,21127,58565,58451,58565,58481,58565, 11,58565, 9875,58593,58435,58593,58471,58593, 17,58397,10111,58601, 10159,58601,58487,58601,58491,58601,36729,58601,58461,58601,58467,58601, 2,58601,10113,58601,58469,58601,58493,58601, 587,58601,10107,58625, 58453,58625,58483,58625,46863,58396, 9,58632, 11,58396,57815,58637, 57823,58637, 8067,58637, 7979,58637, 3,58637,58601,58647,58617,58637, 7981,58637,39747,58637,43027,58637,43837,58637,57833,58637, 1369,58637, 7971,58663,57811,58663, 587,58396,35877,58669,35881,58669, 9439,58669, 9381,58669, 5,58669,58565,58679,58579,58669,37223,58669,37157,58669, 9383,58669,37163,58669,35883,58669, 17,58669, 9377,58695,37145,58695, 35867,58695, 6,58396, 7,58396,25793,58705,41019,58705, 8495,58705, 265,58704, 6,58397,36661,58715,58705,58715,57999,58715, 7,58397, 58703,58723,58027,58723, 265,58396, 6,58728, 7,58728, 6,58729, 58733,58735, 7,58729,58731,58739, 903,56555,17455,58742,17635,58742, 47608,58742, 5771,58742,48560,58742, 11,58743,46863,58755, 9,58742, 483,58742,46863,58742, 11,58763, 1011,58762, 11,58762, 11,58742, 46863,58770, 7,58743, 8165,58775, 1011,58742,46863,58778,46863,56555, 21036,58782,21036,58783,21037,58782,58787,58789,21037,58783,58785,58793, 54477,58782,55211,58782,55803,58782,52756,58782,51593,58782,40675,58782, 43215,58782,36256,58782,11529,58782, 934,58782, 247,58782, 1216,58782, 413,58782,17049,58782, 11,58783, 903,58825, 9,58825, 9,58782, 49713,58830,35187,58830, 11,58831, 1011,58782, 903,58838,35187,58782, 9,58842, 903,58782, 11,58847, 1011,58846, 11,58846, 11,58782, 903,58854, 5,58782,27021,58859,52915,58859, 9195,58859,20763,58859, 49713,58782, 9,58868, 1275,56555, 17,58872, 4,58872, 7,58876, 5,58872, 4,58873,58875,58883, 5,58873,58879,58887,57901,58887, 265,56555,37408,58892,52439,58892, 7,58892, 331,58899,35187,58898, 7,58893, 375,58905, 241,58892, 483,58909,38305,58893, 375,58913, 35187,58892, 6,58916, 7,58916, 6,58917,58921,58923, 7,58917, 58919,58927, 587,56555, 9441,58930, 9439,58933,17637,58930,10107,58937, 37417,58931,37241,58941,11067,58931, 7947,58945, 7,58930, 4,58949, 7,58950,58931,58953, 0,58950,58955,58957, 0,58949, 4,58960, 35186,58949, 1,58930, 4,58967, 1,58968,58931,58971, 6,58968, 58973,58975, 6,58967, 4,58978, 8,58967, 16,58930, 4,58985, 0,58986, 0,58985, 4,58990,35186,58985,22807,58931,37241,58930, 10107,58999,53813,58999,37417,58999, 7947,58930,53813,59007,10107,59007, 11067,59007,10107,58931,17637,59015,48739,59015,37241,59015, 7947,59015, 48739,58930,53813,59025,10107,59025,53813,58931,48739,59031,37241,59031, 7947,59031,40565,58930, 17,58931, 1985,59041, 3721,59041,58989,59041, 58993,59041, 5299,59041,58957,59041,58963,59041, 1,59041,35233,59041, 35917,59041, 4861,59041,17563,59041,58965,59041,58995,59041,35187,59041, 53,59071,58949,59071,58985,59071,35187,58930,35881,59079,35877,59079, 37223,59079,37157,59079, 6,59079, 9439,59079, 9381,59079,37163,59079, 9383,59079,35883,59079, 17,59079,37145,59101, 9377,59101,35867,59101, 9,58930,57797,59109,57805,59109, 3135,59109, 2009,59109, 0,59109, 59041,59119,59057,59109, 5175,59109,14065,59109, 4,58930, 9366,59129, 9195,59129, 483,59132, 483,59129, 9195,59136,31103,59129, 5,58930, 25519,59143, 5,58931,25503,59147,24623,59147,30387,59147,58565,59147, 22605,59147,36526,56555, 6,59158, 7,59158, 6,59159,59163,59165, 7,59159,59161,59169,40920,56555, 7,59172,43400,56555, 7,59177, 16065,56555, 5,59181, 7,59182, 7,59183,56555,59186, 6,59182, 59189,59191, 6,59183,56555,59183, 7,59196,59191,59199, 7,59197, 59195,59203,15029,56555, 5,59206, 6,59209, 6,59208, 14,59206, 15,59206, 6,59206, 5,59218, 7,59206,59211,59223, 375,59223, 6,59207,59217,59229, 7,59207,59221,59233,59213,59233, 59,59233, 59215,59233, 331,59233, 1325,59233, 265,59233,43215,56555, 9,59249, 483,59248,46863,59248, 165,59248, 1011,59248, 7,59259,17125,56555, 4,59262, 7,59265, 1011,59266, 1011,59265, 7,59270, 7,59271, 1170,59265, 5,59263,57993,59279,58313,59279,17129,59279,42811,59263, 42811,59262,44243,59262,42810,59262,59287,59293,42810,59263,59289,59297, 375,59262, 6,59262,59269,59303,59273,59303,59277,59303, 7,59262, 38305,59310, 6,59263,59275,59315,59311,59315, 7,59263,59303,59321, 38305,59262, 7,59324,54295,56555,11731,59328, 113,59328, 5,59328, 5,59329,57901,59337,17455,56555, 7,59341, 4,59342, 4,59343, 16,59341, 17,59341,55211,59340, 803,59340, 903,59340, 9,59340, 4,59340,59351,59361, 5,59340,59345,59365,59349,59365, 4,59341, 7,59370,59365,59373, 5,59341,59347,59377, 4,56554,26454,59381, 26375,59381, 8672,59381, 8743,59381,41692,59381,41607,59381, 8770,59381, 8729,59381, 3795,59381,47953,59381,48062,59381,47961,59381,48009,59404, 48009,59381,47961,59408,26219,59381,26415,59412,41417,59381,41653,59416, 44832,59381,31770,59381, 8757,59381, 8647,59424,41653,59381,41417,59428, 26415,59381,26219,59432, 8647,59381, 305,59436, 8757,59436, 8605,59381, 47580,59381,47933,59445, 8684,59381, 8717,59449, 8916,59381,44243,59381, 483,59454,41502,59381,41559,59459, 340,59381, 8717,59463, 3785,59463, 8495,59463, 375,59381, 8861,59470,46863,59470,47488,59381,26292,59381, 26331,59479, 9,59381,31103,59482, 305,59381, 8647,59486, 7,59381, 1,59491, 264,59492, 264,59493,25793,59491,26415,59499,41019,59491, 41653,59503, 8495,59491, 305,59507, 8757,59507, 8495,59490, 8717,59513, 41019,59490,41559,59517, 265,59491,59497,59521, 8861,59521,46863,59521, 25793,59490,26331,59529, 265,59490, 8717,59533,59495,59533, 3785,59533, 8495,59533,31103,59381, 9,59542, 483,59381,44243,59546,46863,59381, 265,59551,48009,59553, 265,59550,47933,59557, 375,59550,41019,59381, 7,59563,41417,59565, 7,59562,41559,59569, 265,59381,46863,59573, 47961,59575,46863,59572,47933,59579, 7,59573, 8647,59583, 7,59572, 8717,59587, 3785,59587, 8495,59587,25793,59381, 7,59595,26219,59597, 7,59594,26331,59601, 8495,59381, 7,59604, 8717,59607, 7,59605, 8647,59611, 8861,59381, 375,59614, 5,56554,26777,59619, 9741,59619, 9745,59619,26781,59619,30349,59619,26857,59619,26933,59619, 2,59619, 7,59634,57353,59637,57501,59637,58637,59637, 6,59635, 9777,59619, 1368,59619,57501,59649,57353,59649,58637,59649,57515,59619,57373,59619, 58663,59619, 9771,59619,40077,59619,31598,59619,55462,59619,50733,59619, 37519,59619,35690,59619, 8982,59619,55211,59619, 483,59678, 668,59619, 9731,59683,26625,59683, 1419,59619, 9731,59689,26625,59689, 17,59619, 8861,59694, 9,59619, 587,59698, 9731,59701,26625,59701, 375,59619, 35187,59706, 6,59619, 7,59619, 5,59713, 2,59712,57353,59717, 57501,59717,58637,59717, 5,59712,58396,59725,59717,59727,35187,59725, 56555,59730,59717,59733,56555,59725,35187,59736,59717,59739, 7,59618, 3867,59743, 8277,59743, 3997,59743, 4067,59743, 9459,59743, 8953,59743, 31103,59619,26625,59756, 483,59619,55211,59760, 587,59619, 9,59764, 9731,59767,26625,59767,35187,59619, 375,59772,26625,59619,31103,59776, 8861,59619, 7,59781, 17,59780, 6,56554,36633,59787,36627,59787, 1,59787, 4,59792,57253,59795,57381,59795,57577,59795,59109,59795, 5,59792,38304,59787,39987,59787,36544,59787, 9875,59811,20501,59811, 11,59787,35187,59816,20501,59819, 9875,59819, 5,59787, 1,59824, 4,59787, 6,59829, 1369,59831,56555,59833, 1,59828,57253,59837, 57381,59837,57577,59837,59109,59837,59835,59837, 6,59828,58930,59849, 59837,59851, 587,59849,56555,59854,59837,59857,56555,59849, 587,59860, 59837,59863,35187,59787, 11,59866,20501,59869, 9875,59869, 7,56554, 4904,59875,17586,59875,17609,59875,40685,59875,40039,59875,42991,59875, 9484,59875, 272,59875, 1476,59875, 280,59875, 949,59875, 1517,59875, 1197,59875, 4903,59875, 9,59902,17579,59875, 9,59906, 11,59875, 9377,59910, 9,59875, 4903,59914,17579,59914, 253,59875, 265,59920, 53,59875, 265,59924, 1471,59875, 265,59928, 5,59874, 3867,59933, 8277,59933, 4067,59933, 3997,59933, 8953,59933, 9459,59933, 265,59875, 253,59946, 1471,59946, 53,59946, 9377,59875, 11,59954, 5,59955, 7,56555,59826,59960,59827,59961,59963,59965,59827,59960,59826,59961, 59969,59971,59804,59960,59805,59961,59975,59977,59805,59960,59804,59961, 59981,59983,21036,59960,14072,59960,14073,59960,14072,59961,59991,59993, 59183,59960,59191,59997,59183,59961,59185,60001, 4970,59960, 4971,59960, 4970,59961,60007,60009,16169,59961, 9617,60013,39786,59961,59807,59961, 59806,59961,28715,59960,28791,60023,29731,60023,29659,60023,29041,60023, 21036,59961,21037,59960,60033,60035,38304,59961,59787,60038, 483,60038, 38304,59960,60019,60045,59787,60045, 483,60045,18967,59961, 5,60053, 5,60052, 2,59961, 0,60059,56555,60061, 5,60063,59961,60065, 7,60064,60067,60069,59960,60065, 6,60064,60073,60075, 1,59961, 3,60079, 5,60081,56555,60082,56555,60081, 5,60086, 5,60087, 1011,60079,56555,60093, 5,60079, 1,59960,21036,60099, 3,60099, 56555,60103, 5,60105, 5,60104, 5,60103,56555,60110, 5,60099, 18967,60114,18967,60099, 5,60118, 5,60119, 2,59960,59811,60125, 36545,60125,59787,60129,59819,60125,59869,60125, 15,60125,29659,59961, 29077,60139,39787,59961,60045,60143,32103,59961,41746,59961,26106,59961, 8800,59961,36526,59960,40920,59960, 1163,59961,41019,59961, 11,60160, 35187,60161,59619,59961, 4971,59961,60005,60169,14073,59961,59989,60173, 4555,59961, 559,59961, 39,59961, 8495,59961,35187,60183, 11,60182, 15029,59960, 375,60189,17125,59960,38305,60192, 11,59961,41019,60196, 25793,60196, 8495,60196, 265,59961, 3447,60205,10831,60205, 305,60205, 17125,60205,11731,60205, 567,59961,46863,60217, 15,59961, 3651,60221, 1993,60221, 4903,60221,17579,60221, 241,59960,38305,59960,60017,60233, 60021,60233,60041,60233,60043,60233,60039,60233,59787,60243, 483,60243, 17125,60232, 1011,59960,59279,60251,21037,59961,59987,60255, 11,60255, 28715,59961,29533,60261,20273,60261, 9617,60261,35187,59960,25793,60269, 41019,60269, 8495,60269,58715,60269, 265,60268, 265,59960, 331,60281, 35187,60280,38305,59961,37845,60287,37844,60286,60289,60291,37844,60287, 37845,60286,60295,60297,60048,60287,59787,60287,60045,60302,60050,60287, 60045,60287,59787,60308, 483,60308, 483,60287,60045,60314, 1011,59961, 25793,59961,35187,60321, 11,60320, 4,59960,60091,60327,60107,60327, 60033,60327,60101,60327,59337,60327,58191,60327,58211,60327,60057,60327, 60117,60327,60121,60327,21549,60327,21105,60327,19625,60327,58887,60327, 17591,60327, 5,59960, 1,60359, 3,60361,60205,60363,60255,60359, 4,59961,60085,60369,60089,60369,60113,60369,60109,60369,57685,60369, 59335,60369,58201,60369,58221,60369,57775,60369,57777,60369,60095,60369, 60055,60369,60123,60369,31103,60369,21575,60369,58881,60369,58009,60369, 17579,60369, 4903,60369,48408,60369,46863,60369, 483,60410, 483,60369, 46863,60414, 5,59961,18967,60418,60327,60421, 1368,60419, 2,60419, 7,60426, 7,60419, 2,60430,59787,59961,38304,60435,60287,60437, 38304,60434,60233,60441, 483,59961,38304,60445,60287,60447,38304,60444, 60233,60451, 5,56555,60081,60454,60369,60457,60103,60454,60369,60461, 1,60455, 3,60464, 1,60454,59491,60469,59490,60469,59381,60469, 7,60474, 7,60475, 5,60469,59961,60481, 6,60468,60473,60485, 60477,60485, 7,60468,60471,60491,59381,60491, 6,60469,59381,60497, 60491,60498,60479,60497,60494,60497,60491,60497,59381,60506, 7,60469, 59381,60510,60485,60513,60485,60511,59381,60517, 2,60454,60261,60521, 60483,60521,53813,60455, 483,60527,52915,60455,46863,60531,59875,60455, 9801,60454,60369,60537,48735,60454,60369,60541,10107,60455, 483,60545, 9195,60455,46863,60549,54295,60454,60369,60553, 587,60455,17455,60557, 11731,60557, 9,60455, 8861,60563, 17,60455, 587,60567,26625,60569, 9731,60569,60467,60569, 483,60454,53813,60577,10107,60577,20763,60455, 46863,60583,46863,60454,27021,60587,52915,60587, 9195,60587,20763,60587, 1275,60454,60369,60597, 587,60454,25519,60601,27021,60455,46863,60605, 6,60454,38881,60609,59381,60455,30091,60455,31103,60615, 4,56555, 2,60619, 0,60621,56555,60623, 5,60625, 7,60621,60627,60629, 1,60618,59689,60633, 1418,60633,59619,60637,59683,60633, 669,60633, 59619,60643,60569,60633,59701,60633,59767,60633, 15,60633, 1369,60652, 59619,60655, 1369,60633, 15,60658,59619,60661, 842,60619, 9377,60665, 59787,60619, 9377,60618, 483,60671, 587,60619, 483,60674, 9377,60677, 9377,60675, 483,60681,21527,60619, 9,60685,31103,60619, 587,60689, 587,60618, 9366,60693, 9195,60693, 483,60696, 483,60693, 9195,60700, 31103,60693, 483,60619, 587,60706, 9377,60709, 9377,60707, 587,60707, 9195,60715, 7,60618,59337,60719,58191,60719,58211,60719,21105,60719, 21549,60719,19625,60719,58887,60719,17591,60719, 6,60619, 1,60737, 4,60738, 4,60737, 1,60742, 1369,60737,56555,60747,60741,60749, 60745,60749, 7,60619, 2,60755,21183,60755, 9377,60755,59619,60619, 38305,60619, 3,60764, 2,60764,56555,60765, 6,60770,60769,60773, 6,60765,56555,60776,60769,60779, 1011,60619,46862,60782,46862,60783, 46863,60783,60785,60789,46863,60782,60787,60793, 6,56555,36303,60797, 36302,60796,60799,60801,36303,60796,36302,60797,60805,60807,40946,60796, 40946,60797,60765,60796,60769,60815, 2,60797, 0,60818,40947,60796, 60813,60823,40947,60797,60811,60827,60765,60797,60767,60831,59381,60797, 17,60797,35187,60837,20501,60839,60125,60839,60821,60839, 9875,60839, 35187,60796,58723,60849, 5,60796,38881,60853, 0, 3, 8169,60857, 8028,60857, 8173,60857, 8214,60857, 8167,60857, 8154,60857, 8026,60857, 8054,60857,17728,60857,60210,60857,60283,60857,58128,60857,58023,60857, 57476,60857,56854,60857,56856,60857,58901,60857,58906,60857,58122,60857, 58066,60857,56810,60857,56822,60857,16743,60857,16696,60857, 4810,60857, 16745,60857,16729,60857,16714,60857, 6648,60857, 2079,60857, 375,60916, 2086,60857,16733,60857,16565,60857,16683,60924,16692,60857,16735,60857, 16739,60857,51942,60857,44534,60857,42383,60857,44243,60938,44440,60857, 16747,60857, 75,60857, 6625,60946, 6632,60857, 6645,60857,60079,60857, 5,60955,60327,60957, 5,60954,60369,60961,60096,60857,60369,60965, 1325,60856,40829,60969, 1173,60857,17591,60856,17603,60975,10039,60857, 1275,60979,10041,60981,38560,60857, 1205,60985, 1203,60857,38305,60988, 1205,60991,38514,60857, 1007,60995,40741,60856,40829,60999, 531,60856, 1290,60856, 0,61005, 5,61006, 5,61005, 0,61010,40769,60856, 40829,61015,38548,60857, 1325,61019, 177,60857,38305,61022, 59,61025, 17053,60857, 483,61028,10081,61031, 1009,60857,38305,61034, 1007,61037, 1365,60857,38305,61040, 1325,61043,38566,60857, 59,61047,17054,60857, 10081,61051,42109,60857,38305,61054,42103,61057, 9527,60857, 483,61060, 9525,61063,42110,60857,42103,61067, 9528,60857, 9525,61071, 386,60857, 56555,61074, 8150,60857, 113,61078, 347,60857,56555,61082,58905,60857, 375,61086,45432,60857,56555,61090,43099,60857,56555,61094,40829,60857, 1325,61099,40741,61099,40769,61099,60535,60857, 9,61107,57916,60857, 9,61111,57851,60857, 9,61115,17727,60857, 113,61118,57060,60857, 8309,60857,60230,60857,57986,60857,57998,60857,60268,60857,58352,60857, 58704,60857,13820,60857,13772,60857,57994,60857,58056,60857,42155,61144, 36101,60857, 375,61149,37407,60857,47392,60857,36532,60857,36536,60857, 57284,60857,58760,60857,58762,60857,58846,60857,58372,60857,57278,60857, 57996,60857,57470,60857, 305,61174,60205,60857, 305,61178,58374,60857, 58830,60857,57586,60857,57480,60857,57230,60857,57568,60857,40684,60857, 36542,60857, 375,61197,42990,60857,40038,60857,37498,60857,36754,60857, 35796,60857, 8225,60857, 8242,60857, 128,60857, 7971,61214, 101,60857, 7971,61218,37362,60857,48122,60857,12526,60857, 6698,60857,47690,60857, 38704,60857,11943,60857, 9,61235,12343,60857, 5,61239, 4,61238, 61241,61243, 4,61239, 5,61238,61247,61249,40132,60857, 331,61253, 59,61253, 97,61253, 1325,61253, 8148,60857,48753,61263,10081,61263, 11759,61263,39044,60857, 331,61271, 1325,61271, 571,61271, 59,61271, 42338,60857,48753,61281,44451,61281,10081,61281,42959,60857,48753,61289, 44451,61289,42825,61289,10081,61289, 629,60857,56555,61298,38305,61298, 289,60857, 587,61305,10287,60857,17660,60857,10262,60857,40130,60857, 331,61315, 59,61315, 1325,61315,53780,60857,48753,61323,10081,61323, 60668,60857, 9,61329, 8213,60857, 9,61332,11813,60857, 9,61337, 17030,60857, 8211,60857, 8301,60857, 8209,60857,38110,60857, 8052,60857, 9,61350,10464,60857, 9,61355,10527,60857, 9,61359, 4727,60857, 9,61363,11989,60857, 11,61367, 5,61368, 6,61367, 5,61372, 5,61367, 6,61376, 6,61377, 7,61367,61381,61383, 15,61367, 6,61366,61387,61389, 14,61367, 7,61366,61379,61395,61375,61395, 61371,61395,61393,61395,12371,60857, 5,61405, 4,61405, 12,61405, 13,61404,61411,61413, 13,61405, 12,61404,61417,61419, 5,61404, 61409,61423, 4,61404,61407,61427, 6625,60857,44243,61430, 375,61430, 75,61430, 9,61431, 6685,60857, 483,61440,46863,61440,17060,60857, 35768,60857,50524,60857,52806,60857,50480,60857,36296,60857,50990,60857, 510,60857,56555,61460,47608,60857,36293,60857, 483,61466, 295,60857, 49713,61470, 1291,60857,61009,61475,61013,61475,20033,61475, 1831,61475, 1881,61475,19319,61475, 4,61475,19317,61489,15899,61475, 4579,61475, 48561,60857, 9,61497, 922,60857,56555,61500,51937,60857, 375,61504, 57915,60857,57859,61508, 9,61511,39234,60857,60853,61515,60609,61515, 9525,61515,42103,61515, 9517,61515,41989,61515,39485,61515,39481,61515, 57855,61515, 9519,61515,41995,61515,39487,61515, 15,61515, 9513,61541, 41941,61541,39477,61541,50958,60857, 9,61548,35761,60857, 9,61552, 35719,60857, 375,61557,57482,60857,57852,61561,57811,61561, 9,61564, 9,61561,57811,61568,57522,60857, 483,61572,46863,61572, 1072,60857, 1108,60857,49713,61580, 524,60857, 4,61585,19301,61587,19311,61585, 3195,61585, 1965,61585,15899,61585, 4579,61585,40704,60857, 7,61601, 40799,61603,40813,61601, 7961,61601, 7951,61601, 7953,61601,35893,61601, 37897,61601,38299,61601, 1275,61601, 7947,61621,52756,60857, 1011,61624, 10245,60857,37339,60857, 33,60857,10385,61632, 9,61635, 7971,60857, 101,61638, 128,61638, 9,61638, 113,61644, 483,61638,48753,61649, 10081,61649,11759,61649, 113,61638, 9,61656, 21,60857,38305,61660, 331,61663, 59,61663, 97,61663, 1325,61663,47640,60857,56555,61672, 17635,60857,12377,61676,11731,60857,13737,61680, 567,60857,46863,61685, 55211,60857,44243,60857, 6625,61690,42383,61690,58116,61690,42155,61690, 56555,61698,56555,61690,42155,61702, 1505,60857,38057,61706, 288,60857, 46863,61711,48466,60857,56555,61714, 11,60857, 340,61719, 341,61719, 264,61718,61721,61725, 7,61719, 265,61728,61725,61731, 265,61729, 264,61719,61735,61737,56555,61719,57859,61741, 9,61743, 483,61718, 4579,61747,15899,61747, 3195,61747, 1965,61747, 265,61719, 7,61756, 61725,61759,56555,61718,57852,61763,57811,61763, 9,61766, 9,61763, 57811,61770, 265,61718,61723,61775,46863,61775, 9,60857, 8213,61780, 8052,61780, 7971,61780, 113,61786,36527,61780,58782,61780,58362,61780, 8241,61780, 113,61780, 7971,61798,35761,61780,50958,61780, 483,61780, 56555,61806, 1011,61780,49713,61810,38305,61780,38299,61815,37897,61815, 7961,61815, 7951,61815,35893,61815, 7953,61815, 1275,61815, 7947,61829, 49713,61780, 1011,61832,56555,61780,46863,61836, 483,61836,46863,61780, 56555,61842, 7563,60857, 1275,61847, 7565,61849, 7569,61849, 7573,61849, 7065,60857,35187,61857,10089,60857, 16,61861, 16,61860, 17,61861, 61865,61867, 17,61860,61863,61871,10257,60857, 903,61874, 8241,60857, 9,61878, 3255,60857, 9,61883,48789,60857, 16,61887, 16,61886, 17,61887,61891,61893, 17,61886,61889,61897,37357,60857, 903,61900, 3499,60857, 9,61905, 3445,60857, 9,61909,38184,60857, 375,61913, 16722,60857,16543,61917,16679,61917,16537,61917,35187,61916,13922,60857, 13753,61927, 4805,60857, 375,61930,16683,60857,16565,61934, 375,61934, 6515,60857, 9,61941,59824,60857,60369,61945, 9,61945, 9520,60857, 9,61951,16711,60857,16659,61954, 8,60856, 3,61959, 6,61960, 61601,61963,61815,61963, 6,61959, 3,61968,61601,61971,61815,61971, 61829,61959,61621,61959, 1274,61959,61815,61981,61601,61981, 16,60856, 10,60856, 5,61989, 0,61990,61585,61993,61747,61993, 0,61989, 5,61998,61585,62001,61747,62001,57811,61989,59933,61989,59743,61989, 8093,61989, 3837,61989,39619,61989,51421,61989,53703,61989,42435,61989, 4287,61989, 4303,61989,53487,61989,42113,61989, 9839,61989, 9579,61989, 9,61989, 113,62036, 128,61989, 101,61989, 113,61989, 9,62044, 57859,60857,57915,62048, 9,62051, 9,62049,57915,62055, 11,60856, 483,62059, 9,60856,57889,62063, 5185,62063,11243,62063,12557,62063, 11251,62063, 5177,62063, 16,60857,57293,62077,35603,62077,58669,62077, 59079,62077,55005,62077, 17,60856,61685,62089, 483,62089, 15,60856, 40829,62095, 10,60857,21183,62099, 759,62099, 47,62099, 959,62099, 203,62099, 107,62099, 85,62099, 67,62099, 9,62115, 113,60857, 8150,62118,17727,62118,13737,62118, 9,62118, 7971,62126,17025,62118, 7971,62118, 9,62132,10385,60857, 9,62137, 33,62139, 33,62136, 9,62143, 165,60857,17049,62146,17025,60857, 1275,62151, 7947,62153, 48739,62153,17637,62153,17029,62153,37241,62153, 113,62150,17049,60857, 165,62166,10247,60857,37347,60857,10249,60857,16659,60857,16711,62176, 37408,60857,56555,62180,16531,62180, 340,60857,51803,62187, 331,62187, 1325,62187, 59,62187,52439,60857,56555,62196,52563,60857, 265,62201, 1413,60857,56555,62204, 256,60857,56555,62208,38305,62208, 566,60857, 61987,62215, 9377,62215,37325,62215,10219,62215, 959,62215, 47,62215, 759,62215, 587,62215,20763,62215,42810,60857,43073,62235,42827,62235, 58703,62235,60849,62235,58027,62235,42821,62235, 1325,62235, 59,62235, 331,62235, 265,62235,42613,62235,56555,62257, 241,62234, 580,60857, 20033,62263,59143,62263,60601,62263,58029,62263,55210,60857,31103,62273, 37375,60857, 1347,60857,37409,60857, 375,62280, 375,60857,58905,62284, 16683,62284, 4805,62284,58126,62284, 6625,62284, 2079,62284,51937,62284, 305,62284,56555,62300,56555,62284, 305,62304,37409,62284, 803,60857, 37608,60857, 305,60857,60205,62314,57470,62314, 375,62314,56555,62320, 56555,62314, 375,62324,58116,60857,44243,62328,58126,60857, 375,62332, 42155,60857,58056,62336,44243,62336,56555,62340, 483,62336,48753,62345, 44451,62345,10081,62345,56555,62336,44243,62352,53517,60857, 483,62356, 48753,62359,10081,62359, 251,60857,38305,62364, 331,62367, 1325,62367, 59,62367, 555,60857,38305,62374, 331,62377, 1325,62377, 571,62377, 59,62377,60612,60857, 7,62387,36273,60857, 7,62391,59787,60857, 60619,62394, 9,62397, 5,62394,60369,62401, 9,62401, 5,62395, 60327,62407,60719,62407,57901,62407, 17,62407,59381,60857,60455,62416, 7,62419, 9513,60857, 5,62423, 17,62425, 5,62422, 9,62429, 58362,60857, 903,62432, 9,62432,58348,60857, 7,62438,58782,60857, 903,62442, 9,62442,58396,60857, 7,62448,58742,60857, 9,62453, 483,62452,46863,62452,60763,60857, 7,62461, 903,60857,58782,62464, 58362,62464,37357,62464,10257,62464, 483,62464,56555,62474,46863,62464, 56555,62478,56555,62464, 9,62483,46863,62482, 483,62482,38057,62464, 7,62491, 265,60857,46863,62495, 11,62497, 11,62494,46863,62501, 7,62494,51803,62505, 331,62505, 1325,62505, 59,62505, 7,62495, 375,62515,35187,60857,59960,62518,16722,62518, 7,62518,56555,62524, 16531,62524,56555,62518, 7,62530,16531,62518, 7,62534,46863,60857, 36527,62538,58742,62538,57522,62538,12377,62538, 6685,62538, 1011,62538, 903,62538,56555,62552, 9,62538,56555,62556,56555,62538, 903,62560, 9,62560,36527,60857, 7,62567, 331,62569, 9,62566,46863,62566, 483,62566, 7,62566, 375,62579,38305,60857,42109,62582,42103,62585, 1205,62583, 1203,62589, 1007,62583, 1009,62593, 1203,62582, 1205,62597, 1009,62582, 1007,62601, 177,62582, 59,62605, 1365,62582, 1325,62609, 571,62583, 555,62613, 97,62583, 21,62617, 5,62582, 6,62621, 5,62622,62583,62625, 2,62622,62627,62629, 2,62621, 6,62632, 482,62621, 3,62582, 6,62639, 3,62640,62583,62643, 4,62640, 62645,62647, 4,62639, 6,62650, 8,62639, 14,62582, 6,62657, 2,62658, 2,62657, 6,62662, 482,62657, 1274,62582, 6,62669, 4,62670, 4,62669, 6,62674, 8,62669, 256,62582, 629,62582, 555,62582, 59,62685, 331,62685, 1325,62685, 571,62685, 21,62582, 1325,62695, 331,62695, 59,62695, 97,62695, 1325,62583, 1365,62705, 251,62705, 21,62705, 555,62705, 59,62583, 177,62715, 251,62715, 555,62715, 21,62715, 251,62582, 331,62725, 59,62725, 1325,62725, 331,62583, 251,62733, 555,62733, 21,62733, 15,62583,10085,62741, 10093,62741,62661,62741,62665,62741,40909,62741,62629,62741,62635,62741, 3,62741,10087,62741,62637,62741,62667,62741, 483,62741,10081,62765, 62621,62765,62657,62765, 1275,62583,10005,62773,10041,62773,62673,62773, 62677,62773,62647,62773,62653,62773, 5,62773,10009,62773,23879,62773, 31937,62773,30399,62773,62655,62773,62679,62773, 9,62773,10001,62801, 62639,62801,62669,62801, 483,62582,39485,62809,39481,62809, 9525,62809, 9517,62809, 4,62809,62773,62819,62787,62809,42103,62809,41989,62809, 9519,62809,41995,62809,57855,62809,60853,62809,60609,62809,39487,62809, 15,62809, 9513,62841,41941,62841,39477,62841, 9,62582,61971,62849, 61963,62849, 7961,62849, 7951,62849, 2,62849,62741,62859,62757,62849, 7953,62849,35893,62849,38299,62849,37897,62849,61981,62849, 1275,62849, 7947,62875,61959,62875, 6,62582, 7,62582,58703,62883,58027,62883, 60849,62883, 59,62883, 1325,62883, 331,62883, 265,62883,42613,62883, 56555,62899, 241,62882, 7,62583,58715,62905,58056,62905,40799,62905, 375,62905,56555,62905,44243,62914,44243,62905,56555,62918, 265,62583, 375,62923,62881,62923, 241,62582, 6,62928, 7,62928, 6,62929, 62933,62935, 7,62929,62931,62939, 1011,60857,52756,62942,46863,62942, 483,62942, 9,62942,49713,62950,49713,62942, 9,62954, 7,62943, 10107,62959,53813,62959,49713,60857,22807,62965, 1108,62964, 295,62964, 9,62964, 1011,62972, 1011,62964, 9,62976, 4,62964,31103,62981, 241,60857,59960,62984,42810,62984, 7,62984,56555,62990,38305,62990, 56555,62984, 7,62996,38305,62984, 6,63000, 7,63000, 6,63001, 63005,63007, 7,63001,63003,63011, 483,60857, 9527,63014, 9525,63017, 17053,63014,10081,63021,11759,63015, 7971,63025,44451,63015,42155,63029, 0,63014, 5,63033, 0,63034,63015,63037, 7,63034,63039,63041, 7,63033, 5,63044, 10,63033, 6,63014, 5,63051, 6,63052, 63015,63055, 1,63052,63057,63059, 1,63051, 5,63062,38304,63051, 14,63014, 5,63069, 1,63070, 1,63069, 5,63074,38304,63069, 36527,63014,58742,63014,57522,63014,12377,63014, 6685,63014, 7971,63014, 48753,63091,10081,63091,11759,63091,42155,63014,10081,63099,48753,63099, 44451,63099,10081,63015,17053,63107,53517,63107,42155,63107, 7971,63107, 53517,63014,48753,63117,10081,63117,48753,63015,53517,63123, 7971,63123, 42155,63123,36293,63014, 17,63015, 11,63015, 9,63014,56555,63136, 15,63015, 1995,63141, 3755,63141,63073,63141,63077,63141, 5303,63141, 63059,63141,63065,63141, 0,63141,38403,63141,39943,63141, 4917,63141, 17013,63141,63067,63141,63079,63141,38305,63141, 59,63171,63051,63171, 63069,63171, 903,63014,56555,63178, 1011,63014, 11,63014,61993,63185, 62001,63185, 3195,63185, 1965,63185, 1,63185,63141,63195,63157,63185, 4579,63185,15899,63185,38305,63014,39481,63205,39485,63205,42103,63205, 41989,63205, 7,63205, 9525,63205, 9517,63205,41995,63205, 9519,63205, 57855,63205,60609,63205,60853,63205,39487,63205, 15,63205,41941,63233, 9513,63233,39477,63233, 4,63014,20033,63241,59143,63241,60601,63241, 58029,63241,63133,63241, 5,63014,61987,63253, 9377,63253,37325,63253, 10219,63253, 959,63253, 47,63253, 759,63253, 587,63253,20763,63253, 4,63015, 7,63272,63253,63275,20029,63273,59147,63273,21103,63273, 19781,63273,19301,63273,62773,63273, 5,63015, 803,63291,56555,63014, 903,63294, 9,63294,40674,60857, 6,63300, 7,63300, 6,63301, 63305,63307, 7,63301,63303,63311,38266,60857, 7,63315,36752,60857, 7,63318,16937,60857, 580,63322, 483,63322, 4,63327, 4,63326, 49631,63322,49630,63322, 581,63322, 4,63322, 483,63338,46863,63338, 5,63322,63329,63345, 4,63323,63333,63349,63337,63349, 5,63323, 63335,63355,63325,63355,63331,63355,63341,63355,63343,63355,46863,63322, 4,63366,63355,63369, 4,63367,63345,63373,38057,60857, 5,63376, 6,63379, 6,63378, 14,63376, 15,63376, 1505,63376, 6,63376, 5,63390, 7,63376,63381,63395, 375,63395, 6,63377,63387,63401, 7,63377,63393,63405,63383,63405,38161,63405, 59,63405,63385,63405, 331,63405, 1325,63405, 265,63405, 903,63376, 7,63423,16531,60857, 1275,63427,16711,63429,37408,63426, 7,63426,16543,63435,16679,63435, 16537,63435,35187,63434, 7,63427,16565,63445,35187,63426, 7,63448, 12377,60857, 9,63453,46863,63452, 483,63452,17635,63452,13737,60857, 113,63462,11731,63462, 5,63462,13753,63469, 5,63463,13751,63473, 13917,63473,13743,63473,60619,60857,59787,63480, 9,63483,60455,60857, 59381,63486, 7,63489, 5,60856,45491,63493,42800,63493,59694,63493, 10374,63493,60563,63493, 9606,63493,42134,63493, 629,63493, 705,63493, 101,63493, 299,63493, 828,63493, 128,63493, 394,63493,48122,63493, 803,63493, 483,63524,42613,63493, 17,63528,51992,63493, 375,63493, 241,63534,49713,63534,10291,63493, 17,63540, 256,63493, 113,63493, 9,63546, 17,63493,42613,63550,10291,63550,59619,63550, 9565,63550, 41941,63550, 9,63493, 113,63562, 7,63493,21605,63567, 241,63566, 7,63492,59933,63573,59743,63573,57811,63573, 8093,63573, 3837,63573, 53703,63573, 4287,63573,42435,63573, 4303,63573,53487,63573, 9839,63573, 42113,63573, 9579,63573,39619,63573,51421,63573,31103,63493,46863,63493, 12377,63606, 483,63493, 803,63610,49713,63493, 375,63614,56555,63493, 5,63619, 6,63621, 6,63620, 14,63619, 15,63619, 6,63618, 63629,63631, 7,63618,63625,63635,63627,63635, 7,63619,63623,63641, 6,63619, 5,63644,63635,63647, 241,63493, 375,63650, 7,63650, 59619,63493, 7,63657, 17,63656,12377,63493,46863,63662, 9565,63493, 7,63667, 17,63666,41941,63493, 7,63673, 17,63672, 4,60856, 20305,63679, 9641,63679, 9645,63679,20309,63679,21081,63679,20323,63679, 20387,63679, 3,63679, 6,63694,61601,63697,61815,63697,62849,63697, 6,63695, 9701,63679, 1274,63679,61815,63709,61601,63709,62849,63709, 61829,63679,61621,63679,62875,63679, 9719,63679,43005,63679,58056,63679, 386,63679, 347,63679, 767,63679,31103,63733, 524,63679, 9617,63737, 20273,63737, 1291,63679, 9617,63743,20273,63743, 305,63679, 375,63748, 375,63679, 305,63752,44243,63679,56555,63756, 11,63679, 483,63760, 9617,63763,20273,63763, 7,63679,38305,63769,56555,63771, 6,63679, 4,63775, 3,63774,61601,63779,61815,63779,62849,63779, 4,63774, 62582,63787,63779,63789,38305,63787,60857,63792,63779,63795,60857,63787, 38305,63798,63779,63801, 7,63678,63253,63805,62215,63805, 483,63679, 11,63810, 9617,63813,20273,63813,56555,63679,44243,63818, 7,60856, 40787,63823,40793,63823, 0,63823, 5,63828,61475,63831,61585,63831, 61747,63831,63185,63831,36001,63823,26106,63823,32103,63823,41746,63823, 43005,63823, 8800,63823,59910,63823,36539,63823,37595,63823,36049,63823, 63253,63823,62215,63823,61305,63823,48975,63823,48245,63823,48451,63823, 60707,63823, 386,63823, 347,63823, 510,63823,60755,63823, 9852,63823, 53500,63823,36041,63823,37573,63823,36275,63823, 375,63823, 305,63892, 273,63823, 281,63823, 1477,63823, 1516,63823, 948,63823,40704,63823, 10001,63907,27533,63907, 8495,63823, 11,63912,48885,63823, 483,63917, 41019,63823, 11,63920, 567,63823,63493,63925, 165,63823, 903,63928, 11,63823,25793,63932,41019,63932, 8495,63932,59875,63932, 9805,63932, 53391,63932,60618,63823, 483,63947, 9,63823, 483,63950,38305,63950, 27533,63955,10001,63955, 1505,63823, 1011,63960, 305,63823, 375,63964, 4,63823,63610,63969,63291,63969,63493,63969, 483,63974, 483,63969, 63493,63978,56555,63968, 483,63983, 5,63823, 7,63987, 1275,63989, 60857,63991, 0,63986,61475,63995,61585,63995,61747,63995,63185,63995, 63993,63995, 7,63986,63014,64007,63995,64009, 483,64007,60857,64012, 63995,64015,60857,64007, 483,64018,63995,64021, 4,63822,63253,64025, 62215,64025, 5,63822,59743,64031,59933,64031,57811,64031, 8093,64031, 3837,64031,42435,64031, 4303,64031,53703,64031, 4287,64031,42113,64031, 9579,64031,53487,64031, 9839,64031,51421,64031,39619,64031,25793,63823, 11,64062, 903,63823, 165,64066,38305,63823, 9,64070,27533,64073, 10001,64073, 1011,63823, 1505,64078,56555,63823, 4,64082, 483,64085, 483,63823, 9,64088,59875,63823, 11,64092, 5,64093, 9805,63823, 11,64098, 5,64099,53391,63823, 11,64104, 5,64105, 6,60856, 60454,64111,60369,64113, 5,64111,56555,64116,60369,64119,56555,64111, 17,64122, 4,64122, 7,64126, 5,64122,60369,64131, 5,64123, 60327,64135,60719,64135,64129,64135,57901,64135, 4,64123,64125,64145, 7,60857,16539,64149,16683,64151, 264,64149, 264,64148, 3,64149, 16530,64158,16530,64159, 1,64158,58396,64148,58348,64148,36527,64148, 375,64171,40674,64148,36752,64148, 331,64149, 1325,64149, 59,64149, 38057,64148, 375,64185,16531,64148,64161,64189,16543,64189,16679,64189, 16537,64189,35187,64188, 17,64149, 241,64201,38305,64149,42383,64205, 6625,64205,58116,64205,42155,64205,56555,64212,56555,64205,42155,64216, 16531,64149,64163,64221,16659,64221,48885,64149,56555,64227, 15,64149, 483,64231,38305,64231,27533,64235,64165,64235,10001,64235,35187,64148, 56555,64242,16531,64242, 265,64148,64155,64249,51803,64249, 331,64249, 1325,64249, 59,64249, 241,64148,56555,64260,38305,64260,38305,64148, 58703,64267,58027,64267,60849,64267, 59,64267, 1325,64267, 331,64267, 265,64267,42613,64267,56555,64283, 241,64266, 265,64149,64157,64289, 41941,64289,51229,64289, 4213,64289, 8757,64289, 9565,64289,59619,64289, 305,64289, 713,64289, 25,64289, 8165,64289, 9617,64289,20273,64289, 4,64148,57293,64317,35603,64317,58669,64317,59079,64317,55005,64317, 5,64148, 3,64329, 1,64331,64205,64333,21183,64329, 759,64329, 47,64329, 959,64329, 4,64149,43053,64345,54985,64345,54129,64345, 51601,64345,58782,64345,46863,64345,56555,64356,56555,64345,46863,64360, 5,64149, 803,64365, 1275,64149, 9,64369,56555,64148,25793,64373, 8495,64373,41019,64373,35187,64372, 241,64372,59960,60857,25793,64385, 41019,64385, 8495,64385, 241,64384,35187,64384, 5,60857,60079,64396, 60369,64399, 0,64396,63743,64403, 1290,64403,63679,64407,63737,64403, 525,64403,63679,64413,63763,64403,63813,64403, 17,64403, 1275,64420, 63679,64423, 1275,64403, 17,64426,63679,64429, 3,64396, 6,64433, 759,64397, 483,64437,64025,64397, 483,64441,63823,64397, 483,64445, 9377,64397, 483,64449, 9513,64396, 9,64453, 959,64397, 483,64457, 37325,64397, 483,64461, 47,64397, 483,64465,10219,64397, 483,64469, 59787,64396,60369,64473, 9,64473,13737,64396,13753,64479,49713,64397, 61987,64397, 483,64485, 9,64397,42613,64489,59619,64489,10291,64489, 9565,64489,41941,64489, 17,64397, 113,64501,63805,64397, 483,64505, 20763,64397, 483,64509, 483,64396,64025,64513,63823,64513,61987,64513, 63805,64513, 9377,64513,37325,64513,10219,64513, 959,64513, 47,64513, 759,64513, 587,64513,20763,64513, 587,64397, 483,64539, 7,64396, 21183,64543, 759,64543, 47,64543, 959,64543, 6,64397,56555,64553, 4,64554, 5,64554, 5,64555,64557,64561, 4,64555,64559,64565, 7,64397, 0,64569, 5,64570, 5,64569, 0,64574,21105,64569, 21549,64569,19625,64569, 1275,64569,60857,64585,64573,64587,64577,64587, 63679,64397,63705,64593,64435,64593,31103,64593, 375,64593, 7,64593, 64433,64603, 903,64397, 375,64607, 7,64607,35187,64397,60796,64612, 60797,64612,31103,64613,60797,64613,64615,64621, 375,64613,60796,64613, 64617,64627,56555,64397,59787,64631, 9,64633,56555,64396,59914,64637, 60221,64637,59875,64637, 9,64642,60369,64637, 9,64637,59875,64648, 60454,60857,59914,64653,60221,64653,59875,64653, 9,64658,60369,64653, 9,64653,59875,64664, 4,60857, 8743,64669, 8605,64669, 8672,64669, 8647,64669, 305,64676, 3795,64669,10025,64669,27603,64669,31524,64669, 31690,64669,31700,64669,63569,64669,46862,64669, 0,64669, 2,64696, 6,64696, 6,64697,63604,64669,24655,64669,63534,64669, 8916,64669, 62092,64669,63133,64669,48408,64669, 713,64669,31103,64718, 305,64669, 8647,64722,31103,64722, 25,64669,31103,64728, 340,64669, 8717,64733, 3785,64733, 8495,64733, 483,64669,62089,64740,46863,64740, 375,64669, 63493,64746, 8861,64746,62089,64669, 483,64752, 15,64669, 483,64757, 20273,64759, 9617,64759,64403,64759,64699,64759,31103,64669, 305,64768, 713,64768, 25,64768,63493,64768,49713,64769, 483,64668,20033,64781, 59143,64781,58029,64781,60601,64781,49713,64668,31103,64791,46863,64669, 483,64794, 6,64668,64795,64799, 2,64801, 3,64800,64803,64805, 3,64801, 2,64800,64809,64811, 7,64668,57293,64815,64695,64815, 2,64819, 3,64818,64821,64823, 3,64819, 2,64818,64827,64829, 64701,64815, 2,64833, 3,64832,64835,64837, 3,64833, 2,64832, 64841,64843,35603,64815,59079,64815,58669,64815,55005,64815, 6,64669, 0,64854,64815,64857, 2,64859, 3,64858,64861,64863, 3,64859, 2,64858,64867,64869, 7,64669,60857,64873, 264,64874, 264,64875, 1,64873, 264,64880, 264,64881,64703,64873, 2,64887, 3,64886, 64889,64891, 3,64887, 2,64886,64895,64897,25793,64873,41019,64873, 8495,64873, 305,64905,59875,64873,53391,64873, 9805,64873,38305,64873, 483,64915, 265,64872, 8717,64919,64883,64919,64877,64919, 3785,64919, 8495,64919, 265,64873,64885,64931,64879,64931,63493,64931, 8861,64931, 46863,64931, 8861,64669, 375,64942,63493,64669,31103,64946, 375,64946, 265,64669, 7,64952, 8717,64955, 3785,64955, 8495,64955, 7,64953, 8647,64963,56555,64669,59381,64967, 7,64969,56555,64668,31103,64973, 375,64973,59712,64973, 7,64973, 265,64981,59619,64980,59619,64973, 7,64986,60618,60857,31103,64991, 375,64991,59712,64991, 7,64991, 265,64999,59619,64998,59619,64991, 7,65004, 6,60857, 264,65009, 64746,65011, 375,65011,64669,65014,64931,65011,64669,65011, 375,65020, 264,65008,64733,65025, 341,65025,64669,65029,64955,65025,64919,65025, 3,65008, 341,65037,64669,65039,63907,65037,40705,65037,63823,65045, 64235,65037,63955,65037,64073,65037, 17,65037,64953,65009, 375,65057, 4,65009, 1274,65061, 3,65061, 6,65064, 6,65061, 3,65068, 56555,65008,60796,60857,56555,60857, 386,65076,45432,65076, 347,65076, 43099,65076,60418,65077,60327,65087,59961,65077, 5,65091,60369,65093, 5,65090,60327,65097, 18,65076, 12,65076, 1291,65076,48561,65076, 525,65076,49630,65076, 580,65076, 1170,65076,37408,65076, 256,65076, 52439,65076, 629,65076, 1413,65076,47640,65076, 922,65076,49631,65076, 581,65076, 1171,65076,44243,65076,42155,65136, 375,65076, 305,65140, 48466,65076, 510,65076, 13,65077,65103,65149, 19,65077,65101,65153, 13,65076, 18,65077, 19,65076,65159,65161, 12,65077,65157,65165, 57915,65165, 14,65077,57901,65171,60719,65171,60327,65171,65115,65171, 17,65171, 10,65077, 9,65183, 16,65076,65171,65187, 10,65076, 65165,65191,48560,65076, 524,65076, 1290,65076, 11,65076,65149,65201, 57852,65201,65184,65201,65183,65201, 9,65208,57811,65201, 9,65212, 9,65201,65183,65216,57811,65216,46863,65200, 483,65200, 9,65076, 483,65226,46863,65226, 17,65076, 1275,65232, 11,65077,65191,65237, 9,65239,57915,65237, 9,65243, 9,65236,65191,65247,57915,65247, 9,65077, 11,65253,65183,65255,57811,65255, 11,65252,65191,65261, 57915,65261, 15,65077,65233,65267,65135,65267, 305,65076, 375,65272, 42155,65076,44243,65276, 1011,65076, 7,65281, 7,65280,65171,65285, 15,65281, 241,65076, 7,65290, 483,65076, 4,65295, 4,65294, 903,65294, 9,65294, 11,65294, 903,65076, 9,65307,46863,65306, 483,65306,35187,65076, 7,65314, 1275,65076, 17,65318,46863,65076, 4,65323, 4,65322, 903,65322, 9,65322, 11,65322, 7,65077, 9,65335, 11,65335, 567,65335, 4,65335, 483,65343, 5,65335, 5,65334,65343,65349, 4,65334,65347,65353, 6,65076,65350,65357, 65355,65357,65289,65357,65349,65357,65343,65364,65343,65357,65349,65368, 11,65357,65346,65357,65353,65375, 5,65357,65335,65379,65349,65381, 65335,65378,65353,65385,65335,65357, 4,65389, 5,65389,65343,65393, 4,65388,65393,65397, 5,65388,65391,65401,65353,65401, 5,65077, 60629,65407,59960,65406,59960,65407,38185,65407,57993,65407,65115,65407, 65113,65407,65111,65407,59961,65406,65413,65425,60327,65425,65197,65407, 65195,65407,65105,65407,60251,65407,58313,65407,65299,65407,65327,65407, 65285,65407,65225,65407,65223,65407,65305,65407,65333,65407,56555,65407, 7,65454, 7,65455,59961,65407,60359,65461,65411,65461, 11,65461, 1171,65407,65335,65469,65335,65407,65187,65407,57901,65407,60327,65407, 60719,65407, 17,65407,65335,65483,59875,65483,64385,65407,64373,65407, 6,65407,65459,65493,60755,65493,65283,65493, 11,65493, 7,65407, 56555,65502, 7,65406,65461,65507,65493,65507, 6,65406,65505,65513, 65457,65513,60719,65513,65413,65513,60327,65513,57901,65513,65187,65513, 65115,65513,65285,65513,65503,65513, 17,65513, 4,65076, 2,65537, 7,65539,65407,65541,65510,65537,65533,65537,65507,65537,65493,65548, 31103,65537,65493,65537,65507,65554, 483,65536,65407,65559,46863,65536, 65407,65563, 375,65537, 15,65537,65357,65569, 7,65536,65513,65573, 65171,65573,65407,65573,59712,65537,65502,65537,65513,65583, 7,65537, 65493,65587,65407,65587,65507,65591, 265,65587,59619,65586,65407,65586, 65513,65599,59619,65537, 7,65602,65407,65537, 6,65607, 7,65607, 65493,65611, 6,65606,65611,65615, 7,65606,65609,65619,65513,65619, 4,65077,65135,65625,65133,65625,65131,65625,65372,65625,65199,65625, 65109,65625,65107,65625,65235,65625,65321,65625, 11,65625,65357,65644, 65233,65625,65357,65625, 11,65650,65075,65625,65073,65625, 7,65625, 60455,65625, 7,65661, 5,65076, 2,65664,65625,65667, 1,65664, 3,65664, 0,65664,65625,65675,59914,65665,60221,65665,65336,65665, 65297,65665,65325,65665,59875,65665, 9,65688,65659,65665,65667,65693, 65675,65693,60369,65665, 9,65665,65335,65700,59875,65700,65335,65665, 9,65706,65658,65665,65671,65711,65673,65711, 6,65665,65668,65717, 65676,65717,65667,65717,65625,65722,65675,65717,65625,65726,65625,65717, 65667,65730,65675,65730, 7,65665,65671,65737,65625,65739,65673,65737, 65625,65743,65625,65736,65671,65747,65673,65747,65625,65665, 6,65753, 7,65753, 6,65752,65757,65759, 7,65752,65671,65763,65673,65763, 65755,65763, 6,65077,60619,65771, 9,65773, 17,65771,65625,65777, 65537,65771, 9,65781, 5,65771,60369,65785, 9,65785, 5,65770, 65573,65791,60327,65791,60719,65791,57901,65791,65187,65791,65115,65791, 65285,65791, 17,65791, 7,65076,25793,65809,41019,65809, 8495,65809, 1011,65808,65513,65817,65791,65817,65407,65817,65171,65817, 241,65808, 35187,65808, 15,65809,65665,65831,65407,65809, 11,65835, 4,65808, 65791,65839,65513,65839,65171,65839,65407,65839, 4,65809,65785,65849, 65665,65849,65771,65809, 4,65855, 5,65855, 4,65854,65859,65861, 5,65854,65857,65865, 1, 4,49284,65869,49311,65869,48330,65869, 48279,65869,47548,65869,47076,65869,47078,65869,48581,65869,48584,65869, 54254,65869,54260,65869,54266,65869,54222,65869, 8672,65869, 8743,65869, 3795,65869, 8605,65869, 8647,65869, 305,65904,27021,65868,31103,65909, 27377,65910,31894,65909,27377,65909,31103,65916, 21,65868,57577,65921, 59109,65921,19987,65921,57381,65921,59787,65868,57577,65931,57381,65931, 57253,65931,59109,65931,15390,65869,15383,65941,44768,65869,44663,65945, 48284,65869,37897,65949,44243,65869,37845,65953,45411,65955,37845,65952, 44663,65959,37845,65869,44243,65963,45381,65965,44243,65962,44663,65969, 46863,65962,37897,65973, 1175,65869,56555,65977, 1177,65979,49215,65869, 9,65983,49229,65985,56709,65869, 1009,65989,54641,65869,54643,65993, 60737,65868,60749,65997,11355,65868,11495,66001,57793,65868,57577,66005, 57381,66005,59109,66005,59715,65869,56555,66013,59717,66015, 7959,65869, 9,66019, 7961,66021,49534,65869,49537,66025,19086,65869, 1203,66029, 49529,65869, 15,66032,49537,66035,19064,65869, 1009,66039,54668,65869, 54643,66043, 1205,65869,18967,66046, 1203,66049,19949,65868,19987,66053, 1425,65868,57253,66057, 668,65868, 1,66061, 2,66062, 2,66061, 1,66066,56554,66061,58930,65868, 4,66073, 6,66074, 6,66073, 4,66078, 8,66073,19965,65868,19987,66085,56745,65868,57253,66089, 60136,65869,59787,66093, 571,65869,18967,66096, 555,66099,16091,65869, 15,66102, 9513,66105,19078,65869, 21,66109,54655,65869, 15,66112, 54643,66115, 1007,65869,18967,66118, 1009,66121,60125,65869, 15,66124, 59787,66127,19088,65869, 555,66131,16092,65869, 9513,66135, 97,65869, 18967,66138, 21,66141,20347,65869,18967,66144,20345,66147,10095,65869, 15,66150,10093,66153,20348,65869,20345,66157,10096,65869,10093,66161, 32468,65869,27323,66165,33442,65869,48368,65869,32469,65869,65909,66173, 28483,65869,28479,65869,63604,65869,31690,65869,31700,65869,31524,65869, 31596,65869,32464,65869,53380,65869,25037,65869,24655,65869,25457,65869, 23005,65869,27603,65869,22591,65869,23105,65869,23357,65869,23113,65869, 120,65869,46863,66212, 77,65869,46863,66216,54154,65869,54225,66220, 56328,65869,58298,65869,58868,65869,52752,65869,52370,65869,58344,65869, 57253,65869,59787,66237, 1425,66237,56745,66237,19987,65869, 21,66245, 19949,66245,19965,66245,25215,65869,48583,65869, 113,66254,25459,65869, 31920,65869,32263,65869,23099,65869,23107,65869,24631,65869,22915,65869, 22589,65869,65294,65869,65322,65869,63534,65869,54256,65869,54129,66280, 25305,65869,32295,65869,31796,65869,62092,65869,63133,65869,22785,65869, 22803,65869,22951,65869,24735,65869,23012,65869,25546,65869,47364,65869, 25548,65869,62442,65869,63294,65869,62432,65869,62560,65869,57577,65869, 21,66319,59787,66319,57793,66319,57381,65869,59787,66327, 21,66327, 57793,66327,59109,65869, 21,66335,59787,66335,57793,66335,48578,65869, 33,66343,48276,65869, 33,66347,49308,65869, 33,66351,59340,65869, 63135,65869,61464,65869,61580,65869,61578,65869,62946,65869,62950,65869, 62550,65869,61810,65869,63182,65869,62948,65869,57660,65869,57766,65869, 62060,65869,57772,65869,22767,65869,19810,65869, 251,66387, 555,66387, 1365,66387, 21,66387, 9994,65869, 9513,66397,16859,66397,59787,66397, 20620,65869,59787,66405,21529,66405, 9513,66405,19372,65869, 251,66413, 21,66413, 177,66413, 555,66413,20823,65869,59787,66423,21529,66423, 20771,66423, 9513,66423,57971,65869, 21,66433, 251,66433, 177,66433, 159,66433, 555,66433,25303,65869, 11,66445,24739,65869,29028,65869, 57658,65869,57620,65869,48328,65869, 113,66456,19806,65869, 251,66461, 555,66461, 21,66461, 8916,65869,54262,65869,46863,66470,54219,65869, 46863,66474,32556,65869, 759,66479, 7061,65869, 3,66483, 2,66483, 842,66483, 843,66482,66489,66491, 843,66483, 842,66482,66495,66497, 3,66482,66487,66501, 2,66482,66485,66505,47546,65869, 25,66508, 49283,65869, 25,66512,47600,65869,48444,65869,47572,65869,62146,65869, 17476,65869,23010,65869,63184,65869,61584,65869,48558,65869,47408,65869, 25460,65869,61474,65869,47372,65869,61746,65869,47632,65869,17538,65869, 47634,65869,47676,65869,48112,65869,47412,65869, 5886,65869,48095,65869, 1072,65869,60857,66560,48408,65869,49713,66564, 241,66564, 587,66565, 903,66564,48420,65869,61780,65869, 1011,66576,47640,65869, 1011,66580, 483,66580,47590,65869, 483,66586,47672,65869,47368,65869, 1413,65869, 46863,66594,52692,65869,46863,66598,47370,65869, 922,65869,46863,66604, 49075,65869,49395,65869,48586,65869,10025,65869, 1281,65869,46863,66616, 1291,65869,60857,66620, 669,65869,66065,66625,66069,66625,40909,66625, 1821,66625, 1879,66625,38973,66625, 3,66625,38971,66639,57911,66625, 17041,66625, 4897,66625,56739,66625,66071,66625,56555,66625, 671,66653, 66061,66653,25381,65869, 11,66659, 11,66658,58931,65869,66077,66665, 66081,66665,58715,66665,58975,66665,58981,66665,59089,66665, 7,66665, 59079,66679,23879,66665,30399,66665,31937,66665,58983,66665,66083,66665, 9,66665,58967,66693,66073,66693,58782,65869,49713,66698,60857,66698, 11,66699, 1108,65869,60857,66706,62089,65869, 483,66710, 4802,65869, 5314,65869,17670,65869,17693,65869,62059,65869, 483,66722,47608,65869, 60857,66726, 903,66726, 11,66727, 587,66726,19474,65869,10093,66737, 20345,66737,10085,66737,20281,66737,19549,66737,19553,66737,10087,66737, 20285,66737,19555,66737, 483,66737,20273,66757,10081,66757,19545,66757, 61718,65869, 483,66764,22957,65869, 903,66768, 587,66768,62538,65869, 56555,66774, 1011,66774, 288,65869, 9,66781,19916,65869, 7,66785, 35603,66787,35613,66785,10041,66785,10005,66785,10009,66785,23879,66785, 30399,66785,31937,66785, 9,66785,10001,66805,63014,65869,56555,66808, 11,66809, 587,66809, 1011,66808, 11,66808,48534,65869, 1011,66820, 1418,65869, 3,66825,38903,66827,38913,66825, 3587,66825, 1989,66825, 56681,66825,57911,66825,17041,66825, 4897,66825,56555,66825, 1471,66845, 1086,65869,46863,66848, 524,65869,60857,66852, 1304,65869, 9,66857, 1530,65869, 9,66861, 9195,65869,31103,66864,10031,65869,27641,65869, 713,65869,31103,66872, 1447,65869,13737,66877, 9875,65869, 15,66880, 9513,66883,16859,66883,59787,66883, 803,66881, 1325,65869,18967,66892, 251,66895, 555,66895, 1365,66895, 21,66895,16937,65869,46863,66904, 1505,65869,28715,66908, 5438,65869,49162,65869, 113,65869,48583,66916, 48328,66916, 25,66916,46863,66922,46863,66916, 25,66926, 375,65869, 63493,66930, 8861,66930,58334,65869,46863,66936,58362,65869,60857,66940, 506,65869,46863,66944, 587,65869, 759,66949,31103,66951,31103,66948, 759,66955,22957,66948,47608,66948,46863,66948, 1011,66962, 1011,66948, 46863,66966, 1369,65869, 15,66970, 4897,66973,17041,66973, 3587,66973, 1989,66973,57911,66973,56681,66973,56555,66973, 1471,66987, 1275,66970, 9,66991, 1275,65869,18967,66994,31937,66997,30399,66997,10041,66997, 10005,66997,23879,66997,10009,66997, 9,66997,10001,67011, 11,66994, 9,67015, 9,66995, 11,67019, 1369,67019, 1369,66994, 9,67025, 483,65869,32805,67028,56156,67028,65076,67028,25545,67028,62089,67028, 62942,67028,62059,67028,47590,67028,47640,67028,17669,67028, 5313,67028, 4801,67028, 587,67029,46863,67055,61718,67028,49713,67028,46863,67060, 1011,67028,60857,67064, 903,67028,46863,67068,46863,67028,49713,67072, 587,67073, 241,67072, 903,67072,60857,67028,56555,67082, 587,67083, 11,67083, 1011,67082, 11,67082, 11,67028,60857,67094, 5325,67028, 56555,67028,60857,67100, 241,67028,46863,67104, 4593,67028,11985,67028, 5843,67028,49155,67028, 5876,65869,49155,65869, 483,67118, 6267,65869, 9,67123, 6367,67125, 6403,67125, 6407,67125,60419,65869,56555,67133, 60425,67135,60429,67135,60433,67135, 5325,65869, 483,67142,55005,65869, 9,67147, 5843,65869,56555,67150, 1011,67150, 483,67150,12023,65869, 11986,65869, 4608,65869,11985,65869, 483,67164, 3681,65869,56555,67168, 3709,65869,56555,67172, 3357,65869,56555,67176,52840,65869, 4593,65869, 483,67182,54202,65869,54159,67187,46863,67189, 4801,65869, 483,67192, 54129,65869,54256,67196,46863,67196,54225,67200,54225,67196,46863,67204, 17669,65869, 483,67208, 5313,65869,56555,67212, 483,67212,15309,65869, 413,67218,15383,67221, 413,67219,15335,67225,54225,65869,54154,67228, 46863,67228,54129,67232,54129,67228,46863,67236, 1274,65868, 6,67241, 4,67242,66785,67245,66997,67245, 4,67241, 6,67250,66785,67253, 66997,67253,67011,67241,66805,67241, 8,67241,66997,67263,66785,67263, 1368,65868, 1,67269, 2,67270,66825,67273,66973,67273, 2,67269, 1,67278,66825,67281,66973,67281,66987,67269,66845,67269,56554,67269, 66973,67291,66825,67291, 586,65868,24265,67297,28233,67297,29077,67297, 19559,67297, 8251,67297,20361,67297, 9673,67297,20713,67297, 4283,67297, 9967,67297, 4279,67297, 3807,67297, 482,65869, 903,67323, 1,67325, 0,67325, 1,67324,67329,67331, 0,67324,67327,67335, 587,65868, 31690,67339,31103,67339, 713,67342, 713,67339,31103,67346,48408,67339, 46863,67339, 483,67352, 483,67339,46863,67356, 483,65868,57577,67361, 57253,67361,19987,67361,59109,67361,57381,67361, 1369,65868, 1275,65868, 47953,67375,48062,67375,47961,67375,48009,67380,48009,67375,47961,67384, 47580,67375,47933,67389,46863,67375, 265,67393,48009,67395, 265,67392, 47933,67399, 265,67375,46863,67403,47961,67405,46863,67402,47933,67409, 1368,65869,48009,67413,49321,67413,49001,67413, 265,67413,46863,67421, 586,65869,58056,67425,58601,67425,40799,67425,44243,67425,56555,67432, 35927,67425,38155,67425,37611,67425, 375,67425, 510,67425, 9,67425, 483,67446,56555,67425,44243,67450, 483,67425, 9,67454, 843,65869, 9,67459,15705,65869, 9,67463,10001,67465,13755,67465,15733,67465, 27533,67465,17455,65869,56555,67474, 1347,67474, 1011,67474, 767,65869, 56555,67483, 1471,67485, 253,67485, 809,67485, 771,67485, 53,67485, 1347,65869,17455,67496, 567,65869, 9,67501,10033,65869,27691,65869, 10035,65869,27978,65869,26331,67511,23755,67511,27805,67511, 256,65869, 25793,67519,59875,67519,41019,67519, 8495,67519,53391,67519, 9805,67519, 972,65869,25793,67533,41019,67533, 8495,67533,20762,65869,58715,67541, 375,67541, 154,65869,40909,67547,49204,65869, 11,67550, 33,67553, 11,67551, 25,67557, 1369,67551,37409,67551, 340,65869,25793,67565, 41019,67565, 8717,67565, 8495,67565, 3785,67565,49514,65869, 66,65869, 33,67579,46863,67581,46863,67578, 33,67585, 112,65869,44243,67589, 27785,65869, 257,65869,67373,67595,31103,67594,31103,65869,27021,67601, 27377,67603,27021,67600,27323,67607, 25,67600, 713,67600, 305,67600, 63493,67600, 8861,67600, 9195,67600,52915,67600, 1369,67601, 587,67601, 713,67627, 903,67600, 241,67600, 587,67600, 759,67635,49713,67600, 257,67600, 165,65869,60857,67642,31926,65869,27021,65869,27323,67649, 31103,67651,31103,67648,27323,67655,52915,65869,31103,67658, 305,65869, 8647,67662,31103,67662, 25,65869,49283,67668,47546,67668,31103,67668, 113,67668,46863,67676,46863,67668, 113,67680,20501,65869, 15,67684, 59787,67687,21529,67687, 9513,67687, 803,67685, 1141,65869,13737,67697, 33,65869,13737,67701, 331,65869,18967,67704, 251,67707, 21,67707, 555,67707, 59,65869,18967,67714, 251,67717, 21,67717, 177,67717, 555,67717, 8861,65869,60796,67727,60797,67727,60796,67726,67731,67733, 31103,67726,60797,67726,67729,67739, 375,67726,63493,65869,60796,67745, 60797,67745,31103,67744,60797,67744,67747,67753,60796,67744,67749,67757, 375,67744, 413,65869,15309,67762,15383,67765,15309,67763,15363,67769, 46863,67762,32805,65869, 9,67775, 483,67774,46863,67774, 1216,65869, 46863,67782,65076,65869, 9,67787, 483,67786,46863,67786,56156,65869, 483,67794,56555,67794,56555,65869,56156,67800,63014,67800,62538,67800, 3357,67800,17455,67800, 5313,67800, 5843,67800, 3681,67800, 3709,67800, 46863,67800,49713,67820,60857,67820, 11,67821,49713,67800,46863,67828, 483,67800,60857,67832, 11,67801,46863,67837,60857,67800, 9,67841, 483,67840,46863,67840,15029,67800, 7,67849, 903,65869,31103,67852, 22957,67852,47608,67852,48408,67852,46863,67852, 1011,67862, 483,67862, 483,67852,46863,67868, 7,67852,25793,67873,41019,67873, 8495,67873, 1011,67852,46863,67880,28715,67852, 7,67885,21605,65869, 15,67889, 31103,67891, 7,67888,26331,67895,23755,67895,27805,67895, 7,67889, 26219,67903,49713,65869,58782,67906,48408,67906, 483,67906,46863,67912, 31103,67906,56555,67906,46863,67918, 3,67907,31103,67923,46863,67906, 483,67926,56555,67926, 241,65869,31103,67932,48408,67932,46863,67932, 483,67938, 483,67932,46863,67942, 7,67932,25793,67947,59875,67947, 41019,67947, 8495,67947,53391,67947, 9805,67947,56555,67933, 7,67961, 9,65869,25545,67964,62942,67964,60857,67964, 1011,67970, 1011,67964, 60857,67974,25545,65869, 7,67979, 483,67978, 9,67978,46863,67978, 46863,65869,37844,67988,37896,67989,37844,67989, 6,67994,37845,67988, 67993,67999,67997,67999,67995,67999,37897,67999,54262,67988,54219,67988, 120,67988, 77,67988, 6,67989,37844,68017,37844,68016,67999,68021, 32805,67988,37845,67989,68019,68027,67991,68027,37899,68027,37897,67989, 67991,68035,54129,67988,54225,68038,52692,67988,58334,67988,65076,67988, 54225,67988,54129,68048,25545,67988, 66,67988, 33,68055,62942,67988, 25,67988, 113,68060, 113,67988, 25,68064, 506,67988, 1086,67988, 1281,67988, 1216,67988, 413,67988, 922,67988, 1413,67988,16937,67988, 587,67989, 483,68085, 483,67988,49713,68088, 241,68088, 587,68089, 903,68088, 241,67988, 483,68098, 903,67988, 1011,68102, 483,68102, 1275,67989,56555,67988,49713,68110,60857,68110, 11,68111,60857,67988, 56555,68118, 1011,68118, 1011,67988,60857,68124, 903,68124, 11,68125, 587,68124, 587,67988, 1011,68134, 2,67988, 3,67988, 11,68140, 33,68143, 11,68141, 25,68147, 1369,68141,37409,68141, 2,67989, 3,67989, 483,68157,49713,67988,56555,68160, 483,68160, 11,67988, 3,68166, 33,68169, 3,68167, 113,68173, 15,65869,10095,68176, 10093,68179,54643,68177,54655,68183,49537,68177,49529,68187,54655,68176, 54643,68191,49529,68176,49537,68195,16091,68176, 9513,68199,60125,68176, 59787,68203,16859,68177, 9875,68207,21529,68177,20501,68211, 1,68176, 2,68215, 1,68216,68177,68219, 7,68216,68221,68223, 7,68215, 2,68226, 1368,68215, 6,68176, 2,68233, 6,68234,68177,68237, 0,68234,68239,68241, 0,68233, 2,68244,18966,68233,56554,68176, 2,68251, 7,68252, 7,68251, 2,68256, 1368,68251, 482,68176, 2,68263, 0,68264, 0,68263, 2,68268,18966,68263,20501,68176, 9513,68275,59787,68275,21529,68275, 9875,68176,59787,68283, 9513,68283, 16859,68283,59787,68177,60125,68291, 9875,68291,20501,68291, 9513,68177, 16091,68299,20501,68299, 9875,68299, 483,68177, 2007,68307, 3477,68307, 68267,68307,68271,68307, 5197,68307,68241,68307,68247,68307, 1,68307, 19051,68307,19667,68307, 5123,68307,12345,68307,68249,68307,68273,68307, 18967,68307, 555,68337,68233,68337,68263,68337,56555,68177,59637,68345, 59717,68345,68255,68345,68259,68345,68223,68345,68229,68345, 6,68345, 59649,68345,39747,68345,43837,68345,43027,68345,68231,68345,68261,68345, 1369,68345,59619,68373,68215,68373,68251,68373,18967,68176,19553,68381, 19549,68381,20345,68381,20281,68381, 7,68381,68345,68391,68359,68381, 10093,68381,10085,68381,20285,68381,10087,68381,19555,68381, 483,68381, 20273,68407,10081,68407,19545,68407, 1369,68176,67281,68415,67273,68415, 3587,68415, 1989,68415, 0,68415,68307,68425,68323,68415,56681,68415, 57911,68415, 4897,68415,17041,68415,67291,68415,56555,68415, 1471,68441, 67269,68441, 3,68176,40909,68447, 3,68177,40895,68451,40059,68451, 43749,68451,38903,68451,18967,65869,20347,68460,20345,68463, 1203,68461, 1205,68467, 1009,68461, 1007,68471, 1205,68460, 1203,68475, 1007,68460, 1009,68479, 97,68460, 21,68483, 571,68460, 555,68487, 177,68461, 59,68491, 1365,68461, 1325,68495, 2,68460, 6,68499, 2,68500, 68461,68503, 5,68500,68505,68507, 5,68499, 6,68510, 14,68499, 4,68460, 6,68517, 4,68518,68461,68521, 3,68518,68523,68525, 3,68517, 6,68528, 1274,68517, 482,68460, 6,68535, 5,68536, 5,68535, 6,68540, 14,68535, 8,68460, 6,68547, 3,68548, 3,68547, 6,68552, 1274,68547, 256,68461, 629,68461, 1325,68460, 21,68563, 251,68563, 555,68563, 1365,68563, 59,68460, 555,68573, 251,68573, 21,68573, 177,68573, 555,68461, 571,68583, 331,68583, 59,68583, 1325,68583, 21,68461, 97,68593, 331,68593, 1325,68593, 59,68593, 331,68460, 251,68603, 555,68603, 21,68603, 251,68461, 331,68611, 59,68611, 1325,68611, 9,68461, 7951,68619, 7961,68619, 68551,68619,68555,68619,68451,68619,68525,68619,68531,68619, 2,68619, 7953,68619,35893,68619,38299,68619,37897,68619,68533,68619,68557,68619, 1275,68619, 7947,68649,68517,68649,68547,68649, 483,68461, 9517,68657, 9525,68657,68539,68657,68543,68657,20033,68657,68507,68657,68513,68657, 4,68657, 9519,68657,57855,68657,60853,68657,60609,68657,68515,68657, 68545,68657, 15,68657, 9513,68687,68499,68687,68535,68687, 1275,68460, 67245,68695,67253,68695,10041,68695,10005,68695, 5,68695,68657,68705, 68673,68695,10009,68695,23879,68695,31937,68695,30399,68695,67263,68695, 9,68695,10001,68721,67241,68721, 15,68460,19549,68727,19553,68727, 10093,68727,10085,68727, 3,68727,68619,68737,68635,68727,20345,68727, 20281,68727,10087,68727,20285,68727,19555,68727, 483,68727,10081,68753, 20273,68753,19545,68753, 7,68460,58715,68761, 375,68761, 7,68461, 58703,68767,58027,68767,60849,68767,68345,68767,35603,68767, 59,68767, 1325,68767, 331,68767, 265,68767, 241,68766, 241,68461, 6,68789, 7,68789, 6,68788,68793,68795, 7,68788,68791,68799, 265,68460, 375,68803, 1011,65869,59960,68807,61780,68806,63014,68806,62538,68806, 17455,68806,47640,68806, 5843,68806,48534,68806, 483,68806,60857,68824, 9,68806,60857,68828,46863,68806,60857,68832, 903,68832, 11,68833, 587,68832, 587,68806,46863,68842, 11,68807,46863,68847, 7,68807, 56555,68850,63823,68851, 9377,68851, 903,68806,46863,68858,56555,68807, 6,68863, 7,68863, 6,68862,68867,68869, 7,68862,68865,68873, 60857,68806, 7,68877, 483,68876,46863,68876, 9,68876,62942,65869, 7,68887,46863,68886, 9,68886, 483,68886,60857,65869,58782,68896, 58362,68896,47608,68896, 1108,68896, 1072,68896, 165,68896, 524,68896, 1291,68896, 11,68897, 483,68915, 9,68896, 1011,68918, 587,68897, 483,68923,46863,68896,56555,68926, 1011,68926, 483,68896,56555,68932, 587,68933, 11,68933, 1011,68932, 11,68932, 11,68896, 483,68944, 7,68897, 1141,68949, 1447,68949, 33,68949,56555,68896, 9,68957, 46863,68956, 483,68956, 1011,68896, 7,68965, 9,68964, 483,68964, 46863,68964, 265,65869,16710,68974,44242,68974,16711,68974,16710,68975, 68981,68983,45086,68975,44242,68975, 3,68988,44243,68974,68987,68993, 68991,68993,60797,68975,60796,68974,68999,69001,60796,68975,60797,68974, 69005,69007, 3,68975,44242,69011,44242,69010,68993,69015, 6,69010, 1274,68975,44243,68975,69013,69023,45087,68975,68979,69027,16711,68975, 68977,69031, 1275,68975, 4899,69035,14611,69035,47961,69035, 11,68974, 9,69043,46863,68974,69019,69047,69021,69047, 9,68975, 11,69053, 6,68974, 0,69056,69035,69059, 7,68974,25793,69063,41019,69063, 8717,69063, 8495,69063, 3785,69063, 6,68975, 3,69074,69047,69077, 7,68975, 8647,69081,21605,68975, 375,69085,18967,68974, 375,69089, 11,65869,39085,69093,49204,69092, 33,69097, 803,69093,63014,69092, 25381,69092, 265,69092, 9,69107,60857,69092, 483,69110, 483,69092, 60857,69114, 1275,69092, 9,69119, 2,69092,44243,69123, 3,69092, 33,69127,46863,69129,46863,69126, 33,69133, 3,69093,49283,69137, 47546,69137, 113,69137,46863,69142,46863,69137, 113,69146,46863,69092, 3,69150, 33,69153, 3,69151, 113,69157,20034,65869, 375,69161, 48560,65869, 3,69164, 33,69167, 3,69165, 113,69171,59206,65869, 7,69175,29598,65869, 7,69179,60455,65869, 256,69183, 375,69183, 7,69183, 241,69188, 241,69183, 7,69192,15029,65869,56555,69196, 7,69199,28715,65869, 256,69203, 1505,69202, 7,69203, 241,69208, 241,69203, 7,69212, 903,69202, 7,69217,54027,65869, 375,69221, 2,69220,54159,69225,46863,69227, 2,69221,54256,69231,46863,69231, 54225,69234,54225,69231,46863,69238,17635,65869, 7,69243, 2,69244, 2,69245, 1368,69243, 1369,69243, 2,69242,69253,69255, 3,69242, 69247,69259,69251,69259, 2,69243, 7,69264,69259,69267, 3,69243, 69249,69271, 2,65868,41692,69275,41607,69275, 8672,69275, 8743,69275, 26454,69275,26375,69275, 8770,69275, 8729,69275, 3795,69275,47953,69275, 48062,69275,47961,69275,48009,69298,48009,69275,47961,69302,41417,69275, 41653,69306,26219,69275,26415,69310,31770,69275,44832,69275, 8757,69275, 8647,69318,26415,69275,26219,69322,41653,69275,41417,69326, 8647,69275, 305,69330, 8757,69330, 8605,69275,47580,69275,47933,69339, 8684,69275, 8717,69343, 8916,69275,31103,69275, 9,69348,26292,69275,26331,69353, 340,69275, 8717,69357, 3785,69357, 8495,69357, 375,69275, 8861,69364, 46863,69364,47488,69275,41502,69275,41559,69373, 483,69275,44243,69376, 305,69275, 8647,69380, 7,69275, 1,69385, 264,69386, 264,69387, 41019,69385,41653,69393,25793,69385,26415,69397, 8495,69385, 305,69401, 8757,69401, 8495,69384, 8717,69407,25793,69384,26331,69411, 265,69385, 69391,69415, 8861,69415,46863,69415,41019,69384,41559,69423, 265,69384, 8717,69427,69389,69427, 3785,69427, 8495,69427,44243,69275, 483,69436, 9,69275,31103,69440,46863,69275, 265,69445,48009,69447, 265,69444, 47933,69451, 375,69444,25793,69275, 7,69457,26219,69459, 7,69456, 26331,69463, 265,69275,46863,69467,47961,69469,46863,69466,47933,69473, 7,69467, 8647,69477, 7,69466, 8717,69481, 3785,69481, 8495,69481, 41019,69275, 7,69489,41417,69491, 7,69488,41559,69495, 8495,69275, 7,69498, 8717,69501, 7,69499, 8647,69505, 8861,69275, 375,69508, 3,65868,21116,69513,21253,69513,21560,69513,20465,69513,20576,69513, 59683,69513,42035,69513, 9573,69513,59689,69513, 9575,69513,42041,69513, 43711,69513,42089,69513,42129,69513, 1,69513, 6,69543,68974,69544, 68975,69545,69547,69549,68974,69545,68975,69544,69553,69555, 4,69513, 6,69558,66665,69561,66785,69561,66997,69561,68695,69561, 9599,69513, 8,69513,66997,69573,66785,69573,66665,69573,68695,69573,67011,69513, 66805,69513,68721,69513,66693,69513,60569,69513,59701,69513,59767,69513, 9605,69513,32468,69513,28483,69513,19625,69513,20501,69602,43015,69513, 44714,69513,19474,69513,20413,69611,20805,69513,20186,69513,21549,69513, 20501,69618,21105,69513,20501,69622, 1418,69513,59619,69627, 9565,69627, 41941,69627, 669,69513, 9565,69635,59619,69635,41941,69635,37501,69513, 31103,69513,27021,69644, 8386,69513,50657,69513,36944,69513,48408,69513, 1369,69513, 15,69656, 9565,69659,41941,69659,59619,69659, 483,69513, 46863,69666,20501,69513,21105,69670,21549,69670,19625,69670, 6,69513, 3,69679,56555,69681,65869,69683, 4,69678,66665,69687,66785,69687, 66997,69687,68695,69687,69685,69687, 3,69678,68460,69699,69687,69701, 18967,69699,65869,69704,69687,69707,65869,69699,18967,69710,69687,69713, 7,69513,20103,69716, 8337,69716,36773,69716,27021,69513,31103,69724, 7,69512,24265,69729,28233,69729,29077,69729,20361,69729, 9673,69729, 4279,69729, 9967,69729,19559,69729, 4283,69729,20713,69729, 3807,69729, 8251,69729,44243,69513,41941,69754,46863,69513, 483,69758, 15,69513, 18967,69763,20501,69765,18967,69762,20413,69769, 1369,69762, 9565,69773, 41941,69773,59619,69773, 8337,69513, 7,69780,18967,69513, 15,69784, 20413,69787, 1011,69513,44242,69790,44242,69791,44243,69790,69795,69797, 44243,69791,69793,69801,28715,69513, 7,69805,36773,69513, 7,69808, 41941,69513,44243,69812,20103,69513, 7,69816,20273,69513, 6,69820, 7,69820, 6,69821,69825,69827, 7,69821,69823,69831, 9617,69513, 6,69834, 7,69834, 6,69835,69839,69841, 7,69835,69837,69845, 6,65868, 1,69849, 3,69850, 4,69849, 3,69855,67988,69856, 67989,69857,69859,69861,67988,69857,67989,69856,69865,69867,21604,69849, 3,69849, 1,69872, 7,65868,59007,69877,58999,69877,59025,69877, 19981,69877,48747,69877,37279,69877,57047,69877,57029,69877,58153,69877, 1,69877, 2,69896,66625,69899,66825,69899,66973,69899,68415,69899, 58167,69877,56554,69877,66973,69911,66825,69911,66625,69911,68415,69911, 66987,69877,66845,69877,68441,69877,66653,69877,24601,69877,57437,69877, 57021,69877,57069,69877,54107,69877,52743,69877,52193,69877,20734,69877, 25551,69877,24613,69877,28205,69877,20501,69877, 265,69950, 241,69951, 1141,69877,56555,69957,60577,69877,62959,69877,58377,69877,57981,69877, 19916,69877, 7947,69969,48739,69969,37241,69969,58931,69877,48739,69977, 7947,69977,37241,69977, 8306,69877, 33,69877,56555,69987, 1447,69877, 56555,69991, 9875,69877, 241,69995, 265,69994, 9992,69877, 545,69877, 695,69877, 1382,69877, 1374,69877, 1386,69877, 154,69877, 483,70013, 60455,69877, 483,70017, 1369,69877, 331,70020, 1325,70020, 59,70020, 1325,69877, 1369,70028, 1275,69877,18967,70032,48739,70035,37241,70035, 7947,70035, 59,69877, 1369,70042, 2,69877, 7,70047, 9,70049, 65869,70051, 1,70046,66625,70055,66825,70055,66973,70055,68415,70055, 70053,70055, 7,70046,68176,70067,70055,70069, 15,70067,65869,70072, 70055,70075,65869,70067, 15,70078,70055,70081, 3,69877, 8241,70085, 15,70084, 483,70089, 331,69877, 1369,70092, 3,69876,24265,70097, 28233,70097,29077,70097,19559,70097,20713,70097, 4283,70097,20361,70097, 9673,70097, 4279,70097, 9967,70097, 8251,70097, 3807,70097,18967,69877, 1275,70122,48739,70125,37241,70125, 7947,70125, 113,70123, 1011,69877, 265,69877,20501,70136, 8165,70136, 9875,70136,46863,69877,38056,70144, 38056,70145,38057,70144,70149,70151,38057,70145,70147,70155, 15,69877, 3,70159, 1369,70161, 3,70158, 483,70165,54027,69877, 483,70169, 8165,69877, 265,70172, 7,65869,69874,70176,69875,70177,70179,70181, 69875,70176,69874,70177,70185,70187,69852,70176,69853,70177,70191,70193, 69853,70176,69852,70177,70197,70199,11276,70176,11277,70176,11276,70177, 70205,70207, 5044,70176, 5045,70176, 5044,70177,70213,70215,40583,70177, 40583,70176,40582,70176,70219,70223,40582,70177,70221,70227,24094,70177, 69871,70177,69870,70177,21604,70177,69849,70236, 9,70236,21604,70176, 70233,70243,69849,70243, 9,70243, 4,70177, 0,70250, 1,70177, 264,70254, 264,70255,24095,70177,70243,70261,45149,70177,26498,70177, 41326,70177, 8796,70177,27533,70177, 9,70273,25793,70177,27021,70277, 587,70276, 241,70277, 5045,70177,70211,70285,11277,70177,70203,70289, 4551,70177,10001,70177, 9,70295, 8495,70177, 305,70299, 587,70298, 241,70299, 88,70177, 1369,70307, 587,70177,25793,70310,41019,70310, 8495,70310, 1369,70177,20103,70319,36773,70319, 8337,70319, 265,70177, 70259,70327,63493,70327, 8861,70327,46863,70327, 89,70177,46863,70337, 483,70177,18967,70341,37241,70343,48739,70343,70253,70343, 7947,70343, 1275,70177,44243,70353,21605,70176,70231,70357,70235,70357,70239,70357, 70241,70357,70237,70357,69849,70367, 9,70367,26331,70357,23755,70357, 27805,70357, 241,70176,25793,70379,59875,70379,41019,70379, 8495,70379, 9805,70379,53391,70379, 903,70176,25793,70393, 8495,70393,41019,70393, 18967,70176,58715,70401, 375,70401, 265,70176,70257,70407,25793,70407, 41019,70407, 8717,70407, 8495,70407, 3785,70407,21605,70177,70246,70421, 69849,70421,70243,70424,70248,70421,70243,70421,69849,70430, 9,70430, 24545,70421, 9,70421,70243,70438, 903,70421, 241,70177,51487,70445, 375,70177, 1369,70449,41019,70177, 587,70452, 241,70453, 2,70176, 48009,70459, 265,70459,46863,70463,49321,70459,49001,70459, 3,70176, 58056,70471,58601,70471,40799,70471,44243,70471,56555,70478,35927,70471, 375,70471, 510,70471, 483,70471, 9,70488,38155,70471,37611,70471, 56555,70471,44243,70496, 9,70471, 483,70500, 2,70177,44243,70505, 48466,70505,47640,70505,46863,70505, 9,70512, 903,70512, 903,70505, 46863,70518, 9,70505,46863,70522,49155,70505, 3,70177, 1369,70529, 9,70531,37663,70529, 9,70528, 1369,70537,18967,70529,44243,70541, 69849,70177,21604,70545,70421,70547,21604,70544,70357,70551, 9,70177, 21604,70555,70421,70557,21604,70554,70357,70561, 3,70554, 1369,70565, 3,70555, 483,70569, 3,65869,60078,70572,60079,70572,13748,70573, 13736,70572,70579,70581,13736,70573,13737,70572,13749,70573,70587,70589, 1,70573, 5,70592, 1,70572,69385,70597,69384,70597,69275,70597, 7,70602, 7,70603,59961,70597, 6,70596,70601,70611,70605,70611, 7,70596,70599,70617,69275,70617, 6,70597,69275,70623,70617,70624, 70607,70623,70620,70623,70617,70623,69275,70632,56555,70623, 7,70597, 69275,70638,70611,70641,70611,70639,69275,70645,48560,70572, 33,70649, 60230,70573,57986,70573,58352,70573, 8309,70573,13737,70573, 7,70660, 70581,70663,59960,70573,70575,70667,70611,70667, 241,70666, 256,70573, 56555,70674, 11,70573,48583,70679,48328,70679, 25,70679,46863,70684, 46863,70679, 25,70688,59961,70573,70577,70693, 483,70573, 15,70697, 41941,70699, 9565,70699,70595,70699,59619,70699, 1369,70573,46863,70709, 37409,70573,46863,70713,46863,70572, 11,70716, 33,70719, 1369,70717, 11,70717, 25,70725,37409,70717, 15,70572,40909,70731, 11,70572, 33,70735,46863,70737,46863,70734, 33,70741, 6,70572, 1,70744, 70667,70747, 5,70744, 7,70572,70609,70753,58056,70753,70636,70753, 70623,70753,56555,70760,40799,70753,58601,70753,44243,70753,56555,70768, 35927,70753, 375,70753, 510,70753, 483,70753, 9,70778,38155,70753, 37611,70753, 9,70753, 483,70786,56555,70753,70623,70790,44243,70790, 6,70573,70731,70797,56555,70797, 7,70573,13737,70802,70581,70805, 13737,70803,70585,70809,70611,70803,56555,70813,70747,70803,56555,70817, 70751,70803,42613,70803,56555,70823,54497,70803,54159,70803,51803,70803, 58348,70802,10291,70803,56555,70835, 59,70803, 1325,70803, 331,70803, 1275,70803, 9,70845,56555,70802,70611,70849,70747,70849, 241,70848, 241,70802,56555,70856, 15,70803, 483,70861,69275,70573,58348,70573, 7,70866,38057,70573, 7,70871,43503,70573,44243,70875,56555,70573, 256,70878, 7,70878,70611,70883,70747,70883, 241,70882, 7,70879, 70623,70891, 241,70878, 7,70894, 241,70573,44242,70899,44242,70898, 44243,70899,70903,70905,59960,70898,44243,70898,70901,70911, 7,70898, 56555,70914,56555,70898, 7,70918, 2,65869, 1,70922,69635,70925, 668,70925,69513,70929,69627,70925, 1419,70925,69513,70935,70699,70925, 69659,70925,69773,70925, 587,70925, 9,70944,69513,70947, 9,70925, 587,70950,69513,70953,54027,70922,54159,70957,46863,70959,54027,70923, 54154,70963,46863,70963,54129,70966,54129,70963,46863,70970,44243,70923, 11,70975,46863,70922, 11,70922,44243,70981, 6,70922, 0,70985, 5,70986, 5,70985, 0,70991, 0,70990, 1,70984,70995,70997, 70989,70997,70987,70997, 5,71003, 1,70985,70993,71007, 5,71007, 0,70984, 5,71013,71007,71014,71010,71013,71007,71013, 5,71020, 903,70985, 1,71025, 0,71025, 1,71024,71029,71031, 0,71024, 71027,71035, 7,70922,48009,71039, 265,71039,46863,71043,49321,71039, 49001,71039, 7,70923,70989,71051,70997,71052,70995,71051,70997,71056, 70998,71051,71000,71051,71005,71051,71009,71051,71017,71051,71019,71051, 71023,71051,71011,71051,71013,71075,14219,71051,14013,71051,14267,71051, 16151,71051,70997,71051,70995,71086,70989,71086,56554,71051, 1,71051, 2,71094, 2,71051, 1,71098,14211,71051, 9165,71103, 9,71051, 65869,71107,71093,71109,71097,71109,71101,71109,70985,71051,69513,70923, 903,70923,46862,71120,46862,71121,46863,71121,71123,71127,46863,71120, 71125,71131, 6,65869, 1,71134,70803,71137,56555,71139, 4,71134, 69977,71143,58930,71143,69877,71147,69969,71143,19917,71143,69877,71153, 70343,71143,70035,71143,70125,71143, 587,71143,56555,71162,69877,71165, 56555,71143, 587,71168,69877,71171, 2,71134, 903,71175, 1,71177, 0,71177, 1,71176,71181,71183, 0,71176,71179,71187, 2,71135, 265,71191, 0,71192, 1,71192, 0,71193,71197,71199, 1,71193, 71195,71203, 3,71135, 8,71207, 4,71207, 6,71210, 6,71207, 4,71214,56555,71207,65869,71219,71209,71221,71213,71221,71217,71221, 0, 5,59619,71229,59961,71230,60166,71229, 1207,71228,19105,71237, 1180,71228,19119,71241,60158,71228,60180,71228,60178,71228,60318,71228, 60167,71229, 1197,71228,59875,71255,53391,71255, 9805,71255,60159,71228, 60181,71228,60179,71228,38158,71229,44195,71269, 1196,71228,60319,71228, 28739,71229, 2,71277,29229,71279, 59,71228,60221,71283,63823,71228, 61747,71287,61585,71287,61475,71287,63185,71287, 39,71228,56555,71297, 15,71299, 6,71298,71301,71303, 14,71299, 7,71298,71307,71309, 1163,71228,19119,71313, 25,71228,61747,71317,63185,71317,25461,71317, 61585,71317,70985,71228,71086,71327,70997,71327,71051,71330,71051,71327, 70997,71334,38057,71229, 6,71338,44195,71341,60973,71229, 1179,71345, 49213,71229,49217,71349,54619,71229, 11,71353,54655,71355, 1003,71229, 60857,71359, 1007,71361,11995,71228,12025,71365,64569,71228,64587,71369, 61989,71228,61747,71373,63185,71373,61585,71373, 8065,71229, 11,71381, 8067,71383,63777,71229,60857,71387,63779,71389,21918,71229, 987,71393, 54336,71229,54339,71397, 989,71229,21605,71400, 987,71403,21890,71229, 1179,71407,49262,71229,49217,71411,54331,71229, 17,71414,54339,71417, 25395,71228,25461,71421, 1293,71228,61475,71425,25433,71228,25461,71429, 61005,71228,61475,71433,63014,71228, 5,71437, 7,71438, 7,71437, 5,71442, 10,71437, 524,71228, 0,71449, 3,71450, 3,71449, 0,71454,60856,71449,21904,71229, 25,71461, 809,71229,21605,71464, 713,71467,13755,71229, 17,71470, 9377,71473,65054,71229,63823,71477, 117,71229,21605,71480, 25,71483,21916,71229, 713,71487,13764,71229, 9377,71491,65037,71229, 17,71494,63823,71497, 1177,71229,21605,71500, 1179,71503,49229,71229, 17,71506,49217,71509,26867,71229,21605,71512, 26865,71515,10161,71229, 17,71518,10159,71521,26868,71229,26865,71525, 10162,71229,10159,71529, 1180,71229, 2975,71533, 1903,71533,19025,71533, 33464,71229,34655,71541,34447,71541,33221,71541,33773,71541, 1207,71229, 19027,71551, 3567,71551, 1973,71551, 3041,71551, 1921,71551,19049,71551, 9824,71229,71273,71565,53462,71229,71273,71569,59900,71229,71273,71573, 60319,71229,71251,71577,60159,71229,71245,71581,60178,71229,71267,71585, 59901,71229,71255,71589,60158,71229,71263,71593,60180,71229,71265,71597, 25461,71229, 25,71601,25395,71601,25433,71601,61475,71229,63823,71609, 1293,71609,61005,71609,65808,71229,65513,71617,65791,71617,65407,71617, 65171,71617,60835,71229,60318,71229,71275,71629, 9617,71629,19797,71229, 375,71635,20735,71229,47386,71229,20040,71229,20050,71229,61747,71229, 63823,71647, 25,71647,61989,71647,63185,71229, 25,71655,63823,71655, 61989,71655,61585,71229,63823,71663, 25,71663,61989,71663,20056,71229, 375,71671, 9825,71229,71255,71675,53463,71229,71255,71679,57562,71229, 58846,71229,58372,71229,58758,71229,58762,71229,57224,71229,57284,71229, 57278,71229,58760,71229,20686,71229,24738,71229, 305,71703, 713,71703, 1489,71703, 25,71703,10074,71229, 9377,71713,17573,71713,63823,71713, 22766,71229, 305,71721, 25,71721, 147,71721, 713,71721,27672,71229, 63823,71731,27995,71731, 9377,71731,62147,71229, 25,71739, 305,71739, 147,71739, 169,71739, 713,71739,31881,71229,63823,71751,27995,71751, 31359,71751, 9377,71751,60221,71229, 59,71761, 653,71229, 11,71765, 9993,71229,17542,71229, 9936,71229,24734,71229, 305,71775, 713,71775, 25,71775,60834,71229,21350,71229,16129,71229, 3,71787, 2,71787, 842,71787, 843,71786,71793,71795, 843,71787, 842,71786,71799,71801, 3,71786,71791,71805, 2,71786,71789,71809,16966,71229,19480,71229, 50522,71229,52740,71229,57380,71229,59108,71229,50478,71229,57252,71229, 19986,71229,51036,71229,57576,71229,58112,71229,58362,71229, 903,71836, 47640,71229,56555,71840,60179,71229,71249,71845,60181,71229,71247,71849, 63015,71229,71441,71853,71445,71853,62905,71853,63041,71853,63047,71853, 63215,71853, 6,71853,63205,71867,19687,71853,21127,71853,20843,71853, 63049,71853,71447,71853, 11,71853,63033,71881,71437,71881,19917,71229, 9,71886, 525,71229,71453,71891,71457,71891,36729,71891, 1851,71891, 1885,71891,35635,71891, 2,71891,35633,71905,62095,71891,17711,71891, 4907,71891,61003,71891,71459,71891,60857,71891, 531,71919,71449,71919, 1413,71229, 331,71925,49713,71924, 1419,71229,56555,71930,58782,71229, 903,71934, 296,71229, 8861,71939, 1106,71229,18967,71943, 9617,71943, 24095,71229,46863,71949,57522,71229, 11,71953, 903,71952, 587,71952, 51004,71229, 483,71960,22956,71229,70471,71965,70753,71965,10159,71965, 26865,71965,10111,71965,26715,71965,23709,71965,23713,71965,67425,71965, 10113,71965,26719,71965,23715,71965, 587,71965,10107,71991,26625,71991, 23651,71991,19475,71229, 483,71998, 918,71229,56555,72002, 922,71229, 56555,72006,49713,72006, 668,71229,56555,72012, 1290,71229, 2,72017, 35575,72019,35585,72017, 3621,72017, 1991,72017,60969,72017,62095,72017, 17711,72017, 4907,72017,60857,72017, 1325,72037,58930,71229, 9,72040, 52692,71229, 903,72044,25380,71229, 6,72049,38881,72051,38891,72049, 9927,72049, 9891,72049, 9895,72049,19687,72049,21127,72049,20843,72049, 11,72049, 9875,72069, 1447,71229,15705,72073, 9917,71229,20615,71229, 759,71229,17455,72081, 9195,71229, 1487,72085, 1471,71229,21605,72088, 305,72091, 713,72091, 1489,72091, 25,72091, 9805,71229, 1197,72101, 1275,72101, 9,72105, 1197,72100,71273,72109,10001,71229, 17,72112, 9377,72115,17573,72115,63823,72115,17455,71229,12377,72122,59961,71229, 59619,72126, 1011,72126, 9617,72131, 1011,72127, 9565,72135,59619,72135, 89,71229,17455,72141,60797,71229,59381,72144, 165,71229,21315,72148, 587,71229,66971,72153,17455,72153,57522,72152, 9,72152,56555,72160, 56555,72152, 9,72164,60857,72153, 9,72169, 1369,71229,39085,72173, 21605,72172,20843,72177,21127,72177, 9927,72177, 9891,72177,19687,72177, 9895,72177, 11,72177, 9875,72191, 1275,71229, 17,72194, 4907,72197, 17711,72197, 3621,72197, 1991,72197,62095,72197,60969,72197,60857,72197, 1325,72211, 483,71229,20035,72214,58742,72214,19475,72214,51004,72214, 56555,72214, 903,72224, 903,72214,56555,72228,49713,72228,49713,72214, 903,72234,55839,71229,46863,72239,65061,71229,60857,72243,65063,72245, 65067,72245,65071,72245, 7065,71229,18967,72253, 6789,71229, 11,72257, 6843,72259, 6885,72259, 6889,72259,11277,71229,46863,72267, 9935,71229, 1011,72270,20645,71229, 1011,72274, 3445,71229, 375,72279, 5045,71229, 46863,72283,17104,71229,48643,72287,12614,71229, 375,72291,69872,71229, 68155,72295,71116,71229,71013,72299,70985,71229,71013,72303,71051,72305, 71051,72302,71013,72309,71051,71229,70985,72313,70997,72315,70985,72312, 71013,72319, 482,71228,23717,72323,24522,72323,24447,72323,23939,72328, 23939,72323,24447,72332,22956,72323,23651,72337,21605,72323, 17,72341, 23939,72343, 17,72340,23651,72347, 17,72323,21605,72351,24447,72353, 21605,72350,23651,72357, 1368,71228, 7,72361, 5,72362,72049,72365, 72177,72365, 5,72361, 7,72370,72049,72373,72177,72373,72191,72361, 72069,72361, 10,72361,72177,72383,72049,72383,27021,72361,24095,72361, 9195,72361,52915,72361,23651,72361,51435,72361,21605,72361, 9,72401, 67297,72361,70097,72361,69729,72361,11277,72361, 5045,72361,10171,72361, 53941,72361, 9755,72361,26907,72361, 4321,72361,27323,72361, 3833,72361, 9317,72361, 4295,72361,53215,72361, 1274,71228, 3,72435, 0,72436, 72017,72439,72197,72439, 0,72435, 3,72444,72017,72447,72197,72447, 72211,72435,72037,72435,60856,72435,72197,72457,72017,72457, 586,71228, 39619,72463,51421,72463,57811,72463,59933,72463,59743,72463, 8093,72463, 3837,72463,42435,72463, 4287,72463,53703,72463, 4303,72463,42113,72463, 9839,72463,53487,72463, 9579,72463, 483,72463, 803,72494, 828,72463, 705,72463, 803,72463, 483,72502, 482,71229,66737,72507,36661,72507, 62741,72507,68727,72507,68381,72507, 1274,71229, 587,71228,61747,72521, 25461,72521,61475,72521,63185,72521,61585,72521, 483,71228,56555,72533, 6,72535, 5,72536, 7,72535, 5,72535, 6,72542, 6,72543, 72541,72547, 6,72534, 15,72535,72551,72553, 7,72534,72545,72557, 72539,72557, 14,72535,72557,72563, 1368,71229,55839,72567,51803,72567, 54159,72567,54497,72567, 265,72567, 1275,71228,59914,72579,60221,72579, 18708,72579, 9856,72579,53504,72579, 9805,72579, 9,72590,53391,72579, 9,72594,59875,72579, 9,72598,18693,72579, 9,72602,60369,72579, 9,72579,18693,72608, 9805,72608,59875,72608,53391,72608, 586,71229, 33,72619, 1447,72619, 1141,72619, 889,72619, 795,72619, 787,72619, 767,72619, 483,72633, 1505,71229,16937,72636,56555,72636, 581,71229, 60857,72643, 1325,72645, 331,72645, 571,72645, 585,72645, 59,72645, 16937,71229, 1505,72656,13947,71229, 2,72661,14217,72663, 11,72661, 9875,72667,16091,72667,13955,72667,20501,72667, 9919,71229,20623,71229, 9921,71229, 1196,71229,72103,72683,71256,72683,71258,72683,71260,72683, 71255,72683,59875,72692,53391,72692, 9805,72692,59875,72683,71255,72700, 9805,72683,71255,72704,53391,72683,71255,72708, 154,71229,64148,71229, 1325,72715, 59,72715, 331,72715, 265,72715,52501,71229, 265,72725, 297,71229,18967,72729, 1107,71229,59960,71229,21105,72735,65513,72735, 65791,72735,65407,72735,21549,72735,19625,72735,65171,72735,59619,72735, 15,72735, 88,71229,70177,72755,70176,72754,72757,72759,70176,72755, 70177,72754,72763,72765, 1141,72755, 1447,72755, 33,72755, 11,72755, 37409,72755, 972,71229, 59,72779, 1325,72779, 331,72779,27978,71229, 60796,71229,59381,72789,31102,71229,62905,72793,68761,72793,70401,72793, 67541,72793, 164,71229,36729,72803,68447,72803,70731,72803,67547,72803, 54596,71229,44243,72813,20695,71229, 155,71229,20763,71229, 375,72820, 1197,71229,71273,72825,59875,72827, 9805,72827,53391,72827,53391,72824, 71273,72835, 9805,72824,71273,72839,59875,72824,71273,72843, 375,71229, 20763,72846,20836,71229, 1141,71229,15705,72853, 33,71229,15705,72857, 27021,71229, 1487,72861, 959,71229,17455,72865,52915,71229, 1487,72869, 47,71229,17455,72873,59875,71229, 1197,72877,72683,72879, 1275,72877, 9,72883, 1197,72876,71273,72887, 253,71229,21605,72890, 305,72893, 25,72893, 713,72893,53391,71229, 1197,72901,72683,72903, 1275,72901, 9,72907, 1197,72900,71273,72911, 53,71229,21605,72914, 305,72917, 25,72917, 147,72917, 713,72917,27533,71229, 17,72926,63823,72929, 27995,72929, 9377,72929,30749,71229, 7,72937,26970,71229, 7,72941, 70864,71229, 7,72945,69849,71229, 3,72948,68155,72951, 3,72949, 67577,72955,68139,72955,70979,72955,69275,71229,70573,72962, 7,72965, 69513,71229, 1011,72968, 7,72971, 9780,71229, 7,72975,59381,71229, 2,72979,72789,72981,60797,72978, 6,72978,56555,72986,72981,72989, 26625,71229, 1011,72992, 7,72995, 9731,71229, 1011,72998, 7,73001, 69790,71229, 7,73005, 13,71229,32805,71229, 7,73010,33221,73013, 34655,73013,33773,73013,34447,73013, 15,73011,34875,73023, 7,73011, 34723,73027, 19,71229, 59,73031, 18,71229,65076,71229, 7,73037, 65493,73039, 7,73036,65171,73043,65791,73043,65513,73043,65407,73043, 15,73037,65357,73053, 12,71229,68974,71229, 375,73059,71119,71229, 7,73063, 1011,71229,52387,73067,20762,73067,59961,73066, 9617,73073, 20645,73066, 9935,73066, 17,73066,18967,73081, 9617,73081, 6,73066, 7,73067,18967,73088,26625,73066, 7,73093,18967,73067, 7,73096, 17,73097, 9731,73066, 7,73103,69513,73066, 7,73107,21315,73066, 7,73111, 15,71229,18967,73115, 17,73117, 3,73114, 3,73115, 72567,73123, 17,73114, 265,71229, 9,73128, 8861,73131,60857,73129, 9,73135,65869,73128, 375,73139, 11,71229,60857,73143, 9,73145, 1275,73143, 9,73149, 9,73142,60857,71229, 7,73154, 59,73157, 1325,73157, 331,73157, 265,73157, 7,73155, 375,73167, 265,73155, 375,73171,12377,73154, 7,73175,18967,71229, 7,73179,25793,73181, 41019,73181, 8495,73181,46863,71229,20035,73188,58742,73188, 903,73188, 56555,73194,56555,73188, 903,73198,20035,71229,21183,73203, 7,73203, 331,73207, 483,73202,46863,73202, 9,73202, 7,73202, 375,73217, 49713,71229,39085,73221, 136,73220, 1197,73220, 137,73220, 922,73220, 1413,73220, 1011,73220, 6,73234, 483,73220, 903,73238, 903,73220, 483,73242, 2,73220, 9,73246,44243,73247, 3,73220, 5,73253, 6,73255, 9,73253, 2,73221,73257,73261,73229,73261,73258,73261, 29229,73261,72683,73261,73237,73261,73087,73261, 9,73261,73253,73276, 73253,73261, 9,73280, 3,73221,73225,73285,73249,73285,73227,73285, 73247,73285, 9,73293, 9,73220, 2,73296,73285,73299, 2,73297, 73253,73303, 17,71229,10161,73306,10159,73309,54339,73307,54331,73313, 49217,73307,49229,73317,54331,73306,54339,73321,49229,73306,49217,73325, 65037,73306,63823,73329,13755,73306, 9377,73333,27995,73307,27533,73337, 17573,73307,10001,73341, 7,73306, 3,73345, 7,73346,73307,73349, 1,73346,73351,73353, 1,73345, 3,73356,21604,73345, 0,73306, 3,73363, 0,73364,73307,73367, 6,73364,73369,73371, 6,73363, 3,73374, 1274,73363, 586,73306, 3,73381, 1,73382, 1,73381, 3,73386,21604,73381,60856,73306, 3,73393, 6,73394, 6,73393, 3,73398, 1274,73393,10001,73306,63823,73405, 9377,73405,17573,73405, 27533,73306, 9377,73413,63823,73413,27995,73413, 9377,73307,13755,73421, 27533,73421,10001,73421,63823,73307,65037,73429,10001,73429,27533,73429, 60857,73307,63697,73437,63779,73437,73397,73437,73401,73437,73371,73437, 73377,73437, 7,73437,63709,73437,35893,73437,37897,73437,38299,73437, 73379,73437,73403,73437, 1275,73437,63679,73465,73363,73465,73393,73465, 587,73307, 1971,73473, 3507,73473,73385,73473,73389,73473, 5231,73473, 73353,73473,73359,73473, 0,73473,21783,73473,23983,73473, 4625,73473, 10603,73473,73361,73473,73391,73473,21605,73473, 713,73503,73345,73503, 73381,73503, 1011,73306,18967,73511, 9617,73511, 1275,73306,72439,73517, 72447,73517, 3621,73517, 1991,73517, 1,73517,73473,73527,73489,73517, 60969,73517,62095,73517, 4907,73517,17711,73517,72457,73517,60857,73517, 1325,73543,72435,73543,21605,73306,23713,73549,23709,73549,26865,73549, 26715,73549, 6,73549,73437,73559,73451,73549,10159,73549,10111,73549, 26719,73549,10113,73549,67425,73549,70753,73549,70471,73549,23715,73549, 587,73549,26625,73581,10107,73581,23651,73581, 1011,73307, 9565,73589, 2,73306,36729,73593,68447,73593,67547,73593,70731,73593, 2,73307, 36727,73603,68451,73603,37895,73603,36079,73603,35575,73603, 15,73306, 21605,71229,26867,73616,26865,73619, 1179,73617, 1177,73623, 987,73617, 989,73627, 1177,73616, 1179,73631, 989,73616, 987,73635, 809,73616, 713,73639, 117,73616, 25,73643, 1489,73617, 1471,73647, 147,73617, 53,73651,26219,73617, 5,73616, 7,73657, 5,73658,73617,73661, 2,73658,73663,73665, 2,73657, 7,73668, 1368,73657, 3,73616, 7,73675, 3,73676,73617,73679, 4,73676,73681,73683, 4,73675, 7,73686, 16,73675, 10,73616, 7,73693, 2,73694, 2,73693, 7,73698, 1368,73693, 586,73616, 7,73705, 4,73706, 4,73705, 7,73710, 16,73705,44243,73617,48466,73617, 340,73617, 1397,73617, 53,73616, 713,73725, 305,73725, 25,73725, 147,73725, 1471,73616, 25,73735, 305,73735, 713,73735, 1489,73735, 25,73617, 117,73745, 253,73745, 1471,73745, 53,73745, 713,73617, 809,73755, 253,73755, 53,73755, 1471,73755, 253,73616, 305,73765, 25,73765, 713,73765, 305,73617, 253,73773, 1471,73773, 53,73773, 9,73617,46863,73780, 587,73617, 9381,73785, 9439,73785,73709,73785,73713,73785,25519,73785, 73683,73785,73689,73785, 5,73785, 9383,73785,62077,73785,64317,73785, 64815,73785,73691,73785,73715,73785, 17,73785, 9377,73815,73675,73815, 73705,73815, 11,73617, 7979,73823, 8067,73823,73697,73823,73701,73823, 73603,73823,73665,73823,73671,73823, 3,73823, 7981,73823,39747,73823, 43027,73823,43837,73823,73673,73823,73703,73823, 1369,73823, 7971,73853, 73657,73853,73693,73853, 17,73616,23709,73861,23713,73861,10159,73861, 10111,73861, 2,73861,73823,73871,73839,73861,26865,73861,26715,73861, 10113,73861,26719,73861,67425,73861,70471,73861,70753,73861,23715,73861, 587,73861,10107,73893,26625,73893,23651,73893, 1369,73616,72365,73901, 72373,73901, 9927,73901, 9891,73901, 4,73901,73785,73911,73801,73901, 9895,73901,19687,73901,20843,73901,21127,73901,72383,73901, 11,73901, 9875,73927,72361,73927,46863,73617, 9,73932, 6,73616,62905,73937, 68761,73937,70401,73937,67541,73937, 7,73616, 6,73617,62883,73949, 68767,73949,64267,73949,62235,73949,38881,73949,73437,73949,73947,73949, 72787,73949, 7,73617,25793,73967,41019,73967, 8495,73967,73937,73967, 72793,73967, 265,73966, 265,73617, 6,73981, 7,73981, 6,73980, 73985,73987, 7,73980,73983,73991, 903,71229,64148,73995,57522,73994, 58782,73994,58362,73994,52501,73995,52692,73994,46863,73994,56555,74008, 9,73994,56555,74012, 483,73994,56555,74016,49713,74016,49713,73994, 483,74022, 15,73995, 483,74027, 7,73994, 59,74031, 1325,74031, 331,74031, 7,73995,60857,74038,59875,74039, 375,74039, 9805,74039, 53391,74039,60857,73995, 6,74051, 7,74051, 6,74050,74055,74057, 7,74050,74053,74061,56555,73994, 7,74065,46863,74064, 483,74064, 9,74064,58742,71229, 7,74075, 9,74074,46863,74074, 483,74074, 56555,71229,43502,74085,21036,74085, 6,74089, 6,74088,43503,74085, 6,74095, 6,74094,21037,74085,59634,74085,59635,74085, 6,74105, 6,74104,21104,74085,59645,74085,43838,74085,21548,74085,21526,74085, 5,74118,59644,74085,19624,74085,18967,74085, 5,74126, 6,74128, 6,74129, 6,74126, 5,74134, 6,74127, 14,74126,38305,74085, 2,74142,59619,74085, 2,74146, 5,74085,59961,74151, 6,74151, 21526,74150, 6,74150,18967,74158,18967,74150, 6,74162, 6,74163, 2,74085,59619,74168,38305,74168, 14,74085,18967,74174,21527,74085, 74155,74179, 9,74179,19625,74085,21549,74085,43839,74085,21105,74085, 47640,74084, 922,74084, 918,74084, 1505,74084, 668,74084, 1419,74084, 483,74084, 903,74204, 11,74085, 9,74209, 15,74085,74139,74213, 46863,74084, 903,74216, 9,74084, 11,74221, 903,74220, 587,74220, 587,74084, 9,74228, 6,74084,74191,74233,74189,74233,74187,74233, 74113,74233,74087,74233,74101,74233,74103,74233,74171,74233,74169,74233, 59619,74251,74149,74233,72981,74233,74185,74233,74145,74233,74173,74233, 74213,74233,59381,74233, 7,74084,74093,74269,74099,74269,74123,74269, 74109,74269,74159,74269,74089,74269,74095,74269,74105,74269,74151,74269, 74111,74269,74115,74269,74117,74269,74157,74269,74121,74269,21105,74269, 21549,74269,65513,74269,65791,74269,65407,74269,74125,74269,19625,74269, 65171,74269,74175,74269,74131,74269,74129,74269,74137,74269,74177,74269, 74161,74269,74165,74269,74163,74269,74141,74269,59619,74269, 15,74269, 6,74085,21036,74336,74269,74339,43503,74336,74269,74343,59635,74336, 74269,74347, 5,74336,74269,74351,18967,74350,74269,74355,18967,74336, 5,74358,74269,74361, 7,74085,74091,74365,74097,74365,74107,74365, 74155,74365,21183,74365,65493,74365,74133,74365,74167,74365, 9,74365, 959,74365, 47,74365, 759,74365, 903,74084, 7,74391, 483,74390, 9,74390,46863,74390, 9,71229,20035,74400,58742,74400,58930,74400, 19917,74400, 903,74400,56555,74410, 265,74400, 8861,74415, 587,74400, 56555,74418,56555,74400, 11,74423, 903,74422, 587,74422, 265,74401, 8495,74431, 11,74431, 3,74400,70177,74437,70176,74436,74439,74441, 70176,74437,70177,74436,74445,74447, 1141,74437, 1447,74437, 33,74437, 11,74437,37409,74437, 3,74401, 113,74461, 11,74400,21522,71229, 7,74467,63452,71229, 7,74471,13673,71229, 7,74475,17049,71229, 3,74478,48643,74481, 2,74479, 3,74479,48637,74487,49581,74487, 47813,74487,21315,71229, 165,74494, 1011,74494, 7,74499,16163,71229, 2,74503,72683,74505,73087,74505,16171,74505, 375,74503,64669,71229, 7,74515, 265,74517,12377,71229, 256,74521,17455,74520, 7,74520, 375,74527, 7,74521, 241,74530, 331,74531,60857,74520, 7,74537, 241,74521, 7,74540,10385,71229, 375,74545,70899,71229, 7,74549, 18391,71229, 7,74553,18617,71229, 7,74557,12705,71229, 7,74561, 70573,71229,69275,74564, 7,74567, 3,71228,74332,74571,72750,74571, 71253,74571,72985,74571,72147,74571,71783,74571,71577,74571,67600,74571, 45491,74571,42800,74571,59710,74571,74365,74593,74269,74571,59619,74596, 72735,74571,59619,74600,59694,74571,60563,74571, 629,74571, 101,74571, 705,74571, 299,74571, 128,74571, 828,74571, 394,74571,48122,74571, 70327,74571,66930,74571, 9606,74571,10374,74571, 113,74571, 9,74632, 74465,74571,73153,74571,73031,74571,73057,74571,73131,74571,71939,74571, 72733,74571,74415,74571,72145,74571,59381,74653,42134,74571,10291,74571, 17,74658,51992,74571, 375,74571, 241,74664,65869,74664,49713,74664, 60796,74571,74213,74673, 256,74571, 803,74571, 483,74678, 483,74571, 803,74682,31103,74571,65869,74686, 6,74571,59619,74690,74365,74693, 56555,74690,74213,74697, 7,74571, 241,74700, 7,74570,57811,74705, 59933,74705,59743,74705, 9839,74705, 9579,74705,39619,74705,51421,74705, 4287,74705, 4303,74705, 8093,74705, 3837,74705,53487,74705,42113,74705, 42435,74705,53703,74705,42613,74571, 17,74736,46863,74571,12377,74740, 9,74571, 113,74744,49713,74571, 375,74748, 17,74571,42613,74752, 59619,74752,10291,74752, 9565,74752,41941,74752, 9565,74571, 7,74765, 17,74764,65869,74571,60796,74771,60797,74771,31103,74770,60797,74770, 74773,74779,60796,74770,74775,74783, 375,74770, 241,74571, 375,74788, 7,74788,56555,74571, 5,74795,74269,74797,72735,74797, 6,74797, 74365,74803, 6,74796,74269,74807,72735,74807, 14,74795,72735,74813, 74269,74813, 15,74795, 6,74795, 5,74820,74269,74823,72735,74823, 7,74795,74803,74829, 6,74794,74213,74833,74819,74833, 7,74794, 74807,74839,74823,74839,71229,74838,74807,74845,74823,74845,74797,74845, 74813,74845,74813,74839,12377,74571,46863,74856,41941,74571, 7,74861, 17,74860,59619,74571,74269,74866,72735,74866, 6,74866,74365,74873, 6,74867,74269,74877,72735,74877, 7,74867, 17,74866, 2,71228, 71233,74887,56555,74887,72129,74887,72127,74887,59619,74895,71235,74887, 72790,74887,71627,74887,74153,74887,74155,74887,74365,74906,74372,74887, 74158,74887,74269,74913,74279,74887,74350,74887,74269,74919,74353,74887, 74266,74887,74150,74887, 6,74927,74365,74929, 6,74926,74269,74933, 74269,74927,74287,74887,74336,74887, 5,74940,74269,74943,60261,74887, 71629,74887,63737,74887,37179,74887, 9535,74887,63743,74887, 9537,74887, 37185,74887,74264,74887,74174,74887,74269,74965,74315,74887,73073,74887, 37887,74887,37205,74887,37235,74887,74085,74887, 5,74978, 6,74981, 74365,74983, 6,74980,74269,74987,74269,74981, 6,74978, 5,74992, 74269,74995, 6,74979,74213,74999, 14,74978,74269,75003, 5,74887, 74336,75006,74269,75009,74085,75006, 6,75013,74365,75015, 6,75012, 74269,75019,74269,75013,74085,75007,74233,75025, 6,75006,72735,75029, 74085,75028,74269,75033,74269,75029,74085,75029,74233,75039, 7,75006, 71853,75043,72049,75043,72177,75043,73901,75043, 6,75007,74365,75053, 7,75007,72131,74887,72753,74887,74335,74887, 9563,74887,74382,74887, 10,74887,72177,75069,72049,75069,71853,75069,73901,75069, 14,74887, 74085,75079,74233,75081,74085,75078,74269,75085,72735,75079,74269,75079, 72191,74887,72069,74887,73927,74887,71881,74887,64759,74887,63763,74887, 63813,74887, 9559,74887,74213,74887,74233,75108,74365,74887,74155,75112, 9,75112,43123,74887,42606,74887,53318,74887, 9362,74887,27218,74887, 28189,74887,74233,74887,59381,75130,74213,75130,72789,74887,59381,75136, 64289,74887,26182,74887,28991,74887, 8804,74887,54289,74887,53802,74887, 8150,74887, 1290,74887,63679,75155, 9533,75155,37145,75155, 525,74887, 9533,75163,63679,75163,37145,75163, 922,74887, 1413,74887,73615,74887, 73127,74887,73009,74887,73035,74887,73081,74887,71943,74887,72729,74887, 73511,74887,41762,74887, 7971,74887, 9,75192,53517,74887, 9,75196, 483,74887, 903,75200, 9195,74887, 9,75204, 1275,74887, 17,75208, 9533,75211,37145,75211,63679,75211,27021,74887, 9,75218, 7,74887, 2,75223,60857,75225,71229,75227, 5,75222,71853,75231,72049,75231, 72177,75231,73901,75231,75229,75231, 2,75222,73616,75243,75231,75245, 21605,75243,71229,75248,75231,75251,71229,75243,21605,75254,75231,75257, 6,74887,74150,75260,74269,75263,74085,75260, 5,75266,74269,75269, 56555,75261,71229,75272,74085,75261,74155,75277, 9,75277, 5,75260, 72735,75283,74085,75282,74269,75287,74269,75283,74085,75283,74233,75293, 75275,75283, 11,75261,21604,75299,21604,75298,21605,75299,75303,75305, 21605,75298,75301,75309,52915,74887, 9,75312, 6,74886,23717,75317, 24522,75317,24447,75317,23939,75322,23939,75317,24447,75326,22956,75317, 23651,75331, 17,75317,21605,75335,24447,75337,21605,75334,23651,75341, 21605,75317, 17,75345,23939,75347, 17,75344,23651,75351, 7,74886, 27021,75355,24095,75355, 9195,75355,52915,75355,21605,75355, 9,75365, 67297,75355,26907,75355, 9755,75355, 9317,75355, 3833,75355,23651,75355, 51435,75355,27323,75355, 4321,75355,69729,75355,53215,75355, 4295,75355, 70097,75355,53941,75355,10171,75355, 5045,75355,11277,75355,42155,74887, 9,75402, 19,74887, 12,74887, 11,74887, 9,75410, 9,74887, 74365,75414,42155,75414,27021,75414,52915,75414, 9195,75414,25793,75414, 53517,75414, 7971,75414, 8495,75414,41019,75414, 11,75414, 17,74887, 1275,75438, 9533,75441,37145,75441,63679,75441, 8495,74887, 9,75448, 903,74887, 483,75452,21605,74887,26219,75457,42810,75456,75056,75456, 75057,75457,75463,75465,75053,75457,42810,75457,75057,75456,75056,75457, 75473,75475,42811,75456,75471,75479,42811,75457,75461,75483,44243,75457, 375,75457, 6,75457, 7,75457,25793,75493, 6,75456,75493,75497, 7,75456,75491,75501,41019,74887, 9,75504,59381,74887,72789,75508, 74233,75508,25793,74887, 9,75514,26625,74887, 6,75518, 7,75518, 6,75519,75523,75525, 7,75519,75521,75529, 9731,74887, 6,75532, 7,75532, 6,75533,75537,75539, 7,75533,75535,75543,69513,74887, 6,75546, 7,75546, 6,75547,75551,75553, 7,75547,75549,75557, 7,71228,73276,75561,27306,75561,73261,75561, 9,75566,24095,75561, 52603,75561,53910,75561,55537,75561,20053,75561,20831,75561,19783,75561, 64289,75561,27021,75561,25793,75586, 265,75587, 959,75561,60857,75593, 58775,75561, 5045,75561,11277,75561, 4551,75561,70136,75561,10196,75561, 273,75561, 1477,75561, 281,75561, 948,75561, 1516,75561, 922,75561, 1413,75561,52915,75561, 265,75623, 47,75561,60857,75627,25793,75561, 27021,75630, 9195,75561, 265,75635, 759,75561,60857,75639, 89,75561, 5019,75643,60857,75643, 1505,75561, 1011,75648, 587,75561,60857,75653, 70573,75653, 1369,75561,43503,75659, 483,75561, 903,75662, 165,75561, 903,75666, 1141,75561,18967,75671, 1447,75561,18967,75675, 2,75561, 61780,75679, 9,75679,60857,75682,54295,75679,70085,75679,53925,75679, 10155,75679,11529,75679,60857,75679, 9,75696, 3,75561,73221,75701, 9,75703, 8063,75701,53667,75701,42361,75701, 33,75561,18967,75713, 2,75560,27021,75717,24095,75717, 9195,75717,52915,75717,21605,75717, 9,75727,67297,75717,23651,75717,51435,75717,27323,75717, 4321,75717, 9755,75717,26907,75717, 9317,75717, 3833,75717,69729,75717,53941,75717, 10171,75717,70097,75717,53215,75717, 4295,75717, 5045,75717,11277,75717, 3,75560,57811,75765,59933,75765,59743,75765,39619,75765,51421,75765, 4287,75765, 4303,75765, 9839,75765, 9579,75765, 8093,75765, 3837,75765, 42113,75765,53487,75765,42435,75765,53703,75765, 265,75561,53813,75796, 69877,75796,10107,75796, 1011,75561, 1505,75804,54597,75805,21605,75561, 9,75811, 145,75811, 903,75561, 165,75816, 483,75816,54295,75817, 9,75561,73261,75824,69877,75561, 265,75828,10107,75561, 265,75832, 53813,75561, 265,75836, 6,71228,63091,75841,63099,75841,63117,75841, 25451,75841,53597,75841,42283,75841,61289,75841,61281,75841,62345,75841, 0,75841, 3,75860,71891,75863,72017,75863,72197,75863,73517,75863, 3,75861,62359,75841,60856,75841,72197,75877,72017,75877,71891,75877, 73517,75877,72211,75841,72037,75841,73543,75841,71919,75841,19739,75841, 61649,75841,61263,75841,61323,75841,20763,75841, 1011,75903, 1010,75902, 75905,75907, 1010,75903, 1011,75902,75911,75913,25380,75841, 7971,75917, 53517,75917,42155,75917,63015,75841,53517,75925, 7971,75925,42155,75925, 1369,75841,21605,75932,53517,75935,42155,75935, 7971,75935, 3,75841, 6,75943, 11,75945,71229,75947, 0,75942,71891,75951,72017,75951, 72197,75951,73517,75951,75949,75951, 6,75942,73306,75963,75951,75965, 17,75963,71229,75968,75951,75971,71229,75963, 17,75974,75951,75977, 2,75841,60857,75981, 16,75983, 16,75982, 17,75983,75987,75989, 17,75982,75985,75993, 2,75840,23717,75997,24522,75997,23939,75997, 24447,76002,24447,75997,23939,76006,22956,75997,23651,76011,21605,75997, 17,76015,23939,76017, 17,76014,23651,76021, 17,75997,21605,76025, 24447,76027,21605,76024,23651,76031,21605,75841, 1369,76034,53517,76037, 42155,76037, 7971,76037, 17,75841,37844,76044,75872,76044,75873,76045, 76049,76051,37844,76045,75873,76044,75872,76045,76057,76059,37845,76044, 76055,76063,37845,76045,76047,76067, 7,71229,74797,76071,74829,76073, 264,76071, 5,76071, 3,76078, 3,76079, 5,76070,75925,76085, 63014,76085,75841,76089,75917,76085,25381,76085,75841,76095,75935,76085, 76037,76085, 483,76085,60857,76102,75841,76105,60857,76085, 483,76108, 75841,76111,32805,76070,34655,76115,33773,76115,34447,76115,33221,76115, 32805,76071,34003,76125,33319,76125,34447,76071,35031,76131,65407,76071, 65335,76135,65076,76070,65513,76139,65791,76139,65407,76139,65171,76139, 65076,76071,65625,76149,65267,76149,20035,76070, 375,76155,74794,76071, 59381,76159,74819,76159,74571,76071,56555,76165,59619,76167,56555,76164, 59381,76171,12377,76070, 375,76175,49204,76071, 1369,76071, 241,76181, 56555,76071,74571,76184,59381,76187,59381,76185,74571,76191,49205,76071, 65869,76195, 1275,76071, 903,76199,60857,76070, 59,76203, 1325,76203, 331,76203, 265,76203, 903,76070, 59,76213, 1325,76213, 331,76213, 56555,76070,74877,76221,74866,76221,65513,76221,65791,76221,65407,76221, 74807,76221,74823,76221,74797,76221,21105,76221,75029,76221,75283,76221, 21549,76221,19625,76221,65171,76221,75079,76221,74813,76221,59619,76221, 74571,76254,74571,76221,59619,76258, 15,76221,74887,76263,21605,76070, 73949,76267, 265,76071,63823,76271,63679,76271,72619,76271, 9377,76271, 9533,76271,37145,76271, 2,76070,76077,76285,76081,76285,55839,76285, 54159,76285,54497,76285,51803,76285,73123,76285,76179,76285,65869,76301, 265,76285, 3,76070,76196,76307,67988,76307, 33,76307, 1447,76307, 1141,76307,76271,76307,76195,76307,65869,76320, 9,76307,46863,76307, 65869,76326,65869,76307,76195,76330,46863,76330, 2,76071,76310,76337, 76328,76337,76334,76337,76083,76337, 10,76337, 5,76337, 7,76348, 7,76337, 5,76352,55803,76337,54225,76337,54477,76337,51593,76337, 67988,76337,76307,76364,64345,76337,76324,76337,73121,76337,72713,76337, 76326,76337,65869,76376, 9,76337,76307,76380,60857,76337,71229,76385, 76347,76387,76351,76387,76355,76387, 903,76337,46863,76337,76330,76396, 65869,76396,76307,76400,76307,76396,65869,76404,76330,76337,46863,76408, 65869,76337,76326,76412,46863,76412,76307,76416,76307,76412,46863,76420, 76307,76337,67988,76424, 9,76424,46863,76424,65869,76430,65869,76424, 46863,76434, 3,76071, 5,76438,76285,76441, 113,76439,46863,76438, 76285,76447,65869,76449,76285,76439,67988,76453, 9,76453,46863,76453, 65869,76458,65869,76453,46863,76462, 15,76071,74485,76467,73261,76467, 46863,76071, 3,76472,76285,76475,65869,76477, 3,76473,76412,76481, 65869,76481,76337,76484,76337,76481,65869,76488,65869,76070, 375,76493, 70176,71229, 375,76497, 3,71229,70554,76500, 5,76501, 1,76505, 71229,76507, 2,76509,59961,76505,74887,76513, 6,76505,76511,76517, 73261,76517, 0,76500,75163,76523, 524,76523,74887,76527,75155,76523, 1291,76523,74887,76533,75211,76523,75441,76523, 483,76523, 11,76540, 74887,76543, 11,76523, 483,76546,74887,76549, 33,76501, 9,76553, 8147,76501,42315,76501,53777,76501,70555,76500,70176,76500, 9,76565, 43848,76501,70177,76501,76563,76571,76566,76571, 9,76571,76565,76576, 76565,76571, 9,76580, 1141,76501, 9,76585, 1447,76501, 9,76589, 69849,76500,68155,76593,17049,76500,48643,76597, 1369,76501, 803,76601, 15,76500,76337,76605,37409,76501, 9,76609, 9,76500,70177,76613, 76565,76615,70177,76612, 1141,76613, 1447,76613, 33,76613, 11,76613, 37409,76613, 11,76501, 9,76631, 6,76500, 7,76500, 33,76637, 1447,76637, 1141,76637,76271,76637, 6,76501,60856,76647, 0,76647, 3,76650, 3,76647, 0,76654, 11,76647,71229,76659,76649,76661, 76653,76661,76657,76661, 7,76501,43503,76668,70177,76500, 9,76672, 70176,76501,76619,76677,76503,76677,76675,76677,76673,76677, 9,76685, 43503,76501, 7,76688, 17,76689, 1011,76501, 375,76695, 7,76695, 18967,76501, 4,76700, 5,76700,76071,76705, 6,76704, 6,76705, 76070,76701,76709,76713,76705,76713, 14,76700,76713,76719,71229,76701, 7,76723,76711,76725, 7,76722,76709,76729,76705,76729,76719,76729, 15,76723,76071,76701,76703,76739, 15,76700,76739,76743, 6,76700, 5,76746,76729,76749,76713,76749, 7,76700,76707,76755,76711,76755, 6,76701,76743,76761,76737,76761, 7,76701,76749,76767,76709,76767, 71229,76766,76749,76773,76709,76773,76705,76773,76719,76773,76719,76767, 65869,76500,68155,76785,68109,76785, 256,76785, 7,76785, 241,76792, 241,76785, 7,76796,70572,71229,68155,76801,68109,76801, 256,76801, 7,76801, 241,76808, 241,76801, 7,76812, 2,71229, 0,76817, 4,76818, 0,76816, 2,76823, 5,76816,62284,76817,62186,76817, 64248,76817,62504,76817,64205,76817,61690,76817,52501,76817,70021,76817, 17496,76817,11179,76817,10187,76817,53967,76817,17455,76817, 9,76852, 16065,76817, 16,76857, 16,76856, 17,76857,76861,76863, 17,76856, 76859,76867,70802,76817, 340,76817,60857,76872,64148,76817, 265,76876, 9,76817,17455,76880, 375,76817,60857,76884, 587,76817, 17,76889, 37145,76891, 9533,76891,76523,76891,76821,76891,63679,76891,44243,76817, 60857,76902,49713,76903, 17,76816,36729,76909,68447,76909,67547,76909, 70731,76909,49713,76816,44243,76919,54295,76817, 9,76923, 6,76816, 66737,76927,36661,76927,62741,76927,68381,76927,68727,76927, 7,76816, 54497,76939,55839,76939,54159,76939,51803,76939,73123,76939, 265,76939, 7,76817,62494,76952,70573,76952, 265,76952,60857,76958,60857,76952, 265,76962, 265,76953,60857,76967,62494,76817, 7,76970,43215,76817, 9,76975, 265,76817,64148,76978, 483,76979, 7,76978,60857,76984, 60857,76978, 7,76988,60857,76817,42810,76993,42810,76992,42811,76993, 76997,76999, 375,76992, 340,76992,42811,76992,76995,77007,44243,76992, 6,76992, 7,76992, 265,77014, 6,76993,77015,77019, 7,76993, 77013,77023, 265,76993, 7,77027, 265,76992, 7,77030,65869,76817, 69275,77035, 7,77037,70573,76817, 6,77041, 7,77041, 6,77040, 77045,77047, 7,77040,77043,77051,65869,76816,69716,77055, 7,77055, 69513,77058,69513,77055, 7,77062,70922,71229,69716,77067, 7,77067, 69513,77070,69513,77067, 7,77074, 6,71229,74890,77079,59619,77081, 38056,77078, 5,77084,76825,77079,76827,77089,55814,77078,55815,77079, 77093,77095,55815,77078,55814,77079,77099,77101, 1346,77078, 1346,77079, 1347,77078,77107,77109,17126,77079,17125,77079, 2,77114,17127,77079, 9565,77119,74169,77079,59619,77123,60621,77079,59619,77127,38056,77079, 38057,77078,44195,77133,58303,77079, 1010,77079, 1010,77078,77119,77141, 35187,77079, 2,77144, 0,77079, 4,77149, 2,77151,71229,77152, 71229,77151, 2,77156, 2,77157,76816,77151, 1011,77149,71229,77165, 5,77079, 1,77168, 5,77078,38056,77173,77133,77175, 2,77172, 58302,77079,77141,77181, 9565,77181,59619,77181,20501,77079, 1011,77189, 1010,77188,77191,77193, 1010,77189, 1011,77188,77197,77199, 567,77079, 21604,77203,21604,77202,21605,77203,77207,77209,21605,77202,77205,77213, 1347,77079,77105,77217,74887,77079,56555,77220,59619,77223,56555,77221, 59381,77227, 9875,77079, 1011,77231, 1010,77230,77233,77235, 1010,77231, 1011,77230,77239,77241,56555,77079,74887,77244,59619,77247,59619,77245, 74887,77251, 1011,77244, 9565,77255,77141,77255,59619,77255, 1011,77245, 9617,77263,77139,77263,74887,77263, 587,77079,21605,77271,42155,77273, 53517,77273,76085,77273,77171,77273, 7971,77273, 1011,77078,77113,77285, 77117,77285,74505,77285,77131,77285,77137,77285,77147,77285,73261,77285, 38057,77079,77179,77301,77087,77301,41941,77301,76827,77301, 9565,77301, 59619,77301,77141,77301,56555,77078,72981,77317,75508,77317,74887,77317, 59381,77322,59381,77317,74887,77326,21605,77078,62905,77331,68761,77331, 67541,77331,70401,77331,73967,77331, 1011,77079,56555,77343,59381,77345, 56555,77342,59619,77349,77141,77349, 9565,77349, 2,77078,66737,77357, 5,77356,77301,77361,62741,77357,36661,77357,68727,77357,68381,77357, 3,77078,77161,77373, 2,77079,17125,77376,77285,77379,35187,77376, 77285,77383, 3,77079,77155,77387,77159,77387,77163,77387,77167,77387, 11,77079,37844,77397,37844,77396,37845,77397,77401,77403,37845,77396, 77399,77407,65869,71229, 1530,77410, 842,77410,48535,77410, 669,77410, 1419,77410,49514,77410, 136,77410,49515,77410, 137,77410, 843,77411, 77415,77431, 1531,77411,77413,77435, 843,77410, 1530,77411, 1531,77410, 77441,77443, 842,77411,77439,77447, 1418,77410,48534,77410, 668,77410, 587,77410,46863,77456, 9,77456, 1369,77410, 15,77462, 9,77410, 2,77467, 2,77466, 587,77466, 265,77410, 375,77475, 15,77410, 1369,77478,46863,77410, 2,77483, 2,77482, 587,77482, 7,77411, 59,77491, 1325,77491, 331,77491, 265,77491, 6,77410,77491,77501, 2,77503, 3,77503, 2,77502,77507,77509, 3,77502,77505,77513, 3,77411,67577,77517,77425,77517,77423,77517,68139,77517,70979,77517, 77455,77517,77453,77517,77421,77517,77471,77517,77487,77517,77461,77517, 77459,77517,77473,77517,77489,77517, 7,77517, 1011,77517, 7,77549, 2,77410, 9,77552,77517,77555,46863,77552,77517,77559,69716,77553, 77546,77553, 7,77553,69513,77566,77517,77566,69513,77553, 7,77572, 77517,77553, 6,77577, 7,77577, 6,77576,77581,77583, 7,77576, 77579,77587, 2,77411,76517,77591,29229,77591,72789,77591,77429,77591, 77427,77591,72683,77591,74233,77591,77317,77591,77451,77591,77419,77591, 77417,77591,77285,77591,73087,77591,77465,77591,77481,77591, 7,77591, 70573,77591, 7,77625, 3,77410, 4,77628,77591,77631, 1,77628, 5,77628, 0,77628,77591,77639, 5,77629, 6,77643,77591,77645, 68155,77629,77469,77629,77485,77629,68109,77629,77623,77629,77631,77657, 77639,77657, 256,77629,77622,77629,77635,77665,77637,77665, 6,77629, 77632,77671,77640,77671,77631,77671,77591,77676,77639,77671,77591,77680, 77591,77671,77631,77684,77639,77684, 7,77629,77635,77691,77591,77693, 77637,77691,77591,77697, 241,77690,77591,77690,77635,77703,77637,77703, 241,77629, 7,77708,77591,77629, 6,77713, 7,77713, 6,77712, 77717,77719, 7,77712,77635,77723,77637,77723,77715,77723, 6,77411, 7,77410, 375,77733,77731,77733, 2,77737, 3,77737, 2,77736, 77741,77743, 3,77736,77739,77747, 1, 6,18363,77751, 4389,77751, 18362,77751, 4388,77751,70572,77750,70667,77761,70849,77761,70803,77761, 56555,77767,70883,77761, 272,77751, 8997,77773, 4425,77773, 8452,77751, 251,77779, 8841,77779, 8453,77751, 273,77751, 4139,77751, 8429,77751, 4138,77751, 8428,77751,70879,77751,70797,77797,18257,77751, 465,77801, 445,77751,17827,77805, 4371,77751, 265,77808,18339,77751, 265,77812, 64953,77751, 375,77817,14888,77751, 375,77821,13569,77751, 375,77825, 4137,77751, 265,77828, 8401,77751, 265,77832, 413,77750,77835,77837, 77831,77837,77795,77837,77793,77837,77815,77837,77811,77837,77757,77837, 77759,77837, 241,77837, 1217,77750, 412,77750, 8401,77859, 4137,77859, 18339,77859, 4371,77859,77791,77859,77789,77859,77753,77859,77755,77859, 1216,77750,40461,77751, 9,77879,59573,77751, 375,77883,69467,77751, 375,77887, 7047,77751, 412,77891, 413,77890,77893,77895, 413,77891, 412,77890,77899,77901,12615,77751, 375,77905,45880,77751,46275,77909, 33390,77751,34003,77913,77462,77751,77591,77917,65232,77751,65625,77921, 923,77751,16481,77925,16783,77925,18797,77925,25367,77751, 9,77933, 68975,77751, 375,77937,62984,77751, 9,77941, 1412,77751,17827,77945, 412,77751,77837,77949, 1216,77751, 9137,77751, 375,77955, 253,77751, 9136,77959, 9137,77959,17826,77959, 1,77959, 413,77966,17827,77959, 413,77959, 1,77972, 265,77958, 8997,77977, 4425,77977,77963,77977, 77965,77977,77969,77977,77975,77977, 265,77959, 8997,77990, 8997,77959, 265,77994, 265,77995,12377,77959, 8337,77751, 266,78003, 267,78003, 464,78003, 6,78003, 413,78010, 465,78003, 413,78003, 6,78016, 265,78002, 251,78021, 8841,78021,78007,78021,78009,78021,78013,78021, 78019,78021, 265,78003, 251,78034, 251,78003, 265,78038, 265,78039, 375,78003,38057,77751, 265,77751,18339,78048,77837,78051, 4371,78048, 77837,78055, 253,78048, 8997,78059, 4425,78059, 8337,78048, 251,78065, 8841,78065,77837,78049, 8401,78071, 4137,78071,18339,78071, 4371,78071, 4137,78048,77837,78081, 8401,78048,77837,78085, 241,78049, 8401,78089, 4137,78089, 1369,78048,17827,78095, 241,78048, 1011,77751,56555,78101, 60369,78103, 241,77751, 413,78107,14315,78106, 375,78111,57522,78107, 67028,78107, 265,78107,60857,78106, 9,78121,56555,78107, 9,78124, 65869,78107, 483,78128, 483,78107,65869,78132, 9,78107,56555,78136, 265,78106, 8685,77751, 375,78143, 264,77750,78066,78147,78060,78147, 78091,78147,78093,78147,18339,78147, 4371,78147,17911,78147,13433,78147, 13411,78147,13635,78147,77978,78147,78022,78147,77999,78147,78043,78147, 77774,78147,77780,78147,64733,78147,64955,78147,78021,78147, 251,78184, 77977,78147, 8997,78188,78065,78147, 251,78192,78059,78147, 8997,78196, 77779,78147, 251,78200,77773,78147, 8997,78204, 9139,78147, 9123,78147, 9065,78147,14935,78147,64919,78147,59463,78147,69357,78147,59533,78147, 69427,78147,59587,78147,69481,78147,78088,78147, 8401,78231, 4137,78231, 8997,78147,78059,78236,77977,78236,77773,78236, 251,78147,78065,78244, 78021,78244,77779,78244,27979,78147,26293,78147,41503,78147, 8685,78147, 78141,78147,77949,78147,78099,78147,78049,78147, 8337,78267, 251,78269, 253,78267, 8997,78273, 241,78266, 8401,78277, 4137,78277, 241,78267, 1369,78147, 241,78147, 6,78287,78065,78289,78021,78289,77779,78289, 1,78287,78059,78297,77977,78297,77773,78297,78049,78286, 8401,78305, 4137,78305,16381,78147,19513,78147,35843,78147,13325,78147,70407,78147, 69063,78147,67565,78147, 341,78147,64669,78325, 8997,78325,59381,78325, 69275,78325,65869,78325, 241,78325, 471,78147, 367,78147, 357,78147, 8401,78147, 4137,78147,37019,78147, 4063,78147,20219,78147, 3863,78147, 20697,78147,37377,78147, 9955,78147,10273,78147,14625,78147, 4569,78147, 265,77750,77785,78369, 251,78371,77787,78369, 8997,78375, 253,78369, 8997,78379, 8337,78369, 251,78383, 241,78368, 8401,78387, 4137,78387, 77791,78387,77789,78387, 241,78369, 241,77750, 8428,78399,78147,78401, 4138,78399,78147,78405, 4137,78399, 265,78409, 265,78408,78147,78413, 8401,78399, 265,78417, 265,78416,78147,78421, 265,78398, 8401,78425, 4137,78425,77791,78425,77789,78425, 265,78399, 8401,78434,78147,78437, 4137,78434,78147,78441,78147,78435, 8401,78445, 4137,78445, 240,77751, 265,78451, 1010,77751,28337,78455, 264,77751,78426,78459,78428,78459, 78419,78459,78411,78459,78388,78459,78390,78459,77860,78459,77862,78459, 77864,78459,77866,78459,18339,78459,77859,78480, 4371,78459,77859,78484, 78381,78459,78385,78459,13381,78459,77961,78459,78005,78459,77993,78459, 78037,78459,77997,78459,78041,78459,78015,78459,77971,78459,77807,78459, 77803,78459,64746,78459,78382,78459, 251,78517,78378,78459, 8997,78521, 78035,78459, 251,78525,77991,78459, 8997,78529, 9072,78459, 9105,78459, 59470,78459,69364,78459,59521,78459,69415,78459,64931,78459, 413,78459, 77859,78459, 8401,78548, 4137,78548,18339,78548, 4371,78548,78425,78459, 8401,78558, 4137,78558,78387,78459, 8401,78564, 4137,78564, 8401,78459, 78425,78570,78387,78570,77859,78570, 4137,78459,78425,78578,78387,78578, 77859,78578, 8337,78459,78369,78586, 251,78589, 253,78459,78369,78592, 8997,78595,78396,78459,78119,78459,78369,78459, 8337,78602, 251,78605, 253,78602, 8997,78609, 241,78603, 8401,78613, 4137,78613, 241,78602, 69275,78459, 375,78620,59381,78459, 375,78624, 8997,78459, 375,78628, 64669,78459, 375,78632,70327,78459,65869,78459, 375,78638,66930,78459, 375,78459,64669,78644, 8997,78644,59381,78644,69275,78644,65869,78644, 241,78644, 241,78459,78369,78658, 375,78658, 394,78459, 299,78459, 1217,77751, 413,77751,77859,78671,78369,78671, 375,78671,14315,77751, 241,78678, 375,78681, 375,78679, 341,77751,12377,78687, 257,77751, 375,78691,70572,77751,70693,78695,70800,78695,70797,78695,56555,78700, 56555,78695,70797,78704, 1346,77751, 9,78709, 1061,77751, 9,78713, 525,77751, 9,78717,64396,77751, 9,78721,38056,77751,29229,78725, 9,78725, 137,77751,56555,78731, 5,78733, 4,78732,78735,78737, 4,78733, 5,78732,78741,78743,20103,77751, 375,78747, 1471,77751, 12377,78751,36773,77751, 375,78755, 53,77751,12377,78759,45639,77751, 1369,78762,46275,78765,32805,77751, 17,78768,34003,78771,77410,77751, 1369,78774,77591,78777,65076,77751, 17,78780,65625,78783, 1275,77751, 5,78786, 9,78789, 5,78787, 17,78793,35187,77751, 1196,78797, 6,78797, 1011,78800, 137,78797, 136,78797, 1197,78797, 1413,78797, 922,78797, 1011,78797, 6,78814, 903,78797, 483,78818, 483,78797, 903,78822, 2,78796,78805,78827,29229,78827,78799,78827,78817,78827, 78803,78827, 9,78827, 3,78796,78807,78841,78809,78841, 2,78797, 78841,78847, 9,78849, 9,78846,78841,78853, 3,78797, 5,78857, 6,78859,78827,78861,78838,78857, 9,78857,78827,78866,78827,78857, 9,78870, 9,78797, 2,78875,78857,78877, 3,78875, 2,78874, 78841,78883, 3,78874, 17,77751,65076,78889,65407,78891,32805,78889, 34447,78895,20035,78889,58742,78889,65076,78888,65625,78903,32805,78888, 34003,78907, 903,78889,56555,78910,56555,78889, 903,78914,65869,78889, 2,78919, 3,78919, 2,78918, 3,78918,18967,77751, 295,78929, 1108,78929, 1011,78929, 9,78934, 9,78929, 1011,78938, 483,78929, 18967,78943, 5,78944, 5,78945,21036,78943,21037,78943, 4,78943, 78949,78955, 5,78943,18967,78958, 4,78942,78961,78963,78947,78963, 78951,78963, 5,78942,78953,78971, 1369,77751,12376,78974,12376,78975, 12377,78974,78979,78981,77410,78975,77517,78985,45639,78975,46599,78989, 12377,78975,78977,78993,36527,78975,68806,78975,77410,78974,77591,79001, 45639,78974,46275,79005, 1011,78975,65869,79008,65869,78975, 1011,79012, 265,78974,17827,79017,56555,78975, 4,79021, 5,79021, 4,79020, 5,79020,60857,77751, 241,79030, 9,79033, 5,79030, 9,79037, 5,79031, 17,79041,70177,77751,38056,79045,38056,79044,38057,79045, 79049,79051,38057,79044,79047,79055, 375,79045,27979,77751, 375,79061, 2,77750,68283,79065,68275,79065,36633,79065,36627,79065,39987,79065, 66423,79065,66883,79065,66405,79065,66397,79065,67687,79065,78047,79065, 9,79087,36544,79065, 9875,79091,20501,79091,68177,79065, 9875,79097, 20501,79097,64396,79065, 9,79103, 5,79065,60857,79106, 9,79109, 35187,79065, 11,79112,20501,79115, 9875,79115, 11,79065,35187,79120, 9875,79123,20501,79123,60857,79065, 5,79129, 17,79131, 5,79128, 9,79135, 3,77750,40779,79139,63907,79139,73421,79139,73429,79139, 64235,79139,67465,79139,63955,79139,39027,79139,38685,79139,64073,79139, 6,79139, 4,79161,78728,79139,78838,79139,78827,79139, 9,79168, 78725,79139, 9,79172, 9934,79139,20644,79139, 4663,79139, 903,79181, 17219,79139, 903,79185,12345,79139, 5,79189, 4,79188,79191,79193, 4,79189, 5,79188,79197,79199, 5123,79139, 5,79203, 4,79202, 79205,79207, 4,79203, 5,79202,79211,79213,19667,79139, 5,79217, 4,79216,79219,79221, 4,79217, 5,79216,79225,79227,73306,79139, 9377,79231,63823,79231,40705,79139, 9377,79237,63823,79237,21036,79139, 70177,79139, 9,79245, 341,79139,64669,79249,65869,79249, 253,79139, 65869,79255, 8337,79139, 9,79259, 241,79139, 1471,79139,65869,79265, 37325,79139, 903,79269,20103,79139, 9,79273,10219,79139, 903,79277, 4,79139,20501,79280, 9875,79280, 5,79139, 6,79287,78827,79289, 78725,79289,18967,79286, 9935,79287,20645,79287,36773,79139, 9,79301, 53,79139,65869,79305, 5,79138,27979,79309, 8685,79309,41503,79309, 26293,79309, 1369,79309,16381,79309,13325,79309,35843,79309,19513,79309, 8401,79309, 4137,79309,14625,79309, 4569,79309,37019,79309, 4063,79309, 3863,79309,37377,79309,20219,79309,10273,79309, 9955,79309,20697,79309, 9,79139,78725,79352,78827,79352,35187,79139, 1505,79359, 17,79139, 71229,79362, 9377,79365,63823,79365,21315,79363,71229,79139, 17,79372, 63823,79375, 9377,79375,18967,79139,20413,79381, 4,79383, 4,79382, 20487,79381,20486,79381,79161,79381, 4,79393, 4,79392,79163,79381, 580,79381,49630,79381,79162,79381,46863,79381, 4,79406, 4,79407, 483,79381, 4,79412, 4,79413,49631,79381, 581,79381, 4,79381, 20413,79422,79161,79422,46863,79422, 483,79422, 5,79381,79385,79433, 79179,79433,79283,79433,79395,79433,79411,79433,79417,79433,20413,79433, 4,79380,79389,79449,79446,79449,79421,79449,79419,79449,79399,79449, 79433,79449,20413,79460,20413,79449,79433,79464, 5,79380,79425,79469, 79387,79469,79391,79469,79427,79469,79397,79469,79401,79469,79403,79469, 79405,79469,79429,79469,79409,79469,79431,79469,79415,79469,79423,79469, 20413,79495, 1369,79139, 5,79499,27979,79139,65869,79503, 9,79503, 20501,79139, 4,79508,79433,79511, 5,79508,18967,79514,21037,79508, 4,79509,79517,79521,79243,79521,79295,79521,79469,79521, 5,79509, 79519,79531, 9875,79139, 4,79534, 5,79534, 4,79535, 5,79535, 4,77750, 3,79545, 5,77750,10256,79549,37356,79549, 4745,79549, 1011,79555,17423,79549, 1011,79559,63550,79549,64489,79549,63493,79549, 17,79566,70803,79549,56555,79571,74752,79549, 8982,79549,74571,79549, 17,79578, 8861,79549, 17,79582,37844,79549,27979,79549, 483,79589, 253,79549,56555,79593, 8337,79549, 483,79597, 241,79549, 1325,79549, 17,79602, 331,79549, 17,79606, 1328,79549, 334,79549, 53,79549, 56555,79615,20501,79549, 1011,79619,36773,79549, 483,79623, 9875,79549, 1011,79627, 1359,79549, 393,79549, 2,79549,37325,79634,10219,79634, 3,79549, 483,79641,35187,79640,10257,79641,37357,79641, 62,79549, 59,79549, 17,79652,20103,79549, 483,79657, 1471,79549,56555,79661, 3,79548,27979,79665, 8685,79665,26293,79665,41503,79665, 1369,79665, 16381,79665,13325,79665,19513,79665,35843,79665, 8401,79665, 4137,79665, 14625,79665, 4569,79665,20219,79665, 3863,79665, 4063,79665,20697,79665, 37019,79665, 9955,79665,10273,79665,37377,79665,18967,79549, 165,79709, 1369,79549,38057,79713,35187,79549, 3,79717, 3,79716, 17,79549, 63493,79722,74571,79722, 8861,79722, 1325,79722, 331,79722, 59,79722, 37325,79549, 2,79736, 3,79736, 2,79737, 3,79737,10219,79549, 2,79746, 3,79746, 2,79747, 3,79747, 5,77751, 1196,79756, 1196,79757, 1197,79756,79761,79763,21604,79757, 6,79757, 587,79769, 21605,79771, 1,79757, 3,79774, 3,79775,18967,79775, 483,79781, 1,79756,25381,79785,63014,79785,79773,79785,60857,79785, 483,79792, 483,79785,60857,79796, 6,79756,79787,79801,63015,79801,79785,79805, 25380,79801,79785,79809,79789,79801,79783,79801,79799,79801, 1369,79801, 21605,79818,79785,79821,79795,79801,21605,79801, 1369,79826,79785,79829, 1216,79757, 413,79757, 1197,79757,79759,79837,79546,79757, 903,79757, 20735,79757, 9993,79757, 1275,79756, 9,79849,60857,79756, 9,79853, 56555,79757, 1505,79856,21605,79757,21376,79757, 483,79757,21315,79864, 58112,79757,21315,79757, 483,79870, 1505,79757,56555,79874, 2,79756, 79767,79879, 7,79881, 6,79880,79883,79885, 6,79881, 7,79880, 79889,79891,79777,79879, 7,79895, 6,79894,79897,79899, 6,79895, 7,79894,79903,79905,28337,79879, 3,79756,79861,79911, 7,79913, 6,79912,79915,79917, 6,79913, 7,79912,79921,79923, 2,79757, 79779,79927, 7,79929, 6,79928,79931,79933, 6,79929, 7,79928, 79937,79939, 3,79757, 1,79942,79879,79945, 7,79947, 6,79946, 79949,79951, 6,79947, 7,79946,79955,79957,79545,79942,79545,79757, 2,79963, 3,79963, 2,79962, 3,79962, 9,79757,63493,79973, 74571,79973, 8861,79973, 1325,79973, 331,79973, 59,79973, 3,77751, 79112,79987, 9,79989,78847,79987, 9,79993, 1216,79987,12371,79987, 5,79999, 4,79998,80001,80003, 4,79999, 5,79998,80007,80009, 413,79987, 375,79987,60454,79987,60369,80017, 566,79987,35187,79987, 79065,80022, 9,80025,79106,79987, 1011,79987,37407,79987,10287,79987, 65869,79987, 165,80036,38132,79987, 9,79987,38057,80042,67642,79987, 38057,79987, 9,80048, 165,79987,65869,80052, 5,79986, 4,79987, 5,79987,79065,80060,56555,80060,60369,80065, 483,80060,79065,79987, 35187,80070, 9,80073, 4,80071, 5,80071, 4,80070, 5,80070, 56555,79987,49630,80084,46863,80084, 4,80089, 4,80088, 581,80084, 580,80084,49631,80084, 4,80084,46863,80100, 483,80100, 5,80084, 60369,80107,80091,80107, 4,80085,80095,80113,80099,80113, 5,80085, 60327,80119,60719,80119,80097,80119,80087,80119,57901,80119,80093,80119, 80103,80119,80105,80119, 483,80084, 4,80136,80119,80139, 4,80137, 80107,80143, 483,79987, 5,80146, 2,77751,79538,80151,79541,80153, 79514,80151,79521,80157,79024,80151,79027,80161,78958,80151,78963,80165, 79021,80151, 5,80168,79027,80171, 5,80169,79023,80175,78943,80151, 5,80178,78963,80181, 5,80179,78955,80185, 1,80151, 7,80189, 4,80191, 4,80190, 16,80189, 4,80189, 7,80198,28714,80151, 17,80203,79286,80151,79541,80207,79521,80207,35187,80150,79289,80213, 29229,80213,79352,80213, 9,80213,79139,80220,79139,80213, 9,80224, 9,80151, 4,80150, 265,80231, 5,80150,80193,80235,28337,80235, 4,80151, 1011,80241, 5,80151,80195,80245,80201,80245,79534,80245, 79543,80251,79508,80245,79531,80255,79021,80244,79027,80259,78943,80244, 78963,80263,79021,80245,79029,80267,78943,80245,78971,80271,80197,80245, 28219,80245,30475,80245,23939,80245,79139,80244,79541,80283,79521,80283, 21605,80244, 17,80289,79139,80151,35187,80293, 9,80295, 4,80293, 5,80293,79537,80301,79511,80301,79177,80301,79179,80301,79285,80301, 79283,80301, 4,80292,80301,80315, 5,80292,79541,80319,79521,80319, 80299,80319,21605,80151, 5,80326, 17,80329, 5,80327, 9,80333, 4,77751,79750,80337,79753,80339,79740,80337,79743,80343,78922,80337, 78925,80347,78880,80337,78883,80351,78919,80337, 3,80354,78925,80357, 3,80355,78921,80361,78875,80337, 3,80364,78883,80367, 3,80365, 78877,80371, 6,80337, 1369,80375,56555,80377, 1,80337,60857,80381, 1275,80383, 1,80336,58931,80387,19916,80387,80379,80387,18967,80387, 1275,80394, 1275,80387,18967,80398, 6,80336,19917,80403,80387,80405, 80389,80403,80391,80403,58930,80403,80387,80413,80385,80403,80401,80403, 587,80403,56555,80420,80387,80423,80397,80403,56555,80403, 587,80428, 80387,80431,43214,80337,79640,80337,79753,80437,79743,80437, 2,80336, 265,80443, 2,80337, 903,80447, 3,80337,67988,80450,67988,80451, 67989,80450,80455,80457,79746,80451,79755,80461,79736,80451,79745,80465, 78919,80450,78925,80469,78875,80450,78883,80473,78919,80451,78927,80477, 78875,80451,78887,80481,67989,80451,80453,80485,79549,80450,79753,80489, 79743,80489,38305,80450,79549,80337, 2,80497, 3,80497,79749,80501, 79739,80501,79551,80501,79553,80501,79639,80501,79637,80501, 2,80496, 80501,80515, 3,80496,79753,80519,79743,80519,80499,80519,38305,80337, 3,80526, 3,80527, 0, 7, 1517,80532, 2575,80535, 949,80532, 2599,80539, 1476,80532, 2269,80543, 280,80532, 2289,80547, 272,80532, 4437,80551, 121,80532,38343,80555, 3075,80555, 1913,80555, 76,80532, 3005,80563, 1899,80563,38337,80563, 123,80533, 3061,80571, 81,80533, 2997,80575, 367,80532, 7627,80579, 357,80532, 1927,80583, 397,80532, 7895,80587, 1516,80532, 948,80532, 107,80532, 2221,80595, 203,80532, 2215,80599, 215,80532, 4339,80603, 91,80532, 5045,80607, 1477,80532, 281,80532, 273,80532, 317,80532,14469,80617, 67,80532,11087,80621, 4643,80621, 2233,80621, 4625,80621, 9,80629, 53,80532, 2289,80633, 1471,80532, 2269,80637,80012,80533,77949,80641,79834,80533,77949,80645, 79996,80533,78669,80649,79832,80533,78669,80653,78546,80533,77949,80657, 78108,80533,78141,80661,77949,80661,77855,80533,77949,80667, 416,80533, 17993,80671, 418,80533,17993,80675, 447,80533,17993,80679, 295,80532, 294,80532, 76,80533,38587,80687,26285,80533,26390,80533,26106,80533, 121,80533,38585,80697,26502,80533,32269,80533,31761,80533,32563,80533, 31921,80533,31591,80533,78287,80533,78141,80713,78099,80713,77949,80713, 23788,80533,27830,80533,27947,80533,41746,80533,26216,80533,41414,80533, 26126,80533,41348,80533,26328,80533,41556,80533,29029,80533,43319,80533, 203,80533, 2211,80745,60857,80745, 85,80533, 4593,80751, 2229,80751, 60857,80751,80229,80533,39823,80533,23013,80533,39229,80533,39783,80533, 38673,80533,38675,80533, 107,80533, 5019,80773, 2219,80773,60857,80773, 80228,80533,40956,80533,45411,80783,37899,80783,41493,80533, 1517,80533, 2573,80791,80591,80791, 949,80533, 2593,80797,80593,80797, 280,80533, 2287,80803,80613,80803, 1476,80533, 2267,80809,80611,80809, 272,80533, 4457,80815,80615,80815, 8673,80533, 8681,80533, 8800,80533, 8742,80533, 41622,80533, 8740,80533, 8610,80533, 8642,80533, 8638,80533,39650,80533, 42752,80533, 8717,80533, 413,80843, 1369,80842, 341,80842, 3785,80533, 413,80851, 1369,80850, 341,80850, 413,80532, 8717,80859, 3785,80859, 13443,80859, 7627,80859, 7287,80859, 7895,80859,12755,80859, 1689,80859, 2701,80859, 1705,80859,77859,80859,78459,80880,78548,80859,78048,80859, 77837,80887,78071,80859,18454,80859,78147,80859,78459,80859,77859,80896, 265,80859,77751,80900,77837,80903,77751,80901,77859,80907,18391,80859, 331,80910, 331,80859,18391,80914, 8495,80859,77751,80859, 265,80920, 77837,80923,12745,80859, 375,80927, 457,80927, 375,80859,13977,80533, 80021,80533,13767,80533, 4347,80533, 2213,80533, 2225,80533, 2231,80533, 10079,80533,79501,80533,18715,80533,18579,80533,14313,80533,80149,80533, 13945,80533, 4987,80533,14091,80533, 4619,80533,80069,80533,13913,80533, 4555,80533,16635,80533,16301,80533, 2575,80533, 2599,80533, 2289,80533, 2269,80533, 4437,80533, 7549,80533, 7589,80533,13785,80533,80015,80533, 23755,80533, 1369,80996,39633,80533, 1369,81000,78284,80533, 7205,80533, 2561,80533, 2261,80533, 4423,80533, 2307,80533,79318,80533,10058,80533, 79674,80533,26331,80533, 1369,81022,41559,80533, 1369,81026, 4329,80533, 1369,81030, 4311,80533, 1369,81034,10354,80533, 3786,80533, 4330,80533, 27805,80533, 1369,81044,42731,80533, 1369,81048,10055,80533, 1369,81052, 10351,80533, 1369,81056, 4312,80533,78645,80533,78324,80533,78458,80533, 375,81067, 3794,80533,78147,80533, 413,81073, 1369,81072, 341,81072, 215,80533, 4345,81081,60857,81081,79309,80533, 1369,81086,79665,80533, 1369,81090, 1477,80533,80543,81095, 281,80533,80547,81099, 1516,80533, 80535,81103, 948,80533,80539,81107,13443,80533,16669,80533,43293,80533, 26104,80533,41314,80533,26277,80533,41479,80533,13027,80533, 264,81124, 264,81125, 413,81125, 265,81124,81129,81133, 265,81125,81127,81137, 5127,80533, 264,81140, 264,81141, 413,81141, 265,81140,81145,81149, 265,81141,81143,81153,15309,80533, 412,81157, 413,81156,81159,81161, 413,81157, 412,81156,81165,81167,32294,80533,45314,80533,31857,80533, 44925,80533,14053,80533,22897,80533,39143,80533,78107,80533, 413,81184, 78141,81187,77949,81187, 413,81185,77859,81193, 1276,80533,17993,81197, 438,80533,17993,81201, 1278,80533,18759,81205, 1242,80533,18759,81209, 22806,80533, 903,81213, 9,81213,39084,80533, 483,81219,39204,80533, 41941,81223,22956,80533,26625,81227, 1109,80533,35187,81231, 294,80533, 80683,81235,35187,81235, 1413,80533, 1471,81241, 295,80533,80685,81245, 39749,80533, 483,81249,24095,80533,35187,81253, 11,81252,39787,80533, 241,81259, 903,81259, 587,81258,24236,80533,39846,80533,78459,80533, 413,81270,77949,81273, 413,81271,77859,81277,39232,80533,46169,81281, 510,80533, 11,81285, 1108,80533, 11,81289, 1216,80533,79987,81292, 78669,81295,79757,81292,78669,81299, 1275,81292,18759,81303, 15,81292, 18759,81307, 8808,80533,41376,80533, 7195,80533, 1141,80533,14315,81317, 959,80533,17125,81321, 253,80533,25793,81324,41019,81324, 8495,81324, 317,80533,15661,81333,14991,81333,17993,81333, 2899,81333, 273,80533, 80551,81343, 8634,80533, 8677,80533, 331,80533, 413,81351,18391,81353, 413,81350,17993,81357, 8861,81351,63493,81351,74571,81351,15029,81351, 8495,80533, 586,81368, 586,81369, 587,81368,81373,81375, 11,81368, 253,81368, 1471,81368, 53,81368, 587,81369,81371,81387, 305,81369, 713,81369, 25,81369, 1369,81368, 257,81369, 257,81368,14011,80533, 257,80533,25793,81404,41019,81404, 8495,81404, 973,80533,20103,81413, 8337,81413,36773,81413, 341,80533,30091,81421, 8717,81420,20103,81421, 36773,81421, 8337,81421, 3785,81420,78147,81420, 89,80533,10831,81437, 10903,81437, 5019,81437,60857,81437,17125,81437, 567,80533,63493,81449, 74571,81449, 8861,81449, 652,80533,60857,81457, 288,80533, 8861,81461, 265,80533,78670,81465,77859,81467, 413,81465,77751,81471,77837,81473, 77751,81470,77859,81477,73154,81465,62059,81465,78107,81465,15029,81465, 4593,81465,11985,81465,78459,81465,80057,81465,79911,81465, 8861,81465, 63493,81465,74571,81465,72152,81465,61718,81465,77751,81465, 413,81508, 77859,81511, 413,81509,77949,81515, 17,81464,35187,81519, 11,81465, 60857,81522, 587,81465,71229,81526,71229,81465,60857,81530, 11,81531, 587,81530,60857,81465, 10,81539, 10,81538, 305,81539, 11,81539, 81543,81547,71229,81538, 11,81538,81541,81553, 587,81464,60857,81557, 11,81464, 8861,81561, 1011,80533,50785,81565, 9,81564, 11,81569, 11,81565, 9,81573,71229,81565,77387,81577, 903,80533,50959,81581, 45149,80533,35187,81585, 11,81584,32103,80533,27021,81591, 241,81591, 903,81591, 587,81590, 7333,80533, 483,81601, 6789,80533, 9,81605, 903,81605,14073,80533, 241,81611, 903,81611, 587,81610,11277,80533, 35187,81619, 11,81618,42707,80533, 3445,80533, 375,81627,10313,80533, 79643,80533, 2621,80533,14229,80533,11571,80533, 5045,80533,35187,81641, 11,81640, 4971,80533, 241,81647, 903,81647, 587,81646, 7009,80533, 7497,80533, 7287,80533, 7845,80533, 7925,80533, 7895,80533, 7685,80533, 7671,80533, 7627,80533,14102,80533,11348,80533, 5096,80533, 5000,80533, 7533,80533, 4617,80533, 483,81683,13907,80533, 483,81687, 7563,80533, 264,81691, 264,81690, 265,81691,81695,81697, 265,81690,81693,81701, 7531,80533, 483,81705,79634,80533,80501,81709,79719,81709,79640,80533, 483,81715,42716,80533,42795,81719,42704,80533, 483,81723,10308,80533, 36131,81727,10310,80533, 483,81731, 5227,80533, 5009,80533, 3461,80533, 2981,80533, 3049,80533,80061,80533, 483,81745, 240,80532,77859,81749, 78459,81750,78089,81749,78147,81755,78305,81749,78231,81749,78277,81749, 78445,81749,78564,81749,78613,81749,78558,81749,78548,81749,78071,81749, 78387,81749,78459,81776,78425,81749,78459,81780,78434,81749,78147,81785, 13103,81749, 5161,81749,13074,81749, 5150,81749,13057,81749,13051,81796, 5141,81749, 5137,81800,13051,81749,13057,81804, 5137,81749, 5141,81808, 13092,81749,13045,81813, 5154,81749, 5133,81817,78048,81749,77837,81821, 78459,81749,78387,81824,78425,81824,77859,81824,25793,81749,41019,81749, 8495,81749,78147,81749,48009,81749,49321,81749,49001,81749,78399,81749, 265,81847,78459,81849, 265,81846,78147,81853, 265,81749,13027,81856, 13045,81859, 5127,81856, 5133,81863,13027,81857,13057,81867, 5127,81857, 5141,81871,78399,81856,78147,81875,77751,81856,77837,81879,77751,81857, 78387,81883,78425,81883,77859,81883,77751,81749, 265,81890,77837,81893, 23755,81749,39633,81749, 3785,81749, 8717,81749,79309,81749,79665,81749, 10055,81749,10351,81749,27805,81749,42731,81749,26331,81749, 4329,81749, 41559,81749, 4311,81749, 5127,81749, 265,81925, 5137,81927, 265,81924, 5133,81931,13027,81749, 265,81935,13051,81937, 265,81934,13045,81941, 1010,80532,27021,81945,24095,81945,52915,81945, 9195,81945,81565,81945, 9,81955,81569,81945,23651,81945,67297,81945,81289,81945,21605,81945, 9,81967,51435,81945, 4321,81945, 9755,81945,11277,81945, 5045,81945, 4295,81945, 3833,81945,69729,81945,26907,81945,70097,81945,27323,81945, 53941,81945,53215,81945,10171,81945, 9317,81945, 264,80532,51421,82001, 39619,82001,57811,82001,59743,82001,59933,82001, 8093,82001, 3837,82001, 53703,82001, 4303,82001,42435,82001, 4287,82001,53487,82001, 9579,82001, 42113,82001, 9839,82001, 241,82001, 375,82032, 394,82001, 299,82001, 375,82001, 241,82040,78399,80533, 264,82044, 264,82045, 413,82045, 265,82044,82049,82053, 265,82045,82047,82057, 240,80533,78397,82061, 78459,82063,78099,82061,78147,82066,78264,82061,78283,82061,78260,82061, 78262,82061,78661,82061,78599,82061,78619,82061,78601,82061,78675,82061, 77837,82061,77949,82088,78673,82061,77950,82061,78118,82061,78459,82097, 78670,82061,77859,82101,77949,82061,78147,82104,77837,82104,78141,82061, 78147,82110, 413,82061,77751,82115,77837,82117,77751,82114,77859,82121, 78147,82061,78099,82124,78141,82124,77949,82124,78107,82061, 265,82132, 78459,82135, 265,82133,78147,82139,77751,82061, 413,82142,77859,82145, 413,82143,77949,82149, 265,82061,78107,82152,78459,82155,78107,82153, 78141,82159, 902,80533,37663,82163,37599,82163, 265,80532,25793,82169, 41019,82169,39787,82169,23755,82169,39633,82169, 8495,82169,78147,82169, 8717,82169, 3785,82169,79309,82169,79665,82169,27805,82169,42731,82169, 10055,82169,10351,82169,26331,82169,41559,82169, 4329,82169, 4311,82169, 4555,82169,14073,82169, 4971,82169,21605,82169,65869,82215,38305,82169, 56555,82219, 483,82219, 241,80532, 4437,82225, 7,82225, 265,82229, 39787,82225,51615,82225, 4613,82225,12571,82225,14073,82225, 4971,82225, 375,82225, 510,82225,51937,82225,16683,82225, 4805,82225, 9,82225, 483,82254, 483,82225, 9,82258,38305,82225, 483,82263, 1010,80533, 55211,82267,64345,82267,36256,82267,35187,82267, 9,82274, 9,82267, 35187,82278, 1011,80532,10001,82283, 903,82285,27533,82283, 903,82289, 79139,82283, 903,82293,82267,82283, 9,82296,82278,82283,81231,82283, 21605,82283, 903,82305, 9,82283,82267,82308, 903,80532, 3549,82313, 2001,82313,21769,82313,10291,82313, 1011,82321,42613,82313, 1011,82325, 79549,82313, 1011,82329,24095,82313,25793,82313, 8495,82313, 5045,82313, 11277,82313,39787,82313,14073,82313, 4971,82313,21605,82313, 955,82349, 9,82349,65869,82349,38305,82313, 1011,82357, 483,82357,41019,82313, 264,80533, 53,82365, 1471,82365, 253,82365,72567,82365,76285,82365, 76939,82365,77751,82364, 375,82379, 471,82365, 367,82365, 357,82365, 341,82365, 241,82389, 241,82365, 9,82393, 483,82393, 413,80533, 78106,82398,78107,82399,82401,82403,78459,82403,78106,82399,78107,82398, 82409,82411,78141,82411,77949,82411,79987,82398,77949,82419,79757,82398, 77949,82423,78459,82398,77949,82427, 331,82398,17993,82431, 261,82398, 17993,82435,77949,82399,78459,82439,17993,82399, 331,82443, 1275,82398, 17993,82447, 15,82398,17993,82451, 375,80533, 53,82455, 1471,82455, 253,82455, 1369,82455, 11,82455, 261,80533, 413,82467,18391,82469, 413,82466,17993,82473,15029,82467, 264,82477, 265,82476,82479,82481, 264,82476, 265,82477,82485,82487,16531,80533, 483,82491,12745,80533, 264,82495,13129,82495, 413,82495,13119,82501,15503,82495,50535,82495, 50929,82495,51081,82495,82231,82495,13171,82495,13133,82495, 264,82494, 265,82495,82519,82521, 265,82494,82497,82525, 375,82495, 257,82495, 264,82531, 265,82530,82533,82535, 264,82530, 265,82531,82539,82541, 566,80533, 53,82545, 253,82545, 1471,82545, 88,80533, 1369,82553, 1346,80533,55211,82557,28714,80533,28337,82561,60618,80533,60757,82565, 3,82565,60755,82569, 154,80533,37663,82573,43214,80533,43053,82577, 483,82577,43502,80533,80531,82583,46169,82583, 67,80533,11529,82589, 11569,82589, 4610,82589,61780,82589, 9,82589, 4593,82598,60857,82598, 60857,82589, 9,82604, 4593,82589, 9,82608,37845,80533,38305,82612, 45411,82615,37899,82615,79926,80533,79987,82621, 4,82623, 5,82622, 82625,82627, 5,82623, 4,82622,82631,82633,80058,80533,79757,82637, 2,82639, 3,82638,82641,82643, 3,82639, 2,82638,82647,82649, 80244,80533, 17,82653, 1447,80533,14315,82657, 33,80533,14315,82661, 759,80533,17125,82665, 47,80533,17125,82669, 1471,80533,41019,82672, 25793,82672, 8495,82672, 53,80533,25793,82680,41019,82680, 8495,82680, 25793,80533, 586,82688, 586,82689, 11,82688, 1369,82688, 587,82688, 82693,82699, 253,82688, 53,82688, 1471,82688, 587,82689,82691,82709, 25,82689, 713,82689, 305,82689, 257,82688, 257,82689, 1325,80533, 74571,82723,63493,82723, 8861,82723,15029,82723,41019,80533, 586,82732, 586,82733, 587,82732,82737,82739, 11,82732, 253,82732, 1471,82732, 53,82732, 713,82733, 25,82733, 305,82733, 587,82733,82735,82757, 257,82732, 1369,82732, 257,82733, 59,80533,63493,82767,74571,82767, 8861,82767,15029,82767,79139,80533,80244,82777,80245,82777,80293,82777, 4,82782,80319,82785, 4,82783,80301,82789,80298,82777,80319,82793, 21036,82777,21037,82777, 1216,82777, 413,82777,80245,82776,82779,82805, 1011,82777, 903,82808,21037,82776,82797,82813,80244,82776,82781,82817, 21036,82776,82799,82821,65869,82777, 9,82777, 903,82777, 1011,82828, 4,82777,80293,82833,80315,82835,80293,82832,80319,82839,79549,80533, 80450,82843,80451,82843,80497,82843, 2,82848,80519,82851, 2,82849, 80501,82855,80498,82843,80519,82859, 1216,82843, 413,82843,80451,82842, 82845,82867, 903,82843, 1011,82870,80450,82842,82847,82875,56555,82843, 483,82843, 1011,82843, 903,82882, 2,82842,80501,82887,79719,82887, 3,82842,80337,82892, 483,82893, 3,82843,82867,82899, 1369,82899, 2,82843,82875,82905,82895,82905,80497,82905,80515,82911,80497,82904, 80519,82915,80519,82905,80437,82905,80489,82905,79587,82905,79721,82905, 79645,82905,80337,82842, 3,82930,82905,82933, 3,82931,82887,82937, 27533,80533, 1216,82941, 413,82941,21036,82941,21037,82941, 1011,82941, 903,82950,21037,82940,82947,82955,21036,82940,82949,82959, 9,82941, 65869,82941, 903,82941, 1011,82966,42613,80533, 1216,82971, 413,82971, 903,82971, 1011,82976, 483,82971,56555,82971, 1011,82971, 903,82984, 2,82971,42667,82989,42791,82989,42709,82989, 3,82971, 1369,82997, 2,82970,42795,83001, 3,82970, 483,83005,10001,80533, 1216,83009, 413,83009,21036,83009,21037,83009,21036,83008,83017,83019, 1011,83009, 903,83022,21037,83008,83015,83027,65869,83009, 9,83009, 903,83009, 1011,83034,10291,80533, 1216,83039, 413,83039, 903,83039, 1011,83044, 56555,83039, 483,83039, 1011,83039, 903,83052, 2,83039,37871,83057, 36133,83057,35803,83057, 3,83039, 1369,83065, 2,83038,36131,83069, 3,83038, 483,83073, 1369,80533,26331,83076,25793,83076,23755,83076, 27805,83076,40381,83077,41559,83076, 8717,83076,21036,83077,39633,83076, 78147,83076,79309,83076,10055,83076,42731,83076, 3785,83076,79665,83076, 4329,83076,10351,83076, 4311,83076,38305,83076,41941,83115,41019,83076, 8495,83076,38305,83077,41019,83123, 5,83077,18967,83126,18967,83077, 11,83131, 5,83130, 17,80533,25367,83137,62984,83137,60857,83137, 265,83143, 241,83142, 241,83137,60857,83148,21605,83136,26625,83153, 265,83136,35187,83157,21605,83137,25793,83161,35187,83137, 265,83165, 587,80533,62984,83169,62518,83169,68807,83169,36526,83169,17125,83169, 265,83169,35187,83180,35187,83169,60857,83184, 265,83184,32103,83168, 38305,83168, 483,83193,39787,83168,14073,83168, 4971,83168, 265,83168, 60857,83203, 241,83169,60857,83206,60857,83169, 241,83210,35187,83210, 11,80533,25793,83216,41019,83216, 8495,83216, 265,83217, 8495,83225, 45149,83216,21605,83216, 903,83231, 9,83231,24095,83216,11277,83216, 5045,83216, 265,83216, 8861,83243, 3,83217, 375,83247,38305,80533, 76424,83251,54262,83251,54219,83251,76453,83251,42185,83251,42193,83260, 42194,83251,42191,83251,42193,83251,42185,83268,80450,83251,37844,83251, 37845,83251,44663,83277,38707,83277,43483,83277,37897,83277,80451,83251, 80450,83250,83287,83289, 120,83251, 77,83251,32805,83251,54225,83251, 54129,83298,76337,83251,76307,83302,76307,83251,76337,83306,54129,83251, 54225,83310, 113,83251, 25,83314, 506,83251, 1216,83251, 413,83251, 1413,83251,37845,83250,45411,83327,83275,83327,37899,83327,37897,83250, 83275,83335,65076,83251,37844,83250, 6,83340,83277,83343,83277,83341, 80451,83250,83273,83349, 66,83251, 33,83353, 25,83251, 113,83356, 1281,83251, 1086,83251, 922,83251, 483,83251, 241,83366, 587,83367, 903,83366, 241,83251, 483,83374, 903,83251, 1011,83378, 483,83378, 1369,83250,41941,83385, 587,83250, 483,83389, 587,83251, 1011,83392, 1011,83251, 903,83396, 11,83397, 587,83396, 1275,83250,46169,83405, 60857,83251,56555,83408,56555,83251, 11,83413,60857,83412, 2,83250, 80531,83419,46169,83419, 3,83250,43053,83425, 483,83425, 2,83251, 80435,83431,80495,83431,43461,83431,80529,83431,46599,83431,43425,83431, 3,83251,43837,83445,43027,83445, 11,83445, 25,83451,39747,83445, 11,83444, 33,83457, 1369,83445, 11,83251, 3,83463, 113,83465, 3,83462, 33,83469, 15,80533, 1216,83473,18617,83475, 413,83473, 18391,83479,25545,83473,62942,83473, 1216,83472,18759,83487, 413,83472, 17993,83491,60857,83473, 1011,83494,18967,83473, 17,83499, 1011,83473, 60857,83502, 3,83472,37663,83507, 3,83473,37611,83511,38155,83511, 35927,83511,21605,80533,27065,83519,27261,83519,21036,83519,21037,83519, 27067,83519,27255,83519,73221,83519,55211,83519,36256,83519,51593,83519, 55803,83519,64345,83519,54477,83519, 1216,83519, 413,83519,21037,83518, 83525,83551,21036,83518,83527,83555, 247,83519, 934,83519, 9,83519, 35187,83562, 11,83563, 1011,83519, 903,83568, 17,83518,26625,83573, 11,83518, 903,83577, 9,83577, 11,83519, 903,83582, 903,83519, 27021,83587, 1011,83586, 11,83587, 11,83586,35187,83519, 9,83596, 65869,83519, 5,83518,28337,83603, 5,83519,27021,83607,52915,83607, 9195,83607,20501,83607, 9875,83607,30475,83607,28219,83607,23939,83607, 1275,80533,43214,83624,43214,83625,43215,83624,83629,83631, 1216,83625, 18617,83635, 413,83625,18391,83639,43215,83625,83627,83643,40675,83625, 73994,83625, 1216,83624,18759,83651, 413,83624,17993,83655,71229,83625, 903,83658, 903,83625,71229,83662,38305,83624,46169,83667, 5,83624, 55211,83671, 5,83625,53813,83675,10107,83675,69877,83675, 483,80533, 241,83683, 9,83685, 9,83682, 11,83689, 17,83683, 903,83693, 11,83683, 9,83697, 5,83682, 53,83701, 253,83701, 1471,83701, 5,83683, 1505,83709, 9,80533,80151,83712, 1011,83713,82267,83717, 241,83713, 483,83721, 483,83712, 11,83725, 1011,83712,81945,83729, 11,83729, 3,83712, 1369,83735, 3,83713, 483,83739,17025,80533, 5,83742, 2,83745, 17,83746, 17,83745, 2,83750, 2,83751, 164,83745,38057,83743,38057,83742,38056,83742,83759,83763,38056,83743, 83761,83767, 3,83742,83749,83771,83753,83771,83757,83771, 3,83743, 83755,83779,13737,80533, 375,83783,80151,80533, 9,83786,35187,83787, 9,83791, 5,83787, 9,83795, 5,83786, 17,83799,79987,80533, 413,83802,77949,83805, 413,83803,77859,83809, 1216,83802,78669,83813, 1216,83803,77857,83817, 4,83803,79549,83821, 2,83823, 3,83822, 83825,83827, 3,83823, 2,83822,83831,83833, 4,83802,79757,83837, 2,83839, 3,83838,83841,83843, 3,83839, 2,83838,83847,83849, 79757,80533, 413,83852,77949,83855, 413,83853,77859,83859, 1216,83852, 78669,83863, 1216,83853,77857,83867, 2,83853,79139,83871, 4,83873, 5,83872,83875,83877, 5,83873, 4,83872,83881,83883, 2,83852, 79987,83887, 4,83889, 5,83888,83891,83893, 5,83889, 4,83888, 83897,83899, 3,80532,79231,83903,79237,83903,79365,83903,79375,83903, 73413,83903,73405,83903,40793,83903,40787,83903,71751,83903,36001,83903, 71731,83903,72115,83903,72929,83903,71713,83903, 7,83903, 4,83933, 83519,83935,32103,83903,26106,83903,41746,83903,43005,83903, 8800,83903, 64513,83903,63253,83903,62215,83903,59910,83903,41019,83903, 11,83956, 60755,83903,60707,83903, 9852,83903,48975,83903,48245,83903,48451,83903, 76271,83903,82267,83903, 9,83974,82278,83903,83157,83903,81231,83903, 81235,83903,81519,83903, 386,83903, 347,83903, 510,83903, 273,83903, 281,83903, 1477,83903, 1516,83903, 948,83903, 165,83903, 903,84004, 40704,83903,79139,84009,27533,84009,10001,84009,73307,83903,79139,84017, 27533,84017,10001,84017,53500,83903,37595,83903,36049,83903,36539,83903, 68851,83903,36041,83903,37573,83903,36275,83903, 1505,83903, 1011,84040, 25793,83903, 11,84044,64397,83903, 483,84049, 8495,83903, 11,84052, 60618,83903, 483,84057, 375,83903, 305,84060, 903,83903, 165,84064, 1011,83903, 1505,84068, 305,83903, 375,84072, 4,83903,56555,84076, 483,84079, 5,83902,57811,84083,59743,84083,59933,84083, 9579,84083, 9839,84083,51421,84083,39619,84083, 4303,84083, 4287,84083, 8093,84083, 3837,84083,42113,84083,53487,84083,53703,84083,42435,84083,48885,83903, 483,84115, 11,83903,25793,84118,41019,84118, 8495,84118,59875,84118, 9805,84118,53391,84118, 9,83903,82267,84132, 483,84132,38305,84132, 79139,84139,10001,84139,27533,84139,38305,83903, 9,84146,79139,84149, 27533,84149,10001,84149, 9805,83903, 11,84156, 5,84157, 483,83903, 9,84162,56555,83903, 4,84166, 483,84169,53391,83903, 11,84172, 5,84173,59875,83903, 11,84178, 5,84179, 2,80532,11087,84185, 11307,84185,11713,84185,10439,84185, 2221,84185,10665,84185,11037,84185, 2233,84185,17777,84185, 2215,84185,18739,84185, 4339,84185,79091,84185, 79097,84185, 5075,84185, 4643,84185,79115,84185,79123,84185,59811,84185, 36619,84185,68291,84185,68299,84185,24213,84185,24059,84185,22149,84185, 22143,84185,72667,84185,60839,84185,35665,84185,59819,84185,59869,84185, 35487,84185, 7,84185, 4,84251,27306,84185,24095,84185,53910,84185, 55537,84185,79280,84185,80301,84263,83607,84185,40455,84185,25313,84185, 8714,84185,32103,84185,26106,84185, 8800,84185,41746,84185,81569,84185, 48009,84185,49001,84185,49321,84185, 4551,84185,81531,84185,81289,84185, 81245,84185,83729,84185,10196,84185,70136,84185,10603,84185, 9,84305, 4625,84185, 9,84309,81565,84185, 9,84313,23983,84185, 9,84317, 76501,84185,68176,84185,79065,84323,59787,84323, 9513,84323,36545,84185, 79065,84331,59787,84331, 9513,84331, 759,84185,35187,84339,10107,84185, 265,84342, 241,84343,69877,84185, 265,84348, 241,84349, 305,84185, 8495,84354, 959,84185,35187,84359,28714,84185,77079,84185, 1011,84365, 1010,84364,84367,84369, 1010,84365, 1011,84364,84373,84375, 47,84185, 35187,84379,48245,84185,48975,84185,48451,84185,11277,84185, 5045,84185, 52603,84185, 8495,84185, 10,84394, 10,84395, 305,84394, 11,84394, 84399,84403, 11,84395,84397,84407, 331,84185,71229,84411,79549,84185, 1011,84415, 265,84185,53813,84418,71229,84419,10107,84418,69877,84418, 79757,84419, 903,84185,55211,84431,10291,84185, 1011,84435,25793,84185, 10,84438, 10,84439,27021,84438, 11,84438,84443,84447, 11,84439, 84441,84451,42613,84185, 1011,84455, 1325,84185,71229,84459, 5,84185, 27255,84463, 9287,84463,53167,84463,21605,84462, 4,84185,79139,84472, 80301,84475,49475,84473,73066,84473,28715,84473, 1011,84473,71229,84484, 71229,84473, 1011,84488,27693,84473,10047,84473,79287,84473,41019,84185, 10,84498, 10,84499, 11,84498,84503,84505, 11,84499,84501,84509, 59,84185,71229,84513, 4,84184, 8495,84517,41019,84517,25793,84517, 49001,84517,49321,84517,48009,84517, 265,84517,78147,84517,23755,84517, 39633,84517, 3785,84517, 8717,84517,41559,84517, 4311,84517,79665,84517, 10351,84517,26331,84517,42731,84517, 4329,84517,79309,84517,27805,84517, 10055,84517, 5,84184,27021,84563,24095,84563, 9195,84563,52915,84563, 21605,84563, 9,84573,23651,84563, 9755,84563,51435,84563,67297,84563, 4321,84563,69729,84563,26907,84563, 9317,84563,53215,84563,27323,84563, 53941,84563, 3833,84563,10171,84563,70097,84563, 4295,84563, 5045,84563, 11277,84563,53813,84185, 265,84610, 241,84611,48885,84185, 1011,84617, 11,84185,25793,84620, 8495,84620,41019,84620, 17,84185,30091,84629, 65869,84185, 15,84632,79065,84635,59787,84635, 9513,84635, 803,84633, 38305,84185, 1011,84645, 1347,84645, 15,84185,28714,84650,28714,84651, 65869,84650,79065,84657, 9513,84657,59787,84657,28715,84650,84655,84665, 28715,84651,84653,84669, 9195,84185, 241,84673,35187,84673,21605,84185, 27255,84679, 7,84678, 4,84682, 4,84683,84253,84679, 16,84678, 55211,84679, 803,84679, 9,84679, 17,84678, 903,84679,65869,84679, 4,84679,84699,84705, 5,84679,84685,84709,84691,84709,27021,84709, 4,84678, 7,84716,84709,84719, 5,84678,84687,84723,52915,84185, 35187,84727, 241,84727,27021,84185,35187,84733, 241,84733,25793,84732, 79139,84185,80245,84740, 4,84740,80301,84745, 5,84740,80151,84748, 4,84741,80319,84753,84751,84753,80207,84753,80283,84753, 5,84741, 84743,84763, 5,80532,80759,84767, 7,84767, 2,84770, 3,84770, 83251,84775, 2,84771,84776,84779,84775,84779,83251,84782,83251,84779, 84775,84786, 3,84771,84773,84791,83251,84793,27306,84767,24095,84767, 52603,84767,53910,84767,55537,84767,84438,84767,84394,84767,84498,84767, 81539,84767,25793,84767,27021,84814,84185,84814,64289,84767,84060,84767, 81569,84767,83729,84767,81245,84767,81289,84767,70136,84767,10196,84767, 273,84767, 1477,84767, 281,84767, 948,84767, 1516,84767,81565,84767, 9,84847, 1505,84767, 1011,84850, 5045,84767,11277,84767, 4551,84767, 922,84767, 1413,84767,20831,84767,19783,84767,20053,84767,58775,84767, 9195,84767, 265,84873, 47,84767,60857,84877, 165,84767, 903,84880, 41019,84767,84185,84884,27021,84767,25793,84888, 265,84889, 8495,84767, 84185,84894, 959,84767,60857,84899, 89,84767, 5019,84903,60857,84903, 375,84767,83903,84908, 759,84767,60857,84913, 265,84767,53813,84916, 69877,84916,10107,84916, 1011,84767, 1505,84924,54597,84925, 903,84767, 165,84930, 483,84930,54295,84931, 1447,84767,18967,84939, 1141,84767, 18967,84943, 2,84767,61780,84947, 9,84947,60857,84950,54295,84947, 70085,84947,11529,84947,10155,84947,53925,84947,60857,84947, 9,84964, 3,84767, 8063,84969,42361,84969,53667,84969,84185,84767,41019,84976, 8495,84976,25793,84976,83903,84767, 375,84984, 33,84767,18967,84989, 2,84766,27021,84993,24095,84993, 9195,84993,52915,84993,21605,84993, 9,85003,67297,84993, 9755,84993,51435,84993,23651,84993, 4321,84993, 26907,84993,69729,84993,10171,84993,53941,84993,70097,84993,53215,84993, 9317,84993, 4295,84993,27323,84993, 3833,84993, 5045,84993,11277,84993, 3,84766,57811,85041,59743,85041,59933,85041,51421,85041,39619,85041, 4303,85041, 4287,85041, 9579,85041, 9839,85041, 8093,85041, 3837,85041, 53487,85041,42113,85041,53703,85041,42435,85041,52915,84767, 265,85073, 587,84767,60857,85077,70573,85077, 1369,84767,43503,85083, 483,84767, 903,85086,21605,84767, 9,85091, 145,85091,10107,84767, 265,85096, 9,84767,53813,84767, 265,85102,69877,84767, 265,85106, 4,80532, 83715,85111,80781,85111,83789,85111, 7,85111, 2,85118,83511,85121, 2,85119,82163,85125,83507,85125,82573,85125, 1368,85111,83511,85133, 25525,85111,84498,85111,84438,85111,84709,85111,79634,85111,80501,85145, 84394,85111,64513,85111,63253,85111,62215,85111,81539,85111,64397,85111, 483,85159,83787,85111, 9,85163,43214,85111, 8495,85111,84185,85168, 587,85169, 331,85111,60857,85175,79139,85111, 903,85179, 265,85111, 60857,85183,79987,85183,10001,85111, 903,85189,41019,85111,84185,85192, 587,85193,27533,85111, 903,85199, 59,85111,60857,85203, 3,85111, 4,85206,85125,85209,38305,85206, 2,85111, 7,85214,83511,85217, 79549,85214,80501,85221,49155,85215,62464,85215,43215,85215, 903,85215, 60857,85230,60857,85215, 903,85234,42705,85215,10311,85215,79641,85215, 84185,85111,25793,85244,41019,85244, 8495,85244,25793,85111,84185,85252, 587,85253, 1325,85111,60857,85259, 2,85110, 8495,85263,25793,85263, 41019,85263,49321,85263,49001,85263,48009,85263, 265,85263,78147,85263, 39633,85263,23755,85263, 3785,85263, 8717,85263,26331,85263, 4329,85263, 79309,85263,10055,85263,41559,85263,27805,85263, 4311,85263,79665,85263, 42731,85263,10351,85263,49205,85111, 903,85309,21605,85111, 903,85313, 155,85313, 1275,85111,43215,85319,77751,85111,38305,85111, 7,85324, 2,85326, 2,85327, 1368,85324, 1369,85324, 2,85325,85335,85337, 3,85325,85329,85341,85333,85341,84185,85341, 2,85324, 7,85348, 85341,85351, 3,85324,85331,85355,79549,85111,80451,85358, 2,85358, 80501,85363, 3,85358,80337,85366, 2,85359,80519,85371,85369,85371, 80437,85371,80489,85371, 3,85359,85361,85381, 5,80533,83932,85385, 83933,85385,64148,85385,64149,85385, 0,85385,56555,85395, 1369,85397, 7,85385,83903,85400,60857,85400, 265,85401,83903,85407, 1275,85401, 60857,85411, 0,85384,63015,85415,25380,85415,85413,85415,21605,85415, 1369,85422, 1369,85415,21605,85426, 7,85384,85417,85431,25381,85431, 85415,85435,63014,85431,85415,85439,85419,85431,85399,85431,85429,85431, 85425,85431, 483,85431,60857,85450,85415,85453,60857,85431, 483,85456, 85415,85459,54440,85385,83903,85385, 7,85464,27425,85385,53137,85385, 9365,85385, 803,85385,60857,85474,62310,85385,85206,85385,85125,85481, 241,85385, 483,85485,54295,85484,54295,85385, 241,85490, 483,85384, 53,85495, 253,85495, 1471,85495, 1275,85384,55211,85503,21605,85384, 28337,85507, 1369,85385, 1011,85511,60857,85385, 7,85514, 803,85514, 2,85384,85389,85521,85393,85521,55211,85521,64345,85521,84132,85521, 36256,85521,83903,85521, 9,85534, 9,85521,83903,85538,35187,85538, 35187,85521, 9,85544, 3,85384,85467,85549,85387,85549,85403,85549, 85401,85549,83903,85557,85391,85549,85517,85549,85405,85549, 53,85549, 1471,85549, 253,85549,76285,85549,76939,85549,72567,85549, 241,85549, 483,85579, 9,85579, 2,85385, 3,85385, 165,85587, 1108,85587, 1072,85587,76337,85587, 1011,85587, 483,85596, 9,85596,85111,85586, 85125,85603, 9,85587, 1011,85606, 483,85587, 1011,85610,80151,85384, 17,85615,85111,85385, 1368,85618, 7,85618, 2,85623, 2,85622, 1369,85618, 2,85619,85629,85631, 3,85619,85627,85635,85121,85635, 85217,85635,85621,85635,85133,85635, 2,85618, 7,85646,85635,85649, 3,85618,85625,85653,85125,85653,55211,85385, 265,85659, 17,85385, 3,80533,73221,85665, 9,85667,78796,85665, 9,85671, 8139,85665, 53639,85665,42521,85665,85322,85665, 9,85681,55004,85665,85111,85665, 77751,85686, 9,85689,42613,85664, 483,85693,10291,85664, 483,85697, 79549,85664, 483,85701,85585,85665, 9,85705, 9,85664, 1369,85709, 15,85664,37663,85713,85125,85713,38305,85664,43053,85719, 483,85719, 17,85665, 903,85725,35187,85665,77751,85728, 9,85731, 4,85664, 85125,85735,37663,85735, 5,85664,76939,85741, 1471,85741, 53,85741, 253,85741,76285,85741,72567,85741, 241,85741, 9,85755, 483,85755, 5,85665, 1505,85761, 922,85761, 918,85761,54597,85760, 903,85761, 9,85770, 483,85770, 483,85761, 903,85776, 9,85761, 903,85780, 77751,85760, 9,85785,79756,85665, 9,85789,84185,85665, 16,85792, 7,85792, 4,85797, 4,85796, 17,85792, 4,85793,85803,85805, 483,85805, 5,85793,85801,85811,85797,85811,85795,85811, 4,85792, 7,85818,85811,85821, 5,85792,85799,85825,54597,85665, 11,85829, 5,85828, 1369,85665, 9,85835,18967,85665, 4,85839, 483,85841, 77751,85665,35187,85844, 9,85847, 9,85845,85111,85851,85111,85844, 9,85855, 5,85845, 17,85859, 5,85844, 9,85863,77751,85664, 375,85867,79986,80533, 375,85871, 2,80533,80080,85875,80079,85877, 80298,85875,80319,85881,80293,85875, 4,85884,80319,85887, 4,85885, 80301,85891,11727,85875,11047,85875,17787,85875,18737,85875,78670,85875, 77859,85903,10874,85875,77952,85875,77857,85909, 7,85874,83903,85913, 85167,85875,85355,85875,85213,85875, 1216,85875,77751,85923,77877,85925, 77751,85922,77857,85929,62310,85875,64483,85875,68896,85875,62464,85875, 61780,85875,61688,85875,85159,85875,10831,85875, 9,85946, 413,85875, 77751,85951,77837,85953,77751,85950,77859,85957,74571,85875,17178,85875, 50959,85875,43400,85875,11177,85875,84077,85875,85913,85971,40675,85875, 55546,85875,54440,85875,69196,85875,17125,85875, 9,85982,15029,85875, 65869,85986,52169,85875,49155,85875,40453,85875,43305,85875,40005,85875, 84767,85875,77751,86001, 9,86003,73994,85875,42613,85874,42795,86009, 10291,85874,36131,86013,70135,85875,53919,85875,10195,85875,79842,85875, 79757,85875, 903,86024,63493,85875, 8861,85875,80058,85875,80079,86033, 54422,85875,11529,85875,54447,85875,52601,85875, 145,85875,35187,86044, 36096,85875,79601,85875,79549,85874,80501,86053,79719,86053,64396,85875, 85111,86059, 1011,85875,43215,86062, 241,85875,54295,86066,65869,85875, 60857,86070,15029,86070, 9,85875,10831,86076,60857,86076,17125,86076, 84076,85875, 483,86085, 803,85875,60857,86088, 903,85875,53813,86093, 60857,86092,10107,86093,69877,86093,79757,86092,71229,86092, 265,85875, 55211,86106,10371,85875,42787,85875,55211,85875,60857,86114, 265,86114, 38305,85874,46169,86121,80531,86121,72818,85875, 11,85875,43215,86128, 43316,85875,35187,85875,54295,86134, 145,86134,71229,85875, 903,86140, 155,86140,43215,85875, 10,86147, 10,86146,85111,86147, 1011,86146, 84767,86147, 11,86147,86151,86159, 11,86146,86149,86163, 155,85875, 71229,86166, 5,85874,55211,86171,64345,86171,84132,86171,36256,86171, 83903,86171, 9,86180, 9,86171,83903,86184,35187,86184,35187,86171, 9,86190, 4,85875,80070,86195,80077,86197,80293,86195,80315,86201, 80293,86194,80319,86205, 483,86195,83903,86209,80533,86194, 3,86213, 7,86195,86215,86217, 2,86217,86213,86221,79987,86194,80079,86225, 83903,86194, 483,86229,77751,86195,79545,86233, 3,86235, 2,86234, 86237,86239, 2,86235, 3,86234,86243,86245,77751,86194,79549,86249, 3,86251, 2,86250,86253,86255, 2,86251, 3,86250,86259,86261, 5,85875,85914,86265,85913,86265,83903,86268,49713,86265,49712,86264, 86273,86275,49712,86265,49713,86264,86279,86281,53813,86265,64317,86265, 64815,86265,62077,86265,10107,86265,69877,86265, 17,86265,83903,86297, 35187,86297,60857,86264,85111,86303,65869,86265, 9,86307, 587,86265, 60857,86311,83903,86265,85913,86314,79757,85874,79987,86319, 4,86321, 5,86320,86323,86325, 5,86321, 4,86320,86329,86331,80336,85875, 79549,86335, 3,86337, 2,86336,86339,86341, 2,86337, 3,86336, 86345,86347,83903,85875, 16,86351, 7,86351,86265,86355, 4,86354, 4,86355, 17,86351, 4,86351, 7,86364, 5,86351,86361,86369, 4,86350,86363,86373, 483,86373, 5,86350,86359,86379,86367,86379, 86355,86379,86353,86379,54295,85875, 241,86388,35187,86388,60857,85875, 7,86395, 4,86396, 4,86397,86265,86397, 16,86395, 17,86395, 803,86394,55211,86394, 903,86394,65869,86394, 9,86394, 4,86394, 86407,86419, 5,86394,86399,86423,86405,86423,85111,86423, 4,86395, 7,86430,86423,86433, 5,86395,86401,86437,77751,85875, 413,86440, 77859,86443, 413,86441,77949,86447, 1216,86440,77857,86451, 1216,86441, 78669,86455, 4,86441,79757,86459, 3,86461, 2,86460,86463,86465, 2,86461, 3,86460,86469,86471, 4,86440,79549,86475, 3,86477, 2,86476,86479,86481, 2,86477, 3,86476,86485,86487,79987,85875, 80244,86491,80245,86491,80151,86491, 5,86496, 5,86497, 4,86491, 80083,86503,80029,86503,80063,86503,86501,86503, 5,86491,80151,86512, 4,86490,80079,86517,86513,86517,86493,86517,86515,86517,86499,86517, 5,86490,86495,86529,86503,86529,77751,85874,86529,86535,86503,86536, 86532,86535,86521,86535,86512,86535,86517,86545,86503,86535,86529,86548, 86491,86535, 5,86552,86517,86555, 5,86553,86503,86559,85663,86535, 85100,86535, 9,86535,84767,86566,84767,86535, 9,86570, 5,86535, 86491,86574,86517,86577,86491,86575,86529,86581,80150,80533,80315,86585, 80301,86586,80298,86585,80319,86591,80301,86585,80315,86594,80316,86585, 80325,86585,80293,86585, 4,86602,80319,86605, 4,86603,80301,86609, 85663,86585,85100,86585, 9,86585,84767,86616,84767,86585, 9,86620, 4,86585,80293,86625,80315,86627,80293,86624,80319,86631, 4,80533, 79968,86635,79967,86637,80498,86635,80519,86641,80497,86635, 2,86644, 80519,86647, 2,86645,80501,86651,78670,86635,77859,86655,77952,86635, 77857,86659, 0,86635,21605,86663, 587,86665, 7,86635, 483,86669, 18967,86671, 0,86634,19917,86675,58930,86675,86673,86675,56555,86675, 587,86682, 587,86675,56555,86686, 7,86634,58931,86691,86675,86693, 86677,86691,86679,86691,19916,86691,86675,86701,86265,86691,86667,86691, 86689,86691,86685,86691, 1275,86691,18967,86712,86675,86715,18967,86691, 1275,86718,86675,86721,29023,86635,25513,86635,24619,86635,84363,86635, 84723,86635,84471,86635, 1216,86635,77751,86737,77877,86739,77751,86736, 77857,86743,63610,86635,63291,86635,84321,86635,86028,86635,86030,86635, 85960,86635,86437,86635,76631,86635,76601,86635,74682,86635, 8974,86635, 413,86635,77751,86769,77837,86771,77751,86768,77859,86775,63493,86635, 483,86778,85875,86778,29598,86635,25545,86635,59206,86635,15029,86635, 56555,86790,62942,86635,80030,86635,79987,86635, 1011,86798,74571,86635, 85875,86802, 483,86802, 8861,86635,85875,86808, 483,86808,79926,86635, 79967,86815,85875,86635, 8861,86818,63493,86818,74571,86818,79263,86635, 76816,86635,77387,86829,76500,86635,84185,86833, 11,86833, 903,86635, 28715,86838,56555,86635,15029,86842, 483,86635,63493,86846,74571,86846, 8861,86846, 1011,86635,79987,86854,60857,86854,10073,86635,27855,86635, 62278,86635, 587,86635,28715,86866,29026,86635,60857,86635, 1011,86872, 1347,86872,28715,86635, 11,86879,84185,86879, 903,86878, 587,86878, 1347,86635,60857,86888, 2,86634, 4,86893, 7,86895, 3,86634, 85125,86899,37663,86899, 2,86635,79962,86905,79965,86907,80497,86905, 80515,86911,80497,86904,80519,86915,79757,86904,79967,86919,71229,86904, 77387,86923,77751,86905,79065,86927, 5,86929, 4,86928,86931,86933, 4,86929, 5,86928,86937,86939,77751,86904,79139,86943, 5,86945, 4,86944,86947,86949, 4,86945, 5,86944,86953,86955, 3,86635, 85217,86959,85121,86959,86897,86959,86217,86959,85133,86959, 6,86959, 6,86958, 7,86958,86971,86975, 7,86959,86973,86979,60755,86959, 35927,86959,38155,86959,37611,86959,71229,86958,84185,86991, 11,86991, 79987,86634,79757,86997, 2,86999, 3,86998,87001,87003, 3,86999, 2,86998,87007,87009,80150,86635,79139,87013, 5,87015, 4,87014, 87017,87019, 4,87015, 5,87014,87023,87025,84767,86635, 1368,87029, 7,87029, 2,87032, 2,87033, 1369,87029, 2,87029, 7,87040, 3,87029,87037,87045, 2,87028,87039,87049, 3,87028,87035,87053, 87043,87053,87031,87053,71229,86635, 7,87061, 2,87062, 2,87063, 1368,87061, 1369,87061, 2,87060,77387,87073,87071,87073, 3,87060, 87065,87079,87069,87079,84185,87079, 11,87079, 2,87061,77373,87089, 76635,87089, 7,87088,87079,87095,72519,87089, 3,87061,87067,87101, 85875,87101,77751,86635, 413,87106,77859,87109, 413,87107,77949,87113, 1216,87106,77857,87117, 1216,87107,78669,87121, 2,87107,79987,87125, 5,87127, 4,87126,87129,87131, 4,87127, 5,87126,87135,87137, 2,87106,79139,87141, 5,87143, 4,87142,87145,87147, 4,87143, 5,87142,87151,87153,79757,86635,80450,87157,80451,87157,80337,87157, 3,87162, 3,87163, 2,87157,79971,87169,79841,87169,79961,87169, 87167,87169, 3,87157,80337,87178, 2,87156,79967,87183,87179,87183, 87159,87183,87181,87183,87165,87183, 3,87156,87161,87195,87169,87195, 77751,86634,87195,87201,87169,87202,87198,87201,87187,87201,87178,87201, 87183,87211,87169,87201,87195,87214,87157,87201, 3,87218,87183,87221, 3,87219,87169,87225, 3,87201,87157,87228,87183,87231,87157,87229, 87195,87235,80336,80533,80515,87239,80501,87240,80498,87239,80519,87245, 80501,87239,80515,87248,80516,87239,80525,87239,80497,87239, 2,87256, 80519,87259, 2,87257,80501,87263, 2,87239,80497,87267,80515,87269, 80497,87266,80519,87273,77751,80533,79962,87277, 2,87279,79971,87281, 2,87278,79967,87285,80070,87277, 4,87289,80083,87291, 4,87288, 80079,87295,79968,87277,79967,87299,80080,87277,80079,87303,80498,87277, 80519,87307,80298,87277,80319,87311,80497,87277, 2,87314,80519,87317, 2,87315,80501,87321,80293,87277, 4,87324,80319,87327, 4,87325, 80301,87331,81857,87277,78453,87277,80233,87277,80445,87277, 8453,87277, 273,87277,84484,87277,85230,87277,84531,87277,85277,87277,21522,87277, 1516,87277,38266,87277, 948,87277,20239,87277, 1477,87277,37095,87277, 281,87277,84473,87277, 1011,87370,85215,87277, 903,87374,80242,87277, 80448,87277,80447,87277, 903,87382,80241,87277, 1011,87386,38057,87277, 903,87390, 165,87277, 903,87394,21315,87277, 1011,87398, 1505,87277, 1011,87402, 1216,87276, 412,87276, 413,87277,87409,87411, 1217,87277, 87407,87415, 413,87276, 1216,87277, 1217,87276,87421,87423, 412,87277, 87419,87427,12377,87277, 375,87277,57522,87277,67028,87277,67800,87277, 510,87277, 240,87277, 265,87443,77750,87445,77751,87444,87447,87449, 77751,87445,77750,87444,87453,87455, 264,87277,84517,87459,85263,87459, 81749,87459, 341,87459, 264,87276, 375,87469, 241,87277,81464,87472, 81465,87473,87475,87477,81464,87473,81465,87472,87481,87483, 1011,87277, 84473,87486,80241,87486, 1505,87486,21315,87486, 903,87277,85215,87496, 80447,87496, 165,87496,38057,87496, 483,87277,65869,87506, 9,87506, 9,87277,56555,87512, 483,87512,56555,87277, 9,87518,65869,87518, 65869,87277, 483,87524,56555,87524, 5,87277,84185,87531, 1011,87533, 2,87531,80532,87536, 3,87531,85215,87541, 3,87530,87539,87545, 85263,87545,84517,87545,81749,87545, 2,87530,87533,87555, 4,87276, 87531,87559, 2,87561, 3,87561, 2,87560,87565,87567, 3,87560, 87563,87571, 3,87277,85111,87575, 903,87577,87559,87575, 0,87581, 1,87580,87583,87585, 1,87581, 0,87580,87589,87591, 4,87575, 80532,87594, 5,87575,84473,87599, 5,87574,87597,87603,84517,87603, 85263,87603,81749,87603, 4,87574,87577,87613, 2,87276,85663,87617, 85100,87617, 9,87617,84767,87622,84767,87617, 9,87626,87575,87617, 4,87631, 5,87631, 4,87630,87635,87637, 5,87630,87633,87641, 2,87277,79962,87645,79965,87647,80497,87645,80515,87651,80497,87644, 80519,87655,79962,87644,79967,87659,87559,87645, 7,87663, 6,87662, 87665,87667, 6,87663, 7,87662,87671,87673, 4,87645, 1011,87677, 77751,87679,77750,87678,87681,87683,77750,87679,77751,87678,87687,87689, 4,87644, 265,87693,77750,87695,77751,87694,87697,87699,77751,87695, 77750,87694,87703,87705, 3,87276, 375,87709,87645,87709, 4,87713, 5,87713, 4,87712,87717,87719, 5,87712,87715,87723, 4,87277, 80070,87727,80077,87729,80293,87727,80315,87733,80293,87726,80319,87737, 80070,87726,80079,87741, 2,87727, 903,87745,77751,87747,77750,87746, 87749,87751,77750,87747,77751,87746,87755,87757, 2,87726, 265,87761, 77750,87763,77751,87762,87765,87767,77751,87763,77750,87762,87771,87773, 5,87276,87575,87777, 7,87779, 6,87778,87781,87783, 6,87779, 7,87778,87787,87789,87645,87777, 0,87793, 1,87792,87795,87797, 1,87793, 0,87792,87801,87803,87727,87777, 2,87807, 3,87807, 2,87806,87811,87813, 3,87806,87809,87817 }; const int s_nDataSize2 = 24772; unsigned int s_Data2[24772] = { 3, 9, 5, 6, 119, 796, 636, 113, 449, 235, 239, 105, 789, 96, 439, 624, 630, 230, 111, 110, 787, 786, 628, 627, 116, 115, 436, 435, 227, 226, 93, 92, 792, 791, 100, 99, 443, 442, 633, 632, 128, 183, 234, 178, 233, 85, 762, 203, 32, 742, 356, 169, 152, 12, 672, 741, 127, 168, 671, 740, 50, 352, 149, 64, 414, 197, 276, 751, 722, 396, 275, 434, 721, 785, 274, 795, 720, 448, 273, 719, 474, 758, 718, 392, 269, 748, 715, 400, 118, 794, 635, 81, 76, 750, 747, 597, 595, 91, 433, 225, 74, 745, 680, 565, 268, 476, 271, 761, 350, 678, 345, 567, 757, 471, 470, 563, 469, 561, 551, 461, 465, 706, 650, 714, 261, 332, 641, 708, 676, 542, 260, 458, 755, 314, 325, 658, 288, 349, 760, 654, 656, 564, 562, 644, 552, 642, 550, 259, 252, 254, 322, 311, 329, 109, 784, 626, 43, 395, 182, 55, 399, 186, 104, 447, 238, 41, 389, 173, 175, 193, 485, 580, 579, 734, 25, 733, 528, 548, 310, 546, 344, 526, 308, 560, 342, 525, 556, 558, 523, 524, 522, 520, 307, 622, 623, 431, 618, 620, 429, 617, 305, 615, 519, 518, 516, 778, 304, 250, 302, 776, 216, 218, 774, 215, 301, 300, 514, 771, 513, 541, 298, 512, 297, 535, 321, 508, 510, 319, 538, 539, 533, 507, 509, 296, 146, 705, 531, 537, 317, 557, 341, 143, 697, 555, 544, 339, 613, 426, 217, 773, 619, 428, 221, 780, 611, 610, 424, 609, 769, 423, 422, 768, 213, 625, 783, 670, 732, 782, 578, 577, 731, 484, 387, 668, 669, 171, 172, 375, 191, 575, 729, 482, 446, 667, 237, 574, 728, 481, 398, 666, 185, 573, 727, 480, 394, 665, 181, 572, 695, 694, 140, 738, 372, 246, 690, 689, 136, 244, 369, 767, 212, 766, 702, 701, 367, 257, 700, 315, 726, 382, 59, 407, 190, 52, 366, 157, 65, 417, 201, 63, 413, 194, 686, 692, 243, 248, 699, 256, 150, 354, 365, 364, 353, 156, 685, 348, 242, 661, 192, 409, 376, 378, 411, 164, 569, 717, 473, 391, 660, 177, 189, 406, 374, 371, 405, 162, 200, 416, 363, 362, 415, 155, 313, 324, 361, 360, 331, 312, 328, 381, 316, 330, 359, 323, 4596,24359,41366,41344, 4857,37718, 4594,24357, 4846,37706, 4678,26650, 4592,24355, 4844,37704, 4591,24354, 4843,37703, 8816,41900,22056,15422, 7473, 8464,42932, 8814,41898, 6804,20483,12853, 8462,42930, 8809,42808, 21978,15306, 7385, 8456,42895, 8807,41327,21965,15246,15293, 7372, 8454, 42893, 3212,20457,36983, 3516, 6187, 6184,20453,29352,10563,10421, 2593, 20452, 6183, 5637, 2589, 6182, 2645, 2619, 2283,26212,20199, 2269,12513, 2614, 2661,18113, 2288, 4777,35226, 4775, 4774, 4773,42536, 2198,32674, 32753, 8833, 8780,40027,43084,39938,43445, 8548, 8831,24157,26148,31156, 29057, 8503, 8771, 8777,24156,26147,36425,33823,40025,43073,43081,39936, 43443,22500,18803, 8829, 8770,40023,43072,39934,43438, 8546, 8827,24155, 26146,31154,29044, 8501, 8765,24153,26140,36424,33800,33820,40022,43066, 39933,43435,22498,18801,43065,40020,43434,39931,18800,22493, 8764, 8499, 26128,24151,33799,36411, 8826, 8544,26120,24146,29025,31141, 8762, 8824, 43063,40019,43432,39929, 2287, 2286,21235,26865,13688,26627,13207,20826, 2106, 2073, 4667, 4378, 1966, 4054,13206,20825, 2159, 2168,18699,39853, 10355,39675, 2167,39852,13205,18520, 2158,39674,20824,20823,42653,42280, 18519,10116,21390,13926, 2032,42279, 1932,42652, 2166, 2157,42651, 5184, 42278, 5035, 2070,21389,20822, 4377,13925,13204, 5034, 5183,13924,21388, 5033, 5182,39673,42650,39851,42277, 4221, 5142,18518,21387,18698,20821, 4220, 4982,10115,13923,10354,13203,39850,42276,39672,42649,20820,18697, 42648,39671,42275,39849,18517,21386, 4376, 5032,13202,10353,13922,10114, 4375, 5181,20819,18696,21385,18516, 4981, 5141,42274,39848,42647,39670, 5031, 5180,42646, 5140,42273, 4980, 4219,21384,20818, 4374,13921,13201, 5135, 5174,39653,42257,39831,42630, 5172, 5133,24141,26112,31138,29023, 5026, 4969, 4975,24140,26111,36408,33796,39651,42249,42254,39829,42628, 21363,18686, 5139, 5179,39669,42272,39847,42645, 5178, 5138,18515,20817, 18695,21383, 5030, 4979,10113,13200,10352,13920,39668,42271,39846,42644, 21382,18694, 5170,24183, 5169,36516, 5168,39992, 5167,22753, 5166,21404, 5165,39867, 5164,21361, 4045,26846, 4044,21215, 5162,39827, 5191,21359, 5190,39825, 5189, 5160, 5159, 4043, 5157, 5024, 1891,42248, 1847,42621, 4193, 4341,18472,20750, 1681,21357,10093,13145,13869, 2660, 7371, 2659, 2658,13144,20749, 1846, 1890,39824,18682,39649,10344, 1872,39823,18507, 13143, 1889,39648,20748,20747,42620,42247,10107,18506,21356,13868, 1871, 42246, 1843,42619, 2205,26240,26211, 2200,24249,24232, 2478, 2517,36625, 34562,31491,29570, 2507, 2558,34076,37229,29433,31635, 8704, 8600,35491, 38460,30352,32396,28999, 8171, 8335,38314,35364,32268,30297,30134, 8698, 8591,35488,38453,30345,32384,32389, 8166, 8333,38305,35357,32255,30292, 2285, 7325, 1898,14098, 1896, 1895, 1894,39359,24288,41706,41800,20017, 37217,39357,36575,18022,26236,20013,24246,39355,39925,18013,18779,20001, 22482,39395,20196,39397,20208,40017,39923,20064,42324,12370,42658,19065, 18776,41387,41382, 9904,21392,10687,10412,41365,41360,18055,18053,39685, 20893,39857,18775,43056,43431,42334,18524,42660,22479,40016,39922,14502, 15946,39376,39374,20062,20060,21649,22478,39380,39378,12368,18702,43055, 43430,18057,39680, 9906,39855,39991,21351,22752,39816,39990,39815,22751, 21350,39639,39814,33754,42230,28989,42602,18468,18677,24118,26056,31087, 28988,10090,10312,10318,24117,26055,36340,33753,39637,20700,20705,39812, 18675,42228,42600,42219,42225,18464,42598,21348,39635,39810,13101,13106, 13844,26054,24116,33752,36339,20699,21346,26053,24115,28987,31086,42218, 42595,36338,39633,31085,39808,39667,39845,39666,39844,39665,39843,18693, 18692,10351,10350,18514,39842,13199,13198,10112,39664,20816,20815,10111, 18513,42270,42643,13919,21381,13918,42269,21380,42642,39806,21403,21344, 39866,39805,39865,21343,21402,39804,21342,21175,26830,39802,21173,26826, 21340,39346,24061,39338,32626,39333, 9843,39332,39331, 9814,39328,15936, 39183,11746,19744,25614,39182,39181,39180,19836,42268,11903,42641,17932, 17931,40961,40960, 9771,21379, 9770, 9769,40959,40958,17930,17929,39663, 20814,39841,17928,40957,40956,42267,18512,42640,19835,39179,39178,11902, 11901,39177,39176,19834,19833,19832,19831,39175,39174,11900,18691,40955, 40954,17927,39662, 9768,39840,39173,19830,11899,17926,40953,13197, 9767, 40952,20813, 9766,17925,40951,11898,19829,39172,11897,42266,19828,19827, 42639,11896,40950,21378,13917,39171,39170,39169,39168,14088, 3310, 3309, 35263, 2276,26305, 5245, 6267, 5248, 5445,10636,10624, 5401, 7751, 5390, 5674, 2548, 5410, 3350, 3931, 3971, 3960, 6123,28071,22800, 8025,27598, 16338, 7478,22061,15427, 3847, 3840, 3822, 5835,26825,21172, 7148,26571, 13617, 6808,20693,13100, 3469, 3729, 3618, 6021,27993,22666, 7965,27534, 16152,16158, 7368,21963,15285,15291, 3513, 3757, 3655, 6026,28010,22688, 7970,27539,16193, 7376,21969,15297, 3722, 3611,27986,22657,22659,16147, 3608, 3610,25575,25569,25573,25568, 2720, 2722,23945,23941,23943,23940, 3606,26233,26200, 2718,24244,24224, 3603,22654,16143, 2716,22466,15931, 8720, 2547, 2499, 2498,35234, 8719,35524, 7050,35233, 6181,20028, 5622, 20027, 5610, 7023,23939,24648,23938,24484, 5952, 7920,22462,25567,27390, 15928,25566,27757, 5620, 7027,36388,33781,31116,29009, 5970, 7936,33795, 36407,29022,31137, 5612, 7025,24121,24653,24129,24494, 5960, 7922,26081, 27412,26074,27796, 5601, 7014, 6501, 5946,27753,22458, 7917,27387,15926, 4317, 7284,21850,15156, 5825, 5940, 5824, 5794, 7123, 6732, 6038,28015, 22709, 7982,27551,16225, 7395,21983,15311, 8718, 5673, 7049, 8717,35523, 23937,21560,14272,15352,40871,22739,16272,23936,22733,16263,14776,40870, 21558,14265,23935,21474,14087,15148,40869,22445,15906,23934,41714,40868, 34075,23933,34079,40867,41730,23932,41537,31827,37396,23931,41448, 4494, 23930,41503,23929,26451,38349,32305,23928,24323,23927,40866,31785,37351, 23925,40858, 4472,23924,40862,23923,40853,38197,23920,23919,38475,23914, 23913,38152,23908,40840,28843,38481,23905,23904,23903,23902,23901,23900, 23899,23898,23897,23896,40839,40838,23895,23894,40837,40836,23893,40835, 23892,23891,40834,40833,23890,40832,23889,23888,40831,40830,23887,40829, 23886,23885,40828,40827,23884,23882,40823,40826,40822,23879,23878,40819, 40818,23877,23876,23922,23875,23874,32490,32499,23873,23872,32793,23871, 17197,23870,23869,29043,33819,24320,40817,29655,38507,24317,24309,28839, 33590,23867,23868,23865,40816,25558,25555,23866,40815,23860,23864,21472, 14085,40814,22439,15900,25548,23863,40812,23859,23856,40811,40805,40808, 23858,33581,33583,23854,23881,33580,33592,23853,23852,19635,33579,40804, 23848,23844,33560,33558,35258,40795,23843,33557,33556,35255,25392,23842, 33555,33554,23841,24131,24133,23789,17857,23787,18134,25390,26230,23785, 25387,26229,26199,23783,23782,23781,23780,23779,23778,24120,24128,23777, 17845,23775,27731,25366,18759,23762,23761,23760,23759,23758,23757,23851, 23847,40801,40803,23850,33457,33578,35260,23849,33572,23756,33456,23755, 25328,18750,10402,24219,24218,24217,24239,41600,41620,24216,24215,24238, 29171,33958,24221,24241,24214,24237,24213,24236,24223,24243,24231,24248, 24235,24212,41619,41599,24580,24740,24486,24650,24479,24643,24493,24652, 24536,24696,24535,24695,24534,24694,24533,24693,24640,40701,30096,38438, 24638,24477,35149,24692,24532,24054,24053,24052,24051,24050,23803,17878, 23801,25476,23799,23798,23797,33549, 3281, 2981,35267, 2427, 2429, 2425, 2424, 2495, 7047, 7649, 2423,21521,14156, 2422,35247,23754,40705,23741, 40684,40700,23725, 4338,40674,23724,40673, 7842, 7748, 7750, 7746, 7745, 7744, 7761, 7758, 7769, 7651, 7653, 7648, 7647, 7646, 7645,21520,14155, 6300,21670,14601, 7644,35246, 8354,35392, 7811, 7809, 7813,37284,31745, 7771,36483,31210, 7788, 7802,36473,31194, 4186, 4465, 4184,13064, 4181, 4180, 4236, 4246,23721,39799,39630,23720,18459,23719,10083,18671,39628, 33435,13819,10309,39797,28701,21329,36039,30815,42588,42206,25299,25298, 13062,42586,20667,20672,42197,42203,23718,21332,13824,33434,42590,28700, 42208,30814,36038,25297,20676,13069,39022,22404,15866,17830,43413,13837, 9689,43025,21338, 9687,17828,40683,11384,19518,39000,11387,42593,21639, 19521,42214,14460,40699,20689,13087,24049,24531,24691, 4190,23717,22449, 15912,25296,20692,13099,23753,22427,15895,25337,20666,13060,23716,22403, 15865,25288,20665,13059,13584, 4199, 4197,23711,19508,11363,25282,20745, 13140, 9063, 9396, 9184, 9168, 9338,38785,32799, 9254,23359,17393, 9336, 38782,32791, 9247,23353,17357, 9344,38793,32809, 9282,23387,17431, 9456, 38858,32878, 9094,23244,17141,23710,21540,14212,15278,40657,22649,16130, 2758,21538,14208, 3347, 5771, 1853, 5082, 1788, 4966,42481,42234, 1708, 26963,42233,26591,42480, 1852, 3346, 3345,42479,37847, 1851,37846, 1835, 13635,42478,42232,37845,26590, 1785,10346, 1834,35043, 1833,37844,13634, 6891,27206, 6890,42477, 6889,37843, 5951, 5949,22464,27759, 5930, 5929, 22774,28067, 5928, 5927,20495,26455, 5926, 5925,26249,26192, 5924,26307, 5934, 5932,27724,22402, 5923, 6119, 5922, 7262,27717, 5920, 6917, 6277, 5918, 5917, 5916, 5915, 5914, 5954, 6118, 6927,27234, 6888,42759,27205, 29027,43024,42739, 8746,29048, 8768,43069, 6886, 6887,27204,42738,28699, 43023, 8745, 8742,43021, 8741,43020, 8740,43019, 8784,43196, 8739,43018, 8767,43068, 8523, 8744, 4957,42196, 5672,42195, 4956,42194,24230,42193, 33939,33938,24127,42192,33769,35199,24492,42191,35198,33768,24688,20662, 24528,20661,24048,41181, 4990, 4842,42304,37700, 5671, 5670,42303,37699, 2546, 2545,37881,42519, 5669, 5668,37880,42518, 2544, 5667, 5666, 4137, 5106, 5104, 5072, 5070, 5074, 5076, 5068, 5067, 5066, 5065, 5064, 5063, 5100, 5096, 5095, 5094, 5084, 5062, 4634, 5061,42190,28698,42457,26562, 4635, 5091,42302,26982,42517,26626, 4666, 5090,37879, 4989,13687,42301, 42516,37878,26981, 4665,10365, 4136,35060, 5089,42515, 4988,26625,42300, 42514,26624,26980, 4664,42299, 4135,26979, 5088, 4134, 4987, 4663,42298, 42513, 2163,37877,13686, 2162,42512, 2150,26623,37876,10364,35059,13685, 2161,42297, 2142,37875, 2140,42511, 2149,42296, 5087, 4986, 1917,26978, 42295,26622,42510, 2148, 4848, 4862, 4827, 4826, 4841,37698, 4882,13463, 42509,42294,37697,26621, 4840,10189, 4881,34876, 4839,37696, 4880,13462, 37874,13684, 5086,37695, 4985,13461,42293,42508,37694,26977, 4838,10188, 4879,34875,23729,34834,40698,40656,23709,34880,40655,41381,24211,34827, 41560,41559, 4874,34826, 4876,34861, 4892,34905, 4878,37693,13460, 4898, 37778,13508, 8353,35391, 8390,35436, 8581, 8534, 8602,38462, 8683,38525, 15448, 8641,38478, 8579,15277,38435,15138,33431,16652,33730,33429,34560, 29423,29381,40645,41866,33391,26227,33910,40643,18131,33513,11326,11531, 33511,28664,40769,33510,40787,33508,28642,40785,33751,18774,41232,27772, 33679,28943,12118,40634,40633,33677,28941,40629,40632,40628,33675,28936, 41598,41618,33605,33597,33360,33359,33358,33357,33787,39161,39321,39320, 36288,34527,26330,41849,18165,34522,26325,33349,34055,41845,18161,34536, 39160,38969,23693,41793,39327,39626,32091,42030,33307,32090, 4703,33453, 28723,25230,25229,33306,28623,26436,26446,33608,33305,40807,35522,19640, 33304,40825,35232,19645,33303,34053,33301,34044,34048,33298,41691,33296, 41683,41686,33295,33536,33540,33535,33292,33287,33282,33286,33935,33933, 33279,40631,33711,41180,33709,41173,35230,19918,33708,41172,35520,19917, 33707,41171,33577,28797,33278,28611,33892,29148,33886,29144,33277,28610, 33276,28609,33275,28608,33274,28607,33291,28620,33273,28606,43071,33822, 43437,35917,33272,28605,36118,33548,30917,35916,33484,35981,35979,30906, 28760,30775,33546,36116,33383,36083,28645,33367,28749,33482,33271,35915, 36081,30729,33270,28604,39412,30728,39470,35914,33309,33311,39410,39456, 18196,25216,28625,35913,39468,39505,20324,25215,30734,41748,35944,41830, 23695,23697,28638,39458,33331,39507,25232,25234,30736,33269,41797,41832, 18192,23675,35964,35966,41701,41752,20319,23674,35912,30727,41697,28603, 41792,33268,33267,28602,36620,34558,31487,35911,33425,33427,36622,28601, 37113,31476,28689,35910,31489,33266,34471,37010,34556,30813,36021,36023, 29384,34420,37214,28675,33409,33411,31478,37012,30791,33265,29426,35909, 37115,34422,36005,36007,34066,30726,34473,29386,35908,30725,34068,37210, 29428,33264,39067,39069,23701,30724,23703,35907,23673,39065,33386,25214, 23672,39063,28670,25213,36000,30777,40776,40768,25250,25252,33263,40764, 28600,40762,33262,28599,43013,30723,43400,35906,23671,21636,22383,25212, 14454,15824,15837,33740,28975,43052,33261,43429,36320,33739,28974,43051, 31074,43428,36319,24075,31084,21648,28986,22477,26012,36329,14493,33749, 15945,43398,43011,22377,15823,14439,21634,26052,24114,33366,33365,28644, 33480,28747,36111,33529,30902,36079,33473,33260,33259,33972,33258,33553, 33285,28618,41597,41617,33284,33970,33294,33539,33528,28778,11448,40591, 40590,33526,33525,33524,33523,39058,39057,23835,30901,23815,36110,33479, 25517,28746,25494,40753,40752,33538,28787,40610,40608,33522,33780,40589, 42861,23670,33778,35362,33256,35344,33254,33463,34043,29414,41685,41783, 34041,29411,26400,26365,34040,41682,34039,34052,29420,34038,29410,34037, 29409,34065,34064,29425,34036,29408,39406,31565,39466,37204,34456,39450, 18188,26395,37101,39499,20313,26360,41742,41824,24283,24274,29519,34552, 31485,41780,36616,41681,34035,29407,36615,34551,31484,37203,34455,29376, 37100,31472,34411,37003,34047,29418,41695,41790,34046,34050,34034,34073, 34032,33930,33941,29158,33932,29155,33929,29153,33798,41083,18043,35223, 35283,35285,35154,35225,35169,30109,40588,40587,35146,30088,22376,15822, 35144,30086,22374,15820,35142,30084,22372,15818,39529,39623,35148,35209, 39159,35167,39318,35262,30208,40586,40585,35254,30204,41614,41595,35257, 30206,40794,40799,35162,40709,18758,34825,35269,35266,10793,10619,35245, 10783,10561,35251,35243,35242,33724,33728,33722,33721,33968,34685,29738, 40704,40703,34727,29780,41380,41359,34710,29763,20739,40561,13138,40560, 34684,29737,20657,40559,13052,40558,33851,27196, 9902,42736,26993,36435, 42547,42321,12366,27711,36437,43010,33439,42468, 9680,42735, 9685,36043, 11382,33445,11374,42216,36041,43009,33849,37911, 9900,42734,35066,36431, 37907,33847,12364,27710,36433,43008,35081,12602,37746,35083,35007,31772, 37338,35022,35015,35047,35005,35004,35003,35002,35001,35000,10302,35071, 10368,35013,35012,35011,34999,10301,13577,37817,34998,42180,10300,28558, 17770,37820,19393,34996,13579,42450,37818,26546,35045,35058,42292,10363, 26976,10362,37873,13683,35057,13682,42507,37872,26620,35056,37692,10361, 13459,34874,37871,37691,35055,13681,10187,37870,34873,35054,37869,10360, 13680,35053,37868,33660,25733, 9805,40999,26975,36216,42506,42291,11876, 25732,36215,40998,33659,42505, 9804,40997, 9803,36214,11875,33658,11874, 42290,36213,40996,33657,37867, 9802,40995,35052,36212,37866,33656,11873, 25731,36211,40994,33655,37690, 9801,40993,34872,36210,37689,33654,11872, 25730,36209,40992,33496,34824,18484,18433,34860,34891,18526,34871,42289, 10186,26974,10185,37688,13458,34870,13457,42504,37687,26619,34869,37686, 10184,13456,34868,37685,34922,37771,10204,13501,34915,37764,35355,41246, 40557,24074,35361,40556,41290,23645,35390,35394,35388,35387,35423,35431, 35421,35420,35419,34424,34430,29390,34410,29375,34409,29374,34408,29373, 43003,34454,43397,37099,34419,34418,29383,34554,25244,41863,17813,34550, 27709, 2281,26243,26215, 2280, 2279,26242,26806,26214,26542,23643,17768, 9617,19682,25590, 9615,11631,25602,17766,11650,19701,23641,24043,17975, 9857,19915,25886, 9855,12116,25884,17973,12114,19913,24041,24525,18827, 24685,10438,18963,10587,18825,10436,24523,10585,24683,18961, 2443, 2442, 18824,26805,10435,26541, 2441,21154,13576, 9256,38787,32802, 9246,38781, 32790, 9253,38784,32798, 6490, 6682,39661,39839, 6676, 6675, 6674, 6673, 6672,39158, 6697,23640, 6775, 6783,36532,31231, 6580, 6579,18960,26804, 10584,26540, 6578,21153,13575, 6857,38536,32501, 6867,38538,32503, 6855, 38534,32498, 6822,20490,12860, 7477,22060,15426, 6814,20485,12855, 7472, 22055,15421, 8988,38813,32831, 8677,38488, 8239,38346, 6280,21655, 6279, 21654, 6320,23639,23638,23637,23636,40555,23635, 6274, 6315,38953, 8751, 8823, 6245,23632,23631,14039,20651,37335,31769,15808,34822,24166,24163, 37375,31808,23727,25314,39344,39342,23630,14031,25171,15799, 6241,42999, 8753,42998, 6240,42997, 6239,42996, 6238, 7605, 7603,21633,24145,14431, 24150,23743,21632,14430, 7577, 7576,21645,23768,14481,23764, 6237, 6236, 21631,42614,14429,42241, 6235,21630,14428,24073,24072,24071,24070,41264, 24069,24066,24065,37331,31766,24064,26009,24063,21647,14491, 8775,43079, 8774,43078, 8737,42995, 7643,21669,14595,23622,21711,14828, 7827, 7826, 21710,23621,14827,23620, 7824,21709,14826, 6347, 6349, 6351,38519,32485, 6362,38530,32492, 6364,38532,32494, 6358,38528,32489,18365,24583,18606, 18598,18597,18596,42444,37811,24657,24497,24634,24469,35138,24040,24039, 24522,24682,24681,24521,24578,24738,39405,39465,41680,20283,41779,18147, 18187,41741,20312,39449,41823,39498,24520,24680,24679,24519,24038,24037, 39157,39156,40949,19826,40948,17924,23619,23846,24202,35241,41126,33720, 25977,35386,41125,33719,25976,33718,41124,24482,24646,23834,23814,19058, 10678,43037,36075,43422,30854,19057,10677,42994,35892,43396,30674,15796, 22352,24144,24149,23613,23612,19134,10762,42990,37248,43394,31694,18444, 10075,18466,10092,18432,10073,18431,10072,18552,10124,18550,10122,23611, 23610,24036,24035,24518,24678,24677,24517,18454,10080,23609,23608,22370, 22368,15817,18448,25149,25148,18744,18741,10391,20660,23752,23751,22426, 22425,15894,18430,25336,25335,18757,18756,10405,20648,24161,24159,22349, 22348,15794,18522,26155,26150,18733,18732,10388,20880,35161,40708,34821, 25334,18505,10106,18494,10104,23607,23606,19397,19395,11212,18488,25147, 25146,17776,17773, 9620,20742,18381,38855,18383,23136,18385,38407,17765, 38850,17764,23121,17763,38405,17762,43195,17839,43034,17985,42989,17984, 42731,28965,42744,31065,17998,28977,19979,31082,42988,19997,43054,18379, 37275,17761,42173,28551,26945,42439,42170,28550,26539,30673,42436,42437, 19380,26536,26537,17760,42307,28549,30672,19379,42537,17759,42176,28548, 26948,37814,17758,34994,19378,30671,42446,19377,37812,17757,42746,28547, 30670,19376,43059,18265,10019,18264,10018,42987,20311,43393,18186,18921, 18906,18919,18915,18807,18731,38831,18730,23104,18729,38403,18869,18878, 18890,18823, 1666, 1701, 1613,22346,27707, 5904,15787,15792,27365, 7899, 15124,15129,21836, 7255, 1669, 1704, 1616,22339,27700, 5897,15785,27358, 7892,15122,21829, 7248, 1664, 1699, 1611,22772,28065, 6116,16309,27593, 8020,15404,22040, 7459, 1663, 1698, 1610,21183,26835, 5820,13632,26587, 7143,13137,20738, 6799, 1829, 1839,37855,42487, 1838, 1828,42486,37854, 2028, 2063, 1963,40545,40543, 2030, 2065, 1965, 2026, 2061, 1961, 2025, 2060, 1960, 2154, 2146,37897,42535, 2153, 2145,37896,42534, 1827, 1837, 37853,42485, 1662, 1697,21182,26834, 1622, 4117, 7502, 7272, 7274,27373, 27378,27730,27742,17756,17854, 7245,27355,27697,18094, 7287,27392,27763, 6313, 7244,27354,27696, 6266, 7243,27353,27695, 6311, 7242,28038,27694, 7421, 7241,27352,27693, 6335, 7267, 7266, 7265, 7494,23605,23604,25145, 25144,23603,25143, 7324, 7323, 7322, 7321, 7320,20812,13196, 7319, 7318, 21377,13916, 7317, 4373, 7238,26225,26196, 8973,23120,16979, 8991,23130, 16996, 7361, 7359,33574,27527,28795,27980,30929,36127,23669,25203,23595, 25135,23750,25342, 8946,23103,16963,18369,38399,17755,38397,18727,38395, 39660, 8200,39838, 8199, 8198, 8197, 8196,39155, 8195, 8452,38335,42884, 8140, 8431,38284,42842, 8238, 8459,38345,42916,17754,17853,18767,18068, 4795, 4925,37367,42056, 4484, 4737,42533,37895, 4794, 4924,37366,42055, 4483, 4736,37894,42532, 5148, 4829,39792,26808, 5188, 4825,39864,26903, 39989,27146, 4804,37381, 4788,37328, 4856,37595, 4824,37717, 5146, 4855, 39788,26801, 6299,27264,27094, 4457, 7316, 4456,27091,27262, 6297, 4299, 4454,27752,27386, 7280, 4453,27978,27525, 7357, 4452,28047,27577, 7432, 4451,27140,27285, 6329, 4450,27692,27351, 7237,13569, 4475,27089,27259, 6295, 6696,21031,13404,34709,29762, 4560,34755,29808, 4581,34683,29736, 4540,33871,35166,33467,24062,23862,25554,23594,25134,23714,23713,25286, 4462, 4464, 4447, 4446, 4445, 4444, 4443, 4442, 4441, 4490, 4488, 4440, 4439,34673,29726, 4521,33234, 4460, 4438, 4471, 4714, 4116, 4473, 4716, 4119, 4497, 4755, 4167, 4493, 4495, 4753, 4165, 4466, 4711, 4111, 6367, 21723,14912, 6860,21744,15033, 9259,23362,17407,23593, 6328,21692,14780, 6339,21695,14794, 6324,21690,14774, 4486, 4739, 4149, 4482, 4735, 4147, 14023, 4480, 4733, 4145, 4479, 4732, 4144, 4793, 4923,37365,42054, 4807, 37432, 4864,37753, 4806, 4936,37431,42088, 7907,23592,42849,23591,42851, 23590,42847, 8458,42915, 4918, 4916, 4911, 4910, 4909, 4933, 4932, 4931, 4908, 4907, 4914,33979,42019,18138,33978,33765,42018,18021,35195,35194, 42017,18787,33764, 4922, 4792,42053,37364, 4747,26177, 4701,26259, 4705, 4704, 4700, 4699, 4698, 4724, 4726, 4741, 4152, 4707, 4109, 4697, 4101, 4696, 4100, 4695, 4099, 4694, 4098, 4693, 4097, 4745, 4156, 4749, 4162, 4751,25133,24475,35152,24229,33977,24126,33763,24491,35193,34428,29388, 37024,34477,31481,37194,37023,31480,42016,37193,42435,34476,18270,10027, 26730,20331,26939,18213,20344,12777,42015,18212,42434,20330,18798,10416, 26729,20025,26938,18796,21497,14105,42014,18038,42433,21501,18025, 9892, 26728,21500,26937,18037,20021,12308,42013,18795,42432,20024, 4927,42065, 4906,42012, 4935,42087, 4159, 4161, 4096, 4095, 5108,35087, 5099,35070, 5057,34992, 4094, 5661, 4092, 5336,14586,14141,11159,11144, 4091, 5658, 4090, 5522,14874,14302,14990,14331, 5862, 8892,17350,17552, 4089, 4088, 4087, 5339, 4103, 5225,14403,14016, 5549,35329,26162,10521,41333,26658, 38425,42315,42540,15112,26160,38424,41335,33653,25729, 9800,40991,26618, 36208,42288,42503,11871,25728,36207,40990, 4791, 4921,37363,42052, 4478, 4731,21062,26749, 4143, 4142,37893,42531, 4053, 4052,21234,26864, 4790, 4920,37362,42051, 4477, 4730,21061,26748, 2152, 2144,37892,42530, 2059, 2024,21233,26863, 4141, 4051, 1959, 4140,35970,21026,19466,37325,19470, 37594,35973,20647,36795,37324,20288,21025,20446,20646,37216,37593,36757, 37592,20286,20645,20426,21024,37208,37323,36392,41275,36391,41274,36390, 41273,36562,26297,36140,27688,36146,27687,37256,36530,36566,21023,20236, 37322,20194,37591,36542,20644,36570,37273,38249,36136,30938,42243,33227, 42616,33585,35886,30656,42245,33587,42618,33226,35885,30655,43077,28533, 43442,33225,36062,30839,43032,28725,43420,33455,35884,30654,42323,28532, 42657,33224,35963,40621,35883,30653,28530,41592,37231,31646,37228,31634, 37227,31633,37226,31632,37225,31631,36387,31115,36386,31114,36385,31113, 36384,31112,36134,40810,36142,40821,36071,40723,42984,38423,38141,32157, 38140,32156,38139,32155,38149,27088,38109,42750,38108,42749,38107,42748, 38187,27117,38186,27116,38100,42743,38088,27686,38247,38185,27115,38191, 27124,38214,27132,38159,27072,38158,32171,38157,32170,38156,32169,38228, 27110,38222,32183,38091,32101,38138,27063,36315,41193,31056,36314,41192, 31055,36313,41191,31054,36317,41195,31058,36312,31053,36311,31052,36310, 31051,36488,36486,36503,36501,37279,38775,37277,23368,37238,21750,37281, 21729,38738,38749,38748,38747,38746,38867,37264,27685,37262,31730,42983, 29628,43392,34603,37271,21705,37267,27297,37266,21703,37261,21701,36206, 40989,40988,36205,36204,40987,11870,25727,37684,13455,36203,40986,11869, 25726,37865,13677,36202,40985,11868,36078,42982,36077,40791,11447,37590, 37321,37589,37320,37588,37319,37587,37318,37601,37727,37586,37585,38474, 27258,38427,42992,38441,43041,42981,38422,38491,38421,40661,15111,25290, 37828,13590,37018,41853,37017,41852,37016,41851,37014,41847,37022,41855, 36427,41329,37904,42542,20055,26153,42839,38280,36037,40659,42464,37830, 19498,25285,42838,38279,36429,41331,27347,21820,20057,26158,42837,38278, 37832,42467,37810,42431,37809,42430,37825,31965,37834,31981,37808,31952, 37807,31951,37806,31950,37805,31949,37804,31948,37917,37915,37803,37802, 37901,37900,37801,42429,37800,42428,37799,42427,37910,42544,37909,32040, 37903,32034,37891,42529,37361,42050,21232,26862,21060,26747,37890,42528, 42049,37360,21231,26861,26746,21059,37889,42527,21230,26860,37888,42526, 21229,26859,36250,41019,31021,36249,41018,31020,36248,41017,31019,40536, 36252,41021,31023,36246,41015,37359,42048,19815,25716,41014,36245,36244, 41013,42047,37358,19814,25715,41012,36243,36242,41011,37887,42525,19813, 25714,41010,36241,36240,41009,42524,37886,19812,25713,41008,36239,36238, 41007,25712,19811,19810,25711,41006,36237,38303,27404,38277,32219,32089, 31946,38295,32233,38293,32229,38301,32251,38313,32267,38312,32266,38311, 32265,38310,32264,38316,32270,38322,27497,38321,32275,38320,32274,38319, 32273,38348,32304,37330,37597,39790,37599,37315,37576,39863,37575,39988, 37574,37314,37380,21016,21068,20643,20887,37573,37716,37379,37715,39787, 37714,37313,37312,37393,37311,31761,37371,31804,37429,31832,37334,37333, 31768,37340,31774,37317,31763,37373,31806,37310,31760,37309,31759,37308, 31758,37307,31757,37306,31756,37305,31755,37342,31782,37304,31754,37395, 31826,37357,42046,21058,26745,37356,42045,21057,26744,37384,21073,20905, 37725,37383,42080,21072,26757,36539,31236,42240,33909,42613,33908,36552, 36554,41277,27230,41843,41861,41231,32116,41230,41229,41228,40619,41868, 26318,41870,26320,40616,41138,41136,41859,41151,41140,40535,21494,14101, 23589,22490,15957,40534,22327,15761,11105,12188,25952,21433,14012,41188, 42876,41187,42788,41186,41198,41197,41185,41184,41183,41190,22326,15760, 25107,21432,14011,40532,21476,14091,25705,22469,15935,40531,22471,15939, 25961,21478,14093,40530,40528,40529,40526,40524,40522,40521,40546,40520, 40525,40519,40517,40518,40515,40513,40511,40510,40516,40509,40544,40508, 40527,40507,41533,40506,41451,40505,41499,40504,26449,40503,25565,42936, 22325,41892,27294,40502,40500,40501,40498,40497,22354,40496,27209,40495, 40494,40493,40492,40491,40490,40489,40488,40487,40486,40485,40484,40483, 40482,40481,40480,40479,40478,40477,40476,40475,40474,40473,40472,40471, 40470,40844,40873,40842,40469,40468,40467,40731,40727,40726,41525,41516, 41491,41482,41440,41413,41439,41412,41515,41524,41481,41490,43735,22324, 15759,16624,28157,21431,14010,43733,32591,21430,14009,28150,22323,15758, 43855,22322,43755,43758,43761,43764,43754,43757,43760,43763,43720,43719, 43718,43717,43716,43715,40425,40428,21429,14008,23586,22321,15757,40421, 40427,40420,40539,21428,14007,25691,22320,15756,40538,40419,41106,41105, 41104,41103,41102,41101,41100,41099,41098,41097,41096,41095,41094,41093, 41092,41091,41624,41622,41170,41169,41155,41150,41149,25938,40466,41386, 41364,41377,41358,41385,41363,41376,41357,41362,41384,41356,41375,40682, 40681,40697,40696,40680,40695,42655,42309,42637,42264,42636,42263,42635, 42262,42612,42239,41840,41839,40760,40781,40751,40750,40749,40748,40747, 40746,40745,40744,40743,19610,11499,40767,40742,19609,11498,40922,40921, 40920,40919,19824,11893,40806,19637,40824,19642,43451,43494,43383,43382, 43381,43426,43425,43403,43406,43493,42869,43492,41082,43497,25564,43543, 26448,43380,27232,43418,27208,41130,41128,41123,41122,41121,19910,41120, 19909,41119,21668,14585,25832,19949,12173,41118,21519,14140,25831,19948, 12172,40717,21471,14084,25676,22424,15893,40716,21470,14083,23749,22423, 15892,40715,21469,14082,25333,20638,13037,40714,40713,21468,21467,14081, 18429,25332,25331,18755,18754,10404,20637,43096,43094,43089,43552,43379, 43378,43391,43377,43405,43402,43376,43412,43411,43410,43050,27771,43049, 27770,43154,43150,43147,43146,42787,42875,42786,42791,42879,42790,42878, 42785,42874,42784,42873,42783,42872,42797,42800,42887,42799,42886,42804, 42889,42806,42891,42796,42883,42795,42882,42794,42881,42756,42863,42773, 42771,42766,42151,26932,42150,26931,42149,42148,42147,43496,43152,43542, 43214,43417,43030,42146,42578,43375,42972,42145,26304,42144, 8714,42143, 4292,42142,41168,42213,26958,42212,26957,42211,42592,19520,28500,11386, 33192,42172,26944,42175,26947,41865,40982,40981,36199,25725,40980,33652, 36198,41589,38420,41594,26258,28531,41575,30651,28499,28529,30616,41573, 28498,26256,41591,41588,26253,29448,41570,31341,29251,41587,37002,26222, 41569,34280,36861,41579,41583,42426,42003,42441,42021,42422,42001,42421, 42000,42420,41999,42419,41998,42418,41997,42549,42554,42417,42416,42415, 42414,42413,42461,42460,42466,42035,42463,42033,42157,42424,42141,42412, 40979,40978,25668,42855,26110,42918,25092,42853,42871,42934,22317,42082, 25091,41996,26252,41995,41994,42037,43149,43093,42770,43091,42768,42068, 26182,43088,42765,42067,41993,41992,41991,41990,41989,41988,41090,42493, 42031,42411,42455,41986,42410,42058,35228,41985,33976,41984,33762,41983, 35192,41982,42064,26720,26751,42079,26756,41556,41555,41554,41553,41552, 41551,41550,41549,41548,41547,28954,36303,29445,28595,30719,28949,31037, 31036,28948,29138,29146,42040,18503,28890,11603,42085,18546,29136,12591, 28992,34983,33191,33607,28497,28496,28495,30615,28494,30614,28598,30722, 28597,30721,28493,40722,28492,43040,28938,33362,33190,28940,28933,33521, 28882,33189,28885,28491,33576,28490,28489,34058,28488,43036,30613,28487, 33738,43048,30612,28486,33188,33589,30951,30611,36138,35850,37007,33187, 34415,37109,35849,34465,37206,33186,33354,35968,35848,34061,36115,33185, 33364,35978,35847,33545,36598,33184,33281,35919,35846,33986,37009,33183, 34417,37112,35845,34470,37005,33182,34413,37103,35844,34460,36002,33181, 33988,36600,35843,33389,36004,33180,34063,37213,35842,33408,35921,33179, 33533,36113,35841,33289,29190,34982,29185,31274,29184,33907,37001,33984, 34407,37098,36596,34453,37212,33407,18346,19496,28643,33544,28617,28614, 28485,28484,28483,28673,28481,28479,29406,31544,29413,33178,34458,29378, 33352,37000,34029,34406,37097,37202,34452,29424,33406,34469,29382,29417, 29281,29422,29317,29405,29250,28838,28836,37849,42483,28814,30940,28478, 28477,37842,42476,28476,30606,28475,28474,38452,43058,28473,30605,28472, 28471,42453,37823,28739,28734,38419,42971,29679,43208,29678,43207,31729, 29627,33177,43206,31728,29626,29677,29650,43205,38505,28776,28775,42970, 36999,33520,34405,37096,36109,34451,35977,33543,17815,19590,28786,28783, 28774,28772,28771,30898,28770,28769,42474,37840,29623,12817,34588,34600, 31712,31658,37250,37234,37236,37269,29630,29589,34609,34590,33919,33906, 33913,33905,42969,31273,29183,33904,31235,36538,33925,31246,36556,36588, 29160,33943,37105,34462,18195,20323,37111,34468,18199,20327,37192,34475, 34981,37798,37021,34427,37199,34486,34447,37041,37036,34442,37198,34485, 34446,37040,37035,34441,37197,34484,34445,37039,37034,34440,37196,34483, 34444,37038,37033,34439,29372,42968,31543,29404,33981,31196,30367,30203, 30366,41981,18427,30356,14108,42029,18442,30336,14049,43491,18868,41980, 32456,32455,30380,30282,32249,32248,37303,10546,37572,14501,20624,30273, 35009,30290,34980,30280,30107,30279,30106,42967,38418,34593,34595,19025, 34597,19027,34592,19023,35427,30962,17897,28470,17732,38480,19333,35429, 19649,30604,38482,28844,35458,30603,17731,29656,18373,38508,20466,35444, 19332,31721,38493,28469,35460,31660,18367,29663,18375,38516,20472,35448, 20459,31725,38495,29587,28963,35440,31716,18371,30078,18726,38490,21427, 35454,20463,32088,38502,29646,29661,38512,29659,38510,34979,37797,17730, 19331,34977,37793,37795,35338,30602,17729,30097,18746,38439,21463,35336, 19330,32099,38437,28468,29180,29178,35416,31261,18112,29162,38477,20192, 35434,31268,18127,29166,38486,20217,35328,31264,18119,29164,38417,20198, 35327,31092,18019,30124,18785,38416,21482,35326,20004,32123,38415,28995, 34436,37030,18144,20280,34399,36995,29581,31652,29460,31502,31466,29366, 29003,31106,30139,30601,32132,28467,30142,30600,32143,28466,31130,29012, 34426,37020,17728,19329,34393,36989,28465,30597,29451,31497,31451,29356, 29455,29447,31340,30077,32087,31494,29249,30178,30202,30177,30299,30201, 30200,34404,36998,18725,21426,34279,36860,29360,30138,38134,36982,29363, 30425,38670,36988,29362,36987,29359,36981,29848,31780,31779,37302,10167, 37571,13097,20623,29838,31753,31752,37378,10150,37713,13026,20886,29854, 29837,29836,29887,36236,41005,31801,32030,31800,32029,41004,36235,37355, 42044,31799,32028,31798,32027,29877,29972,42043,37354,31797,32026,31796, 32025,29876,29971,37885,42523,31795,32024,31794,32023,29875,29970,42522, 37884,31793,32022,31792,32021,29874,29969,29873,29968,31791,32020,31790, 32019,29872,29967,37442,31835,31838,29892,20945,13294,37758,10198,37441, 42091,31834,32051,31837,32054,29891,29979,29963,29965,29961,29949,29948, 29947,29946,29945,29976,29975,29974,29956,31972,31971,41977,33975,31945, 33761,31944,31943,35191,29944,31942,31941,42063,42090,32050,32053,29978, 37353,42042,31017,31016,31015,31014,28924,28923,37883,42521,31013,31012, 31011,31010,28922,28921,36234,41003,31009,31008,28920,31007,31006,28919, 36573,36559,30749,41750,39927,27061,36085,28663,39519,26343,39521,26345, 39517,38971,39061,30955,30953,28834,28832,26597, 9597,20771, 9596,30942, 28812,13649,13159,36568,29087,20211,36550,30974,39555,30976,31207,31202, 39566,31213,39568,31215,32332,32324,14975,14864,32331,30971, 9587,30784, 30885,11334,11536,31035,28947,31034,28946,31033,28945,31032,30680,30682, 31027,43145,27971,38105,36361,38104,36360,38103,36359,38102,36358,30596, 30904,30595,30731,30594,30858,30593,30922,30592,31569,30591,31279,41602, 28464,40779,28463,40729,28462,30788,30920,30787,30919,30589,32108,30587, 30851,40741,31218,31282,31217,33158,31244,33923,33157,31281,31243,33922, 31223,31649,31222,33156,34481,31229,33155,31648,34480,31228,31103,41708, 30586,41705,30751,34057,30585,34060,30837,33551,31227,34479,33921,31242, 30584,33388,31238,33912,30583,33405,34467,30582,30581,34464,31590,33351, 33917,31240,31277,33471,30580,33542,30579,35822,28461,24137,33154,24135, 30578,35821,28460,20315,33153,18190,30577,35820,28459,20322,33152,18194, 40766,40775,28458,28669,33151,33385,31272,30897,33903,31234,31271,34450, 33902,31233,31270,36595,29182,20310,33983,18185,30576,35819,28457,20059, 33150,18701,40773,28667,42406,40772,30889,33149,30856,33148,31111,42577, 31110,31109,12307,41976,20622,30843,33147,31877,31865,31864,31875,38137, 37570,31904,31542,30896,31541,34449,31540,37201,29403,20309,34026,18184, 31630,42576,31629,31628,12776,41975,20621,31903,43374,33146,31108,31627, 33356,33519,31045,33145,43156,38484,28456,28455,38443,43045,28454,28453, 31152,30572,38414,42966,29040,29047,43204,38501,29676,29645,30895,36108, 28768,23808,33518,23827,31710,42921,31727,29625,36586,36582,36581,36580, 36579,36584,40740,29152,33928,31288,36607,29197,20336,33993,18262,31287, 36606,29196,20335,33992,18261,31286,36605,29195,23570,33991,23569,31284, 36603,29194,20334,33990,18260,37259,22029,43144,27970,32398,33816,32358, 33967,32372,33144,32371,32472,32357,32356,32355,32375,32377,32470,33143, 32469,32454,31940,32488,14328,32491,14344,32497,14301,32500,14308,39361, 26101,32247,10545,39782,26792,32246,31751,14500,13025,32238,39552,32227, 32323,32235,32231,32312,42580,32225,14040,42025,20652,32253,32263,42575, 32262,32261,14104,41974,20620,32260,32259,32300,32243,41593,28452,30571, 31099,41604,28451,30570,28450,30569,28449,41607,29090,41606,29089,30841, 28727,31733,29666,31732,29665,31225,31499,31220,31266,30568,31496,30567, 31263,30566,32131,30565,31105,30564,31091,30563,32122,30562,28448,42539, 28447,37827,28446,32197,32191,32196,32190,31097,31096,31095,38514,20470, 31258,31251,33142,31249,33223,31256,31255,31254,30650,30561,41572,26255, 41586,29175,31260,32084,31062,28962,32185,25060,43143,27969,32154,32153, 32152,32151,21506,32150,21505,37792,38136,43087,27905,42764,27245,41135, 25798,38184,32179,32181,32177,32114,32083,31493,32129,32128,32127,41585, 29248,31771,10157,39784,26794,31750,10149,39862,26902,39987,27145,31749, 31778,13024,13096,31777,10166,39781,26791,33466,43424,35165,40725,33880, 43390,32468,43373,32475,32374,33139,32354,31789,32018,31005,31004,31788, 32017,31787,32016,31830,13286,31829,32048,32045,25059,31976,25310,31939, 26251,31947,31983,31938,31937,32043,12475,31936,14107,31974,14074,31959, 35141,31935,33974,31934,33760,31933,35190,31932,13023,32258,14103,31931, 13022,31930,13021,32223,14038,32221,32257,32014,32013,31992,11595,31990, 31988,31986,31985,31963,31929,37791,29943,21499,34974,18036,29942,34973, 31928,18794,37790,20023,31927,37789,29941,20329,34972,18211,31926,31970, 32047,31003,32903,32767,32894,32750,32590,32608,16656,32623,12282,11039, 32630,32627,16680,32582,16581,32576,32615,32614,32573,32572,32570,32568, 32651,32665,32650,33138,32656,33896,33137,32664,32655,33895,32654,33894, 34023,32564,32563,33517,32562,41669,32828,32827,17502,17501,32745,32744, 16798,16797,32825,17495,32917,17319,32824,32850,17318,32849,32783,17544, 32797,17565,32561,32560,32658,32646,32926,32914,32913,32559,32558,32690, 32795,17563,17381,32684,32777,17541,17317,32672,17200,32670,17194,32669, 32741,16962,32740,32739,32738,32789,32923,32737,32736,32766,32755,10229, 10284,10239,10165,10237,10159,10228,10148,10227,10147,10226,10283, 9863, 9748,40145,10048,40165,10050,40167,32291,31050,30365,28953,30176,28952, 28951,30343,30129,32290,32168,30364,30175,30174,30363,30199,30379, 9665, 21011,36541,36756,35972,36365,20445, 9752, 9582, 9750, 9581, 9627, 9634, 9580, 9579, 9578,11036, 9648,11282, 9577,11035, 9667,34545,34581,35202, 33772, 9889, 9885, 9884, 9883,17877,17837,17713,17879,18133,17856,17712, 18096,17858,18098,18135,17711, 9949, 9955, 9953, 9952, 9951,18129,18093, 10037, 9640,23566,23565, 9646,23564,20220,33136,41616, 9694, 9697,23563, 19433,33135,40607,23562,24496,33134,35221,24699,33133,24539,33132,24046, 41177,10234,10296,10225,10282, 9726,21010, 9717, 9716, 9715, 9714, 9713, 11524, 9728,17865,24209,33927,10733,10730,23561,19623,33131,40798,23560, 24148,33130,33815,10024,21009,23559,20317,33129,41789,23694,20321,33330, 41796,40707,35160,25330,18753,34859,10070,18483,13378,34808,10099,18426, 13436,34909,10126,18555,13494,10794,10495,10784,10441,10782,10434,10796, 10498,10799,10512,10801,10515,10281,10224,10280,10223,10290,10231,35069, 34971,10279,26303,10278,10277,24228,33937,24125,24490,33767,35197,24673, 13015,24513,13014,24030,41167,10777,10431,10306,10236,34976,10768,10408, 10359,10183,10358,10182, 9797, 9796, 9795, 9799, 9794, 9793,10191,10196, 10146,10145,34402,34382,34392,34391,34390,34389,17710,18023,26235,26237, 26202,26204,18125,18089,18105,18118,17709,18100,18018,17708,18784,18778, 17707,18012,18092,26221,26195,18091,18724,18111,37836,42470,21174,26829, 37838,42472,21177,26832,37857,42495, 9576, 9575,21216,26848,11031,11030, 36545,41564,20204,26213, 9574,11029,36549,41567,20210,26218,41566,26217, 10511,10644,10497,10634,10420,10555,10514,10653,10508,10637,10403,34807, 14078,18425,36535,41546,20191,26194,10473,10618,10430,10580,10480,10623, 10491,10625,30183,10532,40102,10560,10582,10554,10579,32289,32272,10562, 10590,10628,10770,10617,10776,10620,10632,10550,10549,10548,10655,10630, 10616, 9860, 9852, 9851, 9854,10530,20618, 5566,20617, 9573,20885, 9712, 20616, 4291, 4290, 4289, 4288, 4287, 4286, 4356, 4355, 4354,41343,41339, 40665, 6669, 6709,20614,13010, 6821,20611,13007, 7470,22053,15419, 6720, 21548,14238,30101,35158,15891,22422,29753,34700,13136,20737, 4549, 4518, 29770,34717, 4565,29796,34743, 4572,29734,34681, 4535,41611,18173,41613, 33786,35208,34535,18103, 4285,42625,32907,32906,32195,32189,32188,32194, 4993,42313, 4949,42140,42312,20607,20879,42139,10304,20606,13058,42138, 10729,20605,16109,42137,42448,42178,10276,42491,42136,42490, 4948,42489, 10286,42409, 4954,42443,36593,42135, 4284,42134,10029,42133, 9940,20935, 9939,23558,12616,42351,23557,20934,33126,42350, 9183, 4283,10121,18549, 4282,40459, 4281, 4280,20604,42634,13003,42261, 4279,20603,13002, 5137, 4978,20602,42260,13001,42633,42632,42259,20601,20600,13000,12999,18690, 10349,20599,20598,12998,18689, 4278,20597,12997,18511,10110,20596,20595, 12996,18510,40918,20594,12995,17923, 9765,40917,20593,40916,17922,40692, 40691,40690,40689, 4320, 4322,40418,40417, 4306,40416,42585,42574, 4973, 42252, 4972,42405,42201,20670,42404,42200,10316,20703,13104,42223,10315, 42403,10097,18481,20592,20591,18478,12994,13134,20735,18415,18413,20734, 10063, 4277,20590,12993, 4335,20733,13133,35135,30076,22307,15748, 4399, 4401, 4276, 4275, 4274, 4273, 4272, 4271,29721,34668, 4515, 4304,40712, 21466,14080,23748,22421,15890,40415,40514,41545,41544, 6668, 8194,33785, 35207,34534,40424,21425,14006,23588,22306,15747,40423,40414,40413,21439, 14026,23556,22334,15779, 4372, 4369, 4368, 4367,35151,30093,22413,15879, 35150, 4709,42027,20654,31957,13047, 4743, 4692,42062,20878,31969,13057, 32452,16107,32464,32480,32369,18743,24473,20658,26549,18117,24227,20589, 26528,18017,24124,20588,26527,18783,24489,20587,26526,40412,10275,20877, 12992,42311,41973,20586,31925,12991,30092,30275,29355,29432,30137,30296, 29002,29008, 4318,17706,23555,20691,26570,40411,25557, 6570, 4334,29718, 34665,12990,20585, 8185, 4333,34541,40410,21144,13573,23554,21321,13811, 4337, 4332, 4331,17775,23649,20740,26589,18110,24208,20732,26586, 4339, 17705,23553,20744,26593,10094,18475,20584,20583,18473,12989,13156,20767, 18411,18408,20766,10060, 4269,20582,12988, 4346,20765,13155,23552,23551, 20958,20950,18569,13299,10132,18561,20957,23550,18568,23549,10131,18560, 23548,20949,23547,13298,10128,18557,20955,20947,18566,13296,23546,20967, 13309, 4426, 4425,20966,23545,13308,23544, 4422,20964,13306,18123,20907, 18736,26927,18735,20656,18116,20581,18016,20580,18782,20579,18072,27682, 18077,20932,18075,26926,18074,20930,18070,20923, 7374,21967,15295, 6806, 20578,12987, 7475,22058,15424, 7355,21955,15281, 6829,20897,13255, 7482, 22065,15432,17704,26941,39072,22305,15746,25553,21424,14005, 4345, 4344, 20764,39836,13154,39658, 4330, 4329,20731,26878,13132,26640, 5176, 5028, 20763,39657,13153,39835, 4328, 4672,20730,26639,13131,26877,39834,39656, 20762,20761,13152,13151,26876,26638,20729,20728,13130,13129, 4343,21375, 13913, 4327,21249,13704,39129,20760,13150,25661,20727,13128, 4364,20803, 13187, 4385,20846,13227, 4366,17904,26925,17903,20775,18109,20759, 4352, 4363,17703,20773, 7224,21817,15106, 7278,21845,15151, 6793,20758,13149, 7453,22033,15389, 4419, 4418,18063,20916,18723,20909, 4414, 4413,17702, 20911, 7222,21815,15104, 7399,21987,15317, 7350,21950,15275, 4312, 4362, 17701,20681, 7220,21813,15100,23543, 7430,22016,15356, 7436,22020,15361, 7409,22000,15333, 7391,21981,15309, 9607, 9609,20868,26645,26883, 9571, 21254, 9570, 9569, 9568,20862,26642,26881, 9605,21252, 9603, 9711, 9710, 20845,26634,26872, 9709,21244, 9708,32149,17742,27675,18764,26633,17850, 27739, 7293,27674,27803, 7219, 7264,27723,27722, 7263,17700,27691, 7218, 27690,27673, 7233, 4397, 4384, 4387, 4383,10544,26524,14097,37564,10164, 26523,13611,37563,37712,26522,26665,37562, 4854,37711, 4819,37561,10169, 26582,13623,37610,37603,26564, 4833,37657,23542,26552,23747,26521,10144, 26664,13559,37710,24179,26684, 4622,26520, 4642,26575, 4621, 4680,26519, 26657, 4620, 4010, 4619, 4009, 4618, 4008, 4617, 4007, 4616, 4006, 4615, 4005, 4614, 4004, 4613, 4003, 4612, 4002, 4651, 4042, 4650, 4041, 4649, 4040,17699,42365, 4999,42364,42338,26673,42337,26672,17698,26694,10370, 26693, 9943,26689, 9942,26688, 4611,26518, 4610,42500, 4609,37862, 4608, 26517,42499,26516,37861,26515, 4984,42285,42284,26514,10357,26513, 4837, 37681,37680,26512,10181,26511,40976,36197,36196,40975, 9792,26510, 4627, 4019, 4677, 4066, 4629, 4023, 4679,26656, 9567,17697,26655,26157,26889, 26152, 9850,17972,26509,25868,26789,25867, 5989, 4001, 5982, 4017, 9724, 9832, 9821, 4068, 4021, 4025, 4000, 3999, 3998, 3997, 3996, 3995, 3994, 3993, 3992,18079,18763,17849,17696, 5676, 3991, 5978, 4076, 9819, 4640, 4639,26788,26573,26828,26827, 4655, 4607,26604,26847,26850,26787, 4653, 4606,26845,26508,26844,26786, 4072, 4071, 4070, 9601, 9599,13239,13706, 9566, 9565,13247,13710, 9707, 9706,13224,13694,32148,17740,27672,18762, 26869,17848,27738,17695,27802,26341,38967,25052,26190,25051,26188,25050, 12633,25049,12628,25048,26338,25047,12682,25046,26280,25045,12771,26095, 26329,25111,12672,25228,25044,25043,25042,25041,25040,25039,25038,25037, 25270,25269,25980,25979,25036,25035,25034,25033,25032,25295,25294,25293, 25292,26167,26172,26166,26171,26165,26170,26164,26169,25309,25308,25307, 26176,26181,26175,26180,26174,26179,25031,25030,25029,25028,25027,25026, 25025,25024,25023,25022,25021,25020,25019,25018,25017,25016,25015,25014, 25013,25012,25011,25010,25009,25008,25238,25236,25264,25266,25543,25542, 25537,25539,26316,26327,26091,25226,26059,26061,26058,32176,38181,25804, 25806,25802,25801,26108,20020,26093,20015,25242,19468,26336,20349,26335, 20348,26334,20347,26332,20343,26323,20340,25391,25370,29835,25369,34970, 26099,31094,32126,31253,35415,38473,36287,38148,36286,36285,25935,27057, 25934,26098,25933,26374,25963,27671,27340,25960,25932,27255,27085,25931, 25959,27050,26097,25967,26186,26184,33117,33965,33116,28439,29173,33964, 29435,34082,33115,28438,33114,34081,26377,26419,25260,33911,33531,28780, 28785,33537,33915,25007,25006,25005,33469,33960,29416,34045,33300,28622, 33283,28616,29170,33957,33350,34056,26369,26402,25004,26005,25003,25341, 29168,33955,34022,33954,26394,26357,28189,22298,28165,28167,33113,33899, 33112,28437,29150,33898,28123,33901,33516,28767,28122,28121,25552,40394, 25551,25550,28436,28435,28641,29402,29401,34021,26373,34969,26372,25248, 19474,11313,19927,25892,12124,28434,28433,25826,25825,26224,25828,26930, 26924,25830,25824,26967,41117,19947,12165,25389,26063,26083,27025,21441, 27190,21629,27108,27071,27244,32175,38180,27074,27070,27069,27076,27059, 21496,27027,27670,27047,34611,35085,27135,27056,34968,27055,38179,35414, 38472,38147,38146,27084,27254,27083,27253,27052,27222,31101,36363,26296, 26288,26271,26287,26283,20247,26285,26264,26290,26273,26294,26277,26293, 26276,26292,26275,25344,28055,28057,27828,27726,27784,27403,27783,27402, 27715,29840,27669,29881,29192,42830,42130,43047,27769,42402,37788,43086, 42763,41134,27668,42752,41279,41836,28023,27667,27737,29834,27736,27904, 27496,27903,27495,38178,32174,28432,28862,29400,29399,29247,27982,27966, 27515,38471,32426,38145,32163,36284,31043,27984,36120,40793,28431,28430, 29046,29039,27762,35413,38470,27243,27242,27068,28429,28880,29398,27126, 27270,27100,26923,27010,27012,26951,26961,26969,26954,26922,26921,26920, 26919,26918,42210,42129,30264,27000,42552,37919,29189,28991,30289,26917, 42459,37899,26956,42401,37787,43142,26916,41838,27054,26915,26914,27261, 27093,27122,27137,27139,27143,26929,27252,27082,26987,26986,26985,26984, 26965,27045,42306,26262,26269,26268,25864,25862,19907,12099,25861,21133, 13558,26232,25284,21158,13589,36233,41002,41001,36232,25459,25467,25466, 25439,25438,25437,25463,25462,25478,25436,25435,25434,25433,25432,25431, 25430,25429,25448,26797,26913,25450,25428,26630,26868,25427,25455,19572, 11451,19575,25453,11454,25425,19564,11435,25422,25421,34547,36611,29498, 31483,40783,36087,27782,27902,27499,27501,27494,27493,27401,27721,27720, 27719,27519,27514,27513,27512,26737,26742,26739,26717,26716,26715,26714, 26713,26735,26734,26733,36534,41543,26558,22395,26507,22420,26675,22296, 26506,20726,26578,20695,26505,20577,20876,26654,30266,30082,29431,29354, 30295,30136,29007,29001,26504,26785,26503,26784,26502,26783,26501,26782, 26653,20576,26803,26818,26810,26781,26780,26779,26778,26777,26905,26776, 26775,26774,26773,26772,26814,27666,26771,27735,27975,27749,28027,28044, 28037,26796,26770,26831,21179,21176,13621,13619,26843,21132,13557,26822, 26821,26820,25684,19793,25679,19791,25660,19781,25659,26261,25658,32147, 25657,26231,25656,25655,25654,27734,25653,25682,27665,27767,25704,27766, 27664,25703,25707,25652,27718,20178,20182,19439,11301,19435,11297,19999, 12305,20245,12674,20249,12676,20253,12680,20252,12679,20251,12678,26247, 21597,21596,21595,21594,30157,35219,33813,29037,29457,34543,40385,40384, 40383,40625,19655,20477,20475,42960,43367,42673,42571,42959,43366,19653, 28426,33105,28425,33104,19651,28424,33103,41111,41110,41108,31886,28423, 28422,28421,28420,19639,11546,19644,11548,19622,19115,41179,41153,19536, 11398,21323,21148,37369,37702,31765,21152,21314,21131,37377,37709,31776, 21130,32245,21129,21313,21128,21312,21127,21311,21126,21401,21305,37295, 37560,31748,21304,21374,13912,20757,20756,13148,21373,21241,13693,20725, 20724,13127,21240,21372,13911,21371,19612,11504,28419,40382,40381,19823, 11892,39128,20755,39127,19822,19780,11781,25651,20723,25650,19779,19821, 11891,19820,19819,11890,11889,19818,41089,41088,19437,11299,19540,11402, 19531,11393,20034,12310,20037,12329,15739,22295,20036,12328,20290,12758, 20300,12769,20299,12768,20298,12767,32458,40797,41132,40630,41662,41707, 41690,41785,41661,41774,41660,41773,41700,41699,41795,41684,41688,41659, 41727,41811,41725,41657,28418,28417,20229,12982,20228,20575,20225,12655, 20222,12653,28416,26302,42400,37786,22294,15738,22293,15737,22292,15736, 22291,15735,22290,15734,22289,15733,22288,15732,22287,15731,34719,29772, 35227,30162,29728,34675,35140,30081,34689,29742,35134,30075,29774,34721, 35133,30074,35253,30198,35132,30073,28931,33671,35130,30071,22286,35177, 22285,22284,22353,22283,31910,29115,29113,31879,28415,28414,22438,15899, 22282,15730,22746,21563,37294,37559,31747,21562,22748,16285,22750,16288, 22415,15884,22281,15729,22280,15728,22392,15849,22463,15930,34658,29711, 35157,30100,29710,34657,35156,30099,22419,15889,31863,29036,29035,22651, 16133,22653,16140,22658,16151,19922,19920,19906,40380,19905,19904,41087, 41116,19968,12203,19966,12201,19946,12164,19945,12163,38940,25109,21310, 21125,20232,12661,20234,12663,20240,12667,20239,12666,20238,12665,20242, 12669,20305,12687,20304,12686,20303,12685,20307,12689,20176,12631,20175, 12630,20180,12635,32140,31127,32139,31126,32138,31125,32137,31124,20351, 20346,31463,31462,31456,31448,31447,31446,31445,31862,32146,31924,41972, 21504,21503,21578,21577,21576,21575,27661,21437,21457,21455,32173,21534, 21532,21530,27660,41713,41802,42860,42754,41724,41810,21525,14160,21523, 14158,21518,14134,21517,14133,21542,14214,22955,23406,23405,23404,23403, 22986,21686,14735,21651,14505,41289,41281,42958,43365,40371,40370,43076, 43441,21638,14457,21657,14512,21674,14605,21672,14603,21667,14579,21666, 14578,19579,11459,19601,11477,25419,25417,19561,35438,30308,41723,41809, 27202,27033,21034,27713,21008,27733,25368,21007,27659,21075,22411,15877, 34878,29879,41558,41577,40612,40614,41693,41787,22278,15727,34907,29889, 26560,26816,22277,15726,26551,26812,22394,15852,22364,15806,34804,29833, 26500,26769,22363,15805,21481,20207,22481,20203,20213,20206,20202,26499, 26768,20201,20270,12650,20269,41342,41338,41337,41341,40664,40663,41562, 41581,20573,12980,29751,34698,34655,29708,34696,29749,34653,29706,41610, 20570,20569,34533,35206,33784,20568,18102,20567,12979,42624,42623,23537, 23536,20566,12978,20565,12977,41086,41085,36592,12658,20564,41808,41374, 41353,41373,41352,41372,41351,41371,40369,40368,40367,40366,40365,40364, 42597,42570,42569,42627,20664,13056,20563,12976,20800,13184,20754,20753, 13147,20799,20842,13223,20722,20721,13126,20841,20798,13183,20797,20650, 13049,20562,12975,20561,12974,20560,12973,20559,12972,41979,31961,42023, 42061,41971,31968,41970,32451,41969,40363,20875,13250,31923,42060,26496, 26767,21448,14037,20720,13125,20719,13124,25860,25859,20718,20717,25966, 25556,20796,13182,20927,13282,20929,13284,20809,13192,20795,13181,20866, 13243,20840,13222,20852,13232,20839,13221,21150,21156,21136,21124,21123, 21122,21121,21120,21278,27658,21119,25367,27732,21118,28025,21138,21117, 13556,21116,13555,21115,13554,21114,13553,21263,21262,21261,25415,25413, 12352,14223,12821,14281,12823,14284,11140,14523,11132,16013,16393,16380, 14985,14869,16399,16386,15015,14892,11966,11104,10996,14459,11321,11539, 11466,10995,11332,11472,11534,10994,11346,16643,10993,16653,11530,11520, 11433,12281,12285,11348,11345,40140,39228,11990,14113,11989,15240,11988, 21492,20011,21491,20010,21490,20009,21489,20008,21488,20007,21512,20042, 34803,29832,23535,23699,24207,21511,20041,33102,11672,22276,35218,11555, 11551,41176,11366,35137,40362,33101,40361,40523,41542,21487,21370,35188, 33950,13910,33100,40360,40499,41541,21486,20006,35187,33949,11888,43364, 33099,43363,12766,42568,18668,12657,36591,33098,32353,11080,12046,12039, 12010,12036,12014,11189,11191,37683,42287,11099,11101,37864,42502,11089, 11091,11066,11068,11117,36201,40984,12614,42348,27657,22275,42347,37744, 12613,12600,42346,37743,12538,12537,33097,13266,23526,27656,22272,12536, 12510,15773,14398,15722,33962,15721,26417,15720,26663,40355,15797,15719, 15718,33946,33830,33433,15717,15716,15715,26691,16233,33096,33095,15713, 33094,37344,33868,37388,33875,20474,32309,33833,33437,33837,17996,33093, 33092,15709,15706,15921,40354,33812,23525,20040,15834,32487,32496,32776, 40353,40352,33091,33811,33810,33809,37293,33808,33807,33806,33805,32299, 32474,32388,33090,32352,17684,23524,27756,22461,27655,22255,17843,23772, 17841,23746,27728,22418,26585,20716,15700,15099,15888,26495,26494,20558, 27029,21447,27036,21462,16104,14669,17900,16103,12971,40351,31922,32450, 25572,19660,17683,23523,26493,20557,16102,15274,26492,20556,12088,12087, 12086,41166,23522,12131,12085,42128,12084,40627,35975,37785,42399,12082, 12113,12079,12078,12077,12076,42498,37860,12075,12074,42283,37679,12073, 12072,40974,36195,12071,12123,41772,41771,41770,41769,41782,36891,41799, 36967,41768,36859,41807,12968,41806,36986,41805,36985,41767,36858,41766, 12517,12514,37751,12606,37749,12604,11378,42546,37906,11431,11430,11429, 11446,11450,11428,11427,11426,21537,12242,20215,20189,20274,21113,20200, 20268,20272,22254,20265,20555,20264,20794,20263,20262,21369,20261,20260, 22253,20257,20715,20267,24168,23521,41348,40350,24206,41540,22356,21036, 22362,21005,21070,22252,21510,21004,21146,22251,21140,22330,21435,21317, 13366,18487,13365,15909,18447,15816,21112,22361,15804,18405,15803,13364, 14077,13363,13435,13809,13572,15699,13492,18554,15698,36471,36498,36547, 15137,14053,16177,14484,40139,39954,15239,14112,15238,14111,15697,15887, 15864,40711,21465,20752,15098,20937,15326,36469,20468,15273,14182,20554, 15272,16100,14326,14299,15021,14896,15013,14890,14961,14960,14959,14958, 14853,14768,14231,14499,14426,14030,14767,14665,14705,14195,14692,14187, 14663,14180,14730,14577,14729,14132,14728,12159,14727,14726,43440,43362, 18059,34607,17682,34605,18720,34602,34903,14772,14786,14269,15355,14267, 14784,16269,15351,16265,14868,14852,14851,14850,14849,14957,14889,25722, 33651,14576,14575,14574,26973,14573,35051,14572,26612,14571,34867,14570, 14569,14096,13552,23520,14062,23519,39795,23518,21316,22250,39531,20793, 14004,39655,14003,21368,14002,39833,14001,14000,13999,39126,19817,40119, 40138,14280,14283,14228,20553,21485,20792,21484,14237,33758,33757,39753, 14240,39752,33089,14247,34800,14246,33088,21111,21451,14222,14207,26584, 15097,16099,14131,25721,33650,14130,14129,14128,26972,14127,35050,14126, 26611,14125,34866,14124,14123,14052,12157,12155,12153,12182,12152,12151, 12150,26971,12149,35049,12148,26610,12147,34865,33649,25720,13454,12146, 16900,17343,16912,17380,16619,16568,23517,16689,16566,24234,16564,22248, 16724,24188,16723,33085,16729,33890,33084,24187,23516,33889,16728,33888, 34012,16559,23826,33515,41648,16558,17067,17181,16557,26220,18087,16720, 16810,16773,16772,20552,17681,16771,16556,18719,16956,16955,17537,17300, 17536,17299,17535,17534,17297,17295,17293,17292,17291,17290,17533,17388, 17377,12965,12964,13095,12963,41609,18172,34532,35205,33783,15477,15532, 17101,12962,32905,32193,32187,16767,12961,13055,41347,13067,12960,18502, 12959,12958,18545,12957,17199,14073,18441,14048,32032,31967,31921,21110, 21446,14036,18404,14035,17680,23511,18740,24471,13163,13660,26601,20777, 18115,24226,18015,24123,18781,24488,12956,13551,26652,20874,40347,13054, 13588,26487,20551,40346,40512,41539,33756,35186,33948,13180,19648,25562, 20465,26438,30161,30303,21450,27031,29353,29430,30135,30294,29000,29006, 21461,27035,36984,41804,12955,13550,37747,42357,12954,13549,40345,25560, 26486,13123,33952,13122,13121,25965,25559,15460,15514,17055,17772,23647, 17679,23510,18108,24205,18121,17678,18738,18114,18014,18780,12953,26651, 18061,18085,17677,18083,18718,18081,15279,16126,15095,15694,17676,17906, 18107,15149,15902,13263,15344,16259,15353,16267,15187,15955,15289,16156, 15127,15790,15093,15692,13548,13610,13596,23508,22329,23745,22417,15809, 34823,15691,34863,22242,24181,15690,15886,20714,13547,40796,35139,33827, 33803,15828,15687,41794,13546,42222,13545,13544,13587,16239,34799,16238, 33082,13543,13578,42408,37794,37816,42445,13657,42127,13656,13655,13654, 42398,37782,13764,42369,17675,42368,13763,42367,13761,17674,13760,15683, 13728,13727,13542,13541,13540,42497,13539,37859,13538,42282,13537,13536, 37678,13535,40973,36194,13534,15680,14206,14568,14122,13667,13586,20550, 13585,11809,11819,11779,11817,12121,11775,11797, 9551,34857,33081,33079, 1870,10340, 1763,21210, 1607,32011, 1803,35041,30536,30534,19291,31901, 17673,29870,28404,28402, 1820,37989, 1577,29932, 1748,18661, 1887,13864, 35765,35763,10964,37629, 9549,34854,33077,33074, 1867,10337, 1760,21207, 1604,32008, 1800,35038,30532,30529,19289,31898,17671,29867,28400,28397, 1817,37986, 1574,29929, 1745,18658, 1884,13861,35761,35758,10962,37626, 9546,33071,33068,33066,19054,18717,14385,19286,38275,38056,30331,33064, 30526,30524,19282,30522,17667,28391,28388,28386,32215,35749,35477,35586, 10674,17664,21625,22234,35746,35744,10957,35742, 9542,33055,33053,33050, 19051,18714,14382,19279,38272,38053,30328,33047,30516,30513,19277,30510, 17661,28384,28382,28379,32212,35739,35474,35583,10671,17657,21622,22231, 35737,35734,10955,35731,17797,34167,33045,33043,36731,34323,33345,31399, 18340,31381,19447,34342,35958,30508,19267,31584,17649,29534,33325,28371, 17808,36906,20409,29311,35939,29295,34185,36925,35717,35715,19461,36750, 17796,34166,33029,33027,36730,34322,33344,31398,18339,31380,19446,34341, 35957,30500,19259,31583,17641,29533,33324,28368,17807,36905,20408,29310, 35938,29294,34184,36924,35713,35711,19460,36749,43358,33025,33022,33020, 7205,40213, 6413,24632, 7559,39912, 6227,33018,42727,30498,27180,30496, 24775,28366,40212,28363, 7556,35709, 6226,43355, 7202,27333, 6412,42724, 35706,35704,39911,35702,43361,33015,33058,33061, 7208,40209, 6409,24630, 7562,39908, 6223,33013,42730,30519,27183,30493,24778,28361,40216,28394, 7555,35699, 6230,43354, 7201,27332, 6416,42723,35755,35752,39915,35697, 17638,10331,34848,35032,30491, 1811,33011, 1568, 9531, 1739,19256, 1878, 35695,32002,21053,21201,18613,18652,33008,29923,17635, 1861,10944, 1754, 35692, 1598,28359, 1794,37620,37980,19253,13855,17632,34202,33647,33633, 36770,34359,33005,31436,18359,31419,19250,34375,35689,30992,19768,31615, 17920,29549,33004,28918,17631,36945,20439,29346,35688,29330,34219,36962, 36230,36193,19249,36789,17630,33377,33646,33632,36229,33003,30991,17919, 30769,19248,35687,19767,28655,28917,35994,36192,17889,10746,35613,35557, 30927, 8803,33565, 5749, 9746, 8073,19628, 8560,36125,32295,22558,21685, 18903,19091,33570,30376,17895, 8844,11544, 6969,36132, 6014,28802, 8448, 38196,38333,19633,14689,17888,10745,35612,35556,30926, 8802,33564, 5748, 9745, 8072,19627, 8559,36124,32294,22557,21684,18902,19090,33569,30375, 17894, 8843,11543, 6968,36131, 6013,28801, 8447,38195,38332,19632,14688, 17887,17628,35611,35555,30925,30488,33563,33001, 9744, 9528,19626,19246, 36123,35685,22556,21683,18901,19089,33568,32999,17893,17626,11542,10941, 36130,35683,28800,28356,38194,38331,19631,19244,39563,10143,34967,34798, 30660,42077,33233,26992,33856,42320,31186,31181,39684,31861,24419,21003, 26998,18587,42331,29831,29068,29085,36449,39689,35890,24423,28540,39559, 37950,37553,42072,13360,33862,18638,33197,33201,35065,37723,32038,34797, 31175,18619,33846,21002,30630,37949,31192,19345,29074,17746,28509,34966, 36467,18586,29079,21066,29936,37552,38021,34889,35855,35859,36462,21109, 33210,18637,33451,33444,35020,37608,31979,34796,30643,18604,33205,21001, 30835,37948,30639,19516,28522,17835,28711,34965,35868,18585,28517,21046, 29911,37551,37970,34832,36049,36060,35864,21108,18010,35175,33221,33215, 31081,18584,33736,21859,37947,37550,29904,35353,36327,30648,19351,32120, 17752,30423,33747,28527,31920,38450,34964,34795,36337,18946,28984,21000, 35874,35879,19988,38641,17823,18358,28697,29563,30809,31435,33401,34358, 38685,38468,31614,31418,36017,36769,11343,12750, 9663,10013,33421,34218, 32162,32425,36788,36944,36033,36961,28685,29329,30799,31601,19492,20438, 17822,18357,28696,29562,30808,31434,33400,34357,38467,38684,31613,31417, 36016,36768,11342,12749, 9662,10012,33420,34217,32424,32161,36787,36943, 36032,36960,28684,29328,30798,31600,19491,20437,17821,18356,33685,33684, 30807,31433,33399,34356,36258,36257,31612,31416,36015,36767,19976,19975, 17962,17961,33419,34216,31042,31041,36786,36942,36031,36959,28683,29327, 36265,36264,19490,20436,10003,34321,34165,34340,17795,32160,11309,35238, 35956,35937,28636,34183,31582,38466,20424,31397,18329,29293,29532,35383, 30747,36729,33323,33343, 9657,38683,19459,30427,36748,36904,12740,36923, 10002,34320,34164,34339,17794,32423,11308,35382,35955,35936,28635,34182, 31581,38682,20423,31396,18328,29292,29531,35237,30746,36728,33322,33342, 9656,38465,19458,30305,36747,36903,12739,36922,33683,34319,34163,34338, 17793,31040,19974,33715,35954,35935,33682,34181,31580,36256,31048,31395, 28956,29291,29530,33714,36263,36727,33321,33341,17960,36255,19457,28928, 36746,36902,36262,36921,43340,17624,32997,32995, 7188,40208, 6408,32993, 7542,39907, 6222,24772,42710,35681,27167,19242,24766,17621,40196,32990, 7554,27177, 6210,43353, 7200,35678, 6396,42722,35675,35673,39895,19240, 34525,23507,32987, 7309,32975, 7308,24977,23337,17054,17288,23183,40340, 24975,23336,17053,17287,23182,40338,40336,23181,17052,24973,23335,17286, 38810,32821,40605,39392,25222,38772,40603,39389,25224,32726,38771,32725, 40601,40599,23180,39383,17051,39386,25220,25218,23334,24199,17285,24192, 25279,25281,38770,38769,38961,32820,32724,32723,38959,38809,40652,40654, 38955,38957,41224,17050,25995,23333,41226,23179,25993,17284,23681,23679, 32973,39048,40641,13960,23505,13952,23503,13969,23500,23498,39722,23496, 39746,23493,39745,40067,31682,40070,31685,40072,31687,40066,31681,40065, 31680,40055,31673,39721, 9923,39744, 9934,39743, 9933,16510,32971, 2826, 28343, 2824,40334,40332,40331,40329,40327,40325,40323,40321, 6294,22565, 16042, 6271,22626,16092, 4266,22625,16091,10919,19223, 6624,10911,24964, 7087,19217,24960, 5724, 2709, 3037, 3181, 4265,22622,16089, 4298,22620, 16087, 7349,21949,15271, 7347,21947,15269, 7345,21945,15267, 3206, 5752, 10899,17800,34171,33121,33125,36735,34327,33348,31403,18344,31385,19450, 34346,35961,30552,19305,31588,17694,29538,33328,28443,17811,36910,20413, 29315,35942,29299,34189,36929,35807,35803,19464,36754,17799,34170,33120, 33124,36734,34326,33347,31402,18343,31384,19449,34345,35960,30551,19304, 31587,17693,29537,33327,28442,17810,36909,20412,29314,35941,29298,34188, 36928,35806,35802,19463,36753,18636,34169,33119,33123,36733,34325,34794, 31401,18342,31383,20999,34344,37946,30550,19303,31586,17692,29536,34963, 28441,18583,36908,20411,29313,37549,29297,34187,36927,35805,35801,21107, 36752,34520,23692,17727,34206,33644,33630,36773,34362,33170,31439,18362, 31423,19328,34379,35834,30989,19765,31619,17917,29553,33166,28915,17723, 36949,20442,29350,35830,29333,34222,36965,36227,36190,19324,36793,17726, 34205,33423,33403,37945,34793,33169,31860,18635,31422,19327,34378,35833, 30811,19494,31618,17825,29552,33165,28687,17722,36948,21106,29349,35829, 29830,34962,37548,36019,36035,19323,36792,17725,34204,34961,34792,36772, 34361,33168,31438,18361,31421,19326,34377,35832,31859,21105,31617,18634, 29551,33164,29829,17721,36947,20441,29348,35828,29332,34221,36964,37944, 37547,19322,36791,17719,33381,33643,33629,36226,33162,30988,17916,30773, 19320,35826,19764,28659,28914,35998,36189,17718,33380,33494,33506,37943, 34791,33161,31858,18633,30772,19319,33379,35825,30915,19588,30771,17875, 28658,33160,28758,17717,35997,21104,28657,35824,29828,34960,37546,36106, 36096,19318,35996,34201,17619,33398,33418,34790,37942,31857,32969,31415, 18632,34374,19209,30806,35662,31611,19489,29548,17820,28682,32964,36941, 17615,29345,21103,29827,35647,37538,34959,36030,36014,36785,19204,38965, 38827,38964,38402,38963,38394,30483,30481,30479,30197,30173,30172,37558, 37533,33232,26991,33855,42319,26997,31853,42071,34785,30663,10141,42330, 20996,31185,37937,30659,42076,28539,39558,29067,34954,39683,18580,28536, 13358,39562,37532,24418,29823,36448,39688,35889,24422,37708,37640,36827, 41765,29940,37091,37531,38132,37530,29954,29939,29952,29938,18047,17687, 18179,17690,37648,36442,36300,26727,26710,26725,26709,36053,36296,36454, 8812, 5812, 8435, 8792, 4905,43814,43311,43002,43286,42582,42845,42928, 42841,17738,17994,17736,17882,37784,37852,36298,36308,42834,26708,42866, 42924,42836,41896, 4061, 5984, 5996, 3392, 6655, 3665, 5991, 2355,11822, 11824,12297,12293,41271,41244, 9823, 9825,28555,30678,23629,25170,28972, 31072,24113,26051,28716,30818,23740,25326,28544,30669,23602,25142, 9678, 9673,12176,11804, 6292,22567,16044,14145,14590, 2539, 5657,14143,14588, 14164,14610, 2549, 5675, 1621, 5475, 1922, 5500, 3097, 5374, 5384, 3103, 1927, 5218, 5216, 1912, 5230, 1907, 5228, 1909, 1924, 5240, 1920, 5242, 5251, 1915,16600,16633,10970,11111,10966,11285,11116,12195,12208,11050, 24332,28819,28826,30947,37995,11048,37653,24461,38605,24787,38432,11046, 28807,30934,11044,43887,43853,43884,43850,43879,43845,43876,43842,14147, 14592,11113,12199,17610,19104,17607,19103,35640,28333, 8578, 8135, 4818, 4785, 8230, 8669, 8667, 8228, 8584, 8161, 8176, 8596, 8576, 8133, 6923, 6164,36294, 8790,36293, 6921, 6162, 6901, 6157, 4816, 4783, 8178, 8598, 6925, 6166, 8586, 8163, 6903, 6159,24751,12788,39418,38649,38634,36069, 38630,37529,39997,39585,40148,40037,40013,40113,39995,39678,40109,39587, 39677,39544,39583,40111,39582,38677,35816,35815,38676,38692,38648,32845, 30554,32330,30665,31742,31199,32322,32317,10868,10865,28325,28322,28318, 28315,18253,11572,11569,37502,37165,35655,35652,35793,36302,36292,18631, 34162,32968,32963,36726,34318,34789,31394,18338,31379,20998,34337,37941, 30485,19208,31579,17614,29529,34958,28341,18582,36901,20407,29309,37537, 29290,34180,36920,35646,35661,21102,36745,18630,18355,32967,32962,31856, 31432,34788,34355,34200,34373,31610,31414,37940,36766,19207,19203,17613, 17618,34957,34215,29547,29344,36784,36940,37536,36958,29826,29326,35645, 35660,21101,20435,18629,17873,32966,32961,31855,30913,34787,33504,33376, 33375,30768,30767,37939,36104,19206,19202,17612,17617,34956,33492,28654, 28653,35993,35992,37535,36094,29825,28756,35644,35659,21100,19586,35799, 9353, 9466, 9351, 8511, 8467, 9356, 9355,38382,28878,28873,28860,28855, 36282,36277,35797,18255,27821, 2597,18244,18243, 2456, 2596,18258,20185, 18251,18250,18248, 2639,37181,37178,37131,37164,37190,37163,37162,37161, 2628, 2484,37160,37130,37159,37189,37158,37107,35671,28353,30196,28348, 30171,28352,28351,30211,28330,32980,32985,32978,32983,28346,28350,28329, 32887,32733,36647,36641,39425,39436,39434,17467,17466,17465,11252,11231, 11249,11228,28577,30701,28571,30695,17464,36512,36527,32681,33885, 2803, 29143, 2801,33883, 2815,29141, 2814,17283,36510,23099, 8940,16953, 8939, 24190,24197,17374,36514,23332, 9222,17282, 9221,24186,24195,16899,36509, 17342,36508,16716,36507,23331, 9220,17281, 9219,23513,23515,16898,35774, 16770,35773,35812,32912, 9413, 9412,38826,38825,32843,32842,36520,32749, 36525,32722,36524,32765, 9315, 9314,38768,38767,32721,32720,36523,32902, 36522,32643,11922,11919,17550,32854,17500,32826,17196,32891,17326,32918, 14566,13036,13033,13045, 9827,20640,20632, 5980,21627, 6232,20630, 4294, 28502,30618, 3072, 3390, 3308, 3501, 3294, 3479, 3296, 3485, 3291, 3474, 24393,42188,24390,42185,10400,38621,10397,38618,38600,37957,38597,37954, 3369, 3053, 2347, 2474, 2341, 2468, 3497, 3306, 3387, 3070, 3372, 3056, 3462, 3288, 3460, 3286, 3367, 3051, 6898, 5577, 6896, 5575, 6912, 5608, 3262,38172,27114, 3033,38221,27106, 3031, 2490,38144,27081, 2488, 9523, 38143,27080, 9895, 3361, 3413, 3411, 2340, 2338,19193,20045, 3436,16188, 7760,16186,16190,16166, 7755,27548, 7979,27546, 7977,27554, 7985,27371, 7905,27369, 7903,10218,34894,29094,29104,23572,40849,33705,33700, 5477, 3365, 5504, 2343, 5409, 3495, 5442, 3385, 5436, 3375, 5376, 3454, 5430, 3363, 5327, 2345, 5283, 2367,32622,30556,30756,31026,32607,30558,30783, 30872,30884, 6085, 1558, 5512, 1532, 5502, 1551, 6098, 1541,16642,32605, 32620,16677,16631,16675,14167,14613,10974,10972, 5387, 3106,12007,12006, 19884,19883,27888,27479,25821,25820,22532,21907,15995,15226,13355,13354, 20992,20991,27887,27478,16175,22682, 3640,22681, 3639,28006, 3745,36150, 14722,16168,31028,14779,14262, 5486, 3092,14788,14271, 5514, 2300,14739, 14218, 5444, 3337, 3130, 5407,14202,14718, 3108, 5389,14190,14695, 3105, 5386,14188,14693,14733,14211, 5433, 3328, 3090, 5367,14184,14674, 2302, 5285,14115,14519, 2320, 5325,14137,14582,10976,10978, 2315, 5308,14118, 14556,12287,16679,12187,12185,12167,12213,12211,12145,12210,12220,12171, 12005,19882,25918,25819,19938,12144,13353,20990,25795,12218,12143,11787, 16647,11802,11800,11791,11789,12169,12012,11287,12142,12004,11785,11783, 32625,32624,16645,11772,16644,11535,11333,11771,11770,11769,11768,37781, 39432,42704,17745,19044,28513,30325,30629,32526,33196,35580,33861,33845, 31191,31174,35858,38269,11123,14378, 9612,10668,33200,35471,29073,29078, 36461,36466,35854,38050,28508,30067,30634,32209,19344,21619,17744,37488, 28512,29885,30628,32037,33195,35064,33860,33844,31190,37929,35857,37722, 11122,29816, 9611,31846,33199,34888,29072,34947,36460,36465,35853,38020, 28507,29935,30633,31908,19343,34770,42124,18618,28511,29884,30627,39579, 33194,35063,33859,39542,31189,31173,41965,37721,26764,13467,24372,10194, 39541,34887,29071,29077,36459,41964,35852,38019,28506,42123,30632,31907, 39578,21065,35579,33450,33204,33209,10667, 9684,21618,19515,32208,30827, 35470,33443,30642,30638,32525,30834,30066,28710,28516,28521,38268,36059, 30324,28721,19043,17834,14377,11391,35867,35863,38049,36048,35019,33449, 33203,33208,31845, 9683,34769,19514,31883,30826,34831,33442,37928,30637, 31978,30833,29910,28709,34946,28520,37607,36058,29852,28720,37487,17833, 29815,11390,35866,35862,37969,36047,35018,33448,39540,33207,10162,24371, 21045,39577,31882,30825,34830,39539,30641,30636,39576,30832,42122,28708, 28515,28519,37606,41963,29851,28719,18603,42121,13429,26763,41962,35861, 37968,36046,18009,35174,33220,33214,31080,10542,33735,21858, 9872,32383, 19996,35352,36326,30647,19350,32119,17751,30422,33746,28526,18003,38449, 12303,30287,36336,18945,28983,15177,35873,35878,19987,38640,18008,35578, 33219,33213,31079,10666,33734,21857, 9871,32382,19995,35469,36325,30646, 19349,32524,17750,30421,33745,28525,18002,38448,12302,30323,36335,19042, 28982,15176,35872,35877,19986,38639,18007,35173,33218,39538,31078,10541, 39575,21856,24379,32381,39537,35351,36324,30645,19348,39574,17749,42120, 33744,28524,41961,38447,26910,30286,42119,18944,28981,15175,35871,41960, 19985,38638,18006,35172,33217,33212,31077,31844,33733,34768, 9870,32380, 19994,35350,36323,37927,19347,32118,17748,30420,33743,34945,18001,38446, 12301,30285,36334,37486,28980,29814,35870,35876,19984,38637,35881,43188, 19019,43115,19000,43043,18937,42904,19125,40860,41464,40864,41531,40856, 41497,27449,27858,26485,26484,18893,35399,18905,18871,36637, 8640,43490, 8638, 8636, 8632,43488, 8630,27913, 6309,27643, 6199,27650, 6201,27648, 27317,15071,21781,27319,36291,30114,30113,18035,18034,18843,27630, 6194, 27198,26411,27628,27627,27626,17953,18752,18873,18877, 6850,14325,14323, 13562,27200,27195,26544,26498,35410,18842,18840, 7945, 4605,36290,29959, 29958,18839,26754,26753,18838,30779,28661,28542,28311,32951,38593,37485, 26198,38808,32719,26208,26206,26210,28413,12590,18544,11602,18501,10103, 18493,11601,18500, 7875, 7873,27185,26532,26483,27409,27411,26491,27792, 26530,26719,26489,26712,12815,27808,26482,27790,27795,27794,26070,27380, 30341,10472,28732,29134,29567,29569,30349,30351,29019,29021,27745,26481, 26480,25346,25339,25355,38807,32718,26068,26073,25349,25351,25348, 2714, 26479,25856,26478,25855,26477,25854,26067,26078,32125,19191,26065,26076, 26476,26475,26072,26080,26131,26136,32145,10040,37484,37483, 4063, 5977, 22224,15675,18722,38647,38592,36537,38591,26410,26474,26473,26416,26683, 27293,27228,26245,26662,35635,28328,28327,43141, 8634, 3698, 3417,43138, 8621, 3713, 3441, 4213, 6544, 4218, 6524,40309,21826,15119,24933,20136, 12548,31819,24935,29131,37427,37426,37408,38126,37407,24931,24929,17280, 35772,17341,35771, 8954, 8953, 8972, 8971,32782,38780,32780, 9335,38778, 9333,35811,32911,35810,32910,35809,32909, 9436, 9435, 9450, 9449, 8407, 8256,38629, 8415, 8264, 8255, 8406, 8263, 8414,35185,30123,35217,30156, 35214,30153,35789,40137,14174,32950,32949,32948,32953,35923,39167,35925, 38697,30195,42782,38646,27407,27788,27787, 8189,35791,12362,12359,11671, 11668, 8208,38343, 8206,38341, 8147,38291, 8145,38289, 8143,38287,10851, 27142,10850,27121,10849,27044, 6334, 1523,11177,11175,15347,23665,25199, 23667,25201,41325,41317,41322,41314,12358,23576,40851,37545,38125,37544, 37543,37541,41764,40304,28309,28308,28307,43105,18991,28306,28304,28884, 35642,42567,41159, 9349,33613, 2854,28895, 2849,33611, 2852,28893, 2847, 13527,26472,11550,36307, 9348,13526,18492,33879,41480,33867,41510,41496, 41445,41530,41535,43810,43282,43307,37913,41501,41463,13758,43028,41495, 43007,41529,12582,18534,26682,12589,18543,33877,41478,33870,41514, 4208, 6553, 4263,22580,16060,11642,19693, 6603,11623,25597, 7060,19674,25585, 5684, 2676, 3005, 3140, 4055, 5988, 4207, 6550,20547, 5987,19189,20546, 9831,13525,20545, 9723,40302,40300,40298,38633,31123,25354,25357,40313, 40315,40312,40311,19187, 2935, 2932, 2975, 2972, 2931, 2389, 2392, 2388, 38391,12812,38367,38390,38360,10845,23489, 9521,23488,23541,23486,10861, 35182,30120,10858,12326,35220,30158,12323, 3320, 3318, 3083, 2317,41305, 27826,27824,27810,30339,28303,30476,21529,28302,30475,21527,28301,30474, 35418,30472,24979,41370,28299,40542,28298,40374,28297,41301,28504,41303, 28296,40378,28295,40389, 9517,22223, 9515,22222,28294,30471,15673,28293, 30470,26087,23485,26085,23484,26089,23634,26143,23482,28291,30468,35840, 25163,24068,33717,30467,33713,31149,36306,36274,36305,33668,36280,36279, 33666,41175,33726,30753, 8805, 9754,35271,35600,11567,11566, 8646,35602, 11561, 8644,40541,43812,40373,43309,40377,40376,43284,40388, 5853,40387, 35409,30466, 8193,35407,30465, 8192,35381,30464, 8184,35379,30463,35570, 30461,43352,28290,30460,27624,28289,30459,28287,30457,39372,30625,39369, 30622,38899,31715,39351,30456,39349,30978,39353,31089,29622,31709,38885, 31720,38884,30455, 8191,38882,30961,39786,30454,31739,35838,35795, 9519, 24942,24946,10856,10860,36345,36353,36344,36355,36343,36351,27406,35181, 30119,35281,30226, 8360, 8356, 8330, 8358,39348,32112,36349,36348,36347, 35184,30122,28764,41298,25054,40688,35240,30453, 8794,35249,30966,28852, 35594,28858,28857,35592,35385,30452, 4903,35397,30969,11554,35412,30451, 24989,41350,37156,36374,38124,38073,32589,11073,42118,18242,16618,38061, 11079,42117,17959,36254,33491,33503,36103,33681,30912,17872,30766,19973, 36261,19585,31039,28755,35991,36093,33703,33698,37155,38123,36373,18241, 37154, 9818,20884,14498,26409,27227,26106,41758,37129,18218,12026,42159, 18240,12035,42116,35785,38881,32098,33691,33693,33689,22218,12043,13218, 10294,10292,12028,30542,30450,30538,30449,31151,30448,31161,30447,31163, 31165,10883,22217, 5329,42155,42974, 8736,42153, 4951,41300,31460,30446, 31458,30544,31450,30445,30548,30444,30546,30443,30850,30442,31129,30441, 31171,30440,31177,31167,35657,35781, 5119, 5121,43484,18837,42822,32959, 28339,32957,28337,10890,10889,35180,30118,10888,35116,30009,32955,28335, 32956,28336,10886,32142,30439,32107,30438,33826,29060,33828,29062,30848, 31159,32105,31158,18239,12112,42115,40294,22797,16335,11611,19666,23481, 11704,19724,23480,11710,19727,23478,11634,19685,23477,11722,19733,23476, 40292,21574,14298,14322,21593,40290,11726,19737,23475,11202,19384,23474, 11677,19713,23473,11674,11673,19710,23534,11205,19387,23472,11208,19390, 23471,11353,19502,23470,11011,19312,23469,11649,19700,23468,12449,20095, 23467,11007,19309,23466,11630,19681,23465,12445,20092,23464,16116,10909, 19216, 6507,10843,19185, 7796, 5508, 1553, 6102, 1544,11201,19383, 7799, 10841,19183, 6769,10917,10916,19222, 6757, 1919, 5507, 5506, 2337,11200, 19382, 7798, 3099, 5379, 5378, 3456,11204,19386, 7743, 3078, 5354,14173, 14650,11010,19311, 6602,10930,19231, 7795,10927,10929,19230, 7724,10926, 19228, 7741, 5302, 2336,11207,19389, 7616,10838,19181,41258,11641,19692, 41257,10836,19179,41256,16649,22930,25272,11033,19314,25535,11323,19482, 25545,11004,19307,25874,11315,19476,25895,12442,20090,25866,11468,19595, 25469,11456,19577,25457,32610,32609,16651,22932,25274,30785,30886,11537, 11335,11325,19484,25547,25471,19597,11470,16682,12289,16681,25058,22939, 16691,12141,11331,16598,30781,11329,11767,11766,11320,19480,25541,12003, 12140,11319,19479,41255,17819,18627,28695,29901,30805,31851,33397,34784, 34199,34372,31609,31413,36013,37935,11341,13776, 9661,10272,33417,34953, 29546,29343,36783,36939,36029,37525,28681,29821,30797,31919,19488,21087, 17818,18651,28694,29922,30804,31892,33396,34847,34198,34371,31608,31412, 36012,37979,11340,13854, 9660,10330,33416,35031,29545,29342,36782,36938, 36028,37619,28680,29861,30796,32001,19487,21199,35953,18354,28693,29561, 30803,31431,33395,34354,34197,34370,35934,31411,36011,36765,28634,12748, 30745,10011,33415,34214,33340,29341,36781,36937,36027,36957,28679,29325, 30795,31599,33320,20434,35951,18353,28692,29560,30802,31430,33394,34353, 34196,34369,35932,31410,36010,36764,28632,12747,30743,10010,33414,34213, 33338,29340,36780,36936,36026,36956,28678,29324,30794,31598,33318,20433, 18163,34524,18170,34539,38973,41703,29442,14761,14765,14758,14451,13068, 10317,20704,13105,42224,24299,30412,43809,43281,43306,38235,27349, 7889, 14291,14320,14307,14275,27292,32314,26432, 8142,38286, 8205,38340,32311, 26426,27542, 7973,24301,30414,29621,31708,38245, 2898,34620, 3233,38243, 2890,34618, 3225,38241, 2909,34616, 3245, 2476, 2353,29613,31699,38239, 2333,34614, 2311,38232, 2959,32947, 2997,38230, 2957,33238, 2995,32946, 2920, 3256,38218,33236, 2918, 3254,38216,32945, 2913, 3249,38211,33141, 2911, 3247,38209, 3284, 3458,28841,30957,38225, 2952,33595, 2990,32944, 2906, 3242,38205,33111, 2889, 3224,38171,26471,33619, 2904, 3240,38203, 33617, 2902, 3238,38201,33615, 2900, 3236,38199, 9347,33603, 2896, 3231, 38189,33601, 2888, 3223,38170,33599, 2908, 3244,38207,40288, 5473,19177, 6077,19175, 6083,40286, 5510,20671,42202,28668,40774,28870,35518,28876, 28875,35516, 3026, 2497,12321,35396,30968,43080, 8776,42253, 4974, 9563, 35780, 9562,35779, 9561,35778, 9560,35777,35621,35776,43187,43525,33087, 28410, 8381,40344, 6063,40349, 5471, 8656, 8665,35769,35619,43193,43529, 24924,24922,19170, 6052,40280, 5460,19169, 6094,40279, 5498,40284, 6048, 40278, 5456,35768, 9554,35767, 9553,42816,42903,33083,28406, 8214, 8219, 42821,42908,35276,30221,10834,40283, 5465,19173, 6057,40282, 5484,19172, 6072, 4604,35480, 8688,38151, 7004,35486, 8696,38161, 7021,35484, 8694, 38154, 7019,11715,11706,15672,11667,11713,11702,15669,11664,11699,11717, 11708, 5397, 3116,14777,14260, 5481, 3113, 5447, 3389,14741,14220, 5446, 3339, 5412, 3500, 3132, 5411,14204,14721, 7329,21927,15249, 5494, 2352, 5372, 3448, 3101, 5382,14186,14691, 2327, 5344,14162,14608, 3077, 5353, 14172,14646,11648,19699, 6601,35482, 8692,38166, 7017, 5392, 3473, 3110, 5391,14192,14699,23463,43692,43694,24920,38951,22867,16482,33249,28118, 16479,28586,28115,22864,30710,35901,40584,16114,11661,23661,38948,22861, 16476,43690,33246,28112,16473,43689,28583,28109,22858,30707,35898,40581, 25195,23462,43789,43767,24919,23461,43688,43686,24918,16464,28568,30692, 28588,33251,30712,24853,35903,24812,28590,33253,30714,24855,35905,24814, 28576,30700,28575,30699,28574,30698,28594,30718,28593,30717,28592,30716, 23460,26117,23459,26125,25062,24917,25064,24916,23615,26119,23618,26127, 24915,25159,24914,25161,23458,25068,23457,25070,25378,24913,25384,24912, 23580,24911,23578,24910,25380,25086,25386,25084,23456,23455,43698,43696, 43702,43700,24909,24908,23454,28127,23453,28131,28125,24907,28129,24906, 23452,25073,23451,25076,27214,24905,27040,24904,23584,24903,23582,24902, 27216,25090,27042,25088, 9897,23617,27212,23825,27038,23807,25508,25507, 25485,25484,38076,32635,24060,43752,24059,43747,43751,25989,43746,25988, 16663,38064,23708,23707,28163,28162,28160,28159,25277,25276,33688,11488, 11501,33695,11465,19593,41254,23833,23813,24901,25514,24900,25491,25516, 25493,23824,23806,25376,25506,25382,25483,25505,25482,23840,23819,25258, 25524,25255,25501,25521,25498,16662,40650,40648,12139,16661,17475,16660, 17494,16708,32634,16655,11765,16654,16668,16665,17463,25268,22928,16640, 16658,12002,16657,41253,22927,16639,27274,27104, 8615, 2949, 8724, 2967, 24899,24898, 5711, 3168,27087,27257,39591,39593,39778,39780,24897,24896, 25305,41442,41415,24895,24981,41405,41436,24894,40670,21283,13733,25304, 20144,12556,40669,23178,17049,25303,23330,17279,40668,22082,15459,25302, 21736,14943,40667,22103,15510,25301,21714,14841,31816,38978,12457,20101, 23723,12456,20100,23722,12455,20099,25853,25930,41147,41165,24893,25153, 25151,41527,41493,41518,41484,24892,24891,24985,24983,41512,41476,41523, 41489,24890,24889,29127,37418,38081,38944,38942,25926,25928,41143,41145, 41161,41163,24888,24887,25157,24316,25155,24308,26445,24886,26435,24885, 31153,30573, 8606,27241, 8708,27067,24884,11397,24883,19535, 5633,40721, 8611,27268, 8716,27098,24882,13815,24881,21327,27278,27119,15862, 8485, 22401, 8532,24880,24879,27266,27096,13813, 5014,21325, 5150,24878,24877, 24305,25080,24314,25078,24876,26430,24875,26443,38381,12808,38372, 9614, 33240,28553,30852,30588,23810,25510,23829,25487,24874,25489,24873,25512, 28730,32109,30590, 8604,27239, 8706,27065,25072,11400,25075,19538,23818, 25523,23839,25500,25257,25497,25254,25520,25114,41379,26145,23677,25211, 24077,36418,36416,36452,21509,20039,35274,30219,12320,35212,30151,33801, 29031,33802,29032,12319,12317,12316,12325,33814,29038,29030,31148,29029, 31147,33804,29034,31169,31146,33818,29042,23805,25504,23823,25481,26115, 25480,26123,25503,25094,40694,30575,35818,25066,41355,14455,13070,10319, 20706,13107,42226,34316,10000,34335,34160,17805,17791,20405,11306,35931, 35950,34178,28631,31377,31577,31392,20421,29288,18326,29307,29527,36724, 30742,33337,33317,18336, 9654,19444,19455,36899,36743,36918,12737,34315, 9999,34334,34159,17804,17790,20404,11305,35930,35949,34177,28630,31376, 31576,31391,20420,29287,18325,29306,29526,36723,30741,33336,33316,18335, 9653,19443,19454,36898,36742,36917,12736,34314, 9998,34333,34158,34388, 36806,31455,29578,35929,35948,34387,28629,31375,31575,31644,20419,29577, 18324,29305,29525,36980,30740,33335,33315,29358,31643,36979,34229,36897, 36741,36916,12735,34530,23691,34519,23690,34518,23689,37417,37349,37500, 37481,37567,37337,37555,33628,33624,33374,33373, 9760, 9764,19763,19759, 31002,30998,33638,33642,30765,30764,30983,30987,28913,28909,28652,28651, 36225,36221,28904,28900,17915,17911,11887,11883,35990,35989,36188,36184, 34783,33502,33372,33371,10271, 9735,21086,19584,31918,30877,34952,33490, 30763,30762,31850,30911,29820,28754,28650,28649,37934,36102,29900,28792, 18626,17871,13775,11515,35988,35987,37524,36092,34846,33501,33370,33369, 10329, 9734,21198,19583,32000,30876,35030,33489,30761,30760,31891,30910, 29860,28753,28648,28647,37978,36101,29921,28791,18650,17870,13853,11514, 35986,35985,37618,36091,33500,33499,38464,38679, 9733, 9732,19582,19581, 30875,30874,33488,33487,30759,30758,30909,30908,28752,28751,32408,32159, 36100,36099,28790,28789,17869,17868,11513,11512,35984,35983,36090,36089, 20673,42204,28671,40777,43082, 8778,35236,31145,42255, 4976,12467,15666, 12584,18536,15665,18529,11600,18499,43684,43683,43682,43681,41521,41506, 41487,41472,28106,28105,41520,41486,41505,41471,28104,28103,12588,18542, 35566,30397,17734,29615,31701,29620,31707,11594,11580,11593,11592,13438, 40317,40319, 2675,11660,19708,41252, 6693,40409,12569,20157,40408,40672, 12563,20151,40276,40403,40406,12618,42353,20165,42669,40402,40405,40550, 40548,12621,42356,20168,42672,40274,40272,40554,40552,35279,30224,34631, 29684,40270,43213,40268,43541,40400,40397,24303,34628,29681,40399,43210, 40396,43538,32283,11690, 3331,32281,11697,11696,11695,11694,19722, 2733, 11692,19720, 2731, 6695, 6692,34708,29761,20865,13242,11180,11183,11179, 11182, 2831,15192,39417,31625,18280,19041,29473,30322,31309,32523,34248, 35577,34246,34106,31307,31515,36671,38267,12696,14376, 9964,10665,34104, 35468,29216,29471,36826,36669,36824,38048,29214,30065,31513,32207,20360, 21617,18318,37584,29511,29813,31361,31913,34295,34944,34300,34148,31356, 37965,36713,37480,12727,29846, 9992,31873,34152,34767,29271,34991,36876, 36717,36881,37926,29266,29895,31557,31843,20395,34820,42168,18576,29518, 29812,31369,39620,34308,34943,34307,39550,31368,31564,42011,37479,26800, 13352,24374,10138,39549,34766,29279,29517,36889,42010,36888,37925,29278, 42167,31563,31842,39619,20989,18315,18575,34990,34819,31355,31912,34299, 34942,34294,34151,31360,31556,36716,37478,21142,21022,18640,18594,34147, 34765,29265,29510,36880,36712,36875,37924,29270,29894,37964,37583,20398, 20988,39536,10155,34989,34818,31354,41959,34298,26909,34293,42114,31359, 31555,39573,31872,24378,21021,26908,18593,42113,29845,29264,29509,36879, 39572,36874,24377,29269,39535,37963,37582,41958,13391,39547,10137,34941, 34764,31365,42007,34304,26936,34303,42164,31364,31560,39617,31841,24384, 20987,26935,18574,42163,29811,29275,29514,36885,39616,36884,24383,29274, 39546,37923,37477,42006,13351,38766,32717,41738,39446,26352,38806,41818, 39493,26389,32819,38805,32818,38804,32817,41744,39452,26362,38765,41826, 39501,26397,32716,38764,32715,41740,41820,23329,39495,17278,39448,26391, 26354,23177,24271,17048,24282,41746,41828,23176,39503,17047,39454,26399, 26364,23328,24276,17277,24285,24278,26367,18312,19039,29506,30320,31351, 32521,34285,35575,34290,34140,31346,31552,36705,38265,12724,14374, 9989, 10663,34144,35466,29261,29502,36866,36709,36871,38046,29256,30063,31548, 32205,20392,21615,18311,37476,29505,29843,31350,31955,34284,34987,34289, 34139,31345,37922,36704,37580,12723,29810, 9988,31840,34143,34816,29260, 34940,36865,36708,36870,37961,29255,29907,31547,31870,20391,34763,42112, 18591,29504,29842,31349,39571,34283,34986,34288,39534,31344,31551,41957, 37579,26762,13389,24370,10153,39533,34815,29259,29501,36864,41956,36869, 37960,29254,42111,31546,31869,39570,21019,18310,18590,34939,34762,31348, 31954,34282,34985,34287,34138,31343,31550,36703,37578,21080,20986,18621, 18573,34142,34814,29258,29500,36863,36707,36868,37959,29253,29906,37921, 37475,20390,21018,39491,41816,18351,18625,29558,29899,31428,31849,34351, 34782,34367,34194,31408,31606,36762,37933,12745,13774,10008,10270,34211, 34951,29338,29543,36934,36778,36954,37523,29322,29819,31596,31917,20431, 21085,18350,18649,29557,29920,31427,31890,34350,34845,34366,34193,31407, 31605,36761,37977,12744,13852,10007,10328,34210,35029,29337,29542,36933, 36777,36953,37617,29321,29859,31595,31999,20430,21197,39509,41834,39497, 41822,39416,39422,36636,26312,40618,12761, 9997,34313,34157,34332,17789, 17803,11304,20403,35947,35928,28628,34176,31574,31374,20418,31390,18323, 29286,29524,29304,30739,36722,33314,33334, 9652,18334,19453,19442,36740, 36896,12734,36915, 9996,34312,34156,34331,17788,17802,11303,20402,35946, 35927,28627,34175,31573,31373,20417,31389,18322,29285,29523,29303,30738, 36721,33313,33333, 9651,18333,19452,19441,36739,36895,12733,36914,26314, 40623,12765,40108,39363,34244,18711,34242,34102, 9962,32204,20358,35465, 31511,10662,34100,21614,31305,38045,31303,20356,29212,18278,29210,35574, 36667,19038,29469,14373,18276,38264,12694,30319,36822,36665,36820,22228, 34292,18709,34297,34146, 9991,32202,20394,35463,31554,10660,34150,21612, 31353,38043,31358,20397,29263,18314,29268,35572,36711,19036,29508,14371, 18317,38262,12726,30317,36873,36715,36878,22226,26350,24269,27187,27023, 34349,33623,34365,34192,10006, 9763,20429,19758,31594,30997,34209,33641, 31406,31604,31426,30986,29320,28908,29336,29541,36760,36220,29556,28899, 18349,17910,12743,11882,36932,36776,36952,36183,34348,33627,34364,34191, 10005, 9759,20428,19762,31593,31001,34208,33637,31405,31603,31425,30982, 29319,28912,29335,29540,36759,36224,29555,28903,18348,17914,12742,11886, 36931,36775,36951,36187,34330,18612,34311,34174, 9995,31998,20416,35028, 31572,10327,34155,21196,31388,37616,31372,20401,29302,18332,29284,34844, 36738,18648,29522,13851,18321,37976,12732,29919,36913,36720,36894,21052, 34329,18579,34310,34173, 9994,31916,20415,34950,31571,10269,34154,21084, 31387,37522,31371,20400,29301,18331,29283,34781,36737,18624,29521,13773, 18320,37932,12731,29898,36912,36719,36893,20995,39415,36635,36645,36634, 18150,32346,18876,18918,24312,24295,43680,43679,43678,43677,26441,26422, 24311,28102,24294,28101,28100,26440,28099,26421,29619,31706,35564,30395, 24748,12785,38909,17715,34572,32943,34565,32942,33109,32941,33107,32940, 33462,32939,33464,33255,33791,32938,33839,32937,26996,33854,42329,33231, 4860,26990, 4869,42075, 4812,31180, 4889,42318,30662,30658,42070,31184, 42110,29066,28535,28538, 4851,41955, 4868,29084, 4811,42109, 4886,26761, 41954,35888,26760,36447,33841,33229, 6909, 6154,33836,33460,36639,34574, 33128,35369,32936,35343,32935,35345,33257, 4929, 4853, 4801, 8174, 8594, 26661,35341,33835,20883, 4403,27646,33832,36456,29081,34567,33172,36633, 33793,33174,35371,33176,20032, 6170,31135, 7934,31122,21877,36400,15196, 38669,38458,32136,32394,36405, 8854,12314, 8759,21876, 7933,32393,31121, 38668,12313,36399,36404,32135, 8758,15195, 8853,38457,31134,20031, 7031, 27226,35360,33777, 6907, 6152,27545, 7976,27376, 7910,25374, 5783,40720, 5590,40719,27247, 8608,27078, 8710,11395,25577,19533,25579,25372,34570, 33459,36372,38122,40107,18793,26105,38657, 5299, 6951, 5277, 6942, 5207, 35783,36420,35787,36422,35213,30152,35211,30150,35122,30023, 8388, 8378, 8328,24307, 8365,36415,36414,35216,30155,26359,24273, 8422, 8428, 5279, 6944, 5209,32415,39946, 7623, 5315,32412,39943, 7620, 5312,18875,32509, 16150, 2984,35426,30960,32517,16139,30869,11425,25477,25461,30880,11462, 30866,11422,39427,30599,35836,36440,36444,10217,34885,14438,42333,10393, 20892,14503,42335,10413,20894,10266,34883,20882, 5976,26660, 7452,40393, 22765,40392,42558,17686,24994,24996,38675,37474,26104,38673,37292,41297, 41296, 5257,41295,42384,35378,31144, 7315,41309,22694,41308,42557,18046, 26133,26138,42926,17689,25000,24998,26707,26706,11659,19707,23731,16164, 22675, 3628,22673, 3626,27999, 3736,16172,22678, 3635,22677, 3634,28001, 3741,36160,14714,11656,36158,14704,11128,11130,11151,11166,11150,11165, 18238,11137,11136,11156,11171,11139,11158,11173,43676,43675,40426,40422, 23861,43674,43673,25549,11054,28809,30936,11052,11058,24334,28821,28828, 30949,37997,11056,37655,19527,24456,19529,24467,17847,28737,30847,28736, 30846,17852,24463,38607,24789,38434,22436,24452,22433,24449,18761,32104, 30104,18766, 9511,24629,23450,22216,19145,21808, 9502,24823, 9509,24627, 9506,24624,23447,22213,10827,22210,19142,10825,27623,21805, 9499,24821, 12241,24413,11978,11977,24351,37674,12240,38014,12239,24346,11976,11975, 24408,38009,12238,37669,36177,23963,36172,23958,34838,10321,34735,29788, 34724,29777,29106,29096,34761,10289,12275,18486,39272,17971,34802,10265, 12256,24403,12237,12236,24341,37664,12254,38004,12252,24339,12235,12234, 24401,38002,12250,37662,36165,23951,36167,23953,34650,29703,34652,29705, 25917,25916,25915,25914,25913,25912,12270,24399,12269,12268,24337,37660, 12267,38000,36163,23949,34648,29701,39271,39270,39269,39268,39614, 9840, 39611, 9837,39311,39313,15815,18446,15664,18407,25958,25957,39326,39325, 15938,18403,11852,24415,11851,11850,24353,37676,11849,38016,11848,24410, 11847,11846,24348,37671,11845,38011,36179,23965,36174,23960,23948,36162, 34737,29790,34726,29779,23955,36169,25637,25636,25635,25634,39114,39113, 39112,39111,39110,39109,25665,25663,12587,18541,11879,18498,14047,18440, 25702,25701,39166,39165,14090,18402,39108,17936,11844,24405,11843,11842, 24343,37666,11841,38006,34806,10216,34670,29723,34760,10233,11867,24398, 11866,11865,24336,37659,11864,37999,34647,29700,10477, 2940,32467,16149, 32466,16148,22209,30149,27815,22206,30146,27818,21516,30358,29052,42781, 5262,29055, 5650,32406,39962, 7642, 5292,32403,39959, 7639, 5289,30355, 31454,31143,27276,27113,15961, 8496,22495, 8542,26122,26114, 9817, 9816, 40359,40358,40357,38632,36068,38628,36066,25364, 5587,25362, 5585,27744, 35164,27741,32167,30182,43039, 8749,28286,30437,28285,30436,28557,30676, 23626,25167,28284,30435,15392,38911,22203,15663,28480,30608,28283,30434, 13472,38888,38891, 9556, 9558,32073,17462,28408,30540,28282,30433,28281, 30432,28546,30667,23599,25139,28280,30431,32743,17461,17460,16952,32742, 32889,17532,32841,17492,32823,28445,30560,26002,23327,17046,17276,23175, 41237,32840,32328,32320,26000,23174,17275,17045,23326,41235,16461,22851, 41251,16456,22848,41249,14757,14744,14494,14440,28961,31061,24084,26022, 9874, 9881,41268,41241,15171,24103,26041,24102,26040,24101,26039,24100, 26038,24099,26037,41261,24098,26036,24096,26034,24095,26033,24094,26032, 28970,31070,24093,26031,17457,14547, 9868, 9879, 9866, 9877,28967,31067, 24111,26049,15173,41263,24108,26046,39341,22202,15662,28964,31064,24106, 26044,28960,31060,24082,26020, 9865, 9876,32852,17456,17548,32851,17455, 32816,32785,32916,17531,17044, 9586, 9584,32333,32325, 9591, 9589, 9595, 9593,28279,30430,12843,38913,22201,15661,28482,30610,40679,23173,17043, 25319,23325,17274,40677,23324,17273,25317,23172,17042,32839,32327,32319, 13094,11464,19592,25465,14477,13090,14461,13088,11377,11369,28713,30829, 23737,25323,13425,39016,38994,39015,38993,39014,38992,39013,38991,39012, 38990, 9676, 9671,17454,28706,30823,28704,30821,11381,11373,13427,25313, 22200,15660,11379,11371,11376,11368,28703,30820,28278,30429,36332,17990, 14546,14542,14497,14496,22199,15659,17992,36342,13093,13092,22198,15658, 36055, 2866, 2829, 3638, 3744, 3499, 3633, 3740, 3484,11658, 3631, 3738, 3477,11670,11655, 5719, 3176, 5341, 4133, 4211, 6542, 5449, 3341, 6652, 3662, 3115, 5396,14196,14706, 3112, 5394,14194,14701,42953, 8732,11657, 19706, 7754, 3118, 5400, 5399, 3481,11676,19712, 7757,11654,19704, 7752, 5403, 3483, 3120, 5402,14198,14713,27282,27129,15657, 8469,22197, 8525, 25605,25607, 5438, 3330, 5347, 2330, 4205, 6539, 4204, 6536, 4216, 6535, 18237,30015, 5335,42108, 5656,42107, 5334, 4130, 4202, 6534, 9809, 9807, 12024,12022,26008,26705,31206,13483,12498,43672,43671,41432,41401,28098, 41431,41400,28097,12417,12474,37392,41411,10446,37390,41407,43005,41462, 12490,13482,12473,13478,12472, 4325,13891,13909,41113,11025,11027,11024, 41934,41909,41932,41907,41930,41905,43557,43224,41928,41903,25633,26470, 39107,22052,15418,25818,26704,10264,10263,10262,10261, 9791, 9790, 2808, 12838,12830, 2417, 2470, 2512,26469,25852,26468,26467,26466,26465,12840, 41950,41925,41947,41922,41942,41917,41939,41914,15417,22051, 7469,12848, 12847,12835,26703,26702,26701,26700,26699,25611,31367,29516,42166, 4823, 42009, 4867,26799, 4810, 4873,34306,36887,42106,26907,41953,31562,29277, 34302,26934,42162, 4821,42005, 4866,31559, 4809, 4871,31363,29273,42105, 29513,41952,26759,36883,13383,12952,13474,12951,13042,12950,13020,12949, 14487,15161,13350,13349,20985,20984,27892,27483,13348,20983,25782,13347, 20982,25206,12948,12947,20544, 4262,12946,12945,26464,14072,26566,26463, 14046,26580,26462,18439, 4603,14071,13524,14070,18453,18438,17861, 4657, 26461,17863,13626,18471,14057, 4633,13523,14045,22196,21308,39164,39106, 39324,34716,29769,10260,10259,10258,10257,10256,10255,13793,13786,13790, 13783,10254,10253,10252,10251,42104, 9370,42103, 4943,42102, 8891,42101, 4942,42100, 5521,42099, 4941,42098, 4940,42097, 5861,42096, 5548,42095, 4939,42094, 4938,42093, 5224,39607, 6179,39604, 6176,39600, 5011,39597, 5008,32103,30103,11072,11078,12111,13800,13797,39315,12034,12944,13018, 26606,13076,13075,13600,32387,18401,26557,32345,32365,14060,26556,14059, 26555,34072,34074,35363,33779,32386,32385,32344,32363,14015,13566,18400, 18399,32343,32360,41729,41726,14014,13565,32342,31867,18491,10102,13908, 18497,32463,16138,39646,39105,39267,39266,39104, 8395,38401, 6355,41721, 2806,14942,14940,15509, 2419, 2472, 2515,15507,38567,30014,30070, 6192, 21609,14364,18236,30013, 5520, 4129,14974,15523,13346,13345,13381,13344, 13040,13343,14489,15163,24034,23979,13415,25700,25956,25911,18771,18770, 14056,10057,10087,17950,18452,18437,18457,10079,14044,17955,25910,25632, 25631,30112,25667,14089,14069,15937,24022,15654,15908,17948,18398,18397, 32341,15653,30111,12274,11878,12266,12265,12264,12263,11863,11862,11861, 11860,11840,11839,11838,11837,11836,11835,11834,11833,11974,11973,12233, 12232,11832,11831,11830,11829,12231,12230,11972,11971,12229,12228,12248, 12246,12260,12258,12227,12226,32071,25909,12471,23983,23975,13362,39031, 39034,23974,23973,24018,13370,24017,25987,23323,17041,17272,23171,41218, 41216,23170,17040,25985,23322,17271,16688,16705,41214,41212,41210,43228, 43561,41208,41207,43742,19608,11484,16702,22946,41206,41222,23193,17068, 25991,23345,17302,41220,32632,32631,32629,32628,24058,43750,43745,25983, 24057,43749,43744,25982,16694,16693,16711,11413,41203,43739,19605,11481, 16698,22943,41202,11444,12020,11198,11196, 2533, 5649,11154,11169,19364, 19373,23443,23442,25123,25132,17605,17604, 9495, 9494,11149,11164,19361, 19370,23441,23439,25120,25129,17603,17601, 9493, 9491,11276,19424,25193, 11263,28096,22842,19411,28093,16450,25186,22839,16447,14152,14598,14154, 14600,40573,43670,43669,40565,11273,19421,25190,11260,28090,22836,19408, 28087,16444,25183,22833,16441,40575,40567,11622,11639,19673,19690,23659, 23654,25584,25596,17786,17781, 9645, 9639,40577,40569,11148,11163,19360, 19369,23657,23652,25119,25128,17784,17779, 9643, 9637,11628,11646,19679, 19697,23437,23436,25589,25601,17599,17598, 9489, 9488,25173,21913,15232, 25175,22538,16001,12943,12942,20543,20542,27895,27486,11632,11651,19683, 19702,23644,23642,25591,25603,17769,17767, 9618, 9616,11621,11638,19672, 19689,23435,23433,25583,25595,17597,17595, 9487, 9485,24843,24802,27885, 27476,24840,24799,27882,27473,11280,11267,19428,19415,24847,24806,11243, 11222,11278,11265,19426,19413,24845,24804,11247,11226,11246,11225,11245, 11224, 9633, 9626, 9631, 9624, 9630, 9623, 9629,22193,22192, 9622,11609, 19664, 6702,11613,19668, 6646,11653,10814,19162, 2877,11724,19735, 6704, 11720,19731, 6648,12357,10807,19156, 2750,35666,14645,35664,14654,14724, 11679,19715, 6691,35668,14649,10928,10937,12356,22619, 3566,27955, 3703, 22617, 3564,27953, 3701, 3642, 3747, 3503, 3652, 3754, 3510, 3650, 3752, 3508,12361,10908,19215, 2747,10907,19214, 2708,10905,19212, 2706,12355, 22624, 3568,27957, 3705, 3648, 3750, 3506,10913,19219, 2711,36153,14644, 3409, 2351,16161,22670, 3623,22669, 3622,27996, 3733, 3621, 3732, 3472, 36155,14698, 5721, 3178,11637,11620,19688,19671,25594,25582, 6644, 2752, 7104, 3068, 5757, 3211,22609, 3556,27948, 3691, 3647, 3749, 3505,11625, 19676, 2678,14720,14712,14697,12350,20053, 6708,10920,10912,19224,19218, 24965,24961, 6625, 2710, 7088, 3038, 5725, 3182,14643,11645,11627,19696, 19678,25600,25588, 6598, 2670, 7057, 3002, 5681, 3137,11643,11624,19694, 19675,25598,25586, 6604, 2677, 7061, 3006, 5685, 3141, 6665,11636,11619, 19687,19670,25593,25581, 6597, 2669, 7056, 3001, 5680, 3136, 7420, 8000, 6079,22010,27569, 1609,15345,28036, 1696,16260,22730, 1661, 5493, 1546, 6090, 1536,14782,14264, 5488, 3076,11352,19501, 6767,11351,19500, 6759, 7423, 8002, 6081,22012,27571, 1593,15349,28040, 1694,16262,22732, 1659, 11360,11358, 4196, 6563, 4559, 2510, 5632, 6430, 6983, 5538, 5417, 3315, 2532, 5648, 6454, 6991, 5552, 7418, 7998, 6076,22006,27567, 1615,15341, 28034, 1703,16258,22728, 1668, 7429, 8005, 6096,22015,27574, 1945,15354, 28043, 2010,16268,22736, 2045,11018, 7431, 8007, 6100,22017,27576, 1943, 15357,28046, 2008,16271,22738, 2043, 7354, 7956, 6008,21954,27522, 3450, 15280,27974, 3718,16127,22646, 3599,11022, 7356, 7958, 6010,21956,27524, 3452,15282,27977, 3720,16129,22648, 3601, 3219, 5763, 3215, 5759, 3217, 5761,12345, 7373,21966,15294,12347, 7375, 7969, 6025,21968,27538, 3512, 15296,28009, 3756,16192,22687, 3654, 6020, 3468, 7964, 3728,27533,27992, 7367, 3617,21962,22665,15290,16157,11605,11607, 6022, 3470, 7966, 3730, 27535,27994, 7369, 3619,21964,22667,15292,16159, 7212, 7880, 5884,21812, 27338, 1956,15096,27654, 2021,15695,22246, 2056,15652, 7176, 7863, 5878, 21771,27307, 1958,15057,27622, 2023,15651,22191, 2058, 5882, 1979, 7878, 2086,27336,27652, 7210, 2119,21810,22244,15094,15693,15650, 5877, 1981, 7862, 2088,27306,27621, 7175, 2121,21770,22190,15056,15649, 5903, 1972, 7898, 2079,27364,27706, 7254, 2112,21835,22345,15128,15791, 5905, 1970, 7900, 2077,27366,27708, 7256, 2110,21837,22347,15130,15793, 7277, 7914, 5937,21844,27383, 1947,15150,27748, 2012,15903,22442, 2047, 7279, 7916, 5939,21846,27385, 1942,15152,27751, 2007,15905,22444, 2042,11579,15682, 15954,15648, 7174, 7861, 5876,21769,27305, 1951,15055,27620, 2016,15647, 22189, 2051, 7225, 7887, 5893,21818,27346, 1941,15107,27681, 2006,15745, 22304, 2041, 5965, 1995, 7927, 2103,27417,27801, 7292, 2136,21871,22489, 15188,15956, 5967, 1997, 7929, 2105,27419,27805, 7295, 2138,21873,22492, 15190,15959,15725,15646, 5875, 1974, 7860, 2081,27304,27619, 7173, 2114, 21768,22188,15054,15645, 5898, 1969, 7893, 2076,27359,27701, 7249, 2109, 21830,22340,15123,15786, 5963, 1993, 7925, 2101,27415,27799, 7290, 2134, 21869,22487,15186,15953, 5975, 2335, 1930, 5492, 3095, 5371, 1929, 5238, 4396, 6018, 3466, 7962, 3726,27531,27990, 7365, 3615,21960,22663,15288, 16155,15644, 5874, 1989, 7859, 2097,27303,27618, 7172, 2130,21767,22187, 15053,15643, 5896, 1991, 7891, 2099,27357,27699, 7247, 2132,21828,22338, 15121,15784, 5901, 1987, 7896, 2095,27362,27704, 7252, 2128,21833,22343, 15126,15789,40964,40969,11764,11763,12001,12000,19881,19880,27891,27482, 25817,25816,22535,21910,15998,15229,11762,11761,19755,19754,27894,27485, 25630,25629,22537,21912,16000,15231,40905,40903, 9789, 9788,40901,40899, 40897,40896,40966,40971,40909,40907,40895,40894, 6556, 2584,10923,19227, 7632, 5986, 2350, 6894, 5573, 5343, 2349, 6532, 2574, 6531, 2573,11135, 5333, 2323, 6530, 2572, 6538, 2576, 6558, 2586, 6548, 2579, 6523, 2567, 6552, 2581,42955,43330,42965,43372,42963,43370,43386,42977,43388,42979, 43328,42952,27399,27780,18424,10069,27918,27458,27867,27441,27850,27237, 18451,10078,26723,26534,25881,26460,25851,25613,25872,25850,25533,33674, 28935,33476,28743,34646,29699,15642,22186,10387,20541,25975,33672,28932, 25970,25973,25724, 6489, 6488,22185,16713,32639,32637,35179,30117,23822, 35131,30072,15714,22269,15641,22184,15819,22373,15848,22391,12098,15640, 22183,22249,16565,32569,32571, 9719,33478,28745,23832,25719,25969,25718, 34680,29733,14043,18436,14466,14392,25879,25878,39323,17980,39257,17970, 39317,17978,26434,29669,40064,43549,26428,39091,17935,39163,17943,39090, 17934,39625,18600,34033,34028,34031,32368,15883,33670,28930,41658,41677, 41679,39052,40789,10443,20697,10475,20687, 6684, 6686,10479,20540, 6681, 6680,18396,10056,14100,18395,32340,15639,21550,16438,32542,32541,22717, 16437,32540,32539,15638,22182,35542,14642, 7787, 7786,10643,19009,10642, 24512,19008,24672,12068,19901,24016, 6774, 6773,15637,22181,34007,34006, 41647,41646,27847,27438,26554, 9787, 9786, 9785, 9784,43226,43559,43555, 43222,25849,25610,26004,26007,15109,14390,26698,25609,10775,34837,15977, 15208,22514,21889,27846,27437,15976,15207,27398,27397,21864,21863,22513, 21888,27779,27778,15181,15180,27845,27436,22476,22475,15944,15943,24033, 24032,23978,23977,27844,27435,22564,22563,16041,16040,27843,27434,21895, 21894,15214,15213,27842,27433,22520,22519,15983,15982,15206,21887,15205, 27865,21886,27456,27841,27432,21015,21014,13387,13386,27840,27431,20628, 20627,13030,13029,15204,21885,25773,12104,12103,11744,11743,12094,12096, 10779,34810, 9700,23972,23971,27861,27452,20981,20980,13342,13341,11739, 11738, 7942, 7940,10724,10721,23970,23969,23982,24015,23968,23967,24014, 23981,24013,24025,24027,24012,12070,27864,27455,22512,22511,15975,15974, 27863,27454,20636,20634,13035,13032,24511,24671,19132,19131,10760,10759, 10732,10735,24516,24676,19106,19108,10731,10734,24510,24670,19113,19112, 10741,10740,24509,24669,19062,19061,10684,10683,10781,34759,15212,21893, 25753, 7947,10429,10571,18816,18957,24508,24668,10426,10568,24505,18813, 18954,24665,27870,27461,21901,21898,15220,15217,27873,27464,22526,22523, 15989,15986,10439,10588,18828,18964,24526,24686,10437,10586,24524,18826, 18962,24684,11737,11736,11945,11944,10596,10595,11735,11734, 9849, 9848, 12067,12066,14142,14587, 9783, 9782,12065,12063,19900,19898,25848,25846, 24011,24009,17969,17967, 9847, 9845,27876,27467,20539,20538,12941,12940, 15223,21904,25776,12061,12060,14139,14584,12117,12115,19916,19914,25887, 25885,24044,24042,17976,17974, 9858, 9856,11432,19557,25411,28147,22914, 16602,41080,11934,19847,25742,28084,22830,16436,12222,12284,16672,12217, 12215,41025,43668,11931,19844,25739,28081,22827,16433,11412,41027,11312, 19473,25900,25247,19933,12130,41029,11109,19341,25898,25106,19931,12128, 12154,19940,25920,28156,22923,16635,12183,19958,25945,25943,19956,12181, 12158,19944,25924,25951,19964,12197,11798,19788,25675,25673,19786,11796, 11776,19772,25641,25639,19770,11774,24992,20537,12939,12938,20536,25208, 12059,11760,19753,25628,25627,19752,11759,11818,19804,25696,25688,19797, 11808,11820,19806,25698,25690,19799,11810,40597,40758,40595,40594,11733, 11449,11453,19574,25452,28145,22912,16597,12058,11816,19802,25694,25686, 19795,11806,40639,41075,40637,11758,16629,11108,12193,11999,19879,25908, 25815,19937,12138,12206,12205,12038,11757,19751,25785,25626,19870,11960, 12937,20535,25784,25002,20534,12936,12057,43728,43725,32603,11411,19550, 25402,28149,22917,16605,23999,25793,23996,25790,11938,19851,24003,11913, 11936,19849,24001,11917,11916,11915,12045,12042,13120,15165,12156,19942, 25922,25823,19886,12009,12122,19926,25891,25643,19774,11778,12125,19928, 25893,25625,19750,11756,11815,32602,30882,43667,40537,12120,19924,25889, 25693,19801,11814,11107,12033,12192,19962,25949,28154,22921,16628,12191, 19961,25948,12190,19960,25947,25839,19892,12032,12296,19991,26015,12292, 27396,21862,19981,27777,15179,26011,22474,15942,15399,12056,12846,12547, 17076,15466,12055,15522,39256,39255,39254,39253,39252,39251,39263,39265, 39250,39249,39248,39247,41047,41046,41059,41061,41051,41045,41043,41042, 41041,41040,41039,41038,41037,41036,41035,25752,22562,16039,25751,22518, 15981,25750,21013,13385,25749,20626,13028,13044,20642,25772,11943,12102, 11742,12092,41054,41053,41056,12137,41034,14685,12136,11996,25761,20979, 13340,11732,12162,25907,17091,15471,15526,39246,19972,12273,12354,17039, 15458,15506,25771,22510,15973,24007,19896,12053,12090,24029,19903,12089, 24006,19895,12052,24005,19894,12051,15407,12851,41065,41064,41063,41070, 41068,41049,12119,41032,25779,22529,15992,11924,12041,41078,41073,11731, 11311,19472,25246,28144,22911,16596,12050,25764,20533,12935,12049,12100, 19908,25863,12189,12110,11106,19340,25105,28153,22920,16627,12109,19912, 25883,12262,11859,17316,14861,11730,14973,14817,11729,12834,12408,39101, 39103,39089,39088,39087,39086,39093,39095,39085,39084,39125,39121,39124, 39120,40887,40886,40885,40884,40883,40882,40927,40893,40881,40880,40879, 11755,40878,14710,14683,11754,11753,25624,25623,14807,12832,39083,20489, 12859,39082,20052,12349,39081,21547,14236,39080,39079,43776,43805,39078, 40447,43732,17270,14840,14939,17396,14901,15027,12225,12244,40915,40914, 40913, 9781, 9780,11077,40876,40925,40891,40889,40936,40934,39151,39147, 39150,39146,11813,11812,40932,40930,40938,14394,11970,12224,40944,40943, 40942,11828,11827,40940,11826,40911,40947,39308,39307,39140,39139,11752, 19749,25622,25621,19748,11751,14389,39077,39076, 9722, 9721,12135,19936, 25814,25906,19878,11995,12934,13377,12967,13339,39117,39116,39149,39145, 39154,39153, 9830, 9829,13375,12933,13338,12970,40737,40739,40734,17453, 16185,16111,14676,12161,12134,12133,19935,25905,25813,19877,11994,12179, 11794,11750,11749,16595,11439,11438,19567,25441,15755,17269,15754,15753, 25531,25446,25408,19555,11420,25620,26459,25475,25474,25473,19599,11474, 25445,25444,19570,11442,25406,19553,11418,25399,19547,11408,16959,17482, 13265,13337,15636,39056,22178,15634,28773,30900,39099,39097,39119,39123, 39075,39074, 9703, 9705,17452,28766,30894,28763,30892,28762,30891,12175, 19951,25937,25837,19890,12018,40756,16626,11529,39135,39137,14641,11793, 19784,25671,11748,19747,25619,12932,20532,25424,12048,11528,11522,11747, 19746,25618,11780,19776,25645,12178,19954,25941,11436,19565,25426,11993, 11992,19876,19875,27860,27451,25812,25811,22516,21891,15979,15210,25844, 30888,11476,30863,11415,25810,12017,12016,19889,19888,27839,27430,25836, 25835,22509,21884,15972,15203,25834,25940,19953,25939,19544,25396,25395, 25617,19745,25616,19562,25420,25418,25647,19778,25649,19560,25416,25414, 25670,19783,25669,19543,25394,25393,34715,29768, 1823, 1805,12576,24366, 1065, 1012,24432,38030,12599,37738,35076,34899,38032,37740,24173,22266, 24434,21419,27315,26681,20922,13278,20920,13276,29112,20926,13281, 1859, 1842, 1150, 1140, 9932,39742, 9931,39741,24819,39740,34742,29795,13907, 18540, 1482, 1476,12573,24363,12596,37734, 1062, 1009,24428,38026,12611, 42344,12595,37733,35078,34901,38034,37742,24175,22274,24436,21423, 9930, 39739, 9929,39738, 9926,39729, 9925,39728,24831,39727,29130,37421,29129, 37420,29099,29109, 1469,36495,37425,37424,37423,12586,18539,12624,42360, 20171,42676, 1479, 1473,12626,20173,42362, 1481,42678, 1475, 8054, 9922, 39720,29125,37415,38037, 1149, 1139, 1152, 1142,12620,20167,42355, 1145, 42671, 1135,35453,39526,38500,38702,24594,22314,41882,29647,27291,27290, 27617,27314,27289,12795,30387,38366,30408,38358,38363,38365, 2930,38357, 2387,37255,29642,37254,29641,37253,29640,19022,43201,30416,38370,27663, 37246,36144,37245,38299,40063,31679,40062,31678,31738,31737,31705,35446, 31723,24604,15633,41888,29654, 8044,31735,38376, 2386,35443,31719,35442, 31718,32516,16284,32479,16283,35456,39528,38504,38704,24596,22316,41884, 29649,24601,29658,41890,15385,37241,37244, 1421,40058,31676,40057,31675, 38385,12811,24756,12793,29602,30390,38389,38388,29600,29596,29618,31704, 34636, 1433,29689, 1438,43219,43551,24599,29653,41887,15383,24598,29652, 41886,15382, 1285, 1418, 8050,38379,12806,24754,12791,24750,12787,38378, 38384,12810,38375,38387, 1306, 1294, 1303, 1291,29617,31703,29612,31698, 34634, 1429,29687, 1436,43217,43548,34630, 1300,29683, 1288,43212,43540, 30964, 3798, 3778, 3800, 3780,35425,30959,32462,16137,32461,16136,36652, 34579,34586,36650,34577,34584,34085,29464,31470,29585,31656,31506,29370, 29462,31468,29583,31654,31504,29368,36644,21875, 7932,32392, 5254,31444, 20450,38667,12312,36398,36403,31443,31624,36800, 8757,12755, 8518,15194, 8852,38456, 8493,31120,31133,36972,36799,36971,12754,32134,20030,31623, 6169,20449, 7030, 8702, 8337,38763, 9313,41293, 8934,36480, 8701,43062, 8761,18031, 8593, 8173,38803,36371,36370,36369,18030,18029,18028,27225, 41287,29017,38339, 8204,38308, 8169,34386,32391,34385,34228,31132, 7931, 33774, 8517,31642, 8756,34227, 5253,36397,31641,38666,35366,35201,38455, 33771,29576,36805, 6168,29575, 8492,36402, 8851,29015, 7029,36978,36804, 36977,30301, 8061,41292, 7297,38121,38120,36368,18792,38119,36491,38118, 38117,38116,31119,31118,41283,18027,41285,18033,27911,27641,42858,42857, 26103,35204, 5619,36383, 5616,36380,24771, 7553,40207, 6407,31301,24617, 34240,40205,34238,34098,31299,39906,36663, 7199,39905, 6221,43351, 7551, 34096, 6406,29208,43349,36818,36661,36816,42721,29206,27330,42720, 7197, 27172, 6220,24769, 7550,40204, 6404,31297,24616,34236,40203,34234,34094, 31295,39903,36659, 7196,39901, 6218,43348, 7549,34092, 6402,29204,43347, 36814,36657,36812,42718,29202,27329,42716, 7195,27170, 6216,34504,30404, 34501,30401,18155,41645, 6885, 6148,41642, 7307,41673,41778,22311,41672, 22818,41641,22547,41640,22332,41639,26348,26380,22545,41668,18159,41675, 38227, 2955,34005, 2993, 2916,38213,34004, 3252, 2894,38183,34025, 3229, 2887,38169,34020, 3222, 2627, 2643,38824, 9409,41720, 9218,36476, 2626, 41719, 2595, 2647, 2634,23169,18235,22102,18234,18217,21766,22081,18233, 37188,18232,18231,18230,18216,21765,21923,18229,18215,36632,14274,35340, 34569,20455, 2653,31640,31453,36976,12760,36803, 2617, 8060, 8540, 8244, 38393, 6849,41718, 6440, 2625,36148, 8149,38297,41717, 3792,18228,18227, 6920, 6161,18226,18225,18224,18223,21921,18222,18221,41757,26415,41756, 26414,20448, 2591,31622,31442,36970,12753,36798, 2464,18210,26408,26407, 41754,34549,35325,41666, 7314,41665,41776,22693,41664, 6432,42556,18178, 26697,26356,26393,34087,38762, 9312,41711, 8933,36479, 2483,41710, 2455, 38802,37153,37152,37151,18209,18208,21763,18207,29565,21760,37224, 2557, 18220,37221, 2554,36643,20333,36602,39439,31285,36604,39484,24264,40237, 40132,40235,40130,39442,31290,36609,41735,39478,24258,40093,40186,40088, 40181,18143,34398,34435,37029,20279,36994,18145,34400,34437,37031,20281, 36996,39483,24263,39482,24262,39486,24266,40091,40184,40086,40179,40083, 40176,40081,40174,40241,40136,40239,40134,34758,10627,34757,10559,39303, 39305,34812,10557,37291,38086,37290,38094,37289,38080,38614,37288,38662, 37287,38664,37301,38656,37473,38655,30133,20531,10622,20530,10525,18394, 10055,18422,10067,18393,10054,26458,26696,10410,13522,15751,22319,25877, 34645,29698,34644,29697,34660,29713,38660,37435,37440,34753,29806,34751, 29804,34672,29725,34643,29696,34642,29695,34656,29709,34662,29715,34730, 29783,34732,29785,34677,29730,34641,29694,34640,29693,34667,29720,34666, 29719,37327,38096,20808,13191,18392,18391,10053,20807,20851,13231,18390, 18389,10052,20850,20857,13235,18421,18419,10066,20855,18410,10062,18477, 10096,20791,13179,18409,18412,10061,20790,14025,18388,13571,18387,20836, 13215,18414,18417,10064,20835,13521,18416,34836,10553,34691,29744,13625, 18470,13520,18480,39295,39298,12931,20529,20572,10615,12981,20574,12930, 20528,12929,20527,12928,20526,32453,16108,27288,18450,10077, 5631,37822, 5630,42452,42565,18490,10101,13290,20941,13178,20789,13214,20834,34706, 29759,34699,29752,13177,18474,20788,20787,18476,10095,13213,18479,20833, 20832,18482,10098,13176,18538,13175,18496,32478,16282,32460,16135,13212, 20831,13174,20786,13220,20838,13190,20806,13230,20849,32339,15631,32362, 15847,32337,15629,39186,39188,15802,22360,25843,39259,39261,15628,22173, 25858,39245,39244,12083,12081,10274,39719,40156,40256,40155,40255,24386, 15813,24636,13407,30271,30269, 6595, 6594,34679,29732,14042,18435, 6251, 6249,13292,20943,34704,29757,34702,29755,34701,29754,13119,13118,18533, 32482,16287,10342,39718,40154,40254,40153,40253,24396,13488,24439,13440, 30194,30193,34714,29767,38659,37400,37405, 8700,30362,30361,30170,30169, 37413,34739,29792,39737,10247,30192,30191,34741,29794,13117,37729,13629, 42340,24441,13487,24438,13490,39736,10215,39748,10210,39731,10209,39726, 10220,39735,10208,39725,10245,39733,10222,39717,10213,20954,10594,10379, 39764,10378,39763,39762,10528,40246,40143,40245,40142,40220,40105,40219, 40104,18564,10135,20952,13301,18563,18571,10134,20960,10373,39756,18559, 10130,20948,13297,18558,18567,10129,20956,10205,34916,34923,37772,13502, 37765,10203,34914,34921,37770,13500,37763,39761,10377,40172,40079,40170, 40077,40152,40252,40151,40251,39766,10523,40161,40261,40160,40260,40233, 40128,40231,40126,34851, 9960,34232,34090,10334, 1864,21204, 1757,32005, 1601,35035, 1797,31293,31509,31895,20354,29864,18274,29200,29467,37983, 1814,29926, 1571,18655, 1742,13858, 1881,36810,36655,37623,12692,34934, 34778,34003, 7306,34002,29395,34001,34498,34011,34508,34000,34497,40229, 34492,41761,34931,34775,41968,34018,34514,40243,34516,42397, 1037,41633, 1031,41632, 1048,42392, 1022,41635, 1050,42394, 1024,41760,41631, 1046, 42390, 1020,41629, 2954,41628, 2992,41627, 2915,41626, 3251,41650, 2892, 41652, 3227,41656, 2886,41654, 3221,34263, 9979,34254,34121, 9970, 936, 20366, 931,31521, 926,34112, 921,31315,31530,31324,20375,29222,18286, 29231,29479,36686, 916,29488, 911,18294, 906,12712, 901,36842,36677, 36833,12703,34381,31639,34224, 2650,34226, 2616,31621, 2599, 2652,36975, 34384,36802,29572,36797,29574,36969, 2482, 6384,37645,37150,37149,39645, 37635,37644,37632,37148,37147,37146,37145,37144,27910, 2624, 8314, 6262, 41716,37187,38260,37297,37347,42609,32086,38078,37639,34016, 7313,34015, 29397,34014,34512,37090, 2481, 2480, 2630, 2637, 2505, 6421,37518,37128, 37399,37127,37495,37126,37469,37124,37468,37513,37142,37123,37511,37462, 37299,37756,37434,37122,37141,37121,37140,39431,36631,37412,37404,37498, 37494,37472,10043,37461,37460,37467,10039,37458,37457,37647,37138,37137, 37120,37510,37517,37520,37174,37505,37439,29444,37119,37136,37135,37172, 37170,37118,37117, 2641, 2632,39414,26406,26405,27640,42564, 2623,37566, 37286,31638,12764,12757,41733, 2622, 2621,37527,37402,37492,10045,37455, 37454,37465,37185,37508,37437,37184,37183,26413,27645,42561,20297, 2612, 20295, 2610,35114, 2608,35112, 2606,12763,37557,39421,18930,22264,27005, 21417,13951,24817,38564,38257,38562,37452,38560,30007,38068,32735,32711, 38761,32710, 9311,38760, 9310,38072,32709,38071,32901,38070,32764,17268, 23321,24825, 9217,24780, 9216,17267,38060,16897,38059,17340,38058,17530, 38066,27635,27312, 7608,38801,32708,27786,32093,30095,22171,15627,38645, 30126,38644,38643, 5247, 5530,32815,38800,32814, 9381,38799, 9380,38075, 32813,27684,30333,18707,35295,27162,27153,35405,22170,39882,38555,24446, 22351,39919,38609,24465,35332,27193,35291,27160,27150,35403,42950, 8731, 42949, 8730,42948, 8729,42947, 8728,35377,32076,40005, 8482,40002, 8479, 35541,14640,35540,14639,14313,27249,27251,17038,23168,24827, 9024,24782, 9023,17037,38063,27021,16563,38690,23265,21508,37451,38084,32336,32515, 15626,32520,15625,32511,15677,32508,15624,32529,16280,38571, 5200,32335, 15623,35539,14638,14662,14637,35552,14666, 8626, 8629,14668,14708,18932, 22271,27007,21421,13942,24829,30360,42780,35108,30005, 5647,35143,30085, 5665,22165,18820, 5605, 5604,35347,32111,32506,15929, 6955, 5331,40061, 43546,42762,18769, 6937, 5272, 6936, 5271, 6935, 5270, 6933, 5268, 5629, 22268, 6939, 5274,22180,22164, 6946, 5281,25809,32240,18748, 8323, 8156, 8316, 8158, 8320, 8153, 5580,35374,32097,35335,32096,35334,32095,32513, 15882,32367,15881,38759, 9309,43061, 8932,36478, 8059,38798,38115,38114, 38113,18791,18790,18789,30347,37642,37515,37450,38130,37755,38112,38111, 27909,27639,37569,38128, 3646,22685,16184, 6338, 1522,12640,12645,15371, 6342, 1510,12642,12647,15373, 6782, 6781,14798,21699, 6344,14796,21697, 6341, 7801, 1555, 7440,12375, 7443, 8012, 6107,22026,27582, 1592,15367, 28052, 1693,16277,22744, 1658, 1489, 7435,12373, 7437, 8010, 6105,22021, 27580, 1940,15362,28050, 2005,16275,22742, 2040, 7442,22025,15366, 7439, 22023,15364, 7426, 1562,12340,12333,12338,12331, 5804, 3214,12342,12335, 6027, 3514, 7971, 3758,27540,28011, 7377, 3656,21970,22689,15298,16194, 15505,12533,15504,14938,16379,14982,16012,12532, 6752, 1497, 6749, 1494, 41395,41428,41393,41426,41397,41430, 7673, 2785,12396, 3807, 8862,12509, 12436,12393, 5370, 3094,12439,12401, 5365, 3088,14737,14216, 5440, 3335, 3128, 5405,14200,14716, 3087, 5364,14181,14664, 7871,12398, 4411, 4409, 12435,20087, 6593, 3074, 5351,14171,14636,12448,20094, 6591,12546,15118, 21825, 7236,12545,20135, 6451,12407,12544,12406,12388,12506, 3804, 8859, 12522,12505, 7664, 2776, 7671, 2783, 7717, 2884,41403,41434, 6017, 3465, 7961, 3725,27530,27989, 7364, 3614,21959,22662,15287,16154,15051,21757, 7169,12568,20156, 6382,14937,21735, 6848,41461,41460,12427,20084, 2755, 31205,31204,16392,12489,12488,12426, 4417,13481, 2225, 7635, 2415,15621, 7167, 7858, 5873,21755,27302, 2239,15049,27613, 2245,15620,22163, 2261, 7304, 7938, 5973,21879,27421, 2241,15198,27830, 2247,15967,22504, 2264, 7251, 7895, 5900,21832,27361, 2237,15125,27703, 2243,15788,22342, 2257, 16032,12416,20081, 7526,31201,12415,12414,15686,15952, 2667,15619, 7166, 7857, 5872,21754,27301, 1949,15048,27612, 2014,15618,22162, 2049,12423, 7223, 7885, 5891,21816,27344, 1939,15105,27679, 2004,15743,22302, 2039, 12404, 7351, 7953, 6005,21951,27517, 3446,15276,27968, 3715,16106,22638, 3587, 2256,21296,12567,13748,20155, 2235, 2255,21295,12566,13747,20154, 2234,12560,20148, 6450,41459,15243, 3788,41450,15617,41420,41458,12425, 20083, 2209,31821,12497,12496,15117,21824, 7235,12562,20150, 6449, 2227, 2223,12487,20114, 4245,12485,20112, 4243,12875,20501, 4242,14245,41418, 41456,12559,20147, 2220, 6016, 3464, 7960, 3724,27529,27988, 7363, 3613, 21958,22661,15286,16153,12500,12432, 7405, 7990, 6044,21993,27559, 1591, 15324,28021, 1692,16231,22715, 1657,15316,41467, 2217,12430, 7400, 7988, 6042,21988,27557, 1938,15318,28019, 2003,16229,22713, 2038, 7404,21992, 15323, 7402,21990,15321, 1457,21287,12552,13738,20140, 1453,41444,15320, 41469, 1463,15615,15612,16030,12413,20080, 1444,12412,20079, 1443,31824, 31818,12565,20153, 2233,12484,32070,12483,12482,13480,13746,21294, 2254, 12481,20111, 4241,12480,20110, 4240,12492,20116, 6512,12479,20109, 6380, 2268,22161,15610,15609,22160, 2259,15966,22503, 2263,12420,12419,15685, 22239, 2251,12495,12558,20146, 2219,12554,20142, 1460,15103, 2216,41454, 12422,41409,41438,15245, 3790,41453,11020,40855,30973,11578,11577,11591, 11575,11589, 4564,11583,11582, 2666,11586,11585,12828,12826, 5829, 3832, 12874,12870,20498, 3812,12869,20497, 3811, 3831, 5828, 3830, 5827, 3834, 5831,12877,12879,12873, 7468,22050,15416, 2531, 5823, 3818, 3836, 3843, 12884,20506, 3875, 3905, 5843, 3898, 5839, 3900, 5841,12888, 7474,22057, 15423,12890, 7476, 8024, 6122,22059,27597, 3926,15425,28070, 3966,16337, 22799, 3955, 6117, 1968, 8021, 2075,27594,28066, 7460, 2108,22041,22773, 15405,16310, 7454, 8017, 6112,22034,27590, 1937,15390,28062, 2002,16302, 22767, 2037, 6115, 1983, 8019, 2091,27592,28064, 7456, 2124,22037,22769, 15401,16306, 7450, 8015, 6110,22032,27588, 1954,15388,28060, 2019,16293, 22756, 2054, 6109, 1977, 8014, 2084,27587,28059, 7449, 2117,22031,22755, 15387,16292,12895, 7488, 8031, 6129,22071,27604, 1590,15438,28077, 1691, 16344,22806, 1656, 3810, 3826, 3829,12893, 7483, 8029, 6127,22066,27602, 1936,15433,28075, 2001,16342,22804, 2036, 7487,22070,15437, 7485,22068, 15435, 5838, 3897, 3886, 3910, 3915, 3877, 3891, 3902, 3874, 3889, 3896, 3873, 3888, 3895, 3879, 3893, 3904, 6124, 3932, 8026, 3972,27599,28072, 7479, 3961,22062,22801,15428,16339, 3884, 3908, 3913, 3809, 3825, 3828, 12865,43305,43632,43303,43630,43300,43627,43299,43626,14287,43298,43625, 43296,43623,14936,21734, 6847,22080,14935,22079,19102,22101,19101,14934, 43294,14933,43621,14932,14931,15462,15475,15457,15456,14956,14950, 6852, 6846, 6845,15485,14333,14993,14992,14981,15007,15006,15005,15022,15014, 15010,15009,15004,15025,14351,15024,15483,15020,14349,15012, 5524, 1639, 14997,14337,14991,14332,14980,14979,14978,14995,14335,14984, 5519, 1906, 14339,15000,14999,43316,43637,15003,15479,14306,43314,43635,15041,14354, 15040,15493,15044,14356,15043,15495, 6866,14914,21725, 6369,14916,21727, 6371,12858,20488, 6820,12872,20500, 3817, 3953,22796,16334,12883,20505, 3872, 3952,22795,16333, 3951,22794,16332, 3865,22785,16323,19032,19100, 38551,19030,19099,38548,30001,29999, 6915, 4625, 4602,35104,29997,15608, 22159,15607,22158,15821,22375, 3127, 3334,35145,30087, 3314, 3325,15606, 27585, 4632,15846,22390,40060,43545, 2385, 2530, 2543,40009,43415, 2964, 38234,30168,30190,40054,43537,30277,23167,19097,40033,43462,38797,32707, 2929,30189,40458,23320,17266,25101,23166,17036,40446,23349,17310,25097, 23198,17075,38926,38925,38924,38923,39028,39026,38922,38921,38920,38919, 39041,39043,40452,40462,40454,40445,40444,40442,40449,32588,32587,32586, 40456,23339,17294,25099,23187,17062,32922,32788,16896,17339,32594,40441, 16617,25096,16879,23055,40439,16911,23063,40438,40437,23400,17527,16871, 23049,40436,40435,22906,16587,40434,22905,16586,16585,22904,40433,40432, 22903,16584,16868,23046,40465,16590,22909,40464,16609,16607,16594,43731, 43730,40431,40430,39039,39038,39037,39036,16616,38937,38936,39243,39241, 38935,38934,39292,39288,17173,16615,16752,16614,16613,16612,16744,16611, 16789,39239,39238,16852,17211,32900,32763,16623,16621,11076,11075,39237, 39236,39278,39277,39276,39275,11952,19862,25769,25748,19855,11942,32899, 32762,17499,17451,17325,25842,21445,14034,17484,16791,25870,23275,17187, 25841,23273,17185,25876,23263,17165,11948,19858,25763,13414,13413,39216, 39215,39197,39196,39291,39287,12478,12477,13373,13336,13335,13368,12031, 12030,39235,39234,12108,12107,39284,39283,11941,11940,19854,19853,27900, 27491,25747,25746,22542,21917,16005,15236,39233,39232,39203,39201,27879, 27470,27855,27446,27838,27429,25904,25903,25745,25955,25902,18666,42563, 25759,25755,25998,27775,25808,27637,27015,27615,41158,41157,27836,27427, 27049,27611,39207,39211,11951,11950,19861,19860,27835,27426,25768,25767, 22508,21883,15971,15202,25766,11956,11954,19866,19864,27875,27466,25778, 25775,22528,21903,15991,15222,39221,39219,39224,39223,39290,39286,39231, 39230,39281,39280,14930,14929,14847,14954,14316,21588, 3816,14319,21591, 3882,14318,21590, 2882,14948,14946,14294,21570, 893,14296,21572, 964, 8262, 8413, 8261, 8412, 8253, 8404, 3081, 5860, 3167, 5859, 3175, 8260, 8411, 1395, 1411, 1414,21584,14311,14347,21606, 1403,14305,21581, 1409, 14342,21602, 3815, 8259, 8410, 8258, 8409, 8252, 8403, 1406, 1393, 1111, 1117,14703,14648,14660, 8187, 8350, 3080, 2322, 5710, 3166, 5718, 3174, 11162,11147,19368,19359,25127,25118, 6642, 2749, 7102, 3062, 5755, 3209, 11161,11146,19367,19358,25126,25117, 6623, 2705, 7086, 3036, 5723, 3180, 14635,11168,11153,19372,19363,25131,25122, 6590, 2665, 7054, 2999, 5678, 3134,11160,11145,19366,19357,25125,25116, 6600, 2674, 7059, 3004, 5683, 3139,14894,16401,15605,15603,14362,15842,14927,16368,43326,42946,43324, 42944,43321,42941,42939,43319,43255,43588,43263,43596,43262,43595,14473, 21643, 6260,30231,32200,38696,30229,38545,30262,30167,38588,30018,30166, 30012, 3276, 3434,43569,43236,43566,43233,16329,22791, 6234,16050,22573, 6247, 7829, 7736, 7585, 7869, 7600, 6756, 7794, 7740, 6576,14475, 6583, 7597, 4175,14479, 4170,15601,22157, 6792,15140,15600,22156, 7261,14360, 2881, 2805, 5527, 2986, 2945, 2937, 2928, 2927, 2384, 2977,38654,30261, 8287, 8126, 8281, 8116, 830, 8286, 8125, 8285, 8124, 824, 827, 8303, 8131, 8302, 8123, 8307, 8101, 8300, 8301, 8120, 8121, 8299, 8119, 8297, 8118, 8295, 8104, 8292, 8129, 8306, 8103, 8308, 8106,30038,30035,38259, 30315, 8425, 8427,32057,14884,13417,15599,22155, 6511,15656,22195, 7821, 6331, 6427,15712, 6424, 7414,15705,22257, 6844, 5887, 5799,16243,14926, 21733, 6841,15598,15965, 6473,22154,15597,15868,15596,15840,22386, 6843, 14445, 5911, 5635,14453,14444,14448,15830,15844,22388, 6840, 5913, 5628, 15833,15827,15826,14839, 7575,15595, 2872, 2741,14925,21732, 6839,15594, 22153, 2833,15593,22152, 2835,15592,22151, 2438,15591,22150, 2432, 2664, 15875,22409, 2445, 2717,15589,22148, 7839,16355,16374,15782,22336, 7823, 16357,22809, 7240,16207,22702, 7765,14756,14227,14755,14226,14754,14225, 16218,16217,43513,43174,43510,43171,16224, 6719,21546,14235,16216,22706, 6725,14763,14230,16220,15588,22147, 7390,15933,22467, 7388,43505,43166, 43502,43163,16209,22704, 7767,15811,22366, 7394,16146,22656, 7387,16145, 3605,22655,16144,15587,22146, 7231,15855,16035,15854,16034, 2839,15860, 22399, 2838,15859,22398, 7229,15586,22145, 7501,30128,38653,30132,38652, 38681,38651,30131,13334,16069,22590,16078, 6270,22599, 6269,16181,12927, 27932, 6914, 6960, 5414, 8057, 5957, 6506, 6505,18941,18940,10538,10537, 16179,13333,16170,13332,16388,15017, 7588, 6306, 5236, 5811, 5851, 5869, 6740, 7127, 5798, 6468, 6996, 5564,14405,14018,14404,14017,15770, 6466, 6994, 5562,14450,14447,15769,15768,15767,16373,22815, 7228,14407,14020, 15772,16122,22643, 7227,14409,14022,14443, 5547, 5223,32069,27917,16038, 22561,16037, 6291,22560, 6288,27915,15874,22408, 4435,15801,22359, 4459, 6574,22144,15585, 6562,22358,15800, 6582,22406,15872,16011, 5655, 4128, 15584,22143, 4437, 5660, 4093,14634,14633,14632,14631,43483,18998,16048, 22571, 6258,43478,43131,43475,43128, 6707,21367,13906,16183,22684, 4239, 14678, 6689,21336,13835,14680,16124,13331, 5770, 5919,14672,14671, 5768, 5868, 5766, 5907, 6561, 4189,15911,22448, 6838, 5943, 5627, 6442, 6987, 5542,15703, 5594, 5416, 5598, 6075, 7011, 7997,28033,27566, 6496, 7417, 22727,22005,16257,15340,15583, 5600, 5867, 7013, 7854,27610,27300, 6498, 7163,22142,21753,15582,15047, 5945, 5645, 6724, 7116, 5787, 5602, 5947, 7015, 7918,27754,27388, 6502, 7285,22459,21851,15927,15157, 5597, 5962, 7010, 7924,27798,27414, 6495, 7289,22486,21868,15951,15185,15455,16352, 15503,16351,16350,15513,22106, 7835,14844,21717, 7820,14886,21720, 7819, 15410,22044, 7818,14825,21708, 7817,14824,21707, 7816,16199,22692, 7815, 14883,14823,43587,43254,43586,43253, 7825, 2663,16362,22811, 1398,16367, 16366,43289,43616,43594,43261, 2414,16372,22814, 1155,16371,22813, 2421, 16359,43280,43613,43252,43585,14838,16365,16364,43278,43611,43275,43608, 43273,43606,43291,43618,15447,38524, 8682,15449,38526, 8684,43271,43604, 43270,43603,43598,43265,43259,43592,16370,43269,43602,43017,43408,15858, 3596,22642,16121,15857,22397, 2837,14234,21545, 6718, 5782,14743,21688, 6318,16198,16215,16304,16214,16197,16213,16206,22701, 7764,16205,22700, 7763, 6717,21544,14233,16291,16212, 5810,43103,43458,40124,14170,40123, 14169,30188,30187,38695,30186,38694,30185,32066,32060,14630,14629,14628, 3343, 7680,39970,32449, 5425, 7677,39967,32446, 5422, 8440, 8451, 3712, 3440, 3696, 3415, 3589, 3585, 3711, 3439,14244,43101,43456, 6671,21079, 13519,15581,16237,43099,43454,43111,18997, 3710, 3438,43109,18995,43123, 43470,43120,43467,16101,22636, 3583,15932, 3604,16312,16142,14805, 5765, 5233,43113,43460,16120, 3595,16119,22641, 3594,16118,22640, 3593,14803, 16047,22570, 3522,16046,22569, 3521, 6706,20785,13173, 6447,21556,14255, 6445,22725,16252, 6333, 6444,14418,14028,14442,15337, 5596, 6067, 7009, 7995,28031,27564, 6494, 7412,22724,22003,16251,15336, 6435,21554,14253, 6438,22722,16249, 6434, 7416,14753,14387, 5540, 6065, 6985, 7993,28029, 27562, 6437, 7410,22721,22001,16248,15334,15301,21973, 7380, 6030, 5803, 6029, 5775, 6743, 7129, 5801, 6731, 7122, 5793, 6727, 7118, 5789,14760, 6032, 5777,14746, 7386,21979,15307, 5781, 5452, 6034, 5779, 6723, 7115, 5786, 5795, 6039, 7124, 7983,28016,27552, 6733, 7396,22710,21984,16226, 15312,14752,14748, 5791, 6037, 7120, 7981,28014,27550, 6729, 7392,22708, 21982,16222,15310,43027,14465,21641, 6257,16327,22789, 6256,32237,15002, 14464,14463, 6589, 6484,21453,14051,16246,14469,14468,15689,15950, 6254, 15580, 5571, 5866, 7001, 7853,27609,27299, 6481, 7162,22141,21752,15579, 15046,14751,14471, 5569, 5889, 6999, 7883,27677,27342, 6479, 7221,22300, 21814,15741,15101,16326,22788, 3938,43577,43244,43574,43241, 6819,21366, 13905, 6818,20784,13172,16331,22793, 4238, 5813, 3987, 6796,21319,13807, 5817, 4015, 5809, 4012, 6805,20713,13116, 6807, 7147, 5834,20783,26609, 3845,13171,26853, 3838,13666,21222, 3820, 6790, 7138, 5808,20805,26616, 1953,13189,26857, 2018,13674,21227, 2053, 5807, 1976, 7137, 2083,26636, 26874, 6789, 2116,20848,21247,13229,13701, 5821, 1967, 7144, 2074,26629, 26867, 6800, 2107,20830,21239,13211,13692, 6794, 7140, 5815,20782,26608, 1935,13170,26852, 2000,13665,21221, 2035, 5819, 1985, 7142, 2093,26647, 26885, 6798, 2126,20870,21256,13245,13708,16325,22787, 3937, 3940, 3946, 3921, 3959, 3970, 3930, 3950, 3964, 3924, 3936, 3944, 3919, 3949, 3963, 3923, 3957, 3968, 3928, 6835, 7154, 5848,20903,26670, 1589,13261,26895, 1690,13717,21268, 1655, 3935, 3943, 3918, 6830, 7152, 5846,20898,26668, 1934,13256,26893, 1999,13715,21266, 2034, 6834,20902,13260, 6832,20900, 13258,16315,22777, 3856, 3855, 3861, 3850, 5836, 3848, 7149, 3841,26628, 26866, 6809, 3823,20829,21238,13210,13691, 3934, 3942, 3917,14837,21713, 6353,22100,14836,14835,14846, 6851,21738,14952, 6837,21731,14924,15502, 15501,15516,15528,15540,14882,15536, 5864, 1638,16378, 5858, 4127, 5857, 1905, 6854,21740,14967,14881,15534,14878,14906,15544,15546, 6862,21746, 15035, 6864,21748,15037,14867,14908,14897,14891,14888,14899,14875,14880, 16098,16095,22634,22631, 3578, 3575,22629, 3573,27960, 3708,22608, 3555, 27947, 3688,22606, 3553,27945, 3686,40118,14110,30165,38687,30164,32068, 3274, 3432, 3268, 3426,27965,27963,14626, 5349,27940,35536,14625,35538, 14627,35535,14624,35534,14623, 6664, 6663, 4303,21444,14033, 6560,21443, 14032, 5738, 3196, 2528, 2527, 5644, 7042, 8345, 8183, 2526, 3323, 3317, 5640, 7038, 6931, 5266, 5641, 7039, 2524, 3313, 7732,39979,32435, 5362, 7729,39976,32432, 5359,22612, 3559,27951, 3694,22611, 3558,27950, 3693, 7630,39953,32422, 5322, 7627,39950,32419, 5319,35533,14622,35532,14621, 35531,14620,35545,14653,35530,14619,35544,14652,10716,10713,10708,10705, 35527,14616,35529,14618,10710,10707,10593,10592, 2702, 2690,18867,18855, 10470,10458, 5741, 3199, 7099, 3049,24735,24575, 5733, 3191, 3272, 3430, 5735, 3193, 5734, 3192, 7096, 3046,24732,24572, 5731, 3189, 7094, 3044, 24730,24570, 5728, 3186, 7091, 3041,24727,24567, 5715, 3172, 7083, 3029, 24724,24564, 3270, 3428, 2700, 2688,18865,18853,10468,10456,43482,18834, 5709, 3165, 5704, 3161, 5626, 4113, 5855, 4085, 5662, 3986, 5701, 3158, 5693, 3150, 7077, 3022, 7069, 3014,24716,24556,24708,24548, 6620, 2699, 6612, 2687,18985,18864,18977,18852,10613,10467,10605,10455, 5697, 3154, 5689, 3146, 7073, 3018,22604, 7065, 3010,24712,24552, 3551,24704,24544, 6616, 2694, 6608, 2682,27943,18981,18859,18973,18847, 3684,10609,10462, 10601,10450,22603, 3550,27942, 3683, 2696, 2684,18861,18849,10464,10452, 5698, 3155, 5690, 3147, 7074, 3019, 7066, 3011,24713,24553,24705,24545, 6617, 2695, 6609, 2683,18982,18860,18974,18848,10610,10463,10602,10451, 28004, 3126, 3060, 3379, 3125, 3123, 3122, 3333, 3066, 3383, 3065, 3382, 10507,18914,10506, 2875,18913, 2874, 3304, 3493, 3302, 3491, 3301, 3490, 2746, 2745,18889,18888,10490,10489, 2744, 2743,18887,18886,10488,10487, 14522, 5654, 2538,15766,15765,14397, 8138, 8310, 5559, 5546, 5545, 5222, 5707, 5221, 5717, 5544, 5220,16422,16417,16419,43666,43661,43664,43659, 43656,43654,43652,43650,43643,43648,43641,43646, 1721, 7573, 1718, 7570, 7711, 2859, 7706, 2844,16494, 7690, 2800, 7688, 2798, 7687, 2797, 7709, 2857, 7704, 2842,16484, 7694, 2813,16502, 7685, 2795, 7714, 2864, 7684, 2794,16491,16490, 7693, 2812, 7683, 2793,16534,16541,16532,16539,16547, 16552,16489,16551,32547,16545,32549,16550,16549,32544,16488,32584,32596, 16580,22899,28140,32583,38724,43714,22901,28142,38722,43712,16582,32581, 16671,16593,16569,16412,16411,16410, 7682, 2792, 7692, 2811,16524,16526, 16408,16407,16430,16406,16509,16506, 3645,22871,16497,16427,16426,22823, 4558,16425,22822, 4556,16592,16500,16511,16465,16469,16467, 7701, 2822, 7699, 2820, 7697, 2818,16504,16951,23098, 8930,32714,16751,16750, 4324, 16746,32898,32761, 9180,23289,17210, 6722,23032,16851,17209,23288, 9179, 17215,23293, 9187,16839,16989, 6471,23037,16857,16836,16987,16831,16984, 43775,43804, 4361, 9178,17191,23279, 9156,17164,23262, 9137,17189,23277, 9154,16785,17184,23272, 9152,17183,23271, 9151,17163,23261, 9136,16793, 17260,23314, 9210,17259,23313, 9209,17258,17257,17256,17540,17520,16895, 16894,17384,16916,17373,17084,23204, 9040,17546, 4126, 8890, 8929,23097, 16950,16949,23096, 8928,16948,23095, 8927,16947,43871,43830,43869,43828, 17472, 6376,22977,16757,16765,22969, 7161,17449,16799,17459,32713,16749, 16748,17470,17447, 8952, 8951,16830,23015, 7448,16850,23031, 6788,32760, 17208,23287, 9177, 8970, 8969,16809,22996, 4555,16808,22995, 6317,16849, 23030, 7159,16829,23014, 6374,16848,23029, 7446,16828,23013, 6786,17207, 23286, 9176,16782,16847,23028, 7215,16827,23012, 6419,16779,17480,32732, 32754,32731,16784,17182,16768, 9189,43807,43778, 4268,17176,17161,43867, 43826,17160,43865,43824, 9208,23312,17030,17255,23160, 9017, 9207,23311, 17029,17254,23159, 9016, 9226,23343,17066,17298,23191, 9030,17028,17253, 9206,23310,17252, 9205,23309,17251,17027,23158, 9015,17250,23308, 9204, 17026,23157, 9014,17249,23307, 9203,17248,23306, 9202,17025,23156, 9013, 17247,16867,17519,16893,16892,16891,16890,16902,16865,23045, 6470,16873, 16870,23048, 6378, 6190,23395,17522,16864,23044, 4525,16883,23059, 4509, 16914,23065, 4508, 9201,23305,17246, 9249,23355,17360,17420,23377, 9272, 17138,23241, 9091, 5871, 7856, 7524, 7165, 8042, 6140,16927,17143,23076, 23246, 7522, 9096,28180,28208, 8040, 9120, 6138, 8876,17436,23391, 9286, 17592,28242, 9307,23430,28276, 8912, 7520, 8038, 6136,17136,23239, 9089, 17430,23386, 9281,17586,28237, 9302,23425,28271, 8907, 7518, 8036, 6134, 9269,23374,16924,17140,17417,23073,23243, 7516, 9093,28177,28205, 8034, 9117, 6132, 8873,17372,16889, 9229,23348,17074,17309,23197, 9034,17073, 23196, 9033,16881,23057, 4517,16670,16574,22893,28134,32575,38716,43706, 22895,28136,38718,43708,16576,32577,32601,16573,22892,28133,16625,22919, 28152,16946,23094, 8925,16945,23093, 8924,38796,32704,17444,17443,17498, 17477,17504,17488,17490,17442,17441,16795, 3581,22981,16775,16774,22980, 4507, 3580,23011,16826, 8943,23102,17179,16957,23268, 9147,32748,32893, 3864,22994,16807,16806,22993, 4539, 2179,23010,16825,17509,16846,23027, 2193, 2184,23020,16838,16855,23035, 2197, 2182,23018,16834,16811,22998, 4506,16813,23000, 4524,16982,16819,43800,43771, 9166, 1673, 9200,23304, 17024,17245,23155, 9012, 9228,23347,17072,17308,23195, 9032, 9224,23341, 17064,17296,23189, 9028,32759,32897,17214,23292, 9186,17206,23285, 9175, 3948,23026,16845, 3644,23025,16844,43803,43774, 9174, 2192,17159,23260, 9135, 9134,23259,17158,17440,17514,17512,16860,23040, 2191,17000,23134, 8995,16998,23132, 8993, 3591,23024,16843,17222,16994, 9192,23296,17218, 9194,23298,17220,17507,16992,23127, 8987,16862,23042, 1328,23154,17244, 17023,17474,17243,17022,17497,17021,17486,17439,17496,17057,17093,17020, 17019,17117,17352,17371,17370,17376,17369,17390,17379,17392,17109, 8894, 1637,17338, 8889, 1904,17356,17103,17438,17401,17126,17403,17128,17409, 23364, 9261,17411,23366, 9263, 8923,23092,16944, 8922,23091,16943, 9133, 2862, 9144, 2791, 9142, 2810, 838,22973,16764,16761,22976, 840, 9131, 2790,16736,16734,17324, 8978,16842,23023, 3814, 9107,23257,17154,17107, 23220, 9070, 9076,23226,17115, 8968, 8967,23119,16978,16803,22990, 3881, 16802,22989, 2880,32747,16805,22992, 1327,16816,23003, 1334, 9165, 8962, 8961, 1344, 9163, 8966,23118,16977, 8964,23116,16975,17217,23295, 9191, 9011,23153,17018,17017,23152, 9010,17120,23229, 9079,17082,23202, 9038, 9062,23213,17099,32758,32757, 8984, 8982, 8977, 8976, 2171, 2170, 2178, 23009,16824,43802,43773, 9173, 2190, 9199,23303,17016,17242,23151, 9009, 9198,23302,17015,17241,23150, 9008, 9196,23300,17239,23148,17238,17237, 17236,17235,17234,17233,17232,17231,17518,17517,17172,17337,17336,17335, 17334,17345,17205,32896,17333,32921,28257, 9056,43837, 9245, 9395,28250, 9329,43796, 9392,28197, 9326,43902,28224, 9053,43895, 9242,43834, 9049, 28254, 9238, 9388,43793, 9322,28247, 9385,43899, 9319,28194,43892, 9046, 28221, 9235, 9232,23352,17089,17323,23207, 9043,17321,17320,32773,32680, 32679,32772,32685,32778,32683,32775,32792,32688,38823,32771,17516,17539, 17543,17204,23284, 9172,17013,23147,17012, 9006,23146, 9005,17011,17010, 23145,23144, 9004, 9003,17009,17007,23143,23141, 9002, 9000,17081,17080, 23201,23200, 9037, 9036,38830, 9416,32848, 9415,32847,38829, 9215,23319, 17035,17265,23165, 9022, 9213,23317,17033,17263,23163, 9020,17203,23283, 9171,16878,23054, 2188,17529,23402, 1325,17526,23399, 9170,16876,23052, 1324,17525,23398, 2187, 1177, 1188, 1160, 1185, 1167, 1170,32806,32697, 1220, 1215, 1246, 1202, 1250, 1232,32811,32702,17134,23237, 9087,17427, 17583,23383,23422,28234,28268, 9278, 1184, 9299, 1187, 8904, 1176,16926, 23075, 1159,17142,28179, 1166,23245,28207, 1169, 9095, 9119, 8875, 9275, 23380,17423, 9277,23382,17426,17148,16931,23251,23080,28212,28184, 9101, 1236, 9124, 1240, 8880, 1226,32808,32699,38792,38755,43819,43784, 9280, 1245, 9301, 1249, 8906, 1231,23385,23083,28236,28187, 9343, 1254, 9363, 1256, 8883, 1210,38860,38757,43860,43786, 9458, 1260, 9471, 1262, 8911, 1219,17429,16934,28215,28270, 9127, 1208, 9376, 1258,32880,32701,43821, 43907, 9306, 1214, 9480, 1264,28241,28275, 9365, 1222, 9378, 1242,43862, 43909, 9473, 1228, 9482, 1252,17153,17585,23256,23424, 9106, 1197,32810, 32931,38794,38872, 9285, 1201,23390,23429, 9345, 1204,38864,38874, 9462, 1206,17435,17591,32884,32933,17434,17590,23389,23428,28240,28274, 9284, 1200, 9305, 1213, 8910, 1218,17433,17589,23388,23427,28239,28273, 9283, 1199, 9304, 1212, 8909, 1217,17147,16930,23250,23079, 9100, 1235,28211, 28183, 9123, 1239, 8879, 1225,16933,23082, 1244,17152,28186, 1248,23255, 28214, 1230, 9105, 9126, 8882,17145,23248, 9098,17151,23254,17150, 9104, 23253, 9103,38863, 9461,32883, 9460,32882,38862, 1316, 1319, 1337, 1313, 1340, 1322,17098,23212,17097, 9061,23211, 9060,38834, 9427,32857, 9426, 32856,38833,17367,17366,17365,17364,17363,16908,32794,32925,17425,17582, 9448, 9447, 1380,17560,23409, 1373,38849, 9446,32872, 9444,32870,38847, 38841, 9434,32864, 9432,32862,38839,38837, 9430,32860, 9429,32859,38836, 32691,32796,17106,17105,23219,23218, 9069, 9068,38844, 9439,32867, 9438, 32866,38843, 1370, 1378, 1348, 1375, 1356, 1362,16910,23062, 2186, 1385, 23412,17568, 9252,23358,17387, 1382, 1390, 1353, 1387, 1359, 1365,32693, 32800,17114,23225,17113, 9075,23224, 9074,38853, 9453,32875, 9452,32874, 38852,17332,17331,17330,17329,16888,32787,32920,17432,17588,17358,17556, 17351,17553,17389,17570,17378,17562,17382,17564,17394,17572,17362,17558, 9442, 9441, 9424, 9423, 1368, 1108,13330,13329,13400,13397,17078,17315, 17071,17307,15133,13770,13518,14434,15468,14972,15521,14863,13769,14436, 15135,13517,13768,14811,15395,13516,13767,14420,15116,13515,15518,14860, 15465,14965,13805,14816,15398,13568,17124,17405,17070,17314,15369,14792, 14790,15359,14821,15430,15491,14910,14770,15314,12926,13328,15520,14971, 13327,12925,13326,12924,13325,12923,15542,15031,13469,13253,14815,15397, 15464,14859,17349,16906,17347,16904,14873,16397,14871,16395,14532,13324, 14527,13323,14525,13393,14530,12922,14535,12984,14537,12921,14517,12920, 16382,14987,16384,14989,16022,13322,16017,13321,16015,13395,16020,12919, 16025,12986,16027,12918,16008,12917,15775,15777,14402,14400,17398,14510, 14903,14858,14508,14424,14819,16961,17305,14412,14855,13876,13883,13881, 13873,14422,14414,14416,14809,13946,13944,13878,13889,13887,15029,14923, 13451,14963,13840,13900,13831,13803,13842,13981,13779,13829,13959,13950, 13971,13964,13962,13967,16068,22589,16077, 4261,22598, 4260,16066,22587, 16075, 4259,22596, 4257,15256,21934,15263, 7336,21941, 7343,15254,21932, 15261, 7334,21939, 7341,12916,20525, 4255,13079,20683, 4314,12915,20524, 4254,12914,20523, 4253,13081,20685, 4316,13320,20978, 4434,13419,21040, 4468,13319,20977, 4433,13318,20976, 4432,13317,20975, 4431,12913,20522, 4252,12912,20521, 4251,12911,20520, 4250, 4301,22781,16319,15412,22046, 7464,12910,20519, 6816,12909,20518, 6634,12908,20517, 6661,12907,20516, 6459,12906,20515, 6453,12905,20514, 6802,13316,20974, 6632,13315,20973, 6637,13314,20972, 6628,13313,20971, 6457,16321,22783, 4249,16308,22771, 4248,16203,22698, 6715,15914,22451, 6492,15305,21977, 7384,15303,21975, 7382,15155,21849, 7283,15414,22048, 7466,13006,20610, 6813,15403,22039, 7458,13009,20613, 6659,16201,22696, 6713,13403,21030, 6639, 8092, 8571, 8574, 8095,38612,37449,38626,37448,38624,37446,38541,37444,14814,17313, 17312,12904,12903,12902,12901,13083,13012, 7107, 5350,42779,42777, 4169, 4393,14834,14922, 4390, 4349, 4424, 4270, 4347,18969,43135,27930,27928, 27921, 4601, 4600, 4598,27511,27509,27504, 7785, 6772, 6679, 6487, 6688, 8090, 8569,30259,35323,30254,35317,30252,35315, 8089, 8568,18967,43133, 30251,35314,30244,35307,30257,35321,30249,35312,15087,21797, 4505, 4504, 4512, 4579, 4577, 4514,29692,34639,29691,34638,29707,34654,29717,34664, 29799,34746,29801,34748,29740,34687,13958, 6932, 5267, 6930, 5265, 4503, 4502, 4501, 4520, 4519, 4551, 8363, 2934, 2926, 2974, 2970, 8370, 2925, 2383, 2391, 2382, 8368, 8347,30250,35313, 8343, 7722, 7720,19096,19094, 10709,10706, 4500,22238,15684, 4499,22236,15681,13514,21078, 7566,12900, 20513, 6779,12899,20512, 6826,12898,20511, 6737,17122,23231, 9081, 9066, 23216,17102,17111,23222, 9072, 9026,23185,17056,17095,23209, 9058,12897, 20510, 7806,15550,22120, 7851, 7507,22090,15478,15533,22114, 7845,15538, 22116, 7847, 7499,22084,15461,15530,22111, 7841,15711,22261, 6742,15708, 22259, 7774, 7581,22380,15829,15836,22382, 7583,15923,22457, 7564, 7593, 22241,15688,15442,22075, 7492,15489,22096, 7513,15481,22092, 7509, 7837, 22108,15515,17005,23139, 8998, 8997,23138,17004,15500,22099, 7832, 7497, 22078,15454,15453,22077, 7496, 7831,22098,15499,15473,22087, 7504, 4529, 22140,15578,13822,15577, 4527,22139,15576,13817,15575,15724,13513,15574, 22138, 4179,15573,13583,14251,15710,15572,22137, 7776,14257,15571,16242, 15707,15570,22136, 6745,16254,15569,15832,15835,15702,15922,15568,22135, 6500,15567,15925, 4188, 4538,22455,15920, 4537,22454,15919, 7591,22453, 15918,15917,13613,15916, 7595,22134,15566,14065,15565,17228,14833, 4173, 13188,20804, 4365,13228,20847, 4386,17227,13237,20859, 4389,13169,20781, 4360,14099,13827, 4534,13603,21164, 7590,14068,14024,13570,13209,20828, 4382,13512,13412,13411,17003,17226,15452,14832,15498,14921,17328,16887, 14866,16391,14521,13410,16377,14977,16010,13409,14396,13941,13885,13074, 20679, 4310,13073,20678, 4309, 4308,22776,16314,15300,21972, 7379,13072, 4531,15564,22133, 6475,15870,15563,15825,13599,13511,15764, 6771, 6670, 6678, 6486, 7784,13448,13897, 3266, 3424,42761,42776, 6929, 5264, 2924, 2381,18833,43481, 8713, 2380, 2379, 2962,19078,42868,18806,43450, 2923, 1016, 1058,35100,29992, 1044,35096,29988,15561,22131,35097,29989, 1040, 2404, 1034, 1042, 1054, 1028, 5115, 5117,16064,22585,16073, 4297,22594, 4296,27926, 4624, 6948, 5294,15252,21930,15259, 7332,21937, 7339,27507, 8352,14813,14857,14970,14969,42775,13447,13896,13446,13895, 7110, 5369, 2980, 8377, 7739, 7738,19111,19110,10739,10738,18987,43158, 2942, 8712, 4563,13639,21187, 4554,13904, 4195, 4381,15070,21780, 4533,13903,14067, 13957,16938,16937,42132,42573,17002,17225,15451,14920,15497,14831,14919, 15409,22043, 7462,13305,20963, 6811,13304,20962, 6657,16196,22691, 6711, 13303,13986,13985,13984,17224,14918,14830,42689,42380,42688,42379, 4429, 13311,20969, 4428,13977,16936,13307,20965, 4423,13509,37779, 4899,13507, 37777, 4897,13983,42687,42378,42373,42682,13988,42377,42686,42691,42382, 9078,23228,17119, 7511,22094,15487,15440,22073, 7490,13115,20712, 6824, 42802, 8376, 8375, 7849,22118,15548,13826,13445,13894,13114,13628, 2232, 21214,13743,13651,21291, 2250, 6477,21167,15144,13606,21841, 7270,13956, 21399, 2214, 2231,21355,13867,15143,21840, 7269, 6483,21334,13833,13955, 4574,13113,13949, 4571, 4570,13731,21281, 4553,13168,13737,21286, 2230, 13742,21290, 2249,13954,21398, 2213,13948,21396, 2229,13112,20711, 6735, 13940,15265,21943,15066,21776,15085,21795,30243,35306,15560,22130, 4548, 29765,34712,29750,34697, 2378, 5130, 5127,43480,18832, 2377,35094,29986, 2376,35090,29982,15558,22128,35091,29983, 2403,15077,21787,30235,35299, 30246,35309, 8342,13111,20710, 6777,13110,20709, 7804, 4550,13208,20827, 4380,18680,42605, 4379,13646,18934,42986, 8312, 1778,42238,42611,13167, 20780, 4359, 7035, 5307,42741, 1710, 1626, 8327, 8326, 2375, 8340, 8325, 7615, 7612,19074,19071,10696,10693, 4562,13166, 8224, 8659,19004,43178, 15330,21997, 8664, 8226, 2922, 2374, 8223, 8658, 5467, 955, 6059, 953, 5464, 959, 6056, 957, 8661, 8663, 8218, 8221,14243,14242,16236,16235, 32298,32297, 8076, 6069,42820,42819, 8383,10641,19007,10640, 6755,19006, 6754,15343,22008, 7135, 5491,42828, 2373, 8387, 8386, 7793, 7792,19130, 19129,10758,10757,19123,42907,43185,43523,42818,42906, 8672, 8675, 1503, 6071, 5483, 1507,32302, 7134, 5490, 8080, 6089,19017,43192,43191,43528, 43190,43527,42827,42913, 8385, 7791, 7790,19128,19127,10756,10755,10651, 19016,10648, 6766,19013, 6763, 8233, 8236,42911,42825, 5497, 1549, 6093, 1539, 5496, 1548, 6092, 1538,15069,21779,15332,21999,15083,21793,15090, 21800,15088,21798,15674,22221,15557,22127,15556,22126,15559,22129,15555, 22125,15078,21788,15080,21790,15076,21786,15554,22124,15562,22132,15553, 22123,15552,22122,15074,21784,15073,21783,15184,21867,15949,22485,15948, 22484,15988,15219,22525,21900,27872,27463,15985,15216,27869,22522,21897, 27460,27857,27448,27849,27440,25615,27633,27608,21778,15068,27834,27425, 27765,27606,15970,15201,22507,21882,27833,27424,15969,15200,27899,27898, 22541,22540,22506,21881,27490,27489,16004,16003,27832,27423,21916,21915, 15235,15234,27897,27488 }; const int s_nDataSize3 = 24772; unsigned int s_Data3[24772] = { //Output priorities (total = 24772): 10, 9, 12, 6, 11, 14, 4, 1, 7, 5, 2, 3, 13, 8, 0, 0, 1, 2, 219, 218, 76, 217, 216, 77, 1, 0, 74, 78, 79, 75, 70, 71, 72, 68, 73, 69, 310, 299, 296, 331, 297, 332, 114, 26, 298, 340, 330, 336, 338, 339, 62, 112, 328, 334, 329, 335, 113, 337, 327, 333, 115, 60, 27, 61, 63, 273, 215, 36, 213, 31, 35, 39, 319, 312, 320, 323, 324, 343, 157, 345, 28, 178, 32, 59, 269, 58, 309, 305, 275, 271, 308, 304, 34, 117, 181, 129, 154, 211, 30, 38, 177, 193, 55, 130, 268, 33, 303, 174, 29, 37, 119, 212, 143, 188, 66, 270, 141, 183, 194, 179, 126, 261, 190, 267, 344, 346, 272, 189, 173, 274, 51, 322, 321, 342, 315, 214, 311, 14, 57, 223, 348, 125, 176, 192, 317, 280, 314, 165, 160, 175, 326, 127, 17, 247, 172, 262, 5, 231, 99, 138, 124, 54, 301, 325, 167, 15, 43, 205, 47, 122, 147, 292, 295, 83, 106, 86, 87, 220, 131, 347, 293, 150, 209, 233, 67, 116, 148, 156, 171, 180, 191, 256, 195, 341, 128, 277, 291, 281, 289, 294, 313, 102, 46, 103, 207, 229, 236, 240, 224, 227, 249, 170, 49, 251, 258, 318, 133, 197, 278, 2, 56, 252, 265, 254, 20, 142, 151, 316, 164, 121, 162, 41, 107, 139, 203, 288, 302, 48, 52, 110, 53, 64, 4, 16, 284, 135, 307, 3, 40, 155, 202, 23, 93, 22, 92, 290, 65, 210, 50, 98, 208, 94, 123, 137, 187, 225, 7, 10, 120, 109, 263, 287, 186, 108, 152, 264, 90, 253, 96, 97, 136, 200, 118, 140, 300, 306, 185, 6, 11, 89, 259, 85, 101, 132, 196, 24, 45, 260, 244, 91, 18, 104, 232, 19, 44, 105, 184, 21, 84, 226, 250, 283, 279, 286, 158, 248, 257, 255, 80, 169, 13, 100, 81, 168, 199, 238, 9, 12, 82, 182, 201, 266, 146, 204, 230, 239, 241, 159, 221, 285, 134, 88, 242, 246, 8, 144, 222, 149, 161, 228, 237, 276, 95, 206, 282, 163, 198, 243, 235, 245, 42, 166, 25, 111, 145, 153, 234, 13, 0, 1, 8, 3, 11, 7, 9, 2, 12, 4, 6, 5, 10, 0, 61, 62, 0, 2, 3, 5, 6, 8, 15, 17, 1, 4, 7, 9, 10, 11, 12, 13, 14, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 4, 5, 2, 0, 1, 3, 7, 10, 8, 11, 6, 9, 97, 100, 22, 123, 124, 125, 98, 101, 40, 39, 66, 72, 75, 69, 68, 74, 21, 41, 67, 73, 77, 30, 71, 23, 106, 36, 54, 55, 63, 96, 32, 99, 58, 59, 65, 38, 107, 27, 17, 56, 57, 64, 70, 76, 29, 15, 31, 122, 102, 25, 48, 49, 50, 51, 52, 53, 26, 28, 103, 37, 127, 104, 120, 121, 24, 33, 46, 47, 62, 112, 113, 116, 105, 20, 13, 126, 128, 35, 34, 19, 42, 43, 44, 45, 60, 61, 18, 79, 84, 91, 16, 14, 82, 89, 94, 85, 119, 83, 88, 95, 118, 78, 90, 81, 86, 93, 12, 80, 87, 92, 108, 109, 110, 111, 114, 115, 117, 148, 542, 149, 147, 303, 531, 555, 573, 574, 532, 556, 150, 153, 155, 578, 304, 560, 536, 151, 154, 157, 534, 558, 576, 533, 538, 557, 575, 547, 551, 570, 305, 568, 306, 540, 541, 544, 546, 550, 553, 562, 564, 565, 571, 552, 554, 572, 535, 559, 577, 537, 561, 569, 539, 543, 545, 548, 549, 563, 566, 567, 308, 307, 152, 156, 158, 382, 144, 128, 145, 438, 446, 450, 458, 462, 470, 474, 482, 492, 500, 504, 510, 516, 522, 530, 204, 394, 528, 381, 397, 480, 498, 396, 400, 436, 444, 448, 456, 460, 468, 472, 490, 502, 508, 514, 520, 286, 388, 393, 294, 403, 273, 384, 385, 387, 391, 399, 408, 313, 317, 347, 354, 414, 419, 426, 25, 88, 127, 130, 198, 275, 336, 483, 126, 281, 283, 341, 432, 299, 325, 390, 402, 415, 416, 417, 418, 427, 428, 116, 124, 134, 142, 221, 229, 298, 479, 486, 497, 527, 24, 87, 227, 311, 315, 329, 353, 506, 512, 518, 30, 34, 41, 196, 300, 484, 48, 104, 186, 191, 264, 335, 343, 363, 234, 276, 441, 443, 453, 455, 465, 467, 477, 495, 525, 222, 269, 476, 494, 524, 395, 89, 140, 413, 420, 425, 481, 499, 505, 511, 517, 529, 200, 257, 327, 398, 401, 440, 445, 452, 457, 464, 469, 32, 36, 42, 47, 345, 365, 435, 442, 447, 454, 459, 466, 471, 478, 489, 496, 501, 507, 513, 519, 526, 202, 323, 146, 170, 177, 179, 248, 255, 368, 380, 206, 122, 132, 258, 279, 288, 296, 349, 375, 434, 46, 114, 165, 180, 201, 219, 243, 250, 297, 405, 429, 33, 38, 43, 172, 203, 208, 346, 392, 404, 410, 485, 488, 183, 216, 261, 348, 386, 430, 20, 26, 65, 100, 131, 162, 167, 174, 182, 188, 189, 194, 210, 218, 240, 252, 260, 266, 272, 284, 360, 372, 383, 423, 12, 17, 57, 92, 99, 129, 213, 215, 230, 231, 278, 291, 293, 339, 389, 406, 411, 422, 15, 60, 62, 97, 117, 119, 135, 199, 224, 225, 236, 245, 267, 302, 321, 326, 377, 407, 102, 137, 175, 274, 431, 412, 421, 424, 173, 238, 246, 251, 253, 262, 270, 282, 366, 370, 378, 437, 439, 449, 451, 461, 463, 473, 475, 491, 493, 503, 509, 515, 521, 523, 0, 1, 81, 82, 106, 160, 168, 184, 185, 192, 193, 263, 271, 277, 322, 358, 22, 28, 31, 40, 67, 98, 103, 105, 138, 254, 316, 319, 355, 328, 10, 14, 49, 52, 59, 70, 73, 90, 112, 133, 220, 228, 232, 233, 301, 309, 314, 331, 333, 337, 344, 351, 35, 37, 44, 163, 342, 409, 433, 487, 259, 27, 29, 39, 50, 161, 164, 176, 178, 181, 187, 190, 197, 205, 239, 241, 242, 324, 332, 359, 361, 362, 371, 373, 374, 6, 7, 45, 55, 56, 75, 77, 79, 80, 108, 109, 159, 166, 169, 171, 195, 217, 237, 247, 249, 256, 265, 268, 280, 334, 340, 350, 357, 367, 369, 379, 2, 3, 9, 18, 19, 21, 23, 53, 63, 64, 66, 68, 72, 76, 83, 84, 93, 95, 96, 101, 107, 111, 120, 121, 123, 125, 139, 141, 143, 212, 244, 290, 295, 310, 312, 318, 320, 330, 338, 352, 356, 4, 5, 8, 11, 13, 51, 54, 58, 61, 69, 71, 74, 78, 85, 86, 94, 110, 113, 115, 136, 207, 209, 211, 214, 223, 226, 235, 285, 287, 289, 292, 364, 376, 16, 91, 118, 0, 3, 19, 149, 96, 20, 150, 5, 1, 6, 4, 2, 147, 93, 91, 145, 148, 95, 146, 85, 55, 66, 76, 59, 73, 81, 51, 61, 64, 54, 58, 92, 94, 63, 173, 62, 86, 65, 75, 60, 74, 82, 56, 52, 53, 57, 171, 167, 160, 159, 170, 72, 141, 162, 172, 28, 68, 29, 140, 168, 27, 70, 126, 139, 69, 163, 89, 137, 166, 71, 169, 129, 142, 164, 116, 135, 143, 90, 67, 113, 121, 165, 161, 131, 123, 125, 133, 30, 7, 138, 10, 117, 119, 11, 120, 127, 134, 130, 132, 115, 124, 114, 136, 9, 118, 33, 77, 157, 158, 8, 12, 88, 155, 156, 34, 78, 99, 97, 128, 36, 44, 87, 35, 43, 15, 13, 17, 122, 21, 23, 25, 144, 37, 45, 47, 103, 32, 42, 80, 39, 49, 83, 108, 40, 50, 84, 38, 46, 48, 31, 41, 79, 18, 98, 22, 24, 26, 14, 16, 105, 107, 100, 152, 111, 109, 104, 101, 110, 112, 106, 153, 102, 151, 154, 0, 1, 3, 4, 2, 12, 13, 10, 11, 14, 9, 6, 5, 7, 8, 21, 24, 23, 22, 20, 19, 15, 16, 17, 18, 0, 1, 3, 2, 108, 109, 139, 153, 122, 96, 178, 97, 126, 95, 101, 100, 94, 174, 140, 172, 175, 173, 5, 36, 154, 88, 83, 80, 35, 161, 151, 19, 11, 6, 147, 143, 34, 176, 123, 37, 169, 170, 171, 163, 164, 165, 166, 167, 168, 155, 156, 157, 158, 159, 160, 82, 162, 177, 152, 81, 111, 7, 12, 20, 128, 4, 93, 21, 64, 13, 148, 60, 62, 118, 10, 18, 33, 144, 30, 48, 135, 149, 86, 114, 99, 124, 129, 130, 131, 61, 63, 65, 8, 14, 16, 22, 24, 26, 28, 73, 75, 77, 90, 56, 72, 74, 76, 78, 51, 53, 55, 57, 59, 67, 69, 71, 79, 89, 91, 50, 52, 54, 58, 66, 68, 70, 92, 107, 39, 41, 43, 45, 47, 110, 103, 105, 120, 145, 127, 38, 40, 42, 44, 46, 137, 102, 104, 106, 31, 32, 49, 9, 15, 17, 23, 29, 87, 25, 27, 150, 141, 142, 84, 85, 146, 98, 116, 119, 133, 115, 121, 136, 132, 125, 117, 112, 113, 138, 134, 2, 0, 1, 3, 8, 6, 7, 4, 5, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 1, 4, 8, 7, 9, 6, 0, 5, 3, 10, 109, 107, 108, 97, 105, 28, 30, 21, 81, 26, 32, 106, 20, 24, 35, 22, 34, 96, 104, 62, 27, 111, 11, 18, 23, 36, 83, 37, 12, 95, 17, 46, 56, 25, 40, 42, 87, 89, 14, 16, 13, 29, 103, 82, 110, 15, 19, 31, 33, 102, 38, 66, 67, 68, 69, 70, 71, 72, 85, 41, 115, 117, 91, 93, 94, 99, 101, 43, 73, 86, 88, 114, 116, 50, 52, 74, 76, 77, 78, 79, 39, 113, 44, 45, 47, 48, 49, 51, 53, 54, 55, 57, 58, 59, 60, 61, 63, 64, 65, 75, 80, 84, 90, 92, 98, 100, 112, 0, 1, 20, 17, 18, 12, 19, 16, 21, 15, 23, 14, 22, 13, 0, 6, 5, 11, 3, 9, 2, 8, 1, 7, 4, 10, 3, 4, 11, 14, 17, 32, 0, 1, 2, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 2, 3, 0, 1, 15, 13, 17, 21, 77, 76, 33, 30, 34, 110, 105, 114, 118, 31, 32, 35, 101, 100, 16, 131, 12, 14, 130, 135, 132, 112, 120, 116, 111, 115, 119, 79, 117, 113, 121, 20, 133, 80, 134, 78, 81, 44, 109, 49, 47, 124, 46, 28, 48, 126, 26, 87, 89, 90, 88, 6, 5, 7, 9, 11, 19, 36, 38, 40, 42, 86, 91, 18, 4, 10, 39, 8, 37, 41, 43, 45, 60, 127, 27, 61, 106, 129, 59, 108, 128, 53, 54, 57, 58, 62, 50, 29, 56, 63, 52, 55, 107, 122, 123, 125, 51, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 82, 83, 84, 85, 92, 93, 94, 95, 96, 97, 98, 99, 102, 103, 104, 23, 25, 24, 22, 175, 174, 176, 162, 158, 165, 124, 166, 15, 155, 126, 160, 120, 121, 122, 123, 125, 127, 128, 129, 153, 157, 171, 152, 163, 170, 96, 97, 108, 0, 3, 6, 9, 12, 66, 69, 72, 75, 78, 81, 130, 131, 150, 151, 156, 159, 161, 168, 169, 173, 177, 154, 164, 167, 172, 1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 178, 179, 0, 1, 2, 8, 6, 7, 3, 5, 4, 0, 1305, 1308, 540, 545, 558, 563, 564, 569, 570, 575, 576, 581, 582, 587, 588, 593, 594, 599, 600, 605, 606, 611, 612, 617, 618, 623, 624, 629, 630, 635, 636, 641, 642, 647, 648, 653, 654, 657, 662, 663, 668, 669, 672, 677, 678, 681, 684, 687, 690, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 541, 542, 543, 544, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 559, 560, 561, 562, 565, 566, 567, 568, 571, 572, 573, 574, 577, 578, 579, 580, 583, 584, 585, 586, 589, 590, 591, 592, 595, 596, 597, 598, 601, 602, 603, 604, 607, 608, 609, 610, 613, 614, 615, 616, 619, 620, 621, 622, 625, 626, 627, 628, 631, 632, 633, 634, 637, 638, 639, 640, 643, 644, 645, 646, 649, 650, 651, 652, 655, 656, 658, 659, 660, 661, 664, 665, 666, 667, 670, 671, 673, 674, 675, 676, 679, 680, 682, 683, 685, 686, 688, 689, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1306, 1307, 1309, 1310, 158, 161, 164, 167, 170, 173, 74, 77, 86, 89, 0, 3, 12, 15, 24, 27, 36, 39, 48, 51, 60, 63, 110, 113, 122, 125, 134, 137, 146, 149, 76, 88, 156, 160, 162, 165, 169, 171, 2, 132, 175, 26, 38, 50, 62, 72, 83, 84, 95, 108, 120, 78, 90, 96, 104, 174, 14, 144, 176, 9, 21, 33, 45, 57, 69, 79, 81, 91, 93, 98, 106, 119, 131, 143, 155, 59, 71, 157, 159, 163, 166, 168, 172, 99, 101, 103, 105, 11, 35, 47, 73, 75, 80, 82, 85, 87, 92, 94, 97, 100, 102, 107, 117, 129, 141, 8, 20, 23, 32, 44, 56, 68, 114, 126, 138, 150, 153, 179, 186, 191, 198, 180, 192, 1, 4, 5, 6, 7, 10, 13, 16, 17, 18, 19, 22, 25, 28, 29, 30, 31, 34, 37, 40, 41, 42, 43, 46, 49, 52, 53, 54, 55, 58, 61, 64, 65, 66, 67, 70, 109, 111, 112, 115, 116, 118, 121, 123, 124, 127, 128, 130, 133, 135, 136, 139, 140, 142, 145, 147, 148, 151, 152, 154, 213, 214, 215, 216, 177, 189, 184, 196, 221, 222, 223, 224, 178, 181, 182, 183, 185, 187, 188, 190, 193, 194, 195, 197, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 217, 218, 219, 220, 2, 4, 6, 8, 10, 12, 32, 34, 36, 46, 48, 52, 54, 56, 58, 60, 62, 64, 86, 87, 88, 105, 106, 107, 108, 109, 112, 113, 115, 117, 121, 1, 3, 5, 7, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 26, 27, 28, 29, 30, 31, 33, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 66, 67, 68, 71, 73, 75, 76, 78, 79, 80, 82, 83, 84, 92, 93, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 110, 111, 114, 116, 118, 119, 120, 122, 124, 126, 127, 129, 131, 141, 143, 145, 146, 148, 150, 152, 153, 156, 166, 167, 170, 173, 174, 176, 180, 182, 184, 186, 0, 22, 24, 50, 69, 70, 72, 74, 77, 81, 85, 89, 90, 91, 95, 123, 125, 128, 130, 132, 133, 134, 135, 136, 137, 138, 139, 140, 142, 144, 147, 149, 151, 154, 155, 157, 158, 159, 160, 161, 162, 163, 164, 165, 168, 169, 171, 172, 175, 177, 178, 179, 181, 183, 185, 122, 85, 89, 92, 106, 118, 136, 148, 156, 164, 27, 35, 37, 38, 52, 57, 62, 67, 71, 83, 55, 65, 68, 121, 26, 53, 63, 66, 80, 82, 105, 114, 119, 123, 137, 143, 14, 25, 30, 31, 100, 28, 117, 108, 134, 3, 12, 34, 36, 39, 40, 45, 46, 51, 59, 60, 61, 73, 74, 75, 76, 77, 78, 84, 86, 87, 88, 90, 91, 93, 94, 95, 110, 112, 115, 116, 120, 127, 128, 130, 132, 141, 142, 152, 175, 58, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 29, 32, 33, 41, 42, 43, 44, 47, 48, 49, 50, 54, 56, 64, 69, 70, 72, 79, 81, 96, 97, 98, 99, 101, 102, 103, 104, 107, 109, 111, 113, 124, 125, 126, 129, 131, 133, 135, 138, 139, 140, 144, 145, 146, 147, 149, 150, 151, 153, 154, 155, 157, 158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 176, 177, 23, 29, 5, 24, 25, 26, 27, 28, 30, 31, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 32, 83, 84, 96, 99, 100, 16, 85, 98, 18, 26, 27, 37, 40, 49, 52, 17, 51, 55, 57, 97, 8, 3, 19, 9, 50, 56, 58, 10, 53, 72, 82, 87, 89, 91, 14, 118, 129, 12, 81, 86, 88, 90, 130, 11, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34, 35, 36, 43, 67, 68, 69, 93, 95, 41, 45, 47, 4, 5, 6, 13, 38, 117, 128, 71, 0, 1, 2, 15, 39, 92, 94, 65, 70, 122, 123, 127, 7, 42, 44, 46, 48, 54, 59, 60, 61, 62, 63, 64, 66, 105, 106, 109, 110, 111, 112, 113, 114, 121, 124, 126, 73, 74, 75, 76, 77, 78, 79, 80, 101, 102, 103, 104, 107, 108, 115, 116, 119, 120, 125, 18, 24, 5, 7, 9, 13, 0, 1, 2, 3, 4, 6, 8, 10, 11, 12, 14, 15, 16, 17, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 38, 37, 3, 2, 39, 4, 40, 5, 109, 110, 111, 99, 107, 97, 105, 140, 141, 142, 0, 98, 106, 1, 100, 108, 34, 35, 36, 10, 11, 42, 46, 50, 54, 58, 62, 66, 70, 13, 17, 21, 30, 6, 88, 90, 96, 102, 113, 115, 121, 123, 125, 135, 137, 139, 9, 14, 18, 22, 33, 44, 48, 52, 56, 60, 64, 68, 72, 116, 126, 130, 43, 47, 51, 55, 59, 63, 67, 71, 85, 91, 93, 103, 80, 82, 83, 73, 75, 76, 119, 129, 133, 12, 16, 20, 31, 7, 41, 45, 49, 53, 57, 61, 65, 69, 117, 127, 131, 87, 89, 95, 101, 112, 114, 120, 122, 124, 134, 136, 138, 86, 92, 94, 104, 118, 128, 132, 79, 81, 84, 74, 77, 78, 8, 15, 19, 23, 32, 24, 25, 28, 26, 27, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 34, 5, 6, 7, 8, 9, 10, 11, 12, 33, 47, 2, 4, 19, 20, 21, 36, 37, 38, 40, 41, 0, 1, 3, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 35, 39, 42, 43, 44, 45, 46, 48, 49, 50, 144, 145, 0, 141, 142, 143, 155, 154, 139, 140, 146, 147, 150, 151, 76, 82, 83, 84, 85, 86, 87, 158, 131, 77, 132, 159, 23, 24, 25, 26, 27, 28, 32, 33, 73, 79, 91, 95, 1, 3, 5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 29, 30, 31, 34, 102, 104, 106, 108, 112, 113, 114, 115, 116, 117, 118, 119, 138, 37, 39, 41, 43, 48, 50, 52, 54, 2, 4, 6, 7, 8, 9, 10, 11, 36, 38, 40, 42, 44, 45, 46, 47, 56, 57, 58, 59, 60, 62, 64, 66, 68, 70, 72, 74, 75, 78, 80, 81, 88, 89, 90, 92, 93, 94, 96, 97, 98, 100, 103, 105, 107, 109, 137, 160, 161, 162, 35, 49, 51, 53, 55, 61, 63, 65, 67, 69, 71, 99, 101, 110, 111, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 133, 134, 135, 136, 148, 149, 152, 153, 156, 157, 4, 11, 5, 6, 7, 8, 10, 9, 12, 17, 18, 19, 21, 2, 3, 0, 1, 13, 14, 15, 16, 20, 28, 32, 34, 38, 40, 22, 23, 24, 25, 26, 27, 29, 30, 31, 33, 35, 36, 37, 39, 41, 73, 69, 95, 11, 72, 14, 12, 13, 93, 71, 74, 94, 87, 81, 86, 79, 60, 96, 98, 88, 59, 82, 97, 44, 46, 54, 68, 92, 100, 45, 53, 67, 43, 91, 99, 80, 89, 77, 1, 3, 9, 5, 6, 7, 8, 70, 28, 83, 22, 34, 42, 49, 51, 57, 17, 23, 29, 37, 63, 19, 25, 31, 39, 48, 50, 52, 56, 58, 62, 64, 66, 84, 76, 90, 78, 75, 85, 4, 0, 2, 10, 20, 26, 32, 36, 40, 15, 61, 16, 18, 24, 30, 35, 38, 47, 55, 65, 21, 27, 33, 41, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 40, 42, 3, 1, 51, 5, 49, 48, 22, 24, 4, 2, 52, 50, 76, 78, 80, 94, 96, 98, 23, 47, 26, 27, 63, 64, 65, 70, 71, 21, 77, 79, 81, 17, 20, 33, 37, 41, 43, 57, 55, 56, 58, 59, 60, 61, 62, 18, 19, 25, 32, 36, 95, 97, 99, 0, 38, 39, 54, 67, 69, 73, 75, 85, 87, 91, 93, 53, 66, 84, 86, 90, 89, 6, 7, 11, 12, 13, 82, 83, 68, 72, 74, 92, 8, 9, 10, 14, 15, 16, 28, 29, 30, 31, 34, 35, 44, 45, 46, 88, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 3, 43, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 44, 45, 46, 89, 90, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 186, 189, 174, 185, 179, 180, 177, 181, 188, 191, 60, 63, 175, 183, 176, 184, 64, 61, 62, 65, 178, 182, 187, 190, 130, 142, 154, 166, 104, 110, 116, 13, 24, 36, 78, 122, 136, 148, 160, 172, 7, 18, 30, 84, 102, 108, 114, 105, 111, 117, 120, 123, 74, 86, 98, 107, 113, 119, 125, 1, 9, 20, 32, 44, 45, 55, 75, 99, 103, 109, 115, 0, 6, 19, 31, 42, 43, 54, 72, 73, 85, 96, 97, 137, 149, 161, 173, 2, 46, 47, 56, 76, 77, 100, 101, 127, 133, 139, 145, 151, 157, 163, 169, 8, 21, 33, 87, 106, 112, 118, 121, 124, 128, 129, 140, 141, 152, 153, 3, 4, 15, 26, 38, 48, 49, 50, 51, 57, 58, 66, 67, 68, 69, 80, 90, 91, 92, 93, 126, 131, 134, 138, 143, 146, 150, 155, 158, 162, 167, 170, 10, 11, 22, 23, 34, 35, 88, 89, 135, 147, 159, 171, 5, 12, 14, 16, 17, 25, 27, 28, 29, 37, 39, 40, 41, 52, 53, 59, 70, 71, 79, 81, 82, 83, 94, 95, 132, 144, 156, 164, 165, 168, 756, 759, 761, 104, 105, 640, 647, 700, 107, 757, 760, 102, 222, 224, 310, 420, 431, 441, 460, 468, 491, 494, 501, 558, 571, 654, 666, 683, 722, 7, 10, 31, 34, 60, 65, 162, 165, 178, 434, 467, 477, 480, 550, 569, 657, 671, 682, 718, 751, 13, 37, 54, 175, 181, 262, 265, 313, 385, 465, 551, 563, 641, 645, 701, 719, 253, 316, 333, 339, 364, 365, 369, 371, 436, 439, 461, 496, 499, 505, 514, 520, 522, 577, 585, 588, 598, 601, 608, 617, 622, 685, 727, 733, 223, 240, 191, 709, 92, 115, 144, 199, 248, 252, 290, 307, 338, 372, 382, 410, 475, 508, 513, 515, 527, 547, 566, 567, 572, 580, 587, 590, 595, 604, 606, 615, 619, 688, 716, 725, 730, 735, 739, 747, 11, 16, 22, 23, 35, 40, 46, 47, 52, 53, 59, 64, 88, 89, 94, 103, 118, 121, 124, 138, 143, 149, 163, 164, 179, 184, 190, 202, 205, 208, 225, 244, 245, 250, 259, 268, 280, 281, 284, 285, 291, 322, 328, 332, 340, 373, 379, 388, 400, 401, 404, 405, 411, 421, 426, 428, 429, 437, 442, 450, 455, 457, 469, 478, 481, 488, 497, 502, 529, 530, 536, 537, 540, 553, 564, 570, 625, 626, 630, 635, 637, 643, 655, 656, 668, 670, 678, 681, 691, 692, 699, 703, 704, 724, 738, 749, 750, 753, 560, 574, 723, 85, 331, 470, 101, 217, 633, 642, 697, 742, 745, 754, 19, 43, 48, 187, 324, 97, 218, 296, 416, 130, 137, 166, 226, 241, 271, 279, 319, 327, 391, 399, 440, 482, 142, 283, 325, 403, 443, 453, 485, 758, 0, 24, 67, 298, 336, 346, 464, 489, 504, 507, 510, 516, 518, 521, 523, 524, 535, 552, 559, 573, 576, 579, 582, 583, 591, 592, 594, 599, 602, 603, 607, 611, 614, 616, 620, 623, 632, 644, 649, 651, 661, 663, 667, 669, 684, 687, 696, 708, 720, 726, 729, 732, 736, 1, 2, 3, 4, 5, 6, 8, 9, 12, 14, 15, 17, 18, 20, 21, 25, 26, 27, 28, 29, 30, 32, 33, 36, 38, 39, 41, 42, 44, 45, 49, 50, 51, 55, 56, 57, 58, 61, 62, 63, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 90, 91, 93, 95, 96, 98, 99, 100, 106, 108, 109, 110, 111, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125, 126, 127, 128, 129, 131, 132, 133, 134, 135, 136, 139, 140, 141, 145, 146, 147, 148, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 167, 168, 169, 170, 171, 172, 173, 174, 176, 177, 180, 182, 183, 185, 186, 188, 189, 192, 193, 194, 195, 196, 197, 198, 200, 201, 203, 204, 206, 207, 209, 210, 211, 212, 213, 214, 215, 216, 219, 220, 221, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 242, 243, 246, 247, 249, 251, 254, 255, 256, 257, 258, 260, 261, 263, 264, 266, 267, 269, 270, 272, 273, 274, 275, 276, 277, 278, 282, 286, 287, 288, 289, 292, 293, 294, 295, 297, 299, 300, 301, 302, 303, 304, 305, 306, 308, 309, 311, 312, 314, 315, 317, 318, 320, 321, 323, 326, 329, 330, 334, 335, 337, 341, 342, 343, 344, 345, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 366, 367, 368, 370, 374, 375, 376, 377, 378, 380, 381, 383, 384, 386, 387, 389, 390, 392, 393, 394, 395, 396, 397, 398, 402, 406, 407, 408, 409, 412, 413, 414, 415, 417, 418, 419, 422, 423, 424, 425, 427, 430, 432, 433, 435, 438, 444, 445, 446, 447, 448, 449, 451, 452, 454, 456, 458, 459, 462, 463, 466, 471, 472, 473, 474, 476, 479, 483, 484, 486, 487, 490, 492, 493, 495, 498, 500, 503, 506, 509, 511, 512, 517, 519, 525, 526, 528, 531, 532, 533, 534, 538, 539, 541, 542, 543, 544, 545, 546, 548, 549, 554, 555, 556, 557, 561, 562, 565, 568, 575, 578, 581, 584, 586, 589, 593, 596, 597, 600, 605, 609, 610, 612, 613, 618, 621, 624, 627, 628, 629, 631, 634, 636, 638, 639, 646, 648, 650, 652, 653, 658, 659, 660, 662, 664, 665, 672, 673, 674, 675, 676, 677, 679, 680, 686, 689, 690, 693, 694, 695, 698, 702, 705, 706, 707, 710, 711, 712, 713, 714, 715, 717, 721, 728, 731, 734, 737, 740, 741, 743, 744, 746, 748, 752, 755, 325, 326, 324, 15, 258, 103, 123, 3, 9, 124, 331, 14, 259, 16, 2, 8, 337, 102, 335, 340, 4, 10, 17, 120, 246, 247, 276, 333, 334, 33, 72, 128, 338, 5, 11, 76, 105, 127, 0, 13, 74, 73, 122, 1, 75, 7, 300, 336, 364, 6, 12, 228, 235, 263, 265, 270, 280, 291, 106, 297, 77, 135, 162, 169, 192, 199, 201, 214, 216, 225, 260, 262, 104, 306, 316, 339, 170, 200, 223, 341, 137, 160, 190, 203, 215, 218, 141, 150, 157, 171, 180, 187, 312, 313, 317, 39, 125, 143, 148, 158, 173, 178, 188, 308, 318, 107, 322, 362, 35, 91, 97, 109, 299, 230, 272, 293, 244, 256, 289, 323, 367, 38, 121, 302, 303, 311, 327, 245, 257, 261, 290, 305, 234, 264, 279, 34, 36, 79, 85, 115, 126, 298, 307, 309, 319, 328, 57, 63, 69, 198, 229, 271, 292, 82, 88, 90, 96, 108, 118, 304, 320, 329, 37, 41, 80, 86, 116, 301, 332, 139, 159, 164, 168, 189, 194, 205, 213, 217, 220, 222, 40, 136, 145, 167, 177, 197, 202, 212, 227, 18, 27, 48, 363, 237, 267, 282, 196, 240, 241, 252, 253, 285, 286, 142, 147, 152, 155, 156, 172, 175, 182, 185, 186, 310, 321, 330, 346, 347, 348, 355, 138, 163, 165, 193, 195, 204, 210, 219, 226, 131, 132, 208, 250, 251, 278, 314, 315, 357, 365, 140, 146, 179, 206, 211, 20, 29, 50, 161, 166, 191, 221, 224, 269, 368, 26, 44, 47, 58, 64, 70, 81, 87, 117, 144, 151, 153, 174, 181, 183, 93, 99, 111, 232, 274, 295, 59, 65, 71, 133, 134, 149, 154, 176, 184, 209, 350, 361, 239, 242, 254, 284, 287, 268, 56, 62, 68, 78, 84, 94, 100, 112, 114, 92, 98, 110, 238, 283, 55, 61, 67, 349, 236, 243, 255, 266, 281, 288, 19, 24, 28, 42, 45, 49, 129, 130, 207, 248, 249, 277, 354, 359, 360, 233, 275, 296, 352, 353, 22, 31, 52, 54, 60, 66, 83, 89, 95, 101, 113, 119, 342, 345, 366, 231, 273, 294, 25, 43, 46, 23, 32, 53, 343, 351, 358, 21, 30, 51, 344, 356, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 19, 29, 33, 45, 86, 88, 90, 92, 18, 27, 31, 47, 82, 103, 37, 41, 55, 87, 11, 35, 39, 43, 49, 51, 53, 57, 61, 63, 89, 91, 105, 109, 114, 20, 9, 13, 107, 28, 30, 32, 34, 46, 48, 78, 84, 133, 135, 93, 112, 134, 136, 36, 40, 62, 66, 80, 38, 42, 44, 50, 52, 54, 56, 58, 64, 127, 131, 137, 1, 15, 16, 21, 22, 102, 111, 113, 128, 132, 138, 23, 25, 59, 68, 70, 94, 69, 3, 4, 6, 7, 10, 104, 106, 108, 110, 121, 123, 67, 24, 26, 60, 122, 124, 72, 76, 81, 96, 85, 74, 98, 129, 83, 125, 0, 2, 5, 8, 12, 14, 17, 71, 73, 75, 77, 79, 95, 97, 99, 100, 126, 65, 130, 101, 118, 116, 120, 115, 117, 119, 219, 220, 221, 127, 131, 135, 139, 228, 229, 230, 231, 232, 233, 234, 235, 222, 223, 224, 225, 226, 227, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 275, 276, 277, 278, 9, 13, 17, 21, 25, 29, 36, 40, 44, 48, 49, 56, 60, 64, 68, 72, 76, 80, 84, 171, 176, 180, 184, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20, 22, 23, 24, 26, 27, 28, 30, 31, 32, 33, 34, 35, 37, 38, 39, 41, 42, 43, 45, 46, 47, 50, 51, 52, 53, 54, 55, 57, 58, 59, 61, 62, 63, 65, 66, 67, 69, 70, 71, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 172, 173, 174, 175, 177, 178, 179, 181, 182, 183, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 267, 268, 269, 270, 271, 272, 273, 274, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 1, 2, 3, 4, 0, 8, 12, 11, 102, 127, 6, 5, 101, 7, 128, 4, 3, 10, 1, 2, 0, 9, 92, 90, 97, 114, 94, 95, 99, 112, 111, 123, 116, 118, 120, 121, 125, 98, 89, 91, 96, 93, 100, 113, 24, 34, 16, 36, 14, 22, 13, 21, 33, 18, 26, 30, 115, 117, 124, 119, 122, 126, 17, 25, 29, 104, 19, 27, 31, 106, 28, 20, 32, 15, 23, 35, 54, 56, 110, 51, 72, 88, 38, 40, 49, 58, 60, 64, 66, 74, 81, 105, 107, 37, 39, 50, 52, 57, 59, 63, 65, 71, 73, 82, 87, 42, 43, 45, 48, 61, 67, 70, 76, 77, 79, 83, 86, 53, 55, 41, 44, 46, 47, 62, 68, 69, 75, 78, 80, 84, 85, 109, 103, 108, 7, 8, 6, 9, 17, 10, 28, 26, 24, 50, 68, 4, 34, 5, 0, 23, 46, 2, 18, 33, 1, 85, 19, 58, 62, 70, 29, 31, 35, 3, 25, 27, 47, 48, 49, 51, 11, 90, 30, 32, 36, 40, 41, 42, 43, 44, 45, 12, 13, 14, 15, 16, 20, 21, 22, 37, 38, 39, 52, 53, 54, 55, 56, 57, 59, 60, 61, 63, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 88, 125, 101, 103, 124, 127, 134, 135, 25, 29, 37, 45, 165, 177, 163, 180, 138, 142, 113, 24, 28, 36, 40, 41, 44, 48, 49, 58, 59, 60, 61, 66, 67, 68, 69, 70, 71, 72, 73, 89, 92, 93, 145, 148, 149, 94, 105, 109, 151, 154, 161, 173, 96, 99, 100, 102, 104, 107, 108, 111, 114, 115, 116, 118, 119, 120, 122, 123, 126, 132, 133, 136, 137, 140, 141, 155, 156, 159, 160, 164, 169, 171, 172, 175, 176, 179, 181, 182, 183, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 26, 27, 30, 31, 32, 33, 34, 35, 38, 39, 42, 43, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 62, 63, 64, 65, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 90, 91, 95, 97, 98, 106, 110, 112, 117, 121, 128, 129, 130, 131, 139, 143, 144, 146, 147, 150, 152, 153, 157, 158, 162, 166, 167, 168, 170, 174, 178, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 306, 146, 158, 174, 216, 233, 27, 29, 121, 123, 125, 127, 144, 150, 152, 173, 188, 218, 295, 299, 307, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 122, 124, 126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 145, 147, 148, 149, 151, 153, 154, 155, 156, 157, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 296, 297, 298, 300, 301, 302, 303, 304, 305, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 76, 106, 77, 107, 125, 115, 126, 60, 61, 71, 59, 96, 99, 110, 89, 70, 58, 25, 27, 33, 35, 86, 87, 72, 75, 79, 94, 112, 95, 100, 73, 74, 78, 101, 102, 105, 109, 88, 26, 32, 34, 103, 104, 108, 24, 97, 98, 113, 114, 44, 64, 69, 36, 38, 41, 43, 47, 54, 57, 63, 66, 111, 37, 39, 40, 42, 45, 46, 55, 56, 62, 65, 67, 68, 90, 92, 5, 11, 9, 84, 8, 4, 10, 2, 48, 50, 52, 81, 82, 0, 6, 12, 14, 85, 80, 83, 49, 51, 53, 91, 93, 118, 121, 124, 3, 17, 18, 21, 22, 29, 30, 1, 7, 13, 15, 116, 119, 122, 129, 16, 19, 20, 23, 28, 31, 117, 120, 123, 127, 128, 130, 3, 4, 5, 6, 25, 26, 27, 28, 29, 33, 41, 54, 61, 62, 99, 101, 105, 106, 107, 108, 133, 134, 0, 7, 30, 83, 86, 87, 88, 90, 91, 92, 93, 135, 136, 137, 1, 2, 31, 32, 34, 100, 102, 103, 104, 119, 132, 138, 139, 140, 16, 21, 22, 23, 24, 44, 51, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, 76, 8, 9, 10, 11, 12, 13, 14, 15, 35, 36, 42, 43, 46, 48, 49, 50, 52, 60, 63, 77, 78, 79, 80, 81, 82, 85, 89, 94, 95, 96, 97, 98, 109, 110, 111, 112, 113, 114, 115, 120, 121, 17, 18, 19, 20, 37, 38, 39, 40, 45, 47, 53, 55, 56, 57, 58, 59, 68, 70, 84, 116, 117, 118, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 49, 18, 16, 17, 42, 45, 15, 8, 46, 39, 6, 48, 7, 9, 10, 41, 44, 5, 40, 43, 30, 47, 51, 52, 25, 19, 20, 21, 22, 23, 24, 3, 4, 29, 31, 32, 33, 34, 35, 36, 37, 38, 71, 73, 11, 12, 13, 14, 50, 70, 0, 1, 2, 26, 27, 28, 60, 62, 69, 61, 63, 64, 65, 72, 75, 76, 54, 55, 56, 57, 58, 59, 66, 68, 81, 82, 83, 84, 86, 74, 53, 67, 77, 78, 79, 80, 85, 87, 88, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 31, 35, 41, 33, 30, 34, 40, 82, 81, 103, 47, 32, 15, 99, 46, 9, 21, 8, 69, 65, 67, 14, 62, 57, 58, 60, 80, 56, 20, 11, 97, 10, 85, 86, 1, 22, 26, 36, 16, 17, 78, 79, 105, 108, 5, 24, 28, 38, 44, 45, 59, 61, 63, 70, 109, 111, 0, 4, 25, 29, 39, 50, 51, 54, 55, 71, 72, 73, 74, 75, 76, 77, 95, 96, 101, 102, 104, 110, 98, 18, 19, 83, 84, 89, 23, 27, 37, 42, 43, 48, 113, 2, 3, 6, 7, 12, 13, 49, 52, 53, 87, 88, 90, 91, 92, 93, 94, 106, 107, 112, 64, 66, 68, 5, 4, 0, 39, 48, 17, 8, 6, 7, 77, 78, 75, 76, 79, 80, 16, 15, 73, 56, 55, 74, 40, 41, 42, 60, 9, 10, 11, 12, 13, 14, 59, 43, 62, 1, 2, 3, 44, 61, 58, 68, 22, 23, 28, 35, 36, 45, 46, 47, 57, 67, 69, 70, 71, 19, 18, 20, 21, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 37, 38, 49, 50, 51, 52, 53, 54, 63, 64, 65, 66, 72, 81, 82, 83, 84, 34, 44, 71, 32, 43, 30, 35, 72, 33, 11, 10, 39, 37, 13, 38, 42, 36, 12, 41, 31, 8, 9, 40, 50, 69, 55, 20, 24, 28, 135, 1, 5, 15, 136, 70, 46, 51, 114, 115, 45, 3, 7, 17, 113, 116, 54, 128, 129, 134, 138, 0, 4, 14, 26, 19, 23, 27, 48, 62, 63, 68, 123, 124, 125, 126, 131, 132, 29, 49, 59, 60, 66, 127, 130, 133, 86, 110, 119, 57, 58, 65, 83, 87, 103, 111, 122, 18, 22, 82, 102, 61, 64, 67, 21, 25, 52, 2, 6, 16, 75, 76, 85, 90, 95, 99, 100, 109, 120, 56, 73, 74, 77, 78, 79, 80, 81, 84, 88, 89, 91, 92, 93, 94, 96, 97, 98, 101, 104, 105, 106, 107, 108, 112, 117, 118, 121, 137, 47, 53, 4, 5, 0, 1, 2, 3, 7, 8, 6, 9, 10, 20, 25, 27, 18, 19, 21, 23, 24, 26, 28, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 22, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 76, 96, 112, 109, 110, 94, 95, 49, 73, 56, 61, 65, 68, 102, 30, 37, 38, 40, 41, 44, 45, 47, 48, 55, 57, 59, 60, 79, 82, 88, 89, 90, 91, 92, 98, 100, 105, 108, 111, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 39, 42, 43, 46, 50, 51, 52, 53, 54, 58, 62, 63, 64, 66, 67, 69, 70, 71, 72, 74, 75, 77, 78, 80, 81, 83, 84, 85, 86, 87, 93, 97, 99, 101, 103, 104, 106, 107, 113, 91, 42, 46, 77, 26, 8, 78, 41, 43, 44, 47, 68, 5, 30, 45, 89, 90, 48, 49, 50, 51, 25, 76, 93, 14, 70, 88, 4, 23, 24, 29, 59, 63, 75, 79, 92, 97, 0, 1, 2, 6, 7, 15, 16, 17, 20, 21, 27, 31, 32, 33, 34, 35, 36, 62, 64, 67, 72, 61, 66, 71, 86, 94, 12, 74, 55, 58, 60, 81, 83, 3, 9, 10, 11, 13, 18, 19, 22, 28, 37, 38, 39, 40, 53, 56, 65, 69, 73, 82, 84, 85, 52, 54, 57, 80, 87, 95, 96, 1, 8, 10, 13, 12, 6, 2, 0, 11, 9, 5, 25, 7, 19, 43, 44, 45, 32, 33, 34, 50, 51, 52, 26, 22, 23, 3, 4, 28, 15, 36, 37, 49, 30, 31, 29, 14, 20, 21, 24, 27, 17, 39, 46, 16, 35, 53, 38, 40, 41, 42, 18, 47, 48, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 49, 310, 312, 314, 269, 271, 273, 275, 277, 279, 281, 297, 299, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 270, 272, 274, 276, 278, 280, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 298, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 311, 313, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 179, 200, 161, 175, 243, 100, 104, 196, 198, 223, 227, 176, 203, 212, 215, 162, 163, 247, 160, 174, 216, 218, 158, 172, 96, 157, 166, 170, 197, 199, 217, 219, 159, 173, 178, 201, 99, 101, 103, 105, 177, 202, 213, 214, 98, 102, 92, 108, 112, 116, 120, 124, 128, 132, 184, 192, 208, 180, 188, 204, 239, 249, 221, 225, 154, 165, 169, 51, 53, 55, 57, 59, 63, 67, 71, 75, 79, 83, 87, 95, 119, 123, 127, 131, 138, 142, 146, 150, 183, 191, 207, 236, 241, 245, 250, 61, 65, 69, 73, 77, 81, 85, 89, 93, 109, 113, 117, 140, 144, 148, 152, 8, 9, 14, 15, 20, 21, 50, 52, 54, 56, 91, 107, 111, 115, 121, 125, 129, 133, 134, 135, 136, 137, 141, 145, 149, 153, 155, 164, 168, 181, 187, 189, 195, 205, 211, 58, 62, 66, 70, 74, 78, 82, 86, 118, 122, 126, 130, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 60, 64, 68, 72, 76, 80, 84, 88, 139, 143, 147, 151, 186, 194, 210, 222, 226, 238, 242, 246, 248, 94, 97, 156, 167, 171, 228, 230, 90, 106, 110, 114, 220, 224, 237, 240, 244, 251, 182, 185, 190, 193, 206, 209, 229, 231, 232, 233, 234, 235, 24, 51, 54, 111, 25, 52, 55, 112, 13, 31, 34, 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 26, 27, 28, 29, 30, 32, 33, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 53, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 8, 16, 18, 7, 26, 30, 34, 104, 14, 15, 17, 19, 22, 48, 68, 73, 75, 79, 11, 1, 6, 20, 28, 32, 36, 38, 40, 44, 98, 102, 103, 105, 106, 115, 2, 13, 21, 23, 49, 53, 54, 55, 56, 57, 58, 60, 61, 64, 66, 67, 69, 76, 83, 85, 95, 100, 10, 0, 3, 4, 5, 9, 12, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46, 47, 50, 51, 52, 59, 62, 63, 65, 70, 71, 72, 74, 77, 78, 80, 81, 82, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 96, 97, 99, 101, 107, 108, 109, 110, 111, 112, 113, 114, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 121, 120, 103, 101, 102, 86, 111, 124, 27, 44, 100, 10, 13, 82, 92, 98, 78, 88, 94, 42, 40, 9, 11, 12, 14, 80, 84, 90, 96, 45, 119, 122, 46, 48, 50, 52, 104, 106, 109, 110, 1, 4, 18, 25, 29, 32, 19, 34, 22, 5, 8, 38, 107, 39, 16, 17, 21, 26, 30, 33, 43, 87, 125, 41, 83, 93, 99, 2, 24, 28, 31, 35, 53, 55, 81, 91, 97, 105, 0, 3, 7, 6, 15, 20, 23, 36, 37, 47, 49, 51, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 85, 89, 95, 108, 112, 113, 114, 115, 116, 117, 118, 123, 161, 57, 60, 95, 169, 165, 171, 0, 160, 40, 168, 164, 39, 58, 59, 96, 1, 2, 50, 55, 64, 75, 85, 92, 97, 71, 77, 81, 87, 6, 16, 30, 44, 181, 170, 49, 56, 63, 76, 86, 91, 98, 174, 180, 5, 15, 29, 43, 72, 78, 82, 88, 113, 126, 194, 195, 198, 158, 159, 162, 163, 114, 125, 144, 145, 166, 167, 192, 193, 156, 47, 48, 51, 52, 53, 54, 61, 62, 65, 66, 83, 84, 89, 90, 93, 94, 99, 100, 101, 102, 103, 104, 130, 131, 132, 133, 134, 135, 152, 175, 176, 177, 67, 69, 73, 79, 105, 3, 4, 7, 8, 13, 14, 17, 18, 19, 20, 25, 26, 27, 28, 31, 32, 33, 34, 37, 38, 41, 42, 45, 46, 68, 70, 74, 80, 106, 117, 118, 142, 143, 178, 179, 138, 9, 140, 147, 148, 107, 109, 111, 139, 141, 146, 149, 182, 183, 184, 185, 190, 191, 115, 119, 121, 123, 137, 155, 157, 187, 189, 197, 10, 11, 12, 21, 22, 23, 24, 35, 36, 108, 110, 112, 116, 120, 122, 124, 127, 128, 129, 136, 150, 151, 153, 154, 173, 186, 188, 196, 172, 37, 36, 33, 32, 35, 34, 4, 2, 6, 0, 44, 45, 47, 46, 42, 43, 39, 41, 40, 38, 5, 7, 3, 1, 51, 17, 11, 15, 19, 9, 13, 10, 14, 18, 16, 23, 24, 27, 28, 31, 8, 12, 20, 22, 21, 25, 26, 29, 30, 49, 48, 50, 179, 176, 165, 178, 171, 175, 174, 177, 162, 168, 190, 188, 202, 200, 33, 75, 93, 51, 81, 87, 173, 164, 157, 114, 3, 6, 156, 15, 21, 27, 170, 167, 123, 63, 69, 39, 45, 57, 199, 211, 172, 208, 205, 214, 181, 184, 203, 196, 169, 198, 201, 160, 161, 137, 163, 125, 209, 119, 183, 215, 166, 207, 204, 213, 197, 191, 206, 210, 182, 212, 187, 185, 53, 83, 89, 192, 186, 193, 136, 180, 194, 130, 142, 154, 155, 148, 149, 131, 143, 116, 32, 74, 92, 122, 101, 107, 110, 113, 98, 104, 71, 65, 41, 47, 59, 2, 11, 14, 20, 26, 195, 189, 147, 150, 151, 145, 133, 127, 139, 126, 138, 132, 144, 117, 159, 52, 82, 88, 158, 120, 96, 102, 108, 99, 105, 111, 30, 72, 90, 8, 5, 9, 0, 124, 97, 103, 109, 12, 18, 24, 48, 78, 84, 66, 60, 70, 62, 35, 77, 95, 68, 42, 50, 80, 86, 17, 23, 29, 36, 54, 38, 44, 56, 152, 153, 64, 40, 58, 46, 128, 140, 129, 134, 135, 141, 146, 106, 100, 112, 121, 7, 4, 115, 118, 34, 61, 76, 94, 16, 22, 28, 37, 43, 55, 49, 79, 85, 67, 1, 13, 19, 25, 31, 73, 91, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 53, 52, 72, 71, 73, 70, 97, 98, 96, 99, 68, 80, 82, 74, 77, 78, 5, 22, 25, 41, 49, 1, 9, 17, 95, 103, 102, 104, 75, 76, 79, 66, 69, 93, 67, 94, 81, 83, 84, 85, 86, 87, 88, 89, 90, 91, 106, 107, 92, 100, 101, 105, 32, 34, 38, 12, 15, 54, 58, 62, 39, 14, 36, 57, 61, 65, 31, 35, 47, 29, 45, 42, 28, 44, 30, 46, 18, 16, 55, 59, 63, 40, 21, 26, 50, 3, 7, 11, 19, 0, 4, 8, 33, 37, 20, 23, 24, 27, 43, 48, 51, 2, 6, 10, 13, 56, 60, 64, 0, 2, 1, 11, 5, 6, 12, 3, 4, 9, 10, 14, 7, 8, 13, 21, 36, 18, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 15, 16, 22, 17, 19, 20, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 48, 5, 34, 63, 4, 62, 50, 47, 49, 33, 35, 36, 29, 3, 6, 61, 64, 54, 58, 45, 32, 51, 56, 60, 70, 57, 40, 46, 11, 55, 59, 44, 53, 65, 72, 14, 15, 17, 20, 22, 27, 66, 68, 69, 71, 26, 19, 67, 1, 9, 12, 7, 25, 24, 28, 30, 31, 10, 8, 16, 18, 21, 23, 52, 0, 2, 41, 42, 43, 13, 37, 38, 39, 107, 15, 97, 100, 101, 105, 99, 33, 81, 79, 80, 34, 92, 95, 86, 48, 118, 41, 43, 119, 35, 36, 37, 75, 102, 103, 104, 23, 24, 25, 26, 31, 4, 17, 19, 21, 22, 27, 38, 39, 52, 56, 58, 64, 70, 72, 82, 47, 87, 51, 55, 57, 77, 78, 98, 116, 117, 28, 29, 30, 32, 40, 42, 5, 7, 9, 93, 96, 1, 2, 3, 6, 8, 10, 12, 54, 59, 65, 66, 68, 69, 71, 73, 74, 76, 83, 84, 89, 90, 106, 109, 111, 112, 114, 44, 45, 46, 49, 50, 11, 53, 16, 18, 20, 0, 13, 14, 60, 61, 62, 63, 67, 85, 88, 91, 94, 108, 110, 113, 115, 13, 4, 46, 47, 2, 6, 37, 38, 43, 51, 54, 55, 58, 67, 69, 0, 1, 3, 5, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 39, 40, 41, 42, 44, 45, 48, 49, 50, 52, 53, 56, 57, 59, 60, 61, 62, 63, 64, 65, 66, 68, 70, 71, 72, 73, 74, 75, 7, 4, 6, 5, 2, 3, 9, 8, 0, 1, 23, 22, 24, 25, 14, 26, 30, 34, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 27, 28, 29, 31, 32, 33, 35, 36, 37, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 0, 1, 2, 3, 4, 4, 0, 1, 2, 3, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 323, 139, 149, 165, 207, 234, 320, 296, 300, 20, 44, 45, 52, 138, 147, 189, 191, 192, 193, 210, 213, 215, 217, 226, 232, 236, 238, 293, 322, 325, 74, 122, 306, 150, 264, 4, 5, 197, 201, 117, 172, 188, 195, 203, 222, 244, 245, 265, 271, 291, 292, 332, 2, 18, 19, 22, 34, 46, 57, 82, 84, 85, 88, 89, 120, 130, 133, 134, 136, 137, 140, 142, 143, 145, 146, 148, 153, 159, 160, 161, 162, 166, 169, 173, 184, 185, 209, 211, 219, 228, 229, 231, 237, 240, 242, 243, 246, 247, 248, 251, 253, 254, 257, 286, 294, 298, 324, 335, 33, 98, 118, 200, 204, 303, 305, 327, 100, 196, 205, 275, 123, 126, 282, 0, 1, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, 79, 80, 81, 83, 86, 87, 90, 91, 92, 93, 94, 95, 96, 97, 99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 119, 121, 124, 125, 127, 128, 129, 131, 132, 135, 141, 144, 151, 152, 154, 155, 156, 157, 158, 163, 164, 167, 168, 170, 171, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 186, 187, 190, 194, 198, 199, 202, 206, 208, 212, 214, 216, 218, 220, 221, 223, 224, 225, 227, 230, 233, 235, 239, 241, 249, 250, 252, 255, 256, 258, 259, 260, 261, 262, 263, 266, 267, 268, 269, 270, 272, 273, 274, 276, 277, 278, 279, 280, 281, 283, 284, 285, 287, 288, 289, 290, 295, 297, 299, 301, 302, 304, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 321, 326, 328, 329, 330, 331, 333, 334, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 4, 5, 18, 20, 0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 23, 24, 25, 26, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 38, 40, 39, 65, 63, 66, 26, 28, 11, 20, 24, 32, 108, 8, 47, 45, 48, 49, 105, 109, 139, 75, 124, 18, 22, 30, 34, 111, 102, 114, 118, 77, 123, 133, 1, 5, 17, 46, 69, 73, 81, 29, 78, 101, 37, 50, 64, 9, 51, 55, 61, 76, 68, 72, 84, 2, 6, 14, 19, 23, 35, 67, 71, 79, 83, 107, 113, 115, 117, 137, 147, 36, 10, 27, 53, 57, 59, 135, 13, 103, 104, 126, 3, 7, 15, 41, 44, 54, 58, 60, 70, 74, 80, 82, 0, 4, 12, 16, 21, 25, 31, 33, 42, 43, 52, 56, 62, 85, 88, 91, 94, 106, 110, 112, 116, 119, 120, 121, 122, 125, 127, 128, 129, 130, 131, 132, 134, 136, 138, 140, 141, 142, 143, 144, 145, 146, 148, 89, 86, 87, 90, 92, 93, 95, 96, 97, 98, 99, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 4, 32, 36, 38, 3, 34, 28, 31, 35, 37, 6, 12, 14, 19, 20, 22, 33, 39, 43, 53, 54, 55, 56, 57, 61, 67, 69, 70, 71, 30, 0, 5, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 21, 23, 24, 25, 26, 27, 29, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 58, 59, 60, 62, 63, 64, 65, 66, 68, 72, 16, 28, 34, 38, 42, 2, 14, 15, 18, 19, 26, 29, 30, 31, 32, 33, 40, 43, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 17, 20, 21, 22, 23, 24, 25, 27, 35, 36, 37, 39, 41, 2, 0, 7, 1, 86, 5, 74, 21, 89, 85, 88, 3, 4, 6, 51, 23, 111, 70, 56, 90, 98, 27, 78, 53, 68, 80, 87, 116, 12, 25, 109, 114, 103, 108, 110, 9, 57, 62, 65, 91, 96, 99, 69, 71, 72, 73, 81, 49, 50, 52, 93, 101, 36, 55, 64, 125, 19, 20, 22, 106, 41, 8, 11, 13, 29, 34, 37, 54, 102, 107, 118, 123, 126, 14, 15, 16, 18, 82, 83, 84, 92, 97, 100, 104, 112, 17, 32, 121, 94, 24, 113, 76, 77, 79, 10, 61, 95, 26, 28, 30, 31, 35, 38, 39, 40, 46, 58, 59, 60, 63, 66, 67, 75, 105, 115, 117, 119, 120, 124, 127, 128, 33, 42, 43, 44, 45, 47, 48, 122, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 2, 0, 1, 3, 4, 5, 6, 7, 8, 82, 11, 26, 19, 75, 6, 9, 47, 54, 66, 73, 80, 87, 0, 3, 4, 5, 18, 23, 24, 25, 44, 53, 62, 63, 65, 67, 68, 69, 70, 72, 76, 77, 86, 88, 89, 90, 91, 92, 93, 22, 10, 15, 21, 49, 58, 50, 59, 83, 1, 2, 7, 8, 12, 13, 14, 16, 17, 20, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 48, 51, 52, 55, 56, 57, 60, 61, 64, 71, 74, 78, 79, 81, 84, 85, 0, 1, 0, 1, 34, 2, 12, 13, 32, 37, 76, 3, 10, 11, 19, 20, 21, 22, 23, 27, 28, 29, 30, 35, 53, 55, 78, 4, 16, 17, 5, 6, 7, 8, 9, 14, 15, 18, 24, 25, 26, 31, 33, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 79, 80, 81, 82, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 30, 31, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 59, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62, 63, 64, 65, 36, 61, 20, 1, 19, 126, 127, 60, 56, 33, 34, 35, 21, 22, 52, 59, 67, 71, 72, 63, 65, 66, 32, 45, 57, 84, 91, 114, 125, 64, 0, 2, 3, 68, 70, 73, 26, 46, 53, 54, 55, 58, 115, 131, 74, 12, 96, 97, 99, 41, 42, 44, 49, 50, 75, 80, 83, 85, 103, 106, 107, 108, 109, 110, 111, 112, 113, 116, 117, 118, 119, 120, 124, 13, 62, 76, 77, 78, 86, 128, 129, 94, 23, 24, 25, 27, 28, 29, 30, 31, 37, 38, 39, 40, 43, 47, 48, 51, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 69, 79, 81, 82, 87, 88, 89, 90, 92, 93, 95, 98, 100, 101, 102, 104, 105, 121, 122, 123, 130, 132, 3, 2, 10, 11, 1, 4, 6, 8, 5, 7, 9, 0, 31, 30, 15, 43, 49, 53, 57, 45, 12, 13, 16, 18, 32, 34, 36, 14, 33, 35, 37, 21, 23, 17, 19, 20, 22, 24, 25, 26, 27, 28, 29, 42, 48, 52, 56, 38, 41, 44, 46, 50, 54, 39, 40, 47, 51, 55, 35, 36, 3, 5, 7, 9, 11, 2, 17, 30, 34, 14, 20, 23, 4, 6, 13, 16, 18, 19, 22, 24, 25, 31, 32, 33, 8, 10, 12, 15, 21, 0, 1, 26, 27, 28, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 5, 4, 6, 21, 0, 3, 18, 16, 15, 17, 9, 12, 20, 7, 14, 19, 8, 10, 11, 13, 1, 2, 167, 168, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 7, 6, 8, 9, 16, 2, 18, 19, 28, 27, 24, 25, 26, 17, 3, 20, 22, 21, 23, 13, 0, 4, 14, 1, 5, 12, 10, 11, 15, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 18, 22, 28, 35, 53, 54, 57, 59, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 55, 56, 58, 9, 13, 4, 6, 11, 15, 8, 12, 5, 7, 10, 14, 2, 3, 0, 1, 0, 3, 4, 7, 1, 2, 5, 6, 8, 9, 10, 0, 1, 2, 65, 64, 66, 52, 46, 49, 53, 59, 44, 48, 45, 57, 34, 25, 26, 27, 36, 56, 24, 43, 47, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 28, 29, 30, 31, 32, 33, 35, 37, 38, 39, 40, 41, 42, 50, 51, 54, 55, 58, 60, 61, 62, 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 84, 86, 5, 16, 18, 21, 81, 82, 3, 6, 10, 12, 14, 22, 24, 26, 29, 39, 41, 42, 54, 56, 58, 60, 62, 75, 0, 1, 2, 4, 7, 8, 9, 11, 13, 15, 17, 19, 20, 23, 25, 27, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 57, 59, 61, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 83, 85, 0, 2, 4, 6, 14, 16, 18, 20, 8, 31, 10, 11, 24, 25, 28, 29, 32, 33, 36, 38, 40, 41, 44, 45, 9, 30, 1, 3, 5, 7, 12, 13, 15, 17, 19, 21, 22, 23, 26, 27, 34, 35, 37, 39, 42, 43, 46, 47, 27, 28, 35, 36, 45, 46, 13, 14, 59, 60, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 30, 31, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0, 4, 1, 2, 3, 7, 5, 9, 6, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 8, 11, 9, 10, 0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 35, 1, 2, 20, 29, 32, 33, 34, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 1, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 1, 4, 27, 19, 21, 5, 18, 6, 8, 10, 11, 12, 14, 15, 16, 17, 20, 0, 1, 2, 3, 7, 9, 13, 22, 23, 24, 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 112, 110, 113, 111, 29, 37, 18, 93, 96, 97, 99, 98, 92, 100, 104, 105, 108, 101, 61, 62, 69, 77, 86, 70, 78, 85, 68, 76, 87, 60, 54, 55, 59, 30, 38, 73, 81, 90, 94, 19, 14, 16, 71, 79, 84, 50, 51, 57, 0, 2, 4, 6, 8, 10, 12, 20, 26, 34, 44, 64, 72, 80, 91, 40, 63, 13, 5, 7, 9, 11, 15, 1, 3, 39, 21, 48, 49, 56, 95, 74, 82, 89, 31, 25, 33, 45, 65, 43, 103, 106, 107, 109, 17, 52, 53, 58, 28, 36, 41, 23, 27, 35, 47, 42, 66, 22, 24, 32, 46, 67, 75, 83, 88, 102, 6, 7, 0, 1, 3, 5, 2, 4, 50, 48, 52, 54, 56, 2, 6, 14, 18, 22, 26, 30, 34, 49, 53, 55, 57, 58, 59, 60, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 19, 20, 21, 23, 24, 25, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 51, 23, 24, 25, 26, 16, 18, 20, 22, 15, 17, 19, 21, 6, 8, 10, 12, 14, 0, 2, 1, 3, 4, 5, 11, 7, 9, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 112, 114, 19, 61, 70, 18, 111, 3, 5, 6, 66, 82, 109, 110, 113, 58, 102, 104, 31, 35, 36, 37, 38, 71, 77, 86, 93, 95, 96, 108, 47, 25, 45, 46, 53, 55, 75, 40, 41, 42, 52, 60, 83, 84, 24, 26, 11, 12, 22, 23, 28, 30, 57, 63, 65, 69, 81, 90, 106, 32, 33, 34, 49, 50, 51, 72, 73, 78, 79, 87, 88, 94, 4, 7, 8, 9, 10, 20, 21, 29, 39, 43, 44, 48, 54, 56, 59, 62, 64, 67, 68, 74, 76, 80, 89, 91, 92, 100, 101, 115, 116, 16, 99, 13, 14, 15, 17, 27, 85, 97, 98, 103, 105, 107, 117, 7, 10, 19, 0, 1, 2, 3, 4, 5, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 0, 1, 2, 3, 4, 5, 7, 17, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 0, 1, 0, 7, 11, 5, 6, 10, 3, 4, 1, 2, 8, 9, 12, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 1, 3, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 0, 1, 75, 78, 76, 15, 79, 77, 8, 85, 14, 0, 4, 10, 81, 83, 84, 87, 12, 80, 82, 11, 9, 2, 6, 86, 36, 38, 37, 13, 1, 5, 3, 7, 49, 22, 24, 28, 32, 50, 58, 63, 66, 71, 23, 25, 29, 33, 47, 48, 51, 52, 53, 54, 46, 17, 19, 16, 20, 21, 26, 27, 30, 31, 34, 35, 39, 40, 41, 42, 43, 44, 45, 55, 56, 57, 59, 60, 61, 62, 64, 65, 67, 68, 69, 70, 72, 73, 74, 18, 11, 22, 1, 3, 5, 7, 9, 10, 13, 15, 16, 18, 20, 26, 28, 0, 2, 4, 6, 8, 12, 14, 17, 19, 21, 23, 24, 25, 27, 29, 47, 45, 43, 48, 42, 44, 49, 46, 33, 11, 27, 31, 37, 38, 63, 17, 18, 21, 23, 25, 29, 32, 35, 77, 83, 97, 0, 5, 9, 15, 16, 19, 39, 41, 53, 69, 20, 22, 24, 26, 28, 30, 34, 36, 76, 82, 96, 102, 103, 1, 3, 7, 13, 40, 51, 57, 61, 67, 71, 73, 75, 81, 87, 95, 101, 106, 107, 70, 2, 4, 6, 8, 10, 12, 14, 50, 52, 54, 55, 56, 58, 59, 60, 62, 64, 65, 66, 68, 72, 74, 78, 79, 80, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94, 98, 99, 100, 104, 105, 108, 109, 0, 1, 46, 43, 47, 42, 3, 44, 5, 20, 4, 18, 24, 26, 30, 38, 34, 36, 7, 9, 22, 2, 45, 21, 40, 19, 35, 37, 39, 32, 12, 14, 28, 10, 16, 41, 25, 27, 31, 6, 8, 23, 33, 11, 17, 13, 15, 29, 52, 50, 53, 48, 49, 51, 0, 1, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 5, 15, 19, 27, 31, 35, 39, 43, 96, 104, 120, 121, 131, 0, 1, 2, 10, 12, 24, 25, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 90, 91, 93, 95, 97, 99, 101, 103, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 122, 123, 124, 125, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136, 137, 138, 140, 144, 148, 152, 156, 160, 164, 3, 4, 6, 7, 8, 9, 11, 13, 14, 16, 17, 18, 20, 21, 22, 23, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 89, 92, 94, 98, 100, 102, 139, 141, 142, 143, 145, 146, 147, 149, 150, 151, 153, 154, 155, 157, 158, 159, 161, 162, 163, 165, 166, 36, 57, 60, 65, 68, 114, 135, 156, 161, 162, 165, 170, 176, 179, 182, 183, 188, 191, 194, 197, 198, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, 61, 62, 63, 64, 66, 67, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 157, 158, 159, 160, 163, 164, 166, 167, 168, 169, 171, 172, 173, 174, 175, 177, 178, 180, 181, 184, 185, 186, 187, 189, 190, 192, 193, 195, 196, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, 0, 3, 5, 10, 16, 18, 94, 4, 6, 7, 8, 17, 37, 44, 48, 51, 56, 66, 69, 75, 79, 82, 84, 88, 98, 99, 102, 1, 2, 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 45, 46, 47, 49, 50, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 68, 70, 71, 72, 73, 74, 76, 77, 78, 80, 81, 83, 85, 86, 87, 89, 90, 91, 92, 93, 95, 96, 97, 100, 101, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 81, 18, 24, 33, 69, 83, 19, 25, 35, 71, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 26, 27, 28, 29, 30, 31, 32, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 82, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 4, 5, 6, 31, 32, 39, 40, 41, 0, 1, 2, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35, 36, 37, 38, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 0, 1, 3, 22, 23, 26, 34, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 51, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 74, 75, 92, 93, 116, 143, 144, 149, 14, 15, 34, 35, 36, 37, 68, 69, 98, 99, 104, 105, 110, 111, 154, 155, 156, 157, 166, 167, 168, 169, 178, 179, 180, 181, 4, 5, 6, 7, 22, 23, 24, 25, 46, 47, 50, 51, 56, 57, 60, 61, 80, 82, 85, 87, 121, 122, 123, 124, 133, 134, 135, 136, 190, 191, 194, 197, 202, 203, 206, 207, 212, 213, 216, 217, 0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 26, 27, 28, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 48, 49, 52, 53, 54, 55, 58, 59, 62, 63, 64, 65, 66, 67, 70, 71, 72, 73, 76, 77, 78, 79, 81, 83, 84, 86, 88, 89, 90, 91, 94, 95, 96, 97, 100, 101, 102, 103, 106, 107, 108, 109, 112, 113, 114, 115, 117, 118, 119, 120, 125, 126, 127, 128, 129, 130, 131, 132, 137, 138, 139, 140, 141, 142, 145, 146, 147, 148, 150, 151, 152, 153, 158, 159, 160, 161, 162, 163, 164, 165, 170, 171, 172, 173, 174, 175, 176, 177, 182, 183, 184, 185, 186, 187, 188, 189, 192, 193, 195, 196, 198, 199, 200, 201, 204, 205, 208, 209, 210, 211, 214, 215, 218, 219, 220, 221, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 14, 15, 16, 17, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 11, 2, 5, 10, 8, 4, 9, 1, 7, 3, 0, 6, 42, 45, 36, 39, 12, 16, 18, 22, 38, 41, 44, 47, 37, 40, 43, 46, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 17, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 4, 5, 6, 8, 1, 3, 0, 2, 7, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 9, 11, 6, 7, 8, 10, 4, 5, 0, 1, 2, 3, 0, 2, 10, 3, 6, 1, 9, 11, 4, 8, 7, 5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 68, 116, 22, 10, 97, 117, 52, 110, 7, 19, 111, 115, 6, 18, 0, 74, 88, 12, 48, 108, 99, 109, 38, 104, 4, 16, 24, 96, 15, 3, 50, 84, 71, 85, 36, 102, 103, 119, 54, 86, 100, 30, 25, 105, 113, 69, 53, 63, 98, 87, 93, 89, 95, 9, 21, 62, 114, 5, 17, 26, 55, 2, 14, 65, 8, 20, 64, 92, 42, 106, 11, 23, 46, 66, 34, 101, 107, 56, 35, 47, 57, 67, 76, 118, 75, 83, 82, 94, 37, 77, 29, 51, 1, 13, 27, 49, 58, 112, 39, 59, 28, 70, 44, 73, 80, 81, 32, 72, 31, 43, 33, 40, 41, 45, 60, 61, 78, 79, 90, 91 }; /**Function************************************************************* Synopsis [Reads library from array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Dar_LibReadNodes() { Vec_Int_t * vResult; int i; vResult = Vec_IntAlloc( s_nDataSize1 ); for ( i = 0; i < s_nDataSize1; i++ ) Vec_IntPush( vResult, s_Data1[i] ); return vResult; } /**Function************************************************************* Synopsis [Reads library from array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Dar_LibReadOuts() { Vec_Int_t * vResult; int i; vResult = Vec_IntAlloc( s_nDataSize2 ); for ( i = 0; i < s_nDataSize2; i++ ) Vec_IntPush( vResult, s_Data2[i] ); return vResult; } /**Function************************************************************* Synopsis [Reads library from array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Dar_LibReadPrios() { Vec_Int_t * vResult; int i; vResult = Vec_IntAlloc( s_nDataSize3 ); for ( i = 0; i < s_nDataSize3; i++ ) Vec_IntPush( vResult, s_Data3[i] ); return vResult; } #if 0 #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Generate arrays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_NtkGenerateArrays( Abc_Ntk_t * pNtk ) { extern int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); Abc_Obj_t * pObj; int i, Count = 0; assert( Abc_NtkPiNum(pNtk) == 4 ); assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_ObjFanoutNum(Abc_AigConst1(pNtk)) == 0 ); /* { unsigned char * pBuffer; int Pos, uLit, uLit0, uLit1, Size, Digit; Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (void *)Count++; Pos = 0; pBuffer = ABC_ALLOC( char, 200000 ); Abc_AigForEachAnd( pNtk, pObj, i ) { pObj->pCopy = (void *)Count++; uLit = ((int)pObj->pCopy << 1); uLit0 = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); uLit1 = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj); assert( uLit0 < uLit1 ); Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); } // write the buffer Size = 0; for ( i = 0; i < Pos; i++ ) { if ( i % 36 == 0 ) printf( "\n" ); Digit = pBuffer[i] & 0xF; if ( Digit < 10 ) printf( "%d", Digit ); else printf( "%c", Digit - 10 + 'A' ); Digit = pBuffer[i]; Digit >>= 4; if ( Digit < 10 ) printf( "%d", Digit ); else printf( "%c", Digit - 10 + 'A' ); } printf( "\n" ); printf( "Size = %d.\n", Pos ); } */ Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (void *)Count++; Abc_AigForEachAnd( pNtk, pObj, i ) { // if ( (Count - 4) % 6 == 0 ) // printf( "\n" ); // printf( "%5d,", (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj) ); // printf( "%5d,", (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj) ); pObj->pCopy = (void *)Count++; } // printf( "\n" ); // printf( "Nodes = %d.\n", Count-4 ); Abc_NtkForEachPo( pNtk, pObj, i ) { if ( i % 12 == 0 ) printf( "\n" ); printf( "%5d,", (int)Abc_ObjFanin0(pObj)->pCopy ); } printf( "\n" ); printf( "Outputs = %d.\n", Abc_NtkPoNum(pNtk) ); /* { unsigned char * pBuffer; Vec_Int_t * vOuts; int Pos, Prev, Out; vOuts = Vec_IntAlloc( 25000 ); Abc_NtkForEachPo( pNtk, pObj, i ) Vec_IntPush( vOuts, Abc_ObjFaninId0(pObj) ); Vec_IntSort( vOuts, 0 ); Pos = 0; pBuffer = ABC_ALLOC( char, 50000 ); Prev = 0; Vec_IntForEachEntry( vOuts, Out, i ) { assert( Prev < Out ); Pos = Io_WriteAigerEncode( pBuffer, Pos, Out - Prev ); Prev = Out; } Vec_IntFree( vOuts ); // write the buffer for ( i = 0; i < Pos; i++ ) { if ( i % 32 == 0 ) printf( "\n" ); printf( "%d,", pBuffer[i] ); } printf( "\n" ); printf( "Size = %d.\n", Pos ); } */ } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darInt.h000066400000000000000000000166201300674244400230030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__dar__darInt_h #define ABC__aig__dar__darInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "aig/aig/aig.h" #include "dar.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Dar_Man_t_ Dar_Man_t; typedef struct Dar_Cut_t_ Dar_Cut_t; // the AIG 4-cut struct Dar_Cut_t_ // 6 words { unsigned uSign; // cut signature unsigned uTruth : 16; // the truth table of the cut function unsigned Value : 11; // the value of the cut unsigned fBest : 1; // marks the best cut unsigned fUsed : 1; // marks the cut currently in use unsigned nLeaves : 3; // the number of leaves int pLeaves[4]; // the array of leaves }; // the AIG manager struct Dar_Man_t_ { // input data Dar_RwrPar_t * pPars; // rewriting parameters Aig_Man_t * pAig; // AIG manager // various data members Aig_MmFixed_t * pMemCuts; // memory manager for cuts void * pManCnf; // CNF managers Vec_Ptr_t * vCutNodes; // the nodes with cuts allocated // current rewriting step Vec_Ptr_t * vLeavesBest; // the best set of leaves int OutBest; // the best output (in the library) int OutNumBest; // the best number of the output int GainBest; // the best gain int LevelBest; // the level of node with the best gain int ClassBest; // the equivalence class of the best replacement // function statistics int nTotalSubgs; // the total number of subgraphs tried int ClassTimes[222];// the runtimes for each class int ClassGains[222];// the gains for each class int ClassSubgs[222];// the graphs for each class int nCutMemUsed; // memory used for cuts // rewriting statistics int nNodesInit; // the original number of nodes int nNodesTried; // the number of nodes attempted int nCutsAll; // all cut pairs int nCutsTried; // computed cuts int nCutsUsed; // used cuts int nCutsBad; // bad cuts due to absent fanin int nCutsGood; // good cuts int nCutsSkipped; // skipped bad cuts // timing statistics abctime timeCuts; abctime timeEval; abctime timeOther; abctime timeTotal; abctime time1; abctime time2; }; static inline Dar_Cut_t * Dar_ObjCuts( Aig_Obj_t * pObj ) { return (Dar_Cut_t *)pObj->pData; } static inline void Dar_ObjSetCuts( Aig_Obj_t * pObj, Dar_Cut_t * pCuts ) { assert( !Aig_ObjIsNone(pObj) ); pObj->pData = pCuts; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // iterator over all cuts of the node #define Dar_ObjForEachCutAll( pObj, pCut, i ) \ for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) #define Dar_ObjForEachCut( pObj, pCut, i ) \ for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) if ( (pCut)->fUsed==0 ) {} else // iterator over leaves of the cut #define Dar_CutForEachLeaf( p, pCut, pLeaf, i ) \ for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pLeaf) = Aig_ManObj(p, (pCut)->pLeaves[i])), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== darBalance.c ========================================================*/ /*=== darCore.c ===========================================================*/ /*=== darCut.c ============================================================*/ extern void Dar_ManCutsRestart( Dar_Man_t * p, Aig_Obj_t * pRoot ); extern void Dar_ManCutsFree( Dar_Man_t * p ); extern Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj ); extern Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj ); extern Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj, int fSkipTtMin ); extern void Dar_ObjCutPrint( Aig_Man_t * p, Aig_Obj_t * pObj ); /*=== darData.c ===========================================================*/ extern Vec_Int_t * Dar_LibReadNodes(); extern Vec_Int_t * Dar_LibReadOuts(); extern Vec_Int_t * Dar_LibReadPrios(); /*=== darLib.c ============================================================*/ extern void Dar_LibStart(); extern void Dar_LibStop(); extern void Dar_LibReturnCanonicals( unsigned * pCanons ); extern void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required, int * pnMffcSize ); extern Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p ); /*=== darMan.c ============================================================*/ extern Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ); extern void Dar_ManStop( Dar_Man_t * p ); extern void Dar_ManPrintStats( Dar_Man_t * p ); /*=== darPrec.c ============================================================*/ extern char ** Dar_Permutations( int n ); extern void Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darLib.c000066400000000000000000001253331300674244400227540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darLib.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Library of AIG subgraphs used for rewriting.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darLib.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" #include "aig/gia/gia.h" #include "dar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Dar_Lib_t_ Dar_Lib_t; typedef struct Dar_LibObj_t_ Dar_LibObj_t; typedef struct Dar_LibDat_t_ Dar_LibDat_t; struct Dar_LibObj_t_ // library object (2 words) { unsigned Fan0 : 16; // the first fanin unsigned Fan1 : 16; // the second fanin unsigned fCompl0 : 1; // the first compl attribute unsigned fCompl1 : 1; // the second compl attribute unsigned fPhase : 1; // the phase of the node unsigned fTerm : 1; // indicates a PI unsigned Num : 28; // internal use }; struct Dar_LibDat_t_ // library object data { union { Aig_Obj_t * pFunc; // the corresponding AIG node if it exists int iGunc; }; // the corresponding AIG node if it exists int Level; // level of this node after it is constructured int TravId; // traversal ID of the library object data float dProb; // probability of the node being 1 unsigned char fMffc; // set to one if node is part of MFFC unsigned char nLats[3]; // the number of latches on the input/output stem }; struct Dar_Lib_t_ // library { // objects Dar_LibObj_t * pObjs; // the set of library objects int nObjs; // the number of objects used int iObj; // the current object // structures by class int nSubgr[222]; // the number of subgraphs by class int * pSubgr[222]; // the subgraphs for each class int * pSubgrMem; // memory for subgraph pointers int nSubgrTotal; // the total number of subgraph // structure priorities int * pPriosMem; // memory for priority of structures int * pPrios[222]; // pointers to the priority numbers // structure places in the priorities int * pPlaceMem; // memory for places of structures in the priority lists int * pPlace[222]; // pointers to the places numbers // structure scores int * pScoreMem; // memory for scores of structures int * pScore[222]; // pointers to the scores numbers // nodes by class int nNodes[222]; // the number of nodes by class int * pNodes[222]; // the nodes for each class int * pNodesMem; // memory for nodes pointers int nNodesTotal; // the total number of nodes // prepared library int nSubgraphs; int nNodes0Max; // nodes by class int nNodes0[222]; // the number of nodes by class int * pNodes0[222]; // the nodes for each class int * pNodes0Mem; // memory for nodes pointers int nNodes0Total; // the total number of nodes // structures by class int nSubgr0[222]; // the number of subgraphs by class int * pSubgr0[222]; // the subgraphs for each class int * pSubgr0Mem; // memory for subgraph pointers int nSubgr0Total; // the total number of subgraph // object data Dar_LibDat_t * pDatas; int nDatas; // information about NPN classes char ** pPerms4; unsigned short * puCanons; char * pPhases; char * pPerms; unsigned char * pMap; }; static Dar_Lib_t * s_DarLib = NULL; static inline Dar_LibObj_t * Dar_LibObj( Dar_Lib_t * p, int Id ) { return p->pObjs + Id; } static inline int Dar_LibObjTruth( Dar_LibObj_t * pObj ) { return pObj->Num < (0xFFFF & ~pObj->Num) ? pObj->Num : (0xFFFF & ~pObj->Num); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dar_Lib_t * Dar_LibAlloc( int nObjs ) { unsigned uTruths[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 }; Dar_Lib_t * p; int i;//, clk = Abc_Clock(); p = ABC_ALLOC( Dar_Lib_t, 1 ); memset( p, 0, sizeof(Dar_Lib_t) ); // allocate objects p->nObjs = nObjs; p->pObjs = ABC_ALLOC( Dar_LibObj_t, nObjs ); memset( p->pObjs, 0, sizeof(Dar_LibObj_t) * nObjs ); // allocate canonical data p->pPerms4 = Dar_Permutations( 4 ); Dar_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap ); // start the elementary objects p->iObj = 4; for ( i = 0; i < 4; i++ ) { p->pObjs[i].fTerm = 1; p->pObjs[i].Num = uTruths[i]; } // ABC_PRT( "Library start", Abc_Clock() - clk ); return p; } /**Function************************************************************* Synopsis [Frees the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibFree( Dar_Lib_t * p ) { ABC_FREE( p->pObjs ); ABC_FREE( p->pDatas ); ABC_FREE( p->pNodesMem ); ABC_FREE( p->pNodes0Mem ); ABC_FREE( p->pSubgrMem ); ABC_FREE( p->pSubgr0Mem ); ABC_FREE( p->pPriosMem ); ABC_FREE( p->pPlaceMem ); ABC_FREE( p->pScoreMem ); ABC_FREE( p->pPerms4 ); ABC_FREE( p->puCanons ); ABC_FREE( p->pPhases ); ABC_FREE( p->pPerms ); ABC_FREE( p->pMap ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns canonical truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_LibReturnClass( unsigned uTruth ) { return s_DarLib->pMap[uTruth & 0xffff]; } /**Function************************************************************* Synopsis [Returns canonical truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibReturnCanonicals( unsigned * pCanons ) { int Visits[222] = {0}; int i, k; // find canonical truth tables for ( i = k = 0; i < (1<<16); i++ ) if ( !Visits[s_DarLib->pMap[i]] ) { Visits[s_DarLib->pMap[i]] = 1; pCanons[k++] = ((i<<16) | i); } assert( k == 222 ); } /**Function************************************************************* Synopsis [Adds one AND to the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibAddNode( Dar_Lib_t * p, int Id0, int Id1, int fCompl0, int fCompl1 ) { Dar_LibObj_t * pFan0 = Dar_LibObj( p, Id0 ); Dar_LibObj_t * pFan1 = Dar_LibObj( p, Id1 ); Dar_LibObj_t * pObj = p->pObjs + p->iObj++; pObj->Fan0 = Id0; pObj->Fan1 = Id1; pObj->fCompl0 = fCompl0; pObj->fCompl1 = fCompl1; pObj->fPhase = (fCompl0 ^ pFan0->fPhase) & (fCompl1 ^ pFan1->fPhase); pObj->Num = 0xFFFF & (fCompl0? ~pFan0->Num : pFan0->Num) & (fCompl1? ~pFan1->Num : pFan1->Num); } /**Function************************************************************* Synopsis [Adds one AND to the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibSetup_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect ) { if ( pObj->fTerm || (int)pObj->Num == Class ) return; pObj->Num = Class; Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect ); Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect ); if ( fCollect ) p->pNodes[Class][ p->nNodes[Class]++ ] = pObj-p->pObjs; else p->nNodes[Class]++; } /**Function************************************************************* Synopsis [Adds one AND to the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibSetup( Dar_Lib_t * p, Vec_Int_t * vOuts, Vec_Int_t * vPrios ) { int fTraining = 0; Dar_LibObj_t * pObj; int nNodesTotal, uTruth, Class, Out, i, k; assert( p->iObj == p->nObjs ); // count the number of representatives of each class for ( i = 0; i < 222; i++ ) p->nSubgr[i] = p->nNodes[i] = 0; Vec_IntForEachEntry( vOuts, Out, i ) { pObj = Dar_LibObj( p, Out ); uTruth = Dar_LibObjTruth( pObj ); Class = p->pMap[uTruth]; p->nSubgr[Class]++; } // allocate memory for the roots of each class p->pSubgrMem = ABC_ALLOC( int, Vec_IntSize(vOuts) ); p->pSubgr0Mem = ABC_ALLOC( int, Vec_IntSize(vOuts) ); p->nSubgrTotal = 0; for ( i = 0; i < 222; i++ ) { p->pSubgr[i] = p->pSubgrMem + p->nSubgrTotal; p->pSubgr0[i] = p->pSubgr0Mem + p->nSubgrTotal; p->nSubgrTotal += p->nSubgr[i]; p->nSubgr[i] = 0; } assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); // add the outputs to storage Vec_IntForEachEntry( vOuts, Out, i ) { pObj = Dar_LibObj( p, Out ); uTruth = Dar_LibObjTruth( pObj ); Class = p->pMap[uTruth]; p->pSubgr[Class][ p->nSubgr[Class]++ ] = Out; } if ( fTraining ) { // allocate memory for the priority of roots of each class p->pPriosMem = ABC_ALLOC( int, Vec_IntSize(vOuts) ); p->nSubgrTotal = 0; for ( i = 0; i < 222; i++ ) { p->pPrios[i] = p->pPriosMem + p->nSubgrTotal; p->nSubgrTotal += p->nSubgr[i]; for ( k = 0; k < p->nSubgr[i]; k++ ) p->pPrios[i][k] = k; } assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); // allocate memory for the priority of roots of each class p->pPlaceMem = ABC_ALLOC( int, Vec_IntSize(vOuts) ); p->nSubgrTotal = 0; for ( i = 0; i < 222; i++ ) { p->pPlace[i] = p->pPlaceMem + p->nSubgrTotal; p->nSubgrTotal += p->nSubgr[i]; for ( k = 0; k < p->nSubgr[i]; k++ ) p->pPlace[i][k] = k; } assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); // allocate memory for the priority of roots of each class p->pScoreMem = ABC_ALLOC( int, Vec_IntSize(vOuts) ); p->nSubgrTotal = 0; for ( i = 0; i < 222; i++ ) { p->pScore[i] = p->pScoreMem + p->nSubgrTotal; p->nSubgrTotal += p->nSubgr[i]; for ( k = 0; k < p->nSubgr[i]; k++ ) p->pScore[i][k] = 0; } assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); } else { int Counter = 0; // allocate memory for the priority of roots of each class p->pPriosMem = ABC_ALLOC( int, Vec_IntSize(vOuts) ); p->nSubgrTotal = 0; for ( i = 0; i < 222; i++ ) { p->pPrios[i] = p->pPriosMem + p->nSubgrTotal; p->nSubgrTotal += p->nSubgr[i]; for ( k = 0; k < p->nSubgr[i]; k++ ) p->pPrios[i][k] = Vec_IntEntry(vPrios, Counter++); } assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); assert( Counter == Vec_IntSize(vPrios) ); } // create traversal IDs for ( i = 0; i < p->iObj; i++ ) Dar_LibObj(p, i)->Num = 0xff; // count nodes in each class for ( i = 0; i < 222; i++ ) for ( k = 0; k < p->nSubgr[i]; k++ ) Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 0 ); // count the total number of nodes p->nNodesTotal = 0; for ( i = 0; i < 222; i++ ) p->nNodesTotal += p->nNodes[i]; // allocate memory for the nodes of each class p->pNodesMem = ABC_ALLOC( int, p->nNodesTotal ); p->pNodes0Mem = ABC_ALLOC( int, p->nNodesTotal ); p->nNodesTotal = 0; for ( i = 0; i < 222; i++ ) { p->pNodes[i] = p->pNodesMem + p->nNodesTotal; p->pNodes0[i] = p->pNodes0Mem + p->nNodesTotal; p->nNodesTotal += p->nNodes[i]; p->nNodes[i] = 0; } // create traversal IDs for ( i = 0; i < p->iObj; i++ ) Dar_LibObj(p, i)->Num = 0xff; // add the nodes to storage nNodesTotal = 0; for ( i = 0; i < 222; i++ ) { for ( k = 0; k < p->nSubgr[i]; k++ ) Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 1 ); nNodesTotal += p->nNodes[i]; //printf( "Class %3d : Subgraphs = %4d. Nodes = %5d.\n", i, p->nSubgr[i], p->nNodes[i] ); } assert( nNodesTotal == p->nNodesTotal ); // prepare the number of the PI nodes for ( i = 0; i < 4; i++ ) Dar_LibObj(p, i)->Num = i; } /**Function************************************************************* Synopsis [Starts the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibCreateData( Dar_Lib_t * p, int nDatas ) { if ( p->nDatas == nDatas ) return; ABC_FREE( p->pDatas ); // allocate datas p->nDatas = nDatas; p->pDatas = ABC_ALLOC( Dar_LibDat_t, nDatas ); memset( p->pDatas, 0, sizeof(Dar_LibDat_t) * nDatas ); } /**Function************************************************************* Synopsis [Adds one AND to the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibSetup0_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect ) { if ( pObj->fTerm || (int)pObj->Num == Class ) return; pObj->Num = Class; Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect ); Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect ); if ( fCollect ) p->pNodes0[Class][ p->nNodes0[Class]++ ] = pObj-p->pObjs; else p->nNodes0[Class]++; } /**Function************************************************************* Synopsis [Starts the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibPrepare( int nSubgraphs ) { Dar_Lib_t * p = s_DarLib; int i, k, nNodes0Total; if ( p->nSubgraphs == nSubgraphs ) return; // favor special classes: // 1 : F = (!d*!c*!b*!a) // 4 : F = (!d*!c*!(b*a)) // 12 : F = (!d*!(c*!(!b*!a))) // 20 : F = (!d*!(c*b*a)) // set the subgraph counters p->nSubgr0Total = 0; for ( i = 0; i < 222; i++ ) { // if ( i == 1 || i == 4 || i == 12 || i == 20 ) // special classes if ( i == 1 ) // special classes p->nSubgr0[i] = p->nSubgr[i]; else p->nSubgr0[i] = Abc_MinInt( p->nSubgr[i], nSubgraphs ); p->nSubgr0Total += p->nSubgr0[i]; for ( k = 0; k < p->nSubgr0[i]; k++ ) p->pSubgr0[i][k] = p->pSubgr[i][ p->pPrios[i][k] ]; } // count the number of nodes // clean node counters for ( i = 0; i < 222; i++ ) p->nNodes0[i] = 0; // create traversal IDs for ( i = 0; i < p->iObj; i++ ) Dar_LibObj(p, i)->Num = 0xff; // count nodes in each class // count the total number of nodes and the largest class p->nNodes0Total = 0; p->nNodes0Max = 0; for ( i = 0; i < 222; i++ ) { for ( k = 0; k < p->nSubgr0[i]; k++ ) Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 0 ); p->nNodes0Total += p->nNodes0[i]; p->nNodes0Max = Abc_MaxInt( p->nNodes0Max, p->nNodes0[i] ); } // clean node counters for ( i = 0; i < 222; i++ ) p->nNodes0[i] = 0; // create traversal IDs for ( i = 0; i < p->iObj; i++ ) Dar_LibObj(p, i)->Num = 0xff; // add the nodes to storage nNodes0Total = 0; for ( i = 0; i < 222; i++ ) { for ( k = 0; k < p->nSubgr0[i]; k++ ) Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 1 ); nNodes0Total += p->nNodes0[i]; } assert( nNodes0Total == p->nNodes0Total ); // prepare the number of the PI nodes for ( i = 0; i < 4; i++ ) Dar_LibObj(p, i)->Num = i; // realloc the datas Dar_LibCreateData( p, p->nNodes0Max + 32 ); // allocated more because Dar_LibBuildBest() sometimes requires more entries } /**Function************************************************************* Synopsis [Reads library from array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dar_Lib_t * Dar_LibRead() { Vec_Int_t * vObjs, * vOuts, * vPrios; Dar_Lib_t * p; int i; // read nodes and outputs vObjs = Dar_LibReadNodes(); vOuts = Dar_LibReadOuts(); vPrios = Dar_LibReadPrios(); // create library p = Dar_LibAlloc( Vec_IntSize(vObjs)/2 + 4 ); // create nodes for ( i = 0; i < vObjs->nSize; i += 2 ) Dar_LibAddNode( p, vObjs->pArray[i] >> 1, vObjs->pArray[i+1] >> 1, vObjs->pArray[i] & 1, vObjs->pArray[i+1] & 1 ); // create outputs Dar_LibSetup( p, vOuts, vPrios ); Vec_IntFree( vObjs ); Vec_IntFree( vOuts ); Vec_IntFree( vPrios ); return p; } /**Function************************************************************* Synopsis [Starts the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibStart() { // abctime clk = Abc_Clock(); if ( s_DarLib != NULL ) return; assert( s_DarLib == NULL ); s_DarLib = Dar_LibRead(); // printf( "The 4-input library started with %d nodes and %d subgraphs. ", s_DarLib->nObjs - 4, s_DarLib->nSubgrTotal ); // ABC_PRT( "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Stops the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibStop() { assert( s_DarLib != NULL ); Dar_LibFree( s_DarLib ); s_DarLib = NULL; } /**Function************************************************************* Synopsis [Updates the score of the class and adjusts the priority of this class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibIncrementScore( int Class, int Out, int Gain ) { int * pPrios = s_DarLib->pPrios[Class]; // pPrios[i] = Out int * pPlace = s_DarLib->pPlace[Class]; // pPlace[Out] = i int * pScore = s_DarLib->pScore[Class]; // score of Out int Out2; assert( Class >= 0 && Class < 222 ); assert( Out >= 0 && Out < s_DarLib->nSubgr[Class] ); assert( pPlace[pPrios[Out]] == Out ); // increment the score pScore[Out] += Gain; // move the out in the order while ( pPlace[Out] > 0 && pScore[Out] > pScore[ pPrios[pPlace[Out]-1] ] ) { // get the previous output in the priority list Out2 = pPrios[pPlace[Out]-1]; // swap Out and Out2 pPlace[Out]--; pPlace[Out2]++; pPrios[pPlace[Out]] = Out; pPrios[pPlace[Out2]] = Out2; } } /**Function************************************************************* Synopsis [Prints out the priorities into the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibDumpPriorities() { int i, k, Out, Out2, Counter = 0, Printed = 0; printf( "\nOutput priorities (total = %d):\n", s_DarLib->nSubgrTotal ); for ( i = 0; i < 222; i++ ) { // printf( "Class%d: ", i ); for ( k = 0; k < s_DarLib->nSubgr[i]; k++ ) { Out = s_DarLib->pPrios[i][k]; Out2 = k == 0 ? Out : s_DarLib->pPrios[i][k-1]; assert( s_DarLib->pScore[i][Out2] >= s_DarLib->pScore[i][Out] ); // printf( "%d(%d), ", Out, s_DarLib->pScore[i][Out] ); printf( "%d, ", Out ); Printed++; if ( ++Counter == 15 ) { printf( "\n" ); Counter = 0; } } } printf( "\n" ); assert( Printed == s_DarLib->nSubgrTotal ); } /**Function************************************************************* Synopsis [Matches the cut with its canonical form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut ) { Aig_Obj_t * pFanin; unsigned uPhase; char * pPerm; int i; assert( pCut->nLeaves == 4 ); // get the fanin permutation uPhase = s_DarLib->pPhases[pCut->uTruth]; pPerm = s_DarLib->pPerms4[ (int)s_DarLib->pPerms[pCut->uTruth] ]; // collect fanins with the corresponding permutation/phase for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Aig_ManObj( p->pAig, pCut->pLeaves[ (int)pPerm[i] ] ); if ( pFanin == NULL ) { p->nCutsBad++; return 0; } pFanin = Aig_NotCond(pFanin, ((uPhase >> i) & 1) ); s_DarLib->pDatas[i].pFunc = pFanin; s_DarLib->pDatas[i].Level = Aig_Regular(pFanin)->Level; // copy the propability of node being one if ( p->pPars->fPower ) { float Prob = Abc_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pFanin)) ) ); s_DarLib->pDatas[i].dProb = Aig_IsComplement(pFanin)? 1.0-Prob : Prob; } } p->nCutsGood++; return 1; } /**Function************************************************************* Synopsis [Marks the MFFC of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves, float * pPower ) { int i, nNodes; // mark the cut leaves for ( i = 0; i < nLeaves; i++ ) Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs++; // label MFFC with current ID nNodes = Aig_NodeMffcLabel( p, pRoot, pPower ); // unmark the cut leaves for ( i = 0; i < nLeaves; i++ ) Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs--; return nNodes; } /**Function************************************************************* Synopsis [Evaluates one cut.] Description [Returns the best gain.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibObjPrint_rec( Dar_LibObj_t * pObj ) { if ( pObj->fTerm ) { printf( "%c", 'a' + (int)(pObj - s_DarLib->pObjs) ); return; } printf( "(" ); Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan0) ); if ( pObj->fCompl0 ) printf( "\'" ); Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan1) ); if ( pObj->fCompl0 ) printf( "\'" ); printf( ")" ); } /**Function************************************************************* Synopsis [Assigns numbers to the nodes of one class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibEvalAssignNums( Dar_Man_t * p, int Class, Aig_Obj_t * pRoot ) { Dar_LibObj_t * pObj; Dar_LibDat_t * pData, * pData0, * pData1; Aig_Obj_t * pFanin0, * pFanin1; int i; for ( i = 0; i < s_DarLib->nNodes0[Class]; i++ ) { // get one class node, assign its temporary number and set its data pObj = Dar_LibObj(s_DarLib, s_DarLib->pNodes0[Class][i]); pObj->Num = 4 + i; assert( (int)pObj->Num < s_DarLib->nNodes0Max + 4 ); pData = s_DarLib->pDatas + pObj->Num; pData->fMffc = 0; pData->pFunc = NULL; pData->TravId = 0xFFFF; // explore the fanins assert( (int)Dar_LibObj(s_DarLib, pObj->Fan0)->Num < s_DarLib->nNodes0Max + 4 ); assert( (int)Dar_LibObj(s_DarLib, pObj->Fan1)->Num < s_DarLib->nNodes0Max + 4 ); pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num; pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num; pData->Level = 1 + Abc_MaxInt(pData0->Level, pData1->Level); if ( pData0->pFunc == NULL || pData1->pFunc == NULL ) continue; pFanin0 = Aig_NotCond( pData0->pFunc, pObj->fCompl0 ); pFanin1 = Aig_NotCond( pData1->pFunc, pObj->fCompl1 ); if ( Aig_Regular(pFanin0) == pRoot || Aig_Regular(pFanin1) == pRoot ) continue; pData->pFunc = Aig_TableLookupTwo( p->pAig, pFanin0, pFanin1 ); if ( pData->pFunc ) { // update the level to be more accurate pData->Level = Aig_Regular(pData->pFunc)->Level; // mark the node if it is part of MFFC pData->fMffc = Aig_ObjIsTravIdCurrent(p->pAig, Aig_Regular(pData->pFunc)); // assign the probability if ( p->pPars->fPower ) { float Prob = Abc_Int2Float( Vec_IntEntry( p->pAig->vProbs, Aig_ObjId(Aig_Regular(pData->pFunc)) ) ); pData->dProb = Aig_IsComplement(pData->pFunc)? 1.0-Prob : Prob; } } } } /**Function************************************************************* Synopsis [Evaluates one cut.] Description [Returns the best gain.] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required, float * pPower ) { Dar_LibDat_t * pData; float Power0, Power1; int Area; if ( pPower ) *pPower = (float)0.0; pData = s_DarLib->pDatas + pObj->Num; if ( pData->TravId == Out ) return 0; pData->TravId = Out; if ( pObj->fTerm ) { if ( pPower ) *pPower = pData->dProb; return 0; } assert( pObj->Num > 3 ); if ( pData->Level > Required ) return 0xff; if ( pData->pFunc && !pData->fMffc ) { if ( pPower ) *pPower = pData->dProb; return 0; } // this is a new node - get a bound on the area of its branches nNodesSaved--; Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1, pPower? &Power0 : NULL ); if ( Area > nNodesSaved ) return 0xff; Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1, pPower? &Power1 : NULL ); if ( Area > nNodesSaved ) return 0xff; if ( pPower ) { Dar_LibDat_t * pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num; Dar_LibDat_t * pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num; pData->dProb = (pObj->fCompl0? 1.0 - pData0->dProb : pData0->dProb)* (pObj->fCompl1? 1.0 - pData1->dProb : pData1->dProb); *pPower = Power0 + 2.0 * pData0->dProb * (1.0 - pData0->dProb) + Power1 + 2.0 * pData1->dProb * (1.0 - pData1->dProb); } return Area + 1; } /**Function************************************************************* Synopsis [Evaluates one cut.] Description [Returns the best gain.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required, int * pnMffcSize ) { int fTraining = 0; float PowerSaved, PowerAdded; Dar_LibObj_t * pObj; int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained; abctime clk = Abc_Clock(); if ( pCut->nLeaves != 4 ) return; // check if the cut exits and assigns leaves and their levels if ( !Dar_LibCutMatch(p, pCut) ) return; // mark MFFC of the node nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves, p->pPars->fPower? &PowerSaved : NULL ); // evaluate the cut Class = s_DarLib->pMap[pCut->uTruth]; Dar_LibEvalAssignNums( p, Class, pRoot ); // profile outputs by their savings p->nTotalSubgs += s_DarLib->nSubgr0[Class]; p->ClassSubgs[Class] += s_DarLib->nSubgr0[Class]; for ( Out = 0; Out < s_DarLib->nSubgr0[Class]; Out++ ) { pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]); if ( Aig_Regular(s_DarLib->pDatas[pObj->Num].pFunc) == pRoot ) continue; nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required, p->pPars->fPower? &PowerAdded : NULL ); nNodesGained = nNodesSaved - nNodesAdded; if ( p->pPars->fPower && PowerSaved < PowerAdded ) continue; if ( fTraining && nNodesGained >= 0 ) Dar_LibIncrementScore( Class, Out, nNodesGained + 1 ); if ( nNodesGained < 0 || (nNodesGained == 0 && !p->pPars->fUseZeros) ) continue; if ( nNodesGained < p->GainBest || (nNodesGained == p->GainBest && s_DarLib->pDatas[pObj->Num].Level >= p->LevelBest) ) continue; // remember this possibility Vec_PtrClear( p->vLeavesBest ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Vec_PtrPush( p->vLeavesBest, s_DarLib->pDatas[k].pFunc ); p->OutBest = s_DarLib->pSubgr0[Class][Out]; p->OutNumBest = Out; p->LevelBest = s_DarLib->pDatas[pObj->Num].Level; p->GainBest = nNodesGained; p->ClassBest = Class; assert( p->LevelBest <= Required ); *pnMffcSize = nNodesSaved; } clk = Abc_Clock() - clk; p->ClassTimes[Class] += clk; p->timeEval += clk; } /**Function************************************************************* Synopsis [Clears the fields of the nodes used in this cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter ) { if ( pObj->fTerm ) return; pObj->Num = (*pCounter)++; s_DarLib->pDatas[ pObj->Num ].pFunc = NULL; Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter ); Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter ); } /**Function************************************************************* Synopsis [Reconstructs the best cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Dar_LibBuildBest_rec( Dar_Man_t * p, Dar_LibObj_t * pObj ) { Aig_Obj_t * pFanin0, * pFanin1; Dar_LibDat_t * pData = s_DarLib->pDatas + pObj->Num; if ( pData->pFunc ) return pData->pFunc; pFanin0 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) ); pFanin1 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) ); pFanin0 = Aig_NotCond( pFanin0, pObj->fCompl0 ); pFanin1 = Aig_NotCond( pFanin1, pObj->fCompl1 ); pData->pFunc = Aig_And( p->pAig, pFanin0, pFanin1 ); // assert( pData->Level == (int)Aig_Regular(pData->pFunc)->Level ); return pData->pFunc; } /**Function************************************************************* Synopsis [Reconstructs the best cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p ) { int i, Counter = 4; for ( i = 0; i < Vec_PtrSize(p->vLeavesBest); i++ ) s_DarLib->pDatas[i].pFunc = (Aig_Obj_t *)Vec_PtrEntry( p->vLeavesBest, i ); Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, p->OutBest), &Counter ); return Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, p->OutBest) ); } /**Function************************************************************* Synopsis [Matches the cut with its canonical form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar2_LibCutMatch( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth ) { unsigned uPhase; char * pPerm; int i; assert( Vec_IntSize(vCutLits) == 4 ); // get the fanin permutation uPhase = s_DarLib->pPhases[uTruth]; pPerm = s_DarLib->pPerms4[ (int)s_DarLib->pPerms[uTruth] ]; // collect fanins with the corresponding permutation/phase for ( i = 0; i < Vec_IntSize(vCutLits); i++ ) { // pFanin = Gia_ManObj( p, pCut->pLeaves[ (int)pPerm[i] ] ); // pFanin = Gia_ManObj( p, Vec_IntEntry( vCutLits, (int)pPerm[i] ) ); // pFanin = Gia_ObjFromLit( p, Vec_IntEntry( vCutLits, (int)pPerm[i] ) ); s_DarLib->pDatas[i].iGunc = Abc_LitNotCond( Vec_IntEntry(vCutLits, (int)pPerm[i]), ((uPhase >> i) & 1) ); s_DarLib->pDatas[i].Level = Gia_ObjLevel( p, Gia_Regular(Gia_ObjFromLit(p, s_DarLib->pDatas[i].iGunc)) ); } return 1; } /**Function************************************************************* Synopsis [Assigns numbers to the nodes of one class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar2_LibEvalAssignNums( Gia_Man_t * p, int Class ) { Dar_LibObj_t * pObj; Dar_LibDat_t * pData, * pData0, * pData1; int iFanin0, iFanin1, i, iLit; for ( i = 0; i < s_DarLib->nNodes0[Class]; i++ ) { // get one class node, assign its temporary number and set its data pObj = Dar_LibObj(s_DarLib, s_DarLib->pNodes0[Class][i]); pObj->Num = 4 + i; assert( (int)pObj->Num < s_DarLib->nNodes0Max + 4 ); pData = s_DarLib->pDatas + pObj->Num; pData->fMffc = 0; pData->iGunc = -1; pData->TravId = 0xFFFF; // explore the fanins assert( (int)Dar_LibObj(s_DarLib, pObj->Fan0)->Num < s_DarLib->nNodes0Max + 4 ); assert( (int)Dar_LibObj(s_DarLib, pObj->Fan1)->Num < s_DarLib->nNodes0Max + 4 ); pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num; pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num; pData->Level = 1 + Abc_MaxInt(pData0->Level, pData1->Level); if ( pData0->iGunc == -1 || pData1->iGunc == -1 ) continue; iFanin0 = Abc_LitNotCond( pData0->iGunc, pObj->fCompl0 ); iFanin1 = Abc_LitNotCond( pData1->iGunc, pObj->fCompl1 ); // compute the resulting literal if ( iFanin0 == 0 || iFanin1 == 0 || iFanin0 == Abc_LitNot(iFanin1) ) iLit = 0; else if ( iFanin0 == 1 || iFanin0 == iFanin1 ) iLit = iFanin1; else if ( iFanin1 == 1 ) iLit = iFanin0; else { iLit = Gia_ManHashLookup( p, Gia_ObjFromLit(p, iFanin0), Gia_ObjFromLit(p, iFanin1) ); if ( iLit == 0 ) iLit = -1; } pData->iGunc = iLit; if ( pData->iGunc >= 0 ) { // update the level to be more accurate pData->Level = Gia_ObjLevel( p, Gia_Regular(Gia_ObjFromLit(p, pData->iGunc)) ); // mark the node if it is part of MFFC // pData->fMffc = Gia_ObjIsTravIdCurrentArray(p, Gia_Regular(pData->pGunc)); } } } /**Function************************************************************* Synopsis [Evaluates one cut.] Description [Returns the best gain.] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar2_LibEval_rec( Dar_LibObj_t * pObj, int Out ) { Dar_LibDat_t * pData; int Area; pData = s_DarLib->pDatas + pObj->Num; if ( pData->TravId == Out ) return 0; pData->TravId = Out; if ( pObj->fTerm ) return 0; assert( pObj->Num > 3 ); if ( pData->iGunc >= 0 )//&& !pData->fMffc ) return 0; // this is a new node - get a bound on the area of its branches // nNodesSaved--; Area = Dar2_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out ); // if ( Area > nNodesSaved ) // return 0xff; Area += Dar2_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out ); // if ( Area > nNodesSaved ) // return 0xff; return Area + 1; } /**Function************************************************************* Synopsis [Evaluates one cut.] Description [Returns the best gain.] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar2_LibEval( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest2 ) { int p_OutBest = -1; int p_OutNumBest = -1; int p_LevelBest = 1000000; int p_GainBest = -1000000; int p_ClassBest = -1; // int fTraining = 0; Dar_LibObj_t * pObj; int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained; // abctime clk = Abc_Clock(); assert( Vec_IntSize(vCutLits) == 4 ); assert( (uTruth >> 16) == 0 ); // check if the cut exits and assigns leaves and their levels if ( !Dar2_LibCutMatch(p, vCutLits, uTruth) ) return -1; // mark MFFC of the node // nNodesSaved = Dar2_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves, p->pPars->fPower? &PowerSaved : NULL ); nNodesSaved = 0; // evaluate the cut Class = s_DarLib->pMap[uTruth]; Dar2_LibEvalAssignNums( p, Class ); // profile outputs by their savings // p->nTotalSubgs += s_DarLib->nSubgr0[Class]; // p->ClassSubgs[Class] += s_DarLib->nSubgr0[Class]; for ( Out = 0; Out < s_DarLib->nSubgr0[Class]; Out++ ) { pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]); // nNodesAdded = Dar2_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required, p->pPars->fPower? &PowerAdded : NULL ); nNodesAdded = Dar2_LibEval_rec( pObj, Out ); nNodesGained = nNodesSaved - nNodesAdded; if ( fKeepLevel ) { if ( s_DarLib->pDatas[pObj->Num].Level > p_LevelBest || (s_DarLib->pDatas[pObj->Num].Level == p_LevelBest && nNodesGained <= p_GainBest) ) continue; } else { if ( nNodesGained < p_GainBest || (nNodesGained == p_GainBest && s_DarLib->pDatas[pObj->Num].Level >= p_LevelBest) ) continue; } // remember this possibility Vec_IntClear( vLeavesBest2 ); for ( k = 0; k < Vec_IntSize(vCutLits); k++ ) Vec_IntPush( vLeavesBest2, s_DarLib->pDatas[k].iGunc ); p_OutBest = s_DarLib->pSubgr0[Class][Out]; p_OutNumBest = Out; p_LevelBest = s_DarLib->pDatas[pObj->Num].Level; p_GainBest = nNodesGained; p_ClassBest = Class; // assert( p_LevelBest <= Required ); } //clk = Abc_Clock() - clk; //p->ClassTimes[Class] += clk; //p->timeEval += clk; assert( p_OutBest != -1 ); return p_OutBest; } /**Function************************************************************* Synopsis [Clears the fields of the nodes used i this cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar2_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter ) { if ( pObj->fTerm ) return; pObj->Num = (*pCounter)++; s_DarLib->pDatas[ pObj->Num ].iGunc = -1; Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter ); Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter ); } /**Function************************************************************* Synopsis [Reconstructs the best cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar2_LibBuildBest_rec( Gia_Man_t * p, Dar_LibObj_t * pObj ) { Gia_Obj_t * pNode; Dar_LibDat_t * pData; int iFanin0, iFanin1; pData = s_DarLib->pDatas + pObj->Num; if ( pData->iGunc >= 0 ) return pData->iGunc; iFanin0 = Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) ); iFanin1 = Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) ); iFanin0 = Abc_LitNotCond( iFanin0, pObj->fCompl0 ); iFanin1 = Abc_LitNotCond( iFanin1, pObj->fCompl1 ); pData->iGunc = Gia_ManHashAnd( p, iFanin0, iFanin1 ); pNode = Gia_ManObj( p, Abc_Lit2Var(pData->iGunc) ); if ( Gia_ObjIsAnd( pNode ) ) Gia_ObjSetAndLevel( p, pNode ); Gia_ObjSetPhase( p, pNode ); return pData->iGunc; } /**Function************************************************************* Synopsis [Reconstructs the best cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar2_LibBuildBest( Gia_Man_t * p, Vec_Int_t * vLeavesBest2, int OutBest ) { int i, iLeaf, Counter = 4; assert( Vec_IntSize(vLeavesBest2) == 4 ); Vec_IntForEachEntry( vLeavesBest2, iLeaf, i ) s_DarLib->pDatas[i].iGunc = iLeaf; Dar2_LibBuildClear_rec( Dar_LibObj(s_DarLib, OutBest), &Counter ); return Dar2_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, OutBest) ); } /**Function************************************************************* Synopsis [Evaluate and build the new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_LibEvalBuild( Gia_Man_t * p, Vec_Int_t * vCutLits, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest2 ) { int OutBest = Dar2_LibEval( p, vCutLits, uTruth, fKeepLevel, vLeavesBest2 ); return Dar2_LibBuildBest( p, vLeavesBest2, OutBest ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darMan.c000066400000000000000000000121041300674244400227500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [AIG manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) { Dar_Man_t * p; Aig_ManCleanData( pAig ); p = ABC_ALLOC( Dar_Man_t, 1 ); memset( p, 0, sizeof(Dar_Man_t) ); p->pPars = pPars; p->pAig = pAig; p->vCutNodes = Vec_PtrAlloc( 1000 ); p->pMemCuts = Aig_MmFixedStart( p->pPars->nCutsMax * sizeof(Dar_Cut_t), 1024 ); p->vLeavesBest = Vec_PtrAlloc( 4 ); return p; } /**Function************************************************************* Synopsis [Stops the rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManStop( Dar_Man_t * p ) { if ( p->pPars->fVerbose ) Dar_ManPrintStats( p ); if ( p->vCutNodes ) Vec_PtrFree( p->vCutNodes ); if ( p->pMemCuts ) Aig_MmFixedStop( p->pMemCuts, 0 ); if ( p->vLeavesBest ) Vec_PtrFree( p->vLeavesBest ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManPrintStats( Dar_Man_t * p ) { unsigned pCanons[222]; int Gain, i; extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig); printf( "Tried = %8d. Beg = %8d. End = %8d. Gain = %6d. (%6.2f %%). Cut mem = %d MB\n", p->nNodesTried, p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit, p->nCutMemUsed ); printf( "Cuts = %8d. Tried = %8d. Used = %8d. Bad = %5d. Skipped = %5d. Ave = %.2f.\n", p->nCutsAll, p->nCutsTried, p->nCutsUsed, p->nCutsBad, p->nCutsSkipped, (float)p->nCutsUsed/Aig_ManNodeNum(p->pAig) ); printf( "Bufs = %5d. BufMax = %5d. BufReplace = %6d. BufFix = %6d. Levels = %4d.\n", Aig_ManBufNum(p->pAig), p->pAig->nBufMax, p->pAig->nBufReplaces, p->pAig->nBufFixes, Aig_ManLevels(p->pAig) ); ABC_PRT( "Cuts ", p->timeCuts ); ABC_PRT( "Eval ", p->timeEval ); ABC_PRT( "Other ", p->timeOther ); ABC_PRT( "TOTAL ", p->timeTotal ); if ( !p->pPars->fVeryVerbose ) return; Dar_LibReturnCanonicals( pCanons ); for ( i = 0; i < 222; i++ ) { if ( p->ClassGains[i] == 0 && p->ClassTimes[i] == 0 ) continue; printf( "%3d : ", i ); printf( "G = %6d (%5.2f %%) ", p->ClassGains[i], Gain? 100.0*p->ClassGains[i]/Gain : 0.0 ); printf( "S = %8d (%5.2f %%) ", p->ClassSubgs[i], p->nTotalSubgs? 100.0*p->ClassSubgs[i]/p->nTotalSubgs : 0.0 ); printf( "R = %7d ", p->ClassGains[i]? p->ClassSubgs[i]/p->ClassGains[i] : 9999999 ); // Kit_DsdPrintFromTruth( pCanons + i, 4 ); // ABC_PRTP( "T", p->ClassTimes[i], p->timeEval ); printf( "\n" ); } fflush( stdout ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #if 0 ABC_NAMESPACE_IMPL_END #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START void Dar_ManPrintScript() { unsigned pCanons[222]; int i; Dar_LibReturnCanonicals( pCanons ); for ( i = 1; i < 222; i++ ) { Kit_DsdNtk_t * pNtk; pNtk = Kit_DsdDecompose( pCanons + i, 4 ); printf( " \"" ); Kit_DsdPrint( stdout, pNtk ); printf( "\", /* %3d */\n", i ); Kit_DsdNtkFree( pNtk ); } } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darPrec.c000066400000000000000000000252231300674244400231340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darPrec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Truth table precomputation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darPrec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocated one-memory-chunk array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char ** Dar_ArrayAlloc( int nCols, int nRows, int Size ) { char ** pRes; char * pBuffer; int i; assert( nCols > 0 && nRows > 0 && Size > 0 ); pBuffer = ABC_ALLOC( char, nCols * (sizeof(void *) + nRows * Size) ); pRes = (char **)pBuffer; pRes[0] = pBuffer + nCols * sizeof(void *); for ( i = 1; i < nCols; i++ ) pRes[i] = pRes[0] + i * nRows * Size; return pRes; } /**Function******************************************************************** Synopsis [Computes the factorial.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ int Dar_Factorial( int n ) { int i, Res = 1; for ( i = 1; i <= n; i++ ) Res *= i; return Res; } /**Function******************************************************************** Synopsis [Fills in the array of permutations.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Dar_Permutations_rec( char ** pRes, int nFact, int n, char Array[] ) { char ** pNext; int nFactNext; int iTemp, iCur, iLast, k; if ( n == 1 ) { pRes[0][0] = Array[0]; return; } // get the next factorial nFactNext = nFact / n; // get the last entry iLast = n - 1; for ( iCur = 0; iCur < n; iCur++ ) { // swap Cur and Last iTemp = Array[iCur]; Array[iCur] = Array[iLast]; Array[iLast] = iTemp; // get the pointer to the current section pNext = pRes + (n - 1 - iCur) * nFactNext; // set the last entry for ( k = 0; k < nFactNext; k++ ) pNext[k][iLast] = Array[iLast]; // call recursively for this part Dar_Permutations_rec( pNext, nFactNext, n - 1, Array ); // swap them back iTemp = Array[iCur]; Array[iCur] = Array[iLast]; Array[iLast] = iTemp; } } /**Function******************************************************************** Synopsis [Computes the set of all permutations.] Description [The number of permutations in the array is n!. The number of entries in each permutation is n. Therefore, the resulting array is a two-dimentional array of the size: n! x n. To free the resulting array, call ABC_FREE() on the pointer returned by this procedure.] SideEffects [] SeeAlso [] ******************************************************************************/ char ** Dar_Permutations( int n ) { char Array[50]; char ** pRes; int nFact, i; // allocate memory nFact = Dar_Factorial( n ); pRes = Dar_ArrayAlloc( nFact, n, sizeof(char) ); // fill in the permutations for ( i = 0; i < n; i++ ) Array[i] = i; Dar_Permutations_rec( pRes, nFact, n, Array ); // print the permutations /* { int i, k; for ( i = 0; i < nFact; i++ ) { printf( "{" ); for ( k = 0; k < n; k++ ) printf( " %d", pRes[i][k] ); printf( " }\n" ); } } */ return pRes; } /**Function************************************************************* Synopsis [Permutes the given vector of minterms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_TruthPermute_int( int * pMints, int nMints, char * pPerm, int nVars, int * pMintsP ) { int m, v; // clean the storage for minterms memset( pMintsP, 0, sizeof(int) * nMints ); // go through minterms and add the variables for ( m = 0; m < nMints; m++ ) for ( v = 0; v < nVars; v++ ) if ( pMints[m] & (1 << v) ) pMintsP[m] |= (1 << pPerm[v]); } /**Function************************************************************* Synopsis [Permutes the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Dar_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse ) { unsigned Result; int * pMints; int * pMintsP; int nMints; int i, m; assert( nVars < 6 ); nMints = (1 << nVars); pMints = ABC_ALLOC( int, nMints ); pMintsP = ABC_ALLOC( int, nMints ); for ( i = 0; i < nMints; i++ ) pMints[i] = i; Dar_TruthPermute_int( pMints, nMints, pPerms, nVars, pMintsP ); Result = 0; if ( fReverse ) { for ( m = 0; m < nMints; m++ ) if ( Truth & (1 << pMintsP[m]) ) Result |= (1 << m); } else { for ( m = 0; m < nMints; m++ ) if ( Truth & (1 << m) ) Result |= (1 << pMintsP[m]); } ABC_FREE( pMints ); ABC_FREE( pMintsP ); return Result; } /**Function************************************************************* Synopsis [Changes the phase of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Dar_TruthPolarize( unsigned uTruth, int Polarity, int nVars ) { // elementary truth tables static unsigned Signs[5] = { 0xAAAAAAAA, // 1010 1010 1010 1010 1010 1010 1010 1010 0xCCCCCCCC, // 1010 1010 1010 1010 1010 1010 1010 1010 0xF0F0F0F0, // 1111 0000 1111 0000 1111 0000 1111 0000 0xFF00FF00, // 1111 1111 0000 0000 1111 1111 0000 0000 0xFFFF0000 // 1111 1111 1111 1111 0000 0000 0000 0000 }; unsigned uTruthRes, uCof0, uCof1; int nMints, Shift, v; assert( nVars < 6 ); nMints = (1 << nVars); uTruthRes = uTruth; for ( v = 0; v < nVars; v++ ) if ( Polarity & (1 << v) ) { uCof0 = uTruth & ~Signs[v]; uCof1 = uTruth & Signs[v]; Shift = (1 << v); uCof0 <<= Shift; uCof1 >>= Shift; uTruth = uCof0 | uCof1; } return uTruth; } /**Function************************************************************* Synopsis [Computes NPN canonical forms for 4-variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ) { unsigned short * uCanons; unsigned char * uMap; unsigned uTruth, uPhase, uPerm; char ** pPerms4, * uPhases, * uPerms; int nFuncs, nClasses; int i, k; nFuncs = (1 << 16); uCanons = ABC_CALLOC( unsigned short, nFuncs ); uPhases = ABC_CALLOC( char, nFuncs ); uPerms = ABC_CALLOC( char, nFuncs ); uMap = ABC_CALLOC( unsigned char, nFuncs ); pPerms4 = Dar_Permutations( 4 ); nClasses = 1; nFuncs = (1 << 15); for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ ) { // skip already assigned if ( uCanons[uTruth] ) { assert( uTruth > uCanons[uTruth] ); uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]]; continue; } uMap[uTruth] = nClasses++; for ( i = 0; i < 16; i++ ) { uPhase = Dar_TruthPolarize( uTruth, i, 4 ); for ( k = 0; k < 24; k++ ) { uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 ); if ( uCanons[uPerm] == 0 ) { uCanons[uPerm] = uTruth; uPhases[uPerm] = i; uPerms[uPerm] = k; uMap[uPerm] = uMap[uTruth]; uPerm = ~uPerm & 0xFFFF; uCanons[uPerm] = uTruth; uPhases[uPerm] = i | 16; uPerms[uPerm] = k; uMap[uPerm] = uMap[uTruth]; } else assert( uCanons[uPerm] == uTruth ); } uPhase = Dar_TruthPolarize( ~uTruth & 0xFFFF, i, 4 ); for ( k = 0; k < 24; k++ ) { uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 ); if ( uCanons[uPerm] == 0 ) { uCanons[uPerm] = uTruth; uPhases[uPerm] = i; uPerms[uPerm] = k; uMap[uPerm] = uMap[uTruth]; uPerm = ~uPerm & 0xFFFF; uCanons[uPerm] = uTruth; uPhases[uPerm] = i | 16; uPerms[uPerm] = k; uMap[uPerm] = uMap[uTruth]; } else assert( uCanons[uPerm] == uTruth ); } } } for ( uTruth = 1; uTruth < 0xffff; uTruth++ ) assert( uMap[uTruth] != 0 ); uPhases[(1<<16)-1] = 16; assert( nClasses == 222 ); ABC_FREE( pPerms4 ); if ( puCanons ) *puCanons = uCanons; else ABC_FREE( uCanons ); if ( puPhases ) *puPhases = uPhases; else ABC_FREE( uPhases ); if ( puPerms ) *puPerms = uPerms; else ABC_FREE( uPerms ); if ( puMap ) *puMap = uMap; else ABC_FREE( uMap ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darRefact.c000066400000000000000000000522621300674244400234520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darRefact.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Refactoring.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darRefact.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" #include "bool/kit/kit.h" #include "bool/bdc/bdc.h" #include "bool/bdc/bdcInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the refactoring manager typedef struct Ref_Man_t_ Ref_Man_t; struct Ref_Man_t_ { // input data Dar_RefPar_t * pPars; // rewriting parameters Aig_Man_t * pAig; // AIG manager // computed cuts Vec_Vec_t * vCuts; // the storage for cuts // truth table and ISOP Vec_Ptr_t * vTruthElem; // elementary truth tables Vec_Ptr_t * vTruthStore; // storage for truth tables Vec_Int_t * vMemory; // storage for ISOP Vec_Ptr_t * vCutNodes; // storage for internal nodes of the cut // various data members Vec_Ptr_t * vLeavesBest; // the best set of leaves Kit_Graph_t * pGraphBest; // the best factored form int GainBest; // the best gain int LevelBest; // the level of node with the best gain // bi-decomposition Bdc_Par_t DecPars; // decomposition parameters Bdc_Man_t * pManDec; // decomposition manager // node statistics int nNodesInit; // the initial number of nodes int nNodesTried; // the number of nodes tried int nNodesBelow; // the number of nodes below the level limit int nNodesExten; // the number of nodes with extended cut int nCutsUsed; // the number of rewriting steps int nCutsTried; // the number of cuts tries // timing statistics abctime timeCuts; abctime timeEval; abctime timeOther; abctime timeTotal; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the structure with default assignment of parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars ) { memset( pPars, 0, sizeof(Dar_RefPar_t) ); pPars->nMffcMin = 2; // the min MFFC size for which refactoring is used pPars->nLeafMax = 12; // the max number of leaves of a cut pPars->nCutsMax = 5; // the max number of cuts to consider pPars->fUpdateLevel = 0; pPars->fUseZeros = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } /**Function************************************************************* Synopsis [Starts the rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ref_Man_t * Dar_ManRefStart( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) { Ref_Man_t * p; // start the manager p = ABC_ALLOC( Ref_Man_t, 1 ); memset( p, 0, sizeof(Ref_Man_t) ); p->pAig = pAig; p->pPars = pPars; // other data p->vCuts = Vec_VecStart( pPars->nCutsMax ); p->vTruthElem = Vec_PtrAllocTruthTables( pPars->nLeafMax ); p->vTruthStore = Vec_PtrAllocSimInfo( 1024, Kit_TruthWordNum(pPars->nLeafMax) ); p->vMemory = Vec_IntAlloc( 1 << 16 ); p->vCutNodes = Vec_PtrAlloc( 256 ); p->vLeavesBest = Vec_PtrAlloc( pPars->nLeafMax ); // alloc bi-decomposition manager p->DecPars.nVarsMax = pPars->nLeafMax; p->DecPars.fVerbose = pPars->fVerbose; p->DecPars.fVeryVerbose = 0; // p->pManDec = Bdc_ManAlloc( &p->DecPars ); return p; } /**Function************************************************************* Synopsis [Prints out the statistics of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManRefPrintStats( Ref_Man_t * p ) { int Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig); printf( "NodesBeg = %8d. NodesEnd = %8d. Gain = %6d. (%6.2f %%).\n", p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit ); printf( "Tried = %6d. Below = %5d. Extended = %5d. Used = %5d. Levels = %4d.\n", p->nNodesTried, p->nNodesBelow, p->nNodesExten, p->nCutsUsed, Aig_ManLevels(p->pAig) ); ABC_PRT( "Cuts ", p->timeCuts ); ABC_PRT( "Eval ", p->timeEval ); ABC_PRT( "Other ", p->timeOther ); ABC_PRT( "TOTAL ", p->timeTotal ); } /**Function************************************************************* Synopsis [Stops the rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dar_ManRefStop( Ref_Man_t * p ) { if ( p->pManDec ) Bdc_ManFree( p->pManDec ); if ( p->pPars->fVerbose ) Dar_ManRefPrintStats( p ); Vec_VecFree( p->vCuts ); Vec_PtrFree( p->vTruthElem ); Vec_PtrFree( p->vTruthStore ); Vec_PtrFree( p->vLeavesBest ); Vec_IntFree( p->vMemory ); Vec_PtrFree( p->vCutNodes ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ref_ObjComputeCuts( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Vec_t * vCuts ) { } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ref_ObjPrint( Aig_Obj_t * pObj ) { printf( "%d", pObj? Aig_Regular(pObj)->Id : -1 ); if ( pObj ) printf( "(%d) ", Aig_IsComplement(pObj) ); } /**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 Dar_RefactTryGraph( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph, int NodeMax, int LevelMax ) { Kit_Node_t * pNode, * pNode0, * pNode1; Aig_Obj_t * pAnd, * pAnd0, * pAnd1; int i, Counter, LevelNew, LevelOld; // check for constant function or a literal if ( Kit_GraphIsConst(pGraph) || Kit_GraphIsVar(pGraph) ) return 0; // set the levels of the leaves Kit_GraphForEachLeaf( pGraph, pNode, i ) { pNode->pFunc = Vec_PtrEntry(vCut, i); pNode->Level = Aig_Regular((Aig_Obj_t *)pNode->pFunc)->Level; assert( Aig_Regular((Aig_Obj_t *)pNode->pFunc)->Level < (1<<24)-1 ); } //printf( "Trying:\n" ); // compute the AIG size after adding the internal nodes Counter = 0; Kit_GraphForEachNode( pGraph, pNode, i ) { // get the children of this node pNode0 = Kit_GraphNode( pGraph, pNode->eEdge0.Node ); pNode1 = Kit_GraphNode( pGraph, pNode->eEdge1.Node ); // get the AIG nodes corresponding to the children pAnd0 = (Aig_Obj_t *)pNode0->pFunc; pAnd1 = (Aig_Obj_t *)pNode1->pFunc; if ( pAnd0 && pAnd1 ) { // if they are both present, find the resulting node pAnd0 = Aig_NotCond( pAnd0, pNode->eEdge0.fCompl ); pAnd1 = Aig_NotCond( pAnd1, pNode->eEdge1.fCompl ); pAnd = Aig_TableLookupTwo( pAig, pAnd0, pAnd1 ); // return -1 if the node is the same as the original root if ( Aig_Regular(pAnd) == pRoot ) return -1; } else pAnd = NULL; // count the number of added nodes if ( pAnd == NULL || Aig_ObjIsTravIdCurrent(pAig, Aig_Regular(pAnd)) ) { if ( ++Counter > NodeMax ) return -1; } // count the number of new levels LevelNew = 1 + Abc_MaxInt( pNode0->Level, pNode1->Level ); if ( pAnd ) { if ( Aig_Regular(pAnd) == Aig_ManConst1(pAig) ) LevelNew = 0; else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd0) ) LevelNew = (int)Aig_Regular(pAnd0)->Level; else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd1) ) LevelNew = (int)Aig_Regular(pAnd1)->Level; LevelOld = (int)Aig_Regular(pAnd)->Level; // assert( LevelNew == LevelOld ); } if ( LevelNew > LevelMax ) return -1; pNode->pFunc = pAnd; pNode->Level = LevelNew; /* printf( "Checking " ); Ref_ObjPrint( pAnd0 ); printf( " and " ); Ref_ObjPrint( pAnd1 ); printf( " Result " ); Ref_ObjPrint( pNode->pFunc ); printf( "\n" ); */ } return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Dar_RefactBuildGraph( Aig_Man_t * pAig, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph ) { Aig_Obj_t * pAnd0, * pAnd1; Kit_Node_t * pNode = NULL; int i; // check for constant function if ( Kit_GraphIsConst(pGraph) ) return Aig_NotCond( Aig_ManConst1(pAig), Kit_GraphIsComplement(pGraph) ); // set the leaves Kit_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = Vec_PtrEntry(vCut, i); // check for a literal if ( Kit_GraphIsVar(pGraph) ) return Aig_NotCond( (Aig_Obj_t *)Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph //printf( "Building (current number %d):\n", Aig_ManObjNumMax(pAig) ); Kit_GraphForEachNode( pGraph, pNode, i ) { pAnd0 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Aig_NotCond( (Aig_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Aig_And( pAig, pAnd0, pAnd1 ); /* printf( "Checking " ); Ref_ObjPrint( pAnd0 ); printf( " and " ); Ref_ObjPrint( pAnd1 ); printf( " Result " ); Ref_ObjPrint( pNode->pFunc ); printf( "\n" ); */ } // complement the result if necessary return Aig_NotCond( (Aig_Obj_t *)pNode->pFunc, Kit_GraphIsComplement(pGraph) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ManRefactorTryCuts( Ref_Man_t * p, Aig_Obj_t * pObj, int nNodesSaved, int Required ) { Vec_Ptr_t * vCut; Kit_Graph_t * pGraphCur; int k, RetValue, GainCur, nNodesAdded; unsigned * pTruth; p->GainBest = -1; p->pGraphBest = NULL; Vec_VecForEachLevel( p->vCuts, vCut, k ) { if ( Vec_PtrSize(vCut) == 0 ) continue; // if ( Vec_PtrSize(vCut) != 0 && Vec_PtrSize(Vec_VecEntry(p->vCuts, k+1)) != 0 ) // continue; p->nCutsTried++; // get the cut nodes Aig_ObjCollectCut( pObj, vCut, p->vCutNodes ); // get the truth table pTruth = Aig_ManCutTruth( pObj, vCut, p->vCutNodes, p->vTruthElem, p->vTruthStore ); if ( Kit_TruthIsConst0(pTruth, Vec_PtrSize(vCut)) ) { p->GainBest = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL ); p->pGraphBest = Kit_GraphCreateConst0(); Vec_PtrCopy( p->vLeavesBest, vCut ); return p->GainBest; } if ( Kit_TruthIsConst1(pTruth, Vec_PtrSize(vCut)) ) { p->GainBest = Aig_NodeMffcSupp( p->pAig, pObj, 0, NULL ); p->pGraphBest = Kit_GraphCreateConst1(); Vec_PtrCopy( p->vLeavesBest, vCut ); return p->GainBest; } // try the positive phase RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 ); if ( RetValue > -1 ) { pGraphCur = Kit_SopFactor( p->vMemory, 0, Vec_PtrSize(vCut), p->vMemory ); /* { int RetValue; RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 ); printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue ); } */ nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required ); if ( nNodesAdded > -1 ) { GainCur = nNodesSaved - nNodesAdded; if ( p->GainBest < GainCur || (p->GainBest == GainCur && (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) ) { p->GainBest = GainCur; if ( p->pGraphBest ) Kit_GraphFree( p->pGraphBest ); p->pGraphBest = pGraphCur; Vec_PtrCopy( p->vLeavesBest, vCut ); } else Kit_GraphFree( pGraphCur ); } else Kit_GraphFree( pGraphCur ); } // try negative phase Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) ); RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 ); // Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) ); if ( RetValue > -1 ) { pGraphCur = Kit_SopFactor( p->vMemory, 1, Vec_PtrSize(vCut), p->vMemory ); /* { int RetValue; RetValue = Bdc_ManDecompose( p->pManDec, pTruth, NULL, Vec_PtrSize(vCut), NULL, 1000 ); printf( "Graph = %d. Bidec = %d.\n", Kit_GraphNodeNum(pGraphCur), RetValue ); } */ nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required ); if ( nNodesAdded > -1 ) { GainCur = nNodesSaved - nNodesAdded; if ( p->GainBest < GainCur || (p->GainBest == GainCur && (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) ) { p->GainBest = GainCur; if ( p->pGraphBest ) Kit_GraphFree( p->pGraphBest ); p->pGraphBest = pGraphCur; Vec_PtrCopy( p->vLeavesBest, vCut ); } else Kit_GraphFree( pGraphCur ); } else Kit_GraphFree( pGraphCur ); } } return p->GainBest; } /**Function************************************************************* Synopsis [Returns 1 if a non-PI node has nLevelMin or below.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ObjCutLevelAchieved( Vec_Ptr_t * vCut, int nLevelMin ) { Aig_Obj_t * pObj; int i; Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) if ( !Aig_ObjIsCi(pObj) && (int)pObj->Level <= nLevelMin ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) { // Bar_Progress_t * pProgress; Ref_Man_t * p; Vec_Ptr_t * vCut, * vCut2; Aig_Obj_t * pObj, * pObjNew; int nNodesOld, nNodeBefore, nNodeAfter, nNodesSaved, nNodesSaved2; int i, Required, nLevelMin; abctime clkStart, clk; // start the manager p = Dar_ManRefStart( pAig, pPars ); // remove dangling nodes Aig_ManCleanup( pAig ); // if updating levels is requested, start fanout and timing Aig_ManFanoutStart( pAig ); if ( p->pPars->fUpdateLevel ) Aig_ManStartReverseLevels( pAig, 0 ); // resynthesize each node once clkStart = Abc_Clock(); vCut = Vec_VecEntry( p->vCuts, 0 ); vCut2 = Vec_VecEntry( p->vCuts, 1 ); p->nNodesInit = Aig_ManNodeNum(pAig); nNodesOld = Vec_PtrSize( pAig->vObjs ); // pProgress = Bar_ProgressStart( stdout, nNodesOld ); Aig_ManForEachObj( pAig, pObj, i ) { // Bar_ProgressUpdate( pProgress, i, NULL ); if ( !Aig_ObjIsNode(pObj) ) continue; if ( i > nNodesOld ) break; if ( pAig->Time2Quit && !(i & 256) && Abc_Clock() > pAig->Time2Quit ) break; Vec_VecClear( p->vCuts ); //printf( "\nConsidering node %d.\n", pObj->Id ); // get the bounded MFFC size clk = Abc_Clock(); nLevelMin = Abc_MaxInt( 0, Aig_ObjLevel(pObj) - 10 ); nNodesSaved = Aig_NodeMffcSupp( pAig, pObj, nLevelMin, vCut ); if ( nNodesSaved < p->pPars->nMffcMin ) // too small to consider { p->timeCuts += Abc_Clock() - clk; continue; } p->nNodesTried++; if ( Vec_PtrSize(vCut) > p->pPars->nLeafMax ) // get one reconv-driven cut { Aig_ManFindCut( pObj, vCut, p->vCutNodes, p->pPars->nLeafMax, 50 ); nNodesSaved = Aig_NodeMffcLabelCut( p->pAig, pObj, vCut ); } else if ( Vec_PtrSize(vCut) < p->pPars->nLeafMax - 2 && p->pPars->fExtend ) { if ( !Dar_ObjCutLevelAchieved(vCut, nLevelMin) ) { if ( Aig_NodeMffcExtendCut( pAig, pObj, vCut, vCut2 ) ) { nNodesSaved2 = Aig_NodeMffcLabelCut( p->pAig, pObj, vCut ); assert( nNodesSaved2 == nNodesSaved ); } if ( Vec_PtrSize(vCut2) > p->pPars->nLeafMax ) Vec_PtrClear(vCut2); if ( Vec_PtrSize(vCut2) > 0 ) { p->nNodesExten++; // printf( "%d(%d) ", Vec_PtrSize(vCut), Vec_PtrSize(vCut2) ); } } else p->nNodesBelow++; } p->timeCuts += Abc_Clock() - clk; // try the cuts clk = Abc_Clock(); Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : ABC_INFINITY; Dar_ManRefactorTryCuts( p, pObj, nNodesSaved, Required ); p->timeEval += Abc_Clock() - clk; // check the best gain if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) { if ( p->pGraphBest ) Kit_GraphFree( p->pGraphBest ); continue; } //printf( "\n" ); // if we end up here, a rewriting step is accepted nNodeBefore = Aig_ManNodeNum( pAig ); pObjNew = Dar_RefactBuildGraph( pAig, p->vLeavesBest, p->pGraphBest ); assert( (int)Aig_Regular(pObjNew)->Level <= Required ); // replace the node Aig_ObjReplace( pAig, pObj, pObjNew, p->pPars->fUpdateLevel ); // compare the gains nNodeAfter = Aig_ManNodeNum( pAig ); assert( p->GainBest <= nNodeBefore - nNodeAfter ); Kit_GraphFree( p->pGraphBest ); p->nCutsUsed++; // break; } p->timeTotal = Abc_Clock() - clkStart; p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; // Bar_ProgressStop( pProgress ); // put the nodes into the DFS order and reassign their IDs // Aig_NtkReassignIds( p ); // fix the levels Aig_ManFanoutStop( pAig ); if ( p->pPars->fUpdateLevel ) Aig_ManStopReverseLevels( pAig ); /* Aig_ManForEachObj( p->pAig, pObj, i ) if ( Aig_ObjIsNode(pObj) && Aig_ObjRefs(pObj) == 0 ) { printf( "Unreferenced " ); Aig_ObjPrintVerbose( pObj, 0 ); printf( "\n" ); } */ // remove dangling nodes (they should not be here!) Aig_ManCleanup( pAig ); // stop the rewriting manager Dar_ManRefStop( p ); // Aig_ManCheckPhase( pAig ); if ( !Aig_ManCheck( pAig ) ) { printf( "Dar_ManRefactor: The network check has failed.\n" ); return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darResub.c000066400000000000000000000026621300674244400233250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darResub.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darResub.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/darScript.c000066400000000000000000000637711300674244400235210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [darScript.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [Rewriting scripts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: darScript.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" #include "proof/dch/dch.h" #include "aig/gia/gia.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs one iteration of AIG rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig ) { Aig_Man_t * pTemp; Dar_RwrPar_t Pars, * pPars = &Pars; Dar_ManDefaultRwrParams( pPars ); pAig = Aig_ManDupDfs( pAig ); Dar_ManRewrite( pAig, pPars ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); return pAig; } /**Function************************************************************* Synopsis [Reproduces script "rwsat".] Description [] SideEffects [This procedure does not tighten level during restructuring.] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ) //alias rwsat "st; rw -l; b -l; rw -l; rf -l" { Aig_Man_t * pTemp; abctime Time = pAig->Time2Quit; Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; Dar_ManDefaultRwrParams( pParsRwr ); Dar_ManDefaultRefParams( pParsRef ); pParsRwr->fUpdateLevel = 0; pParsRef->fUpdateLevel = 0; pParsRwr->fVerbose = fVerbose; pParsRef->fVerbose = fVerbose; //printf( "1" ); pAig = Aig_ManDupDfs( pAig ); if ( fVerbose ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); //printf( "2" ); // balance if ( fBalance ) { pAig->Time2Quit = Time; pAig = Dar_ManBalance( pTemp = pAig, 0 ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); if ( Time && Abc_Clock() > Time ) { if ( pAig ) Aig_ManStop( pAig ); return NULL; } } //Aig_ManDumpBlif( pAig, "inter.blif", NULL, NULL ); //printf( "3" ); // rewrite pAig->Time2Quit = Time; Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); if ( Time && Abc_Clock() > Time ) { if ( pAig ) Aig_ManStop( pAig ); return NULL; } //printf( "4" ); // refactor pAig->Time2Quit = Time; Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); if ( Time && Abc_Clock() > Time ) { if ( pAig ) Aig_ManStop( pAig ); return NULL; } //printf( "5" ); // balance if ( fBalance ) { pAig->Time2Quit = Time; pAig = Dar_ManBalance( pTemp = pAig, 0 ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); if ( Time && Abc_Clock() > Time ) { if ( pAig ) Aig_ManStop( pAig ); return NULL; } } //printf( "6" ); // rewrite pAig->Time2Quit = Time; Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); if ( Time && Abc_Clock() > Time ) { if ( pAig ) Aig_ManStop( pAig ); return NULL; } //printf( "7" ); return pAig; } /**Function************************************************************* Synopsis [Reproduces script "compress".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManCompress( 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 ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); /* // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } */ // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } pParsRwr->fUseZeros = 1; pParsRef->fUseZeros = 1; // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); return pAig; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManCompress2( 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 ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); /* // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } */ // rewrite // Dar_ManRewrite( pAig, pParsRwr ); pParsRwr->fUpdateLevel = 0; // disable level update Dar_ManRewrite( pAig, pParsRwr ); pParsRwr->fUpdateLevel = fUpdateLevel; // reenable level update if needed pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); // balance // if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); pParsRwr->fUseZeros = 1; pParsRef->fUseZeros = 1; // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "RefactorZ: " ), Aig_ManPrintStats( pAig ); // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } return pAig; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Dar_ManChoiceSynthesis( 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 * vAigs; vAigs = Vec_PtrAlloc( 3 ); pAig = Aig_ManDupDfs(pAig); Vec_PtrPush( vAigs, pAig ); pAig = Dar_ManCompress(pAig, fBalance, fUpdateLevel, fPower, fVerbose); Vec_PtrPush( vAigs, pAig ); //Aig_ManPrintStats( pAig ); pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose); Vec_PtrPush( vAigs, pAig ); //Aig_ManPrintStats( pAig ); pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 1 ); return vAigs; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ) { Aig_Man_t * pMan, * pTemp; Vec_Ptr_t * vAigs; int i; abctime clk; clk = Abc_Clock(); // vAigs = Dar_ManChoiceSynthesisExt(); vAigs = Dar_ManChoiceSynthesis( pAig, fBalance, fUpdateLevel, 0, fVerbose ); // swap the first and last network // this should lead to the primary choice being "better" because of synthesis // (it is also important when constructing choices) if ( !fConstruct ) { pMan = (Aig_Man_t *)Vec_PtrPop( vAigs ); Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); Vec_PtrWriteEntry( vAigs, 0, pMan ); } if ( fVerbose ) { ABC_PRT( "Synthesis time", Abc_Clock() - clk ); } clk = Abc_Clock(); if ( fConstruct ) pMan = Aig_ManChoiceConstructive( vAigs, fVerbose ); else pMan = Aig_ManChoicePartitioned( vAigs, 300, nConfMax, nLevelMax, fVerbose ); Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) Aig_ManStop( pTemp ); Vec_PtrFree( vAigs ); if ( fVerbose ) { ABC_PRT( "Choicing time ", Abc_Clock() - clk ); } return pMan; // return NULL; } /**Function************************************************************* Synopsis [Reproduces script "compress".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_NewCompress( 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 ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } pParsRwr->fUseZeros = 1; pParsRef->fUseZeros = 1; // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); return pAig; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_NewCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fLightSynth, 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 ) printf( "Starting: " ), Aig_ManPrintStats( pAig ); // skip if lighter synthesis is requested if ( !fLightSynth ) { // rewrite //Dar_ManRewrite( pAig, pParsRwr ); // pParsRwr->fUpdateLevel = 0; // disable level update // this change was requested in July and later disabled Dar_ManRewrite( pAig, pParsRwr ); // pParsRwr->fUpdateLevel = fUpdateLevel; // reenable level update if needed pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Refactor: " ), Aig_ManPrintStats( pAig ); } // balance pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); // skip if lighter synthesis is requested if ( !fLightSynth ) { // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Rewrite: " ), Aig_ManPrintStats( pAig ); } pParsRwr->fUseZeros = 1; pParsRef->fUseZeros = 1; // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); // skip if lighter synthesis is requested if ( !fLightSynth ) { // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } } // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "RefactorZ: " ), Aig_ManPrintStats( pAig ); // skip if lighter synthesis is requested if ( !fLightSynth ) { // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "RewriteZ: " ), Aig_ManPrintStats( pAig ); } // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) printf( "Balance: " ), Aig_ManPrintStats( pAig ); } return pAig; } /**Function************************************************************* Synopsis [Count the number of nodes with very high fanout count.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dar_NewChoiceSynthesisGuard( Aig_Man_t * pAig ) { Aig_Obj_t * pObj; int i, Count = 0; Aig_ManForEachNode( pAig, pObj, i ) if ( Aig_ObjRefs(pObj) > 1000 ) Count += Aig_ObjRefs(pObj) / 1000; return (int)(Count > 10); } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [Takes AIG manager, consumes it, and produces GIA manager.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Dar_NewChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fLightSynth, 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, * pTemp; int i; if ( fUpdateLevel && Dar_NewChoiceSynthesisGuard(pAig) ) { if ( fVerbose ) printf( "Warning: Due to high fanout count of some nodes, level updating is disabled.\n" ); fUpdateLevel = 0; } vGias = Vec_PtrAlloc( 3 ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); pAig = Dar_NewCompress( pAig, fBalance, fUpdateLevel, fPower, fVerbose ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); //Aig_ManPrintStats( pAig ); pAig = Dar_NewCompress2( pAig, fBalance, fUpdateLevel, 1, fPower, fLightSynth, fVerbose ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); //Aig_ManPrintStats( pAig ); Aig_ManStop( pAig ); // swap around the first and the last pTemp = (Gia_Man_t *)Vec_PtrPop( vGias ); Vec_PtrPush( vGias, Vec_PtrEntry(vGias,0) ); Vec_PtrWriteEntry( vGias, 0, pTemp ); // Aig_Man_t * pAig; // int i; // printf( "Choicing will be performed with %d AIGs:\n", Vec_PtrSize(p->vAigs) ); // Vec_PtrForEachEntry( Aig_Man_t *, p->vAigs, pAig, i ) // Aig_ManPrintStats( pAig ); // derive the miter pGia = Gia_ManChoiceMiter( vGias ); // cleanup Vec_PtrForEachEntry( Gia_Man_t *, vGias, pTemp, i ) Gia_ManStop( pTemp ); Vec_PtrFree( vGias ); return pGia; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { extern Aig_Man_t * Dch_ComputeChoices( Vec_Ptr_t * vAigs, Dch_Pars_t * pPars ); extern Aig_Man_t * Cec_ComputeChoices( Vec_Ptr_t * vAigs, Dch_Pars_t * pPars ); int fVerbose = pPars->fVerbose; int fConstruct = 0; Aig_Man_t * pMan, * pTemp; Vec_Ptr_t * vAigs; int i; abctime clk; clk = Abc_Clock(); // vAigs = Dar_ManChoiceSynthesisExt(); // vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose ); vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, 0 ); // swap the first and last network // this should lead to the primary choice being "better" because of synthesis // (it is also important when constructing choices) if ( !fConstruct ) { pMan = Vec_PtrPop( vAigs ); Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); Vec_PtrWriteEntry( vAigs, 0, pMan ); } if ( fVerbose ) { //ABC_PRT( "Synthesis time", Abc_Clock() - clk ); } pPars->timeSynth = Abc_Clock() - clk; clk = Abc_Clock(); // perform choice computation if ( pPars->fUseGia ) pMan = Cec_ComputeChoices( vAigs, pPars ); else pMan = Dch_ComputeChoices( vAigs, pPars ); // reconstruct the network pMan = Aig_ManDupDfsGuided( pTemp = pMan, Vec_PtrEntry(vAigs,0) ); Aig_ManStop( pTemp ); // duplicate the timing manager pTemp = Vec_PtrEntry( vAigs, 0 ); if ( pTemp->pManTime ) { extern void * Tim_ManDup( void * p, int fDiscrete ); pMan->pManTime = Tim_ManDup( pTemp->pManTime, 0 ); } // reset levels Aig_ManChoiceLevel( pMan ); ABC_FREE( pMan->pName ); ABC_FREE( pMan->pSpec ); pMan->pName = Abc_UtilStrsav( pTemp->pName ); pMan->pSpec = Abc_UtilStrsav( pTemp->pSpec ); // cleanup Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) Aig_ManStop( pTemp ); Vec_PtrFree( vAigs ); if ( fVerbose ) { //ABC_PRT( "Choicing time ", Abc_Clock() - clk ); } return pMan; // return NULL; } */ /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [Consumes the input AIG to reduce memory usage.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManChoiceNewAig( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { // extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); int fVerbose = pPars->fVerbose; Aig_Man_t * pMan, * pTemp; Vec_Ptr_t * vAigs; Vec_Ptr_t * vPios; void * pManTime; char * pName, * pSpec; int i; abctime clk; clk = Abc_Clock(); vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose ); pPars->timeSynth = Abc_Clock() - clk; // swap the first and last network // this should lead to the primary choice being "better" because of synthesis // (it is also important when constructing choices) pMan = (Aig_Man_t *)Vec_PtrPop( vAigs ); Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); Vec_PtrWriteEntry( vAigs, 0, pMan ); // derive the total AIG pMan = Dch_DeriveTotalAig( vAigs ); // cleanup Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) Aig_ManStop( pTemp ); Vec_PtrFree( vAigs ); // compute choices pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); Aig_ManStop( pTemp ); // save useful things pManTime = pAig->pManTime; pAig->pManTime = NULL; pName = Abc_UtilStrsav( pAig->pName ); pSpec = Abc_UtilStrsav( pAig->pSpec ); // create guidence vPios = Aig_ManOrderPios( pMan, pAig ); Aig_ManStop( pAig ); // reconstruct the network pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); Aig_ManStop( pTemp ); Vec_PtrFree( vPios ); // reset levels pMan->pManTime = pManTime; Aig_ManChoiceLevel( pMan ); // copy names ABC_FREE( pMan->pName ); ABC_FREE( pMan->pSpec ); pMan->pName = pName; pMan->pSpec = pSpec; return pMan; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [Consumes the input AIG to reduce memory usage.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { extern Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ); // extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); // int fVerbose = pPars->fVerbose; Aig_Man_t * pMan, * pTemp; Gia_Man_t * pGia; Vec_Ptr_t * vPios; void * pManTime; char * pName, * pSpec; abctime clk; // save useful things pManTime = pAig->pManTime; pAig->pManTime = NULL; pName = Abc_UtilStrsav( pAig->pName ); pSpec = Abc_UtilStrsav( pAig->pSpec ); // perform synthesis clk = Abc_Clock(); pGia = Dar_NewChoiceSynthesis( Aig_ManDupDfs(pAig), 1, 1, pPars->fPower, pPars->fLightSynth, pPars->fVerbose ); pPars->timeSynth = Abc_Clock() - clk; // perform choice computation if ( pPars->fUseGia ) pMan = Cec_ComputeChoices( pGia, pPars ); else { pMan = Gia_ManToAigSkip( pGia, 3 ); Gia_ManStop( pGia ); pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); Aig_ManStop( pTemp ); } // create guidence vPios = Aig_ManOrderPios( pMan, pAig ); Aig_ManStop( pAig ); // reconstruct the network pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); Aig_ManStop( pTemp ); Vec_PtrFree( vPios ); // reset levels pMan->pManTime = pManTime; Aig_ManChoiceLevel( pMan ); // copy names ABC_FREE( pMan->pName ); ABC_FREE( pMan->pSpec ); pMan->pName = pName; pMan->pSpec = pSpec; return pMan; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/dar_.c000066400000000000000000000026521300674244400224620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dar_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "darInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dar/module.make000066400000000000000000000003511300674244400235270ustar00rootroot00000000000000SRC += src/opt/dar/darBalance.c \ src/opt/dar/darCore.c \ src/opt/dar/darCut.c \ src/opt/dar/darData.c \ src/opt/dar/darLib.c \ src/opt/dar/darMan.c \ src/opt/dar/darPrec.c \ src/opt/dar/darRefact.c \ src/opt/dar/darScript.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/000077500000000000000000000000001300674244400214075ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dau.c000066400000000000000000000026451300674244400223330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dau.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dau.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dau.h000066400000000000000000000133701300674244400223350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dau.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dau.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__DAU___h #define ABC__DAU___h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "misc/vec/vec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define DAU_MAX_VAR 12 // should be 6 or more #define DAU_MAX_STR 2000 #define DAU_MAX_WORD (1<<(DAU_MAX_VAR-6)) //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // network types typedef enum { DAU_DSD_NONE = 0, // 0: unknown DAU_DSD_CONST0, // 1: constant DAU_DSD_VAR, // 2: variable DAU_DSD_AND, // 3: AND DAU_DSD_XOR, // 4: XOR DAU_DSD_MUX, // 5: MUX DAU_DSD_PRIME // 6: PRIME } Dau_DsdType_t; typedef struct Dss_Man_t_ Dss_Man_t; typedef struct Abc_TtMan_t_ Abc_TtMan_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Dau_DsdIsConst( char * p ) { return (p[0] == '0' || p[0] == '1') && p[1] == 0; } static inline int Dau_DsdIsConst0( char * p ) { return p[0] == '0' && p[1] == 0; } static inline int Dau_DsdIsConst1( char * p ) { return p[0] == '1' && p[1] == 0; } static inline int Dau_DsdIsVar( char * p ) { if ( *p == '!' ) p++; return *p >= 'a' && *p <= 'z'; } static inline int Dau_DsdReadVar( char * p ) { if ( *p == '!' ) p++; return *p - 'a'; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== dauCanon.c ==========================================================*/ extern unsigned Abc_TtCanonicize( word * pTruth, int nVars, char * pCanonPerm ); extern unsigned Abc_TtCanonicizePhase( word * pTruth, int nVars ); /*=== dauDsd.c ==========================================================*/ extern int * Dau_DsdComputeMatches( char * p ); extern int Dau_DsdDecompose( word * pTruth, int nVarsInit, int fSplitPrime, int fWriteTruth, char * pRes ); extern int Dau_DsdDecomposeLevel( word * pTruth, int nVarsInit, int fSplitPrime, int fWriteTruth, char * pRes, int * pVarLevels ); extern void Dau_DsdPrintFromTruthFile( FILE * pFile, word * pTruth, int nVarsInit ); extern void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit ); extern word * Dau_DsdToTruth( char * p, int nVars ); extern word Dau_Dsd6ToTruth( char * p ); extern void Dau_DsdNormalize( char * p ); extern int Dau_DsdCountAnds( char * pDsd ); extern void Dau_DsdTruthCompose_rec( word * pFunc, word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], word * pRes, int nVars, int nWordsR ); extern int Dau_DsdCheck1Step( void * p, word * pTruth, int nVarsInit, int * pVarLevels ); /*=== dauGia.c ==========================================================*/ extern int Dsm_ManTruthToGia( void * p, word * pTruth, Vec_Int_t * vLeaves, Vec_Int_t * vCover ); extern void * Dsm_ManDeriveGia( void * p, int fUseMuxes ); /*=== dauMerge.c ==========================================================*/ extern void Dau_DsdRemoveBraces( char * pDsd, int * pMatches ); extern char * Dau_DsdMerge( char * pDsd0i, int * pPerm0, char * pDsd1i, int * pPerm1, int fCompl0, int fCompl1, int nVars ); /*=== dauNonDsd.c ==========================================================*/ extern Vec_Int_t * Dau_DecFindSets_int( word * pInit, int nVars, int * pSched[16] ); extern Vec_Int_t * Dau_DecFindSets( word * pInit, int nVars ); extern void Dau_DecSortSet( unsigned set, int nVars, int * pnUnique, int * pnShared, int * pnFree ); extern void Dau_DecPrintSets( Vec_Int_t * vSets, int nVars ); extern void Dau_DecPrintSet( unsigned set, int nVars, int fNewLine ); /*=== dauTree.c ==========================================================*/ extern Dss_Man_t * Dss_ManAlloc( int nVars, int nNonDecLimit ); extern void Dss_ManFree( Dss_Man_t * p ); extern int Dss_ManMerge( Dss_Man_t * p, int * iDsd, int * nFans, int ** pFans, unsigned uSharedMask, int nKLutSize, unsigned char * pPerm, word * pTruth ); extern void Dss_ManPrint( char * pFileName, Dss_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauArray.c000066400000000000000000000161271300674244400233320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauArray.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Array representation of DSD.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauArray.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Dau_Dsd_t_ Dau_Dsd_t; struct Dau_Dsd_t_ { unsigned iVar : 5; // variable unsigned nFans : 5; // fanin count unsigned Depth : 5; // tree depth unsigned Offset : 5; // the diff between this and other node unsigned Data : 5; // user data unsigned Type : 3; // node type unsigned fCompl : 1; // the complemented attribute unsigned fUnused : 1; // this vertice is unused }; static inline void Dau_DsdClean( Dau_Dsd_t * p ) { *((int *)p) = 0; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// int Dau_DsdCountAnd( Dau_Dsd_t * p ) { int Count, Costs[7] = {0, 0, 0, 1, 3, 3, 3}; for ( Count = 0; p->Type; p++ ) Count += Costs[p->Type]; return Count; } /* void Dau_DsdMark( Dau_Dsd_t * p, int nSize, int * pMarks ) { int pStore[DAU_MAX_VAR] = {0}; Dau_Dsd_t * q; if ( p->Type == DAU_DSD_CONST || p->Type == DAU_DSD_VAR ) return; for ( q = p + nSize - 1; q >= p; q-- ) { if ( q->Type == DAU_DSD_VAR ) pStore[q->Depth] += pMarks[q->iVar]; else { q->Data = pStore[q->Depth+1]; pStore[q->Depth+1] = 0; pStore[q->Depth] += (q->Data == q->nFans); } } } */ int Dau_DsdConstruct( char * pDsd, Dau_Dsd_t * pStore ) { Dau_Dsd_t * pLevel[DAU_MAX_VAR]; Dau_Dsd_t * q = pStore; int d = -1, fCompl = 0; if ( Dau_DsdIsConst(pDsd) ) { Dau_DsdClean( q ); q->Type = DAU_DSD_CONST0; q->fCompl = Dau_DsdIsConst1(pDsd); return 1; } for ( --q; *pDsd; pDsd++ ) { if ( *pDsd == '!' ) { fCompl ^= 1; continue; } if ( *pDsd == ')' || *pDsd == ']' || *pDsd == '>' || *pDsd == '}' ) { assert( fCompl == 0 ); if ( --d >= 0 ) { pLevel[d]->nFans++; if ( pLevel[d]->Data > pLevel[d+1]->Data ) pLevel[d]->Data = pLevel[d+1]->Data; } continue; } Dau_DsdClean( ++q ); q->Data = 31; q->fCompl = fCompl; fCompl = 0; if ( *pDsd >= 'a' && *pDsd <= 'z' ) { q->Type = DAU_DSD_VAR; q->iVar = *pDsd - 'a'; q->Depth = d + 1; if ( d >= 0 ) { pLevel[d]->nFans++; if ( pLevel[d]->Data > q->iVar ) pLevel[d]->Data = q->iVar; } continue; } if ( *pDsd == '(' ) q->Type = DAU_DSD_AND; else if ( *pDsd == '[' ) q->Type = DAU_DSD_XOR; else if ( *pDsd == '<' ) q->Type = DAU_DSD_MUX; else if ( *pDsd == '{' ) q->Type = DAU_DSD_PRIME; else assert( 0 ); pLevel[++d] = q; q->Depth = d; } assert( d == -1 ); Dau_DsdClean( ++q ); return q - pStore; } void Dau_DsdPrint( Dau_Dsd_t * p ) { char OpenType[7] = {0, 0, 0, '(', '[', '<', '{'}; char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'}; char pTypes[DAU_MAX_VAR]; int d, pVisits[DAU_MAX_VAR]; if ( p->Type == DAU_DSD_CONST0 ) { printf( "%d\n", p->fCompl ); return; } pVisits[0] = 1; for ( d = 0; p->Type; p++ ) { if ( p->fCompl ) printf( "!" ); if ( p->Type == DAU_DSD_VAR ) { printf( "%c", 'a' + p->iVar ); while ( d > 0 && --pVisits[d] == 0 ) printf( "%c", pTypes[d--] ); } else { pVisits[++d] = p->nFans; printf( "%c", OpenType[p->Type] ); printf( "%c", 'a' + p->Data ); printf( "%d", p->Depth ); pTypes[d] = CloseType[p->Type]; } } assert( d == 0 ); printf( "\n" ); } void Dau_DsdDepth( Dau_Dsd_t * p ) { int d, pVisits[DAU_MAX_VAR]; if ( p->Type == DAU_DSD_CONST0 ) return; pVisits[0] = 1; for ( d = 0; p->Type; p++ ) { p->Depth = d; if ( p->Type == DAU_DSD_VAR ) while ( d > 0 && --pVisits[d] == 0 ) d--; else pVisits[++d] = p->nFans; } assert( d == 0 ); } void Dau_DsdRemoveUseless( Dau_Dsd_t * p ) { Dau_Dsd_t * q = p, * pLevel[DAU_MAX_VAR]; int d, fChange = 0, pVisits[DAU_MAX_VAR]; if ( p->Type == DAU_DSD_CONST0 ) return; pVisits[0] = 1; for ( d = 0; p->Type; p++ ) { p->Depth = d; if ( p->Type == DAU_DSD_VAR ) while ( d > 0 && --pVisits[d] == 0 ) d--; else { if ( d > 0 && (pLevel[d-1]->Type == DAU_DSD_XOR && p->Type == DAU_DSD_XOR || pLevel[d-1]->Type == DAU_DSD_AND && p->Type == DAU_DSD_AND && !p->fCompl) ) { pLevel[d-1]->nFans += p->nFans - 1; pVisits[d] += p->nFans - 1; p->fUnused = 1; fChange = 1; } else { pLevel[d++] = p; pVisits[d] = p->nFans; } } } assert( d == 0 ); // compact if ( fChange ) { for ( p = q; p->Type; p++ ) if ( !p->fUnused ) *q++ = *p; Dau_DsdClean( q ); } } void Dau_DsdTest22() { Dau_Dsd_t pStore[2 * DAU_MAX_VAR]; // char * pDsd = "[(ab)c(f!(he))]"; // char * pDsd = "[(abd)cf(f!{she})]"; char * pDsd = "[(abd)[cf](f(sg(he)))]"; // char * pDsd = "[(ab)[cf]]"; int i, nSize = Dau_DsdConstruct( pDsd, pStore ); // Dau_DsdDepth( pStore ); Dau_DsdPrint( pStore ); Dau_DsdRemoveUseless( pStore ); Dau_DsdPrint( pStore ); i = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauCanon.c000066400000000000000000001216371300674244400233150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauCanon.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Canonical form computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauCanon.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "misc/util/utilTruth.h" #include "misc/vec/vecMem.h" #include "bool/lucky/lucky.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static word s_CMasks6[5] = { ABC_CONST(0x1111111111111111), ABC_CONST(0x0303030303030303), ABC_CONST(0x000F000F000F000F), ABC_CONST(0x000000FF000000FF), ABC_CONST(0x000000000000FFFF) }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Compares Cof0 and Cof1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCompare1VarCofs( word * pTruth, int nWords, int iVar ) { if ( nWords == 1 ) { word Cof0 = pTruth[0] & s_Truths6Neg[iVar]; word Cof1 = (pTruth[0] >> (1 << iVar)) & s_Truths6Neg[iVar]; if ( Cof0 != Cof1 ) return Cof0 < Cof1 ? -1 : 1; return 0; } if ( iVar <= 5 ) { word Cof0, Cof1; int w, shift = (1 << iVar); for ( w = 0; w < nWords; w++ ) { Cof0 = pTruth[w] & s_Truths6Neg[iVar]; Cof1 = (pTruth[w] >> shift) & s_Truths6Neg[iVar]; if ( Cof0 != Cof1 ) return Cof0 < Cof1 ? -1 : 1; } return 0; } // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); assert( nWords >= 2 ); for ( ; pTruth < pLimit; pTruth += 2*iStep ) for ( i = 0; i < iStep; i++ ) if ( pTruth[i] != pTruth[i + iStep] ) return pTruth[i] < pTruth[i + iStep] ? -1 : 1; return 0; } } static inline int Abc_TtCompare1VarCofsRev( word * pTruth, int nWords, int iVar ) { if ( nWords == 1 ) { word Cof0 = pTruth[0] & s_Truths6Neg[iVar]; word Cof1 = (pTruth[0] >> (1 << iVar)) & s_Truths6Neg[iVar]; if ( Cof0 != Cof1 ) return Cof0 < Cof1 ? -1 : 1; return 0; } if ( iVar <= 5 ) { word Cof0, Cof1; int w, shift = (1 << iVar); for ( w = nWords - 1; w >= 0; w-- ) { Cof0 = pTruth[w] & s_Truths6Neg[iVar]; Cof1 = (pTruth[w] >> shift) & s_Truths6Neg[iVar]; if ( Cof0 != Cof1 ) return Cof0 < Cof1 ? -1 : 1; } return 0; } // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); assert( nWords >= 2 ); for ( pLimit -= 2*iStep; pLimit >= pTruth; pLimit -= 2*iStep ) for ( i = iStep - 1; i >= 0; i-- ) if ( pLimit[i] != pLimit[i + iStep] ) return pLimit[i] < pLimit[i + iStep] ? -1 : 1; return 0; } } /**Function************************************************************* Synopsis [Checks equality of pairs of cofactors w.r.t. adjacent variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCheckEqual2VarCofs( word * pTruth, int nWords, int iVar, int Num1, int Num2 ) { assert( Num1 < Num2 && Num2 < 4 ); if ( nWords == 1 ) return ((pTruth[0] >> (Num2 * (1 << iVar))) & s_CMasks6[iVar]) == ((pTruth[0] >> (Num1 * (1 << iVar))) & s_CMasks6[iVar]); if ( iVar <= 4 ) { int w, shift = (1 << iVar); for ( w = 0; w < nWords; w++ ) if ( ((pTruth[w] >> Num2 * shift) & s_CMasks6[iVar]) != ((pTruth[w] >> Num1 * shift) & s_CMasks6[iVar]) ) return 0; return 1; } if ( iVar == 5 ) { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); assert( nWords >= 2 ); for ( ; pTruthU < pLimitU; pTruthU += 4 ) if ( pTruthU[Num2] != pTruthU[Num1] ) return 0; return 1; } // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); assert( nWords >= 4 ); for ( ; pTruth < pLimit; pTruth += 4*iStep ) for ( i = 0; i < iStep; i++ ) if ( pTruth[i+Num2*iStep] != pTruth[i+Num1*iStep] ) return 0; return 1; } } /**Function************************************************************* Synopsis [Compares pairs of cofactors w.r.t. adjacent variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCompare2VarCofs( word * pTruth, int nWords, int iVar, int Num1, int Num2 ) { assert( Num1 < Num2 && Num2 < 4 ); if ( nWords == 1 ) { word Cof1 = (pTruth[0] >> (Num1 * (1 << iVar))) & s_CMasks6[iVar]; word Cof2 = (pTruth[0] >> (Num2 * (1 << iVar))) & s_CMasks6[iVar]; if ( Cof1 != Cof2 ) return Cof1 < Cof2 ? -1 : 1; return 0; } if ( iVar <= 4 ) { word Cof1, Cof2; int w, shift = (1 << iVar); for ( w = 0; w < nWords; w++ ) { Cof1 = (pTruth[w] >> Num1 * shift) & s_CMasks6[iVar]; Cof2 = (pTruth[w] >> Num2 * shift) & s_CMasks6[iVar]; if ( Cof1 != Cof2 ) return Cof1 < Cof2 ? -1 : 1; } return 0; } if ( iVar == 5 ) { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); assert( nWords >= 2 ); for ( ; pTruthU < pLimitU; pTruthU += 4 ) if ( pTruthU[Num1] != pTruthU[Num2] ) return pTruthU[Num1] < pTruthU[Num2] ? -1 : 1; return 0; } // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); int Offset1 = Num1*iStep; int Offset2 = Num2*iStep; assert( nWords >= 4 ); for ( ; pTruth < pLimit; pTruth += 4*iStep ) for ( i = 0; i < iStep; i++ ) if ( pTruth[i + Offset1] != pTruth[i + Offset2] ) return pTruth[i + Offset1] < pTruth[i + Offset2] ? -1 : 1; return 0; } } static inline int Abc_TtCompare2VarCofsRev( word * pTruth, int nWords, int iVar, int Num1, int Num2 ) { assert( Num1 < Num2 && Num2 < 4 ); if ( nWords == 1 ) { word Cof1 = (pTruth[0] >> (Num1 * (1 << iVar))) & s_CMasks6[iVar]; word Cof2 = (pTruth[0] >> (Num2 * (1 << iVar))) & s_CMasks6[iVar]; if ( Cof1 != Cof2 ) return Cof1 < Cof2 ? -1 : 1; return 0; } if ( iVar <= 4 ) { word Cof1, Cof2; int w, shift = (1 << iVar); for ( w = nWords - 1; w >= 0; w-- ) { Cof1 = (pTruth[w] >> Num1 * shift) & s_CMasks6[iVar]; Cof2 = (pTruth[w] >> Num2 * shift) & s_CMasks6[iVar]; if ( Cof1 != Cof2 ) return Cof1 < Cof2 ? -1 : 1; } return 0; } if ( iVar == 5 ) { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); assert( nWords >= 2 ); for ( pLimitU -= 4; pLimitU >= pTruthU; pLimitU -= 4 ) if ( pLimitU[Num1] != pLimitU[Num2] ) return pLimitU[Num1] < pLimitU[Num2] ? -1 : 1; return 0; } // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); int Offset1 = Num1*iStep; int Offset2 = Num2*iStep; assert( nWords >= 4 ); for ( pLimit -= 4*iStep; pLimit >= pTruth; pLimit -= 4*iStep ) for ( i = iStep - 1; i >= 0; i-- ) if ( pLimit[i + Offset1] != pLimit[i + Offset2] ) return pLimit[i + Offset1] < pLimit[i + Offset2] ? -1 : 1; return 0; } } /**Function************************************************************* Synopsis [Minterm counting in all cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCountOnesInTruth( word * pTruth, int nVars ) { int nWords = Abc_TtWordNum( nVars ); int k, Counter = 0; for ( k = 0; k < nWords; k++ ) if ( pTruth[k] ) Counter += Abc_TtCountOnes( pTruth[k] ); return Counter; } static inline void Abc_TtCountOnesInCofs( word * pTruth, int nVars, int * pStore ) { word Temp; int i, k, Counter, nWords; if ( nVars <= 6 ) { for ( i = 0; i < nVars; i++ ) pStore[i] = Abc_TtCountOnes( pTruth[0] & s_Truths6Neg[i] ); return; } assert( nVars > 6 ); nWords = Abc_TtWordNum( nVars ); memset( pStore, 0, sizeof(int) * nVars ); for ( k = 0; k < nWords; k++ ) { // count 1's for the first six variables for ( i = 0; i < 6; i++ ) if ( (Temp = (pTruth[k] & s_Truths6Neg[i]) | ((pTruth[k+1] & s_Truths6Neg[i]) << (1 << i))) ) pStore[i] += Abc_TtCountOnes( Temp ); // count 1's for all other variables if ( pTruth[k] ) { Counter = Abc_TtCountOnes( pTruth[k] ); for ( i = 6; i < nVars; i++ ) if ( (k & (1 << (i-6))) == 0 ) pStore[i] += Counter; } k++; // count 1's for all other variables if ( pTruth[k] ) { Counter = Abc_TtCountOnes( pTruth[k] ); for ( i = 6; i < nVars; i++ ) if ( (k & (1 << (i-6))) == 0 ) pStore[i] += Counter; } } } /**Function************************************************************* Synopsis [Minterm counting in all cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_TtCountOnesInCofsSlow( word * pTruth, int nVars, int * pStore ) { static int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; int i, k, nBytes; unsigned char * pTruthC = (unsigned char *)pTruth; nBytes = 8 * Abc_TtWordNum( nVars ); memset( pStore, 0, sizeof(int) * nVars ); for ( k = 0; k < nBytes; k++ ) { pStore[0] += bit_count[ pTruthC[k] & 0x55 ]; pStore[1] += bit_count[ pTruthC[k] & 0x33 ]; pStore[2] += bit_count[ pTruthC[k] & 0x0F ]; for ( i = 3; i < nVars; i++ ) if ( (k & (1 << (i-3))) == 0 ) pStore[i] += bit_count[pTruthC[k]]; } } /**Function************************************************************* Synopsis [Minterm counting in all cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_TtCountOnesInCofsFast6_rec( word Truth, int iVar, int nBytes, int * pStore ) { static int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; int nMints0, nMints1; if ( Truth == 0 ) return 0; if ( ~Truth == 0 ) { int i; for ( i = 0; i <= iVar; i++ ) pStore[i] += nBytes * 4; return nBytes * 8; } if ( nBytes == 1 ) { assert( iVar == 2 ); pStore[0] += bit_count[ Truth & 0x55 ]; pStore[1] += bit_count[ Truth & 0x33 ]; pStore[2] += bit_count[ Truth & 0x0F ]; return bit_count[ Truth & 0xFF ]; } nMints0 = Abc_TtCountOnesInCofsFast6_rec( Abc_Tt6Cofactor0(Truth, iVar), iVar - 1, nBytes/2, pStore ); nMints1 = Abc_TtCountOnesInCofsFast6_rec( Abc_Tt6Cofactor1(Truth, iVar), iVar - 1, nBytes/2, pStore ); pStore[iVar] += nMints0; return nMints0 + nMints1; } int Abc_TtCountOnesInCofsFast_rec( word * pTruth, int iVar, int nWords, int * pStore ) { int nMints0, nMints1; if ( nWords == 1 ) { assert( iVar == 5 ); return Abc_TtCountOnesInCofsFast6_rec( pTruth[0], iVar, 8, pStore ); } assert( nWords > 1 ); assert( iVar > 5 ); if ( pTruth[0] & 1 ) { if ( Abc_TtIsConst1( pTruth, nWords ) ) { int i; for ( i = 0; i <= iVar; i++ ) pStore[i] += nWords * 32; return nWords * 64; } } else { if ( Abc_TtIsConst0( pTruth, nWords ) ) return 0; } nMints0 = Abc_TtCountOnesInCofsFast_rec( pTruth, iVar - 1, nWords/2, pStore ); nMints1 = Abc_TtCountOnesInCofsFast_rec( pTruth + nWords/2, iVar - 1, nWords/2, pStore ); pStore[iVar] += nMints0; return nMints0 + nMints1; } int Abc_TtCountOnesInCofsFast( word * pTruth, int nVars, int * pStore ) { memset( pStore, 0, sizeof(int) * nVars ); assert( nVars >= 3 ); if ( nVars <= 6 ) return Abc_TtCountOnesInCofsFast6_rec( pTruth[0], nVars - 1, Abc_TtByteNum( nVars ), pStore ); else return Abc_TtCountOnesInCofsFast_rec( pTruth, nVars - 1, Abc_TtWordNum( nVars ), pStore ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Abc_TtSemiCanonicize( word * pTruth, int nVars, char * pCanonPerm, int * pStoreOut ) { int fOldSwap = 0; int pStoreIn[17]; int * pStore = pStoreOut ? pStoreOut : pStoreIn; int i, nOnes, nWords = Abc_TtWordNum( nVars ); unsigned uCanonPhase = 0; assert( nVars <= 16 ); for ( i = 0; i < nVars; i++ ) pCanonPerm[i] = i; // normalize polarity nOnes = Abc_TtCountOnesInTruth( pTruth, nVars ); if ( nOnes > nWords * 32 ) { Abc_TtNot( pTruth, nWords ); nOnes = nWords*64 - nOnes; uCanonPhase |= (1 << nVars); } // normalize phase Abc_TtCountOnesInCofs( pTruth, nVars, pStore ); pStore[nVars] = nOnes; for ( i = 0; i < nVars; i++ ) { if ( pStore[i] >= nOnes - pStore[i] ) continue; Abc_TtFlip( pTruth, nWords, i ); uCanonPhase |= (1 << i); pStore[i] = nOnes - pStore[i]; } // normalize permutation if ( fOldSwap ) { int fChange; do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { if ( pStore[i] <= pStore[i+1] ) // if ( pStore[i] >= pStore[i+1] ) continue; ABC_SWAP( int, pCanonPerm[i], pCanonPerm[i+1] ); ABC_SWAP( int, pStore[i], pStore[i+1] ); if ( ((uCanonPhase >> i) & 1) != ((uCanonPhase >> (i+1)) & 1) ) { uCanonPhase ^= (1 << i); uCanonPhase ^= (1 << (i+1)); } Abc_TtSwapAdjacent( pTruth, nWords, i ); fChange = 1; // nSwaps++; } } while ( fChange ); } else { int k, BestK; for ( i = 0; i < nVars - 1; i++ ) { BestK = i + 1; for ( k = i + 2; k < nVars; k++ ) if ( pStore[BestK] > pStore[k] ) // if ( pStore[BestK] < pStore[k] ) BestK = k; if ( pStore[i] <= pStore[BestK] ) // if ( pStore[i] >= pStore[BestK] ) continue; ABC_SWAP( int, pCanonPerm[i], pCanonPerm[BestK] ); ABC_SWAP( int, pStore[i], pStore[BestK] ); if ( ((uCanonPhase >> i) & 1) != ((uCanonPhase >> BestK) & 1) ) { uCanonPhase ^= (1 << i); uCanonPhase ^= (1 << BestK); } Abc_TtSwapVars( pTruth, nVars, i, BestK ); // nSwaps++; } } return uCanonPhase; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_TtCofactorTest10( word * pTruth, int nVars, int N ) { static word pCopy1[1024]; static word pCopy2[1024]; int nWords = Abc_TtWordNum( nVars ); int i; for ( i = 0; i < nVars - 1; i++ ) { // Kit_DsdPrintFromTruth( pTruth, nVars ); printf( "\n" ); Abc_TtCopy( pCopy1, pTruth, nWords, 0 ); Abc_TtSwapAdjacent( pCopy1, nWords, i ); // Kit_DsdPrintFromTruth( pCopy1, nVars ); printf( "\n" ); Abc_TtCopy( pCopy2, pTruth, nWords, 0 ); Abc_TtSwapVars( pCopy2, nVars, i, i+1 ); // Kit_DsdPrintFromTruth( pCopy2, nVars ); printf( "\n" ); assert( Abc_TtEqual( pCopy1, pCopy2, nWords ) ); } } /**Function************************************************************* Synopsis [Naive evaluation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_Tt6CofactorPermNaive( word * pTruth, int i, int fSwapOnly ) { if ( fSwapOnly ) { word Copy = Abc_Tt6SwapAdjacent( pTruth[0], i ); if ( pTruth[0] > Copy ) { pTruth[0] = Copy; return 4; } return 0; } { word Copy = pTruth[0]; word Best = pTruth[0]; int Config = 0; // PXY // 001 Copy = Abc_Tt6Flip( Copy, i ); if ( Best > Copy ) Best = Copy, Config = 1; // PXY // 011 Copy = Abc_Tt6Flip( Copy, i+1 ); if ( Best > Copy ) Best = Copy, Config = 3; // PXY // 010 Copy = Abc_Tt6Flip( Copy, i ); if ( Best > Copy ) Best = Copy, Config = 2; // PXY // 110 Copy = Abc_Tt6SwapAdjacent( Copy, i ); if ( Best > Copy ) Best = Copy, Config = 6; // PXY // 111 Copy = Abc_Tt6Flip( Copy, i+1 ); if ( Best > Copy ) Best = Copy, Config = 7; // PXY // 101 Copy = Abc_Tt6Flip( Copy, i ); if ( Best > Copy ) Best = Copy, Config = 5; // PXY // 100 Copy = Abc_Tt6Flip( Copy, i+1 ); if ( Best > Copy ) Best = Copy, Config = 4; // PXY // 000 Copy = Abc_Tt6SwapAdjacent( Copy, i ); assert( Copy == pTruth[0] ); assert( Best <= pTruth[0] ); pTruth[0] = Best; return Config; } } int Abc_TtCofactorPermNaive( word * pTruth, int i, int nWords, int fSwapOnly ) { if ( fSwapOnly ) { static word pCopy[1024]; Abc_TtCopy( pCopy, pTruth, nWords, 0 ); Abc_TtSwapAdjacent( pCopy, nWords, i ); if ( Abc_TtCompareRev(pTruth, pCopy, nWords) == 1 ) { Abc_TtCopy( pTruth, pCopy, nWords, 0 ); return 4; } return 0; } { static word pCopy[1024]; static word pBest[1024]; int Config = 0; // save two copies Abc_TtCopy( pCopy, pTruth, nWords, 0 ); Abc_TtCopy( pBest, pTruth, nWords, 0 ); // PXY // 001 Abc_TtFlip( pCopy, nWords, i ); if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 ) Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 1; // PXY // 011 Abc_TtFlip( pCopy, nWords, i+1 ); if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 ) Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 3; // PXY // 010 Abc_TtFlip( pCopy, nWords, i ); if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 ) Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 2; // PXY // 110 Abc_TtSwapAdjacent( pCopy, nWords, i ); if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 ) Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 6; // PXY // 111 Abc_TtFlip( pCopy, nWords, i+1 ); if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 ) Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 7; // PXY // 101 Abc_TtFlip( pCopy, nWords, i ); if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 ) Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 5; // PXY // 100 Abc_TtFlip( pCopy, nWords, i+1 ); if ( Abc_TtCompareRev(pBest, pCopy, nWords) == 1 ) Abc_TtCopy( pBest, pCopy, nWords, 0 ), Config = 4; // PXY // 000 Abc_TtSwapAdjacent( pCopy, nWords, i ); assert( Abc_TtEqual( pTruth, pCopy, nWords ) ); if ( Config == 0 ) return 0; assert( Abc_TtCompareRev(pTruth, pBest, nWords) == 1 ); Abc_TtCopy( pTruth, pBest, nWords, 0 ); return Config; } } /**Function************************************************************* Synopsis [Smart evaluation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_TtCofactorPermConfig( word * pTruth, int i, int nWords, int fSwapOnly, int fNaive ) { if ( nWords == 1 ) return Abc_Tt6CofactorPermNaive( pTruth, i, fSwapOnly ); if ( fNaive ) return Abc_TtCofactorPermNaive( pTruth, i, nWords, fSwapOnly ); if ( fSwapOnly ) { if ( Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 2 ) < 0 ) // Cof1 < Cof2 { Abc_TtSwapAdjacent( pTruth, nWords, i ); return 4; } return 0; } { int fComp01, fComp02, fComp03, fComp12, fComp13, fComp23, Config = 0; fComp01 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 0, 1 ); fComp23 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 2, 3 ); if ( fComp23 >= 0 ) // Cof2 >= Cof3 { if ( fComp01 >= 0 ) // Cof0 >= Cof1 { fComp13 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 3 ); if ( fComp13 < 0 ) // Cof1 < Cof3 Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 2; else if ( fComp13 == 0 ) // Cof1 == Cof3 { fComp02 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 0, 2 ); if ( fComp02 < 0 ) Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 2; } // else Cof1 > Cof3 -- do nothing } else // Cof0 < Cof1 { fComp03 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 0, 3 ); if ( fComp03 < 0 ) // Cof0 < Cof3 { Abc_TtFlip( pTruth, nWords, i ); Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 3; } else // Cof0 >= Cof3 { if ( fComp23 == 0 ) // can flip Cof0 and Cof1 Abc_TtFlip( pTruth, nWords, i ), Config = 1; } } } else // Cof2 < Cof3 { if ( fComp01 >= 0 ) // Cof0 >= Cof1 { fComp12 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 2 ); if ( fComp12 > 0 ) // Cof1 > Cof2 Abc_TtFlip( pTruth, nWords, i ), Config = 1; else if ( fComp12 == 0 ) // Cof1 == Cof2 { Abc_TtFlip( pTruth, nWords, i ); Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 3; } else // Cof1 < Cof2 { Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 2; if ( fComp01 == 0 ) Abc_TtFlip( pTruth, nWords, i ), Config ^= 1; } } else // Cof0 < Cof1 { fComp02 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 0, 2 ); if ( fComp02 == -1 ) // Cof0 < Cof2 { Abc_TtFlip( pTruth, nWords, i ); Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 3; } else if ( fComp02 == 0 ) // Cof0 == Cof2 { fComp13 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 3 ); if ( fComp13 >= 0 ) // Cof1 >= Cof3 Abc_TtFlip( pTruth, nWords, i ), Config = 1; else // Cof1 < Cof3 { Abc_TtFlip( pTruth, nWords, i ); Abc_TtFlip( pTruth, nWords, i + 1 ), Config = 3; } } else // Cof0 > Cof2 Abc_TtFlip( pTruth, nWords, i ), Config = 1; } } // perform final swap if needed fComp12 = Abc_TtCompare2VarCofsRev( pTruth, nWords, i, 1, 2 ); if ( fComp12 < 0 ) // Cof1 < Cof2 Abc_TtSwapAdjacent( pTruth, nWords, i ), Config ^= 4; return Config; } } int Abc_TtCofactorPerm( word * pTruth, int i, int nWords, int fSwapOnly, char * pCanonPerm, unsigned * puCanonPhase, int fNaive ) { if ( fSwapOnly ) { int Config = Abc_TtCofactorPermConfig( pTruth, i, nWords, 1, 0 ); if ( Config ) { if ( ((*puCanonPhase >> i) & 1) != ((*puCanonPhase >> (i+1)) & 1) ) { *puCanonPhase ^= (1 << i); *puCanonPhase ^= (1 << (i+1)); } ABC_SWAP( int, pCanonPerm[i], pCanonPerm[i+1] ); } return Config; } { static word pCopy1[1024]; int Config; Abc_TtCopy( pCopy1, pTruth, nWords, 0 ); Config = Abc_TtCofactorPermConfig( pTruth, i, nWords, 0, fNaive ); if ( Config == 0 ) return 0; if ( Abc_TtCompareRev(pTruth, pCopy1, nWords) == 1 ) // made it worse { Abc_TtCopy( pTruth, pCopy1, nWords, 0 ); return 0; } // improved if ( Config & 1 ) *puCanonPhase ^= (1 << i); if ( Config & 2 ) *puCanonPhase ^= (1 << (i+1)); if ( Config & 4 ) { if ( ((*puCanonPhase >> i) & 1) != ((*puCanonPhase >> (i+1)) & 1) ) { *puCanonPhase ^= (1 << i); *puCanonPhase ^= (1 << (i+1)); } ABC_SWAP( int, pCanonPerm[i], pCanonPerm[i+1] ); } return Config; } } /**Function************************************************************* Synopsis [Semi-canonical form computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //#define CANON_VERIFY unsigned Abc_TtCanonicize( word * pTruth, int nVars, char * pCanonPerm ) { int pStoreIn[17]; unsigned uCanonPhase; int i, k, nWords = Abc_TtWordNum( nVars ); int fNaive = 1; #ifdef CANON_VERIFY char pCanonPermCopy[16]; static word pCopy1[1024]; static word pCopy2[1024]; Abc_TtCopy( pCopy1, pTruth, nWords, 0 ); #endif uCanonPhase = Abc_TtSemiCanonicize( pTruth, nVars, pCanonPerm, pStoreIn ); for ( k = 0; k < 5; k++ ) { int fChanges = 0; for ( i = nVars - 2; i >= 0; i-- ) if ( pStoreIn[i] == pStoreIn[i+1] ) fChanges |= Abc_TtCofactorPerm( pTruth, i, nWords, pStoreIn[i] != pStoreIn[nVars]/2, pCanonPerm, &uCanonPhase, fNaive ); if ( !fChanges ) break; fChanges = 0; for ( i = 1; i < nVars - 1; i++ ) if ( pStoreIn[i] == pStoreIn[i+1] ) fChanges |= Abc_TtCofactorPerm( pTruth, i, nWords, pStoreIn[i] != pStoreIn[nVars]/2, pCanonPerm, &uCanonPhase, fNaive ); if ( !fChanges ) break; } #ifdef CANON_VERIFY Abc_TtCopy( pCopy2, pTruth, nWords, 0 ); memcpy( pCanonPermCopy, pCanonPerm, sizeof(char) * nVars ); Abc_TtImplementNpnConfig( pCopy2, nVars, pCanonPermCopy, uCanonPhase ); if ( !Abc_TtEqual( pCopy1, pCopy2, nWords ) ) printf( "Canonical form verification failed!\n" ); #endif /* if ( !Abc_TtEqual( pCopy1, pCopy2, nWords ) ) { Kit_DsdPrintFromTruth( pCopy1, nVars ); printf( "\n" ); Kit_DsdPrintFromTruth( pCopy2, nVars ); printf( "\n" ); i = 0; } */ return uCanonPhase; } /**Function************************************************************* Synopsis [Semi-canonical form computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_TtCanonicizePhaseVar6( word * pTruth, int nVars, int v ) { int w, nWords = Abc_TtWordNum( nVars ); int s, nStep = 1 << (v-6); assert( v >= 6 ); for ( w = nWords - 1, s = nWords - nStep; w > 0; w-- ) { if ( pTruth[w-nStep] == pTruth[w] ) { if ( w == s ) { w = s - nStep; s = w - nStep; } continue; } if ( pTruth[w-nStep] > pTruth[w] ) return -1; for ( ; w > 0; w-- ) { ABC_SWAP( word, pTruth[w-nStep], pTruth[w] ); if ( w == s ) { w = s - nStep; s = w - nStep; } } assert( w == -1 ); return 1; } return 0; } static inline int Abc_TtCanonicizePhaseVar5( word * pTruth, int nVars, int v ) { int w, nWords = Abc_TtWordNum( nVars ); int Shift = 1 << v; word Mask = s_Truths6[v]; assert( v < 6 ); for ( w = nWords - 1; w >= 0; w-- ) { if ( ((pTruth[w] << Shift) & Mask) == (pTruth[w] & Mask) ) continue; if ( ((pTruth[w] << Shift) & Mask) > (pTruth[w] & Mask) ) return -1; // Extra_PrintHex( stdout, (unsigned *)pTruth, nVars ); printf("\n" ); for ( ; w >= 0; w-- ) pTruth[w] = ((pTruth[w] << Shift) & Mask) | ((pTruth[w] & Mask) >> Shift); // Extra_PrintHex( stdout, (unsigned *)pTruth, nVars ); printf( " changed %d", v ), printf("\n" ); return 1; } return 0; } unsigned Abc_TtCanonicizePhase( word * pTruth, int nVars ) { unsigned uCanonPhase = 0; int v, nWords = Abc_TtWordNum( nVars ); // static int Counter = 0; // Counter++; #ifdef CANON_VERIFY static word pCopy1[1024]; static word pCopy2[1024]; Abc_TtCopy( pCopy1, pTruth, nWords, 0 ); #endif if ( (pTruth[nWords-1] >> 63) & 1 ) { Abc_TtNot( pTruth, nWords ); uCanonPhase ^= (1 << nVars); } // while ( 1 ) // { // unsigned uCanonPhase2 = uCanonPhase; for ( v = nVars - 1; v >= 6; v-- ) if ( Abc_TtCanonicizePhaseVar6( pTruth, nVars, v ) == 1 ) uCanonPhase ^= 1 << v; for ( ; v >= 0; v-- ) if ( Abc_TtCanonicizePhaseVar5( pTruth, nVars, v ) == 1 ) uCanonPhase ^= 1 << v; // if ( uCanonPhase2 == uCanonPhase ) // break; // } // for ( v = 5; v >= 0; v-- ) // assert( Abc_TtCanonicizePhaseVar5( pTruth, nVars, v ) != 1 ); #ifdef CANON_VERIFY Abc_TtCopy( pCopy2, pTruth, nWords, 0 ); Abc_TtImplementNpnConfig( pCopy2, nVars, NULL, uCanonPhase ); if ( !Abc_TtEqual( pCopy1, pCopy2, nWords ) ) printf( "Canonical form verification failed!\n" ); #endif return uCanonPhase; } /**Function************************************************************* Synopsis [Hierarchical semi-canonical form computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define TT_NUM_TABLES 5 struct Abc_TtMan_t_ { Vec_Mem_t * vTtMem[TT_NUM_TABLES]; // truth table memory and hash tables Vec_Int_t ** vRepres; // pointers to the representatives from the last hierarchical level }; Vec_Int_t ** Abc_TtRepresStart() { Vec_Int_t ** vRepres = ABC_ALLOC(Vec_Int_t *, TT_NUM_TABLES - 1); int i; // create a list of pointers for each level of the hierarchy for (i = 0; i < (TT_NUM_TABLES - 1); i++) { vRepres[i] = Vec_IntAlloc(1); } return vRepres; } void Abc_TtRepresStop(Vec_Int_t ** vRepres) { int i; for (i = 0; i < (TT_NUM_TABLES - 1); i++) { Vec_IntFree(vRepres[i]); } ABC_FREE( vRepres ); } Abc_TtMan_t * Abc_TtManStart( int nVars ) { Abc_TtMan_t * p = ABC_CALLOC( Abc_TtMan_t, 1 ); int i, nWords = Abc_TtWordNum( nVars ); for ( i = 0; i < TT_NUM_TABLES; i++ ) { p->vTtMem[i] = Vec_MemAlloc( nWords, 12 ); Vec_MemHashAlloc( p->vTtMem[i], 10000 ); } p->vRepres = Abc_TtRepresStart(); return p; } void Abc_TtManStop( Abc_TtMan_t * p ) { int i; for ( i = 0; i < TT_NUM_TABLES; i++ ) { Vec_MemHashFree( p->vTtMem[i] ); Vec_MemFreeP( &p->vTtMem[i] ); } Abc_TtRepresStop(p->vRepres); ABC_FREE( p ); } int Abc_TtManNumClasses( Abc_TtMan_t * p ) { return Vec_MemEntryNum( p->vTtMem[TT_NUM_TABLES-1] ); } unsigned Abc_TtCanonicizeHie( Abc_TtMan_t * p, word * pTruthInit, int nVars, char * pCanonPerm, int fExact ) { int fNaive = 1; int pStore[17]; static word pTruth[1024]; unsigned uCanonPhase = 0; int nOnes, nWords = Abc_TtWordNum( nVars ); int i, k, truthId; int * pSpot; int vTruthId[TT_NUM_TABLES-1]; int fLevelFound; word * pRepTruth; assert( nVars <= 16 ); Abc_TtCopy( pTruth, pTruthInit, nWords, 0 ); for ( i = 0; i < nVars; i++ ) pCanonPerm[i] = i; // normalize polarity nOnes = Abc_TtCountOnesInTruth( pTruth, nVars ); if ( nOnes > nWords * 32 ) { Abc_TtNot( pTruth, nWords ); nOnes = nWords*64 - nOnes; uCanonPhase |= (1 << nVars); } // check cache pSpot = Vec_MemHashLookup( p->vTtMem[0], pTruth ); if ( *pSpot != -1 ) { fLevelFound = 0; goto end_repres; } vTruthId[0] = Vec_MemHashInsert( p->vTtMem[0], pTruth ); // normalize phase Abc_TtCountOnesInCofs( pTruth, nVars, pStore ); pStore[nVars] = nOnes; for ( i = 0; i < nVars; i++ ) { if ( pStore[i] >= nOnes - pStore[i] ) continue; Abc_TtFlip( pTruth, nWords, i ); uCanonPhase |= (1 << i); pStore[i] = nOnes - pStore[i]; } // check cache pSpot = Vec_MemHashLookup( p->vTtMem[1], pTruth ); if ( *pSpot != -1 ) { fLevelFound = 1; goto end_repres; } vTruthId[1] = Vec_MemHashInsert( p->vTtMem[1], pTruth ); // normalize permutation { int k, BestK; for ( i = 0; i < nVars - 1; i++ ) { BestK = i + 1; for ( k = i + 2; k < nVars; k++ ) if ( pStore[BestK] > pStore[k] ) BestK = k; if ( pStore[i] <= pStore[BestK] ) continue; ABC_SWAP( int, pCanonPerm[i], pCanonPerm[BestK] ); ABC_SWAP( int, pStore[i], pStore[BestK] ); if ( ((uCanonPhase >> i) & 1) != ((uCanonPhase >> BestK) & 1) ) { uCanonPhase ^= (1 << i); uCanonPhase ^= (1 << BestK); } Abc_TtSwapVars( pTruth, nVars, i, BestK ); } } // check cache pSpot = Vec_MemHashLookup( p->vTtMem[2], pTruth ); if ( *pSpot != -1 ) { fLevelFound = 2; goto end_repres; } vTruthId[2] = Vec_MemHashInsert( p->vTtMem[2], pTruth ); // iterate TT permutations for tied variables for ( k = 0; k < 5; k++ ) { int fChanges = 0; for ( i = nVars - 2; i >= 0; i-- ) if ( pStore[i] == pStore[i+1] ) fChanges |= Abc_TtCofactorPerm( pTruth, i, nWords, pStore[i] != pStore[nVars]/2, pCanonPerm, &uCanonPhase, fNaive ); if ( !fChanges ) break; fChanges = 0; for ( i = 1; i < nVars - 1; i++ ) if ( pStore[i] == pStore[i+1] ) fChanges |= Abc_TtCofactorPerm( pTruth, i, nWords, pStore[i] != pStore[nVars]/2, pCanonPerm, &uCanonPhase, fNaive ); if ( !fChanges ) break; } // check cache pSpot = Vec_MemHashLookup( p->vTtMem[3], pTruth ); if ( *pSpot != -1 ) { fLevelFound = 3; goto end_repres; } vTruthId[3] = Vec_MemHashInsert( p->vTtMem[3], pTruth ); // perform exact NPN using groups if ( fExact ) { extern void simpleMinimalGroups(word* x, word* pAux, word* minimal, int* pGroups, int nGroups, permInfo** pis, int nVars, int fFlipOutput, int fFlipInput); word pAuxWord[1024], pAuxWord1[1024]; int pGroups[16]; int nGroups = 0; permInfo * pis[17]; // get groups pGroups[0] = 0; for (i = 0; i < nVars - 1; i++) { if (pStore[i] == pStore[i + 1]) { pGroups[nGroups]++; } else { pGroups[nGroups]++; nGroups++; pGroups[nGroups] = 0; } } pGroups[nGroups]++; nGroups++; // compute permInfo from 0 to nVars (incl.) for (i = 0; i <= nVars; i++) { pis[i] = setPermInfoPtr(i); } // do the exact matching if (nOnes == nWords * 32) /* balanced output */ simpleMinimalGroups(pTruth, pAuxWord, pAuxWord1, pGroups, nGroups, pis, nVars, 1, 1); else if (pStore[0] != pStore[1] && pStore[0] == (nOnes - pStore[0])) /* balanced singleton input */ simpleMinimalGroups(pTruth, pAuxWord, pAuxWord1, pGroups, nGroups, pis, nVars, 0, 1); else simpleMinimalGroups(pTruth, pAuxWord, pAuxWord1, pGroups, nGroups, pis, nVars, 0, 0); // cleanup for (i = 0; i <= nVars; i++) { freePermInfoPtr(pis[i]); } } // check cache pSpot = Vec_MemHashLookup( p->vTtMem[4], pTruth ); fLevelFound = 4; if ( *pSpot != -1 ) { goto end_repres; } *pSpot = Vec_MemHashInsert( p->vTtMem[4], pTruth ); end_repres: // return the class representative if(fLevelFound < (TT_NUM_TABLES - 1)) truthId = Vec_IntEntry(p->vRepres[fLevelFound], *pSpot); else truthId = *pSpot; for(i = 0; i < fLevelFound; i++) Vec_IntSetEntry(p->vRepres[i], vTruthId[i], truthId); pRepTruth = Vec_MemReadEntry(p->vTtMem[TT_NUM_TABLES-1], truthId); Abc_TtCopy( pTruthInit, pRepTruth, nWords, 0 ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauCore.c000066400000000000000000000053161300674244400231420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Disjoint-support decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // parameter structure typedef struct Xyz_ParTry_t_ Xyz_ParTry_t; struct Xyz_ParTry_t_ { int Par; }; // operation manager typedef struct Xyz_ManTry_t_ Xyz_ManTry_t; struct Xyz_ManTry_t_ { Xyz_ParTry_t * pPar; // parameters Aig_Man_t * pAig; // user's AIG }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Xyz_ManTry_t * Xyz_ManTryAlloc( Aig_Man_t * pAig, Xyz_ParTry_t * pPar ) { Xyz_ManTry_t * p; p = ABC_CALLOC( Xyz_ManTry_t, 1 ); p->pAig = pAig; p->pPar = pPar; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Xyz_ManTryFree( Xyz_ManTry_t * p ) { ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Xyz_ManPerform( Aig_Man_t * pAig, Xyz_ParTry_t * pPar ) { Xyz_ManTry_t * p; int RetValue; p = Xyz_ManTryAlloc( pAig, pPar ); RetValue = 1; Xyz_ManTryFree( p ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauDivs.c000066400000000000000000000062661300674244400231640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauDivs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Divisor computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauDivs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Dau_DsdDivisors( word * pTruth, int nVars ) { word Copy[DAU_MAX_WORD]; int nWords = Abc_TtWordNum(nVars); int nDigits = Abc_TtHexDigitNum(nVars); int i, j, k, Digit, Counter[5]; printf( " " ); printf( " !a *!b" ); printf( " !a * b" ); printf( " a *!b" ); printf( " a * b" ); printf( " a + b" ); printf( "\n" ); for ( i = 0; i < nVars; i++ ) for ( j = i+1; j < nVars; j++ ) { Abc_TtCopy( Copy, pTruth, nWords, 0 ); Abc_TtSwapVars( Copy, nVars, 0, i ); Abc_TtSwapVars( Copy, nVars, 1, j ); for ( k = 0; k < 5; k++ ) Counter[k] = 0; for ( k = 0; k < nDigits; k++ ) { Digit = Abc_TtGetHex( Copy, k ); if ( Digit == 1 || Digit == 14 ) Counter[0]++; else if ( Digit == 2 || Digit == 13 ) Counter[1]++; else if ( Digit == 4 || Digit == 11 ) Counter[2]++; else if ( Digit == 8 || Digit == 7 ) Counter[3]++; else if ( Digit == 6 || Digit == 9 ) Counter[4]++; } printf( "%c %c ", 'a'+i, 'a'+j ); for ( k = 0; k < 5; k++ ) printf( "%7d", Counter[k] ); printf( "\n" ); } return NULL; } void Dau_DsdTest000() { // char * pDsd = "!(!(abc)!(def))"; // char * pDsd = "[(abc)(def)]"; char * pDsd = "<d(ef)>"; word t = Dau_Dsd6ToTruth( pDsd ); // word t = 0xCA88CA88CA88CA88; // word t = 0x9ef7a8d9c7193a0f; int nVars = Abc_TtSupportSize( &t, 6 ); return; // word t = 0xCACACACACACACACA; Dau_DsdDivisors( &t, nVars ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauDsd.c000066400000000000000000002213011300674244400227560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Disjoint-support decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* This code performs truth-table-based decomposition for 6-variable functions. Representation of operations: ! = not; (ab) = a and b; [ab] = a xor b; = ITE( a, b, c ) FUNCTION{abc} = FUNCTION( a, b, c ) */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Elementary truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word ** Dau_DsdTtElems() { static word TtElems[DAU_MAX_VAR+1][DAU_MAX_WORD], * pTtElems[DAU_MAX_VAR+1] = {NULL}; if ( pTtElems[0] == NULL ) { int v; for ( v = 0; v <= DAU_MAX_VAR; v++ ) pTtElems[v] = TtElems[v]; Abc_TtElemInit( pTtElems, DAU_MAX_VAR ); } return pTtElems; } /**Function************************************************************* Synopsis [DSD formula manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Dau_DsdComputeMatches( char * p ) { static int pMatches[DAU_MAX_STR]; int pNested[DAU_MAX_VAR]; int v, nNested = 0; for ( v = 0; p[v]; v++ ) { pMatches[v] = 0; if ( p[v] == '(' || p[v] == '[' || p[v] == '<' || p[v] == '{' ) pNested[nNested++] = v; else if ( p[v] == ')' || p[v] == ']' || p[v] == '>' || p[v] == '}' ) pMatches[pNested[--nNested]] = v; assert( nNested < DAU_MAX_VAR ); } assert( nNested == 0 ); return pMatches; } /**Function************************************************************* Synopsis [Generate random permutation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdFindVarNum( char * pDsd ) { int vMax = 0; pDsd--; while ( *++pDsd ) if ( *pDsd >= 'a' && *pDsd <= 'z' ) vMax = Abc_MaxInt( vMax, *pDsd - 'a' ); return vMax + 1; } void Dau_DsdGenRandPerm( int * pPerm, int nVars ) { int v, vNew; for ( v = 0; v < nVars; v++ ) pPerm[v] = v; for ( v = 0; v < nVars; v++ ) { vNew = rand() % nVars; ABC_SWAP( int, pPerm[v], pPerm[vNew] ); } } void Dau_DsdPermute( char * pDsd ) { int pPerm[16]; int nVars = Dau_DsdFindVarNum( pDsd ); Dau_DsdGenRandPerm( pPerm, nVars ); pDsd--; while ( *++pDsd ) if ( *pDsd >= 'a' && *pDsd < 'a' + nVars ) *pDsd = 'a' + pPerm[*pDsd - 'a']; } /**Function************************************************************* Synopsis [Normalize the ordering of components.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Dau_DsdNormalizeCopy( char * pDest, char * pSour, int * pMarks, int i ) { int s; for ( s = pMarks[i]; s < pMarks[i+1]; s++ ) *pDest++ = pSour[s]; return pDest; } int Dau_DsdNormalizeCompare( char * pStr, int * pMarks, int i, int j ) { char * pStr1 = pStr + pMarks[i]; char * pStr2 = pStr + pMarks[j]; char * pLimit1 = pStr + pMarks[i+1]; char * pLimit2 = pStr + pMarks[j+1]; for ( ; pStr1 < pLimit1 && pStr2 < pLimit2; pStr1++, pStr2++ ) { if ( !(*pStr1 >= 'a' && *pStr1 <= 'z') ) { pStr2--; continue; } if ( !(*pStr2 >= 'a' && *pStr2 <= 'z') ) { pStr1--; continue; } if ( *pStr1 < *pStr2 ) return -1; if ( *pStr1 > *pStr2 ) return 1; } assert( pStr1 < pLimit1 || pStr2 < pLimit2 ); if ( pStr1 == pLimit1 ) return -1; if ( pStr2 == pLimit2 ) return 1; assert( 0 ); return 0; } int * Dau_DsdNormalizePerm( char * pStr, int * pMarks, int nMarks ) { static int pPerm[DAU_MAX_VAR]; int i, k; for ( i = 0; i < nMarks; i++ ) pPerm[i] = i; for ( i = 0; i < nMarks; i++ ) { int iBest = i; for ( k = i + 1; k < nMarks; k++ ) if ( Dau_DsdNormalizeCompare( pStr, pMarks, pPerm[iBest], pPerm[k] ) == 1 ) iBest = k; ABC_SWAP( int, pPerm[i], pPerm[iBest] ); } return pPerm; } void Dau_DsdNormalize_rec( char * pStr, char ** p, int * pMatches ) { static char pBuffer[DAU_MAX_STR]; if ( **p == '!' ) (*p)++; while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) (*p)++; if ( **p == '<' ) { char * q = pStr + pMatches[*p - pStr]; if ( *(q+1) == '{' ) *p = q+1; } if ( **p >= 'a' && **p <= 'z' ) // var return; if ( **p == '(' || **p == '[' ) // and/or/xor { char * pStore, * pOld = *p + 1; char * q = pStr + pMatches[ *p - pStr ]; int i, * pPerm, nMarks = 0, pMarks[DAU_MAX_VAR+1]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) { pMarks[nMarks++] = *p - pStr; Dau_DsdNormalize_rec( pStr, p, pMatches ); } pMarks[nMarks] = *p - pStr; assert( *p == q ); // add to buffer in good order pPerm = Dau_DsdNormalizePerm( pStr, pMarks, nMarks ); // copy to the buffer pStore = pBuffer; for ( i = 0; i < nMarks; i++ ) pStore = Dau_DsdNormalizeCopy( pStore, pStr, pMarks, pPerm[i] ); assert( pStore - pBuffer == *p - pOld ); memcpy( pOld, pBuffer, pStore - pBuffer ); return; } if ( **p == '<' || **p == '{' ) // mux { char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); if ( (**p == '<') && (*(q+1) == '{') ) { *p = q+1; Dau_DsdNormalize_rec( pStr, p, pMatches ); return; } for ( (*p)++; *p < q; (*p)++ ) Dau_DsdNormalize_rec( pStr, p, pMatches ); assert( *p == q ); return; } assert( 0 ); } void Dau_DsdNormalize( char * pDsd ) { if ( pDsd[1] != 0 ) Dau_DsdNormalize_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdCountAnds_rec( char * pStr, char ** p, int * pMatches ) { if ( **p == '!' ) (*p)++; while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) (*p)++; if ( **p == '<' ) { char * q = pStr + pMatches[*p - pStr]; if ( *(q+1) == '{' ) *p = q+1; } if ( **p >= 'a' && **p <= 'z' ) // var return 0; if ( **p == '(' || **p == '[' ) // and/or/xor { int Counter = 0, AddOn = (**p == '(')? 1 : 3; char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) Counter += AddOn + Dau_DsdCountAnds_rec( pStr, p, pMatches ); assert( *p == q ); return Counter - AddOn; } if ( **p == '<' || **p == '{' ) // mux { int Counter = 3; char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) Counter += Dau_DsdCountAnds_rec( pStr, p, pMatches ); assert( *p == q ); return Counter; } assert( 0 ); return 0; } int Dau_DsdCountAnds( char * pDsd ) { if ( pDsd[1] == 0 ) return 0; return Dau_DsdCountAnds_rec( pDsd, &pDsd, Dau_DsdComputeMatches(pDsd) ); } /**Function************************************************************* Synopsis [Computes truth table for the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Dau_Dsd6TruthCompose_rec( word Func, word * pFanins, int nVars ) { word t0, t1; if ( Func == 0 ) return 0; if ( Func == ~(word)0 ) return ~(word)0; assert( nVars > 0 ); if ( --nVars == 0 ) { assert( Func == s_Truths6[0] || Func == s_Truths6Neg[0] ); return (Func == s_Truths6[0]) ? pFanins[0] : ~pFanins[0]; } if ( !Abc_Tt6HasVar(Func, nVars) ) return Dau_Dsd6TruthCompose_rec( Func, pFanins, nVars ); t0 = Dau_Dsd6TruthCompose_rec( Abc_Tt6Cofactor0(Func, nVars), pFanins, nVars ); t1 = Dau_Dsd6TruthCompose_rec( Abc_Tt6Cofactor1(Func, nVars), pFanins, nVars ); return (~pFanins[nVars] & t0) | (pFanins[nVars] & t1); } word Dau_Dsd6ToTruth_rec( char * pStr, char ** p, int * pMatches, word * pTruths ) { int fCompl = 0; if ( **p == '!' ) (*p)++, fCompl = 1; if ( **p >= 'a' && **p <= 'f' ) // var { assert( **p - 'a' >= 0 && **p - 'a' < 6 ); return fCompl ? ~pTruths[**p - 'a'] : pTruths[**p - 'a']; } if ( **p == '(' ) // and/or { char * q = pStr + pMatches[ *p - pStr ]; word Res = ~(word)0; assert( **p == '(' && *q == ')' ); for ( (*p)++; *p < q; (*p)++ ) Res &= Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths ); assert( *p == q ); return fCompl ? ~Res : Res; } if ( **p == '[' ) // xor { char * q = pStr + pMatches[ *p - pStr ]; word Res = 0; assert( **p == '[' && *q == ']' ); for ( (*p)++; *p < q; (*p)++ ) Res ^= Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths ); assert( *p == q ); return fCompl ? ~Res : Res; } if ( **p == '<' ) // mux { int nVars = 0; word Temp[3], * pTemp = Temp, Res; word Fanins[6], * pTruths2; char * pOld = *p; char * q = pStr + pMatches[ *p - pStr ]; // read fanins if ( *(q+1) == '{' ) { char * q2; *p = q+1; q2 = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q2 == '}' ); for ( nVars = 0, (*p)++; *p < q2; (*p)++, nVars++ ) Fanins[nVars] = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths ); assert( *p == q2 ); pTruths2 = Fanins; } else pTruths2 = pTruths; // read MUX *p = pOld; q = pStr + pMatches[ *p - pStr ]; assert( **p == '<' && *q == '>' ); // verify internal variables if ( nVars ) for ( ; pOld < q; pOld++ ) if ( *pOld >= 'a' && *pOld <= 'z' ) assert( *pOld - 'a' < nVars ); // derive MAX components for ( (*p)++; *p < q; (*p)++ ) *pTemp++ = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths2 ); assert( pTemp == Temp + 3 ); assert( *p == q ); if ( *(q+1) == '{' ) // and/or { char * q = pStr + pMatches[ ++(*p) - pStr ]; assert( **p == '{' && *q == '}' ); *p = q; } Res = (Temp[0] & Temp[1]) | (~Temp[0] & Temp[2]); return fCompl ? ~Res : Res; } if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { word Func, Fanins[6], Res; char * q; int i, nVars = Abc_TtReadHex( &Func, *p ); *p += Abc_TtHexDigitNum( nVars ); q = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q == '}' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) Fanins[i] = Dau_Dsd6ToTruth_rec( pStr, p, pMatches, pTruths ); assert( i == nVars ); assert( *p == q ); Res = Dau_Dsd6TruthCompose_rec( Func, Fanins, nVars ); return fCompl ? ~Res : Res; } assert( 0 ); return 0; } word Dau_Dsd6ToTruth( char * p ) { word Res; if ( *p == '0' && *(p+1) == 0 ) Res = 0; else if ( *p == '1' && *(p+1) == 0 ) Res = ~(word)0; else Res = Dau_Dsd6ToTruth_rec( p, &p, Dau_DsdComputeMatches(p), s_Truths6 ); assert( *++p == 0 ); return Res; } /**Function************************************************************* Synopsis [Computes truth table for the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTruth6Compose_rec( word Func, word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], word * pRes, int nVars, int nWordsR ) { if ( Func == 0 ) { Abc_TtConst0( pRes, nWordsR ); return; } if ( Func == ~(word)0 ) { Abc_TtConst1( pRes, nWordsR ); return; } assert( nVars > 0 ); if ( --nVars == 0 ) { assert( Func == s_Truths6[0] || Func == s_Truths6Neg[0] ); Abc_TtCopy( pRes, pFanins[0], nWordsR, Func == s_Truths6Neg[0] ); return; } if ( !Abc_Tt6HasVar(Func, nVars) ) { Dau_DsdTruth6Compose_rec( Func, pFanins, pRes, nVars, nWordsR ); return; } { word pTtTemp[2][DAU_MAX_WORD]; Dau_DsdTruth6Compose_rec( Abc_Tt6Cofactor0(Func, nVars), pFanins, pTtTemp[0], nVars, nWordsR ); Dau_DsdTruth6Compose_rec( Abc_Tt6Cofactor1(Func, nVars), pFanins, pTtTemp[1], nVars, nWordsR ); Abc_TtMux( pRes, pFanins[nVars], pTtTemp[1], pTtTemp[0], nWordsR ); return; } } void Dau_DsdTruthCompose_rec( word * pFunc, word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], word * pRes, int nVars, int nWordsR ) { int nWordsF; if ( nVars <= 6 ) { Dau_DsdTruth6Compose_rec( pFunc[0], pFanins, pRes, nVars, nWordsR ); return; } nWordsF = Abc_TtWordNum( nVars ); assert( nWordsF > 1 ); if ( Abc_TtIsConst0(pFunc, nWordsF) ) { Abc_TtConst0( pRes, nWordsR ); return; } if ( Abc_TtIsConst1(pFunc, nWordsF) ) { Abc_TtConst1( pRes, nWordsR ); return; } if ( !Abc_TtHasVar( pFunc, nVars, nVars-1 ) ) { Dau_DsdTruthCompose_rec( pFunc, pFanins, pRes, nVars-1, nWordsR ); return; } { word pTtTemp[2][DAU_MAX_WORD]; nVars--; Dau_DsdTruthCompose_rec( pFunc, pFanins, pTtTemp[0], nVars, nWordsR ); Dau_DsdTruthCompose_rec( pFunc + nWordsF/2, pFanins, pTtTemp[1], nVars, nWordsR ); Abc_TtMux( pRes, pFanins[nVars], pTtTemp[1], pTtTemp[0], nWordsR ); return; } } void Dau_DsdToTruth_rec( char * pStr, char ** p, int * pMatches, word ** pTtElems, word * pRes, int nVars ) { int nWords = Abc_TtWordNum( nVars ); int fCompl = 0; if ( **p == '!' ) (*p)++, fCompl = 1; if ( **p >= 'a' && **p <= 'z' ) // var { assert( **p - 'a' >= 0 && **p - 'a' < nVars ); Abc_TtCopy( pRes, pTtElems[**p - 'a'], nWords, fCompl ); return; } if ( **p == '(' ) // and/or { char * q = pStr + pMatches[ *p - pStr ]; word pTtTemp[DAU_MAX_WORD]; assert( **p == '(' && *q == ')' ); Abc_TtConst1( pRes, nWords ); for ( (*p)++; *p < q; (*p)++ ) { Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp, nVars ); Abc_TtAnd( pRes, pRes, pTtTemp, nWords, 0 ); } assert( *p == q ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } if ( **p == '[' ) // xor { char * q = pStr + pMatches[ *p - pStr ]; word pTtTemp[DAU_MAX_WORD]; assert( **p == '[' && *q == ']' ); Abc_TtConst0( pRes, nWords ); for ( (*p)++; *p < q; (*p)++ ) { Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp, nVars ); Abc_TtXor( pRes, pRes, pTtTemp, nWords, 0 ); } assert( *p == q ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } if ( **p == '<' ) // mux { char * q = pStr + pMatches[ *p - pStr ]; word pTtTemp[3][DAU_MAX_WORD]; int i; assert( **p == '<' && *q == '>' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pTtTemp[i], nVars ); assert( i == 3 ); Abc_TtMux( pRes, pTtTemp[0], pTtTemp[1], pTtTemp[2], nWords ); assert( *p == q ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { word pFanins[DAU_MAX_VAR][DAU_MAX_WORD], pFunc[DAU_MAX_WORD]; char * q; int i, nVarsF = Abc_TtReadHex( pFunc, *p ); *p += Abc_TtHexDigitNum( nVarsF ); q = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q == '}' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) Dau_DsdToTruth_rec( pStr, p, pMatches, pTtElems, pFanins[i], nVars ); assert( i == nVarsF ); assert( *p == q ); Dau_DsdTruthCompose_rec( pFunc, pFanins, pRes, nVarsF, nWords ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } assert( 0 ); } word * Dau_DsdToTruth( char * p, int nVars ) { int nWords = Abc_TtWordNum( nVars ); word ** pTtElems = Dau_DsdTtElems(); word * pRes = pTtElems[DAU_MAX_VAR]; assert( nVars <= DAU_MAX_VAR ); if ( Dau_DsdIsConst0(p) ) Abc_TtConst0( pRes, nWords ); else if ( Dau_DsdIsConst1(p) ) Abc_TtConst1( pRes, nWords ); else Dau_DsdToTruth_rec( p, &p, Dau_DsdComputeMatches(p), pTtElems, pRes, nVars ); assert( *++p == 0 ); return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTest2() { // char * p = Abc_UtilStrsav( "!(ab!(de[cf]))" ); // char * p = Abc_UtilStrsav( "!(a![d]b)" ); // word t = Dau_Dsd6ToTruth( p ); } /**Function************************************************************* Synopsis [Performs DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dau_DsdPerformReplace( char * pBuffer, int PosStart, int Pos, int Symb, char * pNext ) { static char pTemp[DAU_MAX_STR]; char * pCur = pTemp; int i, k, RetValue; for ( i = PosStart; i < Pos; i++ ) if ( pBuffer[i] != Symb ) *pCur++ = pBuffer[i]; else for ( k = 0; pNext[k]; k++ ) *pCur++ = pNext[k]; RetValue = PosStart + (pCur - pTemp); for ( i = PosStart; i < RetValue; i++ ) pBuffer[i] = pTemp[i-PosStart]; return RetValue; } int Dau_DsdPerform_rec( word t, char * pBuffer, int Pos, int * pVars, int nVars ) { char pNest[10]; word Cof0[6], Cof1[6], Cof[4]; int pVarsNew[6], nVarsNew, PosStart; int v, u, vBest, CountBest; assert( Pos < DAU_MAX_STR ); // perform support minimization nVarsNew = 0; for ( v = 0; v < nVars; v++ ) if ( Abc_Tt6HasVar( t, pVars[v] ) ) pVarsNew[ nVarsNew++ ] = pVars[v]; assert( nVarsNew > 0 ); // special case when function is a var if ( nVarsNew == 1 ) { if ( t == s_Truths6[ pVarsNew[0] ] ) { pBuffer[Pos++] = 'a' + pVarsNew[0]; return Pos; } if ( t == ~s_Truths6[ pVarsNew[0] ] ) { pBuffer[Pos++] = '!'; pBuffer[Pos++] = 'a' + pVarsNew[0]; return Pos; } assert( 0 ); return Pos; } // decompose on the output side for ( v = 0; v < nVarsNew; v++ ) { Cof0[v] = Abc_Tt6Cofactor0( t, pVarsNew[v] ); Cof1[v] = Abc_Tt6Cofactor1( t, pVarsNew[v] ); assert( Cof0[v] != Cof1[v] ); if ( Cof0[v] == 0 ) // ax { pBuffer[Pos++] = '('; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( Cof1[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ')'; return Pos; } if ( Cof0[v] == ~(word)0 ) // !(ax) { pBuffer[Pos++] = '!'; pBuffer[Pos++] = '('; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( ~Cof1[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ')'; return Pos; } if ( Cof1[v] == 0 ) // !ax { pBuffer[Pos++] = '('; pBuffer[Pos++] = '!'; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ')'; return Pos; } if ( Cof1[v] == ~(word)0 ) // !(!ax) { pBuffer[Pos++] = '!'; pBuffer[Pos++] = '('; pBuffer[Pos++] = '!'; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( ~Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ')'; return Pos; } if ( Cof0[v] == ~Cof1[v] ) // a^x { pBuffer[Pos++] = '['; pBuffer[Pos++] = 'a' + pVarsNew[v]; Pos = Dau_DsdPerform_rec( Cof0[v], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = ']'; return Pos; } } // decompose on the input side for ( v = 0; v < nVarsNew; v++ ) for ( u = v+1; u < nVarsNew; u++ ) { Cof[0] = Abc_Tt6Cofactor0( Cof0[v], pVarsNew[u] ); Cof[1] = Abc_Tt6Cofactor1( Cof0[v], pVarsNew[u] ); Cof[2] = Abc_Tt6Cofactor0( Cof1[v], pVarsNew[u] ); Cof[3] = Abc_Tt6Cofactor1( Cof1[v], pVarsNew[u] ); if ( Cof[0] == Cof[1] && Cof[0] == Cof[2] ) // vu { PosStart = Pos; sprintf( pNest, "(%c%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[3]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } if ( Cof[0] == Cof[1] && Cof[0] == Cof[3] ) // v!u { PosStart = Pos; sprintf( pNest, "(%c!%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[2]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } if ( Cof[0] == Cof[2] && Cof[0] == Cof[3] ) // !vu { PosStart = Pos; sprintf( pNest, "(!%c%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[1]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } if ( Cof[1] == Cof[2] && Cof[1] == Cof[3] ) // !v!u { PosStart = Pos; sprintf( pNest, "(!%c!%c)", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[0]) | (~s_Truths6[pVarsNew[u]] & Cof[1]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } if ( Cof[0] == Cof[3] && Cof[1] == Cof[2] ) // v+u { PosStart = Pos; sprintf( pNest, "[%c%c]", 'a' + pVarsNew[v], 'a' + pVarsNew[u] ); Pos = Dau_DsdPerform_rec( (s_Truths6[pVarsNew[u]] & Cof[1]) | (~s_Truths6[pVarsNew[u]] & Cof[0]), pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerformReplace( pBuffer, PosStart, Pos, 'a' + pVarsNew[u], pNest ); return Pos; } } // find best variable for MUX decomposition vBest = -1; CountBest = 10; for ( v = 0; v < nVarsNew; v++ ) { int CountCur = 0; for ( u = 0; u < nVarsNew; u++ ) if ( u != v && Abc_Tt6HasVar(Cof0[v], pVarsNew[u]) && Abc_Tt6HasVar(Cof1[v], pVarsNew[u]) ) CountCur++; if ( CountBest > CountCur ) { CountBest = CountCur; vBest = v; } if ( CountCur == 0 ) break; } // perform MUX decomposition pBuffer[Pos++] = '<'; pBuffer[Pos++] = 'a' + pVarsNew[vBest]; Pos = Dau_DsdPerform_rec( Cof1[vBest], pBuffer, Pos, pVarsNew, nVarsNew ); Pos = Dau_DsdPerform_rec( Cof0[vBest], pBuffer, Pos, pVarsNew, nVarsNew ); pBuffer[Pos++] = '>'; return Pos; } char * Dau_DsdPerform( word t ) { static char pBuffer[DAU_MAX_STR]; int pVarsNew[6] = {0, 1, 2, 3, 4, 5}; int Pos = 0; if ( t == 0 ) pBuffer[Pos++] = '0'; else if ( t == ~(word)0 ) pBuffer[Pos++] = '1'; else Pos = Dau_DsdPerform_rec( t, pBuffer, Pos, pVarsNew, 6 ); pBuffer[Pos++] = 0; // printf( "%d ", strlen(pBuffer) ); // printf( "%s ->", pBuffer ); Dau_DsdRemoveBraces( pBuffer, Dau_DsdComputeMatches(pBuffer) ); // printf( " %s\n", pBuffer ); return pBuffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTest3() { // word t = s_Truths6[0] & s_Truths6[1] & s_Truths6[2]; // word t = ~s_Truths6[0] | (s_Truths6[1] ^ ~s_Truths6[2]); // word t = (s_Truths6[1] & s_Truths6[2]) | (s_Truths6[0] & s_Truths6[3]); // word t = (~s_Truths6[1] & ~s_Truths6[2]) | (s_Truths6[0] ^ s_Truths6[3]); // word t = ((~s_Truths6[1] & ~s_Truths6[2]) | (s_Truths6[0] ^ s_Truths6[3])) ^ s_Truths6[5]; // word t = ((s_Truths6[1] & ~s_Truths6[2]) ^ (s_Truths6[0] & s_Truths6[3])) & s_Truths6[5]; // word t = (~(~s_Truths6[0] & ~s_Truths6[4]) & s_Truths6[2]) | (~s_Truths6[1] & ~s_Truths6[0] & ~s_Truths6[4]); // word t = 0x0000000000005F3F; // word t = 0xF3F5030503050305; // word t = (s_Truths6[0] & s_Truths6[1] & (s_Truths6[2] ^ s_Truths6[4])) | (~s_Truths6[0] & ~s_Truths6[1] & ~(s_Truths6[2] ^ s_Truths6[4])); // word t = 0x05050500f5f5f5f3; word t = ABC_CONST(0x9ef7a8d9c7193a0f); char * p = Dau_DsdPerform( t ); word t2 = Dau_Dsd6ToTruth( p ); if ( t != t2 ) printf( "Verification failed.\n" ); } /**Function************************************************************* Synopsis [Find the best cofactoring variable.] Description [Return -2 if non-DSD; -1 if full DSD; otherwise, returns cofactoring variables i (i >= 0).] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdCheck1Step( void * p, word * pTruth, int nVarsInit, int * pVarLevels ) { word pCofTemp[DAU_MAX_WORD]; int pVarPrios[DAU_MAX_VAR]; int nWords = Abc_TtWordNum(nVarsInit); int nSizeNonDec, nSizeNonDec0, nSizeNonDec1; int i, vBest = -2, nSumCofsBest = ABC_INFINITY, nSumCofs; nSizeNonDec = Dau_DsdDecompose( pTruth, nVarsInit, 0, 0, NULL ); if ( nSizeNonDec == 0 ) return -1; assert( nSizeNonDec > 0 ); // find variable priority for ( i = 0; i < nVarsInit; i++ ) pVarPrios[i] = i; if ( pVarLevels ) { extern int Dau_DsdLevelVar( void * pMan, int iVar ); int pVarLevels[DAU_MAX_VAR]; for ( i = 0; i < nVarsInit; i++ ) pVarLevels[i] = -Dau_DsdLevelVar( p, i ); // for ( i = 0; i < nVarsInit; i++ ) // printf( "%d ", -pVarLevels[i] ); // printf( "\n" ); Vec_IntSelectSortCost2( pVarPrios, nVarsInit, pVarLevels ); // for ( i = 0; i < nVarsInit; i++ ) // printf( "%d ", pVarPrios[i] ); // printf( "\n\n" ); } for ( i = 0; i < nVarsInit; i++ ) { assert( pVarPrios[i] >= 0 && pVarPrios[i] < nVarsInit ); // try first cofactor Abc_TtCofactor0p( pCofTemp, pTruth, nWords, pVarPrios[i] ); nSumCofs = Abc_TtSupportSize( pCofTemp, nVarsInit ); nSizeNonDec0 = Dau_DsdDecompose( pCofTemp, nVarsInit, 0, 0, NULL ); // try second cofactor Abc_TtCofactor1p( pCofTemp, pTruth, nWords, pVarPrios[i] ); nSumCofs += Abc_TtSupportSize( pCofTemp, nVarsInit ); nSizeNonDec1 = Dau_DsdDecompose( pCofTemp, nVarsInit, 0, 0, NULL ); // compare cofactors if ( nSizeNonDec0 || nSizeNonDec1 ) continue; if ( nSumCofsBest > nSumCofs ) { vBest = pVarPrios[i]; nSumCofsBest = nSumCofs; } } return vBest; } /**Function************************************************************* Synopsis [Data-structure to store DSD information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ typedef struct Dau_Dsd_t_ Dau_Dsd_t; struct Dau_Dsd_t_ { int nVarsInit; // the initial number of variables int nVarsUsed; // the current number of variables int nPos; // writing position int nSizeNonDec; // size of the largest non-decomposable block int nConsts; // the number of constant decompositions int uConstMask; // constant decomposition mask int fSplitPrime; // represent prime function as 1-step DSD int fWriteTruth; // writing truth table as a hex string int * pVarLevels; // variable levels char pVarDefs[32][8]; // variable definitions char Cache[32][32]; // variable cache char pOutput[DAU_MAX_STR]; // output stream }; static abctime s_Times[3] = {0}; /**Function************************************************************* Synopsis [Manipulation of DSD data-structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dau_DsdInitialize( Dau_Dsd_t * p, int nVarsInit ) { int i, v, u; assert( nVarsInit >= 0 && nVarsInit <= 16 ); p->nVarsInit = nVarsInit; p->nVarsUsed = nVarsInit; p->nPos = 0; p->nSizeNonDec = 0; p->nConsts = 0; p->uConstMask = 0; for ( i = 0; i < nVarsInit; i++ ) p->pVarDefs[i][0] = 'a' + i, p->pVarDefs[i][1] = 0; for ( v = 0; v < nVarsInit; v++ ) for ( u = 0; u < nVarsInit; u++ ) p->Cache[v][u] = 0; } static inline void Dau_DsdWriteString( Dau_Dsd_t * p, char * pStr ) { while ( *pStr ) p->pOutput[ p->nPos++ ] = *pStr++; } static inline void Dau_DsdWriteVar( Dau_Dsd_t * p, int iVar, int fInv ) { char * pStr; if ( fInv ) p->pOutput[ p->nPos++ ] = '!'; for ( pStr = p->pVarDefs[iVar]; *pStr; pStr++ ) if ( *pStr >= 'a' + p->nVarsInit && *pStr < 'a' + p->nVarsUsed ) Dau_DsdWriteVar( p, *pStr - 'a', 0 ); else p->pOutput[ p->nPos++ ] = *pStr; } int Dau_DsdLevelVar( void * pMan, int iVar ) { Dau_Dsd_t * p = (Dau_Dsd_t *)pMan; char * pStr; int LevelMax = 0, Level; for ( pStr = p->pVarDefs[iVar]; *pStr; pStr++ ) { if ( *pStr >= 'a' + p->nVarsInit && *pStr < 'a' + p->nVarsUsed ) Level = 1 + Dau_DsdLevelVar( p, *pStr - 'a' ); else Level = p->pVarLevels[*pStr - 'a']; LevelMax = Abc_MaxInt( LevelMax, Level ); } return LevelMax; } static inline void Dau_DsdTranslate( Dau_Dsd_t * p, int * pVars, int nVars, char * pStr ) { for ( ; *pStr; pStr++ ) if ( *pStr >= 'a' && *pStr < 'a' + nVars ) Dau_DsdWriteVar( p, pVars[*pStr - 'a'], 0 ); else p->pOutput[ p->nPos++ ] = *pStr; } static inline int Dau_DsdWritePrime( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { int v, RetValue = 2; assert( nVars > 2 ); if ( p->fSplitPrime ) { word pCofTemp[DAU_MAX_WORD]; int nWords = Abc_TtWordNum(nVars); int vBest = Dau_DsdCheck1Step( p, pTruth, nVars, p->pVarLevels ); assert( vBest != -1 ); if ( vBest == -2 ) // non-dec p->nPos += Abc_TtWriteHexRev( p->pOutput + p->nPos, pTruth, nVars ); else { char pRes[DAU_MAX_STR]; int nNonDecSize; // compose the result Dau_DsdWriteString( p, "<" ); Dau_DsdWriteVar( p, vBest, 0 ); // split decomposition Abc_TtCofactor1p( pCofTemp, pTruth, nWords, vBest ); nNonDecSize = Dau_DsdDecompose( pCofTemp, nVars, 0, p->fWriteTruth, pRes ); assert( nNonDecSize == 0 ); Dau_DsdWriteString( p, pRes ); // split decomposition Abc_TtCofactor0p( pCofTemp, pTruth, nWords, vBest ); nNonDecSize = Dau_DsdDecompose( pCofTemp, nVars, 0, p->fWriteTruth, pRes ); assert( nNonDecSize == 0 ); Dau_DsdWriteString( p, pRes ); Dau_DsdWriteString( p, ">" ); RetValue = 1; } } else if ( p->fWriteTruth ) p->nPos += Abc_TtWriteHexRev( p->pOutput + p->nPos, pTruth, nVars ); Dau_DsdWriteString( p, "{" ); for ( v = 0; v < nVars; v++ ) Dau_DsdWriteVar( p, pVars[v], 0 ); Dau_DsdWriteString( p, "}" ); p->nSizeNonDec = nVars; return RetValue; } static inline void Dau_DsdFinalize( Dau_Dsd_t * p ) { int i; for ( i = 0; i < p->nConsts; i++ ) p->pOutput[ p->nPos++ ] = ((p->uConstMask >> (p->nConsts-1-i)) & 1) ? ']' : ')'; p->pOutput[ p->nPos++ ] = 0; } static inline int Dau_DsdAddVarDef( Dau_Dsd_t * p, char * pStr ) { int u; assert( strlen(pStr) < 8 ); assert( p->nVarsUsed < 32 ); for ( u = 0; u < p->nVarsUsed; u++ ) p->Cache[p->nVarsUsed][u] = 0; for ( u = 0; u < p->nVarsUsed; u++ ) p->Cache[u][p->nVarsUsed] = 0; sprintf( p->pVarDefs[p->nVarsUsed++], "%s", pStr ); return p->nVarsUsed - 1; } static inline int Dau_DsdFindVarDef( int * pVars, int nVars, int VarDef ) { int v; for ( v = 0; v < nVars; v++ ) if ( pVars[v] == VarDef ) break; assert( v < nVars ); return v; } static inline void Dau_DsdInsertVarCache( Dau_Dsd_t * p, int v, int u, int Status ) { assert( v != u ); assert( Status > 0 && Status < 4 ); assert( p->Cache[v][u] == 0 ); p->Cache[v][u] = Status; } static inline int Dau_DsdLookupVarCache( Dau_Dsd_t * p, int v, int u ) { return p->Cache[v][u]; } /**Function************************************************************* Synopsis [Procedures specialized for 6-variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dau_Dsd6DecomposeSingleVarOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { // consider negative cofactors if ( pTruth[0] & 1 ) { if ( Abc_Tt6Cof0IsConst1( pTruth[0], v ) ) // !(ax) { Dau_DsdWriteString( p, "!(" ); pTruth[0] = ~Abc_Tt6Cofactor1( pTruth[0], v ); goto finish; } } else { if ( Abc_Tt6Cof0IsConst0( pTruth[0], v ) ) // ax { Dau_DsdWriteString( p, "(" ); pTruth[0] = Abc_Tt6Cofactor1( pTruth[0], v ); goto finish; } } // consider positive cofactors if ( pTruth[0] >> 63 ) { if ( Abc_Tt6Cof1IsConst1( pTruth[0], v ) ) // !(!ax) { Dau_DsdWriteString( p, "!(!" ); pTruth[0] = ~Abc_Tt6Cofactor0( pTruth[0], v ); goto finish; } } else { if ( Abc_Tt6Cof1IsConst0( pTruth[0], v ) ) // !ax { Dau_DsdWriteString( p, "(!" ); pTruth[0] = Abc_Tt6Cofactor0( pTruth[0], v ); goto finish; } } // consider equal cofactors if ( Abc_Tt6CofsOpposite( pTruth[0], v ) ) // [ax] { Dau_DsdWriteString( p, "[" ); pTruth[0] = Abc_Tt6Cofactor0( pTruth[0], v ); p->uConstMask |= (1 << p->nConsts); goto finish; } return 0; finish: p->nConsts++; Dau_DsdWriteVar( p, pVars[v], 0 ); pVars[v] = pVars[nVars-1]; Abc_TtSwapVars( pTruth, nVars, v, nVars-1 ); return 1; } int Dau_Dsd6DecomposeSingleVar( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { abctime clk = Abc_Clock(); assert( nVars > 1 ); while ( 1 ) { int v; for ( v = nVars - 1; v >= 0 && nVars > 1; v-- ) if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) ) { nVars--; break; } if ( v == -1 || nVars == 1 ) break; } if ( nVars == 1 ) Dau_DsdWriteVar( p, pVars[--nVars], (int)(pTruth[0] & 1) ); s_Times[0] += Abc_Clock() - clk; return nVars; } static inline int Dau_Dsd6FindSupportOne( Dau_Dsd_t * p, word tCof0, word tCof1, int * pVars, int nVars, int v, int u ) { int Status = p ? Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) : 0; if ( Status == 0 ) { Status = (Abc_Tt6HasVar(tCof1, u) << 1) | Abc_Tt6HasVar(tCof0, u); if ( p ) Dau_DsdInsertVarCache( p, pVars[v], pVars[u], Status ); } return Status; } static inline unsigned Dau_Dsd6FindSupports( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { int u; unsigned uSupports = 0; word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v ); word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v ); //Kit_DsdPrintFromTruth( (unsigned *)&tCof0, 6 );printf( "\n" ); //Kit_DsdPrintFromTruth( (unsigned *)&tCof1, 6 );printf( "\n" ); for ( u = 0; u < nVars; u++ ) if ( u != v ) uSupports |= (Dau_Dsd6FindSupportOne( p, tCof0, tCof1, pVars, nVars, v, u ) << (2 * u)); return uSupports; } static inline void Dau_DsdPrintSupports( unsigned uSupp, int nVars ) { int v, Value; printf( "Cofactor supports: " ); for ( v = nVars - 1; v >= 0; v-- ) { Value = ((uSupp >> (2*v)) & 3); if ( Value == 1 ) printf( "01" ); else if ( Value == 2 ) printf( "10" ); else if ( Value == 3 ) printf( "11" ); else printf( "00" ); if ( v ) printf( "-" ); } printf( "\n" ); } // checks decomposability with respect to the pair (v, u) static inline int Dau_Dsd6DecomposeDoubleVarsOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v, int u ) { char pBuffer[10] = { 0 }; word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v ); word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v ); int Status = Dau_Dsd6FindSupportOne( p, tCof0, tCof1, pVars, nVars, v, u ); assert( v > u ); //printf( "Checking %s and %s.\n", p->pVarDefs[pVars[v]], p->pVarDefs[pVars[u]] ); // Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 );printf( "\n" ); if ( Status == 3 ) { // both F(v=0) and F(v=1) depend on u if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) && Abc_Tt6Cof0EqualCof1(tCof1, tCof0, u) ) // v+u { pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); sprintf( pBuffer, "[%c%c]", 'a' + pVars[v], 'a' + pVars[u] ); goto finish; } } else if ( Status == 2 ) { // F(v=0) does not depend on u; F(v=1) depends on u if ( Abc_Tt6Cof0EqualCof0(tCof0, tCof1, u) ) // vu { sprintf( pBuffer, "(%c%c)", 'a' + pVars[v], 'a' + pVars[u] ); pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); goto finish; } if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // v!u { sprintf( pBuffer, "(%c!%c)", 'a' + pVars[v], 'a' + pVars[u] ); pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); goto finish; } } else if ( Status == 1 ) { // F(v=0) depends on u; F(v=1) does not depend on u if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // !vu { sprintf( pBuffer, "(!%c%c)", 'a' + pVars[v], 'a' + pVars[u] ); pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); goto finish; } if ( Abc_Tt6Cof1EqualCof1(tCof0, tCof1, u) ) // !v!u { sprintf( pBuffer, "(!%c!%c)", 'a' + pVars[v], 'a' + pVars[u] ); pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u)); goto finish; } } return nVars; finish: // finalize decomposition assert( pBuffer[0] ); pVars[u] = Dau_DsdAddVarDef( p, pBuffer ); pVars[v] = pVars[nVars-1]; Abc_TtSwapVars( pTruth, nVars, v, nVars-1 ); if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, --nVars, u ) ) nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, --nVars ); return nVars; } int Dau_Dsd6DecomposeDoubleVars( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { abctime clk = Abc_Clock(); while ( 1 ) { int v, u, nVarsOld; for ( v = nVars - 1; v > 0; v-- ) { for ( u = v - 1; u >= 0; u-- ) { if ( Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) ) continue; nVarsOld = nVars; nVars = Dau_Dsd6DecomposeDoubleVarsOne( p, pTruth, pVars, nVars, v, u ); if ( nVars == 0 ) { s_Times[1] += Abc_Clock() - clk; return 0; } if ( nVarsOld > nVars ) break; } if ( u >= 0 ) // found break; } if ( v == 0 ) // not found break; } s_Times[1] += Abc_Clock() - clk; return nVars; } // look for MUX-decomposable variable on top or at the bottom static inline int Dau_Dsd6DecomposeTripleVarsOuter( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { extern int Dau_DsdDecomposeInt( Dau_Dsd_t * p, word * pTruth, int nVarsInit ); Dau_Dsd_t P1, * p1 = &P1; word tCof0, tCof1; p1->fSplitPrime = 0; p1->fWriteTruth = p->fWriteTruth; // move this variable to the top ABC_SWAP( int, pVars[v], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, nVars, v, nVars-1 ); // cofactor w.r.t the last variable tCof0 = Abc_Tt6Cofactor0( pTruth[0], nVars - 1 ); tCof1 = Abc_Tt6Cofactor1( pTruth[0], nVars - 1 ); // compose the result Dau_DsdWriteString( p, "<" ); Dau_DsdWriteVar( p, pVars[nVars - 1], 0 ); // split decomposition Dau_DsdDecomposeInt( p1, &tCof1, nVars - 1 ); Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput ); p->nSizeNonDec = p1->nSizeNonDec; if ( p1->nSizeNonDec ) *pTruth = tCof1; // split decomposition Dau_DsdDecomposeInt( p1, &tCof0, nVars - 1 ); Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput ); Dau_DsdWriteString( p, ">" ); p->nSizeNonDec = Abc_MaxInt( p->nSizeNonDec, p1->nSizeNonDec ); if ( p1->nSizeNonDec ) *pTruth = tCof0; return 0; } static inline int Dau_Dsd6DecomposeTripleVarsInner( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v, unsigned uSupports ) { int iVar0 = Abc_TtSuppFindFirst( uSupports & (~uSupports >> 1) & 0x55555555 ) >> 1; int iVar1 = Abc_TtSuppFindFirst( ~uSupports & ( uSupports >> 1) & 0x55555555 ) >> 1; word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v ); word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v ); word C00 = Abc_Tt6Cofactor0( tCof0, iVar0 ); word C01 = Abc_Tt6Cofactor1( tCof0, iVar0 ); word C10 = Abc_Tt6Cofactor0( tCof1, iVar1 ); word C11 = Abc_Tt6Cofactor1( tCof1, iVar1 ); int fEqual0 = (C00 == C10) && (C01 == C11); int fEqual1 = (C00 == C11) && (C01 == C10); if ( fEqual0 || fEqual1 ) { char pBuffer[10]; int VarId = pVars[iVar0]; pTruth[0] = (s_Truths6[v] & C11) | (~s_Truths6[v] & C10); sprintf( pBuffer, "<%c%c%s%c>", 'a' + pVars[v], 'a' + pVars[iVar1], fEqual1 ? "!":"", 'a' + pVars[iVar0] ); pVars[v] = Dau_DsdAddVarDef( p, pBuffer ); // remove iVar1 ABC_SWAP( int, pVars[iVar1], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, nVars, iVar1, nVars-1 ); nVars--; // remove iVar0 iVar0 = Dau_DsdFindVarDef( pVars, nVars, VarId ); ABC_SWAP( int, pVars[iVar0], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, nVars, iVar0, nVars-1 ); nVars--; // find the new var v = Dau_DsdFindVarDef( pVars, nVars, p->nVarsUsed-1 ); // remove single variables if possible if ( Dau_Dsd6DecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) ) nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, --nVars ); return nVars; } return nVars; } int Dau_Dsd6DecomposeTripleVars( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { abctime clk = Abc_Clock(); while ( 1 ) { int v; // Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 ); printf( "\n" ); for ( v = nVars - 1; v >= 0; v-- ) { unsigned uSupports = Dau_Dsd6FindSupports( p, pTruth, pVars, nVars, v ); // Dau_DsdPrintSupports( uSupports, nVars ); if ( (uSupports & (uSupports >> 1) & 0x55555555) == 0 ) // non-overlapping supports return Dau_Dsd6DecomposeTripleVarsOuter( p, pTruth, pVars, nVars, v ); if ( Abc_TtSuppOnlyOne( uSupports & (~uSupports >> 1) & 0x55555555) && Abc_TtSuppOnlyOne(~uSupports & ( uSupports >> 1) & 0x55555555) ) // one unique variable in each cofactor { int nVarsNew = Dau_Dsd6DecomposeTripleVarsInner( p, pTruth, pVars, nVars, v, uSupports ); if ( nVarsNew == nVars ) continue; if ( nVarsNew == 0 ) { s_Times[2] += Abc_Clock() - clk; return 0; } nVars = Dau_Dsd6DecomposeDoubleVars( p, pTruth, pVars, nVarsNew ); if ( nVars == 0 ) { s_Times[2] += Abc_Clock() - clk; return 0; } break; } } if ( v == -1 ) { s_Times[2] += Abc_Clock() - clk; return nVars; } } assert( 0 ); return -1; } int Dau_Dsd6DecomposeInternal( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { // decompose single variales on the output side nVars = Dau_Dsd6DecomposeSingleVar( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // decompose double variables on the input side nVars = Dau_Dsd6DecomposeDoubleVars( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // decompose MUX on the output/input side nVars = Dau_Dsd6DecomposeTripleVars( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // write non-decomposable function return Dau_DsdWritePrime( p, pTruth, pVars, nVars ); } /**Function************************************************************* Synopsis [Procedures specialized for 6-variable functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dau_DsdDecomposeSingleVarOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { int nWords = Abc_TtWordNum(nVars); // consider negative cofactors if ( pTruth[0] & 1 ) { if ( Abc_TtCof0IsConst1( pTruth, nWords, v ) ) // !(ax) { Dau_DsdWriteString( p, "!(" ); Abc_TtCofactor1( pTruth, nWords, v ); Abc_TtNot( pTruth, nWords ); goto finish; } } else { if ( Abc_TtCof0IsConst0( pTruth, nWords, v ) ) // ax { Dau_DsdWriteString( p, "(" ); Abc_TtCofactor1( pTruth, nWords, v ); goto finish; } } // consider positive cofactors if ( pTruth[nWords-1] >> 63 ) { if ( Abc_TtCof1IsConst1( pTruth, nWords, v ) ) // !(!ax) { Dau_DsdWriteString( p, "!(!" ); Abc_TtCofactor0( pTruth, nWords, v ); Abc_TtNot( pTruth, nWords ); goto finish; } } else { if ( Abc_TtCof1IsConst0( pTruth, nWords, v ) ) // !ax { Dau_DsdWriteString( p, "(!" ); Abc_TtCofactor0( pTruth, nWords, v ); goto finish; } } // consider equal cofactors if ( Abc_TtCofsOpposite( pTruth, nWords, v ) ) // [ax] { Dau_DsdWriteString( p, "[" ); Abc_TtCofactor0( pTruth, nWords, v ); p->uConstMask |= (1 << p->nConsts); goto finish; } return 0; finish: p->nConsts++; Dau_DsdWriteVar( p, pVars[v], 0 ); pVars[v] = pVars[nVars-1]; Abc_TtSwapVars( pTruth, nVars, v, nVars-1 ); return 1; } int Dau_DsdDecomposeSingleVar( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { abctime clk = Abc_Clock(); assert( nVars > 1 ); while ( 1 ) { int v; for ( v = nVars - 1; v >= 0 && nVars > 1; v-- ) if ( Dau_DsdDecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) ) { nVars--; break; } if ( v == -1 || nVars == 1 ) break; } if ( nVars == 1 ) Dau_DsdWriteVar( p, pVars[--nVars], (int)(pTruth[0] & 1) ); s_Times[0] += Abc_Clock() - clk; return nVars; } static inline int Dau_DsdFindSupportOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v, int u ) { int nWords = Abc_TtWordNum(nVars); int Status = p ? Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) : 0; if ( Status == 0 ) { // Status = (Abc_Tt6HasVar(tCof1, u) << 1) | Abc_Tt6HasVar(tCof0, u); if ( v < u ) Status = (!Abc_TtCheckEqualCofs(pTruth, nWords, v, u, 1, 3) << 1) | !Abc_TtCheckEqualCofs(pTruth, nWords, v, u, 0, 2); else // if ( v > u ) Status = (!Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 2, 3) << 1) | !Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 1); assert( Status != 0 ); if ( p ) Dau_DsdInsertVarCache( p, pVars[v], pVars[u], Status ); } return Status; } static inline unsigned Dau_DsdFindSupports( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { int u; unsigned uSupports = 0; //Kit_DsdPrintFromTruth( (unsigned *)&tCof0, 6 );printf( "\n" ); //Kit_DsdPrintFromTruth( (unsigned *)&tCof1, 6 );printf( "\n" ); for ( u = 0; u < nVars; u++ ) if ( u != v ) uSupports |= (Dau_DsdFindSupportOne( p, pTruth, pVars, nVars, v, u ) << (2 * u)); return uSupports; } // checks decomposability with respect to the pair (v, u) static inline int Dau_DsdDecomposeDoubleVarsOne( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v, int u ) { char pBuffer[10] = { 0 }; int nWords = Abc_TtWordNum(nVars); int Status = Dau_DsdFindSupportOne( p, pTruth, pVars, nVars, v, u ); assert( v > u ); //printf( "Checking %s and %s.\n", p->pVarDefs[pVars[v]], p->pVarDefs[pVars[u]] ); if ( Status == 3 ) { // both F(v=0) and F(v=1) depend on u // if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) && Abc_Tt6Cof0EqualCof1(tCof1, tCof0, u) ) // v+u if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 3) && Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 1, 2) ) // 00=11 01=10 v+u { word pTtTemp[2][DAU_MAX_WORD]; sprintf( pBuffer, "[%c%c]", 'a' + pVars[v], 'a' + pVars[u] ); // pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); Abc_TtCofactor0p( pTtTemp[0], pTruth, nWords, v ); Abc_TtCofactor0( pTtTemp[0], nWords, u ); Abc_TtCofactor0p( pTtTemp[1], pTruth, nWords, v ); Abc_TtCofactor1( pTtTemp[1], nWords, u ); Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords ); goto finish; } } else if ( Status == 2 ) { // F(v=0) does not depend on u; F(v=1) depends on u // if ( Abc_Tt6Cof0EqualCof0(tCof0, tCof1, u) ) // vu if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 2) ) // 00=10 vu { word pTtTemp[2][DAU_MAX_WORD]; sprintf( pBuffer, "(%c%c)", 'a' + pVars[v], 'a' + pVars[u] ); // pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); Abc_TtCofactor0p( pTtTemp[0], pTruth, nWords, v ); Abc_TtCofactor0( pTtTemp[0], nWords, u ); Abc_TtCofactor1p( pTtTemp[1], pTruth, nWords, v ); Abc_TtCofactor1( pTtTemp[1], nWords, u ); Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords ); goto finish; } // if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // v!u if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 3) ) // 00=11 v!u { word pTtTemp[2][DAU_MAX_WORD]; sprintf( pBuffer, "(%c!%c)", 'a' + pVars[v], 'a' + pVars[u] ); // pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof1, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); Abc_TtCofactor0p( pTtTemp[0], pTruth, nWords, v ); Abc_TtCofactor0( pTtTemp[0], nWords, u ); Abc_TtCofactor1p( pTtTemp[1], pTruth, nWords, v ); Abc_TtCofactor0( pTtTemp[1], nWords, u ); Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords ); goto finish; } } else if ( Status == 1 ) { // F(v=0) depends on u; F(v=1) does not depend on u // if ( Abc_Tt6Cof0EqualCof1(tCof0, tCof1, u) ) // !vu if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 0, 3) ) // 00=11 !vu { word pTtTemp[2][DAU_MAX_WORD]; sprintf( pBuffer, "(!%c%c)", 'a' + pVars[v], 'a' + pVars[u] ); // pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor1(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)); Abc_TtCofactor0p( pTtTemp[0], pTruth, nWords, v ); Abc_TtCofactor0( pTtTemp[0], nWords, u ); Abc_TtCofactor0p( pTtTemp[1], pTruth, nWords, v ); Abc_TtCofactor1( pTtTemp[1], nWords, u ); Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords ); goto finish; } // if ( Abc_Tt6Cof1EqualCof1(tCof0, tCof1, u) ) // !v!u if ( Abc_TtCheckEqualCofs(pTruth, nWords, u, v, 1, 3) ) // 01=11 !v!u { word pTtTemp[2][DAU_MAX_WORD]; sprintf( pBuffer, "(!%c!%c)", 'a' + pVars[v], 'a' + pVars[u] ); // pTruth[0] = (s_Truths6[u] & Abc_Tt6Cofactor0(tCof0, u)) | (~s_Truths6[u] & Abc_Tt6Cofactor1(tCof1, u)); Abc_TtCofactor1p( pTtTemp[0], pTruth, nWords, v ); Abc_TtCofactor1( pTtTemp[0], nWords, u ); Abc_TtCofactor0p( pTtTemp[1], pTruth, nWords, v ); Abc_TtCofactor0( pTtTemp[1], nWords, u ); Abc_TtMux( pTruth, Dau_DsdTtElems()[u], pTtTemp[1], pTtTemp[0], nWords ); goto finish; } } return nVars; finish: // finalize decomposition assert( pBuffer[0] ); pVars[u] = Dau_DsdAddVarDef( p, pBuffer ); pVars[v] = pVars[nVars-1]; Abc_TtSwapVars( pTruth, nVars, v, nVars-1 ); if ( Dau_DsdDecomposeSingleVarOne( p, pTruth, pVars, --nVars, u ) ) nVars = Dau_DsdDecomposeSingleVar( p, pTruth, pVars, --nVars ); return nVars; } int Dau_DsdDecomposeDoubleVars( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { abctime clk = Abc_Clock(); while ( 1 ) { int v, u, nVarsOld; for ( v = nVars - 1; v > 0; v-- ) { for ( u = v - 1; u >= 0; u-- ) { if ( Dau_DsdLookupVarCache( p, pVars[v], pVars[u] ) ) continue; nVarsOld = nVars; nVars = Dau_DsdDecomposeDoubleVarsOne( p, pTruth, pVars, nVars, v, u ); if ( nVars == 0 ) { s_Times[1] += Abc_Clock() - clk; return 0; } if ( nVarsOld > nVars ) break; } if ( u >= 0 ) // found break; } if ( v == 0 ) // not found break; } s_Times[1] += Abc_Clock() - clk; return nVars; } // look for MUX-decomposable variable on top or at the bottom static inline int Dau_DsdDecomposeTripleVarsOuter( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v ) { extern int Dau_DsdDecomposeInt( Dau_Dsd_t * p, word * pTruth, int nVarsInit ); Dau_Dsd_t P1, * p1 = &P1; word pTtCof[2][DAU_MAX_WORD]; int nWords = Abc_TtWordNum(nVars); p1->fSplitPrime = 0; p1->fWriteTruth = p->fWriteTruth; // move this variable to the top ABC_SWAP( int, pVars[v], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, nVars, v, nVars-1 ); // cofactor w.r.t the last variable // tCof0 = Abc_Tt6Cofactor0( pTruth[0], nVars - 1 ); // tCof1 = Abc_Tt6Cofactor1( pTruth[0], nVars - 1 ); Abc_TtCofactor0p( pTtCof[0], pTruth, nWords, nVars - 1 ); Abc_TtCofactor1p( pTtCof[1], pTruth, nWords, nVars - 1 ); // compose the result Dau_DsdWriteString( p, "<" ); Dau_DsdWriteVar( p, pVars[nVars - 1], 0 ); // split decomposition Dau_DsdDecomposeInt( p1, pTtCof[1], nVars - 1 ); Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput ); p->nSizeNonDec = p1->nSizeNonDec; if ( p1->nSizeNonDec ) Abc_TtCopy( pTruth, pTtCof[1], Abc_TtWordNum(p1->nSizeNonDec), 0 ); // split decomposition Dau_DsdDecomposeInt( p1, pTtCof[0], nVars - 1 ); Dau_DsdTranslate( p, pVars, nVars - 1, p1->pOutput ); Dau_DsdWriteString( p, ">" ); p->nSizeNonDec = Abc_MaxInt( p->nSizeNonDec, p1->nSizeNonDec ); if ( p1->nSizeNonDec ) Abc_TtCopy( pTruth, pTtCof[0], Abc_TtWordNum(p1->nSizeNonDec), 0 ); return 0; } static inline int Dau_DsdDecomposeTripleVarsInner( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars, int v, unsigned uSupports ) { int nWords = Abc_TtWordNum(nVars); int iVar0 = Abc_TtSuppFindFirst( uSupports & (~uSupports >> 1) & 0x55555555 ) >> 1; int iVar1 = Abc_TtSuppFindFirst( ~uSupports & ( uSupports >> 1) & 0x55555555 ) >> 1; int fEqual0, fEqual1; // word tCof0 = Abc_Tt6Cofactor0( pTruth[0], v ); // word tCof1 = Abc_Tt6Cofactor1( pTruth[0], v ); // word C00 = Abc_Tt6Cofactor0( tCof0, iVar0 ); // word C01 = Abc_Tt6Cofactor1( tCof0, iVar0 ); // word C10 = Abc_Tt6Cofactor0( tCof1, iVar1 ); // word C11 = Abc_Tt6Cofactor1( tCof1, iVar1 ); // int fEqual0 = (C00 == C10) && (C01 == C11); // int fEqual1 = (C00 == C11) && (C01 == C10); word pTtCof[2][DAU_MAX_WORD]; word pTtFour[2][2][DAU_MAX_WORD]; Abc_TtCofactor0p( pTtCof[0], pTruth, nWords, v ); Abc_TtCofactor1p( pTtCof[1], pTruth, nWords, v ); Abc_TtCofactor0p( pTtFour[0][0], pTtCof[0], nWords, iVar0 ); Abc_TtCofactor1p( pTtFour[0][1], pTtCof[0], nWords, iVar0 ); Abc_TtCofactor0p( pTtFour[1][0], pTtCof[1], nWords, iVar1 ); Abc_TtCofactor1p( pTtFour[1][1], pTtCof[1], nWords, iVar1 ); fEqual0 = Abc_TtEqual(pTtFour[0][0], pTtFour[1][0], nWords) && Abc_TtEqual(pTtFour[0][1], pTtFour[1][1], nWords); fEqual1 = Abc_TtEqual(pTtFour[0][0], pTtFour[1][1], nWords) && Abc_TtEqual(pTtFour[0][1], pTtFour[1][0], nWords); if ( fEqual0 || fEqual1 ) { char pBuffer[10]; int VarId = pVars[iVar0]; // pTruth[0] = (s_Truths6[v] & C11) | (~s_Truths6[v] & C10); Abc_TtMux( pTruth, Dau_DsdTtElems()[v], pTtFour[1][1], pTtFour[1][0], nWords ); sprintf( pBuffer, "<%c%c%s%c>", 'a' + pVars[v], 'a' + pVars[iVar1], fEqual1 ? "!":"", 'a' + pVars[iVar0] ); pVars[v] = Dau_DsdAddVarDef( p, pBuffer ); // remove iVar1 ABC_SWAP( int, pVars[iVar1], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, nVars, iVar1, nVars-1 ); nVars--; // remove iVar0 iVar0 = Dau_DsdFindVarDef( pVars, nVars, VarId ); ABC_SWAP( int, pVars[iVar0], pVars[nVars-1] ); Abc_TtSwapVars( pTruth, nVars, iVar0, nVars-1 ); nVars--; // find the new var v = Dau_DsdFindVarDef( pVars, nVars, p->nVarsUsed-1 ); // remove single variables if possible if ( Dau_DsdDecomposeSingleVarOne( p, pTruth, pVars, nVars, v ) ) nVars = Dau_DsdDecomposeSingleVar( p, pTruth, pVars, --nVars ); return nVars; } return nVars; } int Dau_DsdDecomposeTripleVars( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { abctime clk = Abc_Clock(); while ( 1 ) { int v; // Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 ); printf( "\n" ); for ( v = nVars - 1; v >= 0; v-- ) { unsigned uSupports = Dau_DsdFindSupports( p, pTruth, pVars, nVars, v ); // Dau_DsdPrintSupports( uSupports, nVars ); if ( (uSupports & (uSupports >> 1) & 0x55555555) == 0 ) // non-overlapping supports return Dau_DsdDecomposeTripleVarsOuter( p, pTruth, pVars, nVars, v ); if ( Abc_TtSuppOnlyOne( uSupports & (~uSupports >> 1) & 0x55555555) && Abc_TtSuppOnlyOne(~uSupports & ( uSupports >> 1) & 0x55555555) ) // one unique variable in each cofactor { int nVarsNew = Dau_DsdDecomposeTripleVarsInner( p, pTruth, pVars, nVars, v, uSupports ); if ( nVarsNew == nVars ) continue; if ( nVarsNew == 0 ) { s_Times[2] += Abc_Clock() - clk; return 0; } nVars = Dau_DsdDecomposeDoubleVars( p, pTruth, pVars, nVarsNew ); if ( nVars == 0 ) { s_Times[2] += Abc_Clock() - clk; return 0; } break; } } if ( v == -1 ) { s_Times[2] += Abc_Clock() - clk; return nVars; } } assert( 0 ); return -1; } int Dau_DsdDecomposeInternal( Dau_Dsd_t * p, word * pTruth, int * pVars, int nVars ) { // decompose single variales on the output side nVars = Dau_DsdDecomposeSingleVar( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // decompose double variables on the input side nVars = Dau_DsdDecomposeDoubleVars( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // decompose MUX on the output/input side nVars = Dau_DsdDecomposeTripleVars( p, pTruth, pVars, nVars ); if ( nVars == 0 ) return 0; // write non-decomposable function return Dau_DsdWritePrime( p, pTruth, pVars, nVars ); } /**Function************************************************************* Synopsis [Fast DSD for truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdMinBase( word * pTruth, int nVars, int * pVarsNew ) { int v; for ( v = 0; v < nVars; v++ ) pVarsNew[v] = v; for ( v = nVars - 1; v >= 0; v-- ) { if ( Abc_TtHasVar( pTruth, nVars, v ) ) continue; Abc_TtSwapVars( pTruth, nVars, v, nVars-1 ); pVarsNew[v] = pVarsNew[--nVars]; } return nVars; } int Dau_DsdDecomposeInt( Dau_Dsd_t * p, word * pTruth, int nVarsInit ) { int Status = 0, nVars, pVars[16]; Dau_DsdInitialize( p, nVarsInit ); nVars = Dau_DsdMinBase( pTruth, nVarsInit, pVars ); assert( nVars > 0 && nVars <= nVarsInit ); if ( nVars == 1 ) Dau_DsdWriteVar( p, pVars[0], (int)(pTruth[0] & 1) ); else if ( nVars <= 6 ) Status = Dau_Dsd6DecomposeInternal( p, pTruth, pVars, nVars ); else Status = Dau_DsdDecomposeInternal( p, pTruth, pVars, nVars ); Dau_DsdFinalize( p ); return Status; } int Dau_DsdDecompose( word * pTruth, int nVarsInit, int fSplitPrime, int fWriteTruth, char * pRes ) { Dau_Dsd_t P, * p = &P; p->fSplitPrime = fSplitPrime; p->fWriteTruth = fWriteTruth; p->pVarLevels = NULL; p->nSizeNonDec = 0; if ( (pTruth[0] & 1) == 0 && Abc_TtIsConst0(pTruth, Abc_TtWordNum(nVarsInit)) ) { if ( pRes ) pRes[0] = '0', pRes[1] = 0; } else if ( (pTruth[0] & 1) && Abc_TtIsConst1(pTruth, Abc_TtWordNum(nVarsInit)) ) { if ( pRes ) pRes[0] = '1', pRes[1] = 0; } else { int Status = Dau_DsdDecomposeInt( p, pTruth, nVarsInit ); Dau_DsdRemoveBraces( p->pOutput, Dau_DsdComputeMatches(p->pOutput) ); if ( pRes ) strcpy( pRes, p->pOutput ); assert( fSplitPrime || Status != 1 ); if ( fSplitPrime && Status == 2 ) return -1; } // assert( p->nSizeNonDec == 0 ); return p->nSizeNonDec; } int Dau_DsdDecomposeLevel( word * pTruth, int nVarsInit, int fSplitPrime, int fWriteTruth, char * pRes, int * pVarLevels ) { Dau_Dsd_t P, * p = &P; p->fSplitPrime = fSplitPrime; p->fWriteTruth = fWriteTruth; p->pVarLevels = pVarLevels; p->nSizeNonDec = 0; if ( (pTruth[0] & 1) == 0 && Abc_TtIsConst0(pTruth, Abc_TtWordNum(nVarsInit)) ) { if ( pRes ) pRes[0] = '0', pRes[1] = 0; } else if ( (pTruth[0] & 1) && Abc_TtIsConst1(pTruth, Abc_TtWordNum(nVarsInit)) ) { if ( pRes ) pRes[0] = '1', pRes[1] = 0; } else { int Status = Dau_DsdDecomposeInt( p, pTruth, nVarsInit ); Dau_DsdRemoveBraces( p->pOutput, Dau_DsdComputeMatches(p->pOutput) ); if ( pRes ) strcpy( pRes, p->pOutput ); assert( fSplitPrime || Status != 1 ); if ( fSplitPrime && Status == 2 ) return -1; } // assert( p->nSizeNonDec == 0 ); return p->nSizeNonDec; } void Dau_DsdPrintFromTruthFile( FILE * pFile, word * pTruth, int nVarsInit ) { char pRes[DAU_MAX_STR]; word pTemp[DAU_MAX_WORD]; Abc_TtCopy( pTemp, pTruth, Abc_TtWordNum(nVarsInit), 0 ); Dau_DsdDecompose( pTemp, nVarsInit, 0, 1, pRes ); fprintf( pFile, "%s\n", pRes ); } void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit ) { char pRes[DAU_MAX_STR]; word pTemp[DAU_MAX_WORD]; Abc_TtCopy( pTemp, pTruth, Abc_TtWordNum(nVarsInit), 0 ); Dau_DsdDecompose( pTemp, nVarsInit, 0, 1, pRes ); fprintf( stdout, "%s\n", pRes ); } void Dau_DsdTest44() { char pRes[DAU_MAX_STR]; // char * pStr = "(!(!a)!(!fe))"; // char * pStr = "([acb])"; // char * pStr = "!(f!(b!c!(d[ea])))"; // char * pStr = "[!(a[be])!(c!df)]"; // char * pStr = "<(e)fd>"; // char * pStr = "[d8001{abef}c]"; char * pStr = "[dc{abef}]"; // char * pStr3; word t = Dau_Dsd6ToTruth( pStr ); // return; int nNonDec = Dau_DsdDecompose( &t, 6, 1, 1, pRes ); // Dau_DsdNormalize( pStr2 ); // Dau_DsdExtract( pStr, 2, 0 ); t = 0; nNonDec = 0; } void Dau_DsdTest888() { char pDsd[DAU_MAX_STR]; int nVars = 9; // char * pStr = "[(abc)(def)(ghi)]"; // char * pStr = "[a!b!(c!d[e(fg)hi])]"; // char * pStr = "[(abc)(def)]"; // char * pStr = "[(abc)(def)]"; // char * pStr = "[abcdefg]"; // char * pStr = "[(de[ghi])]"; char * pStr = "(())"; word * pTruth = Dau_DsdToTruth( pStr, 9 ); int i, Status; // Kit_DsdPrintFromTruth( (unsigned *)pTruth, 9 ); printf( "\n" ); /* for ( i = 0; i < 6; i++ ) { unsigned uSupp = Dau_Dsd6FindSupports( NULL, pTruth, NULL, 6, i ); Dau_DsdPrintSupports( uSupp, 6 ); } */ /* printf( "\n" ); for ( i = 0; i < nVars; i++ ) { unsigned uSupp = Dau_DsdFindSupports( NULL, pTruth, NULL, nVars, i ); Dau_DsdPrintSupports( uSupp, nVars ); } */ Status = Dau_DsdDecompose( pTruth, nVars, 0, 0, pDsd ); i = 0; } void Dau_DsdTest555() { int nVars = 10; int nWords = Abc_TtWordNum(nVars); char * pFileName = "_npn/npn/dsd10.txt"; FILE * pFile = fopen( pFileName, "rb" ); word Tru[2][DAU_MAX_WORD], * pTruth; char pBuffer[DAU_MAX_STR]; char pRes[DAU_MAX_STR]; int nSizeNonDec; int i, Counter = 0; abctime clk = Abc_Clock(), clkDec = 0, clk2; // return; while ( fgets( pBuffer, DAU_MAX_STR, pFile ) != NULL ) { char * pStr2 = pBuffer + strlen(pBuffer)-1; if ( *pStr2 == '\n' ) *pStr2-- = 0; if ( *pStr2 == '\r' ) *pStr2-- = 0; if ( pBuffer[0] == 'V' || pBuffer[0] == 0 ) continue; Counter++; for ( i = 0; i < 1; i++ ) { // Dau_DsdPermute( pBuffer ); pTruth = Dau_DsdToTruth( pBuffer[0] == '*' ? pBuffer + 1 : pBuffer, nVars ); Abc_TtCopy( Tru[0], pTruth, nWords, 0 ); Abc_TtCopy( Tru[1], pTruth, nWords, 0 ); clk2 = Abc_Clock(); nSizeNonDec = Dau_DsdDecompose( Tru[1], nVars, 0, 1, pRes ); clkDec += Abc_Clock() - clk2; Dau_DsdNormalize( pRes ); // pStr2 = Dau_DsdPerform( t ); nSizeNonDec = 0; assert( nSizeNonDec == 0 ); pTruth = Dau_DsdToTruth( pRes, nVars ); if ( !Abc_TtEqual( pTruth, Tru[0], nWords ) ) { // Kit_DsdPrintFromTruth( (unsigned *)&t, 6 ); // printf( " " ); // Kit_DsdPrintFromTruth( (unsigned *)&t2, 6 ); printf( "%s -> %s \n", pBuffer, pRes ); printf( "Verification failed.\n" ); } } } printf( "Finished trying %d decompositions. ", Counter ); Abc_PrintTime( 1, "Time", clkDec ); Abc_PrintTime( 1, "Total", Abc_Clock() - clk ); Abc_PrintTime( 1, "Time1", s_Times[0] ); Abc_PrintTime( 1, "Time2", s_Times[1] ); Abc_PrintTime( 1, "Time3", s_Times[2] ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauDsd2.c000066400000000000000000000520271300674244400230470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauDsd2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Disjoint-support decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauDsd2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #include DSD_MAX_VAR 12 #include DSD_MAX_WRD ((DSD_MAX_VAR > 6) ? (1 << (DSD_MAX_VAR-6)) : 1) typedef struct Dua_Obj_t_ Dua_Obj_t; struct Dua_Obj_t_ { int Type; // dec type (1=var; 2=and; 3=xor; 4=mux; 5=prime) int nFans; // fanin count char pFans[DSD_MAX_VAR]; // fanins }; typedef struct Dua_Dsd_t_ Dua_Dsd_t; struct Dua_Dsd_t_ { int nSupp; // original variables int nVars; // remaining variables int nWords; // largest non-dec prime int nObjs; // object count int iRoot; // the root of the tree Dua_Obj_t pObjs[DSD_MAX_VAR]; // objects word pTruth[DSD_MAX_WRD]; // original/current truth table }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Makes the fCof1-th cofactor of iVar the 0-th cofactor.] Description [Variable iVar becomes last varaible; others shift back. Only the 0-th cofactor is computed.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Abc_Tt6HalfUnShuffleVars( word t, int iVar, int fCof1 ) { static word Masks[6] = { ABC_CONST(0x5555555555555555), ABC_CONST(0x3333333333333333), ABC_CONST(0x0F0F0F0F0F0F0F0F), ABC_CONST(0x00FF00FF00FF00FF), ABC_CONST(0x0000FFFF0000FFFF), ABC_CONST(0x00000000FFFFFFFF) }; int v, s = (1 << iVar); t = (t >> (fCof1 ? 0 : s)) & Masks[iVar]; for ( v = iVar, s = (1 << v); v < 5; v++, s <<= 1 ) t = ((t >> s) | t) & Masks[v+1]; return t; } static inline void Abc_TtHalfUnShuffleVars( word * pTruth, int nVars, int iVar, int jVar, int fCof1 ) { int w, nWords = Abc_TtWordNum( nVars ); if ( iVar == jVar ) return; assert( iVar < jVar ); if ( iVar < 5 ) { for ( w = 0; w < nWords; w++ ) pTruth[w] = Abc_Tt6HalfUnShuffleVars( pTruth[w], iVar, fCof1 ); iVar = 5; } if ( jVar < 6 ) { for ( w = 0; w < nWords; w++ ) pTruth[w] = (pTruth[w] << 32) | pTruth[w]; return; } if ( iVar == 5 ) { unsigned * pTruthU = (unsigned *)pTruth; for ( w = 0; w < nWords; w += 2 ) pTruthU[w] = pTruthU[w+1]; iVar = 6; } { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); int j, jStep = Abc_TtWordNum(jVar); for ( ; pTruth < pLimit; pTruth += jStep ) for ( i = 0; i < jStep; i += iStep ) for ( j = 0; j < iStep; j++ ) pTruth[w++] = pTruth[iStep + i + j]; assert( w == (nWords >> 1) ); return; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dua_DsdInit( Dua_Dsd_t * pRes, word * pTruth, int nVars ) { int i; pRes->nSupp = nVars; pRes->nVars = nVars; pRes->nWords = Abc_TtWordNum( nVars ); pRes->nObjs = 1; pRes->iRoot = Abc_Var2Lit( 0, 0 ); pRes->pObjs[0].Type = 5; pRes->pObjs[0].nFans = nVars; for ( i = 0; i < nVars; i++ ) pRes->pObjs[0].pFans[i] = (char)Abc_Var2Lit( i, 0 ); memcpy( pRes->pTruth, pTruth, sizeof(word) * pRes->nWords ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // returns 1 if the truth table was complemented int Dua_DsdTryConst( word * pTruth, int nVars ) { if ( !(pTruth[0] & 1) ) return 0; Abc_TtNot( pTruth, Abc_TtWordNum(nVars) ); return 1; } int Dua_DsdTryVar( word * pTruth, int nWords, int iVar ) { int nWordsI = Abc_TtWordNum(iVar); word c0 = (iVar < 6) ? Abc_Tt6Cofactor0( pTruth[0], iVar ) : pTruth[0]; word c1 = (iVar < 6) ? Abc_Tt6Cofactor1( pTruth[0], iVar ) : pTruth[nWords]; if ( c0 != c1 ) { if ( c1 < c0 && c1 < ~c1 ) // flip { Abc_TtFlip( pTruth, nWords, iVar ); return 0; } if ( ~c1 < c0 && ~c1 < c1 ) // flip and compl { Abc_TtFlipNot( pTruth, nWords, iVar ); return 1; } } if ( iVar < 6 ) { word * pLimit = pTruth + nWords; for ( pTruth++; pTruth < pLimit; pTruth++ ) { c0 = Abc_Tt6Cofactor0( pTruth[0], iVar ); c1 = Abc_Tt6Cofactor1( pTruth[0], iVar ); if ( c0 == c1 ) continue; if ( c0 < c1 ) return 0; for ( ; pTruth < pLimit; pTruth++ ) pTruth[0] = Abc_Tt6Flip( pTruth[0], iVar ); return 0; } } else { for ( ; pTruth < pLimit; pTruth += (nWordsI << 1) ) for ( w = 0; w < nWordsI; w++ ) { c0 = pTruth[0]; c1 = pTruth[nWordsI]; if ( c0 == c1 ) continue; if ( c0 < c1 ) return 0; for ( ; pTruth < pLimit; pTruth += (nWordsI << 1) ) for ( ; w < nWordsI; w++ ) ABC_SWAP( word, pTruth[0], pTruth[nWordsI] ); return 0; } } assert( 0 ); return -1; } int Dua_DsdCheckCof0Const0( word * pTruth, int nWords, int iVar ) { if ( nWords == 1 ) return (pTruth[0] & s_Truths6Neg[iVar]) == 0; if ( iVar <= 5 ) { int w; for ( w = 0; w < nWords; w++ ) if ( (pTruth[w] & s_Truths6Neg[iVar]) ) return 0; return 1; } else // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pTruth < pLimit; pTruth += (iStep << 1) ) for ( i = 0; i < iStep; i++ ) if ( pTruth[i] ) return 0; return 1; } } int Dua_DsdCheckCofsEqualNot( word * pTruth, int nWords, int iVar ) { if ( nWords == 1 ) return (pTruth[0] & s_Truths6Neg[iVar]) == ((~pTruth[0] & s_Truths6[iVar]) >> (1 << iVar)); if ( iVar <= 5 ) { int w, shift = (1 << iVar); for ( w = 0; w < nWords; w++ ) if ( (pTruth[w] & s_Truths6Neg[iVar]) != ((~pTruth[w] & s_Truths6[iVar]) >> shift) ) return 0; return 1; } else // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pTruth < pLimit; pTruth += (iStep << 1) ) for ( i = 0; i < iStep; i++ ) if ( pTruth[i] != ~pTruth[i + iStep] ) return 0; return 1; } } int Dua_DsdOneVar( Dua_Dsd_t * pRes ) { int v, fCompl, fChange = 1; fCompl = Dua_DsdTryConst( pRes->pTruth, pRes->nWords ); while ( fChange && pRes->nVars > 2 ) { fChange = 0; for ( v = 0; v < pRes->nVars; v++ ) { fCompl ^= Dua_DsdTryVar( pRes->pTruth, pRes->nWords, v ); if ( Dua_DsdCheckCof0Const0( pRes->pTruth, pRes->nWords, v ) ) { fChange = 1; // record AND(v, F) } else if ( Dua_DsdCheckCofsEqualNot( pRes->pTruth, pRes->nWords, v ) ) { fChange = 1; // record XOR(v, F) } } } return fCompl; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dua_DsdTrySwap( word * pTruth, int nWords, int iVar ) { static word s_PMasks[5][3] = { { ABC_CONST(0x9999999999999999), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444) }, { ABC_CONST(0xC3C3C3C3C3C3C3C3), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030) }, { ABC_CONST(0xF00FF00FF00FF00F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00) }, { ABC_CONST(0xFF0000FFFF0000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000) }, { ABC_CONST(0xFFFF00000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000) } }; if ( iVar < 5 ) { int Shift = (1 << iVar); word c01, c10, * pLimit = pTruth + nWords; for ( ; pTruth < pLimit; pTruth++ ) { c01 = (pTruth[0] & s_PMasks[iVar][1]); c10 = (pTruth[0] & s_PMasks[iVar][2]) >> Shift; if ( c01 == c10 ) continue; if ( c01 < c10 ) return 0; pTruth[0] = (pTruth[0] & s_PMasks[iVar][0]) | ((pTruth[0] & s_PMasks[iVar][1]) << Shift) | ((pTruth[0] & s_PMasks[iVar][2]) >> Shift); return 1; } } else if ( iVar == 5 ) { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); for ( ; pTruthU < pLimitU; pTruthU += 4 ) { c01 = pTruthU[1]; c10 = pTruthU[2]; if ( c01 == c10 ) continue; if ( c01 < c10 ) return 0; for ( ; pTruthU < pLimitU; pTruthU += 4 ) ABC_SWAP( unsigned, pTruthU[1], pTruthU[2] ); return 1; } } else // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pTruth < pLimit; pTruth += 4*iStep ) for ( i = 0; i < iStep; i++ ) { c01 = pTruth[i + iStep]; c10 = pTruth[i + 2*iStep]; if ( c01 == c10 ) continue; if ( c01 < c10 ) return 0; for ( ; pTruth < pLimit; pTruth += 4*iStep ) for ( ; i < iStep; i++ ) ABC_SWAP( word, pTruth[1], pTruth[2] ); return 1; } } return 2; } int Dua_DsdCheckDecomp( word * pTruth, int nWords, int iVar ) { static word s_PMasks[5][4] = { { ABC_CONST(0x1111111111111111), ABC_CONST(0x2222222222222222), ABC_CONST(0x4444444444444444), ABC_CONST(0x8888888888888888) }, { ABC_CONST(0x0303030303030303), ABC_CONST(0x0C0C0C0C0C0C0C0C), ABC_CONST(0x3030303030303030), ABC_CONST(0xC0C0C0C0C0C0C0C0) }, { ABC_CONST(0x000F000F000F000F), ABC_CONST(0x00F000F000F000F0), ABC_CONST(0x0F000F000F000F00), ABC_CONST(0xF000F000F000F000) }, { ABC_CONST(0x000000FF000000FF), ABC_CONST(0x0000FF000000FF00), ABC_CONST(0x00FF000000FF0000), ABC_CONST(0xFF000000FF000000) }, { ABC_CONST(0x000000000000FFFF), ABC_CONST(0x00000000FFFF0000), ABC_CONST(0x0000FFFF00000000), ABC_CONST(0xFFFF000000000000) } }; int fC0eC1 = 1, fC0eC3 = 1; if ( iVar < 5 ) { int Shift = (1 << iVar); word c01, c10, * pLimit = pTruth + nWords; for ( ; pTruth < pLimit; pTruth++ ) { if ( fC0eC1 && (pTruth[0] & s_PMasks[iVar][0]) != ((pTruth[0] & s_PMasks[iVar][1]) >> Shift) ) fC0eC1 = 0; if ( fC0eC3 && (pTruth[0] & s_PMasks[iVar][0]) != ((pTruth[0] & s_PMasks[iVar][3]) >> (3*Shift)) ) fC0eC3 = 0; if ( !fC0eC1 && !fC0eC3 ) return 0; } } if ( iVar == 5 ) { unsigned * pTruthU = (unsigned *)pTruth; unsigned * pLimitU = (unsigned *)(pTruth + nWords); for ( ; pTruthU < pLimitU; pTruthU += 4 ) { if ( fC0eC1 && pTruthU[0] != pTruthU[1] ) fC0eC1 = 0; if ( fC0eC3 && pTruthU[0] != pTruthU[3] ) fC0eC3 = 0; if ( !fC0eC1 && !fC0eC3 ) return 0; } } else // if ( iVar > 5 ) { word * pLimit = pTruth + nWords; int i, iStep = Abc_TtWordNum(iVar); for ( ; pTruth < pLimit; pTruth += 4*iStep ) for ( i = 0; i < iStep; i++ ) { if ( fC0eC1 && pTruth[0] != pTruth[1] ) fC0eC1 = 0; if ( fC0eC3 && pTruth[0] != pTruth[3] ) fC0eC3 = 0; if ( !fC0eC1 && !fC0eC3 ) return 0; } } assert( fC0eC1 != fC0eC3 ); return fC0eC1 ? 1 : 2; } // returns 1 if decomposition detected int Dua_DsdTwoVars( Dua_Dsd_t * pRes ) { int v, RetValue, fChange = 1; while ( fChange && pRes->nVars > 2 ) { fChange = 0; for ( v = 0; v < pRes->nVars - 1; v++ ) { RetValue = Dua_DsdTrySwap( pRes->pTruth, pRes->nWords, v ); if ( RetValue == 1 ) fChange = 1; if ( RetValue != 2 ) continue; // vars are symmetric, check decomp RetValue = Dua_DsdCheckDecomp( pRes->pTruth, pRes->nWords, v ); if ( RetValue == 0 ) continue; if ( RetValue == 1 ) { fChange = 1; // record AND(a, b) } else { fChange = 1; // record XOR(a, b) } } } } /**Function************************************************************* Synopsis [Check DSD for bound-set [iVar; jVar).] Description [Return D-func if decomposable.] SideEffects [] SeeAlso [] ***********************************************************************/ word Dua_DsdRangeVars( word * pTruth, int nVars, int iVar, int jVar, int fPerform ) { int Part, nParts = 1 << (nVars - jVar); int Mint, nMints = 1 << (jVar - iVar); word MaskOne, MaskAll = 0; assert( jVar - iVar > 2 ); assert( jVar - iVar < 7 ); if ( iVar < 6 ) { int Shift = 6 - iVar, MaskF = (1 << Shift) - 1, iMint = 0; word MaskFF = (((word)1) << (1 << iVar)) - 1; word Cof0, Cof1, Value; for ( Part = 0; Part < nParts; Part++ ) { MaskOne = 0; Cof0 = Cof1 = ~(word)0; for ( Mint = 0; Mint < nMints; Mint++, iMint++ ) { Value = (pTruth[iMint>>Shift] >> ((iMint & MaskF)<>Shift] >> ((Mint & MaskF)<>Shift] ^= (Value ^ Cof0) << ((Mint & MaskF)<>Shift] >> ((Mint & MaskF)<>Shift] ^= (Value ^ Cof1) << ((Mint & MaskF)< 2 && iVar < nVars ); if ( iVar == 3 ) { unsigned char * pTruthP = (unsigned char *)pTruth, Dfunc = pTruthP[0]; for ( i = 1; i < nParts; i++ ) if ( pTruthP[i] != Dfunc && pTruthP[i] != ~Dfunc ) return 0; } else if ( iVar == 4 ) { unsigned short * pTruthP = (unsigned short *)pTruth, Dfunc = pTruthP[0]; for ( i = 1; i < nParts; i++ ) if ( pTruthP[i] != Dfunc && pTruthP[i] != ~Dfunc ) return 0; } else if ( iVar == 5 ) { unsigned int * pTruthP = (unsigned int *)pTruth, Dfunc = pTruthP[0]; for ( i = 1; i < nParts; i++ ) if ( pTruthP[i] != Dfunc && pTruthP[i] != ~Dfunc ) return 0; } else { int nStep = 1 << (6 - iVar); assert( iVar >= 6 ); for ( i = 1; i < nParts; i++ ) if ( !Abc_TtEqual(pTruth, pTruth + i * nStep, nStep) && !Abc_TtEqualNot(pTruth, pTruth + i * nStep, nStep) ) return 0; } return 1; } void Dua_DsdRangeVars0Derive( word * pTruth, int nVars, int iVar ) { int i, nParts = 1 << (nVars - iVar); assert( iVar > 2 && iVar < nVars ); if ( iVar == 3 ) { unsigned char * pTruthP = (unsigned char *)pTruth, Dfunc = pTruthP[0]; for ( i = 0; i < nParts; i++ ) if ( Abc_TtGetBit(pTruth, i) ^ (pTruthP[i] != Dfunc) ) Abc_TtXorBit(pTruth, i); } else if ( iVar == 4 ) { unsigned short * pTruthP = (unsigned short *)pTruth, Dfunc = pTruthP[0]; for ( i = 0; i < nParts; i++ ) if ( Abc_TtGetBit(pTruth, i) ^ (pTruthP[i] != Dfunc) ) Abc_TtXorBit(pTruth, i); } else if ( iVar == 5 ) { unsigned int * pTruthP = (unsigned int *)pTruth, Dfunc = pTruthP[0]; for ( i = 0; i < nParts; i++ ) if ( Abc_TtGetBit(pTruth, i) ^ (pTruthP[i] != Dfunc) ) Abc_TtXorBit(pTruth, i); } else { word Dfunc = pTruth[0]; assert( iVar == 6 ); for ( i = 0; i < nParts; i++ ) if ( Abc_TtGetBit(pTruth, i) ^ (pTruth[i] != Dfunc) ) Abc_TtXorBit(pTruth, i); } // stretch if ( nVars - iVar + 1 < 6 ) pTruth[0] = Abc_Tt6Stretch( pTruth[0], nVars - iVar + 1 < 6 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dua_DsdTest( word * pTruth, int nVar ) { Dua_Dsd_t Res, * pRes = &Res; Dua_DsdInit( pRes, pTruth, nVars ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauEnum.c000066400000000000000000000204701300674244400231540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauEnum.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Enumeration of decompositions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauEnum.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Dau_EnumLift( char * pName, int Shift ) { static char pBuffer[64]; char * pTemp; for ( pTemp = pBuffer; *pName; pTemp++, pName++ ) *pTemp = (*pName >= 'a' && *pName <= 'z') ? *pName + Shift : *pName; *pTemp = 0; return pBuffer; } char * Dau_EnumLift2( char * pName, int Shift ) { static char pBuffer[64]; char * pTemp; for ( pTemp = pBuffer; *pName; pTemp++, pName++ ) *pTemp = (*pName >= 'a' && *pName <= 'z') ? *pName + Shift : *pName; *pTemp = 0; return pBuffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_EnumCombineTwo( Vec_Ptr_t * vOne, int fStar, int fXor, char * pName1, char * pName2, int Shift2, int fCompl1, int fCompl2 ) { static char pBuffer[256]; pName2 = Dau_EnumLift( pName2, Shift2 ); sprintf( pBuffer, "%s%c%s%s%s%s%c", fStar?"*":"", fXor?'[':'(', fCompl1?"!":"", pName1[0] == '*' ? pName1 + 1 : pName1, fCompl2?"!":"", pName2[0] == '*' ? pName2 + 1 : pName2, fXor?']':')' ); // printf( "%s ", pBuffer ); Vec_PtrPush( vOne, Abc_UtilStrsav(pBuffer) ); } void Dau_EnumCombineThree( Vec_Ptr_t * vOne, int fStar, char * pNameC, char * pName1, char * pName2, int Shift1, int Shift2, int fComplC, int fCompl1, int fCompl2 ) { static char pBuffer[256]; pName1 = Dau_EnumLift( pName1, Shift1 ); pName2 = Dau_EnumLift2( pName2, Shift2 ); sprintf( pBuffer, "%s%c%s%s%s%s%s%s%c", fStar?"*":"", '<', fComplC?"!":"", pNameC[0] == '*' ? pNameC + 1 : pNameC, fCompl1?"!":"", pName1[0] == '*' ? pName1 + 1 : pName1, fCompl2?"!":"", pName2[0] == '*' ? pName2 + 1 : pName2, '>' ); // printf( "%s ", pBuffer ); Vec_PtrPush( vOne, Abc_UtilStrsav(pBuffer) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_EnumTestDump( Vec_Ptr_t * vSets, char * pFileName ) { FILE * pFile; Vec_Ptr_t * vOne; char * pName; int v, k; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) return; Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v ) { fprintf( pFile, "VARIABLE NUMBER %d:\n", v ); Vec_PtrForEachEntry( char *, vOne, pName, k ) fprintf( pFile, "%s\n", pName ); } fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_EnumTest() { int v, k, nVarMax = 10; Vec_Ptr_t * vSets; Vec_Ptr_t * vOne; char * pName; // 0 vars vSets = Vec_PtrAlloc( 16 ); Vec_PtrPush( vSets, Vec_PtrAlloc(0) ); // 1 vars vOne = Vec_PtrAlloc( 1 ); Vec_PtrPush( vOne, Abc_UtilStrsav("*a") ); Vec_PtrPush( vSets, vOne ); // 2+ vars for ( v = 2; v <= nVarMax; v++ ) { Vec_Ptr_t * vSetI, * vSetJ, * vSetK; char * pNameI, * pNameJ, * pNameK; int i, j, k, i1, j1, k1; vOne = Vec_PtrAlloc( 100 ); for ( i = 1; i < v; i++ ) for ( j = i; j < v; j++ ) { if ( i + j != v ) continue; vSetI = (Vec_Ptr_t *)Vec_PtrEntry( vSets, i ); vSetJ = (Vec_Ptr_t *)Vec_PtrEntry( vSets, j ); Vec_PtrForEachEntry( char *, vSetI, pNameI, i1 ) Vec_PtrForEachEntry( char *, vSetJ, pNameJ, j1 ) { // AND(a,b) Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 0, 0 ); // AND(!a,b) if ( pNameI[0] != '*' ) Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 1, 0 ); // AND(a,!b) if ( pNameJ[0] != '*' && !(i == j && i1 == j1) ) Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 0, 1 ); // AND(!a,!b) if ( pNameI[0] != '*' && pNameJ[0] != '*' ) Dau_EnumCombineTwo( vOne, 0, 0, pNameI, pNameJ, i, 1, 1 ); // XOR(a,b) Dau_EnumCombineTwo( vOne, pNameI[0] == '*' || pNameJ[0] == '*', 1, pNameI, pNameJ, i, 0, 0 ); } } for ( k = 1; k < v; k++ ) for ( i = 1; i < v; i++ ) for ( j = i; j < v; j++ ) { if ( k + i + j != v ) continue; vSetK = (Vec_Ptr_t *)Vec_PtrEntry( vSets, k ); vSetI = (Vec_Ptr_t *)Vec_PtrEntry( vSets, i ); vSetJ = (Vec_Ptr_t *)Vec_PtrEntry( vSets, j ); Vec_PtrForEachEntry( char *, vSetK, pNameK, k1 ) Vec_PtrForEachEntry( char *, vSetI, pNameI, i1 ) Vec_PtrForEachEntry( char *, vSetJ, pNameJ, j1 ) { int fStar = pNameI[0] == '*' && pNameJ[0] == '*'; // MUX(c,a,b) Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 0, 0 ); // MUX(c,!a,b) if ( pNameI[0] != '*' ) Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 1, 0 ); // MUX(c,a,!b) if ( pNameJ[0] != '*' && !(i == j && i1 == j1) ) Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 0, 0, 1 ); if ( pNameK[0] != '*' && !(i == j && i1 == j1) ) { // MUX(!c,a,b) Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 0, 0 ); // MUX(!c,!a,b) if ( pNameI[0] != '*' ) Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 1, 0 ); // MUX(!c,a,!b) if ( pNameJ[0] != '*' ) Dau_EnumCombineThree( vOne, fStar, pNameK, pNameI, pNameJ, k, k+i, 1, 0, 1 ); } } } Vec_PtrPush( vSets, vOne ); } Dau_EnumTestDump( vSets, "_npn/npn/dsd10.txt" ); Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v ) { printf( "VARIABLE NUMBER %d:\n", v ); Vec_PtrForEachEntry( char *, vOne, pName, k ) printf( "%s\n", pName ); if ( v == 4 ) break; } Vec_PtrForEachEntry( Vec_Ptr_t *, vSets, vOne, v ) { printf( "%d=%d ", v, Vec_PtrSize(vOne) ); Vec_PtrFreeFree( vOne ); } Vec_PtrFree( vSets ); printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauGia.c000066400000000000000000000447001300674244400227520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauGia.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Coverting DSD into GIA.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauGia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "aig/gia/gia.h" #include "misc/util/utilTruth.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 ); #define DAU_DSD_MAX_VAR 12 static int m_Calls = 0; static int m_NonDsd = 0; static int m_Non1Step = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives GIA for the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdToGiaCompose_rec( Gia_Man_t * pGia, word Func, int * pFanins, int nVars ) { int t0, t1; if ( Func == 0 ) return 0; if ( Func == ~(word)0 ) return 1; assert( nVars > 0 ); if ( --nVars == 0 ) { assert( Func == s_Truths6[0] || Func == s_Truths6Neg[0] ); return Abc_LitNotCond( pFanins[0], (int)(Func == s_Truths6Neg[0]) ); } if ( !Abc_Tt6HasVar(Func, nVars) ) return Dau_DsdToGiaCompose_rec( pGia, Func, pFanins, nVars ); t0 = Dau_DsdToGiaCompose_rec( pGia, Abc_Tt6Cofactor0(Func, nVars), pFanins, nVars ); t1 = Dau_DsdToGiaCompose_rec( pGia, Abc_Tt6Cofactor1(Func, nVars), pFanins, nVars ); if ( pGia->pMuxes ) return Gia_ManHashMuxReal( pGia, pFanins[nVars], t1, t0 ); else return Gia_ManHashMux( pGia, pFanins[nVars], t1, t0 ); } /**Function************************************************************* Synopsis [Derives GIA for the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DsdToGia2_rec( Gia_Man_t * pGia, char * pStr, char ** p, int * pMatches, int * pLits, Vec_Int_t * vCover ) { int fCompl = 0; if ( **p == '!' ) (*p)++, fCompl = 1; if ( **p >= 'a' && **p < 'a' + DAU_DSD_MAX_VAR ) // var return Abc_LitNotCond( pLits[**p - 'a'], fCompl ); if ( **p == '(' ) // and/or { char * q = pStr + pMatches[ *p - pStr ]; int Res = 1, Lit; assert( **p == '(' && *q == ')' ); for ( (*p)++; *p < q; (*p)++ ) { Lit = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits, vCover ); Res = Gia_ManHashAnd( pGia, Res, Lit ); } assert( *p == q ); return Abc_LitNotCond( Res, fCompl ); } if ( **p == '[' ) // xor { char * q = pStr + pMatches[ *p - pStr ]; int Res = 0, Lit; assert( **p == '[' && *q == ']' ); for ( (*p)++; *p < q; (*p)++ ) { Lit = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits, vCover ); if ( pGia->pMuxes ) Res = Gia_ManHashXorReal( pGia, Res, Lit ); else Res = Gia_ManHashXor( pGia, Res, Lit ); } assert( *p == q ); return Abc_LitNotCond( Res, fCompl ); } if ( **p == '<' ) // mux { int nVars = 0; int Temp[3], * pTemp = Temp, Res; int Fanins[DAU_DSD_MAX_VAR], * pLits2; char * pOld = *p; char * q = pStr + pMatches[ *p - pStr ]; // read fanins if ( *(q+1) == '{' ) { char * q2; *p = q+1; q2 = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q2 == '}' ); for ( nVars = 0, (*p)++; *p < q2; (*p)++, nVars++ ) Fanins[nVars] = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits, vCover ); assert( *p == q2 ); pLits2 = Fanins; } else pLits2 = pLits; // read MUX *p = pOld; q = pStr + pMatches[ *p - pStr ]; assert( **p == '<' && *q == '>' ); // verify internal variables if ( nVars ) for ( ; pOld < q; pOld++ ) if ( *pOld >= 'a' && *pOld <= 'z' ) assert( *pOld - 'a' < nVars ); // derive MUX components for ( (*p)++; *p < q; (*p)++ ) *pTemp++ = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits2, vCover ); assert( pTemp == Temp + 3 ); assert( *p == q ); if ( *(q+1) == '{' ) // and/or { char * q = pStr + pMatches[ ++(*p) - pStr ]; assert( **p == '{' && *q == '}' ); *p = q; } if ( pGia->pMuxes ) Res = Gia_ManHashMuxReal( pGia, Temp[0], Temp[1], Temp[2] ); else Res = Gia_ManHashMux( pGia, Temp[0], Temp[1], Temp[2] ); return Abc_LitNotCond( Res, fCompl ); } if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { Vec_Int_t vLeaves; char * q; word pFunc[DAU_DSD_MAX_VAR > 6 ? (1 << (DAU_DSD_MAX_VAR-6)) : 1]; int Fanins[DAU_DSD_MAX_VAR], Res; int i, nVars = Abc_TtReadHex( pFunc, *p ); *p += Abc_TtHexDigitNum( nVars ); q = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q == '}' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) Fanins[i] = Dau_DsdToGia2_rec( pGia, pStr, p, pMatches, pLits, vCover ); assert( i == nVars ); assert( *p == q ); // Res = Dau_DsdToGia2Compose_rec( pGia, Func, Fanins, nVars ); vLeaves.nCap = nVars; vLeaves.nSize = nVars; vLeaves.pArray = Fanins; Res = Kit_TruthToGia( pGia, (unsigned *)pFunc, nVars, vCover, &vLeaves, 1 ); m_Non1Step++; return Abc_LitNotCond( Res, fCompl ); } assert( 0 ); return 0; } int Dau_DsdToGia2( Gia_Man_t * pGia, char * p, int * pLits, Vec_Int_t * vCover ) { int Res; if ( *p == '0' && *(p+1) == 0 ) Res = 0; else if ( *p == '1' && *(p+1) == 0 ) Res = 1; else Res = Dau_DsdToGia2_rec( pGia, p, &p, Dau_DsdComputeMatches(p), pLits, vCover ); assert( *++p == 0 ); return Res; } /**Function************************************************************* Synopsis [Derives GIA for the DSD formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdAddToArray( Gia_Man_t * pGia, int * pFans, int nFans, int iFan ) { int i; pFans[nFans] = iFan; if ( nFans == 0 ) return; for ( i = nFans; i > 0; i-- ) { if ( Gia_ObjLevelId(pGia, Abc_Lit2Var(pFans[i])) <= Gia_ObjLevelId(pGia, Abc_Lit2Var(pFans[i-1])) ) return; ABC_SWAP( int, pFans[i], pFans[i-1] ); } } int Dau_DsdBalance( Gia_Man_t * pGia, int * pFans, int nFans, int fAnd ) { Gia_Obj_t * pObj; int iFan0, iFan1, iFan; if ( nFans == 1 ) return pFans[0]; assert( nFans > 1 ); iFan0 = pFans[--nFans]; iFan1 = pFans[--nFans]; if ( fAnd ) iFan = Gia_ManHashAnd( pGia, iFan0, iFan1 ); else if ( pGia->pMuxes ) iFan = Gia_ManHashXorReal( pGia, iFan0, iFan1 ); else iFan = Gia_ManHashXor( pGia, iFan0, iFan1 ); pObj = Gia_ManObj(pGia, Abc_Lit2Var(iFan)); if ( Gia_ObjIsAnd(pObj) ) { if ( fAnd ) Gia_ObjSetAndLevel( pGia, pObj ); else if ( pGia->pMuxes ) Gia_ObjSetXorLevel( pGia, pObj ); else { if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) Gia_ObjSetAndLevel( pGia, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) ) Gia_ObjSetAndLevel( pGia, Gia_ObjFanin1(pObj) ); Gia_ObjSetAndLevel( pGia, pObj ); } } Dau_DsdAddToArray( pGia, pFans, nFans++, iFan ); return Dau_DsdBalance( pGia, pFans, nFans, fAnd ); } int Dau_DsdToGia_rec( Gia_Man_t * pGia, char * pStr, char ** p, int * pMatches, int * pLits, Vec_Int_t * vCover ) { int fCompl = 0; if ( **p == '!' ) (*p)++, fCompl = 1; if ( **p >= 'a' && **p < 'a' + DAU_DSD_MAX_VAR ) // var return Abc_LitNotCond( pLits[**p - 'a'], fCompl ); if ( **p == '(' ) // and/or { char * q = pStr + pMatches[ *p - pStr ]; int pFans[DAU_DSD_MAX_VAR], nFans = 0, Fan; assert( **p == '(' && *q == ')' ); for ( (*p)++; *p < q; (*p)++ ) { Fan = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits, vCover ); Dau_DsdAddToArray( pGia, pFans, nFans++, Fan ); } Fan = Dau_DsdBalance( pGia, pFans, nFans, 1 ); assert( *p == q ); return Abc_LitNotCond( Fan, fCompl ); } if ( **p == '[' ) // xor { char * q = pStr + pMatches[ *p - pStr ]; int pFans[DAU_DSD_MAX_VAR], nFans = 0, Fan; assert( **p == '[' && *q == ']' ); for ( (*p)++; *p < q; (*p)++ ) { Fan = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits, vCover ); Dau_DsdAddToArray( pGia, pFans, nFans++, Fan ); } Fan = Dau_DsdBalance( pGia, pFans, nFans, 0 ); assert( *p == q ); return Abc_LitNotCond( Fan, fCompl ); } if ( **p == '<' ) // mux { Gia_Obj_t * pObj; int nVars = 0; int Temp[3], * pTemp = Temp, Res; int Fanins[DAU_DSD_MAX_VAR], * pLits2; char * pOld = *p; char * q = pStr + pMatches[ *p - pStr ]; // read fanins if ( *(q+1) == '{' ) { char * q2; *p = q+1; q2 = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q2 == '}' ); for ( nVars = 0, (*p)++; *p < q2; (*p)++, nVars++ ) Fanins[nVars] = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits, vCover ); assert( *p == q2 ); pLits2 = Fanins; } else pLits2 = pLits; // read MUX *p = pOld; q = pStr + pMatches[ *p - pStr ]; assert( **p == '<' && *q == '>' ); // verify internal variables if ( nVars ) for ( ; pOld < q; pOld++ ) if ( *pOld >= 'a' && *pOld <= 'z' ) assert( *pOld - 'a' < nVars ); // derive MUX components for ( (*p)++; *p < q; (*p)++ ) *pTemp++ = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits2, vCover ); assert( pTemp == Temp + 3 ); assert( *p == q ); if ( *(q+1) == '{' ) // and/or { char * q = pStr + pMatches[ ++(*p) - pStr ]; assert( **p == '{' && *q == '}' ); *p = q; } if ( pGia->pMuxes ) Res = Gia_ManHashMuxReal( pGia, Temp[0], Temp[1], Temp[2] ); else Res = Gia_ManHashMux( pGia, Temp[0], Temp[1], Temp[2] ); pObj = Gia_ManObj(pGia, Abc_Lit2Var(Res)); if ( Gia_ObjIsAnd(pObj) ) { if ( pGia->pMuxes ) Gia_ObjSetMuxLevel( pGia, pObj ); else { if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) Gia_ObjSetAndLevel( pGia, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) ) Gia_ObjSetAndLevel( pGia, Gia_ObjFanin1(pObj) ); Gia_ObjSetAndLevel( pGia, pObj ); } } return Abc_LitNotCond( Res, fCompl ); } if ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { Vec_Int_t vLeaves; char * q; word pFunc[DAU_DSD_MAX_VAR > 6 ? (1 << (DAU_DSD_MAX_VAR-6)) : 1]; int Fanins[DAU_DSD_MAX_VAR], Res, nObjOld; int i, nVars = Abc_TtReadHex( pFunc, *p ); *p += Abc_TtHexDigitNum( nVars ); q = pStr + pMatches[ *p - pStr ]; assert( **p == '{' && *q == '}' ); for ( i = 0, (*p)++; *p < q; (*p)++, i++ ) Fanins[i] = Dau_DsdToGia_rec( pGia, pStr, p, pMatches, pLits, vCover ); assert( i == nVars ); assert( *p == q ); vLeaves.nCap = nVars; vLeaves.nSize = nVars; vLeaves.pArray = Fanins; nObjOld = Gia_ManObjNum(pGia); Res = Kit_TruthToGia( pGia, (unsigned *)pFunc, nVars, vCover, &vLeaves, 1 ); // assert( nVars <= 6 ); // Res = Dau_DsdToGiaCompose_rec( pGia, pFunc[0], Fanins, nVars ); for ( i = nObjOld; i < Gia_ManObjNum(pGia); i++ ) Gia_ObjSetGateLevel( pGia, Gia_ManObj(pGia, i) ); m_Non1Step++; return Abc_LitNotCond( Res, fCompl ); } assert( 0 ); return 0; } int Dau_DsdToGia( Gia_Man_t * pGia, char * p, int * pLits, Vec_Int_t * vCover ) { int Res; if ( *p == '0' && *(p+1) == 0 ) Res = 0; else if ( *p == '1' && *(p+1) == 0 ) Res = 1; else Res = Dau_DsdToGia_rec( pGia, p, &p, Dau_DsdComputeMatches(p), pLits, vCover ); assert( *++p == 0 ); return Res; } /**Function************************************************************* Synopsis [Convert TT to GIA via DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dsm_ManTruthToGia( void * p, word * pTruth, Vec_Int_t * vLeaves, Vec_Int_t * vCover ) { int fUseMuxes = 0; int fDelayBalance = 1; Gia_Man_t * pGia = (Gia_Man_t *)p; int nSizeNonDec; char pDsd[1000]; m_Calls++; assert( Vec_IntSize(vLeaves) <= DAU_DSD_MAX_VAR ); // collect delay information if ( fDelayBalance && fUseMuxes ) { int i, iLit, pVarLevels[DAU_DSD_MAX_VAR]; Vec_IntForEachEntry( vLeaves, iLit, i ) pVarLevels[i] = Gia_ObjLevelId( pGia, Abc_Lit2Var(iLit) ); nSizeNonDec = Dau_DsdDecomposeLevel( pTruth, Vec_IntSize(vLeaves), fUseMuxes, 1, pDsd, pVarLevels ); } else nSizeNonDec = Dau_DsdDecompose( pTruth, Vec_IntSize(vLeaves), fUseMuxes, 1, pDsd ); if ( nSizeNonDec ) m_NonDsd++; // printf( "%s\n", pDsd ); if ( fDelayBalance ) return Dau_DsdToGia( pGia, pDsd, Vec_IntArray(vLeaves), vCover ); else return Dau_DsdToGia2( pGia, pDsd, Vec_IntArray(vLeaves), vCover ); } /**Function************************************************************* Synopsis [Convert TT to GIA via DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dsm_ManReportStats() { printf( "Calls = %d. NonDSD = %d. Non1Step = %d.\n", m_Calls, m_NonDsd, m_Non1Step ); m_Calls = m_NonDsd = m_Non1Step = 0; } /**Function************************************************************* Synopsis [Performs structural hashing on the LUT functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Dsm_ManDeriveGia( void * pGia, int fUseMuxes ) { Gia_Man_t * p = (Gia_Man_t *)pGia; Gia_Man_t * pNew, * pTemp; Vec_Int_t * vCover, * vLeaves; Gia_Obj_t * pObj; int k, i, iLut, iVar; word * pTruth; assert( Gia_ManHasMapping(p) ); // create new manager pNew = Gia_ManStart( 6*Gia_ManObjNum(p)/5 + 100 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->vLevels = Vec_IntStart( 6*Gia_ManObjNum(p)/5 + 100 ); if ( fUseMuxes ) pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); // map primary inputs Gia_ManFillValue(p); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // iterate through nodes used in the mapping vLeaves = Vec_IntAlloc( 16 ); vCover = Vec_IntAlloc( 1 << 16 ); Gia_ManHashStart( pNew ); Gia_ObjComputeTruthTableStart( p, Gia_ManLutSizeMax(p) ); Gia_ManForEachAnd( p, pObj, iLut ) { if ( Gia_ObjIsBuf(pObj) ) { pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); continue; } if ( !Gia_ObjIsLut(p, iLut) ) continue; // collect leaves Vec_IntClear( vLeaves ); Gia_LutForEachFanin( p, iLut, iVar, k ) Vec_IntPush( vLeaves, iVar ); pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, iLut), vLeaves ); // collect incoming literals Vec_IntClear( vLeaves ); Gia_LutForEachFanin( p, iLut, iVar, k ) Vec_IntPush( vLeaves, Gia_ManObj(p, iVar)->Value ); Gia_ManObj(p, iLut)->Value = Dsm_ManTruthToGia( pNew, pTruth, vLeaves, vCover ); } Gia_ObjComputeTruthTableStop( p ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Vec_IntFree( vLeaves ); Vec_IntFree( vCover ); /* Gia_ManForEachAnd( pNew, pObj, i ) { int iLev = Gia_ObjLevelId(pNew, i); int iLev0 = Gia_ObjLevelId(pNew, Gia_ObjFaninId0(pObj, i)); int iLev1 = Gia_ObjLevelId(pNew, Gia_ObjFaninId1(pObj, i)); assert( iLev == 1 + Abc_MaxInt(iLev0, iLev1) ); } */ // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauInt.h000066400000000000000000000041641300674244400230110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Interal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__DAU_INT__h #define ABC__DAU_INT__h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "misc/vec/vec.h" #include "dau.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== zzz.c ==========================================================*/ ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauMerge.c000066400000000000000000000622431300674244400233130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauMerge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Enumeration of decompositions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Substitution storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ typedef struct Dau_Sto_t_ Dau_Sto_t; struct Dau_Sto_t_ { int iVarUsed; // counter of used variables char pOutput[DAU_MAX_STR]; // storage for reduced function char * pPosOutput; // place in the output char pStore[DAU_MAX_VAR][DAU_MAX_STR]; // storage for definitions char * pPosStore[DAU_MAX_VAR]; // place in the store }; static inline void Dau_DsdMergeStoreClean( Dau_Sto_t * pS, int nShared ) { int i; pS->iVarUsed = nShared; for ( i = 0; i < DAU_MAX_VAR; i++ ) pS->pStore[i][0] = 0; } static inline void Dau_DsdMergeStoreCleanOutput( Dau_Sto_t * pS ) { pS->pPosOutput = pS->pOutput; } static inline void Dau_DsdMergeStoreAddToOutput( Dau_Sto_t * pS, char * pBeg, char * pEnd ) { while ( pBeg < pEnd ) *pS->pPosOutput++ = *pBeg++; } static inline void Dau_DsdMergeStoreAddToOutputChar( Dau_Sto_t * pS, char c ) { *pS->pPosOutput++ = c; } static inline int Dau_DsdMergeStoreStartDef( Dau_Sto_t * pS, char c ) { pS->pPosStore[pS->iVarUsed] = pS->pStore[pS->iVarUsed]; if (c) *pS->pPosStore[pS->iVarUsed]++ = c; return pS->iVarUsed++; } static inline void Dau_DsdMergeStoreAddToDef( Dau_Sto_t * pS, int New, char * pBeg, char * pEnd ) { while ( pBeg < pEnd ) *pS->pPosStore[New]++ = *pBeg++; } static inline void Dau_DsdMergeStoreAddToDefChar( Dau_Sto_t * pS, int New, char c ) { *pS->pPosStore[New]++ = c; } static inline void Dau_DsdMergeStoreStopDef( Dau_Sto_t * pS, int New, char c ) { if (c) *pS->pPosStore[New]++ = c; *pS->pPosStore[New]++ = 0; } static inline char Dau_DsdMergeStoreCreateDef( Dau_Sto_t * pS, char * pBeg, char * pEnd ) { int New = Dau_DsdMergeStoreStartDef( pS, 0 ); Dau_DsdMergeStoreAddToDef( pS, New, pBeg, pEnd ); Dau_DsdMergeStoreStopDef( pS, New, 0 ); return New; } static inline void Dau_DsdMergeStorePrintDefs( Dau_Sto_t * pS ) { int i; for ( i = 0; i < DAU_MAX_VAR; i++ ) if ( pS->pStore[i][0] ) printf( "%c = %s\n", 'a' + i, pS->pStore[i] ); } /**Function************************************************************* Synopsis [Creates local copy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dau_DsdMergeCopy( char * pDsd, int fCompl, char * pRes ) { if ( fCompl && pDsd[0] == '!' ) fCompl = 0, pDsd++; if ( Dau_DsdIsConst(pDsd) ) // constant pRes[0] = (fCompl ? (char)((int)pDsd[0] ^ 1) : pDsd[0]), pRes[1] = 0; else sprintf( pRes, "%s%s", fCompl ? "!" : "", pDsd ); } /**Function************************************************************* Synopsis [Replaces variables according to the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dau_DsdMergeReplace( char * pDsd, int * pMatches, int * pMap ) { int i; for ( i = 0; pDsd[i]; i++ ) { // skip non-DSD block if ( pDsd[i] == '<' && pDsd[pMatches[i]+1] == '{' ) i = pMatches[i] + 1; if ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') ) while ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') ) i++; // detect variables if ( pDsd[i] >= 'a' && pDsd[i] <= 'z' ) pDsd[i] = 'a' + pMap[ pDsd[i] - 'a' ]; } } static inline void Dau_DsdMergeMatches( char * pDsd, int * pMatches ) { int pNested[DAU_MAX_VAR]; int i, nNested = 0; for ( i = 0; pDsd[i]; i++ ) { pMatches[i] = 0; if ( pDsd[i] == '(' || pDsd[i] == '[' || pDsd[i] == '<' || pDsd[i] == '{' ) pNested[nNested++] = i; else if ( pDsd[i] == ')' || pDsd[i] == ']' || pDsd[i] == '>' || pDsd[i] == '}' ) pMatches[pNested[--nNested]] = i; assert( nNested < DAU_MAX_VAR ); } assert( nNested == 0 ); } static inline void Dau_DsdMergeVarPres( char * pDsd, int * pMatches, int * pPres, int Mask ) { int i; for ( i = 0; pDsd[i]; i++ ) { // skip non-DSD block if ( pDsd[i] == '<' && pDsd[pMatches[i]+1] == '{' ) i = pMatches[i] + 1; if ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') ) while ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') ) i++; // skip non-variables if ( !(pDsd[i] >= 'a' && pDsd[i] <= 'z') ) continue; // record the mask assert( pDsd[i]-'a' < DAU_MAX_VAR ); pPres[pDsd[i]-'a'] |= Mask; } } static inline int Dau_DsdMergeCountShared( int * pPres, int Mask ) { int i, Counter = 0; for ( i = 0; i < DAU_MAX_VAR; i++ ) Counter += (pPres[i] == Mask); return Counter; } static inline int Dau_DsdMergeFindShared( char * pDsd0, char * pDsd1, int * pMatches0, int * pMatches1, int * pVarPres ) { memset( pVarPres, 0, sizeof(int)*DAU_MAX_VAR ); Dau_DsdMergeVarPres( pDsd0, pMatches0, pVarPres, 1 ); Dau_DsdMergeVarPres( pDsd1, pMatches1, pVarPres, 2 ); return Dau_DsdMergeCountShared( pVarPres, 3 ); } static inline int Dau_DsdMergeCreateMaps( int * pVarPres, int nShared, int * pOld2New, int * pNew2Old ) { int i, Counter = 0, Counter2 = nShared; for ( i = 0; i < DAU_MAX_VAR; i++ ) { if ( pVarPres[i] == 0 ) continue; if ( pVarPres[i] == 3 ) { pOld2New[i] = Counter; pNew2Old[Counter] = i; Counter++; continue; } assert( pVarPres[i] == 1 || pVarPres[i] == 2 ); pOld2New[i] = Counter2; pNew2Old[Counter2] = i; Counter2++; } return Counter2; } static inline void Dau_DsdMergeInlineDefinitions( char * pDsd, int * pMatches, Dau_Sto_t * pS, char * pRes, int nShared ) { int i; char * pDef; char * pBegin = pRes; for ( i = 0; pDsd[i]; i++ ) { // skip non-DSD block if ( pDsd[i] == '<' && pDsd[pMatches[i]+1] == '{' ) { assert( pDsd[pMatches[i]] == '>' ); for ( ; i <= pMatches[i]; i++ ) *pRes++ = pDsd[i]; } if ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') ) while ( (pDsd[i] >= 'A' && pDsd[i] <= 'F') || (pDsd[i] >= '0' && pDsd[i] <= '9') ) *pRes++ = pDsd[i++]; // detect variables if ( !(pDsd[i] >= 'a' && pDsd[i] <= 'z') || (pDsd[i] - 'a' < nShared) ) { *pRes++ = pDsd[i]; continue; } // inline definition assert( pDsd[i]-'a' < DAU_MAX_STR ); for ( pDef = pS->pStore[pDsd[i]-'a']; *pDef; pDef++ ) *pRes++ = *pDef; } *pRes++ = 0; assert( pRes - pBegin < DAU_MAX_STR ); } /**Function************************************************************* Synopsis [Computes independence status for each opening parenthesis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dau_DsdMergePrintWithStatus( char * p, int * pStatus ) { int i; printf( "%s\n", p ); for ( i = 0; p[i]; i++ ) if ( !(p[i] == '(' || p[i] == '[' || p[i] == '<' || p[i] == '{' || (p[i] >= 'a' && p[i] <= 'z')) ) printf( " " ); else if ( pStatus[i] >= 0 ) printf( "%d", pStatus[i] ); else printf( "-" ); printf( "\n" ); } int Dau_DsdMergeStatus_rec( char * pStr, char ** p, int * pMatches, int nShared, int * pStatus ) { // none pure // 1 one pure // 2 two or more pure // 3 all pure if ( **p == '!' ) { pStatus[*p - pStr] = -1; (*p)++; } while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { pStatus[*p - pStr] = -1; (*p)++; } if ( **p == '<' ) { char * q = pStr + pMatches[ *p - pStr ]; if ( *(q+1) == '{' ) { char * pTemp = *p; *p = q+1; for ( ; pTemp < q+1; pTemp++ ) pStatus[pTemp - pStr] = -1; } } if ( **p >= 'a' && **p <= 'z' ) // var return pStatus[*p - pStr] = (**p - 'a' < nShared) ? 0 : 3; if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor { int Status, nPure = 0, nTotal = 0; char * pOld = *p; char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) { Status = Dau_DsdMergeStatus_rec( pStr, p, pMatches, nShared, pStatus ); nPure += (Status == 3); nTotal++; } assert( *p == q ); assert( nTotal > 1 ); if ( nPure == 0 ) Status = 0; else if ( nPure == 1 ) Status = 1; else if ( nPure < nTotal ) Status = 2; else if ( nPure == nTotal ) Status = 3; else assert( 0 ); return (pStatus[pOld - pStr] = Status); } assert( 0 ); return 0; } static inline int Dau_DsdMergeStatus( char * pDsd, int * pMatches, int nShared, int * pStatus ) { return Dau_DsdMergeStatus_rec( pDsd, &pDsd, pMatches, nShared, pStatus ); } /**Function************************************************************* Synopsis [Extracts the formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Dau_DsdMergeGetStatus( char * pBeg, char * pStr, int * pMatches, int * pStatus ) { if ( *pBeg == '!' ) pBeg++; while ( (*pBeg >= 'A' && *pBeg <= 'F') || (*pBeg >= '0' && *pBeg <= '9') ) pBeg++; if ( *pBeg == '<' ) { char * q = pStr + pMatches[pBeg - pStr]; if ( *(q+1) == '{' ) pBeg = q+1; } return pStatus[pBeg - pStr]; } void Dau_DsdMergeSubstitute_rec( Dau_Sto_t * pS, char * pStr, char ** p, int * pMatches, int * pStatus, int fWrite ) { // assert( **p != '!' ); if ( **p == '!' ) { if ( fWrite ) Dau_DsdMergeStoreAddToOutputChar( pS, **p ); (*p)++; } while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) { if ( fWrite ) Dau_DsdMergeStoreAddToOutputChar( pS, **p ); (*p)++; } if ( **p == '<' ) { char * q = pStr + pMatches[ *p - pStr ]; if ( *(q+1) == '{' ) { char * pTemp = *p; *p = q+1; if ( fWrite ) for ( ; pTemp < q+1; pTemp++ ) Dau_DsdMergeStoreAddToOutputChar( pS, *pTemp ); } } if ( **p >= 'a' && **p <= 'z' ) // var { if ( fWrite ) Dau_DsdMergeStoreAddToOutputChar( pS, **p ); return; } if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor { int New, StatusFan, Status = pStatus[*p - pStr]; char * pBeg, * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); if ( !fWrite ) { assert( Status == 3 ); *p = q; return; } assert( Status != 3 ); if ( Status == 0 ) // none pure { Dau_DsdMergeStoreAddToOutputChar( pS, **p ); for ( (*p)++; *p < q; (*p)++ ) { if ( **p == '!' ) { Dau_DsdMergeStoreAddToOutputChar( pS, '!' ); (*p)++; } Dau_DsdMergeSubstitute_rec( pS, pStr, p, pMatches, pStatus, 1 ); } Dau_DsdMergeStoreAddToOutputChar( pS, **p ); assert( *p == q ); return; } if ( Status == 1 || **p == '<' || **p == '{' ) // 1 pure { Dau_DsdMergeStoreAddToOutputChar( pS, **p ); for ( (*p)++; *p < q; (*p)++ ) { if ( **p == '!' ) { Dau_DsdMergeStoreAddToOutputChar( pS, '!' ); (*p)++; } pBeg = *p; StatusFan = Dau_DsdMergeGetStatus( pBeg, pStr, pMatches, pStatus ); Dau_DsdMergeSubstitute_rec( pS, pStr, p, pMatches, pStatus, StatusFan != 3 ); if ( StatusFan == 3 ) { int New = Dau_DsdMergeStoreCreateDef( pS, pBeg, *p+1 ); Dau_DsdMergeStoreAddToOutputChar( pS, (char)('a' + New) ); } } Dau_DsdMergeStoreAddToOutputChar( pS, **p ); assert( *p == q ); return; } if ( Status == 2 ) { // add more than one defs Dau_DsdMergeStoreAddToOutputChar( pS, **p ); New = Dau_DsdMergeStoreStartDef( pS, **p ); for ( (*p)++; *p < q; (*p)++ ) { pBeg = *p; StatusFan = Dau_DsdMergeGetStatus( pBeg, pStr, pMatches, pStatus ); if ( **p == '!' ) { if ( StatusFan != 3 ) Dau_DsdMergeStoreAddToOutputChar( pS, '!' ); else Dau_DsdMergeStoreAddToDefChar( pS, New, '!' ); (*p)++; pBeg++; } Dau_DsdMergeSubstitute_rec( pS, pStr, p, pMatches, pStatus, StatusFan != 3 ); if ( StatusFan == 3 ) Dau_DsdMergeStoreAddToDef( pS, New, pBeg, *p+1 ); } Dau_DsdMergeStoreStopDef( pS, New, *q ); Dau_DsdMergeStoreAddToOutputChar( pS, (char)('a' + New) ); Dau_DsdMergeStoreAddToOutputChar( pS, **p ); return; } assert( 0 ); return; } assert( 0 ); } static inline void Dau_DsdMergeSubstitute( Dau_Sto_t * pS, char * pDsd, int * pMatches, int * pStatus ) { /* int fCompl = 0; if ( pDsd[0] == '!' ) { Dau_DsdMergeStoreAddToOutputChar( pS, '!' ); pDsd++; fCompl = 1; } */ Dau_DsdMergeSubstitute_rec( pS, pDsd, &pDsd, pMatches, pStatus, 1 ); Dau_DsdMergeStoreAddToOutputChar( pS, 0 ); } /**Function************************************************************* Synopsis [Removes braces.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdRemoveBraces_rec( char * pStr, char ** p, int * pMatches ) { if ( **p == '!' ) (*p)++; while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) (*p)++; if ( **p == '<' ) { char * q = pStr + pMatches[*p - pStr]; if ( *(q+1) == '{' ) *p = q+1; } if ( **p >= 'a' && **p <= 'z' ) // var return; if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) { char * q = pStr + pMatches[ *p - pStr ]; assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) { int fCompl = (**p == '!'); char * pBeg = fCompl ? *p + 1 : *p; Dau_DsdRemoveBraces_rec( pStr, p, pMatches ); if ( (!fCompl && *pBeg == '(' && *q == ')') || (*pBeg == '[' && *q == ']') ) { assert( **p == ')' || **p == ']' ); *pBeg = **p = ' '; } } assert( *p == q ); return; } assert( 0 ); } void Dau_DsdRemoveBraces( char * pDsd, int * pMatches ) { char * q, * p = pDsd; if ( pDsd[1] == 0 ) return; Dau_DsdRemoveBraces_rec( pDsd, &pDsd, pMatches ); for ( q = p; *p; p++ ) if ( *p != ' ' ) { if ( *p == '!' && *(q-1) == '!' && p != q ) { q--; continue; } *q++ = *p; } *q = 0; } abctime s_TimeComp[4] = {0}; /**Function************************************************************* Synopsis [Performs merging of two DSD formulas.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Dau_DsdMerge( char * pDsd0i, int * pPerm0, char * pDsd1i, int * pPerm1, int fCompl0, int fCompl1, int nVars ) { int fVerbose = 0; int fCheck = 0; static int Counter = 0; static char pRes[DAU_MAX_STR]; char pDsd0[DAU_MAX_STR]; char pDsd1[DAU_MAX_STR]; int pMatches0[DAU_MAX_STR]; int pMatches1[DAU_MAX_STR]; int pVarPres[DAU_MAX_VAR]; int pOld2New[DAU_MAX_VAR]; int pNew2Old[DAU_MAX_VAR]; int pStatus0[DAU_MAX_STR]; int pStatus1[DAU_MAX_STR]; int pMatches[DAU_MAX_STR]; int nVarsShared, nVarsTotal; Dau_Sto_t S, * pS = &S; word * pTruth, * pt = NULL, * pt0 = NULL, * pt1 = NULL; word pParts[3][DAU_MAX_WORD]; int Status; abctime clk = Abc_Clock(); Counter++; // create local copies Dau_DsdMergeCopy( pDsd0i, fCompl0, pDsd0 ); Dau_DsdMergeCopy( pDsd1i, fCompl1, pDsd1 ); if ( fVerbose ) printf( "\nAfter copying:\n" ); if ( fVerbose ) printf( "%s\n", pDsd0 ); if ( fVerbose ) printf( "%s\n", pDsd1 ); // handle constants if ( Dau_DsdIsConst(pDsd0) || Dau_DsdIsConst(pDsd1) ) { if ( Dau_DsdIsConst0(pDsd0) ) strcpy( pRes, pDsd0 ); else if ( Dau_DsdIsConst1(pDsd0) ) strcpy( pRes, pDsd1 ); else if ( Dau_DsdIsConst0(pDsd1) ) strcpy( pRes, pDsd1 ); else if ( Dau_DsdIsConst1(pDsd1) ) strcpy( pRes, pDsd0 ); else assert( 0 ); return pRes; } // compute matches Dau_DsdMergeMatches( pDsd0, pMatches0 ); Dau_DsdMergeMatches( pDsd1, pMatches1 ); // implement permutation Dau_DsdMergeReplace( pDsd0, pMatches0, pPerm0 ); Dau_DsdMergeReplace( pDsd1, pMatches1, pPerm1 ); if ( fVerbose ) printf( "After replacement:\n" ); if ( fVerbose ) printf( "%s\n", pDsd0 ); if ( fVerbose ) printf( "%s\n", pDsd1 ); if ( fCheck ) { pt0 = Dau_DsdToTruth( pDsd0, nVars ); Abc_TtCopy( pParts[0], pt0, Abc_TtWordNum(nVars), 0 ); } if ( fCheck ) { pt1 = Dau_DsdToTruth( pDsd1, nVars ); Abc_TtCopy( pParts[1], pt1, Abc_TtWordNum(nVars), 0 ); Abc_TtAnd( pParts[2], pParts[0], pParts[1], Abc_TtWordNum(nVars), 0 ); } // find shared varaiables nVarsShared = Dau_DsdMergeFindShared(pDsd0, pDsd1, pMatches0, pMatches1, pVarPres); if ( nVarsShared == 0 ) { sprintf( pRes, "(%s%s)", pDsd0, pDsd1 ); if ( fVerbose ) printf( "Disjoint:\n" ); if ( fVerbose ) printf( "%s\n", pRes ); Dau_DsdMergeMatches( pRes, pMatches ); Dau_DsdRemoveBraces( pRes, pMatches ); Dau_DsdNormalize( pRes ); if ( fVerbose ) printf( "Normalized:\n" ); if ( fVerbose ) printf( "%s\n", pRes ); s_TimeComp[0] += Abc_Clock() - clk; return pRes; } s_TimeComp[3] += Abc_Clock() - clk; // create variable mapping nVarsTotal = Dau_DsdMergeCreateMaps( pVarPres, nVarsShared, pOld2New, pNew2Old ); // perform variable replacement Dau_DsdMergeReplace( pDsd0, pMatches0, pOld2New ); Dau_DsdMergeReplace( pDsd1, pMatches1, pOld2New ); // find uniqueness status Dau_DsdMergeStatus( pDsd0, pMatches0, nVarsShared, pStatus0 ); Dau_DsdMergeStatus( pDsd1, pMatches1, nVarsShared, pStatus1 ); if ( fVerbose ) printf( "Individual status:\n" ); if ( fVerbose ) Dau_DsdMergePrintWithStatus( pDsd0, pStatus0 ); if ( fVerbose ) Dau_DsdMergePrintWithStatus( pDsd1, pStatus1 ); // prepare storage Dau_DsdMergeStoreClean( pS, nVarsShared ); // perform substitutions Dau_DsdMergeStoreCleanOutput( pS ); Dau_DsdMergeSubstitute( pS, pDsd0, pMatches0, pStatus0 ); strcpy( pDsd0, pS->pOutput ); if ( fVerbose ) printf( "Substitutions:\n" ); if ( fVerbose ) printf( "%s\n", pDsd0 ); // perform substitutions Dau_DsdMergeStoreCleanOutput( pS ); Dau_DsdMergeSubstitute( pS, pDsd1, pMatches1, pStatus1 ); strcpy( pDsd1, pS->pOutput ); if ( fVerbose ) printf( "%s\n", pDsd1 ); if ( fVerbose ) Dau_DsdMergeStorePrintDefs( pS ); // create new function // assert( nVarsTotal <= 6 ); sprintf( pS->pOutput, "(%s%s)", pDsd0, pDsd1 ); pTruth = Dau_DsdToTruth( pS->pOutput, nVarsTotal ); Status = Dau_DsdDecompose( pTruth, nVarsTotal, 0, 1, pS->pOutput ); //printf( "%d ", Status ); if ( Status == -1 ) // did not find 1-step DSD return NULL; // if ( Status > 6 ) // non-DSD part is too large // return NULL; if ( Dau_DsdIsConst(pS->pOutput) ) { strcpy( pRes, pS->pOutput ); return pRes; } if ( fVerbose ) printf( "Decomposition:\n" ); if ( fVerbose ) printf( "%s\n", pS->pOutput ); // substitute definitions Dau_DsdMergeMatches( pS->pOutput, pMatches ); Dau_DsdMergeInlineDefinitions( pS->pOutput, pMatches, pS, pRes, nVarsShared ); if ( fVerbose ) printf( "Inlining:\n" ); if ( fVerbose ) printf( "%s\n", pRes ); // perform variable replacement Dau_DsdMergeMatches( pRes, pMatches ); Dau_DsdMergeReplace( pRes, pMatches, pNew2Old ); Dau_DsdRemoveBraces( pRes, pMatches ); if ( fVerbose ) printf( "Replaced:\n" ); if ( fVerbose ) printf( "%s\n", pRes ); Dau_DsdNormalize( pRes ); if ( fVerbose ) printf( "Normalized:\n" ); if ( fVerbose ) printf( "%s\n", pRes ); if ( fCheck ) { pt = Dau_DsdToTruth( pRes, nVars ); if ( !Abc_TtEqual( pParts[2], pt, Abc_TtWordNum(nVars) ) ) printf( "Dau_DsdMerge(): Verification failed!\n" ); } if ( Status == 0 ) s_TimeComp[1] += Abc_Clock() - clk; else s_TimeComp[2] += Abc_Clock() - clk; return pRes; } void Dau_DsdTest66() { int Perm0[DAU_MAX_VAR] = { 0, 1, 2, 3, 4, 5 }; // int pMatches[DAU_MAX_STR]; // int pStatus[DAU_MAX_STR]; // char * pStr = "(!(!a)!(!fe))"; // char * pStr = "([acb])"; // char * pStr = "!(f!(b!c!(d[ea])))"; char * pStr = "[!(a[be])!(c!df)]"; // char * pStr = "<(e)fd>"; // char * pStr = "[d8001{abef}c]"; // char * pStr1 = "(abc)"; // char * pStr2 = "[adf]"; // char * pStr1 = "(!abce)"; // char * pStr2 = "[adf!b]"; // char * pStr1 = "(!abc)"; // char * pStr2 = "[ab]"; // char * pStr1 = "[d81{abe}c]"; // char * pStr1 = "[d{abe}c]"; // char * pStr1 = "[d81{abe}c]"; // char * pStr1 = "[d(a[be])c]"; // char * pStr2 = "(df)"; // char * pStr1 = "(abf)"; // char * pStr2 = "(a[(bc)(fde)])"; // char * pStr1 = "8001{abc[ef]}"; // char * pStr2 = "(abe)"; char * pStr1 = "(!(ab)de)"; char * pStr2 = "(!(ac)f)"; char * pRes; word t = Dau_Dsd6ToTruth( pStr ); return; // pStr2 = Dau_DsdDecompose( &t, 6, 0, NULL ); // Dau_DsdNormalize( pStr2 ); // Dau_DsdMergeMatches( pStr, pMatches ); // Dau_DsdMergeStatus( pStr, pMatches, 2, pStatus ); // Dau_DsdMergePrintWithStatus( pStr, pStatus ); pRes = Dau_DsdMerge( pStr1, Perm0, pStr2, Perm0, 0, 0, 6 ); t = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauNonDsd.c000066400000000000000000000767371300674244400234560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauNonDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauNonDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks decomposability with given variable set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DecCheckSetTop5( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp ) { word Cof[2][64], Value; word MaskFF = (((word)1) << (1 << nVarsF)) - 1; int ShiftF = 6 - nVarsF, MaskF = (1 << ShiftF) - 1; int pVarsS[16], pVarsB[16]; int nMints = (1 << nVarsB); int nMintsB = (1 <<(nVarsB-nVarsS)); int nMintsS = (1 << nVarsS); int s, b, v, m, Mint, MintB, MintS; assert( nVars == nVarsB + nVarsF ); assert( nVars <= 16 ); assert( nVarsS <= 6 ); assert( nVarsF >= 1 && nVarsF <= 5 ); // collect bound/shared variables for ( s = b = v = 0; v < nVarsB; v++ ) if ( (uMaskS >> v) & 1 ) pVarsB[v] = -1, pVarsS[v] = s++; else pVarsS[v] = -1, pVarsB[v] = b++; assert( s == nVarsS ); assert( b == nVarsB-nVarsS ); // clean minterm storage for ( s = 0; s < nMintsS; s++ ) Cof[0][s] = Cof[1][s] = ~(word)0; // iterate through bound set minters for ( MintS = MintB = Mint = m = 0; m < nMints; m++ ) { // find minterm value Value = (p[Mint>>ShiftF] >> ((Mint&MaskF)<>6] |= (((word)1)<<(iMintB & 63)); } } else return 0; // find next minterm v = pSched[m]; Mint ^= (1 << v); if ( (uMaskS >> v) & 1 ) // shared variable MintS ^= (1 << pVarsS[v]); else MintB ^= (1 << pVarsB[v]); } // create composition function if ( pComp ) { for ( s = 0; s < nMintsS; s++ ) { pComp[s>>ShiftF] |= (Cof[0][s] << ((s&MaskF) << nVarsF)); if ( ~Cof[1][s] ) pComp[(s+nMintsS)>>ShiftF] |= (Cof[1][s] << (((s+nMintsS)&MaskF) << nVarsF)); else pComp[(s+nMintsS)>>ShiftF] |= (Cof[0][s] << (((s+nMintsS)&MaskF) << nVarsF)); } if ( nVarsF + nVarsS + 1 < 6 ) pComp[0] = Abc_Tt6Stretch( pComp[0], nVarsF + nVarsS + 1 ); } if ( pDec && nVarsB < 6 ) pDec[0] = Abc_Tt6Stretch( pDec[0], nVarsB ); return 1; } int Dau_DecCheckSetTop6( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp ) { word * Cof[2][64]; int nWordsF = Abc_TtWordNum(nVarsF); int pVarsS[16], pVarsB[16]; int nMints = (1 << nVarsB); int nMintsB = (1 <<(nVarsB-nVarsS)); int nMintsS = (1 << nVarsS); int s, b, v, m, Mint, MintB, MintS; assert( nVars == nVarsB + nVarsF ); assert( nVars <= 16 ); assert( nVarsS <= 6 ); assert( nVarsF >= 6 ); // collect bound/shared variables for ( s = b = v = 0; v < nVarsB; v++ ) if ( (uMaskS >> v) & 1 ) pVarsB[v] = -1, pVarsS[v] = s++; else pVarsS[v] = -1, pVarsB[v] = b++; assert( s == nVarsS ); assert( b == nVarsB-nVarsS ); // clean minterm storage for ( s = 0; s < nMintsS; s++ ) Cof[0][s] = Cof[1][s] = NULL; // iterate through bound set minters for ( MintS = MintB = Mint = m = 0; m < nMints; m++ ) { // check if this cof already appeared if ( !Cof[0][MintS] || !memcmp(Cof[0][MintS], p + Mint * nWordsF, sizeof(word) * nWordsF) ) Cof[0][MintS] = p + Mint * nWordsF; else if ( !Cof[1][MintS] || !memcmp(Cof[1][MintS], p + Mint * nWordsF, sizeof(word) * nWordsF) ) { Cof[1][MintS] = p + Mint * nWordsF; if ( pDec ) { int iMintB = MintS * nMintsB + MintB; pDec[iMintB>>6] |= (((word)1)<<(iMintB & 63)); } } else return 0; // find next minterm v = pSched[m]; Mint ^= (1 << v); if ( (uMaskS >> v) & 1 ) // shared variable MintS ^= (1 << pVarsS[v]); else MintB ^= (1 << pVarsB[v]); } // create composition function if ( pComp ) { for ( s = 0; s < nMintsS; s++ ) { memcpy( pComp + s * nWordsF, Cof[0][s], sizeof(word) * nWordsF ); if ( Cof[1][s] ) memcpy( pComp + (s+nMintsS) * nWordsF, Cof[1][s], sizeof(word) * nWordsF ); else memcpy( pComp + (s+nMintsS) * nWordsF, Cof[0][s], sizeof(word) * nWordsF ); } } if ( pDec && nVarsB < 6 ) pDec[0] = Abc_Tt6Stretch( pDec[0], nVarsB ); return 1; } static inline int Dau_DecCheckSetTop( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int uMaskS, int * pSched, word * pDec, word * pComp ) { if ( nVarsF < 6 ) return Dau_DecCheckSetTop5( p, nVars, nVarsF, nVarsB, nVarsS, uMaskS, pSched, pDec, pComp ); else return Dau_DecCheckSetTop6( p, nVars, nVarsF, nVarsB, nVarsS, uMaskS, pSched, pDec, pComp ); } /**Function************************************************************* Synopsis [Checks decomposability with given BS variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dau_DecGetMinterm( word * p, int g, int nVarsS, int uMaskAll ) { int m, c, v; for ( m = c = v = 0; v < nVarsS; v++ ) if ( !((uMaskAll >> v) & 1) ) // not shared bound set variable { if ( (g >> v) & 1 ) m |= (1 << c); c++; } assert( c >= 2 ); p[m>>6] |= (((word)1)<<(m & 63)); } static inline int Dau_DecCheckSet5( word * p, int nVars, int nVarsF, int uMaskAll, int uMaskValue, word * pCof0, word * pCof1, word * pDec ) { int fFound0 = 0, fFound1 = 0; int g, gMax = (1 << (nVars - nVarsF)); int Shift = 6 - nVarsF, Mask = (1 << Shift) - 1; word Mask2 = (((word)1) << (1 << nVarsF)) - 1; word Cof0 = 0, Cof1 = 0, Value; assert( nVarsF >= 1 && nVarsF <= 5 ); if ( pDec ) *pDec = 0; for ( g = 0; g < gMax; g++ ) if ( (g & uMaskAll) == uMaskValue ) // this minterm g matches shared variable minterm uMaskValue { Value = (p[g>>Shift] >> ((g&Mask)<= 6 && nVarsF <= nVars - 2 ); if ( pDec ) *pDec = 0; for ( g = 0; g < gMax; g++ ) if ( (g & uMaskAll) == uMaskValue ) { if ( !fFound0 ) Cof0 = p + g * nWords, fFound0 = 1; else if ( !memcmp(Cof0, p + g * nWords, sizeof(word) * nWords) ) continue; else if ( !fFound1 ) { Cof1 = p + g * nWords, fFound1 = 1; if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll ); } else if ( !memcmp(Cof1, p + g * nWords, sizeof(word) * nWords) ) { if ( pDec ) Dau_DecGetMinterm( pDec, g, nVars-nVarsF, uMaskAll ); continue; } else return 0; } if ( pCof0 ) { assert( fFound0 ); Cof1 = fFound1 ? Cof1 : Cof0; memcpy( pCof0, Cof0, sizeof(word) * nWords ); memcpy( pCof1, Cof1, sizeof(word) * nWords ); } return 1; } static inline int Dau_DecCheckSetAny( word * p, int nVars, int nVarsF, int uMaskAll, int uMaskValue, word * pCof0, word * pCof1, word * pDec ) { assert( nVarsF >= 1 && nVarsF <= nVars - 2 ); if ( nVarsF < 6 ) return Dau_DecCheckSet5( p, nVars, nVarsF, uMaskAll, uMaskValue, pCof0, pCof1, pDec ); else return Dau_DecCheckSet6( p, nVars, nVarsF, uMaskAll, uMaskValue, pCof0, pCof1, pDec ); } int Dau_DecCheckSetTopOld( word * p, int nVars, int nVarsF, int nVarsB, int nVarsS, int maskS, word ** pCof0, word ** pCof1, word ** pDec ) { int i, pVarsS[16]; int v, m, mMax = (1 << nVarsS), uMaskValue; assert( nVars >= 3 && nVars <= 16 ); assert( nVars == nVarsF + nVarsB ); assert( nVarsF >= 1 && nVarsF <= nVars - 2 ); assert( nVarsB >= 2 && nVarsB <= nVars - 1 ); assert( nVarsS >= 0 && nVarsS <= nVarsB - 2 ); if ( nVarsS == 0 ) return Dau_DecCheckSetAny( p, nVars, nVarsF, 0, 0, pCof0? pCof0[0] : 0, pCof1? pCof1[0] : 0, pDec? pDec[0] : 0 ); // collect shared variables assert( maskS > 0 && maskS < (1 << nVarsB) ); for ( i = 0, v = 0; v < nVarsB; v++ ) if ( (maskS >> v) & 1 ) pVarsS[i++] = v; assert( i == nVarsS ); // go through shared set minterms for ( m = 0; m < mMax; m++ ) { // generate share set mask uMaskValue = 0; for ( v = 0; v < nVarsS; v++ ) if ( (m >> v) & 1 ) uMaskValue |= (1 << pVarsS[v]); assert( (maskS & uMaskValue) == uMaskValue ); // check decomposition if ( !Dau_DecCheckSetAny( p, nVars, nVarsF, maskS, uMaskValue, pCof0? pCof0[m] : 0, pCof1? pCof1[m] : 0, pDec? pDec[m] : 0 ) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Variable sets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Dau_DecCreateSet( int * pVarsB, int sizeB, int maskS ) { unsigned uSet = 0; int v; for ( v = 0; v < sizeB; v++ ) { uSet |= (1 << (pVarsB[v] << 1)); if ( (maskS >> v) & 1 ) uSet |= (1 << ((pVarsB[v] << 1)+1)); } return uSet; } static inline int Dau_DecSetHas01( unsigned Mask ) { return (Mask & ((~Mask) >> 1) & 0x55555555); } static inline int Dau_DecSetIsContained( Vec_Int_t * vSets, unsigned New ) // Old=abcD contains New=abcDE // Old=abcD contains New=abCD { unsigned Old; int i, Entry; Vec_IntForEachEntry( vSets, Entry, i ) { Old = (unsigned)Entry; if ( (Old & ~New) == 0 && !Dau_DecSetHas01(~Old & New)) return 1; } return 0; } void Dau_DecSortSet( unsigned set, int nVars, int * pnUnique, int * pnShared, int * pnFree ) { int v; int nUnique = 0, nShared = 0, nFree = 0; for ( v = 0; v < nVars; v++ ) { int Value = ((set >> (v << 1)) & 3); if ( Value == 1 ) nUnique++; else if ( Value == 3 ) nShared++; else if ( Value == 0 ) nFree++; else assert( 0 ); } *pnUnique = nUnique; *pnShared = nShared; *pnFree = nFree; } void Dau_DecPrintSet( unsigned set, int nVars, int fNewLine ) { int v, Counter = 0; int nUnique = 0, nShared = 0, nFree = 0; Dau_DecSortSet( set, nVars, &nUnique, &nShared, &nFree ); printf( "S =%2d D =%2d C =%2d ", nShared, nUnique+nShared, nShared+nFree+1 ); printf( "x=" ); for ( v = 0; v < nVars; v++ ) { int Value = ((set >> (v << 1)) & 3); if ( Value == 1 ) printf( "%c", 'a' + v ), Counter++; else if ( Value == 3 ) printf( "%c", 'A' + v ), Counter++; else assert( Value == 0 ); } printf( " y=x" ); for ( v = 0; v < nVars; v++ ) { int Value = ((set >> (v << 1)) & 3); if ( Value == 0 ) printf( "%c", 'a' + v ), Counter++; else if ( Value == 3 ) printf( "%c", 'A' + v ), Counter++; } for ( ; Counter < 15; Counter++ ) printf( " " ); if ( fNewLine ) printf( "\n" ); } unsigned Dau_DecReadSet( char * pStr ) { unsigned uSet = 0; int v; for ( v = 0; pStr[v]; v++ ) { if ( pStr[v] >= 'a' && pStr[v] <= 'z' ) uSet |= (1 << ((pStr[v] - 'a') << 1)); else if ( pStr[v] >= 'A' && pStr[v] <= 'Z' ) uSet |= (1 << ((pStr[v] - 'a') << 1)) | (1 << (((pStr[v] - 'a') << 1)+1)); else break; } return uSet; } void Dau_DecPrintSets( Vec_Int_t * vSets, int nVars ) { int i, Entry; printf( "The %d-variable set family contains %d sets:\n", nVars, Vec_IntSize(vSets) ); Vec_IntForEachEntry( vSets, Entry, i ) Dau_DecPrintSet( (unsigned)Entry, nVars, 1 ); printf( "\n" ); } /**Function************************************************************* Synopsis [Find decomposable bound-sets of the given function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DecMoveFreeToLSB( word * p, int nVars, int * V2P, int * P2V, int maskB, int sizeB ) { int v, c = 0; for ( v = 0; v < nVars; v++ ) if ( !((maskB >> v) & 1) ) Abc_TtMoveVar( p, nVars, V2P, P2V, v, c++ ); assert( c == nVars - sizeB ); } Vec_Int_t * Dau_DecFindSets_int( word * pInit, int nVars, int * pSched[16] ) { Vec_Int_t * vSets = Vec_IntAlloc( 32 ); int V2P[16], P2V[16], pVarsB[16]; int Limit = (1 << nVars); int c, v, sizeB, sizeS, maskB, maskS; unsigned setMixed; word p[1<<10]; memcpy( p, pInit, sizeof(word) * Abc_TtWordNum(nVars) ); for ( v = 0; v < nVars; v++ ) assert( Abc_TtHasVar( p, nVars, v ) ); // initialize permutation for ( v = 0; v < nVars; v++ ) V2P[v] = P2V[v] = v; // iterate through bound sets of each size in increasing order for ( sizeB = 2; sizeB < nVars; sizeB++ ) // bound set size for ( maskB = 0; maskB < Limit; maskB++ ) // bound set if ( Abc_TtBitCount16(maskB) == sizeB ) { // permute variables to have bound set on top Dau_DecMoveFreeToLSB( p, nVars, V2P, P2V, maskB, sizeB ); // collect bound set vars on levels nVars-sizeB to nVars-1 for ( c = 0; c < sizeB; c++ ) pVarsB[c] = P2V[nVars-sizeB+c]; // check disjoint // if ( Dau_DecCheckSetTopOld(p, nVars, nVars-sizeB, sizeB, 0, 0, NULL, NULL, NULL) ) if ( Dau_DecCheckSetTop(p, nVars, nVars-sizeB, sizeB, 0, 0, pSched[sizeB], NULL, NULL) ) { Vec_IntPush( vSets, Dau_DecCreateSet(pVarsB, sizeB, 0) ); continue; } if ( sizeB == 2 ) continue; // iterate through shared sets of each size in the increasing order for ( sizeS = 1; sizeS <= sizeB - 2; sizeS++ ) // shared set size if ( sizeS <= 3 ) // sizeS = 1; for ( maskS = 0; maskS < (1 << sizeB); maskS++ ) // shared set if ( Abc_TtBitCount16(maskS) == sizeS ) { setMixed = Dau_DecCreateSet( pVarsB, sizeB, maskS ); // printf( "Considering %10d ", setMixed ); // Dau_DecPrintSet( setMixed, nVars ); // check if it exists if ( Dau_DecSetIsContained(vSets, setMixed) ) continue; // check if it can be added // if ( Dau_DecCheckSetTopOld(p, nVars, nVars-sizeB, sizeB, sizeS, maskS, NULL, NULL, NULL) ) if ( Dau_DecCheckSetTop(p, nVars, nVars-sizeB, sizeB, sizeS, maskS, pSched[sizeB], NULL, NULL) ) Vec_IntPush( vSets, setMixed ); } } return vSets; } Vec_Int_t * Dau_DecFindSets( word * pInit, int nVars ) { Vec_Int_t * vSets; int v, * pSched[16] = {NULL}; for ( v = 2; v < nVars; v++ ) pSched[v] = Extra_GreyCodeSchedule( v ); vSets = Dau_DecFindSets_int( pInit, nVars, pSched ); for ( v = 2; v < nVars; v++ ) ABC_FREE( pSched[v] ); return vSets; } void Dau_DecFindSetsTest2() { Vec_Int_t * vSets; word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]); word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]); word t = (~s_Truths6[0] & a0) | (s_Truths6[0] & a1); // word t = ABC_CONST(0x7EFFFFFFFFFFFF7E); // and(gam1,gam2) // word t = ABC_CONST(0xB0F0BBFFB0F0BAFE); // some funct // word t = ABC_CONST(0x2B0228022B022802); // 5-var non-dec0x0F7700000F770000 // word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e) // word t = ABC_CONST(0x7F00000000000000); // (!(abc)def) int nVars = 5; vSets = Dau_DecFindSets( &t, nVars ); Dau_DecPrintSets( vSets, nVars ); Vec_IntFree( vSets ); } /**Function************************************************************* Synopsis [Replaces variables in the string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DecVarReplace( char * pStr, int * pPerm, int nVars ) { int v; for ( v = 0; pStr[v]; v++ ) if ( pStr[v] >= 'a' && pStr[v] <= 'z' ) { assert( pStr[v] - 'a' < nVars ); pStr[v] = 'a' + pPerm[pStr[v] - 'a']; } } /**Function************************************************************* Synopsis [Decomposes with the given bound-set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DecDecomposeSet( word * pInit, int nVars, unsigned uSet, word * pComp, word * pDec, int * pPermC, int * pPermD, int * pnVarsC, int * pnVarsD, int * pnVarsS ) { word p[1<<13], Cof[64], Cof0[64], Cof1[64], Decs[64]; word * pCof0[64], * pCof1[64], * pDecs[64], MintC, MintD; int V2P[16], P2V[16], pVarsU[16], pVarsS[16], pVarsF[16]; int nVarsU = 0, nVarsS = 0, nVarsF = 0; int nWords = Abc_TtWordNum(nVars); int v, d, c, Status, nDecs; assert( nVars <= 16 ); for ( v = 0; v < nVars; v++ ) V2P[v] = P2V[v] = v; memcpy( p, pInit, sizeof(word) * nWords ); // sort variables for ( v = 0; v < nVars; v++ ) { int Value = (uSet >> (v<<1)) & 3; if ( Value == 0 ) pVarsF[nVarsF++] = v; else if ( Value == 1 ) pVarsU[nVarsU++] = v; else if ( Value == 3 ) pVarsS[nVarsS++] = v; else assert(0); } assert( nVarsS >= 0 && nVarsS <= 6 ); assert( nVarsF + nVarsS + 1 <= 6 ); assert( nVarsU + nVarsS <= 6 ); // init space for decomposition functions nDecs = (1 << nVarsS); for ( d = 0; d < nDecs; d++ ) { pCof0[d] = Cof0 + d; pCof1[d] = Cof1 + d; pDecs[d] = Decs + d; } // permute variables c = 0; for ( v = 0; v < nVarsF; v++ ) Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsF[v], c++ ); for ( v = 0; v < nVarsS; v++ ) Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsS[v], c++ ); for ( v = 0; v < nVarsU; v++ ) Abc_TtMoveVar( p, nVars, V2P, P2V, pVarsU[v], c++ ); assert( c == nVars ); // check decomposition Status = Dau_DecCheckSetTopOld( p, nVars, nVarsF, nVarsS+nVarsU, nVarsS, Abc_InfoMask(nVarsS), pCof0, pCof1, pDecs ); if ( !Status ) return 0; // compute cofactors assert( nVarsF + nVarsS < 6 ); for ( d = 0; d < nDecs; d++ ) { Cof[d] = (pCof1[d][0] & s_Truths6[nVarsF + nVarsS]) | (pCof0[d][0] & ~s_Truths6[nVarsF + nVarsS]); pDecs[d][0] = Abc_Tt6Stretch( pDecs[d][0], nVarsU ); } // compute the resulting functions pComp[0] = 0; pDec[0] = 0; for ( d = 0; d < nDecs; d++ ) { // compute minterms for composition/decomposition function MintC = MintD = ~((word)0); for ( v = 0; v < nVarsS; v++ ) { MintC &= ((d >> v) & 1) ? s_Truths6[nVarsF+v] : ~s_Truths6[nVarsF+v]; MintD &= ((d >> v) & 1) ? s_Truths6[nVarsU+v] : ~s_Truths6[nVarsU+v]; } // derive functions pComp[0] |= MintC & Cof[d]; pDec[0] |= MintD & pDecs[d][0]; } // derive variable permutations if ( pPermC ) { for ( v = 0; v < nVarsF; v++ ) pPermC[v] = pVarsF[v]; for ( v = 0; v < nVarsS; v++ ) pPermC[nVarsF+v] = pVarsS[v]; pPermC[nVarsF + nVarsS] = nVars; } if ( pPermD ) { for ( v = 0; v < nVarsU; v++ ) pPermD[v] = pVarsU[v]; for ( v = 0; v < nVarsS; v++ ) pPermD[nVarsU+v] = pVarsS[v]; } if ( pnVarsC ) *pnVarsC = nVarsF + nVarsS + 1; if ( pnVarsD ) *pnVarsD = nVarsU + nVarsS; if ( pnVarsS ) *pnVarsS = nVarsS; return 1; } /**Function************************************************************* Synopsis [Testing procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dau_DecVerify( word * pInit, int nVars, char * pDsdC, char * pDsdD ) { word pC[1<<13], pD[1<<13], pRes[1<<13]; // max = 16 int nWordsC = Abc_TtWordNum(nVars+1); int nWordsD = Abc_TtWordNum(nVars); assert( nVars < 16 ); memcpy( pC, Dau_DsdToTruth(pDsdC, nVars+1), sizeof(word) * nWordsC ); memcpy( pD, Dau_DsdToTruth(pDsdD, nVars), sizeof(word) * nWordsD ); if ( nVars >= 6 ) { assert( nWordsD >= 1 ); assert( nWordsC > 1 ); Abc_TtMux( pRes, pD, pC + nWordsD, pC, nWordsD ); } else { word pC0 = Abc_Tt6Stretch( pC[0], nVars ); word pC1 = Abc_Tt6Stretch( (pC[0] >> (1 << nVars)), nVars ); Abc_TtMux( pRes, pD, &pC1, &pC0, nWordsD ); } if ( !Abc_TtEqual(pInit, pRes, nWordsD) ) printf( " Verification failed" ); // else // printf( " Verification successful" ); printf( "\n" ); return 1; } int Dau_DecPerform6( word * p, int nVars, unsigned uSet ) { word tComp = 0, tDec = 0, tDec0, tComp0, tComp1, FuncC, FuncD; char pDsdC[1000], pDsdD[1000]; int pPermC[16], pPermD[16]; int nVarsC, nVarsD, nVarsS, nVarsU, nVarsF, nPairs; int i, m, v, status, ResC, ResD, Counter = 0; status = Dau_DecDecomposeSet( p, nVars, uSet, &tComp, &tDec0, pPermC, pPermD, &nVarsC, &nVarsD, &nVarsS ); if ( !status ) { printf( " Decomposition does not exist\n" ); return 0; } nVarsU = nVarsD - nVarsS; nVarsF = nVarsC - nVarsS - 1; tComp0 = Abc_Tt6Cofactor0( tComp, nVarsF + nVarsS ); tComp1 = Abc_Tt6Cofactor1( tComp, nVarsF + nVarsS ); nPairs = 1 << (1 << nVarsS); for ( i = 0; i < nPairs; i++ ) { if ( i & 1 ) continue; // create miterms with this polarity FuncC = FuncD = 0; for ( m = 0; m < (1 << nVarsS); m++ ) { word MintC, MintD; if ( !((i >> m) & 1) ) continue; MintC = MintD = ~(word)0; for ( v = 0; v < nVarsS; v++ ) { MintC &= ((m >> v) & 1) ? s_Truths6[nVarsF+v] : ~s_Truths6[nVarsF+v]; MintD &= ((m >> v) & 1) ? s_Truths6[nVarsU+v] : ~s_Truths6[nVarsU+v]; } FuncC |= MintC; FuncD |= MintD; } // uncomplement given variables tComp = (~s_Truths6[nVarsF + nVarsS] & ((tComp0 & ~FuncC) | (tComp1 & FuncC))) | (s_Truths6[nVarsF + nVarsS] & ((tComp1 & ~FuncC) | (tComp0 & FuncC))); tDec = tDec0 ^ FuncD; // decompose ResC = Dau_DsdDecompose( &tComp, nVarsC, 0, 1, pDsdC ); ResD = Dau_DsdDecompose( &tDec, nVarsD, 0, 1, pDsdD ); // replace variables Dau_DecVarReplace( pDsdD, pPermD, nVarsD ); Dau_DecVarReplace( pDsdC, pPermC, nVarsC ); // report // printf( " " ); printf( "%3d : ", Counter++ ); printf( "%24s ", pDsdD ); printf( "%24s ", pDsdC ); Dau_DecVerify( p, nVars, pDsdC, pDsdD ); } return 1; } int Dau_DecPerform( word * pInit, int nVars, unsigned uSet ) { word p[1<<10], pDec[1<<10], pComp[1<<10]; // at most 2^10 words char pDsdC[5000], pDsdD[5000]; // at most 2^12 hex digits int nVarsU, nVarsS, nVarsF, nVarsC = 0, nVarsD = 0; int V2P[16], P2V[16], pPermC[16], pPermD[16], * pSched; int v, i, status, ResC, ResD; int nWords = Abc_TtWordNum(nVars); assert( nVars <= 16 ); // backup the function memcpy( p, pInit, sizeof(word) * nWords ); // get variable numbers Dau_DecSortSet( uSet, nVars, &nVarsU, &nVarsS, &nVarsF ); // permute function and order variables for ( v = 0; v < nVars; v++ ) V2P[v] = P2V[v] = v; for ( i = v = 0; v < nVars; v++ ) if ( ((uSet >> (v<<1)) & 3) == 0 ) // free first Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermC[nVarsC++] = v; for ( v = 0; v < nVars; v++ ) if ( ((uSet >> (v<<1)) & 3) == 3 ) // share second Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermC[nVarsC++] = v; pPermC[nVarsC++] = nVars; for ( v = 0; v < nVars; v++ ) if ( ((uSet >> (v<<1)) & 3) == 1 ) // unique last Abc_TtMoveVar( p, nVars, V2P, P2V, v, i++ ), pPermD[nVarsD++] = v; for ( v = 0; v < nVarsS; v++ ) pPermD[nVarsD++] = pPermC[nVarsF+v]; assert( nVarsD == nVarsU + nVarsS ); assert( nVarsC == nVarsF + nVarsS + 1 ); assert( i == nVars ); // decompose pSched = Extra_GreyCodeSchedule( nVarsU + nVarsS ); memset( pDec, 0, sizeof(word) * Abc_TtWordNum(nVarsD) ); memset( pComp, 0, sizeof(word) * Abc_TtWordNum(nVarsC) ); status = Dau_DecCheckSetTop( p, nVars, nVarsF, nVarsU + nVarsS, nVarsS, nVarsS ? Abc_InfoMask(nVarsS) : 0, pSched, pDec, pComp ); ABC_FREE( pSched ); if ( !status ) { printf( " Decomposition does not exist\n" ); return 0; } // Dau_DsdPrintFromTruth( stdout, pC, nVars+1 ); //printf( "\n" ); // Dau_DsdPrintFromTruth( stdout, pD, nVars ); //printf( "\n" ); // Kit_DsdPrintFromTruth( (unsigned *)pComp, 6 ); printf( "\n" ); // Kit_DsdPrintFromTruth( (unsigned *)pDec, 6 ); printf( "\n" ); // decompose ResC = Dau_DsdDecompose( pComp, nVarsC, 0, 1, pDsdC ); ResD = Dau_DsdDecompose( pDec, nVarsD, 0, 1, pDsdD ); // replace variables Dau_DecVarReplace( pDsdD, pPermD, nVarsD ); Dau_DecVarReplace( pDsdC, pPermC, nVarsC ); // report printf( " " ); printf( "%3d : ", 0 ); printf( "%24s ", pDsdD ); printf( "%24s ", pDsdC ); Dau_DecVerify( pInit, nVars, pDsdC, pDsdD ); return 1; } void Dau_DecTrySets( word * pInit, int nVars, int fVerbose ) { Vec_Int_t * vSets; int i, Entry; assert( nVars <= 16 ); vSets = Dau_DecFindSets( pInit, nVars ); if ( !fVerbose ) { Vec_IntFree( vSets ); return; } Dau_DsdPrintFromTruth( pInit, nVars ); printf( "This %d-variable function has %d decomposable variable sets:\n", nVars, Vec_IntSize(vSets) ); Vec_IntForEachEntry( vSets, Entry, i ) { unsigned uSet = (unsigned)Entry; printf( "Set %4d : ", i ); if ( nVars > 6 ) { Dau_DecPrintSet( uSet, nVars, 0 ); Dau_DecPerform( pInit, nVars, uSet ); } else { Dau_DecPrintSet( uSet, nVars, 1 ); Dau_DecPerform6( pInit, nVars, uSet ); } } Vec_IntFree( vSets ); // printf( "\n" ); } void Dau_DecFindSetsTest3() { word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]); word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]); word t = (~s_Truths6[0] & a0) | (s_Truths6[0] & a1); // word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e) int nVars = 6; char * pStr = "Bcd"; // char * pStr = "Abcd"; // char * pStr = "ab"; unsigned uSet = Dau_DecReadSet( pStr ); Dau_DecPerform6( &t, nVars, uSet ); } void Dau_DecFindSetsTest() { int nVars = 6; // word a0 = (~s_Truths6[1] & s_Truths6[2]) | (s_Truths6[1] & s_Truths6[3]); // word a1 = (~s_Truths6[1] & s_Truths6[4]) | (s_Truths6[1] & s_Truths6[5]); // word t = (~s_Truths6[0] & a0) | (s_Truths6[0] & a1); // word t = ABC_CONST(0x7EFFFFFFFFFFFF7E); // and(gam1,gam2) // word t = ABC_CONST(0xB0F0BBFFB0F0BAFE); // some funct // word t = ABC_CONST(0x00000000901FFFFF); // some funct word t = ABC_CONST(0x000030F00D0D3FFF); // some funct // word t = ABC_CONST(0x00000000690006FF); // some funct // word t = ABC_CONST(0x7000F80007FF0FFF); // some funct // word t = ABC_CONST(0x4133CB334133CB33); // some funct 5 var // word t = ABC_CONST(0x2B0228022B022802); // 5-var non-dec0x0F7700000F770000 // word t = ABC_CONST(0x0F7700000F770000); // (!<(ab)cd>e) // word t = ABC_CONST(0x7F00000000000000); // (!(abc)def) Dau_DecTrySets( &t, nVars, 1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/dauTree.c000066400000000000000000002143451300674244400231550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dauTree.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware unmapping.] Synopsis [Canonical DSD package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: dauTree.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dauInt.h" #include "misc/mem/mem.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Dss_Fun_t_ Dss_Fun_t; struct Dss_Fun_t_ { unsigned iDsd : 26; // DSD literal unsigned nFans : 6; // fanin count unsigned char pFans[0]; // fanins }; typedef struct Dss_Ent_t_ Dss_Ent_t; struct Dss_Ent_t_ { Dss_Fun_t * pFunc; Dss_Ent_t * pNext; unsigned iDsd0 : 27; // dsd entry unsigned nWords : 5; // total word count (struct + shared) unsigned iDsd1 : 27; // dsd entry unsigned nShared: 5; // shared count unsigned char pShared[0]; // shared literals }; typedef struct Dss_Obj_t_ Dss_Obj_t; struct Dss_Obj_t_ { unsigned Id; // node ID unsigned Type : 3; // node type unsigned nSupp : 8; // variable unsigned iVar : 8; // variable unsigned nWords : 6; // variable unsigned fMark0 : 1; // user mark unsigned fMark1 : 1; // user mark unsigned nFans : 5; // fanin count unsigned pFans[0]; // fanins }; typedef struct Dss_Ntk_t_ Dss_Ntk_t; struct Dss_Ntk_t_ { int nVars; // the number of variables int nMem; // memory used int nMemAlloc; // memory allocated word * pMem; // memory array Dss_Obj_t * pRoot; // root node Vec_Ptr_t * vObjs; // internal nodes }; struct Dss_Man_t_ { int nVars; // variable number int nNonDecLimit; // limit on non-dec size int nBins; // table size unsigned * pBins; // hash table Mem_Flex_t * pMem; // memory for nodes Vec_Ptr_t * vObjs; // objects Vec_Int_t * vNexts; // next pointers Vec_Int_t * vLeaves; // temp Vec_Int_t * vCopies; // temp word ** pTtElems; // elementary TTs Dss_Ent_t ** pCache; // decomposition cache int nCache; // size of decomposition cache Mem_Flex_t * pMemEnts; // memory for cache entries int nCacheHits[2]; int nCacheMisses[2]; int nCacheEntries[2]; abctime timeBeg; abctime timeDec; abctime timeLook; abctime timeEnd; }; static inline Dss_Obj_t * Dss_Regular( Dss_Obj_t * p ) { return (Dss_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Dss_Obj_t * Dss_Not( Dss_Obj_t * p ) { return (Dss_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Dss_Obj_t * Dss_NotCond( Dss_Obj_t * p, int c ) { return (Dss_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int Dss_IsComplement( Dss_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } static inline int Dss_EntWordNum( Dss_Ent_t * p ) { return sizeof(Dss_Ent_t) / 8 + p->nShared / 4 + ((p->nShared & 3) > 0); } static inline int Dss_FunWordNum( Dss_Fun_t * p ) { assert(p->nFans >= 2); return (p->nFans + 4) / 8 + (((p->nFans + 4) & 7) > 0); } static inline int Dss_ObjWordNum( int nFans ) { return sizeof(Dss_Obj_t) / 8 + nFans / 2 + ((nFans & 1) > 0); } static inline word * Dss_ObjTruth( Dss_Obj_t * pObj ) { return (word *)pObj + pObj->nWords; } static inline void Dss_ObjClean( Dss_Obj_t * pObj ) { memset( pObj, 0, sizeof(Dss_Obj_t) ); } static inline int Dss_ObjId( Dss_Obj_t * pObj ) { return pObj->Id; } static inline int Dss_ObjType( Dss_Obj_t * pObj ) { return pObj->Type; } static inline int Dss_ObjSuppSize( Dss_Obj_t * pObj ) { return pObj->nSupp; } static inline int Dss_ObjFaninNum( Dss_Obj_t * pObj ) { return pObj->nFans; } static inline int Dss_ObjFaninC( Dss_Obj_t * pObj, int i ) { assert(i < (int)pObj->nFans); return Abc_LitIsCompl(pObj->pFans[i]); } static inline Dss_Obj_t * Dss_VecObj( Vec_Ptr_t * p, int Id ) { return (Dss_Obj_t *)Vec_PtrEntry(p, Id); } static inline Dss_Obj_t * Dss_VecConst0( Vec_Ptr_t * p ) { return Dss_VecObj( p, 0 ); } static inline Dss_Obj_t * Dss_VecVar( Vec_Ptr_t * p, int v ) { return Dss_VecObj( p, v+1 ); } static inline int Dss_VecLitSuppSize( Vec_Ptr_t * p, int iLit ) { return Dss_VecObj( p, Abc_Lit2Var(iLit) )->nSupp; } static inline int Dss_Obj2Lit( Dss_Obj_t * pObj ) { return Abc_Var2Lit(Dss_Regular(pObj)->Id, Dss_IsComplement(pObj)); } static inline Dss_Obj_t * Dss_Lit2Obj( Vec_Ptr_t * p, int iLit ) { return Dss_NotCond(Dss_VecObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit)); } static inline Dss_Obj_t * Dss_ObjFanin( Vec_Ptr_t * p, Dss_Obj_t * pObj, int i ) { assert(i < (int)pObj->nFans); return Dss_VecObj(p, Abc_Lit2Var(pObj->pFans[i])); } static inline Dss_Obj_t * Dss_ObjChild( Vec_Ptr_t * p, Dss_Obj_t * pObj, int i ) { assert(i < (int)pObj->nFans); return Dss_Lit2Obj(p, pObj->pFans[i]); } #define Dss_VecForEachObj( vVec, pObj, i ) \ Vec_PtrForEachEntry( Dss_Obj_t *, vVec, pObj, i ) #define Dss_VecForEachObjVec( vLits, vVec, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vLits)) && ((pObj) = Dss_Lit2Obj(vVec, Vec_IntEntry(vLits,i))); i++ ) #define Dss_VecForEachNode( vVec, pObj, i ) \ Vec_PtrForEachEntry( Dss_Obj_t *, vVec, pObj, i ) \ if ( pObj->Type == DAU_DSD_CONST0 || pObj->Type == DAU_DSD_VAR ) {} else #define Dss_ObjForEachFanin( vVec, pObj, pFanin, i ) \ for ( i = 0; (i < Dss_ObjFaninNum(pObj)) && ((pFanin) = Dss_ObjFanin(vVec, pObj, i)); i++ ) #define Dss_ObjForEachChild( vVec, pObj, pFanin, i ) \ for ( i = 0; (i < Dss_ObjFaninNum(pObj)) && ((pFanin) = Dss_ObjChild(vVec, pObj, i)); i++ ) static inline int Dss_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 Dss_Lit2Lit( int * pMapLit, int Lit ) { return Abc_Var2Lit( Abc_Lit2Var(pMapLit[Abc_Lit2Var(Lit)]), Abc_LitIsCompl(Lit) ^ Abc_LitIsCompl(pMapLit[Abc_Lit2Var(Lit)]) ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #if 0 /**Function************************************************************* Synopsis [Check decomposability for 666.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // recursively collects 6-feasible supports int Dss_ObjCheck666_rec( Dss_Ntk_t * p, Dss_Obj_t * pObj, Vec_Int_t * vSupps ) { Dss_Obj_t * pFanin; int i, uSupp = 0; assert( !Dss_IsComplement(pObj) ); if ( pObj->Type == DAU_DSD_VAR ) { assert( pObj->iVar >= 0 && pObj->iVar < 30 ); return (1 << pObj->iVar); } if ( pObj->Type == DAU_DSD_AND || pObj->Type == DAU_DSD_XOR ) { int c0, c1, c2, uSuppTemp; int uSuppVars[16]; int nSuppVars = 0; int nFanins = Dss_ObjFaninNum(pObj); int uSupps[16], nSuppSizes[16]; Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i ) { uSupps[i] = Dss_ObjCheck666_rec( p, pFanin, vSupps ); nSuppSizes[i] = Dss_WordCountOnes( uSupps[i] ); uSupp |= uSupps[i]; if ( nSuppSizes[i] == 1 ) uSuppVars[nSuppVars++] = uSupps[i]; } // iterate through the permutations for ( c0 = 0; c0 < nFanins; c0++ ) if ( nSuppSizes[c0] > 1 && nSuppSizes[c0] < 6 ) { uSuppTemp = uSupps[c0]; for ( i = 0; i < nSuppVars; i++ ) if ( nSuppSizes[c0] + i < 6 ) uSuppTemp |= uSuppVars[i]; else break; if ( Dss_WordCountOnes(uSuppTemp) <= 6 ) Vec_IntPush( vSupps, uSuppTemp ); for ( c1 = c0 + 1; c1 < nFanins; c1++ ) if ( nSuppSizes[c1] > 1 && nSuppSizes[c1] < 6 ) { if ( nSuppSizes[c0] + nSuppSizes[c1] <= 6 ) Vec_IntPush( vSupps, uSupps[c0] | uSupps[c1] ); uSuppTemp = uSupps[c0] | uSupps[c1]; for ( i = 0; i < nSuppVars; i++ ) if ( nSuppSizes[c0] + nSuppSizes[c1] + i < 6 ) uSuppTemp |= uSuppVars[i]; else break; if ( Dss_WordCountOnes(uSuppTemp) <= 6 ) Vec_IntPush( vSupps, uSuppTemp ); for ( c2 = c1 + 1; c2 < nFanins; c2++ ) if ( nSuppSizes[c2] > 1 && nSuppSizes[c2] < 6 ) { if ( nSuppSizes[c0] + nSuppSizes[c1] + nSuppSizes[c2] <= 6 ) Vec_IntPush( vSupps, uSupps[c0] | uSupps[c1] | uSupps[c2] ); assert( nSuppSizes[c0] + nSuppSizes[c1] + nSuppSizes[c2] >= 6 ); } } } if ( nSuppVars > 1 && nSuppVars <= 6 ) { uSuppTemp = 0; for ( i = 0; i < nSuppVars; i++ ) uSuppTemp |= uSuppVars[i]; Vec_IntPush( vSupps, uSuppTemp ); } else if ( nSuppVars > 6 && nSuppVars <= 12 ) { uSuppTemp = 0; for ( i = 0; i < 6; i++ ) uSuppTemp |= uSuppVars[i]; Vec_IntPush( vSupps, uSuppTemp ); uSuppTemp = 0; for ( i = 6; i < nSuppVars; i++ ) uSuppTemp |= uSuppVars[i]; Vec_IntPush( vSupps, uSuppTemp ); } } else if ( pObj->Type == DAU_DSD_MUX || pObj->Type == DAU_DSD_PRIME ) { Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i ) uSupp |= Dss_ObjCheck666_rec( p, pFanin, vSupps ); } if ( Dss_WordCountOnes( uSupp ) <= 6 ) Vec_IntPush( vSupps, uSupp ); return uSupp; } int Dss_ObjCheck666( Dss_Ntk_t * p ) { Vec_Int_t * vSupps; int i, k, SuppI, SuppK; int nSupp = Dss_ObjSuppSize(Dss_Regular(p->pRoot)); if ( nSupp <= 6 ) return 1; // compute supports vSupps = Vec_IntAlloc( 100 ); Dss_ObjCheck666_rec( p, Dss_Regular(p->pRoot), vSupps ); Vec_IntUniqify( vSupps ); Vec_IntForEachEntry( vSupps, SuppI, i ) { k = Dss_WordCountOnes(SuppI); assert( k > 0 && k <= 6 ); /* for ( k = 0; k < 16; k++ ) if ( (SuppI >> k) & 1 ) printf( "%c", 'a' + k ); else printf( "-" ); printf( "\n" ); */ } // consider support pairs Vec_IntForEachEntry( vSupps, SuppI, i ) Vec_IntForEachEntryStart( vSupps, SuppK, k, i+1 ) { if ( SuppI & SuppK ) continue; if ( Dss_WordCountOnes(SuppI | SuppK) + 4 >= nSupp ) { Vec_IntFree( vSupps ); return 1; } } Vec_IntFree( vSupps ); return 0; } void Dau_DsdTest_() { /* extern Dss_Ntk_t * Dss_NtkCreate( char * pDsd, int nVars, word * pTruth ); extern void Dss_NtkFree( Dss_Ntk_t * p ); // char * pDsd = "(!(amn!(bh))[cdeij]!(fklg)o)"; char * pDsd = "<[(ab)(cd)(ef)][(gh)(ij)(kl)](mn)>"; Dss_Ntk_t * pNtk = Dss_NtkCreate( pDsd, 16, NULL ); int Status = Dss_ObjCheck666( pNtk ); Dss_NtkFree( pNtk ); */ } abctime if_dec_time; void Dau_DsdCheckStructOne( word * pTruth, int nVars, int nLeaves ) { extern Dss_Ntk_t * Dss_NtkCreate( char * pDsd, int nVars, word * pTruth ); extern void Dss_NtkFree( Dss_Ntk_t * p ); static abctime timeTt = 0; static abctime timeDsd = 0; abctime clkTt, clkDsd; char pDsd[1000]; word Truth[1024]; Dss_Ntk_t * pNtk; int Status, nNonDec; if ( pTruth == NULL ) { Abc_PrintTime( 1, "TT runtime", timeTt ); Abc_PrintTime( 1, "DSD runtime", timeDsd ); Abc_PrintTime( 1, "Total ", if_dec_time ); if_dec_time = 0; timeTt = 0; timeDsd = 0; return; } Abc_TtCopy( Truth, pTruth, Abc_TtWordNum(nVars), 0 ); nNonDec = Dau_DsdDecompose( Truth, nVars, 0, 0, pDsd ); if ( nNonDec > 0 ) return; pNtk = Dss_NtkCreate( pDsd, 16, NULL ); // measure DSD runtime clkDsd = Abc_Clock(); Status = Dss_ObjCheck666( pNtk ); timeDsd += Abc_Clock() - clkDsd; Dss_NtkFree( pNtk ); // measure TT runtime clkTt = Abc_Clock(); { #define CLU_VAR_MAX 16 // decomposition typedef struct If_Grp_t_ If_Grp_t; struct If_Grp_t_ { char nVars; char nMyu; char pVars[CLU_VAR_MAX]; }; int nLutLeaf = 6; int nLutLeaf2 = 6; int nLutRoot = 6; If_Grp_t G; If_Grp_t G2, R; word Func0, Func1, Func2; { extern If_Grp_t If_CluCheck3( void * p, word * pTruth0, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot, If_Grp_t * pR, If_Grp_t * pG2, word * pFunc0, word * pFunc1, word * pFunc2 ); G = If_CluCheck3( NULL, pTruth, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, &R, &G2, &Func0, &Func1, &Func2 ); } } timeTt += Abc_Clock() - clkTt; } #endif /**Function************************************************************* Synopsis [Elementary truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word ** Dss_ManTtElems() { static word TtElems[DAU_MAX_VAR+1][DAU_MAX_WORD], * pTtElems[DAU_MAX_VAR+1] = {NULL}; if ( pTtElems[0] == NULL ) { int v; for ( v = 0; v <= DAU_MAX_VAR; v++ ) pTtElems[v] = TtElems[v]; Abc_TtElemInit( pTtElems, DAU_MAX_VAR ); } return pTtElems; } /**Function************************************************************* Synopsis [Creating DSD network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dss_Obj_t * Dss_ObjAllocNtk( Dss_Ntk_t * p, int Type, int nFans, int nTruthVars ) { Dss_Obj_t * pObj; pObj = (Dss_Obj_t *)(p->pMem + p->nMem); Dss_ObjClean( pObj ); pObj->nFans = nFans; pObj->nWords = Dss_ObjWordNum( nFans ); pObj->Type = Type; pObj->Id = Vec_PtrSize( p->vObjs ); pObj->iVar = 31; Vec_PtrPush( p->vObjs, pObj ); p->nMem += pObj->nWords + (nTruthVars ? Abc_TtWordNum(nTruthVars) : 0); assert( p->nMem < p->nMemAlloc ); return pObj; } Dss_Obj_t * Dss_ObjCreateNtk( Dss_Ntk_t * p, int Type, Vec_Int_t * vFaninLits ) { Dss_Obj_t * pObj; int i, Entry; pObj = Dss_ObjAllocNtk( p, Type, Vec_IntSize(vFaninLits), Type == DAU_DSD_PRIME ? Vec_IntSize(vFaninLits) : 0 ); Vec_IntForEachEntry( vFaninLits, Entry, i ) { pObj->pFans[i] = Entry; pObj->nSupp += Dss_VecLitSuppSize(p->vObjs, Entry); } assert( i == (int)pObj->nFans ); return pObj; } Dss_Ntk_t * Dss_NtkAlloc( int nVars ) { Dss_Ntk_t * p; Dss_Obj_t * pObj; int i; p = ABC_CALLOC( Dss_Ntk_t, 1 ); p->nVars = nVars; p->nMemAlloc = DAU_MAX_STR; p->pMem = ABC_ALLOC( word, p->nMemAlloc ); p->vObjs = Vec_PtrAlloc( 100 ); Dss_ObjAllocNtk( p, DAU_DSD_CONST0, 0, 0 ); for ( i = 0; i < nVars; i++ ) { pObj = Dss_ObjAllocNtk( p, DAU_DSD_VAR, 0, 0 ); pObj->iVar = i; pObj->nSupp = 1; } return p; } void Dss_NtkFree( Dss_Ntk_t * p ) { Vec_PtrFree( p->vObjs ); ABC_FREE( p->pMem ); ABC_FREE( p ); } void Dss_NtkPrint_rec( Dss_Ntk_t * p, Dss_Obj_t * pObj ) { char OpenType[7] = {0, 0, 0, '(', '[', '<', '{'}; char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'}; Dss_Obj_t * pFanin; int i; assert( !Dss_IsComplement(pObj) ); if ( pObj->Type == DAU_DSD_VAR ) { printf( "%c", 'a' + pObj->iVar ); return; } if ( pObj->Type == DAU_DSD_PRIME ) Abc_TtPrintHexRev( stdout, Dss_ObjTruth(pObj), pObj->nFans ); printf( "%c", OpenType[pObj->Type] ); Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i ) { printf( "%s", Dss_ObjFaninC(pObj, i) ? "!":"" ); Dss_NtkPrint_rec( p, pFanin ); } printf( "%c", CloseType[pObj->Type] ); } void Dss_NtkPrint( Dss_Ntk_t * p ) { if ( Dss_Regular(p->pRoot)->Type == DAU_DSD_CONST0 ) printf( "%d", Dss_IsComplement(p->pRoot) ); else { printf( "%s", Dss_IsComplement(p->pRoot) ? "!":"" ); if ( Dss_Regular(p->pRoot)->Type == DAU_DSD_VAR ) printf( "%c", 'a' + Dss_Regular(p->pRoot)->iVar ); else Dss_NtkPrint_rec( p, Dss_Regular(p->pRoot) ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Creating DSD network from SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dau_DsdMergeMatches( char * pDsd, int * pMatches ) { int pNested[DAU_MAX_VAR]; int i, nNested = 0; for ( i = 0; pDsd[i]; i++ ) { pMatches[i] = 0; if ( pDsd[i] == '(' || pDsd[i] == '[' || pDsd[i] == '<' || pDsd[i] == '{' ) pNested[nNested++] = i; else if ( pDsd[i] == ')' || pDsd[i] == ']' || pDsd[i] == '>' || pDsd[i] == '}' ) pMatches[pNested[--nNested]] = i; assert( nNested < DAU_MAX_VAR ); } assert( nNested == 0 ); } int Dss_NtkCreate_rec( char * pStr, char ** p, int * pMatches, Dss_Ntk_t * pNtk, word * pTruth ) { int fCompl = 0; if ( **p == '!' ) { fCompl = 1; (*p)++; } while ( (**p >= 'A' && **p <= 'F') || (**p >= '0' && **p <= '9') ) (*p)++; /* if ( **p == '<' ) { char * q = pStr + pMatches[ *p - pStr ]; if ( *(q+1) == '{' ) *p = q+1; } */ if ( **p >= 'a' && **p <= 'z' ) // var return Abc_Var2Lit( Dss_ObjId(Dss_VecVar(pNtk->vObjs, **p - 'a')), fCompl ); if ( **p == '(' || **p == '[' || **p == '<' || **p == '{' ) // and/or/xor { Dss_Obj_t * pObj; Vec_Int_t * vFaninLits = Vec_IntAlloc( 10 ); char * q = pStr + pMatches[ *p - pStr ]; int Type; if ( **p == '(' ) Type = DAU_DSD_AND; else if ( **p == '[' ) Type = DAU_DSD_XOR; else if ( **p == '<' ) Type = DAU_DSD_MUX; else if ( **p == '{' ) Type = DAU_DSD_PRIME; else assert( 0 ); assert( *q == **p + 1 + (**p != '(') ); for ( (*p)++; *p < q; (*p)++ ) Vec_IntPush( vFaninLits, Dss_NtkCreate_rec(pStr, p, pMatches, pNtk, pTruth) ); assert( *p == q ); if ( Type == DAU_DSD_PRIME ) { Vec_Int_t * vFaninLitsNew; word pTemp[DAU_MAX_WORD]; char pCanonPerm[DAU_MAX_VAR]; int i, uCanonPhase, nFanins = Vec_IntSize(vFaninLits); Abc_TtCopy( pTemp, pTruth, Abc_TtWordNum(nFanins), 0 ); uCanonPhase = Abc_TtCanonicize( pTemp, nFanins, pCanonPerm ); fCompl = (uCanonPhase >> nFanins) & 1; vFaninLitsNew = Vec_IntAlloc( nFanins ); for ( i = 0; i < nFanins; i++ ) Vec_IntPush( vFaninLitsNew, Abc_LitNotCond(Vec_IntEntry(vFaninLits, pCanonPerm[i]), (uCanonPhase>>i)&1) ); pObj = Dss_ObjCreateNtk( pNtk, DAU_DSD_PRIME, vFaninLitsNew ); Abc_TtCopy( Dss_ObjTruth(pObj), pTemp, Abc_TtWordNum(nFanins), 0 ); Vec_IntFree( vFaninLitsNew ); } else pObj = Dss_ObjCreateNtk( pNtk, Type, vFaninLits ); Vec_IntFree( vFaninLits ); return Abc_LitNotCond( Dss_Obj2Lit(pObj), fCompl ); } assert( 0 ); return -1; } Dss_Ntk_t * Dss_NtkCreate( char * pDsd, int nVars, word * pTruth ) { int fCompl = 0; Dss_Ntk_t * pNtk = Dss_NtkAlloc( nVars ); if ( *pDsd == '!' ) pDsd++, fCompl = 1; if ( Dau_DsdIsConst(pDsd) ) pNtk->pRoot = Dss_VecConst0(pNtk->vObjs); else if ( Dau_DsdIsVar(pDsd) ) pNtk->pRoot = Dss_VecVar(pNtk->vObjs, Dau_DsdReadVar(pDsd)); else { int iLit, pMatches[DAU_MAX_STR]; Dau_DsdMergeMatches( pDsd, pMatches ); iLit = Dss_NtkCreate_rec( pDsd, &pDsd, pMatches, pNtk, pTruth ); pNtk->pRoot = Dss_Lit2Obj( pNtk->vObjs, iLit ); } if ( fCompl ) pNtk->pRoot = Dss_Not(pNtk->pRoot); return pNtk; } /**Function************************************************************* Synopsis [Comparing two DSD nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dss_ObjCompare( Vec_Ptr_t * p, Dss_Obj_t * p0i, Dss_Obj_t * p1i ) { Dss_Obj_t * p0 = Dss_Regular(p0i); Dss_Obj_t * p1 = Dss_Regular(p1i); Dss_Obj_t * pChild0, * pChild1; int i, Res; if ( Dss_ObjType(p0) < Dss_ObjType(p1) ) return -1; if ( Dss_ObjType(p0) > Dss_ObjType(p1) ) return 1; if ( Dss_ObjType(p0) < DAU_DSD_AND ) return 0; if ( Dss_ObjFaninNum(p0) < Dss_ObjFaninNum(p1) ) return -1; if ( Dss_ObjFaninNum(p0) > Dss_ObjFaninNum(p1) ) return 1; for ( i = 0; i < Dss_ObjFaninNum(p0); i++ ) { pChild0 = Dss_ObjChild( p, p0, i ); pChild1 = Dss_ObjChild( p, p1, i ); Res = Dss_ObjCompare( p, pChild0, pChild1 ); if ( Res != 0 ) return Res; } if ( Dss_IsComplement(p0i) < Dss_IsComplement(p1i) ) return -1; if ( Dss_IsComplement(p0i) > Dss_IsComplement(p1i) ) return 1; return 0; } void Dss_ObjSort( Vec_Ptr_t * p, Dss_Obj_t ** pNodes, int nNodes, int * pPerm ) { int i, j, best_i; for ( i = 0; i < nNodes-1; i++ ) { best_i = i; for ( j = i+1; j < nNodes; j++ ) if ( Dss_ObjCompare(p, pNodes[best_i], pNodes[j]) == 1 ) best_i = j; if ( i == best_i ) continue; ABC_SWAP( Dss_Obj_t *, pNodes[i], pNodes[best_i] ); if ( pPerm ) ABC_SWAP( int, pPerm[i], pPerm[best_i] ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dss_NtkCheck( Dss_Ntk_t * p ) { Dss_Obj_t * pObj, * pFanin; int i, k; Dss_VecForEachNode( p->vObjs, pObj, i ) { Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, k ) { if ( pObj->Type == DAU_DSD_AND && pFanin->Type == DAU_DSD_AND ) assert( Dss_ObjFaninC(pObj, k) ); else if ( pObj->Type == DAU_DSD_XOR ) assert( pFanin->Type != DAU_DSD_XOR ); else if ( pObj->Type == DAU_DSD_MUX ) assert( !Dss_ObjFaninC(pObj, 0) ); } } } int Dss_NtkCollectPerm_rec( Dss_Ntk_t * p, Dss_Obj_t * pObj, int * pPermDsd, int * pnPerms ) { Dss_Obj_t * pChild; int k, fCompl = Dss_IsComplement(pObj); pObj = Dss_Regular( pObj ); if ( pObj->Type == DAU_DSD_VAR ) { pPermDsd[*pnPerms] = Abc_Var2Lit(pObj->iVar, fCompl); pObj->iVar = (*pnPerms)++; return fCompl; } Dss_ObjForEachChild( p->vObjs, pObj, pChild, k ) if ( Dss_NtkCollectPerm_rec( p, pChild, pPermDsd, pnPerms ) ) pObj->pFans[k] = (unsigned char)Abc_LitRegular((int)pObj->pFans[k]); return 0; } void Dss_NtkTransform( Dss_Ntk_t * p, int * pPermDsd ) { Dss_Obj_t * pChildren[DAU_MAX_VAR]; Dss_Obj_t * pObj, * pChild; int i, k, nPerms; if ( Dss_Regular(p->pRoot)->Type == DAU_DSD_CONST0 ) return; Dss_VecForEachNode( p->vObjs, pObj, i ) { if ( pObj->Type == DAU_DSD_MUX || pObj->Type == DAU_DSD_PRIME ) continue; Dss_ObjForEachChild( p->vObjs, pObj, pChild, k ) pChildren[k] = pChild; Dss_ObjSort( p->vObjs, pChildren, Dss_ObjFaninNum(pObj), NULL ); for ( k = 0; k < Dss_ObjFaninNum(pObj); k++ ) pObj->pFans[k] = Dss_Obj2Lit( pChildren[k] ); } nPerms = 0; if ( Dss_NtkCollectPerm_rec( p, p->pRoot, pPermDsd, &nPerms ) ) p->pRoot = Dss_Regular(p->pRoot); assert( nPerms == (int)Dss_Regular(p->pRoot)->nSupp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dss_Obj_t * Dss_ObjAlloc( Dss_Man_t * p, int Type, int nFans, int nTruthVars ) { int nWords = Dss_ObjWordNum(nFans) + (nTruthVars ? Abc_TtWordNum(nTruthVars) : 0); Dss_Obj_t * pObj = (Dss_Obj_t *)Mem_FlexEntryFetch( p->pMem, sizeof(word) * nWords ); Dss_ObjClean( pObj ); pObj->Type = Type; pObj->nFans = nFans; pObj->nWords = Dss_ObjWordNum(nFans); pObj->Id = Vec_PtrSize( p->vObjs ); pObj->iVar = 31; Vec_PtrPush( p->vObjs, pObj ); Vec_IntPush( p->vNexts, 0 ); return pObj; } Dss_Obj_t * Dss_ObjCreate( Dss_Man_t * p, int Type, Vec_Int_t * vFaninLits, word * pTruth ) { Dss_Obj_t * pObj, * pFanin, * pPrev = NULL; int i, Entry; // check structural canonicity assert( Type != DAU_DSD_MUX || Vec_IntSize(vFaninLits) == 3 ); assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(Vec_IntEntry(vFaninLits, 0)) ); assert( Type != DAU_DSD_MUX || !Abc_LitIsCompl(Vec_IntEntry(vFaninLits, 1)) || !Abc_LitIsCompl(Vec_IntEntry(vFaninLits, 2)) ); // check that leaves are in good order if ( Type == DAU_DSD_AND || Type == DAU_DSD_XOR ) Dss_VecForEachObjVec( vFaninLits, p->vObjs, pFanin, i ) { assert( Type != DAU_DSD_AND || Abc_LitIsCompl(Vec_IntEntry(vFaninLits, i)) || Dss_ObjType(pFanin) != DAU_DSD_AND ); assert( Type != DAU_DSD_XOR || Dss_ObjType(pFanin) != DAU_DSD_XOR ); assert( pPrev == NULL || Dss_ObjCompare(p->vObjs, pPrev, pFanin) <= 0 ); pPrev = pFanin; } // create new node pObj = Dss_ObjAlloc( p, Type, Vec_IntSize(vFaninLits), Type == DAU_DSD_PRIME ? Vec_IntSize(vFaninLits) : 0 ); if ( Type == DAU_DSD_PRIME ) Abc_TtCopy( Dss_ObjTruth(pObj), pTruth, Abc_TtWordNum(Vec_IntSize(vFaninLits)), 0 ); assert( pObj->nSupp == 0 ); Vec_IntForEachEntry( vFaninLits, Entry, i ) { pObj->pFans[i] = Entry; pObj->nSupp += Dss_VecLitSuppSize(p->vObjs, Entry); } /* { extern void Dss_ManPrintOne( Dss_Man_t * p, int iDsdLit, int * pPermLits ); Dss_ManPrintOne( p, Dss_Obj2Lit(pObj), NULL ); } */ return pObj; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dss_ManHashProfile( Dss_Man_t * p ) { Dss_Obj_t * pObj; unsigned * pSpot; int i, Counter; for ( i = 0; i < p->nBins; i++ ) { Counter = 0; for ( pSpot = p->pBins + i; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(p->vNexts, pObj->Id), Counter++ ) pObj = Dss_VecObj( p->vObjs, *pSpot ); if ( Counter ) printf( "%d ", Counter ); } printf( "\n" ); } static inline unsigned Dss_ObjHashKey( Dss_Man_t * p, int Type, Vec_Int_t * vFaninLits, word * pTruth ) { static int s_Primes[8] = { 1699, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; int i, Entry; unsigned uHash = Type * 7873 + Vec_IntSize(vFaninLits) * 8147; Vec_IntForEachEntry( vFaninLits, Entry, i ) uHash += Entry * s_Primes[i & 0x7]; assert( (Type == DAU_DSD_PRIME) == (pTruth != NULL) ); if ( pTruth ) { unsigned char * pTruthC = (unsigned char *)pTruth; int nBytes = Abc_TtByteNum(Vec_IntSize(vFaninLits)); for ( i = 0; i < nBytes; i++ ) uHash += pTruthC[i] * s_Primes[i & 0x7]; } return uHash % p->nBins; } unsigned * Dss_ObjHashLookup( Dss_Man_t * p, int Type, Vec_Int_t * vFaninLits, word * pTruth ) { Dss_Obj_t * pObj; unsigned * pSpot = p->pBins + Dss_ObjHashKey(p, Type, vFaninLits, pTruth); for ( ; *pSpot; pSpot = (unsigned *)Vec_IntEntryP(p->vNexts, pObj->Id) ) { pObj = Dss_VecObj( p->vObjs, *pSpot ); if ( (int)pObj->Type == Type && (int)pObj->nFans == Vec_IntSize(vFaninLits) && !memcmp(pObj->pFans, Vec_IntArray(vFaninLits), sizeof(int)*pObj->nFans) && (pTruth == NULL || !memcmp(Dss_ObjTruth(pObj), pTruth, Abc_TtByteNum(pObj->nFans))) ) // equal return pSpot; } return pSpot; } Dss_Obj_t * Dss_ObjFindOrAdd( Dss_Man_t * p, int Type, Vec_Int_t * vFaninLits, word * pTruth ) { Dss_Obj_t * pObj; unsigned * pSpot = Dss_ObjHashLookup( p, Type, vFaninLits, pTruth ); if ( *pSpot ) return Dss_VecObj( p->vObjs, *pSpot ); *pSpot = Vec_PtrSize( p->vObjs ); pObj = Dss_ObjCreate( p, Type, vFaninLits, pTruth ); return pObj; } /**Function************************************************************* Synopsis [Cache for decomposition calls.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dss_ManCacheAlloc( Dss_Man_t * p ) { assert( p->nCache == 0 ); p->nCache = Abc_PrimeCudd( 100000 ); p->pCache = ABC_CALLOC( Dss_Ent_t *, p->nCache ); } void Dss_ManCacheFree( Dss_Man_t * p ) { if ( p->pCache == NULL ) return; assert( p->nCache != 0 ); p->nCache = 0; ABC_FREE( p->pCache ); } static inline unsigned Dss_ManCacheHashKey( Dss_Man_t * p, Dss_Ent_t * pEnt ) { static int s_Primes[8] = { 1699, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; int i; unsigned uHash = pEnt->nShared * 7103 + pEnt->iDsd0 * 7873 + pEnt->iDsd1 * 8147; for ( i = 0; i < 2*(int)pEnt->nShared; i++ ) uHash += pEnt->pShared[i] * s_Primes[i & 0x7]; return uHash % p->nCache; } void Dss_ManCacheProfile( Dss_Man_t * p ) { Dss_Ent_t ** pSpot; int i, Counter; for ( i = 0; i < p->nCache; i++ ) { Counter = 0; for ( pSpot = p->pCache + i; *pSpot; pSpot = &(*pSpot)->pNext, Counter++ ) ; if ( Counter ) printf( "%d ", Counter ); } printf( "\n" ); } Dss_Ent_t ** Dss_ManCacheLookup( Dss_Man_t * p, Dss_Ent_t * pEnt ) { Dss_Ent_t ** pSpot = p->pCache + Dss_ManCacheHashKey( p, pEnt ); for ( ; *pSpot; pSpot = &(*pSpot)->pNext ) { if ( (*pSpot)->iDsd0 == pEnt->iDsd0 && (*pSpot)->iDsd1 == pEnt->iDsd1 && (*pSpot)->nShared == pEnt->nShared && !memcmp((*pSpot)->pShared, pEnt->pShared, sizeof(char)*2*pEnt->nShared) ) // equal { p->nCacheHits[pEnt->nShared!=0]++; return pSpot; } } p->nCacheMisses[pEnt->nShared!=0]++; return pSpot; } Dss_Ent_t * Dss_ManCacheCreate( Dss_Man_t * p, Dss_Ent_t * pEnt0, Dss_Fun_t * pFun0 ) { Dss_Ent_t * pEnt = (Dss_Ent_t *)Mem_FlexEntryFetch( p->pMemEnts, sizeof(word) * pEnt0->nWords ); Dss_Fun_t * pFun = (Dss_Fun_t *)Mem_FlexEntryFetch( p->pMemEnts, sizeof(word) * Dss_FunWordNum(pFun0) ); memcpy( pEnt, pEnt0, sizeof(word) * pEnt0->nWords ); memcpy( pFun, pFun0, sizeof(word) * Dss_FunWordNum(pFun0) ); pEnt->pFunc = pFun; pEnt->pNext = NULL; p->nCacheEntries[pEnt->nShared!=0]++; return pEnt; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dss_Man_t * Dss_ManAlloc( int nVars, int nNonDecLimit ) { Dss_Man_t * p; p = ABC_CALLOC( Dss_Man_t, 1 ); p->nVars = nVars; p->nNonDecLimit = nNonDecLimit; p->nBins = Abc_PrimeCudd( 1000000 ); p->pBins = ABC_CALLOC( unsigned, p->nBins ); p->pMem = Mem_FlexStart(); p->vObjs = Vec_PtrAlloc( 10000 ); p->vNexts = Vec_IntAlloc( 10000 ); Dss_ObjAlloc( p, DAU_DSD_CONST0, 0, 0 ); Dss_ObjAlloc( p, DAU_DSD_VAR, 0, 0 )->nSupp = 1; p->vLeaves = Vec_IntAlloc( 32 ); p->vCopies = Vec_IntAlloc( 32 ); p->pTtElems = Dss_ManTtElems(); p->pMemEnts = Mem_FlexStart(); // Dss_ManCacheAlloc( p ); return p; } void Dss_ManFree( Dss_Man_t * p ) { Abc_PrintTime( 1, "Time begin ", p->timeBeg ); Abc_PrintTime( 1, "Time decomp", p->timeDec ); Abc_PrintTime( 1, "Time lookup", p->timeLook ); Abc_PrintTime( 1, "Time end ", p->timeEnd ); // Dss_ManCacheProfile( p ); Dss_ManCacheFree( p ); Mem_FlexStop( p->pMemEnts, 0 ); Vec_IntFreeP( &p->vCopies ); Vec_IntFreeP( &p->vLeaves ); Vec_IntFreeP( &p->vNexts ); Vec_PtrFreeP( &p->vObjs ); Mem_FlexStop( p->pMem, 0 ); ABC_FREE( p->pBins ); ABC_FREE( p ); } void Dss_ManPrint_rec( FILE * pFile, Dss_Man_t * p, Dss_Obj_t * pObj, int * pPermLits, int * pnSupp ) { char OpenType[7] = {0, 0, 0, '(', '[', '<', '{'}; char CloseType[7] = {0, 0, 0, ')', ']', '>', '}'}; Dss_Obj_t * pFanin; int i; assert( !Dss_IsComplement(pObj) ); if ( pObj->Type == DAU_DSD_CONST0 ) { fprintf( pFile, "0" ); return; } if ( pObj->Type == DAU_DSD_VAR ) { int iPermLit = pPermLits ? pPermLits[(*pnSupp)++] : Abc_Var2Lit((*pnSupp)++, 0); fprintf( pFile, "%s%c", Abc_LitIsCompl(iPermLit)? "!":"", 'a' + Abc_Lit2Var(iPermLit) ); return; } if ( pObj->Type == DAU_DSD_PRIME ) Abc_TtPrintHexRev( pFile, Dss_ObjTruth(pObj), pObj->nFans ); fprintf( pFile, "%c", OpenType[pObj->Type] ); Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i ) { fprintf( pFile, "%s", Dss_ObjFaninC(pObj, i) ? "!":"" ); Dss_ManPrint_rec( pFile, p, pFanin, pPermLits, pnSupp ); } fprintf( pFile, "%c", CloseType[pObj->Type] ); } void Dss_ManPrintOne( FILE * pFile, Dss_Man_t * p, int iDsdLit, int * pPermLits ) { int nSupp = 0; fprintf( pFile, "%6d : ", Abc_Lit2Var(iDsdLit) ); fprintf( pFile, "%2d ", Dss_VecLitSuppSize(p->vObjs, iDsdLit) ); fprintf( pFile, "%s", Abc_LitIsCompl(iDsdLit) ? "!" : "" ); Dss_ManPrint_rec( pFile, p, Dss_VecObj(p->vObjs, Abc_Lit2Var(iDsdLit)), pPermLits, &nSupp ); fprintf( pFile, "\n" ); assert( nSupp == (int)Dss_VecObj(p->vObjs, Abc_Lit2Var(iDsdLit))->nSupp ); } int Dss_ManCheckNonDec_rec( Dss_Man_t * p, Dss_Obj_t * pObj ) { Dss_Obj_t * pFanin; int i; assert( !Dss_IsComplement(pObj) ); if ( pObj->Type == DAU_DSD_CONST0 ) return 0; if ( pObj->Type == DAU_DSD_VAR ) return 0; if ( pObj->Type == DAU_DSD_PRIME ) return 1; Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i ) if ( Dss_ManCheckNonDec_rec( p, pFanin ) ) return 1; return 0; } void Dss_ManDump( Dss_Man_t * p ) { char * pFileName = "dss_tts.txt"; FILE * pFile; word Temp[DAU_MAX_WORD]; Dss_Obj_t * pObj; int i; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return; } Dss_VecForEachObj( p->vObjs, pObj, i ) { if ( pObj->Type != DAU_DSD_PRIME ) continue; Abc_TtCopy( Temp, Dss_ObjTruth(pObj), Abc_TtWordNum(pObj->nFans), 0 ); Abc_TtStretch6( Temp, pObj->nFans, p->nVars ); fprintf( pFile, "0x" ); Abc_TtPrintHexRev( pFile, Temp, p->nVars ); fprintf( pFile, "\n" ); // printf( "%6d : ", i ); // Abc_TtPrintHexRev( stdout, Temp, p->nVars ); // printf( " " ); // Dau_DsdPrintFromTruth( stdout, Temp, p->nVars ); } fclose( pFile ); } void Dss_ManPrint( char * pFileName, Dss_Man_t * p ) { Dss_Obj_t * pObj; int CountNonDsd = 0, CountNonDsdStr = 0; int i, clk = Abc_Clock(); FILE * pFile; pFile = pFileName ? fopen( pFileName, "wb" ) : stdout; if ( pFileName && pFile == NULL ) { printf( "cannot open output file\n" ); return; } Dss_VecForEachObj( p->vObjs, pObj, i ) { CountNonDsd += (pObj->Type == DAU_DSD_PRIME); CountNonDsdStr += Dss_ManCheckNonDec_rec( p, pObj ); } fprintf( pFile, "Total number of objects = %8d\n", Vec_PtrSize(p->vObjs) ); fprintf( pFile, "Non-DSD objects (max =%2d) = %8d\n", p->nNonDecLimit, CountNonDsd ); fprintf( pFile, "Non-DSD structures = %8d\n", CountNonDsdStr ); fprintf( pFile, "Memory used for objects = %6.2f MB.\n", 1.0*Mem_FlexReadMemUsage(p->pMem)/(1<<20) ); fprintf( pFile, "Memory used for array = %6.2f MB.\n", 1.0*sizeof(void *)*Vec_PtrCap(p->vObjs)/(1<<20) ); fprintf( pFile, "Memory used for hash table = %6.2f MB.\n", 1.0*sizeof(int)*p->nBins/(1<<20) ); fprintf( pFile, "Memory used for cache = %6.2f MB.\n", 1.0*Mem_FlexReadMemUsage(p->pMemEnts)/(1<<20) ); fprintf( pFile, "Cache hits = %8d %8d\n", p->nCacheHits[0], p->nCacheHits[1] ); fprintf( pFile, "Cache misses = %8d %8d\n", p->nCacheMisses[0], p->nCacheMisses[1] ); fprintf( pFile, "Cache entries = %8d %8d\n", p->nCacheEntries[0], p->nCacheEntries[1] ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // Dss_ManHashProfile( p ); // Dss_ManDump( p ); // return; Dss_VecForEachObj( p->vObjs, pObj, i ) { if ( i == 50 ) break; Dss_ManPrintOne( pFile, p, Dss_Obj2Lit(pObj), NULL ); } fprintf( pFile, "\n" ); if ( pFileName ) fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dss_ManComputeTruth_rec( Dss_Man_t * p, Dss_Obj_t * pObj, int nVars, word * pRes, int * pPermLits, int * pnSupp ) { Dss_Obj_t * pChild; int nWords = Abc_TtWordNum(nVars); int i, fCompl = Dss_IsComplement(pObj); pObj = Dss_Regular(pObj); if ( pObj->Type == DAU_DSD_VAR ) { int iPermLit = pPermLits[(*pnSupp)++]; assert( (*pnSupp) <= nVars ); Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], nWords, fCompl ^ Abc_LitIsCompl(iPermLit) ); return; } if ( pObj->Type == DAU_DSD_AND || pObj->Type == DAU_DSD_XOR ) { word pTtTemp[DAU_MAX_WORD]; if ( pObj->Type == DAU_DSD_AND ) Abc_TtConst1( pRes, nWords ); else Abc_TtConst0( pRes, nWords ); Dss_ObjForEachChild( p->vObjs, pObj, pChild, i ) { Dss_ManComputeTruth_rec( p, pChild, nVars, pTtTemp, pPermLits, pnSupp ); if ( pObj->Type == DAU_DSD_AND ) Abc_TtAnd( pRes, pRes, pTtTemp, nWords, 0 ); else Abc_TtXor( pRes, pRes, pTtTemp, nWords, 0 ); } if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } if ( pObj->Type == DAU_DSD_MUX ) // mux { word pTtTemp[3][DAU_MAX_WORD]; Dss_ObjForEachChild( p->vObjs, pObj, pChild, i ) Dss_ManComputeTruth_rec( p, pChild, nVars, pTtTemp[i], pPermLits, pnSupp ); assert( i == 3 ); Abc_TtMux( pRes, pTtTemp[0], pTtTemp[1], pTtTemp[2], nWords ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } if ( pObj->Type == DAU_DSD_PRIME ) // function { word pFanins[DAU_MAX_VAR][DAU_MAX_WORD]; Dss_ObjForEachChild( p->vObjs, pObj, pChild, i ) Dss_ManComputeTruth_rec( p, pChild, nVars, pFanins[i], pPermLits, pnSupp ); Dau_DsdTruthCompose_rec( Dss_ObjTruth(pObj), pFanins, pRes, pObj->nFans, nWords ); if ( fCompl ) Abc_TtNot( pRes, nWords ); return; } assert( 0 ); } word * Dss_ManComputeTruth( Dss_Man_t * p, int iDsd, int nVars, int * pPermLits ) { Dss_Obj_t * pObj = Dss_Lit2Obj(p->vObjs, iDsd); word * pRes = p->pTtElems[DAU_MAX_VAR]; int nWords = Abc_TtWordNum( nVars ); int nSupp = 0; assert( nVars <= DAU_MAX_VAR ); if ( iDsd == 0 ) Abc_TtConst0( pRes, nWords ); else if ( iDsd == 1 ) Abc_TtConst1( pRes, nWords ); else if ( Dss_Regular(pObj)->Type == DAU_DSD_VAR ) { int iPermLit = pPermLits[nSupp++]; Abc_TtCopy( pRes, p->pTtElems[Abc_Lit2Var(iPermLit)], nWords, Abc_LitIsCompl(iDsd) ^ Abc_LitIsCompl(iPermLit) ); } else Dss_ManComputeTruth_rec( p, pObj, nVars, pRes, pPermLits, &nSupp ); assert( nSupp == (int)Dss_Regular(pObj)->nSupp ); return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // returns literal of non-shifted tree in p, corresponding to pObj in pNtk, which may be compl int Dss_NtkRebuild_rec( Dss_Man_t * p, Dss_Ntk_t * pNtk, Dss_Obj_t * pObj ) { Dss_Obj_t * pChildren[DAU_MAX_VAR]; Dss_Obj_t * pChild, * pObjNew; int i, k, fCompl = Dss_IsComplement(pObj); pObj = Dss_Regular(pObj); if ( pObj->Type == DAU_DSD_VAR ) return Abc_Var2Lit( 1, fCompl ); Dss_ObjForEachChild( pNtk->vObjs, pObj, pChild, k ) { pChildren[k] = Dss_Lit2Obj( p->vObjs, Dss_NtkRebuild_rec( p, pNtk, pChild ) ); if ( pObj->Type == DAU_DSD_XOR && Dss_IsComplement(pChildren[k]) ) pChildren[k] = Dss_Not(pChildren[k]), fCompl ^= 1; } // normalize MUX if ( pObj->Type == DAU_DSD_MUX ) { if ( Dss_IsComplement(pChildren[0]) ) { pChildren[0] = Dss_Not(pChildren[0]); ABC_SWAP( Dss_Obj_t *, pChildren[1], pChildren[2] ); } if ( Dss_IsComplement(pChildren[1]) ) { pChildren[1] = Dss_Not(pChildren[1]); pChildren[2] = Dss_Not(pChildren[2]); fCompl ^= 1; } } // shift subgraphs Vec_IntClear( p->vLeaves ); for ( i = 0; i < k; i++ ) Vec_IntPush( p->vLeaves, Dss_Obj2Lit(pChildren[i]) ); // create new graph pObjNew = Dss_ObjFindOrAdd( p, pObj->Type, p->vLeaves, pObj->Type == DAU_DSD_PRIME ? Dss_ObjTruth(pObj) : NULL ); return Abc_Var2Lit( pObjNew->Id, fCompl ); } int Dss_NtkRebuild( Dss_Man_t * p, Dss_Ntk_t * pNtk ) { assert( p->nVars == pNtk->nVars ); if ( Dss_Regular(pNtk->pRoot)->Type == DAU_DSD_CONST0 ) return Dss_IsComplement(pNtk->pRoot); if ( Dss_Regular(pNtk->pRoot)->Type == DAU_DSD_VAR ) return Abc_Var2Lit( Dss_Regular(pNtk->pRoot)->iVar + 1, Dss_IsComplement(pNtk->pRoot) ); return Dss_NtkRebuild_rec( p, pNtk, pNtk->pRoot ); } /**Function************************************************************* Synopsis [Performs DSD operation on the two literals.] Description [Returns the perm of the resulting literals. The perm size is equal to the number of support variables. The perm variables are 0-based numbers of pLits[0] followed by nLits[0]-based numbers of pLits[1].] SideEffects [] SeeAlso [] ***********************************************************************/ int Dss_ManOperation( Dss_Man_t * p, int Type, int * pLits, int nLits, unsigned char * pPerm, word * pTruth ) { Dss_Obj_t * pChildren[DAU_MAX_VAR]; Dss_Obj_t * pObj, * pChild; int i, k, nChildren = 0, fCompl = 0, fComplFan; assert( Type == DAU_DSD_AND || pPerm == NULL ); if ( Type == DAU_DSD_AND && pPerm != NULL ) { int pBegEnd[DAU_MAX_VAR]; int j, nSSize = 0; for ( k = 0; k < nLits; k++ ) { pObj = Dss_Lit2Obj(p->vObjs, pLits[k]); if ( Dss_IsComplement(pObj) || pObj->Type != DAU_DSD_AND ) { fComplFan = (Dss_Regular(pObj)->Type == DAU_DSD_VAR && Dss_IsComplement(pObj)); if ( fComplFan ) pObj = Dss_Regular(pObj); pBegEnd[nChildren] = (nSSize << 16) | (fComplFan << 8) | (nSSize + Dss_Regular(pObj)->nSupp); nSSize += Dss_Regular(pObj)->nSupp; pChildren[nChildren++] = pObj; } else Dss_ObjForEachChild( p->vObjs, pObj, pChild, i ) { fComplFan = (Dss_Regular(pChild)->Type == DAU_DSD_VAR && Dss_IsComplement(pChild)); if ( fComplFan ) pChild = Dss_Regular(pChild); pBegEnd[nChildren] = (nSSize << 16) | (fComplFan << 8) | (nSSize + Dss_Regular(pChild)->nSupp); nSSize += Dss_Regular(pChild)->nSupp; pChildren[nChildren++] = pChild; } } Dss_ObjSort( p->vObjs, pChildren, nChildren, pBegEnd ); // create permutation for ( j = i = 0; i < nChildren; i++ ) for ( k = (pBegEnd[i] >> 16); k < (pBegEnd[i] & 0xFF); k++ ) pPerm[j++] = (unsigned char)Abc_Var2Lit( k, (pBegEnd[i] >> 8) & 1 ); assert( j == nSSize ); } else if ( Type == DAU_DSD_AND ) { for ( k = 0; k < nLits; k++ ) { pObj = Dss_Lit2Obj(p->vObjs, pLits[k]); if ( Dss_IsComplement(pObj) || pObj->Type != DAU_DSD_AND ) pChildren[nChildren++] = pObj; else Dss_ObjForEachChild( p->vObjs, pObj, pChild, i ) pChildren[nChildren++] = pChild; } Dss_ObjSort( p->vObjs, pChildren, nChildren, NULL ); } else if ( Type == DAU_DSD_XOR ) { for ( k = 0; k < nLits; k++ ) { fCompl ^= Abc_LitIsCompl(pLits[k]); pObj = Dss_Lit2Obj(p->vObjs, Abc_LitRegular(pLits[k])); if ( pObj->Type != DAU_DSD_XOR ) pChildren[nChildren++] = pObj; else Dss_ObjForEachChild( p->vObjs, pObj, pChild, i ) { assert( !Dss_IsComplement(pChild) ); pChildren[nChildren++] = pChild; } } Dss_ObjSort( p->vObjs, pChildren, nChildren, NULL ); } else if ( Type == DAU_DSD_MUX ) { if ( Abc_LitIsCompl(pLits[0]) ) { pLits[0] = Abc_LitNot(pLits[0]); ABC_SWAP( int, pLits[1], pLits[2] ); } if ( Abc_LitIsCompl(pLits[1]) ) { pLits[1] = Abc_LitNot(pLits[1]); pLits[2] = Abc_LitNot(pLits[2]); fCompl ^= 1; } for ( k = 0; k < nLits; k++ ) pChildren[nChildren++] = Dss_Lit2Obj(p->vObjs, pLits[k]); } else if ( Type == DAU_DSD_PRIME ) { for ( k = 0; k < nLits; k++ ) pChildren[nChildren++] = Dss_Lit2Obj(p->vObjs, pLits[k]); } else assert( 0 ); // shift subgraphs Vec_IntClear( p->vLeaves ); for ( i = 0; i < nChildren; i++ ) Vec_IntPush( p->vLeaves, Dss_Obj2Lit(pChildren[i]) ); // create new graph pObj = Dss_ObjFindOrAdd( p, Type, p->vLeaves, pTruth ); return Abc_Var2Lit( pObj->Id, fCompl ); } Dss_Fun_t * Dss_ManOperationFun( Dss_Man_t * p, int * iDsd, int nFansTot ) { static char Buffer[100]; Dss_Fun_t * pFun = (Dss_Fun_t *)Buffer; pFun->iDsd = Dss_ManOperation( p, DAU_DSD_AND, iDsd, 2, pFun->pFans, NULL ); //printf( "%d %d -> %d ", iDsd[0], iDsd[1], pFun->iDsd ); pFun->nFans = nFansTot; assert( (int)pFun->nFans == Dss_VecLitSuppSize(p->vObjs, pFun->iDsd) ); return pFun; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dss_EntPrint( Dss_Ent_t * p, Dss_Fun_t * pFun ) { int i; printf( "%d %d ", p->iDsd0, p->iDsd1 ); for ( i = 0; i < (int)p->nShared; i++ ) printf( "%d=%d ", p->pShared[2*i], p->pShared[2*i+1] ); printf( "-> %d ", pFun->iDsd ); } /**Function************************************************************* Synopsis [Performs AND on two DSD functions with support overlap.] Description [Returns the perm of the resulting literals. The perm size is equal to the number of support variables. The perm variables are 0-based numbers of pLits[0] followed by nLits[0]-based numbers of pLits[1].] SideEffects [] SeeAlso [] ***********************************************************************/ Dss_Fun_t * Dss_ManBooleanAnd( Dss_Man_t * p, Dss_Ent_t * pEnt, int Counter ) { static char Buffer[100]; Dss_Fun_t * pFun = (Dss_Fun_t *)Buffer; Dss_Ntk_t * pNtk; word * pTruthOne, pTruth[DAU_MAX_WORD]; char pDsd[DAU_MAX_STR]; int pMapDsd2Truth[DAU_MAX_VAR]; int pPermLits[DAU_MAX_VAR]; int pPermDsd[DAU_MAX_VAR]; int i, nNonDec, nSuppSize = 0; int nFans[2]; nFans[0] = Dss_VecLitSuppSize( p->vObjs, pEnt->iDsd0 ); nFans[1] = Dss_VecLitSuppSize( p->vObjs, pEnt->iDsd1 ); // create first truth table for ( i = 0; i < nFans[0]; i++ ) { pMapDsd2Truth[nSuppSize] = i; pPermLits[i] = Abc_Var2Lit( nSuppSize++, 0 ); } pTruthOne = Dss_ManComputeTruth( p, pEnt->iDsd0, p->nVars, pPermLits ); Abc_TtCopy( pTruth, pTruthOne, Abc_TtWordNum(p->nVars), 0 ); if ( Counter ) { //Kit_DsdPrintFromTruth( pTruthOne, p->nVars ); printf( "\n" ); } // create second truth table for ( i = 0; i < nFans[1]; i++ ) pPermLits[i] = -1; for ( i = 0; i < (int)pEnt->nShared; i++ ) pPermLits[pEnt->pShared[2*i+0]] = pEnt->pShared[2*i+1]; for ( i = 0; i < nFans[1]; i++ ) if ( pPermLits[i] == -1 ) { pMapDsd2Truth[nSuppSize] = nFans[0] + i; pPermLits[i] = Abc_Var2Lit( nSuppSize++, 0 ); } pTruthOne = Dss_ManComputeTruth( p, pEnt->iDsd1, p->nVars, pPermLits ); if ( Counter ) { //Kit_DsdPrintFromTruth( pTruthOne, p->nVars ); printf( "\n" ); } Abc_TtAnd( pTruth, pTruth, pTruthOne, Abc_TtWordNum(p->nVars), 0 ); // perform decomposition nNonDec = Dau_DsdDecompose( pTruth, nSuppSize, 0, 0, pDsd ); if ( p->nNonDecLimit && nNonDec > p->nNonDecLimit ) return NULL; // derive network and convert it into the manager pNtk = Dss_NtkCreate( pDsd, p->nVars, nNonDec ? pTruth : NULL ); //Dss_NtkPrint( pNtk ); Dss_NtkCheck( pNtk ); Dss_NtkTransform( pNtk, pPermDsd ); //Dss_NtkPrint( pNtk ); pFun->iDsd = Dss_NtkRebuild( p, pNtk ); Dss_NtkFree( pNtk ); // pPermDsd maps vars of iDsdRes into literals of pTruth // translate this map into the one that maps vars of iDsdRes into literals of cut pFun->nFans = Dss_VecLitSuppSize( p->vObjs, pFun->iDsd ); for ( i = 0; i < (int)pFun->nFans; i++ ) pFun->pFans[i] = (unsigned char)Abc_Lit2LitV( pMapDsd2Truth, pPermDsd[i] ); // Dss_EntPrint( pEnt, pFun ); return pFun; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // returns mapping of variables of dsd1 into literals of dsd0 Dss_Ent_t * Dss_ManSharedMap( Dss_Man_t * p, int * iDsd, int * nFans, int ** pFans, unsigned uSharedMask ) { static char Buffer[100]; Dss_Ent_t * pEnt = (Dss_Ent_t *)Buffer; pEnt->iDsd0 = iDsd[0]; pEnt->iDsd1 = iDsd[1]; pEnt->nShared = 0; if ( uSharedMask ) { int i, g, pMapGtoL[DAU_MAX_VAR] = {-1}; for ( i = 0; i < nFans[0]; i++ ) pMapGtoL[ Abc_Lit2Var(pFans[0][i]) ] = Abc_Var2Lit( i, Abc_LitIsCompl(pFans[0][i]) ); for ( i = 0; i < nFans[1]; i++ ) { g = Abc_Lit2Var( pFans[1][i] ); if ( (uSharedMask >> g) & 1 ) { assert( pMapGtoL[g] >= 0 ); pEnt->pShared[2*pEnt->nShared+0] = (unsigned char)i; pEnt->pShared[2*pEnt->nShared+1] = (unsigned char)Abc_LitNotCond( pMapGtoL[g], Abc_LitIsCompl(pFans[1][i]) ); pEnt->nShared++; } } } pEnt->nWords = Dss_EntWordNum( pEnt ); return pEnt; } // merge two DSD functions int Dss_ManMerge( Dss_Man_t * p, int * iDsd, int * nFans, int ** pFans, unsigned uSharedMask, int nKLutSize, unsigned char * pPermRes, word * pTruth ) { int fVerbose = 0; int fCheck = 0; static int Counter = 0; // word pTtTemp[DAU_MAX_WORD]; word * pTruthOne; int pPermResInt[DAU_MAX_VAR]; Dss_Ent_t * pEnt, ** ppSpot; Dss_Fun_t * pFun; int i; abctime clk; Counter++; if ( DAU_MAX_VAR < nKLutSize ) { printf( "Paramater DAU_MAX_VAR (%d) smaller than LUT size (%d).\n", DAU_MAX_VAR, nKLutSize ); return -1; } assert( iDsd[0] <= iDsd[1] ); if ( fVerbose ) { Dss_ManPrintOne( stdout, p, iDsd[0], pFans[0] ); Dss_ManPrintOne( stdout, p, iDsd[1], pFans[1] ); } // constant argument if ( iDsd[0] == 0 ) return 0; if ( iDsd[0] == 1 ) return iDsd[1]; if ( iDsd[1] == 0 ) return 0; if ( iDsd[1] == 1 ) return iDsd[0]; // no overlap clk = Abc_Clock(); assert( nFans[0] == Dss_VecLitSuppSize(p->vObjs, iDsd[0]) ); assert( nFans[1] == Dss_VecLitSuppSize(p->vObjs, iDsd[1]) ); assert( nFans[0] + nFans[1] <= nKLutSize + Dss_WordCountOnes(uSharedMask) ); // create map of shared variables pEnt = Dss_ManSharedMap( p, iDsd, nFans, pFans, uSharedMask ); p->timeBeg += Abc_Clock() - clk; // check cache if ( p->pCache == NULL ) { clk = Abc_Clock(); if ( uSharedMask == 0 ) pFun = Dss_ManOperationFun( p, iDsd, nFans[0] + nFans[1] ); else pFun = Dss_ManBooleanAnd( p, pEnt, 0 ); if ( pFun == NULL ) return -1; assert( (int)pFun->nFans == Dss_VecLitSuppSize(p->vObjs, pFun->iDsd) ); assert( (int)pFun->nFans <= nKLutSize ); p->timeDec += Abc_Clock() - clk; } else { clk = Abc_Clock(); ppSpot = Dss_ManCacheLookup( p, pEnt ); p->timeLook += Abc_Clock() - clk; clk = Abc_Clock(); if ( *ppSpot == NULL ) { if ( uSharedMask == 0 ) pFun = Dss_ManOperationFun( p, iDsd, nFans[0] + nFans[1] ); else pFun = Dss_ManBooleanAnd( p, pEnt, 0 ); if ( pFun == NULL ) return -1; assert( (int)pFun->nFans == Dss_VecLitSuppSize(p->vObjs, pFun->iDsd) ); assert( (int)pFun->nFans <= nKLutSize ); // create cache entry *ppSpot = Dss_ManCacheCreate( p, pEnt, pFun ); } pFun = (*ppSpot)->pFunc; p->timeDec += Abc_Clock() - clk; } clk = Abc_Clock(); for ( i = 0; i < (int)pFun->nFans; i++ ) if ( pFun->pFans[i] < 2 * nFans[0] ) // first dec pPermRes[i] = (unsigned char)Dss_Lit2Lit( pFans[0], pFun->pFans[i] ); else pPermRes[i] = (unsigned char)Dss_Lit2Lit( pFans[1], pFun->pFans[i] - 2 * nFans[0] ); // perform support minimization if ( uSharedMask && pFun->nFans > 1 ) { int pVarPres[DAU_MAX_VAR]; int nSupp = 0; for ( i = 0; i < p->nVars; i++ ) pVarPres[i] = -1; for ( i = 0; i < (int)pFun->nFans; i++ ) pVarPres[ Abc_Lit2Var(pPermRes[i]) ] = i; for ( i = 0; i < p->nVars; i++ ) if ( pVarPres[i] >= 0 ) pPermRes[pVarPres[i]] = Abc_Var2Lit( nSupp++, Abc_LitIsCompl(pPermRes[pVarPres[i]]) ); assert( nSupp == (int)pFun->nFans ); } for ( i = 0; i < (int)pFun->nFans; i++ ) pPermResInt[i] = pPermRes[i]; p->timeEnd += Abc_Clock() - clk; if ( fVerbose ) { Dss_ManPrintOne( stdout, p, pFun->iDsd, pPermResInt ); printf( "\n" ); } if ( Counter == 43418 ) { // int s = 0; // Dss_ManPrint( NULL, p ); } if ( fCheck ) { pTruthOne = Dss_ManComputeTruth( p, pFun->iDsd, p->nVars, pPermResInt ); if ( !Abc_TtEqual( pTruthOne, pTruth, Abc_TtWordNum(p->nVars) ) ) { int s; // Kit_DsdPrintFromTruth( pTruthOne, p->nVars ); printf( "\n" ); // Kit_DsdPrintFromTruth( pTruth, p->nVars ); printf( "\n" ); printf( "Verification failed.\n" ); s = 0; } } return pFun->iDsd; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dss_Ent_t * Dss_ManSharedMapDerive( Dss_Man_t * p, int iDsd0, int iDsd1, Vec_Str_t * vShared ) { static char Buffer[100]; Dss_Ent_t * pEnt = (Dss_Ent_t *)Buffer; pEnt->iDsd0 = iDsd0; pEnt->iDsd1 = iDsd1; pEnt->nShared = Vec_StrSize(vShared)/2; memcpy( pEnt->pShared, (unsigned char *)Vec_StrArray(vShared), sizeof(char) * Vec_StrSize(vShared) ); pEnt->nWords = Dss_EntWordNum( pEnt ); return pEnt; } int Mpm_FuncCompute( Dss_Man_t * p, int iDsd0, int iDsd1, Vec_Str_t * vShared, int * pPerm, int * pnLeaves ) { int fVerbose = 0; // int fCheck = 0; Dss_Ent_t * pEnt, ** ppSpot; Dss_Fun_t * pFun; int iDsd[2] = { iDsd0, iDsd1 }; int i; abctime clk; assert( iDsd0 <= iDsd1 ); if ( DAU_MAX_VAR < *pnLeaves ) { printf( "Paramater DAU_MAX_VAR (%d) smaller than LUT size (%d).\n", DAU_MAX_VAR, *pnLeaves ); return -1; } if ( fVerbose ) { Dss_ManPrintOne( stdout, p, iDsd0, NULL ); Dss_ManPrintOne( stdout, p, iDsd1, NULL ); } clk = Abc_Clock(); pEnt = Dss_ManSharedMapDerive( p, iDsd0, iDsd1, vShared ); ppSpot = Dss_ManCacheLookup( p, pEnt ); p->timeLook += Abc_Clock() - clk; clk = Abc_Clock(); if ( *ppSpot == NULL ) { if ( Vec_StrSize(vShared) == 0 ) pFun = Dss_ManOperationFun( p, iDsd, *pnLeaves ); else pFun = Dss_ManBooleanAnd( p, pEnt, 0 ); if ( pFun == NULL ) return -1; assert( (int)pFun->nFans == Dss_VecLitSuppSize(p->vObjs, pFun->iDsd) ); assert( (int)pFun->nFans <= *pnLeaves ); // create cache entry *ppSpot = Dss_ManCacheCreate( p, pEnt, pFun ); } pFun = (*ppSpot)->pFunc; p->timeDec += Abc_Clock() - clk; *pnLeaves = (int)pFun->nFans; for ( i = 0; i < (int)pFun->nFans; i++ ) pPerm[i] = (int)pFun->pFans[i]; if ( fVerbose ) { Dss_ManPrintOne( stdout, p, pFun->iDsd, NULL ); printf( "\n" ); } /* if ( fCheck ) { pTruthOne = Dss_ManComputeTruth( p, pFun->iDsd, p->nVars, pPermResInt ); if ( !Abc_TtEqual( pTruthOne, pTruth, Abc_TtWordNum(p->nVars) ) ) { int s; // Kit_DsdPrintFromTruth( pTruthOne, p->nVars ); printf( "\n" ); // Kit_DsdPrintFromTruth( pTruth, p->nVars ); printf( "\n" ); printf( "Verification failed.\n" ); s = 0; } } */ return pFun->iDsd; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dss_ObjCheckTransparent( Dss_Man_t * p, Dss_Obj_t * pObj ) { Dss_Obj_t * pFanin; int i; if ( pObj->Type == DAU_DSD_VAR ) return 1; if ( pObj->Type == DAU_DSD_AND ) return 0; if ( pObj->Type == DAU_DSD_XOR ) { Dss_ObjForEachFanin( p->vObjs, pObj, pFanin, i ) if ( Dss_ObjCheckTransparent( p, pFanin ) ) return 1; return 0; } if ( pObj->Type == DAU_DSD_MUX ) { pFanin = Dss_ObjFanin( p->vObjs, pObj, 1 ); if ( !Dss_ObjCheckTransparent(p, pFanin) ) return 0; pFanin = Dss_ObjFanin( p->vObjs, pObj, 2 ); if ( !Dss_ObjCheckTransparent(p, pFanin) ) return 0; return 1; } assert( pObj->Type == DAU_DSD_PRIME ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTest__() { int nVars = 8; // char * pDsd = "[(ab)(cd)]"; char * pDsd = "(!(a!(bh))[cde]!(fg))"; Dss_Ntk_t * pNtk = Dss_NtkCreate( pDsd, nVars, NULL ); // Dss_NtkPrint( pNtk ); // Dss_NtkCheck( pNtk ); // Dss_NtkTransform( pNtk ); // Dss_NtkPrint( pNtk ); Dss_NtkFree( pNtk ); nVars = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTest() { int nVars = 8; Vec_Vec_t * vFuncs; Vec_Int_t * vOne, * vTwo, * vRes;//, * vThree; Dss_Man_t * p; int pEntries[3]; int iLit, e0, e1;//, e2; int i, k, s;//, j; return; vFuncs = Vec_VecStart( nVars+1 ); assert( nVars < DAU_MAX_VAR ); p = Dss_ManAlloc( nVars, 0 ); // init Vec_VecPushInt( vFuncs, 1, Dss_Obj2Lit(Dss_VecVar(p->vObjs,0)) ); // enumerate for ( s = 2; s <= nVars; s++ ) { vRes = Vec_VecEntryInt( vFuncs, s ); for ( i = 1; i < s; i++ ) for ( k = i; k < s; k++ ) if ( i + k == s ) { vOne = Vec_VecEntryInt( vFuncs, i ); vTwo = Vec_VecEntryInt( vFuncs, k ); Vec_IntForEachEntry( vOne, pEntries[0], e0 ) Vec_IntForEachEntry( vTwo, pEntries[1], e1 ) { int fAddInv0 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[0])) ); int fAddInv1 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[1])) ); iLit = Dss_ManOperation( p, DAU_DSD_AND, pEntries, 2, NULL, NULL ); assert( !Abc_LitIsCompl(iLit) ); Vec_IntPush( vRes, iLit ); if ( fAddInv0 ) { pEntries[0] = Abc_LitNot( pEntries[0] ); iLit = Dss_ManOperation( p, DAU_DSD_AND, pEntries, 2, NULL, NULL ); pEntries[0] = Abc_LitNot( pEntries[0] ); assert( !Abc_LitIsCompl(iLit) ); Vec_IntPush( vRes, iLit ); } if ( fAddInv1 ) { pEntries[1] = Abc_LitNot( pEntries[1] ); iLit = Dss_ManOperation( p, DAU_DSD_AND, pEntries, 2, NULL, NULL ); pEntries[1] = Abc_LitNot( pEntries[1] ); assert( !Abc_LitIsCompl(iLit) ); Vec_IntPush( vRes, iLit ); } if ( fAddInv0 && fAddInv1 ) { pEntries[0] = Abc_LitNot( pEntries[0] ); pEntries[1] = Abc_LitNot( pEntries[1] ); iLit = Dss_ManOperation( p, DAU_DSD_AND, pEntries, 2, NULL, NULL ); pEntries[0] = Abc_LitNot( pEntries[0] ); pEntries[1] = Abc_LitNot( pEntries[1] ); assert( !Abc_LitIsCompl(iLit) ); Vec_IntPush( vRes, iLit ); } iLit = Dss_ManOperation( p, DAU_DSD_XOR, pEntries, 2, NULL, NULL ); assert( !Abc_LitIsCompl(iLit) ); Vec_IntPush( vRes, Abc_LitRegular(iLit) ); } } /* for ( i = 1; i < s; i++ ) for ( k = 1; k < s; k++ ) for ( j = 1; j < s; j++ ) if ( i + k + j == s ) { vOne = Vec_VecEntryInt( vFuncs, i ); vTwo = Vec_VecEntryInt( vFuncs, k ); vThree = Vec_VecEntryInt( vFuncs, j ); Vec_IntForEachEntry( vOne, pEntries[0], e0 ) Vec_IntForEachEntry( vTwo, pEntries[1], e1 ) Vec_IntForEachEntry( vThree, pEntries[2], e2 ) { int fAddInv0 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[0])) ); int fAddInv1 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[1])) ); int fAddInv2 = !Dss_ObjCheckTransparent( p, Dss_VecObj(p->vObjs, Abc_Lit2Var(pEntries[2])) ); if ( !fAddInv0 && k > j ) continue; iLit = Dss_ManOperation( p, DAU_DSD_MUX, pEntries, 3, NULL, NULL ); assert( !Abc_LitIsCompl(iLit) ); Vec_IntPush( vRes, iLit ); if ( fAddInv1 ) { pEntries[1] = Abc_LitNot( pEntries[1] ); iLit = Dss_ManOperation( p, DAU_DSD_MUX, pEntries, 3, NULL, NULL ); pEntries[1] = Abc_LitNot( pEntries[1] ); assert( !Abc_LitIsCompl(iLit) ); Vec_IntPush( vRes, iLit ); } if ( fAddInv2 ) { pEntries[2] = Abc_LitNot( pEntries[2] ); iLit = Dss_ManOperation( p, DAU_DSD_MUX, pEntries, 3, NULL, NULL ); pEntries[2] = Abc_LitNot( pEntries[2] ); assert( !Abc_LitIsCompl(iLit) ); Vec_IntPush( vRes, iLit ); } } } */ Vec_IntUniqify( vRes ); } Dss_ManPrint( "_npn/npn/dsdcanon.txt", p ); Dss_ManFree( p ); Vec_VecFree( vFuncs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dau_DsdTest444() { Dss_Man_t * p = Dss_ManAlloc( 6, 0 ); int iLit1[3] = { 2, 4 }; int iLit2[3] = { 2, 4, 6 }; int iRes[5]; int nFans[2] = { 4, 3 }; int pPermLits1[4] = { 0, 2, 5, 6 }; int pPermLits2[5] = { 2, 9, 10 }; int * pPermLits[2] = { pPermLits1, pPermLits2 }; unsigned char pPermRes[6]; int pPermResInt[6]; unsigned uMaskShared = 2; int i; iRes[0] = 1 ^ Dss_ManOperation( p, DAU_DSD_AND, iLit1, 2, NULL, NULL ); iRes[1] = iRes[0]; iRes[2] = 1 ^ Dss_ManOperation( p, DAU_DSD_AND, iRes, 2, NULL, NULL ); iRes[3] = Dss_ManOperation( p, DAU_DSD_AND, iLit2, 3, NULL, NULL ); Dss_ManPrintOne( stdout, p, iRes[0], NULL ); Dss_ManPrintOne( stdout, p, iRes[2], NULL ); Dss_ManPrintOne( stdout, p, iRes[3], NULL ); Dss_ManPrintOne( stdout, p, iRes[2], pPermLits1 ); Dss_ManPrintOne( stdout, p, iRes[3], pPermLits2 ); iRes[4] = Dss_ManMerge( p, iRes+2, nFans, pPermLits, uMaskShared, 6, pPermRes, NULL ); for ( i = 0; i < 6; i++ ) pPermResInt[i] = pPermRes[i]; Dss_ManPrintOne( stdout, p, iRes[4], NULL ); Dss_ManPrintOne( stdout, p, iRes[4], pPermResInt ); Dss_ManFree( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/dau/module.make000066400000000000000000000003471300674244400235370ustar00rootroot00000000000000SRC += src/opt/dau/dauCanon.c \ src/opt/dau/dauCore.c \ src/opt/dau/dauDivs.c \ src/opt/dau/dauDsd.c \ src/opt/dau/dauEnum.c \ src/opt/dau/dauGia.c \ src/opt/dau/dauMerge.c \ src/opt/dau/dauNonDsd.c \ src/opt/dau/dauTree.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fret/000077500000000000000000000000001300674244400215765ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fret/fretFlow.c000066400000000000000000000413621300674244400235400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fretFlow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Flow-based retiming package.] Synopsis [Max-flow computation.] Author [Aaron Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2008.] Revision [$Id: fretFlow.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] ***********************************************************************/ #include "fretime.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void dfsfast_e_retreat( Abc_Obj_t *pObj ); static void dfsfast_r_retreat( Abc_Obj_t *pObj ); #define FDIST(xn, xe, yn, ye) (FDATA(xn)->xe##_dist == (FDATA(yn)->ye##_dist + 1)) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Fast DFS.] Description [Uses sink-distance-histogram heuristic. May not find all flow paths: this occurs in a small number of cases where the flow predecessor points to a non-adjacent node and the distance ordering is perturbed.] SideEffects [] SeeAlso [] ***********************************************************************/ void dfsfast_preorder( Abc_Ntk_t *pNtk ) { Abc_Obj_t *pObj, *pNext; Vec_Ptr_t *vTimeIn, *qn = Vec_PtrAlloc(Abc_NtkObjNum(pNtk)); Vec_Int_t *qe = Vec_IntAlloc(Abc_NtkObjNum(pNtk)); int i, j, d = 0, end; int qpos = 0; // create reverse timing edges for backward traversal #if !defined(IGNORE_TIMING) if (pManMR->maxDelay) { Abc_NtkForEachObj( pNtk, pObj, i ) { Vec_PtrForEachEntry( Abc_Obj_t *, FTIMEEDGES(pObj), pNext, j ) { vTimeIn = FDATA(pNext)->vNodes; if (!vTimeIn) { vTimeIn = FDATA(pNext)->vNodes = Vec_PtrAlloc(2); } Vec_PtrPush(vTimeIn, pObj); } } } #endif // clear histogram assert(pManMR->vSinkDistHist); memset(Vec_IntArray(pManMR->vSinkDistHist), 0, sizeof(int)*Vec_IntSize(pManMR->vSinkDistHist)); // seed queue : latches, PIOs, and blocks Abc_NtkForEachObj( pNtk, pObj, i ) if (Abc_ObjIsPo(pObj) || Abc_ObjIsLatch(pObj) || (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) { Vec_PtrPush(qn, pObj); Vec_IntPush(qe, 'r'); FDATA(pObj)->r_dist = 1; } else if (Abc_ObjIsPi(pObj) || (!pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) { Vec_PtrPush(qn, pObj); Vec_IntPush(qe, 'e'); FDATA(pObj)->e_dist = 1; } // until queue is empty... while(qpos < Vec_PtrSize(qn)) { pObj = (Abc_Obj_t *)Vec_PtrEntry(qn, qpos); assert(pObj); end = Vec_IntEntry(qe, qpos); qpos++; if (end == 'r') { d = FDATA(pObj)->r_dist; // 1. structural edges if (pManMR->fIsForward) { Abc_ObjForEachFanin( pObj, pNext, i ) if (!FDATA(pNext)->e_dist) { FDATA(pNext)->e_dist = d+1; Vec_PtrPush(qn, pNext); Vec_IntPush(qe, 'e'); } } else Abc_ObjForEachFanout( pObj, pNext, i ) if (!FDATA(pNext)->e_dist) { FDATA(pNext)->e_dist = d+1; Vec_PtrPush(qn, pNext); Vec_IntPush(qe, 'e'); } if (d == 1) continue; // 2. reverse edges (forward retiming only) if (pManMR->fIsForward) { Abc_ObjForEachFanout( pObj, pNext, i ) if (!FDATA(pNext)->r_dist && !Abc_ObjIsLatch(pNext)) { FDATA(pNext)->r_dist = d+1; Vec_PtrPush(qn, pNext); Vec_IntPush(qe, 'r'); } // 3. timimg edges (forward retiming only) #if !defined(IGNORE_TIMING) if (pManMR->maxDelay && FDATA(pObj)->vNodes) Vec_PtrForEachEntry(Abc_Obj_t *, FDATA(pObj)->vNodes, pNext, i ) { if (!FDATA(pNext)->r_dist) { FDATA(pNext)->r_dist = d+1; Vec_PtrPush(qn, pNext); Vec_IntPush(qe, 'r'); } } #endif } } else { // if 'e' if (Abc_ObjIsLatch(pObj)) continue; d = FDATA(pObj)->e_dist; // 1. through node if (!FDATA(pObj)->r_dist) { FDATA(pObj)->r_dist = d+1; Vec_PtrPush(qn, pObj); Vec_IntPush(qe, 'r'); } // 2. reverse edges (backward retiming only) if (!pManMR->fIsForward) { Abc_ObjForEachFanin( pObj, pNext, i ) if (!FDATA(pNext)->e_dist && !Abc_ObjIsLatch(pNext)) { FDATA(pNext)->e_dist = d+1; Vec_PtrPush(qn, pNext); Vec_IntPush(qe, 'e'); } // 3. timimg edges (backward retiming only) #if !defined(IGNORE_TIMING) if (pManMR->maxDelay && FDATA(pObj)->vNodes) Vec_PtrForEachEntry(Abc_Obj_t *, FDATA(pObj)->vNodes, pNext, i ) { if (!FDATA(pNext)->e_dist) { FDATA(pNext)->e_dist = d+1; Vec_PtrPush(qn, pNext); Vec_IntPush(qe, 'e'); } } #endif } } } // free time edges #if !defined(IGNORE_TIMING) if (pManMR->maxDelay) { Abc_NtkForEachObj( pNtk, pObj, i ) { vTimeIn = FDATA(pObj)->vNodes; if (vTimeIn) { Vec_PtrFree(vTimeIn); FDATA(pObj)->vNodes = 0; } } } #endif Abc_NtkForEachObj( pNtk, pObj, i ) { Vec_IntAddToEntry(pManMR->vSinkDistHist, FDATA(pObj)->r_dist, 1); Vec_IntAddToEntry(pManMR->vSinkDistHist, FDATA(pObj)->e_dist, 1); #ifdef DEBUG_PREORDER printf("node %d\t: r=%d\te=%d\n", Abc_ObjId(pObj), FDATA(pObj)->r_dist, FDATA(pObj)->e_dist); #endif } // printf("\t\tpre-ordered (max depth=%d)\n", d+1); // deallocate Vec_PtrFree( qn ); Vec_IntFree( qe ); } int dfsfast_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) { int i; Abc_Obj_t *pNext; if (pManMR->fSinkDistTerminate) return 0; // have we reached the sink? if(FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask || Abc_ObjIsPi(pObj)) { assert(pPred); assert(!pManMR->fIsForward); return 1; } FSET(pObj, VISITED_E); #ifdef DEBUG_VISITED printf("(%de=%d) ", Abc_ObjId(pObj), FDATA(pObj)->e_dist); #endif // 1. structural edges if (pManMR->fIsForward) Abc_ObjForEachFanout( pObj, pNext, i ) { if (!FTEST(pNext, VISITED_R) && FDIST(pObj, e, pNext, r) && dfsfast_r(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("o"); #endif goto found; } } else Abc_ObjForEachFanin( pObj, pNext, i ) { if (!FTEST(pNext, VISITED_R) && FDIST(pObj, e, pNext, r) && dfsfast_r(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("o"); #endif goto found; } } if (Abc_ObjIsLatch(pObj)) goto not_found; // 2. reverse edges (backward retiming only) if (!pManMR->fIsForward) { Abc_ObjForEachFanout( pObj, pNext, i ) { if (!FTEST(pNext, VISITED_E) && FDIST(pObj, e, pNext, e) && dfsfast_e(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("i"); #endif goto found; } } // 3. timing edges (backward retiming only) #if !defined(IGNORE_TIMING) if (pManMR->maxDelay) Vec_PtrForEachEntry(Abc_Obj_t *, FTIMEEDGES(pObj), pNext, i) { if (!FTEST(pNext, VISITED_E) && FDIST(pObj, e, pNext, e) && dfsfast_e(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("o"); #endif goto found; } } #endif } // unwind if (FTEST(pObj, FLOW) && !FTEST(pObj, VISITED_R) && FDIST(pObj, e, pObj, r) && dfsfast_r(pObj, FGETPRED(pObj))) { FUNSET(pObj, FLOW); FSETPRED(pObj, NULL); #ifdef DEBUG_PRINT_FLOWS printf("u"); #endif goto found; } not_found: FUNSET(pObj, VISITED_E); dfsfast_e_retreat(pObj); return 0; found: #ifdef DEBUG_PRINT_FLOWS printf("%d ", Abc_ObjId(pObj)); #endif FUNSET(pObj, VISITED_E); return 1; } int dfsfast_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) { int i; Abc_Obj_t *pNext, *pOldPred; if (pManMR->fSinkDistTerminate) return 0; #ifdef DEBUG_VISITED printf("(%dr=%d) ", Abc_ObjId(pObj), FDATA(pObj)->r_dist); #endif // have we reached the sink? if (Abc_ObjIsLatch(pObj) || (pManMR->fIsForward && Abc_ObjIsPo(pObj)) || (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) { assert(pPred); return 1; } FSET(pObj, VISITED_R); if (FTEST(pObj, FLOW)) { pOldPred = FGETPRED(pObj); if (pOldPred && !FTEST(pOldPred, VISITED_E) && FDIST(pObj, r, pOldPred, e) && dfsfast_e(pOldPred, pOldPred)) { FSETPRED(pObj, pPred); #ifdef DEBUG_PRINT_FLOWS printf("fr"); #endif goto found; } } else { if (!FTEST(pObj, VISITED_E) && FDIST(pObj, r, pObj, e) && dfsfast_e(pObj, pObj)) { FSET(pObj, FLOW); FSETPRED(pObj, pPred); #ifdef DEBUG_PRINT_FLOWS printf("f"); #endif goto found; } } // 2. reverse edges (forward retiming only) if (pManMR->fIsForward) { Abc_ObjForEachFanin( pObj, pNext, i ) { if (!FTEST(pNext, VISITED_R) && FDIST(pObj, r, pNext, r) && !Abc_ObjIsLatch(pNext) && dfsfast_r(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("i"); #endif goto found; } } // 3. timing edges (forward retiming only) #if !defined(IGNORE_TIMING) if (pManMR->maxDelay) Vec_PtrForEachEntry(Abc_Obj_t*, FTIMEEDGES(pObj), pNext, i) { if (!FTEST(pNext, VISITED_R) && FDIST(pObj, r, pNext, r) && dfsfast_r(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("o"); #endif goto found; } } #endif } FUNSET(pObj, VISITED_R); dfsfast_r_retreat(pObj); return 0; found: #ifdef DEBUG_PRINT_FLOWS printf("%d ", Abc_ObjId(pObj)); #endif FUNSET(pObj, VISITED_R); return 1; } void dfsfast_e_retreat(Abc_Obj_t *pObj) { Abc_Obj_t *pNext; int i, *h; int old_dist = FDATA(pObj)->e_dist; int adj_dist, min_dist = MAX_DIST; // 1. structural edges if (pManMR->fIsForward) Abc_ObjForEachFanout( pObj, pNext, i ) { adj_dist = FDATA(pNext)->r_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } else Abc_ObjForEachFanin( pObj, pNext, i ) { adj_dist = FDATA(pNext)->r_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } if (Abc_ObjIsLatch(pObj)) goto update; // 2. through if (FTEST(pObj, FLOW)) { adj_dist = FDATA(pObj)->r_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } // 3. reverse edges (backward retiming only) if (!pManMR->fIsForward) { Abc_ObjForEachFanout( pObj, pNext, i ) { adj_dist = FDATA(pNext)->e_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } // 4. timing edges (backward retiming only) #if !defined(IGNORE_TIMING) if (pManMR->maxDelay) Vec_PtrForEachEntry(Abc_Obj_t*, FTIMEEDGES(pObj), pNext, i) { adj_dist = FDATA(pNext)->e_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } #endif } update: ++min_dist; if (min_dist >= MAX_DIST) min_dist = 0; // printf("[%de=%d->%d] ", Abc_ObjId(pObj), old_dist, min_dist+1); FDATA(pObj)->e_dist = min_dist; assert(min_dist < Vec_IntSize(pManMR->vSinkDistHist)); h = Vec_IntArray(pManMR->vSinkDistHist); h[old_dist]--; h[min_dist]++; if (!h[old_dist]) { pManMR->fSinkDistTerminate = 1; } } void dfsfast_r_retreat(Abc_Obj_t *pObj) { Abc_Obj_t *pNext; int i, *h; int old_dist = FDATA(pObj)->r_dist; int adj_dist, min_dist = MAX_DIST; // 1. through or pred if (FTEST(pObj, FLOW)) { if (FGETPRED(pObj)) { adj_dist = FDATA(FGETPRED(pObj))->e_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } } else { adj_dist = FDATA(pObj)->e_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } // 2. reverse edges (forward retiming only) if (pManMR->fIsForward) { Abc_ObjForEachFanin( pObj, pNext, i ) if (!Abc_ObjIsLatch(pNext)) { adj_dist = FDATA(pNext)->r_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } // 3. timing edges (forward retiming only) #if !defined(IGNORE_TIMING) if (pManMR->maxDelay) Vec_PtrForEachEntry(Abc_Obj_t*, FTIMEEDGES(pObj), pNext, i) { adj_dist = FDATA(pNext)->r_dist; if (adj_dist) min_dist = MIN(min_dist, adj_dist); } #endif } ++min_dist; if (min_dist >= MAX_DIST) min_dist = 0; //printf("[%dr=%d->%d] ", Abc_ObjId(pObj), old_dist, min_dist+1); FDATA(pObj)->r_dist = min_dist; assert(min_dist < Vec_IntSize(pManMR->vSinkDistHist)); h = Vec_IntArray(pManMR->vSinkDistHist); h[old_dist]--; h[min_dist]++; if (!h[old_dist]) { pManMR->fSinkDistTerminate = 1; } } /**Function************************************************************* Synopsis [Plain DFS.] Description [Does not use sink-distance-histogram heuristic.] SideEffects [] SeeAlso [] ***********************************************************************/ int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) { int i; Abc_Obj_t *pNext; if (FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask || Abc_ObjIsPi(pObj)) { assert(pPred); assert(!pManMR->fIsForward); return 1; } FSET(pObj, VISITED_E); // printf(" %de\n", Abc_ObjId(pObj)); // 1. structural edges if (pManMR->fIsForward) Abc_ObjForEachFanout( pObj, pNext, i ) { if (!FTEST(pNext, VISITED_R) && dfsplain_r(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("o"); #endif goto found; } } else Abc_ObjForEachFanin( pObj, pNext, i ) { if (!FTEST(pNext, VISITED_R) && dfsplain_r(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("o"); #endif goto found; } } if (Abc_ObjIsLatch(pObj)) return 0; // 2. reverse edges (backward retiming only) if (!pManMR->fIsForward) { Abc_ObjForEachFanout( pObj, pNext, i ) { if (!FTEST(pNext, VISITED_E) && dfsplain_e(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("i"); #endif goto found; } } // 3. timing edges (backward retiming only) #if !defined(IGNORE_TIMING) if (pManMR->maxDelay) Vec_PtrForEachEntry(Abc_Obj_t*, FTIMEEDGES(pObj), pNext, i) { if (!FTEST(pNext, VISITED_E) && dfsplain_e(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("o"); #endif goto found; } } #endif } // unwind if (FTEST(pObj, FLOW) && !FTEST(pObj, VISITED_R) && dfsplain_r(pObj, FGETPRED(pObj))) { FUNSET(pObj, FLOW); FSETPRED(pObj, NULL); #ifdef DEBUG_PRINT_FLOWS printf("u"); #endif goto found; } return 0; found: #ifdef DEBUG_PRINT_FLOWS printf("%d ", Abc_ObjId(pObj)); #endif return 1; } int dfsplain_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ) { int i; Abc_Obj_t *pNext, *pOldPred; // have we reached the sink? if (Abc_ObjIsLatch(pObj) || (pManMR->fIsForward && Abc_ObjIsPo(pObj)) || (pManMR->fIsForward && FTEST(pObj, BLOCK_OR_CONS) & pManMR->constraintMask)) { assert(pPred); return 1; } FSET(pObj, VISITED_R); // printf(" %dr\n", Abc_ObjId(pObj)); if (FTEST(pObj, FLOW)) { pOldPred = FGETPRED(pObj); if (pOldPred && !FTEST(pOldPred, VISITED_E) && dfsplain_e(pOldPred, pOldPred)) { FSETPRED(pObj, pPred); #ifdef DEBUG_PRINT_FLOWS printf("fr"); #endif goto found; } } else { if (!FTEST(pObj, VISITED_E) && dfsplain_e(pObj, pObj)) { FSET(pObj, FLOW); FSETPRED(pObj, pPred); #ifdef DEBUG_PRINT_FLOWS printf("f"); #endif goto found; } } // 2. follow reverse edges if (pManMR->fIsForward) { // forward retiming only Abc_ObjForEachFanin( pObj, pNext, i ) { if (!FTEST(pNext, VISITED_R) && !Abc_ObjIsLatch(pNext) && dfsplain_r(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("i"); #endif goto found; } } // 3. timing edges (forward only) #if !defined(IGNORE_TIMING) if (pManMR->maxDelay) Vec_PtrForEachEntry(Abc_Obj_t*, FTIMEEDGES(pObj), pNext, i) { if (!FTEST(pNext, VISITED_R) && dfsplain_r(pNext, pPred)) { #ifdef DEBUG_PRINT_FLOWS printf("o"); #endif goto found; } } #endif } return 0; found: #ifdef DEBUG_PRINT_FLOWS printf("%d ", Abc_ObjId(pObj)); #endif return 1; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fret/fretInit.c000066400000000000000000001075611300674244400235400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fretInit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Flow-based retiming package.] Synopsis [Initialization for retiming package.] Author [Aaron Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2008.] Revision [$Id: fretInit.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] ***********************************************************************/ #include "fretime.h" #include "base/io/ioAbc.h" #include "map/mio/mio.h" #include "aig/hop/hop.h" #ifdef ABC_USE_CUDD #include "bdd/cudd/cuddInt.h" #endif ABC_NAMESPACE_IMPL_START #undef DEBUG_PRINT_INIT_NTK //////////////////////////////////////////////////////////////////////// /// FUNCTION PROTOTYPES /// //////////////////////////////////////////////////////////////////////// static void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ); static void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk ); static void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ); static Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj ); static void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ); static void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ); static void Abc_FlowRetime_SetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t *pOrig ); static void Abc_FlowRetime_GetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t **pOrig, int *lag ); static void Abc_FlowRetime_ClearInitToOrig( Abc_Obj_t *pInit ); extern void * Abc_FrameReadLibGen(); extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Updates initial state information.] Description [Assumes latch boxes in original position, latches in new positions.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk ) { if (!pManMR->fComputeInitState) return; if (pManMR->fIsForward) Abc_FlowRetime_UpdateForwardInit( pNtk ); else { Abc_FlowRetime_UpdateBackwardInit( pNtk ); } } /**Function************************************************************* Synopsis [Prints initial state information.] Description [Prints distribution of 0,1,and X initial states.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_FlowRetime_ObjFirstNonLatchBox( Abc_Obj_t * pOrigObj, Abc_Obj_t ** pResult ) { int lag = 0; Abc_Ntk_t *pNtk; *pResult = pOrigObj; pNtk = Abc_ObjNtk( pOrigObj ); Abc_NtkIncrementTravId( pNtk ); while( Abc_ObjIsBo(*pResult) || Abc_ObjIsLatch(*pResult) || Abc_ObjIsBi(*pResult) ) { assert(Abc_ObjFaninNum(*pResult)); *pResult = Abc_ObjFanin0(*pResult); if (Abc_NodeIsTravIdCurrent(*pResult)) return -1; Abc_NodeSetTravIdCurrent(*pResult); if (Abc_ObjIsLatch(*pResult)) ++lag; } return lag; } /**Function************************************************************* Synopsis [Prints initial state information.] Description [Prints distribution of 0,1,and X initial states.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk ) { int i, n0=0, n1=0, nDC=0, nOther=0; Abc_Obj_t *pLatch; Abc_NtkForEachLatch( pNtk, pLatch, i ) { if (Abc_LatchIsInit0(pLatch)) n0++; else if (Abc_LatchIsInit1(pLatch)) n1++; else if (Abc_LatchIsInitDc(pLatch)) nDC++; else nOther++; } printf("\tinitial states {0,1,x} = {%d, %d, %d}", n0, n1, nDC); if (nOther) printf(" + %d UNKNOWN", nOther); printf("\n"); } /**Function************************************************************* Synopsis [Computes initial state after forward retiming.] Description [Assumes box outputs in old positions stored w/ init values. Uses three-value simulation to preserve don't cares.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk ) { Abc_Obj_t *pObj, *pFanin; int i; vprintf("\t\tupdating init state\n"); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachLatch( pNtk, pObj, i ) { pFanin = Abc_ObjFanin0(pObj); Abc_FlowRetime_UpdateForwardInit_rec( pFanin ); if (FTEST(pFanin, INIT_0)) Abc_LatchSetInit0( pObj ); else if (FTEST(pFanin, INIT_1)) Abc_LatchSetInit1( pObj ); else Abc_LatchSetInitDc( pObj ); } } void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ) { Abc_Obj_t *pNext; int i; assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs if (Abc_ObjIsBo(pObj)) return; // visited? if (Abc_NodeIsTravIdCurrent(pObj)) return; Abc_NodeSetTravIdCurrent(pObj); Abc_ObjForEachFanin( pObj, pNext, i ) { Abc_FlowRetime_UpdateForwardInit_rec( pNext ); } Abc_FlowRetime_SimulateNode( pObj ); } /**Function************************************************************* Synopsis [Recursively evaluates HOP netlist.] Description [Exponential. There aren't enough flags on a HOP node.] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_FlowRetime_EvalHop_rec( Hop_Man_t *pHop, Hop_Obj_t *pObj, int *f, int *dc ) { int f1, dc1, f2, dc2; Hop_Obj_t *pReg = Hop_Regular(pObj); // const 0 if (Hop_ObjIsConst1(pReg)) { *f = 1; *f ^= (pReg == pObj ? 1 : 0); *dc = 0; return; } // PI if (Hop_ObjIsPi(pReg)) { *f = pReg->fMarkA; *f ^= (pReg == pObj ? 1 : 0); *dc = pReg->fMarkB; return; } // PO if (Hop_ObjIsPo(pReg)) { assert( pReg == pObj ); Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild0(pReg), f, dc); return; } // AND if (Hop_ObjIsAnd(pReg)) { Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild0(pReg), &f1, &dc1); Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild1(pReg), &f2, &dc2); *dc = (dc1 & f2) | (dc2 & f1) | (dc1 & dc2); *f = f1 & f2; *f ^= (pReg == pObj ? 1 : 0); return; } assert(0); } /**Function************************************************************* Synopsis [Sets initial value flags.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_FlowRetime_SetInitValue( Abc_Obj_t * pObj, int val, int dc ) { // store init value FUNSET(pObj, INIT_CARE); if (!dc){ if (val) { FSET(pObj, INIT_1); } else { FSET(pObj, INIT_0); } } } /**Function************************************************************* Synopsis [Propogates initial state through a logic node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ) { Abc_Ntk_t *pNtk = Abc_ObjNtk(pObj); Abc_Obj_t * pFanin; int i, rAnd, rVar, dcAnd, dcVar; #ifdef ABC_USE_CUDD DdManager * dd = (DdManager*)pNtk->pManFunc; DdNode *pBdd = (DdNode*)pObj->pData, *pVar; #endif Hop_Man_t *pHop = (Hop_Man_t*)pNtk->pManFunc; assert(!Abc_ObjIsLatch(pObj)); assert(Abc_ObjRegular(pObj)); // (i) constant nodes if (Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(pObj)) { Abc_FlowRetime_SetInitValue(pObj, 1, 0); return; } if (!Abc_NtkIsStrash( pNtk ) && Abc_ObjIsNode(pObj)) { if (Abc_NodeIsConst0(pObj)) { Abc_FlowRetime_SetInitValue(pObj, 0, 0); return; } else if (Abc_NodeIsConst1(pObj)) { Abc_FlowRetime_SetInitValue(pObj, 1, 0); return; } } // (ii) terminal nodes if (!Abc_ObjIsNode(pObj)) { pFanin = Abc_ObjFanin0(pObj); Abc_FlowRetime_SetInitValue(pObj, (FTEST(pFanin, INIT_1) ? 1 : 0) ^ pObj->fCompl0, !FTEST(pFanin, INIT_CARE)); return; } // (iii) logic nodes // ------ SOP network if ( Abc_NtkHasSop( pNtk )) { Abc_FlowRetime_SimulateSop( pObj, (char *)Abc_ObjData(pObj) ); return; } #ifdef ABC_USE_CUDD // ------ BDD network else if ( Abc_NtkHasBdd( pNtk )) { assert(dd); assert(pBdd); // cofactor for 0,1 inputs // do nothing for X values Abc_ObjForEachFanin(pObj, pFanin, i) { pVar = Cudd_bddIthVar( dd, i ); if (FTEST(pFanin, INIT_CARE)) { if (FTEST(pFanin, INIT_0)) pBdd = Cudd_Cofactor( dd, pBdd, Cudd_Not(pVar) ); else pBdd = Cudd_Cofactor( dd, pBdd, pVar ); } } // if function has not been reduced to // a constant, propagate an X rVar = (pBdd == Cudd_ReadOne(dd)); dcVar = !Cudd_IsConstant(pBdd); Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar); return; } #endif // #ifdef ABC_USE_CUDD // ------ AIG logic network else if ( Abc_NtkHasAig( pNtk ) && !Abc_NtkIsStrash( pNtk )) { assert(Abc_ObjIsNode(pObj)); assert(pObj->pData); assert(Abc_ObjFaninNum(pObj) <= Hop_ManPiNum(pHop) ); // set vals at inputs Abc_ObjForEachFanin(pObj, pFanin, i) { Hop_ManPi(pHop, i)->fMarkA = FTEST(pFanin, INIT_1)?1:0; Hop_ManPi(pHop, i)->fMarkB = FTEST(pFanin, INIT_CARE)?1:0; } Abc_FlowRetime_EvalHop_rec( pHop, (Hop_Obj_t*)pObj->pData, &rVar, &dcVar ); Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar); // clear flags Abc_ObjForEachFanin(pObj, pFanin, i) { Hop_ManPi(pHop, i)->fMarkA = 0; Hop_ManPi(pHop, i)->fMarkB = 0; } return; } // ------ strashed network else if ( Abc_NtkIsStrash( pNtk )) { assert(Abc_ObjType(pObj) == ABC_OBJ_NODE); dcAnd = 0, rAnd = 1; pFanin = Abc_ObjFanin0(pObj); dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1; rVar = FTEST(pFanin, INIT_0) ? 0 : 1; if (pObj->fCompl0) rVar ^= 1; // complimented? rAnd &= rVar; pFanin = Abc_ObjFanin1(pObj); dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1; rVar = FTEST(pFanin, INIT_0) ? 0 : 1; if (pObj->fCompl1) rVar ^= 1; // complimented? rAnd &= rVar; if (!rAnd) dcAnd = 0; /* controlling value */ Abc_FlowRetime_SetInitValue(pObj, rAnd, dcAnd); return; } // ------ MAPPED network else if ( Abc_NtkHasMapping( pNtk )) { Abc_FlowRetime_SimulateSop( pObj, (char *)Mio_GateReadSop((Mio_Gate_t*)pObj->pData) ); return; } assert(0); } /**Function************************************************************* Synopsis [Propogates initial state through a SOP node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ) { Abc_Obj_t * pFanin; char *pCube; int i, j, rAnd, rOr, rVar, dcAnd, dcOr, v; assert( pSop && !Abc_SopIsExorType(pSop) ); rOr = 0, dcOr = 0; i = Abc_SopGetVarNum(pSop); Abc_SopForEachCube( pSop, i, pCube ) { rAnd = 1, dcAnd = 0; Abc_CubeForEachVar( pCube, v, j ) { pFanin = Abc_ObjFanin(pObj, j); if ( v == '0' ) rVar = FTEST(pFanin, INIT_0) ? 1 : 0; else if ( v == '1' ) rVar = FTEST(pFanin, INIT_1) ? 1 : 0; else continue; if (FTEST(pFanin, INIT_CARE)) rAnd &= rVar; else dcAnd = 1; } if (!rAnd) dcAnd = 0; /* controlling value */ if (dcAnd) dcOr = 1; else rOr |= rAnd; } if (rOr) dcOr = 0; /* controlling value */ // complement the result if necessary if ( !Abc_SopGetPhase(pSop) ) rOr ^= 1; Abc_FlowRetime_SetInitValue(pObj, rOr, dcOr); } /**Function************************************************************* Synopsis [Sets up backward initial state computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) { Abc_Obj_t *pLatch, *pObj, *pPi; int i; Vec_Ptr_t *vObj = Vec_PtrAlloc(100); // create the network used for the initial state computation if (Abc_NtkIsStrash(pNtk)) { pManMR->pInitNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); } else if (Abc_NtkHasMapping(pNtk)) pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, ABC_FUNC_SOP, 1 ); else pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // mitre inputs Abc_NtkForEachLatch( pNtk, pLatch, i ) { // map latch to initial state network pPi = Abc_NtkCreatePi( pManMR->pInitNtk ); // DEBUG // printf("setup : mapping latch %d to PI %d\n", pLatch->Id, pPi->Id); // has initial state requirement? if (Abc_LatchIsInit0(pLatch)) { pObj = Abc_NtkCreateNodeInv( pManMR->pInitNtk, pPi ); Vec_PtrPush(vObj, pObj); } else if (Abc_LatchIsInit1(pLatch)) { Vec_PtrPush(vObj, pPi); } Abc_ObjSetData( pLatch, pPi ); // if not verifying init state // FDATA(pLatch)->pInitObj = pPi; // if verifying init state } // are there any nodes not DC? if (!Vec_PtrSize(vObj)) { pManMR->fSolutionIsDc = 1; return; } else pManMR->fSolutionIsDc = 0; // mitre output // create n-input AND gate pObj = Abc_NtkCreateNodeAnd( pManMR->pInitNtk, vObj ); Abc_ObjAddFanin( Abc_NtkCreatePo( pManMR->pInitNtk ), pObj ); Vec_PtrFree( vObj ); } /**Function************************************************************* Synopsis [Solves backward initial state computation.] Description [] SideEffects [Sets object copies in init ntk.] SeeAlso [] ***********************************************************************/ int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) { int i; Abc_Obj_t *pObj, *pInitObj; Vec_Ptr_t *vDelete = Vec_PtrAlloc(0); Abc_Ntk_t *pSatNtk; int result; assert(pManMR->pInitNtk); // is the solution entirely DC's? if (pManMR->fSolutionIsDc) { Vec_PtrFree(vDelete); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj ); vprintf("\tno init state computation: all-don't-care solution\n"); return 1; } // check that network is combinational Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) { assert(!Abc_ObjIsLatch(pObj)); assert(!Abc_ObjIsBo(pObj)); assert(!Abc_ObjIsBi(pObj)); } // delete superfluous nodes while(Vec_PtrSize( vDelete )) { pObj = (Abc_Obj_t *)Vec_PtrPop( vDelete ); Abc_NtkDeleteObj( pObj ); } Vec_PtrFree(vDelete); // do some final cleanup on the network Abc_NtkAddDummyPoNames(pManMR->pInitNtk); Abc_NtkAddDummyPiNames(pManMR->pInitNtk); if (Abc_NtkIsLogic(pManMR->pInitNtk)) Abc_NtkCleanup(pManMR->pInitNtk, 0); #if defined(DEBUG_PRINT_INIT_NTK) Abc_NtkLevelReverse( pManMR->pInitNtk ); Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) if (Abc_ObjLevel( pObj ) < 2) Abc_ObjPrint(stdout, pObj); #endif vprintf("\tsolving for init state (%d nodes)... ", Abc_NtkObjNum(pManMR->pInitNtk)); fflush(stdout); #ifdef ABC_USE_CUDD // convert SOPs to BDD if (Abc_NtkHasSop(pManMR->pInitNtk)) Abc_NtkSopToBdd( pManMR->pInitNtk ); // convert AIGs to BDD if (Abc_NtkHasAig(pManMR->pInitNtk)) Abc_NtkAigToBdd( pManMR->pInitNtk ); #else // convert SOPs to AIG if (Abc_NtkHasSop(pManMR->pInitNtk)) Abc_NtkSopToAig( pManMR->pInitNtk ); #endif pSatNtk = pManMR->pInitNtk; // solve result = Abc_NtkMiterSat( pSatNtk, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL ); if (!result) { vprintf("SUCCESS\n"); } else { vprintf("FAILURE\n"); return 0; } // clear initial values, associate PIs to latches Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) Abc_ObjSetCopy( pInitObj, NULL ); Abc_NtkForEachLatch( pNtk, pObj, i ) { pInitObj = (Abc_Obj_t*)Abc_ObjData( pObj ); assert( Abc_ObjIsPi( pInitObj )); Abc_ObjSetCopy( pInitObj, pObj ); Abc_LatchSetInitNone( pObj ); // DEBUG // printf("solve : getting latch %d from PI %d\n", pObj->Id, pInitObj->Id); } // copy solution from PIs to latches assert(pManMR->pInitNtk->pModel); Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) { if ((pObj = Abc_ObjCopy( pInitObj ))) { if ( pManMR->pInitNtk->pModel[i] ) Abc_LatchSetInit1( pObj ); else Abc_LatchSetInit0( pObj ); } } #if defined(DEBUG_CHECK) // check that all latches have initial state Abc_NtkForEachLatch( pNtk, pObj, i ) assert( !Abc_LatchIsInitNone( pObj ) ); #endif return 1; } /**Function************************************************************* Synopsis [Updates backward initial state computation problem.] Description [Assumes box outputs in old positions stored w/ init values.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) { Abc_Obj_t *pOrigObj, *pInitObj; Vec_Ptr_t *vBo = Vec_PtrAlloc(100); Vec_Ptr_t *vPi = Vec_PtrAlloc(100); Abc_Ntk_t *pInitNtk = pManMR-> pInitNtk; Abc_Obj_t *pBuf; int i; // remove PIs from network (from BOs) Abc_NtkForEachObj( pNtk, pOrigObj, i ) if (Abc_ObjIsBo(pOrigObj)) { pInitObj = FDATA(pOrigObj)->pInitObj; assert(Abc_ObjIsPi(pInitObj)); // DEBUG // printf("update : freeing PI %d\n", pInitObj->Id); // create a buffer instead pBuf = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); Abc_FlowRetime_ClearInitToOrig( pBuf ); Abc_ObjBetterTransferFanout( pInitObj, pBuf, 0 ); FDATA(pOrigObj)->pInitObj = pBuf; pOrigObj->fMarkA = 1; Vec_PtrPush(vBo, pOrigObj); Vec_PtrPush(vPi, pInitObj); } // check that PIs are all free Abc_NtkForEachPi( pInitNtk, pInitObj, i) { assert( Abc_ObjFanoutNum( pInitObj ) == 0); } // add PIs to to latches Abc_NtkForEachLatch( pNtk, pOrigObj, i ) { assert(Vec_PtrSize(vPi) > 0); pInitObj = (Abc_Obj_t*)Vec_PtrPop(vPi); // DEBUG // printf("update : mapping latch %d to PI %d\n", pOrigObj->Id, pInitObj->Id); pOrigObj->fMarkA = pOrigObj->fMarkB = 1; FDATA(pOrigObj)->pInitObj = pInitObj; Abc_ObjSetData(pOrigObj, pInitObj); } // recursively build init network Vec_PtrForEachEntry( Abc_Obj_t *, vBo, pOrigObj, i ) Abc_FlowRetime_UpdateBackwardInit_rec( pOrigObj ); // clear flags Abc_NtkForEachObj( pNtk, pOrigObj, i ) pOrigObj->fMarkA = pOrigObj->fMarkB = 0; // deallocate Vec_PtrFree( vBo ); Vec_PtrFree( vPi ); } /**Function************************************************************* Synopsis [Creates a corresponding node in the init state network] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t *Abc_FlowRetime_CopyNodeToInitNtk( Abc_Obj_t *pOrigObj ) { Abc_Ntk_t *pNtk = pManMR->pNtk; Abc_Ntk_t *pInitNtk = pManMR->pInitNtk; Abc_Obj_t *pInitObj; void *pData; int fCompl[2]; assert(pOrigObj); // what we do depends on the ntk types of original / init networks... // (0) convert BI/BO nodes to buffers if (Abc_ObjIsBi( pOrigObj ) || Abc_ObjIsBo( pOrigObj ) ) { pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); Abc_FlowRetime_ClearInitToOrig( pInitObj ); return pInitObj; } // (i) strash node -> SOP node if (Abc_NtkIsStrash( pNtk )) { if (Abc_AigNodeIsConst( pOrigObj )) { return Abc_NtkCreateNodeConst1( pInitNtk ); } if (!Abc_ObjIsNode( pOrigObj )) { assert(Abc_ObjFaninNum(pOrigObj) == 1); pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); Abc_FlowRetime_ClearInitToOrig( pInitObj ); return pInitObj; } assert( Abc_ObjIsNode(pOrigObj) ); pInitObj = Abc_NtkCreateObj( pInitNtk, ABC_OBJ_NODE ); fCompl[0] = pOrigObj->fCompl0 ? 1 : 0; fCompl[1] = pOrigObj->fCompl1 ? 1 : 0; pData = Abc_SopCreateAnd( (Mem_Flex_t *)pInitNtk->pManFunc, 2, fCompl ); assert(pData); pInitObj->pData = Abc_SopRegister( (Mem_Flex_t *)pInitNtk->pManFunc, (const char*)pData ); } // (ii) mapped node -> SOP node else if (Abc_NtkHasMapping( pNtk )) { if (!pOrigObj->pData) { // assume terminal... assert(Abc_ObjFaninNum(pOrigObj) == 1); pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); Abc_FlowRetime_ClearInitToOrig( pInitObj ); return pInitObj; } pInitObj = Abc_NtkCreateObj( pInitNtk, (Abc_ObjType_t)Abc_ObjType(pOrigObj) ); pData = Mio_GateReadSop((Mio_Gate_t*)pOrigObj->pData); assert( Abc_SopGetVarNum((char*)pData) == Abc_ObjFaninNum(pOrigObj) ); pInitObj->pData = Abc_SopRegister( (Mem_Flex_t *)pInitNtk->pManFunc, (const char*)pData ); } // (iii) otherwise, duplicate obj else { pInitObj = Abc_NtkDupObj( pInitNtk, pOrigObj, 0 ); // copy phase pInitObj->fPhase = pOrigObj->fPhase; } assert(pInitObj); return pInitObj; } /**Function************************************************************* Synopsis [Updates backward initial state computation problem.] Description [Creates a duplicate node in the initial state network corresponding to a node in the original circuit. If fRecurse is set, the procedure recurses on and connects the new node to its fan-ins. A latch in the original circuit corresponds to a PI in the initial state network. An existing PI may be supplied by pUseThisPi, and if the node is a latch, it will be used; otherwise the PI is saved in the list vOtherPis and subsequently used for another latch.] SideEffects [Nodes that have a corresponding initial state node are marked with fMarkA. Nodes that have been fully connected in the initial state network are marked with fMarkB.] SeeAlso [] ***********************************************************************/ Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj) { Abc_Obj_t *pOrigFanin, *pInitFanin, *pInitObj; int i; assert(pOrigObj); // should never reach primary IOs assert(!Abc_ObjIsPi(pOrigObj)); assert(!Abc_ObjIsPo(pOrigObj)); // skip bias nodes if (FTEST(pOrigObj, BIAS_NODE)) return NULL; // does an init node already exist? if(!pOrigObj->fMarkA) { pInitObj = Abc_FlowRetime_CopyNodeToInitNtk( pOrigObj ); Abc_FlowRetime_SetInitToOrig( pInitObj, pOrigObj ); FDATA(pOrigObj)->pInitObj = pInitObj; pOrigObj->fMarkA = 1; } else { pInitObj = FDATA(pOrigObj)->pInitObj; } assert(pInitObj); // have we already connected this object? if (!pOrigObj->fMarkB) { // create and/or connect fanins Abc_ObjForEachFanin( pOrigObj, pOrigFanin, i ) { // should not reach BOs (i.e. the start of the next frame) // the new latch bounday should lie before it assert(!Abc_ObjIsBo( pOrigFanin )); pInitFanin = Abc_FlowRetime_UpdateBackwardInit_rec( pOrigFanin ); Abc_ObjAddFanin( pInitObj, pInitFanin ); } pOrigObj->fMarkB = 1; } return pInitObj; } /**Function************************************************************* Synopsis [Verifies backward init state computation.] Description [This procedure requires the BOs to store the original latch values and the latches to store the new values: both in the INIT_0 and INIT_1 flags in the Flow_Data structure. (This is not currently the case in the rest of the code.) Also, can not verify backward state computations that span multiple combinational frames.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk ) { Abc_Obj_t *pObj, *pFanin; int i; vprintf("\t\tupdating init state\n"); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachObj( pNtk, pObj, i ) if (Abc_ObjIsBo( pObj )) { pFanin = Abc_ObjFanin0(pObj); Abc_FlowRetime_VerifyBackwardInit_rec( pFanin ); if (FTEST(pObj, INIT_CARE)) { if(FTEST(pObj, INIT_CARE) != FTEST(pFanin, INIT_CARE)) { printf("ERROR: expected val=%d care=%d and got val=%d care=%d\n", FTEST(pObj, INIT_1)?1:0, FTEST(pObj, INIT_CARE)?1:0, FTEST(pFanin, INIT_1)?1:0, FTEST(pFanin, INIT_CARE)?1:0 ); } } } } void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ) { Abc_Obj_t *pNext; int i; assert(!Abc_ObjIsBo(pObj)); // should never reach the inputs assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs // visited? if (Abc_NodeIsTravIdCurrent(pObj)) return; Abc_NodeSetTravIdCurrent(pObj); if (Abc_ObjIsLatch(pObj)) { FUNSET(pObj, INIT_CARE); if (Abc_LatchIsInit0(pObj)) FSET(pObj, INIT_0); else if (Abc_LatchIsInit1(pObj)) FSET(pObj, INIT_1); return; } Abc_ObjForEachFanin( pObj, pNext, i ) { Abc_FlowRetime_VerifyBackwardInit_rec( pNext ); } Abc_FlowRetime_SimulateNode( pObj ); } /**Function************************************************************* Synopsis [Constrains backward retiming for initializability.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FlowRetime_PartialSat(Vec_Ptr_t *vNodes, int cut) { Abc_Ntk_t *pPartNtk, *pInitNtk = pManMR->pInitNtk; Abc_Obj_t *pObj, *pNext, *pPartObj, *pPartNext, *pPo; int i, j, result; assert( Abc_NtkPoNum( pInitNtk ) == 1 ); pPartNtk = Abc_NtkAlloc( pInitNtk->ntkType, pInitNtk->ntkFunc, 0 ); // copy network Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { pObj->Level = i; assert(!Abc_ObjIsPo( pObj )); if (i < cut && !pObj->fMarkA) { pPartObj = Abc_NtkCreatePi( pPartNtk ); Abc_ObjSetCopy( pObj, pPartObj ); } else { // copy node pPartObj = Abc_NtkDupObj( pPartNtk, pObj, 0 ); // copy complementation pPartObj->fPhase = pObj->fPhase; // connect fanins Abc_ObjForEachFanin( pObj, pNext, j ) { pPartNext = Abc_ObjCopy( pNext ); assert(pPartNext); Abc_ObjAddFanin( pPartObj, pPartNext ); } } assert(pObj->pCopy == pPartObj); } // create PO pPo = Abc_NtkCreatePo( pPartNtk ); pNext = Abc_ObjFanin0( Abc_NtkPo( pInitNtk, 0 ) ); pPartNext = Abc_ObjCopy( pNext ); assert( pPartNext ); Abc_ObjAddFanin( pPo, pPartNext ); // check network #if defined(DEBUG_CHECK) Abc_NtkAddDummyPoNames(pPartNtk); Abc_NtkAddDummyPiNames(pPartNtk); Abc_NtkCheck( pPartNtk ); #endif result = Abc_NtkMiterSat( pPartNtk, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL ); Abc_NtkDelete( pPartNtk ); return !result; } /**Function************************************************************* Synopsis [Constrains backward retiming for initializability.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_ConstrainInit( ) { Vec_Ptr_t *vNodes; int low, high, mid; int i, n, lag; Abc_Obj_t *pObj = NULL, *pOrigObj; InitConstraint_t *pConstraint = ABC_ALLOC( InitConstraint_t, 1 ); memset( pConstraint, 0, sizeof(InitConstraint_t) ); assert(pManMR->pInitNtk); vprintf("\tsearch for initial state conflict...\n"); vNodes = Abc_NtkDfs(pManMR->pInitNtk, 0); n = Vec_PtrSize(vNodes); // also add PIs to vNodes Abc_NtkForEachPi(pManMR->pInitNtk, pObj, i) Vec_PtrPush(vNodes, pObj); Vec_PtrReorder(vNodes, n); #if defined(DEBUG_CHECK) assert(!Abc_FlowRetime_PartialSat( vNodes, 0 )); #endif // grow initialization constraint do { vprintf("\t\t"); // find element to add to set... low = 0, high = Vec_PtrSize(vNodes); while (low != high-1) { mid = (low + high) >> 1; if (!Abc_FlowRetime_PartialSat( vNodes, mid )) { low = mid; vprintf("-"); } else { high = mid; vprintf("*"); } fflush(stdout); } #if defined(DEBUG_CHECK) assert(Abc_FlowRetime_PartialSat( vNodes, high )); assert(!Abc_FlowRetime_PartialSat( vNodes, low )); #endif // mark its TFO pObj = (Abc_Obj_t*)Vec_PtrEntry( vNodes, low ); Abc_NtkMarkCone_rec( pObj, 1 ); vprintf(" conflict term = %d ", low); #if 0 printf("init ------\n"); Abc_ObjPrint(stdout, pObj); printf("\n"); Abc_ObjPrintNeighborhood( pObj, 1 ); printf("------\n"); #endif // add node to constraint Abc_FlowRetime_GetInitToOrig( pObj, &pOrigObj, &lag ); assert(pOrigObj); vprintf(" <=> %d/%d\n", Abc_ObjId(pOrigObj), lag); #if 0 printf("orig ------\n"); Abc_ObjPrint(stdout, pOrigObj); printf("\n"); Abc_ObjPrintNeighborhood( pOrigObj, 1 ); printf("------\n"); #endif Vec_IntPush( &pConstraint->vNodes, Abc_ObjId(pOrigObj) ); Vec_IntPush( &pConstraint->vLags, lag ); } while (Abc_FlowRetime_PartialSat( vNodes, Vec_PtrSize(vNodes) )); pConstraint->pBiasNode = NULL; // add constraint Vec_PtrPush( pManMR->vInitConstraints, pConstraint ); // clear marks Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i) pObj->fMarkA = 0; // free Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Removes nodes to bias against uninitializable cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_RemoveInitBias( ) { // Abc_Ntk_t *pNtk = pManMR->pNtk; Abc_Obj_t *pBiasNode; InitConstraint_t *pConstraint; int i; Vec_PtrForEachEntry( InitConstraint_t *, pManMR->vInitConstraints, pConstraint, i ) { pBiasNode = pConstraint->pBiasNode; pConstraint->pBiasNode = NULL; if (pBiasNode) Abc_NtkDeleteObj(pBiasNode); } } /**Function************************************************************* Synopsis [Connects the bias node to one of the constraint vertices.] Description [ACK! Currently this is dumb dumb hack. What should we do with biases that belong on BOs? These move through the circuit. Currently, the bias gets marked on the fan-in of BO and the bias gets implemented on every BO fan-out of a node.] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_FlowRetime_ConnectBiasNode(Abc_Obj_t *pBiasNode, Abc_Obj_t *pObj, int biasLag) { Abc_Obj_t *pCur, *pNext; int i; int lag; Vec_Ptr_t *vNodes = Vec_PtrAlloc(1); Vec_Int_t *vLags = Vec_IntAlloc(1); Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj ); Vec_PtrPush( vNodes, pObj ); Vec_IntPush( vLags, 0 ); Abc_NtkIncrementTravId( pNtk ); while (Vec_PtrSize( vNodes )) { pCur = (Abc_Obj_t*)Vec_PtrPop( vNodes ); lag = Vec_IntPop( vLags ); if (Abc_NodeIsTravIdCurrent( pCur )) continue; Abc_NodeSetTravIdCurrent( pCur ); if (!Abc_ObjIsLatch(pCur) && !Abc_ObjIsBo(pCur) && Abc_FlowRetime_GetLag(pObj)+lag == biasLag ) { // printf("biasing : "); // Abc_ObjPrint(stdout, pCur ); #if 1 FSET( pCur, BLOCK ); #else Abc_ObjAddFanin( pCur, pBiasNode ); #endif } Abc_ObjForEachFanout( pCur, pNext, i ) { if (Abc_ObjIsBi(pNext) || Abc_ObjIsLatch(pNext) || Abc_ObjIsBo(pNext) || Abc_ObjIsBo(pCur)) { Vec_PtrPush( vNodes, pNext ); Vec_IntPush( vLags, lag - Abc_ObjIsLatch(pNext) ? 1 : 0 ); } } } Vec_PtrFree( vNodes ); Vec_IntFree( vLags ); } /**Function************************************************************* Synopsis [Adds nodes to bias against uninitializable cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_AddInitBias( ) { Abc_Ntk_t *pNtk = pManMR->pNtk; Abc_Obj_t *pBiasNode, *pObj; InitConstraint_t *pConstraint; int i, j, id; const int nConstraints = Vec_PtrSize( pManMR->vInitConstraints ); pManMR->pDataArray = ABC_REALLOC( Flow_Data_t, pManMR->pDataArray, pManMR->nNodes + (nConstraints*(pManMR->iteration+1)) ); memset(pManMR->pDataArray + pManMR->nNodes, 0, sizeof(Flow_Data_t)*(nConstraints*(pManMR->iteration+1))); vprintf("\t\tcreating %d bias structures\n", nConstraints); Vec_PtrForEachEntry(InitConstraint_t*, pManMR->vInitConstraints, pConstraint, i ) { if (pConstraint->pBiasNode) continue; // printf("\t\t\tbias %d...\n", i); pBiasNode = Abc_NtkCreateBlackbox( pNtk ); Vec_IntForEachEntry( &pConstraint->vNodes, id, j ) { pObj = Abc_NtkObj(pNtk, id); Abc_FlowRetime_ConnectBiasNode(pBiasNode, pObj, Vec_IntEntry(&pConstraint->vLags, j)); } // pConstraint->pBiasNode = pBiasNode; } } /**Function************************************************************* Synopsis [Clears mapping from init node to original node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_ClearInitToOrig( Abc_Obj_t *pInit ) { int id = Abc_ObjId( pInit ); // grow data structure if necessary if (id >= pManMR->sizeInitToOrig) { int oldSize = pManMR->sizeInitToOrig; pManMR->sizeInitToOrig = 1.5*id + 10; pManMR->pInitToOrig = (NodeLag_t*)realloc(pManMR->pInitToOrig, sizeof(NodeLag_t)*pManMR->sizeInitToOrig); memset( &(pManMR->pInitToOrig[oldSize]), 0, sizeof(NodeLag_t)*(pManMR->sizeInitToOrig-oldSize) ); } assert( pManMR->pInitToOrig ); pManMR->pInitToOrig[id].id = -1; } /**Function************************************************************* Synopsis [Sets mapping from init node to original node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_SetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t *pOrig) { int lag; int id = Abc_ObjId( pInit ); // grow data structure if necessary if (id >= pManMR->sizeInitToOrig) { int oldSize = pManMR->sizeInitToOrig; pManMR->sizeInitToOrig = 1.5*id + 10; pManMR->pInitToOrig = (NodeLag_t*)realloc(pManMR->pInitToOrig, sizeof(NodeLag_t)*pManMR->sizeInitToOrig); memset( &(pManMR->pInitToOrig[oldSize]), 0, sizeof(NodeLag_t)*(pManMR->sizeInitToOrig-oldSize) ); } assert( pManMR->pInitToOrig ); // ignore BI, BO, and latch nodes if (Abc_ObjIsBo(pOrig) || Abc_ObjIsBi(pOrig) || Abc_ObjIsLatch(pOrig)) { Abc_FlowRetime_ClearInitToOrig(pInit); return; } // move out of latch boxes lag = Abc_FlowRetime_ObjFirstNonLatchBox(pOrig, &pOrig); pManMR->pInitToOrig[id].id = Abc_ObjId(pOrig); pManMR->pInitToOrig[id].lag = Abc_FlowRetime_GetLag(pOrig) + lag; } /**Function************************************************************* Synopsis [Gets mapping from init node to original node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_GetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t **pOrig, int *lag ) { int id = Abc_ObjId( pInit ); int origId; assert(id < pManMR->sizeInitToOrig); origId = pManMR->pInitToOrig[id].id; if (origId < 0) { assert(Abc_ObjFaninNum(pInit)); Abc_FlowRetime_GetInitToOrig( Abc_ObjFanin0(pInit), pOrig, lag); return; } *pOrig = Abc_NtkObj(pManMR->pNtk, origId); *lag = pManMR->pInitToOrig[id].lag; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fret/fretMain.c000066400000000000000000001121121300674244400235050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fretMain.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Flow-based retiming package.] Synopsis [Main file for retiming package.] Author [Aaron Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2008.] Revision [$Id: fretMain.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] ***********************************************************************/ #include "fretime.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj ); static Abc_Ntk_t* Abc_FlowRetime_MainLoop( ); static void Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ); static void Abc_FlowRetime_MarkReachable_rec( Abc_Obj_t * pObj, char end ); static int Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ); static void Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch ); static Abc_Ntk_t* Abc_FlowRetime_NtkDup( Abc_Ntk_t * pNtk ); static void Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk ); static int Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD ); static void Abc_FlowRetime_UpdateLags_forw_rec( Abc_Obj_t *pObj ); static void Abc_FlowRetime_UpdateLags_back_rec( Abc_Obj_t *pObj ); extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ); void print_node3(Abc_Obj_t *pObj); MinRegMan_t *pManMR; int fPathError = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs minimum-register retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState, int fGuaranteeInitState, int fBlockConst, int fForwardOnly, int fBackwardOnly, int nMaxIters, int maxDelay, int fFastButConservative ) { int i; Abc_Obj_t *pObj, *pNext; InitConstraint_t *pData; // create manager pManMR = ABC_ALLOC( MinRegMan_t, 1 ); pManMR->pNtk = pNtk; pManMR->fVerbose = fVerbose; pManMR->fComputeInitState = fComputeInitState; pManMR->fGuaranteeInitState = fGuaranteeInitState; pManMR->fBlockConst = fBlockConst; pManMR->fForwardOnly = fForwardOnly; pManMR->fBackwardOnly = fBackwardOnly; pManMR->nMaxIters = nMaxIters; pManMR->maxDelay = maxDelay; pManMR->fComputeInitState = fComputeInitState; pManMR->fConservTimingOnly = fFastButConservative; pManMR->vNodes = Vec_PtrAlloc(100); pManMR->vInitConstraints = Vec_PtrAlloc(2); pManMR->pInitNtk = NULL; pManMR->pInitToOrig = NULL; pManMR->sizeInitToOrig = 0; vprintf("Flow-based minimum-register retiming...\n"); if (!Abc_NtkHasOnlyLatchBoxes(pNtk)) { printf("\tERROR: Can not retime with black/white boxes\n"); return pNtk; } if (maxDelay) { vprintf("\tmax delay constraint = %d\n", maxDelay); if (maxDelay < (i = Abc_NtkLevel(pNtk))) { printf("ERROR: max delay constraint (%d) must be > current max delay (%d)\n", maxDelay, i); return pNtk; } } // print info about type of network vprintf("\tnetlist type = "); if (Abc_NtkIsNetlist( pNtk )) { vprintf("netlist/"); } else if (Abc_NtkIsLogic( pNtk )) { vprintf("logic/"); } else if (Abc_NtkIsStrash( pNtk )) { vprintf("strash/"); } else { vprintf("***unknown***/"); } if (Abc_NtkHasSop( pNtk )) { vprintf("sop\n"); } else if (Abc_NtkHasBdd( pNtk )) { vprintf("bdd\n"); } else if (Abc_NtkHasAig( pNtk )) { vprintf("aig\n"); } else if (Abc_NtkHasMapping( pNtk )) { vprintf("mapped\n"); } else { vprintf("***unknown***\n"); } vprintf("\tinitial reg count = %d\n", Abc_NtkLatchNum(pNtk)); vprintf("\tinitial levels = %d\n", Abc_NtkLevel(pNtk)); // remove bubbles from latch boxes if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk); vprintf("\tpushing bubbles out of latch boxes\n"); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_FlowRetime_RemoveLatchBubbles(pObj); if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk); // check for box inputs/outputs Abc_NtkForEachLatch( pNtk, pObj, i ) { assert(Abc_ObjFaninNum(pObj) == 1); assert(Abc_ObjFanoutNum(pObj) == 1); assert(!Abc_ObjFaninC0(pObj)); pNext = Abc_ObjFanin0(pObj); assert(Abc_ObjIsBi(pNext)); assert(Abc_ObjFaninNum(pNext) <= 1); if(Abc_ObjFaninNum(pNext) == 0) // every Bi should have a fanin Abc_FlowRetime_AddDummyFanin( pNext ); pNext = Abc_ObjFanout0(pObj); assert(Abc_ObjIsBo(pNext)); assert(Abc_ObjFaninNum(pNext) == 1); assert(!Abc_ObjFaninC0(pNext)); } pManMR->nLatches = Abc_NtkLatchNum( pNtk ); pManMR->nNodes = Abc_NtkObjNumMax( pNtk )+1; // build histogram pManMR->vSinkDistHist = Vec_IntStart( pManMR->nNodes*2+10 ); // initialize timing if (maxDelay) Abc_FlowRetime_InitTiming( pNtk ); // create lag and Flow_Data structure pManMR->vLags = Vec_IntStart(pManMR->nNodes); memset(pManMR->vLags->pArray, 0, sizeof(int)*pManMR->nNodes); pManMR->pDataArray = ABC_ALLOC( Flow_Data_t, pManMR->nNodes ); Abc_FlowRetime_ClearFlows( 1 ); // main loop! pNtk = Abc_FlowRetime_MainLoop(); // cleanup node fields Abc_NtkForEachObj( pNtk, pObj, i ) { // if not computing init state, set all latches to DC if (!fComputeInitState && Abc_ObjIsLatch(pObj)) Abc_LatchSetInitDc(pObj); } // deallocate space ABC_FREE( pManMR->pDataArray ); if (pManMR->pInitToOrig) ABC_FREE( pManMR->pInitToOrig ); if (pManMR->vNodes) Vec_PtrFree(pManMR->vNodes); if (pManMR->vLags) Vec_IntFree(pManMR->vLags); if (pManMR->vSinkDistHist) Vec_IntFree(pManMR->vSinkDistHist); if (pManMR->maxDelay) Abc_FlowRetime_FreeTiming( pNtk ); while( Vec_PtrSize( pManMR->vInitConstraints )) { pData = (InitConstraint_t*)Vec_PtrPop( pManMR->vInitConstraints ); //assert( pData->pBiasNode ); //Abc_NtkDeleteObj( pData->pBiasNode ); ABC_FREE( pData->vNodes.pArray ); ABC_FREE( pData ); } ABC_FREE( pManMR->vInitConstraints ); // restrash if necessary if (Abc_NtkIsStrash(pNtk)) { Abc_NtkReassignIds( pNtk ); pNtk = Abc_FlowRetime_NtkSilentRestrash( pNtk, 1 ); } vprintf("\tfinal reg count = %d\n", Abc_NtkLatchNum(pNtk)); vprintf("\tfinal levels = %d\n", Abc_NtkLevel(pNtk)); #if defined(DEBUG_CHECK) Abc_NtkDoCheck( pNtk ); #endif // free manager ABC_FREE( pManMR ); return pNtk; } /**Function************************************************************* Synopsis [Main loop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_FlowRetime_MainLoop( ) { Abc_Ntk_t *pNtk = pManMR->pNtk, *pNtkCopy = pNtk; Abc_Obj_t *pObj; int i; int last, flow = 0, cut; // (i) forward retiming loop pManMR->fIsForward = 1; pManMR->iteration = 0; if (!pManMR->fBackwardOnly) do { if (pManMR->iteration == pManMR->nMaxIters) break; pManMR->subIteration = 0; vprintf("\tforward iteration %d\n", pManMR->iteration); last = Abc_NtkLatchNum( pNtk ); Abc_FlowRetime_MarkBlocks( pNtk ); if (pManMR->maxDelay) { // timing-constrained loop Abc_FlowRetime_ConstrainConserv( pNtk ); while(Abc_FlowRetime_RefineConstraints( )) { pManMR->subIteration++; Abc_FlowRetime_ClearFlows( 0 ); } } else { flow = Abc_FlowRetime_PushFlows( pNtk, 1 ); } cut = Abc_FlowRetime_ImplementCut( pNtk ); #if defined (DEBUG_PRINT_LEVELS) vprintf("\t\tlevels = %d\n", Abc_NtkLevel(pNtk)); #endif Abc_FlowRetime_ClearFlows( 1 ); pManMR->iteration++; } while( cut != last ); // intermediate cleanup (for strashed networks) if (Abc_NtkIsStrash(pNtk)) { Abc_NtkReassignIds( pNtk ); pNtk = pManMR->pNtk = Abc_FlowRetime_NtkSilentRestrash( pNtk, 1 ); } // print info about initial states if (pManMR->fComputeInitState && pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo( pNtk ); // (ii) backward retiming loop pManMR->fIsForward = 0; if (!pManMR->fForwardOnly) do { // initializability loop pManMR->iteration = 0; // copy/restore network if (pManMR->fGuaranteeInitState) { if ( pNtk != pNtkCopy ) Abc_NtkDelete( pNtk ); pNtk = pManMR->pNtk = Abc_FlowRetime_NtkDup( pNtkCopy ); vprintf("\trestoring network. regs = %d\n", Abc_NtkLatchNum( pNtk )); } if (pManMR->fComputeInitState) { Abc_FlowRetime_SetupBackwardInit( pNtk ); } do { if (pManMR->iteration == pManMR->nMaxIters) break; pManMR->subIteration = 0; vprintf("\tbackward iteration %d\n", pManMR->iteration); last = Abc_NtkLatchNum( pNtk ); Abc_FlowRetime_AddInitBias( ); Abc_FlowRetime_MarkBlocks( pNtk ); if (pManMR->maxDelay) { // timing-constrained loop Abc_FlowRetime_ConstrainConserv( pNtk ); while(Abc_FlowRetime_RefineConstraints( )) { pManMR->subIteration++; Abc_FlowRetime_ClearFlows( 0 ); } } else { flow = Abc_FlowRetime_PushFlows( pNtk, 1 ); } Abc_FlowRetime_RemoveInitBias( ); cut = Abc_FlowRetime_ImplementCut( pNtk ); #if defined(DEBUG_PRINT_LEVELS) vprintf("\t\tlevels = %d\n", Abc_NtkLevelReverse(pNtk)); #endif Abc_FlowRetime_ClearFlows( 1 ); pManMR->iteration++; } while( cut != last ); // compute initial states if (!pManMR->fComputeInitState) break; if (Abc_FlowRetime_SolveBackwardInit( pNtk )) { if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo( pNtk ); break; } else { if (!pManMR->fGuaranteeInitState) { printf("WARNING: no equivalent init state. setting all initial states to don't-cares\n"); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj ); break; } Abc_FlowRetime_ConstrainInit( ); } Abc_NtkDelete(pManMR->pInitNtk); pManMR->pInitNtk = NULL; } while(1); // assert(!pManMR->fComputeInitState || pManMR->pInitNtk); if (pManMR->fComputeInitState) Abc_NtkDelete(pManMR->pInitNtk); // if (pManMR->fGuaranteeInitState) ; /* Abc_NtkDelete(pNtkCopy); note: original ntk deleted later */ return pNtk; } /**Function************************************************************* Synopsis [Pushes latch bubbles outside of box.] Description [If network is an AIG, a fCompl0 is allowed to remain on the BI node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_RemoveLatchBubbles( Abc_Obj_t * pLatch ) { int bubble = 0; Abc_Ntk_t *pNtk = pManMR->pNtk; Abc_Obj_t *pBi, *pBo, *pInv; pBi = Abc_ObjFanin0(pLatch); pBo = Abc_ObjFanout0(pLatch); assert(!Abc_ObjIsComplement(pBi)); assert(!Abc_ObjIsComplement(pBo)); // push bubbles on BO into latch box if (Abc_ObjFaninC0(pBo) && Abc_ObjFanoutNum(pBo) > 0) { bubble = 1; if (Abc_LatchIsInit0(pLatch)) Abc_LatchSetInit1(pLatch); else if (Abc_LatchIsInit1(pLatch)) Abc_LatchSetInit0(pLatch); } // absorb bubbles on BI pBi->fCompl0 ^= bubble ^ Abc_ObjFaninC0(pLatch); // convert bubble to INV if not AIG if (!Abc_NtkIsStrash( pNtk ) && Abc_ObjFaninC0(pBi)) { pBi->fCompl0 = 0; pInv = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanin0(pBi) ); Abc_ObjPatchFanin( pBi, Abc_ObjFanin0(pBi), pInv ); } pBo->fCompl0 = 0; pLatch->fCompl0 = 0; } /**Function************************************************************* Synopsis [Marks nodes in TFO/TFI of PI/PO.] Description [Sets flow data flag BLOCK appropriately.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_MarkBlocks( Abc_Ntk_t * pNtk ) { int i; Abc_Obj_t *pObj; if (pManMR->fIsForward){ // --- forward retiming : block TFO of inputs // mark the frontier Abc_NtkForEachPo( pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachLatch( pNtk, pObj, i ) { pObj->fMarkA = 1; } // mark the nodes reachable from the PIs Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward ); } else { // --- backward retiming : block TFI of outputs // mark the frontier Abc_NtkForEachPi( pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachLatch( pNtk, pObj, i ) { pObj->fMarkA = 1; } // mark the nodes reachable from the POs Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkMarkCone_rec( pObj, pManMR->fIsForward ); // block constant nodes (if enabled) if (pManMR->fBlockConst) { Abc_NtkForEachObj( pNtk, pObj, i ) if ((Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(pObj)) || (!Abc_NtkIsStrash(pNtk) && Abc_NodeIsConst(pObj))) { FSET(pObj, BLOCK); } } } // copy marks Abc_NtkForEachObj( pNtk, pObj, i ) { if (pObj->fMarkA) { pObj->fMarkA = 0; if (!Abc_ObjIsLatch(pObj) /* && !Abc_ObjIsPi(pObj) */ ) FSET(pObj, BLOCK); } } } /**Function************************************************************* Synopsis [Computes maximum flow.] Description [] SideEffects [Leaves VISITED flags on source-reachable nodes.] SeeAlso [] ***********************************************************************/ int Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, int fVerbose ) { int i, j, flow = 0, last, srcDist = 0; Abc_Obj_t *pObj, *pObj2; // int clk = clock(); pManMR->constraintMask |= BLOCK; pManMR->fSinkDistTerminate = 0; dfsfast_preorder( pNtk ); // (i) fast max-flow computation while(!pManMR->fSinkDistTerminate && srcDist < MAX_DIST) { srcDist = MAX_DIST; Abc_NtkForEachLatch( pNtk, pObj, i ) if (FDATA(pObj)->e_dist) srcDist = MIN(srcDist, (int)FDATA(pObj)->e_dist); Abc_NtkForEachLatch( pNtk, pObj, i ) { if (srcDist == (int)FDATA(pObj)->e_dist && dfsfast_e( pObj, NULL )) { #ifdef DEBUG_PRINT_FLOWS printf("\n\n"); #endif flow++; } } } if (fVerbose) vprintf("\t\tmax-flow1 = %d \t", flow); // (ii) complete max-flow computation // also, marks source-reachable nodes do { last = flow; Abc_NtkForEachLatch( pNtk, pObj, i ) { if (dfsplain_e( pObj, NULL )) { #ifdef DEBUG_PRINT_FLOWS printf("\n\n"); #endif flow++; Abc_NtkForEachObj( pNtk, pObj2, j ) FUNSET( pObj2, VISITED ); } } } while (flow > last); if (fVerbose) vprintf("max-flow2 = %d\n", flow); // PRT( "time", clock() - clk ); return flow; } /**Function************************************************************* Synopsis [Restores latch boxes.] Description [Latchless BI/BO nodes are removed. Latch boxes are restored around remaining latches.] SideEffects [Deletes nodes as appropriate.] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_FixLatchBoxes( Abc_Ntk_t *pNtk, Vec_Ptr_t *vBoxIns ) { int i; Abc_Obj_t *pObj, *pBo = NULL, *pBi = NULL; Vec_Ptr_t *vFreeBi = Vec_PtrAlloc( 100 ); Vec_Ptr_t *vFreeBo = Vec_PtrAlloc( 100 ); // 1. remove empty bi/bo pairs while(Vec_PtrSize( vBoxIns )) { pBi = (Abc_Obj_t *)Vec_PtrPop( vBoxIns ); assert(Abc_ObjIsBi(pBi)); assert(Abc_ObjFanoutNum(pBi) == 1); // APH: broken by bias nodes assert(Abc_ObjFaninNum(pBi) == 1); pBo = Abc_ObjFanout0(pBi); assert(!Abc_ObjFaninC0(pBo)); if (Abc_ObjIsBo(pBo)) { // an empty bi/bo pair Abc_ObjRemoveFanins( pBo ); // transfer complement from BI, if present assert(!Abc_ObjIsComplement(Abc_ObjFanin0(pBi))); Abc_ObjBetterTransferFanout( pBo, Abc_ObjFanin0(pBi), Abc_ObjFaninC0(pBi) ); Abc_ObjRemoveFanins( pBi ); pBi->fCompl0 = 0; Vec_PtrPush( vFreeBi, pBi ); Vec_PtrPush( vFreeBo, pBo ); // free names if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pBi))) Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pBi)); if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pBo))) Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pBo)); // check for complete detachment assert(Abc_ObjFaninNum(pBi) == 0); assert(Abc_ObjFanoutNum(pBi) == 0); assert(Abc_ObjFaninNum(pBo) == 0); assert(Abc_ObjFanoutNum(pBo) == 0); } else if (Abc_ObjIsLatch(pBo)) { } else { Abc_ObjPrint(stdout, pBi); Abc_ObjPrint(stdout, pBo); assert(0); } } // 2. add bi/bos as necessary for latches Abc_NtkForEachLatch( pNtk, pObj, i ) { assert(Abc_ObjFaninNum(pObj) == 1); if (Abc_ObjFanoutNum(pObj)) pBo = Abc_ObjFanout0(pObj); else pBo = NULL; pBi = Abc_ObjFanin0(pObj); // add BO if (!pBo || !Abc_ObjIsBo(pBo)) { pBo = (Abc_Obj_t *)Vec_PtrPop( vFreeBo ); if (Abc_ObjFanoutNum(pObj)) Abc_ObjTransferFanout( pObj, pBo ); Abc_ObjAddFanin( pBo, pObj ); } // add BI if (!Abc_ObjIsBi(pBi)) { pBi = (Abc_Obj_t *)Vec_PtrPop( vFreeBi ); assert(Abc_ObjFaninNum(pBi) == 0); Abc_ObjAddFanin( pBi, Abc_ObjFanin0(pObj) ); pBi->fCompl0 = pObj->fCompl0; Abc_ObjRemoveFanins( pObj ); Abc_ObjAddFanin( pObj, pBi ); } } // delete remaining BIs and BOs while(Vec_PtrSize( vFreeBi )) { pObj = (Abc_Obj_t *)Vec_PtrPop( vFreeBi ); Abc_NtkDeleteObj( pObj ); } while(Vec_PtrSize( vFreeBo )) { pObj = (Abc_Obj_t *)Vec_PtrPop( vFreeBo ); Abc_NtkDeleteObj( pObj ); } #if defined(DEBUG_CHECK) Abc_NtkForEachObj( pNtk, pObj, i ) { if (Abc_ObjIsBo(pObj)) { assert(Abc_ObjFaninNum(pObj) == 1); assert(Abc_ObjIsLatch(Abc_ObjFanin0(pObj))); } if (Abc_ObjIsBi(pObj)) { assert(Abc_ObjFaninNum(pObj) == 1); assert(Abc_ObjFanoutNum(pObj) == 1); assert(Abc_ObjIsLatch(Abc_ObjFanout0(pObj))); } if (Abc_ObjIsLatch(pObj)) { assert(Abc_ObjFanoutNum(pObj) == 1); assert(Abc_ObjFaninNum(pObj) == 1); } } #endif Vec_PtrFree( vFreeBi ); Vec_PtrFree( vFreeBo ); } /**Function************************************************************* Synopsis [Checks register count along all combinational paths.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_VerifyPathLatencies( Abc_Ntk_t * pNtk ) { int i; Abc_Obj_t *pObj; fPathError = 0; vprintf("\t\tVerifying latency along all paths..."); Abc_NtkForEachObj( pNtk, pObj, i ) { if (Abc_ObjIsBo(pObj)) { Abc_FlowRetime_VerifyPathLatencies_rec( pObj, 0 ); } else if (!pManMR->fIsForward && Abc_ObjIsPi(pObj)) { Abc_FlowRetime_VerifyPathLatencies_rec( pObj, 0 ); } if (fPathError) { if (Abc_ObjFaninNum(pObj) > 0) { printf("fanin "); print_node(Abc_ObjFanin0(pObj)); } printf("\n"); exit(0); } } vprintf(" ok\n"); Abc_NtkForEachObj( pNtk, pObj, i ) { pObj->fMarkA = 0; pObj->fMarkB = 0; pObj->fMarkC = 0; } } int Abc_FlowRetime_VerifyPathLatencies_rec( Abc_Obj_t * pObj, int markD ) { int i, j; Abc_Obj_t *pNext; int fCare = 0; int markC = pObj->fMarkC; if (!pObj->fMarkB) { pObj->fMarkB = 1; // visited if (Abc_ObjIsLatch(pObj)) markC = 1; // latch in output if (!pManMR->fIsForward && !Abc_ObjIsPo(pObj) && !Abc_ObjFanoutNum(pObj)) return -1; // dangling non-PO outputs : don't care what happens Abc_ObjForEachFanout( pObj, pNext, i ) { // reached end of cycle? if ( Abc_ObjIsBo(pNext) || (pManMR->fIsForward && Abc_ObjIsPo(pNext)) ) { if (!markD && !Abc_ObjIsLatch(pObj)) { printf("\nERROR: no-latch path (end)\n"); print_node(pNext); printf("\n"); fPathError = 1; } } else if (!pManMR->fIsForward && Abc_ObjIsPo(pNext)) { if (markD || Abc_ObjIsLatch(pObj)) { printf("\nERROR: extra-latch path to outputs\n"); print_node(pNext); printf("\n"); fPathError = 1; } } else { j = Abc_FlowRetime_VerifyPathLatencies_rec( pNext, markD || Abc_ObjIsLatch(pObj) ); if (j >= 0) { markC |= j; fCare = 1; } } if (fPathError) { print_node(pObj); printf("\n"); return 0; } } } if (!fCare) return -1; if (markC && markD) { printf("\nERROR: mult-latch path\n"); print_node(pObj); printf("\n"); fPathError = 1; } if (!markC && !markD) { printf("\nERROR: no-latch path (inter)\n"); print_node(pObj); printf("\n"); fPathError = 1; } return (pObj->fMarkC = markC); } /**Function************************************************************* Synopsis [Copies initial state from latches to BO nodes.] Description [Initial states are marked on BO nodes with INIT_0 and INIT_1 flags in their Flow_Data structures.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_CopyInitState( Abc_Obj_t * pSrc, Abc_Obj_t * pDest ) { Abc_Obj_t *pObj; if (!pManMR->fComputeInitState) return; assert(Abc_ObjIsLatch(pSrc)); assert(Abc_ObjFanin0(pDest) == pSrc); assert(!Abc_ObjFaninC0(pDest)); FUNSET(pDest, INIT_CARE); if (Abc_LatchIsInit0(pSrc)) { FSET(pDest, INIT_0); } else if (Abc_LatchIsInit1(pSrc)) { FSET(pDest, INIT_1); } if (!pManMR->fIsForward) { pObj = (Abc_Obj_t*)Abc_ObjData(pSrc); assert(Abc_ObjIsPi(pObj)); FDATA(pDest)->pInitObj = pObj; } } /**Function************************************************************* Synopsis [Implements min-cut.] Description [Requires source-reachable nodes to be marked VISITED.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FlowRetime_ImplementCut( Abc_Ntk_t * pNtk ) { int i, j, cut = 0, unmoved = 0; Abc_Obj_t *pObj, *pReg, *pNext, *pBo = NULL, *pBi = NULL; Vec_Ptr_t *vFreeRegs = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); Vec_Ptr_t *vBoxIns = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); Vec_Ptr_t *vMove = Vec_PtrAlloc( 100 ); // remove latches from netlist Abc_NtkForEachLatch( pNtk, pObj, i ) { pBo = Abc_ObjFanout0(pObj); pBi = Abc_ObjFanin0(pObj); assert(Abc_ObjIsBo(pBo) && Abc_ObjIsBi(pBi)); Vec_PtrPush( vBoxIns, pBi ); // copy initial state values to BO Abc_FlowRetime_CopyInitState( pObj, pBo ); // re-use latch elsewhere Vec_PtrPush( vFreeRegs, pObj ); FSET(pBo, CROSS_BOUNDARY); // cut out of netlist Abc_ObjPatchFanin( pBo, pObj, pBi ); Abc_ObjRemoveFanins( pObj ); // free name if (Nm_ManFindNameById(pNtk->pManName, Abc_ObjId(pObj))) Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pObj)); } // insert latches into netlist Abc_NtkForEachObj( pNtk, pObj, i ) { if (Abc_ObjIsLatch( pObj )) continue; if (FTEST(pObj, BIAS_NODE)) continue; // a latch is required on every node that lies across the min-cit assert(!pManMR->fIsForward || !FTEST(pObj, VISITED_E) || FTEST(pObj, VISITED_R)); if (FTEST(pObj, VISITED_R) && !FTEST(pObj, VISITED_E)) { assert(FTEST(pObj, FLOW)); // count size of cut cut++; if ((pManMR->fIsForward && Abc_ObjIsBo(pObj)) || (!pManMR->fIsForward && Abc_ObjIsBi(pObj))) unmoved++; // only insert latch between fanouts that lie across min-cut // some fanout paths may be cut at deeper points Abc_ObjForEachFanout( pObj, pNext, j ) if (Abc_FlowRetime_IsAcrossCut( pObj, pNext )) Vec_PtrPush(vMove, pNext); // check that move-set is non-zero if (Vec_PtrSize(vMove) == 0) print_node(pObj); assert(Vec_PtrSize(vMove) > 0); // insert one of re-useable registers assert(Vec_PtrSize( vFreeRegs )); pReg = (Abc_Obj_t *)Vec_PtrPop( vFreeRegs ); Abc_ObjAddFanin(pReg, pObj); while(Vec_PtrSize( vMove )) { pNext = (Abc_Obj_t *)Vec_PtrPop( vMove ); Abc_ObjPatchFanin( pNext, pObj, pReg ); if (Abc_ObjIsBi(pNext)) assert(Abc_ObjFaninNum(pNext) == 1); } // APH: broken by bias nodes if (Abc_ObjIsBi(pObj)) assert(Abc_ObjFaninNum(pObj) == 1); } } #if defined(DEBUG_CHECK) Abc_FlowRetime_VerifyPathLatencies( pNtk ); #endif // delete remaining latches while(Vec_PtrSize( vFreeRegs )) { pReg = (Abc_Obj_t *)Vec_PtrPop( vFreeRegs ); Abc_NtkDeleteObj( pReg ); } // update initial states Abc_FlowRetime_UpdateLags( ); Abc_FlowRetime_InitState( pNtk ); // restore latch boxes Abc_FlowRetime_FixLatchBoxes( pNtk, vBoxIns ); Vec_PtrFree( vFreeRegs ); Vec_PtrFree( vMove ); Vec_PtrFree( vBoxIns ); vprintf("\t\tmin-cut = %d (unmoved = %d)\n", cut, unmoved); return cut; } /**Function************************************************************* Synopsis [Adds dummy fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_AddDummyFanin( Abc_Obj_t * pObj ) { Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj ); if (Abc_NtkIsStrash(pNtk)) Abc_ObjAddFanin(pObj, Abc_AigConst1( pNtk )); else Abc_ObjAddFanin(pObj, Abc_NtkCreateNodeConst0( pNtk )); } /**Function************************************************************* Synopsis [Prints information about a node.] Description [Debuging.] SideEffects [] SeeAlso [] ***********************************************************************/ void print_node(Abc_Obj_t *pObj) { int i; Abc_Obj_t * pNext; char m[6]; m[0] = 0; if (pObj->fMarkA) strcat(m, "A"); if (pObj->fMarkB) strcat(m, "B"); if (pObj->fMarkC) strcat(m, "C"); printf("node %d type=%d lev=%d tedge=%d (%x%s) fanouts {", Abc_ObjId(pObj), Abc_ObjType(pObj), pObj->Level, Vec_PtrSize(FTIMEEDGES(pObj)), FDATA(pObj)->mark, m); Abc_ObjForEachFanout( pObj, pNext, i ) printf("%d[%d](%d),", Abc_ObjId(pNext), Abc_ObjType(pNext), FDATA(pNext)->mark); printf("} fanins {"); Abc_ObjForEachFanin( pObj, pNext, i ) printf("%d[%d](%d),", Abc_ObjId(pNext), Abc_ObjType(pNext), FDATA(pNext)->mark); printf("}\n"); } void print_node2(Abc_Obj_t *pObj) { int i; Abc_Obj_t * pNext; char m[6]; m[0] = 0; if (pObj->fMarkA) strcat(m, "A"); if (pObj->fMarkB) strcat(m, "B"); if (pObj->fMarkC) strcat(m, "C"); printf("node %d type=%d %s fanouts {", Abc_ObjId(pObj), Abc_ObjType(pObj), m); Abc_ObjForEachFanout( pObj, pNext, i ) printf("%d ,", Abc_ObjId(pNext)); printf("} fanins {"); Abc_ObjForEachFanin( pObj, pNext, i ) printf("%d ,", Abc_ObjId(pNext)); printf("} "); } void print_node3(Abc_Obj_t *pObj) { int i; Abc_Obj_t * pNext; char m[6]; m[0] = 0; if (pObj->fMarkA) strcat(m, "A"); if (pObj->fMarkB) strcat(m, "B"); if (pObj->fMarkC) strcat(m, "C"); printf("\nnode %d type=%d mark=%d %s\n", Abc_ObjId(pObj), Abc_ObjType(pObj), FDATA(pObj)->mark, m); printf("fanouts\n"); Abc_ObjForEachFanout( pObj, pNext, i ) { print_node(pNext); printf("\n"); } printf("fanins\n"); Abc_ObjForEachFanin( pObj, pNext, i ) { print_node(pNext); printf("\n"); } } /**Function************************************************************* Synopsis [Transfers fanout.] Description [Does not produce an error if there is no fanout. Complements as necessary.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjBetterTransferFanout( Abc_Obj_t * pFrom, Abc_Obj_t * pTo, int complement ) { Abc_Obj_t *pNext; while(Abc_ObjFanoutNum(pFrom) > 0) { pNext = Abc_ObjFanout0(pFrom); Abc_ObjPatchFanin( pNext, pFrom, Abc_ObjNotCond(pTo, complement) ); } } /**Function************************************************************* Synopsis [Returns true is a connection spans the min-cut.] Description [pNext is a direct fanout of pObj.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pObj, Abc_Obj_t *pNext ) { if (FTEST(pObj, VISITED_R) && !FTEST(pObj, VISITED_E)) { if (pManMR->fIsForward) { if (!FTEST(pNext, VISITED_R) || (FTEST(pNext, BLOCK_OR_CONS) & pManMR->constraintMask)|| FTEST(pNext, CROSS_BOUNDARY) || Abc_ObjIsLatch(pNext)) return 1; } else { if (FTEST(pNext, VISITED_E) || FTEST(pNext, CROSS_BOUNDARY)) return 1; } } return 0; } /**Function************************************************************* Synopsis [Resets flow problem] Description [If fClearAll is true, all marks will be cleared; this is typically appropriate after the circuit structure has been modified.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_ClearFlows( int fClearAll ) { int i; if (fClearAll) memset(pManMR->pDataArray, 0, sizeof(Flow_Data_t)*pManMR->nNodes); else { // clear only data related to flow problem for(i=0; inNodes; i++) { pManMR->pDataArray[i].mark &= ~(VISITED | FLOW ); pManMR->pDataArray[i].e_dist = 0; pManMR->pDataArray[i].r_dist = 0; pManMR->pDataArray[i].pred = NULL; } } } /**Function************************************************************* Synopsis [Duplicates network.] Description [Duplicates any type of network. Preserves copy data.] SideEffects [] SeeAlso [] ***********************************************************************/ static Abc_Ntk_t* Abc_FlowRetime_NtkDup( Abc_Ntk_t * pNtk ) { Abc_Ntk_t *pNtkCopy; Abc_Obj_t *pObj, *pObjCopy, *pNext, *pNextCopy; int i, j; pNtkCopy = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); pNtkCopy->pName = Extra_UtilStrsav(pNtk->pName); pNtkCopy->pSpec = Extra_UtilStrsav(pNtk->pSpec); // copy each object Abc_NtkForEachObj( pNtk, pObj, i) { if (Abc_NtkIsStrash( pNtk ) && Abc_AigNodeIsConst( pObj )) pObjCopy = Abc_AigConst1( pNtkCopy ); else pObjCopy = Abc_NtkDupObj( pNtkCopy, pObj, 0 ); FDATA( pObj )->pCopy = pObjCopy; FDATA( pObj )->mark = 0; // assert( pManMR->fIsForward || pObj->Id == pObjCopy->Id ); // copy complementation pObjCopy->fCompl0 = pObj->fCompl0; pObjCopy->fCompl1 = pObj->fCompl1; pObjCopy->fPhase = pObj->fPhase; } // connect fanin Abc_NtkForEachObj( pNtk, pObj, i) { pObjCopy = FDATA(pObj)->pCopy; assert(pObjCopy); Abc_ObjForEachFanin( pObj, pNext, j ) { pNextCopy = FDATA(pNext)->pCopy; assert(pNextCopy); assert(pNext->Type == pNextCopy->Type); Abc_ObjAddFanin(pObjCopy, pNextCopy); } } #if defined(DEBUG_CHECK) || 1 Abc_NtkForEachObj( pNtk, pObj, i) { pObjCopy = FDATA(pObj)->pCopy; assert( Abc_ObjFanoutNum( pObj ) == Abc_ObjFanoutNum( pObjCopy ) ); assert( Abc_ObjFaninNum( pObj ) == Abc_ObjFaninNum( pObjCopy ) ); } #endif assert(Abc_NtkObjNum( pNtk ) == Abc_NtkObjNum( pNtkCopy ) ); assert(Abc_NtkLatchNum( pNtk ) == Abc_NtkLatchNum( pNtkCopy ) ); assert(Abc_NtkPoNum( pNtk ) == Abc_NtkPoNum( pNtkCopy ) ); assert(Abc_NtkPiNum( pNtk ) == Abc_NtkPiNum( pNtkCopy ) ); return pNtkCopy; } /**Function************************************************************* Synopsis [Silent restrash.] Description [Same functionality as Abc_NtkRestrash but w/o warnings.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_FlowRetime_NtkSilentRestrash( Abc_Ntk_t * pNtk, int fCleanup ) { Abc_Ntk_t * pNtkAig; Abc_Obj_t * pObj; int i, nNodes;//, RetValue; 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_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // 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 ); // perform cleanup if requested if ( fCleanup ) nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc); // duplicate EXDC if ( pNtk->pExdc ) pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); // 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 [Updates lag values.] Description [Recursive. Forward retiming.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_UpdateLags_forw_rec( Abc_Obj_t *pObj ) { Abc_Obj_t *pNext; int i; assert(!Abc_ObjIsPi(pObj)); assert(!Abc_ObjIsLatch(pObj)); if (Abc_ObjIsBo(pObj)) return; if (Abc_NodeIsTravIdCurrent(pObj)) return; Abc_NodeSetTravIdCurrent(pObj); if (Abc_ObjIsNode(pObj)) { Abc_FlowRetime_SetLag( pObj, -1+Abc_FlowRetime_GetLag(pObj) ); } Abc_ObjForEachFanin( pObj, pNext, i ) { Abc_FlowRetime_UpdateLags_forw_rec( pNext ); } } /**Function************************************************************* Synopsis [Updates lag values.] Description [Recursive. Backward retiming.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_UpdateLags_back_rec( Abc_Obj_t *pObj ) { Abc_Obj_t *pNext; int i; assert(!Abc_ObjIsPo(pObj)); assert(!Abc_ObjIsLatch(pObj)); if (Abc_ObjIsBo(pObj)) return; if (Abc_NodeIsTravIdCurrent(pObj)) return; Abc_NodeSetTravIdCurrent(pObj); if (Abc_ObjIsNode(pObj)) { Abc_FlowRetime_SetLag( pObj, 1+Abc_FlowRetime_GetLag(pObj) ); } Abc_ObjForEachFanout( pObj, pNext, i ) { Abc_FlowRetime_UpdateLags_back_rec( pNext ); } } /**Function************************************************************* Synopsis [Updates lag values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_UpdateLags( ) { Abc_Obj_t *pObj, *pNext; int i, j; Abc_NtkIncrementTravId( pManMR->pNtk ); Abc_NtkForEachLatch( pManMR->pNtk, pObj, i ) if (pManMR->fIsForward) { Abc_ObjForEachFanin( pObj, pNext, j ) Abc_FlowRetime_UpdateLags_forw_rec( pNext ); } else { Abc_ObjForEachFanout( pObj, pNext, j ) Abc_FlowRetime_UpdateLags_back_rec( pNext ); } } /**Function************************************************************* Synopsis [Gets lag value of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FlowRetime_GetLag( Abc_Obj_t *pObj ) { assert( !Abc_ObjIsLatch(pObj) ); assert( (int)Abc_ObjId(pObj) < Vec_IntSize(pManMR->vLags) ); return Vec_IntEntry(pManMR->vLags, Abc_ObjId(pObj)); } /**Function************************************************************* Synopsis [Sets lag value of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_SetLag( Abc_Obj_t *pObj, int lag ) { assert( Abc_ObjIsNode(pObj) ); assert( (int)Abc_ObjId(pObj) < Vec_IntSize(pManMR->vLags) ); Vec_IntWriteEntry(pManMR->vLags, Abc_ObjId(pObj), lag); } static void Abc_ObjPrintNeighborhood_rec( Abc_Obj_t *pObj, Vec_Ptr_t *vNodes, int depth ) { Abc_Obj_t *pObj2; int i; if (pObj->fMarkC || depth < 0) return; pObj->fMarkC = 1; Vec_PtrPush( vNodes, pObj ); Abc_ObjPrint( stdout, pObj ); Abc_ObjForEachFanout(pObj, pObj2, i) { Abc_ObjPrintNeighborhood_rec( pObj2, vNodes, depth-1 ); } Abc_ObjForEachFanin(pObj, pObj2, i) { Abc_ObjPrintNeighborhood_rec( pObj2, vNodes, depth-1 ); } } void Abc_ObjPrintNeighborhood( Abc_Obj_t *pObj, int depth ) { Vec_Ptr_t *vNodes = Vec_PtrAlloc(100); Abc_Obj_t *pObj2; Abc_ObjPrintNeighborhood_rec( pObj, vNodes, depth ); while(Vec_PtrSize(vNodes)) { pObj2 = (Abc_Obj_t*)Vec_PtrPop(vNodes); pObj2->fMarkC = 0; } Vec_PtrFree(vNodes); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fret/fretTime.c000066400000000000000000000462341300674244400235320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fretTime.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Flow-based retiming package.] Synopsis [Delay-constrained retiming code.] Author [Aaron Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2008.] Revision [$Id: fretTime.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] ***********************************************************************/ #include "fretime.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ); static void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ); static void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj ); static void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj ); static void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk ); static void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk ); void trace2(Abc_Obj_t *pObj) { Abc_Obj_t *pNext; int i; print_node(pObj); Abc_ObjForEachFanin(pObj, pNext, i) if (pNext->Level >= pObj->Level - 1) { trace2(pNext); break; } } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Initializes timing] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk ) { pManMR->nConservConstraints = pManMR->nExactConstraints = 0; pManMR->vExactNodes = Vec_PtrAlloc(1000); pManMR->vTimeEdges = ABC_ALLOC( Vec_Ptr_t, Abc_NtkObjNumMax(pNtk)+1 ); assert(pManMR->vTimeEdges); memset(pManMR->vTimeEdges, 0, (Abc_NtkObjNumMax(pNtk)+1) * sizeof(Vec_Ptr_t) ); } /**Function************************************************************* Synopsis [Marks nodes with conservative constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk ) { Abc_Obj_t *pObj; int i; void *pArray; // clear all exact constraints pManMR->nExactConstraints = 0; while( Vec_PtrSize( pManMR->vExactNodes )) { pObj = (Abc_Obj_t*)Vec_PtrPop( pManMR->vExactNodes ); if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); ABC_FREE( pArray ); } } #if !defined(IGNORE_TIMING) if (pManMR->fIsForward) { Abc_FlowRetime_ConstrainConserv_forw(pNtk); } else { Abc_FlowRetime_ConstrainConserv_back(pNtk); } #endif Abc_NtkForEachObj( pNtk, pObj, i) assert( !Vec_PtrSize(FTIMEEDGES(pObj)) ); } void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk ) { Vec_Ptr_t *vNodes = pManMR->vNodes; Abc_Obj_t *pObj, *pNext, *pBi, *pBo; int i, j; assert(!Vec_PtrSize( vNodes )); pManMR->nConservConstraints = 0; // 1. hard constraints // (i) collect TFO of PIs Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachPi(pNtk, pObj, i) Abc_FlowRetime_Dfs_forw( pObj, vNodes ); // ... propagate values Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->Level = 0; Abc_ObjForEachFanin( pObj, pNext, j ) { if ( Abc_NodeIsTravIdCurrent(pNext) && pObj->Level < pNext->Level ) pObj->Level = pNext->Level; } pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; if ( Abc_ObjIsBi(pObj) ) pObj->fMarkA = 1; assert((int)pObj->Level <= pManMR->maxDelay); } // collect TFO of latches // seed arrival times from BIs Vec_PtrClear(vNodes); Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch(pNtk, pObj, i) { pBo = Abc_ObjFanout0( pObj ); pBi = Abc_ObjFanin0( pObj ); Abc_NodeSetTravIdCurrent( pObj ); Abc_FlowRetime_Dfs_forw( pBo, vNodes ); if (pBi->fMarkA) { pBi->fMarkA = 0; pObj->Level = pBi->Level; assert((int)pObj->Level <= pManMR->maxDelay); } else pObj->Level = 0; } #if defined(DEBUG_CHECK) // DEBUG: check DFS ordering Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->fMarkB = 1; Abc_ObjForEachFanin( pObj, pNext, j ) if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext)) assert(pNext->fMarkB); } Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) pObj->fMarkB = 0; #endif // ... propagate values Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->Level = 0; Abc_ObjForEachFanin( pObj, pNext, j ) { if ( Abc_NodeIsTravIdCurrent(pNext) && pObj->Level < pNext->Level ) pObj->Level = pNext->Level; } pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; if ((int)pObj->Level > pManMR->maxDelay) { FSET(pObj, BLOCK); } } // 2. conservative constraints // first pass: seed latches with T=0 Abc_NtkForEachLatch(pNtk, pObj, i) { pObj->Level = 0; } // ... propagate values Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->Level = 0; Abc_ObjForEachFanin( pObj, pNext, j ) { if ( Abc_NodeIsTravIdCurrent(pNext) && pObj->Level < pNext->Level ) pObj->Level = pNext->Level; } pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; if ( Abc_ObjIsBi(pObj) ) pObj->fMarkA = 1; assert((int)pObj->Level <= pManMR->maxDelay); } Abc_NtkForEachLatch(pNtk, pObj, i) { pBo = Abc_ObjFanout0( pObj ); pBi = Abc_ObjFanin0( pObj ); if (pBi->fMarkA) { pBi->fMarkA = 0; pObj->Level = pBi->Level; assert((int)pObj->Level <= pManMR->maxDelay); } else pObj->Level = 0; } // ... propagate values Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->Level = 0; Abc_ObjForEachFanin( pObj, pNext, j ) { if ( Abc_NodeIsTravIdCurrent(pNext) && pObj->Level < pNext->Level ) pObj->Level = pNext->Level; } pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; // constrained? if ((int)pObj->Level > pManMR->maxDelay) { FSET( pObj, CONSERVATIVE ); pManMR->nConservConstraints++; } else FUNSET( pObj, CONSERVATIVE ); } Vec_PtrClear( vNodes ); } void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk ) { Vec_Ptr_t *vNodes = pManMR->vNodes; Abc_Obj_t *pObj, *pNext, *pBi, *pBo; int i, j, l; assert(!Vec_PtrSize(vNodes)); pManMR->nConservConstraints = 0; // 1. hard constraints // (i) collect TFO of POs Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachPo(pNtk, pObj, i) Abc_FlowRetime_Dfs_back( pObj, vNodes ); // ... propagate values Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->Level = 0; Abc_ObjForEachFanout( pObj, pNext, j ) { l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); if ( Abc_NodeIsTravIdCurrent(pNext) && (int)pObj->Level < l ) pObj->Level = l; } if ( Abc_ObjIsBo(pObj) ) pObj->fMarkA = 1; assert((int)pObj->Level <= pManMR->maxDelay); } // collect TFO of latches // seed arrival times from BIs Vec_PtrClear(vNodes); Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch(pNtk, pObj, i) { pBo = Abc_ObjFanout0( pObj ); pBi = Abc_ObjFanin0( pObj ); Abc_NodeSetTravIdCurrent( pObj ); Abc_FlowRetime_Dfs_back( pBi, vNodes ); if (pBo->fMarkA) { pBo->fMarkA = 0; pObj->Level = pBo->Level; assert((int)pObj->Level <= pManMR->maxDelay); } else pObj->Level = 0; } #if defined(DEBUG_CHECK) // DEBUG: check DFS ordering Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->fMarkB = 1; Abc_ObjForEachFanout( pObj, pNext, j ) if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext)) assert(pNext->fMarkB); } Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) pObj->fMarkB = 0; #endif // ... propagate values Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->Level = 0; Abc_ObjForEachFanout( pObj, pNext, j ) { l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); if ( Abc_NodeIsTravIdCurrent(pNext) && (int)pObj->Level < l ) pObj->Level = l; } if ((int)pObj->Level + (Abc_ObjIsNode(pObj)?1:0) > pManMR->maxDelay) { FSET(pObj, BLOCK); } } // 2. conservative constraints // first pass: seed latches with T=0 Abc_NtkForEachLatch(pNtk, pObj, i) { pObj->Level = 0; } // ... propagate values Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->Level = 0; Abc_ObjForEachFanout( pObj, pNext, j ) { l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); if ( Abc_NodeIsTravIdCurrent(pNext) && (int)pObj->Level < l ) pObj->Level = l; } if ( Abc_ObjIsBo(pObj) ) { pObj->fMarkA = 1; } assert((int)pObj->Level <= pManMR->maxDelay); } Abc_NtkForEachLatch(pNtk, pObj, i) { pBo = Abc_ObjFanout0( pObj ); assert(Abc_ObjIsBo(pBo)); pBi = Abc_ObjFanin0( pObj ); assert(Abc_ObjIsBi(pBi)); if (pBo->fMarkA) { pBo->fMarkA = 0; pObj->Level = pBo->Level; } else pObj->Level = 0; } // ... propagate values Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { pObj->Level = 0; Abc_ObjForEachFanout( pObj, pNext, j ) { l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); if ( Abc_NodeIsTravIdCurrent(pNext) && (int)pObj->Level < l ) pObj->Level = l; } // constrained? if ((int)pObj->Level > pManMR->maxDelay) { FSET( pObj, CONSERVATIVE ); pManMR->nConservConstraints++; } else FUNSET( pObj, CONSERVATIVE ); } Vec_PtrClear( vNodes ); } /**Function************************************************************* Synopsis [Introduces exact timing constraints for a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj ) { if (FTEST( pObj, CONSERVATIVE )) { pManMR->nConservConstraints--; FUNSET( pObj, CONSERVATIVE ); } #if !defined(IGNORE_TIMING) if (pManMR->fIsForward) { Abc_FlowRetime_ConstrainExact_forw(pObj); } else { Abc_FlowRetime_ConstrainExact_back(pObj); } #endif } void Abc_FlowRetime_ConstrainExact_forw_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) { Abc_Obj_t *pNext; int i; // terminate? if (Abc_ObjIsLatch(pObj)) { if (latch) return; latch = 1; } // already visited? if (!latch) { if (pObj->fMarkA) return; pObj->fMarkA = 1; } else { if (pObj->fMarkB) return; pObj->fMarkB = 1; } // recurse Abc_ObjForEachFanin(pObj, pNext, i) { Abc_FlowRetime_ConstrainExact_forw_rec( pNext, vNodes, latch ); } // add pObj->Level = 0; Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch)); } void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj ) { Vec_Ptr_t *vNodes = pManMR->vNodes; Abc_Obj_t *pNext, *pCur, *pReg; // Abc_Ntk_t *pNtk = pManMR->pNtk; int i, j; assert( !Vec_PtrSize(vNodes) ); assert( !Abc_ObjIsLatch(pObj) ); assert( !Vec_PtrSize( FTIMEEDGES(pObj) )); Vec_PtrPush( pManMR->vExactNodes, pObj ); // rev topo order Abc_FlowRetime_ConstrainExact_forw_rec( pObj, vNodes, 0 ); Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pCur, i) { pReg = Abc_ObjRegular( pCur ); if (pReg == pCur) { assert(!Abc_ObjIsLatch(pReg)); Abc_ObjForEachFanin(pReg, pNext, j) pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); assert((int)pReg->Level <= pManMR->maxDelay); pReg->Level = 0; pReg->fMarkA = pReg->fMarkB = 0; } } Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pCur, i) { pReg = Abc_ObjRegular( pCur ); if (pReg != pCur) { Abc_ObjForEachFanin(pReg, pNext, j) if (!Abc_ObjIsLatch(pNext)) pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); if ((int)pReg->Level == pManMR->maxDelay) { Vec_PtrPush( FTIMEEDGES(pObj), pReg); pManMR->nExactConstraints++; } pReg->Level = 0; pReg->fMarkA = pReg->fMarkB = 0; } } Vec_PtrClear( vNodes ); } void Abc_FlowRetime_ConstrainExact_back_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) { Abc_Obj_t *pNext; int i; // terminate? if (Abc_ObjIsLatch(pObj)) { if (latch) return; latch = 1; } // already visited? if (!latch) { if (pObj->fMarkA) return; pObj->fMarkA = 1; } else { if (pObj->fMarkB) return; pObj->fMarkB = 1; } // recurse Abc_ObjForEachFanout(pObj, pNext, i) { Abc_FlowRetime_ConstrainExact_back_rec( pNext, vNodes, latch ); } // add pObj->Level = 0; Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch)); } void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj ) { Vec_Ptr_t *vNodes = pManMR->vNodes; Abc_Obj_t *pNext, *pCur, *pReg; // Abc_Ntk_t *pNtk = pManMR->pNtk; int i, j; assert( !Vec_PtrSize( vNodes )); assert( !Abc_ObjIsLatch(pObj) ); assert( !Vec_PtrSize( FTIMEEDGES(pObj) )); Vec_PtrPush( pManMR->vExactNodes, pObj ); // rev topo order Abc_FlowRetime_ConstrainExact_back_rec( pObj, vNodes, 0 ); Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pCur, i) { pReg = Abc_ObjRegular( pCur ); if (pReg == pCur) { assert(!Abc_ObjIsLatch(pReg)); Abc_ObjForEachFanout(pReg, pNext, j) pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); assert((int)pReg->Level <= pManMR->maxDelay); pReg->Level = 0; pReg->fMarkA = pReg->fMarkB = 0; } } Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pCur, i) { pReg = Abc_ObjRegular( pCur ); if (pReg != pCur) { Abc_ObjForEachFanout(pReg, pNext, j) if (!Abc_ObjIsLatch(pNext)) pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); if ((int)pReg->Level == pManMR->maxDelay) { Vec_PtrPush( FTIMEEDGES(pObj), pReg); pManMR->nExactConstraints++; } pReg->Level = 0; pReg->fMarkA = pReg->fMarkB = 0; } } Vec_PtrClear( vNodes ); } /**Function************************************************************* Synopsis [Introduces all exact timing constraints in a network] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk ) { int i; Abc_Obj_t *pObj; void *pArray; // free existing constraints Abc_NtkForEachObj( pNtk, pObj, i ) if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); ABC_FREE( pArray ); } pManMR->nExactConstraints = 0; // generate all constraints Abc_NtkForEachObj(pNtk, pObj, i) if (!Abc_ObjIsLatch(pObj) && FTEST( pObj, CONSERVATIVE ) && !FTEST( pObj, BLOCK )) if (!Vec_PtrSize( FTIMEEDGES( pObj ) )) Abc_FlowRetime_ConstrainExact( pObj ); } /**Function************************************************************* Synopsis [Deallocates exact constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk ) { Abc_Obj_t *pObj; void *pArray; while( Vec_PtrSize( pManMR->vExactNodes )) { pObj = (Abc_Obj_t*)Vec_PtrPop( pManMR->vExactNodes ); if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); ABC_FREE( pArray ); } } Vec_PtrFree(pManMR->vExactNodes); ABC_FREE( pManMR->vTimeEdges ); } /**Function************************************************************* Synopsis [DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) { Abc_Obj_t *pNext; int i; if (Abc_ObjIsLatch(pObj)) return; Abc_NodeSetTravIdCurrent( pObj ); Abc_ObjForEachFanout( pObj, pNext, i ) if (!Abc_NodeIsTravIdCurrent( pNext )) Abc_FlowRetime_Dfs_forw( pNext, vNodes ); Vec_PtrPush( vNodes, pObj ); } void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) { Abc_Obj_t *pNext; int i; if (Abc_ObjIsLatch(pObj)) return; Abc_NodeSetTravIdCurrent( pObj ); Abc_ObjForEachFanin( pObj, pNext, i ) if (!Abc_NodeIsTravIdCurrent( pNext )) Abc_FlowRetime_Dfs_back( pNext, vNodes ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Main timing-constrained routine.] Description [Refines constraints that are limiting area improvement. These are identified by computing the min-cuts both with and without the conservative constraints: these two situation represent an over- and under-constrained version of the timing.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_FlowRetime_RefineConstraints( ) { Abc_Ntk_t *pNtk = pManMR->pNtk; int i, flow, count = 0; Abc_Obj_t *pObj; int maxTighten = 99999; vprintf("\t\tsubiter %d : constraints = {cons, exact} = %d, %d\n", pManMR->subIteration, pManMR->nConservConstraints, pManMR->nExactConstraints); // 1. overconstrained pManMR->constraintMask = BLOCK | CONSERVATIVE; vprintf("\t\trefinement: over "); fflush(stdout); flow = Abc_FlowRetime_PushFlows( pNtk, 0 ); vprintf("= %d ", flow); // remember nodes if (pManMR->fIsForward) { Abc_NtkForEachObj( pNtk, pObj, i ) if (!FTEST(pObj, VISITED_R)) pObj->fMarkC = 1; } else { Abc_NtkForEachObj( pNtk, pObj, i ) if (!FTEST(pObj, VISITED_E)) pObj->fMarkC = 1; } if (pManMR->fConservTimingOnly) { vprintf(" done\n"); return 0; } // 2. underconstrained pManMR->constraintMask = BLOCK; Abc_FlowRetime_ClearFlows( 0 ); vprintf("under = "); fflush(stdout); flow = Abc_FlowRetime_PushFlows( pNtk, 0 ); vprintf("%d refined nodes = ", flow); fflush(stdout); // find area-limiting constraints if (pManMR->fIsForward) { Abc_NtkForEachObj( pNtk, pObj, i ) { if (pObj->fMarkC && FTEST(pObj, VISITED_R) && FTEST(pObj, CONSERVATIVE) && count < maxTighten) { count++; Abc_FlowRetime_ConstrainExact( pObj ); } pObj->fMarkC = 0; } } else { Abc_NtkForEachObj( pNtk, pObj, i ) { if (pObj->fMarkC && FTEST(pObj, VISITED_E) && FTEST(pObj, CONSERVATIVE) && count < maxTighten) { count++; Abc_FlowRetime_ConstrainExact( pObj ); } pObj->fMarkC = 0; } } vprintf("%d\n", count); return (count > 0); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fret/fretime.h000066400000000000000000000134151300674244400234060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fretime.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Flow-based retiming package.] Synopsis [Header file for retiming package.] Author [Aaron Hurst] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2008.] Revision [$Id: fretime.h,v 1.00 2008/01/01 00:00:00 ahurst Exp $] ***********************************************************************/ #if !defined(RETIME_H_) #define RETIME_H_ #include "base/abc/abc.h" #include "misc/vec/vec.h" ABC_NAMESPACE_HEADER_START // #define IGNORE_TIMING // #define DEBUG_PRINT_FLOWS // #define DEBUG_VISITED // #define DEBUG_PREORDER #define DEBUG_CHECK // #define DEBUG_PRINT_LEVELS //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define MAX_DIST 30000 // flags in Flow_Data structure... #define VISITED_E 0x001 #define VISITED_R 0x002 #define VISITED (VISITED_E | VISITED_R) #define FLOW 0x004 #define CROSS_BOUNDARY 0x008 #define BLOCK 0x010 #define INIT_0 0x020 #define INIT_1 0x040 #define INIT_CARE (INIT_0 | INIT_1) #define CONSERVATIVE 0x080 #define BLOCK_OR_CONS (BLOCK | CONSERVATIVE) #define BIAS_NODE 0x100 #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) typedef struct Flow_Data_t_ { unsigned int mark : 16; union { Abc_Obj_t *pred; /* unsigned int var; */ Abc_Obj_t *pInitObj; Abc_Obj_t *pCopy; Vec_Ptr_t *vNodes; }; unsigned int e_dist : 16; unsigned int r_dist : 16; } Flow_Data_t; // useful macros for manipulating Flow_Data structure... #define FDATA( x ) (pManMR->pDataArray+Abc_ObjId(x)) #define FSET( x, y ) FDATA(x)->mark |= y #define FUNSET( x, y ) FDATA(x)->mark &= ~y #define FTEST( x, y ) (FDATA(x)->mark & y) #define FTIMEEDGES( x ) &(pManMR->vTimeEdges[Abc_ObjId( x )]) typedef struct NodeLag_T_ { int id; int lag; } NodeLag_t; typedef struct InitConstraint_t_ { Abc_Obj_t *pBiasNode; Vec_Int_t vNodes; Vec_Int_t vLags; } InitConstraint_t; typedef struct MinRegMan_t_ { // problem description: int maxDelay; int fComputeInitState, fGuaranteeInitState, fBlockConst; int nNodes, nLatches; int fForwardOnly, fBackwardOnly; int fConservTimingOnly; int nMaxIters; int fVerbose; Abc_Ntk_t *pNtk; int nPreRefine; // problem state int fIsForward; int fSinkDistTerminate; int nExactConstraints, nConservConstraints; int fSolutionIsDc; int constraintMask; int iteration, subIteration; Vec_Int_t *vLags; // problem data Vec_Int_t *vSinkDistHist; Flow_Data_t *pDataArray; Vec_Ptr_t *vTimeEdges; Vec_Ptr_t *vExactNodes; Vec_Ptr_t *vInitConstraints; Abc_Ntk_t *pInitNtk; Vec_Ptr_t *vNodes; // re-useable struct NodeLag_t *pInitToOrig; int sizeInitToOrig; } MinRegMan_t ; extern MinRegMan_t *pManMR; #define vprintf if (pManMR->fVerbose) printf static inline void FSETPRED(Abc_Obj_t *pObj, Abc_Obj_t *pPred) { assert(!Abc_ObjIsLatch(pObj)); // must preserve field to maintain init state linkage FDATA(pObj)->pred = pPred; } static inline Abc_Obj_t * FGETPRED(Abc_Obj_t *pObj) { return FDATA(pObj)->pred; } /*=== fretMain.c ==========================================================*/ Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState, int fGuaranteeInitState, int fBlockConst, int fForward, int fBackward, int nMaxIters, int maxDelay, int fFastButConservative); void print_node(Abc_Obj_t *pObj); void Abc_ObjBetterTransferFanout( Abc_Obj_t * pFrom, Abc_Obj_t * pTo, int complement ); int Abc_FlowRetime_PushFlows( Abc_Ntk_t * pNtk, int fVerbose ); int Abc_FlowRetime_IsAcrossCut( Abc_Obj_t *pCur, Abc_Obj_t *pNext ); void Abc_FlowRetime_ClearFlows( int fClearAll ); int Abc_FlowRetime_GetLag( Abc_Obj_t *pObj ); void Abc_FlowRetime_SetLag( Abc_Obj_t *pObj, int lag ); void Abc_FlowRetime_UpdateLags( ); void Abc_ObjPrintNeighborhood( Abc_Obj_t *pObj, int depth ); Abc_Ntk_t * Abc_FlowRetime_NtkSilentRestrash( Abc_Ntk_t * pNtk, int fCleanup ); /*=== fretFlow.c ==========================================================*/ int dfsplain_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ); int dfsplain_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ); void dfsfast_preorder( Abc_Ntk_t *pNtk ); int dfsfast_e( Abc_Obj_t *pObj, Abc_Obj_t *pPred ); int dfsfast_r( Abc_Obj_t *pObj, Abc_Obj_t *pPred ); /*=== fretInit.c ==========================================================*/ void Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk ); void Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk ); void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk ); void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ); void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ); int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ); void Abc_FlowRetime_ConstrainInit( ); void Abc_FlowRetime_AddInitBias( ); void Abc_FlowRetime_RemoveInitBias( ); /*=== fretTime.c ==========================================================*/ void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk ); void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk ); int Abc_FlowRetime_RefineConstraints( ); void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk ); void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj ); void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk ); ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fret/module.make000066400000000000000000000002041300674244400237160ustar00rootroot00000000000000SRC += \ src/opt/fret/fretMain.c \ src/opt/fret/fretFlow.c \ src/opt/fret/fretInit.c \ src/opt/fret/fretTime.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/000077500000000000000000000000001300674244400215745ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/fsim.h000066400000000000000000000074541300674244400227150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fsim.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast sequential AIG simulator.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: fsim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__fsim__fsim_h #define ABC__aig__fsim__fsim_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Fsim_Man_t_ Fsim_Man_t; // simulation parameters typedef struct Fsim_ParSim_t_ Fsim_ParSim_t; struct Fsim_ParSim_t_ { // user-controlled parameters int nWords; // the number of machine words int nIters; // the number of timeframes int TimeLimit; // time limit in seconds int fCheckMiter; // check if miter outputs are non-zero int fVerbose; // enables verbose output // internal parameters int fCompressAig; // compresses internal data }; // switching estimation parameters typedef struct Fsim_ParSwitch_t_ Fsim_ParSwitch_t; struct Fsim_ParSwitch_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 nRandPiNum; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc) int fProbOne; // collect probability of one int fProbTrans; // collect probatility of switching int fVerbose; // enables verbose output }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== fsimCore.c ==========================================================*/ extern void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p ); extern void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p ); /*=== fsimSim.c ==========================================================*/ extern int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars ); /*=== fsimSwitch.c ==========================================================*/ extern Vec_Int_t * Fsim_ManSwitchSimulate( Aig_Man_t * pAig, Fsim_ParSwitch_t * pPars ); /*=== fsimTsim.c ==========================================================*/ extern Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/fsimCore.c000066400000000000000000000055271300674244400235200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fsimCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast sequential AIG simulator.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: fsimCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fsimInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManSetDefaultParamsSim( Fsim_ParSim_t * p ) { memset( p, 0, sizeof(Fsim_ParSim_t) ); // user-controlled parameters p->nWords = 8; // the number of machine words p->nIters = 32; // the number of timeframes p->TimeLimit = 60; // time limit in seconds p->fCheckMiter = 0; // check if miter outputs are non-zero p->fVerbose = 1; // enables verbose output // internal parameters p->fCompressAig = 0; // compresses internal data } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManSetDefaultParamsSwitch( Fsim_ParSwitch_t * p ) { memset( p, 0, sizeof(Fsim_ParSwitch_t) ); // user-controlled parameters p->nWords = 1; // the number of machine words p->nIters = 48; // the number of timeframes p->nPref = 16; // the number of first timeframes to skip p->nRandPiNum = 0; // PI trans prob (0=1/2; 1=1/4; 2=1/8, etc) p->fProbOne = 1; // collect probability of one p->fProbTrans = 1; // collect probatility of switching p->fVerbose = 1; // enables verbose output } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/fsimFront.c000066400000000000000000000253061300674244400237150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fsimFront.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast sequential AIG simulator.] Synopsis [Simulation frontier.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: fsimFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fsimInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManStoreNum( Fsim_Man_t * p, int Num ) { unsigned x = (unsigned)Num; assert( Num >= 0 ); while ( x & ~0x7f ) { *p->pDataCur++ = (x & 0x7f) | 0x80; x >>= 7; } *p->pDataCur++ = x; assert( p->pDataCur - p->pDataAig < p->nDataAig ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fsim_ManRestoreNum( Fsim_Man_t * p ) { int ch, i, x = 0; for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ ) x |= (ch & 0x7f) << (7 * i); assert( p->pDataCur - p->pDataAig < p->nDataAig ); return x | (ch << (7 * i)); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManStoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) { if ( p->pDataAig2 ) { *p->pDataCur2++ = pObj->iNode; *p->pDataCur2++ = pObj->iFan0; *p->pDataCur2++ = pObj->iFan1; return; } if ( pObj->iFan0 && pObj->iFan1 ) // and { assert( pObj->iNode ); assert( pObj->iNode >= p->iNodePrev ); assert( (pObj->iNode << 1) > pObj->iFan0 ); assert( pObj->iFan0 > pObj->iFan1 ); Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 3 ); Fsim_ManStoreNum( p, (pObj->iNode << 1) - pObj->iFan0 ); Fsim_ManStoreNum( p, pObj->iFan0 - pObj->iFan1 ); p->iNodePrev = pObj->iNode; } else if ( !pObj->iFan0 && !pObj->iFan1 ) // ci { assert( pObj->iNode ); assert( pObj->iNode >= p->iNodePrev ); Fsim_ManStoreNum( p, ((pObj->iNode - p->iNodePrev) << 2) | 1 ); p->iNodePrev = pObj->iNode; } else // if ( !pObj->iFan0 && pObj->iFan1 ) // co { assert( pObj->iNode == 0 ); assert( pObj->iFan0 != 0 ); assert( pObj->iFan1 == 0 ); assert( ((p->iNodePrev << 1) | 1) >= pObj->iFan0 ); Fsim_ManStoreNum( p, (((p->iNodePrev << 1) | 1) - pObj->iFan0) << 1 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) { int iValue = Fsim_ManRestoreNum( p ); if ( (iValue & 3) == 3 ) // and { pObj->iNode = (iValue >> 2) + p->iNodePrev; pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p ); pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p ); p->iNodePrev = pObj->iNode; } else if ( (iValue & 3) == 1 ) // ci { pObj->iNode = (iValue >> 2) + p->iNodePrev; pObj->iFan0 = 0; pObj->iFan1 = 0; p->iNodePrev = pObj->iNode; } else // if ( (iValue & 1) == 0 ) // co { pObj->iNode = 0; pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1); pObj->iFan1 = 0; } return 1; } /**Function************************************************************* Synopsis [Determine the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fsim_ManFrontFindNext( Fsim_Man_t * p, char * pFront ) { assert( p->iNumber < (1 << 30) - p->nFront ); while ( 1 ) { if ( p->iNumber % p->nFront == 0 ) p->iNumber++; if ( pFront[p->iNumber % p->nFront] == 0 ) { pFront[p->iNumber % p->nFront] = 1; return p->iNumber; } p->iNumber++; } return -1; } /**Function************************************************************* Synopsis [Verifies the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManVerifyFront( Fsim_Man_t * p ) { Fsim_Obj_t * pObj; int * pFans0, * pFans1; // representation of fanins int * pFrontToId; // mapping of nodes into frontier variables int i, iVar0, iVar1; pFans0 = ABC_ALLOC( int, p->nObjs ); pFans1 = ABC_ALLOC( int, p->nObjs ); pFans0[0] = pFans1[0] = 0; pFans0[1] = pFans1[1] = 0; pFrontToId = ABC_CALLOC( int, p->nFront ); if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) pFrontToId[1] = 1; Fsim_ManForEachObj( p, pObj, i ) { if ( pObj->iNode ) pFrontToId[pObj->iNode % p->nFront] = i; iVar0 = Fsim_Lit2Var(pObj->iFan0); iVar1 = Fsim_Lit2Var(pObj->iFan1); pFans0[i] = Fsim_Var2Lit(pFrontToId[iVar0 % p->nFront], Fsim_LitIsCompl(pObj->iFan0)); pFans1[i] = Fsim_Var2Lit(pFrontToId[iVar1 % p->nFront], Fsim_LitIsCompl(pObj->iFan1)); } for ( i = 0; i < p->nObjs; i++ ) { assert( pFans0[i] == p->pFans0[i] ); assert( pFans1[i] == p->pFans1[i] ); } ABC_FREE( pFrontToId ); ABC_FREE( pFans0 ); ABC_FREE( pFans1 ); } /**Function************************************************************* Synopsis [Determine the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig ) { Fsim_Obj_t Obj, * pObj = &Obj; char * pFront; // places used for the frontier int * pIdToFront; // mapping of nodes into frontier places int i, iVar0, iVar1, nCrossCut = 0, nCrossCutMax = 0; // start the frontier pFront = ABC_CALLOC( char, p->nFront ); pIdToFront = ABC_ALLOC( int, p->nObjs ); pIdToFront[0] = -1; pIdToFront[1] = -1; // add constant node p->iNumber = 1; if ( p->pRefs[1] ) { pIdToFront[1] = Fsim_ManFrontFindNext( p, pFront ); nCrossCut = 1; } // allocate room for data if ( fCompressAig ) { p->nDataAig = p->nObjs * 6; p->pDataAig = ABC_ALLOC( unsigned char, p->nDataAig ); p->pDataCur = p->pDataAig; p->iNodePrev = 0; } else { p->pDataAig2 = ABC_ALLOC( int, 3 * p->nObjs ); p->pDataCur2 = p->pDataAig2 + 6; } // iterate through the objects for ( i = 2; i < p->nObjs; i++ ) { if ( p->pFans0[i] == 0 ) // ci { // store node pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront ); pObj->iNode = pIdToFront[i]; pObj->iFan0 = 0; pObj->iFan1 = 0; Fsim_ManStoreObj( p, pObj ); // handle CIs without fanout if ( p->pRefs[i] == 0 ) { pFront[pIdToFront[i] % p->nFront] = 0; pIdToFront[i] = -1; } } else if ( p->pFans1[i] == 0 ) // co { assert( p->pRefs[i] == 0 ); // get the fanin iVar0 = Fsim_Lit2Var(p->pFans0[i]); assert( pIdToFront[iVar0] > 0 ); // store node pObj->iNode = 0; pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i])); pObj->iFan1 = 0; Fsim_ManStoreObj( p, pObj ); // deref the fanin if ( --p->pRefs[iVar0] == 0 ) { pFront[pIdToFront[iVar0] % p->nFront] = 0; pIdToFront[iVar0] = -1; nCrossCut--; } } else { // get the fanins iVar0 = Fsim_Lit2Var(p->pFans0[i]); assert( pIdToFront[iVar0] > 0 ); iVar1 = Fsim_Lit2Var(p->pFans1[i]); assert( pIdToFront[iVar1] > 0 ); // store node pIdToFront[i] = Fsim_ManFrontFindNext( p, pFront ); pObj->iNode = pIdToFront[i]; pObj->iFan0 = Fsim_Var2Lit(pIdToFront[iVar0], Fsim_LitIsCompl(p->pFans0[i])); pObj->iFan1 = Fsim_Var2Lit(pIdToFront[iVar1], Fsim_LitIsCompl(p->pFans1[i])); Fsim_ManStoreObj( p, pObj ); // deref the fanins if ( --p->pRefs[iVar0] == 0 ) { pFront[pIdToFront[iVar0] % p->nFront] = 0; pIdToFront[iVar0] = -1; nCrossCut--; } if ( --p->pRefs[iVar1] == 0 ) { pFront[pIdToFront[iVar1] % p->nFront] = 0; pIdToFront[iVar1] = -1; nCrossCut--; } // handle nodes without fanout (choice nodes) if ( p->pRefs[i] == 0 ) { pFront[pIdToFront[i] % p->nFront] = 0; pIdToFront[i] = -1; } } if ( p->pRefs[i] ) if ( nCrossCutMax < ++nCrossCut ) nCrossCutMax = nCrossCut; } assert( p->pDataAig2 == NULL || p->pDataCur2 - p->pDataAig2 == (3 * p->nObjs) ); assert( nCrossCut == 0 ); assert( nCrossCutMax == p->nCrossCutMax ); for ( i = 0; i < p->nFront; i++ ) assert( pFront[i] == 0 ); ABC_FREE( pFront ); ABC_FREE( pIdToFront ); // Fsim_ManVerifyFront( p ); ABC_FREE( p->pFans0 ); ABC_FREE( p->pFans1 ); ABC_FREE( p->pRefs ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/fsimInt.h000066400000000000000000000134051300674244400233610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fsimInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast sequential AIG simulator.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: fsimInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__fsim__fsimInt_h #define ABC__aig__fsim__fsimInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/saig/saig.h" #include "fsim.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // simulation object typedef struct Fsim_Obj_t_ Fsim_Obj_t; struct Fsim_Obj_t_ { int iNode; // the node ID int iFan0; // the first fanin int iFan1; // the second fanin }; // fast sequential simulation manager struct Fsim_Man_t_ { // parameters Aig_Man_t * pAig; // the AIG to be used for simulation int nWords; // the number of simulation words // 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 int * pRefs; // reference counter for each node int * pRefsCopy; // reference counter for each node Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids Vec_Int_t * vLos; // register outputs Vec_Int_t * vLis; // register inputs // cross-cut representation int nCrossCut; // temporary cross-cut variable int nCrossCutMax; // maximum cross-cut variable int nFront; // the size of frontier // derived AIG representation int nDataAig; // the length of allocated data unsigned char * pDataAig; // AIG representation unsigned char * pDataCur; // AIG representation (current position) int iNodePrev; // previous extracted value int iNumber; // the number of the last object Fsim_Obj_t Obj; // current object // temporary AIG representation int * pDataAig2; // temporary representation int * pDataCur2; // AIG representation (current position) // simulation information unsigned * pDataSim; // simulation data unsigned * pDataSimCis; // simulation data for CIs unsigned * pDataSimCos; // simulation data for COs // other information int * pData1; int * pData2; }; static inline unsigned * Fsim_SimData( Fsim_Man_t * p, int i ) { return p->pDataSim + i * p->nWords; } static inline unsigned * Fsim_SimDataCi( Fsim_Man_t * p, int i ) { return p->pDataSimCis + i * p->nWords; } static inline unsigned * Fsim_SimDataCo( Fsim_Man_t * p, int i ) { return p->pDataSimCos + i * p->nWords; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Fsim_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } static inline int Fsim_Lit2Var( int Lit ) { return Lit >> 1; } static inline int Fsim_LitIsCompl( int Lit ) { return Lit & 1; } static inline int Fsim_LitNot( int Lit ) { return Lit ^ 1; } static inline int Fsim_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } static inline int Fsim_LitRegular( int Lit ) { return Lit & ~01; } #define Fsim_ManForEachObj( p, pObj, i )\ for ( i = 2, p->pDataCur = p->pDataAig, p->iNodePrev = 0, pObj = &p->Obj;\ i < p->nObjs && Fsim_ManRestoreObj( p, pObj ); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== fsimFront.c ========================================================*/ extern void Fsim_ManFront( Fsim_Man_t * p, int fCompressAig ); /*=== fsimMan.c ==========================================================*/ extern Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig ); extern void Fsim_ManDelete( Fsim_Man_t * p ); extern void Fsim_ManTest( Aig_Man_t * pAig ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/fsimMan.c000066400000000000000000000141761300674244400233430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fsimMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast sequential AIG simulator.] Synopsis [Simulation manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: fsimMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fsimInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fsim_ManCreate_rec( Fsim_Man_t * p, Aig_Obj_t * pObj ) { int iFan0, iFan1, iTemp; assert( !Aig_IsComplement(pObj) ); if ( pObj->iData ) return pObj->iData; assert( !Aig_ObjIsConst1(pObj) ); if ( Aig_ObjIsNode(pObj) ) { iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); iFan1 = Fsim_ManCreate_rec( p, Aig_ObjFanin1(pObj) ); assert( iFan0 != iFan1 ); if ( --p->pRefs[iFan0] == 0 ) p->nCrossCut--; iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) ); if ( --p->pRefs[iFan1] == 0 ) p->nCrossCut--; iFan1 = Fsim_Var2Lit( iFan1, Aig_ObjFaninC1(pObj) ); if ( p->pAig->pEquivs ) Fsim_ManCreate_rec( p, Aig_ObjEquiv(p->pAig, pObj) ); } else if ( Aig_ObjIsPo(pObj) ) { assert( Aig_ObjRefs(pObj) == 0 ); iFan0 = Fsim_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); if ( --p->pRefs[iFan0] == 0 ) p->nCrossCut--; iFan0 = Fsim_Var2Lit( iFan0, Aig_ObjFaninC0(pObj) ); iFan1 = 0; } else { iFan0 = iFan1 = 0; Vec_IntPush( p->vCis2Ids, Aig_ObjPioNum(pObj) ); } if ( iFan0 < iFan1 ) iTemp = iFan0, iFan0 = iFan1, iFan1 = iTemp; p->pFans0[p->nObjs] = iFan0; p->pFans1[p->nObjs] = iFan1; p->pRefs[p->nObjs] = Aig_ObjRefs(pObj); if ( p->pRefs[p->nObjs] ) if ( p->nCrossCutMax < ++p->nCrossCut ) p->nCrossCutMax = p->nCrossCut; return pObj->iData = p->nObjs++; } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fsim_Man_t * Fsim_ManCreate( Aig_Man_t * pAig ) { Fsim_Man_t * p; Aig_Obj_t * pObj; int i, nObjs; Aig_ManCleanData( pAig ); p = (Fsim_Man_t *)ABC_ALLOC( Fsim_Man_t, 1 ); memset( p, 0, sizeof(Fsim_Man_t) ); p->pAig = pAig; p->nPis = Saig_ManPiNum(pAig); p->nPos = Saig_ManPoNum(pAig); p->nCis = Aig_ManPiNum(pAig); p->nCos = Aig_ManPoNum(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->vCis2Ids = Vec_IntAlloc( Aig_ManPiNum(pAig) ); // add objects (0=unused; 1=const1) p->pFans0[0] = p->pFans1[0] = 0; p->pFans0[1] = p->pFans1[1] = 0; p->pRefs[0] = 0; p->nObjs = 2; pObj = Aig_ManConst1( pAig ); pObj->iData = 1; p->pRefs[1] = Aig_ObjRefs(pObj); if ( p->pRefs[1] ) p->nCrossCut = 1; Aig_ManForEachPi( pAig, pObj, i ) if ( Aig_ObjRefs(pObj) == 0 ) Fsim_ManCreate_rec( p, pObj ); Aig_ManForEachPo( pAig, pObj, i ) Fsim_ManCreate_rec( p, pObj ); assert( Vec_IntSize(p->vCis2Ids) == Aig_ManPiNum(pAig) ); assert( p->nObjs == nObjs ); // check references assert( p->nCrossCut == 0 ); Aig_ManForEachObj( pAig, pObj, i ) { assert( p->pRefs[pObj->iData] == 0 ); p->pRefs[pObj->iData] = Aig_ObjRefs(pObj); } // 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 ); // determine the frontier size p->nFront = 1 + (int)(1.1 * p->nCrossCutMax); return p; } /**Function************************************************************* Synopsis [Deletes fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManDelete( Fsim_Man_t * p ) { Vec_IntFree( p->vCis2Ids ); Vec_IntFree( p->vLos ); Vec_IntFree( p->vLis ); ABC_FREE( p->pDataAig2 ); ABC_FREE( p->pDataAig ); ABC_FREE( p->pFans0 ); ABC_FREE( p->pFans1 ); ABC_FREE( p->pRefs ); ABC_FREE( p->pDataSim ); ABC_FREE( p->pDataSimCis ); ABC_FREE( p->pDataSimCos ); ABC_FREE( p->pData1 ); ABC_FREE( p->pData2 ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Testing procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManTest( Aig_Man_t * pAig ) { Fsim_Man_t * p; p = Fsim_ManCreate( pAig ); Fsim_ManFront( p, 0 ); Fsim_ManDelete( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/fsimSim.c000066400000000000000000000372571300674244400233650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fsimSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast sequential AIG simulator.] Synopsis [Simulation procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: fsimSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fsimInt.h" #include "aig/ssw/ssw.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManSimInfoRandom( Fsim_Man_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = Aig_ManRandom( 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManSimInfoZero( Fsim_Man_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 Fsim_ManSimInfoIsZero( Fsim_Man_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) if ( pInfo[w] ) return 32*(w-1) + Aig_WordFindFirstBit( pInfo[w] ); return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManSimInfoOne( Fsim_Man_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 Fsim_ManSimInfoCopy( Fsim_Man_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 Fsim_ManSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) { unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); unsigned * pInfo0 = Fsim_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 Fsim_ManSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) { unsigned * pInfo = Fsim_SimDataCo( p, iCo ); unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); int w; if ( Fsim_LitIsCompl(iFan0) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w]; else //if ( !Fsim_LitIsCompl(iFan0) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) { unsigned * pInfo = Fsim_SimData( p, iNode % p->nFront ); unsigned * pInfo0 = Fsim_SimData( p, Fsim_Lit2Var(iFan0) % p->nFront ); unsigned * pInfo1 = Fsim_SimData( p, Fsim_Lit2Var(iFan1) % p->nFront ); int w; if ( Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~(pInfo0[w] | pInfo1[w]); else if ( Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w] & pInfo1[w]; else if ( !Fsim_LitIsCompl(iFan0) && Fsim_LitIsCompl(iFan1) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & ~pInfo1[w]; else //if ( !Fsim_LitIsCompl(iFan0) && !Fsim_LitIsCompl(iFan1) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & pInfo1[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManSimInfoInit( Fsim_Man_t * p ) { int iPioNum, i; Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) { if ( iPioNum < p->nPis ) Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) ); else Fsim_ManSimInfoZero( p, Fsim_SimDataCi(p, i) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManSimInfoTransfer( Fsim_Man_t * p ) { int iPioNum, i; Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) { if ( iPioNum < p->nPis ) Fsim_ManSimInfoRandom( p, Fsim_SimDataCi(p, i) ); else Fsim_ManSimInfoCopy( p, Fsim_SimDataCi(p, i), Fsim_SimDataCo(p, p->nPos+iPioNum-p->nPis) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fsim_ManRestoreNum( Fsim_Man_t * p ) { int ch, i, x = 0; for ( i = 0; (ch = *p->pDataCur++) & 0x80; i++ ) x |= (ch & 0x7f) << (7 * i); assert( p->pDataCur - p->pDataAig < p->nDataAig ); return x | (ch << (7 * i)); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fsim_ManRestoreObj( Fsim_Man_t * p, Fsim_Obj_t * pObj ) { int iValue = Fsim_ManRestoreNum( p ); if ( (iValue & 3) == 3 ) // and { pObj->iNode = (iValue >> 2) + p->iNodePrev; pObj->iFan0 = (pObj->iNode << 1) - Fsim_ManRestoreNum( p ); pObj->iFan1 = pObj->iFan0 - Fsim_ManRestoreNum( p ); p->iNodePrev = pObj->iNode; } else if ( (iValue & 3) == 1 ) // ci { pObj->iNode = (iValue >> 2) + p->iNodePrev; pObj->iFan0 = 0; pObj->iFan1 = 0; p->iNodePrev = pObj->iNode; } else // if ( (iValue & 1) == 0 ) // co { pObj->iNode = 0; pObj->iFan0 = ((p->iNodePrev << 1) | 1) - (iValue >> 1); pObj->iFan1 = 0; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManSimulateRound2( Fsim_Man_t * p ) { Fsim_Obj_t * pObj; int i, iCis = 0, iCos = 0; if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) ); Fsim_ManForEachObj( p, pObj, i ) { if ( pObj->iFan0 == 0 ) Fsim_ManSimulateCi( p, pObj->iNode, iCis++ ); else if ( pObj->iFan1 == 0 ) Fsim_ManSimulateCo( p, iCos++, pObj->iFan0 ); else Fsim_ManSimulateNode( p, pObj->iNode, pObj->iFan0, pObj->iFan1 ); } assert( iCis == p->nCis ); assert( iCos == p->nCos ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManSimulateRound( Fsim_Man_t * p ) { int * pCur, * pEnd; int iCis = 0, iCos = 0; if ( p->pDataAig2 == NULL ) { Fsim_ManSimulateRound2( p ); return; } if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) Fsim_ManSimInfoOne( p, Fsim_SimData(p, 1) ); pCur = p->pDataAig2 + 6; pEnd = p->pDataAig2 + 3 * p->nObjs; while ( pCur < pEnd ) { if ( pCur[1] == 0 ) Fsim_ManSimulateCi( p, pCur[0], iCis++ ); else if ( pCur[2] == 0 ) Fsim_ManSimulateCo( p, iCos++, pCur[1] ); else Fsim_ManSimulateNode( p, pCur[0], pCur[1], pCur[2] ); pCur += 3; } assert( iCis == p->nCis ); assert( iCos == p->nCos ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManSimulateRoundTest( Fsim_Man_t * p ) { Fsim_Obj_t * pObj; int i; clock_t clk = clock(); Fsim_ManForEachObj( p, pObj, i ) { } // ABC_PRT( "Unpacking time", p->pPars->nIters * (clock() - clk) ); } /**Function************************************************************* Synopsis [Returns index of the PO and pattern that failed it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fsim_ManCheckPos( Fsim_Man_t * p, int * piPo, int * piPat ) { int i, iPat; for ( i = 0; i < p->nPos; i++ ) { iPat = Fsim_ManSimInfoIsZero( p, Fsim_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 * Fsim_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_ManPiNum(pAig); i++ ) { iPioId = Vec_IntEntry( vCis2Ids, i ); if ( iPioId >= p->nPis ) continue; for ( w = nWords-1; w >= 0; w-- ) pData[w] = Aig_ManRandom( 0 ); if ( Aig_InfoHasBit( pData, iPat ) ) Aig_InfoSetBit( p->pData, Counter + iPioId ); } ABC_FREE( pData ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fsim_ManSimulate( Aig_Man_t * pAig, Fsim_ParSim_t * pPars ) { Fsim_Man_t * p; Sec_MtrStatus_t Status; int i, iOut, iPat; clock_t clk, clkTotal = clock(), clk2, clk2Total = 0; assert( Aig_ManRegNum(pAig) > 0 ); if ( pPars->fCheckMiter ) { 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; } } // create manager clk = clock(); p = Fsim_ManCreate( pAig ); p->nWords = pPars->nWords; if ( pPars->fVerbose ) { printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f MB. ", p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, 4.0*p->nWords*(p->nFront)/(1<<20) ); ABC_PRT( "Time", clock() - clk ); } // create simulation frontier clk = clock(); Fsim_ManFront( p, pPars->fCompressAig ); if ( pPars->fVerbose ) { printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f MB (%5.2f byte/obj). ", p->iNumber, Aig_Base2Log(p->iNumber), 1.0*(p->pDataCur-p->pDataAig)/(1<<20), 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); ABC_PRT( "Time", clock() - clk ); } // perform simulation Aig_ManRandom( 1 ); assert( p->pDataSim == NULL ); p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->nFront ); p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * p->nCis ); p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * p->nCos ); Fsim_ManSimInfoInit( p ); for ( i = 0; i < pPars->nIters; i++ ) { Fsim_ManSimulateRound( p ); if ( pPars->fVerbose ) { printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit ); printf( "Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC ); } if ( pPars->fCheckMiter && Fsim_ManCheckPos( p, &iOut, &iPat ) ) { assert( pAig->pSeqModel == NULL ); pAig->pSeqModel = Fsim_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids ); if ( pPars->fVerbose ) printf( "Miter is satisfiable after simulation (output %d).\n", iOut ); break; } if ( (clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit ) break; clk2 = clock(); if ( i < pPars->nIters - 1 ) Fsim_ManSimInfoTransfer( p ); clk2Total += clock() - clk2; } if ( pAig->pSeqModel == NULL ) printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, pPars->TimeLimit ); if ( pPars->fVerbose ) { printf( "Maxcut = %8d. AigMem = %7.2f MB. SimMem = %7.2f MB. ", p->nCrossCutMax, p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), 4.0*p->nWords*(p->nFront+p->nCis+p->nCos)/(1<<20) ); ABC_PRT( "Sim time", clock() - clkTotal ); // ABC_PRT( "Additional time", clk2Total ); // Fsim_ManSimulateRoundTest( p ); // Fsim_ManSimulateRoundTest2( p ); } Fsim_ManDelete( p ); return pAig->pSeqModel != NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/fsimSwitch.c000066400000000000000000000023551300674244400240650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fsimSwitch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast sequential AIG simulator.] Synopsis [Computing switching activity.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: fsimSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fsimInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/fsimTsim.c000066400000000000000000000316151300674244400235410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fsimTsim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast sequential AIG simulator.] Synopsis [Varius utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: fsimTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fsimInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define FSIM_ZER 1 #define FSIM_ONE 2 #define FSIM_UND 3 static inline int Aig_XsimNotCond( int Value, int fCompl ) { if ( Value == FSIM_UND ) return FSIM_UND; if ( Value == FSIM_ZER + fCompl ) return FSIM_ZER; return FSIM_ONE; } static inline int Aig_XsimAndCond( int Value0, int fCompl0, int Value1, int fCompl1 ) { if ( Value0 == FSIM_UND || Value1 == FSIM_UND ) return FSIM_UND; if ( Value0 == FSIM_ZER + fCompl0 || Value1 == FSIM_ZER + fCompl1 ) return FSIM_ZER; return FSIM_ONE; } static inline int Fsim_ManTerSimInfoGet( unsigned * pInfo, int i ) { return 3 & (pInfo[i >> 4] >> ((i & 15) << 1)); } static inline void Fsim_ManTerSimInfoSet( unsigned * pInfo, int i, int Value ) { assert( Value >= FSIM_ZER && Value <= FSIM_UND ); Value ^= Fsim_ManTerSimInfoGet( pInfo, i ); pInfo[i >> 4] ^= (Value << ((i & 15) << 1)); } static inline unsigned * Fsim_ManTerStateNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } static inline void Fsim_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManTerSimulateCi( Fsim_Man_t * p, int iNode, int iCi ) { Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Fsim_ManTerSimInfoGet(p->pDataSimCis, iCi) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManTerSimulateCo( Fsim_Man_t * p, int iCo, int iFan0 ) { int Value = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) ); Fsim_ManTerSimInfoSet( p->pDataSimCos, iCo, Aig_XsimNotCond( Value, Fsim_LitIsCompl(iFan0) ) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManTerSimulateNode( Fsim_Man_t * p, int iNode, int iFan0, int iFan1 ) { int Value0 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan0) ); int Value1 = Fsim_ManTerSimInfoGet( p->pDataSim, Fsim_Lit2Var(iFan1) ); Fsim_ManTerSimInfoSet( p->pDataSim, iNode, Aig_XsimAndCond( Value0, Fsim_LitIsCompl(iFan0), Value1, Fsim_LitIsCompl(iFan1) ) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManTerSimInfoInit( Fsim_Man_t * p ) { int iPioNum, i; Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) { if ( iPioNum < p->nPis ) Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND ); else Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_ZER ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManTerSimInfoTransfer( Fsim_Man_t * p ) { int iPioNum, i; Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) { if ( iPioNum < p->nPis ) Fsim_ManTerSimInfoSet( p->pDataSimCis, i, FSIM_UND ); else Fsim_ManTerSimInfoSet( p->pDataSimCis, i, Fsim_ManTerSimInfoGet( p->pDataSimCos, p->nPos+iPioNum-p->nPis ) ); } } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fsim_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 [] ***********************************************************************/ int Fsim_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) { unsigned * pEntry; int Hash; Hash = Fsim_ManTerStateHash( pState, nWords, nBins ); for ( pEntry = pBins[Hash]; pEntry; pEntry = Fsim_ManTerStateNext(pEntry, nWords) ) if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) { int Hash = Fsim_ManTerStateHash( pState, nWords, nBins ); assert( !Fsim_ManTerStateLookup( pState, nWords, pBins, nBins ) ); Fsim_ManTerStateSetNext( pState, nWords, pBins[Hash] ); pBins[Hash] = pState; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Fsim_ManTerStateCreate( unsigned * pInfo, int nPis, int nCis, int nWords ) { unsigned * pRes; int i; pRes = (unsigned *)ABC_CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) ); for ( i = nPis; i < nCis; i++ ) Fsim_ManTerSimInfoSet( pRes, i-nPis, Fsim_ManTerSimInfoGet(pInfo, i) ); return pRes; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fsim_ManTerStatePrint( unsigned * pState, int nRegs ) { int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; for ( i = 0; i < nRegs; i++ ) { Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fsim_ManTerSimulateRound( Fsim_Man_t * p ) { int * pCur, * pEnd; int iCis = 0, iCos = 0; if ( Aig_ObjRefs(Aig_ManConst1(p->pAig)) ) Fsim_ManTerSimInfoSet( p->pDataSimCis, 1, FSIM_ONE ); pCur = p->pDataAig2 + 6; pEnd = p->pDataAig2 + 3 * p->nObjs; while ( pCur < pEnd ) { if ( pCur[1] == 0 ) Fsim_ManTerSimulateCi( p, pCur[0], iCis++ ); else if ( pCur[2] == 0 ) Fsim_ManTerSimulateCo( p, iCos++, pCur[1] ); else Fsim_ManTerSimulateNode( p, pCur[0], pCur[1], pCur[2] ); pCur += 3; } assert( iCis == p->nCis ); assert( iCos == p->nCos ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Fsim_ManTerSimulate( Aig_Man_t * pAig, int fVerbose ) { Fsim_Man_t * p; Vec_Ptr_t * vStates; unsigned ** pBins, * pState; int i, nWords, nBins; clock_t clk, clkTotal = clock(); assert( Aig_ManRegNum(pAig) > 0 ); // create manager clk = clock(); p = Fsim_ManCreate( pAig ); if ( fVerbose ) { printf( "Obj = %8d (%8d). Cut = %6d. Front = %6d. FrtMem = %7.2f MB. ", p->nObjs, p->nCis + p->nNodes, p->nCrossCutMax, p->nFront, 4.0*Aig_BitWordNum(2 * p->nFront)/(1<<20) ); ABC_PRT( "Time", clock() - clk ); } // create simulation frontier clk = clock(); Fsim_ManFront( p, 0 ); if ( fVerbose ) { printf( "Max ID = %8d. Log max ID = %2d. AigMem = %7.2f MB (%5.2f byte/obj). ", p->iNumber, Aig_Base2Log(p->iNumber), 1.0*(p->pDataCur-p->pDataAig)/(1<<20), 1.0*(p->pDataCur-p->pDataAig)/p->nObjs ); ABC_PRT( "Time", clock() - clk ); } // allocate storage for terminary states nWords = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) ); vStates = Vec_PtrAlloc( 1000 ); nBins = Abc_PrimeCudd( 500 ); pBins = ABC_ALLOC( unsigned *, nBins ); memset( pBins, 0, sizeof(unsigned *) * nBins ); // perform simulation assert( p->pDataSim == NULL ); p->pDataSim = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nFront) * sizeof(unsigned) ); p->pDataSimCis = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nCis) * sizeof(unsigned) ); p->pDataSimCos = ABC_ALLOC( unsigned, Aig_BitWordNum(2 * p->nCos) * sizeof(unsigned) ); Fsim_ManTerSimInfoInit( p ); // hash the first state pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords ); Vec_PtrPush( vStates, pState ); Fsim_ManTerStateInsert( pState, nWords, pBins, nBins ); // perform simuluation till convergence for ( i = 0; ; i++ ) { Fsim_ManTerSimulateRound( p ); Fsim_ManTerSimInfoTransfer( p ); // hash the first state pState = Fsim_ManTerStateCreate( p->pDataSimCis, p->nPis, p->nCis, nWords ); Vec_PtrPush( vStates, pState ); if ( Fsim_ManTerStateLookup(pState, nWords, pBins, nBins) ) break; Fsim_ManTerStateInsert( pState, nWords, pBins, nBins ); } if ( fVerbose ) { printf( "Maxcut = %8d. AigMem = %7.2f MB. SimMem = %7.2f MB. ", p->nCrossCutMax, p->pDataAig2? 12.0*p->nObjs/(1<<20) : 1.0*(p->pDataCur-p->pDataAig)/(1<<20), 4.0*(Aig_BitWordNum(2 * p->nFront)+Aig_BitWordNum(2 * p->nCis)+Aig_BitWordNum(2 * p->nCos))/(1<<20) ); ABC_PRT( "Sim time", clock() - clkTotal ); } ABC_FREE( pBins ); Fsim_ManDelete( p ); return vStates; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fsim/module.make000066400000000000000000000002471300674244400237230ustar00rootroot00000000000000SRC += src/opt/fsim/fsimCore.c \ src/opt/fsim/fsimFront.c \ src/opt/fsim/fsimMan.c \ src/opt/fsim/fsimSim.c \ src/opt/fsim/fsimSwitch.c \ src/opt/fsim/fsimTsim.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxch/000077500000000000000000000000001300674244400215665ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxch/Fxch.c000066400000000000000000000175741300674244400226400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ Fxch.c ] PackageName [ Fast eXtract with Cube Hashing (FXCH) ] Synopsis [ The entrance into the fast extract module. ] Author [ Bruno Schmitt - boschmitt at inf.ufrgs.br ] Affiliation [ UFRGS ] Date [ Ver. 1.0. Started - March 6, 2016. ] Revision [] ***********************************************************************/ #include "Fxch.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxch_CubesGruping(Fxch_Man_t* pFxchMan) { Vec_Int_t* vCube; int iCube, nOutputs, SizeOutputID; Hsh_VecMan_t* pCubeHash; /* Identify the number of Outputs and create the translation table */ pFxchMan->vTranslation = Vec_IntAlloc( 32 ); Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube ) { int Id = Vec_IntEntry( vCube, 0 ); int iTranslation = Vec_IntFind( pFxchMan->vTranslation, Id ); if ( iTranslation == -1 ) Vec_IntPush( pFxchMan->vTranslation, Id ); } nOutputs = Vec_IntSize( pFxchMan->vTranslation ); /* Size of the OutputID in number o ints */ SizeOutputID = ( nOutputs >> 5 ) + ( ( nOutputs & 31 ) > 0 ); /* Initialize needed structures */ pFxchMan->vOutputID = Vec_IntAlloc( 4096 ); pFxchMan->pTempOutputID = ABC_CALLOC( int, SizeOutputID ); pFxchMan->nSizeOutputID = SizeOutputID; pCubeHash = Hsh_VecManStart( 1024 ); /* Identify equal cubes */ Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube ) { int Id = Vec_IntEntry( vCube, 0 ); int iTranslation = Vec_IntFind( pFxchMan->vTranslation, Id ); int i, iCubeNoID, Temp, * pEntry; Vec_IntWriteEntry( vCube, 0, 0 ); // Clear ID, Outputs will be identified by it later iCubeNoID = Hsh_VecManAdd( pCubeHash, vCube ); Temp = ( 1 << ( iTranslation & 31 ) ); if ( iCubeNoID == Vec_IntSize( pFxchMan->vOutputID ) / SizeOutputID ) { for ( i = 0; i < SizeOutputID; i++ ) pFxchMan->pTempOutputID[i] = 0; pFxchMan->pTempOutputID[ iTranslation >> 5 ] = Temp; Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, SizeOutputID ); } else { Vec_IntClear( vCube ); pEntry = Vec_IntEntryP( pFxchMan->vOutputID, ( iCubeNoID * SizeOutputID ) + ( iTranslation >> 5 ) ); *pEntry |= Temp; } } Hsh_VecManStop( pCubeHash ); Vec_WecRemoveEmpty( pFxchMan->vCubes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxch_CubesUnGruping(Fxch_Man_t* pFxchMan) { int iCube; int i, j; Vec_Int_t* vCube; Vec_Int_t* vNewCube; assert( Vec_WecSize( pFxchMan->vCubes ) == ( Vec_IntSize( pFxchMan->vOutputID ) / pFxchMan->nSizeOutputID ) ); Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube ) { int * pOutputID, nOnes; if ( Vec_IntSize( vCube ) == 0 || Vec_IntEntry( vCube, 0 ) != 0 ) continue; pOutputID = Vec_IntEntryP( pFxchMan->vOutputID, iCube * pFxchMan->nSizeOutputID ); nOnes = 0; for ( i = 0; i < pFxchMan->nSizeOutputID; i++ ) nOnes += Fxch_CountOnes( (unsigned int) pOutputID[i] ); for ( i = 0; i < pFxchMan->nSizeOutputID && nOnes; i++ ) for ( j = 0; j < 32 && nOnes; j++ ) if ( pOutputID[i] & ( 1 << j ) ) { if ( nOnes == 1 ) Vec_IntWriteEntry( vCube, 0, Vec_IntEntry( pFxchMan->vTranslation, ( i << 5 ) | j ) ); else { vNewCube = Vec_WecPushLevel( pFxchMan->vCubes ); Vec_IntAppend( vNewCube, vCube ); Vec_IntWriteEntry( vNewCube, 0, Vec_IntEntry( pFxchMan->vTranslation, (i << 5 ) | j ) ); } nOnes -= 1; } } Vec_IntFree( pFxchMan->vTranslation ); Vec_IntFree( pFxchMan->vOutputID ); ABC_FREE( pFxchMan->pTempOutputID ); return; } /**Function************************************************************* Synopsis [ Performs fast extract with cube hashing on a set of covers. ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxch_FastExtract( Vec_Wec_t* vCubes, int ObjIdMax, int nMaxDivExt, int fVerbose, int fVeryVerbose ) { abctime TempTime; Fxch_Man_t* pFxchMan = Fxch_ManAlloc( vCubes ); int i; TempTime = Abc_Clock(); Fxch_CubesGruping( pFxchMan ); Fxch_ManMapLiteralsIntoCubes( pFxchMan, ObjIdMax ); Fxch_ManGenerateLitHashKeys( pFxchMan ); Fxch_ManComputeLevel( pFxchMan ); Fxch_ManSCHashTablesInit( pFxchMan ); Fxch_ManDivCreate( pFxchMan ); pFxchMan->timeInit = Abc_Clock() - TempTime; if ( fVeryVerbose ) Fxch_ManPrintDivs( pFxchMan ); if ( fVerbose ) Fxch_ManPrintStats( pFxchMan ); TempTime = Abc_Clock(); for ( i = 0; (!nMaxDivExt || i < nMaxDivExt) && Vec_QueTopPriority( pFxchMan->vDivPrio ) > 0.0; i++ ) { int iDiv = Vec_QuePop( pFxchMan->vDivPrio ); if ( fVeryVerbose ) Fxch_DivPrint( pFxchMan, iDiv ); Fxch_ManUpdate( pFxchMan, iDiv ); } pFxchMan->timeExt = Abc_Clock() - TempTime; if ( fVerbose ) { Fxch_ManPrintStats( pFxchMan ); Abc_PrintTime( 1, "\n[FXCH] Elapsed Time", pFxchMan->timeInit + pFxchMan->timeExt ); Abc_PrintTime( 1, "[FXCH] +-> Init", pFxchMan->timeInit ); Abc_PrintTime( 1, "[FXCH] +-> Extr", pFxchMan->timeExt ); } Fxch_CubesUnGruping( pFxchMan ); Fxch_ManSCHashTablesFree( pFxchMan ); Fxch_ManFree( pFxchMan ); Vec_WecRemoveEmpty( vCubes ); Vec_WecSortByFirstInt( vCubes, 0 ); return 1; } /**Function************************************************************* Synopsis [ Retrives the necessary information for the fast extract with cube hashing. ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFxchPerform( Abc_Ntk_t* pNtk, int nMaxDivExt, int fVerbose, int fVeryVerbose ) { Vec_Wec_t* vCubes; assert( Abc_NtkIsSopLogic( pNtk ) ); if ( !Abc_NtkFxCheck( pNtk ) ) { printf( "Abc_NtkFxchPerform(): Nodes have duplicated fanins. FXCH is not performed.\n" ); return 0; } vCubes = Abc_NtkFxRetrieve( pNtk ); if ( Fxch_FastExtract( vCubes, Abc_NtkObjNumMax( pNtk ), nMaxDivExt, fVerbose, fVeryVerbose ) > 0 ) { Abc_NtkFxInsert( pNtk, vCubes ); Vec_WecFree( vCubes ); if ( !Abc_NtkCheck( pNtk ) ) printf( "Abc_NtkFxchPerform(): The network check has failed.\n" ); return 1; } else printf( "Warning: The network has not been changed by \"fxch\".\n" ); Vec_WecFree( vCubes ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxch/Fxch.h000066400000000000000000000206571300674244400226410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ Fxch.h ] PackageName [ Fast eXtract with Cube Hashing (FXCH) ] Synopsis [ External declarations of fast extract with cube hashing. ] Author [ Bruno Schmitt - boschmitt at inf.ufrgs.br ] Affiliation [ UFRGS ] Date [ Ver. 1.0. Started - March 6, 2016. ] Revision [] ***********************************************************************/ #ifndef ABC__opt__fxch__fxch_h #define ABC__opt__fxch__fxch_h #include "base/abc/abc.h" #include "misc/vec/vecHsh.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecVec.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_HEADER_START typedef unsigned char uint8_t; typedef unsigned int uint32_t; //////////////////////////////////////////////////////////////////////// /// TYPEDEF DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Fxch_Man_t_ Fxch_Man_t; typedef struct Fxch_SubCube_t_ Fxch_SubCube_t; typedef struct Fxch_SCHashTable_t_ Fxch_SCHashTable_t; typedef struct Fxch_SCHashTable_Entry_t_ Fxch_SCHashTable_Entry_t; //////////////////////////////////////////////////////////////////////// /// STRUCTURES DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /* Sub-Cube Structure * * In the context of this program, a sub-cube is a cube derived from * another cube by removing one or two literals. Since a cube is represented * as a vector of literals, one might think that a sub-cube would also be * represented in the same way. However, in order to same memory, we only * store a sub-cube identifier and the data necessary to generate the sub-cube: * - The index number of the orignal cube in the cover. (iCube) * - Identifiers of which literal(s) was(were) removed. (iLit0, iLit1) * * The sub-cube identifier is generated by adding the unique identifiers of * its literals. * */ struct Fxch_SubCube_t_ { uint32_t Id, iCube; uint32_t iLit0 : 16, iLit1 : 16; }; /* Sub-cube Hash Table */ struct Fxch_SCHashTable_Entry_t_ { Fxch_SubCube_t* vSCData; uint32_t Size : 16, Cap : 16; }; struct Fxch_SCHashTable_t_ { Fxch_Man_t* pFxchMan; /* Internal data */ Fxch_SCHashTable_Entry_t* pBins; unsigned int nEntries, SizeMask; /* Temporary data */ Vec_Int_t vSubCube0; Vec_Int_t vSubCube1; }; struct Fxch_Man_t_ { /* user's data */ Vec_Wec_t* vCubes; int nCubesInit; int LitCountMax; /* internal data */ Fxch_SCHashTable_t* pSCHashTable; Vec_Wec_t* vLits; /* lit -> cube */ Vec_Int_t* vLitCount; /* literal counts (currently not used) */ Vec_Int_t* vLitHashKeys; /* Literal hash keys used to generate subcube hash */ Hsh_VecMan_t* pDivHash; Vec_Flt_t* vDivWeights; /* divisor weights */ Vec_Que_t* vDivPrio; /* priority queue for divisors by weight */ Vec_Wec_t* vDivCubePairs; /* cube pairs for each div */ Vec_Int_t* vLevels; /* variable levels */ // Cube Grouping Vec_Int_t* vTranslation; Vec_Int_t* vOutputID; int* pTempOutputID; int nSizeOutputID; // temporary data to update the data-structure when a divisor is extracted Vec_Int_t* vCubesS; /* cubes for the given single cube divisor */ Vec_Int_t* vPairs; /* cube pairs for the given double cube divisor */ Vec_Int_t* vCubeFree; // cube-free divisor Vec_Int_t* vDiv; // selected divisor Vec_Int_t* vCubesToRemove; Vec_Int_t* vCubesToUpdate; Vec_Int_t* vSCC; /* Statistics */ abctime timeInit; /* Initialization time */ abctime timeExt; /* Extraction time */ int nVars; // original problem variables int nLits; // the number of SOP literals int nPairsS; // number of lit pairs int nPairsD; // number of cube pairs int nExtDivs; /* Number of extracted divisor */ }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /* The following functions are from abcFx.c * They are use in order to retrive SOP information for fast_extract * Since I want an implementation that change only the core part of * the algorithm I'm using this */ extern Vec_Wec_t* Abc_NtkFxRetrieve( Abc_Ntk_t* pNtk ); extern void Abc_NtkFxInsert( Abc_Ntk_t* pNtk, Vec_Wec_t* vCubes ); extern int Abc_NtkFxCheck( Abc_Ntk_t* pNtk ); static inline int Fxch_CountOnes( unsigned num ) { num = ( num & 0x55555555 ) + ( ( num >> 1) & 0x55555555 ); num = ( num & 0x33333333 ) + ( ( num >> 2) & 0x33333333 ); num = ( num & 0x0F0F0F0F ) + ( ( num >> 4) & 0x0F0F0F0F ); num = ( num & 0x00FF00FF ) + ( ( num >> 8) & 0x00FF00FF ); return ( num & 0x0000FFFF ) + ( num >> 16 ); } /*===== Fxch.c =======================================================*/ int Abc_NtkFxchPerform( Abc_Ntk_t* pNtk, int nMaxDivExt, int fVerbose, int fVeryVerbose ); int Fxch_FastExtract( Vec_Wec_t* vCubes, int ObjIdMax, int nMaxDivExt, int fVerbose, int fVeryVerbose ); /*===== FxchDiv.c ====================================================================================================*/ int Fxch_DivCreate( Fxch_Man_t* pFxchMan, Fxch_SubCube_t* pSubCube0, Fxch_SubCube_t* pSubCube1 ); int Fxch_DivAdd( Fxch_Man_t* pFxchMan, int fUpdate, int fSingleCube, int fBase ); int Fxch_DivRemove( Fxch_Man_t* pFxchMan, int fUpdate, int fSingleCube, int fBase ); void Fxch_DivSepareteCubes( Vec_Int_t* vDiv, Vec_Int_t* vCube0, Vec_Int_t* vCube1 ); int Fxch_DivRemoveLits( Vec_Int_t* vCube0, Vec_Int_t* vCube1, Vec_Int_t* vDiv, int *fCompl ); void Fxch_DivPrint( Fxch_Man_t* pFxchMan, int iDiv ); int Fxch_DivIsNotConstant1( Vec_Int_t* vDiv ); /*===== FxchMan.c ====================================================================================================*/ Fxch_Man_t* Fxch_ManAlloc( Vec_Wec_t* vCubes ); void Fxch_ManFree( Fxch_Man_t* pFxchMan ); void Fxch_ManMapLiteralsIntoCubes( Fxch_Man_t* pFxchMan, int nVars ); void Fxch_ManGenerateLitHashKeys( Fxch_Man_t* pFxchMan ); void Fxch_ManSCHashTablesInit( Fxch_Man_t* pFxchMan ); void Fxch_ManSCHashTablesFree( Fxch_Man_t* pFxchMan ); void Fxch_ManDivCreate( Fxch_Man_t* pFxchMan ); int Fxch_ManComputeLevelDiv( Fxch_Man_t* pFxchMan, Vec_Int_t* vCubeFree ); int Fxch_ManComputeLevelCube( Fxch_Man_t* pFxchMan, Vec_Int_t* vCube ); void Fxch_ManComputeLevel( Fxch_Man_t* pFxchMan ); void Fxch_ManUpdate( Fxch_Man_t* pFxchMan, int iDiv ); void Fxch_ManPrintDivs( Fxch_Man_t* pFxchMan ); void Fxch_ManPrintStats( Fxch_Man_t* pFxchMan ); static inline Vec_Int_t* Fxch_ManGetCube( Fxch_Man_t* pFxchMan, int iCube ) { return Vec_WecEntry( pFxchMan->vCubes, iCube ); } static inline int Fxch_ManGetLit( Fxch_Man_t* pFxchMan, int iCube, int iLit ) { return Vec_IntEntry( Vec_WecEntry(pFxchMan->vCubes, iCube), iLit ); } /*===== FxchSCHashTable.c ============================================*/ Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan, int nEntries ); void Fxch_SCHashTableDelete( Fxch_SCHashTable_t* ); int Fxch_SCHashTableInsert( Fxch_SCHashTable_t* pSCHashTable, Vec_Wec_t* vCubes, uint32_t SubCubeID, uint32_t iCube, uint32_t iLit0, uint32_t iLit1, char fUpdate ); int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable, Vec_Wec_t* vCubes, uint32_t SubCubeID, uint32_t iCube, uint32_t iLit0, uint32_t iLit1, char fUpdate ); unsigned int Fxch_SCHashTableMemory( Fxch_SCHashTable_t* ); void Fxch_SCHashTablePrint( Fxch_SCHashTable_t* ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxch/FxchDiv.c000066400000000000000000000376671300674244400233100ustar00rootroot00000000000000/**CFile**************************************************************************************************************** FileName [ FxchDiv.c ] PackageName [ Fast eXtract with Cube Hashing (FXCH) ] Synopsis [ Divisor handling functions ] Author [ Bruno Schmitt - boschmitt at inf.ufrgs.br ] Affiliation [ UFRGS ] Date [ Ver. 1.0. Started - March 6, 2016. ] Revision [] ***********************************************************************************************************************/ #include "Fxch.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FUNCTION DEFINITIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static inline int Fxch_DivNormalize( Vec_Int_t* vCubeFree ) { int * L = Vec_IntArray(vCubeFree); int RetValue = 0, LitA0 = -1, LitB0 = -1, LitA1 = -1, LitB1 = -1; assert( Vec_IntSize(vCubeFree) == 4 ); if ( Abc_LitIsCompl(L[0]) != Abc_LitIsCompl(L[1]) && (L[0] >> 2) == (L[1] >> 2) ) // diff cubes, same vars { if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[3]) ) return -1; LitA0 = Abc_Lit2Var(L[0]), LitB0 = Abc_Lit2Var(L[1]); if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[2]) ) { assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[3]) ); LitA1 = Abc_Lit2Var(L[2]), LitB1 = Abc_Lit2Var(L[3]); } else { assert( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) ); assert( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[2]) ); LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[2]); } } else if ( Abc_LitIsCompl(L[1]) != Abc_LitIsCompl(L[2]) && (L[1] >> 2) == (L[2] >> 2) ) { if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[3]) ) return -1; LitA0 = Abc_Lit2Var(L[1]), LitB0 = Abc_Lit2Var(L[2]); if ( Abc_LitIsCompl(L[1]) == Abc_LitIsCompl(L[0]) ) LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[3]); else LitA1 = Abc_Lit2Var(L[3]), LitB1 = Abc_Lit2Var(L[0]); } else if ( Abc_LitIsCompl(L[2]) != Abc_LitIsCompl(L[3]) && (L[2] >> 2) == (L[3] >> 2) ) { if ( Abc_LitIsCompl(L[0]) == Abc_LitIsCompl(L[1]) ) return -1; LitA0 = Abc_Lit2Var(L[2]), LitB0 = Abc_Lit2Var(L[3]); if ( Abc_LitIsCompl(L[2]) == Abc_LitIsCompl(L[0]) ) LitA1 = Abc_Lit2Var(L[0]), LitB1 = Abc_Lit2Var(L[1]); else LitA1 = Abc_Lit2Var(L[1]), LitB1 = Abc_Lit2Var(L[0]); } else return -1; assert( LitA0 == Abc_LitNot(LitB0) ); if ( Abc_LitIsCompl(LitA0) ) { ABC_SWAP( int, LitA0, LitB0 ); ABC_SWAP( int, LitA1, LitB1 ); } assert( !Abc_LitIsCompl(LitA0) ); if ( Abc_LitIsCompl(LitA1) ) { LitA1 = Abc_LitNot(LitA1); LitB1 = Abc_LitNot(LitB1); RetValue = 1; } assert( !Abc_LitIsCompl(LitA1) ); // arrange literals in such as a way that // - the first two literals are control literals from different cubes // - the third literal is non-complented data input // - the forth literal is possibly complemented data input L[0] = Abc_Var2Lit( LitA0, 0 ); L[1] = Abc_Var2Lit( LitB0, 1 ); L[2] = Abc_Var2Lit( LitA1, 0 ); L[3] = Abc_Var2Lit( LitB1, 1 ); return RetValue; } /**Function************************************************************* Synopsis [ Creates a Divisor. ] Description [ This functions receive as input two sub-cubes and creates a divisor using their information. The divisor is stored in vCubeFree vector of the pFxchMan structure. It returns the base value, which is the number of elements that the cubes pair used to generate the devisor have in common. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxch_DivCreate( Fxch_Man_t* pFxchMan, Fxch_SubCube_t* pSubCube0, Fxch_SubCube_t* pSubCube1 ) { int Base = 0; int SC0_Lit0, SC0_Lit1, SC1_Lit0, SC1_Lit1; int Cube0Size, Cube1Size; Vec_IntClear( pFxchMan->vCubeFree ); SC0_Lit0 = Fxch_ManGetLit( pFxchMan, pSubCube0->iCube, pSubCube0->iLit0 ); SC0_Lit1 = 0; SC1_Lit0 = Fxch_ManGetLit( pFxchMan, pSubCube1->iCube, pSubCube1->iLit0 ); SC1_Lit1 = 0; if ( pSubCube0->iLit1 == 0 && pSubCube1->iLit1 == 0 ) { Vec_IntPush( pFxchMan->vCubeFree, SC0_Lit0 ); Vec_IntPush( pFxchMan->vCubeFree, SC1_Lit0 ); } else if ( pSubCube0->iLit1 > 0 && pSubCube1->iLit1 > 0 ) { int RetValue; SC0_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube0->iCube, pSubCube0->iLit1 ); SC1_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube1->iCube, pSubCube1->iLit1 ); if ( SC0_Lit0 < SC1_Lit0 ) { Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 0 ) ); Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 1 ) ); Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 0 ) ); Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 1 ) ); } else { Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit0, 0 ) ); Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit0, 1 ) ); Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC1_Lit1, 0 ) ); Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( SC0_Lit1, 1 ) ); } RetValue = Fxch_DivNormalize( pFxchMan->vCubeFree ); if ( RetValue == -1 ) return -1; } else { if ( pSubCube0->iLit1 > 0 ) { SC0_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube0->iCube, pSubCube0->iLit1 ); Vec_IntPush( pFxchMan->vCubeFree, SC1_Lit0 ); if ( SC0_Lit0 == Abc_LitNot( SC1_Lit0 ) ) Vec_IntPush( pFxchMan->vCubeFree, SC0_Lit1 ); else if ( SC0_Lit1 == Abc_LitNot( SC1_Lit0 ) ) Vec_IntPush( pFxchMan->vCubeFree, SC0_Lit0 ); } else { SC1_Lit1 = Fxch_ManGetLit( pFxchMan, pSubCube1->iCube, pSubCube1->iLit1 ); Vec_IntPush( pFxchMan->vCubeFree, SC0_Lit0 ); if ( SC1_Lit0 == Abc_LitNot( SC0_Lit0 ) ) Vec_IntPush( pFxchMan->vCubeFree, SC1_Lit1 ); else if ( SC1_Lit1 == Abc_LitNot( SC0_Lit0 ) ) Vec_IntPush( pFxchMan->vCubeFree, SC1_Lit0 ); } } if ( Vec_IntSize( pFxchMan->vCubeFree ) == 0 ) return -1; if ( Vec_IntSize ( pFxchMan->vCubeFree ) == 2 ) { Vec_IntSort( pFxchMan->vCubeFree, 0 ); Vec_IntWriteEntry( pFxchMan->vCubeFree, 0, Abc_Var2Lit( Vec_IntEntry( pFxchMan->vCubeFree, 0 ), 0 ) ); Vec_IntWriteEntry( pFxchMan->vCubeFree, 1, Abc_Var2Lit( Vec_IntEntry( pFxchMan->vCubeFree, 1 ), 1 ) ); } Cube0Size = Vec_IntSize( Fxch_ManGetCube( pFxchMan, pSubCube0->iCube ) ); Cube1Size = Vec_IntSize( Fxch_ManGetCube( pFxchMan, pSubCube1->iCube ) ); if ( Vec_IntSize( pFxchMan->vCubeFree ) % 2 == 0 ) { Base = Abc_MinInt( Cube0Size, Cube1Size ) -( Vec_IntSize( pFxchMan->vCubeFree ) / 2) - 1; /* 1 or 2 Lits, 1 SOP NodeID */ } else return -1; return Base; } /**Function************************************************************* Synopsis [ Add a divisor to the divisors hash table. ] Description [ This functions will try to add the divisor store in vCubeFree to the divisor hash table. If the divisor is already present in the hash table it will just increment its weight, otherwise it will add the divisor and asign an initial weight. ] SideEffects [ If the fUpdate option is set, the function will also update the divisor priority queue. ] SeeAlso [] ***********************************************************************/ int Fxch_DivAdd( Fxch_Man_t* pFxchMan, int fUpdate, int fSingleCube, int fBase ) { int iDiv = Hsh_VecManAdd( pFxchMan->pDivHash, pFxchMan->vCubeFree ); /* Verify if the divisor already exist */ if ( iDiv == Vec_FltSize( pFxchMan->vDivWeights ) ) { Vec_WecPushLevel( pFxchMan->vDivCubePairs ); /* Assign initial weight */ if ( fSingleCube ) { Vec_FltPush( pFxchMan->vDivWeights, -Vec_IntSize( pFxchMan->vCubeFree ) + 0.9 -0.001 * Fxch_ManComputeLevelDiv( pFxchMan, pFxchMan->vCubeFree ) ); } else { Vec_FltPush( pFxchMan->vDivWeights, -Vec_IntSize( pFxchMan->vCubeFree ) + 0.9 -0.0009 * Fxch_ManComputeLevelDiv( pFxchMan, pFxchMan->vCubeFree ) ); } } /* Increment weight */ if ( fSingleCube ) Vec_FltAddToEntry( pFxchMan->vDivWeights, iDiv, 1 ); else Vec_FltAddToEntry( pFxchMan->vDivWeights, iDiv, fBase + Vec_IntSize( pFxchMan->vCubeFree ) - 1 ); assert( iDiv < Vec_FltSize( pFxchMan->vDivWeights ) ); if ( fUpdate ) if ( pFxchMan->vDivPrio ) { if ( Vec_QueIsMember( pFxchMan->vDivPrio, iDiv ) ) Vec_QueUpdate( pFxchMan->vDivPrio, iDiv ); else Vec_QuePush( pFxchMan->vDivPrio, iDiv ); } return iDiv; } /**Function************************************************************* Synopsis [ Removes a divisor to the divisors hash table. ] Description [ This function don't effectively removes a divisor from the hash table (the hash table implementation don't support such operation). It only assures its existence and decrement its weight. ] SideEffects [ If the fUpdate option is set, the function will also update the divisor priority queue. ] SeeAlso [] ***********************************************************************/ int Fxch_DivRemove( Fxch_Man_t* pFxchMan, int fUpdate, int fSingleCube, int fBase ) { int iDiv = Hsh_VecManAdd( pFxchMan->pDivHash, pFxchMan->vCubeFree ); assert( iDiv < Vec_FltSize( pFxchMan->vDivWeights ) ); /* Decrement weight */ if ( fSingleCube ) Vec_FltAddToEntry( pFxchMan->vDivWeights, iDiv, -1 ); else Vec_FltAddToEntry( pFxchMan->vDivWeights, iDiv, -( fBase + Vec_IntSize( pFxchMan->vCubeFree ) - 1 ) ); if ( fUpdate ) if ( pFxchMan->vDivPrio ) { if ( Vec_QueIsMember( pFxchMan->vDivPrio, iDiv ) ) Vec_QueUpdate( pFxchMan->vDivPrio, iDiv ); } return iDiv; } /**Function************************************************************* Synopsis [ Separete the cubes in present in a divisor ] Description [ In this implementation *all* stored divsors are composed of two cubes. In order to save space and to be able to use the Vec_Int_t hash table both cubes are stored in the same vector - using a little hack to differentiate which literal belongs to each cube. This function separetes the two cubes in their own vectors so that they can be added to the cover. *Note* that this also applies to single cube divisors beacuse of the DeMorgan Law: ab = ( a! + !b )! ] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxch_DivSepareteCubes( Vec_Int_t* vDiv, Vec_Int_t* vCube0, Vec_Int_t* vCube1 ) { int* pArray; int i, Lit; Vec_IntForEachEntry( vDiv, Lit, i ) if ( Abc_LitIsCompl(Lit) ) Vec_IntPush( vCube1, Abc_Lit2Var( Lit ) ); else Vec_IntPush( vCube0, Abc_Lit2Var( Lit ) ); if ( ( Vec_IntSize( vDiv ) == 4 ) && ( Vec_IntSize( vCube0 ) == 3 ) ) { assert( Vec_IntSize( vCube1 ) == 3 ); pArray = Vec_IntArray( vCube0 ); if ( pArray[1] > pArray[2] ) ABC_SWAP( int, pArray[1], pArray[2] ); pArray = Vec_IntArray( vCube1 ); if ( pArray[1] > pArray[2] ) ABC_SWAP( int, pArray[1], pArray[2] ); } } /**Function************************************************************* Synopsis [ Removes the literals present in the divisor from their original cubes. ] Description [ This function returns the numeber of removed literals which should be equal to the size of the divisor. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxch_DivRemoveLits( Vec_Int_t* vCube0, Vec_Int_t* vCube1, Vec_Int_t* vDiv, int *fCompl ) { int i, Lit, CountP = 0, CountN = 0, Count = 0, ret = 0; Vec_IntForEachEntry( vDiv, Lit, i ) if ( Abc_LitIsCompl( Abc_Lit2Var( Lit ) ) ) CountN += Vec_IntRemove1( vCube0, Abc_Lit2Var( Lit ) ); else CountP += Vec_IntRemove1( vCube0, Abc_Lit2Var( Lit ) ); Vec_IntForEachEntry( vDiv, Lit, i ) Count += Vec_IntRemove1( vCube1, Abc_Lit2Var( Lit ) ); if ( Vec_IntSize( vDiv ) == 2 ) Vec_IntForEachEntry( vDiv, Lit, i ) { Vec_IntRemove1( vCube0, Abc_LitNot( Abc_Lit2Var( Lit ) ) ); Vec_IntRemove1( vCube1, Abc_LitNot( Abc_Lit2Var( Lit ) ) ); } ret = Count + CountP + CountN; if ( Vec_IntSize( vDiv ) == 4 ) { int Lit0 = Abc_Lit2Var( Vec_IntEntry( vDiv, 0 ) ), Lit1 = Abc_Lit2Var( Vec_IntEntry( vDiv, 1 ) ), Lit2 = Abc_Lit2Var( Vec_IntEntry( vDiv, 2 ) ), Lit3 = Abc_Lit2Var( Vec_IntEntry( vDiv, 3 ) ); if ( Lit0 == Abc_LitNot( Lit1 ) && Lit2 == Abc_LitNot( Lit3 ) && CountN == 1 ) *fCompl = 1; if ( Lit0 == Abc_LitNot( Lit1 ) && ret == 2 ) { *fCompl = 1; Vec_IntForEachEntry( vDiv, Lit, i ) ret += Vec_IntRemove1( vCube0, ( Abc_Lit2Var( Lit ) ^ (fCompl && i > 1) ) ); Vec_IntForEachEntry( vDiv, Lit, i ) ret += Vec_IntRemove1( vCube1, ( Abc_Lit2Var( Lit ) ^ (fCompl && i > 1) ) ); } } return ret; } /**Function************************************************************* Synopsis [ Print the divisor identified by iDiv. ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxch_DivPrint( Fxch_Man_t* pFxchMan, int iDiv ) { Vec_Int_t* vDiv = Hsh_VecReadEntry( pFxchMan->pDivHash, iDiv ); int i, Lit; printf( "Div %7d : ", iDiv ); printf( "Weight %12.5f ", Vec_FltEntry( pFxchMan->vDivWeights, iDiv ) ); Vec_IntForEachEntry( vDiv, Lit, i ) if ( !Abc_LitIsCompl( Lit ) ) printf( "%d(1)", Abc_Lit2Var( Lit ) ); printf( " + " ); Vec_IntForEachEntry( vDiv, Lit, i ) if ( Abc_LitIsCompl( Lit ) ) printf( "%d(2)", Abc_Lit2Var( Lit ) ); printf( " Lits =%7d ", pFxchMan->nLits ); printf( "Divs =%8d \n", Hsh_VecSize( pFxchMan->pDivHash ) ); } int Fxch_DivIsNotConstant1( Vec_Int_t* vDiv ) { int Lit0 = Abc_Lit2Var( Vec_IntEntry( vDiv, 0 ) ), Lit1 = Abc_Lit2Var( Vec_IntEntry( vDiv, 1 ) ); if ( ( Vec_IntSize( vDiv ) == 2 ) && ( Lit0 == Abc_LitNot( Lit1 ) ) ) return 0; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxch/FxchMan.c000066400000000000000000000635571300674244400232760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ FxchMan.c ] PackageName [ Fast eXtract with Cube Hashing (FXCH) ] Synopsis [ Fxch Manager implementation ] Author [ Bruno Schmitt - boschmitt at inf.ufrgs.br ] Affiliation [ UFRGS ] Date [ Ver. 1.0. Started - March 6, 2016. ] Revision [] ***********************************************************************/ #include "Fxch.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// LOCAL FUNCTIONS DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Fxch_ManSCAddRemove( Fxch_Man_t* pFxchMan, unsigned int SubCubeID, unsigned int iCube, unsigned int iLit0, unsigned int iLit1, char fAdd, char fUpdate ) { int ret = 0; if ( fAdd ) { ret = Fxch_SCHashTableInsert( pFxchMan->pSCHashTable, pFxchMan->vCubes, SubCubeID, iCube, iLit0, iLit1, fUpdate ); } else { ret = Fxch_SCHashTableRemove( pFxchMan->pSCHashTable, pFxchMan->vCubes, SubCubeID, iCube, iLit0, iLit1, fUpdate ); } return ret; } static inline int Fxch_ManDivSingleCube( Fxch_Man_t* pFxchMan, int iCube, int fAdd, int fUpdate ) { Vec_Int_t* vCube = Vec_WecEntry( pFxchMan->vCubes, iCube ); int i, k, Lit0, Lit1, fSingleCube = 1, fBase = 0; if ( Vec_IntSize( vCube ) < 2 ) return 0; Vec_IntForEachEntryStart( vCube, Lit0, i, 1) Vec_IntForEachEntryStart( vCube, Lit1, k, (i + 1) ) { int * pOutputID, nOnes, j, z; assert( Lit0 < Lit1 ); Vec_IntClear( pFxchMan->vCubeFree ); Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit0 ), 0 ) ); Vec_IntPush( pFxchMan->vCubeFree, Abc_Var2Lit( Abc_LitNot( Lit1 ), 1 ) ); pOutputID = Vec_IntEntryP( pFxchMan->vOutputID, iCube * pFxchMan->nSizeOutputID ); nOnes = 0; for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) nOnes += Fxch_CountOnes( pOutputID[j] ); if ( nOnes == 0 ) nOnes = 1; if (fAdd) { for ( z = 0; z < nOnes; z++ ) Fxch_DivAdd( pFxchMan, fUpdate, fSingleCube, fBase ); pFxchMan->nPairsS++; } else { for ( z = 0; z < nOnes; z++ ) Fxch_DivRemove( pFxchMan, fUpdate, fSingleCube, fBase ); pFxchMan->nPairsS--; } } return Vec_IntSize( vCube ) * ( Vec_IntSize( vCube ) - 1 ) / 2; } static inline void Fxch_ManDivDoubleCube( Fxch_Man_t* pFxchMan, int iCube, int fAdd, int fUpdate ) { Vec_Int_t* vLitHashKeys = pFxchMan->vLitHashKeys, * vCube = Vec_WecEntry( pFxchMan->vCubes, iCube ); int SubCubeID = 0, iLit0, Lit0; Vec_IntForEachEntryStart( vCube, Lit0, iLit0, 1) SubCubeID += Vec_IntEntry( vLitHashKeys, Lit0 ); Fxch_ManSCAddRemove( pFxchMan, SubCubeID, iCube, 0, 0, (char)fAdd, (char)fUpdate ); Vec_IntForEachEntryStart( vCube, Lit0, iLit0, 1) { /* 1 Lit remove */ SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit0 ); pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID, iCube, iLit0, 0, (char)fAdd, (char)fUpdate ); if ( Vec_IntSize( vCube ) >= 3 ) { int Lit1, iLit1; Vec_IntForEachEntryStart( vCube, Lit1, iLit1, iLit0 + 1) { /* 2 Lit remove */ SubCubeID -= Vec_IntEntry( vLitHashKeys, Lit1 ); pFxchMan->nPairsD += Fxch_ManSCAddRemove( pFxchMan, SubCubeID, iCube, iLit0, iLit1, (char)fAdd, (char)fUpdate ); SubCubeID += Vec_IntEntry( vLitHashKeys, Lit1 ); } } SubCubeID += Vec_IntEntry( vLitHashKeys, Lit0 ); } } static inline void Fxch_ManCompressCubes( Vec_Wec_t* vCubes, Vec_Int_t* vLit2Cube ) { int i, k = 0, CubeId; Vec_IntForEachEntry( vLit2Cube, CubeId, i ) if ( Vec_IntSize(Vec_WecEntry(vCubes, CubeId)) > 0 ) Vec_IntWriteEntry( vLit2Cube, k++, CubeId ); Vec_IntShrink( vLit2Cube, k ); } //////////////////////////////////////////////////////////////////////// /// PUBLIC INTERFACE /// //////////////////////////////////////////////////////////////////////// Fxch_Man_t* Fxch_ManAlloc( Vec_Wec_t* vCubes ) { Fxch_Man_t* pFxchMan = ABC_CALLOC( Fxch_Man_t, 1 ); pFxchMan->vCubes = vCubes; pFxchMan->nCubesInit = Vec_WecSize( vCubes ); pFxchMan->pDivHash = Hsh_VecManStart( 1024 ); pFxchMan->vDivWeights = Vec_FltAlloc( 1024 ); pFxchMan->vDivCubePairs = Vec_WecAlloc( 1024 ); pFxchMan->vCubeFree = Vec_IntAlloc( 4 ); pFxchMan->vDiv = Vec_IntAlloc( 4 ); pFxchMan->vCubesS = Vec_IntAlloc( 128 ); pFxchMan->vPairs = Vec_IntAlloc( 128 ); pFxchMan->vCubesToUpdate = Vec_IntAlloc( 64 ); pFxchMan->vCubesToRemove = Vec_IntAlloc( 64 ); pFxchMan->vSCC = Vec_IntAlloc( 64 ); return pFxchMan; } void Fxch_ManFree( Fxch_Man_t* pFxchMan ) { Vec_WecFree( pFxchMan->vLits ); Vec_IntFree( pFxchMan->vLitCount ); Vec_IntFree( pFxchMan->vLitHashKeys ); Hsh_VecManStop( pFxchMan->pDivHash ); Vec_FltFree( pFxchMan->vDivWeights ); Vec_QueFree( pFxchMan->vDivPrio ); Vec_WecFree( pFxchMan->vDivCubePairs ); Vec_IntFree( pFxchMan->vLevels ); Vec_IntFree( pFxchMan->vCubeFree ); Vec_IntFree( pFxchMan->vDiv ); Vec_IntFree( pFxchMan->vCubesS ); Vec_IntFree( pFxchMan->vPairs ); Vec_IntFree( pFxchMan->vCubesToUpdate ); Vec_IntFree( pFxchMan->vCubesToRemove ); Vec_IntFree( pFxchMan->vSCC ); ABC_FREE( pFxchMan ); } void Fxch_ManMapLiteralsIntoCubes( Fxch_Man_t* pFxchMan, int nVars ) { Vec_Int_t* vCube; int i, k, Lit, Count; pFxchMan->nVars = 0; pFxchMan->nLits = 0; Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i ) { assert( Vec_IntSize(vCube) > 0 ); pFxchMan->nVars = Abc_MaxInt( pFxchMan->nVars, Vec_IntEntry( vCube, 0 ) ); pFxchMan->nLits += Vec_IntSize(vCube) - 1; Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) pFxchMan->nVars = Abc_MaxInt( pFxchMan->nVars, Abc_Lit2Var( Lit ) ); } assert( pFxchMan->nVars < nVars ); pFxchMan->nVars = nVars; /* Count the number of time each literal appears on the SOP */ pFxchMan->vLitCount = Vec_IntStart( 2 * pFxchMan->nVars ); Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i ) Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) Vec_IntAddToEntry( pFxchMan->vLitCount, Lit, 1 ); /* Allocate space to the array of arrays wich maps Literals into cubes which uses them */ pFxchMan->vLits = Vec_WecStart( 2 * pFxchMan->nVars ); Vec_IntForEachEntry( pFxchMan->vLitCount, Count, Lit ) Vec_IntGrow( Vec_WecEntry( pFxchMan->vLits, Lit ), Count ); /* Maps Literals into cubes which uses them */ Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i ) Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) Vec_WecPush( pFxchMan->vLits, Lit, i ); } void Fxch_ManGenerateLitHashKeys( Fxch_Man_t* pFxchMan ) { int i; /* Generates the random number which will be used for hashing cubes */ Gia_ManRandom( 1 ); pFxchMan->vLitHashKeys = Vec_IntAlloc( ( 2 * pFxchMan->nVars ) ); for ( i = 0; i < (2 * pFxchMan->nVars); i++ ) Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF ); } void Fxch_ManSCHashTablesInit( Fxch_Man_t* pFxchMan ) { Vec_Wec_t* vCubes = pFxchMan->vCubes; Vec_Int_t* vCube; int iCube, nTotalHashed = 0; Vec_WecForEachLevel( vCubes, vCube, iCube ) { int nLits = Vec_IntSize( vCube ) - 1, nSubCubes = nLits <= 2? nLits + 1: ( nLits * nLits + nLits ) / 2; nTotalHashed += nSubCubes + 1; } pFxchMan->pSCHashTable = Fxch_SCHashTableCreate( pFxchMan, nTotalHashed ); } void Fxch_ManSCHashTablesFree( Fxch_Man_t* pFxchMan ) { Fxch_SCHashTableDelete( pFxchMan->pSCHashTable ); } void Fxch_ManDivCreate( Fxch_Man_t* pFxchMan ) { Vec_Int_t* vCube; float Weight; int fAdd = 1, fUpdate = 0, iCube; Vec_WecForEachLevel( pFxchMan->vCubes, vCube, iCube ) { Fxch_ManDivSingleCube( pFxchMan, iCube, fAdd, fUpdate ); Fxch_ManDivDoubleCube( pFxchMan, iCube, fAdd, fUpdate ); } pFxchMan->vDivPrio = Vec_QueAlloc( Vec_FltSize( pFxchMan->vDivWeights ) ); Vec_QueSetPriority( pFxchMan->vDivPrio, Vec_FltArrayP( pFxchMan->vDivWeights ) ); Vec_FltForEachEntry( pFxchMan->vDivWeights, Weight, iCube ) { if ( Weight > 0.0 ) Vec_QuePush( pFxchMan->vDivPrio, iCube ); } } /* Level Computation */ int Fxch_ManComputeLevelDiv( Fxch_Man_t* pFxchMan, Vec_Int_t* vCubeFree ) { int i, Lit, Level = 0; Vec_IntForEachEntry( vCubeFree, Lit, i ) Level = Abc_MaxInt( Level, Vec_IntEntry( pFxchMan->vLevels, Abc_Lit2Var( Abc_Lit2Var( Lit ) ) ) ); return Abc_MinInt( Level, 800 ); } int Fxch_ManComputeLevelCube( Fxch_Man_t* pFxchMan, Vec_Int_t * vCube ) { int k, Lit, Level = 0; Vec_IntForEachEntryStart( vCube, Lit, k, 1 ) Level = Abc_MaxInt( Level, Vec_IntEntry( pFxchMan->vLevels, Abc_Lit2Var( Lit ) ) ); return Level; } void Fxch_ManComputeLevel( Fxch_Man_t* pFxchMan ) { Vec_Int_t* vCube; int i, iVar, iFirst = 0; iVar = Vec_IntEntry( Vec_WecEntry( pFxchMan->vCubes, 0 ), 0 ); pFxchMan->vLevels = Vec_IntStart( pFxchMan->nVars ); Vec_WecForEachLevel( pFxchMan->vCubes, vCube, i ) { if ( iVar != Vec_IntEntry( vCube, 0 ) ) { Vec_IntAddToEntry( pFxchMan->vLevels, iVar, i - iFirst ); iVar = Vec_IntEntry( vCube, 0 ); iFirst = i; } Vec_IntUpdateEntry( pFxchMan->vLevels, iVar, Fxch_ManComputeLevelCube( pFxchMan, vCube ) ); } } /* Extract divisor from single-cubes */ static inline void Fxch_ManExtractDivFromCube( Fxch_Man_t* pFxchMan, const int Lit0, const int Lit1, const int iVarNew ) { int i, iCube0; Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ); Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i ) { int RetValue; Vec_Int_t* vCube0; vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ); RetValue = Vec_IntRemove1( vCube0, Abc_LitNot( Lit0 ) ); RetValue += Vec_IntRemove1( vCube0, Abc_LitNot( Lit1 ) ); assert( RetValue == 2 ); Vec_IntPush( vCube0, Abc_Var2Lit( iVarNew, 0 ) ); Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 ); pFxchMan->nLits--; } } /* Extract divisor from cube pairs */ static inline void Fxch_ManExtractDivFromCubePairs( Fxch_Man_t* pFxchMan, const int iVarNew ) { /* For each pair (Ci, Cj) */ int iCube0, iCube1, i; Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i ) { int j, Lit, RetValue, fCompl = 0; int * pOutputID0, * pOutputID1; Vec_Int_t* vCube = NULL, * vCube0 = Fxch_ManGetCube( pFxchMan, iCube0 ), * vCube1 = Fxch_ManGetCube( pFxchMan, iCube1 ), * vCube0Copy = Vec_IntDup( vCube0 ), * vCube1Copy = Vec_IntDup( vCube1 ); RetValue = Fxch_DivRemoveLits( vCube0Copy, vCube1Copy, pFxchMan->vDiv, &fCompl ); assert( RetValue == Vec_IntSize( pFxchMan->vDiv ) ); pFxchMan->nLits -= Vec_IntSize( pFxchMan->vDiv ) + Vec_IntSize( vCube1 ) - 2; /* Identify type of Extraction */ pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID ); pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID ); RetValue = 1; for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ ) RetValue = ( pOutputID0[j] == pOutputID1[j] ); /* Exact Extractraion */ if ( RetValue ) { Vec_IntClear( vCube0 ); Vec_IntAppend( vCube0, vCube0Copy ); vCube = vCube0; Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 ); Vec_IntClear( vCube1 ); /* Update Lit -> Cube mapping */ Vec_IntForEachEntry( pFxchMan->vDiv, Lit, j ) { Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_Lit2Var( Lit ) ), Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); Vec_IntRemove( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Abc_Lit2Var( Lit ) ) ), Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); } } /* Unexact Extraction */ else { for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) pFxchMan->pTempOutputID[j] = ( pOutputID0[j] & pOutputID1[j] ); /* Create new cube */ vCube = Vec_WecPushLevel( pFxchMan->vCubes ); Vec_IntAppend( vCube, vCube0Copy ); Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID ); Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); /* Update Lit -> Cube mapping */ Vec_IntForEachEntryStart( vCube, Lit, j, 1 ) Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); /*********************************************************/ RetValue = 0; for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) { pFxchMan->pTempOutputID[j] = pOutputID0[j]; RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) ); pOutputID0[j] &= ~( pOutputID1[j] ); } if ( RetValue != 0 ) Vec_IntPush( pFxchMan->vCubesToUpdate, iCube0 ); else Vec_IntClear( vCube0 ); /*********************************************************/ RetValue = 0; for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) { RetValue |= ( pOutputID1[j] & ~( pFxchMan->pTempOutputID[j] ) ); pOutputID1[j] &= ~( pFxchMan->pTempOutputID[j] ); } if ( RetValue != 0 ) Vec_IntPush( pFxchMan->vCubesToUpdate, iCube1 ); else Vec_IntClear( vCube1 ); } Vec_IntFree( vCube0Copy ); Vec_IntFree( vCube1Copy ); if ( iVarNew ) { Vec_Int_t* vLitP = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 2 ), * vLitN = Vec_WecEntry( pFxchMan->vLits, Vec_WecSize( pFxchMan->vLits ) - 1 ); assert( vCube ); if ( Vec_IntSize( pFxchMan->vDiv ) == 2 || fCompl ) { Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 1 ) ); Vec_IntPush( vLitN, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); Vec_IntSort( vLitN, 0 ); } else { Vec_IntPush( vCube, Abc_Var2Lit( iVarNew, 0 ) ); Vec_IntPush( vLitP, Vec_WecLevelId( pFxchMan->vCubes, vCube ) ); Vec_IntSort( vLitP, 0 ); } } } return; } static inline int Fxch_ManCreateCube( Fxch_Man_t* pFxchMan, int Lit0, int Lit1 ) { int Level, iVarNew, j; Vec_Int_t* vCube0, * vCube1; /* Create a new variable */ iVarNew = pFxchMan->nVars; pFxchMan->nVars++; /* Clear temporary outputID vector */ for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) pFxchMan->pTempOutputID[j] = 0; /* Create new Lit hash keys */ Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF ); Vec_IntPush( pFxchMan->vLitHashKeys, Gia_ManRandom(0) & 0x3FFFFFF ); /* Create new Cube */ vCube0 = Vec_WecPushLevel( pFxchMan->vCubes ); Vec_IntPush( vCube0, iVarNew ); Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID ); if ( Vec_IntSize( pFxchMan->vDiv ) == 2 ) { if ( Lit0 > Lit1 ) ABC_SWAP(int, Lit0, Lit1); Vec_IntPush( vCube0, Abc_LitNot( Lit0 ) ); Vec_IntPush( vCube0, Abc_LitNot( Lit1 ) ); Level = 1 + Fxch_ManComputeLevelCube( pFxchMan, vCube0 ); } else { int i; int Lit; vCube1 = Vec_WecPushLevel( pFxchMan->vCubes ); Vec_IntPush( vCube1, iVarNew ); Vec_IntPushArray( pFxchMan->vOutputID, pFxchMan->pTempOutputID, pFxchMan->nSizeOutputID ); vCube0 = Fxch_ManGetCube( pFxchMan, Vec_WecSize( pFxchMan->vCubes ) - 2 ); Fxch_DivSepareteCubes( pFxchMan->vDiv, vCube0, vCube1 ); Level = 2 + Abc_MaxInt( Fxch_ManComputeLevelCube( pFxchMan, vCube0 ), Fxch_ManComputeLevelCube( pFxchMan, vCube1 ) ); Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); Vec_IntPush( pFxchMan->vCubesToUpdate, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) ); /* Update Lit -> Cube mapping */ Vec_IntForEachEntryStart( vCube0, Lit, i, 1 ) Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube0 ) ); Vec_IntForEachEntryStart( vCube1, Lit, i, 1 ) Vec_WecPush( pFxchMan->vLits, Lit, Vec_WecLevelId( pFxchMan->vCubes, vCube1 ) ); } assert( Vec_IntSize( pFxchMan->vLevels ) == iVarNew ); Vec_IntPush( pFxchMan->vLevels, Level ); pFxchMan->nLits += Vec_IntSize( pFxchMan->vDiv ); /* Create new literals */ Vec_WecPushLevel( pFxchMan->vLits ); Vec_WecPushLevel( pFxchMan->vLits ); return iVarNew; } void Fxch_ManUpdate( Fxch_Man_t* pFxchMan, int iDiv ) { int i, iCube0, iCube1, Lit0 = -1, Lit1 = -1, iVarNew; Vec_Int_t* vCube0, * vCube1, * vDivCubePairs; /* Get the selected candidate (divisor) */ Vec_IntClear( pFxchMan->vDiv ); Vec_IntAppend( pFxchMan->vDiv, Hsh_VecReadEntry( pFxchMan->pDivHash, iDiv ) ); /* Find cubes associated with the divisor */ Vec_IntClear( pFxchMan->vCubesS ); if ( Vec_IntSize( pFxchMan->vDiv ) == 2 ) { Lit0 = Abc_Lit2Var( Vec_IntEntry( pFxchMan->vDiv, 0 ) ); Lit1 = Abc_Lit2Var( Vec_IntEntry( pFxchMan->vDiv, 1 ) ); assert( Lit0 >= 0 && Lit1 >= 0 ); Fxch_ManCompressCubes( pFxchMan->vCubes, Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit0 ) ) ); Fxch_ManCompressCubes( pFxchMan->vCubes, Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit1 ) ) ); Vec_IntTwoRemoveCommon( Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit0 ) ), Vec_WecEntry( pFxchMan->vLits, Abc_LitNot( Lit1 ) ), pFxchMan->vCubesS ); } /* Find pairs associated with the divisor */ Vec_IntClear( pFxchMan->vPairs ); vDivCubePairs = Vec_WecEntry( pFxchMan->vDivCubePairs, iDiv ); Vec_IntAppend( pFxchMan->vPairs, vDivCubePairs ); Vec_IntErase( vDivCubePairs ); Vec_IntForEachEntryDouble( pFxchMan->vPairs, iCube0, iCube1, i ) { assert( Fxch_ManGetLit( pFxchMan, iCube0, 0) == Fxch_ManGetLit( pFxchMan, iCube1, 0) ); if (iCube0 > iCube1) { Vec_IntSetEntry( pFxchMan->vPairs, i, iCube1); Vec_IntSetEntry( pFxchMan->vPairs, i+1, iCube0); } } Vec_IntUniqifyPairs( pFxchMan->vPairs ); assert( Vec_IntSize( pFxchMan->vPairs ) % 2 == 0 ); /* subtract cost of single-cube divisors */ Vec_IntForEachEntry( pFxchMan->vCubesS, iCube0, i ) { Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1); if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); } Vec_IntForEachEntry( pFxchMan->vPairs, iCube0, i ) { Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1); if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); } Vec_IntClear( pFxchMan->vCubesToUpdate ); if ( Fxch_DivIsNotConstant1( pFxchMan->vDiv ) ) { iVarNew = Fxch_ManCreateCube( pFxchMan, Lit0, Lit1 ); Fxch_ManExtractDivFromCube( pFxchMan, Lit0, Lit1, iVarNew ); Fxch_ManExtractDivFromCubePairs( pFxchMan, iVarNew ); } else Fxch_ManExtractDivFromCubePairs( pFxchMan, 0 ); assert( Vec_IntSize( pFxchMan->vCubesToUpdate ) ); /* Add cost */ Vec_IntForEachEntry( pFxchMan->vCubesToUpdate, iCube0, i ) { Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); if ( Vec_WecEntryEntry( pFxchMan->vCubes, iCube0, 0 ) == 0 ) Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); } /* Deal with SCC */ if ( Vec_IntSize( pFxchMan->vSCC ) ) { Vec_IntUniqifyPairs( pFxchMan->vSCC ); assert( Vec_IntSize( pFxchMan->vSCC ) % 2 == 0 ); Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i ) { int j, RetValue = 1; int* pOutputID0 = Vec_IntEntryP( pFxchMan->vOutputID, iCube0 * pFxchMan->nSizeOutputID ); int* pOutputID1 = Vec_IntEntryP( pFxchMan->vOutputID, iCube1 * pFxchMan->nSizeOutputID ); vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 ); vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 ); if ( !Vec_WecIntHasMark( vCube0 ) ) { Fxch_ManDivSingleCube( pFxchMan, iCube0, 0, 1 ); Fxch_ManDivDoubleCube( pFxchMan, iCube0, 0, 1 ); Vec_WecIntSetMark( vCube0 ); } if ( !Vec_WecIntHasMark( vCube1 ) ) { Fxch_ManDivSingleCube( pFxchMan, iCube1, 0, 1 ); Fxch_ManDivDoubleCube( pFxchMan, iCube1, 0, 1 ); Vec_WecIntSetMark( vCube1 ); } if ( Vec_IntSize( vCube0 ) == Vec_IntSize( vCube1 ) ) { for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) { pOutputID1[j] |= pOutputID0[j]; pOutputID0[j] = 0; } Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); Vec_WecIntXorMark( vCube0 ); continue; } for ( j = 0; j < pFxchMan->nSizeOutputID && RetValue; j++ ) RetValue = ( pOutputID0[j] == pOutputID1[j] ); if ( RetValue ) { Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); Vec_WecIntXorMark( vCube0 ); } else { RetValue = 0; for ( j = 0; j < pFxchMan->nSizeOutputID; j++ ) { RetValue |= ( pOutputID0[j] & ~( pOutputID1[j] ) ); pOutputID0[j] &= ~( pOutputID1[j] ); } if ( RetValue == 0 ) { Vec_IntClear( Vec_WecEntry( pFxchMan->vCubes, iCube0 ) ); Vec_WecIntXorMark( vCube0 ); } } } Vec_IntForEachEntryDouble( pFxchMan->vSCC, iCube0, iCube1, i ) { vCube0 = Vec_WecEntry( pFxchMan->vCubes, iCube0 ); vCube1 = Vec_WecEntry( pFxchMan->vCubes, iCube1 ); if ( Vec_WecIntHasMark( vCube0 ) ) { Fxch_ManDivSingleCube( pFxchMan, iCube0, 1, 1 ); Fxch_ManDivDoubleCube( pFxchMan, iCube0, 1, 1 ); Vec_WecIntXorMark( vCube0 ); } if ( Vec_WecIntHasMark( vCube1 ) ) { Fxch_ManDivSingleCube( pFxchMan, iCube1, 1, 1 ); Fxch_ManDivDoubleCube( pFxchMan, iCube1, 1, 1 ); Vec_WecIntXorMark( vCube1 ); } } Vec_IntClear( pFxchMan->vSCC ); } pFxchMan->nExtDivs++; } /* Print */ void Fxch_ManPrintDivs( Fxch_Man_t* pFxchMan ) { int iDiv; for ( iDiv = 0; iDiv < Vec_FltSize( pFxchMan->vDivWeights ); iDiv++ ) Fxch_DivPrint( pFxchMan, iDiv ); } void Fxch_ManPrintStats( Fxch_Man_t* pFxchMan ) { printf( "Cubes =%8d ", Vec_WecSizeUsed( pFxchMan->vCubes ) ); printf( "Lits =%8d ", Vec_WecSizeUsed( pFxchMan->vLits ) ); printf( "Divs =%8d ", Hsh_VecSize( pFxchMan->pDivHash ) ); printf( "Divs+ =%8d ", Vec_QueSize( pFxchMan->vDivPrio ) ); printf( "Extr =%7d \n", pFxchMan->nExtDivs ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxch/FxchSCHashTable.c000066400000000000000000000300131300674244400246210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ FxchSCHashTable.c ] PackageName [ Fast eXtract with Cube Hashing (FXCH) ] Synopsis [ Sub-cubes hash table implementation ] Author [ Bruno Schmitt - boschmitt at inf.ufrgs.br ] Affiliation [ UFRGS ] Date [ Ver. 1.0. Started - March 6, 2016. ] Revision [] ***********************************************************************/ #include "Fxch.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline void MurmurHash3_x86_32 ( const void* key, int len, uint32_t seed, void* out ) { const uint8_t* data = (const uint8_t*)key; const int nblocks = len / 4; uint32_t h1 = seed; const uint32_t c1 = 0xcc9e2d51; const uint32_t c2 = 0x1b873593; const uint8_t * tail; uint32_t k1; //---------- // body const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); int i; for(i = -nblocks; i; i++) { uint32_t k1 = blocks[i]; k1 *= c1; k1 = (k1 << 15) | (k1 >> (32 - 15)); k1 *= c2; h1 ^= k1; h1 = (h1 << 13) | (h1 >> (32 - 13)); h1 = h1*5+0xe6546b64; } //---------- // tail tail = (const uint8_t*)(data + nblocks*4); k1 = 0; switch(len & 3) { case 3: k1 ^= tail[2] << 16; case 2: k1 ^= tail[1] << 8; case 1: k1 ^= tail[0]; k1 *= c1; k1 = (k1 << 15) | (k1 >> (32 - 15)); k1 *= c2; h1 ^= k1; }; //---------- // finalization h1 ^= len; h1 ^= h1 >> 16; h1 *= 0x85ebca6b; h1 ^= h1 >> 13; h1 *= 0xc2b2ae35; h1 ^= h1 >> 16; *(uint32_t*)out = h1; } Fxch_SCHashTable_t* Fxch_SCHashTableCreate( Fxch_Man_t* pFxchMan, int nEntries ) { Fxch_SCHashTable_t* pSCHashTable = ABC_CALLOC( Fxch_SCHashTable_t, 1 ); int nBits = Abc_Base2Log( nEntries + 1 ); pSCHashTable->pFxchMan = pFxchMan; pSCHashTable->SizeMask = (1 << nBits) - 1; pSCHashTable->pBins = ABC_CALLOC( Fxch_SCHashTable_Entry_t, pSCHashTable->SizeMask + 1 ); return pSCHashTable; } void Fxch_SCHashTableDelete( Fxch_SCHashTable_t* pSCHashTable ) { Vec_IntErase( &pSCHashTable->vSubCube0 ); Vec_IntErase( &pSCHashTable->vSubCube1 ); ABC_FREE( pSCHashTable->pBins ); ABC_FREE( pSCHashTable ); } static inline Fxch_SCHashTable_Entry_t* Fxch_SCHashTableBin( Fxch_SCHashTable_t* pSCHashTable, unsigned int SubCubeID ) { return pSCHashTable->pBins + (SubCubeID & pSCHashTable->SizeMask); } static inline int Fxch_SCHashTableEntryCompare( Fxch_SCHashTable_t* pSCHashTable, Vec_Wec_t* vCubes, Fxch_SubCube_t* pSCData0, Fxch_SubCube_t* pSCData1 ) { Vec_Int_t* vCube0 = Vec_WecEntry( vCubes, pSCData0->iCube ), * vCube1 = Vec_WecEntry( vCubes, pSCData1->iCube ); int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pSCData0->iCube * pSCHashTable->pFxchMan->nSizeOutputID ), * pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pSCData1->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); int i, Result = 0; if ( !Vec_IntSize( vCube0 ) || !Vec_IntSize( vCube1 ) || Vec_IntEntry( vCube0, 0 ) != Vec_IntEntry( vCube1, 0 ) || pSCData0->Id != pSCData1->Id ) return 0; for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID && Result == 0; i++ ) Result = ( pOutputID0[i] & pOutputID1[i] ); if ( Result == 0 ) return 0; Vec_IntClear( &pSCHashTable->vSubCube0 ); Vec_IntClear( &pSCHashTable->vSubCube1 ); if ( pSCData0->iLit1 > 0 && pSCData1->iLit1 > 0 && ( Vec_IntEntry( vCube0, pSCData0->iLit0 ) == Vec_IntEntry( vCube1, pSCData1->iLit0 ) || Vec_IntEntry( vCube0, pSCData0->iLit0 ) == Vec_IntEntry( vCube1, pSCData1->iLit1 ) || Vec_IntEntry( vCube0, pSCData0->iLit1 ) == Vec_IntEntry( vCube1, pSCData1->iLit0 ) || Vec_IntEntry( vCube0, pSCData0->iLit1 ) == Vec_IntEntry( vCube1, pSCData1->iLit1 ) ) ) return 0; if ( pSCData0->iLit0 > 0 ) Vec_IntAppendSkip( &pSCHashTable->vSubCube0, vCube0, pSCData0->iLit0 ); else Vec_IntAppend( &pSCHashTable->vSubCube0, vCube0 ); if ( pSCData1->iLit0 > 0 ) Vec_IntAppendSkip( &pSCHashTable->vSubCube1, vCube1, pSCData1->iLit0 ); else Vec_IntAppend( &pSCHashTable->vSubCube1, vCube1 ); if ( pSCData0->iLit1 > 0) Vec_IntDrop( &pSCHashTable->vSubCube0, pSCData0->iLit0 < pSCData0->iLit1 ? pSCData0->iLit1 - 1 : pSCData0->iLit1 ); if ( pSCData1->iLit1 > 0 ) Vec_IntDrop( &pSCHashTable->vSubCube1, pSCData1->iLit0 < pSCData1->iLit1 ? pSCData1->iLit1 - 1 : pSCData1->iLit1 ); return Vec_IntEqual( &pSCHashTable->vSubCube0, &pSCHashTable->vSubCube1 ); } int Fxch_SCHashTableInsert( Fxch_SCHashTable_t* pSCHashTable, Vec_Wec_t* vCubes, uint32_t SubCubeID, uint32_t iCube, uint32_t iLit0, uint32_t iLit1, char fUpdate ) { int iNewEntry; int Pairs = 0; uint32_t BinID; Fxch_SCHashTable_Entry_t* pBin; Fxch_SubCube_t* pNewEntry; int iEntry; MurmurHash3_x86_32( ( void* ) &SubCubeID, sizeof( int ), 0x9747b28c, &BinID); pBin = Fxch_SCHashTableBin( pSCHashTable, BinID ); if ( pBin->vSCData == NULL ) { pBin->vSCData = ABC_CALLOC( Fxch_SubCube_t, 16 ); pBin->Size = 0; pBin->Cap = 16; } else if ( pBin->Size == pBin->Cap ) { pBin->Cap = 2 * pBin->Size; pBin->vSCData = ABC_REALLOC( Fxch_SubCube_t, pBin->vSCData, pBin->Cap ); } iNewEntry = pBin->Size++; pBin->vSCData[iNewEntry].Id = SubCubeID; pBin->vSCData[iNewEntry].iCube = iCube; pBin->vSCData[iNewEntry].iLit0 = iLit0; pBin->vSCData[iNewEntry].iLit1 = iLit1; pSCHashTable->nEntries++; if ( pBin->Size == 1 ) return 0; pNewEntry = &( pBin->vSCData[iNewEntry] ); for ( iEntry = 0; iEntry < (int)pBin->Size - 1; iEntry++ ) { Fxch_SubCube_t* pEntry = &( pBin->vSCData[iEntry] ); int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); int* pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pNewEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); int Result = 0; int Base; int iNewDiv = -1, i, z; if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, pEntry, pNewEntry ) ) continue; if ( ( pEntry->iLit0 == 0 ) || ( pNewEntry->iLit0 == 0 ) ) { Vec_Int_t* vCube0 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pEntry->iCube ), * vCube1 = Fxch_ManGetCube( pSCHashTable->pFxchMan, pNewEntry->iCube ); if ( Vec_IntSize( vCube0 ) > Vec_IntSize( vCube1 ) ) { Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->iCube ); Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->iCube ); } else { Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pNewEntry->iCube ); Vec_IntPush( pSCHashTable->pFxchMan->vSCC, pEntry->iCube ); } continue; } Base = Fxch_DivCreate( pSCHashTable->pFxchMan, pEntry, pNewEntry ); if ( Base < 0 ) continue; for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID; i++ ) Result += Fxch_CountOnes( pOutputID0[i] & pOutputID1[i] ); for ( z = 0; z < Result; z++ ) iNewDiv = Fxch_DivAdd( pSCHashTable->pFxchMan, fUpdate, 0, Base ); Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pEntry->iCube ); Vec_WecPush( pSCHashTable->pFxchMan->vDivCubePairs, iNewDiv, pNewEntry->iCube ); Pairs++; } return Pairs; } int Fxch_SCHashTableRemove( Fxch_SCHashTable_t* pSCHashTable, Vec_Wec_t* vCubes, uint32_t SubCubeID, uint32_t iCube, uint32_t iLit0, uint32_t iLit1, char fUpdate ) { int iEntry; int Pairs = 0; uint32_t BinID; Fxch_SCHashTable_Entry_t* pBin; Fxch_SubCube_t* pEntry; int idx; MurmurHash3_x86_32( ( void* ) &SubCubeID, sizeof( int ), 0x9747b28c, &BinID); pBin = Fxch_SCHashTableBin( pSCHashTable, BinID ); if ( pBin->Size == 1 ) { pBin->Size = 0; return 0; } for ( iEntry = 0; iEntry < (int)pBin->Size; iEntry++ ) if ( pBin->vSCData[iEntry].iCube == iCube ) break; assert( ( iEntry != (int)pBin->Size ) && ( pBin->Size != 0 ) ); pEntry = &( pBin->vSCData[iEntry] ); for ( idx = 0; idx < (int)pBin->Size; idx++ ) if ( idx != iEntry ) { int Base, iDiv = -1; int i, z, iCube0, iCube1; Fxch_SubCube_t* pNextEntry = &( pBin->vSCData[idx] ); Vec_Int_t* vDivCubePairs; int* pOutputID0 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); int* pOutputID1 = Vec_IntEntryP( pSCHashTable->pFxchMan->vOutputID, pNextEntry->iCube * pSCHashTable->pFxchMan->nSizeOutputID ); int Result = 0; if ( !Fxch_SCHashTableEntryCompare( pSCHashTable, vCubes, pEntry, pNextEntry ) || pEntry->iLit0 == 0 || pNextEntry->iLit0 == 0 ) continue; Base = Fxch_DivCreate( pSCHashTable->pFxchMan, pNextEntry, pEntry ); if ( Base < 0 ) continue; for ( i = 0; i < pSCHashTable->pFxchMan->nSizeOutputID; i++ ) Result += Fxch_CountOnes( pOutputID0[i] & pOutputID1[i] ); for ( z = 0; z < Result; z++ ) iDiv = Fxch_DivRemove( pSCHashTable->pFxchMan, fUpdate, 0, Base ); vDivCubePairs = Vec_WecEntry( pSCHashTable->pFxchMan->vDivCubePairs, iDiv ); Vec_IntForEachEntryDouble( vDivCubePairs, iCube0, iCube1, i ) if ( ( iCube0 == (int)pNextEntry->iCube && iCube1 == (int)pEntry->iCube ) || ( iCube0 == (int)pEntry->iCube && iCube1 == (int)pNextEntry->iCube ) ) { Vec_IntDrop( vDivCubePairs, i+1 ); Vec_IntDrop( vDivCubePairs, i ); } if ( Vec_IntSize( vDivCubePairs ) == 0 ) Vec_IntErase( vDivCubePairs ); Pairs++; } memmove(pBin->vSCData + iEntry, pBin->vSCData + iEntry + 1, (pBin->Size - iEntry - 1) * sizeof(*pBin->vSCData)); pBin->Size -= 1; return Pairs; } unsigned int Fxch_SCHashTableMemory( Fxch_SCHashTable_t* pHashTable ) { unsigned int Memory = sizeof ( Fxch_SCHashTable_t ); Memory += sizeof( Fxch_SubCube_t ) * ( pHashTable->SizeMask + 1 ); return Memory; } void Fxch_SCHashTablePrint( Fxch_SCHashTable_t* pHashTable ) { int Memory; printf( "SubCube Hash Table at %p\n", ( void* )pHashTable ); printf("%20s %20s\n", "nEntries", "Memory Usage (MB)" ); Memory = Fxch_SCHashTableMemory( pHashTable ); printf("%20d %18.2f\n", pHashTable->nEntries, ( ( double ) Memory / 1048576 ) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxch/module.make000066400000000000000000000001671300674244400237160ustar00rootroot00000000000000SRC += src/opt/fxch/Fxch.c \ src/opt/fxch/FxchDiv.c \ src/opt/fxch/FxchMan.c \ src/opt/fxch/FxchSCHashTable.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/000077500000000000000000000000001300674244400214405ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxu.c000066400000000000000000000174471300674244400224230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxu.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [The entrance into the fast extract module.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxu.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" #include "fxu.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*===== fxuCreate.c ====================================================*/ extern Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ); extern void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData ); static int s_MemoryTotal; static int s_MemoryPeak; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs fast_extract on a set of covers.] Description [All the covers are given in the array p->vSops. The resulting covers are returned in the array p->vSopsNew. The entries in these arrays correspond to objects in the network. The entries corresponding to the PI and objects with trivial covers are NULL. The number of extracted covers (not exceeding p->nNodesExt) is returned. Two other things are important for the correct operation of this procedure: (1) The input covers do not have duplicated fanins and are SCC-free. (2) The fanins array contains the numbers of the fanin objects.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_FastExtract( Fxu_Data_t * pData ) { int fScrollLines = 0; Fxu_Matrix * p; Fxu_Single * pSingle; Fxu_Double * pDouble; int Weight1, Weight2, Weight3; int Counter = 0; s_MemoryTotal = 0; s_MemoryPeak = 0; // create the matrix p = Fxu_CreateMatrix( pData ); if ( p == NULL ) return -1; // if ( pData->fVerbose ) // printf( "Memory usage after construction: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak ); //Fxu_MatrixPrint( NULL, p ); if ( pData->fOnlyS ) { pData->nNodesNew = 0; do { Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); if ( pData->fVerbose ) printf( "Div %5d : Best single = %5d.%s", Counter++, Weight1, fScrollLines?"\n":"\r" ); if ( Weight1 > pData->WeightMin || (Weight1 == 0 && pData->fUse0) ) Fxu_UpdateSingle( p ); else break; } while ( ++pData->nNodesNew < pData->nNodesExt ); } else if ( pData->fOnlyD ) { pData->nNodesNew = 0; do { Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); if ( pData->fVerbose ) printf( "Div %5d : Best double = %5d.%s", Counter++, Weight2, fScrollLines?"\n":"\r" ); if ( Weight2 > pData->WeightMin || (Weight2 == 0 && pData->fUse0) ) Fxu_UpdateDouble( p ); else break; } while ( ++pData->nNodesNew < pData->nNodesExt ); } else if ( !pData->fUseCompl ) { pData->nNodesNew = 0; do { Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); if ( pData->fVerbose ) printf( "Div %5d : Best double = %5d. Best single = %5d.%s", Counter++, Weight2, Weight1, fScrollLines?"\n":"\r" ); //Fxu_Select( p, &pSingle, &pDouble ); if ( Weight1 >= Weight2 ) { if ( Weight1 > pData->WeightMin || (Weight1 == 0 && pData->fUse0) ) Fxu_UpdateSingle( p ); else break; } else { if ( Weight2 > pData->WeightMin || (Weight2 == 0 && pData->fUse0) ) Fxu_UpdateDouble( p ); else break; } } while ( ++pData->nNodesNew < pData->nNodesExt ); } else { // use the complement pData->nNodesNew = 0; do { Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); // select the best single and double Weight3 = Fxu_Select( p, &pSingle, &pDouble ); if ( pData->fVerbose ) printf( "Div %5d : Best double = %5d. Best single = %5d. Best complement = %5d.%s", Counter++, Weight2, Weight1, Weight3, fScrollLines?"\n":"\r" ); if ( Weight3 > pData->WeightMin || (Weight3 == 0 && pData->fUse0) ) Fxu_Update( p, pSingle, pDouble ); else break; } while ( ++pData->nNodesNew < pData->nNodesExt ); } if ( pData->fVerbose ) printf( "Total single = %3d. Total double = %3d. Total compl = %3d. \n", p->nDivs1, p->nDivs2, p->nDivs3 ); // create the new covers if ( pData->nNodesNew ) Fxu_CreateCovers( p, pData ); Fxu_MatrixDelete( p ); // printf( "Memory usage after deallocation: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak ); if ( pData->nNodesNew == pData->nNodesExt ) printf( "Warning: The limit on the number of extracted divisors has been reached.\n" ); return pData->nNodesNew; } /**Function************************************************************* Synopsis [Unmarks the cubes in the ring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p ) { Fxu_Cube * pCube, * pCube2; // unmark the cubes Fxu_MatrixForEachCubeInRingSafe( p, pCube, pCube2 ) pCube->pOrder = NULL; Fxu_MatrixRingCubesReset( p ); } /**Function************************************************************* Synopsis [Unmarks the vars in the ring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p ) { Fxu_Var * pVar, * pVar2; // unmark the vars Fxu_MatrixForEachVarInRingSafe( p, pVar, pVar2 ) pVar->pOrder = NULL; Fxu_MatrixRingVarsReset( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes ) { s_MemoryTotal += nBytes; if ( s_MemoryPeak < s_MemoryTotal ) s_MemoryPeak = s_MemoryTotal; // return ABC_ALLOC( char, nBytes ); return Extra_MmFixedEntryFetch( p->pMemMan ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes ) { s_MemoryTotal -= nBytes; // ABC_FREE( pItem ); Extra_MmFixedEntryRecycle( p->pMemMan, pItem ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxu.h000066400000000000000000000077051300674244400224240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxu.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [External declarations of fast extract for unate covers.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxu.h,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__fxu__fxu_h #define ABC__opt__fxu__fxu_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/vec/vec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct FxuDataStruct Fxu_Data_t; // structure for the FX input/output data struct FxuDataStruct { // user specified parameters int fOnlyS; // set to 1 to have only single-cube divs int fOnlyD; // set to 1 to have only double-cube divs int fUse0; // set to 1 to have 0-weight also extracted int fUseCompl; // set to 1 to have complement taken into account int fVerbose; // set to 1 to have verbose output int fVeryVerbose; // set to 1 to have more verbose output int nNodesExt; // the number of divisors to extract int nSingleMax; // the max number of single-cube divisors to consider int nPairsMax; // the max number of double-cube divisors to consider int WeightMin; // the min weight of a divisor to extract int LitCountMax; // the max literal count of a divisor to consider int fCanonDivs; // use only canonical divisors (AND/XOR/MUX) // the input information Vec_Ptr_t * vSops; // the SOPs for each node in the network Vec_Ptr_t * vFanins; // the fanins of each node in the network // output information Vec_Ptr_t * vSopsNew; // the SOPs for each node in the network after extraction Vec_Ptr_t * vFaninsNew; // the fanins of each node in the network after extraction // the SOP manager Mem_Flex_t * pManSop; // statistics int nNodesOld; // the old number of nodes int nNodesNew; // the number of divisors actually extracted }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*===== fxu.c ==========================================================*/ extern void Abc_NtkSetDefaultFxParams( Fxu_Data_t * p ); extern int Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); extern void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuCreate.c000066400000000000000000000371541300674244400235440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuCreate.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Create matrix from covers and covers from matrix.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuCreate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" #include "fxu.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder ); static int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY ); static void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext ); static Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode ); static int * s_pLits; extern int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the sparse matrix from the array of SOPs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) { Fxu_Matrix * p; Fxu_Var * pVar; Fxu_Cube * pCubeFirst, * pCubeNew; Fxu_Cube * pCube1, * pCube2; Vec_Int_t * vFanins; char * pSopCover; char * pSopCube; int * pOrder, nBitsMax; int i, v, c; int nCubesTotal; int nPairsTotal; int nPairsStore; int nCubes; int iCube, iPair; int nFanins; // collect all sorts of statistics nCubesTotal = 0; nPairsTotal = 0; nPairsStore = 0; nBitsMax = -1; for ( i = 0; i < pData->nNodesOld; i++ ) if ( (pSopCover = (char *)pData->vSops->pArray[i]) ) { nCubes = Abc_SopGetCubeNum( pSopCover ); nFanins = Abc_SopGetVarNum( pSopCover ); assert( nFanins > 1 && nCubes > 0 ); nCubesTotal += nCubes; nPairsTotal += nCubes * (nCubes - 1) / 2; nPairsStore += nCubes * nCubes; if ( nBitsMax < nFanins ) nBitsMax = nFanins; } if ( nBitsMax <= 0 ) { printf( "The current network does not have SOPs to perform extraction.\n" ); return NULL; } if ( nPairsStore > 50000000 ) { printf( "The problem is too large to be solved by \"fxu\" (%d cubes and %d cube pairs)\n", nCubesTotal, nPairsStore ); return NULL; } // start the matrix p = Fxu_MatrixAllocate(); // create the column labels p->ppVars = ABC_ALLOC( Fxu_Var *, 2 * (pData->nNodesOld + pData->nNodesExt) ); for ( i = 0; i < 2 * pData->nNodesOld; i++ ) p->ppVars[i] = Fxu_MatrixAddVar( p ); // allocate storage for all cube pairs at once p->pppPairs = ABC_ALLOC( Fxu_Pair **, nCubesTotal + 100 ); p->ppPairs = ABC_ALLOC( Fxu_Pair *, nPairsStore + 100 ); memset( p->ppPairs, 0, sizeof(Fxu_Pair *) * nPairsStore ); iCube = 0; iPair = 0; for ( i = 0; i < pData->nNodesOld; i++ ) if ( (pSopCover = (char *)pData->vSops->pArray[i]) ) { // get the number of cubes nCubes = Abc_SopGetCubeNum( pSopCover ); // get the new var in the matrix pVar = p->ppVars[2*i+1]; // assign the pair storage pVar->nCubes = nCubes; if ( nCubes > 0 ) { pVar->ppPairs = p->pppPairs + iCube; pVar->ppPairs[0] = p->ppPairs + iPair; for ( v = 1; v < nCubes; v++ ) pVar->ppPairs[v] = pVar->ppPairs[v-1] + nCubes; } // update iCube += nCubes; iPair += nCubes * nCubes; } assert( iCube == nCubesTotal ); assert( iPair == nPairsStore ); // allocate room for the reordered literals pOrder = ABC_ALLOC( int, nBitsMax ); // create the rows for ( i = 0; i < pData->nNodesOld; i++ ) if ( (pSopCover = (char *)pData->vSops->pArray[i]) ) { // get the new var in the matrix pVar = p->ppVars[2*i+1]; // here we sort the literals of the cover // in the increasing order of the numbers of the corresponding nodes // because literals should be added to the matrix in this order vFanins = (Vec_Int_t *)pData->vFanins->pArray[i]; s_pLits = vFanins->pArray; // start the variable order nFanins = Abc_SopGetVarNum( pSopCover ); for ( v = 0; v < nFanins; v++ ) pOrder[v] = v; // reorder the fanins qsort( (void *)pOrder, nFanins, sizeof(int),(int (*)(const void *, const void *))Fxu_CreateMatrixLitCompare); assert( s_pLits[ pOrder[0] ] < s_pLits[ pOrder[nFanins-1] ] ); // create the corresponding cubes in the matrix pCubeFirst = NULL; c = 0; Abc_SopForEachCube( pSopCover, nFanins, pSopCube ) { // create the cube pCubeNew = Fxu_MatrixAddCube( p, pVar, c++ ); Fxu_CreateMatrixAddCube( p, pCubeNew, pSopCube, vFanins, pOrder ); if ( pCubeFirst == NULL ) pCubeFirst = pCubeNew; pCubeNew->pFirst = pCubeFirst; } // set the first cube of this var pVar->pFirst = pCubeFirst; // create the divisors without preprocessing if ( nPairsTotal <= pData->nPairsMax ) { for ( pCube1 = pCubeFirst; pCube1; pCube1 = pCube1->pNext ) for ( pCube2 = pCube1? pCube1->pNext: NULL; pCube2; pCube2 = pCube2->pNext ) Fxu_MatrixAddDivisor( p, pCube1, pCube2 ); } } ABC_FREE( pOrder ); // consider the case when cube pairs should be preprocessed // before adding them to the set of divisors // if ( pData->fVerbose ) // printf( "The total number of cube pairs is %d.\n", nPairsTotal ); if ( nPairsTotal > 10000000 ) { printf( "The total number of cube pairs of the network is more than 10,000,000.\n" ); printf( "Command \"fx\" takes a long time to run in such cases. It is suggested\n" ); printf( "that the user changes the network by reducing the size of logic node and\n" ); printf( "consequently the number of cube pairs to be processed by this command.\n" ); printf( "It can be achieved as follows: \"st; if -K \" or \"st; renode -s -K \"\n" ); printf( "as a proprocessing step, while selecting as approapriate.\n" ); return NULL; } if ( nPairsTotal > pData->nPairsMax ) if ( !Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax ) ) return NULL; // if ( pData->fVerbose ) // printf( "Only %d best cube pairs will be used by the fast extract command.\n", pData->nPairsMax ); if ( p->lVars.nItems > 1000000 ) { printf( "The total number of variables is more than 1,000,000.\n" ); printf( "Command \"fx\" takes a long time to run in such cases. It is suggested\n" ); printf( "that the user changes the network by reducing the size of logic node and\n" ); printf( "consequently the number of cube pairs to be processed by this command.\n" ); printf( "It can be achieved as follows: \"st; if -K \" or \"st; renode -s -K \"\n" ); printf( "as a proprocessing step, while selecting as approapriate.\n" ); return NULL; } // add the var pairs to the heap Fxu_MatrixComputeSingles( p, pData->fUse0, pData->nSingleMax ); // print stats if ( pData->fVerbose ) { double Density; Density = ((double)p->nEntries) / p->lVars.nItems / p->lCubes.nItems; fprintf( stdout, "Matrix: [vars x cubes] = [%d x %d] ", p->lVars.nItems, p->lCubes.nItems ); fprintf( stdout, "Lits = %d Density = %.5f%%\n", p->nEntries, Density ); fprintf( stdout, "1-cube divs = %6d. (Total = %6d) ", p->lSingles.nItems, p->nSingleTotal ); fprintf( stdout, "2-cube divs = %6d. (Total = %6d)", p->nDivsTotal, nPairsTotal ); fprintf( stdout, "\n" ); } // Fxu_MatrixPrint( stdout, p ); return p; } /**Function************************************************************* Synopsis [Adds one cube with literals to the matrix.] Description [Create the cube and literals in the matrix corresponding to the given cube in the SOP cover. Co-singleton transform is performed here.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder ) { Fxu_Var * pVar; int Value, i; // add literals to the matrix Abc_CubeForEachVar( pSopCube, Value, i ) { Value = pSopCube[pOrder[i]]; if ( Value == '0' ) { pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] + 1 ]; // CST Fxu_MatrixAddLiteral( p, pCube, pVar ); } else if ( Value == '1' ) { pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] ]; // CST Fxu_MatrixAddLiteral( p, pCube, pVar ); } } } /**Function************************************************************* Synopsis [Creates the new array of Sop covers from the sparse matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData ) { Fxu_Cube * pCube, * pCubeFirst, * pCubeNext; char * pSopCover; int iNode, n; // get the first cube of the first internal node pCubeFirst = Fxu_CreateCoversFirstCube( p, pData, 0 ); // go through the internal nodes for ( n = 0; n < pData->nNodesOld; n++ ) if ( (pSopCover = (char *)pData->vSops->pArray[n]) ) { // get the number of this node iNode = n; // get the next first cube pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 ); // check if there any new variables in these cubes for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) if ( pCube->lLits.pTail && pCube->lLits.pTail->iVar >= 2 * pData->nNodesOld ) break; if ( pCube != pCubeNext ) Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext ); // update the first cube pCubeFirst = pCubeNext; } // add the covers for the extracted nodes for ( n = 0; n < pData->nNodesNew; n++ ) { // get the number of this node iNode = pData->nNodesOld + n; // get the next first cube pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 ); // the node should be added Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext ); // update the first cube pCubeFirst = pCubeNext; } } /**Function************************************************************* Synopsis [Create Sop covers for one node that has changed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext ) { Vec_Int_t * vInputsNew; char * pSopCover, * pSopCube; Fxu_Var * pVar; Fxu_Cube * pCube; Fxu_Lit * pLit; int iNum, nCubes, v; // collect positive polarity variable in the cubes between pCubeFirst and pCubeNext Fxu_MatrixRingVarsStart( p ); for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext ) { pVar = p->ppVars[ 2 * (pLit->pVar->iVar/2) + 1 ]; if ( pVar->pOrder == NULL ) Fxu_MatrixRingVarsAdd( p, pVar ); } Fxu_MatrixRingVarsStop( p ); // collect the variable numbers vInputsNew = Vec_IntAlloc( 4 ); Fxu_MatrixForEachVarInRing( p, pVar ) Vec_IntPush( vInputsNew, pVar->iVar / 2 ); Fxu_MatrixRingVarsUnmark( p ); // sort the vars by their number Vec_IntSort( vInputsNew, 0 ); // mark the vars with their numbers in the sorted array for ( v = 0; v < vInputsNew->nSize; v++ ) { p->ppVars[ 2 * vInputsNew->pArray[v] + 0 ]->lLits.nItems = v; // hack - reuse lLits.nItems p->ppVars[ 2 * vInputsNew->pArray[v] + 1 ]->lLits.nItems = v; // hack - reuse lLits.nItems } // count the number of cubes nCubes = 0; for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) if ( pCube->lLits.nItems ) nCubes++; // allocate room for the new cover pSopCover = Abc_SopStart( pData->pManSop, nCubes, vInputsNew->nSize ); // set the correct polarity of the cover if ( iNode < pData->nNodesOld && Abc_SopGetPhase( (char *)pData->vSops->pArray[iNode] ) == 0 ) Abc_SopComplement( pSopCover ); // add the cubes nCubes = 0; for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) { if ( pCube->lLits.nItems == 0 ) continue; // get hold of the SOP cube pSopCube = pSopCover + nCubes * (vInputsNew->nSize + 3); // insert literals for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext ) { iNum = pLit->pVar->lLits.nItems; // hack - reuse lLits.nItems assert( iNum < vInputsNew->nSize ); if ( pLit->pVar->iVar / 2 < pData->nNodesOld ) pSopCube[iNum] = (pLit->pVar->iVar & 1)? '0' : '1'; // reverse CST else pSopCube[iNum] = (pLit->pVar->iVar & 1)? '1' : '0'; // no CST } // count the cube nCubes++; } assert( nCubes == Abc_SopGetCubeNum(pSopCover) ); // set the new cover and the array of fanins pData->vSopsNew->pArray[iNode] = pSopCover; pData->vFaninsNew->pArray[iNode] = vInputsNew; } /**Function************************************************************* Synopsis [Adds the var to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iVar ) { int v; for ( v = iVar; v < pData->nNodesOld + pData->nNodesNew; v++ ) if ( p->ppVars[ 2*v + 1 ]->pFirst ) return p->ppVars[ 2*v + 1 ]->pFirst; return NULL; } /**Function************************************************************* Synopsis [Compares the vars by their number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY ) { return s_pLits[*ptrX] - s_pLits[*ptrY]; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuHeapD.c000066400000000000000000000275701300674244400233230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuHeapD.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [The priority queue for double cube divisors.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuHeapD.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define FXU_HEAP_DOUBLE_WEIGHT(pDiv) ((pDiv)->Weight) #define FXU_HEAP_DOUBLE_CURRENT(p, pDiv) ((p)->pTree[(pDiv)->HNum]) #define FXU_HEAP_DOUBLE_PARENT_EXISTS(p, pDiv) ((pDiv)->HNum > 1) #define FXU_HEAP_DOUBLE_CHILD1_EXISTS(p, pDiv) (((pDiv)->HNum << 1) <= p->nItems) #define FXU_HEAP_DOUBLE_CHILD2_EXISTS(p, pDiv) ((((pDiv)->HNum << 1)+1) <= p->nItems) #define FXU_HEAP_DOUBLE_PARENT(p, pDiv) ((p)->pTree[(pDiv)->HNum >> 1]) #define FXU_HEAP_DOUBLE_CHILD1(p, pDiv) ((p)->pTree[(pDiv)->HNum << 1]) #define FXU_HEAP_DOUBLE_CHILD2(p, pDiv) ((p)->pTree[((pDiv)->HNum << 1)+1]) #define FXU_HEAP_DOUBLE_ASSERT(p, pDiv) assert( (pDiv)->HNum >= 1 && (pDiv)->HNum <= p->nItemsAlloc ) static void Fxu_HeapDoubleResize( Fxu_HeapDouble * p ); static void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 ); static void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv ); static void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_HeapDouble * Fxu_HeapDoubleStart() { Fxu_HeapDouble * p; p = ABC_ALLOC( Fxu_HeapDouble, 1 ); memset( p, 0, sizeof(Fxu_HeapDouble) ); p->nItems = 0; p->nItemsAlloc = 10000; p->pTree = ABC_ALLOC( Fxu_Double *, p->nItemsAlloc + 1 ); p->pTree[0] = NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleResize( Fxu_HeapDouble * p ) { p->nItemsAlloc *= 2; p->pTree = ABC_REALLOC( Fxu_Double *, p->pTree, p->nItemsAlloc + 1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleStop( Fxu_HeapDouble * p ) { ABC_FREE( p->pTree ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p ) { Fxu_Double * pDiv; int Counter = 1; int Degree = 1; Fxu_HeapDoubleCheck( p ); fprintf( pFile, "The contents of the heap:\n" ); fprintf( pFile, "Level %d: ", Degree ); Fxu_HeapDoubleForEachItem( p, pDiv ) { assert( Counter == p->pTree[Counter]->HNum ); fprintf( pFile, "%2d=%3d ", Counter, FXU_HEAP_DOUBLE_WEIGHT(p->pTree[Counter]) ); if ( ++Counter == (1 << Degree) ) { fprintf( pFile, "\n" ); Degree++; fprintf( pFile, "Level %d: ", Degree ); } } fprintf( pFile, "\n" ); fprintf( pFile, "End of the heap printout.\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p ) { Fxu_Double * pDiv; Fxu_HeapDoubleForEachItem( p, pDiv ) { assert( pDiv->HNum == p->i ); Fxu_HeapDoubleCheckOne( p, pDiv ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv ) { int Weight1, Weight2; if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) ) { Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv); Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) ); assert( Weight1 >= Weight2 ); } if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) ) { Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv); Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) ); assert( Weight1 >= Weight2 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv ) { if ( p->nItems == p->nItemsAlloc ) Fxu_HeapDoubleResize( p ); // put the last entry to the last place and move up p->pTree[++p->nItems] = pDiv; pDiv->HNum = p->nItems; // move the last entry up if necessary Fxu_HeapDoubleMoveUp( p, pDiv ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv ) { //printf( "Updating divisor %d.\n", pDiv->Num ); FXU_HEAP_DOUBLE_ASSERT(p,pDiv); if ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,pDiv) && FXU_HEAP_DOUBLE_WEIGHT(pDiv) > FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_PARENT(p,pDiv) ) ) Fxu_HeapDoubleMoveUp( p, pDiv ); else if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) && FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) ) ) Fxu_HeapDoubleMoveDn( p, pDiv ); else if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) && FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) ) ) Fxu_HeapDoubleMoveDn( p, pDiv ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv ) { FXU_HEAP_DOUBLE_ASSERT(p,pDiv); // put the last entry to the deleted place // decrement the number of entries p->pTree[pDiv->HNum] = p->pTree[p->nItems--]; p->pTree[pDiv->HNum]->HNum = pDiv->HNum; // move the top entry down if necessary Fxu_HeapDoubleUpdate( p, p->pTree[pDiv->HNum] ); pDiv->HNum = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p ) { if ( p->nItems == 0 ) return NULL; return p->pTree[1]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p ) { Fxu_Double * pDiv; if ( p->nItems == 0 ) return NULL; // prepare the return value pDiv = p->pTree[1]; pDiv->HNum = 0; // put the last entry on top // decrement the number of entries p->pTree[1] = p->pTree[p->nItems--]; p->pTree[1]->HNum = 1; // move the top entry down if necessary Fxu_HeapDoubleMoveDn( p, p->pTree[1] ); return pDiv; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p ) { if ( p->nItems == 0 ) return -1; else return FXU_HEAP_DOUBLE_WEIGHT(p->pTree[1]); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 ) { Fxu_Double * pDiv; int Temp; pDiv = *pDiv1; *pDiv1 = *pDiv2; *pDiv2 = pDiv; Temp = (*pDiv1)->HNum; (*pDiv1)->HNum = (*pDiv2)->HNum; (*pDiv2)->HNum = Temp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv ) { Fxu_Double ** ppDiv, ** ppPar; ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv); while ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,*ppDiv) ) { ppPar = &FXU_HEAP_DOUBLE_PARENT(p,*ppDiv); if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) > FXU_HEAP_DOUBLE_WEIGHT(*ppPar) ) { Fxu_HeapDoubleSwap( ppDiv, ppPar ); ppDiv = ppPar; } else break; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv ) { Fxu_Double ** ppChild1, ** ppChild2, ** ppDiv; ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv); while ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,*ppDiv) ) { // if Child1 does not exist, Child2 also does not exists // get the children ppChild1 = &FXU_HEAP_DOUBLE_CHILD1(p,*ppDiv); if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,*ppDiv) ) { ppChild2 = &FXU_HEAP_DOUBLE_CHILD2(p,*ppDiv); // consider two cases if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) && FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) ) { // Div is larger than both, skip break; } else { // Div is smaller than one of them, then swap it with larger if ( FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) ) { Fxu_HeapDoubleSwap( ppDiv, ppChild1 ); // update the pointer ppDiv = ppChild1; } else { Fxu_HeapDoubleSwap( ppDiv, ppChild2 ); // update the pointer ppDiv = ppChild2; } } } else // Child2 does not exist { // consider two cases if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) ) { // Div is larger than Child1, skip break; } else { // Div is smaller than Child1, then swap them Fxu_HeapDoubleSwap( ppDiv, ppChild1 ); // update the pointer ppDiv = ppChild1; } } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuHeapS.c000066400000000000000000000302111300674244400233240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuHeapS.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [The priority queue for variables.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuHeapS.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define FXU_HEAP_SINGLE_WEIGHT(pSingle) ((pSingle)->Weight) #define FXU_HEAP_SINGLE_CURRENT(p, pSingle) ((p)->pTree[(pSingle)->HNum]) #define FXU_HEAP_SINGLE_PARENT_EXISTS(p, pSingle) ((pSingle)->HNum > 1) #define FXU_HEAP_SINGLE_CHILD1_EXISTS(p, pSingle) (((pSingle)->HNum << 1) <= p->nItems) #define FXU_HEAP_SINGLE_CHILD2_EXISTS(p, pSingle) ((((pSingle)->HNum << 1)+1) <= p->nItems) #define FXU_HEAP_SINGLE_PARENT(p, pSingle) ((p)->pTree[(pSingle)->HNum >> 1]) #define FXU_HEAP_SINGLE_CHILD1(p, pSingle) ((p)->pTree[(pSingle)->HNum << 1]) #define FXU_HEAP_SINGLE_CHILD2(p, pSingle) ((p)->pTree[((pSingle)->HNum << 1)+1]) #define FXU_HEAP_SINGLE_ASSERT(p, pSingle) assert( (pSingle)->HNum >= 1 && (pSingle)->HNum <= p->nItemsAlloc ) static void Fxu_HeapSingleResize( Fxu_HeapSingle * p ); static void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 ); static void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle ); static void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_HeapSingle * Fxu_HeapSingleStart() { Fxu_HeapSingle * p; p = ABC_ALLOC( Fxu_HeapSingle, 1 ); memset( p, 0, sizeof(Fxu_HeapSingle) ); p->nItems = 0; p->nItemsAlloc = 2000; p->pTree = ABC_ALLOC( Fxu_Single *, p->nItemsAlloc + 10 ); p->pTree[0] = NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleResize( Fxu_HeapSingle * p ) { p->nItemsAlloc *= 2; p->pTree = ABC_REALLOC( Fxu_Single *, p->pTree, p->nItemsAlloc + 10 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleStop( Fxu_HeapSingle * p ) { int i; i = 0; ABC_FREE( p->pTree ); i = 1; ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p ) { Fxu_Single * pSingle; int Counter = 1; int Degree = 1; Fxu_HeapSingleCheck( p ); fprintf( pFile, "The contents of the heap:\n" ); fprintf( pFile, "Level %d: ", Degree ); Fxu_HeapSingleForEachItem( p, pSingle ) { assert( Counter == p->pTree[Counter]->HNum ); fprintf( pFile, "%2d=%3d ", Counter, FXU_HEAP_SINGLE_WEIGHT(p->pTree[Counter]) ); if ( ++Counter == (1 << Degree) ) { fprintf( pFile, "\n" ); Degree++; fprintf( pFile, "Level %d: ", Degree ); } } fprintf( pFile, "\n" ); fprintf( pFile, "End of the heap printout.\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleCheck( Fxu_HeapSingle * p ) { Fxu_Single * pSingle; Fxu_HeapSingleForEachItem( p, pSingle ) { assert( pSingle->HNum == p->i ); Fxu_HeapSingleCheckOne( p, pSingle ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle ) { int Weight1, Weight2; if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) ) { Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle); Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) ); assert( Weight1 >= Weight2 ); } if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) ) { Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle); Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) ); assert( Weight1 >= Weight2 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle ) { if ( p->nItems == p->nItemsAlloc ) Fxu_HeapSingleResize( p ); // put the last entry to the last place and move up p->pTree[++p->nItems] = pSingle; pSingle->HNum = p->nItems; // move the last entry up if necessary Fxu_HeapSingleMoveUp( p, pSingle ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle ) { FXU_HEAP_SINGLE_ASSERT(p,pSingle); if ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,pSingle) && FXU_HEAP_SINGLE_WEIGHT(pSingle) > FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_PARENT(p,pSingle) ) ) Fxu_HeapSingleMoveUp( p, pSingle ); else if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) && FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) ) ) Fxu_HeapSingleMoveDn( p, pSingle ); else if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) && FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) ) ) Fxu_HeapSingleMoveDn( p, pSingle ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle ) { int Place = pSingle->HNum; FXU_HEAP_SINGLE_ASSERT(p,pSingle); // put the last entry to the deleted place // decrement the number of entries p->pTree[Place] = p->pTree[p->nItems--]; p->pTree[Place]->HNum = Place; // move the top entry down if necessary Fxu_HeapSingleUpdate( p, p->pTree[Place] ); pSingle->HNum = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p ) { if ( p->nItems == 0 ) return NULL; return p->pTree[1]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p ) { Fxu_Single * pSingle; if ( p->nItems == 0 ) return NULL; // prepare the return value pSingle = p->pTree[1]; pSingle->HNum = 0; // put the last entry on top // decrement the number of entries p->pTree[1] = p->pTree[p->nItems--]; p->pTree[1]->HNum = 1; // move the top entry down if necessary Fxu_HeapSingleMoveDn( p, p->pTree[1] ); return pSingle; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p ) { if ( p->nItems == 0 ) return -1; return FXU_HEAP_SINGLE_WEIGHT(p->pTree[1]); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 ) { Fxu_Single * pSingle; int Temp; pSingle = *pSingle1; *pSingle1 = *pSingle2; *pSingle2 = pSingle; Temp = (*pSingle1)->HNum; (*pSingle1)->HNum = (*pSingle2)->HNum; (*pSingle2)->HNum = Temp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle ) { Fxu_Single ** ppSingle, ** ppPar; ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle); while ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,*ppSingle) ) { ppPar = &FXU_HEAP_SINGLE_PARENT(p,*ppSingle); if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) > FXU_HEAP_SINGLE_WEIGHT(*ppPar) ) { Fxu_HeapSingleSwap( ppSingle, ppPar ); ppSingle = ppPar; } else break; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle ) { Fxu_Single ** ppChild1, ** ppChild2, ** ppSingle; ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle); while ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,*ppSingle) ) { // if Child1 does not exist, Child2 also does not exists // get the children ppChild1 = &FXU_HEAP_SINGLE_CHILD1(p,*ppSingle); if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,*ppSingle) ) { ppChild2 = &FXU_HEAP_SINGLE_CHILD2(p,*ppSingle); // consider two cases if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) && FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) ) { // Var is larger than both, skip break; } else { // Var is smaller than one of them, then swap it with larger if ( FXU_HEAP_SINGLE_WEIGHT(*ppChild1) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) ) { Fxu_HeapSingleSwap( ppSingle, ppChild1 ); // update the pointer ppSingle = ppChild1; } else { Fxu_HeapSingleSwap( ppSingle, ppChild2 ); // update the pointer ppSingle = ppChild2; } } } else // Child2 does not exist { // consider two cases if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) ) { // Var is larger than Child1, skip break; } else { // Var is smaller than Child1, then swap them Fxu_HeapSingleSwap( ppSingle, ppChild1 ); // update the pointer ppSingle = ppChild1; } } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuInt.h000066400000000000000000000573061300674244400231010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuInt.h] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Internal declarations of fast extract for unate covers.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuInt.h,v 1.3 2003/04/10 05:42:44 donald Exp $] ***********************************************************************/ #ifndef ABC__opt__fxu__fxuInt_h #define ABC__opt__fxu__fxuInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // uncomment this macro to switch to standard memory management //#define USE_SYSTEM_MEMORY_MANAGEMENT //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /* Here is an informal description of the FX data structure. (1) The sparse matrix is filled with literals, associated with cubes (row) and variables (columns). The matrix contains all the cubes of all the nodes in the network. (2) A cube is associated with (a) its literals in the matrix, (b) the output variable of the node, to which this cube belongs, (3) A variable is associated with (a) its literals in the matrix and (b) the list of cube pairs in the cover, for which it is the output (4) A cube pair is associated with two cubes and contains the counters of literals in the base and in the cubes without the base (5) A double-cube divisor is associated with list of all cube pairs that produce it and its current weight (which is updated automatically each time a new pair is added or an old pair is removed). (6) A single-cube divisor is associated the pair of variables. */ // sparse matrix typedef struct FxuMatrix Fxu_Matrix; // the sparse matrix // sparse matrix contents: cubes (rows), vars (columns), literals (entries) typedef struct FxuCube Fxu_Cube; // one cube in the sparse matrix typedef struct FxuVar Fxu_Var; // one literal in the sparse matrix typedef struct FxuLit Fxu_Lit; // one entry in the sparse matrix // double cube divisors typedef struct FxuPair Fxu_Pair; // the pair of cubes typedef struct FxuDouble Fxu_Double; // the double-cube divisor typedef struct FxuSingle Fxu_Single; // the two-literal single-cube divisor // various lists typedef struct FxuListCube Fxu_ListCube; // the list of cubes typedef struct FxuListVar Fxu_ListVar; // the list of literals typedef struct FxuListLit Fxu_ListLit; // the list of entries typedef struct FxuListPair Fxu_ListPair; // the list of pairs typedef struct FxuListDouble Fxu_ListDouble; // the list of divisors typedef struct FxuListSingle Fxu_ListSingle; // the list of single-cube divisors // various heaps typedef struct FxuHeapDouble Fxu_HeapDouble; // the heap of divisors typedef struct FxuHeapSingle Fxu_HeapSingle; // the heap of variables // various lists // the list of cubes in the sparse matrix struct FxuListCube { Fxu_Cube * pHead; Fxu_Cube * pTail; int nItems; }; // the list of literals in the sparse matrix struct FxuListVar { Fxu_Var * pHead; Fxu_Var * pTail; int nItems; }; // the list of entries in the sparse matrix struct FxuListLit { Fxu_Lit * pHead; Fxu_Lit * pTail; int nItems; }; // the list of cube pair in the sparse matrix struct FxuListPair { Fxu_Pair * pHead; Fxu_Pair * pTail; int nItems; }; // the list of divisors in the sparse matrix struct FxuListDouble { Fxu_Double * pHead; Fxu_Double * pTail; int nItems; }; // the list of divisors in the sparse matrix struct FxuListSingle { Fxu_Single * pHead; Fxu_Single * pTail; int nItems; }; // various heaps // the heap of double cube divisors by weight struct FxuHeapDouble { Fxu_Double ** pTree; int nItems; int nItemsAlloc; int i; }; // the heap of variable by their occurrence in the cubes struct FxuHeapSingle { Fxu_Single ** pTree; int nItems; int nItemsAlloc; int i; }; // sparse matrix struct FxuMatrix // ~ 30 words { // the cubes Fxu_ListCube lCubes; // the double linked list of cubes // the values (binary literals) Fxu_ListVar lVars; // the double linked list of variables Fxu_Var ** ppVars; // the array of variables // the double cube divisors Fxu_ListDouble * pTable; // the hash table of divisors int nTableSize; // the hash table size int nDivs; // the number of divisors in the table int nDivsTotal; // the number of divisors in the table Fxu_HeapDouble * pHeapDouble; // the heap of divisors by weight // the single cube divisors Fxu_ListSingle lSingles; // the linked list of single cube divisors Fxu_HeapSingle * pHeapSingle; // the heap of variables by the number of literals in the matrix int nWeightLimit;// the limit on weight of single cube divisors collected int nSingleTotal;// the total number of single cube divisors // storage for cube pairs Fxu_Pair *** pppPairs; Fxu_Pair ** ppPairs; // temporary storage for cubes Fxu_Cube * pOrderCubes; Fxu_Cube ** ppTailCubes; // temporary storage for variables Fxu_Var * pOrderVars; Fxu_Var ** ppTailVars; // temporary storage for pairs Vec_Ptr_t * vPairs; // statistics int nEntries; // the total number of entries in the sparse matrix int nDivs1; // the single cube divisors taken int nDivs2; // the double cube divisors taken int nDivs3; // the double cube divisors with complement // memory manager Extra_MmFixed_t * pMemMan; // the memory manager for all small sized entries }; // the cube in the sparse matrix struct FxuCube // 9 words { int iCube; // the number of this cube in the cover Fxu_Cube * pFirst; // the pointer to the first cube of this cover Fxu_Var * pVar; // the variable representing the output of the cover Fxu_ListLit lLits; // the row in the table Fxu_Cube * pPrev; // the previous cube Fxu_Cube * pNext; // the next cube Fxu_Cube * pOrder; // the specialized linked list of cubes }; // the variable in the sparse matrix struct FxuVar // 10 words { int iVar; // the number of this variable int nCubes; // the number of cubes assoc with this var Fxu_Cube * pFirst; // the first cube assoc with this var Fxu_Pair *** ppPairs; // the pairs of cubes assoc with this var Fxu_ListLit lLits; // the column in the table Fxu_Var * pPrev; // the previous variable Fxu_Var * pNext; // the next variable Fxu_Var * pOrder; // the specialized linked list of variables }; // the literal entry in the sparse matrix struct FxuLit // 8 words { int iVar; // the number of this variable int iCube; // the number of this cube Fxu_Cube * pCube; // the cube of this literal Fxu_Var * pVar; // the variable of this literal Fxu_Lit * pHPrev; // prev lit in the cube Fxu_Lit * pHNext; // next lit in the cube Fxu_Lit * pVPrev; // prev lit of the var Fxu_Lit * pVNext; // next lit of the var }; // the cube pair struct FxuPair // 10 words { int nLits1; // the number of literals in the two cubes int nLits2; // the number of literals in the two cubes int nBase; // the number of literals in the base Fxu_Double * pDiv; // the divisor of this pair Fxu_Cube * pCube1; // the first cube of the pair Fxu_Cube * pCube2; // the second cube of the pair int iCube1; // the first cube of the pair int iCube2; // the second cube of the pair Fxu_Pair * pDPrev; // the previous pair in the divisor Fxu_Pair * pDNext; // the next pair in the divisor }; // the double cube divisor struct FxuDouble // 10 words { int Num; // the unique number of this divisor int HNum; // the heap number of this divisor int Weight; // the weight of this divisor unsigned Key; // the hash key of this divisor Fxu_ListPair lPairs; // the pairs of cubes, which produce this divisor Fxu_Double * pPrev; // the previous divisor in the table Fxu_Double * pNext; // the next divisor in the table Fxu_Double * pOrder; // the specialized linked list of divisors }; // the single cube divisor struct FxuSingle // 7 words { int Num; // the unique number of this divisor int HNum; // the heap number of this divisor int Weight; // the weight of this divisor Fxu_Var * pVar1; // the first variable of the single-cube divisor Fxu_Var * pVar2; // the second variable of the single-cube divisor Fxu_Single * pPrev; // the previous divisor in the list Fxu_Single * pNext; // the next divisor in the list }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // minimum/maximum #define Fxu_Min( a, b ) ( ((a)<(b))? (a):(b) ) #define Fxu_Max( a, b ) ( ((a)>(b))? (a):(b) ) // selection of the minimum/maximum cube in the pair #define Fxu_PairMinCube( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2) #define Fxu_PairMaxCube( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2) #define Fxu_PairMinCubeInt( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2) #define Fxu_PairMaxCubeInt( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2) // iterators #define Fxu_MatrixForEachCube( Matrix, Cube )\ for ( Cube = (Matrix)->lCubes.pHead;\ Cube;\ Cube = Cube->pNext ) #define Fxu_MatrixForEachCubeSafe( Matrix, Cube, Cube2 )\ for ( Cube = (Matrix)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\ Cube;\ Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) #define Fxu_MatrixForEachVariable( Matrix, Var )\ for ( Var = (Matrix)->lVars.pHead;\ Var;\ Var = Var->pNext ) #define Fxu_MatrixForEachVariableSafe( Matrix, Var, Var2 )\ for ( Var = (Matrix)->lVars.pHead, Var2 = (Var? Var->pNext: NULL);\ Var;\ Var = Var2, Var2 = (Var? Var->pNext: NULL) ) #define Fxu_MatrixForEachSingle( Matrix, Single )\ for ( Single = (Matrix)->lSingles.pHead;\ Single;\ Single = Single->pNext ) #define Fxu_MatrixForEachSingleSafe( Matrix, Single, Single2 )\ for ( Single = (Matrix)->lSingles.pHead, Single2 = (Single? Single->pNext: NULL);\ Single;\ Single = Single2, Single2 = (Single? Single->pNext: NULL) ) #define Fxu_TableForEachDouble( Matrix, Key, Div )\ for ( Div = (Matrix)->pTable[Key].pHead;\ Div;\ Div = Div->pNext ) #define Fxu_TableForEachDoubleSafe( Matrix, Key, Div, Div2 )\ for ( Div = (Matrix)->pTable[Key].pHead, Div2 = (Div? Div->pNext: NULL);\ Div;\ Div = Div2, Div2 = (Div? Div->pNext: NULL) ) #define Fxu_MatrixForEachDouble( Matrix, Div, Index )\ for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\ Fxu_TableForEachDouble( Matrix, Index, Div ) #define Fxu_MatrixForEachDoubleSafe( Matrix, Div, Div2, Index )\ for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\ Fxu_TableForEachDoubleSafe( Matrix, Index, Div, Div2 ) #define Fxu_CubeForEachLiteral( Cube, Lit )\ for ( Lit = (Cube)->lLits.pHead;\ Lit;\ Lit = Lit->pHNext ) #define Fxu_CubeForEachLiteralSafe( Cube, Lit, Lit2 )\ for ( Lit = (Cube)->lLits.pHead, Lit2 = (Lit? Lit->pHNext: NULL);\ Lit;\ Lit = Lit2, Lit2 = (Lit? Lit->pHNext: NULL) ) #define Fxu_VarForEachLiteral( Var, Lit )\ for ( Lit = (Var)->lLits.pHead;\ Lit;\ Lit = Lit->pVNext ) #define Fxu_CubeForEachDivisor( Cube, Div )\ for ( Div = (Cube)->lDivs.pHead;\ Div;\ Div = Div->pCNext ) #define Fxu_DoubleForEachPair( Div, Pair )\ for ( Pair = (Div)->lPairs.pHead;\ Pair;\ Pair = Pair->pDNext ) #define Fxu_DoubleForEachPairSafe( Div, Pair, Pair2 )\ for ( Pair = (Div)->lPairs.pHead, Pair2 = (Pair? Pair->pDNext: NULL);\ Pair;\ Pair = Pair2, Pair2 = (Pair? Pair->pDNext: NULL) ) // iterator through the cube pairs belonging to the given cube #define Fxu_CubeForEachPair( pCube, pPair, i )\ for ( i = 0;\ i < pCube->pVar->nCubes && (((pPair) = (pCube)->pVar->ppPairs[(pCube)->iCube][i]), 1);\ i++ )\ if ( pPair == NULL ) {} else // iterator through all the items in the heap #define Fxu_HeapDoubleForEachItem( Heap, Div )\ for ( Heap->i = 1;\ Heap->i <= Heap->nItems && (Div = Heap->pTree[Heap->i]);\ Heap->i++ ) #define Fxu_HeapSingleForEachItem( Heap, Single )\ for ( Heap->i = 1;\ Heap->i <= Heap->nItems && (Single = Heap->pTree[Heap->i]);\ Heap->i++ ) // starting the rings #define Fxu_MatrixRingCubesStart( Matrix ) (((Matrix)->ppTailCubes = &((Matrix)->pOrderCubes)), ((Matrix)->pOrderCubes = NULL)) #define Fxu_MatrixRingVarsStart( Matrix ) (((Matrix)->ppTailVars = &((Matrix)->pOrderVars)), ((Matrix)->pOrderVars = NULL)) // stopping the rings #define Fxu_MatrixRingCubesStop( Matrix ) #define Fxu_MatrixRingVarsStop( Matrix ) // resetting the rings #define Fxu_MatrixRingCubesReset( Matrix ) (((Matrix)->pOrderCubes = NULL), ((Matrix)->ppTailCubes = NULL)) #define Fxu_MatrixRingVarsReset( Matrix ) (((Matrix)->pOrderVars = NULL), ((Matrix)->ppTailVars = NULL)) // adding to the rings #define Fxu_MatrixRingCubesAdd( Matrix, Cube) ((*((Matrix)->ppTailCubes) = Cube), ((Matrix)->ppTailCubes = &(Cube)->pOrder), ((Cube)->pOrder = (Fxu_Cube *)1)) #define Fxu_MatrixRingVarsAdd( Matrix, Var ) ((*((Matrix)->ppTailVars ) = Var ), ((Matrix)->ppTailVars = &(Var)->pOrder ), ((Var)->pOrder = (Fxu_Var *)1)) // iterating through the rings #define Fxu_MatrixForEachCubeInRing( Matrix, Cube )\ if ( (Matrix)->pOrderCubes )\ for ( Cube = (Matrix)->pOrderCubes;\ Cube != (Fxu_Cube *)1;\ Cube = Cube->pOrder ) #define Fxu_MatrixForEachCubeInRingSafe( Matrix, Cube, Cube2 )\ if ( (Matrix)->pOrderCubes )\ for ( Cube = (Matrix)->pOrderCubes, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1);\ Cube != (Fxu_Cube *)1;\ Cube = Cube2, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1) ) #define Fxu_MatrixForEachVarInRing( Matrix, Var )\ if ( (Matrix)->pOrderVars )\ for ( Var = (Matrix)->pOrderVars;\ Var != (Fxu_Var *)1;\ Var = Var->pOrder ) #define Fxu_MatrixForEachVarInRingSafe( Matrix, Var, Var2 )\ if ( (Matrix)->pOrderVars )\ for ( Var = (Matrix)->pOrderVars, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1);\ Var != (Fxu_Var *)1;\ Var = Var2, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1) ) // the procedures are related to the above macros extern void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p ); extern void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p ); // macros working with memory // MEM_ALLOC: allocate the given number (Size) of items of type (Type) // MEM_FREE: deallocate the pointer (Pointer) to the given number (Size) of items of type (Type) #ifdef USE_SYSTEM_MEMORY_MANAGEMENT #define MEM_ALLOC_FXU( Manager, Type, Size ) ((Type *)ABC_ALLOC( char, (Size) * sizeof(Type) )) #define MEM_FREE_FXU( Manager, Type, Size, Pointer ) if ( Pointer ) { ABC_FREE(Pointer); Pointer = NULL; } #else #define MEM_ALLOC_FXU( Manager, Type, Size )\ ((Type *)Fxu_MemFetch( Manager, (Size) * sizeof(Type) )) #define MEM_FREE_FXU( Manager, Type, Size, Pointer )\ if ( Pointer ) { Fxu_MemRecycle( Manager, (char *)(Pointer), (Size) * sizeof(Type) ); Pointer = NULL; } #endif //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*===== fxu.c ====================================================*/ extern char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes ); extern void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes ); /*===== fxuCreate.c ====================================================*/ /*===== fxuReduce.c ====================================================*/ /*===== fxuPrint.c ====================================================*/ extern void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p ); extern void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p ); /*===== fxuSelect.c ====================================================*/ extern int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble ); extern int Fxu_SelectSCD( Fxu_Matrix * p, int Weight, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 ); /*===== fxuUpdate.c ====================================================*/ extern void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble ); extern void Fxu_UpdateDouble( Fxu_Matrix * p ); extern void Fxu_UpdateSingle( Fxu_Matrix * p ); /*===== fxuPair.c ====================================================*/ extern void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ); extern unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ); extern unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 ); extern unsigned Fxu_PairHashKeyMv( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 ); extern int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 ); extern void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes ); extern void Fxu_PairFreeStorage( Fxu_Var * pVar ); extern void Fxu_PairClearStorage( Fxu_Cube * pCube ); extern Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ); extern void Fxu_PairAdd( Fxu_Pair * pPair ); /*===== fxuSingle.c ====================================================*/ extern void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax ); extern void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ); extern int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 ); /*===== fxuMatrix.c ====================================================*/ // matrix extern Fxu_Matrix * Fxu_MatrixAllocate(); extern void Fxu_MatrixDelete( Fxu_Matrix * p ); // double-cube divisor extern void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ); extern void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); // single-cube divisor extern void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight ); // variable extern Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p ); // cube extern Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube ); // literal extern void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar ); extern void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit ); /*===== fxuList.c ====================================================*/ // matrix -> variable extern void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pVar ); extern void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pVar ); // matrix -> cube extern void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube ); extern void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pCube ); // matrix -> single extern void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); extern void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); // table -> divisor extern void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); extern void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); // cube -> literal extern void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit ); extern void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit ); // var -> literal extern void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLit ); extern void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLit ); // divisor -> pair extern void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink ); extern void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink ); extern void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink ); extern void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pPair ); /*===== fxuHeapDouble.c ====================================================*/ extern Fxu_HeapDouble * Fxu_HeapDoubleStart(); extern void Fxu_HeapDoubleStop( Fxu_HeapDouble * p ); extern void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p ); extern void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p ); extern void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv ); extern void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv ); extern void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv ); extern void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv ); extern int Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p ); extern Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p ); extern Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p ); /*===== fxuHeapSingle.c ====================================================*/ extern Fxu_HeapSingle * Fxu_HeapSingleStart(); extern void Fxu_HeapSingleStop( Fxu_HeapSingle * p ); extern void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p ); extern void Fxu_HeapSingleCheck( Fxu_HeapSingle * p ); extern void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle ); extern void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle ); extern void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle ); extern void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle ); extern int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p ); extern Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p ); extern Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuList.c000066400000000000000000000267751300674244400232630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuList.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Operations on lists.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuList.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // matrix -> var /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pLink ) { Fxu_ListVar * pList = &p->lVars; if ( pList->pHead == NULL ) { pList->pHead = pLink; pList->pTail = pLink; pLink->pPrev = NULL; pLink->pNext = NULL; } else { pLink->pNext = NULL; pList->pTail->pNext = pLink; pLink->pPrev = pList->pTail; pList->pTail = pLink; } pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pLink ) { Fxu_ListVar * pList = &p->lVars; if ( pList->pHead == pLink ) pList->pHead = pLink->pNext; if ( pList->pTail == pLink ) pList->pTail = pLink->pPrev; if ( pLink->pPrev ) pLink->pPrev->pNext = pLink->pNext; if ( pLink->pNext ) pLink->pNext->pPrev = pLink->pPrev; pList->nItems--; } // matrix -> cube /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pLink ) { Fxu_ListCube * pList = &p->lCubes; if ( pList->pHead == NULL ) { pList->pHead = pLink; pList->pTail = pLink; pLink->pPrev = NULL; pLink->pNext = NULL; } else { pLink->pNext = NULL; pList->pTail->pNext = pLink; pLink->pPrev = pList->pTail; pList->pTail = pLink; } pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pLink ) { Fxu_ListCube * pList = &p->lCubes; if ( pList->pHead == pLink ) pList->pHead = pLink->pNext; if ( pList->pTail == pLink ) pList->pTail = pLink->pPrev; if ( pLink->pPrev ) pLink->pPrev->pNext = pLink->pNext; if ( pLink->pNext ) pLink->pNext->pPrev = pLink->pPrev; pList->nItems--; } // matrix -> single /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pLink ) { Fxu_ListSingle * pList = &p->lSingles; if ( pList->pHead == NULL ) { pList->pHead = pLink; pList->pTail = pLink; pLink->pPrev = NULL; pLink->pNext = NULL; } else { pLink->pNext = NULL; pList->pTail->pNext = pLink; pLink->pPrev = pList->pTail; pList->pTail = pLink; } pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pLink ) { Fxu_ListSingle * pList = &p->lSingles; if ( pList->pHead == pLink ) pList->pHead = pLink->pNext; if ( pList->pTail == pLink ) pList->pTail = pLink->pPrev; if ( pLink->pPrev ) pLink->pPrev->pNext = pLink->pNext; if ( pLink->pNext ) pLink->pNext->pPrev = pLink->pPrev; pList->nItems--; } // table -> divisor /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pLink ) { Fxu_ListDouble * pList = &(p->pTable[pLink->Key]); if ( pList->pHead == NULL ) { pList->pHead = pLink; pList->pTail = pLink; pLink->pPrev = NULL; pLink->pNext = NULL; } else { pLink->pNext = NULL; pList->pTail->pNext = pLink; pLink->pPrev = pList->pTail; pList->pTail = pLink; } pList->nItems++; p->nDivs++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pLink ) { Fxu_ListDouble * pList = &(p->pTable[pLink->Key]); if ( pList->pHead == pLink ) pList->pHead = pLink->pNext; if ( pList->pTail == pLink ) pList->pTail = pLink->pPrev; if ( pLink->pPrev ) pLink->pPrev->pNext = pLink->pNext; if ( pLink->pNext ) pLink->pNext->pPrev = pLink->pPrev; pList->nItems--; p->nDivs--; } // cube -> literal /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink ) { Fxu_ListLit * pList = &(pCube->lLits); if ( pList->pHead == NULL ) { pList->pHead = pLink; pList->pTail = pLink; pLink->pHPrev = NULL; pLink->pHNext = NULL; } else { pLink->pHNext = NULL; pList->pTail->pHNext = pLink; pLink->pHPrev = pList->pTail; pList->pTail = pLink; } pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink ) { Fxu_ListLit * pList = &(pCube->lLits); if ( pList->pHead == pLink ) pList->pHead = pLink->pHNext; if ( pList->pTail == pLink ) pList->pTail = pLink->pHPrev; if ( pLink->pHPrev ) pLink->pHPrev->pHNext = pLink->pHNext; if ( pLink->pHNext ) pLink->pHNext->pHPrev = pLink->pHPrev; pList->nItems--; } // var -> literal /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLink ) { Fxu_ListLit * pList = &(pVar->lLits); if ( pList->pHead == NULL ) { pList->pHead = pLink; pList->pTail = pLink; pLink->pVPrev = NULL; pLink->pVNext = NULL; } else { pLink->pVNext = NULL; pList->pTail->pVNext = pLink; pLink->pVPrev = pList->pTail; pList->pTail = pLink; } pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLink ) { Fxu_ListLit * pList = &(pVar->lLits); if ( pList->pHead == pLink ) pList->pHead = pLink->pVNext; if ( pList->pTail == pLink ) pList->pTail = pLink->pVPrev; if ( pLink->pVPrev ) pLink->pVPrev->pVNext = pLink->pVNext; if ( pLink->pVNext ) pLink->pVNext->pVPrev = pLink->pVPrev; pList->nItems--; } // divisor -> pair /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink ) { Fxu_ListPair * pList = &pDiv->lPairs; if ( pList->pHead == NULL ) { pList->pHead = pLink; pList->pTail = pLink; pLink->pDPrev = NULL; pLink->pDNext = NULL; } else { pLink->pDNext = NULL; pList->pTail->pDNext = pLink; pLink->pDPrev = pList->pTail; pList->pTail = pLink; } pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink ) { Fxu_ListPair * pList = &pDiv->lPairs; if ( pList->pHead == NULL ) { pList->pHead = pLink; pList->pTail = pLink; pLink->pDPrev = NULL; pLink->pDNext = NULL; } else { pLink->pDPrev = NULL; pList->pHead->pDPrev = pLink; pLink->pDNext = pList->pHead; pList->pHead = pLink; } pList->nItems++; } /**Function************************************************************* Synopsis [Adds the entry in the middle of the list after the spot.] Description [Assumes that spot points to the link, after which the given link should be added. Spot cannot be NULL or the tail of the list. Therefore, the head and the tail of the list are not changed.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink ) { Fxu_ListPair * pList = &pDiv->lPairs; assert( pSpot ); assert( pSpot != pList->pTail ); pLink->pDPrev = pSpot; pLink->pDNext = pSpot->pDNext; pLink->pDPrev->pDNext = pLink; pLink->pDNext->pDPrev = pLink; pList->nItems++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pLink ) { Fxu_ListPair * pList = &pDiv->lPairs; if ( pList->pHead == pLink ) pList->pHead = pLink->pDNext; if ( pList->pTail == pLink ) pList->pTail = pLink->pDPrev; if ( pLink->pDPrev ) pLink->pDPrev->pDNext = pLink->pDNext; if ( pLink->pDNext ) pLink->pDNext->pDPrev = pLink->pDPrev; pList->nItems--; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_ListDoubleAddPairPlace( Fxu_Double * pDiv, Fxu_Pair * pPair, Fxu_Pair * pPairSpot ) { printf( "Fxu_ListDoubleAddPairPlace() is called!\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuMatrix.c000066400000000000000000000251111300674244400235730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuMatrix.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Procedures to manipulate the sparse matrix.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuMatrix.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Matrix * Fxu_MatrixAllocate() { Fxu_Matrix * p; p = ABC_ALLOC( Fxu_Matrix, 1 ); memset( p, 0, sizeof(Fxu_Matrix) ); p->nTableSize = Abc_PrimeCudd(10000); p->pTable = ABC_ALLOC( Fxu_ListDouble, p->nTableSize ); memset( p->pTable, 0, sizeof(Fxu_ListDouble) * p->nTableSize ); #ifndef USE_SYSTEM_MEMORY_MANAGEMENT { // get the largest size in bytes for the following structures: // Fxu_Cube, Fxu_Var, Fxu_Lit, Fxu_Pair, Fxu_Double, Fxu_Single // (currently, Fxu_Var, Fxu_Pair, Fxu_Double take 10 machine words) int nSizeMax, nSizeCur; nSizeMax = -1; nSizeCur = sizeof(Fxu_Cube); if ( nSizeMax < nSizeCur ) nSizeMax = nSizeCur; nSizeCur = sizeof(Fxu_Var); if ( nSizeMax < nSizeCur ) nSizeMax = nSizeCur; nSizeCur = sizeof(Fxu_Lit); if ( nSizeMax < nSizeCur ) nSizeMax = nSizeCur; nSizeCur = sizeof(Fxu_Pair); if ( nSizeMax < nSizeCur ) nSizeMax = nSizeCur; nSizeCur = sizeof(Fxu_Double); if ( nSizeMax < nSizeCur ) nSizeMax = nSizeCur; nSizeCur = sizeof(Fxu_Single); if ( nSizeMax < nSizeCur ) nSizeMax = nSizeCur; p->pMemMan = Extra_MmFixedStart( nSizeMax ); } #endif p->pHeapDouble = Fxu_HeapDoubleStart(); p->pHeapSingle = Fxu_HeapSingleStart(); p->vPairs = Vec_PtrAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixDelete( Fxu_Matrix * p ) { Fxu_HeapDoubleCheck( p->pHeapDouble ); Fxu_HeapDoubleStop( p->pHeapDouble ); Fxu_HeapSingleStop( p->pHeapSingle ); // delete other things #ifdef USE_SYSTEM_MEMORY_MANAGEMENT // this code is not needed when the custom memory manager is used { Fxu_Cube * pCube, * pCube2; Fxu_Var * pVar, * pVar2; Fxu_Lit * pLit, * pLit2; Fxu_Double * pDiv, * pDiv2; Fxu_Single * pSingle, * pSingle2; Fxu_Pair * pPair, * pPair2; int i; // delete the divisors Fxu_MatrixForEachDoubleSafe( p, pDiv, pDiv2, i ) { Fxu_DoubleForEachPairSafe( pDiv, pPair, pPair2 ) MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); } Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 ) MEM_FREE_FXU( p, Fxu_Single, 1, pSingle ); // delete the entries Fxu_MatrixForEachCube( p, pCube ) Fxu_CubeForEachLiteralSafe( pCube, pLit, pLit2 ) MEM_FREE_FXU( p, Fxu_Lit, 1, pLit ); // delete the cubes Fxu_MatrixForEachCubeSafe( p, pCube, pCube2 ) MEM_FREE_FXU( p, Fxu_Cube, 1, pCube ); // delete the vars Fxu_MatrixForEachVariableSafe( p, pVar, pVar2 ) MEM_FREE_FXU( p, Fxu_Var, 1, pVar ); } #else Extra_MmFixedStop( p->pMemMan ); #endif Vec_PtrFree( p->vPairs ); ABC_FREE( p->pppPairs ); ABC_FREE( p->ppPairs ); // ABC_FREE( p->pPairsTemp ); ABC_FREE( p->pTable ); ABC_FREE( p->ppVars ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Adds a variable to the matrix.] Description [This procedure always adds variables at the end of the matrix. It assigns the var's node and number. It adds the var to the linked list of all variables and to the table of all nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p ) { Fxu_Var * pVar; pVar = MEM_ALLOC_FXU( p, Fxu_Var, 1 ); memset( pVar, 0, sizeof(Fxu_Var) ); pVar->iVar = p->lVars.nItems; p->ppVars[pVar->iVar] = pVar; Fxu_ListMatrixAddVariable( p, pVar ); return pVar; } /**Function************************************************************* Synopsis [Adds a literal to the matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube ) { Fxu_Cube * pCube; pCube = MEM_ALLOC_FXU( p, Fxu_Cube, 1 ); memset( pCube, 0, sizeof(Fxu_Cube) ); pCube->pVar = pVar; pCube->iCube = iCube; Fxu_ListMatrixAddCube( p, pCube ); return pCube; } /**Function************************************************************* Synopsis [Adds a literal to the matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar ) { Fxu_Lit * pLit; pLit = MEM_ALLOC_FXU( p, Fxu_Lit, 1 ); memset( pLit, 0, sizeof(Fxu_Lit) ); // insert the literal into two linked lists Fxu_ListCubeAddLiteral( pCube, pLit ); Fxu_ListVarAddLiteral( pVar, pLit ); // set the back pointers pLit->pCube = pCube; pLit->pVar = pVar; pLit->iCube = pCube->iCube; pLit->iVar = pVar->iVar; // increment the literal counter p->nEntries++; } /**Function************************************************************* Synopsis [Deletes the divisor from the matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ) { // delete divisor from the table Fxu_ListTableDelDivisor( p, pDiv ); // recycle the divisor MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); } /**Function************************************************************* Synopsis [Deletes the literal fromthe matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit ) { // delete the literal Fxu_ListCubeDelLiteral( pLit->pCube, pLit ); Fxu_ListVarDelLiteral( pLit->pVar, pLit ); MEM_FREE_FXU( p, Fxu_Lit, 1, pLit ); // increment the literal counter p->nEntries--; } /**Function************************************************************* Synopsis [Creates and adds a single cube divisor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight ) { Fxu_Single * pSingle; assert( pVar1->iVar < pVar2->iVar ); pSingle = MEM_ALLOC_FXU( p, Fxu_Single, 1 ); memset( pSingle, 0, sizeof(Fxu_Single) ); pSingle->Num = p->lSingles.nItems; pSingle->Weight = Weight; pSingle->HNum = 0; pSingle->pVar1 = pVar1; pSingle->pVar2 = pVar2; Fxu_ListMatrixAddSingle( p, pSingle ); // add to the heap Fxu_HeapSingleInsert( p->pHeapSingle, pSingle ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ) { Fxu_Pair * pPair; Fxu_Double * pDiv; int nBase, nLits1, nLits2; int fFound; unsigned Key; // canonicize the pair Fxu_PairCanonicize( &pCube1, &pCube2 ); // compute the hash key Key = Fxu_PairHashKey( p, pCube1, pCube2, &nBase, &nLits1, &nLits2 ); // create the cube pair pPair = Fxu_PairAlloc( p, pCube1, pCube2 ); pPair->nBase = nBase; pPair->nLits1 = nLits1; pPair->nLits2 = nLits2; // check if the divisor for this pair already exists fFound = 0; Key %= p->nTableSize; Fxu_TableForEachDouble( p, Key, pDiv ) { if ( Fxu_PairCompare( pPair, pDiv->lPairs.pTail ) ) // they are equal { fFound = 1; break; } } if ( !fFound ) { // create the new divisor pDiv = MEM_ALLOC_FXU( p, Fxu_Double, 1 ); memset( pDiv, 0, sizeof(Fxu_Double) ); pDiv->Key = Key; // set the number of this divisor pDiv->Num = p->nDivsTotal++; // p->nDivs; // insert the divisor in the table Fxu_ListTableAddDivisor( p, pDiv ); // set the initial cost of the divisor pDiv->Weight -= pPair->nLits1 + pPair->nLits2; } // link the pair to the cubes Fxu_PairAdd( pPair ); // connect the pair and the divisor pPair->pDiv = pDiv; Fxu_ListDoubleAddPairLast( pDiv, pPair ); // update the max number of pairs in a divisor // if ( p->nPairsMax < pDiv->lPairs.nItems ) // p->nPairsMax = pDiv->lPairs.nItems; // update the divisor's weight pDiv->Weight += pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase; if ( fFound ) // update the divisor in the heap Fxu_HeapDoubleUpdate( p->pHeapDouble, pDiv ); else // add the new divisor to the heap Fxu_HeapDoubleInsert( p->pHeapDouble, pDiv ); } /* { int piVarsC1[100], piVarsC2[100], nVarsC1, nVarsC2; Fxu_Double * pDivCur; Fxu_MatrixGetDoubleVars( p, pDiv, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); pDivCur = Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 ); assert( pDivCur == pDiv ); } */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuPair.c000066400000000000000000000344471300674244400232360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuPair.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Operations on cube pairs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuPair.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define MAX_PRIMES 304 static int s_Primes[MAX_PRIMES] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the canonical permutation of two cubes in the pair.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ) { Fxu_Lit * pLit1, * pLit2; Fxu_Cube * pCubeTemp; // walk through the cubes to determine // the one that has higher first variable pLit1 = (*ppCube1)->lLits.pHead; pLit2 = (*ppCube2)->lLits.pHead; while ( 1 ) { if ( pLit1->iVar == pLit2->iVar ) { pLit1 = pLit1->pHNext; pLit2 = pLit2->pHNext; continue; } assert( pLit1 && pLit2 ); // this is true if the covers are SCC-free if ( pLit1->iVar > pLit2->iVar ) { // swap the cubes pCubeTemp = *ppCube1; *ppCube1 = *ppCube2; *ppCube2 = pCubeTemp; } break; } } /**Function************************************************************* Synopsis [Find the canonical permutation of two cubes in the pair.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_PairCanonicize2( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ) { Fxu_Cube * pCubeTemp; // canonicize the pair by ordering the cubes if ( (*ppCube1)->iCube > (*ppCube2)->iCube ) { // swap the cubes pCubeTemp = *ppCube1; *ppCube1 = *ppCube2; *ppCube2 = pCubeTemp; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ) { int Offset1 = 100, Offset2 = 200, i; unsigned Key; // compute the hash key Key = 0; for ( i = 0; i < nVarsC1; i++ ) Key ^= s_Primes[Offset1+i] * piVarsC1[i]; for ( i = 0; i < nVarsC2; i++ ) Key ^= s_Primes[Offset2+i] * piVarsC2[i]; return Key; } /**Function************************************************************* Synopsis [Computes the hash key of the divisor represented by the pair of cubes.] Description [Goes through the variables in both cubes. Skips the identical ones (this corresponds to making the cubes cube-free). Computes the hash value of the cubes. Assigns the number of literals in the base and in the cubes without base.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 ) { int Offset1 = 100, Offset2 = 200; int nBase, nLits1, nLits2; Fxu_Lit * pLit1, * pLit2; unsigned Key; // compute the hash key Key = 0; nLits1 = 0; nLits2 = 0; nBase = 0; pLit1 = pCube1->lLits.pHead; pLit2 = pCube2->lLits.pHead; while ( 1 ) { if ( pLit1 && pLit2 ) { if ( pLit1->iVar == pLit2->iVar ) { // ensure cube-free pLit1 = pLit1->pHNext; pLit2 = pLit2->pHNext; // add this literal to the base nBase++; } else if ( pLit1->iVar < pLit2->iVar ) { Key ^= s_Primes[Offset1+nLits1] * pLit1->iVar; pLit1 = pLit1->pHNext; nLits1++; } else { Key ^= s_Primes[Offset2+nLits2] * pLit2->iVar; pLit2 = pLit2->pHNext; nLits2++; } } else if ( pLit1 && !pLit2 ) { Key ^= s_Primes[Offset1+nLits1] * pLit1->iVar; pLit1 = pLit1->pHNext; nLits1++; } else if ( !pLit1 && pLit2 ) { Key ^= s_Primes[Offset2+nLits2] * pLit2->iVar; pLit2 = pLit2->pHNext; nLits2++; } else break; } *pnBase = nBase; *pnLits1 = nLits1; *pnLits2 = nLits2; return Key; } /**Function************************************************************* Synopsis [Compares the two pairs.] Description [Returns 1 if the divisors represented by these pairs are equal.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 ) { Fxu_Lit * pD1C1, * pD1C2; Fxu_Lit * pD2C1, * pD2C2; int TopVar1, TopVar2; int Code; if ( pPair1->nLits1 != pPair2->nLits1 ) return 0; if ( pPair1->nLits2 != pPair2->nLits2 ) return 0; pD1C1 = pPair1->pCube1->lLits.pHead; pD1C2 = pPair1->pCube2->lLits.pHead; pD2C1 = pPair2->pCube1->lLits.pHead; pD2C2 = pPair2->pCube2->lLits.pHead; Code = pD1C1? 8: 0; Code |= pD1C2? 4: 0; Code |= pD2C1? 2: 0; Code |= pD2C2? 1: 0; assert( Code == 15 ); while ( 1 ) { switch ( Code ) { case 0: // -- -- NULL NULL NULL NULL return 1; case 1: // -- -1 NULL NULL NULL pD2C2 return 0; case 2: // -- 1- NULL NULL pD2C1 NULL return 0; case 3: // -- 11 NULL NULL pD2C1 pD2C2 if ( pD2C1->iVar != pD2C2->iVar ) return 0; pD2C1 = pD2C1->pHNext; pD2C2 = pD2C2->pHNext; break; case 4: // -1 -- NULL pD1C2 NULL NULL return 0; case 5: // -1 -1 NULL pD1C2 NULL pD2C2 if ( pD1C2->iVar != pD2C2->iVar ) return 0; pD1C2 = pD1C2->pHNext; pD2C2 = pD2C2->pHNext; break; case 6: // -1 1- NULL pD1C2 pD2C1 NULL return 0; case 7: // -1 11 NULL pD1C2 pD2C1 pD2C2 TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); if ( TopVar2 == pD1C2->iVar ) { if ( pD2C1->iVar <= pD2C2->iVar ) return 0; pD1C2 = pD1C2->pHNext; pD2C2 = pD2C2->pHNext; } else if ( TopVar2 < pD1C2->iVar ) { if ( pD2C1->iVar != pD2C2->iVar ) return 0; pD2C1 = pD2C1->pHNext; pD2C2 = pD2C2->pHNext; } else return 0; break; case 8: // 1- -- pD1C1 NULL NULL NULL return 0; case 9: // 1- -1 pD1C1 NULL NULL pD2C2 return 0; case 10: // 1- 1- pD1C1 NULL pD2C1 NULL if ( pD1C1->iVar != pD2C1->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD2C1 = pD2C1->pHNext; break; case 11: // 1- 11 pD1C1 NULL pD2C1 pD2C2 TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); if ( TopVar2 == pD1C1->iVar ) { if ( pD2C1->iVar >= pD2C2->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD2C1 = pD2C1->pHNext; } else if ( TopVar2 < pD1C1->iVar ) { if ( pD2C1->iVar != pD2C2->iVar ) return 0; pD2C1 = pD2C1->pHNext; pD2C2 = pD2C2->pHNext; } else return 0; break; case 12: // 11 -- pD1C1 pD1C2 NULL NULL if ( pD1C1->iVar != pD1C2->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD1C2 = pD1C2->pHNext; break; case 13: // 11 -1 pD1C1 pD1C2 NULL pD2C2 TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); if ( TopVar1 == pD2C2->iVar ) { if ( pD1C1->iVar <= pD1C2->iVar ) return 0; pD1C2 = pD1C2->pHNext; pD2C2 = pD2C2->pHNext; } else if ( TopVar1 < pD2C2->iVar ) { if ( pD1C1->iVar != pD1C2->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD1C2 = pD1C2->pHNext; } else return 0; break; case 14: // 11 1- pD1C1 pD1C2 pD2C1 NULL TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); if ( TopVar1 == pD2C1->iVar ) { if ( pD1C1->iVar >= pD1C2->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD2C1 = pD2C1->pHNext; } else if ( TopVar1 < pD2C1->iVar ) { if ( pD1C1->iVar != pD1C2->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD1C2 = pD1C2->pHNext; } else return 0; break; case 15: // 11 11 pD1C1 pD1C2 pD2C1 pD2C2 TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); if ( TopVar1 == TopVar2 ) { if ( pD1C1->iVar == pD1C2->iVar ) { if ( pD2C1->iVar != pD2C2->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD1C2 = pD1C2->pHNext; pD2C1 = pD2C1->pHNext; pD2C2 = pD2C2->pHNext; } else { if ( pD2C1->iVar == pD2C2->iVar ) return 0; if ( pD1C1->iVar < pD1C2->iVar ) { if ( pD2C1->iVar > pD2C2->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD2C1 = pD2C1->pHNext; } else { if ( pD2C1->iVar < pD2C2->iVar ) return 0; pD1C2 = pD1C2->pHNext; pD2C2 = pD2C2->pHNext; } } } else if ( TopVar1 < TopVar2 ) { if ( pD1C1->iVar != pD1C2->iVar ) return 0; pD1C1 = pD1C1->pHNext; pD1C2 = pD1C2->pHNext; } else { if ( pD2C1->iVar != pD2C2->iVar ) return 0; pD2C1 = pD2C1->pHNext; pD2C2 = pD2C2->pHNext; } break; default: assert( 0 ); break; } Code = pD1C1? 8: 0; Code |= pD1C2? 4: 0; Code |= pD2C1? 2: 0; Code |= pD2C2? 1: 0; } return 1; } /**Function************************************************************* Synopsis [Allocates the storage for cubes pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes ) { int k; // assert( pVar->nCubes == 0 ); pVar->nCubes = nCubes; // allocate memory for all the pairs pVar->ppPairs = ABC_ALLOC( Fxu_Pair **, nCubes ); pVar->ppPairs[0] = ABC_ALLOC( Fxu_Pair *, nCubes * nCubes ); memset( pVar->ppPairs[0], 0, sizeof(Fxu_Pair *) * nCubes * nCubes ); for ( k = 1; k < nCubes; k++ ) pVar->ppPairs[k] = pVar->ppPairs[k-1] + nCubes; } /**Function************************************************************* Synopsis [Clears all pairs associated with this cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_PairClearStorage( Fxu_Cube * pCube ) { Fxu_Var * pVar; int i; pVar = pCube->pVar; for ( i = 0; i < pVar->nCubes; i++ ) { pVar->ppPairs[pCube->iCube][i] = NULL; pVar->ppPairs[i][pCube->iCube] = NULL; } } /**Function************************************************************* Synopsis [Clears all pairs associated with this cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_PairFreeStorage( Fxu_Var * pVar ) { if ( pVar->ppPairs ) { ABC_FREE( pVar->ppPairs[0] ); ABC_FREE( pVar->ppPairs ); } } /**Function************************************************************* Synopsis [Adds the pair to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ) { Fxu_Pair * pPair; assert( pCube1->pVar == pCube2->pVar ); pPair = MEM_ALLOC_FXU( p, Fxu_Pair, 1 ); memset( pPair, 0, sizeof(Fxu_Pair) ); pPair->pCube1 = pCube1; pPair->pCube2 = pCube2; pPair->iCube1 = pCube1->iCube; pPair->iCube2 = pCube2->iCube; return pPair; } /**Function************************************************************* Synopsis [Adds the pair to storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_PairAdd( Fxu_Pair * pPair ) { Fxu_Var * pVar; pVar = pPair->pCube1->pVar; assert( pVar == pPair->pCube2->pVar ); pVar->ppPairs[pPair->iCube1][pPair->iCube2] = pPair; pVar->ppPairs[pPair->iCube2][pPair->iCube1] = pPair; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuPrint.c000066400000000000000000000130411300674244400234220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuPrint.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Various printing procedures.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuPrint.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p ) { Fxu_Var * pVar; Fxu_Cube * pCube; Fxu_Double * pDiv; Fxu_Single * pSingle; Fxu_Lit * pLit; Fxu_Pair * pPair; int i, LastNum; int fStdout; fStdout = 1; if ( pFile == NULL ) { pFile = fopen( "matrix.txt", "w" ); fStdout = 0; } fprintf( pFile, "Matrix has %d vars, %d cubes, %d literals, %d divisors.\n", p->lVars.nItems, p->lCubes.nItems, p->nEntries, p->nDivs ); fprintf( pFile, "Divisors selected so far: single = %d, double = %d.\n", p->nDivs1, p->nDivs2 ); fprintf( pFile, "\n" ); // print the numbers on top of the matrix for ( i = 0; i < 12; i++ ) fprintf( pFile, " " ); Fxu_MatrixForEachVariable( p, pVar ) fprintf( pFile, "%d", pVar->iVar % 10 ); fprintf( pFile, "\n" ); // print the rows Fxu_MatrixForEachCube( p, pCube ) { fprintf( pFile, "%4d", pCube->iCube ); fprintf( pFile, " " ); fprintf( pFile, "%4d", pCube->pVar->iVar ); fprintf( pFile, " " ); // print the literals LastNum = -1; Fxu_CubeForEachLiteral( pCube, pLit ) { for ( i = LastNum + 1; i < pLit->pVar->iVar; i++ ) fprintf( pFile, "." ); fprintf( pFile, "1" ); LastNum = i; } for ( i = LastNum + 1; i < p->lVars.nItems; i++ ) fprintf( pFile, "." ); fprintf( pFile, "\n" ); } fprintf( pFile, "\n" ); // print the double-cube divisors fprintf( pFile, "The double divisors are:\n" ); Fxu_MatrixForEachDouble( p, pDiv, i ) { fprintf( pFile, "Divisor #%3d (lit=%d,%d) (w=%2d): ", pDiv->Num, pDiv->lPairs.pHead->nLits1, pDiv->lPairs.pHead->nLits2, pDiv->Weight ); Fxu_DoubleForEachPair( pDiv, pPair ) fprintf( pFile, " <%d, %d> (b=%d)", pPair->pCube1->iCube, pPair->pCube2->iCube, pPair->nBase ); fprintf( pFile, "\n" ); } fprintf( pFile, "\n" ); // print the divisors associated with each cube fprintf( pFile, "The cubes are:\n" ); Fxu_MatrixForEachCube( p, pCube ) { fprintf( pFile, "Cube #%3d: ", pCube->iCube ); if ( pCube->pVar->ppPairs ) { Fxu_CubeForEachPair( pCube, pPair, i ) fprintf( pFile, " <%d %d> (d=%d) (b=%d)", pPair->iCube1, pPair->iCube2, pPair->pDiv->Num, pPair->nBase ); } fprintf( pFile, "\n" ); } fprintf( pFile, "\n" ); // print the single-cube divisors fprintf( pFile, "The single divisors are:\n" ); Fxu_MatrixForEachSingle( p, pSingle ) { fprintf( pFile, "Single-cube divisor #%5d: Var1 = %4d. Var2 = %4d. Weight = %2d\n", pSingle->Num, pSingle->pVar1->iVar, pSingle->pVar2->iVar, pSingle->Weight ); } fprintf( pFile, "\n" ); /* { int Index; fprintf( pFile, "Distribution of divisors in the hash table:\n" ); for ( Index = 0; Index < p->nTableSize; Index++ ) fprintf( pFile, " %d", p->pTable[Index].nItems ); fprintf( pFile, "\n" ); } */ if ( !fStdout ) fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p ) { Fxu_Double * pDiv; int WeightMax; int * pProfile; int Counter1; // the number of -1 weight int CounterL; // the number of less than -1 weight int i; WeightMax = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); pProfile = ABC_ALLOC( int, (WeightMax + 1) ); memset( pProfile, 0, sizeof(int) * (WeightMax + 1) ); Counter1 = 0; CounterL = 0; Fxu_MatrixForEachDouble( p, pDiv, i ) { assert( pDiv->Weight <= WeightMax ); if ( pDiv->Weight == -1 ) Counter1++; else if ( pDiv->Weight < 0 ) CounterL++; else pProfile[ pDiv->Weight ]++; } fprintf( pFile, "The double divisors profile:\n" ); fprintf( pFile, "Weight < -1 divisors = %6d\n", CounterL ); fprintf( pFile, "Weight -1 divisors = %6d\n", Counter1 ); for ( i = 0; i <= WeightMax; i++ ) if ( pProfile[i] ) fprintf( pFile, "Weight %3d divisors = %6d\n", i, pProfile[i] ); fprintf( pFile, "End of divisor profile printout\n" ); ABC_FREE( pProfile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuReduce.c000066400000000000000000000165271300674244400235510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuReduce.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Procedures to reduce the number of considered cube pairs.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuReduce.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "fxuInt.h" #include "fxu.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Precomputes the pairs to use for creating two-cube divisors.] Description [This procedure takes the matrix with variables and cubes allocated (p), the original covers of the nodes (i-sets) and their number (ppCovers,nCovers). The maximum number of pairs to compute and the total number of pairs in existence. This procedure adds to the storage of divisors exactly the given number of pairs (nPairsMax) while taking first those pairs that have the smallest number of literals in their cube-free form.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax ) { unsigned char * pnLitsDiff; // storage for the counters of diff literals int * pnPairCounters; // the counters of pairs for each number of diff literals Fxu_Cube * pCubeFirst, * pCubeLast; Fxu_Cube * pCube1, * pCube2; Fxu_Var * pVar; int nCubes, nBitsMax, nSum; int CutOffNum = -1, CutOffQuant = -1; // Suppress "might be used uninitialized" int iPair, iQuant, k, c; // abctime clk = Abc_Clock(); char * pSopCover; int nFanins; assert( nPairsMax < nPairsTotal ); // allocate storage for counter of diffs pnLitsDiff = ABC_FALLOC( unsigned char, nPairsTotal ); // go through the covers and precompute the distances between the pairs iPair = 0; nBitsMax = -1; for ( c = 0; c < vCovers->nSize; c++ ) if ( (pSopCover = (char *)vCovers->pArray[c]) ) { nFanins = Abc_SopGetVarNum(pSopCover); // precompute the differences Fxu_CountPairDiffs( pSopCover, pnLitsDiff + iPair ); // update the counter nCubes = Abc_SopGetCubeNum( pSopCover ); iPair += nCubes * (nCubes - 1) / 2; if ( nBitsMax < nFanins ) nBitsMax = nFanins; } assert( iPair == nPairsTotal ); // allocate storage for counters of cube pairs by difference pnPairCounters = ABC_FALLOC( int, 2 * nBitsMax ); memset( pnPairCounters, 0, sizeof(int) * 2 * nBitsMax ); // count the number of different pairs for ( k = 0; k < nPairsTotal; k++ ) pnPairCounters[ pnLitsDiff[k] ]++; // determine what pairs to take starting from the lower // so that there would be exactly pPairsMax pairs if ( pnPairCounters[0] != 0 ) { ABC_FREE( pnLitsDiff ); ABC_FREE( pnPairCounters ); printf( "The SOPs of the nodes contain duplicated cubes. Run \"bdd; sop\" before \"fx\".\n" ); return 0; } if ( pnPairCounters[1] != 0 ) { ABC_FREE( pnLitsDiff ); ABC_FREE( pnPairCounters ); printf( "The SOPs of the nodes are not SCC-free. Run \"bdd; sop\" before \"fx\".\n" ); return 0; } assert( pnPairCounters[0] == 0 ); // otherwise, covers are not dup-free assert( pnPairCounters[1] == 0 ); // otherwise, covers are not SCC-free nSum = 0; for ( k = 0; k < 2 * nBitsMax; k++ ) { nSum += pnPairCounters[k]; if ( nSum >= nPairsMax ) { CutOffNum = k; CutOffQuant = pnPairCounters[k] - (nSum - nPairsMax); break; } } ABC_FREE( pnPairCounters ); // set to 0 all the pairs above the cut-off number and quantity iQuant = 0; iPair = 0; for ( k = 0; k < nPairsTotal; k++ ) if ( pnLitsDiff[k] > CutOffNum ) pnLitsDiff[k] = 0; else if ( pnLitsDiff[k] == CutOffNum ) { if ( iQuant++ >= CutOffQuant ) pnLitsDiff[k] = 0; else iPair++; } else iPair++; assert( iPair == nPairsMax ); // collect the corresponding pairs and add the divisors iPair = 0; for ( c = 0; c < vCovers->nSize; c++ ) if ( (pSopCover = (char *)vCovers->pArray[c]) ) { // get the var pVar = p->ppVars[2*c+1]; // get the first cube pCubeFirst = pVar->pFirst; // get the last cube pCubeLast = pCubeFirst; for ( k = 0; k < pVar->nCubes; k++ ) pCubeLast = pCubeLast->pNext; assert( pCubeLast == NULL || pCubeLast->pVar != pVar ); // go through the cube pairs for ( pCube1 = pCubeFirst; pCube1 != pCubeLast; pCube1 = pCube1->pNext ) for ( pCube2 = pCube1->pNext; pCube2 != pCubeLast; pCube2 = pCube2->pNext ) if ( pnLitsDiff[iPair++] ) { // create the divisors for this pair Fxu_MatrixAddDivisor( p, pCube1, pCube2 ); } } assert( iPair == nPairsTotal ); ABC_FREE( pnLitsDiff ); //ABC_PRT( "Preprocess", Abc_Clock() - clk ); return 1; } /**Function************************************************************* Synopsis [Counts the differences in each cube pair in the cover.] Description [Takes the cover (pCover) and the array where the diff counters go (pDiffs). The array pDiffs should have as many entries as there are different pairs of cubes in the cover: n(n-1)/2. Fills out the array pDiffs with the following info: For each cube pair, included in the array is the number of literals in both cubes after they are made cube free.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] ) { char * pCube1, * pCube2; int nOnes, nCubePairs, nFanins, v; nCubePairs = 0; nFanins = Abc_SopGetVarNum(pCover); Abc_SopForEachCube( pCover, nFanins, pCube1 ) Abc_SopForEachCube( pCube1, nFanins, pCube2 ) { if ( pCube1 == pCube2 ) continue; nOnes = 0; for ( v = 0; v < nFanins; v++ ) nOnes += (pCube1[v] != pCube2[v]); pDiffs[nCubePairs++] = nOnes; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuSelect.c000066400000000000000000000416421300674244400235550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuSelect.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Procedures to select the best divisor/complement pair.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuSelect.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define MAX_SIZE_LOOKAHEAD 20 static int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar ); static Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); static Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble ); static Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble ); Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ); void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Selects the best pair (Single,Double) and returns their weight.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble ) { // the top entries Fxu_Single * pSingles[MAX_SIZE_LOOKAHEAD] = {0}; Fxu_Double * pDoubles[MAX_SIZE_LOOKAHEAD] = {0}; // the complements Fxu_Double * pSCompl[MAX_SIZE_LOOKAHEAD] = {0}; Fxu_Single * pDComplS[MAX_SIZE_LOOKAHEAD] = {0}; Fxu_Double * pDComplD[MAX_SIZE_LOOKAHEAD] = {0}; Fxu_Pair * pPair; int nSingles; int nDoubles; int i; int WeightBest; int WeightCur; int iNum, fBestS; // collect the top entries from the queues for ( nSingles = 0; nSingles < MAX_SIZE_LOOKAHEAD; nSingles++ ) { pSingles[nSingles] = Fxu_HeapSingleGetMax( p->pHeapSingle ); if ( pSingles[nSingles] == NULL ) break; } // put them back into the queue for ( i = 0; i < nSingles; i++ ) if ( pSingles[i] ) Fxu_HeapSingleInsert( p->pHeapSingle, pSingles[i] ); // the same for doubles // collect the top entries from the queues for ( nDoubles = 0; nDoubles < MAX_SIZE_LOOKAHEAD; nDoubles++ ) { pDoubles[nDoubles] = Fxu_HeapDoubleGetMax( p->pHeapDouble ); if ( pDoubles[nDoubles] == NULL ) break; } // put them back into the queue for ( i = 0; i < nDoubles; i++ ) if ( pDoubles[i] ) Fxu_HeapDoubleInsert( p->pHeapDouble, pDoubles[i] ); // for each single, find the complement double (if any) for ( i = 0; i < nSingles; i++ ) if ( pSingles[i] ) pSCompl[i] = Fxu_MatrixFindComplementSingle( p, pSingles[i] ); // for each double, find the complement single or double (if any) for ( i = 0; i < nDoubles; i++ ) if ( pDoubles[i] ) { pPair = pDoubles[i]->lPairs.pHead; if ( pPair->nLits1 == 1 && pPair->nLits2 == 1 ) { pDComplS[i] = Fxu_MatrixFindComplementDouble2( p, pDoubles[i] ); pDComplD[i] = NULL; } // else if ( pPair->nLits1 == 2 && pPair->nLits2 == 2 ) // { // pDComplS[i] = NULL; // pDComplD[i] = Fxu_MatrixFindComplementDouble4( p, pDoubles[i] ); // } else { pDComplS[i] = NULL; pDComplD[i] = NULL; } } // select the best pair WeightBest = -1; for ( i = 0; i < nSingles; i++ ) { WeightCur = pSingles[i]->Weight; if ( pSCompl[i] ) { // add the weight of the double WeightCur += pSCompl[i]->Weight; // there is no need to implement this double, so... pPair = pSCompl[i]->lPairs.pHead; WeightCur += pPair->nLits1 + pPair->nLits2; } if ( WeightBest < WeightCur ) { WeightBest = WeightCur; *ppSingle = pSingles[i]; *ppDouble = pSCompl[i]; fBestS = 1; iNum = i; } } for ( i = 0; i < nDoubles; i++ ) { WeightCur = pDoubles[i]->Weight; if ( pDComplS[i] ) { // add the weight of the single WeightCur += pDComplS[i]->Weight; // there is no need to implement this double, so... pPair = pDoubles[i]->lPairs.pHead; WeightCur += pPair->nLits1 + pPair->nLits2; } if ( WeightBest < WeightCur ) { WeightBest = WeightCur; *ppSingle = pDComplS[i]; *ppDouble = pDoubles[i]; fBestS = 0; iNum = i; } } /* // print the statistics printf( "\n" ); for ( i = 0; i < nSingles; i++ ) { printf( "Single #%d: Weight = %3d. ", i, pSingles[i]->Weight ); printf( "Compl: " ); if ( pSCompl[i] == NULL ) printf( "None." ); else printf( "D Weight = %3d Sum = %3d", pSCompl[i]->Weight, pSCompl[i]->Weight + pSingles[i]->Weight ); printf( "\n" ); } printf( "\n" ); for ( i = 0; i < nDoubles; i++ ) { printf( "Double #%d: Weight = %3d. ", i, pDoubles[i]->Weight ); printf( "Compl: " ); if ( pDComplS[i] == NULL && pDComplD[i] == NULL ) printf( "None." ); else if ( pDComplS[i] ) printf( "S Weight = %3d Sum = %3d", pDComplS[i]->Weight, pDComplS[i]->Weight + pDoubles[i]->Weight ); else if ( pDComplD[i] ) printf( "D Weight = %3d Sum = %3d", pDComplD[i]->Weight, pDComplD[i]->Weight + pDoubles[i]->Weight ); printf( "\n" ); } if ( WeightBest == -1 ) printf( "Selected NONE\n" ); else { printf( "Selected = %s. ", fBestS? "S": "D" ); printf( "Number = %d. ", iNum ); printf( "Weight = %d.\n", WeightBest ); } printf( "\n" ); */ return WeightBest; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle ) { // int * pValue2Node = p->pValue2Node; int iVar1, iVar2; int iVar1C, iVar2C; // get the variables of this single div iVar1 = pSingle->pVar1->iVar; iVar2 = pSingle->pVar2->iVar; iVar1C = Fxu_MatrixFindComplement( p, iVar1 ); iVar2C = Fxu_MatrixFindComplement( p, iVar2 ); if ( iVar1C == -1 || iVar2C == -1 ) return NULL; assert( iVar1C < iVar2C ); return Fxu_MatrixFindDouble( p, &iVar1C, &iVar2C, 1, 1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble ) { // int * pValue2Node = p->pValue2Node; int piVarsC1[10], piVarsC2[10]; int nVarsC1, nVarsC2; int iVar1, iVar2, iVarTemp; int iVar1C, iVar2C; Fxu_Single * pSingle; // get the variables of this double div Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); assert( nVarsC1 == 1 ); assert( nVarsC2 == 1 ); iVar1 = piVarsC1[0]; iVar2 = piVarsC2[0]; assert( iVar1 < iVar2 ); iVar1C = Fxu_MatrixFindComplement( p, iVar1 ); iVar2C = Fxu_MatrixFindComplement( p, iVar2 ); if ( iVar1C == -1 || iVar2C == -1 ) return NULL; // go through the queque and find this one // assert( iVar1C < iVar2C ); if ( iVar1C > iVar2C ) { iVarTemp = iVar1C; iVar1C = iVar2C; iVar2C = iVarTemp; } Fxu_MatrixForEachSingle( p, pSingle ) if ( pSingle->pVar1->iVar == iVar1C && pSingle->pVar2->iVar == iVar2C ) return pSingle; return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble ) { // int * pValue2Node = p->pValue2Node; int piVarsC1[10], piVarsC2[10]; int nVarsC1, nVarsC2; int iVar11, iVar12, iVar21, iVar22; int iVar11C, iVar12C, iVar21C, iVar22C; int RetValue; // get the variables of this double div Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); assert( nVarsC1 == 2 && nVarsC2 == 2 ); iVar11 = piVarsC1[0]; iVar12 = piVarsC1[1]; iVar21 = piVarsC2[0]; iVar22 = piVarsC2[1]; assert( iVar11 < iVar21 ); iVar11C = Fxu_MatrixFindComplement( p, iVar11 ); iVar12C = Fxu_MatrixFindComplement( p, iVar12 ); iVar21C = Fxu_MatrixFindComplement( p, iVar21 ); iVar22C = Fxu_MatrixFindComplement( p, iVar22 ); if ( iVar11C == -1 || iVar12C == -1 || iVar21C == -1 || iVar22C == -1 ) return NULL; if ( iVar11C != iVar21 || iVar12C != iVar22 || iVar21C != iVar11 || iVar22C != iVar12 ) return NULL; // a'b' + ab => a'b + ab' // a'b + ab' => a'b' + ab // swap the second pair in each cube RetValue = piVarsC1[1]; piVarsC1[1] = piVarsC2[1]; piVarsC2[1] = RetValue; return Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, 2, 2 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar ) { return iVar ^ 1; /* // int * pValue2Node = p->pValue2Node; int iVarC; int iNode; int Beg, End; // get the nodes iNode = pValue2Node[iVar]; // get the first node with the same var for ( Beg = iVar; Beg >= 0; Beg-- ) if ( pValue2Node[Beg] != iNode ) { Beg++; break; } // get the last node with the same var for ( End = iVar; ; End++ ) if ( pValue2Node[End] != iNode ) { End--; break; } // if one of the vars is not binary, quit if ( End - Beg > 1 ) return -1; // get the complements if ( iVar == Beg ) iVarC = End; else if ( iVar == End ) iVarC = Beg; else { assert( 0 ); } return iVarC; */ } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 ) { Fxu_Pair * pPair; Fxu_Lit * pLit1, * pLit2; int nLits1, nLits2; // get the first pair pPair = pDouble->lPairs.pHead; // init the parameters nLits1 = 0; nLits2 = 0; pLit1 = pPair->pCube1->lLits.pHead; pLit2 = pPair->pCube2->lLits.pHead; while ( 1 ) { if ( pLit1 && pLit2 ) { if ( pLit1->iVar == pLit2->iVar ) { // ensure cube-free pLit1 = pLit1->pHNext; pLit2 = pLit2->pHNext; } else if ( pLit1->iVar < pLit2->iVar ) { piVarsC1[nLits1++] = pLit1->iVar; pLit1 = pLit1->pHNext; } else { piVarsC2[nLits2++] = pLit2->iVar; pLit2 = pLit2->pHNext; } } else if ( pLit1 && !pLit2 ) { piVarsC1[nLits1++] = pLit1->iVar; pLit1 = pLit1->pHNext; } else if ( !pLit1 && pLit2 ) { piVarsC2[nLits2++] = pLit2->iVar; pLit2 = pLit2->pHNext; } else break; } *pnVarsC1 = nLits1; *pnVarsC2 = nLits2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ) { int piVarsC1_[100], piVarsC2_[100]; int nVarsC1_, nVarsC2_, i; Fxu_Double * pDouble; Fxu_Pair * pPair; unsigned Key; assert( nVarsC1 > 0 ); assert( nVarsC2 > 0 ); assert( piVarsC1[0] < piVarsC2[0] ); // get the hash key Key = Fxu_PairHashKeyArray( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 ); // check if the divisor for this pair already exists Key %= p->nTableSize; Fxu_TableForEachDouble( p, Key, pDouble ) { pPair = pDouble->lPairs.pHead; if ( pPair->nLits1 != nVarsC1 ) continue; if ( pPair->nLits2 != nVarsC2 ) continue; // get the cubes of this divisor Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1_, piVarsC2_, &nVarsC1_, &nVarsC2_ ); // compare lits of the first cube for ( i = 0; i < nVarsC1; i++ ) if ( piVarsC1[i] != piVarsC1_[i] ) break; if ( i != nVarsC1 ) continue; // compare lits of the second cube for ( i = 0; i < nVarsC2; i++ ) if ( piVarsC2[i] != piVarsC2_[i] ) break; if ( i != nVarsC2 ) continue; return pDouble; } return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_SelectSCD( Fxu_Matrix * p, int WeightLimit, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 ) { // int * pValue2Node = p->pValue2Node; Fxu_Var * pVar1; Fxu_Var * pVar2, * pVarTemp; Fxu_Lit * pLitV, * pLitH; int Coin; int CounterAll; int CounterTest; int WeightCur; int WeightBest; CounterAll = 0; CounterTest = 0; WeightBest = -10; // iterate through the columns in the matrix Fxu_MatrixForEachVariable( p, pVar1 ) { // start collecting the affected vars Fxu_MatrixRingVarsStart( p ); // go through all the literals of this variable for ( pLitV = pVar1->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) { // for this literal, go through all the horizontal literals for ( pLitH = pLitV->pHNext; pLitH; pLitH = pLitH->pHNext ) { // get another variable pVar2 = pLitH->pVar; CounterAll++; // skip the var if it is already used if ( pVar2->pOrder ) continue; // skip the var if it belongs to the same node // if ( pValue2Node[pVar1->iVar] == pValue2Node[pVar2->iVar] ) // continue; // collect the var Fxu_MatrixRingVarsAdd( p, pVar2 ); } } // stop collecting the selected vars Fxu_MatrixRingVarsStop( p ); // iterate through the selected vars Fxu_MatrixForEachVarInRing( p, pVar2 ) { CounterTest++; // count the coincidence Coin = Fxu_SingleCountCoincidence( p, pVar1, pVar2 ); assert( Coin > 0 ); // get the new weight WeightCur = Coin - 2; // compare the weights if ( WeightBest < WeightCur ) { WeightBest = WeightCur; *ppVar1 = pVar1; *ppVar2 = pVar2; } } // unmark the vars Fxu_MatrixForEachVarInRingSafe( p, pVar2, pVarTemp ) pVar2->pOrder = NULL; Fxu_MatrixRingVarsReset( p ); } // if ( WeightBest == WeightLimit ) // return -1; return WeightBest; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuSingle.c000066400000000000000000000221271300674244400235540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuSingle.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Procedures to compute the set of single-cube divisors.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuSingle.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" #include "misc/vec/vec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes and adds all single-cube divisors to storage.] Description [This procedure should be called once when the matrix is already contructed before the process of logic extraction begins..] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax ) { Fxu_Var * pVar; Vec_Ptr_t * vSingles; int i, k; // set the weight limit p->nWeightLimit = 1 - fUse0; // iterate through columns in the matrix and collect single-cube divisors vSingles = Vec_PtrAlloc( 10000 ); Fxu_MatrixForEachVariable( p, pVar ) Fxu_MatrixComputeSinglesOneCollect( p, pVar, vSingles ); p->nSingleTotal = Vec_PtrSize(vSingles) / 3; // check if divisors should be filtered if ( Vec_PtrSize(vSingles) > nSingleMax ) { int * pWeigtCounts, nDivCount, Weight, i, c;; assert( Vec_PtrSize(vSingles) % 3 == 0 ); // count how many divisors have the given weight pWeigtCounts = ABC_ALLOC( int, 1000 ); memset( pWeigtCounts, 0, sizeof(int) * 1000 ); for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 ) { Weight = (int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles, i); if ( Weight >= 999 ) pWeigtCounts[999]++; else pWeigtCounts[Weight]++; } // select the bound on the weight (above this bound, singles will be included) nDivCount = 0; for ( c = 999; c >= 0; c-- ) { nDivCount += pWeigtCounts[c]; if ( nDivCount >= nSingleMax ) break; } ABC_FREE( pWeigtCounts ); // collect singles with the given costs k = 0; for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 ) { Weight = (int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles, i); if ( Weight < c ) continue; Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-2) ); Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-1) ); Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i) ); if ( k/3 == nSingleMax ) break; } Vec_PtrShrink( vSingles, k ); // adjust the weight limit p->nWeightLimit = c; } // collect the selected divisors assert( Vec_PtrSize(vSingles) % 3 == 0 ); for ( i = 0; i < Vec_PtrSize(vSingles); i += 3 ) { Fxu_MatrixAddSingle( p, (Fxu_Var *)Vec_PtrEntry(vSingles,i), (Fxu_Var *)Vec_PtrEntry(vSingles,i+1), (int)(ABC_PTRUINT_T)Vec_PtrEntry(vSingles,i+2) ); } Vec_PtrFree( vSingles ); } /**Function************************************************************* Synopsis [Adds the single-cube divisors associated with a new column.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles ) { Fxu_Lit * pLitV, * pLitH; Fxu_Var * pVar2; int Coin; int WeightCur; // start collecting the affected vars Fxu_MatrixRingVarsStart( p ); // go through all the literals of this variable for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) // for this literal, go through all the horizontal literals for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev ) { // get another variable pVar2 = pLitH->pVar; // skip the var if it is already used if ( pVar2->pOrder ) continue; // skip the var if it belongs to the same node // if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] ) // continue; // collect the var Fxu_MatrixRingVarsAdd( p, pVar2 ); } // stop collecting the selected vars Fxu_MatrixRingVarsStop( p ); // iterate through the selected vars Fxu_MatrixForEachVarInRing( p, pVar2 ) { // count the coincidence Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar ); assert( Coin > 0 ); // get the new weight WeightCur = Coin - 2; // peformance fix (August 24, 2007) if ( WeightCur >= p->nWeightLimit ) { Vec_PtrPush( vSingles, pVar2 ); Vec_PtrPush( vSingles, pVar ); Vec_PtrPush( vSingles, (void *)(ABC_PTRUINT_T)WeightCur ); } } // unmark the vars Fxu_MatrixRingVarsUnmark( p ); } /**Function************************************************************* Synopsis [Adds the single-cube divisors associated with a new column.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ) { Fxu_Lit * pLitV, * pLitH; Fxu_Var * pVar2; int Coin; int WeightCur; // start collecting the affected vars Fxu_MatrixRingVarsStart( p ); // go through all the literals of this variable for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) // for this literal, go through all the horizontal literals for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev ) { // get another variable pVar2 = pLitH->pVar; // skip the var if it is already used if ( pVar2->pOrder ) continue; // skip the var if it belongs to the same node // if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] ) // continue; // collect the var Fxu_MatrixRingVarsAdd( p, pVar2 ); } // stop collecting the selected vars Fxu_MatrixRingVarsStop( p ); // iterate through the selected vars Fxu_MatrixForEachVarInRing( p, pVar2 ) { // count the coincidence Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar ); assert( Coin > 0 ); // get the new weight WeightCur = Coin - 2; // peformance fix (August 24, 2007) // if ( WeightCur >= 0 ) // Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur ); if ( WeightCur >= p->nWeightLimit ) Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur ); } // unmark the vars Fxu_MatrixRingVarsUnmark( p ); } /**Function************************************************************* Synopsis [Computes the coincidence count of two columns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 ) { Fxu_Lit * pLit1, * pLit2; int Result; // compute the coincidence count Result = 0; pLit1 = pVar1->lLits.pHead; pLit2 = pVar2->lLits.pHead; while ( 1 ) { if ( pLit1 && pLit2 ) { if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar ) { // the variables are the same if ( pLit1->iCube == pLit2->iCube ) { // the literals are the same pLit1 = pLit1->pVNext; pLit2 = pLit2->pVNext; // add this literal to the coincidence Result++; } else if ( pLit1->iCube < pLit2->iCube ) pLit1 = pLit1->pVNext; else pLit2 = pLit2->pVNext; } else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar ) pLit1 = pLit1->pVNext; else pLit2 = pLit2->pVNext; } else if ( pLit1 && !pLit2 ) pLit1 = pLit1->pVNext; else if ( !pLit1 && pLit2 ) pLit2 = pLit2->pVNext; else break; } return Result; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/fxuUpdate.c000066400000000000000000000615611300674244400235620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fxuUpdate.c] PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] Synopsis [Updating the sparse matrix when divisors are accepted.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fxuUpdate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fxuInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar ); static void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv ); static void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem ); static void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew ); static void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes ); static int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 ); static void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble ); static void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube ); static void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube ); static void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p ); static void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Updates the matrix after selecting two divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble ) { Fxu_Cube * pCube, * pCubeNew; Fxu_Var * pVarC, * pVarD; Fxu_Var * pVar1, * pVar2; // consider trivial cases if ( pSingle == NULL ) { assert( pDouble->Weight == Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ) ); Fxu_UpdateDouble( p ); return; } if ( pDouble == NULL ) { assert( pSingle->Weight == Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ) ); Fxu_UpdateSingle( p ); return; } // get the variables of the single pVar1 = pSingle->pVar1; pVar2 = pSingle->pVar2; // remove the best double from the heap Fxu_HeapDoubleDelete( p->pHeapDouble, pDouble ); // remove the best divisor from the table Fxu_ListTableDelDivisor( p, pDouble ); // create two new columns (vars) Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 ); // create one new row (cube) pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 ); pCubeNew->pFirst = pCubeNew; // set the first cube of the positive var pVarD->pFirst = pCubeNew; // start collecting the affected vars and cubes Fxu_MatrixRingCubesStart( p ); Fxu_MatrixRingVarsStart( p ); // add the vars Fxu_MatrixRingVarsAdd( p, pVar1 ); Fxu_MatrixRingVarsAdd( p, pVar2 ); // remove the literals and collect the affected cubes // remove the divisors associated with this cube // add to the affected cube the literal corresponding to the new column Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD ); // replace each two cubes of the pair by one new cube // the new cube contains the base and the new literal Fxu_UpdateDoublePairs( p, pDouble, pVarC ); // stop collecting the affected vars and cubes Fxu_MatrixRingCubesStop( p ); Fxu_MatrixRingVarsStop( p ); // add the literals to the new cube assert( pVar1->iVar < pVar2->iVar ); assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 ); Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 ); Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 ); // create new doubles; we cannot add them in the same loop // because we first have to create *all* new cubes for each node Fxu_MatrixForEachCubeInRing( p, pCube ) Fxu_UpdateAddNewDoubles( p, pCube ); // update the singles after removing some literals Fxu_UpdateCleanOldSingles( p ); // undo the temporary rings with cubes and vars Fxu_MatrixRingCubesUnmark( p ); Fxu_MatrixRingVarsUnmark( p ); // we should undo the rings before creating new singles // create new singles Fxu_UpdateAddNewSingles( p, pVarC ); Fxu_UpdateAddNewSingles( p, pVarD ); // recycle the divisor MEM_FREE_FXU( p, Fxu_Double, 1, pDouble ); p->nDivs3++; } /**Function************************************************************* Synopsis [Updates after accepting single cube divisor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateSingle( Fxu_Matrix * p ) { Fxu_Single * pSingle; Fxu_Cube * pCube, * pCubeNew; Fxu_Var * pVarC, * pVarD; Fxu_Var * pVar1, * pVar2; // read the best divisor from the heap pSingle = Fxu_HeapSingleReadMax( p->pHeapSingle ); // get the variables of this single-cube divisor pVar1 = pSingle->pVar1; pVar2 = pSingle->pVar2; // create two new columns (vars) Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 ); // create one new row (cube) pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 ); pCubeNew->pFirst = pCubeNew; // set the first cube pVarD->pFirst = pCubeNew; // start collecting the affected vars and cubes Fxu_MatrixRingCubesStart( p ); Fxu_MatrixRingVarsStart( p ); // add the vars Fxu_MatrixRingVarsAdd( p, pVar1 ); Fxu_MatrixRingVarsAdd( p, pVar2 ); // remove the literals and collect the affected cubes // remove the divisors associated with this cube // add to the affected cube the literal corresponding to the new column Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD ); // stop collecting the affected vars and cubes Fxu_MatrixRingCubesStop( p ); Fxu_MatrixRingVarsStop( p ); // add the literals to the new cube assert( pVar1->iVar < pVar2->iVar ); assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 ); Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 ); Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 ); // create new doubles; we cannot add them in the same loop // because we first have to create *all* new cubes for each node Fxu_MatrixForEachCubeInRing( p, pCube ) Fxu_UpdateAddNewDoubles( p, pCube ); // update the singles after removing some literals Fxu_UpdateCleanOldSingles( p ); // we should undo the rings before creating new singles // unmark the cubes Fxu_MatrixRingCubesUnmark( p ); Fxu_MatrixRingVarsUnmark( p ); // create new singles Fxu_UpdateAddNewSingles( p, pVarC ); Fxu_UpdateAddNewSingles( p, pVarD ); p->nDivs1++; } /**Function************************************************************* Synopsis [Updates the matrix after accepting a double cube divisor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateDouble( Fxu_Matrix * p ) { Fxu_Double * pDiv; Fxu_Cube * pCube, * pCubeNew1, * pCubeNew2; Fxu_Var * pVarC, * pVarD; // remove the best divisor from the heap pDiv = Fxu_HeapDoubleGetMax( p->pHeapDouble ); // remove the best divisor from the table Fxu_ListTableDelDivisor( p, pDiv ); // create two new columns (vars) Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 2 ); // create two new rows (cubes) pCubeNew1 = Fxu_MatrixAddCube( p, pVarD, 0 ); pCubeNew1->pFirst = pCubeNew1; pCubeNew2 = Fxu_MatrixAddCube( p, pVarD, 1 ); pCubeNew2->pFirst = pCubeNew1; // set the first cube pVarD->pFirst = pCubeNew1; // add the literals to the new cubes Fxu_UpdateMatrixDoubleCreateCubes( p, pCubeNew1, pCubeNew2, pDiv ); // start collecting the affected cubes and vars Fxu_MatrixRingCubesStart( p ); Fxu_MatrixRingVarsStart( p ); // replace each two cubes of the pair by one new cube // the new cube contains the base and the new literal Fxu_UpdateDoublePairs( p, pDiv, pVarD ); // stop collecting the affected cubes and vars Fxu_MatrixRingCubesStop( p ); Fxu_MatrixRingVarsStop( p ); // create new doubles; we cannot add them in the same loop // because we first have to create *all* new cubes for each node Fxu_MatrixForEachCubeInRing( p, pCube ) Fxu_UpdateAddNewDoubles( p, pCube ); // update the singles after removing some literals Fxu_UpdateCleanOldSingles( p ); // undo the temporary rings with cubes and vars Fxu_MatrixRingCubesUnmark( p ); Fxu_MatrixRingVarsUnmark( p ); // we should undo the rings before creating new singles // create new singles Fxu_UpdateAddNewSingles( p, pVarC ); Fxu_UpdateAddNewSingles( p, pVarD ); // recycle the divisor MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); p->nDivs2++; } /**Function************************************************************* Synopsis [Update the pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar ) { Fxu_Pair * pPair; Fxu_Cube * pCubeUse, * pCubeRem; int i; // collect and sort the pairs Fxu_UpdatePairsSort( p, pDouble ); // for ( i = 0; i < p->nPairsTemp; i++ ) for ( i = 0; i < p->vPairs->nSize; i++ ) { // get the pair // pPair = p->pPairsTemp[i]; pPair = (Fxu_Pair *)p->vPairs->pArray[i]; // out of the two cubes, select the one which comes earlier pCubeUse = Fxu_PairMinCube( pPair ); pCubeRem = Fxu_PairMaxCube( pPair ); // collect the affected cube assert( pCubeUse->pOrder == NULL ); Fxu_MatrixRingCubesAdd( p, pCubeUse ); // remove some literals from pCubeUse and all literals from pCubeRem Fxu_UpdateMatrixDoubleClean( p, pCubeUse, pCubeRem ); // add a literal that depends on the new variable Fxu_MatrixAddLiteral( p, pCubeUse, pVar ); // check the literal count assert( pCubeUse->lLits.nItems == pPair->nBase + 1 ); assert( pCubeRem->lLits.nItems == 0 ); // update the divisors by removing useless pairs Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeUse ); Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeRem ); // remove the pair MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); } p->vPairs->nSize = 0; } /**Function************************************************************* Synopsis [Add two cubes corresponding to the given double-cube divisor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv ) { Fxu_Lit * pLit1, * pLit2; Fxu_Pair * pPair; int nBase, nLits1, nLits2; // fill in the SOP and copy the fanins nBase = nLits1 = nLits2 = 0; pPair = pDiv->lPairs.pHead; pLit1 = pPair->pCube1->lLits.pHead; pLit2 = pPair->pCube2->lLits.pHead; while ( 1 ) { if ( pLit1 && pLit2 ) { if ( pLit1->iVar == pLit2->iVar ) { // skip the cube free part pLit1 = pLit1->pHNext; pLit2 = pLit2->pHNext; nBase++; } else if ( pLit1->iVar < pLit2->iVar ) { // add literal to the first cube Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar ); // move to the next literal in this cube pLit1 = pLit1->pHNext; nLits1++; } else { // add literal to the second cube Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar ); // move to the next literal in this cube pLit2 = pLit2->pHNext; nLits2++; } } else if ( pLit1 && !pLit2 ) { // add literal to the first cube Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar ); // move to the next literal in this cube pLit1 = pLit1->pHNext; nLits1++; } else if ( !pLit1 && pLit2 ) { // add literal to the second cube Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar ); // move to the next literal in this cube pLit2 = pLit2->pHNext; nLits2++; } else break; } assert( pPair->nLits1 == nLits1 ); assert( pPair->nLits2 == nLits2 ); assert( pPair->nBase == nBase ); } /**Function************************************************************* Synopsis [Create the node equal to double-cube divisor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem ) { Fxu_Lit * pLit1, * bLit1Next; Fxu_Lit * pLit2, * bLit2Next; // initialize the starting literals pLit1 = pCubeUse->lLits.pHead; pLit2 = pCubeRem->lLits.pHead; bLit1Next = pLit1? pLit1->pHNext: NULL; bLit2Next = pLit2? pLit2->pHNext: NULL; // go through the pair and remove the literals in the base // from the first cube and all literals from the second cube while ( 1 ) { if ( pLit1 && pLit2 ) { if ( pLit1->iVar == pLit2->iVar ) { // this literal is present in both cubes - it belongs to the base // mark the affected var if ( pLit1->pVar->pOrder == NULL ) Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); // leave the base in pCubeUse; delete it from pCubeRem Fxu_MatrixDelLiteral( p, pLit2 ); // step to the next literals pLit1 = bLit1Next; pLit2 = bLit2Next; bLit1Next = pLit1? pLit1->pHNext: NULL; bLit2Next = pLit2? pLit2->pHNext: NULL; } else if ( pLit1->iVar < pLit2->iVar ) { // this literal is present in pCubeUse - remove it // mark the affected var if ( pLit1->pVar->pOrder == NULL ) Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); // delete this literal Fxu_MatrixDelLiteral( p, pLit1 ); // step to the next literals pLit1 = bLit1Next; bLit1Next = pLit1? pLit1->pHNext: NULL; } else { // this literal is present in pCubeRem - remove it // mark the affected var if ( pLit2->pVar->pOrder == NULL ) Fxu_MatrixRingVarsAdd( p, pLit2->pVar ); // delete this literal Fxu_MatrixDelLiteral( p, pLit2 ); // step to the next literals pLit2 = bLit2Next; bLit2Next = pLit2? pLit2->pHNext: NULL; } } else if ( pLit1 && !pLit2 ) { // this literal is present in pCubeUse - leave it // mark the affected var if ( pLit1->pVar->pOrder == NULL ) Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); // delete this literal Fxu_MatrixDelLiteral( p, pLit1 ); // step to the next literals pLit1 = bLit1Next; bLit1Next = pLit1? pLit1->pHNext: NULL; } else if ( !pLit1 && pLit2 ) { // this literal is present in pCubeRem - remove it // mark the affected var if ( pLit2->pVar->pOrder == NULL ) Fxu_MatrixRingVarsAdd( p, pLit2->pVar ); // delete this literal Fxu_MatrixDelLiteral( p, pLit2 ); // step to the next literals pLit2 = bLit2Next; bLit2Next = pLit2? pLit2->pHNext: NULL; } else break; } } /**Function************************************************************* Synopsis [Updates the matrix after selecting a single cube divisor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew ) { Fxu_Lit * pLit1, * bLit1Next; Fxu_Lit * pLit2, * bLit2Next; // initialize the starting literals pLit1 = pVar1->lLits.pHead; pLit2 = pVar2->lLits.pHead; bLit1Next = pLit1? pLit1->pVNext: NULL; bLit2Next = pLit2? pLit2->pVNext: NULL; while ( 1 ) { if ( pLit1 && pLit2 ) { if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar ) { // these literals coincide if ( pLit1->iCube == pLit2->iCube ) { // these literals coincide // collect the affected cube assert( pLit1->pCube->pOrder == NULL ); Fxu_MatrixRingCubesAdd( p, pLit1->pCube ); // add the literal to this cube corresponding to the new column Fxu_MatrixAddLiteral( p, pLit1->pCube, pVarNew ); // clean the old cubes Fxu_UpdateCleanOldDoubles( p, NULL, pLit1->pCube ); // remove the literals Fxu_MatrixDelLiteral( p, pLit1 ); Fxu_MatrixDelLiteral( p, pLit2 ); // go to the next literals pLit1 = bLit1Next; pLit2 = bLit2Next; bLit1Next = pLit1? pLit1->pVNext: NULL; bLit2Next = pLit2? pLit2->pVNext: NULL; } else if ( pLit1->iCube < pLit2->iCube ) { pLit1 = bLit1Next; bLit1Next = pLit1? pLit1->pVNext: NULL; } else { pLit2 = bLit2Next; bLit2Next = pLit2? pLit2->pVNext: NULL; } } else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar ) { pLit1 = bLit1Next; bLit1Next = pLit1? pLit1->pVNext: NULL; } else { pLit2 = bLit2Next; bLit2Next = pLit2? pLit2->pVNext: NULL; } } else if ( pLit1 && !pLit2 ) { pLit1 = bLit1Next; bLit1Next = pLit1? pLit1->pVNext: NULL; } else if ( !pLit1 && pLit2 ) { pLit2 = bLit2Next; bLit2Next = pLit2? pLit2->pVNext: NULL; } else break; } } /**Function************************************************************* Synopsis [Sort the pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble ) { Fxu_Pair * pPair; // order the pairs by the first cube to ensure that new literals are added // to the matrix from top to bottom - collect pairs into the array p->vPairs->nSize = 0; Fxu_DoubleForEachPair( pDouble, pPair ) Vec_PtrPush( p->vPairs, pPair ); if ( p->vPairs->nSize < 2 ) return; // sort qsort( (void *)p->vPairs->pArray, p->vPairs->nSize, sizeof(Fxu_Pair *), (int (*)(const void *, const void *)) Fxu_UpdatePairCompare ); assert( Fxu_UpdatePairCompare( (Fxu_Pair**)p->vPairs->pArray, (Fxu_Pair**)p->vPairs->pArray + p->vPairs->nSize - 1 ) < 0 ); } /**Function************************************************************* Synopsis [Compares the vars by their number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 ) { Fxu_Cube * pC1 = (*ppP1)->pCube1; Fxu_Cube * pC2 = (*ppP2)->pCube1; int iP1CubeMin, iP2CubeMin; if ( pC1->pVar->iVar < pC2->pVar->iVar ) return -1; if ( pC1->pVar->iVar > pC2->pVar->iVar ) return 1; iP1CubeMin = Fxu_PairMinCubeInt( *ppP1 ); iP2CubeMin = Fxu_PairMinCubeInt( *ppP2 ); if ( iP1CubeMin < iP2CubeMin ) return -1; if ( iP1CubeMin > iP2CubeMin ) return 1; assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Create new variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes ) { Fxu_Var * pVarC, * pVarD; // add a new column for the complement pVarC = Fxu_MatrixAddVar( p ); pVarC->nCubes = 0; // add a new column for the divisor pVarD = Fxu_MatrixAddVar( p ); pVarD->nCubes = nCubes; // mark this entry in the Value2Node array // assert( p->pValue2Node[pVarC->iVar] > 0 ); // p->pValue2Node[pVarD->iVar ] = p->pValue2Node[pVarC->iVar]; // p->pValue2Node[pVarD->iVar+1] = p->pValue2Node[pVarC->iVar]+1; *ppVarC = pVarC; *ppVarD = pVarD; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube ) { Fxu_Double * pDivCur; Fxu_Pair * pPair; int i; // if the cube is a recently introduced one // it does not have pairs allocated // in this case, there is nothing to update if ( pCube->pVar->ppPairs == NULL ) return; // go through all the pairs of this cube Fxu_CubeForEachPair( pCube, pPair, i ) { // get the divisor of this pair pDivCur = pPair->pDiv; // skip the current divisor if ( pDivCur == pDiv ) continue; // remove this pair Fxu_ListDoubleDelPair( pDivCur, pPair ); // the divisor may have become useless by now if ( pDivCur->lPairs.nItems == 0 ) { assert( pDivCur->Weight == pPair->nBase - 1 ); Fxu_HeapDoubleDelete( p->pHeapDouble, pDivCur ); Fxu_MatrixDelDivisor( p, pDivCur ); } else { // update the divisor's weight pDivCur->Weight -= pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase; Fxu_HeapDoubleUpdate( p->pHeapDouble, pDivCur ); } MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); } // finally erase all the pair info associated with this cube Fxu_PairClearStorage( pCube ); } /**Function************************************************************* Synopsis [Adds the new divisors that depend on the cube.] Description [Go through all the non-empty cubes of this cover (except the given cube) and, for each of them, add the new divisor with the given cube.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube ) { Fxu_Cube * pTemp; assert( pCube->pOrder ); // if the cube is a recently introduced one // it does not have pairs allocated // in this case, there is nothing to update if ( pCube->pVar->ppPairs == NULL ) return; for ( pTemp = pCube->pFirst; pTemp->pVar == pCube->pVar; pTemp = pTemp->pNext ) { // do not add pairs with the empty cubes if ( pTemp->lLits.nItems == 0 ) continue; // to prevent adding duplicated pairs of the new cubes // do not add the pair, if the current cube is marked if ( pTemp->pOrder && pTemp->iCube >= pCube->iCube ) continue; Fxu_MatrixAddDivisor( p, pTemp, pCube ); } } /**Function************************************************************* Synopsis [Removes old single cube divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p ) { Fxu_Single * pSingle, * pSingle2; int WeightNew; int Counter = 0; Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 ) { // if at least one of the variables is marked, recalculate if ( pSingle->pVar1->pOrder || pSingle->pVar2->pOrder ) { Counter++; // get the new weight WeightNew = -2 + Fxu_SingleCountCoincidence( p, pSingle->pVar1, pSingle->pVar2 ); if ( WeightNew >= 0 ) { pSingle->Weight = WeightNew; Fxu_HeapSingleUpdate( p->pHeapSingle, pSingle ); } else { Fxu_HeapSingleDelete( p->pHeapSingle, pSingle ); Fxu_ListMatrixDelSingle( p, pSingle ); MEM_FREE_FXU( p, Fxu_Single, 1, pSingle ); } } } // printf( "Called procedure %d times.\n", Counter ); } /**Function************************************************************* Synopsis [Updates the single cube divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar ) { Fxu_MatrixComputeSinglesOne( p, pVar ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/fxu/module.make000066400000000000000000000005101300674244400235600ustar00rootroot00000000000000SRC += src/opt/fxu/fxu.c \ src/opt/fxu/fxuCreate.c \ src/opt/fxu/fxuHeapD.c \ src/opt/fxu/fxuHeapS.c \ src/opt/fxu/fxuList.c \ src/opt/fxu/fxuMatrix.c \ src/opt/fxu/fxuPair.c \ src/opt/fxu/fxuPrint.c \ src/opt/fxu/fxuReduce.c \ src/opt/fxu/fxuSelect.c \ src/opt/fxu/fxuSingle.c \ src/opt/fxu/fxuUpdate.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/000077500000000000000000000000001300674244400214245ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpk.h000066400000000000000000000065301300674244400223670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpk.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpk.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__lpk__lpk_h #define ABC__opt__lpk__lpk_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Lpk_Par_t_ Lpk_Par_t; struct Lpk_Par_t_ { // user-controlled parameters int nLutsMax; // (N) the maximum number of LUTs in the structure int nLutsOver; // (Q) the maximum number of LUTs not in the MFFC int nVarsShared; // (S) the maximum number of shared variables (crossbars) int nGrowthLevel; // (L) the maximum increase in the node level after resynthesis int fSatur; // iterate till saturation int fZeroCost; // accept zero-cost replacements int fFirst; // use root node and first cut only int fOldAlgo; // use old algorithm int fVerbose; // the verbosiness flag int fVeryVerbose; // additional verbose info printout // internal parameters int nLutSize; // (K) the LUT size (determined by the input network) int nVarsMax; // (V) the largest number of variables: V = N * (K-1) + 1 }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== lpkCore.c ========================================================*/ extern int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkAbcDec.c000066400000000000000000000233321300674244400234030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkAbcDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [The new core procedure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkAbcDec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Implements the function.] Description [Returns the node implementing this function.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p ) { extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); unsigned * pTruth; Abc_Obj_t * pObjNew; int i; if ( p->fMark ) pMan->nMuxes++; else pMan->nDsds++; // create the new node pObjNew = Abc_NtkCreateNode( pNtk ); for ( i = 0; i < (int)p->nVars; i++ ) Abc_ObjAddFanin( pObjNew, Abc_ObjRegular((Abc_Obj_t *)Vec_PtrEntry(vLeaves, p->pFanins[i])) ); Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) ); // assign the node's function pTruth = Lpk_FunTruth(p, 0); if ( p->nVars == 0 ) { pObjNew->pData = Hop_NotCond( Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc), !(pTruth[0] & 1) ); return pObjNew; } if ( p->nVars == 1 ) { pObjNew->pData = Hop_NotCond( Hop_ManPi((Hop_Man_t *)pNtk->pManFunc, 0), (pTruth[0] & 1) ); return pObjNew; } // create the logic function pObjNew->pData = Kit_TruthToHop( (Hop_Man_t *)pNtk->pManFunc, pTruth, p->nVars, NULL ); return pObjNew; } /**Function************************************************************* Synopsis [Implements the function.] Description [Returns the node implementing this function.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Lpk_Implement_rec( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * pFun ) { Abc_Obj_t * pFanin, * pRes; int i; // prepare the leaves of the function for ( i = 0; i < (int)pFun->nVars; i++ ) { pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, pFun->pFanins[i] ); if ( !Abc_ObjIsComplement(pFanin) ) Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)pFanin ); pFanin = (Abc_Obj_t *)Vec_PtrEntry( vLeaves, pFun->pFanins[i] ); assert( Abc_ObjIsComplement(pFanin) ); } // construct the function pRes = Lpk_ImplementFun( pMan, pNtk, vLeaves, pFun ); // replace the function Vec_PtrWriteEntry( vLeaves, pFun->Id, Abc_ObjNot(pRes) ); Lpk_FunFree( pFun ); return pRes; } /**Function************************************************************* Synopsis [Implements the function.] Description [Returns the node implementing this function.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Lpk_Implement( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, int nLeavesOld ) { Abc_Obj_t * pFanin, * pRes; int i; assert( nLeavesOld < Vec_PtrSize(vLeaves) ); // mark implemented nodes Vec_PtrForEachEntryStop( Abc_Obj_t *, vLeaves, pFanin, i, nLeavesOld ) Vec_PtrWriteEntry( vLeaves, i, Abc_ObjNot(pFanin) ); // recursively construct starting from the first entry pRes = Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)Vec_PtrEntry( vLeaves, nLeavesOld ) ); Vec_PtrShrink( vLeaves, nLeavesOld ); return pRes; } /**Function************************************************************* Synopsis [Decomposes the function using recursive MUX decomposition.] Description [Returns the ID of the top-most decomposition node implementing this function, or 0 if there is no decomposition satisfying the constraints on area and delay.] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_Decompose_rec( Lpk_Man_t * pMan, Lpk_Fun_t * p ) { Lpk_Res_t * pResMux, * pResDsd; Lpk_Fun_t * p2; abctime clk; // is only called for non-trivial blocks assert( p->nLutK >= 3 && p->nLutK <= 6 ); assert( p->nVars > p->nLutK ); // skip if area bound is exceeded if ( Lpk_LutNumLuts(p->nVars, p->nLutK) > (int)p->nAreaLim ) return 0; // skip if delay bound is exceeded if ( Lpk_SuppDelay(p->uSupp, p->pDelays) > (int)p->nDelayLim ) return 0; // compute supports if needed if ( !p->fSupports ) Lpk_FunComputeCofSupps( p ); // check DSD decomposition clk = Abc_Clock(); pResDsd = Lpk_DsdAnalize( pMan, p, pMan->pPars->nVarsShared ); pMan->timeEvalDsdAn += Abc_Clock() - clk; if ( pResDsd && (pResDsd->nBSVars == (int)p->nLutK || pResDsd->nBSVars == (int)p->nLutK - 1) && pResDsd->AreaEst <= (int)p->nAreaLim && pResDsd->DelayEst <= (int)p->nDelayLim ) { clk = Abc_Clock(); p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars ); pMan->timeEvalDsdSp += Abc_Clock() - clk; assert( p2->nVars <= (int)p->nLutK ); if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) return 0; return 1; } // check MUX decomposition clk = Abc_Clock(); pResMux = Lpk_MuxAnalize( pMan, p ); pMan->timeEvalMuxAn += Abc_Clock() - clk; // pResMux = NULL; assert( !pResMux || (pResMux->DelayEst <= (int)p->nDelayLim && pResMux->AreaEst <= (int)p->nAreaLim) ); // accept MUX decomposition if it is "good" if ( pResMux && pResMux->nSuppSizeS <= (int)p->nLutK && pResMux->nSuppSizeL <= (int)p->nLutK ) pResDsd = NULL; else if ( pResMux && pResDsd ) { // compare two decompositions if ( pResMux->AreaEst < pResDsd->AreaEst || (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL < pResDsd->nSuppSizeL) || (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL == pResDsd->nSuppSizeL && pResMux->DelayEst < pResDsd->DelayEst) ) pResDsd = NULL; else pResMux = NULL; } assert( pResMux == NULL || pResDsd == NULL ); if ( pResMux ) { clk = Abc_Clock(); p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity ); pMan->timeEvalMuxSp += Abc_Clock() - clk; if ( p2->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p2 ) ) return 0; if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) return 0; return 1; } if ( pResDsd ) { clk = Abc_Clock(); p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars ); pMan->timeEvalDsdSp += Abc_Clock() - clk; assert( p2->nVars <= (int)p->nLutK ); if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) return 0; return 1; } return 0; } /**Function************************************************************* Synopsis [Removes decomposed nodes from the array of fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_DecomposeClean( Vec_Ptr_t * vLeaves, int nLeavesOld ) { Lpk_Fun_t * pFunc; int i; Vec_PtrForEachEntryStart( Lpk_Fun_t *, vLeaves, pFunc, i, nLeavesOld ) Lpk_FunFree( pFunc ); Vec_PtrShrink( vLeaves, nLeavesOld ); } /**Function************************************************************* Synopsis [Decomposes the function using recursive MUX decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim ) { Lpk_Fun_t * pFun; Abc_Obj_t * pObjNew = NULL; int nLeaves = Vec_PtrSize( vLeaves ); pFun = Lpk_FunCreate( pNtk, vLeaves, pTruth, nLutK, AreaLim, DelayLim ); if ( puSupps[0] || puSupps[1] ) { /* int i; Lpk_FunComputeCofSupps( pFun ); for ( i = 0; i < nLeaves; i++ ) { assert( pFun->puSupps[2*i+0] == puSupps[2*i+0] ); assert( pFun->puSupps[2*i+1] == puSupps[2*i+1] ); } */ memcpy( pFun->puSupps, puSupps, sizeof(unsigned) * 2 * nLeaves ); pFun->fSupports = 1; } Lpk_FunSuppMinimize( pFun ); if ( pFun->nVars <= pFun->nLutK ) pObjNew = Lpk_ImplementFun( p, pNtk, vLeaves, pFun ); else if ( Lpk_Decompose_rec(p, pFun) ) pObjNew = Lpk_Implement( p, pNtk, vLeaves, nLeaves ); Lpk_DecomposeClean( vLeaves, nLeaves ); return pObjNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkAbcDsd.c000066400000000000000000000500261300674244400234220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkAbcDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [LUT-decomposition based on recursive DSD.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkAbcDsd.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Cofactors TTs w.r.t. all vars and finds the best var.] Description [The best variable is the variable with the minimum sum total of the support sizes of all truth tables. This procedure computes and returns cofactors w.r.t. the best variable.] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_FunComputeMinSuppSizeVar( Lpk_Fun_t * p, unsigned ** ppTruths, int nTruths, unsigned ** ppCofs, unsigned uNonDecSupp ) { int i, Var, VarBest, nSuppSize0, nSuppSize1; int nSuppTotalMin = -1; // Suppress "might be used uninitialized" int nSuppTotalCur; int nSuppMaxMin = -1; // Suppress "might be used uninitialized" int nSuppMaxCur; assert( nTruths > 0 ); VarBest = -1; Lpk_SuppForEachVar( p->uSupp, Var ) { if ( (uNonDecSupp & (1 << Var)) == 0 ) continue; nSuppMaxCur = 0; nSuppTotalCur = 0; for ( i = 0; i < nTruths; i++ ) { if ( nTruths == 1 ) { nSuppSize0 = Kit_WordCountOnes( p->puSupps[2*Var+0] ); nSuppSize1 = Kit_WordCountOnes( p->puSupps[2*Var+1] ); } else { Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, Var ); Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, Var ); nSuppSize0 = Kit_TruthSupportSize( ppCofs[2*i+0], p->nVars ); nSuppSize1 = Kit_TruthSupportSize( ppCofs[2*i+1], p->nVars ); } nSuppMaxCur = Abc_MaxInt( nSuppMaxCur, nSuppSize0 ); nSuppMaxCur = Abc_MaxInt( nSuppMaxCur, nSuppSize1 ); nSuppTotalCur += nSuppSize0 + nSuppSize1; } if ( VarBest == -1 || nSuppMaxMin > nSuppMaxCur || (nSuppMaxMin == nSuppMaxCur && nSuppTotalMin > nSuppTotalCur) ) { VarBest = Var; nSuppMaxMin = nSuppMaxCur; nSuppTotalMin = nSuppTotalCur; } } // recompute cofactors for the best var for ( i = 0; i < nTruths; i++ ) { Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, VarBest ); Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, VarBest ); } return VarBest; } /**Function************************************************************* Synopsis [Recursively computes decomposable subsets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Lpk_ComputeBoundSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets, int nSizeMax ) { unsigned i, iLitFanin, uSupport, uSuppCur; Kit_DsdObj_t * pObj; // consider the case of simple gate pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) return (1 << Abc_Lit2Var(iLit)); if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) { unsigned uSupps[16], Limit, s; uSupport = 0; Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) { uSupps[i] = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax ); uSupport |= uSupps[i]; } // create all subsets, except empty and full Limit = (1 << pObj->nFans) - 1; for ( s = 1; s < Limit; s++ ) { uSuppCur = 0; for ( i = 0; i < pObj->nFans; i++ ) if ( s & (1 << i) ) uSuppCur |= uSupps[i]; if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax ) Vec_IntPush( vSets, uSuppCur ); } return uSupport; } assert( pObj->Type == KIT_DSD_PRIME ); // get the cumulative support of all fanins uSupport = 0; Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) { uSuppCur = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax ); uSupport |= uSuppCur; if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax ) Vec_IntPush( vSets, uSuppCur ); } return uSupport; } /**Function************************************************************* Synopsis [Computes the set of subsets of decomposable variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Lpk_ComputeBoundSets( Kit_DsdNtk_t * p, int nSizeMax ) { Vec_Int_t * vSets; unsigned uSupport, Entry; int Number, i; assert( p->nVars <= 16 ); vSets = Vec_IntAlloc( 100 ); Vec_IntPush( vSets, 0 ); if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) return vSets; if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) { uSupport = ( 1 << Abc_Lit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); if ( Kit_WordCountOnes(uSupport) <= nSizeMax ) Vec_IntPush( vSets, uSupport ); return vSets; } uSupport = Lpk_ComputeBoundSets_rec( p, p->Root, vSets, nSizeMax ); assert( (uSupport & 0xFFFF0000) == 0 ); // add the total support of the network if ( Kit_WordCountOnes(uSupport) <= nSizeMax ) Vec_IntPush( vSets, uSupport ); // set the remaining variables Vec_IntForEachEntry( vSets, Number, i ) { Entry = Number; Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) ); } return vSets; } /**Function************************************************************* Synopsis [Prints the sets of subsets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Lpk_PrintSetOne( int uSupport ) { unsigned k; for ( k = 0; k < 16; k++ ) if ( uSupport & (1<> 16)) ) continue; if ( Kit_WordCountOnes(Entry & 0xffff) <= nSizeMax ) Vec_IntPush( vSets, Entry ); } return vSets; } /**Function************************************************************* Synopsis [Performs DSD-based decomposition of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth, unsigned uNonDecSupp, unsigned uLateArrSupp, Lpk_Res_t * pRes ) { int fVerbose = 0; unsigned uBoundSet; int i, nVarsBS, nVarsRem, Delay, Area; // compare the resulting boundsets memset( pRes, 0, sizeof(Lpk_Res_t) ); Vec_IntForEachEntry( vBSets, uBoundSet, i ) { if ( (uBoundSet & 0xFFFF) == 0 ) // skip empty boundset continue; if ( (uBoundSet & uNonDecSupp) == 0 ) // skip those boundsets that are not in the domain of interest continue; if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving continue; if ( fVerbose ) { Lpk_PrintSetOne( uBoundSet & 0xFFFF ); //printf( "\n" ); //Lpk_PrintSetOne( uBoundSet >> 16 ); //printf( "\n" ); } assert( (uBoundSet & (uBoundSet >> 16)) == 0 ); nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF ); if ( nVarsBS == 1 ) continue; assert( nVarsBS <= (int)p->nLutK - nCofDepth ); nVarsRem = p->nVars - nVarsBS + 1; Area = 1 + Lpk_LutNumLuts( nVarsRem, p->nLutK ); Delay = 1 + Lpk_SuppDelay( uBoundSet & 0xFFFF, p->pDelays ); if ( fVerbose ) printf( "area = %d limit = %d delay = %d limit = %d\n", Area, (int)p->nAreaLim, Delay, (int)p->nDelayLim ); if ( Area > (int)p->nAreaLim || Delay > (int)p->nDelayLim ) continue; if ( pRes->BSVars == 0 || pRes->nSuppSizeL > nVarsRem || (pRes->nSuppSizeL == nVarsRem && pRes->DelayEst > Delay) ) { pRes->nBSVars = nVarsBS; pRes->BSVars = (uBoundSet & 0xFFFF); pRes->nSuppSizeS = nVarsBS + nCofDepth; pRes->nSuppSizeL = nVarsRem; pRes->DelayEst = Delay; pRes->AreaEst = Area; } } if ( fVerbose ) { if ( pRes->BSVars ) { printf( "Found bound set " ); Lpk_PrintSetOne( pRes->BSVars ); printf( "\n" ); } else printf( "Did not find boundsets.\n" ); printf( "\n" ); } if ( pRes->BSVars ) { assert( pRes->DelayEst <= (int)p->nDelayLim ); assert( pRes->AreaEst <= (int)p->nAreaLim ); } } /**Function************************************************************* Synopsis [Finds late arriving inputs, which cannot be in the bound set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Lpk_DsdLateArriving( Lpk_Fun_t * p ) { unsigned i, uLateArrSupp = 0; Lpk_SuppForEachVar( p->uSupp, i ) if ( p->pDelays[i] > (int)p->nDelayLim - 2 ) uLateArrSupp |= (1 << i); return uLateArrSupp; } /**Function************************************************************* Synopsis [Performs DSD-based decomposition of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_DsdAnalizeOne( Lpk_Fun_t * p, unsigned * ppTruths[5][16], Kit_DsdNtk_t * pNtks[], char pCofVars[], int nCofDepth, Lpk_Res_t * pRes ) { int fVerbose = 0; Vec_Int_t * pvBSets[4][8]; unsigned uNonDecSupp, uLateArrSupp; int i, k, nNonDecSize, nNonDecSizeMax; assert( nCofDepth >= 1 && nCofDepth <= 3 ); assert( nCofDepth < (int)p->nLutK - 1 ); assert( p->fSupports ); // find the support of the largest non-DSD block nNonDecSizeMax = 0; uNonDecSupp = p->uSupp; for ( i = 0; i < (1<<(nCofDepth-1)); i++ ) { nNonDecSize = Kit_DsdNonDsdSizeMax( pNtks[i] ); if ( nNonDecSizeMax < nNonDecSize ) { nNonDecSizeMax = nNonDecSize; uNonDecSupp = Kit_DsdNonDsdSupports( pNtks[i] ); } else if ( nNonDecSizeMax == nNonDecSize ) uNonDecSupp |= Kit_DsdNonDsdSupports( pNtks[i] ); } // remove those variables that cannot be used because of delay constraints // if variables arrival time is more than p->DelayLim - 2, it cannot be used uLateArrSupp = Lpk_DsdLateArriving( p ); if ( (uNonDecSupp & ~uLateArrSupp) == 0 ) { memset( pRes, 0, sizeof(Lpk_Res_t) ); return 0; } // find the next cofactoring variable pCofVars[nCofDepth-1] = Lpk_FunComputeMinSuppSizeVar( p, ppTruths[nCofDepth-1], 1<<(nCofDepth-1), ppTruths[nCofDepth], uNonDecSupp & ~uLateArrSupp ); // derive decomposed networks for ( i = 0; i < (1<nVars ); if ( fVerbose ) Kit_DsdPrint( stdout, pNtks[i] ); pvBSets[nCofDepth][i] = Lpk_ComputeBoundSets( pNtks[i], p->nLutK - nCofDepth ); // try restricting to those in uNonDecSupp!!! } // derive the set of feasible boundsets for ( i = nCofDepth - 1; i >= 0; i-- ) for ( k = 0; k < (1<nLutK - nCofDepth ); // compare bound-sets Lpk_FunCompareBoundSets( p, pvBSets[0][0], nCofDepth, uNonDecSupp, uLateArrSupp, pRes ); // free the bound sets for ( i = nCofDepth; i >= 0; i-- ) for ( k = 0; k < (1<BSVars ) { pRes->nCofVars = nCofDepth; for ( i = 0; i < nCofDepth; i++ ) pRes->pCofVars[i] = pCofVars[i]; } return 1; } /**Function************************************************************* Synopsis [Performs DSD-based decomposition of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Lpk_Res_t * Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared ) { static Lpk_Res_t Res0, * pRes0 = &Res0; static Lpk_Res_t Res1, * pRes1 = &Res1; static Lpk_Res_t Res2, * pRes2 = &Res2; static Lpk_Res_t Res3, * pRes3 = &Res3; int fUseBackLooking = 1; Lpk_Res_t * pRes = NULL; Vec_Int_t * vBSets; Kit_DsdNtk_t * pNtks[8] = {NULL}; char pCofVars[5]; int i; assert( p->nLutK >= 3 ); assert( nShared >= 0 && nShared <= 3 ); assert( p->uSupp == Kit_BitMask(p->nVars) ); // try decomposition without cofactoring pNtks[0] = Kit_DsdDecomposeExpand( Lpk_FunTruth( p, 0 ), p->nVars ); if ( pMan->pPars->fVerbose ) pMan->nBlocks[ Kit_DsdNonDsdSizeMax(pNtks[0]) ]++; vBSets = Lpk_ComputeBoundSets( pNtks[0], p->nLutK ); Lpk_FunCompareBoundSets( p, vBSets, 0, 0xFFFF, Lpk_DsdLateArriving(p), pRes0 ); Vec_IntFree( vBSets ); // check the result if ( pRes0->nBSVars == (int)p->nLutK ) { pRes = pRes0; goto finish; } if ( pRes0->nBSVars == (int)p->nLutK - 1 ) { pRes = pRes0; goto finish; } if ( nShared == 0 ) goto finish; // prepare storage Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth( p, 0 ), p->nVars ); // cofactor 1 time if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 1, pRes1 ) ) goto finish; assert( pRes1->nBSVars <= (int)p->nLutK - 1 ); if ( pRes1->nBSVars == (int)p->nLutK - 1 ) { pRes = pRes1; goto finish; } if ( pRes0->nBSVars == (int)p->nLutK - 2 ) { pRes = pRes0; goto finish; } if ( pRes1->nBSVars == (int)p->nLutK - 2 ) { pRes = pRes1; goto finish; } if ( nShared == 1 ) goto finish; // cofactor 2 times if ( p->nLutK >= 4 ) { if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 2, pRes2 ) ) goto finish; assert( pRes2->nBSVars <= (int)p->nLutK - 2 ); if ( pRes2->nBSVars == (int)p->nLutK - 2 ) { pRes = pRes2; goto finish; } if ( fUseBackLooking ) { if ( pRes0->nBSVars == (int)p->nLutK - 3 ) { pRes = pRes0; goto finish; } if ( pRes1->nBSVars == (int)p->nLutK - 3 ) { pRes = pRes1; goto finish; } } if ( pRes2->nBSVars == (int)p->nLutK - 3 ) { pRes = pRes2; goto finish; } if ( nShared == 2 ) goto finish; assert( nShared == 3 ); } // cofactor 3 times if ( p->nLutK >= 5 ) { if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 3, pRes3 ) ) goto finish; assert( pRes3->nBSVars <= (int)p->nLutK - 3 ); if ( pRes3->nBSVars == (int)p->nLutK - 3 ) { pRes = pRes3; goto finish; } if ( fUseBackLooking ) { if ( pRes0->nBSVars == (int)p->nLutK - 4 ) { pRes = pRes0; goto finish; } if ( pRes1->nBSVars == (int)p->nLutK - 4 ) { pRes = pRes1; goto finish; } if ( pRes2->nBSVars == (int)p->nLutK - 4 ) { pRes = pRes2; goto finish; } } if ( pRes3->nBSVars == (int)p->nLutK - 4 ) { pRes = pRes3; goto finish; } } finish: // free the networks for ( i = 0; i < (1<ppTruths[0][0], Lpk_FunTruth(p, 0), p->nVars ); // get the vacuous variable iVacVar = Kit_WordFindFirstBit( uBoundSet ); // compute the cofactors for ( i = 0; i < nCofVars; i++ ) for ( k = 0; k < (1<ppTruths[i+1][2*k+0], pMan->ppTruths[i][k], p->nVars, pCofVars[i] ); Kit_TruthCofactor1New( pMan->ppTruths[i+1][2*k+1], pMan->ppTruths[i][k], p->nVars, pCofVars[i] ); } // decompose each cofactor w.r.t. the bound set nCofs = (1<ppTruths[nCofVars][k], p->nVars ); Kit_DsdTruthPartialTwo( pMan->pDsdMan, pNtkDec, uBoundSet, iVacVar, pMan->ppTruths[nCofVars+1][k], pMan->ppTruths[nCofVars+1][nCofs+k] ); Kit_DsdNtkFree( pNtkDec ); } // compute the composition/decomposition functions (they will be in pMan->ppTruths[1][0]/pMan->ppTruths[1][1]) for ( i = nCofVars; i >= 1; i-- ) for ( k = 0; k < (1<ppTruths[i][k], pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i+1][2*k+1], p->nVars, pCofVars[i-1] ); // derive the new component (decomposition function) pNew = Lpk_FunDup( p, pMan->ppTruths[1][1] ); // update the old component (composition function) Kit_TruthCopy( Lpk_FunTruth(p, 0), pMan->ppTruths[1][0], p->nVars ); p->uSupp = Kit_TruthSupport( Lpk_FunTruth(p, 0), p->nVars ); p->pFanins[iVacVar] = pNew->Id; p->pDelays[iVacVar] = Lpk_SuppDelay( pNew->uSupp, pNew->pDelays ); // support minimize both p->fSupports = 0; Lpk_FunSuppMinimize( p ); Lpk_FunSuppMinimize( pNew ); // update delay and area requirements pNew->nDelayLim = p->pDelays[iVacVar]; pNew->nAreaLim = 1; p->nAreaLim = p->nAreaLim - 1; return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkAbcMux.c000066400000000000000000000224551300674244400234660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkAbcMux.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [LUT-decomposition based on recursive MUX decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkAbcMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks the possibility of MUX decomposition.] Description [Returns the best variable to use for MUX decomposition.] SideEffects [] SeeAlso [] ***********************************************************************/ Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) { static Lpk_Res_t Res, * pRes = &Res; int nSuppSize0, nSuppSize1, nSuppSizeS, nSuppSizeL; int Var, Area, Polarity, Delay, Delay0, Delay1, DelayA, DelayB; memset( pRes, 0, sizeof(Lpk_Res_t) ); assert( p->uSupp == Kit_BitMask(p->nVars) ); assert( p->fSupports ); // derive the delay and area after MUX-decomp with each var - and find the best var pRes->Variable = -1; Lpk_SuppForEachVar( p->uSupp, Var ) { nSuppSize0 = Kit_WordCountOnes(p->puSupps[2*Var+0]); nSuppSize1 = Kit_WordCountOnes(p->puSupps[2*Var+1]); assert( nSuppSize0 < (int)p->nVars ); assert( nSuppSize1 < (int)p->nVars ); if ( nSuppSize0 < 1 || nSuppSize1 < 1 ) continue; //printf( "%d %d ", nSuppSize0, nSuppSize1 ); if ( nSuppSize0 <= (int)p->nLutK - 2 && nSuppSize1 <= (int)p->nLutK - 2 ) { // include cof var into 0-block DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); Delay0 = Abc_MaxInt( DelayA, DelayB + 1 ); // include cof var into 1-block DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); Delay1 = Abc_MaxInt( DelayA, DelayB + 1 ); // get the best delay Delay = Abc_MinInt( Delay0, Delay1 ); Area = 2; Polarity = (int)(Delay == Delay1); } else if ( nSuppSize0 <= (int)p->nLutK - 2 ) { DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); Delay = Abc_MaxInt( DelayA, DelayB + 1 ); Area = 1 + Lpk_LutNumLuts( nSuppSize1, p->nLutK ); Polarity = 0; } else if ( nSuppSize1 <= (int)p->nLutK - 2 ) { DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); Delay = Abc_MaxInt( DelayA, DelayB + 1 ); Area = 1 + Lpk_LutNumLuts( nSuppSize0, p->nLutK ); Polarity = 1; } else if ( nSuppSize0 <= (int)p->nLutK ) { DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); Delay = Abc_MaxInt( DelayA, DelayB + 1 ); Area = 1 + Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ); Polarity = 1; } else if ( nSuppSize1 <= (int)p->nLutK ) { DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); Delay = Abc_MaxInt( DelayA, DelayB + 1 ); Area = 1 + Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ); Polarity = 0; } else { // include cof var into 0-block DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); Delay0 = Abc_MaxInt( DelayA, DelayB + 1 ); // include cof var into 1-block DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); Delay1 = Abc_MaxInt( DelayA, DelayB + 1 ); // get the best delay Delay = Abc_MinInt( Delay0, Delay1 ); if ( Delay == Delay0 ) Area = Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize1, p->nLutK ); else Area = Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize0, p->nLutK ); Polarity = (int)(Delay == Delay1); } // find the best variable if ( Delay > (int)p->nDelayLim ) continue; if ( Area > (int)p->nAreaLim ) continue; nSuppSizeS = Abc_MinInt( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity ); nSuppSizeL = Abc_MaxInt( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity ); if ( nSuppSizeL > (int)p->nVars ) continue; if ( pRes->Variable == -1 || pRes->AreaEst > Area || (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL > nSuppSizeS + nSuppSizeL) || (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL == nSuppSizeS + nSuppSizeL && pRes->DelayEst > Delay) ) { pRes->Variable = Var; pRes->Polarity = Polarity; pRes->AreaEst = Area; pRes->DelayEst = Delay; pRes->nSuppSizeS = nSuppSizeS; pRes->nSuppSizeL = nSuppSizeL; } } return pRes->Variable == -1 ? NULL : pRes; } /**Function************************************************************* Synopsis [Transforms the function decomposed by the MUX decomposition.] Description [Returns the best variable to use for MUX decomposition.] SideEffects [] SeeAlso [] ***********************************************************************/ Lpk_Fun_t * Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol ) { Lpk_Fun_t * pNew; unsigned * pTruth = Lpk_FunTruth( p, 0 ); unsigned * pTruth0 = Lpk_FunTruth( p, 1 ); unsigned * pTruth1 = Lpk_FunTruth( p, 2 ); // unsigned uSupp; int iVarVac; assert( Var >= 0 && Var < (int)p->nVars ); assert( p->nAreaLim >= 2 ); assert( p->uSupp == Kit_BitMask(p->nVars) ); Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var ); Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var ); /* uSupp = Kit_TruthSupport( pTruth, p->nVars ); Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" ); uSupp = Kit_TruthSupport( pTruth0, p->nVars ); Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" ); uSupp = Kit_TruthSupport( pTruth1, p->nVars ); Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n\n" ); */ // derive the new component pNew = Lpk_FunDup( p, Pol ? pTruth0 : pTruth1 ); // update the support of the old component p->uSupp = Kit_TruthSupport( Pol ? pTruth1 : pTruth0, p->nVars ); p->uSupp |= (1 << Var); // update the truth table of the old component iVarVac = Kit_WordFindFirstBit( ~p->uSupp ); assert( iVarVac < (int)p->nVars ); p->uSupp |= (1 << iVarVac); Kit_TruthIthVar( pTruth, p->nVars, iVarVac ); if ( Pol ) Kit_TruthMuxVar( pTruth, pTruth, pTruth1, p->nVars, Var ); else Kit_TruthMuxVar( pTruth, pTruth0, pTruth, p->nVars, Var ); assert( p->uSupp == Kit_TruthSupport(pTruth, p->nVars) ); // set the decomposed variable p->pFanins[iVarVac] = pNew->Id; p->pDelays[iVarVac] = p->nDelayLim - 1; // support minimize both p->fSupports = 0; Lpk_FunSuppMinimize( p ); Lpk_FunSuppMinimize( pNew ); // update delay and area requirements pNew->nDelayLim = p->nDelayLim - 1; if ( pNew->nVars <= pNew->nLutK ) { pNew->nAreaLim = 1; p->nAreaLim = p->nAreaLim - 1; } else if ( p->nVars <= p->nLutK ) { pNew->nAreaLim = p->nAreaLim - 1; p->nAreaLim = 1; } else if ( p->nVars < pNew->nVars ) { pNew->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2; p->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2; } else // if ( pNew->nVars < p->nVars ) { pNew->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2; p->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2; } pNew->fMark = 1; return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkAbcUtil.c000066400000000000000000000152551300674244400236320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkAbcUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [Procedures working on decomposed functions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkAbcUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Lpk_Fun_t * Lpk_FunAlloc( int nVars ) { Lpk_Fun_t * p; p = (Lpk_Fun_t *)ABC_ALLOC( char, sizeof(Lpk_Fun_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars) * 3 ); memset( p, 0, sizeof(Lpk_Fun_t) ); return p; } /**Function************************************************************* Synopsis [Deletes the function] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_FunFree( Lpk_Fun_t * p ) { ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates the starting function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Lpk_Fun_t * Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim ) { Lpk_Fun_t * p; Abc_Obj_t * pNode; int i; p = Lpk_FunAlloc( Vec_PtrSize(vLeaves) ); p->Id = Vec_PtrSize(vLeaves); p->vNodes = vLeaves; p->nVars = Vec_PtrSize(vLeaves); p->nLutK = nLutK; p->nAreaLim = AreaLim; p->nDelayLim = DelayLim; p->uSupp = Kit_TruthSupport( pTruth, p->nVars ); Kit_TruthCopy( Lpk_FunTruth(p,0), pTruth, p->nVars ); Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i ) { p->pFanins[i] = i; p->pDelays[i] = pNode->Level; } Vec_PtrPush( p->vNodes, p ); return p; } /**Function************************************************************* Synopsis [Creates the new function with the given truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Lpk_Fun_t * Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth ) { Lpk_Fun_t * pNew; pNew = Lpk_FunAlloc( p->nVars ); pNew->Id = Vec_PtrSize(p->vNodes); pNew->vNodes = p->vNodes; pNew->nVars = p->nVars; pNew->nLutK = p->nLutK; pNew->nAreaLim = p->nAreaLim; pNew->nDelayLim = p->nDelayLim; pNew->uSupp = Kit_TruthSupport( pTruth, p->nVars ); Kit_TruthCopy( Lpk_FunTruth(pNew,0), pTruth, p->nVars ); memcpy( pNew->pFanins, p->pFanins, 16 ); memcpy( pNew->pDelays, p->pDelays, 16 ); Vec_PtrPush( p->vNodes, pNew ); return pNew; } /**Function************************************************************* Synopsis [Minimizes support of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_FunSuppMinimize( Lpk_Fun_t * p ) { int i, k, nVarsNew; // compress the truth table if ( p->uSupp == Kit_BitMask(p->nVars) ) return 0; // invalidate support info p->fSupports = 0; //Extra_PrintBinary( stdout, &p->uSupp, p->nVars ); printf( "\n" ); // minimize support nVarsNew = Kit_WordCountOnes(p->uSupp); Kit_TruthShrink( Lpk_FunTruth(p, 1), Lpk_FunTruth(p, 0), nVarsNew, p->nVars, p->uSupp, 1 ); k = 0; Lpk_SuppForEachVar( p->uSupp, i ) { p->pFanins[k] = p->pFanins[i]; p->pDelays[k] = p->pDelays[i]; /* if ( p->fSupports ) { p->puSupps[2*k+0] = p->puSupps[2*i+0]; p->puSupps[2*k+1] = p->puSupps[2*i+1]; } */ k++; } assert( k == nVarsNew ); p->nVars = k; p->uSupp = Kit_BitMask(p->nVars); return 1; } /**Function************************************************************* Synopsis [Computes cofactors w.r.t. each variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_FunComputeCofSupps( Lpk_Fun_t * p ) { unsigned * pTruth = Lpk_FunTruth( p, 0 ); unsigned * pTruth0 = Lpk_FunTruth( p, 1 ); unsigned * pTruth1 = Lpk_FunTruth( p, 2 ); int Var; assert( p->fSupports == 0 ); // Lpk_SuppForEachVar( p->uSupp, Var ) for ( Var = 0; Var < (int)p->nVars; Var++ ) { Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var ); Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var ); p->puSupps[2*Var+0] = Kit_TruthSupport( pTruth0, p->nVars ); p->puSupps[2*Var+1] = Kit_TruthSupport( pTruth1, p->nVars ); } p->fSupports = 1; } /**Function************************************************************* Synopsis [Get the delay of the bound set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_SuppDelay( unsigned uSupp, char * pDelays ) { int Delay, Var; Delay = 0; Lpk_SuppForEachVar( uSupp, Var ) Delay = Abc_MaxInt( Delay, pDelays[Var] ); return Delay + 1; } /**Function************************************************************* Synopsis [Converts support into variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_SuppToVars( unsigned uBoundSet, char * pVars ) { int i, nVars = 0; Lpk_SuppForEachVar( uBoundSet, i ) pVars[nVars++] = i; return nVars; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkCore.c000066400000000000000000000562111300674244400231740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" #include "bool/kit/cloud.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prepares the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_IfManStart( Lpk_Man_t * p ) { If_Par_t * pPars; assert( p->pIfMan == NULL ); // set defaults pPars = ABC_ALLOC( If_Par_t, 1 ); memset( pPars, 0, sizeof(If_Par_t) ); // user-controlable paramters pPars->nLutSize = p->pPars->nLutSize; pPars->nCutsMax = 16; pPars->nFlowIters = 0; // 1 pPars->nAreaIters = 0; // 1 pPars->DelayTarget = -1; pPars->Epsilon = (float)0.005; pPars->fPreprocess = 0; pPars->fArea = 1; pPars->fFancy = 0; pPars->fExpRed = 0; // pPars->fLatchPaths = 0; pPars->fVerbose = 0; // internal parameters pPars->fTruth = 1; pPars->fUsePerm = 0; pPars->nLatchesCi = 0; pPars->nLatchesCo = 0; pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); pPars->pTimesArr = NULL; pPars->pTimesArr = NULL; pPars->fUseBdds = 0; pPars->fUseSops = 0; pPars->fUseCnfs = 0; pPars->fUseMv = 0; // start the mapping manager and set its parameters p->pIfMan = If_ManStart( pPars ); If_ManSetupSetAll( p->pIfMan, 1000 ); p->pIfMan->pPars->pTimesArr = ABC_ALLOC( float, 32 ); } /**Function************************************************************* Synopsis [Returns 1 if at least one entry has changed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_NodeHasChanged( Lpk_Man_t * p, int iNode ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pTemp; int i; vNodes = Vec_VecEntry( p->vVisited, iNode ); if ( Vec_PtrSize(vNodes) == 0 ) return 1; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pTemp, i ) { // check if the node has changed pTemp = Abc_NtkObj( p->pNtk, (int)(ABC_PTRUINT_T)pTemp ); if ( pTemp == NULL ) return 1; // check if the number of fanouts has changed // if ( Abc_ObjFanoutNum(pTemp) != (int)Vec_PtrEntry(vNodes, i+1) ) // return 1; i++; } return 0; } /**Function************************************************************* Synopsis [Prepares the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk ) { extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ); Kit_DsdObj_t * pRoot; If_Obj_t * pDriver, * ppLeaves[16]; Abc_Obj_t * pLeaf, * pObjNew; int nGain, i; abctime clk; int nNodesBef; // int nOldShared; // check special cases pRoot = Kit_DsdNtkRoot( pNtk ); if ( pRoot->Type == KIT_DSD_CONST1 ) { if ( Abc_LitIsCompl(pNtk->Root) ) pObjNew = Abc_NtkCreateNodeConst0( p->pNtk ); else pObjNew = Abc_NtkCreateNodeConst1( p->pNtk ); Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); p->nGainTotal += pCut->nNodes - pCut->nNodesDup; return 1; } if ( pRoot->Type == KIT_DSD_VAR ) { pObjNew = Abc_NtkObj( p->pNtk, pCut->pLeaves[ Abc_Lit2Var(pRoot->pFans[0]) ] ); if ( Abc_LitIsCompl(pNtk->Root) ^ Abc_LitIsCompl(pRoot->pFans[0]) ) pObjNew = Abc_NtkCreateNodeInv( p->pNtk, pObjNew ); Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); p->nGainTotal += pCut->nNodes - pCut->nNodesDup; return 1; } assert( pRoot->Type == KIT_DSD_AND || pRoot->Type == KIT_DSD_XOR || pRoot->Type == KIT_DSD_PRIME ); // start the mapping manager if ( p->pIfMan == NULL ) Lpk_IfManStart( p ); // prepare the mapping manager If_ManRestart( p->pIfMan ); // create the PI variables for ( i = 0; i < p->pPars->nVarsMax; i++ ) ppLeaves[i] = If_ManCreateCi( p->pIfMan ); // set the arrival times Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i ) p->pIfMan->pPars->pTimesArr[i] = (float)pLeaf->Level; // prepare the PI cuts If_ManSetupCiCutSets( p->pIfMan ); // create the internal nodes p->fCalledOnce = 0; p->nCalledSRed = 0; pDriver = Lpk_MapTree_rec( p, pNtk, ppLeaves, pNtk->Root, NULL ); if ( pDriver == NULL ) return 0; // create the PO node If_ManCreateCo( p->pIfMan, If_Regular(pDriver) ); // perform mapping p->pIfMan->pPars->fAreaOnly = 1; clk = Abc_Clock(); If_ManPerformMappingComb( p->pIfMan ); p->timeMap += Abc_Clock() - clk; // compute the gain in area nGain = pCut->nNodes - pCut->nNodesDup - (int)p->pIfMan->AreaGlo; if ( p->pPars->fVeryVerbose ) printf( " Mffc = %2d. Mapped = %2d. Gain = %3d. Depth increase = %d. SReds = %d.\n", pCut->nNodes - pCut->nNodesDup, (int)p->pIfMan->AreaGlo, nGain, (int)p->pIfMan->RequiredGlo - (int)p->pObj->Level, p->nCalledSRed ); // quit if there is no gain if ( !(nGain > 0 || (p->pPars->fZeroCost && nGain == 0)) ) return 0; // quit if depth increases too much if ( (int)p->pIfMan->RequiredGlo > Abc_ObjRequiredLevel(p->pObj) ) return 0; // perform replacement p->nGainTotal += nGain; p->nChanges++; if ( p->nCalledSRed ) p->nBenefited++; nNodesBef = Abc_NtkNodeNum(p->pNtk); // prepare the mapping manager If_ManCleanNodeCopy( p->pIfMan ); If_ManCleanCutData( p->pIfMan ); // set the PIs of the cut Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i ) If_ObjSetCopy( If_ManCi(p->pIfMan, i), pLeaf ); // get the area of mapping pObjNew = Abc_NodeFromIf_rec( p->pNtk, p->pIfMan, If_Regular(pDriver), p->vCover ); pObjNew->pData = Hop_NotCond( (Hop_Obj_t *)pObjNew->pData, If_IsComplement(pDriver) ); // perform replacement Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); //printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain ); return 1; } /**Function************************************************************* Synopsis [Performs resynthesis for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_ResynthesizeNode( Lpk_Man_t * p ) { // static int Count = 0; Kit_DsdNtk_t * pDsdNtk; Lpk_Cut_t * pCut; unsigned * pTruth; int i, k, nSuppSize, nCutNodes, RetValue; abctime clk; // compute the cuts clk = Abc_Clock(); if ( !Lpk_NodeCuts( p ) ) { p->timeCuts += Abc_Clock() - clk; return 0; } p->timeCuts += Abc_Clock() - clk; //return 0; if ( p->pPars->fVeryVerbose ) printf( "Node %5d : Mffc size = %5d. Cuts = %5d.\n", p->pObj->Id, p->nMffc, p->nEvals ); // try the good cuts p->nCutsTotal += p->nCuts; p->nCutsUseful += p->nEvals; for ( i = 0; i < p->nEvals; i++ ) { // get the cut pCut = p->pCuts + p->pEvals[i]; if ( p->pPars->fFirst && i == 1 ) break; // skip bad cuts // printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++; nCutNodes = Abc_NodeMffcLabel(p->pObj); // printf( "Mffc with cut = %d. ", nCutNodes ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--; // printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup ); // printf( "\n" ); if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup ) continue; // compute the truth table clk = Abc_Clock(); pTruth = Lpk_CutTruth( p, pCut, 0 ); nSuppSize = Extra_TruthSupportSize(pTruth, pCut->nLeaves); p->timeTruth += Abc_Clock() - clk; pDsdNtk = Kit_DsdDecompose( pTruth, pCut->nLeaves ); // Kit_DsdVerify( pDsdNtk, pTruth, pCut->nLeaves ); // skip 16-input non-DSD because ISOP will not work if ( Kit_DsdNtkRoot(pDsdNtk)->nFans == 16 ) { Kit_DsdNtkFree( pDsdNtk ); continue; } // if DSD has nodes that require splitting to fit them into LUTs // we can skip those cuts that cannot lead to improvement // (a full DSD network requires V = Nmin * (K-1) + 1 for improvement) if ( Kit_DsdNonDsdSizeMax(pDsdNtk) > p->pPars->nLutSize && nSuppSize >= ((int)pCut->nNodes - (int)pCut->nNodesDup - 1) * (p->pPars->nLutSize - 1) + 1 ) { Kit_DsdNtkFree( pDsdNtk ); continue; } if ( p->pPars->fVeryVerbose ) { // char * pFileName; printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ", i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight ); Kit_DsdPrint( stdout, pDsdNtk ); Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); // pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ ); // printf( "Saved truth table in file \"%s\".\n", pFileName ); } // update the network clk = Abc_Clock(); RetValue = Lpk_ExploreCut( p, pCut, pDsdNtk ); p->timeEval += Abc_Clock() - clk; Kit_DsdNtkFree( pDsdNtk ); if ( RetValue ) break; } return 1; } /**Function************************************************************* Synopsis [Computes supports of the cofactors of the function.] Description [This procedure should be called after Lpk_CutTruth(p,pCut,0)] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_ComputeSupports( Lpk_Man_t * p, Lpk_Cut_t * pCut, unsigned * pTruth ) { unsigned * pTruthInv; int RetValue1, RetValue2; pTruthInv = Lpk_CutTruth( p, pCut, 1 ); RetValue1 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruth, pCut->nLeaves, p->vBddDir ); RetValue2 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruthInv, pCut->nLeaves, p->vBddInv ); if ( RetValue1 && RetValue2 && Vec_IntSize(p->vBddDir) > 1 && Vec_IntSize(p->vBddInv) > 1 ) Kit_TruthCofSupports( p->vBddDir, p->vBddInv, pCut->nLeaves, p->vMemory, p->puSupps ); else p->puSupps[0] = p->puSupps[1] = 0; } /**Function************************************************************* Synopsis [Performs resynthesis for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_ResynthesizeNodeNew( Lpk_Man_t * p ) { // static int Count = 0; Abc_Obj_t * pObjNew, * pLeaf; Lpk_Cut_t * pCut; unsigned * pTruth; int nNodesBef, nNodesAft, nCutNodes; int i, k; abctime clk; int Required = Abc_ObjRequiredLevel(p->pObj); // CloudNode * pFun2;//, * pFun1; // compute the cuts clk = Abc_Clock(); if ( !Lpk_NodeCuts( p ) ) { p->timeCuts += Abc_Clock() - clk; return 0; } p->timeCuts += Abc_Clock() - clk; if ( p->pPars->fVeryVerbose ) printf( "Node %5d : Mffc size = %5d. Cuts = %5d. Level = %2d. Req = %2d.\n", p->pObj->Id, p->nMffc, p->nEvals, p->pObj->Level, Required ); // try the good cuts p->nCutsTotal += p->nCuts; p->nCutsUseful += p->nEvals; for ( i = 0; i < p->nEvals; i++ ) { // get the cut pCut = p->pCuts + p->pEvals[i]; if ( p->pPars->fFirst && i == 1 ) break; // if ( pCut->Weight < 1.05 ) // continue; // skip bad cuts // printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++; nCutNodes = Abc_NodeMffcLabel(p->pObj); // printf( "Mffc with cut = %d. ", nCutNodes ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--; // printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup ); // printf( "\n" ); if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup ) continue; // collect nodes into the array Vec_PtrClear( p->vLeaves ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Vec_PtrPush( p->vLeaves, Abc_NtkObj(p->pNtk, pCut->pLeaves[k]) ); // compute the truth table clk = Abc_Clock(); pTruth = Lpk_CutTruth( p, pCut, 0 ); p->timeTruth += Abc_Clock() - clk; clk = Abc_Clock(); Lpk_ComputeSupports( p, pCut, pTruth ); p->timeSupps += Abc_Clock() - clk; //clk = Abc_Clock(); // pFun1 = Lpk_CutTruthBdd( p, pCut ); //p->timeTruth2 += Abc_Clock() - clk; /* clk = Abc_Clock(); Cloud_Restart( p->pDsdMan->dd ); pFun2 = Kit_TruthToCloud( p->pDsdMan->dd, pTruth, pCut->nLeaves ); RetValue = Kit_CreateCloud( p->pDsdMan->dd, pFun2, p->vBddNodes ); p->timeTruth3 += Abc_Clock() - clk; */ // if ( pFun1 != pFun2 ) // printf( "Truth tables do not agree!\n" ); // else // printf( "Fine!\n" ); if ( p->pPars->fVeryVerbose ) { // char * pFileName; int nSuppSize = Extra_TruthSupportSize( pTruth, pCut->nLeaves ); printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ", i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pLeaf, k ) printf( "%c=%d ", 'a'+k, Abc_ObjLevel(pLeaf) ); printf( "\n" ); Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); // pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ ); // printf( "Saved truth table in file \"%s\".\n", pFileName ); } // update the network nNodesBef = Abc_NtkNodeNum(p->pNtk); clk = Abc_Clock(); pObjNew = Lpk_Decompose( p, p->pNtk, p->vLeaves, pTruth, p->puSupps, p->pPars->nLutSize, (int)pCut->nNodes - (int)pCut->nNodesDup - 1 + (int)(p->pPars->fZeroCost > 0), Required ); p->timeEval += Abc_Clock() - clk; nNodesAft = Abc_NtkNodeNum(p->pNtk); // perform replacement if ( pObjNew ) { int nGain = (int)pCut->nNodes - (int)pCut->nNodesDup - (nNodesAft - nNodesBef); assert( nGain >= 1 - p->pPars->fZeroCost ); assert( Abc_ObjLevel(pObjNew) <= Required ); /* if ( nGain <= 0 ) { int x = 0; } if ( Abc_ObjLevel(pObjNew) > Required ) { int x = 0; } */ p->nGainTotal += nGain; p->nChanges++; if ( p->pPars->fVeryVerbose ) printf( "Performed resynthesis: Gain = %2d. Level = %2d. Req = %2d.\n", nGain, Abc_ObjLevel(pObjNew), Required ); Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); //printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain ); break; } } return 1; } /**Function************************************************************* Synopsis [Performs resynthesis for one network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars ) { ProgressBar * pProgress = NULL; // Suppress "might be used uninitialized" Lpk_Man_t * p; Abc_Obj_t * pObj; double Delta; // int * pnFanouts, nObjMax; int i, Iter, nNodes, nNodesPrev; abctime clk = Abc_Clock(); assert( Abc_NtkIsLogic(pNtk) ); // sweep dangling nodes as a preprocessing step Abc_NtkSweep( pNtk, 0 ); // get the number of inputs if ( Abc_FrameReadLibLut() ) pPars->nLutSize = ((If_LibLut_t *)Abc_FrameReadLibLut())->LutMax; else pPars->nLutSize = Abc_NtkGetFaninMax( pNtk ); if ( pPars->nLutSize > 6 ) pPars->nLutSize = 6; if ( pPars->nLutSize < 3 ) pPars->nLutSize = 3; // adjust the number of crossbars based on LUT size if ( pPars->nVarsShared > pPars->nLutSize - 2 ) pPars->nVarsShared = pPars->nLutSize - 2; // get the max number of LUTs tried pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; // V = N * (K-1) + 1 while ( pPars->nVarsMax > 16 ) { pPars->nLutsMax--; pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; } if ( pPars->fVerbose ) { printf( "Resynthesis for %d %d-LUTs with %d non-MFFC LUTs, %d crossbars, and %d-input cuts.\n", pPars->nLutsMax, pPars->nLutSize, pPars->nLutsOver, pPars->nVarsShared, pPars->nVarsMax ); } // convert into the AIG if ( !Abc_NtkToAig(pNtk) ) { fprintf( stdout, "Converting to BDD has failed.\n" ); return 0; } assert( Abc_NtkHasAig(pNtk) ); // set the number of levels Abc_NtkLevel( pNtk ); Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); // start the manager p = Lpk_ManStart( pPars ); p->pNtk = pNtk; p->nNodesTotal = Abc_NtkNodeNum(pNtk); p->vLevels = Vec_VecStart( pNtk->LevelMax ); if ( p->pPars->fSatur ) p->vVisited = Vec_VecStart( 0 ); if ( pPars->fVerbose ) { p->nTotalNets = Abc_NtkGetTotalFanins(pNtk); p->nTotalNodes = Abc_NtkNodeNum(pNtk); } /* // save the number of fanouts of all objects nObjMax = Abc_NtkObjNumMax( pNtk ); pnFanouts = ABC_ALLOC( int, nObjMax ); memset( pnFanouts, 0, sizeof(int) * nObjMax ); Abc_NtkForEachObj( pNtk, pObj, i ) pnFanouts[pObj->Id] = Abc_ObjFanoutNum(pObj); */ // iterate over the network nNodesPrev = p->nNodesTotal; for ( Iter = 1; ; Iter++ ) { // expand storage for changed nodes if ( p->pPars->fSatur ) Vec_VecExpand( p->vVisited, Abc_NtkObjNumMax(pNtk) + 1 ); // consider all nodes nNodes = Abc_NtkObjNumMax(pNtk); if ( !pPars->fVeryVerbose ) pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachNode( pNtk, pObj, i ) { // skip all except the final node if ( pPars->fFirst ) { if ( !Abc_ObjIsCo(Abc_ObjFanout0(pObj)) ) continue; } if ( i >= nNodes ) break; if ( !pPars->fVeryVerbose ) Extra_ProgressBarUpdate( pProgress, i, NULL ); // skip the nodes that did not change if ( p->pPars->fSatur && !Lpk_NodeHasChanged(p, pObj->Id) ) continue; // resynthesize p->pObj = pObj; if ( p->pPars->fOldAlgo ) Lpk_ResynthesizeNode( p ); else Lpk_ResynthesizeNodeNew( p ); } if ( !pPars->fVeryVerbose ) Extra_ProgressBarStop( pProgress ); // check the increase Delta = 100.00 * (nNodesPrev - Abc_NtkNodeNum(pNtk)) / p->nNodesTotal; if ( Delta < 0.05 ) break; nNodesPrev = Abc_NtkNodeNum(pNtk); if ( !p->pPars->fSatur ) break; if ( pPars->fFirst ) break; } Abc_NtkStopReverseLevels( pNtk ); /* // report the fanout changes Abc_NtkForEachObj( pNtk, pObj, i ) { if ( i >= nObjMax ) continue; if ( Abc_ObjFanoutNum(pObj) - pnFanouts[pObj->Id] == 0 ) continue; printf( "%d ", Abc_ObjFanoutNum(pObj) - pnFanouts[pObj->Id] ); } printf( "\n" ); */ if ( pPars->fVerbose ) { // Cloud_PrintInfo( p->pDsdMan->dd ); p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk); p->nTotalNodes2 = Abc_NtkNodeNum(pNtk); printf( "Node gain = %5d. (%.2f %%) ", p->nTotalNodes-p->nTotalNodes2, 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes ); printf( "Edge gain = %5d. (%.2f %%) ", p->nTotalNets-p->nTotalNets2, 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets ); printf( "Muxes = %4d. Dsds = %4d.", p->nMuxes, p->nDsds ); printf( "\n" ); printf( "Nodes = %5d (%3d) Cuts = %5d (%4d) Changes = %5d Iter = %2d Benefit = %d.\n", p->nNodesTotal, p->nNodesOver, p->nCutsTotal, p->nCutsUseful, p->nChanges, Iter, p->nBenefited ); printf( "Non-DSD:" ); for ( i = 3; i <= pPars->nVarsMax; i++ ) if ( p->nBlocks[i] ) printf( " %d=%d", i, p->nBlocks[i] ); printf( "\n" ); p->timeTotal = Abc_Clock() - clk; p->timeEval = p->timeEval - p->timeMap; p->timeOther = p->timeTotal - p->timeCuts - p->timeTruth - p->timeEval - p->timeMap; ABC_PRTP( "Cuts ", p->timeCuts, p->timeTotal ); ABC_PRTP( "Truth ", p->timeTruth, p->timeTotal ); ABC_PRTP( "CSupps", p->timeSupps, p->timeTotal ); ABC_PRTP( "Eval ", p->timeEval, p->timeTotal ); ABC_PRTP( " MuxAn", p->timeEvalMuxAn, p->timeEval ); ABC_PRTP( " MuxSp", p->timeEvalMuxSp, p->timeEval ); ABC_PRTP( " DsdAn", p->timeEvalDsdAn, p->timeEval ); ABC_PRTP( " DsdSp", p->timeEvalDsdSp, p->timeEval ); ABC_PRTP( " Other", p->timeEval-p->timeEvalMuxAn-p->timeEvalMuxSp-p->timeEvalDsdAn-p->timeEvalDsdSp, p->timeEval ); ABC_PRTP( "Map ", p->timeMap, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); } Lpk_ManStop( p ); // check the resulting network if ( !Abc_NtkCheck( pNtk ) ) { printf( "Lpk_Resynthesize: The network check has failed.\n" ); return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkCut.c000066400000000000000000000521721300674244400230410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" #include "bool/kit/cloud.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the truth table of one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ CloudNode * Lpk_CutTruthBdd_rec( CloudManager * dd, Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars ) { CloudNode * pTruth, * pTruth0, * pTruth1; assert( !Hop_IsComplement(pObj) ); if ( pObj->pData ) { assert( ((unsigned)(ABC_PTRUINT_T)pObj->pData) & 0xffff0000 ); return (CloudNode *)pObj->pData; } // get the plan for a new truth table if ( Hop_ObjIsConst1(pObj) ) pTruth = dd->one; else { assert( Hop_ObjIsAnd(pObj) ); // compute the truth tables of the fanins pTruth0 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin0(pObj), nVars ); pTruth1 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin1(pObj), nVars ); pTruth0 = Cloud_NotCond( pTruth0, Hop_ObjFaninC0(pObj) ); pTruth1 = Cloud_NotCond( pTruth1, Hop_ObjFaninC1(pObj) ); // creat the truth table of the node pTruth = Cloud_bddAnd( dd, pTruth0, pTruth1 ); } pObj->pData = pTruth; return pTruth; } /**Function************************************************************* Synopsis [Verifies that the factoring is correct.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ CloudNode * Lpk_CutTruthBdd( Lpk_Man_t * p, Lpk_Cut_t * pCut ) { CloudManager * dd = p->pDsdMan->dd; Hop_Man_t * pManHop = (Hop_Man_t *)p->pNtk->pManFunc; Hop_Obj_t * pObjHop; Abc_Obj_t * pObj, * pFanin; CloudNode * pTruth = NULL; // Suppress "might be used uninitialized" int i, k; // return NULL; // Lpk_NodePrintCut( p, pCut ); // initialize the leaves Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) pObj->pCopy = (Abc_Obj_t *)dd->vars[pCut->nLeaves-1-i]; // construct truth table in the topological order Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i ) { // get the local AIG pObjHop = Hop_Regular((Hop_Obj_t *)pObj->pData); // clean the data field of the nodes in the AIG subgraph Hop_ObjCleanData_rec( pObjHop ); // set the initial truth tables at the fanins Abc_ObjForEachFanin( pObj, pFanin, k ) { assert( ((unsigned)(ABC_PTRUINT_T)pFanin->pCopy) & 0xffff0000 ); Hop_ManPi( pManHop, k )->pData = pFanin->pCopy; } // compute the truth table of internal nodes pTruth = Lpk_CutTruthBdd_rec( dd, pManHop, pObjHop, pCut->nLeaves ); if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) ) pTruth = Cloud_Not(pTruth); // set the truth table at the node pObj->pCopy = (Abc_Obj_t *)pTruth; } // Cloud_bddPrint( dd, pTruth ); // printf( "Bdd size = %d. Total nodes = %d.\n", Cloud_DagSize( dd, pTruth ), dd->nNodesCur-dd->nVars-1 ); return pTruth; } /**Function************************************************************* Synopsis [Computes the truth table of one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Lpk_CutTruth_rec( Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars, Vec_Ptr_t * vTtNodes, int * piCount ) { unsigned * pTruth, * pTruth0, * pTruth1; assert( !Hop_IsComplement(pObj) ); if ( pObj->pData ) { assert( ((unsigned)(ABC_PTRUINT_T)pObj->pData) & 0xffff0000 ); return (unsigned *)pObj->pData; } // get the plan for a new truth table pTruth = (unsigned *)Vec_PtrEntry( vTtNodes, (*piCount)++ ); if ( Hop_ObjIsConst1(pObj) ) Kit_TruthFill( pTruth, nVars ); else { assert( Hop_ObjIsAnd(pObj) ); // compute the truth tables of the fanins pTruth0 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin0(pObj), nVars, vTtNodes, piCount ); pTruth1 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin1(pObj), nVars, vTtNodes, piCount ); // creat the truth table of the node Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Hop_ObjFaninC0(pObj), Hop_ObjFaninC1(pObj) ); } pObj->pData = pTruth; return pTruth; } /**Function************************************************************* Synopsis [Computes the truth able of one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv ) { Hop_Man_t * pManHop = (Hop_Man_t *)p->pNtk->pManFunc; Hop_Obj_t * pObjHop; Abc_Obj_t * pObj = NULL; // Suppress "might be used uninitialized" Abc_Obj_t * pFanin; unsigned * pTruth = NULL; // Suppress "might be used uninitialized" int i, k, iCount = 0; // Lpk_NodePrintCut( p, pCut ); assert( pCut->nNodes > 0 ); // initialize the leaves Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( p->vTtElems, fInv? pCut->nLeaves-1-i : i ); // construct truth table in the topological order Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i ) { // get the local AIG pObjHop = Hop_Regular((Hop_Obj_t *)pObj->pData); // clean the data field of the nodes in the AIG subgraph Hop_ObjCleanData_rec( pObjHop ); // set the initial truth tables at the fanins Abc_ObjForEachFanin( pObj, pFanin, k ) { assert( ((unsigned)(ABC_PTRUINT_T)pFanin->pCopy) & 0xffff0000 ); Hop_ManPi( pManHop, k )->pData = pFanin->pCopy; } // compute the truth table of internal nodes pTruth = Lpk_CutTruth_rec( pManHop, pObjHop, pCut->nLeaves, p->vTtNodes, &iCount ); if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) ) Kit_TruthNot( pTruth, pTruth, pCut->nLeaves ); // set the truth table at the node pObj->pCopy = (Abc_Obj_t *)pTruth; } // make sure direct truth table is stored elsewhere (assuming the first call for direct truth!!!) if ( fInv == 0 ) { pTruth = (unsigned *)Vec_PtrEntry( p->vTtNodes, iCount++ ); Kit_TruthCopy( pTruth, (unsigned *)(ABC_PTRUINT_T)pObj->pCopy, pCut->nLeaves ); } assert( iCount <= Vec_PtrSize(p->vTtNodes) ); return pTruth; } /**Function************************************************************* Synopsis [Returns 1 if at least one entry has changed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_NodeRecordImpact( Lpk_Man_t * p ) { Lpk_Cut_t * pCut; Vec_Ptr_t * vNodes = Vec_VecEntry( p->vVisited, p->pObj->Id ); Abc_Obj_t * pNode; int i, k; // collect the nodes that impact the given node Vec_PtrClear( vNodes ); for ( i = 0; i < p->nCuts; i++ ) { pCut = p->pCuts + i; for ( k = 0; k < (int)pCut->nLeaves; k++ ) { pNode = Abc_NtkObj( p->pNtk, pCut->pLeaves[k] ); if ( pNode->fMarkC ) continue; pNode->fMarkC = 1; Vec_PtrPush( vNodes, (void *)(ABC_PTRUINT_T)pNode->Id ); Vec_PtrPush( vNodes, (void *)(ABC_PTRUINT_T)Abc_ObjFanoutNum(pNode) ); } } // clear the marks Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { pNode = Abc_NtkObj( p->pNtk, (int)(ABC_PTRUINT_T)pNode ); pNode->fMarkC = 0; i++; } //printf( "%d ", Vec_PtrSize(vNodes) ); } /**Function************************************************************* Synopsis [Returns 1 if the cut has structural DSD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_NodeCutsCheckDsd( Lpk_Man_t * p, Lpk_Cut_t * pCut ) { Abc_Obj_t * pObj, * pFanin; int i, k, nCands, fLeavesOnly, RetValue; assert( pCut->nLeaves > 0 ); // clear ref counters memset( p->pRefs, 0, sizeof(int) * pCut->nLeaves ); // mark cut leaves Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) { assert( pObj->fMarkA == 0 ); pObj->fMarkA = 1; pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)i; } // ref leaves pointed from the internal nodes nCands = 0; Lpk_CutForEachNode( p->pNtk, pCut, pObj, i ) { fLeavesOnly = 1; Abc_ObjForEachFanin( pObj, pFanin, k ) if ( pFanin->fMarkA ) p->pRefs[(int)(ABC_PTRUINT_T)pFanin->pCopy]++; else fLeavesOnly = 0; if ( fLeavesOnly ) p->pCands[nCands++] = pObj->Id; } // look at the nodes that only point to the leaves RetValue = 0; for ( i = 0; i < nCands; i++ ) { pObj = Abc_NtkObj( p->pNtk, p->pCands[i] ); Abc_ObjForEachFanin( pObj, pFanin, k ) { assert( pFanin->fMarkA == 1 ); if ( p->pRefs[(int)(ABC_PTRUINT_T)pFanin->pCopy] > 1 ) break; } if ( k == Abc_ObjFaninNum(pObj) ) { RetValue = 1; break; } } // unmark cut leaves Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) pObj->fMarkA = 0; return RetValue; } /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lpk_NodeCutsOneDominance( Lpk_Cut_t * pDom, Lpk_Cut_t * pCut ) { int i, k; for ( i = 0; i < (int)pDom->nLeaves; i++ ) { for ( k = 0; k < (int)pCut->nLeaves; k++ ) if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) break; if ( k == (int)pCut->nLeaves ) // 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 Lpk_NodeCutsOneFilter( Lpk_Cut_t * pCuts, int nCuts, Lpk_Cut_t * pCutNew ) { Lpk_Cut_t * pCut; int i, k; assert( pCutNew->uSign[0] || pCutNew->uSign[1] ); // try to find the cut for ( i = 0; i < nCuts; i++ ) { pCut = pCuts + i; if ( pCut->nLeaves == 0 ) continue; if ( pCut->nLeaves == pCutNew->nLeaves ) { if ( pCut->uSign[0] == pCutNew->uSign[0] && pCut->uSign[1] == pCutNew->uSign[1] ) { for ( k = 0; k < (int)pCutNew->nLeaves; k++ ) if ( pCut->pLeaves[k] != pCutNew->pLeaves[k] ) break; if ( k == (int)pCutNew->nLeaves ) return 1; } continue; } if ( pCut->nLeaves < pCutNew->nLeaves ) { // skip the non-contained cuts if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCut->uSign[0] ) continue; if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCut->uSign[1] ) continue; // check containment seriously if ( Lpk_NodeCutsOneDominance( pCut, pCutNew ) ) return 1; continue; } // check potential containment of other cut // skip the non-contained cuts if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCutNew->uSign[0] ) continue; if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCutNew->uSign[1] ) continue; // check containment seriously if ( Lpk_NodeCutsOneDominance( pCutNew, pCut ) ) pCut->nLeaves = 0; // removed } return 0; } /**Function************************************************************* Synopsis [Prints the given cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_NodePrintCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fLeavesOnly ) { Abc_Obj_t * pObj; int i; if ( !fLeavesOnly ) printf( "LEAVES:\n" ); Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) printf( "%d,", pObj->Id ); if ( !fLeavesOnly ) { printf( "\nNODES:\n" ); Lpk_CutForEachNode( p->pNtk, pCut, pObj, i ) { printf( "%d,", pObj->Id ); assert( Abc_ObjIsNode(pObj) ); } printf( "\n" ); } } /**Function************************************************************* Synopsis [Set the cut signature.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_NodeCutSignature( Lpk_Cut_t * pCut ) { unsigned i; pCut->uSign[0] = pCut->uSign[1] = 0; for ( i = 0; i < pCut->nLeaves; i++ ) { pCut->uSign[(pCut->pLeaves[i] & 32) > 0] |= (1 << (pCut->pLeaves[i] & 31)); if ( i != pCut->nLeaves - 1 ) assert( pCut->pLeaves[i] < pCut->pLeaves[i+1] ); } } /**Function************************************************************* Synopsis [Computes the set of all cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_NodeCutsOne( Lpk_Man_t * p, Lpk_Cut_t * pCut, int Node ) { Lpk_Cut_t * pCutNew; Abc_Obj_t * pObj, * pFanin; int i, k, j, nLeavesNew; /* printf( "Exploring cut " ); Lpk_NodePrintCut( p, pCut, 1 ); printf( "with node %d\n", Node ); */ // check if the cut can stand adding one more internal node if ( pCut->nNodes == LPK_SIZE_MAX ) return; // if the node is a PI, quit pObj = Abc_NtkObj( p->pNtk, Node ); if ( Abc_ObjIsCi(pObj) ) return; assert( Abc_ObjIsNode(pObj) ); // assert( Abc_ObjFaninNum(pObj) <= p->pPars->nLutSize ); // if the node is not in the MFFC, check the limit if ( !Abc_NodeIsTravIdCurrent(pObj) ) { if ( (int)pCut->nNodesDup == p->pPars->nLutsOver ) return; assert( (int)pCut->nNodesDup < p->pPars->nLutsOver ); } // check the possibility of adding this node using the signature nLeavesNew = pCut->nLeaves - 1; Abc_ObjForEachFanin( pObj, pFanin, i ) { if ( (pCut->uSign[(pFanin->Id & 32) > 0] & (1 << (pFanin->Id & 31))) ) continue; if ( ++nLeavesNew > p->pPars->nVarsMax ) return; } // initialize the set of leaves to the nodes in the cut assert( p->nCuts < LPK_CUTS_MAX ); pCutNew = p->pCuts + p->nCuts; pCutNew->nLeaves = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) if ( pCut->pLeaves[i] != Node ) pCutNew->pLeaves[pCutNew->nLeaves++] = pCut->pLeaves[i]; // add new nodes Abc_ObjForEachFanin( pObj, pFanin, i ) { // find the place where this node belongs for ( k = 0; k < (int)pCutNew->nLeaves; k++ ) if ( pCutNew->pLeaves[k] >= pFanin->Id ) break; if ( k < (int)pCutNew->nLeaves && pCutNew->pLeaves[k] == pFanin->Id ) continue; // check if there is room if ( (int)pCutNew->nLeaves == p->pPars->nVarsMax ) return; // move all the nodes for ( j = pCutNew->nLeaves; j > k; j-- ) pCutNew->pLeaves[j] = pCutNew->pLeaves[j-1]; pCutNew->pLeaves[k] = pFanin->Id; pCutNew->nLeaves++; assert( pCutNew->nLeaves <= LPK_SIZE_MAX ); } // skip the contained cuts Lpk_NodeCutSignature( pCutNew ); if ( Lpk_NodeCutsOneFilter( p->pCuts, p->nCuts, pCutNew ) ) return; // update the set of internal nodes assert( pCut->nNodes < LPK_SIZE_MAX ); memcpy( pCutNew->pNodes, pCut->pNodes, pCut->nNodes * sizeof(int) ); pCutNew->nNodes = pCut->nNodes; pCutNew->nNodesDup = pCut->nNodesDup; // check if the node is already there // if so, move the node to be the last for ( i = 0; i < (int)pCutNew->nNodes; i++ ) if ( pCutNew->pNodes[i] == Node ) { for ( k = i; k < (int)pCutNew->nNodes - 1; k++ ) pCutNew->pNodes[k] = pCutNew->pNodes[k+1]; pCutNew->pNodes[k] = Node; break; } if ( i == (int)pCutNew->nNodes ) // new node { pCutNew->pNodes[ pCutNew->nNodes++ ] = Node; pCutNew->nNodesDup += !Abc_NodeIsTravIdCurrent(pObj); } // the number of nodes does not exceed MFFC plus duplications assert( pCutNew->nNodes <= p->nMffc + pCutNew->nNodesDup ); // add the cut to storage assert( p->nCuts < LPK_CUTS_MAX ); p->nCuts++; } /**Function************************************************************* Synopsis [Computes the set of all cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_NodeCuts( Lpk_Man_t * p ) { Lpk_Cut_t * pCut, * pCut2; int i, k, Temp, nMffc, fChanges; // mark the MFFC of the node with the current trav ID nMffc = p->nMffc = Abc_NodeMffcLabel( p->pObj ); assert( nMffc > 0 ); if ( nMffc == 1 ) return 0; // initialize the first cut pCut = p->pCuts; p->nCuts = 1; pCut->nNodes = 0; pCut->nNodesDup = 0; pCut->nLeaves = 1; pCut->pLeaves[0] = p->pObj->Id; // assign the signature Lpk_NodeCutSignature( pCut ); // perform the cut computation for ( i = 0; i < p->nCuts; i++ ) { pCut = p->pCuts + i; if ( pCut->nLeaves == 0 ) continue; // try to expand the fanins of this cut for ( k = 0; k < (int)pCut->nLeaves; k++ ) { // create a new cut Lpk_NodeCutsOne( p, pCut, pCut->pLeaves[k] ); // quit if the number of cuts has exceeded the limit if ( p->nCuts == LPK_CUTS_MAX ) break; } if ( p->nCuts == LPK_CUTS_MAX ) break; } if ( p->nCuts == LPK_CUTS_MAX ) p->nNodesOver++; // record the impact of this node if ( p->pPars->fSatur ) Lpk_NodeRecordImpact( p ); // compress the cuts by removing empty ones, those with negative Weight, and decomposable ones p->nEvals = 0; for ( i = 0; i < p->nCuts; i++ ) { pCut = p->pCuts + i; if ( pCut->nLeaves < 2 ) continue; // compute the minimum number of LUTs needed to implement this cut // V = N * (K-1) + 1 ~~~~~ N = Ceiling[(V-1)/(K-1)] = (V-1)/(K-1) + [(V-1)%(K-1) > 0] pCut->nLuts = Lpk_LutNumLuts( pCut->nLeaves, p->pPars->nLutSize ); // pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup - 1) / pCut->nLuts; //p->pPars->nLutsMax; pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup) / pCut->nLuts; //p->pPars->nLutsMax; if ( pCut->Weight <= 1.001 ) // if ( pCut->Weight <= 0.999 ) continue; pCut->fHasDsd = Lpk_NodeCutsCheckDsd( p, pCut ); if ( pCut->fHasDsd ) continue; p->pEvals[p->nEvals++] = i; } if ( p->nEvals == 0 ) return 0; // sort the cuts by Weight do { fChanges = 0; for ( i = 0; i < p->nEvals - 1; i++ ) { pCut = p->pCuts + p->pEvals[i]; pCut2 = p->pCuts + p->pEvals[i+1]; if ( pCut->Weight >= pCut2->Weight - 0.001 ) continue; Temp = p->pEvals[i]; p->pEvals[i] = p->pEvals[i+1]; p->pEvals[i+1] = Temp; fChanges = 1; } } while ( fChanges ); /* for ( i = 0; i < p->nEvals; i++ ) { pCut = p->pCuts + p->pEvals[i]; printf( "Cut %3d : W = %5.2f.\n", i, pCut->Weight ); } printf( "\n" ); */ return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkInt.h000066400000000000000000000276071300674244400230520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__lpk__lpkInt_h #define ABC__opt__lpk__lpkInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" #include "bool/kit/kit.h" #include "map/if/if.h" #include "lpk.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// #define LPK_SIZE_MAX 24 // the largest size of the function #define LPK_CUTS_MAX 512 // the largest number of cuts considered typedef struct Lpk_Man_t_ Lpk_Man_t; typedef struct Lpk_Cut_t_ Lpk_Cut_t; struct Lpk_Cut_t_ { unsigned nLeaves : 6; // (L) the number of leaves unsigned nNodes : 6; // (M) the number of nodes unsigned nNodesDup : 6; // (Q) nodes outside of MFFC unsigned nLuts : 6; // (N) the number of LUTs to try unsigned unused : 6; // unused unsigned fHasDsd : 1; // set to 1 if the cut has structural DSD (and so cannot be used) unsigned fMark : 1; // multipurpose mark unsigned uSign[2]; // the signature float Weight; // the weight of the cut: (M - Q)/N(V) (the larger the better) int Gain; // the gain achieved using this cut int pLeaves[LPK_SIZE_MAX]; // the leaves of the cut int pNodes[LPK_SIZE_MAX]; // the nodes of the cut }; struct Lpk_Man_t_ { // parameters Lpk_Par_t * pPars; // the set of parameters // current representation Abc_Ntk_t * pNtk; // the network Abc_Obj_t * pObj; // the node to resynthesize // cut representation int nMffc; // the size of MFFC of the node int nCuts; // the total number of cuts int nCutsMax; // the largest possible number of cuts int nEvals; // the number of good cuts Lpk_Cut_t pCuts[LPK_CUTS_MAX]; // the storage for cuts int pEvals[LPK_CUTS_MAX]; // the good cuts // visited nodes Vec_Vec_t * vVisited; // mapping manager If_Man_t * pIfMan; Vec_Int_t * vCover; Vec_Vec_t * vLevels; // temporary variables int fCofactoring; // working in the cofactoring mode int fCalledOnce; // limits the depth of MUX cofactoring int nCalledSRed; // the number of called to SRed int pRefs[LPK_SIZE_MAX]; // fanin reference counters int pCands[LPK_SIZE_MAX]; // internal nodes pointing only to the leaves Vec_Ptr_t * vLeaves; // truth table representation Vec_Ptr_t * vTtElems; // elementary truth tables Vec_Ptr_t * vTtNodes; // storage for temporary truth tables of the nodes Vec_Int_t * vMemory; Vec_Int_t * vBddDir; Vec_Int_t * vBddInv; unsigned puSupps[32]; // the supports of the cofactors unsigned * ppTruths[5][16]; // variable sets Vec_Int_t * vSets[8]; Kit_DsdMan_t* pDsdMan; // statistics int nNodesTotal; // total number of nodes int nNodesOver; // nodes with cuts over the limit int nCutsTotal; // total number of cuts int nCutsUseful; // useful cuts int nGainTotal; // the gain in LUTs int nChanges; // the number of changed nodes int nBenefited; // the number of gainful that benefited from decomposition int nMuxes; int nDsds; int nTotalNets; int nTotalNets2; int nTotalNodes; int nTotalNodes2; // counter of non-DSD blocks int nBlocks[17]; // runtime abctime timeCuts; abctime timeTruth; abctime timeSupps; abctime timeTruth2; abctime timeTruth3; abctime timeEval; abctime timeMap; abctime timeOther; abctime timeTotal; // runtime of eval abctime timeEvalMuxAn; abctime timeEvalMuxSp; abctime timeEvalDsdAn; abctime timeEvalDsdSp; }; // internal representation of the function to be decomposed typedef struct Lpk_Fun_t_ Lpk_Fun_t; struct Lpk_Fun_t_ { Vec_Ptr_t * vNodes; // the array of leaves and decomposition nodes unsigned Id : 7; // the ID of this node unsigned nVars : 5; // the number of variables unsigned nLutK : 4; // the number of LUT inputs unsigned nAreaLim : 5; // the area limit (the largest allowed) unsigned nDelayLim : 9; // the delay limit (the largest allowed) unsigned fSupports : 1; // supports of cofactors were precomputed unsigned fMark : 1; // marks the MUX-based dec unsigned uSupp; // the support of this component unsigned puSupps[32]; // the supports of the cofactors char pDelays[16]; // the delays of the inputs char pFanins[16]; // the fanins of this function unsigned pTruth[0]; // the truth table (contains room for three truth tables) }; // preliminary decomposition result typedef struct Lpk_Res_t_ Lpk_Res_t; struct Lpk_Res_t_ { int nBSVars; // the number of bound set variables unsigned BSVars; // the bound set int nCofVars; // the number of cofactoring variables char pCofVars[4]; // the cofactoring variables int nSuppSizeS; // support size of the smaller (decomposed) function int nSuppSizeL; // support size of the larger (composition) function int DelayEst; // estimated delay of the decomposition int AreaEst; // estimated area of the decomposition int Variable; // variable in MUX decomposition int Polarity; // polarity in MUX decomposition }; static inline int Lpk_LutNumVars( int nLutsLim, int nLutK ) { return nLutsLim * (nLutK - 1) + 1; } static inline int Lpk_LutNumLuts( int nVarsMax, int nLutK ) { return (nVarsMax - 1) / (nLutK - 1) + (int)((nVarsMax - 1) % (nLutK - 1) > 0); } static inline unsigned * Lpk_FunTruth( Lpk_Fun_t * p, int Num ) { assert( Num < 3 ); return p->pTruth + Kit_TruthWordNum(p->nVars) * Num; } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// #define Lpk_CutForEachLeaf( pNtk, pCut, pObj, i ) \ for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pLeaves[i])), 1); i++ ) #define Lpk_CutForEachNode( pNtk, pCut, pObj, i ) \ for ( i = 0; (i < (int)(pCut)->nNodes) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i++ ) #define Lpk_CutForEachNodeReverse( pNtk, pCut, pObj, i ) \ for ( i = (int)(pCut)->nNodes - 1; (i >= 0) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i-- ) #define Lpk_SuppForEachVar( Supp, Var )\ for ( Var = 0; Var < 16; Var++ )\ if ( !(Supp & (1<nLutsMax <= 16 ); assert( pPars->nVarsMax > 0 && pPars->nVarsMax <= 16 ); p = ABC_ALLOC( Lpk_Man_t, 1 ); memset( p, 0, sizeof(Lpk_Man_t) ); p->pPars = pPars; p->nCutsMax = LPK_CUTS_MAX; p->vTtElems = Vec_PtrAllocTruthTables( pPars->nVarsMax ); p->vTtNodes = Vec_PtrAllocSimInfo( 1024, Abc_TruthWordNum(pPars->nVarsMax) ); p->vCover = Vec_IntAlloc( 1 << 12 ); p->vLeaves = Vec_PtrAlloc( 32 ); for ( i = 0; i < 8; i++ ) p->vSets[i] = Vec_IntAlloc(100); p->pDsdMan = Kit_DsdManAlloc( pPars->nVarsMax, 64 ); p->vMemory = Vec_IntAlloc( 1024 * 32 ); p->vBddDir = Vec_IntAlloc( 256 ); p->vBddInv = Vec_IntAlloc( 256 ); // allocate temporary storage for truth tables nWords = Kit_TruthWordNum(pPars->nVarsMax); p->ppTruths[0][0] = ABC_ALLOC( unsigned, 32 * nWords ); p->ppTruths[1][0] = p->ppTruths[0][0] + 1 * nWords; for ( i = 1; i < 2; i++ ) p->ppTruths[1][i] = p->ppTruths[1][0] + i * nWords; p->ppTruths[2][0] = p->ppTruths[1][0] + 2 * nWords; for ( i = 1; i < 4; i++ ) p->ppTruths[2][i] = p->ppTruths[2][0] + i * nWords; p->ppTruths[3][0] = p->ppTruths[2][0] + 4 * nWords; for ( i = 1; i < 8; i++ ) p->ppTruths[3][i] = p->ppTruths[3][0] + i * nWords; p->ppTruths[4][0] = p->ppTruths[3][0] + 8 * nWords; for ( i = 1; i < 16; i++ ) p->ppTruths[4][i] = p->ppTruths[4][0] + i * nWords; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_ManStop( Lpk_Man_t * p ) { int i; ABC_FREE( p->ppTruths[0][0] ); Vec_IntFree( p->vBddDir ); Vec_IntFree( p->vBddInv ); Vec_IntFree( p->vMemory ); Kit_DsdManFree( p->pDsdMan ); for ( i = 0; i < 8; i++ ) Vec_IntFree(p->vSets[i]); if ( p->pIfMan ) { void * pPars = p->pIfMan->pPars; If_ManStop( p->pIfMan ); ABC_FREE( pPars ); } if ( p->vLevels ) Vec_VecFree( p->vLevels ); if ( p->vVisited ) Vec_VecFree( p->vVisited ); Vec_PtrFree( p->vLeaves ); Vec_IntFree( p->vCover ); Vec_PtrFree( p->vTtElems ); Vec_PtrFree( p->vTtNodes ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkMap.c000066400000000000000000000160041300674244400230150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkMap.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * Lpk_MapPrimeInternal( If_Man_t * pIfMan, Kit_Graph_t * pGraph ) { Kit_Node_t * pNode = NULL; // Suppress "might be used uninitialized" If_Obj_t * pAnd0, * pAnd1; int i; // check for constant function if ( Kit_GraphIsConst(pGraph) ) return If_ManConst1(pIfMan); // check for a literal if ( Kit_GraphIsVar(pGraph) ) return (If_Obj_t *)Kit_GraphVar(pGraph)->pFunc; // build the AIG nodes corresponding to the AND gates of the graph Kit_GraphForEachNode( pGraph, pNode, i ) { pAnd0 = (If_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; pAnd1 = (If_Obj_t *)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; pNode->pFunc = If_ManCreateAnd( pIfMan, If_NotCond( If_Regular(pAnd0), If_IsComplement(pAnd0) ^ pNode->eEdge0.fCompl ), If_NotCond( If_Regular(pAnd1), If_IsComplement(pAnd1) ^ pNode->eEdge1.fCompl ) ); } return (If_Obj_t *)pNode->pFunc; } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) { Kit_Graph_t * pGraph; Kit_Node_t * pNode; If_Obj_t * pRes; int i; // derive the factored form pGraph = Kit_TruthToGraph( pTruth, nVars, p->vCover ); if ( pGraph == NULL ) return NULL; // collect the fanins Kit_GraphForEachLeaf( pGraph, pNode, i ) pNode->pFunc = ppLeaves[i]; // perform strashing pRes = Lpk_MapPrimeInternal( p->pIfMan, pGraph ); pRes = If_NotCond( pRes, Kit_GraphIsComplement(pGraph) ); Kit_GraphFree( pGraph ); return pRes; } /**Function************************************************************* Synopsis [Prepares the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult ) { Kit_DsdObj_t * pObj; If_Obj_t * pObjNew = NULL, * pObjNew2 = NULL, * pFansNew[16]; unsigned i, iLitFanin; assert( iLit >= 0 ); // consider the case of a gate pObj = Kit_DsdNtkObj( pNtk, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) { pObjNew = ppLeaves[Abc_Lit2Var(iLit)]; return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ); } if ( pObj->Type == KIT_DSD_CONST1 ) { return If_NotCond( If_ManConst1(p->pIfMan), Abc_LitIsCompl(iLit) ); } if ( pObj->Type == KIT_DSD_VAR ) { pObjNew = ppLeaves[Abc_Lit2Var(pObj->pFans[0])]; return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ^ Abc_LitIsCompl(pObj->pFans[0]) ); } if ( pObj->Type == KIT_DSD_AND ) { assert( pObj->nFans == 2 ); pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL ); pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL ); if ( pFansNew[0] == NULL || pFansNew[1] == NULL ) return NULL; pObjNew = If_ManCreateAnd( p->pIfMan, pFansNew[0], pFansNew[1] ); return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ); } if ( pObj->Type == KIT_DSD_XOR ) { int fCompl = Abc_LitIsCompl(iLit); assert( pObj->nFans == 2 ); pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL ); pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL ); if ( pFansNew[0] == NULL || pFansNew[1] == NULL ) return NULL; fCompl ^= If_IsComplement(pFansNew[0]) ^ If_IsComplement(pFansNew[1]); pObjNew = If_ManCreateXor( p->pIfMan, If_Regular(pFansNew[0]), If_Regular(pFansNew[1]) ); return If_NotCond( pObjNew, fCompl ); } assert( pObj->Type == KIT_DSD_PRIME ); p->nBlocks[pObj->nFans]++; // solve for the inputs Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) { if ( i == 0 ) pFansNew[i] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL ); else pFansNew[i] = Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL ); if ( pFansNew[i] == NULL ) return NULL; } /* if ( !p->fCofactoring && p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize ) { pObjNew = Lpk_MapTreeMulti( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ); } */ /* if ( (int)pObj->nFans > p->pPars->nLutSize ) { pObjNew2 = Lpk_MapTreeMux_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); // if ( pObjNew2 ) // return If_NotCond( pObjNew2, Abc_LitIsCompl(iLit) ); } */ // find best cofactoring variable if ( p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize ) { pObjNew2 = Lpk_MapSuppRedDec_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); if ( pObjNew2 ) return If_NotCond( pObjNew2, Abc_LitIsCompl(iLit) ); } pObjNew = Lpk_MapPrime( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); // add choice if ( pObjNew && pObjNew2 ) { If_ObjSetChoice( If_Regular(pObjNew), If_Regular(pObjNew2) ); If_ManCreateChoice( p->pIfMan, If_Regular(pObjNew) ); } return If_NotCond( pObjNew, Abc_LitIsCompl(iLit) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkMulti.c000066400000000000000000000365221300674244400234010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkMulti.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkMulti.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Records variable order.] Description [Increaments Order[x][y] by 1 if x should be above y in the DSD.] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_CreateVarOrder( Kit_DsdNtk_t * pNtk, char pTable[][16] ) { Kit_DsdObj_t * pObj; unsigned uSuppFanins, k; int Above[16], Below[16]; int nAbove, nBelow, iFaninLit, i, x, y; // iterate through the nodes Kit_DsdNtkForEachObj( pNtk, pObj, i ) { // collect fanin support of this node nAbove = 0; uSuppFanins = 0; Kit_DsdObjForEachFanin( pNtk, pObj, iFaninLit, k ) { if ( Kit_DsdLitIsLeaf( pNtk, iFaninLit ) ) Above[nAbove++] = Abc_Lit2Var(iFaninLit); else uSuppFanins |= Kit_DsdLitSupport( pNtk, iFaninLit ); } // find the below variables nBelow = 0; for ( y = 0; y < 16; y++ ) if ( uSuppFanins & (1 << y) ) Below[nBelow++] = y; // create all pairs for ( x = 0; x < nAbove; x++ ) for ( y = 0; y < nBelow; y++ ) pTable[Above[x]][Below[y]]++; } } /**Function************************************************************* Synopsis [Creates commmon variable order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_CreateCommonOrder( char pTable[][16], int piCofVar[], int nCBars, int pPrios[], int nVars, int fVerbose ) { int Score[16] = {0}, pPres[16]; int i, y, x, iVarBest, ScoreMax, PrioCount; // mark the present variables for ( i = 0; i < nVars; i++ ) pPres[i] = 1; // remove cofactored variables for ( i = 0; i < nCBars; i++ ) pPres[piCofVar[i]] = 0; // compute scores for each leaf for ( i = 0; i < nVars; i++ ) { if ( pPres[i] == 0 ) continue; for ( y = 0; y < nVars; y++ ) Score[i] += pTable[i][y]; for ( x = 0; x < nVars; x++ ) Score[i] -= pTable[x][i]; } // print the scores if ( fVerbose ) { printf( "Scores: " ); for ( i = 0; i < nVars; i++ ) printf( "%c=%d ", 'a'+i, Score[i] ); printf( " " ); printf( "Prios: " ); } // derive variable priority // variables with equal score receive the same priority for ( i = 0; i < nVars; i++ ) pPrios[i] = 16; // iterate until variables remain for ( PrioCount = 1; ; PrioCount++ ) { // find the present variable with the highest score iVarBest = -1; ScoreMax = -100000; for ( i = 0; i < nVars; i++ ) { if ( pPres[i] == 0 ) continue; if ( ScoreMax < Score[i] ) { ScoreMax = Score[i]; iVarBest = i; } } if ( iVarBest == -1 ) break; // give the next priority to all vars having this score if ( fVerbose ) printf( "%d=", PrioCount ); for ( i = 0; i < nVars; i++ ) { if ( pPres[i] == 0 ) continue; if ( Score[i] == ScoreMax ) { pPrios[i] = PrioCount; pPres[i] = 0; if ( fVerbose ) printf( "%c", 'a'+i ); } } if ( fVerbose ) printf( " " ); } if ( fVerbose ) printf( "\n" ); } /**Function************************************************************* Synopsis [Finds components with the highest priority.] Description [Returns the number of components selected.] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_FindHighest( Kit_DsdNtk_t ** ppNtks, int * piLits, int nSize, int * pPrio, int * pDecision ) { Kit_DsdObj_t * pObj; unsigned uSupps[8], uSuppFanin, uSuppTotal, uSuppLarge; int i, pTriv[8], PrioMin, iVarMax, nComps, fOneNonTriv; // find individual support and total support uSuppTotal = 0; for ( i = 0; i < nSize; i++ ) { pTriv[i] = 1; if ( piLits[i] < 0 ) uSupps[i] = 0; else if ( Kit_DsdLitIsLeaf(ppNtks[i], piLits[i]) ) uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ); else { pObj = Kit_DsdNtkObj( ppNtks[i], Abc_Lit2Var(piLits[i]) ); if ( pObj->Type == KIT_DSD_PRIME ) { pTriv[i] = 0; uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[0] ); } else { assert( pObj->nFans == 2 ); if ( !Kit_DsdLitIsLeaf(ppNtks[i], pObj->pFans[0]) ) pTriv[i] = 0; uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[1] ); } uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ) & ~uSuppFanin; } assert( uSupps[i] <= 0xFFFF ); uSuppTotal |= uSupps[i]; } if ( uSuppTotal == 0 ) return 0; // find one support variable with the highest priority PrioMin = ABC_INFINITY; iVarMax = -1; for ( i = 0; i < 16; i++ ) if ( uSuppTotal & (1 << i) ) if ( PrioMin > pPrio[i] ) { PrioMin = pPrio[i]; iVarMax = i; } assert( iVarMax != -1 ); // select components, which have this variable nComps = 0; fOneNonTriv = 0; uSuppLarge = 0; for ( i = 0; i < nSize; i++ ) if ( uSupps[i] & (1<pIfMan) ); // iterate over the nodes if ( p->pPars->fVeryVerbose ) printf( "Decision: " ); for ( i = 0; i < nSize; i++ ) { if ( pDecision[i] ) { if ( p->pPars->fVeryVerbose ) printf( "%d ", i ); assert( piLits[i] >= 0 ); pObj = Kit_DsdNtkObj( ppNtks[i], Abc_Lit2Var(piLits[i]) ); if ( pObj == NULL ) piLitsNew[i] = -2; else if ( pObj->Type == KIT_DSD_PRIME ) piLitsNew[i] = pObj->pFans[0]; else piLitsNew[i] = pObj->pFans[1]; } else piLitsNew[i] = piLits[i]; } if ( p->pPars->fVeryVerbose ) printf( "\n" ); // call again pResPrev = Lpk_MapTreeMulti_rec( p, ppNtks, piLitsNew, piCofVar, nCBars, ppLeaves, nLeaves, pPrio ); // create new set of nodes for ( i = 0; i < nSize; i++ ) { if ( pDecision[i] ) pObjsNew[nCBars][i] = Lpk_MapTree_rec( p, ppNtks[i], ppLeaves, piLits[i], pResPrev ); else if ( piLits[i] == -1 ) pObjsNew[nCBars][i] = If_ManConst1(p->pIfMan); else if ( piLits[i] == -2 ) pObjsNew[nCBars][i] = If_Not( If_ManConst1(p->pIfMan) ); else pObjsNew[nCBars][i] = pResPrev; } // create MUX using these outputs for ( k = nCBars; k > 0; k-- ) { nSize /= 2; for ( i = 0; i < nSize; i++ ) pObjsNew[k-1][i] = If_ManCreateMux( p->pIfMan, pObjsNew[k][2*i+0], pObjsNew[k][2*i+1], ppLeaves[piCofVar[k-1]] ); } assert( nSize == 1 ); return pObjsNew[0][0]; } /**Function************************************************************* Synopsis [Prepares the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) { static int Counter = 0; If_Obj_t * pResult; Kit_DsdNtk_t * ppNtks[8] = {0}, * pTemp; Kit_DsdObj_t * pRoot; int piCofVar[4], pPrios[16], pFreqs[16] = {0}, piLits[16]; int i, k, nCBars, nSize, nMemSize; unsigned * ppCofs[4][8], uSupport; char pTable[16][16] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; int fVerbose = p->pPars->fVeryVerbose; Counter++; // printf( "Run %d.\n", Counter ); // allocate storage for cofactors nMemSize = Kit_TruthWordNum(nVars); ppCofs[0][0] = ABC_ALLOC( unsigned, 32 * nMemSize ); nSize = 0; for ( i = 0; i < 4; i++ ) for ( k = 0; k < 8; k++ ) ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; assert( nSize == 32 ); // find the best cofactoring variables nCBars = Kit_DsdCofactoring( pTruth, nVars, piCofVar, p->pPars->nVarsShared, 0 ); // nCBars = 2; // piCofVar[0] = 0; // piCofVar[1] = 1; // copy the function Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); // decompose w.r.t. these variables for ( k = 0; k < nCBars; k++ ) { nSize = (1 << k); for ( i = 0; i < nSize; i++ ) { Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); } } nSize = (1 << nCBars); // compute DSD networks for ( i = 0; i < nSize; i++ ) { ppNtks[i] = Kit_DsdDecompose( ppCofs[nCBars][i], nVars ); ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) { printf( "Cof%d%d: ", nCBars, i ); Kit_DsdPrint( stdout, ppNtks[i] ); } } // compute variable frequences for ( i = 0; i < nSize; i++ ) { uSupport = Kit_TruthSupport( ppCofs[nCBars][i], nVars ); for ( k = 0; k < nVars; k++ ) if ( uSupport & (1<pSupps[0] <= 0xFFFF ); // undec nodes should be rotated in such a way that the first input has as many shared inputs as possible Kit_DsdRotate( ppNtks[i], pFreqs ); // print the resulting networks if ( fVerbose ) { printf( "Cof%d%d: ", nCBars, i ); Kit_DsdPrint( stdout, ppNtks[i] ); } } for ( i = 0; i < nSize; i++ ) { // collect the roots pRoot = Kit_DsdNtkRoot(ppNtks[i]); if ( pRoot->Type == KIT_DSD_CONST1 ) piLits[i] = Abc_LitIsCompl(ppNtks[i]->Root)? -2: -1; else if ( pRoot->Type == KIT_DSD_VAR ) piLits[i] = Abc_LitNotCond( pRoot->pFans[0], Abc_LitIsCompl(ppNtks[i]->Root) ); else piLits[i] = ppNtks[i]->Root; } // recursively construct AIG for mapping p->fCofactoring = 1; pResult = Lpk_MapTreeMulti_rec( p, ppNtks, piLits, piCofVar, nCBars, ppLeaves, nVars, pPrios ); p->fCofactoring = 0; if ( fVerbose ) printf( "\n" ); // verify the transformations nSize = (1 << nCBars); for ( i = 0; i < nSize; i++ ) Kit_DsdTruth( ppNtks[i], ppCofs[nCBars][i] ); // mux the truth tables for ( k = nCBars-1; k >= 0; k-- ) { nSize = (1 << k); for ( i = 0; i < nSize; i++ ) Kit_TruthMuxVar( ppCofs[k][i], ppCofs[k+1][2*i+0], ppCofs[k+1][2*i+1], nVars, piCofVar[k] ); } if ( !Extra_TruthIsEqual( pTruth, ppCofs[0][0], nVars ) ) printf( "Verification failed.\n" ); // free the networks for ( i = 0; i < 8; i++ ) if ( ppNtks[i] ) Kit_DsdNtkFree( ppNtks[i] ); ABC_FREE( ppCofs[0][0] ); return pResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkMux.c000066400000000000000000000224111300674244400230500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkMux.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the best cofactoring variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lpk_MapTreeBestCofVar( Lpk_Man_t * p, unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ) { int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin; // iterate through variables iBestVar = -1; nSuppSizeMin = KIT_INFINITY; for ( i = 0; i < nVars; i++ ) { // cofactor the functiona and get support sizes Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars ); nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars ); nSuppSizeCur = nSuppSizeCur0 + nSuppSizeCur1; // skip cofactoring that goes above the limit if ( nSuppSizeCur0 > p->pPars->nLutSize || nSuppSizeCur1 > p->pPars->nLutSize ) continue; // compare this variable with other variables if ( nSuppSizeMin > nSuppSizeCur ) { nSuppSizeMin = nSuppSizeCur; iBestVar = i; } } // cofactor w.r.t. this variable if ( iBestVar != -1 ) { Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar ); Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar ); } return iBestVar; } /**Function************************************************************* Synopsis [Maps the function by the best cofactoring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) { unsigned * pCof0 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 0 ); unsigned * pCof1 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 1 ); If_Obj_t * pObj0, * pObj1; Kit_DsdNtk_t * ppNtks[2]; int iBestVar; assert( nVars > 3 ); p->fCalledOnce = 1; // cofactor w.r.t. the best variable iBestVar = Lpk_MapTreeBestCofVar( p, pTruth, nVars, pCof0, pCof1 ); if ( iBestVar == -1 ) return NULL; // decompose the functions ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); if ( p->pPars->fVeryVerbose ) { printf( "Cofactoring w.r.t. var %c (%d -> %d+%d supp vars):\n", 'a'+iBestVar, nVars, Kit_TruthSupportSize(pCof0, nVars), Kit_TruthSupportSize(pCof1, nVars) ); Kit_DsdPrintExpanded( ppNtks[0] ); Kit_DsdPrintExpanded( ppNtks[1] ); } // map the DSD structures pObj0 = Lpk_MapTree_rec( p, ppNtks[0], ppLeaves, ppNtks[0]->Root, NULL ); pObj1 = Lpk_MapTree_rec( p, ppNtks[1], ppLeaves, ppNtks[1]->Root, NULL ); Kit_DsdNtkFree( ppNtks[0] ); Kit_DsdNtkFree( ppNtks[1] ); return If_ManCreateMux( p->pIfMan, pObj0, pObj1, ppLeaves[iBestVar] ); } /**Function************************************************************* Synopsis [Implements support-reducing decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) { Kit_DsdNtk_t * pNtkDec, * pNtkComp, * ppNtks[2], * pTemp; If_Obj_t * pObjNew; unsigned * pCof0 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 0 ); unsigned * pCof1 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 1 ); unsigned * pDec0 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 2 ); unsigned * pDec1 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 3 ); unsigned * pDec = (unsigned *)Vec_PtrEntry( p->vTtNodes, 4 ); unsigned * pCo00 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 5 ); unsigned * pCo01 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 6 ); unsigned * pCo10 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 7 ); unsigned * pCo11 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 8 ); unsigned * pCo0 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 9 ); unsigned * pCo1 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 10 ); unsigned * pCo = (unsigned *)Vec_PtrEntry( p->vTtNodes, 11 ); int TrueMint0, TrueMint1, FalseMint0, FalseMint1; int uSubsets, uSubset0, uSubset1, iVar, iVarReused, i; // determine if supp-red decomposition exists uSubsets = Lpk_MapSuppRedDecSelect( p, pTruth, nVars, &iVar, &iVarReused ); if ( uSubsets == 0 ) return NULL; p->nCalledSRed++; // get the cofactors Kit_TruthCofactor0New( pCof0, pTruth, nVars, iVar ); Kit_TruthCofactor1New( pCof1, pTruth, nVars, iVar ); // get the bound sets uSubset0 = uSubsets & 0xFFFF; uSubset1 = uSubsets >> 16; // compute the decomposed functions ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp ); ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp ); Kit_DsdTruthPartial( p->pDsdMan, ppNtks[0], pDec0, uSubset0 ); Kit_DsdTruthPartial( p->pDsdMan, ppNtks[1], pDec1, uSubset1 ); // Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[0], uSubset0, iVarReused, pCo0, pDec0 ); // Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[1], uSubset1, iVarReused, pCo1, pDec1 ); Kit_DsdNtkFree( ppNtks[0] ); Kit_DsdNtkFree( ppNtks[1] ); //Kit_DsdPrintFromTruth( pDec0, nVars ); //Kit_DsdPrintFromTruth( pDec1, nVars ); // get the decomposed function Kit_TruthMuxVar( pDec, pDec0, pDec1, nVars, iVar ); // find any true assignments of the decomposed functions TrueMint0 = Kit_TruthFindFirstBit( pDec0, nVars ); TrueMint1 = Kit_TruthFindFirstBit( pDec1, nVars ); assert( TrueMint0 >= 0 && TrueMint1 >= 0 ); // find any false assignments of the decomposed functions FalseMint0 = Kit_TruthFindFirstZero( pDec0, nVars ); FalseMint1 = Kit_TruthFindFirstZero( pDec1, nVars ); assert( FalseMint0 >= 0 && FalseMint1 >= 0 ); // cofactor the cofactors according to these minterms Kit_TruthCopy( pCo00, pCof0, nVars ); Kit_TruthCopy( pCo01, pCof0, nVars ); for ( i = 0; i < nVars; i++ ) if ( uSubset0 & (1 << i) ) { if ( FalseMint0 & (1 << i) ) Kit_TruthCofactor1( pCo00, nVars, i ); else Kit_TruthCofactor0( pCo00, nVars, i ); if ( TrueMint0 & (1 << i) ) Kit_TruthCofactor1( pCo01, nVars, i ); else Kit_TruthCofactor0( pCo01, nVars, i ); } Kit_TruthCopy( pCo10, pCof1, nVars ); Kit_TruthCopy( pCo11, pCof1, nVars ); for ( i = 0; i < nVars; i++ ) if ( uSubset1 & (1 << i) ) { if ( FalseMint1 & (1 << i) ) Kit_TruthCofactor1( pCo10, nVars, i ); else Kit_TruthCofactor0( pCo10, nVars, i ); if ( TrueMint1 & (1 << i) ) Kit_TruthCofactor1( pCo11, nVars, i ); else Kit_TruthCofactor0( pCo11, nVars, i ); } // derive the functions by composing them with the new variable (iVarReused) Kit_TruthMuxVar( pCo0, pCo00, pCo01, nVars, iVarReused ); Kit_TruthMuxVar( pCo1, pCo10, pCo11, nVars, iVarReused ); //Kit_DsdPrintFromTruth( pCo0, nVars ); //Kit_DsdPrintFromTruth( pCo1, nVars ); // derive the composition function Kit_TruthMuxVar( pCo , pCo0 , pCo1 , nVars, iVar ); // process the decomposed function pNtkDec = Kit_DsdDecompose( pDec, nVars ); pNtkComp = Kit_DsdDecompose( pCo, nVars ); //Kit_DsdPrint( stdout, pNtkDec ); //Kit_DsdPrint( stdout, pNtkComp ); //printf( "cofactored variable %c\n", 'a' + iVar ); //printf( "reused variable %c\n", 'a' + iVarReused ); ppLeaves[iVarReused] = Lpk_MapTree_rec( p, pNtkDec, ppLeaves, pNtkDec->Root, NULL ); pObjNew = Lpk_MapTree_rec( p, pNtkComp, ppLeaves, pNtkComp->Root, NULL ); Kit_DsdNtkFree( pNtkDec ); Kit_DsdNtkFree( pNtkComp ); return pObjNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpkSets.c000066400000000000000000000326611300674244400232250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpkSets.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpkSets.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Lpk_Set_t_ Lpk_Set_t; struct Lpk_Set_t_ { char iVar; // the cofactoring variable char Over; // the overlap in supports char SRed; // the support reduction char Size; // the size of the boundset unsigned uSubset0; // the first subset (with removed) unsigned uSubset1; // the second subset (with removed) }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Recursively computes decomposable subsets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Lpk_ComputeSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets ) { unsigned i, iLitFanin, uSupport, uSuppCur; Kit_DsdObj_t * pObj; // consider the case of simple gate pObj = Kit_DsdNtkObj( p, Abc_Lit2Var(iLit) ); if ( pObj == NULL ) return (1 << Abc_Lit2Var(iLit)); if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) { unsigned uSupps[16], Limit, s; uSupport = 0; Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) { uSupps[i] = Lpk_ComputeSets_rec( p, iLitFanin, vSets ); uSupport |= uSupps[i]; } // create all subsets, except empty and full Limit = (1 << pObj->nFans) - 1; for ( s = 1; s < Limit; s++ ) { uSuppCur = 0; for ( i = 0; i < pObj->nFans; i++ ) if ( s & (1 << i) ) uSuppCur |= uSupps[i]; Vec_IntPush( vSets, uSuppCur ); } return uSupport; } assert( pObj->Type == KIT_DSD_PRIME ); // get the cumulative support of all fanins uSupport = 0; Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) { uSuppCur = Lpk_ComputeSets_rec( p, iLitFanin, vSets ); uSupport |= uSuppCur; Vec_IntPush( vSets, uSuppCur ); } return uSupport; } /**Function************************************************************* Synopsis [Computes the set of subsets of decomposable variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Lpk_ComputeSets( Kit_DsdNtk_t * p, Vec_Int_t * vSets ) { unsigned uSupport, Entry; int Number, i; assert( p->nVars <= 16 ); Vec_IntClear( vSets ); Vec_IntPush( vSets, 0 ); if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) return 0; if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) { uSupport = ( 1 << Abc_Lit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); Vec_IntPush( vSets, uSupport ); return uSupport; } uSupport = Lpk_ComputeSets_rec( p, p->Root, vSets ); assert( (uSupport & 0xFFFF0000) == 0 ); Vec_IntPush( vSets, uSupport ); // set the remaining variables Vec_IntForEachEntry( vSets, Number, i ) { Entry = Number; Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) ); } return uSupport; } /**Function************************************************************* Synopsis [Prints the sets of subsets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Lpk_PrintSetOne( int uSupport ) { unsigned k; for ( k = 0; k < 16; k++ ) if ( uSupport & (1<> 16) ); // get the support reduction nSuppRed = nSuppSize - 1 - nSuppOver; // only consider support-reducing subsets if ( nSuppRed <= 0 ) continue; // check if this support is already used if ( TravId[uSupp] < nTravId ) { Used[nUsed++] = uSupp; TravId[uSupp] = nTravId; SRed[uSupp] = nSuppRed; Over[uSupp] = nSuppOver; Parents[uSupp] = (k << 16) | i; } else if ( TravId[uSupp] == nTravId && SRed[uSupp] < nSuppRed ) { TravId[uSupp] = nTravId; SRed[uSupp] = nSuppRed; Over[uSupp] = nSuppOver; Parents[uSupp] = (k << 16) | i; } } // find the minimum overlap nMinOver = 1000; for ( s = 0; s < nUsed; s++ ) if ( nMinOver > Over[Used[s]] ) nMinOver = Over[Used[s]]; // collect the accumulated ones for ( s = 0; s < nUsed; s++ ) if ( Over[Used[s]] == nMinOver ) { // save the entry if ( *pSize == nSizeLimit ) return; pEntry = pStore + (*pSize)++; i = Parents[Used[s]] & 0xFFFF; k = Parents[Used[s]] >> 16; pEntry->uSubset0 = Vec_IntEntry(vSets0, i); pEntry->uSubset1 = Vec_IntEntry(vSets1, k); Entry = pEntry->uSubset0 | pEntry->uSubset1; // record the cofactoring variable pEntry->iVar = iCofVar; // set the bound set size pEntry->Size = Kit_WordCountOnes( Entry & 0xFFFF ); // get the number of overlapping vars pEntry->Over = Kit_WordCountOnes( Entry & (Entry >> 16) ); // get the support reduction pEntry->SRed = pEntry->Size - 1 - pEntry->Over; assert( pEntry->SRed > 0 ); } } /**Function************************************************************* Synopsis [Prints one set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lpk_MapSuppPrintSet( Lpk_Set_t * pSet, int i ) { unsigned Entry; Entry = pSet->uSubset0 | pSet->uSubset1; printf( "%2d : ", i ); printf( "Var = %c ", 'a' + pSet->iVar ); printf( "Size = %2d ", pSet->Size ); printf( "Over = %2d ", pSet->Over ); printf( "SRed = %2d ", pSet->SRed ); Lpk_PrintSetOne( Entry ); printf( " " ); Lpk_PrintSetOne( Entry >> 16 ); printf( "\n" ); } /**Function************************************************************* Synopsis [Evaluates the cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused ) { static int nStoreSize = 256; static Lpk_Set_t pStore[256], * pSet, * pSetBest; Kit_DsdNtk_t * ppNtks[2], * pTemp; Vec_Int_t * vSets0 = p->vSets[0]; Vec_Int_t * vSets1 = p->vSets[1]; unsigned * pCof0 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 0 ); unsigned * pCof1 = (unsigned *)Vec_PtrEntry( p->vTtNodes, 1 ); int nSets, i, SizeMax;//, SRedMax; unsigned Entry; int fVerbose = p->pPars->fVeryVerbose; // int fVerbose = 0; // collect decomposable subsets for each pair of cofactors if ( fVerbose ) { printf( "\nExploring support-reducing bound-sets of function:\n" ); Kit_DsdPrintFromTruth( pTruth, nVars ); } nSets = 0; for ( i = 0; i < nVars; i++ ) { if ( fVerbose ) printf( "Evaluating variable %c:\n", 'a'+i ); // evaluate the cofactor pair Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); // decompose and expand ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp ); ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp ); if ( fVerbose ) Kit_DsdPrint( stdout, ppNtks[0] ); if ( fVerbose ) Kit_DsdPrint( stdout, ppNtks[1] ); // compute subsets Lpk_ComputeSets( ppNtks[0], vSets0 ); Lpk_ComputeSets( ppNtks[1], vSets1 ); // print subsets if ( fVerbose ) Lpk_PrintSets( vSets0 ); if ( fVerbose ) Lpk_PrintSets( vSets1 ); // free the networks Kit_DsdNtkFree( ppNtks[0] ); Kit_DsdNtkFree( ppNtks[1] ); // evaluate the pair Lpk_ComposeSets( vSets0, vSets1, nVars, i, pStore, &nSets, nStoreSize ); } // print the results if ( fVerbose ) printf( "\n" ); if ( fVerbose ) for ( i = 0; i < nSets; i++ ) Lpk_MapSuppPrintSet( pStore + i, i ); // choose the best subset SizeMax = 0; pSetBest = NULL; for ( i = 0; i < nSets; i++ ) { pSet = pStore + i; if ( pSet->Size > p->pPars->nLutSize - 1 ) continue; if ( SizeMax < pSet->Size ) { pSetBest = pSet; SizeMax = pSet->Size; } } /* // if the best is not choosen, select the one with largest reduction SRedMax = 0; if ( pSetBest == NULL ) { for ( i = 0; i < nSets; i++ ) { pSet = pStore + i; if ( SRedMax < pSet->SRed ) { pSetBest = pSet; SRedMax = pSet->SRed; } } } */ if ( pSetBest == NULL ) { if ( fVerbose ) printf( "Could not select a subset.\n" ); return 0; } else { if ( fVerbose ) printf( "Selected the following subset:\n" ); if ( fVerbose ) Lpk_MapSuppPrintSet( pSetBest, pSetBest - pStore ); } // prepare the return result // get the remaining variables Entry = ((pSetBest->uSubset0 >> 16) | (pSetBest->uSubset1 >> 16)); // get the variables to be removed Entry = Kit_BitMask(nVars) & ~(1<iVar) & ~Entry; // make sure there are some - otherwise it is not supp-red assert( Entry ); // remember the first such variable *piVarReused = Kit_WordFindFirstBit( Entry ); *piVar = pSetBest->iVar; return (pSetBest->uSubset1 << 16) | (pSetBest->uSubset0 & 0xFFFF); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/lpk_.c000066400000000000000000000026731300674244400225250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [lpk_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Fast Boolean matching for LUT structures.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: lpk_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "lpkInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/lpk/module.make000066400000000000000000000004361300674244400235530ustar00rootroot00000000000000SRC += src/opt/lpk/lpkCore.c \ src/opt/lpk/lpkAbcDec.c \ src/opt/lpk/lpkAbcMux.c \ src/opt/lpk/lpkAbcDsd.c \ src/opt/lpk/lpkAbcUtil.c \ src/opt/lpk/lpkCut.c \ src/opt/lpk/lpkMan.c \ src/opt/lpk/lpkMap.c \ src/opt/lpk/lpkMulti.c \ src/opt/lpk/lpkMux.c \ src/opt/lpk/lpkSets.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/000077500000000000000000000000001300674244400214235ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfs.h000066400000000000000000000064751300674244400223750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfs.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfs.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__mfs__mfs_h #define ABC__opt__mfs__mfs_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Mfs_Par_t_ Mfs_Par_t; struct Mfs_Par_t_ { // general parameters int nWinTfoLevs; // the maximum fanout levels int nFanoutsMax; // the maximum number of fanouts int nDepthMax; // the maximum number of logic levels int nWinMax; // the maximum size of the window int nGrowthLevel; // the maximum allowed growth in level int nBTLimit; // the maximum number of conflicts in one SAT run int fRrOnly; // perform redundance removal int fResub; // performs resubstitution int fArea; // performs optimization for area int fMoreEffort; // performs high-affort minimization int fSwapEdge; // performs edge swapping int fOneHotness; // adds one-hotness conditions int fDelay; // performs optimization for delay int fPower; // performs power-aware optimization int fGiaSat; // use new SAT solver int fVerbose; // enable basic stats int fVeryVerbose; // enable detailed stats }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== mfsCore.c ==========================================================*/ extern void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars ); extern int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsCore.c000066400000000000000000000443301300674244400231710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Core procedures of this package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars ) { memset( pPars, 0, sizeof(Mfs_Par_t) ); pPars->nWinTfoLevs = 2; pPars->nFanoutsMax = 30; pPars->nDepthMax = 20; pPars->nWinMax = 300; pPars->nGrowthLevel = 0; pPars->nBTLimit = 5000; pPars->fRrOnly = 0; pPars->fResub = 1; pPars->fArea = 0; pPars->fMoreEffort = 0; pPars->fSwapEdge = 0; pPars->fOneHotness = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } /* int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i; // try replacing area critical fanins Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( Abc_MfsObjProb(p, pFanin) >= 0.4 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) return 1; } else if ( Abc_MfsObjProb(p, pFanin) >= 0.3 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) return 1; } } return 0; } */ int Abc_WinNode(Mfs_Man_t * p, Abc_Obj_t *pNode) { // abctime clk; // Abc_Obj_t * pFanin; // int i; p->nNodesTried++; // prepare data structure for this node Mfs_ManClean( p ); // compute window roots, window support, and window nodes p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); if ( p->pPars->nWinMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinMax ) return 1; // compute the divisors of the window p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 ); p->nTotalDivs += Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode); // construct AIG for the window p->pAigWin = Abc_NtkConstructAig( p, pNode ); // translate it into CNF p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); // create the SAT problem p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 ); if ( p->pSat == NULL ) { p->nNodesBad++; return 1; } return 0; } /* int Abc_NtkMfsPowerResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) { abctime clk; Abc_Obj_t * pFanin; int i; if (Abc_WinNode(p, pNode) // something wrong return 1; // solve the SAT problem // Abc_NtkMfsEdgePower( p, pNode ); // try replacing area critical fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_MfsObjProb(p, pFanin) >= 0.37 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) return 1; Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_MfsObjProb(p, pFanin) >= 0.1 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) return 1; if ( Abc_ObjFaninNum(pNode) == p->nFaninMax ) return 0; // try replacing area critical fanins while adding two new fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_MfsObjProb(p, pFanin) >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) return 1; } return 0; return 1; } */ void Abc_NtkMfsPowerResub( Mfs_Man_t * p, Mfs_Par_t * pPars) { int i, k; Abc_Obj_t *pFanin, *pNode; Abc_Ntk_t *pNtk = p->pNtk; int nFaninMax = Abc_NtkGetFaninMax(p->pNtk); Abc_NtkForEachNode( pNtk, pNode, k ) { if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) continue; if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) continue; if (Abc_WinNode(p, pNode) ) // something wrong continue; // solve the SAT problem // Abc_NtkMfsEdgePower( p, pNode ); // try replacing area critical fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_MfsObjProb(p, pFanin) >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) continue; } Abc_NtkForEachNode( pNtk, pNode, k ) { if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) continue; if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) continue; if (Abc_WinNode(p, pNode) ) // something wrong continue; // solve the SAT problem // Abc_NtkMfsEdgePower( p, pNode ); // try replacing area critical fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_MfsObjProb(p, pFanin) >= 0.35 && Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) continue; } Abc_NtkForEachNode( pNtk, pNode, k ) { if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) continue; if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax ) continue; if (Abc_WinNode(p, pNode) ) // something wrong continue; Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_MfsObjProb(p, pFanin) >= 0.2 && Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) continue; } /* Abc_NtkForEachNode( pNtk, pNode, k ) { if ( p->pPars->nDepthMax && (int)pNode->Level > p->pPars->nDepthMax ) continue; if ( Abc_ObjFaninNum(pNode) < 2 || Abc_ObjFaninNum(pNode) > nFaninMax - 2) continue; if (Abc_WinNode(p, pNode) ) // something wrong continue; Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_MfsObjProb(p, pFanin) >= 0.37 && Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) continue; } */ } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode ) { abctime clk; p->nNodesTried++; // prepare data structure for this node Mfs_ManClean( p ); // compute window roots, window support, and window nodes clk = Abc_Clock(); p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->timeWin += Abc_Clock() - clk; if ( p->pPars->nWinMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinMax ) { p->nMaxDivs++; return 1; } // compute the divisors of the window clk = Abc_Clock(); p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 ); p->nTotalDivs += Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode); p->timeDiv += Abc_Clock() - clk; // construct AIG for the window clk = Abc_Clock(); p->pAigWin = Abc_NtkConstructAig( p, pNode ); p->timeAig += Abc_Clock() - clk; // translate it into CNF clk = Abc_Clock(); p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); p->timeCnf += Abc_Clock() - clk; // create the SAT problem clk = Abc_Clock(); p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 ); if ( p->pSat == NULL ) { p->nNodesBad++; return 1; } //clk = Abc_Clock(); // if ( p->pPars->fGiaSat ) // Abc_NtkMfsConstructGia( p ); //p->timeGia += Abc_Clock() - clk; // solve the SAT problem if ( p->pPars->fPower ) Abc_NtkMfsEdgePower( p, pNode ); else if ( p->pPars->fSwapEdge ) Abc_NtkMfsEdgeSwapEval( p, pNode ); else { Abc_NtkMfsResubNode( p, pNode ); if ( p->pPars->fMoreEffort ) Abc_NtkMfsResubNode2( p, pNode ); } p->timeSat += Abc_Clock() - clk; // if ( p->pPars->fGiaSat ) // Abc_NtkMfsDeconstructGia( p ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Hop_Obj_t * pObj; int RetValue; float dProb; extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); int nGain; abctime clk; p->nNodesTried++; // prepare data structure for this node Mfs_ManClean( p ); // compute window roots, window support, and window nodes clk = Abc_Clock(); p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->timeWin += Abc_Clock() - clk; // count the number of patterns // p->dTotalRatios += Abc_NtkConstraintRatio( p, pNode ); // construct AIG for the window clk = Abc_Clock(); p->pAigWin = Abc_NtkConstructAig( p, pNode ); p->timeAig += Abc_Clock() - clk; // translate it into CNF clk = Abc_Clock(); p->pCnf = Cnf_DeriveSimple( p->pAigWin, Abc_ObjFaninNum(pNode) ); p->timeCnf += Abc_Clock() - clk; // create the SAT problem clk = Abc_Clock(); p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); if ( p->pSat && p->pPars->fOneHotness ) Abc_NtkAddOneHotness( p ); if ( p->pSat == NULL ) return 0; // solve the SAT problem RetValue = Abc_NtkMfsSolveSat( p, pNode ); p->nTotConfLevel += p->pSat->stats.conflicts; p->timeSat += Abc_Clock() - clk; if ( RetValue == 0 ) { p->nTimeOutsLevel++; p->nTimeOuts++; return 0; } // minimize the local function of the node using bi-decomposition assert( p->nFanins == Abc_ObjFaninNum(pNode) ); dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; pObj = Abc_NodeIfNodeResyn( p->pManDec, (Hop_Man_t *)pNode->pNtk->pManFunc, (Hop_Obj_t *)pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb ); nGain = Hop_DagSize((Hop_Obj_t *)pNode->pData) - Hop_DagSize(pObj); if ( nGain >= 0 ) { p->nNodesDec++; p->nNodesGained += nGain; p->nNodesGainedLevel += nGain; pNode->pData = pObj; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Bdc_Par_t Pars = {0}, * pDecPars = &Pars; ProgressBar * pProgress; Mfs_Man_t * p; Abc_Obj_t * pObj; Vec_Vec_t * vLevels; Vec_Ptr_t * vNodes; int i, k, nNodes, nFaninMax; abctime clk = Abc_Clock(), clk2; int nTotalNodesBeg = Abc_NtkNodeNum(pNtk); int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk); assert( Abc_NtkIsLogic(pNtk) ); nFaninMax = Abc_NtkGetFaninMax(pNtk); if ( pPars->fResub ) { if ( nFaninMax > 8 ) { printf( "Nodes with more than %d fanins will not be processed.\n", 8 ); nFaninMax = 8; } } else { if ( nFaninMax > MFS_FANIN_MAX ) { printf( "Nodes with more than %d fanins will not be processed.\n", MFS_FANIN_MAX ); nFaninMax = MFS_FANIN_MAX; } } // perform the network sweep // Abc_NtkSweep( pNtk, 0 ); // convert into the AIG if ( !Abc_NtkToAig(pNtk) ) { fprintf( stdout, "Converting to AIGs has failed.\n" ); return 0; } assert( Abc_NtkHasAig(pNtk) ); // start the manager p = Mfs_ManAlloc( pPars ); p->pNtk = pNtk; p->nFaninMax = nFaninMax; // precomputer power-aware metrics if ( pPars->fPower ) { extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ); if ( pPars->fResub ) p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); else p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 ); #if 0 printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); #else p->TotalSwitchingBeg = Abc_NtkMfsTotalSwitching(pNtk); #endif } if ( pNtk->pExcare ) { Abc_Ntk_t * pTemp; if ( Abc_NtkPiNum((Abc_Ntk_t *)pNtk->pExcare) != Abc_NtkCiNum(pNtk) ) printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", Abc_NtkPiNum((Abc_Ntk_t *)pNtk->pExcare), Abc_NtkCiNum(pNtk) ); else { pTemp = Abc_NtkStrash( (Abc_Ntk_t *)pNtk->pExcare, 0, 0, 0 ); p->pCare = Abc_NtkToDar( pTemp, 0, 0 ); Abc_NtkDelete( pTemp ); p->vSuppsInv = Aig_ManSupportsInverse( p->pCare ); } } if ( p->pCare != NULL ) printf( "Performing optimization with %d external care clauses.\n", Aig_ManCoNum(p->pCare) ); // prepare the BDC manager if ( !pPars->fResub ) { pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax; pDecPars->fVerbose = pPars->fVerbose; p->vTruth = Vec_IntAlloc( 0 ); p->pManDec = Bdc_ManAlloc( pDecPars ); } // label the register outputs if ( p->pCare ) { Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pData = (void *)(ABC_PTRUINT_T)i; } // compute levels Abc_NtkLevel( pNtk ); Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); // compute don't-cares for each node nNodes = 0; p->nTotalNodesBeg = nTotalNodesBeg; p->nTotalEdgesBeg = nTotalEdgesBeg; if ( pPars->fResub ) { #if 0 printf( "TotalSwitching (%7.2f --> ", Abc_NtkMfsTotalSwitching(pNtk) ); #endif if (pPars->fPower) { Abc_NtkMfsPowerResub( p, pPars); } else { pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) { if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) continue; if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) continue; if ( !p->pPars->fVeryVerbose ) Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( pPars->fResub ) Abc_NtkMfsResub( p, pObj ); else Abc_NtkMfsNode( p, pObj ); } Extra_ProgressBarStop( pProgress ); #if 0 printf( " %7.2f )\n", Abc_NtkMfsTotalSwitching(pNtk) ); #endif } } else { #if 0 printf( "Total switching before = %7.2f, ----> ", Abc_NtkMfsTotalSwitching(pNtk) ); #endif pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); vLevels = Abc_NtkLevelize( pNtk ); Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) { if ( !p->pPars->fVeryVerbose ) Extra_ProgressBarUpdate( pProgress, nNodes, NULL ); p->nNodesGainedLevel = 0; p->nTotConfLevel = 0; p->nTimeOutsLevel = 0; clk2 = Abc_Clock(); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) break; if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) continue; if ( pPars->fResub ) Abc_NtkMfsResub( p, pObj ); else Abc_NtkMfsNode( p, pObj ); } nNodes += Vec_PtrSize(vNodes); if ( pPars->fVerbose ) { /* printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", k, Vec_PtrSize(vNodes), 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes), 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes), 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) ); ABC_PRT( "Time", Abc_Clock() - clk2 ); */ } } Extra_ProgressBarStop( pProgress ); Vec_VecFree( vLevels ); #if 0 printf( " %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); #endif } Abc_NtkStopReverseLevels( pNtk ); // perform the sweeping if ( !pPars->fResub ) { extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); // Abc_NtkSweep( pNtk, 0 ); // Abc_NtkBidecResyn( pNtk, 0 ); } p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk); p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk); // undo labesl if ( p->pCare ) { Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pData = NULL; } if ( pPars->fPower ) { #if 1 p->TotalSwitchingEnd = Abc_NtkMfsTotalSwitching(pNtk); // printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); #else printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); #endif } // free the manager p->timeTotal = Abc_Clock() - clk; Mfs_ManStop( p ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsCore_.c000066400000000000000000000305301300674244400233250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Core procedures of this package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsParsDefault( Mfs_Par_t * pPars ) { memset( pPars, 0, sizeof(Mfs_Par_t) ); pPars->nWinTfoLevs = 2; pPars->nFanoutsMax = 10; pPars->nDepthMax = 20; pPars->nWinSizeMax = 300; pPars->nGrowthLevel = 0; pPars->nBTLimit = 5000; pPars->fResub = 1; pPars->fArea = 0; pPars->fMoreEffort = 0; pPars->fSwapEdge = 0; pPars->fOneHotness = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsResub( Mfs_Man_t * p, Abc_Obj_t * pNode ) { clock_t clk; p->nNodesTried++; // prepare data structure for this node Mfs_ManClean( p ); // compute window roots, window support, and window nodes clk = clock(); p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->timeWin += clock() - clk; if ( p->pPars->nWinSizeMax && Vec_PtrSize(p->vNodes) > p->pPars->nWinSizeMax ) return 1; // compute the divisors of the window clk = clock(); p->vDivs = Abc_MfsComputeDivisors( p, pNode, Abc_ObjRequiredLevel(pNode) - 1 ); p->nTotalDivs += Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode); p->timeDiv += clock() - clk; // construct AIG for the window clk = clock(); p->pAigWin = Abc_NtkConstructAig( p, pNode ); p->timeAig += clock() - clk; // translate it into CNF clk = clock(); p->pCnf = Cnf_DeriveSimple( p->pAigWin, 1 + Vec_PtrSize(p->vDivs) ); p->timeCnf += clock() - clk; // create the SAT problem clk = clock(); p->pSat = Abc_MfsCreateSolverResub( p, NULL, 0, 0 ); if ( p->pSat == NULL ) { p->nNodesBad++; return 1; } // solve the SAT problem if ( p->pPars->fPower ) Abc_NtkMfsEdgePower( p, pNode ); else if ( p->pPars->fSwapEdge ) Abc_NtkMfsEdgeSwapEval( p, pNode ); else { Abc_NtkMfsResubNode( p, pNode ); if ( p->pPars->fMoreEffort ) Abc_NtkMfsResubNode2( p, pNode ); } p->timeSat += clock() - clk; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Hop_Obj_t * pObj; int RetValue; float dProb; extern Hop_Obj_t * Abc_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); int nGain; clock_t clk; p->nNodesTried++; // prepare data structure for this node Mfs_ManClean( p ); // compute window roots, window support, and window nodes clk = clock(); p->vRoots = Abc_MfsComputeRoots( pNode, p->pPars->nWinTfoLevs, p->pPars->nFanoutsMax ); p->vSupp = Abc_NtkNodeSupport( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->vNodes = Abc_NtkDfsNodes( p->pNtk, (Abc_Obj_t **)Vec_PtrArray(p->vRoots), Vec_PtrSize(p->vRoots) ); p->timeWin += clock() - clk; // count the number of patterns // p->dTotalRatios += Abc_NtkConstraintRatio( p, pNode ); // construct AIG for the window clk = clock(); p->pAigWin = Abc_NtkConstructAig( p, pNode ); p->timeAig += clock() - clk; // translate it into CNF clk = clock(); p->pCnf = Cnf_DeriveSimple( p->pAigWin, Abc_ObjFaninNum(pNode) ); p->timeCnf += clock() - clk; // create the SAT problem clk = clock(); p->pSat = Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); if ( p->pSat && p->pPars->fOneHotness ) Abc_NtkAddOneHotness( p ); if ( p->pSat == NULL ) return 0; // solve the SAT problem RetValue = Abc_NtkMfsSolveSat( p, pNode ); p->nTotConfLevel += p->pSat->stats.conflicts; p->timeSat += clock() - clk; if ( RetValue == 0 ) { p->nTimeOutsLevel++; p->nTimeOuts++; return 0; } // minimize the local function of the node using bi-decomposition assert( p->nFanins == Abc_ObjFaninNum(pNode) ); dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0; pObj = Abc_NodeIfNodeResyn( p->pManDec, pNode->pNtk->pManFunc, pNode->pData, p->nFanins, p->vTruth, p->uCare, dProb ); nGain = Hop_DagSize(pNode->pData) - Hop_DagSize(pObj); if ( nGain >= 0 ) { p->nNodesDec++; p->nNodesGained += nGain; p->nNodesGainedLevel += nGain; pNode->pData = pObj; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Bdc_Par_t Pars = {0}, * pDecPars = &Pars; ProgressBar * pProgress; Mfs_Man_t * p; Abc_Obj_t * pObj; Vec_Vec_t * vLevels; Vec_Ptr_t * vNodes; int i, k, nNodes, nFaninMax; clock_t clk = clock(), clk2; int nTotalNodesBeg = Abc_NtkNodeNum(pNtk); int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk); assert( Abc_NtkIsLogic(pNtk) ); nFaninMax = Abc_NtkGetFaninMax(pNtk); if ( pPars->fResub ) { if ( nFaninMax > 8 ) { printf( "Nodes with more than %d fanins will not be processed.\n", 8 ); nFaninMax = 8; } } else { if ( nFaninMax > MFS_FANIN_MAX ) { printf( "Nodes with more than %d fanins will not be processed.\n", MFS_FANIN_MAX ); nFaninMax = MFS_FANIN_MAX; } } // perform the network sweep Abc_NtkSweep( pNtk, 0 ); // convert into the AIG if ( !Abc_NtkToAig(pNtk) ) { fprintf( stdout, "Converting to AIGs has failed.\n" ); return 0; } assert( Abc_NtkHasAig(pNtk) ); // start the manager p = Mfs_ManAlloc( pPars ); p->pNtk = pNtk; p->nFaninMax = nFaninMax; // precomputer power-aware metrics if ( pPars->fPower ) { extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ); if ( pPars->fResub ) p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); else p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 ); printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); } if ( pNtk->pExcare ) { Abc_Ntk_t * pTemp; if ( Abc_NtkPiNum(pNtk->pExcare) != Abc_NtkCiNum(pNtk) ) printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", Abc_NtkPiNum(pNtk->pExcare), Abc_NtkCiNum(pNtk) ); else { pTemp = Abc_NtkStrash( pNtk->pExcare, 0, 0, 0 ); p->pCare = Abc_NtkToDar( pTemp, 0, 0 ); Abc_NtkDelete( pTemp ); p->vSuppsInv = Aig_ManSupportsInverse( p->pCare ); } } if ( p->pCare != NULL ) printf( "Performing optimization with %d external care clauses.\n", Aig_ManPoNum(p->pCare) ); // prepare the BDC manager if ( !pPars->fResub ) { pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax; pDecPars->fVerbose = pPars->fVerbose; p->vTruth = Vec_IntAlloc( 0 ); p->pManDec = Bdc_ManAlloc( pDecPars ); } // label the register outputs if ( p->pCare ) { Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pData = (void *)(PORT_PTRUINT_T)i; } // compute levels Abc_NtkLevel( pNtk ); Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); // compute don't-cares for each node nNodes = 0; p->nTotalNodesBeg = nTotalNodesBeg; p->nTotalEdgesBeg = nTotalEdgesBeg; if ( pPars->fResub ) { pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) { if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) continue; if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) continue; if ( !p->pPars->fVeryVerbose ) Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( pPars->fResub ) Abc_NtkMfsResub( p, pObj ); else Abc_NtkMfsNode( p, pObj ); } Extra_ProgressBarStop( pProgress ); } else { pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); vLevels = Abc_NtkLevelize( pNtk ); Vec_VecForEachLevelStart( vLevels, vNodes, k, 1 ) { if ( !p->pPars->fVeryVerbose ) Extra_ProgressBarUpdate( pProgress, nNodes, NULL ); p->nNodesGainedLevel = 0; p->nTotConfLevel = 0; p->nTimeOutsLevel = 0; clk2 = clock(); Vec_PtrForEachEntry( vNodes, pObj, i ) { if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) break; if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) continue; if ( pPars->fResub ) Abc_NtkMfsResub( p, pObj ); else Abc_NtkMfsNode( p, pObj ); } nNodes += Vec_PtrSize(vNodes); if ( pPars->fVerbose ) { printf( "Lev = %2d. Node = %5d. Ave gain = %5.2f. Ave conf = %5.2f. T/o = %6.2f %% ", k, Vec_PtrSize(vNodes), 1.0*p->nNodesGainedLevel/Vec_PtrSize(vNodes), 1.0*p->nTotConfLevel/Vec_PtrSize(vNodes), 100.0*p->nTimeOutsLevel/Vec_PtrSize(vNodes) ); PRT( "Time", clock() - clk2 ); } } Extra_ProgressBarStop( pProgress ); Vec_VecFree( vLevels ); } Abc_NtkStopReverseLevels( pNtk ); // perform the sweeping if ( !pPars->fResub ) { extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); // Abc_NtkSweep( pNtk, 0 ); // Abc_NtkBidecResyn( pNtk, 0 ); } p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk); p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk); // undo labesl if ( p->pCare ) { Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pData = NULL; } if ( pPars->fPower ) printf( "Total switching after = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); // free the manager p->timeTotal = clock() - clk; Mfs_ManStop( p ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsDiv.c000066400000000000000000000225451300674244400230270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsDiv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Procedures to compute candidate divisors.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsDiv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Marks and collects the TFI cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MfsWinMarkTfi_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vCone ) { Abc_Obj_t * pFanin; int i; if ( Abc_NodeIsTravIdCurrent(pObj) ) return; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsCi(pObj) ) { Vec_PtrPush( vCone, pObj ); return; } assert( Abc_ObjIsNode(pObj) ); // visit the fanins of the node Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_MfsWinMarkTfi_rec( pFanin, vCone ); Vec_PtrPush( vCone, pObj ); } /**Function************************************************************* Synopsis [Marks and collects the TFI cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_MfsWinMarkTfi( Abc_Obj_t * pNode ) { Vec_Ptr_t * vCone; vCone = Vec_PtrAlloc( 100 ); Abc_MfsWinMarkTfi_rec( pNode, vCone ); return vCone; } /**Function************************************************************* Synopsis [Marks the TFO of the collected nodes up to the given level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MfsWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit ) { Abc_Obj_t * pFanout; int i; if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit ) return; if ( Abc_NodeIsTravIdCurrent(pObj) ) return; Abc_NodeSetTravIdCurrent( pObj ); Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_MfsWinSweepLeafTfo_rec( pFanout, nLevelLimit ); } /**Function************************************************************* Synopsis [Dereferences the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_MfsNodeDeref_rec( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i, Counter = 1; if ( Abc_ObjIsCi(pNode) ) return 0; Abc_NodeSetTravIdCurrent( pNode ); Abc_ObjForEachFanin( pNode, pFanin, i ) { assert( pFanin->vFanouts.nSize > 0 ); if ( --pFanin->vFanouts.nSize == 0 ) Counter += Abc_MfsNodeDeref_rec( pFanin ); } return Counter; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_MfsNodeRef_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_MfsNodeRef_rec( pFanin ); } return Counter; } /**Function************************************************************* Synopsis [Labels MFFC of the node with the current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_MfsWinVisitMffc( Abc_Obj_t * pNode ) { int Count1, Count2; assert( Abc_ObjIsNode(pNode) ); // dereference the node (mark with the current trav ID) Count1 = Abc_MfsNodeDeref_rec( pNode ); // reference it back Count2 = Abc_MfsNodeRef_rec( pNode ); assert( Count1 == Count2 ); return Count1; } /**Function************************************************************* Synopsis [Computes divisors and add them to nodes in the window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_MfsComputeDivisors( Mfs_Man_t * p, Abc_Obj_t * pNode, int nLevDivMax ) { Vec_Ptr_t * vCone, * vDivs; Abc_Obj_t * pObj, * pFanout, * pFanin; int k, f, m; int nDivsPlus = 0, nTrueSupp; assert( p->vDivs == NULL ); // mark the TFI with the current trav ID Abc_NtkIncrementTravId( pNode->pNtk ); vCone = Abc_MfsWinMarkTfi( pNode ); // count the number of PIs nTrueSupp = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, k ) nTrueSupp += Abc_ObjIsCi(pObj); // printf( "%d(%d) ", Vec_PtrSize(p->vSupp), m ); // mark with the current trav ID those nodes that should not be divisors: // (1) the node and its TFO // (2) the MFFC of the node // (3) the node's fanins (these are treated as a special case) Abc_NtkIncrementTravId( pNode->pNtk ); Abc_MfsWinSweepLeafTfo_rec( pNode, nLevDivMax ); // Abc_MfsWinVisitMffc( pNode ); Abc_ObjForEachFanin( pNode, pObj, k ) Abc_NodeSetTravIdCurrent( pObj ); // at this point the nodes are marked with two trav IDs: // nodes to be collected as divisors are marked with previous trav ID // nodes to be avoided as divisors are marked with current trav ID // start collecting the divisors vDivs = Vec_PtrAlloc( p->pPars->nWinMax ); Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, k ) { if ( !Abc_NodeIsTravIdPrevious(pObj) ) continue; if ( (int)pObj->Level > nLevDivMax ) continue; Vec_PtrPush( vDivs, pObj ); if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax ) break; } Vec_PtrFree( vCone ); // explore the fanouts of already collected divisors if ( Vec_PtrSize(vDivs) < p->pPars->nWinMax ) Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, k ) { // consider fanouts of this node Abc_ObjForEachFanout( pObj, pFanout, f ) { // stop if there are too many fanouts if ( p->pPars->nFanoutsMax && f > p->pPars->nFanoutsMax ) break; // skip nodes that are already added if ( Abc_NodeIsTravIdPrevious(pFanout) ) continue; // skip nodes in the TFO or in the MFFC of node if ( Abc_NodeIsTravIdCurrent(pFanout) ) continue; // skip COs if ( !Abc_ObjIsNode(pFanout) ) continue; // skip nodes with large level if ( (int)pFanout->Level > nLevDivMax ) continue; // skip nodes whose fanins are not divisors -- here we skip more than we need to skip!!! (revise later) August 7, 2009 Abc_ObjForEachFanin( pFanout, pFanin, m ) if ( !Abc_NodeIsTravIdPrevious(pFanin) ) break; if ( m < Abc_ObjFaninNum(pFanout) ) continue; // make sure this divisor in not among the nodes // Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pFanin, m ) // assert( pFanout != pFanin ); // add the node to the divisors Vec_PtrPush( vDivs, pFanout ); // Vec_PtrPush( p->vNodes, pFanout ); Vec_PtrPushUnique( p->vNodes, pFanout ); Abc_NodeSetTravIdPrevious( pFanout ); nDivsPlus++; if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax ) break; } if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax ) break; } p->nMaxDivs += (Vec_PtrSize(vDivs) >= p->pPars->nWinMax); // sort the divisors by level in the increasing order Vec_PtrSort( vDivs, (int (*)(void))Abc_NodeCompareLevelsIncrease ); // add the fanins of the node Abc_ObjForEachFanin( pNode, pFanin, k ) Vec_PtrPush( vDivs, pFanin ); /* printf( "Node level = %d. ", Abc_ObjLevel(p->pNode) ); Vec_PtrForEachEntryStart( Abc_Obj_t *, vDivs, pObj, k, Vec_PtrSize(vDivs)-p->nDivsPlus ) printf( "%d ", Abc_ObjLevel(pObj) ); printf( "\n" ); */ //printf( "%d ", p->nDivsPlus ); // printf( "(%d+%d)(%d+%d+%d) ", Vec_PtrSize(p->vSupp), Vec_PtrSize(p->vNodes), // nTrueSupp, Vec_PtrSize(vDivs)-nTrueSupp-nDivsPlus, nDivsPlus ); return vDivs; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsGia.c000066400000000000000000000221241300674244400227760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsGia.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Experimental code based on the new AIG package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 29, 2009.] Revision [$Id: mfsGia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Gia_ObjChild0Copy( Aig_Obj_t * pObj ) { return Gia_LitNotCond( Aig_ObjFanin0(pObj)->iData, Aig_ObjFaninC0(pObj) ); } static inline int Gia_ObjChild1Copy( Aig_Obj_t * pObj ) { return Gia_LitNotCond( Aig_ObjFanin1(pObj)->iData, Aig_ObjFaninC1(pObj) ); } // r i10_if6.blif; ps; mfs -v // r pj1_if6.blif; ps; mfs -v // r x/01_if6.blif; ps; mfs -v //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the resubstitution miter as an GIA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCreateResubMiter( Aig_Man_t * p ) { Gia_Man_t * pNew;//, * pTemp; Aig_Obj_t * pObj; int i, * pOuts0, * pOuts1; Aig_ManSetPioNumbers( p ); // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); pNew->pName = Gia_UtilStrsav( p->pName ); pNew->pSpec = Gia_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); // create the objects pOuts0 = ABC_ALLOC( int, Aig_ManPoNum(p) ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsAnd(pObj) ) pObj->iData = Gia_ManHashAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); else if ( Aig_ObjIsPi(pObj) ) pObj->iData = Gia_ManAppendCi( pNew ); else if ( Aig_ObjIsPo(pObj) ) pOuts0[ Aig_ObjPioNum(pObj) ] = Gia_ObjChild0Copy(pObj); else if ( Aig_ObjIsConst1(pObj) ) pObj->iData = 1; else assert( 0 ); } // create the objects pOuts1 = ABC_ALLOC( int, Aig_ManPoNum(p) ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsAnd(pObj) ) pObj->iData = Gia_ManHashAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); else if ( Aig_ObjIsPi(pObj) ) pObj->iData = Gia_ManAppendCi( pNew ); else if ( Aig_ObjIsPo(pObj) ) pOuts1[ Aig_ObjPioNum(pObj) ] = Gia_ObjChild0Copy(pObj); else if ( Aig_ObjIsConst1(pObj) ) pObj->iData = 1; else assert( 0 ); } // add the outputs Gia_ManAppendCo( pNew, pOuts0[0] ); Gia_ManAppendCo( pNew, pOuts1[0] ); Gia_ManAppendCo( pNew, pOuts0[1] ); Gia_ManAppendCo( pNew, Gia_LitNot(pOuts1[1]) ); for ( i = 2; i < Aig_ManPoNum(p); i++ ) Gia_ManAppendCo( pNew, Gia_LitNot( Gia_ManHashXor(pNew, pOuts0[i], pOuts1[i]) ) ); Gia_ManHashStop( pNew ); ABC_FREE( pOuts0 ); ABC_FREE( pOuts1 ); // pNew = Gia_ManCleanup( pTemp = pNew ); // Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsConstructGia( Mfs_Man_t * p ) { int nBTLimit = 500; // prepare AIG assert( p->pGia == NULL ); p->pGia = Gia_ManCreateResubMiter( p->pAigWin ); // prepare AIG Gia_ManCreateRefs( p->pGia ); Gia_ManCleanMark0( p->pGia ); Gia_ManCleanMark1( p->pGia ); Gia_ManFillValue ( p->pGia ); // maps nodes into trail ids Gia_ManCleanPhase( p->pGia ); // prepare solver p->pTas = Tas_ManAlloc( p->pGia, nBTLimit ); p->vCex = Tas_ReadModel( p->pTas ); p->vGiaLits = Vec_PtrAlloc( 100 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsDeconstructGia( Mfs_Man_t * p ) { assert( p->pGia != NULL ); Gia_ManStop( p->pGia ); p->pGia = NULL; Tas_ManStop( p->pTas ); p->pTas = NULL; Vec_PtrFree( p->vGiaLits ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsResimulate( Gia_Man_t * p, Vec_Int_t * vCex ) { Gia_Obj_t * pObj; int i, Entry; // Gia_ManCleanMark1( p ); Gia_ManConst0(p)->fMark1 = 0; Gia_ManForEachCi( p, pObj, i ) pObj->fMark1 = 0; // pObj->fMark1 = Gia_ManRandom(0); Vec_IntForEachEntry( vCex, Entry, i ) { pObj = Gia_ManCi( p, Gia_Lit2Var(Entry) ); pObj->fMark1 = !Gia_LitIsCompl(Entry); } 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); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsTryResubOnceGia( Mfs_Man_t * p, int * pCands, int nCands ) { int fVeryVerbose = 0; int fUseGia = 1; unsigned * pData; int i, iVar, status, iOut; clock_t clk = clock(); p->nSatCalls++; // return -1; assert( p->pGia != NULL ); assert( p->pTas != NULL ); // convert to literals Vec_PtrClear( p->vGiaLits ); // create the first four literals Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 0)) ); Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 1)) ); Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 2)) ); Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 3)) ); for ( i = 0; i < nCands; i++ ) { // get the output number iOut = Gia_Lit2Var(pCands[i]) - 2 * p->pCnf->nVars; // write the literal Vec_PtrPush( p->vGiaLits, Gia_ObjChild0(Gia_ManPo(p->pGia, 4 + iOut)) ); } // perform SAT solving status = Tas_ManSolveArray( p->pTas, p->vGiaLits ); if ( status == -1 ) { p->nTimeOuts++; if ( fVeryVerbose ) printf( "t" ); // p->nSatUndec++; // p->nConfUndec += p->Pars.nBTThis; // Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout // p->timeSatUndec += clock() - clk; } else if ( status == 1 ) { if ( fVeryVerbose ) printf( "u" ); // p->nSatUnsat++; // p->nConfUnsat += p->Pars.nBTThis; // p->timeSatUnsat += clock() - clk; } else { p->nSatCexes++; if ( fVeryVerbose ) printf( "s" ); // p->nSatSat++; // p->nConfSat += p->Pars.nBTThis; // Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); // Cec_ManSatAddToStore( vCexStore, vCex, i ); // p->timeSatSat += clock() - clk; // resimulate the counter-example Abc_NtkMfsResimulate( p->pGia, Tas_ReadModel(p->pTas) ); if ( fUseGia ) { /* int Val0 = Gia_ManPo(p->pGia, 0)->fMark1; int Val1 = Gia_ManPo(p->pGia, 1)->fMark1; int Val2 = Gia_ManPo(p->pGia, 2)->fMark1; int Val3 = Gia_ManPo(p->pGia, 3)->fMark1; assert( Val0 == 1 ); assert( Val1 == 1 ); assert( Val2 == 1 ); assert( Val3 == 1 ); */ // store the counter-example Vec_IntForEachEntry( p->vProjVarsSat, iVar, i ) { pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); iOut = iVar - 2 * p->pCnf->nVars; // if ( !Gia_ManPo( p->pGia, 4 + iOut )->fMark1 ) // remove 0s!!! if ( Gia_ManPo( p->pGia, 4 + iOut )->fMark1 ) // remove 0s!!! - rememeber complemented attribute { assert( Aig_InfoHasBit(pData, p->nCexes) ); Aig_InfoXorBit( pData, p->nCexes ); } } p->nCexes++; } } return status; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsInt.h000066400000000000000000000204361300674244400230410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__mfs__mfsInt_h #define ABC__opt__mfs__mfsInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" #include "mfs.h" #include "aig/aig/aig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" #include "sat/bsat/satStore.h" #include "bool/bdc/bdc.h" #include "aig/gia/gia.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define MFS_FANIN_MAX 12 typedef struct Mfs_Man_t_ Mfs_Man_t; struct Mfs_Man_t_ { // input data Mfs_Par_t * pPars; Abc_Ntk_t * pNtk; Aig_Man_t * pCare; Vec_Ptr_t * vSuppsInv; int nFaninMax; // intermeditate data for the node Vec_Ptr_t * vRoots; // the roots of the window Vec_Ptr_t * vSupp; // the support of the window Vec_Ptr_t * vNodes; // the internal nodes of the window Vec_Ptr_t * vDivs; // the divisors of the node Vec_Int_t * vDivLits; // the SAT literals of divisor nodes Vec_Int_t * vProjVarsCnf; // the projection variables Vec_Int_t * vProjVarsSat; // the projection variables // intermediate simulation data Vec_Ptr_t * vDivCexes; // the counter-example for dividors int nDivWords; // the number of words int nCexes; // the numbe rof current counter-examples int nSatCalls; int nSatCexes; /* // intermediate AIG data Gia_Man_t * pGia; // replica of the AIG in the new package // Gia_Obj_t ** pSat2Gia; // mapping of PO SAT var into internal GIA nodes Tas_Man_t * pTas; // the SAT solver Vec_Int_t * vCex; // the counter-example Vec_Ptr_t * vGiaLits; // literals given as assumptions */ // used for bidecomposition Vec_Int_t * vTruth; Bdc_Man_t * pManDec; int nNodesDec; int nNodesGained; int nNodesGainedLevel; // solving data Aig_Man_t * pAigWin; // window AIG with constraints Cnf_Dat_t * pCnf; // the CNF for the window sat_solver * pSat; // the SAT solver used Int_Man_t * pMan; // interpolation manager; Vec_Int_t * vMem; // memory for intermediate SOPs Vec_Vec_t * vLevels; // levelized structure for updating Vec_Ptr_t * vMfsFanins; // the new set of fanins int nTotConfLim; // total conflict limit int nTotConfLevel; // total conflicts on this level // switching activity Vec_Int_t * vProbs; // the result of solving int nFanins; // the number of fanins int nWords; // the number of words int nCares; // the number of care minterms unsigned uCare[(MFS_FANIN_MAX<=5)?1:1<<(MFS_FANIN_MAX-5)]; // the computed care-set // performance statistics int nTryRemoves; // number of fanin removals int nTryResubs; // number of resubstitutions int nRemoves; // number of fanin removals int nResubs; // number of resubstitutions int nNodesTried; int nNodesResub; int nMintsCare; int nMintsTotal; int nNodesBad; int nTotalDivs; int nTimeOuts; int nTimeOutsLevel; int nDcMints; int nMaxDivs; double dTotalRatios; // node/edge stats int nTotalNodesBeg; int nTotalNodesEnd; int nTotalEdgesBeg; int nTotalEdgesEnd; float TotalSwitchingBeg; float TotalSwitchingEnd; // statistics abctime timeWin; abctime timeDiv; abctime timeAig; abctime timeGia; abctime timeCnf; abctime timeSat; abctime timeInt; abctime timeTotal; }; static inline float Abc_MfsObjProb( Mfs_Man_t * p, Abc_Obj_t * pObj ) { return (p->vProbs && pObj->Id < Vec_IntSize(p->vProbs))? Abc_Int2Float(Vec_IntEntry(p->vProbs,pObj->Id)) : 0.0; } //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== mfsDiv.c ==========================================================*/ extern Vec_Ptr_t * Abc_MfsComputeDivisors( Mfs_Man_t * p, Abc_Obj_t * pNode, int nLevDivMax ); /*=== mfsInter.c ==========================================================*/ extern sat_solver * Abc_MfsCreateSolverResub( Mfs_Man_t * p, int * pCands, int nCands, int fInvert ); extern Hop_Obj_t * Abc_NtkMfsInterplate( Mfs_Man_t * p, int * pCands, int nCands ); extern int Abc_NtkMfsInterplateEval( Mfs_Man_t * p, int * pCands, int nCands ); /*=== mfsMan.c ==========================================================*/ extern Mfs_Man_t * Mfs_ManAlloc( Mfs_Par_t * pPars ); extern void Mfs_ManStop( Mfs_Man_t * p ); extern void Mfs_ManClean( Mfs_Man_t * p ); /*=== mfsResub.c ==========================================================*/ extern void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ); extern int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode ); /*=== mfsSat.c ==========================================================*/ extern int Abc_NtkMfsSolveSat( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern int Abc_NtkAddOneHotness( Mfs_Man_t * p ); /*=== mfsStrash.c ==========================================================*/ extern Aig_Man_t * Abc_NtkConstructAig( Mfs_Man_t * p, Abc_Obj_t * pNode ); extern double Abc_NtkConstraintRatio( Mfs_Man_t * p, Abc_Obj_t * pNode ); /*=== mfsWin.c ==========================================================*/ extern Vec_Ptr_t * Abc_MfsComputeRoots( Abc_Obj_t * pNode, int nWinTfoMax, int nFanoutLimit ); /*=== mfsGia.c ==========================================================*/ extern void Abc_NtkMfsConstructGia( Mfs_Man_t * p ); extern void Abc_NtkMfsDeconstructGia( Mfs_Man_t * p ); extern int Abc_NtkMfsTryResubOnceGia( Mfs_Man_t * p, int * pCands, int nCands ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsInter.c000066400000000000000000000300341300674244400233560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsInter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Procedures for computing resub function by interpolation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds constraints for the two-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_MfsSatAddXor( sat_solver * pSat, int iVarA, int iVarB, int iVarC ) { lit Lits[3]; Lits[0] = toLitCond( iVarA, 1 ); Lits[1] = toLitCond( iVarB, 1 ); Lits[2] = toLitCond( iVarC, 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; Lits[0] = toLitCond( iVarA, 1 ); Lits[1] = toLitCond( iVarB, 0 ); Lits[2] = toLitCond( iVarC, 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; Lits[0] = toLitCond( iVarA, 0 ); Lits[1] = toLitCond( iVarB, 1 ); Lits[2] = toLitCond( iVarC, 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; Lits[0] = toLitCond( iVarA, 0 ); Lits[1] = toLitCond( iVarB, 0 ); Lits[2] = toLitCond( iVarC, 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Creates miter for checking resubsitution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Abc_MfsCreateSolverResub( Mfs_Man_t * p, int * pCands, int nCands, int fInvert ) { sat_solver * pSat; Aig_Obj_t * pObjPo; int Lits[2], status, iVar, i, c; // get the literal for the output of F pObjPo = Aig_ManCo( p->pAigWin, Aig_ManCoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) - 1 ); Lits[0] = toLitCond( p->pCnf->pVarNums[pObjPo->Id], fInvert ); // collect the outputs of the divisors Vec_IntClear( p->vProjVarsCnf ); Vec_PtrForEachEntryStart( Aig_Obj_t *, p->pAigWin->vCos, pObjPo, i, Aig_ManCoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) ) { assert( p->pCnf->pVarNums[pObjPo->Id] >= 0 ); Vec_IntPush( p->vProjVarsCnf, p->pCnf->pVarNums[pObjPo->Id] ); } assert( Vec_IntSize(p->vProjVarsCnf) == Vec_PtrSize(p->vDivs) ); // start the solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, 2 * p->pCnf->nVars + Vec_PtrSize(p->vDivs) ); if ( pCands ) sat_solver_store_alloc( pSat ); // load the first copy of the clauses for ( i = 0; i < p->pCnf->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) ) { sat_solver_delete( pSat ); return NULL; } } // add the clause for the first output of F if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) { sat_solver_delete( pSat ); return NULL; } // add one-hotness constraints if ( p->pPars->fOneHotness ) { p->pSat = pSat; if ( !Abc_NtkAddOneHotness( p ) ) return NULL; p->pSat = NULL; } // bookmark the clauses of A if ( pCands ) sat_solver_store_mark_clauses_a( pSat ); // transform the literals for ( i = 0; i < p->pCnf->nLiterals; i++ ) p->pCnf->pClauses[0][i] += 2 * p->pCnf->nVars; // load the second copy of the clauses for ( i = 0; i < p->pCnf->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) ) { sat_solver_delete( pSat ); return NULL; } } // add one-hotness constraints if ( p->pPars->fOneHotness ) { p->pSat = pSat; if ( !Abc_NtkAddOneHotness( p ) ) return NULL; p->pSat = NULL; } // transform the literals for ( i = 0; i < p->pCnf->nLiterals; i++ ) p->pCnf->pClauses[0][i] -= 2 * p->pCnf->nVars; // add the clause for the second output of F Lits[0] = 2 * p->pCnf->nVars + lit_neg( Lits[0] ); if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) { sat_solver_delete( pSat ); return NULL; } if ( pCands ) { // add relevant clauses for EXOR gates for ( c = 0; c < nCands; c++ ) { // get the variable number of this divisor i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; // get the corresponding SAT variable iVar = Vec_IntEntry( p->vProjVarsCnf, i ); // add the corresponding EXOR gate if ( !Abc_MfsSatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) ) { sat_solver_delete( pSat ); return NULL; } // add the corresponding clause if ( !sat_solver_addclause( pSat, pCands + c, pCands + c + 1 ) ) { sat_solver_delete( pSat ); return NULL; } } // bookmark the roots sat_solver_store_mark_roots( pSat ); } else { // add the clauses for the EXOR gates - and remember their outputs Vec_IntClear( p->vProjVarsSat ); Vec_IntForEachEntry( p->vProjVarsCnf, iVar, i ) { if ( !Abc_MfsSatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) ) { sat_solver_delete( pSat ); return NULL; } Vec_IntPush( p->vProjVarsSat, 2 * p->pCnf->nVars + i ); } assert( Vec_IntSize(p->vProjVarsCnf) == Vec_IntSize(p->vProjVarsSat) ); // simplify the solver status = sat_solver_simplify(pSat); if ( status == 0 ) { // printf( "Abc_MfsCreateSolverResub(): SAT solver construction has failed. Skipping node.\n" ); sat_solver_delete( pSat ); return NULL; } } return pSat; } /**Function************************************************************* Synopsis [Performs interpolation.] Description [Derives the new function of the node.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Abc_NtkMfsInterplateTruth( Mfs_Man_t * p, int * pCands, int nCands, int fInvert ) { sat_solver * pSat; Sto_Man_t * pCnf = NULL; unsigned * puTruth; int nFanins, status; int c, i, * pGloVars; // derive the SAT solver for interpolation pSat = Abc_MfsCreateSolverResub( p, pCands, nCands, fInvert ); // solve the problem status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status != l_False ) { p->nTimeOuts++; return NULL; } // get the learned clauses pCnf = (Sto_Man_t *)sat_solver_store_release( pSat ); sat_solver_delete( pSat ); // set the global variables pGloVars = Int_ManSetGlobalVars( p->pMan, nCands ); for ( c = 0; c < nCands; c++ ) { // get the variable number of this divisor i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; // get the corresponding SAT variable pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i ); } // derive the interpolant nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth ); Sto_ManFree( pCnf ); assert( nFanins == nCands ); return puTruth; } /**Function************************************************************* Synopsis [Performs interpolation.] Description [Derives the new function of the node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsInterplateEval( Mfs_Man_t * p, int * pCands, int nCands ) { unsigned * pTruth, uTruth0[2], uTruth1[2]; int nCounter; pTruth = Abc_NtkMfsInterplateTruth( p, pCands, nCands, 0 ); if ( nCands == 6 ) { uTruth1[0] = pTruth[0]; uTruth1[1] = pTruth[1]; } else { uTruth1[0] = pTruth[0]; uTruth1[1] = pTruth[0]; } pTruth = Abc_NtkMfsInterplateTruth( p, pCands, nCands, 1 ); if ( nCands == 6 ) { uTruth0[0] = ~pTruth[0]; uTruth0[1] = ~pTruth[1]; } else { uTruth0[0] = ~pTruth[0]; uTruth0[1] = ~pTruth[0]; } nCounter = Extra_WordCountOnes( uTruth0[0] ^ uTruth1[0] ); nCounter += Extra_WordCountOnes( uTruth0[1] ^ uTruth1[1] ); // printf( "%d ", nCounter ); return nCounter; } /**Function************************************************************* Synopsis [Performs interpolation.] Description [Derives the new function of the node.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_NtkMfsInterplate( Mfs_Man_t * p, int * pCands, int nCands ) { extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); int fDumpFile = 0; char FileName[32]; sat_solver * pSat; Sto_Man_t * pCnf = NULL; unsigned * puTruth; Kit_Graph_t * pGraph; Hop_Obj_t * pFunc; int nFanins, status; int c, i, * pGloVars; // abctime clk = Abc_Clock(); // p->nDcMints += Abc_NtkMfsInterplateEval( p, pCands, nCands ); // derive the SAT solver for interpolation pSat = Abc_MfsCreateSolverResub( p, pCands, nCands, 0 ); // dump CNF file (remember to uncomment two-lit clases in clause_create_new() in 'satSolver.c') if ( fDumpFile ) { static int Counter = 0; sprintf( FileName, "cnf\\pj1_if6_mfs%03d.cnf", Counter++ ); Sat_SolverWriteDimacs( pSat, FileName, NULL, NULL, 1 ); } // solve the problem status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( fDumpFile ) printf( "File %s has UNSAT problem with %d conflicts.\n", FileName, (int)pSat->stats.conflicts ); if ( status != l_False ) { p->nTimeOuts++; return NULL; } //printf( "%d\n", pSat->stats.conflicts ); // ABC_PRT( "S", Abc_Clock() - clk ); // get the learned clauses pCnf = (Sto_Man_t *)sat_solver_store_release( pSat ); sat_solver_delete( pSat ); // set the global variables pGloVars = Int_ManSetGlobalVars( p->pMan, nCands ); for ( c = 0; c < nCands; c++ ) { // get the variable number of this divisor i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars; // get the corresponding SAT variable pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i ); } // derive the interpolant nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth ); Sto_ManFree( pCnf ); assert( nFanins == nCands ); // transform interpolant into AIG pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem ); pFunc = Kit_GraphToHop( (Hop_Man_t *)p->pNtk->pManFunc, pGraph ); Kit_GraphFree( pGraph ); return pFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsMan.c000066400000000000000000000154271300674244400230210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Procedures working with the manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mfs_Man_t * Mfs_ManAlloc( Mfs_Par_t * pPars ) { Mfs_Man_t * p; // start the manager p = ABC_ALLOC( Mfs_Man_t, 1 ); memset( p, 0, sizeof(Mfs_Man_t) ); p->pPars = pPars; p->vProjVarsCnf = Vec_IntAlloc( 100 ); p->vProjVarsSat = Vec_IntAlloc( 100 ); p->vDivLits = Vec_IntAlloc( 100 ); p->nDivWords = Abc_BitWordNum(p->pPars->nWinMax + MFS_FANIN_MAX); p->vDivCexes = Vec_PtrAllocSimInfo( p->pPars->nWinMax + MFS_FANIN_MAX + 1, p->nDivWords ); p->pMan = Int_ManAlloc(); p->vMem = Vec_IntAlloc( 0 ); p->vLevels = Vec_VecStart( 32 ); p->vMfsFanins= Vec_PtrAlloc( 32 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mfs_ManClean( Mfs_Man_t * p ) { if ( p->pAigWin ) Aig_ManStop( p->pAigWin ); if ( p->pCnf ) Cnf_DataFree( p->pCnf ); if ( p->pSat ) sat_solver_delete( p->pSat ); if ( p->vRoots ) Vec_PtrFree( p->vRoots ); if ( p->vSupp ) Vec_PtrFree( p->vSupp ); if ( p->vNodes ) Vec_PtrFree( p->vNodes ); if ( p->vDivs ) Vec_PtrFree( p->vDivs ); p->pAigWin = NULL; p->pCnf = NULL; p->pSat = NULL; p->vRoots = NULL; p->vSupp = NULL; p->vNodes = NULL; p->vDivs = NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mfs_ManPrint( Mfs_Man_t * p ) { if ( p->pPars->fResub ) { printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d. MaxDivs = %d.\n", p->nTotalNodesBeg, p->nNodesTried, p->nNodesResub, p->nTotalDivs, p->nSatCalls, p->nTimeOuts, p->nMaxDivs ); printf( "Attempts : " ); printf( "Remove %6d out of %6d (%6.2f %%) ", p->nRemoves, p->nTryRemoves, 100.0*p->nRemoves/Abc_MaxInt(1, p->nTryRemoves) ); printf( "Resub %6d out of %6d (%6.2f %%) ", p->nResubs, p->nTryResubs, 100.0*p->nResubs /Abc_MaxInt(1, p->nTryResubs) ); printf( "\n" ); printf( "Reduction: " ); printf( "Nodes %6d out of %6d (%6.2f %%) ", p->nTotalNodesBeg-p->nTotalNodesEnd, p->nTotalNodesBeg, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/Abc_MaxInt(1, p->nTotalNodesBeg) ); printf( "Edges %6d out of %6d (%6.2f %%) ", p->nTotalEdgesBeg-p->nTotalEdgesEnd, p->nTotalEdgesBeg, 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/Abc_MaxInt(1, p->nTotalEdgesBeg) ); printf( "\n" ); if (p->pPars->fPower) printf( "Power( %5.2f, %4.2f%%) \n", p->TotalSwitchingBeg - p->TotalSwitchingEnd, 100.0*(p->TotalSwitchingBeg-p->TotalSwitchingEnd)/p->TotalSwitchingBeg ); if ( p->pPars->fSwapEdge ) printf( "Swappable edges = %d. Total edges = %d. Ratio = %5.2f.\n", p->nNodesResub, Abc_NtkGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Abc_NtkGetTotalFanins(p->pNtk) ); // printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) ); } else { printf( "Nodes = %d. Try = %d. Total mints = %d. Local DC mints = %d. Ratio = %5.2f.\n", p->nTotalNodesBeg, p->nNodesTried, p->nMintsTotal, p->nMintsTotal-p->nMintsCare, 1.0 * (p->nMintsTotal-p->nMintsCare) / p->nMintsTotal ); // printf( "Average ratio of sequential DCs in the global space = %5.2f.\n", // 1.0-(p->dTotalRatios/p->nNodesTried) ); printf( "Nodes resyn = %d. Ratio = %5.2f. Total AIG node gain = %d. Timeouts = %d.\n", p->nNodesDec, 1.0 * p->nNodesDec / p->nNodesTried, p->nNodesGained, p->nTimeOuts ); } ABC_PRTP( "Win", p->timeWin , p->timeTotal ); ABC_PRTP( "Div", p->timeDiv , p->timeTotal ); ABC_PRTP( "Aig", p->timeAig , p->timeTotal ); ABC_PRTP( "Gia", p->timeGia , p->timeTotal ); ABC_PRTP( "Cnf", p->timeCnf , p->timeTotal ); ABC_PRTP( "Sat", p->timeSat-p->timeInt , p->timeTotal ); ABC_PRTP( "Int", p->timeInt , p->timeTotal ); ABC_PRTP( "ALL", p->timeTotal , p->timeTotal ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mfs_ManStop( Mfs_Man_t * p ) { if ( p->pPars->fVerbose ) Mfs_ManPrint( p ); if ( p->vTruth ) Vec_IntFree( p->vTruth ); if ( p->pManDec ) Bdc_ManFree( p->pManDec ); if ( p->pCare ) Aig_ManStop( p->pCare ); if ( p->vSuppsInv ) Vec_VecFree( (Vec_Vec_t *)p->vSuppsInv ); if ( p->vProbs ) Vec_IntFree( p->vProbs ); Mfs_ManClean( p ); Int_ManFree( p->pMan ); Vec_IntFree( p->vMem ); Vec_VecFree( p->vLevels ); Vec_PtrFree( p->vMfsFanins ); Vec_IntFree( p->vProjVarsCnf ); Vec_IntFree( p->vProjVarsSat ); Vec_IntFree( p->vDivLits ); Vec_PtrFree( p->vDivCexes ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsResub.c000066400000000000000000000463741300674244400233730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsResub.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Procedures to perform resubstitution.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Updates the network after resubstitution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsUpdateNetwork( Mfs_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vMfsFanins, Hop_Obj_t * pFunc ) { Abc_Obj_t * pObjNew, * pFanin; int k; // create the new node pObjNew = Abc_NtkCreateNode( pObj->pNtk ); pObjNew->pData = pFunc; Vec_PtrForEachEntry( Abc_Obj_t *, vMfsFanins, pFanin, k ) Abc_ObjAddFanin( pObjNew, pFanin ); // replace the old node by the new node //printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj ); //printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew ); // update the level of the node Abc_NtkUpdate( pObj, pObjNew, p->vLevels ); } /**Function************************************************************* Synopsis [Prints resub candidate stats.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ) { Abc_Obj_t * pFanin, * pNode; int i, k, nAreaCrits = 0, nAreaExpanse = 0; int nFaninMax = Abc_NtkGetFaninMax(p->pNtk); Abc_NtkForEachNode( p->pNtk, pNode, i ) Abc_ObjForEachFanin( pNode, pFanin, k ) { if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { nAreaCrits++; nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax); } } // printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", // nAreaCrits, nAreaExpanse ); } /**Function************************************************************* Synopsis [Tries resubstitution.] Description [Returns 1 if it is feasible, or 0 if c-ex is found.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsTryResubOnce( Mfs_Man_t * p, int * pCands, int nCands ) { int fVeryVerbose = 0; unsigned * pData; int RetValue, RetValue2 = -1, iVar, i;//, clk = Abc_Clock(); /* if ( p->pPars->fGiaSat ) { RetValue2 = Abc_NtkMfsTryResubOnceGia( p, pCands, nCands ); p->timeGia += Abc_Clock() - clk; return RetValue2; } */ p->nSatCalls++; RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); // assert( RetValue == l_False || RetValue == l_True ); if ( RetValue != l_Undef && RetValue2 != -1 ) { assert( (RetValue == l_False) == (RetValue2 == 1) ); } if ( RetValue == l_False ) { if ( fVeryVerbose ) printf( "U " ); return 1; } if ( RetValue != l_True ) { if ( fVeryVerbose ) printf( "T " ); p->nTimeOuts++; return -1; } if ( fVeryVerbose ) printf( "S " ); p->nSatCexes++; // store the counter-example Vec_IntForEachEntry( p->vProjVarsSat, iVar, i ) { pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!! { assert( Abc_InfoHasBit(pData, p->nCexes) ); Abc_InfoXorBit( pData, p->nCexes ); } } p->nCexes++; return 0; } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ) { int fVeryVerbose = 0;//p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 200;// || pNode->Id == 556; unsigned * pData; int pCands[MFS_FANIN_MAX]; int RetValue, iVar, i, nCands, nWords, w; abctime clk; Abc_Obj_t * pFanin; Hop_Obj_t * pFunc; assert( iFanin >= 0 ); p->nTryRemoves++; // clean simulation info Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); p->nCexes = 0; if ( p->pPars->fVeryVerbose ) { // printf( "\n" ); printf( "%5d : Lev =%3d. Leaf =%3d. Node =%3d. Divs =%3d. Fanin = %4d (%d/%d), MFFC = %d\n", pNode->Id, pNode->Level, Vec_PtrSize(p->vSupp), Vec_PtrSize(p->vNodes), Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), Abc_ObjFaninId(pNode, iFanin), iFanin, Abc_ObjFaninNum(pNode), Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); } // try fanins without the critical fanin nCands = 0; Vec_PtrClear( p->vMfsFanins ); Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( i == iFanin ) continue; Vec_PtrPush( p->vMfsFanins, pFanin ); iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVarsSat, iVar ), 1 ); } RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); if ( RetValue == -1 ) return 0; if ( RetValue == 1 ) { if ( p->pPars->fVeryVerbose ) printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin ); p->nNodesResub++; p->nNodesGainedLevel++; if ( fSkipUpdate ) return 1; clk = Abc_Clock(); // derive the function pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); if ( pFunc == NULL ) return 0; // update the network Abc_NtkMfsUpdateNetwork( p, pNode, p->vMfsFanins, pFunc ); p->timeInt += Abc_Clock() - clk; p->nRemoves++; return 1; } if ( fOnlyRemove || p->pPars->fRrOnly ) return 0; p->nTryResubs++; if ( fVeryVerbose ) { for ( i = 0; i < 9; i++ ) printf( " " ); for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) printf( "%d", i % 10 ); for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) if ( i == iFanin ) printf( "*" ); else printf( "%c", 'a' + i ); printf( "\n" ); } iVar = -1; while ( 1 ) { if ( fVeryVerbose ) { printf( "%3d: %3d ", p->nCexes, iVar ); for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) { pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); printf( "%d", Abc_InfoHasBit(pData, p->nCexes-1) ); } printf( "\n" ); } // find the next divisor to try nWords = Abc_BitWordNum(p->nCexes); assert( nWords <= p->nDivWords ); for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { if ( p->pPars->fPower ) { Abc_Obj_t * pDiv = (Abc_Obj_t *)Vec_PtrEntry(p->vDivs, iVar); // only accept the divisor if it is "cool" if ( Abc_MfsObjProb(p, pDiv) >= 0.15 ) continue; } pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar ); for ( w = 0; w < nWords; w++ ) if ( pData[w] != ~0 ) break; if ( w == nWords ) break; } if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) return 0; pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar), 1 ); RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+1 ); if ( RetValue == -1 ) return 0; if ( RetValue == 1 ) { if ( p->pPars->fVeryVerbose ) printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar ); p->nNodesResub++; p->nNodesGainedLevel++; if ( fSkipUpdate ) return 1; clk = Abc_Clock(); // derive the function pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+1 ); if ( pFunc == NULL ) return 0; // update the network Vec_PtrPush( p->vMfsFanins, Vec_PtrEntry(p->vDivs, iVar) ); Abc_NtkMfsUpdateNetwork( p, pNode, p->vMfsFanins, pFunc ); p->timeInt += Abc_Clock() - clk; p->nResubs++; return 1; } if ( p->nCexes >= p->pPars->nWinMax ) break; } if ( p->pPars->fVeryVerbose ) printf( "Node %d: Cannot find replacement for fanin %d.\n", pNode->Id, iFanin ); return 0; } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsSolveSatResub2( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int iFanin2 ) { int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; unsigned * pData, * pData2; int pCands[MFS_FANIN_MAX]; int RetValue, iVar, iVar2, i, w, nCands, nWords, fBreak; abctime clk; Abc_Obj_t * pFanin; Hop_Obj_t * pFunc; assert( iFanin >= 0 ); assert( iFanin2 >= 0 || iFanin2 == -1 ); // clean simulation info Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); p->nCexes = 0; if ( fVeryVerbose ) { printf( "\n" ); printf( "Node %5d : Level = %2d. Divs = %3d. Fanins = %d/%d (out of %d). MFFC = %d\n", pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), iFanin, iFanin2, Abc_ObjFaninNum(pNode), Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); } // try fanins without the critical fanin nCands = 0; Vec_PtrClear( p->vMfsFanins ); Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( i == iFanin || i == iFanin2 ) continue; Vec_PtrPush( p->vMfsFanins, pFanin ); iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVarsSat, iVar ), 1 ); } RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); if ( RetValue == -1 ) return 0; if ( RetValue == 1 ) { if ( fVeryVerbose ) printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 ); p->nNodesResub++; p->nNodesGainedLevel++; clk = Abc_Clock(); // derive the function pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); if ( pFunc == NULL ) return 0; // update the network Abc_NtkMfsUpdateNetwork( p, pNode, p->vMfsFanins, pFunc ); p->timeInt += Abc_Clock() - clk; return 1; } if ( fVeryVerbose ) { for ( i = 0; i < 11; i++ ) printf( " " ); for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) printf( "%d", i % 10 ); for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) if ( i == iFanin || i == iFanin2 ) printf( "*" ); else printf( "%c", 'a' + i ); printf( "\n" ); } iVar = iVar2 = -1; while ( 1 ) { #if 1 // sjang #endif if ( fVeryVerbose ) { printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 ); for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) { pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, i ); printf( "%d", Abc_InfoHasBit(pData, p->nCexes-1) ); } printf( "\n" ); } // find the next divisor to try nWords = Abc_BitWordNum(p->nCexes); assert( nWords <= p->nDivWords ); fBreak = 0; for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { pData = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar ); #if 1 // sjang if ( p->pPars->fPower ) { Abc_Obj_t * pDiv = (Abc_Obj_t *)Vec_PtrEntry(p->vDivs, iVar); // only accept the divisor if it is "cool" if ( Abc_MfsObjProb(p, pDiv) >= 0.12 ) continue; } #endif for ( iVar2 = 0; iVar2 < iVar; iVar2++ ) { pData2 = (unsigned *)Vec_PtrEntry( p->vDivCexes, iVar2 ); #if 1 // sjang if ( p->pPars->fPower ) { Abc_Obj_t * pDiv = (Abc_Obj_t *)Vec_PtrEntry(p->vDivs, iVar2); // only accept the divisor if it is "cool" if ( Abc_MfsObjProb(p, pDiv) >= 0.12 ) continue; } #endif for ( w = 0; w < nWords; w++ ) if ( (pData[w] | pData2[w]) != ~0 ) break; if ( w == nWords ) { fBreak = 1; break; } } if ( fBreak ) break; } if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) return 0; pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar2), 1 ); pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVarsSat, iVar), 1 ); RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+2 ); if ( RetValue == -1 ) return 0; if ( RetValue == 1 ) { if ( fVeryVerbose ) printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 ); p->nNodesResub++; p->nNodesGainedLevel++; clk = Abc_Clock(); // derive the function pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+2 ); if ( pFunc == NULL ) return 0; // update the network Vec_PtrPush( p->vMfsFanins, Vec_PtrEntry(p->vDivs, iVar2) ); Vec_PtrPush( p->vMfsFanins, Vec_PtrEntry(p->vDivs, iVar) ); assert( Vec_PtrSize(p->vMfsFanins) == nCands + 2 ); Abc_NtkMfsUpdateNetwork( p, pNode, p->vMfsFanins, pFunc ); p->timeInt += Abc_Clock() - clk; return 1; } if ( p->nCexes >= p->pPars->nWinMax ) break; } return 0; } /**Function************************************************************* Synopsis [Evaluates the possibility of replacing given edge by another edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i; Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 1 ); return 0; } /**Function************************************************************* Synopsis [Evaluates the possibility of replacing given edge by another edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i; // try replacing area critical fanins Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( Abc_MfsObjProb(p, pFanin) >= 0.35 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) return 1; } else if ( Abc_MfsObjProb(p, pFanin) >= 0.25 ) // sjang { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) return 1; } } return 0; } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i; // try replacing area critical fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) return 1; } // try removing redundant edges if ( !p->pPars->fArea ) { Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_ObjIsCi(pFanin) || Abc_ObjFanoutNum(pFanin) != 1 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) return 1; } } if ( Abc_ObjFaninNum(pNode) == p->nFaninMax ) return 0; /* // try replacing area critical fanins while adding two new fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) return 1; } */ return 0; } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin, * pFanin2; int i, k; /* Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) return 1; } */ if ( Abc_ObjFaninNum(pNode) < 2 ) return 0; // try replacing one area critical fanin and one other fanin while adding two new fanins Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { // consider second fanin to remove at the same time Abc_ObjForEachFanin( pNode, pFanin2, k ) { if ( i != k && Abc_NtkMfsSolveSatResub2( p, pNode, i, k ) ) return 1; } } } return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsResub_.c000066400000000000000000000430551300674244400235230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsResub.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Procedures to perform resubstitution.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Updates the network after resubstitution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsUpdateNetwork( Mfs_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc ) { Abc_Obj_t * pObjNew, * pFanin; int k; // create the new node pObjNew = Abc_NtkCreateNode( pObj->pNtk ); pObjNew->pData = pFunc; Vec_PtrForEachEntry( vFanins, pFanin, k ) Abc_ObjAddFanin( pObjNew, pFanin ); // replace the old node by the new node //printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj ); //printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew ); // update the level of the node Abc_NtkUpdate( pObj, pObjNew, p->vLevels ); } /**Function************************************************************* Synopsis [Prints resub candidate stats.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMfsPrintResubStats( Mfs_Man_t * p ) { Abc_Obj_t * pFanin, * pNode; int i, k, nAreaCrits = 0, nAreaExpanse = 0; int nFaninMax = Abc_NtkGetFaninMax(p->pNtk); Abc_NtkForEachNode( p->pNtk, pNode, i ) Abc_ObjForEachFanin( pNode, pFanin, k ) { if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { nAreaCrits++; nAreaExpanse += (int)(Abc_ObjFaninNum(pNode) < nFaninMax); } } printf( "Total area-critical fanins = %d. Belonging to expandable nodes = %d.\n", nAreaCrits, nAreaExpanse ); } /**Function************************************************************* Synopsis [Tries resubstitution.] Description [Returns 1 if it is feasible, or 0 if c-ex is found.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsTryResubOnce( Mfs_Man_t * p, int * pCands, int nCands ) { unsigned * pData; int RetValue, iVar, i; p->nSatCalls++; RetValue = sat_solver_solve( p->pSat, pCands, pCands + nCands, (sint64)p->pPars->nBTLimit, (sint64)0, (sint64)0, (sint64)0 ); // assert( RetValue == l_False || RetValue == l_True ); if ( RetValue == l_False ) return 1; if ( RetValue != l_True ) { p->nTimeOuts++; return -1; } p->nSatCexes++; // store the counter-example Vec_IntForEachEntry( p->vProjVars, iVar, i ) { pData = Vec_PtrEntry( p->vDivCexes, i ); if ( !sat_solver_var_value( p->pSat, iVar ) ) // remove 0s!!! { assert( Aig_InfoHasBit(pData, p->nCexes) ); Aig_InfoXorBit( pData, p->nCexes ); } } p->nCexes++; return 0; } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsSolveSatResub( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int fOnlyRemove, int fSkipUpdate ) { int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; unsigned * pData; int pCands[MFS_FANIN_MAX]; int RetValue, iVar, i, nCands, nWords, w; clock_t clk; Abc_Obj_t * pFanin; Hop_Obj_t * pFunc; assert( iFanin >= 0 ); // clean simulation info Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); p->nCexes = 0; if ( fVeryVerbose ) { printf( "\n" ); printf( "Node %5d : Level = %2d. Divs = %3d. Fanin = %d (out of %d). MFFC = %d\n", pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), iFanin, Abc_ObjFaninNum(pNode), Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); } // try fanins without the critical fanin nCands = 0; Vec_PtrClear( p->vFanins ); Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( i == iFanin ) continue; Vec_PtrPush( p->vFanins, pFanin ); iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 ); } RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); if ( RetValue == -1 ) return 0; if ( RetValue == 1 ) { if ( fVeryVerbose ) printf( "Node %d: Fanin %d can be removed.\n", pNode->Id, iFanin ); p->nNodesResub++; p->nNodesGainedLevel++; if ( fSkipUpdate ) return 1; clk = clock(); // derive the function pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); if ( pFunc == NULL ) return 0; // update the network Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); p->timeInt += clock() - clk; return 1; } if ( fOnlyRemove ) return 0; if ( fVeryVerbose ) { for ( i = 0; i < 8; i++ ) printf( " " ); for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) printf( "%d", i % 10 ); for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) if ( i == iFanin ) printf( "*" ); else printf( "%c", 'a' + i ); printf( "\n" ); } iVar = -1; while ( 1 ) { float * pProbab = (float *)(p->vProbs? p->vProbs->pArray : NULL); assert( (pProbab != NULL) == p->pPars->fPower ); if ( fVeryVerbose ) { printf( "%3d: %2d ", p->nCexes, iVar ); for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) { pData = Vec_PtrEntry( p->vDivCexes, i ); printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); } printf( "\n" ); } // find the next divisor to try nWords = Aig_BitWordNum(p->nCexes); assert( nWords <= p->nDivWords ); for ( iVar = 0; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { if ( p->pPars->fPower ) { Abc_Obj_t * pDiv = Vec_PtrEntry(p->vDivs, iVar); // only accept the divisor if it is "cool" if ( pProbab[Abc_ObjId(pDiv)] >= 0.2 ) continue; } pData = Vec_PtrEntry( p->vDivCexes, iVar ); for ( w = 0; w < nWords; w++ ) if ( pData[w] != ~0 ) break; if ( w == nWords ) break; } if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) return 0; pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 ); RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+1 ); if ( RetValue == -1 ) return 0; if ( RetValue == 1 ) { if ( fVeryVerbose ) printf( "Node %d: Fanin %d can be replaced by divisor %d.\n", pNode->Id, iFanin, iVar ); p->nNodesResub++; p->nNodesGainedLevel++; if ( fSkipUpdate ) return 1; clk = clock(); // derive the function pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+1 ); if ( pFunc == NULL ) return 0; // update the network Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); p->timeInt += clock() - clk; return 1; } if ( p->nCexes >= p->pPars->nDivMax ) break; } return 0; } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsSolveSatResub2( Mfs_Man_t * p, Abc_Obj_t * pNode, int iFanin, int iFanin2 ) { int fVeryVerbose = p->pPars->fVeryVerbose && Vec_PtrSize(p->vDivs) < 80; unsigned * pData, * pData2; int pCands[MFS_FANIN_MAX]; int RetValue, iVar, iVar2, i, w, nCands, nWords, fBreak; clock_t clk; Abc_Obj_t * pFanin; Hop_Obj_t * pFunc; assert( iFanin >= 0 ); assert( iFanin2 >= 0 || iFanin2 == -1 ); // clean simulation info Vec_PtrFillSimInfo( p->vDivCexes, 0, p->nDivWords ); p->nCexes = 0; if ( fVeryVerbose ) { printf( "\n" ); printf( "Node %5d : Level = %2d. Divs = %3d. Fanins = %d/%d (out of %d). MFFC = %d\n", pNode->Id, pNode->Level, Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode), iFanin, iFanin2, Abc_ObjFaninNum(pNode), Abc_ObjFanoutNum(Abc_ObjFanin(pNode, iFanin)) == 1 ? Abc_NodeMffcLabel(Abc_ObjFanin(pNode, iFanin)) : 0 ); } // try fanins without the critical fanin nCands = 0; Vec_PtrClear( p->vFanins ); Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( i == iFanin || i == iFanin2 ) continue; Vec_PtrPush( p->vFanins, pFanin ); iVar = Vec_PtrSize(p->vDivs) - Abc_ObjFaninNum(pNode) + i; pCands[nCands++] = toLitCond( Vec_IntEntry( p->vProjVars, iVar ), 1 ); } RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands ); if ( RetValue == -1 ) return 0; if ( RetValue == 1 ) { if ( fVeryVerbose ) printf( "Node %d: Fanins %d/%d can be removed.\n", pNode->Id, iFanin, iFanin2 ); p->nNodesResub++; p->nNodesGainedLevel++; clk = clock(); // derive the function pFunc = Abc_NtkMfsInterplate( p, pCands, nCands ); if ( pFunc == NULL ) return 0; // update the network Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); p->timeInt += clock() - clk; return 1; } if ( fVeryVerbose ) { for ( i = 0; i < 11; i++ ) printf( " " ); for ( i = 0; i < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); i++ ) printf( "%d", i % 10 ); for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) if ( i == iFanin || i == iFanin2 ) printf( "*" ); else printf( "%c", 'a' + i ); printf( "\n" ); } iVar = iVar2 = -1; while ( 1 ) { if ( fVeryVerbose ) { printf( "%3d: %2d %2d ", p->nCexes, iVar, iVar2 ); for ( i = 0; i < Vec_PtrSize(p->vDivs); i++ ) { pData = Vec_PtrEntry( p->vDivCexes, i ); printf( "%d", Aig_InfoHasBit(pData, p->nCexes-1) ); } printf( "\n" ); } // find the next divisor to try nWords = Aig_BitWordNum(p->nCexes); assert( nWords <= p->nDivWords ); fBreak = 0; for ( iVar = 1; iVar < Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode); iVar++ ) { pData = Vec_PtrEntry( p->vDivCexes, iVar ); for ( iVar2 = 0; iVar2 < iVar; iVar2++ ) { pData2 = Vec_PtrEntry( p->vDivCexes, iVar2 ); for ( w = 0; w < nWords; w++ ) if ( (pData[w] | pData2[w]) != ~0 ) break; if ( w == nWords ) { fBreak = 1; break; } } if ( fBreak ) break; } if ( iVar == Vec_PtrSize(p->vDivs)-Abc_ObjFaninNum(pNode) ) return 0; pCands[nCands] = toLitCond( Vec_IntEntry(p->vProjVars, iVar2), 1 ); pCands[nCands+1] = toLitCond( Vec_IntEntry(p->vProjVars, iVar), 1 ); RetValue = Abc_NtkMfsTryResubOnce( p, pCands, nCands+2 ); if ( RetValue == -1 ) return 0; if ( RetValue == 1 ) { if ( fVeryVerbose ) printf( "Node %d: Fanins %d/%d can be replaced by divisors %d/%d.\n", pNode->Id, iFanin, iFanin2, iVar, iVar2 ); p->nNodesResub++; p->nNodesGainedLevel++; clk = clock(); // derive the function pFunc = Abc_NtkMfsInterplate( p, pCands, nCands+2 ); if ( pFunc == NULL ) return 0; // update the network Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar2) ); Vec_PtrPush( p->vFanins, Vec_PtrEntry(p->vDivs, iVar) ); assert( Vec_PtrSize(p->vFanins) == nCands + 2 ); Abc_NtkMfsUpdateNetwork( p, pNode, p->vFanins, pFunc ); p->timeInt += clock() - clk; return 1; } if ( p->nCexes >= p->pPars->nDivMax ) break; } return 0; } /**Function************************************************************* Synopsis [Evaluates the possibility of replacing given edge by another edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsEdgeSwapEval( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i; Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 1 ); return 0; } /**Function************************************************************* Synopsis [Evaluates the possibility of replacing given edge by another edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsEdgePower( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; float * pProbab = (float *)p->vProbs->pArray; int i; // try replacing area critical fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( pProbab[pFanin->Id] >= 0.4 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) return 1; } return 0; } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsResubNode( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i; // try replacing area critical fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) return 1; } // try removing redundant edges if ( !p->pPars->fArea ) { Abc_ObjForEachFanin( pNode, pFanin, i ) if ( Abc_ObjIsCi(pFanin) || Abc_ObjFanoutNum(pFanin) != 1 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 1, 0 ) ) return 1; } } if ( Abc_ObjFaninNum(pNode) == p->nFaninMax ) return 0; // try replacing area critical fanins while adding two new fanins Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) return 1; } return 0; } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsResubNode2( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin, * pFanin2; int i, k; /* Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { if ( Abc_NtkMfsSolveSatResub( p, pNode, i, 0, 0 ) ) return 1; } */ if ( Abc_ObjFaninNum(pNode) < 2 ) return 0; // try replacing one area critical fanin and one other fanin while adding two new fanins Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { // consider second fanin to remove at the same time Abc_ObjForEachFanin( pNode, pFanin2, k ) { if ( i != k && Abc_NtkMfsSolveSatResub2( p, pNode, i, k ) ) return 1; } } } return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsSat.c000066400000000000000000000133721300674244400230320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Procedures to compute don't-cares using SAT.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Enumerates through the SAT assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsSolveSat_iter( Mfs_Man_t * p ) { int Lits[MFS_FANIN_MAX]; int RetValue, nBTLimit, iVar, b, Mint; // int nConfs = p->pSat->stats.conflicts; if ( p->nTotConfLim && p->nTotConfLim <= p->pSat->stats.conflicts ) return -1; nBTLimit = p->nTotConfLim? p->nTotConfLim - p->pSat->stats.conflicts : 0; RetValue = sat_solver_solve( p->pSat, NULL, NULL, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); assert( RetValue == l_Undef || RetValue == l_True || RetValue == l_False ); //printf( "%c", RetValue==l_Undef ? '?' : (RetValue==l_False ? '-' : '+') ); //printf( "%d ", p->pSat->stats.conflicts-nConfs ); //if ( RetValue==l_False ) //printf( "\n" ); if ( RetValue == l_Undef ) return -1; if ( RetValue == l_False ) return 0; p->nCares++; // add SAT assignment to the solver Mint = 0; Vec_IntForEachEntry( p->vProjVarsSat, iVar, b ) { Lits[b] = toLit( iVar ); if ( sat_solver_var_value( p->pSat, iVar ) ) { Mint |= (1 << b); Lits[b] = lit_neg( Lits[b] ); } } assert( !Abc_InfoHasBit(p->uCare, Mint) ); Abc_InfoSetBit( p->uCare, Mint ); // add the blocking clause RetValue = sat_solver_addclause( p->pSat, Lits, Lits + Vec_IntSize(p->vProjVarsSat) ); if ( RetValue == 0 ) return 0; return 1; } /**Function************************************************************* Synopsis [Enumerates through the SAT assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfsSolveSat( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Aig_Obj_t * pObjPo; int RetValue, i; // collect projection variables Vec_IntClear( p->vProjVarsSat ); Vec_PtrForEachEntryStart( Aig_Obj_t *, p->pAigWin->vCos, pObjPo, i, Aig_ManCoNum(p->pAigWin) - Abc_ObjFaninNum(pNode) ) { assert( p->pCnf->pVarNums[pObjPo->Id] >= 0 ); Vec_IntPush( p->vProjVarsSat, p->pCnf->pVarNums[pObjPo->Id] ); } // prepare the truth table of care set p->nFanins = Vec_IntSize( p->vProjVarsSat ); p->nWords = Abc_TruthWordNum( p->nFanins ); memset( p->uCare, 0, sizeof(unsigned) * p->nWords ); // iterate through the SAT assignments p->nCares = 0; p->nTotConfLim = p->pPars->nBTLimit; while ( (RetValue = Abc_NtkMfsSolveSat_iter(p)) == 1 ); if ( RetValue == -1 ) return 0; // write statistics p->nMintsCare += p->nCares; p->nMintsTotal += (1<nFanins); if ( p->pPars->fVeryVerbose ) { printf( "Node %4d : Care = %2d. Total = %2d. ", pNode->Id, p->nCares, (1<nFanins) ); Extra_PrintBinary( stdout, p->uCare, (1<nFanins) ); printf( "\n" ); } // map the care if ( p->nFanins > 4 ) return 1; if ( p->nFanins == 4 ) p->uCare[0] = p->uCare[0] | (p->uCare[0] << 16); if ( p->nFanins == 3 ) p->uCare[0] = p->uCare[0] | (p->uCare[0] << 8) | (p->uCare[0] << 16) | (p->uCare[0] << 24); if ( p->nFanins == 2 ) p->uCare[0] = p->uCare[0] | (p->uCare[0] << 4) | (p->uCare[0] << 8) | (p->uCare[0] << 12) | (p->uCare[0] << 16) | (p->uCare[0] << 20) | (p->uCare[0] << 24) | (p->uCare[0] << 28); assert( p->nFanins != 1 ); return 1; } /**Function************************************************************* Synopsis [Adds one-hotness constraints for the window inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkAddOneHotness( Mfs_Man_t * p ) { Aig_Obj_t * pObj1, * pObj2; int i, k, Lits[2]; for ( i = 0; i < Vec_PtrSize(p->pAigWin->vCis); i++ ) for ( k = i+1; k < Vec_PtrSize(p->pAigWin->vCis); k++ ) { pObj1 = Aig_ManCi( p->pAigWin, i ); pObj2 = Aig_ManCi( p->pAigWin, k ); Lits[0] = toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ); Lits[1] = toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ); if ( !sat_solver_addclause( p->pSat, Lits, Lits+2 ) ) { sat_solver_delete( p->pSat ); p->pSat = NULL; return 0; } } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsStrash.c000066400000000000000000000322671300674244400235530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsStrash.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Structural hashing of the window with ODCs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Recursively converts AIG from Aig_Man_t into Hop_Obj_t.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MfsConvertAigToHop_rec( Aig_Obj_t * pObj, Hop_Man_t * pHop ) { assert( !Aig_IsComplement(pObj) ); if ( pObj->pData ) return; Abc_MfsConvertAigToHop_rec( Aig_ObjFanin0(pObj), pHop ); Abc_MfsConvertAigToHop_rec( Aig_ObjFanin1(pObj), pHop ); pObj->pData = Hop_And( pHop, (Hop_Obj_t *)Aig_ObjChild0Copy(pObj), (Hop_Obj_t *)Aig_ObjChild1Copy(pObj) ); assert( !Hop_IsComplement((Hop_Obj_t *)pObj->pData) ); } /**Function************************************************************* Synopsis [Converts AIG from Aig_Man_t into Hop_Obj_t.] Description [Assumes that Aig_Man_t has exactly one primary outputs. Returns the pointer to the root node (Hop_Obj_t) in Hop_Man_t.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_MfsConvertAigToHop( Aig_Man_t * pMan, Hop_Man_t * pHop ) { Aig_Obj_t * pRoot, * pObj; int i; assert( Aig_ManCoNum(pMan) == 1 ); pRoot = Aig_ManCo( pMan, 0 ); // check the case of a constant if ( Aig_ObjIsConst1( Aig_ObjFanin0(pRoot) ) ) return Hop_NotCond( Hop_ManConst1(pHop), Aig_ObjFaninC0(pRoot) ); // set the PI mapping Aig_ManCleanData( pMan ); Aig_ManForEachCi( pMan, pObj, i ) pObj->pData = Hop_IthVar( pHop, i ); // construct the AIG Abc_MfsConvertAigToHop_rec( Aig_ObjFanin0(pRoot), pHop ); return Hop_NotCond( (Hop_Obj_t *)Aig_ObjFanin0(pRoot)->pData, Aig_ObjFaninC0(pRoot) ); } // should be called as follows: pNodeNew->pData = Abc_MfsConvertAigToHop( pAigManInterpol, pNodeNew->pNtk->pManFunc ); /**Function************************************************************* Synopsis [Construct BDDs and mark AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MfsConvertHopToAig_rec( Hop_Obj_t * pObj, Aig_Man_t * pMan ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Abc_MfsConvertHopToAig_rec( Hop_ObjFanin0(pObj), pMan ); Abc_MfsConvertHopToAig_rec( Hop_ObjFanin1(pObj), pMan ); pObj->pData = Aig_And( pMan, (Aig_Obj_t *)Hop_ObjChild0Copy(pObj), (Aig_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 [] ***********************************************************************/ void Abc_MfsConvertHopToAig( Abc_Obj_t * pObjOld, Aig_Man_t * pMan ) { 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) ) ) { pObjOld->pCopy = (Abc_Obj_t *)Aig_NotCond( Aig_ManConst1(pMan), Hop_IsComplement(pRoot) ); pObjOld->pNext = pObjOld->pCopy; return; } // assign the fanin nodes Abc_ObjForEachFanin( pObjOld, pFanin, i ) Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy; // construct the AIG Abc_MfsConvertHopToAig_rec( Hop_Regular(pRoot), pMan ); pObjOld->pCopy = (Abc_Obj_t *)Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); // assign the fanin nodes Abc_ObjForEachFanin( pObjOld, pFanin, i ) Hop_ManPi(pHopMan, i)->pData = pFanin->pNext; // construct the AIG Abc_MfsConvertHopToAig_rec( Hop_Regular(pRoot), pMan ); pObjOld->pNext = (Abc_Obj_t *)Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); } /**Function************************************************************* Synopsis [Computes the care set of the node under ODCs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Abc_NtkConstructAig_rec( Mfs_Man_t * p, Abc_Obj_t * pNode, Aig_Man_t * pMan ) { Aig_Obj_t * pRoot, * pExor; Abc_Obj_t * pObj; int i; // assign AIG nodes to the leaves Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pObj, i ) pObj->pCopy = pObj->pNext = (Abc_Obj_t *)Aig_ObjCreateCi( pMan ); // strash intermediate nodes Abc_NtkIncrementTravId( pNode->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i ) { Abc_MfsConvertHopToAig( pObj, pMan ); if ( pObj == pNode ) pObj->pNext = Abc_ObjNot(pObj->pNext); } // create the observability condition pRoot = Aig_ManConst0(pMan); Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i ) { pExor = Aig_Exor( pMan, (Aig_Obj_t *)pObj->pCopy, (Aig_Obj_t *)pObj->pNext ); pRoot = Aig_Or( pMan, pRoot, pExor ); } return pRoot; } /**Function************************************************************* Synopsis [Adds relevant constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Abc_NtkConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pMan ) { Aig_Obj_t * pObj0, * pObj1; if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) ) return (Aig_Obj_t *)pObj->pData; Aig_ObjSetTravIdCurrent( pCare, pObj ); if ( Aig_ObjIsCi(pObj) ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj0 = Abc_NtkConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pMan ); if ( pObj0 == NULL ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj1 = Abc_NtkConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pMan ); if ( pObj1 == NULL ) return (Aig_Obj_t *)(pObj->pData = NULL); pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) ); pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pMan, pObj0, pObj1 )); } /**Function************************************************************* Synopsis [Creates AIG for the window with constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Abc_NtkConstructAig( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Aig_Man_t * pMan; Abc_Obj_t * pFanin; Aig_Obj_t * pObjAig, * pPi, * pPo; Vec_Int_t * vOuts; int i, k, iOut; // start the new manager pMan = Aig_ManStart( 1000 ); // construct the root node's AIG cone pObjAig = Abc_NtkConstructAig_rec( p, pNode, pMan ); // assert( Aig_ManConst1(pMan) == pObjAig ); Aig_ObjCreateCo( pMan, pObjAig ); if ( p->pCare ) { // mark the care set Aig_ManIncrementTravId( p->pCare ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i ) { pPi = Aig_ManCi( p->pCare, (int)(ABC_PTRUINT_T)pFanin->pData ); Aig_ObjSetTravIdCurrent( p->pCare, pPi ); pPi->pData = pFanin->pCopy; } // construct the constraints Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i ) { vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vSuppsInv, (int)(ABC_PTRUINT_T)pFanin->pData ); Vec_IntForEachEntry( vOuts, iOut, k ) { pPo = Aig_ManCo( p->pCare, iOut ); if ( Aig_ObjIsTravIdCurrent( p->pCare, pPo ) ) continue; Aig_ObjSetTravIdCurrent( p->pCare, pPo ); if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) ) continue; pObjAig = Abc_NtkConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan ); if ( pObjAig == NULL ) continue; pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); Aig_ObjCreateCo( pMan, pObjAig ); } } /* Aig_ManForEachCo( p->pCare, pPo, i ) { // assert( Aig_ObjFanin0(pPo) != Aig_ManConst1(p->pCare) ); if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) ) continue; pObjAig = Abc_NtkConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan ); if ( pObjAig == NULL ) continue; pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); Aig_ObjCreateCo( pMan, pObjAig ); } */ } if ( p->pPars->fResub ) { // construct the node pObjAig = (Aig_Obj_t *)pNode->pCopy; Aig_ObjCreateCo( pMan, pObjAig ); // construct the divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pFanin, i ) { pObjAig = (Aig_Obj_t *)pFanin->pCopy; Aig_ObjCreateCo( pMan, pObjAig ); } } else { // construct the fanins Abc_ObjForEachFanin( pNode, pFanin, i ) { pObjAig = (Aig_Obj_t *)pFanin->pCopy; Aig_ObjCreateCo( pMan, pObjAig ); } } Aig_ManCleanup( pMan ); return pMan; } /**Function************************************************************* Synopsis [Creates AIG for the window with constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Abc_NtkAigForConstraints( Mfs_Man_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; Aig_Man_t * pMan; Aig_Obj_t * pPi, * pPo, * pObjAig, * pObjRoot; Vec_Int_t * vOuts; int i, k, iOut; if ( p->pCare == NULL ) return NULL; pMan = Aig_ManStart( 1000 ); // mark the care set Aig_ManIncrementTravId( p->pCare ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i ) { pPi = Aig_ManCi( p->pCare, (int)(ABC_PTRUINT_T)pFanin->pData ); Aig_ObjSetTravIdCurrent( p->pCare, pPi ); pPi->pData = Aig_ObjCreateCi(pMan); } // construct the constraints pObjRoot = Aig_ManConst1(pMan); Vec_PtrForEachEntry( Abc_Obj_t *, p->vSupp, pFanin, i ) { vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vSuppsInv, (int)(ABC_PTRUINT_T)pFanin->pData ); Vec_IntForEachEntry( vOuts, iOut, k ) { pPo = Aig_ManCo( p->pCare, iOut ); if ( Aig_ObjIsTravIdCurrent( p->pCare, pPo ) ) continue; Aig_ObjSetTravIdCurrent( p->pCare, pPo ); if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(p->pCare) ) continue; pObjAig = Abc_NtkConstructCare_rec( p->pCare, Aig_ObjFanin0(pPo), pMan ); if ( pObjAig == NULL ) continue; pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); pObjRoot = Aig_And( pMan, pObjRoot, pObjAig ); } } Aig_ObjCreateCo( pMan, pObjRoot ); Aig_ManCleanup( pMan ); return pMan; } ABC_NAMESPACE_IMPL_END #include "proof/fra/fra.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Compute the ratio of don't-cares.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Abc_NtkConstraintRatio( Mfs_Man_t * p, Abc_Obj_t * pNode ) { int nSimWords = 256; Aig_Man_t * pMan; Fra_Sml_t * pSim; int Counter; pMan = Abc_NtkAigForConstraints( p, pNode ); pSim = Fra_SmlSimulateComb( pMan, nSimWords, 0 ); Counter = Fra_SmlNodeCountOnes( pSim, Aig_ManCo(pMan, 0) ); Aig_ManStop( pMan ); Fra_SmlStop( pSim ); return 1.0 * Counter / (32 * nSimWords); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfsWin.c000066400000000000000000000072561300674244400230440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfsWin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [Procedures to compute windows stretching to the PIs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfsWin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if the node should be a root.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_MfsComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit ) { Abc_Obj_t * pFanout; int i; // the node is the root if one of the following is true: // (1) the node has more than fanouts than the limit if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit ) return 1; // (2) the node has CO fanouts // (3) the node has fanouts above the cutoff level Abc_ObjForEachFanout( pNode, pFanout, i ) if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax ) return 1; return 0; } /**Function************************************************************* Synopsis [Recursively collects the root candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_MfsComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots ) { Abc_Obj_t * pFanout; int i; assert( Abc_ObjIsNode(pNode) ); if ( Abc_NodeIsTravIdCurrent(pNode) ) return; Abc_NodeSetTravIdCurrent( pNode ); // check if the node should be the root if ( Abc_MfsComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) ) Vec_PtrPush( vRoots, pNode ); else // if not, explore its fanouts Abc_ObjForEachFanout( pNode, pFanout, i ) Abc_MfsComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots ); } /**Function************************************************************* Synopsis [Recursively collects the root candidates.] Description [Returns 1 if the only root is this node.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_MfsComputeRoots( Abc_Obj_t * pNode, int nWinTfoMax, int nFanoutLimit ) { Vec_Ptr_t * vRoots; vRoots = Vec_PtrAlloc( 10 ); Abc_NtkIncrementTravId( pNode->pNtk ); Abc_MfsComputeRoots_rec( pNode, pNode->Level + nWinTfoMax, nFanoutLimit, vRoots ); assert( Vec_PtrSize(vRoots) > 0 ); // if ( Vec_PtrSize(vRoots) == 1 && Vec_PtrEntry(vRoots, 0) == pNode ) // return 0; return vRoots; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/mfs_.c000066400000000000000000000027041300674244400225160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [mfs_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [The good old minimization with complete don't-cares.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: mfs_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "mfsInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/mfs/module.make000066400000000000000000000003251300674244400235470ustar00rootroot00000000000000SRC += src/opt/mfs/mfsCore.c \ src/opt/mfs/mfsDiv.c \ src/opt/mfs/mfsInter.c \ src/opt/mfs/mfsMan.c \ src/opt/mfs/mfsResub.c \ src/opt/mfs/mfsSat.c \ src/opt/mfs/mfsStrash.c \ src/opt/mfs/mfsWin.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/000077500000000000000000000000001300674244400214355ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/module.make000066400000000000000000000005501300674244400235610ustar00rootroot00000000000000SRC += src/opt/nwk/nwkAig.c \ src/opt/nwk/nwkCheck.c \ src/opt/nwk/nwkBidec.c \ src/opt/nwk/nwkDfs.c \ src/opt/nwk/nwkFanio.c \ src/opt/nwk/nwkFlow.c \ src/opt/nwk/nwkMan.c \ src/opt/nwk/nwkMap.c \ src/opt/nwk/nwkMerge.c \ src/opt/nwk/nwkObj.c \ src/opt/nwk/nwkSpeedup.c \ src/opt/nwk/nwkStrash.c \ src/opt/nwk/nwkTiming.c \ src/opt/nwk/nwkUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/ntlnwk.h000066400000000000000000000133411300674244400231250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ntlnwk.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Netlist and network representation.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: ntlnwk.h,v 1.3 2008/10/24 14:18:44 mjarvin Exp $] ***********************************************************************/ #ifndef __NTLNWK_abc_opt_nwk_h #define __NTLNWK_abc_opt_nwk_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Ntl_Man_t_ Ntl_Man_t; typedef struct Nwk_Man_t_ Nwk_Man_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// INLINED FUNCTIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern ABC_DLL Ntl_Man_t * Ntl_ManReadBlif( char * pFileName, int fCheck ); extern ABC_DLL void Ntl_ManWriteBlif( Ntl_Man_t * p, char * pFileName ); extern ABC_DLL Tim_Man_t * Ntl_ManReadTimeMan( Ntl_Man_t * p ); extern ABC_DLL Ntl_Man_t * Ntl_ManDup( Ntl_Man_t * p ); extern ABC_DLL void Ntl_ManFree( Ntl_Man_t * p ); extern ABC_DLL int Ntl_ManIsComb( Ntl_Man_t * p ); extern ABC_DLL void Ntl_ManPrintStats( Ntl_Man_t * p ); extern ABC_DLL int Ntl_ManSweep( Ntl_Man_t * p, int fVerbose ); extern ABC_DLL Ntl_Man_t * Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ); extern ABC_DLL Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ); extern ABC_DLL Aig_Man_t * Ntl_ManExtract( Ntl_Man_t * p ); extern ABC_DLL Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p, int fSeq ); extern ABC_DLL Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p, int nMinDomSize, int fVerbose ); extern ABC_DLL Ntl_Man_t * Ntl_ManDupCollapseLuts( Ntl_Man_t * p ); extern ABC_DLL Ntl_Man_t * Ntl_ManFraig( Ntl_Man_t * p, int nPartSize, int nConfLimit, int nLevelMax, int fUseCSat, int fVerbose ); extern ABC_DLL void Ntl_ManPrepareCecMans( Ntl_Man_t * pMan1, Ntl_Man_t * pMan2, Aig_Man_t ** ppAig1, Aig_Man_t ** ppAig2 ); extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCiNames( Ntl_Man_t * p ); extern ABC_DLL Vec_Ptr_t * Ntl_ManCollectCoNames( Ntl_Man_t * p ); extern ABC_DLL Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVerbose ); extern ABC_DLL Ntl_Man_t * Ntl_ManLcorr( Ntl_Man_t * p, int nConfMax, int fScorrGia, int fUseCSat, int fVerbose ); extern ABC_DLL Ntl_Man_t * Ntl_ManSsw( Ntl_Man_t * p, Fra_Ssw_t * pPars ); extern ABC_DLL Ntl_Man_t * Ntl_ManScorr( Ntl_Man_t * p, Ssw_Pars_t * pPars ); extern ABC_DLL void Ntl_ManTransformInitValues( Ntl_Man_t * p ); extern ABC_DLL void Ntl_ManPrepareCec( char * pFileName1, char * pFileName2, Aig_Man_t ** ppMan1, Aig_Man_t ** ppMan2 ); extern ABC_DLL Aig_Man_t * Ntl_ManPrepareSec( char * pFileName1, char * pFileName2 ); extern ABC_DLL Nwk_Man_t * Ntl_ManExtractNwk( Ntl_Man_t * p, Aig_Man_t * pAig, Tim_Man_t * pManTime ); extern ABC_DLL Nwk_Man_t * Ntl_ManReadNwk( char * pFileName, Aig_Man_t * pAig, Tim_Man_t * pManTime ); extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_LibLut_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ); extern ABC_DLL void Nwk_ManPrintStatsShort( Ntl_Man_t * p, Aig_Man_t * pAig, Nwk_Man_t * pNtk ); extern ABC_DLL void Nwk_ManPrintFanioNew( Nwk_Man_t * p ); extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ); extern ABC_DLL void Nwk_ManSetIfParsDefault( If_Par_t * pPars ); extern ABC_DLL void Nwk_ManBidecResyn( Nwk_Man_t * p, int fVerbose ); extern ABC_DLL Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * p, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); extern ABC_DLL Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * p ); extern ABC_DLL Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * p, void * pPars ); extern ABC_DLL int Nwk_ManCheck( Nwk_Man_t * p ); extern ABC_DLL void Nwk_ManDumpBlif( Nwk_Man_t * p, char * pFileName, Vec_Ptr_t * vCiNames, Vec_Ptr_t * vCoNames ); extern ABC_DLL void Nwk_ManFree( Nwk_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwk.h000066400000000000000000000466601300674244400224210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwk.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwk.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $] ***********************************************************************/ #ifndef __NWK_abc_opt_nwk_h #define __NWK_abc_opt_nwk_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/aig/aig.h" #include "aig/hop/hop.h" #include "misc/tim/tim.h" #include "map/if/if.h" #include "bool/bdc/bdc.h" #include "proof/fra/fra.h" #include "proof/ssw/ssw.h" #include "ntlnwk.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Nwk_Obj_t_ Nwk_Obj_t; // object types typedef enum { NWK_OBJ_NONE, // 0: non-existant object NWK_OBJ_CI, // 1: combinational input NWK_OBJ_CO, // 2: combinational output NWK_OBJ_NODE, // 3: logic node NWK_OBJ_LATCH, // 4: register NWK_OBJ_VOID // 5: unused object } Nwk_Type_t; struct Nwk_Man_t_ { // models of this design char * pName; // the name of this design char * pSpec; // the name of input file // node representation Vec_Ptr_t * vCis; // the primary inputs of the extracted part Vec_Ptr_t * vCos; // the primary outputs of the extracted part Vec_Ptr_t * vObjs; // the objects in the topological order int nObjs[NWK_OBJ_VOID]; // counter of objects of each type int nFanioPlus; // the number of extra fanins/fanouts alloc by default // functionality, timing, memory, etc Hop_Man_t * pManHop; // the functionality representation Tim_Man_t * pManTime; // the timing manager If_LibLut_t * pLutLib; // the LUT library Aig_MmFlex_t * pMemObjs; // memory for objects Vec_Ptr_t * vTemp; // array used for incremental updates int nTravIds; // the counter of traversal IDs int nRealloced; // the number of realloced nodes // sequential information int nLatches; // the total number of latches int nTruePis; // the number of true primary inputs int nTruePos; // the number of true primary outputs }; struct Nwk_Obj_t_ { Nwk_Man_t * pMan; // the manager Hop_Obj_t * pFunc; // functionality void * pCopy; // temporary pointer union { void * pNext; // temporary pointer int iTemp; // temporary number }; // node information unsigned Type : 3; // object type unsigned fInvert : 1; // complemented attribute unsigned MarkA : 1; // temporary mark unsigned MarkB : 1; // temporary mark unsigned MarkC : 1; // temporary mark unsigned PioId : 25; // number of this node in the PI/PO list int Id; // unique ID int TravId; // traversal ID // timing information int Level; // the topological level float tArrival; // the arrival time float tRequired; // the required time float tSlack; // the slack // fanin/fanout representation int nFanins; // the number of fanins int nFanouts; // the number of fanouts int nFanioAlloc; // the number of allocated fanins/fanouts Nwk_Obj_t ** pFanio; // fanins/fanouts }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// INLINED FUNCTIONS /// //////////////////////////////////////////////////////////////////////// static inline int Nwk_ManCiNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_CI]; } static inline int Nwk_ManCoNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_CO]; } static inline int Nwk_ManNodeNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_NODE]; } static inline int Nwk_ManLatchNum( Nwk_Man_t * p ) { return p->nObjs[NWK_OBJ_LATCH]; } static inline int Nwk_ManObjNumMax( Nwk_Man_t * p ) { return Vec_PtrSize(p->vObjs); } static inline Nwk_Obj_t * Nwk_ManCi( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vCis, i ); } static inline Nwk_Obj_t * Nwk_ManCo( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vCos, i ); } static inline Nwk_Obj_t * Nwk_ManObj( Nwk_Man_t * p, int i ) { return (Nwk_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } static inline int Nwk_ObjId( Nwk_Obj_t * p ) { return p->Id; } static inline int Nwk_ObjPioNum( Nwk_Obj_t * p ) { return p->PioId; } static inline int Nwk_ObjFaninNum( Nwk_Obj_t * p ) { return p->nFanins; } static inline int Nwk_ObjFanoutNum( Nwk_Obj_t * p ) { return p->nFanouts; } static inline Nwk_Obj_t * Nwk_ObjFanin0( Nwk_Obj_t * p ) { return p->pFanio[0]; } static inline Nwk_Obj_t * Nwk_ObjFanout0( Nwk_Obj_t * p ) { return p->pFanio[p->nFanins]; } static inline Nwk_Obj_t * Nwk_ObjFanin( Nwk_Obj_t * p, int i ) { return p->pFanio[i]; } static inline Nwk_Obj_t * Nwk_ObjFanout( Nwk_Obj_t * p, int i ) { return p->pFanio[p->nFanins+1]; } static inline int Nwk_ObjIsNone( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_NONE; } static inline int Nwk_ObjIsCi( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_CI; } static inline int Nwk_ObjIsCo( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_CO; } static inline int Nwk_ObjIsNode( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_NODE; } static inline int Nwk_ObjIsLatch( Nwk_Obj_t * p ) { return p->Type == NWK_OBJ_LATCH; } static inline int Nwk_ObjIsPi( Nwk_Obj_t * p ) { return Nwk_ObjIsCi(p) && (p->pMan->pManTime == NULL || Tim_ManBoxForCi(p->pMan->pManTime, p->PioId) == -1); } static inline int Nwk_ObjIsPo( Nwk_Obj_t * p ) { return Nwk_ObjIsCo(p) && (p->pMan->pManTime == NULL || Tim_ManBoxForCo(p->pMan->pManTime, p->PioId) == -1); } static inline int Nwk_ObjIsLi( Nwk_Obj_t * p ) { return p->pMan->nTruePos && Nwk_ObjIsCo(p) && (int)p->PioId >= p->pMan->nTruePos; } static inline int Nwk_ObjIsLo( Nwk_Obj_t * p ) { return p->pMan->nTruePis && Nwk_ObjIsCi(p) && (int)p->PioId >= p->pMan->nTruePis; } static inline float Nwk_ObjArrival( Nwk_Obj_t * pObj ) { return pObj->tArrival; } static inline float Nwk_ObjRequired( Nwk_Obj_t * pObj ) { return pObj->tRequired; } static inline float Nwk_ObjSlack( Nwk_Obj_t * pObj ) { return pObj->tSlack; } static inline void Nwk_ObjSetArrival( Nwk_Obj_t * pObj, float Time ) { pObj->tArrival = Time; } static inline void Nwk_ObjSetRequired( Nwk_Obj_t * pObj, float Time ) { pObj->tRequired = Time; } static inline void Nwk_ObjSetSlack( Nwk_Obj_t * pObj, float Time ) { pObj->tSlack = Time; } static inline int Nwk_ObjLevel( Nwk_Obj_t * pObj ) { return pObj->Level; } static inline void Nwk_ObjSetLevel( Nwk_Obj_t * pObj, int Level ) { pObj->Level = Level; } static inline void Nwk_ObjSetTravId( Nwk_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } static inline void Nwk_ObjSetTravIdCurrent( Nwk_Obj_t * pObj ) { pObj->TravId = pObj->pMan->nTravIds; } static inline void Nwk_ObjSetTravIdPrevious( Nwk_Obj_t * pObj ) { pObj->TravId = pObj->pMan->nTravIds - 1; } static inline int Nwk_ObjIsTravIdCurrent( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds; } static inline int Nwk_ObjIsTravIdPrevious( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 1; } static inline int Nwk_ManTimeEqual( float f1, float f2, float Eps ) { return (f1 < f2 + Eps) && (f2 < f1 + Eps); } static inline int Nwk_ManTimeLess( float f1, float f2, float Eps ) { return (f1 < f2 + Eps); } static inline int Nwk_ManTimeMore( float f1, float f2, float Eps ) { return (f1 + Eps > f2); } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// #define Nwk_ManForEachCi( p, pObj, i ) \ Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCis, pObj, i ) #define Nwk_ManForEachCo( p, pObj, i ) \ Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCos, pObj, i ) #define Nwk_ManForEachPi( p, pObj, i ) \ Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCis, pObj, i ) \ if ( !Nwk_ObjIsPi(pObj) ) {} else #define Nwk_ManForEachPo( p, pObj, i ) \ Vec_PtrForEachEntry( Nwk_Obj_t *, p->vCos, pObj, i ) \ if ( !Nwk_ObjIsPo(pObj) ) {} else #define Nwk_ManForEachObj( p, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ if ( pObj == NULL ) {} else #define Nwk_ManForEachNode( p, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ if ( (pObj) == NULL || !Nwk_ObjIsNode(pObj) ) {} else #define Nwk_ManForEachLatch( p, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize(p->vObjs)) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vObjs, i)), 1); i++ ) \ if ( (pObj) == NULL || !Nwk_ObjIsLatch(pObj) ) {} else #define Nwk_ObjForEachFanin( pObj, pFanin, i ) \ for ( i = 0; (i < (int)(pObj)->nFanins) && ((pFanin) = (pObj)->pFanio[i]); i++ ) #define Nwk_ObjForEachFanout( pObj, pFanout, i ) \ for ( i = 0; (i < (int)(pObj)->nFanouts) && ((pFanout) = (pObj)->pFanio[(pObj)->nFanins+i]); i++ ) // sequential iterators #define Nwk_ManForEachPiSeq( p, pObj, i ) \ Vec_PtrForEachEntryStop( Nwk_Obj_t *, p->vCis, pObj, i, (p)->nTruePis ) #define Nwk_ManForEachPoSeq( p, pObj, i ) \ Vec_PtrForEachEntryStop( Nwk_Obj_t *, p->vCos, pObj, i, (p)->nTruePos ) #define Nwk_ManForEachLoSeq( p, pObj, i ) \ for ( i = 0; (i < (p)->nLatches) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vCis, i+(p)->nTruePis)), 1); i++ ) #define Nwk_ManForEachLiSeq( p, pObj, i ) \ for ( i = 0; (i < (p)->nLatches) && (((pObj) = (Nwk_Obj_t *)Vec_PtrEntry(p->vCos, i+(p)->nTruePos)), 1); i++ ) #define Nwk_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) \ for ( i = 0; (i < (p)->nLatches) && (((pObjLi) = Nwk_ManCo(p, i+(p)->nTruePos)), 1) \ && (((pObjLo) = Nwk_ManCi(p, i+(p)->nTruePis)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== nwkAig.c ==========================================================*/ extern ABC_DLL Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose ); /*=== nwkBidec.c ==========================================================*/ extern ABC_DLL void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose ); extern ABC_DLL Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ); /*=== nwkCheck.c ==========================================================*/ extern ABC_DLL int Nwk_ManCheck( Nwk_Man_t * p ); /*=== nwkDfs.c ==========================================================*/ extern ABC_DLL int Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ManLevelBackup( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ManLevel( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ManLevelMax( Nwk_Man_t * pNtk ); extern ABC_DLL Vec_Vec_t * Nwk_ManLevelize( Nwk_Man_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Nwk_ManDfs( Nwk_Man_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ); extern ABC_DLL Vec_Ptr_t * Nwk_ManDfsReverse( Nwk_Man_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ); extern ABC_DLL void Nwk_ManSupportSum( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ObjMffcLabel( Nwk_Obj_t * pNode ); /*=== nwkFanio.c ==========================================================*/ extern ABC_DLL void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ); extern ABC_DLL void Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ); extern ABC_DLL int Nwk_ObjFindFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); extern ABC_DLL int Nwk_ObjFindFanout( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanout ); extern ABC_DLL void Nwk_ObjAddFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); extern ABC_DLL void Nwk_ObjDeleteFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ); extern ABC_DLL void Nwk_ObjPatchFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFaninOld, Nwk_Obj_t * pFaninNew ); extern ABC_DLL void Nwk_ObjTransferFanout( Nwk_Obj_t * pNodeFrom, Nwk_Obj_t * pNodeTo ); extern ABC_DLL void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNew ); /*=== nwkFlow.c ============================================================*/ extern ABC_DLL Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ); extern ABC_DLL Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ); /*=== nwkMan.c ============================================================*/ extern ABC_DLL Nwk_Man_t * Nwk_ManAlloc(); extern ABC_DLL void Nwk_ManFree( Nwk_Man_t * p ); extern ABC_DLL float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk ); extern ABC_DLL void Nwk_ManPrintStats( Nwk_Man_t * p, If_LibLut_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ); /*=== nwkMap.c ============================================================*/ extern ABC_DLL Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ); /*=== nwkObj.c ============================================================*/ extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * pMan, int nFanouts ); extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * pMan ); extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateNode( Nwk_Man_t * pMan, int nFanins, int nFanouts ); extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateBox( Nwk_Man_t * pMan, int nFanins, int nFanouts ); extern ABC_DLL Nwk_Obj_t * Nwk_ManCreateLatch( Nwk_Man_t * pMan ); extern ABC_DLL void Nwk_ManDeleteNode( Nwk_Obj_t * pObj ); extern ABC_DLL void Nwk_ManDeleteNode_rec( Nwk_Obj_t * pObj ); /*=== nwkSpeedup.c ============================================================*/ extern ABC_DLL Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); /*=== nwkStrash.c ============================================================*/ extern ABC_DLL Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk ); /*=== nwkTiming.c ============================================================*/ extern ABC_DLL int Nwk_ManVerifyTiming( Nwk_Man_t * pNtk ); extern ABC_DLL void Nwk_ManDelayTraceSortPins( Nwk_Obj_t * pNode, int * pPinPerm, float * pPinDelays ); extern ABC_DLL float Nwk_ManDelayTraceLut( Nwk_Man_t * pNtk ); extern ABC_DLL void Nwk_ManDelayTracePrint( Nwk_Man_t * pNtk ); extern ABC_DLL void Nwk_ManUpdate( Nwk_Obj_t * pObj, Nwk_Obj_t * pObjNew, Vec_Vec_t * vLevels ); extern ABC_DLL int Nwk_ManVerifyLevel( Nwk_Man_t * pNtk ); /*=== nwkUtil.c ============================================================*/ extern ABC_DLL void Nwk_ManIncrementTravId( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ManGetFaninMax( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ManPiNum( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ManPoNum( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk ); extern ABC_DLL int Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ); extern ABC_DLL int Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ); extern ABC_DLL void Nwk_ObjPrint( Nwk_Obj_t * pObj ); extern ABC_DLL void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vCiNames, Vec_Ptr_t * vCoNames ); extern ABC_DLL void Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk ); extern ABC_DLL void Nwk_ManCleanMarks( Nwk_Man_t * pNtk ); extern ABC_DLL void Nwk_ManMinimumBase( Nwk_Man_t * pNtk, int fVerbose ); extern ABC_DLL void Nwk_ManRemoveDupFanins( Nwk_Man_t * pNtk, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkAig.c000066400000000000000000000240531300674244400230250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkAig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Netlist representation.] Synopsis [Translating of AIG into the network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converts AIG into the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Man_t * Nwk_ManDeriveFromAig( Aig_Man_t * p ) { Nwk_Man_t * pNtk; Aig_Obj_t * pObj; int i; pNtk = Nwk_ManAlloc(); pNtk->nFanioPlus = 0; Hop_ManStop( pNtk->pManHop ); pNtk->pManHop = NULL; pNtk->pName = Abc_UtilStrsav( p->pName ); pNtk->pSpec = Abc_UtilStrsav( p->pSpec ); pObj = Aig_ManConst1(p); pObj->pData = Nwk_ManCreateNode( pNtk, 0, pObj->nRefs ); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Nwk_ManCreateCi( pNtk, pObj->nRefs ); Aig_ManForEachNode( p, pObj, i ) { pObj->pData = Nwk_ManCreateNode( pNtk, 2, pObj->nRefs ); Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin1(pObj)->pData ); } Aig_ManForEachCo( p, pObj, i ) { pObj->pData = Nwk_ManCreateCo( pNtk ); Nwk_ObjAddFanin( (Nwk_Obj_t *)pObj->pData, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); } return pNtk; } /**Function************************************************************* Synopsis [Converts AIG into the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose ) { Vec_Ptr_t * vNodes; Nwk_Man_t * pNtk; Nwk_Obj_t * pNode; Aig_Obj_t * pObj; int i; pNtk = Nwk_ManDeriveFromAig( p ); if ( fForward ) vNodes = Nwk_ManRetimeCutForward( pNtk, Aig_ManRegNum(p), fVerbose ); else vNodes = Nwk_ManRetimeCutBackward( pNtk, Aig_ManRegNum(p), fVerbose ); Aig_ManForEachObj( p, pObj, i ) ((Nwk_Obj_t *)pObj->pData)->pCopy = pObj; Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pNode, i ) Vec_PtrWriteEntry( vNodes, i, pNode->pCopy ); Nwk_ManFree( pNtk ); // assert( Vec_PtrSize(vNodes) <= Aig_ManRegNum(p) ); return vNodes; } ABC_NAMESPACE_IMPL_END #include "proof/abs/abs.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Collects reachable nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManColleacReached_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes, Vec_Int_t * vLeaves ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vLeaves, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Nwk_ManColleacReached_rec( p, Gia_ObjFanin0(pObj), vNodes, vLeaves ); Nwk_ManColleacReached_rec( p, Gia_ObjFanin1(pObj), vNodes, vLeaves ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } /**Function************************************************************* Synopsis [Converts AIG into the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Man_t * Nwk_ManCreateFromGia( Gia_Man_t * p, Vec_Int_t * vPPis, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t ** pvMapInv ) { Nwk_Man_t * pNtk; Nwk_Obj_t ** ppCopies; Gia_Obj_t * pObj; Vec_Int_t * vMaps; int i; // assert( Vec_IntSize(vLeaves) >= Vec_IntSize(vPPis) ); Gia_ManCreateRefs( p ); pNtk = Nwk_ManAlloc(); pNtk->pName = Abc_UtilStrsav( p->pName ); pNtk->nFanioPlus = 0; Hop_ManStop( pNtk->pManHop ); pNtk->pManHop = NULL; // allocate vMaps = Vec_IntAlloc( Vec_IntSize(vNodes) + Abc_MaxInt(Vec_IntSize(vPPis), Vec_IntSize(vLeaves)) + 1 ); ppCopies = ABC_ALLOC( Nwk_Obj_t *, Gia_ManObjNum(p) ); // copy objects pObj = Gia_ManConst0(p); // ppCopies[Gia_ObjId(p,pObj)] = Nwk_ManCreateNode( pNtk, 0, Gia_ObjRefNum(p,pObj) ); ppCopies[Gia_ObjId(p,pObj)] = Nwk_ManCreateNode( pNtk, 0, Gia_ObjRefNum(p,pObj) + (Vec_IntSize(vLeaves) > Vec_IntSize(vPPis) ? Vec_IntSize(vLeaves) - Vec_IntSize(vPPis) : 0) ); Vec_IntPush( vMaps, Gia_ObjId(p,pObj) ); Gia_ManForEachObjVec( vLeaves, p, pObj, i ) { ppCopies[Gia_ObjId(p,pObj)] = Nwk_ManCreateCi( pNtk, Gia_ObjRefNum(p,pObj) ); assert( Vec_IntSize(vMaps) == Nwk_ObjId(ppCopies[Gia_ObjId(p,pObj)]) ); Vec_IntPush( vMaps, Gia_ObjId(p,pObj) ); } for ( i = Vec_IntSize(vLeaves); i < Vec_IntSize(vPPis); i++ ) { Nwk_ManCreateCi( pNtk, 0 ); Vec_IntPush( vMaps, -1 ); } Gia_ManForEachObjVec( vNodes, p, pObj, i ) { ppCopies[Gia_ObjId(p,pObj)] = Nwk_ManCreateNode( pNtk, 2, Gia_ObjRefNum(p,pObj) ); Nwk_ObjAddFanin( ppCopies[Gia_ObjId(p,pObj)], ppCopies[Gia_ObjFaninId0p(p,pObj)] ); Nwk_ObjAddFanin( ppCopies[Gia_ObjId(p,pObj)], ppCopies[Gia_ObjFaninId1p(p,pObj)] ); assert( Vec_IntSize(vMaps) == Nwk_ObjId(ppCopies[Gia_ObjId(p,pObj)]) ); Vec_IntPush( vMaps, Gia_ObjId(p,pObj) ); } Gia_ManForEachObjVec( vPPis, p, pObj, i ) { assert( ppCopies[Gia_ObjId(p,pObj)] != NULL ); Nwk_ObjAddFanin( Nwk_ManCreateCo(pNtk), ppCopies[Gia_ObjId(p,pObj)] ); } for ( i = Vec_IntSize(vPPis); i < Vec_IntSize(vLeaves); i++ ) Nwk_ObjAddFanin( Nwk_ManCreateCo(pNtk), ppCopies[0] ); assert( Vec_IntSize(vMaps) == Vec_IntSize(vNodes) + Abc_MaxInt(Vec_IntSize(vPPis), Vec_IntSize(vLeaves)) + 1 ); ABC_FREE( ppCopies ); *pvMapInv = vMaps; return pNtk; } /**Function************************************************************* Synopsis [Returns min-cut in the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDeriveMinCut( Gia_Man_t * p, int fVerbose ) { Nwk_Man_t * pNtk; Nwk_Obj_t * pNode; Vec_Ptr_t * vMinCut; Vec_Int_t * vPPis, * vNodes, * vLeaves, * vNodes2, * vLeaves2, * vMapInv; Vec_Int_t * vCommon, * vDiff0, * vDiff1; Gia_Obj_t * pObj; int i, iObjId; // get inputs Gia_ManGlaCollect( p, p->vGateClasses, NULL, &vPPis, NULL, NULL ); // collect nodes rechable from PPIs vNodes = Vec_IntAlloc( 100 ); vLeaves = Vec_IntAlloc( 100 ); Gia_ManIncrementTravId( p ); Gia_ManForEachObjVec( vPPis, p, pObj, i ) Nwk_ManColleacReached_rec( p, pObj, vNodes, vLeaves ); // derive the new network pNtk = Nwk_ManCreateFromGia( p, vPPis, vNodes, vLeaves, &vMapInv ); assert( Nwk_ManPiNum(pNtk) == Nwk_ManPoNum(pNtk) ); // create min-cut vMinCut = Nwk_ManRetimeCutBackward( pNtk, Nwk_ManPiNum(pNtk), fVerbose ); // copy from the GIA back // Aig_ManForEachObj( p, pObj, i ) // ((Nwk_Obj_t *)pObj->pData)->pCopy = pObj; // mark min-cut nodes vNodes2 = Vec_IntAlloc( 100 ); vLeaves2 = Vec_IntAlloc( 100 ); Gia_ManIncrementTravId( p ); Vec_PtrForEachEntry( Nwk_Obj_t *, vMinCut, pNode, i ) { pObj = Gia_ManObj( p, Vec_IntEntry(vMapInv, Nwk_ObjId(pNode)) ); if ( Gia_ObjIsConst0(pObj) ) continue; Nwk_ManColleacReached_rec( p, pObj, vNodes2, vLeaves2 ); } if ( fVerbose ) printf( "Min-cut: %d -> %d. Nodes %d -> %d. ", Vec_IntSize(vPPis)+1, Vec_PtrSize(vMinCut), Vec_IntSize(vNodes), Vec_IntSize(vNodes2) ); Vec_IntFree( vPPis ); Vec_PtrFree( vMinCut ); Vec_IntFree( vMapInv ); Nwk_ManFree( pNtk ); // sort the results Vec_IntSort( vNodes, 0 ); Vec_IntSort( vNodes2, 0 ); vCommon = Vec_IntAlloc( Vec_IntSize(vNodes) ); vDiff0 = Vec_IntAlloc( 100 ); vDiff1 = Vec_IntAlloc( 100 ); Vec_IntTwoSplit( vNodes, vNodes2, vCommon, vDiff0, vDiff1 ); if ( fVerbose ) printf( "Common = %d. Diff0 = %d. Diff1 = %d.\n", Vec_IntSize(vCommon), Vec_IntSize(vDiff0), Vec_IntSize(vDiff1) ); // fill in Vec_IntForEachEntry( vDiff0, iObjId, i ) Vec_IntWriteEntry( p->vGateClasses, iObjId, 1 ); Vec_IntFree( vLeaves ); Vec_IntFree( vNodes ); Vec_IntFree( vLeaves2 ); Vec_IntFree( vNodes2 ); Vec_IntFree( vCommon ); Vec_IntFree( vDiff0 ); Vec_IntFree( vDiff1 ); // check abstraction Gia_ManForEachObj( p, pObj, i ) { if ( Vec_IntEntry( p->vGateClasses, i ) == 0 ) continue; assert( Gia_ObjIsConst0(pObj) || Gia_ObjIsRo(p, pObj) || Gia_ObjIsAnd(pObj) ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkBidec.c000066400000000000000000000133271300674244400233350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkBidec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Bi-decomposition of local functions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn[w]; } static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] | pIn1[w]; } static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) { int w; for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn0[w] & ~pIn1[w]; } static inline Hop_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Resynthesizes nodes using bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Nwk_NodeIfNodeResyn( Bdc_Man_t * p, Hop_Man_t * pHop, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, unsigned * puCare, float dProb ) { unsigned * pTruth; Bdc_Fun_t * pFunc; int nNodes, i; assert( nVars <= 16 ); // derive truth table pTruth = Hop_ManConvertAigToTruth( pHop, Hop_Regular(pRoot), nVars, vTruth, 0 ); if ( Hop_IsComplement(pRoot) ) for ( i = Abc_TruthWordNum(nVars)-1; i >= 0; i-- ) pTruth[i] = ~pTruth[i]; // perform power-aware decomposition if ( dProb >= 0.0 ) { float Prob = (float)2.0 * dProb * (1.0 - dProb); assert( Prob >= 0.0 && Prob <= 0.5 ); if ( Prob >= 0.4 ) { Extra_TruthNot( puCare, puCare, nVars ); if ( dProb > 0.5 ) // more 1s than 0s Extra_TruthOr( pTruth, pTruth, puCare, nVars ); else Extra_TruthSharp( pTruth, pTruth, puCare, nVars ); Extra_TruthNot( puCare, puCare, nVars ); // decompose truth table Bdc_ManDecompose( p, pTruth, NULL, nVars, NULL, 1000 ); } else { // decompose truth table Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); } } else { // decompose truth table Bdc_ManDecompose( p, pTruth, puCare, nVars, NULL, 1000 ); } // convert back into HOP Bdc_FuncSetCopy( Bdc_ManFunc( p, 0 ), Hop_ManConst1( pHop ) ); for ( i = 0; i < nVars; i++ ) Bdc_FuncSetCopy( Bdc_ManFunc( p, i+1 ), Hop_ManPi( pHop, i ) ); nNodes = Bdc_ManNodeNum(p); for ( i = nVars + 1; i < nNodes; i++ ) { pFunc = Bdc_ManFunc( p, i ); Bdc_FuncSetCopy( pFunc, Hop_And( pHop, Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) ); } return Bdc_FunCopyHop( Bdc_ManRoot(p) ); } /**Function************************************************************* Synopsis [Resynthesizes nodes using bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManBidecResyn( Nwk_Man_t * pNtk, int fVerbose ) { Bdc_Par_t Pars = {0}, * pPars = &Pars; Bdc_Man_t * p; Nwk_Obj_t * pObj; Vec_Int_t * vTruth; int i, nGainTotal = 0, nNodes1, nNodes2; abctime clk = Abc_Clock(); pPars->nVarsMax = Nwk_ManGetFaninMax( pNtk ); pPars->fVerbose = fVerbose; if ( pPars->nVarsMax < 2 ) { printf( "Resynthesis is not performed for networks whose nodes are less than 2 inputs.\n" ); return; } if ( pPars->nVarsMax > 15 ) { if ( fVerbose ) printf( "Resynthesis is not performed for nodes with more than 15 inputs.\n" ); pPars->nVarsMax = 15; } vTruth = Vec_IntAlloc( 0 ); p = Bdc_ManAlloc( pPars ); Nwk_ManForEachNode( pNtk, pObj, i ) { if ( Nwk_ObjFaninNum(pObj) > 15 ) continue; nNodes1 = Hop_DagSize(pObj->pFunc); pObj->pFunc = Nwk_NodeIfNodeResyn( p, pNtk->pManHop, pObj->pFunc, Nwk_ObjFaninNum(pObj), vTruth, NULL, -1.0 ); nNodes2 = Hop_DagSize(pObj->pFunc); nGainTotal += nNodes1 - nNodes2; } Bdc_ManFree( p ); Vec_IntFree( vTruth ); if ( fVerbose ) { printf( "Total gain in AIG nodes = %d. ", nGainTotal ); ABC_PRT( "Total runtime", Abc_Clock() - clk ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkCheck.c000066400000000000000000000050721300674244400233420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkCheck.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Consistency checking procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checking the logic network for consistency.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManCheck( Nwk_Man_t * p ) { Nwk_Obj_t * pObj, * pNext; int i, k, m; // check if the nodes have duplicated fanins Nwk_ManForEachNode( p, pObj, i ) { for ( k = 0; k < pObj->nFanins; k++ ) for ( m = k + 1; m < pObj->nFanins; m++ ) if ( pObj->pFanio[k] == pObj->pFanio[m] ) printf( "Node %d has duplicated fanin %d.\n", pObj->Id, pObj->pFanio[k]->Id ); } // check if all nodes are in the correct fanin/fanout relationship Nwk_ManForEachObj( p, pObj, i ) { Nwk_ObjForEachFanin( pObj, pNext, k ) if ( Nwk_ObjFanoutNum(pNext) < 100 && Nwk_ObjFindFanout( pNext, pObj ) == -1 ) printf( "Nwk_ManCheck(): Object %d has fanin %d which does not have a corresponding fanout.\n", pObj->Id, pNext->Id ); Nwk_ObjForEachFanout( pObj, pNext, k ) if ( Nwk_ObjFindFanin( pNext, pObj ) == -1 ) printf( "Nwk_ManCheck(): Object %d has fanout %d which does not have a corresponding fanin.\n", pObj->Id, pNext->Id ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkDfs.c000066400000000000000000000445111300674244400230420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkDfs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [DFS traversals.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Verifies that the objects are in a topo order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManVerifyTopoOrder( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj, * pNext; int i, k, iBox, iTerm1, nTerms; Nwk_ManIncrementTravId( pNtk ); Nwk_ManForEachObj( pNtk, pObj, i ) { if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ) { Nwk_ObjForEachFanin( pObj, pNext, k ) { if ( !Nwk_ObjIsTravIdCurrent(pNext) ) { printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); return 0; } } } else if ( Nwk_ObjIsCi(pObj) ) { if ( pNtk->pManTime ) { iBox = Tim_ManBoxForCi( pNtk->pManTime, pObj->PioId ); if ( iBox >= 0 ) // this is not a true PI { iTerm1 = Tim_ManBoxInputFirst( pNtk->pManTime, iBox ); nTerms = Tim_ManBoxInputNum( pNtk->pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pNext = Nwk_ManCo( pNtk, iTerm1 + k ); if ( !Nwk_ObjIsTravIdCurrent(pNext) ) { printf( "Box %d has input %d that is not in a topological order.\n", iBox, pNext->Id ); return 0; } } } } } else assert( 0 ); Nwk_ObjSetTravIdCurrent( pObj ); } return 1; } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [Assumes that white boxes have unit level.] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManLevelBackup( Nwk_Man_t * pNtk ) { Tim_Man_t * pManTimeUnit; Nwk_Obj_t * pObj, * pFanin; int i, k, LevelMax, Level; assert( Nwk_ManVerifyTopoOrder(pNtk) ); // clean the levels Nwk_ManForEachObj( pNtk, pObj, i ) Nwk_ObjSetLevel( pObj, 0 ); // perform level computation LevelMax = 0; pManTimeUnit = pNtk->pManTime ? Tim_ManDup( pNtk->pManTime, 1 ) : NULL; if ( pManTimeUnit ) Tim_ManIncrementTravId( pManTimeUnit ); Nwk_ManForEachObj( pNtk, pObj, i ) { if ( Nwk_ObjIsCi(pObj) ) { Level = pManTimeUnit? (int)Tim_ManGetCiArrival( pManTimeUnit, pObj->PioId ) : 0; Nwk_ObjSetLevel( pObj, Level ); } else if ( Nwk_ObjIsCo(pObj) ) { Level = Nwk_ObjLevel( Nwk_ObjFanin0(pObj) ); if ( pManTimeUnit ) Tim_ManSetCoArrival( pManTimeUnit, pObj->PioId, (float)Level ); Nwk_ObjSetLevel( pObj, Level ); if ( LevelMax < Nwk_ObjLevel(pObj) ) LevelMax = Nwk_ObjLevel(pObj); } else if ( Nwk_ObjIsNode(pObj) ) { Level = 0; Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( Level < Nwk_ObjLevel(pFanin) ) Level = Nwk_ObjLevel(pFanin); Nwk_ObjSetLevel( pObj, Level + 1 ); } else assert( 0 ); } // set the old timing manager if ( pManTimeUnit ) Tim_ManStop( pManTimeUnit ); return LevelMax; } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManLevel_rec( Nwk_Obj_t * pObj ) { Tim_Man_t * pManTime = pObj->pMan->pManTime; Nwk_Obj_t * pNext; int i, iBox, iTerm1, nTerms, LevelMax = 0; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return; Nwk_ObjSetTravIdCurrent( pObj ); if ( Nwk_ObjIsCi(pObj) ) { if ( pManTime ) { iBox = Tim_ManBoxForCi( pManTime, pObj->PioId ); 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 = Nwk_ManCo(pObj->pMan, iTerm1 + i); Nwk_ManLevel_rec( pNext ); if ( LevelMax < Nwk_ObjLevel(pNext) ) LevelMax = Nwk_ObjLevel(pNext); } LevelMax++; } } } else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ) { Nwk_ObjForEachFanin( pObj, pNext, i ) { Nwk_ManLevel_rec( pNext ); if ( LevelMax < Nwk_ObjLevel(pNext) ) LevelMax = Nwk_ObjLevel(pNext); } if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0 ) LevelMax++; } else assert( 0 ); Nwk_ObjSetLevel( pObj, LevelMax ); } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [Does not assume that the objects are in a topo order.] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManLevel( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj; int i, LevelMax = 0; Nwk_ManForEachObj( pNtk, pObj, i ) Nwk_ObjSetLevel( pObj, 0 ); Nwk_ManIncrementTravId( pNtk ); Nwk_ManForEachPo( pNtk, pObj, i ) { Nwk_ManLevel_rec( pObj ); if ( LevelMax < Nwk_ObjLevel(pObj) ) LevelMax = Nwk_ObjLevel(pObj); } Nwk_ManForEachCi( pNtk, pObj, i ) { Nwk_ManLevel_rec( pObj ); if ( LevelMax < Nwk_ObjLevel(pObj) ) LevelMax = Nwk_ObjLevel(pObj); } return LevelMax; } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [Does not assume that the objects are in a topo order.] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManLevelMax( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj; int i, LevelMax = 0; Nwk_ManForEachPo( pNtk, pObj, i ) if ( LevelMax < Nwk_ObjLevel(pObj) ) LevelMax = Nwk_ObjLevel(pObj); return LevelMax; } /**Function************************************************************* Synopsis [Returns the array of objects in the AIG manager ordered by level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Nwk_ManLevelize( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj; Vec_Vec_t * vLevels; int nLevels, i; assert( Nwk_ManVerifyLevel(pNtk) ); nLevels = Nwk_ManLevelMax( pNtk ); vLevels = Vec_VecStart( nLevels + 1 ); Nwk_ManForEachNode( pNtk, pObj, i ) { assert( Nwk_ObjLevel(pObj) <= nLevels ); Vec_VecPush( vLevels, Nwk_ObjLevel(pObj), pObj ); } return vLevels; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDfs_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return; Nwk_ObjSetTravIdCurrent( pObj ); Nwk_ObjForEachFanin( pObj, pNext, i ) Nwk_ManDfs_rec( pNext, vNodes ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Returns the DFS ordered array of all objects except latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManDfs( Nwk_Man_t * pNtk ) { Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj; int i; Nwk_ManIncrementTravId( pNtk ); vNodes = Vec_PtrAlloc( 100 ); Nwk_ManForEachObj( pNtk, pObj, i ) { if ( Nwk_ObjIsCi(pObj) ) { Nwk_ObjSetTravIdCurrent( pObj ); Vec_PtrPush( vNodes, pObj ); } else if ( Nwk_ObjIsCo(pObj) ) Nwk_ManDfs_rec( pObj, vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDfsNodes_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return; Nwk_ObjSetTravIdCurrent( pObj ); if ( Nwk_ObjIsCi(pObj) ) return; assert( Nwk_ObjIsNode(pObj) ); Nwk_ObjForEachFanin( pObj, pNext, i ) Nwk_ManDfsNodes_rec( pNext, vNodes ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Returns the set of internal nodes rooted in the given nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManDfsNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ) { Vec_Ptr_t * vNodes; int i; // set the traversal ID Nwk_ManIncrementTravId( 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 ( Nwk_ObjIsCo(ppNodes[i]) ) Nwk_ManDfsNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes ); else Nwk_ManDfsNodes_rec( ppNodes[i], vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDfsReverse_rec( Nwk_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pNext; int i, iBox, iTerm1, nTerms; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return; Nwk_ObjSetTravIdCurrent( pObj ); if ( Nwk_ObjIsCo(pObj) ) { if ( pObj->pMan->pManTime ) { iBox = Tim_ManBoxForCo( pObj->pMan->pManTime, pObj->PioId ); if ( iBox >= 0 ) // this is not a true PO { iTerm1 = Tim_ManBoxOutputFirst( pObj->pMan->pManTime, iBox ); nTerms = Tim_ManBoxOutputNum( pObj->pMan->pManTime, iBox ); for ( i = 0; i < nTerms; i++ ) { pNext = Nwk_ManCi(pObj->pMan, iTerm1 + i); Nwk_ManDfsReverse_rec( pNext, vNodes ); } } } } else if ( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) ) { Nwk_ObjForEachFanout( pObj, pNext, i ) Nwk_ManDfsReverse_rec( pNext, vNodes ); } else assert( 0 ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Returns the DFS ordered array of all objects except latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManDfsReverse( Nwk_Man_t * pNtk ) { Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj; int i; Nwk_ManIncrementTravId( pNtk ); vNodes = Vec_PtrAlloc( 100 ); Nwk_ManForEachPi( pNtk, pObj, i ) Nwk_ManDfsReverse_rec( pObj, vNodes ); // add nodes without fanins Nwk_ManForEachNode( pNtk, pObj, i ) if ( Nwk_ObjFaninNum(pObj) == 0 && !Nwk_ObjIsTravIdCurrent(pObj) ) Vec_PtrPush( vNodes, pObj ); return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManSupportNodes_rec( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pFanin; int i; // if this node is already visited, skip if ( Nwk_ObjIsTravIdCurrent( pNode ) ) return; // mark the node as visited Nwk_ObjSetTravIdCurrent( pNode ); // collect the CI if ( Nwk_ObjIsCi(pNode) ) { Vec_PtrPush( vNodes, pNode ); return; } assert( Nwk_ObjIsNode( pNode ) ); // visit the transitive fanin of the node Nwk_ObjForEachFanin( pNode, pFanin, i ) Nwk_ManSupportNodes_rec( pFanin, vNodes ); } /**Function************************************************************* Synopsis [Returns the set of CI nodes in the support of the given nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManSupportNodes( Nwk_Man_t * pNtk, Nwk_Obj_t ** ppNodes, int nNodes ) { Vec_Ptr_t * vNodes; int i; // set the traversal ID Nwk_ManIncrementTravId( 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 ( Nwk_ObjIsCo(ppNodes[i]) ) Nwk_ManSupportNodes_rec( Nwk_ObjFanin0(ppNodes[i]), vNodes ); else Nwk_ManSupportNodes_rec( ppNodes[i], vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Computes the sum total of supports of all outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManSupportSum( Nwk_Man_t * pNtk ) { Vec_Ptr_t * vSupp; Nwk_Obj_t * pObj; int i, nTotalSupps = 0; Nwk_ManForEachCo( pNtk, pObj, i ) { vSupp = Nwk_ManSupportNodes( pNtk, &pObj, 1 ); nTotalSupps += Vec_PtrSize( vSupp ); Vec_PtrFree( vSupp ); } printf( "Total supports = %d.\n", nTotalSupps ); } /**Function************************************************************* Synopsis [Dereferences the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ObjDeref_rec( Nwk_Obj_t * pNode ) { Nwk_Obj_t * pFanin; int i, Counter = 1; if ( Nwk_ObjIsCi(pNode) ) return 0; Nwk_ObjForEachFanin( pNode, pFanin, i ) { assert( pFanin->nFanouts > 0 ); if ( --pFanin->nFanouts == 0 ) Counter += Nwk_ObjDeref_rec( pFanin ); } return Counter; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ObjRef_rec( Nwk_Obj_t * pNode ) { Nwk_Obj_t * pFanin; int i, Counter = 1; if ( Nwk_ObjIsCi(pNode) ) return 0; Nwk_ObjForEachFanin( pNode, pFanin, i ) { if ( pFanin->nFanouts++ == 0 ) Counter += Nwk_ObjRef_rec( pFanin ); } return Counter; } /**Function************************************************************* Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjMffcLabel_rec( Nwk_Obj_t * pNode, int fTopmost ) { Nwk_Obj_t * pFanin; int i; // add to the new support nodes if ( !fTopmost && (Nwk_ObjIsCi(pNode) || pNode->nFanouts > 0) ) return; // skip visited nodes if ( Nwk_ObjIsTravIdCurrent(pNode) ) return; Nwk_ObjSetTravIdCurrent(pNode); // recur on the children Nwk_ObjForEachFanin( pNode, pFanin, i ) Nwk_ObjMffcLabel_rec( pFanin, 0 ); // collect the internal node // printf( "%d ", pNode->Id ); } /**Function************************************************************* Synopsis [Collects the internal nodes of the MFFC limited by cut.] Description [] SideEffects [Increments the trav ID and marks visited nodes.] SeeAlso [] ***********************************************************************/ int Nwk_ObjMffcLabel( Nwk_Obj_t * pNode ) { int Count1, Count2; // dereference the node Count1 = Nwk_ObjDeref_rec( pNode ); // collect the nodes inside the MFFC Nwk_ManIncrementTravId( pNode->pMan ); Nwk_ObjMffcLabel_rec( pNode, 1 ); // reference it back Count2 = Nwk_ObjRef_rec( pNode ); assert( Count1 == Count2 ); return Count1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkFanio.c000066400000000000000000000231031300674244400233540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkFanio.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Manipulation of fanins/fanouts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects fanins of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pFanin; int i; Vec_PtrClear(vNodes); Nwk_ObjForEachFanin( pNode, pFanin, i ) Vec_PtrPush( vNodes, pFanin ); } /**Function************************************************************* Synopsis [Collects fanouts of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjCollectFanouts( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pFanout; int i; Vec_PtrClear(vNodes); Nwk_ObjForEachFanout( pNode, pFanout, i ) Vec_PtrPush( vNodes, pFanout ); } /**Function************************************************************* Synopsis [Returns the number of the fanin of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ObjFindFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) { Nwk_Obj_t * pTemp; int i; Nwk_ObjForEachFanin( pObj, pTemp, i ) if ( pTemp == pFanin ) return i; return -1; } /**Function************************************************************* Synopsis [Returns the number of the fanout of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ObjFindFanout( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanout ) { Nwk_Obj_t * pTemp; int i; Nwk_ObjForEachFanout( pObj, pTemp, i ) if ( pTemp == pFanout ) return i; return -1; } /**Function************************************************************* Synopsis [Returns 1 if the node has to be reallocated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Nwk_ObjReallocIsNeeded( Nwk_Obj_t * pObj ) { return pObj->nFanins + pObj->nFanouts == pObj->nFanioAlloc; } /**Function************************************************************* Synopsis [Reallocates the object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Nwk_Obj_t * Nwk_ManReallocNode( Nwk_Obj_t * pObj ) { Nwk_Obj_t ** pFanioOld = pObj->pFanio; assert( Nwk_ObjReallocIsNeeded(pObj) ); pObj->pFanio = (Nwk_Obj_t **)Aig_MmFlexEntryFetch( pObj->pMan->pMemObjs, 2 * pObj->nFanioAlloc * sizeof(Nwk_Obj_t *) ); memmove( pObj->pFanio, pFanioOld, pObj->nFanioAlloc * sizeof(Nwk_Obj_t *) ); pObj->nFanioAlloc *= 2; pObj->pMan->nRealloced++; return NULL; } /**Function************************************************************* Synopsis [Creates fanout/fanin relationship between the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjAddFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) { int i; assert( pObj->pMan == pFanin->pMan ); assert( pObj->Id >= 0 && pFanin->Id >= 0 ); if ( Nwk_ObjReallocIsNeeded(pObj) ) Nwk_ManReallocNode( pObj ); if ( Nwk_ObjReallocIsNeeded(pFanin) ) Nwk_ManReallocNode( pFanin ); for ( i = pObj->nFanins + pObj->nFanouts; i > pObj->nFanins; i-- ) pObj->pFanio[i] = pObj->pFanio[i-1]; pObj->pFanio[pObj->nFanins++] = pFanin; pFanin->pFanio[pFanin->nFanins + pFanin->nFanouts++] = pObj; pObj->Level = Abc_MaxInt( pObj->Level, pFanin->Level + Nwk_ObjIsNode(pObj) ); } /**Function************************************************************* Synopsis [Removes fanout/fanin relationship between the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjDeleteFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFanin ) { int i, k, Limit, fFound; // remove pFanin from the fanin list of pObj Limit = pObj->nFanins + pObj->nFanouts; fFound = 0; for ( k = i = 0; i < Limit; i++ ) if ( fFound || pObj->pFanio[i] != pFanin ) pObj->pFanio[k++] = pObj->pFanio[i]; else fFound = 1; assert( i == k + 1 ); // if it fails, likely because of duplicated fanin pObj->nFanins--; // remove pObj from the fanout list of pFanin Limit = pFanin->nFanins + pFanin->nFanouts; fFound = 0; for ( k = i = pFanin->nFanins; i < Limit; i++ ) if ( fFound || pFanin->pFanio[i] != pObj ) pFanin->pFanio[k++] = pFanin->pFanio[i]; else fFound = 1; assert( i == k + 1 ); // if it fails, likely because of duplicated fanout pFanin->nFanouts--; } /**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 Nwk_ObjPatchFanin( Nwk_Obj_t * pObj, Nwk_Obj_t * pFaninOld, Nwk_Obj_t * pFaninNew ) { int i, k, iFanin, Limit; assert( pFaninOld != pFaninNew ); assert( pObj != pFaninOld ); assert( pObj != pFaninNew ); assert( pObj->pMan == pFaninOld->pMan ); assert( pObj->pMan == pFaninNew->pMan ); // update the fanin iFanin = Nwk_ObjFindFanin( pObj, pFaninOld ); if ( iFanin == -1 ) { printf( "Nwk_ObjPatchFanin(); Error! Node %d is not among", pFaninOld->Id ); printf( " the fanins of node %d...\n", pObj->Id ); return; } pObj->pFanio[iFanin] = pFaninNew; // remove pObj from the fanout list of pFaninOld Limit = pFaninOld->nFanins + pFaninOld->nFanouts; for ( k = i = pFaninOld->nFanins; i < Limit; i++ ) if ( pFaninOld->pFanio[i] != pObj ) pFaninOld->pFanio[k++] = pFaninOld->pFanio[i]; pFaninOld->nFanouts--; // add pObj to the fanout list of pFaninNew if ( Nwk_ObjReallocIsNeeded(pFaninNew) ) Nwk_ManReallocNode( pFaninNew ); pFaninNew->pFanio[pFaninNew->nFanins + pFaninNew->nFanouts++] = pObj; } /**Function************************************************************* Synopsis [Transfers fanout from the old node to the new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjTransferFanout( Nwk_Obj_t * pNodeFrom, Nwk_Obj_t * pNodeTo ) { Vec_Ptr_t * vFanouts = pNodeFrom->pMan->vTemp; Nwk_Obj_t * pTemp; int nFanoutsOld, i; assert( !Nwk_ObjIsCo(pNodeFrom) && !Nwk_ObjIsCo(pNodeTo) ); assert( pNodeFrom->pMan == pNodeTo->pMan ); assert( pNodeFrom != pNodeTo ); assert( Nwk_ObjFanoutNum(pNodeFrom) > 0 ); // get the fanouts of the old node nFanoutsOld = Nwk_ObjFanoutNum(pNodeTo); Nwk_ObjCollectFanouts( pNodeFrom, vFanouts ); // patch the fanin of each of them Vec_PtrForEachEntry( Nwk_Obj_t *, vFanouts, pTemp, i ) Nwk_ObjPatchFanin( pTemp, pNodeFrom, pNodeTo ); assert( Nwk_ObjFanoutNum(pNodeFrom) == 0 ); assert( Nwk_ObjFanoutNum(pNodeTo) == nFanoutsOld + Vec_PtrSize(vFanouts) ); } /**Function************************************************************* Synopsis [Replaces the node by a new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjReplace( Nwk_Obj_t * pNodeOld, Nwk_Obj_t * pNodeNew ) { assert( pNodeOld->pMan == pNodeNew->pMan ); assert( pNodeOld != pNodeNew ); assert( Nwk_ObjFanoutNum(pNodeOld) > 0 ); // transfer the fanouts to the old node Nwk_ObjTransferFanout( pNodeOld, pNodeNew ); // remove the old node Nwk_ManDeleteNode_rec( pNodeOld ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkFlow.c000066400000000000000000000434221300674244400232350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkFlow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Netlist representation.] Synopsis [Max-flow/min-cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START /* This code is based on the papers: A. Hurst, A. Mishchenko, and R. Brayton, "Fast minimum-register retiming via binary maximum-flow", Proc. FMCAD '07, pp. 181-187. A. Hurst, A. Mishchenko, and R. Brayton, "Scalable min-area retiming under simultaneous delay and initial state constraints". Proc. DAC'08. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // predecessors static inline Nwk_Obj_t * Nwk_ObjPred( Nwk_Obj_t * pObj ) { return (Nwk_Obj_t *)pObj->pCopy; } static inline int Nwk_ObjSetPred( Nwk_Obj_t * pObj, Nwk_Obj_t * p ) { pObj->pCopy = p; return 1; } // sink static inline int Nwk_ObjIsSink( Nwk_Obj_t * pObj ) { return pObj->MarkA; } static inline void Nwk_ObjSetSink( Nwk_Obj_t * pObj ) { pObj->MarkA = 1; } // flow static inline int Nwk_ObjHasFlow( Nwk_Obj_t * pObj ) { return pObj->MarkB; } static inline void Nwk_ObjSetFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 1; } static inline void Nwk_ObjClearFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 0; } // representation of visited nodes // pObj->TravId < pNtk->nTravIds-2 --- not visited // pObj->TravId == pNtk->nTravIds-2 --- visited bot only // pObj->TravId == pNtk->nTravIds-1 --- visited top only // pObj->TravId == pNtk->nTravIds --- visited bot and top static inline int Nwk_ObjVisitedBotOnly( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 2; } static inline int Nwk_ObjVisitedBot( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 2 || pObj->TravId == pObj->pMan->nTravIds; } static inline int Nwk_ObjVisitedTop( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 1 || pObj->TravId == pObj->pMan->nTravIds; } static inline void Nwk_ObjSetVisitedBot( Nwk_Obj_t * pObj ) { if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) pObj->TravId = pObj->pMan->nTravIds - 2; else if ( pObj->TravId == pObj->pMan->nTravIds - 1 ) pObj->TravId = pObj->pMan->nTravIds; else assert( 0 ); } static inline void Nwk_ObjSetVisitedTop( Nwk_Obj_t * pObj ) { if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) pObj->TravId = pObj->pMan->nTravIds - 1; else if ( pObj->TravId == pObj->pMan->nTravIds - 2 ) pObj->TravId = pObj->pMan->nTravIds; else assert( 0 ); } static inline void Nwk_ManIncrementTravIdFlow( Nwk_Man_t * pMan ) { Nwk_ManIncrementTravId( pMan ); Nwk_ManIncrementTravId( pMan ); Nwk_ManIncrementTravId( pMan ); } static int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); static int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); static int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); static int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Marks TFI of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMarkTfiCone_rec( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; if ( pObj->MarkA ) return; pObj->MarkA = 1; Nwk_ObjForEachFanin( pObj, pNext, i ) Nwk_ManMarkTfiCone_rec( pNext ); } /**Function************************************************************* Synopsis [Marks TFO of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMarkTfoCone_rec( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; if ( pObj->MarkA ) return; pObj->MarkA = 1; Nwk_ObjForEachFanout( pObj, pNext, i ) Nwk_ManMarkTfoCone_rec( pNext ); } /**Function************************************************************* Synopsis [Fast forward flow pushing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushForwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return 0; Nwk_ObjSetTravIdCurrent( pObj ); if ( Nwk_ObjHasFlow(pObj) ) return 0; if ( Nwk_ObjIsSink(pObj) ) { Nwk_ObjSetFlow(pObj); return Nwk_ObjSetPred( pObj, pPred ); } Nwk_ObjForEachFanout( pObj, pNext, i ) if ( Nwk_ManPushForwardFast_rec( pNext, pObj ) ) { Nwk_ObjSetFlow(pObj); return Nwk_ObjSetPred( pObj, pPred ); } return 0; } /**Function************************************************************* Synopsis [Fast backward flow pushing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushBackwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return 0; Nwk_ObjSetTravIdCurrent( pObj ); if ( Nwk_ObjHasFlow(pObj) ) return 0; if ( Nwk_ObjIsSink(pObj) ) { Nwk_ObjSetFlow(pObj); return Nwk_ObjSetPred( pObj, pPred ); } Nwk_ObjForEachFanin( pObj, pNext, i ) if ( Nwk_ManPushBackwardFast_rec( pNext, pObj ) ) { Nwk_ObjSetFlow(pObj); return Nwk_ObjSetPred( pObj, pPred ); } return 0; } /**Function************************************************************* Synopsis [Pushing the flow through the bottom part of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjVisitedBot(pObj) ) return 0; Nwk_ObjSetVisitedBot(pObj); // propagate through the internal edge if ( Nwk_ObjHasFlow(pObj) ) { if ( Nwk_ObjPred(pObj) ) if ( Nwk_ManPushForwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) return Nwk_ObjSetPred( pObj, pPred ); } else if ( Nwk_ManPushForwardTop_rec(pObj, pObj) ) { Nwk_ObjSetFlow( pObj ); return Nwk_ObjSetPred( pObj, pPred ); } // try to push through the fanins Nwk_ObjForEachFanin( pObj, pNext, i ) if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Pushing the flow through the top part of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjVisitedTop(pObj) ) return 0; Nwk_ObjSetVisitedTop(pObj); // check if this is the sink if ( Nwk_ObjIsSink(pObj) ) return 1; // try to push through the fanouts Nwk_ObjForEachFanout( pObj, pNext, i ) if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) return 1; // redirect the flow if ( Nwk_ObjHasFlow(pObj) && !Nwk_ObjIsCi(pObj) ) if ( Nwk_ManPushForwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) { Nwk_ObjClearFlow( pObj ); return Nwk_ObjSetPred( pObj, NULL ); } return 0; } /**Function************************************************************* Synopsis [Pushing the flow through the bottom part of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { if ( Nwk_ObjVisitedBot(pObj) ) return 0; Nwk_ObjSetVisitedBot(pObj); // propagate through the internal edge if ( Nwk_ObjHasFlow(pObj) ) { if ( Nwk_ObjPred(pObj) ) if ( Nwk_ManPushBackwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) return Nwk_ObjSetPred( pObj, pPred ); } else if ( Nwk_ManPushBackwardTop_rec(pObj, pObj) ) { Nwk_ObjSetFlow( pObj ); return Nwk_ObjSetPred( pObj, pPred ); } return 0; } /**Function************************************************************* Synopsis [Pushing the flow through the top part of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjVisitedTop(pObj) ) return 0; Nwk_ObjSetVisitedTop(pObj); // check if this is the sink if ( Nwk_ObjIsSink(pObj) ) return 1; // try to push through the fanins Nwk_ObjForEachFanin( pObj, pNext, i ) if ( Nwk_ManPushBackwardBot_rec( pNext, pPred ) ) return 1; // try to push through the fanouts Nwk_ObjForEachFanout( pObj, pNext, i ) if ( !Nwk_ObjIsCo(pObj) && Nwk_ManPushBackwardTop_rec( pNext, pPred ) ) return 1; // redirect the flow if ( Nwk_ObjHasFlow(pObj) ) if ( Nwk_ObjPred(pObj) && Nwk_ManPushBackwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) { Nwk_ObjClearFlow( pObj ); return Nwk_ObjSetPred( pObj, NULL ); } return 0; } /**Function************************************************************* Synopsis [Returns 0 if there is an unmarked path to a CI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManVerifyCut_rec( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; if ( pObj->MarkA ) return 1; if ( Nwk_ObjIsLo(pObj) ) return 0; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return 1; Nwk_ObjSetTravIdCurrent( pObj ); Nwk_ObjForEachFanin( pObj, pNext, i ) if ( !Nwk_ManVerifyCut_rec( pNext ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Verifies the forward cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManRetimeVerifyCutForward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pObj; int i; // mark the nodes Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) { assert( pObj->MarkA == 0 ); pObj->MarkA = 1; } // traverse from the COs Nwk_ManIncrementTravId( pMan ); Nwk_ManForEachCo( pMan, pObj, i ) if ( !Nwk_ManVerifyCut_rec( pObj ) ) printf( "Nwk_ManRetimeVerifyCutForward(): Internal cut verification failed.\n" ); // unmark the nodes Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) pObj->MarkA = 0; return 1; } /**Function************************************************************* Synopsis [Verifies the forward cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManRetimeVerifyCutBackward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) { return 1; } /**Function************************************************************* Synopsis [Computes minimum cut for forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) { Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj; int i, RetValue, Counter = 0, Counter2 = 0; abctime clk = Abc_Clock(); // set the sequential parameters pMan->nLatches = nLatches; pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; // mark the COs and the TFO of PIs Nwk_ManForEachCo( pMan, pObj, i ) pObj->MarkA = 1; Nwk_ManForEachPiSeq( pMan, pObj, i ) Nwk_ManMarkTfoCone_rec( pObj ); // start flow computation from each LO Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLoSeq( pMan, pObj, i ) { if ( !Nwk_ManPushForwardFast_rec( pObj, NULL ) ) continue; Nwk_ManIncrementTravIdFlow( pMan ); Counter++; } if ( fVerbose ) printf( "Forward: Max-flow = %4d -> ", Counter ); // continue flow computation from each LO Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLoSeq( pMan, pObj, i ) { if ( !Nwk_ManPushForwardBot_rec( pObj, NULL ) ) continue; Nwk_ManIncrementTravIdFlow( pMan ); Counter2++; } if ( fVerbose ) printf( "%4d. ", Counter+Counter2 ); // repeat flow computation from each LO if ( Counter2 > 0 ) { Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLoSeq( pMan, pObj, i ) { RetValue = Nwk_ManPushForwardBot_rec( pObj, NULL ); assert( !RetValue ); } } // cut is a set of nodes whose bottom is visited but top is not visited vNodes = Vec_PtrAlloc( Counter+Counter2 ); Counter = 0; Nwk_ManForEachObj( pMan, pObj, i ) { if ( Nwk_ObjVisitedBotOnly(pObj) ) { assert( Nwk_ObjHasFlow(pObj) ); assert( !Nwk_ObjIsCo(pObj) ); Vec_PtrPush( vNodes, pObj ); Counter += Nwk_ObjIsCi(pObj); } } Nwk_ManCleanMarks( pMan ); // assert( Nwk_ManRetimeVerifyCutForward(pMan, vNodes) ); if ( fVerbose ) { printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); ABC_PRT( "Time", Abc_Clock() - clk ); } return vNodes; } /**Function************************************************************* Synopsis [Computes minimum cut for backward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) { Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj; int i, RetValue, Counter = 0, Counter2 = 0; abctime clk = Abc_Clock(); // set the sequential parameters pMan->nLatches = nLatches; pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; // mark the CIs, the TFI of POs, and the constant nodes Nwk_ManForEachCi( pMan, pObj, i ) pObj->MarkA = 1; Nwk_ManForEachPoSeq( pMan, pObj, i ) Nwk_ManMarkTfiCone_rec( pObj ); Nwk_ManForEachNode( pMan, pObj, i ) if ( Nwk_ObjFaninNum(pObj) == 0 ) pObj->MarkA = 1; // start flow computation from each LI driver Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLiSeq( pMan, pObj, i ) { if ( !Nwk_ManPushBackwardFast_rec( Nwk_ObjFanin0(pObj), NULL ) ) continue; Nwk_ManIncrementTravIdFlow( pMan ); Counter++; } if ( fVerbose ) printf( "Backward: Max-flow = %4d -> ", Counter ); // continue flow computation from each LI driver Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLiSeq( pMan, pObj, i ) { if ( !Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ) ) continue; Nwk_ManIncrementTravIdFlow( pMan ); Counter2++; } if ( fVerbose ) printf( "%4d. ", Counter+Counter2 ); // repeat flow computation from each LI driver if ( Counter2 > 0 ) { Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLiSeq( pMan, pObj, i ) { RetValue = Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ); assert( !RetValue ); } } // cut is a set of nodes whose bottom is visited but top is not visited vNodes = Vec_PtrAlloc( Counter+Counter2 ); Nwk_ManForEachObj( pMan, pObj, i ) { if ( Nwk_ObjVisitedBotOnly(pObj) ) { assert( Nwk_ObjHasFlow(pObj) ); assert( !Nwk_ObjIsCo(pObj) ); Vec_PtrPush( vNodes, pObj ); } } // count CO drivers Counter = 0; Nwk_ManForEachLiSeq( pMan, pObj, i ) if ( Nwk_ObjVisitedBotOnly( Nwk_ObjFanin0(pObj) ) ) Counter++; Nwk_ManCleanMarks( pMan ); // assert( Nwk_ManRetimeVerifyCutBackward(pMan, vNodes) ); if ( fVerbose ) { printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); ABC_PRT( "Time", Abc_Clock() - clk ); } return vNodes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkFlow_depth.c000066400000000000000000000444501300674244400244230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkFlow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Netlist representation.] Synopsis [Max-flow/min-cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START /* This code is based on the papers: A. Hurst, A. Mishchenko, and R. Brayton, "Fast minimum-register retiming via binary maximum-flow", Proc. FMCAD '07, pp. 181-187. A. Hurst, A. Mishchenko, and R. Brayton, "Scalable min-area retiming under simultaneous delay and initial state constraints". Proc. DAC'08. */ int DepthFwd, DepthBwd, DepthFwdMax, DepthBwdMax; //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // predecessors static inline Nwk_Obj_t * Nwk_ObjPred( Nwk_Obj_t * pObj ) { return pObj->pCopy; } static inline int Nwk_ObjSetPred( Nwk_Obj_t * pObj, Nwk_Obj_t * p ) { pObj->pCopy = p; return 1; } // sink static inline int Nwk_ObjIsSink( Nwk_Obj_t * pObj ) { return pObj->MarkA; } static inline void Nwk_ObjSetSink( Nwk_Obj_t * pObj ) { pObj->MarkA = 1; } // flow static inline int Nwk_ObjHasFlow( Nwk_Obj_t * pObj ) { return pObj->MarkB; } static inline void Nwk_ObjSetFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 1; } static inline void Nwk_ObjClearFlow( Nwk_Obj_t * pObj ) { pObj->MarkB = 0; } // representation of visited nodes // pObj->TravId < pNtk->nTravIds-2 --- not visited // pObj->TravId == pNtk->nTravIds-2 --- visited bot only // pObj->TravId == pNtk->nTravIds-1 --- visited top only // pObj->TravId == pNtk->nTravIds --- visited bot and top static inline int Nwk_ObjVisitedBotOnly( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 2; } static inline int Nwk_ObjVisitedBot( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 2 || pObj->TravId == pObj->pMan->nTravIds; } static inline int Nwk_ObjVisitedTop( Nwk_Obj_t * pObj ) { return pObj->TravId == pObj->pMan->nTravIds - 1 || pObj->TravId == pObj->pMan->nTravIds; } static inline void Nwk_ObjSetVisitedBot( Nwk_Obj_t * pObj ) { if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) pObj->TravId = pObj->pMan->nTravIds - 2; else if ( pObj->TravId == pObj->pMan->nTravIds - 1 ) pObj->TravId = pObj->pMan->nTravIds; else assert( 0 ); } static inline void Nwk_ObjSetVisitedTop( Nwk_Obj_t * pObj ) { if ( pObj->TravId < pObj->pMan->nTravIds - 2 ) pObj->TravId = pObj->pMan->nTravIds - 1; else if ( pObj->TravId == pObj->pMan->nTravIds - 2 ) pObj->TravId = pObj->pMan->nTravIds; else assert( 0 ); } static inline Nwk_ManIncrementTravIdFlow( Nwk_Man_t * pMan ) { Nwk_ManIncrementTravId( pMan ); Nwk_ManIncrementTravId( pMan ); Nwk_ManIncrementTravId( pMan ); } static int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); static int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); static int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); static int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Marks TFI of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMarkTfiCone_rec( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; if ( pObj->MarkA ) return; pObj->MarkA = 1; Nwk_ObjForEachFanin( pObj, pNext, i ) Nwk_ManMarkTfiCone_rec( pNext ); } /**Function************************************************************* Synopsis [Marks TFO of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMarkTfoCone_rec( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; if ( pObj->MarkA ) return; pObj->MarkA = 1; Nwk_ObjForEachFanout( pObj, pNext, i ) Nwk_ManMarkTfoCone_rec( pNext ); } /**Function************************************************************* Synopsis [Fast forward flow pushing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushForwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return 0; Nwk_ObjSetTravIdCurrent( pObj ); if ( Nwk_ObjHasFlow(pObj) ) return 0; if ( Nwk_ObjIsSink(pObj) ) { Nwk_ObjSetFlow(pObj); return Nwk_ObjSetPred( pObj, pPred ); } Nwk_ObjForEachFanout( pObj, pNext, i ) if ( Nwk_ManPushForwardFast_rec( pNext, pObj ) ) { Nwk_ObjSetFlow(pObj); return Nwk_ObjSetPred( pObj, pPred ); } return 0; } /**Function************************************************************* Synopsis [Fast backward flow pushing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushBackwardFast_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return 0; Nwk_ObjSetTravIdCurrent( pObj ); if ( Nwk_ObjHasFlow(pObj) ) return 0; if ( Nwk_ObjIsSink(pObj) ) { Nwk_ObjSetFlow(pObj); return Nwk_ObjSetPred( pObj, pPred ); } Nwk_ObjForEachFanin( pObj, pNext, i ) if ( Nwk_ManPushBackwardFast_rec( pNext, pObj ) ) { Nwk_ObjSetFlow(pObj); return Nwk_ObjSetPred( pObj, pPred ); } return 0; } /**Function************************************************************* Synopsis [Pushing the flow through the bottom part of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushForwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjVisitedBot(pObj) ) return 0; Nwk_ObjSetVisitedBot(pObj); DepthFwd++; if ( DepthFwdMax < DepthFwd ) DepthFwdMax = DepthFwd; // propagate through the internal edge if ( Nwk_ObjHasFlow(pObj) ) { if ( Nwk_ObjPred(pObj) ) if ( Nwk_ManPushForwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) { DepthFwd--; return Nwk_ObjSetPred( pObj, pPred ); } } else if ( Nwk_ManPushForwardTop_rec(pObj, pObj) ) { DepthFwd--; Nwk_ObjSetFlow( pObj ); return Nwk_ObjSetPred( pObj, pPred ); } // try to push through the fanins Nwk_ObjForEachFanin( pObj, pNext, i ) if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) { DepthFwd--; return 1; } DepthFwd--; return 0; } /**Function************************************************************* Synopsis [Pushing the flow through the top part of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushForwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjVisitedTop(pObj) ) return 0; Nwk_ObjSetVisitedTop(pObj); // check if this is the sink if ( Nwk_ObjIsSink(pObj) ) return 1; DepthFwd++; if ( DepthFwdMax < DepthFwd ) DepthFwdMax = DepthFwd; // try to push through the fanouts Nwk_ObjForEachFanout( pObj, pNext, i ) if ( Nwk_ManPushForwardBot_rec( pNext, pPred ) ) { DepthFwd--; return 1; } // redirect the flow if ( Nwk_ObjHasFlow(pObj) && !Nwk_ObjIsCi(pObj) ) if ( Nwk_ManPushForwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) { DepthFwd--; Nwk_ObjClearFlow( pObj ); return Nwk_ObjSetPred( pObj, NULL ); } DepthFwd--; return 0; } /**Function************************************************************* Synopsis [Pushing the flow through the bottom part of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushBackwardBot_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { if ( Nwk_ObjVisitedBot(pObj) ) return 0; Nwk_ObjSetVisitedBot(pObj); // propagate through the internal edge if ( Nwk_ObjHasFlow(pObj) ) { if ( Nwk_ObjPred(pObj) ) if ( Nwk_ManPushBackwardTop_rec( Nwk_ObjPred(pObj), Nwk_ObjPred(pObj) ) ) return Nwk_ObjSetPred( pObj, pPred ); } else if ( Nwk_ManPushBackwardTop_rec(pObj, pObj) ) { Nwk_ObjSetFlow( pObj ); return Nwk_ObjSetPred( pObj, pPred ); } return 0; } /**Function************************************************************* Synopsis [Pushing the flow through the top part of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPushBackwardTop_rec( Nwk_Obj_t * pObj, Nwk_Obj_t * pPred ) { Nwk_Obj_t * pNext; int i; if ( Nwk_ObjVisitedTop(pObj) ) return 0; Nwk_ObjSetVisitedTop(pObj); // check if this is the sink if ( Nwk_ObjIsSink(pObj) ) return 1; // try to push through the fanins Nwk_ObjForEachFanin( pObj, pNext, i ) if ( Nwk_ManPushBackwardBot_rec( pNext, pPred ) ) return 1; // try to push through the fanouts Nwk_ObjForEachFanout( pObj, pNext, i ) if ( !Nwk_ObjIsCo(pObj) && Nwk_ManPushBackwardTop_rec( pNext, pPred ) ) return 1; // redirect the flow if ( Nwk_ObjHasFlow(pObj) ) if ( Nwk_ObjPred(pObj) && Nwk_ManPushBackwardBot_rec( pObj, Nwk_ObjPred(pObj) ) ) { Nwk_ObjClearFlow( pObj ); return Nwk_ObjSetPred( pObj, NULL ); } return 0; } /**Function************************************************************* Synopsis [Returns 0 if there is an unmarked path to a CI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManVerifyCut_rec( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; if ( pObj->MarkA ) return 1; if ( Nwk_ObjIsLo(pObj) ) return 0; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) return 1; Nwk_ObjSetTravIdCurrent( pObj ); Nwk_ObjForEachFanin( pObj, pNext, i ) if ( !Nwk_ManVerifyCut_rec( pNext ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Verifies the forward cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManRetimeVerifyCutForward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pObj; int i; // mark the nodes Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) { assert( pObj->MarkA == 0 ); pObj->MarkA = 1; } // traverse from the COs Nwk_ManIncrementTravId( pMan ); Nwk_ManForEachCo( pMan, pObj, i ) if ( !Nwk_ManVerifyCut_rec( pObj ) ) printf( "Nwk_ManRetimeVerifyCutForward(): Internal cut verification failed.\n" ); // unmark the nodes Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) pObj->MarkA = 0; return 1; } /**Function************************************************************* Synopsis [Verifies the forward cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManRetimeVerifyCutBackward( Nwk_Man_t * pMan, Vec_Ptr_t * vNodes ) { return 1; } /**Function************************************************************* Synopsis [Computes minimum cut for forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManRetimeCutForward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) { Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj; int i, RetValue, Counter = 0, Counter2 = 0; clock_t clk = clock(); // set the sequential parameters pMan->nLatches = nLatches; pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; // mark the COs and the TFO of PIs Nwk_ManForEachCo( pMan, pObj, i ) pObj->MarkA = 1; Nwk_ManForEachPiSeq( pMan, pObj, i ) Nwk_ManMarkTfoCone_rec( pObj ); // start flow computation from each LO Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLoSeq( pMan, pObj, i ) { if ( !Nwk_ManPushForwardFast_rec( pObj, NULL ) ) continue; Nwk_ManIncrementTravIdFlow( pMan ); Counter++; } if ( fVerbose ) printf( "Forward: Max-flow = %4d -> ", Counter ); // continue flow computation from each LO DepthFwdMax = DepthFwd = 0; Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLoSeq( pMan, pObj, i ) { printf( "%d ", DepthFwdMax ); if ( !Nwk_ManPushForwardBot_rec( pObj, NULL ) ) continue; assert( DepthFwd == 0 ); Nwk_ManIncrementTravIdFlow( pMan ); Counter2++; } printf( "DepthMax = %d.\n", DepthFwdMax ); if ( fVerbose ) printf( "%4d. ", Counter+Counter2 ); // repeat flow computation from each LO if ( Counter2 > 0 ) { Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLoSeq( pMan, pObj, i ) { RetValue = Nwk_ManPushForwardBot_rec( pObj, NULL ); assert( !RetValue ); } } // cut is a set of nodes whose bottom is visited but top is not visited vNodes = Vec_PtrAlloc( Counter+Counter2 ); Counter = 0; Nwk_ManForEachObj( pMan, pObj, i ) { if ( Nwk_ObjVisitedBotOnly(pObj) ) { assert( Nwk_ObjHasFlow(pObj) ); assert( !Nwk_ObjIsCo(pObj) ); Vec_PtrPush( vNodes, pObj ); Counter += Nwk_ObjIsCi(pObj); } } Nwk_ManCleanMarks( pMan ); assert( Nwk_ManRetimeVerifyCutForward(pMan, vNodes) ); if ( fVerbose ) { printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); PRT( "Time", clock() - clk ); } return vNodes; } /**Function************************************************************* Synopsis [Computes minimum cut for backward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Nwk_ManRetimeCutBackward( Nwk_Man_t * pMan, int nLatches, int fVerbose ) { Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj; int i, RetValue, Counter = 0, Counter2 = 0; clock_t clk = clock(); // set the sequential parameters pMan->nLatches = nLatches; pMan->nTruePis = Nwk_ManCiNum(pMan) - nLatches; pMan->nTruePos = Nwk_ManCoNum(pMan) - nLatches; // mark the CIs, the TFI of POs, and the constant nodes Nwk_ManForEachCi( pMan, pObj, i ) pObj->MarkA = 1; Nwk_ManForEachPoSeq( pMan, pObj, i ) Nwk_ManMarkTfiCone_rec( pObj ); Nwk_ManForEachNode( pMan, pObj, i ) if ( Nwk_ObjFaninNum(pObj) == 0 ) pObj->MarkA = 1; // start flow computation from each LI driver Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLiSeq( pMan, pObj, i ) { if ( !Nwk_ManPushBackwardFast_rec( Nwk_ObjFanin0(pObj), NULL ) ) continue; Nwk_ManIncrementTravIdFlow( pMan ); Counter++; } if ( fVerbose ) printf( "Backward: Max-flow = %4d -> ", Counter ); // continue flow computation from each LI driver Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLiSeq( pMan, pObj, i ) { if ( !Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ) ) continue; Nwk_ManIncrementTravIdFlow( pMan ); Counter2++; } if ( fVerbose ) printf( "%4d. ", Counter+Counter2 ); // repeat flow computation from each LI driver if ( Counter2 > 0 ) { Nwk_ManIncrementTravIdFlow( pMan ); Nwk_ManForEachLiSeq( pMan, pObj, i ) { RetValue = Nwk_ManPushBackwardBot_rec( Nwk_ObjFanin0(pObj), NULL ); assert( !RetValue ); } } // cut is a set of nodes whose bottom is visited but top is not visited vNodes = Vec_PtrAlloc( Counter+Counter2 ); Nwk_ManForEachObj( pMan, pObj, i ) { if ( Nwk_ObjVisitedBotOnly(pObj) ) { assert( Nwk_ObjHasFlow(pObj) ); assert( !Nwk_ObjIsCo(pObj) ); Vec_PtrPush( vNodes, pObj ); } } // count CO drivers Counter = 0; Nwk_ManForEachLiSeq( pMan, pObj, i ) if ( Nwk_ObjVisitedBotOnly( Nwk_ObjFanin0(pObj) ) ) Counter++; Nwk_ManCleanMarks( pMan ); assert( Nwk_ManRetimeVerifyCutBackward(pMan, vNodes) ); if ( fVerbose ) { printf( "Min-cut = %4d. Unmoved = %4d. ", Vec_PtrSize(vNodes), Counter ); PRT( "Time", clock() - clk ); } return vNodes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkMan.c000066400000000000000000000216631300674244400230440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Network manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkMan.c,v 1.1 2008/10/10 14:09:30 mjarvin Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Man_t * Nwk_ManAlloc() { Nwk_Man_t * p; p = ABC_ALLOC( Nwk_Man_t, 1 ); memset( p, 0, sizeof(Nwk_Man_t) ); p->vCis = Vec_PtrAlloc( 1000 ); p->vCos = Vec_PtrAlloc( 1000 ); p->vObjs = Vec_PtrAlloc( 1000 ); p->vTemp = Vec_PtrAlloc( 1000 ); p->nFanioPlus = 2; p->pMemObjs = Aig_MmFlexStart(); p->pManHop = Hop_ManStart(); return p; } /**Function************************************************************* Synopsis [Deallocates the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManFree( Nwk_Man_t * p ) { // printf( "The number of realloced nodes = %d.\n", p->nRealloced ); if ( p->pName ) ABC_FREE( p->pName ); if ( p->pSpec ) ABC_FREE( p->pSpec ); if ( p->vCis ) Vec_PtrFree( p->vCis ); if ( p->vCos ) Vec_PtrFree( p->vCos ); if ( p->vObjs ) Vec_PtrFree( p->vObjs ); if ( p->vTemp ) Vec_PtrFree( p->vTemp ); if ( p->pManTime ) Tim_ManStop( p->pManTime ); if ( p->pMemObjs ) Aig_MmFlexStop( p->pMemObjs, 0 ); if ( p->pManHop ) Hop_ManStop( p->pManHop ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints stats of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManPrintLutSizes( Nwk_Man_t * p, If_LibLut_t * pLutLib ) { Nwk_Obj_t * pObj; int i, Counters[256] = {0}; Nwk_ManForEachNode( p, pObj, i ) Counters[Nwk_ObjFaninNum(pObj)]++; printf( "LUTs by size: " ); for ( i = 0; i <= pLutLib->LutMax; i++ ) printf( "%d:%d ", i, Counters[i] ); } /**Function************************************************************* Synopsis [If the network is best, saves it in "best.blif" and returns 1.] Description [If the networks are incomparable, saves the new network, returns its parameters in the internal parameter structure, and returns 1. If the new network is not a logic network, quits without saving and returns 0.] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManCompareAndSaveBest( Nwk_Man_t * pNtk, void * pNtl ) { // extern void Ntl_WriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName ); extern void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ); static struct ParStruct { char * pName; // name of the best saved network int Depth; // depth of the best saved network int Flops; // flops in the best saved network int Nodes; // nodes in the best saved network int nPis; // the number of primary inputs int nPos; // the number of primary outputs } ParsNew, ParsBest = { 0 }; // free storage for the name if ( pNtk == NULL ) { ABC_FREE( ParsBest.pName ); return 0; } // get the parameters ParsNew.Depth = Nwk_ManLevel( pNtk ); ParsNew.Flops = Nwk_ManLatchNum( pNtk ); ParsNew.Nodes = Nwk_ManNodeNum( pNtk ); ParsNew.nPis = Nwk_ManPiNum( pNtk ); ParsNew.nPos = Nwk_ManPoNum( pNtk ); // reset the parameters if the network has the same name if ( ParsBest.pName == NULL || strcmp(ParsBest.pName, pNtk->pName) || ParsBest.Depth > ParsNew.Depth || (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops > ParsNew.Flops) || (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops == ParsNew.Flops && ParsBest.Nodes > ParsNew.Nodes) ) { ABC_FREE( ParsBest.pName ); ParsBest.pName = Abc_UtilStrsav( pNtk->pName ); ParsBest.Depth = ParsNew.Depth; ParsBest.Flops = ParsNew.Flops; ParsBest.Nodes = ParsNew.Nodes; ParsBest.nPis = ParsNew.nPis; ParsBest.nPos = ParsNew.nPos; // write the network // Ntl_WriteBlifLogic( pNtk, pNtl, "best.blif" ); // Nwk_ManDumpBlif( pNtk, "best_map.blif", NULL, NULL ); return 1; } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Nwk_FileNameGeneric( char * FileName ) { char * pDot, * pRes; pRes = Abc_UtilStrsav( FileName ); if ( (pDot = strrchr( pRes, '.' )) ) *pDot = 0; return pRes; } /**Function************************************************************* Synopsis [Marks nodes for power-optimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Nwl_ManComputeTotalSwitching( Nwk_Man_t * pNtk ) { extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Vec_Int_t * vSwitching; float * pSwitching; Aig_Man_t * pAig; Aig_Obj_t * pObjAig; Nwk_Obj_t * pObjAbc; float Result = (float)0; int i; // strash the network // map network into an AIG pAig = Nwk_ManStrash( pNtk ); vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 ); pSwitching = (float *)vSwitching->pArray; Nwk_ManForEachObj( pNtk, pObjAbc, i ) { if ( (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc->pCopy)) ) Result += Nwk_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id]; } Vec_IntFree( vSwitching ); Aig_ManStop( pAig ); return Result; } /**Function************************************************************* Synopsis [Prints stats of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManPrintStats( Nwk_Man_t * pNtk, If_LibLut_t * pLutLib, int fSaveBest, int fDumpResult, int fPower, Ntl_Man_t * pNtl ) { // extern int Ntl_ManLatchNum( Ntl_Man_t * p ); // extern void Ntl_ManWriteBlifLogic( Nwk_Man_t * pNtk, void * pNtl, char * pFileName ); if ( fSaveBest ) Nwk_ManCompareAndSaveBest( pNtk, pNtl ); if ( fDumpResult ) { char Buffer[1000] = {0}; const char * pNameGen = pNtk->pSpec? Nwk_FileNameGeneric( pNtk->pSpec ) : "nameless_"; sprintf( Buffer, "%s_dump.blif", pNameGen ); // Ntl_ManWriteBlifLogic( pNtk, pNtl, Buffer ); // sprintf( Buffer, "%s_dump_map.blif", pNameGen ); // Nwk_ManDumpBlif( pNtk, Buffer, NULL, NULL ); if ( pNtk->pSpec ) ABC_FREE( pNameGen ); } pNtk->pLutLib = pLutLib; printf( "%-15s : ", pNtk->pName ); printf( "pi = %5d ", Nwk_ManPiNum(pNtk) ); printf( "po = %5d ", Nwk_ManPoNum(pNtk) ); printf( "ci = %5d ", Nwk_ManCiNum(pNtk) ); printf( "co = %5d ", Nwk_ManCoNum(pNtk) ); // printf( "lat = %5d ", Ntl_ManLatchNum(pNtl) ); printf( "node = %5d ", Nwk_ManNodeNum(pNtk) ); printf( "edge = %5d ", Nwk_ManGetTotalFanins(pNtk) ); printf( "aig = %6d ", Nwk_ManGetAigNodeNum(pNtk) ); printf( "lev = %3d ", Nwk_ManLevel(pNtk) ); // printf( "lev2 = %3d ", Nwk_ManLevelBackup(pNtk) ); printf( "delay = %5.2f ", Nwk_ManDelayTraceLut(pNtk) ); if ( fPower ) printf( "power = %7.2f ", Nwl_ManComputeTotalSwitching(pNtk) ); Nwk_ManPrintLutSizes( pNtk, pLutLib ); printf( "\n" ); // Nwk_ManDelayTracePrint( pNtk, pLutLib ); fflush( stdout ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkMap.c000066400000000000000000000317621300674244400230470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkMap.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Interface to technology mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Load the network into FPGA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManSetIfParsDefault( If_Par_t * pPars ) { // extern void * Abc_FrameReadLibLut(); // set defaults memset( pPars, 0, sizeof(If_Par_t) ); // user-controlable paramters // pPars->nLutSize = -1; pPars->nLutSize = 6; pPars->nCutsMax = 8; pPars->nFlowIters = 1; pPars->nAreaIters = 2; pPars->DelayTarget = -1; pPars->Epsilon = (float)0.005; pPars->fPreprocess = 1; pPars->fArea = 0; pPars->fFancy = 0; pPars->fExpRed = 1; //// pPars->fLatchPaths = 0; pPars->fEdge = 1; pPars->fPower = 0; pPars->fCutMin = 0; pPars->fVerbose = 0; // internal parameters pPars->fTruth = 0; pPars->nLatchesCi = 0; pPars->nLatchesCo = 0; pPars->fLiftLeaves = 0; // pPars->pLutLib = Abc_FrameReadLibLut(); pPars->pLutLib = NULL; pPars->pTimesArr = NULL; pPars->pTimesArr = NULL; pPars->pFuncCost = NULL; /* if ( pPars->nLutSize == -1 ) { if ( pPars->pLutLib == NULL ) { printf( "The LUT library is not given.\n" ); return; } // get LUT size from the library pPars->nLutSize = pPars->pLutLib->LutMax; } */ } /**Function************************************************************* Synopsis [Load the network into FPGA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Man_t * Nwk_ManToIf( Aig_Man_t * p, If_Par_t * pPars, Vec_Ptr_t * vAigToIf ) { extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); Vec_Int_t * vSwitching = NULL, * vSwitching2 = NULL; float * pSwitching = NULL, * pSwitching2 = NULL; If_Man_t * pIfMan; If_Obj_t * pIfObj; Aig_Obj_t * pNode, * pFanin, * pPrev; int i; abctime clk = Abc_Clock(); // set the number of registers (switch activity will be combinational) Aig_ManSetRegNum( p, 0 ); if ( pPars->fPower ) { vSwitching = Saig_ManComputeSwitchProbs( p, 48, 16, 0 ); if ( pPars->fVerbose ) { ABC_PRT( "Computing switching activity", Abc_Clock() - clk ); } pSwitching = (float *)vSwitching->pArray; vSwitching2 = Vec_IntStart( Aig_ManObjNumMax(p) ); pSwitching2 = (float *)vSwitching2->pArray; } // start the mapping manager and set its parameters pIfMan = If_ManStart( pPars ); pIfMan->vSwitching = vSwitching2; // load the AIG into the mapper Aig_ManForEachObj( p, pNode, i ) { if ( Aig_ObjIsAnd(pNode) ) { pIfObj = If_ManCreateAnd( pIfMan, If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) ); // printf( "no%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); } else if ( Aig_ObjIsCi(pNode) ) { pIfObj = If_ManCreateCi( pIfMan ); If_ObjSetLevel( pIfObj, Aig_ObjLevel(pNode) ); // printf( "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); if ( pIfMan->nLevelMax < (int)pIfObj->Level ) pIfMan->nLevelMax = (int)pIfObj->Level; } else if ( Aig_ObjIsCo(pNode) ) { pIfObj = If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) ); // printf( "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); } else if ( Aig_ObjIsConst1(pNode) ) pIfObj = If_ManConst1( pIfMan ); else // add the node to the mapper assert( 0 ); // save the result assert( Vec_PtrEntry(vAigToIf, i) == NULL ); Vec_PtrWriteEntry( vAigToIf, i, pIfObj ); pNode->pData = pIfObj; if ( vSwitching2 ) pSwitching2[pIfObj->Id] = pSwitching[pNode->Id]; // set up the choice node if ( Aig_ObjIsChoice( p, pNode ) ) { for ( pPrev = pNode, pFanin = Aig_ObjEquiv(p, pNode); pFanin; pPrev = pFanin, pFanin = Aig_ObjEquiv(p, pFanin) ) If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); } // assert( If_ObjLevel(pIfObj) == Aig_ObjLevel(pNode) ); } if ( vSwitching ) Vec_IntFree( vSwitching ); return pIfMan; } /**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Nwk_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) { If_Cut_t * pCut; If_Obj_t * pTemp; Hop_Obj_t * gFunc, * gFunc0, * gFunc1; // get the best cut pCut = If_ObjCutBest(pIfObj); // if the cut is visited, return the result if ( If_CutData(pCut) ) return (Hop_Obj_t *)If_CutData(pCut); // mark the node as visited Vec_PtrPush( vVisited, pCut ); // insert the worst case If_CutSetData( pCut, (void *)1 ); // skip in case of primary input if ( If_ObjIsCi(pIfObj) ) return (Hop_Obj_t *)If_CutData(pCut); // compute the functions of the children for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) { gFunc0 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin0, vVisited ); if ( gFunc0 == (void *)1 ) continue; gFunc1 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin1, vVisited ); if ( gFunc1 == (void *)1 ) continue; // both branches are solved gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pTemp->fCompl0), Hop_NotCond(gFunc1, pTemp->fCompl1) ); if ( pTemp->fPhase != pIfObj->fPhase ) gFunc = Hop_Not(gFunc); If_CutSetData( pCut, gFunc ); break; } return (Hop_Obj_t *)If_CutData(pCut); } /**Function************************************************************* Synopsis [Derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Nwk_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ) { If_Cut_t * pCut; Hop_Obj_t * gFunc; If_Obj_t * pLeaf; int i; // get the best cut pCut = If_ObjCutBest(pIfObj); assert( pCut->nLeaves > 1 ); // set the leaf variables If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) ); // recursively compute the function while collecting visited cuts Vec_PtrClear( pIfMan->vTemp ); gFunc = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); if ( gFunc == (void *)1 ) { printf( "Nwk_NodeIfToHop(): Computing local AIG has failed.\n" ); return NULL; } // printf( "%d ", Vec_PtrSize(p->vTemp) ); // clean the cuts If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) If_CutSetData( If_ObjCutBest(pLeaf), NULL ); Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) If_CutSetData( pCut, NULL ); return gFunc; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Man_t * Nwk_ManFromIf( If_Man_t * pIfMan, Aig_Man_t * p, Vec_Ptr_t * vAigToIf ) { Vec_Ptr_t * vIfToAig; Nwk_Man_t * pNtk; Nwk_Obj_t * pObjNew; Aig_Obj_t * pObj, * pObjRepr; If_Obj_t * pIfObj; If_Cut_t * pCutBest; int i, k, nLeaves, * ppLeaves; assert( Aig_ManCiNum(p) == If_ManCiNum(pIfMan) ); assert( Aig_ManCoNum(p) == If_ManCoNum(pIfMan) ); assert( Aig_ManNodeNum(p) == If_ManAndNum(pIfMan) ); Aig_ManCleanData( p ); If_ManCleanCutData( pIfMan ); // create mapping of IF to AIG vIfToAig = Vec_PtrStart( If_ManObjNum(pIfMan) ); Aig_ManForEachObj( p, pObj, i ) { pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); Vec_PtrWriteEntry( vIfToAig, pIfObj->Id, pObj ); } // construct the network pNtk = Nwk_ManAlloc(); pNtk->pName = Abc_UtilStrsav( p->pName ); pNtk->pSpec = Abc_UtilStrsav( p->pSpec ); // pNtk->nLatches = Aig_ManRegNum(p); // pNtk->nTruePis = Nwk_ManCiNum(pNtk) - pNtk->nLatches; // pNtk->nTruePos = Nwk_ManCoNum(pNtk) - pNtk->nLatches; Aig_ManForEachObj( p, pObj, i ) { pIfObj = (If_Obj_t *)Vec_PtrEntry( vAigToIf, i ); if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) continue; if ( Aig_ObjIsNode(pObj) ) { pCutBest = If_ObjCutBest( pIfObj ); nLeaves = If_CutLeaveNum( pCutBest ); ppLeaves = If_CutLeaves( pCutBest ); // create node pObjNew = Nwk_ManCreateNode( pNtk, nLeaves, pIfObj->nRefs ); for ( k = 0; k < nLeaves; k++ ) { pObjRepr = (Aig_Obj_t *)Vec_PtrEntry( vIfToAig, ppLeaves[k] ); Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)pObjRepr->pData ); } // get the functionality pObjNew->pFunc = Nwk_NodeIfToHop( pNtk->pManHop, pIfMan, pIfObj ); } else if ( Aig_ObjIsCi(pObj) ) pObjNew = Nwk_ManCreateCi( pNtk, pIfObj->nRefs ); else if ( Aig_ObjIsCo(pObj) ) { pObjNew = Nwk_ManCreateCo( pNtk ); pObjNew->fInvert = Aig_ObjFaninC0(pObj); Nwk_ObjAddFanin( pObjNew, (Nwk_Obj_t *)Aig_ObjFanin0(pObj)->pData ); //printf( "%d ", pObjNew->Id ); } else if ( Aig_ObjIsConst1(pObj) ) { pObjNew = Nwk_ManCreateNode( pNtk, 0, pIfObj->nRefs ); pObjNew->pFunc = Hop_ManConst1( pNtk->pManHop ); } else assert( 0 ); pObj->pData = pObjNew; } //printf( "\n" ); Vec_PtrFree( vIfToAig ); pNtk->pManTime = Tim_ManDup( pIfMan->pManTim, 0 ); Nwk_ManMinimumBase( pNtk, 0 ); assert( Nwk_ManCheck( pNtk ) ); return pNtk; } /**Function************************************************************* Synopsis [Interface with the FPGA mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Man_t * Nwk_MappingIf( Aig_Man_t * p, Tim_Man_t * pManTime, If_Par_t * pPars ) { Nwk_Man_t * pNtk; If_Man_t * pIfMan; Vec_Ptr_t * vAigToIf; // set the arrival times pPars->pTimesArr = ABC_ALLOC( float, Aig_ManCiNum(p) ); memset( pPars->pTimesArr, 0, sizeof(float) * Aig_ManCiNum(p) ); // translate into the mapper vAigToIf = Vec_PtrStart( Aig_ManObjNumMax(p) ); pIfMan = Nwk_ManToIf( p, pPars, vAigToIf ); if ( pIfMan == NULL ) return NULL; pIfMan->pManTim = Tim_ManDup( pManTime, 0 ); pIfMan->pPars->fCutMin = 0; // is not compatible with deriving result if ( !If_ManPerformMapping( pIfMan ) ) { If_ManStop( pIfMan ); return NULL; } // transform the result of mapping into the new network pNtk = Nwk_ManFromIf( pIfMan, p, vAigToIf ); if ( pPars->fBidec && pPars->nLutSize <= 8 ) Nwk_ManBidecResyn( pNtk, 0 ); If_ManStop( pIfMan ); Vec_PtrFree( vAigToIf ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkMerge.c000066400000000000000000000775761300674244400234060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkMerge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Netlist representation.] Synopsis [LUT merging algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" #include "nwkMerge.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax ) { Nwk_Grf_t * p; p = ABC_ALLOC( Nwk_Grf_t, 1 ); memset( p, 0, sizeof(Nwk_Grf_t) ); p->nVertsMax = nVertsMax; p->nEdgeHash = Abc_PrimeCudd( 3 * nVertsMax ); p->pEdgeHash = ABC_CALLOC( Nwk_Edg_t *, p->nEdgeHash ); p->pMemEdges = Aig_MmFixedStart( sizeof(Nwk_Edg_t), p->nEdgeHash ); p->vPairs = Vec_IntAlloc( 1000 ); return p; } /**Function************************************************************* Synopsis [Deallocates the graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManGraphFree( Nwk_Grf_t * p ) { if ( p->vPairs ) Vec_IntFree( p->vPairs ); if ( p->pMemEdges ) Aig_MmFixedStop( p->pMemEdges, 0 ); if ( p->pMemVerts ) Aig_MmFlexStop( p->pMemVerts, 0 ); ABC_FREE( p->pVerts ); ABC_FREE( p->pEdgeHash ); ABC_FREE( p->pMapLut2Id ); ABC_FREE( p->pMapId2Lut ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prepares the graph for solving the problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p ) { p->nMemBytes1 = sizeof(Nwk_Grf_t) + sizeof(void *) * p->nEdgeHash + sizeof(int) * (p->nObjs + p->nVertsMax) + sizeof(Nwk_Edg_t) * p->nEdges; p->nMemBytes2 = sizeof(Nwk_Vrt_t) * p->nVerts + sizeof(int) * 2 * p->nEdges; printf( "Memory usage stats: Preprocessing = %.2f MB. Solving = %.2f MB.\n", 1.0 * p->nMemBytes1 / (1<<20), 1.0 * p->nMemBytes2 / (1<<20) ); } /**Function************************************************************* Synopsis [Finds or adds the edge to the graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 ) { Nwk_Edg_t * pEntry; unsigned Key; if ( iLut1 == iLut2 ) return; if ( iLut1 > iLut2 ) { Key = iLut1; iLut1 = iLut2; iLut2 = Key; } assert( iLut1 < iLut2 ); if ( p->nObjs < iLut2 ) p->nObjs = iLut2; Key = (unsigned)(741457 * iLut1 + 4256249 * iLut2) % p->nEdgeHash; for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext ) if ( pEntry->iNode1 == iLut1 && pEntry->iNode2 == iLut2 ) return; pEntry = (Nwk_Edg_t *)Aig_MmFixedEntryFetch( p->pMemEdges ); pEntry->iNode1 = iLut1; pEntry->iNode2 = iLut2; pEntry->pNext = p->pEdgeHash[Key]; p->pEdgeHash[Key] = pEntry; p->nEdges++; } /**Function************************************************************* Synopsis [Adds one entry to the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex ) { if ( *pList ) { Nwk_Vrt_t * pHead; pHead = p->pVerts[*pList]; pVertex->iPrev = 0; pVertex->iNext = pHead->Id; pHead->iPrev = pVertex->Id; } *pList = pVertex->Id; } /**Function************************************************************* Synopsis [Deletes one entry from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex ) { assert( *pList ); if ( pVertex->iPrev ) { // assert( p->pVerts[pVertex->iPrev]->iNext == pVertex->Id ); p->pVerts[pVertex->iPrev]->iNext = pVertex->iNext; } if ( pVertex->iNext ) { // assert( p->pVerts[pVertex->iNext]->iPrev == pVertex->Id ); p->pVerts[pVertex->iNext]->iPrev = pVertex->iPrev; } if ( *pList == pVertex->Id ) *pList = pVertex->iNext; pVertex->iPrev = pVertex->iNext = 0; } /**Function************************************************************* Synopsis [Inserts the edge into one of the linked lists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) { Nwk_Vrt_t * pNext; assert( pVertex->nEdges > 0 ); if ( pVertex->nEdges == 1 ) { pNext = p->pVerts[ pVertex->pEdges[0] ]; if ( pNext->nEdges >= NWK_MAX_LIST ) Nwk_ManGraphListAdd( p, p->pLists1 + NWK_MAX_LIST, pVertex ); else Nwk_ManGraphListAdd( p, p->pLists1 + pNext->nEdges, pVertex ); } else { if ( pVertex->nEdges >= NWK_MAX_LIST ) Nwk_ManGraphListAdd( p, p->pLists2 + NWK_MAX_LIST, pVertex ); else Nwk_ManGraphListAdd( p, p->pLists2 + pVertex->nEdges, pVertex ); } } /**Function************************************************************* Synopsis [Extracts the edge from one of the linked lists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex ) { Nwk_Vrt_t * pNext; assert( pVertex->nEdges > 0 ); if ( pVertex->nEdges == 1 ) { pNext = p->pVerts[ pVertex->pEdges[0] ]; if ( pNext->nEdges >= NWK_MAX_LIST ) Nwk_ManGraphListDelete( p, p->pLists1 + NWK_MAX_LIST, pVertex ); else Nwk_ManGraphListDelete( p, p->pLists1 + pNext->nEdges, pVertex ); } else { if ( pVertex->nEdges >= NWK_MAX_LIST ) Nwk_ManGraphListDelete( p, p->pLists2 + NWK_MAX_LIST, pVertex ); else Nwk_ManGraphListDelete( p, p->pLists2 + pVertex->nEdges, pVertex ); } } /**Function************************************************************* Synopsis [Prepares the graph for solving the problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManGraphPrepare( Nwk_Grf_t * p ) { Nwk_Edg_t * pEntry; Nwk_Vrt_t * pVertex; int * pnEdges, nBytes, i; // allocate memory for the present objects p->pMapLut2Id = ABC_ALLOC( int, p->nObjs+1 ); p->pMapId2Lut = ABC_ALLOC( int, p->nVertsMax+1 ); memset( p->pMapLut2Id, 0xff, sizeof(int) * (p->nObjs+1) ); memset( p->pMapId2Lut, 0xff, sizeof(int) * (p->nVertsMax+1) ); // mark present objects Nwk_GraphForEachEdge( p, pEntry, i ) { assert( pEntry->iNode1 <= p->nObjs ); assert( pEntry->iNode2 <= p->nObjs ); p->pMapLut2Id[ pEntry->iNode1 ] = 0; p->pMapLut2Id[ pEntry->iNode2 ] = 0; } // map objects p->nVerts = 0; for ( i = 0; i <= p->nObjs; i++ ) { if ( p->pMapLut2Id[i] == 0 ) { p->pMapLut2Id[i] = ++p->nVerts; p->pMapId2Lut[p->nVerts] = i; } } // count the edges and mark present objects pnEdges = ABC_CALLOC( int, p->nVerts+1 ); Nwk_GraphForEachEdge( p, pEntry, i ) { // translate into vertices assert( pEntry->iNode1 <= p->nObjs ); assert( pEntry->iNode2 <= p->nObjs ); pEntry->iNode1 = p->pMapLut2Id[pEntry->iNode1]; pEntry->iNode2 = p->pMapLut2Id[pEntry->iNode2]; // count the edges assert( pEntry->iNode1 <= p->nVerts ); assert( pEntry->iNode2 <= p->nVerts ); pnEdges[pEntry->iNode1]++; pnEdges[pEntry->iNode2]++; } // allocate the real graph p->pMemVerts = Aig_MmFlexStart(); p->pVerts = ABC_ALLOC( Nwk_Vrt_t *, p->nVerts + 1 ); p->pVerts[0] = NULL; for ( i = 1; i <= p->nVerts; i++ ) { assert( pnEdges[i] > 0 ); nBytes = sizeof(Nwk_Vrt_t) + sizeof(int) * pnEdges[i]; p->pVerts[i] = (Nwk_Vrt_t *)Aig_MmFlexEntryFetch( p->pMemVerts, nBytes ); memset( p->pVerts[i], 0, nBytes ); p->pVerts[i]->Id = i; } // add edges to the real graph Nwk_GraphForEachEdge( p, pEntry, i ) { pVertex = p->pVerts[pEntry->iNode1]; pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode2; pVertex = p->pVerts[pEntry->iNode2]; pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode1; } // put vertices into the data structure for ( i = 1; i <= p->nVerts; i++ ) { assert( p->pVerts[i]->nEdges == pnEdges[i] ); Nwk_ManGraphListInsert( p, p->pVerts[i] ); } // clean up Aig_MmFixedStop( p->pMemEdges, 0 ); p->pMemEdges = NULL; ABC_FREE( p->pEdgeHash ); // p->nEdgeHash = 0; ABC_FREE( pnEdges ); } /**Function************************************************************* Synopsis [Sort pairs by the first vertex in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManGraphSortPairs( Nwk_Grf_t * p ) { int nSize = Vec_IntSize(p->vPairs); int * pIdToPair, i; // allocate storage pIdToPair = ABC_ALLOC( int, p->nObjs+1 ); for ( i = 0; i <= p->nObjs; i++ ) pIdToPair[i] = -1; // create mapping for ( i = 0; i < p->vPairs->nSize; i += 2 ) { assert( pIdToPair[ p->vPairs->pArray[i] ] == -1 ); pIdToPair[ p->vPairs->pArray[i] ] = p->vPairs->pArray[i+1]; } // recreate pairs Vec_IntClear( p->vPairs ); for ( i = 0; i <= p->nObjs; i++ ) if ( pIdToPair[i] >= 0 ) { assert( i < pIdToPair[i] ); Vec_IntPush( p->vPairs, i ); Vec_IntPush( p->vPairs, pIdToPair[i] ); } assert( nSize == Vec_IntSize(p->vPairs) ); ABC_FREE( pIdToPair ); } /**Function************************************************************* Synopsis [Updates the problem after pulling out one edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManGraphCheckLists( Nwk_Grf_t * p ) { Nwk_Vrt_t * pVertex, * pNext; int i, j; assert( p->pLists1[0] == 0 ); for ( i = 1; i <= NWK_MAX_LIST; i++ ) if ( p->pLists1[i] ) { pVertex = p->pVerts[ p->pLists1[i] ]; assert( pVertex->nEdges == 1 ); pNext = p->pVerts[ pVertex->pEdges[0] ]; assert( pNext->nEdges == i || pNext->nEdges > NWK_MAX_LIST ); } // find the next vertext to extract assert( p->pLists2[0] == 0 ); assert( p->pLists2[1] == 0 ); for ( j = 2; j <= NWK_MAX_LIST; j++ ) if ( p->pLists2[j] ) { pVertex = p->pVerts[ p->pLists2[j] ]; assert( pVertex->nEdges == j || pVertex->nEdges > NWK_MAX_LIST ); } } /**Function************************************************************* Synopsis [Extracts the edge from one of the linked lists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Nwk_ManGraphVertexRemoveEdge( Nwk_Vrt_t * pThis, Nwk_Vrt_t * pNext ) { int k; for ( k = 0; k < pThis->nEdges; k++ ) if ( pThis->pEdges[k] == pNext->Id ) break; assert( k < pThis->nEdges ); pThis->nEdges--; for ( ; k < pThis->nEdges; k++ ) pThis->pEdges[k] = pThis->pEdges[k+1]; } /**Function************************************************************* Synopsis [Updates the problem after pulling out one edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext ) { Nwk_Vrt_t * pChanged, * pOther; int i, k; // Nwk_ManGraphCheckLists( p ); Nwk_ManGraphListExtract( p, pVertex ); Nwk_ManGraphListExtract( p, pNext ); // update neihbors of pVertex Nwk_VertexForEachAdjacent( p, pVertex, pChanged, i ) { if ( pChanged == pNext ) continue; Nwk_ManGraphListExtract( p, pChanged ); // move those that use this one if ( pChanged->nEdges > 1 ) Nwk_VertexForEachAdjacent( p, pChanged, pOther, k ) { if ( pOther == pVertex || pOther->nEdges > 1 ) continue; assert( pOther->nEdges == 1 ); Nwk_ManGraphListExtract( p, pOther ); pChanged->nEdges--; Nwk_ManGraphListInsert( p, pOther ); pChanged->nEdges++; } // remove the edge Nwk_ManGraphVertexRemoveEdge( pChanged, pVertex ); // add the changed vertex back if ( pChanged->nEdges > 0 ) Nwk_ManGraphListInsert( p, pChanged ); } // update neihbors of pNext Nwk_VertexForEachAdjacent( p, pNext, pChanged, i ) { if ( pChanged == pVertex ) continue; Nwk_ManGraphListExtract( p, pChanged ); // move those that use this one if ( pChanged->nEdges > 1 ) Nwk_VertexForEachAdjacent( p, pChanged, pOther, k ) { if ( pOther == pNext || pOther->nEdges > 1 ) continue; assert( pOther->nEdges == 1 ); Nwk_ManGraphListExtract( p, pOther ); pChanged->nEdges--; Nwk_ManGraphListInsert( p, pOther ); pChanged->nEdges++; } // remove the edge Nwk_ManGraphVertexRemoveEdge( pChanged, pNext ); // add the changed vertex back if ( pChanged->nEdges > 0 ) Nwk_ManGraphListInsert( p, pChanged ); } // add to the result if ( pVertex->Id < pNext->Id ) { Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); } else { Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); } // Nwk_ManGraphCheckLists( p ); } /**Function************************************************************* Synopsis [Counts the number of entries in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManGraphListLength( Nwk_Grf_t * p, int List ) { Nwk_Vrt_t * pThis; int fVerbose = 0; int Counter = 0; Nwk_ListForEachVertex( p, List, pThis ) { if ( fVerbose && Counter < 20 ) printf( "%d ", p->pVerts[pThis->pEdges[0]]->nEdges ); Counter++; } if ( fVerbose ) printf( "\n" ); return Counter; } /**Function************************************************************* Synopsis [Returns the adjacent vertex with the mininum number of edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Vrt_t * Nwk_ManGraphListFindMinEdge( Nwk_Grf_t * p, Nwk_Vrt_t * pVert ) { Nwk_Vrt_t * pThis, * pMinCost = NULL; int k; Nwk_VertexForEachAdjacent( p, pVert, pThis, k ) { if ( pMinCost == NULL || pMinCost->nEdges > pThis->nEdges ) pMinCost = pThis; } return pMinCost; } /**Function************************************************************* Synopsis [Finds the best vertext in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Vrt_t * Nwk_ManGraphListFindMin( Nwk_Grf_t * p, int List ) { Nwk_Vrt_t * pThis, * pMinCost = NULL; int k, Counter = 10000, BestCost = 1000000; Nwk_ListForEachVertex( p, List, pThis ) { for ( k = 0; k < pThis->nEdges; k++ ) { if ( pMinCost == NULL || BestCost > p->pVerts[pThis->pEdges[k]]->nEdges ) { BestCost = p->pVerts[pThis->pEdges[k]]->nEdges; pMinCost = pThis; } } if ( --Counter == 0 ) break; } return pMinCost; } /**Function************************************************************* Synopsis [Solves the problem by extracting one edge at a time.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManGraphSolve( Nwk_Grf_t * p ) { Nwk_Vrt_t * pVertex, * pNext; int i, j; Nwk_ManGraphPrepare( p ); while ( 1 ) { // find the next vertex to extract assert( p->pLists1[0] == 0 ); for ( i = 1; i <= NWK_MAX_LIST; i++ ) if ( p->pLists1[i] ) { // printf( "%d ", i ); // printf( "ListA = %2d. Length = %5d.\n", i, Nwk_ManGraphListLength(p,p->pLists1[i]) ); pVertex = p->pVerts[ p->pLists1[i] ]; assert( pVertex->nEdges == 1 ); pNext = p->pVerts[ pVertex->pEdges[0] ]; Nwk_ManGraphUpdate( p, pVertex, pNext ); break; } if ( i < NWK_MAX_LIST + 1 ) continue; // find the next vertex to extract assert( p->pLists2[0] == 0 ); assert( p->pLists2[1] == 0 ); for ( j = 2; j <= NWK_MAX_LIST; j++ ) if ( p->pLists2[j] ) { // printf( "***%d ", j ); // printf( "ListB = %2d. Length = %5d.\n", j, Nwk_ManGraphListLength(p,p->pLists2[j]) ); pVertex = Nwk_ManGraphListFindMin( p, p->pLists2[j] ); assert( pVertex->nEdges == j || j == NWK_MAX_LIST ); pNext = Nwk_ManGraphListFindMinEdge( p, pVertex ); Nwk_ManGraphUpdate( p, pVertex, pNext ); break; } if ( j == NWK_MAX_LIST + 1 ) break; } Nwk_ManGraphSortPairs( p ); } /**Function************************************************************* Synopsis [Reads graph from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Grf_t * Nwk_ManLutMergeReadGraph( char * pFileName ) { Nwk_Grf_t * p; FILE * pFile; char Buffer[100]; int nNodes, nEdges, iNode1, iNode2; int RetValue; pFile = fopen( pFileName, "r" ); RetValue = fscanf( pFile, "%s %d", Buffer, &nNodes ); RetValue = fscanf( pFile, "%s %d", Buffer, &nEdges ); p = Nwk_ManGraphAlloc( nNodes ); while ( fscanf( pFile, "%s %d %d", Buffer, &iNode1, &iNode2 ) == 3 ) Nwk_ManGraphHashEdge( p, iNode1, iNode2 ); assert( p->nEdges == nEdges ); fclose( pFile ); return p; } /**Function************************************************************* Synopsis [Solves the graph coming from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManLutMergeGraphTest( char * pFileName ) { int nPairs; Nwk_Grf_t * p; abctime clk = Abc_Clock(); p = Nwk_ManLutMergeReadGraph( pFileName ); ABC_PRT( "Reading", Abc_Clock() - clk ); clk = Abc_Clock(); Nwk_ManGraphSolve( p ); printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); ABC_PRT( "Solving", Abc_Clock() - clk ); nPairs = Vec_IntSize(p->vPairs)/2; Nwk_ManGraphReportMemoryUsage( p ); Nwk_ManGraphFree( p ); return nPairs; } /**Function************************************************************* Synopsis [Marks the fanins of the node with the current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin ) { Nwk_Obj_t * pNext; int i; if ( !Nwk_ObjIsNode(pLut) ) return; if ( Nwk_ObjIsTravIdCurrent( pLut ) ) return; Nwk_ObjSetTravIdCurrent( pLut ); if ( Nwk_ObjLevel(pLut) < nLevMin ) return; Nwk_ObjForEachFanin( pLut, pNext, i ) Nwk_ManMarkFanins_rec( pNext, nLevMin ); } /**Function************************************************************* Synopsis [Marks the fanouts of the node with the current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax ) { Nwk_Obj_t * pNext; int i; if ( !Nwk_ObjIsNode(pLut) ) return; if ( Nwk_ObjIsTravIdCurrent( pLut ) ) return; Nwk_ObjSetTravIdCurrent( pLut ); if ( Nwk_ObjLevel(pLut) > nLevMax ) return; if ( Nwk_ObjFanoutNum(pLut) > nFanMax ) return; Nwk_ObjForEachFanout( pLut, pNext, i ) Nwk_ManMarkFanouts_rec( pNext, nLevMax, nFanMax ); } /**Function************************************************************* Synopsis [Collects the circle of nodes around the given set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) { Nwk_Obj_t * pObj, * pNext; int i, k; Vec_PtrClear( vNext ); Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, i ) { Nwk_ObjForEachFanin( pObj, pNext, k ) { if ( !Nwk_ObjIsNode(pNext) ) continue; if ( Nwk_ObjIsTravIdCurrent( pNext ) ) continue; Nwk_ObjSetTravIdCurrent( pNext ); Vec_PtrPush( vNext, pNext ); } Nwk_ObjForEachFanout( pObj, pNext, k ) { if ( !Nwk_ObjIsNode(pNext) ) continue; if ( Nwk_ObjIsTravIdCurrent( pNext ) ) continue; Nwk_ObjSetTravIdCurrent( pNext ); if ( Nwk_ObjFanoutNum(pNext) > nFanMax ) continue; Vec_PtrPush( vNext, pNext ); } } } /**Function************************************************************* Synopsis [Collects the circle of nodes removes from the given one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) { Vec_Ptr_t * vTemp; Nwk_Obj_t * pObj; int i, k; Vec_PtrClear( vCands ); if ( pPars->nMaxSuppSize - Nwk_ObjFaninNum(pLut) <= 1 ) return; // collect nodes removed by this distance assert( pPars->nMaxDistance > 0 ); Vec_PtrClear( vStart ); Vec_PtrPush( vStart, pLut ); Nwk_ManIncrementTravId( pLut->pMan ); Nwk_ObjSetTravIdCurrent( pLut ); for ( i = 1; i <= pPars->nMaxDistance; i++ ) { Nwk_ManCollectCircle( vStart, vNext, pPars->nMaxFanout ); vTemp = vStart; vStart = vNext; vNext = vTemp; // collect the nodes in vStart Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, k ) Vec_PtrPush( vCands, pObj ); } // mark the TFI/TFO nodes Nwk_ManIncrementTravId( pLut->pMan ); if ( pPars->fUseTfiTfo ) Nwk_ObjSetTravIdCurrent( pLut ); else { Nwk_ObjSetTravIdPrevious( pLut ); Nwk_ManMarkFanins_rec( pLut, Nwk_ObjLevel(pLut) - pPars->nMaxDistance ); Nwk_ObjSetTravIdPrevious( pLut ); Nwk_ManMarkFanouts_rec( pLut, Nwk_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); } // collect nodes satisfying the following conditions: // - they are close enough in terms of distance // - they are not in the TFI/TFO of the LUT // - they have no more than the given number of fanins // - they have no more than the given diff in delay k = 0; Vec_PtrForEachEntry( Nwk_Obj_t *, vCands, pObj, i ) { if ( Nwk_ObjIsTravIdCurrent(pObj) ) continue; if ( Nwk_ObjFaninNum(pLut) + Nwk_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) continue; if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff ) continue; Vec_PtrWriteEntry( vCands, k++, pObj ); } Vec_PtrShrink( vCands, k ); } /**Function************************************************************* Synopsis [Count the total number of fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand ) { Nwk_Obj_t * pFanin; int i, nCounter = Nwk_ObjFaninNum(pLut); Nwk_ObjForEachFanin( pCand, pFanin, i ) nCounter += !pFanin->MarkC; return nCounter; } /**Function************************************************************* Synopsis [Collects overlapping candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) { Nwk_Obj_t * pFanin, * pObj; int i, k; // mark fanins of pLut Nwk_ObjForEachFanin( pLut, pFanin, i ) pFanin->MarkC = 1; // collect the matching fanouts of each fanin of the node Vec_PtrClear( vCands ); Nwk_ManIncrementTravId( pLut->pMan ); Nwk_ObjSetTravIdCurrent( pLut ); Nwk_ObjForEachFanin( pLut, pFanin, i ) { if ( !Nwk_ObjIsNode(pFanin) ) continue; if ( Nwk_ObjFanoutNum(pFanin) > pPars->nMaxFanout ) continue; Nwk_ObjForEachFanout( pFanin, pObj, k ) { if ( !Nwk_ObjIsNode(pObj) ) continue; if ( Nwk_ObjIsTravIdCurrent( pObj ) ) continue; Nwk_ObjSetTravIdCurrent( pObj ); // check the difference in delay if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff ) continue; // check the total number of fanins of the node if ( Nwk_ManCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) continue; Vec_PtrPush( vCands, pObj ); } } // unmark fanins of pLut Nwk_ObjForEachFanin( pLut, pFanin, i ) pFanin->MarkC = 0; } /**Function************************************************************* Synopsis [Performs LUT merging with parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, void * pParsInit ) { Nwk_LMPars_t * pPars = (Nwk_LMPars_t *)pParsInit; Nwk_Grf_t * p; Vec_Int_t * vResult; Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; Nwk_Obj_t * pLut, * pCand; int i, k, nVertsMax, nCands; abctime clk = Abc_Clock(); // count the number of vertices nVertsMax = 0; Nwk_ManForEachNode( pNtk, pLut, i ) nVertsMax += (int)(Nwk_ObjFaninNum(pLut) <= pPars->nMaxLutSize); p = Nwk_ManGraphAlloc( nVertsMax ); // create graph vStart = Vec_PtrAlloc( 1000 ); vNext = Vec_PtrAlloc( 1000 ); vCands1 = Vec_PtrAlloc( 1000 ); vCands2 = Vec_PtrAlloc( 1000 ); nCands = 0; Nwk_ManForEachNode( pNtk, pLut, i ) { if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize ) continue; Nwk_ManCollectOverlapCands( pLut, vCands1, pPars ); if ( pPars->fUseDiffSupp ) Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) continue; nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2); // save candidates Vec_PtrForEachEntry( Nwk_Obj_t *, vCands1, pCand, k ) Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) ); Vec_PtrForEachEntry( Nwk_Obj_t *, vCands2, pCand, k ) Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) ); // print statistics about this node if ( pPars->fVeryVerbose ) printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", Nwk_ObjId(pLut), Nwk_ObjFaninNum(pLut), Nwk_ObjFaninNum(pLut), Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); } Vec_PtrFree( vStart ); Vec_PtrFree( vNext ); Vec_PtrFree( vCands1 ); Vec_PtrFree( vCands2 ); if ( pPars->fVerbose ) { printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands ); ABC_PRT( "Deriving graph", Abc_Clock() - clk ); } // solve the graph problem clk = Abc_Clock(); Nwk_ManGraphSolve( p ); if ( pPars->fVerbose ) { printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); ABC_PRT( "Solving", Abc_Clock() - clk ); Nwk_ManGraphReportMemoryUsage( p ); } vResult = p->vPairs; p->vPairs = NULL; /* for ( i = 0; i < vResult->nSize; i += 2 ) printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); printf( "\n" ); */ Nwk_ManGraphFree( p ); return vResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkMerge.h000066400000000000000000000137401300674244400233720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkMerge.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkMerge.h,v 1.1 2008/05/14 22:13:09 wudenni Exp $] ***********************************************************************/ #ifndef __NWK_MERGE_H__ #define __NWK_MERGE_H__ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define NWK_MAX_LIST 16 //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // the LUT merging parameters typedef struct Nwk_LMPars_t_ Nwk_LMPars_t; struct Nwk_LMPars_t_ { int nMaxLutSize; // the max LUT size for merging (N=5) int nMaxSuppSize; // the max total support size after merging (S=5) int nMaxDistance; // the max number of nodes separating LUTs int nMaxLevelDiff; // the max difference in levels int nMaxFanout; // the max number of fanouts to traverse int fUseDiffSupp; // enables the use of nodes with different support int fUseTfiTfo; // enables the use of TFO/TFO nodes as candidates int fVeryVerbose; // enables additional verbose output int fVerbose; // enables verbose output }; // edge of the graph typedef struct Nwk_Edg_t_ Nwk_Edg_t; struct Nwk_Edg_t_ { int iNode1; // the first node int iNode2; // the second node Nwk_Edg_t * pNext; // the next edge }; // vertex of the graph typedef struct Nwk_Vrt_t_ Nwk_Vrt_t; struct Nwk_Vrt_t_ { int Id; // the vertex number int iPrev; // the previous vertex in the list int iNext; // the next vertex in the list int nEdges; // the number of edges int pEdges[0]; // the array of edges }; // the connectivity graph typedef struct Nwk_Grf_t_ Nwk_Grf_t; struct Nwk_Grf_t_ { // preliminary graph representation int nObjs; // the number of objects int nVertsMax; // the upper bound on the number of vertices int nEdgeHash; // an approximate number of edges Nwk_Edg_t ** pEdgeHash; // hash table for edges Aig_MmFixed_t * pMemEdges; // memory for edges // graph representation int nEdges; // the number of edges int nVerts; // the number of vertices Nwk_Vrt_t ** pVerts; // the array of vertices Aig_MmFlex_t * pMemVerts; // memory for vertices // intermediate data int pLists1[NWK_MAX_LIST+1]; // lists of nodes with one edge int pLists2[NWK_MAX_LIST+1]; // lists of nodes with more than one edge // the results of matching Vec_Int_t * vPairs; // pairs matched in the graph // object mappings int * pMapLut2Id; // LUT numbers into vertex IDs int * pMapId2Lut; // vertex IDs into LUT numbers // other things int nMemBytes1; // memory usage in bytes int nMemBytes2; // memory usage in bytes }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Nwk_GraphForEachEdge( p, pEdge, k ) \ for ( k = 0; k < p->nEdgeHash; k++ ) \ for ( pEdge = p->pEdgeHash[k]; pEdge; pEdge = pEdge->pNext ) #define Nwk_ListForEachVertex( p, List, pVrt ) \ for ( pVrt = List? p->pVerts[List] : NULL; pVrt; \ pVrt = pVrt->iNext? p->pVerts[pVrt->iNext] : NULL ) #define Nwk_VertexForEachAdjacent( p, pVrt, pNext, k ) \ for ( k = 0; (k < pVrt->nEdges) && (((pNext) = p->pVerts[pVrt->pEdges[k]]), 1); k++ ) //////////////////////////////////////////////////////////////////////// /// INLINED FUNCTIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== nwkMerge.c ==========================================================*/ extern ABC_DLL Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax ); extern ABC_DLL void Nwk_ManGraphFree( Nwk_Grf_t * p ); extern ABC_DLL void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p ); extern ABC_DLL void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 ); extern ABC_DLL void Nwk_ManGraphSolve( Nwk_Grf_t * p ); extern ABC_DLL int Nwk_ManLutMergeGraphTest( char * pFileName ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkObj.c000066400000000000000000000126331300674244400230400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkObj.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Manipulation of objects.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates an object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Obj_t * Nwk_ManCreateObj( Nwk_Man_t * p, int nFanins, int nFanouts ) { Nwk_Obj_t * pObj; pObj = (Nwk_Obj_t *)Aig_MmFlexEntryFetch( p->pMemObjs, sizeof(Nwk_Obj_t) + (nFanins + nFanouts + p->nFanioPlus) * sizeof(Nwk_Obj_t *) ); memset( pObj, 0, sizeof(Nwk_Obj_t) ); pObj->pFanio = (Nwk_Obj_t **)((char *)pObj + sizeof(Nwk_Obj_t)); pObj->Id = Vec_PtrSize( p->vObjs ); Vec_PtrPush( p->vObjs, pObj ); pObj->pMan = p; pObj->nFanioAlloc = nFanins + nFanouts + p->nFanioPlus; return pObj; } /**Function************************************************************* Synopsis [Creates a primary input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Obj_t * Nwk_ManCreateCi( Nwk_Man_t * p, int nFanouts ) { Nwk_Obj_t * pObj; pObj = Nwk_ManCreateObj( p, 1, nFanouts ); pObj->PioId = Vec_PtrSize( p->vCis ); Vec_PtrPush( p->vCis, pObj ); pObj->Type = NWK_OBJ_CI; p->nObjs[NWK_OBJ_CI]++; return pObj; } /**Function************************************************************* Synopsis [Creates a primary output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Obj_t * Nwk_ManCreateCo( Nwk_Man_t * p ) { Nwk_Obj_t * pObj; pObj = Nwk_ManCreateObj( p, 1, 1 ); pObj->PioId = Vec_PtrSize( p->vCos ); Vec_PtrPush( p->vCos, pObj ); pObj->Type = NWK_OBJ_CO; p->nObjs[NWK_OBJ_CO]++; return pObj; } /**Function************************************************************* Synopsis [Creates a latch.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Obj_t * Nwk_ManCreateLatch( Nwk_Man_t * p ) { Nwk_Obj_t * pObj; pObj = Nwk_ManCreateObj( p, 1, 1 ); pObj->Type = NWK_OBJ_LATCH; p->nObjs[NWK_OBJ_LATCH]++; return pObj; } /**Function************************************************************* Synopsis [Creates a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nwk_Obj_t * Nwk_ManCreateNode( Nwk_Man_t * p, int nFanins, int nFanouts ) { Nwk_Obj_t * pObj; pObj = Nwk_ManCreateObj( p, nFanins, nFanouts ); pObj->Type = NWK_OBJ_NODE; p->nObjs[NWK_OBJ_NODE]++; return pObj; } /**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDeleteNode( Nwk_Obj_t * pObj ) { Vec_Ptr_t * vNodes = pObj->pMan->vTemp; Nwk_Obj_t * pTemp; int i; assert( Nwk_ObjFanoutNum(pObj) == 0 ); // delete fanins Nwk_ObjCollectFanins( pObj, vNodes ); Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pTemp, i ) Nwk_ObjDeleteFanin( pObj, pTemp ); // remove from the list of objects Vec_PtrWriteEntry( pObj->pMan->vObjs, pObj->Id, NULL ); pObj->pMan->nObjs[pObj->Type]--; memset( pObj, 0, sizeof(Nwk_Obj_t) ); pObj->Id = -1; } /**Function************************************************************* Synopsis [Deletes the node and MFFC of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDeleteNode_rec( Nwk_Obj_t * pObj ) { Vec_Ptr_t * vNodes; int i; assert( !Nwk_ObjIsCi(pObj) ); assert( Nwk_ObjFanoutNum(pObj) == 0 ); vNodes = Vec_PtrAlloc( 100 ); Nwk_ObjCollectFanins( pObj, vNodes ); Nwk_ManDeleteNode( pObj ); Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) if ( Nwk_ObjIsNode(pObj) && Nwk_ObjFanoutNum(pObj) == 0 ) Nwk_ManDeleteNode_rec( pObj ); Vec_PtrFree( vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkSpeedup.c000066400000000000000000000324661300674244400237410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkSpeedup.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Netlist representation.] Synopsis [Global delay optimization using structural choices.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkSpeedup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds strashed nodes for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManSpeedupNode_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) return 1; if ( Aig_ObjIsCi(pNode) ) return 0; assert( Aig_ObjIsNode(pNode) ); Aig_ObjSetTravIdCurrent( pAig, pNode ); if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin0(pNode), vNodes ) ) return 0; if ( !Aig_ManSpeedupNode_rec( pAig, Aig_ObjFanin1(pNode), vNodes ) ) return 0; Vec_PtrPush( vNodes, pNode ); return 1; } /**Function************************************************************* Synopsis [Adds strashed nodes for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSpeedupNode( Nwk_Man_t * pNtk, Aig_Man_t * pAig, Nwk_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vTimes ) { Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj, * pObj2; Aig_Obj_t * ppCofs[32], * pAnd, * pTemp; int nCofs, i, k, nSkip; // quit of regulars are the same Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i ) Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj2, k ) if ( i != k && Aig_Regular((Aig_Obj_t *)pObj->pCopy) == Aig_Regular((Aig_Obj_t *)pObj2->pCopy) ) { // printf( "Identical after structural hashing!!!\n" ); return; } // collect the AIG nodes vNodes = Vec_PtrAlloc( 100 ); Aig_ManIncrementTravId( pAig ); Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, i ) { pAnd = (Aig_Obj_t *)pObj->pCopy; Aig_ObjSetTravIdCurrent( pAig, Aig_Regular(pAnd) ); } // traverse from the root node pAnd = (Aig_Obj_t *)pNode->pCopy; if ( !Aig_ManSpeedupNode_rec( pAig, Aig_Regular(pAnd), vNodes ) ) { // printf( "Bad node!!!\n" ); Vec_PtrFree( vNodes ); return; } // derive cofactors nCofs = (1 << Vec_PtrSize(vTimes)); for ( i = 0; i < nCofs; i++ ) { Vec_PtrForEachEntry( Nwk_Obj_t *, vLeaves, pObj, k ) { pAnd = (Aig_Obj_t *)pObj->pCopy; Aig_Regular(pAnd)->pData = Aig_Regular(pAnd); } Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k ) { pAnd = (Aig_Obj_t *)pObj->pCopy; Aig_Regular(pAnd)->pData = Aig_NotCond( Aig_ManConst1(pAig), ((i & (1<pData = Aig_And( pAig, Aig_ObjChild0Copy(pTemp), Aig_ObjChild1Copy(pTemp) ); // save the result pAnd = (Aig_Obj_t *)pNode->pCopy; ppCofs[i] = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pAnd)->pData, Aig_IsComplement(pAnd) ); } Vec_PtrFree( vNodes ); //Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] ); //Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[1] ); // collect the resulting tree Vec_PtrForEachEntry( Nwk_Obj_t *, vTimes, pObj, k ) for ( nSkip = (1<pCopy; ppCofs[i] = Aig_Mux( pAig, Aig_Regular(pAnd), ppCofs[i+nSkip], ppCofs[i] ); } //Nwk_ObjAddFanin( Nwk_ManCreatePo(pAig), ppCofs[0] ); // create choice node pAnd = Aig_Regular((Aig_Obj_t *)pNode->pCopy); // repr pTemp = Aig_Regular(ppCofs[0]); // new if ( Aig_ObjEquiv(pAig, pAnd) == NULL && Aig_ObjEquiv(pAig, pTemp) == NULL && !Aig_ObjCheckTfi(pAig, pTemp, pAnd) ) pAig->pEquivs[pAnd->Id] = pTemp; } /**Function************************************************************* Synopsis [Determines timing-critical edges of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Nwk_ManDelayTraceTCEdges( Nwk_Man_t * pNtk, Nwk_Obj_t * pNode, float tDelta, int fUseLutLib ) { int pPinPerm[32]; float pPinDelays[32]; If_LibLut_t * pLutLib = fUseLutLib? pNtk->pLutLib : NULL; Nwk_Obj_t * pFanin; unsigned uResult = 0; float tRequired, * pDelays; int k; tRequired = Nwk_ObjRequired(pNode); if ( pLutLib == NULL ) { Nwk_ObjForEachFanin( pNode, pFanin, k ) if ( tRequired < Nwk_ObjArrival(pFanin) + 1.0 + tDelta ) uResult |= (1 << k); } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)]; Nwk_ObjForEachFanin( pNode, pFanin, k ) if ( tRequired < Nwk_ObjArrival(pFanin) + pDelays[0] + tDelta ) uResult |= (1 << k); } else { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pNode)]; Nwk_ManDelayTraceSortPins( pNode, pPinPerm, pPinDelays ); Nwk_ObjForEachFanin( pNode, pFanin, k ) if ( tRequired < Nwk_ObjArrival(Nwk_ObjFanin(pNode,pPinPerm[k])) + pDelays[k] + tDelta ) uResult |= (1 << pPinPerm[k]); } return uResult; } /**Function************************************************************* Synopsis [Adds choices to speed up the network by the given percentage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Nwk_ManSpeedup( Nwk_Man_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ) { Aig_Man_t * pAig, * pTemp; Vec_Ptr_t * vTimeCries, * vTimeFanins; Nwk_Obj_t * pNode, * pFanin, * pFanin2; Aig_Obj_t * pAnd; If_LibLut_t * pTempLib = pNtk->pLutLib; Tim_Man_t * pTempTim = NULL; float tDelta, tArrival; int i, k, k2, Counter, CounterRes, nTimeCris; unsigned * puTCEdges; // perform delay trace if ( !fUseLutLib ) { pNtk->pLutLib = NULL; if ( pNtk->pManTime ) { pTempTim = pNtk->pManTime; pNtk->pManTime = Tim_ManDup( pTempTim, 1 ); } } tArrival = Nwk_ManDelayTraceLut( pNtk ); 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_ALLOC( unsigned, Nwk_ManObjNumMax(pNtk) ); memset( puTCEdges, 0, sizeof(unsigned) * Nwk_ManObjNumMax(pNtk) ); Nwk_ManForEachNode( pNtk, pNode, i ) { if ( Nwk_ObjSlack(pNode) >= tDelta ) continue; puTCEdges[pNode->Id] = Nwk_ManDelayTraceTCEdges( pNtk, pNode, tDelta, fUseLutLib ); } if ( fVerbose ) { Counter = CounterRes = 0; Nwk_ManForEachNode( pNtk, pNode, i ) { Nwk_ObjForEachFanin( pNode, pFanin, k ) if ( !Nwk_ObjIsCi(pFanin) && Nwk_ObjSlack(pFanin) < tDelta ) Counter++; CounterRes += Aig_WordCountOnes( puTCEdges[pNode->Id] ); } printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", Nwk_ManGetTotalFanins(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); } // start the resulting network pAig = Nwk_ManStrash( pNtk ); pAig->pEquivs = ABC_ALLOC( Aig_Obj_t *, 3 * Aig_ManObjNumMax(pAig) ); memset( pAig->pEquivs, 0, sizeof(Aig_Obj_t *) * 3 * Aig_ManObjNumMax(pAig) ); // collect nodes to be used for resynthesis Counter = CounterRes = 0; vTimeCries = Vec_PtrAlloc( 16 ); vTimeFanins = Vec_PtrAlloc( 16 ); Nwk_ManForEachNode( pNtk, pNode, i ) { if ( Nwk_ObjSlack(pNode) >= tDelta ) continue; // count the number of non-PI timing-critical nodes nTimeCris = 0; Nwk_ObjForEachFanin( pNode, pFanin, k ) if ( !Nwk_ObjIsCi(pFanin) && (puTCEdges[pNode->Id] & (1<Id] & (1<Id] & (1< Degree) ) if ( (Vec_PtrSize(vTimeCries) == 0 || Vec_PtrSize(vTimeCries) > Degree) ) continue; CounterRes++; // collect second generation nodes Vec_PtrClear( vTimeFanins ); Nwk_ObjForEachFanin( pNode, pFanin, k ) { if ( Nwk_ObjIsCi(pFanin) ) Vec_PtrPushUnique( vTimeFanins, pFanin ); else Nwk_ObjForEachFanin( pFanin, pFanin2, k2 ) Vec_PtrPushUnique( vTimeFanins, pFanin2 ); } // print the results if ( fVeryVerbose ) { printf( "%5d Node %5d : %d %2d %2d ", Counter, pNode->Id, nTimeCris, Vec_PtrSize(vTimeCries), Vec_PtrSize(vTimeFanins) ); Nwk_ObjForEachFanin( pNode, pFanin, k ) printf( "%d(%.2f)%s ", pFanin->Id, Nwk_ObjSlack(pFanin), (puTCEdges[pNode->Id] & (1< Degree ) continue; // order the fanins in the increasing order of criticalily if ( Vec_PtrSize(vTimeCries) > 1 ) { pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) { Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); } } if ( Vec_PtrSize(vTimeCries) > 2 ) { pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 2 ); if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) { Vec_PtrWriteEntry( vTimeCries, 1, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 2, pFanin ); } pFanin = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 0 ); pFanin2 = (Nwk_Obj_t *)Vec_PtrEntry( vTimeCries, 1 ); if ( Nwk_ObjSlack(pFanin) < Nwk_ObjSlack(pFanin2) ) { Vec_PtrWriteEntry( vTimeCries, 0, pFanin2 ); Vec_PtrWriteEntry( vTimeCries, 1, pFanin ); } } // add choice Aig_ManSpeedupNode( pNtk, pAig, pNode, vTimeFanins, vTimeCries ); } Vec_PtrFree( vTimeCries ); Vec_PtrFree( vTimeFanins ); ABC_FREE( puTCEdges ); if ( fVerbose ) printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", Nwk_ManNodeNum(pNtk), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); // remove invalid choice nodes Aig_ManForEachNode( pAig, pAnd, i ) if ( Aig_ObjEquiv(pAig, pAnd) ) { if ( Aig_ObjRefs(Aig_ObjEquiv(pAig, pAnd)) > 0 ) pAig->pEquivs[pAnd->Id] = NULL; } // put back the library if ( !fUseLutLib ) pNtk->pLutLib = pTempLib; if ( pTempTim ) { Tim_ManStop( pNtk->pManTime ); pNtk->pManTime = pTempTim; } // reconstruct the network pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); // reset levels Aig_ManChoiceLevel( pAig ); return pAig; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkStrash.c000066400000000000000000000113641300674244400235720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkStrash.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Performs structural hashing for the network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives AIG from the local functions of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManStrashNode_rec( Aig_Man_t * p, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Nwk_ManStrashNode_rec( p, Hop_ObjFanin0(pObj) ); Nwk_ManStrashNode_rec( p, Hop_ObjFanin1(pObj) ); pObj->pData = Aig_And( p, (Aig_Obj_t *)Hop_ObjChild0Copy(pObj), (Aig_Obj_t *)Hop_ObjChild1Copy(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Derives AIG from the local functions of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Nwk_ManStrashNode( Aig_Man_t * p, Nwk_Obj_t * pObj ) { Hop_Man_t * pMan = pObj->pMan->pManHop; Hop_Obj_t * pRoot = pObj->pFunc; Nwk_Obj_t * pFanin; int i; assert( Nwk_ObjIsNode(pObj) ); // check the constant case if ( Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) return Aig_NotCond( Aig_ManConst1(p), Hop_IsComplement(pRoot) ); // set elementary variables Nwk_ObjForEachFanin( pObj, pFanin, i ) Hop_IthVar(pMan, i)->pData = pFanin->pCopy; // strash the AIG of this node Nwk_ManStrashNode_rec( p, Hop_Regular(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); // return the final node return Aig_NotCond( (Aig_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Derives AIG from the logic network.] Description [Assumes topological ordering of nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Nwk_ManStrash( Nwk_Man_t * pNtk ) { Vec_Ptr_t * vObjs; Aig_Man_t * pMan; Aig_Obj_t * pObjNew; Nwk_Obj_t * pObj; int i, Level; pMan = Aig_ManStart( Nwk_ManGetAigNodeNum(pNtk) ); pMan->pName = Abc_UtilStrsav( pNtk->pName ); pMan->pSpec = Abc_UtilStrsav( pNtk->pSpec ); pMan->pManTime = Tim_ManDup( (Tim_Man_t *)pNtk->pManTime, 1 ); Tim_ManIncrementTravId( (Tim_Man_t *)pMan->pManTime ); Nwk_ManForEachObj( pNtk, pObj, i ) pObj->pCopy = NULL; // Nwk_ManForEachObj( pNtk, pObj, i ) vObjs = Nwk_ManDfs( pNtk ); Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i ) { if ( Nwk_ObjIsCi(pObj) ) { pObjNew = Aig_ObjCreateCi(pMan); Level = Tim_ManGetCiArrival( (Tim_Man_t *)pMan->pManTime, pObj->PioId ); Aig_ObjSetLevel( pObjNew, Level ); } else if ( Nwk_ObjIsCo(pObj) ) { pObjNew = Aig_ObjCreateCo( pMan, Aig_NotCond((Aig_Obj_t *)Nwk_ObjFanin0(pObj)->pCopy, pObj->fInvert) ); Level = Aig_ObjLevel( pObjNew ); Tim_ManSetCoArrival( (Tim_Man_t *)pMan->pManTime, pObj->PioId, (float)Level ); } else if ( Nwk_ObjIsNode(pObj) ) { pObjNew = Nwk_ManStrashNode( pMan, pObj ); } else assert( 0 ); pObj->pCopy = pObjNew; } Vec_PtrFree( vObjs ); Aig_ManCleanup( pMan ); Aig_ManSetRegNum( pMan, 0 ); return pMan; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkTiming.c000066400000000000000000000724231300674244400235600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkTiming.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Manipulation of timing information.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Cleans timing information for all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManCleanTiming( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj; int i; Nwk_ManForEachObj( pNtk, pObj, i ) { pObj->tArrival = pObj->tSlack = 0.0; pObj->tRequired = TIM_ETERNITY; } } /**Function************************************************************* Synopsis [Sorts the pins in the decreasing order of delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDelayTraceSortPins( Nwk_Obj_t * pNode, int * pPinPerm, float * pPinDelays ) { Nwk_Obj_t * pFanin; int i, j, best_i, temp; // start the trivial permutation and collect pin delays Nwk_ObjForEachFanin( pNode, pFanin, i ) { pPinPerm[i] = i; pPinDelays[i] = Nwk_ObjArrival(pFanin); } // 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 < Nwk_ObjFaninNum(pNode)-1; i++ ) { best_i = i; for ( j = i+1; j < Nwk_ObjFaninNum(pNode); 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( Nwk_ObjFaninNum(pNode) == 0 || pPinPerm[0] < Nwk_ObjFaninNum(pNode) ); for ( i = 1; i < Nwk_ObjFaninNum(pNode); i++ ) { assert( pPinPerm[i] < Nwk_ObjFaninNum(pNode) ); assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); } } /**Function************************************************************* Synopsis [Sorts the pins in the decreasing order of delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManWhereIsPin( Nwk_Obj_t * pFanout, Nwk_Obj_t * pFanin, int * pPinPerm ) { int i; for ( i = 0; i < Nwk_ObjFaninNum(pFanout); i++ ) if ( Nwk_ObjFanin(pFanout, pPinPerm[i]) == pFanin ) return i; return -1; } /**Function************************************************************* Synopsis [Computes the arrival times for the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Nwk_NodeComputeArrival( Nwk_Obj_t * pObj, int fUseSorting ) { If_LibLut_t * pLutLib = pObj->pMan->pLutLib; int pPinPerm[32]; float pPinDelays[32]; Nwk_Obj_t * pFanin; float tArrival, * pDelays; int k; assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) || Nwk_ObjIsCo(pObj) ); if ( Nwk_ObjIsCi(pObj) ) return Nwk_ObjArrival(pObj); if ( Nwk_ObjIsCo(pObj) ) return Nwk_ObjArrival( Nwk_ObjFanin0(pObj) ); tArrival = -TIM_ETERNITY; if ( pLutLib == NULL ) { Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( tArrival < Nwk_ObjArrival(pFanin) + 1.0 ) tArrival = Nwk_ObjArrival(pFanin) + 1.0; } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( tArrival < Nwk_ObjArrival(pFanin) + pDelays[0] ) tArrival = Nwk_ObjArrival(pFanin) + pDelays[0]; } else { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; if ( fUseSorting ) { Nwk_ManDelayTraceSortPins( pObj, pPinPerm, pPinDelays ); Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( tArrival < Nwk_ObjArrival(Nwk_ObjFanin(pObj,pPinPerm[k])) + pDelays[k] ) tArrival = Nwk_ObjArrival(Nwk_ObjFanin(pObj,pPinPerm[k])) + pDelays[k]; } else { Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( tArrival < Nwk_ObjArrival(pFanin) + pDelays[k] ) tArrival = Nwk_ObjArrival(pFanin) + pDelays[k]; } } if ( Nwk_ObjFaninNum(pObj) == 0 ) tArrival = 0.0; return tArrival; } /**Function************************************************************* Synopsis [Computes the required times for the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Nwk_NodeComputeRequired( Nwk_Obj_t * pObj, int fUseSorting ) { If_LibLut_t * pLutLib = pObj->pMan->pLutLib; int pPinPerm[32]; float pPinDelays[32]; Nwk_Obj_t * pFanout; float tRequired, tDelay, * pDelays; int k, iFanin; assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCi(pObj) || Nwk_ObjIsCo(pObj) ); if ( Nwk_ObjIsCo(pObj) ) return Nwk_ObjRequired(pObj); tRequired = TIM_ETERNITY; if ( pLutLib == NULL ) { Nwk_ObjForEachFanout( pObj, pFanout, k ) { tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : 1.0; if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) tRequired = Nwk_ObjRequired(pFanout) - tDelay; } } else if ( !pLutLib->fVarPinDelays ) { Nwk_ObjForEachFanout( pObj, pFanout, k ) { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[0]; if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) tRequired = Nwk_ObjRequired(pFanout) - tDelay; } } else { if ( fUseSorting ) { Nwk_ObjForEachFanout( pObj, pFanout, k ) { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; Nwk_ManDelayTraceSortPins( pFanout, pPinPerm, pPinDelays ); iFanin = Nwk_ManWhereIsPin( pFanout, pObj, pPinPerm ); assert( Nwk_ObjFanin(pFanout,pPinPerm[iFanin]) == pObj ); tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) tRequired = Nwk_ObjRequired(pFanout) - tDelay; } } else { Nwk_ObjForEachFanout( pObj, pFanout, k ) { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pFanout)]; iFanin = Nwk_ObjFindFanin( pFanout, pObj ); assert( Nwk_ObjFanin(pFanout,iFanin) == pObj ); tDelay = Nwk_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; if ( tRequired > Nwk_ObjRequired(pFanout) - tDelay ) tRequired = Nwk_ObjRequired(pFanout) - tDelay; } } } return tRequired; } /**Function************************************************************* Synopsis [Propagates the required times through the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Nwk_NodePropagateRequired( Nwk_Obj_t * pObj, int fUseSorting ) { If_LibLut_t * pLutLib = pObj->pMan->pLutLib; int pPinPerm[32]; float pPinDelays[32]; Nwk_Obj_t * pFanin; float tRequired = 0.0; // Suppress "might be used uninitialized" float * pDelays; int k; assert( Nwk_ObjIsNode(pObj) ); if ( pLutLib == NULL ) { tRequired = Nwk_ObjRequired(pObj) - (float)1.0; Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( Nwk_ObjRequired(pFanin) > tRequired ) Nwk_ObjSetRequired( pFanin, tRequired ); } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; tRequired = Nwk_ObjRequired(pObj) - pDelays[0]; Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( Nwk_ObjRequired(pFanin) > tRequired ) Nwk_ObjSetRequired( pFanin, tRequired ); } else { pDelays = pLutLib->pLutDelays[Nwk_ObjFaninNum(pObj)]; if ( fUseSorting ) { Nwk_ManDelayTraceSortPins( pObj, pPinPerm, pPinDelays ); Nwk_ObjForEachFanin( pObj, pFanin, k ) { tRequired = Nwk_ObjRequired(pObj) - pDelays[k]; if ( Nwk_ObjRequired(Nwk_ObjFanin(pObj,pPinPerm[k])) > tRequired ) Nwk_ObjSetRequired( Nwk_ObjFanin(pObj,pPinPerm[k]), tRequired ); } } else { Nwk_ObjForEachFanin( pObj, pFanin, k ) { tRequired = Nwk_ObjRequired(pObj) - pDelays[k]; if ( Nwk_ObjRequired(pFanin) > tRequired ) Nwk_ObjSetRequired( pFanin, tRequired ); } } } return tRequired; } /**Function************************************************************* Synopsis [Computes the delay trace of the given network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Nwk_ManDelayTraceLut( Nwk_Man_t * pNtk ) { Vec_Ptr_t * vObjs; int fUseSorting = 1; If_LibLut_t * pLutLib = pNtk->pLutLib; Vec_Ptr_t * vNodes; Nwk_Obj_t * pObj; float tArrival, tRequired, tSlack; int i; // get the library if ( pLutLib && pLutLib->LutMax < Nwk_ManGetFaninMax(pNtk) ) { printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", pLutLib->LutMax, Nwk_ManGetFaninMax(pNtk) ); return -TIM_ETERNITY; } // compute the reverse order of all objects vNodes = Nwk_ManDfsReverse( pNtk ); // initialize the arrival times Nwk_ManCleanTiming( pNtk ); // propagate arrival times if ( pNtk->pManTime ) Tim_ManIncrementTravId( pNtk->pManTime ); // Nwk_ManForEachObj( pNtk, pObj, i ) vObjs = Nwk_ManDfs( pNtk ); Vec_PtrForEachEntry( Nwk_Obj_t *, vObjs, pObj, i ) { tArrival = Nwk_NodeComputeArrival( pObj, fUseSorting ); if ( Nwk_ObjIsCi(pObj) && pNtk->pManTime ) tArrival = Tim_ManGetCiArrival( pNtk->pManTime, pObj->PioId ); if ( Nwk_ObjIsCo(pObj) && pNtk->pManTime ) Tim_ManSetCoArrival( pNtk->pManTime, pObj->PioId, tArrival ); Nwk_ObjSetArrival( pObj, tArrival ); } Vec_PtrFree( vObjs ); // get the latest arrival times tArrival = -TIM_ETERNITY; Nwk_ManForEachPo( pNtk, pObj, i ) if ( tArrival < Nwk_ObjArrival(pObj) ) tArrival = Nwk_ObjArrival(pObj); // initialize the required times if ( pNtk->pManTime ) { Tim_ManIncrementTravId( pNtk->pManTime ); Tim_ManInitPoRequiredAll( pNtk->pManTime, tArrival ); } else { Nwk_ManForEachCo( pNtk, pObj, i ) Nwk_ObjSetRequired( pObj, tArrival ); } // propagate the required times Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) { if ( Nwk_ObjIsNode(pObj) ) { Nwk_NodePropagateRequired( pObj, fUseSorting ); } else if ( Nwk_ObjIsCi(pObj) ) { if ( pNtk->pManTime ) Tim_ManSetCiRequired( pNtk->pManTime, pObj->PioId, Nwk_ObjRequired(pObj) ); } else if ( Nwk_ObjIsCo(pObj) ) { if ( pNtk->pManTime ) { tRequired = Tim_ManGetCoRequired( pNtk->pManTime, pObj->PioId ); Nwk_ObjSetRequired( pObj, tRequired ); } if ( Nwk_ObjRequired(Nwk_ObjFanin0(pObj)) > Nwk_ObjRequired(pObj) ) Nwk_ObjSetRequired( Nwk_ObjFanin0(pObj), Nwk_ObjRequired(pObj) ); } // set slack for this object tSlack = Nwk_ObjRequired(pObj) - Nwk_ObjArrival(pObj); assert( tSlack + 0.01 > 0.0 ); Nwk_ObjSetSlack( pObj, tSlack < 0.0 ? 0.0 : tSlack ); } Vec_PtrFree( vNodes ); return tArrival; } /**Function************************************************************* Synopsis [Computes the arrival times for the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManVerifyTiming( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj; float tArrival, tRequired; int i; Nwk_ManForEachObj( pNtk, pObj, i ) { if ( Nwk_ObjIsCi(pObj) && Nwk_ObjFanoutNum(pObj) == 0 ) continue; tArrival = Nwk_NodeComputeArrival( pObj, 1 ); tRequired = Nwk_NodeComputeRequired( pObj, 1 ); if ( !Nwk_ManTimeEqual( tArrival, Nwk_ObjArrival(pObj), (float)0.01 ) ) printf( "Nwk_ManVerifyTiming(): Object %d has different arrival time (%.2f) from computed (%.2f).\n", pObj->Id, Nwk_ObjArrival(pObj), tArrival ); if ( !Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pObj), (float)0.01 ) ) printf( "Nwk_ManVerifyTiming(): Object %d has different required time (%.2f) from computed (%.2f).\n", pObj->Id, Nwk_ObjRequired(pObj), tRequired ); } return 1; } /**Function************************************************************* Synopsis [Prints the delay trace for the given network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDelayTracePrint( Nwk_Man_t * pNtk ) { If_LibLut_t * pLutLib = pNtk->pLutLib; Nwk_Obj_t * pNode; int i, Nodes, * pCounters; float tArrival, tDelta, nSteps, Num; // get the library if ( pLutLib && pLutLib->LutMax < Nwk_ManGetFaninMax(pNtk) ) { printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", pLutLib->LutMax, Nwk_ManGetFaninMax(pNtk) ); return; } // decide how many steps nSteps = pLutLib ? 20 : Nwk_ManLevelMax(pNtk); pCounters = ABC_ALLOC( int, nSteps + 1 ); memset( pCounters, 0, sizeof(int)*(nSteps + 1) ); // perform delay trace tArrival = Nwk_ManDelayTraceLut( pNtk ); tDelta = tArrival / nSteps; // count how many nodes have slack in the corresponding intervals Nwk_ManForEachNode( pNtk, pNode, i ) { if ( Nwk_ObjFaninNum(pNode) == 0 ) continue; Num = Nwk_ObjSlack(pNode) / tDelta; if ( Num > nSteps ) continue; assert( Num >=0 && Num <= nSteps ); pCounters[(int)Num]++; } // print the results 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/Nwk_ManNodeNum(pNtk) ); } ABC_FREE( pCounters ); } /**Function************************************************************* Synopsis [Inserts node into the queue of nodes sorted by level.] Description [The inserted node should not go before the current position given by iCurrent. If the arrival times are computed, the nodes are sorted in the increasing order of levels. If the required times are computed, the nodes are sorted in the decreasing order of levels.] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_NodeUpdateAddToQueue( Vec_Ptr_t * vQueue, Nwk_Obj_t * pObj, int iCurrent, int fArrival ) { Nwk_Obj_t * pTemp1, * pTemp2; int i; Vec_PtrPush( vQueue, pObj ); for ( i = Vec_PtrSize(vQueue) - 1; i > iCurrent + 1; i-- ) { pTemp1 = (Nwk_Obj_t *)vQueue->pArray[i]; pTemp2 = (Nwk_Obj_t *)vQueue->pArray[i-1]; if ( fArrival ) { if ( Nwk_ObjLevel(pTemp2) <= Nwk_ObjLevel(pTemp1) ) break; } else { if ( Nwk_ObjLevel(pTemp2) >= Nwk_ObjLevel(pTemp1) ) break; } vQueue->pArray[i-1] = pTemp1; vQueue->pArray[i] = pTemp2; } // verification for ( i = iCurrent + 1; i < Vec_PtrSize(vQueue) - 1; i++ ) { pTemp1 = (Nwk_Obj_t *)vQueue->pArray[i]; pTemp2 = (Nwk_Obj_t *)vQueue->pArray[i+1]; if ( fArrival ) assert( Nwk_ObjLevel(pTemp1) <= Nwk_ObjLevel(pTemp2) ); else assert( Nwk_ObjLevel(pTemp1) >= Nwk_ObjLevel(pTemp2) ); } } /**Function************************************************************* Synopsis [Incrementally updates arrival times of the node.] Description [Supports variable-pin delay model and white-boxes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_NodeUpdateArrival( Nwk_Obj_t * pObj ) { Tim_Man_t * pManTime = pObj->pMan->pManTime; Vec_Ptr_t * vQueue = pObj->pMan->vTemp; Nwk_Obj_t * pTemp; Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" float tArrival; int iCur, k, iBox, iTerm1, nTerms; assert( Nwk_ObjIsNode(pObj) ); // verify the arrival time tArrival = Nwk_NodeComputeArrival( pObj, 1 ); assert( Nwk_ManTimeLess( tArrival, Nwk_ObjRequired(pObj), (float)0.01 ) ); // initialize the queue with the node Vec_PtrClear( vQueue ); Vec_PtrPush( vQueue, pObj ); pObj->MarkA = 1; // process objects if ( pManTime ) Tim_ManIncrementTravId( pManTime ); Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) { pTemp->MarkA = 0; tArrival = Nwk_NodeComputeArrival( pTemp, 1 ); if ( Nwk_ObjIsCi(pTemp) && pManTime ) tArrival = Tim_ManGetCiArrival( pManTime, pTemp->PioId ); if ( Nwk_ManTimeEqual( tArrival, Nwk_ObjArrival(pTemp), (float)0.01 ) ) continue; Nwk_ObjSetArrival( pTemp, tArrival ); // add the fanouts to the queue if ( Nwk_ObjIsCo(pTemp) ) { if ( pManTime ) { iBox = Tim_ManBoxForCo( pManTime, pTemp->PioId ); if ( iBox >= 0 ) // this CO is an input of the box { // it may happen that a box-input (CO) was already marked as visited // when some other box-input of the same box was visited - here we undo this if ( Tim_ManIsCoTravIdCurrent( pManTime, pTemp->PioId ) ) Tim_ManSetPreviousTravIdBoxInputs( pManTime, iBox ); Tim_ManSetCoArrival( pManTime, pTemp->PioId, tArrival ); Tim_ManSetCurrentTravIdBoxInputs( pManTime, iBox ); iTerm1 = Tim_ManBoxOutputFirst( pManTime, iBox ); nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pNext = Nwk_ManCi(pNext->pMan, iTerm1 + k); if ( pNext->MarkA ) continue; Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); pNext->MarkA = 1; } } } } else { Nwk_ObjForEachFanout( pTemp, pNext, k ) { if ( pNext->MarkA ) continue; Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); pNext->MarkA = 1; } } } } /**Function************************************************************* Synopsis [Incrementally updates required times of the node.] Description [Supports variable-pin delay model and white-boxes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_NodeUpdateRequired( Nwk_Obj_t * pObj ) { Tim_Man_t * pManTime = pObj->pMan->pManTime; Vec_Ptr_t * vQueue = pObj->pMan->vTemp; Nwk_Obj_t * pTemp; Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" float tRequired; int iCur, k, iBox, iTerm1, nTerms; assert( Nwk_ObjIsNode(pObj) ); // make sure the node's required time remained the same tRequired = Nwk_NodeComputeRequired( pObj, 1 ); assert( Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pObj), (float)0.01 ) ); // initialize the queue with the node's faninsa and the old node's fanins Vec_PtrClear( vQueue ); Nwk_ObjForEachFanin( pObj, pNext, k ) { if ( pNext->MarkA ) continue; Nwk_NodeUpdateAddToQueue( vQueue, pNext, -1, 0 ); pNext->MarkA = 1; } // process objects if ( pManTime ) Tim_ManIncrementTravId( pManTime ); Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) { pTemp->MarkA = 0; tRequired = Nwk_NodeComputeRequired( pTemp, 1 ); if ( Nwk_ObjIsCo(pTemp) && pManTime ) tRequired = Tim_ManGetCoRequired( pManTime, pTemp->PioId ); if ( Nwk_ManTimeEqual( tRequired, Nwk_ObjRequired(pTemp), (float)0.01 ) ) continue; Nwk_ObjSetRequired( pTemp, tRequired ); // add the fanins to the queue if ( Nwk_ObjIsCi(pTemp) ) { if ( pManTime ) { iBox = Tim_ManBoxForCi( pManTime, pTemp->PioId ); if ( iBox >= 0 ) // this CI is an output of the box { // it may happen that a box-output (CI) was already marked as visited // when some other box-output of the same box was visited - here we undo this if ( Tim_ManIsCiTravIdCurrent( pManTime, pTemp->PioId ) ) Tim_ManSetPreviousTravIdBoxOutputs( pManTime, iBox ); Tim_ManSetCiRequired( pManTime, pTemp->PioId, tRequired ); Tim_ManSetCurrentTravIdBoxOutputs( pManTime, iBox ); iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); nTerms = Tim_ManBoxInputNum( pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pNext = Nwk_ManCo(pNext->pMan, iTerm1 + k); if ( pNext->MarkA ) continue; Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 0 ); pNext->MarkA = 1; } } } } else { Nwk_ObjForEachFanin( pTemp, pNext, k ) { if ( pNext->MarkA ) continue; Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 0 ); pNext->MarkA = 1; } } } } /**Function************************************************************* Synopsis [Computes the level of the node using its fanin levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ObjLevelNew( Nwk_Obj_t * pObj ) { Tim_Man_t * pManTime = pObj->pMan->pManTime; Nwk_Obj_t * pFanin; int i, iBox, iTerm1, nTerms, Level = 0; if ( Nwk_ObjIsCi(pObj) || Nwk_ObjIsLatch(pObj) ) { if ( pManTime ) { iBox = Tim_ManBoxForCi( pManTime, pObj->PioId ); if ( iBox >= 0 ) // this CI is an output of the box { iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); nTerms = Tim_ManBoxInputNum( pManTime, iBox ); for ( i = 0; i < nTerms; i++ ) { pFanin = Nwk_ManCo(pObj->pMan, iTerm1 + i); Level = Abc_MaxInt( Level, Nwk_ObjLevel(pFanin) ); } Level++; } } return Level; } assert( Nwk_ObjIsNode(pObj) || Nwk_ObjIsCo(pObj) ); Nwk_ObjForEachFanin( pObj, pFanin, i ) Level = Abc_MaxInt( Level, Nwk_ObjLevel(pFanin) ); return Level + (Nwk_ObjIsNode(pObj) && Nwk_ObjFaninNum(pObj) > 0); } /**Function************************************************************* Synopsis [Incrementally updates level of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManUpdateLevel( Nwk_Obj_t * pObj ) { Tim_Man_t * pManTime = pObj->pMan->pManTime; Vec_Ptr_t * vQueue = pObj->pMan->vTemp; Nwk_Obj_t * pTemp; Nwk_Obj_t * pNext = NULL; // Suppress "might be used uninitialized" int LevelNew, iCur, k, iBox, iTerm1, nTerms; assert( Nwk_ObjIsNode(pObj) ); // initialize the queue with the node Vec_PtrClear( vQueue ); Vec_PtrPush( vQueue, pObj ); pObj->MarkA = 1; // process objects Vec_PtrForEachEntry( Nwk_Obj_t *, vQueue, pTemp, iCur ) { pTemp->MarkA = 0; LevelNew = Nwk_ObjLevelNew( pTemp ); if ( LevelNew == Nwk_ObjLevel(pTemp) ) continue; Nwk_ObjSetLevel( pTemp, LevelNew ); // add the fanouts to the queue if ( Nwk_ObjIsCo(pTemp) ) { if ( pManTime ) { iBox = Tim_ManBoxForCo( pManTime, pTemp->PioId ); if ( iBox >= 0 ) // this is not a true PO { Tim_ManSetCurrentTravIdBoxInputs( pManTime, iBox ); iTerm1 = Tim_ManBoxOutputFirst( pManTime, iBox ); nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pNext = Nwk_ManCi(pNext->pMan, iTerm1 + k); if ( pNext->MarkA ) continue; Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); pNext->MarkA = 1; } } } } else { Nwk_ObjForEachFanout( pTemp, pNext, k ) { if ( pNext->MarkA ) continue; Nwk_NodeUpdateAddToQueue( vQueue, pNext, iCur, 1 ); pNext->MarkA = 1; } } } } /**Function************************************************************* Synopsis [Computes the level of the node using its fanin levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManVerifyLevel( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj; int LevelNew, i; Nwk_ManForEachObj( pNtk, pObj, i ) { assert( pObj->MarkA == 0 ); LevelNew = Nwk_ObjLevelNew( pObj ); if ( Nwk_ObjLevel(pObj) != LevelNew ) { printf( "Object %6d: Mismatch betweeh levels: Actual = %d. Correct = %d.\n", i, Nwk_ObjLevel(pObj), LevelNew ); } } return 1; } /**Function************************************************************* Synopsis [Replaces the node and incrementally updates levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManUpdate( Nwk_Obj_t * pObj, Nwk_Obj_t * pObjNew, Vec_Vec_t * vLevels ) { assert( pObj->pMan == pObjNew->pMan ); assert( pObj != pObjNew ); assert( Nwk_ObjFanoutNum(pObj) > 0 ); assert( Nwk_ObjIsNode(pObj) && !Nwk_ObjIsCo(pObjNew) ); // transfer fanouts to the old node Nwk_ObjTransferFanout( pObj, pObjNew ); // transfer the timing information // (this is needed because updating level happens if the level has changed; // when we set the old level, it will be recomputed by the level updating // procedure, which will update level of other nodes if there is a difference) pObjNew->Level = pObj->Level; pObjNew->tArrival = pObj->tArrival; pObjNew->tRequired = pObj->tRequired; // update required times of the old fanins pObj->tRequired = TIM_ETERNITY; Nwk_NodeUpdateRequired( pObj ); // remove the old node Nwk_ManDeleteNode_rec( pObj ); // update the information of the new node Nwk_ManUpdateLevel( pObjNew ); Nwk_NodeUpdateArrival( pObjNew ); Nwk_NodeUpdateRequired( pObjNew ); //Nwk_ManVerifyTiming( pObjNew->pMan ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwkUtil.c000066400000000000000000000461421300674244400232450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwkUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Logic network representation.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwkUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "nwk.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Increments the current traversal ID of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManIncrementTravId( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pObj; int i; if ( pNtk->nTravIds >= (1<<26)-1 ) { pNtk->nTravIds = 0; Nwk_ManForEachObj( pNtk, pObj, i ) pObj->TravId = 0; } pNtk->nTravIds++; } /**Function************************************************************* Synopsis [Reads the maximum number of fanins of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManGetFaninMax( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, nFaninsMax = 0; Nwk_ManForEachNode( pNtk, pNode, i ) { if ( nFaninsMax < Nwk_ObjFaninNum(pNode) ) nFaninsMax = Nwk_ObjFaninNum(pNode); } return nFaninsMax; } /**Function************************************************************* Synopsis [Reads the total number of all fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManGetTotalFanins( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, nFanins = 0; Nwk_ManForEachNode( pNtk, pNode, i ) nFanins += Nwk_ObjFaninNum(pNode); return nFanins; } /**Function************************************************************* Synopsis [Returns the number of true PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPiNum( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, Counter = 0; Nwk_ManForEachCi( pNtk, pNode, i ) Counter += Nwk_ObjIsPi( pNode ); return Counter; } /**Function************************************************************* Synopsis [Returns the number of true POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManPoNum( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, Counter = 0; Nwk_ManForEachCo( pNtk, pNode, i ) Counter += Nwk_ObjIsPo( pNode ); return Counter; } /**Function************************************************************* Synopsis [Reads the number of AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManGetAigNodeNum( Nwk_Man_t * pNtk ) { Nwk_Obj_t * pNode; int i, nNodes = 0; Nwk_ManForEachNode( pNtk, pNode, i ) { if ( pNode->pFunc == NULL ) { printf( "Nwk_ManGetAigNodeNum(): Local AIG of node %d is not assigned.\n", pNode->Id ); continue; } if ( Nwk_ObjFaninNum(pNode) < 2 ) continue; nNodes += Hop_DagSize( pNode->pFunc ); } return nNodes; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in increasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_NodeCompareLevelsIncrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ) { int Diff = (*pp1)->Level - (*pp2)->Level; 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 Nwk_NodeCompareLevelsDecrease( Nwk_Obj_t ** pp1, Nwk_Obj_t ** pp2 ) { int Diff = (*pp1)->Level - (*pp2)->Level; if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Prints the objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjPrint( Nwk_Obj_t * pObj ) { Nwk_Obj_t * pNext; int i; printf( "ObjId = %5d. ", pObj->Id ); if ( Nwk_ObjIsPi(pObj) ) printf( "PI" ); if ( Nwk_ObjIsPo(pObj) ) printf( "PO" ); if ( Nwk_ObjIsNode(pObj) ) printf( "Node" ); printf( " Fanins = " ); Nwk_ObjForEachFanin( pObj, pNext, i ) printf( "%d ", pNext->Id ); printf( " Fanouts = " ); Nwk_ObjForEachFanout( pObj, pNext, i ) printf( "%d ", pNext->Id ); printf( "\n" ); } /**Function************************************************************* Synopsis [Dumps the BLIF file for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManDumpBlif( Nwk_Man_t * pNtk, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ) { FILE * pFile; Vec_Ptr_t * vNodes; Vec_Int_t * vTruth; Vec_Int_t * vCover; Nwk_Obj_t * pObj, * pFanin; Aig_MmFlex_t * pMem; char * pSop = NULL; unsigned * pTruth; int i, k, nDigits; if ( Nwk_ManPoNum(pNtk) == 0 ) { printf( "Nwk_ManDumpBlif(): Network does not have POs.\n" ); return; } // collect nodes in the DFS order nDigits = Abc_Base10Log( Nwk_ManObjNumMax(pNtk) ); // write the file pFile = fopen( pFileName, "w" ); fprintf( pFile, "# BLIF file written by procedure Nwk_ManDumpBlif()\n" ); // fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); fprintf( pFile, ".model %s\n", pNtk->pName ); // write PIs fprintf( pFile, ".inputs" ); Nwk_ManForEachCi( pNtk, pObj, i ) if ( vPiNames ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, i) ); else fprintf( pFile, " n%0*d", nDigits, pObj->Id ); fprintf( pFile, "\n" ); // write POs fprintf( pFile, ".outputs" ); Nwk_ManForEachCo( pNtk, pObj, i ) if ( vPoNames ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, i) ); else fprintf( pFile, " n%0*d", nDigits, pObj->Id ); fprintf( pFile, "\n" ); // write nodes pMem = Aig_MmFlexStart(); vTruth = Vec_IntAlloc( 1 << 16 ); vCover = Vec_IntAlloc( 1 << 16 ); vNodes = Nwk_ManDfs( pNtk ); Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pObj, i ) { if ( !Nwk_ObjIsNode(pObj) ) continue; // derive SOP for the AIG pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); if ( Hop_IsComplement(pObj->pFunc) ) Kit_TruthNot( pTruth, pTruth, Nwk_ObjFaninNum(pObj) ); pSop = Kit_PlaFromTruth( pMem, pTruth, Nwk_ObjFaninNum(pObj), vCover ); // write the node fprintf( pFile, ".names" ); if ( !Kit_TruthIsConst0(pTruth, Nwk_ObjFaninNum(pObj)) && !Kit_TruthIsConst1(pTruth, Nwk_ObjFaninNum(pObj)) ) { Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( vPiNames && Nwk_ObjIsPi(pFanin) ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(pFanin)) ); else fprintf( pFile, " n%0*d", nDigits, pFanin->Id ); } fprintf( pFile, " n%0*d\n", nDigits, pObj->Id ); // write the function fprintf( pFile, "%s", pSop ); } Vec_IntFree( vCover ); Vec_IntFree( vTruth ); Vec_PtrFree( vNodes ); Aig_MmFlexStop( pMem, 0 ); // write POs Nwk_ManForEachCo( pNtk, pObj, i ) { fprintf( pFile, ".names" ); if ( vPiNames && Nwk_ObjIsPi(Nwk_ObjFanin0(pObj)) ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Nwk_ObjPioNum(Nwk_ObjFanin0(pObj))) ); else fprintf( pFile, " n%0*d", nDigits, Nwk_ObjFanin0(pObj)->Id ); if ( vPoNames ) fprintf( pFile, " %s\n", (char*)Vec_PtrEntry(vPoNames, Nwk_ObjPioNum(pObj)) ); else fprintf( pFile, " n%0*d\n", nDigits, pObj->Id ); fprintf( pFile, "%d 1\n", !pObj->fInvert ); } fprintf( pFile, ".end\n\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Prints the distribution of fanins/fanouts in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManPrintFanioNew( Nwk_Man_t * pNtk ) { char Buffer[100]; Nwk_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; Nwk_ManForEachNode( pNtk, pNode, i ) { nFanins = Nwk_ObjFaninNum(pNode); nFanouts = Nwk_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 Nwk_ManForEachNode( pNtk, pNode, i ) { nFanins = Nwk_ObjFaninNum(pNode); nFanouts = Nwk_ObjFanoutNum(pNode); // nFanouts = Nwk_NodeMffcSize(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/Nwk_ManNodeNum(pNtk), nFanoutsMax, 1.0*nFanoutsAll/Nwk_ManNodeNum(pNtk) ); } /**Function************************************************************* Synopsis [Cleans the temporary marks of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManCleanMarks( Nwk_Man_t * pMan ) { Nwk_Obj_t * pObj; int i; Nwk_ManForEachObj( pMan, pObj, i ) pObj->MarkA = pObj->MarkB = 0; } /**Function************************************************************* Synopsis [Minimizes the support of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManMinimumBaseNode( Nwk_Obj_t * pObj, Vec_Int_t * vTruth, int fVerbose ) { unsigned * pTruth; Nwk_Obj_t * pFanin, * pObjNew; Nwk_Man_t * pNtk = pObj->pMan; int uSupp, nSuppSize, k, Counter = 0; pTruth = Hop_ManConvertAigToTruth( pNtk->pManHop, Hop_Regular(pObj->pFunc), Nwk_ObjFaninNum(pObj), vTruth, 0 ); nSuppSize = Kit_TruthSupportSize(pTruth, Nwk_ObjFaninNum(pObj)); if ( nSuppSize == Nwk_ObjFaninNum(pObj) ) return 0; Counter++; uSupp = Kit_TruthSupport( pTruth, Nwk_ObjFaninNum(pObj) ); // create new node with the given support pObjNew = Nwk_ManCreateNode( pNtk, nSuppSize, Nwk_ObjFanoutNum(pObj) ); Nwk_ObjForEachFanin( pObj, pFanin, k ) if ( uSupp & (1 << k) ) Nwk_ObjAddFanin( pObjNew, pFanin ); pObjNew->pFunc = Hop_Remap( pNtk->pManHop, pObj->pFunc, uSupp, Nwk_ObjFaninNum(pObj) ); if ( fVerbose ) printf( "Reducing node %d fanins from %d to %d.\n", pObj->Id, Nwk_ObjFaninNum(pObj), Nwk_ObjFaninNum(pObjNew) ); Nwk_ObjReplace( pObj, pObjNew ); return 1; } /**Function************************************************************* Synopsis [Minimizes the support of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nwk_ManMinimumBaseInt( Nwk_Man_t * pNtk, int fVerbose ) { Vec_Int_t * vTruth; Nwk_Obj_t * pObj; int i, Counter = 0; vTruth = Vec_IntAlloc( 1 << 16 ); Nwk_ManForEachNode( pNtk, pObj, i ) Counter += Nwk_ManMinimumBaseNode( pObj, vTruth, fVerbose ); if ( fVerbose && Counter ) printf( "Support minimization reduced support of %d nodes.\n", Counter ); Vec_IntFree( vTruth ); return Counter; } /**Function************************************************************* Synopsis [Minimizes the support of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMinimumBaseRec( Nwk_Man_t * pNtk, int fVerbose ) { int i; abctime clk = Abc_Clock(); for ( i = 0; Nwk_ManMinimumBaseInt( pNtk, fVerbose ); i++ ); ABC_PRT( "Minbase", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Minimizes the support of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManMinimumBase( Nwk_Man_t * pNtk, int fVerbose ) { Vec_Int_t * vTruth; Nwk_Obj_t * pObj; int i, Counter = 0; vTruth = Vec_IntAlloc( 1 << 16 ); Nwk_ManForEachNode( pNtk, pObj, i ) Counter += Nwk_ManMinimumBaseNode( pObj, vTruth, fVerbose ); if ( fVerbose && Counter ) printf( "Support minimization reduced support of %d nodes.\n", Counter ); Vec_IntFree( vTruth ); } /**Function************************************************************* Synopsis [Minimizes the support of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManRemoveDupFaninsNode( Nwk_Obj_t * pObj, int iFan0, int iFan1, Vec_Int_t * vTruth ) { Hop_Man_t * pManHop = pObj->pMan->pManHop; // Nwk_Obj_t * pFanin0 = pObj->pFanio[iFan0]; // Nwk_Obj_t * pFanin1 = pObj->pFanio[iFan1]; assert( pObj->pFanio[iFan0] == pObj->pFanio[iFan1] ); pObj->pFunc = Hop_Compose( pManHop, pObj->pFunc, Hop_IthVar(pManHop,iFan0), iFan1 ); Nwk_ManMinimumBaseNode( pObj, vTruth, 0 ); } /**Function************************************************************* Synopsis [Minimizes the support of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ManRemoveDupFanins( Nwk_Man_t * pNtk, int fVerbose ) { Vec_Int_t * vTruth; Nwk_Obj_t * pObj; int i, k, m, fFound; // check if the nodes have duplicated fanins vTruth = Vec_IntAlloc( 1 << 16 ); Nwk_ManForEachNode( pNtk, pObj, i ) { fFound = 0; for ( k = 0; k < pObj->nFanins; k++ ) { for ( m = k + 1; m < pObj->nFanins; m++ ) if ( pObj->pFanio[k] == pObj->pFanio[m] ) { if ( fVerbose ) printf( "Removing duplicated fanins of node %d (fanins %d and %d).\n", pObj->Id, pObj->pFanio[k]->Id, pObj->pFanio[m]->Id ); Nwk_ManRemoveDupFaninsNode( pObj, k, m, vTruth ); fFound = 1; break; } if ( fFound ) break; } } Vec_IntFree( vTruth ); // Nwk_ManMinimumBase( pNtk, fVerbose ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/nwk/nwk_.c000066400000000000000000000026441300674244400225450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [nwk_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Netlist representation.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: nwk_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "nwk.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/000077500000000000000000000000001300674244400214275ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/module.make000066400000000000000000000002741300674244400235560ustar00rootroot00000000000000SRC += src/opt/res/resCore.c \ src/opt/res/resDivs.c \ src/opt/res/resFilter.c \ src/opt/res/resSat.c \ src/opt/res/resSim.c \ src/opt/res/resStrash.c \ src/opt/res/resWin.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/res.h000066400000000000000000000052541300674244400223770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [res.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: res.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__res__res_h #define ABC__opt__res__res_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Res_Par_t_ Res_Par_t; struct Res_Par_t_ { // general parameters int nWindow; // window size int nGrowthLevel; // the maximum allowed growth in level after one iteration of resynthesis int nSimWords; // the number of simulation words int nCands; // the number of candidates to try int fArea; // performs optimization for area int fDelay; // performs optimization for delay int fVerbose; // enable basic stats int fVeryVerbose; // enable detailed stats }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== resCore.c ==========================================================*/ extern int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resCore.c000066400000000000000000000345111300674244400232010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Top-level resynthesis procedure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resCore.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "resInt.h" #include "bool/kit/kit.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Res_Man_t_ Res_Man_t; struct Res_Man_t_ { // general parameters Res_Par_t * pPars; // specialized manager Res_Win_t * pWin; // windowing manager Abc_Ntk_t * pAig; // the strashed window Res_Sim_t * pSim; // simulation manager Sto_Man_t * pCnf; // the CNF of the SAT problem Int_Man_t * pMan; // interpolation manager; Vec_Int_t * vMem; // memory for intermediate SOPs Vec_Vec_t * vResubs; // resubstitution candidates of the AIG Vec_Vec_t * vResubsW; // resubstitution candidates of the window Vec_Vec_t * vLevels; // levelized structure for updating // statistics int nWins; // the number of windows tried int nWinNodes; // the total number of window nodes int nDivNodes; // the total number of divisors int nWinsTriv; // the total number of trivial windows int nWinsUsed; // the total number of useful windows (with at least one candidate) int nConstsUsed; // the total number of constant nodes under ODC int nCandSets; // the total number of candidates int nProvedSets; // the total number of proved groups int nSimEmpty; // the empty simulation info int nTotalNets; // the total number of nets int nTotalNodes; // the total number of nodess int nTotalNets2; // the total number of nets int nTotalNodes2; // the total number of nodess // runtime abctime timeWin; // windowing abctime timeDiv; // divisors abctime timeAig; // strashing abctime timeSim; // simulation abctime timeCand; // resubstitution candidates abctime timeSatTotal; // SAT solving total abctime timeSatSat; // SAT solving (sat calls) abctime timeSatUnsat; // SAT solving (unsat calls) abctime timeSatSim; // SAT solving (simulation) abctime timeInt; // interpolation abctime timeUpd; // updating abctime timeTotal; // total runtime }; extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); extern abctime s_ResynTime; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocate resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Res_Man_t * Res_ManAlloc( Res_Par_t * pPars ) { Res_Man_t * p; p = ABC_ALLOC( Res_Man_t, 1 ); memset( p, 0, sizeof(Res_Man_t) ); assert( pPars->nWindow > 0 && pPars->nWindow < 100 ); assert( pPars->nCands > 0 && pPars->nCands < 100 ); p->pPars = pPars; p->pWin = Res_WinAlloc(); p->pSim = Res_SimAlloc( pPars->nSimWords ); p->pMan = Int_ManAlloc(); p->vMem = Vec_IntAlloc( 0 ); p->vResubs = Vec_VecStart( pPars->nCands ); p->vResubsW = Vec_VecStart( pPars->nCands ); p->vLevels = Vec_VecStart( 32 ); return p; } /**Function************************************************************* Synopsis [Deallocate resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_ManFree( Res_Man_t * p ) { if ( p->pPars->fVerbose ) { printf( "Reduction in nodes = %5d. (%.2f %%) ", p->nTotalNodes-p->nTotalNodes2, 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes ); printf( "Reduction in edges = %5d. (%.2f %%) ", p->nTotalNets-p->nTotalNets2, 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets ); printf( "\n" ); printf( "Winds = %d. ", p->nWins ); printf( "Nodes = %d. (Ave = %5.1f) ", p->nWinNodes, 1.0*p->nWinNodes/p->nWins ); printf( "Divs = %d. (Ave = %5.1f) ", p->nDivNodes, 1.0*p->nDivNodes/p->nWins ); printf( "\n" ); printf( "WinsTriv = %d. ", p->nWinsTriv ); printf( "SimsEmpt = %d. ", p->nSimEmpty ); printf( "Const = %d. ", p->nConstsUsed ); printf( "WindUsed = %d. ", p->nWinsUsed ); printf( "Cands = %d. ", p->nCandSets ); printf( "Proved = %d.", p->nProvedSets ); printf( "\n" ); ABC_PRTP( "Windowing ", p->timeWin, p->timeTotal ); ABC_PRTP( "Divisors ", p->timeDiv, p->timeTotal ); ABC_PRTP( "Strashing ", p->timeAig, p->timeTotal ); ABC_PRTP( "Simulation ", p->timeSim, p->timeTotal ); ABC_PRTP( "Candidates ", p->timeCand, p->timeTotal ); ABC_PRTP( "SAT solver ", p->timeSatTotal, p->timeTotal ); ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); ABC_PRTP( " simul ", p->timeSatSim, p->timeTotal ); ABC_PRTP( "Interpol ", p->timeInt, p->timeTotal ); ABC_PRTP( "Undating ", p->timeUpd, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); } Res_WinFree( p->pWin ); if ( p->pAig ) Abc_NtkDelete( p->pAig ); Res_SimFree( p->pSim ); if ( p->pCnf ) Sto_ManFree( p->pCnf ); Int_ManFree( p->pMan ); Vec_IntFree( p->vMem ); Vec_VecFree( p->vResubs ); Vec_VecFree( p->vResubsW ); Vec_VecFree( p->vLevels ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Incrementally updates level of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels ) { Abc_Obj_t * pObjNew, * pFanin; int k; // create the new node pObjNew = Abc_NtkCreateNode( pObj->pNtk ); pObjNew->pData = pFunc; Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pFanin, k ) Abc_ObjAddFanin( pObjNew, pFanin ); // replace the old node by the new node //printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj ); //printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew ); // update the level of the node Abc_NtkUpdate( pObj, pObjNew, vLevels ); } /**Function************************************************************* Synopsis [Entrace into the resynthesis package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars ) { ProgressBar * pProgress; Res_Man_t * p; Abc_Obj_t * pObj; Hop_Obj_t * pFunc; Kit_Graph_t * pGraph; Vec_Ptr_t * vFanins; unsigned * puTruth; int i, k, RetValue, nNodesOld, nFanins, nFaninsMax; abctime clk, clkTotal = Abc_Clock(); // start the manager p = Res_ManAlloc( pPars ); p->nTotalNets = Abc_NtkGetTotalFanins(pNtk); p->nTotalNodes = Abc_NtkNodeNum(pNtk); nFaninsMax = Abc_NtkGetFaninMax(pNtk); if ( nFaninsMax > 8 ) nFaninsMax = 8; // perform the network sweep Abc_NtkSweep( pNtk, 0 ); // convert into the AIG if ( !Abc_NtkToAig(pNtk) ) { fprintf( stdout, "Converting to BDD has failed.\n" ); Res_ManFree( p ); return 0; } assert( Abc_NtkHasAig(pNtk) ); // set the number of levels Abc_NtkLevel( pNtk ); Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); // try resynthesizing nodes in the topological order nNodesOld = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodesOld ); Abc_NtkForEachObj( pNtk, pObj, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( !Abc_ObjIsNode(pObj) ) continue; if ( Abc_ObjFaninNum(pObj) > 8 ) continue; if ( pObj->Id > nNodesOld ) break; // create the window for this node clk = Abc_Clock(); RetValue = Res_WinCompute( pObj, p->pPars->nWindow/10, p->pPars->nWindow%10, p->pWin ); p->timeWin += Abc_Clock() - clk; if ( !RetValue ) continue; p->nWinsTriv += Res_WinIsTrivial( p->pWin ); if ( p->pPars->fVeryVerbose ) { printf( "%5d (lev=%2d) : ", pObj->Id, pObj->Level ); printf( "Win = %3d/%3d/%4d/%3d ", Vec_PtrSize(p->pWin->vLeaves), Vec_PtrSize(p->pWin->vBranches), Vec_PtrSize(p->pWin->vNodes), Vec_PtrSize(p->pWin->vRoots) ); } // collect the divisors clk = Abc_Clock(); Res_WinDivisors( p->pWin, Abc_ObjRequiredLevel(pObj) - 1 ); p->timeDiv += Abc_Clock() - clk; p->nWins++; p->nWinNodes += Vec_PtrSize(p->pWin->vNodes); p->nDivNodes += Vec_PtrSize( p->pWin->vDivs); if ( p->pPars->fVeryVerbose ) { printf( "D = %3d ", Vec_PtrSize(p->pWin->vDivs) ); printf( "D+ = %3d ", p->pWin->nDivsPlus ); } // create the AIG for the window clk = Abc_Clock(); if ( p->pAig ) Abc_NtkDelete( p->pAig ); p->pAig = Res_WndStrash( p->pWin ); p->timeAig += Abc_Clock() - clk; if ( p->pPars->fVeryVerbose ) { printf( "AIG = %4d ", Abc_NtkNodeNum(p->pAig) ); printf( "\n" ); } // prepare simulation info clk = Abc_Clock(); RetValue = Res_SimPrepare( p->pSim, p->pAig, Vec_PtrSize(p->pWin->vLeaves), 0 ); //p->pPars->fVerbose ); p->timeSim += Abc_Clock() - clk; if ( !RetValue ) { p->nSimEmpty++; continue; } // consider the case of constant node if ( p->pSim->fConst0 || p->pSim->fConst1 ) { p->nConstsUsed++; pFunc = p->pSim->fConst1? Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc) : Hop_ManConst0((Hop_Man_t *)pNtk->pManFunc); vFanins = Vec_VecEntry( p->vResubsW, 0 ); Vec_PtrClear( vFanins ); Res_UpdateNetwork( pObj, vFanins, pFunc, p->vLevels ); continue; } // printf( " " ); // find resub candidates for the node clk = Abc_Clock(); if ( p->pPars->fArea ) RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 1 ); else RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 0 ); p->timeCand += Abc_Clock() - clk; p->nCandSets += RetValue; if ( RetValue == 0 ) continue; // printf( "%d(%d) ", Vec_PtrSize(p->pWin->vDivs), RetValue ); p->nWinsUsed++; // iterate through candidate resubstitutions Vec_VecForEachLevel( p->vResubs, vFanins, k ) { if ( Vec_PtrSize(vFanins) == 0 ) break; // solve the SAT problem and get clauses clk = Abc_Clock(); if ( p->pCnf ) Sto_ManFree( p->pCnf ); p->pCnf = (Sto_Man_t *)Res_SatProveUnsat( p->pAig, vFanins ); if ( p->pCnf == NULL ) { p->timeSatSat += Abc_Clock() - clk; // printf( " Sat\n" ); // printf( "-" ); continue; } p->timeSatUnsat += Abc_Clock() - clk; // printf( "+" ); p->nProvedSets++; // printf( " Unsat\n" ); // continue; // printf( "Proved %d.\n", k ); // write it into a file // Sto_ManDumpClauses( p->pCnf, "trace.cnf" ); // interpolate the problem if it was UNSAT clk = Abc_Clock(); nFanins = Int_ManInterpolate( p->pMan, p->pCnf, 0, &puTruth ); p->timeInt += Abc_Clock() - clk; if ( nFanins != Vec_PtrSize(vFanins) - 2 ) continue; assert( puTruth ); // Extra_PrintBinary( stdout, puTruth, 1 << nFanins ); printf( "\n" ); // transform interpolant into the AIG pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem ); // derive the AIG for the decomposition tree pFunc = Kit_GraphToHop( (Hop_Man_t *)pNtk->pManFunc, pGraph ); Kit_GraphFree( pGraph ); // update the network clk = Abc_Clock(); Res_UpdateNetwork( pObj, Vec_VecEntry(p->vResubsW, k), pFunc, p->vLevels ); p->timeUpd += Abc_Clock() - clk; break; } // printf( "\n" ); } Extra_ProgressBarStop( pProgress ); Abc_NtkStopReverseLevels( pNtk ); p->timeSatSim += p->pSim->timeSat; p->timeSatTotal = p->timeSatSat + p->timeSatUnsat + p->timeSatSim; p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk); p->nTotalNodes2 = Abc_NtkNodeNum(pNtk); // quit resubstitution manager p->timeTotal = Abc_Clock() - clkTotal; Res_ManFree( p ); s_ResynTime += Abc_Clock() - clkTotal; // check the resulting network if ( !Abc_NtkCheck( pNtk ) ) { fprintf( stdout, "Abc_NtkResynthesize(): Network check has failed.\n" ); return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resDivs.c000066400000000000000000000204571300674244400232220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resDivs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Collect divisors for the given window.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resDivs.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Res_WinMarkTfi( Res_Win_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds candidate divisors of the node to its window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinDivisors( Res_Win_t * p, int nLevDivMax ) { Abc_Obj_t * pObj, * pFanout, * pFanin; int k, f, m; // set the maximum level of the divisors p->nLevDivMax = nLevDivMax; // mark the TFI with the current trav ID Abc_NtkIncrementTravId( p->pNode->pNtk ); Res_WinMarkTfi( p ); // mark with the current trav ID those nodes that should not be divisors: // (1) the node and its TFO // (2) the MFFC of the node // (3) the node's fanins (these are treated as a special case) Abc_NtkIncrementTravId( p->pNode->pNtk ); Res_WinSweepLeafTfo_rec( p->pNode, p->nLevDivMax ); Res_WinVisitMffc( p->pNode ); Abc_ObjForEachFanin( p->pNode, pObj, k ) Abc_NodeSetTravIdCurrent( pObj ); // at this point the nodes are marked with two trav IDs: // nodes to be collected as divisors are marked with previous trav ID // nodes to be avoided as divisors are marked with current trav ID // start collecting the divisors Vec_PtrClear( p->vDivs ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, k ) { assert( (int)pObj->Level >= p->nLevLeafMin ); if ( !Abc_NodeIsTravIdPrevious(pObj) ) continue; if ( (int)pObj->Level > p->nLevDivMax ) continue; Vec_PtrPush( p->vDivs, pObj ); } // add the internal nodes to the data structure Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, k ) { if ( !Abc_NodeIsTravIdPrevious(pObj) ) continue; if ( (int)pObj->Level > p->nLevDivMax ) continue; Vec_PtrPush( p->vDivs, pObj ); } // explore the fanouts of already collected divisors p->nDivsPlus = 0; Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pObj, k ) { // consider fanouts of this node Abc_ObjForEachFanout( pObj, pFanout, f ) { // stop if there are too many fanouts if ( f > 20 ) break; // skip nodes that are already added if ( Abc_NodeIsTravIdPrevious(pFanout) ) continue; // skip nodes in the TFO or in the MFFC of node if ( Abc_NodeIsTravIdCurrent(pFanout) ) continue; // skip COs if ( !Abc_ObjIsNode(pFanout) ) continue; // skip nodes with large level if ( (int)pFanout->Level > p->nLevDivMax ) continue; // skip nodes whose fanins are not divisors Abc_ObjForEachFanin( pFanout, pFanin, m ) if ( !Abc_NodeIsTravIdPrevious(pFanin) ) break; if ( m < Abc_ObjFaninNum(pFanout) ) continue; // add the node to the divisors Vec_PtrPush( p->vDivs, pFanout ); Vec_PtrPush( p->vNodes, pFanout ); Abc_NodeSetTravIdPrevious( pFanout ); p->nDivsPlus++; } } /* printf( "Node level = %d. ", Abc_ObjLevel(p->pNode) ); Vec_PtrForEachEntryStart( Abc_Obj_t *, p->vDivs, pObj, k, Vec_PtrSize(p->vDivs)-p->nDivsPlus ) printf( "%d ", Abc_ObjLevel(pObj) ); printf( "\n" ); */ //printf( "%d ", p->nDivsPlus ); } /**Function************************************************************* Synopsis [Marks the TFI cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinMarkTfi_rec( Res_Win_t * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; if ( Abc_NodeIsTravIdCurrent(pObj) ) return; Abc_NodeSetTravIdCurrent( pObj ); assert( Abc_ObjIsNode(pObj) ); // visit the fanins of the node Abc_ObjForEachFanin( pObj, pFanin, i ) Res_WinMarkTfi_rec( p, pFanin ); } /**Function************************************************************* Synopsis [Marks the TFI cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinMarkTfi( Res_Win_t * p ) { Abc_Obj_t * pObj; int i; // mark the leaves Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); // start from the node Res_WinMarkTfi_rec( p, p->pNode ); } /**Function************************************************************* Synopsis [Marks the TFO of the collected nodes up to the given level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit ) { Abc_Obj_t * pFanout; int i; if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit ) return; if ( Abc_NodeIsTravIdCurrent(pObj) ) return; Abc_NodeSetTravIdCurrent( pObj ); Abc_ObjForEachFanout( pObj, pFanout, i ) Res_WinSweepLeafTfo_rec( pFanout, nLevelLimit ); } /**Function************************************************************* Synopsis [Dereferences the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_NodeDeref_rec( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i, Counter = 1; if ( Abc_ObjIsCi(pNode) ) return 0; Abc_NodeSetTravIdCurrent( pNode ); Abc_ObjForEachFanin( pNode, pFanin, i ) { assert( pFanin->vFanouts.nSize > 0 ); if ( --pFanin->vFanouts.nSize == 0 ) Counter += Res_NodeDeref_rec( pFanin ); } return Counter; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_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 += Res_NodeRef_rec( pFanin ); } return Counter; } /**Function************************************************************* Synopsis [Labels MFFC of the node with the current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_WinVisitMffc( Abc_Obj_t * pNode ) { int Count1, Count2; assert( Abc_ObjIsNode(pNode) ); // dereference the node (mark with the current trav ID) Count1 = Res_NodeDeref_rec( pNode ); // reference it back Count2 = Res_NodeRef_rec( pNode ); assert( Count1 == Count2 ); return Count1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resFilter.c000066400000000000000000000371231300674244400235400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resFilter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Filtering resubstitution candidates.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resFilter.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask ); static int Res_FilterCriticalFanin( Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Finds sets of feasible candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea ) { Abc_Obj_t * pFanin, * pFanin2, * pFaninTemp; unsigned * pInfo, * pInfoDiv, * pInfoDiv2; int Counter, RetValue, i, i2, d, d2, iDiv, iDiv2, k; // check that the info the node is one pInfo = (unsigned *)Vec_PtrEntry( pSim->vOuts, 1 ); RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); if ( RetValue == 0 ) { // printf( "Failed 1!\n" ); return 0; } // collect the fanin info pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 ); RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); if ( RetValue == 0 ) { // printf( "Failed 2!\n" ); return 0; } // try removing each fanin // printf( "Fanins: " ); Counter = 0; Vec_VecClear( vResubs ); Vec_VecClear( vResubsW ); Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) { if ( fArea && Abc_ObjFanoutNum(pFanin) > 1 ) continue; // get simulation info without this fanin pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); if ( RetValue ) { // printf( "Node %4d. Candidate fanin %4d.\n", pWin->pNode->Id, pFanin->Id ); // collect the nodes Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) { if ( k != i ) { Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); Vec_VecPush( vResubsW, Counter, pFaninTemp ); } } Counter++; if ( Counter == Vec_VecSize(vResubs) ) return Counter; } } // try replacing each critical fanin by a non-critical fanin Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) { if ( Abc_ObjFanoutNum(pFanin) > 1 ) continue; // get simulation info without this fanin pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); // go over the set of divisors for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) { pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d ); iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) continue; // collect the nodes Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); // collect the remaning fanins and the divisor Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) { if ( k != i ) { Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); Vec_VecPush( vResubsW, Counter, pFaninTemp ); } } // collect the divisor Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); Counter++; if ( Counter == Vec_VecSize(vResubs) ) return Counter; } } // consider the case when two fanins can be added instead of one if ( Abc_ObjFaninNum(pWin->pNode) < nFaninsMax ) { // try to replace each critical fanin by two non-critical fanins Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) { if ( Abc_ObjFanoutNum(pFanin) > 1 ) continue; // get simulation info without this fanin pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); // go over the set of divisors for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) { pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d ); iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); // go through the second divisor for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ ) { pInfoDiv2 = (unsigned *)Vec_PtrEntry( pSim->vOuts, d2 ); iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2); if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) ) continue; // collect the nodes Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); // collect the remaning fanins and the divisor Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) { if ( k != i ) { Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); Vec_VecPush( vResubsW, Counter, pFaninTemp ); } } // collect the divisor Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) ); Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) ); Counter++; if ( Counter == Vec_VecSize(vResubs) ) return Counter; } } } } // try to replace two nets by one if ( !fArea ) { Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) { for ( i2 = i + 1; i2 < Abc_ObjFaninNum(pWin->pNode); i2++ ) { pFanin2 = Abc_ObjFanin(pWin->pNode, i2); // get simulation info without these fanins pInfo = Res_FilterCollectFaninInfo( pWin, pSim, (~(1 << i)) & (~(1 << i2)) ); // go over the set of divisors for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) { pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d ); iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) continue; // collect the nodes Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); // collect the remaning fanins and the divisor Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) { if ( k != i && k != i2 ) { Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); Vec_VecPush( vResubsW, Counter, pFaninTemp ); } } // collect the divisor Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); Counter++; if ( Counter == Vec_VecSize(vResubs) ) return Counter; } } } } return Counter; } /**Function************************************************************* Synopsis [Finds sets of feasible candidates.] Description [This procedure is a special case of the above.] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax ) { Abc_Obj_t * pFanin; unsigned * pInfo, * pInfoDiv, * pInfoDiv2; int Counter, RetValue, d, d2, k, iDiv, iDiv2, iBest; // check that the info the node is one pInfo = (unsigned *)Vec_PtrEntry( pSim->vOuts, 1 ); RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); if ( RetValue == 0 ) { // printf( "Failed 1!\n" ); return 0; } // collect the fanin info pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 ); RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); if ( RetValue == 0 ) { // printf( "Failed 2!\n" ); return 0; } // try removing fanins // printf( "Fanins: " ); Counter = 0; Vec_VecClear( vResubs ); Vec_VecClear( vResubsW ); // get the best fanins iBest = Res_FilterCriticalFanin( pWin->pNode ); if ( iBest == -1 ) return 0; // get the info without the critical fanin pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << iBest) ); RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); if ( RetValue ) { // printf( "Can be done without one!\n" ); // collect the nodes Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) { if ( k != iBest ) { Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); Vec_VecPush( vResubsW, Counter, pFanin ); } } Counter++; // printf( "*" ); return Counter; } // go through the divisors for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) { pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d ); iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) continue; //if ( Abc_ObjLevel(pWin->pNode) <= Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) ) // printf( "Node level = %d. Divisor level = %d.\n", Abc_ObjLevel(pWin->pNode), Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) ); // collect the nodes Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); // collect the remaning fanins and the divisor Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) { if ( k != iBest ) { Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); Vec_VecPush( vResubsW, Counter, pFanin ); } } // collect the divisor Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); Counter++; if ( Counter == Vec_VecSize(vResubs) ) break; } if ( Counter > 0 || Abc_ObjFaninNum(pWin->pNode) >= nFaninsMax ) return Counter; // try to find the node pairs for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) { pInfoDiv = (unsigned *)Vec_PtrEntry( pSim->vOuts, d ); iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); // go through the second divisor for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ ) { pInfoDiv2 = (unsigned *)Vec_PtrEntry( pSim->vOuts, d2 ); iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2); if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) ) continue; // collect the nodes Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); // collect the remaning fanins and the divisor Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) { if ( k != iBest ) { Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); Vec_VecPush( vResubsW, Counter, pFanin ); } } // collect the divisor Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) ); Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) ); Counter++; if ( Counter == Vec_VecSize(vResubs) ) break; } if ( Counter == Vec_VecSize(vResubs) ) break; } return Counter; } /**Function************************************************************* Synopsis [Finds sets of feasible candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask ) { Abc_Obj_t * pFanin; unsigned * pInfo; int i; pInfo = (unsigned *)Vec_PtrEntry( pSim->vOuts, 0 ); Abc_InfoClear( pInfo, pSim->nWordsOut ); Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) { if ( uMask & (1 << i) ) Abc_InfoOr( pInfo, (unsigned *)Vec_PtrEntry(pSim->vOuts, 2+i), pSim->nWordsOut ); } return pInfo; } /**Function************************************************************* Synopsis [Returns the index of the most critical fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_FilterCriticalFanin( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i, iBest = -1, CostMax = 0, CostCur; Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( !Abc_ObjIsNode(pFanin) ) continue; if ( Abc_ObjFanoutNum(pFanin) > 1 ) continue; CostCur = Res_WinVisitMffc( pFanin ); if ( CostMax < CostCur ) { CostMax = CostCur; iBest = i; } } // if ( CostMax > 0 ) // printf( "<%d>", CostMax ); return iBest; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resInt.h000066400000000000000000000147441300674244400230560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__res__resInt_h #define ABC__opt__res__resInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "res.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Res_Win_t_ Res_Win_t; struct Res_Win_t_ { // windowing parameters Abc_Obj_t * pNode; // the node in the center int nWinTfiMax; // the fanin levels int nWinTfoMax; // the fanout levels int nLevDivMax; // the maximum divisor level // internal windowing parameters int nFanoutLimit; // the limit on the fanout count of a TFO node (if more, the node is treated as a root) int nLevTfiMinus; // the number of additional levels to search from TFO below the level of leaves // derived windowing parameters int nLevLeafMin; // the minimum level of a leaf int nLevTravMin; // the minimum level to search from TFO int nDivsPlus; // the number of additional divisors // the window data Vec_Ptr_t * vRoots; // outputs of the window Vec_Ptr_t * vLeaves; // inputs of the window Vec_Ptr_t * vBranches; // side nodes of the window Vec_Ptr_t * vNodes; // internal nodes of the window Vec_Ptr_t * vDivs; // candidate divisors of the node // temporary data Vec_Vec_t * vMatrix; // TFI nodes below the given node }; typedef struct Res_Sim_t_ Res_Sim_t; struct Res_Sim_t_ { Abc_Ntk_t * pAig; // AIG for simulation int nTruePis; // the number of true PIs of the window int fConst0; // the node can be replaced by constant 0 int fConst1; // the node can be replaced by constant 0 // simulation parameters int nWords; // the number of simulation words int nPats; // the number of patterns int nWordsIn; // the number of simulation words in the input patterns int nPatsIn; // the number of patterns in the input patterns int nBytesIn; // the number of bytes in the input patterns int nWordsOut; // the number of simulation words in the output patterns int nPatsOut; // the number of patterns in the output patterns // simulation info Vec_Ptr_t * vPats; // input simulation patterns Vec_Ptr_t * vPats0; // input simulation patterns Vec_Ptr_t * vPats1; // input simulation patterns Vec_Ptr_t * vOuts; // output simulation info int nPats0; // the number of 0-patterns accumulated int nPats1; // the number of 1-patterns accumulated // resub candidates Vec_Vec_t * vCands; // resubstitution candidates // statistics abctime timeSat; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== resDivs.c ==========================================================*/ extern void Res_WinDivisors( Res_Win_t * p, int nLevDivMax ); extern void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit ); extern int Res_WinVisitMffc( Abc_Obj_t * pNode ); /*=== resFilter.c ==========================================================*/ extern int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea ); extern int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax ); /*=== resSat.c ==========================================================*/ extern void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins ); extern int Res_SatSimulate( Res_Sim_t * p, int nPats, int fOnSet ); /*=== resSim.c ==========================================================*/ extern Res_Sim_t * Res_SimAlloc( int nWords ); extern void Res_SimFree( Res_Sim_t * p ); extern int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ); /*=== resStrash.c ==========================================================*/ extern Abc_Ntk_t * Res_WndStrash( Res_Win_t * p ); /*=== resWnd.c ==========================================================*/ extern void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels ); /*=== resWnd.c ==========================================================*/ extern Res_Win_t * Res_WinAlloc(); extern void Res_WinFree( Res_Win_t * p ); extern int Res_WinIsTrivial( Res_Win_t * p ); extern int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resSat.c000066400000000000000000000314371300674244400230440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Interface with the SAT solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resSat.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "resInt.h" #include "aig/hop/hop.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl ); extern int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl ); extern int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Loads AIG into the SAT solver for checking resubstitution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins ) { void * pCnf = NULL; sat_solver * pSat; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i, nNodes, status; // make sure fanins contain POs of the AIG pObj = (Abc_Obj_t *)Vec_PtrEntry( vFanins, 0 ); assert( pObj->pNtk == pAig && Abc_ObjIsPo(pObj) ); // collect reachable nodes vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize ); // assign unique numbers to each node nNodes = 0; Abc_AigConst1(pAig)->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; Abc_NtkForEachPi( pAig, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) // useful POs pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; // start the solver pSat = sat_solver_new(); sat_solver_store_alloc( pSat ); // add clause for the constant node Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)Abc_AigConst1(pAig)->pCopy, 0 ); // add clauses for AND gates Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Res_SatAddAnd( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); Vec_PtrFree( vNodes ); // add clauses for POs Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); // add trivial clauses pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 0); Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // care-set pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 1); Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // on-set // bookmark the clauses of A sat_solver_store_mark_clauses_a( pSat ); // duplicate the clauses pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 1); Sat_SolverDoubleClauses( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy ); // add the equality constraints Vec_PtrForEachEntryStart( Abc_Obj_t *, vFanins, pObj, i, 2 ) Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, ((int)(ABC_PTRUINT_T)pObj->pCopy) + nNodes, 0 ); // bookmark the roots sat_solver_store_mark_roots( pSat ); // solve the problem status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_False ) { pCnf = sat_solver_store_release( pSat ); // printf( "unsat\n" ); } else if ( status == l_True ) { // printf( "sat\n" ); } else { // printf( "undef\n" ); } sat_solver_delete( pSat ); return pCnf; } /**Function************************************************************* Synopsis [Loads AIG into the SAT solver for constrained simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Res_SatSimulateConstr( Abc_Ntk_t * pAig, int fOnSet ) { sat_solver * pSat; Vec_Ptr_t * vFanins; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i, nNodes; // start the array vFanins = Vec_PtrAlloc( 2 ); pObj = Abc_NtkPo( pAig, 0 ); Vec_PtrPush( vFanins, pObj ); pObj = Abc_NtkPo( pAig, 1 ); Vec_PtrPush( vFanins, pObj ); // collect reachable nodes vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize ); // assign unique numbers to each node nNodes = 0; Abc_AigConst1(pAig)->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; Abc_NtkForEachPi( pAig, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) // useful POs pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++; // start the solver pSat = sat_solver_new(); // add clause for the constant node Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)Abc_AigConst1(pAig)->pCopy, 0 ); // add clauses for AND gates Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Res_SatAddAnd( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); Vec_PtrFree( vNodes ); // add clauses for the first PO pObj = Abc_NtkPo( pAig, 0 ); Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); // add clauses for the second PO pObj = Abc_NtkPo( pAig, 1 ); Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); // add trivial clauses pObj = Abc_NtkPo( pAig, 0 ); Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // care-set pObj = Abc_NtkPo( pAig, 1 ); Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, !fOnSet ); // on-set Vec_PtrFree( vFanins ); return pSat; } /**Function************************************************************* Synopsis [Loads AIG into the SAT solver for constrained simulation.] Description [Returns 1 if the required number of patterns are found. Returns 0 if the solver ran out of time or proved a constant. In the latter, case one of the flags, fConst0 or fConst1, are set to 1.] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_SatSimulate( Res_Sim_t * p, int nPatsLimit, int fOnSet ) { Vec_Int_t * vLits; Vec_Ptr_t * vPats; sat_solver * pSat; int RetValue = -1; // Suppress "might be used uninitialized" int i, k, value, status, Lit, Var, iPat; abctime clk = Abc_Clock(); //printf( "Looking for %s: ", fOnSet? "onset " : "offset" ); // decide what problem should be solved Lit = toLitCond( (int)(ABC_PTRUINT_T)Abc_NtkPo(p->pAig,1)->pCopy, !fOnSet ); if ( fOnSet ) { iPat = p->nPats1; vPats = p->vPats1; } else { iPat = p->nPats0; vPats = p->vPats0; } assert( iPat < nPatsLimit ); // derive the SAT solver pSat = (sat_solver *)Res_SatSimulateConstr( p->pAig, fOnSet ); pSat->fSkipSimplify = 1; status = sat_solver_simplify( pSat ); if ( status == 0 ) { if ( iPat == 0 ) { // if ( fOnSet ) // p->fConst0 = 1; // else // p->fConst1 = 1; RetValue = 0; } goto finish; } // enumerate through the SAT assignments RetValue = 1; vLits = Vec_IntAlloc( 32 ); for ( k = iPat; k < nPatsLimit; k++ ) { // solve with the assumption // status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_False ) { //printf( "Const %d\n", !fOnSet ); if ( k == 0 ) { if ( fOnSet ) p->fConst0 = 1; else p->fConst1 = 1; RetValue = 0; } break; } else if ( status == l_True ) { // save the pattern Vec_IntClear( vLits ); for ( i = 0; i < p->nTruePis; i++ ) { Var = (int)(ABC_PTRUINT_T)Abc_NtkPi(p->pAig,i)->pCopy; // value = (int)(pSat->model.ptr[Var] == l_True); value = sat_solver_var_value(pSat, Var); if ( value ) Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vPats, i), k ); Lit = toLitCond( Var, value ); Vec_IntPush( vLits, Lit ); // printf( "%d", value ); } // printf( "\n" ); status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); if ( status == 0 ) { k++; RetValue = 1; break; } } else { //printf( "Undecided\n" ); if ( k == 0 ) RetValue = 0; else RetValue = 1; break; } } Vec_IntFree( vLits ); //printf( "Found %d patterns\n", k - iPat ); // set the new number of patterns if ( fOnSet ) p->nPats1 = k; else p->nPats0 = k; finish: sat_solver_delete( pSat ); p->timeSat += Abc_Clock() - clk; return RetValue; } /**Function************************************************************* Synopsis [Asserts equality of the variable to a constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_SatAddConst1( 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 [Asserts equality of two variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_SatAddEqual( 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 constraints for the two-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_SatAddAnd( 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; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resSim.c000066400000000000000000000554371300674244400230530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Simulation engine.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocate simulation engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Res_Sim_t * Res_SimAlloc( int nWords ) { Res_Sim_t * p; p = ABC_ALLOC( Res_Sim_t, 1 ); memset( p, 0, sizeof(Res_Sim_t) ); // simulation parameters p->nWords = nWords; p->nPats = p->nWords * 8 * sizeof(unsigned); p->nWordsIn = p->nPats; p->nBytesIn = p->nPats * sizeof(unsigned); p->nPatsIn = p->nPats * 8 * sizeof(unsigned); p->nWordsOut = p->nPats * p->nWords; p->nPatsOut = p->nPats * p->nPats; // simulation info p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWordsIn ); p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords ); p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords ); p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut ); // resub candidates p->vCands = Vec_VecStart( 16 ); return p; } /**Function************************************************************* Synopsis [Allocate simulation engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis ) { srand( 0xABC ); assert( Abc_NtkIsStrash(pAig) ); p->pAig = pAig; p->nTruePis = nTruePis; if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 ) { Vec_PtrFree( p->vPats ); p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWordsIn ); } if ( Vec_PtrSize(p->vPats0) < nTruePis ) { Vec_PtrFree( p->vPats0 ); p->vPats0 = Vec_PtrAllocSimInfo( nTruePis, p->nWords ); } if ( Vec_PtrSize(p->vPats1) < nTruePis ) { Vec_PtrFree( p->vPats1 ); p->vPats1 = Vec_PtrAllocSimInfo( nTruePis, p->nWords ); } if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) ) { Vec_PtrFree( p->vOuts ); p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut ); } // clean storage info for patterns Abc_InfoClear( (unsigned *)Vec_PtrEntry(p->vPats0,0), p->nWords * nTruePis ); Abc_InfoClear( (unsigned *)Vec_PtrEntry(p->vPats1,0), p->nWords * nTruePis ); p->nPats0 = 0; p->nPats1 = 0; p->fConst0 = 0; p->fConst1 = 0; } /**Function************************************************************* Synopsis [Free simulation engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimFree( Res_Sim_t * p ) { Vec_PtrFree( p->vPats ); Vec_PtrFree( p->vPats0 ); Vec_PtrFree( p->vPats1 ); Vec_PtrFree( p->vOuts ); Vec_VecFree( p->vCands ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Sets random PI simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_InfoRandomBytes( unsigned * p, int nWords ) { int i, Num; for ( i = nWords - 1; i >= 0; i-- ) { Num = rand(); p[i] = (Num & 1)? 0xff : 0; p[i] = (p[i] << 8) | ((Num & 2)? 0xff : 0); p[i] = (p[i] << 8) | ((Num & 4)? 0xff : 0); p[i] = (p[i] << 8) | ((Num & 8)? 0xff : 0); } // Extra_PrintBinary( stdout, p, 32 ); printf( "\n" ); } /**Function************************************************************* Synopsis [Sets random PI simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimSetRandomBytes( Res_Sim_t * p ) { Abc_Obj_t * pObj; unsigned * pInfo; int i; Abc_NtkForEachPi( p->pAig, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id ); if ( i < p->nTruePis ) Abc_InfoRandomBytes( pInfo, p->nWordsIn ); else Abc_InfoRandom( pInfo, p->nWordsIn ); } /* // double-check that all are byte-patterns Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; pInfoC = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); for ( k = 0; k < p->nBytesIn; k++ ) assert( pInfoC[k] == 0 || pInfoC[k] == 0xff ); } */ } /**Function************************************************************* Synopsis [Sets random PI simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimSetDerivedBytes( Res_Sim_t * p, int fUseWalk ) { Vec_Ptr_t * vPatsSource[2]; int nPatsSource[2]; Abc_Obj_t * pObj; unsigned char * pInfo; int i, k, z, s, nPats; // set several random patterns assert( p->nBytesIn % 32 == 0 ); nPats = p->nBytesIn/8; Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; Abc_InfoRandomBytes( (unsigned *)Vec_PtrEntry(p->vPats, pObj->Id), nPats/4 ); } // set special patterns if ( fUseWalk ) { for ( z = 0; z < 2; z++ ) { // set the zero pattern Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); pInfo[nPats] = z ? 0xff : 0; } if ( ++nPats == p->nBytesIn ) return; // set the walking zero pattern for ( k = 0; k < p->nTruePis; k++ ) { Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); pInfo[nPats] = ((i == k) ^ z) ? 0xff : 0; } if ( ++nPats == p->nBytesIn ) return; } } } // decide what patterns to set first if ( p->nPats0 < p->nPats1 ) { nPatsSource[0] = p->nPats0; vPatsSource[0] = p->vPats0; nPatsSource[1] = p->nPats1; vPatsSource[1] = p->vPats1; } else { nPatsSource[0] = p->nPats1; vPatsSource[0] = p->vPats1; nPatsSource[1] = p->nPats0; vPatsSource[1] = p->vPats0; } for ( z = 0; z < 2; z++ ) { for ( s = nPatsSource[z] - 1; s >= 0; s-- ) { // if ( s == 0 ) // printf( "Patterns:\n" ); // set the given source pattern for ( k = 0; k < p->nTruePis; k++ ) { Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); if ( (i == k) ^ Abc_InfoHasBit( (unsigned *)Vec_PtrEntry(vPatsSource[z], i), s ) ) { pInfo[nPats] = 0xff; // if ( s == 0 ) // printf( "1" ); } else { pInfo[nPats] = 0; // if ( s == 0 ) // printf( "0" ); } } // if ( s == 0 ) // printf( "\n" ); if ( ++nPats == p->nBytesIn ) return; } } } // clean the rest for ( z = nPats; z < p->nBytesIn; z++ ) { Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); memset( pInfo + nPats, 0, p->nBytesIn - nPats ); } } /* // double-check that all are byte-patterns Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); for ( k = 0; k < p->nBytesIn; k++ ) assert( pInfo[k] == 0 || pInfo[k] == 0xff ); } */ } /**Function************************************************************* Synopsis [Sets given PI simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo ) { Abc_Obj_t * pObj; unsigned * pInfo, * pInfo2; int i, w; Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id ); pInfo2 = (unsigned *)Vec_PtrEntry( vInfo, i ); for ( w = 0; w < p->nWords; w++ ) pInfo[w] = pInfo2[w]; } } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) { unsigned * pInfo, * pInfo1, * pInfo2; int k, fComp1, fComp2; // simulate the internal nodes assert( Abc_ObjIsNode(pNode) ); pInfo = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id); pInfo1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); pInfo2 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); fComp1 = Abc_ObjFaninC0(pNode); fComp2 = Abc_ObjFaninC1(pNode); if ( fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; else if ( fComp1 && !fComp2 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = ~pInfo1[k] & pInfo2[k]; else if ( !fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = pInfo1[k] & ~pInfo2[k]; else // if ( fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = pInfo1[k] & pInfo2[k]; } /**Function************************************************************* Synopsis [Simulates one CO node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) { unsigned * pInfo, * pInfo1; int k, fComp1; // simulate the internal nodes assert( Abc_ObjIsCo(pNode) ); pInfo = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id); pInfo1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); fComp1 = Abc_ObjFaninC0(pNode); if ( fComp1 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = ~pInfo1[k]; else for ( k = 0; k < nSimWords; k++ ) pInfo[k] = pInfo1[k]; } /**Function************************************************************* Synopsis [Performs one round of simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPerformRound( Res_Sim_t * p, int nWords ) { Abc_Obj_t * pObj; int i; Abc_InfoFill( (unsigned *)Vec_PtrEntry(p->vPats,0), nWords ); Abc_AigForEachAnd( p->pAig, pObj, i ) Res_SimPerformOne( pObj, p->vPats, nWords ); Abc_NtkForEachPo( p->pAig, pObj, i ) Res_SimTransferOne( pObj, p->vPats, nWords ); } /**Function************************************************************* Synopsis [Pads the extra space with duplicated simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords ) { unsigned * pInfo; int i, w, iWords; assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) ); // pad the first word if ( nPats < 8 * sizeof(unsigned) ) { Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i ) if ( pInfo[0] & 1 ) pInfo[0] |= ((~0) << nPats); nPats = 8 * sizeof(unsigned); } // pad the empty words iWords = nPats / (8 * sizeof(unsigned)); Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i ) { for ( w = iWords; w < nWords; w++ ) pInfo[w] = pInfo[0]; } } /**Function************************************************************* Synopsis [Duplicates the simulation info to fill the space.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimDeriveInfoReplicate( Res_Sim_t * p ) { unsigned * pInfo, * pInfo2; Abc_Obj_t * pObj; int i, j, w; Abc_NtkForEachPo( p->pAig, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id ); pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i ); for ( j = 0; j < p->nPats; j++ ) for ( w = 0; w < p->nWords; w++ ) *pInfo2++ = pInfo[w]; } } /**Function************************************************************* Synopsis [Complement the simulation info if necessary.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimDeriveInfoComplement( Res_Sim_t * p ) { unsigned * pInfo, * pInfo2; Abc_Obj_t * pObj; int i, j, w; Abc_NtkForEachPo( p->pAig, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id ); pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i ); for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords ) if ( Abc_InfoHasBit( pInfo, j ) ) for ( w = 0; w < p->nWords; w++ ) pInfo2[w] = ~pInfo2[w]; } } /**Function************************************************************* Synopsis [Prints output patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) { Abc_Obj_t * pObj; unsigned * pInfo2; int i; Abc_NtkForEachPo( pAig, pObj, i ) { pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i ); Extra_PrintBinary( stdout, pInfo2, p->nPatsOut ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Prints output patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPrintNodePatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) { unsigned * pInfo; pInfo = (unsigned *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); Extra_PrintBinary( stdout, pInfo, p->nPats ); printf( "\n" ); } /**Function************************************************************* Synopsis [Counts the number of patters of different type.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimCountResults( Res_Sim_t * p, int * pnDcs, int * pnOnes, int * pnZeros, int fVerbose ) { unsigned char * pInfoCare, * pInfoNode; int i, nTotal = 0; pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); for ( i = 0; i < p->nBytesIn; i++ ) { if ( !pInfoCare[i] ) (*pnDcs)++; else if ( !pInfoNode[i] ) (*pnZeros)++; else (*pnOnes)++; } nTotal += *pnDcs; nTotal += *pnZeros; nTotal += *pnOnes; if ( fVerbose ) { printf( "Dc = %7.2f %% ", 100.0*(*pnDcs) /nTotal ); printf( "On = %7.2f %% ", 100.0*(*pnOnes) /nTotal ); printf( "Off = %7.2f %% ", 100.0*(*pnZeros)/nTotal ); } } /**Function************************************************************* Synopsis [Counts the number of patters of different type.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimCollectPatterns( Res_Sim_t * p, int fVerbose ) { Abc_Obj_t * pObj; unsigned char * pInfoCare, * pInfoNode, * pInfo; int i, j; pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); for ( i = 0; i < p->nBytesIn; i++ ) { // skip don't-care patterns if ( !pInfoCare[i] ) continue; // separate offset and onset patterns assert( pInfoNode[i] == 0 || pInfoNode[i] == 0xff ); if ( !pInfoNode[i] ) { if ( p->nPats0 >= p->nPats ) continue; Abc_NtkForEachPi( p->pAig, pObj, j ) { if ( j == p->nTruePis ) break; pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); assert( pInfo[i] == 0 || pInfo[i] == 0xff ); if ( pInfo[i] ) Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPats0, j), p->nPats0 ); } p->nPats0++; } else { if ( p->nPats1 >= p->nPats ) continue; Abc_NtkForEachPi( p->pAig, pObj, j ) { if ( j == p->nTruePis ) break; pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); assert( pInfo[i] == 0 || pInfo[i] == 0xff ); if ( pInfo[i] ) Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPats1, j), p->nPats1 ); } p->nPats1++; } if ( p->nPats0 >= p->nPats && p->nPats1 >= p->nPats ) break; } if ( fVerbose ) { printf( "| " ); printf( "On = %3d ", p->nPats1 ); printf( "Off = %3d ", p->nPats0 ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Verifies the last pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_SimVerifyValue( Res_Sim_t * p, int fOnSet ) { Abc_Obj_t * pObj; unsigned * pInfo, * pInfo2; int i, value; Abc_NtkForEachPi( p->pAig, pObj, i ) { if ( i == p->nTruePis ) break; if ( fOnSet ) { pInfo2 = (unsigned *)Vec_PtrEntry( p->vPats1, i ); value = Abc_InfoHasBit( pInfo2, p->nPats1 - 1 ); } else { pInfo2 = (unsigned *)Vec_PtrEntry( p->vPats0, i ); value = Abc_InfoHasBit( pInfo2, p->nPats0 - 1 ); } pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id ); pInfo[0] = value ? ~0 : 0; } Res_SimPerformRound( p, 1 ); pObj = Abc_NtkPo( p->pAig, 1 ); pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id ); assert( pInfo[0] == 0 || pInfo[0] == ~0 ); return pInfo[0] > 0; } /**Function************************************************************* Synopsis [Prepares simulation info for candidate filtering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ) { int i, nOnes = 0, nZeros = 0, nDcs = 0; if ( fVerbose ) printf( "\n" ); // prepare the manager Res_SimAdjust( p, pAig, nTruePis ); // estimate the number of patterns Res_SimSetRandomBytes( p ); Res_SimPerformRound( p, p->nWordsIn ); Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose ); // collect the patterns Res_SimCollectPatterns( p, fVerbose ); // add more patterns using constraint simulation if ( p->nPats0 < 8 ) { if ( !Res_SatSimulate( p, 16, 0 ) ) return p->fConst0 || p->fConst1; // return 0; // printf( "Value0 = %d\n", Res_SimVerifyValue( p, 0 ) ); } if ( p->nPats1 < 8 ) { if ( !Res_SatSimulate( p, 16, 1 ) ) return p->fConst0 || p->fConst1; // return 0; // printf( "Value1 = %d\n", Res_SimVerifyValue( p, 1 ) ); } // generate additional patterns for ( i = 0; i < 2; i++ ) { if ( p->nPats0 > p->nPats*7/8 && p->nPats1 > p->nPats*7/8 ) break; Res_SimSetDerivedBytes( p, i==0 ); Res_SimPerformRound( p, p->nWordsIn ); Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose ); Res_SimCollectPatterns( p, fVerbose ); } // create bit-matrix info if ( p->nPats0 < p->nPats ) Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords ); if ( p->nPats1 < p->nPats ) Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords ); // resimulate 0-patterns Res_SimSetGiven( p, p->vPats0 ); Res_SimPerformRound( p, p->nWords ); //Res_SimPrintNodePatterns( p, pAig ); Res_SimDeriveInfoReplicate( p ); // resimulate 1-patterns Res_SimSetGiven( p, p->vPats1 ); Res_SimPerformRound( p, p->nWords ); //Res_SimPrintNodePatterns( p, pAig ); Res_SimDeriveInfoComplement( p ); // print output patterns // Res_SimPrintOutPatterns( p, pAig ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resSim_old.c000066400000000000000000000351641300674244400237040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Simulation engine.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocate simulation engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Res_Sim_t * Res_SimAlloc( int nWords ) { Res_Sim_t * p; p = ALLOC( Res_Sim_t, 1 ); memset( p, 0, sizeof(Res_Sim_t) ); // simulation parameters p->nWords = nWords; p->nPats = 8 * sizeof(unsigned) * p->nWords; p->nWordsOut = p->nPats * p->nWords; p->nPatsOut = p->nPats * p->nPats; // simulation info p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWords ); p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords ); p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords ); p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut ); // resub candidates p->vCands = Vec_VecStart( 16 ); return p; } /**Function************************************************************* Synopsis [Allocate simulation engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig ) { srand( 0xABC ); assert( Abc_NtkIsStrash(pAig) ); p->pAig = pAig; if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 ) { Vec_PtrFree( p->vPats ); p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWords ); } if ( Vec_PtrSize(p->vPats0) < Abc_NtkPiNum(pAig) ) { Vec_PtrFree( p->vPats0 ); p->vPats0 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords ); } if ( Vec_PtrSize(p->vPats1) < Abc_NtkPiNum(pAig) ) { Vec_PtrFree( p->vPats1 ); p->vPats1 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords ); } if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) ) { Vec_PtrFree( p->vOuts ); p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut ); } // clean storage info for patterns Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * Abc_NtkPiNum(pAig) ); Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * Abc_NtkPiNum(pAig) ); p->nPats0 = 0; p->nPats1 = 0; } /**Function************************************************************* Synopsis [Free simulation engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimFree( Res_Sim_t * p ) { Vec_PtrFree( p->vPats ); Vec_PtrFree( p->vPats0 ); Vec_PtrFree( p->vPats1 ); Vec_PtrFree( p->vOuts ); Vec_VecFree( p->vCands ); free( p ); } /**Function************************************************************* Synopsis [Sets random PI simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimSetRandom( Res_Sim_t * p ) { Abc_Obj_t * pObj; unsigned * pInfo; int i; Abc_NtkForEachPi( p->pAig, pObj, i ) { pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); Abc_InfoRandom( pInfo, p->nWords ); } } /**Function************************************************************* Synopsis [Sets given PI simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo ) { Abc_Obj_t * pObj; unsigned * pInfo, * pInfo2; int i, w; Abc_NtkForEachPi( p->pAig, pObj, i ) { pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); pInfo2 = Vec_PtrEntry( vInfo, i ); for ( w = 0; w < p->nWords; w++ ) pInfo[w] = pInfo2[w]; } } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) { unsigned * pInfo, * pInfo1, * pInfo2; int k, fComp1, fComp2; // simulate the internal nodes assert( Abc_ObjIsNode(pNode) ); pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); fComp1 = Abc_ObjFaninC0(pNode); fComp2 = Abc_ObjFaninC1(pNode); if ( fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; else if ( fComp1 && !fComp2 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = ~pInfo1[k] & pInfo2[k]; else if ( !fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = pInfo1[k] & ~pInfo2[k]; else // if ( fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = pInfo1[k] & pInfo2[k]; } /**Function************************************************************* Synopsis [Simulates one CO node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) { unsigned * pInfo, * pInfo1; int k, fComp1; // simulate the internal nodes assert( Abc_ObjIsCo(pNode) ); pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); fComp1 = Abc_ObjFaninC0(pNode); if ( fComp1 ) for ( k = 0; k < nSimWords; k++ ) pInfo[k] = ~pInfo1[k]; else for ( k = 0; k < nSimWords; k++ ) pInfo[k] = pInfo1[k]; } /**Function************************************************************* Synopsis [Performs one round of simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPerformRound( Res_Sim_t * p ) { Abc_Obj_t * pObj; int i; Abc_InfoFill( Vec_PtrEntry(p->vPats,0), p->nWords ); Abc_AigForEachAnd( p->pAig, pObj, i ) Res_SimPerformOne( pObj, p->vPats, p->nWords ); Abc_NtkForEachPo( p->pAig, pObj, i ) Res_SimTransferOne( pObj, p->vPats, p->nWords ); } /**Function************************************************************* Synopsis [Processes simulation patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimProcessPats( Res_Sim_t * p ) { Abc_Obj_t * pObj; unsigned * pInfoCare, * pInfoNode; int i, j, nDcs = 0; pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); for ( i = 0; i < p->nPats; i++ ) { // skip don't-care patterns if ( !Abc_InfoHasBit(pInfoCare, i) ) { nDcs++; continue; } // separate offset and onset patterns if ( !Abc_InfoHasBit(pInfoNode, i) ) { if ( p->nPats0 >= p->nPats ) continue; Abc_NtkForEachPi( p->pAig, pObj, j ) if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) ) Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 ); p->nPats0++; } else { if ( p->nPats1 >= p->nPats ) continue; Abc_NtkForEachPi( p->pAig, pObj, j ) if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) ) Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 ); p->nPats1++; } } } /**Function************************************************************* Synopsis [Pads the extra space with duplicated simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords ) { unsigned * pInfo; int i, w, iWords; assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) ); // pad the first word if ( nPats < 8 * sizeof(unsigned) ) { Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i ) if ( pInfo[0] & 1 ) pInfo[0] |= ((~0) << nPats); nPats = 8 * sizeof(unsigned); } // pad the empty words iWords = nPats / (8 * sizeof(unsigned)); Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i ) { for ( w = iWords; w < nWords; w++ ) pInfo[w] = pInfo[0]; } } /**Function************************************************************* Synopsis [Duplicates the simulation info to fill the space.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimDeriveInfoReplicate( Res_Sim_t * p ) { unsigned * pInfo, * pInfo2; Abc_Obj_t * pObj; int i, j, w; Abc_NtkForEachPo( p->pAig, pObj, i ) { pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); pInfo2 = Vec_PtrEntry( p->vOuts, i ); for ( j = 0; j < p->nPats; j++ ) for ( w = 0; w < p->nWords; w++ ) *pInfo2++ = pInfo[w]; } } /**Function************************************************************* Synopsis [Complement the simulation info if necessary.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimDeriveInfoComplement( Res_Sim_t * p ) { unsigned * pInfo, * pInfo2; Abc_Obj_t * pObj; int i, j, w; Abc_NtkForEachPo( p->pAig, pObj, i ) { pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); pInfo2 = Vec_PtrEntry( p->vOuts, i ); for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords ) if ( Abc_InfoHasBit( pInfo, j ) ) for ( w = 0; w < p->nWords; w++ ) pInfo2[w] = ~pInfo2[w]; } } /**Function************************************************************* Synopsis [Free simulation engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimReportOne( Res_Sim_t * p ) { unsigned * pInfoCare, * pInfoNode; int i, nDcs, nOnes, nZeros; pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); nDcs = nOnes = nZeros = 0; for ( i = 0; i < p->nPats; i++ ) { // skip don't-care patterns if ( !Abc_InfoHasBit(pInfoCare, i) ) { nDcs++; continue; } // separate offset and onset patterns if ( !Abc_InfoHasBit(pInfoNode, i) ) nZeros++; else nOnes++; } printf( "On = %3d (%7.2f %%) ", nOnes, 100.0*nOnes/p->nPats ); printf( "Off = %3d (%7.2f %%) ", nZeros, 100.0*nZeros/p->nPats ); printf( "Dc = %3d (%7.2f %%) ", nDcs, 100.0*nDcs/p->nPats ); printf( "P0 = %3d ", p->nPats0 ); printf( "P1 = %3d ", p->nPats1 ); if ( p->nPats0 < 4 || p->nPats1 < 4 ) printf( "*" ); printf( "\n" ); } /**Function************************************************************* Synopsis [Prints output patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) { Abc_Obj_t * pObj; unsigned * pInfo2; int i; Abc_NtkForEachPo( pAig, pObj, i ) { pInfo2 = Vec_PtrEntry( p->vOuts, i ); Extra_PrintBinary( stdout, pInfo2, p->nPatsOut ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Prepares simulation info for candidate filtering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ) { int Limit; // prepare the manager Res_SimAdjust( p, pAig ); // collect 0/1 simulation info for ( Limit = 0; Limit < 10; Limit++ ) { Res_SimSetRandom( p ); Res_SimPerformRound( p ); Res_SimProcessPats( p ); if ( !(p->nPats0 < p->nPats || p->nPats1 < p->nPats) ) break; } // printf( "%d ", Limit ); // report the last set of patterns // Res_SimReportOne( p ); // printf( "\n" ); // quit if there is not enough // if ( p->nPats0 < 4 || p->nPats1 < 4 ) if ( p->nPats0 < 4 || p->nPats1 < 4 ) { // Res_SimReportOne( p ); return 0; } // create bit-matrix info if ( p->nPats0 < p->nPats ) Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords ); if ( p->nPats1 < p->nPats ) Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords ); // resimulate 0-patterns Res_SimSetGiven( p, p->vPats0 ); Res_SimPerformRound( p ); Res_SimDeriveInfoReplicate( p ); // resimulate 1-patterns Res_SimSetGiven( p, p->vPats1 ); Res_SimPerformRound( p ); Res_SimDeriveInfoComplement( p ); // print output patterns // Res_SimPrintOutPatterns( p, pAig ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resStrash.c000066400000000000000000000103111300674244400235450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resStrash.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Structural hashing of the nodes in the window.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resStrash.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pAig, Abc_Obj_t * pObjOld ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Structurally hashes the given window.] Description [The first PO is the observability condition. The second is the node's function. The remaining POs are the candidate divisors.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Res_WndStrash( Res_Win_t * p ) { Vec_Ptr_t * vPairs; Abc_Ntk_t * pAig; Abc_Obj_t * pObj, * pMiter; int i; assert( Abc_NtkHasAig(p->pNode->pNtk) ); // Abc_NtkCleanCopy( p->pNode->pNtk ); // create the network pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pAig->pName = Extra_UtilStrsav( "window" ); // create the inputs Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i ) pObj->pCopy = Abc_NtkCreatePi( pAig ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vBranches, pObj, i ) pObj->pCopy = Abc_NtkCreatePi( pAig ); // go through the nodes in the topological order Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i ) { pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj ); if ( pObj == p->pNode ) pObj->pCopy = Abc_ObjNot( pObj->pCopy ); } // collect the POs vPairs = Vec_PtrAlloc( 2 * Vec_PtrSize(p->vRoots) ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i ) { Vec_PtrPush( vPairs, pObj->pCopy ); Vec_PtrPush( vPairs, NULL ); } // mark the TFO of the node Abc_NtkIncrementTravId( p->pNode->pNtk ); Res_WinSweepLeafTfo_rec( p->pNode, (int)p->pNode->Level + p->nWinTfoMax ); // update strashing of the node p->pNode->pCopy = Abc_ObjNot( p->pNode->pCopy ); Abc_NodeSetTravIdPrevious( p->pNode ); // redo strashing in the TFO Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i ) { if ( Abc_NodeIsTravIdCurrent(pObj) ) pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj ); } // collect the POs Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i ) Vec_PtrWriteEntry( vPairs, 2 * i + 1, pObj->pCopy ); // add the miter pMiter = Abc_AigMiter( (Abc_Aig_t *)pAig->pManFunc, vPairs, 0 ); Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pMiter ); Vec_PtrFree( vPairs ); // add the node Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), p->pNode->pCopy ); // add the fanins Abc_ObjForEachFanin( p->pNode, pObj, i ) Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy ); // add the divisors Vec_PtrForEachEntry( Abc_Obj_t *, p->vDivs, pObj, i ) Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy ); // add the names Abc_NtkAddDummyPiNames( pAig ); Abc_NtkAddDummyPoNames( pAig ); // check the resulting network if ( !Abc_NtkCheck( pAig ) ) fprintf( stdout, "Res_WndStrash(): Network check has failed.\n" ); return pAig; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/resWin.c000066400000000000000000000343611300674244400230510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [resWin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [Windowing algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: resWin.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "resInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Res_Win_t * Res_WinAlloc() { Res_Win_t * p; // start the manager p = ABC_ALLOC( Res_Win_t, 1 ); memset( p, 0, sizeof(Res_Win_t) ); // set internal parameters p->nFanoutLimit = 10; p->nLevTfiMinus = 3; // allocate storage p->vRoots = Vec_PtrAlloc( 256 ); p->vLeaves = Vec_PtrAlloc( 256 ); p->vBranches = Vec_PtrAlloc( 256 ); p->vNodes = Vec_PtrAlloc( 256 ); p->vDivs = Vec_PtrAlloc( 256 ); p->vMatrix = Vec_VecStart( 128 ); return p; } /**Function************************************************************* Synopsis [Frees the window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinFree( Res_Win_t * p ) { Vec_PtrFree( p->vRoots ); Vec_PtrFree( p->vLeaves ); Vec_PtrFree( p->vBranches ); Vec_PtrFree( p->vNodes ); Vec_PtrFree( p->vDivs ); Vec_VecFree( p->vMatrix ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collect the limited TFI cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_WinCollectLeavesAndNodes( Res_Win_t * p ) { Vec_Ptr_t * vFront; Abc_Obj_t * pObj, * pTemp; int i, k, m; assert( p->nWinTfiMax > 0 ); assert( Vec_VecSize(p->vMatrix) > p->nWinTfiMax ); // start matrix with the node Vec_VecClear( p->vMatrix ); Vec_VecPush( p->vMatrix, 0, p->pNode ); Abc_NtkIncrementTravId( p->pNode->pNtk ); Abc_NodeSetTravIdCurrent( p->pNode ); // collect the leaves (nodes pTemp such that "p->pNode->Level - pTemp->Level > p->nWinTfiMax") Vec_PtrClear( p->vLeaves ); Vec_VecForEachLevelStartStop( p->vMatrix, vFront, i, 0, p->nWinTfiMax+1 ) { Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pObj, k ) { Abc_ObjForEachFanin( pObj, pTemp, m ) { if ( Abc_NodeIsTravIdCurrent( pTemp ) ) continue; Abc_NodeSetTravIdCurrent( pTemp ); if ( Abc_ObjIsCi(pTemp) || (int)(p->pNode->Level - pTemp->Level) > p->nWinTfiMax ) Vec_PtrPush( p->vLeaves, pTemp ); else Vec_VecPush( p->vMatrix, p->pNode->Level - pTemp->Level, pTemp ); } } } if ( Vec_PtrSize(p->vLeaves) == 0 ) return 0; // collect the nodes in the reverse order Vec_PtrClear( p->vNodes ); Vec_VecForEachLevelReverseStartStop( p->vMatrix, vFront, i, p->nWinTfiMax+1, 0 ) { Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pObj, k ) Vec_PtrPush( p->vNodes, pObj ); Vec_PtrClear( vFront ); } // get the lowest leaf level p->nLevLeafMin = ABC_INFINITY; Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, k ) p->nLevLeafMin = Abc_MinInt( p->nLevLeafMin, (int)pObj->Level ); // set minimum traversal level p->nLevTravMin = Abc_MaxInt( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin ); assert( p->nLevTravMin >= 0 ); return 1; } /**Function************************************************************* Synopsis [Returns 1 if the node should be a root.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Res_WinComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit ) { Abc_Obj_t * pFanout; int i; // the node is the root if one of the following is true: // (1) the node has more than fanouts than the limit if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit ) return 1; // (2) the node has CO fanouts // (3) the node has fanouts above the cutoff level Abc_ObjForEachFanout( pNode, pFanout, i ) if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax ) return 1; return 0; } /**Function************************************************************* Synopsis [Recursively collects the root candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots ) { Abc_Obj_t * pFanout; int i; assert( Abc_ObjIsNode(pNode) ); if ( Abc_NodeIsTravIdCurrent(pNode) ) return; Abc_NodeSetTravIdCurrent( pNode ); // check if the node should be the root if ( Res_WinComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) ) Vec_PtrPush( vRoots, pNode ); else // if not, explore its fanouts Abc_ObjForEachFanout( pNode, pFanout, i ) Res_WinComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots ); } /**Function************************************************************* Synopsis [Recursively collects the root candidates.] Description [Returns 1 if the only root is this node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_WinComputeRoots( Res_Win_t * p ) { Vec_PtrClear( p->vRoots ); Abc_NtkIncrementTravId( p->pNode->pNtk ); Res_WinComputeRoots_rec( p->pNode, p->pNode->Level + p->nWinTfoMax, p->nFanoutLimit, p->vRoots ); assert( Vec_PtrSize(p->vRoots) > 0 ); if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) return 0; return 1; } /**Function************************************************************* Synopsis [Marks the paths from the roots to the leaves.] Description [Returns 1 if the the node can reach a leaf.] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_WinMarkPaths_rec( Abc_Obj_t * pNode, Abc_Obj_t * pPivot, int nLevelMin ) { Abc_Obj_t * pFanin; int i, RetValue; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pNode) ) return 1; if ( Abc_NodeIsTravIdPrevious(pNode) ) return 0; // assume that the node does not have access to the leaves Abc_NodeSetTravIdPrevious( pNode ); // skip nodes below the given level if ( pNode == pPivot || (int)pNode->Level <= nLevelMin ) return 0; assert( Abc_ObjIsNode(pNode) ); // check if the fanins have access to the leaves RetValue = 0; Abc_ObjForEachFanin( pNode, pFanin, i ) RetValue |= Res_WinMarkPaths_rec( pFanin, pPivot, nLevelMin ); // relabel the node if it has access to the leaves if ( RetValue ) Abc_NodeSetTravIdCurrent( pNode ); return RetValue; } /**Function************************************************************* Synopsis [Marks the paths from the roots to the leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinMarkPaths( Res_Win_t * p ) { Abc_Obj_t * pObj; int i; // mark the leaves Abc_NtkIncrementTravId( p->pNode->pNtk ); Abc_NtkIncrementTravId( p->pNode->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); // traverse from the roots and mark the nodes that can reach leaves // the nodes that do not reach leaves have previous trav ID // the nodes that reach leaves have current trav ID Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i ) Res_WinMarkPaths_rec( pObj, p->pNode, p->nLevTravMin ); } /**Function************************************************************* Synopsis [Recursively collects the roots.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinFinalizeRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots ) { Abc_Obj_t * pFanout; int i; assert( Abc_ObjIsNode(pObj) ); assert( Abc_NodeIsTravIdCurrent(pObj) ); // check if the node has all fanouts marked Abc_ObjForEachFanout( pObj, pFanout, i ) if ( !Abc_NodeIsTravIdCurrent(pFanout) ) break; // if some of the fanouts are unmarked, add the node to the roots if ( i < Abc_ObjFanoutNum(pObj) ) Vec_PtrPushUnique( vRoots, pObj ); else // otherwise, call recursively Abc_ObjForEachFanout( pObj, pFanout, i ) Res_WinFinalizeRoots_rec( pFanout, vRoots ); } /**Function************************************************************* Synopsis [Finalizes the roots of the window.] Description [Roots of the window are the nodes that have at least one fanout that it not in the TFO of the leaves.] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_WinFinalizeRoots( Res_Win_t * p ) { assert( !Abc_NodeIsTravIdCurrent(p->pNode) ); // mark the node with the old traversal ID Abc_NodeSetTravIdCurrent( p->pNode ); // recollect the roots Vec_PtrClear( p->vRoots ); Res_WinFinalizeRoots_rec( p->pNode, p->vRoots ); assert( Vec_PtrSize(p->vRoots) > 0 ); if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) return 0; return 1; } /**Function************************************************************* Synopsis [Recursively adds missing nodes and leaves.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinAddMissing_rec( Res_Win_t * p, Abc_Obj_t * pObj, int nLevTravMin ) { Abc_Obj_t * pFanin; int i; // skip the already collected leaves, nodes, and branches if ( Abc_NodeIsTravIdCurrent(pObj) ) return; // if this is not an internal node - make it a new branch if ( !Abc_NodeIsTravIdPrevious(pObj) ) { assert( Vec_PtrFind(p->vLeaves, pObj) == -1 ); Abc_NodeSetTravIdCurrent( pObj ); Vec_PtrPush( p->vBranches, pObj ); return; } assert( Abc_ObjIsNode(pObj) ); // if this is a CI, then the window is incorrect! Abc_NodeSetTravIdCurrent( pObj ); // visit the fanins of the node Abc_ObjForEachFanin( pObj, pFanin, i ) Res_WinAddMissing_rec( p, pFanin, nLevTravMin ); // collect the node Vec_PtrPush( p->vNodes, pObj ); } /**Function************************************************************* Synopsis [Adds to the window nodes and leaves in the TFI of the roots.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Res_WinAddMissing( Res_Win_t * p ) { Abc_Obj_t * pObj; int i; // mark the leaves Abc_NtkIncrementTravId( p->pNode->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vLeaves, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); // mark the already collected nodes Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); // explore from the roots Vec_PtrClear( p->vBranches ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vRoots, pObj, i ) Res_WinAddMissing_rec( p, pObj, p->nLevTravMin ); } /**Function************************************************************* Synopsis [Returns 1 if the window is trivial (without TFO).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_WinIsTrivial( Res_Win_t * p ) { return Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode; } /**Function************************************************************* Synopsis [Computes the window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p ) { assert( Abc_ObjIsNode(pNode) ); assert( nWinTfiMax > 0 && nWinTfiMax < 10 ); assert( nWinTfoMax >= 0 && nWinTfoMax < 10 ); // initialize the window p->pNode = pNode; p->nWinTfiMax = nWinTfiMax; p->nWinTfoMax = nWinTfoMax; Vec_PtrClear( p->vBranches ); Vec_PtrClear( p->vDivs ); Vec_PtrClear( p->vRoots ); Vec_PtrPush( p->vRoots, pNode ); // compute the leaves if ( !Res_WinCollectLeavesAndNodes( p ) ) return 0; // compute the candidate roots if ( p->nWinTfoMax > 0 && Res_WinComputeRoots(p) ) { // mark the paths from the roots to the leaves Res_WinMarkPaths( p ); // refine the roots and add branches and missing nodes if ( Res_WinFinalizeRoots( p ) ) Res_WinAddMissing( p ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/res/res_.c000066400000000000000000000027001300674244400225220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [res_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Resynthesis package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 15, 2007.] Revision [$Id: res_.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "res.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/000077500000000000000000000000001300674244400214305ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/module.make000066400000000000000000000003461300674244400235570ustar00rootroot00000000000000SRC += src/opt/ret/retArea.c \ src/opt/ret/retCore.c \ src/opt/ret/retDelay.c \ src/opt/ret/retFlow.c \ src/opt/ret/retIncrem.c \ src/opt/ret/retInit.c \ src/opt/ret/retLvalue.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/retArea.c000066400000000000000000000446151300674244400231710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [retArea.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [Min-area retiming.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retArea.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fUseOldNames, int fVerbose ); static void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ); static void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); static Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); static void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward, int fUseOldNames ); extern Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs min-area retiming.] Description [Returns the number of latches reduced.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fUseOldNames, int fVerbose ) { Abc_Ntk_t * pNtkTotal = NULL, * pNtkBottom; Vec_Int_t * vValuesNew = NULL, * vValues; int nLatches = Abc_NtkLatchNum(pNtk); int fOneFrame = 0; assert( !fForwardOnly || !fBackwardOnly ); // there should not be black boxes assert( Abc_NtkIsSopLogic(pNtk) ); assert( Abc_NtkLatchNum(pNtk) == Vec_PtrSize(pNtk->vBoxes) ); // reorder CI/CO/latch inputs Abc_NtkOrderCisCos( pNtk ); // perform forward retiming if ( !fBackwardOnly ) { if ( fOneFrame ) Abc_NtkRetimeMinAreaOne( pNtk, 1, fUseOldNames, fVerbose ); else while ( Abc_NtkRetimeMinAreaOne( pNtk, 1, fUseOldNames, fVerbose ) ); } // remember initial values vValues = Abc_NtkCollectLatchValues( pNtk ); // perform backward retiming if ( !fForwardOnly ) { if ( fOneFrame ) pNtkTotal = Abc_NtkRetimeMinAreaOne( pNtk, 0, fUseOldNames, fVerbose ); else while ( (pNtkBottom = Abc_NtkRetimeMinAreaOne( pNtk, 0, fUseOldNames, fVerbose )) ) pNtkTotal = Abc_NtkAttachBottom( pNtkTotal, pNtkBottom ); } // compute initial values vValuesNew = Abc_NtkRetimeInitialValues( pNtkTotal, vValues, fVerbose ); if ( pNtkTotal ) Abc_NtkDelete( pNtkTotal ); // insert new initial values Abc_NtkInsertLatchValues( pNtk, vValuesNew ); if ( vValuesNew ) Vec_IntFree( vValuesNew ); if ( vValues ) Vec_IntFree( vValues ); // fix the COs (this changes the circuit structure) // Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); // check for correctness if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkRetimeMinArea(): Network check has failed.\n" ); // return the number of latches saved return nLatches - Abc_NtkLatchNum(pNtk); } /**Function************************************************************* Synopsis [Performs min-area retiming backward.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fUseOldNames, int fVerbose ) { Abc_Ntk_t * pNtkNew = NULL; Vec_Ptr_t * vMinCut; // mark current latches and TFI(POs) Abc_NtkRetimeMinAreaPrepare( pNtk, fForward ); // run the maximum forward flow vMinCut = Abc_NtkMaxFlow( pNtk, fForward, fVerbose ); // assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) ); // create new latch boundary if there is improvement if ( Vec_PtrSize(vMinCut) < Abc_NtkLatchNum(pNtk) ) { pNtkNew = (Abc_Ntk_t *)1; if ( fForward ) Abc_NtkRetimeMinAreaInitValues( pNtk, vMinCut ); else pNtkNew = Abc_NtkRetimeMinAreaConstructNtk( pNtk, vMinCut ); Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, fForward, fUseOldNames ); } // clean up Vec_PtrFree( vMinCut ); Abc_NtkCleanMarkA( pNtk ); return pNtkNew; } /**Function************************************************************* Synopsis [Marks the cone with MarkA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ) { Abc_Obj_t * pNext; int i; if ( pObj->fMarkA ) return; pObj->fMarkA = 1; if ( fForward ) { Abc_ObjForEachFanout( pObj, pNext, i ) Abc_NtkMarkCone_rec( pNext, fForward ); } else { Abc_ObjForEachFanin( pObj, pNext, i ) Abc_NtkMarkCone_rec( pNext, fForward ); } } /**Function************************************************************* Synopsis [Marks the cone with MarkA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkUnmarkCone_rec( Abc_Obj_t * pObj, int fForward ) { Abc_Obj_t * pNext; int i; if ( !pObj->fMarkA || Abc_ObjIsLatch(pObj) ) return; pObj->fMarkA = 0; if ( fForward ) { Abc_ObjForEachFanout( pObj, pNext, i ) Abc_NtkUnmarkCone_rec( pNext, fForward ); } else { Abc_ObjForEachFanin( pObj, pNext, i ) Abc_NtkUnmarkCone_rec( pNext, fForward ); } } /**Function************************************************************* Synopsis [Prepares the network for running MaxFlow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin; int i, k; if ( fForward ) { // mark the frontier Abc_NtkForEachPo( pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachLatch( pNtk, pObj, i ) { pObj->fMarkA = 1; Abc_ObjFanin0(pObj)->fMarkA = 1; } // mark the nodes reachable from the PIs Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkMarkCone_rec( pObj, fForward ); // collect the unmarked fanins of the marked nodes vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->fMarkA ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( !pFanin->fMarkA ) Vec_PtrPush( vNodes, pFanin ); // mark these nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->fMarkA = 1; Vec_PtrFree( vNodes ); } else { // mark the frontier Abc_NtkForEachPi( pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachLatch( pNtk, pObj, i ) { pObj->fMarkA = 1; Abc_ObjFanout0(pObj)->fMarkA = 1; } // mark the nodes reachable from the POs Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkMarkCone_rec( pObj, fForward ); } } /**Function************************************************************* Synopsis [Compute initial values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeMinAreaInitValues_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return (int)(ABC_PTRUINT_T)pObj->pCopy; Abc_NodeSetTravIdCurrent(pObj); // consider the case of a latch output if ( Abc_ObjIsBo(pObj) ) { assert( Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ); pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_NtkRetimeMinAreaInitValues_rec( Abc_ObjFanin0(pObj) ); return (int)(ABC_PTRUINT_T)pObj->pCopy; } assert( Abc_ObjIsNode(pObj) ); // visit the fanins Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_NtkRetimeMinAreaInitValues_rec( pFanin ); // compute the value of the node pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate(pObj); return (int)(ABC_PTRUINT_T)pObj->pCopy; } /**Function************************************************************* Synopsis [Compute initial values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) { Abc_Obj_t * pObj; int i; // transfer initial values to pCopy and mark the latches Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch( pNtk, pObj, i ) { pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_LatchIsInit1(pObj); Abc_NodeSetTravIdCurrent( pObj ); } // propagate initial values Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i ) Abc_NtkRetimeMinAreaInitValues_rec( pObj ); // unmark the latches Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_NodeSetTravIdPrevious( pObj ); } /**Function************************************************************* Synopsis [Performs min-area retiming backward.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkRetimeMinAreaConstructNtk_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return pObj->pCopy; Abc_NodeSetTravIdCurrent(pObj); // consider the case of a latch output if ( Abc_ObjIsBi(pObj) ) { pObj->pCopy = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) ); return pObj->pCopy; } assert( Abc_ObjIsNode(pObj) ); // visit the fanins Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, pFanin ); // compute the value of the node Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); return pObj->pCopy; } /**Function************************************************************* Synopsis [Creates the network from computing initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pObjNew; int i; // create new network pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); // map new latches into PIs of the new network Abc_NtkIncrementTravId(pNtk); Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i ) { pObj->pCopy = Abc_NtkCreatePi(pNtkNew); Abc_NodeSetTravIdCurrent( pObj ); } // construct the network recursively Abc_NtkForEachLatch( pNtk, pObj, i ) { pObjNew = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) ); Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObjNew ); } // unmark the nodes in the cut Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i ) Abc_NodeSetTravIdPrevious( pObj ); // unmark the latches Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_NodeSetTravIdPrevious( pObj ); // assign dummy node names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkRetimeMinAreaConstructNtk(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Updates the network after backward retiming.] Description [Assumes that fMarkA denotes all nodes reachabe from the latches toward the cut.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward, int fUseOldNames ) { Vec_Ptr_t * vCis, * vCos, * vBoxes, * vBoxesNew, * vNodes, * vBuffers; Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut, * pNext, * pBuffer; int i, k; // create new latches Vec_PtrShrink( pNtk->vCis, Abc_NtkCiNum(pNtk) - Abc_NtkLatchNum(pNtk) ); Vec_PtrShrink( pNtk->vCos, Abc_NtkCoNum(pNtk) - Abc_NtkLatchNum(pNtk) ); vCis = pNtk->vCis; pNtk->vCis = NULL; vCos = pNtk->vCos; pNtk->vCos = NULL; vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; // transfer boxes vBoxesNew = Vec_PtrAlloc(100); Vec_PtrForEachEntry( Abc_Obj_t *, vBoxes, pObj, i ) if ( !Abc_ObjIsLatch(pObj) ) Vec_PtrPush( vBoxesNew, pObj ); // create or reuse latches vNodes = Vec_PtrAlloc( 100 ); vBuffers = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i ) { if ( Abc_ObjIsCi(pObj) && fForward ) { pLatchOut = pObj; pLatch = Abc_ObjFanin0(pLatchOut); pLatchIn = Abc_ObjFanin0(pLatch); assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) ); // mark the latch as reused Abc_NodeSetTravIdCurrent( pLatch ); // check if there are marked fanouts // (these are fanouts to be connected to the latch input) Abc_ObjForEachFanout( pObj, pNext, k ) if ( pNext->fMarkA ) break; if ( k < Abc_ObjFanoutNum(pObj) ) { // add the buffer pBuffer = Abc_NtkCreateNodeBuf( pNtk, Abc_ObjFanin0(pLatchIn) ); Abc_ObjAssignName( pBuffer, Abc_ObjName(pObj), "_buf" ); Abc_ObjPatchFanin( pLatchIn, Abc_ObjFanin0(pLatchIn), pBuffer ); Vec_PtrPush( vBuffers, pBuffer ); // redirect edges to the unvisited fanouts of the node Abc_NodeCollectFanouts( pObj, vNodes ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, k ) if ( pNext->fMarkA ) Abc_ObjPatchFanin( pNext, pObj, pBuffer ); } assert( Abc_ObjFanoutNum(pObj) > 0 ); // if ( Abc_ObjFanoutNum(pObj) == 0 ) // Abc_NtkDeleteObj_rec( pObj, 0 ); } else if ( Abc_ObjIsCo(pObj) && !fForward ) { pLatchIn = pObj; pLatch = Abc_ObjFanout0(pLatchIn); pLatchOut = Abc_ObjFanout0(pLatch); assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) ); // mark the latch as reused Abc_NodeSetTravIdCurrent( pLatch ); assert( !Abc_ObjFanin0(pLatchIn)->fMarkA ); } else { pLatchOut = Abc_NtkCreateBo(pNtk); pLatch = Abc_NtkCreateLatch(pNtk); pLatchIn = Abc_NtkCreateBi(pNtk); if ( fUseOldNames ) { Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" ); Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" ); } else { Abc_ObjAssignName( pLatchOut, Abc_ObjName(pObj), "_o1" ); Abc_ObjAssignName( pLatchIn, Abc_ObjName(pObj), "_i1" ); } // connect Abc_ObjAddFanin( pLatchOut, pLatch ); Abc_ObjAddFanin( pLatch, pLatchIn ); if ( fForward ) { pLatch->pData = (void *)(ABC_PTRUINT_T)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO); // redirect edges to the unvisited fanouts of the node Abc_NodeCollectFanouts( pObj, vNodes ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, k ) if ( !pNext->fMarkA ) Abc_ObjPatchFanin( pNext, pObj, pLatchOut ); } else { // redirect edges to the visited fanouts of the node Abc_NodeCollectFanouts( pObj, vNodes ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, k ) if ( pNext->fMarkA ) Abc_ObjPatchFanin( pNext, pObj, pLatchOut ); } // connect latch to the node Abc_ObjAddFanin( pLatchIn, pObj ); } Vec_PtrPush( vCis, pLatchOut ); Vec_PtrPush( vBoxesNew, pLatch ); Vec_PtrPush( vCos, pLatchIn ); } Vec_PtrFree( vNodes ); // remove buffers Vec_PtrForEachEntry( Abc_Obj_t *, vBuffers, pObj, i ) { Abc_ObjTransferFanout( pObj, Abc_ObjFanin0(pObj) ); Abc_NtkDeleteObj( pObj ); } Vec_PtrFree( vBuffers ); // remove useless latches Vec_PtrForEachEntry( Abc_Obj_t *, vBoxes, pObj, i ) { if ( !Abc_ObjIsLatch(pObj) ) continue; if ( Abc_NodeIsTravIdCurrent(pObj) ) continue; pLatchOut = Abc_ObjFanout0(pObj); pLatch = pObj; pLatchIn = Abc_ObjFanin0(pObj); if ( Abc_ObjFanoutNum(pLatchOut) > 0 ) Abc_ObjTransferFanout( pLatchOut, Abc_ObjFanin0(pLatchIn) ); Abc_NtkDeleteObj( pLatchOut ); Abc_NtkDeleteObj( pObj ); Abc_NtkDeleteObj( pLatchIn ); } // set the arrays pNtk->vCis = vCis; pNtk->vCos = vCos; pNtk->vBoxes = vBoxesNew; Vec_PtrFree( vBoxes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/retCore.c000066400000000000000000000114551300674244400232050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [retCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [The core retiming procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retCore.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// abctime timeRetime = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Implementation of retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int nDelayLim, int fForwardOnly, int fBackwardOnly, int fOneStep, int fUseOldNames, int fVerbose ) { int nLatches = Abc_NtkLatchNum(pNtk); int nLevels = Abc_NtkLevel(pNtk); int RetValue = 0; abctime clkTotal = Abc_Clock(); int nNodesOld, nLatchesOld; assert( Mode > 0 && Mode < 7 ); assert( !fForwardOnly || !fBackwardOnly ); // cleanup the network nNodesOld = Abc_NtkNodeNum(pNtk); nLatchesOld = Abc_NtkLatchNum(pNtk); Abc_NtkCleanupSeq(pNtk, 0, 0, 0); if ( nNodesOld > Abc_NtkNodeNum(pNtk) || nLatchesOld > Abc_NtkLatchNum(pNtk) ) printf( "Cleanup before retiming removed %d dangling nodes and %d dangling latches.\n", nNodesOld - Abc_NtkNodeNum(pNtk), nLatchesOld - Abc_NtkLatchNum(pNtk) ); // perform retiming switch ( Mode ) { case 1: // forward RetValue = Abc_NtkRetimeIncremental( pNtk, nDelayLim, 1, 0, 0, fUseOldNames, fVerbose ); break; case 2: // backward RetValue = Abc_NtkRetimeIncremental( pNtk, nDelayLim, 0, 0, 0, fUseOldNames, fVerbose ); break; case 3: // min-area RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fUseOldNames, fVerbose ); break; case 4: // min-delay if ( !fBackwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, nDelayLim, 1, 1, fOneStep, fUseOldNames, fVerbose ); if ( !fForwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, nDelayLim, 0, 1, fOneStep, fUseOldNames, fVerbose ); break; case 5: // min-area + min-delay RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fUseOldNames, fVerbose ); if ( !fBackwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, nDelayLim, 1, 1, 0, fUseOldNames, fVerbose ); if ( !fForwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, nDelayLim, 0, 1, 0, fUseOldNames, fVerbose ); break; case 6: // Pan's algorithm RetValue = Abc_NtkRetimeLValue( pNtk, 500, fVerbose ); break; default: printf( "Unknown retiming option.\n" ); break; } if ( fVerbose ) { printf( "Reduction in area = %3d. Reduction in delay = %3d. ", nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkLevel(pNtk) ); ABC_PRT( "Total runtime", Abc_Clock() - clkTotal ); } timeRetime = Abc_Clock() - clkTotal; return RetValue; } /**Function************************************************************* Synopsis [Used for automated debugging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk ) { extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); Abc_Ntk_t * pNtkRet; assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); // if ( !Abc_NtkCheck( pNtk ) ) // fprintf( stdout, "Abc_NtkRetimeDebug(): Network check has failed.\n" ); // Io_WriteBlifLogic( pNtk, "debug_temp.blif", 1 ); pNtkRet = Abc_NtkDup( pNtk ); Abc_NtkRetime( pNtkRet, 3, 0, 0, 1, 0, 1, 0 ); // debugging backward flow return !Abc_NtkSecFraig( pNtk, pNtkRet, 10000, 3, 0 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/retDelay.c000066400000000000000000000245171300674244400233560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [retDelay.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [Incremental retiming for optimum delay.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retDelay.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose ); static int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical ); static int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Retimes incrementally for minimum delay.] Description [This procedure cannot be called in the application code because it assumes that the network is preprocessed by removing LIs/LOs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nDelayLim, int nIterLimit, int fForward, int fVerbose ) { int IterBest, DelayBest; int IterBest2, DelayBest2; // try to find the best delay iteration on a copy DelayBest = Abc_NtkRetimeMinDelayTry( pNtkCopy, nDelayLim, fForward, 0, nIterLimit, &IterBest, fVerbose ); if ( IterBest == 0 ) return 1; // perform the given number of iterations on the original network DelayBest2 = Abc_NtkRetimeMinDelayTry( pNtk, nDelayLim, fForward, 1, IterBest, &IterBest2, fVerbose ); assert( DelayBest == DelayBest2 ); assert( IterBest == IterBest2 ); return 1; } /**Function************************************************************* Synopsis [Returns the best delay and the number of best iteration.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose ) { Abc_Ntk_t * pNtkNew = NULL; Vec_Ptr_t * vCritical; Vec_Int_t * vValues = NULL; // Suppress "might be used uninitialized" Abc_Obj_t * pObj; int i, k, IterBest, DelayCur, DelayBest; int DelayStart = -1; // Suppress "might be used uninitialized" int LatchesBest; // transfer intitial values if ( fInitial ) { if ( fForward ) Abc_NtkRetimeTranferToCopy( pNtk ); else { // save initial value of the latches vValues = Abc_NtkRetimeCollectLatchValues( pNtk ); // start the network for initial value computation pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk ); } } if ( fVerbose && !fInitial ) printf( "Performing analysis:\n" ); // find the best iteration DelayBest = ABC_INFINITY; IterBest = 0; LatchesBest = Abc_NtkLatchNum(pNtk); vCritical = Vec_PtrAlloc( 100 ); for ( i = 0; ; i++ ) { // perform moves for the timing-critical nodes DelayCur = Abc_NtkRetimeTiming( pNtk, fForward, vCritical ); if ( i == 0 ) DelayStart = DelayCur; // record this position if it has the best delay if ( DelayBest > DelayCur ) { if ( fVerbose && !fInitial ) printf( "%s Iter = %3d. Delay = %3d. Latches = %5d. Delta = %6.2f. Ratio = %4.2f %%\n", fForward ? "Fwd": "Bwd", i, DelayCur, Abc_NtkLatchNum(pNtk), 1.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/(DelayBest-DelayCur), 100.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/Abc_NtkLatchNum(pNtk)/(DelayBest-DelayCur) ); DelayBest = DelayCur; IterBest = i; LatchesBest = Abc_NtkLatchNum(pNtk); } // quit after timing analysis if ( i == nIterLimit ) break; // skip if 10 interations did not give improvement if ( i - IterBest > 20 ) break; // skip if delay limit is reached if ( nDelayLim > 0 && DelayCur <= nDelayLim ) break; // try retiming to improve the delay Vec_PtrForEachEntry( Abc_Obj_t *, vCritical, pObj, k ) if ( Abc_NtkRetimeNodeIsEnabled(pObj, fForward) ) Abc_NtkRetimeNode( pObj, fForward, fInitial ); // share latches if ( !fForward ) Abc_NtkRetimeShareLatches( pNtk, fInitial ); } Vec_PtrFree( vCritical ); // transfer the initial state back to the latches if ( fInitial ) { if ( fForward ) Abc_NtkRetimeTranferFromCopy( pNtk ); else { Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose ); Abc_NtkDelete( pNtkNew ); Vec_IntFree( vValues ); } } if ( fVerbose && !fInitial ) printf( "%s : Starting delay = %3d. Final delay = %3d. IterBest = %2d (out of %2d).\n", fForward? "Forward " : "Backward", DelayStart, DelayBest, IterBest, nIterLimit ); *pIterBest = (nIterLimit == 1) ? 1 : IterBest; return DelayBest; } /**Function************************************************************* Synopsis [Returns the set of timing-critical nodes.] Description [Performs static timing analysis on the network. Uses unit-delay model.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical ) { Vec_Ptr_t * vLatches; Abc_Obj_t * pObj, * pNext; int i, k, LevelCur, LevelMax = 0; // mark all objects except nodes Abc_NtkIncrementTravId(pNtk); vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachObj( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) Vec_PtrPush( vLatches, pObj ); if ( Abc_ObjIsNode(pObj) ) continue; pObj->Level = 0; Abc_NodeSetTravIdCurrent( pObj ); } // perform analysis from CIs/COs if ( fForward ) { Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) { Abc_ObjForEachFanout( pObj, pNext, k ) { LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } Abc_NtkForEachPi( pNtk, pObj, i ) { Abc_ObjForEachFanout( pObj, pNext, k ) { LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } } else { Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) { LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } Abc_NtkForEachPo( pNtk, pObj, i ) { LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } // collect timing critical nodes, which should be retimed forward/backward Vec_PtrClear( vCritical ); Abc_NtkIncrementTravId(pNtk); if ( fForward ) { Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) { Abc_ObjForEachFanout( pObj, pNext, k ) { if ( Abc_NodeIsTravIdCurrent(pNext) ) continue; if ( LevelMax != (int)pNext->Level ) continue; // new critical node Vec_PtrPush( vCritical, pNext ); Abc_NodeSetTravIdCurrent( pNext ); } } } else { Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) { Abc_ObjForEachFanin( pObj, pNext, k ) { if ( Abc_NodeIsTravIdCurrent(pNext) ) continue; if ( LevelMax != (int)pNext->Level ) continue; // new critical node Vec_PtrPush( vCritical, pNext ); Abc_NodeSetTravIdCurrent( pNext ); } } } Vec_PtrFree( vLatches ); return LevelMax; } /**Function************************************************************* Synopsis [Recursively performs timing analysis.] Description [Performs static timing analysis on the network. Uses unit-delay model.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward ) { Abc_Obj_t * pNext; int i, LevelCur, LevelMax = 0; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return pObj->Level; Abc_NodeSetTravIdCurrent(pObj); // visit the next nodes if ( fForward ) { Abc_ObjForEachFanout( pObj, pNext, i ) { LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } else { Abc_ObjForEachFanin( pObj, pNext, i ) { LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } // printf( "Node %3d -> Level %3d.\n", pObj->Id, LevelMax + 1 ); pObj->Level = LevelMax + 1; return pObj->Level; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/retFlow.c000066400000000000000000000606251300674244400232270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [retFlow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Implementation of maximum flow (min-area retiming).] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retFlow.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Abc_ObjSetPath( Abc_Obj_t * pObj, Abc_Obj_t * pNext ) { pObj->pCopy = pNext; return 1; } static inline Abc_Obj_t * Abc_ObjGetPath( Abc_Obj_t * pObj ) { return pObj->pCopy; } static inline Abc_Obj_t * Abc_ObjGetFanoutPath( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; assert( Abc_ObjGetPath(pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_ObjGetPath(pFanout) == pObj ) return pFanout; return NULL; } static inline Abc_Obj_t * Abc_ObjGetFaninPath( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; assert( Abc_ObjGetPath(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, i ) if ( Abc_ObjGetPath(pFanin) == pObj ) return pFanin; return NULL; } static inline Abc_Obj_t * Abc_ObjGetPredecessorBwd( Abc_Obj_t * pObj ) { Abc_Obj_t * pNext; int i; Abc_ObjForEachFanout( pObj, pNext, i ) if ( Abc_ObjGetPath(pNext) == pObj ) return pNext; Abc_ObjForEachFanin( pObj, pNext, i ) if ( Abc_ObjGetPath(pNext) == pObj ) return pNext; return NULL; } static inline Abc_Obj_t * Abc_ObjGetPredecessorFwd( Abc_Obj_t * pObj ) { Abc_Obj_t * pNext; int i; Abc_ObjForEachFanin( pObj, pNext, i ) if ( Abc_ObjGetPath(pNext) == pObj ) return pNext; Abc_ObjForEachFanout( pObj, pNext, i ) if ( Abc_ObjGetPath(pNext) == pObj ) return pNext; return NULL; } static int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ); static int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ); static int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj ); static int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj ); //static int Abc_NtkMaxFlowBwdPath3_rec( Abc_Obj_t * pObj ); static int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin ); static Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward ); static void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); static int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); static void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); static void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Test-bench for the max-flow computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vMinCut; Abc_Obj_t * pObj; int i; // forward flow Abc_NtkForEachPo( pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->fMarkA = Abc_ObjFanin0(pObj)->fMarkA = 1; // Abc_ObjFanin0(pObj)->fMarkA = 1; vMinCut = Abc_NtkMaxFlow( pNtk, 1, 1 ); Vec_PtrFree( vMinCut ); Abc_NtkCleanMarkA( pNtk ); // backward flow Abc_NtkForEachPi( pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->fMarkA = Abc_ObjFanout0(pObj)->fMarkA = 1; // Abc_ObjFanout0(pObj)->fMarkA = 1; vMinCut = Abc_NtkMaxFlow( pNtk, 0, 1 ); Vec_PtrFree( vMinCut ); Abc_NtkCleanMarkA( pNtk ); } /**Function************************************************************* Synopsis [Implementation of max-flow/min-cut computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) { Vec_Ptr_t * vMinCut; Abc_Obj_t * pLatch; int Flow, FlowCur, RetValue, i; abctime clk = Abc_Clock(); int fUseDirectedFlow = 1; // find the max-flow Abc_NtkCleanCopy( pNtk ); Flow = 0; Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( fForward ) { // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); FlowCur = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); // FlowCur = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 ); Flow += FlowCur; } else { assert( !Abc_ObjFanin0(pLatch)->fMarkA ); FlowCur = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); Flow += FlowCur; } if ( FlowCur ) Abc_NtkIncrementTravId(pNtk); } if ( !fUseDirectedFlow ) { Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( fForward ) { // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); FlowCur = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); Flow += FlowCur; } else { assert( !Abc_ObjFanin0(pLatch)->fMarkA ); FlowCur = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); Flow += FlowCur; } if ( FlowCur ) Abc_NtkIncrementTravId(pNtk); } } // Abc_NtkMaxFlowPrintFlow( pNtk, fForward ); // mark the nodes reachable from the latches Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( fForward ) { // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); if ( fUseDirectedFlow ) RetValue = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); // RetValue = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 ); else RetValue = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); } else { assert( !Abc_ObjFanin0(pLatch)->fMarkA ); if ( fUseDirectedFlow ) RetValue = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); else RetValue = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); } assert( RetValue == 0 ); } // find the min-cut with the smallest volume vMinCut = Abc_NtkMaxFlowMinCut( pNtk, fForward ); // verify the cut if ( !Abc_NtkMaxFlowVerifyCut(pNtk, vMinCut, fForward) ) printf( "Abc_NtkMaxFlow() error! The computed min-cut is not a cut!\n" ); // make the cut retimable Abc_NtkMaxFlowMinCutUpdate( pNtk, vMinCut, fForward ); // report the results if ( fVerbose ) { printf( "L = %6d. %s max-flow = %6d. Min-cut = %6d. ", Abc_NtkLatchNum(pNtk), fForward? "Forward " : "Backward", Flow, Vec_PtrSize(vMinCut) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // Abc_NtkMaxFlowPrintCut( pNtk, vMinCut ); return vMinCut; } /**Function************************************************************* Synopsis [Tries to find an augmenting path originating in this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pNext, * pPred; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return 0; Abc_NodeSetTravIdCurrent(pObj); // get the predecessor pPred = Abc_ObjGetPredecessorBwd( pObj ); // process node without flow if ( !Abc_ObjGetPath(pObj) ) { // start the path if we reached a terminal node if ( pObj->fMarkA ) return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 ); // explore the fanins Abc_ObjForEachFanin( pObj, pNext, i ) if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) ) return Abc_ObjSetPath( pObj, pNext ); Abc_ObjForEachFanout( pObj, pNext, i ) if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) ) return Abc_ObjSetPath( pObj, pNext ); return 0; } // pObj has flow - find the fanout with flow if ( pPred == NULL ) return 0; // go through the successors of the predecessor Abc_ObjForEachFanin( pPred, pNext, i ) if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) ) return Abc_ObjSetPath( pPred, pNext ); Abc_ObjForEachFanout( pPred, pNext, i ) if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) ) return Abc_ObjSetPath( pPred, pNext ); // try the fanout if ( Abc_NtkMaxFlowBwdPath_rec( pPred ) ) return Abc_ObjSetPath( pPred, NULL ); return 0; } /**Function************************************************************* Synopsis [Tries to find an augmenting path originating in this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pNext, * pPred; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return 0; Abc_NodeSetTravIdCurrent(pObj); // get the predecessor pPred = Abc_ObjGetPredecessorFwd( pObj ); // process node without flow if ( !Abc_ObjGetPath(pObj) ) { // start the path if we reached a terminal node if ( pObj->fMarkA ) return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 ); // explore the fanins Abc_ObjForEachFanout( pObj, pNext, i ) if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) ) return Abc_ObjSetPath( pObj, pNext ); Abc_ObjForEachFanin( pObj, pNext, i ) if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) ) return Abc_ObjSetPath( pObj, pNext ); return 0; } // pObj has flow - find the fanout with flow if ( pPred == NULL ) return 0; // go through the successors of the predecessor Abc_ObjForEachFanout( pPred, pNext, i ) if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) ) return Abc_ObjSetPath( pPred, pNext ); Abc_ObjForEachFanin( pPred, pNext, i ) if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) ) return Abc_ObjSetPath( pPred, pNext ); // try the fanout if ( Abc_NtkMaxFlowFwdPath_rec( pPred ) ) return Abc_ObjSetPath( pPred, NULL ); return 0; } /**Function************************************************************* Synopsis [Tries to find an augmenting path originating in this edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin ) { Abc_Obj_t * pFanin, * pFanout; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return 0; Abc_NodeSetTravIdCurrent(pObj); // skip the fanin which already has flow if ( fFanin && Abc_ObjGetPath(pPrev) ) return 0; // if the node has no flow, try to push through the fanouts if ( !Abc_ObjGetPath(pObj) ) { // start the path if we reached a terminal node if ( pObj->fMarkA ) return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 ); // try to push flow through the fanouts Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_NtkMaxFlowFwdPath3_rec(pFanout, pObj, 1) ) return fFanin? Abc_ObjSetPath(pPrev, pObj) : 1; } // try to push through the fanins Abc_ObjForEachFanin( pObj, pFanin, i ) if ( !Abc_ObjIsLatch(pFanin) && Abc_NtkMaxFlowFwdPath3_rec(pFanin, pObj, 0) ) return Abc_ObjSetPath( pFanin, NULL ); return 0; } /**Function************************************************************* Synopsis [Tries to find an augmenting path originating in this node.] Description [This procedure works for directed graphs only!] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout, * pFanin; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return 0; Abc_NodeSetTravIdCurrent(pObj); // process node without flow if ( !Abc_ObjGetPath(pObj) ) { // start the path if we reached a terminal node if ( pObj->fMarkA ) return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 ); // explore the fanins Abc_ObjForEachFanin( pObj, pFanin, i ) if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) return Abc_ObjSetPath( pObj, pFanin ); return 0; } // pObj has flow - find the fanout with flow pFanout = Abc_ObjGetFanoutPath( pObj ); if ( pFanout == NULL ) return 0; // go through the fanins of the fanout with flow Abc_ObjForEachFanin( pFanout, pFanin, i ) if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) ) return Abc_ObjSetPath( pFanout, pFanin ); // try the fanout if ( Abc_NtkMaxFlowBwdPath2_rec( pFanout ) ) return Abc_ObjSetPath( pFanout, NULL ); return 0; } /**Function************************************************************* Synopsis [Tries to find an augmenting path originating in this node.] Description [This procedure works for directed graphs only!] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout, * pFanin; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return 0; Abc_NodeSetTravIdCurrent(pObj); // process node without flow if ( !Abc_ObjGetPath(pObj) ) { // start the path if we reached a terminal node if ( pObj->fMarkA ) return Abc_ObjSetPath( pObj, (Abc_Obj_t *)1 ); // explore the fanins Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_NtkMaxFlowFwdPath2_rec(pFanout) ) return Abc_ObjSetPath( pObj, pFanout ); return 0; } // pObj has flow - find the fanout with flow pFanin = Abc_ObjGetFaninPath( pObj ); if ( pFanin == NULL ) return 0; // go through the fanins of the fanout with flow Abc_ObjForEachFanout( pFanin, pFanout, i ) if ( Abc_NtkMaxFlowFwdPath2_rec( pFanout ) ) return Abc_ObjSetPath( pFanin, pFanout ); // try the fanout if ( Abc_NtkMaxFlowFwdPath2_rec( pFanin ) ) return Abc_ObjSetPath( pFanin, NULL ); return 0; } /**Function************************************************************* Synopsis [Find minimum-volume minumum cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward ) { Vec_Ptr_t * vMinCut; Abc_Obj_t * pObj; int i; // collect the cut nodes vMinCut = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachObj( pNtk, pObj, i ) { // node without flow is not a cut node if ( !Abc_ObjGetPath(pObj) ) continue; // unvisited node is below the cut if ( !Abc_NodeIsTravIdCurrent(pObj) ) continue; // add terminal with flow or node whose path is not visited if ( pObj->fMarkA || !Abc_NodeIsTravIdCurrent( Abc_ObjGetPath(pObj) ) ) Vec_PtrPush( vMinCut, pObj ); } return vMinCut; } /**Function************************************************************* Synopsis [Marks the TFI cone with MarkA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMaxFlowMarkCut_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pNext; int i; if ( pObj->fMarkA ) return; pObj->fMarkA = 1; Abc_ObjForEachFanin( pObj, pNext, i ) Abc_NtkMaxFlowMarkCut_rec( pNext ); } /**Function************************************************************* Synopsis [Visits the TFI up to marked nodes and collects marked nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMaxFlowCollectCut_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pNext; int i; if ( Abc_NodeIsTravIdCurrent(pObj) ) return; Abc_NodeSetTravIdCurrent(pObj); if ( pObj->fMarkA ) { Vec_PtrPush( vNodes, pObj ); return; } Abc_ObjForEachFanin( pObj, pNext, i ) Abc_NtkMaxFlowCollectCut_rec( pNext, vNodes ); } /**Function************************************************************* Synopsis [Updates the minimum cut to be retimable.] Description [This procedure also labels the nodes reachable from the latches to the cut with fMarkA.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) { Abc_Obj_t * pObj, * pNext; int i, k; // clean marks Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkA = 0; // set latch outputs Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjFanout0(pObj)->fMarkA = 1; // traverse from cut nodes Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i ) Abc_NtkMaxFlowMarkCut_rec( pObj ); if ( fForward ) { // change mincut to be nodes with unmarked fanouts Vec_PtrClear( vMinCut ); Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !pObj->fMarkA ) continue; Abc_ObjForEachFanout( pObj, pNext, k ) { if ( pNext->fMarkA ) continue; Vec_PtrPush( vMinCut, pObj ); break; } } } else { // change mincut to be marked fanins of the unmarked nodes Vec_PtrClear( vMinCut ); Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_NtkMaxFlowCollectCut_rec( Abc_ObjFanin0(pObj), vMinCut ); // transfer the attribute Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkA = Abc_NodeIsTravIdCurrent(pObj); // unmark the cut nodes Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i ) pObj->fMarkA = 0; } } /**Function************************************************************* Synopsis [Verifies the min-cut is indeed a cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMaxFlowVerifyCut_rec( Abc_Obj_t * pObj, int fForward ) { Abc_Obj_t * pNext; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return 1; Abc_NodeSetTravIdCurrent(pObj); // visit the node if ( fForward ) { if ( Abc_ObjIsCo(pObj) ) return 0; // explore the fanouts Abc_ObjForEachFanout( pObj, pNext, i ) if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) ) return 0; } else { if ( Abc_ObjIsCi(pObj) ) return 0; // explore the fanins Abc_ObjForEachFanin( pObj, pNext, i ) if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Verifies the min-cut is indeed a cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) { Abc_Obj_t * pObj; int i; // mark the cut with the current traversal ID Abc_NtkIncrementTravId(pNtk); Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); // search from the latches for a path to the COs/CIs Abc_NtkForEachLatch( pNtk, pObj, i ) { if ( fForward ) { if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanout0(pObj), fForward ) ) return 0; } else { if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanin0(pObj), fForward ) ) return 0; } } /* { // count the volume of the cut int Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) Counter += Abc_NodeIsTravIdCurrent( pObj ); printf( "Volume = %d.\n", Counter ); } */ return 1; } /**Function************************************************************* Synopsis [Prints the flows.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward ) { Abc_Obj_t * pLatch, * pNext; Abc_Obj_t * pPrev = NULL; // Suppress "might be used uninitialized" int i; if ( fForward ) { Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vBoxes, pLatch, i ) { assert( !Abc_ObjFanout0(pLatch)->fMarkA ); if ( Abc_ObjGetPath(Abc_ObjFanout0(pLatch)) == NULL ) // no flow through this latch continue; printf( "Path = " ); for ( pNext = Abc_ObjFanout0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) ) { printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id ); pPrev = pNext; } if ( !Abc_ObjIsPo(pPrev) ) printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanout0(pPrev)), Abc_ObjFanout0(pPrev)->Id ); printf( "\n" ); } } else { Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vBoxes, pLatch, i ) { assert( !Abc_ObjFanin0(pLatch)->fMarkA ); if ( Abc_ObjGetPath(Abc_ObjFanin0(pLatch)) == NULL ) // no flow through this latch continue; printf( "Path = " ); for ( pNext = Abc_ObjFanin0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) ) { printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id ); pPrev = pNext; } if ( !Abc_ObjIsPi(pPrev) ) printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanin0(pPrev)), Abc_ObjFanin0(pPrev)->Id ); printf( "\n" ); } } } /**Function************************************************************* Synopsis [Prints the min-cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) { Abc_Obj_t * pObj; int i; printf( "Min-cut: " ); Vec_PtrForEachEntry( Abc_Obj_t *, vMinCut, pObj, i ) printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id ); printf( "\n" ); printf( "Marked nodes: " ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->fMarkA ) printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id ); printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/retIncrem.c000066400000000000000000000401111300674244400235210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [retIncrem.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [Incremental retiming in one direction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retIncrem.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs retiming in one direction.] Description [Currently does not retime over black boxes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fMinDelay, int fOneStep, int fUseOldNames, int fVerbose ) { Abc_Ntk_t * pNtkCopy = NULL; Vec_Ptr_t * vBoxes; st__table * tLatches; int nLatches = Abc_NtkLatchNum(pNtk); int nIdMaxStart = Abc_NtkObjNumMax(pNtk); int RetValue; int nIterLimit = -1; // Suppress "might be used uninitialized" if ( Abc_NtkNodeNum(pNtk) == 0 ) return 0; // reorder CI/CO/latch inputs Abc_NtkOrderCisCos( pNtk ); if ( fMinDelay ) { nIterLimit = fOneStep? 1 : 2 * Abc_NtkLevel(pNtk); pNtkCopy = Abc_NtkDup( pNtk ); tLatches = Abc_NtkRetimePrepareLatches( pNtkCopy ); st__free_table( tLatches ); } // collect latches and remove CIs/COs tLatches = Abc_NtkRetimePrepareLatches( pNtk ); // share the latches Abc_NtkRetimeShareLatches( pNtk, 0 ); // save boxes vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; // perform the retiming if ( fMinDelay ) Abc_NtkRetimeMinDelay( pNtk, pNtkCopy, nDelayLim, nIterLimit, fForward, fVerbose ); else Abc_NtkRetimeOneWay( pNtk, fForward, fVerbose ); if ( fMinDelay ) Abc_NtkDelete( pNtkCopy ); // share the latches Abc_NtkRetimeShareLatches( pNtk, 0 ); // restore boxes pNtk->vBoxes = vBoxes; // finalize the latches RetValue = Abc_NtkRetimeFinalizeLatches( pNtk, tLatches, nIdMaxStart, fUseOldNames ); st__free_table( tLatches ); if ( RetValue == 0 ) return 0; // fix the COs // Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); // check for correctness if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkRetimeForward(): Network check has failed.\n" ); // return the number of latches saved return nLatches - Abc_NtkLatchNum(pNtk); } /**Function************************************************************* Synopsis [Prepares the network for retiming.] Description [Hash latches into their number in the original network.] SideEffects [] SeeAlso [] ***********************************************************************/ st__table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ) { st__table * tLatches; Abc_Obj_t * pLatch, * pLatchIn, * pLatchOut, * pFanin; int i, nOffSet = Abc_NtkBoxNum(pNtk) - Abc_NtkLatchNum(pNtk); // collect latches and remove CIs/COs tLatches = st__init_table( st__ptrcmp, st__ptrhash ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { // map latch into its true number st__insert( tLatches, (char *)(ABC_PTRUINT_T)pLatch, (char *)(ABC_PTRUINT_T)(i-nOffSet) ); // disconnect LI pLatchIn = Abc_ObjFanin0(pLatch); pFanin = Abc_ObjFanin0(pLatchIn); Abc_ObjTransferFanout( pLatchIn, pFanin ); Abc_ObjDeleteFanin( pLatchIn, pFanin ); // disconnect LO pLatchOut = Abc_ObjFanout0(pLatch); pFanin = Abc_ObjFanin0(pLatchOut); if ( Abc_ObjFanoutNum(pLatchOut) > 0 ) Abc_ObjTransferFanout( pLatchOut, pFanin ); Abc_ObjDeleteFanin( pLatchOut, pFanin ); } return tLatches; } /**Function************************************************************* Synopsis [Finalizes the latches after retiming.] Description [Reuses the LIs/LOs for old latches.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st__table * tLatches, int nIdMaxStart, int fUseOldNames ) { Vec_Ptr_t * vCisOld, * vCosOld, * vBoxesOld, * vCisNew, * vCosNew, * vBoxesNew; Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut; int i, Index; // create new arrays vCisOld = pNtk->vCis; pNtk->vCis = NULL; vCisNew = Vec_PtrAlloc( 100 ); vCosOld = pNtk->vCos; pNtk->vCos = NULL; vCosNew = Vec_PtrAlloc( 100 ); vBoxesOld = pNtk->vBoxes; pNtk->vBoxes = NULL; vBoxesNew = Vec_PtrAlloc( 100 ); // copy boxes and their CIs/COs Vec_PtrForEachEntryStop( Abc_Obj_t *, vCisOld, pObj, i, Vec_PtrSize(vCisOld) - st__count(tLatches) ) Vec_PtrPush( vCisNew, pObj ); Vec_PtrForEachEntryStop( Abc_Obj_t *, vCosOld, pObj, i, Vec_PtrSize(vCosOld) - st__count(tLatches) ) Vec_PtrPush( vCosNew, pObj ); Vec_PtrForEachEntryStop( Abc_Obj_t *, vBoxesOld, pObj, i, Vec_PtrSize(vBoxesOld) - st__count(tLatches) ) Vec_PtrPush( vBoxesNew, pObj ); // go through the latches Abc_NtkForEachObj( pNtk, pLatch, i ) { if ( !Abc_ObjIsLatch(pLatch) ) continue; if ( Abc_ObjId(pLatch) >= (unsigned)nIdMaxStart ) { // this is a new latch pLatchIn = Abc_NtkCreateBi(pNtk); pLatchOut = Abc_NtkCreateBo(pNtk); if ( fUseOldNames ) { Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" ); Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" ); } else { Abc_ObjAssignName( pLatchOut, Abc_ObjName(Abc_ObjFanin0(pLatch)), "_o2" ); Abc_ObjAssignName( pLatchIn, Abc_ObjName(Abc_ObjFanin0(pLatch)), "_i2" ); } } else { // this is an old latch // get its number in the original order if ( ! st__lookup_int( tLatches, (char *)pLatch, &Index ) ) { printf( "Abc_NtkRetimeFinalizeLatches(): Internal error.\n" ); return 0; } assert( pLatch == Vec_PtrEntry(vBoxesOld, Vec_PtrSize(vBoxesOld) - st__count(tLatches) + Index) ); // reconnect with the old LIs/LOs pLatchIn = (Abc_Obj_t *)Vec_PtrEntry( vCosOld, Vec_PtrSize(vCosOld) - st__count(tLatches) + Index ); pLatchOut = (Abc_Obj_t *)Vec_PtrEntry( vCisOld, Vec_PtrSize(vCisOld) - st__count(tLatches) + Index ); } // connect Abc_ObjAddFanin( pLatchIn, Abc_ObjFanin0(pLatch) ); Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(pLatch), pLatchIn ); if ( Abc_ObjFanoutNum(pLatch) > 0 ) Abc_ObjTransferFanout( pLatch, pLatchOut ); Abc_ObjAddFanin( pLatchOut, pLatch ); // add to the arrays Vec_PtrPush( vCisNew, pLatchOut ); Vec_PtrPush( vCosNew, pLatchIn ); Vec_PtrPush( vBoxesNew, pLatch ); } // free useless Cis/Cos Vec_PtrForEachEntry( Abc_Obj_t *, vCisOld, pObj, i ) if ( !Abc_ObjIsPi(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) Abc_NtkDeleteObj(pObj); Vec_PtrForEachEntry( Abc_Obj_t *, vCosOld, pObj, i ) if ( !Abc_ObjIsPo(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) Abc_NtkDeleteObj(pObj); // set the new arrays pNtk->vCis = vCisNew; Vec_PtrFree( vCisOld ); pNtk->vCos = vCosNew; Vec_PtrFree( vCosOld ); pNtk->vBoxes = vBoxesNew; Vec_PtrFree( vBoxesOld ); return 1; } /**Function************************************************************* Synopsis [Performs retiming one way, forward or backward.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) { Abc_Ntk_t * pNtkNew = NULL; // Suppress "might be used uninitialized" Vec_Int_t * vValues = NULL; // Suppress "might be used uninitialized" Abc_Obj_t * pObj; int i, fChanges, nTotalMoves = 0, nTotalMovesLimit = 10000; if ( fForward ) Abc_NtkRetimeTranferToCopy( pNtk ); else { // save initial values of the latches vValues = Abc_NtkRetimeCollectLatchValues( pNtk ); // start the network for initial value computation pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk ); } // try to move latches forward whenever possible do { fChanges = 0; Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !Abc_ObjIsNode(pObj) ) continue; if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) ) { Abc_NtkRetimeNode( pObj, fForward, 1 ); fChanges = 1; nTotalMoves++; if ( nTotalMoves >= nTotalMovesLimit ) { printf( "Stopped after %d latch moves.\n", nTotalMoves ); break; } } } } while ( fChanges && nTotalMoves < nTotalMovesLimit ); // transfer the initial state back to the latches if ( fForward ) Abc_NtkRetimeTranferFromCopy( pNtk ); else { Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose ); Abc_NtkDelete( pNtkNew ); Vec_IntFree( vValues ); } return 0; } /**Function************************************************************* Synopsis [Returns 1 if retiming forward/backward is possible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward ) { Abc_Obj_t * pNext; int i; assert( Abc_ObjIsNode(pObj) ); if ( fForward ) { Abc_ObjForEachFanin( pObj, pNext, i ) if ( !Abc_ObjIsLatch(pNext) ) return 0; } else { Abc_ObjForEachFanout( pObj, pNext, i ) if ( !Abc_ObjIsLatch(pNext) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Retimes the node backward or forward.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial ) { Abc_Ntk_t * pNtkNew = NULL; Vec_Ptr_t * vNodes; Abc_Obj_t * pNext, * pLatch; int i; vNodes = Vec_PtrAlloc( 10 ); if ( fForward ) { // compute the initial value if ( fInitial ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate( pObj ); // collect fanins Abc_NodeCollectFanins( pObj, vNodes ); // make the node point to the fanins fanins Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, i ) { assert( Abc_ObjIsLatch(pNext) ); Abc_ObjPatchFanin( pObj, pNext, Abc_ObjFanin0(pNext) ); if ( Abc_ObjFanoutNum(pNext) == 0 ) Abc_NtkDeleteObj(pNext); } // add a new latch on top pNext = Abc_NtkCreateLatch(pObj->pNtk); if ( Abc_ObjFanoutNum(pObj) > 0 ) Abc_ObjTransferFanout( pObj, pNext ); Abc_ObjAddFanin( pNext, pObj ); // set the initial value if ( fInitial ) pNext->pCopy = pObj->pCopy; } else { // compute the initial value if ( fInitial ) { pNtkNew = Abc_ObjFanout0(pObj)->pCopy->pNtk; Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanout( pObj, pNext, i ) { assert( Abc_ObjFaninNum(pNext->pCopy) == 0 ); Abc_ObjAddFanin( pNext->pCopy, pObj->pCopy ); } } // collect fanouts Abc_NodeCollectFanouts( pObj, vNodes ); // make the fanouts fanouts point to the node Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNext, i ) { assert( Abc_ObjIsLatch(pNext) ); Abc_ObjTransferFanout( pNext, pObj ); Abc_NtkDeleteObj( pNext ); } // add new latches to the fanins Abc_ObjForEachFanin( pObj, pNext, i ) { pLatch = Abc_NtkCreateLatch(pObj->pNtk); Abc_ObjPatchFanin( pObj, pNext, pLatch ); Abc_ObjAddFanin( pLatch, pNext ); // create buffer isomorphic to this latch if ( fInitial ) { pLatch->pCopy = Abc_NtkCreateNodeBuf( pNtkNew, NULL ); Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pNext), "_buf" ); Abc_ObjAddFanin( pObj->pCopy, pLatch->pCopy ); } } } Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Returns the number of compatible fanout latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeCheckCompatibleLatchFanouts( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, nLatches = 0, Init = -1; Abc_ObjForEachFanout( pObj, pFanout, i ) { if ( !Abc_ObjIsLatch(pFanout) ) continue; if ( Init == -1 ) { Init = (int)(ABC_PTRUINT_T)pObj->pData; nLatches++; } else if ( Init == (int)(ABC_PTRUINT_T)pObj->pData ) nLatches++; } return nLatches; } /**Function************************************************************* Synopsis [Retimes the node backward or forward.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pFanin, * pLatchTop, * pLatchCur; int i, k; vNodes = Vec_PtrAlloc( 10 ); // consider latch fanins Abc_NtkForEachObj( pNtk, pFanin, i ) { if ( Abc_NtkRetimeCheckCompatibleLatchFanouts(pFanin) <= 1 ) continue; // get the first latch pLatchTop = NULL; Abc_ObjForEachFanout( pFanin, pLatchTop, k ) if ( Abc_ObjIsLatch(pLatchTop) ) break; assert( pLatchTop && Abc_ObjIsLatch(pLatchTop) ); // redirect compatible fanout latches to the first latch Abc_NodeCollectFanouts( pFanin, vNodes ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pLatchCur, k ) { if ( !Abc_ObjIsLatch(pLatchCur) ) continue; if ( pLatchCur == pLatchTop ) continue; if ( pLatchCur->pData != pLatchTop->pData ) continue; // connect the initial state if ( fInitial ) Abc_ObjAddFanin( pLatchCur->pCopy, pLatchTop->pCopy ); // redirect the fanouts Abc_ObjTransferFanout( pLatchCur, pLatchTop ); Abc_NtkDeleteObj(pLatchCur); } } Vec_PtrFree( vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/retInit.c000066400000000000000000000267231300674244400232240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [retInit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [Initial state computation for backward retiming.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retInit.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes initial values of the new latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose ) { Vec_Int_t * vSolution; Abc_Ntk_t * pNtkMiter, * pNtkLogic; int RetValue; abctime clk; if ( pNtkCone == NULL ) return Vec_IntDup( vValues ); // convert the target network to AIG pNtkLogic = Abc_NtkDup( pNtkCone ); Abc_NtkToAig( pNtkLogic ); // get the miter pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues ); if ( fVerbose ) printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) ); // solve the miter clk = Abc_Clock(); RetValue = Abc_NtkMiterSat( pNtkMiter, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL ); if ( fVerbose ) { ABC_PRT( "SAT solving time", Abc_Clock() - clk ); } // analyze the result if ( RetValue == 1 ) printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" ); else if ( RetValue == -1 ) printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" ); else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) ) printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" ); // set the values of the latches vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) ); pNtkMiter->pModel = NULL; Abc_NtkDelete( pNtkMiter ); Abc_NtkDelete( pNtkLogic ); return vSolution; } /**Function************************************************************* Synopsis [Computes the results of simulating one node.] Description [Assumes that fanins have pCopy set to the input values.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjSopSimulate( Abc_Obj_t * pObj ) { char * pCube, * pSop = (char *)pObj->pData; int nVars, Value, v, ResOr, ResAnd, ResVar; assert( pSop && !Abc_SopIsExorType(pSop) ); // simulate the SOP of the node ResOr = 0; nVars = Abc_SopGetVarNum(pSop); Abc_SopForEachCube( pSop, nVars, pCube ) { ResAnd = 1; Abc_CubeForEachVar( pCube, Value, v ) { if ( Value == '0' ) ResVar = 1 ^ ((int)(ABC_PTRUINT_T)Abc_ObjFanin(pObj, v)->pCopy); else if ( Value == '1' ) ResVar = (int)(ABC_PTRUINT_T)Abc_ObjFanin(pObj, v)->pCopy; else continue; ResAnd &= ResVar; } ResOr |= ResAnd; } // complement the result if necessary if ( !Abc_SopGetPhase(pSop) ) ResOr ^= 1; return ResOr; } /**Function************************************************************* Synopsis [Verifies the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i, Counter = 0; assert( Abc_NtkIsSopLogic(pNtkCone) ); // set the PIs Abc_NtkForEachPi( pNtkCone, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)pModel[i]; // simulate the internal nodes vNodes = Abc_NtkDfs( pNtkCone, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate( pObj ); Vec_PtrFree( vNodes ); // compare the outputs Abc_NtkForEachPo( pNtkCone, pObj, i ) pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; Abc_NtkForEachPo( pNtkCone, pObj, i ) Counter += (Vec_IntEntry(vValues, i) != (int)(ABC_PTRUINT_T)pObj->pCopy); if ( Counter > 0 ) printf( "%d outputs (out of %d) have a value mismatch.\n", Counter, Abc_NtkPoNum(pNtkCone) ); return 1; } /**Function************************************************************* Synopsis [Transfer latch initial values to pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_LatchIsInit1(pObj); } /**Function************************************************************* Synopsis [Transfer latch initial values from pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pData = (void *)(ABC_PTRUINT_T)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO); } /**Function************************************************************* Synopsis [Transfer latch initial values to pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk ) { Vec_Int_t * vValues; Abc_Obj_t * pObj; int i; vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) Vec_IntPush( vValues, Abc_LatchIsInit1(pObj) ); return vValues; } /**Function************************************************************* Synopsis [Transfer latch initial values from pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) { Abc_Obj_t * pObj; int i, Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Counter++; Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pData = (Abc_Obj_t *)(ABC_PTRUINT_T)(vValues? (Vec_IntEntry(vValues,(int)(ABC_PTRUINT_T)pObj->pCopy)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); } /**Function************************************************************* Synopsis [Transfer latch initial values to pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj; int i; // create the network used for the initial state computation pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); // create POs corresponding to the initial values Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pCopy = Abc_NtkCreatePo(pNtkNew); return pNtkNew; } /**Function************************************************************* Synopsis [Transfer latch initial values to pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose ) { Vec_Int_t * vValuesNew; Abc_Obj_t * pObj; int i; // create PIs corresponding to the initial values Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) Abc_ObjAddFanin( pObj->pCopy, Abc_NtkCreatePi(pNtkNew) ); // assign dummy node names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); // check the network if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkRetimeBackwardInitialFinish(): Network check has failed.\n" ); // derive new initial values vValuesNew = Abc_NtkRetimeInitialValues( pNtkNew, vValuesOld, fVerbose ); // insert new initial values Abc_NtkRetimeInsertLatchValues( pNtk, vValuesNew ); if ( vValuesNew ) Vec_IntFree( vValuesNew ); } /**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 [] ***********************************************************************/ void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i, f; assert( Abc_NtkIsSopLogic(pNtk) ); srand( 0x12341234 ); // initialize the values Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(rand() & 1); Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_LatchIsInit1(pObj); // simulate for the given number of timeframes vNodes = Abc_NtkDfs( pNtk, 0 ); for ( f = 0; f < nFrames; f++ ) { // simulate internal nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate( pObj ); // bring the results to the COs Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; // assign PI values Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(rand() & 1); // transfer the latch values Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjFanout0(pObj)->pCopy = Abc_ObjFanin0(pObj)->pCopy; } Vec_PtrFree( vNodes ); // set the final values Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pData = (void *)(ABC_PTRUINT_T)(Abc_ObjFanout0(pObj)->pCopy ? ABC_INIT_ONE : ABC_INIT_ZERO); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/retInt.h000066400000000000000000000105351300674244400230520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [retInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retInt.h,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__ret__retInt_h #define ABC__opt__ret__retInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== retArea.c ========================================================*/ extern int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fUseOldNames, int fVerbose ); /*=== retCore.c ========================================================*/ extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int nDelayLim, int fForwardOnly, int fBackwardOnly, int fOneStep, int fUseOldNames, int fVerbose ); /*=== retDelay.c ========================================================*/ extern int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nDelayLim, int nIterLimit, int fForward, int fVerbose ); /*=== retDirect.c ========================================================*/ extern int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fMinDelay, int fOneStep, int fUseOldNames, int fVerbose ); extern void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial ); extern int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward ); extern void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial ); extern st__table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ); extern int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st__table * tLatches, int nIdMaxStart, int fUseOldNames ); /*=== retFlow.c ========================================================*/ extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ); extern Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); /*=== retInit.c ========================================================*/ extern Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkSat, Vec_Int_t * vValues, int fVerbose ); extern int Abc_ObjSopSimulate( Abc_Obj_t * pObj ); extern void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk ); extern void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk ); extern Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk ); extern void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); extern Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk ); extern void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose ); /*=== retLvalue.c ========================================================*/ extern int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/retLvalue.c000066400000000000000000000323751300674244400235510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [retLvalue.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [Implementation of Pan's retiming algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retLvalue.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // node status after updating its arrival time enum { ABC_RET_UPDATE_FAIL, ABC_RET_UPDATE_NO, ABC_RET_UPDATE_YES }; // the internal procedures static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ); static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose ); static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose ); static int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi ); static int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi ); static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk ); static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose ); static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); } static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)(ABC_PTRUINT_T)pNode->pCopy; } static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Value; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Implements Pan's retiming algorithm.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ) { Vec_Int_t * vLags; int nLatches = Abc_NtkLatchNum(pNtk); assert( Abc_NtkIsLogic( pNtk ) ); // get the lags vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose ); // compute the retiming // Abc_NtkRetimeUsingLags( pNtk, vLags, fVerbose ); Vec_IntFree( vLags ); // fix the COs // Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); // check for correctness if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" ); // return the number of latches saved return nLatches - Abc_NtkLatchNum(pNtk); } /**Function************************************************************* Synopsis [Computes the retiming lags.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ) { Vec_Int_t * vLags; Vec_Ptr_t * vNodes, * vLatches; Abc_Obj_t * pNode; int i, FiMax, FiBest, RetValue; abctime clk, clkIter; char NodeLag; // get the upper bound on the clock period FiMax = Abc_NtkLevel(pNtk); // make sure this clock period is feasible vNodes = Abc_NtkDfs( pNtk, 0 ); vLatches = Abc_ManCollectLatches( pNtk ); if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiMax, nIterLimit, fVerbose ) ) { Vec_PtrFree( vLatches ); Vec_PtrFree( vNodes ); printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" ); return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); } // search for the optimal clock period between 0 and nLevelMax clk = Abc_Clock(); FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose ); clkIter = Abc_Clock() - clk; // recompute the best l-values RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiBest, nIterLimit, fVerbose ); assert( RetValue ); // fix the problem with non-converged delays Abc_NtkForEachNode( pNtk, pNode, i ) if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 ) Abc_NodeSetLValue( pNode, 0 ); // write the retiming lags vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); Abc_NtkForEachNode( pNtk, pNode, i ) { NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest ); Vec_IntWriteEntry( vLags, pNode->Id, NodeLag ); } /* Abc_NtkForEachPo( pNtk, pNode, i ) printf( "%d ", Abc_NodeGetLValue(Abc_ObjFanin0(pNode)) ); printf( "\n" ); Abc_NtkForEachLatch( pNtk, pNode, i ) printf( "%d/%d ", Abc_NodeGetLValue(Abc_ObjFanout0(pNode)), Abc_NodeGetLValue(Abc_ObjFanout0(pNode)) + FiBest ); printf( "\n" ); */ // print the result // if ( fVerbose ) printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest ); /* { FILE * pTable; pTable = fopen( "iscas/seqmap__stats2.txt", "a+" ); fprintf( pTable, "%d ", FiBest ); fprintf( pTable, "\n" ); fclose( pTable ); } */ Vec_PtrFree( vNodes ); Vec_PtrFree( vLatches ); return vLags; } /**Function************************************************************* Synopsis [Performs binary search for the optimal clock period.] Description [Assumes that FiMin is infeasible while FiMax is feasible.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose ) { int Median; assert( FiMin < FiMax ); if ( FiMin + 1 == FiMax ) return FiMax; Median = FiMin + (FiMax - FiMin)/2; if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, Median, nMaxIters, fVerbose ) ) return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, FiMin, Median, nMaxIters, fVerbose ); // Median is feasible else return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, Median, FiMax, nMaxIters, fVerbose ); // Median is infeasible } /**Function************************************************************* Synopsis [Returns 1 if retiming with this clock period is feasible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose ) { Abc_Obj_t * pObj; int c, i, fConverged; // set l-values of all nodes to be minus infinity, except PIs and constants Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjFaninNum(pObj) == 0 ) Abc_NodeSetLValue( pObj, 0 ); else Abc_NodeSetLValue( pObj, -ABC_INFINITY ); // update all values iteratively fConverged = 0; for ( c = 1; c <= nMaxIters; c++ ) { if ( !Abc_NtkRetimeUpdateLValue( pNtk, vNodes, vLatches, Fi ) ) { fConverged = 1; break; } if ( Abc_NtkRetimePosOverLimit(pNtk, Fi) ) break; } // report the results if ( fVerbose ) { if ( !fConverged ) printf( "Period = %3d. Iterations = %3d. Infeasible %s\n", Fi, c, (c > nMaxIters)? "(timeout)" : "" ); else printf( "Period = %3d. Iterations = %3d. Feasible\n", Fi, c ); } /* // check if any AND gates have infinite delay Counter = 0; Abc_NtkForEachNode( pNtk, pObj, i ) Counter += (Abc_NodeGetLValue(pObj) < -ABC_INFINITY/2); if ( Counter > 0 ) printf( "Warning: %d internal nodes have wrong l-values!\n", Counter ); */ return fConverged; } /**Function************************************************************* Synopsis [Performs one iteration of l-value computation for the nodes.] Description [Experimentally it was found that checking POs changes is not enough to detect the convergence of l-values in the network.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi ) { Abc_Obj_t * pObj, * pFanin; int i, k, lValueNew, fChange; // go through the nodes and detect change fChange = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { assert( Abc_ObjIsNode(pObj) ); lValueNew = -ABC_INFINITY; Abc_ObjForEachFanin( pObj, pFanin, k ) { if ( lValueNew < Abc_NodeGetLValue(pFanin) ) lValueNew = Abc_NodeGetLValue(pFanin); } lValueNew++; if ( Abc_NodeGetLValue(pObj) < lValueNew ) { Abc_NodeSetLValue( pObj, lValueNew ); fChange = 1; } } // propagate values through the latches Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) Abc_NodeSetLValue( Abc_ObjFanout0(pObj), Abc_NodeGetLValue(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) - Fi ); return fChange; } /**Function************************************************************* Synopsis [Detects the case when l-values exceeded the limit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachPo( pNtk, pObj, i ) if ( Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi ) return 1; return 0; } /**Function************************************************************* Synopsis [Collects latches in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ManCollectLatches_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLatches ) { Abc_Obj_t * pDriver; if ( !Abc_ObjIsLatch(pObj) ) return; // skip already collected latches if ( Abc_NodeIsTravIdCurrent(pObj) ) return; Abc_NodeSetTravIdCurrent(pObj); // get the driver node feeding into the latch pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); // call recursively if the driver looks like a latch output if ( Abc_ObjIsBo(pDriver) ) Abc_ManCollectLatches_rec( Abc_ObjFanin0(pDriver), vLatches ); // collect the latch Vec_PtrPush( vLatches, pObj ); } /**Function************************************************************* Synopsis [Collects latches in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vLatches; Abc_Obj_t * pObj; int i; vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ManCollectLatches_rec( pObj, vLatches ); assert( Vec_PtrSize(vLatches) == Abc_NtkLatchNum(pNtk) ); return vLatches; } /**Function************************************************************* Synopsis [Implements the retiming given as the array of retiming lags.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose ) { Abc_Obj_t * pObj; int fChanges, fForward, nTotalMoves, Lag, Counter, i; // iterate over the nodes nTotalMoves = 0; do { fChanges = 0; Abc_NtkForEachNode( pNtk, pObj, i ) { Lag = Vec_IntEntry( vLags, pObj->Id ); if ( !Lag ) continue; fForward = (Lag < 0); if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) ) { Abc_NtkRetimeNode( pObj, fForward, 0 ); fChanges = 1; nTotalMoves++; Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 ); } } } while ( fChanges ); if ( fVerbose ) printf( "Total latch moves = %d.\n", nTotalMoves ); // check if there are remaining lags Counter = 0; Abc_NtkForEachNode( pNtk, pObj, i ) Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0); if ( Counter ) printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/ret/ret_.c000066400000000000000000000026411300674244400225300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ret_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: ret_.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/000077500000000000000000000000001300674244400214505ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/module.make000066400000000000000000000002671300674244400236010ustar00rootroot00000000000000SRC += src/opt/rwr/rwrDec.c \ src/opt/rwr/rwrEva.c \ src/opt/rwr/rwrExp.c \ src/opt/rwr/rwrLib.c \ src/opt/rwr/rwrMan.c \ src/opt/rwr/rwrPrint.c \ src/opt/rwr/rwrUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwr.h000066400000000000000000000175631300674244400224470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwr.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__rwr__rwr_h #define ABC__opt__rwr__rwr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "base/abc/abc.h" #include "opt/cut/cut.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// #define RWR_LIMIT 1048576/4 // ((1 << 20) typedef struct Rwr_Man_t_ Rwr_Man_t; typedef struct Rwr_Node_t_ Rwr_Node_t; struct Rwr_Man_t_ { // internal lookups int nFuncs; // number of four var functions unsigned short * puCanons; // canonical forms char * pPhases; // canonical phases char * pPerms; // canonical permutations unsigned char * pMap; // mapping of functions into class numbers unsigned short * pMapInv; // mapping of classes into functions char * pPractical; // practical NPN classes char ** pPerms4; // four-var permutations // node space Vec_Ptr_t * vForest; // all the nodes Rwr_Node_t ** pTable; // the hash table of nodes by their canonical form Vec_Vec_t * vClasses; // the nodes of the equivalence classes Extra_MmFixed_t * pMmNode; // memory for nodes and cuts // statistical variables int nTravIds; // the counter of traversal IDs int nConsidered; // the number of nodes considered int nAdded; // the number of nodes added to lists int nClasses; // the number of NN classes // the result of resynthesis int fCompl; // indicates if the output of FF should be complemented void * pGraph; // the decomposition tree (temporary) Vec_Ptr_t * vFanins; // the fanins array (temporary) Vec_Ptr_t * vFaninsCur; // the fanins array (temporary) Vec_Int_t * vLevNums; // the array of levels (temporary) Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary) // node statistics int nNodesConsidered; int nNodesRewritten; int nNodesGained; int nNodesBeg; int nNodesEnd; int nScores[222]; int nCutsGood; int nCutsBad; int nSubgraphs; // runtime statistics abctime timeStart; abctime timeCut; abctime timeRes; abctime timeEval; abctime timeMffc; abctime timeUpdate; abctime timeTotal; }; struct Rwr_Node_t_ // 24 bytes { int Id; // ID int TravId; // traversal ID short nScore; short nGain; short nAdded; unsigned uTruth : 16; // truth table unsigned Volume : 8; // volume unsigned Level : 6; // level unsigned fUsed : 1; // mark unsigned fExor : 1; // mark Rwr_Node_t * p0; // first child Rwr_Node_t * p1; // second child Rwr_Node_t * pNext; // next in the table }; // manipulation of complemented attributes static inline int Rwr_IsComplement( Rwr_Node_t * p ) { return (int )(((ABC_PTRUINT_T)p) & 01); } static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((ABC_PTRUINT_T)(p) ^ (c)); } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== rwrDec.c ========================================================*/ extern void Rwr_ManPreprocess( Rwr_Man_t * p ); /*=== rwrEva.c ========================================================*/ extern int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ); extern void Rwr_ScoresClean( Rwr_Man_t * p ); extern void Rwr_ScoresReport( Rwr_Man_t * p ); /*=== rwrLib.c ========================================================*/ extern void Rwr_ManPrecompute( Rwr_Man_t * p ); extern Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute ); extern Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ); extern int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 ); extern void Rwr_ManIncTravId( Rwr_Man_t * p ); /*=== rwrMan.c ========================================================*/ extern Rwr_Man_t * Rwr_ManStart( int fPrecompute ); extern void Rwr_ManStop( Rwr_Man_t * p ); extern void Rwr_ManPrintStats( Rwr_Man_t * p ); extern void Rwr_ManPrintStatsFile( Rwr_Man_t * p ); extern void * Rwr_ManReadDecs( Rwr_Man_t * p ); extern Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p ); extern int Rwr_ManReadCompl( Rwr_Man_t * p ); extern void Rwr_ManAddTimeCuts( Rwr_Man_t * p, abctime Time ); extern void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, abctime Time ); extern void Rwr_ManAddTimeTotal( Rwr_Man_t * p, abctime Time ); /*=== rwrPrint.c ========================================================*/ extern void Rwr_ManPrint( Rwr_Man_t * p ); /*=== rwrUtil.c ========================================================*/ extern void Rwr_ManWriteToArray( Rwr_Man_t * p ); extern void Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose ); extern void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName ); extern void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName ); extern void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode ); extern char * Rwr_ManGetPractical( Rwr_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwrDec.c000066400000000000000000000116701300674244400230470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwrDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Evaluation and decomposition procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwr.h" #include "bool/dec/dec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode ); static Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Preprocesses computed library of subgraphs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManPreprocess( Rwr_Man_t * p ) { Dec_Graph_t * pGraph; Rwr_Node_t * pNode; int i, k; // put the nodes into the structure p->pMapInv = ABC_ALLOC( unsigned short, 222 ); memset( p->pMapInv, 0, sizeof(unsigned short) * 222 ); p->vClasses = Vec_VecStart( 222 ); for ( i = 0; i < p->nFuncs; i++ ) { if ( p->pTable[i] == NULL ) continue; // consider all implementations of this function for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) { assert( pNode->uTruth == p->pTable[i]->uTruth ); assert( p->pMap[pNode->uTruth] < 222 ); // Guaranteed to be >=0 b/c unsigned Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode ); p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth]; } } // compute decomposition forms for each node and verify them Vec_VecForEachEntry( Rwr_Node_t *, p->vClasses, pNode, i, k ) { pGraph = Rwr_NodePreprocess( p, pNode ); pNode->pNext = (Rwr_Node_t *)pGraph; assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) ); } } /**Function************************************************************* Synopsis [Preprocesses subgraphs rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode ) { Dec_Graph_t * pGraph; Dec_Edge_t eRoot; assert( !Rwr_IsComplement(pNode) ); // consider constant if ( pNode->uTruth == 0 ) return Dec_GraphCreateConst0(); // consider the case of elementary var if ( pNode->uTruth == 0x00FF ) return Dec_GraphCreateLeaf( 3, 4, 1 ); // start the subgraphs pGraph = Dec_GraphCreate( 4 ); // collect the nodes Rwr_ManIncTravId( p ); eRoot = Rwr_TravCollect_rec( p, pNode, pGraph ); Dec_GraphSetRoot( pGraph, eRoot ); return pGraph; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph ) { Dec_Edge_t eNode0, eNode1, eNode; // elementary variable if ( pNode->fUsed ) return Dec_EdgeCreate( pNode->Id - 1, 0 ); // previously visited node if ( pNode->TravId == p->nTravIds ) return Dec_IntToEdge( pNode->Volume ); pNode->TravId = p->nTravIds; // solve for children eNode0 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p0), pGraph ); if ( Rwr_IsComplement(pNode->p0) ) eNode0.fCompl = !eNode0.fCompl; eNode1 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p1), pGraph ); if ( Rwr_IsComplement(pNode->p1) ) eNode1.fCompl = !eNode1.fCompl; // create the decomposition node(s) if ( pNode->fExor ) eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); else eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); // save the result pNode->Volume = Dec_EdgeToInt( eNode ); return eNode; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwrEva.c000066400000000000000000000450421300674244400230670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwrDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Evaluation and decomposition procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwr.h" #include "bool/dec/dec.h" #include "aig/ivy/ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable ); static int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ); static int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut ); static int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**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 Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ) { int fVeryVerbose = 0; Dec_Graph_t * pGraph; Cut_Cut_t * pCut;//, * pTemp; Abc_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, GainCur = -1, GainBest = -1; abctime clk, clk2;//, Counter; p->nNodesConsidered++; // get the required times Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; // get the node's cuts clk = Abc_Clock(); pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); assert( pCut != NULL ); p->timeCut += Abc_Clock() - clk; //printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) ); /* Counter = 0; for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext ) Counter++; printf( "%d ", Counter ); */ // go through the cuts clk = Abc_Clock(); for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { // consider only 4-input cuts if ( pCut->nLeaves < 4 ) continue; // Cut_CutPrint( pCut, 0 ), printf( "\n" ); // get the fanin permutation uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); 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->nLeaves, 0 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Abc_NtkObj( pNode->pNtk, pCut->pLeaves[(int)pPerm[i]] ); if ( pFanin == NULL ) break; pFanin = Abc_ObjNotCond(pFanin, ((uPhase & (1< 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } if ( i != (int)pCut->nLeaves ) { p->nCutsBad++; continue; } p->nCutsGood++; { int Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 ) Counter++; if ( Counter > 2 ) continue; } clk2 = Abc_Clock(); /* printf( "Considering: (" ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) ); printf( ")\n" ); */ // mark the fanin boundary Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize++; // label MFFC with current ID Abc_NtkIncrementTravId( pNode->pNtk ); nNodesSaved = Abc_NodeMffcLabelAig( pNode ); // unmark the fanin boundary Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Abc_ObjRegular(pFanin)->vFanouts.nSize--; p->timeMffc += Abc_Clock() - clk2; // evaluate the cut clk2 = Abc_Clock(); pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable ); 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 = 0xFFFF & *Cut_CutReadTruth(pCut); // collect fanins in the Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } } p->timeRes += Abc_Clock() - clk; if ( GainBest == -1 ) return -1; /* if ( GainBest > 0 ) { printf( "Class %d ", p->pMap[uTruthBest] ); printf( "Gain = %d. Node %d : ", GainBest, pNode->Id ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanins, pFanin, i ) printf( "%d ", Abc_ObjRegular(pFanin)->Id ); Dec_GraphPrint( stdout, p->pGraph, NULL, NULL ); printf( "\n" ); } */ // printf( "%d", nNodesSaveCur - GainBest ); /* if ( GainBest > 0 ) { if ( Rwr_CutIsBoolean( pNode, p->vFanins ) ) printf( "b" ); else { printf( "Node %d : ", pNode->Id ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanins, pFanin, i ) printf( "%d ", Abc_ObjRegular(pFanin)->Id ); printf( "a" ); } } */ /* if ( GainBest > 0 ) if ( p->fCompl ) printf( "c" ); else printf( "." ); */ // copy the leaves Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanins, pFanin, i ) Dec_GraphNode((Dec_Graph_t *)p->pGraph, i)->pFunc = pFanin; /* printf( "(" ); Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanins, pFanin, i ) printf( " %d", Abc_ObjRegular(pFanin)->vFanouts.nSize - 1 ); printf( " ) " ); */ // printf( "%d ", Rwr_NodeGetDepth_rec( pNode, p->vFanins ) ); p->nScores[p->pMap[uTruthBest]]++; p->nNodesGained += GainBest; if ( fUseZeros || GainBest > 0 ) { p->nNodesRewritten++; } // report the progress if ( fVeryVerbose && GainBest > 0 ) { printf( "Node %6s : ", Abc_ObjName(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 * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable ) { extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); Vec_Ptr_t * vSubgraphs; Dec_Graph_t * pGraphBest = NULL; // Suppress "might be used uninitialized" Dec_Graph_t * pGraphCur; Rwr_Node_t * pNode, * pFanin; int nNodesAdded, GainBest, i, k; unsigned uTruth; float CostBest;//, CostCur; // find the matching class of subgraphs uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); p->nSubgraphs += vSubgraphs->nSize; // determine the best subgraph GainBest = -1; CostBest = ABC_INFINITY; Vec_PtrForEachEntry( Rwr_Node_t *, vSubgraphs, pNode, i ) { // get the current graph pGraphCur = (Dec_Graph_t *)pNode->pNext; // copy the leaves Vec_PtrForEachEntry( Rwr_Node_t *, vFaninsCur, pFanin, k ) Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; // detect how many unlabeled nodes will be reused nNodesAdded = Dec_GraphToNetworkCount( pRoot, pGraphCur, nNodesSaved, LevelMax ); if ( nNodesAdded == -1 ) continue; assert( nNodesSaved >= nNodesAdded ); /* // evaluate the cut if ( fPlaceEnable ) { extern float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins ); float Alpha = 0.5; // ??? float PlaceCost; // get the placement cost of the cut PlaceCost = Abc_PlaceEvaluateCut( pRoot, vFaninsCur ); // get the weigted cost of the cut CostCur = nNodesSaved - nNodesAdded + Alpha * PlaceCost; // do not allow uphill moves if ( nNodesSaved - nNodesAdded < 0 ) continue; // decide what cut to use if ( CostBest > CostCur ) { GainBest = nNodesSaved - nNodesAdded; // pure node cost CostBest = CostCur; // cost with placement pGraphBest = pGraphCur; // subgraph to be used for rewriting // score the graph if ( nNodesSaved - nNodesAdded > 0 ) { pNode->nScore++; pNode->nGain += GainBest; pNode->nAdded += nNodesAdded; } } } else */ { // count the gain at this node if ( GainBest < nNodesSaved - nNodesAdded ) { GainBest = nNodesSaved - nNodesAdded; pGraphBest = pGraphCur; // score the graph if ( nNodesSaved - nNodesAdded > 0 ) { pNode->nScore++; pNode->nGain += GainBest; pNode->nAdded += nNodesAdded; } } } } if ( GainBest == -1 ) return NULL; *pGainBest = GainBest; return pGraphBest; } /**Function************************************************************* Synopsis [Checks the type of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_CutIsBoolean_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, int fMarkA ) { if ( Vec_PtrFind(vLeaves, pObj) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pObj)) >= 0 ) { if ( fMarkA ) pObj->fMarkA = 1; else pObj->fMarkB = 1; return; } assert( !Abc_ObjIsCi(pObj) ); Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, fMarkA ); Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, fMarkA ); } /**Function************************************************************* Synopsis [Checks the type of the cut.] Description [Returns 1(0) if the cut is Boolean (algebraic).] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) { Abc_Obj_t * pTemp; int i, RetValue; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pTemp, i ) { pTemp = Abc_ObjRegular(pTemp); assert( !pTemp->fMarkA && !pTemp->fMarkB ); } Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, 1 ); Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, 0 ); RetValue = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pTemp, i ) { pTemp = Abc_ObjRegular(pTemp); RetValue |= pTemp->fMarkA && pTemp->fMarkB; pTemp->fMarkA = pTemp->fMarkB = 0; } return RetValue; } /**Function************************************************************* Synopsis [Count the nodes in the cut space of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_CutCountNumNodes_rec( Abc_Obj_t * pObj, Cut_Cut_t * pCut, Vec_Ptr_t * vNodes ) { int i; for ( i = 0; i < (int)pCut->nLeaves; i++ ) if ( pCut->pLeaves[i] == pObj->Id ) { // check if the node is collected if ( pObj->fMarkC == 0 ) { pObj->fMarkC = 1; Vec_PtrPush( vNodes, pObj ); } return; } assert( Abc_ObjIsNode(pObj) ); // check if the node is collected if ( pObj->fMarkC == 0 ) { pObj->fMarkC = 1; Vec_PtrPush( vNodes, pObj ); } // traverse the fanins Rwr_CutCountNumNodes_rec( Abc_ObjFanin0(pObj), pCut, vNodes ); Rwr_CutCountNumNodes_rec( Abc_ObjFanin1(pObj), pCut, vNodes ); } /**Function************************************************************* Synopsis [Count the nodes in the cut space of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut ) { Vec_Ptr_t * vNodes; int i, Counter; // collect all nodes vNodes = Vec_PtrAlloc( 100 ); for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) Rwr_CutCountNumNodes_rec( pObj, pCut, vNodes ); // clean all nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->fMarkC = 0; // delete and return Counter = Vec_PtrSize(vNodes); Vec_PtrFree( vNodes ); return Counter; } /**Function************************************************************* Synopsis [Returns depth of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) { Abc_Obj_t * pLeaf; int i, Depth0, Depth1; if ( Abc_ObjIsCi(pObj) ) return 0; Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pLeaf, i ) if ( pObj == Abc_ObjRegular(pLeaf) ) return 0; Depth0 = Rwr_NodeGetDepth_rec( Abc_ObjFanin0(pObj), vLeaves ); Depth1 = Rwr_NodeGetDepth_rec( Abc_ObjFanin1(pObj), vLeaves ); return 1 + Abc_MaxInt( Depth0, Depth1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ScoresClean( Rwr_Man_t * p ) { Vec_Ptr_t * vSubgraphs; Rwr_Node_t * pNode; int i, k; for ( i = 0; i < p->vClasses->nSize; i++ ) { vSubgraphs = Vec_VecEntry( p->vClasses, i ); Vec_PtrForEachEntry( Rwr_Node_t *, vSubgraphs, pNode, k ) pNode->nScore = pNode->nGain = pNode->nAdded = 0; } } static int Gains[222]; /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_ScoresCompare( int * pNum1, int * pNum2 ) { if ( Gains[*pNum1] > Gains[*pNum2] ) return -1; if ( Gains[*pNum1] < Gains[*pNum2] ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ScoresReport( Rwr_Man_t * p ) { extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); int Perm[222]; Vec_Ptr_t * vSubgraphs; Rwr_Node_t * pNode; int i, iNew, k; unsigned uTruth; // collect total gains assert( p->vClasses->nSize == 222 ); for ( i = 0; i < p->vClasses->nSize; i++ ) { Perm[i] = i; Gains[i] = 0; vSubgraphs = Vec_VecEntry( p->vClasses, i ); Vec_PtrForEachEntry( Rwr_Node_t *, vSubgraphs, pNode, k ) Gains[i] += pNode->nGain; } // sort the gains qsort( Perm, 222, sizeof(int), (int (*)(const void *, const void *))Rwr_ScoresCompare ); // print classes for ( i = 0; i < p->vClasses->nSize; i++ ) { iNew = Perm[i]; if ( Gains[iNew] == 0 ) break; vSubgraphs = Vec_VecEntry( p->vClasses, iNew ); printf( "CLASS %3d: Subgr = %3d. Total gain = %6d. ", iNew, Vec_PtrSize(vSubgraphs), Gains[iNew] ); uTruth = (unsigned)p->pMapInv[iNew]; Extra_PrintBinary( stdout, &uTruth, 16 ); printf( " " ); Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[iNew] | ((unsigned)p->pMapInv[iNew] << 16) ); Vec_PtrForEachEntry( Rwr_Node_t *, vSubgraphs, pNode, k ) { if ( pNode->nScore == 0 ) continue; printf( " %2d: S=%5d. A=%5d. G=%6d. ", k, pNode->nScore, pNode->nAdded, pNode->nGain ); Dec_GraphPrint( stdout, (Dec_Graph_t *)pNode->pNext, NULL, NULL ); } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwrExp.c000066400000000000000000000245751300674244400231200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwrExp.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Computation of practically used NN-classes of 4-input cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwrExp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Rwr_Man4_t_ Rwr_Man4_t; struct Rwr_Man4_t_ { // internal lookups int nFuncs; // the number of four-var functions unsigned short * puCanons; // canonical forms int * pnCounts; // the counters of functions in each class int nConsidered; // the number of nodes considered int nClasses; // the number of NN classes }; typedef struct Rwr_Man5_t_ Rwr_Man5_t; struct Rwr_Man5_t_ { // internal lookups stmm_table * tTableNN; // the NN canonical forms stmm_table * tTableNPN; // the NPN canonical forms }; static Rwr_Man4_t * s_pManRwrExp4 = NULL; static Rwr_Man5_t * s_pManRwrExp5 = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects stats about 4-var functions appearing in netlists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_Man4ExploreStart() { Rwr_Man4_t * p; p = ABC_ALLOC( Rwr_Man4_t, 1 ); memset( p, 0, sizeof(Rwr_Man4_t) ); // canonical forms p->nFuncs = (1<<16); // canonical forms, phases, perms Extra_Truth4VarNPN( &p->puCanons, NULL, NULL, NULL ); // counters p->pnCounts = ABC_ALLOC( int, p->nFuncs ); memset( p->pnCounts, 0, sizeof(int) * p->nFuncs ); s_pManRwrExp4 = p; } /**Function************************************************************* Synopsis [Collects stats about 4-var functions appearing in netlists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_Man4ExploreCount( unsigned uTruth ) { assert( uTruth < (1<<16) ); s_pManRwrExp4->pnCounts[ s_pManRwrExp4->puCanons[uTruth] ]++; } /**Function************************************************************* Synopsis [Collects stats about 4-var functions appearing in netlists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_Man4ExplorePrint() { FILE * pFile; int i, CountMax, CountWrite, nCuts, nClasses; int * pDistrib; int * pReprs; // find the max number of occurences nCuts = nClasses = 0; CountMax = 0; for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) { if ( CountMax < s_pManRwrExp4->pnCounts[i] ) CountMax = s_pManRwrExp4->pnCounts[i]; nCuts += s_pManRwrExp4->pnCounts[i]; if ( s_pManRwrExp4->pnCounts[i] > 0 ) nClasses++; } printf( "Number of cuts considered = %8d.\n", nCuts ); printf( "Classes occurring at least once = %8d.\n", nClasses ); // print the distribution of classes pDistrib = ABC_ALLOC( int, CountMax + 1 ); pReprs = ABC_ALLOC( int, CountMax + 1 ); memset( pDistrib, 0, sizeof(int)*(CountMax + 1) ); for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) { pDistrib[ s_pManRwrExp4->pnCounts[i] ]++; pReprs[ s_pManRwrExp4->pnCounts[i] ] = i; } printf( "Occurence = %6d. Num classes = %4d. \n", 0, 2288-nClasses ); for ( i = 1; i <= CountMax; i++ ) if ( pDistrib[i] ) { printf( "Occurence = %6d. Num classes = %4d. Repr = ", i, pDistrib[i] ); Extra_PrintBinary( stdout, (unsigned*)&(pReprs[i]), 16 ); printf( "\n" ); } ABC_FREE( pDistrib ); ABC_FREE( pReprs ); // write into a file all classes above limit (5) CountWrite = 0; pFile = fopen( "npnclass_stats4.txt", "w" ); for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) if ( s_pManRwrExp4->pnCounts[i] > 0 ) { Extra_PrintHex( pFile, (unsigned *)&i, 4 ); fprintf( pFile, " %10d\n", s_pManRwrExp4->pnCounts[i] ); // fprintf( pFile, "%d ", i ); CountWrite++; } fclose( pFile ); printf( "%d classes written into file \"%s\".\n", CountWrite, "npnclass_stats4.txt" ); } /**Function************************************************************* Synopsis [Collects stats about 4-var functions appearing in netlists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_Man5ExploreStart() { Rwr_Man5_t * p; p = ABC_ALLOC( Rwr_Man5_t, 1 ); memset( p, 0, sizeof(Rwr_Man5_t) ); p->tTableNN = stmm_init_table( st__numcmp, st__numhash ); p->tTableNPN = stmm_init_table( st__numcmp, st__numhash ); s_pManRwrExp5 = p; //Extra_PrintHex( stdout, Extra_TruthCanonNPN( 0x0000FFFF, 5 ), 5 ); //printf( "\n" ); } /**Function************************************************************* Synopsis [Collects stats about 4-var functions appearing in netlists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_Man5ExploreCount( unsigned uTruth ) { int * pCounter; if ( !stmm_find_or_add( s_pManRwrExp5->tTableNN, (char *)(ABC_PTRUINT_T)uTruth, (char***)&pCounter ) ) *pCounter = 0; (*pCounter)++; } /**Function************************************************************* Synopsis [Collects stats about 4-var functions appearing in netlists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_Man5ExplorePrint() { FILE * pFile; stmm_generator * gen; int i, CountMax, nCuts, Counter; int * pDistrib; unsigned * pReprs; unsigned uTruth, uTruthC; abctime clk = Abc_Clock(); Vec_Int_t * vClassesNN, * vClassesNPN; // find the max number of occurences nCuts = 0; CountMax = 0; stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, (char **)&Counter ) { nCuts += Counter; if ( CountMax < Counter ) CountMax = Counter; } printf( "Number of cuts considered = %8d.\n", nCuts ); printf( "Classes occurring at least once = %8d.\n", stmm_count(s_pManRwrExp5->tTableNN) ); printf( "The largest number of occurence = %8d.\n", CountMax ); // print the distribution of classes pDistrib = ABC_ALLOC( int, CountMax + 1 ); pReprs = ABC_ALLOC( unsigned, CountMax + 1 ); memset( pDistrib, 0, sizeof(int)*(CountMax + 1) ); stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, (char **)&Counter ) { assert( Counter <= CountMax ); pDistrib[ Counter ]++; pReprs[ Counter ] = uTruth; } for ( i = 1; i <= CountMax; i++ ) if ( pDistrib[i] ) { printf( "Occurence = %6d. Num classes = %4d. Repr = ", i, pDistrib[i] ); Extra_PrintBinary( stdout, pReprs + i, 32 ); printf( "\n" ); } ABC_FREE( pDistrib ); ABC_FREE( pReprs ); // put them into an array vClassesNN = Vec_IntAlloc( stmm_count(s_pManRwrExp5->tTableNN) ); stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, NULL ) Vec_IntPush( vClassesNN, (int)uTruth ); Vec_IntSortUnsigned( vClassesNN ); // write into a file all classes pFile = fopen( "nnclass_stats5.txt", "w" ); Vec_IntForEachEntry( vClassesNN, uTruth, i ) { if ( !stmm_lookup( s_pManRwrExp5->tTableNN, (char *)(ABC_PTRUINT_T)uTruth, (char **)&Counter ) ) { assert( 0 ); } Extra_PrintHex( pFile, &uTruth, 5 ); fprintf( pFile, " %10d\n", Counter ); } fclose( pFile ); printf( "%d classes written into file \"%s\".\n", vClassesNN->nSize, "nnclass_stats5.txt" ); clk = Abc_Clock(); // how many NPN classes exist? Vec_IntForEachEntry( vClassesNN, uTruth, i ) { int * pCounter; uTruthC = Extra_TruthCanonNPN( uTruth, 5 ); if ( !stmm_find_or_add( s_pManRwrExp5->tTableNPN, (char *)(ABC_PTRUINT_T)uTruthC, (char***)&pCounter ) ) *pCounter = 0; if ( !stmm_lookup( s_pManRwrExp5->tTableNN, (char *)(ABC_PTRUINT_T)uTruth, (char **)&Counter ) ) { assert( 0 ); } (*pCounter) += Counter; } printf( "The numbe of NPN classes = %d.\n", stmm_count(s_pManRwrExp5->tTableNPN) ); ABC_PRT( "Computing NPN classes", Abc_Clock() - clk ); // put them into an array vClassesNPN = Vec_IntAlloc( stmm_count(s_pManRwrExp5->tTableNPN) ); stmm_foreach_item( s_pManRwrExp5->tTableNPN, gen, (char **)&uTruth, NULL ) Vec_IntPush( vClassesNPN, (int)uTruth ); Vec_IntSortUnsigned( vClassesNPN ); // write into a file all classes pFile = fopen( "npnclass_stats5.txt", "w" ); Vec_IntForEachEntry( vClassesNPN, uTruth, i ) { if ( !stmm_lookup( s_pManRwrExp5->tTableNPN, (char *)(ABC_PTRUINT_T)uTruth, (char **)&Counter ) ) { assert( 0 ); } Extra_PrintHex( pFile, &uTruth, 5 ); fprintf( pFile, " %10d\n", Counter ); } fclose( pFile ); printf( "%d classes written into file \"%s\".\n", vClassesNPN->nSize, "npnclass_stats5.txt" ); // can they be uniquely characterized? } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwrLib.c000066400000000000000000000257161300674244400230700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwrLib.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwrLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ); static void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Precomputes the forest in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManPrecompute( Rwr_Man_t * p ) { Rwr_Node_t * p0, * p1; int i, k, Level, Volume; int LevelOld = -1; int nNodes; Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 1 ) Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p1, k, 1 ) { if ( LevelOld < (int)p0->Level ) { LevelOld = p0->Level; printf( "Starting level %d (at %d nodes).\n", LevelOld+1, i ); printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); } if ( k == i ) break; // if ( p0->Level + p1->Level > 6 ) // hard // break; if ( p0->Level + p1->Level > 5 ) // easy break; // if ( p0->Level + p1->Level > 6 || (p0->Level == 3 && p1->Level == 3) ) // break; // compute the level and volume of the new nodes Level = 1 + Abc_MaxInt( p0->Level, p1->Level ); Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); // try four different AND nodes Rwr_ManTryNode( p, p0 , p1 , 0, Level, Volume ); Rwr_ManTryNode( p, Rwr_Not(p0), p1 , 0, Level, Volume ); Rwr_ManTryNode( p, p0 , Rwr_Not(p1), 0, Level, Volume ); Rwr_ManTryNode( p, Rwr_Not(p0), Rwr_Not(p1), 0, Level, Volume ); // try EXOR Rwr_ManTryNode( p, p0 , p1 , 1, Level, Volume + 1 ); // report the progress if ( p->nConsidered % 50000000 == 0 ) printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); // quit after some time if ( p->vForest->nSize == RWR_LIMIT + 5 ) { printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); goto save; } } save : // mark the relevant ones Rwr_ManIncTravId( p ); k = 5; nNodes = 0; Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 5 ) if ( p0->uTruth == p->puCanons[p0->uTruth] ) { Rwr_MarkUsed_rec( p, p0 ); nNodes++; } // compact the array by throwing away non-canonical k = 5; Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 5 ) if ( p0->fUsed ) { p->vForest->pArray[k] = p0; p0->Id = k++; } p->vForest->nSize = k; printf( "Total canonical = %4d. Total used = %5d.\n", nNodes, p->vForest->nSize ); } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) { Rwr_Node_t * pOld, * pNew, ** ppPlace; unsigned uTruth; // compute truth table, level, volume p->nConsidered++; if ( fExor ) { // printf( "Considering EXOR of %d and %d.\n", p0->Id, p1->Id ); uTruth = (p0->uTruth ^ p1->uTruth); } else uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; // skip non-practical classes if ( Level > 2 && !p->pPractical[p->puCanons[uTruth]] ) return NULL; // enumerate through the nodes with the same canonical form ppPlace = p->pTable + uTruth; for ( pOld = *ppPlace; pOld; ppPlace = &pOld->pNext, pOld = pOld->pNext ) { if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) return NULL; if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) return NULL; // if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) // return NULL; } /* // enumerate through the nodes with the opposite polarity for ( pOld = p->pTable[~uTruth & 0xFFFF]; pOld; pOld = pOld->pNext ) { if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) return NULL; if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) return NULL; // if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) // return NULL; } */ // count the classes if ( p->pTable[uTruth] == NULL && p->puCanons[uTruth] == uTruth ) p->nClasses++; // create the new node pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); pNew->Id = p->vForest->nSize; pNew->TravId = 0; pNew->uTruth = uTruth; pNew->Level = Level; pNew->Volume = Volume; pNew->fUsed = 0; pNew->fExor = fExor; pNew->p0 = p0; pNew->p1 = p1; pNew->pNext = NULL; Vec_PtrPush( p->vForest, pNew ); *ppPlace = pNew; return pNew; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) { Rwr_Node_t * pNew; unsigned uTruth; // compute truth table, leve, volume p->nConsidered++; if ( fExor ) uTruth = (p0->uTruth ^ p1->uTruth); else uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; // create the new node pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); pNew->Id = p->vForest->nSize; pNew->TravId = 0; pNew->uTruth = uTruth; pNew->Level = Level; pNew->Volume = Volume; pNew->fUsed = 0; pNew->fExor = fExor; pNew->p0 = p0; pNew->p1 = p1; pNew->pNext = NULL; Vec_PtrPush( p->vForest, pNew ); // do not add if the node is not essential if ( uTruth != p->puCanons[uTruth] ) return pNew; // add to the list p->nAdded++; if ( p->pTable[uTruth] == NULL ) p->nClasses++; Rwr_ListAddToTail( p->pTable + uTruth, pNew ); return pNew; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute ) { Rwr_Node_t * pNew; pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); pNew->Id = p->vForest->nSize; pNew->TravId = 0; pNew->uTruth = uTruth; pNew->Level = 0; pNew->Volume = 0; pNew->fUsed = 1; pNew->fExor = 0; pNew->p0 = NULL; pNew->p1 = NULL; pNew->pNext = NULL; Vec_PtrPush( p->vForest, pNew ); if ( fPrecompute ) Rwr_ListAddToTail( p->pTable + uTruth, pNew ); return pNew; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ) { if ( pNode->fUsed || pNode->TravId == p->nTravIds ) return; pNode->TravId = p->nTravIds; pNode->fUsed = 1; Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p0) ); Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p1) ); } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_Trav_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume ) { if ( pNode->fUsed || pNode->TravId == p->nTravIds ) return; pNode->TravId = p->nTravIds; (*pVolume)++; if ( pNode->fExor ) (*pVolume)++; Rwr_Trav_rec( p, Rwr_Regular(pNode->p0), pVolume ); Rwr_Trav_rec( p, Rwr_Regular(pNode->p1), pVolume ); } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 ) { int Volume = 0; Rwr_ManIncTravId( p ); Rwr_Trav_rec( p, p0, &Volume ); Rwr_Trav_rec( p, p1, &Volume ); return Volume; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManIncTravId( Rwr_Man_t * p ) { Rwr_Node_t * pNode; int i; if ( p->nTravIds++ < 0x8FFFFFFF ) return; Vec_PtrForEachEntry( Rwr_Node_t *, p->vForest, pNode, i ) pNode->TravId = 0; p->nTravIds = 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwrMan.c000066400000000000000000000211341300674244400230630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwrMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Rewriting manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwrMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwr.h" #include "base/main/main.h" #include "bool/dec/dec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwr_Man_t * Rwr_ManStart( int fPrecompute ) { Dec_Man_t * pManDec; Rwr_Man_t * p; abctime clk = Abc_Clock(); clk = Abc_Clock(); p = ABC_ALLOC( Rwr_Man_t, 1 ); memset( p, 0, sizeof(Rwr_Man_t) ); p->nFuncs = (1<<16); pManDec = (Dec_Man_t *)Abc_FrameReadManDec(); p->puCanons = pManDec->puCanons; p->pPhases = pManDec->pPhases; p->pPerms = pManDec->pPerms; p->pMap = pManDec->pMap; // initialize practical NPN classes p->pPractical = Rwr_ManGetPractical( p ); // create the table p->pTable = ABC_ALLOC( Rwr_Node_t *, p->nFuncs ); memset( p->pTable, 0, sizeof(Rwr_Node_t *) * p->nFuncs ); // create the elementary nodes p->pMmNode = Extra_MmFixedStart( sizeof(Rwr_Node_t) ); p->vForest = Vec_PtrAlloc( 100 ); Rwr_ManAddVar( p, 0x0000, fPrecompute ); // constant 0 Rwr_ManAddVar( p, 0xAAAA, fPrecompute ); // var A Rwr_ManAddVar( p, 0xCCCC, fPrecompute ); // var B Rwr_ManAddVar( p, 0xF0F0, fPrecompute ); // var C Rwr_ManAddVar( p, 0xFF00, fPrecompute ); // var D p->nClasses = 5; // other stuff p->nTravIds = 1; p->pPerms4 = Extra_Permutations( 4 ); p->vLevNums = Vec_IntAlloc( 50 ); p->vFanins = Vec_PtrAlloc( 50 ); p->vFaninsCur = Vec_PtrAlloc( 50 ); p->vNodesTemp = Vec_PtrAlloc( 50 ); if ( fPrecompute ) { // precompute subgraphs Rwr_ManPrecompute( p ); // Rwr_ManPrint( p ); Rwr_ManWriteToArray( p ); } else { // load saved subgraphs Rwr_ManLoadFromArray( p, 0 ); // Rwr_ManPrint( p ); Rwr_ManPreprocess( p ); } p->timeStart = Abc_Clock() - clk; return p; } /**Function************************************************************* Synopsis [Stops rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManStop( Rwr_Man_t * p ) { if ( p->vClasses ) { Rwr_Node_t * pNode; int i, k; Vec_VecForEachEntry( Rwr_Node_t *, p->vClasses, pNode, i, k ) Dec_GraphFree( (Dec_Graph_t *)pNode->pNext ); } if ( p->vClasses ) Vec_VecFree( p->vClasses ); Vec_PtrFree( p->vNodesTemp ); Vec_PtrFree( p->vForest ); Vec_IntFree( p->vLevNums ); Vec_PtrFree( p->vFanins ); Vec_PtrFree( p->vFaninsCur ); Extra_MmFixedStop( p->pMmNode ); ABC_FREE( p->pMapInv ); ABC_FREE( p->pTable ); ABC_FREE( p->pPractical ); ABC_FREE( p->pPerms4 ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManPrintStats( Rwr_Man_t * p ) { int i, Counter = 0; for ( i = 0; i < 222; i++ ) Counter += (p->nScores[i] > 0); printf( "Rewriting statistics:\n" ); printf( "Total cuts tries = %8d.\n", p->nCutsGood ); printf( "Bad cuts found = %8d.\n", p->nCutsBad ); printf( "Total subgraphs = %8d.\n", p->nSubgraphs ); printf( "Used NPN classes = %8d.\n", Counter ); printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten ); printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); ABC_PRT( "Start ", p->timeStart ); ABC_PRT( "Cuts ", p->timeCut ); ABC_PRT( "Resynthesis ", p->timeRes ); ABC_PRT( " Mffc ", p->timeMffc ); ABC_PRT( " Eval ", p->timeEval ); ABC_PRT( "Update ", p->timeUpdate ); ABC_PRT( "TOTAL ", p->timeTotal ); /* printf( "The scores are:\n" ); for ( i = 0; i < 222; i++ ) if ( p->nScores[i] > 0 ) { extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] ); Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) ); } */ printf( "\n" ); } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManPrintStatsFile( Rwr_Man_t * p ) { FILE * pTable; pTable = fopen( "stats.txt", "a+" ); fprintf( pTable, "%d ", p->nCutsGood ); fprintf( pTable, "%d ", p->nSubgraphs ); fprintf( pTable, "%d ", p->nNodesRewritten ); fprintf( pTable, "%d", p->nNodesGained ); fprintf( pTable, "\n" ); fclose( pTable ); } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Rwr_ManReadDecs( Rwr_Man_t * p ) { return p->pGraph; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p ) { return p->vFanins; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_ManReadCompl( Rwr_Man_t * p ) { return p->fCompl; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManAddTimeCuts( Rwr_Man_t * p, abctime Time ) { p->timeCut += Time; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, abctime Time ) { p->timeUpdate += Time; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManAddTimeTotal( Rwr_Man_t * p, abctime Time ) { p->timeTotal += Time; } /**Function************************************************************* Synopsis [Precomputes AIG subgraphs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_Precompute() { Rwr_Man_t * p; p = Rwr_ManStart( 1 ); Rwr_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwrPrint.c000066400000000000000000000161631300674244400234520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwrCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_Trav2_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume ) { if ( pNode->fUsed || pNode->TravId == p->nTravIds ) return; pNode->TravId = p->nTravIds; (*pVolume)++; Rwr_Trav2_rec( p, Rwr_Regular(pNode->p0), pVolume ); Rwr_Trav2_rec( p, Rwr_Regular(pNode->p1), pVolume ); } /**Function************************************************************* Synopsis [Adds the node to the end of the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_GetBushVolume( Rwr_Man_t * p, int Entry, int * pVolume, int * pnFuncs ) { Rwr_Node_t * pNode; int Volume = 0; int nFuncs = 0; Rwr_ManIncTravId( p ); for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext ) { if ( pNode->uTruth != p->puCanons[pNode->uTruth] ) continue; nFuncs++; Rwr_Trav2_rec( p, pNode, &Volume ); } *pVolume = Volume; *pnFuncs = nFuncs; } /**Function************************************************************* Synopsis [Adds the node to the end of the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_GetBushSumOfVolumes( Rwr_Man_t * p, int Entry ) { Rwr_Node_t * pNode; int Volume, VolumeTotal = 0; for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext ) { if ( pNode->uTruth != p->puCanons[pNode->uTruth] ) continue; Volume = 0; Rwr_ManIncTravId( p ); Rwr_Trav2_rec( p, pNode, &Volume ); VolumeTotal += Volume; } return VolumeTotal; } /**Function************************************************************* Synopsis [Prints one rwr node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_NodePrint_rec( FILE * pFile, Rwr_Node_t * pNode ) { assert( !Rwr_IsComplement(pNode) ); if ( pNode->Id == 0 ) { fprintf( pFile, "Const1" ); return; } if ( pNode->Id < 5 ) { fprintf( pFile, "%c", 'a' + pNode->Id - 1 ); return; } if ( Rwr_IsComplement(pNode->p0) ) { if ( Rwr_Regular(pNode->p0)->Id < 5 ) { Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); fprintf( pFile, "\'" ); } else { fprintf( pFile, "(" ); Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); fprintf( pFile, ")\'" ); } } else { if ( Rwr_Regular(pNode->p0)->Id < 5 ) { Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); } else { fprintf( pFile, "(" ); Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); fprintf( pFile, ")" ); } } if ( pNode->fExor ) fprintf( pFile, "+" ); if ( Rwr_IsComplement(pNode->p1) ) { if ( Rwr_Regular(pNode->p1)->Id < 5 ) { Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); fprintf( pFile, "\'" ); } else { fprintf( pFile, "(" ); Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); fprintf( pFile, ")\'" ); } } else { if ( Rwr_Regular(pNode->p1)->Id < 5 ) { Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); } else { fprintf( pFile, "(" ); Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); fprintf( pFile, ")" ); } } } /**Function************************************************************* Synopsis [Prints one rwr node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_NodePrint( FILE * pFile, Rwr_Man_t * p, Rwr_Node_t * pNode ) { unsigned uTruth; fprintf( pFile, "%5d : ", pNode->Id ); uTruth = pNode->uTruth; Extra_PrintHex( pFile, &uTruth, 4 ); fprintf( pFile, " tt=" ); Extra_PrintBinary( pFile, &uTruth, 16 ); // fprintf( pFile, " cn=", pNode->Id ); // uTruth = p->puCanons[pNode->uTruth]; // Extra_PrintBinary( pFile, &uTruth, 16 ); fprintf( pFile, " lev=%d", pNode->Level ); fprintf( pFile, " vol=%d", pNode->Volume ); fprintf( pFile, " " ); Rwr_NodePrint_rec( pFile, pNode ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Prints one rwr node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManPrint( Rwr_Man_t * p ) { FILE * pFile; Rwr_Node_t * pNode; unsigned uTruth; int Limit, Counter, Volume, nFuncs, i; pFile = fopen( "graph_lib.txt", "w" ); Counter = 0; Limit = (1 << 16); for ( i = 0; i < Limit; i++ ) { if ( p->pTable[i] == NULL ) continue; if ( i != p->puCanons[i] ) continue; fprintf( pFile, "\nClass %3d. Func %6d. ", p->pMap[i], Counter++ ); Rwr_GetBushVolume( p, i, &Volume, &nFuncs ); fprintf( pFile, "Roots = %3d. Vol = %3d. Sum = %3d. ", nFuncs, Volume, Rwr_GetBushSumOfVolumes(p, i) ); uTruth = i; Extra_PrintBinary( pFile, &uTruth, 16 ); fprintf( pFile, "\n" ); for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) if ( pNode->uTruth == p->puCanons[pNode->uTruth] ) Rwr_NodePrint( pFile, p, pNode ); } fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwrTemp.c000066400000000000000000000063731300674244400232650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwrCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int pTruths[13719]; static int pFreqs[13719]; static int pPerm[13719]; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwr_TempCompare( int * pNum1, int * pNum2 ) { int Freq1 = pFreqs[*pNum1]; int Freq2 = pFreqs[*pNum2]; if ( Freq1 < Freq2 ) return 1; if ( Freq1 > Freq2 ) return -1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_Temp() { char Buffer[32]; int nFuncs = 13719; int nEntries = 100; unsigned uTruth; int i, k; FILE * pFile; pFile = fopen( "nnclass_stats5.txt", "r" ); for ( i = 0; i < 13719; i++ ) { int RetValue = fscanf( pFile, "%s%d", Buffer, &pFreqs[i] ); Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); pTruths[i] = uTruth; } fclose( pFile ); for ( i = 0; i < 13719; i++ ) pPerm[i] = i; qsort( (void *)pPerm, 13719, sizeof(int), (int (*)(const void *, const void *)) Rwr_TempCompare ); pFile = fopen( "5npn_100.blif", "w" ); fprintf( pFile, "# Most frequent NPN classes of 5 vars.\n" ); fprintf( pFile, ".model 5npn\n" ); fprintf( pFile, ".inputs a b c d e\n" ); fprintf( pFile, ".outputs" ); for ( i = 0; i < nEntries; i++ ) fprintf( pFile, " %02d", i ); fprintf( pFile, "\n" ); for ( i = 0; i < nEntries; i++ ) { fprintf( pFile, ".names a b c d e %02d\n", i ); uTruth = pTruths[pPerm[i]]; for ( k = 0; k < 32; k++ ) if ( uTruth & (1 << k) ) { Extra_PrintBinary( pFile, (unsigned *)&k, 5 ); fprintf( pFile, " 1\n" ); } } fprintf( pFile, ".end\n" ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwr/rwrUtil.c000066400000000000000000001125101300674244400232640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwrUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwrUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // precomputed data // the following 135 practical NPN classes of 4-variable functions were computed // by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks static unsigned short s_RwrPracticalClasses[] = { 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368, 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5, 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669, 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2, 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8, 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4, 0x1ee1, 0x3cc3, 0x6996, 0x0000 }; static unsigned short s_RwtAigSubgraphs[] = { 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, 0x0000,0x0000 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManWriteToArray( Rwr_Man_t * p ) { FILE * pFile; Rwr_Node_t * pNode; unsigned Entry0, Entry1; int i, nEntries; abctime clk = Abc_Clock(); // prepare the buffer nEntries = p->vForest->nSize - 5; pFile = fopen( "npn4_aig_array.txt", "w" ); fprintf( pFile, "static unsigned short s_RwtAigSubgraphs[] = \n{" ); for ( i = 0; i < nEntries; i++ ) { if ( i % 5 == 0 ) fprintf( pFile, "\n " ); pNode = (Rwr_Node_t *)p->vForest->pArray[i+5]; Entry0 = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0); Entry1 = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1); Entry0 = (Entry0 << 1) | pNode->fExor; Extra_PrintHex( pFile, &Entry0, 4 ); fprintf( pFile, "," ); Extra_PrintHex( pFile, &Entry1, 4 ); fprintf( pFile, ", " ); } if ( i % 5 == 0 ) fprintf( pFile, "\n " ); Entry0 = 0; Extra_PrintHex( pFile, &Entry0, 4 ); fprintf( pFile, "," ); Extra_PrintHex( pFile, &Entry0, 4 ); fprintf( pFile, " \n};\n" ); fclose( pFile ); printf( "The number of nodes saved = %d. ", nEntries ); ABC_PRT( "Saving", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Loads data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose ) { unsigned short * pArray = s_RwtAigSubgraphs; Rwr_Node_t * p0, * p1; unsigned Entry0, Entry1; int Level, Volume, nEntries, fExor; int i; abctime clk = Abc_Clock(); // reconstruct the forest for ( i = 0; ; i++ ) { Entry0 = pArray[2*i + 0]; Entry1 = pArray[2*i + 1]; if ( Entry0 == 0 && Entry1 == 0 ) break; // get EXOR flag fExor = (Entry0 & 1); Entry0 >>= 1; // get the nodes p0 = (Rwr_Node_t *)p->vForest->pArray[Entry0 >> 1]; p1 = (Rwr_Node_t *)p->vForest->pArray[Entry1 >> 1]; // compute the level and volume of the new nodes Level = 1 + Abc_MaxInt( p0->Level, p1->Level ); Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); // set the complemented attributes p0 = Rwr_NotCond( p0, (Entry0 & 1) ); p1 = Rwr_NotCond( p1, (Entry1 & 1) ); // add the node // Rwr_ManTryNode( p, p0, p1, Level, Volume ); Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); } nEntries = i - 1; if ( fVerbose ) { printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); printf( "The number of nodes loaded = %d. ", nEntries ); ABC_PRT( "Loading", Abc_Clock() - clk ); } } /**Function************************************************************* Synopsis [Writes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName ) { FILE * pFile; Rwr_Node_t * pNode; unsigned * pBuffer; int i, nEntries; abctime clk = Abc_Clock(); // prepare the buffer nEntries = p->vForest->nSize - 5; pBuffer = ABC_ALLOC( unsigned, nEntries * 2 ); for ( i = 0; i < nEntries; i++ ) { pNode = (Rwr_Node_t *)p->vForest->pArray[i+5]; pBuffer[2*i + 0] = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0); pBuffer[2*i + 1] = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1); // save EXOR flag pBuffer[2*i + 0] = (pBuffer[2*i + 0] << 1) | pNode->fExor; } pFile = fopen( pFileName, "wb" ); fwrite( &nEntries, sizeof(int), 1, pFile ); fwrite( pBuffer, sizeof(unsigned), nEntries * 2, pFile ); ABC_FREE( pBuffer ); fclose( pFile ); printf( "The number of nodes saved = %d. ", nEntries ); ABC_PRT( "Saving", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Loads data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName ) { FILE * pFile; Rwr_Node_t * p0, * p1; unsigned * pBuffer; int Level, Volume, nEntries, fExor; int i; abctime clk = Abc_Clock(); int RetValue; // load the data pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Rwr_ManLoadFromFile: Cannot open file \"%s\".\n", pFileName ); return; } RetValue = fread( &nEntries, sizeof(int), 1, pFile ); pBuffer = ABC_ALLOC( unsigned, nEntries * 2 ); RetValue = fread( pBuffer, sizeof(unsigned), nEntries * 2, pFile ); fclose( pFile ); // reconstruct the forest for ( i = 0; i < nEntries; i++ ) { // get EXOR flag fExor = (pBuffer[2*i + 0] & 1); pBuffer[2*i + 0] = (pBuffer[2*i + 0] >> 1); // get the nodes p0 = (Rwr_Node_t *)p->vForest->pArray[pBuffer[2*i + 0] >> 1]; p1 = (Rwr_Node_t *)p->vForest->pArray[pBuffer[2*i + 1] >> 1]; // compute the level and volume of the new nodes Level = 1 + Abc_MaxInt( p0->Level, p1->Level ); Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); // set the complemented attributes p0 = Rwr_NotCond( p0, (pBuffer[2*i + 0] & 1) ); p1 = Rwr_NotCond( p1, (pBuffer[2*i + 1] & 1) ); // add the node // Rwr_ManTryNode( p, p0, p1, Level, Volume ); Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); } ABC_FREE( pBuffer ); printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); printf( "The number of nodes loaded = %d. ", nEntries ); ABC_PRT( "Loading", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Adds the node to the end of the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode ) { Rwr_Node_t * pTemp; // find the last one for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext ) ppList = &pTemp->pNext; // attach at the end *ppList = pNode; } /**Function************************************************************* Synopsis [Create practical classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Rwr_ManGetPractical( Rwr_Man_t * p ) { char * pPractical; int i; pPractical = ABC_ALLOC( char, p->nFuncs ); memset( pPractical, 0, sizeof(char) * p->nFuncs ); pPractical[0] = 1; for ( i = 1; ; i++ ) { if ( s_RwrPracticalClasses[i] == 0 ) break; pPractical[ s_RwrPracticalClasses[i] ] = 1; } return pPractical; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwt/000077500000000000000000000000001300674244400214525ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwt/module.make000066400000000000000000000001211300674244400235700ustar00rootroot00000000000000SRC += src/opt/rwt/rwtDec.c \ src/opt/rwt/rwtMan.c \ src/opt/rwt/rwtUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwt/rwt.h000066400000000000000000000157571300674244400224560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__rwt__rwt_h #define ABC__aig__rwt__rwt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "misc/extra/extra.h" #include "misc/mem/mem.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// #define RWT_LIMIT 1048576/4 // ((1 << 20) #define RWT_MIN(a,b) (((a) < (b))? (a) : (b)) #define RWT_MAX(a,b) (((a) > (b))? (a) : (b)) typedef struct Rwt_Man_t_ Rwt_Man_t; typedef struct Rwt_Node_t_ Rwt_Node_t; struct Rwt_Man_t_ { // internal lookups int nFuncs; // number of four var functions unsigned short * puCanons; // canonical forms char * pPhases; // canonical phases char * pPerms; // canonical permutations unsigned char * pMap; // mapping of functions into class numbers unsigned short * pMapInv; // mapping of classes into functions char * pPractical; // practical NPN classes char ** pPerms4; // four-var permutations // node space Vec_Ptr_t * vForest; // all the nodes Rwt_Node_t ** pTable; // the hash table of nodes by their canonical form Vec_Vec_t * vClasses; // the nodes of the equivalence classes Mem_Fixed_t * pMmNode; // memory for nodes and cuts // statistical variables int nTravIds; // the counter of traversal IDs int nConsidered; // the number of nodes considered int nAdded; // the number of nodes added to lists int nClasses; // the number of NN classes // the result of resynthesis int fCompl; // indicates if the output of FF should be complemented void * pCut; // the decomposition tree (temporary) void * pGraph; // the decomposition tree (temporary) char * pPerm; // permutation used for the best cut Vec_Ptr_t * vFanins; // the fanins array (temporary) Vec_Ptr_t * vFaninsCur; // the fanins array (temporary) Vec_Int_t * vLevNums; // the array of levels (temporary) Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary) // node statistics int nNodesConsidered; int nNodesRewritten; int nNodesGained; int nScores[222]; int nCutsGood; int nCutsBad; int nSubgraphs; // runtime statistics abctime timeStart; abctime timeTruth; abctime timeCut; abctime timeRes; abctime timeEval; abctime timeMffc; abctime timeUpdate; abctime timeTotal; }; struct Rwt_Node_t_ // 24 bytes { int Id; // ID int TravId; // traversal ID unsigned uTruth : 16; // truth table unsigned Volume : 8; // volume unsigned Level : 6; // level unsigned fUsed : 1; // mark unsigned fExor : 1; // mark Rwt_Node_t * p0; // first child Rwt_Node_t * p1; // second child Rwt_Node_t * pNext; // next in the table }; // manipulation of complemented attributes static inline int Rwt_IsComplement( Rwt_Node_t * p ) { return (int)(((ABC_PTRUINT_T)p) & 01); } static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((ABC_PTRUINT_T)(p) ^ (c)); } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== rwrDec.c ========================================================*/ extern void Rwt_ManPreprocess( Rwt_Man_t * p ); /*=== rwrMan.c ========================================================*/ extern Rwt_Man_t * Rwt_ManStart( int fPrecompute ); extern void Rwt_ManStop( Rwt_Man_t * p ); extern void Rwt_ManPrintStats( Rwt_Man_t * p ); extern void Rwt_ManPrintStatsFile( Rwt_Man_t * p ); extern void * Rwt_ManReadDecs( Rwt_Man_t * p ); extern Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ); extern int Rwt_ManReadCompl( Rwt_Man_t * p ); extern void Rwt_ManAddTimeCuts( Rwt_Man_t * p, abctime Time ); extern void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, abctime Time ); extern void Rwt_ManAddTimeTotal( Rwt_Man_t * p, abctime Time ); /*=== rwrUtil.c ========================================================*/ extern void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ); extern char * Rwt_ManGetPractical( Rwt_Man_t * p ); extern Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ); extern void Rwt_ManIncTravId( Rwt_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwt/rwtDec.c000066400000000000000000000116641300674244400230560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwtDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Evaluation and decomposition procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwtDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwt.h" #include "bool/deco/deco.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ); static Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Preprocesses computed library of subgraphs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManPreprocess( Rwt_Man_t * p ) { Dec_Graph_t * pGraph; Rwt_Node_t * pNode; int i, k; // put the nodes into the structure p->pMapInv = ABC_ALLOC( unsigned short, 222 ); memset( p->pMapInv, 0, sizeof(unsigned short) * 222 ); p->vClasses = Vec_VecStart( 222 ); for ( i = 0; i < p->nFuncs; i++ ) { if ( p->pTable[i] == NULL ) continue; // consider all implementations of this function for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) { assert( pNode->uTruth == p->pTable[i]->uTruth ); assert( p->pMap[pNode->uTruth] < 222 ); // Always >= 0 b/c unsigned. Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode ); p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth]; } } // compute decomposition forms for each node and verify them Vec_VecForEachEntry( Rwt_Node_t *, p->vClasses, pNode, i, k ) { pGraph = Rwt_NodePreprocess( p, pNode ); pNode->pNext = (Rwt_Node_t *)pGraph; // assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) ); } } /**Function************************************************************* Synopsis [Preprocesses subgraphs rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ) { Dec_Graph_t * pGraph; Dec_Edge_t eRoot; assert( !Rwt_IsComplement(pNode) ); // consider constant if ( pNode->uTruth == 0 ) return Dec_GraphCreateConst0(); // consider the case of elementary var if ( pNode->uTruth == 0x00FF ) return Dec_GraphCreateLeaf( 3, 4, 1 ); // start the subgraphs pGraph = Dec_GraphCreate( 4 ); // collect the nodes Rwt_ManIncTravId( p ); eRoot = Rwt_TravCollect_rec( p, pNode, pGraph ); Dec_GraphSetRoot( pGraph, eRoot ); return pGraph; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ) { Dec_Edge_t eNode0, eNode1, eNode; // elementary variable if ( pNode->fUsed ) return Dec_EdgeCreate( pNode->Id - 1, 0 ); // previously visited node if ( pNode->TravId == p->nTravIds ) return Dec_IntToEdge( pNode->Volume ); pNode->TravId = p->nTravIds; // solve for children eNode0 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p0), pGraph ); if ( Rwt_IsComplement(pNode->p0) ) eNode0.fCompl = !eNode0.fCompl; eNode1 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p1), pGraph ); if ( Rwt_IsComplement(pNode->p1) ) eNode1.fCompl = !eNode1.fCompl; // create the decomposition node(s) if ( pNode->fExor ) eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); else eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); // save the result pNode->Volume = Dec_EdgeToInt( eNode ); return eNode; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwt/rwtMan.c000066400000000000000000000227141300674244400230740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwtMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Rewriting manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwt.h" #include "bool/deco/deco.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static unsigned short * s_puCanons = NULL; static char * s_pPhases = NULL; static char * s_pPerms = NULL; static unsigned char * s_pMap = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts residual rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManGlobalStart() { if ( s_puCanons == NULL ) Extra_Truth4VarNPN( &s_puCanons, &s_pPhases, &s_pPerms, &s_pMap ); } /**Function************************************************************* Synopsis [Starts residual rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManGlobalStop() { ABC_FREE( s_puCanons ); ABC_FREE( s_pPhases ); ABC_FREE( s_pPerms ); ABC_FREE( s_pMap ); } /**Function************************************************************* Synopsis [Starts rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwt_Man_t * Rwt_ManStart( int fPrecompute ) { Rwt_Man_t * p; abctime clk = Abc_Clock(); clk = Abc_Clock(); p = ABC_ALLOC( Rwt_Man_t, 1 ); memset( p, 0, sizeof(Rwt_Man_t) ); p->nFuncs = (1<<16); // copy the global tables Rwt_ManGlobalStart(); p->puCanons = s_puCanons; p->pPhases = s_pPhases; p->pPerms = s_pPerms; p->pMap = s_pMap; // initialize practical NPN classes p->pPractical = Rwt_ManGetPractical( p ); // create the table p->pTable = ABC_ALLOC( Rwt_Node_t *, p->nFuncs ); memset( p->pTable, 0, sizeof(Rwt_Node_t *) * p->nFuncs ); // create the elementary nodes p->pMmNode = Mem_FixedStart( sizeof(Rwt_Node_t) ); p->vForest = Vec_PtrAlloc( 100 ); Rwt_ManAddVar( p, 0x0000, fPrecompute ); // constant 0 Rwt_ManAddVar( p, 0xAAAA, fPrecompute ); // var A Rwt_ManAddVar( p, 0xCCCC, fPrecompute ); // var B Rwt_ManAddVar( p, 0xF0F0, fPrecompute ); // var C Rwt_ManAddVar( p, 0xFF00, fPrecompute ); // var D p->nClasses = 5; // other stuff p->nTravIds = 1; p->pPerms4 = Extra_Permutations( 4 ); p->vLevNums = Vec_IntAlloc( 50 ); p->vFanins = Vec_PtrAlloc( 50 ); p->vFaninsCur = Vec_PtrAlloc( 50 ); p->vNodesTemp = Vec_PtrAlloc( 50 ); if ( fPrecompute ) { // precompute subgraphs // Rwt_ManPrecompute( p ); // Rwt_ManPrint( p ); // Rwt_ManWriteToArray( p ); } else { // load saved subgraphs Rwt_ManLoadFromArray( p, 0 ); // Rwt_ManPrint( p ); Rwt_ManPreprocess( p ); } p->timeStart = Abc_Clock() - clk; return p; } /**Function************************************************************* Synopsis [Stops rewriting manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManStop( Rwt_Man_t * p ) { if ( p->vClasses ) { Rwt_Node_t * pNode; int i, k; Vec_VecForEachEntry( Rwt_Node_t *, p->vClasses, pNode, i, k ) Dec_GraphFree( (Dec_Graph_t *)pNode->pNext ); } if ( p->vClasses ) Vec_VecFree( p->vClasses ); Vec_PtrFree( p->vNodesTemp ); Vec_PtrFree( p->vForest ); Vec_IntFree( p->vLevNums ); Vec_PtrFree( p->vFanins ); Vec_PtrFree( p->vFaninsCur ); Mem_FixedStop( p->pMmNode, 0 ); ABC_FREE( p->pMapInv ); ABC_FREE( p->pTable ); ABC_FREE( p->pPractical ); ABC_FREE( p->pPerms4 ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManPrintStats( Rwt_Man_t * p ) { int i, Counter = 0; for ( i = 0; i < 222; i++ ) Counter += (p->nScores[i] > 0); printf( "Rewriting statistics:\n" ); printf( "Total cuts tries = %8d.\n", p->nCutsGood ); printf( "Bad cuts found = %8d.\n", p->nCutsBad ); printf( "Total subgraphs = %8d.\n", p->nSubgraphs ); printf( "Used NPN classes = %8d.\n", Counter ); printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten ); printf( "Calculated gain = %8d.\n", p->nNodesGained ); ABC_PRT( "Start ", p->timeStart ); ABC_PRT( "Cuts ", p->timeCut ); ABC_PRT( "Truth ", p->timeTruth ); ABC_PRT( "Resynthesis ", p->timeRes ); ABC_PRT( " Mffc ", p->timeMffc ); ABC_PRT( " Eval ", p->timeEval ); ABC_PRT( "Update ", p->timeUpdate ); ABC_PRT( "TOTAL ", p->timeTotal ); /* printf( "The scores are:\n" ); for ( i = 0; i < 222; i++ ) if ( p->nScores[i] > 0 ) { extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] ); Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) ); } printf( "\n" ); */ } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManPrintStatsFile( Rwt_Man_t * p ) { FILE * pTable; pTable = fopen( "stats.txt", "a+" ); fprintf( pTable, "%d ", p->nCutsGood ); fprintf( pTable, "%d ", p->nSubgraphs ); fprintf( pTable, "%d ", p->nNodesRewritten ); fprintf( pTable, "%d", p->nNodesGained ); fprintf( pTable, "\n" ); fclose( pTable ); } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Rwt_ManReadDecs( Rwt_Man_t * p ) { return p->pGraph; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ) { return p->vFanins; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwt_ManReadCompl( Rwt_Man_t * p ) { return p->fCompl; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManAddTimeCuts( Rwt_Man_t * p, abctime Time ) { p->timeCut += Time; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, abctime Time ) { p->timeUpdate += Time; } /**Function************************************************************* Synopsis [Stops the resynthesis manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManAddTimeTotal( Rwt_Man_t * p, abctime Time ) { p->timeTotal += Time; } /**Function************************************************************* Synopsis [Precomputes AIG subgraphs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_Precompute() { Rwt_Man_t * p; p = Rwt_ManStart( 1 ); Rwt_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/rwt/rwtUtil.c000066400000000000000000001113241300674244400232720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rwtUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [DAG-aware AIG rewriting package.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rwtUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "rwt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // precomputed data static unsigned short s_RwtAigSubgraphs[] = { 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, 0x0000,0x0000 }; static unsigned short s_RwtPracticalClasses[] = { 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368, 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5, 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669, 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2, 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8, 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4, 0x1ee1, 0x3cc3, 0x6996, 0x0000 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds the node to the end of the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ListAddToTail( Rwt_Node_t ** ppList, Rwt_Node_t * pNode ) { Rwt_Node_t * pTemp; // find the last one for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext ) ppList = &pTemp->pNext; // attach at the end *ppList = pNode; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ) { Rwt_Node_t * pNew; pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); pNew->Id = p->vForest->nSize; pNew->TravId = 0; pNew->uTruth = uTruth; pNew->Level = 0; pNew->Volume = 0; pNew->fUsed = 1; pNew->fExor = 0; pNew->p0 = NULL; pNew->p1 = NULL; pNew->pNext = NULL; Vec_PtrPush( p->vForest, pNew ); if ( fPrecompute ) Rwt_ListAddToTail( p->pTable + uTruth, pNew ); return pNew; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwt_Node_t * Rwt_ManAddNode( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1, int fExor, int Level, int Volume ) { Rwt_Node_t * pNew; unsigned uTruth; // compute truth table, leve, volume p->nConsidered++; if ( fExor ) uTruth = (p0->uTruth ^ p1->uTruth); else uTruth = (Rwt_IsComplement(p0)? ~Rwt_Regular(p0)->uTruth : Rwt_Regular(p0)->uTruth) & (Rwt_IsComplement(p1)? ~Rwt_Regular(p1)->uTruth : Rwt_Regular(p1)->uTruth) & 0xFFFF; // create the new node pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); pNew->Id = p->vForest->nSize; pNew->TravId = 0; pNew->uTruth = uTruth; pNew->Level = Level; pNew->Volume = Volume; pNew->fUsed = 0; pNew->fExor = fExor; pNew->p0 = p0; pNew->p1 = p1; pNew->pNext = NULL; Vec_PtrPush( p->vForest, pNew ); // do not add if the node is not essential if ( uTruth != p->puCanons[uTruth] ) return pNew; // add to the list p->nAdded++; if ( p->pTable[uTruth] == NULL ) p->nClasses++; Rwt_ListAddToTail( p->pTable + uTruth, pNew ); return pNew; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_Trav_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, int * pVolume ) { if ( pNode->fUsed || pNode->TravId == p->nTravIds ) return; pNode->TravId = p->nTravIds; (*pVolume)++; if ( pNode->fExor ) (*pVolume)++; Rwt_Trav_rec( p, Rwt_Regular(pNode->p0), pVolume ); Rwt_Trav_rec( p, Rwt_Regular(pNode->p1), pVolume ); } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManIncTravId( Rwt_Man_t * p ) { Rwt_Node_t * pNode; int i; if ( p->nTravIds++ < 0x8FFFFFFF ) return; Vec_PtrForEachEntry( Rwt_Node_t *, p->vForest, pNode, i ) pNode->TravId = 0; p->nTravIds = 1; } /**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rwt_ManNodeVolume( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1 ) { int Volume = 0; Rwt_ManIncTravId( p ); Rwt_Trav_rec( p, p0, &Volume ); Rwt_Trav_rec( p, p1, &Volume ); return Volume; } /**Function************************************************************* Synopsis [Loads data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ) { unsigned short * pArray = s_RwtAigSubgraphs; Rwt_Node_t * p0, * p1; unsigned Entry0, Entry1; int Level, Volume, nEntries, fExor; int i; abctime clk = Abc_Clock(); // reconstruct the forest for ( i = 0; ; i++ ) { Entry0 = pArray[2*i + 0]; Entry1 = pArray[2*i + 1]; if ( Entry0 == 0 && Entry1 == 0 ) break; // get EXOR flag fExor = (Entry0 & 1); Entry0 >>= 1; // get the nodes p0 = (Rwt_Node_t *)p->vForest->pArray[Entry0 >> 1]; p1 = (Rwt_Node_t *)p->vForest->pArray[Entry1 >> 1]; // compute the level and volume of the new nodes Level = 1 + RWT_MAX( p0->Level, p1->Level ); Volume = 1 + Rwt_ManNodeVolume( p, p0, p1 ); // set the complemented attributes p0 = Rwt_NotCond( p0, (Entry0 & 1) ); p1 = Rwt_NotCond( p1, (Entry1 & 1) ); // add the node // Rwt_ManTryNode( p, p0, p1, Level, Volume ); Rwt_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); } nEntries = i - 1; if ( fVerbose ) { printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); printf( "The number of nodes loaded = %d. ", nEntries ); ABC_PRT( "Loading", Abc_Clock() - clk ); } } /**Function************************************************************* Synopsis [Create practical classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Rwt_ManGetPractical( Rwt_Man_t * p ) { char * pPractical; int i; pPractical = ABC_ALLOC( char, p->nFuncs ); memset( pPractical, 0, sizeof(char) * p->nFuncs ); pPractical[0] = 1; for ( i = 1; ; i++ ) { if ( s_RwtPracticalClasses[i] == 0 ) break; pPractical[ s_RwtPracticalClasses[i] ] = 1; } return pPractical; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// // the following 135 practical NPN classes of 4-variable functions were computed // by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/000077500000000000000000000000001300674244400214235ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/module.make000066400000000000000000000003661300674244400235540ustar00rootroot00000000000000SRC += src/opt/sfm/sfmArea.c \ src/opt/sfm/sfmCnf.c \ src/opt/sfm/sfmCore.c \ src/opt/sfm/sfmDec.c \ src/opt/sfm/sfmLib.c \ src/opt/sfm/sfmNtk.c \ src/opt/sfm/sfmSat.c \ src/opt/sfm/sfmTim.c \ src/opt/sfm/sfmMit.c \ src/opt/sfm/sfmWin.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfm.h000066400000000000000000000120261300674244400223620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfm.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfm.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt_sfm__h #define ABC__opt_sfm__h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/vec/vecWec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Sfm_Ntk_t_ Sfm_Ntk_t; typedef struct Sfm_Par_t_ Sfm_Par_t; struct Sfm_Par_t_ { int nTfoLevMax; // the maximum fanout levels int nTfiLevMax; // the maximum fanin levels int nFanoutMax; // the maximum number of fanouts int nDepthMax; // the maximum depth to try int nVarMax; // the maximum variable count int nMffcMin; // the minimum MFFC size int nMffcMax; // the maximum MFFC size int nDecMax; // the maximum number of decompositions int nWinSizeMax; // the maximum window size int nGrowthLevel; // the maximum allowed growth in level int nBTLimit; // the maximum number of conflicts in one SAT run int nNodesMax; // the maximum number of nodes to try int iNodeOne; // one particular node to try int nFirstFixed; // the number of first nodes to be treated as fixed int nTimeWin; // the size of timing window in percents int DeltaCrit; // delay delta in picoseconds int DelAreaRatio; // delay/area tradeoff (how many ps we trade for a unit of area) int fRrOnly; // perform redundance removal int fArea; // performs optimization for area int fAreaRev; // performs optimization for area in reverse order int fMoreEffort; // performs high-affort minimization int fUseAndOr; // enable internal detection of AND/OR gates int fZeroCost; // enable zero-cost replacement int fUseSim; // enable simulation int fPrintDecs; // enable printing decompositions int fLibVerbose; // enable library stats int fDelayVerbose; // enable delay stats int fVerbose; // enable basic stats int fVeryVerbose; // enable detailed stats }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== sfmCnf.c ==========================================================*/ /*=== sfmCore.c ==========================================================*/ extern void Sfm_ParSetDefault( Sfm_Par_t * pPars ); extern int Sfm_NtkPerform( Sfm_Ntk_t * p, Sfm_Par_t * pPars ); /*=== sfmNtk.c ==========================================================*/ extern Sfm_Ntk_t * Sfm_NtkConstruct( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed, Vec_Str_t * vEmpty, Vec_Wrd_t * vTruths ); extern void Sfm_NtkFree( Sfm_Ntk_t * p ); extern Vec_Int_t * Sfm_NodeReadFanins( Sfm_Ntk_t * p, int i ); extern word * Sfm_NodeReadTruth( Sfm_Ntk_t * p, int i ); extern int Sfm_NodeReadFixed( Sfm_Ntk_t * p, int i ); extern int Sfm_NodeReadUsed( Sfm_Ntk_t * p, int i ); /*=== sfmWin.c ==========================================================*/ extern Vec_Int_t * Sfm_NtkDfs( Sfm_Ntk_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vGroupMap, Vec_Int_t * vBoxesLeft ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmArea.c000066400000000000000000000331561300674244400231550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmArea.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [Area optimization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmArea.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" #include "map/mio/mio.h" #include "misc/util/utilTruth.h" #include "misc/util/utilNam.h" #include "map/scl/sclLib.h" #include "map/scl/sclCon.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Precompute cell parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkPrecomputeCellPairs( Mio_Cell2_t * pCells, int nCells ) { Vec_Int_t * vInfo = Vec_IntAlloc( 1000 ); word iBestArea, tCur, iThis; int * pPerm[7], nPerms[7], Perm[7], * Perm1, * Perm2; int iBestCell, iBestPerm, iBestDiff; int i, k, n, v, p, Count = 0; int iGate1 = -1, iGate2 = -1; for ( i = 1; i <= 6; i++ ) pPerm[i] = Extra_PermSchedule( i ); for ( i = 1; i <= 6; i++ ) nPerms[i] = Extra_Factorial( i ); for ( i = 2; i < nCells; i++ ) { int nFanins = pCells[i].nFanins; for ( n = 0; n <= nFanins; n++ ) { // get the truth table iThis = (n == nFanins) ? ~pCells[i].uTruth : Abc_Tt6Flip(pCells[i].uTruth, n); // init the comparison iBestArea = ~((word)0); iBestCell = iBestPerm = iBestDiff = -1; // iterate through cells for ( k = 2; k < nCells; k++ ) { if ( nFanins != (int)pCells[k].nFanins ) continue; if ( i != k && pCells[i].uTruth == pCells[k].uTruth ) { iGate1 = i; iGate2 = k; Count++; continue; } // set unit permutation for ( v = 0; v < nFanins; v++ ) Perm[v] = v; // go through all permutation of Cell[k] tCur = pCells[k].uTruth; for ( p = 0; p < nPerms[nFanins]; p++ ) { if ( iThis == tCur && iBestArea > pCells[k].AreaW ) { iBestArea = pCells[k].AreaW; iBestCell = k; iBestPerm = 0; for ( v = 0; v < nFanins; v++ ) iBestPerm |= (v << (Perm[v] << 2)); iBestDiff = (pCells[i].AreaW >= pCells[k].AreaW) ? (int)(pCells[i].AreaW - pCells[k].AreaW) : -(int)(pCells[k].AreaW - pCells[i].AreaW); } if ( nPerms[nFanins] == 1 ) continue; // update tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[nFanins][p] ); Perm1 = Perm + pPerm[nFanins][p]; Perm2 = Perm1 + 1; ABC_SWAP( int, *Perm1, *Perm2 ); } assert( tCur == pCells[k].uTruth ); } Vec_IntPushThree( vInfo, iBestCell, iBestPerm, iBestDiff ); } } for ( i = 1; i <= 6; i++ ) ABC_FREE( pPerm[i] ); if ( Count ) printf( "In this library, %d cell pairs have equal functions (for example, %s and %s).\n", Count/2, pCells[iGate1].pName, pCells[iGate2].pName ); return vInfo; } Vec_Int_t * Abc_NtkPrecomputeFirsts( Mio_Cell2_t * pCells, int nCells ) { int i, Index = 0; Vec_Int_t * vFirst = Vec_IntStartFull( 2 ); for ( i = 2; i < nCells; i++ ) { Vec_IntPush( vFirst, Index ); Index += 3 * (pCells[i].nFanins + 1); } assert( nCells == Vec_IntSize(vFirst) ); return vFirst; } int Abc_NtkPrecomputePrint( Mio_Cell2_t * pCells, int nCells, Vec_Int_t * vInfo ) { int i, n, v, Index = 0, nRecUsed = 0; for ( i = 2; i < nCells; i++ ) { int nFanins = pCells[i].nFanins; printf( "%3d : %8s Fanins = %d ", i, pCells[i].pName, nFanins ); Dau_DsdPrintFromTruth( &pCells[i].uTruth, nFanins ); for ( n = 0; n <= nFanins; n++, Index += 3 ) { int iCellA = Vec_IntEntry( vInfo, Index+0 ); int iPerm = Vec_IntEntry( vInfo, Index+1 ); int Diff = Vec_IntEntry( vInfo, Index+2 ); if ( iCellA == -1 ) continue; printf( "%d : {", n ); for ( v = 0; v < nFanins; v++ ) printf( " %d ", (iPerm >> (v << 2)) & 15 ); printf( "} Index = %d ", Index ); printf( "Gain = %6.2f ", Scl_Int2Flt(Diff) ); Dau_DsdPrintFromTruth( &pCells[iCellA].uTruth, pCells[iCellA].nFanins ); nRecUsed++; } } return nRecUsed; } void Abc_NtkPrecomputeCellPairsTest() { int nCells; Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); Vec_Int_t * vInfo = Abc_NtkPrecomputeCellPairs( pCells, nCells ); int nRecUsed = Abc_NtkPrecomputePrint( pCells, nCells, vInfo ); // iterate through the cells Vec_Int_t * vFirst = Abc_NtkPrecomputeFirsts( pCells, nCells ); printf( "Used records = %d. All records = %d.\n", nRecUsed, Vec_IntSize(vInfo)/3 - nRecUsed ); assert( nCells == Vec_IntSize(vFirst) ); Vec_IntFree( vFirst ); Vec_IntFree( vInfo ); ABC_FREE( pCells ); } int Abc_NodeCheckFanoutHasFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) { Abc_Obj_t * pThis; int i; Abc_ObjForEachFanout( pNode, pThis, i ) if ( Abc_NodeFindFanin(pThis, pFanin) >= 0 ) return i; return -1; } /**Function************************************************************* Synopsis [Evaluate changes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjHasDupFanins( Abc_Obj_t * pObj ) { int * pArray = pObj->vFanins.pArray; int i, k, Limit = Abc_ObjFaninNum(pObj); for ( i = 0; i < Limit; i++ ) for ( k = i+1; k < Limit; k++ ) if ( pArray[i] == pArray[k] ) return 1; return 0; } int Abc_ObjHasDupFanouts( Abc_Obj_t * pObj ) { int * pArray = pObj->vFanouts.pArray; int i, k, Limit = Abc_ObjFanoutNum(pObj); for ( i = 0; i < Limit; i++ ) for ( k = i+1; k < Limit; k++ ) if ( pArray[i] == pArray[k] ) return 1; return 0; } int Abc_ObjChangeEval( Abc_Obj_t * pObj, Vec_Int_t * vInfo, Vec_Int_t * vFirst, int InvArea, int * pfUseInv ) { Abc_Obj_t * pNext; //Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; int iFanCell, iNodeCell = Mio_GateReadCell( (Mio_Gate_t *)pObj->pData ); int * pFanInfo, * pNodeInfo = Vec_IntEntryP( vInfo, Vec_IntEntry(vFirst, iNodeCell) ); int i, fNeedInv = 0, Gain = 0, iFanin = Abc_ObjFaninNum(pObj), fUseInv = Abc_NodeIsInv(pObj); assert( iFanin > 0 ); *pfUseInv = 0; if ( pNodeInfo[3*iFanin] == -1 ) return 0; if ( fUseInv ) Gain = InvArea; else Gain = pNodeInfo[3*iFanin+2]; Abc_ObjForEachFanout( pObj, pNext, i ) { if ( fUseInv && Abc_NodeFindFanin(pNext, Abc_ObjFanin0(pObj)) >= 0 ) return 0; if ( Abc_ObjHasDupFanins(pNext) ) return 0; if ( !Abc_ObjIsNode(pNext) || Abc_NodeIsBuf(pNext) ) { fNeedInv = 1; continue; } if ( Abc_NodeIsInv(pNext) ) { if ( Abc_NodeCheckFanoutHasFanin(pNext, pObj) >= 0 ) return 0; Gain += InvArea; continue; } iFanCell = Mio_GateReadCell( (Mio_Gate_t *)pNext->pData ); pFanInfo = Vec_IntEntryP( vInfo, Vec_IntEntry(vFirst, iFanCell) ); iFanin = Abc_NodeFindFanin( pNext, pObj ); if ( pFanInfo[3*iFanin] == -1 ) { fNeedInv = 1; continue; } Gain += pFanInfo[3*iFanin+2]; } if ( fNeedInv ) Gain -= InvArea; *pfUseInv = fNeedInv; return Gain; } void Abc_ObjChangeUpdate( Abc_Obj_t * pObj, int iFanin, Mio_Cell2_t * pCells, int * pNodeInfo, Vec_Int_t * vTemp ) { int v, Perm, iNodeCell = pNodeInfo[3*iFanin]; //Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; //Abc_ObjPrint( stdout, pObj ); //printf( "Replacing fanout %d with %s by %s with fanin %d.\n", Abc_ObjId(pObj), Mio_GateReadName(pGate), Mio_GateReadName((Mio_Gate_t *)pCells[iNodeCell].pMioGate), iFanin ); pObj->pData = (Mio_Gate_t *)pCells[iNodeCell].pMioGate; Perm = pNodeInfo[3*iFanin+1]; Vec_IntClear( vTemp ); for ( v = 0; v < Abc_ObjFaninNum(pObj); v++ ) Vec_IntPush( vTemp, Abc_ObjFaninId(pObj, (Perm >> (v << 2)) & 15) ); Vec_IntClear( &pObj->vFanins ); Vec_IntAppend( &pObj->vFanins, vTemp ); } void Abc_ObjChangePerform( Abc_Obj_t * pObj, Vec_Int_t * vInfo, Vec_Int_t * vFirst, int fUseInv, Vec_Int_t * vTemp, Vec_Ptr_t * vFanout, Vec_Ptr_t * vFanout2, Mio_Cell2_t * pCells ) { Abc_Obj_t * pNext, * pNext2, * pNodeInv = NULL; int iFanCell, iNodeCell = Mio_GateReadCell( (Mio_Gate_t *)pObj->pData ); int * pFanInfo, * pNodeInfo = Vec_IntEntryP( vInfo, Vec_IntEntry(vFirst, iNodeCell) ); int i, k, iFanin = Abc_ObjFaninNum(pObj); assert( iFanin > 0 && pNodeInfo[3*iFanin] != -1 ); // update the node Abc_NodeCollectFanouts( pObj, vFanout ); if ( Abc_NodeIsInv(pObj) ) { Abc_Obj_t * pFanin = Abc_ObjFanin0(pObj); Vec_PtrForEachEntry( Abc_Obj_t *, vFanout, pNext, k ) Abc_ObjPatchFanin( pNext, pObj, pFanin ); assert( Abc_ObjFanoutNum(pObj) == 0 ); Abc_NtkDeleteObj(pObj); pObj = pFanin; // assert( fUseInv == 0 ); } else Abc_ObjChangeUpdate( pObj, iFanin, pCells, pNodeInfo, vTemp ); // add inverter if needed if ( fUseInv ) pNodeInv = Abc_NtkCreateNodeInv(pObj->pNtk, pObj); // update the fanouts Vec_PtrForEachEntry( Abc_Obj_t *, vFanout, pNext, i ) { if ( !Abc_ObjIsNode(pNext) || Abc_NodeIsBuf(pNext) ) { Abc_ObjPatchFanin( pNext, pObj, pNodeInv ); continue; } if ( Abc_NodeIsInv(pNext) ) { Abc_NodeCollectFanouts( pNext, vFanout2 ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanout2, pNext2, k ) Abc_ObjPatchFanin( pNext2, pNext, pObj ); assert( Abc_ObjFanoutNum(pNext) == 0 ); Abc_NtkDeleteObj(pNext); continue; } iFanin = Abc_NodeFindFanin( pNext, pObj ); iFanCell = Mio_GateReadCell( (Mio_Gate_t *)pNext->pData ); pFanInfo = Vec_IntEntryP( vInfo, Vec_IntEntry(vFirst, iFanCell) ); if ( pFanInfo[3*iFanin] == -1 ) { Abc_ObjPatchFanin( pNext, pObj, pNodeInv ); continue; } Abc_ObjChangeUpdate( pNext, iFanin, pCells, pFanInfo, vTemp ); } } void Abc_NtkChangePerform( Abc_Ntk_t * pNtk, int fVerbose ) { abctime clk = Abc_Clock(); int i, fNeedInv, nCells, Gain, GainAll = 0, Count = 0, CountInv = 0; Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); Vec_Int_t * vInfo = Abc_NtkPrecomputeCellPairs( pCells, nCells ); Vec_Int_t * vFirst = Abc_NtkPrecomputeFirsts( pCells, nCells ); Vec_Ptr_t * vFanout = Vec_PtrAlloc( 100 ); Vec_Ptr_t * vFanout2 = Vec_PtrAlloc( 100 ); Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); Abc_Obj_t * pObj; Abc_NtkForEachNode( pNtk, pObj, i ) { if ( Abc_ObjFaninNum(pObj) < 2 && !Abc_NodeIsInv(pObj) ) continue; if ( Abc_ObjHasDupFanouts(pObj) ) continue; Gain = Abc_ObjChangeEval( pObj, vInfo, vFirst, (int)pCells[3].AreaW, &fNeedInv ); if ( Gain <= 0 ) continue; //printf( "Obj %d\n", Abc_ObjId(pObj) ); Count++; CountInv += Abc_NodeIsInv(pObj); GainAll += Gain; Abc_ObjChangePerform( pObj, vInfo, vFirst, fNeedInv, vTemp, vFanout, vFanout2, pCells ); } Vec_PtrFree( vFanout2 ); Vec_PtrFree( vFanout ); Vec_IntFree( vTemp ); Vec_IntFree( vFirst ); Vec_IntFree( vInfo ); ABC_FREE( pCells ); if ( fVerbose ) printf( "Total gain in area = %6.2f after %d changes (including %d inverters). ", Scl_Int2Flt(GainAll), Count, CountInv ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmCnf.c000066400000000000000000000122461300674244400230100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmCnf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [CNF computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_PrintCnf( Vec_Str_t * vCnf ) { char Entry; int i, Lit; Vec_StrForEachEntry( vCnf, Entry, i ) { Lit = (int)Entry; if ( Lit == -1 ) printf( "\n" ); else printf( "%s%d ", Abc_LitIsCompl(Lit) ? "-":"", Abc_Lit2Var(Lit) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_TruthToCnf( word Truth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vCnf ) { Vec_StrClear( vCnf ); if ( Truth == 0 || ~Truth == 0 ) { // assert( nVars == 0 ); Vec_StrPush( vCnf, (char)(Truth == 0) ); Vec_StrPush( vCnf, (char)-1 ); return 1; } else { int i, k, c, RetValue, Literal, Cube, nCubes = 0; assert( nVars > 0 ); for ( c = 0; c < 2; c ++ ) { Truth = c ? ~Truth : Truth; RetValue = Kit_TruthIsop( (unsigned *)&Truth, nVars, vCover, 0 ); assert( RetValue == 0 ); nCubes += Vec_IntSize( vCover ); Vec_IntForEachEntry( vCover, Cube, i ) { for ( k = 0; k < nVars; k++ ) { Literal = 3 & (Cube >> (k << 1)); if ( Literal == 1 ) // '0' -> pos lit Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 0) ); else if ( Literal == 2 ) // '1' -> neg lit Vec_StrPush( vCnf, (char)Abc_Var2Lit(k, 1) ); else if ( Literal != 0 ) assert( 0 ); } Vec_StrPush( vCnf, (char)Abc_Var2Lit(nVars, c) ); Vec_StrPush( vCnf, (char)-1 ); } } return nCubes; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Sfm_CreateCnf( Sfm_Ntk_t * p ) { Vec_Wec_t * vCnfs; Vec_Str_t * vCnf, * vCnfBase; word uTruth; int i, nCubes; vCnf = Vec_StrAlloc( 100 ); vCnfs = Vec_WecStart( p->nObjs ); Vec_WrdForEachEntryStartStop( p->vTruths, uTruth, i, p->nPis, Vec_WrdSize(p->vTruths)-p->nPos ) { nCubes = Sfm_TruthToCnf( uTruth, Sfm_ObjFaninNum(p, i), p->vCover, vCnf ); vCnfBase = (Vec_Str_t *)Vec_WecEntry( vCnfs, i ); Vec_StrGrow( vCnfBase, Vec_StrSize(vCnf) ); memcpy( Vec_StrArray(vCnfBase), Vec_StrArray(vCnf), Vec_StrSize(vCnf) ); vCnfBase->nSize = Vec_StrSize(vCnf); } Vec_StrFree( vCnf ); return vCnfs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_TranslateCnf( Vec_Wec_t * vRes, Vec_Str_t * vCnf, Vec_Int_t * vFaninMap, int iPivotVar ) { Vec_Int_t * vClause; char Entry; int i, Lit; Vec_WecClear( vRes ); vClause = Vec_WecPushLevel( vRes ); Vec_StrForEachEntry( vCnf, Entry, i ) { if ( (int)Entry == -1 ) { vClause = Vec_WecPushLevel( vRes ); continue; } Lit = Abc_Lit2LitV( Vec_IntArray(vFaninMap), (int)Entry ); Lit = Abc_LitNotCond( Lit, Abc_Lit2Var(Lit) == iPivotVar ); Vec_IntPush( vClause, Lit ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmCore.c000066400000000000000000000256261300674244400232000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Setup parameter structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_ParSetDefault( Sfm_Par_t * pPars ) { memset( pPars, 0, sizeof(Sfm_Par_t) ); pPars->nTfoLevMax = 2; // the maximum fanout levels pPars->nFanoutMax = 30; // the maximum number of fanouts pPars->nDepthMax = 20; // the maximum depth to try pPars->nWinSizeMax = 300; // the maximum window size pPars->nGrowthLevel = 0; // the maximum allowed growth in level pPars->nBTLimit = 5000; // the maximum number of conflicts in one SAT run pPars->fRrOnly = 0; // perform redundancy removal pPars->fArea = 0; // performs optimization for area pPars->fMoreEffort = 0; // performs high-affort minimization pPars->fVerbose = 0; // enable basic stats pPars->fVeryVerbose = 0; // enable detailed stats } /**Function************************************************************* Synopsis [Prints statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_NtkPrintStats( Sfm_Ntk_t * p ) { p->timeOther = p->timeTotal - p->timeWin - p->timeDiv - p->timeCnf - p->timeSat; printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d. MaxDivs = %d.\n", Sfm_NtkNodeNum(p), p->nNodesTried, p->nRemoves + p->nResubs, p->nTotalDivs, p->nSatCalls, p->nTimeOuts, p->nMaxDivs ); printf( "Attempts : " ); printf( "Remove %6d out of %6d (%6.2f %%) ", p->nRemoves, p->nTryRemoves, 100.0*p->nRemoves/Abc_MaxInt(1, p->nTryRemoves) ); printf( "Resub %6d out of %6d (%6.2f %%) ", p->nResubs, p->nTryResubs, 100.0*p->nResubs /Abc_MaxInt(1, p->nTryResubs) ); printf( "\n" ); printf( "Reduction: " ); printf( "Nodes %6d out of %6d (%6.2f %%) ", p->nTotalNodesBeg-p->nTotalNodesEnd, p->nTotalNodesBeg, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/Abc_MaxInt(1, p->nTotalNodesBeg) ); printf( "Edges %6d out of %6d (%6.2f %%) ", p->nTotalEdgesBeg-p->nTotalEdgesEnd, p->nTotalEdgesBeg, 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/Abc_MaxInt(1, p->nTotalEdgesBeg) ); printf( "\n" ); ABC_PRTP( "Win", p->timeWin , p->timeTotal ); ABC_PRTP( "Div", p->timeDiv , p->timeTotal ); ABC_PRTP( "Cnf", p->timeCnf , p->timeTotal ); ABC_PRTP( "Sat", p->timeSat , p->timeTotal ); ABC_PRTP( "Oth", p->timeOther, p->timeTotal ); ABC_PRTP( "ALL", p->timeTotal, p->timeTotal ); // ABC_PRTP( " ", p->time1 , p->timeTotal ); } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_NodeResubSolve( Sfm_Ntk_t * p, int iNode, int f, int fRemoveOnly ) { int fSkipUpdate = 0; int fVeryVerbose = 0;//p->pPars->fVeryVerbose && Vec_IntSize(p->vDivs) < 200;// || pNode->Id == 556; int i, iFanin, iVar = -1; word uTruth, uSign, uMask; abctime clk; assert( Sfm_ObjIsNode(p, iNode) ); assert( f >= 0 && f < Sfm_ObjFaninNum(p, iNode) ); p->nTryRemoves++; // report init stats if ( p->pPars->fVeryVerbose ) printf( "%5d : Lev =%3d. Leaf =%3d. Node =%3d. Div=%3d. Fanin =%4d (%d/%d). MFFC = %d\n", iNode, Sfm_ObjLevel(p, iNode), 0, Vec_IntSize(p->vNodes), Vec_IntSize(p->vDivs), Sfm_ObjFanin(p, iNode, f), f, Sfm_ObjFaninNum(p, iNode), Sfm_ObjMffcSize(p, Sfm_ObjFanin(p, iNode, f)) ); // clean simulation info p->nCexes = 0; Vec_WrdFill( p->vDivCexes, Vec_IntSize(p->vDivs), 0 ); // try removing the critical fanin Vec_IntClear( p->vDivIds ); Sfm_ObjForEachFanin( p, iNode, iFanin, i ) if ( i != f ) Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iFanin) ); clk = Abc_Clock(); uTruth = Sfm_ComputeInterpolant( p ); p->timeSat += Abc_Clock() - clk; // analyze outcomes if ( uTruth == SFM_SAT_UNDEC ) { p->nTimeOuts++; return 0; } if ( uTruth != SFM_SAT_SAT ) goto finish; if ( fRemoveOnly || p->pPars->fRrOnly || Vec_IntSize(p->vDivs) == 0 ) return 0; p->nTryResubs++; if ( fVeryVerbose ) { for ( i = 0; i < 9; i++ ) printf( " " ); for ( i = 0; i < Vec_IntSize(p->vDivs); i++ ) printf( "%d", i % 10 ); printf( "\n" ); } while ( 1 ) { if ( fVeryVerbose ) { printf( "%3d: %3d ", p->nCexes, iVar ); Vec_WrdForEachEntry( p->vDivCexes, uSign, i ) printf( "%d", Abc_InfoHasBit((unsigned *)&uSign, p->nCexes-1) ); printf( "\n" ); } // find the next divisor to try uMask = (~(word)0) >> (64 - p->nCexes); Vec_WrdForEachEntry( p->vDivCexes, uSign, iVar ) if ( uSign == uMask ) break; if ( iVar == Vec_IntSize(p->vDivs) ) return 0; // try replacing the critical fanin Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, Vec_IntEntry(p->vDivs, iVar)) ); clk = Abc_Clock(); uTruth = Sfm_ComputeInterpolant( p ); p->timeSat += Abc_Clock() - clk; // analyze outcomes if ( uTruth == SFM_SAT_UNDEC ) { p->nTimeOuts++; return 0; } if ( uTruth != SFM_SAT_SAT ) goto finish; if ( p->nCexes == 64 ) return 0; // remove the last variable Vec_IntPop( p->vDivIds ); } finish: if ( p->pPars->fVeryVerbose ) { if ( iVar == -1 ) printf( "Node %d: Fanin %d (%d) can be removed. ", iNode, f, Sfm_ObjFanin(p, iNode, f) ); else printf( "Node %d: Fanin %d (%d) can be replaced by divisor %d (%d). ", iNode, f, Sfm_ObjFanin(p, iNode, f), iVar, Vec_IntEntry(p->vDivs, iVar) ); Kit_DsdPrintFromTruth( (unsigned *)&uTruth, Vec_IntSize(p->vDivIds) ); printf( "\n" ); } if ( iVar == -1 ) p->nRemoves++; else p->nResubs++; if ( fSkipUpdate ) return 0; // update the network Sfm_NtkUpdate( p, iNode, f, (iVar == -1 ? iVar : Vec_IntEntry(p->vDivs, iVar)), uTruth ); return 1; } int Sfm_NodeResub( Sfm_Ntk_t * p, int iNode ) { int i, iFanin; p->nNodesTried++; // prepare SAT solver if ( !Sfm_NtkCreateWindow( p, iNode, p->pPars->fVeryVerbose ) ) return 0; if ( !Sfm_NtkWindowToSolver( p ) ) return 0; // try replacing area critical fanins Sfm_ObjForEachFanin( p, iNode, iFanin, i ) if ( Sfm_ObjIsNode(p, iFanin) && Sfm_ObjFanoutNum(p, iFanin) == 1 ) { if ( Sfm_NodeResubSolve( p, iNode, i, 0 ) ) return 1; } if ( p->pPars->fArea ) return 0; // try removing redundant edges Sfm_ObjForEachFanin( p, iNode, iFanin, i ) if ( !(Sfm_ObjIsNode(p, iFanin) && Sfm_ObjFanoutNum(p, iFanin) == 1) ) { if ( Sfm_NodeResubSolve( p, iNode, i, 1 ) ) return 1; } /* // try replacing area critical fanins while adding two new fanins if ( Sfm_ObjFaninNum(p, iNode) < p->nFaninMax ) Abc_ObjForEachFanin( pNode, pFanin, i ) if ( !Abc_ObjIsCi(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) { if ( Abc_NtkMfsSolveSatResub2( p, pNode, i, -1 ) ) return 1; } */ return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_NtkPerform( Sfm_Ntk_t * p, Sfm_Par_t * pPars ) { int i, k, Counter = 0; p->timeTotal = Abc_Clock(); if ( pPars->fVerbose ) { int nFixed = p->vFixed ? Vec_StrSum(p->vFixed) : 0; int nEmpty = p->vEmpty ? Vec_StrSum(p->vEmpty) : 0; printf( "Performing MFS with %d PIs, %d POs, %d nodes (%d flexible, %d fixed, %d empty).\n", p->nPis, p->nPos, p->nNodes, p->nNodes-nFixed, nFixed, nEmpty ); } p->pPars = pPars; Sfm_NtkPrepare( p ); // Sfm_ComputeInterpolantCheck( p ); // return 0; p->nTotalNodesBeg = Vec_WecSizeUsedLimits( &p->vFanins, Sfm_NtkPiNum(p), Vec_WecSize(&p->vFanins) - Sfm_NtkPoNum(p) ); p->nTotalEdgesBeg = Vec_WecSizeSize(&p->vFanins) - Sfm_NtkPoNum(p); Sfm_NtkForEachNode( p, i ) { if ( Sfm_ObjIsFixed( p, i ) ) continue; if ( p->pPars->nDepthMax && Sfm_ObjLevel(p, i) > p->pPars->nDepthMax ) continue; if ( Sfm_ObjFaninNum(p, i) < 2 || Sfm_ObjFaninNum(p, i) > 6 ) continue; for ( k = 0; Sfm_NodeResub(p, i); k++ ) { // Counter++; // break; } Counter += (k > 0); if ( pPars->nNodesMax && Counter >= pPars->nNodesMax ) break; } p->nTotalNodesEnd = Vec_WecSizeUsedLimits( &p->vFanins, Sfm_NtkPiNum(p), Vec_WecSize(&p->vFanins) - Sfm_NtkPoNum(p) ); p->nTotalEdgesEnd = Vec_WecSizeSize(&p->vFanins) - Sfm_NtkPoNum(p); p->timeTotal = Abc_Clock() - p->timeTotal; if ( pPars->fVerbose ) Sfm_NtkPrintStats( p ); return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmDec.c000066400000000000000000002526541300674244400230060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [SAT-based decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "base/abc/abc.h" #include "misc/util/utilTruth.h" #include "opt/dau/dau.h" #include "map/mio/exp.h" #include "map/scl/sclCon.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Sfm_Dec_t_ Sfm_Dec_t; struct Sfm_Dec_t_ { // external Sfm_Par_t * pPars; // parameters Sfm_Lib_t * pLib; // library Sfm_Tim_t * pTim; // timing Sfm_Mit_t * pMit; // timing Abc_Ntk_t * pNtk; // network // library Vec_Int_t vGateSizes; // fanin counts Vec_Wrd_t vGateFuncs; // gate truth tables Vec_Wec_t vGateCnfs; // gate CNFs Vec_Ptr_t vGateHands; // gate handles int GateConst0; // special gates int GateConst1; // special gates int GateBuffer; // special gates int GateInvert; // special gates int GateAnd[4]; // special gates int GateOr[4]; // special gates // objects int nDivs; // the number of divisors int nMffc; // the number of divisors int AreaMffc; // the area of gates in MFFC int DelayMin; // temporary min delay int iTarget; // target node int iUseThis; // next cofactoring var to try int DeltaCrit; // critical delta int AreaInv; // inverter area int DelayInv; // inverter delay Mio_Gate_t * pGateInv; // inverter word uCareSet; // computed careset Vec_Int_t vObjRoots; // roots of the window Vec_Int_t vObjGates; // functionality Vec_Wec_t vObjFanins; // fanin IDs Vec_Int_t vObjMap; // object map Vec_Int_t vObjDec; // decomposition Vec_Int_t vObjMffc; // MFFC nodes Vec_Int_t vObjInMffc; // inputs of MFFC nodes Vec_Wrd_t vObjSims; // simulation patterns Vec_Wrd_t vObjSims2; // simulation patterns Vec_Ptr_t vMatchGates; // matched gates Vec_Ptr_t vMatchFans; // matched fanins // solver sat_solver * pSat; // reusable solver Vec_Wec_t vClauses; // CNF clauses for the node Vec_Int_t vImpls[2]; // onset/offset implications Vec_Wrd_t vSets[2]; // onset/offset patterns int nPats[2]; // CEX count int nPatWords[2];// CEX words int nDivWords; // div words int nDivWordsAlloc; // div words word TtElems[SFM_SUPP_MAX][SFM_WORD_MAX]; word * pTtElems[SFM_SUPP_MAX]; word * pDivWords[SFM_SUPP_MAX]; // temporary Vec_Int_t vNewNodes; Vec_Int_t vGateTfi; Vec_Int_t vGateTfo; Vec_Int_t vGateCut; Vec_Int_t vGateTemp; Vec_Int_t vGateMffc; Vec_Int_t vCands; word Copy[4]; int nSuppVars; // statistics abctime timeLib; abctime timeWin; abctime timeCnf; abctime timeSat; abctime timeSatSat; abctime timeSatUnsat; abctime timeEval; abctime timeTime; abctime timeOther; abctime timeStart; abctime timeTotal; int nTotalNodesBeg; int nTotalEdgesBeg; int nTotalNodesEnd; int nTotalEdgesEnd; int nNodesTried; int nNodesChanged; int nNodesConst0; int nNodesConst1; int nNodesBuf; int nNodesInv; int nNodesAndOr; int nNodesResyn; int nSatCalls; int nSatCallsSat; int nSatCallsUnsat; int nSatCallsOver; int nTimeOuts; int nNoDecs; int nEfforts; int nMaxDivs; int nMaxWin; word nAllDivs; word nAllWin; int nLuckySizes[SFM_SUPP_MAX+1]; int nLuckyGates[SFM_SUPP_MAX+1]; }; #define SFM_MASK_PI 1 // supp(node) is contained in supp(TFI(pivot)) #define SFM_MASK_INPUT 2 // supp(node) does not overlap with supp(TFI(pivot)) #define SFM_MASK_FANIN 4 // the same as above (pointed to by node with SFM_MASK_PI | SFM_MASK_INPUT) #define SFM_MASK_MFFC 8 // MFFC nodes, including the target node #define SFM_MASK_PIVOT 16 // the target node static inline Sfm_Dec_t * Sfm_DecMan( Abc_Obj_t * p ) { return (Sfm_Dec_t *)p->pNtk->pData; } static inline word Sfm_DecObjSim( Sfm_Dec_t * p, Abc_Obj_t * pObj ) { return Vec_WrdEntry(&p->vObjSims, Abc_ObjId(pObj)); } static inline word Sfm_DecObjSim2( Sfm_Dec_t * p, Abc_Obj_t * pObj ) { return Vec_WrdEntry(&p->vObjSims2, Abc_ObjId(pObj)); } static inline word * Sfm_DecDivPats( Sfm_Dec_t * p, int d, int c ) { return Vec_WrdEntryP(&p->vSets[c], d*SFM_SIM_WORDS); } static inline int Sfm_ManReadObjDelay( Sfm_Dec_t * p, int Id ) { return p->pMit ? Sfm_MitReadObjDelay(p->pMit, Id) : Sfm_TimReadObjDelay(p->pTim, Id); } static inline int Sfm_ManReadNtkDelay( Sfm_Dec_t * p ) { return p->pMit ? Sfm_MitReadNtkDelay(p->pMit) : Sfm_TimReadNtkDelay(p->pTim); } static inline int Sfm_ManReadNtkMinSlack( Sfm_Dec_t * p ) { return p->pMit ? Sfm_MitReadNtkMinSlack(p->pMit) : 0; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Setup parameter structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_ParSetDefault3( Sfm_Par_t * pPars ) { memset( pPars, 0, sizeof(Sfm_Par_t) ); pPars->nTfoLevMax = 100; // the maximum fanout levels pPars->nTfiLevMax = 100; // the maximum fanin levels pPars->nFanoutMax = 10; // the maximum number of fanouts pPars->nMffcMin = 1; // the maximum MFFC size pPars->nMffcMax = 3; // the maximum MFFC size pPars->nVarMax = 6; // the maximum variable count pPars->nDecMax = 1; // the maximum number of decompositions pPars->nWinSizeMax = 0; // the maximum window size pPars->nGrowthLevel = 0; // the maximum allowed growth in level pPars->nBTLimit = 0; // the maximum number of conflicts in one SAT run pPars->nTimeWin = 1; // the size of timing window in percents pPars->DeltaCrit = 0; // delta delay in picoseconds pPars->fUseAndOr = 0; // enable internal detection of AND/OR gates pPars->fZeroCost = 0; // enable zero-cost replacement pPars->fMoreEffort = 0; // enables using more effort pPars->fUseSim = 0; // enable simulation pPars->fArea = 0; // performs optimization for area pPars->fVerbose = 0; // enable basic stats pPars->fVeryVerbose = 0; // enable detailed stats } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sfm_Dec_t * Sfm_DecStart( Sfm_Par_t * pPars, Mio_Library_t * pLib, Abc_Ntk_t * pNtk ) { extern void Sfm_LibPreprocess( Mio_Library_t * pLib, Vec_Int_t * vGateSizes, Vec_Wrd_t * vGateFuncs, Vec_Wec_t * vGateCnfs, Vec_Ptr_t * vGateHands ); Sfm_Dec_t * p = ABC_CALLOC( Sfm_Dec_t, 1 ); int i; p->timeStart = Abc_Clock(); p->pPars = pPars; p->pNtk = pNtk; p->pSat = sat_solver_new(); p->pGateInv = Mio_LibraryReadInv( pLib ); p->AreaInv = Scl_Flt2Int(Mio_GateReadArea(p->pGateInv)); p->DelayInv = Scl_Flt2Int(Mio_GateReadDelayMax(p->pGateInv)); p->DeltaCrit = pPars->DeltaCrit ? Scl_Flt2Int((float)pPars->DeltaCrit) : 5 * Scl_Flt2Int(Mio_LibraryReadDelayInvMax(pLib)) / 2; p->timeLib = Abc_Clock(); p->pLib = Sfm_LibPrepare( pPars->nVarMax, 1, !pPars->fArea, pPars->fVerbose, pPars->fLibVerbose ); p->timeLib = Abc_Clock() - p->timeLib; if ( !pPars->fArea ) { if ( Abc_FrameReadLibScl() ) p->pMit = Sfm_MitStart( pLib, (SC_Lib *)Abc_FrameReadLibScl(), Scl_ConReadMan(), pNtk, p->DeltaCrit ); if ( p->pMit == NULL ) p->pTim = Sfm_TimStart( pLib, Scl_ConReadMan(), pNtk, p->DeltaCrit ); } if ( pPars->fVeryVerbose ) // if ( pPars->fVerbose ) Sfm_LibPrint( p->pLib ); pNtk->pData = p; // enter library assert( Abc_NtkIsMappedLogic(pNtk) ); Sfm_LibPreprocess( pLib, &p->vGateSizes, &p->vGateFuncs, &p->vGateCnfs, &p->vGateHands ); p->GateConst0 = Mio_GateReadValue( Mio_LibraryReadConst0(pLib) ); p->GateConst1 = Mio_GateReadValue( Mio_LibraryReadConst1(pLib) ); p->GateBuffer = Mio_GateReadValue( Mio_LibraryReadBuf(pLib) ); p->GateInvert = Mio_GateReadValue( Mio_LibraryReadInv(pLib) ); // elementary truth tables for ( i = 0; i < SFM_SUPP_MAX; i++ ) p->pTtElems[i] = p->TtElems[i]; Abc_TtElemInit( p->pTtElems, SFM_SUPP_MAX ); p->iUseThis = -1; return p; } void Sfm_DecStop( Sfm_Dec_t * p ) { Abc_Ntk_t * pNtk = p->pNtk; Abc_Obj_t * pObj; int i; Abc_NtkForEachNode( pNtk, pObj, i ) if ( (int)pObj->Level != Abc_ObjLevelNew(pObj) ) printf( "Level count mismatch at node %d.\n", i ); Sfm_LibStop( p->pLib ); if ( p->pTim ) Sfm_TimStop( p->pTim ); if ( p->pMit ) Sfm_MitStop( p->pMit ); // divisors for ( i = 0; i < SFM_SUPP_MAX; i++ ) ABC_FREE( p->pDivWords[i] ); // library Vec_IntErase( &p->vGateSizes ); Vec_WrdErase( &p->vGateFuncs ); Vec_WecErase( &p->vGateCnfs ); Vec_PtrErase( &p->vGateHands ); // objects Vec_IntErase( &p->vObjRoots ); Vec_IntErase( &p->vObjGates ); Vec_WecErase( &p->vObjFanins ); Vec_IntErase( &p->vObjMap ); Vec_IntErase( &p->vObjDec ); Vec_IntErase( &p->vObjMffc ); Vec_IntErase( &p->vObjInMffc ); Vec_WrdErase( &p->vObjSims ); Vec_WrdErase( &p->vObjSims2 ); Vec_PtrErase( &p->vMatchGates ); Vec_PtrErase( &p->vMatchFans ); // solver sat_solver_delete( p->pSat ); Vec_WecErase( &p->vClauses ); Vec_IntErase( &p->vImpls[0] ); Vec_IntErase( &p->vImpls[1] ); Vec_WrdErase( &p->vSets[0] ); Vec_WrdErase( &p->vSets[1] ); // temporary Vec_IntErase( &p->vNewNodes ); Vec_IntErase( &p->vGateTfi ); Vec_IntErase( &p->vGateTfo ); Vec_IntErase( &p->vGateCut ); Vec_IntErase( &p->vGateTemp ); Vec_IntErase( &p->vGateMffc ); Vec_IntErase( &p->vCands ); ABC_FREE( p ); pNtk->pData = NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Sfm_ObjSimulate( Abc_Obj_t * pObj ) { Sfm_Dec_t * p = Sfm_DecMan( pObj ); Vec_Int_t * vExpr = Mio_GateReadExpr( (Mio_Gate_t *)pObj->pData ); Abc_Obj_t * pFanin; int i; word uFanins[6]; assert( Abc_ObjFaninNum(pObj) <= 6 ); Abc_ObjForEachFanin( pObj, pFanin, i ) uFanins[i] = Sfm_DecObjSim( p, pFanin ); return Exp_Truth6( Abc_ObjFaninNum(pObj), vExpr, uFanins ); } static inline word Sfm_ObjSimulate2( Abc_Obj_t * pObj ) { Sfm_Dec_t * p = Sfm_DecMan( pObj ); Vec_Int_t * vExpr = Mio_GateReadExpr( (Mio_Gate_t *)pObj->pData ); Abc_Obj_t * pFanin; int i; word uFanins[6]; Abc_ObjForEachFanin( pObj, pFanin, i ) if ( (pFanin->iTemp & SFM_MASK_PIVOT) ) uFanins[i] = Sfm_DecObjSim2( p, pFanin ); else uFanins[i] = Sfm_DecObjSim( p, pFanin ); return Exp_Truth6( Abc_ObjFaninNum(pObj), vExpr, uFanins ); } static inline void Sfm_NtkSimulate( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; word uTemp; Sfm_Dec_t * p = Sfm_DecMan( Abc_NtkPi(pNtk, 0) ); Vec_WrdFill( &p->vObjSims, 2*Abc_NtkObjNumMax(pNtk), 0 ); Vec_WrdFill( &p->vObjSims2, 2*Abc_NtkObjNumMax(pNtk), 0 ); Gia_ManRandomW(1); assert( p->pPars->fUseSim ); Abc_NtkForEachCi( pNtk, pObj, i ) { Vec_WrdWriteEntry( &p->vObjSims, Abc_ObjId(pObj), (uTemp = Gia_ManRandomW(0)) ); //printf( "Inpt = %5d : ", Abc_ObjId(pObj) ); //Extra_PrintBinary( stdout, (unsigned *)&uTemp, 64 ); //printf( "\n" ); } vNodes = Abc_NtkDfs( pNtk, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Vec_WrdWriteEntry( &p->vObjSims, Abc_ObjId(pObj), (uTemp = Sfm_ObjSimulate(pObj)) ); //printf( "Obj = %5d : ", Abc_ObjId(pObj) ); //Extra_PrintBinary( stdout, (unsigned *)&uTemp, 64 ); //printf( "\n" ); } Vec_PtrFree( vNodes ); } static inline void Sfm_ObjSimulateNode( Abc_Obj_t * pObj ) { Sfm_Dec_t * p = Sfm_DecMan( pObj ); if ( !p->pPars->fUseSim ) return; Vec_WrdWriteEntry( &p->vObjSims, Abc_ObjId(pObj), Sfm_ObjSimulate(pObj) ); if ( (pObj->iTemp & SFM_MASK_PIVOT) ) Vec_WrdWriteEntry( &p->vObjSims2, Abc_ObjId(pObj), Sfm_ObjSimulate2(pObj) ); } static inline void Sfm_ObjFlipNode( Abc_Obj_t * pObj ) { Sfm_Dec_t * p = Sfm_DecMan( pObj ); if ( !p->pPars->fUseSim ) return; Vec_WrdWriteEntry( &p->vObjSims2, Abc_ObjId(pObj), ~Sfm_DecObjSim(p, pObj) ); } static inline word Sfm_ObjFindCareSet( Abc_Ntk_t * pNtk, Vec_Int_t * vRoots ) { Sfm_Dec_t * p = Sfm_DecMan( Abc_NtkPi(pNtk, 0) ); Abc_Obj_t * pObj; int i; word Res = 0; if ( !p->pPars->fUseSim ) return 0; Abc_NtkForEachObjVec( vRoots, pNtk, pObj, i ) Res |= Sfm_DecObjSim(p, pObj) ^ Sfm_DecObjSim2(p, pObj); return Res; } static inline void Sfm_ObjSetupSimInfo( Abc_Obj_t * pObj ) { Sfm_Dec_t * p = Sfm_DecMan( pObj ); int i; p->nPats[0] = p->nPats[1] = 0; p->nPatWords[0] = p->nPatWords[1] = 0; Vec_WrdFill( &p->vSets[0], p->nDivs*SFM_SIM_WORDS, 0 ); Vec_WrdFill( &p->vSets[1], p->nDivs*SFM_SIM_WORDS, 0 ); // alloc divwords p->nDivWords = Abc_Bit6WordNum( 4 * p->nDivs ); if ( p->nDivWordsAlloc < p->nDivWords ) { p->nDivWordsAlloc = Abc_MaxInt( 16, p->nDivWords ); for ( i = 0; i < SFM_SUPP_MAX; i++ ) p->pDivWords[i] = ABC_REALLOC( word, p->pDivWords[i], p->nDivWordsAlloc ); } memset( p->pDivWords[0], 0, sizeof(word) * p->nDivWords ); // collect simulation info if ( p->pPars->fUseSim && p->uCareSet != 0 ) { word uCareSet = p->uCareSet; word uValues = Sfm_DecObjSim(p, pObj); int c, d, i, Indexes[2][64]; assert( p->iTarget == pObj->iTemp ); assert( p->pPars->fUseSim ); // find what patterns go to on-set/off-set for ( i = 0; i < 64; i++ ) if ( (uCareSet >> i) & 1 ) { c = !((uValues >> i) & 1); Indexes[c][p->nPats[c]++] = i; } for ( c = 0; c < 2; c++ ) p->nPatWords[c] = 1 + (p->nPats[c] >> 6); // write patterns for ( d = 0; d < p->nDivs; d++ ) { word uSim = Vec_WrdEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d) ); for ( c = 0; c < 2; c++ ) for ( i = 0; i < p->nPats[c]; i++ ) if ( (uSim >> Indexes[c][i]) & 1 ) Abc_TtSetBit( Sfm_DecDivPats(p, d, c), i ); } //printf( "Node %d : Onset = %d. Offset = %d.\n", pObj->Id, p->nPats[0], p->nPats[1] ); } } static inline void Sfm_ObjSetdownSimInfo( Abc_Obj_t * pObj ) { int nPatKeep = 32; Sfm_Dec_t * p = Sfm_DecMan( pObj ); int c, d; word uSim, uSims[2], uMask; if ( !p->pPars->fUseSim ) return; for ( d = 0; d < p->nDivs; d++ ) { uSim = Vec_WrdEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d) ); for ( c = 0; c < 2; c++ ) { uMask = Abc_Tt6Mask( Abc_MinInt(p->nPats[c], nPatKeep) ); uSims[c] = (Sfm_DecDivPats(p, d, c)[0] & uMask) | (uSim & ~uMask); uSim >>= 32; } uSim = (uSims[0] & 0xFFFFFFFF) | (uSims[1] << 32); Vec_WrdWriteEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d), uSim ); } } /* void Sfm_ObjSetdownSimInfo( Abc_Obj_t * pObj ) { int nPatKeep = 32; Sfm_Dec_t * p = Sfm_DecMan( pObj ); word uSim, uMaskKeep[2]; int c, d, nKeeps[2]; for ( c = 0; c < 2; c++ ) { nKeeps[c] = Abc_MaxInt(p->nPats[c], nPatKeep); uMaskKeep[c] = Abc_Tt6Mask( nKeeps[c] ); } for ( d = 0; d < p->nDivs; d++ ) { uSim = Vec_WrdEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d) ) << (nKeeps[0] + nKeeps[1]); uSim |= (Vec_WrdEntry(&p->vSets[0], d) & uMaskKeep[0]) | ((Vec_WrdEntry(&p->vSets[1], d) & uMaskKeep[1]) << nKeeps[0]); Vec_WrdWriteEntry( &p->vObjSims, Vec_IntEntry(&p->vObjMap, d), uSim ); } } */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_DecPrepareSolver( Sfm_Dec_t * p ) { Vec_Int_t * vRoots = &p->vObjRoots; Vec_Int_t * vFaninVars = &p->vGateTemp; Vec_Int_t * vLevel, * vClause; int i, k, Gate, iObj, RetValue; int nTfiSize = p->iTarget + 1; // including node int nWinSize = Vec_IntSize(&p->vObjGates); int nSatVars = 2 * nWinSize - nTfiSize; assert( nWinSize == Vec_IntSize(&p->vObjGates) ); assert( p->iTarget < nWinSize ); // create SAT solver sat_solver_restart( p->pSat ); sat_solver_setnvars( p->pSat, nSatVars + Vec_IntSize(vRoots) ); // add CNF clauses for the TFI Vec_IntForEachEntry( &p->vObjGates, Gate, i ) { if ( Gate == -1 ) continue; // generate CNF vLevel = Vec_WecEntry( &p->vObjFanins, i ); Vec_IntPush( vLevel, i ); Sfm_TranslateCnf( &p->vClauses, (Vec_Str_t *)Vec_WecEntry(&p->vGateCnfs, Gate), vLevel, -1 ); Vec_IntPop( vLevel ); // add clauses Vec_WecForEachLevel( &p->vClauses, vClause, k ) { if ( Vec_IntSize(vClause) == 0 ) break; RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) ); if ( RetValue == 0 ) return 0; } } // add CNF clauses for the TFO Vec_IntForEachEntryStart( &p->vObjGates, Gate, i, nTfiSize ) { assert( Gate != -1 ); vLevel = Vec_WecEntry( &p->vObjFanins, i ); Vec_IntClear( vFaninVars ); Vec_IntForEachEntry( vLevel, iObj, k ) Vec_IntPush( vFaninVars, iObj <= p->iTarget ? iObj : iObj + nWinSize - nTfiSize ); Vec_IntPush( vFaninVars, i + nWinSize - nTfiSize ); // generate CNF Sfm_TranslateCnf( &p->vClauses, (Vec_Str_t *)Vec_WecEntry(&p->vGateCnfs, Gate), vFaninVars, p->iTarget ); // add clauses Vec_WecForEachLevel( &p->vClauses, vClause, k ) { if ( Vec_IntSize(vClause) == 0 ) break; RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) ); if ( RetValue == 0 ) return 0; } } if ( nTfiSize < nWinSize ) { // create XOR clauses for the roots Vec_IntClear( vFaninVars ); Vec_IntForEachEntry( vRoots, iObj, i ) { Vec_IntPush( vFaninVars, Abc_Var2Lit(nSatVars, 0) ); sat_solver_add_xor( p->pSat, iObj, iObj + nWinSize - nTfiSize, nSatVars++, 0 ); } // make OR clause for the last nRoots variables RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vFaninVars), Vec_IntLimit(vFaninVars) ); if ( RetValue == 0 ) return 0; assert( nSatVars == sat_solver_nvars(p->pSat) ); } else assert( Vec_IntSize(vRoots) == 1 ); // finalize RetValue = sat_solver_simplify( p->pSat ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_DecFindCost( Sfm_Dec_t * p, int c, int iLit, word * pMask ) { word * pPats = Sfm_DecDivPats( p, Abc_Lit2Var(iLit), !c ); return Abc_TtCountOnesVecMask( pPats, pMask, p->nPatWords[!c], Abc_LitIsCompl(iLit) ); } void Sfm_DecPrint( Sfm_Dec_t * p, word Masks[2][SFM_SIM_WORDS] ) { int c, i, k, Entry; for ( c = 0; c < 2; c++ ) { Vec_Int_t * vLevel = Vec_WecEntry( &p->vObjFanins, p->iTarget ); printf( "%s-SET of object %d (divs = %d) with gate \"%s\" and fanins: ", c ? "OFF": "ON", p->iTarget, p->nDivs, Mio_GateReadName((Mio_Gate_t *)Vec_PtrEntry(&p->vGateHands, Vec_IntEntry(&p->vObjGates,p->iTarget))) ); Vec_IntForEachEntry( vLevel, Entry, i ) printf( "%d ", Entry ); printf( "\n" ); printf( "Implications: " ); Vec_IntForEachEntry( &p->vImpls[c], Entry, i ) printf( "%s%d(%d) ", Abc_LitIsCompl(Entry)? "!":"", Abc_Lit2Var(Entry), Sfm_DecFindCost(p, c, Entry, Masks[!c]) ); printf( "\n" ); printf( " " ); for ( i = 0; i < p->nDivs; i++ ) printf( "%d", (i / 10) % 10 ); printf( "\n" ); printf( " " ); for ( i = 0; i < p->nDivs; i++ ) printf( "%d", i % 10 ); printf( "\n" ); for ( k = 0; k < p->nPats[c]; k++ ) { printf( "%2d : ", k ); for ( i = 0; i < p->nDivs; i++ ) printf( "%d", Abc_TtGetBit(Sfm_DecDivPats(p, i, c), k) ); printf( "\n" ); } //printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_DecVarCost( Sfm_Dec_t * p, word Masks[2][SFM_SIM_WORDS], int d, int Counts[2][2] ) { int c; for ( c = 0; c < 2; c++ ) { word * pPats = Sfm_DecDivPats( p, d, c ); int Num = Abc_TtCountOnesVec( Masks[c], p->nPatWords[c] ); Counts[c][1] = Abc_TtCountOnesVecMask( pPats, Masks[c], p->nPatWords[c], 0 ); Counts[c][0] = Num - Counts[c][1]; assert( Counts[c][0] >= 0 && Counts[c][1] >= 0 ); } //printf( "%5d %5d %5d %5d \n", Counts[0][0], Counts[0][1], Counts[1][0], Counts[1][1] ); } int Sfm_DecFindBestVar2( Sfm_Dec_t * p, word Masks[2][SFM_SIM_WORDS] ) { int Counts[2][2]; int d, VarBest = -1, CostBest = ABC_INFINITY, Cost; for ( d = 0; d < p->nDivs; d++ ) { Sfm_DecVarCost( p, Masks, d, Counts ); if ( (Counts[0][0] < Counts[0][1]) == (Counts[1][0] < Counts[1][1]) ) continue; Cost = Abc_MinInt(Counts[0][0], Counts[0][1]) + Abc_MinInt(Counts[1][0], Counts[1][1]); if ( CostBest > Cost ) { CostBest = Cost; VarBest = d; } } return VarBest; } int Sfm_DecFindBestVar( Sfm_Dec_t * p, word Masks[2][SFM_SIM_WORDS] ) { int c, i, iLit, Var = -1, Cost, CostMin = ABC_INFINITY; for ( c = 0; c < 2; c++ ) { Vec_IntForEachEntry( &p->vImpls[c], iLit, i ) { if ( Vec_IntSize(&p->vImpls[c]) > 1 && Vec_IntFind(&p->vObjDec, Abc_Lit2Var(iLit)) >= 0 ) continue; Cost = Sfm_DecFindCost( p, c, iLit, Masks[!c] ); if ( CostMin > Cost ) { CostMin = Cost; Var = Abc_Lit2Var(iLit); } } } return Var; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_DecMffcArea( Abc_Ntk_t * pNtk, Vec_Int_t * vMffc ) { Abc_Obj_t * pObj; int i, nAreaMffc = 0; Abc_NtkForEachObjVec( vMffc, pNtk, pObj, i ) nAreaMffc += Scl_Flt2Int(Mio_GateReadArea((Mio_Gate_t *)pObj->pData)); return nAreaMffc; } int Sfm_MffcDeref_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i, Area = Scl_Flt2Int(Mio_GateReadArea((Mio_Gate_t *)pObj->pData)); Abc_ObjForEachFanin( pObj, pFanin, i ) { assert( pFanin->vFanouts.nSize > 0 ); if ( --pFanin->vFanouts.nSize == 0 && !Abc_ObjIsCi(pFanin) ) Area += Sfm_MffcDeref_rec( pFanin ); } return Area; } int Sfm_MffcRef_rec( Abc_Obj_t * pObj, Vec_Int_t * vMffc ) { Abc_Obj_t * pFanin; int i, Area = Scl_Flt2Int(Mio_GateReadArea((Mio_Gate_t *)pObj->pData)); Abc_ObjForEachFanin( pObj, pFanin, i ) { if ( pFanin->vFanouts.nSize++ == 0 && !Abc_ObjIsCi(pFanin) ) Area += Sfm_MffcRef_rec( pFanin, vMffc ); } if ( vMffc ) Vec_IntPush( vMffc, Abc_ObjId(pObj) ); return Area; } int Sfm_DecMffcAreaReal( Abc_Obj_t * pPivot, Vec_Int_t * vCut, Vec_Int_t * vMffc ) { Abc_Ntk_t * pNtk = pPivot->pNtk; Abc_Obj_t * pObj; int i, Area1, Area2; assert( Abc_ObjIsNode(pPivot) ); if ( vMffc ) Vec_IntClear( vMffc ); Abc_NtkForEachObjVec( vCut, pNtk, pObj, i ) pObj->vFanouts.nSize++; Area1 = Sfm_MffcDeref_rec( pPivot ); Area2 = Sfm_MffcRef_rec( pPivot, vMffc ); Abc_NtkForEachObjVec( vCut, pNtk, pObj, i ) pObj->vFanouts.nSize--; assert( Area1 == Area2 ); return Area1; } void Sfm_DecPrepareVec( Vec_Int_t * vMap, int * pNodes, int nNodes, Vec_Int_t * vCut ) { int i; Vec_IntClear( vCut ); for ( i = 0; i < nNodes; i++ ) Vec_IntPush( vCut, Vec_IntEntry(vMap, pNodes[i]) ); } int Sfm_DecComputeFlipInvGain( Sfm_Dec_t * p, Abc_Obj_t * pPivot, int * pfNeedInv ) { Abc_Obj_t * pFanout; Mio_Gate_t * pGate, * pGateNew; int i, Handle, fNeedInv = 0, Gain = 0; Abc_ObjForEachFanout( pPivot, pFanout, i ) { if ( !Abc_ObjIsNode(pFanout) ) { fNeedInv = 1; continue; } pGate = (Mio_Gate_t*)pFanout->pData; if ( Abc_ObjFaninNum(pFanout) == 1 && Mio_GateIsInv(pGate) ) { Gain += p->AreaInv; continue; } Handle = Sfm_LibFindComplInputGate( &p->vGateFuncs, Mio_GateReadValue(pGate), Abc_ObjFaninNum(pFanout), Abc_NodeFindFanin(pFanout, pPivot), NULL ); if ( Handle == -1 ) { fNeedInv = 1; continue; } pGateNew = (Mio_Gate_t *)Vec_PtrEntry( &p->vGateHands, Handle ); Gain += Scl_Flt2Int(Mio_GateReadArea(pGate)) - Scl_Flt2Int(Mio_GateReadArea(pGateNew)); } if ( fNeedInv ) Gain -= p->AreaInv; if ( pfNeedInv ) *pfNeedInv = fNeedInv; return Gain; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_DecCombineDec( Sfm_Dec_t * p, word * pTruth0, word * pTruth1, int * pSupp0, int * pSupp1, int nSupp0, int nSupp1, word * pTruth, int * pSupp, int Var ) { Vec_Int_t vVec0 = { 2*SFM_SUPP_MAX, nSupp0, pSupp0 }; Vec_Int_t vVec1 = { 2*SFM_SUPP_MAX, nSupp1, pSupp1 }; Vec_Int_t vVec = { 2*SFM_SUPP_MAX, 0, pSupp }; int nWords0 = Abc_TtWordNum(nSupp0); int nSupp, iSuppVar; // check the case of equal cofactors if ( nSupp0 == nSupp1 && !memcmp(pSupp0, pSupp1, sizeof(int)*nSupp0) && !memcmp(pTruth0, pTruth1, sizeof(word)*nWords0) ) { memcpy( pSupp, pSupp0, sizeof(int)*nSupp0 ); memcpy( pTruth, pTruth0, sizeof(word)*nWords0 ); Abc_TtStretch6( pTruth, nSupp0, p->pPars->nVarMax ); return nSupp0; } // merge support variables Vec_IntTwoMerge2Int( &vVec0, &vVec1, &vVec ); Vec_IntPushOrder( &vVec, Var ); nSupp = Vec_IntSize( &vVec ); if ( nSupp > p->pPars->nVarMax ) return -2; // expand truth tables Abc_TtStretch6( pTruth0, nSupp0, nSupp ); Abc_TtStretch6( pTruth1, nSupp1, nSupp ); Abc_TtExpand( pTruth0, nSupp, pSupp0, nSupp0, pSupp, nSupp ); Abc_TtExpand( pTruth1, nSupp, pSupp1, nSupp1, pSupp, nSupp ); // perform operation iSuppVar = Vec_IntFind( &vVec, Var ); Abc_TtMux( pTruth, p->pTtElems[iSuppVar], pTruth1, pTruth0, Abc_TtWordNum(nSupp) ); Abc_TtStretch6( pTruth, nSupp, p->pPars->nVarMax ); return nSupp; } int Sfm_DecPeformDec_rec( Sfm_Dec_t * p, word * pTruth, int * pSupp, int * pAssump, int nAssump, word Masks[2][SFM_SIM_WORDS], int fCofactor, int nSuppAdd ) { int nBTLimit = p->pPars->nBTLimit; // int fVerbose = p->pPars->fVeryVerbose; int c, i, d, iLit, status, Var = -1; word * pDivWords = p->pDivWords[nAssump]; abctime clk; assert( nAssump <= SFM_SUPP_MAX ); if ( p->pPars->fVeryVerbose ) { printf( "\nObject %d\n", p->iTarget ); printf( "Divs = %d. Nodes = %d. Mffc = %d. Mffc area = %.2f. ", p->nDivs, Vec_IntSize(&p->vObjGates), p->nMffc, Scl_Int2Flt(p->AreaMffc) ); printf( "Pat0 = %d. Pat1 = %d. ", p->nPats[0], p->nPats[1] ); printf( "\n" ); if ( nAssump ) { printf( "Cofactor: " ); for ( i = 0; i < nAssump; i++ ) printf( " %s%d", Abc_LitIsCompl(pAssump[i])? "!":"", Abc_Lit2Var(pAssump[i]) ); printf( "\n" ); } } // check constant for ( c = 0; c < 2; c++ ) { if ( !Abc_TtIsConst0(Masks[c], p->nPatWords[c]) ) // there are some patterns continue; p->nSatCalls++; pAssump[nAssump] = Abc_Var2Lit( p->iTarget, c ); clk = Abc_Clock(); status = sat_solver_solve( p->pSat, pAssump, pAssump + nAssump + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) { p->nTimeOuts++; return -2; } if ( status == l_False ) { p->nSatCallsUnsat++; p->timeSatUnsat += Abc_Clock() - clk; Abc_TtConst( pTruth, Abc_TtWordNum(p->pPars->nVarMax), c ); if ( p->pPars->fVeryVerbose ) printf( "Found constant %d.\n", c ); return 0; } assert( status == l_True ); p->nSatCallsSat++; p->timeSatSat += Abc_Clock() - clk; if ( p->nPats[c] == 64*SFM_SIM_WORDS ) { p->nSatCallsOver++; continue;//return -2;//continue; } for ( i = 0; i < p->nDivs; i++ ) if ( sat_solver_var_value(p->pSat, i) ) Abc_TtSetBit( Sfm_DecDivPats(p, i, c), p->nPats[c] ); p->nPatWords[c] = 1 + (p->nPats[c] >> 6); Abc_TtSetBit( Masks[c], p->nPats[c]++ ); } if ( p->iUseThis != -1 ) { Var = p->iUseThis; p->iUseThis = -1; goto cofactor; } // check implications Vec_IntClear( &p->vImpls[0] ); Vec_IntClear( &p->vImpls[1] ); for ( d = 0; d < p->nDivs; d++ ) { int Impls[2] = {-1, -1}; for ( c = 0; c < 2; c++ ) { word * pPats = Sfm_DecDivPats( p, d, c ); int fHas0s = Abc_TtIntersect( pPats, Masks[c], p->nPatWords[c], 1 ); int fHas1s = Abc_TtIntersect( pPats, Masks[c], p->nPatWords[c], 0 ); if ( fHas0s && fHas1s ) continue; pAssump[nAssump] = Abc_Var2Lit( p->iTarget, c ); pAssump[nAssump+1] = Abc_Var2Lit( d, fHas1s ); // if there are 1s, check if 0 is SAT clk = Abc_Clock(); if ( Abc_TtGetBit( pDivWords, 4*d+2*c+fHas1s ) ) { p->nSatCallsUnsat--; status = l_False; } else { p->nSatCalls++; status = sat_solver_solve( p->pSat, pAssump, pAssump + nAssump + 2, nBTLimit, 0, 0, 0 ); } if ( status == l_Undef ) { p->nTimeOuts++; return -2; } if ( status == l_False ) { p->nSatCallsUnsat++; p->timeSatUnsat += Abc_Clock() - clk; Impls[c] = Abc_LitNot(pAssump[nAssump+1]); Vec_IntPush( &p->vImpls[c], Abc_LitNot(pAssump[nAssump+1]) ); Abc_TtSetBit( pDivWords, 4*d+2*c+fHas1s ); continue; } assert( status == l_True ); p->nSatCallsSat++; p->timeSatSat += Abc_Clock() - clk; if ( p->nPats[c] == 64*SFM_SIM_WORDS ) { p->nSatCallsOver++; continue;//return -2;//continue; } // record this status for ( i = 0; i < p->nDivs; i++ ) if ( sat_solver_var_value(p->pSat, i) ) Abc_TtSetBit( Sfm_DecDivPats(p, i, c), p->nPats[c] ); p->nPatWords[c] = 1 + (p->nPats[c] >> 6); Abc_TtSetBit( Masks[c], p->nPats[c]++ ); } if ( Impls[0] == -1 || Impls[1] == -1 ) continue; if ( Impls[0] == Impls[1] ) { Vec_IntPop( &p->vImpls[0] ); Vec_IntPop( &p->vImpls[1] ); continue; } assert( Abc_Lit2Var(Impls[0]) == Abc_Lit2Var(Impls[1]) ); // found buffer/inverter Abc_TtUnit( pTruth, Abc_TtWordNum(p->pPars->nVarMax), Abc_LitIsCompl(Impls[0]) ); pSupp[0] = Abc_Lit2Var(Impls[0]); if ( p->pPars->fVeryVerbose ) printf( "Found variable %s%d.\n", Abc_LitIsCompl(Impls[0]) ? "!":"", pSupp[0] ); return 1; } if ( nSuppAdd > p->pPars->nVarMax - 2 ) { if ( p->pPars->fVeryVerbose ) printf( "The number of assumption is more than MFFC size.\n" ); return -2; } // try using all implications at once if ( p->pPars->fUseAndOr ) for ( c = 0; c < 2; c++ ) { if ( Vec_IntSize(&p->vImpls[!c]) < 2 ) continue; p->nSatCalls++; pAssump[nAssump] = Abc_Var2Lit( p->iTarget, c ); assert( Vec_IntSize(&p->vImpls[!c]) < SFM_WIN_MAX-10 ); Vec_IntForEachEntry( &p->vImpls[!c], iLit, i ) pAssump[nAssump+1+i] = iLit; clk = Abc_Clock(); status = sat_solver_solve( p->pSat, pAssump, pAssump + nAssump+1+i, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) { p->nTimeOuts++; return -2; } if ( status == l_False ) { int * pFinal, nFinal = sat_solver_final( p->pSat, &pFinal ); p->nSatCallsUnsat++; p->timeSatUnsat += Abc_Clock() - clk; if ( nFinal + nSuppAdd > 6 ) continue; // collect only relevant literals for ( i = d = 0; i < nFinal; i++ ) if ( Vec_IntFind(&p->vImpls[!c], Abc_LitNot(pFinal[i])) >= 0 ) pSupp[d++] = Abc_LitNot(pFinal[i]); nFinal = d; // create AND/OR gate assert( nFinal <= 6 ); if ( c ) { *pTruth = ~(word)0; for ( i = 0; i < nFinal; i++ ) { *pTruth &= Abc_LitIsCompl(pSupp[i]) ? ~s_Truths6[i] : s_Truths6[i]; pSupp[i] = Abc_Lit2Var(pSupp[i]); } } else { *pTruth = 0; for ( i = 0; i < nFinal; i++ ) { *pTruth |= Abc_LitIsCompl(pSupp[i]) ? s_Truths6[i] : ~s_Truths6[i]; pSupp[i] = Abc_Lit2Var(pSupp[i]); } } Abc_TtStretch6( pTruth, nFinal, p->pPars->nVarMax ); p->nNodesAndOr++; if ( p->pPars->fVeryVerbose ) printf( "Found %d-input AND/OR gate.\n", nFinal ); return nFinal; } assert( status == l_True ); p->nSatCallsSat++; p->timeSatSat += Abc_Clock() - clk; if ( p->nPats[c] == 64*SFM_SIM_WORDS ) { p->nSatCallsOver++; continue;//return -2;//continue; } for ( i = 0; i < p->nDivs; i++ ) if ( sat_solver_var_value(p->pSat, i) ) Abc_TtSetBit( Sfm_DecDivPats(p, i, c), p->nPats[c] ); p->nPatWords[c] = 1 + (p->nPats[c] >> 6); Abc_TtSetBit( Masks[c], p->nPats[c]++ ); } // find the best cofactoring variable // if ( !fCofactor || Vec_IntSize(&p->vImpls[0]) + Vec_IntSize(&p->vImpls[1]) > 2 ) Var = Sfm_DecFindBestVar( p, Masks ); // if ( Var == -1 ) // Var = Sfm_DecFindBestVar2( p, Masks ); /* { int Lit0 = Vec_IntSize(&p->vImpls[0]) ? Vec_IntEntry(&p->vImpls[0], 0) : -1; int Lit1 = Vec_IntSize(&p->vImpls[1]) ? Vec_IntEntry(&p->vImpls[1], 0) : -1; if ( Lit0 == -1 && Lit1 >= 0 ) Var = Abc_Lit2Var(Lit1); else if ( Lit1 == -1 && Lit0 >= 0 ) Var = Abc_Lit2Var(Lit0); else if ( Lit0 >= 0 && Lit1 >= 0 ) { if ( Lit0 < Lit1 ) Var = Abc_Lit2Var(Lit0); else Var = Abc_Lit2Var(Lit1); } } */ if ( Var == -1 && fCofactor ) { //for ( Var = p->nDivs - 1; Var >= 0; Var-- ) Vec_IntForEachEntryReverse( &p->vObjInMffc, Var, i ) if ( Vec_IntFind(&p->vObjDec, Var) == -1 ) break; // if ( i == Vec_IntSize(&p->vObjInMffc) ) if ( i == -1 ) Var = -1; fCofactor = 0; } if ( p->pPars->fVeryVerbose ) { Sfm_DecPrint( p, Masks ); printf( "Best var %d\n", Var ); printf( "\n" ); } cofactor: // cofactor the problem if ( Var >= 0 ) { word uTruth[2][SFM_WORD_MAX], MasksNext[2][SFM_SIM_WORDS]; int w, Supp[2][2*SFM_SUPP_MAX], nSupp[2] = {0}; Vec_IntPush( &p->vObjDec, Var ); for ( i = 0; i < 2; i++ ) { for ( c = 0; c < 2; c++ ) { Abc_TtAndSharp( MasksNext[c], Masks[c], Sfm_DecDivPats(p, Var, c), p->nPatWords[c], !i ); for ( w = p->nPatWords[c]; w < SFM_SIM_WORDS; w++ ) MasksNext[c][w] = 0; } pAssump[nAssump] = Abc_Var2Lit( Var, !i ); memcpy( p->pDivWords[nAssump+1], p->pDivWords[nAssump], sizeof(word) * p->nDivWords ); nSupp[i] = Sfm_DecPeformDec_rec( p, uTruth[i], Supp[i], pAssump, nAssump+1, MasksNext, fCofactor, (i ? nSupp[0] : 0) + nSuppAdd + 1 ); if ( nSupp[i] == -2 ) return -2; } // combine solutions return Sfm_DecCombineDec( p, uTruth[0], uTruth[1], Supp[0], Supp[1], nSupp[0], nSupp[1], pTruth, pSupp, Var ); } return -2; } int Sfm_DecPeformDec2( Sfm_Dec_t * p, Abc_Obj_t * pObj ) { word uTruth[SFM_DEC_MAX][SFM_WORD_MAX], Masks[2][SFM_SIM_WORDS]; int pSupp[SFM_DEC_MAX][2*SFM_SUPP_MAX]; int nSupp[SFM_DEC_MAX], pAssump[SFM_WIN_MAX]; int fVeryVerbose = p->pPars->fPrintDecs || p->pPars->fVeryVerbose; int nDecs = Abc_MaxInt(p->pPars->nDecMax, 1); //int fNeedInv, AreaGainInv = Sfm_DecComputeFlipInvGain(p, pObj, &fNeedInv); int i, RetValue, Prev = 0, iBest = -1, AreaThis, AreaNew;//, AreaNewInv; int GainThis, GainBest = -1, iLibObj, iLibObjBest = -1; assert( p->pPars->fArea == 1 ); //printf( "AreaGainInv = %8.2f ", Scl_Int2Flt(AreaGainInv) ); //Sfm_DecPrint( p, NULL ); if ( fVeryVerbose ) printf( "\nNode %4d : MFFC %2d\n", p->iTarget, p->nMffc ); assert( p->pPars->nDecMax <= SFM_DEC_MAX ); Sfm_ObjSetupSimInfo( pObj ); Vec_IntClear( &p->vObjDec ); for ( i = 0; i < nDecs; i++ ) { // reduce the variable array if ( Vec_IntSize(&p->vObjDec) > Prev ) Vec_IntShrink( &p->vObjDec, Prev ); Prev = Vec_IntSize(&p->vObjDec) + 1; // perform decomposition Abc_TtMask( Masks[0], SFM_SIM_WORDS, p->nPats[0] ); Abc_TtMask( Masks[1], SFM_SIM_WORDS, p->nPats[1] ); nSupp[i] = Sfm_DecPeformDec_rec( p, uTruth[i], pSupp[i], pAssump, 0, Masks, 1, 0 ); if ( nSupp[i] == -2 ) { if ( fVeryVerbose ) printf( "Dec %d: Pat0 = %2d Pat1 = %2d NO DEC.\n", i, p->nPats[0], p->nPats[1] ); continue; } if ( fVeryVerbose ) printf( "Dec %d: Pat0 = %2d Pat1 = %2d Supp = %d ", i, p->nPats[0], p->nPats[1], nSupp[i] ); if ( fVeryVerbose ) Dau_DsdPrintFromTruth( uTruth[i], nSupp[i] ); if ( nSupp[i] < 2 ) { p->nSuppVars = nSupp[i]; Abc_TtCopy( p->Copy, uTruth[i], SFM_WORD_MAX, 0 ); RetValue = Sfm_LibImplementSimple( p->pLib, uTruth[i], pSupp[i], nSupp[i], &p->vObjGates, &p->vObjFanins ); assert( nSupp[i] <= p->pPars->nVarMax ); p->nLuckySizes[nSupp[i]]++; assert( RetValue <= 2 ); p->nLuckyGates[RetValue]++; //printf( "\n" ); return RetValue; } p->nSuppVars = nSupp[i]; Abc_TtCopy( p->Copy, uTruth[i], SFM_WORD_MAX, 0 ); AreaNew = Sfm_LibFindAreaMatch( p->pLib, uTruth[i], nSupp[i], &iLibObj ); /* uTruth[i][0] = ~uTruth[i][0]; AreaNewInv = Sfm_LibFindAreaMatch( p->pLib, uTruth[i], nSupp[i], NULL ); uTruth[i][0] = ~uTruth[i][0]; if ( AreaNew > 0 && AreaNewInv > 0 && AreaNew - AreaNewInv + AreaGainInv > 0 ) printf( "AreaNew = %8.2f AreaNewInv = %8.2f Gain = %8.2f Total = %8.2f\n", Scl_Int2Flt(AreaNew), Scl_Int2Flt(AreaNewInv), Scl_Int2Flt(AreaNew - AreaNewInv), Scl_Int2Flt(AreaNew - AreaNewInv + AreaGainInv) ); else printf( "\n" ); */ if ( AreaNew == -1 ) continue; // compute area savings Sfm_DecPrepareVec( &p->vObjMap, pSupp[i], nSupp[i], &p->vGateCut ); AreaThis = Sfm_DecMffcAreaReal(pObj, &p->vGateCut, NULL); assert( p->AreaMffc <= AreaThis ); if ( p->pPars->fZeroCost ? (AreaNew > AreaThis) : (AreaNew >= AreaThis) ) continue; // find the best gain GainThis = AreaThis - AreaNew; assert( GainThis >= 0 ); if ( GainBest < GainThis ) { GainBest = GainThis; iLibObjBest = iLibObj; iBest = i; } } Sfm_ObjSetdownSimInfo( pObj ); if ( iBest == -1 ) { if ( fVeryVerbose ) printf( "Best : NO DEC.\n" ); p->nNoDecs++; //printf( "\n" ); return -2; } if ( fVeryVerbose ) printf( "Best %d: %d ", iBest, nSupp[iBest] ); if ( fVeryVerbose ) Dau_DsdPrintFromTruth( uTruth[iBest], nSupp[iBest] ); // implement assert( iLibObjBest >= 0 ); RetValue = Sfm_LibImplementGatesArea( p->pLib, pSupp[iBest], nSupp[iBest], iLibObjBest, &p->vObjGates, &p->vObjFanins ); assert( nSupp[iBest] <= p->pPars->nVarMax ); p->nLuckySizes[nSupp[iBest]]++; assert( RetValue <= 2 ); p->nLuckyGates[RetValue]++; return 1; } int Sfm_DecPeformDec3( Sfm_Dec_t * p, Abc_Obj_t * pObj ) { word uTruth[SFM_DEC_MAX][SFM_WORD_MAX], Masks[2][SFM_SIM_WORDS]; int pSupp[SFM_DEC_MAX][2*SFM_SUPP_MAX]; int nSupp[SFM_DEC_MAX], pAssump[SFM_WIN_MAX]; int fVeryVerbose = p->pPars->fPrintDecs || p->pPars->fVeryVerbose; int nDecs = Abc_MaxInt(p->pPars->nDecMax, 1); int i, k, DelayOrig = 0, DelayMin, GainMax, AreaMffc, nMatches, iBest = -1, RetValue, Prev = 0; Mio_Gate_t * pGate1Best = NULL, * pGate2Best = NULL; char * pFans1Best = NULL, * pFans2Best = NULL; assert( p->pPars->fArea == 0 ); p->DelayMin = 0; //Sfm_DecPrint( p, NULL ); if ( fVeryVerbose ) printf( "\nNode %4d : MFFC %2d\n", p->iTarget, p->nMffc ); // set limit on search for decompositions in delay-model assert( p->pPars->nDecMax <= SFM_DEC_MAX ); Sfm_ObjSetupSimInfo( pObj ); Vec_IntClear( &p->vObjDec ); for ( i = 0; i < nDecs; i++ ) { GainMax = 0; DelayMin = DelayOrig = Sfm_ManReadObjDelay( p, Abc_ObjId(pObj) ); // reduce the variable array if ( Vec_IntSize(&p->vObjDec) > Prev ) Vec_IntShrink( &p->vObjDec, Prev ); Prev = Vec_IntSize(&p->vObjDec) + 1; // perform decomposition Abc_TtMask( Masks[0], SFM_SIM_WORDS, p->nPats[0] ); Abc_TtMask( Masks[1], SFM_SIM_WORDS, p->nPats[1] ); nSupp[i] = Sfm_DecPeformDec_rec( p, uTruth[i], pSupp[i], pAssump, 0, Masks, 1, 0 ); if ( nSupp[i] == -2 ) { if ( fVeryVerbose ) printf( "Dec %d: Pat0 = %2d Pat1 = %2d NO DEC.\n", i, p->nPats[0], p->nPats[1] ); continue; } if ( fVeryVerbose ) printf( "Dec %d: Pat0 = %2d Pat1 = %2d Supp = %d ", i, p->nPats[0], p->nPats[1], nSupp[i] ); if ( fVeryVerbose ) Dau_DsdPrintFromTruth( uTruth[i], nSupp[i] ); if ( p->pTim && nSupp[i] == 1 && uTruth[i][0] == ABC_CONST(0x5555555555555555) && DelayMin <= p->DelayInv + Sfm_ManReadObjDelay(p, Vec_IntEntry(&p->vObjMap, pSupp[i][0])) ) { if ( fVeryVerbose ) printf( "Dec %d: Pat0 = %2d Pat1 = %2d NO DEC.\n", i, p->nPats[0], p->nPats[1] ); continue; } if ( p->pMit && nSupp[i] == 1 && uTruth[i][0] == ABC_CONST(0x5555555555555555) ) { if ( fVeryVerbose ) printf( "Dec %d: Pat0 = %2d Pat1 = %2d NO DEC.\n", i, p->nPats[0], p->nPats[1] ); continue; } if ( nSupp[i] < 2 ) { p->nSuppVars = nSupp[i]; Abc_TtCopy( p->Copy, uTruth[i], SFM_WORD_MAX, 0 ); RetValue = Sfm_LibImplementSimple( p->pLib, uTruth[i], pSupp[i], nSupp[i], &p->vObjGates, &p->vObjFanins ); assert( nSupp[i] <= p->pPars->nVarMax ); p->nLuckySizes[nSupp[i]]++; assert( RetValue <= 2 ); p->nLuckyGates[RetValue]++; return RetValue; } // get MFFC Sfm_DecPrepareVec( &p->vObjMap, pSupp[i], nSupp[i], &p->vGateCut ); // returns cut in p->vGateCut AreaMffc = Sfm_DecMffcAreaReal(pObj, &p->vGateCut, &p->vGateMffc ); // returns MFFC in p->vGateMffc // try the delay p->nSuppVars = nSupp[i]; Abc_TtCopy( p->Copy, uTruth[i], SFM_WORD_MAX, 0 ); nMatches = Sfm_LibFindDelayMatches( p->pLib, uTruth[i], pSupp[i], nSupp[i], &p->vMatchGates, &p->vMatchFans ); for ( k = 0; k < nMatches; k++ ) { abctime clk = Abc_Clock(); Mio_Gate_t * pGate1 = (Mio_Gate_t *)Vec_PtrEntry( &p->vMatchGates, 2*k+0 ); Mio_Gate_t * pGate2 = (Mio_Gate_t *)Vec_PtrEntry( &p->vMatchGates, 2*k+1 ); int AreaNew = Scl_Flt2Int( Mio_GateReadArea(pGate1) + (pGate2 ? Mio_GateReadArea(pGate2) : 0.0) ); char * pFans1 = (char *)Vec_PtrEntry( &p->vMatchFans, 2*k+0 ); char * pFans2 = (char *)Vec_PtrEntry( &p->vMatchFans, 2*k+1 ); Vec_Int_t vFanins = { nSupp[i], nSupp[i], pSupp[i] }; // skip identical gate //if ( pGate2 == NULL && pGate1 == (Mio_Gate_t *)pObj->pData ) // continue; if ( p->pMit ) { int Gain = Sfm_MitEvalRemapping( p->pMit, &p->vGateMffc, pObj, &vFanins, &p->vObjMap, pGate1, pFans1, pGate2, pFans2 ); if ( p->pPars->DelAreaRatio && AreaNew > AreaMffc && (Gain / (AreaNew - AreaMffc)) < p->pPars->DelAreaRatio ) continue; if ( GainMax < Gain ) { GainMax = Gain; pGate1Best = pGate1; pGate2Best = pGate2; pFans1Best = pFans1; pFans2Best = pFans2; iBest = i; } } else { int Delay = Sfm_TimEvalRemapping( p->pTim, &vFanins, &p->vObjMap, pGate1, pFans1, pGate2, pFans2 ); if ( p->pPars->DelAreaRatio && AreaNew > AreaMffc && (Delay / (AreaNew - AreaMffc)) < p->pPars->DelAreaRatio ) continue; if ( DelayMin > Delay ) { DelayMin = Delay; pGate1Best = pGate1; pGate2Best = pGate2; pFans1Best = pFans1; pFans2Best = pFans2; iBest = i; } } p->timeEval += Abc_Clock() - clk; } } //printf( "Gain max = %d.\n", GainMax ); Sfm_ObjSetdownSimInfo( pObj ); if ( iBest == -1 ) { if ( fVeryVerbose ) printf( "Best : NO DEC.\n" ); p->nNoDecs++; return -2; } if ( fVeryVerbose ) printf( "Best %d: %d ", iBest, nSupp[iBest] ); // if ( fVeryVerbose ) // Dau_DsdPrintFromTruth( uTruth[iBest], nSupp[iBest] ); RetValue = Sfm_LibImplementGatesDelay( p->pLib, pSupp[iBest], pGate1Best, pGate2Best, pFans1Best, pFans2Best, &p->vObjGates, &p->vObjFanins ); assert( nSupp[iBest] <= p->pPars->nVarMax ); p->nLuckySizes[nSupp[iBest]]++; assert( RetValue <= 2 ); p->nLuckyGates[RetValue]++; p->DelayMin = DelayMin; return 1; } /**Function************************************************************* Synopsis [Incremental level update.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkUpdateIncLevel_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, LevelNew = Abc_ObjLevelNew(pObj); if ( LevelNew == Abc_ObjLevel(pObj) && Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) > 0 ) return; pObj->Level = LevelNew; if ( !Abc_ObjIsCo(pObj) ) Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_NtkUpdateIncLevel_rec( pFanout ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDfsCheck_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPivot ) { Abc_Obj_t * pFanin; int i; if ( pObj == pPivot ) return 0; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return 1; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsCi(pObj) ) return 1; assert( Abc_ObjIsNode(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, i ) if ( !Abc_NtkDfsCheck_rec(pFanin, pPivot) ) return 0; return 1; } void Abc_NtkDfsReverseOne_rec( Abc_Obj_t * pObj, Vec_Int_t * vTfo, int nLevelMax, int nFanoutMax ) { Abc_Obj_t * pFanout; int i; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsCo(pObj) || Abc_ObjLevel(pObj) > nLevelMax ) return; assert( Abc_ObjIsNode( pObj ) ); if ( Abc_ObjFanoutNum(pObj) <= nFanoutMax ) { Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_ObjIsCo(pFanout) || Abc_ObjLevel(pFanout) > nLevelMax ) break; if ( i == Abc_ObjFanoutNum(pObj) ) Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_NtkDfsReverseOne_rec( pFanout, vTfo, nLevelMax, nFanoutMax ); } Vec_IntPush( vTfo, Abc_ObjId(pObj) ); pObj->iTemp = 0; } int Abc_NtkDfsOne_rec( Abc_Obj_t * pObj, Vec_Int_t * vTfi, int nLevelMin, int CiLabel ) { Abc_Obj_t * pFanin; int i; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return pObj->iTemp; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsCi(pObj) || (Abc_ObjLevel(pObj) < nLevelMin && Abc_ObjFaninNum(pObj) > 0) ) { Vec_IntPush( vTfi, Abc_ObjId(pObj) ); return (pObj->iTemp = CiLabel); } assert( Abc_ObjIsNode(pObj) ); pObj->iTemp = Abc_ObjFaninNum(pObj) ? 0 : CiLabel; Abc_ObjForEachFanin( pObj, pFanin, i ) pObj->iTemp |= Abc_NtkDfsOne_rec( pFanin, vTfi, nLevelMin, CiLabel ); Vec_IntPush( vTfi, Abc_ObjId(pObj) ); Sfm_ObjSimulateNode( pObj ); return pObj->iTemp; } void Sfm_DecAddNode( Abc_Obj_t * pObj, Vec_Int_t * vMap, Vec_Int_t * vGates, int fSkip, int fVeryVerbose ) { if ( fVeryVerbose ) printf( "%d:%d(%d) ", Vec_IntSize(vMap), Abc_ObjId(pObj), pObj->iTemp ); if ( fVeryVerbose ) Abc_ObjPrint( stdout, pObj ); Vec_IntPush( vMap, Abc_ObjId(pObj) ); Vec_IntPush( vGates, fSkip ? -1 : Mio_GateReadValue((Mio_Gate_t *)pObj->pData) ); } static inline int Sfm_DecNodeIsMffc( Abc_Obj_t * p, int nLevelMin ) { return Abc_ObjIsNode(p) && Abc_ObjFanoutNum(p) == 1 && Abc_NodeIsTravIdCurrent(p) && (Abc_ObjLevel(p) >= nLevelMin || Abc_ObjFaninNum(p) == 0); } static inline int Sfm_DecNodeIsMffcInput( Abc_Obj_t * p, int nLevelMin, Sfm_Tim_t * pTim, Abc_Obj_t * pPivot ) { return Abc_NodeIsTravIdCurrent(p) && Sfm_TimNodeIsNonCritical(pTim, pPivot, p); } static inline int Sfm_DecNodeIsMffcInput2( Abc_Obj_t * p, int nLevelMin, Sfm_Mit_t * pMit, Abc_Obj_t * pPivot ) { return Abc_NodeIsTravIdCurrent(p) && Sfm_MitNodeIsNonCritical(pMit, pPivot, p); } void Sfm_DecMarkMffc( Abc_Obj_t * pPivot, int nLevelMin, int nMffcMax, int fVeryVerbose, Vec_Int_t * vMffc, Vec_Int_t * vInMffc, Sfm_Tim_t * pTim, Sfm_Mit_t * pMit ) { Abc_Obj_t * pFanin, * pFanin2, * pFanin3, * pObj; int i, k, n; assert( nMffcMax > 0 ); Vec_IntFill( vMffc, 1, Abc_ObjId(pPivot) ); if ( pMit != NULL ) { pPivot->iTemp |= SFM_MASK_MFFC; pPivot->iTemp |= SFM_MASK_PIVOT; // collect MFFC inputs (these are low-delay nodes close to the pivot) Vec_IntClear(vInMffc); Abc_ObjForEachFanin( pPivot, pFanin, i ) if ( Sfm_DecNodeIsMffcInput2(pFanin, nLevelMin, pMit, pPivot) ) Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin) ); Abc_ObjForEachFanin( pPivot, pFanin, i ) Abc_ObjForEachFanin( pFanin, pFanin2, k ) if ( Sfm_DecNodeIsMffcInput2(pFanin2, nLevelMin, pMit, pPivot) ) Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin2) ); Abc_ObjForEachFanin( pPivot, pFanin, i ) Abc_ObjForEachFanin( pFanin, pFanin2, k ) Abc_ObjForEachFanin( pFanin2, pFanin3, n ) if ( Sfm_DecNodeIsMffcInput2(pFanin3, nLevelMin, pMit, pPivot) ) Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin3) ); } else if ( pTim != NULL ) { pPivot->iTemp |= SFM_MASK_MFFC; pPivot->iTemp |= SFM_MASK_PIVOT; // collect MFFC inputs (these are low-delay nodes close to the pivot) Vec_IntClear(vInMffc); Abc_ObjForEachFanin( pPivot, pFanin, i ) if ( Sfm_DecNodeIsMffcInput(pFanin, nLevelMin, pTim, pPivot) ) Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin) ); Abc_ObjForEachFanin( pPivot, pFanin, i ) Abc_ObjForEachFanin( pFanin, pFanin2, k ) if ( Sfm_DecNodeIsMffcInput(pFanin2, nLevelMin, pTim, pPivot) ) Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin2) ); Abc_ObjForEachFanin( pPivot, pFanin, i ) Abc_ObjForEachFanin( pFanin, pFanin2, k ) Abc_ObjForEachFanin( pFanin2, pFanin3, n ) if ( Sfm_DecNodeIsMffcInput(pFanin3, nLevelMin, pTim, pPivot) ) Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin3) ); /* printf( "Node %d: (%.2f) ", pPivot->Id, Scl_Int2Flt(Sfm_ManReadObjDelay(p, Abc_ObjId(pPivot))) ); Abc_ObjForEachFanin( pPivot, pFanin, i ) printf( "%d: %.2f ", Abc_ObjLevel(pFanin), Scl_Int2Flt(Sfm_ManReadObjDelay(p, Abc_ObjId(pFanin))) ); printf( "\n" ); printf( "Node %d: ", pPivot->Id ); Abc_NtkForEachObjVec( vInMffc, pPivot->pNtk, pObj, i ) printf( "%d: %.2f ", Abc_ObjLevel(pObj), Scl_Int2Flt(Sfm_ManReadObjDelay(p, Abc_ObjId(pObj))) ); printf( "\n" ); */ } else { // collect MFFC Abc_ObjForEachFanin( pPivot, pFanin, i ) if ( Sfm_DecNodeIsMffc(pFanin, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax ) Vec_IntPushUnique( vMffc, Abc_ObjId(pFanin) ); Abc_ObjForEachFanin( pPivot, pFanin, i ) if ( Sfm_DecNodeIsMffc(pFanin, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax ) Abc_ObjForEachFanin( pFanin, pFanin2, k ) if ( Sfm_DecNodeIsMffc(pFanin2, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax ) Vec_IntPushUnique( vMffc, Abc_ObjId(pFanin2) ); Abc_ObjForEachFanin( pPivot, pFanin, i ) if ( Sfm_DecNodeIsMffc(pFanin, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax ) Abc_ObjForEachFanin( pFanin, pFanin2, k ) if ( Sfm_DecNodeIsMffc(pFanin2, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax ) Abc_ObjForEachFanin( pFanin2, pFanin3, n ) if ( Sfm_DecNodeIsMffc(pFanin3, nLevelMin) && Vec_IntSize(vMffc) < nMffcMax ) Vec_IntPushUnique( vMffc, Abc_ObjId(pFanin3) ); // mark MFFC assert( Vec_IntSize(vMffc) <= nMffcMax ); Abc_NtkForEachObjVec( vMffc, pPivot->pNtk, pObj, i ) pObj->iTemp |= SFM_MASK_MFFC; pPivot->iTemp |= SFM_MASK_PIVOT; // collect MFFC inputs Vec_IntClear(vInMffc); Abc_NtkForEachObjVec( vMffc, pPivot->pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( Abc_NodeIsTravIdCurrent(pFanin) && pFanin->iTemp == SFM_MASK_PI ) Vec_IntPushUnique( vInMffc, Abc_ObjId(pFanin) ); // printf( "Node %d: ", pPivot->Id ); // Abc_ObjForEachFanin( pPivot, pFanin, i ) // printf( "%d ", Abc_ObjFanoutNum(pFanin) ); // printf( "\n" ); // Abc_NtkForEachObjVec( vInMffc, pPivot->pNtk, pObj, i ) // printf( "%d ", Abc_ObjFanoutNum(pObj) ); // printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_DecExtract( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars, Abc_Obj_t * pPivot, Vec_Int_t * vRoots, Vec_Int_t * vGates, Vec_Wec_t * vFanins, Vec_Int_t * vMap, Vec_Int_t * vTfi, Vec_Int_t * vTfo, Vec_Int_t * vMffc, Vec_Int_t * vInMffc, Sfm_Tim_t * pTim, Sfm_Mit_t * pMit ) { int fVeryVerbose = 0;//pPars->fVeryVerbose; Vec_Int_t * vLevel; Abc_Obj_t * pObj, * pFanin; int nLevelMax = pPivot->Level + pPars->nTfoLevMax; int nLevelMin = pPivot->Level - pPars->nTfiLevMax; int i, k, nTfiSize, nDivs = -1; assert( Abc_ObjIsNode(pPivot) ); if ( fVeryVerbose ) printf( "\n\nTarget %d\n", Abc_ObjId(pPivot) ); // collect TFO nodes Vec_IntClear( vTfo ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkDfsReverseOne_rec( pPivot, vTfo, nLevelMax, pPars->nFanoutMax ); // count internal fanouts Abc_NtkForEachObjVec( vTfo, pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) pFanin->iTemp++; // compute roots Vec_IntClear( vRoots ); Abc_NtkForEachObjVec( vTfo, pNtk, pObj, i ) if ( pObj->iTemp != Abc_ObjFanoutNum(pObj) ) Vec_IntPush( vRoots, Abc_ObjId(pObj) ); assert( Vec_IntSize(vRoots) > 0 ); // collect TFI and mark nodes Vec_IntClear( vTfi ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkDfsOne_rec( pPivot, vTfi, nLevelMin, SFM_MASK_PI ); nTfiSize = Vec_IntSize(vTfi); Sfm_ObjFlipNode( pPivot ); // additinally mark MFFC Sfm_DecMarkMffc( pPivot, nLevelMin, pPars->nMffcMax, fVeryVerbose, vMffc, vInMffc, pTim, pMit ); assert( Vec_IntSize(vMffc) <= pPars->nMffcMax ); if ( fVeryVerbose ) printf( "Mffc size = %d. Mffc area = %.2f. InMffc size = %d.\n", Vec_IntSize(vMffc), Scl_Int2Flt(Sfm_DecMffcArea(pNtk, vMffc)), Vec_IntSize(vInMffc) ); // collect TFI(TFO) Abc_NtkForEachObjVec( vRoots, pNtk, pObj, i ) Abc_NtkDfsOne_rec( pObj, vTfi, nLevelMin, SFM_MASK_INPUT ); // mark input-only nodes pointed to by mixed nodes Abc_NtkForEachObjVecStart( vTfi, pNtk, pObj, i, nTfiSize ) if ( pObj->iTemp != SFM_MASK_INPUT ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( pFanin->iTemp == SFM_MASK_INPUT ) pFanin->iTemp = SFM_MASK_FANIN; // collect nodes supported only on TFI fanins and not MFFC if ( fVeryVerbose ) printf( "\nDivs:\n" ); Vec_IntClear( vMap ); Vec_IntClear( vGates ); Abc_NtkForEachObjVec( vTfi, pNtk, pObj, i ) if ( pObj->iTemp == SFM_MASK_PI ) Sfm_DecAddNode( pObj, vMap, vGates, Abc_ObjIsCi(pObj) || (Abc_ObjLevel(pObj) < nLevelMin && Abc_ObjFaninNum(pObj) > 0), fVeryVerbose ); nDivs = Vec_IntSize(vMap); // add other nodes that are not in TFO and not in MFFC if ( fVeryVerbose ) printf( "\nSides:\n" ); Abc_NtkForEachObjVec( vTfi, pNtk, pObj, i ) if ( pObj->iTemp == (SFM_MASK_PI | SFM_MASK_INPUT) || pObj->iTemp == SFM_MASK_FANIN ) Sfm_DecAddNode( pObj, vMap, vGates, pObj->iTemp == SFM_MASK_FANIN, fVeryVerbose ); // reorder nodes acording to delay if ( pMit ) { int nDivsNew, nOldSize = Vec_IntSize(vMap); Vec_IntClear( vTfo ); Vec_IntAppend( vTfo, vMap ); nDivsNew = Sfm_MitSortArrayByArrival( pMit, vTfo, Abc_ObjId(pPivot) ); // collect again Vec_IntClear( vMap ); Vec_IntClear( vGates ); Abc_NtkForEachObjVec( vTfo, pNtk, pObj, i ) Sfm_DecAddNode( pObj, vMap, vGates, Abc_ObjIsCi(pObj) || (Abc_ObjLevel(pObj) < nLevelMin && Abc_ObjFaninNum(pObj) > 0) || pObj->iTemp == SFM_MASK_FANIN, 0 ); assert( nOldSize == Vec_IntSize(vMap) ); // update divisor count nDivs = nDivsNew; } else if ( pTim ) { int nDivsNew, nOldSize = Vec_IntSize(vMap); Vec_IntClear( vTfo ); Vec_IntAppend( vTfo, vMap ); nDivsNew = Sfm_TimSortArrayByArrival( pTim, vTfo, Abc_ObjId(pPivot) ); // collect again Vec_IntClear( vMap ); Vec_IntClear( vGates ); Abc_NtkForEachObjVec( vTfo, pNtk, pObj, i ) Sfm_DecAddNode( pObj, vMap, vGates, Abc_ObjIsCi(pObj) || (Abc_ObjLevel(pObj) < nLevelMin && Abc_ObjFaninNum(pObj) > 0) || pObj->iTemp == SFM_MASK_FANIN, 0 ); assert( nOldSize == Vec_IntSize(vMap) ); // update divisor count nDivs = nDivsNew; } // add the TFO nodes if ( fVeryVerbose ) printf( "\nTFO:\n" ); Abc_NtkForEachObjVec( vTfi, pNtk, pObj, i ) if ( pObj->iTemp >= SFM_MASK_MFFC ) Sfm_DecAddNode( pObj, vMap, vGates, 0, fVeryVerbose ); assert( Vec_IntSize(vMap) == Vec_IntSize(vGates) ); if ( fVeryVerbose ) printf( "\n" ); // create node IDs Vec_WecClear( vFanins ); Abc_NtkForEachObjVec( vMap, pNtk, pObj, i ) { pObj->iTemp = i; vLevel = Vec_WecPushLevel( vFanins ); if ( Vec_IntEntry(vGates, i) >= 0 ) Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vLevel, pFanin->iTemp ); } // compute care set Sfm_DecMan(pPivot)->uCareSet = Sfm_ObjFindCareSet(pPivot->pNtk, vRoots); //printf( "care = %5d : ", Abc_ObjId(pPivot) ); //Extra_PrintBinary( stdout, (unsigned *)&Sfm_DecMan(pPivot)->uCareSet, 64 ); //printf( "\n" ); // remap roots Abc_NtkForEachObjVec( vRoots, pNtk, pObj, i ) Vec_IntWriteEntry( vRoots, i, pObj->iTemp ); // remap inputs to MFFC Abc_NtkForEachObjVec( vInMffc, pNtk, pObj, i ) Vec_IntWriteEntry( vInMffc, i, pObj->iTemp ); /* // check Abc_NtkForEachObjVec( vMap, pNtk, pObj, i ) { if ( i == nDivs ) break; Abc_NtkIncrementTravId( pNtk ); assert( Abc_NtkDfsCheck_rec(pObj, pPivot) ); } */ return nDivs; } Abc_Obj_t * Sfm_DecInsert( Abc_Ntk_t * pNtk, Abc_Obj_t * pPivot, int Limit, Vec_Int_t * vGates, Vec_Wec_t * vFanins, Vec_Int_t * vMap, Vec_Ptr_t * vGateHandles, int GateBuf, int GateInv, Vec_Wrd_t * vFuncs, Vec_Int_t * vNewNodes, Sfm_Mit_t * pMit ) { Abc_Obj_t * pObjNew = NULL; Vec_Int_t * vLevel; int i, k, iObj, Gate; if ( vNewNodes ) Vec_IntClear( vNewNodes ); // assuming that new gates are appended at the end assert( Limit < Vec_IntSize(vGates) ); assert( Limit == Vec_IntSize(vMap) ); if ( Limit + 1 == Vec_IntSize(vGates) ) { Gate = Vec_IntEntryLast(vGates); if ( Gate == GateBuf ) { iObj = Vec_WecEntryEntry( vFanins, Limit, 0 ); pObjNew = Abc_NtkObj( pNtk, Vec_IntEntry(vMap, iObj) ); // transfer load if ( pMit ) Sfm_MitTransferLoad( pMit, pObjNew, pPivot ); // replace logic cone Abc_ObjReplace( pPivot, pObjNew ); // update level pObjNew->Level = 0; Abc_NtkUpdateIncLevel_rec( pObjNew ); if ( vNewNodes ) Vec_IntPush( vNewNodes, Abc_ObjId(pObjNew) ); return pObjNew; } else if ( vNewNodes == NULL && Gate == GateInv ) { // check if fanouts can be updated Abc_Obj_t * pFanout; Abc_ObjForEachFanout( pPivot, pFanout, i ) if ( !Abc_ObjIsNode(pFanout) || Sfm_LibFindComplInputGate(vFuncs, Mio_GateReadValue((Mio_Gate_t*)pFanout->pData), Abc_ObjFaninNum(pFanout), Abc_NodeFindFanin(pFanout, pPivot), NULL) == -1 ) break; // update fanouts if ( i == Abc_ObjFanoutNum(pPivot) ) { Abc_ObjForEachFanout( pPivot, pFanout, i ) { int iFanin = Abc_NodeFindFanin(pFanout, pPivot), iFaninNew = -1; int iGate = Mio_GateReadValue((Mio_Gate_t*)pFanout->pData); int iGateNew = Sfm_LibFindComplInputGate( vFuncs, iGate, Abc_ObjFaninNum(pFanout), iFanin, &iFaninNew ); assert( iGateNew >= 0 && iGateNew != iGate && iFaninNew >= 0 ); pFanout->pData = Vec_PtrEntry( vGateHandles, iGateNew ); //assert( iFanin == iFaninNew ); // swap fanins if ( iFanin != iFaninNew ) { int * pArray = Vec_IntArray( &pFanout->vFanins ); ABC_SWAP( int, pArray[iFanin], pArray[iFaninNew] ); } } iObj = Vec_WecEntryEntry( vFanins, Limit, 0 ); pObjNew = Abc_NtkObj( pNtk, Vec_IntEntry(vMap, iObj) ); Abc_ObjReplace( pPivot, pObjNew ); // update level pObjNew->Level = 0; Abc_NtkUpdateIncLevel_rec( pObjNew ); return pObjNew; } } } // introduce new gates Vec_IntForEachEntryStart( vGates, Gate, i, Limit ) { vLevel = Vec_WecEntry( vFanins, i ); pObjNew = Abc_NtkCreateNode( pNtk ); Vec_IntForEachEntry( vLevel, iObj, k ) Abc_ObjAddFanin( pObjNew, Abc_NtkObj(pNtk, Vec_IntEntry(vMap, iObj)) ); pObjNew->pData = Vec_PtrEntry( vGateHandles, Gate ); assert( Abc_ObjFaninNum(pObjNew) == Mio_GateReadPinNum((Mio_Gate_t *)pObjNew->pData) ); Vec_IntPush( vMap, Abc_ObjId(pObjNew) ); if ( vNewNodes ) Vec_IntPush( vNewNodes, Abc_ObjId(pObjNew) ); } // transfer load if ( pMit ) { Sfm_MitTimingGrow( pMit ); Sfm_MitTransferLoad( pMit, pObjNew, pPivot ); } // replace logic cone Abc_ObjReplace( pPivot, pObjNew ); // update level Abc_NtkForEachObjVecStart( vMap, pNtk, pObjNew, i, Limit ) Abc_NtkUpdateIncLevel_rec( pObjNew ); return pObjNew; } void Sfm_DecPrintStats( Sfm_Dec_t * p ) { int i; printf( "Node = %d. Try = %d. Change = %d. Const0 = %d. Const1 = %d. Buf = %d. Inv = %d. Gate = %d. AndOr = %d. Effort = %d. NoDec = %d.\n", p->nTotalNodesBeg, p->nNodesTried, p->nNodesChanged, p->nNodesConst0, p->nNodesConst1, p->nNodesBuf, p->nNodesInv, p->nNodesResyn, p->nNodesAndOr, p->nEfforts, p->nNoDecs ); printf( "MaxDiv = %d. MaxWin = %d. AveDiv = %d. AveWin = %d. Calls = %d. (Sat = %d. Unsat = %d.) Over = %d. T/O = %d.\n", p->nMaxDivs, p->nMaxWin, (int)(p->nAllDivs/Abc_MaxInt(1, p->nNodesTried)), (int)(p->nAllWin/Abc_MaxInt(1, p->nNodesTried)), p->nSatCalls, p->nSatCallsSat, p->nSatCallsUnsat, p->nSatCallsOver, p->nTimeOuts ); p->timeTotal = Abc_Clock() - p->timeStart; p->timeOther = p->timeTotal - p->timeLib - p->timeWin - p->timeCnf - p->timeSat - p->timeTime; ABC_PRTP( "Lib ", p->timeLib , p->timeTotal ); ABC_PRTP( "Win ", p->timeWin , p->timeTotal ); ABC_PRTP( "Cnf ", p->timeCnf , p->timeTotal ); ABC_PRTP( "Sat ", p->timeSat-p->timeEval, p->timeTotal ); ABC_PRTP( " Sat ", p->timeSatSat, p->timeTotal ); ABC_PRTP( " Unsat", p->timeSatUnsat, p->timeTotal ); ABC_PRTP( "Eval ", p->timeEval , p->timeTotal ); ABC_PRTP( "Timing", p->timeTime , p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "ALL ", p->timeTotal, p->timeTotal ); printf( "Cone sizes: " ); for ( i = 0; i <= SFM_SUPP_MAX; i++ ) if ( p->nLuckySizes[i] ) printf( "%d=%d ", i, p->nLuckySizes[i] ); printf( " " ); printf( "Gate sizes: " ); for ( i = 0; i <= SFM_SUPP_MAX; i++ ) if ( p->nLuckyGates[i] ) printf( "%d=%d ", i, p->nLuckyGates[i] ); printf( "\n" ); printf( "Reduction: " ); printf( "Nodes %6d out of %6d (%6.2f %%) ", p->nTotalNodesBeg-p->nTotalNodesEnd, p->nTotalNodesBeg, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/Abc_MaxInt(1, p->nTotalNodesBeg) ); printf( "Edges %6d out of %6d (%6.2f %%) ", p->nTotalEdgesBeg-p->nTotalEdgesEnd, p->nTotalEdgesBeg, 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/Abc_MaxInt(1, p->nTotalEdgesBeg) ); printf( "\n" ); } void Abc_NtkCountStats( Sfm_Dec_t * p, int Limit ) { int Gate, nGates = Vec_IntSize(&p->vObjGates); if ( nGates == Limit ) return; Gate = Vec_IntEntryLast(&p->vObjGates); if ( nGates > Limit + 1 ) p->nNodesResyn++; else if ( Gate == p->GateConst0 ) p->nNodesConst0++; else if ( Gate == p->GateConst1 ) p->nNodesConst1++; else if ( Gate == p->GateBuffer ) p->nNodesBuf++; else if ( Gate == p->GateInvert ) p->nNodesInv++; else p->nNodesResyn++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkAreaOptOne( Sfm_Dec_t * p, int i ) { abctime clk; Abc_Ntk_t * pNtk = p->pNtk; Sfm_Par_t * pPars = p->pPars; Abc_Obj_t * pObj = Abc_NtkObj( p->pNtk, i ); int Limit, RetValue; if ( pPars->nMffcMin > 1 && Abc_NodeMffcLabel(pObj) < pPars->nMffcMin ) return NULL; if ( pPars->iNodeOne && i != pPars->iNodeOne ) return NULL; if ( pPars->iNodeOne ) pPars->fVeryVerbose = (int)(i == pPars->iNodeOne); p->nNodesTried++; clk = Abc_Clock(); p->nDivs = Sfm_DecExtract( pNtk, pPars, pObj, &p->vObjRoots, &p->vObjGates, &p->vObjFanins, &p->vObjMap, &p->vGateTfi, &p->vGateTfo, &p->vObjMffc, &p->vObjInMffc, NULL, NULL ); p->timeWin += Abc_Clock() - clk; if ( pPars->nWinSizeMax && pPars->nWinSizeMax < Vec_IntSize(&p->vObjGates) ) return NULL; p->nMffc = Vec_IntSize(&p->vObjMffc); p->AreaMffc = Sfm_DecMffcArea(pNtk, &p->vObjMffc); p->nMaxDivs = Abc_MaxInt( p->nMaxDivs, p->nDivs ); p->nAllDivs += p->nDivs; p->iTarget = pObj->iTemp; Limit = Vec_IntSize( &p->vObjGates ); p->nMaxWin = Abc_MaxInt( p->nMaxWin, Limit ); p->nAllWin += Limit; clk = Abc_Clock(); RetValue = Sfm_DecPrepareSolver( p ); p->timeCnf += Abc_Clock() - clk; if ( !RetValue ) return NULL; clk = Abc_Clock(); RetValue = Sfm_DecPeformDec2( p, pObj ); if ( pPars->fMoreEffort && RetValue < 0 ) { int Var, i; Vec_IntForEachEntryReverse( &p->vObjInMffc, Var, i ) { p->iUseThis = Var; RetValue = Sfm_DecPeformDec2( p, pObj ); p->iUseThis = -1; if ( RetValue < 0 ) { //printf( "Node %d: Not found among %d.\n", Abc_ObjId(pObj), Vec_IntSize(&p->vObjInMffc) ); } else { p->nEfforts++; if ( p->pPars->fVerbose ) { //printf( "Node %5d: (%2d out of %2d) Gate=%s ", Abc_ObjId(pObj), i, Vec_IntSize(&p->vObjInMffc), Mio_GateReadName((Mio_Gate_t*)pObj->pData) ); //Dau_DsdPrintFromTruth( p->Copy, p->nSuppVars ); } break; } } } if ( p->pPars->fVeryVerbose ) printf( "\n\n" ); p->timeSat += Abc_Clock() - clk; if ( RetValue < 0 ) return NULL; p->nNodesChanged++; Abc_NtkCountStats( p, Limit ); return Sfm_DecInsert( pNtk, pObj, Limit, &p->vObjGates, &p->vObjFanins, &p->vObjMap, &p->vGateHands, p->GateBuffer, p->GateInvert, &p->vGateFuncs, NULL, p->pMit ); } void Abc_NtkAreaOpt( Sfm_Dec_t * p ) { Abc_Obj_t * pObj; int i, nStop = Abc_NtkObjNumMax(p->pNtk); Abc_NtkForEachNode( p->pNtk, pObj, i ) { if ( i >= nStop || (p->pPars->nNodesMax && i > p->pPars->nNodesMax) ) break; Abc_NtkAreaOptOne( p, i ); } } void Abc_NtkAreaOpt2( Sfm_Dec_t * p ) { Abc_Obj_t * pObj, * pObjNew, * pFanin; int i, k, nStop = Abc_NtkObjNumMax(p->pNtk); Vec_Ptr_t * vFront = Vec_PtrAlloc( 1000 ); Abc_NtkForEachObj( p->pNtk, pObj, i ) assert( pObj->fMarkB == 0 ); // start the queue of nodes to be tried Abc_NtkForEachCo( p->pNtk, pObj, i ) if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) && !Abc_ObjFanin0(pObj)->fMarkB ) { Abc_ObjFanin0(pObj)->fMarkB = 1; Vec_PtrPush( vFront, Abc_ObjFanin0(pObj) ); } // process nodes in this order Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pObj, i ) { if ( Abc_ObjIsNone(pObj) ) continue; pObjNew = Abc_NtkAreaOptOne( p, Abc_ObjId(pObj) ); if ( pObjNew != NULL ) { if ( !Abc_ObjIsNode(pObjNew) || Abc_ObjFaninNum(pObjNew) == 0 || pObjNew->fMarkB ) continue; if ( (int)Abc_ObjId(pObjNew) < nStop ) { pObjNew->fMarkB = 1; Vec_PtrPush( vFront, pObjNew ); continue; } } else pObjNew = pObj; Abc_ObjForEachFanin( pObjNew, pFanin, k ) if ( Abc_ObjIsNode(pFanin) && Abc_ObjFaninNum(pObjNew) > 0 && !pFanin->fMarkB ) { pFanin->fMarkB = 1; Vec_PtrPush( vFront, pFanin ); } } Abc_NtkForEachObj( p->pNtk, pObj, i ) pObj->fMarkB = 0; Vec_PtrFree( vFront ); } void Abc_NtkDelayOpt( Sfm_Dec_t * p ) { Abc_Ntk_t * pNtk = p->pNtk; Sfm_Par_t * pPars = p->pPars; int n; Abc_NtkCleanMarkABC( pNtk ); for ( n = 0; pPars->nNodesMax == 0 || n < pPars->nNodesMax; n++ ) { Abc_Obj_t * pObj, * pObjNew; abctime clk; int i = 0, Limit, RetValue; // collect nodes if ( pPars->iNodeOne ) Vec_IntFill( &p->vCands, 1, pPars->iNodeOne ); else if ( p->pTim && !Sfm_TimPriorityNodes(p->pTim, &p->vCands, p->pPars->nTimeWin) ) break; else if ( p->pMit && !Sfm_MitPriorityNodes(p->pMit, &p->vCands, p->pPars->nTimeWin) ) break; // try improving delay for the nodes according to the priority Abc_NtkForEachObjVec( &p->vCands, p->pNtk, pObj, i ) { int OldId = Abc_ObjId(pObj); int DelayOld = Sfm_ManReadObjDelay(p, OldId); assert( pObj->fMarkA == 0 ); p->nNodesTried++; clk = Abc_Clock(); p->nDivs = Sfm_DecExtract( pNtk, pPars, pObj, &p->vObjRoots, &p->vObjGates, &p->vObjFanins, &p->vObjMap, &p->vGateTfi, &p->vGateTfo, &p->vObjMffc, &p->vObjInMffc, p->pTim, p->pMit ); p->timeWin += Abc_Clock() - clk; if ( p->nDivs < 2 || (pPars->nWinSizeMax && pPars->nWinSizeMax < Vec_IntSize(&p->vObjGates)) ) { pObj->fMarkA = 1; continue; } p->nMffc = Vec_IntSize(&p->vObjMffc); p->AreaMffc = Sfm_DecMffcArea(pNtk, &p->vObjMffc); p->nMaxDivs = Abc_MaxInt( p->nMaxDivs, p->nDivs ); p->nAllDivs += p->nDivs; p->iTarget = pObj->iTemp; Limit = Vec_IntSize( &p->vObjGates ); p->nMaxWin = Abc_MaxInt( p->nMaxWin, Limit ); p->nAllWin += Limit; clk = Abc_Clock(); RetValue = Sfm_DecPrepareSolver( p ); p->timeCnf += Abc_Clock() - clk; if ( !RetValue ) { pObj->fMarkA = 1; continue; } clk = Abc_Clock(); RetValue = Sfm_DecPeformDec3( p, pObj ); if ( pPars->fMoreEffort && RetValue < 0 ) { int Var, i; Vec_IntForEachEntryReverse( &p->vObjInMffc, Var, i ) { p->iUseThis = Var; RetValue = Sfm_DecPeformDec3( p, pObj ); p->iUseThis = -1; if ( RetValue < 0 ) { //printf( "Node %d: Not found among %d.\n", Abc_ObjId(pObj), Vec_IntSize(&p->vObjInMffc) ); } else { p->nEfforts++; if ( p->pPars->fVerbose ) { //printf( "Node %5d: (%2d out of %2d) Gate=%s ", Abc_ObjId(pObj), i, Vec_IntSize(&p->vObjInMffc), Mio_GateReadName((Mio_Gate_t*)pObj->pData) ); //Dau_DsdPrintFromTruth( p->Copy, p->nSuppVars ); } break; } } } if ( p->pPars->fVeryVerbose ) printf( "\n\n" ); p->timeSat += Abc_Clock() - clk; if ( RetValue < 0 ) { pObj->fMarkA = 1; continue; } assert( Vec_IntSize(&p->vObjGates) - Limit > 0 ); assert( Vec_IntSize(&p->vObjGates) - Limit <= 2 ); p->nNodesChanged++; Abc_NtkCountStats( p, Limit ); // reduce load due to removed MFFC if ( p->pMit ) Sfm_MitUpdateLoad( p->pMit, &p->vGateMffc, 0 ); // assuming &p->vGateMffc contains MFFC Sfm_DecInsert( pNtk, pObj, Limit, &p->vObjGates, &p->vObjFanins, &p->vObjMap, &p->vGateHands, p->GateBuffer, p->GateInvert, &p->vGateFuncs, &p->vNewNodes, p->pMit ); // increase load due to added new nodes if ( p->pMit ) Sfm_MitUpdateLoad( p->pMit, &p->vNewNodes, 1 ); // assuming &p->vNewNodes contains new nodes clk = Abc_Clock(); if ( p->pMit ) Sfm_MitUpdateTiming( p->pMit, &p->vNewNodes ); else Sfm_TimUpdateTiming( p->pTim, &p->vNewNodes ); p->timeTime += Abc_Clock() - clk; pObjNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk)-1 ); assert( p->pMit || p->DelayMin == 0 || p->DelayMin == Sfm_ManReadObjDelay(p, Abc_ObjId(pObjNew)) ); // report if ( pPars->fDelayVerbose ) printf( "Node %5d %5d : I =%3d. Cand = %5d (%6.2f %%) Old =%8.2f. New =%8.2f. Final =%8.2f. WNS =%8.2f.\n", OldId, Abc_NtkObjNumMax(p->pNtk), i, Vec_IntSize(&p->vCands), 100.0 * Vec_IntSize(&p->vCands) / Abc_NtkNodeNum(p->pNtk), Scl_Int2Flt(DelayOld), Scl_Int2Flt(Sfm_ManReadObjDelay(p, Abc_ObjId(pObjNew))), Scl_Int2Flt(Sfm_ManReadNtkDelay(p)), Scl_Int2Flt(Sfm_ManReadNtkMinSlack(p)) ); break; } if ( pPars->iNodeOne ) break; } Abc_NtkCleanMarkABC( pNtk ); } void Abc_NtkPerformMfs3( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ) { Sfm_Dec_t * p = Sfm_DecStart( pPars, (Mio_Library_t *)pNtk->pManFunc, pNtk ); if ( pPars->fVerbose ) { printf( "Remapping parameters: " ); if ( pPars->nTfoLevMax ) printf( "TFO = %d. ", pPars->nTfoLevMax ); if ( pPars->nTfiLevMax ) printf( "TFI = %d. ", pPars->nTfiLevMax ); if ( pPars->nFanoutMax ) printf( "FanMax = %d. ", pPars->nFanoutMax ); if ( pPars->nWinSizeMax ) printf( "WinMax = %d. ", pPars->nWinSizeMax ); if ( pPars->nBTLimit ) printf( "Confl = %d. ", pPars->nBTLimit ); if ( pPars->nMffcMin && pPars->fArea ) printf( "MffcMin = %d. ", pPars->nMffcMin ); if ( pPars->nMffcMax && pPars->fArea ) printf( "MffcMax = %d. ", pPars->nMffcMax ); if ( pPars->nDecMax ) printf( "DecMax = %d. ", pPars->nDecMax ); if ( pPars->iNodeOne ) printf( "Pivot = %d. ", pPars->iNodeOne ); if ( !pPars->fArea ) printf( "Win = %d. ", pPars->nTimeWin ); if ( !pPars->fArea ) printf( "Delta = %.2f ps. ", Scl_Int2Flt(p->DeltaCrit) ); if ( pPars->fArea ) printf( "0-cost = %s. ", pPars->fZeroCost ? "yes" : "no" ); printf( "Effort = %s. ", pPars->fMoreEffort ? "yes" : "no" ); printf( "Sim = %s. ", pPars->fUseSim ? "yes" : "no" ); printf( "\n" ); } // preparation steps Abc_NtkLevel( pNtk ); if ( p->pPars->fUseSim ) Sfm_NtkSimulate( pNtk ); // record statistics if ( pPars->fVerbose ) p->nTotalNodesBeg = Abc_NtkNodeNum(pNtk); if ( pPars->fVerbose ) p->nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk); // perform optimization if ( pPars->fArea ) { if ( pPars->fAreaRev ) Abc_NtkAreaOpt2( p ); else Abc_NtkAreaOpt( p ); } else Abc_NtkDelayOpt( p ); // record statistics if ( pPars->fVerbose ) p->nTotalNodesEnd = Abc_NtkNodeNum(pNtk); if ( pPars->fVerbose ) p->nTotalEdgesEnd = Abc_NtkGetTotalFanins(pNtk); // print stats and quit if ( pPars->fVerbose ) Sfm_DecPrintStats( p ); if ( pPars->fLibVerbose ) Sfm_LibPrint( p->pLib ); Sfm_DecStop( p ); if ( pPars->fArea ) { extern void Abc_NtkChangePerform( Abc_Ntk_t * pNtk, int fVerbose ); Abc_NtkChangePerform( pNtk, pPars->fVerbose ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmInt.h000066400000000000000000000353531300674244400230450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [rsbInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: rsbInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt_sfmInt__h #define ABC__opt_sfmInt__h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "sat/bsat/satSolver.h" #include "misc/util/utilNam.h" #include "map/scl/sclLib.h" #include "map/scl/sclCon.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "base/abc/abc.h" #include "sfm.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define SFM_FANIN_MAX 6 #define SFM_SAT_UNDEC 0x1234567812345678 #define SFM_SAT_SAT 0x8765432187654321 #define SFM_SUPP_MAX 8 #define SFM_WORD_MAX ((SFM_SUPP_MAX>6) ? (1<<(SFM_SUPP_MAX-6)) : 1) #define SFM_WIN_MAX 1000 #define SFM_DEC_MAX 4 #define SFM_SIM_WORDS 8 //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Sfm_Fun_t_ Sfm_Fun_t; typedef struct Sfm_Lib_t_ Sfm_Lib_t; typedef struct Sfm_Tim_t_ Sfm_Tim_t; typedef struct Sfm_Mit_t_ Sfm_Mit_t; struct Sfm_Ntk_t_ { // parameters Sfm_Par_t * pPars; // parameters // objects int nPis; // PI count (PIs should be first objects) int nPos; // PO count (POs should be last objects) int nNodes; // internal nodes int nObjs; // total objects int nLevelMax; // maximum level // user data Vec_Str_t * vFixed; // persistent objects Vec_Str_t * vEmpty; // transparent objects Vec_Wrd_t * vTruths; // truth tables Vec_Wec_t vFanins; // fanins // attributes Vec_Wec_t vFanouts; // fanouts Vec_Int_t vLevels; // logic level Vec_Int_t vLevelsR; // logic level Vec_Int_t vCounts; // fanin counters Vec_Int_t vId2Var; // ObjId -> SatVar Vec_Int_t vVar2Id; // SatVar -> ObjId Vec_Wec_t * vCnfs; // CNFs Vec_Int_t * vCover; // temporary // traversal IDs Vec_Int_t vTravIds; // traversal IDs Vec_Int_t vTravIds2; // traversal IDs int nTravIds; // traversal IDs int nTravIds2; // traversal IDs // window int iPivotNode; // window pivot Vec_Int_t * vNodes; // internal Vec_Int_t * vDivs; // divisors Vec_Int_t * vRoots; // roots Vec_Int_t * vTfo; // TFO (excluding iNode) // SAT solving sat_solver * pSat; // SAT solver int nSatVars; // the number of variables int nTryRemoves; // number of fanin removals int nTryResubs; // number of resubstitutions int nRemoves; // number of fanin removals int nResubs; // number of resubstitutions // counter-examples int nCexes; // number of CEXes Vec_Wrd_t * vDivCexes; // counter-examples // intermediate data Vec_Int_t * vOrder; // object order Vec_Int_t * vDivVars; // divisor SAT variables Vec_Int_t * vDivIds; // divisors indexes Vec_Int_t * vLits; // literals Vec_Int_t * vValues; // SAT variable values Vec_Wec_t * vClauses; // CNF clauses for the node Vec_Int_t * vFaninMap; // mapping fanins into their SAT vars // nodes int nTotalNodesBeg; int nTotalEdgesBeg; int nTotalNodesEnd; int nTotalEdgesEnd; int nNodesTried; int nTotalDivs; int nSatCalls; int nTimeOuts; int nMaxDivs; // runtime abctime timeWin; abctime timeDiv; abctime timeCnf; abctime timeSat; abctime timeOther; abctime timeTotal; // abctime time1; }; static inline int Sfm_NtkPiNum( Sfm_Ntk_t * p ) { return p->nPis; } static inline int Sfm_NtkPoNum( Sfm_Ntk_t * p ) { return p->nPos; } static inline int Sfm_NtkNodeNum( Sfm_Ntk_t * p ) { return p->nObjs - p->nPis - p->nPos; } static inline int Sfm_ObjIsPi( Sfm_Ntk_t * p, int i ) { return i < p->nPis; } static inline int Sfm_ObjIsPo( Sfm_Ntk_t * p, int i ) { return i + p->nPos >= p->nObjs; } static inline int Sfm_ObjIsNode( Sfm_Ntk_t * p, int i ) { return i >= p->nPis && i + p->nPos < p->nObjs; } static inline int Sfm_ObjIsFixed( Sfm_Ntk_t * p, int i ) { return Vec_StrEntry(p->vFixed, i); } static inline int Sfm_ObjAddsLevelArray( Vec_Str_t * p, int i ) { return p == NULL || Vec_StrEntry(p, i) == 0; } static inline int Sfm_ObjAddsLevel( Sfm_Ntk_t * p, int i ) { return Sfm_ObjAddsLevelArray(p->vEmpty, i); } static inline Vec_Int_t * Sfm_ObjFiArray( Sfm_Ntk_t * p, int i ) { return Vec_WecEntry(&p->vFanins, i); } static inline Vec_Int_t * Sfm_ObjFoArray( Sfm_Ntk_t * p, int i ) { return Vec_WecEntry(&p->vFanouts, i); } static inline int Sfm_ObjFaninNum( Sfm_Ntk_t * p, int i ) { return Vec_IntSize(Sfm_ObjFiArray(p, i)); } static inline int Sfm_ObjFanoutNum( Sfm_Ntk_t * p, int i ) { return Vec_IntSize(Sfm_ObjFoArray(p, i)); } static inline int Sfm_ObjRefIncrement( Sfm_Ntk_t * p, int iObj ) { return ++Sfm_ObjFoArray(p, iObj)->nSize; } static inline int Sfm_ObjRefDecrement( Sfm_Ntk_t * p, int iObj ) { return --Sfm_ObjFoArray(p, iObj)->nSize; } static inline int Sfm_ObjFanin( Sfm_Ntk_t * p, int i, int k ) { return Vec_IntEntry(Sfm_ObjFiArray(p, i), k); } static inline int Sfm_ObjFanout( Sfm_Ntk_t * p, int i, int k ) { return Vec_IntEntry(Sfm_ObjFoArray(p, i), k); } static inline int Sfm_ObjSatVar( Sfm_Ntk_t * p, int iObj ) { assert(Vec_IntEntry(&p->vId2Var, iObj) > 0); return Vec_IntEntry(&p->vId2Var, iObj); } static inline void Sfm_ObjSetSatVar( Sfm_Ntk_t * p, int iObj, int Num ) { assert(Vec_IntEntry(&p->vId2Var, iObj) == -1); Vec_IntWriteEntry(&p->vId2Var, iObj, Num); Vec_IntWriteEntry(&p->vVar2Id, Num, iObj); } static inline void Sfm_ObjCleanSatVar( Sfm_Ntk_t * p, int Num ) { int iObj = Vec_IntEntry(&p->vVar2Id, Num); assert(Vec_IntEntry(&p->vId2Var, iObj) > 0); Vec_IntWriteEntry(&p->vId2Var, iObj, -1); Vec_IntWriteEntry(&p->vVar2Id, Num, -1); } static inline void Sfm_NtkCleanVars( Sfm_Ntk_t * p ) { int i; for ( i = 1; i < p->nSatVars; i++ ) if ( Vec_IntEntry(&p->vVar2Id, i) != -1 ) Sfm_ObjCleanSatVar( p, i ); } static inline int Sfm_ObjLevel( Sfm_Ntk_t * p, int iObj ) { return Vec_IntEntry( &p->vLevels, iObj ); } static inline void Sfm_ObjSetLevel( Sfm_Ntk_t * p, int iObj, int Lev ) { Vec_IntWriteEntry( &p->vLevels, iObj, Lev ); } static inline int Sfm_ObjLevelR( Sfm_Ntk_t * p, int iObj ) { return Vec_IntEntry( &p->vLevelsR, iObj ); } static inline void Sfm_ObjSetLevelR( Sfm_Ntk_t * p, int iObj, int Lev ) { Vec_IntWriteEntry( &p->vLevelsR, iObj, Lev ); } static inline int Sfm_ObjUpdateFaninCount( Sfm_Ntk_t * p, int iObj ) { return Vec_IntAddToEntry(&p->vCounts, iObj, -1); } static inline void Sfm_ObjResetFaninCount( Sfm_Ntk_t * p, int iObj ) { Vec_IntWriteEntry(&p->vCounts, iObj, Sfm_ObjFaninNum(p, iObj)-1); } extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Sfm_NtkForEachPi( p, i ) for ( i = 0; i < p->nPis; i++ ) #define Sfm_NtkForEachPo( p, i ) for ( i = p->nObjs - p->nPos; i < p->nObjs; i++ ) #define Sfm_NtkForEachNode( p, i ) for ( i = p->nPis; i + p->nPos < p->nObjs; i++ ) #define Sfm_NtkForEachNodeReverse( p, i ) for ( i = p->nObjs - p->nPos - 1; i >= p->nPis; i-- ) #define Sfm_ObjForEachFanin( p, Node, Fan, i ) for ( i = 0; i < Sfm_ObjFaninNum(p, Node) && ((Fan = Sfm_ObjFanin(p, Node, i)), 1); i++ ) #define Sfm_ObjForEachFanout( p, Node, Fan, i ) for ( i = 0; i < Sfm_ObjFanoutNum(p, Node) && ((Fan = Sfm_ObjFanout(p, Node, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== sfmCnf.c ==========================================================*/ extern void Sfm_PrintCnf( Vec_Str_t * vCnf ); extern int Sfm_TruthToCnf( word Truth, int nVars, Vec_Int_t * vCover, Vec_Str_t * vCnf ); extern Vec_Wec_t * Sfm_CreateCnf( Sfm_Ntk_t * p ); extern void Sfm_TranslateCnf( Vec_Wec_t * vRes, Vec_Str_t * vCnf, Vec_Int_t * vFaninMap, int iPivotVar ); /*=== sfmCore.c ==========================================================*/ /*=== sfmLib.c ==========================================================*/ extern int Sfm_LibFindComplInputGate( Vec_Wrd_t * vFuncs, int iGate, int nFanins, int iFanin, int * piFaninNew ); extern Sfm_Lib_t * Sfm_LibPrepare( int nVars, int fTwo, int fDelay, int fVerbose, int fLibVerbose ); extern void Sfm_LibPrint( Sfm_Lib_t * p ); extern void Sfm_LibStop( Sfm_Lib_t * p ); extern int Sfm_LibFindAreaMatch( Sfm_Lib_t * p, word * pTruth, int nFanins, int * piObj ); extern int Sfm_LibFindDelayMatches( Sfm_Lib_t * p, word * pTruth, int * pFanins, int nFanins, Vec_Ptr_t * vGates, Vec_Ptr_t * vFans ); extern int Sfm_LibImplementSimple( Sfm_Lib_t * p, word * pTruth, int * pFanins, int nFanins, Vec_Int_t * vGates, Vec_Wec_t * vFanins ); extern int Sfm_LibImplementGatesArea( Sfm_Lib_t * p, int * pFanins, int nFanins, int iObj, Vec_Int_t * vGates, Vec_Wec_t * vFanins ); extern int Sfm_LibImplementGatesDelay( Sfm_Lib_t * p, int * pFanins, Mio_Gate_t * pGateB, Mio_Gate_t * pGateT, char * pFansB, char * pFansT, Vec_Int_t * vGates, Vec_Wec_t * vFanins ); /*=== sfmNtk.c ==========================================================*/ extern Sfm_Ntk_t * Sfm_ConstructNetwork( Vec_Wec_t * vFanins, int nPis, int nPos ); extern void Sfm_NtkPrepare( Sfm_Ntk_t * p ); extern void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth ); /*=== sfmSat.c ==========================================================*/ extern int Sfm_NtkWindowToSolver( Sfm_Ntk_t * p ); extern word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ); /*=== sfmTim.c ==========================================================*/ extern Sfm_Tim_t * Sfm_TimStart( Mio_Library_t * pLib, Scl_Con_t * pExt, Abc_Ntk_t * pNtk, int DeltaCrit ); extern void Sfm_TimStop( Sfm_Tim_t * p ); extern int Sfm_TimReadNtkDelay( Sfm_Tim_t * p ); extern int Sfm_TimReadObjDelay( Sfm_Tim_t * p, int iObj ); extern void Sfm_TimUpdateTiming( Sfm_Tim_t * p, Vec_Int_t * vTimeNodes ); extern int Sfm_TimSortArrayByArrival( Sfm_Tim_t * p, Vec_Int_t * vNodes, int iPivot ); extern int Sfm_TimPriorityNodes( Sfm_Tim_t * p, Vec_Int_t * vCands, int Window ); extern int Sfm_TimNodeIsNonCritical( Sfm_Tim_t * p, Abc_Obj_t * pPivot, Abc_Obj_t * pNode ); extern int Sfm_TimEvalRemapping( Sfm_Tim_t * p, Vec_Int_t * vFanins, Vec_Int_t * vMap, Mio_Gate_t * pGate1, char * pFans1, Mio_Gate_t * pGate2, char * pFans2 ); /*=== sfmMit.c ==========================================================*/ extern Sfm_Mit_t * Sfm_MitStart( Mio_Library_t * pLib, SC_Lib * pScl, Scl_Con_t * pExt, Abc_Ntk_t * pNtk, int DeltaCrit ); extern void Sfm_MitStop( Sfm_Mit_t * p ); extern int Sfm_MitReadNtkDelay( Sfm_Mit_t * p ); extern int Sfm_MitReadNtkMinSlack( Sfm_Mit_t * p ); extern int Sfm_MitReadObjDelay( Sfm_Mit_t * p, int iObj ); extern void Sfm_MitTransferLoad( Sfm_Mit_t * p, Abc_Obj_t * pNew, Abc_Obj_t * pOld ); extern void Sfm_MitTimingGrow( Sfm_Mit_t * p ); extern void Sfm_MitUpdateLoad( Sfm_Mit_t * p, Vec_Int_t * vTimeNodes, int fAdd ); extern void Sfm_MitUpdateTiming( Sfm_Mit_t * p, Vec_Int_t * vTimeNodes ); extern int Sfm_MitSortArrayByArrival( Sfm_Mit_t * p, Vec_Int_t * vNodes, int iPivot ); extern int Sfm_MitPriorityNodes( Sfm_Mit_t * p, Vec_Int_t * vCands, int Window ); extern int Sfm_MitNodeIsNonCritical( Sfm_Mit_t * p, Abc_Obj_t * pPivot, Abc_Obj_t * pNode ); extern int Sfm_MitEvalRemapping( Sfm_Mit_t * p, Vec_Int_t * vMffc, Abc_Obj_t * pObj, Vec_Int_t * vFanins, Vec_Int_t * vMap, Mio_Gate_t * pGate1, char * pFans1, Mio_Gate_t * pGate2, char * pFans2 ); /*=== sfmWin.c ==========================================================*/ extern int Sfm_ObjMffcSize( Sfm_Ntk_t * p, int iObj ); extern int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmLib.c000066400000000000000000000676401300674244400230200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmLib.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [Preprocessing genlib library.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "misc/vec/vecMem.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" #include "map/mio/exp.h" #include "opt/dau/dau.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Sfm_Fun_t_ { int Next; // next function in the list int Area; // area of this function char pFansT[SFM_SUPP_MAX+1]; // top gate ID, followed by fanin perm char pFansB[SFM_SUPP_MAX+1]; // bottom gate ID, followed by fanin perm }; struct Sfm_Lib_t_ { int nVars; // variable count int nWords; // truth table words int fVerbose; // verbose statistics Mio_Cell2_t * pCells; // library gates int nCells; // library gate count int fDelay; // uses delay profile int nObjs; // object count int nObjsAlloc; // object count Sfm_Fun_t * pObjs; // objects Vec_Mem_t * vTtMem; // truth tables Vec_Int_t vLists; // lists of funcs for each truth table Vec_Int_t vCounts; // counters of functions for each truth table Vec_Int_t vHits; // the number of times this function was used Vec_Int_t vProfs; // area/delay profiles Vec_Int_t vStore; // storage for area/delay profiles Vec_Int_t vTemp; // temporary storage for candidates int nObjSkipped; int nObjRemoved; }; static inline Sfm_Fun_t * Sfm_LibFun( Sfm_Lib_t * p, int i ) { return i == -1 ? NULL : p->pObjs + i; } static inline int Sfm_LibFunId( Sfm_Lib_t * p, Sfm_Fun_t * pFun ) { return pFun - p->pObjs; } #define Sfm_LibForEachSuper( p, pObj, Func ) \ for ( pObj = Sfm_LibFun(p, Vec_IntEntry(&p->vLists, Func)); pObj; pObj = Sfm_LibFun(p, pObj->Next) ) static word s_Truth8[8][4] = { { ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA) }, { ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC) }, { ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0) }, { ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00) }, { ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000) }, { ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000) }, { ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF) }, { ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF) } }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_DecCreateCnf( Vec_Int_t * vGateSizes, Vec_Wrd_t * vGateFuncs, Vec_Wec_t * vGateCnfs ) { Vec_Str_t * vCnf, * vCnfBase; Vec_Int_t * vCover; word uTruth; int i, nCubes; vCnf = Vec_StrAlloc( 100 ); vCover = Vec_IntAlloc( 100 ); Vec_WrdForEachEntry( vGateFuncs, uTruth, i ) { nCubes = Sfm_TruthToCnf( uTruth, Vec_IntEntry(vGateSizes, i), vCover, vCnf ); vCnfBase = (Vec_Str_t *)Vec_WecEntry( vGateCnfs, i ); Vec_StrGrow( vCnfBase, Vec_StrSize(vCnf) ); memcpy( Vec_StrArray(vCnfBase), Vec_StrArray(vCnf), Vec_StrSize(vCnf) ); vCnfBase->nSize = Vec_StrSize(vCnf); } Vec_IntFree( vCover ); Vec_StrFree( vCnf ); } /**Function************************************************************* Synopsis [Preprocess the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_LibPreprocess( Mio_Library_t * pLib, Vec_Int_t * vGateSizes, Vec_Wrd_t * vGateFuncs, Vec_Wec_t * vGateCnfs, Vec_Ptr_t * vGateHands ) { Mio_Gate_t * pGate; int nGates = Mio_LibraryReadGateNum(pLib); Vec_IntGrow( vGateSizes, nGates ); Vec_WrdGrow( vGateFuncs, nGates ); Vec_WecInit( vGateCnfs, nGates ); Vec_PtrGrow( vGateHands, nGates ); Mio_LibraryForEachGate( pLib, pGate ) { Vec_IntPush( vGateSizes, Mio_GateReadPinNum(pGate) ); Vec_WrdPush( vGateFuncs, Mio_GateReadTruth(pGate) ); Mio_GateSetValue( pGate, Vec_PtrSize(vGateHands) ); Vec_PtrPush( vGateHands, pGate ); } Sfm_DecCreateCnf( vGateSizes, vGateFuncs, vGateCnfs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_LibFindComplInputGate( Vec_Wrd_t * vFuncs, int iGate, int nFanins, int iFanin, int * piFaninNew ) { word uTruthGate = Vec_WrdEntry( vFuncs, iGate ); word uTruthFlip = Abc_Tt6Flip( uTruthGate, iFanin ); word uTruth, uTruthSwap; int i; assert( iFanin >= 0 && iFanin < nFanins ); if ( piFaninNew ) *piFaninNew = iFanin; Vec_WrdForEachEntry( vFuncs, uTruth, i ) if ( uTruth == uTruthFlip ) return i; if ( iFanin-1 >= 0 ) { if ( piFaninNew ) *piFaninNew = iFanin-1; uTruthSwap = Abc_Tt6SwapAdjacent( uTruthFlip, iFanin-1 ); Vec_WrdForEachEntry( vFuncs, uTruth, i ) if ( uTruth == uTruthSwap ) return i; } if ( iFanin+1 < nFanins ) { if ( piFaninNew ) *piFaninNew = iFanin+1; uTruthSwap = Abc_Tt6SwapAdjacent( uTruthFlip, iFanin ); Vec_WrdForEachEntry( vFuncs, uTruth, i ) if ( uTruth == uTruthSwap ) return i; } // add checking for complemeting control input of a MUX if ( piFaninNew ) *piFaninNew = -1; return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sfm_Lib_t * Sfm_LibStart( int nVars, int fDelay, int fVerbose ) { Sfm_Lib_t * p = ABC_CALLOC( Sfm_Lib_t, 1 ); assert( nVars <= SFM_SUPP_MAX ); p->vTtMem = Vec_MemAllocForTT( nVars, 0 ); Vec_IntGrow( &p->vLists, (1 << 16) ); Vec_IntGrow( &p->vCounts, (1 << 16) ); Vec_IntGrow( &p->vHits, (1 << 16) ); Vec_IntFill( &p->vLists, 2, -1 ); Vec_IntFill( &p->vCounts, 2, -1 ); Vec_IntFill( &p->vHits, 2, -1 ); p->nObjsAlloc = (1 << 16); p->pObjs = ABC_CALLOC( Sfm_Fun_t, p->nObjsAlloc ); p->fDelay = fDelay; if ( fDelay ) Vec_IntGrow( &p->vProfs, (1 << 16) ); if ( fDelay ) Vec_IntGrow( &p->vStore, (1 << 18) ); Vec_IntGrow( &p->vTemp, 16 ); p->nVars = nVars; p->nWords = Abc_TtWordNum( nVars ); p->fVerbose = fVerbose; return p; } void Sfm_LibStop( Sfm_Lib_t * p ) { Vec_MemHashFree( p->vTtMem ); Vec_MemFree( p->vTtMem ); Vec_IntErase( &p->vLists ); Vec_IntErase( &p->vCounts ); Vec_IntErase( &p->vHits ); Vec_IntErase( &p->vProfs ); Vec_IntErase( &p->vStore ); Vec_IntErase( &p->vTemp ); ABC_FREE( p->pCells ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Sfm_LibTruth6Two( Mio_Cell2_t * pCellBot, Mio_Cell2_t * pCellTop, int InTop ) { word uFanins[SFM_SUPP_MAX]; int i, k; word uTruthBot = Exp_Truth6( pCellBot->nFanins, pCellBot->vExpr, NULL ); assert( InTop >= 0 && InTop < (int)pCellTop->nFanins ); for ( i = 0, k = pCellBot->nFanins; i < (int)pCellTop->nFanins; i++ ) if ( i == InTop ) uFanins[i] = uTruthBot; else uFanins[i] = s_Truths6[k++]; assert( (int)pCellBot->nFanins + (int)pCellTop->nFanins == k + 1 ); uTruthBot = Exp_Truth6( pCellTop->nFanins, pCellTop->vExpr, uFanins ); return uTruthBot; } void Sfm_LibTruth8Two( Mio_Cell2_t * pCellBot, Mio_Cell2_t * pCellTop, int InTop, word * pRes ) { word uTruthBot[4], * puFanins[SFM_SUPP_MAX]; int i, k; Exp_Truth8( pCellBot->nFanins, pCellBot->vExpr, NULL, uTruthBot ); assert( InTop >= 0 && InTop < (int)pCellTop->nFanins ); for ( i = 0, k = pCellBot->nFanins; i < (int)pCellTop->nFanins; i++ ) if ( i == InTop ) puFanins[i] = uTruthBot; else puFanins[i] = s_Truth8[k++]; assert( (int)pCellBot->nFanins + (int)pCellTop->nFanins == k + 1 ); Exp_Truth8( pCellTop->nFanins, pCellTop->vExpr, puFanins, pRes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* void Sfm_LibCellProfile( Mio_Cell2_t * pCellBot, Mio_Cell2_t * pCellTop, int InTop, int nFanins, int * Perm, int * pProf ) { int i, DelayAdd = pCellTop ? pCellTop->iDelays[InTop] : 0; for ( i = 0; i < nFanins; i++ ) if ( Perm[i] < (int)pCellBot->nFanins ) pProf[i] = pCellBot->iDelays[Perm[i]] + DelayAdd; else if ( Perm[i] < (int)pCellBot->nFanins + InTop ) pProf[i] = pCellTop->iDelays[Perm[i] - (int)pCellBot->nFanins]; else // if ( Perm[i] >= (int)pCellBot->nFanins + InTop ) pProf[i] = pCellTop->iDelays[Perm[i] - (int)pCellBot->nFanins + 1]; } */ void Sfm_LibCellProfile( Mio_Cell2_t * pCellBot, Mio_Cell2_t * pCellTop, int InTop, int nFanins, int * Perm, int * pProf ) { int i, DelayAdd = pCellTop ? 1 : 0; for ( i = 0; i < nFanins; i++ ) if ( Perm[i] < (int)pCellBot->nFanins ) pProf[i] = 1 + DelayAdd; else if ( Perm[i] < (int)pCellBot->nFanins + InTop ) pProf[i] = 1; else // if ( Perm[i] >= (int)pCellBot->nFanins + InTop ) pProf[i] = 1; } static inline int Sfm_LibNewIsContained( Sfm_Fun_t * pObj, int * pProf, int Area, int * pProfNew, int nFanins ) { int k; if ( Area < pObj->Area ) return 0; for ( k = 0; k < nFanins; k++ ) if ( pProfNew[k] < pProf[k] ) return 0; return 1; } static inline int Sfm_LibNewContains( Sfm_Fun_t * pObj, int * pProf, int Area, int * pProfNew, int nFanins ) { int k; if ( Area > pObj->Area ) return 0; for ( k = 0; k < nFanins; k++ ) if ( pProfNew[k] > pProf[k] ) return 0; return 1; } void Sfm_LibPrepareAdd( Sfm_Lib_t * p, word * pTruth, int * Perm, int nFanins, Mio_Cell2_t * pCellBot, Mio_Cell2_t * pCellTop, int InTop ) { Sfm_Fun_t * pObj; int InvPerm[SFM_SUPP_MAX], Profile[SFM_SUPP_MAX]; int Area = (int)pCellBot->AreaW + (pCellTop ? (int)pCellTop->AreaW : 0); int i, k, Id, Prev, Offset, * pProf, iFunc = Vec_MemHashInsert( p->vTtMem, pTruth ); if ( iFunc == Vec_IntSize(&p->vLists) ) { Vec_IntPush( &p->vLists, -1 ); Vec_IntPush( &p->vCounts, 0 ); Vec_IntPush( &p->vHits, 0 ); } assert( pCellBot != NULL ); // iterate through the supergates of this truth table if ( p->fDelay ) { assert( Vec_IntSize(&p->vProfs) == p->nObjs ); Sfm_LibCellProfile( pCellBot, pCellTop, InTop, nFanins, Perm, Profile ); // check if new one is contained in old ones Vec_IntClear( &p->vTemp ); Sfm_LibForEachSuper( p, pObj, iFunc ) { Vec_IntPush( &p->vTemp, Sfm_LibFunId(p, pObj) ); Offset = Vec_IntEntry( &p->vProfs, Sfm_LibFunId(p, pObj) ); pProf = Vec_IntEntryP( &p->vStore, Offset ); if ( Sfm_LibNewIsContained(pObj, pProf, Area, Profile, nFanins) ) { p->nObjSkipped++; return; } } // check if old ones are contained in new one k = 0; Vec_IntForEachEntry( &p->vTemp, Id, i ) { Offset = Vec_IntEntry( &p->vProfs, Id ); pProf = Vec_IntEntryP( &p->vStore, Offset ); if ( !Sfm_LibNewContains(Sfm_LibFun(p, Id), pProf, Area, Profile, nFanins) ) Vec_IntWriteEntry( &p->vTemp, k++, Id ); else p->nObjRemoved++; } if ( k < i ) // change { if ( k == 0 ) Vec_IntWriteEntry( &p->vLists, iFunc, -1 ); else { Vec_IntShrink( &p->vTemp, k ); Prev = Vec_IntEntry(&p->vTemp, 0); Vec_IntWriteEntry( &p->vLists, iFunc, Prev ); Vec_IntForEachEntryStart( &p->vTemp, Id, i, 1 ) { Sfm_LibFun(p, Prev)->Next = Id; Prev = Id; } Sfm_LibFun(p, Prev)->Next = -1; } } } else { Sfm_LibForEachSuper( p, pObj, iFunc ) { if ( Area >= pObj->Area ) return; } } for ( k = 0; k < nFanins; k++ ) InvPerm[Perm[k]] = k; // create delay profile if ( p->fDelay ) { Vec_IntPush( &p->vProfs, Vec_IntSize(&p->vStore) ); for ( k = 0; k < nFanins; k++ ) Vec_IntPush( &p->vStore, Profile[k] ); } // create new object if ( p->nObjs == p->nObjsAlloc ) { int nObjsAlloc = 2 * p->nObjsAlloc; p->pObjs = ABC_REALLOC( Sfm_Fun_t, p->pObjs, nObjsAlloc ); memset( p->pObjs + p->nObjsAlloc, 0, sizeof(Sfm_Fun_t) * p->nObjsAlloc ); p->nObjsAlloc = nObjsAlloc; } pObj = p->pObjs + p->nObjs; pObj->Area = Area; pObj->Next = Vec_IntEntry(&p->vLists, iFunc); Vec_IntWriteEntry( &p->vLists, iFunc, p->nObjs++ ); Vec_IntAddToEntry( &p->vCounts, iFunc, 1 ); // create gate assert( pCellBot->Id < 128 ); pObj->pFansB[0] = (char)pCellBot->Id; for ( k = 0; k < (int)pCellBot->nFanins; k++ ) pObj->pFansB[k+1] = InvPerm[k]; if ( pCellTop == NULL ) return; assert( pCellTop->Id < 128 ); pObj->pFansT[0] = (char)pCellTop->Id; for ( i = 0; i < (int)pCellTop->nFanins; i++ ) pObj->pFansT[i+1] = (char)(i == InTop ? 16 : InvPerm[k++]); assert( k == nFanins ); } Sfm_Lib_t * Sfm_LibPrepare( int nVars, int fTwo, int fDelay, int fVerbose, int fLibVerbose ) { abctime clk = Abc_Clock(); Sfm_Lib_t * p = Sfm_LibStart( nVars, fDelay, fLibVerbose ); Mio_Cell2_t * pCell1, * pCell2, * pLimit; int * pPerm[SFM_SUPP_MAX+1], * Perm1, * Perm2, Perm[SFM_SUPP_MAX]; int nPerms[SFM_SUPP_MAX+1], i, f, n; word tTemp1[4], tCur[4]; char pRes[1000]; assert( nVars <= SFM_SUPP_MAX ); // precompute gates p->pCells = Mio_CollectRootsNewDefault2( Abc_MinInt(6, nVars), &p->nCells, 0 ); pLimit = p->pCells + p->nCells; // find useful ones for ( pCell1 = p->pCells + 4; pCell1 < pLimit; pCell1++ ) { word uTruth = pCell1->uTruth; pCell1->Type = 0; if ( Abc_Tt6IsAndType(uTruth, pCell1->nFanins) || Abc_Tt6IsOrType(uTruth, pCell1->nFanins) ) pCell1->Type = 1; else if ( Dau_DsdDecompose(&uTruth, pCell1->nFanins, 0, 0, pRes) <= 3 ) pCell1->Type = 2; else if ( fLibVerbose ) printf( "Skipping gate \"%s\" with non-DSD function %s\n", pCell1->pName, pRes ); } // generate permutations for ( i = 2; i <= nVars; i++ ) pPerm[i] = Extra_PermSchedule( i ); for ( i = 2; i <= nVars; i++ ) nPerms[i] = Extra_Factorial( i ); // add single cells for ( pCell1 = p->pCells + 4; pCell1 < pLimit; pCell1++ ) { int nFanins = pCell1->nFanins; assert( nFanins >= 2 && nFanins <= nVars ); for ( i = 0; i < nFanins; i++ ) Perm[i] = i; // permute truth table tCur[0] = tTemp1[0] = pCell1->uTruth; if ( p->nVars > 6 ) tTemp1[1] = tTemp1[2] = tTemp1[3] = tCur[1] = tCur[2] = tCur[3] = tCur[0]; for ( n = 0; n < nPerms[nFanins]; n++ ) { Sfm_LibPrepareAdd( p, tCur, Perm, nFanins, pCell1, NULL, -1 ); // update Abc_TtSwapAdjacent( tCur, p->nWords, pPerm[nFanins][n] ); Perm1 = Perm + pPerm[nFanins][n]; Perm2 = Perm1 + 1; ABC_SWAP( int, *Perm1, *Perm2 ); } assert( Abc_TtEqual(tTemp1, tCur, p->nWords) ); } // add double cells if ( fTwo ) for ( pCell1 = p->pCells + 4; pCell1 < pLimit; pCell1++ ) // Bot if ( pCell1->Type > 0 ) for ( pCell2 = p->pCells + 4; pCell2 < pLimit; pCell2++ ) // Top if ( pCell2->Type > 0 )//&& pCell1->Type + pCell2->Type <= 2 ) if ( (int)pCell1->nFanins + (int)pCell2->nFanins <= nVars + 1 ) for ( f = 0; f < (int)pCell2->nFanins; f++ ) { int nFanins = pCell1->nFanins + pCell2->nFanins - 1; assert( nFanins >= 2 && nFanins <= nVars ); for ( i = 0; i < nFanins; i++ ) Perm[i] = i; // permute truth table if ( p->nVars > 6 ) { Sfm_LibTruth8Two( pCell1, pCell2, f, tCur ); Abc_TtCopy( tTemp1, tCur, p->nWords, 0 ); } else tCur[0] = tTemp1[0] = Sfm_LibTruth6Two( pCell1, pCell2, f ); for ( n = 0; n < nPerms[nFanins]; n++ ) { Sfm_LibPrepareAdd( p, tCur, Perm, nFanins, pCell1, pCell2, f ); if ( nFanins > 5 ) break; // update Abc_TtSwapAdjacent( tCur, p->nWords, pPerm[nFanins][n] ); Perm1 = Perm + pPerm[nFanins][n]; Perm2 = Perm1 + 1; ABC_SWAP( int, *Perm1, *Perm2 ); } assert( Abc_TtEqual(tTemp1, tCur, p->nWords) ); } // cleanup for ( i = 2; i <= nVars; i++ ) ABC_FREE( pPerm[i] ); if ( fVerbose ) { printf( "Library processing: Var = %d. Cell = %d. Fun = %d. Obj = %d. Ave = %.2f. Skip = %d. Rem = %d. ", nVars, p->nCells, Vec_MemEntryNum(p->vTtMem)-2, p->nObjs-p->nObjRemoved, 1.0*(p->nObjs-p->nObjRemoved)/(Vec_MemEntryNum(p->vTtMem)-2), p->nObjSkipped, p->nObjRemoved ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return p; } void Sfm_LibPrintGate( Mio_Cell2_t * pCell, char * pFanins, Mio_Cell2_t * pCell2, char * pFanins2 ) { int k; printf( " %-20s(", pCell->pName ); for ( k = 0; k < (int)pCell->nFanins; k++ ) if ( pFanins[k] == (char)16 ) Sfm_LibPrintGate( pCell2, pFanins2, NULL, NULL ); else printf( " %c", 'a' + pFanins[k] ); printf( " )" ); } void Sfm_LibPrintObj( Sfm_Lib_t * p, Sfm_Fun_t * pObj ) { Mio_Cell2_t * pCellB = p->pCells + (int)pObj->pFansB[0]; Mio_Cell2_t * pCellT = p->pCells + (int)pObj->pFansT[0]; int i, nFanins = pCellB->nFanins + (pCellT == p->pCells ? 0 : pCellT->nFanins - 1); printf( "F = %d A =%6.2f ", nFanins, Scl_Int2Flt(pObj->Area) ); if ( pCellT == p->pCells ) Sfm_LibPrintGate( pCellB, pObj->pFansB + 1, NULL, NULL ); else Sfm_LibPrintGate( pCellT, pObj->pFansT + 1, pCellB, pObj->pFansB + 1 ); // get hold of delay info if ( p->fDelay ) { int Offset = Vec_IntEntry( &p->vProfs, Sfm_LibFunId(p, pObj) ); int * pProf = Vec_IntEntryP( &p->vStore, Offset ); for ( i = 0; i < nFanins; i++ ) printf( "%6.2f ", Scl_Int2Flt(pProf[i]) ); } } void Sfm_LibPrint( Sfm_Lib_t * p ) { Sfm_Fun_t * pObj; word * pTruth; int i, nFanins; Vec_MemForEachEntry( p->vTtMem, pTruth, i ) { if ( i < 2 || Vec_IntEntry(&p->vHits, i) == 0 ) continue; nFanins = Abc_TtSupportSize(pTruth, p->nVars); printf( "%8d : ", i ); printf( "Num =%5d ", Vec_IntEntry(&p->vCounts, i) ); printf( "Hit =%4d ", Vec_IntEntry(&p->vHits, i) ); Sfm_LibForEachSuper( p, pObj, i ) { Sfm_LibPrintObj( p, pObj ); break; } printf( " " ); Dau_DsdPrintFromTruth( pTruth, nFanins ); } } void Sfm_LibTest() { Sfm_Lib_t * p; int fVerbose = 1; if ( Abc_FrameReadLibGen() == NULL ) { printf( "There is no current library.\n" ); return; } p = Sfm_LibPrepare( 7, 1, 1, 1, fVerbose ); if ( fVerbose ) Sfm_LibPrint( p ); Sfm_LibStop( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_LibFindAreaMatch( Sfm_Lib_t * p, word * pTruth, int nFanins, int * piObj ) { Sfm_Fun_t * pObj = NULL; int iFunc = *Vec_MemHashLookup( p->vTtMem, pTruth ); if ( iFunc == -1 ) return -1; Sfm_LibForEachSuper( p, pObj, iFunc ) break; if ( piObj ) *piObj = pObj - p->pObjs; return pObj->Area; } int Sfm_LibFindDelayMatches( Sfm_Lib_t * p, word * pTruth, int * pFanins, int nFanins, Vec_Ptr_t * vGates, Vec_Ptr_t * vFans ) { Sfm_Fun_t * pObj; Mio_Cell2_t * pCellB, * pCellT; int iFunc; if ( nFanins > 6 ) { word pCopy[4]; Abc_TtCopy( pCopy, pTruth, 4, 0 ); Dau_DsdPrintFromTruth( pCopy, p->nVars ); } Vec_PtrClear( vGates ); Vec_PtrClear( vFans ); // look for gate assert( !Abc_TtIsConst0(pTruth, p->nWords) && !Abc_TtIsConst1(pTruth, p->nWords) && !Abc_TtEqual(pTruth, s_Truth8[0], p->nWords) && !Abc_TtOpposite(pTruth, s_Truth8[0], p->nWords) ); iFunc = *Vec_MemHashLookup( p->vTtMem, pTruth ); if ( iFunc == -1 ) { // print functions not found in the library if ( p->fVerbose || nFanins > 6 ) { printf( "Not found in the precomputed library: " ); Dau_DsdPrintFromTruth( pTruth, nFanins ); } return 0; } Vec_IntAddToEntry( &p->vHits, iFunc, 1 ); // collect matches Sfm_LibForEachSuper( p, pObj, iFunc ) { pCellB = p->pCells + (int)pObj->pFansB[0]; pCellT = p->pCells + (int)pObj->pFansT[0]; Vec_PtrPush( vGates, pCellB->pMioGate ); Vec_PtrPush( vGates, pCellT == p->pCells ? NULL : pCellT->pMioGate ); Vec_PtrPush( vFans, pObj->pFansB + 1 ); Vec_PtrPush( vFans, pCellT == p->pCells ? NULL : pObj->pFansT + 1 ); } return Vec_PtrSize(vGates) / 2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_LibImplementSimple( Sfm_Lib_t * p, word * pTruth, int * pFanins, int nFanins, Vec_Int_t * vGates, Vec_Wec_t * vFanins ) { Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Mio_Gate_t * pGate; Vec_Int_t * vLevel; if ( Abc_TtIsConst0(pTruth, p->nWords) || Abc_TtIsConst1(pTruth, p->nWords) ) { assert( nFanins == 0 ); pGate = Abc_TtIsConst1(pTruth, p->nWords) ? Mio_LibraryReadConst1(pLib) : Mio_LibraryReadConst0(pLib); Vec_IntPush( vGates, Mio_GateReadValue(pGate) ); vLevel = Vec_WecPushLevel( vFanins ); return 1; } if ( Abc_TtEqual(pTruth, s_Truth8[0], p->nWords) || Abc_TtOpposite(pTruth, s_Truth8[0], p->nWords) ) { assert( nFanins == 1 ); pGate = Abc_TtEqual(pTruth, s_Truth8[0], p->nWords) ? Mio_LibraryReadBuf(pLib) : Mio_LibraryReadInv(pLib); Vec_IntPush( vGates, Mio_GateReadValue(pGate) ); vLevel = Vec_WecPushLevel( vFanins ); Vec_IntPush( vLevel, pFanins[0] ); return 1; } assert( 0 ); return -1; } int Sfm_LibImplementGatesArea( Sfm_Lib_t * p, int * pFanins, int nFanins, int iObj, Vec_Int_t * vGates, Vec_Wec_t * vFanins ) { Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Sfm_Fun_t * pObjMin = p->pObjs + iObj; Mio_Cell2_t * pCellB, * pCellT; Mio_Gate_t * pGate; Vec_Int_t * vLevel; int i; // get the gates pCellB = p->pCells + (int)pObjMin->pFansB[0]; pCellT = p->pCells + (int)pObjMin->pFansT[0]; // create bottom gate pGate = Mio_LibraryReadGateByName( pLib, pCellB->pName, NULL ); assert( pGate == pCellB->pMioGate ); Vec_IntPush( vGates, Mio_GateReadValue(pGate) ); vLevel = Vec_WecPushLevel( vFanins ); for ( i = 0; i < (int)pCellB->nFanins; i++ ) Vec_IntPush( vLevel, pFanins[(int)pObjMin->pFansB[i+1]] ); if ( pCellT == p->pCells ) return 1; // create top gate pGate = Mio_LibraryReadGateByName( pLib, pCellT->pName, NULL ); assert( pGate == pCellT->pMioGate ); Vec_IntPush( vGates, Mio_GateReadValue(pGate) ); vLevel = Vec_WecPushLevel( vFanins ); for ( i = 0; i < (int)pCellT->nFanins; i++ ) if ( pObjMin->pFansT[i+1] == (char)16 ) Vec_IntPush( vLevel, Vec_WecSize(vFanins)-2 ); else Vec_IntPush( vLevel, pFanins[(int)pObjMin->pFansT[i+1]] ); return 2; } int Sfm_LibImplementGatesDelay( Sfm_Lib_t * p, int * pFanins, Mio_Gate_t * pGateB, Mio_Gate_t * pGateT, char * pFansB, char * pFansT, Vec_Int_t * vGates, Vec_Wec_t * vFanins ) { Vec_Int_t * vLevel; int i, nFanins; // create bottom gate Vec_IntPush( vGates, Mio_GateReadValue(pGateB) ); vLevel = Vec_WecPushLevel( vFanins ); nFanins = Mio_GateReadPinNum( pGateB ); for ( i = 0; i < nFanins; i++ ) Vec_IntPush( vLevel, pFanins[(int)pFansB[i]] ); if ( pGateT == NULL ) return 1; // create top gate Vec_IntPush( vGates, Mio_GateReadValue(pGateT) ); vLevel = Vec_WecPushLevel( vFanins ); nFanins = Mio_GateReadPinNum( pGateT ); for ( i = 0; i < nFanins; i++ ) if ( pFansT[i] == (char)16 ) Vec_IntPush( vLevel, Vec_WecSize(vFanins)-2 ); else Vec_IntPush( vLevel, pFanins[(int)pFansT[i]] ); return 2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmMit.c000066400000000000000000000062011300674244400230250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmMit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [Timing manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmMit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Sfm_Mit_t_ { int Value1; int Value2; int Value3; int Value4; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Temporary place holders.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sfm_Mit_t * Sfm_MitStart( Mio_Library_t * pLib, SC_Lib * pScl, Scl_Con_t * pExt, Abc_Ntk_t * pNtk, int DeltaCrit ) { return NULL; } void Sfm_MitStop( Sfm_Mit_t * p ) {} int Sfm_MitReadNtkDelay( Sfm_Mit_t * p ) { return 0;} int Sfm_MitReadNtkMinSlack( Sfm_Mit_t * p ) { return 0;} int Sfm_MitReadObjDelay( Sfm_Mit_t * p, int iObj ) { return 0;} void Sfm_MitTransferLoad( Sfm_Mit_t * p, Abc_Obj_t * pNew, Abc_Obj_t * pOld ) {}; void Sfm_MitTimingGrow( Sfm_Mit_t * p ) {}; void Sfm_MitUpdateLoad( Sfm_Mit_t * p, Vec_Int_t * vTimeNodes, int fAdd ) {} void Sfm_MitUpdateTiming( Sfm_Mit_t * p, Vec_Int_t * vTimeNodes ) {} int Sfm_MitSortArrayByArrival( Sfm_Mit_t * p, Vec_Int_t * vNodes, int iPivot ) { return 0;} int Sfm_MitPriorityNodes( Sfm_Mit_t * p, Vec_Int_t * vCands, int Window ) { return 0;} int Sfm_MitNodeIsNonCritical( Sfm_Mit_t * p, Abc_Obj_t * pPivot, Abc_Obj_t * pNode ) { return 0;} int Sfm_MitEvalRemapping( Sfm_Mit_t * p, Vec_Int_t * vMffc, Abc_Obj_t * pObj, Vec_Int_t * vFanins, Vec_Int_t * vMap, Mio_Gate_t * pGate1, char * pFans1, Mio_Gate_t * pGate2, char * pFans2 ) { return 0;} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmNtk.c000066400000000000000000000305271300674244400230400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmNtk.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [Logic network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_CheckConsistency( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed ) { Vec_Int_t * vArray; int i, k, Fanin; // check entries Vec_WecForEachLevel( vFanins, vArray, i ) { // PIs have no fanins if ( i < nPis ) assert( Vec_IntSize(vArray) == 0 && Vec_StrEntry(vFixed, i) == (char)0 ); // nodes are in a topo order; POs cannot be fanins Vec_IntForEachEntry( vArray, Fanin, k ) // assert( Fanin < i && Fanin + nPos < Vec_WecSize(vFanins) ); assert( Fanin + nPos < Vec_WecSize(vFanins) ); // POs have one fanout if ( i + nPos >= Vec_WecSize(vFanins) ) assert( Vec_IntSize(vArray) == 1 && Vec_StrEntry(vFixed, i) == (char)0 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_CreateFanout( Vec_Wec_t * vFanins, Vec_Wec_t * vFanouts ) { Vec_Int_t * vArray; int i, k, Fanin; // count fanouts Vec_WecInit( vFanouts, Vec_WecSize(vFanins) ); Vec_WecForEachLevel( vFanins, vArray, i ) Vec_IntForEachEntry( vArray, Fanin, k ) Vec_WecEntry( vFanouts, Fanin )->nSize++; // allocate fanins Vec_WecForEachLevel( vFanouts, vArray, i ) { k = vArray->nSize; vArray->nSize = 0; Vec_IntGrow( vArray, k ); } // add fanouts Vec_WecForEachLevel( vFanins, vArray, i ) Vec_IntForEachEntry( vArray, Fanin, k ) Vec_IntPush( Vec_WecEntry( vFanouts, Fanin ), i ); // verify Vec_WecForEachLevel( vFanouts, vArray, i ) assert( Vec_IntSize(vArray) == Vec_IntCap(vArray) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sfm_ObjLevelNew( Vec_Int_t * vArray, Vec_Int_t * vLevels, int fAddLevel ) { int k, Fanin, Level = 0; Vec_IntForEachEntry( vArray, Fanin, k ) Level = Abc_MaxInt( Level, Vec_IntEntry(vLevels, Fanin) ); return Level + fAddLevel; } void Sfm_CreateLevel( Vec_Wec_t * vFanins, Vec_Int_t * vLevels, Vec_Str_t * vEmpty ) { Vec_Int_t * vArray; int i; assert( Vec_IntSize(vLevels) == 0 ); Vec_IntFill( vLevels, Vec_WecSize(vFanins), 0 ); Vec_WecForEachLevel( vFanins, vArray, i ) Vec_IntWriteEntry( vLevels, i, Sfm_ObjLevelNew(vArray, vLevels, Sfm_ObjAddsLevelArray(vEmpty, i)) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sfm_ObjLevelNewR( Vec_Int_t * vArray, Vec_Int_t * vLevelsR, int fAddLevel ) { int k, Fanout, LevelR = 0; Vec_IntForEachEntry( vArray, Fanout, k ) LevelR = Abc_MaxInt( LevelR, Vec_IntEntry(vLevelsR, Fanout) ); return LevelR + fAddLevel; } void Sfm_CreateLevelR( Vec_Wec_t * vFanouts, Vec_Int_t * vLevelsR, Vec_Str_t * vEmpty ) { Vec_Int_t * vArray; int i; assert( Vec_IntSize(vLevelsR) == 0 ); Vec_IntFill( vLevelsR, Vec_WecSize(vFanouts), 0 ); Vec_WecForEachLevelReverse( vFanouts, vArray, i ) Vec_IntWriteEntry( vLevelsR, i, Sfm_ObjLevelNewR(vArray, vLevelsR, Sfm_ObjAddsLevelArray(vEmpty, i)) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sfm_Ntk_t * Sfm_NtkConstruct( Vec_Wec_t * vFanins, int nPis, int nPos, Vec_Str_t * vFixed, Vec_Str_t * vEmpty, Vec_Wrd_t * vTruths ) { Sfm_Ntk_t * p; Sfm_CheckConsistency( vFanins, nPis, nPos, vFixed ); p = ABC_CALLOC( Sfm_Ntk_t, 1 ); p->nObjs = Vec_WecSize( vFanins ); p->nPis = nPis; p->nPos = nPos; p->nNodes = p->nObjs - p->nPis - p->nPos; // user data p->vFixed = vFixed; p->vEmpty = vEmpty; p->vTruths = vTruths; p->vFanins = *vFanins; ABC_FREE( vFanins ); // attributes Sfm_CreateFanout( &p->vFanins, &p->vFanouts ); Sfm_CreateLevel( &p->vFanins, &p->vLevels, vEmpty ); Sfm_CreateLevelR( &p->vFanouts, &p->vLevelsR, vEmpty ); Vec_IntFill( &p->vCounts, p->nObjs, 0 ); Vec_IntFill( &p->vTravIds, p->nObjs, 0 ); Vec_IntFill( &p->vTravIds2, p->nObjs, 0 ); Vec_IntFill( &p->vId2Var, 2*p->nObjs, -1 ); Vec_IntFill( &p->vVar2Id, 2*p->nObjs, -1 ); p->vCover = Vec_IntAlloc( 1 << 16 ); p->vCnfs = Sfm_CreateCnf( p ); return p; } void Sfm_NtkPrepare( Sfm_Ntk_t * p ) { p->nLevelMax = Vec_IntFindMax(&p->vLevels) + p->pPars->nGrowthLevel; p->vNodes = Vec_IntAlloc( 1000 ); p->vDivs = Vec_IntAlloc( 100 ); p->vRoots = Vec_IntAlloc( 1000 ); p->vTfo = Vec_IntAlloc( 1000 ); p->vDivCexes = Vec_WrdStart( p->pPars->nWinSizeMax ); p->vOrder = Vec_IntAlloc( 100 ); p->vDivVars = Vec_IntAlloc( 100 ); p->vDivIds = Vec_IntAlloc( 1000 ); p->vLits = Vec_IntAlloc( 100 ); p->vValues = Vec_IntAlloc( 100 ); p->vClauses = Vec_WecAlloc( 100 ); p->vFaninMap = Vec_IntAlloc( 10 ); p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, p->pPars->nWinSizeMax ); } void Sfm_NtkFree( Sfm_Ntk_t * p ) { // user data Vec_StrFree( p->vFixed ); Vec_StrFreeP( &p->vEmpty ); Vec_WrdFree( p->vTruths ); Vec_WecErase( &p->vFanins ); // attributes Vec_WecErase( &p->vFanouts ); ABC_FREE( p->vLevels.pArray ); ABC_FREE( p->vLevelsR.pArray ); ABC_FREE( p->vCounts.pArray ); ABC_FREE( p->vTravIds.pArray ); ABC_FREE( p->vTravIds2.pArray ); ABC_FREE( p->vId2Var.pArray ); ABC_FREE( p->vVar2Id.pArray ); Vec_WecFree( p->vCnfs ); Vec_IntFree( p->vCover ); // other data Vec_IntFreeP( &p->vNodes ); Vec_IntFreeP( &p->vDivs ); Vec_IntFreeP( &p->vRoots ); Vec_IntFreeP( &p->vTfo ); Vec_WrdFreeP( &p->vDivCexes ); Vec_IntFreeP( &p->vOrder ); Vec_IntFreeP( &p->vDivVars ); Vec_IntFreeP( &p->vDivIds ); Vec_IntFreeP( &p->vLits ); Vec_IntFreeP( &p->vValues ); Vec_WecFreeP( &p->vClauses ); Vec_IntFreeP( &p->vFaninMap ); if ( p->pSat ) sat_solver_delete( p->pSat ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Performs resubstitution for the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_NtkRemoveFanin( Sfm_Ntk_t * p, int iNode, int iFanin ) { int RetValue; assert( Sfm_ObjIsNode(p, iNode) ); assert( !Sfm_ObjIsPo(p, iFanin) ); RetValue = Vec_IntRemove( Sfm_ObjFiArray(p, iNode), iFanin ); assert( RetValue ); RetValue = Vec_IntRemove( Sfm_ObjFoArray(p, iFanin), iNode ); assert( RetValue ); } void Sfm_NtkAddFanin( Sfm_Ntk_t * p, int iNode, int iFanin ) { if ( iFanin < 0 ) return; assert( Sfm_ObjIsNode(p, iNode) ); assert( !Sfm_ObjIsPo(p, iFanin) ); assert( Vec_IntFind( Sfm_ObjFiArray(p, iNode), iFanin ) == -1 ); assert( Vec_IntFind( Sfm_ObjFoArray(p, iFanin), iNode ) == -1 ); Vec_IntPush( Sfm_ObjFiArray(p, iNode), iFanin ); Vec_IntPush( Sfm_ObjFoArray(p, iFanin), iNode ); } void Sfm_NtkDeleteObj_rec( Sfm_Ntk_t * p, int iNode ) { int i, iFanin; if ( Sfm_ObjFanoutNum(p, iNode) > 0 || Sfm_ObjIsPi(p, iNode) || Sfm_ObjIsFixed(p, iNode) ) return; assert( Sfm_ObjIsNode(p, iNode) ); Sfm_ObjForEachFanin( p, iNode, iFanin, i ) { int RetValue = Vec_IntRemove( Sfm_ObjFoArray(p, iFanin), iNode ); assert( RetValue ); Sfm_NtkDeleteObj_rec( p, iFanin ); } Vec_IntClear( Sfm_ObjFiArray(p, iNode) ); Vec_WrdWriteEntry( p->vTruths, iNode, (word)0 ); } void Sfm_NtkUpdateLevel_rec( Sfm_Ntk_t * p, int iNode ) { int i, iFanout; int LevelNew = Sfm_ObjLevelNew( Sfm_ObjFiArray(p, iNode), &p->vLevels, Sfm_ObjAddsLevel(p, iNode) ); if ( LevelNew == Sfm_ObjLevel(p, iNode) ) return; Sfm_ObjSetLevel( p, iNode, LevelNew ); Sfm_ObjForEachFanout( p, iNode, iFanout, i ) Sfm_NtkUpdateLevel_rec( p, iFanout ); } void Sfm_NtkUpdateLevelR_rec( Sfm_Ntk_t * p, int iNode ) { int i, iFanin; int LevelNew = Sfm_ObjLevelNewR( Sfm_ObjFoArray(p, iNode), &p->vLevelsR, Sfm_ObjAddsLevel(p, iNode) ); if ( LevelNew == Sfm_ObjLevelR(p, iNode) ) return; Sfm_ObjSetLevelR( p, iNode, LevelNew ); Sfm_ObjForEachFanin( p, iNode, iFanin, i ) Sfm_NtkUpdateLevelR_rec( p, iFanin ); } void Sfm_NtkUpdate( Sfm_Ntk_t * p, int iNode, int f, int iFaninNew, word uTruth ) { int iFanin = Sfm_ObjFanin( p, iNode, f ); assert( Sfm_ObjIsNode(p, iNode) ); assert( iFanin != iFaninNew ); if ( uTruth == 0 || ~uTruth == 0 ) { Sfm_ObjForEachFanin( p, iNode, iFanin, f ) { int RetValue = Vec_IntRemove( Sfm_ObjFoArray(p, iFanin), iNode ); assert( RetValue ); Sfm_NtkDeleteObj_rec( p, iFanin ); } Vec_IntClear( Sfm_ObjFiArray(p, iNode) ); } else { // replace old fanin by new fanin Sfm_NtkRemoveFanin( p, iNode, iFanin ); Sfm_NtkAddFanin( p, iNode, iFaninNew ); // recursively remove MFFC Sfm_NtkDeleteObj_rec( p, iFanin ); } // update logic level Sfm_NtkUpdateLevel_rec( p, iNode ); if ( iFaninNew != -1 ) Sfm_NtkUpdateLevelR_rec( p, iFaninNew ); if ( Sfm_ObjFanoutNum(p, iFanin) > 0 ) Sfm_NtkUpdateLevelR_rec( p, iFanin ); // update truth table Vec_WrdWriteEntry( p->vTruths, iNode, uTruth ); Sfm_TruthToCnf( uTruth, Sfm_ObjFaninNum(p, iNode), p->vCover, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode) ); } /**Function************************************************************* Synopsis [Public APIs of this network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Sfm_NodeReadFanins( Sfm_Ntk_t * p, int i ) { return Vec_WecEntry( &p->vFanins, i ); } word * Sfm_NodeReadTruth( Sfm_Ntk_t * p, int i ) { return Vec_WrdEntryP( p->vTruths, i ); } int Sfm_NodeReadFixed( Sfm_Ntk_t * p, int i ) { return (int)Vec_StrEntry( p->vFixed, i ); } int Sfm_NodeReadUsed( Sfm_Ntk_t * p, int i ) { return (Sfm_ObjFaninNum(p, i) > 0) || (Sfm_ObjFanoutNum(p, i) > 0); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmSat.c000066400000000000000000000241261300674244400230310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [SAT-based procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static word s_Truths6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converts a window into a SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_NtkWindowToSolver( Sfm_Ntk_t * p ) { // p->vOrder contains all variables in the window in a good order // p->vDivs is a subset of nodes in p->vOrder used as divisor candidates // p->vTfo contains TFO of the node (does not include node) // p->vRoots contains roots of the TFO of the node (may include node) Vec_Int_t * vClause; int RetValue, iNode = -1, iFanin, i, k; abctime clk = Abc_Clock(); // if ( p->pSat ) // printf( "%d ", p->pSat->stats.learnts ); sat_solver_restart( p->pSat ); sat_solver_setnvars( p->pSat, 1 + Vec_IntSize(p->vOrder) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots) + 10 ); // create SAT variables Sfm_NtkCleanVars( p ); p->nSatVars = 1; Vec_IntForEachEntry( p->vOrder, iNode, i ) Sfm_ObjSetSatVar( p, iNode, p->nSatVars++ ); // collect divisor variables Vec_IntClear( p->vDivVars ); Vec_IntForEachEntry( p->vDivs, iNode, i ) Vec_IntPush( p->vDivVars, Sfm_ObjSatVar(p, iNode) ); // add CNF clauses for the TFI Vec_IntForEachEntry( p->vOrder, iNode, i ) { if ( Sfm_ObjIsPi(p, iNode) ) continue; // collect fanin variables Vec_IntClear( p->vFaninMap ); Sfm_ObjForEachFanin( p, iNode, iFanin, k ) Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iFanin) ); Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iNode) ); // generate CNF Sfm_TranslateCnf( p->vClauses, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode), p->vFaninMap, -1 ); // add clauses Vec_WecForEachLevel( p->vClauses, vClause, k ) { if ( Vec_IntSize(vClause) == 0 ) break; RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) ); if ( RetValue == 0 ) return 0; } } if ( Vec_IntSize(p->vTfo) > 0 ) { assert( p->pPars->nTfoLevMax > 0 ); assert( Vec_IntSize(p->vRoots) > 0 ); assert( Vec_IntEntry(p->vTfo, 0) != p->iPivotNode ); // collect variables of root nodes Vec_IntClear( p->vLits ); Vec_IntForEachEntry( p->vRoots, iNode, i ) Vec_IntPush( p->vLits, Sfm_ObjSatVar(p, iNode) ); // assign new variables to the TFO nodes Vec_IntForEachEntry( p->vTfo, iNode, i ) { Sfm_ObjCleanSatVar( p, Sfm_ObjSatVar(p, iNode) ); Sfm_ObjSetSatVar( p, iNode, p->nSatVars++ ); } // add CNF clauses for the TFO Vec_IntForEachEntry( p->vTfo, iNode, i ) { assert( Sfm_ObjIsNode(p, iNode) ); // collect fanin variables Vec_IntClear( p->vFaninMap ); Sfm_ObjForEachFanin( p, iNode, iFanin, k ) Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iFanin) ); Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iNode) ); // generate CNF Sfm_TranslateCnf( p->vClauses, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode), p->vFaninMap, Sfm_ObjSatVar(p, p->iPivotNode) ); // add clauses Vec_WecForEachLevel( p->vClauses, vClause, k ) { if ( Vec_IntSize(vClause) == 0 ) break; RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) ); if ( RetValue == 0 ) return 0; } } // create XOR clauses for the roots Vec_IntForEachEntry( p->vRoots, iNode, i ) { sat_solver_add_xor( p->pSat, Vec_IntEntry(p->vLits, i), Sfm_ObjSatVar(p, iNode), p->nSatVars++, 0 ); Vec_IntWriteEntry( p->vLits, i, Abc_Var2Lit(p->nSatVars-1, 0) ); } // make OR clause for the last nRoots variables RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits) ); if ( RetValue == 0 ) return 0; } // finalize RetValue = sat_solver_simplify( p->pSat ); p->timeCnf += Abc_Clock() - clk; return RetValue; } /**Function************************************************************* Synopsis [Takes SAT solver and returns interpolant.] Description [If interpolant does not exist, records difference variables.] SideEffects [] SeeAlso [] ***********************************************************************/ word Sfm_ComputeInterpolant( Sfm_Ntk_t * p ) { word * pSign, uCube, uTruth = 0; int status, i, Div, iVar, nFinal, * pFinal, nIter = 0; int pLits[2], nVars = sat_solver_nvars( p->pSat ); sat_solver_setnvars( p->pSat, nVars + 1 ); pLits[0] = Abc_Var2Lit( Sfm_ObjSatVar(p, p->iPivotNode), 0 ); // F = 1 pLits[1] = Abc_Var2Lit( nVars, 0 ); // iNewLit while ( 1 ) { // find onset minterm p->nSatCalls++; status = sat_solver_solve( p->pSat, pLits, pLits + 2, p->pPars->nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) return SFM_SAT_UNDEC; if ( status == l_False ) return uTruth; assert( status == l_True ); // remember variable values Vec_IntClear( p->vValues ); Vec_IntForEachEntry( p->vDivVars, iVar, i ) Vec_IntPush( p->vValues, sat_solver_var_value(p->pSat, iVar) ); // collect divisor literals Vec_IntClear( p->vLits ); Vec_IntPush( p->vLits, Abc_LitNot(pLits[0]) ); // F = 0 Vec_IntForEachEntry( p->vDivIds, Div, i ) Vec_IntPush( p->vLits, sat_solver_var_literal(p->pSat, Div) ); // check against offset p->nSatCalls++; status = sat_solver_solve( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits), p->pPars->nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) return SFM_SAT_UNDEC; if ( status == l_True ) break; assert( status == l_False ); // compute cube and add clause nFinal = sat_solver_final( p->pSat, &pFinal ); uCube = ~(word)0; Vec_IntClear( p->vLits ); Vec_IntPush( p->vLits, Abc_LitNot(pLits[1]) ); // NOT(iNewLit) for ( i = 0; i < nFinal; i++ ) { if ( pFinal[i] == pLits[0] ) continue; Vec_IntPush( p->vLits, pFinal[i] ); iVar = Vec_IntFind( p->vDivIds, Abc_Lit2Var(pFinal[i]) ); assert( iVar >= 0 ); uCube &= Abc_LitIsCompl(pFinal[i]) ? s_Truths6[iVar] : ~s_Truths6[iVar]; } uTruth |= uCube; status = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits) ); assert( status ); nIter++; } assert( status == l_True ); // store the counter-example Vec_IntForEachEntry( p->vDivVars, iVar, i ) if ( Vec_IntEntry(p->vValues, i) ^ sat_solver_var_value(p->pSat, iVar) ) // insert 1 { pSign = Vec_WrdEntryP( p->vDivCexes, i ); assert( !Abc_InfoHasBit( (unsigned *)pSign, p->nCexes) ); Abc_InfoXorBit( (unsigned *)pSign, p->nCexes ); } p->nCexes++; return SFM_SAT_SAT; } /**Function************************************************************* Synopsis [Checks resubstitution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_ComputeInterpolantCheck( Sfm_Ntk_t * p ) { int iNode = 3; int iDiv0 = 6; int iDiv1 = 7; word uTruth; // int i; // Sfm_NtkForEachNode( p, i ) { Sfm_NtkCreateWindow( p, iNode, 1 ); Sfm_NtkWindowToSolver( p ); // collect SAT variables of divisors Vec_IntClear( p->vDivIds ); Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iDiv0) ); Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iDiv1) ); uTruth = Sfm_ComputeInterpolant( p ); if ( uTruth == SFM_SAT_SAT ) printf( "The problem is SAT.\n" ); else if ( uTruth == SFM_SAT_UNDEC ) printf( "The problem is UNDEC.\n" ); else Kit_DsdPrintFromTruth( (unsigned *)&uTruth, 2 ); printf( "\n" ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmTim.c000066400000000000000000000374031300674244400230350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmTim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [Timing manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmTim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Sfm_Tim_t_ { // external Mio_Library_t * pLib; // library Scl_Con_t * pExt; // external timing Abc_Ntk_t * pNtk; // mapped network int Delay; // the largest delay int DeltaCrit; // critical delay delta // timing info Vec_Int_t vTimArrs; // arrivals (rise/fall) Vec_Int_t vTimReqs; // required (rise/fall) // incremental timing Vec_Wec_t vLevels; // levels // critical path Vec_Int_t vPath; // critical path Vec_Wrd_t vSortData; // node priority order }; static inline int * Sfm_TimArrId( Sfm_Tim_t * p, int Id ) { return Vec_IntEntryP( &p->vTimArrs, Abc_Var2Lit(Id, 0) ); } static inline int * Sfm_TimReqId( Sfm_Tim_t * p, int Id ) { return Vec_IntEntryP( &p->vTimReqs, Abc_Var2Lit(Id, 0) ); } static inline int * Sfm_TimArr( Sfm_Tim_t * p, Abc_Obj_t * pNode ) { return Vec_IntEntryP( &p->vTimArrs, Abc_Var2Lit(Abc_ObjId(pNode), 0) ); } static inline int * Sfm_TimReq( Sfm_Tim_t * p, Abc_Obj_t * pNode ) { return Vec_IntEntryP( &p->vTimReqs, Abc_Var2Lit(Abc_ObjId(pNode), 0) ); } static inline int Sfm_TimArrMaxId( Sfm_Tim_t * p, int Id ) { int * a = Sfm_TimArrId(p, Id); return Abc_MaxInt(a[0], a[1]); } static inline int Sfm_TimArrMax( Sfm_Tim_t * p, Abc_Obj_t * pNode ) { int * a = Sfm_TimArr(p, pNode); return Abc_MaxInt(a[0], a[1]); } static inline void Sfm_TimSetReq( Sfm_Tim_t * p, Abc_Obj_t * pNode, int t ) { int * r = Sfm_TimReq(p, pNode); r[0] = r[1] = t; } static inline int Sfm_TimSlack( Sfm_Tim_t * p, Abc_Obj_t * pNode ) { int * r = Sfm_TimReq(p, pNode), * a = Sfm_TimArr(p, pNode); return Abc_MinInt(r[0]-a[0], r[1]-a[1]); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sfm_TimEdgeArrival( Sfm_Tim_t * p, Mio_Pin_t * pPin, int * pTimeIn, int * pTimeOut ) { Mio_PinPhase_t PinPhase = Mio_PinReadPhase(pPin); int tDelayBlockRise = Scl_Flt2Int(Mio_PinReadDelayBlockRise(pPin)); int tDelayBlockFall = Scl_Flt2Int(Mio_PinReadDelayBlockFall(pPin)); if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present { pTimeOut[0] = Abc_MaxInt( pTimeOut[0], pTimeIn[0] + tDelayBlockRise ); pTimeOut[1] = Abc_MaxInt( pTimeOut[1], pTimeIn[1] + tDelayBlockFall ); } if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present { pTimeOut[0] = Abc_MaxInt( pTimeOut[0], pTimeIn[1] + tDelayBlockRise ); pTimeOut[1] = Abc_MaxInt( pTimeOut[1], pTimeIn[0] + tDelayBlockFall ); } } static inline void Sfm_TimGateArrival( Sfm_Tim_t * p, Mio_Gate_t * pGate, int ** pTimesIn, int * pTimeOut ) { Mio_Pin_t * pPin; int i = 0; pTimeOut[0] = pTimeOut[1] = 0; Mio_GateForEachPin( pGate, pPin ) Sfm_TimEdgeArrival( p, pPin, pTimesIn[i++], pTimeOut ); assert( i == Mio_GateReadPinNum(pGate) ); } static inline void Sfm_TimNodeArrival( Sfm_Tim_t * p, Abc_Obj_t * pNode ) { int i, iFanin, * pTimesIn[6]; int * pTimeOut = Sfm_TimArr(p, pNode); assert( Abc_ObjFaninNum(pNode) <= 6 ); Abc_ObjForEachFaninId( pNode, iFanin, i ) pTimesIn[i] = Sfm_TimArrId( p, iFanin ); Sfm_TimGateArrival( p, (Mio_Gate_t *)pNode->pData, pTimesIn, pTimeOut ); } static inline void Sfm_TimEdgeRequired( Sfm_Tim_t * p, Mio_Pin_t * pPin, int * pTimeIn, int * pTimeOut ) { Mio_PinPhase_t PinPhase = Mio_PinReadPhase(pPin); int tDelayBlockRise = Scl_Flt2Int(Mio_PinReadDelayBlockRise(pPin)); int tDelayBlockFall = Scl_Flt2Int(Mio_PinReadDelayBlockFall(pPin)); if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present { pTimeIn[0] = Abc_MinInt( pTimeIn[0], pTimeOut[0] - tDelayBlockRise ); pTimeIn[1] = Abc_MinInt( pTimeIn[1], pTimeOut[1] - tDelayBlockFall ); } if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present { pTimeIn[0] = Abc_MinInt( pTimeIn[0], pTimeOut[1] - tDelayBlockRise ); pTimeIn[1] = Abc_MinInt( pTimeIn[1], pTimeOut[0] - tDelayBlockFall ); } } static inline void Sfm_TimGateRequired( Sfm_Tim_t * p, Mio_Gate_t * pGate, int ** pTimesIn, int * pTimeOut ) { Mio_Pin_t * pPin; int i = 0; Mio_GateForEachPin( pGate, pPin ) Sfm_TimEdgeRequired( p, pPin, pTimesIn[i++], pTimeOut ); assert( i == Mio_GateReadPinNum(pGate) ); } void Sfm_TimNodeRequired( Sfm_Tim_t * p, Abc_Obj_t * pNode ) { int i, iFanin, * pTimesIn[6]; int * pTimeOut = Sfm_TimReq(p, pNode); assert( Abc_ObjFaninNum(pNode) <= 6 ); Abc_ObjForEachFaninId( pNode, iFanin, i ) pTimesIn[i] = Sfm_TimReqId( p, iFanin ); Sfm_TimGateRequired( p, (Mio_Gate_t *)pNode->pData, pTimesIn, pTimeOut ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_TimCriticalPath_int( Sfm_Tim_t * p, Abc_Obj_t * pObj, Vec_Int_t * vPath, int SlackMax ) { Abc_Obj_t * pNext; int i; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); assert( Abc_ObjIsNode(pObj) ); Abc_ObjForEachFanin( pObj, pNext, i ) { if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) == 0 ) continue; assert( Abc_ObjIsNode(pNext) ); if ( Sfm_TimSlack(p, pNext) <= SlackMax ) Sfm_TimCriticalPath_int( p, pNext, vPath, SlackMax ); } if ( Abc_ObjFaninNum(pObj) > 0 ) Vec_IntPush( vPath, Abc_ObjId(pObj) ); } int Sfm_TimCriticalPath( Sfm_Tim_t * p, int Window ) { int i, SlackMax = p->Delay * Window / 100; Abc_Obj_t * pObj, * pNext; Vec_IntClear( &p->vPath ); Abc_NtkIncrementTravId( p->pNtk ); Abc_NtkForEachCo( p->pNtk, pObj, i ) { pNext = Abc_ObjFanin0(pObj); if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) == 0 ) continue; assert( Abc_ObjIsNode(pNext) ); if ( Sfm_TimSlack(p, pNext) <= SlackMax ) Sfm_TimCriticalPath_int( p, pNext, &p->vPath, SlackMax ); } return Vec_IntSize(&p->vPath); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_TimTrace( Sfm_Tim_t * p ) { Abc_Obj_t * pObj; int i, Delay = 0; Vec_Ptr_t * vNodes = Abc_NtkDfs( p->pNtk, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Sfm_TimNodeArrival( p, pObj ); Abc_NtkForEachCo( p->pNtk, pObj, i ) Delay = Abc_MaxInt( Delay, Sfm_TimArrMax(p, Abc_ObjFanin0(pObj)) ); Vec_IntFill( &p->vTimReqs, 2*Abc_NtkObjNumMax(p->pNtk), ABC_INFINITY ); Abc_NtkForEachCo( p->pNtk, pObj, i ) Sfm_TimSetReq( p, Abc_ObjFanin0(pObj), Delay ); Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i ) Sfm_TimNodeRequired( p, pObj ); Vec_PtrFree( vNodes ); return Delay; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sfm_Tim_t * Sfm_TimStart( Mio_Library_t * pLib, Scl_Con_t * pExt, Abc_Ntk_t * pNtk, int DeltaCrit ) { Sfm_Tim_t * p = ABC_CALLOC( Sfm_Tim_t, 1 ); p->pLib = pLib; p->pExt = pExt; p->pNtk = pNtk; Vec_IntFill( &p->vTimArrs, 3*Abc_NtkObjNumMax(pNtk), 0 ); Vec_IntFill( &p->vTimReqs, 3*Abc_NtkObjNumMax(pNtk), 0 ); p->Delay = Sfm_TimTrace( p ); assert( DeltaCrit > 0 && DeltaCrit < Scl_Flt2Int(1000.0) ); p->DeltaCrit = DeltaCrit; return p; } void Sfm_TimStop( Sfm_Tim_t * p ) { Vec_IntErase( &p->vTimArrs ); Vec_IntErase( &p->vTimReqs ); Vec_WecErase( &p->vLevels ); Vec_IntErase( &p->vPath ); Vec_WrdErase( &p->vSortData ); ABC_FREE( p ); } int Sfm_TimReadNtkDelay( Sfm_Tim_t * p ) { return p->Delay; } int Sfm_TimReadObjDelay( Sfm_Tim_t * p, int iObj ) { return Sfm_TimArrMaxId(p, iObj); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_TimTest( Abc_Ntk_t * pNtk ) { Mio_Library_t * pLib = (Mio_Library_t *)pNtk->pManFunc; Sfm_Tim_t * p = Sfm_TimStart( pLib, NULL, pNtk, 100 ); printf( "Max delay = %.2f. Path = %d (%d).\n", Scl_Int2Flt(p->Delay), Sfm_TimCriticalPath(p, 1), Abc_NtkNodeNum(p->pNtk) ); Sfm_TimStop( p ); } /**Function************************************************************* Synopsis [Levelized structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sfm_TimUpdateClean( Sfm_Tim_t * p ) { Vec_Int_t * vLevel; Abc_Obj_t * pObj; int i, k; Vec_WecForEachLevel( &p->vLevels, vLevel, i ) { Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k ) { assert( pObj->fMarkC == 1 ); pObj->fMarkC = 0; } Vec_IntClear( vLevel ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_TimUpdateTiming( Sfm_Tim_t * p, Vec_Int_t * vTimeNodes ) { assert( Vec_IntSize(vTimeNodes) > 0 && Vec_IntSize(vTimeNodes) <= 2 ); Vec_IntFillExtra( &p->vTimArrs, 2*Abc_NtkObjNumMax(p->pNtk), 0 ); Vec_IntFillExtra( &p->vTimReqs, 2*Abc_NtkObjNumMax(p->pNtk), 0 ); p->Delay = Sfm_TimTrace( p ); } /**Function************************************************************* Synopsis [Sort an array of nodes using their max arrival times.] Description [Returns the number of new divisor nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_TimSortArrayByArrival( Sfm_Tim_t * p, Vec_Int_t * vNodes, int iPivot ) { word Entry; int i, Id, Time, nDivNew = -1; int MaxDelay = ABC_INFINITY/2+Sfm_TimArrMaxId(p, iPivot); assert( p->DeltaCrit > 0 ); // collect nodes Vec_WrdClear( &p->vSortData ); Vec_IntForEachEntry( vNodes, Id, i ) { Time = Sfm_TimArrMaxId( p, Id ); assert( -ABC_INFINITY/2 < Time && Time < ABC_INFINITY/2 ); Vec_WrdPush( &p->vSortData, ((word)Id << 32) | (ABC_INFINITY/2+Time) ); } // sort nodes by delay Abc_QuickSort3( Vec_WrdArray(&p->vSortData), Vec_WrdSize(&p->vSortData), 0 ); // collect sorted nodes and find place where divisors end Vec_IntClear( vNodes ); Vec_WrdForEachEntry( &p->vSortData, Entry, i ) { Vec_IntPush( vNodes, (int)(Entry >> 32) ); if ( nDivNew == -1 && ((int)Entry) + p->DeltaCrit > MaxDelay ) nDivNew = i; } return nDivNew; } /**Function************************************************************* Synopsis [Priority of nodes to try remapping for delay.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_TimPriorityNodes( Sfm_Tim_t * p, Vec_Int_t * vCands, int Window ) { Vec_Int_t * vLevel; Abc_Obj_t * pObj; int i, k; assert( Window >= 0 && Window <= 100 ); // collect critical path Sfm_TimCriticalPath( p, Window ); // add nodes to the levelized structure Sfm_TimUpdateClean( p ); Abc_NtkForEachObjVec( &p->vPath, p->pNtk, pObj, i ) { assert( pObj->fMarkC == 0 ); pObj->fMarkC = 1; Vec_WecPush( &p->vLevels, Abc_ObjLevel(pObj), Abc_ObjId(pObj) ); } // prioritize nodes by expected gain Vec_WecSort( &p->vLevels, 0 ); Vec_IntClear( vCands ); Vec_WecForEachLevel( &p->vLevels, vLevel, i ) Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k ) if ( !pObj->fMarkA ) Vec_IntPush( vCands, Abc_ObjId(pObj) ); // printf( "Path = %5d Cand = %5d\n", Vec_IntSize(&p->vPath) ); return Vec_IntSize(vCands) > 0; } /**Function************************************************************* Synopsis [Returns 1 if node is relatively non-critical compared to the pivot.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_TimNodeIsNonCritical( Sfm_Tim_t * p, Abc_Obj_t * pPivot, Abc_Obj_t * pNode ) { return Sfm_TimArrMax(p, pNode) + p->DeltaCrit <= Sfm_TimArrMax(p, pPivot); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_TimEvalRemapping( Sfm_Tim_t * p, Vec_Int_t * vFanins, Vec_Int_t * vMap, Mio_Gate_t * pGate1, char * pFans1, Mio_Gate_t * pGate2, char * pFans2 ) { int TimeOut[2][2]; int * pTimesIn1[6], * pTimesIn2[6]; int i, nFanins1, nFanins2; // process the first gate nFanins1 = Mio_GateReadPinNum( pGate1 ); for ( i = 0; i < nFanins1; i++ ) pTimesIn1[i] = Sfm_TimArrId( p, Vec_IntEntry(vMap, Vec_IntEntry(vFanins, (int)pFans1[i])) ); Sfm_TimGateArrival( p, pGate1, pTimesIn1, TimeOut[0] ); if ( pGate2 == NULL ) return Abc_MaxInt(TimeOut[0][0], TimeOut[0][1]); // process the second gate nFanins2 = Mio_GateReadPinNum( pGate2 ); for ( i = 0; i < nFanins2; i++ ) if ( (int)pFans2[i] == 16 ) pTimesIn2[i] = TimeOut[0]; else pTimesIn2[i] = Sfm_TimArrId( p, Vec_IntEntry(vMap, Vec_IntEntry(vFanins, (int)pFans2[i])) ); Sfm_TimGateArrival( p, pGate2, pTimesIn2, TimeOut[1] ); return Abc_MaxInt(TimeOut[1][0], TimeOut[1][1]); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sfm/sfmWin.c000066400000000000000000000403301300674244400230320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sfmWin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based optimization using internal don't-cares.] Synopsis [Structural window computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sfmWin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sfmInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the MFFC size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_ObjRef_rec( Sfm_Ntk_t * p, int iObj ) { int i, iFanin, Value, Count; if ( Sfm_ObjIsPi(p, iObj) ) return 0; assert( Sfm_ObjIsNode(p, iObj) ); Value = Sfm_ObjRefIncrement(p, iObj); if ( Value > 1 ) return 0; assert( Value == 1 ); Count = 1; Sfm_ObjForEachFanin( p, iObj, iFanin, i ) Count += Sfm_ObjRef_rec( p, iFanin ); return Count; } int Sfm_ObjRef( Sfm_Ntk_t * p, int iObj ) { int i, iFanin, Count = 1; Sfm_ObjForEachFanin( p, iObj, iFanin, i ) Count += Sfm_ObjRef_rec( p, iFanin ); return Count; } int Sfm_ObjDeref_rec( Sfm_Ntk_t * p, int iObj ) { int i, iFanin, Value, Count; if ( Sfm_ObjIsPi(p, iObj) ) return 0; assert( Sfm_ObjIsNode(p, iObj) ); Value = Sfm_ObjRefDecrement(p, iObj); if ( Value > 0 ) return 0; assert( Value == 0 ); Count = 1; Sfm_ObjForEachFanin( p, iObj, iFanin, i ) Count += Sfm_ObjDeref_rec( p, iFanin ); return Count; } int Sfm_ObjDeref( Sfm_Ntk_t * p, int iObj ) { int i, iFanin, Count = 1; Sfm_ObjForEachFanin( p, iObj, iFanin, i ) Count += Sfm_ObjDeref_rec( p, iFanin ); return Count; } int Sfm_ObjMffcSize( Sfm_Ntk_t * p, int iObj ) { int Count1, Count2; if ( Sfm_ObjIsPi(p, iObj) ) return 0; if ( Sfm_ObjFanoutNum(p, iObj) != 1 ) return 0; assert( Sfm_ObjIsNode( p, iObj ) ); Count1 = Sfm_ObjDeref( p, iObj ); Count2 = Sfm_ObjRef( p, iObj ); assert( Count1 == Count2 ); return Count1; } /**Function************************************************************* Synopsis [Working with traversal IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sfm_NtkIncrementTravId( Sfm_Ntk_t * p ) { p->nTravIds++; } static inline void Sfm_ObjSetTravIdCurrent( Sfm_Ntk_t * p, int Id ) { Vec_IntWriteEntry( &p->vTravIds, Id, p->nTravIds ); } static inline int Sfm_ObjIsTravIdCurrent( Sfm_Ntk_t * p, int Id ) { return (Vec_IntEntry(&p->vTravIds, Id) == p->nTravIds); } static inline int Sfm_ObjIsTravIdPrevious( Sfm_Ntk_t * p, int Id ) { return (Vec_IntEntry(&p->vTravIds, Id) == p->nTravIds-1); } static inline void Sfm_NtkIncrementTravId2( Sfm_Ntk_t * p ) { p->nTravIds2++; } static inline void Sfm_ObjSetTravIdCurrent2( Sfm_Ntk_t * p, int Id ) { Vec_IntWriteEntry( &p->vTravIds2, Id, p->nTravIds2 ); } static inline int Sfm_ObjIsTravIdCurrent2( Sfm_Ntk_t * p, int Id ) { return (Vec_IntEntry(&p->vTravIds2, Id) == p->nTravIds2); } /**Function************************************************************* Synopsis [Collects used internal nodes in a topological order.] Description [Additionally considers objects in groups as a single object and collects them in a topological order together as single entity.] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_NtkDfs_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes, Vec_Wec_t * vGroups, Vec_Int_t * vGroupMap, Vec_Int_t * vBoxesLeft ) { int i, iFanin; if ( Sfm_ObjIsPi(p, iNode) ) return; if ( Sfm_ObjIsTravIdCurrent(p, iNode) ) return; if ( Vec_IntEntry(vGroupMap, iNode) >= 0 ) { int k, iGroup = Abc_Lit2Var( Vec_IntEntry(vGroupMap, iNode) ); Vec_Int_t * vGroup = Vec_WecEntry( vGroups, iGroup ); Vec_IntForEachEntry( vGroup, iNode, i ) assert( Sfm_ObjIsNode(p, iNode) ); Vec_IntForEachEntry( vGroup, iNode, i ) Sfm_ObjSetTravIdCurrent( p, iNode ); Vec_IntForEachEntry( vGroup, iNode, i ) Sfm_ObjForEachFanin( p, iNode, iFanin, k ) Sfm_NtkDfs_rec( p, iFanin, vNodes, vGroups, vGroupMap, vBoxesLeft ); Vec_IntForEachEntry( vGroup, iNode, i ) Vec_IntPush( vNodes, iNode ); Vec_IntPush( vBoxesLeft, iGroup ); } else { Sfm_ObjSetTravIdCurrent(p, iNode); Sfm_ObjForEachFanin( p, iNode, iFanin, i ) Sfm_NtkDfs_rec( p, iFanin, vNodes, vGroups, vGroupMap, vBoxesLeft ); Vec_IntPush( vNodes, iNode ); } } Vec_Int_t * Sfm_NtkDfs( Sfm_Ntk_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vGroupMap, Vec_Int_t * vBoxesLeft ) { Vec_Int_t * vNodes; int i; Vec_IntClear( vBoxesLeft ); vNodes = Vec_IntAlloc( p->nObjs ); Sfm_NtkIncrementTravId( p ); Sfm_NtkForEachPo( p, i ) Sfm_NtkDfs_rec( p, Sfm_ObjFanin(p, i, 0), vNodes, vGroups, vGroupMap, vBoxesLeft ); return vNodes; } /**Function************************************************************* Synopsis [Check if this fanout overlaps with TFI cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_NtkCheckOverlap_rec( Sfm_Ntk_t * p, int iThis, int iNode ) { int i, iFanin; if ( Sfm_ObjIsTravIdCurrent2(p, iThis) || iThis == iNode ) return 0; // if ( Sfm_ObjIsTravIdCurrent(p, iThis) ) if ( Sfm_ObjIsTravIdPrevious(p, iThis) ) return 1; Sfm_ObjSetTravIdCurrent2(p, iThis); Sfm_ObjForEachFanin( p, iThis, iFanin, i ) if ( Sfm_NtkCheckOverlap_rec(p, iFanin, iNode) ) return 1; return 0; } int Sfm_NtkCheckOverlap( Sfm_Ntk_t * p, int iFan, int iNode ) { Sfm_NtkIncrementTravId2( p ); return Sfm_NtkCheckOverlap_rec( p, iFan, iNode ); } /**Function************************************************************* Synopsis [Recursively collects roots of the window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sfm_NtkCheckRoot( Sfm_Ntk_t * p, int iNode, int nLevelMax ) { int i, iFanout; // the node is the root if one of the following is true: // (1) the node has more than fanouts than the limit or has no fanouts (should not happen in general) if ( Sfm_ObjFanoutNum(p, iNode) == 0 || Sfm_ObjFanoutNum(p, iNode) > p->pPars->nFanoutMax ) return 1; // (2) the node has CO fanouts // (3) the node has fanouts above the cutoff level Sfm_ObjForEachFanout( p, iNode, iFanout, i ) if ( Sfm_ObjIsPo(p, iFanout) || Sfm_ObjLevel(p, iFanout) > nLevelMax )//|| !Sfm_NtkCheckOverlap(p, iFanout, iNode) ) return 1; return 0; } void Sfm_NtkComputeRoots_rec( Sfm_Ntk_t * p, int iNode, int nLevelMax, Vec_Int_t * vRoots, Vec_Int_t * vTfo ) { int i, iFanout; assert( Sfm_ObjIsNode(p, iNode) ); if ( Sfm_ObjIsTravIdCurrent(p, iNode) ) return; Sfm_ObjSetTravIdCurrent(p, iNode); if ( iNode != p->iPivotNode ) Vec_IntPush( vTfo, iNode ); // check if the node should be the root if ( Sfm_NtkCheckRoot( p, iNode, nLevelMax ) ) Vec_IntPush( vRoots, iNode ); else // if not, explore its fanouts Sfm_ObjForEachFanout( p, iNode, iFanout, i ) Sfm_NtkComputeRoots_rec( p, iFanout, nLevelMax, vRoots, vTfo ); } /**Function************************************************************* Synopsis [Collects divisors of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sfm_NtkAddDivisors( Sfm_Ntk_t * p, int iNode, int nLevelMax ) { int i, iFanout; Sfm_ObjForEachFanout( p, iNode, iFanout, i ) { // skip some of the fanouts if the number is large if ( p->pPars->nFanoutMax && i > p->pPars->nFanoutMax ) return; // skip TFI nodes, PO nodes, or nodes with high logic level if ( Sfm_ObjIsTravIdCurrent(p, iFanout) || Sfm_ObjIsPo(p, iFanout) || Sfm_ObjLevel(p, iFanout) > nLevelMax ) continue; // handle single-input nodes if ( Sfm_ObjFaninNum(p, iFanout) == 1 ) Vec_IntPush( p->vDivs, iFanout ); // visit node for the first time else if ( !Sfm_ObjIsTravIdCurrent2(p, iFanout) ) { assert( Sfm_ObjFaninNum(p, iFanout) > 1 ); Sfm_ObjSetTravIdCurrent2( p, iFanout ); Sfm_ObjResetFaninCount( p, iFanout ); } // visit node again else if ( Sfm_ObjUpdateFaninCount(p, iFanout) == 0 ) Vec_IntPush( p->vDivs, iFanout ); } } /**Function************************************************************* Synopsis [Fixed object is useful when it has a non-fixed fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sfm_ObjIsUseful( Sfm_Ntk_t * p, int iNode ) { int i, iFanout; if ( !Sfm_ObjIsFixed(p, iNode) ) return 1; Sfm_ObjForEachFanout( p, iNode, iFanout, i ) if ( !Sfm_ObjIsFixed(p, iFanout) ) return 1; return 0; } /**Function************************************************************* Synopsis [Computes structural window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sfm_NtkCollectTfi_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes ) { int i, iFanin; if ( Sfm_ObjIsTravIdCurrent( p, iNode ) ) return 0; Sfm_ObjSetTravIdCurrent( p, iNode ); Sfm_ObjForEachFanin( p, iNode, iFanin, i ) if ( Sfm_NtkCollectTfi_rec( p, iFanin, vNodes ) ) return 1; Vec_IntPush( vNodes, iNode ); return p->pPars->nWinSizeMax && (Vec_IntSize(vNodes) > p->pPars->nWinSizeMax); } int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose ) { int i, k, iTemp; abctime clkDiv, clkWin = Abc_Clock(); assert( Sfm_ObjIsNode( p, iNode ) ); p->iPivotNode = iNode; Vec_IntClear( p->vNodes ); // internal Vec_IntClear( p->vDivs ); // divisors Vec_IntClear( p->vRoots ); // roots Vec_IntClear( p->vTfo ); // roots Vec_IntClear( p->vOrder ); // variable order // collect transitive fanin Sfm_NtkIncrementTravId( p ); if ( Sfm_NtkCollectTfi_rec( p, iNode, p->vNodes ) ) { p->nMaxDivs++; p->timeWin += Abc_Clock() - clkWin; return 0; } // create divisors clkDiv = Abc_Clock(); Vec_IntClear( p->vDivs ); Vec_IntAppend( p->vDivs, p->vNodes ); Vec_IntPop( p->vDivs ); // add non-topological divisors if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 ) { Sfm_NtkIncrementTravId2( p ); Vec_IntForEachEntry( p->vDivs, iTemp, i ) if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 ) // Sfm_NtkAddDivisors( p, iTemp, Sfm_ObjLevel(p, iNode) - 1 ); Sfm_NtkAddDivisors( p, iTemp, p->nLevelMax - Sfm_ObjLevelR(p, iNode) ); } if ( Vec_IntSize(p->vDivs) > p->pPars->nWinSizeMax ) { /* k = 0; Vec_IntForEachEntryStart( p->vDivs, iTemp, i, Vec_IntSize(p->vDivs) - p->pPars->nWinSizeMax ) Vec_IntWriteEntry( p->vDivs, k++, iTemp ); assert( k == p->pPars->nWinSizeMax ); */ Vec_IntShrink( p->vDivs, p->pPars->nWinSizeMax ); } assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax ); p->nMaxDivs += (int)(Vec_IntSize(p->vDivs) == p->pPars->nWinSizeMax); // remove node/fanins from divisors // mark fanins Sfm_NtkIncrementTravId2( p ); Sfm_ObjSetTravIdCurrent2( p, iNode ); Sfm_ObjForEachFanin( p, iNode, iTemp, i ) Sfm_ObjSetTravIdCurrent2( p, iTemp ); // compact divisors k = 0; Vec_IntForEachEntry( p->vDivs, iTemp, i ) if ( !Sfm_ObjIsTravIdCurrent2(p, iTemp) && Sfm_ObjIsUseful(p, iTemp) ) Vec_IntWriteEntry( p->vDivs, k++, iTemp ); Vec_IntShrink( p->vDivs, k ); assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax ); clkDiv = Abc_Clock() - clkDiv; p->timeDiv += clkDiv; p->nTotalDivs += Vec_IntSize(p->vDivs); // collect TFO and window roots if ( p->pPars->nTfoLevMax > 0 && !Sfm_NtkCheckRoot(p, iNode, Sfm_ObjLevel(p, iNode) + p->pPars->nTfoLevMax) ) { // explore transitive fanout Sfm_NtkIncrementTravId( p ); Sfm_NtkComputeRoots_rec( p, iNode, Sfm_ObjLevel(p, iNode) + p->pPars->nTfoLevMax, p->vRoots, p->vTfo ); assert( Vec_IntSize(p->vRoots) > 0 ); assert( Vec_IntSize(p->vTfo) > 0 ); // compute new leaves and nodes Sfm_NtkIncrementTravId( p ); Vec_IntForEachEntry( p->vRoots, iTemp, i ) if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) ) { Vec_IntClear( p->vRoots ); Vec_IntClear( p->vTfo ); Vec_IntClear( p->vOrder ); break; } if ( Vec_IntSize(p->vRoots) > 0 ) Vec_IntForEachEntry( p->vTfo, iTemp, i ) if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) ) { Vec_IntClear( p->vRoots ); Vec_IntClear( p->vTfo ); Vec_IntClear( p->vOrder ); break; } if ( Vec_IntSize(p->vRoots) > 0 ) Vec_IntForEachEntry( p->vDivs, iTemp, i ) if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) ) { Vec_IntClear( p->vRoots ); Vec_IntClear( p->vTfo ); Vec_IntClear( p->vOrder ); break; } } if ( Vec_IntSize(p->vOrder) == 0 ) { int Temp = p->pPars->nWinSizeMax; p->pPars->nWinSizeMax = 0; Sfm_NtkIncrementTravId( p ); Sfm_NtkCollectTfi_rec( p, iNode, p->vOrder ); Vec_IntForEachEntry( p->vDivs, iTemp, i ) Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ); p->pPars->nWinSizeMax = Temp; } // statistics p->timeWin += Abc_Clock() - clkWin - clkDiv; if ( !fVerbose ) return 1; // print stats about the window printf( "%6d : ", iNode ); printf( "Leaves = %5d. ", 0 ); printf( "Nodes = %5d. ", Vec_IntSize(p->vNodes) ); printf( "Roots = %5d. ", Vec_IntSize(p->vRoots) ); printf( "Divs = %5d. ", Vec_IntSize(p->vDivs) ); printf( "\n" ); return 1; } void Sfm_NtkWindowTest( Sfm_Ntk_t * p, int iNode ) { int i; Sfm_NtkForEachNode( p, i ) Sfm_NtkCreateWindow( p, i, 1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/000077500000000000000000000000001300674244400214265ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/module.make000066400000000000000000000003651300674244400235560ustar00rootroot00000000000000SRC += src/opt/sim/simMan.c \ src/opt/sim/simSeq.c \ src/opt/sim/simSupp.c \ src/opt/sim/simSwitch.c \ src/opt/sim/simSym.c \ src/opt/sim/simSymSat.c \ src/opt/sim/simSymSim.c \ src/opt/sim/simSymStr.c \ src/opt/sim/simUtils.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/sim.h000066400000000000000000000255411300674244400223760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sim.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Simulation package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: sim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__opt__sim__sim_h #define ABC__opt__sim__sim_h /* The ideas realized in this package are described in the paper: "Detecting Symmetries in Boolean Functions using Circuit Representation, Simulation, and Satisfiability". */ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Sym_Man_t_ Sym_Man_t; struct Sym_Man_t_ { // info about the network Abc_Ntk_t * pNtk; // the network Vec_Ptr_t * vNodes; // internal nodes in topological order int nInputs; int nOutputs; // internal simulation information int nSimWords; // the number of bits in simulation info Vec_Ptr_t * vSim; // simulation info // support information Vec_Ptr_t * vSuppFun; // bit representation Vec_Vec_t * vSupports; // integer representation // symmetry info for each output Vec_Ptr_t * vMatrSymms; // symmetric pairs Vec_Ptr_t * vMatrNonSymms; // non-symmetric pairs Vec_Int_t * vPairsTotal; // total pairs Vec_Int_t * vPairsSym; // symmetric pairs Vec_Int_t * vPairsNonSym; // non-symmetric pairs // temporary simulation info unsigned * uPatRand; unsigned * uPatCol; unsigned * uPatRow; // temporary Vec_Int_t * vVarsU; Vec_Int_t * vVarsV; int iOutput; int iVar1; int iVar2; int iVar1Old; int iVar2Old; // internal data structures int nSatRuns; int nSatRunsSat; int nSatRunsUnsat; // pairs int nPairsSymm; int nPairsSymmStr; int nPairsNonSymm; int nPairsRem; int nPairsTotal; // runtime statistics abctime timeStruct; abctime timeCount; abctime timeMatr; abctime timeSim; abctime timeFraig; abctime timeSat; abctime timeTotal; }; typedef struct Sim_Man_t_ Sim_Man_t; struct Sim_Man_t_ { // info about the network Abc_Ntk_t * pNtk; int nInputs; int nOutputs; int fLightweight; // internal simulation information int nSimBits; // the number of bits in simulation info int nSimWords; // the number of words in simulation info Vec_Ptr_t * vSim0; // simulation info 1 Vec_Ptr_t * vSim1; // simulation info 2 // support information int nSuppBits; // the number of bits in support info int nSuppWords; // the number of words in support info Vec_Ptr_t * vSuppStr; // structural supports Vec_Ptr_t * vSuppFun; // functional supports // simulation targets Vec_Vec_t * vSuppTargs; // support targets int iInput; // the input current processed // internal data structures Extra_MmFixed_t * pMmPat; Vec_Ptr_t * vFifo; Vec_Int_t * vDiffs; int nSatRuns; int nSatRunsSat; int nSatRunsUnsat; // runtime statistics abctime timeSim; abctime timeTrav; abctime timeFraig; abctime timeSat; abctime timeTotal; }; typedef struct Sim_Pat_t_ Sim_Pat_t; struct Sim_Pat_t_ { int Input; // the input which it has detected int Output; // the output for which it was collected unsigned * pData; // the simulation data }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define SIM_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) #define SIM_LAST_BITS(n) ((((n)&31) > 0)? (n)&31 : 32) #define SIM_MASK_FULL (0xFFFFFFFF) #define SIM_MASK_BEG(n) (SIM_MASK_FULL >> (32-n)) #define SIM_MASK_END(n) (SIM_MASK_FULL << (n)) #define SIM_SET_0_FROM(m,n) ((m) & ~SIM_MASK_BEG(n)) #define SIM_SET_1_FROM(m,n) ((m) | SIM_MASK_END(n)) // generating random unsigned (#define RAND_MAX 0x7fff) #define SIM_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) // macros to get hold of bits in a bit string #define Sim_SetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31))) #define Sim_XorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31))) #define Sim_HasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0) // macros to get hold of the support info #define Sim_SuppStrSetVar(vSupps,pNode,v) Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) #define Sim_SuppStrHasVar(vSupps,pNode,v) Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) #define Sim_SuppFunSetVar(vSupps,Output,v) Sim_SetBit((unsigned*)(vSupps)->pArray[Output],(v)) #define Sim_SuppFunHasVar(vSupps,Output,v) Sim_HasBit((unsigned*)(vSupps)->pArray[Output],(v)) #define Sim_SimInfoSetVar(vSupps,pNode,v) Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) #define Sim_SimInfoHasVar(vSupps,pNode,v) Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) #define Sim_SimInfoGet(vInfo,pNode) ((unsigned *)((vInfo)->pArray[(pNode)->Id])) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== simMan.c ==========================================================*/ extern Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose ); extern void Sym_ManStop( Sym_Man_t * p ); extern void Sym_ManPrintStats( Sym_Man_t * p ); extern Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight ); extern void Sim_ManStop( Sim_Man_t * p ); extern void Sim_ManPrintStats( Sim_Man_t * p ); extern Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p ); extern void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat ); /*=== simSeq.c ==========================================================*/ extern Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords ); extern Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel ); /*=== simSupp.c ==========================================================*/ extern Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk ); extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ); /*=== simSym.c ==========================================================*/ extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ); /*=== simSymSat.c ==========================================================*/ extern int Sim_SymmsGetPatternUsingSat( Sym_Man_t * p, unsigned * pPattern ); /*=== simSymStr.c ==========================================================*/ extern void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * vSuppFun ); /*=== simSymSim.c ==========================================================*/ extern void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPatRand, Vec_Ptr_t * vMatrsNonSym ); /*=== simUtil.c ==========================================================*/ extern Vec_Ptr_t * Sim_UtilInfoAlloc( int nSize, int nWords, int fClean ); extern void Sim_UtilInfoFree( Vec_Ptr_t * p ); extern void Sim_UtilInfoAdd( unsigned * pInfo1, unsigned * pInfo2, int nWords ); extern void Sim_UtilInfoDetectDiffs( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ); extern void Sim_UtilInfoDetectNews( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ); extern void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode ); extern int Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode ); extern void Sim_UtilSimulate( Sim_Man_t * p, int fFirst ); extern void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, int fType, int fType1, int fType2 ); extern void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset ); extern void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift ); extern int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct ); extern int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords ); extern Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords ); extern void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords ); extern void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords ); extern void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 ); extern int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords ); extern int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords ); extern int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords ); extern int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters ); extern void Sim_UtilCountPairsAll( Sym_Man_t * p ); extern int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simMan.c000066400000000000000000000227041300674244400230230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Simulation manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose ) { Sym_Man_t * p; int i, v; // start the manager p = ABC_ALLOC( Sym_Man_t, 1 ); memset( p, 0, sizeof(Sym_Man_t) ); p->pNtk = pNtk; p->vNodes = Abc_NtkDfs( pNtk, 0 ); p->nInputs = Abc_NtkCiNum(p->pNtk); p->nOutputs = Abc_NtkCoNum(p->pNtk); // internal simulation information p->nSimWords = SIM_NUM_WORDS(p->nInputs); p->vSim = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); // symmetry info for each output p->vMatrSymms = Vec_PtrStart( p->nOutputs ); p->vMatrNonSymms = Vec_PtrStart( p->nOutputs ); p->vPairsTotal = Vec_IntStart( p->nOutputs ); p->vPairsSym = Vec_IntStart( p->nOutputs ); p->vPairsNonSym = Vec_IntStart( p->nOutputs ); for ( i = 0; i < p->nOutputs; i++ ) { p->vMatrSymms->pArray[i] = Extra_BitMatrixStart( p->nInputs ); p->vMatrNonSymms->pArray[i] = Extra_BitMatrixStart( p->nInputs ); } // temporary patterns p->uPatRand = ABC_ALLOC( unsigned, p->nSimWords ); p->uPatCol = ABC_ALLOC( unsigned, p->nSimWords ); p->uPatRow = ABC_ALLOC( unsigned, p->nSimWords ); p->vVarsU = Vec_IntStart( 100 ); p->vVarsV = Vec_IntStart( 100 ); // compute supports p->vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose ); p->vSupports = Vec_VecStart( p->nOutputs ); for ( i = 0; i < p->nOutputs; i++ ) for ( v = 0; v < p->nInputs; v++ ) if ( Sim_SuppFunHasVar( p->vSuppFun, i, v ) ) Vec_VecPush( p->vSupports, i, (void *)(ABC_PTRUINT_T)v ); return p; } /**Function************************************************************* Synopsis [Stops the simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sym_ManStop( Sym_Man_t * p ) { int i; Sym_ManPrintStats( p ); if ( p->vSuppFun ) Sim_UtilInfoFree( p->vSuppFun ); if ( p->vSim ) Sim_UtilInfoFree( p->vSim ); if ( p->vNodes ) Vec_PtrFree( p->vNodes ); if ( p->vSupports ) Vec_VecFree( p->vSupports ); for ( i = 0; i < p->nOutputs; i++ ) { Extra_BitMatrixStop( (Extra_BitMat_t *)p->vMatrSymms->pArray[i] ); Extra_BitMatrixStop( (Extra_BitMat_t *)p->vMatrNonSymms->pArray[i] ); } Vec_IntFree( p->vVarsU ); Vec_IntFree( p->vVarsV ); Vec_PtrFree( p->vMatrSymms ); Vec_PtrFree( p->vMatrNonSymms ); Vec_IntFree( p->vPairsTotal ); Vec_IntFree( p->vPairsSym ); Vec_IntFree( p->vPairsNonSym ); ABC_FREE( p->uPatRand ); ABC_FREE( p->uPatCol ); ABC_FREE( p->uPatRow ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the manager statisticis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sym_ManPrintStats( Sym_Man_t * p ) { // printf( "Inputs = %5d. Outputs = %5d. Sim words = %5d.\n", // Abc_NtkCiNum(p->pNtk), Abc_NtkCoNum(p->pNtk), p->nSimWords ); printf( "Total symm = %8d.\n", p->nPairsSymm ); printf( "Structural symm = %8d.\n", p->nPairsSymmStr ); printf( "Total non-sym = %8d.\n", p->nPairsNonSymm ); printf( "Total var pairs = %8d.\n", p->nPairsTotal ); printf( "Sat runs SAT = %8d.\n", p->nSatRunsSat ); printf( "Sat runs UNSAT = %8d.\n", p->nSatRunsUnsat ); ABC_PRT( "Structural ", p->timeStruct ); ABC_PRT( "Simulation ", p->timeSim ); ABC_PRT( "Matrix ", p->timeMatr ); ABC_PRT( "Counting ", p->timeCount ); ABC_PRT( "Fraiging ", p->timeFraig ); ABC_PRT( "SAT ", p->timeSat ); ABC_PRT( "TOTAL ", p->timeTotal ); } /**Function************************************************************* Synopsis [Starts the simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight ) { Sim_Man_t * p; // start the manager p = ABC_ALLOC( Sim_Man_t, 1 ); memset( p, 0, sizeof(Sim_Man_t) ); p->pNtk = pNtk; p->nInputs = Abc_NtkCiNum(p->pNtk); p->nOutputs = Abc_NtkCoNum(p->pNtk); // internal simulation information p->nSimBits = 2048; p->nSimWords = SIM_NUM_WORDS(p->nSimBits); p->vSim0 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); p->fLightweight = fLightweight; if (!p->fLightweight) { p->vSim1 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); // support information p->nSuppBits = Abc_NtkCiNum(pNtk); p->nSuppWords = SIM_NUM_WORDS(p->nSuppBits); p->vSuppStr = Sim_ComputeStrSupp( pNtk ); p->vSuppFun = Sim_UtilInfoAlloc( Abc_NtkCoNum(p->pNtk), p->nSuppWords, 1 ); // other data p->pMmPat = Extra_MmFixedStart( sizeof(Sim_Pat_t) + p->nSuppWords * sizeof(unsigned) ); p->vFifo = Vec_PtrAlloc( 100 ); p->vDiffs = Vec_IntAlloc( 100 ); // allocate support targets (array of unresolved outputs for each input) p->vSuppTargs = Vec_VecStart( p->nInputs ); } return p; } /**Function************************************************************* Synopsis [Stops the simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_ManStop( Sim_Man_t * p ) { Sim_ManPrintStats( p ); if ( p->vSim0 ) Sim_UtilInfoFree( p->vSim0 ); if ( p->vSim1 ) Sim_UtilInfoFree( p->vSim1 ); if ( p->vSuppStr ) Sim_UtilInfoFree( p->vSuppStr ); // if ( p->vSuppFun ) Sim_UtilInfoFree( p->vSuppFun ); if ( p->vSuppTargs ) Vec_VecFree( p->vSuppTargs ); if ( p->pMmPat ) Extra_MmFixedStop( p->pMmPat ); if ( p->vFifo ) Vec_PtrFree( p->vFifo ); if ( p->vDiffs ) Vec_IntFree( p->vDiffs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the manager statisticis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_ManPrintStats( Sim_Man_t * p ) { // printf( "Inputs = %5d. Outputs = %5d. Sim words = %5d.\n", // Abc_NtkCiNum(p->pNtk), Abc_NtkCoNum(p->pNtk), p->nSimWords ); printf( "Total func supps = %8d.\n", Sim_UtilCountSuppSizes(p, 0) ); printf( "Total struct supps = %8d.\n", Sim_UtilCountSuppSizes(p, 1) ); printf( "Sat runs SAT = %8d.\n", p->nSatRunsSat ); printf( "Sat runs UNSAT = %8d.\n", p->nSatRunsUnsat ); ABC_PRT( "Simulation ", p->timeSim ); ABC_PRT( "Traversal ", p->timeTrav ); ABC_PRT( "Fraiging ", p->timeFraig ); ABC_PRT( "SAT ", p->timeSat ); ABC_PRT( "TOTAL ", p->timeTotal ); } /**Function************************************************************* Synopsis [Returns one simulation pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p ) { Sim_Pat_t * pPat; pPat = (Sim_Pat_t *)Extra_MmFixedEntryFetch( p->pMmPat ); pPat->Output = -1; pPat->pData = (unsigned *)((char *)pPat + sizeof(Sim_Pat_t)); memset( pPat->pData, 0, p->nSuppWords * sizeof(unsigned) ); return pPat; } /**Function************************************************************* Synopsis [Returns one simulation pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat ) { Extra_MmFixedEntryRecycle( p->pMmPat, (char *)pPat ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simSat.c000066400000000000000000000027601300674244400230370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Simulation to determine functional support.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simSeq.c000066400000000000000000000141101300674244400230300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simSeq.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Simulation for sequential circuits.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Simulates sequential circuit.] Description [Takes sequential circuit (pNtk). Simulates the given number (nFrames) of the circuit with the given number of machine words (nWords) of random simulation data, starting from the initial state. If the initial state of some latches is a don't-care, uses random input for that latch.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords ) { Vec_Ptr_t * vInfo; Abc_Obj_t * pNode; int i; assert( Abc_NtkIsStrash(pNtk) ); vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nWords * nFrames, 0 ); // set the constant data pNode = Abc_AigConst1(pNtk); Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames, 1 ); // set the random PI data Abc_NtkForEachPi( pNtk, pNode, i ) Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames ); // set the initial state data Abc_NtkForEachLatch( pNtk, pNode, i ) if ( Abc_LatchIsInit0(pNode) ) Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 0 ); else if ( Abc_LatchIsInit1(pNode) ) Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 1 ); else Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords ); // simulate the nodes for the given number of timeframes for ( i = 0; i < nFrames; i++ ) Sim_SimulateSeqFrame( vInfo, pNtk, i, nWords, (int)(i < nFrames-1) ); return vInfo; } /**Function************************************************************* Synopsis [Simulates sequential circuit.] Description [Takes sequential circuit (pNtk). Simulates the given number (nFrames) of the circuit with the given model. The model is assumed to contain values of PIs for each frame. The latches are initialized to the initial state. One word of data is simulated.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel ) { Vec_Ptr_t * vInfo; Abc_Obj_t * pNode; unsigned * pUnsigned; int i, k; vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nFrames, 0 ); // set the constant data pNode = Abc_AigConst1(pNtk); Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nFrames, 1 ); // set the random PI data Abc_NtkForEachPi( pNtk, pNode, i ) { pUnsigned = Sim_SimInfoGet(vInfo,pNode); for ( k = 0; k < nFrames; k++ ) pUnsigned[k] = pModel[k * Abc_NtkPiNum(pNtk) + i] ? ~((unsigned)0) : 0; } // set the initial state data Abc_NtkForEachLatch( pNtk, pNode, i ) { pUnsigned = Sim_SimInfoGet(vInfo,pNode); if ( Abc_LatchIsInit0(pNode) ) pUnsigned[0] = 0; else if ( Abc_LatchIsInit1(pNode) ) pUnsigned[0] = ~((unsigned)0); else pUnsigned[0] = SIM_RANDOM_UNSIGNED; } // simulate the nodes for the given number of timeframes for ( i = 0; i < nFrames; i++ ) Sim_SimulateSeqFrame( vInfo, pNtk, i, 1, (int)(i < nFrames-1) ); /* // print the simulated values for ( i = 0; i < nFrames; i++ ) { printf( "Frame %d : ", i+1 ); Abc_NtkForEachPi( pNtk, pNode, k ) printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); printf( " " ); Abc_NtkForEachLatch( pNtk, pNode, k ) printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); printf( " " ); Abc_NtkForEachPo( pNtk, pNode, k ) printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); printf( "\n" ); } printf( "\n" ); */ return vInfo; } /**Function************************************************************* Synopsis [Simulates one frame of sequential circuit.] Description [Assumes that the latches and POs are already initialized. In the end transfers the data to the latches of the next frame.] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer ) { Abc_Obj_t * pNode; int i; Abc_NtkForEachNode( pNtk, pNode, i ) Sim_UtilSimulateNodeOne( pNode, vInfo, nWords, iFrames * nWords ); Abc_NtkForEachPo( pNtk, pNode, i ) Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 0 ); if ( !fTransfer ) return; Abc_NtkForEachLatch( pNtk, pNode, i ) Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simSupp.c000066400000000000000000000474061300674244400232450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simSupp.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Simulation to determine functional support.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "proof/fraig/fraig.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Sim_ComputeSuppRound( Sim_Man_t * p, int fUseTargets ); static int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, int fUseTargets ); static void Sim_ComputeSuppSetTargets( Sim_Man_t * p ); static void Sim_UtilAssignRandom( Sim_Man_t * p ); static void Sim_UtilAssignFromFifo( Sim_Man_t * p ); static void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int nCounters ); static int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes structural supports.] Description [Supports are returned as an array of bit strings, one for each CO.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vSuppStr; Abc_Obj_t * pNode; unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; int nSuppWords, i, k; // allocate room for structural supports nSuppWords = SIM_NUM_WORDS( Abc_NtkCiNum(pNtk) ); vSuppStr = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSuppWords, 1 ); // assign the structural support to the PIs Abc_NtkForEachCi( pNtk, pNode, i ) Sim_SuppStrSetVar( vSuppStr, pNode, i ); // derive the structural supports of the internal nodes Abc_NtkForEachNode( pNtk, pNode, i ) { // if ( Abc_NodeIsConst(pNode) ) // continue; pSimmNode = (unsigned *)vSuppStr->pArray[ pNode->Id ]; pSimmNode1 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ]; pSimmNode2 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId1(pNode) ]; for ( k = 0; k < nSuppWords; k++ ) pSimmNode[k] = pSimmNode1[k] | pSimmNode2[k]; } // set the structural supports of the PO nodes Abc_NtkForEachCo( pNtk, pNode, i ) { pSimmNode = (unsigned *)vSuppStr->pArray[ pNode->Id ]; pSimmNode1 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ]; for ( k = 0; k < nSuppWords; k++ ) pSimmNode[k] = pSimmNode1[k]; } return vSuppStr; } /**Function************************************************************* Synopsis [Compute functional supports.] Description [Supports are returned as an array of bit strings, one for each CO.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ) { Sim_Man_t * p; Vec_Ptr_t * vResult; int nSolved, i; abctime clk = Abc_Clock(); srand( 0xABC ); // start the simulation manager p = Sim_ManStart( pNtk, 0 ); // compute functional support using one round of random simulation Sim_UtilAssignRandom( p ); Sim_ComputeSuppRound( p, 0 ); // set the support targets Sim_ComputeSuppSetTargets( p ); if ( fVerbose ) printf( "Number of support targets after simulation = %5d.\n", Vec_VecSizeSize(p->vSuppTargs) ); if ( Vec_VecSizeSize(p->vSuppTargs) == 0 ) goto exit; for ( i = 0; i < 1; i++ ) { // compute patterns using one round of random simulation Sim_UtilAssignRandom( p ); nSolved = Sim_ComputeSuppRound( p, 1 ); if ( Vec_VecSizeSize(p->vSuppTargs) == 0 ) goto exit; if ( fVerbose ) printf( "Targets = %5d. Solved = %5d. Fifo = %5d.\n", Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo) ); } // try to solve the support targets while ( Vec_VecSizeSize(p->vSuppTargs) > 0 ) { // solve targets until the first disproved one (which gives counter-example) Sim_SolveTargetsUsingSat( p, p->nSimWords/p->nSuppWords ); // compute additional functional support Sim_UtilAssignFromFifo( p ); nSolved = Sim_ComputeSuppRound( p, 1 ); if ( fVerbose ) printf( "Targets = %5d. Solved = %5d. Fifo = %5d. SAT runs = %3d.\n", Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo), p->nSatRuns ); } exit: p->timeTotal = Abc_Clock() - clk; vResult = p->vSuppFun; // p->vSuppFun = NULL; Sim_ManStop( p ); return vResult; } /**Function************************************************************* Synopsis [Computes functional support using one round of simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_ComputeSuppRound( Sim_Man_t * p, int fUseTargets ) { Vec_Ptr_t * vTargets; int i, Counter = 0; abctime clk; // perform one round of random simulation clk = Abc_Clock(); Sim_UtilSimulate( p, 0 ); p->timeSim += Abc_Clock() - clk; // iterate through the CIs and detect COs that depend on them for ( i = p->iInput; i < p->nInputs; i++ ) { vTargets = (Vec_Ptr_t *)p->vSuppTargs->pArray[i]; if ( fUseTargets && vTargets->nSize == 0 ) continue; Counter += Sim_ComputeSuppRoundNode( p, i, fUseTargets ); } return Counter; } /**Function************************************************************* Synopsis [Computes functional support for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, int fUseTargets ) { int fVerbose = 0; Sim_Pat_t * pPat; Vec_Ptr_t * vTargets; Vec_Vec_t * vNodesByLevel; Abc_Obj_t * pNodeCi, * pNode; int i, k, v, Output, LuckyPat, fType0, fType1; int Counter = 0; int fFirst = 1; abctime clk; // collect nodes by level in the TFO of the CI // this procedure does not collect the CIs and COs // but it increments TravId of the collected nodes and CIs/COs clk = Abc_Clock(); pNodeCi = Abc_NtkCi( p->pNtk, iNumCi ); vNodesByLevel = Abc_DfsLevelized( pNodeCi, 0 ); p->timeTrav += Abc_Clock() - clk; // complement the simulation info of the selected CI Sim_UtilInfoFlip( p, pNodeCi ); // simulate the levelized structure of nodes Vec_VecForEachEntry( Abc_Obj_t *, vNodesByLevel, pNode, i, k ) { fType0 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin0(pNode) ); fType1 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin1(pNode) ); clk = Abc_Clock(); Sim_UtilSimulateNode( p, pNode, 1, fType0, fType1 ); p->timeSim += Abc_Clock() - clk; } // set the simulation info of the affected COs if ( fUseTargets ) { vTargets = (Vec_Ptr_t *)p->vSuppTargs->pArray[iNumCi]; for ( i = vTargets->nSize - 1; i >= 0; i-- ) { // get the target output Output = (int)(ABC_PTRUINT_T)vTargets->pArray[i]; // get the target node pNode = Abc_ObjFanin0( Abc_NtkCo(p->pNtk, Output) ); // the output should be in the cone assert( Abc_NodeIsTravIdCurrent(pNode) ); // skip if the simulation info is equal if ( Sim_UtilInfoCompare( p, pNode ) ) continue; // otherwise, we solved a new target Vec_PtrRemove( vTargets, vTargets->pArray[i] ); if ( fVerbose ) printf( "(%d,%d) ", iNumCi, Output ); Counter++; // make sure this variable is not yet detected assert( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) ); // set this variable Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi ); // detect the differences in the simulation info Sim_UtilInfoDetectDiffs( (unsigned *)p->vSim0->pArray[pNode->Id], (unsigned *)p->vSim1->pArray[pNode->Id], p->nSimWords, p->vDiffs ); // create new patterns if ( !fFirst && p->vFifo->nSize > 1000 ) continue; Vec_IntForEachEntry( p->vDiffs, LuckyPat, k ) { // set the new pattern pPat = Sim_ManPatAlloc( p ); pPat->Input = iNumCi; pPat->Output = Output; Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) if ( Sim_SimInfoHasVar( p->vSim0, pNodeCi, LuckyPat ) ) Sim_SetBit( pPat->pData, v ); Vec_PtrPush( p->vFifo, pPat ); fFirst = 0; break; } } if ( fVerbose && Counter ) printf( "\n" ); } else { Abc_NtkForEachCo( p->pNtk, pNode, Output ) { if ( !Abc_NodeIsTravIdCurrent( pNode ) ) continue; if ( !Sim_UtilInfoCompare( p, Abc_ObjFanin0(pNode) ) ) { if ( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) ) { Counter++; Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi ); } } } } Vec_VecFree( vNodesByLevel ); return Counter; } /**Function************************************************************* Synopsis [Sets the simulation targets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_ComputeSuppSetTargets( Sim_Man_t * p ) { Abc_Obj_t * pNode; unsigned * pSuppStr, * pSuppFun; int i, k, Num; Abc_NtkForEachCo( p->pNtk, pNode, i ) { pSuppStr = (unsigned *)p->vSuppStr->pArray[pNode->Id]; pSuppFun = (unsigned *)p->vSuppFun->pArray[i]; // find vars in the structural support that are not in the functional support Sim_UtilInfoDetectNews( pSuppFun, pSuppStr, p->nSuppWords, p->vDiffs ); Vec_IntForEachEntry( p->vDiffs, Num, k ) Vec_VecPush( p->vSuppTargs, Num, (void *)(ABC_PTRUINT_T)i ); } } /**Function************************************************************* Synopsis [Assigns random simulation info to the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilAssignRandom( Sim_Man_t * p ) { Abc_Obj_t * pNode; unsigned * pSimInfo; int i, k; // assign the random/systematic simulation info to the PIs Abc_NtkForEachCi( p->pNtk, pNode, i ) { pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id]; for ( k = 0; k < p->nSimWords; k++ ) pSimInfo[k] = SIM_RANDOM_UNSIGNED; } } /**Function************************************************************* Synopsis [Sets the new patterns from fifo.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilAssignFromFifo( Sim_Man_t * p ) { int fUseOneWord = 0; Abc_Obj_t * pNode; Sim_Pat_t * pPat; unsigned * pSimInfo; int nWordsNew, iWord, iWordLim, i, w; int iBeg, iEnd; int Counter = 0; // go through the patterns and fill in the dist-1 minterms for each for ( iWord = 0; p->vFifo->nSize > 0; iWord = iWordLim ) { ++Counter; // get the pattern pPat = (Sim_Pat_t *)Vec_PtrPop( p->vFifo ); if ( fUseOneWord ) { // get the first word of the next series iWordLim = iWord + 1; // set the pattern for all PIs from iBit to iWord + p->nInputs iBeg = p->iInput; iEnd = Abc_MinInt( iBeg + 32, p->nInputs ); // for ( i = iBeg; i < iEnd; i++ ) Abc_NtkForEachCi( p->pNtk, pNode, i ) { pNode = Abc_NtkCi(p->pNtk,i); pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id]; if ( Sim_HasBit(pPat->pData, i) ) pSimInfo[iWord] = SIM_MASK_FULL; else pSimInfo[iWord] = 0; // flip one bit if ( i >= iBeg && i < iEnd ) Sim_XorBit( pSimInfo + iWord, i-iBeg ); } } else { // get the number of words for the remaining inputs nWordsNew = p->nSuppWords; // nWordsNew = SIM_NUM_WORDS( p->nInputs - p->iInput ); // get the first word of the next series iWordLim = (iWord + nWordsNew < p->nSimWords)? iWord + nWordsNew : p->nSimWords; // set the pattern for all CIs from iWord to iWord + nWordsNew Abc_NtkForEachCi( p->pNtk, pNode, i ) { pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id]; if ( Sim_HasBit(pPat->pData, i) ) { for ( w = iWord; w < iWordLim; w++ ) pSimInfo[w] = SIM_MASK_FULL; } else { for ( w = iWord; w < iWordLim; w++ ) pSimInfo[w] = 0; } Sim_XorBit( pSimInfo + iWord, i ); // flip one bit // if ( i >= p->iInput ) // Sim_XorBit( pSimInfo + iWord, i-p->iInput ); } } Sim_ManPatFree( p, pPat ); // stop if we ran out of room for patterns if ( iWordLim == p->nSimWords ) break; // if ( Counter == 1 ) // break; } } /**Function************************************************************* Synopsis [Get the given number of counter-examples using SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int Limit ) { Fraig_Params_t Params; Fraig_Man_t * pMan; Abc_Obj_t * pNodeCi; Abc_Ntk_t * pMiter; Sim_Pat_t * pPat; void * pEntry; int * pModel; int RetValue, Output, Input, k, v; int Counter = 0; abctime clk; p->nSatRuns = 0; // put targets into one array Vec_VecForEachEntryReverse( void *, p->vSuppTargs, pEntry, Input, k ) { p->nSatRuns++; Output = (int)(ABC_PTRUINT_T)pEntry; // set up the miter for the two cofactors of this output w.r.t. this input pMiter = Abc_NtkMiterForCofactors( p->pNtk, Output, Input, -1 ); // transform the miter into a fraig Fraig_ParamsSetDefault( &Params ); Params.nSeconds = ABC_INFINITY; Params.fInternal = 1; clk = Abc_Clock(); pMan = (Fraig_Man_t *)Abc_NtkToFraig( pMiter, &Params, 0, 0 ); p->timeFraig += Abc_Clock() - clk; clk = Abc_Clock(); Fraig_ManProveMiter( pMan ); p->timeSat += Abc_Clock() - clk; // analyze the result RetValue = Fraig_ManCheckMiter( pMan ); assert( RetValue >= 0 ); if ( RetValue == 1 ) // unsat { p->nSatRunsUnsat++; pModel = NULL; Vec_PtrRemove( (Vec_Ptr_t *)p->vSuppTargs->pArray[Input], pEntry ); } else // sat { p->nSatRunsSat++; pModel = Fraig_ManReadModel( pMan ); assert( pModel != NULL ); assert( Sim_SolveSuppModelVerify( p->pNtk, pModel, Input, Output ) ); //printf( "Solved by SAT (%d,%d).\n", Input, Output ); // set the new pattern pPat = Sim_ManPatAlloc( p ); pPat->Input = Input; pPat->Output = Output; Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) if ( pModel[v] ) Sim_SetBit( pPat->pData, v ); Vec_PtrPush( p->vFifo, pPat ); /* // set the new pattern pPat = Sim_ManPatAlloc( p ); pPat->Input = Input; pPat->Output = Output; Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) if ( pModel[v] ) Sim_SetBit( pPat->pData, v ); Sim_XorBit( pPat->pData, Input ); // add this bit in the opposite polarity Vec_PtrPush( p->vFifo, pPat ); */ Counter++; } // delete the fraig manager Fraig_ManFree( pMan ); // delete the miter Abc_NtkDelete( pMiter ); // makr the input, which we are processing p->iInput = Input; // stop when we found enough patterns // if ( Counter == Limit ) if ( Counter == 1 ) return; } } /**Function************************************************************* Synopsis [Saves the counter example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_NtkSimTwoPats_rec( Abc_Obj_t * pNode ) { int Value0, Value1; if ( Abc_NodeIsTravIdCurrent( pNode ) ) return (int)(ABC_PTRUINT_T)pNode->pCopy; Abc_NodeSetTravIdCurrent( pNode ); Value0 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin0(pNode) ); Value1 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin1(pNode) ); if ( Abc_ObjFaninC0(pNode) ) Value0 = ~Value0; if ( Abc_ObjFaninC1(pNode) ) Value1 = ~Value1; pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(Value0 & Value1); return Value0 & Value1; } /**Function************************************************************* Synopsis [Verifies that pModel proves the presence of Input in the support of Output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output ) { Abc_Obj_t * pNode; int RetValue, i; // set the PI values Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCi( pNtk, pNode, i ) { Abc_NodeSetTravIdCurrent( pNode ); if ( pNode == Abc_NtkCi(pNtk,Input) ) pNode->pCopy = (Abc_Obj_t *)1; else if ( pModel[i] == 1 ) pNode->pCopy = (Abc_Obj_t *)3; else pNode->pCopy = NULL; } // perform the traversal RetValue = 3 & Sim_NtkSimTwoPats_rec( Abc_ObjFanin0( Abc_NtkCo(pNtk,Output) ) ); // assert( RetValue == 1 || RetValue == 2 ); return RetValue == 1 || RetValue == 2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simSwitch.c000066400000000000000000000073251300674244400235530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simSwitch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Computes switching activity of nodes in the ABC network.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Sim_NodeSimulate( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ); static float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes switching activity using simulation.] Description [Computes switching activity, which is understood as the probability of switching under random simulation. Assigns the random simulation information at the CI and propagates it through the internal nodes of the AIG.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ) { Vec_Int_t * vSwitching; float * pSwitching; Vec_Ptr_t * vNodes; Vec_Ptr_t * vSimInfo; Abc_Obj_t * pNode; unsigned * pSimInfo; int nSimWords, i; // allocate space for simulation info of all nodes nSimWords = SIM_NUM_WORDS(nPatterns); vSimInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSimWords, 0 ); // assign the random simulation to the CIs vSwitching = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); pSwitching = (float *)vSwitching->pArray; Abc_NtkForEachCi( pNtk, pNode, i ) { pSimInfo = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id); Sim_UtilSetRandom( pSimInfo, nSimWords ); pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords ); } // simulate the internal nodes vNodes = Abc_AigDfs( pNtk, 1, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { pSimInfo = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id); Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords, 0 ); pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords ); } Vec_PtrFree( vNodes ); Sim_UtilInfoFree( vSimInfo ); return vSwitching; } /**Function************************************************************* Synopsis [Computes switching activity of one node.] Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] SideEffects [] SeeAlso [] ***********************************************************************/ float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ) { int nOnes, nTotal; nTotal = 32 * nSimWords; nOnes = Sim_UtilCountOnes( pSimInfo, nSimWords ); return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simSym.c000066400000000000000000000117271300674244400230630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simSym.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Simulation to determine two-variable symmetries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simSym.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes two variable symmetries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ) { Sym_Man_t * p; Vec_Ptr_t * vResult; int Result; int i; abctime clk, clkTotal = Abc_Clock(); srand( 0xABC ); // start the simulation manager p = Sym_ManStart( pNtk, fVerbose ); p->nPairsTotal = p->nPairsRem = Sim_UtilCountAllPairs( p->vSuppFun, p->nSimWords, p->vPairsTotal ); if ( fVerbose ) printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); // detect symmetries using circuit structure clk = Abc_Clock(); Sim_SymmsStructCompute( pNtk, p->vMatrSymms, p->vSuppFun ); p->timeStruct = Abc_Clock() - clk; Sim_UtilCountPairsAll( p ); p->nPairsSymmStr = p->nPairsSymm; if ( fVerbose ) printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); // detect symmetries using simulation for ( i = 1; i <= 1000; i++ ) { // simulate this pattern Sim_UtilSetRandom( p->uPatRand, p->nSimWords ); Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); if ( i % 50 != 0 ) continue; // check disjointness assert( Sim_UtilMatrsAreDisjoint( p ) ); // count the number of pairs Sim_UtilCountPairsAll( p ); if ( i % 500 != 0 ) continue; if ( fVerbose ) printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); } // detect symmetries using SAT for ( i = 1; Sim_SymmsGetPatternUsingSat( p, p->uPatRand ); i++ ) { // simulate this pattern in four polarities Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); Sim_XorBit( p->uPatRand, p->iVar1 ); Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); Sim_XorBit( p->uPatRand, p->iVar2 ); Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); Sim_XorBit( p->uPatRand, p->iVar1 ); Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); Sim_XorBit( p->uPatRand, p->iVar2 ); /* // try the previuos pair Sim_XorBit( p->uPatRand, p->iVar1Old ); Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); Sim_XorBit( p->uPatRand, p->iVar2Old ); Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); Sim_XorBit( p->uPatRand, p->iVar1Old ); Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); */ if ( i % 10 != 0 ) continue; // check disjointness assert( Sim_UtilMatrsAreDisjoint( p ) ); // count the number of pairs Sim_UtilCountPairsAll( p ); if ( i % 50 != 0 ) continue; if ( fVerbose ) printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); } // count the number of pairs Sim_UtilCountPairsAll( p ); if ( fVerbose ) printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); // Sim_UtilCountPairsAllPrint( p ); Result = p->nPairsSymm; vResult = p->vMatrSymms; p->timeTotal = Abc_Clock() - clkTotal; // p->vMatrSymms = NULL; Sym_ManStop( p ); return Result; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simSymSat.c000066400000000000000000000157221300674244400235320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simSymSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Satisfiability to determine two variable symmetries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simSymSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "proof/fraig/fraig.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Tries to prove the remaining pairs using SAT.] Description [Continues to prove as long as it encounters symmetric pairs. Returns 1 if a non-symmetric pair is found (which gives a counter-example). Returns 0 if it finishes considering all pairs for all outputs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_SymmsGetPatternUsingSat( Sym_Man_t * p, unsigned * pPattern ) { Vec_Int_t * vSupport; Extra_BitMat_t * pMatSym, * pMatNonSym; int Index1, Index2, Index3, IndexU, IndexV; int v, u, i, k, b, out; // iterate through outputs for ( out = p->iOutput; out < p->nOutputs; out++ ) { pMatSym = (Extra_BitMat_t *)Vec_PtrEntry( p->vMatrSymms, out ); pMatNonSym = (Extra_BitMat_t *)Vec_PtrEntry( p->vMatrNonSymms, out ); // go through the remaining variable pairs vSupport = Vec_VecEntryInt( p->vSupports, out ); Vec_IntForEachEntry( vSupport, v, Index1 ) Vec_IntForEachEntryStart( vSupport, u, Index2, Index1+1 ) { if ( Extra_BitMatrixLookup1( pMatSym, v, u ) || Extra_BitMatrixLookup1( pMatNonSym, v, u ) ) continue; p->nSatRuns++; // collect the support variables that are symmetric with u and v Vec_IntClear( p->vVarsU ); Vec_IntClear( p->vVarsV ); Vec_IntForEachEntry( vSupport, b, Index3 ) { if ( Extra_BitMatrixLookup1( pMatSym, u, b ) ) Vec_IntPush( p->vVarsU, b ); if ( Extra_BitMatrixLookup1( pMatSym, v, b ) ) Vec_IntPush( p->vVarsV, b ); } if ( Sim_SymmsSatProveOne( p, out, v, u, pPattern ) ) { // update the symmetric variable info p->nSatRunsUnsat++; Vec_IntForEachEntry( p->vVarsU, i, IndexU ) Vec_IntForEachEntry( p->vVarsV, k, IndexV ) { Extra_BitMatrixInsert1( pMatSym, i, k ); // Theorem 1 Extra_BitMatrixInsert2( pMatSym, i, k ); // Theorem 1 Extra_BitMatrixOrTwo( pMatNonSym, i, k ); // Theorem 2 } } else { // update the assymmetric variable info p->nSatRunsSat++; Vec_IntForEachEntry( p->vVarsU, i, IndexU ) Vec_IntForEachEntry( p->vVarsV, k, IndexV ) { Extra_BitMatrixInsert1( pMatNonSym, i, k ); // Theorem 3 Extra_BitMatrixInsert2( pMatNonSym, i, k ); // Theorem 3 } // remember the out p->iOutput = out; p->iVar1Old = p->iVar1; p->iVar2Old = p->iVar2; p->iVar1 = v; p->iVar2 = u; return 1; } } // make sure that the symmetry matrix contains only cliques assert( Extra_BitMatrixIsClique( pMatSym ) ); } // mark that we finished all outputs p->iOutput = p->nOutputs; return 0; } /**Function************************************************************* Synopsis [Returns 1 if the variables are symmetric; 0 otherwise.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern ) { Fraig_Params_t Params; Fraig_Man_t * pMan; Abc_Ntk_t * pMiter; int RetValue, i; abctime clk; int * pModel; // get the miter for this problem pMiter = Abc_NtkMiterForCofactors( p->pNtk, Out, Var1, Var2 ); // transform the miter into a fraig Fraig_ParamsSetDefault( &Params ); Params.fInternal = 1; Params.nPatsRand = 512; Params.nPatsDyna = 512; Params.nSeconds = ABC_INFINITY; clk = Abc_Clock(); pMan = (Fraig_Man_t *)Abc_NtkToFraig( pMiter, &Params, 0, 0 ); p->timeFraig += Abc_Clock() - clk; clk = Abc_Clock(); Fraig_ManProveMiter( pMan ); p->timeSat += Abc_Clock() - clk; // analyze the result RetValue = Fraig_ManCheckMiter( pMan ); // assert( RetValue >= 0 ); // save the pattern if ( RetValue == 0 ) { // get the pattern pModel = Fraig_ManReadModel( pMan ); assert( pModel != NULL ); //printf( "Disproved by SAT: out = %d pair = (%d, %d)\n", Out, Var1, Var2 ); // transfer the model into the pattern for ( i = 0; i < p->nSimWords; i++ ) pPattern[i] = 0; for ( i = 0; i < p->nInputs; i++ ) if ( pModel[i] ) Sim_SetBit( pPattern, i ); // make sure these variables have the same value (1) Sim_SetBit( pPattern, Var1 ); Sim_SetBit( pPattern, Var2 ); } else if ( RetValue == -1 ) { // this should never happen; if it happens, such is life // we are conservative and assume that there is no symmetry //printf( "STRANGE THING: out = %d %s pair = (%d %s, %d %s)\n", // Out, Abc_ObjName(Abc_NtkCo(p->pNtk,Out)), // Var1, Abc_ObjName(Abc_NtkCi(p->pNtk,Var1)), // Var2, Abc_ObjName(Abc_NtkCi(p->pNtk,Var2)) ); memset( pPattern, 0, sizeof(unsigned) * p->nSimWords ); RetValue = 0; } // delete the fraig manager Fraig_ManFree( pMan ); // delete the miter Abc_NtkDelete( pMiter ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simSymSim.c000066400000000000000000000132161300674244400235270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simSymSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Simulation to determine two-variable symmetries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simSymSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat ); static void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Detects non-symmetric pairs using one pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPat, Vec_Ptr_t * vMatrsNonSym ) { Abc_Obj_t * pNode; int i, nPairsTotal, nPairsSym, nPairsNonSym; abctime clk; // create the simulation matrix Sim_SymmsCreateSquare( p, pPat ); // simulate each node in the DFS order clk = Abc_Clock(); Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pNode, i ) { // if ( Abc_NodeIsConst(pNode) ) // continue; Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords, 0 ); } p->timeSim += Abc_Clock() - clk; // collect info into the CO matrices clk = Abc_Clock(); Abc_NtkForEachCo( p->pNtk, pNode, i ) { pNode = Abc_ObjFanin0(pNode); // if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) // continue; nPairsTotal = Vec_IntEntry(p->vPairsTotal, i); nPairsSym = Vec_IntEntry(p->vPairsSym, i); nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i); assert( nPairsTotal >= nPairsSym + nPairsNonSym ); if ( nPairsTotal == nPairsSym + nPairsNonSym ) continue; Sim_SymmsDeriveInfo( p, pPat, pNode, vMatrsNonSym, i ); } p->timeMatr += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Creates the square matrix of simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat ) { unsigned * pSimInfo; Abc_Obj_t * pNode; int i, w; // for each PI var copy the pattern Abc_NtkForEachCi( p->pNtk, pNode, i ) { pSimInfo = (unsigned *)Vec_PtrEntry( p->vSim, pNode->Id ); if ( Sim_HasBit(pPat, i) ) { for ( w = 0; w < p->nSimWords; w++ ) pSimInfo[w] = SIM_MASK_FULL; } else { for ( w = 0; w < p->nSimWords; w++ ) pSimInfo[w] = 0; } // flip one bit Sim_XorBit( pSimInfo, i ); } } /**Function************************************************************* Synopsis [Transfers the info to the POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output ) { Extra_BitMat_t * pMat; Vec_Int_t * vSupport; unsigned * pSupport; unsigned * pSimInfo; int i, w, Index; // get the matrix, the support, and the simulation info pMat = (Extra_BitMat_t *)Vec_PtrEntry( vMatrsNonSym, Output ); vSupport = Vec_VecEntryInt( p->vSupports, Output ); pSupport = (unsigned *)Vec_PtrEntry( p->vSuppFun, Output ); pSimInfo = (unsigned *)Vec_PtrEntry( p->vSim, pNode->Id ); // generate vectors A1 and A2 for ( w = 0; w < p->nSimWords; w++ ) { p->uPatCol[w] = pSupport[w] & pPat[w] & pSimInfo[w]; p->uPatRow[w] = pSupport[w] & pPat[w] & ~pSimInfo[w]; } // add two dimensions Vec_IntForEachEntry( vSupport, i, Index ) if ( Sim_HasBit( p->uPatCol, i ) ) Extra_BitMatrixOr( pMat, i, p->uPatRow ); // add two dimensions Vec_IntForEachEntry( vSupport, i, Index ) if ( Sim_HasBit( p->uPatRow, i ) ) Extra_BitMatrixOr( pMat, i, p->uPatCol ); // generate vectors B1 and B2 for ( w = 0; w < p->nSimWords; w++ ) { p->uPatCol[w] = pSupport[w] & ~pPat[w] & pSimInfo[w]; p->uPatRow[w] = pSupport[w] & ~pPat[w] & ~pSimInfo[w]; } // add two dimensions Vec_IntForEachEntry( vSupport, i, Index ) if ( Sim_HasBit( p->uPatCol, i ) ) Extra_BitMatrixOr( pMat, i, p->uPatRow ); // add two dimensions Vec_IntForEachEntry( vSupport, i, Index ) if ( Sim_HasBit( p->uPatRow, i ) ) Extra_BitMatrixOr( pMat, i, p->uPatCol ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simSymStr.c000066400000000000000000000364241300674244400235550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simSymStr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Structural detection of symmetries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simSymStr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define SIM_READ_SYMMS(pNode) ((Vec_Int_t *)pNode->pCopy) #define SIM_SET_SYMMS(pNode,vVect) (pNode->pCopy = (Abc_Obj_t *)(vVect)) static void Sim_SymmsStructComputeOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int * pMap ); static void Sim_SymmsBalanceCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); static void Sim_SymmsPartitionNodes( Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesPis0, Vec_Ptr_t * vNodesPis1, Vec_Ptr_t * vNodesOther ); static void Sim_SymmsAppendFromGroup( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesPi, Vec_Ptr_t * vNodesOther, Vec_Int_t * vSymms, int * pMap ); static void Sim_SymmsAppendFromNode( Abc_Ntk_t * pNtk, Vec_Int_t * vSymms0, Vec_Ptr_t * vNodesOther, Vec_Ptr_t * vNodesPi0, Vec_Ptr_t * vNodesPi1, Vec_Int_t * vSymms, int * pMap ); static int Sim_SymmsIsCompatibleWithNodes( Abc_Ntk_t * pNtk, unsigned uSymm, Vec_Ptr_t * vNodesOther, int * pMap ); static int Sim_SymmsIsCompatibleWithGroup( unsigned uSymm, Vec_Ptr_t * vNodesPi, int * pMap ); static void Sim_SymmsPrint( Vec_Int_t * vSymms ); static void Sim_SymmsTrans( Vec_Int_t * vSymms ); static void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, unsigned * pSupport ); static int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes symmetries for a single output function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * vSuppFun ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pTemp; int * pMap, i; assert( Abc_NtkCiNum(pNtk) + 10 < (1<<16) ); // get the structural support pNtk->vSupps = Sim_ComputeStrSupp( pNtk ); // set elementary info for the CIs Abc_NtkForEachCi( pNtk, pTemp, i ) SIM_SET_SYMMS( pTemp, Vec_IntAlloc(0) ); // create the map of CI ids into their numbers pMap = Sim_SymmsCreateMap( pNtk ); // collect the nodes in the TFI cone of this output vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pTemp, i ) { // if ( Abc_NodeIsConst(pTemp) ) // continue; Sim_SymmsStructComputeOne( pNtk, pTemp, pMap ); } // collect the results for the COs; Abc_NtkForEachCo( pNtk, pTemp, i ) { //printf( "Output %d:\n", i ); pTemp = Abc_ObjFanin0(pTemp); if ( Abc_ObjIsCi(pTemp) || Abc_AigNodeIsConst(pTemp) ) continue; Sim_SymmsTransferToMatrix( (Extra_BitMat_t *)Vec_PtrEntry(vMatrs, i), SIM_READ_SYMMS(pTemp), (unsigned *)Vec_PtrEntry(vSuppFun, i) ); } // clean the intermediate results Sim_UtilInfoFree( pNtk->vSupps ); pNtk->vSupps = NULL; Abc_NtkForEachCi( pNtk, pTemp, i ) Vec_IntFree( SIM_READ_SYMMS(pTemp) ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pTemp, i ) // if ( !Abc_NodeIsConst(pTemp) ) Vec_IntFree( SIM_READ_SYMMS(pTemp) ); Vec_PtrFree( vNodes ); ABC_FREE( pMap ); } /**Function************************************************************* Synopsis [Recursively computes symmetries. ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsStructComputeOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int * pMap ) { Vec_Ptr_t * vNodes, * vNodesPi0, * vNodesPi1, * vNodesOther; Vec_Int_t * vSymms; Abc_Obj_t * pTemp; int i; // allocate the temporary arrays vNodes = Vec_PtrAlloc( 10 ); vNodesPi0 = Vec_PtrAlloc( 10 ); vNodesPi1 = Vec_PtrAlloc( 10 ); vNodesOther = Vec_PtrAlloc( 10 ); // collect the fanins of the implication supergate Sim_SymmsBalanceCollect_rec( pNode, vNodes ); // sort the nodes in the implication supergate Sim_SymmsPartitionNodes( vNodes, vNodesPi0, vNodesPi1, vNodesOther ); // start the resulting set vSymms = Vec_IntAlloc( 10 ); // generate symmetries from the groups Sim_SymmsAppendFromGroup( pNtk, vNodesPi0, vNodesOther, vSymms, pMap ); Sim_SymmsAppendFromGroup( pNtk, vNodesPi1, vNodesOther, vSymms, pMap ); // add symmetries from other inputs for ( i = 0; i < vNodesOther->nSize; i++ ) { pTemp = Abc_ObjRegular((Abc_Obj_t *)vNodesOther->pArray[i]); Sim_SymmsAppendFromNode( pNtk, SIM_READ_SYMMS(pTemp), vNodesOther, vNodesPi0, vNodesPi1, vSymms, pMap ); } Vec_PtrFree( vNodes ); Vec_PtrFree( vNodesPi0 ); Vec_PtrFree( vNodesPi1 ); Vec_PtrFree( vNodesOther ); // set the symmetry at the node SIM_SET_SYMMS( pNode, vSymms ); } /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsBalanceCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { // if the new node is complemented, another gate begins if ( Abc_ObjIsComplement(pNode) ) { Vec_PtrPushUnique( vNodes, pNode ); return; } // if pNew is the PI node, return if ( Abc_ObjIsCi(pNode) ) { Vec_PtrPushUnique( vNodes, pNode ); return; } // go through the branches Sim_SymmsBalanceCollect_rec( Abc_ObjChild0(pNode), vNodes ); Sim_SymmsBalanceCollect_rec( Abc_ObjChild1(pNode), vNodes ); } /**Function************************************************************* Synopsis [Divides PI variables into groups.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsPartitionNodes( Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesPis0, Vec_Ptr_t * vNodesPis1, Vec_Ptr_t * vNodesOther ) { Abc_Obj_t * pNode; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( !Abc_ObjIsCi(Abc_ObjRegular(pNode)) ) Vec_PtrPush( vNodesOther, pNode ); else if ( Abc_ObjIsComplement(pNode) ) Vec_PtrPush( vNodesPis0, pNode ); else Vec_PtrPush( vNodesPis1, pNode ); } } /**Function************************************************************* Synopsis [Makes the product of two partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsAppendFromGroup( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesPi, Vec_Ptr_t * vNodesOther, Vec_Int_t * vSymms, int * pMap ) { Abc_Obj_t * pNode1, * pNode2; unsigned uSymm; int i, k; if ( vNodesPi->nSize == 0 ) return; // go through the pairs for ( i = 0; i < vNodesPi->nSize; i++ ) for ( k = i+1; k < vNodesPi->nSize; k++ ) { // get the two PI nodes pNode1 = Abc_ObjRegular((Abc_Obj_t *)vNodesPi->pArray[i]); pNode2 = Abc_ObjRegular((Abc_Obj_t *)vNodesPi->pArray[k]); assert( pMap[pNode1->Id] != pMap[pNode2->Id] ); assert( pMap[pNode1->Id] >= 0 ); assert( pMap[pNode2->Id] >= 0 ); // generate symmetry if ( pMap[pNode1->Id] < pMap[pNode2->Id] ) uSymm = ((pMap[pNode1->Id] << 16) | pMap[pNode2->Id]); else uSymm = ((pMap[pNode2->Id] << 16) | pMap[pNode1->Id]); // check if symmetry belongs if ( Sim_SymmsIsCompatibleWithNodes( pNtk, uSymm, vNodesOther, pMap ) ) Vec_IntPushUnique( vSymms, (int)uSymm ); } } /**Function************************************************************* Synopsis [Add the filters symmetries from the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsAppendFromNode( Abc_Ntk_t * pNtk, Vec_Int_t * vSymms0, Vec_Ptr_t * vNodesOther, Vec_Ptr_t * vNodesPi0, Vec_Ptr_t * vNodesPi1, Vec_Int_t * vSymms, int * pMap ) { unsigned uSymm; int i; if ( vSymms0->nSize == 0 ) return; // go through the pairs for ( i = 0; i < vSymms0->nSize; i++ ) { uSymm = (unsigned)vSymms0->pArray[i]; // check if symmetry belongs if ( Sim_SymmsIsCompatibleWithNodes( pNtk, uSymm, vNodesOther, pMap ) && Sim_SymmsIsCompatibleWithGroup( uSymm, vNodesPi0, pMap ) && Sim_SymmsIsCompatibleWithGroup( uSymm, vNodesPi1, pMap ) ) Vec_IntPushUnique( vSymms, (int)uSymm ); } } /**Function************************************************************* Synopsis [Returns 1 if symmetry is compatible with the group of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_SymmsIsCompatibleWithNodes( Abc_Ntk_t * pNtk, unsigned uSymm, Vec_Ptr_t * vNodesOther, int * pMap ) { Vec_Int_t * vSymmsNode; Abc_Obj_t * pNode; int i, s, Ind1, Ind2, fIsVar1, fIsVar2; if ( vNodesOther->nSize == 0 ) return 1; // get the indices of the PI variables Ind1 = (uSymm & 0xffff); Ind2 = (uSymm >> 16); // go through the nodes // if they do not belong to a support, it is okay // if one belongs, the other does not belong, quit // if they belong, but are not part of symmetry, quit for ( i = 0; i < vNodesOther->nSize; i++ ) { pNode = Abc_ObjRegular((Abc_Obj_t *)vNodesOther->pArray[i]); fIsVar1 = Sim_SuppStrHasVar( pNtk->vSupps, pNode, Ind1 ); fIsVar2 = Sim_SuppStrHasVar( pNtk->vSupps, pNode, Ind2 ); if ( !fIsVar1 && !fIsVar2 ) continue; if ( fIsVar1 ^ fIsVar2 ) return 0; // both belong // check if there is a symmetry vSymmsNode = SIM_READ_SYMMS( pNode ); for ( s = 0; s < vSymmsNode->nSize; s++ ) if ( uSymm == (unsigned)vSymmsNode->pArray[s] ) break; if ( s == vSymmsNode->nSize ) return 0; } return 1; } /**Function************************************************************* Synopsis [Returns 1 if symmetry is compatible with the group of PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_SymmsIsCompatibleWithGroup( unsigned uSymm, Vec_Ptr_t * vNodesPi, int * pMap ) { Abc_Obj_t * pNode; int i, Ind1, Ind2, fHasVar1, fHasVar2; if ( vNodesPi->nSize == 0 ) return 1; // get the indices of the PI variables Ind1 = (uSymm & 0xffff); Ind2 = (uSymm >> 16); // go through the PI nodes fHasVar1 = fHasVar2 = 0; for ( i = 0; i < vNodesPi->nSize; i++ ) { pNode = Abc_ObjRegular((Abc_Obj_t *)vNodesPi->pArray[i]); if ( pMap[pNode->Id] == Ind1 ) fHasVar1 = 1; else if ( pMap[pNode->Id] == Ind2 ) fHasVar2 = 1; } return fHasVar1 == fHasVar2; } /**Function************************************************************* Synopsis [Improvements due to transitivity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsTrans( Vec_Int_t * vSymms ) { unsigned uSymm, uSymma, uSymmr; int i, Ind1, Ind2; int k, Ind1a, Ind2a; int j; int nTrans = 0; for ( i = 0; i < vSymms->nSize; i++ ) { uSymm = (unsigned)vSymms->pArray[i]; Ind1 = (uSymm & 0xffff); Ind2 = (uSymm >> 16); // find other symmetries that have Ind1 for ( k = i+1; k < vSymms->nSize; k++ ) { uSymma = (unsigned)vSymms->pArray[k]; if ( uSymma == uSymm ) continue; Ind1a = (uSymma & 0xffff); Ind2a = (uSymma >> 16); if ( Ind1a == Ind1 ) { // find the symmetry (Ind2,Ind2a) if ( Ind2 < Ind2a ) uSymmr = ((Ind2 << 16) | Ind2a); else uSymmr = ((Ind2a << 16) | Ind2); for ( j = 0; j < vSymms->nSize; j++ ) if ( uSymmr == (unsigned)vSymms->pArray[j] ) break; if ( j == vSymms->nSize ) nTrans++; } } } printf( "Trans = %d.\n", nTrans ); } /**Function************************************************************* Synopsis [Transfers from the vector to the matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, unsigned * pSupport ) { int i, Ind1, Ind2, nInputs; unsigned uSymm; // add diagonal elements nInputs = Extra_BitMatrixReadSize( pMatSymm ); for ( i = 0; i < nInputs; i++ ) Extra_BitMatrixInsert1( pMatSymm, i, i ); // add non-diagonal elements for ( i = 0; i < vSymms->nSize; i++ ) { uSymm = (unsigned)vSymms->pArray[i]; Ind1 = (uSymm & 0xffff); Ind2 = (uSymm >> 16); //printf( "%d,%d ", Ind1, Ind2 ); // skip variables that are not in the true support assert( Sim_HasBit(pSupport, Ind1) == Sim_HasBit(pSupport, Ind2) ); if ( !Sim_HasBit(pSupport, Ind1) || !Sim_HasBit(pSupport, Ind2) ) continue; Extra_BitMatrixInsert1( pMatSymm, Ind1, Ind2 ); Extra_BitMatrixInsert2( pMatSymm, Ind1, Ind2 ); } } /**Function************************************************************* Synopsis [Mapping of indices into numbers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk ) { int * pMap; Abc_Obj_t * pNode; int i; pMap = ABC_ALLOC( int, Abc_NtkObjNumMax(pNtk) ); for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ ) pMap[i] = -1; Abc_NtkForEachCi( pNtk, pNode, i ) pMap[pNode->Id] = i; return pMap; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/opt/sim/simUtils.c000066400000000000000000000511061300674244400234060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [simUtils.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Various simulation utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "sim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates simulation information for all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Sim_UtilInfoAlloc( int nSize, int nWords, int fClean ) { Vec_Ptr_t * vInfo; int i; assert( nSize > 0 && nWords > 0 ); vInfo = Vec_PtrAlloc( nSize ); vInfo->pArray[0] = ABC_ALLOC( unsigned, nSize * nWords ); if ( fClean ) memset( vInfo->pArray[0], 0, sizeof(unsigned) * nSize * nWords ); for ( i = 1; i < nSize; i++ ) vInfo->pArray[i] = ((unsigned *)vInfo->pArray[i-1]) + nWords; vInfo->nSize = nSize; return vInfo; } /**Function************************************************************* Synopsis [Allocates simulation information for all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilInfoFree( Vec_Ptr_t * p ) { ABC_FREE( p->pArray[0] ); Vec_PtrFree( p ); } /**Function************************************************************* Synopsis [Adds the second supp-info the first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilInfoAdd( unsigned * pInfo1, unsigned * pInfo2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) pInfo1[w] |= pInfo2[w]; } /**Function************************************************************* Synopsis [Returns the positions where pInfo2 is 1 while pInfo1 is 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilInfoDetectDiffs( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ) { int w, b; unsigned uMask; vDiffs->nSize = 0; for ( w = 0; w < nWords; w++ ) if ( (uMask = (pInfo2[w] ^ pInfo1[w])) ) for ( b = 0; b < 32; b++ ) if ( uMask & (1 << b) ) Vec_IntPush( vDiffs, 32*w + b ); } /**Function************************************************************* Synopsis [Returns the positions where pInfo2 is 1 while pInfo1 is 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilInfoDetectNews( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ) { int w, b; unsigned uMask; vDiffs->nSize = 0; for ( w = 0; w < nWords; w++ ) if ( (uMask = (pInfo2[w] & ~pInfo1[w])) ) for ( b = 0; b < 32; b++ ) if ( uMask & (1 << b) ) Vec_IntPush( vDiffs, 32*w + b ); } /**Function************************************************************* Synopsis [Flips the simulation info of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode ) { unsigned * pSimInfo1, * pSimInfo2; int k; pSimInfo1 = (unsigned *)p->vSim0->pArray[pNode->Id]; pSimInfo2 = (unsigned *)p->vSim1->pArray[pNode->Id]; for ( k = 0; k < p->nSimWords; k++ ) pSimInfo2[k] = ~pSimInfo1[k]; } /**Function************************************************************* Synopsis [Returns 1 if the simulation infos are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode ) { unsigned * pSimInfo1, * pSimInfo2; int k; pSimInfo1 = (unsigned *)p->vSim0->pArray[pNode->Id]; pSimInfo2 = (unsigned *)p->vSim1->pArray[pNode->Id]; for ( k = 0; k < p->nSimWords; k++ ) if ( pSimInfo2[k] != pSimInfo1[k] ) return 0; return 1; } /**Function************************************************************* Synopsis [Simulates the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilSimulate( Sim_Man_t * p, int fType ) { Abc_Obj_t * pNode; int i; // simulate the internal nodes Abc_NtkForEachNode( p->pNtk, pNode, i ) Sim_UtilSimulateNode( p, pNode, fType, fType, fType ); // assign simulation info of the CO nodes Abc_NtkForEachCo( p->pNtk, pNode, i ) Sim_UtilSimulateNode( p, pNode, fType, fType, fType ); } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, int fType, int fType1, int fType2 ) { unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; int k, fComp1, fComp2; // simulate the internal nodes if ( Abc_ObjIsNode(pNode) ) { if ( fType ) pSimmNode = (unsigned *)p->vSim1->pArray[ pNode->Id ]; else pSimmNode = (unsigned *)p->vSim0->pArray[ pNode->Id ]; if ( fType1 ) pSimmNode1 = (unsigned *)p->vSim1->pArray[ Abc_ObjFaninId0(pNode) ]; else pSimmNode1 = (unsigned *)p->vSim0->pArray[ Abc_ObjFaninId0(pNode) ]; if ( fType2 ) pSimmNode2 = (unsigned *)p->vSim1->pArray[ Abc_ObjFaninId1(pNode) ]; else pSimmNode2 = (unsigned *)p->vSim0->pArray[ Abc_ObjFaninId1(pNode) ]; fComp1 = Abc_ObjFaninC0(pNode); fComp2 = Abc_ObjFaninC1(pNode); if ( fComp1 && fComp2 ) for ( k = 0; k < p->nSimWords; k++ ) pSimmNode[k] = ~pSimmNode1[k] & ~pSimmNode2[k]; else if ( fComp1 && !fComp2 ) for ( k = 0; k < p->nSimWords; k++ ) pSimmNode[k] = ~pSimmNode1[k] & pSimmNode2[k]; else if ( !fComp1 && fComp2 ) for ( k = 0; k < p->nSimWords; k++ ) pSimmNode[k] = pSimmNode1[k] & ~pSimmNode2[k]; else // if ( fComp1 && fComp2 ) for ( k = 0; k < p->nSimWords; k++ ) pSimmNode[k] = pSimmNode1[k] & pSimmNode2[k]; } else { assert( Abc_ObjFaninNum(pNode) == 1 ); if ( fType ) pSimmNode = (unsigned *)p->vSim1->pArray[ pNode->Id ]; else pSimmNode = (unsigned *)p->vSim0->pArray[ pNode->Id ]; if ( fType1 ) pSimmNode1 = (unsigned *)p->vSim1->pArray[ Abc_ObjFaninId0(pNode) ]; else pSimmNode1 = (unsigned *)p->vSim0->pArray[ Abc_ObjFaninId0(pNode) ]; fComp1 = Abc_ObjFaninC0(pNode); if ( fComp1 ) for ( k = 0; k < p->nSimWords; k++ ) pSimmNode[k] = ~pSimmNode1[k]; else for ( k = 0; k < p->nSimWords; k++ ) pSimmNode[k] = pSimmNode1[k]; } } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset ) { unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; int k, fComp1, fComp2; // simulate the internal nodes assert( Abc_ObjIsNode(pNode) ); pSimmNode = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id); pSimmNode1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); pSimmNode2 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); pSimmNode += nOffset; pSimmNode1 += nOffset; pSimmNode2 += nOffset; fComp1 = Abc_ObjFaninC0(pNode); fComp2 = Abc_ObjFaninC1(pNode); if ( fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pSimmNode[k] = ~pSimmNode1[k] & ~pSimmNode2[k]; else if ( fComp1 && !fComp2 ) for ( k = 0; k < nSimWords; k++ ) pSimmNode[k] = ~pSimmNode1[k] & pSimmNode2[k]; else if ( !fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pSimmNode[k] = pSimmNode1[k] & ~pSimmNode2[k]; else // if ( fComp1 && fComp2 ) for ( k = 0; k < nSimWords; k++ ) pSimmNode[k] = pSimmNode1[k] & pSimmNode2[k]; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift ) { unsigned * pSimmNode, * pSimmNode1; int k, fComp1; // simulate the internal nodes assert( Abc_ObjIsCo(pNode) ); pSimmNode = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id); pSimmNode1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); pSimmNode += nOffset + (fShift > 0)*nSimWords; pSimmNode1 += nOffset; fComp1 = Abc_ObjFaninC0(pNode); if ( fComp1 ) for ( k = 0; k < nSimWords; k++ ) pSimmNode[k] = ~pSimmNode1[k]; else for ( k = 0; k < nSimWords; k++ ) pSimmNode[k] = pSimmNode1[k]; } /**Function************************************************************* Synopsis [Returns 1 if the simulation infos are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct ) { Abc_Obj_t * pNode, * pNodeCi; int i, v, Counter; Counter = 0; if ( fStruct ) { Abc_NtkForEachCo( p->pNtk, pNode, i ) Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) Counter += Sim_SuppStrHasVar( p->vSuppStr, pNode, v ); } else { Abc_NtkForEachCo( p->pNtk, pNode, i ) Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) Counter += Sim_SuppFunHasVar( p->vSuppFun, i, v ); } return Counter; } /**Function************************************************************* Synopsis [Counts the number of 1's in the bitstring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords ) { unsigned char * pBytes; int nOnes, nBytes, i; pBytes = (unsigned char *)pSimInfo; nBytes = 4 * nSimWords; nOnes = 0; for ( i = 0; i < nBytes; i++ ) nOnes += bit_count[ pBytes[i] ]; return nOnes; } /**Function************************************************************* Synopsis [Counts the number of 1's in the bitstring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords ) { Vec_Int_t * vCounters; unsigned * pSimInfo; int i; vCounters = Vec_IntStart( Vec_PtrSize(vInfo) ); Vec_PtrForEachEntry( unsigned *, vInfo, pSimInfo, i ) Vec_IntWriteEntry( vCounters, i, Sim_UtilCountOnes(pSimInfo, nSimWords) ); return vCounters; } /**Function************************************************************* Synopsis [Returns random patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords ) { int k; for ( k = 0; k < nSimWords; k++ ) pPatRand[k] = SIM_RANDOM_UNSIGNED; } /**Function************************************************************* Synopsis [Returns complemented patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords ) { int k; for ( k = 0; k < nSimWords; k++ ) pPatRand[k] = ~pPatRand[k]; } /**Function************************************************************* Synopsis [Returns constant patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 ) { int k; for ( k = 0; k < nSimWords; k++ ) pPatRand[k] = 0; if ( fConst1 ) Sim_UtilSetCompl( pPatRand, nSimWords ); } /**Function************************************************************* Synopsis [Returns 1 if equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords ) { int k; for ( k = 0; k < nSimWords; k++ ) if ( pPats1[k] != pPats2[k] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if Node1 implies Node2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords ) { int k; for ( k = 0; k < nSimWords; k++ ) if ( pPats1[k] & ~pPats2[k] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if Node1 v Node2 is always true.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords ) { int k; for ( k = 0; k < nSimWords; k++ ) if ( ~pPats1[k] & ~pPats2[k] ) return 0; return 1; } /**Function************************************************************* Synopsis [Counts the total number of pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters ) { unsigned * pSupp; int Counter, nOnes, nPairs, i; Counter = 0; Vec_PtrForEachEntry( unsigned *, vSuppFun, pSupp, i ) { nOnes = Sim_UtilCountOnes( pSupp, nSimWords ); nPairs = nOnes * (nOnes - 1) / 2; Vec_IntWriteEntry( vCounters, i, nPairs ); Counter += nPairs; } return Counter; } /**Function************************************************************* Synopsis [Counts the number of entries in the array of matrices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilCountPairsOne( Extra_BitMat_t * pMat, Vec_Int_t * vSupport ) { int i, k, Index1, Index2; int Counter = 0; // int Counter2; Vec_IntForEachEntry( vSupport, i, Index1 ) Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 ) Counter += Extra_BitMatrixLookup1( pMat, i, k ); // Counter2 = Extra_BitMatrixCountOnesUpper(pMat); // assert( Counter == Counter2 ); return Counter; } /**Function************************************************************* Synopsis [Counts the number of entries in the array of matrices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilCountPairsOnePrint( Extra_BitMat_t * pMat, Vec_Int_t * vSupport ) { int i, k, Index1, Index2; Vec_IntForEachEntry( vSupport, i, Index1 ) Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 ) if ( Extra_BitMatrixLookup1( pMat, i, k ) ) printf( "(%d,%d) ", i, k ); return 0; } /**Function************************************************************* Synopsis [Counts the number of entries in the array of matrices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilCountPairsAllPrint( Sym_Man_t * p ) { int i; abctime clk; clk = Abc_Clock(); for ( i = 0; i < p->nOutputs; i++ ) { printf( "Output %2d :", i ); Sim_UtilCountPairsOnePrint( (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntryInt(p->vSupports, i) ); printf( "\n" ); } p->timeCount += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Counts the number of entries in the array of matrices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sim_UtilCountPairsAll( Sym_Man_t * p ) { int nPairsTotal, nPairsSym, nPairsNonSym, i; abctime clk; clk = Abc_Clock(); p->nPairsSymm = 0; p->nPairsNonSymm = 0; for ( i = 0; i < p->nOutputs; i++ ) { nPairsTotal = Vec_IntEntry(p->vPairsTotal, i); nPairsSym = Vec_IntEntry(p->vPairsSym, i); nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i); assert( nPairsTotal >= nPairsSym + nPairsNonSym ); if ( nPairsTotal == nPairsSym + nPairsNonSym ) { p->nPairsSymm += nPairsSym; p->nPairsNonSymm += nPairsNonSym; continue; } nPairsSym = Sim_UtilCountPairsOne( (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntryInt(p->vSupports, i) ); nPairsNonSym = Sim_UtilCountPairsOne( (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrNonSymms,i), Vec_VecEntryInt(p->vSupports, i) ); assert( nPairsTotal >= nPairsSym + nPairsNonSym ); Vec_IntWriteEntry( p->vPairsSym, i, nPairsSym ); Vec_IntWriteEntry( p->vPairsNonSym, i, nPairsNonSym ); p->nPairsSymm += nPairsSym; p->nPairsNonSymm += nPairsNonSym; // printf( "%d ", nPairsTotal - nPairsSym - nPairsNonSym ); } //printf( "\n" ); p->nPairsRem = p->nPairsTotal-p->nPairsSymm-p->nPairsNonSymm; p->timeCount += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p ) { int i; for ( i = 0; i < p->nOutputs; i++ ) if ( !Extra_BitMatrixIsDisjoint( (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrSymms,i), (Extra_BitMat_t *)Vec_PtrEntry(p->vMatrNonSymms,i) ) ) return 0; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/000077500000000000000000000000001300674244400210175ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/000077500000000000000000000000001300674244400221035ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/Makefile000066400000000000000000000011611300674244400235420ustar00rootroot00000000000000TARGETS = place_test BookshelfView.class CFLAGS = -g -pedantic -Wall STATIC_LIBS = libhmetis.a DYNAMIC_LIBS = -lm OBJECTS = place_test.o place_qpsolver.o place_base.o place_pads.o place_genqp.o place_gordian.o \ place_partition.o place_legalize.o place_bin.o # For hMetis free code, uncomment the following lines # # CFLAGS = -g -pedantic -Wall -DNO_HMETIS # STATIC_LIBS = all: $(TARGETS) %.o: %.c *.h gcc $(CFLAGS) -c -o $@ $< place_test: $(OBJECTS) gcc *.o $(STATIC_LIBS) $(DYNAMIC_LIBS) -o place_test BookshelfView.class: BookshelfView.java javac BookshelfView.java clean: rm -rf *.o place_test *.class *~ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/README000066400000000000000000000030511300674244400227620ustar00rootroot00000000000000/*===================================================================*/ // // GORDIAN-like placement package // // Aaron P. Hurst (ahurst@eecs.berkeley.edu) // Addl code from Philip Chong (pchong@cadence.com) // hMetis partitioner (www.cs.umn.edu/~metis) // /*===================================================================*/ 1. Requirements An i386 Linux system (though others will certainly work with some tweaks). A standard ANSI C development platform. The following are optional, but useful: - hMetis partitioner. This can be obtained from (www.cs.umn.edu/~metis) Place (links to) the files "libhmetis.a" and "libhtmetis.h" in this directory. Otherwise, #define NO_HMETIS in the file "place_gordian.h" - Java SDK, if compiling BookshelfView is desired. - Perl, if additional script utilities are desired. 2. Descriptions of contents: place_base.h contains the basic data structures and "external" API. place_gordian.h contains the "internal" API and configuration options. There are also several utilities: i) place_test Reads a netlist description in GSRC Bookshelf format, performs global placement, and rewrites the placement file. An example usage: ./place_test ac97_emap.nodes ac97_emap.nets ac97_emap.pl ii) BookshelfView A simple Java GUI to view the resulting placements. It has been tested with Java 5 and 6. Usage: java BookshelfView ac97_emap.nodes ac97_emap.pl iii) hpwl A perl script to print the half-perimeter wirelength of a placement. Usage: ./hpwl ac97_emap.nets ac97_emal.pl berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/hpwl000066400000000000000000000022401300674244400227760ustar00rootroot00000000000000#! /usr/bin/perl $netsfile = shift; $plfile = shift; # ------------------------------ read placement open FILE, $plfile; while () { chop; if (/(\w+)\s+([\-\d\.]+)\s+([\-\d\.]+)\s+\:/) { $loc{$1} = "$2 $3"; } } close FILE; open FILE, $netsfile; while () { chop; $net = $2 if /NetDegree\s+\:\s+(\d+)\s+(\w+)/; if (/(\w+)\s+(\w+)\s+\:/) { $netconn{$net} .= "$1 "; $cellconn{$1} .= "$net "; } } close FILE; # ----------------------------- compute HPWL $hpwl = 0; foreach $net (keys %netconn) { @conns = split ' ',$netconn{$net}; $min_x = $min_y = 1e12; $max_x = $max_y = -1e12; foreach $cell (@conns) { if (!exists $loc{$cell}) { print "WARNING: Unknown cell location: $cell\n"; } else { ($x, $y) = split ' ',$loc{$cell}; $min_x = $x if $x < $min_x; $min_y = $y if $y < $min_y; $max_x = $x if $x > $max_x; $max_y = $y if $y > $max_y; } } if ($min_x eq 1e12 or $min_y eq 1e12 or $max_x eq -1e12 or $max_y eq -1e12) { print "WARNING: Unbounded box\n"; } else { $hpwl = $hpwl + $max_x - $min_x + $max_y - $min_y; } } print "HPWL = "; printf "%e",$hpwl; print "\n"; berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/libhmetis.h000066400000000000000000000012541300674244400242360ustar00rootroot00000000000000// A. Hurst ahurst@eecs.berkeley.edu #ifndef ABC__phys__place__libhmetis_h #define ABC__phys__place__libhmetis_h ABC_NAMESPACE_HEADER_START static void HMETIS_PartRecursive(int nvtxs, int nhedges, int *vwgts, int *eptr, int *eind, int *hewgts, int nparts, int nbfactor, int *options, int *part, int *edgecnt ) {} //; static void HMETIS_PartKway(int nvtxs, int nhedges, int *vwgts, int *eptr, int *eind, int *hewgts, int nparts, int nbfactor, int *options, int *part, int *edgecnt ) {} //; ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/module.make000066400000000000000000000005401300674244400242260ustar00rootroot00000000000000SRC += src/phys/place/place_base.c \ src/phys/place/place_bin.c \ src/phys/place/place_genqp.c \ src/phys/place/place_gordian.c \ src/phys/place/place_legalize.c \ src/phys/place/place_pads.c \ src/phys/place/place_partition.c \ src/phys/place/place_qpsolver.c \ src/phys/place/place_io.c \ src/phys/place/place_inc.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_base.c000066400000000000000000000233371300674244400243350ustar00rootroot00000000000000/*===================================================================*/ // // place_base.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include "place_base.h" #include "place_gordian.h" ABC_NAMESPACE_IMPL_START // -------------------------------------------------------------------- // Global variables // // -------------------------------------------------------------------- int g_place_numCells = 0; int g_place_numNets = 0; float g_place_rowHeight = 1.0; Rect g_place_coreBounds; Rect g_place_padBounds; ConcreteCell **g_place_concreteCells = NULL; int g_place_concreteCellsSize = 0; ConcreteNet **g_place_concreteNets = NULL; int g_place_concreteNetsSize = 0; // -------------------------------------------------------------------- // getNetBBox() // /// \brief Returns the bounding box of a net. // // -------------------------------------------------------------------- Rect getNetBBox(const ConcreteNet *net) { int t; Rect r; assert(net); r.x = r.y = INT_MAX; r.w = r.h = -INT_MAX; for(t=0; tm_numTerms; t++) { r.x = net->m_terms[t]->m_x < r.x ? net->m_terms[t]->m_x : r.x; r.y = net->m_terms[t]->m_y < r.y ? net->m_terms[t]->m_y : r.y; r.w = net->m_terms[t]->m_x > r.w ? net->m_terms[t]->m_x : r.w; r.h = net->m_terms[t]->m_y > r.h ? net->m_terms[t]->m_y : r.h; } r.w -= r.x; r.h -= r.y; return r; } // -------------------------------------------------------------------- // getNetWirelength() // /// \brief Returns the half-perimeter wirelength of a net. // // -------------------------------------------------------------------- float getNetWirelength(const ConcreteNet *net) { Rect r; assert(net); r = getNetBBox(net); return r.w+r.h; } // -------------------------------------------------------------------- // getTotalWirelength() // /// \brief Returns the total HPWL of all nets. // // -------------------------------------------------------------------- float getTotalWirelength() { float r = 0; int n; for(n=0; nm_parent->m_width*cell->m_parent->m_height; } // -------------------------------------------------------------------- // addConcreteNet() // /// \brief Adds a net to the placement database. /// /// The net object must already be allocated and the ID must be set /// appropriately. // // -------------------------------------------------------------------- void addConcreteNet(ConcreteNet *net) { assert(net); assert(net->m_id >= 0); if (net->m_id >= g_place_concreteNetsSize) { g_place_concreteNetsSize = (net->m_id > g_place_concreteNetsSize ? net->m_id : g_place_concreteNetsSize); g_place_concreteNetsSize *= 1.5; g_place_concreteNetsSize += 20; g_place_concreteNets = (ConcreteNet**)realloc(g_place_concreteNets, sizeof(ConcreteNet*)*g_place_concreteNetsSize); assert(g_place_concreteNets); } if (net->m_id >= g_place_numNets) { memset(&(g_place_concreteNets[g_place_numNets]), 0, sizeof(ConcreteNet*)*(net->m_id+1-g_place_numNets)); g_place_numNets = net->m_id+1; assert(g_place_numNets <= g_place_concreteNetsSize); } g_place_concreteNets[net->m_id] = net; } // -------------------------------------------------------------------- // delConcreteNet() // /// Does not deallocate memory. // -------------------------------------------------------------------- void delConcreteNet(ConcreteNet *net) { assert(net); g_place_concreteNets[net->m_id] = 0; while(!g_place_concreteNets[g_place_numNets-1]) g_place_numNets--; } // -------------------------------------------------------------------- // addConcreteCell() // /// The cell object must already be allocated and the ID must be set /// appropriately. // // -------------------------------------------------------------------- void addConcreteCell(ConcreteCell *cell) { assert(cell); assert(cell->m_id >= 0); if (cell->m_id >= g_place_concreteCellsSize) { g_place_concreteCellsSize = (cell->m_id > g_place_concreteCellsSize ? cell->m_id : g_place_concreteCellsSize); g_place_concreteCellsSize *= 1.5; g_place_concreteCellsSize += 20; g_place_concreteCells = (ConcreteCell**)realloc(g_place_concreteCells, sizeof(ConcreteCell*)*g_place_concreteCellsSize); assert(g_place_concreteCells); } if (cell->m_id >= g_place_numCells) { memset(&(g_place_concreteCells[g_place_numCells]), 0, sizeof(ConcreteCell*)*(cell->m_id+1-g_place_numCells)); g_place_numCells = cell->m_id+1; } g_place_concreteCells[cell->m_id] = cell; } // -------------------------------------------------------------------- // delCellFromPartition() // // -------------------------------------------------------------------- void delCellFromPartition(ConcreteCell *cell, Partition *p) { int c; bool found = false; assert(cell); assert(p); for(c=0; cm_numMembers; c++) if (p->m_members[c] == cell) { p->m_members[c] = 0; p->m_area -= getCellArea(cell); found = true; break; } if (!found) return; if (!p->m_leaf) { delCellFromPartition(cell, p->m_sub1); delCellFromPartition(cell, p->m_sub2); } } // -------------------------------------------------------------------- // delConcreteCell() // /// \brief Removes a cell from the placement database. /// /// Does not deallocate memory. /// /// Important: does not modify nets that may point to this /// cell. If these are connections are not removed, segmentation faults /// and other nasty errors will occur. // // -------------------------------------------------------------------- void delConcreteCell(ConcreteCell *cell) { assert(cell); g_place_concreteCells[cell->m_id] = 0; while(!g_place_concreteCells[g_place_numCells-1]) g_place_numCells--; if (g_place_rootPartition) delCellFromPartition(cell, g_place_rootPartition); } // -------------------------------------------------------------------- // netSortByX... // /// \brief Sorts nets by position of one of its corners. // /// These are for use with qsort(). /// /// Can tolerate pointers to NULL objects. /// // -------------------------------------------------------------------- int netSortByL(const void *a, const void *b) { const ConcreteNet *pa = *(const ConcreteNet **)a; const ConcreteNet *pb = *(const ConcreteNet **)b; Rect ba, bb; if (!pa && !pb) return 0; else if (!pa) return -1; else if (!pb) return 1; ba = getNetBBox(pa), bb = getNetBBox(pb); if (ba.x < bb.x) return -1; if (ba.x > bb.x) return 1; return 0; } int netSortByR(const void *a, const void *b) { const ConcreteNet *pa = *(const ConcreteNet **)a; const ConcreteNet *pb = *(const ConcreteNet **)b; Rect ba, bb; if (!pa && !pb) return 0; else if (!pa) return -1; else if (!pb) return 1; ba = getNetBBox(pa), bb = getNetBBox(pb); if (ba.x + ba.w < bb.x + bb.w) return -1; if (ba.x + ba.w > bb.x + bb.w) return 1; return 0; } int netSortByB(const void *a, const void *b) { const ConcreteNet *pa = *(const ConcreteNet **)a; const ConcreteNet *pb = *(const ConcreteNet **)b; Rect ba, bb; if (!pa && !pb) return 0; else if (!pa) return -1; else if (!pb) return 1; ba = getNetBBox(pa), bb = getNetBBox(pb); if (ba.y + ba.h < bb.y + bb.h) return -1; if (ba.y + ba.h > bb.y + bb.h) return 1; return 0; } int netSortByT(const void *a, const void *b) { const ConcreteNet *pa = *(const ConcreteNet **)a; const ConcreteNet *pb = *(const ConcreteNet **)b; Rect ba, bb; if (!pa && !pb) return 0; else if (!pa) return -1; else if (!pb) return 1; ba = getNetBBox(pa), bb = getNetBBox(pb); if (ba.y < bb.y) return -1; if (ba.y > bb.y) return 1; return 0; } int netSortByID(const void *a, const void *b) { const ConcreteNet *pa = *(const ConcreteNet **)a; const ConcreteNet *pb = *(const ConcreteNet **)b; if (!pa && !pb) return 0; else if (!pa) return -1; else if (!pb) return 1; if (pa->m_id < pb->m_id) return -1; if (pa->m_id > pb->m_id) return 1; return 0; } // -------------------------------------------------------------------- // cellSortByX... // /// \brief Sorts cells by either position coordinate. // /// These are for use with qsort(). /// /// Can tolerate pointers to NULL objects. // // -------------------------------------------------------------------- int cellSortByX(const void *a, const void *b) { const ConcreteCell *pa = *(const ConcreteCell **)a; const ConcreteCell *pb = *(const ConcreteCell **)b; if (!pa && !pb) return 0; else if (!pa) return -1; else if (!pb) return 1; if (pa->m_x < pb->m_x) return -1; if (pa->m_x > pb->m_x) return 1; return 0; } int cellSortByY(const void *a, const void *b) { const ConcreteCell *pa = *(const ConcreteCell **)a; const ConcreteCell *pb = *(const ConcreteCell **)b; if (!pa && !pb) return 0; else if (!pa) return -1; else if (!pb) return 1; if (pa->m_y < pb->m_y) return -1; if (pa->m_y > pb->m_y) return 1; return 0; } int cellSortByID(const void *a, const void *b) { const ConcreteCell *pa = *(const ConcreteCell **)a; const ConcreteCell *pb = *(const ConcreteCell **)b; if (!pa && !pb) return 0; else if (!pa) return -1; else if (!pb) return 1; if (pa->m_id < pb->m_id) return -1; if (pa->m_id > pb->m_id) return 1; return 0; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_base.h000066400000000000000000000076651300674244400243500ustar00rootroot00000000000000/*===================================================================*/ // // place_base.h // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #if !defined(PLACE_BASE_H_) #define ABC__phys__place__place_base_h ABC_NAMESPACE_HEADER_START // -------------------------------------------------------------------- // Data structures // // -------------------------------------------------------------------- // --- a C++ bool-like type //typedef char bool; #ifndef ABC__phys__place__place_base_h #define bool int #endif #define true 1 #define false 0 // --- Rect - rectangle typedef struct Rect { float x, y; float w, h; } Rect; // --- AbstractCell - a definition of a cell type typedef struct AbstractCell { char *m_label; // string description float m_width, m_height; // dimensions bool m_pad; // a pad (external I/O) cell? } AbstractCell; // --- ConcreteCell - a design object typedef struct ConcreteCell { int m_id; // a unique ID (see below) char *m_label; // string description AbstractCell *m_parent; // cell type bool m_fixed; // position is fixed? float m_x, m_y; // center of cell int m_data; } ConcreteCell; // --- ConcreteNet - a design net typedef struct ConcreteNet { int m_id; // a unique ID (see below) int m_numTerms; // num. of connected cells ConcreteCell **m_terms; // connected cells float m_weight; // relative weight int m_data; } ConcreteNet; // A note about IDs - the IDs are non-nonegative integers. They need not // be contiguous, but this is certainly a good idea, as they are stored // in a non-sparse array. // Cells and nets have separate ID spaces. // -------------------------------------------------------------------- // Global variable prototypes // // -------------------------------------------------------------------- // NOTE: None of these need to be managed externally. extern int g_place_numCells; // number of cells extern int g_place_numNets; // number of nets extern float g_place_rowHeight; // height of placement row extern Rect g_place_coreBounds; // border of placeable area // (x,y) = corner extern Rect g_place_padBounds; // border of total die area // (x,y) = corner extern ConcreteCell **g_place_concreteCells; // all concrete cells extern ConcreteNet **g_place_concreteNets; // all concrete nets // -------------------------------------------------------------------- // Function prototypes // // -------------------------------------------------------------------- void addConcreteNet(ConcreteNet *net); void addConcreteCell(ConcreteCell *cell); void delConcreteNet(ConcreteNet *net); void delConcreteCell(ConcreteCell *cell); void globalPreplace(float utilization); void globalPlace(); void globalIncremental(); void globalFixDensity(int numBins, float maxMovement); float fastEstimate(ConcreteCell *cell, int numNets, ConcreteNet *nets[]); float fastTopoPlace(int numCells, ConcreteCell *cells[], int numNets, ConcreteNet *nets[]); Rect getNetBBox(const ConcreteNet *net); float getNetWirelength(const ConcreteNet *net); float getTotalWirelength(); float getCellArea(const ConcreteCell *cell); void writeBookshelf(const char *filename); // comparative qsort-style functions int netSortByL(const void *a, const void *b); int netSortByR(const void *a, const void *b); int netSortByB(const void *a, const void *b); int netSortByT(const void *a, const void *b); int netSortByID(const void *a, const void *b); int cellSortByX(const void *a, const void *b); int cellSortByY(const void *a, const void *b); int cellSortByID(const void *a, const void *b); ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_bin.c000066400000000000000000000210541300674244400241650ustar00rootroot00000000000000/*===================================================================*/ // // place_bin.c // // Aaron P. Hurst, 2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include //#define DEBUG #include "place_base.h" ABC_NAMESPACE_IMPL_START // -------------------------------------------------------------------- // Global variables // // -------------------------------------------------------------------- // -------------------------------------------------------------------- // Function prototypes and local data structures // // -------------------------------------------------------------------- void spreadDensityX(int numBins, float maxMovement); void spreadDensityY(int numBins, float maxMovement); // -------------------------------------------------------------------- // globalFixDensity() // /// Doesn't deal well with fixed cells in the core area. // -------------------------------------------------------------------- void globalFixDensity(int numBins, float maxMovement) { printf("QCLN-10 : \tbin-based density correction\n"); spreadDensityX(numBins, maxMovement); // spreadDensityY(numBins, maxMovement); } // -------------------------------------------------------------------- // spreadDensityX() // // -------------------------------------------------------------------- void spreadDensityX(int numBins, float maxMovement) { int c, c2, c3, x, y; float totalArea = 0; int moveableCells = 0; float yBinArea = 0, yCumArea = 0; int yBinStart = 0, yBinCount = 0; int xBinCount, xBinStart; float xBinArea, xCumArea; float lastOldEdge; float lastNewEdge; float curOldEdge, curNewEdge; float stretch, w; ConcreteCell *xCell, *yCell; ConcreteCell **binCells; ConcreteCell **allCells; binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); for(c=0; cm_fixed && !cell->m_parent->m_pad) { allCells[moveableCells++] = cell; totalArea += getCellArea(cell); } } // spread X qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByY); y = 0; // for each y-bin... for(c=0; c= totalArea*(y+1)/numBins && yBinArea > 0) { memcpy(binCells, &(allCells[yBinStart]), sizeof(ConcreteCell*)*yBinCount); qsort(binCells, yBinCount, sizeof(ConcreteCell*), cellSortByX); #if defined(DEBUG) printf("y-bin %d count=%d area=%f\n",y,yBinCount, yBinArea); #endif x = 0; xBinCount = 0, xBinStart = 0; xBinArea = 0, xCumArea = 0; lastOldEdge = g_place_coreBounds.x; lastNewEdge = g_place_coreBounds.x; // for each x-bin... for(c2=0; c2m_x; printf("%.3f ", xCell->m_x); // have we filled up an x-bin? if (xCumArea >= yBinArea*(x+1)/numBins && xBinArea > 0) { curNewEdge = lastNewEdge + g_place_coreBounds.w*xBinArea/yBinArea; if (curNewEdge > g_place_coreBounds.x+g_place_coreBounds.w) curNewEdge = g_place_coreBounds.x+g_place_coreBounds.w; if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement; if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement; #if defined(DEBUG) printf("->\tx-bin %d count=%d area=%f (%f,%f)->(%f,%f)\n",x, xBinCount, xBinArea, curOldEdge, lastOldEdge, curNewEdge, lastNewEdge); #endif stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge); // stretch! for(c3=xBinStart; c3m_x = lastNewEdge+(c3-xBinStart)*(curNewEdge-lastNewEdge); else binCells[c3]->m_x = lastNewEdge+(binCells[c3]->m_x-lastOldEdge)*stretch; // force within core w = binCells[c3]->m_parent->m_width*0.5; if (binCells[c3]->m_x-w < g_place_coreBounds.x) binCells[c3]->m_x = g_place_coreBounds.x+w; if (binCells[c3]->m_x+w > g_place_coreBounds.x+g_place_coreBounds.w) binCells[c3]->m_x = g_place_coreBounds.x+g_place_coreBounds.w-w; } lastOldEdge = curOldEdge; lastNewEdge = curNewEdge; x++; xBinCount = 0; xBinArea = 0; xBinStart = c2+1; } } y++; yBinCount = 0; yBinArea = 0; yBinStart = c+1; } } free(binCells); free(allCells); } // -------------------------------------------------------------------- // spreadDensityY() // // -------------------------------------------------------------------- void spreadDensityY(int numBins, float maxMovement) { int c, c2, c3, x, y; float totalArea = 0; int moveableCells = 0; float xBinArea = 0, xCumArea = 0; int xBinStart = 0, xBinCount = 0; int yBinCount, yBinStart; float yBinArea, yCumArea; float lastOldEdge; float lastNewEdge; float curOldEdge, curNewEdge; float stretch, h; ConcreteCell *xCell, *yCell; ConcreteCell **binCells; ConcreteCell **allCells; binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); for(c=0; cm_fixed && !cell->m_parent->m_pad) { allCells[moveableCells++] = cell; totalArea += getCellArea(cell); } } // spread Y qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByX); x = 0; // for each x-bin... for(c=0; c= totalArea*(x+1)/numBins && xBinArea > 0) { memcpy(binCells, &(allCells[xBinStart]), sizeof(ConcreteCell*)*xBinCount); qsort(binCells, xBinCount, sizeof(ConcreteCell*), cellSortByY); // printf("x-bin %d count=%d area=%f\n",y,yBinCount, yBinArea); y = 0; yBinCount = 0, yBinStart = 0; yBinArea = 0, yCumArea = 0; lastOldEdge = g_place_coreBounds.y; lastNewEdge = g_place_coreBounds.y; // for each y-bin... for(c2=0; c2m_y; // have we filled up an x-bin? if (yCumArea >= xBinArea*(y+1)/numBins && yBinArea > 0) { curNewEdge = lastNewEdge + g_place_coreBounds.h*yBinArea/xBinArea; if (curNewEdge > g_place_coreBounds.y+g_place_coreBounds.h) curNewEdge = g_place_coreBounds.y+g_place_coreBounds.h; if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement; if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement; if (curOldEdge == lastOldEdge) continue; // hmmm stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge); // stretch! for(c3=yBinStart; c3m_y = lastNewEdge+(binCells[c3]->m_y-lastOldEdge)*stretch; // force within core h = binCells[c3]->m_parent->m_height; if (binCells[c3]->m_y-h < g_place_coreBounds.y) binCells[c3]->m_y = g_place_coreBounds.y+h; if (binCells[c3]->m_y+h > g_place_coreBounds.y+g_place_coreBounds.h) binCells[c3]->m_y = g_place_coreBounds.y+g_place_coreBounds.h-h; } lastOldEdge = curOldEdge; lastNewEdge = curNewEdge; y++; yBinCount = 0; yBinArea = 0; yBinStart = c2+1; } } x++; xBinCount = 0; xBinArea = 0; xBinStart = c+1; } } free(binCells); free(allCells); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_genqp.c000066400000000000000000000221431300674244400245270ustar00rootroot00000000000000/*===================================================================*/ // // place_genqp.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include #include "place_base.h" #include "place_qpsolver.h" #include "place_gordian.h" ABC_NAMESPACE_IMPL_START // -------------------------------------------------------------------- // Global variables // // -------------------------------------------------------------------- qps_problem_t *g_place_qpProb = NULL; // -------------------------------------------------------------------- // splitPenalty() // /// \brief Returns a weight for all of the edges in the clique for a multipin net. // // -------------------------------------------------------------------- float splitPenalty(int pins) { if (pins > 1) { return 1.0 + CLIQUE_PENALTY/(pins - 1); // return pow(pins - 1, CLIQUE_PENALTY); } return 1.0 + CLIQUE_PENALTY; } // -------------------------------------------------------------------- // constructQuadraticProblem() // /// \brief Constructs the matrices necessary to do analytical placement. // // -------------------------------------------------------------------- void constructQuadraticProblem() { int maxConnections = 1; int ignoreNum = 0; int n,t,c,c2,p; ConcreteCell *cell; ConcreteNet *net; int *cell_numTerms = calloc(g_place_numCells, sizeof(int)); ConcreteNet ***cell_terms = calloc(g_place_numCells, sizeof(ConcreteNet**)); bool incremental = false; int nextIndex = 1; int *seen = calloc(g_place_numCells, sizeof(int)); float weight; int last_index; // create problem object if (!g_place_qpProb) { g_place_qpProb = malloc(sizeof(qps_problem_t)); g_place_qpProb->area = NULL; g_place_qpProb->x = NULL; g_place_qpProb->y = NULL; g_place_qpProb->fixed = NULL; g_place_qpProb->connect = NULL; g_place_qpProb->edge_weight = NULL; } // count the maximum possible number of non-sparse entries for(n=0; nm_numTerms > IGNORE_NETSIZE) { ignoreNum++; } else { maxConnections += net->m_numTerms*(net->m_numTerms-1); for(t=0; tm_numTerms; t++) { c = net->m_terms[t]->m_id; p = ++cell_numTerms[c]; cell_terms[c] = (ConcreteNet**)realloc(cell_terms[c], p*sizeof(ConcreteNet*)); cell_terms[c][p-1] = net; } } } if(ignoreNum) { printf("QMAN-10 : \t\t%d large nets ignored\n", ignoreNum); } // initialize the data structures g_place_qpProb->num_cells = g_place_numCells; maxConnections += g_place_numCells + 1; g_place_qpProb->area = realloc(g_place_qpProb->area, sizeof(float)*g_place_numCells);// "area" matrix g_place_qpProb->edge_weight = realloc(g_place_qpProb->edge_weight, sizeof(float)*maxConnections); // "weight" matrix g_place_qpProb->connect = realloc(g_place_qpProb->connect, sizeof(int)*maxConnections); // "connectivity" matrix g_place_qpProb->fixed = realloc(g_place_qpProb->fixed, sizeof(int)*g_place_numCells); // "fixed" matrix // initialize or keep preexisting locations if (g_place_qpProb->x != NULL && g_place_qpProb->y != NULL) { printf("QMAN-10 :\tperforming incremental placement\n"); incremental = true; } g_place_qpProb->x = (float*)realloc(g_place_qpProb->x, sizeof(float)*g_place_numCells); g_place_qpProb->y = (float*)realloc(g_place_qpProb->y, sizeof(float)*g_place_numCells); // form a row for each cell // build data for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) { cell = g_place_concreteCells[c]; // fill in the characteristics for this cell g_place_qpProb->area[c] = getCellArea(cell); if (cell->m_fixed || cell->m_parent->m_pad) { g_place_qpProb->x[c] = cell->m_x; g_place_qpProb->y[c] = cell->m_y; g_place_qpProb->fixed[c] = 1; } else { if (!incremental) { g_place_qpProb->x[c] = g_place_coreBounds.x+g_place_coreBounds.w*0.5; g_place_qpProb->y[c] = g_place_coreBounds.y+g_place_coreBounds.h*0.5; } g_place_qpProb->fixed[c] = 0; } // update connectivity matrices last_index = nextIndex; for(n=0; nm_weight / splitPenalty(net->m_numTerms); for(t=0; tm_numTerms; t++) { c2 = net->m_terms[t]->m_id; if (c2 == c) continue; if (seen[c2] < last_index) { // not seen g_place_qpProb->connect[nextIndex-1] = c2; g_place_qpProb->edge_weight[nextIndex-1] = weight; seen[c2] = nextIndex; nextIndex++; } else { // seen g_place_qpProb->edge_weight[seen[c2]-1] += weight; } } } g_place_qpProb->connect[nextIndex-1] = -1; g_place_qpProb->edge_weight[nextIndex-1] = -1.0; nextIndex++; } else { // fill in dummy values for connectivity matrices g_place_qpProb->connect[nextIndex-1] = -1; g_place_qpProb->edge_weight[nextIndex-1] = -1.0; nextIndex++; } free(cell_numTerms); free(cell_terms); free(seen); } typedef struct reverseCOG { float x,y; Partition *part; float delta; } reverseCOG; // -------------------------------------------------------------------- // generateCoGConstraints() // /// \brief Generates center of gravity constraints. // // -------------------------------------------------------------------- int generateCoGConstraints(reverseCOG COG_rev[]) { int numConstraints = 0; // actual num constraints int cogRevNum = 0; Partition **stack = malloc(sizeof(Partition*)*g_place_numPartitions*2); int stackPtr = 0; Partition *p; float cgx, cgy; int next_index = 0, last_constraint = 0; bool isTrueConstraint = false; int i, m; float totarea; ConcreteCell *cell; // each partition may give rise to a center-of-gravity constraint stack[stackPtr] = g_place_rootPartition; while(stackPtr >= 0) { p = stack[stackPtr--]; assert(p); // traverse down the partition tree to leaf nodes-only if (!p->m_leaf) { stack[++stackPtr] = p->m_sub1; stack[++stackPtr] = p->m_sub2; } else { /* cout << "adding a COG constraint for box " << p->bounds.x << "," << p->bounds.y << " of size" << p->bounds.w << "x" << p->bounds.h << endl; */ cgx = p->m_bounds.x + p->m_bounds.w*0.5; cgy = p->m_bounds.y + p->m_bounds.h*0.5; COG_rev[cogRevNum].x = cgx; COG_rev[cogRevNum].y = cgy; COG_rev[cogRevNum].part = p; COG_rev[cogRevNum].delta = 0; cogRevNum++; } } assert(cogRevNum == g_place_numPartitions); for (i = 0; i < g_place_numPartitions; i++) { p = COG_rev[i].part; assert(p); g_place_qpProb->cog_x[numConstraints] = COG_rev[i].x; g_place_qpProb->cog_y[numConstraints] = COG_rev[i].y; totarea = 0.0; for(m=0; mm_numMembers; m++) if (p->m_members[m]) { cell = p->m_members[m]; assert(cell); if (!cell->m_fixed && !cell->m_parent->m_pad) { isTrueConstraint = true; } else { continue; } g_place_qpProb->cog_list[next_index++] = cell->m_id; totarea += getCellArea(cell); } if (totarea == 0.0) { isTrueConstraint = false; } if (isTrueConstraint) { numConstraints++; g_place_qpProb->cog_list[next_index++] = -1; last_constraint = next_index; } else { next_index = last_constraint; } } free(stack); return --numConstraints; } // -------------------------------------------------------------------- // solveQuadraticProblem() // /// \brief Calls quadratic solver. // // -------------------------------------------------------------------- void solveQuadraticProblem(bool useCOG) { int c; reverseCOG *COG_rev = malloc(sizeof(reverseCOG)*g_place_numPartitions); g_place_qpProb->cog_list = malloc(sizeof(int)*(g_place_numPartitions+g_place_numCells)); g_place_qpProb->cog_x = malloc(sizeof(float)*g_place_numPartitions); g_place_qpProb->cog_y = malloc(sizeof(float)*g_place_numPartitions); // memset(g_place_qpProb->x, 0, sizeof(float)*g_place_numCells); // memset(g_place_qpProb->y, 0, sizeof(float)*g_place_numCells); qps_init(g_place_qpProb); if (useCOG) g_place_qpProb->cog_num = generateCoGConstraints(COG_rev); else g_place_qpProb->cog_num = 0; g_place_qpProb->loop_num = 0; qps_solve(g_place_qpProb); qps_clean(g_place_qpProb); // set the positions for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) { g_place_concreteCells[c]->m_x = g_place_qpProb->x[c]; g_place_concreteCells[c]->m_y = g_place_qpProb->y[c]; } // clean up free(g_place_qpProb->cog_list); free(g_place_qpProb->cog_x); free(g_place_qpProb->cog_y); free(COG_rev); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_gordian.c000066400000000000000000000116111300674244400250360ustar00rootroot00000000000000/*===================================================================*/ // // place_gordian.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include #include "place_gordian.h" #include "place_base.h" ABC_NAMESPACE_IMPL_START // -------------------------------------------------------------------- // Global variables // // -------------------------------------------------------------------- int g_place_numPartitions; // -------------------------------------------------------------------- // globalPlace() // /// \brief Performs analytic placement using a GORDIAN-like algorithm. // /// Updates the positions of all non-fixed non-pad cells. /// // -------------------------------------------------------------------- void globalPlace() { bool completionFlag = false; int iteration = 0; printf("PLAC-10 : Global placement (wirelength-driven Gordian)\n"); initPartitioning(); // build matrices representing interconnections printf("QMAN-00 : \tconstructing initial quadratic problem...\n"); constructQuadraticProblem(); // iterate placement until termination condition is met while(!completionFlag) { printf("QMAN-01 : \titeration %d numPartitions = %d\n",iteration,g_place_numPartitions); // do the global optimization in each direction printf("QMAN-01 : \t\tglobal optimization\n"); solveQuadraticProblem(!IGNORE_COG); // -------- PARTITIONING BASED CELL SPREADING ------ // bisection printf("QMAN-01 : \t\tpartition refinement\n"); if (REALLOCATE_PARTITIONS) reallocPartitions(); completionFlag |= refinePartitions(); printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); iteration++; } // final global optimization printf("QMAN-02 : \t\tfinal pass\n"); if (FINAL_REALLOCATE_PARTITIONS) reallocPartitions(); solveQuadraticProblem(!IGNORE_COG); printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); // clean up sanitizePlacement(); printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); globalFixDensity(25, g_place_rowHeight*5); printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); } // -------------------------------------------------------------------- // globalIncremental() // /// \brief Performs analytic placement using a GORDIAN-like algorithm. // /// Requires a valid set of partitions. /// // -------------------------------------------------------------------- void globalIncremental() { if (!g_place_rootPartition) { printf("WARNING: Can not perform incremental placement\n"); globalPlace(); return; } printf("PLAC-10 : Incremental global placement\n"); incrementalPartition(); printf("QMAN-00 : \tconstructing initial quadratic problem...\n"); constructQuadraticProblem(); solveQuadraticProblem(!IGNORE_COG); printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); // clean up sanitizePlacement(); printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); globalFixDensity(25, g_place_rowHeight*5); printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); } // -------------------------------------------------------------------- // sanitizePlacement() // /// \brief Moves any cells that are outside of the core bounds to the nearest location within. // // -------------------------------------------------------------------- void sanitizePlacement() { int c; float order_width = g_place_rowHeight; float x, y, edge, w, h; printf("QCLN-10 : \tsanitizing placement\n"); for(c=0; cm_fixed || cell->m_parent->m_pad) { continue; } // the new locations of the cells will be distributed within // a small margin inside the border so that ordering is preserved order_width = g_place_rowHeight; x = cell->m_x, y = cell->m_y, w = cell->m_parent->m_width, h = cell->m_parent->m_height; if ((edge=x-w*0.5) < g_place_coreBounds.x) { x = g_place_coreBounds.x+w*0.5 + order_width/(1.0+g_place_coreBounds.x-edge); } else if ((edge=x+w*0.5) > g_place_coreBounds.x+g_place_coreBounds.w) { x = g_place_coreBounds.x+g_place_coreBounds.w-w*0.5 - order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w); } if ((edge=y-h*0.5) < g_place_coreBounds.y) { y = g_place_coreBounds.y+h*0.5 + order_width/(1.0+g_place_coreBounds.y-edge); } else if ((edge=y+h*0.5) > g_place_coreBounds.y+g_place_coreBounds.h) { y = g_place_coreBounds.y+g_place_coreBounds.h-h*0.5 - order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w); } cell->m_x = x; cell->m_y = y; } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_gordian.h000066400000000000000000000036511300674244400250500ustar00rootroot00000000000000/*===================================================================*/ // // place_gordian.h // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #if !defined(PLACE_GORDIAN_H_) #define ABC__phys__place__place_gordian_h #include "place_base.h" #include "place_qpsolver.h" ABC_NAMESPACE_HEADER_START // Parameters for analytic placement #define CLIQUE_PENALTY 1.0 #define IGNORE_NETSIZE 20 // Parameters for partitioning #define LARGEST_FINAL_SIZE 20 #define PARTITION_AREA_ONLY true #define REALLOCATE_PARTITIONS false #define FINAL_REALLOCATE_PARTITIONS false #define IGNORE_COG false #define MAX_PARTITION_NONSYMMETRY 0.30 // Parameters for re-partitioning #define REPARTITION_LEVEL_DEPTH 4 #define REPARTITION_TARGET_FRACTION 0.15 #define REPARTITION_FM false #define REPARTITION_HMETIS true // Parameters for F-M re-partitioning #define FM_MAX_BIN 10 #define FM_MAX_PASSES 10 extern int g_place_numPartitions; extern qps_problem_t *g_place_qpProb; typedef struct Partition { int m_numMembers; ConcreteCell **m_members; Rect m_bounds; bool m_done, m_leaf, m_vertical; float m_area; int m_level; struct Partition *m_sub1, *m_sub2; } Partition; extern Partition *g_place_rootPartition; void initPartitioning(); void incrementalPartition(); bool refinePartitions(); void reallocPartitions(); bool refinePartition(Partition *p); void resizePartition(Partition *p); void reallocPartition(Partition *p); void repartitionHMetis(Partition *parent); void repartitionFM(Partition *parent); void partitionScanlineMincut(Partition *parent); void partitionEqualArea(Partition *parent); void sanitizePlacement(); void constructQuadraticProblem(); void solveQuadraticProblem(bool useCOG); ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_inc.c000066400000000000000000000054421300674244400241710ustar00rootroot00000000000000/*===================================================================*/ // // place_inc.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include "place_base.h" #include "place_gordian.h" ABC_NAMESPACE_IMPL_START inline int sqHashId(int id, int max) { return ((id * (id+17)) % max); } #if 0 // -------------------------------------------------------------------- // fastPlace() // /// The first cell is assumed to be the "output". // -------------------------------------------------------------------- float fastPlace(int numCells, ConcreteCell *cells[], int numNets, ConcreteNet *nets[]) { int n, t, c, i, local_id = 0, pass; const int NUM_PASSES = 4; int *cell_numTerms = calloc(numCells, sizeof(int)); ConcreteNet **cell_terms; ConcreteNet *net; Rect outputBox; outputBox = getNetBBox(nets[0]); // assign local ids // put cells in reasonable initial location for(n=0; nm_numTerms; t++) nets[n]->m_terms[t]->m_data = -1; for(c=0; cm_data = local_id; cells[c]->m_x = outputBox.x + 0.5*outputBox.w; cells[c]->m_y = outputBox.y + 0.5*outputBox.h; } // build reverse map of cells to nets for(n=0; nm_numTerms; t++) { local_id = nets[n]->m_terms[t]->m_data; if (local_id >= 0) cell_numTerms[local_id]++; } for(c=0; cm_numTerms; t++) { local_id = nets[n]->m_terms[t]->m_data; if (local_id >= 0) cell_terms[cell_numTerms[local_id]++] = nets[n]; } // topological order? // iterative linear for(pass=0; passm_numTerms; t++); } } } #endif // -------------------------------------------------------------------- // fastEstimate() // // -------------------------------------------------------------------- float fastEstimate(ConcreteCell *cell, int numNets, ConcreteNet *nets[]) { float len = 0; int n; Rect box; assert(cell); for(n=0; nm_x < box.x) len += (box.x - cell->m_x); if (cell->m_x > box.x+box.w) len += (cell->m_x-box.x-box.w); if (cell->m_y < box.y) len += (box.x - cell->m_y); if (cell->m_y > box.y+box.h) len += (cell->m_y-box.y-box.h); } return len; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_io.c000066400000000000000000000047711300674244400240330ustar00rootroot00000000000000/*===================================================================*/ // // place_io.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include #include "place_base.h" ABC_NAMESPACE_IMPL_START // -------------------------------------------------------------------- // writeBookshelfNodes() // // -------------------------------------------------------------------- void writeBookshelfNodes(const char *filename) { int c = 0; int numNodes, numTerms; FILE *nodesFile = fopen(filename, "w"); if (!nodesFile) { printf("ERROR: Could not open .nodes file\n"); exit(1); } numNodes = numTerms = 0; for(c=0; cm_parent->m_pad) numTerms++; } fprintf(nodesFile, "UCLA nodes 1.0\n"); fprintf(nodesFile, "NumNodes : %d\n", numNodes); fprintf(nodesFile, "NumTerminals : %d\n", numTerms); for(c=0; cm_id, g_place_concreteCells[c]->m_parent->m_width, g_place_concreteCells[c]->m_parent->m_height, (g_place_concreteCells[c]->m_parent->m_pad ? " terminal" : "")); } fclose(nodesFile); } // -------------------------------------------------------------------- // writeBookshelfPl() // // -------------------------------------------------------------------- void writeBookshelfPl(const char *filename) { int c = 0; FILE *plFile = fopen(filename, "w"); if (!plFile) { printf("ERROR: Could not open .pl file\n"); exit(1); } fprintf(plFile, "UCLA pl 1.0\n"); for(c=0; cm_id, g_place_concreteCells[c]->m_x, g_place_concreteCells[c]->m_y, (g_place_concreteCells[c]->m_fixed ? "\\FIXED" : "")); } fclose(plFile); } // -------------------------------------------------------------------- // writeBookshelf() // // -------------------------------------------------------------------- void writeBookshelf(const char *filename) { writeBookshelfNodes("out.nodes"); writeBookshelfPl("out.pl"); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_legalize.c000066400000000000000000000010651300674244400252110ustar00rootroot00000000000000/*===================================================================*/ // // place_legalize.c // // Aaron P. Hurst, 2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include "place_base.h" ABC_NAMESPACE_IMPL_START // -------------------------------------------------------------------- // legalize() // // -------------------------------------------------------------------- void legalize() { // UNIMPLEMENTED } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_pads.c000066400000000000000000000115271300674244400243500ustar00rootroot00000000000000/*===================================================================*/ // // place_pads.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include "place_base.h" ABC_NAMESPACE_IMPL_START // -------------------------------------------------------------------- // globalPreplace() // /// \brief Place pad ring, leaving a core area to meet a desired utilization. // /// Sets the position of pads that aren't already fixed. /// /// Computes g_place_coreBounds and g_place_padBounds. Determines /// g_place_rowHeight. // // -------------------------------------------------------------------- void globalPreplace(float utilization) { int i, c, h, numRows; float coreArea = 0, totalArea = 0; int padCount = 0; float area; ConcreteCell **padCells = NULL; AbstractCell *padType = NULL; ConcreteCell *cell; float nextPos; int remainingPads, northPads, southPads, eastPads, westPads; printf("PLAC-00 : Placing IO pads\n");; // identify the pads and compute the total core area g_place_coreBounds.x = g_place_coreBounds.y = 0; g_place_coreBounds.w = g_place_coreBounds.h = -INT_MAX; for(c=0; cm_parent->m_pad) { padType = cell->m_parent; } else { coreArea += area; g_place_rowHeight = cell->m_parent->m_height; } if (cell->m_fixed) { g_place_coreBounds.x = g_place_coreBounds.x < cell->m_x ? g_place_coreBounds.x : cell->m_x; g_place_coreBounds.y = g_place_coreBounds.y < cell->m_y ? g_place_coreBounds.y : cell->m_y; g_place_coreBounds.w = g_place_coreBounds.w > cell->m_x ? g_place_coreBounds.w : cell->m_x; g_place_coreBounds.h = g_place_coreBounds.h > cell->m_y ? g_place_coreBounds.h : cell->m_y; } else if (cell->m_parent->m_pad) { padCells = realloc(padCells, sizeof(ConcreteCell **)*(padCount+1)); padCells[padCount++] = cell; } totalArea += area; } if (!padType) { printf("ERROR: No pad cells\n"); exit(1); } g_place_padBounds.w -= g_place_padBounds.x; g_place_padBounds.h -= g_place_padBounds.y; coreArea /= utilization; // create the design boundaries numRows = sqrt(coreArea)/g_place_rowHeight+1; h = numRows * g_place_rowHeight; g_place_coreBounds.h = g_place_coreBounds.h > h ? g_place_coreBounds.h : h; g_place_coreBounds.w = g_place_coreBounds.w > coreArea/g_place_coreBounds.h ? g_place_coreBounds.w : coreArea/g_place_coreBounds.h; // increase the dimensions by the width of the padring g_place_padBounds = g_place_coreBounds; if (padCount) { printf("PLAC-05 : \tpreplacing %d pad cells\n", padCount); g_place_padBounds.x -= padType->m_width; g_place_padBounds.y -= padType->m_height; g_place_padBounds.w = g_place_coreBounds.w+2*padType->m_width; g_place_padBounds.h = g_place_coreBounds.h+2*padType->m_height; } printf("PLAC-05 : \tplaceable rows : %d\n", numRows); printf("PLAC-05 : \tcore dimensions : %.0fx%.0f\n", g_place_coreBounds.w, g_place_coreBounds.h); printf("PLAC-05 : \tchip dimensions : %.0fx%.0f\n", g_place_padBounds.w, g_place_padBounds.h); remainingPads = padCount; c = 0; // north pads northPads = remainingPads/4; remainingPads -= northPads; nextPos = 0; for(i=0; im_x = g_place_padBounds.x+cell->m_parent->m_width*0.5 + nextPos; cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5; nextPos += (g_place_padBounds.w-padType->m_width) / northPads; } // south pads southPads = remainingPads/3; remainingPads -= southPads; nextPos = 0; for(i=0; im_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5 - nextPos; cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5; nextPos += (g_place_padBounds.w-2*padType->m_width) / southPads; } // east pads eastPads = remainingPads/2; remainingPads -= eastPads; nextPos = 0; for(i=0; im_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5; cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5 + nextPos; nextPos += (g_place_padBounds.h-padType->m_height) / eastPads; } // west pads westPads = remainingPads; nextPos = 0; for(i=0; im_x = g_place_padBounds.x+cell->m_parent->m_width*0.5; cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5 - nextPos; nextPos += (g_place_padBounds.h-padType->m_height) / westPads; } } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_partition.c000066400000000000000000001102011300674244400254170ustar00rootroot00000000000000/*===================================================================*/ // // place_partition.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include #include //#include //#include #include "place_base.h" #include "place_gordian.h" #if !defined(NO_HMETIS) #include "libhmetis.h" ABC_NAMESPACE_IMPL_START #endif // -------------------------------------------------------------------- // Global variables // // -------------------------------------------------------------------- Partition *g_place_rootPartition = NULL; ConcreteNet **allNetsR2 = NULL, **allNetsL2 = NULL, **allNetsB2 = NULL, **allNetsT2 = NULL; // -------------------------------------------------------------------- // Function prototypes and local data structures // // -------------------------------------------------------------------- typedef struct FM_cell { int loc; int gain; ConcreteCell *cell; struct FM_cell *next, *prev; bool locked; } FM_cell; void FM_updateGains(ConcreteNet *net, int partition, int inc, FM_cell target [], FM_cell *bin [], int count_1 [], int count_2 []); // -------------------------------------------------------------------- // initPartitioning() // /// \brief Initializes data structures necessary for partitioning. // /// Creates a valid g_place_rootPartition. /// // -------------------------------------------------------------------- void initPartitioning() { int i; float area; // create root partition g_place_numPartitions = 1; if (g_place_rootPartition) free(g_place_rootPartition); g_place_rootPartition = malloc(sizeof(Partition)); g_place_rootPartition->m_level = 0; g_place_rootPartition->m_area = 0; g_place_rootPartition->m_bounds = g_place_coreBounds; g_place_rootPartition->m_vertical = false; g_place_rootPartition->m_done = false; g_place_rootPartition->m_leaf = true; // add all of the cells to this partition g_place_rootPartition->m_members = malloc(sizeof(ConcreteCell*)*g_place_numCells); g_place_rootPartition->m_numMembers = 0; for (i=0; im_fixed) { area = getCellArea(g_place_concreteCells[i]); g_place_rootPartition->m_members[g_place_rootPartition->m_numMembers++] = g_place_concreteCells[i]; g_place_rootPartition->m_area += area; } } } // -------------------------------------------------------------------- // presortNets() // /// \brief Sorts nets by corner positions. // /// Allocates allNetsX2 structures. /// // -------------------------------------------------------------------- void presortNets() { allNetsL2 = (ConcreteNet**)realloc(allNetsL2, sizeof(ConcreteNet*)*g_place_numNets); allNetsR2 = (ConcreteNet**)realloc(allNetsR2, sizeof(ConcreteNet*)*g_place_numNets); allNetsB2 = (ConcreteNet**)realloc(allNetsB2, sizeof(ConcreteNet*)*g_place_numNets); allNetsT2 = (ConcreteNet**)realloc(allNetsT2, sizeof(ConcreteNet*)*g_place_numNets); memcpy(allNetsL2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); memcpy(allNetsR2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); memcpy(allNetsB2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); memcpy(allNetsT2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); qsort(allNetsL2, g_place_numNets, sizeof(ConcreteNet*), netSortByL); qsort(allNetsR2, g_place_numNets, sizeof(ConcreteNet*), netSortByR); qsort(allNetsB2, g_place_numNets, sizeof(ConcreteNet*), netSortByB); qsort(allNetsT2, g_place_numNets, sizeof(ConcreteNet*), netSortByT); } // -------------------------------------------------------------------- // refinePartitions() // /// \brief Splits large leaf partitions. // // -------------------------------------------------------------------- bool refinePartitions() { return refinePartition(g_place_rootPartition); } // -------------------------------------------------------------------- // reallocPartitions() // /// \brief Reallocates the partitions based on placement information. // // -------------------------------------------------------------------- void reallocPartitions() { reallocPartition(g_place_rootPartition); } // -------------------------------------------------------------------- // refinePartition() // /// \brief Splits any large leaves within a partition. // // -------------------------------------------------------------------- bool refinePartition(Partition *p) { bool degenerate = false; int nonzeroCount = 0; int i; assert(p); // is this partition completed? if (p->m_done) return true; // is this partition a non-leaf node? if (!p->m_leaf) { p->m_done = refinePartition(p->m_sub1); p->m_done &= refinePartition(p->m_sub2); return p->m_done; } // leaf... // create two new subpartitions g_place_numPartitions++; p->m_sub1 = malloc(sizeof(Partition)); p->m_sub1->m_level = p->m_level+1; p->m_sub1->m_leaf = true; p->m_sub1->m_done = false; p->m_sub1->m_area = 0; p->m_sub1->m_vertical = !p->m_vertical; p->m_sub1->m_numMembers = 0; p->m_sub1->m_members = NULL; p->m_sub2 = malloc(sizeof(Partition)); p->m_sub2->m_level = p->m_level+1; p->m_sub2->m_leaf = true; p->m_sub2->m_done = false; p->m_sub2->m_area = 0; p->m_sub2->m_vertical = !p->m_vertical; p->m_sub2->m_numMembers = 0; p->m_sub2->m_members = NULL; p->m_leaf = false; // --- INITIAL PARTITION if (PARTITION_AREA_ONLY) partitionEqualArea(p); else partitionScanlineMincut(p); resizePartition(p); // --- PARTITION IMPROVEMENT if (p->m_level < REPARTITION_LEVEL_DEPTH) { if (REPARTITION_FM) repartitionFM(p); else if (REPARTITION_HMETIS) repartitionHMetis(p); } resizePartition(p); // fix imbalances due to zero-area cells for(i=0; im_sub1->m_numMembers; i++) if (p->m_sub1->m_members[i]) if (getCellArea(p->m_sub1->m_members[i]) > 0) { nonzeroCount++; } // is this leaf now done? if (nonzeroCount <= LARGEST_FINAL_SIZE) p->m_sub1->m_done = true; if (nonzeroCount == 0) degenerate = true; nonzeroCount = 0; for(i=0; im_sub2->m_numMembers; i++) if (p->m_sub2->m_members[i]) if (getCellArea(p->m_sub2->m_members[i]) > 0) { nonzeroCount++; } // is this leaf now done? if (nonzeroCount <= LARGEST_FINAL_SIZE) p->m_sub2->m_done = true; if (nonzeroCount == 0) degenerate = true; // have we found a degenerate partitioning? if (degenerate) { printf("QPART-35 : WARNING: degenerate partition generated\n"); partitionEqualArea(p); resizePartition(p); p->m_sub1->m_done = true; p->m_sub2->m_done = true; } // is this parent now finished? if (p->m_sub1->m_done && p->m_sub2->m_done) p->m_done = true; return p->m_done; } // -------------------------------------------------------------------- // repartitionHMetis() // /// \brief Repartitions the two subpartitions using the hMetis min-cut library. /// /// The number of cut nets between the two partitions will be minimized. // // -------------------------------------------------------------------- void repartitionHMetis(Partition *parent) { #if defined(NO_HMETIS) printf("QPAR_02 : \t\tERROR: hMetis not available. Ignoring.\n"); #else int n,c,t, i; float area; int *edgeConnections = NULL; int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int)); int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int)); int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1)); int numConnections = 0; int numEdges = 0; float initial_cut; int targets = 0; ConcreteCell *cell = NULL; int options[9]; int afterCuts = 0; assert(parent); assert(parent->m_sub1); assert(parent->m_sub2); printf("QPAR-02 : \t\trepartitioning with hMetis\n"); // count edges edgeDegree[0] = 0; for(n=0; nm_numTerms > 1) { numConnections += g_place_concreteNets[n]->m_numTerms; edgeDegree[++numEdges] = numConnections; } if (parent->m_vertical) { // vertical initial_cut = parent->m_sub2->m_bounds.x; // initialize all cells for(c=0; cm_x < initial_cut) partitionAssignment[c] = 0; else partitionAssignment[c] = 1; } // initialize cells in partition 1 for(t=0; tm_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) { cell = parent->m_sub1->m_members[t]; vertexWeights[cell->m_id] = getCellArea(cell); // pay attention to cells that are close to the cut if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { targets++; partitionAssignment[cell->m_id] = -1; } } // initialize cells in partition 2 for(t=0; tm_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) { cell = parent->m_sub2->m_members[t]; vertexWeights[cell->m_id] = getCellArea(cell); // pay attention to cells that are close to the cut if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { targets++; partitionAssignment[cell->m_id] = -1; } } } else { // horizontal initial_cut = parent->m_sub2->m_bounds.y; // initialize all cells for(c=0; cm_y < initial_cut) partitionAssignment[c] = 0; else partitionAssignment[c] = 1; } // initialize cells in partition 1 for(t=0; tm_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) { cell = parent->m_sub1->m_members[t]; vertexWeights[cell->m_id] = getCellArea(cell); // pay attention to cells that are close to the cut if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { targets++; partitionAssignment[cell->m_id] = -1; } } // initialize cells in partition 2 for(t=0; tm_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) { cell = parent->m_sub2->m_members[t]; vertexWeights[cell->m_id] = getCellArea(cell); // pay attention to cells that are close to the cut if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { targets++; partitionAssignment[cell->m_id] = -1; } } } options[0] = 1; // any non-default values? options[1] = 3; // num bisections options[2] = 1; // grouping scheme options[3] = 1; // refinement scheme options[4] = 1; // cycle refinement scheme options[5] = 0; // reconstruction scheme options[6] = 0; // fixed assignments? options[7] = 12261980; // random seed options[8] = 0; // debugging level edgeConnections = (int *)malloc(sizeof(int)*numConnections); i = 0; for(n=0; nm_numTerms > 1) for(t=0; tm_numTerms; t++) edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id; } HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights, edgeDegree, edgeConnections, NULL, 2, (int)(100*MAX_PARTITION_NONSYMMETRY), options, partitionAssignment, &afterCuts); /* printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers, parent->m_sub2->m_numMembers); */ // reassign members to subpartitions parent->m_sub1->m_numMembers = 0; parent->m_sub1->m_area = 0; parent->m_sub2->m_numMembers = 0; parent->m_sub2->m_area = 0; parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, sizeof(ConcreteCell*)*parent->m_numMembers); parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, sizeof(ConcreteCell*)*parent->m_numMembers); for(t=0; tm_numMembers; t++) if (parent->m_members[t]) { cell = parent->m_members[t]; area = getCellArea(cell); if (partitionAssignment[cell->m_id] == 0) { parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell; parent->m_sub1->m_area += area; } else { parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell; parent->m_sub2->m_area += area; } } /* printf("after %d / %d\n", parent->m_sub1->m_numMembers, parent->m_sub2->m_numMembers); */ // cout << "HMET-21 : \t\t\tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl; // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl; free(edgeConnections); free(vertexWeights); free(edgeDegree); free(partitionAssignment); #endif } // -------------------------------------------------------------------- // repartitionFM() // /// \brief Fiduccia-Matheyses mincut partitioning algorithm. // /// UNIMPLEMENTED (well, un-C-ified) // // -------------------------------------------------------------------- void repartitionFM(Partition *parent) { #if 0 assert(!parent->leaf && parent->m_sub1->leaf && parent->m_sub2->leaf); // count of each net's number of cells in each bipartition int count_1[m_design->nets.length()]; memset(count_1, 0, sizeof(int)*m_design->nets.length()); int count_2[m_design->nets.length()]; memset(count_2, 0, sizeof(int)*m_design->nets.length()); FM_cell target[m_design->cells.length()]; memset(target, 0, sizeof(FM_cell)*m_design->cells.length()); FM_cell *bin[FM_MAX_BIN+1]; FM_cell *locked = 0; memset(bin, 0, sizeof(FM_cell *)*(FM_MAX_BIN+1)); int max_gain = 0; int before_cuts = 0, current_cuts = 0; double initial_cut; int targets = 0; long cell_id; double halfArea = parent->m_area / 2.0; double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY; ConcreteNet *net; // INITIALIZATION // select cells to partition if (parent->vertical) { // vertical initial_cut = parent->m_sub2->m_bounds.x; // initialize all cells for(h::list::iterator it = rootPartition->m_members.begin(); !it; it++) { cell_id = (*it)->getID(); if ((*it)->temp_x < initial_cut) target[cell_id].loc = -1; else target[cell_id].loc = -2; target[cell_id].cell = *it; target[cell_id].gain = 0; } // initialize cells in partition 1 for(h::list::iterator it = parent->m_sub1->m_members.begin(); !it; it++) { cell_id = (*it)->getID(); // pay attention to cells that are close to the cut if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { targets++; target[cell_id].loc = 1; } } // initialize cells in partition 2 for(h::list::iterator it = parent->m_sub2->m_members.begin(); !it; it++) { cell_id = (*it)->getID(); // pay attention to cells that are close to the cut if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { targets++; target[cell_id].loc = 2; } } // count the number of cells on each side of the partition for every net for(h::hash_map::iterator n_it = m_design->nets.begin(); !n_it; n_it++) { for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++) if (abs(target[(*p_it)->getCell()->getID()].loc) == 1) count_1[net->getID()]++; else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2) count_2[net->getID()]++; else if ((*p_it)->getCell()->temp_x < initial_cut) count_1[net->getID()]++; else count_2[net->getID()]++; if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++; } } else { // horizontal initial_cut = parent->m_sub2->m_bounds.y; // initialize all cells for(h::list::iterator it = rootPartition->m_members.begin(); !it; it++) { cell_id = (*it)->getID(); if ((*it)->temp_y < initial_cut) target[cell_id].loc = -1; else target[cell_id].loc = -2; target[cell_id].cell = *it; target[cell_id].gain = 0; } // initialize cells in partition 1 for(h::list::iterator it = parent->m_sub1->m_members.begin(); !it; it++) { cell_id = (*it)->getID(); // pay attention to cells that are close to the cut if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { targets++; target[cell_id].loc = 1; } } // initialize cells in partition 2 for(h::list::iterator it = parent->m_sub2->m_members.begin(); !it; it++) { cell_id = (*it)->getID(); // pay attention to cells that are close to the cut if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { targets++; target[cell_id].loc = 2; } } // count the number of cells on each side of the partition for every net for(h::hash_map::iterator n_it = m_design->nets.begin(); !n_it; n_it++) { for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++) if (abs(target[(*p_it)->getCell()->getID()].loc) == 1) count_1[net->getID()]++; else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2) count_2[net->getID()]++; else if ((*p_it)->getCell()->temp_y < initial_cut) count_1[net->getID()]++; else count_2[net->getID()]++; if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++; } } // INITIAL GAIN CALCULATION for(long id=0; id < m_design->cells.length(); id++) if (target[id].loc > 0) { assert(target[id].cell != 0); assert(target[id].gain == 0); // examine counts for the net on each pin for(ConcretePinMap::iterator p_it = target[id].cell->getPins().begin(); !p_it; p_it++) if ((*p_it)->isAttached()) { int n_id = (*p_it)->getNet()->getID(); if (target[id].loc == 1 && count_1[n_id] == 1) target[id].gain++; if (target[id].loc == 1 && count_2[n_id] == 0) target[id].gain--; if (target[id].loc == 2 && count_1[n_id] == 0) target[id].gain--; if (target[id].loc == 2 && count_2[n_id] == 1) target[id].gain++; } assert(target[id].cell->getPins().length() >= abs(target[id].gain)); // add it to a bin int bin_num = min(max(0, target[id].gain),FM_MAX_BIN); max_gain = max(max_gain, bin_num); assert(bin_num >= 0 && bin_num <= FM_MAX_BIN); target[id].next = bin[bin_num]; target[id].prev = 0; if (bin[bin_num] != 0) bin[bin_num]->prev = &target[id]; bin[bin_num] = &target[id]; } // OUTER F-M LOOP current_cuts = before_cuts; int num_moves = 1; int pass = 0; while(num_moves > 0 && pass < FM_MAX_PASSES) { pass++; num_moves = 0; // check_list(bin, locked, targets); // DEBUG // move all locked cells back int moved_back = 0; while(locked != 0) { FM_cell *current = locked; current->locked = false; int bin_num = min(max(0, current->gain),FM_MAX_BIN); max_gain = max(max_gain, bin_num); locked = current->next; if (locked != 0) locked->prev = 0; if (bin[bin_num] != 0) bin[bin_num]->prev = current; current->next = bin[bin_num]; bin[bin_num] = current; moved_back++; } // cout << "\tmoved back: " << moved_back << endl; // check_list(bin, locked, targets); // DEBUG max_gain = FM_MAX_BIN; while(bin[max_gain] == 0 && max_gain > 0) max_gain--; // INNER F-M LOOP (single pass) while(1) { int bin_num = FM_MAX_BIN; FM_cell *current = bin[bin_num]; // look for next cell to move while (bin_num > 0 && (current == 0 || (current->loc==1 && current->cell->getArea()+parent->m_sub2->m_area > halfArea+areaFlexibility) || (current->loc==2 && current->cell->getArea()+parent->m_sub1->m_area > halfArea+areaFlexibility))) { if (current == 0) current = bin[--bin_num]; else current = current->next; } if (bin_num == 0) break; num_moves++; current->locked = true; // cout << "moving cell " << current->cell->getID() << " gain=" << current->gain << " pins= " << current->cell->getPins().length() << " from " << current->loc; // change partition marking and areas if (current->loc == 1) { current->loc = 2; parent->m_sub1->m_area -= current->cell->getArea(); parent->m_sub2->m_area += current->cell->getArea(); // update partition counts on all nets attached to this cell for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); !p_it; p_it++) { if (!(*p_it)->isAttached()) // ignore unattached pins continue; net = (*p_it)->getNet(); count_1[net->getID()]--; count_2[net->getID()]++; // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]+1 << "/" << count_2[net->getID()]-1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl; // if net becomes critical, update gains on attached cells and resort bins if (count_1[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); } if (count_2[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); } // check_list(bin, locked, targets); // DEBUG } } else { current->loc = 1; parent->m_sub2->m_area -= current->cell->getArea(); parent->m_sub1->m_area += current->cell->getArea(); // update gains on all nets attached to this cell for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); !p_it; p_it++) { if (!(*p_it)->isAttached()) // ignore unattached pins continue; net = (*p_it)->getNet(); count_2[net->getID()]--; count_1[net->getID()]++; // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]-1 << "/" << count_2[net->getID()]+1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl; if (count_2[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); } if (count_1[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); } // check_list(bin, locked, targets); // DEBUG } } //cout << " cuts=" << current_cuts << endl; // move current to locked /* cout << "b=" << bin[bin_num] << " "; cout << current->prev << "-> "; if (current->prev == 0) cout << "X"; else cout << current->prev->next; cout << "=" << current << "="; if (current->next == 0) cout << "X"; else cout << current->next->prev; cout << " ->" << current->next << endl; */ if (bin[bin_num] == current) bin[bin_num] = current->next; if (current->prev != 0) current->prev->next = current->next; if (current->next != 0) current->next->prev = current->prev; /* cout << "b=" << bin[bin_num] << " "; cout << current->prev << "-> "; if (current->prev == 0) cout << "X"; else cout << current->prev->next; cout << "=" << current << "="; if (current->next == 0) cout << "X"; else cout << current->next->prev; cout << " ->" << current->next << endl; */ current->prev = 0; current->next = locked; if (locked != 0) locked->prev = current; locked = current; // check_list(bin, locked, targets); // DEBUG // update max_gain max_gain = FM_MAX_BIN; while(bin[max_gain] == 0 && max_gain > 0) max_gain--; } // cout << "\tcurrent cuts= " << current_cuts << " moves= " << num_moves << endl; } // reassign members to subpartitions cout << "FIDM-20 : \tbalance before " << parent->m_sub1->m_members.length() << "/" << parent->m_sub2->m_members.length() << " "; parent->m_sub1->m_members.clear(); parent->m_sub1->m_area = 0; parent->m_sub2->m_members.clear(); parent->m_sub2->m_area = 0; for(h::list::iterator it = parent->m_members.begin(); !it; it++) { if (target[(*it)->getID()].loc == 1 || target[(*it)->getID()].loc == -1) { parent->m_sub1->m_members.push_back(*it); parent->m_sub1->m_area += (*it)->getArea(); } else { parent->m_sub2->m_members.push_back(*it); parent->m_sub2->m_area += (*it)->getArea(); } } cout << " after " << parent->m_sub1->m_members.length() << "/" << parent->m_sub2->m_members.length() << endl; cout << "FIDM-21 : \tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl; cout << "FIDM-22 : \tstarting cuts= " << before_cuts << " final cuts= " << current_cuts << endl; #endif } // ----- FM_updateGains() // moves a cell between bins #if 0 void FM_updateGains(ConcreteNet *net, int partition, int inc, FM_cell target [], FM_cell *bin [], int count_1 [], int count_2 []) { for(ConcretePinList::iterator it = net->getPins().begin(); !it; it++) { FM_cell *current = &(target[(*it)->getCell()->getID()]); assert(current->cell != 0); int old_gain = current->gain; current->gain = 0; // examine counts for the net on each pin for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); !p_it; p_it++) if ((*p_it)->isAttached()) { int n_id = (*p_it)->getNet()->getID(); if (current->loc == 1 && count_1[n_id] == 1) current->gain++; if (current->loc == 1 && count_2[n_id] == 0) current->gain--; if (current->loc == 2 && count_1[n_id] == 0) current->gain--; if (current->loc == 2 && count_2[n_id] == 1) current->gain++; } if (!current->locked) { // remove cell from existing bin int bin_num = min(max(0, old_gain),FM_MAX_BIN); if (bin[bin_num] == current) bin[bin_num] = current->next; if (current->prev != 0) current->prev->next = current->next; if (current->next != 0) current->next->prev = current->prev; // add cell to correct bin bin_num = min(max(0, current->gain),FM_MAX_BIN); current->prev = 0; current->next = bin[bin_num]; if (bin[bin_num] != 0) bin[bin_num]->prev = current; bin[bin_num] = current; } } } #endif // -------------------------------------------------------------------- // partitionEqualArea() // /// \brief Splits a partition into two halves of equal area. // // -------------------------------------------------------------------- void partitionEqualArea(Partition *parent) { float halfArea, area; int i=0; // which way to sort? if (parent->m_vertical) // sort by X position qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByX); else // sort by Y position qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByY); // split the list halfArea = parent->m_area*0.5; parent->m_sub1->m_area = 0.0; parent->m_sub1->m_numMembers = 0; parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, sizeof(ConcreteCell*)*parent->m_numMembers); parent->m_sub2->m_area = 0.0; parent->m_sub2->m_numMembers = 0; parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, sizeof(ConcreteCell*)*parent->m_numMembers); for(; parent->m_sub1->m_area < halfArea; i++) if (parent->m_members[i]) { area = getCellArea(parent->m_members[i]); parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = parent->m_members[i]; parent->m_sub1->m_area += area; } for(; im_numMembers; i++) if (parent->m_members[i]) { area = getCellArea(parent->m_members[i]); parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = parent->m_members[i]; parent->m_sub2->m_area += area; } } // -------------------------------------------------------------------- // partitionScanlineMincut() // /// \brief Scans the cells within a partition from left to right and chooses the min-cut. // // -------------------------------------------------------------------- void partitionScanlineMincut(Partition *parent) { #if 0 int current_cuts = 0; int minimum_cuts = INT_MAX; ConcreteCell *minimum_location = NULL; double currentArea = 0, halfArea = parent->m_area * 0.5; double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY; double newLine, oldLine = -DBL_MAX; for(ConcreteNetList::iterator n_it = m_design->nets.begin(); !n_it; n_it++) (*n_it)->m_mark = 0; for(h::list::iterator i = parent->m_members.begin(); !i.isDone(); i++) { assert(*i); for(ConcretePinMap::iterator j = (*i)->getPins().begin(); !j.isDone(); j++) { assert(*j); if((*j)->isAttached()) { (*j)->getNet()->m_mark = 1; } } } if (parent->vertical) { parent->m_members.sort(sortByX); int all1 = 0, all2 = 0; h::list::iterator local = parent->m_members.begin(); for(; !local.isDone(); local++) { currentArea += (*local)->getArea(); if (currentArea < halfArea-areaFlexibility) continue; if (currentArea > halfArea+areaFlexibility) break; newLine = (*local)->temp_x; while(all1 < g_place_numNets && allNetsL2[all1]->getBoundingBox().left() <= newLine) { if(allNetsL2[all1]->m_mark) { current_cuts++; } all1++; } while(all2 < g_place_numNets && allNetsR2[all2]->getBoundingBox().right() <= newLine) { if(allNetsR2[all2]->m_mark) { current_cuts--; } all2++; } if (current_cuts < minimum_cuts) { minimum_cuts = current_cuts; minimum_location = *local; } oldLine = newLine; } } else { parent->m_members.sort(sortByY); int all1 = 0, all2 = 0; h::list::iterator local = parent->m_members.begin(); for(; !local.isDone(); local++) { currentArea += (*local)->getArea(); if (currentArea < halfArea-areaFlexibility) continue; if (currentArea > halfArea+areaFlexibility) break; newLine = (*local)->temp_y; while(all1 < g_place_numNets && allNetsB2[all1]->getBoundingBox().top() <= newLine) { if(allNetsB2[all1]->m_mark) { current_cuts++; } all1++; } while(all2 < g_place_numNets && allNetsT2[all2]->getBoundingBox().bottom() <= newLine) { if(allNetsT2[all2]->m_mark) { current_cuts--; } all2++; } if (current_cuts < minimum_cuts) { minimum_cuts = current_cuts; minimum_location = *local; } oldLine = newLine; } } if (minimum_location == NULL) { return partitionEqualArea(parent); } h::list::iterator it = parent->m_members.begin(); parent->m_sub1->m_members.clear(); parent->m_sub1->m_area = 0; for(; *it != minimum_location; it++) { parent->m_sub1->m_members.push_front(*it); parent->m_sub1->m_area += (*it)->getArea(); } parent->m_sub2->m_members.clear(); parent->m_sub2->m_area = 0; for(; !it; it++) { parent->m_sub2->m_members.push_front(*it); parent->m_sub2->m_area += (*it)->getArea(); } #endif } // -------------------------------------------------------------------- // reallocPartition() // /// \brief Reallocates a partition and all of its children. // // -------------------------------------------------------------------- void reallocPartition(Partition *p) { if (p->m_leaf) { return; } // --- INITIAL PARTITION if (PARTITION_AREA_ONLY) partitionEqualArea(p); else partitionScanlineMincut(p); resizePartition(p); // --- PARTITION IMPROVEMENT if (p->m_level < REPARTITION_LEVEL_DEPTH) { if (REPARTITION_HMETIS) repartitionHMetis(p); resizePartition(p); } reallocPartition(p->m_sub1); reallocPartition(p->m_sub2); } // -------------------------------------------------------------------- // resizePartition() // /// \brief Recomputes the bounding boxes of the child partitions based on their relative areas. // // -------------------------------------------------------------------- void resizePartition(Partition *p) { // compute the new bounding box p->m_sub1->m_bounds.x = p->m_bounds.x; p->m_sub1->m_bounds.y = p->m_bounds.y; if (p->m_vertical) { p->m_sub1->m_bounds.w = p->m_bounds.w*(p->m_sub1->m_area/p->m_area); p->m_sub1->m_bounds.h = p->m_bounds.h; p->m_sub2->m_bounds.x = p->m_bounds.x + p->m_sub1->m_bounds.w; p->m_sub2->m_bounds.w = p->m_bounds.w*(p->m_sub2->m_area/p->m_area); p->m_sub2->m_bounds.y = p->m_bounds.y; p->m_sub2->m_bounds.h = p->m_bounds.h; } else { p->m_sub1->m_bounds.h = p->m_bounds.h*(p->m_sub1->m_area/p->m_area); p->m_sub1->m_bounds.w = p->m_bounds.w; p->m_sub2->m_bounds.y = p->m_bounds.y + p->m_sub1->m_bounds.h; p->m_sub2->m_bounds.h = p->m_bounds.h*(p->m_sub2->m_area/p->m_area); p->m_sub2->m_bounds.x = p->m_bounds.x; p->m_sub2->m_bounds.w = p->m_bounds.w; } } // -------------------------------------------------------------------- // incrementalSubpartition() // /// \brief Adds new cells to an existing partition. Partition sizes/locations are unchanged. /// /// The function recurses, adding new cells to appropriate subpartitions. // // -------------------------------------------------------------------- void incrementalSubpartition(Partition *p, ConcreteCell *newCells [], const int numNewCells) { int c; ConcreteCell **newCells1 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells), **newCells2 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells); int numNewCells1 = 0, numNewCells2 = 0; float cut_loc; assert(p); // add new cells to partition list p->m_members = (ConcreteCell**)realloc(p->m_members, sizeof(ConcreteCell*)*(p->m_numMembers+numNewCells)); memcpy(&(p->m_members[p->m_numMembers]), newCells, sizeof(ConcreteCell*)*numNewCells); p->m_numMembers += numNewCells; // if is a leaf partition, finished if (p->m_leaf) return; // split new cells into sub-partitions based on location if (p->m_vertical) { cut_loc = p->m_sub2->m_bounds.x; for(c=0; cm_x < cut_loc) newCells1[numNewCells1++] = newCells[c]; else newCells2[numNewCells2++] = newCells[c]; } else { cut_loc = p->m_sub2->m_bounds.y; for(c=0; cm_y < cut_loc) newCells1[numNewCells1++] = newCells[c]; else newCells2[numNewCells2++] = newCells[c]; } if (numNewCells1 > 0) incrementalSubpartition(p->m_sub1, newCells1, numNewCells1); if (numNewCells2 > 0) incrementalSubpartition(p->m_sub2, newCells2, numNewCells2); free(newCells1); free(newCells2); } // -------------------------------------------------------------------- // incrementalPartition() // /// \brief Adds new cells to an existing partition. Partition sizes/locations are unchanged. /// /// The function recurses, adding new cells to appropriate subpartitions. // // -------------------------------------------------------------------- void incrementalPartition() { int c = 0, c2 = 0; int numNewCells = 0; ConcreteCell **allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells), **newCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); assert(g_place_rootPartition); // update cell list of root partition memcpy(allCells, g_place_concreteCells, sizeof(ConcreteCell*)*g_place_numCells); qsort(allCells, g_place_numCells, sizeof(ConcreteCell*), cellSortByID); qsort(g_place_rootPartition->m_members, g_place_rootPartition->m_numMembers, sizeof(ConcreteCell*), cellSortByID); // scan sorted lists and collect cells not in partitions while(!allCells[c++]); while(!g_place_rootPartition->m_members[c2++]); for(; cm_numMembers && allCells[c]->m_id > g_place_rootPartition->m_members[c2]->m_id) c2++; while(c < g_place_numCells && (c2 >= g_place_rootPartition->m_numMembers || allCells[c]->m_id < g_place_rootPartition->m_members[c2]->m_id)) { // a new cell! newCells[numNewCells++] = allCells[c]; c++; } } printf("QPRT-50 : \tincremental partitioning with %d new cells\n", numNewCells); if (numNewCells>0) incrementalSubpartition(g_place_rootPartition, newCells, numNewCells); free(allCells); free(newCells); } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_qpsolver.c000066400000000000000000000710701300674244400252730ustar00rootroot00000000000000/*===================================================================*/ // // place_qpsolver.c // // Philip Chong // pchong@cadence.com // /*===================================================================*/ #include #include #include #include #include "place_qpsolver.h" ABC_NAMESPACE_IMPL_START #undef QPS_DEBUG #define QPS_TOL 1.0e-3 #define QPS_EPS (QPS_TOL * QPS_TOL) #define QPS_MAX_TOL 0.1 #define QPS_LOOP_TOL 1.0e-3 #define QPS_RELAX_ITER 180 #define QPS_MAX_ITER 200 #define QPS_STEPSIZE_RETRIES 2 #define QPS_MINSTEP 1.0e-6 #define QPS_DEC_CHANGE 0.01 #define QPS_PRECON #define QPS_PRECON_EPS 1.0e-9 #undef QPS_HOIST #if defined(QPS_DEBUG) #define QPS_DEBUG_FILE "/tmp/qps_debug.log" #endif #if 0 /* ii is an array [0..p->num_cells-1] of indices from cells of original problem to modified problem variables. If ii[k] >= 0, cell is an independent cell; ii[k], ii[k]+1 are the indices of the corresponding variables for the modified problem. If ii[k] == -1, cell is a fixed cell. If ii[k] <= -2, cell is a dependent cell; -(ii[k]+2) is the index of the corresponding COG constraint. */ int *ii; /* gt is an array [0..p->cog_num-1] of indices from COG constraints to locations in the gl array (in qps_problem_t). gt[k] is the offset into gl where the kth constraint begins. */ int *gt; /* n is the number of variables in the modified problem. n should be twice the number of independent cells. */ int n; qps_float_t *cp; /* current location during CG iteration */ qps_float_t f; /* value of cost function at p */ #endif /**********************************************************************/ static void qps_settp(qps_problem_t * p) { /* Fill in the p->priv_tp array with the current locations of all cells (independent, dependent and fixed). */ int i; int t, u; int pr; qps_float_t rx, ry; qps_float_t ta; int *ii = p->priv_ii; qps_float_t *tp = p->priv_tp; qps_float_t *cp = p->priv_cp; /* do independent and fixed cells first */ for (i = p->num_cells; i--;) { t = ii[i]; if (t >= 0) { /* indep cell */ tp[i * 2] = cp[t]; tp[i * 2 + 1] = cp[t + 1]; } else if (t == -1) { /* fixed cell */ tp[i * 2] = p->x[i]; tp[i * 2 + 1] = p->y[i]; } } /* now do dependent cells */ for (i = p->num_cells; i--;) { if (ii[i] < -1) { t = -(ii[i] + 2); /* index of COG constraint */ ta = 0.0; rx = 0.0; ry = 0.0; pr = p->priv_gt[t]; while ((u = p->cog_list[pr++]) >= 0) { ta += p->area[u]; if (u != i) { rx -= p->area[u] * tp[u * 2]; ry -= p->area[u] * tp[u * 2 + 1]; } } rx += p->cog_x[t] * ta; ry += p->cog_y[t] * ta; tp[i * 2] = rx / p->area[i]; tp[i * 2 + 1] = ry / p->area[i]; } } #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### qps_settp()\n"); for (i = 0; i < p->num_cells; i++) { fprintf(p->priv_fp, "%f %f\n", tp[i * 2], tp[i * 2 + 1]); } #endif } /**********************************************************************/ static qps_float_t qps_func(qps_problem_t * p) { /* Return f(p). qps_settp() should have already been called before entering here */ int j, k; int pr; qps_float_t jx, jy, tx, ty; qps_float_t f; qps_float_t w; #if !defined(QPS_HOIST) int i; int st; qps_float_t kx, ky, sx, sy; qps_float_t t; #endif qps_float_t *tp = p->priv_tp; f = 0.0; pr = 0; for (j = 0; j < p->num_cells; j++) { jx = tp[j * 2]; jy = tp[j * 2 + 1]; while ((k = p->priv_cc[pr]) >= 0) { w = p->priv_cw[pr]; tx = tp[k * 2] - jx; ty = tp[k * 2 + 1] - jy; f += w * (tx * tx + ty * ty); pr++; } pr++; } p->f = f; #if !defined(QPS_HOIST) /* loop penalties */ pr = 0; for (i = 0; i < p->loop_num; i++) { t = 0.0; j = st = p->loop_list[pr++]; jx = sx = tp[j * 2]; jy = sy = tp[j * 2 + 1]; while ((k = p->loop_list[pr]) >= 0) { kx = tp[k * 2]; ky = tp[k * 2 + 1]; tx = jx - kx; ty = jy - ky; t += tx * tx + ty * ty; j = k; jx = kx; jy = ky; pr++; } tx = jx - sx; ty = jy - sy; t += tx * tx + ty * ty; t -= p->loop_max[i]; #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### qps_penalty() %d %f %f\n", i, p->loop_max[i], t); #endif p->priv_lt[i] = t; f += p->loop_penalty[i] * t; pr++; } #endif /* QPS_HOIST */ if (p->max_enable) { for (j = p->num_cells; j--;) { f += p->priv_mxl[j] * (-tp[j * 2]); f += p->priv_mxh[j] * (tp[j * 2] - p->max_x); f += p->priv_myl[j] * (-tp[j * 2 + 1]); f += p->priv_myh[j] * (tp[j * 2 + 1] - p->max_y); } } #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### qps_func() %f %f\n", f, p->f); #endif return f; } /**********************************************************************/ static void qps_dfunc(qps_problem_t * p, qps_float_t * d) { /* Set d to grad f(p). First computes partial derivatives wrt all cells then finds gradient wrt only the independent cells. qps_settp() should have already been called before entering here */ int i, j, k; int pr = 0; qps_float_t jx, jy, kx, ky, tx, ty; int ji, ki; qps_float_t w; #if !defined(QPS_HOIST) qps_float_t sx, sy; int st; #endif qps_float_t *tp = p->priv_tp; qps_float_t *tp2 = p->priv_tp2; /* compute partials and store in tp2 */ for (i = p->num_cells; i--;) { tp2[i * 2] = 0.0; tp2[i * 2 + 1] = 0.0; } for (j = 0; j < p->num_cells; j++) { jx = tp[j * 2]; jy = tp[j * 2 + 1]; while ((k = p->priv_cc[pr]) >= 0) { w = 2.0 * p->priv_cw[pr]; kx = tp[k * 2]; ky = tp[k * 2 + 1]; tx = w * (jx - kx); ty = w * (jy - ky); tp2[j * 2] += tx; tp2[k * 2] -= tx; tp2[j * 2 + 1] += ty; tp2[k * 2 + 1] -= ty; pr++; } pr++; } #if !defined(QPS_HOIST) /* loop penalties */ pr = 0; for (i = 0; i < p->loop_num; i++) { j = st = p->loop_list[pr++]; jx = sx = tp[j * 2]; jy = sy = tp[j * 2 + 1]; w = 2.0 * p->loop_penalty[i]; while ((k = p->loop_list[pr]) >= 0) { kx = tp[k * 2]; ky = tp[k * 2 + 1]; tx = w * (jx - kx); ty = w * (jy - ky); tp2[j * 2] += tx; tp2[k * 2] -= tx; tp2[j * 2 + 1] += ty; tp2[k * 2 + 1] -= ty; j = k; jx = kx; jy = ky; pr++; } tx = w * (jx - sx); ty = w * (jy - sy); tp2[j * 2] += tx; tp2[st * 2] -= tx; tp2[j * 2 + 1] += ty; tp2[st * 2 + 1] -= ty; pr++; } #endif /* QPS_HOIST */ if (p->max_enable) { for (j = p->num_cells; j--;) { tp2[j * 2] += p->priv_mxh[j] - p->priv_mxl[j]; tp2[j * 2 + 1] += p->priv_myh[j] - p->priv_myl[j]; } } #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### qps_dfunc() partials\n"); for (j = 0; j < p->num_cells; j++) { fprintf(p->priv_fp, "%f %f\n", tp2[j * 2], tp2[j * 2 + 1]); } #endif /* translate partials to independent variables */ for (j = p->priv_n; j--;) { d[j] = 0.0; } for (j = p->num_cells; j--;) { ji = p->priv_ii[j]; if (ji >= 0) { /* indep var */ d[ji] += tp2[j * 2]; d[ji + 1] += tp2[j * 2 + 1]; } else if (ji < -1) { /* dependent variable */ ji = -(ji + 2); /* get COG index */ pr = p->priv_gt[ji]; while ((k = p->cog_list[pr]) >= 0) { ki = p->priv_ii[k]; if (ki >= 0) { w = p->priv_gw[pr]; #if (QPS_DEBUG > 0) assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6); #endif d[ki] -= tp2[j * 2] * w; d[ki + 1] -= tp2[j * 2 + 1] * w; } pr++; } } } #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### qps_dfunc() gradient\n"); for (j = 0; j < p->priv_n; j++) { fprintf(p->priv_fp, "%f\n", d[j]); } #endif } /**********************************************************************/ static void qps_linmin(qps_problem_t * p, qps_float_t dgg, qps_float_t * h) { /* Perform line minimization. p->priv_cp is the current location, h is direction of the gradient. Updates p->priv_cp to line minimal position based on formulas from "Handbook of Applied Optimization", Pardalos and Resende, eds., Oxford Univ. Press, 2002. qps_settp() should have already been called before entering here. Since p->priv_cp is changed, p->priv_tp array becomes invalid following this routine. */ int i, j, k; int pr; int ji, ki; qps_float_t jx, jy, kx, ky; qps_float_t f = 0.0; qps_float_t w; #if !defined(QPS_HOIST) int st; qps_float_t sx, sy, tx, ty; qps_float_t t; #endif qps_float_t *tp = p->priv_tp; /* translate h vector to partials over all variables and store in tp */ for (i = p->num_cells; i--;) { tp[i * 2] = 0.0; tp[i * 2 + 1] = 0.0; } for (j = p->num_cells; j--;) { ji = p->priv_ii[j]; if (ji >= 0) { /* indep cell */ tp[j * 2] = h[ji]; tp[j * 2 + 1] = h[ji + 1]; } else if (ji < -1) { /* dep cell */ ji = -(ji + 2); /* get COG index */ pr = p->priv_gt[ji]; while ((k = p->cog_list[pr]) >= 0) { ki = p->priv_ii[k]; if (ki >= 0) { w = p->priv_gw[pr]; #if (QPS_DEBUG > 0) assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6); #endif tp[j * 2] -= h[ki] * w; tp[j * 2 + 1] -= h[ki + 1] * w; } pr++; } } } /* take product x^T Z^T C Z x */ pr = 0; for (j = 0; j < p->num_cells; j++) { jx = tp[j * 2]; jy = tp[j * 2 + 1]; while ((k = p->priv_cc[pr]) >= 0) { w = p->priv_cw[pr]; kx = tp[k * 2] - jx; ky = tp[k * 2 + 1] - jy; f += w * (kx * kx + ky * ky); pr++; } pr++; } #if !defined(QPS_HOIST) /* add loop penalties */ pr = 0; for (i = 0; i < p->loop_num; i++) { t = 0.0; j = st = p->loop_list[pr++]; jx = sx = tp[j * 2]; jy = sy = tp[j * 2 + 1]; while ((k = p->loop_list[pr]) >= 0) { kx = tp[k * 2]; ky = tp[k * 2 + 1]; tx = jx - kx; ty = jy - ky; t += tx * tx + ty * ty; j = k; jx = kx; jy = ky; pr++; } tx = jx - sx; ty = jy - sy; t += tx * tx + ty * ty; f += p->loop_penalty[i] * t; pr++; } #endif /* QPS_HOIST */ #if (QPS_DEBUG > 0) assert(f); #endif /* compute step size */ f = (dgg / f) / 2.0; for (j = p->priv_n; j--;) { p->priv_cp[j] += f * h[j]; } #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### qps_linmin() step %f\n", f); for (j = 0; j < p->priv_n; j++) { fprintf(p->priv_fp, "%f\n", p->priv_cp[j]); } #endif } /**********************************************************************/ static void qps_cgmin(qps_problem_t * p) { /* Perform CG minimization. Mostly from "Numerical Recipes", Press et al., Cambridge Univ. Press, 1992, with some changes to help performance in our restricted problem domain. */ qps_float_t fp, gg, dgg, gam; qps_float_t t; int i, j; int n = p->priv_n; qps_float_t *g = p->priv_g; qps_float_t *h = p->priv_h; qps_float_t *xi = p->priv_xi; qps_settp(p); fp = qps_func(p); qps_dfunc(p, g); dgg = 0.0; for (j = n; j--;) { g[j] = -g[j]; h[j] = g[j]; #if defined(QPS_PRECON) h[j] *= p->priv_pcgt[j]; #endif dgg += g[j] * h[j]; } for (i = 0; i < 2 * n; i++) { #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### qps_cgmin() top\n"); for (j = 0; j < p->priv_n; j++) { fprintf(p->priv_fp, "%f\n", p->priv_cp[j]); } #endif if (dgg == 0.0) { break; } qps_linmin(p, dgg, h); qps_settp(p); p->priv_f = qps_func(p); if (fabs((p->priv_f) - fp) <= (fabs(p->priv_f) + fabs(fp) + QPS_EPS) * QPS_TOL / 2.0) { break; } fp = p->priv_f; qps_dfunc(p, xi); gg = dgg; dgg = 0.0; for (j = n; j--;) { t = xi[j] * xi[j]; #if defined(QPS_PRECON) t *= p->priv_pcgt[j]; #endif dgg += t; } gam = dgg / gg; for (j = n; j--;) { g[j] = -xi[j]; t = g[j]; #if defined(QPS_PRECON) t *= p->priv_pcgt[j]; #endif h[j] = t + gam * h[j]; } } #if (QPS_DEBUG > 0) fprintf(p->priv_fp, "### CG ITERS=%d %d %d\n", i, p->cog_num, p->loop_num); #endif if (i == 2 * n) { fprintf(stderr, "### Too many iterations in qps_cgmin()\n"); #if defined(QPS_DEBUG) fprintf(p->priv_fp, "### Too many iterations in qps_cgmin()\n"); #endif } } /**********************************************************************/ void qps_init(qps_problem_t * p) { int i, j; int pr, pw; #if defined(QPS_DEBUG) p->priv_fp = fopen(QPS_DEBUG_FILE, "a"); assert(p->priv_fp); #endif #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### n=%d gn=%d ln=%d\n", p->num_cells, p->cog_num, p->loop_num); pr = 0; fprintf(p->priv_fp, "### (c w) values\n"); for (i = 0; i < p->num_cells; i++) { fprintf(p->priv_fp, "net %d: ", i); while (p->connect[pr] >= 0) { fprintf(p->priv_fp, "(%d %f) ", p->connect[pr], p->edge_weight[pr]); pr++; } fprintf(p->priv_fp, "(-1 -1.0)\n"); pr++; } fprintf(p->priv_fp, "### (x y f) values\n"); for (i = 0; i < p->num_cells; i++) { fprintf(p->priv_fp, "cell %d: (%f %f %d)\n", i, p->x[i], p->y[i], p->fixed[i]); } #if 0 if (p->cog_num) { fprintf(p->priv_fp, "### ga values\n"); for (i = 0; i < p->num_cells; i++) { fprintf(p->priv_fp, "cell %d: (%f)\n", i, p->area[i]); } } pr = 0; fprintf(p->priv_fp, "### gl values\n"); for (i = 0; i < p->cog_num; i++) { fprintf(p->priv_fp, "cog %d: ", i); while (p->cog_list[pr] >= 0) { fprintf(p->priv_fp, "%d ", p->cog_list[pr]); pr++; } fprintf(p->priv_fp, "-1\n"); pr++; } fprintf(p->priv_fp, "### (gx gy) values\n"); for (i = 0; i < p->cog_num; i++) { fprintf(p->priv_fp, "cog %d: (%f %f)\n", i, p->cog_x[i], p->cog_y[i]); } #endif #endif /* QPS_DEBUG */ p->priv_ii = (int *)malloc(p->num_cells * sizeof(int)); assert(p->priv_ii); p->max_enable = 0; p->priv_fopt = 0.0; /* canonify c and w */ pr = pw = 0; for (i = 0; i < p->num_cells; i++) { while ((j = p->connect[pr]) >= 0) { if (j > i) { pw++; } pr++; } pw++; pr++; } p->priv_cc = (int *)malloc(pw * sizeof(int)); assert(p->priv_cc); p->priv_cr = (int *)malloc(p->num_cells * sizeof(int)); assert(p->priv_cr); p->priv_cw = (qps_float_t*)malloc(pw * sizeof(qps_float_t)); assert(p->priv_cw); p->priv_ct = (qps_float_t*)malloc(pw * sizeof(qps_float_t)); assert(p->priv_ct); p->priv_cm = pw; pr = pw = 0; for (i = 0; i < p->num_cells; i++) { p->priv_cr[i] = pw; while ((j = p->connect[pr]) >= 0) { if (j > i) { p->priv_cc[pw] = p->connect[pr]; p->priv_ct[pw] = p->edge_weight[pr]; pw++; } pr++; } p->priv_cc[pw] = -1; p->priv_ct[pw] = -1.0; pw++; pr++; } assert(pw == p->priv_cm); /* temp arrays for function eval */ p->priv_tp = (qps_float_t *) malloc(4 * p->num_cells * sizeof(qps_float_t)); assert(p->priv_tp); p->priv_tp2 = p->priv_tp + 2 * p->num_cells; } /**********************************************************************/ static qps_float_t qps_estopt(qps_problem_t * p) { int i, j, cell; qps_float_t r; qps_float_t *t1, *t2; qps_float_t t; if (p->max_enable) { r = 0.0; t1 = (qps_float_t *) malloc(2 * p->num_cells * sizeof(qps_float_t)); #if (QPS_DEBUG > 0) assert(t1); #endif for (i = 2 * p->num_cells; i--;) { t1[i] = 0.0; } j = 0; for (i = 0; i < p->cog_num; i++) { while ((cell = p->cog_list[j]) >= 0) { t1[cell * 2] = p->cog_x[i]; t1[cell * 2 + 1] = p->cog_y[i]; j++; } j++; } t2 = p->priv_tp; p->priv_tp = t1; r = qps_func(p); p->priv_tp = t2; free(t1); t = (p->max_x * p->max_x + p->max_y * p->max_y); t *= p->num_cells; for (i = p->num_cells; i--;) { if (p->fixed[i]) { r += t; } } } else { r = p->priv_f; } if (p->loop_num) { /* FIXME hacky */ r *= 8.0; } return r; } /**********************************************************************/ static void qps_solve_inner(qps_problem_t * p) { int i; qps_float_t t; qps_float_t z; qps_float_t pm1, pm2, tp; qps_float_t *tw; #if defined(QPS_HOIST) int j, k; qps_float_t jx, jy, kx, ky, sx, sy, tx, ty; int pr, st; #endif tw = p->priv_cw; #if defined(QPS_HOIST) if (!p->loop_num) { p->priv_cw = p->priv_ct; } else { for(i=p->priv_cm; i--;) { p->priv_cw[i] = p->priv_ct[i]; } /* augment with loop penalties */ pr = 0; for (i = 0; i < p->loop_num; i++) { while ((j = p->priv_la[pr++]) != -1) { if (j >= 0) { p->priv_cw[j] += p->loop_penalty[i]; } } pr++; } } #else /* !QPS_HOIST */ p->priv_cw = p->priv_ct; #endif /* QPS_HOIST */ qps_cgmin(p); if (p->max_enable || p->loop_num) { if (p->max_enable == 1 || (p->loop_num && p->loop_k == 0)) { p->priv_eps = 2.0; p->priv_fmax = p->priv_f; p->priv_fprev = p->priv_f; p->priv_fopt = qps_estopt(p); p->priv_pn = 0; p->loop_fail = 0; } else { if (p->priv_f < p->priv_fprev && (p->priv_fprev - p->priv_f) > QPS_DEC_CHANGE * fabs(p->priv_fprev)) { if (p->priv_pn++ >= QPS_STEPSIZE_RETRIES) { p->priv_eps /= 2.0; p->priv_pn = 0; } } p->priv_fprev = p->priv_f; if (p->priv_fmax < p->priv_f) { p->priv_fmax = p->priv_f; } if (p->priv_f >= p->priv_fopt) { p->priv_fopt = p->priv_fmax * 2.0; p->loop_fail |= 2; #if (QPS_DEBUG > 0) fprintf(p->priv_fp, "### warning: changing fopt\n"); #endif } } #if (QPS_DEBUG > 0) fprintf(p->priv_fp, "### max_stat %.2e %.2e %.2e %.2e\n", p->priv_f, p->priv_eps, p->priv_fmax, p->priv_fopt); fflush(p->priv_fp); #endif } p->loop_done = 1; if (p->loop_num) { #if (QPS_DEBUG > 0) fprintf(p->priv_fp, "### begin_update %d\n", p->loop_k); #endif p->loop_k++; #if defined(QPS_HOIST) /* calc loop penalties */ pr = 0; for (i = 0; i < p->loop_num; i++) { t = 0.0; j = st = p->loop_list[pr++]; jx = sx = p->priv_tp[j * 2]; jy = sy = p->priv_tp[j * 2 + 1]; while ((k = p->loop_list[pr]) >= 0) { kx = p->priv_tp[k * 2]; ky = p->priv_tp[k * 2 + 1]; tx = jx - kx; ty = jy - ky; t += tx * tx + ty * ty; j = k; jx = kx; jy = ky; pr++; } tx = jx - sx; ty = jy - sy; t += tx * tx + ty * ty; p->priv_lt[i] = t - p->loop_max[i]; pr++; } #endif /* QPS_HOIST */ /* check KKT conditions */ #if (QPS_DEBUG > 1) for (i = p->loop_num; i--;) { if (p->loop_penalty[i] != 0.0) { fprintf(p->priv_fp, "### penalty %d %.2e\n", i, p->loop_penalty[i]); } } #endif t = 0.0; for (i = p->loop_num; i--;) { if (p->priv_lt[i] > 0.0 || p->loop_penalty[i] > 0.0) { t += p->priv_lt[i] * p->priv_lt[i]; } if (fabs(p->priv_lt[i]) < QPS_LOOP_TOL) { #if (QPS_DEBUG > 4) fprintf(p->priv_fp, "### skip %d %f\n", i, p->priv_lt[i]); #endif continue; } z = QPS_LOOP_TOL * p->loop_max[i]; if (p->priv_lt[i] > z || (p->loop_k < QPS_RELAX_ITER && p->loop_penalty[i] * p->priv_lt[i] < -z)) { p->loop_done = 0; #if (QPS_DEBUG > 1) fprintf(p->priv_fp, "### not_done %d %f %f %f %f\n", i, p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]); #endif } #if (QPS_DEBUG > 5) else { fprintf(p->priv_fp, "### done %d %f %f %f %f\n", i, p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]); } #endif } /* update penalties */ if (!p->loop_done) { t = p->priv_eps * (p->priv_fopt - p->priv_f) / t; tp = 0.0; for (i = p->loop_num; i--;) { pm1 = p->loop_penalty[i]; #if (QPS_DEBUG > 5) fprintf(p->priv_fp, "### update %d %.2e %.2e %.2e %.2e %.2e\n", i, t, p->priv_lt[i], t * p->priv_lt[i], pm1, p->loop_max[i]); #endif p->loop_penalty[i] += t * p->priv_lt[i]; if (p->loop_penalty[i] < 0.0) { p->loop_penalty[i] = 0.0; } pm2 = p->loop_penalty[i]; tp += fabs(pm1 - pm2); } #if (QPS_DEBUG > 4) fprintf(p->priv_fp, "### penalty mag %f\n", tp); #endif } } p->max_done = 1; if (p->max_enable) { #if (QPS_DEBUG > 4) fprintf(p->priv_fp, "### begin_max_update %d\n", p->max_enable); #endif t = 0.0; for (i = p->num_cells; i--;) { z = -(p->x[i]); t += z * z; if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER && p->priv_mxl[i] * z < -QPS_MAX_TOL)) { p->max_done = 0; #if (QPS_DEBUG > 4) fprintf(p->priv_fp, "### nxl %d %f %f\n", i, z, p->priv_mxl[i]); #endif } z = (p->x[i] - p->max_x); t += z * z; if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER && p->priv_mxh[i] * z < -QPS_MAX_TOL)) { p->max_done = 0; #if (QPS_DEBUG > 4) fprintf(p->priv_fp, "### nxh %d %f %f\n", i, z, p->priv_mxh[i]); #endif } z = -(p->y[i]); t += z * z; if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER && p->priv_myl[i] * z < -QPS_MAX_TOL)) { p->max_done = 0; #if (QPS_DEBUG > 4) fprintf(p->priv_fp, "### nyl %d %f %f\n", i, z, p->priv_myl[i]); #endif } z = (p->y[i] - p->max_y); t += z * z; if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER && p->priv_myh[i] * z < -QPS_MAX_TOL)) { p->max_done = 0; #if (QPS_DEBUG > 4) fprintf(p->priv_fp, "### nyh %d %f %f\n", i, z, p->priv_myh[i]); #endif } } #if (QPS_DEBUG > 4) fprintf(p->priv_fp, "### max_done %d %f\n", p->max_done, t); #endif if (!p->max_done) { t = p->priv_eps * (p->priv_fopt - p->priv_f) / t; tp = 0.0; for (i = p->num_cells; i--;) { z = -(p->x[i]); pm1 = p->priv_mxl[i]; p->priv_mxl[i] += t * z; if (p->priv_mxl[i] < 0.0) { p->priv_mxl[i] = 0.0; } pm2 = p->priv_mxl[i]; tp += fabs(pm1 - pm2); z = (p->x[i] - p->max_x); pm1 = p->priv_mxh[i]; p->priv_mxh[i] += t * z; if (p->priv_mxh[i] < 0.0) { p->priv_mxh[i] = 0.0; } pm2 = p->priv_mxh[i]; tp += fabs(pm1 - pm2); z = -(p->y[i]); pm1 = p->priv_myl[i]; p->priv_myl[i] += t * z; if (p->priv_myl[i] < 0.0) { p->priv_myl[i] = 0.0; } pm2 = p->priv_myl[i]; tp += fabs(pm1 - pm2); z = (p->y[i] - p->max_y); pm1 = p->priv_myh[i]; p->priv_myh[i] += t * z; if (p->priv_myh[i] < 0.0) { p->priv_myh[i] = 0.0; } pm2 = p->priv_myh[i]; tp += fabs(pm1 - pm2); } } #if (QPS_DEBUG > 4) for (i = p->num_cells; i--;) { fprintf(p->priv_fp, "### max_penalty %d %f %f %f %f\n", i, p->priv_mxl[i], p->priv_mxh[i], p->priv_myl[i], p->priv_myh[i]); } #endif p->max_enable++; } if (p->loop_k >= QPS_MAX_ITER || p->priv_eps < QPS_MINSTEP) { p->loop_fail |= 1; } if (p->loop_fail) { p->loop_done = 1; } p->priv_cw = tw; } /**********************************************************************/ void qps_solve(qps_problem_t * p) { int i, j; int pr, pw; qps_float_t bk; int tk; #if defined(QPS_PRECON) int c; qps_float_t t; #endif #if defined(QPS_HOIST) int k; int st; int m1, m2; #endif if (p->max_enable) { p->priv_mxl = (qps_float_t *) malloc(4 * p->num_cells * sizeof(qps_float_t)); assert(p->priv_mxl); p->priv_mxh = p->priv_mxl + p->num_cells; p->priv_myl = p->priv_mxl + 2 * p->num_cells; p->priv_myh = p->priv_mxl + 3 * p->num_cells; for (i = 4 * p->num_cells; i--;) { p->priv_mxl[i] = 0.0; } } /* flag fixed cells with -1 */ for (i = p->num_cells; i--;) { p->priv_ii[i] = (p->fixed[i]) ? (-1) : (0); } /* read gl and set up dependent variables */ if (p->cog_num) { p->priv_gt = (int *)malloc(p->cog_num * sizeof(int)); assert(p->priv_gt); p->priv_gm = (qps_float_t*)malloc(p->cog_num * sizeof(qps_float_t)); assert(p->priv_gm); pr = 0; for (i = 0; i < p->cog_num; i++) { tk = -1; bk = -1.0; pw = pr; while ((j = p->cog_list[pr++]) >= 0) { if (!p->fixed[j]) { /* use largest entry for numerical stability; see Gordian paper */ if (p->area[j] > bk) { tk = j; bk = p->area[j]; } } } assert(bk > 0.0); /* dependent variables have index=(-2-COG_constraint) */ p->priv_ii[tk] = -2 - i; p->priv_gt[i] = pw; p->priv_gm[i] = bk; } p->priv_gw = (qps_float_t*)malloc(pr * sizeof(qps_float_t)); assert(p->priv_gw); pr = 0; for (i = 0; i < p->cog_num; i++) { while ((j = p->cog_list[pr]) >= 0) { p->priv_gw[pr] = p->area[j] / p->priv_gm[i]; pr++; } p->priv_gw[pr] = -1.0; pr++; } } /* set up indexes from independent floating cells to variables */ p->priv_n = 0; for (i = p->num_cells; i--;) { if (!p->priv_ii[i]) { p->priv_ii[i] = 2 * (p->priv_n++); } } p->priv_n *= 2; #if (QPS_DEBUG > 5) for (i = 0; i < p->num_cells; i++) { fprintf(p->priv_fp, "### ii %d %d\n", i, p->priv_ii[i]); } #endif #if defined(QPS_PRECON) p->priv_pcg = (qps_float_t *) malloc(p->num_cells * sizeof(qps_float_t)); assert(p->priv_pcg); p->priv_pcgt = (qps_float_t *) malloc(p->priv_n * sizeof(qps_float_t)); assert(p->priv_pcgt); for (i = p->num_cells; i--;) { p->priv_pcg[i] = 0.0; } pr = 0; for (i = 0; i < p->num_cells; i++) { while ((c = p->priv_cc[pr]) >= 0) { t = p->priv_ct[pr]; p->priv_pcg[i] += t; p->priv_pcg[c] += t; pr++; } pr++; } pr = 0; for (i = 0; i < p->loop_num; i++) { t = 2.0 * p->loop_penalty[i]; while ((c = p->loop_list[pr++]) >= 0) { p->priv_pcg[c] += t; } pr++; } #if (QPS_DEBUG > 6) for (i = p->num_cells; i--;) { fprintf(p->priv_fp, "### precon %d %.2e\n", i, p->priv_pcg[i]); } #endif for (i = p->priv_n; i--;) { p->priv_pcgt[i] = 0.0; } for (i = 0; i < p->num_cells; i++) { c = p->priv_ii[i]; if (c >= 0) { t = p->priv_pcg[i]; p->priv_pcgt[c] += t; p->priv_pcgt[c + 1] += t; } #if 0 else if (c < -1) { pr = p->priv_gt[-(c+2)]; while ((j = p->cog_list[pr++]) >= 0) { ji = p->priv_ii[j]; if (ji >= 0) { w = p->area[j] / p->area[i]; t = w * w * p->priv_pcg[i]; p->priv_pcgt[ji] += t; p->priv_pcgt[ji + 1] += t; } } } #endif } for (i = 0; i < p->priv_n; i++) { t = p->priv_pcgt[i]; if (fabs(t) < QPS_PRECON_EPS || fabs(t) > 1.0/QPS_PRECON_EPS) { p->priv_pcgt[i] = 1.0; } else { p->priv_pcgt[i] = 1.0 / p->priv_pcgt[i]; } } #endif /* allocate variable storage */ p->priv_cp = (qps_float_t *) malloc(4 * p->priv_n * sizeof(qps_float_t)); assert(p->priv_cp); /* temp arrays for cg */ p->priv_g = p->priv_cp + p->priv_n; p->priv_h = p->priv_cp + 2 * p->priv_n; p->priv_xi = p->priv_cp + 3 * p->priv_n; /* set values */ for (i = p->num_cells; i--;) { if (p->priv_ii[i] >= 0) { p->priv_cp[p->priv_ii[i]] = p->x[i]; p->priv_cp[p->priv_ii[i] + 1] = p->y[i]; } } if (p->loop_num) { p->priv_lt = (qps_float_t *) malloc(p->loop_num * sizeof(qps_float_t)); assert(p->priv_lt); #if defined(QPS_HOIST) pr = 0; for (i=p->loop_num; i--;) { while (p->loop_list[pr++] >= 0) { } pr++; } p->priv_lm = pr; p->priv_la = (int *) malloc(pr * sizeof(int)); assert(p->priv_la); pr = 0; for (i = 0; i < p->loop_num; i++) { j = st = p->loop_list[pr++]; while ((k = p->loop_list[pr]) >= 0) { if (j > k) { m1 = k; m2 = j; } else { assert(k > j); m1 = j; m2 = k; } pw = p->priv_cr[m1]; while (p->priv_cc[pw] != m2) { /* assert(p->priv_cc[pw] >= 0); */ if (p->priv_cc[pw] < 0) { pw = -2; break; } pw++; } p->priv_la[pr-1] = pw; j = k; pr++; } if (j > st) { m1 = st; m2 = j; } else { assert(st > j); m1 = j; m2 = st; } pw = p->priv_cr[m1]; while (p->priv_cc[pw] != m2) { /* assert(p->priv_cc[pw] >= 0); */ if (p->priv_cc[pw] < 0) { pw = -2; break; } pw++; } p->priv_la[pr-1] = pw; p->priv_la[pr] = -1; pr++; } #endif /* QPS_HOIST */ } do { qps_solve_inner(p); } while (!p->loop_done || !p->max_done); /* retrieve values */ /* qps_settp() should have already been called at this point */ for (i = p->num_cells; i--;) { p->x[i] = p->priv_tp[i * 2]; p->y[i] = p->priv_tp[i * 2 + 1]; } #if (QPS_DEBUG > 5) for (i = p->num_cells; i--;) { fprintf(p->priv_fp, "### cloc %d %f %f\n", i, p->x[i], p->y[i]); } #endif free(p->priv_cp); if (p->max_enable) { free(p->priv_mxl); } if (p->cog_num) { free(p->priv_gt); free(p->priv_gm); free(p->priv_gw); } if(p->loop_num) { free(p->priv_lt); #if defined(QPS_HOIST) free(p->priv_la); #endif } #if defined(QPS_PRECON) free(p->priv_pcg); free(p->priv_pcgt); #endif } /**********************************************************************/ void qps_clean(qps_problem_t * p) { free(p->priv_tp); free(p->priv_ii); free(p->priv_cc); free(p->priv_cr); free(p->priv_cw); free(p->priv_ct); #if defined(QPS_DEBUG) fclose(p->priv_fp); #endif /* QPS_DEBUG */ } /**********************************************************************/ ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_qpsolver.h000066400000000000000000000113541300674244400252770ustar00rootroot00000000000000/*===================================================================*/ // // place_qpsolver.h // // Philip Chong // pchong@cadence.com // /*===================================================================*/ #if !defined(_QPS_H) #define ABC__phys__place__place_qpsolver_h #include ABC_NAMESPACE_HEADER_START typedef float qps_float_t; typedef struct qps_problem { /* Basic stuff */ int num_cells; /* Total number of cells (both fixed and floating) to be placed. */ int *connect; /* Connectivity array. Must contain at least num_cells elements with value -1. The entries which precede the first element with value -1 are the indices of the cells which connect to cell 0; the entries which lie between the first and second elements with value -1 are the indices of the cells which connect to cell 1; etc. Example: cells 0 and 1 are connected together, and 1 and 2 are connected as well. *connect = { 1, -1, 0, 2, -1, 1, -1 }. */ qps_float_t *edge_weight; /* Same structure as connectivity array, but giving the weights assigned to each edge instead. */ qps_float_t *x; /* num_cells element array which contains the x-coordinates of the cells. This is used for the initial values in the iterative solution of floating cells, and for the fixed location of fixed cells. */ qps_float_t *y; /* num_cells element array of y-coordinates. */ int *fixed; /* num_cells element array with value 1 if corresponding cell is fixed, 0 if floating. */ qps_float_t f; /* return value for sum-of-square wirelengths. */ /* COG stuff */ int cog_num; /* Number of COG constraints. */ int *cog_list; /* Array indicating for each COG constraint which cells belong to that constraint. Format is similar to c array: there must be at least cog_num elements with value -1. The entries of cog_list preceding the first -1 element are the indices of the cells which belong to the first COG constraint; etc. Example: cells 0 and 1 belong to one COG constraint, cells 4 and 5 belong to another. *cog_list= { 0, 1, -1, 4, 5, -1 }. */ qps_float_t *cog_x; /* cog_num element array whose values are the x-coordinates for the corresponding COG constraints. */ qps_float_t *cog_y; /* cog_num element array whose values are the y-coordinates for the corresponding COG constraints. */ qps_float_t *area; /* num_cells element array whose values are the areas for the corresponding cells; only useful with COG constraints. */ /* Loop constraint stuff */ int loop_num; /* Number of loop constraints. */ int *loop_list; /* Array with list of cells for each loop constraint. Format is similar to cog_list. */ qps_float_t *loop_max; /* loop_num element array indicating maximum distance for each loop. */ qps_float_t *loop_penalty; /* loop_num element array indicating penalty for each loop. */ int loop_k; /* Current iteration for loop optimization. */ int loop_done; /* Done flag for loop optimization. */ int loop_fail; /* max_x/max_y stuff */ qps_float_t max_x; /* max x location; only used in constrained optimization. */ qps_float_t max_y; /* max y location; only used in constrained optimization. */ int max_enable; /* Set to 1 after qps_init() to enable max_x/max_y. */ int max_done; /* Done flag for max optimization. */ /* Private stuff */ int *priv_ii; int *priv_cc, *priv_cr; qps_float_t *priv_cw, *priv_ct; int priv_cm; int *priv_gt; int *priv_la; int priv_lm; qps_float_t *priv_gm, *priv_gw; qps_float_t *priv_g, *priv_h, *priv_xi; qps_float_t *priv_tp, *priv_tp2; int priv_n; qps_float_t *priv_cp; qps_float_t priv_f; qps_float_t *priv_lt; qps_float_t *priv_pcg, *priv_pcgt; qps_float_t priv_fmax; qps_float_t priv_fprev; qps_float_t priv_fopt; qps_float_t priv_eps; int priv_pn; qps_float_t *priv_mxl, *priv_mxh, *priv_myl, *priv_myh; int priv_ik; FILE *priv_fp; } qps_problem_t; /* call qps_init() as soon as the qps_problem_t has been set up */ /* this initializes some private data structures */ extern void qps_init(qps_problem_t *); /* call qps_solve() to solve the given qp problem */ extern void qps_solve(qps_problem_t *); /* call qps_clean() when finished with the qps_problem_t */ /* this discards the private data structures assigned by qps_init() */ extern void qps_clean(qps_problem_t *); ABC_NAMESPACE_HEADER_END #endif /* _QPS_H */ berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/phys/place/place_test.c000066400000000000000000000224411300674244400243750ustar00rootroot00000000000000/*===================================================================*/ // // place_test.c // // Aaron P. Hurst, 2003-2007 // ahurst@eecs.berkeley.edu // /*===================================================================*/ #include #include #include #include #include "place_base.h" ABC_NAMESPACE_IMPL_START // -------------------------------------------------------------------- // Hash type/functions // // -------------------------------------------------------------------- struct hash_element { ConcreteCell *obj; struct hash_element *next; } hash_element; int hash_string(int hash_max, const char *str) { unsigned int hash = 0; int p; for(p = 0; pm_label); // printf("adding %s key = %d\n", cell->m_label, key); struct hash_element *element = malloc(sizeof(struct hash_element)); assert(element); element->obj = cell; element->next = hash[key]; hash[key] = element; } ConcreteCell *hash_find(struct hash_element **hash, int hash_max, const char *str) { int key = hash_string(hash_max, str); // printf("looking for %s key = %d\n", str, key); struct hash_element *next = hash[key]; while(next) { if (!strcmp(str, next->obj->m_label)) return next->obj; next = next->next; } return 0; } // -------------------------------------------------------------------- // Global variables // // -------------------------------------------------------------------- struct hash_element **hash_cellname; int numCells = 0, numNets = 0; AbstractCell *abstractCells; ConcreteCell *concreteCells; ConcreteNet *concreteNets; // -------------------------------------------------------------------- // Function implementations // // -------------------------------------------------------------------- void readBookshelfNets(char *filename) { char *tok; char buf[1024]; const char *DELIMITERS = " \n\t:"; int id = 0; int t; ConcreteCell *cell; FILE *netsFile = fopen(filename, "r"); if (!netsFile) { printf("ERROR: Could not open .nets file\n"); exit(1); } // line 1 : version while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#')); // line 2 : number of nets while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#')); tok = strtok(buf, DELIMITERS); tok = strtok(NULL, DELIMITERS); numNets = atoi(tok); printf("READ-20 : number of nets = %d\n", numNets); concreteNets = malloc(sizeof(ConcreteNet)*numNets); // line 3 : number of pins while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#')); // line XXX : net definitions while(fgets(buf, 1024, netsFile)) { if (buf[0] == '\n' || buf[0] == '#') continue; concreteNets[id].m_id = id; concreteNets[id].m_weight = 1.0; tok = strtok(buf, DELIMITERS); if (!!strcmp(tok, "NetDegree")) { printf("%s\n",buf); printf("ERROR: Incorrect format in .nets file\n"); exit(1); } tok = strtok(NULL, DELIMITERS); concreteNets[id].m_numTerms = atoi(tok); if (concreteNets[id].m_numTerms < 0 || concreteNets[id].m_numTerms > 100000) { printf("ERROR: Bad net degree\n"); exit(1); } concreteNets[id].m_terms = malloc(sizeof(ConcreteCell*)* concreteNets[id].m_numTerms); // read terms t = 0; while(t < concreteNets[id].m_numTerms && fgets(buf, 1024, netsFile)) { if (buf[0] == '\n' || buf[0] == '#') continue; // cell name tok = strtok(buf, DELIMITERS); cell = hash_find(hash_cellname, numCells, tok); if (!cell) { printf("ERROR: Could not find cell %s in .nodes file\n", tok); exit(1); } concreteNets[id].m_terms[t] = cell; t++; } // add! addConcreteNet(&(concreteNets[id])); id++; } fclose(netsFile); } void readBookshelfNodes(char *filename) { char *tok; char buf[1024]; const char *DELIMITERS = " \n\t:"; int id = 0; FILE *nodesFile = fopen(filename, "r"); if (!nodesFile) { printf("ERROR: Could not open .nodes file\n"); exit(1); } // line 1 : version while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#')); // line 2 : num nodes while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#')); tok = strtok(buf, DELIMITERS); tok = strtok(NULL, DELIMITERS); numCells = atoi(tok); printf("READ-10 : number of cells = %d\n", numCells); concreteCells = malloc(sizeof(ConcreteCell)*numCells); abstractCells = malloc(sizeof(AbstractCell)*numCells); hash_cellname = calloc(numCells, sizeof(struct hash_element*)); // line 3 : num terminals while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#')); // line XXX : cell definitions while(fgets(buf, 1024, nodesFile)) { if (buf[0] == '\n' || buf[0] == '#') continue; tok = strtok(buf, DELIMITERS); concreteCells[id].m_id = id;; // label concreteCells[id].m_parent = &(abstractCells[id]); concreteCells[id].m_label = malloc(sizeof(char)*strlen(tok)+1); strcpy(concreteCells[id].m_label, tok); abstractCells[id].m_label = concreteCells[id].m_label; hash_add(hash_cellname, numCells, &(concreteCells[id])); // dimensions tok = strtok(NULL, DELIMITERS); abstractCells[id].m_width = atof(tok); tok = strtok(NULL, DELIMITERS); abstractCells[id].m_height = atof(tok); tok = strtok(NULL, DELIMITERS); // terminal abstractCells[id].m_pad = tok && !strcmp(tok, "terminal"); // add! addConcreteCell(&(concreteCells[id])); // DEBUG /* printf("\"%s\" : %f x %f\n", concreteCells[id].m_label, abstractCells[id].m_width, abstractCells[id].m_height); */ id++; } fclose(nodesFile); } void readBookshelfPlacement(char *filename) { char *tok; char buf[1024]; const char *DELIMITERS = " \n\t:"; ConcreteCell *cell; FILE *plFile = fopen(filename, "r"); FILE *netsFile = fopen(filename, "r"); if (!plFile) { printf("ERROR: Could not open .pl file\n"); exit(1); } if (!netsFile) { printf("ERROR: Could not open .nets file\n"); exit(1); } // line 1 : version while (fgets(buf, 1024, plFile) && (buf[0] == '\n' || buf[0] == '#')); // line XXX : placement definitions while(fgets(buf, 1024, plFile)) { if (buf[0] == '\n' || buf[0] == '#') continue; tok = strtok(buf, DELIMITERS); // cell name cell = hash_find(hash_cellname, numCells, tok); if (!cell) { printf("ERROR: Could not find cell %s in .nodes file\n",tok); exit(1); } // position tok = strtok(NULL, DELIMITERS); cell->m_x = atof(tok); tok = strtok(NULL, DELIMITERS); cell->m_y = atof(tok); // hfixed cell->m_fixed = strtok(NULL, DELIMITERS) && (tok = strtok(NULL, DELIMITERS)) && !strcmp(tok, "\\FIXED"); } fclose(plFile); } void writeBookshelfPlacement(char *filename) { int c = 0; FILE *plFile = fopen(filename, "w"); if (!plFile) { printf("ERROR: Could not open .pl file\n"); exit(1); } fprintf(plFile, "UCLA pl 1.0\n"); for(c=0; cm_numTerms; t++) if (net->m_terms[t] == cell) count++; if (count) { memcpy(old, net->m_terms, sizeof(ConcreteCell*)*net->m_numTerms); net->m_terms = realloc(net->m_terms, sizeof(ConcreteCell*)*(net->m_numTerms-count)); t2 = 0; for(t=0; tm_numTerms; t++) if (old[t] != cell) net->m_terms[t2++] = old[t]; net->m_numTerms -= count; } } free(old); } int main(int argc, char **argv) { if (argc != 4) { printf("Usage: %s [nodes] [nets] [pl]\n", argv[0]); exit(1); } readBookshelfNodes(argv[1]); readBookshelfNets(argv[2]); readBookshelfPlacement(argv[3]); globalPreplace(0.8); globalPlace(); // DEBUG net/cell removal/addition /* int i; for(i=1000; i<2000; i++) { delConcreteNet(g_place_concreteNets[i]); delNetConnections(g_place_concreteCells[i]); delConcreteCell(g_place_concreteCells[i]); } ConcreteCell newCell[2]; newCell[0].m_id = g_place_numCells+1; newCell[0].m_x = 1000; newCell[0].m_y = 1000; newCell[0].m_fixed = false; newCell[0].m_parent = &(abstractCells[1000]); newCell[0].m_label = " "; addConcreteCell(&newCell[0]); newCell[1].m_id = g_place_numCells+3; newCell[1].m_x = 1000; newCell[1].m_y = 1000; newCell[1].m_fixed = false; newCell[1].m_parent = &(abstractCells[1000]); newCell[1].m_label = " "; addConcreteCell(&newCell[1]); */ globalIncremental(); writeBookshelfPlacement(argv[3]); free(hash_cellname); return 0; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/000077500000000000000000000000001300674244400211615ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/000077500000000000000000000000001300674244400217265ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/abs.c000066400000000000000000000026611300674244400226440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/abs.h000066400000000000000000000253761300674244400226610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abs.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abs.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__proof_abs__Abs_h #define ABC__proof_abs__Abs_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "aig/gia/giaAig.h" #include "aig/saig/saig.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // abstraction parameters typedef struct Abs_Par_t_ Abs_Par_t; struct Abs_Par_t_ { int nFramesMax; // maximum frames int nFramesStart; // starting frame int nFramesPast; // overlap frames int nConfLimit; // conflict limit int nLearnedMax; // max number of learned clauses int nLearnedStart; // max number of learned clauses int nLearnedDelta; // delta increase of learned clauses int nLearnedPerce; // percentage of clauses to leave int nTimeOut; // timeout in seconds int nRatioMin; // stop when less than this % of object is unabstracted int nRatioMin2; // stop when less than this % of object is unabstracted during refinement int nRatioMax; // restart when the number of abstracted object is more than this int fUseTermVars; // use terminal variables int fUseRollback; // use rollback to the starting number of frames int fPropFanout; // propagate fanout implications int fAddLayer; // refinement strategy by adding layers int fNewRefine; // uses new refinement heuristics int fUseSkip; // skip proving intermediate timeframes int fUseSimple; // use simple CNF construction int fSkipHash; // skip hashing CNF while unrolling int fUseFullProof; // use full proof for UNSAT cores int fDumpVabs; // dumps the abstracted model int fDumpMabs; // dumps the original AIG with abstraction map int fCallProver; // calls the prover int fSimpProver; // calls simplification before prover char * pFileVabs; // dumps the abstracted model into this file int fVerbose; // verbose flag int fVeryVerbose; // print additional information int iFrame; // the number of frames covered int iFrameProved; // the number of frames proved int nFramesNoChange; // the number of last frames without changes int nFramesNoChangeLim; // the number of last frames without changes to dump abstraction }; // old abstraction parameters typedef struct Gia_ParAbs_t_ Gia_ParAbs_t; struct Gia_ParAbs_t_ { int Algo; // the algorithm to be used int nFramesMax; // timeframes for PBA int nConfMax; // conflicts for PBA int fDynamic; // dynamic unfolding for PBA int fConstr; // use constraints int nFramesBmc; // timeframes for BMC int nConfMaxBmc; // conflicts for BMC int nStableMax; // the number of stable frames to quit int nRatio; // ratio of flops to quit int TimeOut; // approximate timeout in seconds int TimeOutVT; // approximate timeout in seconds int nBobPar; // Bob's parameter int fUseBdds; // use BDDs to refine abstraction int fUseDprove; // use 'dprove' to refine abstraction int fUseStart; // use starting frame int fVerbose; // verbose output int fVeryVerbose; // printing additional information int Status; // the problem status int nFramesDone; // the number of frames covered }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Ga2_ObjOffset( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry(p->vMapping, Gia_ObjId(p, pObj)); } static inline int Ga2_ObjLeaveNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj)); } static inline int * Ga2_ObjLeavePtr( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntryP(p->vMapping, Ga2_ObjOffset(p, pObj) + 1); } static inline unsigned Ga2_ObjTruth( Gia_Man_t * p, Gia_Obj_t * pObj ) { return (unsigned)Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj) + Ga2_ObjLeaveNum(p, pObj) + 1); } static inline int Ga2_ObjRefNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { return (unsigned)Vec_IntEntry(p->vMapping, Ga2_ObjOffset(p, pObj) + Ga2_ObjLeaveNum(p, pObj) + 2); } static inline Vec_Int_t * Ga2_ObjLeaves( Gia_Man_t * p, Gia_Obj_t * pObj ) { static Vec_Int_t v; v.nSize = Ga2_ObjLeaveNum(p, pObj), v.pArray = Ga2_ObjLeavePtr(p, pObj); return &v; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== abs.c =========================================================*/ /*=== absDup.c =========================================================*/ extern Gia_Man_t * Gia_ManDupAbsFlops( Gia_Man_t * p, Vec_Int_t * vFlopClasses ); extern Gia_Man_t * Gia_ManDupAbsGates( Gia_Man_t * p, Vec_Int_t * vGateClasses ); extern void Gia_ManGlaCollect( Gia_Man_t * p, Vec_Int_t * vGateClasses, Vec_Int_t ** pvPis, Vec_Int_t ** pvPPis, Vec_Int_t ** pvFlops, Vec_Int_t ** pvNodes ); extern void Gia_ManPrintFlopClasses( Gia_Man_t * p ); extern void Gia_ManPrintObjClasses( Gia_Man_t * p ); extern void Gia_ManPrintGateClasses( Gia_Man_t * p ); /*=== absGla.c =========================================================*/ extern int Gia_ManPerformGla( Gia_Man_t * p, Abs_Par_t * pPars ); /*=== absGlaOld.c =========================================================*/ extern int Gia_ManPerformGlaOld( Gia_Man_t * p, Abs_Par_t * pPars, int fStartVta ); /*=== absIter.c =========================================================*/ extern Gia_Man_t * Gia_ManShrinkGla( Gia_Man_t * p, int nFrameMax, int nTimeOut, int fUsePdr, int fUseSat, int fUseBdd, int fVerbose ); /*=== absPth.c =========================================================*/ extern void Gia_GlaProveAbsracted( Gia_Man_t * p, int fSimpProver, int fVerbose ); extern void Gia_GlaProveCancel( int fVerbose ); extern int Gia_GlaProveCheck( int fVerbose ); /*=== absVta.c =========================================================*/ extern int Gia_VtaPerform( Gia_Man_t * pAig, Abs_Par_t * pPars ); /*=== absUtil.c =========================================================*/ extern void Abs_ParSetDefaults( Abs_Par_t * p ); extern Vec_Int_t * Gia_VtaConvertToGla( Gia_Man_t * p, Vec_Int_t * vVta ); extern Vec_Int_t * Gia_VtaConvertFromGla( Gia_Man_t * p, Vec_Int_t * vGla, int nFrames ); extern Vec_Int_t * Gia_FlaConvertToGla( Gia_Man_t * p, Vec_Int_t * vFla ); extern Vec_Int_t * Gia_GlaConvertToFla( Gia_Man_t * p, Vec_Int_t * vGla ); extern int Gia_GlaCountFlops( Gia_Man_t * p, Vec_Int_t * vGla ); extern int Gia_GlaCountNodes( Gia_Man_t * p, Vec_Int_t * vGla ); /*=== absRpm.c =========================================================*/ extern Gia_Man_t * Abs_RpmPerform( Gia_Man_t * p, int nCutMax, int fVerbose, int fVeryVerbose ); /*=== absRpmOld.c =========================================================*/ extern Gia_Man_t * Abs_RpmPerformOld( Gia_Man_t * p, int fVerbose ); extern void Gia_ManAbsSetDefaultParams( Gia_ParAbs_t * p ); extern Vec_Int_t * Saig_ManCexAbstractionFlops( Aig_Man_t * p, Gia_ParAbs_t * pPars ); /*=== absOldCex.c ==========================================================*/ extern Vec_Int_t * Saig_ManCbaFilterFlops( Aig_Man_t * pAig, Abc_Cex_t * pAbsCex, Vec_Int_t * vFlopClasses, Vec_Int_t * vAbsFfsToAdd, int nFfsToSelect ); extern Abc_Cex_t * Saig_ManCbaFindCexCareBits( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose ); /*=== absOldRef.c ==========================================================*/ extern int Gia_ManCexAbstractionRefine( Gia_Man_t * pGia, Abc_Cex_t * pCex, int nFfToAddMax, int fTryFour, int fSensePath, int fVerbose ); /*=== absOldSat.c ==========================================================*/ extern Vec_Int_t * Saig_ManExtendCounterExampleTest3( Aig_Man_t * pAig, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose ); /*=== absOldSim.c ==========================================================*/ extern Vec_Int_t * Saig_ManExtendCounterExampleTest2( Aig_Man_t * p, int iFirstPi, Abc_Cex_t * pCex, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absDup.c000066400000000000000000000356051300674244400233210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absDup.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Duplication procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupAbsFlops_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) ); Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Extractes a flop-level abstraction given a flop map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupAbsFlops( Gia_Man_t * p, Vec_Int_t * vFlopClasses ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, nFlops = 0; Gia_ManFillValue( p ); // start the new manager pNew = Gia_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create PIs Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create additional PIs Gia_ManForEachRo( p, pObj, i ) if ( !Vec_IntEntry(vFlopClasses, i) ) pObj->Value = Gia_ManAppendCi(pNew); // create ROs Gia_ManForEachRo( p, pObj, i ) if ( Vec_IntEntry(vFlopClasses, i) ) pObj->Value = Gia_ManAppendCi(pNew); // create POs Gia_ManHashAlloc( pNew ); Gia_ManForEachPo( p, pObj, i ) { Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } // create RIs Gia_ManForEachRi( p, pObj, i ) if ( Vec_IntEntry(vFlopClasses, i) ) { Gia_ManDupAbsFlops_rec( pNew, Gia_ObjFanin0(pObj) ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); nFlops++; } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, nFlops ); // clean up pNew = Gia_ManSeqCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Returns the array of neighbors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_GlaCollectAssigned( Gia_Man_t * p, Vec_Int_t * vGateClasses ) { Vec_Int_t * vAssigned; Gia_Obj_t * pObj; int i, Entry; vAssigned = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( vGateClasses, Entry, i ) { if ( Entry == 0 ) continue; assert( Entry > 0 ); pObj = Gia_ManObj( p, i ); Vec_IntPush( vAssigned, Gia_ObjId(p, pObj) ); if ( Gia_ObjIsAnd(pObj) ) { Vec_IntPush( vAssigned, Gia_ObjFaninId0p(p, pObj) ); Vec_IntPush( vAssigned, Gia_ObjFaninId1p(p, pObj) ); } else if ( Gia_ObjIsRo(p, pObj) ) Vec_IntPush( vAssigned, Gia_ObjFaninId0p(p, Gia_ObjRoToRi(p, pObj)) ); else assert( Gia_ObjIsConst0(pObj) ); } Vec_IntUniqify( vAssigned ); return vAssigned; } /**Function************************************************************* Synopsis [Collects PIs and PPIs of the abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManGlaCollect( Gia_Man_t * p, Vec_Int_t * vGateClasses, Vec_Int_t ** pvPis, Vec_Int_t ** pvPPis, Vec_Int_t ** pvFlops, Vec_Int_t ** pvNodes ) { Vec_Int_t * vAssigned; Gia_Obj_t * pObj; int i; assert( Gia_ManPoNum(p) == 1 ); assert( Vec_IntSize(vGateClasses) == Gia_ManObjNum(p) ); // create included objects and their fanins vAssigned = Gia_GlaCollectAssigned( p, vGateClasses ); // create additional arrays if ( pvPis ) *pvPis = Vec_IntAlloc( 100 ); if ( pvPPis ) *pvPPis = Vec_IntAlloc( 100 ); if ( pvFlops ) *pvFlops = Vec_IntAlloc( 100 ); if ( pvNodes ) *pvNodes = Vec_IntAlloc( 1000 ); Gia_ManForEachObjVec( vAssigned, p, pObj, i ) { if ( Gia_ObjIsPi(p, pObj) ) { if ( pvPis ) Vec_IntPush( *pvPis, Gia_ObjId(p,pObj) ); } else if ( !Vec_IntEntry(vGateClasses, Gia_ObjId(p,pObj)) ) { if ( pvPPis ) Vec_IntPush( *pvPPis, Gia_ObjId(p,pObj) ); } else if ( Gia_ObjIsRo(p, pObj) ) { if ( pvFlops ) Vec_IntPush( *pvFlops, Gia_ObjId(p,pObj) ); } else if ( Gia_ObjIsAnd(pObj) ) { if ( pvNodes ) Vec_IntPush( *pvNodes, Gia_ObjId(p,pObj) ); } else assert( Gia_ObjIsConst0(pObj) ); } Vec_IntFree( vAssigned ); } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupAbsGates_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupAbsGates_rec( pNew, Gia_ObjFanin0(pObj) ); Gia_ManDupAbsGates_rec( pNew, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Extractes a gate-level abstraction given a gate map.] Description [The array contains 1 for those objects (const, RO, AND) that are included in the abstraction; 0, otherwise.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupAbsGates( Gia_Man_t * p, Vec_Int_t * vGateClasses ) { Vec_Int_t * vPis, * vPPis, * vFlops, * vNodes; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pCopy; int i;//, nFlops = 0; assert( Gia_ManPoNum(p) == 1 ); assert( Vec_IntSize(vGateClasses) == Gia_ManObjNum(p) ); // create additional arrays Gia_ManGlaCollect( p, vGateClasses, &vPis, &vPPis, &vFlops, &vNodes ); // start the new manager pNew = Gia_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create constant Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; // create PIs Gia_ManForEachObjVec( vPis, p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create additional PIs Gia_ManForEachObjVec( vPPis, p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create ROs Gia_ManForEachObjVec( vFlops, p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create internal nodes Gia_ManForEachObjVec( vNodes, p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // Gia_ManDupAbsGates_rec( pNew, pObj ); // create PO Gia_ManForEachPo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // create RIs Gia_ManForEachObjVec( vFlops, p, pObj, i ) Gia_ObjRoToRi(p, pObj)->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ObjRoToRi(p, pObj)) ); Gia_ManSetRegNum( pNew, Vec_IntSize(vFlops) ); // clean up pNew = Gia_ManSeqCleanup( pTemp = pNew ); // transfer copy values: (p -> pTemp -> pNew) => (p -> pNew) if ( Gia_ManObjNum(pTemp) != Gia_ManObjNum(pNew) ) { // printf( "Gia_ManDupAbsGates() Internal error: object mismatch.\n" ); Gia_ManForEachObj( p, pObj, i ) { if ( !~pObj->Value ) continue; assert( !Abc_LitIsCompl(pObj->Value) ); pCopy = Gia_ObjCopy( pTemp, pObj ); if ( !~pCopy->Value ) { Vec_IntWriteEntry( vGateClasses, i, 0 ); pObj->Value = ~0; continue; } assert( !Abc_LitIsCompl(pCopy->Value) ); pObj->Value = pCopy->Value; } } Gia_ManStop( pTemp ); Vec_IntFree( vPis ); Vec_IntFree( vPPis ); Vec_IntFree( vFlops ); Vec_IntFree( vNodes ); return pNew; } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintFlopClasses( Gia_Man_t * p ) { int Counter0, Counter1; if ( p->vFlopClasses == NULL ) return; if ( Vec_IntSize(p->vFlopClasses) != Gia_ManRegNum(p) ) { printf( "Gia_ManPrintFlopClasses(): The number of flop map entries differs from the number of flops.\n" ); return; } Counter0 = Vec_IntCountEntry( p->vFlopClasses, 0 ); Counter1 = Vec_IntCountEntry( p->vFlopClasses, 1 ); printf( "Flop-level abstraction: Excluded FFs = %d Included FFs = %d (%.2f %%) ", Counter0, Counter1, 100.0*Counter1/(Counter0 + Counter1 + 1) ); if ( Counter0 + Counter1 < Gia_ManRegNum(p) ) printf( "and there are other FF classes..." ); printf( "\n" ); } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintGateClasses( Gia_Man_t * p ) { Vec_Int_t * vPis, * vPPis, * vFlops, * vNodes; int nTotal; if ( p->vGateClasses == NULL ) return; if ( Vec_IntSize(p->vGateClasses) != Gia_ManObjNum(p) ) { printf( "Gia_ManPrintGateClasses(): The number of flop map entries differs from the number of flops.\n" ); return; } // create additional arrays Gia_ManGlaCollect( p, p->vGateClasses, &vPis, &vPPis, &vFlops, &vNodes ); nTotal = 1 + Vec_IntSize(vFlops) + Vec_IntSize(vNodes); printf( "Gate-level abstraction: PI = %d PPI = %d FF = %d (%.2f %%) AND = %d (%.2f %%) Obj = %d (%.2f %%)\n", Vec_IntSize(vPis), Vec_IntSize(vPPis), Vec_IntSize(vFlops), 100.0*Vec_IntSize(vFlops)/(Gia_ManRegNum(p)+1), Vec_IntSize(vNodes), 100.0*Vec_IntSize(vNodes)/(Gia_ManAndNum(p)+1), nTotal, 100.0*nTotal /(Gia_ManRegNum(p)+Gia_ManAndNum(p)+1) ); Vec_IntFree( vPis ); Vec_IntFree( vPPis ); Vec_IntFree( vFlops ); Vec_IntFree( vNodes ); } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintObjClasses( Gia_Man_t * p ) { Vec_Int_t * vSeens; // objects seen so far Vec_Int_t * vAbs = p->vObjClasses; int i, k, Entry, iStart, iStop = -1, nFrames; int nObjBits, nObjMask, iObj, iFrame, nWords; unsigned * pInfo; int * pCountAll, * pCountUni; if ( vAbs == NULL ) return; nFrames = Vec_IntEntry( vAbs, 0 ); assert( Vec_IntEntry(vAbs, nFrames+1) == Vec_IntSize(vAbs) ); pCountAll = ABC_ALLOC( int, nFrames + 1 ); pCountUni = ABC_ALLOC( int, nFrames + 1 ); // start storage for seen objects nWords = Abc_BitWordNum( nFrames ); vSeens = Vec_IntStart( Gia_ManObjNum(p) * nWords ); // get the bitmasks nObjBits = Abc_Base2Log( Gia_ManObjNum(p) ); nObjMask = (1 << nObjBits) - 1; assert( Gia_ManObjNum(p) <= nObjMask ); // print info about frames printf( "Frame Core F0 F1 F2 F3 ...\n" ); for ( i = 0; i < nFrames; i++ ) { iStart = Vec_IntEntry( vAbs, i+1 ); iStop = Vec_IntEntry( vAbs, i+2 ); memset( pCountAll, 0, sizeof(int) * (nFrames + 1) ); memset( pCountUni, 0, sizeof(int) * (nFrames + 1) ); Vec_IntForEachEntryStartStop( vAbs, Entry, k, iStart, iStop ) { iObj = (Entry & nObjMask); iFrame = (Entry >> nObjBits); pInfo = (unsigned *)Vec_IntEntryP( vSeens, nWords * iObj ); if ( Abc_InfoHasBit(pInfo, iFrame) == 0 ) { Abc_InfoSetBit( pInfo, iFrame ); pCountUni[iFrame+1]++; pCountUni[0]++; } pCountAll[iFrame+1]++; pCountAll[0]++; } assert( pCountAll[0] == (iStop - iStart) ); // printf( "%5d%5d ", pCountAll[0], pCountUni[0] ); printf( "%3d :", i ); printf( "%7d", pCountAll[0] ); if ( i >= 10 ) { for ( k = 0; k < 4; k++ ) printf( "%5d", pCountAll[k+1] ); printf( " ..." ); for ( k = i-4; k <= i; k++ ) printf( "%5d", pCountAll[k+1] ); } else { for ( k = 0; k <= i; k++ ) if ( k <= i ) printf( "%5d", pCountAll[k+1] ); } // for ( k = 0; k < nFrames; k++ ) // if ( k <= i ) // printf( "%5d", pCountAll[k+1] ); printf( "\n" ); } assert( iStop == Vec_IntSize(vAbs) ); Vec_IntFree( vSeens ); ABC_FREE( pCountAll ); ABC_FREE( pCountUni ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absGla.c000066400000000000000000002140161300674244400232670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absGla2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Scalable gate-level abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absGla2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/main/main.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver2.h" #include "bool/kit/kit.h" #include "abs.h" #include "absRef.h" //#include "absRef2.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define GA2_BIG_NUM 0x3FFFFFF0 typedef struct Ga2_Man_t_ Ga2_Man_t; // manager struct Ga2_Man_t_ { // user data Gia_Man_t * pGia; // working AIG manager Abs_Par_t * pPars; // parameters // markings Vec_Ptr_t * vCnfs; // for each object: CNF0, CNF1 // abstraction Vec_Int_t * vIds; // abstraction ID for each GIA object Vec_Int_t * vProofIds; // mapping of GIA objects into their proof IDs Vec_Int_t * vAbs; // array of abstracted objects Vec_Int_t * vValues; // array of objects with abstraction ID assigned int nProofIds; // the counter of proof IDs int LimAbs; // limit value for starting abstraction objects int LimPpi; // limit value for starting PPI objects int nMarked; // total number of marked nodes and flops int fUseNewLine; // remember that you used new line // refinement Rnm_Man_t * pRnm; // refinement manager // Rf2_Man_t * pRf2; // refinement manager // SAT solver and variables Vec_Ptr_t * vId2Lit; // mapping, for each timeframe, of object ID into SAT literal sat_solver2 * pSat; // incremental SAT solver int nSatVars; // the number of SAT variables int nCexes; // the number of counter-examples int nObjAdded; // objs added during refinement int nPdrCalls; // count the number of concurrent calls // hash table int * pTable; int nTable; int nHashHit; int nHashMiss; int nHashOver; // temporaries Vec_Int_t * vLits; Vec_Int_t * vIsopMem; char * pSopSizes, ** pSops; // CNF representation // statistics abctime timeStart; abctime timeInit; abctime timeSat; abctime timeUnsat; abctime timeCex; abctime timeOther; }; static inline int Ga2_ObjId( Ga2_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry(p->vIds, Gia_ObjId(p->pGia, pObj)); } static inline void Ga2_ObjSetId( Ga2_Man_t * p, Gia_Obj_t * pObj, int i ) { Vec_IntWriteEntry(p->vIds, Gia_ObjId(p->pGia, pObj), i); } static inline Vec_Int_t * Ga2_ObjCnf0( Ga2_Man_t * p, Gia_Obj_t * pObj ) { assert(Ga2_ObjId(p,pObj) >= 0); return (Vec_Int_t *)Vec_PtrEntry( p->vCnfs, 2*Ga2_ObjId(p,pObj) ); } static inline Vec_Int_t * Ga2_ObjCnf1( Ga2_Man_t * p, Gia_Obj_t * pObj ) { assert(Ga2_ObjId(p,pObj) >= 0); return (Vec_Int_t *)Vec_PtrEntry( p->vCnfs, 2*Ga2_ObjId(p,pObj)+1 ); } static inline int Ga2_ObjIsAbs0( Ga2_Man_t * p, Gia_Obj_t * pObj ) { assert(Ga2_ObjId(p,pObj) >= 0); return Ga2_ObjId(p,pObj) >= 0 && Ga2_ObjId(p,pObj) < p->LimAbs; } static inline int Ga2_ObjIsLeaf0( Ga2_Man_t * p, Gia_Obj_t * pObj ) { assert(Ga2_ObjId(p,pObj) >= 0); return Ga2_ObjId(p,pObj) >= p->LimAbs && Ga2_ObjId(p,pObj) < p->LimPpi; } static inline int Ga2_ObjIsAbs( Ga2_Man_t * p, Gia_Obj_t * pObj ) { return Ga2_ObjId(p,pObj) >= 0 && Ga2_ObjCnf0(p,pObj); } static inline int Ga2_ObjIsLeaf( Ga2_Man_t * p, Gia_Obj_t * pObj ) { return Ga2_ObjId(p,pObj) >= 0 && !Ga2_ObjCnf0(p,pObj); } static inline Vec_Int_t * Ga2_MapFrameMap( Ga2_Man_t * p, int f ) { return (Vec_Int_t *)Vec_PtrEntry( p->vId2Lit, f ); } // returns literal of this object, or -1 if SAT variable of the object is not assigned static inline int Ga2_ObjFindLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f ) { // int Id = Ga2_ObjId(p,pObj); assert( Ga2_ObjId(p,pObj) >= 0 && Ga2_ObjId(p,pObj) < Vec_IntSize(p->vValues) ); return Vec_IntEntry( Ga2_MapFrameMap(p, f), Ga2_ObjId(p,pObj) ); } // inserts literal of this object static inline void Ga2_ObjAddLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f, int Lit ) { // assert( Lit > 1 ); assert( Ga2_ObjFindLit(p, pObj, f) == -1 ); Vec_IntSetEntry( Ga2_MapFrameMap(p, f), Ga2_ObjId(p,pObj), Lit ); } // returns or inserts-and-returns literal of this object static inline int Ga2_ObjFindOrAddLit( Ga2_Man_t * p, Gia_Obj_t * pObj, int f ) { int Lit = Ga2_ObjFindLit( p, pObj, f ); if ( Lit == -1 ) { Lit = toLitCond( p->nSatVars++, 0 ); Ga2_ObjAddLit( p, pObj, f, Lit ); } // assert( Lit > 1 ); return Lit; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes truth table for the marked node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ga2_ObjComputeTruth_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fFirst ) { unsigned Val0, Val1; if ( pObj->fPhase && !fFirst ) return pObj->Value; assert( Gia_ObjIsAnd(pObj) ); Val0 = Ga2_ObjComputeTruth_rec( p, Gia_ObjFanin0(pObj), 0 ); Val1 = Ga2_ObjComputeTruth_rec( p, Gia_ObjFanin1(pObj), 0 ); return (Gia_ObjFaninC0(pObj) ? ~Val0 : Val0) & (Gia_ObjFaninC1(pObj) ? ~Val1 : Val1); } unsigned Ga2_ManComputeTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves ) { static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; Gia_Obj_t * pObj; unsigned Res; int i; Gia_ManForEachObjVec( vLeaves, p, pObj, i ) pObj->Value = uTruth5[i]; Res = Ga2_ObjComputeTruth_rec( p, pRoot, 1 ); Gia_ManForEachObjVec( vLeaves, p, pObj, i ) pObj->Value = 0; return Res; } /**Function************************************************************* Synopsis [Returns AIG marked for CNF generation.] Description [The marking satisfies the following requirements: Each marked node has the number of marked fanins no more than N.] SideEffects [Uses pObj->fPhase to store the markings.] SeeAlso [] ***********************************************************************/ int Ga2_ManBreakTree_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fFirst, int N ) { // breaks a tree rooted at the node into N-feasible subtrees int Val0, Val1; if ( pObj->fPhase && !fFirst ) return 1; Val0 = Ga2_ManBreakTree_rec( p, Gia_ObjFanin0(pObj), 0, N ); Val1 = Ga2_ManBreakTree_rec( p, Gia_ObjFanin1(pObj), 0, N ); if ( Val0 + Val1 < N ) return Val0 + Val1; if ( Val0 + Val1 == N ) { pObj->fPhase = 1; return 1; } assert( Val0 + Val1 > N ); assert( Val0 < N && Val1 < N ); if ( Val0 >= Val1 ) { Gia_ObjFanin0(pObj)->fPhase = 1; Val0 = 1; } else { Gia_ObjFanin1(pObj)->fPhase = 1; Val1 = 1; } if ( Val0 + Val1 < N ) return Val0 + Val1; if ( Val0 + Val1 == N ) { pObj->fPhase = 1; return 1; } assert( 0 ); return -1; } int Ga2_ManCheckNodesAnd( Gia_Man_t * p, Vec_Int_t * vNodes ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObjVec( vNodes, p, pObj, i ) if ( (!Gia_ObjFanin0(pObj)->fPhase && Gia_ObjFaninC0(pObj)) || (!Gia_ObjFanin1(pObj)->fPhase && Gia_ObjFaninC1(pObj)) ) return 0; return 1; } void Ga2_ManCollectNodes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes, int fFirst ) { if ( pObj->fPhase && !fFirst ) return; assert( Gia_ObjIsAnd(pObj) ); Ga2_ManCollectNodes_rec( p, Gia_ObjFanin0(pObj), vNodes, 0 ); Ga2_ManCollectNodes_rec( p, Gia_ObjFanin1(pObj), vNodes, 0 ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } void Ga2_ManCollectLeaves_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, int fFirst ) { if ( pObj->fPhase && !fFirst ) { Vec_IntPushUnique( vLeaves, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Ga2_ManCollectLeaves_rec( p, Gia_ObjFanin0(pObj), vLeaves, 0 ); Ga2_ManCollectLeaves_rec( p, Gia_ObjFanin1(pObj), vLeaves, 0 ); } int Ga2_ManMarkup( Gia_Man_t * p, int N, int fSimple ) { static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; // abctime clk = Abc_Clock(); Vec_Int_t * vLeaves; Gia_Obj_t * pObj; int i, k, Leaf, CountMarks; vLeaves = Vec_IntAlloc( 100 ); if ( fSimple ) { Gia_ManForEachObj( p, pObj, i ) pObj->fPhase = !Gia_ObjIsCo(pObj); } else { // label nodes with multiple fanouts and inputs MUXes Gia_ManForEachObj( p, pObj, i ) { pObj->Value = 0; if ( !Gia_ObjIsAnd(pObj) ) continue; Gia_ObjFanin0(pObj)->Value++; Gia_ObjFanin1(pObj)->Value++; if ( !Gia_ObjIsMuxType(pObj) ) continue; Gia_ObjFanin0(Gia_ObjFanin0(pObj))->Value++; Gia_ObjFanin1(Gia_ObjFanin0(pObj))->Value++; Gia_ObjFanin0(Gia_ObjFanin1(pObj))->Value++; Gia_ObjFanin1(Gia_ObjFanin1(pObj))->Value++; } Gia_ManForEachObj( p, pObj, i ) { pObj->fPhase = 0; if ( Gia_ObjIsAnd(pObj) ) pObj->fPhase = (pObj->Value > 1); else if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->fPhase = 1; else pObj->fPhase = 1; } // add marks when needed Gia_ManForEachAnd( p, pObj, i ) { if ( !pObj->fPhase ) continue; Vec_IntClear( vLeaves ); Ga2_ManCollectLeaves_rec( p, pObj, vLeaves, 1 ); if ( Vec_IntSize(vLeaves) > N ) Ga2_ManBreakTree_rec( p, pObj, 1, N ); } } // verify that the tree is split correctly Vec_IntFreeP( &p->vMapping ); p->vMapping = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManForEachRo( p, pObj, i ) { Gia_Obj_t * pObjRi = Gia_ObjRoToRi(p, pObj); assert( pObj->fPhase ); assert( Gia_ObjFanin0(pObjRi)->fPhase ); // create map Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) ); Vec_IntPush( p->vMapping, 1 ); Vec_IntPush( p->vMapping, Gia_ObjFaninId0p(p, pObjRi) ); Vec_IntPush( p->vMapping, Gia_ObjFaninC0(pObjRi) ? 0x55555555 : 0xAAAAAAAA ); Vec_IntPush( p->vMapping, -1 ); // placeholder for ref counter } CountMarks = Gia_ManRegNum(p); Gia_ManForEachAnd( p, pObj, i ) { if ( !pObj->fPhase ) continue; Vec_IntClear( vLeaves ); Ga2_ManCollectLeaves_rec( p, pObj, vLeaves, 1 ); assert( Vec_IntSize(vLeaves) <= N ); // create map Vec_IntWriteEntry( p->vMapping, i, Vec_IntSize(p->vMapping) ); Vec_IntPush( p->vMapping, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, Leaf, k ) { Vec_IntPush( p->vMapping, Leaf ); Gia_ManObj(p, Leaf)->Value = uTruth5[k]; assert( Gia_ManObj(p, Leaf)->fPhase ); } Vec_IntPush( p->vMapping, (int)Ga2_ObjComputeTruth_rec( p, pObj, 1 ) ); Vec_IntPush( p->vMapping, -1 ); // placeholder for ref counter CountMarks++; } // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Vec_IntFree( vLeaves ); Gia_ManCleanValue( p ); return CountMarks; } void Ga2_ManComputeTest( Gia_Man_t * p ) { abctime clk; // unsigned uTruth; Gia_Obj_t * pObj; int i, Counter = 0; clk = Abc_Clock(); Ga2_ManMarkup( p, 5, 0 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Gia_ManForEachAnd( p, pObj, i ) { if ( !pObj->fPhase ) continue; // uTruth = Ga2_ObjTruth( p, pObj ); // printf( "%6d : ", Counter ); // Kit_DsdPrintFromTruth( &uTruth, Ga2_ObjLeaveNum(p, pObj) ); // printf( "\n" ); Counter++; } Abc_Print( 1, "Marked AND nodes = %6d. ", Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ga2_Man_t * Ga2_ManStart( Gia_Man_t * pGia, Abs_Par_t * pPars ) { Ga2_Man_t * p; p = ABC_CALLOC( Ga2_Man_t, 1 ); p->timeStart = Abc_Clock(); p->fUseNewLine = 1; // user data p->pGia = pGia; p->pPars = pPars; // markings p->nMarked = Ga2_ManMarkup( pGia, 5, pPars->fUseSimple ); p->vCnfs = Vec_PtrAlloc( 1000 ); Vec_PtrPush( p->vCnfs, Vec_IntAlloc(0) ); Vec_PtrPush( p->vCnfs, Vec_IntAlloc(0) ); // abstraction p->vIds = Vec_IntStartFull( Gia_ManObjNum(pGia) ); p->vProofIds = Vec_IntAlloc( 0 ); p->vAbs = Vec_IntAlloc( 1000 ); p->vValues = Vec_IntAlloc( 1000 ); // add constant node to abstraction Ga2_ObjSetId( p, Gia_ManConst0(pGia), 0 ); Vec_IntPush( p->vValues, 0 ); Vec_IntPush( p->vAbs, 0 ); // refinement p->pRnm = Rnm_ManStart( pGia ); // p->pRf2 = Rf2_ManStart( pGia ); // SAT solver and variables p->vId2Lit = Vec_PtrAlloc( 1000 ); // temporaries p->vLits = Vec_IntAlloc( 100 ); p->vIsopMem = Vec_IntAlloc( 100 ); Cnf_ReadMsops( &p->pSopSizes, &p->pSops ); // hash table p->nTable = Abc_PrimeCudd(1<<18); p->pTable = ABC_CALLOC( int, 6 * p->nTable ); return p; } void Ga2_ManDumpStats( Gia_Man_t * pGia, Abs_Par_t * pPars, sat_solver2 * pSat, int iFrame, int fUseN ) { FILE * pFile; char pFileName[32]; sprintf( pFileName, "stats_gla%s%s.txt", fUseN ? "n":"", pPars->fUseFullProof ? "p":"" ); pFile = fopen( pFileName, "a+" ); fprintf( pFile, "%s pi=%d ff=%d and=%d mem=%d bmc=%d", pGia->pName, Gia_ManPiNum(pGia), Gia_ManRegNum(pGia), Gia_ManAndNum(pGia), (int)(1 + sat_solver2_memory_proof(pSat)/(1<<20)), iFrame ); if ( pGia->vGateClasses ) fprintf( pFile, " ff=%d and=%d", Gia_GlaCountFlops( pGia, pGia->vGateClasses ), Gia_GlaCountNodes( pGia, pGia->vGateClasses ) ); fprintf( pFile, "\n" ); fclose( pFile ); } void Ga2_ManReportMemory( Ga2_Man_t * p ) { double memTot = 0; double memAig = 1.0 * p->pGia->nObjsAlloc * sizeof(Gia_Obj_t) + Vec_IntMemory(p->pGia->vMapping); double memSat = sat_solver2_memory( p->pSat, 1 ); double memPro = sat_solver2_memory_proof( p->pSat ); double memMap = Vec_VecMemoryInt( (Vec_Vec_t *)p->vId2Lit ); double memRef = Rnm_ManMemoryUsage( p->pRnm ); double memHash= sizeof(int) * 6 * p->nTable; double memOth = sizeof(Ga2_Man_t); memOth += Vec_VecMemoryInt( (Vec_Vec_t *)p->vCnfs ); memOth += Vec_IntMemory( p->vIds ); memOth += Vec_IntMemory( p->vProofIds ); memOth += Vec_IntMemory( p->vAbs ); memOth += Vec_IntMemory( p->vValues ); memOth += Vec_IntMemory( p->vLits ); memOth += Vec_IntMemory( p->vIsopMem ); memOth += 336450 + (sizeof(char) + sizeof(char*)) * 65536; memTot = memAig + memSat + memPro + memMap + memRef + memHash + memOth; ABC_PRMP( "Memory: AIG ", memAig, memTot ); ABC_PRMP( "Memory: SAT ", memSat, memTot ); ABC_PRMP( "Memory: Proof ", memPro, memTot ); ABC_PRMP( "Memory: Map ", memMap, memTot ); ABC_PRMP( "Memory: Refine ", memRef, memTot ); ABC_PRMP( "Memory: Hash ", memHash,memTot ); ABC_PRMP( "Memory: Other ", memOth, memTot ); ABC_PRMP( "Memory: TOTAL ", memTot, memTot ); } void Ga2_ManStop( Ga2_Man_t * p ) { Vec_IntFreeP( &p->pGia->vMapping ); Gia_ManSetPhase( p->pGia ); if ( p->pPars->fVerbose ) Abc_Print( 1, "SAT solver: Var = %d Cla = %d Conf = %d Lrn = %d Reduce = %d Cex = %d ObjsAdded = %d\n", sat_solver2_nvars(p->pSat), sat_solver2_nclauses(p->pSat), sat_solver2_nconflicts(p->pSat), sat_solver2_nlearnts(p->pSat), p->pSat->nDBreduces, p->nCexes, p->nObjAdded ); if ( p->pPars->fVerbose ) Abc_Print( 1, "Hash hits = %d. Hash misses = %d. Hash overs = %d. Concurrent calls = %d.\n", p->nHashHit, p->nHashMiss, p->nHashOver, p->nPdrCalls ); if( p->pSat ) sat_solver2_delete( p->pSat ); Vec_VecFree( (Vec_Vec_t *)p->vCnfs ); Vec_VecFree( (Vec_Vec_t *)p->vId2Lit ); Vec_IntFree( p->vIds ); Vec_IntFree( p->vProofIds ); Vec_IntFree( p->vAbs ); Vec_IntFree( p->vValues ); Vec_IntFree( p->vLits ); Vec_IntFree( p->vIsopMem ); Rnm_ManStop( p->pRnm, 0 ); // Rf2_ManStop( p->pRf2, p->pPars->fVerbose ); ABC_FREE( p->pTable ); ABC_FREE( p->pSopSizes ); ABC_FREE( p->pSops[1] ); ABC_FREE( p->pSops ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Computes a minimized truth table.] Description [Input literals can be 0/1 (const 0/1), non-trivial literals (integers that are more than 1) and unassigned literals (large integers). This procedure computes the truth table that essentially depends on input variables ordered in the increasing order of their positive literals.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Ga2_ObjTruthDepends( unsigned t, int v ) { static unsigned uInvTruth5[5] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF }; assert( v >= 0 && v <= 4 ); return ((t ^ (t >> (1 << v))) & uInvTruth5[v]); } unsigned Ga2_ObjComputeTruthSpecial( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vLits ) { int fVerbose = 0; static unsigned uTruth5[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; unsigned Res; Gia_Obj_t * pObj; int i, Entry; // int Id = Gia_ObjId(p, pRoot); assert( Gia_ObjIsAnd(pRoot) ); if ( fVerbose ) printf( "Object %d.\n", Gia_ObjId(p, pRoot) ); // assign elementary truth tables Gia_ManForEachObjVec( vLeaves, p, pObj, i ) { Entry = Vec_IntEntry( vLits, i ); assert( Entry >= 0 ); if ( Entry == 0 ) pObj->Value = 0; else if ( Entry == 1 ) pObj->Value = ~0; else // non-trivial literal pObj->Value = uTruth5[i]; if ( fVerbose ) printf( "%d ", Entry ); } if ( fVerbose ) { Res = Ga2_ObjTruth( p, pRoot ); // Kit_DsdPrintFromTruth( &Res, Vec_IntSize(vLeaves) ); printf( "\n" ); } // compute truth table Res = Ga2_ObjComputeTruth_rec( p, pRoot, 1 ); if ( Res != 0 && Res != ~0 ) { // find essential variables int nUsed = 0, pUsed[5]; for ( i = 0; i < Vec_IntSize(vLeaves); i++ ) if ( Ga2_ObjTruthDepends( Res, i ) ) pUsed[nUsed++] = i; assert( nUsed > 0 ); // order positions by literal value Vec_IntSelectSortCost( pUsed, nUsed, vLits ); assert( Vec_IntEntry(vLits, pUsed[0]) <= Vec_IntEntry(vLits, pUsed[nUsed-1]) ); // assign elementary truth tables to the leaves Gia_ManForEachObjVec( vLeaves, p, pObj, i ) { Entry = Vec_IntEntry( vLits, i ); assert( Entry >= 0 ); if ( Entry == 0 ) pObj->Value = 0; else if ( Entry == 1 ) pObj->Value = ~0; else // non-trivial literal pObj->Value = 0xDEADCAFE; // not important } for ( i = 0; i < nUsed; i++ ) { Entry = Vec_IntEntry( vLits, pUsed[i] ); assert( Entry > 1 ); pObj = Gia_ManObj( p, Vec_IntEntry(vLeaves, pUsed[i]) ); pObj->Value = Abc_LitIsCompl(Entry) ? ~uTruth5[i] : uTruth5[i]; // pObj->Value = uTruth5[i]; // remember this literal pUsed[i] = Abc_LitRegular(Entry); // pUsed[i] = Entry; } // compute truth table Res = Ga2_ObjComputeTruth_rec( p, pRoot, 1 ); // reload the literals Vec_IntClear( vLits ); for ( i = 0; i < nUsed; i++ ) { Vec_IntPush( vLits, pUsed[i] ); assert( Ga2_ObjTruthDepends(Res, i) ); if ( fVerbose ) printf( "%d ", pUsed[i] ); } for ( ; i < 5; i++ ) assert( !Ga2_ObjTruthDepends(Res, i) ); if ( fVerbose ) { // Kit_DsdPrintFromTruth( &Res, nUsed ); printf( "\n" ); } } else { if ( fVerbose ) { Vec_IntClear( vLits ); printf( "Const %d\n", Res > 0 ); } } Gia_ManForEachObjVec( vLeaves, p, pObj, i ) pObj->Value = 0; return Res; } /**Function************************************************************* Synopsis [Returns CNF of the function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ga2_ManCnfCompute( unsigned uTruth, int nVars, Vec_Int_t * vCover ) { int RetValue; assert( nVars <= 5 ); // transform truth table into the SOP RetValue = Kit_TruthIsop( &uTruth, nVars, vCover, 0 ); assert( RetValue == 0 ); // check the case of constant cover return Vec_IntDup( vCover ); } /**Function************************************************************* Synopsis [Derives CNF for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Ga2_ManCnfAddDynamic( Ga2_Man_t * p, int uTruth, int Lits[], int iLitOut, int ProofId ) { int i, k, b, Cube, nClaLits, ClaLits[6]; // assert( uTruth > 0 && uTruth < 0xffff ); for ( i = 0; i < 2; i++ ) { if ( i ) uTruth = 0xffff & ~uTruth; // Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" ); for ( k = 0; k < p->pSopSizes[uTruth]; k++ ) { nClaLits = 0; ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut; Cube = p->pSops[uTruth][k]; for ( b = 3; b >= 0; b-- ) { if ( Cube % 3 == 0 ) // value 0 --> add positive literal { assert( Lits[b] > 1 ); ClaLits[nClaLits++] = Lits[b]; } else if ( Cube % 3 == 1 ) // value 1 --> add negative literal { assert( Lits[b] > 1 ); ClaLits[nClaLits++] = lit_neg(Lits[b]); } Cube = Cube / 3; } sat_solver2_addclause( p->pSat, ClaLits, ClaLits+nClaLits, ProofId ); } } } void Ga2_ManCnfAddStatic( sat_solver2 * pSat, Vec_Int_t * vCnf0, Vec_Int_t * vCnf1, int Lits[], int iLitOut, int ProofId ) { Vec_Int_t * vCnf; int i, k, b, Cube, Literal, nClaLits, ClaLits[6]; for ( i = 0; i < 2; i++ ) { vCnf = i ? vCnf1 : vCnf0; Vec_IntForEachEntry( vCnf, Cube, k ) { nClaLits = 0; ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut; for ( b = 0; b < 5; b++ ) { Literal = 3 & (Cube >> (b << 1)); if ( Literal == 1 ) // value 0 --> add positive literal { // assert( Lits[b] > 1 ); ClaLits[nClaLits++] = Lits[b]; } else if ( Literal == 2 ) // value 1 --> add negative literal { // assert( Lits[b] > 1 ); ClaLits[nClaLits++] = lit_neg(Lits[b]); } else if ( Literal != 0 ) assert( 0 ); } sat_solver2_addclause( pSat, ClaLits, ClaLits+nClaLits, ProofId ); } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Saig_ManBmcHashKey( int * pArray ) { static int s_Primes[5] = { 12582917, 25165843, 50331653, 100663319, 201326611 }; unsigned i, Key = 0; for ( i = 0; i < 5; i++ ) Key += pArray[i] * s_Primes[i]; return Key; } static inline int * Saig_ManBmcLookup( Ga2_Man_t * p, int * pArray ) { int * pTable = p->pTable + 6 * (Saig_ManBmcHashKey(pArray) % p->nTable); if ( memcmp( pTable, pArray, 20 ) ) { if ( pTable[0] == 0 ) p->nHashMiss++; else p->nHashOver++; memcpy( pTable, pArray, 20 ); pTable[5] = 0; } else p->nHashHit++; assert( pTable + 5 < pTable + 6 * p->nTable ); return pTable + 5; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Ga2_ManSetupNode( Ga2_Man_t * p, Gia_Obj_t * pObj, int fAbs ) { unsigned uTruth; int nLeaves; // int Id = Gia_ObjId(p->pGia, pObj); assert( pObj->fPhase ); assert( Vec_PtrSize(p->vCnfs) == 2 * Vec_IntSize(p->vValues) ); // assign abstraction ID to the node if ( Ga2_ObjId(p,pObj) == -1 ) { Ga2_ObjSetId( p, pObj, Vec_IntSize(p->vValues) ); Vec_IntPush( p->vValues, Gia_ObjId(p->pGia, pObj) ); Vec_PtrPush( p->vCnfs, NULL ); Vec_PtrPush( p->vCnfs, NULL ); } assert( Ga2_ObjCnf0(p, pObj) == NULL ); if ( !fAbs ) return; Vec_IntPush( p->vAbs, Gia_ObjId(p->pGia, pObj) ); assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) ); // compute parameters nLeaves = Ga2_ObjLeaveNum(p->pGia, pObj); uTruth = Ga2_ObjTruth( p->pGia, pObj ); // create CNF for pos/neg phases Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj), Ga2_ManCnfCompute( uTruth, nLeaves, p->vIsopMem) ); Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj) + 1, Ga2_ManCnfCompute(~uTruth, nLeaves, p->vIsopMem) ); } static inline void Ga2_ManAddToAbsOneStatic( Ga2_Man_t * p, Gia_Obj_t * pObj, int f, int fUseId ) { Vec_Int_t * vLeaves; Gia_Obj_t * pLeaf; int k, Lit, iLitOut = Ga2_ObjFindOrAddLit( p, pObj, f ); assert( iLitOut > 1 ); assert( Gia_ObjIsConst0(pObj) || Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) ); if ( Gia_ObjIsConst0(pObj) || (f == 0 && Gia_ObjIsRo(p->pGia, pObj)) ) { iLitOut = Abc_LitNot( iLitOut ); sat_solver2_addclause( p->pSat, &iLitOut, &iLitOut + 1, fUseId ? Gia_ObjId(p->pGia, pObj) : -1 ); } else { int fUseStatic = 1; Vec_IntClear( p->vLits ); vLeaves = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vLeaves, p->pGia, pLeaf, k ) { Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f - Gia_ObjIsRo(p->pGia, pObj) ); Vec_IntPush( p->vLits, Lit ); if ( Lit < 2 ) fUseStatic = 0; } if ( fUseStatic || Gia_ObjIsRo(p->pGia, pObj) ) Ga2_ManCnfAddStatic( p->pSat, Ga2_ObjCnf0(p, pObj), Ga2_ObjCnf1(p, pObj), Vec_IntArray(p->vLits), iLitOut, fUseId ? Gia_ObjId(p->pGia, pObj) : -1 ); else { unsigned uTruth = Ga2_ObjComputeTruthSpecial( p->pGia, pObj, vLeaves, p->vLits ); Ga2_ManCnfAddDynamic( p, uTruth & 0xFFFF, Vec_IntArray(p->vLits), iLitOut, Gia_ObjId(p->pGia, pObj) ); } } } static inline void Ga2_ManAddToAbsOneDynamic( Ga2_Man_t * p, Gia_Obj_t * pObj, int f ) { // int Id = Gia_ObjId(p->pGia, pObj); Vec_Int_t * vLeaves; Gia_Obj_t * pLeaf; unsigned uTruth; int i, Lit; assert( Ga2_ObjIsAbs0(p, pObj) ); assert( Gia_ObjIsConst0(pObj) || Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) ); if ( Gia_ObjIsConst0(pObj) || (f == 0 && Gia_ObjIsRo(p->pGia, pObj)) ) { Ga2_ObjAddLit( p, pObj, f, 0 ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { // if flop is included in the abstraction, but its driver is not // flop input driver has no variable assigned -- we assign it here pLeaf = Gia_ObjRoToRi( p->pGia, pObj ); Lit = Ga2_ObjFindOrAddLit( p, Gia_ObjFanin0(pLeaf), f-1 ); assert( Lit >= 0 ); Lit = Abc_LitNotCond( Lit, Gia_ObjFaninC0(pLeaf) ); Ga2_ObjAddLit( p, pObj, f, Lit ); } else { assert( Gia_ObjIsAnd(pObj) ); Vec_IntClear( p->vLits ); vLeaves = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vLeaves, p->pGia, pLeaf, i ) { if ( Ga2_ObjIsAbs0(p, pLeaf) ) // belongs to original abstraction { Lit = Ga2_ObjFindLit( p, pLeaf, f ); assert( Lit >= 0 ); } else if ( Ga2_ObjIsLeaf0(p, pLeaf) ) // belongs to original PPIs { Lit = Ga2_ObjFindLit( p, pLeaf, f ); // Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f ); if ( Lit == -1 ) { Lit = GA2_BIG_NUM + 2*i; // assert( 0 ); } } else assert( 0 ); Vec_IntPush( p->vLits, Lit ); } // minimize truth table uTruth = Ga2_ObjComputeTruthSpecial( p->pGia, pObj, vLeaves, p->vLits ); if ( uTruth == 0 || uTruth == ~0 ) // const 0 / 1 { Lit = (uTruth > 0); Ga2_ObjAddLit( p, pObj, f, Lit ); } else if ( uTruth == 0xAAAAAAAA || uTruth == 0x55555555 ) // buffer / inverter { Lit = Vec_IntEntry( p->vLits, 0 ); if ( Lit >= GA2_BIG_NUM ) { pLeaf = Gia_ManObj( p->pGia, Vec_IntEntry(vLeaves, (Lit-GA2_BIG_NUM)/2) ); Lit = Ga2_ObjFindLit( p, pLeaf, f ); assert( Lit == -1 ); Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f ); } assert( Lit >= 0 ); Lit = Abc_LitNotCond( Lit, uTruth == 0x55555555 ); Ga2_ObjAddLit( p, pObj, f, Lit ); assert( Lit < 10000000 ); } else { assert( Vec_IntSize(p->vLits) > 1 && Vec_IntSize(p->vLits) < 6 ); // replace literals Vec_IntForEachEntry( p->vLits, Lit, i ) { if ( Lit >= GA2_BIG_NUM ) { pLeaf = Gia_ManObj( p->pGia, Vec_IntEntry(vLeaves, (Lit-GA2_BIG_NUM)/2) ); Lit = Ga2_ObjFindLit( p, pLeaf, f ); assert( Lit == -1 ); Lit = Ga2_ObjFindOrAddLit( p, pLeaf, f ); Vec_IntWriteEntry( p->vLits, i, Lit ); } assert( Lit < 10000000 ); } // add new nodes if ( Vec_IntSize(p->vLits) == 5 ) { Vec_IntClear( p->vLits ); Gia_ManForEachObjVec( vLeaves, p->pGia, pLeaf, i ) Vec_IntPush( p->vLits, Ga2_ObjFindOrAddLit( p, pLeaf, f ) ); Lit = Ga2_ObjFindOrAddLit(p, pObj, f); Ga2_ManCnfAddStatic( p->pSat, Ga2_ObjCnf0(p, pObj), Ga2_ObjCnf1(p, pObj), Vec_IntArray(p->vLits), Lit, -1 ); } else { // int fUseHash = 1; if ( !p->pPars->fSkipHash ) { int * pLookup, nSize = Vec_IntSize(p->vLits); assert( Vec_IntSize(p->vLits) < 5 ); assert( Vec_IntEntry(p->vLits, 0) <= Vec_IntEntryLast(p->vLits) ); assert( Ga2_ObjFindLit(p, pObj, f) == -1 ); for ( i = Vec_IntSize(p->vLits); i < 4; i++ ) Vec_IntPush( p->vLits, GA2_BIG_NUM ); Vec_IntPush( p->vLits, (int)uTruth ); assert( Vec_IntSize(p->vLits) == 5 ); // perform structural hashing here!!! pLookup = Saig_ManBmcLookup( p, Vec_IntArray(p->vLits) ); if ( *pLookup == 0 ) { *pLookup = Ga2_ObjFindOrAddLit(p, pObj, f); Vec_IntShrink( p->vLits, nSize ); Ga2_ManCnfAddDynamic( p, uTruth & 0xFFFF, Vec_IntArray(p->vLits), *pLookup, -1 ); } else Ga2_ObjAddLit( p, pObj, f, *pLookup ); } else { Lit = Ga2_ObjFindOrAddLit(p, pObj, f); Ga2_ManCnfAddDynamic( p, uTruth & 0xFFFF, Vec_IntArray(p->vLits), Lit, -1 ); } } } } } void Ga2_ManAddAbsClauses( Ga2_Man_t * p, int f ) { int fSimple = 0; Gia_Obj_t * pObj; int i; Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i ) { if ( i == p->LimAbs ) break; if ( fSimple ) Ga2_ManAddToAbsOneStatic( p, pObj, f, 0 ); else Ga2_ManAddToAbsOneDynamic( p, pObj, f ); } Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i ) if ( i >= p->LimAbs ) Ga2_ManAddToAbsOneStatic( p, pObj, f, 1 ); // sat_solver2_simplify( p->pSat ); } void Ga2_ManAddToAbs( Ga2_Man_t * p, Vec_Int_t * vToAdd ) { Vec_Int_t * vLeaves; Gia_Obj_t * pObj, * pFanin; int f, i, k; // add abstraction objects Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i ) { Ga2_ManSetupNode( p, pObj, 1 ); if ( p->pSat->pPrf2 ) Vec_IntWriteEntry( p->vProofIds, Gia_ObjId(p->pGia, pObj), p->nProofIds++ ); } // add PPI objects Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i ) { vLeaves = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k ) if ( Ga2_ObjId( p, pFanin ) == -1 ) Ga2_ManSetupNode( p, pFanin, 0 ); } // add new clauses to the timeframes for ( f = 0; f <= p->pPars->iFrame; f++ ) { Vec_IntFillExtra( Ga2_MapFrameMap(p, f), Vec_IntSize(p->vValues), -1 ); Gia_ManForEachObjVec( vToAdd, p->pGia, pObj, i ) Ga2_ManAddToAbsOneStatic( p, pObj, f, 1 ); } // sat_solver2_simplify( p->pSat ); } void Ga2_ManShrinkAbs( Ga2_Man_t * p, int nAbs, int nValues, int nSatVars ) { Vec_Int_t * vMap; Gia_Obj_t * pObj; int i, k, Entry; assert( nAbs > 0 ); assert( nValues > 0 ); assert( nSatVars > 0 ); // shrink abstraction Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i ) { if ( !i ) continue; assert( Ga2_ObjCnf0(p, pObj) != NULL ); assert( Ga2_ObjCnf1(p, pObj) != NULL ); if ( i < nAbs ) continue; Vec_IntFree( Ga2_ObjCnf0(p, pObj) ); Vec_IntFree( Ga2_ObjCnf1(p, pObj) ); Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj), NULL ); Vec_PtrWriteEntry( p->vCnfs, 2 * Ga2_ObjId(p,pObj) + 1, NULL ); } Vec_IntShrink( p->vAbs, nAbs ); // shrink values Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i ) { assert( Ga2_ObjId(p,pObj) >= 0 ); if ( i < nValues ) continue; Ga2_ObjSetId( p, pObj, -1 ); } Vec_IntShrink( p->vValues, nValues ); Vec_PtrShrink( p->vCnfs, 2 * nValues ); // hack to clear constant if ( nValues == 1 ) nValues = 0; // clean mapping for each timeframe Vec_PtrForEachEntry( Vec_Int_t *, p->vId2Lit, vMap, i ) { Vec_IntShrink( vMap, nValues ); Vec_IntForEachEntryStart( vMap, Entry, k, p->LimAbs ) if ( Entry >= 2*nSatVars ) Vec_IntWriteEntry( vMap, k, -1 ); } // shrink SAT variables p->nSatVars = nSatVars; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ga2_ManAbsTranslate_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vClasses, int fFirst ) { if ( pObj->fPhase && !fFirst ) return; assert( Gia_ObjIsAnd(pObj) ); Ga2_ManAbsTranslate_rec( p, Gia_ObjFanin0(pObj), vClasses, 0 ); Ga2_ManAbsTranslate_rec( p, Gia_ObjFanin1(pObj), vClasses, 0 ); Vec_IntWriteEntry( vClasses, Gia_ObjId(p, pObj), 1 ); } Vec_Int_t * Ga2_ManAbsTranslate( Ga2_Man_t * p ) { Vec_Int_t * vGateClasses; Gia_Obj_t * pObj; int i; vGateClasses = Vec_IntStart( Gia_ManObjNum(p->pGia) ); Vec_IntWriteEntry( vGateClasses, 0, 1 ); Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) Ga2_ManAbsTranslate_rec( p->pGia, pObj, vGateClasses, 1 ); else if ( Gia_ObjIsRo(p->pGia, pObj) ) Vec_IntWriteEntry( vGateClasses, Gia_ObjId(p->pGia, pObj), 1 ); else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); // Gia_ObjPrint( p->pGia, pObj ); } return vGateClasses; } Vec_Int_t * Ga2_ManAbsDerive( Gia_Man_t * p ) { Vec_Int_t * vToAdd; Gia_Obj_t * pObj; int i; vToAdd = Vec_IntAlloc( 1000 ); Gia_ManForEachRo( p, pObj, i ) if ( pObj->fPhase && Vec_IntEntry(p->vGateClasses, Gia_ObjId(p, pObj)) ) Vec_IntPush( vToAdd, Gia_ObjId(p, pObj) ); Gia_ManForEachAnd( p, pObj, i ) if ( pObj->fPhase && Vec_IntEntry(p->vGateClasses, i) ) Vec_IntPush( vToAdd, i ); return vToAdd; } void Ga2_ManRestart( Ga2_Man_t * p ) { Vec_Int_t * vToAdd; int Lit = 1; assert( p->pGia != NULL && p->pGia->vGateClasses != NULL ); assert( Gia_ManPi(p->pGia, 0)->fPhase ); // marks are set // clear SAT variable numbers (begin with 1) if ( p->pSat ) sat_solver2_delete( p->pSat ); p->pSat = sat_solver2_new(); p->pSat->nLearntStart = p->pPars->nLearnedStart; p->pSat->nLearntDelta = p->pPars->nLearnedDelta; p->pSat->nLearntRatio = p->pPars->nLearnedPerce; p->pSat->nLearntMax = p->pSat->nLearntStart; // add clause x0 = 0 (lit0 = 1; lit1 = 0) sat_solver2_addclause( p->pSat, &Lit, &Lit + 1, -1 ); // remove previous abstraction Ga2_ManShrinkAbs( p, 1, 1, 1 ); // start new abstraction vToAdd = Ga2_ManAbsDerive( p->pGia ); assert( p->pSat->pPrf2 == NULL ); assert( p->pPars->iFrame < 0 ); Ga2_ManAddToAbs( p, vToAdd ); Vec_IntFree( vToAdd ); p->LimAbs = Vec_IntSize(p->vAbs); p->LimPpi = Vec_IntSize(p->vValues); // set runtime limit if ( p->pPars->nTimeOut ) sat_solver2_set_runtime_limit( p->pSat, p->pPars->nTimeOut * CLOCKS_PER_SEC + p->timeStart ); // clean the hash table memset( p->pTable, 0, 6 * sizeof(int) * p->nTable ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ga2_ObjSatValue( Ga2_Man_t * p, Gia_Obj_t * pObj, int f ) { int Lit = Ga2_ObjFindLit( p, pObj, f ); assert( !Gia_ObjIsConst0(pObj) ); if ( Lit == -1 ) return 0; if ( Abc_Lit2Var(Lit) >= p->pSat->size ) return 0; return Abc_LitIsCompl(Lit) ^ sat_solver2_var_value( p->pSat, Abc_Lit2Var(Lit) ); } Abc_Cex_t * Ga2_ManDeriveCex( Ga2_Man_t * p, Vec_Int_t * vPis ) { Abc_Cex_t * pCex; Gia_Obj_t * pObj; int i, f; pCex = Abc_CexAlloc( Gia_ManRegNum(p->pGia), Gia_ManPiNum(p->pGia), p->pPars->iFrame+1 ); pCex->iPo = 0; pCex->iFrame = p->pPars->iFrame; Gia_ManForEachObjVec( vPis, p->pGia, pObj, i ) { if ( !Gia_ObjIsPi(p->pGia, pObj) ) continue; assert( Gia_ObjIsPi(p->pGia, pObj) ); for ( f = 0; f <= pCex->iFrame; f++ ) if ( Ga2_ObjSatValue( p, pObj, f ) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Gia_ObjCioId(pObj) ); } return pCex; } void Ga2_ManRefinePrint( Ga2_Man_t * p, Vec_Int_t * vVec ) { Gia_Obj_t * pObj, * pFanin; int i, k; printf( "\n Unsat core: \n" ); Gia_ManForEachObjVec( vVec, p->pGia, pObj, i ) { Vec_Int_t * vLeaves = Ga2_ObjLeaves( p->pGia, pObj ); printf( "%12d : ", i ); printf( "Obj =%6d ", Gia_ObjId(p->pGia, pObj) ); if ( Gia_ObjIsRo(p->pGia, pObj) ) printf( "ff " ); else printf( " " ); if ( Ga2_ObjIsAbs0(p, pObj) ) printf( "a " ); else if ( Ga2_ObjIsLeaf0(p, pObj) ) printf( "l " ); else printf( " " ); printf( "Fanins: " ); Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k ) { printf( "%6d ", Gia_ObjId(p->pGia, pFanin) ); if ( Gia_ObjIsRo(p->pGia, pFanin) ) printf( "ff " ); else printf( " " ); if ( Ga2_ObjIsAbs0(p, pFanin) ) printf( "a " ); else if ( Ga2_ObjIsLeaf0(p, pFanin) ) printf( "l " ); else printf( " " ); } printf( "\n" ); } } void Ga2_ManRefinePrintPPis( Ga2_Man_t * p ) { Vec_Int_t * vVec = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj; int i; Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i ) { if ( !i ) continue; if ( Ga2_ObjIsAbs(p, pObj) ) continue; assert( pObj->fPhase ); assert( Ga2_ObjIsLeaf(p, pObj) ); assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj) ); Vec_IntPush( vVec, Gia_ObjId(p->pGia, pObj) ); } printf( " Current PPIs (%d): ", Vec_IntSize(vVec) ); Vec_IntSort( vVec, 1 ); Gia_ManForEachObjVec( vVec, p->pGia, pObj, i ) printf( "%d ", Gia_ObjId(p->pGia, pObj) ); printf( "\n" ); Vec_IntFree( vVec ); } void Ga2_GlaPrepareCexAndMap( Ga2_Man_t * p, Abc_Cex_t ** ppCex, Vec_Int_t ** pvMaps ) { Abc_Cex_t * pCex; Vec_Int_t * vMap; Gia_Obj_t * pObj; int f, i, k; /* Gia_ManForEachObj( p->pGia, pObj, i ) if ( Ga2_ObjId(p, pObj) >= 0 ) assert( Vec_IntEntry(p->vValues, Ga2_ObjId(p, pObj)) == i ); */ // find PIs and PPIs vMap = Vec_IntAlloc( 1000 ); Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i ) { if ( !i ) continue; if ( Ga2_ObjIsAbs(p, pObj) ) continue; assert( pObj->fPhase ); assert( Ga2_ObjIsLeaf(p, pObj) ); assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj) ); Vec_IntPush( vMap, Gia_ObjId(p->pGia, pObj) ); } // derive counter-example pCex = Abc_CexAlloc( 0, Vec_IntSize(vMap), p->pPars->iFrame+1 ); pCex->iFrame = p->pPars->iFrame; for ( f = 0; f <= p->pPars->iFrame; f++ ) Gia_ManForEachObjVec( vMap, p->pGia, pObj, k ) if ( Ga2_ObjSatValue( p, pObj, f ) ) Abc_InfoSetBit( pCex->pData, f * Vec_IntSize(vMap) + k ); *pvMaps = vMap; *ppCex = pCex; } Vec_Int_t * Ga2_ManRefine( Ga2_Man_t * p ) { Abc_Cex_t * pCex; Vec_Int_t * vMap, * vVec; Gia_Obj_t * pObj; int i, k; if ( p->pPars->fAddLayer ) { // use simplified refinement strategy, which adds logic near at PPI without finding important ones vVec = Vec_IntAlloc( 100 ); Gia_ManForEachObjVec( p->vValues, p->pGia, pObj, i ) { if ( !i ) continue; if ( Ga2_ObjIsAbs(p, pObj) ) continue; assert( pObj->fPhase ); assert( Ga2_ObjIsLeaf(p, pObj) ); assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj) ); if ( Gia_ObjIsPi(p->pGia, pObj) ) continue; Vec_IntPush( vVec, Gia_ObjId(p->pGia, pObj) ); } p->nObjAdded += Vec_IntSize(vVec); return vVec; } Ga2_GlaPrepareCexAndMap( p, &pCex, &vMap ); // Rf2_ManRefine( p->pRf2, pCex, vMap, p->pPars->fPropFanout, 1 ); vVec = Rnm_ManRefine( p->pRnm, pCex, vMap, p->pPars->fPropFanout, p->pPars->fNewRefine, 1 ); // printf( "Refinement %d\n", Vec_IntSize(vVec) ); Abc_CexFree( pCex ); if ( Vec_IntSize(vVec) == 0 ) { Vec_IntFree( vVec ); Abc_CexFreeP( &p->pGia->pCexSeq ); p->pGia->pCexSeq = Ga2_ManDeriveCex( p, vMap ); Vec_IntFree( vMap ); return NULL; } Vec_IntFree( vMap ); // remove those already added k = 0; Gia_ManForEachObjVec( vVec, p->pGia, pObj, i ) if ( !Ga2_ObjIsAbs(p, pObj) ) Vec_IntWriteEntry( vVec, k++, Gia_ObjId(p->pGia, pObj) ); Vec_IntShrink( vVec, k ); // these objects should be PPIs that are not abstracted yet Gia_ManForEachObjVec( vVec, p->pGia, pObj, i ) assert( pObj->fPhase );//&& Ga2_ObjIsLeaf(p, pObj) ); p->nObjAdded += Vec_IntSize(vVec); return vVec; } /**Function************************************************************* Synopsis [Creates a new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ga2_GlaAbsCount( Ga2_Man_t * p, int fRo, int fAnd ) { Gia_Obj_t * pObj; int i, Counter = 0; if ( fRo ) Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i ) Counter += Gia_ObjIsRo(p->pGia, pObj); else if ( fAnd ) Gia_ManForEachObjVec( p->vAbs, p->pGia, pObj, i ) Counter += Gia_ObjIsAnd(pObj); else assert( 0 ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ga2_ManAbsPrintFrame( Ga2_Man_t * p, int nFrames, int nConfls, int nCexes, abctime Time, int fFinal ) { int fUseNewLine = ((fFinal && nCexes) || p->pPars->fVeryVerbose); if ( Abc_FrameIsBatchMode() && !fUseNewLine ) return; p->fUseNewLine = fUseNewLine; Abc_Print( 1, "%4d :", nFrames ); Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * Vec_IntSize(p->vAbs) / p->nMarked) ); Abc_Print( 1, "%6d", Vec_IntSize(p->vAbs) ); Abc_Print( 1, "%5d", Vec_IntSize(p->vValues)-Vec_IntSize(p->vAbs)-1 ); Abc_Print( 1, "%5d", Ga2_GlaAbsCount(p, 1, 0) ); Abc_Print( 1, "%6d", Ga2_GlaAbsCount(p, 0, 1) ); Abc_Print( 1, "%8d", nConfls ); if ( nCexes == 0 ) Abc_Print( 1, "%5c", '-' ); else Abc_Print( 1, "%5d", nCexes ); Abc_PrintInt( sat_solver2_nvars(p->pSat) ); Abc_PrintInt( sat_solver2_nclauses(p->pSat) ); Abc_PrintInt( sat_solver2_nlearnts(p->pSat) ); Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC ); Abc_Print( 1, "%5.0f MB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<20) ); Abc_Print( 1, "%s", fUseNewLine ? "\n" : "\r" ); fflush( stdout ); } /**Function************************************************************* Synopsis [Send abstracted model or send cancel.] Description [Counter-example will be sent automatically when &vta terminates.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ga2_GlaGetFileName( Ga2_Man_t * p, int fAbs ) { static char * pFileNameDef = "glabs.aig"; if ( p->pPars->pFileVabs ) return p->pPars->pFileVabs; if ( p->pGia->pSpec ) { if ( fAbs ) return Extra_FileNameGenericAppend( p->pGia->pSpec, "_abs.aig"); else return Extra_FileNameGenericAppend( p->pGia->pSpec, "_gla.aig"); } return pFileNameDef; } void Ga2_GlaDumpAbsracted( Ga2_Man_t * p, int fVerbose ) { char * pFileName; assert( p->pPars->fDumpMabs || p->pPars->fDumpVabs ); if ( p->pPars->fDumpMabs ) { pFileName = Ga2_GlaGetFileName(p, 0); if ( fVerbose ) Abc_Print( 1, "Dumping miter with abstraction map into file \"%s\"...\n", pFileName ); // dump abstraction map Vec_IntFreeP( &p->pGia->vGateClasses ); p->pGia->vGateClasses = Ga2_ManAbsTranslate( p ); Gia_AigerWrite( p->pGia, pFileName, 0, 0 ); } else if ( p->pPars->fDumpVabs ) { Vec_Int_t * vGateClasses; Gia_Man_t * pAbs; pFileName = Ga2_GlaGetFileName(p, 1); if ( fVerbose ) Abc_Print( 1, "Dumping abstracted model into file \"%s\"...\n", pFileName ); // dump absracted model vGateClasses = Ga2_ManAbsTranslate( p ); pAbs = Gia_ManDupAbsGates( p->pGia, vGateClasses ); Gia_ManCleanValue( p->pGia ); Gia_AigerWrite( pAbs, pFileName, 0, 0 ); Gia_ManStop( pAbs ); Vec_IntFreeP( &vGateClasses ); } else assert( 0 ); } /**Function************************************************************* Synopsis [Send abstracted model or send cancel.] Description [Counter-example will be sent automatically when &vta terminates.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Ga2SendAbsracted( Ga2_Man_t * p, int fVerbose ) { Gia_Man_t * pAbs; Vec_Int_t * vGateClasses; assert( Abc_FrameIsBridgeMode() ); // if ( fVerbose ) // Abc_Print( 1, "Sending abstracted model...\n" ); // create abstraction (value of p->pGia is not used here) vGateClasses = Ga2_ManAbsTranslate( p ); pAbs = Gia_ManDupAbsGates( p->pGia, vGateClasses ); Vec_IntFreeP( &vGateClasses ); Gia_ManCleanValue( p->pGia ); // send it out Gia_ManToBridgeAbsNetlist( stdout, pAbs, BRIDGE_ABS_NETLIST ); Gia_ManStop( pAbs ); } void Gia_Ga2SendCancel( Ga2_Man_t * p, int fVerbose ) { extern int Gia_ManToBridgeBadAbs( FILE * pFile ); assert( Abc_FrameIsBridgeMode() ); // if ( fVerbose ) // Abc_Print( 1, "Cancelling previously sent model...\n" ); Gia_ManToBridgeBadAbs( stdout ); } /**Function************************************************************* Synopsis [Performs gate-level abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManPerformGla( Gia_Man_t * pAig, Abs_Par_t * pPars ) { int fUseSecondCore = 1; Ga2_Man_t * p; Vec_Int_t * vCore, * vPPis; abctime clk2, clk = Abc_Clock(); int Status = l_Undef, RetValue = -1, iFrameTryToProve = -1, fOneIsSent = 0; int i, c, f, Lit; pPars->iFrame = -1; // check trivial case assert( Gia_ManPoNum(pAig) == 1 ); ABC_FREE( pAig->pCexSeq ); if ( Gia_ObjIsConst0(Gia_ObjFanin0(Gia_ManPo(pAig,0))) ) { if ( !Gia_ObjFaninC0(Gia_ManPo(pAig,0)) ) { Abc_Print( 1, "Sequential miter is trivially UNSAT.\n" ); return 1; } pAig->pCexSeq = Abc_CexMakeTriv( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), 1, 0 ); Abc_Print( 1, "Sequential miter is trivially SAT.\n" ); return 0; } // create gate classes if not given if ( pAig->vGateClasses == NULL ) { pAig->vGateClasses = Vec_IntStart( Gia_ManObjNum(pAig) ); Vec_IntWriteEntry( pAig->vGateClasses, 0, 1 ); Vec_IntWriteEntry( pAig->vGateClasses, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)), 1 ); } // start the manager p = Ga2_ManStart( pAig, pPars ); p->timeInit = Abc_Clock() - clk; // perform initial abstraction if ( p->pPars->fVerbose ) { Abc_Print( 1, "Running gate-level abstraction (GLA) with the following parameters:\n" ); Abc_Print( 1, "FrameMax = %d ConfMax = %d Timeout = %d Limit = %d %% Limit2 = %d %% RatioMax = %d %%\n", pPars->nFramesMax, pPars->nConfLimit, pPars->nTimeOut, pPars->nRatioMin, pPars->nRatioMin2, pPars->nRatioMax ); Abc_Print( 1, "LrnStart = %d LrnDelta = %d LrnRatio = %d %% Skip = %d SimpleCNF = %d Dump = %d\n", pPars->nLearnedStart, pPars->nLearnedDelta, pPars->nLearnedPerce, pPars->fUseSkip, pPars->fUseSimple, pPars->fDumpVabs|pPars->fDumpMabs ); if ( pPars->fDumpVabs || pPars->fDumpMabs ) Abc_Print( 1, "%s will be dumped into file \"%s\".\n", pPars->fDumpVabs ? "Abstracted model" : "Miter with abstraction map", Ga2_GlaGetFileName(p, pPars->fDumpVabs) ); Abc_Print( 1, " Frame %% Abs PPI FF LUT Confl Cex Vars Clas Lrns Time Mem\n" ); } // iterate unrolling for ( i = f = 0; !pPars->nFramesMax || f < pPars->nFramesMax; i++ ) { int nAbsOld; // remember the timeframe p->pPars->iFrame = -1; // create new SAT solver Ga2_ManRestart( p ); // remember abstraction size after the last restart nAbsOld = Vec_IntSize(p->vAbs); // unroll the circuit for ( f = 0; !pPars->nFramesMax || f < pPars->nFramesMax; f++ ) { // remember current limits int nConflsBeg = sat_solver2_nconflicts(p->pSat); int nAbs = Vec_IntSize(p->vAbs); int nValues = Vec_IntSize(p->vValues); int nVarsOld; // remember the timeframe p->pPars->iFrame = f; // extend and clear storage if ( f == Vec_PtrSize(p->vId2Lit) ) Vec_PtrPush( p->vId2Lit, Vec_IntAlloc(0) ); Vec_IntFillExtra( Ga2_MapFrameMap(p, f), Vec_IntSize(p->vValues), -1 ); // add static clauses to this timeframe Ga2_ManAddAbsClauses( p, f ); // skip checking if skipcheck is enabled (&gla -s) if ( p->pPars->fUseSkip && f <= p->pPars->iFrameProved ) continue; // skip checking if we need to skip several starting frames (&gla -S ) if ( p->pPars->nFramesStart && f <= p->pPars->nFramesStart ) continue; // get the output literal // Lit = Ga2_ManUnroll_rec( p, Gia_ManPo(pAig,0), f ); Lit = Ga2_ObjFindLit( p, Gia_ObjFanin0(Gia_ManPo(pAig,0)), f ); assert( Lit >= 0 ); Lit = Abc_LitNotCond( Lit, Gia_ObjFaninC0(Gia_ManPo(pAig,0)) ); if ( Lit == 0 ) continue; assert( Lit > 1 ); // check for counter-examples if ( p->nSatVars > sat_solver2_nvars(p->pSat) ) sat_solver2_setnvars( p->pSat, p->nSatVars ); nVarsOld = p->nSatVars; for ( c = 0; ; c++ ) { // consider the special case when the target literal is implied false // by implications which happened as a result of previous refinements // note that incremental UNSAT core cannot be computed because there is no learned clauses // in this case, we will assume that UNSAT core cannot reduce the problem if ( var_is_assigned(p->pSat, Abc_Lit2Var(Lit)) ) { Prf_ManStopP( &p->pSat->pPrf2 ); break; } // perform SAT solving clk2 = Abc_Clock(); Status = sat_solver2_solve( p->pSat, &Lit, &Lit+1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( Status == l_True ) // perform refinement { p->nCexes++; p->timeSat += Abc_Clock() - clk2; // cancel old one if it was sent if ( Abc_FrameIsBridgeMode() && fOneIsSent ) { Gia_Ga2SendCancel( p, pPars->fVerbose ); fOneIsSent = 0; } if ( iFrameTryToProve >= 0 ) { Gia_GlaProveCancel( pPars->fVerbose ); iFrameTryToProve = -1; } // perform refinement clk2 = Abc_Clock(); Rnm_ManSetRefId( p->pRnm, c ); vPPis = Ga2_ManRefine( p ); p->timeCex += Abc_Clock() - clk2; if ( vPPis == NULL ) { if ( pPars->fVerbose ) Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c, Abc_Clock() - clk, 1 ); goto finish; } if ( c == 0 ) { // Ga2_ManRefinePrintPPis( p ); // create bookmark to be used for rollback assert( nVarsOld == p->pSat->size ); sat_solver2_bookmark( p->pSat ); // start incremental proof manager assert( p->pSat->pPrf2 == NULL ); p->pSat->pPrf2 = Prf_ManAlloc(); if ( p->pSat->pPrf2 ) { p->nProofIds = 0; Vec_IntFill( p->vProofIds, Gia_ManObjNum(p->pGia), -1 ); Prf_ManRestart( p->pSat->pPrf2, p->vProofIds, sat_solver2_nlearnts(p->pSat), Vec_IntSize(vPPis) ); } } else { // resize the proof logger if ( p->pSat->pPrf2 ) Prf_ManGrow( p->pSat->pPrf2, p->nProofIds + Vec_IntSize(vPPis) ); } Ga2_ManAddToAbs( p, vPPis ); Vec_IntFree( vPPis ); if ( pPars->fVerbose ) Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c+1, Abc_Clock() - clk, 0 ); // check if the number of objects is below limit if ( pPars->nRatioMin2 && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin2 / 100 ) { Status = l_Undef; goto finish; } continue; } p->timeUnsat += Abc_Clock() - clk2; if ( Status == l_Undef ) // ran out of resources goto finish; if ( p->pSat->nRuntimeLimit && Abc_Clock() > p->pSat->nRuntimeLimit ) // timeout goto finish; if ( c == 0 ) { if ( f > p->pPars->iFrameProved ) p->pPars->nFramesNoChange++; break; } if ( f > p->pPars->iFrameProved ) p->pPars->nFramesNoChange = 0; // derive the core assert( p->pSat->pPrf2 != NULL ); vCore = (Vec_Int_t *)Sat_ProofCore( p->pSat ); Prf_ManStopP( &p->pSat->pPrf2 ); // update the SAT solver sat_solver2_rollback( p->pSat ); // reduce abstraction Ga2_ManShrinkAbs( p, nAbs, nValues, nVarsOld ); // purify UNSAT core if ( fUseSecondCore ) { // int nOldCore = Vec_IntSize(vCore); // reverse the order of objects in the core // Vec_IntSort( vCore, 0 ); // Vec_IntPrint( vCore ); // create bookmark to be used for rollback assert( nVarsOld == p->pSat->size ); sat_solver2_bookmark( p->pSat ); // start incremental proof manager assert( p->pSat->pPrf2 == NULL ); p->pSat->pPrf2 = Prf_ManAlloc(); if ( p->pSat->pPrf2 ) { p->nProofIds = 0; Vec_IntFill( p->vProofIds, Gia_ManObjNum(p->pGia), -1 ); Prf_ManRestart( p->pSat->pPrf2, p->vProofIds, sat_solver2_nlearnts(p->pSat), Vec_IntSize(vCore) ); Ga2_ManAddToAbs( p, vCore ); Vec_IntFree( vCore ); } // run SAT solver clk2 = Abc_Clock(); Status = sat_solver2_solve( p->pSat, &Lit, &Lit+1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( Status == l_Undef ) goto finish; assert( Status == l_False ); p->timeUnsat += Abc_Clock() - clk2; // derive the core assert( p->pSat->pPrf2 != NULL ); vCore = (Vec_Int_t *)Sat_ProofCore( p->pSat ); Prf_ManStopP( &p->pSat->pPrf2 ); // update the SAT solver sat_solver2_rollback( p->pSat ); // reduce abstraction Ga2_ManShrinkAbs( p, nAbs, nValues, nVarsOld ); // printf( "\n%4d -> %4d\n", nOldCore, Vec_IntSize(vCore) ); } Ga2_ManAddToAbs( p, vCore ); // Ga2_ManRefinePrint( p, vCore ); Vec_IntFree( vCore ); break; } // remember the last proved frame if ( p->pPars->iFrameProved < f ) p->pPars->iFrameProved = f; // print statistics if ( pPars->fVerbose ) Ga2_ManAbsPrintFrame( p, f, sat_solver2_nconflicts(p->pSat)-nConflsBeg, c, Abc_Clock() - clk, 1 ); // check if abstraction was proved if ( Gia_GlaProveCheck( pPars->fVerbose ) ) { RetValue = 1; goto finish; } if ( c > 0 ) { if ( p->pPars->fVeryVerbose ) Abc_Print( 1, "\n" ); // recompute the abstraction Vec_IntFreeP( &pAig->vGateClasses ); pAig->vGateClasses = Ga2_ManAbsTranslate( p ); // check if the number of objects is below limit if ( pPars->nRatioMin && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin / 100 ) { Status = l_Undef; goto finish; } } // check the number of stable frames if ( p->pPars->nFramesNoChange == p->pPars->nFramesNoChangeLim ) { // dump the model into file if ( p->pPars->fDumpVabs || p->pPars->fDumpMabs ) { char Command[1000]; Abc_FrameSetStatus( -1 ); Abc_FrameSetCex( NULL ); Abc_FrameSetNFrames( f ); sprintf( Command, "write_status %s", Extra_FileNameGenericAppend((char *)(p->pPars->pFileVabs ? p->pPars->pFileVabs : "glabs.aig"), ".status")); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); Ga2_GlaDumpAbsracted( p, pPars->fVerbose ); } // call the prover if ( p->pPars->fCallProver ) { // cancel old one if it is proving if ( iFrameTryToProve >= 0 ) Gia_GlaProveCancel( pPars->fVerbose ); // prove new one Gia_GlaProveAbsracted( pAig, pPars->fSimpProver, pPars->fVeryVerbose ); iFrameTryToProve = f; p->nPdrCalls++; } // speak to the bridge if ( Abc_FrameIsBridgeMode() ) { // cancel old one if it was sent if ( fOneIsSent ) Gia_Ga2SendCancel( p, pPars->fVerbose ); // send new one Gia_Ga2SendAbsracted( p, pPars->fVerbose ); fOneIsSent = 1; } } // if abstraction grew more than a certain percentage, force a restart if ( pPars->nRatioMax == 0 ) continue; if ( c > 0 && (f > 20 || Vec_IntSize(p->vAbs) > 100) && Vec_IntSize(p->vAbs) - nAbsOld >= nAbsOld * pPars->nRatioMax / 100 ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Forcing restart because abstraction grew from %d to %d (more than %d %%).\n", nAbsOld, Vec_IntSize(p->vAbs), pPars->nRatioMax ); break; } } } finish: Prf_ManStopP( &p->pSat->pPrf2 ); // cancel old one if it is proving if ( iFrameTryToProve >= 0 ) Gia_GlaProveCancel( pPars->fVerbose ); // analize the results if ( !p->fUseNewLine ) Abc_Print( 1, "\n" ); if ( RetValue == 1 ) Abc_Print( 1, "GLA completed %d frames and proved abstraction derived in frame %d ", p->pPars->iFrameProved+1, iFrameTryToProve ); else if ( pAig->pCexSeq == NULL ) { Vec_IntFreeP( &pAig->vGateClasses ); pAig->vGateClasses = Ga2_ManAbsTranslate( p ); if ( p->pPars->nTimeOut && Abc_Clock() >= p->pSat->nRuntimeLimit ) Abc_Print( 1, "GLA reached timeout %d sec in frame %d with a %d-stable abstraction. ", p->pPars->nTimeOut, p->pPars->iFrameProved+1, p->pPars->nFramesNoChange ); else if ( pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit ) Abc_Print( 1, "GLA exceeded %d conflicts in frame %d with a %d-stable abstraction. ", pPars->nConfLimit, p->pPars->iFrameProved+1, p->pPars->nFramesNoChange ); else if ( pPars->nRatioMin2 && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin2 / 100 ) Abc_Print( 1, "GLA found that the size of abstraction exceeds %d %% in frame %d during refinement. ", pPars->nRatioMin2, p->pPars->iFrameProved+1 ); else if ( pPars->nRatioMin && Vec_IntSize(p->vAbs) >= p->nMarked * pPars->nRatioMin / 100 ) Abc_Print( 1, "GLA found that the size of abstraction exceeds %d %% in frame %d. ", pPars->nRatioMin, p->pPars->iFrameProved+1 ); else Abc_Print( 1, "GLA finished %d frames and produced a %d-stable abstraction. ", p->pPars->iFrameProved+1, p->pPars->nFramesNoChange ); p->pPars->iFrame = p->pPars->iFrameProved; } else { if ( p->pPars->fVerbose ) Abc_Print( 1, "\n" ); if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) ) Abc_Print( 1, " Gia_ManPerformGlaOld(): CEX verification has failed!\n" ); Abc_Print( 1, "True counter-example detected in frame %d. ", f ); p->pPars->iFrame = f - 1; Vec_IntFreeP( &pAig->vGateClasses ); RetValue = 0; } Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( p->pPars->fVerbose ) { p->timeOther = (Abc_Clock() - clk) - p->timeUnsat - p->timeSat - p->timeCex - p->timeInit; ABC_PRTP( "Runtime: Initializing", p->timeInit, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Solver UNSAT", p->timeUnsat, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Solver SAT ", p->timeSat, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Refinement ", p->timeCex, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Other ", p->timeOther, Abc_Clock() - clk ); ABC_PRTP( "Runtime: TOTAL ", Abc_Clock() - clk, Abc_Clock() - clk ); Ga2_ManReportMemory( p ); } // Ga2_ManDumpStats( p->pGia, p->pPars, p->pSat, p->pPars->iFrameProved, 0 ); Ga2_ManStop( p ); fflush( stdout ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absGlaOld.c000066400000000000000000002162651300674244400237360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absGla.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Gate-level abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absGla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver2.h" #include "base/main/main.h" #include "abs.h" #include "absRef.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Rfn_Obj_t_ Rfn_Obj_t; // refinement object struct Rfn_Obj_t_ { unsigned Value : 1; // value unsigned fVisit : 1; // visited unsigned fPPi : 1; // PPI unsigned Prio : 16; // priority unsigned Sign : 12; // traversal signature }; typedef struct Gla_Obj_t_ Gla_Obj_t; // abstraction object struct Gla_Obj_t_ { int iGiaObj; // corresponding GIA obj unsigned fAbs : 1; // belongs to abstraction unsigned fCompl0 : 1; // compl bit of the first fanin unsigned fConst : 1; // object attribute unsigned fPi : 1; // object attribute unsigned fPo : 1; // object attribute unsigned fRo : 1; // object attribute unsigned fRi : 1; // object attribute unsigned fAnd : 1; // object attribute unsigned fMark : 1; // nearby object unsigned nFanins : 23; // fanin count int Fanins[4]; // fanins Vec_Int_t vFrames; // variables in each timeframe }; typedef struct Gla_Man_t_ Gla_Man_t; // manager struct Gla_Man_t_ { // user data Gia_Man_t * pGia0; // starting AIG manager Gia_Man_t * pGia; // working AIG manager Abs_Par_t * pPars; // parameters // internal data Vec_Int_t * vAbs; // abstracted objects Gla_Obj_t * pObjRoot; // the primary output Gla_Obj_t * pObjs; // objects unsigned * pObj2Obj; // mapping of GIA obj into GLA obj int nObjs; // the number of objects int nAbsOld; // previous abstraction // int nAbsNew; // previous abstraction // int nLrnOld; // the number of bytes // int nLrnNew; // the number of bytes // other data int nCexes; // the number of counter-examples int nObjAdded; // total number of objects added int nSatVars; // the number of SAT variables Cnf_Dat_t * pCnf; // CNF derived for the nodes sat_solver2 * pSat; // incremental SAT solver Vec_Int_t * vTemp; // temporary array Vec_Int_t * vAddedNew; // temporary array Vec_Int_t * vObjCounts; // object counters Vec_Int_t * vCoreCounts; // counts how many times each object appears in the core Vec_Int_t * vProofIds; // counts how many times each object appears in the core int nProofIds; // proof ID counter // refinement Vec_Int_t * pvRefis; // vectors of each object // refinement manager Gia_Man_t * pGia2; Rnm_Man_t * pRnm; // statistics abctime timeInit; abctime timeSat; abctime timeUnsat; abctime timeCex; abctime timeOther; }; // declarations static Vec_Int_t * Gla_ManCollectPPis( Gla_Man_t * p, Vec_Int_t * vPis ); static int Gla_ManCheckVar( Gla_Man_t * p, int iObj, int iFrame ); static int Gla_ManGetVar( Gla_Man_t * p, int iObj, int iFrame ); // object procedures static inline int Gla_ObjId( Gla_Man_t * p, Gla_Obj_t * pObj ) { assert( pObj > p->pObjs && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; } static inline Gla_Obj_t * Gla_ManObj( Gla_Man_t * p, int i ) { assert( i >= 0 && i < p->nObjs ); return i ? p->pObjs + i : NULL; } static inline Gia_Obj_t * Gla_ManGiaObj( Gla_Man_t * p, Gla_Obj_t * pObj ) { return Gia_ManObj( p->pGia, pObj->iGiaObj ); } static inline int Gla_ObjSatValue( Gla_Man_t * p, int iGia, int f ) { return Gla_ManCheckVar(p, p->pObj2Obj[iGia], f) ? sat_solver2_var_value( p->pSat, Gla_ManGetVar(p, p->pObj2Obj[iGia], f) ) : 0; } static inline Rfn_Obj_t * Gla_ObjRef( Gla_Man_t * p, Gia_Obj_t * pObj, int f ) { return (Rfn_Obj_t *)Vec_IntGetEntryP( &(p->pvRefis[Gia_ObjId(p->pGia, pObj)]), f ); } static inline void Gla_ObjClearRef( Rfn_Obj_t * p ) { *((int *)p) = 0; } // iterator through abstracted objects #define Gla_ManForEachObj( p, pObj ) \ for ( pObj = p->pObjs + 1; pObj < p->pObjs + p->nObjs; pObj++ ) #define Gla_ManForEachObjAbs( p, pObj, i ) \ for ( i = 0; i < Vec_IntSize(p->vAbs) && ((pObj = Gla_ManObj(p, Vec_IntEntry(p->vAbs, i))),1); i++) #define Gla_ManForEachObjAbsVec( vVec, p, pObj, i ) \ for ( i = 0; i < Vec_IntSize(vVec) && ((pObj = Gla_ManObj(p, Vec_IntEntry(vVec, i))),1); i++) // iterator through fanins of an abstracted object #define Gla_ObjForEachFanin( p, pObj, pFanin, i ) \ for ( i = 0; (i < (int)pObj->nFanins) && ((pFanin = Gla_ManObj(p, pObj->Fanins[i])),1); i++ ) // some lessons learned from debugging mismatches between GIA and mapped CNF // - inputs/output of AND-node may be PPIs (have SAT vars), but the node is not included in the abstraction // - some logic node can be a PPI of one LUT and an internal node of another LUT //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prepares CEX and vMap for refinement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_GlaPrepareCexAndMap( Gla_Man_t * p, Abc_Cex_t ** ppCex, Vec_Int_t ** pvMap ) { Abc_Cex_t * pCex; Vec_Int_t * vMap; Gla_Obj_t * pObj, * pFanin; Gia_Obj_t * pGiaObj; int f, i, k; // find PIs and PPIs vMap = Vec_IntAlloc( 1000 ); Gla_ManForEachObjAbs( p, pObj, i ) { assert( pObj->fConst || pObj->fRo || pObj->fAnd ); Gla_ObjForEachFanin( p, pObj, pFanin, k ) if ( !pFanin->fAbs ) Vec_IntPush( vMap, pFanin->iGiaObj ); } Vec_IntUniqify( vMap ); // derive counter-example pCex = Abc_CexAlloc( 0, Vec_IntSize(vMap), p->pPars->iFrame+1 ); pCex->iFrame = p->pPars->iFrame; for ( f = 0; f <= p->pPars->iFrame; f++ ) Gia_ManForEachObjVec( vMap, p->pGia, pGiaObj, k ) if ( Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pGiaObj), f ) ) Abc_InfoSetBit( pCex->pData, f * Vec_IntSize(vMap) + k ); *pvMap = vMap; *ppCex = pCex; } /**Function************************************************************* Synopsis [Derives counter-example using current assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gla_ManDeriveCex( Gla_Man_t * p, Vec_Int_t * vPis ) { Abc_Cex_t * pCex; Gia_Obj_t * pObj; int i, f; pCex = Abc_CexAlloc( Gia_ManRegNum(p->pGia), Gia_ManPiNum(p->pGia), p->pPars->iFrame+1 ); pCex->iPo = 0; pCex->iFrame = p->pPars->iFrame; Gia_ManForEachObjVec( vPis, p->pGia, pObj, i ) { if ( !Gia_ObjIsPi(p->pGia, pObj) ) continue; assert( Gia_ObjIsPi(p->pGia, pObj) ); for ( f = 0; f <= pCex->iFrame; f++ ) if ( Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f ) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Gia_ObjCioId(pObj) ); } return pCex; } /**Function************************************************************* Synopsis [Collects GIA abstraction objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gla_ManCollectInternal_rec( Gia_Man_t * p, Gia_Obj_t * pGiaObj, Vec_Int_t * vRoAnds ) { if ( Gia_ObjIsTravIdCurrent(p, pGiaObj) ) return; Gia_ObjSetTravIdCurrent(p, pGiaObj); assert( Gia_ObjIsAnd(pGiaObj) ); Gla_ManCollectInternal_rec( p, Gia_ObjFanin0(pGiaObj), vRoAnds ); Gla_ManCollectInternal_rec( p, Gia_ObjFanin1(pGiaObj), vRoAnds ); Vec_IntPush( vRoAnds, Gia_ObjId(p, pGiaObj) ); } void Gla_ManCollect( Gla_Man_t * p, Vec_Int_t * vPis, Vec_Int_t * vPPis, Vec_Int_t * vCos, Vec_Int_t * vRoAnds ) { Gla_Obj_t * pObj, * pFanin; Gia_Obj_t * pGiaObj; int i, k; // collect COs Vec_IntPush( vCos, Gia_ObjId(p->pGia, Gia_ManPo(p->pGia, 0)) ); // collect fanins of abstracted objects Gla_ManForEachObjAbs( p, pObj, i ) { assert( pObj->fConst || pObj->fRo || pObj->fAnd ); if ( pObj->fRo ) { pGiaObj = Gia_ObjRoToRi( p->pGia, Gia_ManObj(p->pGia, pObj->iGiaObj) ); Vec_IntPush( vCos, Gia_ObjId(p->pGia, pGiaObj) ); } Gla_ObjForEachFanin( p, pObj, pFanin, k ) if ( !pFanin->fAbs ) Vec_IntPush( (pFanin->fPi ? vPis : vPPis), pFanin->iGiaObj ); } Vec_IntUniqify( vPis ); Vec_IntUniqify( vPPis ); Vec_IntSort( vCos, 0 ); // sorting PIs/PPIs/COs leads to refinements that are more "well-aligned"... // mark const/PIs/PPIs Gia_ManIncrementTravId( p->pGia ); Gia_ObjSetTravIdCurrent( p->pGia, Gia_ManConst0(p->pGia) ); Gia_ManForEachObjVec( vPis, p->pGia, pGiaObj, i ) Gia_ObjSetTravIdCurrent( p->pGia, pGiaObj ); Gia_ManForEachObjVec( vPPis, p->pGia, pGiaObj, i ) Gia_ObjSetTravIdCurrent( p->pGia, pGiaObj ); // mark and add ROs first Gia_ManForEachObjVec( vCos, p->pGia, pGiaObj, i ) { if ( i == 0 ) continue; pGiaObj = Gia_ObjRiToRo( p->pGia, pGiaObj ); Gia_ObjSetTravIdCurrent( p->pGia, pGiaObj ); Vec_IntPush( vRoAnds, Gia_ObjId(p->pGia, pGiaObj) ); } // collect nodes between PIs/PPIs/ROs and COs Gia_ManForEachObjVec( vCos, p->pGia, pGiaObj, i ) Gla_ManCollectInternal_rec( p->pGia, Gia_ObjFanin0(pGiaObj), vRoAnds ); } /**Function************************************************************* Synopsis [Drive implications of the given node towards primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManRefSetAndPropFanout_rec( Gla_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vSelect, int Sign ) { int i;//, Id = Gia_ObjId(p->pGia, pObj); Rfn_Obj_t * pRef0, * pRef1, * pRef = Gla_ObjRef( p, pObj, f ); Gia_Obj_t * pFanout; int k; if ( (int)pRef->Sign != Sign ) return; assert( pRef->fVisit == 0 ); pRef->fVisit = 1; if ( pRef->fPPi ) { assert( (int)pRef->Prio > 0 ); for ( i = p->pPars->iFrame; i >= 0; i-- ) if ( !Gla_ObjRef(p, pObj, i)->fVisit ) Gia_ManRefSetAndPropFanout_rec( p, pObj, i, vSelect, Sign ); Vec_IntPush( vSelect, Gia_ObjId(p->pGia, pObj) ); return; } if ( (Gia_ObjIsCo(pObj) && f == p->pPars->iFrame) || Gia_ObjIsPo(p->pGia, pObj) ) return; if ( Gia_ObjIsRi(p->pGia, pObj) ) { pFanout = Gia_ObjRiToRo(p->pGia, pObj); if ( !Gla_ObjRef(p, pFanout, f+1)->fVisit ) Gia_ManRefSetAndPropFanout_rec( p, pFanout, f+1, vSelect, Sign ); return; } assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) ); Gia_ObjForEachFanoutStatic( p->pGia, pObj, pFanout, k ) { // Rfn_Obj_t * pRefF = Gla_ObjRef(p, pFanout, f); if ( Gla_ObjRef(p, pFanout, f)->fVisit ) continue; if ( Gia_ObjIsCo(pFanout) ) { Gia_ManRefSetAndPropFanout_rec( p, pFanout, f, vSelect, Sign ); continue; } assert( Gia_ObjIsAnd(pFanout) ); pRef0 = Gla_ObjRef( p, Gia_ObjFanin0(pFanout), f ); pRef1 = Gla_ObjRef( p, Gia_ObjFanin1(pFanout), f ); if ( ((pRef0->Value ^ Gia_ObjFaninC0(pFanout)) == 0 && pRef0->fVisit) || ((pRef1->Value ^ Gia_ObjFaninC1(pFanout)) == 0 && pRef1->fVisit) || ( ((pRef0->Value ^ Gia_ObjFaninC0(pFanout)) == 1 && pRef0->fVisit) && ((pRef1->Value ^ Gia_ObjFaninC1(pFanout)) == 1 && pRef1->fVisit) ) ) Gia_ManRefSetAndPropFanout_rec( p, pFanout, f, vSelect, Sign ); } } /**Function************************************************************* Synopsis [Selects assignments to be refined.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gla_ManRefSelect_rec( Gla_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vSelect, int Sign ) { int i;//, Id = Gia_ObjId(p->pGia, pObj); Rfn_Obj_t * pRef = Gla_ObjRef( p, pObj, f ); // assert( (int)pRef->Sign == Sign ); if ( pRef->fVisit ) return; if ( p->pPars->fPropFanout ) Gia_ManRefSetAndPropFanout_rec( p, pObj, f, vSelect, Sign ); else pRef->fVisit = 1; if ( pRef->fPPi ) { assert( (int)pRef->Prio > 0 ); if ( p->pPars->fPropFanout ) { for ( i = p->pPars->iFrame; i >= 0; i-- ) if ( !Gla_ObjRef(p, pObj, i)->fVisit ) Gia_ManRefSetAndPropFanout_rec( p, pObj, i, vSelect, Sign ); } else { Vec_IntPush( vSelect, Gia_ObjId(p->pGia, pObj) ); Vec_IntAddToEntry( p->vObjCounts, f, 1 ); } return; } if ( Gia_ObjIsPi(p->pGia, pObj) || Gia_ObjIsConst0(pObj) ) return; if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( f > 0 ) Gla_ManRefSelect_rec( p, Gia_ObjFanin0(Gia_ObjRoToRi(p->pGia, pObj)), f-1, vSelect, Sign ); return; } if ( Gia_ObjIsAnd(pObj) ) { Rfn_Obj_t * pRef0 = Gla_ObjRef( p, Gia_ObjFanin0(pObj), f ); Rfn_Obj_t * pRef1 = Gla_ObjRef( p, Gia_ObjFanin1(pObj), f ); if ( pRef->Value == 1 ) { if ( pRef0->Prio > 0 ) Gla_ManRefSelect_rec( p, Gia_ObjFanin0(pObj), f, vSelect, Sign ); if ( pRef1->Prio > 0 ) Gla_ManRefSelect_rec( p, Gia_ObjFanin1(pObj), f, vSelect, Sign ); } else // select one value { if ( (pRef0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRef1->Value ^ Gia_ObjFaninC1(pObj)) == 0 ) { if ( pRef0->Prio <= pRef1->Prio ) // choice { if ( pRef0->Prio > 0 ) Gla_ManRefSelect_rec( p, Gia_ObjFanin0(pObj), f, vSelect, Sign ); } else { if ( pRef1->Prio > 0 ) Gla_ManRefSelect_rec( p, Gia_ObjFanin1(pObj), f, vSelect, Sign ); } } else if ( (pRef0->Value ^ Gia_ObjFaninC0(pObj)) == 0 ) { if ( pRef0->Prio > 0 ) Gla_ManRefSelect_rec( p, Gia_ObjFanin0(pObj), f, vSelect, Sign ); } else if ( (pRef1->Value ^ Gia_ObjFaninC1(pObj)) == 0 ) { if ( pRef1->Prio > 0 ) Gla_ManRefSelect_rec( p, Gia_ObjFanin1(pObj), f, vSelect, Sign ); } else assert( 0 ); } } else assert( 0 ); } /**Function************************************************************* Synopsis [Performs refinement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gla_ManVerifyUsingTerSim( Gla_Man_t * p, Vec_Int_t * vPis, Vec_Int_t * vPPis, Vec_Int_t * vRoAnds, Vec_Int_t * vCos, Vec_Int_t * vRes ) { Gia_Obj_t * pObj; int i, f; // Gia_ManForEachObj( p->pGia, pObj, i ) // assert( Gia_ObjTerSimGetC(pObj) ); for ( f = 0; f <= p->pPars->iFrame; f++ ) { Gia_ObjTerSimSet0( Gia_ManConst0(p->pGia) ); Gia_ManForEachObjVec( vPis, p->pGia, pObj, i ) { if ( Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f ) ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); } Gia_ManForEachObjVec( vPPis, p->pGia, pObj, i ) Gia_ObjTerSimSetX( pObj ); Gia_ManForEachObjVec( vRes, p->pGia, pObj, i ) if ( Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f ) ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); Gia_ManForEachObjVec( vRoAnds, p->pGia, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) Gia_ObjTerSimAnd( pObj ); else if ( f == 0 ) Gia_ObjTerSimSet0( pObj ); else Gia_ObjTerSimRo( p->pGia, pObj ); } Gia_ManForEachObjVec( vCos, p->pGia, pObj, i ) Gia_ObjTerSimCo( pObj ); } pObj = Gia_ManPo( p->pGia, 0 ); if ( !Gia_ObjTerSimGet1(pObj) ) Abc_Print( 1, "\nRefinement verification has failed!!!\n" ); // clear Gia_ObjTerSimSetC( Gia_ManConst0(p->pGia) ); Gia_ManForEachObjVec( vPis, p->pGia, pObj, i ) Gia_ObjTerSimSetC( pObj ); Gia_ManForEachObjVec( vPPis, p->pGia, pObj, i ) Gia_ObjTerSimSetC( pObj ); Gia_ManForEachObjVec( vRoAnds, p->pGia, pObj, i ) Gia_ObjTerSimSetC( pObj ); Gia_ManForEachObjVec( vCos, p->pGia, pObj, i ) Gia_ObjTerSimSetC( pObj ); } /**Function************************************************************* Synopsis [Performs refinement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gla_ManRefinement( Gla_Man_t * p ) { Abc_Cex_t * pCex; Vec_Int_t * vMap, * vVec; Gia_Obj_t * pObj; int i; Gia_GlaPrepareCexAndMap( p, &pCex, &vMap ); vVec = Rnm_ManRefine( p->pRnm, pCex, vMap, p->pPars->fPropFanout, p->pPars->fNewRefine, 1 ); Abc_CexFree( pCex ); if ( Vec_IntSize(vVec) == 0 ) { Vec_IntFree( vVec ); Abc_CexFreeP( &p->pGia->pCexSeq ); p->pGia->pCexSeq = Gla_ManDeriveCex( p, vMap ); Vec_IntFree( vMap ); return NULL; } Vec_IntFree( vMap ); // remap them into GLA objects Gia_ManForEachObjVec( vVec, p->pGia, pObj, i ) Vec_IntWriteEntry( vVec, i, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)] ); p->nObjAdded += Vec_IntSize(vVec); return vVec; } /**Function************************************************************* Synopsis [Performs refinement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gla_ManRefinement2( Gla_Man_t * p ) { int fVerify = 1; static int Sign = 0; Vec_Int_t * vPis, * vPPis, * vCos, * vRoAnds, * vSelect = NULL; Rfn_Obj_t * pRef, * pRef0, * pRef1; Gia_Obj_t * pObj; int i, f; Sign++; // compute PIs and pseudo-PIs vCos = Vec_IntAlloc( 1000 ); vPis = Vec_IntAlloc( 1000 ); vPPis = Vec_IntAlloc( 1000 ); vRoAnds = Vec_IntAlloc( 1000 ); Gla_ManCollect( p, vPis, vPPis, vCos, vRoAnds ); /* // check how many pseudo PIs have variables Gla_ManForEachObjAbsVec( vPis, p, pGla, i ) { Abc_Print( 1, " %5d : ", Gla_ObjId(p, pGla) ); for ( f = 0; f <= p->pPars->iFrame; f++ ) Abc_Print( 1, "%d", Gla_ManCheckVar(p, Gla_ObjId(p, pGla), f) ); Abc_Print( 1, "\n" ); } // check how many pseudo PIs have variables Gla_ManForEachObjAbsVec( vPPis, p, pGla, i ) { Abc_Print( 1, "%5d : ", Gla_ObjId(p, pGla) ); for ( f = 0; f <= p->pPars->iFrame; f++ ) Abc_Print( 1, "%d", Gla_ManCheckVar(p, Gla_ObjId(p, pGla), f) ); Abc_Print( 1, "\n" ); } */ // propagate values for ( f = 0; f <= p->pPars->iFrame; f++ ) { // constant pRef = Gla_ObjRef( p, Gia_ManConst0(p->pGia), f ); Gla_ObjClearRef( pRef ); pRef->Value = 0; pRef->Prio = 0; pRef->Sign = Sign; // primary input Gia_ManForEachObjVec( vPis, p->pGia, pObj, i ) { // assert( f == p->pPars->iFrame || Gla_ManCheckVar(p, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)], f) ); pRef = Gla_ObjRef( p, pObj, f ); Gla_ObjClearRef( pRef ); pRef->Value = Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f ); pRef->Prio = 0; pRef->Sign = Sign; assert( pRef->fVisit == 0 ); } // primary input Gia_ManForEachObjVec( vPPis, p->pGia, pObj, i ) { // assert( f == p->pPars->iFrame || Gla_ManCheckVar(p, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)], f) ); assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) ); pRef = Gla_ObjRef( p, pObj, f ); Gla_ObjClearRef( pRef ); pRef->Value = Gla_ObjSatValue( p, Gia_ObjId(p->pGia, pObj), f ); pRef->Prio = i+1; pRef->fPPi = 1; pRef->Sign = Sign; assert( pRef->fVisit == 0 ); } // internal nodes Gia_ManForEachObjVec( vRoAnds, p->pGia, pObj, i ) { assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) ); pRef = Gla_ObjRef( p, pObj, f ); Gla_ObjClearRef( pRef ); if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( f == 0 ) { pRef->Value = 0; pRef->Prio = 0; pRef->Sign = Sign; } else { pRef0 = Gla_ObjRef( p, Gia_ObjRoToRi(p->pGia, pObj), f-1 ); pRef->Value = pRef0->Value; pRef->Prio = pRef0->Prio; pRef->Sign = Sign; } continue; } assert( Gia_ObjIsAnd(pObj) ); pRef0 = Gla_ObjRef( p, Gia_ObjFanin0(pObj), f ); pRef1 = Gla_ObjRef( p, Gia_ObjFanin1(pObj), f ); pRef->Value = (pRef0->Value ^ Gia_ObjFaninC0(pObj)) & (pRef1->Value ^ Gia_ObjFaninC1(pObj)); if ( p->pObj2Obj[Gia_ObjId(p->pGia, pObj)] != ~0 && Gla_ManCheckVar(p, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)], f) && (int)pRef->Value != Gla_ObjSatValue(p, Gia_ObjId(p->pGia, pObj), f) ) { Abc_Print( 1, "Object has value mismatch " ); Gia_ObjPrint( p->pGia, pObj ); } if ( pRef->Value == 1 ) pRef->Prio = Abc_MaxInt( pRef0->Prio, pRef1->Prio ); else if ( (pRef0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRef1->Value ^ Gia_ObjFaninC1(pObj)) == 0 ) pRef->Prio = Abc_MinInt( pRef0->Prio, pRef1->Prio ); // choice else if ( (pRef0->Value ^ Gia_ObjFaninC0(pObj)) == 0 ) pRef->Prio = pRef0->Prio; else pRef->Prio = pRef1->Prio; assert( pRef->fVisit == 0 ); pRef->Sign = Sign; } // output nodes Gia_ManForEachObjVec( vCos, p->pGia, pObj, i ) { pRef = Gla_ObjRef( p, pObj, f ); Gla_ObjClearRef( pRef ); pRef0 = Gla_ObjRef( p, Gia_ObjFanin0(pObj), f ); pRef->Value = (pRef0->Value ^ Gia_ObjFaninC0(pObj)); pRef->Prio = pRef0->Prio; assert( pRef->fVisit == 0 ); pRef->Sign = Sign; } } // make sure the output value is 1 pObj = Gia_ManPo( p->pGia, 0 ); pRef = Gla_ObjRef( p, pObj, p->pPars->iFrame ); if ( pRef->Value != 1 ) Abc_Print( 1, "\nCounter-example verification has failed!!!\n" ); // check the CEX if ( pRef->Prio == 0 ) { p->pGia->pCexSeq = Gla_ManDeriveCex( p, vPis ); Vec_IntFree( vPis ); Vec_IntFree( vPPis ); Vec_IntFree( vRoAnds ); Vec_IntFree( vCos ); return NULL; } // select objects vSelect = Vec_IntAlloc( 100 ); Vec_IntFill( p->vObjCounts, p->pPars->iFrame+1, 0 ); Gla_ManRefSelect_rec( p, Gia_ObjFanin0(Gia_ManPo(p->pGia, 0)), p->pPars->iFrame, vSelect, Sign ); Vec_IntUniqify( vSelect ); /* for ( f = 0; f < p->pPars->iFrame; f++ ) printf( "%2d", Vec_IntEntry(p->vObjCounts, f) ); printf( "\n" ); */ if ( fVerify ) Gla_ManVerifyUsingTerSim( p, vPis, vPPis, vRoAnds, vCos, vSelect ); // remap them into GLA objects Gia_ManForEachObjVec( vSelect, p->pGia, pObj, i ) Vec_IntWriteEntry( vSelect, i, p->pObj2Obj[Gia_ObjId(p->pGia, pObj)] ); Vec_IntFree( vPis ); Vec_IntFree( vPPis ); Vec_IntFree( vRoAnds ); Vec_IntFree( vCos ); p->nObjAdded += Vec_IntSize(vSelect); return vSelect; } /**Function************************************************************* Synopsis [Adds clauses for the given obj in the given frame.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gla_ManCollectFanins( Gla_Man_t * p, Gla_Obj_t * pGla, int iObj, Vec_Int_t * vFanins ) { int i, nClauses, iFirstClause, * pLit; nClauses = p->pCnf->pObj2Count[pGla->iGiaObj]; iFirstClause = p->pCnf->pObj2Clause[pGla->iGiaObj]; Vec_IntClear( vFanins ); for ( i = iFirstClause; i < iFirstClause + nClauses; i++ ) for ( pLit = p->pCnf->pClauses[i]; pLit < p->pCnf->pClauses[i+1]; pLit++ ) if ( lit_var(*pLit) != iObj ) Vec_IntPushUnique( vFanins, lit_var(*pLit) ); assert( Vec_IntSize( vFanins ) <= 4 ); Vec_IntSort( vFanins, 0 ); } /**Function************************************************************* Synopsis [Duplicates AIG while decoupling nodes duplicated in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupMapped_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) ); Gia_ManDupMapped_rec( p, Gia_ObjFanin0(pObj), pNew ); Gia_ManDupMapped_rec( p, Gia_ObjFanin1(pObj), pNew ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Vec_IntPush( pNew->vLutConfigs, Gia_ObjId(p, pObj) ); } Gia_Man_t * Gia_ManDupMapped( Gia_Man_t * p, Vec_Int_t * vMapping ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pFanin; int i, k, * pMapping, * pObj2Obj; // start new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // start mapping Gia_ManFillValue( p ); pObj2Obj = ABC_FALLOC( int, Gia_ManObjNum(p) ); pObj2Obj[0] = 0; // create reverse mapping and attach it to the node pNew->vLutConfigs = Vec_IntAlloc( Gia_ManObjNum(p) * 4 / 3 ); Vec_IntPush( pNew->vLutConfigs, 0 ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { int Offset = Vec_IntEntry(vMapping, Gia_ObjId(p, pObj)); if ( Offset == 0 ) continue; pMapping = Vec_IntEntryP( vMapping, Offset ); Gia_ManIncrementTravId( p ); for ( k = 1; k <= 4; k++ ) { if ( pMapping[k] == -1 ) continue; pFanin = Gia_ManObj(p, pMapping[k]); Gia_ObjSetTravIdCurrent( p, pFanin ); pFanin->Value = pObj2Obj[pMapping[k]]; assert( ~pFanin->Value ); } assert( !Gia_ObjIsTravIdCurrent(p, pObj) ); assert( !~pObj->Value ); Gia_ManDupMapped_rec( p, pObj, pNew ); pObj2Obj[i] = pObj->Value; assert( ~pObj->Value ); } else if ( Gia_ObjIsCi(pObj) ) { pObj2Obj[i] = Gia_ManAppendCi( pNew ); Vec_IntPush( pNew->vLutConfigs, i ); } else if ( Gia_ObjIsCo(pObj) ) { Gia_ObjFanin0(pObj)->Value = pObj2Obj[Gia_ObjFaninId0p(p, pObj)]; assert( ~Gia_ObjFanin0(pObj)->Value ); pObj2Obj[i] = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntPush( pNew->vLutConfigs, i ); } } assert( Vec_IntSize(pNew->vLutConfigs) == Gia_ManObjNum(pNew) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // map original AIG into the new AIG Gia_ManForEachObj( p, pObj, i ) pObj->Value = pObj2Obj[i]; ABC_FREE( pObj2Obj ); return pNew; } /**Function************************************************************* Synopsis [Creates a new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gla_Man_t * Gla_ManStart( Gia_Man_t * pGia0, Abs_Par_t * pPars ) { Gla_Man_t * p; Aig_Man_t * pAig; Gia_Obj_t * pObj; Gla_Obj_t * pGla; Vec_Int_t * vMappingNew; int i, k, Offset, * pMapping, * pLits, * pObj2Count, * pObj2Clause; // start p = ABC_CALLOC( Gla_Man_t, 1 ); p->pGia0 = pGia0; p->pPars = pPars; p->vAbs = Vec_IntAlloc( 100 ); p->vTemp = Vec_IntAlloc( 100 ); p->vAddedNew = Vec_IntAlloc( 100 ); p->vObjCounts = Vec_IntAlloc( 100 ); // internal data pAig = Gia_ManToAigSimple( pGia0 ); p->pCnf = Cnf_DeriveOther( pAig, 1 ); Aig_ManStop( pAig ); // create working GIA p->pGia = Gia_ManDupMapped( pGia0, p->pCnf->vMapping ); if ( pPars->fPropFanout ) Gia_ManStaticFanoutStart( p->pGia ); // derive new gate map assert( pGia0->vGateClasses != 0 ); p->pGia->vGateClasses = Vec_IntStart( Gia_ManObjNum(p->pGia) ); p->vCoreCounts = Vec_IntStart( Gia_ManObjNum(p->pGia) ); p->vProofIds = Vec_IntAlloc(0); // update p->pCnf->vMapping, p->pCnf->pObj2Count, p->pCnf->pObj2Clause // (here are not updating p->pCnf->pVarNums because it is not needed) vMappingNew = Vec_IntStart( Gia_ManObjNum(p->pGia) ); pObj2Count = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) ); pObj2Clause = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) ); Gia_ManForEachObj( pGia0, pObj, i ) { // skip internal nodes not used in the mapping if ( !~pObj->Value ) continue; // replace positive literal by variable assert( !Abc_LitIsCompl(pObj->Value) ); pObj->Value = Abc_Lit2Var(pObj->Value); assert( (int)pObj->Value < Gia_ManObjNum(p->pGia) ); // update arrays pObj2Count[pObj->Value] = p->pCnf->pObj2Count[i]; pObj2Clause[pObj->Value] = p->pCnf->pObj2Clause[i]; if ( Vec_IntEntry(pGia0->vGateClasses, i) ) Vec_IntWriteEntry( p->pGia->vGateClasses, pObj->Value, 1 ); // update mappings Offset = Vec_IntEntry(p->pCnf->vMapping, i); Vec_IntWriteEntry( vMappingNew, pObj->Value, Vec_IntSize(vMappingNew) ); pMapping = Vec_IntEntryP(p->pCnf->vMapping, Offset); Vec_IntPush( vMappingNew, pMapping[0] ); for ( k = 1; k <= 4; k++ ) { if ( pMapping[k] == -1 ) Vec_IntPush( vMappingNew, -1 ); else { assert( ~Gia_ManObj(pGia0, pMapping[k])->Value ); Vec_IntPush( vMappingNew, Gia_ManObj(pGia0, pMapping[k])->Value ); } } } // update mapping after the offset (currently not being done because it is not used) Vec_IntFree( p->pCnf->vMapping ); p->pCnf->vMapping = vMappingNew; ABC_FREE( p->pCnf->pObj2Count ); p->pCnf->pObj2Count = pObj2Count; ABC_FREE( p->pCnf->pObj2Clause ); p->pCnf->pObj2Clause = pObj2Clause; // count the number of variables p->nObjs = 1; Gia_ManForEachObj( p->pGia, pObj, i ) if ( p->pCnf->pObj2Count[i] >= 0 ) pObj->Value = p->nObjs++; else pObj->Value = ~0; // re-express CNF using new variable IDs pLits = p->pCnf->pClauses[0]; for ( i = 0; i < p->pCnf->nLiterals; i++ ) { // find the original AIG object pObj = Gia_ManObj( pGia0, lit_var(pLits[i]) ); assert( ~pObj->Value ); // find the working AIG object pObj = Gia_ManObj( p->pGia, pObj->Value ); assert( ~pObj->Value ); // express literal in terms of LUT variables pLits[i] = toLitCond( pObj->Value, lit_sign(pLits[i]) ); } // create objects p->pObjs = ABC_CALLOC( Gla_Obj_t, p->nObjs ); p->pObj2Obj = ABC_FALLOC( unsigned, Gia_ManObjNum(p->pGia) ); // p->pvRefis = ABC_CALLOC( Vec_Int_t, Gia_ManObjNum(p->pGia) ); Gia_ManForEachObj( p->pGia, pObj, i ) { p->pObj2Obj[i] = pObj->Value; if ( !~pObj->Value ) continue; pGla = Gla_ManObj( p, pObj->Value ); pGla->iGiaObj = i; pGla->fCompl0 = Gia_ObjFaninC0(pObj); pGla->fConst = Gia_ObjIsConst0(pObj); pGla->fPi = Gia_ObjIsPi(p->pGia, pObj); pGla->fPo = Gia_ObjIsPo(p->pGia, pObj); pGla->fRi = Gia_ObjIsRi(p->pGia, pObj); pGla->fRo = Gia_ObjIsRo(p->pGia, pObj); pGla->fAnd = Gia_ObjIsAnd(pObj); if ( Gia_ObjIsConst0(pObj) || Gia_ObjIsPi(p->pGia, pObj) ) continue; if ( Gia_ObjIsCo(pObj) ) { pGla->nFanins = 1; pGla->Fanins[0] = Gia_ObjFanin0(pObj)->Value; continue; } if ( Gia_ObjIsAnd(pObj) ) { // Gla_ManCollectFanins( p, pGla, pObj->Value, p->vTemp ); // pGla->nFanins = Vec_IntSize( p->vTemp ); // memcpy( pGla->Fanins, Vec_IntArray(p->vTemp), sizeof(int) * Vec_IntSize(p->vTemp) ); Offset = Vec_IntEntry( p->pCnf->vMapping, i ); pMapping = Vec_IntEntryP( p->pCnf->vMapping, Offset ); pGla->nFanins = 0; for ( k = 1; k <= 4; k++ ) if ( pMapping[k] != -1 ) pGla->Fanins[ pGla->nFanins++ ] = Gia_ManObj(p->pGia, pMapping[k])->Value; continue; } assert( Gia_ObjIsRo(p->pGia, pObj) ); pGla->nFanins = 1; pGla->Fanins[0] = Gia_ObjFanin0( Gia_ObjRoToRi(p->pGia, pObj) )->Value; pGla->fCompl0 = Gia_ObjFaninC0( Gia_ObjRoToRi(p->pGia, pObj) ); } p->pObjRoot = Gla_ManObj( p, Gia_ManPo(p->pGia, 0)->Value ); // abstraction assert( p->pGia->vGateClasses != NULL ); Gla_ManForEachObj( p, pGla ) { if ( Vec_IntEntry( p->pGia->vGateClasses, pGla->iGiaObj ) == 0 ) continue; pGla->fAbs = 1; Vec_IntPush( p->vAbs, Gla_ObjId(p, pGla) ); } // other p->pSat = sat_solver2_new(); if ( pPars->fUseFullProof ) p->pSat->pPrf1 = Vec_SetAlloc( 20 ); // p->pSat->fVerbose = p->pPars->fVerbose; // sat_solver2_set_learntmax( p->pSat, pPars->nLearnedMax ); p->pSat->nLearntStart = p->pPars->nLearnedStart; p->pSat->nLearntDelta = p->pPars->nLearnedDelta; p->pSat->nLearntRatio = p->pPars->nLearnedPerce; p->pSat->nLearntMax = p->pSat->nLearntStart; p->nSatVars = 1; // start the refinement manager // p->pGia2 = Gia_ManDup( p->pGia ); p->pRnm = Rnm_ManStart( p->pGia ); return p; } /**Function************************************************************* Synopsis [Creates a new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gla_Man_t * Gla_ManStart2( Gia_Man_t * pGia, Abs_Par_t * pPars ) { Gla_Man_t * p; Aig_Man_t * pAig; Gia_Obj_t * pObj; Gla_Obj_t * pGla; int i, * pLits; // start p = ABC_CALLOC( Gla_Man_t, 1 ); p->pGia = pGia; p->pPars = pPars; p->vAbs = Vec_IntAlloc( 100 ); p->vTemp = Vec_IntAlloc( 100 ); p->vAddedNew = Vec_IntAlloc( 100 ); // internal data pAig = Gia_ManToAigSimple( p->pGia ); p->pCnf = Cnf_DeriveOther( pAig, 1 ); Aig_ManStop( pAig ); // count the number of variables p->nObjs = 1; Gia_ManForEachObj( p->pGia, pObj, i ) if ( p->pCnf->pObj2Count[i] >= 0 ) pObj->Value = p->nObjs++; else pObj->Value = ~0; // re-express CNF using new variable IDs pLits = p->pCnf->pClauses[0]; for ( i = 0; i < p->pCnf->nLiterals; i++ ) { pObj = Gia_ManObj( p->pGia, lit_var(pLits[i]) ); assert( ~pObj->Value ); pLits[i] = toLitCond( pObj->Value, lit_sign(pLits[i]) ); } // create objects p->pObjs = ABC_CALLOC( Gla_Obj_t, p->nObjs ); p->pObj2Obj = ABC_FALLOC( unsigned, Gia_ManObjNum(p->pGia) ); // p->pvRefis = ABC_CALLOC( Vec_Int_t, Gia_ManObjNum(p->pGia) ); Gia_ManForEachObj( p->pGia, pObj, i ) { p->pObj2Obj[i] = pObj->Value; if ( !~pObj->Value ) continue; pGla = Gla_ManObj( p, pObj->Value ); pGla->iGiaObj = i; pGla->fCompl0 = Gia_ObjFaninC0(pObj); pGla->fConst = Gia_ObjIsConst0(pObj); pGla->fPi = Gia_ObjIsPi(p->pGia, pObj); pGla->fPo = Gia_ObjIsPo(p->pGia, pObj); pGla->fRi = Gia_ObjIsRi(p->pGia, pObj); pGla->fRo = Gia_ObjIsRo(p->pGia, pObj); pGla->fAnd = Gia_ObjIsAnd(pObj); if ( Gia_ObjIsConst0(pObj) || Gia_ObjIsPi(p->pGia, pObj) ) continue; if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ) { Gla_ManCollectFanins( p, pGla, pObj->Value, p->vTemp ); pGla->nFanins = Vec_IntSize( p->vTemp ); memcpy( pGla->Fanins, Vec_IntArray(p->vTemp), sizeof(int) * Vec_IntSize(p->vTemp) ); continue; } assert( Gia_ObjIsRo(p->pGia, pObj) ); pGla->nFanins = 1; pGla->Fanins[0] = Gia_ObjFanin0( Gia_ObjRoToRi(p->pGia, pObj) )->Value; pGla->fCompl0 = Gia_ObjFaninC0( Gia_ObjRoToRi(p->pGia, pObj) ); } p->pObjRoot = Gla_ManObj( p, Gia_ManPo(p->pGia, 0)->Value ); // abstraction assert( pGia->vGateClasses != NULL ); Gla_ManForEachObj( p, pGla ) { if ( Vec_IntEntry( pGia->vGateClasses, pGla->iGiaObj ) == 0 ) continue; pGla->fAbs = 1; Vec_IntPush( p->vAbs, Gla_ObjId(p, pGla) ); } // other p->pSat = sat_solver2_new(); p->nSatVars = 1; return p; } /**Function************************************************************* Synopsis [Creates a new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gla_ManStop( Gla_Man_t * p ) { Gla_Obj_t * pGla; int i; if ( p->pPars->fVerbose ) Abc_Print( 1, "SAT solver: Var = %d Cla = %d Conf = %d Lrn = %d Reduce = %d Cex = %d Objs+ = %d\n", sat_solver2_nvars(p->pSat), sat_solver2_nclauses(p->pSat), sat_solver2_nconflicts(p->pSat), sat_solver2_nlearnts(p->pSat), p->pSat->nDBreduces, p->nCexes, p->nObjAdded ); // stop the refinement manager // Gia_ManStopP( &p->pGia2 ); Rnm_ManStop( p->pRnm, 0 ); if ( p->pvRefis ) for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) ABC_FREE( p->pvRefis[i].pArray ); Gla_ManForEachObj( p, pGla ) ABC_FREE( pGla->vFrames.pArray ); Cnf_DataFree( p->pCnf ); if ( p->pGia0 != NULL ) Gia_ManStop( p->pGia ); // Gia_ManStaticFanoutStart( p->pGia0 ); sat_solver2_delete( p->pSat ); Vec_IntFreeP( &p->vObjCounts ); Vec_IntFreeP( &p->vAddedNew ); Vec_IntFreeP( &p->vCoreCounts ); Vec_IntFreeP( &p->vProofIds ); Vec_IntFreeP( &p->vTemp ); Vec_IntFreeP( &p->vAbs ); ABC_FREE( p->pvRefis ); ABC_FREE( p->pObj2Obj ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates a new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_GlaAbsCount( Gla_Man_t * p, int fRo, int fAnd ) { Gla_Obj_t * pObj; int i, Counter = 0; if ( fRo ) Gla_ManForEachObjAbs( p, pObj, i ) Counter += (pObj->fRo && pObj->fAbs); else if ( fAnd ) Gla_ManForEachObjAbs( p, pObj, i ) Counter += (pObj->fAnd && pObj->fAbs); else Gla_ManForEachObjAbs( p, pObj, i ) Counter += (pObj->fAbs); return Counter; } /**Function************************************************************* Synopsis [Derives new abstraction map.] Description [Returns 1 if node contains abstracted leaf on the path.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gla_ManTranslate_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vGla, int nUsageCount ) { int Value0, Value1; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 1; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) return 0; assert( Gia_ObjIsAnd(pObj) ); Value0 = Gla_ManTranslate_rec( p, Gia_ObjFanin0(pObj), vGla, nUsageCount ); Value1 = Gla_ManTranslate_rec( p, Gia_ObjFanin1(pObj), vGla, nUsageCount ); if ( Value0 || Value1 ) Vec_IntAddToEntry( vGla, Gia_ObjId(p, pObj), nUsageCount ); return Value0 || Value1; } Vec_Int_t * Gla_ManTranslate( Gla_Man_t * p ) { Vec_Int_t * vGla, * vGla2; Gla_Obj_t * pObj, * pFanin; Gia_Obj_t * pGiaObj; int i, k, nUsageCount; vGla = Vec_IntStart( Gia_ManObjNum(p->pGia) ); Gla_ManForEachObjAbs( p, pObj, i ) { nUsageCount = Vec_IntEntry(p->vCoreCounts, pObj->iGiaObj); assert( nUsageCount >= 0 ); if ( nUsageCount == 0 ) nUsageCount++; pGiaObj = Gla_ManGiaObj( p, pObj ); if ( Gia_ObjIsConst0(pGiaObj) || Gia_ObjIsRo(p->pGia, pGiaObj) ) { Vec_IntWriteEntry( vGla, pObj->iGiaObj, nUsageCount ); continue; } assert( Gia_ObjIsAnd(pGiaObj) ); Gia_ManIncrementTravId( p->pGia ); Gla_ObjForEachFanin( p, pObj, pFanin, k ) Gia_ObjSetTravIdCurrent( p->pGia, Gla_ManGiaObj(p, pFanin) ); Gla_ManTranslate_rec( p->pGia, pGiaObj, vGla, nUsageCount ); } Vec_IntWriteEntry( vGla, 0, p->pPars->iFrame+1 ); if ( p->pGia->vLutConfigs ) // use mapping from new to old { vGla2 = Vec_IntStart( Gia_ManObjNum(p->pGia0) ); for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) if ( Vec_IntEntry(vGla, i) ) Vec_IntWriteEntry( vGla2, Vec_IntEntry(p->pGia->vLutConfigs, i), Vec_IntEntry(vGla, i) ); Vec_IntFree( vGla ); return vGla2; } return vGla; } /**Function************************************************************* Synopsis [Collect pseudo-PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gla_ManCollectPPis( Gla_Man_t * p, Vec_Int_t * vPis ) { Vec_Int_t * vPPis; Gla_Obj_t * pObj, * pFanin; int i, k; vPPis = Vec_IntAlloc( 1000 ); if ( vPis ) Vec_IntClear( vPis ); Gla_ManForEachObjAbs( p, pObj, i ) { assert( pObj->fConst || pObj->fRo || pObj->fAnd ); Gla_ObjForEachFanin( p, pObj, pFanin, k ) if ( !pFanin->fPi && !pFanin->fAbs ) Vec_IntPush( vPPis, pObj->Fanins[k] ); else if ( vPis && pFanin->fPi && !pFanin->fAbs ) Vec_IntPush( vPis, pObj->Fanins[k] ); } Vec_IntUniqify( vPPis ); Vec_IntReverseOrder( vPPis ); if ( vPis ) Vec_IntUniqify( vPis ); return vPPis; } int Gla_ManCountPPis( Gla_Man_t * p ) { Vec_Int_t * vPPis = Gla_ManCollectPPis( p, NULL ); int RetValue = Vec_IntSize( vPPis ); Vec_IntFree( vPPis ); return RetValue; } void Gla_ManExplorePPis( Gla_Man_t * p, Vec_Int_t * vPPis ) { static int Round = 0; Gla_Obj_t * pObj, * pFanin; int i, j, k, Count; if ( (Round++ % 5) == 0 ) return; j = 0; Gla_ManForEachObjAbsVec( vPPis, p, pObj, i ) { assert( pObj->fAbs == 0 ); Count = 0; Gla_ObjForEachFanin( p, pObj, pFanin, k ) Count += pFanin->fAbs; if ( Count == 0 || ((Round & 1) && Count == 1) ) continue; Vec_IntWriteEntry( vPPis, j++, Gla_ObjId(p, pObj) ); } // printf( "\n%d -> %d\n", Vec_IntSize(vPPis), j ); Vec_IntShrink( vPPis, j ); } /**Function************************************************************* Synopsis [Adds CNF for the given timeframe.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gla_ManCheckVar( Gla_Man_t * p, int iObj, int iFrame ) { Gla_Obj_t * pGla = Gla_ManObj( p, iObj ); int iVar = Vec_IntGetEntry( &pGla->vFrames, iFrame ); assert( !pGla->fPo && !pGla->fRi ); return (iVar > 0); } int Gla_ManGetVar( Gla_Man_t * p, int iObj, int iFrame ) { Gla_Obj_t * pGla = Gla_ManObj( p, iObj ); int iVar = Vec_IntGetEntry( &pGla->vFrames, iFrame ); assert( !pGla->fPo && !pGla->fRi ); if ( iVar == 0 ) { Vec_IntSetEntry( &pGla->vFrames, iFrame, (iVar = p->nSatVars++) ); // remember the change Vec_IntPush( p->vAddedNew, iObj ); Vec_IntPush( p->vAddedNew, iFrame ); } return iVar; } void Gla_ManAddClauses( Gla_Man_t * p, int iObj, int iFrame, Vec_Int_t * vLits ) { Gla_Obj_t * pGlaObj = Gla_ManObj( p, iObj ); int iVar, iVar1, iVar2; if ( pGlaObj->fConst ) { iVar = Gla_ManGetVar( p, iObj, iFrame ); sat_solver2_add_const( p->pSat, iVar, 1, 0, iObj ); } else if ( pGlaObj->fRo ) { assert( pGlaObj->nFanins == 1 ); if ( iFrame == 0 ) { iVar = Gla_ManGetVar( p, iObj, iFrame ); sat_solver2_add_const( p->pSat, iVar, 1, 0, iObj ); } else { iVar1 = Gla_ManGetVar( p, iObj, iFrame ); iVar2 = Gla_ManGetVar( p, pGlaObj->Fanins[0], iFrame-1 ); sat_solver2_add_buffer( p->pSat, iVar1, iVar2, pGlaObj->fCompl0, 0, iObj ); } } else if ( pGlaObj->fAnd ) { int i, RetValue, nClauses, iFirstClause, * pLit; nClauses = p->pCnf->pObj2Count[pGlaObj->iGiaObj]; iFirstClause = p->pCnf->pObj2Clause[pGlaObj->iGiaObj]; for ( i = iFirstClause; i < iFirstClause + nClauses; i++ ) { Vec_IntClear( vLits ); for ( pLit = p->pCnf->pClauses[i]; pLit < p->pCnf->pClauses[i+1]; pLit++ ) { iVar = Gla_ManGetVar( p, lit_var(*pLit), iFrame ); Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) ); } RetValue = sat_solver2_addclause( p->pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits), iObj ); } } else assert( 0 ); } void Gia_GlaAddToCounters( Gla_Man_t * p, Vec_Int_t * vCore ) { Gla_Obj_t * pGla; int i; Gla_ManForEachObjAbsVec( vCore, p, pGla, i ) Vec_IntAddToEntry( p->vCoreCounts, pGla->iGiaObj, 1 ); } void Gia_GlaAddToAbs( Gla_Man_t * p, Vec_Int_t * vAbsAdd, int fCheck ) { Gla_Obj_t * pGla; int i, k = 0; Gla_ManForEachObjAbsVec( vAbsAdd, p, pGla, i ) { if ( fCheck ) { assert( pGla->fAbs == 0 ); if ( p->pSat->pPrf2 ) Vec_IntWriteEntry( p->vProofIds, Gla_ObjId(p, pGla), p->nProofIds++ ); } if ( pGla->fAbs ) continue; pGla->fAbs = 1; Vec_IntPush( p->vAbs, Gla_ObjId(p, pGla) ); // filter clauses to remove those contained in the abstraction Vec_IntWriteEntry( vAbsAdd, k++, Gla_ObjId(p, pGla) ); } Vec_IntShrink( vAbsAdd, k ); } void Gia_GlaAddTimeFrame( Gla_Man_t * p, int f ) { Gla_Obj_t * pObj; int i; Gla_ManForEachObjAbs( p, pObj, i ) Gla_ManAddClauses( p, Gla_ObjId(p, pObj), f, p->vTemp ); sat_solver2_simplify( p->pSat ); } void Gia_GlaAddOneSlice( Gla_Man_t * p, int fCur, Vec_Int_t * vCore ) { int f, i, iGlaObj; for ( f = fCur; f >= 0; f-- ) Vec_IntForEachEntry( vCore, iGlaObj, i ) Gla_ManAddClauses( p, iGlaObj, f, p->vTemp ); sat_solver2_simplify( p->pSat ); } void Gla_ManRollBack( Gla_Man_t * p ) { int i, iObj, iFrame; Vec_IntForEachEntryDouble( p->vAddedNew, iObj, iFrame, i ) { assert( Vec_IntEntry( &Gla_ManObj(p, iObj)->vFrames, iFrame ) > 0 ); Vec_IntWriteEntry( &Gla_ManObj(p, iObj)->vFrames, iFrame, 0 ); } Vec_IntForEachEntryStart( p->vAbs, iObj, i, p->nAbsOld ) { assert( Gla_ManObj( p, iObj )->fAbs == 1 ); Gla_ManObj( p, iObj )->fAbs = 0; } Vec_IntShrink( p->vAbs, p->nAbsOld ); } /**Function************************************************************* Synopsis [Finds the set of clauses involved in the UNSAT core.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gla_ManGetOutLit( Gla_Man_t * p, int f ) { Gla_Obj_t * pFanin = Gla_ManObj( p, p->pObjRoot->Fanins[0] ); int iSat = Vec_IntEntry( &pFanin->vFrames, f ); assert( iSat > 0 ); if ( f == 0 && pFanin->fRo && !p->pObjRoot->fCompl0 ) return -1; return Abc_Var2Lit( iSat, p->pObjRoot->fCompl0 ); } Vec_Int_t * Gla_ManUnsatCore( Gla_Man_t * p, int f, sat_solver2 * pSat, int nConfMax, int fVerbose, int * piRetValue, int * pnConfls ) { Vec_Int_t * vCore = NULL; int nConfPrev = pSat->stats.conflicts; int RetValue, iLit = Gla_ManGetOutLit( p, f ); abctime clk = Abc_Clock(); if ( piRetValue ) *piRetValue = 1; // consider special case when PO points to the flop // this leads to immediate conflict in the first timeframe if ( iLit == -1 ) { vCore = Vec_IntAlloc( 1 ); Vec_IntPush( vCore, p->pObjRoot->Fanins[0] ); return vCore; } // solve the problem RetValue = sat_solver2_solve( pSat, &iLit, &iLit+1, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( pnConfls ) *pnConfls = (int)pSat->stats.conflicts - nConfPrev; if ( RetValue == l_Undef ) { if ( piRetValue ) *piRetValue = -1; return NULL; } if ( RetValue == l_True ) { if ( piRetValue ) *piRetValue = 0; return NULL; } if ( fVerbose ) { // Abc_Print( 1, "%6d", (int)pSat->stats.conflicts - nConfPrev ); // Abc_Print( 1, "UNSAT after %7d conflicts. ", pSat->stats.conflicts ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } assert( RetValue == l_False ); // derive the UNSAT core clk = Abc_Clock(); vCore = (Vec_Int_t *)Sat_ProofCore( pSat ); if ( vCore ) Vec_IntSort( vCore, 1 ); if ( fVerbose ) { // Abc_Print( 1, "Core is %8d vars (out of %8d). ", Vec_IntSize(vCore), sat_solver2_nvars(pSat) ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return vCore; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gla_ManAbsPrintFrame( Gla_Man_t * p, int nCoreSize, int nFrames, int nConfls, int nCexes, abctime Time ) { if ( Abc_FrameIsBatchMode() && nCoreSize <= 0 ) return; Abc_Print( 1, "%4d :", nFrames-1 ); Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * Gia_GlaAbsCount(p, 0, 0) / (p->nObjs - Gia_ManPoNum(p->pGia) + Gia_ManCoNum(p->pGia) + 1)) ); Abc_Print( 1, "%6d", Gia_GlaAbsCount(p, 0, 0) ); Abc_Print( 1, "%5d", Gla_ManCountPPis(p) ); Abc_Print( 1, "%5d", Gia_GlaAbsCount(p, 1, 0) ); Abc_Print( 1, "%6d", Gia_GlaAbsCount(p, 0, 1) ); Abc_Print( 1, "%8d", nConfls ); if ( nCexes == 0 ) Abc_Print( 1, "%5c", '-' ); else Abc_Print( 1, "%5d", nCexes ); // Abc_Print( 1, " %9d", sat_solver2_nvars(p->pSat) ); Abc_PrintInt( sat_solver2_nvars(p->pSat) ); Abc_PrintInt( sat_solver2_nclauses(p->pSat) ); Abc_PrintInt( sat_solver2_nlearnts(p->pSat) ); // Abc_Print( 1, " %6d", nCoreSize > 0 ? nCoreSize : 0 ); Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC ); Abc_Print( 1, "%5.0f MB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<20) ); // Abc_PrintInt( p->nAbsNew ); // Abc_PrintInt( p->nLrnNew ); // Abc_Print( 1, "%4.1f MB", 4.0 * p->nLrnNew * Abc_BitWordNum(p->nAbsNew) / (1<<20) ); Abc_Print( 1, "%s", (nCoreSize > 0 && nCexes > 0) ? "\n" : "\r" ); fflush( stdout ); } void Gla_ManReportMemory( Gla_Man_t * p ) { Gla_Obj_t * pGla; double memTot = 0; double memAig = Gia_ManObjNum(p->pGia) * sizeof(Gia_Obj_t); double memSat = sat_solver2_memory( p->pSat, 1 ); double memPro = sat_solver2_memory_proof( p->pSat ); double memMap = p->nObjs * sizeof(Gla_Obj_t) + Gia_ManObjNum(p->pGia) * sizeof(int); double memRef = Rnm_ManMemoryUsage( p->pRnm ); double memOth = sizeof(Gla_Man_t); for ( pGla = p->pObjs; pGla < p->pObjs + p->nObjs; pGla++ ) memMap += Vec_IntCap(&pGla->vFrames) * sizeof(int); memOth += Vec_IntCap(p->vAddedNew) * sizeof(int); memOth += Vec_IntCap(p->vTemp) * sizeof(int); memOth += Vec_IntCap(p->vAbs) * sizeof(int); memTot = memAig + memSat + memPro + memMap + memRef + memOth; ABC_PRMP( "Memory: AIG ", memAig, memTot ); ABC_PRMP( "Memory: SAT ", memSat, memTot ); ABC_PRMP( "Memory: Proof ", memPro, memTot ); ABC_PRMP( "Memory: Map ", memMap, memTot ); ABC_PRMP( "Memory: Refine ", memRef, memTot ); ABC_PRMP( "Memory: Other ", memOth, memTot ); ABC_PRMP( "Memory: TOTAL ", memTot, memTot ); } /**Function************************************************************* Synopsis [Send abstracted model or send cancel.] Description [Counter-example will be sent automatically when &vta terminates.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_GlaSendAbsracted( Gla_Man_t * p, int fVerbose ) { Gia_Man_t * pAbs; Vec_Int_t * vGateClasses; assert( Abc_FrameIsBridgeMode() ); // if ( fVerbose ) // Abc_Print( 1, "Sending abstracted model...\n" ); // create abstraction (value of p->pGia is not used here) vGateClasses = Gla_ManTranslate( p ); pAbs = Gia_ManDupAbsGates( p->pGia0, vGateClasses ); Vec_IntFreeP( &vGateClasses ); // send it out Gia_ManToBridgeAbsNetlist( stdout, pAbs, BRIDGE_ABS_NETLIST ); Gia_ManStop( pAbs ); } void Gia_GlaSendCancel( Gla_Man_t * p, int fVerbose ) { extern int Gia_ManToBridgeBadAbs( FILE * pFile ); assert( Abc_FrameIsBridgeMode() ); // if ( fVerbose ) // Abc_Print( 1, "Cancelling previously sent model...\n" ); Gia_ManToBridgeBadAbs( stdout ); } /**Function************************************************************* Synopsis [Send abstracted model or send cancel.] Description [Counter-example will be sent automatically when &vta terminates.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_GlaDumpAbsracted( Gla_Man_t * p, int fVerbose ) { char * pFileNameDef = "glabs.aig"; char * pFileName = p->pPars->pFileVabs ? p->pPars->pFileVabs : pFileNameDef; Gia_Man_t * pAbs; Vec_Int_t * vGateClasses; if ( fVerbose ) Abc_Print( 1, "Dumping abstracted model into file \"%s\"...\n", pFileName ); // create abstraction vGateClasses = Gla_ManTranslate( p ); pAbs = Gia_ManDupAbsGates( p->pGia0, vGateClasses ); Vec_IntFreeP( &vGateClasses ); // write into file Gia_AigerWrite( pAbs, pFileName, 0, 0 ); Gia_ManStop( pAbs ); } /**Function************************************************************* Synopsis [Performs gate-level abstraction] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManPerformGlaOld( Gia_Man_t * pAig, Abs_Par_t * pPars, int fStartVta ) { extern int Gia_VtaPerformInt( Gia_Man_t * pAig, Abs_Par_t * pPars ); extern void Ga2_ManDumpStats( Gia_Man_t * pGia, Abs_Par_t * pPars, sat_solver2 * pSat, int iFrame, int fUseN ); Gla_Man_t * p; Vec_Int_t * vPPis, * vCore;//, * vCore2 = NULL; Abc_Cex_t * pCex = NULL; int f, i, iPrev, nConfls, Status, nVarsOld = 0, nCoreSize, fOneIsSent = 0, RetValue = -1; abctime clk2, clk = Abc_Clock(); // preconditions assert( Gia_ManPoNum(pAig) == 1 ); assert( pPars->nFramesMax == 0 || pPars->nFramesStart <= pPars->nFramesMax ); if ( Gia_ObjIsConst0(Gia_ObjFanin0(Gia_ManPo(pAig,0))) ) { if ( !Gia_ObjFaninC0(Gia_ManPo(pAig,0)) ) { printf( "Sequential miter is trivially UNSAT.\n" ); return 1; } ABC_FREE( pAig->pCexSeq ); pAig->pCexSeq = Abc_CexMakeTriv( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), 1, 0 ); printf( "Sequential miter is trivially SAT.\n" ); return 0; } // compute intial abstraction if ( pAig->vGateClasses == NULL ) { if ( fStartVta ) { int nFramesMaxOld = pPars->nFramesMax; int nFramesStartOld = pPars->nFramesStart; int nTimeOutOld = pPars->nTimeOut; int nDumpOld = pPars->fDumpVabs; pPars->nFramesMax = pPars->nFramesStart; pPars->nFramesStart = Abc_MinInt( pPars->nFramesStart/2 + 1, 3 ); pPars->nTimeOut = 20; pPars->fDumpVabs = 0; RetValue = Gia_VtaPerformInt( pAig, pPars ); pPars->nFramesMax = nFramesMaxOld; pPars->nFramesStart = nFramesStartOld; pPars->nTimeOut = nTimeOutOld; pPars->fDumpVabs = nDumpOld; // create gate classes Vec_IntFreeP( &pAig->vGateClasses ); if ( pAig->vObjClasses ) pAig->vGateClasses = Gia_VtaConvertToGla( pAig, pAig->vObjClasses ); Vec_IntFreeP( &pAig->vObjClasses ); // return if VTA solve the problem if could not start if ( RetValue == 0 || pAig->vGateClasses == NULL ) return RetValue; } else { pAig->vGateClasses = Vec_IntStart( Gia_ManObjNum(pAig) ); Vec_IntWriteEntry( pAig->vGateClasses, 0, 1 ); Vec_IntWriteEntry( pAig->vGateClasses, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)), 1 ); } } // start the manager p = Gla_ManStart( pAig, pPars ); p->timeInit = Abc_Clock() - clk; // set runtime limit if ( p->pPars->nTimeOut ) sat_solver2_set_runtime_limit( p->pSat, p->pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); // perform initial abstraction if ( p->pPars->fVerbose ) { Abc_Print( 1, "Running gate-level abstraction (GLA) with the following parameters:\n" ); Abc_Print( 1, "FrameMax = %d ConfMax = %d Timeout = %d RatioMin = %d %%.\n", pPars->nFramesMax, pPars->nConfLimit, pPars->nTimeOut, pPars->nRatioMin ); Abc_Print( 1, "LearnStart = %d LearnDelta = %d LearnRatio = %d %%.\n", pPars->nLearnedStart, pPars->nLearnedDelta, pPars->nLearnedPerce ); Abc_Print( 1, " Frame %% Abs PPI FF LUT Confl Cex Vars Clas Lrns Time Mem\n" ); } for ( f = i = iPrev = 0; !p->pPars->nFramesMax || f < p->pPars->nFramesMax; f++, iPrev = i ) { int nConflsBeg = sat_solver2_nconflicts(p->pSat); p->pPars->iFrame = f; // load timeframe Gia_GlaAddTimeFrame( p, f ); // iterate as long as there are counter-examples for ( i = 0; ; i++ ) { clk2 = Abc_Clock(); vCore = Gla_ManUnsatCore( p, f, p->pSat, pPars->nConfLimit, pPars->fVerbose, &Status, &nConfls ); // assert( (vCore != NULL) == (Status == 1) ); if ( Status == -1 || (p->pSat->nRuntimeLimit && Abc_Clock() > p->pSat->nRuntimeLimit) ) // resource limit is reached { Prf_ManStopP( &p->pSat->pPrf2 ); // if ( Gia_ManRegNum(p->pGia) > 1 ) // for comb cases, return the abstraction // Vec_IntShrink( p->vAbs, p->nAbsOld ); goto finish; } if ( Status == 1 ) { Prf_ManStopP( &p->pSat->pPrf2 ); p->timeUnsat += Abc_Clock() - clk2; break; } p->timeSat += Abc_Clock() - clk2; assert( Status == 0 ); p->nCexes++; // cancel old one if it was sent if ( Abc_FrameIsBridgeMode() && fOneIsSent ) { Gia_GlaSendCancel( p, pPars->fVerbose ); fOneIsSent = 0; } // perform the refinement clk2 = Abc_Clock(); if ( pPars->fAddLayer ) { vPPis = Gla_ManCollectPPis( p, NULL ); // Gla_ManExplorePPis( p, vPPis ); } else { vPPis = Gla_ManRefinement( p ); if ( vPPis == NULL ) { Prf_ManStopP( &p->pSat->pPrf2 ); pCex = p->pGia->pCexSeq; p->pGia->pCexSeq = NULL; break; } } assert( pCex == NULL ); // start proof logging if ( i == 0 ) { // create bookmark to be used for rollback sat_solver2_bookmark( p->pSat ); Vec_IntClear( p->vAddedNew ); p->nAbsOld = Vec_IntSize( p->vAbs ); nVarsOld = p->nSatVars; // p->nLrnOld = sat_solver2_nlearnts( p->pSat ); // p->nAbsNew = 0; // p->nLrnNew = 0; // start incremental proof manager assert( p->pSat->pPrf2 == NULL ); if ( p->pSat->pPrf1 == NULL ) p->pSat->pPrf2 = Prf_ManAlloc(); if ( p->pSat->pPrf2 ) { p->nProofIds = 0; Vec_IntFill( p->vProofIds, Gia_ManObjNum(p->pGia), -1 ); Prf_ManRestart( p->pSat->pPrf2, p->vProofIds, sat_solver2_nlearnts(p->pSat), Vec_IntSize(vPPis) ); } } else { // resize the proof logger if ( p->pSat->pPrf2 ) Prf_ManGrow( p->pSat->pPrf2, p->nProofIds + Vec_IntSize(vPPis) ); } Gia_GlaAddToAbs( p, vPPis, 1 ); Gia_GlaAddOneSlice( p, f, vPPis ); Vec_IntFree( vPPis ); // print the result (do not count it towards change) if ( p->pPars->fVerbose ) Gla_ManAbsPrintFrame( p, -1, f+1, sat_solver2_nconflicts(p->pSat)-nConflsBeg, i, Abc_Clock() - clk ); } if ( pCex != NULL ) break; assert( Status == 1 ); // valid core is obtained nCoreSize = 1; if ( vCore ) { nCoreSize += Vec_IntSize( vCore ); Gia_GlaAddToCounters( p, vCore ); } if ( i == 0 ) { p->pPars->nFramesNoChange++; Vec_IntFreeP( &vCore ); } else { p->pPars->nFramesNoChange = 0; // p->nAbsNew = Vec_IntSize( p->vAbs ) - p->nAbsOld; // p->nLrnNew = Abc_AbsInt( sat_solver2_nlearnts( p->pSat ) - p->nLrnOld ); // update the SAT solver sat_solver2_rollback( p->pSat ); // update storage Gla_ManRollBack( p ); p->nSatVars = nVarsOld; // load this timeframe Gia_GlaAddToAbs( p, vCore, 0 ); Gia_GlaAddOneSlice( p, f, vCore ); Vec_IntFree( vCore ); // run SAT solver clk2 = Abc_Clock(); vCore = Gla_ManUnsatCore( p, f, p->pSat, pPars->nConfLimit, p->pPars->fVerbose, &Status, &nConfls ); p->timeUnsat += Abc_Clock() - clk2; // assert( (vCore != NULL) == (Status == 1) ); Vec_IntFreeP( &vCore ); if ( Status == -1 ) // resource limit is reached break; if ( Status == 0 ) { assert( 0 ); // Vta_ManSatVerify( p ); // make sure, there was no initial abstraction (otherwise, it was invalid) assert( pAig->vObjClasses == NULL && f < p->pPars->nFramesStart ); // pCex = Vga_ManDeriveCex( p ); break; } } // print the result if ( p->pPars->fVerbose ) Gla_ManAbsPrintFrame( p, nCoreSize, f+1, sat_solver2_nconflicts(p->pSat)-nConflsBeg, i, Abc_Clock() - clk ); if ( f > 2 && iPrev > 0 && i == 0 ) // change has happened { if ( Abc_FrameIsBridgeMode() ) { // cancel old one if it was sent if ( fOneIsSent ) Gia_GlaSendCancel( p, pPars->fVerbose ); // send new one Gia_GlaSendAbsracted( p, pPars->fVerbose ); fOneIsSent = 1; } // dump the model into file if ( p->pPars->fDumpVabs ) { char Command[1000]; Abc_FrameSetStatus( -1 ); Abc_FrameSetCex( NULL ); Abc_FrameSetNFrames( f+1 ); sprintf( Command, "write_status %s", Extra_FileNameGenericAppend((char *)(p->pPars->pFileVabs ? p->pPars->pFileVabs : "glabs.aig"), ".status") ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); Gia_GlaDumpAbsracted( p, pPars->fVerbose ); } } // check if the number of objects is below limit if ( Gia_GlaAbsCount(p,0,0) >= (p->nObjs - 1) * (100 - pPars->nRatioMin) / 100 ) { Status = -1; break; } } finish: // analize the results if ( pCex == NULL ) { if ( p->pPars->fVerbose && Status == -1 ) printf( "\n" ); // if ( pAig->vGateClasses != NULL ) // Abc_Print( 1, "Replacing the old abstraction by a new one.\n" ); Vec_IntFreeP( &pAig->vGateClasses ); pAig->vGateClasses = Gla_ManTranslate( p ); if ( Status == -1 ) { if ( p->pPars->nTimeOut && Abc_Clock() >= p->pSat->nRuntimeLimit ) Abc_Print( 1, "Timeout %d sec in frame %d with a %d-stable abstraction. ", p->pPars->nTimeOut, f, p->pPars->nFramesNoChange ); else if ( pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit ) Abc_Print( 1, "Exceeded %d conflicts in frame %d with a %d-stable abstraction. ", pPars->nConfLimit, f, p->pPars->nFramesNoChange ); else if ( Gia_GlaAbsCount(p,0,0) >= (p->nObjs - 1) * (100 - pPars->nRatioMin) / 100 ) Abc_Print( 1, "The ratio of abstracted objects is less than %d %% in frame %d. ", pPars->nRatioMin, f ); else Abc_Print( 1, "Abstraction stopped for unknown reason in frame %d. ", f ); } else { p->pPars->iFrame++; Abc_Print( 1, "GLA completed %d frames with a %d-stable abstraction. ", f, p->pPars->nFramesNoChange ); } } else { if ( p->pPars->fVerbose ) printf( "\n" ); ABC_FREE( pAig->pCexSeq ); pAig->pCexSeq = pCex; if ( !Gia_ManVerifyCex( pAig, pCex, 0 ) ) Abc_Print( 1, " Gia_ManPerformGlaOld(): CEX verification has failed!\n" ); Abc_Print( 1, "Counter-example detected in frame %d. ", f ); p->pPars->iFrame = pCex->iFrame - 1; Vec_IntFreeP( &pAig->vGateClasses ); RetValue = 0; } Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( p->pPars->fVerbose ) { p->timeOther = (Abc_Clock() - clk) - p->timeUnsat - p->timeSat - p->timeCex - p->timeInit; ABC_PRTP( "Runtime: Initializing", p->timeInit, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Solver UNSAT", p->timeUnsat, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Solver SAT ", p->timeSat, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Refinement ", p->timeCex, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Other ", p->timeOther, Abc_Clock() - clk ); ABC_PRTP( "Runtime: TOTAL ", Abc_Clock() - clk, Abc_Clock() - clk ); Gla_ManReportMemory( p ); } // Ga2_ManDumpStats( pAig, p->pPars, p->pSat, p->pPars->iFrame, 1 ); Gla_ManStop( p ); fflush( stdout ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absIter.c000066400000000000000000000123211300674244400234620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absIter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Iterative improvement of abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Gia_ObjIsInGla( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry(p->vGateClasses, Gia_ObjId(p, pObj)); } static inline void Gia_ObjAddToGla( Gia_Man_t * p, Gia_Obj_t * pObj ) { Vec_IntWriteEntry(p->vGateClasses, Gia_ObjId(p, pObj), 1); } static inline void Gia_ObjRemFromGla( Gia_Man_t * p, Gia_Obj_t * pObj ) { Vec_IntWriteEntry(p->vGateClasses, Gia_ObjId(p, pObj), 0); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_IterTryImprove( Gia_Man_t * p, int nTimeOut, int iFrame0 ) { Gia_Man_t * pAbs = Gia_ManDupAbsGates( p, p->vGateClasses ); Aig_Man_t * pAig = Gia_ManToAigSimple( pAbs ); int nStart = 0; int nFrames = iFrame0 ? iFrame0 + 1 : 10000000; int nNodeDelta = 2000; int nBTLimit = 0; int nBTLimitAll = 0; int fVerbose = 0; int RetValue, iFrame; RetValue = Saig_BmcPerform( pAig, nStart, nFrames, nNodeDelta, nTimeOut, nBTLimit, nBTLimitAll, fVerbose, 0, &iFrame, 1 ); assert( RetValue == 0 || RetValue == -1 ); Aig_ManStop( pAig ); Gia_ManStop( pAbs ); return iFrame; } Gia_Man_t * Gia_ManShrinkGla( Gia_Man_t * p, int nFrameMax, int nTimeOut, int fUsePdr, int fUseSat, int fUseBdd, int fVerbose ) { Gia_Obj_t * pObj; int i, iFrame0, iFrame; int nTotal = 0, nRemoved = 0; Vec_Int_t * vGScopy; abctime clk, clkTotal = Abc_Clock(); assert( Gia_ManPoNum(p) == 1 ); assert( p->vGateClasses != NULL ); vGScopy = Vec_IntDup( p->vGateClasses ); if ( nFrameMax == 0 ) iFrame0 = Gia_IterTryImprove( p, 0, 0 ); else iFrame0 = nFrameMax - 1; while ( 1 ) { int fChanges = 0; Gia_ManForEachObj1( p, pObj, i ) { if ( pObj->fMark0 ) continue; if ( !Gia_ObjIsInGla(p, pObj) ) continue; if ( pObj == Gia_ObjFanin0( Gia_ManPo(p, 0) ) ) continue; if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjIsInGla(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsInGla(p, Gia_ObjFanin1(pObj)) ) continue; } if ( Gia_ObjIsRo(p, pObj) ) { if ( Gia_ObjIsInGla(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))) ) continue; } clk = Abc_Clock(); printf( "%5d : ", nTotal ); printf( "Obj =%7d ", i ); Gia_ObjRemFromGla( p, pObj ); iFrame = Gia_IterTryImprove( p, nTimeOut, iFrame0 ); if ( nFrameMax ) assert( iFrame <= nFrameMax ); else assert( iFrame <= iFrame0 ); printf( "Frame =%6d ", iFrame ); if ( iFrame < iFrame0 ) { pObj->fMark0 = 1; Gia_ObjAddToGla( p, pObj ); printf( " " ); } else { fChanges = 1; nRemoved++; printf( "Removing " ); Vec_IntWriteEntry( vGScopy, Gia_ObjId(p, pObj), 0 ); } Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); nTotal++; // update the classes Vec_IntFreeP( &p->vGateClasses ); p->vGateClasses = Vec_IntDup(vGScopy); } if ( !fChanges ) break; } Gia_ManCleanMark0(p); Vec_IntFree( vGScopy ); printf( "Tried = %d. ", nTotal ); printf( "Removed = %d. (%.2f %%) ", nRemoved, 100.0 * nRemoved / Vec_IntCountPositive(p->vGateClasses) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absOldCex.c000066400000000000000000000741151300674244400237460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigAbsCba.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [CEX-based abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigAbsCba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // local manager typedef struct Saig_ManCba_t_ Saig_ManCba_t; struct Saig_ManCba_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 // additional information Vec_Vec_t * vReg2Frame; // register to frame mapping Vec_Vec_t * vReg2Value; // register to value mapping }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Selects the best flops from the given array.] Description [Selects the best 'nFfsToSelect' flops among the array 'vAbsFfsToAdd' of flops that should be added to the abstraction. To this end, this procedure simulates the original AIG (pAig) using the given CEX (pAbsCex), which was detected for the abstraction.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManCbaFilterFlops( Aig_Man_t * pAig, Abc_Cex_t * pAbsCex, Vec_Int_t * vFlopClasses, Vec_Int_t * vAbsFfsToAdd, int nFfsToSelect ) { Aig_Obj_t * pObj, * pObjRi, * pObjRo; Vec_Int_t * vMapEntries, * vFlopCosts, * vFlopAddCosts, * vFfsToAddBest; int i, k, f, Entry, iBit, * pPerm; assert( Aig_ManRegNum(pAig) == Vec_IntSize(vFlopClasses) ); assert( Vec_IntSize(vAbsFfsToAdd) > nFfsToSelect ); // map previously abstracted flops into their original numbers vMapEntries = Vec_IntAlloc( Vec_IntSize(vFlopClasses) ); Vec_IntForEachEntry( vFlopClasses, Entry, i ) if ( Entry == 0 ) Vec_IntPush( vMapEntries, i ); // simulate one frame at a time assert( Saig_ManPiNum(pAig) + Vec_IntSize(vMapEntries) == pAbsCex->nPis ); vFlopCosts = Vec_IntStart( Vec_IntSize(vMapEntries) ); // initialize the flops Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) pObj->fMarkB = 0; for ( f = 0; f < pAbsCex->iFrame; f++ ) { // override the flop values according to the cex iBit = pAbsCex->nRegs + f * pAbsCex->nPis + Saig_ManPiNum(pAig); Vec_IntForEachEntry( vMapEntries, Entry, k ) Saig_ManLo(pAig, Entry)->fMarkB = Abc_InfoHasBit(pAbsCex->pData, iBit + k); // simulate 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); // transfer Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) pObjRo->fMarkB = pObjRi->fMarkB; // compare iBit = pAbsCex->nRegs + (f + 1) * pAbsCex->nPis + Saig_ManPiNum(pAig); Vec_IntForEachEntry( vMapEntries, Entry, k ) if ( Saig_ManLi(pAig, Entry)->fMarkB != (unsigned)Abc_InfoHasBit(pAbsCex->pData, iBit + k) ) Vec_IntAddToEntry( vFlopCosts, k, 1 ); } // Vec_IntForEachEntry( vFlopCosts, Entry, i ) // printf( "%d ", Entry ); // printf( "\n" ); // remap the cost vFlopAddCosts = Vec_IntAlloc( Vec_IntSize(vAbsFfsToAdd) ); Vec_IntForEachEntry( vAbsFfsToAdd, Entry, i ) Vec_IntPush( vFlopAddCosts, -Vec_IntEntry(vFlopCosts, Entry) ); // sort the flops pPerm = Abc_MergeSortCost( Vec_IntArray(vFlopAddCosts), Vec_IntSize(vFlopAddCosts) ); // shrink the array vFfsToAddBest = Vec_IntAlloc( nFfsToSelect ); for ( i = 0; i < nFfsToSelect; i++ ) { // printf( "%d ", Vec_IntEntry(vFlopAddCosts, pPerm[i]) ); Vec_IntPush( vFfsToAddBest, Vec_IntEntry(vAbsFfsToAdd, pPerm[i]) ); } // printf( "\n" ); // cleanup ABC_FREE( pPerm ); Vec_IntFree( vMapEntries ); Vec_IntFree( vFlopCosts ); Vec_IntFree( vFlopAddCosts ); Aig_ManCleanMarkB(pAig); // return the computed flops return vFfsToAddBest; } /**Function************************************************************* Synopsis [Duplicate with literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupWithCubes( Aig_Man_t * pAig, Vec_Vec_t * vReg2Value ) { Vec_Int_t * vLevel; Aig_Man_t * pAigNew; Aig_Obj_t * pObj, * pMiter; int i, k, Lit; assert( pAig->nConstrs == 0 ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) + Vec_VecSizeSize(vReg2Value) ); 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) ); // create POs for cubes Vec_VecForEachLevelInt( vReg2Value, vLevel, i ) { pMiter = Aig_ManConst1( pAigNew ); Vec_IntForEachEntry( vLevel, Lit, k ) { pObj = Saig_ManLi( pAig, Abc_Lit2Var(Lit) ); pMiter = Aig_And( pAigNew, pMiter, Aig_NotCond(Aig_ObjChild0Copy(pObj), Abc_LitIsCompl(Lit)) ); } Aig_ObjCreateCo( pAigNew, pMiter ); } // transfer to register outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // finalize Aig_ManCleanup( pAigNew ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); return pAigNew; } /**Function************************************************************* Synopsis [Maps array of frame PI IDs into array of additional PI IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManCbaReason2Inputs( Saig_ManCba_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 >= p->nInputs && iInput < Aig_ManCiNum(p->pAig) ); if ( Vec_IntEntry(vVisited, iInput) == 0 ) Vec_IntPush( vOriginal, iInput - p->nInputs ); Vec_IntAddToEntry( vVisited, iInput, 1 ); } Vec_IntFree( vVisited ); return vOriginal; } /**Function************************************************************* Synopsis [Creates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_ManCbaReason2Cex( Saig_ManCba_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 ); } /* for ( iFrame = 0; iFrame <= pCare->iFrame; iFrame++ ) { int Count = 0; for ( i = 0; i < pCare->nPis; i++ ) Count += Abc_InfoHasBit(pCare->pData, pCare->nRegs + pCare->nPis * iFrame + i); printf( "%d ", Count ); } printf( "\n" ); */ return pCare; } /**Function************************************************************* Synopsis [Returns reasons for the property to fail.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCbaFindReason_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_ObjIsConst1(pObj) ) return; if ( Aig_ObjIsCi(pObj) ) { Vec_IntPush( vReasons, Aig_ObjCioId(pObj) ); return; } assert( Aig_ObjIsNode(pObj) ); if ( pObj->fPhase ) { Saig_ManCbaFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); Saig_ManCbaFindReason_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_ManCbaFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); else if ( fPhase0 && !fPhase1 ) Saig_ManCbaFindReason_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_ManCbaFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); else Saig_ManCbaFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons ); } } } /**Function************************************************************* Synopsis [Returns reasons for the property to fail.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManCbaFindReason( Saig_ManCba_t * p ) { Aig_Obj_t * pObj; Vec_Int_t * vPrios, * vReasons; int i; // set PI values according to CEX vPrios = Vec_IntStartFull( Aig_ManObjNumMax(p->pFrames) ); 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 ); Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), i ); } // 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 ); pObj->fPhase = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase; assert( !pObj->fPhase ); // select the reason vReasons = Vec_IntAlloc( 100 ); Aig_ManIncrementTravId( p->pFrames ); Saig_ManCbaFindReason_rec( p->pFrames, Aig_ObjFanin0(pObj), vPrios, vReasons ); Vec_IntFree( vPrios ); // assert( !Aig_ObjIsTravIdCurrent(p->pFrames, Aig_ManConst1(p->pFrames)) ); return vReasons; } /**Function************************************************************* Synopsis [Collect nodes in the unrolled timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCbaUnrollCollect_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_ManCbaUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots ); else if ( Aig_ObjIsNode(pObj) ) { Saig_ManCbaUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots ); Saig_ManCbaUnrollCollect_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_ManCbaUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, Vec_Int_t ** pvMapPiF2A, Vec_Vec_t ** pvReg2Frame ) { 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_ManCbaUnrollCollect_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 if ( Saig_ManRegNum(pAig) == pCex->nRegs ) { Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, i) ); } else // this is the case when synthesis was applied, assume all-0 init state { Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), 1 ); } // 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; if ( *pvReg2Frame ) { Vec_VecPushInt( *pvReg2Frame, f, Aig_ObjId(pObj) ); // record LO Vec_VecPushInt( *pvReg2Frame, f, Aig_ObjToLit((Aig_Obj_t *)pObj->pData) ); // record its literal } } } // 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_ManCba_t * Saig_ManCbaStart( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose ) { Saig_ManCba_t * p; p = ABC_CALLOC( Saig_ManCba_t, 1 ); p->pAig = pAig; p->pCex = pCex; p->nInputs = nInputs; p->fVerbose = fVerbose; return p; } /**Function************************************************************* Synopsis [Destroys refinement manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCbaStop( Saig_ManCba_t * p ) { Vec_VecFreeP( &p->vReg2Frame ); Vec_VecFreeP( &p->vReg2Value ); Aig_ManStopP( &p->pFrames ); Vec_IntFreeP( &p->vMapPiF2A ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Destroys refinement manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCbaShrink( Saig_ManCba_t * p ) { Aig_Man_t * pManNew; Aig_Obj_t * pObjLi, * pObjFrame; Vec_Int_t * vLevel, * vLevel2; int f, k, ObjId, Lit; // assuming that important objects are labeled in Saig_ManCbaFindReason() Vec_VecForEachLevelInt( p->vReg2Frame, vLevel, f ) { Vec_IntForEachEntryDouble( vLevel, ObjId, Lit, k ) { pObjFrame = Aig_ManObj( p->pFrames, Abc_Lit2Var(Lit) ); if ( pObjFrame == NULL || (!Aig_ObjIsConst1(pObjFrame) && !Aig_ObjIsTravIdCurrent(p->pFrames, pObjFrame)) ) continue; pObjLi = Aig_ManObj( p->pAig, ObjId ); assert( Saig_ObjIsLi(p->pAig, pObjLi) ); Vec_VecPushInt( p->vReg2Value, f, Abc_Var2Lit( Aig_ObjCioId(pObjLi) - Saig_ManPoNum(p->pAig), Abc_LitIsCompl(Lit) ^ !pObjFrame->fPhase ) ); } } // print statistics Vec_VecForEachLevelInt( p->vReg2Frame, vLevel, k ) { vLevel2 = Vec_VecEntryInt( p->vReg2Value, k ); printf( "Level = %4d StateBits = %4d (%6.2f %%) CareBits = %4d (%6.2f %%)\n", k, Vec_IntSize(vLevel)/2, 100.0 * (Vec_IntSize(vLevel)/2) / Aig_ManRegNum(p->pAig), Vec_IntSize(vLevel2), 100.0 * Vec_IntSize(vLevel2) / Aig_ManRegNum(p->pAig) ); } // try reducing the frames pManNew = Saig_ManDupWithCubes( p->pAig, p->vReg2Value ); // Ioa_WriteAiger( pManNew, "aigcube.aig", 0, 0 ); Aig_ManStop( pManNew ); } static inline void Saig_ObjCexMinSet0( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; pObj->fMarkB = 0; } static inline void Saig_ObjCexMinSet1( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; pObj->fMarkB = 1; } static inline void Saig_ObjCexMinSetX( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; pObj->fMarkB = 1; } static inline int Saig_ObjCexMinGet0( Aig_Obj_t * pObj ) { return pObj->fMarkA && !pObj->fMarkB; } static inline int Saig_ObjCexMinGet1( Aig_Obj_t * pObj ) { return !pObj->fMarkA && pObj->fMarkB; } static inline int Saig_ObjCexMinGetX( Aig_Obj_t * pObj ) { return pObj->fMarkA && pObj->fMarkB; } static inline int Saig_ObjCexMinGet0Fanin0( Aig_Obj_t * pObj ) { return (Saig_ObjCexMinGet1(Aig_ObjFanin0(pObj)) && Aig_ObjFaninC0(pObj)) || (Saig_ObjCexMinGet0(Aig_ObjFanin0(pObj)) && !Aig_ObjFaninC0(pObj)); } static inline int Saig_ObjCexMinGet1Fanin0( Aig_Obj_t * pObj ) { return (Saig_ObjCexMinGet0(Aig_ObjFanin0(pObj)) && Aig_ObjFaninC0(pObj)) || (Saig_ObjCexMinGet1(Aig_ObjFanin0(pObj)) && !Aig_ObjFaninC0(pObj)); } static inline int Saig_ObjCexMinGet0Fanin1( Aig_Obj_t * pObj ) { return (Saig_ObjCexMinGet1(Aig_ObjFanin1(pObj)) && Aig_ObjFaninC1(pObj)) || (Saig_ObjCexMinGet0(Aig_ObjFanin1(pObj)) && !Aig_ObjFaninC1(pObj)); } static inline int Saig_ObjCexMinGet1Fanin1( Aig_Obj_t * pObj ) { return (Saig_ObjCexMinGet0(Aig_ObjFanin1(pObj)) && Aig_ObjFaninC1(pObj)) || (Saig_ObjCexMinGet1(Aig_ObjFanin1(pObj)) && !Aig_ObjFaninC1(pObj)); } static inline void Saig_ObjCexMinSim( Aig_Obj_t * pObj ) { if ( Aig_ObjIsAnd(pObj) ) { if ( Saig_ObjCexMinGet0Fanin0(pObj) || Saig_ObjCexMinGet0Fanin1(pObj) ) Saig_ObjCexMinSet0( pObj ); else if ( Saig_ObjCexMinGet1Fanin0(pObj) && Saig_ObjCexMinGet1Fanin1(pObj) ) Saig_ObjCexMinSet1( pObj ); else Saig_ObjCexMinSetX( pObj ); } else if ( Aig_ObjIsCo(pObj) ) { if ( Saig_ObjCexMinGet0Fanin0(pObj) ) Saig_ObjCexMinSet0( pObj ); else if ( Saig_ObjCexMinGet1Fanin0(pObj) ) Saig_ObjCexMinSet1( pObj ); else Saig_ObjCexMinSetX( pObj ); } else assert( 0 ); } static inline void Saig_ObjCexMinPrint( Aig_Obj_t * pObj ) { if ( Saig_ObjCexMinGet0(pObj) ) printf( "0" ); else if ( Saig_ObjCexMinGet1(pObj) ) printf( "1" ); else if ( Saig_ObjCexMinGetX(pObj) ) printf( "X" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManCexVerifyUsingTernary( Aig_Man_t * pAig, Abc_Cex_t * pCex, Abc_Cex_t * pCare ) { Aig_Obj_t * pObj, * pObjRi, * pObjRo; int i, f, iBit = 0; assert( pCex->iFrame == pCare->iFrame ); assert( pCex->nBits == pCare->nBits ); assert( pCex->iPo < Saig_ManPoNum(pAig) ); Saig_ObjCexMinSet1( Aig_ManConst1(pAig) ); // set flops to the init state Saig_ManForEachLo( pAig, pObj, i ) { assert( !Abc_InfoHasBit(pCex->pData, iBit) ); assert( !Abc_InfoHasBit(pCare->pData, iBit) ); // if ( Abc_InfoHasBit(pCare->pData, iBit++) ) Saig_ObjCexMinSet0( pObj ); // else // Saig_ObjCexMinSetX( pObj ); } iBit = pCex->nRegs; for ( f = 0; f <= pCex->iFrame; f++ ) { // init inputs Saig_ManForEachPi( pAig, pObj, i ) { if ( Abc_InfoHasBit(pCare->pData, iBit++) ) { if ( Abc_InfoHasBit(pCex->pData, iBit-1) ) Saig_ObjCexMinSet1( pObj ); else Saig_ObjCexMinSet0( pObj ); } else Saig_ObjCexMinSetX( pObj ); } // simulate internal nodes Aig_ManForEachNode( pAig, pObj, i ) Saig_ObjCexMinSim( pObj ); // simulate COs Aig_ManForEachCo( pAig, pObj, i ) Saig_ObjCexMinSim( pObj ); /* Aig_ManForEachObj( pAig, pObj, i ) { Aig_ObjPrint(pAig, pObj); printf( " Value = " ); Saig_ObjCexMinPrint( pObj ); printf( "\n" ); } */ // transfer Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, i ) pObjRo->fMarkA = pObjRi->fMarkA, pObjRo->fMarkB = pObjRi->fMarkB; } assert( iBit == pCex->nBits ); return Saig_ObjCexMinGet1( Aig_ManCo( pAig, pCex->iPo ) ); } /**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_ManCbaFindCexCareBits( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose ) { Saig_ManCba_t * p; Vec_Int_t * vReasons; Abc_Cex_t * pCare; abctime clk = Abc_Clock(); clk = Abc_Clock(); p = Saig_ManCbaStart( pAig, pCex, nInputs, fVerbose ); // p->vReg2Frame = Vec_VecStart( pCex->iFrame ); // p->vReg2Value = Vec_VecStart( pCex->iFrame ); p->pFrames = Saig_ManCbaUnrollWithCex( pAig, pCex, nInputs, &p->vMapPiF2A, &p->vReg2Frame ); vReasons = Saig_ManCbaFindReason( p ); if ( p->vReg2Frame ) Saig_ManCbaShrink( p ); //if ( fVerbose ) //Aig_ManPrintStats( p->pFrames ); if ( fVerbose ) { Vec_Int_t * vRes = Saig_ManCbaReason2Inputs( 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", Abc_Clock() - clk ); } pCare = Saig_ManCbaReason2Cex( p, vReasons ); Vec_IntFree( vReasons ); Saig_ManCbaStop( p ); if ( fVerbose ) { printf( "Real " ); Abc_CexPrintStats( pCex ); } if ( fVerbose ) { printf( "Care " ); Abc_CexPrintStats( pCare ); } /* // verify the reduced counter-example using ternary simulation if ( !Saig_ManCexVerifyUsingTernary( pAig, pCex, pCare ) ) printf( "Saig_ManCbaFindCexCareBits(): Minimized counter-example verification has failed!!!\n" ); else if ( fVerbose ) printf( "Saig_ManCbaFindCexCareBits(): Minimized counter-example verification is successful.\n" ); */ Aig_ManCleanMarkAB( pAig ); return pCare; } /**Function************************************************************* Synopsis [Returns the array of PIs for flops that should not be absracted.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManCbaFilterInputs( Aig_Man_t * pAig, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose ) { Saig_ManCba_t * p; Vec_Int_t * vRes, * vReasons; abctime clk; if ( Saig_ManPiNum(pAig) != pCex->nPis ) { printf( "Saig_ManCbaFilterInputs(): The PI count of AIG (%d) does not match that of cex (%d).\n", Aig_ManCiNum(pAig), pCex->nPis ); return NULL; } clk = Abc_Clock(); p = Saig_ManCbaStart( pAig, pCex, iFirstFlopPi, fVerbose ); p->pFrames = Saig_ManCbaUnrollWithCex( pAig, pCex, iFirstFlopPi, &p->vMapPiF2A, &p->vReg2Frame ); vReasons = Saig_ManCbaFindReason( p ); vRes = Saig_ManCbaReason2Inputs( 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", Abc_Clock() - clk ); } Vec_IntFree( vReasons ); Saig_ManCbaStop( p ); return vRes; } /**Function************************************************************* Synopsis [Checks the abstracted model for a counter-example.] Description [Returns the array of abstracted flops that should be added to the abstraction.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManCbaPerform( Aig_Man_t * pAbs, int nInputs, Saig_ParBmc_t * pPars ) { Vec_Int_t * vAbsFfsToAdd; int RetValue; abctime clk = Abc_Clock(); // assert( pAbs->nRegs > 0 ); // perform BMC RetValue = Saig_ManBmcScalable( pAbs, pPars ); if ( RetValue == -1 ) // time out - nothing to add { printf( "Resource limit is reached during BMC.\n" ); assert( pAbs->pSeqModel == NULL ); return Vec_IntAlloc( 0 ); } if ( pAbs->pSeqModel == NULL ) { printf( "BMC did not detect a CEX with the given depth.\n" ); return Vec_IntAlloc( 0 ); } if ( pPars->fVerbose ) Abc_CexPrintStats( pAbs->pSeqModel ); // CEX is detected - refine the flops vAbsFfsToAdd = Saig_ManCbaFilterInputs( pAbs, nInputs, pAbs->pSeqModel, pPars->fVerbose ); if ( Vec_IntSize(vAbsFfsToAdd) == 0 ) { Vec_IntFree( vAbsFfsToAdd ); return NULL; } if ( pPars->fVerbose ) { printf( "Adding %d registers to the abstraction (total = %d). ", Vec_IntSize(vAbsFfsToAdd), Aig_ManRegNum(pAbs)+Vec_IntSize(vAbsFfsToAdd) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return vAbsFfsToAdd; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absOldRef.c000066400000000000000000000404351300674244400237410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigAbsStart.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Counter-example-based abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigAbsStart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" #include "proof/ssw/ssw.h" #include "proof/fra/fra.h" #include "bdd/bbr/bbr.h" #include "proof/pdr/pdr.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAbsSetDefaultParams( Gia_ParAbs_t * p ) { memset( p, 0, sizeof(Gia_ParAbs_t) ); p->Algo = 0; // algorithm: CBA p->nFramesMax = 10; // timeframes for PBA p->nConfMax = 10000; // conflicts for PBA p->fDynamic = 1; // dynamic unfolding for PBA p->fConstr = 0; // use constraints p->nFramesBmc = 250; // timeframes for BMC p->nConfMaxBmc = 5000; // conflicts for BMC p->nStableMax = 1000000; // the number of stable frames to quit p->nRatio = 10; // ratio of flops to quit p->nBobPar = 1000000; // the number of frames before trying to quit p->fUseBdds = 0; // use BDDs to refine abstraction p->fUseDprove = 0; // use 'dprove' to refine abstraction p->fUseStart = 1; // use starting frame p->fVerbose = 0; // verbose output p->fVeryVerbose= 0; // printing additional information p->Status = -1; // the problem status p->nFramesDone = -1; // the number of rames covered } /**Function************************************************************* Synopsis [Derive a new counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_ManCexRemap( Aig_Man_t * p, Aig_Man_t * pAbs, Abc_Cex_t * pCexAbs ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; int i, f; if ( !Saig_ManVerifyCex( pAbs, pCexAbs ) ) printf( "Saig_ManCexRemap(): The initial counter-example is invalid.\n" ); // else // printf( "Saig_ManCexRemap(): The initial counter-example is correct.\n" ); // start the counter-example pCex = Abc_CexAlloc( Aig_ManRegNum(p), Saig_ManPiNum(p), pCexAbs->iFrame+1 ); pCex->iFrame = pCexAbs->iFrame; pCex->iPo = pCexAbs->iPo; // copy the bit data for ( f = 0; f <= pCexAbs->iFrame; f++ ) { Saig_ManForEachPi( pAbs, pObj, i ) { if ( i == Saig_ManPiNum(p) ) break; if ( Abc_InfoHasBit( pCexAbs->pData, pCexAbs->nRegs + pCexAbs->nPis * f + i ) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * f + i ); } } // verify the counter example if ( !Saig_ManVerifyCex( p, pCex ) ) { printf( "Saig_ManCexRemap(): Counter-example is invalid.\n" ); Abc_CexFree( pCex ); pCex = NULL; } else { Abc_Print( 1, "Counter-example verification is successful.\n" ); Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. \n", pCex->iPo, p->pName, pCex->iFrame ); } return pCex; } /**Function************************************************************* Synopsis [Find the first PI corresponding to the flop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManCexFirstFlopPi( Aig_Man_t * p, Aig_Man_t * pAbs ) { Aig_Obj_t * pObj; int i; assert( pAbs->vCiNumsOrig != NULL ); Aig_ManForEachCi( p, pObj, i ) { if ( Vec_IntEntry(pAbs->vCiNumsOrig, i) >= Saig_ManPiNum(p) ) return i; } return -1; } /**Function************************************************************* Synopsis [Refines abstraction using one step.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManCexRefine( Aig_Man_t * p, Aig_Man_t * pAbs, Vec_Int_t * vFlops, int nFrames, int nConfMaxOne, int fUseBdds, int fUseDprove, int fVerbose, int * pnUseStart, int * piRetValue, int * pnFrames ) { Vec_Int_t * vFlopsNew; int i, Entry, RetValue; *piRetValue = -1; if ( fUseDprove && Aig_ManRegNum(pAbs) > 0 ) { /* Fra_Sec_t SecPar, * pSecPar = &SecPar; Fra_SecSetDefaultParams( pSecPar ); pSecPar->fVerbose = fVerbose; RetValue = Fra_FraigSec( pAbs, pSecPar, NULL ); */ Aig_Man_t * pAbsOrpos = Saig_ManDupOrpos( pAbs ); Pdr_Par_t Pars, * pPars = &Pars; Pdr_ManSetDefaultParams( pPars ); pPars->nTimeOut = 10; pPars->fVerbose = fVerbose; if ( pPars->fVerbose ) printf( "Running property directed reachability...\n" ); RetValue = Pdr_ManSolve( pAbsOrpos, pPars ); if ( pAbsOrpos->pSeqModel ) pAbsOrpos->pSeqModel->iPo = Saig_ManFindFailedPoCex( pAbs, pAbsOrpos->pSeqModel ); pAbs->pSeqModel = pAbsOrpos->pSeqModel; pAbsOrpos->pSeqModel = NULL; Aig_ManStop( pAbsOrpos ); if ( RetValue ) *piRetValue = 1; } else if ( fUseBdds && (Aig_ManRegNum(pAbs) > 0 && Aig_ManRegNum(pAbs) <= 80) ) { Saig_ParBbr_t Pars, * pPars = &Pars; Bbr_ManSetDefaultParams( pPars ); pPars->TimeLimit = 0; pPars->nBddMax = 1000000; pPars->nIterMax = nFrames; pPars->fPartition = 1; pPars->fReorder = 1; pPars->fReorderImage = 1; pPars->fVerbose = fVerbose; pPars->fSilent = 0; RetValue = Aig_ManVerifyUsingBdds( pAbs, pPars ); if ( RetValue ) *piRetValue = 1; } else { Saig_BmcPerform( pAbs, pnUseStart? *pnUseStart: 0, nFrames, 2000, 0, nConfMaxOne, 0, fVerbose, 0, pnFrames, 0 ); } if ( pAbs->pSeqModel == NULL ) return NULL; if ( pnUseStart ) *pnUseStart = pAbs->pSeqModel->iFrame; // vFlopsNew = Saig_ManExtendCounterExampleTest( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pAbs->pSeqModel, 1, fVerbose ); vFlopsNew = Saig_ManExtendCounterExampleTest3( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pAbs->pSeqModel, fVerbose ); if ( vFlopsNew == NULL ) return NULL; if ( Vec_IntSize(vFlopsNew) == 0 ) { printf( "Discovered a true counter-example!\n" ); p->pSeqModel = Saig_ManCexRemap( p, pAbs, pAbs->pSeqModel ); Vec_IntFree( vFlopsNew ); *piRetValue = 0; return NULL; } // vFlopsNew contains PI numbers that should be kept in pAbs if ( fVerbose ) printf( "Adding %d registers to the abstraction (total = %d).\n\n", Vec_IntSize(vFlopsNew), Aig_ManRegNum(pAbs)+Vec_IntSize(vFlopsNew) ); // add to the abstraction Vec_IntForEachEntry( vFlopsNew, Entry, i ) { Entry = Vec_IntEntry(pAbs->vCiNumsOrig, Entry); assert( Entry >= Saig_ManPiNum(p) ); assert( Entry < Aig_ManCiNum(p) ); Vec_IntPush( vFlops, Entry-Saig_ManPiNum(p) ); } Vec_IntFree( vFlopsNew ); Vec_IntSort( vFlops, 0 ); Vec_IntForEachEntryStart( vFlops, Entry, i, 1 ) assert( Vec_IntEntry(vFlops, i-1) != Entry ); return Saig_ManDupAbstraction( p, vFlops ); } /**Function************************************************************* Synopsis [Refines abstraction using one step.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManCexRefineStep( Aig_Man_t * p, Vec_Int_t * vFlops, Vec_Int_t * vFlopClasses, Abc_Cex_t * pCex, int nFfToAddMax, int fTryFour, int fSensePath, int fVerbose ) { Aig_Man_t * pAbs; Vec_Int_t * vFlopsNew; int i, Entry; abctime clk = Abc_Clock(); pAbs = Saig_ManDupAbstraction( p, vFlops ); if ( fSensePath ) vFlopsNew = Saig_ManExtendCounterExampleTest2( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pCex, fVerbose ); else // vFlopsNew = Saig_ManExtendCounterExampleTest( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pCex, fTryFour, fVerbose ); vFlopsNew = Saig_ManExtendCounterExampleTest3( pAbs, Saig_ManCexFirstFlopPi(p, pAbs), pCex, fVerbose ); if ( vFlopsNew == NULL ) { Aig_ManStop( pAbs ); return 0; } if ( Vec_IntSize(vFlopsNew) == 0 ) { printf( "Refinement did not happen. Discovered a true counter-example.\n" ); printf( "Remapping counter-example from %d to %d primary inputs.\n", Aig_ManCiNum(pAbs), Aig_ManCiNum(p) ); p->pSeqModel = Saig_ManCexRemap( p, pAbs, pCex ); Vec_IntFree( vFlopsNew ); Aig_ManStop( pAbs ); return 0; } if ( fVerbose ) { printf( "Adding %d registers to the abstraction (total = %d). ", Vec_IntSize(vFlopsNew), Aig_ManRegNum(p)+Vec_IntSize(vFlopsNew) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } // vFlopsNew contains PI numbers that should be kept in pAbs // select the most useful flops among those to be added if ( nFfToAddMax > 0 && Vec_IntSize(vFlopsNew) > nFfToAddMax ) { Vec_Int_t * vFlopsNewBest; // shift the indices Vec_IntForEachEntry( vFlopsNew, Entry, i ) Vec_IntAddToEntry( vFlopsNew, i, -Saig_ManPiNum(p) ); // create new flops vFlopsNewBest = Saig_ManCbaFilterFlops( p, pCex, vFlopClasses, vFlopsNew, nFfToAddMax ); assert( Vec_IntSize(vFlopsNewBest) == nFfToAddMax ); printf( "Filtering flops based on cost (%d -> %d).\n", Vec_IntSize(vFlopsNew), Vec_IntSize(vFlopsNewBest) ); // update Vec_IntFree( vFlopsNew ); vFlopsNew = vFlopsNewBest; // shift the indices Vec_IntForEachEntry( vFlopsNew, Entry, i ) Vec_IntAddToEntry( vFlopsNew, i, Saig_ManPiNum(p) ); } // add to the abstraction Vec_IntForEachEntry( vFlopsNew, Entry, i ) { Entry = Vec_IntEntry(pAbs->vCiNumsOrig, Entry); assert( Entry >= Saig_ManPiNum(p) ); assert( Entry < Aig_ManCiNum(p) ); Vec_IntPush( vFlops, Entry-Saig_ManPiNum(p) ); } Vec_IntFree( vFlopsNew ); Aig_ManStop( pAbs ); return 1; } /**Function************************************************************* Synopsis [Transform flop map into flop list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManClasses2Flops( Vec_Int_t * vFlopClasses ) { Vec_Int_t * vFlops; int i, Entry; vFlops = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vFlopClasses, Entry, i ) if ( Entry ) Vec_IntPush( vFlops, i ); return vFlops; } /**Function************************************************************* Synopsis [Transform flop list into flop map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManFlops2Classes( Gia_Man_t * pGia, Vec_Int_t * vFlops ) { Vec_Int_t * vFlopClasses; int i, Entry; vFlopClasses = Vec_IntStart( Gia_ManRegNum(pGia) ); Vec_IntForEachEntry( vFlops, Entry, i ) Vec_IntWriteEntry( vFlopClasses, Entry, 1 ); return vFlopClasses; } /**Function************************************************************* Synopsis [Refines abstraction using the latch map.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCexAbstractionRefine( Gia_Man_t * pGia, Abc_Cex_t * pCex, int nFfToAddMax, int fTryFour, int fSensePath, int fVerbose ) { Aig_Man_t * pNew; Vec_Int_t * vFlops; if ( pGia->vFlopClasses == NULL ) { printf( "Gia_ManCexAbstractionRefine(): Abstraction latch map is missing.\n" ); return -1; } pNew = Gia_ManToAig( pGia, 0 ); vFlops = Gia_ManClasses2Flops( pGia->vFlopClasses ); if ( !Saig_ManCexRefineStep( pNew, vFlops, pGia->vFlopClasses, pCex, nFfToAddMax, fTryFour, fSensePath, fVerbose ) ) { pGia->pCexSeq = pNew->pSeqModel; pNew->pSeqModel = NULL; Vec_IntFree( vFlops ); Aig_ManStop( pNew ); return 0; } Vec_IntFree( pGia->vFlopClasses ); pGia->vFlopClasses = Gia_ManFlops2Classes( pGia, vFlops ); Vec_IntFree( vFlops ); Aig_ManStop( pNew ); return -1; } /**Function************************************************************* Synopsis [Computes the flops to remain after abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManCexAbstractionFlops( Aig_Man_t * p, Gia_ParAbs_t * pPars ) { int nUseStart = 0; Aig_Man_t * pAbs, * pTemp; Vec_Int_t * vFlops; int Iter;//, clk = Abc_Clock(), clk2 = Abc_Clock();//, iFlop; assert( Aig_ManRegNum(p) > 0 ); if ( pPars->fVerbose ) printf( "Performing counter-example-based refinement.\n" ); Aig_ManSetCioIds( p ); vFlops = Vec_IntStartNatural( 1 ); /* iFlop = Saig_ManFindFirstFlop( p ); assert( iFlop >= 0 ); vFlops = Vec_IntAlloc( 1 ); Vec_IntPush( vFlops, iFlop ); */ // create the resulting AIG pAbs = Saig_ManDupAbstraction( p, vFlops ); if ( !pPars->fVerbose ) { printf( "Init : " ); Aig_ManPrintStats( pAbs ); } printf( "Refining abstraction...\n" ); for ( Iter = 0; ; Iter++ ) { pTemp = Saig_ManCexRefine( p, pAbs, vFlops, pPars->nFramesBmc, pPars->nConfMaxBmc, pPars->fUseBdds, pPars->fUseDprove, pPars->fVerbose, pPars->fUseStart?&nUseStart:NULL, &pPars->Status, &pPars->nFramesDone ); if ( pTemp == NULL ) { ABC_FREE( p->pSeqModel ); p->pSeqModel = pAbs->pSeqModel; pAbs->pSeqModel = NULL; Aig_ManStop( pAbs ); break; } Aig_ManStop( pAbs ); pAbs = pTemp; printf( "ITER %4d : ", Iter ); if ( !pPars->fVerbose ) Aig_ManPrintStats( pAbs ); // output the intermediate result of abstraction Ioa_WriteAiger( pAbs, "gabs.aig", 0, 0 ); // printf( "Intermediate abstracted model was written into file \"%s\".\n", "gabs.aig" ); // check if the ratio is reached if ( 100.0*(Aig_ManRegNum(p)-Aig_ManRegNum(pAbs))/Aig_ManRegNum(p) < 1.0*pPars->nRatio ) { printf( "Refinements is stopped because flop reduction is less than %d%%\n", pPars->nRatio ); Aig_ManStop( pAbs ); pAbs = NULL; Vec_IntFree( vFlops ); vFlops = NULL; break; } } return vFlops; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absOldSat.c000066400000000000000000001043601300674244400237520ustar00rootroot00000000000000/**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 "abs.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; abctime clk = Abc_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", Abc_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 = Abc_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", Abc_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; abctime clk = Abc_Clock(); clk = Abc_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", Abc_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", Abc_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; abctime 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 = Abc_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", Abc_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", Abc_Clock() - clk ); } */ Vec_IntFree( vReasons ); Saig_RefManStop( p ); return vRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absOldSim.c000066400000000000000000000406441300674244400237570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigSimExt2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Extending simulation trace to contain ternary values.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigSimExt2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define SAIG_ZER 1 #define SAIG_ONE 2 #define SAIG_UND 3 static inline int Saig_ManSimInfoNot( int Value ) { if ( Value == SAIG_ZER ) return SAIG_ONE; if ( Value == SAIG_ONE ) return SAIG_ZER; return SAIG_UND; } static inline int Saig_ManSimInfoAnd( int Value0, int Value1 ) { if ( Value0 == SAIG_ZER || Value1 == SAIG_ZER ) return SAIG_ZER; if ( Value0 == SAIG_ONE && Value1 == SAIG_ONE ) return SAIG_ONE; return SAIG_UND; } static inline int Saig_ManSimInfoGet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame ) { unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) ); return 3 & (pInfo[iFrame >> 4] >> ((iFrame & 15) << 1)); } static inline void Saig_ManSimInfoSet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value ) { unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) ); assert( Value >= SAIG_ZER && Value <= SAIG_UND ); Value ^= Saig_ManSimInfoGet( vSimInfo, pObj, iFrame ); pInfo[iFrame >> 4] ^= (Value << ((iFrame & 15) << 1)); } #define SAIG_ZER_NEW 0 // 0 not visited #define SAIG_ONE_NEW 1 // 1 not visited #define SAIG_ZER_OLD 2 // 0 visited #define SAIG_ONE_OLD 3 // 1 visited static inline int Saig_ManSimInfo2IsOld( int Value ) { return Value == SAIG_ZER_OLD || Value == SAIG_ONE_OLD; } static inline int Saig_ManSimInfo2SetOld( int Value ) { if ( Value == SAIG_ZER_NEW ) return SAIG_ZER_OLD; if ( Value == SAIG_ONE_NEW ) return SAIG_ONE_OLD; assert( 0 ); return 0; } static inline int Saig_ManSimInfo2Not( int Value ) { if ( Value == SAIG_ZER_NEW ) return SAIG_ONE_NEW; if ( Value == SAIG_ONE_NEW ) return SAIG_ZER_NEW; if ( Value == SAIG_ZER_OLD ) return SAIG_ONE_OLD; if ( Value == SAIG_ONE_OLD ) return SAIG_ZER_OLD; assert( 0 ); return 0; } static inline int Saig_ManSimInfo2And( int Value0, int Value1 ) { if ( Value0 == SAIG_ZER_NEW || Value1 == SAIG_ZER_NEW ) return SAIG_ZER_NEW; if ( Value0 == SAIG_ONE_NEW && Value1 == SAIG_ONE_NEW ) return SAIG_ONE_NEW; assert( 0 ); return 0; } static inline int Saig_ManSimInfo2Get( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame ) { unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) ); return 3 & (pInfo[iFrame >> 4] >> ((iFrame & 15) << 1)); } static inline void Saig_ManSimInfo2Set( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value ) { unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjId(pObj) ); Value ^= Saig_ManSimInfo2Get( vSimInfo, pObj, iFrame ); pInfo[iFrame >> 4] ^= (Value << ((iFrame & 15) << 1)); } // 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 [Performs ternary simulation for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManExtendOneEval( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame ) { int Value0, Value1, Value; Value0 = Saig_ManSimInfoGet( vSimInfo, Aig_ObjFanin0(pObj), iFrame ); if ( Aig_ObjFaninC0(pObj) ) Value0 = Saig_ManSimInfoNot( Value0 ); if ( Aig_ObjIsCo(pObj) ) { Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value0 ); return Value0; } assert( Aig_ObjIsNode(pObj) ); Value1 = Saig_ManSimInfoGet( vSimInfo, Aig_ObjFanin1(pObj), iFrame ); if ( Aig_ObjFaninC1(pObj) ) Value1 = Saig_ManSimInfoNot( Value1 ); Value = Saig_ManSimInfoAnd( Value0, Value1 ); Saig_ManSimInfoSet( vSimInfo, pObj, iFrame, Value ); return Value; } /**Function************************************************************* Synopsis [Performs ternary simulation for one design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManSimDataInit( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes ) { Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f, Entry, iBit = 0; Saig_ManForEachLo( p, pObj, i ) Saig_ManSimInfoSet( vSimInfo, pObj, 0, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER ); for ( f = 0; f <= pCex->iFrame; f++ ) { Saig_ManSimInfoSet( vSimInfo, Aig_ManConst1(p), f, SAIG_ONE ); Saig_ManForEachPi( p, pObj, i ) Saig_ManSimInfoSet( vSimInfo, pObj, f, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE:SAIG_ZER ); if ( vRes ) Vec_IntForEachEntry( vRes, Entry, i ) Saig_ManSimInfoSet( vSimInfo, Aig_ManCi(p, Entry), f, SAIG_UND ); Aig_ManForEachNode( p, pObj, i ) Saig_ManExtendOneEval( vSimInfo, pObj, f ); Aig_ManForEachCo( p, pObj, i ) Saig_ManExtendOneEval( vSimInfo, pObj, f ); if ( f == pCex->iFrame ) break; Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) Saig_ManSimInfoSet( vSimInfo, pObjLo, f+1, Saig_ManSimInfoGet(vSimInfo, pObjLi, f) ); } // make sure the output of the property failed pObj = Aig_ManCo( p, pCex->iPo ); return Saig_ManSimInfoGet( vSimInfo, pObj, pCex->iFrame ); } /**Function************************************************************* Synopsis [Performs ternary simulation for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManExtendOneEval2( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame ) { int Value0, Value1, Value; Value0 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin0(pObj), iFrame ); if ( Aig_ObjFaninC0(pObj) ) Value0 = Saig_ManSimInfo2Not( Value0 ); if ( Aig_ObjIsCo(pObj) ) { Saig_ManSimInfo2Set( vSimInfo, pObj, iFrame, Value0 ); return Value0; } assert( Aig_ObjIsNode(pObj) ); Value1 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin1(pObj), iFrame ); if ( Aig_ObjFaninC1(pObj) ) Value1 = Saig_ManSimInfo2Not( Value1 ); Value = Saig_ManSimInfo2And( Value0, Value1 ); Saig_ManSimInfo2Set( vSimInfo, pObj, iFrame, Value ); return Value; } /**Function************************************************************* Synopsis [Performs sensitization analysis for one design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManSimDataInit2( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo ) { Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f, iBit = 0; Saig_ManForEachLo( p, pObj, i ) Saig_ManSimInfo2Set( vSimInfo, pObj, 0, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE_NEW:SAIG_ZER_NEW ); for ( f = 0; f <= pCex->iFrame; f++ ) { Saig_ManSimInfo2Set( vSimInfo, Aig_ManConst1(p), f, SAIG_ONE_NEW ); Saig_ManForEachPi( p, pObj, i ) Saig_ManSimInfo2Set( vSimInfo, pObj, f, Abc_InfoHasBit(pCex->pData, iBit++)?SAIG_ONE_NEW:SAIG_ZER_NEW ); Aig_ManForEachNode( p, pObj, i ) Saig_ManExtendOneEval2( vSimInfo, pObj, f ); Aig_ManForEachCo( p, pObj, i ) Saig_ManExtendOneEval2( vSimInfo, pObj, f ); if ( f == pCex->iFrame ) break; Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) Saig_ManSimInfo2Set( vSimInfo, pObjLo, f+1, Saig_ManSimInfo2Get(vSimInfo, pObjLi, f) ); } // make sure the output of the property failed pObj = Aig_ManCo( p, pCex->iPo ); return Saig_ManSimInfo2Get( vSimInfo, pObj, pCex->iFrame ); } /**Function************************************************************* Synopsis [Drive implications of the given node towards primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManSetAndDriveImplications_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int f, int fMax, Vec_Ptr_t * vSimInfo ) { Aig_Obj_t * pFanout; int k, iFanout = -1, Value0, Value1; int Value = Saig_ManSimInfo2Get( vSimInfo, pObj, f ); assert( !Saig_ManSimInfo2IsOld( Value ) ); Saig_ManSimInfo2Set( vSimInfo, pObj, f, Saig_ManSimInfo2SetOld(Value) ); if ( (Aig_ObjIsCo(pObj) && f == fMax) || Saig_ObjIsPo(p, pObj) ) return; if ( Saig_ObjIsLi( p, pObj ) ) { assert( f < fMax ); pFanout = Saig_ObjLiToLo(p, pObj); Value = Saig_ManSimInfo2Get( vSimInfo, pFanout, f+1 ); if ( !Saig_ManSimInfo2IsOld( Value ) ) Saig_ManSetAndDriveImplications_rec( p, pFanout, f+1, fMax, vSimInfo ); return; } assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ); Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) { Value = Saig_ManSimInfo2Get( vSimInfo, pFanout, f ); if ( Saig_ManSimInfo2IsOld( Value ) ) continue; if ( Aig_ObjIsCo(pFanout) ) { Saig_ManSetAndDriveImplications_rec( p, pFanout, f, fMax, vSimInfo ); continue; } assert( Aig_ObjIsNode(pFanout) ); Value0 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin0(pFanout), f ); Value1 = Saig_ManSimInfo2Get( vSimInfo, Aig_ObjFanin1(pFanout), f ); if ( Aig_ObjFaninC0(pFanout) ) Value0 = Saig_ManSimInfo2Not( Value0 ); if ( Aig_ObjFaninC1(pFanout) ) Value1 = Saig_ManSimInfo2Not( Value1 ); if ( Value0 == SAIG_ZER_OLD || Value1 == SAIG_ZER_OLD || (Value0 == SAIG_ONE_OLD && Value1 == SAIG_ONE_OLD) ) Saig_ManSetAndDriveImplications_rec( p, pFanout, f, fMax, vSimInfo ); } } /**Function************************************************************* Synopsis [Performs recursive sensetization analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManExplorePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int f, int fMax, Vec_Ptr_t * vSimInfo ) { int Value = Saig_ManSimInfo2Get( vSimInfo, pObj, f ); if ( Saig_ManSimInfo2IsOld( Value ) ) return; Saig_ManSetAndDriveImplications_rec( p, pObj, f, fMax, vSimInfo ); assert( !Aig_ObjIsConst1(pObj) ); if ( Saig_ObjIsLo(p, pObj) && f == 0 ) return; if ( Saig_ObjIsPi(p, pObj) ) { // propagate implications of this assignment int i, iPiNum = Aig_ObjCioId(pObj); for ( i = fMax; i >= 0; i-- ) if ( i != f ) Saig_ManSetAndDriveImplications_rec( p, Aig_ManCi(p, iPiNum), i, fMax, vSimInfo ); return; } if ( Saig_ObjIsLo( p, pObj ) ) { assert( f > 0 ); Saig_ManExplorePaths_rec( p, Saig_ObjLoToLi(p, pObj), f-1, fMax, vSimInfo ); return; } if ( Aig_ObjIsCo(pObj) ) { Saig_ManExplorePaths_rec( p, Aig_ObjFanin0(pObj), f, fMax, vSimInfo ); return; } assert( Aig_ObjIsNode(pObj) ); if ( Value == SAIG_ZER_OLD ) { // if ( (Aig_ObjId(pObj) & 1) == 0 ) Saig_ManExplorePaths_rec( p, Aig_ObjFanin0(pObj), f, fMax, vSimInfo ); // else // Saig_ManExplorePaths_rec( p, Aig_ObjFanin1(pObj), f, fMax, vSimInfo ); } else { Saig_ManExplorePaths_rec( p, Aig_ObjFanin0(pObj), f, fMax, vSimInfo ); Saig_ManExplorePaths_rec( p, Aig_ObjFanin1(pObj), f, fMax, vSimInfo ); } } /**Function************************************************************* Synopsis [Returns the array of PIs for flops that should not be absracted.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManProcessCex( Aig_Man_t * p, int iFirstFlopPi, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, int fVerbose ) { Aig_Obj_t * pObj; Vec_Int_t * vRes, * vResInv; int i, f, Value; // assert( Aig_ManRegNum(p) > 0 ); assert( (unsigned *)Vec_PtrEntry(vSimInfo,1) - (unsigned *)Vec_PtrEntry(vSimInfo,0) >= Abc_BitWordNum(2*(pCex->iFrame+1)) ); // start simulation data Value = Saig_ManSimDataInit2( p, pCex, vSimInfo ); assert( Value == SAIG_ONE_NEW ); // derive implications of constants and primary inputs Saig_ManForEachLo( p, pObj, i ) Saig_ManSetAndDriveImplications_rec( p, pObj, 0, pCex->iFrame, vSimInfo ); for ( f = pCex->iFrame; f >= 0; f-- ) { Saig_ManSetAndDriveImplications_rec( p, Aig_ManConst1(p), f, pCex->iFrame, vSimInfo ); for ( i = 0; i < iFirstFlopPi; i++ ) Saig_ManSetAndDriveImplications_rec( p, Aig_ManCi(p, i), f, pCex->iFrame, vSimInfo ); } // recursively compute justification Saig_ManExplorePaths_rec( p, Aig_ManCo(p, pCex->iPo), pCex->iFrame, pCex->iFrame, vSimInfo ); // select the result vRes = Vec_IntAlloc( 1000 ); vResInv = Vec_IntAlloc( 1000 ); for ( i = iFirstFlopPi; i < Saig_ManPiNum(p); i++ ) { for ( f = pCex->iFrame; f >= 0; f-- ) { Value = Saig_ManSimInfo2Get( vSimInfo, Aig_ManCi(p, i), f ); if ( Saig_ManSimInfo2IsOld( Value ) ) break; } if ( f >= 0 ) Vec_IntPush( vRes, i ); else Vec_IntPush( vResInv, i ); } // resimulate to make sure it is valid Value = Saig_ManSimDataInit( p, pCex, vSimInfo, vResInv ); assert( Value == SAIG_ONE ); Vec_IntFree( vResInv ); return vRes; } /**Function************************************************************* Synopsis [Returns the array of PIs for flops that should not be absracted.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManExtendCounterExampleTest2( Aig_Man_t * p, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose ) { Vec_Int_t * vRes; Vec_Ptr_t * vSimInfo; abctime clk; if ( Saig_ManPiNum(p) != pCex->nPis ) { printf( "Saig_ManExtendCounterExampleTest2(): The PI count of AIG (%d) does not match that of cex (%d).\n", Aig_ManCiNum(p), pCex->nPis ); return NULL; } Aig_ManFanoutStart( p ); vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), Abc_BitWordNum(2*(pCex->iFrame+1)) ); Vec_PtrCleanSimInfo( vSimInfo, 0, Abc_BitWordNum(2*(pCex->iFrame+1)) ); clk = Abc_Clock(); vRes = Saig_ManProcessCex( p, iFirstFlopPi, pCex, vSimInfo, fVerbose ); if ( fVerbose ) { printf( "Total new PIs = %3d. Non-removable PIs = %3d. ", Saig_ManPiNum(p)-iFirstFlopPi, Vec_IntSize(vRes) ); ABC_PRT( "Time", Abc_Clock() - clk ); } Vec_PtrFree( vSimInfo ); Aig_ManFanoutStop( p ); return vRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absOut.c000066400000000000000000000374421300674244400233410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absOut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Abstraction refinement outside of abstraction engines.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absOut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derive a new counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gia_ManCexRemap( Gia_Man_t * p, Abc_Cex_t * pCexAbs, Vec_Int_t * vPis ) { Abc_Cex_t * pCex; int i, f, iPiNum; assert( pCexAbs->iPo == 0 ); // start the counter-example pCex = Abc_CexAlloc( Gia_ManRegNum(p), Gia_ManPiNum(p), pCexAbs->iFrame+1 ); pCex->iFrame = pCexAbs->iFrame; pCex->iPo = pCexAbs->iPo; // copy the bit data for ( f = 0; f <= pCexAbs->iFrame; f++ ) for ( i = 0; i < Vec_IntSize(vPis); i++ ) { if ( Abc_InfoHasBit( pCexAbs->pData, pCexAbs->nRegs + pCexAbs->nPis * f + i ) ) { iPiNum = Gia_ObjCioId( Gia_ManObj(p, Vec_IntEntry(vPis, i)) ); Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * f + iPiNum ); } } // verify the counter example if ( !Gia_ManVerifyCex( p, pCex, 0 ) ) { Abc_Print( 1, "Gia_ManCexRemap(): Counter-example is invalid.\n" ); Abc_CexFree( pCex ); pCex = NULL; } else { Abc_Print( 1, "Counter-example verification is successful.\n" ); Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. \n", pCex->iPo, p->pName, pCex->iFrame ); } return pCex; } /**Function************************************************************* Synopsis [Refines gate-level abstraction using the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManGlaRefine( Gia_Man_t * p, Abc_Cex_t * pCex, int fMinCut, int fVerbose ) { extern void Nwk_ManDeriveMinCut( Gia_Man_t * p, int fVerbose ); int fAddOneLayer = 1; Abc_Cex_t * pCexNew = NULL; Gia_Man_t * pAbs; Aig_Man_t * pAig; Abc_Cex_t * pCare; Vec_Int_t * vPis, * vPPis; int f, i, iObjId; abctime clk = Abc_Clock(); int nOnes = 0, Counter = 0; if ( p->vGateClasses == NULL ) { Abc_Print( 1, "Gia_ManGlaRefine(): Abstraction gate map is missing.\n" ); return -1; } // derive abstraction pAbs = Gia_ManDupAbsGates( p, p->vGateClasses ); Gia_ManStop( pAbs ); pAbs = Gia_ManDupAbsGates( p, p->vGateClasses ); if ( Gia_ManPiNum(pAbs) != pCex->nPis ) { Abc_Print( 1, "Gia_ManGlaRefine(): The PI counts in GLA and in CEX do not match.\n" ); Gia_ManStop( pAbs ); return -1; } if ( !Gia_ManVerifyCex( pAbs, pCex, 0 ) ) { Abc_Print( 1, "Gia_ManGlaRefine(): The initial counter-example is invalid.\n" ); // Gia_ManStop( pAbs ); // return -1; } // else // Abc_Print( 1, "Gia_ManGlaRefine(): The initial counter-example is correct.\n" ); // get inputs Gia_ManGlaCollect( p, p->vGateClasses, &vPis, &vPPis, NULL, NULL ); assert( Vec_IntSize(vPis) + Vec_IntSize(vPPis) == Gia_ManPiNum(pAbs) ); // add missing logic if ( fAddOneLayer ) { Gia_Obj_t * pObj; // check if this is a real counter-example Gia_ObjTerSimSet0( Gia_ManConst0(pAbs) ); for ( f = 0; f <= pCex->iFrame; f++ ) { Gia_ManForEachPi( pAbs, pObj, i ) { if ( i >= Vec_IntSize(vPis) ) // PPIs Gia_ObjTerSimSetX( pObj ); else if ( Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); } Gia_ManForEachRo( pAbs, pObj, i ) { if ( f == 0 ) Gia_ObjTerSimSet0( pObj ); else Gia_ObjTerSimRo( pAbs, pObj ); } Gia_ManForEachAnd( pAbs, pObj, i ) Gia_ObjTerSimAnd( pObj ); Gia_ManForEachCo( pAbs, pObj, i ) Gia_ObjTerSimCo( pObj ); } pObj = Gia_ManPo( pAbs, 0 ); if ( Gia_ObjTerSimGet1(pObj) ) { pCexNew = Gia_ManCexRemap( p, pCex, vPis ); Abc_Print( 1, "Procedure &gla_refine found a real counter-example in frame %d.\n", pCexNew->iFrame ); } // else // Abc_Print( 1, "CEX is not real.\n" ); Gia_ManForEachObj( pAbs, pObj, i ) Gia_ObjTerSimSetC( pObj ); if ( pCexNew == NULL ) { // grow one layer Vec_IntForEachEntry( vPPis, iObjId, i ) { assert( Vec_IntEntry( p->vGateClasses, iObjId ) == 0 ); Vec_IntWriteEntry( p->vGateClasses, iObjId, 1 ); } if ( fVerbose ) { Abc_Print( 1, "Additional objects = %d. ", Vec_IntSize(vPPis) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } } } else { // minimize the CEX pAig = Gia_ManToAigSimple( pAbs ); pCare = Saig_ManCbaFindCexCareBits( pAig, pCex, Vec_IntSize(vPis), fVerbose ); Aig_ManStop( pAig ); if ( pCare == NULL ) Abc_Print( 1, "Counter-example minimization has failed.\n" ); // add new objects to the map iObjId = -1; for ( f = 0; f <= pCare->iFrame; f++ ) for ( i = 0; i < pCare->nPis; i++ ) if ( Abc_InfoHasBit( pCare->pData, pCare->nRegs + f * pCare->nPis + i ) ) { nOnes++; assert( i >= Vec_IntSize(vPis) ); iObjId = Vec_IntEntry( vPPis, i - Vec_IntSize(vPis) ); assert( iObjId > 0 && iObjId < Gia_ManObjNum(p) ); if ( Vec_IntEntry( p->vGateClasses, iObjId ) > 0 ) continue; assert( Vec_IntEntry( p->vGateClasses, iObjId ) == 0 ); Vec_IntWriteEntry( p->vGateClasses, iObjId, 1 ); // Abc_Print( 1, "Adding object %d.\n", iObjId ); // Gia_ObjPrint( p, Gia_ManObj(p, iObjId) ); Counter++; } Abc_CexFree( pCare ); if ( fVerbose ) { Abc_Print( 1, "Essential bits = %d. Additional objects = %d. ", nOnes, Counter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } // consider the case of SAT if ( iObjId == -1 ) { pCexNew = Gia_ManCexRemap( p, pCex, vPis ); Abc_Print( 1, "Procedure &gla_refine found a real counter-example in frame %d.\n", pCexNew->iFrame ); } } Vec_IntFree( vPis ); Vec_IntFree( vPPis ); Gia_ManStop( pAbs ); if ( pCexNew ) { ABC_FREE( p->pCexSeq ); p->pCexSeq = pCexNew; return 0; } // extract abstraction to include min-cut if ( fMinCut ) Nwk_ManDeriveMinCut( p, fVerbose ); return -1; } /**Function************************************************************* Synopsis [Resimulates the counter-example and returns flop values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManGetStateAndCheckCex( Gia_Man_t * pAig, Abc_Cex_t * p, int iFrame ) { Vec_Int_t * vInit = Vec_IntAlloc( Gia_ManRegNum(pAig) ); Gia_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; assert( iFrame >= 0 && iFrame <= p->iFrame ); Gia_ManCleanMark0(pAig); Gia_ManForEachRo( pAig, pObj, i ) pObj->fMark0 = 0;//Abc_InfoHasBit(p->pData, iBit++); for ( i = 0, iBit = p->nRegs; i <= p->iFrame; i++ ) { if ( i == iFrame ) { Gia_ManForEachRo( pAig, pObjRo, k ) Vec_IntPush( vInit, pObjRo->fMark0 ); } 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 ); RetValue = Gia_ManPo(pAig, p->iPo)->fMark0; if ( RetValue != 1 ) Vec_IntFreeP( &vInit ); Gia_ManCleanMark0(pAig); return vInit; } /**Function************************************************************* Synopsis [Verify counter-example starting in the given timeframe.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCheckCex( Gia_Man_t * pAig, Abc_Cex_t * p, int iFrame ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; assert( iFrame >= 0 && iFrame <= p->iFrame ); Gia_ManCleanMark0(pAig); Gia_ManForEachRo( pAig, pObj, i ) pObj->fMark0 = 0;//Abc_InfoHasBit(p->pData, iBit++); for ( i = iFrame, iBit += p->nRegs + Gia_ManPiNum(pAig) * iFrame; 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 ); RetValue = Gia_ManPo(pAig, p->iPo)->fMark0; Gia_ManCleanMark0(pAig); if ( RetValue == 1 ) printf( "Shortened CEX holds for the abstraction of the fast-forwarded model.\n" ); else printf( "Shortened CEX does not hold for the abstraction of the fast-forwarded model.\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManTransformFlops( Gia_Man_t * p, Vec_Int_t * vFlops, Vec_Int_t * vInit ) { Vec_Bit_t * vInitNew; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, iFlopId; assert( Vec_IntSize(vInit) == Vec_IntSize(vFlops) ); vInitNew = Vec_BitStart( Gia_ManRegNum(p) ); Gia_ManForEachObjVec( vFlops, p, pObj, i ) { assert( Gia_ObjIsRo(p, pObj) ); if ( Vec_IntEntry(vInit, i) == 0 ) continue; iFlopId = Gia_ObjCioId(pObj) - Gia_ManPiNum(p); assert( iFlopId >= 0 && iFlopId < Gia_ManRegNum(p) ); Vec_BitWriteEntry( vInitNew, iFlopId, 1 ); } pNew = Gia_ManDupFlip( p, Vec_BitArray(vInitNew) ); Vec_BitFree( vInitNew ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManNewRefine( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int iFrameExtra, int fVerbose ) { Gia_Man_t * pAbs, * pNew; Vec_Int_t * vFlops, * vInit; Vec_Int_t * vCopy; // abctime clk = Abc_Clock(); int RetValue; ABC_FREE( p->pCexSeq ); if ( p->vGateClasses == NULL ) { Abc_Print( 1, "Gia_ManNewRefine(): Abstraction gate map is missing.\n" ); return -1; } vCopy = Vec_IntDup( p->vGateClasses ); Abc_Print( 1, "Refining with %d-frame CEX, starting in frame %d, with %d extra frames.\n", pCex->iFrame, iFrameStart, iFrameExtra ); // derive abstraction pAbs = Gia_ManDupAbsGates( p, p->vGateClasses ); Gia_ManStop( pAbs ); pAbs = Gia_ManDupAbsGates( p, p->vGateClasses ); if ( Gia_ManPiNum(pAbs) != pCex->nPis ) { Abc_Print( 1, "Gia_ManNewRefine(): The PI counts in GLA and in CEX do not match.\n" ); Gia_ManStop( pAbs ); Vec_IntFree( vCopy ); return -1; } // get the state in frame iFrameStart vInit = Gia_ManGetStateAndCheckCex( pAbs, pCex, iFrameStart ); if ( vInit == NULL ) { Abc_Print( 1, "Gia_ManNewRefine(): The initial counter-example is invalid.\n" ); Gia_ManStop( pAbs ); Vec_IntFree( vCopy ); return -1; } if ( fVerbose ) Abc_Print( 1, "Gia_ManNewRefine(): The initial counter-example is correct.\n" ); // get inputs Gia_ManGlaCollect( p, p->vGateClasses, NULL, NULL, &vFlops, NULL ); // assert( Vec_IntSize(vPis) + Vec_IntSize(vPPis) == Gia_ManPiNum(pAbs) ); Gia_ManStop( pAbs ); //Vec_IntPrint( vFlops ); //Vec_IntPrint( vInit ); // transform the manager to have new init state pNew = Gia_ManTransformFlops( p, vFlops, vInit ); Vec_IntFree( vFlops ); Vec_IntFree( vInit ); // verify abstraction { Gia_Man_t * pAbs = Gia_ManDupAbsGates( pNew, p->vGateClasses ); Gia_ManCheckCex( pAbs, pCex, iFrameStart ); Gia_ManStop( pAbs ); } // transfer abstraction assert( pNew->vGateClasses == NULL ); pNew->vGateClasses = Vec_IntDup( p->vGateClasses ); // perform abstraction for the new AIG { Abs_Par_t Pars, * pPars = &Pars; Abs_ParSetDefaults( pPars ); pPars->nFramesMax = pCex->iFrame - iFrameStart + 1 + iFrameExtra; pPars->fVerbose = fVerbose; RetValue = Gia_ManPerformGla( pNew, pPars ); if ( RetValue == 0 ) // spurious SAT { Vec_IntFreeP( &pNew->vGateClasses ); pNew->vGateClasses = Vec_IntDup( vCopy ); } } // move the abstraction map Vec_IntFreeP( &p->vGateClasses ); p->vGateClasses = pNew->vGateClasses; pNew->vGateClasses = NULL; // cleanup Gia_ManStop( pNew ); Vec_IntFree( vCopy ); return -1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absPth.c000066400000000000000000000144421300674244400233200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absPth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Interface to pthreads.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absPth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" #include "proof/pdr/pdr.h" #include "proof/ssw/ssw.h" #ifdef ABC_USE_PTHREADS #ifdef _WIN32 #include "../lib/pthread.h" #else #include #include #endif #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifndef ABC_USE_PTHREADS void Gia_GlaProveAbsracted( Gia_Man_t * p, int fSimpProver, int fVerbose ) {} void Gia_GlaProveCancel( int fVerbose ) {} int Gia_GlaProveCheck( int fVerbose ) { return 0; } #else // pthreads are used // information given to the thread typedef struct Abs_ThData_t_ { Aig_Man_t * pAig; int fVerbose; int RunId; } Abs_ThData_t; // mutext to control access to shared variables pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; static volatile int g_nRunIds = 0; // the number of the last prover instance static volatile int g_fAbstractionProved = 0; // set to 1 when prover successed to prove // call back procedure for PDR int Abs_CallBackToStop( int RunId ) { assert( RunId <= g_nRunIds ); return RunId < g_nRunIds; } // test procedure to replace PDR int Pdr_ManSolve_test( Aig_Man_t * pAig, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex ) { char * p = ABC_ALLOC( char, 111 ); while ( 1 ) { if ( pPars->pFuncStop && pPars->pFuncStop(pPars->RunId) ) break; } ABC_FREE( p ); return -1; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create one thread] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abs_ProverThread( void * pArg ) { Abs_ThData_t * pThData = (Abs_ThData_t *)pArg; Pdr_Par_t Pars, * pPars = &Pars; int RetValue, status; // call PDR Pdr_ManSetDefaultParams( pPars ); pPars->fSilent = 1; pPars->RunId = pThData->RunId; pPars->pFuncStop = Abs_CallBackToStop; RetValue = Pdr_ManSolve( pThData->pAig, pPars ); // update the result if ( RetValue == 1 ) { status = pthread_mutex_lock(&g_mutex); assert( status == 0 ); g_fAbstractionProved = 1; status = pthread_mutex_unlock(&g_mutex); assert( status == 0 ); } // quit this thread if ( pThData->fVerbose ) { if ( RetValue == 1 ) Abc_Print( 1, "Proved abstraction %d.\n", pThData->RunId ); else if ( RetValue == 0 ) Abc_Print( 1, "Disproved abstraction %d.\n", pThData->RunId ); else if ( RetValue == -1 ) Abc_Print( 1, "Cancelled abstraction %d.\n", pThData->RunId ); else assert( 0 ); } // free memory Aig_ManStop( pThData->pAig ); ABC_FREE( pThData ); // quit this thread pthread_exit( NULL ); assert(0); return NULL; } void Gia_GlaProveAbsracted( Gia_Man_t * pGia, int fSimpProver, int fVerbose ) { extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ); Abs_ThData_t * pThData; Ssw_Pars_t Pars, * pPars = &Pars; Aig_Man_t * pAig, * pTemp; Gia_Man_t * pAbs; pthread_t ProverThread; int status; // disable verbosity // fVerbose = 0; // create abstraction assert( pGia->vGateClasses != NULL ); pAbs = Gia_ManDupAbsGates( pGia, pGia->vGateClasses ); Gia_ManCleanValue( pGia ); pAig = Gia_ManToAigSimple( pAbs ); Gia_ManStop( pAbs ); // simplify abstraction if ( fSimpProver ) { Ssw_ManSetDefaultParams( pPars ); pPars->nFramesK = 4; pAig = Ssw_SignalCorrespondence( pTemp = pAig, pPars ); //printf( "\n" ); //Aig_ManPrintStats( pTemp ); //Aig_ManPrintStats( pAig ); Aig_ManStop( pTemp ); } // synthesize abstraction // pAig = Dar_ManRwsat( pTemp = pAig, 0, 0 ); // Aig_ManStop( pTemp ); // reset the proof status = pthread_mutex_lock(&g_mutex); assert( status == 0 ); g_fAbstractionProved = 0; status = pthread_mutex_unlock(&g_mutex); assert( status == 0 ); // collect thread data pThData = ABC_CALLOC( Abs_ThData_t, 1 ); pThData->pAig = pAig; pThData->fVerbose = fVerbose; status = pthread_mutex_lock(&g_mutex); assert( status == 0 ); pThData->RunId = ++g_nRunIds; status = pthread_mutex_unlock(&g_mutex); assert( status == 0 ); // create thread if ( fVerbose ) Abc_Print( 1, "\nTrying to prove abstraction %d.\n", pThData->RunId ); status = pthread_create( &ProverThread, NULL, Abs_ProverThread, pThData ); assert( status == 0 ); } void Gia_GlaProveCancel( int fVerbose ) { int status; status = pthread_mutex_lock(&g_mutex); assert( status == 0 ); g_nRunIds++; status = pthread_mutex_unlock(&g_mutex); assert( status == 0 ); } int Gia_GlaProveCheck( int fVerbose ) { int status; if ( g_fAbstractionProved == 0 ) return 0; status = pthread_mutex_lock(&g_mutex); assert( status == 0 ); g_fAbstractionProved = 0; status = pthread_mutex_unlock(&g_mutex); assert( status == 0 ); return 1; } #endif // pthreads are used //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absRef.c000066400000000000000000000707061300674244400233060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absRef.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Refinement manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absRef.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sat/bsat/satSolver2.h" #include "abs.h" #include "absRef.h" ABC_NAMESPACE_IMPL_START /* Description of the refinement manager This refinement manager should be * started by calling Rnm_ManStart() this procedure takes one argument, the user's seq miter as a GIA manager - the manager should have only one property output - this manager should not change while the refinement manager is alive - it cannot be used by external applications for any purpose - when the refinement manager stop, GIA manager is the same as at the beginning - in the meantime, it will have some data-structures attached to its nodes... * stopped by calling Rnm_ManStop() * between starting and stopping, refinements are obtained by calling Rnm_ManRefine() Procedure Rnm_ManRefine() takes the following arguments: * the refinement manager previously started by Rnm_ManStart() * counter-example (CEX) obtained by abstracting some logic of GIA * mapping (vMap) of inputs of the CEX into the object IDs of the GIA manager - only PI, flop outputs, and internal AND nodes can be used in vMap - the ordering of objects in vMap is not important - however, the index of a non-PI object in vMap is used as its priority (the smaller the index, the more likely this non-PI object apears in a refinement) - only the logic between PO and the objects listed in vMap is traversed by the manager (as a result, GIA can be arbitrarily large, but only objects used in the abstraction and the pseudo-PI, that is, objects in the cut, will be visited by the manager) * flag fPropFanout defines whether value propagation is done through the fanout - it this flag is enabled, theoretically refinement should be better (the result smaller) * flag fVerbose may print some statistics The refinement manager returns a minimal-size array of integer IDs of GIA objects which should be added to the abstraction to possibly prevent the given counter-example - only flop output and internal AND nodes from vMap may appear in the resulting array - if the resulting array is empty, the CEX is a true CEX (in other words, non-PI objects are not needed to set the PO value to 1) Verification of the selected refinement is performed by - initializing all PI objects in vMap to value 0 or 1 they have in the CEX - initializing all remaining objects in vMap to value X - initializing objects used in the refiment to value 0 or 1 they have in the CEX - simulating through as many timeframes as required by the CEX - if the PO value in the last frame is 1, the refinement is correct (however, the minimality of the refinement is not currently checked) */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* static inline int Rnm_ObjSatVar( Rnm_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry( p->vSatVars, Gia_ObjId(p->pGia, pObj) ); } static inline void Rnm_ObjSetSatVar( Rnm_Man_t * p, Gia_Obj_t * pObj, int c) { Vec_IntWriteEntry( p->vSatVars, Gia_ObjId(p->pGia, pObj), c ); } static inline int Rnm_ObjFindOrAddSatVar( Rnm_Man_t * p, Gia_Obj_t * pObj) { if ( Rnm_ObjSatVar(p, pObj) == 0 ) { Rnm_ObjSetSatVar(p, pObj, Vec_IntSize(p->vSat2Ids)); Vec_IntPush(p->vSat2Ids, Gia_ObjId(p->pGia, pObj)); }; return 2*Rnm_ObjSatVar(p, pObj); } */ extern void Ga2_ManCnfAddStatic( sat_solver2 * pSat, Vec_Int_t * vCnf0, Vec_Int_t * vCnf1, int * pLits, int iLitOut, int ProofId ); extern Vec_Int_t * Ga2_ManCnfCompute( unsigned uTruth, int nVars, Vec_Int_t * vCover ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #if 0 /**Function************************************************************* Synopsis [Performs UNSAT-core-based refinement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rnm_ManRefineCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vVisited, Vec_Int_t * vFlops ) { Vec_Int_t * vLeaves; Gia_Obj_t * pFanin; int k; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjIsRo(p, pObj) ) Vec_IntPush( vFlops, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); vLeaves = Ga2_ObjLeaves( p, pObj ); Gia_ManForEachObjVec( vLeaves, p, pFanin, k ) Rnm_ManRefineCollect_rec( p, pFanin, vVisited, vFlops ); Vec_IntPush( vVisited, Gia_ObjId(p, pObj) ); } Vec_Int_t * Rnm_ManRefineUnsatCore( Rnm_Man_t * p, Vec_Int_t * vPPIs ) { Vec_Int_t * vCnf0, * vCnf1; Vec_Int_t * vLeaves, * vLits, * vPpi2Map; Vec_Int_t * vVisited, * vFlops, * vCore, * vCoreFinal; Gia_Obj_t * pObj, * pFanin; int i, k, f, Status, Entry, pLits[5], iBit = p->pCex->nRegs; // map PPIs into their positions in the map // CAN BE MADE FASTER vPpi2Map = Vec_IntAlloc( Vec_IntSize(vPPIs) ); Vec_IntForEachEntry( vPPIs, Entry, i ) { Entry = Vec_IntFind( p->vMap, Entry ); assert( Entry >= 0 ); Vec_IntPush( vPpi2Map, Entry ); } // collect nodes between selected PPIs and CIs vFlops = Vec_IntAlloc( 100 ); vVisited = Vec_IntAlloc( 100 ); Gia_ManIncrementTravId( p->pGia ); Gia_ManForEachObjVec( vPPIs, p->pGia, pObj, i ) // if ( !Gia_ObjIsRo(p->pGia, pObj) ) // SKIP PPIs that are flops Rnm_ManRefineCollect_rec( p->pGia, pObj, vVisited, vFlops ); // create SAT variables and SAT solver Vec_IntFill( p->vSat2Ids, 1, -1 ); assert( p->pSat == NULL ); p->pSat = sat_solver2_new(); Vec_IntFill( p->vSatVars, Gia_ManObjNum(p->pGia), 0 ); // NO NEED TO CLEAN EACH TIME // assign PPI variables Gia_ManForEachObjVec( vFlops, p->pGia, pObj, i ) Rnm_ObjFindOrAddSatVar( p, pObj ); // assign other variables Gia_ManForEachObjVec( vVisited, p->pGia, pObj, i ) { vLeaves = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k ) pLits[k] = Rnm_ObjFindOrAddSatVar( p, pFanin ); vCnf0 = Ga2_ManCnfCompute( Ga2_ObjTruth(p->pGia, pObj), Vec_IntSize(vLeaves), p->vIsopMem ); vCnf1 = Ga2_ManCnfCompute( ~Ga2_ObjTruth(p->pGia, pObj), Vec_IntSize(vLeaves), p->vIsopMem ); Ga2_ManCnfAddStatic( p->pSat, vCnf0, vCnf1, pLits, Rnm_ObjFindOrAddSatVar(p, pObj), Rnm_ObjFindOrAddSatVar(p, pObj)/2 ); Vec_IntFree( vCnf0 ); Vec_IntFree( vCnf1 ); } // printf( "\n" ); p->pSat->pPrf2 = Prf_ManAlloc(); Prf_ManRestart( p->pSat->pPrf2, NULL, sat_solver2_nlearnts(p->pSat), Vec_IntSize(p->vSat2Ids) ); // iterate UNSAT core computation for each timeframe vLits = Vec_IntAlloc( 100 ); vCoreFinal = Vec_IntAlloc( 100 ); for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis ) { // collect values of PPIs in this timeframe Vec_IntClear( vLits ); Gia_ManForEachObjVec( vPPIs, p->pGia, pObj, i ) { Entry = Abc_InfoHasBit( p->pCex->pData, iBit + Vec_IntEntry(vPpi2Map, i) ); Vec_IntPush( vLits, Abc_LitNotCond( Rnm_ObjFindOrAddSatVar(p, pObj), !Entry ) ); } // handle the first timeframe in a special vay if ( f == 0 ) Gia_ManForEachObjVec( vFlops, p->pGia, pObj, i ) if ( Vec_IntFind( vPPIs, Gia_ObjId(p->pGia, pObj) ) == -1 ) Vec_IntPush( vLits, Abc_LitNotCond( Rnm_ObjFindOrAddSatVar(p, pObj), 1 ) ); /* // uniqify literals and detect special conflicts Vec_IntUniqify( vLits ); Vec_IntForEachEntryStart( vLits, Entry, i, 1 ) if ( Vec_IntEntry(vLits, i-1) == Abc_LitNot(Entry) ) break; if ( i < Vec_IntSize(vLits) ) printf( "triv_unsat " ); else */ Status = sat_solver2_solve( p->pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( Status != l_False ) continue; vCore = (Vec_Int_t *)Sat_ProofCore( p->pSat ); // vCore = Vec_IntAlloc( 0 ); // add to the UNSAT core Vec_IntAppend( vCoreFinal, vCore ); // printf( "Frame %d : ", f ); // Vec_IntPrint( vCore ); Vec_IntFree( vCore ); } assert( iBit == p->pCex->nBits ); Vec_IntUniqify( vCoreFinal ); Vec_IntFree( vLits ); Prf_ManStopP( &p->pSat->pPrf2 ); sat_solver2_delete( p->pSat ); p->pSat = NULL; // translate from entry into ID Vec_IntForEachEntry( vCoreFinal, Entry, i ) { assert( Vec_IntEntry(p->vSat2Ids, Entry) >= 0 ); assert( Vec_IntEntry(p->vSat2Ids, Entry) < Gia_ManObjNum(p->pGia) ); Vec_IntWriteEntry( vCoreFinal, i, Vec_IntEntry(p->vSat2Ids, Entry) ); } // if there are flop outputs, add them Gia_ManForEachObjVec( vPPIs, p->pGia, pObj, i ) if ( Gia_ObjIsRo(p->pGia, pObj) ) Vec_IntPush( vCoreFinal, Gia_ObjId(p->pGia, pObj) ); Vec_IntUniqify( vCoreFinal ); // printf( "\n" ); // Vec_IntPrint( vPPIs ); // Vec_IntPrint( vCoreFinal ); // printf( "\n" ); // clean SAT variable numbers Gia_ManForEachObjVec( vVisited, p->pGia, pObj, i ) { Rnm_ObjSetSatVar( p, pObj, 0 ); vLeaves = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vLeaves, p->pGia, pFanin, k ) Rnm_ObjSetSatVar( p, pFanin, 0 ); } Vec_IntFree( vFlops ); Vec_IntFree( vVisited ); Vec_IntFree( vPpi2Map ); return vCoreFinal; } #endif /**Function************************************************************* Synopsis [Creates a new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rnm_Man_t * Rnm_ManStart( Gia_Man_t * pGia ) { Rnm_Man_t * p; assert( Gia_ManPoNum(pGia) == 1 ); p = ABC_CALLOC( Rnm_Man_t, 1 ); p->pGia = pGia; p->vObjs = Vec_IntAlloc( 100 ); p->vCounts = Vec_StrStart( Gia_ManObjNum(pGia) ); p->vFanins = Vec_IntAlloc( 1000 ); // p->vSatVars = Vec_IntAlloc( 0 ); // p->vSat2Ids = Vec_IntAlloc( 1000 ); // p->vIsopMem = Vec_IntAlloc( 0 ); p->nObjsAlloc = 10000; p->pObjs = ABC_ALLOC( Rnm_Obj_t, p->nObjsAlloc ); if ( p->pGia->vFanout == NULL ) Gia_ManStaticFanoutStart( p->pGia ); Gia_ManCleanValue(pGia); Gia_ManCleanMark0(pGia); Gia_ManCleanMark1(pGia); return p; } void Rnm_ManStop( Rnm_Man_t * p, int fProfile ) { if ( !p ) return; // print runtime statistics if ( fProfile && p->nCalls ) { double MemGia = sizeof(Gia_Man_t) + sizeof(Gia_Obj_t) * p->pGia->nObjsAlloc + sizeof(int) * p->pGia->nTravIdsAlloc; double MemOther = sizeof(Rnm_Man_t) + sizeof(Rnm_Obj_t) * p->nObjsAlloc + sizeof(int) * Vec_IntCap(p->vObjs); abctime timeOther = p->timeTotal - p->timeFwd - p->timeBwd - p->timeVer; printf( "Abstraction refinement runtime statistics:\n" ); ABC_PRTP( "Sensetization", p->timeFwd, p->timeTotal ); ABC_PRTP( "Justification", p->timeBwd, p->timeTotal ); ABC_PRTP( "Verification ", p->timeVer, p->timeTotal ); ABC_PRTP( "Other ", timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); printf( "Total calls = %d. Average refine = %.1f. GIA mem = %.3f MB. Other mem = %.3f MB.\n", p->nCalls, 1.0*p->nRefines/p->nCalls, MemGia/(1<<20), MemOther/(1<<20) ); } Gia_ManCleanMark0(p->pGia); Gia_ManCleanMark1(p->pGia); Gia_ManStaticFanoutStop(p->pGia); // Gia_ManSetPhase(p->pGia); // Vec_IntFree( p->vIsopMem ); // Vec_IntFree( p->vSatVars ); // Vec_IntFree( p->vSat2Ids ); Vec_StrFree( p->vCounts ); Vec_IntFree( p->vFanins ); Vec_IntFree( p->vObjs ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } double Rnm_ManMemoryUsage( Rnm_Man_t * p ) { return (double)(sizeof(Rnm_Man_t) + sizeof(Rnm_Obj_t) * p->nObjsAlloc + sizeof(int) * Vec_IntCap(p->vObjs)); } /**Function************************************************************* Synopsis [Collect internal objects to be used in value propagation.] Description [Resulting array vObjs contains RO, AND, PO/RI in a topo order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Rnm_ManCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs, int nAddOn ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCo(pObj) ) Rnm_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs, nAddOn ); else if ( Gia_ObjIsAnd(pObj) ) { Rnm_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs, nAddOn ); Rnm_ManCollect_rec( p, Gia_ObjFanin1(pObj), vObjs, nAddOn ); } else if ( !Gia_ObjIsRo(p, pObj) ) assert( 0 ); pObj->Value = Vec_IntSize(vObjs) + nAddOn; Vec_IntPush( vObjs, Gia_ObjId(p, pObj) ); } void Rnm_ManCollect( Rnm_Man_t * p ) { Gia_Obj_t * pObj = NULL; int i; // mark const/PIs/PPIs Gia_ManIncrementTravId( p->pGia ); Gia_ObjSetTravIdCurrent( p->pGia, Gia_ManConst0(p->pGia) ); Gia_ManConst0(p->pGia)->Value = 0; Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); Gia_ObjSetTravIdCurrent( p->pGia, pObj ); pObj->Value = 1 + i; } // collect objects Vec_IntClear( p->vObjs ); Rnm_ManCollect_rec( p->pGia, Gia_ManPo(p->pGia, 0), p->vObjs, 1 + Vec_IntSize(p->vMap) ); Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i ) if ( Gia_ObjIsRo(p->pGia, pObj) ) Rnm_ManCollect_rec( p->pGia, Gia_ObjRoToRi(p->pGia, pObj), p->vObjs, 1 + Vec_IntSize(p->vMap) ); // the last object should be a CO assert( Gia_ObjIsCo(pObj) ); assert( (int)pObj->Value == Vec_IntSize(p->vMap) + Vec_IntSize(p->vObjs) ); } void Rnm_ManCleanValues( Rnm_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) pObj->Value = 0; Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i ) pObj->Value = 0; } /**Function************************************************************* Synopsis [Performs sensitization analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rnm_ManSensitize( Rnm_Man_t * p ) { Rnm_Obj_t * pRnm, * pRnm0, * pRnm1; Gia_Obj_t * pObj; int f, i, iBit = p->pCex->nRegs; // const0 is initialized automatically in all timeframes for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis ) { Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); pRnm = Rnm_ManObj( p, pObj, f ); pRnm->Value = Abc_InfoHasBit( p->pCex->pData, iBit + i ); if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI { assert( pObj->Value > 0 ); pRnm->Prio = pObj->Value; pRnm->fPPi = 1; } } Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i ) { assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ); pRnm = Rnm_ManObj( p, pObj, f ); assert( !pRnm->fPPi ); if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( f == 0 ) continue; pRnm0 = Rnm_ManObj( p, Gia_ObjRoToRi(p->pGia, pObj), f-1 ); pRnm->Value = pRnm0->Value; pRnm->Prio = pRnm0->Prio; continue; } if ( Gia_ObjIsCo(pObj) ) { pRnm0 = Rnm_ManObj( p, Gia_ObjFanin0(pObj), f ); pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj)); pRnm->Prio = pRnm0->Prio; continue; } assert( Gia_ObjIsAnd(pObj) ); pRnm0 = Rnm_ManObj( p, Gia_ObjFanin0(pObj), f ); pRnm1 = Rnm_ManObj( p, Gia_ObjFanin1(pObj), f ); pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) & (pRnm1->Value ^ Gia_ObjFaninC1(pObj)); if ( pRnm->Value == 1 ) pRnm->Prio = Abc_MaxInt( pRnm0->Prio, pRnm1->Prio ); else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 ) pRnm->Prio = Abc_MinInt( pRnm0->Prio, pRnm1->Prio ); // choice else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 ) pRnm->Prio = pRnm0->Prio; else pRnm->Prio = pRnm1->Prio; } } assert( iBit == p->pCex->nBits ); pRnm = Rnm_ManObj( p, Gia_ManPo(p->pGia, 0), p->pCex->iFrame ); if ( pRnm->Value != 1 ) printf( "Output value is incorrect.\n" ); return pRnm->Prio; } /**Function************************************************************* Synopsis [Drive implications of the given node towards primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rnm_ManJustifyPropFanout_rec( Rnm_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vSelect ) { Rnm_Obj_t * pRnm0, * pRnm1, * pRnm = Rnm_ManObj( p, pObj, f ); Gia_Obj_t * pFanout = NULL; int i, k;//, Id = Gia_ObjId(p->pGia, pObj); assert( pRnm->fVisit == 0 ); pRnm->fVisit = 1; if ( Rnm_ManObj( p, pObj, 0 )->fVisitJ == 0 ) { Rnm_ManObj( p, pObj, 0 )->fVisitJ = 1; p->nVisited++; } if ( pRnm->fPPi ) { assert( (int)pRnm->Prio > 0 ); for ( i = p->pCex->iFrame; i >= 0; i-- ) if ( !Rnm_ManObj(p, pObj, i)->fVisit ) Rnm_ManJustifyPropFanout_rec( p, pObj, i, vSelect ); Vec_IntPush( vSelect, Gia_ObjId(p->pGia, pObj) ); return; } if ( (Gia_ObjIsCo(pObj) && f == p->pCex->iFrame) || Gia_ObjIsPo(p->pGia, pObj) ) return; if ( Gia_ObjIsRi(p->pGia, pObj) ) { pFanout = Gia_ObjRiToRo(p->pGia, pObj); if ( !Rnm_ManObj(p, pFanout, f+1)->fVisit ) Rnm_ManJustifyPropFanout_rec( p, pFanout, f+1, vSelect ); return; } assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) ); Gia_ObjForEachFanoutStatic( p->pGia, pObj, pFanout, k ) { Rnm_Obj_t * pRnmF; if ( pFanout->Value == 0 ) continue; pRnmF = Rnm_ManObj(p, pFanout, f); if ( pRnmF->fPPi || pRnmF->fVisit ) continue; if ( Gia_ObjIsCo(pFanout) ) { Rnm_ManJustifyPropFanout_rec( p, pFanout, f, vSelect ); continue; } assert( Gia_ObjIsAnd(pFanout) ); pRnm0 = Rnm_ManObj( p, Gia_ObjFanin0(pFanout), f ); pRnm1 = Rnm_ManObj( p, Gia_ObjFanin1(pFanout), f ); if ( ((pRnm0->Value ^ Gia_ObjFaninC0(pFanout)) == 0 && pRnm0->fVisit) || ((pRnm1->Value ^ Gia_ObjFaninC1(pFanout)) == 0 && pRnm1->fVisit) || ( ((pRnm0->Value ^ Gia_ObjFaninC0(pFanout)) == 1 && pRnm0->fVisit) && ((pRnm1->Value ^ Gia_ObjFaninC1(pFanout)) == 1 && pRnm1->fVisit) ) ) Rnm_ManJustifyPropFanout_rec( p, pFanout, f, vSelect ); } } void Rnm_ManJustify_rec( Rnm_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vSelect ) { Rnm_Obj_t * pRnm = Rnm_ManObj( p, pObj, f ); int i;//, Id = Gia_ObjId(p->pGia, pObj); if ( pRnm->fVisit ) return; if ( p->fPropFanout ) Rnm_ManJustifyPropFanout_rec( p, pObj, f, vSelect ); else { pRnm->fVisit = 1; if ( Rnm_ManObj( p, pObj, 0 )->fVisitJ == 0 ) { Rnm_ManObj( p, pObj, 0 )->fVisitJ = 1; p->nVisited++; } } if ( pRnm->fPPi ) { assert( (int)pRnm->Prio > 0 ); if ( p->fPropFanout ) { for ( i = p->pCex->iFrame; i >= 0; i-- ) if ( !Rnm_ManObj(p, pObj, i)->fVisit ) Rnm_ManJustifyPropFanout_rec( p, pObj, i, vSelect ); } else { Vec_IntPush( vSelect, Gia_ObjId(p->pGia, pObj) ); // for ( i = p->pCex->iFrame; i >= 0; i-- ) // Rnm_ManObj(p, pObj, i)->fVisit = 1; } return; } if ( Gia_ObjIsPi(p->pGia, pObj) || Gia_ObjIsConst0(pObj) ) return; if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( f > 0 ) Rnm_ManJustify_rec( p, Gia_ObjFanin0(Gia_ObjRoToRi(p->pGia, pObj)), f-1, vSelect ); return; } if ( Gia_ObjIsAnd(pObj) ) { Rnm_Obj_t * pRnm0 = Rnm_ManObj( p, Gia_ObjFanin0(pObj), f ); Rnm_Obj_t * pRnm1 = Rnm_ManObj( p, Gia_ObjFanin1(pObj), f ); if ( pRnm->Value == 1 ) { if ( pRnm0->Prio > 0 ) Rnm_ManJustify_rec( p, Gia_ObjFanin0(pObj), f, vSelect ); if ( pRnm1->Prio > 0 ) Rnm_ManJustify_rec( p, Gia_ObjFanin1(pObj), f, vSelect ); } else // select one value { if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 ) { if ( pRnm0->Prio <= pRnm1->Prio ) // choice { if ( pRnm0->Prio > 0 ) Rnm_ManJustify_rec( p, Gia_ObjFanin0(pObj), f, vSelect ); } else { if ( pRnm1->Prio > 0 ) Rnm_ManJustify_rec( p, Gia_ObjFanin1(pObj), f, vSelect ); } } else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 ) { if ( pRnm0->Prio > 0 ) Rnm_ManJustify_rec( p, Gia_ObjFanin0(pObj), f, vSelect ); } else if ( (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 ) { if ( pRnm1->Prio > 0 ) Rnm_ManJustify_rec( p, Gia_ObjFanin1(pObj), f, vSelect ); } else assert( 0 ); } } else assert( 0 ); } /**Function************************************************************* Synopsis [Performs refinement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rnm_ManVerifyUsingTerSim( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, Vec_Int_t * vObjs, Vec_Int_t * vRes ) { Gia_Obj_t * pObj; int i, f, iBit = pCex->nRegs; Gia_ObjTerSimSet0( Gia_ManConst0(p) ); for ( f = 0; f <= pCex->iFrame; f++, iBit += pCex->nPis ) { Gia_ManForEachObjVec( vMap, p, pObj, i ) { pObj->Value = Abc_InfoHasBit( pCex->pData, iBit + i ); if ( !Gia_ObjIsPi(p, pObj) ) Gia_ObjTerSimSetX( pObj ); else if ( pObj->Value ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); } Gia_ManForEachObjVec( vRes, p, pObj, i ) // vRes is subset of vMap { if ( pObj->Value ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); } Gia_ManForEachObjVec( vObjs, p, pObj, i ) { if ( Gia_ObjIsCo(pObj) ) Gia_ObjTerSimCo( pObj ); else if ( Gia_ObjIsAnd(pObj) ) Gia_ObjTerSimAnd( pObj ); else if ( f == 0 ) Gia_ObjTerSimSet0( pObj ); else Gia_ObjTerSimRo( p, pObj ); } } Gia_ManForEachObjVec( vMap, p, pObj, i ) pObj->Value = 0; pObj = Gia_ManPo( p, 0 ); if ( !Gia_ObjTerSimGet1(pObj) ) Abc_Print( 1, "\nRefinement verification has failed!!!\n" ); } /**Function************************************************************* Synopsis [Computes the refinement for a given counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Rnm_ManRefine( Rnm_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fNewRefinement, int fVerbose ) { int fVerify = 1; Vec_Int_t * vGoodPPis, * vNewPPis; abctime clk, clk2 = Abc_Clock(); int RetValue; p->nCalls++; // Gia_ManCleanValue( p->pGia ); // initialize p->pCex = pCex; p->vMap = vMap; p->fPropFanout = fPropFanout; p->fVerbose = fVerbose; // collects used objects Rnm_ManCollect( p ); // initialize datastructure p->nObjsFrame = 1 + Vec_IntSize(vMap) + Vec_IntSize(p->vObjs); p->nObjs = p->nObjsFrame * (pCex->iFrame + 1); if ( p->nObjs > p->nObjsAlloc ) p->pObjs = ABC_REALLOC( Rnm_Obj_t, p->pObjs, (p->nObjsAlloc = p->nObjs + 10000) ); memset( p->pObjs, 0, sizeof(Rnm_Obj_t) * p->nObjs ); // propagate priorities clk = Abc_Clock(); vGoodPPis = Vec_IntAlloc( 100 ); if ( Rnm_ManSensitize( p ) ) // the CEX is not a true CEX { p->timeFwd += Abc_Clock() - clk; // select refinement clk = Abc_Clock(); p->nVisited = 0; Rnm_ManJustify_rec( p, Gia_ObjFanin0(Gia_ManPo(p->pGia, 0)), pCex->iFrame, vGoodPPis ); RetValue = Vec_IntUniqify( vGoodPPis ); // assert( RetValue == 0 ); p->timeBwd += Abc_Clock() - clk; } // verify (empty) refinement // (only works when post-processing is not applied) if ( fVerify ) { clk = Abc_Clock(); Rnm_ManVerifyUsingTerSim( p->pGia, p->pCex, p->vMap, p->vObjs, vGoodPPis ); p->timeVer += Abc_Clock() - clk; } // at this point array vGoodPPis contains the set of important PPIs if ( Vec_IntSize(vGoodPPis) > 0 ) // spurious CEX resulting in a non-trivial refinement { // filter selected set if ( !fNewRefinement ) // default vNewPPis = Rnm_ManFilterSelected( p, vGoodPPis ); else // this is enabled when &gla is called with -r (&gla -r) vNewPPis = Rnm_ManFilterSelectedNew( p, vGoodPPis ); // replace the PPI array if necessary if ( Vec_IntSize(vNewPPis) > 0 ) // something to select, replace current refinement Vec_IntFree( vGoodPPis ), vGoodPPis = vNewPPis; else // if there is nothing to select, do not change the current refinement array Vec_IntFree( vNewPPis ); } // clean values // we cannot do this before, because we need to remember what objects // belong to the abstraction when we do Rnm_ManFilterSelected() Rnm_ManCleanValues( p ); // Vec_IntReverseOrder( vGoodPPis ); p->timeTotal += Abc_Clock() - clk2; p->nRefines += Vec_IntSize(vGoodPPis); return vGoodPPis; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absRef.h000066400000000000000000000135611300674244400233070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absRef.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Refinement manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absRef.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__proof_abs__AbsRef_h #define ABC__proof_abs__AbsRef_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Rnm_Obj_t_ Rnm_Obj_t; // refinement object struct Rnm_Obj_t_ { unsigned Value : 1; // binary value unsigned fVisit : 1; // visited object unsigned fVisitJ : 1; // justified visited object unsigned fPPi : 1; // PPI object unsigned Prio : 24; // priority (0 - highest) }; typedef struct Rnm_Man_t_ Rnm_Man_t; // refinement manager struct Rnm_Man_t_ { // user data Gia_Man_t * pGia; // working AIG manager (it is completely owned by this package) Abc_Cex_t * pCex; // counter-example Vec_Int_t * vMap; // mapping of CEX inputs into objects (PI + PPI, in any order) int fPropFanout; // propagate fanouts int fVerbose; // verbose flag int nRefId; // refinement ID // traversing data Vec_Int_t * vObjs; // internal objects used in value propagation // filtering of selected objects Vec_Str_t * vCounts; // fanin counters Vec_Int_t * vFanins; // fanins /* // SAT solver sat_solver2 * pSat; // incremental SAT solver Vec_Int_t * vSatVars; // SAT variables Vec_Int_t * vSat2Ids; // mapping of SAT variables into object IDs Vec_Int_t * vIsopMem; // memory for ISOP computation */ // internal data Rnm_Obj_t * pObjs; // refinement objects int nObjs; // the number of used objects int nObjsAlloc; // the number of allocated objects int nObjsFrame; // the number of used objects in each frame int nCalls; // total number of calls int nRefines; // total refined objects int nVisited; // visited during justification // statistics abctime timeFwd; // forward propagation abctime timeBwd; // backward propagation abctime timeVer; // ternary simulation abctime timeTotal; // other time }; // accessing the refinement object static inline Rnm_Obj_t * Rnm_ManObj( Rnm_Man_t * p, Gia_Obj_t * pObj, int f ) { assert( Gia_ObjIsConst0(pObj) || pObj->Value ); assert( (int)pObj->Value < p->nObjsFrame ); assert( f >= 0 && f <= p->pCex->iFrame ); return p->pObjs + f * p->nObjsFrame + pObj->Value; } static inline void Rnm_ManSetRefId( Rnm_Man_t * p, int RefId ) { p->nRefId = RefId; } static inline int Rnm_ObjCount( Rnm_Man_t * p, Gia_Obj_t * pObj ) { return Vec_StrEntry( p->vCounts, Gia_ObjId(p->pGia, pObj) ); } static inline void Rnm_ObjSetCount( Rnm_Man_t * p, Gia_Obj_t * pObj, int c ) { Vec_StrWriteEntry( p->vCounts, Gia_ObjId(p->pGia, pObj), (char)c ); } static inline int Rnm_ObjAddToCount( Rnm_Man_t * p, Gia_Obj_t * pObj ) { int c = Rnm_ObjCount(p, pObj); if ( c < 16 ) Rnm_ObjSetCount(p, pObj, c+1); return c; } static inline int Rnm_ObjIsJust( Rnm_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsConst0(pObj) || (pObj->Value && Rnm_ManObj(p, pObj, 0)->fVisitJ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== absRef.c ===========================================================*/ extern Rnm_Man_t * Rnm_ManStart( Gia_Man_t * pGia ); extern void Rnm_ManStop( Rnm_Man_t * p, int fProfile ); extern double Rnm_ManMemoryUsage( Rnm_Man_t * p ); extern Vec_Int_t * Rnm_ManRefine( Rnm_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fNewRefinement, int fVerbose ); /*=== absRefSelected.c ===========================================================*/ extern Vec_Int_t * Rnm_ManFilterSelected( Rnm_Man_t * p, Vec_Int_t * vOldPPis ); extern Vec_Int_t * Rnm_ManFilterSelectedNew( Rnm_Man_t * p, Vec_Int_t * vOldPPis ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absRefJ.c000066400000000000000000001007641300674244400234160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absRef2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Refinement manager to compute all justifying subsets.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absRef2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" #include "absRef2.h" ABC_NAMESPACE_IMPL_START /* Description of the refinement manager This refinement manager should be * started by calling Rf2_ManStart() this procedure takes one argument, the user's seq miter as a GIA manager - the manager should have only one property output - this manager should not change while the refinement manager is alive - it cannot be used by external applications for any purpose - when the refinement manager stop, GIA manager is the same as at the beginning - in the meantime, it will have some data-structures attached to its nodes... * stopped by calling Rf2_ManStop() * between starting and stopping, refinements are obtained by calling Rf2_ManRefine() Procedure Rf2_ManRefine() takes the following arguments: * the refinement manager previously started by Rf2_ManStart() * counter-example (CEX) obtained by abstracting some logic of GIA * mapping (vMap) of inputs of the CEX into the object IDs of the GIA manager - only PI, flop outputs, and internal AND nodes can be used in vMap - the ordering of objects in vMap is not important - however, the index of a non-PI object in vMap is used as its priority (the smaller the index, the more likely this non-PI object apears in a refinement) - only the logic between PO and the objects listed in vMap is traversed by the manager (as a result, GIA can be arbitrarily large, but only objects used in the abstraction and the pseudo-PI, that is, objects in the cut, will be visited by the manager) * flag fPropFanout defines whether value propagation is done through the fanout - it this flag is enabled, theoretically refinement should be better (the result smaller) * flag fVerbose may print some statistics The refinement manager returns a minimal-size array of integer IDs of GIA objects which should be added to the abstraction to possibly prevent the given counter-example - only flop output and internal AND nodes from vMap may appear in the resulting array - if the resulting array is empty, the CEX is a true CEX (in other words, non-PI objects are not needed to set the PO value to 1) Verification of the selected refinement is performed by - initializing all PI objects in vMap to value 0 or 1 they have in the CEX - initializing all remaining objects in vMap to value X - initializing objects used in the refiment to value 0 or 1 they have in the CEX - simulating through as many timeframes as required by the CEX - if the PO value in the last frame is 1, the refinement is correct (however, the minimality of the refinement is not currently checked) */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Rf2_Obj_t_ Rf2_Obj_t; // refinement object struct Rf2_Obj_t_ { unsigned Value : 1; // binary value unsigned fVisit : 1; // visited object unsigned fPPi : 1; // PPI object unsigned Prio : 24; // priority (0 - highest) }; struct Rf2_Man_t_ { // user data Gia_Man_t * pGia; // working AIG manager (it is completely owned by this package) Abc_Cex_t * pCex; // counter-example Vec_Int_t * vMap; // mapping of CEX inputs into objects (PI + PPI, in any order) int fPropFanout; // propagate fanouts int fVerbose; // verbose flag // traversing data Vec_Int_t * vObjs; // internal objects used in value propagation Vec_Int_t * vFanins; // fanins of the PPI nodes Vec_Int_t * pvVecs; // vectors of integers for each object Vec_Vec_t * vGrp2Ppi; // for each node, the set of PPIs to include int nMapWords; // internal data Rf2_Obj_t * pObjs; // refinement objects int nObjs; // the number of used objects int nObjsAlloc; // the number of allocated objects int nObjsFrame; // the number of used objects in each frame int nCalls; // total number of calls int nRefines; // total refined objects // statistics clock_t timeFwd; // forward propagation clock_t timeBwd; // backward propagation clock_t timeVer; // ternary simulation clock_t timeTotal; // other time }; // accessing the refinement object static inline Rf2_Obj_t * Rf2_ManObj( Rf2_Man_t * p, Gia_Obj_t * pObj, int f ) { assert( Gia_ObjIsConst0(pObj) || pObj->Value ); assert( (int)pObj->Value < p->nObjsFrame ); assert( f >= 0 && f <= p->pCex->iFrame ); return p->pObjs + f * p->nObjsFrame + pObj->Value; } static inline Vec_Int_t * Rf2_ObjVec( Rf2_Man_t * p, Gia_Obj_t * pObj ) { return p->pvVecs + Gia_ObjId(p->pGia, pObj); } static inline unsigned * Rf2_ObjA( Rf2_Man_t * p, Gia_Obj_t * pObj ) { return (unsigned *)Vec_IntArray(Rf2_ObjVec(p, pObj)); } static inline unsigned * Rf2_ObjN( Rf2_Man_t * p, Gia_Obj_t * pObj ) { return (unsigned *)Vec_IntArray(Rf2_ObjVec(p, pObj)) + p->nMapWords; } static inline void Rf2_ObjClear( Rf2_Man_t * p, Gia_Obj_t * pObj ) { Vec_IntFill( Rf2_ObjVec(p, pObj), 2*p->nMapWords, 0 ); } static inline void Rf2_ObjStart( Rf2_Man_t * p, Gia_Obj_t * pObj, int i ) { Vec_Int_t * vVec = Rf2_ObjVec(p, pObj); int w; Vec_IntClear( vVec ); for ( w = 0; w < p->nMapWords; w++ ) Vec_IntPush( vVec, 0 ); for ( w = 0; w < p->nMapWords; w++ ) Vec_IntPush( vVec, ~0 ); Abc_InfoSetBit( Rf2_ObjA(p, pObj), i ); Abc_InfoXorBit( Rf2_ObjN(p, pObj), i ); } static inline void Rf2_ObjCopy( Rf2_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) { assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 2*p->nMapWords ); memcpy( Rf2_ObjA(p, pObj), Rf2_ObjA(p, pFanin), sizeof(unsigned) * 2 * p->nMapWords ); } static inline void Rf2_ObjDeriveAnd( Rf2_Man_t * p, Gia_Obj_t * pObj, int One ) { unsigned * pInfo, * pInfo0, * pInfo1; int i; assert( Gia_ObjIsAnd(pObj) ); assert( One == (int)pObj->fMark0 ); assert( One == (int)(Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) ); assert( One == (int)(Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) ); assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 2*p->nMapWords ); pInfo = Rf2_ObjA( p, pObj ); pInfo0 = Rf2_ObjA( p, Gia_ObjFanin0(pObj) ); pInfo1 = Rf2_ObjA( p, Gia_ObjFanin1(pObj) ); for ( i = 0; i < p->nMapWords; i++ ) pInfo[i] = One ? (pInfo0[i] & pInfo1[i]) : (pInfo0[i] | pInfo1[i]); pInfo = Rf2_ObjN( p, pObj ); pInfo0 = Rf2_ObjN( p, Gia_ObjFanin0(pObj) ); pInfo1 = Rf2_ObjN( p, Gia_ObjFanin1(pObj) ); for ( i = 0; i < p->nMapWords; i++ ) pInfo[i] = One ? (pInfo0[i] | pInfo1[i]) : (pInfo0[i] & pInfo1[i]); } static inline void Rf2_ObjPrint( Rf2_Man_t * p, Gia_Obj_t * pRoot ) { Gia_Obj_t * pObj; unsigned * pInfo; int i; pInfo = Rf2_ObjA( p, pRoot ); Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) if ( !Gia_ObjIsPi(p->pGia, pObj) ) printf( "%d", Abc_InfoHasBit(pInfo, i) ); printf( "\n" ); pInfo = Rf2_ObjN( p, pRoot ); Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) if ( !Gia_ObjIsPi(p->pGia, pObj) ) printf( "%d", !Abc_InfoHasBit(pInfo, i) ); printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates a new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rf2_Man_t * Rf2_ManStart( Gia_Man_t * pGia ) { Rf2_Man_t * p; assert( Gia_ManPoNum(pGia) == 1 ); p = ABC_CALLOC( Rf2_Man_t, 1 ); p->pGia = pGia; p->vObjs = Vec_IntAlloc( 1000 ); p->vFanins = Vec_IntAlloc( 1000 ); p->pvVecs = ABC_CALLOC( Vec_Int_t, Gia_ManObjNum(pGia) ); p->vGrp2Ppi = Vec_VecStart( 100 ); Gia_ManCleanMark0(pGia); Gia_ManCleanMark1(pGia); return p; } void Rf2_ManStop( Rf2_Man_t * p, int fProfile ) { if ( !p ) return; // print runtime statistics if ( fProfile && p->nCalls ) { double MemGia = sizeof(Gia_Man_t) + sizeof(Gia_Obj_t) * p->pGia->nObjsAlloc + sizeof(int) * p->pGia->nTravIdsAlloc; double MemOther = sizeof(Rf2_Man_t) + sizeof(Rf2_Obj_t) * p->nObjsAlloc + sizeof(int) * Vec_IntCap(p->vObjs); clock_t timeOther = p->timeTotal - p->timeFwd - p->timeBwd - p->timeVer; printf( "Abstraction refinement runtime statistics:\n" ); ABC_PRTP( "Sensetization", p->timeFwd, p->timeTotal ); ABC_PRTP( "Justification", p->timeBwd, p->timeTotal ); ABC_PRTP( "Verification ", p->timeVer, p->timeTotal ); ABC_PRTP( "Other ", timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); printf( "Total calls = %d. Average refine = %.1f. GIA mem = %.3f MB. Other mem = %.3f MB.\n", p->nCalls, 1.0*p->nRefines/p->nCalls, MemGia/(1<<20), MemOther/(1<<20) ); } Vec_IntFree( p->vObjs ); Vec_IntFree( p->vFanins ); Vec_VecFree( p->vGrp2Ppi ); ABC_FREE( p->pvVecs ); ABC_FREE( p ); } double Rf2_ManMemoryUsage( Rf2_Man_t * p ) { return (double)(sizeof(Rf2_Man_t) + sizeof(Vec_Int_t) * Gia_ManObjNum(p->pGia)); } /**Function************************************************************* Synopsis [Collect internal objects to be used in value propagation.] Description [Resulting array vObjs contains RO, AND, PO/RI in a topo order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Rf2_ManCollect_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_ObjIsCo(pObj) ) Rf2_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs ); else if ( Gia_ObjIsAnd(pObj) ) { Rf2_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs ); Rf2_ManCollect_rec( p, Gia_ObjFanin1(pObj), vObjs ); } else if ( !Gia_ObjIsRo(p, pObj) ) assert( 0 ); Vec_IntPush( vObjs, Gia_ObjId(p, pObj) ); } void Rf2_ManCollect( Rf2_Man_t * p ) { Gia_Obj_t * pObj = NULL; int i; // mark const/PIs/PPIs Gia_ManIncrementTravId( p->pGia ); Gia_ObjSetTravIdCurrent( p->pGia, Gia_ManConst0(p->pGia) ); Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); Gia_ObjSetTravIdCurrent( p->pGia, pObj ); } // collect objects Vec_IntClear( p->vObjs ); Rf2_ManCollect_rec( p->pGia, Gia_ManPo(p->pGia, 0), p->vObjs ); Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i ) if ( Gia_ObjIsRo(p->pGia, pObj) ) Rf2_ManCollect_rec( p->pGia, Gia_ObjRoToRi(p->pGia, pObj), p->vObjs ); // the last object should be a CO assert( Gia_ObjIsCo(pObj) ); } /**Function************************************************************* Synopsis [Performs sensitization analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rf2_ManSensitize( Rf2_Man_t * p ) { Rf2_Obj_t * pRnm, * pRnm0, * pRnm1; Gia_Obj_t * pObj; int f, i, iBit = p->pCex->nRegs; // const0 is initialized automatically in all timeframes for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis ) { Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); pRnm = Rf2_ManObj( p, pObj, f ); pRnm->Value = Abc_InfoHasBit( p->pCex->pData, iBit + i ); if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI { assert( pObj->Value > 0 ); pRnm->Prio = pObj->Value; pRnm->fPPi = 1; } } Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i ) { assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ); pRnm = Rf2_ManObj( p, pObj, f ); assert( !pRnm->fPPi ); if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( f == 0 ) continue; pRnm0 = Rf2_ManObj( p, Gia_ObjRoToRi(p->pGia, pObj), f-1 ); pRnm->Value = pRnm0->Value; pRnm->Prio = pRnm0->Prio; continue; } if ( Gia_ObjIsCo(pObj) ) { pRnm0 = Rf2_ManObj( p, Gia_ObjFanin0(pObj), f ); pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj)); pRnm->Prio = pRnm0->Prio; continue; } assert( Gia_ObjIsAnd(pObj) ); pRnm0 = Rf2_ManObj( p, Gia_ObjFanin0(pObj), f ); pRnm1 = Rf2_ManObj( p, Gia_ObjFanin1(pObj), f ); pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) & (pRnm1->Value ^ Gia_ObjFaninC1(pObj)); if ( pRnm->Value == 1 ) pRnm->Prio = Abc_MaxInt( pRnm0->Prio, pRnm1->Prio ); else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 ) pRnm->Prio = Abc_MinInt( pRnm0->Prio, pRnm1->Prio ); // choice else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 ) pRnm->Prio = pRnm0->Prio; else pRnm->Prio = pRnm1->Prio; } } assert( iBit == p->pCex->nBits ); pRnm = Rf2_ManObj( p, Gia_ManPo(p->pGia, 0), p->pCex->iFrame ); if ( pRnm->Value != 1 ) printf( "Output value is incorrect.\n" ); return pRnm->Prio; } /**Function************************************************************* Synopsis [Performs refinement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rf2_ManVerifyUsingTerSim( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, Vec_Int_t * vObjs, Vec_Int_t * vRes ) { Gia_Obj_t * pObj; int i, f, iBit = pCex->nRegs; Gia_ObjTerSimSet0( Gia_ManConst0(p) ); for ( f = 0; f <= pCex->iFrame; f++, iBit += pCex->nPis ) { Gia_ManForEachObjVec( vMap, p, pObj, i ) { pObj->Value = Abc_InfoHasBit( pCex->pData, iBit + i ); if ( !Gia_ObjIsPi(p, pObj) ) Gia_ObjTerSimSetX( pObj ); else if ( pObj->Value ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); } Gia_ManForEachObjVec( vRes, p, pObj, i ) // vRes is subset of vMap { if ( pObj->Value ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); } Gia_ManForEachObjVec( vObjs, p, pObj, i ) { if ( Gia_ObjIsCo(pObj) ) Gia_ObjTerSimCo( pObj ); else if ( Gia_ObjIsAnd(pObj) ) Gia_ObjTerSimAnd( pObj ); else if ( f == 0 ) Gia_ObjTerSimSet0( pObj ); else Gia_ObjTerSimRo( p, pObj ); } } Gia_ManForEachObjVec( vMap, p, pObj, i ) pObj->Value = 0; pObj = Gia_ManPo( p, 0 ); if ( !Gia_ObjTerSimGet1(pObj) ) Abc_Print( 1, "\nRefinement verification has failed!!!\n" ); } /**Function************************************************************* Synopsis [Computes the refinement for a given counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rf2_ManGatherFanins_rec( Rf2_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vFanins, int Depth, int RootId, int fFirst ) { if ( Gia_ObjIsTravIdCurrent(p->pGia, pObj) ) return; Gia_ObjSetTravIdCurrent(p->pGia, pObj); if ( pObj->fPhase && !fFirst ) { Vec_Int_t * vVec = Rf2_ObjVec( p, pObj ); // if ( Vec_IntEntry( vVec, 0 ) == 0 ) // return; if ( Vec_IntSize(vVec) == 0 ) Vec_IntPush( vFanins, Gia_ObjId(p->pGia, pObj) ); Vec_IntPushUnique( vVec, RootId ); if ( Depth == 0 ) return; } if ( Gia_ObjIsPi(p->pGia, pObj) || Gia_ObjIsConst0(pObj) ) return; if ( Gia_ObjIsRo(p->pGia, pObj) ) { assert( pObj->fPhase ); pObj = Gia_ObjRoToRi(p->pGia, pObj); Rf2_ManGatherFanins_rec( p, Gia_ObjFanin0(pObj), vFanins, Depth - 1, RootId, 0 ); } else if ( Gia_ObjIsAnd(pObj) ) { Rf2_ManGatherFanins_rec( p, Gia_ObjFanin0(pObj), vFanins, Depth - pObj->fPhase, RootId, 0 ); Rf2_ManGatherFanins_rec( p, Gia_ObjFanin1(pObj), vFanins, Depth - pObj->fPhase, RootId, 0 ); } else assert( 0 ); } void Rf2_ManGatherFanins( Rf2_Man_t * p, int Depth ) { Vec_Int_t * vUsed; Vec_Int_t * vVec; Gia_Obj_t * pObj; int i, k, Entry; // mark PPIs Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { vVec = Rf2_ObjVec( p, pObj ); assert( Vec_IntSize(vVec) == 0 ); Vec_IntPush( vVec, 0 ); } // collect internal Vec_IntClear( p->vFanins ); Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { if ( Gia_ObjIsPi(p->pGia, pObj) ) continue; Gia_ManIncrementTravId( p->pGia ); Rf2_ManGatherFanins_rec( p, pObj, p->vFanins, Depth, i, 1 ); } vUsed = Vec_IntStart( Vec_IntSize(p->vMap) ); // evaluate collected printf( "\nMap (%d): ", Vec_IntSize(p->vMap) ); Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { vVec = Rf2_ObjVec( p, pObj ); if ( Vec_IntSize(vVec) > 1 ) printf( "%d=%d ", i, Vec_IntSize(vVec) - 1 ); Vec_IntForEachEntryStart( vVec, Entry, k, 1 ) Vec_IntAddToEntry( vUsed, Entry, 1 ); Vec_IntClear( vVec ); } printf( "\n" ); // evaluate internal printf( "Int (%d): ", Vec_IntSize(p->vFanins) ); Gia_ManForEachObjVec( p->vFanins, p->pGia, pObj, i ) { vVec = Rf2_ObjVec( p, pObj ); if ( Vec_IntSize(vVec) > 1 ) printf( "%d=%d ", i, Vec_IntSize(vVec) ); if ( Vec_IntSize(vVec) > 1 ) Vec_IntForEachEntry( vVec, Entry, k ) Vec_IntAddToEntry( vUsed, Entry, 1 ); Vec_IntClear( vVec ); } printf( "\n" ); // evaluate PPIs Vec_IntForEachEntry( vUsed, Entry, k ) printf( "%d ", Entry ); printf( "\n" ); Vec_IntFree( vUsed ); } /**Function************************************************************* Synopsis [Sort, make dup- and containment-free, and filter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Rf2_ManCountPpis( Rf2_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI Counter++; return Counter; } /**Function************************************************************* Synopsis [Sort, make dup- and containment-free, and filter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Rf2_ManPrintVector( Vec_Int_t * p, int Num ) { int i, k, Entry; Vec_IntForEachEntry( p, Entry, i ) { for ( k = 0; k < Num; k++ ) printf( "%c", '0' + ((Entry>>k) & 1) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Sort, make dup- and containment-free, and filter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Rf2_ManProcessVector( Vec_Int_t * p, int Limit ) { // int Start = Vec_IntSize(p); int Start = 0; int i, j, k, Entry, Entry2; // printf( "%d", Vec_IntSize(p) ); if ( Start > 5 ) { printf( "Before: \n" ); Rf2_ManPrintVector( p, 31 ); } k = 0; Vec_IntForEachEntry( p, Entry, i ) if ( Gia_WordCountOnes((unsigned)Entry) <= Limit ) Vec_IntWriteEntry( p, k++, Entry ); Vec_IntShrink( p, k ); Vec_IntSort( p, 0 ); k = 0; Vec_IntForEachEntry( p, Entry, i ) { Vec_IntForEachEntryStop( p, Entry2, j, i ) if ( (Entry2 & Entry) == Entry2 ) // Entry2 is a subset of Entry break; if ( j == i ) // Entry is not contained in any Entry2 Vec_IntWriteEntry( p, k++, Entry ); } Vec_IntShrink( p, k ); // printf( "->%d ", Vec_IntSize(p) ); if ( Start > 5 ) { printf( "After: \n" ); Rf2_ManPrintVector( p, 31 ); k = 0; } } /**Function************************************************************* Synopsis [Assigns a unique justifification ID for each PPI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rf2_ManAssignJustIds( Rf2_Man_t * p ) { Gia_Obj_t * pObj; int nPpis = Rf2_ManCountPpis( p ); int nGroupSize = (nPpis / 30) + (nPpis % 30 > 0); int i, k = 0; Vec_VecClear( p->vGrp2Ppi ); Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI Vec_VecPushInt( p->vGrp2Ppi, (k++ / nGroupSize), i ); printf( "Considering %d PPIs combined into %d groups of size %d.\n", k, (k-1)/nGroupSize+1, nGroupSize ); return (k-1)/nGroupSize+1; } /**Function************************************************************* Synopsis [Sort, make dup- and containment-free, and filter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Rf2_ManPrintVectorSpecial( Rf2_Man_t * p, Vec_Int_t * vVec ) { Gia_Obj_t * pObj; int nPpis = Rf2_ManCountPpis( p ); int nGroupSize = (nPpis / 30) + (nPpis % 30 > 0); int s, i, k, Entry, Counter; Vec_IntForEachEntry( vVec, Entry, s ) { k = 0; Counter = 0; Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI { if ( (Entry >> (k++ / nGroupSize)) & 1 ) printf( "1" ), Counter++; else printf( "0" ); } else printf( "-" ); } printf( " %3d \n", Counter ); } } /**Function************************************************************* Synopsis [Performs justification propagation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Rf2_ManPropagate( Rf2_Man_t * p, int Limit ) { Vec_Int_t * vVec, * vVec0, * vVec1; Gia_Obj_t * pObj; int f, i, k, j, Entry, Entry2, iBit = p->pCex->nRegs; // init constant pObj = Gia_ManConst0(p->pGia); pObj->fMark0 = 0; Vec_IntFill( Rf2_ObjVec(p, pObj), 1, 0 ); // iterate through the timeframes for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis ) { // initialize frontier values and init justification sets Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); pObj->fMark0 = Abc_InfoHasBit( p->pCex->pData, iBit + i ); Vec_IntFill( Rf2_ObjVec(p, pObj), 1, 0 ); } // assign justification sets for PPis Vec_VecForEachLevelInt( p->vGrp2Ppi, vVec, i ) Vec_IntForEachEntry( vVec, Entry, k ) { assert( i < 31 ); pObj = Gia_ManObj( p->pGia, Vec_IntEntry(p->vMap, Entry) ); assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 1 ); Vec_IntAddToEntry( Rf2_ObjVec(p, pObj), 0, (1 << i) ); } // propagate internal nodes Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i ) { pObj->fMark0 = 0; vVec = Rf2_ObjVec(p, pObj); Vec_IntClear( vVec ); if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( f == 0 ) { Vec_IntPush( vVec, 0 ); continue; } pObj->fMark0 = Gia_ObjRoToRi(p->pGia, pObj)->fMark0; vVec0 = Rf2_ObjVec( p, Gia_ObjRoToRi(p->pGia, pObj) ); Vec_IntAppend( vVec, vVec0 ); continue; } if ( Gia_ObjIsCo(pObj) ) { pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)); vVec0 = Rf2_ObjVec( p, Gia_ObjFanin0(pObj) ); Vec_IntAppend( vVec, vVec0 ); continue; } assert( Gia_ObjIsAnd(pObj) ); vVec0 = Rf2_ObjVec(p, Gia_ObjFanin0(pObj)); vVec1 = Rf2_ObjVec(p, Gia_ObjFanin1(pObj)); pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); if ( pObj->fMark0 == 1 ) { Vec_IntForEachEntry( vVec0, Entry, k ) Vec_IntForEachEntry( vVec1, Entry2, j ) Vec_IntPush( vVec, Entry | Entry2 ); Rf2_ManProcessVector( vVec, Limit ); } else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 ) { Vec_IntAppend( vVec, vVec0 ); Vec_IntAppend( vVec, vVec1 ); Rf2_ManProcessVector( vVec, Limit ); } else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 ) Vec_IntAppend( vVec, vVec0 ); else Vec_IntAppend( vVec, vVec1 ); } } assert( iBit == p->pCex->nBits ); if ( Gia_ManPo(p->pGia, 0)->fMark0 != 1 ) printf( "Output value is incorrect.\n" ); return Rf2_ObjVec(p, Gia_ManPo(p->pGia, 0)); } /**Function************************************************************* Synopsis [Performs justification propagation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rf2_ManBounds( Rf2_Man_t * p ) { Gia_Obj_t * pObj; int f, i, iBit = p->pCex->nRegs; // init constant pObj = Gia_ManConst0(p->pGia); pObj->fMark0 = 0; Rf2_ObjStart( p, pObj, Vec_IntSize(p->vMap) + Vec_IntSize(p->vObjs) ); // iterate through the timeframes for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis ) { // initialize frontier values and init justification sets Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) { assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); pObj->fMark0 = Abc_InfoHasBit( p->pCex->pData, iBit + i ); Rf2_ObjStart( p, pObj, i ); } // propagate internal nodes Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i ) { pObj->fMark0 = 0; Rf2_ObjClear( p, pObj ); if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( f == 0 ) { Rf2_ObjStart( p, pObj, Vec_IntSize(p->vMap) + i ); continue; } pObj->fMark0 = Gia_ObjRoToRi(p->pGia, pObj)->fMark0; Rf2_ObjCopy( p, pObj, Gia_ObjRoToRi(p->pGia, pObj) ); continue; } if ( Gia_ObjIsCo(pObj) ) { pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)); Rf2_ObjCopy( p, pObj, Gia_ObjFanin0(pObj) ); continue; } assert( Gia_ObjIsAnd(pObj) ); pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); if ( pObj->fMark0 == 1 ) Rf2_ObjDeriveAnd( p, pObj, 1 ); else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 ) Rf2_ObjDeriveAnd( p, pObj, 0 ); else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 ) Rf2_ObjCopy( p, pObj, Gia_ObjFanin0(pObj) ); else Rf2_ObjCopy( p, pObj, Gia_ObjFanin1(pObj) ); } } assert( iBit == p->pCex->nBits ); if ( Gia_ManPo(p->pGia, 0)->fMark0 != 1 ) printf( "Output value is incorrect.\n" ); printf( "Bounds: \n" ); Rf2_ObjPrint( p, Gia_ManPo(p->pGia, 0) ); } /**Function************************************************************* Synopsis [Computes the refinement for a given counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Rf2_ManRefine( Rf2_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fVerbose ) { Vec_Int_t * vJusts; // Vec_Int_t * vSelected = Vec_IntAlloc( 100 ); Vec_Int_t * vSelected = NULL; clock_t clk, clk2 = clock(); int nGroups; p->nCalls++; // initialize p->pCex = pCex; p->vMap = vMap; p->fPropFanout = fPropFanout; p->fVerbose = fVerbose; // collects used objects Rf2_ManCollect( p ); // collect reconvergence points // Rf2_ManGatherFanins( p, 2 ); // propagate justification IDs nGroups = Rf2_ManAssignJustIds( p ); vJusts = Rf2_ManPropagate( p, 32 ); // printf( "\n" ); // Rf2_ManPrintVector( vJusts, nGroups ); Rf2_ManPrintVectorSpecial( p, vJusts ); if ( Vec_IntSize(vJusts) == 0 ) { printf( "Empty set of justifying subsets.\n" ); return NULL; } // p->nMapWords = Abc_BitWordNum( Vec_IntSize(p->vMap) + Vec_IntSize(p->vObjs) + 1 ); // Map + Flops + Const // Rf2_ManBounds( p ); // select the result // Abc_PrintTime( 1, "Time", clock() - clk2 ); // verify (empty) refinement clk = clock(); // Rf2_ManVerifyUsingTerSim( p->pGia, p->pCex, p->vMap, p->vObjs, vSelected ); // Vec_IntUniqify( vSelected ); // Vec_IntReverseOrder( vSelected ); p->timeVer += clock() - clk; p->timeTotal += clock() - clk2; // p->nRefines += Vec_IntSize(vSelected); return vSelected; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absRefJ.h000066400000000000000000000046061300674244400234210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absRef2.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Refinement manager to compute all justifying subsets.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absRef2.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__proof_abs__AbsRef2_h #define ABC__proof_abs__AbsRef2_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Rf2_Man_t_ Rf2_Man_t; // refinement manager //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== giaAbsRef.c ===========================================================*/ extern Rf2_Man_t * Rf2_ManStart( Gia_Man_t * pGia ); extern void Rf2_ManStop( Rf2_Man_t * p, int fProfile ); extern double Rf2_ManMemoryUsage( Rf2_Man_t * p ); extern Vec_Int_t * Rf2_ManRefine( Rf2_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absRefSelect.c000066400000000000000000000257571300674244400244540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absRefSelect.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Post-processes the set of selected refinement objects.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absRefSelect.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" #include "absRef.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rnm_ManPrintSelected( Rnm_Man_t * p, Vec_Int_t * vNewPPis ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i ) if ( Gia_ObjIsPi(p->pGia, pObj) ) printf( "-" ); else if ( Vec_IntFind(vNewPPis, Gia_ObjId(p->pGia, pObj)) >= 0 )// this is PPI printf( "1" ), Counter++; else printf( "0" ); printf( " %3d\n", Counter ); } /**Function************************************************************* Synopsis [Perform structural analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ga2_StructAnalize( Gia_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInter, Vec_Int_t * vNewPPis ) { Vec_Int_t * vFanins; Gia_Obj_t * pObj, * pFanin; int i, k; // clean labels Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = pObj->fMark1 = 0; // label frontier Gia_ManForEachObjVec( vFront, p, pObj, i ) pObj->fMark0 = 1, pObj->fMark1 = 0; // label objects Gia_ManForEachObjVec( vInter, p, pObj, i ) pObj->fMark1 = 0, pObj->fMark1 = 1; // label selected Gia_ManForEachObjVec( vNewPPis, p, pObj, i ) pObj->fMark1 = 1, pObj->fMark1 = 1; // explore selected Gia_ManForEachObjVec( vNewPPis, p, pObj, i ) { printf( "Selected PPI %3d : ", i+1 ); printf( "%6d ", Gia_ObjId(p, pObj) ); printf( "\n" ); vFanins = Ga2_ObjLeaves( p, pObj ); Gia_ManForEachObjVec( vFanins, p, pFanin, k ) { printf( " " ); printf( "%6d ", Gia_ObjId(p, pFanin) ); if ( pFanin->fMark0 && pFanin->fMark1 ) printf( "selected PPI" ); else if ( pFanin->fMark0 && !pFanin->fMark1 ) printf( "frontier (original PI or PPI)" ); else if ( !pFanin->fMark0 && pFanin->fMark1 ) printf( "abstracted node" ); else if ( !pFanin->fMark0 && !pFanin->fMark1 ) printf( "free variable" ); printf( "\n" ); } } } /**Function************************************************************* Synopsis [Postprocessing the set of PPIs using structural analysis.] Description [The following sets are used: The set of all PI+PPI is in p->vMap. The set of all abstracted objects is in p->vObjs; The set of important PPIs is in vOldPPis. The new set of selected PPIs is in vNewPPis.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Rnm_ManFilterSelected( Rnm_Man_t * p, Vec_Int_t * vOldPPis ) { int fVerbose = 0; Vec_Int_t * vNewPPis, * vFanins; Gia_Obj_t * pObj, * pFanin; int i, k, RetValue, Counters[3] = {0}; // (0) make sure fanin counters are 0 at the beginning // Gia_ManForEachObj( p->pGia, pObj, i ) // assert( Rnm_ObjCount(p, pObj) == 0 ); // (1) increment PPI fanin counters Vec_IntClear( p->vFanins ); Gia_ManForEachObjVec( vOldPPis, p->pGia, pObj, i ) { vFanins = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vFanins, p->pGia, pFanin, k ) if ( Rnm_ObjAddToCount(p, pFanin) == 0 ) // fanin counter is 0 -- save it Vec_IntPush( p->vFanins, Gia_ObjId(p->pGia, pFanin) ); } // (3) select objects with reconvergence, which create potential constraints // - flop objects // - objects whose fanin belongs to the justified area // - objects whose fanins overlap // (these do not guantee reconvergence, but may potentially have it) // (other objects cannot have reconvergence, even if they are added) vNewPPis = Vec_IntAlloc( 100 ); Gia_ManForEachObjVec( vOldPPis, p->pGia, pObj, i ) { if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( fVerbose ) Counters[0]++; Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) ); continue; } vFanins = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vFanins, p->pGia, pFanin, k ) { if ( Rnm_ObjIsJust(p, pFanin) || Rnm_ObjCount(p, pFanin) > 1 ) { if ( fVerbose ) Counters[1] += Rnm_ObjIsJust(p, pFanin); if ( fVerbose ) Counters[2] += (Rnm_ObjCount(p, pFanin) > 1); Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) ); break; } } } RetValue = Vec_IntUniqify( vNewPPis ); assert( RetValue == 0 ); // (4) clear fanin counters // this is important for counters to be correctly set in the future iterations -- see step (0) Gia_ManForEachObjVec( p->vFanins, p->pGia, pObj, i ) Rnm_ObjSetCount( p, pObj, 0 ); // visualize if ( fVerbose ) printf( "*** Refinement %3d : PI+PPI =%4d. Old =%4d. New =%4d. FF =%4d. Just =%4d. Shared =%4d.\n", p->nRefId, Vec_IntSize(p->vMap), Vec_IntSize(vOldPPis), Vec_IntSize(vNewPPis), Counters[0], Counters[1], Counters[2] ); // Rnm_ManPrintSelected( p, vNewPPis ); // Ga2_StructAnalize( p->pGia, p->vMap, p->vObjs, vNewPPis ); return vNewPPis; } /**Function************************************************************* Synopsis [Improved postprocessing the set of PPIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Rnm_ManFilterSelectedNew( Rnm_Man_t * p, Vec_Int_t * vOldPPis ) { static int Counter = 0; int fVerbose = 0; Vec_Int_t * vNewPPis, * vFanins, * vFanins2; Gia_Obj_t * pObj, * pFanin, * pFanin2; int i, k, k2, RetValue, Counters[3] = {0}; // return full set of PPIs once in a while if ( ++Counter % 9 == 0 ) return Vec_IntDup( vOldPPis ); return Rnm_ManFilterSelected( p, vOldPPis ); // (0) make sure fanin counters are 0 at the beginning // Gia_ManForEachObj( p->pGia, pObj, i ) // assert( Rnm_ObjCount(p, pObj) == 0 ); // (1) increment two levels of PPI fanin counters Vec_IntClear( p->vFanins ); Gia_ManForEachObjVec( vOldPPis, p->pGia, pObj, i ) { // go through the fanins vFanins = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vFanins, p->pGia, pFanin, k ) { Rnm_ObjAddToCount(p, pFanin); if ( Rnm_ObjIsJust(p, pFanin) ) // included in the abstraction Rnm_ObjAddToCount(p, pFanin); // count it second time! Vec_IntPush( p->vFanins, Gia_ObjId(p->pGia, pFanin) ); // go through the fanins of the fanins vFanins2 = Ga2_ObjLeaves( p->pGia, pFanin ); Gia_ManForEachObjVec( vFanins2, p->pGia, pFanin2, k2 ) { Rnm_ObjAddToCount(p, pFanin2); if ( Rnm_ObjIsJust(p, pFanin2) ) // included in the abstraction Rnm_ObjAddToCount(p, pFanin2); // count it second time! Vec_IntPush( p->vFanins, Gia_ObjId(p->pGia, pFanin2) ); } } } // (3) select objects with reconvergence, which create potential constraints // - flop objects - yes // - objects whose fanin (or fanins' fanin) belongs to the justified area - yes // - objects whose fanins (or fanins' fanin) overlap - yes // (these do not guantee reconvergence, but may potentially have it) // (other objects cannot have reconvergence, even if they are added) vNewPPis = Vec_IntAlloc( 100 ); Gia_ManForEachObjVec( vOldPPis, p->pGia, pObj, i ) { if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( fVerbose ) Counters[0]++; Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) ); continue; } // go through the first fanins vFanins = Ga2_ObjLeaves( p->pGia, pObj ); Gia_ManForEachObjVec( vFanins, p->pGia, pFanin, k ) { if ( Rnm_ObjCount(p, pFanin) > 1 ) Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) ); continue; // go through the fanins of the fanins vFanins2 = Ga2_ObjLeaves( p->pGia, pFanin ); Gia_ManForEachObjVec( vFanins2, p->pGia, pFanin2, k2 ) { if ( Rnm_ObjCount(p, pFanin2) > 1 ) { // Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pFanin) ); Vec_IntPush( vNewPPis, Gia_ObjId(p->pGia, pObj) ); } } } } RetValue = Vec_IntUniqify( vNewPPis ); // assert( RetValue == 0 ); // we will have duplicated entries here! // (4) clear fanin counters // this is important for counters to be correctly set in the future iterations -- see step (0) Gia_ManForEachObjVec( p->vFanins, p->pGia, pObj, i ) Rnm_ObjSetCount( p, pObj, 0 ); // visualize if ( fVerbose ) printf( "*** Refinement %3d : PI+PPI =%4d. Old =%4d. New =%4d. FF =%4d. Just =%4d. Shared =%4d.\n", p->nRefId, Vec_IntSize(p->vMap), Vec_IntSize(vOldPPis), Vec_IntSize(vNewPPis), Counters[0], Counters[1], Counters[2] ); // Rnm_ManPrintSelected( p, vNewPPis ); // Ga2_StructAnalize( p->pGia, p->vMap, p->vObjs, vNewPPis ); return vNewPPis; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absRpm.c000066400000000000000000000664021300674244400233260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absRpm.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Structural reparameterization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absRpm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" #include "misc/vec/vecWec.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); } static int Abs_ManSupport2( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ); static int Abs_GiaObjDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode ); static int Abs_GiaObjRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// 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 [] ***********************************************************************/ 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) ); } 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 ( pObj->fMark1 || (p->pRefs && Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p, pObj) == 0) ) 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Gia_ManCreateSupps( Gia_Man_t * p, int fVerbose ) { abctime clk = Abc_Clock(); Gia_Obj_t * pObj; int i, Id; 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(vSupps, Gia_ObjId(p, pObj)), Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); if ( fVerbose ) Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); return vSupps; } void Gia_ManDomTest( Gia_Man_t * p ) { Vec_Int_t * vDoms = Vec_IntAlloc( 100 ); Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); Vec_Wec_t * vSupps = Gia_ManCreateSupps( p, 1 ); Vec_Wec_t * vDomeds = Vec_WecStart( Gia_ManObjNum(p) ); Gia_Obj_t * pObj, * pDom; int i, Id, nMffcSize; Gia_ManCreateRefs( p ); Gia_ManComputeDoms( p ); Gia_ManForEachCi( p, pObj, i ) { if ( Gia_ObjDom(p, pObj) == -1 ) continue; for ( pDom = Gia_ManObj(p, Gia_ObjDom(p, pObj)); Gia_ObjIsAnd(pDom); pDom = Gia_ManObj(p, Gia_ObjDom(p, pDom)) ) Vec_IntPush( Vec_WecEntry(vDomeds, Gia_ObjId(p, pDom)), i ); } Gia_ManForEachAnd( p, pObj, i ) if ( Vec_IntEqual(Vec_WecEntry(vSupps, i), Vec_WecEntry(vDomeds, i)) ) Vec_IntPush( vDoms, i ); Vec_WecFree( vSupps ); Vec_WecFree( vDomeds ); // check MFFC sizes Vec_IntForEachEntry( vDoms, Id, i ) Gia_ObjRefInc( p, Gia_ManObj(p, Id) ); Vec_IntForEachEntry( vDoms, Id, i ) { nMffcSize = Gia_NodeMffcSizeSupp( p, Gia_ManObj(p, Id), vSupp ); printf( "%d(%d:%d) ", Id, Vec_IntSize(vSupp), nMffcSize ); } printf( "\n" ); Vec_IntForEachEntry( vDoms, Id, i ) Gia_ObjRefDec( p, Gia_ManObj(p, Id) ); // Vec_IntPrint( vDoms ); Vec_IntFree( vDoms ); Vec_IntFree( vSupp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTestDoms2( Gia_Man_t * p ) { Vec_Int_t * vNodes; Gia_Obj_t * pObj, * pDom; abctime clk = Abc_Clock(); int i; assert( p->vDoms == NULL ); Gia_ManComputeDoms( p ); /* Gia_ManForEachPi( p, pObj, i ) if ( Gia_ObjId(p, pObj) != Gia_ObjDom(p, pObj) ) printf( "PI =%6d Id =%8d. Dom =%8d.\n", i, Gia_ObjId(p, pObj), Gia_ObjDom(p, pObj) ); */ Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // for each dominated PI, when if the PIs is in a leaf of the MFFC of the dominator Gia_ManCleanMark1( p ); Gia_ManForEachPi( p, pObj, i ) pObj->fMark1 = 1; vNodes = Vec_IntAlloc( 100 ); Gia_ManCreateRefs( p ); Gia_ManForEachPi( p, pObj, i ) { if ( Gia_ObjId(p, pObj) == Gia_ObjDom(p, pObj) ) continue; pDom = Gia_ManObj(p, Gia_ObjDom(p, pObj)); if ( Gia_ObjIsCo(pDom) ) { assert( Gia_ObjFanin0(pDom) == pObj ); continue; } assert( Gia_ObjIsAnd(pDom) ); Abs_GiaObjDeref_rec( p, pDom ); Abs_ManSupport2( p, pDom, vNodes ); Abs_GiaObjRef_rec( p, pDom ); if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) == -1 ) printf( "FAILURE.\n" ); // else // printf( "Success.\n" ); } Vec_IntFree( vNodes ); Gia_ManCleanMark1( p ); } /**Function************************************************************* Synopsis [Collect PI doms.] Description [Assumes that some PIs and ANDs are marked with fMark1.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCollectDoms( Gia_Man_t * p ) { Vec_Int_t * vNodes; Gia_Obj_t * pObj; int Lev, LevMax = ABC_INFINITY; int i, iDom, iDomNext; vNodes = Vec_IntAlloc( 100 ); Gia_ManForEachObj( p, pObj, i ) { if ( !pObj->fMark1 ) continue; if ( p->pRefs && Gia_ObjRefNum(p, pObj) == 0 ) continue; iDom = Gia_ObjDom(p, pObj); if ( iDom == -1 ) continue; if ( iDom == i ) continue; for ( Lev = 0; Lev < LevMax && Gia_ObjIsAnd( Gia_ManObj(p, iDom) ); Lev++ ) { Vec_IntPush( vNodes, iDom ); iDomNext = Gia_ObjDom( p, Gia_ManObj(p, iDom) ); if ( iDomNext == iDom ) break; iDom = iDomNext; } } Vec_IntUniqify( vNodes ); return vNodes; } Vec_Int_t * Gia_ManComputePiDoms( Gia_Man_t * p ) { Vec_Int_t * vNodes; Gia_ManComputeDoms( p ); vNodes = Gia_ManCollectDoms( p ); // Vec_IntPrint( vNodes ); return vNodes; } void Gia_ManTestDoms( Gia_Man_t * p ) { Vec_Int_t * vNodes; Gia_Obj_t * pObj; int i; // mark PIs // Gia_ManCreateRefs( p ); Gia_ManCleanMark1( p ); Gia_ManForEachPi( p, pObj, i ) pObj->fMark1 = 1; // compute dominators assert( p->vDoms == NULL ); vNodes = Gia_ManComputePiDoms( p ); // printf( "Nodes = %d. Doms = %d.\n", Gia_ManAndNum(p), Vec_IntSize(vNodes) ); Vec_IntFree( vNodes ); // unmark PIs Gia_ManCleanMark1( p ); } /**Function************************************************************* Synopsis [Counts flops without fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCountFanoutlessFlops( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; int Counter = 0; Gia_ManCreateRefs( p ); Gia_ManForEachRo( p, pObj, i ) if ( Gia_ObjRefNum(p, pObj) == 0 ) Counter++; printf( "Fanoutless flops = %d.\n", Counter ); ABC_FREE( p->pRefs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCountPisNodes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPis, Vec_Int_t * vAnds ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( pObj->fMark1 ) { Vec_IntPush( vPis, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManCountPisNodes_rec( p, Gia_ObjFanin0(pObj), vPis, vAnds ); Gia_ManCountPisNodes_rec( p, Gia_ObjFanin1(pObj), vPis, vAnds ); Vec_IntPush( vAnds, Gia_ObjId(p, pObj) ); } void Gia_ManCountPisNodes( Gia_Man_t * p, Vec_Int_t * vPis, Vec_Int_t * vAnds ) { Gia_Obj_t * pObj; int i; // mark const0 and flop output Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachRo( p, pObj, i ) Gia_ObjSetTravIdCurrent( p, pObj ); // count PIs and internal nodes reachable from COs Vec_IntClear( vPis ); Vec_IntClear( vAnds ); Gia_ManForEachCo( p, pObj, i ) Gia_ManCountPisNodes_rec( p, Gia_ObjFanin0(pObj), vPis, vAnds ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abs_GiaObjDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) { Gia_Obj_t * pFanin; int Counter = 0; if ( pNode->fMark1 || Gia_ObjIsRo(p, pNode) ) return 0; assert( Gia_ObjIsAnd(pNode) ); pFanin = Gia_ObjFanin0(pNode); assert( Gia_ObjRefNum(p, pFanin) > 0 ); if ( Gia_ObjRefDec(p, pFanin) == 0 ) Counter += Abs_GiaObjDeref_rec( p, pFanin ); pFanin = Gia_ObjFanin1(pNode); assert( Gia_ObjRefNum(p, pFanin) > 0 ); if ( Gia_ObjRefDec(p, pFanin) == 0 ) Counter += Abs_GiaObjDeref_rec( p, pFanin ); return Counter + 1; } int Abs_GiaObjRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) { Gia_Obj_t * pFanin; int Counter = 0; if ( pNode->fMark1 || Gia_ObjIsRo(p, pNode) ) return 0; assert( Gia_ObjIsAnd(pNode) ); pFanin = Gia_ObjFanin0(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) Counter += Abs_GiaObjRef_rec( p, pFanin ); pFanin = Gia_ObjFanin1(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) Counter += Abs_GiaObjRef_rec( p, pFanin ); return Counter + 1; } /**Function************************************************************* Synopsis [Returns the number of nodes with zero refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abs_GiaSortNodes( Gia_Man_t * p, Vec_Int_t * vSupp ) { Gia_Obj_t * pObj; int nSize = Vec_IntSize(vSupp); int i, RetValue; Gia_ManForEachObjVec( vSupp, p, pObj, i ) if ( i < nSize && Gia_ObjRefNum(p, pObj) == 0 && !Gia_ObjIsRo(p, pObj) ) // add removable leaves { assert( pObj->fMark1 ); Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); } RetValue = Vec_IntSize(vSupp) - nSize; Gia_ManForEachObjVec( vSupp, p, pObj, i ) if ( i < nSize && !(Gia_ObjRefNum(p, pObj) == 0 && !Gia_ObjIsRo(p, pObj)) ) // add non-removable leaves Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); assert( Vec_IntSize(vSupp) == 2 * nSize ); memmove( Vec_IntArray(vSupp), Vec_IntArray(vSupp) + nSize, sizeof(int) * nSize ); Vec_IntShrink( vSupp, nSize ); return RetValue; } /**Function************************************************************* Synopsis [Computes support in terms of PIs and flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abs_ManSupport1_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( pObj->fMark1 || Gia_ObjIsRo(p, pObj) ) { Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Abs_ManSupport1_rec( p, Gia_ObjFanin0(pObj), vSupp ); Abs_ManSupport1_rec( p, Gia_ObjFanin1(pObj), vSupp ); } int Abs_ManSupport1( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) { assert( Gia_ObjIsAnd(pObj) ); Vec_IntClear( vSupp ); Gia_ManIncrementTravId( p ); Abs_ManSupport1_rec( p, pObj, vSupp ); return Vec_IntSize(vSupp); } /**Function************************************************************* Synopsis [Computes support of the MFFC.] Description [Should be called when pObj's cone is dereferenced.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abs_ManSupport2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( pObj->fMark1 || Gia_ObjIsRo(p, pObj) || Gia_ObjRefNum(p, pObj) > 0 ) { Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Abs_ManSupport2_rec( p, Gia_ObjFanin0(pObj), vSupp ); Abs_ManSupport2_rec( p, Gia_ObjFanin1(pObj), vSupp ); } int Abs_ManSupport2( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) { assert( Gia_ObjIsAnd(pObj) ); Vec_IntClear( vSupp ); Gia_ManIncrementTravId( p ); Abs_ManSupport2_rec( p, Gia_ObjFanin0(pObj), vSupp ); Abs_ManSupport2_rec( p, Gia_ObjFanin1(pObj), vSupp ); Gia_ObjSetTravIdCurrent(p, pObj); return Vec_IntSize(vSupp); } /**Function************************************************************* Synopsis [Computes support of the extended MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abs_ManSupport3( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) { Gia_Obj_t * pTemp, * pFan0, * pFan1; int i, nSize0; // collect MFFC Abs_ManSupport2( p, pObj, vSupp ); // move dominated to the front nSize0 = Abs_GiaSortNodes( p, vSupp ); assert( nSize0 > 0 ); // consider remaining nodes while ( 1 ) { int fChanges = 0; Gia_ManForEachObjVec( vSupp, p, pTemp, i ) { if ( i < nSize0 ) continue; if ( !Gia_ObjIsAnd(pTemp) ) continue; assert( !pTemp->fMark1 ); assert( Gia_ObjRefNum(p, pTemp) > 0 ); pFan0 = Gia_ObjFanin0(pTemp); pFan1 = Gia_ObjFanin1(pTemp); if ( Gia_ObjIsTravIdCurrent(p, pFan0) && Gia_ObjIsTravIdCurrent(p, pFan1) ) { Vec_IntRemove( vSupp, Gia_ObjId(p, pTemp) ); fChanges = 1; break; } if ( Gia_ObjIsTravIdCurrent(p, pFan0) ) { Vec_IntRemove( vSupp, Gia_ObjId(p, pTemp) ); Vec_IntPush( vSupp, Gia_ObjId(p, pFan1) ); assert( !Gia_ObjIsTravIdCurrent(p, pFan1) ); Gia_ObjSetTravIdCurrent(p, pFan1); fChanges = 1; break; } if ( Gia_ObjIsTravIdCurrent(p, pFan1) ) { Vec_IntRemove( vSupp, Gia_ObjId(p, pTemp) ); Vec_IntPush( vSupp, Gia_ObjId(p, pFan0) ); assert( !Gia_ObjIsTravIdCurrent(p, pFan0) ); Gia_ObjSetTravIdCurrent(p, pFan0); fChanges = 1; break; } } if ( !fChanges ) break; } return Vec_IntSize(vSupp); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abs_GiaCofPrint( word * pTruth, int nSize, int nSize0, int Res ) { int i, Bit; int nBits = (1 << nSize); int nStep = (1 << nSize0); int Mark[2] = {1,1}; for ( i = 0; i < nBits; i++ ) { if ( i % nStep == 0 ) { printf( " " ); assert( Res || (Mark[0] && Mark[1]) ); Mark[0] = Mark[1] = 0; } Bit = Abc_InfoHasBit((unsigned *)pTruth, i); Mark[Bit] = 1; printf( "%d", Bit ); } printf( "\n" ); assert( Res || (Mark[0] && Mark[1]) ); return 1; } /**Function************************************************************* Synopsis [Returns 1 if truth table has no const cofactors.] Description [The cofactoring variables are the (nSize-nSize0) most significant vars. Each cofactor depends on nSize0 vars.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abs_GiaCheckTruth( word * pTruth, int nSize, int nSize0 ) { unsigned char * pStr = (unsigned char *)pTruth; int nStr = (nSize >= 3 ? (1 << (nSize - 3)) : 1); int i, k, nSteps; assert( nSize0 > 0 && nSize0 <= nSize ); if ( nSize0 == 1 ) { for ( i = 0; i < nStr; i++ ) if ( (((unsigned)pStr[i] ^ ((unsigned)pStr[i] >> 1)) & 0x55) != 0x55 ) return 0; return 1; } if ( nSize0 == 2 ) { for ( i = 0; i < nStr; i++ ) if ( ((unsigned)pStr[i] & 0xF) == 0x0 || (((unsigned)pStr[i] >> 4) & 0xF) == 0x0 || ((unsigned)pStr[i] & 0xF) == 0xF || (((unsigned)pStr[i] >> 4) & 0xF) == 0xF ) return 0; return 1; } assert( nSize0 >= 3 ); nSteps = (1 << (nSize0 - 3)); for ( i = 0; i < nStr; i += nSteps ) { for ( k = 0; k < nSteps; k++ ) if ( ((unsigned)pStr[i+k] & 0xFF) != 0x00 ) break; if ( k == nSteps ) break; for ( k = 0; k < nSteps; k++ ) if ( ((unsigned)pStr[i+k] & 0xFF) != 0xFF ) break; if ( k == nSteps ) break; } assert( i <= nStr ); return (int)( i == nStr ); } /**Function************************************************************* Synopsis [Returns 1 if truth table has const cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abs_RpmPerformMark( Gia_Man_t * p, int nCutMax, int fVerbose, int fVeryVerbose ) { Vec_Int_t * vPis, * vAnds, * vDoms; Vec_Int_t * vSupp, * vSupp1, * vSupp2; Gia_Obj_t * pObj; word * pTruth; int Iter, i, nSize0, nNodes; int fHasConst, fChanges = 1; Gia_ManCreateRefs( p ); Gia_ManCleanMark1( p ); Gia_ManForEachPi( p, pObj, i ) pObj->fMark1 = 1; vPis = Vec_IntAlloc( 100 ); vAnds = Vec_IntAlloc( 100 ); vSupp1 = Vec_IntAlloc( 100 ); vSupp2 = Vec_IntAlloc( 100 ); for ( Iter = 0; fChanges; Iter++ ) { fChanges = 0; vDoms = Gia_ManComputePiDoms( p ); // count the number of PIs and internal nodes if ( fVerbose || fVeryVerbose ) { Gia_ManCountPisNodes( p, vPis, vAnds ); printf( "Iter %3d : ", Iter ); printf( "PI = %5d (%6.2f %%) ", Vec_IntSize(vPis), 100.0 * Vec_IntSize(vPis) / Gia_ManPiNum(p) ); printf( "And = %6d (%6.2f %%) ", Vec_IntSize(vAnds), 100.0 * Vec_IntSize(vAnds) / Gia_ManAndNum(p) ); printf( "Dom = %5d (%6.2f %%) ", Vec_IntSize(vDoms), 100.0 * Vec_IntSize(vDoms) / Gia_ManAndNum(p) ); printf( "\n" ); } // pObj = Gia_ObjFanin0( Gia_ManPo(p, 1) ); Gia_ManForEachObjVec( vDoms, p, pObj, i ) { assert( !pObj->fMark1 ); assert( Gia_ObjRefNum( p, pObj ) > 0 ); // dereference root node nNodes = Abs_GiaObjDeref_rec( p, pObj ); /* // compute support of full cone if ( Abs_ManSupport1(p, pObj, vSupp1) > nCutMax ) // if ( 1 ) { // check support of MFFC if ( Abs_ManSupport2(p, pObj, vSupp2) > nCutMax ) // if ( 1 ) { Abs_GiaObjRef_rec( p, pObj ); continue; } vSupp = vSupp2; // printf( "-" ); } else { vSupp = vSupp1; // printf( "+" ); } */ if ( Abs_ManSupport2(p, pObj, vSupp2) > nCutMax ) { Abs_GiaObjRef_rec( p, pObj ); continue; } vSupp = vSupp2; // order nodes by their ref counts nSize0 = Abs_GiaSortNodes( p, vSupp ); assert( nSize0 > 0 && nSize0 <= nCutMax ); // check if truth table has const cofs pTruth = Gia_ObjComputeTruthTableCut( p, pObj, vSupp ); if ( pTruth == NULL ) { Abs_GiaObjRef_rec( p, pObj ); continue; } fHasConst = !Abs_GiaCheckTruth( pTruth, Vec_IntSize(vSupp), nSize0 ); if ( fVeryVerbose ) { printf( "Nodes =%3d ", nNodes ); printf( "Size =%3d ", Vec_IntSize(vSupp) ); printf( "Size0 =%3d ", nSize0 ); printf( "%3s", fHasConst ? "yes" : "no" ); Abs_GiaCofPrint( pTruth, Vec_IntSize(vSupp), nSize0, fHasConst ); } if ( fHasConst ) { Abs_GiaObjRef_rec( p, pObj ); continue; } // pObj can be reparamed pObj->fMark1 = 1; fChanges = 1; } Vec_IntFree( vDoms ); } // count the number of PIs and internal nodes if ( fVeryVerbose ) { Gia_ManCountPisNodes( p, vPis, vAnds ); printf( "Iter %3d : ", Iter ); printf( "PI = %5d (%6.2f %%) ", Vec_IntSize(vPis), 100.0 * Vec_IntSize(vPis) / Gia_ManPiNum(p) ); printf( "And = %6d (%6.2f %%) ", Vec_IntSize(vAnds), 100.0 * Vec_IntSize(vAnds) / Gia_ManAndNum(p) ); // printf( "Dom = %5d (%6.2f %%) ", Vec_IntSize(vDoms), 100.0 * Vec_IntSize(vDoms) / Gia_ManAndNum(p) ); printf( "\n" ); } // cleanup Vec_IntFree( vPis ); Vec_IntFree( vAnds ); Vec_IntFree( vSupp1 ); Vec_IntFree( vSupp2 ); // Gia_ManCleanMark1( p ); // this will erase markings ABC_FREE( p->pRefs ); } /**Function************************************************************* Synopsis [Assumed that fMark1 marks the internal PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupRpm( Gia_Man_t * p ) { Vec_Int_t * vPis, * vAnds; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; // derive PIs and internal nodes vPis = Vec_IntAlloc( 100 ); vAnds = Vec_IntAlloc( 100 ); Gia_ManCountPisNodes( p, vPis, vAnds ); // duplicate AIG 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 PIs Gia_ManForEachObjVec( vPis, p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create flops Gia_ManForEachRo( 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 COs Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // cleanup Vec_IntFree( vPis ); Vec_IntFree( vAnds ); return pNew; } /**Function************************************************************* Synopsis [Performs structural reparametrization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abs_RpmPerform( Gia_Man_t * p, int nCutMax, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pNew; // Gia_ManTestDoms( p ); // return NULL; // perform structural analysis Gia_ObjComputeTruthTableStart( p, nCutMax ); Abs_RpmPerformMark( p, nCutMax, fVerbose, fVeryVerbose ); Gia_ObjComputeTruthTableStop( p ); // derive new AIG pNew = Gia_ManDupRpm( p ); Gia_ManCleanMark1( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absRpmOld.c000066400000000000000000000140361300674244400237610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absRpmOld.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Old min-cut-based reparametrization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absRpmOld.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Specialized duplication.] Description [Replaces registers by PIs/POs and PIs by registers.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupIn2Ff( Gia_Man_t * p ) { Vec_Int_t * vPiOuts; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; vPiOuts = Vec_IntAlloc( Gia_ManPiNum(p) ); pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 * Gia_ManPiNum(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 ) Vec_IntPush( vPiOuts, Gia_ManAppendCi(pNew) ); Gia_ManForEachRo( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachPi( 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 ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachPi( p, pObj, i ) Gia_ManAppendCo( pNew, Vec_IntEntry(vPiOuts, i) ); Gia_ManSetRegNum( pNew, Gia_ManPiNum(p) ); Vec_IntFree( vPiOuts ); return pNew; } /**Function************************************************************* Synopsis [Reverses the above step.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDupFf2In_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj ) { if ( pObj->Value != ~0 ) return pObj->Value; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupFf2In_rec( pNew, Gia_ObjFanin0(pObj) ); Gia_ManDupFf2In_rec( pNew, Gia_ObjFanin1(pObj) ); return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Reverses the above step.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupFf2In( Gia_Man_t * p, int nFlopsOld ) { 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_ManForEachRo( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); for ( i = Gia_ManPiNum(p) - nFlopsOld; i < Gia_ManPiNum(p); i++ ) Gia_ManPi(p, i)->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachPo( p, pObj, i ) Gia_ManDupFf2In_rec( pNew, Gia_ObjFanin0(pObj) ); Gia_ManForEachPo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, nFlopsOld ); return pNew; } /**Function************************************************************* Synopsis [Reparameterized to get rid of useless primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abs_RpmPerformOld( Gia_Man_t * p, int fVerbose ) { // extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); Aig_Man_t * pMan, * pTemp; Gia_Man_t * pNew, * pTmp; int nFlopsOld = Gia_ManRegNum(p); if ( fVerbose ) { printf( "Original AIG:\n" ); Gia_ManPrintStats( p, NULL ); } // perform input trimming pNew = Gia_ManDupTrimmed( p, 1, 0, 0, -1 ); if ( fVerbose ) { printf( "After PI trimming:\n" ); Gia_ManPrintStats( pNew, NULL ); } // transform GIA pNew = Gia_ManDupIn2Ff( pTmp = pNew ); Gia_ManStop( pTmp ); if ( fVerbose ) { printf( "After PI-2-FF transformation:\n" ); Gia_ManPrintStats( pNew, NULL ); } // derive AIG pMan = Gia_ManToAigSimple( pNew ); Gia_ManStop( pNew ); // perform min-reg retiming pMan = Saig_ManRetimeMinArea( pTemp = pMan, 10, 0, 0, 1, 0 ); Aig_ManStop( pTemp ); // derive GIA pNew = Gia_ManFromAigSimple( pMan ); Aig_ManStop( pMan ); if ( fVerbose ) { printf( "After min-area retiming:\n" ); Gia_ManPrintStats( pNew, NULL ); } // transform back pNew = Gia_ManDupFf2In( pTmp = pNew, nFlopsOld ); Gia_ManStop( pTmp ); if ( fVerbose ) { printf( "After FF-2-PI tranformation:\n" ); Gia_ManPrintStats( pNew, NULL ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absUtil.c000066400000000000000000000204621300674244400235010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Interface to pthreads.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abs.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abs_ParSetDefaults( Abs_Par_t * p ) { memset( p, 0, sizeof(Abs_Par_t) ); p->nFramesMax = 0; // maximum frames p->nFramesStart = 0; // starting frame p->nFramesPast = 4; // overlap frames p->nConfLimit = 0; // conflict limit p->nLearnedMax = 1000; // max number of learned clauses p->nLearnedStart = 1000; // max number of learned clauses p->nLearnedDelta = 200; // max number of learned clauses p->nLearnedPerce = 70; // max number of learned clauses p->nTimeOut = 0; // timeout in seconds p->nRatioMin = 0; // stop when less than this % of object is abstracted p->nRatioMax = 30; // restart when more than this % of object is abstracted p->fUseTermVars = 0; // use terminal variables p->fUseRollback = 0; // use rollback to the starting number of frames p->fPropFanout = 1; // propagate fanouts during refinement p->fVerbose = 0; // verbose flag p->iFrame = -1; // the number of frames covered p->iFrameProved = -1; // the number of frames proved p->nFramesNoChangeLim = 2; // the number of frames without change to dump abstraction } /**Function************************************************************* Synopsis [Converting VTA vector to GLA vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_VtaConvertToGla( Gia_Man_t * p, Vec_Int_t * vVta ) { Gia_Obj_t * pObj; Vec_Int_t * vGla; int nObjMask, nObjs = Gia_ManObjNum(p); int i, Entry, nFrames = Vec_IntEntry( vVta, 0 ); assert( Vec_IntEntry(vVta, nFrames+1) == Vec_IntSize(vVta) ); // get the bitmask nObjMask = (1 << Abc_Base2Log(nObjs)) - 1; assert( nObjs <= nObjMask ); // go through objects vGla = Vec_IntStart( nObjs ); Vec_IntForEachEntryStart( vVta, Entry, i, nFrames+2 ) { pObj = Gia_ManObj( p, (Entry & nObjMask) ); assert( Gia_ObjIsRo(p, pObj) || Gia_ObjIsAnd(pObj) || Gia_ObjIsConst0(pObj) ); Vec_IntAddToEntry( vGla, (Entry & nObjMask), 1 ); } Vec_IntWriteEntry( vGla, 0, nFrames ); return vGla; } /**Function************************************************************* Synopsis [Converting GLA vector to VTA vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_VtaConvertFromGla( Gia_Man_t * p, Vec_Int_t * vGla, int nFrames ) { Vec_Int_t * vVta; int nObjBits, nObjMask, nObjs = Gia_ManObjNum(p); int i, k, j, Entry, Counter, nGlaSize; //. get the GLA size nGlaSize = Vec_IntSum(vGla); // get the bitmask nObjBits = Abc_Base2Log(nObjs); nObjMask = (1 << Abc_Base2Log(nObjs)) - 1; assert( nObjs <= nObjMask ); // go through objects vVta = Vec_IntAlloc( 1000 ); Vec_IntPush( vVta, nFrames ); Counter = nFrames + 2; for ( i = 0; i <= nFrames; i++, Counter += i * nGlaSize ) Vec_IntPush( vVta, Counter ); for ( i = 0; i < nFrames; i++ ) for ( k = 0; k <= i; k++ ) Vec_IntForEachEntry( vGla, Entry, j ) if ( Entry ) Vec_IntPush( vVta, (k << nObjBits) | j ); Counter = Vec_IntEntry(vVta, nFrames+1); assert( Vec_IntEntry(vVta, nFrames+1) == Vec_IntSize(vVta) ); return vVta; } /**Function************************************************************* Synopsis [Converting GLA vector to FLA vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_FlaConvertToGla_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vGla ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); Vec_IntWriteEntry( vGla, Gia_ObjId(p, pObj), 1 ); if ( Gia_ObjIsRo(p, pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_FlaConvertToGla_rec( p, Gia_ObjFanin0(pObj), vGla ); Gia_FlaConvertToGla_rec( p, Gia_ObjFanin1(pObj), vGla ); } /**Function************************************************************* Synopsis [Converting FLA vector to GLA vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_FlaConvertToGla( Gia_Man_t * p, Vec_Int_t * vFla ) { Vec_Int_t * vGla; Gia_Obj_t * pObj; int i; // mark const0 and relevant CI objects Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent(p, Gia_ManConst0(p)); Gia_ManForEachPi( p, pObj, i ) Gia_ObjSetTravIdCurrent(p, pObj); Gia_ManForEachRo( p, pObj, i ) if ( !Vec_IntEntry(vFla, i) ) Gia_ObjSetTravIdCurrent(p, pObj); // label all objects reachable from the PO and selected flops vGla = Vec_IntStart( Gia_ManObjNum(p) ); Vec_IntWriteEntry( vGla, 0, 1 ); Gia_ManForEachPo( p, pObj, i ) Gia_FlaConvertToGla_rec( p, Gia_ObjFanin0(pObj), vGla ); Gia_ManForEachRi( p, pObj, i ) if ( Vec_IntEntry(vFla, i) ) Gia_FlaConvertToGla_rec( p, Gia_ObjFanin0(pObj), vGla ); return vGla; } /**Function************************************************************* Synopsis [Converting GLA vector to FLA vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_GlaConvertToFla( Gia_Man_t * p, Vec_Int_t * vGla ) { Vec_Int_t * vFla; Gia_Obj_t * pObj; int i; vFla = Vec_IntStart( Gia_ManRegNum(p) ); Gia_ManForEachRo( p, pObj, i ) if ( Vec_IntEntry(vGla, Gia_ObjId(p, pObj)) ) Vec_IntWriteEntry( vFla, i, 1 ); return vFla; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_GlaCountFlops( Gia_Man_t * p, Vec_Int_t * vGla ) { Gia_Obj_t * pObj; int i, Count = 0; Gia_ManForEachRo( p, pObj, i ) if ( Vec_IntEntry(vGla, Gia_ObjId(p, pObj)) ) Count++; return Count; } int Gia_GlaCountNodes( Gia_Man_t * p, Vec_Int_t * vGla ) { Gia_Obj_t * pObj; int i, Count = 0; Gia_ManForEachAnd( p, pObj, i ) if ( Vec_IntEntry(vGla, Gia_ObjId(p, pObj)) ) Count++; return Count; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/absVta.c000066400000000000000000001721261300674244400233230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [absVta.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Abstraction package.] Synopsis [Variable time-frame abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: absVta.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sat/bsat/satSolver2.h" #include "base/main/main.h" #include "abs.h" ABC_NAMESPACE_IMPL_START #define VTA_LARGE 0xFFFFFFF //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Vta_Obj_t_ Vta_Obj_t; // object struct Vta_Obj_t_ { int iObj; int iFrame; int iNext; unsigned Prio : 28; // related to VTA_LARGE unsigned Value : 2; unsigned fAdded : 1; unsigned fVisit : 1; }; typedef struct Vta_Man_t_ Vta_Man_t; // manager struct Vta_Man_t_ { // user data Gia_Man_t * pGia; // AIG manager Abs_Par_t * pPars; // parameters // internal data int nObjs; // the number of objects int nObjsAlloc; // the number of objects allocated int nBins; // number of hash table entries int * pBins; // hash table bins Vta_Obj_t * pObjs; // storage for objects Vec_Int_t * vOrder; // objects in DPS order // abstraction int nObjBits; // the number of bits to represent objects unsigned nObjMask; // object mask Vec_Ptr_t * vFrames; // start abstraction for each frame int nWords; // the number of words in the record int nCexes; // the number of CEXes int nObjAdded; // objects added to the abstraction Vec_Int_t * vSeens; // seen objects Vec_Bit_t * vSeenGla; // seen objects in all frames int nSeenGla; // seen objects in all frames int nSeenAll; // seen objects in all frames // other data Vec_Ptr_t * vCores; // unsat core for each frame sat_solver2 * pSat; // incremental SAT solver Vec_Int_t * vAddedNew; // the IDs of variables added to the solver // statistics abctime timeSat; abctime timeUnsat; abctime timeCex; abctime timeOther; }; // ternary simulation #define VTA_VAR0 1 #define VTA_VAR1 2 #define VTA_VARX 3 static inline int Vta_ValIs0( Vta_Obj_t * pThis, int fCompl ) { if ( pThis->Value == VTA_VAR1 && fCompl ) return 1; if ( pThis->Value == VTA_VAR0 && !fCompl ) return 1; return 0; } static inline int Vta_ValIs1( Vta_Obj_t * pThis, int fCompl ) { if ( pThis->Value == VTA_VAR0 && fCompl ) return 1; if ( pThis->Value == VTA_VAR1 && !fCompl ) return 1; return 0; } static inline Vta_Obj_t * Vta_ManObj( Vta_Man_t * p, int i ) { assert( i >= 0 && i < p->nObjs ); return i ? p->pObjs + i : NULL; } static inline int Vta_ObjId( Vta_Man_t * p, Vta_Obj_t * pObj ) { assert( pObj > p->pObjs && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; } #define Vta_ManForEachObj( p, pObj, i ) \ for ( i = 1; (i < p->nObjs) && ((pObj) = Vta_ManObj(p, i)); i++ ) #define Vta_ManForEachObjObj( p, pObjVta, pObjGia, i ) \ for ( i = 1; (i < p->nObjs) && ((pObjVta) = Vta_ManObj(p, i)) && ((pObjGia) = Gia_ManObj(p->pGia, pObjVta->iObj)); i++ ) #define Vta_ManForEachObjObjReverse( p, pObjVta, pObjGia, i ) \ for ( i = Vec_IntSize(vVec) - 1; (i >= 1) && ((pObjVta) = Vta_ManObj(p, i)) && ((pObjGia) = Gia_ManObj(p->pGia, pObjVta->iObj)); i++ ) #define Vta_ManForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Vta_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) #define Vta_ManForEachObjVecReverse( vVec, p, pObj, i ) \ for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && ((pObj) = Vta_ManObj(p, Vec_IntEntry(vVec,i))); i-- ) #define Vta_ManForEachObjObjVec( vVec, p, pObj, pObjG, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Vta_ManObj(p, Vec_IntEntry(vVec,i))) && ((pObjG) = Gia_ManObj(p->pGia, pObj->iObj)); i++ ) #define Vta_ManForEachObjObjVecReverse( vVec, p, pObj, pObjG, i ) \ for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && ((pObj) = Vta_ManObj(p, Vec_IntEntry(vVec,i))) && ((pObjG) = Gia_ManObj(p->pGia, pObj->iObj)); i-- ) // abstraction is given as an array of integers: // - the first entry is the number of timeframes (F) // - the next (F+1) entries give the beginning position of each timeframe // - the following entries give the object IDs // invariant: assert( vec[vec[0]+1] == size(vec) ); extern void Vga_ManAddClausesOne( Vta_Man_t * p, int iObj, int iFrame ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converting from one array to per-frame arrays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_VtaAbsToFrames( Vec_Int_t * vAbs ) { Vec_Ptr_t * vFrames; Vec_Int_t * vFrame; int i, k, Entry, iStart, iStop = -1; int nFrames = Vec_IntEntry( vAbs, 0 ); assert( Vec_IntEntry(vAbs, nFrames+1) == Vec_IntSize(vAbs) ); vFrames = Vec_PtrAlloc( nFrames ); for ( i = 0; i < nFrames; i++ ) { iStart = Vec_IntEntry( vAbs, i+1 ); iStop = Vec_IntEntry( vAbs, i+2 ); vFrame = Vec_IntAlloc( iStop - iStart ); Vec_IntForEachEntryStartStop( vAbs, Entry, k, iStart, iStop ) Vec_IntPush( vFrame, Entry ); Vec_PtrPush( vFrames, vFrame ); } assert( iStop == Vec_IntSize(vAbs) ); return vFrames; } /**Function************************************************************* Synopsis [Converting from per-frame arrays to one integer array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_VtaFramesToAbs( Vec_Vec_t * vFrames ) { Vec_Int_t * vOne, * vAbs; int i, k, Entry, nSize; vAbs = Vec_IntAlloc( 2 + Vec_VecSize(vFrames) + Vec_VecSizeSize(vFrames) ); Vec_IntPush( vAbs, Vec_VecSize(vFrames) ); nSize = Vec_VecSize(vFrames) + 2; Vec_VecForEachLevelInt( vFrames, vOne, i ) { Vec_IntPush( vAbs, nSize ); nSize += Vec_IntSize( vOne ); } Vec_IntPush( vAbs, nSize ); assert( Vec_IntSize(vAbs) == Vec_VecSize(vFrames) + 2 ); Vec_VecForEachLevelInt( vFrames, vOne, i ) Vec_IntForEachEntry( vOne, Entry, k ) Vec_IntPush( vAbs, Entry ); assert( Vec_IntEntry(vAbs, Vec_IntEntry(vAbs,0)+1) == Vec_IntSize(vAbs) ); return vAbs; } /**Function************************************************************* Synopsis [Detects how many frames are completed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vta_ManDeriveAbsAll( Vec_Int_t * p, int nWords ) { Vec_Int_t * vRes; unsigned * pThis; int i, w, nObjs = Vec_IntSize(p) / nWords; assert( Vec_IntSize(p) % nWords == 0 ); vRes = Vec_IntAlloc( nObjs ); for ( i = 0; i < nObjs; i++ ) { pThis = (unsigned *)Vec_IntEntryP( p, nWords * i ); for ( w = 0; w < nWords; w++ ) if ( pThis[w] ) break; Vec_IntPush( vRes, (int)(w < nWords) ); } return vRes; } /**Function************************************************************* Synopsis [Collect nodes/flops involved in different timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Vec_IntDoubleWidth( Vec_Int_t * p, int nWords ) { int * pArray = ABC_CALLOC( int, Vec_IntSize(p) * 2 ); int i, w, nObjs = Vec_IntSize(p) / nWords; assert( Vec_IntSize(p) % nWords == 0 ); for ( i = 0; i < nObjs; i++ ) for ( w = 0; w < nWords; w++ ) pArray[2 * nWords * i + w] = p->pArray[nWords * i + w]; ABC_FREE( p->pArray ); p->pArray = pArray; p->nSize *= 2; p->nCap = p->nSize; return 2 * nWords; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vga_ManHash( int iObj, int iFrame, int nBins ) { return ((unsigned)((iObj + iFrame)*(iObj + iFrame + 1))) % nBins; } static inline int * Vga_ManLookup( Vta_Man_t * p, int iObj, int iFrame ) { Vta_Obj_t * pThis; int * pPlace = p->pBins + Vga_ManHash( iObj, iFrame, p->nBins ); for ( pThis = Vta_ManObj(p, *pPlace); pThis; pPlace = &pThis->iNext, pThis = Vta_ManObj(p, *pPlace) ) if ( pThis->iObj == iObj && pThis->iFrame == iFrame ) break; return pPlace; } static inline Vta_Obj_t * Vga_ManFind( Vta_Man_t * p, int iObj, int iFrame ) { int * pPlace = Vga_ManLookup( p, iObj, iFrame ); return Vta_ManObj(p, *pPlace); } static inline Vta_Obj_t * Vga_ManFindOrAdd( Vta_Man_t * p, int iObj, int iFrame ) { Vta_Obj_t * pThis; int i, * pPlace; assert( iObj >= 0 && iFrame >= -1 ); if ( p->nObjs == p->nObjsAlloc ) { // resize objects p->pObjs = ABC_REALLOC( Vta_Obj_t, p->pObjs, 2 * p->nObjsAlloc ); memset( p->pObjs + p->nObjsAlloc, 0, p->nObjsAlloc * sizeof(Vta_Obj_t) ); p->nObjsAlloc *= 2; // rehash entries in the table ABC_FREE( p->pBins ); p->nBins = Abc_PrimeCudd( 2 * p->nBins ); p->pBins = ABC_CALLOC( int, p->nBins ); Vta_ManForEachObj( p, pThis, i ) { pThis->iNext = 0; pPlace = Vga_ManLookup( p, pThis->iObj, pThis->iFrame ); assert( *pPlace == 0 ); *pPlace = i; } } pPlace = Vga_ManLookup( p, iObj, iFrame ); if ( *pPlace ) return Vta_ManObj(p, *pPlace); *pPlace = p->nObjs++; pThis = Vta_ManObj(p, *pPlace); pThis->iObj = iObj; pThis->iFrame = iFrame; return pThis; } static inline void Vga_ManDelete( Vta_Man_t * p, int iObj, int iFrame ) { int * pPlace = Vga_ManLookup( p, iObj, iFrame ); Vta_Obj_t * pThis = Vta_ManObj(p, *pPlace); assert( pThis != NULL ); *pPlace = pThis->iNext; pThis->iNext = -1; } /**Function************************************************************* Synopsis [Derives counter-example using current assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Vga_ManDeriveCex( Vta_Man_t * p ) { Abc_Cex_t * pCex; Vta_Obj_t * pThis; Gia_Obj_t * pObj; int i; pCex = Abc_CexAlloc( Gia_ManRegNum(p->pGia), Gia_ManPiNum(p->pGia), p->pPars->iFrame+1 ); pCex->iPo = 0; pCex->iFrame = p->pPars->iFrame; Vta_ManForEachObjObj( p, pThis, pObj, i ) if ( Gia_ObjIsPi(p->pGia, pObj) && sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + pThis->iFrame * pCex->nPis + Gia_ObjCioId(pObj) ); return pCex; } /**Function************************************************************* Synopsis [Remaps core into frame/node pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vta_ManUnsatCoreRemap( Vta_Man_t * p, Vec_Int_t * vCore ) { Vta_Obj_t * pThis; int i, Entry; Vec_IntForEachEntry( vCore, Entry, i ) { pThis = Vta_ManObj( p, Entry ); Entry = (pThis->iFrame << p->nObjBits) | pThis->iObj; Vec_IntWriteEntry( vCore, i, Entry ); } } /**Function************************************************************* Synopsis [Compares two objects by their distance.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Vta_ManComputeDepthIncrease( Vta_Obj_t ** pp1, Vta_Obj_t ** pp2 ) { int Diff = (*pp1)->Prio - (*pp2)->Prio; if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; Diff = (*pp1) - (*pp2); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns 1 if the object is already used.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Vta_ManObjIsUsed( Vta_Man_t * p, int iObj ) { int i; unsigned * pInfo = (unsigned *)Vec_IntEntryP( p->vSeens, p->nWords * iObj ); for ( i = 0; i < p->nWords; i++ ) if ( pInfo[i] ) return 1; return 0; } /**Function************************************************************* Synopsis [Finds predecessors of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vta_ObjPreds( Vta_Man_t * p, Vta_Obj_t * pThis, Gia_Obj_t * pObj, Vta_Obj_t ** ppThis0, Vta_Obj_t ** ppThis1 ) { *ppThis0 = NULL; *ppThis1 = NULL; // if ( !pThis->fAdded ) // return; assert( !Gia_ObjIsPi(p->pGia, pObj) ); if ( Gia_ObjIsConst0(pObj) || (Gia_ObjIsCi(pObj) && pThis->iFrame == 0) ) return; if ( Gia_ObjIsAnd(pObj) ) { *ppThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame ); *ppThis1 = Vga_ManFind( p, Gia_ObjFaninId1p(p->pGia, pObj), pThis->iFrame ); // assert( *ppThis0 && *ppThis1 ); return; } assert( Gia_ObjIsRo(p->pGia, pObj) && pThis->iFrame > 0 ); pObj = Gia_ObjRoToRi( p->pGia, pObj ); *ppThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame-1 ); // assert( *ppThis0 ); } /**Function************************************************************* Synopsis [Collect const/PI/RO/AND in a topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vta_ManCollectNodes_rec( Vta_Man_t * p, Vta_Obj_t * pThis, Vec_Int_t * vOrder ) { Gia_Obj_t * pObj; Vta_Obj_t * pThis0, * pThis1; if ( pThis->fVisit ) return; pThis->fVisit = 1; pObj = Gia_ManObj( p->pGia, pThis->iObj ); if ( pThis->fAdded ) { Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 ); if ( pThis0 ) Vta_ManCollectNodes_rec( p, pThis0, vOrder ); if ( pThis1 ) Vta_ManCollectNodes_rec( p, pThis1, vOrder ); } Vec_IntPush( vOrder, Vta_ObjId(p, pThis) ); } Vec_Int_t * Vta_ManCollectNodes( Vta_Man_t * p, int f ) { Vta_Obj_t * pThis; Gia_Obj_t * pObj; Vec_IntClear( p->vOrder ); pObj = Gia_ManPo( p->pGia, 0 ); pThis = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), f ); assert( pThis != NULL ); assert( !pThis->fVisit ); Vta_ManCollectNodes_rec( p, pThis, p->vOrder ); assert( pThis->fVisit ); return p->vOrder; } /**Function************************************************************* Synopsis [Refines abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vta_ManSatVerify( Vta_Man_t * p ) { Vta_Obj_t * pThis, * pThis0, * pThis1; Gia_Obj_t * pObj; int i; Vta_ManForEachObj( p, pThis, i ) pThis->Value = (sat_solver2_var_value(p->pSat, i) ? VTA_VAR1 : VTA_VAR0); Vta_ManForEachObjObj( p, pThis, pObj, i ) { if ( !pThis->fAdded ) continue; Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 ); if ( Gia_ObjIsAnd(pObj) ) { if ( pThis->Value == VTA_VAR1 ) assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) ); else if ( pThis->Value == VTA_VAR0 ) assert( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) || Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) ); else assert( 0 ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { pObj = Gia_ObjRoToRi( p->pGia, pObj ); if ( pThis->iFrame == 0 ) assert( pThis->Value == VTA_VAR0 ); else if ( pThis->Value == VTA_VAR0 ) assert( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) ); else if ( pThis->Value == VTA_VAR1 ) assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) ); else assert( 0 ); } } } /**Function************************************************************* Synopsis [Refines abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vta_ManProfileAddition( Vta_Man_t * p, Vec_Int_t * vTermsToAdd ) { Vta_Obj_t * pThis; Gia_Obj_t * pObj; // profile the added ones int i, * pCounters = ABC_CALLOC( int, p->pPars->iFrame+1 ); Vta_ManForEachObjObjVec( vTermsToAdd, p, pThis, pObj, i ) pCounters[pThis->iFrame]++; for ( i = 0; i <= p->pPars->iFrame; i++ ) Abc_Print( 1, "%2d", pCounters[i] ); Abc_Print( 1, "***\n" ); } /**Function************************************************************* Synopsis [Refines abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Vta_ManRefineAbstraction( Vta_Man_t * p, int f ) { int fVerify = 0; Abc_Cex_t * pCex = NULL; Vec_Int_t * vOrder, * vTermsToAdd; Vec_Ptr_t * vTermsUsed, * vTermsUnused; Vta_Obj_t * pThis, * pThis0, * pThis1, * pTop; Gia_Obj_t * pObj; int i, Counter; if ( fVerify ) Vta_ManSatVerify( p ); // collect nodes in a topological order vOrder = Vta_ManCollectNodes( p, f ); Vta_ManForEachObjObjVec( vOrder, p, pThis, pObj, i ) { pThis->Prio = VTA_LARGE; pThis->Value = sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) ? VTA_VAR1 : VTA_VAR0; pThis->fVisit = 0; } // verify if ( fVerify ) Vta_ManForEachObjObjVec( vOrder, p, pThis, pObj, i ) { if ( !pThis->fAdded ) continue; Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 ); if ( Gia_ObjIsAnd(pObj) ) { if ( pThis->Value == VTA_VAR1 ) assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) ); else if ( pThis->Value == VTA_VAR0 ) assert( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) || Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) ); else assert( 0 ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { pObj = Gia_ObjRoToRi( p->pGia, pObj ); if ( pThis->iFrame == 0 ) assert( pThis->Value == VTA_VAR0 ); else if ( pThis->Value == VTA_VAR0 ) assert( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) ); else if ( pThis->Value == VTA_VAR1 ) assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) ); else assert( 0 ); } } // compute distance in reverse order pThis = Vta_ManObj( p, Vec_IntEntryLast(vOrder) ); pThis->Prio = 1; // collect used and unused terms vTermsUsed = Vec_PtrAlloc( 1015 ); vTermsUnused = Vec_PtrAlloc( 1016 ); Vta_ManForEachObjObjVecReverse( vOrder, p, pThis, pObj, i ) { // there is no unreachable states assert( pThis->Prio < VTA_LARGE ); // skip constants and PIs if ( Gia_ObjIsConst0(pObj) || Gia_ObjIsPi(p->pGia, pObj) ) { pThis->Prio = 0; // set highest priority continue; } // collect terminals assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) ); if ( !pThis->fAdded ) { assert( pThis->Prio > 0 ); if ( Vta_ManObjIsUsed(p, pThis->iObj) ) Vec_PtrPush( vTermsUsed, pThis ); else Vec_PtrPush( vTermsUnused, pThis ); continue; } // propagate Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 ); if ( pThis0 ) pThis0->Prio = Abc_MinInt( pThis0->Prio, pThis->Prio + 1 ); if ( pThis1 ) pThis1->Prio = Abc_MinInt( pThis1->Prio, pThis->Prio + 1 ); } /* Vta_ManForEachObjObjVecReverse( vOrder, p, pThis, pObj, i ) if ( pThis->Prio > 0 ) pThis->Prio = 10; */ /* // update priorities according to reconvergence counters Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUsed, pThis, i ) { Vta_Obj_t * pThis0, * pThis1; Gia_Obj_t * pObj = Gia_ManObj( p->pGia, pThis->iObj ); Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 ); pThis->Prio += 10000000; if ( pThis0 ) pThis->Prio -= 1000000 * pThis0->fAdded; if ( pThis1 ) pThis->Prio -= 1000000 * pThis1->fAdded; } Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUnused, pThis, i ) { Vta_Obj_t * pThis0, * pThis1; Gia_Obj_t * pObj = Gia_ManObj( p->pGia, pThis->iObj ); Vta_ObjPreds( p, pThis, pObj, &pThis0, &pThis1 ); pThis->Prio += 10000000; if ( pThis0 ) pThis->Prio -= 1000000 * pThis0->fAdded; if ( pThis1 ) pThis->Prio -= 1000000 * pThis1->fAdded; } */ // update priorities according to reconvergence counters Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUsed, pThis, i ) pThis->Prio = pThis->iObj; Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUnused, pThis, i ) pThis->Prio = pThis->iObj; // objects with equal distance should receive priority based on number // those objects whose prototypes have been added in other timeframes // should have higher priority than the current object Vec_PtrSort( vTermsUsed, (int (*)(void))Vta_ManComputeDepthIncrease ); Vec_PtrSort( vTermsUnused, (int (*)(void))Vta_ManComputeDepthIncrease ); if ( Vec_PtrSize(vTermsUsed) > 1 ) { pThis0 = (Vta_Obj_t *)Vec_PtrEntry(vTermsUsed, 0); pThis1 = (Vta_Obj_t *)Vec_PtrEntryLast(vTermsUsed); assert( pThis0->Prio <= pThis1->Prio ); } // assign the priority based on these orders Counter = 1; Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUsed, pThis, i ) pThis->Prio = Counter++; Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUnused, pThis, i ) pThis->Prio = Counter++; // Abc_Print( 1, "Used %d Unused %d\n", Vec_PtrSize(vTermsUsed), Vec_PtrSize(vTermsUnused) ); // propagate in the direct order Vta_ManForEachObjObjVec( vOrder, p, pThis, pObj, i ) { assert( pThis->fVisit == 0 ); assert( pThis->Prio < VTA_LARGE ); // skip terminal objects if ( !pThis->fAdded ) continue; // assumes that values are assigned!!! assert( pThis->Value != 0 ); // propagate if ( Gia_ObjIsAnd(pObj) ) { pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame ); pThis1 = Vga_ManFind( p, Gia_ObjFaninId1p(p->pGia, pObj), pThis->iFrame ); assert( pThis0 && pThis1 ); if ( pThis->Value == VTA_VAR1 ) { assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) ); pThis->Prio = Abc_MaxInt( pThis0->Prio, pThis1->Prio ); } else if ( pThis->Value == VTA_VAR0 ) { if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) ) pThis->Prio = Abc_MinInt( pThis0->Prio, pThis1->Prio ); // choice!!! else if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) ) pThis->Prio = pThis0->Prio; else if ( Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) ) pThis->Prio = pThis1->Prio; else assert( 0 ); } else assert( 0 ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( pThis->iFrame > 0 ) { pObj = Gia_ObjRoToRi( p->pGia, pObj ); pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame-1 ); assert( pThis0 ); pThis->Prio = pThis0->Prio; } else pThis->Prio = 0; } else if ( Gia_ObjIsConst0(pObj) ) pThis->Prio = 0; else assert( 0 ); } // select important values pTop = Vta_ManObj( p, Vec_IntEntryLast(vOrder) ); pTop->fVisit = 1; vTermsToAdd = Vec_IntAlloc( 100 ); Vta_ManForEachObjObjVecReverse( vOrder, p, pThis, pObj, i ) { if ( !pThis->fVisit ) continue; pThis->fVisit = 0; assert( pThis->Prio >= 0 && pThis->Prio <= pTop->Prio ); // skip terminal objects if ( !pThis->fAdded ) { assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsConst0(pObj) || Gia_ObjIsPi(p->pGia, pObj) ); Vec_IntPush( vTermsToAdd, Vta_ObjId(p, pThis) ); continue; } // assumes that values are assigned!!! assert( pThis->Value != 0 ); // propagate if ( Gia_ObjIsAnd(pObj) ) { pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame ); pThis1 = Vga_ManFind( p, Gia_ObjFaninId1p(p->pGia, pObj), pThis->iFrame ); assert( pThis0 && pThis1 ); if ( pThis->Value == VTA_VAR1 ) { assert( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) ); assert( pThis0->Prio <= pThis->Prio ); assert( pThis1->Prio <= pThis->Prio ); pThis0->fVisit = 1; pThis1->fVisit = 1; } else if ( pThis->Value == VTA_VAR0 ) { if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) ) { if ( pThis0->fVisit ) { } else if ( pThis1->fVisit ) { } else if ( pThis0->Prio <= pThis1->Prio ) // choice!!! { pThis0->fVisit = 1; assert( pThis0->Prio == pThis->Prio ); } else { pThis1->fVisit = 1; assert( pThis1->Prio == pThis->Prio ); } } else if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) ) { pThis0->fVisit = 1; assert( pThis0->Prio == pThis->Prio ); } else if ( Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) ) { pThis1->fVisit = 1; assert( pThis1->Prio == pThis->Prio ); } else assert( 0 ); } else assert( 0 ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( pThis->iFrame > 0 ) { pObj = Gia_ObjRoToRi( p->pGia, pObj ); pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame-1 ); assert( pThis0 ); pThis0->fVisit = 1; assert( pThis0->Prio == pThis->Prio ); } } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); } if ( p->pPars->fAddLayer ) { // mark those currently included Vta_ManForEachObjVec( vTermsToAdd, p, pThis, i ) { assert( pThis->fVisit == 0 ); pThis->fVisit = 1; } // add used terms, which have close relationship Counter = Vec_IntSize(vTermsToAdd); Vec_PtrForEachEntry( Vta_Obj_t *, vTermsUsed, pThis, i ) { if ( pThis->fVisit ) continue; // Vta_ObjPreds( p, pThis, Gia_ManObj(p->pGia, pThis->iObj), &pThis0, &pThis1 ); // if ( (pThis0 && (pThis0->fAdded || pThis0->fVisit)) || (pThis1 && (pThis1->fAdded || pThis1->fVisit)) ) Vec_IntPush( vTermsToAdd, Vta_ObjId(p, pThis) ); } // remove those currenty included Vta_ManForEachObjVec( vTermsToAdd, p, pThis, i ) pThis->fVisit = 0; } // printf( "\n%d -> %d\n", Counter, Vec_IntSize(vTermsToAdd) ); //Vec_IntReverseOrder( vTermsToAdd ); //Vec_IntSort( vTermsToAdd, 1 ); // cleanup Vec_PtrFree( vTermsUsed ); Vec_PtrFree( vTermsUnused ); if ( fVerify ) { // verify Vta_ManForEachObjVec( vOrder, p, pThis, i ) pThis->Value = VTA_VARX; Vta_ManForEachObjVec( vTermsToAdd, p, pThis, i ) { assert( !pThis->fAdded ); pThis->Value = sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) ? VTA_VAR1 : VTA_VAR0; } // simulate Vta_ManForEachObjObjVec( vOrder, p, pThis, pObj, i ) { assert( pThis->fVisit == 0 ); if ( !pThis->fAdded ) continue; if ( Gia_ObjIsAnd(pObj) ) { pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame ); pThis1 = Vga_ManFind( p, Gia_ObjFaninId1p(p->pGia, pObj), pThis->iFrame ); assert( pThis0 && pThis1 ); if ( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) && Vta_ValIs1(pThis1, Gia_ObjFaninC1(pObj)) ) pThis->Value = VTA_VAR1; else if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) || Vta_ValIs0(pThis1, Gia_ObjFaninC1(pObj)) ) pThis->Value = VTA_VAR0; else pThis->Value = VTA_VARX; } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( pThis->iFrame > 0 ) { pObj = Gia_ObjRoToRi( p->pGia, pObj ); pThis0 = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), pThis->iFrame-1 ); assert( pThis0 ); if ( Vta_ValIs0(pThis0, Gia_ObjFaninC0(pObj)) ) pThis->Value = VTA_VAR0; else if ( Vta_ValIs1(pThis0, Gia_ObjFaninC0(pObj)) ) pThis->Value = VTA_VAR1; else pThis->Value = VTA_VARX; } else { pThis->Value = VTA_VAR0; } } else if ( Gia_ObjIsConst0(pObj) ) { pThis->Value = VTA_VAR0; } else assert( 0 ); // double check the solver assert( pThis->Value == VTA_VARX || (int)pThis->Value == (sat_solver2_var_value(p->pSat, Vta_ObjId(p, pThis)) ? VTA_VAR1 : VTA_VAR0) ); } // check the output if ( !Vta_ValIs1(pTop, Gia_ObjFaninC0(Gia_ManPo(p->pGia, 0))) ) Abc_Print( 1, "Vta_ManRefineAbstraction(): Terminary simulation verification failed!\n" ); // else // Abc_Print( 1, "Verification OK.\n" ); } // produce true counter-example if ( pTop->Prio == 0 ) pCex = Vga_ManDeriveCex( p ); else { // Vta_ManProfileAddition( p, vTermsToAdd ); Vta_ManForEachObjObjVec( vTermsToAdd, p, pThis, pObj, i ) if ( !Gia_ObjIsPi(p->pGia, pObj) ) Vga_ManAddClausesOne( p, pThis->iObj, pThis->iFrame ); sat_solver2_simplify( p->pSat ); } p->nObjAdded += Vec_IntSize(vTermsToAdd); Vec_IntFree( vTermsToAdd ); return pCex; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vta_Man_t * Vga_ManStart( Gia_Man_t * pGia, Abs_Par_t * pPars ) { Vta_Man_t * p; p = ABC_CALLOC( Vta_Man_t, 1 ); p->pGia = pGia; p->pPars = pPars; // internal data p->nObjsAlloc = (1 << 18); p->pObjs = ABC_CALLOC( Vta_Obj_t, p->nObjsAlloc ); p->nObjs = 1; p->nBins = Abc_PrimeCudd( 2*p->nObjsAlloc ); p->pBins = ABC_CALLOC( int, p->nBins ); p->vOrder = Vec_IntAlloc( 1013 ); // abstraction p->nObjBits = Abc_Base2Log( Gia_ManObjNum(pGia) ); p->nObjMask = (1 << p->nObjBits) - 1; assert( Gia_ManObjNum(pGia) <= (int)p->nObjMask ); p->nWords = 1; p->vSeens = Vec_IntStart( Gia_ManObjNum(pGia) * p->nWords ); p->vSeenGla = Vec_BitStart( Gia_ManObjNum(pGia) ); p->nSeenGla = 1; p->nSeenAll = 1; // other data p->vCores = Vec_PtrAlloc( 100 ); p->pSat = sat_solver2_new(); p->pSat->pPrf1 = Vec_SetAlloc( 20 ); // p->pSat->fVerbose = p->pPars->fVerbose; // sat_solver2_set_learntmax( p->pSat, pPars->nLearnedMax ); p->pSat->nLearntStart = p->pPars->nLearnedStart; p->pSat->nLearntDelta = p->pPars->nLearnedDelta; p->pSat->nLearntRatio = p->pPars->nLearnedPerce; p->pSat->nLearntMax = p->pSat->nLearntStart; // start the abstraction assert( pGia->vObjClasses != NULL ); p->vFrames = Gia_VtaAbsToFrames( pGia->vObjClasses ); p->vAddedNew = Vec_IntAlloc( 1000 ); return p; } /**Function************************************************************* Synopsis [Delete manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vga_ManStop( Vta_Man_t * p ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "SAT solver: Var = %d Cla = %d Conf = %d Lrn = %d Reduce = %d Cex = %d Objs+ = %d\n", sat_solver2_nvars(p->pSat), sat_solver2_nclauses(p->pSat), sat_solver2_nconflicts(p->pSat), sat_solver2_nlearnts(p->pSat), p->pSat->nDBreduces, p->nCexes, p->nObjAdded ); Vec_VecFreeP( (Vec_Vec_t **)&p->vCores ); Vec_VecFreeP( (Vec_Vec_t **)&p->vFrames ); Vec_BitFreeP( &p->vSeenGla ); Vec_IntFreeP( &p->vSeens ); Vec_IntFreeP( &p->vOrder ); Vec_IntFreeP( &p->vAddedNew ); sat_solver2_delete( p->pSat ); ABC_FREE( p->pBins ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the output literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vga_ManGetOutLit( Vta_Man_t * p, int f ) { Gia_Obj_t * pObj = Gia_ManPo(p->pGia, 0); Vta_Obj_t * pThis = Vga_ManFind( p, Gia_ObjFaninId0p(p->pGia, pObj), f ); assert( pThis != NULL && pThis->fAdded ); if ( f == 0 && Gia_ObjIsRo(p->pGia, Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj) ) return -Vta_ObjId(p, pThis); return Abc_Var2Lit( Vta_ObjId(p, pThis), Gia_ObjFaninC0(pObj) ); } /**Function************************************************************* Synopsis [Finds the set of clauses involved in the UNSAT core.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Vta_ManUnsatCore( int iLit, sat_solver2 * pSat, int nConfMax, int fVerbose, int * piRetValue, int * pnConfls ) { abctime clk = Abc_Clock(); Vec_Int_t * vCore; int RetValue, nConfPrev = pSat->stats.conflicts; if ( piRetValue ) *piRetValue = 1; // consider special case when PO points to the flop // this leads to immediate conflict in the first timeframe if ( iLit < 0 ) { vCore = Vec_IntAlloc( 1 ); Vec_IntPush( vCore, -iLit ); return vCore; } // solve the problem RetValue = sat_solver2_solve( pSat, &iLit, &iLit+1, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( pnConfls ) *pnConfls = (int)pSat->stats.conflicts - nConfPrev; if ( RetValue == l_Undef ) { if ( piRetValue ) *piRetValue = -1; return NULL; } if ( RetValue == l_True ) { if ( piRetValue ) *piRetValue = 0; return NULL; } if ( fVerbose ) { // Abc_Print( 1, "%6d", (int)pSat->stats.conflicts - nConfPrev ); // Abc_Print( 1, "UNSAT after %7d conflicts. ", pSat->stats.conflicts ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } assert( RetValue == l_False ); // derive the UNSAT core clk = Abc_Clock(); vCore = (Vec_Int_t *)Sat_ProofCore( pSat ); if ( fVerbose ) { // Abc_Print( 1, "Core is %8d vars (out of %8d). ", Vec_IntSize(vCore), sat_solver2_nvars(pSat) ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return vCore; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Vta_ManAbsPrintFrame( Vta_Man_t * p, Vec_Int_t * vCore, int nFrames, int nConfls, int nCexes, abctime Time, int fVerbose ) { unsigned * pInfo; int * pCountAll = NULL, * pCountUni = NULL; int i, iFrame, iObj, Entry, fChanges = 0; // print info about frames if ( vCore ) { pCountAll = ABC_CALLOC( int, nFrames + 1 ); pCountUni = ABC_CALLOC( int, nFrames + 1 ); Vec_IntForEachEntry( vCore, Entry, i ) { iObj = (Entry & p->nObjMask); iFrame = (Entry >> p->nObjBits); assert( iFrame < nFrames ); pInfo = (unsigned *)Vec_IntEntryP( p->vSeens, p->nWords * iObj ); if ( !Abc_InfoHasBit(pInfo, iFrame) ) { Abc_InfoSetBit( pInfo, iFrame ); pCountUni[iFrame+1]++; pCountUni[0]++; p->nSeenAll++; } pCountAll[iFrame+1]++; pCountAll[0]++; if ( !Vec_BitEntry(p->vSeenGla, iObj) ) { Vec_BitWriteEntry(p->vSeenGla, iObj, 1); p->nSeenGla++; fChanges = 1; } } } if ( !fVerbose ) { ABC_FREE( pCountAll ); ABC_FREE( pCountUni ); return fChanges; } if ( Abc_FrameIsBatchMode() && !vCore ) return fChanges; // Abc_Print( 1, "%5d%5d", pCountAll[0], pCountUni[0] ); Abc_Print( 1, "%4d :", nFrames-1 ); Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * p->nSeenGla / (Gia_ManRegNum(p->pGia) + Gia_ManAndNum(p->pGia) + 1)) ); Abc_Print( 1, "%6d", p->nSeenGla ); Abc_Print( 1, "%4d", Abc_MinInt(100, 100 * p->nSeenAll / (p->nSeenGla * nFrames)) ); Abc_Print( 1, "%8d", nConfls ); if ( nCexes == 0 ) Abc_Print( 1, "%5c", '-' ); else Abc_Print( 1, "%5d", nCexes ); // Abc_Print( 1, " %9d", sat_solver2_nvars(p->pSat) ); Abc_PrintInt( sat_solver2_nvars(p->pSat) ); Abc_PrintInt( sat_solver2_nclauses(p->pSat) ); Abc_PrintInt( sat_solver2_nlearnts(p->pSat) ); if ( vCore == NULL ) { Abc_Print( 1, " ..." ); // for ( k = 0; k < 7; k++ ) // Abc_Print( 1, " " ); Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC ); Abc_Print( 1, "%5.1f GB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<30) ); Abc_Print( 1, "\r" ); } else { Abc_PrintInt( pCountAll[0] ); /* if ( nFrames > 7 ) { for ( k = 0; k < 3; k++ ) Abc_Print( 1, "%5d", pCountAll[k+1] ); Abc_Print( 1, " ..." ); for ( k = nFrames-3; k < nFrames; k++ ) Abc_Print( 1, "%5d", pCountAll[k+1] ); } else { for ( k = 0; k < nFrames; k++ ) Abc_Print( 1, "%5d", pCountAll[k+1] ); for ( k = nFrames; k < 7; k++ ) Abc_Print( 1, " " ); } */ Abc_Print( 1, "%9.2f sec", 1.0*Time/CLOCKS_PER_SEC ); Abc_Print( 1, "%5.1f GB", (sat_solver2_memory_proof(p->pSat) + sat_solver2_memory(p->pSat, 0)) / (1<<30) ); Abc_Print( 1, "\n" ); } fflush( stdout ); if ( vCore ) { ABC_FREE( pCountAll ); ABC_FREE( pCountUni ); } return fChanges; } /**Function************************************************************* Synopsis [Adds clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vga_ManAddClausesOne( Vta_Man_t * p, int iObj, int iFrame ) { Vta_Obj_t * pThis0, * pThis1; Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); Vta_Obj_t * pThis = Vga_ManFindOrAdd( p, iObj, iFrame ); int iThis0, iMainVar = Vta_ObjId(p, pThis); assert( pThis->iObj == iObj && pThis->iFrame == iFrame ); if ( pThis->fAdded ) return; pThis->fAdded = 1; Vec_IntPush( p->vAddedNew, iMainVar ); if ( Gia_ObjIsAnd(pObj) ) { pThis0 = Vga_ManFindOrAdd( p, Gia_ObjFaninId0p(p->pGia, pObj), iFrame ); iThis0 = Vta_ObjId(p, pThis0); pThis1 = Vga_ManFindOrAdd( p, Gia_ObjFaninId1p(p->pGia, pObj), iFrame ); sat_solver2_add_and( p->pSat, iMainVar, iThis0, Vta_ObjId(p, pThis1), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0, iMainVar ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { if ( iFrame == 0 ) { if ( p->pPars->fUseTermVars ) { pThis0 = Vga_ManFindOrAdd( p, iObj, -1 ); sat_solver2_add_constraint( p->pSat, iMainVar, Vta_ObjId(p, pThis0), 1, 0, iMainVar ); } else { sat_solver2_add_const( p->pSat, iMainVar, 1, 0, iMainVar ); } } else { pObj = Gia_ObjRoToRi( p->pGia, pObj ); pThis0 = Vga_ManFindOrAdd( p, Gia_ObjFaninId0p(p->pGia, pObj), iFrame-1 ); sat_solver2_add_buffer( p->pSat, iMainVar, Vta_ObjId(p, pThis0), Gia_ObjFaninC0(pObj), 0, iMainVar ); } } else if ( Gia_ObjIsConst0(pObj) ) { sat_solver2_add_const( p->pSat, iMainVar, 1, 0, iMainVar ); } else //if ( !Gia_ObjIsPi(p->pGia, pObj) ) assert( 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vga_ManLoadSlice( Vta_Man_t * p, Vec_Int_t * vOne, int Lift ) { int i, Entry; Vec_IntForEachEntry( vOne, Entry, i ) Vga_ManAddClausesOne( p, Entry & p->nObjMask, (Entry >> p->nObjBits) + Lift ); sat_solver2_simplify( p->pSat ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vga_ManPrintCore( Vta_Man_t * p, Vec_Int_t * vCore, int Lift ) { int i, Entry, iObj, iFrame; Vec_IntForEachEntry( vCore, Entry, i ) { iObj = (Entry & p->nObjMask); iFrame = (Entry >> p->nObjBits); Abc_Print( 1, "%d*%d ", iObj, iFrame+Lift ); } Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vga_ManRollBack( Vta_Man_t * p, int nObjOld ) { Vta_Obj_t * pThis = p->pObjs + nObjOld; Vta_Obj_t * pLimit = p->pObjs + p->nObjs; int i, Entry; for ( ; pThis < pLimit; pThis++ ) Vga_ManDelete( p, pThis->iObj, pThis->iFrame ); memset( p->pObjs + nObjOld, 0, sizeof(Vta_Obj_t) * (p->nObjs - nObjOld) ); p->nObjs = nObjOld; Vec_IntForEachEntry( p->vAddedNew, Entry, i ) if ( Entry < p->nObjs ) { pThis = Vta_ManObj(p, Entry); assert( pThis->fAdded == 1 ); pThis->fAdded = 0; } } /**Function************************************************************* Synopsis [Send abstracted model or send cancel.] Description [Counter-example will be sent automatically when &vta terminates.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_VtaSendAbsracted( Vta_Man_t * p, int fVerbose ) { Gia_Man_t * pAbs; assert( Abc_FrameIsBridgeMode() ); // if ( fVerbose ) // Abc_Print( 1, "Sending abstracted model...\n" ); // create obj classes Vec_IntFreeP( &p->pGia->vObjClasses ); p->pGia->vObjClasses = Gia_VtaFramesToAbs( (Vec_Vec_t *)p->vCores ); // create gate classes Vec_IntFreeP( &p->pGia->vGateClasses ); p->pGia->vGateClasses = Gia_VtaConvertToGla( p->pGia, p->pGia->vObjClasses ); Vec_IntFreeP( &p->pGia->vObjClasses ); // create abstrated model pAbs = Gia_ManDupAbsGates( p->pGia, p->pGia->vGateClasses ); Vec_IntFreeP( &p->pGia->vGateClasses ); // send it out Gia_ManToBridgeAbsNetlist( stdout, pAbs, BRIDGE_ABS_NETLIST ); Gia_ManStop( pAbs ); } void Gia_VtaSendCancel( Vta_Man_t * p, int fVerbose ) { extern int Gia_ManToBridgeBadAbs( FILE * pFile ); assert( Abc_FrameIsBridgeMode() ); // if ( fVerbose ) // Abc_Print( 1, "Cancelling previously sent model...\n" ); Gia_ManToBridgeBadAbs( stdout ); } /**Function************************************************************* Synopsis [Send abstracted model or send cancel.] Description [Counter-example will be sent automatically when &vta terminates.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_VtaDumpAbsracted( Vta_Man_t * p, int fVerbose ) { char * pFileNameDef = "vabs.aig"; char * pFileName = p->pPars->pFileVabs ? p->pPars->pFileVabs : pFileNameDef; Gia_Man_t * pAbs; if ( fVerbose ) Abc_Print( 1, "Dumping abstracted model into file \"%s\"...\n", pFileName ); // create obj classes Vec_IntFreeP( &p->pGia->vObjClasses ); p->pGia->vObjClasses = Gia_VtaFramesToAbs( (Vec_Vec_t *)p->vCores ); // create gate classes Vec_IntFreeP( &p->pGia->vGateClasses ); p->pGia->vGateClasses = Gia_VtaConvertToGla( p->pGia, p->pGia->vObjClasses ); Vec_IntFreeP( &p->pGia->vObjClasses ); // create abstrated model pAbs = Gia_ManDupAbsGates( p->pGia, p->pGia->vGateClasses ); Vec_IntFreeP( &p->pGia->vGateClasses ); // send it out Gia_AigerWrite( pAbs, pFileName, 0, 0 ); Gia_ManStop( pAbs ); } /**Function************************************************************* Synopsis [Print memory report.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_VtaPrintMemory( Vta_Man_t * p ) { double memTot = 0; double memAig = Gia_ManObjNum(p->pGia) * sizeof(Gia_Obj_t); double memSat = sat_solver2_memory( p->pSat, 1 ); double memPro = sat_solver2_memory_proof( p->pSat ); double memMap = p->nObjsAlloc * sizeof(Vta_Obj_t) + p->nBins * sizeof(int); double memOth = sizeof(Vta_Man_t); memOth += Vec_IntCap(p->vOrder) * sizeof(int); memOth += Vec_VecMemoryInt( (Vec_Vec_t *)p->vFrames ); memOth += Vec_BitCap(p->vSeenGla) * sizeof(int); memOth += Vec_VecMemoryInt( (Vec_Vec_t *)p->vCores ); memOth += Vec_IntCap(p->vAddedNew) * sizeof(int); memTot = memAig + memSat + memPro + memMap + memOth; ABC_PRMP( "Memory: AIG ", memAig, memTot ); ABC_PRMP( "Memory: SAT ", memSat, memTot ); ABC_PRMP( "Memory: Proof ", memPro, memTot ); ABC_PRMP( "Memory: Map ", memMap, memTot ); ABC_PRMP( "Memory: Other ", memOth, memTot ); ABC_PRMP( "Memory: TOTAL ", memTot, memTot ); } /**Function************************************************************* Synopsis [Collect nodes/flops involved in different timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_VtaPerformInt( Gia_Man_t * pAig, Abs_Par_t * pPars ) { Vta_Man_t * p; Vec_Int_t * vCore; Abc_Cex_t * pCex = NULL; int i, f, nConfls, Status, nObjOld, RetValue = -1, nCountNoChange = 0, fOneIsSent = 0; abctime clk = Abc_Clock(), clk2; // preconditions assert( Gia_ManPoNum(pAig) == 1 ); assert( pPars->nFramesMax == 0 || pPars->nFramesStart <= pPars->nFramesMax ); if ( Gia_ObjIsConst0(Gia_ObjFanin0(Gia_ManPo(pAig,0))) ) { if ( !Gia_ObjFaninC0(Gia_ManPo(pAig,0)) ) { printf( "Sequential miter is trivially UNSAT.\n" ); return 1; } ABC_FREE( pAig->pCexSeq ); pAig->pCexSeq = Abc_CexMakeTriv( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), 1, 0 ); printf( "Sequential miter is trivially SAT.\n" ); return 0; } // compute intial abstraction if ( pAig->vObjClasses == NULL ) { pAig->vObjClasses = Vec_IntAlloc( 5 ); Vec_IntPush( pAig->vObjClasses, 1 ); Vec_IntPush( pAig->vObjClasses, 3 ); Vec_IntPush( pAig->vObjClasses, 4 ); Vec_IntPush( pAig->vObjClasses, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)) ); } // start the manager p = Vga_ManStart( pAig, pPars ); // set runtime limit if ( p->pPars->nTimeOut ) sat_solver2_set_runtime_limit( p->pSat, p->pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); // perform initial abstraction if ( p->pPars->fVerbose ) { Abc_Print( 1, "Running variable-timeframe abstraction (VTA) with the following parameters:\n" ); Abc_Print( 1, "FramePast = %d FrameMax = %d ConfMax = %d Timeout = %d RatioMin = %d %%\n", pPars->nFramesPast, pPars->nFramesMax, pPars->nConfLimit, pPars->nTimeOut, pPars->nRatioMin ); Abc_Print( 1, "LearnStart = %d LearnDelta = %d LearnRatio = %d %%.\n", pPars->nLearnedStart, pPars->nLearnedDelta, pPars->nLearnedPerce ); // Abc_Print( 1, "Frame %% Abs %% Confl Cex SatVar Core F0 F1 F2 ...\n" ); Abc_Print( 1, " Frame %% Abs %% Confl Cex Vars Clas Lrns Core Time Mem\n" ); } assert( Vec_PtrSize(p->vFrames) > 0 ); for ( f = i = 0; !p->pPars->nFramesMax || f < p->pPars->nFramesMax; f++ ) { int nConflsBeg = sat_solver2_nconflicts(p->pSat); p->pPars->iFrame = f; // realloc storage for abstraction marks if ( f == p->nWords * 32 ) p->nWords = Vec_IntDoubleWidth( p->vSeens, p->nWords ); // create bookmark to be used for rollback nObjOld = p->nObjs; sat_solver2_bookmark( p->pSat ); Vec_IntClear( p->vAddedNew ); // load new timeframe Vga_ManAddClausesOne( p, 0, f ); if ( f < Vec_PtrSize(p->vFrames) ) Vga_ManLoadSlice( p, (Vec_Int_t *)Vec_PtrEntry(p->vFrames, f), 0 ); else { for ( i = 1; i <= Abc_MinInt(p->pPars->nFramesPast, f); i++ ) Vga_ManLoadSlice( p, (Vec_Int_t *)Vec_PtrEntry(p->vCores, f-i), i ); } // iterate as long as there are counter-examples for ( i = 0; ; i++ ) { clk2 = Abc_Clock(); vCore = Vta_ManUnsatCore( Vga_ManGetOutLit(p, f), p->pSat, pPars->nConfLimit, pPars->fVerbose, &Status, &nConfls ); assert( (vCore != NULL) == (Status == 1) ); if ( Status == -1 ) // resource limit is reached { Vga_ManRollBack( p, nObjOld ); goto finish; } // check timeout if ( p->pSat->nRuntimeLimit && Abc_Clock() > p->pSat->nRuntimeLimit ) { Vga_ManRollBack( p, nObjOld ); goto finish; } if ( vCore != NULL ) { p->timeUnsat += Abc_Clock() - clk2; break; } p->timeSat += Abc_Clock() - clk2; assert( Status == 0 ); p->nCexes++; // perform the refinement clk2 = Abc_Clock(); pCex = Vta_ManRefineAbstraction( p, f ); p->timeCex += Abc_Clock() - clk2; if ( pCex != NULL ) goto finish; // print the result (do not count it towards change) Vta_ManAbsPrintFrame( p, NULL, f+1, sat_solver2_nconflicts(p->pSat)-nConflsBeg, i, Abc_Clock() - clk, p->pPars->fVerbose ); } assert( Status == 1 ); // valid core is obtained Vta_ManUnsatCoreRemap( p, vCore ); Vec_IntSort( vCore, 1 ); // update the SAT solver sat_solver2_rollback( p->pSat ); // update storage Vga_ManRollBack( p, nObjOld ); // load this timeframe Vga_ManLoadSlice( p, vCore, 0 ); Vec_IntFree( vCore ); // run SAT solver clk2 = Abc_Clock(); vCore = Vta_ManUnsatCore( Vga_ManGetOutLit(p, f), p->pSat, pPars->nConfLimit, p->pPars->fVerbose, &Status, &nConfls ); p->timeUnsat += Abc_Clock() - clk2; assert( (vCore != NULL) == (Status == 1) ); if ( Status == -1 ) // resource limit is reached break; if ( Status == 0 ) { Vta_ManSatVerify( p ); // make sure, there was no initial abstraction (otherwise, it was invalid) assert( pAig->vObjClasses == NULL && f < p->pPars->nFramesStart ); pCex = Vga_ManDeriveCex( p ); break; } // add the core Vta_ManUnsatCoreRemap( p, vCore ); // add in direct topological order Vec_IntSort( vCore, 1 ); Vec_PtrPush( p->vCores, vCore ); // print the result if ( Vta_ManAbsPrintFrame( p, vCore, f+1, sat_solver2_nconflicts(p->pSat)-nConflsBeg, i, Abc_Clock() - clk, p->pPars->fVerbose ) ) { // reset the counter of frames without change nCountNoChange = 1; p->pPars->nFramesNoChange = 0; } else if ( ++nCountNoChange == 2 ) // time to send { p->pPars->nFramesNoChange++; if ( Abc_FrameIsBridgeMode() ) { // cancel old one if it was sent if ( fOneIsSent ) Gia_VtaSendCancel( p, pPars->fVerbose ); // send new one Gia_VtaSendAbsracted( p, pPars->fVerbose ); fOneIsSent = 1; } } // dump the model if ( p->pPars->fDumpVabs && (f & 1) ) { char Command[1000]; Abc_FrameSetStatus( -1 ); Abc_FrameSetCex( NULL ); Abc_FrameSetNFrames( f+1 ); sprintf( Command, "write_status %s", Extra_FileNameGenericAppend((char *)(p->pPars->pFileVabs ? p->pPars->pFileVabs : "vtabs.aig"), ".status") ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); Gia_VtaDumpAbsracted( p, pPars->fVerbose ); } // check if the number of objects is below limit if ( p->nSeenGla >= Gia_ManCandNum(pAig) * (100-pPars->nRatioMin) / 100 ) { Status = -1; break; } } finish: // analize the results if ( pCex == NULL ) { if ( p->pPars->fVerbose && Status == -1 ) printf( "\n" ); if ( Vec_PtrSize(p->vCores) == 0 ) Abc_Print( 1, "Abstraction is not produced because first frame is not solved. " ); else { assert( Vec_PtrSize(p->vCores) > 0 ); // if ( pAig->vObjClasses != NULL ) // Abc_Print( 1, "Replacing the old abstraction by a new one.\n" ); Vec_IntFreeP( &pAig->vObjClasses ); pAig->vObjClasses = Gia_VtaFramesToAbs( (Vec_Vec_t *)p->vCores ); if ( Status == -1 ) { if ( p->pPars->nTimeOut && Abc_Clock() >= p->pSat->nRuntimeLimit ) Abc_Print( 1, "Timeout %d sec in frame %d with a %d-stable abstraction. ", p->pPars->nTimeOut, f, p->pPars->nFramesNoChange ); else if ( pPars->nConfLimit && sat_solver2_nconflicts(p->pSat) >= pPars->nConfLimit ) Abc_Print( 1, "Exceeded %d conflicts in frame %d with a %d-stable abstraction. ", pPars->nConfLimit, f, p->pPars->nFramesNoChange ); else if ( p->nSeenGla >= Gia_ManCandNum(pAig) * (100-pPars->nRatioMin) / 100 ) Abc_Print( 1, "The ratio of abstracted objects is less than %d %% in frame %d. ", pPars->nRatioMin, f ); else Abc_Print( 1, "Abstraction stopped for unknown reason in frame %d. ", f ); } else { p->pPars->iFrame++; Abc_Print( 1, "VTA completed %d frames with a %d-stable abstraction. ", f, p->pPars->nFramesNoChange ); } } } else { if ( p->pPars->fVerbose ) printf( "\n" ); ABC_FREE( p->pGia->pCexSeq ); p->pGia->pCexSeq = pCex; if ( !Gia_ManVerifyCex( p->pGia, pCex, 0 ) ) Abc_Print( 1, " Gia_VtaPerform(): CEX verification has failed!\n" ); Abc_Print( 1, "Counter-example detected in frame %d. ", f ); p->pPars->iFrame = pCex->iFrame - 1; Vec_IntFreeP( &pAig->vObjClasses ); RetValue = 0; } Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( p->pPars->fVerbose ) { p->timeOther = (Abc_Clock() - clk) - p->timeUnsat - p->timeSat - p->timeCex; ABC_PRTP( "Runtime: Solver UNSAT", p->timeUnsat, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Solver SAT ", p->timeSat, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Refinement ", p->timeCex, Abc_Clock() - clk ); ABC_PRTP( "Runtime: Other ", p->timeOther, Abc_Clock() - clk ); ABC_PRTP( "Runtime: TOTAL ", Abc_Clock() - clk, Abc_Clock() - clk ); Gia_VtaPrintMemory( p ); } Vga_ManStop( p ); fflush( stdout ); return RetValue; } /**Function************************************************************* Synopsis [Collect nodes/flops involved in different timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_VtaPerform( Gia_Man_t * pAig, Abs_Par_t * pPars ) { int RetValue = -1; if ( pAig->vObjClasses == NULL && pPars->fUseRollback ) { int nFramesMaxOld = pPars->nFramesMax; pPars->nFramesMax = pPars->nFramesStart; RetValue = Gia_VtaPerformInt( pAig, pPars ); pPars->nFramesMax = nFramesMaxOld; } if ( RetValue == 0 ) return RetValue; return Gia_VtaPerformInt( pAig, pPars ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/abs/module.make000066400000000000000000000006761300674244400240630ustar00rootroot00000000000000SRC += src/proof/abs/absDup.c \ src/proof/abs/absGla.c \ src/proof/abs/absGlaOld.c \ src/proof/abs/absIter.c \ src/proof/abs/absOldCex.c \ src/proof/abs/absOldRef.c \ src/proof/abs/absOldSat.c \ src/proof/abs/absOldSim.c \ src/proof/abs/absOut.c \ src/proof/abs/absPth.c \ src/proof/abs/absRef.c \ src/proof/abs/absRefSelect.c \ src/proof/abs/absRpm.c \ src/proof/abs/absRpmOld.c \ src/proof/abs/absVta.c \ src/proof/abs/absUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/000077500000000000000000000000001300674244400220545ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acec.c000066400000000000000000000026551300674244400231230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acec.h000066400000000000000000000061031300674244400231200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acec.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__proof__acec__acec_h #define ABC__proof__acec__acec_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== acecCore.c ========================================================*/ extern int Gia_PolynCec( Gia_Man_t * pGia0, Gia_Man_t * pGia1, Cec_ParCec_t * pPars ); /*=== acecFadds.c ========================================================*/ extern Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose, Vec_Int_t ** vCutsXor2 ); extern Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose ); /*=== acecOrder.c ========================================================*/ extern Vec_Int_t * Gia_PolynReorder( Gia_Man_t * pGia, int fVerbose, int fVeryVerbose ); extern Vec_Int_t * Gia_PolynFindOrder( Gia_Man_t * pGia, Vec_Int_t * vFadds, Vec_Int_t * vHadds, int fVerbose, int fVeryVerbose ); /*=== acecPolyn.c ========================================================*/ extern void Gia_PolynBuild( Gia_Man_t * pGia, Vec_Int_t * vOrder, int fSigned, int fVerbose, int fVeryVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecCo.c000066400000000000000000000257011300674244400234020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecCo.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecCo.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collect non-XOR inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_PolynCoreNonXors_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vXorPairs ) { Gia_Obj_t * pFan0, * pFan1; if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) return; Gia_PolynCoreNonXors_rec( pGia, Gia_Regular(pFan0), vXorPairs ); Gia_PolynCoreNonXors_rec( pGia, Gia_Regular(pFan1), vXorPairs ); Vec_IntPushTwo( vXorPairs, Gia_ObjId(pGia, Gia_Regular(pFan0)), Gia_ObjId(pGia, Gia_Regular(pFan1)) ); } Vec_Int_t * Gia_PolynAddHaRoots( Gia_Man_t * pGia ) { int i, iFan0, iFan1; Vec_Int_t * vNewOuts = Vec_IntAlloc( 100 ); Vec_Int_t * vXorPairs = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj = Gia_ManCo( pGia, Gia_ManCoNum(pGia)-1 ); Gia_PolynCoreNonXors_rec( pGia, Gia_ObjFanin0(pObj), vXorPairs ); // add new outputs Gia_ManSetPhase( pGia ); Vec_IntForEachEntryDouble( vXorPairs, iFan0, iFan1, i ) { Gia_Obj_t * pFan0 = Gia_ManObj( pGia, iFan0 ); Gia_Obj_t * pFan1 = Gia_ManObj( pGia, iFan1 ); int iLit0 = Abc_Var2Lit( iFan0, pFan0->fPhase ); int iLit1 = Abc_Var2Lit( iFan1, pFan1->fPhase ); int iRoot = Gia_ManAppendAnd( pGia, iLit0, iLit1 ); Vec_IntPush( vNewOuts, Abc_Lit2Var(iRoot) ); } Vec_IntFree( vXorPairs ); printf( "On top of %d COs, created %d new adder outputs.\n", Gia_ManCoNum(pGia), Vec_IntSize(vNewOuts) ); return vNewOuts; } /**Function************************************************************* Synopsis [Detects the order of adders.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_PolynCoreOrder( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vAddCos, Vec_Int_t ** pvIns, Vec_Int_t ** pvOuts ) { Vec_Int_t * vOrder = Vec_IntAlloc( 1000 ); Vec_Bit_t * vIsRoot = Vec_BitStart( Gia_ManObjNum(pGia) ); Vec_Int_t * vRoots = Vec_IntAlloc( 5 * Gia_ManCoNum(pGia) ); Vec_Int_t * vLeaves = Vec_IntAlloc( 2 * Gia_ManCiNum(pGia) ); Vec_Wec_t * vMap = Vec_WecStart( Gia_ManObjNum(pGia) ); int i, k, Index, Driver, Entry1, Entry2 = -1; // nodes driven by adders into adder indexes for ( i = 0; 5*i < Vec_IntSize(vAdds); i++ ) { Entry1 = Vec_IntEntry( vAdds, 5*i + 3 ); Entry2 = Vec_IntEntry( vAdds, 5*i + 4 ); Vec_WecPush( vMap, Entry1, i ); Vec_WecPush( vMap, Entry1, Entry2 ); Vec_WecPush( vMap, Entry2, i ); Vec_WecPush( vMap, Entry2, Entry1 ); } // collect roots Gia_ManForEachCoDriverId( pGia, Driver, i ) { Vec_IntPush( vRoots, Driver ); Vec_BitWriteEntry( vIsRoot, Driver, 1 ); } // collect additional outputs Vec_IntForEachEntry( vAddCos, Driver, i ) { Vec_IntPush( vRoots, Driver ); Vec_BitWriteEntry( vIsRoot, Driver, 1 ); } // detect full adder tree *pvOuts = Vec_IntDup( vRoots ); while ( 1 ) { // iterate through boxes driving this one Vec_IntForEachEntry( vRoots, Entry1, i ) { Vec_Int_t * vLevel = Vec_WecEntry( vMap, Entry1 ); Vec_IntForEachEntryDouble( vLevel, Index, Entry2, k ) if ( Vec_BitEntry(vIsRoot, Entry2) ) break; if ( k == Vec_IntSize(vLevel) ) continue; assert( Vec_BitEntry(vIsRoot, Entry1) ); assert( Vec_BitEntry(vIsRoot, Entry2) ); // collect adder Vec_IntPush( vOrder, Index ); // clean marks Vec_BitWriteEntry( vIsRoot, Entry1, 0 ); Vec_BitWriteEntry( vIsRoot, Entry2, 0 ); Vec_IntRemove( vRoots, Entry1 ); Vec_IntRemove( vRoots, Entry2 ); // set new marks Entry1 = Vec_IntEntry( vAdds, 5*Index + 0 ); Entry2 = Vec_IntEntry( vAdds, 5*Index + 1 ); Driver = Vec_IntEntry( vAdds, 5*Index + 2 ); Vec_BitWriteEntry( vIsRoot, Entry1, 1 ); Vec_BitWriteEntry( vIsRoot, Entry2, 1 ); Vec_BitWriteEntry( vIsRoot, Driver, 1 ); Vec_IntPushUnique( vRoots, Entry1 ); Vec_IntPushUnique( vRoots, Entry2 ); Vec_IntPushUnique( vRoots, Driver ); break; } if ( i == Vec_IntSize(vRoots) ) break; } // collect remaining leaves Vec_BitForEachEntryStart( vIsRoot, Driver, i, 1 ) if ( Driver ) Vec_IntPush( vLeaves, i ); *pvIns = vLeaves; // cleanup Vec_BitFree( vIsRoot ); Vec_IntFree( vRoots ); Vec_WecFree( vMap ); return vOrder; } /**Function************************************************************* Synopsis [Collect internal node order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_PolynCoreCollect_rec( Gia_Man_t * pGia, int iObj, Vec_Int_t * vNodes, Vec_Bit_t * vVisited ) { if ( Vec_BitEntry(vVisited, iObj) ) return; Vec_BitSetEntry( vVisited, iObj, 1 ); Gia_PolynCoreCollect_rec( pGia, Gia_ObjFaninId0p(pGia, Gia_ManObj(pGia, iObj)), vNodes, vVisited ); Gia_PolynCoreCollect_rec( pGia, Gia_ObjFaninId1p(pGia, Gia_ManObj(pGia, iObj)), vNodes, vVisited ); Vec_IntPush( vNodes, iObj ); } Vec_Int_t * Gia_PolynCoreCollect( Gia_Man_t * pGia, Vec_Int_t * vAdds, Vec_Int_t * vOrder ) { Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); Vec_Bit_t * vVisited = Vec_BitStart( Gia_ManObjNum(pGia) ); int i, Index, Entry1, Entry2, Entry3; Vec_IntForEachEntryReverse( vOrder, Index, i ) { // mark inputs Entry1 = Vec_IntEntry( vAdds, 5*Index + 0 ); Entry2 = Vec_IntEntry( vAdds, 5*Index + 1 ); Entry3 = Vec_IntEntry( vAdds, 5*Index + 2 ); Vec_BitWriteEntry( vVisited, Entry1, 1 ); Vec_BitWriteEntry( vVisited, Entry2, 1 ); Vec_BitWriteEntry( vVisited, Entry3, 1 ); // traverse from outputs Entry1 = Vec_IntEntry( vAdds, 5*Index + 3 ); Entry2 = Vec_IntEntry( vAdds, 5*Index + 4 ); Gia_PolynCoreCollect_rec( pGia, Entry1, vNodes, vVisited ); Gia_PolynCoreCollect_rec( pGia, Entry2, vNodes, vVisited ); } Vec_BitFree( vVisited ); return vNodes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_PolynCorePrintCones( Gia_Man_t * pGia, Vec_Int_t * vLeaves ) { int i, iObj; Vec_IntForEachEntry( vLeaves, iObj, i ) { printf( "%4d : ", i ); printf( "Supp = %3d ", Gia_ManSuppSize(pGia, &iObj, 1) ); printf( "Cone = %3d ", Gia_ManConeSize(pGia, &iObj, 1) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_PolynCoreDupTree( Gia_Man_t * p, Vec_Int_t * vAddCos, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Gia_ManRegNum(p) == 0 ); 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_ManForEachObjVec( vLeaves, 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 ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachObjVec( vAddCos, p, pObj, i ) Gia_ManAppendCo( pNew, pObj->Value ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_PolynCoreDetectTest_int( Gia_Man_t * pGia, Vec_Int_t * vAddCos ) { extern Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ); abctime clk = Abc_Clock(); Gia_Man_t * pNew; Vec_Int_t * vAdds = Ree_ManComputeCuts( pGia, 1 ); Vec_Int_t * vLeaves, * vRoots, * vOrder = Gia_PolynCoreOrder( pGia, vAdds, vAddCos, &vLeaves, &vRoots ); Vec_Int_t * vNodes = Gia_PolynCoreCollect( pGia, vAdds, vOrder ); printf( "Detected %d FAs/HAs. Roots = %d. Leaves = %d. Nodes = %d. Adds = %d. ", Vec_IntSize(vAdds), Vec_IntSize(vLeaves), Vec_IntSize(vRoots), Vec_IntSize(vNodes), Vec_IntSize(vOrder) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Gia_PolynCorePrintCones( pGia, vLeaves ); pNew = Gia_PolynCoreDupTree( pGia, vAddCos, vLeaves, vNodes ); Vec_IntFree( vAdds ); Vec_IntFree( vLeaves ); Vec_IntFree( vRoots ); Vec_IntFree( vOrder ); Vec_IntFree( vNodes ); return pNew; } Gia_Man_t * Gia_PolynCoreDetectTest( Gia_Man_t * pGia ) { Vec_Int_t * vAddCos = Gia_PolynAddHaRoots( pGia ); Gia_Man_t * pNew = Gia_PolynCoreDetectTest_int( pGia, vAddCos ); Vec_IntFree( vAddCos ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecCore.c000066400000000000000000000037211300674244400237270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_PolynCec( Gia_Man_t * pGia0, Gia_Man_t * pGia1, Cec_ParCec_t * pPars ) { Vec_Int_t * vOrder0 = Gia_PolynReorder( pGia0, pPars->fVerbose, pPars->fVeryVerbose ); Vec_Int_t * vOrder1 = Gia_PolynReorder( pGia1, pPars->fVerbose, pPars->fVeryVerbose ); Gia_PolynBuild( pGia0, vOrder0, 0, pPars->fVerbose, pPars->fVeryVerbose ); Gia_PolynBuild( pGia1, vOrder1, 0, pPars->fVerbose, pPars->fVeryVerbose ); Vec_IntFree( vOrder0 ); Vec_IntFree( vOrder1 ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecCover.c000066400000000000000000000201171300674244400241130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecCover.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecCover.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AcecMark_rec( Gia_Man_t * p, int iObj, int fFirst ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); if ( pObj->fMark0 && !fFirst ) return; assert( Gia_ObjIsAnd(pObj) ); pObj->fMark1 = 1; Gia_AcecMark_rec( p, Gia_ObjFaninId0(pObj, iObj), 0 ); Gia_AcecMark_rec( p, Gia_ObjFaninId1(pObj, iObj), 0 ); } void Gia_AcecMarkFadd( Gia_Man_t * p, int * pSigs ) { // if ( Gia_ManObj(p, pSigs[3])->fMark1 || Gia_ManObj(p, pSigs[4])->fMark1 ) // return; Gia_ManObj( p, pSigs[0] )->fMark0 = 1; Gia_ManObj( p, pSigs[1] )->fMark0 = 1; Gia_ManObj( p, pSigs[2] )->fMark0 = 1; // assert( !Gia_ManObj(p, pSigs[3])->fMark1 ); // assert( !Gia_ManObj(p, pSigs[4])->fMark1 ); Gia_AcecMark_rec( p, pSigs[3], 1 ); Gia_AcecMark_rec( p, pSigs[4], 1 ); } void Gia_AcecMarkHadd( Gia_Man_t * p, int * pSigs ) { Gia_Obj_t * pObj = Gia_ManObj( p, pSigs[0] ); int iFan0 = Gia_ObjFaninId0( pObj, pSigs[0] ); int iFan1 = Gia_ObjFaninId1( pObj, pSigs[0] ); Gia_ManObj( p, iFan0 )->fMark0 = 1; Gia_ManObj( p, iFan1 )->fMark0 = 1; Gia_AcecMark_rec( p, pSigs[0], 1 ); Gia_AcecMark_rec( p, pSigs[1], 1 ); } /**Function************************************************************* Synopsis [Collect XORs reachable from the last output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AcecCollectXors_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Bit_t * vMap, Vec_Int_t * vXors ) { if ( !Gia_ObjIsXor(pObj) )//|| Vec_BitEntry(vMap, Gia_ObjId(p, pObj)) ) return; Vec_IntPush( vXors, Gia_ObjId(p, pObj) ); Gia_AcecCollectXors_rec( p, Gia_ObjFanin0(pObj), vMap, vXors ); Gia_AcecCollectXors_rec( p, Gia_ObjFanin1(pObj), vMap, vXors ); } Vec_Int_t * Gia_AcecCollectXors( Gia_Man_t * p, Vec_Bit_t * vMap ) { Vec_Int_t * vXors = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj = Gia_ObjFanin0( Gia_ManCo(p, Gia_ManCoNum(p)-1) ); Gia_AcecCollectXors_rec( p, pObj, vMap, vXors ); return vXors; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AcecExplore( Gia_Man_t * p, int fVerbose ) { Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); Vec_Int_t * vFadds, * vHadds, * vXors; Vec_Bit_t * vMap = Vec_BitStart( Gia_ManObjNum(p) ); Gia_Obj_t * pObj; int i, nSupp, nCone, nHadds = 0; assert( p->pMuxes != NULL ); vFadds = Gia_ManDetectFullAdders( p, fVerbose, NULL ); vHadds = Gia_ManDetectHalfAdders( p, fVerbose ); pObj = Gia_ManObj( p, 352 ); printf( "Xor = %d.\n", Gia_ObjIsXor(pObj) ); printf( "Fanin0 = %d. Fanin1 = %d.\n", Gia_ObjFaninId0(pObj, 352), Gia_ObjFaninId1(pObj, 352) ); printf( "Fan00 = %d. Fan01 = %d. Fan10 = %d. Fan11 = %d.\n", Gia_ObjFaninId0(Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, 352)), Gia_ObjFaninId1(Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, 352)), Gia_ObjFaninId0(Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, 352)), Gia_ObjFaninId1(Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, 352)) ); // create a map of all HADD/FADD outputs for ( i = 0; i < Vec_IntSize(vHadds)/2; i++ ) { int * pSigs = Vec_IntEntryP(vHadds, 2*i); Vec_BitWriteEntry( vMap, pSigs[0], 1 ); Vec_BitWriteEntry( vMap, pSigs[1], 1 ); } for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ ) { int * pSigs = Vec_IntEntryP(vFadds, 5*i); Vec_BitWriteEntry( vMap, pSigs[3], 1 ); Vec_BitWriteEntry( vMap, pSigs[4], 1 ); } Gia_ManCleanMark01( p ); // mark outputs Gia_ManForEachCo( p, pObj, i ) Gia_ObjFanin0(pObj)->fMark0 = 1; // collect XORs vXors = Gia_AcecCollectXors( p, vMap ); Vec_BitFree( vMap ); printf( "Collected XORs: " ); Vec_IntPrint( vXors ); // mark their fanins Gia_ManForEachObjVec( vXors, p, pObj, i ) { pObj->fMark1 = 1; Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ObjFanin1(pObj)->fMark0 = 1; } // mark FADDs for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ ) Gia_AcecMarkFadd( p, Vec_IntEntryP(vFadds, 5*i) ); // iterate through HADDs and find those that fit in while ( 1 ) { int fChange = 0; for ( i = 0; i < Vec_IntSize(vHadds)/2; i++ ) { int * pSigs = Vec_IntEntryP(vHadds, 2*i); if ( !Gia_ManObj(p, pSigs[0])->fMark0 || !Gia_ManObj(p, pSigs[1])->fMark0 ) continue; if ( Gia_ManObj(p, pSigs[0])->fMark1 || Gia_ManObj(p, pSigs[1])->fMark1 ) continue; Gia_AcecMarkHadd( p, pSigs ); fChange = 1; nHadds++; } if ( !fChange ) break; } // print inputs to the adder network Gia_ManForEachAnd( p, pObj, i ) if ( pObj->fMark0 && !pObj->fMark1 ) { nSupp = Gia_ManSuppSize( p, &i, 1 ); nCone = Gia_ManConeSize( p, &i, 1 ); printf( "Node %5d : Supp = %5d. Cone = %5d.\n", i, nSupp, nCone ); Vec_IntPush( vNodes, i ); } printf( "Fadds = %d. Hadds = %d. Root nodes found = %d.\n", Vec_IntSize(vFadds)/5, nHadds, Vec_IntSize(vNodes) ); Gia_ManCleanMark01( p ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) pObj->fMark0 = 1; Vec_IntFree( vFadds ); Vec_IntFree( vHadds ); Vec_IntFree( vNodes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AcecCover( Gia_Man_t * p ) { int fVerbose = 1; int i, k, Entry; Gia_Obj_t * pObj; Vec_Int_t * vCutsXor2 = NULL; Vec_Int_t * vFadds = Gia_ManDetectFullAdders( p, fVerbose, &vCutsXor2 ); // mark FADDs Gia_ManCleanMark01( p ); for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ ) Gia_AcecMarkFadd( p, Vec_IntEntryP(vFadds, 5*i) ); k = 0; Vec_IntForEachEntry( vCutsXor2, Entry, i ) { if ( i % 3 != 2 ) continue; pObj = Gia_ManObj( p, Entry ); if ( pObj->fMark1 ) continue; printf( "%d ", Entry ); } printf( "\n" ); Gia_ManCleanMark01( p ); Vec_IntFree( vFadds ); Vec_IntFree( vCutsXor2 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecFadds.c000066400000000000000000001351411300674244400240620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecFadds.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Detecting half-adders and full-adders.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecFadds.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" #include "misc/vec/vecWec.h" #include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define Dtc_ForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += pCut[0] + 1 ) #define Dtc_ForEachFadd( vFadds, i ) for ( i = 0; i < Vec_IntSize(vFadds)/5; i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Detecting HADDs in the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManDetectHalfAdders( Gia_Man_t * p, int fVerbose ) { Vec_Int_t * vHadds = Vec_IntAlloc( 1000 ); Gia_Obj_t * pObj, * pFan0, * pFan1; int i, iLit, iFan0, iFan1, fComplDiff, Count, Counts[5] = {0}; Gia_ManHashStart( p ); if ( p->nXors ) { Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjIsXor(pObj) ) continue; Count = 0; iFan0 = Gia_ObjFaninId0(pObj, i); iFan1 = Gia_ObjFaninId1(pObj, i); if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 0), Abc_Var2Lit(iFan1, 0))) ) Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 1), Abc_Var2Lit(iFan1, 1))) ) Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 0), Abc_Var2Lit(iFan1, 1))) ) Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 1), Abc_Var2Lit(iFan1, 0))) ) Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; Counts[Count]++; } } else { ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) continue; Count = 0; if ( Gia_ObjRefNumId(p, Gia_ObjFaninId0(pObj, i)) > 1 ) Vec_IntPushTwo( vHadds, i, Gia_ObjFaninId0(pObj, i) ), Count++; if ( Gia_ObjRefNumId(p, Gia_ObjFaninId1(pObj, i)) > 1 ) Vec_IntPushTwo( vHadds, i, Gia_ObjFaninId1(pObj, i) ), Count++; iFan0 = Gia_ObjId( p, pFan0 ); iFan1 = Gia_ObjId( p, pFan1 ); fComplDiff = (Gia_ObjFaninC0(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC1(Gia_ObjFanin0(pObj))); assert( fComplDiff == (Gia_ObjFaninC0(Gia_ObjFanin1(pObj)) ^ Gia_ObjFaninC1(Gia_ObjFanin1(pObj))) ); if ( fComplDiff ) { if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 0), Abc_Var2Lit(iFan1, 0))) ) Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 1), Abc_Var2Lit(iFan1, 1))) ) Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; } else { if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 0), Abc_Var2Lit(iFan1, 1))) ) Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; if ( (iLit = Gia_ManHashLookupInt(p, Abc_Var2Lit(iFan0, 1), Abc_Var2Lit(iFan1, 0))) ) Vec_IntPushTwo( vHadds, i, Abc_Lit2Var(iLit) ), Count++; } Counts[Count]++; } ABC_FREE( p->pRefs ); } Gia_ManHashStop( p ); if ( fVerbose ) { int iXor, iAnd; printf( "Found %d half-adders with XOR gates: ", Vec_IntSize(vHadds)/2 ); for ( i = 0; i <= 4; i++ ) printf( "%d=%d ", i, Counts[i] ); printf( "\n" ); Vec_IntForEachEntryDouble( vHadds, iXor, iAnd, i ) { pObj = Gia_ManObj( p, iXor ); printf( "%3d : %5d %5d -> %5d %5d\n", i, Gia_ObjFaninId0(pObj, iXor), Gia_ObjFaninId1(pObj, iXor), iXor, iAnd ); } } return vHadds; } /**Function************************************************************* Synopsis [Derive GIA with boxes containing adder-chains.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManIllustrateBoxes( Gia_Man_t * p ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; int nBoxes = Tim_ManBoxNum( pManTime ); int i, k, curCi, curCo, nBoxIns, nBoxOuts; Gia_Obj_t * pObj; // walk through the boxes curCi = Tim_ManPiNum(pManTime); curCo = 0; for ( i = 0; i < nBoxes; i++ ) { nBoxIns = Tim_ManBoxInputNum(pManTime, i); nBoxOuts = Tim_ManBoxOutputNum(pManTime, i); printf( "Box %4d [%d x %d] : ", i, nBoxIns, nBoxOuts ); printf( "Input obj IDs = " ); for ( k = 0; k < nBoxIns; k++ ) { pObj = Gia_ManCo( p, curCo + k ); printf( "%d ", Gia_ObjId(p, pObj) ); } printf( " Output obj IDs = " ); for ( k = 0; k < nBoxOuts; k++ ) { pObj = Gia_ManCi( p, curCi + k ); printf( "%d ", Gia_ObjId(p, pObj) ); } curCo += nBoxIns; curCi += nBoxOuts; printf( "\n" ); } curCo += Tim_ManPoNum(pManTime); // verify counts assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); } /**Function************************************************************* Synopsis [Detecting FADDs in the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dtc_ManCutMergeOne( int * pCut0, int * pCut1, int * pCut ) { int i, k; for ( k = 0; k <= pCut1[0]; k++ ) pCut[k] = pCut1[k]; for ( i = 1; i <= pCut0[0]; i++ ) { for ( k = 1; k <= pCut1[0]; k++ ) if ( pCut0[i] == pCut1[k] ) break; if ( k <= pCut1[0] ) continue; if ( pCut[0] == 3 ) return 0; pCut[1+pCut[0]++] = pCut0[i]; } assert( pCut[0] == 2 || pCut[0] == 3 ); if ( pCut[1] > pCut[2] ) ABC_SWAP( int, pCut[1], pCut[2] ); assert( pCut[1] < pCut[2] ); if ( pCut[0] == 2 ) return 1; if ( pCut[2] > pCut[3] ) ABC_SWAP( int, pCut[2], pCut[3] ); if ( pCut[1] > pCut[2] ) ABC_SWAP( int, pCut[1], pCut[2] ); assert( pCut[1] < pCut[2] ); assert( pCut[2] < pCut[3] ); return 1; } int Dtc_ManCutCheckEqual( Vec_Int_t * vCuts, int * pCutNew ) { int * pList = Vec_IntArray( vCuts ); int i, k, * pCut; Dtc_ForEachCut( pList, pCut, i ) { for ( k = 0; k <= pCut[0]; k++ ) if ( pCut[k] != pCutNew[k] ) break; if ( k > pCut[0] ) return 1; } return 0; } int Dtc_ObjComputeTruth_rec( Gia_Obj_t * pObj ) { int Truth0, Truth1; if ( pObj->Value ) return pObj->Value; assert( Gia_ObjIsAnd(pObj) ); Truth0 = Dtc_ObjComputeTruth_rec( Gia_ObjFanin0(pObj) ); Truth1 = Dtc_ObjComputeTruth_rec( Gia_ObjFanin1(pObj) ); if ( Gia_ObjIsXor(pObj) ) return (pObj->Value = (Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0) ^ (Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1)); else return (pObj->Value = (Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0) & (Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1)); } void Dtc_ObjCleanTruth_rec( Gia_Obj_t * pObj ) { if ( !pObj->Value ) return; pObj->Value = 0; if ( !Gia_ObjIsAnd(pObj) ) return; Dtc_ObjCleanTruth_rec( Gia_ObjFanin0(pObj) ); Dtc_ObjCleanTruth_rec( Gia_ObjFanin1(pObj) ); } int Dtc_ObjComputeTruth( Gia_Man_t * p, int iObj, int * pCut, int * pTruth ) { unsigned Truth, Truths[3] = { 0xAA, 0xCC, 0xF0 }; int i; for ( i = 1; i <= pCut[0]; i++ ) Gia_ManObj(p, pCut[i])->Value = Truths[i-1]; Truth = 0xFF & Dtc_ObjComputeTruth_rec( Gia_ManObj(p, iObj) ); Dtc_ObjCleanTruth_rec( Gia_ManObj(p, iObj) ); if ( pTruth ) *pTruth = Truth; if ( Truth == 0x66 || Truth == 0x99 ) return 3; if ( Truth == 0x96 || Truth == 0x69 ) return 1; if ( Truth == 0xE8 || Truth == 0xD4 || Truth == 0xB2 || Truth == 0x71 || Truth == 0x17 || Truth == 0x2B || Truth == 0x4D || Truth == 0x8E ) return 2; return 0; } void Dtc_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Vec_Int_t * vCutsXor2, Vec_Int_t * vCutsXor, Vec_Int_t * vCutsMaj ) { int fVerbose = 0; Vec_Int_t * vTemp; int i, k, c, Type, * pCut0, * pCut1, pCut[4]; if ( fVerbose ) printf( "Object %d = :\n", iObj ); Vec_IntFill( vCuts, 2, 1 ); Vec_IntPush( vCuts, iObj ); Dtc_ForEachCut( pList0, pCut0, i ) Dtc_ForEachCut( pList1, pCut1, k ) { if ( !Dtc_ManCutMergeOne(pCut0, pCut1, pCut) ) continue; if ( Dtc_ManCutCheckEqual(vCuts, pCut) ) continue; Vec_IntAddToEntry( vCuts, 0, 1 ); if ( fVerbose ) printf( "%d : ", pCut[0] ); for ( c = 0; c <= pCut[0]; c++ ) { Vec_IntPush( vCuts, pCut[c] ); if ( fVerbose && c ) printf( "%d ", pCut[c] ); } if ( fVerbose ) printf( "\n" ); if ( pCut[0] == 2 ) { int Value = Dtc_ObjComputeTruth( p, iObj, pCut, NULL ); assert( Value == 3 || Value == 0 ); if ( Value == 3 ) { Vec_IntPush( vCutsXor2, pCut[1] ); Vec_IntPush( vCutsXor2, pCut[2] ); Vec_IntPush( vCutsXor2, iObj ); } continue; } if ( pCut[0] != 3 ) continue; Type = Dtc_ObjComputeTruth( p, iObj, pCut, NULL ); if ( Type == 0 ) continue; vTemp = Type == 1 ? vCutsXor : vCutsMaj; if ( fVerbose ) printf( "%d = %s(", iObj, Type == 1 ? "XOR" : "MAJ" ); for ( c = 1; c <= pCut[0]; c++ ) { if ( fVerbose ) printf( " %d", pCut[c] ); Vec_IntPush( vTemp, pCut[c] ); } if ( fVerbose ) printf( " )\n" ); Vec_IntPush( vTemp, iObj ); } } void Dtc_ManComputeCuts( Gia_Man_t * p, Vec_Int_t ** pvCutsXor2, Vec_Int_t ** pvCutsXor, Vec_Int_t ** pvCutsMaj, int fVerbose ) { Gia_Obj_t * pObj; int * pList0, * pList1, i, nCuts = 0; Vec_Int_t * vTemp = Vec_IntAlloc( 1000 ); Vec_Int_t * vCutsXor2 = Vec_IntAlloc( Gia_ManAndNum(p) ); Vec_Int_t * vCutsXor = Vec_IntAlloc( Gia_ManAndNum(p) ); Vec_Int_t * vCutsMaj = Vec_IntAlloc( Gia_ManAndNum(p) ); Vec_Int_t * vCuts = Vec_IntAlloc( 30 * Gia_ManAndNum(p) ); Vec_IntFill( vCuts, Gia_ManObjNum(p), 0 ); Gia_ManCleanValue( p ); Gia_ManForEachCi( p, pObj, i ) { Vec_IntWriteEntry( vCuts, Gia_ObjId(p, pObj), Vec_IntSize(vCuts) ); Vec_IntPush( vCuts, 1 ); Vec_IntPush( vCuts, 1 ); Vec_IntPush( vCuts, Gia_ObjId(p, pObj) ); } Gia_ManForEachAnd( p, pObj, i ) { pList0 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId0(pObj, i)) ); pList1 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId1(pObj, i)) ); Dtc_ManCutMerge( p, i, pList0, pList1, vTemp, vCutsXor2, vCutsXor, vCutsMaj ); Vec_IntWriteEntry( vCuts, i, Vec_IntSize(vCuts) ); Vec_IntAppend( vCuts, vTemp ); nCuts += Vec_IntEntry( vTemp, 0 ); } if ( fVerbose ) printf( "Nodes = %d. Cuts = %d. Cuts/Node = %.2f. Ints/Node = %.2f.\n", Gia_ManAndNum(p), nCuts, 1.0*nCuts/Gia_ManAndNum(p), 1.0*Vec_IntSize(vCuts)/Gia_ManAndNum(p) ); Vec_IntFree( vTemp ); Vec_IntFree( vCuts ); if ( pvCutsXor2 ) *pvCutsXor2 = vCutsXor2; else Vec_IntFree( vCutsXor2 ); *pvCutsXor = vCutsXor; *pvCutsMaj = vCutsMaj; } Vec_Int_t * Dtc_ManFindCommonCuts( Gia_Man_t * p, Vec_Int_t * vCutsXor, Vec_Int_t * vCutsMaj ) { int * pCuts0 = Vec_IntArray(vCutsXor); int * pCuts1 = Vec_IntArray(vCutsMaj); int * pLimit0 = Vec_IntLimit(vCutsXor); int * pLimit1 = Vec_IntLimit(vCutsMaj); int i; Vec_Int_t * vFadds = Vec_IntAlloc( 1000 ); assert( Vec_IntSize(vCutsXor) % 4 == 0 ); assert( Vec_IntSize(vCutsMaj) % 4 == 0 ); while ( pCuts0 < pLimit0 && pCuts1 < pLimit1 ) { for ( i = 0; i < 3; i++ ) if ( pCuts0[i] != pCuts1[i] ) break; if ( i == 3 ) { for ( i = 0; i < 4; i++ ) Vec_IntPush( vFadds, pCuts0[i] ); Vec_IntPush( vFadds, pCuts1[3] ); pCuts0 += 4; pCuts1 += 4; } else if ( pCuts0[i] < pCuts1[i] ) pCuts0 += 4; else if ( pCuts0[i] > pCuts1[i] ) pCuts1 += 4; } assert( Vec_IntSize(vFadds) % 5 == 0 ); return vFadds; } void Dtc_ManPrintFadds( Vec_Int_t * vFadds ) { int i; Dtc_ForEachFadd( vFadds, i ) { printf( "%6d : ", i ); printf( "%6d ", Vec_IntEntry(vFadds, 5*i+0) ); printf( "%6d ", Vec_IntEntry(vFadds, 5*i+1) ); printf( "%6d ", Vec_IntEntry(vFadds, 5*i+2) ); printf( " -> " ); printf( "%6d ", Vec_IntEntry(vFadds, 5*i+3) ); printf( "%6d ", Vec_IntEntry(vFadds, 5*i+4) ); printf( "\n" ); if ( i == 100 ) { printf( "Skipping other FADDs.\n" ); break; } } } int Dtc_ManCompare( int * pCut0, int * pCut1 ) { if ( pCut0[0] < pCut1[0] ) return -1; if ( pCut0[0] > pCut1[0] ) return 1; if ( pCut0[1] < pCut1[1] ) return -1; if ( pCut0[1] > pCut1[1] ) return 1; if ( pCut0[2] < pCut1[2] ) return -1; if ( pCut0[2] > pCut1[2] ) return 1; return 0; } int Dtc_ManCompare2( int * pCut0, int * pCut1 ) { if ( pCut0[4] < pCut1[4] ) return -1; if ( pCut0[4] > pCut1[4] ) return 1; return 0; } // returns array of 5-tuples containing inputs/sum/cout of each full adder Vec_Int_t * Gia_ManDetectFullAdders( Gia_Man_t * p, int fVerbose, Vec_Int_t ** pvCutsXor2 ) { Vec_Int_t * vCutsXor, * vCutsMaj, * vFadds; Dtc_ManComputeCuts( p, pvCutsXor2, &vCutsXor, &vCutsMaj, fVerbose ); qsort( Vec_IntArray(vCutsXor), Vec_IntSize(vCutsXor)/4, 16, (int (*)(const void *, const void *))Dtc_ManCompare ); qsort( Vec_IntArray(vCutsMaj), Vec_IntSize(vCutsMaj)/4, 16, (int (*)(const void *, const void *))Dtc_ManCompare ); vFadds = Dtc_ManFindCommonCuts( p, vCutsXor, vCutsMaj ); qsort( Vec_IntArray(vFadds), Vec_IntSize(vFadds)/5, 20, (int (*)(const void *, const void *))Dtc_ManCompare2 ); if ( fVerbose ) printf( "XOR3 cuts = %d. MAJ cuts = %d. Full-adders = %d.\n", Vec_IntSize(vCutsXor)/4, Vec_IntSize(vCutsMaj)/4, Vec_IntSize(vFadds)/5 ); if ( fVerbose ) Dtc_ManPrintFadds( vFadds ); Vec_IntFree( vCutsXor ); Vec_IntFree( vCutsMaj ); return vFadds; } /**Function************************************************************* Synopsis [Map each MAJ into the topmost MAJ of its chain.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // maps MAJ nodes into FADD indexes Vec_Int_t * Gia_ManCreateMap( Gia_Man_t * p, Vec_Int_t * vFadds ) { Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); int i; Dtc_ForEachFadd( vFadds, i ) Vec_IntWriteEntry( vMap, Vec_IntEntry(vFadds, 5*i+4), i ); return vMap; } // find chain length (for each MAJ, how many FADDs are rooted in its first input) int Gia_ManFindChains_rec( Gia_Man_t * p, int iMaj, Vec_Int_t * vFadds, Vec_Int_t * vMap, Vec_Int_t * vLength ) { assert( Vec_IntEntry(vMap, iMaj) >= 0 ); // MAJ if ( Vec_IntEntry(vLength, iMaj) >= 0 ) return Vec_IntEntry(vLength, iMaj); assert( Gia_ObjIsAnd(Gia_ManObj(p, iMaj)) ); { int iFadd = Vec_IntEntry( vMap, iMaj ); int iXor0 = Vec_IntEntry( vFadds, 5*iFadd+0 ); int iXor1 = Vec_IntEntry( vFadds, 5*iFadd+1 ); int iXor2 = Vec_IntEntry( vFadds, 5*iFadd+2 ); int iLen0 = Vec_IntEntry( vMap, iXor0 ) == -1 ? 0 : Gia_ManFindChains_rec( p, iXor0, vFadds, vMap, vLength ); int iLen1 = Vec_IntEntry( vMap, iXor1 ) == -1 ? 0 : Gia_ManFindChains_rec( p, iXor1, vFadds, vMap, vLength ); int iLen2 = Vec_IntEntry( vMap, iXor2 ) == -1 ? 0 : Gia_ManFindChains_rec( p, iXor2, vFadds, vMap, vLength ); int iLen = Abc_MaxInt( iLen0, Abc_MaxInt(iLen1, iLen2) ); if ( iLen0 < iLen ) { if ( iLen == iLen1 ) { ABC_SWAP( int, Vec_IntArray(vFadds)[5*iFadd+0], Vec_IntArray(vFadds)[5*iFadd+1] ); } else if ( iLen == iLen2 ) { ABC_SWAP( int, Vec_IntArray(vFadds)[5*iFadd+0], Vec_IntArray(vFadds)[5*iFadd+2] ); } } Vec_IntWriteEntry( vLength, iMaj, iLen + 1 ); return iLen + 1; } } // for each FADD find the longest chain and reorder its inputs void Gia_ManFindChains( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vMap ) { int i; // for each FADD find the longest chain rooted in it Vec_Int_t * vLength = Vec_IntStartFull( Gia_ManObjNum(p) ); Dtc_ForEachFadd( vFadds, i ) Gia_ManFindChains_rec( p, Vec_IntEntry(vFadds, 5*i+4), vFadds, vMap, vLength ); Vec_IntFree( vLength ); } // collect one carry-chain void Gia_ManCollectOneChain( Gia_Man_t * p, Vec_Int_t * vFadds, int iFaddTop, Vec_Int_t * vMap, Vec_Int_t * vChain ) { int iFadd; Vec_IntClear( vChain ); for ( iFadd = iFaddTop; iFadd >= 0 && !Gia_ObjIsTravIdCurrentId(p, Vec_IntEntry(vFadds, 5*iFadd+3)) && !Gia_ObjIsTravIdCurrentId(p, Vec_IntEntry(vFadds, 5*iFadd+4)); iFadd = Vec_IntEntry(vMap, Vec_IntEntry(vFadds, 5*iFadd+0)) ) { Vec_IntPush( vChain, iFadd ); } Vec_IntReverseOrder( vChain ); } void Gia_ManMarkWithTravId_rec( Gia_Man_t * p, int Id ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return; Gia_ObjSetTravIdCurrentId(p, Id); pObj = Gia_ManObj( p, Id ); if ( Gia_ObjIsAnd(pObj) ) Gia_ManMarkWithTravId_rec( p, Gia_ObjFaninId0(pObj, Id) ); if ( Gia_ObjIsAnd(pObj) ) Gia_ManMarkWithTravId_rec( p, Gia_ObjFaninId1(pObj, Id) ); } // returns mapping of each MAJ into the topmost elements of its chain Vec_Wec_t * Gia_ManCollectTopmost( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vMap, int nFaddMin ) { int i, j, iFadd; Vec_Int_t * vChain = Vec_IntAlloc( 100 ); Vec_Wec_t * vChains = Vec_WecAlloc( Vec_IntSize(vFadds)/5 ); // erase elements appearing as FADD inputs Vec_Bit_t * vMarksTop = Vec_BitStart( Vec_IntSize(vFadds)/5 ); Dtc_ForEachFadd( vFadds, i ) if ( (iFadd = Vec_IntEntry(vMap, Vec_IntEntry(vFadds, 5*i+0))) >= 0 ) Vec_BitWriteEntry( vMarksTop, iFadd, 1 ); // compress the remaining ones Gia_ManIncrementTravId( p ); Dtc_ForEachFadd( vFadds, i ) { if ( Vec_BitEntry(vMarksTop, i) ) continue; Gia_ManCollectOneChain( p, vFadds, i, vMap, vChain ); if ( Vec_IntSize(vChain) < nFaddMin ) continue; Vec_IntAppend( Vec_WecPushLevel(vChains), vChain ); Vec_IntForEachEntry( vChain, iFadd, j ) { assert( !Gia_ObjIsTravIdCurrentId(p, Vec_IntEntry(vFadds, 5*iFadd+3)) ); assert( !Gia_ObjIsTravIdCurrentId(p, Vec_IntEntry(vFadds, 5*iFadd+4)) ); Gia_ManMarkWithTravId_rec( p, Vec_IntEntry(vFadds, 5*iFadd+3) ); Gia_ManMarkWithTravId_rec( p, Vec_IntEntry(vFadds, 5*iFadd+4) ); } } // cleanup Vec_BitFree( vMarksTop ); Vec_IntFree( vChain ); return vChains; } // prints chains beginning in majority nodes contained in vTops void Gia_ManPrintChains( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vMap, Vec_Wec_t * vChains ) { Vec_Int_t * vChain; int i, k, iFadd, Count = 0; Vec_WecForEachLevel( vChains, vChain, i ) { Count += Vec_IntSize(vChain); if ( i < 10 ) { printf( "Chain %4d : %4d ", i, Vec_IntSize(vChain) ); Vec_IntForEachEntry( vChain, iFadd, k ) { printf( "%d(%d) ", iFadd, Vec_IntEntry(vFadds, 5*iFadd+4) ); if ( k != Vec_IntSize(vChain) - 1 ) printf( "-> " ); if ( k > 6 ) { printf( "..." ); break; } } printf( "\n" ); } else if ( i == 10 ) printf( "...\n" ); } printf( "Total chains = %d. Total full-adders = %d.\n", Vec_WecSize(vChains), Count ); } // map SUM bits and topmost MAJ into topmost FADD number Vec_Int_t * Gia_ManFindMapping( Gia_Man_t * p, Vec_Int_t * vFadds, Vec_Int_t * vMap, Vec_Wec_t * vChains ) { Vec_Int_t * vChain; int i, k, iFadd = -1; Vec_Int_t * vMap2Chain = Vec_IntStartFull( Gia_ManObjNum(p) ); Vec_WecForEachLevel( vChains, vChain, i ) { assert( Vec_IntSize(vChain) > 0 ); Vec_IntForEachEntry( vChain, iFadd, k ) { //printf( "Chain %d: setting SUM %d (obj %d)\n", i, k, Vec_IntEntry(vFadds, 5*iFadd+3) ); assert( Vec_IntEntry(vMap2Chain, Vec_IntEntry(vFadds, 5*iFadd+3)) == -1 ); Vec_IntWriteEntry( vMap2Chain, Vec_IntEntry(vFadds, 5*iFadd+3), i ); } //printf( "Chain %d: setting CARRY (obj %d)\n", i, Vec_IntEntry(vFadds, 5*iFadd+4) ); assert( Vec_IntEntry(vMap2Chain, Vec_IntEntry(vFadds, 5*iFadd+4)) == -1 ); Vec_IntWriteEntry( vMap2Chain, Vec_IntEntry(vFadds, 5*iFadd+4), i ); } return vMap2Chain; } /**Function************************************************************* Synopsis [Derive GIA with boxes containing adder-chains.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCollectTruthTables( Gia_Man_t * p, Vec_Int_t * vFadds ) { int i, k, Type, Truth, pCut[4] = {3}; Vec_Int_t * vTruths = Vec_IntAlloc( 2*Vec_IntSize(vFadds)/5 ); Gia_ManCleanValue( p ); Dtc_ForEachFadd( vFadds, i ) { for ( k = 0; k < 3; k++ ) pCut[k+1] = Vec_IntEntry( vFadds, 5*i+k ); Type = Dtc_ObjComputeTruth( p, Vec_IntEntry(vFadds, 5*i+3), pCut, &Truth ); assert( Type == 1 ); Vec_IntPush( vTruths, Truth ); Type = Dtc_ObjComputeTruth( p, Vec_IntEntry(vFadds, 5*i+4), pCut, &Truth ); assert( Type == 2 ); Vec_IntPush( vTruths, Truth ); } return vTruths; } float * Gia_ManGenerateDelayTableFloat( int nIns, int nOuts ) { int i, Total = nIns * nOuts; float * pDelayTable = ABC_ALLOC( float, Total + 3 ); pDelayTable[0] = 0; pDelayTable[1] = nIns; pDelayTable[2] = nOuts; for ( i = 0; i < Total; i++ ) pDelayTable[i+3] = 1; pDelayTable[i+3 - nIns] = -ABC_INFINITY; return pDelayTable; } Tim_Man_t * Gia_ManGenerateTim( int nPis, int nPos, int nBoxes, int nIns, int nOuts ) { Tim_Man_t * pMan; int i, curPi, curPo; Vec_Ptr_t * vDelayTables = Vec_PtrAlloc( 1 ); Vec_PtrPush( vDelayTables, Gia_ManGenerateDelayTableFloat(nIns, nOuts) ); pMan = Tim_ManStart( nPis + nOuts * nBoxes, nPos + nIns * nBoxes ); Tim_ManSetDelayTables( pMan, vDelayTables ); curPi = nPis; curPo = 0; for ( i = 0; i < nBoxes; i++ ) { Tim_ManCreateBox( pMan, curPo, nIns, curPi, nOuts, 0, 0 ); curPi += nOuts; curPo += nIns; } curPo += nPos; assert( curPi == Tim_ManCiNum(pMan) ); assert( curPo == Tim_ManCoNum(pMan) ); //Tim_ManPrint( pMan ); return pMan; } Gia_Man_t * Gia_ManGenerateExtraAig( int nBoxes, int nIns, int nOuts ) { Gia_Man_t * pNew = Gia_ManStart( nBoxes * 20 ); int i, k, pInLits[16], pOutLits[16]; assert( nIns < 16 && nOuts < 16 ); for ( i = 0; i < nIns; i++ ) pInLits[i] = Gia_ManAppendCi( pNew ); pOutLits[0] = Gia_ManAppendXor( pNew, Gia_ManAppendXor(pNew, pInLits[0], pInLits[1]), pInLits[2] ); pOutLits[1] = Gia_ManAppendMaj( pNew, pInLits[0], pInLits[1], pInLits[2] ); for ( i = 0; i < nBoxes; i++ ) for ( k = 0; k < nOuts; k++ ) Gia_ManAppendCo( pNew, pOutLits[k] ); return pNew; } void Gia_ManDupFadd( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vChain, Vec_Int_t * vFadds, Vec_Int_t * vMap, Vec_Wec_t * vChains, Vec_Int_t * vMap2Chain, Vec_Int_t * vTruths ) { extern void Gia_ManDupWithFaddBoxes_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vFadds, Vec_Int_t * vMap, Vec_Wec_t * vChains, Vec_Int_t * vMap2Chain, Vec_Int_t * vTruths ); int i, k, iFadd = -1, iCiLit, pLits[3]; Gia_Obj_t * pObj; // construct FADD inputs Vec_IntForEachEntry( vChain, iFadd, i ) for ( k = 0; k < 3; k++ ) { if ( i && !k ) continue; pObj = Gia_ManObj( p, Vec_IntEntry(vFadds, 5*iFadd+k) ); Gia_ManDupWithFaddBoxes_rec( pNew, p, pObj, vFadds, vMap, vChains, vMap2Chain, vTruths ); } // construct boxes iCiLit = 0; Vec_IntForEachEntry( vChain, iFadd, i ) { int iXorTruth = Vec_IntEntry( vTruths, 2*iFadd+0 ); int iMajTruth = Vec_IntEntry( vTruths, 2*iFadd+1 ); for ( k = 0; k < 3; k++ ) { pObj = Gia_ManObj( p, Vec_IntEntry(vFadds, 5*iFadd+k) ); pLits[k] = (!k && iCiLit) ? iCiLit : pObj->Value; assert( pLits[k] >= 0 ); } // normalize truth table // if ( Truth == 0xE8 || Truth == 0xD4 || Truth == 0xB2 || Truth == 0x71 || // Truth == 0x17 || Truth == 0x2B || Truth == 0x4D || Truth == 0x8E ) if ( iMajTruth == 0x4D ) pLits[0] = Abc_LitNot(pLits[0]), iMajTruth = 0x8E, iXorTruth = 0xFF & ~iXorTruth; else if ( iMajTruth == 0xD4 ) pLits[0] = Abc_LitNot(pLits[0]), iMajTruth = 0xE8, iXorTruth = 0xFF & ~iXorTruth; else if ( iMajTruth == 0x2B ) pLits[1] = Abc_LitNot(pLits[1]), iMajTruth = 0x8E, iXorTruth = 0xFF & ~iXorTruth; else if ( iMajTruth == 0xB2 ) pLits[1] = Abc_LitNot(pLits[1]), iMajTruth = 0xE8, iXorTruth = 0xFF & ~iXorTruth; if ( iMajTruth == 0x8E ) pLits[2] = Abc_LitNot(pLits[2]), iMajTruth = 0xE8, iXorTruth = 0xFF & ~iXorTruth; else if ( iMajTruth == 0x71 ) pLits[2] = Abc_LitNot(pLits[2]), iMajTruth = 0x17, iXorTruth = 0xFF & ~iXorTruth; else assert( iMajTruth == 0xE8 || iMajTruth == 0x17 ); // normalize carry-in if ( Abc_LitIsCompl(pLits[0]) ) { for ( k = 0; k < 3; k++ ) pLits[k] = Abc_LitNot(pLits[k]); iXorTruth = 0xFF & ~iXorTruth; iMajTruth = 0xFF & ~iMajTruth; } // add COs assert( !Abc_LitIsCompl(pLits[0]) ); for ( k = 0; k < 3; k++ ) Gia_ManAppendCo( pNew, pLits[k] ); // create CI assert( iXorTruth == 0x96 || iXorTruth == 0x69 ); pObj = Gia_ManObj( p, Vec_IntEntry(vFadds, 5*iFadd+3) ); pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), (int)(iXorTruth == 0x69) ); // create CI assert( iMajTruth == 0xE8 || iMajTruth == 0x17 ); iCiLit = Abc_LitNotCond( Gia_ManAppendCi(pNew), (int)(iMajTruth == 0x17) ); } // assign carry out assert( iFadd == Vec_IntEntryLast(vChain) ); pObj = Gia_ManObj( p, Vec_IntEntry(vFadds, 5*iFadd+4) ); pObj->Value = iCiLit; } void Gia_ManDupWithFaddBoxes_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vFadds, Vec_Int_t * vMap, Vec_Wec_t * vChains, Vec_Int_t * vMap2Chain, Vec_Int_t * vTruths ) { int iChain; if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); iChain = Vec_IntEntry( vMap2Chain, Gia_ObjId(p, pObj) ); /* assert( iChain == -1 ); if ( iChain >= 0 ) { Gia_ManDupFadd( pNew, p, Vec_WecEntry(vChains, iChain), vFadds, vMap, vChains, vMap2Chain, vTruths ); assert( ~pObj->Value ); return; } */ Gia_ManDupWithFaddBoxes_rec( pNew, p, Gia_ObjFanin0(pObj), vFadds, vMap, vChains, vMap2Chain, vTruths ); Gia_ManDupWithFaddBoxes_rec( pNew, p, Gia_ObjFanin1(pObj), vFadds, vMap, vChains, vMap2Chain, vTruths ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_Man_t * Gia_ManDupWithNaturalBoxes( Gia_Man_t * p, int nFaddMin, int fVerbose ) { abctime clk = Abc_Clock(); Gia_Man_t * pNew;//, * pTemp; Vec_Int_t * vFadds, * vMap, * vMap2Chain, * vTruths, * vChain; Vec_Wec_t * vChains; Gia_Obj_t * pObj; int i, nBoxes; if ( Gia_ManBoxNum(p) > 0 ) { printf( "Currently natural carry-chains cannot be detected when boxes are present.\n" ); return NULL; } assert( Gia_ManBoxNum(p) == 0 ); // detect FADDs vFadds = Gia_ManDetectFullAdders( p, fVerbose, NULL ); assert( Vec_IntSize(vFadds) % 5 == 0 ); // map MAJ into its FADD vMap = Gia_ManCreateMap( p, vFadds ); // for each FADD, find the longest chain and reorder its inputs Gia_ManFindChains( p, vFadds, vMap ); // returns the set of topmost MAJ nodes vChains = Gia_ManCollectTopmost( p, vFadds, vMap, nFaddMin ); if ( fVerbose ) Gia_ManPrintChains( p, vFadds, vMap, vChains ); if ( Vec_WecSize(vChains) == 0 ) { Vec_IntFree( vFadds ); Vec_IntFree( vMap ); Vec_WecFree( vChains ); return Gia_ManDup( p ); } // returns mapping of each MAJ into the topmost elements of its chain vMap2Chain = Gia_ManFindMapping( p, vFadds, vMap, vChains ); // compute truth tables for FADDs vTruths = Gia_ManCollectTruthTables( p, vFadds ); if ( fVerbose ) Abc_PrintTime( 1, "Carry-chain detection time", Abc_Clock() - clk ); // duplicate clk = Abc_Clock(); 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_WecForEachLevel( vChains, vChain, i ) Gia_ManDupFadd( pNew, p, vChain, vFadds, vMap, vChains, vMap2Chain, vTruths ); Gia_ManForEachCo( p, pObj, i ) Gia_ManDupWithFaddBoxes_rec( pNew, p, Gia_ObjFanin0(pObj), vFadds, vMap, vChains, vMap2Chain, vTruths ); Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); if ( Gia_ManRegNum(p) ) { if ( fVerbose ) printf( "Warning: Sequential design is coverted into combinational one by adding white boxes.\n" ); pNew->nRegs = 0; } assert( !Gia_ManHasDangling(pNew) ); // cleanup Vec_IntFree( vFadds ); Vec_IntFree( vMap ); Vec_WecFree( vChains ); Vec_IntFree( vMap2Chain ); Vec_IntFree( vTruths ); // other information nBoxes = (Gia_ManCiNum(pNew) - Gia_ManCiNum(p)) / 2; assert( nBoxes == (Gia_ManCoNum(pNew) - Gia_ManCoNum(p)) / 3 ); pNew->pManTime = Gia_ManGenerateTim( Gia_ManCiNum(p), Gia_ManCoNum(p), nBoxes, 3, 2 ); pNew->pAigExtra = Gia_ManGenerateExtraAig( nBoxes, 3, 2 ); /* // normalize pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); pNew->pManTime = pTemp->pManTime; pTemp->pManTime = NULL; pNew->pAigExtra = pTemp->pAigExtra; pTemp->pAigExtra = NULL; Gia_ManStop( pTemp ); */ //pNew = Gia_ManDupCollapse( pTemp = pNew, pNew->pAigExtra, NULL ); //Gia_ManStop( pTemp ); //Gia_ManIllustrateBoxes( pNew ); if ( fVerbose ) Abc_PrintTime( 1, "AIG with boxes construction time", Abc_Clock() - clk ); return pNew; } /**Function************************************************************* Synopsis [Converting AIG with annotated carry-chains into AIG with boxes.] Description [Assumes that annotations are pObj->fMark0 or pObj->fMark1. Only one of these can be set to 1. If fMark0 (fMark1) is set to 1, the first (second) input of an AND-gate is chained.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjFanin0CopyCarry( Vec_Int_t * vCarries, Gia_Obj_t * pObj, int Id ) { if ( vCarries == NULL || Vec_IntEntry(vCarries, Gia_ObjFaninId0(pObj, Id)) == -1 ) return Gia_ObjFanin0Copy(pObj); return Abc_LitNotCond( Vec_IntEntry(vCarries, Gia_ObjFaninId0(pObj, Id)), Gia_ObjFaninC0(pObj) ); } int Gia_ObjFanin1CopyCarry( Vec_Int_t * vCarries, Gia_Obj_t * pObj, int Id ) { if ( vCarries == NULL || Vec_IntEntry(vCarries, Gia_ObjFaninId1(pObj, Id)) == -1 ) return Gia_ObjFanin1Copy(pObj); return Abc_LitNotCond( Vec_IntEntry(vCarries, Gia_ObjFaninId1(pObj, Id)), Gia_ObjFaninC1(pObj) ); } Gia_Man_t * Gia_ManDupWithArtificalFaddBoxes( Gia_Man_t * p, int fUseFanout, int fXorTrick ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int nBoxes = Gia_ManBoxNum(p); int i, nRealPis, nRealPos; Vec_Int_t * vCarries = NULL; // make sure two chains do not overlap Gia_ManCleanPhase( p ); Gia_ManForEachCi( p, pObj, i ) assert( !pObj->fMark0 && !pObj->fMark1 ); Gia_ManForEachCo( p, pObj, i ) assert( !pObj->fMark0 && !pObj->fMark1 ); Gia_ManForEachAnd( p, pObj, i ) { assert( !pObj->fMark0 || !pObj->fMark1 ); if ( pObj->fMark0 ) { assert( Gia_ObjFanin0(pObj)->fPhase == 0 ); Gia_ObjFanin0(pObj)->fPhase = 1; } if ( pObj->fMark1 ) { assert( Gia_ObjFanin1(pObj)->fPhase == 0 ); Gia_ObjFanin1(pObj)->fPhase = 1; } } // create mapping for carry-chains if ( !fUseFanout ) vCarries = Vec_IntStartFull( Gia_ManObjNum(p) ); // create references and discount carries if ( vCarries ) { Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) if ( pObj->fMark0 ) Gia_ObjRefFanin0Dec( p, pObj ); else if ( pObj->fMark1 ) Gia_ObjRefFanin1Dec( p, pObj ); } // if AIG already has (natural) FADD boxes, it should not un-normalized 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_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 ( !pObj->fMark0 && !pObj->fMark1 ) // AND-gate pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else // AND-gate with chain { int iCiLit, iOtherLit, iLit0, iLit1, iLit2, iXorLit; assert( pObj->fMark0 != pObj->fMark1 ); iCiLit = pObj->fMark0 ? Gia_ObjFanin0CopyCarry(vCarries, pObj, i) : Gia_ObjFanin1CopyCarry(vCarries, pObj, i); iOtherLit = pObj->fMark0 ? Gia_ObjFanin1Copy(pObj) : Gia_ObjFanin0Copy(pObj); assert( iCiLit >= 0 && iOtherLit >= 0 ); iLit0 = Abc_LitNotCond( iCiLit, Abc_LitIsCompl(iCiLit) ); iLit1 = Abc_LitNotCond( iOtherLit, Abc_LitIsCompl(iCiLit) ); iLit2 = Abc_LitNotCond( 0, Abc_LitIsCompl(iCiLit) ); // add COs assert( !Abc_LitIsCompl(iLit0) ); Gia_ManAppendCo( pNew, iLit0 ); Gia_ManAppendCo( pNew, iLit1 ); Gia_ManAppendCo( pNew, iLit2 ); // add CI (unused sum bit) iXorLit = Gia_ManAppendCi(pNew); // add CI (carry bit) pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), Abc_LitIsCompl(iCiLit) ); if ( vCarries && pObj->fPhase ) { Vec_IntWriteEntry( vCarries, i, pObj->Value ); if ( Gia_ObjRefNum(p, pObj) > 0 ) { if ( fXorTrick ) pObj->Value = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iXorLit, !Abc_LitIsCompl(iCiLit)), iOtherLit ); else pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } } nBoxes++; } } Gia_ManCleanPhase( p ); Vec_IntFreeP( &vCarries ); ABC_FREE( p->pRefs ); assert( !Gia_ManHasDangling(pNew) ); // other information // nBoxes += (Gia_ManCiNum(pNew) - Gia_ManCiNum(p)) / 2; // assert( nBoxes == Gia_ManBoxNum(p) + (Gia_ManCoNum(pNew) - Gia_ManCoNum(p)) / 3 ); nRealPis = Gia_ManBoxNum(p) ? Tim_ManPiNum((Tim_Man_t *)p->pManTime) : Gia_ManCiNum(p); nRealPos = Gia_ManBoxNum(p) ? Tim_ManPoNum((Tim_Man_t *)p->pManTime) : Gia_ManCoNum(p); pNew->pManTime = Gia_ManGenerateTim( nRealPis, nRealPos, nBoxes, 3, 2 ); pNew->pAigExtra = Gia_ManGenerateExtraAig( nBoxes, 3, 2 ); // optionally normalize the AIG return pNew; } Gia_Man_t * Gia_ManDupWithArtificalFaddBoxesTest( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; // label some and-gates Gia_ManCleanMark01( p ); Gia_ManForEachAnd( p, pObj, i ) { pObj->fMark0 = i % 5; pObj->fMark1 = i % 7; if ( pObj->fMark0 && pObj->fMark1 ) pObj->fMark0 = pObj->fMark1 = 0; } // output new AIG pNew = Gia_ManDupWithArtificalFaddBoxes( p, 0, 0 ); Gia_ManCleanMark01( p ); return pNew; } /**Function************************************************************* Synopsis [Adds artificial carry chains to the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // computes AIG delay information when boxes are used int Gia_ManFindAnnotatedDelay( Gia_Man_t * p, int DelayC, int * pnBoxes, int fIgnoreBoxDelays ) { Gia_Obj_t * pObj; int nRealPis = Gia_ManBoxNum(p) ? Tim_ManPiNum((Tim_Man_t *)p->pManTime) : Gia_ManCiNum(p); int * pDelays = Vec_IntArray(p->vLevels); int i, k, iBox, iBoxOutId, Delay, Delay0, Delay1, DelayMax = 0, nBoxes = 0; Vec_IntFill( p->vLevels, Gia_ManObjNum(p), 0 ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { if ( fIgnoreBoxDelays ) continue; // check if it is real PI iBoxOutId = Gia_ObjCioId(pObj) - nRealPis; if ( iBoxOutId < 0 ) continue; // if it is a box output, find box number iBox = iBoxOutId / 2; assert( iBox < Gia_ManBoxNum(p) ); // check find the maximum delay of the box inputs Delay = 0; for ( k = 0; k < 3; k++ ) { int Id = Gia_ObjId( p, Gia_ManCo(p, iBox*3+k) ); assert( Id < i ); Delay = Abc_MaxInt( Delay, pDelays[Id] ); } // consider outputs if ( iBoxOutId & 1 ) // carry output Delay += DelayC; else // sum output Delay += 100; pDelays[i] = Delay; continue; } if ( Gia_ObjIsCo(pObj) ) { pDelays[i] = pDelays[Gia_ObjFaninId0(pObj, i)]; DelayMax = Abc_MaxInt( DelayMax, pDelays[i] ); continue; } assert( !pObj->fMark0 || !pObj->fMark1 ); Delay0 = pDelays[Gia_ObjFaninId0(pObj, i)]; Delay1 = pDelays[Gia_ObjFaninId1(pObj, i)]; if ( pObj->fMark0 ) { Delay = Abc_MaxInt( Delay0 + DelayC, Delay1 + 100 ); nBoxes++; } else if ( pObj->fMark1 ) { Delay = Abc_MaxInt( Delay1 + DelayC, Delay0 + 100 ); nBoxes++; } else Delay = Abc_MaxInt( Delay0 + 100, Delay1 + 100 ); pDelays[i] = Delay; } if ( pnBoxes ) *pnBoxes = nBoxes; return DelayMax; } // check if the object is already used in some chain static inline int Gia_ObjIsUsed( Gia_Obj_t * pObj ) { return pObj->fMark0 || pObj->fMark1 || pObj->fPhase; } // finds internal node that can begin a new chain int Gia_ManFindChainStart( Gia_Man_t * p ) { Gia_Obj_t * pObj; int * pDelays = Vec_IntArray(p->vLevels); int i, iMax = -1, DelayMax = 0; Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsUsed(pObj) ) continue; if ( DelayMax > pDelays[i] ) continue; DelayMax = pDelays[i]; iMax = i; } return iMax; } // finds a sequence of internal nodes that creates a new chain int Gia_ManFindPath( Gia_Man_t * p, int DelayC, int nPathMin, int nPathMax, Vec_Int_t * vPath ) { Gia_Obj_t * pObj, * pFanin0, * pFanin1; int * pDelays = Vec_IntArray(p->vLevels); int i, iLit, iMax = Gia_ManFindChainStart( p ); if ( iMax == -1 ) return -1; Vec_IntClear( vPath ); pObj = Gia_ManObj(p, iMax); assert( Gia_ObjIsAnd(pObj) ); while ( Gia_ObjIsAnd(pObj) ) { assert( !Gia_ObjIsUsed(pObj) ); pFanin0 = Gia_ObjFanin0(pObj); pFanin1 = Gia_ObjFanin1(pObj); if ( Gia_ObjIsUsed(pFanin0) && Gia_ObjIsUsed(pFanin1) ) break; if ( Gia_ObjIsUsed(pFanin0) ) { Vec_IntPush( vPath, Abc_Var2Lit(Gia_ObjId(p, pObj), 1) ); pObj = pFanin1; } else if ( Gia_ObjIsUsed(pFanin1) ) { Vec_IntPush( vPath, Abc_Var2Lit(Gia_ObjId(p, pObj), 0) ); pObj = pFanin0; } else { if ( pDelays[Gia_ObjId(p, pFanin1)] > pDelays[Gia_ObjId(p, pFanin0)] ) { Vec_IntPush( vPath, Abc_Var2Lit(Gia_ObjId(p, pObj), 1) ); pObj = pFanin1; } else { Vec_IntPush( vPath, Abc_Var2Lit(Gia_ObjId(p, pObj), 0) ); pObj = pFanin0; } } } if ( Vec_IntSize(vPath) < nPathMin ) { Gia_ManObj(p, iMax)->fPhase = 1; return 0; } // label nodes if ( Vec_IntSize(vPath) > nPathMax ) Vec_IntShrink( vPath, nPathMax ); Vec_IntForEachEntry( vPath, iLit, i ) { pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); if ( Abc_LitIsCompl(iLit) ) { assert( pObj->fMark1 == 0 ); pObj->fMark1 = 1; assert( Gia_ObjFanin1(pObj)->fPhase == 0 ); Gia_ObjFanin1(pObj)->fPhase = 1; } else { assert( pObj->fMark0 == 0 ); pObj->fMark0 = 1; assert( Gia_ObjFanin0(pObj)->fPhase == 0 ); Gia_ObjFanin0(pObj)->fPhase = 1; } } return Vec_IntSize(vPath); } // iteratively create the given number of chains int Gia_ManIteratePaths( Gia_Man_t * p, int DelayC, int nPathMin, int nPathMax, int nPathLimit, int fIgnoreBoxDelays, int fVerbose ) { Gia_Obj_t * pObj; Vec_Int_t * vPath = Vec_IntAlloc( 100 ); int i, RetValue, nBoxes, MaxDelay, nPaths = 0; assert( p->vLevels == NULL ); p->vLevels = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManCleanMark01( p ); Gia_ManCleanPhase( p ); Gia_ManForEachCi( p, pObj, i ) pObj->fPhase = 1; if ( fVerbose ) printf( "Running path detection: BoxDelay = %d, PathMin = %d, PathMax = %d, PathLimit = %d.\n", DelayC, nPathMin, nPathMax, nPathLimit ); for ( i = 0; i < nPathLimit; i++ ) { MaxDelay = Gia_ManFindAnnotatedDelay( p, DelayC, &nBoxes, fIgnoreBoxDelays ); RetValue = Gia_ManFindPath( p, DelayC, nPathMin, nPathMax, vPath ); if ( RetValue == -1 ) break; nPaths += (RetValue > 0); if ( fVerbose ) printf( "Iter %5d : Paths = %2d. Boxes = %2d. Total boxes = %6d. Max delay = %5d.\n", i, nPaths, RetValue, nBoxes, MaxDelay ); } Vec_IntFree( vPath ); Vec_IntFreeP( &p->vLevels ); Gia_ManCleanPhase( p ); return 1; } // annotate artificial chains and then put them into boxes Gia_Man_t * Gia_ManDupWithArtificialBoxes( Gia_Man_t * p, int DelayC, int nPathMin, int nPathMax, int nPathLimit, int fUseFanout, int fXorTrick, int fIgnoreBoxDelays, int fVerbose ) { Gia_Man_t * pNew; /* if ( Gia_ManBoxNum(p) > 0 ) { printf( "Currently artifical carry-chains cannot be detected when natural ones are present.\n" ); return NULL; } */ Gia_ManIteratePaths( p, DelayC, nPathMin, nPathMax, nPathLimit, fIgnoreBoxDelays, fVerbose ); pNew = Gia_ManDupWithArtificalFaddBoxes( p, fUseFanout, fXorTrick ); Gia_ManCleanMark01( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecInt.h000066400000000000000000000047401300674244400236000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__proof__acec__acec__int_h #define ABC__proof__acec__acec__int_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "proof/cec/cec.h" #include "acec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== acecUtil.c ========================================================*/ extern void Gia_PolynAnalyzeXors( Gia_Man_t * pGia, int fVerbose ); extern Vec_Int_t * Gia_PolynCollectLastXor( Gia_Man_t * pGia, int fVerbose ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecOrder.c000066400000000000000000000234051300674244400241130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecOrder.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Node ordering.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_PolynFindOrder( Gia_Man_t * pGia, Vec_Int_t * vFadds, Vec_Int_t * vHadds, int fVerbose, int fVeryVerbose ) { int fDumpLeftOver = 0; int i, iXor, iMaj, iAnd, Entry, Iter, fFound, fFoundAll = 1; Vec_Int_t * vRecord = Vec_IntAlloc( 100 ), * vLeft, * vRecord2; Vec_Int_t * vMap = Vec_IntStart( Gia_ManObjNum(pGia) ); Gia_ManForEachCoDriverId( pGia, iAnd, i ) Vec_IntWriteEntry( vMap, iAnd, 1 ); // collect the last XOR Vec_IntFreeP( &pGia->vXors ); pGia->vXors = Gia_PolynCollectLastXor( pGia, fVerbose ); printf( "Collected %d topmost XORs\n", Vec_IntSize(pGia->vXors) ); //Vec_IntPrint( p->vXors ); Vec_IntForEachEntry( pGia->vXors, iAnd, i ) { Gia_Obj_t * pAnd = Gia_ManObj( pGia, iAnd ); assert( Vec_IntEntry(vMap, iAnd) ); Vec_IntWriteEntry( vMap, iAnd, 0 ); Vec_IntWriteEntry( vMap, Gia_ObjFaninId0(pAnd, iAnd), 1 ); Vec_IntWriteEntry( vMap, Gia_ObjFaninId1(pAnd, iAnd), 1 ); Vec_IntPush( vRecord, Abc_Var2Lit2(iAnd, 3) ); if ( fVeryVerbose ) printf( "Recognizing %d => XXXOR(%d %d)\n", iAnd, Gia_ObjFaninId0(pAnd, iAnd), Gia_ObjFaninId1(pAnd, iAnd) ); } // detect FAs and HAs for ( Iter = 0; fFoundAll; Iter++ ) { if ( fVeryVerbose ) printf( "Iteration %d\n", Iter ); // check if we can extract FADDs fFoundAll = 0; do { fFound = 0; for ( i = Vec_IntSize(vFadds)/5 - 1; i >= 0; i-- ) { iXor = Vec_IntEntry(vFadds, 5*i+3); iMaj = Vec_IntEntry(vFadds, 5*i+4); if ( Vec_IntEntry(vMap, iXor) && Vec_IntEntry(vMap, iMaj) ) { Vec_IntWriteEntry( vMap, iXor, 0 ); Vec_IntWriteEntry( vMap, iMaj, 0 ); Vec_IntWriteEntry( vMap, Vec_IntEntry(vFadds, 5*i+0), 1 ); Vec_IntWriteEntry( vMap, Vec_IntEntry(vFadds, 5*i+1), 1 ); Vec_IntWriteEntry( vMap, Vec_IntEntry(vFadds, 5*i+2), 1 ); Vec_IntPush( vRecord, Abc_Var2Lit2(i, 2) ); fFound = 1; fFoundAll = 1; if ( fVeryVerbose ) printf( "Recognizing (%d %d) => FA(%d %d %d)\n", iXor, iMaj, Vec_IntEntry(vFadds, 5*i+0), Vec_IntEntry(vFadds, 5*i+1), Vec_IntEntry(vFadds, 5*i+2) ); } } } while ( fFound ); // check if we can extract HADDs do { fFound = 0; for ( i = Vec_IntSize(vHadds)/2 - 1; i >= 0; i-- ) { iXor = Vec_IntEntry(vHadds, 2*i+0); iMaj = Vec_IntEntry(vHadds, 2*i+1); if ( Vec_IntEntry(vMap, iXor) && Vec_IntEntry(vMap, iMaj) ) { Gia_Obj_t * pAnd = Gia_ManObj( pGia, iMaj ); Vec_IntWriteEntry( vMap, iXor, 0 ); Vec_IntWriteEntry( vMap, iMaj, 0 ); Vec_IntWriteEntry( vMap, Gia_ObjFaninId0(pAnd, iMaj), 1 ); Vec_IntWriteEntry( vMap, Gia_ObjFaninId1(pAnd, iMaj), 1 ); Vec_IntPush( vRecord, Abc_Var2Lit2(i, 1) ); fFound = 1; fFoundAll = 1; if ( fVeryVerbose ) printf( "Recognizing (%d %d) => HA(%d %d)\n", iXor, iMaj, Gia_ObjFaninId0(pAnd, iMaj), Gia_ObjFaninId1(pAnd, iMaj) ); } } break; // only one iter! } while ( fFound ); if ( fFoundAll ) continue; /* // find the last one Vec_IntForEachEntryReverse( vMap, Entry, iAnd ) if ( Entry && Gia_ObjIsAnd(Gia_ManObj(pGia, iAnd)) )//&& Vec_IntFind(vFadds, iAnd) == -1 )//&& Vec_IntFind(vHadds, iAnd) == -1 ) { Gia_Obj_t * pFan0, * pFan1, * pAnd = Gia_ManObj( pGia, iAnd ); if ( !Gia_ObjRecognizeExor(pAnd, &pFan0, &pFan1) ) { Vec_IntWriteEntry( vMap, iAnd, 0 ); Vec_IntWriteEntry( vMap, Gia_ObjFaninId0(pAnd, iAnd), 1 ); Vec_IntWriteEntry( vMap, Gia_ObjFaninId1(pAnd, iAnd), 1 ); Vec_IntPush( vRecord, Abc_Var2Lit2(iAnd, 0) ); } else { Vec_IntWriteEntry( vMap, iAnd, 0 ); Vec_IntWriteEntry( vMap, Gia_ObjId(pGia, pFan0), 1 ); Vec_IntWriteEntry( vMap, Gia_ObjId(pGia, pFan1), 1 ); Vec_IntPush( vRecord, Abc_Var2Lit2(iAnd, 0) ); Vec_IntPush( vRecord, Abc_Var2Lit2(Gia_ObjFaninId0(pAnd, iAnd), 0) ); Vec_IntPush( vRecord, Abc_Var2Lit2(Gia_ObjFaninId1(pAnd, iAnd), 0) ); printf( "Recognizing %d => XOR(%d %d)\n", iAnd, Gia_ObjId(pGia, pFan0), Gia_ObjId(pGia, pFan1) ); } fFoundAll = 1; if ( fVeryVerbose ) printf( "Recognizing %d => AND(%d %d)\n", iAnd, Gia_ObjFaninId0(pAnd, iAnd), Gia_ObjFaninId1(pAnd, iAnd) ); break; } */ } //Vec_IntPrint( vMap ); // collect remaining ones vLeft = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vMap, Entry, i ) if ( Entry && Gia_ObjIsAnd(Gia_ManObj(pGia, i)) ) Vec_IntPush( vLeft, i ); Vec_IntFree( vMap ); // collect them in the topo order vRecord2 = Vec_IntAlloc( 100 ); Gia_ManIncrementTravId( pGia ); Gia_ManCollectAnds( pGia, Vec_IntArray(vLeft), Vec_IntSize(vLeft), vRecord2, NULL ); Vec_IntForEachEntry( vRecord2, iAnd, i ) Vec_IntWriteEntry( vRecord2, i, Abc_Var2Lit2(iAnd, 0) ); // dump remaining nodes as an AIG if ( fDumpLeftOver ) { Gia_Man_t * pNew; pNew = Gia_ManDupAndCones( pGia, Vec_IntArray(vLeft), Vec_IntSize(vLeft), 0 ); Gia_AigerWrite( pNew, "leftover.aig", 0, 0 ); printf( "Leftover AIG with %d nodes is dumped into file \"%s\".\n", Gia_ManAndNum(pNew), "leftover.aig" ); Gia_ManStop( pNew ); } Vec_IntFree( vLeft ); Vec_IntReverseOrder( vRecord ); Vec_IntAppend( vRecord2, vRecord ); Vec_IntFree( vRecord ); return vRecord2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_PolynReorder( Gia_Man_t * pGia, int fVerbose, int fVeryVerbose ) { Vec_Int_t * vFadds = Gia_ManDetectFullAdders( pGia, fVeryVerbose, NULL ); Vec_Int_t * vHadds = Gia_ManDetectHalfAdders( pGia, fVeryVerbose ); Vec_Int_t * vRecord = Gia_PolynFindOrder( pGia, vFadds, vHadds, fVerbose, fVeryVerbose ); Vec_Int_t * vOrder = Vec_IntAlloc( Gia_ManAndNum(pGia) ); Vec_Int_t * vOrder2 = Vec_IntStart( Gia_ManObjNum(pGia) ); int i, k, Entry; // collect nodes Gia_ManIncrementTravId( pGia ); Vec_IntForEachEntry( vRecord, Entry, i ) { int Node = Abc_Lit2Var2(Entry); int Attr = Abc_Lit2Att2(Entry); if ( Attr == 2 ) { int * pFanins = Vec_IntEntryP( vFadds, 5*Node ); for ( k = 3; k < 5; k++ ) Gia_ManCollectAnds_rec( pGia, pFanins[k], vOrder ); } else if ( Attr == 1 ) { int * pFanins = Vec_IntEntryP( vHadds, 2*Node ); for ( k = 0; k < 2; k++ ) Gia_ManCollectAnds_rec( pGia, pFanins[k], vOrder ); } else Gia_ManCollectAnds_rec( pGia, Node, vOrder ); //printf( "Order = %d. Node = %d. Size = %d ", i, Node, Vec_IntSize(vOrder) ); } //printf( "\n" ); //assert( Vec_IntSize(vOrder) == Gia_ManAndNum(pGia) ); // remap order Gia_ManForEachCiId( pGia, Entry, i ) Vec_IntWriteEntry( vOrder2, Entry, 1+i ); Vec_IntForEachEntry( vOrder, Entry, i ) Vec_IntWriteEntry( vOrder2, Entry, 1+Gia_ManCiNum(pGia)+i ); //Vec_IntPrint( vOrder ); Vec_IntFree( vRecord ); Vec_IntFree( vFadds ); Vec_IntFree( vHadds ); Vec_IntFree( vOrder ); return vOrder2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecPo.c000066400000000000000000000527051300674244400234230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecPo.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecPo.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" #include "misc/vec/vecWec.h" #include "misc/vec/vecHsh.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prints polynomial.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_PolynPrintMono( Vec_Int_t * vConst, Vec_Int_t * vMono ) { int k, Entry; Vec_IntForEachEntry( vConst, Entry, k ) printf( "%s2^%d", Entry < 0 ? "-" : "+", Abc_AbsInt(Entry)-1 ); Vec_IntForEachEntry( vMono, Entry, k ) printf( " * %d", Entry ); printf( "\n" ); } void Gia_PolynPrint( Vec_Wec_t * vPolyn ) { Vec_Int_t * vConst, * vMono; int i; printf( "Polynomial with %d monomials:\n", Vec_WecSize(vPolyn)/2 ); for ( i = 0; i < Vec_WecSize(vPolyn)/2; i++ ) { vConst = Vec_WecEntry( vPolyn, 2*i+0 ); vMono = Vec_WecEntry( vPolyn, 2*i+1 ); Gia_PolynPrintMono( vConst, vMono ); } } void Gia_PolynPrintStats( Vec_Wec_t * vPolyn ) { Vec_Int_t * vConst, * vCountsP, * vCountsN; int i, Entry, Max = 0; printf( "Polynomial with %d monomials:\n", Vec_WecSize(vPolyn)/2 ); for ( i = 0; i < Vec_WecSize(vPolyn)/2; i++ ) { vConst = Vec_WecEntry( vPolyn, 2*i+0 ); Max = Abc_MaxInt( Max, Abc_AbsInt(Abc_AbsInt(Vec_IntEntry(vConst, 0))) ); } vCountsP = Vec_IntStart( Max + 1 ); vCountsN = Vec_IntStart( Max + 1 ); for ( i = 0; i < Vec_WecSize(vPolyn)/2; i++ ) { vConst = Vec_WecEntry( vPolyn, 2*i+0 ); Entry = Vec_IntEntry(vConst, 0); if ( Entry > 0 ) Vec_IntAddToEntry( vCountsP, Entry, 1 ); else Vec_IntAddToEntry( vCountsN, -Entry, 1 ); } Vec_IntForEachEntry( vCountsN, Entry, i ) if ( Entry ) printf( "-2^%d appears %d times\n", Abc_AbsInt(i)-1, Entry ); Vec_IntForEachEntry( vCountsP, Entry, i ) if ( Entry ) printf( "+2^%d appears %d times\n", Abc_AbsInt(i)-1, Entry ); Vec_IntFree( vCountsP ); Vec_IntFree( vCountsN ); } /**Function************************************************************* Synopsis [Collects polynomial.] Description [Collects non-trivial monomials in the increasing order of the absolute value of the their first coefficients.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Gia_PolynGetResult( Hsh_VecMan_t * pHashC, Hsh_VecMan_t * pHashM, Vec_Int_t * vCoefs ) { Vec_Int_t * vClass, * vLevel, * vArray; Vec_Wec_t * vPolyn, * vSorted; int i, k, iConst, iMono; // find the largest int nLargest = 0, nNonConst = 0; Vec_IntForEachEntry( vCoefs, iConst, iMono ) { //Vec_IntPrint( Hsh_VecReadEntry(pHashM, iMono) ); if ( iConst == 0 ) continue; vArray = Hsh_VecReadEntry( pHashC, iConst ); nLargest = Abc_MaxInt( nLargest, Abc_AbsInt(Vec_IntEntry(vArray, 0)) ); nNonConst++; } // sort by the size of the largest coefficient vSorted = Vec_WecStart( nLargest+1 ); Vec_IntForEachEntry( vCoefs, iConst, iMono ) { if ( iConst == 0 ) continue; vArray = Hsh_VecReadEntry( pHashC, iConst ); vLevel = Vec_WecEntry( vSorted, Abc_AbsInt(Vec_IntEntry(vArray, 0)) ); Vec_IntPushTwo( vLevel, iConst, iMono ); } // reload in the given order vPolyn = Vec_WecAlloc( 2*nNonConst ); Vec_WecForEachLevel( vSorted, vClass, i ) { Vec_IntForEachEntryDouble( vClass, iConst, iMono, k ) { vArray = Hsh_VecReadEntry( pHashC, iConst ); vLevel = Vec_WecPushLevel( vPolyn ); Vec_IntGrow( vLevel, Vec_IntSize(vArray) ); Vec_IntAppend( vLevel, vArray ); vArray = Hsh_VecReadEntry( pHashM, iMono ); vLevel = Vec_WecPushLevel( vPolyn ); Vec_IntGrow( vLevel, Vec_IntSize(vArray) ); Vec_IntAppend( vLevel, vArray ); } } assert( Vec_WecSize(vPolyn) == 2*nNonConst ); Vec_WecFree( vSorted ); return vPolyn; } /**Function************************************************************* Synopsis [Derives new constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_PolynMergeConstOne( Vec_Int_t * vConst, int New ) { int i, Old; assert( New != 0 ); Vec_IntForEachEntry( vConst, Old, i ) { assert( Old != 0 ); if ( Old == New ) // A == B { Vec_IntDrop( vConst, i ); Gia_PolynMergeConstOne( vConst, New > 0 ? New + 1 : New - 1 ); return; } if ( Abc_AbsInt(Old) == Abc_AbsInt(New) ) // A == -B { Vec_IntDrop( vConst, i ); return; } if ( Old + New == 1 || Old + New == -1 ) // sign(A) != sign(B) && abs(abs(A)-abs(B)) == 1 { int Value = Abc_MinInt( Abc_AbsInt(Old), Abc_AbsInt(New) ); Vec_IntDrop( vConst, i ); Gia_PolynMergeConstOne( vConst, (Old + New == 1) ? Value : -Value ); return; } } Vec_IntPushUniqueOrder( vConst, New ); } static inline void Gia_PolynMergeConst( Vec_Int_t * vTempC, Hsh_VecMan_t * pHashC, int iConstAdd ) { int i, New; Vec_Int_t * vConstAdd = Hsh_VecReadEntry( pHashC, iConstAdd ); Vec_IntForEachEntry( vConstAdd, New, i ) { Gia_PolynMergeConstOne( vTempC, New ); vConstAdd = Hsh_VecReadEntry( pHashC, iConstAdd ); } } static inline int Gia_PolynBuildAdd( Hsh_VecMan_t * pHashC, Hsh_VecMan_t * pHashM, Vec_Int_t * vCoefs, Vec_Wec_t * vLit2Mono, Vec_Int_t * vTempC, Vec_Int_t * vTempM ) { int i, iLit, iConst, iConstNew; int iMono = Hsh_VecManAdd(pHashM, vTempM); if ( iMono == Vec_IntSize(vCoefs) ) // new monomial { // map monomial into a constant assert( Vec_IntSize(vTempC) > 0 ); iConst = Hsh_VecManAdd( pHashC, vTempC ); Vec_IntPush( vCoefs, iConst ); // map literals into monomial assert( Vec_IntSize(vTempM) > 0 ); Vec_IntForEachEntry( vTempM, iLit, i ) Vec_WecPush( vLit2Mono, iLit, iMono ); //printf( "New monomial: \n" ); //Gia_PolynPrintMono( vTempC, vTempM ); return 1; } // this monomial exists iConst = Vec_IntEntry( vCoefs, iMono ); if ( iConst ) Gia_PolynMergeConst( vTempC, pHashC, iConst ); iConstNew = Hsh_VecManAdd( pHashC, vTempC ); Vec_IntWriteEntry( vCoefs, iMono, iConstNew ); //printf( "Old monomial: \n" ); //Gia_PolynPrintMono( vTempC, vTempM ); if ( iConst && !iConstNew ) return -1; if ( !iConst && iConstNew ) return 1; return 0; } /**Function************************************************************* Synopsis [Computing for literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_PolynHandleOne( Hsh_VecMan_t * pHashC, Hsh_VecMan_t * pHashM, Vec_Int_t * vCoefs, Vec_Wec_t * vLit2Mono, Vec_Int_t * vTempC, Vec_Int_t * vTempM, int iMono, int iLitOld, int iLitNew0, int iLitNew1 ) { int status, iConst = Vec_IntEntry( vCoefs, iMono ); Vec_Int_t * vArrayC = Hsh_VecReadEntry( pHashC, iConst ); Vec_Int_t * vArrayM = Hsh_VecReadEntry( pHashM, iMono ); // create new monomial Vec_IntClear( vTempM ); Vec_IntAppend( vTempM, vArrayM ); status = Vec_IntRemove( vTempM, iLitOld ); assert( status ); // create new monomial if ( iLitNew0 == -1 && iLitNew1 == -1 ) // no new lit - the same const Vec_IntAppendMinus( vTempC, vArrayC, 0 ); else if ( iLitNew0 > -1 && iLitNew1 == -1 ) // one new lit - opposite const { Vec_IntAppendMinus( vTempC, vArrayC, 1 ); Vec_IntPushUniqueOrder( vTempM, iLitNew0 ); } else if ( iLitNew0 > -1 && iLitNew1 > -1 ) // both new lit - the same const { Vec_IntAppendMinus( vTempC, vArrayC, 0 ); Vec_IntPushUniqueOrder( vTempM, iLitNew0 ); Vec_IntPushUniqueOrder( vTempM, iLitNew1 ); } else assert( 0 ); return Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC, vTempM ); } Vec_Wec_t * Gia_PolynBuildNew2( Gia_Man_t * pGia, Vec_Int_t * vRootLits, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, int fSigned, int fVerbose, int fVeryVerbose ) { abctime clk = Abc_Clock(); Vec_Wec_t * vPolyn; Vec_Wec_t * vLit2Mono = Vec_WecStart( 2 * Gia_ManObjNum(pGia) ); // mapping AIG literals into monomials Hsh_VecMan_t * pHashC = Hsh_VecManStart( 1000 ); // hash table for constants Hsh_VecMan_t * pHashM = Hsh_VecManStart( 1000 ); // hash table for monomials Vec_Int_t * vCoefs = Vec_IntAlloc( 1000 ); // monomial coefficients Vec_Int_t * vTempC = Vec_IntAlloc( 10 ); // temporary array Vec_Int_t * vTempM = Vec_IntAlloc( 10 ); // temporary array int i, k, iObj, iLit, iMono, nMonos = 0, nBuilds = 0; // add 0-constant and 1-monomial Hsh_VecManAdd( pHashC, vTempC ); Hsh_VecManAdd( pHashM, vTempM ); Vec_IntPush( vCoefs, 0 ); // create output signature Vec_IntForEachEntry( vRootLits, iLit, i ) { Vec_IntFill( vTempC, 1, (fSigned && i == Vec_IntSize(vRootLits)-1) ? -i-1 : i+1 ); Vec_IntFill( vTempM, 1, iLit ); nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC, vTempM ); nBuilds++; } // perform construction for internal nodes Vec_IntForEachEntryReverse( vNodes, iObj, i ) { Gia_Obj_t * pObj = Gia_ManObj( pGia, iObj ); int iLits[2] = { Abc_Var2Lit(iObj, 0), Abc_Var2Lit(iObj, 1) }; int iFans[2] = { Gia_ObjFaninLit0(pObj, iObj), Gia_ObjFaninLit1(pObj, iObj) }; // add inverter Vec_Int_t * vArray = Vec_WecEntry( vLit2Mono, iLits[1] ); Vec_IntForEachEntry( vArray, iMono, k ) if ( Vec_IntEntry(vCoefs, iMono) > 0 ) { nMonos += Gia_PolynHandleOne( pHashC, pHashM, vCoefs, vLit2Mono, vTempC, vTempM, iMono, iLits[1], -1, -1 ); nMonos += Gia_PolynHandleOne( pHashC, pHashM, vCoefs, vLit2Mono, vTempC, vTempM, iMono, iLits[1], iLits[0], -1 ); Vec_IntWriteEntry( vCoefs, iMono, 0 ); nMonos--; nBuilds++; nBuilds++; } // add AND gate vArray = Vec_WecEntry( vLit2Mono, iLits[0] ); Vec_IntForEachEntry( vArray, iMono, k ) if ( Vec_IntEntry(vCoefs, iMono) > 0 ) { nMonos += Gia_PolynHandleOne( pHashC, pHashM, vCoefs, vLit2Mono, vTempC, vTempM, iMono, iLits[0], iFans[0], iFans[1] ); Vec_IntWriteEntry( vCoefs, iMono, 0 ); nMonos--; nBuilds++; } //printf( "Obj %5d : nMonos = %6d nUsed = %6d\n", iObj, nBuilds, nMonos ); } // complement leave nodes Vec_IntForEachEntry( vLeaves, iObj, i ) { int iLits[2] = { Abc_Var2Lit(iObj, 0), Abc_Var2Lit(iObj, 1) }; // add inverter Vec_Int_t * vArray = Vec_WecEntry( vLit2Mono, iLits[1] ); Vec_IntForEachEntry( vArray, iMono, k ) if ( Vec_IntEntry(vCoefs, iMono) > 0 ) { nMonos += Gia_PolynHandleOne( pHashC, pHashM, vCoefs, vLit2Mono, vTempC, vTempM, iMono, iLits[1], -1, -1 ); nMonos += Gia_PolynHandleOne( pHashC, pHashM, vCoefs, vLit2Mono, vTempC, vTempM, iMono, iLits[1], iLits[0], -1 ); Vec_IntWriteEntry( vCoefs, iMono, 0 ); nMonos--; nBuilds++; } } // get the results vPolyn = Gia_PolynGetResult( pHashC, pHashM, vCoefs ); printf( "HashC = %d. HashM = %d. Total = %d. Left = %d. Used = %d. ", Hsh_VecSize(pHashC), Hsh_VecSize(pHashM), nBuilds, nMonos, Vec_WecSize(vPolyn)/2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Vec_IntFree( vTempC ); Vec_IntFree( vTempM ); Vec_IntFree( vCoefs ); Vec_WecFree( vLit2Mono ); Hsh_VecManStop( pHashC ); Hsh_VecManStop( pHashM ); return vPolyn; } /**Function************************************************************* Synopsis [Computing for objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_PolynPrepare2( Vec_Int_t * vTempC[2], Vec_Int_t * vTempM[2], int iObj, int iCst ) { Vec_IntFill( vTempC[0], 1, iCst ); Vec_IntFill( vTempC[1], 1, -iCst ); Vec_IntClear( vTempM[0] ); Vec_IntFill( vTempM[1], 1, iObj ); } static inline void Gia_PolynPrepare4( Vec_Int_t * vTempC[4], Vec_Int_t * vTempM[4], Vec_Int_t * vConst, Vec_Int_t * vMono, int iObj, int iFan0, int iFan1 ) { int i, k, Entry; for ( i = 0; i < 4; i++ ) Vec_IntAppendMinus( vTempC[i], vConst, i & 1 ); for ( i = 0; i < 4; i++ ) Vec_IntClear( vTempM[i] ); Vec_IntForEachEntry( vMono, Entry, k ) if ( Entry != iObj ) for ( i = 0; i < 4; i++ ) Vec_IntPush( vTempM[i], Entry ); Vec_IntPushUniqueOrder( vTempM[1], iFan0 ); Vec_IntPushUniqueOrder( vTempM[2], iFan1 ); Vec_IntPushUniqueOrder( vTempM[3], iFan0 ); Vec_IntPushUniqueOrder( vTempM[3], iFan1 ); } Vec_Wec_t * Gia_PolynBuildNew( Gia_Man_t * pGia, Vec_Int_t * vRootLits, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, int fSigned, int fVerbose, int fVeryVerbose ) { abctime clk = Abc_Clock(); Vec_Wec_t * vPolyn; Vec_Wec_t * vLit2Mono = Vec_WecStart( Gia_ManObjNum(pGia) ); // mapping AIG literals into monomials Hsh_VecMan_t * pHashC = Hsh_VecManStart( 1000 ); // hash table for constants Hsh_VecMan_t * pHashM = Hsh_VecManStart( 1000 ); // hash table for monomials Vec_Int_t * vCoefs = Vec_IntAlloc( 1000 ); // monomial coefficients Vec_Int_t * vTempC[4], * vTempM[4]; // temporary array int i, k, iObj, iLit, iMono, iConst, nMonos = 0, nBuilds = 0; for ( i = 0; i < 4; i++ ) vTempC[i] = Vec_IntAlloc( 10 ); for ( i = 0; i < 4; i++ ) vTempM[i] = Vec_IntAlloc( 10 ); // add 0-constant and 1-monomial Hsh_VecManAdd( pHashC, vTempC[0] ); Hsh_VecManAdd( pHashM, vTempM[0] ); Vec_IntPush( vCoefs, 0 ); // create output signature Vec_IntForEachEntry( vRootLits, iLit, i ) { Gia_PolynPrepare2( vTempC, vTempM, Abc_Lit2Var(iLit), i+1 ); if ( fSigned && i == Vec_IntSize(vRootLits)-1 ) { if ( Abc_LitIsCompl(iLit) ) { nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[1], vTempM[0] ); // -C nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[0], vTempM[1] ); // C * Driver nBuilds++; } else nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[1], vTempM[1] ); // -C * Driver } else { if ( Abc_LitIsCompl(iLit) ) { nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[0], vTempM[0] ); // C nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[1], vTempM[1] ); // -C * Driver nBuilds++; } else nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[0], vTempM[1] ); // C * Driver } nBuilds++; } // perform construction for internal nodes Vec_IntForEachEntryReverse( vNodes, iObj, i ) { Gia_Obj_t * pObj = Gia_ManObj( pGia, iObj ); Vec_Int_t * vArray = Vec_WecEntry( vLit2Mono, iObj ); Vec_IntForEachEntry( vArray, iMono, k ) if ( (iConst = Vec_IntEntry(vCoefs, iMono)) > 0 ) { Vec_Int_t * vArrayC = Hsh_VecReadEntry( pHashC, iConst ); Vec_Int_t * vArrayM = Hsh_VecReadEntry( pHashM, iMono ); Gia_PolynPrepare4( vTempC, vTempM, vArrayC, vArrayM, iObj, Gia_ObjFaninId0(pObj, iObj), Gia_ObjFaninId1(pObj, iObj) ); if ( Gia_ObjIsXor(pObj) ) { } else if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) // C * (1 - x) * (1 - y) { nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[0], vTempM[0] ); // C * 1 nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[1], vTempM[1] ); // -C * x nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[3], vTempM[2] ); // -C * y nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[2], vTempM[3] ); // C * x * y nBuilds += 3; } else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) // C * (1 - x) * y { nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[0], vTempM[2] ); // C * y nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[1], vTempM[3] ); // -C * x * y nBuilds += 2; } else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) // C * x * (1 - y) { nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[0], vTempM[1] ); // C * x nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[1], vTempM[3] ); // -C * x * y nBuilds++; } else nMonos += Gia_PolynBuildAdd( pHashC, pHashM, vCoefs, vLit2Mono, vTempC[0], vTempM[3] ); // C * x * y Vec_IntWriteEntry( vCoefs, iMono, 0 ); nMonos--; nBuilds++; } //printf( "Obj %5d : nMonos = %6d nUsed = %6d\n", iObj, nBuilds, nMonos ); } // get the results vPolyn = Gia_PolynGetResult( pHashC, pHashM, vCoefs ); printf( "HashC = %d. HashM = %d. Total = %d. Left = %d. Used = %d. ", Hsh_VecSize(pHashC), Hsh_VecSize(pHashM), nBuilds, nMonos, Vec_WecSize(vPolyn)/2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); for ( i = 0; i < 4; i++ ) Vec_IntFree( vTempC[i] ); for ( i = 0; i < 4; i++ ) Vec_IntFree( vTempM[i] ); Vec_IntFree( vCoefs ); Vec_WecFree( vLit2Mono ); Hsh_VecManStop( pHashC ); Hsh_VecManStop( pHashM ); return vPolyn; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_PolynBuild2Test( Gia_Man_t * pGia ) { Vec_Wec_t * vPolyn; Vec_Int_t * vRootLits = Vec_IntAlloc( Gia_ManCoNum(pGia) ); Vec_Int_t * vLeaves = Vec_IntAlloc( Gia_ManCiNum(pGia) ); Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManAndNum(pGia) ); Gia_Obj_t * pObj; int i; Gia_ManForEachObj( pGia, pObj, i ) if ( Gia_ObjIsCi(pObj) ) Vec_IntPush( vLeaves, i ); else if ( Gia_ObjIsAnd(pObj) ) Vec_IntPush( vNodes, i ); else if ( Gia_ObjIsCo(pObj) ) Vec_IntPush( vRootLits, Gia_ObjFaninLit0p(pGia, pObj) ); vPolyn = Gia_PolynBuildNew( pGia, vRootLits, vLeaves, vNodes, 0, 0, 0 ); // printf( "Polynomial has %d monomials.\n", Vec_WecSize(vPolyn)/2 ); // Gia_PolynPrintStats( vPolyn ); // Gia_PolynPrint( vPolyn ); Vec_WecFree( vPolyn ); Vec_IntFree( vRootLits ); Vec_IntFree( vLeaves ); Vec_IntFree( vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecPolyn.c000066400000000000000000000367341300674244400241520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecPolyn.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Polynomial extraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecPolyn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" #include "misc/vec/vecWec.h" #include "misc/vec/vecHsh.h" #include "misc/vec/vecQue.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* !a -> 1 - a a & b -> ab a | b -> a + b - ab a ^ b -> a + b - 2ab MUX(a, b, c) -> ab | (1 - a)c = ab + (1-a)c - ab(1-a)c = ab + c - ac !a & b -> (1 - a)b = b - ab a & !b -> a(1 - b) = a - ab !a & !b -> 1 - a - b + ab */ typedef struct Pln_Man_t_ Pln_Man_t; struct Pln_Man_t_ { Gia_Man_t * pGia; // AIG manager Hsh_VecMan_t * pHashC; // hash table for constants Hsh_VecMan_t * pHashM; // hash table for monomials Vec_Que_t * vQue; // queue by largest node Vec_Flt_t * vCounts; // largest node Vec_Int_t * vCoefs; // coefficients for each monomial Vec_Int_t * vTempC[2]; // polynomial representation Vec_Int_t * vTempM[4]; // polynomial representation Vec_Int_t * vOrder; // order of collapsing int nBuilds; // built monomials int nUsed; // used monomials }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pln_Man_t * Pln_ManAlloc( Gia_Man_t * pGia, Vec_Int_t * vOrder ) { Pln_Man_t * p = ABC_CALLOC( Pln_Man_t, 1 ); p->pGia = pGia; p->pHashC = Hsh_VecManStart( 1000 ); p->pHashM = Hsh_VecManStart( 1000 ); p->vQue = Vec_QueAlloc( 1000 ); p->vCounts = Vec_FltAlloc( 1000 ); p->vCoefs = Vec_IntAlloc( 1000 ); p->vTempC[0] = Vec_IntAlloc( 100 ); p->vTempC[1] = Vec_IntAlloc( 100 ); p->vTempM[0] = Vec_IntAlloc( 100 ); p->vTempM[1] = Vec_IntAlloc( 100 ); p->vTempM[2] = Vec_IntAlloc( 100 ); p->vTempM[3] = Vec_IntAlloc( 100 ); p->vOrder = vOrder ? Vec_IntDup(vOrder) : Vec_IntStartNatural( Gia_ManObjNum(pGia) ); assert( Vec_IntSize(p->vOrder) == Gia_ManObjNum(pGia) ); Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vCounts) ); // add 0-constant and 1-monomial Hsh_VecManAdd( p->pHashC, p->vTempC[0] ); Hsh_VecManAdd( p->pHashM, p->vTempM[0] ); Vec_FltPush( p->vCounts, 0 ); Vec_IntPush( p->vCoefs, 0 ); return p; } void Pln_ManStop( Pln_Man_t * p ) { Hsh_VecManStop( p->pHashC ); Hsh_VecManStop( p->pHashM ); Vec_QueFree( p->vQue ); Vec_FltFree( p->vCounts ); Vec_IntFree( p->vCoefs ); Vec_IntFree( p->vTempC[0] ); Vec_IntFree( p->vTempC[1] ); Vec_IntFree( p->vTempM[0] ); Vec_IntFree( p->vTempM[1] ); Vec_IntFree( p->vTempM[2] ); Vec_IntFree( p->vTempM[3] ); Vec_IntFree( p->vOrder ); ABC_FREE( p ); } int Pln_ManCompare3( int * pData0, int * pData1 ) { if ( pData0[0] < pData1[0] ) return -1; if ( pData0[0] > pData1[0] ) return 1; if ( pData0[1] < pData1[1] ) return -1; if ( pData0[1] > pData1[1] ) return 1; return 0; } void Pln_ManPrintFinal( Pln_Man_t * p, int fVerbose, int fVeryVerbose ) { Vec_Int_t * vArray; int i, k, Entry, iMono, iConst; // collect triples Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( p->vCoefs, iConst, iMono ) { if ( iConst == 0 ) continue; vArray = Hsh_VecReadEntry( p->pHashC, iConst ); Vec_IntPush( vPairs, Vec_IntEntry(vArray, 0) ); vArray = Hsh_VecReadEntry( p->pHashM, iMono ); Vec_IntPush( vPairs, Vec_IntSize(vArray) ? Vec_IntEntry(vArray, 0) : 0 ); Vec_IntPushTwo( vPairs, iConst, iMono ); } // sort triples qsort( Vec_IntArray(vPairs), Vec_IntSize(vPairs)/4, 16, (int (*)(const void *, const void *))Pln_ManCompare3 ); // print if ( fVerbose ) Vec_IntForEachEntryDouble( vPairs, iConst, iMono, i ) { if ( i % 4 == 0 ) continue; printf( "%-6d : ", i/4 ); vArray = Hsh_VecReadEntry( p->pHashC, iConst ); Vec_IntForEachEntry( vArray, Entry, k ) printf( "%s%d", Entry < 0 ? "-" : "+", (1 << (Abc_AbsInt(Entry)-1)) ); vArray = Hsh_VecReadEntry( p->pHashM, iMono ); Vec_IntForEachEntry( vArray, Entry, k ) printf( " * %d", Entry ); printf( "\n" ); } printf( "HashC = %d. HashM = %d. Total = %d. Used = %d. ", Hsh_VecSize(p->pHashC), Hsh_VecSize(p->pHashM), p->nBuilds, Vec_IntSize(vPairs)/4 ); Vec_IntFree( vPairs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntAppendMinus2x( Vec_Int_t * vVec1, Vec_Int_t * vVec2 ) { int Entry, i; Vec_IntClear( vVec1 ); Vec_IntForEachEntry( vVec2, Entry, i ) Vec_IntPush( vVec1, Entry > 0 ? -Entry-1 : -Entry+1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_PolynMergeConstOne( Vec_Int_t * vConst, int New ) { int i, Old; assert( New != 0 ); Vec_IntForEachEntry( vConst, Old, i ) { assert( Old != 0 ); if ( Old == New ) // A == B { Vec_IntDrop( vConst, i ); Gia_PolynMergeConstOne( vConst, New > 0 ? New + 1 : New - 1 ); return; } if ( Abc_AbsInt(Old) == Abc_AbsInt(New) ) // A == -B { Vec_IntDrop( vConst, i ); return; } if ( Old + New == 1 || Old + New == -1 ) // sign(A) != sign(B) && abs(abs(A)-abs(B)) == 1 { int Value = Abc_MinInt( Abc_AbsInt(Old), Abc_AbsInt(New) ); Vec_IntDrop( vConst, i ); Gia_PolynMergeConstOne( vConst, (Old + New == 1) ? Value : -Value ); return; } } Vec_IntPushUniqueOrder( vConst, New ); } static inline void Gia_PolynMergeConst( Vec_Int_t * vConst, Pln_Man_t * p, int iConstAdd ) { int i, New; Vec_Int_t * vConstAdd = Hsh_VecReadEntry( p->pHashC, iConstAdd ); Vec_IntForEachEntry( vConstAdd, New, i ) { Gia_PolynMergeConstOne( vConst, New ); vConstAdd = Hsh_VecReadEntry( p->pHashC, iConstAdd ); } } static inline void Gia_PolynBuildAdd( Pln_Man_t * p, Vec_Int_t * vTempC, Vec_Int_t * vTempM ) { int iConst, iConstNew, iMono = vTempM ? Hsh_VecManAdd(p->pHashM, vTempM) : 0; p->nBuilds++; if ( iMono == Vec_IntSize(p->vCoefs) ) // new monomial { iConst = Hsh_VecManAdd( p->pHashC, vTempC ); Vec_IntPush( p->vCoefs, iConst ); // Vec_FltPush( p->vCounts, Vec_IntEntryLast(vTempM) ); Vec_FltPush( p->vCounts, (float)Vec_IntEntry(p->vOrder, Vec_IntEntryLast(vTempM)) ); Vec_QuePush( p->vQue, iMono ); // Vec_QueUpdate( p->vQue, iMono ); if ( iConst ) p->nUsed++; return; } // this monomial exists iConst = Vec_IntEntry( p->vCoefs, iMono ); if ( iConst ) Gia_PolynMergeConst( vTempC, p, iConst ); iConstNew = Hsh_VecManAdd( p->pHashC, vTempC ); Vec_IntWriteEntry( p->vCoefs, iMono, iConstNew ); if ( iConst && !iConstNew ) p->nUsed--; else if ( !iConst && iConstNew ) p->nUsed++; //assert( p->nUsed == Vec_IntSize(p->vCoefs) - Vec_IntCountZero(p->vCoefs) ); } void Gia_PolynBuildOne( Pln_Man_t * p, int iMono ) { Gia_Obj_t * pObj; Vec_Int_t * vArray, * vConst; int iFan0, iFan1; int k, iConst, iDriver; assert( Vec_IntSize(p->vCoefs) == Hsh_VecSize(p->pHashM) ); vArray = Hsh_VecReadEntry( p->pHashM, iMono ); iDriver = Vec_IntEntryLast( vArray ); pObj = Gia_ManObj( p->pGia, iDriver ); if ( !Gia_ObjIsAnd(pObj) ) return; assert( !Gia_ObjIsMux(p->pGia, pObj) ); iConst = Vec_IntEntry( p->vCoefs, iMono ); if ( iConst == 0 ) return; Vec_IntWriteEntry( p->vCoefs, iMono, 0 ); p->nUsed--; iFan0 = Gia_ObjFaninId0p(p->pGia, pObj); iFan1 = Gia_ObjFaninId1p(p->pGia, pObj); for ( k = 0; k < 4; k++ ) { Vec_IntClear( p->vTempM[k] ); Vec_IntAppend( p->vTempM[k], vArray ); Vec_IntPop( p->vTempM[k] ); if ( k == 1 || k == 3 ) Vec_IntPushUniqueOrderCost( p->vTempM[k], iFan0, p->vOrder ); // x // Vec_IntPushUniqueOrder( p->vTempM[k], iFan0 ); // x if ( k == 2 || k == 3 ) Vec_IntPushUniqueOrderCost( p->vTempM[k], iFan1, p->vOrder ); // y // Vec_IntPushUniqueOrder( p->vTempM[k], iFan1 ); // y } vConst = Hsh_VecReadEntry( p->pHashC, iConst ); if ( !Gia_ObjIsXor(pObj) ) for ( k = 0; k < 2; k++ ) Vec_IntAppendMinus( p->vTempC[k], vConst, k ); if ( Gia_ObjIsXor(pObj) ) { vConst = Hsh_VecReadEntry( p->pHashC, iConst ); Vec_IntAppendMinus( p->vTempC[0], vConst, 0 ); Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[1] ); // C * x vConst = Hsh_VecReadEntry( p->pHashC, iConst ); Vec_IntAppendMinus( p->vTempC[0], vConst, 0 ); Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[2] ); // C * y //if ( !p->pGia->vXors || Vec_IntFind(p->pGia->vXors, iDriver) == -1 || Vec_IntFind(p->pGia->vXors, iDriver) == 5 ) { vConst = Hsh_VecReadEntry( p->pHashC, iConst ); Vec_IntAppendMinus2x( p->vTempC[0], vConst ); Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[3] ); // -C * x * y } } else if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) // C * (1 - x) * (1 - y) { Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[0] ); // C * 1 Gia_PolynBuildAdd( p, p->vTempC[1], p->vTempM[1] ); // -C * x vConst = Hsh_VecReadEntry( p->pHashC, iConst ); for ( k = 0; k < 2; k++ ) Vec_IntAppendMinus( p->vTempC[k], vConst, k ); Gia_PolynBuildAdd( p, p->vTempC[1], p->vTempM[2] ); // -C * y Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[3] ); // C * x * y } else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) // C * (1 - x) * y { Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[2] ); // C * y Gia_PolynBuildAdd( p, p->vTempC[1], p->vTempM[3] ); // -C * x * y } else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) // C * x * (1 - y) { Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[1] ); // C * x Gia_PolynBuildAdd( p, p->vTempC[1], p->vTempM[3] ); // -C * x * y } else Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[3] ); // C * x * y } void Gia_PolynBuild( Gia_Man_t * pGia, Vec_Int_t * vOrder, int fSigned, int fVerbose, int fVeryVerbose ) { abctime clk = Abc_Clock();//, clk2 = 0; Gia_Obj_t * pObj; Vec_Bit_t * vPres = Vec_BitStart( Gia_ManObjNum(pGia) ); int i, iMono, iDriver, LevPrev, LevCur, Iter, Line = 0; Pln_Man_t * p = Pln_ManAlloc( pGia, vOrder ); Gia_ManForEachCoReverse( pGia, pObj, i ) { Vec_IntFill( p->vTempC[0], 1, i+1 ); // 2^i Vec_IntFill( p->vTempC[1], 1, -i-1 ); // -2^i iDriver = Gia_ObjFaninId0p( pGia, pObj ); Vec_IntFill( p->vTempM[0], 1, iDriver ); // Driver if ( fSigned && i == Gia_ManCoNum(pGia)-1 ) { if ( Gia_ObjFaninC0(pObj) ) { Gia_PolynBuildAdd( p, p->vTempC[1], NULL ); // -C Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[0] ); // C * Driver } else Gia_PolynBuildAdd( p, p->vTempC[1], p->vTempM[0] ); // -C * Driver } else { if ( Gia_ObjFaninC0(pObj) ) { Gia_PolynBuildAdd( p, p->vTempC[0], NULL ); // C Gia_PolynBuildAdd( p, p->vTempC[1], p->vTempM[0] ); // -C * Driver } else Gia_PolynBuildAdd( p, p->vTempC[0], p->vTempM[0] ); // C * Driver } } LevPrev = -1; for ( Iter = 0; ; Iter++ ) { Vec_Int_t * vTempM; //abctime temp = Abc_Clock(); if ( Vec_QueSize(p->vQue) == 0 ) break; iMono = Vec_QuePop(p->vQue); // report vTempM = Hsh_VecReadEntry( p->pHashM, iMono ); //printf( "Removing var %d\n", Vec_IntEntryLast(vTempM) ); LevCur = Vec_IntEntryLast(vTempM); if ( !Gia_ObjIsAnd(Gia_ManObj(pGia, LevCur)) ) continue; if ( LevPrev != LevCur ) { if ( Vec_BitEntry( vPres, LevCur ) && fVerbose ) printf( "Repeating entry %d\n", LevCur ); else Vec_BitSetEntry( vPres, LevCur, 1 ); if ( fVeryVerbose ) printf( "Line%5d Iter%10d : Obj =%6d. Order =%6d. HashC =%6d. HashM =%10d. Total =%10d. Used =%10d.\n", Line++, Iter, LevCur, Vec_IntEntry(p->vOrder, LevCur), Hsh_VecSize(p->pHashC), Hsh_VecSize(p->pHashM), p->nBuilds, p->nUsed ); } LevPrev = LevCur; Gia_PolynBuildOne( p, iMono ); //clk2 += Abc_Clock() - temp; } //Abc_PrintTime( 1, "Time2", clk2 ); Pln_ManPrintFinal( p, fVerbose, fVeryVerbose ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Pln_ManStop( p ); Vec_BitFree( vPres ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_PolynBuild2( Gia_Man_t * pGia, int fSigned, int fVerbose, int fVeryVerbose ) { Hsh_VecMan_t * pHashC = Hsh_VecManStart( 1000 ); // hash table for constants Hsh_VecMan_t * pHashM = Hsh_VecManStart( 1000 ); // hash table for monomials Vec_Wec_t * vLit2Mono = Vec_WecStart( Gia_ManObjNum(pGia) * 2 ); Hsh_VecManStop( pHashC ); Hsh_VecManStop( pHashM ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecRe.c000066400000000000000000000345251300674244400234130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecRe.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecRe.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" #include "misc/vec/vecHash.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define Ree_ForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += pCut[0] + 2 ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Detecting FADDs in the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ree_TruthPrecompute() { word Truths[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; word Truth; int i; for ( i = 0; i < 8; i++ ) { Truth = Truths[i]; Truth = Abc_Tt6SwapAdjacent( Truth, 1 ); Abc_TtPrintHexRev( stdout, &Truth, 3 ); printf( "\n" ); } printf( "\n" ); for ( i = 0; i < 8; i++ ) { Truth = Truths[i]; Truth = Abc_Tt6SwapAdjacent( Truth, 1 ); Truth = Abc_Tt6SwapAdjacent( Truth, 0 ); Abc_TtPrintHexRev( stdout, &Truth, 3 ); printf( "\n" ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Detecting FADDs in the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ree_ManCutMergeOne( int * pCut0, int * pCut1, int * pCut ) { int i, k; for ( k = 0; k <= pCut1[0]; k++ ) pCut[k] = pCut1[k]; for ( i = 1; i <= pCut0[0]; i++ ) { for ( k = 1; k <= pCut1[0]; k++ ) if ( pCut0[i] == pCut1[k] ) break; if ( k <= pCut1[0] ) continue; if ( pCut[0] == 3 ) return 0; pCut[1+pCut[0]++] = pCut0[i]; } assert( pCut[0] == 2 || pCut[0] == 3 ); if ( pCut[1] > pCut[2] ) ABC_SWAP( int, pCut[1], pCut[2] ); assert( pCut[1] < pCut[2] ); if ( pCut[0] == 2 ) return 1; if ( pCut[2] > pCut[3] ) ABC_SWAP( int, pCut[2], pCut[3] ); if ( pCut[1] > pCut[2] ) ABC_SWAP( int, pCut[1], pCut[2] ); assert( pCut[1] < pCut[2] ); assert( pCut[2] < pCut[3] ); return 1; } static inline int Ree_ManCutCheckEqual( Vec_Int_t * vCuts, int * pCutNew ) { int * pList = Vec_IntArray( vCuts ); int i, k, * pCut; Ree_ForEachCut( pList, pCut, i ) { for ( k = 0; k <= pCut[0]; k++ ) if ( pCut[k] != pCutNew[k] ) break; if ( k > pCut[0] ) return 1; } return 0; } static inline int Ree_ManCutFind( int iObj, int * pCut ) { if ( pCut[1] == iObj ) return 0; if ( pCut[2] == iObj ) return 1; if ( pCut[3] == iObj ) return 2; assert( 0 ); return -1; } static inline int Ree_ManCutNotFind( int iObj1, int iObj2, int * pCut ) { if ( pCut[3] != iObj1 && pCut[3] != iObj2 ) return 0; if ( pCut[2] != iObj1 && pCut[2] != iObj2 ) return 1; if ( pCut[1] != iObj1 && pCut[1] != iObj2 ) return 2; assert( 0 ); return -1; } static inline int Ree_ManCutTruthOne( int * pCut0, int * pCut ) { int Truth0 = pCut0[pCut0[0]+1]; int fComp0 = (Truth0 >> 7) & 1; if ( pCut0[0] == 3 ) return Truth0; Truth0 = fComp0 ? ~Truth0 : Truth0; if ( pCut0[0] == 2 ) { int Truths[3][8] = { { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, // {0,1,-} { 0x00, 0x05, 0x0A, 0x0F, 0x50, 0x55, 0x5A, 0x5F }, // {0,-,1} { 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F } // {-,0,1} }; int Truth = Truths[Ree_ManCutNotFind(pCut0[1], pCut0[2], pCut)][Truth0 & 0x7]; return 0xFF & (fComp0 ? ~Truth : Truth); } if ( pCut0[0] == 1 ) { int Truths[3] = { 0x55, 0x33, 0x0F }; int Truth = Truths[Ree_ManCutFind(pCut0[1], pCut)]; return 0xFF & (fComp0 ? ~Truth : Truth); } assert( 0 ); return -1; } static inline int Ree_ManCutTruth( Gia_Obj_t * pObj, int * pCut0, int * pCut1, int * pCut ) { int Truth0 = Ree_ManCutTruthOne( pCut0, pCut ); int Truth1 = Ree_ManCutTruthOne( pCut1, pCut ); Truth0 = Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0; Truth1 = Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1; return 0xFF & (Gia_ObjIsXor(pObj) ? Truth0 ^ Truth1 : Truth0 & Truth1); } #if 0 int Ree_ObjComputeTruth_rec( Gia_Obj_t * pObj ) { int Truth0, Truth1; if ( pObj->Value ) return pObj->Value; assert( Gia_ObjIsAnd(pObj) ); Truth0 = Ree_ObjComputeTruth_rec( Gia_ObjFanin0(pObj) ); Truth1 = Ree_ObjComputeTruth_rec( Gia_ObjFanin1(pObj) ); if ( Gia_ObjIsXor(pObj) ) return (pObj->Value = (Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0) ^ (Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1)); else return (pObj->Value = (Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0) & (Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1)); } void Ree_ObjCleanTruth_rec( Gia_Obj_t * pObj ) { if ( !pObj->Value ) return; pObj->Value = 0; if ( !Gia_ObjIsAnd(pObj) ) return; Ree_ObjCleanTruth_rec( Gia_ObjFanin0(pObj) ); Ree_ObjCleanTruth_rec( Gia_ObjFanin1(pObj) ); } int Ree_ObjComputeTruth( Gia_Man_t * p, int iObj, int * pCut ) { unsigned Truth, Truths[3] = { 0xAA, 0xCC, 0xF0 }; int i; for ( i = 1; i <= pCut[0]; i++ ) Gia_ManObj(p, pCut[i])->Value = Truths[i-1]; Truth = 0xFF & Ree_ObjComputeTruth_rec( Gia_ManObj(p, iObj) ); Ree_ObjCleanTruth_rec( Gia_ManObj(p, iObj) ); return Truth; } #endif /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ree_ManCutPrint( int * pCut, int Count, word Truth ) { int c; printf( "%d : ", Count ); for ( c = 1; c <= pCut[0]; c++ ) printf( "%3d ", pCut[c] ); for ( ; c <= 4; c++ ) printf( " " ); printf( "0x" ); Abc_TtPrintHexRev( stdout, &Truth, 3 ); printf( "\n" ); } void Ree_ManCutMerge( Gia_Man_t * p, int iObj, int * pList0, int * pList1, Vec_Int_t * vCuts, Hash_IntMan_t * pHash, Vec_Int_t * vData ) { int fVerbose = 0; int i, k, c, Value, Truth, TruthC, * pCut0, * pCut1, pCut[5], Count = 0; if ( fVerbose ) printf( "Object %d\n", iObj ); Vec_IntFill( vCuts, 2, 1 ); Vec_IntPush( vCuts, iObj ); Vec_IntPush( vCuts, 0xAA ); Ree_ForEachCut( pList0, pCut0, i ) Ree_ForEachCut( pList1, pCut1, k ) { if ( !Ree_ManCutMergeOne(pCut0, pCut1, pCut) ) continue; if ( Ree_ManCutCheckEqual(vCuts, pCut) ) continue; Truth = TruthC = Ree_ManCutTruth(Gia_ManObj(p, iObj), pCut0, pCut1, pCut); //assert( Truth == Ree_ObjComputeTruth(p, iObj, pCut) ); Vec_IntAddToEntry( vCuts, 0, 1 ); for ( c = 0; c <= pCut[0]; c++ ) Vec_IntPush( vCuts, pCut[c] ); Vec_IntPush( vCuts, Truth ); if ( Truth & 0x80 ) Truth = 0xFF & ~Truth; if ( (Truth == 0x66 || Truth == 0x11 || Truth == 0x22 || Truth == 0x44 || Truth == 0x77) && pCut[0] == 2 ) { assert( pCut[0] == 2 ); Value = Hsh_Int3ManInsert( pHash, pCut[1], pCut[2], 0 ); Vec_IntPushThree( vData, iObj, Value, TruthC ); } else if ( Truth == 0x69 || Truth == 0x17 || Truth == 0x2B || Truth == 0x4D || Truth == 0x71 ) { assert( pCut[0] == 3 ); Value = Hsh_Int3ManInsert( pHash, pCut[1], pCut[2], pCut[3] ); Vec_IntPushThree( vData, iObj, Value, TruthC ); } if ( fVerbose ) Ree_ManCutPrint( pCut, ++Count, TruthC ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ree_ManDeriveAdds( Hash_IntMan_t * p, Vec_Int_t * vData ) { int i, j, k, iObj, iObj2, Value, Truth, CountX, CountM, Index = 0; int nEntries = Hash_IntManEntryNum(p); Vec_Int_t * vAdds = Vec_IntAlloc( 1000 ); Vec_Int_t * vXors = Vec_IntStart( nEntries + 1 ); Vec_Int_t * vMajs = Vec_IntStart( nEntries + 1 ); Vec_Int_t * vIndex = Vec_IntStartFull( nEntries + 1 ); Vec_Int_t * vIndexRev = Vec_IntAlloc( 1000 ); Vec_Wec_t * vXorMap, * vMajMap; Vec_IntForEachEntryTriple( vData, iObj, Value, Truth, i ) { assert( Value <= nEntries ); if ( Truth == 0x66 || Truth == 0x99 || Truth == 0x69 || Truth == 0x96 ) Vec_IntAddToEntry( vXors, Value, 1 ); else Vec_IntAddToEntry( vMajs, Value, 1 ); } // remap these into indexes Vec_IntForEachEntryTwo( vXors, vMajs, CountX, CountM, i ) if ( CountX && CountM ) { Vec_IntPush( vIndexRev, i ); Vec_IntWriteEntry( vIndex, i, Index++ ); } Vec_IntFree( vXors ); Vec_IntFree( vMajs ); printf( "Detected %d shared cuts among %d hashed cuts.\n", Index, nEntries ); // collect nodes vXorMap = Vec_WecStart( Index ); vMajMap = Vec_WecStart( Index ); Vec_IntForEachEntryTriple( vData, iObj, Value, Truth, i ) { Index = Vec_IntEntry( vIndex, Value ); if ( Index == -1 ) continue; if ( Truth == 0x66 || Truth == 0x99 || Truth == 0x69 || Truth == 0x96 ) Vec_WecPush( vXorMap, Index, iObj ); else Vec_WecPush( vMajMap, Index, iObj ); } Vec_IntFree( vIndex ); // create pairs Vec_IntForEachEntry( vIndexRev, Value, i ) { Vec_Int_t * vXorOne = Vec_WecEntry( vXorMap, i ); Vec_Int_t * vMajOne = Vec_WecEntry( vMajMap, i ); Hash_IntObj_t * pObj = Hash_IntObj( p, Value ); Vec_IntForEachEntry( vXorOne, iObj, j ) Vec_IntForEachEntry( vMajOne, iObj2, k ) { Vec_IntPushThree( vAdds, pObj->iData0, pObj->iData1, pObj->iData2 ); Vec_IntPushTwo( vAdds, iObj, iObj2 ); } } Vec_IntFree( vIndexRev ); Vec_WecFree( vXorMap ); Vec_WecFree( vMajMap ); return vAdds; } Vec_Int_t * Ree_ManComputeCuts( Gia_Man_t * p, int fVerbose ) { Gia_Obj_t * pObj; int * pList0, * pList1, i, nCuts = 0; Hash_IntMan_t * pHash = Hash_IntManStart( 1000 ); Vec_Int_t * vAdds; Vec_Int_t * vTemp = Vec_IntAlloc( 1000 ); Vec_Int_t * vData = Vec_IntAlloc( 1000 ); Vec_Int_t * vCuts = Vec_IntAlloc( 30 * Gia_ManAndNum(p) ); Vec_IntFill( vCuts, Gia_ManObjNum(p), 0 ); Gia_ManCleanValue( p ); Gia_ManForEachCi( p, pObj, i ) { Vec_IntWriteEntry( vCuts, Gia_ObjId(p, pObj), Vec_IntSize(vCuts) ); Vec_IntPush( vCuts, 1 ); Vec_IntPush( vCuts, 1 ); Vec_IntPush( vCuts, Gia_ObjId(p, pObj) ); Vec_IntPush( vCuts, 0xAA ); } Gia_ManForEachAnd( p, pObj, i ) { pList0 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId0(pObj, i)) ); pList1 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId1(pObj, i)) ); Ree_ManCutMerge( p, i, pList0, pList1, vTemp, pHash, vData ); Vec_IntWriteEntry( vCuts, i, Vec_IntSize(vCuts) ); Vec_IntAppend( vCuts, vTemp ); nCuts += Vec_IntEntry( vTemp, 0 ); } if ( fVerbose ) printf( "Nodes = %d. Cuts = %d. Cuts/Node = %.2f. Ints/Node = %.2f.\n", Gia_ManAndNum(p), nCuts, 1.0*nCuts/Gia_ManAndNum(p), 1.0*Vec_IntSize(vCuts)/Gia_ManAndNum(p) ); Vec_IntFree( vTemp ); Vec_IntFree( vCuts ); vAdds = Ree_ManDeriveAdds( pHash, vData ); if ( fVerbose ) printf( "Adds = %d. Total = %d. Hashed = %d. Hashed/Adds = %.2f.\n", Vec_IntSize(vAdds)/5, Vec_IntSize(vData)/3, Hash_IntManEntryNum(pHash), 5.0*Hash_IntManEntryNum(pHash)/Vec_IntSize(vAdds) ); Vec_IntFree( vData ); Hash_IntManStop( pHash ); return vAdds; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ree_ManComputeCutsTest( Gia_Man_t * p ) { abctime clk = Abc_Clock(); Vec_Int_t * vAdds = Ree_ManComputeCuts( p, 1 ); int i, Count = 0; for ( i = 0; 5*i < Vec_IntSize(vAdds); i++ ) { if ( Vec_IntEntry(vAdds, 5*i+2) == 0 ) continue; Count++; continue; printf( "%6d : ", i ); printf( "%6d ", Vec_IntEntry(vAdds, 5*i+0) ); printf( "%6d ", Vec_IntEntry(vAdds, 5*i+1) ); printf( "%6d ", Vec_IntEntry(vAdds, 5*i+2) ); printf( " -> " ); printf( "%6d ", Vec_IntEntry(vAdds, 5*i+3) ); printf( "%6d ", Vec_IntEntry(vAdds, 5*i+4) ); printf( "\n" ); } Vec_IntFree( vAdds ); printf( "Detected %d FAs and %d HAs. ", Count, Vec_IntSize(vAdds)/5-Count ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/acecUtil.c000066400000000000000000000062001300674244400237470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acecUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [CEC for arithmetic circuits.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: acecUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "acecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_PolynCollectXors_rec( Gia_Man_t * pGia, int iObj, Vec_Int_t * vXors ) { Gia_Obj_t * pObj = Gia_ManObj( pGia, iObj ); if ( Gia_ObjIsTravIdCurrent(pGia, pObj) ) return; Gia_ObjSetTravIdCurrent(pGia, pObj); if ( !Gia_ObjIsAnd(pObj) || !Gia_ObjIsXor(pObj) || Gia_ObjRefNum(pGia, pObj) > 1 ) return; Gia_PolynCollectXors_rec( pGia, Gia_ObjFaninId0(pObj, iObj), vXors ); Gia_PolynCollectXors_rec( pGia, Gia_ObjFaninId1(pObj, iObj), vXors ); Vec_IntPushUnique( vXors, iObj ); } Vec_Int_t * Gia_PolynCollectLastXor( Gia_Man_t * pGia, int fVerbose ) { Vec_Int_t * vXors = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj = Gia_ManCo( pGia, Gia_ManCoNum(pGia)-1 ); ABC_FREE( pGia->pRefs ); Gia_ManCreateRefs( pGia ); Gia_ManIncrementTravId( pGia ); Gia_PolynCollectXors_rec( pGia, Gia_ObjFaninId0p(pGia, pObj), vXors ); Vec_IntReverseOrder( vXors ); ABC_FREE( pGia->pRefs ); return vXors; } void Gia_PolynAnalyzeXors( Gia_Man_t * pGia, int fVerbose ) { int i, iDriver, Count = 0; Vec_Int_t * vXors = Vec_IntAlloc( 100 ); if ( pGia->pMuxes == NULL ) { printf( "AIG does not have XORs extracted.\n" ); return; } assert( pGia->pMuxes ); Gia_ManForEachCoDriverId( pGia, iDriver, i ) { Vec_IntClear( vXors ); Gia_ManIncrementTravId( pGia ); Gia_PolynCollectXors_rec( pGia, iDriver, vXors ); //printf( "%3d : ", i ); //Vec_IntPrint( vXors ); printf( "%d=%d ", i, Vec_IntSize(vXors) ); Count += Vec_IntSize(vXors); } printf( "Total = %d.\n", Count ); Vec_IntFree( vXors ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/acec/module.make000066400000000000000000000004121300674244400241750ustar00rootroot00000000000000SRC += src/proof/acec/acecCore.c \ src/proof/acec/acecCo.c \ src/proof/acec/acecRe.c \ src/proof/acec/acecPo.c \ src/proof/acec/acecCover.c \ src/proof/acec/acecFadds.c \ src/proof/acec/acecOrder.c \ src/proof/acec/acecPolyn.c \ src/proof/acec/acecUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/000077500000000000000000000000001300674244400217135ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cec.c000066400000000000000000000026611300674244400226160ustar00rootroot00000000000000**CFile**************************************************************** FileName [cec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cec.h000066400000000000000000000265611300674244400226300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cec.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__cec__cec_h #define ABC__aig__cec__cec_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // dynamic SAT parameters typedef struct Cec_ParSat_t_ Cec_ParSat_t; struct Cec_ParSat_t_ { int nBTLimit; // conflict limit at a node int nSatVarMax; // the max number of SAT variables int nCallsRecycle; // calls to perform before recycling SAT solver int fNonChrono; // use non-chronological backtracling (for circuit SAT only) int fPolarFlip; // flops polarity of variables int fCheckMiter; // the circuit is the miter // int fFirstStop; // stop on the first sat output int fLearnCls; // perform clause learning int fVerbose; // verbose stats }; // simulation parameters typedef struct Cec_ParSim_t_ Cec_ParSim_t; struct Cec_ParSim_t_ { int nWords; // the number of simulation words int nFrames; // the number of simulation frames int nRounds; // the number of simulation rounds int nNonRefines; // the max number of rounds without refinement int TimeLimit; // the runtime limit in seconds int fDualOut; // miter with separate outputs int fCheckMiter; // the circuit is the miter // int fFirstStop; // stop on the first sat output int fSeqSimulate; // performs sequential simulation int fLatchCorr; // consider only latch outputs int fConstCorr; // consider only constants int fVeryVerbose; // verbose stats int fVerbose; // verbose stats }; // semiformal parameters typedef struct Cec_ParSmf_t_ Cec_ParSmf_t; struct Cec_ParSmf_t_ { int nWords; // the number of simulation words int nRounds; // the number of simulation rounds int nFrames; // the max number of time frames int nNonRefines; // the max number of rounds without refinement int nMinOutputs; // the min outputs to accumulate int nBTLimit; // conflict limit at a node int TimeLimit; // the runtime limit in seconds int fDualOut; // miter with separate outputs int fCheckMiter; // the circuit is the miter // int fFirstStop; // stop on the first sat output int fVerbose; // verbose stats }; // combinational SAT sweeping parameters typedef struct Cec_ParFra_t_ Cec_ParFra_t; struct Cec_ParFra_t_ { int nWords; // the number of simulation words int nRounds; // the number of simulation rounds int nItersMax; // the maximum number of iterations of SAT sweeping int nBTLimit; // conflict limit at a node int TimeLimit; // the runtime limit in seconds int nLevelMax; // restriction on the level nodes to be swept int nDepthMax; // the depth in terms of steps of speculative reduction int fRewriting; // enables AIG rewriting int fCheckMiter; // the circuit is the miter // int fFirstStop; // stop on the first sat output int fDualOut; // miter with separate outputs int fColorDiff; // miter with separate outputs int fSatSweeping; // enable SAT sweeping int fRunCSat; // enable another solver int fUseOrigIds; // enable recording of original IDs int fVeryVerbose; // verbose stats int fVerbose; // verbose stats int iOutFail; // the failed output }; // combinational equivalence checking parameters typedef struct Cec_ParCec_t_ Cec_ParCec_t; struct Cec_ParCec_t_ { int nBTLimit; // conflict limit at a node int TimeLimit; // the runtime limit in seconds // int fFirstStop; // stop on the first sat output int fUseSmartCnf; // use smart CNF computation int fRewriting; // enables AIG rewriting int fNaive; // performs naive SAT-based checking int fSilent; // print no messages int fVeryVerbose; // verbose stats int fVerbose; // verbose stats int iOutFail; // the number of failed output }; // sequential register correspodence parameters typedef struct Cec_ParCor_t_ Cec_ParCor_t; struct Cec_ParCor_t_ { int nWords; // the number of simulation words int nRounds; // the number of simulation rounds int nFrames; // the number of time frames int nPrefix; // the number of time frames in the prefix int nBTLimit; // conflict limit at a node int nLevelMax; // (scorr only) the max number of levels int nStepsMax; // (scorr only) the max number of induction steps int fLatchCorr; // consider only latch outputs int fConstCorr; // consider only constants int fUseRings; // use rings int fMakeChoices; // use equilvaences as choices int fUseCSat; // use circuit-based solver // int fFirstStop; // stop on the first sat output int fUseSmartCnf; // use smart CNF computation int fStopWhenGone; // quit when PO is not a candidate constant int fVerboseFlops; // verbose stats int fVeryVerbose; // verbose stats int fVerbose; // verbose stats // callback void * pData; void * pFunc; }; // sequential register correspodence parameters typedef struct Cec_ParChc_t_ Cec_ParChc_t; struct Cec_ParChc_t_ { int nWords; // the number of simulation words int nRounds; // the number of simulation rounds int nBTLimit; // conflict limit at a node int fUseRings; // use rings int fUseCSat; // use circuit-based solver int fVeryVerbose; // verbose stats int fVerbose; // verbose stats }; // sequential synthesis parameters typedef struct Cec_ParSeq_t_ Cec_ParSeq_t; struct Cec_ParSeq_t_ { int fUseLcorr; // enables latch correspondence int fUseScorr; // enables signal correspondence int nBTLimit; // (scorr/lcorr) conflict limit at a node int nFrames; // (scorr/lcorr) the number of timeframes int nLevelMax; // (scorr only) the max number of levels int fConsts; // (scl only) merging constants int fEquivs; // (scl only) merging equivalences int fUseMiniSat; // enables MiniSat in lcorr/scorr int nMinDomSize; // the size of minimum clock domain int fVeryVerbose; // verbose stats int fVerbose; // verbose stats }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cecCec.c ==========================================================*/ extern int Cec_ManVerify( Gia_Man_t * p, Cec_ParCec_t * pPars ); extern int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose ); extern int Cec_ManVerifySimple( Gia_Man_t * p ); /*=== cecChoice.c ==========================================================*/ extern Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pPars ); /*=== cecCorr.c ==========================================================*/ extern int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ); extern Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ); /*=== cecCore.c ==========================================================*/ extern void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ); extern void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p ); extern void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p ); extern void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p ); extern void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ); extern void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p ); extern void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p ); extern Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSilent ); extern Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars ); extern void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars ); /*=== cecSeq.c ==========================================================*/ extern int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex ); extern int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars ); extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ); /*=== cecSynth.c ==========================================================*/ extern int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p ); extern int Cec_SeqReadVerbose( Cec_ParSeq_t * p ); extern void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * pPars ); extern int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecCec.c000066400000000000000000000446241300674244400232360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecCec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Integrated combinatinal equivalence checker.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecCec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" #include "proof/fra/fra.h" #include "aig/gia/giaAig.h" #include "misc/extra/extra.h" #include "sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Saves the input pattern with the given number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManTransformPattern( Gia_Man_t * p, int iOut, int * pValues ) { int i; assert( p->pCexComb == NULL ); p->pCexComb = Abc_CexAlloc( 0, Gia_ManCiNum(p), 1 ); p->pCexComb->iPo = iOut; for ( i = 0; i < Gia_ManCiNum(p); i++ ) if ( pValues && pValues[i] ) Abc_InfoSetBit( p->pCexComb->pData, i ); } /**Function************************************************************* Synopsis [Interface to the old CEC engine] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManVerifyOld( Gia_Man_t * pMiter, int fVerbose, int * piOutFail, abctime clkTotal, int fSilent ) { // extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); extern int Ssw_SecCexResimulate( Aig_Man_t * p, int * pModel, int * pnOutputs ); Gia_Man_t * pTemp = Gia_ManTransformMiter( pMiter ); Aig_Man_t * pMiterCec = Gia_ManToAig( pTemp, 0 ); int RetValue, iOut, nOuts; if ( piOutFail ) *piOutFail = -1; Gia_ManStop( pTemp ); // run CEC on this miter RetValue = Fra_FraigCec( &pMiterCec, 10000000, fVerbose ); // report the miter if ( RetValue == 1 ) { if ( !fSilent ) { Abc_Print( 1, "Networks are equivalent. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } } else if ( RetValue == 0 ) { if ( !fSilent ) { Abc_Print( 1, "Networks are NOT EQUIVALENT. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } if ( pMiterCec->pData == NULL ) Abc_Print( 1, "Counter-example is not available.\n" ); else { iOut = Ssw_SecCexResimulate( pMiterCec, (int *)pMiterCec->pData, &nOuts ); if ( iOut == -1 ) Abc_Print( 1, "Counter-example verification has failed.\n" ); else { if ( !fSilent ) { Abc_Print( 1, "Primary output %d has failed", iOut ); if ( nOuts-1 >= 0 ) Abc_Print( 1, ", along with other %d incorrect outputs", nOuts-1 ); Abc_Print( 1, ".\n" ); } if ( piOutFail ) *piOutFail = iOut; } Cec_ManTransformPattern( pMiter, iOut, (int *)pMiterCec->pData ); } } else if ( !fSilent ) { Abc_Print( 1, "Networks are UNDECIDED. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } fflush( stdout ); Aig_ManStop( pMiterCec ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManHandleSpecialCases( Gia_Man_t * p, Cec_ParCec_t * pPars ) { Gia_Obj_t * pObj1, * pObj2; Gia_Obj_t * pDri1, * pDri2; int i; abctime clk = Abc_Clock(); Gia_ManSetPhase( p ); Gia_ManForEachPo( p, pObj1, i ) { pObj2 = Gia_ManPo( p, ++i ); // check if they different on all-0 pattern // (for example, when they have the same driver but complemented) if ( Gia_ObjPhase(pObj1) != Gia_ObjPhase(pObj2) ) { if ( !pPars->fSilent ) { Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d trivially differs (different phase). ", i/2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } pPars->iOutFail = i/2; Cec_ManTransformPattern( p, i/2, NULL ); return 0; } // get the drivers pDri1 = Gia_ObjFanin0(pObj1); pDri2 = Gia_ObjFanin0(pObj2); // drivers are different PIs if ( Gia_ObjIsPi(p, pDri1) && Gia_ObjIsPi(p, pDri2) && pDri1 != pDri2 ) { if ( !pPars->fSilent ) { Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d trivially differs (different PIs). ", i/2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } pPars->iOutFail = i/2; Cec_ManTransformPattern( p, i/2, NULL ); // if their compl attributes are the same - one should be complemented assert( Gia_ObjFaninC0(pObj1) == Gia_ObjFaninC0(pObj2) ); Abc_InfoSetBit( p->pCexComb->pData, Gia_ObjCioId(pDri1) ); return 0; } // one of the drivers is a PI; another is a constant 0 if ( (Gia_ObjIsPi(p, pDri1) && Gia_ObjIsConst0(pDri2)) || (Gia_ObjIsPi(p, pDri2) && Gia_ObjIsConst0(pDri1)) ) { if ( !pPars->fSilent ) { Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d trivially differs (PI vs. constant). ", i/2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } pPars->iOutFail = i/2; Cec_ManTransformPattern( p, i/2, NULL ); // the compl attributes are the same - the PI should be complemented assert( Gia_ObjFaninC0(pObj1) == Gia_ObjFaninC0(pObj2) ); if ( Gia_ObjIsPi(p, pDri1) ) Abc_InfoSetBit( p->pCexComb->pData, Gia_ObjCioId(pDri1) ); else Abc_InfoSetBit( p->pCexComb->pData, Gia_ObjCioId(pDri2) ); return 0; } } if ( Gia_ManAndNum(p) == 0 ) { if ( !pPars->fSilent ) { Abc_Print( 1, "Networks are equivalent. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return 1; } return -1; } /**Function************************************************************* Synopsis [Performs naive checking.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManVerifyNaive( Gia_Man_t * p, Cec_ParCec_t * pPars ) { extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); Gia_Obj_t * pObj0, * pObj1; abctime clkStart = Abc_Clock(); int nPairs = Gia_ManPoNum(p)/2; int nUnsats = 0, nSats = 0, nUndecs = 0, nTrivs = 0; int i, iVar0, iVar1, pLits[2], status, RetValue; ProgressBar * pProgress = Extra_ProgressBarStart( stdout, nPairs ); assert( Gia_ManPoNum(p) % 2 == 0 ); for ( i = 0; i < nPairs; i++ ) { if ( (i & 0xFF) == 0 ) Extra_ProgressBarUpdate( pProgress, i, NULL ); pObj0 = Gia_ManPo(p, 2*i); pObj1 = Gia_ManPo(p, 2*i+1); if ( Gia_ObjChild0(pObj0) == Gia_ObjChild0(pObj1) ) { nUnsats++; nTrivs++; continue; } if ( pPars->TimeLimit && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= pPars->TimeLimit ) { printf( "Timeout (%d sec) is reached.\n", pPars->TimeLimit ); nUndecs = nPairs - nUnsats - nSats; break; } iVar0 = pCnf->pVarNums[ Gia_ObjId(p, pObj0) ]; iVar1 = pCnf->pVarNums[ Gia_ObjId(p, pObj1) ]; assert( iVar0 >= 0 && iVar1 >= 0 ); pLits[0] = Abc_Var2Lit( iVar0, 0 ); pLits[1] = Abc_Var2Lit( iVar1, 0 ); // check direct pLits[0] = lit_neg(pLits[0]); status = sat_solver_solve( pSat, pLits, pLits + 2, pPars->nBTLimit, 0, 0, 0 ); if ( status == l_False ) { pLits[0] = lit_neg( pLits[0] ); pLits[1] = lit_neg( pLits[1] ); RetValue = sat_solver_addclause( pSat, pLits, pLits + 2 ); assert( RetValue ); } else if ( status == l_True ) { printf( "Output %d is SAT.\n", i ); nSats++; continue; } else { nUndecs++; continue; } // check inverse status = sat_solver_solve( pSat, pLits, pLits + 2, pPars->nBTLimit, 0, 0, 0 ); if ( status == l_False ) { pLits[0] = lit_neg( pLits[0] ); pLits[1] = lit_neg( pLits[1] ); RetValue = sat_solver_addclause( pSat, pLits, pLits + 2 ); assert( RetValue ); } else if ( status == l_True ) { printf( "Output %d is SAT.\n", i ); nSats++; continue; } else { nUndecs++; continue; } nUnsats++; } Extra_ProgressBarStop( pProgress ); printf( "UNSAT = %6d. SAT = %6d. UNDEC = %6d. Trivial = %6d. ", nUnsats, nSats, nUndecs, nTrivs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); if ( nSats ) return 0; if ( nUndecs ) return -1; return 1; } /**Function************************************************************* Synopsis [New CEC engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManVerify( Gia_Man_t * pInit, Cec_ParCec_t * pPars ) { int fDumpUndecided = 0; Cec_ParFra_t ParsFra, * pParsFra = &ParsFra; Gia_Man_t * p, * pNew; int RetValue; abctime clk = Abc_Clock(); abctime clkTotal = Abc_Clock(); // consider special cases: // 1) (SAT) a pair of POs have different value under all-0 pattern // 2) (SAT) a pair of POs has different PI/Const drivers // 3) (UNSAT) 1-2 do not hold and there is no nodes RetValue = Cec_ManHandleSpecialCases( pInit, pPars ); if ( RetValue == 0 || RetValue == 1 ) return RetValue; // preprocess p = Gia_ManDup( pInit ); Gia_ManEquivFixOutputPairs( p ); p = Gia_ManCleanup( pNew = p ); Gia_ManStop( pNew ); if ( pPars->fNaive ) { RetValue = Cec_ManVerifyNaive( p, pPars ); Gia_ManStop( p ); return RetValue; } // sweep for equivalences Cec_ManFraSetDefaultParams( pParsFra ); pParsFra->nItersMax = 1000; pParsFra->nBTLimit = pPars->nBTLimit; pParsFra->TimeLimit = pPars->TimeLimit; pParsFra->fVerbose = pPars->fVerbose; pParsFra->fCheckMiter = 1; pParsFra->fDualOut = 1; pNew = Cec_ManSatSweeping( p, pParsFra, pPars->fSilent ); pPars->iOutFail = pParsFra->iOutFail; // update pInit->pCexComb = p->pCexComb; p->pCexComb = NULL; Gia_ManStop( p ); p = pInit; // continue if ( pNew == NULL ) { if ( p->pCexComb != NULL ) { if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) ) Abc_Print( 1, "Counter-example simulation has failed.\n" ); if ( !pPars->fSilent ) { Abc_Print( 1, "Networks are NOT EQUIVALENT. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return 0; } p = Gia_ManDup( pInit ); Gia_ManEquivFixOutputPairs( p ); p = Gia_ManCleanup( pNew = p ); Gia_ManStop( pNew ); pNew = p; } if ( pPars->fVerbose ) { Abc_Print( 1, "Networks are UNDECIDED after the new CEC engine. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } if ( fDumpUndecided ) { ABC_FREE( pNew->pReprs ); ABC_FREE( pNew->pNexts ); Gia_AigerWrite( pNew, "gia_cec_undecided.aig", 0, 0 ); Abc_Print( 1, "The result is written into file \"%s\".\n", "gia_cec_undecided.aig" ); } if ( pPars->TimeLimit && (Abc_Clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit ) { Gia_ManStop( pNew ); return -1; } // call other solver if ( pPars->fVerbose ) Abc_Print( 1, "Calling the old CEC engine.\n" ); fflush( stdout ); RetValue = Cec_ManVerifyOld( pNew, pPars->fVerbose, &pPars->iOutFail, clkTotal, pPars->fSilent ); p->pCexComb = pNew->pCexComb; pNew->pCexComb = NULL; if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) ) Abc_Print( 1, "Counter-example simulation has failed.\n" ); Gia_ManStop( pNew ); return RetValue; } /**Function************************************************************* Synopsis [Simple SAT run to check equivalence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManVerifySimple( Gia_Man_t * p ) { Cec_ParCec_t ParsCec, * pPars = &ParsCec; Cec_ManCecSetDefaultParams( pPars ); pPars->fSilent = 1; assert( Gia_ManCoNum(p) == 2 ); assert( Gia_ManRegNum(p) == 0 ); return Cec_ManVerify( p, pPars ); } /**Function************************************************************* Synopsis [New CEC engine applied to two circuits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose ) { Cec_ParCec_t ParsCec, * pPars = &ParsCec; Gia_Man_t * pMiter; int RetValue; Cec_ManCecSetDefaultParams( pPars ); pPars->fVerbose = fVerbose; pMiter = Gia_ManMiter( p0, p1, 0, 1, 0, 0, pPars->fVerbose ); if ( pMiter == NULL ) return -1; RetValue = Cec_ManVerify( pMiter, pPars ); p0->pCexComb = pMiter->pCexComb; pMiter->pCexComb = NULL; Gia_ManStop( pMiter ); return RetValue; } /**Function************************************************************* Synopsis [New CEC engine applied to two circuits.] Description [Returns 1 if equivalent, 0 if counter-example, -1 if undecided. Counter-example is returned in the first manager as pAig0->pSeqModel. The format is given in Abc_Cex_t (file "abc\src\aig\gia\gia.h").] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManVerifyTwoAigs( Aig_Man_t * pAig0, Aig_Man_t * pAig1, int fVerbose ) { Gia_Man_t * p0, * p1, * pTemp; int RetValue; p0 = Gia_ManFromAig( pAig0 ); p0 = Gia_ManCleanup( pTemp = p0 ); Gia_ManStop( pTemp ); p1 = Gia_ManFromAig( pAig1 ); p1 = Gia_ManCleanup( pTemp = p1 ); Gia_ManStop( pTemp ); RetValue = Cec_ManVerifyTwo( p0, p1, fVerbose ); pAig0->pSeqModel = p0->pCexComb; p0->pCexComb = NULL; Gia_ManStop( p0 ); Gia_ManStop( p1 ); return RetValue; } /**Function************************************************************* Synopsis [Implementation of new signal correspodence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ) { Gia_Man_t * pGia; Cec_ParCor_t CorPars, * pCorPars = &CorPars; Cec_ManCorSetDefaultParams( pCorPars ); pCorPars->fLatchCorr = 1; pCorPars->fUseCSat = fUseCSat; pCorPars->nBTLimit = nConfs; pGia = Gia_ManFromAigSimple( pAig ); Cec_ManLSCorrespondenceClasses( pGia, pCorPars ); Gia_ManReprToAigRepr( pAig, pGia ); Gia_ManStop( pGia ); return Aig_ManDupSimple( pAig ); } /**Function************************************************************* Synopsis [Implementation of new signal correspodence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ) { Gia_Man_t * pGia; Cec_ParCor_t CorPars, * pCorPars = &CorPars; Cec_ManCorSetDefaultParams( pCorPars ); pCorPars->fUseCSat = fUseCSat; pCorPars->nBTLimit = nConfs; pGia = Gia_ManFromAigSimple( pAig ); Cec_ManLSCorrespondenceClasses( pGia, pCorPars ); Gia_ManReprToAigRepr( pAig, pGia ); Gia_ManStop( pGia ); return Aig_ManDupSimple( pAig ); } /**Function************************************************************* Synopsis [Implementation of fraiging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Cec_FraigCombinational( Aig_Man_t * pAig, int nConfs, int fVerbose ) { Gia_Man_t * pGia; Cec_ParFra_t FraPars, * pFraPars = &FraPars; Cec_ManFraSetDefaultParams( pFraPars ); pFraPars->fSatSweeping = 1; pFraPars->nBTLimit = nConfs; pFraPars->nItersMax = 20; pFraPars->fVerbose = fVerbose; pGia = Gia_ManFromAigSimple( pAig ); Cec_ManSatSweeping( pGia, pFraPars, 0 ); Gia_ManReprToAigRepr( pAig, pGia ); Gia_ManStop( pGia ); return Aig_ManDupSimple( pAig ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecChoice.c000066400000000000000000000347611300674244400237370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecChoice.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Computation of structural choices.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecChoice.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" #include "aig/gia/giaAig.h" #include "proof/dch/dch.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ); extern int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore ); extern int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the real value of the literal w/o spec reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cec_ManCombSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj) ); return Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Recursively performs speculative reduction for the object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pRepr; if ( ~pObj->Value ) return; if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) { Cec_ManCombSpecReduce_rec( pNew, p, pRepr ); pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); return; } pObj->Value = Cec_ManCombSpecReal( pNew, p, pObj ); } /**Function************************************************************* Synopsis [Derives SRM for signal correspondence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cec_ManCombSpecReduce( Gia_Man_t * p, Vec_Int_t ** pvOutputs, int fRings ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pRepr; Vec_Int_t * vXorLits; int i, iPrev, iObj, iPrevNew, iObjNew; assert( p->pReprs != NULL ); 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); *pvOutputs = Vec_IntAlloc( 1000 ); vXorLits = Vec_IntAlloc( 1000 ); if ( fRings ) { Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsConst( p, i ) ) { iObjNew = Cec_ManCombSpecReal( pNew, p, pObj ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ); if ( iObjNew != 0 ) { Vec_IntPush( *pvOutputs, 0 ); Vec_IntPush( *pvOutputs, i ); Vec_IntPush( vXorLits, iObjNew ); } } else if ( Gia_ObjIsHead( p, i ) ) { iPrev = i; Gia_ClassForEachObj1( p, i, iObj ) { iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) ); iObjNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) ); iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) { Vec_IntPush( *pvOutputs, iPrev ); Vec_IntPush( *pvOutputs, iObj ); Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); } iPrev = iObj; } iObj = i; iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) ); iObjNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) ); iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) { Vec_IntPush( *pvOutputs, iPrev ); Vec_IntPush( *pvOutputs, iObj ); Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); } } } } else { Gia_ManForEachObj1( p, pObj, i ) { pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); if ( pRepr == NULL ) continue; iPrevNew = Gia_ObjIsConst(p, i)? 0 : Cec_ManCombSpecReal( pNew, p, pRepr ); iObjNew = Cec_ManCombSpecReal( pNew, p, pObj ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); if ( iPrevNew != iObjNew ) { Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); } } } Vec_IntForEachEntry( vXorLits, iObjNew, i ) Gia_ManAppendCo( pNew, iObjNew ); Vec_IntFree( vXorLits ); Gia_ManHashStop( pNew ); //Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); pNew = Gia_ManCleanup( pTemp = pNew ); //Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManChoiceComputation_int( Gia_Man_t * pAig, Cec_ParChc_t * pPars ) { int nItersMax = 1000; Vec_Str_t * vStatus; Vec_Int_t * vOutputs; Vec_Int_t * vCexStore; Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; Cec_ManSim_t * pSim; Gia_Man_t * pSrm; int r, RetValue; abctime clkSat = 0, clkSim = 0, clkSrm = 0, clkTotal = Abc_Clock(); abctime clk2, clk = Abc_Clock(); ABC_FREE( pAig->pReprs ); ABC_FREE( pAig->pNexts ); Gia_ManRandom( 1 ); // prepare simulation manager Cec_ManSimSetDefaultParams( pParsSim ); pParsSim->nWords = pPars->nWords; pParsSim->nFrames = pPars->nRounds; pParsSim->fVerbose = pPars->fVerbose; pParsSim->fLatchCorr = 0; pParsSim->fSeqSimulate = 0; // create equivalence classes of registers pSim = Cec_ManSimStart( pAig, pParsSim ); Cec_ManSimClassesPrepare( pSim, -1 ); Cec_ManSimClassesRefine( pSim ); // prepare SAT solving Cec_ManSatSetDefaultParams( pParsSat ); pParsSat->nBTLimit = pPars->nBTLimit; pParsSat->fVerbose = pPars->fVerbose; if ( pPars->fVerbose ) { Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Ring = %d. CSat = %d.\n", Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), pPars->nBTLimit, pPars->fUseRings, pPars->fUseCSat ); Cec_ManRefinedClassPrintStats( pAig, NULL, 0, Abc_Clock() - clk ); } // perform refinement of equivalence classes for ( r = 0; r < nItersMax; r++ ) { clk = Abc_Clock(); // perform speculative reduction clk2 = Abc_Clock(); pSrm = Cec_ManCombSpecReduce( pAig, &vOutputs, pPars->fUseRings ); assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManCiNum(pSrm) == Gia_ManCiNum(pAig) ); clkSrm += Abc_Clock() - clk2; if ( Gia_ManCoNum(pSrm) == 0 ) { if ( pPars->fVerbose ) Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, Abc_Clock() - clk ); Vec_IntFree( vOutputs ); Gia_ManStop( pSrm ); break; } //Gia_DumpAiger( pSrm, "choicesrm", r, 2 ); // found counter-examples to speculation clk2 = Abc_Clock(); if ( pPars->fUseCSat ) vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); else vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); Gia_ManStop( pSrm ); clkSat += Abc_Clock() - clk2; if ( Vec_IntSize(vCexStore) == 0 ) { if ( pPars->fVerbose ) Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, Abc_Clock() - clk ); Vec_IntFree( vCexStore ); Vec_StrFree( vStatus ); Vec_IntFree( vOutputs ); break; } // refine classes with these counter-examples clk2 = Abc_Clock(); RetValue = Cec_ManResimulateCounterExamplesComb( pSim, vCexStore ); Vec_IntFree( vCexStore ); clkSim += Abc_Clock() - clk2; Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); if ( pPars->fVerbose ) Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, Abc_Clock() - clk ); Vec_StrFree( vStatus ); Vec_IntFree( vOutputs ); //Gia_ManEquivPrintClasses( pAig, 1, 0 ); } // check the overflow if ( r == nItersMax ) Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" ); Cec_ManSimStop( pSim ); clkTotal = Abc_Clock() - clkTotal; // report the results if ( pPars->fVerbose ) { Abc_PrintTimeP( 1, "Srm ", clkSrm, clkTotal ); Abc_PrintTimeP( 1, "Sat ", clkSat, clkTotal ); Abc_PrintTimeP( 1, "Sim ", clkSim, clkTotal ); Abc_PrintTimeP( 1, "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); Abc_PrintTime( 1, "TOTAL", clkTotal ); } return 0; } /**Function************************************************************* Synopsis [Computes choices for the vector of AIGs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cec_ManChoiceComputationVec( Gia_Man_t * pGia, int nGias, Cec_ParChc_t * pPars ) { Gia_Man_t * pNew; int RetValue; // compute equivalences of the miter // pMiter = Gia_ManChoiceMiter( vGias ); // Gia_ManSetRegNum( pMiter, 0 ); RetValue = Cec_ManChoiceComputation_int( pGia, pPars ); // derive AIG with choices pNew = Gia_ManEquivToChoices( pGia, nGias ); // Gia_ManHasChoices_very_old( pNew ); // Gia_ManStop( pMiter ); // report the results if ( pPars->fVerbose ) { // Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", // Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), // 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), // Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), // 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); } return pNew; } /**Function************************************************************* Synopsis [Computes choices for one AIGs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pParsChc ) { // extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); Dch_Pars_t Pars, * pPars = &Pars; Aig_Man_t * pMan, * pManNew; Gia_Man_t * pGia; if ( 0 ) { pGia = Cec_ManChoiceComputationVec( pAig, 3, pParsChc ); } else { pMan = Gia_ManToAig( pAig, 0 ); Dch_ManSetDefaultParams( pPars ); pPars->fUseGia = 1; pPars->nBTLimit = pParsChc->nBTLimit; pPars->fUseCSat = pParsChc->fUseCSat; pPars->fVerbose = pParsChc->fVerbose; pManNew = Dar_ManChoiceNew( pMan, pPars ); pGia = Gia_ManFromAig( pManNew ); Aig_ManStop( pManNew ); // Aig_ManStop( pMan ); } return pGia; } /**Function************************************************************* Synopsis [Performs computation of AIGs with choices.] Description [Takes several AIGs and performs choicing.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars ) { Cec_ParChc_t ParsChc, * pParsChc = &ParsChc; Aig_Man_t * pAig; if ( pPars->fVerbose ) Abc_PrintTime( 1, "Synthesis time", pPars->timeSynth ); Cec_ManChcSetDefaultParams( pParsChc ); pParsChc->nBTLimit = pPars->nBTLimit; pParsChc->fUseCSat = pPars->fUseCSat; if ( pParsChc->fUseCSat && pParsChc->nBTLimit > 100 ) pParsChc->nBTLimit = 100; pParsChc->fVerbose = pPars->fVerbose; pGia = Cec_ManChoiceComputationVec( pGia, 3, pParsChc ); Gia_ManSetRegNum( pGia, Gia_ManRegNum(pGia) ); pAig = Gia_ManToAig( pGia, 1 ); Gia_ManStop( pGia ); return pAig; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecClass.c000066400000000000000000000656321300674244400236130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecClass.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Equivalence class refinement.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecClass.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned * Cec_ObjSim( Cec_ManSim_t * p, int Id ) { return p->pMems + p->pSimInfo[Id] + 1; } static inline void Cec_ObjSetSim( Cec_ManSim_t * p, int Id, int n ) { p->pSimInfo[Id] = n; } static inline float Cec_MemUsage( Cec_ManSim_t * p ) { return 1.0*p->nMemsMax*(p->pPars->nWords+1)/(1<<20); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Compares simulation info of one node with constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimCompareConst( unsigned * p, int nWords ) { int w; if ( p[0] & 1 ) { for ( w = 0; w < nWords; w++ ) if ( p[w] != ~0 ) return 0; return 1; } else { for ( w = 0; w < nWords; w++ ) if ( p[w] != 0 ) return 0; return 1; } } /**Function************************************************************* Synopsis [Compares simulation info of two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimCompareEqual( unsigned * p0, unsigned * p1, int nWords ) { int w; if ( (p0[0] & 1) == (p1[0] & 1) ) { 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 [Returns the number of the first non-equal bit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimCompareConstFirstBit( unsigned * p, int nWords ) { int w; if ( p[0] & 1 ) { for ( w = 0; w < nWords; w++ ) if ( p[w] != ~0 ) return 32*w + Gia_WordFindFirstBit( ~p[w] ); return -1; } else { for ( w = 0; w < nWords; w++ ) if ( p[w] != 0 ) return 32*w + Gia_WordFindFirstBit( p[w] ); return -1; } } /**Function************************************************************* Synopsis [Compares simulation info of two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimCompareEqualFirstBit( unsigned * p0, unsigned * p1, int nWords ) { int w; if ( (p0[0] & 1) == (p1[0] & 1) ) { for ( w = 0; w < nWords; w++ ) if ( p0[w] != p1[w] ) return 32*w + Gia_WordFindFirstBit( p0[w] ^ p1[w] ); return -1; } else { for ( w = 0; w < nWords; w++ ) if ( p0[w] != ~p1[w] ) return 32*w + Gia_WordFindFirstBit( p0[w] ^ ~p1[w] ); return -1; } } /**Function************************************************************* Synopsis [Returns the number of the first non-equal bit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimCompareConstScore( unsigned * p, int nWords, int * pScores ) { int w, b; if ( p[0] & 1 ) { for ( w = 0; w < nWords; w++ ) if ( p[w] != ~0 ) for ( b = 0; b < 32; b++ ) if ( ((~p[w]) >> b ) & 1 ) pScores[32*w + b]++; } else { for ( w = 0; w < nWords; w++ ) if ( p[w] != 0 ) for ( b = 0; b < 32; b++ ) if ( ((p[w]) >> b ) & 1 ) pScores[32*w + b]++; } } /**Function************************************************************* Synopsis [Compares simulation info of two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimCompareEqualScore( unsigned * p0, unsigned * p1, int nWords, int * pScores ) { int w, b; if ( (p0[0] & 1) == (p1[0] & 1) ) { for ( w = 0; w < nWords; w++ ) if ( p0[w] != p1[w] ) for ( b = 0; b < 32; b++ ) if ( ((p0[w] ^ p1[w]) >> b ) & 1 ) pScores[32*w + b]++; } else { for ( w = 0; w < nWords; w++ ) if ( p0[w] != ~p1[w] ) for ( b = 0; b < 32; b++ ) if ( ((p0[w] ^ ~p1[w]) >> b ) & 1 ) pScores[32*w + b]++; } } /**Function************************************************************* Synopsis [Creates equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimClassCreate( 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 Cec_ManSimClassRefineOne( Cec_ManSim_t * p, int i ) { unsigned * pSim0, * pSim1; int Ent; Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Vec_IntPush( p->vClassOld, i ); pSim0 = Cec_ObjSim(p, i); Gia_ClassForEachObj1( p->pAig, i, Ent ) { pSim1 = Cec_ObjSim(p, Ent); if ( Cec_ManSimCompareEqual( pSim0, pSim1, p->nWords ) ) Vec_IntPush( p->vClassOld, Ent ); else { Vec_IntPush( p->vClassNew, Ent ); if ( p->pBestState ) Cec_ManSimCompareEqualScore( pSim0, pSim1, p->nWords, p->pScores ); } } if ( Vec_IntSize( p->vClassNew ) == 0 ) return 0; Cec_ManSimClassCreate( p->pAig, p->vClassOld ); Cec_ManSimClassCreate( p->pAig, p->vClassNew ); if ( Vec_IntSize(p->vClassNew) > 1 ) return 1 + Cec_ManSimClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); return 1; } /**Function************************************************************* Synopsis [Refines one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i ) { int iRepr, Ent; if ( Gia_ObjIsConst(p->pAig, i) ) { Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); return 1; } if ( !Gia_ObjIsClass(p->pAig, i) ) return 0; assert( Gia_ObjIsClass(p->pAig, i) ); iRepr = Gia_ObjRepr( p->pAig, i ); if ( iRepr == GIA_VOID ) iRepr = i; // collect nodes Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Gia_ClassForEachObj( p->pAig, iRepr, Ent ) { if ( Ent == i ) Vec_IntPush( p->vClassNew, Ent ); else Vec_IntPush( p->vClassOld, Ent ); } assert( Vec_IntSize( p->vClassNew ) == 1 ); Cec_ManSimClassCreate( p->pAig, p->vClassOld ); Cec_ManSimClassCreate( p->pAig, p->vClassNew ); assert( !Gia_ObjIsClass(p->pAig, i) ); return 1; } /**Function************************************************************* Synopsis [Computes hash key of the simuation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimHashKey( 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 [Resets pointers to the simulation memory.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimMemRelink( Cec_ManSim_t * p ) { unsigned * pPlace, Ent; 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->nWordsOld = p->nWords; } /**Function************************************************************* Synopsis [References simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Cec_ManSimSimRef( Cec_ManSim_t * p, int i ) { unsigned * pSim; assert( p->pSimInfo[i] == 0 ); if ( p->MemFree == 0 ) { 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 ); Cec_ManSimMemRelink( p ); } p->pSimInfo[i] = p->MemFree; pSim = p->pMems + p->MemFree; p->MemFree = pSim[0]; pSim[0] = Gia_ObjValue( Gia_ManObj(p->pAig, i) ); p->nMems++; if ( p->nMemsMax < p->nMems ) p->nMemsMax = p->nMems; return pSim; } /**Function************************************************************* Synopsis [Dereferences simulaton info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Cec_ManSimSimDeref( Cec_ManSim_t * p, int i ) { unsigned * pSim; assert( p->pSimInfo[i] > 0 ); pSim = p->pMems + p->pSimInfo[i]; if ( --pSim[0] == 0 ) { pSim[0] = p->MemFree; p->MemFree = p->pSimInfo[i]; p->pSimInfo[i] = 0; p->nMems--; } return pSim; } /**Function************************************************************* Synopsis [Refines nodes belonging to candidate constant class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimProcessRefined( Cec_ManSim_t * p, Vec_Int_t * vRefined ) { unsigned * pSim; int * pTable, nTableSize, i, k, Key; if ( Vec_IntSize(vRefined) == 0 ) return; nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 3 ); pTable = ABC_CALLOC( int, nTableSize ); Vec_IntForEachEntry( vRefined, i, k ) { pSim = Cec_ObjSim( p, i ); assert( !Cec_ManSimCompareConst( pSim, p->nWords ) ); Key = Cec_ManSimHashKey( 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 ) ) Cec_ManSimClassRefineOne( p, i ); } Vec_IntForEachEntry( vRefined, i, k ) Cec_ManSimSimDeref( p, i ); ABC_FREE( pTable ); } /**Function************************************************************* Synopsis [Saves the input pattern with the given number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimSavePattern( Cec_ManSim_t * p, int iPat ) { unsigned * pInfo; int i; assert( p->pCexComb == NULL ); assert( iPat >= 0 && iPat < 32 * p->nWords ); p->pCexComb = (Abc_Cex_t *)ABC_CALLOC( char, sizeof(Abc_Cex_t) + sizeof(unsigned) * Abc_BitWordNum(Gia_ManCiNum(p->pAig)) ); p->pCexComb->iPo = p->iOut; p->pCexComb->nPis = Gia_ManCiNum(p->pAig); p->pCexComb->nBits = Gia_ManCiNum(p->pAig); for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) { pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i ); if ( Abc_InfoHasBit( pInfo, iPat ) ) Abc_InfoSetBit( p->pCexComb->pData, i ); } } /**Function************************************************************* Synopsis [Find the best pattern using the scores.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimFindBestPattern( Cec_ManSim_t * p ) { unsigned * pInfo; int i, ScoreBest = 0, iPatBest = 1; // set the first pattern // find the best pattern for ( i = 0; i < 32 * p->nWords; i++ ) if ( ScoreBest < p->pScores[i] ) { ScoreBest = p->pScores[i]; iPatBest = i; } // compare this with the available patterns - and save if ( p->pBestState->iPo <= ScoreBest ) { assert( p->pBestState->nRegs == Gia_ManRegNum(p->pAig) ); for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i ); if ( Abc_InfoHasBit(p->pBestState->pData, i) != Abc_InfoHasBit(pInfo, iPatBest) ) Abc_InfoXorBit( p->pBestState->pData, i ); } p->pBestState->iPo = ScoreBest; } } /**Function************************************************************* Synopsis [Returns 1 if computation should stop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimAnalyzeOutputs( Cec_ManSim_t * p ) { unsigned * pInfo, * pInfo2; int i; if ( !p->pPars->fCheckMiter ) return 0; assert( p->vCoSimInfo != NULL ); // compare outputs with 0 if ( p->pPars->fDualOut ) { assert( (Gia_ManPoNum(p->pAig) & 1) == 0 ); for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ ) { pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i ); pInfo2 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, ++i ); if ( !Cec_ManSimCompareEqual( pInfo, pInfo2, p->nWords ) ) { if ( p->iOut == -1 ) { p->iOut = i/2; Cec_ManSimSavePattern( p, Cec_ManSimCompareEqualFirstBit(pInfo, pInfo2, p->nWords) ); } if ( p->pCexes == NULL ) p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig)/2 ); if ( p->pCexes[i/2] == NULL ) { p->nOuts++; p->pCexes[i/2] = (void *)1; } } } } else { for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ ) { pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i ); if ( !Cec_ManSimCompareConst( pInfo, p->nWords ) ) { if ( p->iOut == -1 ) { p->iOut = i; Cec_ManSimSavePattern( p, Cec_ManSimCompareConstFirstBit(pInfo, p->nWords) ); } if ( p->pCexes == NULL ) p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig) ); if ( p->pCexes[i] == NULL ) { p->nOuts++; p->pCexes[i] = (void *)1; } } } } return p->pCexes != NULL; } /**Function************************************************************* Synopsis [Simulates one round.] Description [Returns the number of PO entry if failed; 0 otherwise.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ) { Gia_Obj_t * pObj; unsigned * pRes0, * pRes1, * pRes; int i, k, w, Ent, iCiId = 0, iCoId = 0; // prepare internal storage if ( p->nWordsOld != p->nWords ) Cec_ManSimMemRelink( p ); p->nMemsMax = 0; // allocate score counters ABC_FREE( p->pScores ); if ( p->pBestState ) p->pScores = ABC_CALLOC( int, 32 * p->nWords ); // simulate nodes Vec_IntClear( p->vRefinedC ); if ( Gia_ObjValue(Gia_ManConst0(p->pAig)) ) { pRes = Cec_ManSimSimRef( p, 0 ); for ( w = 1; w <= p->nWords; w++ ) pRes[w] = 0; } Gia_ManForEachObj1( p->pAig, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjValue(pObj) == 0 ) { iCiId++; continue; } pRes = Cec_ManSimSimRef( p, i ); if ( vInfoCis ) { pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, iCiId++ ); for ( w = 1; w <= p->nWords; w++ ) pRes[w] = pRes0[w-1]; } else { for ( w = 1; w <= p->nWords; w++ ) pRes[w] = Gia_ManRandom( 0 ); } // make sure the first pattern is always zero pRes[1] ^= (pRes[1] & 1); goto references; } if ( Gia_ObjIsCo(pObj) ) // co always has non-zero 1st fanin and zero 2nd fanin { pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) ); if ( vInfoCos ) { pRes = (unsigned *)Vec_PtrEntry( vInfoCos, iCoId++ ); if ( Gia_ObjFaninC0(pObj) ) for ( w = 1; w <= p->nWords; w++ ) pRes[w-1] = ~pRes0[w]; else for ( w = 1; w <= p->nWords; w++ ) pRes[w-1] = pRes0[w]; } continue; } assert( Gia_ObjValue(pObj) ); pRes = Cec_ManSimSimRef( p, i ); pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) ); pRes1 = Cec_ManSimSimDeref( p, Gia_ObjFaninId1(pObj,i) ); // Abc_Print( 1, "%d,%d ", Gia_ObjValue( Gia_ObjFanin0(pObj) ), Gia_ObjValue( Gia_ObjFanin1(pObj) ) ); if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) for ( w = 1; w <= p->nWords; w++ ) pRes[w] = ~(pRes0[w] | pRes1[w]); else for ( w = 1; w <= p->nWords; w++ ) pRes[w] = ~pRes0[w] & pRes1[w]; } else { if ( Gia_ObjFaninC1(pObj) ) for ( w = 1; w <= p->nWords; w++ ) pRes[w] = pRes0[w] & ~pRes1[w]; else for ( w = 1; w <= p->nWords; w++ ) pRes[w] = pRes0[w] & pRes1[w]; } references: // if this node is candidate constant, collect it if ( Gia_ObjIsConst(p->pAig, i) && !Cec_ManSimCompareConst(pRes + 1, p->nWords) ) { pRes[0]++; Vec_IntPush( p->vRefinedC, i ); if ( p->pBestState ) Cec_ManSimCompareConstScore( pRes + 1, p->nWords, p->pScores ); } // if the node belongs to a class, save it if ( Gia_ObjIsClass(p->pAig, i) ) pRes[0]++; // if this is the last node of the class, process it if ( Gia_ObjIsTail(p->pAig, i) ) { Vec_IntClear( p->vClassTemp ); Gia_ClassForEachObj( p->pAig, Gia_ObjRepr(p->pAig, i), Ent ) Vec_IntPush( p->vClassTemp, Ent ); Cec_ManSimClassRefineOne( p, Gia_ObjRepr(p->pAig, i) ); Vec_IntForEachEntry( p->vClassTemp, Ent, k ) Cec_ManSimSimDeref( p, Ent ); } } if ( p->pPars->fConstCorr ) { Vec_IntForEachEntry( p->vRefinedC, i, k ) { Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); Cec_ManSimSimDeref( p, i ); } Vec_IntClear( p->vRefinedC ); } if ( Vec_IntSize(p->vRefinedC) > 0 ) Cec_ManSimProcessRefined( p, p->vRefinedC ); assert( vInfoCis == NULL || iCiId == Gia_ManCiNum(p->pAig) ); assert( vInfoCos == NULL || iCoId == Gia_ManCoNum(p->pAig) ); assert( p->nMems == 1 ); if ( p->nMems != 1 ) Abc_Print( 1, "Cec_ManSimSimulateRound(): Memory management error!\n" ); if ( p->pPars->fVeryVerbose ) Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); if ( p->pBestState ) Cec_ManSimFindBestPattern( p ); /* if ( p->nMems > 1 ) { for ( i = 1; i < p->nObjs; i++ ) if ( p->pSims[i] ) { int x = 0; } } */ return Cec_ManSimAnalyzeOutputs( p ); } /**Function************************************************************* Synopsis [Creates simulation info for this round.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ) { unsigned * pRes0, * pRes1; int i, w; if ( p->pPars->fSeqSimulate && Gia_ManRegNum(p->pAig) > 0 ) { assert( vInfoCis && vInfoCos ); for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) { pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i ); for ( w = 0; w < p->nWords; w++ ) pRes0[w] = Gia_ManRandom( 0 ); } for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, Gia_ManPiNum(p->pAig) + i ); pRes1 = (unsigned *)Vec_PtrEntry( vInfoCos, Gia_ManPoNum(p->pAig) + i ); for ( w = 0; w < p->nWords; w++ ) pRes0[w] = pRes1[w]; } } else { for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) { pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i ); for ( w = 0; w < p->nWords; w++ ) pRes0[w] = Gia_ManRandom( 0 ); } } } /**Function************************************************************* Synopsis [Returns 1 if the bug is found.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax ) { Gia_Obj_t * pObj; int i; assert( p->pAig->pReprs == NULL ); // allocate representation p->pAig->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p->pAig) ); p->pAig->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) ); // create references Gia_ManCreateValueRefs( p->pAig ); // set starting representative of internal nodes to be constant 0 if ( p->pPars->fLatchCorr ) Gia_ManForEachObj( p->pAig, pObj, i ) Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); else if ( LevelMax == -1 ) Gia_ManForEachObj( p->pAig, pObj, i ) Gia_ObjSetRepr( p->pAig, i, Gia_ObjIsAnd(pObj) ? 0 : GIA_VOID ); else { Gia_ManLevelNum( p->pAig ); Gia_ManForEachObj( p->pAig, pObj, i ) Gia_ObjSetRepr( p->pAig, i, (Gia_ObjIsAnd(pObj) && Gia_ObjLevel(p->pAig,pObj) <= LevelMax) ? 0 : GIA_VOID ); Vec_IntFreeP( &p->pAig->vLevels ); } // if sequential simulation, set starting representative of ROs to be constant 0 if ( p->pPars->fSeqSimulate ) Gia_ManForEachRo( p->pAig, pObj, i ) if ( pObj->Value ) Gia_ObjSetRepr( p->pAig, Gia_ObjId(p->pAig, pObj), 0 ); // perform simulation p->nWords = 1; do { if ( p->pPars->fVerbose ) Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); for ( i = 0; i < 4; i++ ) { Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) return 1; } p->nWords = 2 * p->nWords + 1; } while ( p->nWords <= p->pPars->nWords ); return 0; } /**Function************************************************************* Synopsis [Returns 1 if the bug is found.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimClassesRefine( Cec_ManSim_t * p ) { int i; Gia_ManCreateValueRefs( p->pAig ); p->nWords = p->pPars->nWords; for ( i = 0; i < p->pPars->nRounds; i++ ) { if ( (i % (p->pPars->nRounds / 5)) == 0 && p->pPars->fVerbose ) Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo ); if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) return 1; } if ( p->pPars->fVerbose ) Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecCore.c000066400000000000000000000473031300674244400234310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p ) { memset( p, 0, sizeof(Cec_ParSat_t) ); p->nBTLimit = 100; // conflict limit at a node p->nSatVarMax = 2000; // the max number of SAT variables p->nCallsRecycle = 200; // calls to perform before recycling SAT solver p->fNonChrono = 0; // use non-chronological backtracling (for circuit SAT only) p->fPolarFlip = 1; // flops polarity of variables p->fCheckMiter = 0; // the circuit is the miter // p->fFirstStop = 0; // stop on the first sat output p->fLearnCls = 0; // perform clause learning p->fVerbose = 0; // verbose stats } /**Function************ ************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p ) { memset( p, 0, sizeof(Cec_ParSim_t) ); p->nWords = 31; // the number of simulation words p->nFrames = 100; // the number of simulation frames p->nRounds = 20; // the max number of simulation rounds p->nNonRefines = 3; // the max number of rounds without refinement p->TimeLimit = 0; // the runtime limit in seconds p->fCheckMiter = 0; // the circuit is the miter // p->fFirstStop = 0; // stop on the first sat output p->fDualOut = 0; // miter with separate outputs p->fConstCorr = 0; // consider only constants p->fSeqSimulate = 0; // performs sequential simulation p->fVeryVerbose = 0; // verbose stats p->fVerbose = 0; // verbose stats } /**Function************ ************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p ) { memset( p, 0, sizeof(Cec_ParSmf_t) ); p->nWords = 31; // the number of simulation words p->nRounds = 200; // the number of simulation rounds p->nFrames = 200; // the max number of time frames p->nNonRefines = 3; // the max number of rounds without refinement p->nMinOutputs = 0; // the min outputs to accumulate p->nBTLimit = 100; // conflict limit at a node p->TimeLimit = 0; // the runtime limit in seconds p->fDualOut = 0; // miter with separate outputs p->fCheckMiter = 0; // the circuit is the miter // p->fFirstStop = 0; // stop on the first sat output p->fVerbose = 0; // verbose stats } /**Function************ ************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p ) { memset( p, 0, sizeof(Cec_ParFra_t) ); p->nWords = 15; // the number of simulation words p->nRounds = 15; // the number of simulation rounds p->TimeLimit = 0; // the runtime limit in seconds p->nItersMax = 10; // the maximum number of iterations of SAT sweeping p->nBTLimit = 100; // conflict limit at a node p->nLevelMax = 0; // restriction on the level of nodes to be swept p->nDepthMax = 1; // the depth in terms of steps of speculative reduction p->fRewriting = 0; // enables AIG rewriting p->fCheckMiter = 0; // the circuit is the miter // p->fFirstStop = 0; // stop on the first sat output p->fDualOut = 0; // miter with separate outputs p->fColorDiff = 0; // miter with separate outputs p->fSatSweeping = 0; // enable SAT sweeping p->fVeryVerbose = 0; // verbose stats p->fVerbose = 0; // verbose stats p->iOutFail = -1; // the failed output } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p ) { memset( p, 0, sizeof(Cec_ParCec_t) ); p->nBTLimit = 1000; // conflict limit at a node p->TimeLimit = 0; // the runtime limit in seconds // p->fFirstStop = 0; // stop on the first sat output p->fUseSmartCnf = 0; // use smart CNF computation p->fRewriting = 0; // enables AIG rewriting p->fVeryVerbose = 0; // verbose stats p->fVerbose = 0; // verbose stats p->iOutFail = -1; // the number of failed output } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p ) { memset( p, 0, sizeof(Cec_ParCor_t) ); p->nWords = 15; // the number of simulation words p->nRounds = 15; // the number of simulation rounds p->nFrames = 1; // the number of time frames p->nBTLimit = 100; // conflict limit at a node p->nLevelMax = -1; // (scorr only) the max number of levels p->nStepsMax = -1; // (scorr only) the max number of induction steps p->fLatchCorr = 0; // consider only latch outputs p->fConstCorr = 0; // consider only constants p->fUseRings = 1; // combine classes into rings p->fUseCSat = 1; // use circuit-based solver // p->fFirstStop = 0; // stop on the first sat output p->fUseSmartCnf = 0; // use smart CNF computation p->fVeryVerbose = 0; // verbose stats p->fVerbose = 0; // verbose stats } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p ) { memset( p, 0, sizeof(Cec_ParChc_t) ); p->nWords = 15; // the number of simulation words p->nRounds = 15; // the number of simulation rounds p->nBTLimit = 1000; // conflict limit at a node p->fUseRings = 1; // use rings p->fUseCSat = 0; // use circuit-based solver p->fVeryVerbose = 0; // verbose stats p->fVerbose = 0; // verbose stats } /**Function************************************************************* Synopsis [Core procedure for SAT sweeping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars ) { Gia_Man_t * pNew; Cec_ManPat_t * pPat; pPat = Cec_ManPatStart(); Cec_ManSatSolve( pPat, pAig, pPars, NULL, NULL, NULL ); // pNew = Gia_ManDupDfsSkip( pAig ); pNew = Gia_ManDup( pAig ); Cec_ManPatStop( pPat ); return pNew; } /**Function************************************************************* Synopsis [Core procedure for simulation.] Description [Returns 1 if refinement has happened.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSimulationOne( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) { Cec_ManSim_t * pSim; int RetValue = 0; abctime clkTotal = Abc_Clock(); pSim = Cec_ManSimStart( pAig, pPars ); if ( (pAig->pReprs == NULL && (RetValue = Cec_ManSimClassesPrepare( pSim, -1 ))) || (RetValue == 0 && (RetValue = Cec_ManSimClassesRefine( pSim ))) ) Abc_Print( 1, "The number of failed outputs of the miter = %6d. (Words = %4d. Frames = %4d.)\n", pSim->nOuts, pPars->nWords, pPars->nFrames ); if ( pPars->fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); Cec_ManSimStop( pSim ); return RetValue; } /**Function************************************************************* Synopsis [Core procedure for simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) { int r, nLitsOld, nLitsNew, nCountNoRef = 0, fStop = 0; Gia_ManRandom( 1 ); if ( pPars->fSeqSimulate ) Abc_Print( 1, "Performing rounds of random simulation of %d frames with %d words.\n", pPars->nRounds, pPars->nFrames, pPars->nWords ); nLitsOld = Gia_ManEquivCountLits( pAig ); for ( r = 0; r < pPars->nRounds; r++ ) { if ( Cec_ManSimulationOne( pAig, pPars ) ) { fStop = 1; break; } // decide when to stop nLitsNew = Gia_ManEquivCountLits( pAig ); if ( nLitsOld == 0 || nLitsOld > nLitsNew ) { nLitsOld = nLitsNew; nCountNoRef = 0; } else if ( ++nCountNoRef == pPars->nNonRefines ) { r++; break; } assert( nLitsOld == nLitsNew ); } // if ( pPars->fVerbose ) if ( r == pPars->nRounds || fStop ) Abc_Print( 1, "Random simulation is stopped after %d rounds.\n", r ); else Abc_Print( 1, "Random simulation saturated after %d rounds.\n", r ); if ( pPars->fCheckMiter ) { int nNonConsts = Cec_ManCountNonConstOutputs( pAig ); if ( nNonConsts ) Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts ); } } /**Function************************************************************* Synopsis [Core procedure for SAT sweeping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSilent ) { int fOutputResult = 0; Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; Gia_Man_t * pIni, * pSrm, * pTemp; Cec_ManFra_t * p; Cec_ManSim_t * pSim; Cec_ManPat_t * pPat; int i, fTimeOut = 0, nMatches = 0; abctime clk, clk2, clkTotal = Abc_Clock(); // duplicate AIG and transfer equivalence classes Gia_ManRandom( 1 ); pIni = Gia_ManDup(pAig); pIni->pReprs = pAig->pReprs; pAig->pReprs = NULL; pIni->pNexts = pAig->pNexts; pAig->pNexts = NULL; if ( pPars->fUseOrigIds ) { Gia_ManOrigIdsInit( pIni ); Vec_IntFreeP( &pAig->vIdsEquiv ); pAig->vIdsEquiv = Vec_IntAlloc( 1000 ); } // prepare the managers // SAT sweeping p = Cec_ManFraStart( pIni, pPars ); if ( pPars->fDualOut ) pPars->fColorDiff = 1; // simulation Cec_ManSimSetDefaultParams( pParsSim ); pParsSim->nWords = pPars->nWords; pParsSim->nFrames = pPars->nRounds; pParsSim->fCheckMiter = pPars->fCheckMiter; pParsSim->fDualOut = pPars->fDualOut; pParsSim->fVerbose = pPars->fVerbose; pSim = Cec_ManSimStart( p->pAig, pParsSim ); // SAT solving Cec_ManSatSetDefaultParams( pParsSat ); pParsSat->nBTLimit = pPars->nBTLimit; pParsSat->fVerbose = pPars->fVeryVerbose; // simulation patterns pPat = Cec_ManPatStart(); pPat->fVerbose = pPars->fVeryVerbose; // start equivalence classes clk = Abc_Clock(); if ( p->pAig->pReprs == NULL ) { if ( Cec_ManSimClassesPrepare(pSim, -1) || Cec_ManSimClassesRefine(pSim) ) { Gia_ManStop( p->pAig ); p->pAig = NULL; goto finalize; } } p->timeSim += Abc_Clock() - clk; // perform solving for ( i = 1; i <= pPars->nItersMax; i++ ) { clk2 = Abc_Clock(); nMatches = 0; if ( pPars->fDualOut ) { nMatches = Gia_ManEquivSetColors( p->pAig, pPars->fVeryVerbose ); // p->pAig->pIso = Cec_ManDetectIsomorphism( p->pAig ); // Gia_ManEquivTransform( p->pAig, 1 ); } pSrm = Cec_ManFraSpecReduction( p ); // Gia_AigerWrite( pSrm, "gia_srm.aig", 0, 0 ); if ( pPars->fVeryVerbose ) Gia_ManPrintStats( pSrm, NULL ); if ( Gia_ManCoNum(pSrm) == 0 ) { Gia_ManStop( pSrm ); if ( p->pPars->fVerbose ) Abc_Print( 1, "Considered all available candidate equivalences.\n" ); if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) > 0 ) { if ( pPars->fColorDiff ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Switching into reduced mode.\n" ); pPars->fColorDiff = 0; } else { if ( p->pPars->fVerbose ) Abc_Print( 1, "Switching into normal mode.\n" ); pPars->fDualOut = 0; } continue; } break; } clk = Abc_Clock(); if ( pPars->fRunCSat ) Cec_ManSatSolveCSat( pPat, pSrm, pParsSat ); else Cec_ManSatSolve( pPat, pSrm, pParsSat, p->pAig->vIdsOrig, p->vXorNodes, pAig->vIdsEquiv ); p->timeSat += Abc_Clock() - clk; if ( Cec_ManFraClassesUpdate( p, pSim, pPat, pSrm ) ) { Gia_ManStop( pSrm ); Gia_ManStop( p->pAig ); p->pAig = NULL; goto finalize; } Gia_ManStop( pSrm ); // update the manager pSim->pAig = p->pAig = Gia_ManEquivReduceAndRemap( pTemp = p->pAig, 0, pParsSim->fDualOut ); if ( p->pAig == NULL ) { p->pAig = pTemp; break; } Gia_ManStop( pTemp ); if ( p->pPars->fVerbose ) { Abc_Print( 1, "%3d : P =%7d. D =%7d. F =%6d. M = %7d. And =%8d. ", i, p->nAllProved, p->nAllDisproved, p->nAllFailed, nMatches, Gia_ManAndNum(p->pAig) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); } if ( Gia_ManAndNum(p->pAig) == 0 ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Network after reduction is empty.\n" ); break; } // check resource limits if ( p->pPars->TimeLimit && (Abc_Clock() - clkTotal)/CLOCKS_PER_SEC >= p->pPars->TimeLimit ) { fTimeOut = 1; break; } // if ( p->nAllFailed && !p->nAllProved && !p->nAllDisproved ) if ( p->nAllFailed > p->nAllProved + p->nAllDisproved ) { if ( pParsSat->nBTLimit >= 10001 ) break; if ( pPars->fSatSweeping ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Exceeded the limit on the number of conflicts (%d).\n", pParsSat->nBTLimit ); break; } pParsSat->nBTLimit *= 10; if ( p->pPars->fVerbose ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Increasing conflict limit to %d.\n", pParsSat->nBTLimit ); if ( fOutputResult ) { Gia_AigerWrite( p->pAig, "gia_cec_temp.aig", 0, 0 ); Abc_Print( 1,"The result is written into file \"%s\".\n", "gia_cec_temp.aig" ); } } } if ( pPars->fDualOut && pPars->fColorDiff && (Gia_ManAndNum(p->pAig) < 100000 || p->nAllProved + p->nAllDisproved < 10) ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Switching into reduced mode.\n" ); pPars->fColorDiff = 0; } // if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) < 20000 ) else if ( pPars->fDualOut && (Gia_ManAndNum(p->pAig) < 20000 || p->nAllProved + p->nAllDisproved < 10) ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Switching into normal mode.\n" ); pPars->fColorDiff = 0; pPars->fDualOut = 0; } } finalize: if ( p->pPars->fVerbose && p->pAig ) { Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", Gia_ManAndNum(pAig), Gia_ManAndNum(p->pAig), 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(p->pAig))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), Gia_ManRegNum(pAig), Gia_ManRegNum(p->pAig), 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(p->pAig))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); Abc_PrintTimeP( 1, "Sim ", p->timeSim, Abc_Clock() - (int)clkTotal ); Abc_PrintTimeP( 1, "Sat ", p->timeSat-pPat->timeTotalSave, Abc_Clock() - (int)clkTotal ); Abc_PrintTimeP( 1, "Pat ", p->timePat+pPat->timeTotalSave, Abc_Clock() - (int)clkTotal ); Abc_PrintTime( 1, "Time", (int)(Abc_Clock() - clkTotal) ); } pTemp = p->pAig; p->pAig = NULL; if ( pTemp == NULL && pSim->iOut >= 0 ) { if ( !fSilent ) Abc_Print( 1, "Disproved at least one output of the miter (zero-based number %d).\n", pSim->iOut ); pPars->iOutFail = pSim->iOut; } else if ( pSim->pCexes && !fSilent ) Abc_Print( 1, "Disproved %d outputs of the miter.\n", pSim->nOuts ); if ( fTimeOut && !fSilent ) Abc_Print( 1, "Timed out after %d seconds.\n", (int)((double)Abc_Clock() - clkTotal)/CLOCKS_PER_SEC ); pAig->pCexComb = pSim->pCexComb; pSim->pCexComb = NULL; Cec_ManSimStop( pSim ); Cec_ManPatStop( pPat ); Cec_ManFraStop( p ); return pTemp; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecCorr.c000066400000000000000000001236661300674244400234550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecCorr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Latch/signal correspondence computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecCorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the real value of the literal w/o spec reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) { if ( Gia_ObjIsAnd(pObj) ) { Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f, nPrefix ); Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), f, nPrefix ); return Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj) ); } if ( f == 0 ) { assert( Gia_ObjIsRo(p, pObj) ); return Gia_ObjCopyF(p, f, pObj); } assert( f && Gia_ObjIsRo(p, pObj) ); pObj = Gia_ObjRoToRi( p, pObj ); Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f-1, nPrefix ); return Gia_ObjFanin0CopyF( p, f-1, pObj ); } /**Function************************************************************* Synopsis [Recursively performs speculative reduction for the object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix ) { Gia_Obj_t * pRepr; int iLitNew; if ( ~Gia_ObjCopyF(p, f, pObj) ) return; if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) { Gia_ManCorrSpecReduce_rec( pNew, p, pRepr, f, nPrefix ); iLitNew = Abc_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); Gia_ObjSetCopyF( p, f, pObj, iLitNew ); return; } assert( Gia_ObjIsCand(pObj) ); iLitNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); Gia_ObjSetCopyF( p, f, pObj, iLitNew ); } /**Function************************************************************* Synopsis [Derives SRM for signal correspondence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pRepr; Vec_Int_t * vXorLits; int f, i, iPrev, iObj, iPrevNew, iObjNew; assert( nFrames > 0 ); assert( Gia_ManRegNum(p) > 0 ); assert( p->pReprs != NULL ); Vec_IntFill( &p->vCopies, (nFrames+fScorr)*Gia_ManObjNum(p), -1 ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 ); Gia_ManForEachRo( p, pObj, i ) Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) ); Gia_ManForEachRo( p, pObj, i ) if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) ); for ( f = 0; f < nFrames+fScorr; f++ ) { Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); Gia_ManForEachPi( p, pObj, i ) Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); } *pvOutputs = Vec_IntAlloc( 1000 ); vXorLits = Vec_IntAlloc( 1000 ); if ( fRings ) { Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsConst( p, i ) ) { iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ); if ( iObjNew != 0 ) { Vec_IntPush( *pvOutputs, 0 ); Vec_IntPush( *pvOutputs, i ); Vec_IntPush( vXorLits, iObjNew ); } } else if ( Gia_ObjIsHead( p, i ) ) { iPrev = i; Gia_ClassForEachObj1( p, i, iObj ) { iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) { Vec_IntPush( *pvOutputs, iPrev ); Vec_IntPush( *pvOutputs, iObj ); Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); } iPrev = iObj; } iObj = i; iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 ); iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 ); iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) ); if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 ) { Vec_IntPush( *pvOutputs, iPrev ); Vec_IntPush( *pvOutputs, iObj ); Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) ); } } } } else { Gia_ManForEachObj1( p, pObj, i ) { pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); if ( pRepr == NULL ) continue; iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 ); iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); if ( iPrevNew != iObjNew ) { Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); } } } Vec_IntForEachEntry( vXorLits, iObjNew, i ) Gia_ManAppendCo( pNew, iObjNew ); Vec_IntFree( vXorLits ); Gia_ManHashStop( pNew ); Vec_IntErase( &p->vCopies ); //Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); pNew = Gia_ManCleanup( pTemp = pNew ); //Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Derives SRM for signal correspondence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int fRings ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pRepr; Vec_Int_t * vXorLits; int f, i, iPrevNew, iObjNew; assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix ); assert( Gia_ManRegNum(p) > 0 ); assert( p->pReprs != NULL ); Vec_IntFill( &p->vCopies, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p), -1 ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManForEachRo( p, pObj, i ) { Gia_ManAppendCi(pNew); Gia_ObjSetCopyF( p, 0, pObj, 0 ); } for ( f = 0; f < nFrames+nPrefix+fScorr; f++ ) { Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); Gia_ManForEachPi( p, pObj, i ) Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); } *pvOutputs = Vec_IntAlloc( 1000 ); vXorLits = Vec_IntAlloc( 1000 ); for ( f = nPrefix; f < nFrames+nPrefix; f++ ) { Gia_ManForEachObj1( p, pObj, i ) { pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); if ( pRepr == NULL ) continue; iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix ); iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix ); iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); if ( iPrevNew != iObjNew ) { Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) ); Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) ); Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) ); } } } Vec_IntForEachEntry( vXorLits, iObjNew, i ) Gia_ManAppendCo( pNew, iObjNew ); Vec_IntFree( vXorLits ); Gia_ManHashStop( pNew ); Vec_IntErase( &p->vCopies ); //Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) ); pNew = Gia_ManCleanup( pTemp = pNew ); //Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Initializes simulation info for lcorr/scorr counter-examples.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops ) { unsigned * pInfo; int k, w, nWords; nWords = Vec_PtrReadWordsSimInfo( vInfo ); assert( nFlops <= Vec_PtrSize(vInfo) ); for ( k = 0; k < nFlops; k++ ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); for ( w = 0; w < nWords; w++ ) pInfo[w] = 0; } for ( k = nFlops; k < Vec_PtrSize(vInfo); k++ ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); for ( w = 0; w < nWords; w++ ) pInfo[w] = Gia_ManRandom( 0 ); } } /**Function************************************************************* Synopsis [Remaps simulation info from SRM to the original AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCorrRemapSimInfo( Gia_Man_t * p, Vec_Ptr_t * vInfo ) { Gia_Obj_t * pObj, * pRepr; unsigned * pInfoObj, * pInfoRepr; int i, w, nWords; nWords = Vec_PtrReadWordsSimInfo( vInfo ); Gia_ManForEachRo( p, pObj, i ) { // skip ROs without representatives pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); if ( pRepr == NULL || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) continue; pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, i ); for ( w = 0; w < nWords; w++ ) assert( pInfoObj[w] == 0 ); // skip ROs with constant representatives if ( Gia_ObjIsConst0(pRepr) ) continue; assert( Gia_ObjIsRo(p, pRepr) ); // Abc_Print( 1, "%d -> %d ", i, Gia_ObjId(p, pRepr) ); // transfer info from the representative pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); for ( w = 0; w < nWords; w++ ) pInfoObj[w] = pInfoRepr[w]; } // Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [Collects information about remapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p ) { Vec_Int_t * vPairs; Gia_Obj_t * pObj, * pRepr; int i; vPairs = Vec_IntAlloc( 100 ); Gia_ManForEachRo( p, pObj, i ) { // skip ROs without representatives pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) ) // if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjIsFailedPair(p, Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj)) ) continue; assert( Gia_ObjIsRo(p, pRepr) ); // Abc_Print( 1, "%d -> %d ", Gia_ObjId(p,pObj), Gia_ObjId(p, pRepr) ); // remember the pair Vec_IntPush( vPairs, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) ); Vec_IntPush( vPairs, i ); } return vPairs; } /**Function************************************************************* Synopsis [Remaps simulation info from SRM to the original AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo ) { unsigned * pInfoObj, * pInfoRepr; int w, i, iObj, iRepr, nWords; nWords = Vec_PtrReadWordsSimInfo( vInfo ); Vec_IntForEachEntry( vPairs, iRepr, i ) { iObj = Vec_IntEntry( vPairs, ++i ); pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, iObj ); pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, iRepr ); for ( w = 0; w < nWords; w++ ) { assert( pInfoObj[w] == 0 ); pInfoObj[w] = pInfoRepr[w]; } } } /**Function************************************************************* Synopsis [Packs one counter-examples into the array of simulation info.] Description [] SideEffects [] SeeAlso [] *************************************`**********************************/ int Cec_ManLoadCounterExamplesTry( 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 [Performs bitpacking of counter-examples.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) { Vec_Int_t * vPat; Vec_Ptr_t * vPres; int nWords = Vec_PtrReadWordsSimInfo(vInfo); int nBits = 32 * nWords; int k, nSize, kMax = 0;//, iBit = 1; vPat = Vec_IntAlloc( 100 ); vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords ); Vec_PtrCleanSimInfo( vPres, 0, nWords ); while ( iStart < Vec_IntSize(vCexStore) ) { // skip the output number iStart++; // get the number of items nSize = Vec_IntEntry( vCexStore, iStart++ ); if ( nSize <= 0 ) continue; // extract pattern Vec_IntClear( vPat ); for ( k = 0; k < nSize; k++ ) Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); // add pattern to storage for ( k = 1; k < nBits; k++ ) if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) break; kMax = Abc_MaxInt( kMax, k ); if ( k == nBits-1 ) break; } Vec_PtrFree( vPres ); Vec_IntFree( vPat ); return iStart; } /**Function************************************************************* Synopsis [Performs bitpacking of counter-examples.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart ) { unsigned * pInfo; int nBits = 32 * Vec_PtrReadWordsSimInfo(vInfo); int k, iLit, nLits, Out, iBit = 1; while ( iStart < Vec_IntSize(vCexStore) ) { // skip the output number // iStart++; Out = Vec_IntEntry( vCexStore, iStart++ ); // Abc_Print( 1, "iBit = %d. Out = %d.\n", iBit, Out ); // get the number of items nLits = Vec_IntEntry( vCexStore, iStart++ ); if ( nLits <= 0 ) continue; // add pattern to storage for ( k = 0; k < nLits; k++ ) { iLit = Vec_IntEntry( vCexStore, iStart++ ); pInfo = (unsigned *)Vec_PtrEntry( vInfo, Abc_Lit2Var(iLit) ); if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(iLit) ) Abc_InfoXorBit( pInfo, iBit ); } if ( ++iBit == nBits ) break; } // Abc_Print( 1, "added %d bits\n", iBit-1 ); return iStart; } /**Function************************************************************* Synopsis [Resimulates counter-examples derived by the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames ) { Vec_Int_t * vPairs; Vec_Ptr_t * vSimInfo; int RetValue = 0, iStart = 0; vPairs = Gia_ManCorrCreateRemapping( pSim->pAig ); Gia_ManCreateValueRefs( pSim->pAig ); // pSim->pPars->nWords = 63; pSim->pPars->nFrames = nFrames; vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords ); while ( iStart < Vec_IntSize(vCexStore) ) { Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) ); iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); // iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart ); // Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo ); Gia_ManCorrPerformRemapping( vPairs, vSimInfo ); RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); // Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL ); } //Gia_ManEquivPrintOne( pSim->pAig, 85, 0 ); assert( iStart == Vec_IntSize(vCexStore) ); Vec_PtrFree( vSimInfo ); Vec_IntFree( vPairs ); return RetValue; } /**Function************************************************************* Synopsis [Resimulates counter-examples derived by the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore ) { Vec_Ptr_t * vSimInfo; int RetValue = 0, iStart = 0; Gia_ManCreateValueRefs( pSim->pAig ); pSim->pPars->nFrames = 1; vSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(pSim->pAig), pSim->pPars->nWords ); while ( iStart < Vec_IntSize(vCexStore) ) { Cec_ManStartSimInfo( vSimInfo, 0 ); iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart ); RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo ); } assert( iStart == Vec_IntSize(vCexStore) ); Vec_PtrFree( vSimInfo ); return RetValue; } /**Function************************************************************* Synopsis [Updates equivalence classes by marking those that timed out.] Description [Returns 1 if all ndoes are proved.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings ) { int i, status, iRepr, iObj; int Counter = 0; assert( 2 * Vec_StrSize(vStatus) == Vec_IntSize(vOutputs) ); Vec_StrForEachEntry( vStatus, status, i ) { iRepr = Vec_IntEntry( vOutputs, 2*i ); iObj = Vec_IntEntry( vOutputs, 2*i+1 ); if ( status == 1 ) continue; if ( status == 0 ) { if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) Counter++; // if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) // Abc_Print( 1, "Gia_ManCheckRefinements(): Disproved equivalence (%d,%d) is not refined!\n", iRepr, iObj ); // if ( Gia_ObjHasSameRepr(p, iRepr, iObj) ) // Cec_ManSimClassRemoveOne( pSim, iObj ); continue; } if ( status == -1 ) { // if ( !Gia_ObjFailed( p, iObj ) ) // Abc_Print( 1, "Gia_ManCheckRefinements(): Failed equivalence is not marked as failed!\n" ); // Gia_ObjSetFailed( p, iRepr ); // Gia_ObjSetFailed( p, iObj ); // if ( fRings ) // Cec_ManSimClassRemoveOne( pSim, iRepr ); Cec_ManSimClassRemoveOne( pSim, iObj ); continue; } } // if ( Counter ) // Abc_Print( 1, "Gia_ManCheckRefinements(): Could not refine %d nodes.\n", Counter ); return 1; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCorrReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pRepr; if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) { Gia_ManCorrReduce_rec( pNew, p, pRepr ); pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin1(pObj) ); 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_ManCorrReduce( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; 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_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Prints statistics during solving.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, abctime Time ) { int nLits, CounterX = 0, Counter0 = 0, Counter = 0; int i, Entry, nProve = 0, nDispr = 0, nFail = 0; for ( i = 1; i < Gia_ManObjNum(p); i++ ) { if ( Gia_ObjIsNone(p, i) ) CounterX++; else if ( Gia_ObjIsConst(p, i) ) Counter0++; else if ( Gia_ObjIsHead(p, i) ) Counter++; } CounterX -= Gia_ManCoNum(p); nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; if ( iIter == -1 ) Abc_Print( 1, "BMC : " ); else Abc_Print( 1, "%3d : ", iIter ); Abc_Print( 1, "c =%8d cl =%7d lit =%8d ", Counter0, Counter, nLits ); if ( vStatus ) Vec_StrForEachEntry( vStatus, Entry, i ) { if ( Entry == 1 ) nProve++; else if ( Entry == 0 ) nDispr++; else if ( Entry == -1 ) nFail++; } Abc_Print( 1, "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail ); Abc_Print( 1, "%c ", Gia_ObjIsConst( p, Gia_ObjFaninId0p(p, Gia_ManPo(p, 0)) ) ? '+' : '-' ); Abc_PrintTime( 1, "T", Time ); } /**Function************************************************************* Synopsis [Runs BMC for the equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPrefs ) { Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; Vec_Str_t * vStatus; Vec_Int_t * vOutputs; Vec_Int_t * vCexStore; Cec_ManSim_t * pSim; Gia_Man_t * pSrm; int fChanges, RetValue; // prepare simulation manager Cec_ManSimSetDefaultParams( pParsSim ); pParsSim->nWords = pPars->nWords; pParsSim->nFrames = pPars->nRounds; pParsSim->fVerbose = pPars->fVerbose; pParsSim->fLatchCorr = pPars->fLatchCorr; pParsSim->fSeqSimulate = 1; pSim = Cec_ManSimStart( pAig, pParsSim ); // prepare SAT solving Cec_ManSatSetDefaultParams( pParsSat ); pParsSat->nBTLimit = pPars->nBTLimit; pParsSat->fVerbose = pPars->fVerbose; fChanges = 1; while ( fChanges ) { abctime clkBmc = Abc_Clock(); fChanges = 0; pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); if ( Gia_ManPoNum(pSrm) == 0 ) { Gia_ManStop( pSrm ); Vec_IntFree( vOutputs ); break; } pParsSat->nBTLimit *= 10; if ( pPars->fUseCSat ) vCexStore = Tas_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); else vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); // refine classes with these counter-examples if ( Vec_IntSize(vCexStore) ) { RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nPrefs ); Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); fChanges = 1; } if ( pPars->fVerbose ) Cec_ManRefinedClassPrintStats( pAig, vStatus, -1, Abc_Clock() - clkBmc ); // recycle Vec_IntFree( vCexStore ); Vec_StrFree( vStatus ); Gia_ManStop( pSrm ); Vec_IntFree( vOutputs ); } Cec_ManSimStop( pSim ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManLSCorrAnalyzeDependence( Gia_Man_t * p, Vec_Int_t * vEquivs, Vec_Str_t * vStatus ) { Gia_Obj_t * pObj, * pObjRo; int i, Iter, iObj, iRepr, fPrev, Total, Count0, Count1; assert( Vec_StrSize(vStatus) * 2 == Vec_IntSize(vEquivs) ); Total = 0; Gia_ManForEachObj( p, pObj, i ) { assert( pObj->fMark1 == 0 ); if ( Gia_ObjHasRepr(p, i) ) Total++; } Count0 = 0; for ( i = 0; i < Vec_StrSize(vStatus); i++ ) { iRepr = Vec_IntEntry(vEquivs, 2*i); iObj = Vec_IntEntry(vEquivs, 2*i+1); assert( iRepr == Gia_ObjRepr(p, iObj) ); if ( Vec_StrEntry(vStatus, i) != 1 ) // disproved or undecided { Gia_ManObj(p, iObj)->fMark1 = 1; Count0++; } } for ( Iter = 0; Iter < 100; Iter++ ) { int fChanges = 0; Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) continue; assert( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ); // fPrev = pObj->fMark1; if ( Gia_ObjIsAnd(pObj) ) pObj->fMark1 |= Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1; else pObj->fMark1 |= Gia_ObjFanin0(pObj)->fMark1; // fChanges += fPrev ^ pObj->fMark1; } Gia_ManForEachRiRo( p, pObj, pObjRo, i ) { fPrev = pObjRo->fMark1; pObjRo->fMark1 = pObj->fMark1; fChanges += fPrev ^ pObjRo->fMark1; } if ( fChanges == 0 ) break; } Count1 = 0; Gia_ManForEachObj( p, pObj, i ) { if ( pObj->fMark1 && Gia_ObjHasRepr(p, i) ) Count1++; pObj->fMark1 = 0; } printf( "%5d -> %5d (%3d) ", Count0, Count1, Iter ); return 0; } /**Function************************************************************* Synopsis [Internal procedure for register correspondence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) { int nIterMax = 100000; int nAddFrames = 1; // additional timeframes to simulate int fRunBmcFirst = 1; Vec_Str_t * vStatus; Vec_Int_t * vOutputs; Vec_Int_t * vCexStore; Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; Cec_ManSim_t * pSim; Gia_Man_t * pSrm; int r, RetValue; abctime clkTotal = Abc_Clock(); abctime clkSat = 0, clkSim = 0, clkSrm = 0; abctime clk2, clk = Abc_Clock(); if ( Gia_ManRegNum(pAig) == 0 ) { Abc_Print( 1, "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" ); return 0; } Gia_ManRandom( 1 ); // prepare simulation manager Cec_ManSimSetDefaultParams( pParsSim ); pParsSim->nWords = pPars->nWords; pParsSim->nFrames = pPars->nFrames; pParsSim->fVerbose = pPars->fVerbose; pParsSim->fLatchCorr = pPars->fLatchCorr; pParsSim->fConstCorr = pPars->fConstCorr; pParsSim->fSeqSimulate = 1; // create equivalence classes of registers pSim = Cec_ManSimStart( pAig, pParsSim ); if ( pAig->pReprs == NULL ) { Cec_ManSimClassesPrepare( pSim, pPars->nLevelMax ); Cec_ManSimClassesRefine( pSim ); } // prepare SAT solving Cec_ManSatSetDefaultParams( pParsSat ); pParsSat->nBTLimit = pPars->nBTLimit; pParsSat->fVerbose = pPars->fVerbose; // limit the number of conflicts in the circuit-based solver if ( pPars->fUseCSat ) pParsSat->nBTLimit = Abc_MinInt( pParsSat->nBTLimit, 1000 ); if ( pPars->fVerbose ) { Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n", Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat ); Cec_ManRefinedClassPrintStats( pAig, NULL, 0, Abc_Clock() - clk ); } // check the base case if ( fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) ) Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 ); if ( pPars->pFunc ) { ((int (*)(void *))pPars->pFunc)( pPars->pData ); ((int (*)(void *))pPars->pFunc)( pPars->pData ); } if ( pPars->nStepsMax == 0 ) { Abc_Print( 1, "Stopped signal correspondence after BMC.\n" ); Cec_ManSimStop( pSim ); return 1; } // perform refinement of equivalence classes for ( r = 0; r < nIterMax; r++ ) { if ( pPars->nStepsMax == r ) { Cec_ManSimStop( pSim ); Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", r ); return 1; } clk = Abc_Clock(); // perform speculative reduction clk2 = Abc_Clock(); pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings ); assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) ); clkSrm += Abc_Clock() - clk2; if ( Gia_ManCoNum(pSrm) == 0 ) { Vec_IntFree( vOutputs ); Gia_ManStop( pSrm ); break; } //Gia_DumpAiger( pSrm, "corrsrm", r, 2 ); // found counter-examples to speculation clk2 = Abc_Clock(); if ( pPars->fUseCSat ) vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 ); else vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus ); Gia_ManStop( pSrm ); clkSat += Abc_Clock() - clk2; if ( Vec_IntSize(vCexStore) == 0 ) { Vec_IntFree( vCexStore ); Vec_StrFree( vStatus ); Vec_IntFree( vOutputs ); break; } // Cec_ManLSCorrAnalyzeDependence( pAig, vOutputs, vStatus ); // refine classes with these counter-examples clk2 = Abc_Clock(); RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames ); Vec_IntFree( vCexStore ); clkSim += Abc_Clock() - clk2; Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings ); if ( pPars->fVerbose ) Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, Abc_Clock() - clk ); Vec_StrFree( vStatus ); Vec_IntFree( vOutputs ); //Gia_ManEquivPrintClasses( pAig, 1, 0 ); if ( pPars->pFunc ) ((int (*)(void *))pPars->pFunc)( pPars->pData ); // quit if const is no longer there if ( pPars->fStopWhenGone && Gia_ManPoNum(pAig) == 1 && !Gia_ObjIsConst( pAig, Gia_ObjFaninId0p(pAig, Gia_ManPo(pAig, 0)) ) ) { printf( "Iterative refinement is stopped after iteration %d\n", r ); printf( "because the property output is no longer a candidate constant.\n" ); Cec_ManSimStop( pSim ); return 0; } } if ( pPars->fVerbose ) Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, Abc_Clock() - clk ); // check the overflow if ( r == nIterMax ) Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" ); Cec_ManSimStop( pSim ); // check the base case if ( !fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) ) Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 ); clkTotal = Abc_Clock() - clkTotal; // report the results if ( pPars->fVerbose ) { ABC_PRTP( "Srm ", clkSrm, clkTotal ); ABC_PRTP( "Sat ", clkSat, clkTotal ); ABC_PRTP( "Sim ", clkSim, clkTotal ); ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal ); Abc_PrintTime( 1, "TOTAL", clkTotal ); } return 1; } /**Function************************************************************* Synopsis [Computes new initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Cec_ManComputeInitState( Gia_Man_t * pAig, int nFrames ) { Gia_Obj_t * pObj, * pObjRo, * pObjRi; unsigned * pInitState; int i, f; Gia_ManRandom( 1 ); // Abc_Print( 1, "Simulating %d timeframes.\n", nFrames ); Gia_ManForEachRo( pAig, pObj, i ) pObj->fMark1 = 0; for ( f = 0; f < nFrames; f++ ) { Gia_ManConst0(pAig)->fMark1 = 0; Gia_ManForEachPi( pAig, pObj, i ) pObj->fMark1 = Gia_ManRandom(0) & 1; Gia_ManForEachAnd( pAig, pObj, i ) pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachRi( pAig, pObj, i ) pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)); Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, i ) pObjRo->fMark1 = pObjRi->fMark1; } pInitState = ABC_CALLOC( unsigned, Abc_BitWordNum(Gia_ManRegNum(pAig)) ); Gia_ManForEachRo( pAig, pObj, i ) { if ( pObj->fMark1 ) Abc_InfoSetBit( pInitState, i ); // Abc_Print( 1, "%d", pObj->fMark1 ); } // Abc_Print( 1, "\n" ); Gia_ManCleanMark1( pAig ); return pInitState; } /**Function************************************************************* Synopsis [Prints flop equivalences.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPrintFlopEquivs( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pRepr; int i; assert( p->vNamesIn != NULL ); Gia_ManForEachRo( p, pObj, i ) { if ( Gia_ObjIsConst(p, Gia_ObjId(p, pObj)) ) Abc_Print( 1, "Original flop %s is proved equivalent to constant.\n", Vec_PtrEntry(p->vNamesIn, Gia_ObjCioId(pObj)) ); else if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) { if ( Gia_ObjIsCi(pRepr) ) Abc_Print( 1, "Original flop %s is proved equivalent to flop %s.\n", Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ), Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pRepr) ) ); else Abc_Print( 1, "Original flop %s is proved equivalent to internal node %d.\n", Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ), Gia_ObjId(p, pRepr) ); } } } /**Function************************************************************* Synopsis [Top-level procedure for register correspondence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars ) { Gia_Man_t * pNew, * pTemp; unsigned * pInitState; int RetValue; ABC_FREE( pAig->pReprs ); ABC_FREE( pAig->pNexts ); if ( pPars->nPrefix == 0 ) { RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars ); if ( RetValue == 0 ) return Gia_ManDup( pAig ); } else { // compute the cycles AIG pInitState = Cec_ManComputeInitState( pAig, pPars->nPrefix ); pTemp = Gia_ManDupFlip( pAig, (int *)pInitState ); ABC_FREE( pInitState ); // compute classes of this AIG RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars ); // transfer the class info pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL; pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL; // perform additional BMC pPars->fUseCSat = 0; pPars->nBTLimit = Abc_MaxInt( pPars->nBTLimit, 1000 ); Cec_ManLSCorrespondenceBmc( pAig, pPars, pPars->nPrefix ); /* // transfer the class info back pTemp->pReprs = pAig->pReprs; pAig->pReprs = NULL; pTemp->pNexts = pAig->pNexts; pAig->pNexts = NULL; // continue refining RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars ); // transfer the class info pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL; pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL; */ Gia_ManStop( pTemp ); } // derive reduced AIG if ( pPars->fMakeChoices ) { pNew = Gia_ManEquivToChoices( pAig, 1 ); // Gia_ManHasChoices_very_old( pNew ); } else { // Gia_ManEquivImprove( pAig ); pNew = Gia_ManCorrReduce( pAig ); pNew = Gia_ManSeqCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); //Gia_AigerWrite( pNew, "reduced.aig", 0, 0 ); } // report the results if ( pPars->fVerbose ) { Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", Gia_ManAndNum(pAig), Gia_ManAndNum(pNew), 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1), Gia_ManRegNum(pAig), Gia_ManRegNum(pNew), 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) ); } if ( pPars->nPrefix && (Gia_ManAndNum(pNew) < Gia_ManAndNum(pAig) || Gia_ManRegNum(pNew) < Gia_ManRegNum(pAig)) ) Abc_Print( 1, "The reduced AIG was produced using %d-th invariants and will not verify.\n", pPars->nPrefix ); // print verbose info about equivalences if ( pPars->fVerboseFlops ) { if ( pAig->vNamesIn == NULL ) Abc_Print( 1, "Flop output names are not available. Use command \"&get -n\".\n" ); else Cec_ManPrintFlopEquivs( pAig ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecInt.h000066400000000000000000000272241300674244400233000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__cec__cecInt_h #define ABC__aig__cec__cecInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "sat/bsat/satSolver.h" #include "misc/bar/bar.h" #include "aig/gia/gia.h" #include "cec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // simulation pattern manager typedef struct Cec_ManPat_t_ Cec_ManPat_t; struct Cec_ManPat_t_ { Vec_Int_t * vPattern1; // pattern in terms of primary inputs Vec_Int_t * vPattern2; // pattern in terms of primary inputs Vec_Str_t * vStorage; // storage for compressed patterns int iStart; // position in the array where recent patterns begin int nPats; // total number of recent patterns int nPatsAll; // total number of all patterns int nPatLits; // total number of literals in recent patterns int nPatLitsAll; // total number of literals in all patterns int nPatLitsMin; // total number of literals in minimized recent patterns int nPatLitsMinAll; // total number of literals in minimized all patterns int nSeries; // simulation series int fVerbose; // verbose stats // runtime statistics abctime timeFind; // detecting the pattern abctime timeShrink; // minimizing the pattern abctime timeVerify; // verifying the result of minimisation abctime timeSort; // sorting literals abctime timePack; // packing into sim info structures abctime timeTotal; // total runtime abctime timeTotalSave; // total runtime for saving }; // SAT solving manager typedef struct Cec_ManSat_t_ Cec_ManSat_t; struct Cec_ManSat_t_ { // parameters Cec_ParSat_t * pPars; // AIGs used in the package Gia_Man_t * pAig; // the AIG whose outputs are considered Vec_Int_t * vStatus; // status for each output // SAT solving sat_solver * pSat; // recyclable SAT solver int nSatVars; // the counter of SAT variables int * pSatVars; // mapping of each node into its SAT var Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned int nRecycles; // the number of times SAT solver was recycled int nCallsSince; // the number of calls since the last recycle Vec_Ptr_t * vFanins; // fanins of the CNF node // counter-examples Vec_Int_t * vCex; // the latest counter-example Vec_Int_t * vVisits; // temporary array for visited nodes // 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 int nCexLits; // conflicts int nConfUnsat; // conflicts in unsat problems int nConfSat; // conflicts in sat problems int nConfUndec; // conflicts in undec problems // runtime stats int timeSatUnsat; // unsat int timeSatSat; // sat int timeSatUndec; // undecided int timeTotal; // total runtime }; // combinational simulation manager typedef struct Cec_ManSim_t_ Cec_ManSim_t; struct Cec_ManSim_t_ { // parameters Gia_Man_t * pAig; // the AIG to be used for simulation Cec_ParSim_t * pPars; // simulation parameters int nWords; // the number of simulation words // recycable memory int * pSimInfo; // simulation information offsets 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 int nWordsOld; // the number of simulation words after previous relink // internal simulation info Vec_Ptr_t * vCiSimInfo; // CI simulation info Vec_Ptr_t * vCoSimInfo; // CO simulation info // counter examples void ** pCexes; // counter-examples for each output int iOut; // first failed output int nOuts; // the number of failed outputs Abc_Cex_t * pCexComb; // counter-example for the first failed output Abc_Cex_t * pBestState; // the state that led to most of the refinements // scoring simulation patterns int * pScores; // counters of refinement for each pattern // 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 }; // combinational simulation manager typedef struct Cec_ManFra_t_ Cec_ManFra_t; struct Cec_ManFra_t_ { // parameters Gia_Man_t * pAig; // the AIG to be used for simulation Cec_ParFra_t * pPars; // SAT sweeping parameters // simulation patterns Vec_Int_t * vXorNodes; // nodes used in speculative reduction int nAllProved; // total number of proved nodes int nAllDisproved; // total number of disproved nodes int nAllFailed; // total number of failed nodes // runtime stats abctime timeSim; // unsat abctime timePat; // unsat abctime timeSat; // sat abctime timeTotal; // total runtime }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== cecCorr.c ============================================================*/ extern void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, abctime Time ); /*=== cecClass.c ============================================================*/ extern int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i ); extern int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax ); extern int Cec_ManSimClassesRefine( Cec_ManSim_t * p ); extern int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos ); /*=== cecIso.c ============================================================*/ extern int * Cec_ManDetectIsomorphism( Gia_Man_t * p ); /*=== cecMan.c ============================================================*/ extern Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars ); extern void Cec_ManSatPrintStats( Cec_ManSat_t * p ); extern void Cec_ManSatStop( Cec_ManSat_t * p ); extern Cec_ManPat_t * Cec_ManPatStart(); extern void Cec_ManPatPrintStats( Cec_ManPat_t * p ); extern void Cec_ManPatStop( Cec_ManPat_t * p ); extern Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t * pPars ); extern void Cec_ManSimStop( Cec_ManSim_t * p ); extern Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t * pPars ); extern void Cec_ManFraStop( Cec_ManFra_t * p ); /*=== cecPat.c ============================================================*/ extern void Cec_ManPatSavePattern( Cec_ManPat_t * pPat, Cec_ManSat_t * p, Gia_Obj_t * pObj ); extern void Cec_ManPatSavePatternCSat( Cec_ManPat_t * pMan, Vec_Int_t * vPat ); extern Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int nInputs, int nWords ); extern Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit ); /*=== cecSeq.c ============================================================*/ extern int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo ); extern int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter ); extern void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ); extern int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig ); extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ); /*=== cecSolve.c ============================================================*/ extern int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj ); extern void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Int_t * vIdsOrig, Vec_Int_t * vMiterPairs, Vec_Int_t * vEquivPairs ); extern void Cec_ManSatSolveCSat( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ); extern Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats ); extern Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ); extern int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj ); extern int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); extern void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ); extern Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * p ); /*=== ceFraeep.c ============================================================*/ extern Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p ); extern int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecIso.c000066400000000000000000000262141300674244400232710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecIso.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Detection of structural isomorphism.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned * Cec_ManIsoInfo( unsigned * pStore, int nWords, int Id ) { return pStore + nWords * Id; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes simulation info for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManIsoSimulate( Gia_Obj_t * pObj, int Id, unsigned * pStore, int nWords ) { unsigned * pInfo = Cec_ManIsoInfo( pStore, nWords, Id ); unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId0(pObj, Id) ); unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId1(pObj, Id) ); int w; if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_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 ( Gia_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]; } } /**Function************************************************************* Synopsis [Copies simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManIsoCopy( int IdDest, int IdSour, unsigned * pStore, int nWords ) { unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, IdDest ); unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, IdSour ); int w; for ( w = 0; w < nWords; w++ ) pInfo0[w] = pInfo1[w]; } /**Function************************************************************* Synopsis [Compares simulation info of two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManIsoEqual( int Id0, int Id1, unsigned * pStore, int nWords ) { unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id0 ); unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Id1 ); int w; for ( w = 0; w < nWords; w++ ) if ( pInfo0[w] != pInfo1[w] ) return 0; return 1; } /**Function************************************************************* Synopsis [Generates random simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManIsoRandom( int Id, unsigned * pStore, int nWords ) { unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id ); int w; for ( w = 0; w < nWords; w++ ) pInfo0[w] = Gia_ManRandom( 0 ); } /**Function************************************************************* Synopsis [Computes hash key of the simuation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManIsoHashKey( int Id, unsigned * pStore, 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 * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id ); unsigned uHash = 0; int i; for ( i = 0; i < nWords; i++ ) uHash ^= pInfo0[i] * s_Primes[i & 0xf]; return (int)(uHash % nTableSize); } /**Function************************************************************* Synopsis [Adds node to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManIsoTableAdd( Gia_Man_t * p, int Id, unsigned * pStore, int nWords, int * pTable, int nTableSize ) { Gia_Obj_t * pTemp; int Key, Ent, Color = Gia_ObjColors( p, Id ); assert( Color == 1 || Color == 2 ); Key = Gia_ManIsoHashKey( Id, pStore, nWords, nTableSize ); for ( Ent = pTable[Key], pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL); pTemp; Ent = pTemp->Value, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL) ) { if ( Gia_ObjColors( p, Ent ) != Color ) continue; if ( !Gia_ManIsoEqual( Id, Ent, pStore, nWords ) ) continue; // found node with the same color and signature - mark it and do not add new node pTemp->fMark0 = 1; return; } // did not find the node with the same color and signature - add new node pTemp = Gia_ManObj( p, Id ); assert( pTemp->Value == 0 ); assert( pTemp->fMark0 == 0 ); pTemp->Value = pTable[Key]; pTable[Key] = Id; } /**Function************************************************************* Synopsis [Extracts equivalence class candidates from one bin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManIsoExtractClasses( Gia_Man_t * p, int Bin, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB ) { Gia_Obj_t * pTemp; int Ent; Vec_IntClear( vNodesA ); Vec_IntClear( vNodesB ); for ( Ent = Bin, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL); pTemp; Ent = pTemp->Value, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL) ) { if ( pTemp->fMark0 ) { pTemp->fMark0 = 0; continue; } if ( Gia_ObjColors( p, Ent ) == 1 ) Vec_IntPush( vNodesA, Ent ); else Vec_IntPush( vNodesB, Ent ); } return Vec_IntSize(vNodesA) > 0 && Vec_IntSize(vNodesB) > 0; } /**Function************************************************************* Synopsis [Matches nodes in the extacted classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManIsoMatchNodes( int * pIso, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB ) { int k0, k1, IdA, IdB; Vec_IntForEachEntry( vNodesA, IdA, k0 ) Vec_IntForEachEntry( vNodesB, IdB, k1 ) { if ( Gia_ManIsoEqual( IdA, IdB, pStore, nWords ) ) { assert( pIso[IdA] == 0 ); assert( pIso[IdB] == 0 ); assert( IdA != IdB ); pIso[IdA] = IdB; pIso[IdB] = IdA; continue; } } } /**Function************************************************************* Synopsis [Transforms iso into equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManTransformClasses( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; assert( p->pReprs && p->pNexts && p->pIso ); memset( p->pReprs, 0, sizeof(int) * Gia_ManObjNum(p) ); memset( p->pNexts, 0, sizeof(int) * Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) { p->pReprs[i].iRepr = GIA_VOID; if ( p->pIso[i] && p->pIso[i] < i ) { p->pReprs[i].iRepr = p->pIso[i]; p->pNexts[p->pIso[i]] = i; } } } /**Function************************************************************* Synopsis [Finds node correspondences in the miter.] Description [Assumes that the colors are assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ int * Cec_ManDetectIsomorphism( Gia_Man_t * p ) { int nWords = 2; Gia_Obj_t * pObj; Vec_Int_t * vNodesA, * vNodesB; unsigned * pStore, Counter; int i, * pIso, * pTable, nTableSize; // start equivalence classes pIso = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsCo(pObj) ) { assert( Gia_ObjColors(p, i) == 0 ); continue; } assert( Gia_ObjColors(p, i) ); if ( Gia_ObjColors(p, i) == 3 ) pIso[i] = i; } // start simulation info pStore = ABC_ALLOC( unsigned, Gia_ManObjNum(p) * nWords ); // simulate and create table nTableSize = Abc_PrimeCudd( 100 + Gia_ManObjNum(p)/2 ); pTable = ABC_CALLOC( int, nTableSize ); Gia_ManCleanValue( p ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCo(pObj) ) continue; if ( pIso[i] == 0 ) // simulate Gia_ManIsoSimulate( pObj, i, pStore, nWords ); else if ( pIso[i] < i ) // copy Gia_ManIsoCopy( i, pIso[i], pStore, nWords ); else // generate Gia_ManIsoRandom( i, pStore, nWords ); if ( pIso[i] == 0 ) Gia_ManIsoTableAdd( p, i, pStore, nWords, pTable, nTableSize ); } // create equivalence classes vNodesA = Vec_IntAlloc( 100 ); vNodesB = Vec_IntAlloc( 100 ); for ( i = 0; i < nTableSize; i++ ) if ( Gia_ManIsoExtractClasses( p, pTable[i], pStore, nWords, vNodesA, vNodesB ) ) Gia_ManIsoMatchNodes( pIso, pStore, nWords, vNodesA, vNodesB ); Vec_IntFree( vNodesA ); Vec_IntFree( vNodesB ); // collect info Counter = 0; Gia_ManForEachObj1( p, pObj, i ) { Counter += (pIso[i] && pIso[i] < i); /* if ( pIso[i] && pIso[i] < i ) { if ( (Gia_ObjIsHead(p,pIso[i]) && Gia_ObjRepr(p,i)==pIso[i]) || (Gia_ObjIsClass(p,pIso[i]) && Gia_ObjRepr(p,i)==Gia_ObjRepr(p,pIso[i])) ) Abc_Print( 1, "1" ); else Abc_Print( 1, "0" ); } */ } Abc_Print( 1, "Computed %d pairs of structurally equivalent nodes.\n", Counter ); // p->pIso = pIso; // Cec_ManTransformClasses( p ); ABC_FREE( pTable ); ABC_FREE( pStore ); return pIso; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecMan.c000066400000000000000000000210541300674244400232470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Manager procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars ) { Cec_ManSat_t * p; // create interpolation manager p = ABC_ALLOC( Cec_ManSat_t, 1 ); memset( p, 0, sizeof(Cec_ManSat_t) ); p->pPars = pPars; p->pAig = pAig; // SAT solving p->nSatVars = 1; p->pSatVars = ABC_CALLOC( int, Gia_ManObjNum(pAig) ); p->vUsedNodes = Vec_PtrAlloc( 1000 ); p->vFanins = Vec_PtrAlloc( 100 ); p->vCex = Vec_IntAlloc( 100 ); p->vVisits = Vec_IntAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [Prints statistics of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSatPrintStats( Cec_ManSat_t * p ) { Abc_Print( 1, "CO = %8d ", Gia_ManCoNum(p->pAig) ); Abc_Print( 1, "AND = %8d ", Gia_ManAndNum(p->pAig) ); Abc_Print( 1, "Conf = %5d ", p->pPars->nBTLimit ); Abc_Print( 1, "MinVar = %5d ", p->pPars->nSatVarMax ); Abc_Print( 1, "MinCalls = %5d\n", p->pPars->nCallsRecycle ); Abc_Print( 1, "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_PrintTimeP( 1, "Time", p->timeSatUnsat, p->timeTotal ); Abc_Print( 1, "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_PrintTimeP( 1, "Time", p->timeSatSat, p->timeTotal ); Abc_Print( 1, "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_PrintTimeP( 1, "Time", p->timeSatUndec, p->timeTotal ); Abc_PrintTime( 1, "Total time", p->timeTotal ); } /**Function************************************************************* Synopsis [Frees the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSatStop( Cec_ManSat_t * p ) { if ( p->pSat ) sat_solver_delete( p->pSat ); Vec_IntFree( p->vCex ); Vec_IntFree( p->vVisits ); Vec_PtrFree( p->vUsedNodes ); Vec_PtrFree( p->vFanins ); ABC_FREE( p->pSatVars ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cec_ManPat_t * Cec_ManPatStart() { Cec_ManPat_t * p; p = ABC_CALLOC( Cec_ManPat_t, 1 ); p->vStorage = Vec_StrAlloc( 1<<20 ); p->vPattern1 = Vec_IntAlloc( 1000 ); p->vPattern2 = Vec_IntAlloc( 1000 ); return p; } /**Function************************************************************* Synopsis [Creates AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPatPrintStats( Cec_ManPat_t * p ) { Abc_Print( 1, "Latest: P = %8d. L = %10d. Lm = %10d. Ave = %6.1f. MEM =%6.2f MB\n", p->nPats, p->nPatLits, p->nPatLitsMin, 1.0 * p->nPatLitsMin/p->nPats, 1.0*(Vec_StrSize(p->vStorage)-p->iStart)/(1<<20) ); Abc_Print( 1, "Total: P = %8d. L = %10d. Lm = %10d. Ave = %6.1f. MEM =%6.2f MB\n", p->nPatsAll, p->nPatLitsAll, p->nPatLitsMinAll, 1.0 * p->nPatLitsMinAll/p->nPatsAll, 1.0*Vec_StrSize(p->vStorage)/(1<<20) ); Abc_PrintTimeP( 1, "Finding ", p->timeFind, p->timeTotal ); Abc_PrintTimeP( 1, "Shrinking", p->timeShrink, p->timeTotal ); Abc_PrintTimeP( 1, "Verifying", p->timeVerify, p->timeTotal ); Abc_PrintTimeP( 1, "Sorting ", p->timeSort, p->timeTotal ); Abc_PrintTimeP( 1, "Packing ", p->timePack, p->timeTotal ); Abc_PrintTime( 1, "TOTAL ", p->timeTotal ); } /**Function************************************************************* Synopsis [Deletes AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPatStop( Cec_ManPat_t * p ) { Vec_StrFree( p->vStorage ); Vec_IntFree( p->vPattern1 ); Vec_IntFree( p->vPattern2 ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t * pPars ) { Cec_ManSim_t * p; p = ABC_ALLOC( Cec_ManSim_t, 1 ); memset( p, 0, sizeof(Cec_ManSim_t) ); p->pAig = pAig; p->pPars = pPars; p->nWords = pPars->nWords; p->pSimInfo = ABC_CALLOC( int, Gia_ManObjNum(pAig) ); p->vClassOld = Vec_IntAlloc( 1000 ); p->vClassNew = Vec_IntAlloc( 1000 ); p->vClassTemp = Vec_IntAlloc( 1000 ); p->vRefinedC = Vec_IntAlloc( 10000 ); p->vCiSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(p->pAig), pPars->nWords ); if ( pPars->fCheckMiter || Gia_ManRegNum(p->pAig) ) { p->vCoSimInfo = Vec_PtrAllocSimInfo( Gia_ManCoNum(p->pAig), pPars->nWords ); Vec_PtrCleanSimInfo( p->vCoSimInfo, 0, pPars->nWords ); } p->iOut = -1; return p; } /**Function************************************************************* Synopsis [Deletes AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSimStop( Cec_ManSim_t * p ) { Vec_IntFree( p->vClassOld ); Vec_IntFree( p->vClassNew ); Vec_IntFree( p->vClassTemp ); Vec_IntFree( p->vRefinedC ); if ( p->vCiSimInfo ) Vec_PtrFree( p->vCiSimInfo ); if ( p->vCoSimInfo ) Vec_PtrFree( p->vCoSimInfo ); ABC_FREE( p->pScores ); ABC_FREE( p->pCexComb ); ABC_FREE( p->pCexes ); ABC_FREE( p->pMems ); ABC_FREE( p->pSimInfo ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t * pPars ) { Cec_ManFra_t * p; p = ABC_ALLOC( Cec_ManFra_t, 1 ); memset( p, 0, sizeof(Cec_ManFra_t) ); p->pAig = pAig; p->pPars = pPars; p->vXorNodes = Vec_IntAlloc( 1000 ); return p; } /**Function************************************************************* Synopsis [Deletes AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManFraStop( Cec_ManFra_t * p ) { Vec_IntFree( p->vXorNodes ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecPat.c000066400000000000000000000422101300674244400232550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecPat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Simulation pattern manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecPat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cec_ManPatStoreNum( Cec_ManPat_t * p, int Num ) { unsigned x = (unsigned)Num; assert( Num >= 0 ); while ( x & ~0x7f ) { Vec_StrPush( p->vStorage, (char)((x & 0x7f) | 0x80) ); x >>= 7; } Vec_StrPush( p->vStorage, (char)x ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cec_ManPatRestoreNum( Cec_ManPat_t * p ) { int ch, i, x = 0; for ( i = 0; (ch = Vec_StrEntry(p->vStorage, p->iStart++)) & 0x80; i++ ) x |= (ch & 0x7f) << (7 * i); return x | (ch << (7 * i)); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cec_ManPatStore( Cec_ManPat_t * p, Vec_Int_t * vPat ) { int i, Number, NumberPrev; assert( Vec_IntSize(vPat) > 0 ); Cec_ManPatStoreNum( p, Vec_IntSize(vPat) ); NumberPrev = Vec_IntEntry( vPat, 0 ); Cec_ManPatStoreNum( p, NumberPrev ); Vec_IntForEachEntryStart( vPat, Number, i, 1 ) { assert( NumberPrev < Number ); Cec_ManPatStoreNum( p, Number - NumberPrev ); NumberPrev = Number; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cec_ManPatRestore( Cec_ManPat_t * p, Vec_Int_t * vPat ) { int i, Size, Number; Vec_IntClear( vPat ); Size = Cec_ManPatRestoreNum( p ); Number = Cec_ManPatRestoreNum( p ); Vec_IntPush( vPat, Number ); for ( i = 1; i < Size; i++ ) { Number += Cec_ManPatRestoreNum( p ); Vec_IntPush( vPat, Number ); } assert( Vec_IntSize(vPat) == Size ); } /**Function************************************************************* Synopsis [Derives satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManPatComputePattern_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj ) { int Counter = 0; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { pObj->fMark1 = Cec_ObjSatVarValue( pSat, pObj ); return 1; } assert( Gia_ObjIsAnd(pObj) ); Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin0(pObj) ); Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin1(pObj) ); pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); return Counter; } /**Function************************************************************* Synopsis [Derives satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPatComputePattern1_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vPat, Abc_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) ); return; } assert( Gia_ObjIsAnd(pObj) ); if ( pObj->fMark1 == 1 ) { Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat ); Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat ); } else { assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 || (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ); if ( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 ) Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat ); else Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat ); } } /**Function************************************************************* Synopsis [Derives satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPatComputePattern2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vPat, Abc_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) ); return; } assert( Gia_ObjIsAnd(pObj) ); if ( pObj->fMark1 == 1 ) { Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat ); Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat ); } else { assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 || (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ); if ( (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 ) Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat ); else Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat ); } } /**Function************************************************************* Synopsis [Derives satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManPatComputePattern3_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { int Value0, Value1, Value; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return (pObj->fMark1 << 1) | pObj->fMark0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { pObj->fMark0 = 1; pObj->fMark1 = 1; return GIA_UND; } assert( Gia_ObjIsAnd(pObj) ); Value0 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) ); Value1 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin1(pObj) ); Value = Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) ); pObj->fMark0 = (Value & 1); pObj->fMark1 = ((Value >> 1) & 1); return Value; } /**Function************************************************************* Synopsis [Derives satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat ) { Gia_Obj_t * pTemp; int i, Value; Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vPat, Value, i ) { pTemp = Gia_ManCi( p, Abc_Lit2Var(Value) ); // assert( Abc_LitIsCompl(Value) != (int)pTemp->fMark1 ); if ( pTemp->fMark1 ) { pTemp->fMark0 = 0; pTemp->fMark1 = 1; } else { pTemp->fMark0 = 1; pTemp->fMark1 = 0; } Gia_ObjSetTravIdCurrent( p, pTemp ); } Value = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) ); Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pObj) ); if ( Value != GIA_ONE ) Abc_Print( 1, "Cec_ManPatVerifyPattern(): Verification failed.\n" ); assert( Value == GIA_ONE ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPatComputePattern4_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); pObj->fMark0 = 0; if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) ); Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPatCleanMark0( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); Gia_ManIncrementTravId( p ); Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManPatSavePattern( Cec_ManPat_t * pMan, Cec_ManSat_t * p, Gia_Obj_t * pObj ) { Vec_Int_t * vPat; int nPatLits; abctime clkTotal = Abc_Clock(); // abctime clk; assert( Gia_ObjIsCo(pObj) ); pMan->nPats++; pMan->nPatsAll++; // compute values in the cone of influence //clk = Abc_Clock(); Gia_ManIncrementTravId( p->pAig ); nPatLits = Cec_ManPatComputePattern_rec( p, p->pAig, Gia_ObjFanin0(pObj) ); assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 1 ); pMan->nPatLits += nPatLits; pMan->nPatLitsAll += nPatLits; //pMan->timeFind += Abc_Clock() - clk; // compute sensitizing path //clk = Abc_Clock(); Vec_IntClear( pMan->vPattern1 ); Gia_ManIncrementTravId( p->pAig ); Cec_ManPatComputePattern1_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern1 ); // compute sensitizing path Vec_IntClear( pMan->vPattern2 ); Gia_ManIncrementTravId( p->pAig ); Cec_ManPatComputePattern2_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern2 ); // compare patterns vPat = Vec_IntSize(pMan->vPattern1) < Vec_IntSize(pMan->vPattern2) ? pMan->vPattern1 : pMan->vPattern2; pMan->nPatLitsMin += Vec_IntSize(vPat); pMan->nPatLitsMinAll += Vec_IntSize(vPat); //pMan->timeShrink += Abc_Clock() - clk; // verify pattern using ternary simulation //clk = Abc_Clock(); // Cec_ManPatVerifyPattern( p->pAig, pObj, vPat ); //pMan->timeVerify += Abc_Clock() - clk; // sort pattern //clk = Abc_Clock(); Vec_IntSort( vPat, 0 ); //pMan->timeSort += Abc_Clock() - clk; // save pattern Cec_ManPatStore( pMan, vPat ); pMan->timeTotal += Abc_Clock() - clkTotal; } void Cec_ManPatSavePatternCSat( Cec_ManPat_t * pMan, Vec_Int_t * vPat ) { // sort pattern Vec_IntSort( vPat, 0 ); // save pattern Cec_ManPatStore( pMan, vPat ); } /**Function************************************************************* Synopsis [Packs patterns into array of simulation info.] Description [] SideEffects [] SeeAlso [] *************************************`**********************************/ int Cec_ManPatCollectTry( 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 [Packs patterns into array of simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int nInputs, int nWordsInit ) { Vec_Int_t * vPat = pMan->vPattern1; Vec_Ptr_t * vInfo, * vPres; int k, kMax = -1, nPatterns = 0; int iStartOld = pMan->iStart; int nWords = nWordsInit; int nBits = 32 * nWords; abctime clk = Abc_Clock(); vInfo = Vec_PtrAllocSimInfo( nInputs, nWords ); Gia_ManRandomInfo( vInfo, 0, 0, nWords ); vPres = Vec_PtrAllocSimInfo( nInputs, nWords ); Vec_PtrCleanSimInfo( vPres, 0, nWords ); while ( pMan->iStart < Vec_StrSize(pMan->vStorage) ) { nPatterns++; Cec_ManPatRestore( pMan, vPat ); for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) ) if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) break; kMax = Abc_MaxInt( kMax, k ); if ( k == nBits-1 ) { Vec_PtrReallocSimInfo( vInfo ); Gia_ManRandomInfo( vInfo, 0, nWords, 2*nWords ); Vec_PtrReallocSimInfo( vPres ); Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords ); nWords *= 2; nBits *= 2; } } Vec_PtrFree( vPres ); pMan->nSeries = Vec_PtrReadWordsSimInfo(vInfo) / nWordsInit; pMan->timePack += Abc_Clock() - clk; pMan->timeTotal += Abc_Clock() - clk; pMan->iStart = iStartOld; if ( pMan->fVerbose ) { Abc_Print( 1, "Total = %5d. Max used = %5d. Full = %5d. Series = %d. ", nPatterns, kMax, nWordsInit*32, pMan->nSeries ); ABC_PRT( "Time", Abc_Clock() - clk ); Cec_ManPatPrintStats( pMan ); } return vInfo; } /**Function************************************************************* Synopsis [Packs patterns into array of simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit ) { Vec_Int_t * vPat; Vec_Ptr_t * vInfo, * vPres; int k, nSize, iStart, kMax = 0, nPatterns = 0; int nWords = nWordsInit; int nBits = 32 * nWords; // int RetValue; assert( nRegs <= nInputs ); vPat = Vec_IntAlloc( 100 ); vInfo = Vec_PtrAllocSimInfo( nInputs, nWords ); Vec_PtrCleanSimInfo( vInfo, 0, nWords ); Gia_ManRandomInfo( vInfo, nRegs, 0, nWords ); vPres = Vec_PtrAllocSimInfo( nInputs, nWords ); Vec_PtrCleanSimInfo( vPres, 0, nWords ); iStart = 0; while ( iStart < Vec_IntSize(vCexStore) ) { nPatterns++; // skip the output number iStart++; // get the number of items nSize = Vec_IntEntry( vCexStore, iStart++ ); if ( nSize <= 0 ) continue; // extract pattern Vec_IntClear( vPat ); for ( k = 0; k < nSize; k++ ) Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); // add pattern to storage for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) ) if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) ) break; // k = kMax + 1; // RetValue = Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ); // assert( RetValue == 1 ); kMax = Abc_MaxInt( kMax, k ); if ( k == nBits-1 ) { Vec_PtrReallocSimInfo( vInfo ); Vec_PtrCleanSimInfo( vInfo, nWords, 2*nWords ); Gia_ManRandomInfo( vInfo, nRegs, nWords, 2*nWords ); Vec_PtrReallocSimInfo( vPres ); Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords ); nWords *= 2; nBits *= 2; } } // Abc_Print( 1, "packed %d patterns into %d vectors (out of %d)\n", nPatterns, kMax, nBits ); Vec_PtrFree( vPres ); Vec_IntFree( vPat ); return vInfo; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecSeq.c000066400000000000000000000360061300674244400232670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecSeq.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Refinement of sequential equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sets register values from the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSeqDeriveInfoFromCex( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ) { unsigned * pInfo; int k, i, w, nWords; assert( pCex->nBits == pCex->nRegs + pCex->nPis * (pCex->iFrame + 1) ); assert( pCex->nBits - pCex->nRegs + Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) ); nWords = Vec_PtrReadWordsSimInfo( vInfo ); /* // user register values assert( pCex->nRegs == Gia_ManRegNum(pAig) ); for ( k = 0; k < pCex->nRegs; k++ ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); for ( w = 0; w < nWords; w++ ) pInfo[w] = Abc_InfoHasBit( pCex->pData, k )? ~0 : 0; } */ // print warning about register values for ( k = 0; k < pCex->nRegs; k++ ) if ( Abc_InfoHasBit( pCex->pData, k ) ) break; if ( k < pCex->nRegs ) Abc_Print( 0, "The CEX has flop values different from 0, but they are currently not used by \"resim\".\n" ); // assign zero register values for ( k = 0; k < Gia_ManRegNum(pAig); k++ ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); for ( w = 0; w < nWords; w++ ) pInfo[w] = 0; } for ( i = pCex->nRegs; i < pCex->nBits; i++ ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, k++ ); for ( w = 0; w < nWords; w++ ) pInfo[w] = Gia_ManRandom(0); // set simulation pattern and make sure it is second (first will be erased during simulation) pInfo[0] = (pInfo[0] << 1) | Abc_InfoHasBit( pCex->pData, i ); pInfo[0] <<= 1; } for ( ; k < Vec_PtrSize(vInfo); k++ ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); for ( w = 0; w < nWords; w++ ) pInfo[w] = Gia_ManRandom(0); } } /**Function************************************************************* Synopsis [Sets register values from the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex ) { unsigned * pInfo; int k, w, nWords; nWords = Vec_PtrReadWordsSimInfo( vInfo ); assert( pCex == NULL || Gia_ManRegNum(pAig) == pCex->nRegs ); assert( Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) ); for ( k = 0; k < Gia_ManRegNum(pAig); k++ ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); for ( w = 0; w < nWords; w++ ) pInfo[w] = (pCex && Abc_InfoHasBit(pCex->pData, k))? ~0 : 0; } for ( ; k < Vec_PtrSize(vInfo); k++ ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, k ); for ( w = 0; w < nWords; w++ ) pInfo[w] = Gia_ManRandom( 0 ); } } /**Function************************************************************* Synopsis [Resimulates the classes using sequential simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo ) { unsigned * pInfo0, * pInfo1; int f, i, k, w; // assert( Gia_ManRegNum(p->pAig) > 0 ); assert( Vec_PtrSize(vInfo) == Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * p->pPars->nFrames ); for ( k = 0; k < Gia_ManRegNum(p->pAig); k++ ) { pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k ); pInfo1 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + k ); for ( w = 0; w < p->nWords; w++ ) pInfo1[w] = pInfo0[w]; } for ( f = 0; f < p->pPars->nFrames; f++ ) { for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) { pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k++ ); pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i ); for ( w = 0; w < p->nWords; w++ ) pInfo1[w] = pInfo0[w]; } for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { pInfo0 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + i ); pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i ); for ( w = 0; w < p->nWords; w++ ) pInfo1[w] = pInfo0[w]; } if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) ) return 1; } assert( k == Vec_PtrSize(vInfo) ); return 0; } /**Function************************************************************* Synopsis [Resimulates information to refine equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter ) { Cec_ParSim_t ParsSim, * pParsSim = &ParsSim; Cec_ManSim_t * pSim; int RetValue;//, clkTotal = Abc_Clock(); assert( (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) % Gia_ManPiNum(pAig) == 0 ); Cec_ManSimSetDefaultParams( pParsSim ); pParsSim->nFrames = (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) / Gia_ManPiNum(pAig); pParsSim->nWords = Vec_PtrReadWordsSimInfo( vSimInfo ); pParsSim->fCheckMiter = fCheckMiter; Gia_ManCreateValueRefs( pAig ); pSim = Cec_ManSimStart( pAig, pParsSim ); if ( pBestState ) pSim->pBestState = pBestState; RetValue = Cec_ManSeqResimulate( pSim, vSimInfo ); pSim->pBestState = NULL; Cec_ManSimStop( pSim ); return RetValue; } /**Function************************************************************* Synopsis [Resimuates one counter-example to refine equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex ) { Vec_Ptr_t * vSimInfo; int RetValue; abctime clkTotal = Abc_Clock(); if ( pCex == NULL ) { Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Counter-example is not available.\n" ); return -1; } if ( pAig->pReprs == NULL ) { Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Equivalence classes are not available.\n" ); return -1; } if ( Gia_ManRegNum(pAig) == 0 ) { Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Not a sequential AIG.\n" ); return -1; } // if ( Gia_ManRegNum(pAig) != pCex->nRegs || Gia_ManPiNum(pAig) != pCex->nPis ) if ( Gia_ManPiNum(pAig) != pCex->nPis ) { Abc_Print( 1, "Cec_ManSeqResimulateCounter(): The number of PIs in the AIG and the counter-example differ.\n" ); return -1; } if ( pPars->fVerbose ) Abc_Print( 1, "Resimulating %d timeframes.\n", pPars->nFrames + pCex->iFrame + 1 ); Gia_ManRandom( 1 ); vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) + Gia_ManPiNum(pAig) * (pPars->nFrames + pCex->iFrame + 1), 1 ); Cec_ManSeqDeriveInfoFromCex( vSimInfo, pAig, pCex ); if ( pPars->fVerbose ) Gia_ManEquivPrintClasses( pAig, 0, 0 ); RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, NULL, pPars->fCheckMiter ); if ( pPars->fVerbose ) Gia_ManEquivPrintClasses( pAig, 0, 0 ); Vec_PtrFree( vSimInfo ); if ( pPars->fVerbose ) ABC_PRT( "Time", Abc_Clock() - clkTotal ); // if ( RetValue && pPars->fCheckMiter ) // Abc_Print( 1, "Cec_ManSeqResimulateCounter(): An output of the miter is asserted!\n" ); return RetValue; } /**Function************************************************************* Synopsis [Returns the number of POs that are not const0 cands.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig ) { Gia_Obj_t * pObj; int i, Counter = 0; if ( pAig->pReprs == NULL ) return -1; Gia_ManForEachPo( pAig, pObj, i ) if ( !Gia_ObjIsConst( pAig, Gia_ObjFaninId0p(pAig, pObj) ) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Returns the number of POs that are not const0 cands.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ) { Gia_Obj_t * pObj; int i, RetValue = 0; if ( pAig->pReprs == NULL ) return 0; // label internal nodes driving POs Gia_ManForEachPo( pAig, pObj, i ) Gia_ObjFanin0(pObj)->fMark0 = 1; // check if there are non-labled equivs Gia_ManForEachObj( pAig, pObj, i ) if ( Gia_ObjIsCand(pObj) && !pObj->fMark0 && Gia_ObjRepr(pAig, i) != GIA_VOID ) { RetValue = 1; break; } // clean internal nodes driving POs Gia_ManForEachPo( pAig, pObj, i ) Gia_ObjFanin0(pObj)->fMark0 = 0; return RetValue; } /**Function************************************************************* Synopsis [Performs semiformal refinement of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars ) { int nAddFrames = 16; // additional timeframes to simulate int nCountNoRef = 0; int nFramesReal; Cec_ParSat_t ParsSat, * pParsSat = &ParsSat; Vec_Ptr_t * vSimInfo; Vec_Str_t * vStatus; Abc_Cex_t * pState; Gia_Man_t * pSrm, * pReduce, * pAux; int r, nPats, RetValue = 0; if ( pAig->pReprs == NULL ) { Abc_Print( 1, "Cec_ManSeqSemiformal(): Equivalence classes are not available.\n" ); return -1; } if ( Gia_ManRegNum(pAig) == 0 ) { Abc_Print( 1, "Cec_ManSeqSemiformal(): Not a sequential AIG.\n" ); return -1; } Gia_ManRandom( 1 ); // prepare starting pattern pState = Abc_CexAlloc( Gia_ManRegNum(pAig), 0, 0 ); pState->iFrame = -1; pState->iPo = -1; // prepare SAT solving Cec_ManSatSetDefaultParams( pParsSat ); pParsSat->nBTLimit = pPars->nBTLimit; pParsSat->fVerbose = pPars->fVerbose; if ( pParsSat->fVerbose ) { Abc_Print( 1, "Starting: " ); Gia_ManEquivPrintClasses( pAig, 0, 0 ); } // perform the given number of BMC rounds Gia_ManCleanMark0( pAig ); for ( r = 0; r < pPars->nRounds; r++ ) { if ( !Cec_ManCheckNonTrivialCands(pAig) ) { Abc_Print( 1, "Cec_ManSeqSemiformal: There are only trivial equiv candidates left (PO drivers). Quitting.\n" ); break; } // Abc_CexPrint( pState ); // derive speculatively reduced model // pSrm = Gia_ManSpecReduceInit( pAig, pState, pPars->nFrames, pPars->fDualOut ); pSrm = Gia_ManSpecReduceInitFrames( pAig, pState, pPars->nFrames, &nFramesReal, pPars->fDualOut, pPars->nMinOutputs ); if ( pSrm == NULL ) { Abc_Print( 1, "Quitting refinement because miter could not be unrolled.\n" ); break; } assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == (Gia_ManPiNum(pAig) * nFramesReal) ); if ( pPars->fVerbose ) Abc_Print( 1, "Unrolled for %d frames.\n", nFramesReal ); // allocate room for simulation info vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) + Gia_ManPiNum(pAig) * (nFramesReal + nAddFrames), pPars->nWords ); Cec_ManSeqDeriveInfoInitRandom( vSimInfo, pAig, pState ); // fill in simulation info with counter-examples vStatus = Cec_ManSatSolveSeq( vSimInfo, pSrm, pParsSat, Gia_ManRegNum(pAig), &nPats ); Vec_StrFree( vStatus ); Gia_ManStop( pSrm ); // resimulate and refine the classes RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, pState, pPars->fCheckMiter ); Vec_PtrFree( vSimInfo ); assert( pState->iPo >= 0 ); // hit counter pState->iPo = -1; if ( pPars->fVerbose ) { Abc_Print( 1, "BMC = %3d ", nPats ); Gia_ManEquivPrintClasses( pAig, 0, 0 ); } // write equivalence classes Gia_AigerWrite( pAig, "gore.aig", 0, 0 ); // reduce the model pReduce = Gia_ManSpecReduce( pAig, 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 ); // Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" ); // Gia_ManPrintStatsShort( pReduce ); Gia_ManStop( pReduce ); } if ( RetValue ) { Abc_Print( 1, "Cec_ManSeqSemiformal(): An output of the miter is asserted. Refinement stopped.\n" ); break; } // decide when to stop if ( nPats > 0 ) nCountNoRef = 0; else if ( ++nCountNoRef == pPars->nNonRefines ) break; } ABC_FREE( pState ); if ( pPars->fCheckMiter ) { int nNonConsts = Cec_ManCountNonConstOutputs( pAig ); if ( nNonConsts ) Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts ); } return RetValue; } //&r s13207.aig; &ps; ≡ &ps; &semi -R 2 -vm //&r bug/50/temp.aig; &ps; &equiv -smv; &semi -v //r mentor/1_05c.blif; st; &get; &ps; &equiv -smv; &semi -mv //&r bug/50/hdl1.aig; &ps; &equiv -smv; &semi -mv; &srm; &r gsrm.aig; &ps //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecSim.c000066400000000000000000000026761300674244400232750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Simulation manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecSolve.c000066400000000000000000001060341300674244400236260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecSolve.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Performs one round of SAT solving.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecSolve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Cec_ObjSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { return p->pSatVars[Gia_ObjId(p->pAig,pObj)]; } static inline void Cec_ObjSetSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj, int Num ) { p->pSatVars[Gia_ObjId(p->pAig,pObj)] = Num; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns value of the SAT variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { return sat_solver_var_value( p->pSat, Cec_ObjSatNum(p, pObj) ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_AddClausesMux( Cec_ManSat_t * p, Gia_Obj_t * pNode ) { Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; assert( !Gia_IsComplement( pNode ) ); assert( Gia_ObjIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the variable numbers VarF = Cec_ObjSatNum(p,pNode); VarI = Cec_ObjSatNum(p,pNodeI); VarT = Cec_ObjSatNum(p,Gia_Regular(pNodeT)); VarE = Cec_ObjSatNum(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] = toLitCond(VarI, 1); pLits[1] = toLitCond(VarT, 1^fCompT); pLits[2] = toLitCond(VarF, 0); if ( p->pPars->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_AddClausesSuper( Cec_ManSat_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper ) { 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] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), Gia_IsComplement(pFanin)); pLits[1] = toLitCond(Cec_ObjSatNum(p,pNode), 1); if ( p->pPars->fPolarFlip ) { if ( Gia_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); } // add A & B => C or !A + !B + C Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) { pLits[i] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), !Gia_IsComplement(pFanin)); if ( p->pPars->fPolarFlip ) { if ( Gia_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); } } pLits[nLits-1] = toLitCond(Cec_ObjSatNum(p,pNode), 0); if ( p->pPars->fPolarFlip ) { if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); assert( RetValue ); ABC_FREE( pLits ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_CollectSuper_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 && Gia_ObjIsMuxType(pObj)) ) { Vec_PtrPushUnique( vSuper, pObj ); return; } // go through the branches Cec_CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes ); Cec_CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) { assert( !Gia_IsComplement(pObj) ); assert( !Gia_ObjIsCi(pObj) ); Vec_PtrClear( vSuper ); Cec_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ObjAddToFrontier( Cec_ManSat_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier ) { assert( !Gia_IsComplement(pObj) ); if ( Cec_ObjSatNum(p,pObj) ) return; assert( Cec_ObjSatNum(p,pObj) == 0 ); if ( Gia_ObjIsConst0(pObj) ) return; Vec_PtrPush( p->vUsedNodes, pObj ); Cec_ObjSetSatNum( p, pObj, p->nSatVars++ ); if ( Gia_ObjIsAnd(pObj) ) Vec_PtrPush( vFrontier, pObj ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { Vec_Ptr_t * vFrontier; Gia_Obj_t * pNode, * pFanin; int i, k, fUseMuxes = 1; // quit if CNF is ready if ( Cec_ObjSatNum(p,pObj) ) return; if ( Gia_ObjIsCi(pObj) ) { Vec_PtrPush( p->vUsedNodes, pObj ); Cec_ObjSetSatNum( p, pObj, p->nSatVars++ ); sat_solver_setnvars( p->pSat, p->nSatVars ); return; } assert( Gia_ObjIsAnd(pObj) ); // start the frontier vFrontier = Vec_PtrAlloc( 100 ); Cec_ObjAddToFrontier( p, pObj, vFrontier ); // explore nodes in the frontier Vec_PtrForEachEntry( Gia_Obj_t *, vFrontier, pNode, i ) { // create the supergate assert( Cec_ObjSatNum(p,pNode) ); if ( fUseMuxes && Gia_ObjIsMuxType(pNode) ) { 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 ) Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier ); Cec_AddClausesMux( p, pNode ); } else { Cec_CollectSuper( pNode, fUseMuxes, p->vFanins ); Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier ); Cec_AddClausesSuper( p, pNode, p->vFanins ); } assert( Vec_PtrSize(p->vFanins) > 1 ); } Vec_PtrFree( vFrontier ); } /**Function************************************************************* Synopsis [Recycles the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSatSolverRecycle( Cec_ManSat_t * p ) { int Lit; if ( p->pSat ) { Gia_Obj_t * pObj; int i; Vec_PtrForEachEntry( Gia_Obj_t *, p->vUsedNodes, pObj, i ) Cec_ObjSetSatNum( p, pObj, 0 ); Vec_PtrClear( p->vUsedNodes ); // memset( p->pSatVars, 0, sizeof(int) * Gia_ManObjNumMax(p->pAigTotal) ); sat_solver_delete( p->pSat ); } p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, 1000 ); p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); // var 0 is not used // var 1 is reserved for const0 node - add the clause p->nSatVars = 1; // p->nSatVars = 0; Lit = toLitCond( p->nSatVars, 1 ); // if ( p->pPars->fPolarFlip ) // no need to normalize const0 node (bug fix by SS on 9/17/2012) // Lit = lit_neg( Lit ); sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); Cec_ObjSetSatNum( p, Gia_ManConst0(p->pAig), p->nSatVars++ ); p->nRecycles++; p->nCallsSince = 0; } /**Function************************************************************* Synopsis [Sets variable activities in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_SetActivityFactors_rec( Cec_ManSat_t * p, Gia_Obj_t * pObj, int LevelMin, int LevelMax ) { float dActConeBumpMax = 20.0; int iVar; // skip visited variables if ( Gia_ObjIsTravIdCurrent(p->pAig, pObj) ) return; Gia_ObjSetTravIdCurrent(p->pAig, pObj); // add the PI to the list if ( Gia_ObjLevel(p->pAig, pObj) <= LevelMin || Gia_ObjIsCi(pObj) ) return; // set the factor of this variable // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump if ( (iVar = Cec_ObjSatNum(p,pObj)) ) { p->pSat->factors[iVar] = dActConeBumpMax * (Gia_ObjLevel(p->pAig, pObj) - LevelMin)/(LevelMax - LevelMin); veci_push(&p->pSat->act_vars, iVar); } // explore the fanins Cec_SetActivityFactors_rec( p, Gia_ObjFanin0(pObj), LevelMin, LevelMax ); Cec_SetActivityFactors_rec( p, Gia_ObjFanin1(pObj), LevelMin, LevelMax ); } /**Function************************************************************* Synopsis [Sets variable activities in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_SetActivityFactors( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { float dActConeRatio = 0.5; int LevelMin, LevelMax; // reset the active variables veci_resize(&p->pSat->act_vars, 0); // prepare for traversal Gia_ManIncrementTravId( p->pAig ); // determine the min and max level to visit assert( dActConeRatio > 0 && dActConeRatio < 1 ); LevelMax = Gia_ObjLevel(p->pAig,pObj); LevelMin = (int)(LevelMax * (1.0 - dActConeRatio)); // traverse Cec_SetActivityFactors_rec( p, pObj, LevelMin, LevelMax ); //Cec_PrintActivity( p ); return 1; } /**Function************************************************************* Synopsis [Runs equivalence test for the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pObjR = Gia_Regular(pObj); int nBTLimit = p->pPars->nBTLimit; int Lit, RetValue, status, nConflicts; abctime clk, clk2; if ( pObj == Gia_ManConst0(p->pAig) ) return 1; if ( pObj == Gia_ManConst1(p->pAig) ) { assert( 0 ); return 0; } p->nCallsSince++; // experiment with this!!! p->nSatTotal++; // check if SAT solver needs recycling if ( p->pSat == NULL || (p->pPars->nSatVarMax && p->nSatVars > p->pPars->nSatVarMax && p->nCallsSince > p->pPars->nCallsRecycle) ) Cec_ManSatSolverRecycle( p ); // if the nodes do not have SAT variables, allocate them clk2 = Abc_Clock(); Cec_CnfNodeAddToSolver( p, pObjR ); //ABC_PRT( "cnf", Abc_Clock() - clk2 ); //Abc_Print( 1, "%d \n", p->pSat->size ); clk2 = Abc_Clock(); // Cec_SetActivityFactors( p, pObjR ); //ABC_PRT( "act", Abc_Clock() - clk2 ); // propage unit clauses if ( p->pSat->qtail != p->pSat->qhead ) { status = sat_solver_simplify(p->pSat); assert( status != 0 ); assert( p->pSat->qtail == p->pSat->qhead ); } // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 Lit = toLitCond( Cec_ObjSatNum(p,pObjR), Gia_IsComplement(pObj) ); if ( p->pPars->fPolarFlip ) { if ( pObjR->fPhase ) Lit = lit_neg( Lit ); } //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); clk = Abc_Clock(); nConflicts = p->pSat->stats.conflicts; clk2 = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); //ABC_PRT( "sat", Abc_Clock() - clk2 ); if ( RetValue == l_False ) { p->timeSatUnsat += Abc_Clock() - clk; Lit = lit_neg( Lit ); RetValue = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); assert( RetValue ); p->nSatUnsat++; p->nConfUnsat += p->pSat->stats.conflicts - nConflicts; //Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); return 1; } else if ( RetValue == l_True ) { p->timeSatSat += Abc_Clock() - clk; p->nSatSat++; p->nConfSat += p->pSat->stats.conflicts - nConflicts; //Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); return 0; } else // if ( RetValue == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatUndec++; p->nConfUndec += p->pSat->stats.conflicts - nConflicts; //Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); return -1; } } /**Function************************************************************* Synopsis [Runs equivalence test for the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ) { Gia_Obj_t * pObjR1 = Gia_Regular(pObj1); Gia_Obj_t * pObjR2 = Gia_Regular(pObj2); int nBTLimit = p->pPars->nBTLimit; int Lits[2], RetValue, status, nConflicts; abctime clk, clk2; if ( pObj1 == Gia_ManConst0(p->pAig) || pObj2 == Gia_ManConst0(p->pAig) || pObj1 == Gia_Not(pObj2) ) return 1; if ( pObj1 == Gia_ManConst1(p->pAig) && (pObj2 == NULL || pObj2 == Gia_ManConst1(p->pAig)) ) { assert( 0 ); return 0; } p->nCallsSince++; // experiment with this!!! p->nSatTotal++; // check if SAT solver needs recycling if ( p->pSat == NULL || (p->pPars->nSatVarMax && p->nSatVars > p->pPars->nSatVarMax && p->nCallsSince > p->pPars->nCallsRecycle) ) Cec_ManSatSolverRecycle( p ); // if the nodes do not have SAT variables, allocate them clk2 = Abc_Clock(); Cec_CnfNodeAddToSolver( p, pObjR1 ); Cec_CnfNodeAddToSolver( p, pObjR2 ); //ABC_PRT( "cnf", Abc_Clock() - clk2 ); //Abc_Print( 1, "%d \n", p->pSat->size ); clk2 = Abc_Clock(); // Cec_SetActivityFactors( p, pObjR1 ); // Cec_SetActivityFactors( p, pObjR2 ); //ABC_PRT( "act", Abc_Clock() - clk2 ); // propage unit clauses if ( p->pSat->qtail != p->pSat->qhead ) { status = sat_solver_simplify(p->pSat); assert( status != 0 ); assert( p->pSat->qtail == p->pSat->qhead ); } // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 Lits[0] = toLitCond( Cec_ObjSatNum(p,pObjR1), Gia_IsComplement(pObj1) ); Lits[1] = toLitCond( Cec_ObjSatNum(p,pObjR2), Gia_IsComplement(pObj2) ); if ( p->pPars->fPolarFlip ) { if ( pObjR1->fPhase ) Lits[0] = lit_neg( Lits[0] ); if ( pObjR2->fPhase ) Lits[1] = lit_neg( Lits[1] ); } //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); clk = Abc_Clock(); nConflicts = p->pSat->stats.conflicts; clk2 = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, Lits, Lits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); //ABC_PRT( "sat", Abc_Clock() - clk2 ); if ( RetValue == l_False ) { p->timeSatUnsat += Abc_Clock() - clk; Lits[0] = lit_neg( Lits[0] ); Lits[1] = lit_neg( Lits[1] ); RetValue = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); assert( RetValue ); p->nSatUnsat++; p->nConfUnsat += p->pSat->stats.conflicts - nConflicts; //Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); return 1; } else if ( RetValue == l_True ) { p->timeSatSat += Abc_Clock() - clk; p->nSatSat++; p->nConfSat += p->pSat->stats.conflicts - nConflicts; //Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); return 0; } else // if ( RetValue == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatUndec++; p->nConfUndec += p->pSat->stats.conflicts - nConflicts; //Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts ); return -1; } } /**Function************************************************************* Synopsis [Performs one round of solving for the POs of the AIG.] Description [Labels the nodes that have been proved (pObj->fMark1) and returns the set of satisfying assignments.] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Int_t * vIdsOrig, Vec_Int_t * vMiterPairs, Vec_Int_t * vEquivPairs ) { Bar_Progress_t * pProgress = NULL; Cec_ManSat_t * p; Gia_Obj_t * pObj; int i, status; abctime clk = Abc_Clock(), clk2; // reset the manager if ( pPat ) { pPat->iStart = Vec_StrSize(pPat->vStorage); pPat->nPats = 0; pPat->nPatLits = 0; pPat->nPatLitsMin = 0; } Gia_ManSetPhase( pAig ); Gia_ManLevelNum( pAig ); Gia_ManIncrementTravId( pAig ); p = Cec_ManSatCreate( pAig, pPars ); pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); Gia_ManForEachCo( pAig, pObj, i ) { if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) { pObj->fMark0 = 0; pObj->fMark1 = 1; continue; } Bar_ProgressUpdate( pProgress, i, "SAT..." ); clk2 = Abc_Clock(); status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); pObj->fMark0 = (status == 0); pObj->fMark1 = (status == 1); if ( status == 1 && vIdsOrig ) { int iObj1 = Vec_IntEntry(vMiterPairs, 2*i); int iObj2 = Vec_IntEntry(vMiterPairs, 2*i+1); int OrigId1 = Vec_IntEntry(vIdsOrig, iObj1); int OrigId2 = Vec_IntEntry(vIdsOrig, iObj2); assert( OrigId1 >= 0 && OrigId2 >= 0 ); Vec_IntPushTwo( vEquivPairs, OrigId1, OrigId2 ); } /* if ( status == -1 ) { Gia_Man_t * pTemp = Gia_ManDupDfsCone( pAig, pObj ); Gia_AigerWrite( pTemp, "gia_hard.aig", 0, 0 ); Gia_ManStop( pTemp ); Abc_Print( 1, "Dumping hard cone into file \"%s\".\n", "gia_hard.aig" ); } */ if ( status != 0 ) continue; // save the pattern if ( pPat ) { abctime clk3 = Abc_Clock(); Cec_ManPatSavePattern( pPat, p, pObj ); pPat->timeTotalSave += Abc_Clock() - clk3; } // quit if one of them is solved if ( pPars->fCheckMiter ) break; } p->timeTotal = Abc_Clock() - clk; Bar_ProgressStop( pProgress ); if ( pPars->fVerbose ) Cec_ManSatPrintStats( p ); Cec_ManSatStop( p ); } /**Function************************************************************* Synopsis [Performs one round of solving for the POs of the AIG.] Description [Labels the nodes that have been proved (pObj->fMark1) and returns the set of satisfying assignments.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSatSolveExractPattern( Vec_Int_t * vCexStore, int iStart, Vec_Int_t * vPat ) { int k, nSize; Vec_IntClear( vPat ); // skip the output number iStart++; // get the number of items nSize = Vec_IntEntry( vCexStore, iStart++ ); if ( nSize <= 0 ) return iStart; // extract pattern for ( k = 0; k < nSize; k++ ) Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) ); return iStart; } void Cec_ManSatSolveCSat( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars ) { Vec_Str_t * vStatus; Vec_Int_t * vPat = Vec_IntAlloc( 1000 ); Vec_Int_t * vCexStore = Cbs_ManSolveMiterNc( pAig, pPars->nBTLimit, &vStatus, 0 ); Gia_Obj_t * pObj; int i, status, iStart = 0; assert( Vec_StrSize(vStatus) == Gia_ManCoNum(pAig) ); // reset the manager if ( pPat ) { pPat->iStart = Vec_StrSize(pPat->vStorage); pPat->nPats = 0; pPat->nPatLits = 0; pPat->nPatLitsMin = 0; } Gia_ManForEachCo( pAig, pObj, i ) { status = (int)Vec_StrEntry(vStatus, i); pObj->fMark0 = (status == 0); pObj->fMark1 = (status == 1); if ( Vec_IntSize(vCexStore) > 0 && status != 1 ) iStart = Cec_ManSatSolveExractPattern( vCexStore, iStart, vPat ); if ( status != 0 ) continue; // save the pattern if ( pPat && Vec_IntSize(vPat) > 0 ) { abctime clk3 = Abc_Clock(); Cec_ManPatSavePatternCSat( pPat, vPat ); pPat->timeTotalSave += Abc_Clock() - clk3; } // quit if one of them is solved if ( pPars->fCheckMiter ) break; } assert( iStart == Vec_IntSize(vCexStore) ); Vec_IntFree( vPat ); Vec_StrFree( vStatus ); Vec_IntFree( vCexStore ); } /**Function************************************************************* Synopsis [Returns the pattern stored.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * pSat ) { return pSat->vCex; } /**Function************************************************************* Synopsis [Save values in the cone of influence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSatSolveSeq_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vInfo, int iPat, int nRegs ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { unsigned * pInfo = (unsigned *)Vec_PtrEntry( vInfo, nRegs + Gia_ObjCioId(pObj) ); if ( Cec_ObjSatVarValue( pSat, pObj ) != Abc_InfoHasBit( pInfo, iPat ) ) Abc_InfoXorBit( pInfo, iPat ); pSat->nCexLits++; // Vec_IntPush( pSat->vCex, Abc_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) ); return; } assert( Gia_ObjIsAnd(pObj) ); Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin0(pObj), vInfo, iPat, nRegs ); Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin1(pObj), vInfo, iPat, nRegs ); } /**Function************************************************************* Synopsis [Performs one round of solving for the POs of the AIG.] Description [Labels the nodes that have been proved (pObj->fMark1) and returns the set of satisfying assignments.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats ) { Bar_Progress_t * pProgress = NULL; Vec_Str_t * vStatus; Cec_ManSat_t * p; Gia_Obj_t * pObj; int iPat = 0, nPatsInit, nPats; int i, status; abctime clk = Abc_Clock(); nPatsInit = nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts); Gia_ManSetPhase( pAig ); Gia_ManLevelNum( pAig ); Gia_ManIncrementTravId( pAig ); p = Cec_ManSatCreate( pAig, pPars ); vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); Gia_ManForEachCo( pAig, pObj, i ) { Bar_ProgressUpdate( pProgress, i, "SAT..." ); if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) { if ( Gia_ObjFaninC0(pObj) ) { // Abc_Print( 1, "Constant 1 output of SRM!!!\n" ); Vec_StrPush( vStatus, 0 ); } else { // Abc_Print( 1, "Constant 0 output of SRM!!!\n" ); Vec_StrPush( vStatus, 1 ); } continue; } status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); //Abc_Print( 1, "output %d status = %d\n", i, status ); Vec_StrPush( vStatus, (char)status ); if ( status != 0 ) continue; // resize storage if ( iPat == nPats ) { int nWords = Vec_PtrReadWordsSimInfo(vPatts); Vec_PtrReallocSimInfo( vPatts ); Vec_PtrCleanSimInfo( vPatts, nWords, 2*nWords ); nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts); } if ( iPat % nPatsInit == 0 ) iPat++; // save the pattern Gia_ManIncrementTravId( pAig ); // Vec_IntClear( p->vCex ); Cec_ManSatSolveSeq_rec( p, pAig, Gia_ObjFanin0(pObj), vPatts, iPat++, nRegs ); // Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits ); // Cec_ManSatAddToStore( p->vCexStore, p->vCex ); // if ( iPat == nPats ) // break; // quit if one of them is solved // if ( pPars->fFirstStop ) // break; // if ( iPat == 32 * 15 * 16 - 1 ) // break; } p->timeTotal = Abc_Clock() - clk; Bar_ProgressStop( pProgress ); if ( pPars->fVerbose ) Cec_ManSatPrintStats( p ); // Abc_Print( 1, "Total number of cex literals = %d. (Ave = %d)\n", p->nCexLits, p->nCexLits/p->nSatSat ); Cec_ManSatStop( p ); if ( pnPats ) *pnPats = iPat-1; return vStatus; } /**Function************************************************************* Synopsis [Save values in the cone of influence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ) { int i, Entry; Vec_IntPush( vCexStore, Out ); if ( vCex == NULL ) // timeout { Vec_IntPush( vCexStore, -1 ); return; } // write the counter-example Vec_IntPush( vCexStore, Vec_IntSize(vCex) ); Vec_IntForEachEntry( vCex, Entry, i ) Vec_IntPush( vCexStore, Entry ); } /**Function************************************************************* Synopsis [Save values in the cone of influence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSatSolveMiter_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { pSat->nCexLits++; Vec_IntPush( pSat->vCex, Abc_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) ); return; } assert( Gia_ObjIsAnd(pObj) ); Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin0(pObj) ); Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Save patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 ) { Vec_IntClear( p->vCex ); Gia_ManIncrementTravId( p->pAig ); Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj1) ); if ( pObj2 ) Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj2) ); } /**Function************************************************************* Synopsis [Performs one round of solving for the POs of the AIG.] Description [Labels the nodes that have been proved (pObj->fMark1) and returns the set of satisfying assignments.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus ) { Bar_Progress_t * pProgress = NULL; Vec_Int_t * vCexStore; Vec_Str_t * vStatus; Cec_ManSat_t * p; Gia_Obj_t * pObj; int i, status; abctime clk = Abc_Clock(); // prepare AIG Gia_ManSetPhase( pAig ); Gia_ManLevelNum( pAig ); Gia_ManIncrementTravId( pAig ); // create resulting data-structures vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); vCexStore = Vec_IntAlloc( 10000 ); // perform solving p = Cec_ManSatCreate( pAig, pPars ); pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) ); Gia_ManForEachCo( pAig, pObj, i ) { Vec_IntClear( p->vCex ); Bar_ProgressUpdate( pProgress, i, "SAT..." ); if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) { if ( Gia_ObjFaninC0(pObj) ) { // Abc_Print( 1, "Constant 1 output of SRM!!!\n" ); Cec_ManSatAddToStore( vCexStore, p->vCex, i ); // trivial counter-example Vec_StrPush( vStatus, 0 ); } else { // Abc_Print( 1, "Constant 0 output of SRM!!!\n" ); Vec_StrPush( vStatus, 1 ); } continue; } status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) ); Vec_StrPush( vStatus, (char)status ); if ( status == -1 ) { Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout continue; } if ( status == 1 ) continue; assert( status == 0 ); // save the pattern // Gia_ManIncrementTravId( pAig ); // Cec_ManSatSolveMiter_rec( p, pAig, Gia_ObjFanin0(pObj) ); Cec_ManSavePattern( p, Gia_ObjFanin0(pObj), NULL ); // Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits ); Cec_ManSatAddToStore( vCexStore, p->vCex, i ); } p->timeTotal = Abc_Clock() - clk; Bar_ProgressStop( pProgress ); // if ( pPars->fVerbose ) // Cec_ManSatPrintStats( p ); Cec_ManSatStop( p ); *pvStatus = vStatus; return vCexStore; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecSplit.c000066400000000000000000000700131300674244400236260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecSplit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Cofactoring for combinational miters.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecSplit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "aig/gia/gia.h" #include "aig/gia/giaAig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" #include "misc/util/utilTruth.h" //#include "bdd/cudd/cuddInt.h" #ifdef ABC_USE_PTHREADS #ifdef _WIN32 #include "../lib/pthread.h" #else #include #include #endif #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifndef ABC_USE_PTHREADS int Cec_GiaSplitTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose, int fSilent ) { return -1; } #else // pthreads are used //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #if 0 // BDD code /**Function************************************************************* Synopsis [Permute primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Gia_ManBuildBdd( Gia_Man_t * p, Vec_Ptr_t ** pvNodes, int nSkip ) { abctime clk = Abc_Clock(); DdManager * dd; DdNode * bBdd, * bBdd0, * bBdd1; Vec_Ptr_t * vNodes; Gia_Obj_t * pObj; int i; vNodes = Vec_PtrStart( Gia_ManObjNum(p) ); dd = Cudd_Init( Gia_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); bBdd = Cudd_ReadLogicZero(dd); Cudd_Ref( bBdd ); Vec_PtrWriteEntry( vNodes, 0, bBdd ); Gia_ManForEachPi( p, pObj, i ) { bBdd = i > nSkip ? Cudd_bddIthVar(dd, i) : Cudd_ReadLogicZero(dd); Cudd_Ref( bBdd ); Vec_PtrWriteEntry( vNodes, Gia_ObjId(p, pObj), bBdd ); } Gia_ManForEachAnd( p, pObj, i ) { bBdd0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vNodes, Gia_ObjFaninId0(pObj, i)), Gia_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vNodes, Gia_ObjFaninId1(pObj, i)), Gia_ObjFaninC1(pObj) ); bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); Vec_PtrWriteEntry( vNodes, Gia_ObjId(p, pObj), bBdd ); if ( i % 10 == 0 ) printf( "%d ", i ); // if ( i == 3000 ) // break; } printf( "\n" ); Gia_ManForEachPo( p, pObj, i ) { bBdd = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vNodes, Gia_ObjFaninId0(pObj, Gia_ObjId(p, pObj))), Gia_ObjFaninC0(pObj) ); Cudd_Ref( bBdd ); Vec_PtrWriteEntry( vNodes, Gia_ObjId(p, pObj), bBdd ); } if ( bBdd == Cudd_ReadLogicZero(dd) ) printf( "Equivalent!\n" ); else printf( "Not tquivalent!\n" ); if ( pvNodes ) *pvNodes = vNodes; Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return dd; } void Gia_ManDerefBdd( DdManager * dd, Vec_Ptr_t * vNodes ) { DdNode * bBdd; int i; Vec_PtrForEachEntry( DdNode *, vNodes, bBdd, i ) if ( bBdd ) Cudd_RecursiveDeref( dd, bBdd ); if ( Cudd_CheckZeroRef(dd) > 0 ) printf( "The number of referenced nodes = %d\n", Cudd_CheckZeroRef(dd) ); Cudd_PrintInfo( dd, stdout ); Cudd_Quit( dd ); } void Gia_ManBuildBddTest( Gia_Man_t * p ) { Vec_Ptr_t * vNodes; DdManager * dd = Gia_ManBuildBdd( p, &vNodes, 50 ); Gia_ManDerefBdd( dd, vNodes ); } #endif // BDD code /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_GiaSplitExplore( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pFan0, * pFan1; int i, Counter = 0; assert( p->pMuxes == NULL ); ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) continue; if ( Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) > 1 && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) > 1 ) continue; printf( "%5d : ", Counter++ ); printf( "%2d %2d ", Gia_ObjRefNum(p, Gia_Regular(pFan0)), Gia_ObjRefNum(p, Gia_Regular(pFan1)) ); printf( "%2d %2d \n", Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)), Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) ); } } /**Function************************************************************* Synopsis [Find cofactoring variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_PermuteSpecialOrder( Gia_Man_t * p ) { Vec_Int_t * vPerm; Gia_Obj_t * pObj; int i, * pOrder; Gia_ManCreateRefs( p ); vPerm = Vec_IntAlloc( Gia_ManPiNum(p) ); Gia_ManForEachPi( p, pObj, i ) Vec_IntPush( vPerm, Gia_ObjRefNum(p, pObj) ); pOrder = Abc_QuickSortCost( Vec_IntArray(vPerm), Vec_IntSize(vPerm), 1 ); Vec_IntFree( vPerm ); return pOrder; } Gia_Man_t * Gia_PermuteSpecial( Gia_Man_t * p ) { Gia_Man_t * pNew; Vec_Int_t * vPerm; int * pOrder = Gia_PermuteSpecialOrder( p ); vPerm = Vec_IntAllocArray( pOrder, Gia_ManPiNum(p) ); pNew = Gia_ManDupPerm( p, vPerm ); Vec_IntFree( vPerm ); return pNew; } /**Function************************************************************* Synopsis [Find cofactoring variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SplitCofVar2( Gia_Man_t * p, int * pnFanouts, int * pnCost ) { Gia_Obj_t * pObj; int i, iBest = -1, CostBest = -1; if ( p->pRefs == NULL ) Gia_ManCreateRefs( p ); Gia_ManForEachPi( p, pObj, i ) if ( CostBest < Gia_ObjRefNum(p, pObj) ) iBest = i, CostBest = Gia_ObjRefNum(p, pObj); assert( iBest >= 0 ); *pnFanouts = Gia_ObjRefNum(p, Gia_ManPi(p, iBest)); *pnCost = -1; return iBest; } int Gia_SplitCofVar( Gia_Man_t * p, int LookAhead, int * pnFanouts, int * pnCost ) { Gia_Man_t * pPart; int Cost0, Cost1, CostBest = ABC_INFINITY; int * pOrder, i, iBest = -1; if ( LookAhead == 1 ) return Gia_SplitCofVar2( p, pnFanouts, pnCost ); pOrder = Gia_PermuteSpecialOrder( p ); LookAhead = Abc_MinInt( LookAhead, Gia_ManPiNum(p) ); for ( i = 0; i < LookAhead; i++ ) { pPart = Gia_ManDupCofactorVar( p, pOrder[i], 0 ); Cost0 = Gia_ManAndNum(pPart); Gia_ManStop( pPart ); pPart = Gia_ManDupCofactorVar( p, pOrder[i], 1 ); Cost1 = Gia_ManAndNum(pPart); Gia_ManStop( pPart ); if ( CostBest > Cost0 + Cost1 ) CostBest = Cost0 + Cost1, iBest = pOrder[i]; /* pPart = Gia_ManDupExist( p, pOrder[i] ); printf( "%2d : Var = %4d Refs = %3d %6d %6d -> %6d %6d -> %6d\n", i, pOrder[i], Gia_ObjRefNum(p, Gia_ManPi(p, pOrder[i])), Cost0, Cost1, Cost0+Cost1, Gia_ManAndNum(p), Gia_ManAndNum(pPart) ); Gia_ManStop( pPart ); printf( "%2d : Var = %4d Refs = %3d %6d %6d -> %6d\n", i, pOrder[i], Gia_ObjRefNum(p, Gia_ManPi(p, pOrder[i])), Cost0, Cost1, Cost0+Cost1 ); */ } ABC_FREE( pOrder ); assert( iBest >= 0 ); *pnFanouts = Gia_ObjRefNum(p, Gia_ManPi(p, iBest)); *pnCost = CostBest; return iBest; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Cec_SplitDeriveModel( Gia_Man_t * p, Cnf_Dat_t * pCnf, sat_solver * pSat ) { Abc_Cex_t * pCex; Gia_Obj_t * pObj; int i, iLit, * pModel; pModel = ABC_CALLOC( int, Gia_ManPiNum(p) ); Gia_ManForEachPi( p, pObj, i ) pModel[i] = sat_solver_var_value(pSat, pCnf->pVarNums[Gia_ObjId(p, pObj)]); if ( p->vCofVars ) Vec_IntForEachEntry( p->vCofVars, iLit, i ) pModel[Abc_Lit2Var(iLit)] = !Abc_LitIsCompl(iLit); pCex = Abc_CexCreate( 0, Gia_ManPiNum(p), pModel, 0, 0, 0 ); ABC_FREE( pModel ); return pCex; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cnf_Dat_t * Cec_GiaDeriveGiaRemapped( Gia_Man_t * p ) { Cnf_Dat_t * pCnf; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); pAig->nRegs = 0; pCnf = Cnf_Derive( pAig, 0 );//Aig_ManCoNum(pAig) ); Aig_ManStop( pAig ); return pCnf; } static inline sat_solver * Cec_GiaDeriveSolver( Gia_Man_t * p, Cnf_Dat_t * pCnf, int nTimeOut ) { sat_solver * pSat; int i; pSat = sat_solver_new(); 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] ) ) { // the problem is UNSAT sat_solver_delete( pSat ); return NULL; } sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); return pSat; } static inline int Cnf_GiaSolveOne( Gia_Man_t * p, Cnf_Dat_t * pCnf, int nTimeOut, int * pnVars, int * pnConfs ) { int status; sat_solver * pSat = Cec_GiaDeriveSolver( p, pCnf, nTimeOut ); if ( pSat == NULL ) { *pnVars = 0; *pnConfs = 0; return 1; } status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); *pnVars = sat_solver_nvars( pSat ); *pnConfs = sat_solver_nconflicts( pSat ); if ( status == l_True ) p->pCexComb = Cec_SplitDeriveModel( p, pCnf, pSat ); sat_solver_delete( pSat ); if ( status == l_Undef ) return -1; if ( status == l_False ) return 1; return 0; } static inline void Cec_GiaSplitClean( Vec_Ptr_t * vStack ) { Gia_Man_t * pNew; int i; Vec_PtrForEachEntry( Gia_Man_t *, vStack, pNew, i ) Gia_ManStop( pNew ); Vec_PtrFree( vStack ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_GiaSplitPrint( int nIter, int Depth, int nVars, int nConfs, int fStatus, double Prog, abctime clk ) { printf( "%4d : ", nIter ); printf( "Depth =%3d ", Depth ); printf( "SatVar =%7d ", nVars ); printf( "SatConf =%7d ", nConfs ); printf( "%s ", fStatus ? (fStatus == 1 ? "UNSAT " : "UNDECIDED") : "SAT " ); printf( "Solved %8.4f %% ", 100*Prog ); Abc_PrintTime( 1, "Time", clk ); //ABC_PRTr( "Time", Abc_Clock()-clk ); fflush( stdout ); } void Cec_GiaSplitPrintRefs( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; if ( p->pRefs == NULL ) Gia_ManCreateRefs( p ); Gia_ManForEachPi( p, pObj, i ) printf( "%d ", Gia_ObjRefNum(p, pObj) ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_GiaSplitTest2( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose, int fSilent ) { abctime clkTotal = Abc_Clock(); Vec_Ptr_t * vStack; Cnf_Dat_t * pCnf; int nSatVars, nSatConfs; int nIter, status, RetValue = -1; double Progress = 0; // check the problem pCnf = Cec_GiaDeriveGiaRemapped( p ); status = Cnf_GiaSolveOne( p, pCnf, nTimeOut, &nSatVars, &nSatConfs ); Cnf_DataFree( pCnf ); if ( fVerbose ) Cec_GiaSplitPrint( 0, 0, nSatVars, nSatConfs, status, Progress, Abc_Clock() - clkTotal ); if ( status == 0 ) { if ( !fSilent ) printf( "The problem is SAT without cofactoring.\n" ); return 0; } if ( status == 1 ) { if ( !fSilent ) printf( "The problem is UNSAT without cofactoring.\n" ); return 1; } assert( status == -1 ); // create local copy vStack = Vec_PtrAlloc( 1000 ); Vec_PtrPush( vStack, Gia_ManDup(p) ); // start with the current problem for ( nIter = 1; Vec_PtrSize(vStack) > 0; nIter++ ) { // get the last AIG Gia_Man_t * pLast = (Gia_Man_t *)Vec_PtrPop( vStack ); // determine cofactoring variable int Depth = 1 + (pLast->vCofVars ? Vec_IntSize(pLast->vCofVars) : 0); int nFanouts, Cost, iVar = Gia_SplitCofVar( pLast, LookAhead, &nFanouts, &Cost ); // cofactor Gia_Man_t * pPart = Gia_ManDupCofactorVar( pLast, iVar, 0 ); if ( pLast->vCofVars == NULL ) pLast->vCofVars = Vec_IntAlloc( 100 ); // print results if ( fVeryVerbose ) { // Cec_GiaSplitPrintRefs( pLast ); printf( "Var = %5d. Fanouts = %5d. Cost = %8d. AndBefore = %6d. AndAfter = %6d.\n", iVar, nFanouts, Cost, Gia_ManAndNum(pLast), Gia_ManAndNum(pPart) ); // Cec_GiaSplitPrintRefs( pPart ); } // create variable pPart->vCofVars = Vec_IntAlloc( Vec_IntSize(pLast->vCofVars) + 1 ); Vec_IntAppend( pPart->vCofVars, pLast->vCofVars ); Vec_IntPush( pPart->vCofVars, Abc_Var2Lit(iVar, 1) ); // solve the problem pCnf = Cec_GiaDeriveGiaRemapped( pPart ); status = Cnf_GiaSolveOne( pPart, pCnf, nTimeOut, &nSatVars, &nSatConfs ); Cnf_DataFree( pCnf ); if ( status == 1 ) Progress += 1.0 / pow(2, Depth); if ( fVerbose ) Cec_GiaSplitPrint( nIter, Depth, nSatVars, nSatConfs, status, Progress, Abc_Clock() - clkTotal ); if ( status == 0 ) // SAT { p->pCexComb = pPart->pCexComb; pPart->pCexComb = NULL; Gia_ManStop( pLast ); Gia_ManStop( pPart ); RetValue = 0; break; } if ( status == 1 ) // UNSAT Gia_ManStop( pPart ); else // UNDEC Vec_PtrPush( vStack, pPart ); // cofactor pPart = Gia_ManDupCofactorVar( pLast, iVar, 1 ); // create variable pPart->vCofVars = Vec_IntAlloc( Vec_IntSize(pLast->vCofVars) + 1 ); Vec_IntAppend( pPart->vCofVars, pLast->vCofVars ); Vec_IntPush( pPart->vCofVars, Abc_Var2Lit(iVar, 0) ); Gia_ManStop( pLast ); // solve the problem pCnf = Cec_GiaDeriveGiaRemapped( pPart ); status = Cnf_GiaSolveOne( pPart, pCnf, nTimeOut, &nSatVars, &nSatConfs ); Cnf_DataFree( pCnf ); if ( status == 1 ) Progress += 1.0 / pow(2, Depth); if ( fVerbose ) Cec_GiaSplitPrint( nIter, Depth, nSatVars, nSatConfs, status, Progress, Abc_Clock() - clkTotal ); if ( status == 0 ) // SAT { p->pCexComb = pPart->pCexComb; pPart->pCexComb = NULL; Gia_ManStop( pPart ); RetValue = 0; break; } if ( status == 1 ) // UNSAT Gia_ManStop( pPart ); else // UNDEC Vec_PtrPush( vStack, pPart ); if ( nIterMax && nIter >= nIterMax ) break; } if ( Vec_PtrSize(vStack) == 0 ) RetValue = 1; // finish Cec_GiaSplitClean( vStack ); if ( !fSilent ) { if ( RetValue == 0 ) printf( "Problem is SAT " ); else if ( RetValue == 1 ) printf( "Problem is UNSAT " ); else if ( RetValue == -1 ) printf( "Problem is UNDECIDED " ); else assert( 0 ); printf( "after %d case-splits. ", nIter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); fflush( stdout ); } return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define PAR_THR_MAX 100 typedef struct Par_ThData_t_ { Gia_Man_t * p; Cnf_Dat_t * pCnf; int iThread; int nTimeOut; int fWorking; int Result; int nVars; int nConfs; } Par_ThData_t; void * Cec_GiaSplitWorkerThread( void * pArg ) { Par_ThData_t * pThData = (Par_ThData_t *)pArg; volatile int * pPlace = &pThData->fWorking; while ( 1 ) { while ( *pPlace == 0 ); assert( pThData->fWorking ); if ( pThData->p == NULL ) { pthread_exit( NULL ); assert( 0 ); return NULL; } pThData->Result = Cnf_GiaSolveOne( pThData->p, pThData->pCnf, pThData->nTimeOut, &pThData->nVars, &pThData->nConfs ); pThData->fWorking = 0; } assert( 0 ); return NULL; } int Cec_GiaSplitTestInt( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose, int fSilent ) { abctime clkTotal = Abc_Clock(); Par_ThData_t ThData[PAR_THR_MAX]; pthread_t WorkerThread[PAR_THR_MAX]; Vec_Ptr_t * vStack; Cnf_Dat_t * pCnf; double Progress = 0; int i, status, nSatVars, nSatConfs; int nIter = 0, RetValue = -1, fWorkToDo = 1; Abc_CexFreeP( &p->pCexComb ); if ( fVerbose ) printf( "Solving CEC problem by cofactoring with the following parameters:\n" ); if ( fVerbose ) printf( "Processes = %d TimeOut = %d sec MaxIter = %d LookAhead = %d Verbose = %d.\n", nProcs, nTimeOut, nIterMax, LookAhead, fVerbose ); fflush( stdout ); if ( nProcs == 1 ) return Cec_GiaSplitTest2( p, nProcs, nTimeOut, nIterMax, LookAhead, fVerbose, fVeryVerbose, fSilent ); // subtract manager thread nProcs--; assert( nProcs >= 1 && nProcs <= PAR_THR_MAX ); // check the problem pCnf = Cec_GiaDeriveGiaRemapped( p ); status = Cnf_GiaSolveOne( p, pCnf, nTimeOut, &nSatVars, &nSatConfs ); Cnf_DataFree( pCnf ); if ( fVerbose && status != -1 ) Cec_GiaSplitPrint( 0, 0, nSatVars, nSatConfs, status, Progress, Abc_Clock() - clkTotal ); if ( status == 0 ) { if ( !fSilent ) printf( "The problem is SAT without cofactoring.\n" ); return 0; } if ( status == 1 ) { if ( !fSilent ) printf( "The problem is UNSAT without cofactoring.\n" ); return 1; } assert( status == -1 ); // create local copy vStack = Vec_PtrAlloc( 1000 ); Vec_PtrPush( vStack, Gia_ManDup(p) ); // start threads for ( i = 0; i < nProcs; i++ ) { ThData[i].p = NULL; ThData[i].pCnf = NULL; ThData[i].iThread = i; ThData[i].nTimeOut = nTimeOut; ThData[i].fWorking = 0; ThData[i].Result = -1; ThData[i].nVars = -1; ThData[i].nConfs = -1; status = pthread_create( WorkerThread + i, NULL,Cec_GiaSplitWorkerThread, (void *)(ThData + i) ); assert( status == 0 ); } // look at the threads while ( fWorkToDo ) { fWorkToDo = (int)(Vec_PtrSize(vStack) > 0); for ( i = 0; i < nProcs; i++ ) { // check if this thread is working if ( ThData[i].fWorking ) { fWorkToDo = 1; continue; } // check if this thread has recently finished if ( ThData[i].p != NULL ) { Gia_Man_t * pLast = ThData[i].p; int Depth = pLast->vCofVars ? Vec_IntSize(pLast->vCofVars) : 0; if ( pLast->vCofVars == NULL ) pLast->vCofVars = Vec_IntAlloc( 100 ); if ( fVerbose ) Cec_GiaSplitPrint( i+1, Depth, ThData[i].nVars, ThData[i].nConfs, ThData[i].Result, Progress, Abc_Clock() - clkTotal ); if ( ThData[i].Result == 0 ) // SAT { p->pCexComb = pLast->pCexComb; pLast->pCexComb = NULL; RetValue = 0; goto finish; } if ( ThData[i].Result == -1 ) // UNDEC { // determine cofactoring variable int nFanouts, Cost, iVar = Gia_SplitCofVar( pLast, LookAhead, &nFanouts, &Cost ); // cofactor Gia_Man_t * pPart = Gia_ManDupCofactorVar( pLast, iVar, 0 ); pPart->vCofVars = Vec_IntAlloc( Vec_IntSize(pLast->vCofVars) + 1 ); Vec_IntAppend( pPart->vCofVars, pLast->vCofVars ); Vec_IntPush( pPart->vCofVars, Abc_Var2Lit(iVar, 1) ); Vec_PtrPush( vStack, pPart ); // print results if ( fVeryVerbose ) { // Cec_GiaSplitPrintRefs( pLast ); printf( "Var = %5d. Fanouts = %5d. Cost = %8d. AndBefore = %6d. AndAfter = %6d.\n", iVar, nFanouts, Cost, Gia_ManAndNum(pLast), Gia_ManAndNum(pPart) ); // Cec_GiaSplitPrintRefs( pPart ); } // cofactor pPart = Gia_ManDupCofactorVar( pLast, iVar, 1 ); pPart->vCofVars = Vec_IntAlloc( Vec_IntSize(pLast->vCofVars) + 1 ); Vec_IntAppend( pPart->vCofVars, pLast->vCofVars ); Vec_IntPush( pPart->vCofVars, Abc_Var2Lit(iVar, 1) ); Vec_PtrPush( vStack, pPart ); // keep working fWorkToDo = 1; nIter++; } else Progress += 1.0 / pow(2, Depth); Gia_ManStopP( &ThData[i].p ); if ( ThData[i].pCnf == NULL ) continue; Cnf_DataFree( ThData[i].pCnf ); ThData[i].pCnf = NULL; } if ( Vec_PtrSize(vStack) == 0 ) continue; // start a new thread assert( ThData[i].p == NULL ); ThData[i].p = (Gia_Man_t*)Vec_PtrPop( vStack ); ThData[i].pCnf = Cec_GiaDeriveGiaRemapped( ThData[i].p ); ThData[i].fWorking = 1; } if ( nIterMax && nIter >= nIterMax ) break; } if ( !fWorkToDo ) RetValue = 1; finish: // wait till threads finish for ( i = 0; i < nProcs; i++ ) if ( ThData[i].fWorking ) i = 0; // stop threads for ( i = 0; i < nProcs; i++ ) { assert( !ThData[i].fWorking ); // cleanup Gia_ManStopP( &ThData[i].p ); if ( ThData[i].pCnf == NULL ) continue; Cnf_DataFree( ThData[i].pCnf ); ThData[i].pCnf = NULL; // stop ThData[i].p = NULL; ThData[i].fWorking = 1; } // finish Cec_GiaSplitClean( vStack ); if ( !fSilent ) { if ( RetValue == 0 ) printf( "Problem is SAT " ); else if ( RetValue == 1 ) printf( "Problem is UNSAT " ); else if ( RetValue == -1 ) printf( "Problem is UNDECIDED " ); else assert( 0 ); printf( "after %d case-splits. ", nIter ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); fflush( stdout ); } return RetValue; } int Cec_GiaSplitTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nIterMax, int LookAhead, int fVerbose, int fVeryVerbose, int fSilent ) { Abc_Cex_t * pCex = NULL; Gia_Man_t * pOne; Gia_Obj_t * pObj; int i, RetValue1, fOneUndef = 0, RetValue = -1; Abc_CexFreeP( &p->pCexComb ); Gia_ManForEachPo( p, pObj, i ) { pOne = Gia_ManDupOutputGroup( p, i, i+1 ); if ( fVerbose ) printf( "\nSolving output %d:\n", i ); RetValue1 = Cec_GiaSplitTestInt( pOne, nProcs, nTimeOut, nIterMax, LookAhead, fVerbose, fVeryVerbose, fSilent ); Gia_ManStop( pOne ); // collect the result if ( RetValue1 == 0 && RetValue == -1 ) { pCex = pOne->pCexComb; pOne->pCexComb = NULL; pCex->iPo = i; RetValue = 0; } if ( RetValue1 == -1 ) fOneUndef = 1; } if ( RetValue == -1 ) RetValue = fOneUndef ? -1 : 1; else p->pCexComb = pCex; return RetValue; } /**Function************************************************************* Synopsis [Print stats about cofactoring variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_GiaPrintCofStats( Gia_Man_t * p ) { Gia_Man_t * pCof0, * pCof1; Gia_Obj_t * pObj, * pFan0, * pFan1, * pCtrl; Vec_Int_t * vMarks; int i, Count = 0; vMarks = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjIsMuxType(pObj) ) continue; if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) continue; pCtrl = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); pCtrl = Gia_Regular(pCtrl); Vec_IntAddToEntry( vMarks, Gia_ObjId(p, pCtrl), 1 ); } printf( "The AIG with %d candidate nodes (PI+AND) has %d unique MUX control drivers:\n", Gia_ManCandNum(p), Vec_IntCountPositive(vMarks) ); Gia_ManLevelNum( p ); Gia_ManForEachCand( p, pObj, i ) { if ( !Vec_IntEntry(vMarks, i) ) continue; pCof0 = Gia_ManDupCofactorObj( p, i, 0 ); pCof1 = Gia_ManDupCofactorObj( p, i, 1 ); printf( "%6d : ", Count++ ); printf( "Obj = %6d ", i ); printf( "MUX refs = %5d ", Vec_IntEntry(vMarks, i) ); printf( "Level = %5d ", Gia_ObjLevelId(p, i) ); printf( "Cof0 = %7d ", Gia_ManAndNum(pCof0) ); printf( "Cof1 = %7d ", Gia_ManAndNum(pCof1) ); printf( "\n" ); Gia_ManStop( pCof0 ); Gia_ManStop( pCof1 ); } Vec_IntFree( vMarks ); } void Cec_GiaPrintCofStats2( Gia_Man_t * p ) { Gia_Man_t * pCof0, * pCof1; Gia_Obj_t * pObj; int i; Gia_ManLevelNum( p ); Gia_ManCreateRefs( p ); Gia_ManForEachPi( p, pObj, i ) { pCof0 = Gia_ManDupCofactorVar( p, i, 0 ); pCof1 = Gia_ManDupCofactorVar( p, i, 1 ); printf( "PI %5d : ", i ); printf( "Refs = %5d ", Gia_ObjRefNum(p, pObj) ); printf( "Cof0 = %7d ", Gia_ManAndNum(pCof0) ); printf( "Cof1 = %7d ", Gia_ManAndNum(pCof1) ); printf( "\n" ); Gia_ManStop( pCof0 ); Gia_ManStop( pCof1 ); } } #endif // pthreads are used //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecSweep.c000066400000000000000000000242551300674244400236250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecSweep.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [SAT sweeping manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs limited speculative reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pRepr = NULL; int iRes0, iRes1, iRepr, iNode, iMiter; int i, fCompl, * piCopies, * pDepths; Gia_ManSetPhase( p->pAig ); Vec_IntClear( p->vXorNodes ); if ( p->pPars->nLevelMax ) Gia_ManLevelNum( p->pAig ); pNew = Gia_ManStart( Gia_ManObjNum(p->pAig) ); pNew->pName = Abc_UtilStrsav( p->pAig->pName ); pNew->pSpec = Abc_UtilStrsav( p->pAig->pName ); Gia_ManHashAlloc( pNew ); piCopies = ABC_FALLOC( int, Gia_ManObjNum(p->pAig) ); pDepths = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) ); piCopies[0] = 0; Gia_ManForEachObj1( p->pAig, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { piCopies[i] = Gia_ManAppendCi( pNew ); continue; } if ( Gia_ObjIsCo(pObj) ) continue; if ( piCopies[Gia_ObjFaninId0(pObj,i)] == -1 || piCopies[Gia_ObjFaninId1(pObj,i)] == -1 ) continue; iRes0 = Abc_LitNotCond( piCopies[Gia_ObjFaninId0(pObj,i)], Gia_ObjFaninC0(pObj) ); iRes1 = Abc_LitNotCond( piCopies[Gia_ObjFaninId1(pObj,i)], Gia_ObjFaninC1(pObj) ); iNode = piCopies[i] = Gia_ManHashAnd( pNew, iRes0, iRes1 ); pDepths[i] = Abc_MaxInt( pDepths[Gia_ObjFaninId0(pObj,i)], pDepths[Gia_ObjFaninId1(pObj,i)] ); if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID || Gia_ObjFailed(p->pAig, i) ) continue; assert( Gia_ObjRepr(p->pAig, i) < i ); iRepr = piCopies[Gia_ObjRepr(p->pAig, i)]; if ( iRepr == -1 ) continue; if ( Abc_LitRegular(iNode) == Abc_LitRegular(iRepr) ) continue; if ( p->pPars->nLevelMax && (Gia_ObjLevelId(p->pAig, i) > p->pPars->nLevelMax || Gia_ObjLevelId(p->pAig, Abc_Lit2Var(iRepr)) > p->pPars->nLevelMax) ) continue; if ( p->pPars->fDualOut ) { // if ( i % 1000 == 0 && Gia_ObjRepr(p->pAig, i) ) // Gia_ManEquivPrintOne( p->pAig, Gia_ObjRepr(p->pAig, i), 0 ); if ( p->pPars->fColorDiff ) { if ( !Gia_ObjDiffColors( p->pAig, Gia_ObjRepr(p->pAig, i), i ) ) continue; } else { if ( !Gia_ObjDiffColors2( p->pAig, Gia_ObjRepr(p->pAig, i), i ) ) continue; } } pRepr = Gia_ManObj( p->pAig, Gia_ObjRepr(p->pAig, i) ); fCompl = Gia_ObjPhaseReal(pObj) ^ Gia_ObjPhaseReal(pRepr); piCopies[i] = Abc_LitNotCond( iRepr, fCompl ); if ( Gia_ObjProved(p->pAig, i) ) continue; // produce speculative miter iMiter = Gia_ManHashXor( pNew, iNode, piCopies[i] ); Gia_ManAppendCo( pNew, iMiter ); Vec_IntPush( p->vXorNodes, Gia_ObjRepr(p->pAig, i) ); Vec_IntPush( p->vXorNodes, i ); // add to the depth of this node pDepths[i] = 1 + Abc_MaxInt( pDepths[i], pDepths[Gia_ObjRepr(p->pAig, i)] ); if ( p->pPars->nDepthMax && pDepths[i] >= p->pPars->nDepthMax ) piCopies[i] = -1; } ABC_FREE( piCopies ); ABC_FREE( pDepths ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, 0 ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManFraClassesUpdate_rec( Gia_Obj_t * pObj ) { int Result; if ( pObj->fMark0 ) return 1; if ( Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj) ) return 0; Result = (Cec_ManFraClassesUpdate_rec( Gia_ObjFanin0(pObj) ) | Cec_ManFraClassesUpdate_rec( Gia_ObjFanin1(pObj) )); return pObj->fMark0 = Result; } /**Function************************************************************* Synopsis [Creates simulation info for this round.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManFraCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vCiInfo, Vec_Ptr_t * vInfo, int nSeries ) { unsigned * pRes0, * pRes1; int i, w; for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ ) { pRes0 = (unsigned *)Vec_PtrEntry( vCiInfo, i ); pRes1 = (unsigned *)Vec_PtrEntry( vInfo, i ); pRes1 += p->nWords * nSeries; for ( w = 0; w < p->nWords; w++ ) pRes0[w] = pRes1[w]; } } /**Function************************************************************* Synopsis [Updates equivalence classes using the patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew ) { Vec_Ptr_t * vInfo; Gia_Obj_t * pObj, * pObjOld, * pReprOld; int i, k, iRepr, iNode; abctime clk; clk = Abc_Clock(); vInfo = Cec_ManPatCollectPatterns( pPat, Gia_ManCiNum(p->pAig), pSim->nWords ); p->timePat += Abc_Clock() - clk; clk = Abc_Clock(); if ( vInfo != NULL ) { Gia_ManCreateValueRefs( p->pAig ); for ( i = 0; i < pPat->nSeries; i++ ) { Cec_ManFraCreateInfo( pSim, pSim->vCiSimInfo, vInfo, i ); if ( Cec_ManSimSimulateRound( pSim, pSim->vCiSimInfo, pSim->vCoSimInfo ) ) { Vec_PtrFree( vInfo ); return 1; } } Vec_PtrFree( vInfo ); } p->timeSim += Abc_Clock() - clk; assert( Vec_IntSize(p->vXorNodes) == 2*Gia_ManCoNum(pNew) ); // mark the transitive fanout of failed nodes if ( p->pPars->nDepthMax != 1 ) { Gia_ManCleanMark0( p->pAig ); Gia_ManCleanMark1( p->pAig ); Gia_ManForEachCo( pNew, pObj, k ) { iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved continue; // Gia_ManObj(p->pAig, iRepr)->fMark0 = 1; Gia_ManObj(p->pAig, iNode)->fMark0 = 1; } // mark the nodes reachable through the failed nodes Gia_ManForEachAnd( p->pAig, pObjOld, k ) pObjOld->fMark0 |= (Gia_ObjFanin0(pObjOld)->fMark0 | Gia_ObjFanin1(pObjOld)->fMark0); // unmark the disproved nodes Gia_ManForEachCo( pNew, pObj, k ) { iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved continue; pObjOld = Gia_ManObj(p->pAig, iNode); assert( pObjOld->fMark0 == 1 ); if ( Gia_ObjFanin0(pObjOld)->fMark0 == 0 && Gia_ObjFanin1(pObjOld)->fMark0 == 0 ) pObjOld->fMark1 = 1; } // clean marks Gia_ManForEachAnd( p->pAig, pObjOld, k ) if ( pObjOld->fMark1 ) { pObjOld->fMark0 = 0; pObjOld->fMark1 = 0; } } // set the results p->nAllProved = p->nAllDisproved = p->nAllFailed = 0; Gia_ManForEachCo( pNew, pObj, k ) { iRepr = Vec_IntEntry( p->vXorNodes, 2*k ); iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 ); pReprOld = Gia_ManObj(p->pAig, iRepr); pObjOld = Gia_ManObj(p->pAig, iNode); if ( pObj->fMark1 ) { // proved assert( pObj->fMark0 == 0 ); assert( !Gia_ObjProved(p->pAig, iNode) ); if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 ) // if ( pObjOld->fMark0 == 0 ) { assert( iRepr == Gia_ObjRepr(p->pAig, iNode) ); Gia_ObjSetProved( p->pAig, iNode ); p->nAllProved++; } } else if ( pObj->fMark0 ) { // disproved assert( pObj->fMark1 == 0 ); if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 ) // if ( pObjOld->fMark0 == 0 ) { if ( iRepr == Gia_ObjRepr(p->pAig, iNode) ) Abc_Print( 1, "Cec_ManFraClassesUpdate(): Error! Node is not refined!\n" ); p->nAllDisproved++; } } else { // failed assert( pObj->fMark0 == 0 ); assert( pObj->fMark1 == 0 ); assert( !Gia_ObjFailed(p->pAig, iNode) ); assert( !Gia_ObjProved(p->pAig, iNode) ); Gia_ObjSetFailed( p->pAig, iNode ); p->nAllFailed++; } } return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/cecSynth.c000066400000000000000000000304511300674244400236420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cecSynth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Partitioned sequential synthesis.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecSynth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Populate sequential synthesis parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * p ) { memset( p, 0, sizeof(Cec_ParSeq_t) ); p->fUseLcorr = 0; // enables latch correspondence p->fUseScorr = 0; // enables signal correspondence p->nBTLimit = 1000; // (scorr/lcorr) conflict limit at a node p->nFrames = 1; // (scorr only) the number of timeframes p->nLevelMax = -1; // (scorr only) the max number of levels p->fConsts = 1; // (scl only) merging constants p->fEquivs = 1; // (scl only) merging equivalences p->fUseMiniSat = 0; // enables MiniSat in lcorr/scorr p->nMinDomSize = 100; // the size of minimum clock domain p->fVeryVerbose = 0; // verbose stats p->fVerbose = 0; // verbose stats } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p ) { return p->nMinDomSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_SeqReadVerbose( Cec_ParSeq_t * p ) { return p->fVerbose; } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRegCreatePart( Gia_Man_t * p, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vNodes, * vRoots; int i, iOut, nCountPis, nCountRegs; int * pMapBack; // collect/mark nodes/PIs in the DFS order from the roots Gia_ManIncrementTravId( p ); vRoots = Vec_IntAlloc( Vec_IntSize(vPart) ); Vec_IntForEachEntry( vPart, iOut, i ) Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManCo(p, Gia_ManPoNum(p)+iOut)) ); vNodes = Gia_ManCollectNodesCis( p, Vec_IntArray(vRoots), Vec_IntSize(vRoots) ); Vec_IntFree( vRoots ); // unmark register outputs Vec_IntForEachEntry( vPart, iOut, i ) Gia_ObjSetTravIdPrevious( p, Gia_ManCi(p, Gia_ManPiNum(p)+iOut) ); // count pure PIs nCountPis = nCountRegs = 0; Gia_ManForEachPi( p, pObj, i ) nCountPis += Gia_ObjIsTravIdCurrent(p, pObj); // count outputs of other registers Gia_ManForEachRo( p, pObj, i ) nCountRegs += Gia_ObjIsTravIdCurrent(p, pObj); // should be !Gia_... ??? if ( pnCountPis ) *pnCountPis = nCountPis; if ( pnCountRegs ) *pnCountRegs = nCountRegs; // clean old manager Gia_ManFillValue(p); Gia_ManConst0(p)->Value = 0; // create the new manager pNew = Gia_ManStart( Vec_IntSize(vNodes) ); // create the PIs Gia_ManForEachCi( p, pObj, i ) if ( Gia_ObjIsTravIdCurrent(p, pObj) ) pObj->Value = Gia_ManAppendCi(pNew); // add variables for the register outputs // create fake POs to hold the register outputs Vec_IntForEachEntry( vPart, iOut, i ) { pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut); pObj->Value = Gia_ManAppendCi(pNew); Gia_ManAppendCo( pNew, pObj->Value ); Gia_ObjSetTravIdCurrent( p, pObj ); // added } // create the nodes Gia_ManForEachObjVec( vNodes, p, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // add real POs for the registers Vec_IntForEachEntry( vPart, iOut, i ) { pObj = Gia_ManCo( p, Gia_ManPoNum(p)+iOut ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManSetRegNum( pNew, Vec_IntSize(vPart) ); // create map if ( ppMapBack ) { pMapBack = ABC_FALLOC( int, Gia_ManObjNum(pNew) ); // map constant nodes pMapBack[0] = 0; // logic cones of register outputs Gia_ManForEachObjVec( vNodes, p, pObj, i ) { // pObjNew = Aig_Regular(pObj->pData); // pMapBack[pObjNew->Id] = pObj->Id; assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 ); assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) ); pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj); } // map register outputs Vec_IntForEachEntry( vPart, iOut, i ) { pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut); // pObjNew = pObj->pData; // pMapBack[pObjNew->Id] = pObj->Id; assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 ); assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) ); pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj); } *ppMapBack = pMapBack; } Vec_IntFree( vNodes ); return pNew; } /**Function************************************************************* Synopsis [Transfers the classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_TransferMappedClasses( Gia_Man_t * pPart, int * pMapBack, int * pReprs ) { Gia_Obj_t * pObj; int i, Id1, Id2, nClasses; if ( pPart->pReprs == NULL ) return 0; nClasses = 0; Gia_ManForEachObj( pPart, pObj, i ) { if ( Gia_ObjRepr(pPart, i) == GIA_VOID ) continue; assert( i < Gia_ManObjNum(pPart) ); assert( Gia_ObjRepr(pPart, i) < Gia_ManObjNum(pPart) ); Id1 = pMapBack[ i ]; Id2 = pMapBack[ Gia_ObjRepr(pPart, i) ]; if ( Id1 == Id2 ) continue; if ( Id1 < Id2 ) pReprs[Id2] = Id1; else pReprs[Id1] = Id2; nClasses++; } return nClasses; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFindRepr_rec( int * pReprs, int Id ) { if ( pReprs[Id] == 0 ) return 0; if ( pReprs[Id] == ~0 ) return Id; return Gia_ManFindRepr_rec( pReprs, pReprs[Id] ); } /**Function************************************************************* Synopsis [Normalizes equivalences.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManNormalizeEquivalences( Gia_Man_t * p, int * pReprs ) { int i, iRepr; 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 ( pReprs[i] == ~0 ) continue; iRepr = Gia_ManFindRepr_rec( pReprs, i ); Gia_ObjSetRepr( p, i, iRepr ); } p->pNexts = Gia_ManDeriveNexts( p ); } /**Function************************************************************* Synopsis [Partitioned sequential synthesis.] Description [Returns AIG annotated with equivalence classes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars ) { int fPrintParts = 0; char Buffer[100]; Gia_Man_t * pTemp; Vec_Ptr_t * vParts = (Vec_Ptr_t *)p->vClockDoms; Vec_Int_t * vPart; int * pMapBack, * pReprs; int i, nCountPis, nCountRegs; int nClasses; abctime clk = Abc_Clock(); // save parameters if ( fPrintParts ) { // print partitions Abc_Print( 1, "The following clock domains are used:\n" ); Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) { pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, NULL ); sprintf( Buffer, "part%03d.aig", i ); Gia_AigerWrite( pTemp, Buffer, 0, 0 ); Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp) ); Gia_ManStop( pTemp ); } } // perform sequential synthesis for clock domains pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) ); Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) { pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, &pMapBack ); if ( nCountPis > 0 ) { if ( pPars->fUseScorr ) { Cec_ParCor_t CorPars, * pCorPars = &CorPars; Cec_ManCorSetDefaultParams( pCorPars ); pCorPars->nBTLimit = pPars->nBTLimit; pCorPars->nLevelMax = pPars->nLevelMax; pCorPars->fVerbose = pPars->fVeryVerbose; pCorPars->fUseCSat = 1; Cec_ManLSCorrespondenceClasses( pTemp, pCorPars ); } else if ( pPars->fUseLcorr ) { Cec_ParCor_t CorPars, * pCorPars = &CorPars; Cec_ManCorSetDefaultParams( pCorPars ); pCorPars->fLatchCorr = 1; pCorPars->nBTLimit = pPars->nBTLimit; pCorPars->fVerbose = pPars->fVeryVerbose; pCorPars->fUseCSat = 1; Cec_ManLSCorrespondenceClasses( pTemp, pCorPars ); } else { // pNew = Gia_ManSeqStructSweep( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose ); // Gia_ManStop( pNew ); Gia_ManSeqCleanupClasses( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose ); } //Abc_Print( 1, "Part equivalences = %d.\n", Gia_ManEquivCountLitsAll(pTemp) ); nClasses = Gia_TransferMappedClasses( pTemp, pMapBack, pReprs ); if ( pPars->fVerbose ) { Abc_Print( 1, "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. Cl = %5d.\n", i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp), nClasses ); } } Gia_ManStop( pTemp ); ABC_FREE( pMapBack ); } // generate resulting equivalences Gia_ManNormalizeEquivalences( p, pReprs ); //Abc_Print( 1, "Total equivalences = %d.\n", Gia_ManEquivCountLitsAll(p) ); ABC_FREE( pReprs ); if ( pPars->fVerbose ) { Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/cec/module.make000066400000000000000000000005451300674244400240430ustar00rootroot00000000000000SRC += src/proof/cec/cecCec.c \ src/proof/cec/cecChoice.c \ src/proof/cec/cecClass.c \ src/proof/cec/cecCore.c \ src/proof/cec/cecCorr.c \ src/proof/cec/cecIso.c \ src/proof/cec/cecMan.c \ src/proof/cec/cecPat.c \ src/proof/cec/cecSeq.c \ src/proof/cec/cecSolve.c \ src/proof/cec/cecSplit.c \ src/proof/cec/cecSynth.c \ src/proof/cec/cecSweep.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/000077500000000000000000000000001300674244400217175ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dch.h000066400000000000000000000072171300674244400226350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dch.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dch.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__dch__dch_h #define ABC__aig__dch__dch_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // choicing parameters typedef struct Dch_Pars_t_ Dch_Pars_t; struct Dch_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 fLightSynth; // uses lighter version of synthesis int fSkipRedSupp; // skip choices with redundant support vars int fVerbose; // verbose stats abctime timeSynth; // synthesis runtime int nNodesAhead; // the lookahead in terms of nodes int nCallsRecycle; // calls to perform before recycling SAT solver }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== dchAig.c ==========================================================*/ extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); /*=== dchCore.c ==========================================================*/ extern void Dch_ManSetDefaultParams( Dch_Pars_t * p ); extern int Dch_ManReadVerbose( Dch_Pars_t * p ); extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); extern void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ); /*=== dchScript.c ==========================================================*/ extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchAig.c000066400000000000000000000071631300674244400232510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchAig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [AIG manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchAig.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the cumulative AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_DeriveTotalAig_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj->pData ) return; Dch_DeriveTotalAig_rec( p, Aig_ObjFanin0(pObj) ); Dch_DeriveTotalAig_rec( p, Aig_ObjFanin1(pObj) ); pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } /**Function************************************************************* Synopsis [Derives the cumulative AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ) { Aig_Man_t * pAig, * pAig2, * pAigTotal; Aig_Obj_t * pObj, * pObjPi, * pObjPo; int i, k, nNodes; assert( Vec_PtrSize(vAigs) > 0 ); // make sure they have the same number of PIs/POs nNodes = 0; pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, i ) { assert( Aig_ManCiNum(pAig) == Aig_ManCiNum(pAig2) ); assert( Aig_ManCoNum(pAig) == Aig_ManCoNum(pAig2) ); nNodes += Aig_ManNodeNum(pAig2); Aig_ManCleanData( pAig2 ); } // map constant nodes pAigTotal = Aig_ManStart( nNodes ); Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAigTotal); // map primary inputs Aig_ManForEachCi( pAig, pObj, i ) { pObjPi = Aig_ObjCreateCi( pAigTotal ); Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) Aig_ManCi( pAig2, i )->pData = pObjPi; } // construct the AIG in the order of POs Aig_ManForEachCo( pAig, pObj, i ) { Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k ) { pObjPo = Aig_ManCo( pAig2, i ); Dch_DeriveTotalAig_rec( pAigTotal, Aig_ObjFanin0(pObjPo) ); } Aig_ObjCreateCo( pAigTotal, Aig_ObjChild0Copy(pObj) ); } /* // mark the cone of the first AIG Aig_ManIncrementTravId( pAigTotal ); Aig_ManForEachObj( pAig, pObj, i ) if ( pObj->pData ) Aig_ObjSetTravIdCurrent( pAigTotal, pObj->pData ); */ // cleanup should not be done return pAigTotal; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchChoice.c000066400000000000000000000444531300674244400237460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchChoice.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [Contrustion of choices.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchChoice.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Counts support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_ObjCountSupp_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { int Count; if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) return 0; Aig_ObjSetTravIdCurrent( p, pObj ); if ( Aig_ObjIsCi(pObj) ) return 1; assert( Aig_ObjIsNode(pObj) ); Count = Dch_ObjCountSupp_rec( p, Aig_ObjFanin0(pObj) ); Count += Dch_ObjCountSupp_rec( p, Aig_ObjFanin1(pObj) ); return Count; } int Dch_ObjCountSupp( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_ManIncrementTravId( p ); return Dch_ObjCountSupp_rec( p, pObj ); } /**Function************************************************************* Synopsis [Counts the number of representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig ) { Aig_Obj_t * pObj, * pRepr; int i, nReprs = 0; Aig_ManForEachObj( pAig, pObj, i ) { pRepr = Aig_ObjRepr( pAig, pObj ); if ( pRepr == NULL ) continue; assert( pRepr->Id < pObj->Id ); nReprs++; } return nReprs; } int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ) { Aig_Obj_t * pObj, * pEquiv; int i, nEquivs = 0; Aig_ManForEachObj( pAig, pObj, i ) { pEquiv = Aig_ObjEquiv( pAig, pObj ); if ( pEquiv == NULL ) continue; assert( pEquiv->Id < pObj->Id ); nEquivs++; } return nEquivs; } /**Function************************************************************* Synopsis [Marks the TFI of the node.] Description [Returns 1 if there is a CI not marked with previous ID.] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_ObjMarkTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { int RetValue; if ( pObj == NULL ) return 0; if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) return 0; if ( Aig_ObjIsCi(pObj) ) { RetValue = !Aig_ObjIsTravIdPrevious( p, pObj ); Aig_ObjSetTravIdCurrent( p, pObj ); return RetValue; } assert( Aig_ObjIsNode(pObj) ); Aig_ObjSetTravIdCurrent( p, pObj ); RetValue = Dch_ObjMarkTfi_rec( p, Aig_ObjFanin0(pObj) ); RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjFanin1(pObj) ); // RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjEquiv(p, pObj) ); return (RetValue > 0); } int Dch_ObjCheckSuppRed( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) { // mark support of the representative node (pRepr) Aig_ManIncrementTravId( p ); Dch_ObjMarkTfi_rec( p, pRepr ); // detect if the new node (pObj) depends on additional variables Aig_ManIncrementTravId( p ); if ( Dch_ObjMarkTfi_rec( p, pObj ) ) return 1;//, printf( "1" ); // detect if the representative node (pRepr) depends on additional variables Aig_ManIncrementTravId( p ); if ( Dch_ObjMarkTfi_rec( p, pRepr ) ) return 1;//, printf( "2" ); // skip the choice if this is what is happening return 0; } /**Function************************************************************* Synopsis [Make sure reprsentative nodes do not have representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCheckReprs( Aig_Man_t * p ) { int fPrintConst = 0; Aig_Obj_t * pObj; int i, fProb = 0; int Class0 = 0, ClassCi = 0; Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjRepr(p, pObj) == NULL ) continue; if ( !Aig_ObjIsNode(pObj) ) printf( "Obj %d is not an AND but it has a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)) ), fProb = 1; else if ( Aig_ObjRepr(p, Aig_ObjRepr(p, pObj)) ) printf( "Obj %d has repr %d with a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)), Aig_ObjId(Aig_ObjRepr(p, Aig_ObjRepr(p, pObj))) ), fProb = 1; } if ( !fProb ) printf( "Representive verification successful.\n" ); else printf( "Representive verification FAILED.\n" ); if ( !fPrintConst ) return; // count how many representatives are const0 or a CI Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjRepr(p, pObj) == Aig_ManConst1(p) ) Class0++; if ( Aig_ObjRepr(p, pObj) && Aig_ObjIsCi(Aig_ObjRepr(p, pObj)) ) ClassCi++; } printf( "Const0 nodes = %d. ConstCI nodes = %d.\n", Class0, ClassCi ); } /**Function************************************************************* Synopsis [Verify correctness of choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_CheckChoices( Aig_Man_t * p, int fSkipRedSupps ) { Aig_Obj_t * pObj; int i, fProb = 0; Aig_ManCleanMarkA( p ); Aig_ManForEachNode( p, pObj, i ) { if ( p->pEquivs[i] != NULL ) { if ( pObj->fMarkA == 1 ) printf( "node %d participates in more than one choice class\n", i ), fProb = 1; pObj->fMarkA = 1; // check redundancy if ( fSkipRedSupps && Dch_ObjCheckSuppRed( p, pObj, p->pEquivs[i]) ) printf( "node %d and repr %d have diff supports\n", pObj->Id, p->pEquivs[i]->Id ); // consider the next one pObj = p->pEquivs[i]; if ( p->pEquivs[Aig_ObjId(pObj)] == NULL ) { if ( pObj->fMarkA == 1 ) printf( "repr %d has final node %d participates in more than one choice class\n", i, pObj->Id ), fProb = 1; pObj->fMarkA = 1; } // consider the non-head ones if ( pObj->nRefs > 0 ) printf( "node %d belonging to choice has fanout %d\n", pObj->Id, pObj->nRefs ); } if ( p->pReprs && p->pReprs[i] != NULL ) { if ( pObj->nRefs > 0 ) printf( "node %d has representative %d and fanout count %d\n", pObj->Id, p->pReprs[i]->Id, pObj->nRefs ), fProb = 1; } } Aig_ManCleanMarkA( p ); if ( !fProb ) printf( "Verification of choice AIG succeeded.\n" ); else printf( "Verification of choice AIG FAILED.\n" ); } /**Function************************************************************* Synopsis [Checks for combinational loops in the AIG.] Description [Returns 1 if combinational loop is detected.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCheckAcyclic_rec( Aig_Man_t * p, Aig_Obj_t * pNode, int fVerbose ) { Aig_Obj_t * pFanin; int fAcyclic; if ( Aig_ObjIsCi(pNode) || Aig_ObjIsConst1(pNode) ) return 1; assert( Aig_ObjIsNode(pNode) ); // make sure the node is not visited assert( !Aig_ObjIsTravIdPrevious(p, pNode) ); // check if the node is part of the combinational loop if ( Aig_ObjIsTravIdCurrent(p, pNode) ) { if ( fVerbose ) Abc_Print( 1, "Network \"%s\" contains combinational loop!\n", p->pSpec? p->pSpec : NULL ); if ( fVerbose ) Abc_Print( 1, "Node \"%d\" is encountered twice on the following path to the COs:\n", Aig_ObjId(pNode) ); return 0; } // mark this node as a node on the current path Aig_ObjSetTravIdCurrent( p, pNode ); // visit the transitive fanin pFanin = Aig_ObjFanin0(pNode); // check if the fanin is visited if ( !Aig_ObjIsTravIdPrevious(p, pFanin) ) { // traverse the fanin's cone searching for the loop if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) { // return as soon as the loop is detected if ( fVerbose ) Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) ); return 0; } } // visit the transitive fanin pFanin = Aig_ObjFanin1(pNode); // check if the fanin is visited if ( !Aig_ObjIsTravIdPrevious(p, pFanin) ) { // traverse the fanin's cone searching for the loop if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) { // return as soon as the loop is detected if ( fVerbose ) Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) ); return 0; } } // visit choices if ( Aig_ObjRepr(p, pNode) == NULL && Aig_ObjEquiv(p, pNode) != NULL ) { for ( pFanin = Aig_ObjEquiv(p, pNode); pFanin; pFanin = Aig_ObjEquiv(p, pFanin) ) { // check if the fanin is visited if ( Aig_ObjIsTravIdPrevious(p, pFanin) ) continue; // traverse the fanin's cone searching for the loop if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) ) continue; // return as soon as the loop is detected if ( fVerbose ) Abc_Print( 1, " %d", Aig_ObjId(pFanin) ); if ( fVerbose ) Abc_Print( 1, " (choice of %d) -> ", Aig_ObjId(pNode) ); return 0; } } // mark this node as a visited node Aig_ObjSetTravIdPrevious( p, pNode ); return 1; } int Aig_ManCheckAcyclic( Aig_Man_t * p, int fVerbose ) { Aig_Obj_t * pNode; int fAcyclic; int i; // set the traversal ID for this DFS ordering Aig_ManIncrementTravId( p ); Aig_ManIncrementTravId( p ); // 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; Aig_ManForEachCo( p, pNode, i ) { pNode = Aig_ObjFanin0(pNode); if ( Aig_ObjIsTravIdPrevious(p, pNode) ) continue; // traverse the output logic cone if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pNode, fVerbose)) ) continue; // stop as soon as the first loop is detected if ( fVerbose ) Abc_Print( 1, " CO %d\n", i ); break; } return fAcyclic; } /**Function************************************************************* Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { // check the trivial cases if ( pObj == NULL ) return 0; if ( Aig_ObjIsCi(pObj) ) return 0; if ( pObj->fMarkA ) return 1; // skip the visited node if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) return 0; Aig_ObjSetTravIdCurrent( p, pObj ); // check the children if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin0(pObj) ) ) return 1; if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin1(pObj) ) ) return 1; // check equivalent nodes return Dch_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pObj) ); } int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) { Aig_Obj_t * pTemp; int RetValue; assert( !Aig_IsComplement(pObj) ); assert( !Aig_IsComplement(pRepr) ); // mark nodes of the choice node for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) pTemp->fMarkA = 1; // traverse the new node Aig_ManIncrementTravId( p ); RetValue = Dch_ObjCheckTfi_rec( p, pObj ); // unmark nodes of the choice node for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) pTemp->fMarkA = 0; return RetValue; } /**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_ObjRepr(p, Aig_Regular(pObj))) ) return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) ); return pObj; } static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); } static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); } /**Function************************************************************* Synopsis [Derives the AIG with choices from representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj, int fSkipRedSupps ) { Aig_Obj_t * pRepr, * pObjNew, * pReprNew; assert( !Aig_IsComplement(pObj) ); // get the representative pRepr = Aig_ObjRepr( pAigOld, pObj ); if ( pRepr != NULL && (Aig_ObjIsConst1(pRepr) || Aig_ObjIsCi(pRepr)) ) { assert( pRepr->pData != NULL ); pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase ); return; } // get the new node pObjNew = Aig_And( pAigNew, Aig_ObjChild0CopyRepr(pAigNew, pObj), Aig_ObjChild1CopyRepr(pAigNew, pObj) ); // pObjNew = Aig_ObjGetRepr( pAigNew, pObjNew ); while ( 1 ) { Aig_Obj_t * pObjNew2 = pObjNew; pObjNew = Aig_ObjGetRepr( pAigNew, pObjNew2 ); if ( pObjNew == pObjNew2 ) break; } // assert( Aig_ObjRepr( pAigNew, pObjNew ) == NULL ); // assign the copy assert( pObj->pData == NULL ); pObj->pData = pObjNew; // skip those without reprs if ( pRepr == NULL ) return; assert( pRepr->Id < pObj->Id ); assert( Aig_ObjIsNode(pRepr) ); // get the corresponding new nodes pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData); pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData); // skip earlier nodes if ( pReprNew->Id >= pObjNew->Id ) return; assert( pReprNew->Id < pObjNew->Id ); // set the representatives Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew ); // skip used nodes if ( pObjNew->nRefs > 0 ) return; assert( pObjNew->nRefs == 0 ); // skip choices that can lead to combo loops if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) ) return; // don't add choice if structural support of pObjNew and pReprNew differ if ( fSkipRedSupps && Dch_ObjCheckSuppRed(pAigNew, pObjNew, pReprNew) ) return; // add choice to the end of the list while ( pAigNew->pEquivs[pReprNew->Id] != NULL ) pReprNew = pAigNew->pEquivs[pReprNew->Id]; assert( pAigNew->pEquivs[pReprNew->Id] == NULL ); pAigNew->pEquivs[pReprNew->Id] = pObjNew; } Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig, int fSkipRedSupps ) { Aig_Man_t * pChoices; Aig_Obj_t * pObj; int i; // start recording equivalences pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); // map constants and PIs Aig_ManCleanData( pAig ); Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices); Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pChoices ); // construct choices for the internal nodes assert( pAig->pReprs != NULL ); Aig_ManForEachNode( pAig, pObj, i ) Dch_DeriveChoiceAigNode( pChoices, pAig, pObj, fSkipRedSupps ); Aig_ManForEachCo( pAig, pObj, i ) Aig_ObjCreateCo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) ); Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) ); return pChoices; } Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig, int fSkipRedSupps ) { int fCheck = 0; Aig_Man_t * pChoices, * pTemp; // verify if ( fCheck ) Aig_ManCheckReprs( pAig ); // compute choices pChoices = Dch_DeriveChoiceAigInt( pAig, fSkipRedSupps ); ABC_FREE( pChoices->pReprs ); // verify if ( fCheck ) Dch_CheckChoices( pChoices, fSkipRedSupps ); // find correct topo order with choices pChoices = Aig_ManDupDfs( pTemp = pChoices ); Aig_ManStop( pTemp ); // verify if ( fCheck ) Dch_CheckChoices( pChoices, fSkipRedSupps ); return pChoices; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchClass.c000066400000000000000000000464451300674244400236240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchClass.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [Representation of candidate equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START /* The candidate equivalence classes are stored as a vector of pointers to the array of pointers to the nodes in each class. The first node of the class is its representative node. The representative has the smallest topological order among the class nodes. The nodes inside each class are ordered according to their topological order. The classes are ordered according to the topo order of their representatives. */ // internal representation of candidate equivalence classes struct Dch_Cla_t_ { // class information Aig_Man_t * pAig; // original AIG manager Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node int * pClassSizes; // sizes of each equivalence class // statistics int nClasses; // the total number of non-const classes int nCands1; // the total number of const candidates int nLits; // the number of literals in all classes // memory Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used // temporary data Vec_Ptr_t * vClassOld; // old equivalence class after splitting Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting // procedures used for class refinement void * pManData; unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement }; //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline Aig_Obj_t * Dch_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } static inline void Dch_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } // iterator through the equivalence classes #define Dch_ManForEachClass( p, ppClass, i ) \ for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \ if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else // iterator through the nodes in one class #define Dch_ClassForEachNode( p, pRepr, pNode, i ) \ for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \ if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Dch_ObjAddClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize ) { assert( p->pId2Class[pRepr->Id] == NULL ); p->pId2Class[pRepr->Id] = pClass; assert( p->pClassSizes[pRepr->Id] == 0 ); assert( nSize > 1 ); p->pClassSizes[pRepr->Id] = nSize; p->nClasses++; p->nLits += nSize - 1; } /**Function************************************************************* Synopsis [Removes one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t ** Dch_ObjRemoveClass( Dch_Cla_t * p, Aig_Obj_t * pRepr ) { Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id]; int nSize; assert( pClass != NULL ); p->pId2Class[pRepr->Id] = NULL; nSize = p->pClassSizes[pRepr->Id]; assert( nSize > 1 ); p->nClasses--; p->nLits -= nSize - 1; p->pClassSizes[pRepr->Id] = 0; return pClass; } /**Function************************************************************* Synopsis [Starts representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig ) { Dch_Cla_t * p; p = ABC_ALLOC( Dch_Cla_t, 1 ); memset( p, 0, sizeof(Dch_Cla_t) ); p->pAig = pAig; p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) ); p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); p->vClassOld = Vec_PtrAlloc( 100 ); p->vClassNew = Vec_PtrAlloc( 100 ); assert( pAig->pReprs == NULL ); Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); return p; } /**Function************************************************************* Synopsis [Starts representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData, unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement { p->pManData = pManData; p->pFuncNodeHash = pFuncNodeHash; p->pFuncNodeIsConst = pFuncNodeIsConst; p->pFuncNodesAreEqual = pFuncNodesAreEqual; } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ClassesStop( Dch_Cla_t * p ) { if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); ABC_FREE( p->pId2Class ); ABC_FREE( p->pClassSizes ); ABC_FREE( p->pMemClasses ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_ClassesLitNum( Dch_Cla_t * p ) { return p->nLits; } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ) { assert( p->pId2Class[pRepr->Id] != NULL ); assert( p->pClassSizes[pRepr->Id] > 1 ); *pnSize = p->pClassSizes[pRepr->Id]; return p->pId2Class[pRepr->Id]; } /**Function************************************************************* Synopsis [Checks candidate equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ClassesCheck( Dch_Cla_t * p ) { Aig_Obj_t * pObj, * pPrev, ** ppClass; int i, k, nLits, nClasses, nCands1; nClasses = nLits = 0; Dch_ManForEachClass( p, ppClass, k ) { pPrev = NULL; Dch_ClassForEachNode( p, ppClass[0], pObj, i ) { if ( i == 0 ) assert( Aig_ObjRepr(p->pAig, pObj) == NULL ); else { assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] ); assert( pPrev->Id < pObj->Id ); nLits++; } pPrev = pObj; } nClasses++; } nCands1 = 0; Aig_ManForEachObj( p->pAig, pObj, i ) nCands1 += Dch_ObjIsConst1Cand( p->pAig, pObj ); assert( p->nLits == nLits ); assert( p->nCands1 == nCands1 ); assert( p->nClasses == nClasses ); } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ClassesPrintOne( Dch_Cla_t * p, Aig_Obj_t * pRepr ) { Aig_Obj_t * pObj; int i; Abc_Print( 1, "{ " ); Dch_ClassForEachNode( p, pRepr, pObj, i ) Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); Abc_Print( 1, "}\n" ); } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose ) { Aig_Obj_t ** ppClass; Aig_Obj_t * pObj; int i; Abc_Print( 1, "Equivalence classes: Const1 = %5d. Class = %5d. Lit = %5d.\n", p->nCands1, p->nClasses, p->nLits ); if ( !fVeryVerbose ) return; Abc_Print( 1, "Constants { " ); Aig_ManForEachObj( p->pAig, pObj, i ) if ( Dch_ObjIsConst1Cand( p->pAig, pObj ) ) Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); Abc_Print( 1, "}\n" ); Dch_ManForEachClass( p, ppClass, i ) { Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] ); Dch_ClassesPrintOne( p, ppClass[0] ); } Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [Creates initial simulation classes.] Description [Assumes that simulation info is assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs ) { Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew; Aig_Obj_t * pObj, * pTemp, * pRepr; int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2; // allocate the hash table hashing simulation info into nodes nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig)/4 ); ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); // add all the nodes to the hash table nEntries = 0; Aig_ManForEachObj( p->pAig, pObj, i ) { if ( fLatchCorr ) { if ( !Aig_ObjIsCi(pObj) ) continue; } else { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; // skip the node with more that the given number of levels if ( nMaxLevs && (int)pObj->Level >= nMaxLevs ) continue; } // check if the node belongs to the class of constant 1 if ( p->pFuncNodeIsConst( p->pManData, pObj ) ) { Dch_ObjSetConst1Cand( p->pAig, pObj ); p->nCands1++; continue; } // hash the node by its simulation info iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize; // add the node to the class if ( ppTable[iEntry] == NULL ) ppTable[iEntry] = pObj; else { // set the representative of this node pRepr = ppTable[iEntry]; Aig_ObjSetRepr( p->pAig, pObj, pRepr ); // add node to the table if ( Dch_ObjNext( ppNexts, pRepr ) == NULL ) { // this will be the second entry p->pClassSizes[pRepr->Id]++; nEntries++; } // add the entry to the list Dch_ObjSetNext( ppNexts, pObj, Dch_ObjNext( ppNexts, pRepr ) ); Dch_ObjSetNext( ppNexts, pRepr, pObj ); p->pClassSizes[pRepr->Id]++; nEntries++; } } // allocate room for classes p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nEntries + p->nCands1 ); p->pMemClassesFree = p->pMemClasses + nEntries; // copy the entries into storage in the topological order nEntries2 = 0; Aig_ManForEachObj( p->pAig, pObj, i ) { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; nNodes = p->pClassSizes[pObj->Id]; // skip the nodes that are not representatives of non-trivial classes if ( nNodes == 0 ) continue; assert( nNodes > 1 ); // add the nodes to the class in the topological order ppClassNew = p->pMemClasses + nEntries2; ppClassNew[0] = pObj; for ( pTemp = Dch_ObjNext(ppNexts, pObj), k = 1; pTemp; pTemp = Dch_ObjNext(ppNexts, pTemp), k++ ) { ppClassNew[nNodes-k] = pTemp; } // add the class of nodes p->pClassSizes[pObj->Id] = 0; Dch_ObjAddClass( p, pObj, ppClassNew, nNodes ); // increment the number of entries nEntries2 += nNodes; } assert( nEntries == nEntries2 ); ABC_FREE( ppTable ); ABC_FREE( ppNexts ); // now it is time to refine the classes Dch_ClassesRefine( p ); Dch_ClassesCheck( p ); } /**Function************************************************************* Synopsis [Iteratively refines the classes after simulation.] Description [Returns the number of refinements performed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive ) { Aig_Obj_t ** pClassOld, ** pClassNew; Aig_Obj_t * pObj, * pReprNew; int i; // split the class Vec_PtrClear( p->vClassOld ); Vec_PtrClear( p->vClassNew ); Dch_ClassForEachNode( p, pReprOld, pObj, i ) if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) ) Vec_PtrPush( p->vClassOld, pObj ); else Vec_PtrPush( p->vClassNew, pObj ); // check if splitting happened if ( Vec_PtrSize(p->vClassNew) == 0 ) return 0; // get the new representative pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); assert( Vec_PtrSize(p->vClassOld) > 0 ); assert( Vec_PtrSize(p->vClassNew) > 0 ); // create old class pClassOld = Dch_ObjRemoveClass( p, pReprOld ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i ) { pClassOld[i] = pObj; Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL ); } // create new class pClassNew = pClassOld + i; Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) { pClassNew[i] = pObj; Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); } // put classes back if ( Vec_PtrSize(p->vClassOld) > 1 ) Dch_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) ); if ( Vec_PtrSize(p->vClassNew) > 1 ) Dch_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) ); // check if the class should be recursively refined if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 ) return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 ); return 1; } /**Function************************************************************* Synopsis [Refines the classes after simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_ClassesRefine( Dch_Cla_t * p ) { Aig_Obj_t ** ppClass; int i, nRefis = 0; Dch_ManForEachClass( p, ppClass, i ) nRefis += Dch_ClassesRefineOneClass( p, ppClass[0], 0 ); return nRefis; } /**Function************************************************************* Synopsis [Returns equivalence class of the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots ) { Aig_Obj_t * pObj; int i; Vec_PtrClear( vRoots ); Dch_ClassForEachNode( p, pRepr, pObj, i ) Vec_PtrPush( vRoots, pObj ); assert( Vec_PtrSize(vRoots) > 1 ); } /**Function************************************************************* Synopsis [Returns equivalence class of the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots ) { int i, Limit; Vec_PtrClear( vRoots ); Limit = Abc_MinInt( pObj->Id + nNodes, Aig_ManObjNumMax(p->pAig) ); for ( i = pObj->Id; i < Limit; i++ ) { pObj = Aig_ManObj( p->pAig, i ); if ( pObj && Dch_ObjIsConst1Cand( p->pAig, pObj ) ) Vec_PtrPush( vRoots, pObj ); } } /**Function************************************************************* Synopsis [Refine the group of constant 1 nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ) { Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; int i; if ( Vec_PtrSize(vRoots) == 0 ) return 0; // collect the nodes to be refined Vec_PtrClear( p->vClassNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) Vec_PtrPush( p->vClassNew, pObj ); // check if there is a new class if ( Vec_PtrSize(p->vClassNew) == 0 ) return 0; p->nCands1 -= Vec_PtrSize(p->vClassNew); pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); if ( Vec_PtrSize(p->vClassNew) == 1 ) return 1; // create a new class composed of these nodes ppClassNew = p->pMemClassesFree; p->pMemClassesFree += Vec_PtrSize(p->vClassNew); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) { ppClassNew[i] = pObj; Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); } Dch_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); // refine them recursively if ( fRecursive ) return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchCnf.c000066400000000000000000000254551300674244400232630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchCnf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [Computation of CNF.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchCnf.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_AddClausesMux( Dch_Man_t * p, Aig_Obj_t * pNode ) { Aig_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; assert( !Aig_IsComplement( pNode ) ); assert( Aig_ObjIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the variable numbers VarF = Dch_ObjSatNum(p,pNode); VarI = Dch_ObjSatNum(p,pNodeI); VarT = Dch_ObjSatNum(p,Aig_Regular(pNodeT)); VarE = Dch_ObjSatNum(p,Aig_Regular(pNodeE)); // get the complementation flags fCompT = Aig_IsComplement(pNodeT); fCompE = Aig_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); if ( p->pPars->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->pPars->fPolarFlip ) { if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_AddClausesSuper( Dch_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper ) { Aig_Obj_t * pFanin; int * pLits, nLits, RetValue, i; assert( !Aig_IsComplement(pNode) ); assert( Aig_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( Aig_Obj_t *, vSuper, pFanin, i ) { pLits[0] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); pLits[1] = toLitCond(Dch_ObjSatNum(p,pNode), 1); if ( p->pPars->fPolarFlip ) { if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); } // add A & B => C or !A + !B + C Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) { pLits[i] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); if ( p->pPars->fPolarFlip ) { if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); } } pLits[nLits-1] = toLitCond(Dch_ObjSatNum(p,pNode), 0); if ( p->pPars->fPolarFlip ) { if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); assert( RetValue ); ABC_FREE( pLits ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) { // if the new node is complemented or a PI, another gate begins if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || (!fFirst && Aig_ObjRefs(pObj) > 1) || (fUseMuxes && Aig_ObjIsMuxType(pObj)) ) { Vec_PtrPushUnique( vSuper, pObj ); return; } // go through the branches Dch_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); Dch_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) { assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCi(pObj) ); Vec_PtrClear( vSuper ); Dch_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ObjAddToFrontier( Dch_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) { assert( !Aig_IsComplement(pObj) ); if ( Dch_ObjSatNum(p,pObj) ) return; assert( Dch_ObjSatNum(p,pObj) == 0 ); if ( Aig_ObjIsConst1(pObj) ) return; Vec_PtrPush( p->vUsedNodes, pObj ); Dch_ObjSetSatNum( p, pObj, p->nSatVars++ ); if ( Aig_ObjIsNode(pObj) ) Vec_PtrPush( vFrontier, pObj ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj ) { Vec_Ptr_t * vFrontier; Aig_Obj_t * pNode, * pFanin; int i, k, fUseMuxes = 1; // quit if CNF is ready if ( Dch_ObjSatNum(p,pObj) ) return; // start the frontier vFrontier = Vec_PtrAlloc( 100 ); Dch_ObjAddToFrontier( p, pObj, vFrontier ); // explore nodes in the frontier Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i ) { // create the supergate assert( Dch_ObjSatNum(p,pNode) ); if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) { Vec_PtrClear( p->vFanins ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); Dch_AddClausesMux( p, pNode ); } else { Dch_CollectSuper( pNode, fUseMuxes, p->vFanins ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); Dch_AddClausesSuper( p, pNode, p->vFanins ); } assert( Vec_PtrSize(p->vFanins) > 1 ); } Vec_PtrFree( vFrontier ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchCore.c000066400000000000000000000122151300674244400234330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [The core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchCore.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManSetDefaultParams( Dch_Pars_t * p ) { memset( p, 0, sizeof(Dch_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->fLightSynth = 0; // uses lighter version of synthesis p->fSkipRedSupp = 0; // skips choices with redundant structural support 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 [Returns verbose parameter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_ManReadVerbose( Dch_Pars_t * p ) { return p->fVerbose; } /**Function************************************************************* Synopsis [Performs computation of AIGs with choices.] Description [Takes several AIGs and performs choicing.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { Dch_Man_t * p; Aig_Man_t * pResult; abctime clk, clkTotal = Abc_Clock(); // reset random numbers Aig_ManRandom(1); // start the choicing manager p = Dch_ManCreate( pAig, pPars ); // compute candidate equivalence classes clk = Abc_Clock(); p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose ); p->timeSimInit = Abc_Clock() - clk; // Dch_ClassesPrint( p->ppClasses, 0 ); p->nLits = Dch_ClassesLitNum( p->ppClasses ); // perform SAT sweeping Dch_ManSweep( p ); // free memory ahead of time p->timeTotal = Abc_Clock() - clkTotal; Dch_ManStop( p ); // create choices ABC_FREE( pAig->pTable ); pResult = Dch_DeriveChoiceAig( pAig, pPars->fSkipRedSupp ); // count the number of representatives if ( pPars->fVerbose ) Abc_Print( 1, "STATS: Ands:%8d ->%8d. Reprs:%7d ->%7d. Choices =%7d.\n", Aig_ManNodeNum(pAig), Aig_ManNodeNum(pResult), Dch_DeriveChoiceCountReprs( pAig ), Dch_DeriveChoiceCountEquivs( pResult ), Aig_ManChoiceNum( pResult ) ); return pResult; } /**Function************************************************************* Synopsis [Performs computation of AIGs with choices.] Description [Takes several AIGs and performs choicing.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { Dch_Man_t * p; abctime clk, clkTotal = Abc_Clock(); // reset random numbers Aig_ManRandom(1); // start the choicing manager p = Dch_ManCreate( pAig, pPars ); // compute candidate equivalence classes clk = Abc_Clock(); p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose ); p->timeSimInit = Abc_Clock() - clk; // Dch_ClassesPrint( p->ppClasses, 0 ); p->nLits = Dch_ClassesLitNum( p->ppClasses ); // perform SAT sweeping Dch_ManSweep( p ); // free memory ahead of time p->timeTotal = Abc_Clock() - clkTotal; Dch_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchInt.h000066400000000000000000000177711300674244400233160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchInt.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__dch__dchInt_h #define ABC__aig__dch__dchInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/aig/aig.h" #include "sat/bsat/satSolver.h" #include "dch.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // equivalence classes typedef struct Dch_Cla_t_ Dch_Cla_t; // choicing manager typedef struct Dch_Man_t_ Dch_Man_t; struct Dch_Man_t_ { // parameters Dch_Pars_t * pPars; // choicing parameters // AIGs used in the package // Vec_Ptr_t * vAigs; // user-given AIGs Aig_Man_t * pAigTotal; // intermediate AIG Aig_Man_t * pAigFraig; // final AIG // equivalence classes Dch_Cla_t * ppClasses; // equivalence classes of nodes Aig_Obj_t ** pReprsProved; // equivalences proved // SAT solving sat_solver * pSat; // recyclable SAT solver int nSatVars; // the counter of SAT variables int * pSatVars; // mapping of each node into its SAT var Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned int nRecycles; // the number of times SAT solver was recycled int nCallsSince; // the number of calls since the last recycle Vec_Ptr_t * vFanins; // fanins of the CNF node Vec_Ptr_t * vSimRoots; // the roots of cand const 1 nodes to simulate Vec_Ptr_t * vSimClasses; // the roots of cand equiv classes to simulate // solver cone size int nConeThis; int nConeMax; // SAT calls statistics int nSatCalls; // the number of SAT calls int nSatProof; // the number of proofs int nSatFailsReal; // the number of timeouts int nSatCallsUnsat; // the number of unsat SAT calls int nSatCallsSat; // the number of sat SAT calls // choice node statistics int nLits; // the number of lits in the cand equiv classes int nReprs; // the number of proved equivalent pairs int nEquivs; // the number of final equivalences int nChoices; // the number of final choice nodes // runtime stats abctime timeSimInit; // simulation and class computation abctime timeSimSat; // simulation of the counter-examples abctime timeSat; // solving SAT abctime timeSatSat; // sat abctime timeSatUnsat; // unsat abctime timeSatUndec; // undecided abctime timeChoice; // choice computation abctime timeOther; // other runtime abctime timeTotal; // total runtime }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Dch_ObjSatNum( Dch_Man_t * p, Aig_Obj_t * pObj ) { return p->pSatVars[pObj->Id]; } static inline void Dch_ObjSetSatNum( Dch_Man_t * p, Aig_Obj_t * pObj, int Num ) { p->pSatVars[pObj->Id] = Num; } static inline Aig_Obj_t * Dch_ObjFraig( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } static inline void Dch_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { pObj->pData = pNode; } static inline int Dch_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) { return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig); } static inline void Dch_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) { assert( !Dch_ObjIsConst1Cand( pAig, pObj ) ); Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== dchAig.c ===================================================*/ /*=== dchChoice.c ===================================================*/ extern int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig ); extern int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ); extern Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig, int fSkipRedSupps ); /*=== dchClass.c =================================================*/ extern Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig ); extern void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData, unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ); extern void Dch_ClassesStop( Dch_Cla_t * p ); extern int Dch_ClassesLitNum( Dch_Cla_t * p ); extern Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ); extern void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose ); extern void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs ); extern int Dch_ClassesRefine( Dch_Cla_t * p ); extern int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive ); extern void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots ); extern void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots ); extern int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ); /*=== dchCnf.c ===================================================*/ extern void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj ); /*=== dchMan.c ===================================================*/ extern Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars ); extern void Dch_ManStop( Dch_Man_t * p ); extern void Dch_ManSatSolverRecycle( Dch_Man_t * p ); /*=== dchSat.c ===================================================*/ extern int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ); /*=== dchSim.c ===================================================*/ extern Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose ); /*=== dchSimSat.c ===================================================*/ extern void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); extern void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); /*=== dchSweep.c ===================================================*/ extern void Dch_ManSweep( Dch_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchMan.c000066400000000000000000000142221300674244400232560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [Calls to the SAT solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchMan.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { Dch_Man_t * p; // create interpolation manager p = ABC_ALLOC( Dch_Man_t, 1 ); memset( p, 0, sizeof(Dch_Man_t) ); p->pPars = pPars; p->pAigTotal = pAig; //Dch_DeriveTotalAig( vAigs ); Aig_ManFanoutStart( p->pAigTotal ); // SAT solving p->nSatVars = 1; p->pSatVars = ABC_CALLOC( int, Aig_ManObjNumMax(p->pAigTotal) ); p->vUsedNodes = Vec_PtrAlloc( 1000 ); p->vFanins = Vec_PtrAlloc( 100 ); p->vSimRoots = Vec_PtrAlloc( 1000 ); p->vSimClasses = Vec_PtrAlloc( 1000 ); // equivalences proved p->pReprsProved = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAigTotal) ); return p; } /**Function************************************************************* Synopsis [Prints stats of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManPrintStats( Dch_Man_t * p ) { int nNodeNum = Aig_ManNodeNum(p->pAigTotal) / 3; Abc_Print( 1, "Parameters: Sim words = %d. Conf limit = %d. SAT var max = %d.\n", p->pPars->nWords, p->pPars->nBTLimit, p->pPars->nSatVarMax ); Abc_Print( 1, "AIG nodes : Total = %6d. Dangling = %6d. Main = %6d. (%6.2f %%)\n", Aig_ManNodeNum(p->pAigTotal), Aig_ManNodeNum(p->pAigTotal)-nNodeNum, nNodeNum, 100.0 * nNodeNum/Aig_ManNodeNum(p->pAigTotal) ); Abc_Print( 1, "SAT solver: Vars = %d. Max cone = %d. Recycles = %d.\n", p->nSatVars, p->nConeMax, p->nRecycles ); Abc_Print( 1, "SAT calls : All = %6d. Unsat = %6d. Sat = %6d. Fail = %6d.\n", p->nSatCalls, p->nSatCalls-p->nSatCallsSat-p->nSatFailsReal, p->nSatCallsSat, p->nSatFailsReal ); Abc_Print( 1, "Choices : Lits = %6d. Reprs = %5d. Equivs = %5d. Choices = %5d.\n", p->nLits, p->nReprs, p->nEquivs, p->nChoices ); Abc_Print( 1, "Choicing runtime statistics:\n" ); p->timeOther = p->timeTotal-p->timeSimInit-p->timeSimSat-p->timeSat-p->timeChoice; Abc_PrintTimeP( 1, "Sim init ", p->timeSimInit, p->timeTotal ); Abc_PrintTimeP( 1, "Sim SAT ", p->timeSimSat, p->timeTotal ); Abc_PrintTimeP( 1, "SAT solving", p->timeSat, p->timeTotal ); Abc_PrintTimeP( 1, " sat ", p->timeSatSat, p->timeTotal ); Abc_PrintTimeP( 1, " unsat ", p->timeSatUnsat, p->timeTotal ); Abc_PrintTimeP( 1, " undecided", p->timeSatUndec, p->timeTotal ); Abc_PrintTimeP( 1, "Choice ", p->timeChoice, p->timeTotal ); Abc_PrintTimeP( 1, "Other ", p->timeOther, p->timeTotal ); Abc_PrintTimeP( 1, "TOTAL ", p->timeTotal, p->timeTotal ); if ( p->pPars->timeSynth ) { Abc_PrintTime( 1, "Synthesis ", p->pPars->timeSynth ); } } /**Function************************************************************* Synopsis [Frees the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManStop( Dch_Man_t * p ) { Aig_ManFanoutStop( p->pAigTotal ); if ( p->pPars->fVerbose ) Dch_ManPrintStats( p ); if ( p->pAigFraig ) Aig_ManStop( p->pAigFraig ); if ( p->ppClasses ) Dch_ClassesStop( p->ppClasses ); if ( p->pSat ) sat_solver_delete( p->pSat ); Vec_PtrFree( p->vUsedNodes ); Vec_PtrFree( p->vFanins ); Vec_PtrFree( p->vSimRoots ); Vec_PtrFree( p->vSimClasses ); ABC_FREE( p->pReprsProved ); ABC_FREE( p->pSatVars ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Recycles the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManSatSolverRecycle( Dch_Man_t * p ) { int Lit; if ( p->pSat ) { Aig_Obj_t * pObj; int i; Vec_PtrForEachEntry( Aig_Obj_t *, p->vUsedNodes, pObj, i ) Dch_ObjSetSatNum( p, pObj, 0 ); Vec_PtrClear( p->vUsedNodes ); // memset( p->pSatVars, 0, sizeof(int) * Aig_ManObjNumMax(p->pAigTotal) ); sat_solver_delete( p->pSat ); } p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, 1000 ); // var 0 is not used // var 1 is reserved for const1 node - add the clause p->nSatVars = 1; // p->nSatVars = 0; Lit = toLit( p->nSatVars ); if ( p->pPars->fPolarFlip ) Lit = lit_neg( Lit ); sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); Dch_ObjSetSatNum( p, Aig_ManConst1(p->pAigFraig), p->nSatVars++ ); p->nRecycles++; p->nCallsSince = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchSat.c000066400000000000000000000117111300674244400232720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [Calls to the SAT solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Runs equivalence test for the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) { int nBTLimit = p->pPars->nBTLimit; int pLits[2], RetValue, RetValue1, status; abctime clk; p->nSatCalls++; // sanity checks assert( !Aig_IsComplement(pNew) ); assert( !Aig_IsComplement(pOld) ); assert( pNew != pOld ); p->nCallsSince++; // experiment with this!!! // check if SAT solver needs recycling if ( p->pSat == NULL || (p->pPars->nSatVarMax && p->nSatVars > p->pPars->nSatVarMax && p->nCallsSince > p->pPars->nCallsRecycle) ) Dch_ManSatSolverRecycle( p ); // if the nodes do not have SAT variables, allocate them Dch_CnfNodeAddToSolver( p, pOld ); Dch_CnfNodeAddToSolver( p, pNew ); // propage unit clauses if ( p->pSat->qtail != p->pSat->qhead ) { status = sat_solver_simplify(p->pSat); assert( status != 0 ); assert( p->pSat->qtail == p->pSat->qhead ); } // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 0 ); pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase == pNew->fPhase ); if ( p->pPars->fPolarFlip ) { if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); } //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); clk = Abc_Clock(); RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); 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; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatFailsReal++; return -1; } // if the old node was constant 0, we already know the answer if ( pOld == Aig_ManConst1(p->pAigFraig) ) { p->nSatProof++; return 1; } // solve under assumptions // A = 0; B = 1 OR A = 0; B = 0 pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 1 ); pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase ^ pNew->fPhase ); if ( p->pPars->fPolarFlip ) { if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); } clk = Abc_Clock(); RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); 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; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatFailsReal++; return -1; } // return SAT proof p->nSatProof++; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchSim.c000066400000000000000000000215651300674244400233030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [Performs random simulation at the beginning.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchSim.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned * Dch_ObjSim( Vec_Ptr_t * vSims, Aig_Obj_t * pObj ) { return (unsigned *)Vec_PtrEntry( vSims, pObj->Id ); } static inline unsigned Dch_ObjRandomSim() { return Aig_ManRandom(0); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if the node appears to be constant 1 candidate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_NodeIsConstCex( void * p, Aig_Obj_t * pObj ) { return pObj->fPhase == pObj->fMarkB; } /**Function************************************************************* Synopsis [Returns 1 if the nodes appear equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_NodesAreEqualCex( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB); } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Dch_NodeHash( void * p, Aig_Obj_t * pObj ) { Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; 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 * pSim; unsigned uHash; int k, nWords; nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); uHash = 0; pSim = Dch_ObjSim( vSims, pObj ); if ( pObj->fPhase ) { for ( k = 0; k < nWords; k++ ) uHash ^= ~pSim[k] * s_FPrimes[k & 0x7F]; } else { for ( k = 0; k < nWords; k++ ) uHash ^= pSim[k] * s_FPrimes[k & 0x7F]; } return uHash; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_NodeIsConst( void * p, Aig_Obj_t * pObj ) { Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; unsigned * pSim; int k, nWords; nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); pSim = Dch_ObjSim( vSims, pObj ); if ( pObj->fPhase ) { for ( k = 0; k < nWords; k++ ) if ( ~pSim[k] ) return 0; } else { for ( k = 0; k < nWords; k++ ) if ( pSim[k] ) return 0; } return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation infos are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dch_NodesAreEqual( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { Vec_Ptr_t * vSims = (Vec_Ptr_t *)p; unsigned * pSim0, * pSim1; int k, nWords; nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); pSim0 = Dch_ObjSim( vSims, pObj0 ); pSim1 = Dch_ObjSim( vSims, pObj1 ); if ( pObj0->fPhase != pObj1->fPhase ) { for ( k = 0; k < nWords; k++ ) if ( pSim0[k] != ~pSim1[k] ) return 0; } else { for ( k = 0; k < nWords; k++ ) if ( pSim0[k] != pSim1[k] ) return 0; } return 1; } /**Function************************************************************* Synopsis [Perform random simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_PerformRandomSimulation( Aig_Man_t * pAig, Vec_Ptr_t * vSims ) { unsigned * pSim, * pSim0, * pSim1; Aig_Obj_t * pObj; int i, k, nWords; nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0); // assign const 1 sim info pObj = Aig_ManConst1(pAig); pSim = Dch_ObjSim( vSims, pObj ); memset( pSim, 0xff, sizeof(unsigned) * nWords ); // assign primary input random sim info Aig_ManForEachCi( pAig, pObj, i ) { pSim = Dch_ObjSim( vSims, pObj ); for ( k = 0; k < nWords; k++ ) pSim[k] = Dch_ObjRandomSim(); pSim[0] <<= 1; } // simulate AIG in the topological order Aig_ManForEachNode( pAig, pObj, i ) { pSim0 = Dch_ObjSim( vSims, Aig_ObjFanin0(pObj) ); pSim1 = Dch_ObjSim( vSims, Aig_ObjFanin1(pObj) ); pSim = Dch_ObjSim( vSims, pObj ); if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // both are compls { for ( k = 0; k < nWords; k++ ) pSim[k] = ~pSim0[k] & ~pSim1[k]; } else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) // first one is compl { for ( k = 0; k < nWords; k++ ) pSim[k] = ~pSim0[k] & pSim1[k]; } else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // second one is compl { for ( k = 0; k < nWords; k++ ) pSim[k] = pSim0[k] & ~pSim1[k]; } else // if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // none is compl { for ( k = 0; k < nWords; k++ ) pSim[k] = pSim0[k] & pSim1[k]; } } // get simulation information for primary outputs } /**Function************************************************************* Synopsis [Derives candidate equivalence classes of AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose ) { Dch_Cla_t * pClasses; Vec_Ptr_t * vSims; int i; // allocate simulation information vSims = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), nWords ); // run random simulation from the primary inputs Dch_PerformRandomSimulation( pAig, vSims ); // start storage for equivalence classes pClasses = Dch_ClassesStart( pAig ); Dch_ClassesSetData( pClasses, vSims, Dch_NodeHash, Dch_NodeIsConst, Dch_NodesAreEqual ); // hash nodes by sim info Dch_ClassesPrepare( pClasses, 0, 0 ); // iterate random simulation for ( i = 0; i < 7; i++ ) { Dch_PerformRandomSimulation( pAig, vSims ); Dch_ClassesRefine( pClasses ); } // clean up and return Vec_PtrFree( vSims ); // prepare class refinement procedures Dch_ClassesSetData( pClasses, NULL, NULL, Dch_NodeIsConstCex, Dch_NodesAreEqualCex ); return pClasses; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchSimSat.c000066400000000000000000000213231300674244400237430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchSimSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [Performs resimulation using counter-examples.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchSimSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects internal nodes in the reverse DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManCollectTfoCands_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pFanout, * pRepr; int iFanout = -1, i; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) return; Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); // traverse the fanouts Aig_ObjForEachFanout( p->pAigTotal, pObj, pFanout, iFanout, i ) Dch_ManCollectTfoCands_rec( p, pFanout ); // check if the given node has a representative pRepr = Aig_ObjRepr( p->pAigTotal, pObj ); if ( pRepr == NULL ) return; // pRepr is the constant 1 node if ( pRepr == Aig_ManConst1(p->pAigTotal) ) { Vec_PtrPush( p->vSimRoots, pObj ); return; } // pRepr is the representative of an equivalence class if ( pRepr->fMarkA ) return; pRepr->fMarkA = 1; Vec_PtrPush( p->vSimClasses, pRepr ); } /**Function************************************************************* Synopsis [Collect equivalence classes and const1 cands in the TFO.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManCollectTfoCands( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) { Aig_Obj_t * pObj; int i; Vec_PtrClear( p->vSimRoots ); Vec_PtrClear( p->vSimClasses ); Aig_ManIncrementTravId( p->pAigTotal ); Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); Dch_ManCollectTfoCands_rec( p, pObj1 ); Dch_ManCollectTfoCands_rec( p, pObj2 ); Vec_PtrSort( p->vSimRoots, (int (*)(void))Aig_ObjCompareIdIncrease ); Vec_PtrSort( p->vSimClasses, (int (*)(void))Aig_ObjCompareIdIncrease ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pObj, i ) pObj->fMarkA = 0; } /**Function************************************************************* Synopsis [Resimulates the cone of influence of the solved nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManResimulateSolved_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) { if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) return; Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); if ( Aig_ObjIsCi(pObj) ) { Aig_Obj_t * pObjFraig; int nVarNum; pObjFraig = Dch_ObjFraig( pObj ); assert( !Aig_IsComplement(pObjFraig) ); nVarNum = Dch_ObjSatNum( p, pObjFraig ); // get the value from the SAT solver // (account for the fact that some vars may be minimized away) pObj->fMarkB = !nVarNum? 0 : sat_solver_var_value( p->pSat, nVarNum ); // pObj->fMarkB = !nVarNum? Aig_ManRandom(0) & 1 : sat_solver_var_value( p->pSat, nVarNum ); return; } Dch_ManResimulateSolved_rec( p, Aig_ObjFanin0(pObj) ); Dch_ManResimulateSolved_rec( p, Aig_ObjFanin1(pObj) ); pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); // count the cone size if ( Dch_ObjSatNum( p, Aig_Regular(Dch_ObjFraig(pObj)) ) > 0 ) p->nConeThis++; } /**Function************************************************************* Synopsis [Resimulates the cone of influence of the other nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManResimulateOther_rec( Dch_Man_t * p, Aig_Obj_t * pObj ) { if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) ) return; Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj); if ( Aig_ObjIsCi(pObj) ) { // set random value pObj->fMarkB = Aig_ManRandom(0) & 1; return; } Dch_ManResimulateOther_rec( p, Aig_ObjFanin0(pObj) ); Dch_ManResimulateOther_rec( p, Aig_ObjFanin1(pObj) ); pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); } /**Function************************************************************* Synopsis [Handle the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) { Aig_Obj_t * pRoot, ** ppClass; int i, k, nSize, RetValue1, RetValue2; abctime clk = Abc_Clock(); // get the equivalence classes Dch_ManCollectTfoCands( p, pObj, pRepr ); // resimulate the cone of influence of the solved nodes p->nConeThis = 0; Aig_ManIncrementTravId( p->pAigTotal ); Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); Dch_ManResimulateSolved_rec( p, pObj ); Dch_ManResimulateSolved_rec( p, pRepr ); p->nConeMax = Abc_MaxInt( p->nConeMax, p->nConeThis ); // resimulate the cone of influence of the other nodes Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i ) Dch_ManResimulateOther_rec( p, pRoot ); // refine these nodes RetValue1 = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 ); // resimulate the cone of influence of the cand classes RetValue2 = 0; Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pRoot, i ) { ppClass = Dch_ClassesReadClass( p->ppClasses, pRoot, &nSize ); for ( k = 0; k < nSize; k++ ) Dch_ManResimulateOther_rec( p, ppClass[k] ); // refine this class RetValue2 += Dch_ClassesRefineOneClass( p->ppClasses, pRoot, 0 ); } // make sure refinement happened if ( Aig_ObjIsConst1(pRepr) ) assert( RetValue1 ); else assert( RetValue2 ); p->timeSimSat += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Handle the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) { Aig_Obj_t * pRoot; int i, RetValue; abctime clk = Abc_Clock(); // get the equivalence class if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) ) Dch_ClassesCollectConst1Group( p->ppClasses, pObj, 500, p->vSimRoots ); else Dch_ClassesCollectOneClass( p->ppClasses, pRepr, p->vSimRoots ); // resimulate the cone of influence of the solved nodes p->nConeThis = 0; Aig_ManIncrementTravId( p->pAigTotal ); Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) ); Dch_ManResimulateSolved_rec( p, pObj ); Dch_ManResimulateSolved_rec( p, pRepr ); p->nConeMax = Abc_MaxInt( p->nConeMax, p->nConeThis ); // resimulate the cone of influence of the other nodes Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i ) Dch_ManResimulateOther_rec( p, pRoot ); // refine this class if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) ) RetValue = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 ); else RetValue = Dch_ClassesRefineOneClass( p->ppClasses, pRepr, 0 ); assert( RetValue ); p->timeSimSat += Abc_Clock() - clk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/dchSweep.c000066400000000000000000000117661300674244400236400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [dchSweep.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [One round of SAT sweeping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: dchSweep.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dchInt.h" #include "misc/bar/bar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline Aig_Obj_t * Dch_ObjChild0Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Dch_ObjChild1Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManSweepNode( Dch_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; int RetValue; // get representative of this class pObjRepr = Aig_ObjRepr( p->pAigTotal, pObj ); if ( pObjRepr == NULL ) return; // get the fraiged node pObjFraig = Dch_ObjFraig( pObj ); if ( pObjFraig == NULL ) return; // get the fraiged representative pObjReprFraig = Dch_ObjFraig( pObjRepr ); if ( pObjReprFraig == NULL ) return; // if the fraiged nodes are the same, return if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) { // remember the proved equivalence p->pReprsProved[ pObj->Id ] = pObjRepr; return; } assert( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pAigFraig) ); RetValue = Dch_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); if ( RetValue == -1 ) // timed out { Dch_ObjSetFraig( pObj, NULL ); return; } if ( RetValue == 1 ) // proved equivalent { pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); Dch_ObjSetFraig( pObj, pObjFraig2 ); // remember the proved equivalence p->pReprsProved[ pObj->Id ] = pObjRepr; return; } // disproved the equivalence if ( p->pPars->fSimulateTfo ) Dch_ManResimulateCex( p, pObj, pObjRepr ); else Dch_ManResimulateCex2( p, pObj, pObjRepr ); assert( Aig_ObjRepr( p->pAigTotal, pObj ) != pObjRepr ); } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dch_ManSweep( Dch_Man_t * p ) { Bar_Progress_t * pProgress = NULL; Aig_Obj_t * pObj, * pObjNew; int i; // map constants and PIs p->pAigFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAigTotal) ); Aig_ManCleanData( p->pAigTotal ); Aig_ManConst1(p->pAigTotal)->pData = Aig_ManConst1(p->pAigFraig); Aig_ManForEachCi( p->pAigTotal, pObj, i ) pObj->pData = Aig_ObjCreateCi( p->pAigFraig ); // sweep internal nodes pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAigTotal) ); Aig_ManForEachNode( p->pAigTotal, pObj, i ) { Bar_ProgressUpdate( pProgress, i, NULL ); if ( Dch_ObjFraig(Aig_ObjFanin0(pObj)) == NULL || Dch_ObjFraig(Aig_ObjFanin1(pObj)) == NULL ) continue; pObjNew = Aig_And( p->pAigFraig, Dch_ObjChild0Fra(pObj), Dch_ObjChild1Fra(pObj) ); if ( pObjNew == NULL ) continue; Dch_ObjSetFraig( pObj, pObjNew ); Dch_ManSweepNode( p, pObj ); } Bar_ProgressStop( pProgress ); // update the representatives of the nodes (makes classes invalid) ABC_FREE( p->pAigTotal->pReprs ); p->pAigTotal->pReprs = p->pReprsProved; p->pReprsProved = NULL; // clean the mark Aig_ManCleanMarkB( p->pAigTotal ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/dch/module.make000066400000000000000000000004231300674244400240420ustar00rootroot00000000000000SRC += src/proof/dch/dchAig.c \ src/proof/dch/dchChoice.c \ src/proof/dch/dchClass.c \ src/proof/dch/dchCnf.c \ src/proof/dch/dchCore.c \ src/proof/dch/dchMan.c \ src/proof/dch/dchSat.c \ src/proof/dch/dchSim.c \ src/proof/dch/dchSimSat.c \ src/proof/dch/dchSweep.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/000077500000000000000000000000001300674244400217315ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fra.h000066400000000000000000000557121300674244400226640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fra.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [[New FRAIG package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fra.h,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__fra__fra_h #define ABC__aig__fra__fra_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "aig/aig/aig.h" #include "opt/dar/dar.h" #include "sat/bsat/satSolver.h" #include "aig/ioa/ioa.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Fra_Par_t_ Fra_Par_t; typedef struct Fra_Ssw_t_ Fra_Ssw_t; typedef struct Fra_Sec_t_ Fra_Sec_t; typedef struct Fra_Man_t_ Fra_Man_t; typedef struct Fra_Cla_t_ Fra_Cla_t; typedef struct Fra_Sml_t_ Fra_Sml_t; typedef struct Fra_Bmc_t_ Fra_Bmc_t; // FRAIG parameters struct Fra_Par_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 fChoicing; // enables choicing int fSpeculate; // use speculative reduction int fProve; // prove the miter outputs int fVerbose; // verbose output int fDoSparse; // skip sparse functions int fConeBias; // bias variables in the cone (good for unsat runs) int nBTLimitNode; // conflict limit at a node int nBTLimitMiter; // conflict limit at an output int nLevelMax; // the max level to consider seriously int nFramesP; // the number of timeframes to in the prefix int nFramesK; // the number of timeframes to unroll int nMaxImps; // the maximum number of implications to consider int nMaxLevs; // the maximum number of levels to consider int fRewrite; // use rewriting for constraint reduction int fLatchCorr; // computes latch correspondence only int fUseImps; // use implications int fUse1Hot; // use one-hotness conditions int fWriteImps; // record implications int fDontShowBar; // does not show progressbar during fraiging }; // seq SAT sweeping parameters struct Fra_Ssw_t_ { int nPartSize; // size of the partition int nOverSize; // size of the overlap between partitions int nFramesP; // number of frames in the prefix int nFramesK; // number of frames for induction (1=simple) int nMaxImps; // max implications to consider int nMaxLevs; // max levels to consider int nMinDomSize; // min clock domain considered for optimization int fUseImps; // use implications int fRewrite; // enable rewriting of the specualatively reduced model int fFraiging; // enable comb SAT sweeping as preprocessing int fLatchCorr; // perform register correspondence int fWriteImps; // write implications into a file int fUse1Hot; // use one-hotness constraints int fVerbose; // enable verbose output int fSilent; // disable any output int nIters; // the number of iterations performed float TimeLimit; // the runtime budget for this call }; // SEC parametesr struct Fra_Sec_t_ { int fTryComb; // try CEC call as a preprocessing step int fTryBmc; // try BMC call as a preprocessing step int nFramesMax; // the max number of frames used for induction int nBTLimit; // the conflict limit at a node int nBTLimitGlobal; // the global conflict limit int nBTLimitInter; // the conflict limit for interpolation int nBddVarsMax; // the state space limit for BDD reachability int nBddMax; // the max number of BDD nodes int nBddIterMax; // the limit on the number of BDD iterations int nPdrTimeout; // the timeout for PDR in the end int fPhaseAbstract; // enables phase abstraction int fRetimeFirst; // enables most-forward retiming at the beginning int fRetimeRegs; // enables min-register retiming at the beginning int fFraiging; // enables fraiging at the beginning int fInduction; // enable the use of induction int fInterpolation; // enables interpolation int fInterSeparate; // enables interpolation for each outputs separately int fReachability; // enables BDD based reachability int fReorderImage; // enables BDD reordering during image computation int fStopOnFirstFail; // enables stopping after first output of a miter has failed to prove int fUseNewProver; // the new prover int fUsePdr; // the PDR int fSilent; // disables all output int fVerbose; // enables verbose reporting of statistics int fVeryVerbose; // enables very verbose reporting int TimeLimit; // enables the timeout int fReadUnsolved; // inserts the unsolved model back int nSMnumber; // the number of model written // internal parameters int fRecursive; // set to 1 when SEC is called recursively int fReportSolution; // enables report solution in a special form }; // FRAIG equivalence classes struct Fra_Cla_t_ { Aig_Man_t * pAig; // the original AIG manager Aig_Obj_t ** pMemRepr; // pointers to representatives of each node Vec_Ptr_t * vClasses; // equivalence classes Vec_Ptr_t * vClasses1; // equivalence class of Const1 node Vec_Ptr_t * vClassesTemp; // temporary storage for new classes Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used Vec_Ptr_t * vClassOld; // old equivalence class after splitting Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting int nPairs; // the number of pairs of nodes int fRefinement; // set to 1 when refinement has happened Vec_Int_t * vImps; // implications // procedures used for class refinement int (*pFuncNodeHash) (Aig_Obj_t *, int); // returns has key of the node int (*pFuncNodeIsConst) (Aig_Obj_t *); // returns 1 if the node is a constant int (*pFuncNodesAreEqual)(Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement }; // simulation manager struct Fra_Sml_t_ { Aig_Man_t * pAig; // the original AIG manager int nPref; // the number of times frames in the prefix int nFrames; // the number of times frames int nWordsFrame; // the number of words in each time frame int nWordsTotal; // the total number of words at a node int nWordsPref; // the number of word in the prefix int fNonConstOut; // have seen a non-const-0 output during simulation int nSimRounds; // statistics int timeSim; // statistics unsigned pData[0]; // simulation data for the nodes }; // FRAIG manager struct Fra_Man_t_ { // high-level data Fra_Par_t * pPars; // parameters governing fraiging // AIG managers Aig_Man_t * pManAig; // the starting AIG manager Aig_Man_t * pManFraig; // the final AIG manager // mapping AIG into FRAIG int nFramesAll; // the number of timeframes used Aig_Obj_t ** pMemFraig; // memory allocated for points to the fraig nodes int nSizeAlloc; // allocated size of the arrays for timeframe nodes // equivalence classes Fra_Cla_t * pCla; // representation of (candidate) equivalent nodes // simulation info Fra_Sml_t * pSml; // simulation manager // bounded model checking manager Fra_Bmc_t * pBmc; // counter example storage int nPatWords; // the number of words in the counter example unsigned * pPatWords; // the counter example Vec_Int_t * vCex; // one-hotness conditions Vec_Int_t * vOneHots; // satisfiability solving sat_solver * pSat; // SAT solver int nSatVars; // the number of variables currently used Vec_Ptr_t * vPiVars; // the PIs of the cone used ABC_INT64_T nBTLimitGlobal; // resource limit ABC_INT64_T nInsLimitGlobal; // resource limit Vec_Ptr_t ** pMemFanins; // the arrays of fanins for some FRAIG nodes int * pMemSatNums; // the array of SAT numbers for some FRAIG nodes int nMemAlloc; // allocated size of the arrays for FRAIG varnums and fanins Vec_Ptr_t * vTimeouts; // the nodes, for which equivalence checking timed out // statistics int nSimRounds; int nNodesMiter; int nLitsBeg; int nLitsEnd; int nNodesBeg; int nNodesEnd; int nRegsBeg; int nRegsEnd; int nSatCalls; int nSatCallsSat; int nSatCallsUnsat; int nSatProof; int nSatFails; int nSatFailsReal; int nSpeculs; int nChoices; int nChoicesFake; int nSatCallsRecent; int nSatCallsSkipped; // runtime abctime timeSim; abctime timeTrav; abctime timeRwr; abctime timeSat; abctime timeSatUnsat; abctime timeSatSat; abctime timeSatFail; abctime timeRef; abctime timeTotal; abctime time1; abctime time2; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned * Fra_ObjSim( Fra_Sml_t * p, int Id ) { return p->pData + p->nWordsTotal * Id; } static inline unsigned Fra_ObjRandomSim() { return Aig_ManRandom(0); } static inline Aig_Obj_t * Fra_ObjFraig( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i]; } static inline void Fra_ObjSetFraig( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i] = pNode; } static inline Vec_Ptr_t * Fra_ObjFaninVec( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id]; } static inline void Fra_ObjSetFaninVec( Aig_Obj_t * pObj, Vec_Ptr_t * vFanins ) { ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id] = vFanins; } static inline int Fra_ObjSatNum( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id]; } static inline void Fra_ObjSetSatNum( Aig_Obj_t * pObj, int Num ) { ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id] = Num; } static inline Aig_Obj_t * Fra_ClassObjRepr( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id]; } static inline void Fra_ClassObjSetRepr( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id] = pNode; } static inline Aig_Obj_t * Fra_ObjChild0Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Fra_ObjChild1Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } static inline int Fra_ImpLeft( int Imp ) { return Imp & 0xFFFF; } static inline int Fra_ImpRight( int Imp ) { return Imp >> 16; } static inline int Fra_ImpCreate( int Left, int Right ) { return (Right << 16) | Left; } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== fraCec.c ========================================================*/ 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 ); extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); extern int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose ); /*=== fraClass.c ========================================================*/ extern int Fra_BmcNodeIsConst( Aig_Obj_t * pObj ); extern int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); extern void Fra_BmcStop( Fra_Bmc_t * p ); extern void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth ); extern void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose ); /*=== fraClass.c ========================================================*/ extern Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig ); extern void Fra_ClassesStop( Fra_Cla_t * p ); extern void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed ); extern void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose ); extern void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr, int nMaxLevs ); extern int Fra_ClassesRefine( Fra_Cla_t * p ); extern int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped ); extern int Fra_ClassesCountLits( Fra_Cla_t * p ); extern int Fra_ClassesCountPairs( Fra_Cla_t * p ); extern void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 ); extern void Fra_ClassesLatchCorr( Fra_Man_t * p ); extern void Fra_ClassesPostprocess( Fra_Cla_t * p ); extern void Fra_ClassesSelectRepr( Fra_Cla_t * p ); extern Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK ); /*=== fraCnf.c ========================================================*/ extern void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); /*=== fraCore.c ========================================================*/ extern void Fra_FraigSweep( Fra_Man_t * pManAig ); extern int Fra_FraigMiterStatus( Aig_Man_t * p ); extern int Fra_FraigMiterAssertedOutput( Aig_Man_t * p ); extern Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars ); extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax ); extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve ); /*=== fraHot.c ========================================================*/ extern Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim ); extern void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots ); extern void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots ); extern int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots ); extern int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots ); extern void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots ); extern Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots ); extern void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots ); /*=== fraImp.c ========================================================*/ extern Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr ); extern void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums ); extern int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos ); extern int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps ); extern void Fra_ImpCompactArray( Vec_Int_t * vImps ); extern double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p ); extern int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p ); extern void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew ); /*=== fraInd.c ========================================================*/ extern Aig_Man_t * Fra_FraigInduction( Aig_Man_t * p, Fra_Ssw_t * pPars ); /*=== fraIndVer.c =====================================================*/ extern int Fra_InvariantVerify( Aig_Man_t * p, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits ); /*=== fraLcr.c ========================================================*/ extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter, float TimeLimit ); /*=== fraMan.c ========================================================*/ extern void Fra_ParamsDefault( Fra_Par_t * pParams ); extern void Fra_ParamsDefaultSeq( Fra_Par_t * pParams ); extern Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pParams ); extern void Fra_ManClean( Fra_Man_t * p, int nNodesMax ); extern Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p ); extern void Fra_ManFinalizeComb( Fra_Man_t * p ); extern void Fra_ManStop( Fra_Man_t * p ); extern void Fra_ManPrint( Fra_Man_t * p ); /*=== fraSat.c ========================================================*/ extern int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); extern int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR ); extern int Fra_NodesAreClause( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR ); extern int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew ); /*=== fraSec.c ========================================================*/ extern void Fra_SecSetDefaultParams( Fra_Sec_t * p ); extern int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult ); /*=== fraSim.c ========================================================*/ extern int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize ); extern int Fra_SmlNodeIsConst( Aig_Obj_t * pObj ); extern int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); extern int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right ); extern int Fra_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj ); extern int Fra_SmlCheckOutput( Fra_Man_t * p ); extern void Fra_SmlSavePattern( Fra_Man_t * p ); extern void Fra_SmlSimulate( Fra_Man_t * p, int fInit ); extern void Fra_SmlResimulate( Fra_Man_t * p ); extern Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ); extern void Fra_SmlStop( Fra_Sml_t * p ); extern Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords, int fCheckMiter ); extern Fra_Sml_t * Fra_SmlSimulateCombGiven( Aig_Man_t * pAig, char * pFileName, int fCheckMiter, int fVerbose ); extern Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords, int fCheckMiter ); extern Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ); extern Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraBmc.c000066400000000000000000000406101300674244400232700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraBmc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Bounded model checking.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraBmc.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // simulation manager struct Fra_Bmc_t_ { // parameters int nPref; // the size of the prefix int nDepth; // the depth of the frames int nFramesAll; // the total number of timeframes // implications to be filtered Vec_Int_t * vImps; // AIG managers Aig_Man_t * pAig; // the original AIG manager Aig_Man_t * pAigFrames; // initialized timeframes Aig_Man_t * pAigFraig; // the fraiged initialized timeframes // mapping of nodes Aig_Obj_t ** pObjToFrames; // mapping of the original node into frames Aig_Obj_t ** pObjToFraig; // mapping of the frames node into fraig }; static inline Aig_Obj_t * Bmc_ObjFrames( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i]; } static inline void Bmc_ObjSetFrames( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i] = pNode; } static inline Aig_Obj_t * Bmc_ObjFraig( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id]; } static inline void Bmc_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id] = pNode; } static inline Aig_Obj_t * Bmc_ObjChild0Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Bmc_ObjChild1Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if the nodes are equivalent.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { Fra_Man_t * p = (Fra_Man_t *)pObj0->pData; Aig_Obj_t * pObjFrames0, * pObjFrames1; Aig_Obj_t * pObjFraig0, * pObjFraig1; int i; for ( i = p->pBmc->nPref; i < p->pBmc->nFramesAll; i++ ) { pObjFrames0 = Aig_Regular( Bmc_ObjFrames(pObj0, i) ); pObjFrames1 = Aig_Regular( Bmc_ObjFrames(pObj1, i) ); if ( pObjFrames0 == pObjFrames1 ) continue; pObjFraig0 = Aig_Regular( Bmc_ObjFraig(pObjFrames0) ); pObjFraig1 = Aig_Regular( Bmc_ObjFraig(pObjFrames1) ); if ( pObjFraig0 != pObjFraig1 ) return 0; } return 1; } /**Function************************************************************* Synopsis [Returns 1 if the node is costant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_BmcNodeIsConst( Aig_Obj_t * pObj ) { Fra_Man_t * p = (Fra_Man_t *)pObj->pData; return Fra_BmcNodesAreEqual( pObj, Aig_ManConst1(p->pManAig) ); } /**Function************************************************************* Synopsis [Refines implications using BMC.] Description [The input is the combinational FRAIG manager, which is used to FRAIG the timeframes. ] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_BmcFilterImplications( Fra_Man_t * p, Fra_Bmc_t * pBmc ) { Aig_Obj_t * pLeft, * pRight; Aig_Obj_t * pLeftT, * pRightT; Aig_Obj_t * pLeftF, * pRightF; int i, f, Imp, Left, Right; int fComplL, fComplR; assert( p->nFramesAll == 1 ); assert( p->pManAig == pBmc->pAigFrames ); Vec_IntForEachEntry( pBmc->vImps, Imp, i ) { if ( Imp == 0 ) continue; Left = Fra_ImpLeft(Imp); Right = Fra_ImpRight(Imp); // get the corresponding nodes pLeft = Aig_ManObj( pBmc->pAig, Left ); pRight = Aig_ManObj( pBmc->pAig, Right ); // iterate through the timeframes for ( f = pBmc->nPref; f < pBmc->nFramesAll; f++ ) { // get timeframe nodes pLeftT = Bmc_ObjFrames( pLeft, f ); pRightT = Bmc_ObjFrames( pRight, f ); // get the corresponding FRAIG nodes pLeftF = Fra_ObjFraig( Aig_Regular(pLeftT), 0 ); pRightF = Fra_ObjFraig( Aig_Regular(pRightT), 0 ); // get the complemented attributes fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF) ^ Aig_IsComplement(pLeftT); fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF) ^ Aig_IsComplement(pRightT); // check equality if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) ) { if ( fComplL == fComplR ) // x => x - always true continue; assert( fComplL != fComplR ); // consider 4 possibilities: // NOT(1) => 1 or 0 => 1 - always true // 1 => NOT(1) or 1 => 0 - never true // NOT(x) => x or x - not always true // x => NOT(x) or NOT(x) - not always true if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication continue; // disproved implication Vec_IntWriteEntry( pBmc->vImps, i, 0 ); break; } // check the implication if ( Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR ) != 1 ) { Vec_IntWriteEntry( pBmc->vImps, i, 0 ); break; } } } Fra_ImpCompactArray( pBmc->vImps ); } /**Function************************************************************* Synopsis [Starts the BMC manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Bmc_t * Fra_BmcStart( Aig_Man_t * pAig, int nPref, int nDepth ) { Fra_Bmc_t * p; p = ABC_ALLOC( Fra_Bmc_t, 1 ); memset( p, 0, sizeof(Fra_Bmc_t) ); p->pAig = pAig; p->nPref = nPref; p->nDepth = nDepth; p->nFramesAll = nPref + nDepth; p->pObjToFrames = ABC_ALLOC( Aig_Obj_t *, p->nFramesAll * Aig_ManObjNumMax(pAig) ); memset( p->pObjToFrames, 0, sizeof(Aig_Obj_t *) * p->nFramesAll * Aig_ManObjNumMax(pAig) ); return p; } /**Function************************************************************* Synopsis [Stops the BMC manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_BmcStop( Fra_Bmc_t * p ) { Aig_ManStop( p->pAigFrames ); if ( p->pAigFraig ) Aig_ManStop( p->pAigFraig ); ABC_FREE( p->pObjToFrames ); ABC_FREE( p->pObjToFraig ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Constructs initialized timeframes of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_BmcFrames( Fra_Bmc_t * p, int fKeepPos ) { Aig_Man_t * pAigFrames; Aig_Obj_t * pObj, * pObjNew; Aig_Obj_t ** pLatches; int i, k, f; // start the fraig package pAigFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFramesAll ); pAigFrames->pName = Abc_UtilStrsav( p->pAig->pName ); pAigFrames->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); // create PI nodes for the frames for ( f = 0; f < p->nFramesAll; f++ ) Bmc_ObjSetFrames( Aig_ManConst1(p->pAig), f, Aig_ManConst1(pAigFrames) ); for ( f = 0; f < p->nFramesAll; f++ ) Aig_ManForEachPiSeq( p->pAig, pObj, i ) Bmc_ObjSetFrames( pObj, f, Aig_ObjCreateCi(pAigFrames) ); // set initial state for the latches Aig_ManForEachLoSeq( p->pAig, pObj, i ) Bmc_ObjSetFrames( pObj, 0, Aig_ManConst0(pAigFrames) ); // add timeframes pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) ); for ( f = 0; f < p->nFramesAll; f++ ) { // add internal nodes of this frame Aig_ManForEachNode( p->pAig, pObj, i ) { pObjNew = Aig_And( pAigFrames, Bmc_ObjChild0Frames(pObj,f), Bmc_ObjChild1Frames(pObj,f) ); Bmc_ObjSetFrames( pObj, f, pObjNew ); } if ( f == p->nFramesAll - 1 ) break; // save the latch input values k = 0; Aig_ManForEachLiSeq( p->pAig, pObj, i ) pLatches[k++] = Bmc_ObjChild0Frames(pObj,f); assert( k == Aig_ManRegNum(p->pAig) ); // insert them to the latch output values k = 0; Aig_ManForEachLoSeq( p->pAig, pObj, i ) Bmc_ObjSetFrames( pObj, f+1, pLatches[k++] ); assert( k == Aig_ManRegNum(p->pAig) ); } ABC_FREE( pLatches ); if ( fKeepPos ) { for ( f = 0; f < p->nFramesAll; f++ ) Aig_ManForEachPoSeq( p->pAig, pObj, i ) Aig_ObjCreateCo( pAigFrames, Bmc_ObjChild0Frames(pObj,f) ); Aig_ManCleanup( pAigFrames ); } else { // add POs to all the dangling nodes Aig_ManForEachObj( pAigFrames, pObjNew, i ) if ( Aig_ObjIsNode(pObjNew) && pObjNew->nRefs == 0 ) Aig_ObjCreateCo( pAigFrames, pObjNew ); } // return the new manager return pAigFrames; } /**Function************************************************************* Synopsis [Performs BMC for the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth ) { Aig_Obj_t * pObj; int i, nImpsOld = 0; abctime clk = Abc_Clock(); assert( p->pBmc == NULL ); // derive and fraig the frames p->pBmc = Fra_BmcStart( p->pManAig, nPref, nDepth ); p->pBmc->pAigFrames = Fra_BmcFrames( p->pBmc, 0 ); // if implications are present, configure the AIG manager to check them if ( p->pCla->vImps ) { p->pBmc->pAigFrames->pImpFunc = (void (*) (void*, void*))Fra_BmcFilterImplications; p->pBmc->pAigFrames->pImpData = p->pBmc; p->pBmc->vImps = p->pCla->vImps; nImpsOld = Vec_IntSize(p->pCla->vImps); } p->pBmc->pAigFraig = Fra_FraigEquivence( p->pBmc->pAigFrames, 1000000, 0 ); p->pBmc->pObjToFraig = p->pBmc->pAigFrames->pObjCopies; p->pBmc->pAigFrames->pObjCopies = NULL; // annotate frames nodes with pointers to the manager Aig_ManForEachObj( p->pBmc->pAigFrames, pObj, i ) pObj->pData = p; // report the results if ( p->pPars->fVerbose ) { printf( "Original AIG = %d. Init %d frames = %d. Fraig = %d. ", Aig_ManNodeNum(p->pBmc->pAig), p->pBmc->nFramesAll, Aig_ManNodeNum(p->pBmc->pAigFrames), Aig_ManNodeNum(p->pBmc->pAigFraig) ); ABC_PRT( "Time", Abc_Clock() - clk ); printf( "Before BMC: " ); // Fra_ClassesPrint( p->pCla, 0 ); printf( "Const = %5d. Class = %5d. Lit = %5d. ", Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); if ( p->pCla->vImps ) printf( "Imp = %5d. ", nImpsOld ); printf( "\n" ); } // refine the classes p->pCla->pFuncNodeIsConst = Fra_BmcNodeIsConst; p->pCla->pFuncNodesAreEqual = Fra_BmcNodesAreEqual; Fra_ClassesRefine( p->pCla ); Fra_ClassesRefine1( p->pCla, 1, NULL ); p->pCla->pFuncNodeIsConst = Fra_SmlNodeIsConst; p->pCla->pFuncNodesAreEqual = Fra_SmlNodesAreEqual; // report the results if ( p->pPars->fVerbose ) { printf( "After BMC: " ); // Fra_ClassesPrint( p->pCla, 0 ); printf( "Const = %5d. Class = %5d. Lit = %5d. ", Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); if ( p->pCla->vImps ) printf( "Imp = %5d. ", Vec_IntSize(p->pCla->vImps) ); printf( "\n" ); } // free the BMC manager Fra_BmcStop( p->pBmc ); p->pBmc = NULL; } /**Function************************************************************* Synopsis [Performs BMC for the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose ) { extern Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig ); Fra_Man_t * pTemp; Fra_Bmc_t * pBmc; Aig_Man_t * pAigTemp; abctime clk; int iOutput; // derive and fraig the frames clk = Abc_Clock(); pBmc = Fra_BmcStart( pAig, 0, nFrames ); pTemp = Fra_LcrAigPrepare( pAig ); pTemp->pBmc = pBmc; pBmc->pAigFrames = Fra_BmcFrames( pBmc, 1 ); if ( fVerbose ) { printf( "AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig), Aig_ManRegNum(pAig), Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); printf( "Time-frames (%d): PI/PO = %d/%d. Node = %6d. Lev = %5d. ", nFrames, Aig_ManCiNum(pBmc->pAigFrames), Aig_ManCoNum(pBmc->pAigFrames), Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( fRewrite ) { clk = Abc_Clock(); pBmc->pAigFrames = Dar_ManRwsat( pAigTemp = pBmc->pAigFrames, 1, 0 ); Aig_ManStop( pAigTemp ); if ( fVerbose ) { printf( "Time-frames after rewriting: Node = %6d. Lev = %5d. ", Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } clk = Abc_Clock(); iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFrames ); if ( iOutput >= 0 ) pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig), iOutput ); else { pBmc->pAigFraig = Fra_FraigEquivence( pBmc->pAigFrames, nBTLimit, 1 ); iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFraig ); if ( pBmc->pAigFraig->pData ) { pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pBmc->pAigFrames, (int *)pBmc->pAigFraig->pData ); ABC_FREE( pBmc->pAigFraig->pData ); } else if ( iOutput >= 0 ) pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig), iOutput ); } if ( fVerbose ) { printf( "Fraiged init frames: Node = %6d. Lev = %5d. ", pBmc->pAigFraig? Aig_ManNodeNum(pBmc->pAigFraig) : -1, pBmc->pAigFraig? Aig_ManLevelNum(pBmc->pAigFraig) : -1 ); ABC_PRT( "Time", Abc_Clock() - clk ); } Fra_BmcStop( pBmc ); ABC_FREE( pTemp ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraCec.c000066400000000000000000000424251300674244400232670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraCec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [CEC engined based on fraiging.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraCec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver2.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 ) { if ( fNewSolver ) { extern void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit ); extern int Cnf_DataWriteOrClause2( void * pSat, Cnf_Dat_t * pCnf ); sat_solver2 * pSat; Cnf_Dat_t * pCnf; int status, RetValue; abctime clk = Abc_Clock(); Vec_Int_t * vCiIds; assert( Aig_ManRegNum(pMan) == 0 ); pMan->pData = NULL; // derive CNF pCnf = Cnf_Derive( pMan, Aig_ManCoNum(pMan) ); // pCnf = Cnf_DeriveSimple( pMan, Aig_ManCoNum(pMan) ); if ( fFlipBits ) Cnf_DataTranformPolarity( pCnf, 0 ); if ( fVerbose ) { printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } // convert into SAT solver pSat = (sat_solver2 *)Cnf_DataWriteIntoSolver2( pCnf, 1, 0 ); if ( pSat == NULL ) { Cnf_DataFree( pCnf ); return 1; } if ( fAndOuts ) { // assert each output independently if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) ) { sat_solver2_delete( pSat ); Cnf_DataFree( pCnf ); return 1; } } else { // add the OR clause for the outputs if ( !Cnf_DataWriteOrClause2( pSat, pCnf ) ) { sat_solver2_delete( pSat ); Cnf_DataFree( pCnf ); return 1; } } vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); Cnf_DataFree( pCnf ); printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) ); ABC_PRT( "Time", Abc_Clock() - clk ); // simplify the problem clk = Abc_Clock(); status = sat_solver2_simplify(pSat); // printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) ); // ABC_PRT( "Time", Abc_Clock() - clk ); if ( status == 0 ) { Vec_IntFree( vCiIds ); sat_solver2_delete( pSat ); // printf( "The problem is UNSATISFIABLE after simplification.\n" ); return 1; } // solve the miter clk = Abc_Clock(); if ( fVerbose ) pSat->verbosity = 1; status = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) { // printf( "The problem timed out.\n" ); RetValue = -1; } else if ( status == l_True ) { // printf( "The problem is SATISFIABLE.\n" ); RetValue = 0; } else if ( status == l_False ) { // printf( "The problem is UNSATISFIABLE.\n" ); RetValue = 1; } else assert( 0 ); // Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts ); // Abc_PrintTime( 1, "Solving time", Abc_Clock() - clk ); // if the problem is SAT, get the counterexample if ( status == l_True ) { pMan->pData = Sat_Solver2GetModel( pSat, vCiIds->pArray, vCiIds->nSize ); } // free the sat_solver2 if ( fVerbose ) Sat_Solver2PrintStats( stdout, pSat ); //sat_solver2_store_write( pSat, "trace.cnf" ); //sat_solver2_store_free( pSat ); sat_solver2_delete( pSat ); Vec_IntFree( vCiIds ); return RetValue; } else { sat_solver * pSat; Cnf_Dat_t * pCnf; int status, RetValue; abctime clk = Abc_Clock(); Vec_Int_t * vCiIds; assert( Aig_ManRegNum(pMan) == 0 ); pMan->pData = NULL; // derive CNF pCnf = Cnf_Derive( pMan, Aig_ManCoNum(pMan) ); // pCnf = Cnf_DeriveSimple( pMan, Aig_ManCoNum(pMan) ); if ( fFlipBits ) Cnf_DataTranformPolarity( pCnf, 0 ); if ( fVerbose ) { printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } // convert into SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat == NULL ) { Cnf_DataFree( pCnf ); return 1; } if ( nLearnedStart ) pSat->nLearntStart = pSat->nLearntMax = nLearnedStart; if ( nLearnedDelta ) pSat->nLearntDelta = nLearnedDelta; if ( nLearnedPerce ) pSat->nLearntRatio = nLearnedPerce; if ( fVerbose ) pSat->fVerbose = fVerbose; if ( fAndOuts ) { // assert each output independently if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) ) { sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); return 1; } } else { // add the OR clause for the outputs if ( !Cnf_DataWriteOrClause( pSat, pCnf ) ) { sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); return 1; } } vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); Cnf_DataFree( pCnf ); // printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); // ABC_PRT( "Time", Abc_Clock() - clk ); // simplify the problem clk = Abc_Clock(); status = sat_solver_simplify(pSat); // printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); // ABC_PRT( "Time", Abc_Clock() - clk ); if ( status == 0 ) { Vec_IntFree( vCiIds ); sat_solver_delete( pSat ); // printf( "The problem is UNSATISFIABLE after simplification.\n" ); return 1; } // solve the miter clk = Abc_Clock(); // if ( fVerbose ) // pSat->verbosity = 1; status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) { // printf( "The problem timed out.\n" ); RetValue = -1; } else if ( status == l_True ) { // printf( "The problem is SATISFIABLE.\n" ); RetValue = 0; } else if ( status == l_False ) { // printf( "The problem is UNSATISFIABLE.\n" ); RetValue = 1; } else assert( 0 ); // Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts ); // Abc_PrintTime( 1, "Solving time", Abc_Clock() - clk ); // if the problem is SAT, get the counterexample if ( status == l_True ) { pMan->pData = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); } // free the sat_solver if ( fVerbose ) Sat_SolverPrintStats( stdout, pSat ); //sat_solver_store_write( pSat, "trace.cnf" ); //sat_solver_store_free( pSat ); sat_solver_delete( pSat ); Vec_IntFree( vCiIds ); return RetValue; } } /**Function************************************************************* Synopsis [Recognizes what nodes are inputs of the EXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCountXors( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pFan0, * pFan1; int i, Counter = 0; Aig_ManForEachNode( p, pObj, i ) if ( Aig_ObjIsMuxType(pObj) && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ) { int nBTLimitStart = 300; // starting SAT run int nBTLimitFirst = 2; // first fraiging iteration int nBTLimitLast = nConfLimit; // the last-gasp SAT run Fra_Par_t Params, * pParams = &Params; Aig_Man_t * pAig = *ppAig, * pTemp; int i, RetValue; abctime clk; // report the original miter if ( fVerbose ) { printf( "Original miter: Nodes = %6d.\n", Aig_ManNodeNum(pAig) ); } RetValue = Fra_FraigMiterStatus( pAig ); // assert( RetValue == -1 ); if ( RetValue == 0 ) { pAig->pData = ABC_ALLOC( int, Aig_ManCiNum(pAig) ); memset( pAig->pData, 0, sizeof(int) * Aig_ManCiNum(pAig) ); return RetValue; } // if SAT only, solve without iteration clk = Abc_Clock(); RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)2*nBTLimitStart, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 ); if ( fVerbose ) { printf( "Initial SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( RetValue >= 0 ) return RetValue; // duplicate the AIG clk = Abc_Clock(); pAig = Dar_ManRwsat( pTemp = pAig, 1, 0 ); Aig_ManStop( pTemp ); if ( fVerbose ) { printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // perform the loop Fra_ParamsDefault( pParams ); pParams->nBTLimitNode = nBTLimitFirst; pParams->nBTLimitMiter = nBTLimitStart; pParams->fDontShowBar = 1; pParams->fProve = 1; for ( i = 0; i < 6; i++ ) { //printf( "Running fraiging with %d BTnode and %d BTmiter.\n", pParams->nBTLimitNode, pParams->nBTLimitMiter ); // try XOR balancing if ( Aig_ManCountXors(pAig) * 30 > Aig_ManNodeNum(pAig) + 300 ) { clk = Abc_Clock(); pAig = Dar_ManBalanceXor( pTemp = pAig, 1, 0, 0 ); Aig_ManStop( pTemp ); if ( fVerbose ) { printf( "Balance-X: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // run fraiging clk = Abc_Clock(); pAig = Fra_FraigPerform( pTemp = pAig, pParams ); Aig_ManStop( pTemp ); if ( fVerbose ) { printf( "Fraiging (i=%d): Nodes = %6d. ", i+1, Aig_ManNodeNum(pAig) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // check the miter status RetValue = Fra_FraigMiterStatus( pAig ); if ( RetValue >= 0 ) break; // perform rewriting clk = Abc_Clock(); pAig = Dar_ManRewriteDefault( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) { printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // check the miter status RetValue = Fra_FraigMiterStatus( pAig ); if ( RetValue >= 0 ) break; // try simulation // set the parameters for the next run pParams->nBTLimitNode = 8 * pParams->nBTLimitNode; pParams->nBTLimitMiter = 2 * pParams->nBTLimitMiter; } // if still unsolved try last gasp if ( RetValue == -1 ) { clk = Abc_Clock(); RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)nBTLimitLast, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 ); if ( fVerbose ) { printf( "Final SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } *ppAig = pAig; return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose ) { Aig_Man_t * pAig; Vec_Ptr_t * vParts; int i, RetValue = 1, nOutputs; // create partitions vParts = Aig_ManMiterPartitioned( pMan1, pMan2, nPartSize, fSmart ); // solve the partitions nOutputs = -1; Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i ) { nOutputs++; if ( fVerbose ) { printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAig), Aig_ManCoNum(pAig), Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); fflush( stdout ); } RetValue = Fra_FraigMiterStatus( pAig ); if ( RetValue == 1 ) continue; if ( RetValue == 0 ) break; RetValue = Fra_FraigCec( &pAig, nConfLimit, 0 ); Vec_PtrWriteEntry( vParts, i, pAig ); if ( RetValue == 1 ) continue; if ( RetValue == 0 ) break; break; } // clear the result if ( fVerbose ) { printf( " \r" ); fflush( stdout ); } // report the timeout if ( RetValue == -1 ) { printf( "Timed out after verifying %d partitions (out of %d).\n", nOutputs, Vec_PtrSize(vParts) ); fflush( stdout ); } // free intermediate results Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i ) Aig_ManStop( pAig ); Vec_PtrFree( vParts ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_FraigCecTop( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose ) { Aig_Man_t * pTemp; //Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose ); int RetValue; abctime clkTotal = Abc_Clock(); if ( Aig_ManCiNum(pMan1) != Aig_ManCiNum(pMan1) ) { printf( "Abc_CommandAbc8Cec(): Miters have different number of PIs.\n" ); return 0; } if ( Aig_ManCoNum(pMan1) != Aig_ManCoNum(pMan1) ) { printf( "Abc_CommandAbc8Cec(): Miters have different number of POs.\n" ); return 0; } assert( Aig_ManCiNum(pMan1) == Aig_ManCiNum(pMan1) ); assert( Aig_ManCoNum(pMan1) == Aig_ManCoNum(pMan1) ); // make sure that the first miter has more nodes if ( Aig_ManNodeNum(pMan1) < Aig_ManNodeNum(pMan2) ) { pTemp = pMan1; pMan1 = pMan2; pMan2 = pTemp; } assert( Aig_ManNodeNum(pMan1) >= Aig_ManNodeNum(pMan2) ); if ( nPartSize ) RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, nPartSize, fSmart, fVerbose ); else // no partitioning RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, Aig_ManCoNum(pMan1), 0, fVerbose ); // 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 ); } else { printf( "Networks are UNDECIDED. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } fflush( stdout ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraClass.c000066400000000000000000000701511300674244400236370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraClass.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraClass.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START /* The candidate equivalence classes are stored as a vector of pointers to the array of pointers to the nodes in each class. The first node of the class is its representative node. The representative has the smallest topological order among the class nodes. The nodes inside each class are ordered according to their topological order. The classes are ordered according to the topological order of their representatives. The array of pointers to the class nodes is terminated with a NULL pointer. To enable dynamic addition of new classes (during class refinement), each array has at least as many NULLs in the end, as there are nodes in the class. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline Aig_Obj_t * Fra_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } static inline void Fra_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig ) { Fra_Cla_t * p; p = ABC_ALLOC( Fra_Cla_t, 1 ); memset( p, 0, sizeof(Fra_Cla_t) ); p->pAig = pAig; p->pMemRepr = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); memset( p->pMemRepr, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) ); p->vClasses = Vec_PtrAlloc( 100 ); p->vClasses1 = Vec_PtrAlloc( 100 ); p->vClassesTemp = Vec_PtrAlloc( 100 ); p->vClassOld = Vec_PtrAlloc( 100 ); p->vClassNew = Vec_PtrAlloc( 100 ); p->pFuncNodeHash = Fra_SmlNodeHash; p->pFuncNodeIsConst = Fra_SmlNodeIsConst; p->pFuncNodesAreEqual = Fra_SmlNodesAreEqual; return p; } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassesStop( Fra_Cla_t * p ) { ABC_FREE( p->pMemClasses ); ABC_FREE( p->pMemRepr ); if ( p->vClassesTemp ) Vec_PtrFree( p->vClassesTemp ); if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); if ( p->vClasses1 ) Vec_PtrFree( p->vClasses1 ); if ( p->vClasses ) Vec_PtrFree( p->vClasses ); if ( p->vImps ) Vec_IntFree( p->vImps ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Starts representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed ) { Aig_Obj_t * pObj; int i; Aig_ManReprStart( p->pAig, Aig_ManObjNumMax(p->pAig) ); memmove( p->pAig->pReprs, p->pMemRepr, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) ); if ( Vec_PtrSize(p->vClasses1) == 0 && Vec_PtrSize(p->vClasses) == 0 ) { Aig_ManForEachObj( p->pAig, pObj, i ) { if ( p->pAig->pReprs[i] != NULL ) printf( "Classes are not cleared!\n" ); assert( p->pAig->pReprs[i] == NULL ); } } if ( vFailed ) Vec_PtrForEachEntry( Aig_Obj_t *, vFailed, pObj, i ) p->pAig->pReprs[pObj->Id] = NULL; } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClassCount( Aig_Obj_t ** pClass ) { Aig_Obj_t * pTemp; int i; for ( i = 0; (pTemp = pClass[i]); i++ ); return i; } /**Function************************************************************* Synopsis [Count the number of literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClassesCountLits( Fra_Cla_t * p ) { Aig_Obj_t ** pClass; int i, nNodes, nLits = 0; nLits = Vec_PtrSize( p->vClasses1 ); Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i ) { nNodes = Fra_ClassCount( pClass ); assert( nNodes > 1 ); nLits += nNodes - 1; } return nLits; } /**Function************************************************************* Synopsis [Count the number of pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClassesCountPairs( Fra_Cla_t * p ) { Aig_Obj_t ** pClass; int i, nNodes, nPairs = 0; Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i ) { nNodes = Fra_ClassCount( pClass ); assert( nNodes > 1 ); nPairs += nNodes * (nNodes - 1) / 2; } return nPairs; } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_PrintClass( Fra_Cla_t * p, Aig_Obj_t ** pClass ) { Aig_Obj_t * pTemp; int i; for ( i = 1; (pTemp = pClass[i]); i++ ) assert( Fra_ClassObjRepr(pTemp) == pClass[0] ); printf( "{ " ); for ( i = 0; (pTemp = pClass[i]); i++ ) printf( "%d(%d,%d) ", pTemp->Id, pTemp->Level, Aig_SupportSize(p->pAig,pTemp) ); printf( "}\n" ); } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose ) { Aig_Obj_t ** pClass; Aig_Obj_t * pObj; int i; printf( "Const = %5d. Class = %5d. Lit = %5d. ", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses), Fra_ClassesCountLits(p) ); if ( p->vImps && Vec_IntSize(p->vImps) > 0 ) printf( "Imp = %5d. ", Vec_IntSize(p->vImps) ); printf( "\n" ); if ( fVeryVerbose ) { Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i ) assert( Fra_ClassObjRepr(pObj) == Aig_ManConst1(p->pAig) ); printf( "Constants { " ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i ) printf( "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); printf( "}\n" ); Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i ) { printf( "%3d (%3d) : ", i, Fra_ClassCount(pClass) ); Fra_PrintClass( p, pClass ); } printf( "\n" ); } } /**Function************************************************************* Synopsis [Creates initial simulation classes.] Description [Assumes that simulation info is assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr, int nMaxLevs ) { Aig_Obj_t ** ppTable, ** ppNexts; Aig_Obj_t * pObj, * pTemp; int i, k, nTableSize, nEntries, nNodes, iEntry; // allocate the hash table hashing simulation info into nodes nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig) ); ppTable = ABC_FALLOC( Aig_Obj_t *, nTableSize ); ppNexts = ABC_FALLOC( Aig_Obj_t *, nTableSize ); memset( ppTable, 0, sizeof(Aig_Obj_t *) * nTableSize ); // add all the nodes to the hash table Vec_PtrClear( p->vClasses1 ); Aig_ManForEachObj( p->pAig, pObj, i ) { if ( fLatchCorr ) { if ( !Aig_ObjIsCi(pObj) ) continue; } else { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; // skip the node with more that the given number of levels if ( nMaxLevs && (int)pObj->Level > nMaxLevs ) continue; } // hash the node by its simulation info iEntry = p->pFuncNodeHash( pObj, nTableSize ); // check if the node belongs to the class of constant 1 if ( p->pFuncNodeIsConst( pObj ) ) { Vec_PtrPush( p->vClasses1, pObj ); Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pAig) ); continue; } // add the node to the class if ( ppTable[iEntry] == NULL ) { ppTable[iEntry] = pObj; Fra_ObjSetNext( ppNexts, pObj, pObj ); } else { Fra_ObjSetNext( ppNexts, pObj, Fra_ObjNext(ppNexts,ppTable[iEntry]) ); Fra_ObjSetNext( ppNexts, ppTable[iEntry], pObj ); } } // count the total number of nodes in the non-trivial classes // mark the representative nodes of each equivalence class nEntries = 0; for ( i = 0; i < nTableSize; i++ ) if ( ppTable[i] && ppTable[i] != Fra_ObjNext(ppNexts, ppTable[i]) ) { for ( pTemp = Fra_ObjNext(ppNexts, ppTable[i]), k = 1; pTemp != ppTable[i]; pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ); assert( k > 1 ); nEntries += k; // mark the node assert( ppTable[i]->fMarkA == 0 ); ppTable[i]->fMarkA = 1; } // allocate room for classes p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->vClasses1)) ); p->pMemClassesFree = p->pMemClasses + 2*nEntries; // copy the entries into storage in the topological order Vec_PtrClear( p->vClasses ); nEntries = 0; Aig_ManForEachObj( p->pAig, pObj, i ) { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; // skip the nodes that are not representatives of non-trivial classes if ( pObj->fMarkA == 0 ) continue; pObj->fMarkA = 0; // add the class of nodes Vec_PtrPush( p->vClasses, p->pMemClasses + 2*nEntries ); // count the number of entries in this class for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; pTemp != pObj; pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ); nNodes = k; assert( nNodes > 1 ); // add the nodes to the class in the topological order p->pMemClasses[2*nEntries] = pObj; for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; pTemp != pObj; pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ) { p->pMemClasses[2*nEntries+nNodes-k] = pTemp; Fra_ClassObjSetRepr( pTemp, pObj ); } // add as many empty entries p->pMemClasses[2*nEntries + nNodes] = NULL; // increment the number of entries nEntries += k; } ABC_FREE( ppTable ); ABC_FREE( ppNexts ); // now it is time to refine the classes Fra_ClassesRefine( p ); // Fra_ClassesPrint( p, 0 ); } /**Function************************************************************* Synopsis [Refines one class using simulation info.] Description [Returns the new class if refinement happened.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t ** Fra_RefineClassOne( Fra_Cla_t * p, Aig_Obj_t ** ppClass ) { Aig_Obj_t * pObj, ** ppThis; int i; assert( ppClass[0] != NULL && ppClass[1] != NULL ); // check if the class is going to be refined for ( ppThis = ppClass + 1; (pObj = *ppThis); ppThis++ ) if ( !p->pFuncNodesAreEqual(ppClass[0], pObj) ) break; if ( pObj == NULL ) return NULL; // split the class Vec_PtrClear( p->vClassOld ); Vec_PtrClear( p->vClassNew ); Vec_PtrPush( p->vClassOld, ppClass[0] ); for ( ppThis = ppClass + 1; (pObj = *ppThis); ppThis++ ) if ( p->pFuncNodesAreEqual(ppClass[0], pObj) ) Vec_PtrPush( p->vClassOld, pObj ); else Vec_PtrPush( p->vClassNew, pObj ); /* printf( "Refining class (" ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i ) printf( "%d,", pObj->Id ); printf( ") + (" ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) printf( "%d,", pObj->Id ); printf( ")\n" ); */ // put the nodes back into the class memory Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i ) { ppClass[i] = pObj; ppClass[Vec_PtrSize(p->vClassOld)+i] = NULL; Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); } ppClass += 2*Vec_PtrSize(p->vClassOld); // put the new nodes into the class memory Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) { ppClass[i] = pObj; ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL; Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); } return ppClass; } /**Function************************************************************* Synopsis [Iteratively refines the classes after simulation.] Description [Returns the number of refinements performed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_RefineClassLastIter( Fra_Cla_t * p, Vec_Ptr_t * vClasses ) { Aig_Obj_t ** pClass, ** pClass2; int nRefis; pClass = (Aig_Obj_t **)Vec_PtrEntryLast( vClasses ); for ( nRefis = 0; (pClass2 = Fra_RefineClassOne( p, pClass )); nRefis++ ) { // if the original class is trivial, remove it if ( pClass[1] == NULL ) Vec_PtrPop( vClasses ); // if the new class is trivial, stop if ( pClass2[1] == NULL ) { nRefis++; break; } // othewise, add the class and continue assert( pClass2[0] != NULL ); Vec_PtrPush( vClasses, pClass2 ); pClass = pClass2; } return nRefis; } /**Function************************************************************* Synopsis [Refines the classes after simulation.] Description [Assumes that simulation info is assigned. Returns the number of classes refined.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClassesRefine( Fra_Cla_t * p ) { Vec_Ptr_t * vTemp; Aig_Obj_t ** pClass; int i, nRefis; // refine the classes nRefis = 0; Vec_PtrClear( p->vClassesTemp ); Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i ) { // add the class to the new array assert( pClass[0] != NULL ); Vec_PtrPush( p->vClassesTemp, pClass ); // refine the class iteratively nRefis += Fra_RefineClassLastIter( p, p->vClassesTemp ); } // exchange the class representation vTemp = p->vClassesTemp; p->vClassesTemp = p->vClasses; p->vClasses = vTemp; return nRefis; } /**Function************************************************************* Synopsis [Refines constant 1 equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped ) { Aig_Obj_t * pObj, ** ppClass; int i, k, nRefis = 1; // check if there is anything to refine if ( Vec_PtrSize(p->vClasses1) == 0 ) return 0; // make sure constant 1 class contains only non-constant nodes assert( Vec_PtrEntry(p->vClasses1,0) != Aig_ManConst1(p->pAig) ); // collect all the nodes to be refined k = 0; Vec_PtrClear( p->vClassNew ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i ) { if ( p->pFuncNodeIsConst( pObj ) ) Vec_PtrWriteEntry( p->vClasses1, k++, pObj ); else Vec_PtrPush( p->vClassNew, pObj ); } Vec_PtrShrink( p->vClasses1, k ); if ( Vec_PtrSize(p->vClassNew) == 0 ) return 0; /* printf( "Refined const-1 class: {" ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) printf( " %d", pObj->Id ); printf( " }\n" ); */ if ( Vec_PtrSize(p->vClassNew) == 1 ) { Fra_ClassObjSetRepr( (Aig_Obj_t *)Vec_PtrEntry(p->vClassNew,0), NULL ); return 1; } // create a new class composed of these nodes ppClass = p->pMemClassesFree; p->pMemClassesFree += 2 * Vec_PtrSize(p->vClassNew); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) { ppClass[i] = pObj; ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL; Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); } assert( ppClass[0] != NULL ); Vec_PtrPush( p->vClasses, ppClass ); // iteratively refine this class if ( fRefineNewClass ) nRefis += Fra_RefineClassLastIter( p, p->vClasses ); else if ( pSkipped ) (*pSkipped)++; return nRefis; } /**Function************************************************************* Synopsis [Starts representation of equivalence classes with one class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 ) { Aig_Obj_t ** pClass; p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 4 ); pClass = p->pMemClasses; assert( Id1 < Id2 ); pClass[0] = Aig_ManObj( p->pAig, Id1 ); pClass[1] = Aig_ManObj( p->pAig, Id2 ); pClass[2] = NULL; pClass[3] = NULL; Fra_ClassObjSetRepr( pClass[1], pClass[0] ); Vec_PtrPush( p->vClasses, pClass ); } /**Function************************************************************* Synopsis [Creates latch correspondence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassesLatchCorr( Fra_Man_t * p ) { Aig_Obj_t * pObj; int i, nEntries = 0; Vec_PtrClear( p->pCla->vClasses1 ); Aig_ManForEachLoSeq( p->pManAig, pObj, i ) { Vec_PtrPush( p->pCla->vClasses1, pObj ); Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pManAig) ); } // allocate room for classes p->pCla->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->pCla->vClasses1)) ); p->pCla->pMemClassesFree = p->pCla->pMemClasses + 2*nEntries; } /**Function************************************************************* Synopsis [Postprocesses the classes by removing half of the less useful.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassesPostprocess( Fra_Cla_t * p ) { int Ratio = 2; Fra_Sml_t * pComb; Aig_Obj_t * pObj, * pRepr, ** ppClass; int * pWeights, WeightMax = 0, i, k, c; // perform combinational simulation pComb = Fra_SmlSimulateComb( p->pAig, 32, 0 ); // compute the weight of each node in the classes pWeights = ABC_ALLOC( int, Aig_ManObjNumMax(p->pAig) ); memset( pWeights, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) ); Aig_ManForEachObj( p->pAig, pObj, i ) { pRepr = Fra_ClassObjRepr( pObj ); if ( pRepr == NULL ) continue; pWeights[i] = Fra_SmlNodeNotEquWeight( pComb, pRepr->Id, pObj->Id ); WeightMax = Abc_MaxInt( WeightMax, pWeights[i] ); } Fra_SmlStop( pComb ); printf( "Before: Const = %6d. Class = %6d. ", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) ); // remove nodes from classes whose weight is less than WeightMax/Ratio k = 0; Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i ) { if ( pWeights[pObj->Id] >= WeightMax/Ratio ) Vec_PtrWriteEntry( p->vClasses1, k++, pObj ); else Fra_ClassObjSetRepr( pObj, NULL ); } Vec_PtrShrink( p->vClasses1, k ); // in each class, compact the nodes Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, ppClass, i ) { k = 1; for ( c = 1; ppClass[c]; c++ ) { if ( pWeights[ppClass[c]->Id] >= WeightMax/Ratio ) ppClass[k++] = ppClass[c]; else Fra_ClassObjSetRepr( ppClass[c], NULL ); } ppClass[k] = NULL; } // remove classes with only repr k = 0; Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, ppClass, i ) if ( ppClass[1] != NULL ) Vec_PtrWriteEntry( p->vClasses, k++, ppClass ); Vec_PtrShrink( p->vClasses, k ); printf( "After: Const = %6d. Class = %6d. \n", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) ); ABC_FREE( pWeights ); } /**Function************************************************************* Synopsis [Postprocesses the classes by selecting representative lowest in top order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassesSelectRepr( Fra_Cla_t * p ) { Aig_Obj_t ** pClass, * pNodeMin; int i, c, cMinSupp, nSuppSizeMin, nSuppSizeCur; // reassign representatives in each class Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i ) { // collect support sizes and find the min-support node cMinSupp = -1; pNodeMin = NULL; nSuppSizeMin = ABC_INFINITY; for ( c = 0; pClass[c]; c++ ) { nSuppSizeCur = Aig_SupportSize( p->pAig, pClass[c] ); // nSuppSizeCur = 1; if ( nSuppSizeMin > nSuppSizeCur || (nSuppSizeMin == nSuppSizeCur && pNodeMin->Level > pClass[c]->Level) ) { nSuppSizeMin = nSuppSizeCur; pNodeMin = pClass[c]; cMinSupp = c; } } // skip the case when the repr did not change if ( cMinSupp == 0 ) continue; // make the new node the representative of the class pClass[cMinSupp] = pClass[0]; pClass[0] = pNodeMin; // set the representative for ( c = 0; pClass[c]; c++ ) Fra_ClassObjSetRepr( pClass[c], c? pClass[0] : NULL ); } } static inline Aig_Obj_t * Fra_ObjEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return ppEquivs[pObj->Id]; } static inline void Fra_ObjSetEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ppEquivs[pObj->Id] = pNode; } static inline Aig_Obj_t * Fra_ObjChild0Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)); } static inline Aig_Obj_t * Fra_ObjChild1Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)); } /**Function************************************************************* Synopsis [Add the node and its constraints to the new AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fra_ClassesDeriveNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, Aig_Obj_t ** ppEquivs ) { Aig_Obj_t * pObjNew, * pObjRepr, * pObjReprNew, * pMiter;//, * pObjNew2; // skip nodes without representative if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL ) return; assert( pObjRepr->Id < pObj->Id ); // get the new node pObjNew = Fra_ObjEqu( ppEquivs, pObj ); // get the new node of the representative pObjReprNew = Fra_ObjEqu( ppEquivs, pObjRepr ); // if this is the same node, no need to add constraints if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) ) return; // these are different nodes - perform speculative reduction // pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); // set the new node // Fra_ObjSetEqu( ppEquivs, pObj, pObjNew2 ); // add the constraint pMiter = Aig_Exor( pManFraig, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) ); pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); pMiter = Aig_Not( pMiter ); Aig_ObjCreateCo( pManFraig, pMiter ); } /**Function************************************************************* Synopsis [Derives AIG for the partitioned problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK ) { Aig_Man_t * pManFraig; Aig_Obj_t * pObj, * pObjNew; Aig_Obj_t ** pLatches, ** ppEquivs; int i, k, f, nFramesAll = nFramesK + 1; assert( Aig_ManRegNum(p->pAig) > 0 ); assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) ); assert( nFramesK > 0 ); // start the fraig package pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * nFramesAll ); pManFraig->pName = Abc_UtilStrsav( p->pAig->pName ); pManFraig->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); // allocate place for the node mapping ppEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); Fra_ObjSetEqu( ppEquivs, Aig_ManConst1(p->pAig), Aig_ManConst1(pManFraig) ); // create latches for the first frame Aig_ManForEachLoSeq( p->pAig, pObj, i ) Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreateCi(pManFraig) ); // add timeframes pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) ); for ( f = 0; f < nFramesAll; f++ ) { // create PIs for this frame Aig_ManForEachPiSeq( p->pAig, pObj, i ) Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreateCi(pManFraig) ); // set the constraints on the latch outputs Aig_ManForEachLoSeq( p->pAig, pObj, i ) Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs ); // add internal nodes of this frame Aig_ManForEachNode( p->pAig, pObj, i ) { pObjNew = Aig_And( pManFraig, Fra_ObjChild0Equ(ppEquivs, pObj), Fra_ObjChild1Equ(ppEquivs, pObj) ); Fra_ObjSetEqu( ppEquivs, pObj, pObjNew ); Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs ); } if ( f == nFramesAll - 1 ) break; if ( f == nFramesAll - 2 ) pManFraig->nAsserts = Aig_ManCoNum(pManFraig); // save the latch input values k = 0; Aig_ManForEachLiSeq( p->pAig, pObj, i ) pLatches[k++] = Fra_ObjChild0Equ( ppEquivs, pObj ); // insert them to the latch output values k = 0; Aig_ManForEachLoSeq( p->pAig, pObj, i ) Fra_ObjSetEqu( ppEquivs, pObj, pLatches[k++] ); } ABC_FREE( pLatches ); ABC_FREE( ppEquivs ); // mark the asserts assert( Aig_ManCoNum(pManFraig) % nFramesAll == 0 ); printf( "Assert miters = %6d. Output miters = %6d.\n", pManFraig->nAsserts, Aig_ManCoNum(pManFraig) - pManFraig->nAsserts ); // remove dangling nodes Aig_ManCleanup( pManFraig ); return pManFraig; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraClau.c000066400000000000000000000571141300674244400234620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraClau.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Induction with clause strengthening.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START /* This code is inspired by the paper: Aaron Bradley and Zohar Manna, "Checking safety by inductive generalization of counterexamples to induction", FMCAD '07. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Cla_Man_t_ Cla_Man_t; struct Cla_Man_t_ { // SAT solvers sat_solver * pSatMain; sat_solver * pSatTest; sat_solver * pSatBmc; // CNF for the test solver // Cnf_Dat_t * pCnfTest; // SAT variables Vec_Int_t * vSatVarsMainCs; Vec_Int_t * vSatVarsTestCs; Vec_Int_t * vSatVarsTestNs; Vec_Int_t * vSatVarsBmcNs; // helper variables int nSatVarsTestBeg; int nSatVarsTestCur; // counter-examples Vec_Int_t * vCexMain0; Vec_Int_t * vCexMain; Vec_Int_t * vCexTest; Vec_Int_t * vCexBase; Vec_Int_t * vCexAssm; Vec_Int_t * vCexBmc; // mapping of CS into NS var numbers int * pMapCsMainToCsTest; int * pMapCsTestToCsMain; int * pMapCsTestToNsTest; int * pMapCsTestToNsBmc; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Saves variables corresponding to latch outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Fra_ClauSaveLatchVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int fCsVars ) { Vec_Int_t * vVars; Aig_Obj_t * pObjLo, * pObjLi; int i; vVars = Vec_IntAlloc( Aig_ManRegNum(pMan) ); Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) Vec_IntPush( vVars, pCnf->pVarNums[fCsVars? pObjLo->Id : pObjLi->Id] ); return vVars; } /**Function************************************************************* Synopsis [Saves variables corresponding to latch outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Fra_ClauSaveOutputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf ) { Vec_Int_t * vVars; Aig_Obj_t * pObj; int i; vVars = Vec_IntAlloc( Aig_ManCoNum(pMan) ); Aig_ManForEachCo( pMan, pObj, i ) Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] ); return vVars; } /**Function************************************************************* Synopsis [Saves variables corresponding to latch outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Fra_ClauSaveInputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int nStarting ) { Vec_Int_t * vVars; Aig_Obj_t * pObj; int i; vVars = Vec_IntAlloc( Aig_ManCiNum(pMan) - nStarting ); Aig_ManForEachCi( pMan, pObj, i ) { if ( i < nStarting ) continue; Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] ); } return vVars; } /**Function************************************************************* Synopsis [Saves variables corresponding to latch outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Fra_ClauCreateMapping( Vec_Int_t * vSatVarsFrom, Vec_Int_t * vSatVarsTo, int nVarsMax ) { int * pMapping, Var, i; assert( Vec_IntSize(vSatVarsFrom) == Vec_IntSize(vSatVarsTo) ); pMapping = ABC_ALLOC( int, nVarsMax ); for ( i = 0; i < nVarsMax; i++ ) pMapping[i] = -1; Vec_IntForEachEntry( vSatVarsFrom, Var, i ) pMapping[Var] = Vec_IntEntry(vSatVarsTo,i); return pMapping; } /**Function************************************************************* Synopsis [Deletes the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClauStop( Cla_Man_t * p ) { ABC_FREE( p->pMapCsMainToCsTest ); ABC_FREE( p->pMapCsTestToCsMain ); ABC_FREE( p->pMapCsTestToNsTest ); ABC_FREE( p->pMapCsTestToNsBmc ); Vec_IntFree( p->vSatVarsMainCs ); Vec_IntFree( p->vSatVarsTestCs ); Vec_IntFree( p->vSatVarsTestNs ); Vec_IntFree( p->vSatVarsBmcNs ); Vec_IntFree( p->vCexMain0 ); Vec_IntFree( p->vCexMain ); Vec_IntFree( p->vCexTest ); Vec_IntFree( p->vCexBase ); Vec_IntFree( p->vCexAssm ); Vec_IntFree( p->vCexBmc ); if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); if ( p->pSatTest ) sat_solver_delete( p->pSatTest ); if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Takes the AIG with the single output to be checked.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cla_Man_t * Fra_ClauStart( Aig_Man_t * pMan ) { Cla_Man_t * p; Cnf_Dat_t * pCnfMain; Cnf_Dat_t * pCnfTest; Cnf_Dat_t * pCnfBmc; Aig_Man_t * pFramesMain; Aig_Man_t * pFramesTest; Aig_Man_t * pFramesBmc; assert( Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) == 1 ); // start the manager p = ABC_ALLOC( Cla_Man_t, 1 ); memset( p, 0, sizeof(Cla_Man_t) ); p->vCexMain0 = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexMain = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexTest = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexBase = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexAssm = Vec_IntAlloc( Aig_ManRegNum(pMan) ); p->vCexBmc = Vec_IntAlloc( Aig_ManRegNum(pMan) ); // derive two timeframes to be checked pFramesMain = Aig_ManFrames( pMan, 2, 0, 1, 0, 0, NULL ); // nFrames, fInit, fOuts, fRegs //Aig_ManShow( pFramesMain, 0, NULL ); assert( Aig_ManCoNum(pFramesMain) == 2 ); Aig_ObjChild0Flip( Aig_ManCo(pFramesMain, 0) ); // complement the first output pCnfMain = Cnf_DeriveSimple( pFramesMain, 0 ); //Cnf_DataWriteIntoFile( pCnfMain, "temp.cnf", 1 ); p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfMain, 1, 0 ); /* { int i; Aig_Obj_t * pObj; Aig_ManForEachObj( pFramesMain, pObj, i ) printf( "%d -> %d \n", pObj->Id, pCnfMain->pVarNums[pObj->Id] ); printf( "\n" ); } */ // derive one timeframe to be checked pFramesTest = Aig_ManFrames( pMan, 1, 0, 0, 1, 0, NULL ); assert( Aig_ManCoNum(pFramesTest) == Aig_ManRegNum(pMan) ); pCnfTest = Cnf_DeriveSimple( pFramesTest, Aig_ManRegNum(pMan) ); p->pSatTest = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfTest, 1, 0 ); p->nSatVarsTestBeg = p->nSatVarsTestCur = sat_solver_nvars( p->pSatTest ); // derive one timeframe to be checked for BMC pFramesBmc = Aig_ManFrames( pMan, 1, 1, 0, 1, 0, NULL ); //Aig_ManShow( pFramesBmc, 0, NULL ); assert( Aig_ManCoNum(pFramesBmc) == Aig_ManRegNum(pMan) ); pCnfBmc = Cnf_DeriveSimple( pFramesBmc, Aig_ManRegNum(pMan) ); p->pSatBmc = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfBmc, 1, 0 ); // create variable sets p->vSatVarsMainCs = Fra_ClauSaveInputVars( pFramesMain, pCnfMain, 2 * (Aig_ManCiNum(pMan)-Aig_ManRegNum(pMan)) ); p->vSatVarsTestCs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 1 ); p->vSatVarsTestNs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 0 ); p->vSatVarsBmcNs = Fra_ClauSaveOutputVars( pFramesBmc, pCnfBmc ); assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsMainCs) ); assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsBmcNs) ); // create mapping of CS into NS vars p->pMapCsMainToCsTest = Fra_ClauCreateMapping( p->vSatVarsMainCs, p->vSatVarsTestCs, Aig_ManObjNumMax(pFramesMain) ); p->pMapCsTestToCsMain = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsMainCs, Aig_ManObjNumMax(pFramesTest) ); p->pMapCsTestToNsTest = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsTestNs, Aig_ManObjNumMax(pFramesTest) ); p->pMapCsTestToNsBmc = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsBmcNs, Aig_ManObjNumMax(pFramesTest) ); // cleanup Cnf_DataFree( pCnfMain ); Cnf_DataFree( pCnfTest ); Cnf_DataFree( pCnfBmc ); Aig_ManStop( pFramesMain ); Aig_ManStop( pFramesTest ); Aig_ManStop( pFramesBmc ); if ( p->pSatMain == NULL || p->pSatTest == NULL || p->pSatBmc == NULL ) { Fra_ClauStop( p ); return NULL; } return p; } /**Function************************************************************* Synopsis [Splits off second half and returns it as a new vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Vec_Int_t * Vec_IntSplitHalf( Vec_Int_t * vVec ) { Vec_Int_t * vPart; int Entry, i; assert( Vec_IntSize(vVec) > 1 ); vPart = Vec_IntAlloc( Vec_IntSize(vVec) / 2 + 1 ); Vec_IntForEachEntryStart( vVec, Entry, i, Vec_IntSize(vVec) / 2 ) Vec_IntPush( vPart, Entry ); Vec_IntShrink( vVec, Vec_IntSize(vVec) / 2 ); return vPart; } /**Function************************************************************* Synopsis [Complements all literals in the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Vec_IntComplement( Vec_Int_t * vVec ) { int i; for ( i = 0; i < Vec_IntSize(vVec); i++ ) vVec->pArray[i] = lit_neg( vVec->pArray[i] ); } /**Function************************************************************* Synopsis [Checks if the property holds. Returns counter-example if not.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClauCheckProperty( Cla_Man_t * p, Vec_Int_t * vCex ) { int nBTLimit = 0; int RetValue, iVar, i; sat_solver_act_var_clear( p->pSatMain ); RetValue = sat_solver_solve( p->pSatMain, NULL, NULL, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); Vec_IntClear( vCex ); if ( RetValue == l_False ) return 1; assert( RetValue == l_True ); Vec_IntForEachEntry( p->vSatVarsMainCs, iVar, i ) Vec_IntPush( vCex, sat_solver_var_literal(p->pSatMain, iVar) ); /* { int i; for (i = 0; i < p->pSatMain->size; i++) printf( "%d=%d ", i, p->pSatMain->model.ptr[i] == l_True ); printf( "\n" ); } */ return 0; } /**Function************************************************************* Synopsis [Checks if the clause holds using BMC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClauCheckBmc( Cla_Man_t * p, Vec_Int_t * vClause ) { int nBTLimit = 0; int RetValue; RetValue = sat_solver_solve( p->pSatBmc, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause), (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) return 1; assert( RetValue == l_True ); return 0; } /**Function************************************************************* Synopsis [Lifts the clause to depend on NS variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClauRemapClause( int * pMap, Vec_Int_t * vClause, Vec_Int_t * vRemapped, int fInv ) { int iLit, i; Vec_IntClear( vRemapped ); Vec_IntForEachEntry( vClause, iLit, i ) { assert( pMap[lit_var(iLit)] >= 0 ); iLit = toLitCond( pMap[lit_var(iLit)], lit_sign(iLit) ^ fInv ); Vec_IntPush( vRemapped, iLit ); } } /**Function************************************************************* Synopsis [Checks if the clause holds. Returns counter example if not.] Description [Uses test SAT solver.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClauCheckClause( Cla_Man_t * p, Vec_Int_t * vClause, Vec_Int_t * vCex ) { int nBTLimit = 0; int RetValue, iVar, i; // complement literals Vec_IntPush( vClause, toLit( p->nSatVarsTestCur++ ) ); // helper positive Vec_IntComplement( vClause ); // helper negative (the clause is C v h') // add the clause RetValue = sat_solver_addclause( p->pSatTest, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) ); assert( RetValue == 1 ); // complement all literals Vec_IntPop( vClause ); // helper removed Vec_IntComplement( vClause ); // create the assumption in terms of NS variables Fra_ClauRemapClause( p->pMapCsTestToNsTest, vClause, p->vCexAssm, 0 ); // add helper literals for ( i = p->nSatVarsTestBeg; i < p->nSatVarsTestCur - 1; i++ ) Vec_IntPush( p->vCexAssm, toLitCond(i,1) ); // other helpers negative Vec_IntPush( p->vCexAssm, toLitCond(i,0) ); // positive helper // try to solve RetValue = sat_solver_solve( p->pSatTest, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm), (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( vCex ) Vec_IntClear( vCex ); if ( RetValue == l_False ) return 1; assert( RetValue == l_True ); if ( vCex ) { Vec_IntForEachEntry( p->vSatVarsTestCs, iVar, i ) Vec_IntPush( vCex, sat_solver_var_literal(p->pSatTest, iVar) ); } return 0; } /**Function************************************************************* Synopsis [Reduces the counter-example by removing complemented literals.] Description [Removes literals from vMain that differ from those in the counter-example (vNew). Relies on the fact that the PI variables are assigned in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClauReduceClause( Vec_Int_t * vMain, Vec_Int_t * vNew ) { int LitM, LitN, VarM, VarN, i, j, k; assert( Vec_IntSize(vMain) <= Vec_IntSize(vNew) ); for ( i = j = k = 0; i < Vec_IntSize(vMain) && j < Vec_IntSize(vNew); ) { LitM = Vec_IntEntry( vMain, i ); LitN = Vec_IntEntry( vNew, j ); VarM = lit_var( LitM ); VarN = lit_var( LitN ); if ( VarM < VarN ) { assert( 0 ); } else if ( VarM > VarN ) { j++; } else // if ( VarM == VarN ) { i++; j++; if ( LitM == LitN ) Vec_IntWriteEntry( vMain, k++, LitM ); } } assert( i == Vec_IntSize(vMain) ); Vec_IntShrink( vMain, k ); } /**Function************************************************************* Synopsis [Computes the minimal invariant that holds.] Description [On entrace, vBasis does not hold, vBasis+vExtra holds but is not minimal. On exit, vBasis is unchanged, vBasis+vExtra is minimal.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClauMinimizeClause_rec( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra ) { Vec_Int_t * vExtra2; int nSizeOld; if ( Vec_IntSize(vExtra) == 1 ) return; nSizeOld = Vec_IntSize( vBasis ); vExtra2 = Vec_IntSplitHalf( vExtra ); // try the first half Vec_IntAppend( vBasis, vExtra ); if ( Fra_ClauCheckClause( p, vBasis, NULL ) ) { Vec_IntShrink( vBasis, nSizeOld ); Fra_ClauMinimizeClause_rec( p, vBasis, vExtra ); return; } Vec_IntShrink( vBasis, nSizeOld ); // try the second half Vec_IntAppend( vBasis, vExtra2 ); if ( Fra_ClauCheckClause( p, vBasis, NULL ) ) { Vec_IntShrink( vBasis, nSizeOld ); Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 ); return; } // Vec_IntShrink( vBasis, nSizeOld ); // find the smallest with the second half added Fra_ClauMinimizeClause_rec( p, vBasis, vExtra ); Vec_IntShrink( vBasis, nSizeOld ); Vec_IntAppend( vBasis, vExtra ); // find the smallest with the second half added Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 ); Vec_IntShrink( vBasis, nSizeOld ); Vec_IntAppend( vExtra, vExtra2 ); Vec_IntFree( vExtra2 ); } /**Function************************************************************* Synopsis [Minimizes the clauses using a simple method.] Description [The input and output clause are in vExtra.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClauMinimizeClause( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra ) { int iLit, iLit2, i, k; Vec_IntForEachEntryReverse( vExtra, iLit, i ) { // copy literals without the given one Vec_IntClear( vBasis ); Vec_IntForEachEntry( vExtra, iLit2, k ) if ( k != i ) Vec_IntPush( vBasis, iLit2 ); // try whether it is inductive if ( !Fra_ClauCheckClause( p, vBasis, NULL ) ) continue; // the clause is inductive // remove the literal for ( k = i; k < Vec_IntSize(vExtra)-1; k++ ) Vec_IntWriteEntry( vExtra, k, Vec_IntEntry(vExtra,k+1) ); Vec_IntShrink( vExtra, Vec_IntSize(vExtra)-1 ); } } /**Function************************************************************* Synopsis [Prints the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClauPrintClause( Vec_Int_t * vSatCsVars, Vec_Int_t * vCex ) { int LitM, VarM, VarN, i, j, k; assert( Vec_IntSize(vCex) <= Vec_IntSize(vSatCsVars) ); for ( i = j = k = 0; i < Vec_IntSize(vCex) && j < Vec_IntSize(vSatCsVars); ) { LitM = Vec_IntEntry( vCex, i ); VarM = lit_var( LitM ); VarN = Vec_IntEntry( vSatCsVars, j ); if ( VarM < VarN ) { assert( 0 ); } else if ( VarM > VarN ) { j++; printf( "-" ); } else // if ( VarM == VarN ) { i++; j++; printf( "%d", !lit_sign(LitM) ); } } assert( i == Vec_IntSize(vCex) ); } /**Function************************************************************* Synopsis [Takes the AIG with the single output to be checked.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose ) { Cla_Man_t * p; int Iter, RetValue, fFailed, i; assert( Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) == 1 ); // create the manager p = Fra_ClauStart( pMan ); if ( p == NULL ) { printf( "The property is trivially inductive.\n" ); return 1; } // generate counter-examples and expand them for ( Iter = 0; !Fra_ClauCheckProperty( p, p->vCexMain0 ) && Iter < nIters; Iter++ ) { if ( fVerbose ) printf( "%4d : ", Iter ); // remap clause into the test manager Fra_ClauRemapClause( p->pMapCsMainToCsTest, p->vCexMain0, p->vCexMain, 0 ); if ( fVerbose && fVeryVerbose ) Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); // the main counter-example is in p->vCexMain // intermediate counter-examples are in p->vCexTest // generate the reduced counter-example to the inductive property fFailed = 0; for ( i = 0; !Fra_ClauCheckClause( p, p->vCexMain, p->vCexTest ); i++ ) { Fra_ClauReduceClause( p->vCexMain, p->vCexTest ); Fra_ClauRemapClause( p->pMapCsTestToNsBmc, p->vCexMain, p->vCexBmc, 0 ); // if ( !Fra_ClauCheckBmc(p, p->vCexBmc) ) if ( Vec_IntSize(p->vCexMain) < 1 ) { Vec_IntComplement( p->vCexMain0 ); RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexMain0), Vec_IntArray(p->vCexMain0) + Vec_IntSize(p->vCexMain0) ); if ( RetValue == 0 ) { printf( "\nProperty is proved after %d iterations.\n", Iter+1 ); return 0; } fFailed = 1; break; } } if ( fFailed ) { if ( fVerbose ) printf( " Reducing failed after %d iterations (BMC failed).\n", i ); continue; } if ( Vec_IntSize(p->vCexMain) == 0 ) { if ( fVerbose ) printf( " Reducing failed after %d iterations (nothing left).\n", i ); continue; } if ( fVerbose ) printf( " " ); if ( fVerbose && fVeryVerbose ) Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); if ( fVerbose ) printf( " LitsInd = %3d. ", Vec_IntSize(p->vCexMain) ); // minimize the inductive property Vec_IntClear( p->vCexBase ); if ( Vec_IntSize(p->vCexMain) > 1 ) // Fra_ClauMinimizeClause_rec( p, p->vCexBase, p->vCexMain ); Fra_ClauMinimizeClause( p, p->vCexBase, p->vCexMain ); assert( Vec_IntSize(p->vCexMain) > 0 ); if ( fVerbose && fVeryVerbose ) Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain ); if ( fVerbose ) printf( " LitsRed = %3d. ", Vec_IntSize(p->vCexMain) ); if ( fVerbose ) printf( "\n" ); // add the clause to the solver Fra_ClauRemapClause( p->pMapCsTestToCsMain, p->vCexMain, p->vCexAssm, 1 ); RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm) ); if ( RetValue == 0 ) { Iter++; break; } if ( p->pSatMain->qtail != p->pSatMain->qhead ) { RetValue = sat_solver_simplify(p->pSatMain); assert( RetValue != 0 ); assert( p->pSatMain->qtail == p->pSatMain->qhead ); } } // report the results if ( Iter == nIters ) { printf( "Property is not proved after %d iterations.\n", nIters ); return 0; } printf( "Property is proved after %d iterations.\n", Iter ); Fra_ClauStop( p ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraClaus.c000066400000000000000000001610511300674244400236410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraClaus.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Induction with clause strengthening.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Clu_Man_t_ Clu_Man_t; struct Clu_Man_t_ { // parameters int nFrames; // the K of the K-step induction int nPref; // the number of timeframes to skip int nClausesMax; // the max number of 4-clauses to consider int nLutSize; // the max cut size int nLevels; // the number of levels for cut computation int nCutsMax; // the maximum number of cuts to compute at a node int nBatches; // the number of clause batches to use int fStepUp; // increase cut size for each batch int fTarget; // tries to prove the property int fVerbose; int fVeryVerbose; // internal parameters int nSimWords; // the number of simulation words int nSimWordsPref; // the number of simulation words in the prefix int nSimFrames; // the number of frames to simulate int nBTLimit; // the largest number of backtracks (0 = infinite) // the network Aig_Man_t * pAig; // SAT solvers sat_solver * pSatMain; sat_solver * pSatBmc; // CNF for the test solver Cnf_Dat_t * pCnf; int fFail; int fFiltering; int fNothingNew; // clauses Vec_Int_t * vLits; Vec_Int_t * vClauses; Vec_Int_t * vCosts; int nClauses; int nCuts; int nOneHots; int nOneHotsProven; // clauses proven Vec_Int_t * vLitsProven; Vec_Int_t * vClausesProven; // counter-examples Vec_Ptr_t * vCexes; int nCexes; int nCexesAlloc; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Runs the SAT solver on the problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausRunBmc( Clu_Man_t * p ) { Aig_Obj_t * pObj; int Lits[2], nLitsTot, RetValue, i; // set the output literals nLitsTot = 2 * p->pCnf->nVars; pObj = Aig_ManCo(p->pAig, 0); for ( i = 0; i < p->nPref + p->nFrames; i++ ) { Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 0 ); RetValue = sat_solver_solve( p->pSatBmc, Lits, Lits + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue != l_False ) return 0; } return 1; } /**Function************************************************************* Synopsis [Runs the SAT solver on the problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausRunSat( Clu_Man_t * p ) { Aig_Obj_t * pObj; int * pLits; int i, RetValue; pLits = ABC_ALLOC( int, p->nFrames + 1 ); // set the output literals pObj = Aig_ManCo(p->pAig, 0); for ( i = 0; i <= p->nFrames; i++ ) pLits[i] = i * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObj->Id], i != p->nFrames ); // try to solve the problem RetValue = sat_solver_solve( p->pSatMain, pLits, pLits + p->nFrames + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); ABC_FREE( pLits ); if ( RetValue == l_False ) return 1; // get the counter-example assert( RetValue == l_True ); return 0; } /**Function************************************************************* Synopsis [Runs the SAT solver on the problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausRunSat0( Clu_Man_t * p ) { Aig_Obj_t * pObj; int Lits[2], RetValue; pObj = Aig_ManCo(p->pAig, 0); Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 0 ); RetValue = sat_solver_solve( p->pSatMain, Lits, Lits + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) return 1; return 0; } /**Function************************************************************* Synopsis [Return combinations appearing in the cut.] Description [This procedure is taken from "Hacker's Delight" by H.S.Warren.] SideEffects [] SeeAlso [] ***********************************************************************/ void transpose32a( unsigned a[32] ) { int j, k; unsigned long m, t; for ( j = 16, m = 0x0000FFFF; j; j >>= 1, m ^= m << j ) { for ( k = 0; k < 32; k = ((k | j) + 1) & ~j ) { t = (a[k] ^ (a[k|j] >> j)) & m; a[k] ^= t; a[k|j] ^= (t << j); } } } /**Function************************************************************* Synopsis [Return combinations appearing in the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausProcessClausesCut( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores ) { unsigned Matrix[32]; unsigned * pSims[16], uWord; int nSeries, i, k, j; int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; // compute parameters assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 ); assert( nWordsForSim % 8 == 0 ); // get parameters for ( i = 0; i < (int)pCut->nLeaves; i++ ) pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref; // add combinational patterns memset( pScores, 0, sizeof(int) * 16 ); nSeries = nWordsForSim / 8; for ( i = 0; i < nSeries; i++ ) { memset( Matrix, 0, sizeof(unsigned) * 32 ); for ( k = 0; k < 8; k++ ) for ( j = 0; j < (int)pCut->nLeaves; j++ ) Matrix[31-(k*4+j)] = pSims[j][i*8+k]; transpose32a( Matrix ); for ( k = 0; k < 32; k++ ) for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 ) pScores[uWord & 0xF]++; } // collect patterns uWord = 0; for ( i = 0; i < 16; i++ ) if ( pScores[i] ) uWord |= (1 << i); // Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" ); return (int)uWord; } /**Function************************************************************* Synopsis [Return combinations appearing in the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausProcessClausesCut2( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores ) { unsigned * pSims[16], uWord; int iMint, i, k, b; int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; // compute parameters assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 ); assert( nWordsForSim % 8 == 0 ); // get parameters for ( i = 0; i < (int)pCut->nLeaves; i++ ) pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref; // add combinational patterns memset( pScores, 0, sizeof(int) * 16 ); for ( i = 0; i < nWordsForSim; i++ ) for ( k = 0; k < 32; k++ ) { iMint = 0; for ( b = 0; b < (int)pCut->nLeaves; b++ ) if ( pSims[b][i] & (1 << k) ) iMint |= (1 << b); pScores[iMint]++; } // collect patterns uWord = 0; for ( i = 0; i < 16; i++ ) if ( pScores[i] ) uWord |= (1 << i); // Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" ); return (int)uWord; } /**Function************************************************************* Synopsis [Return the number of combinations appearing in the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausProcessClausesCut3( Clu_Man_t * p, Fra_Sml_t * pSimMan, Aig_Cut_t * pCut, int * pScores ) { unsigned Matrix[32]; unsigned * pSims[16], uWord; int iMint, i, j, k, b, nMints, nSeries; int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref; // compute parameters assert( pCut->nFanins > 1 && pCut->nFanins < 17 ); assert( nWordsForSim % 8 == 0 ); // get parameters for ( i = 0; i < (int)pCut->nFanins; i++ ) pSims[i] = Fra_ObjSim( pSimMan, pCut->pFanins[i] ) + p->nSimWordsPref; // add combinational patterns nMints = (1 << pCut->nFanins); memset( pScores, 0, sizeof(int) * nMints ); if ( pCut->nLeafMax == 4 ) { // convert the simulation patterns nSeries = nWordsForSim / 8; for ( i = 0; i < nSeries; i++ ) { memset( Matrix, 0, sizeof(unsigned) * 32 ); for ( k = 0; k < 8; k++ ) for ( j = 0; j < (int)pCut->nFanins; j++ ) Matrix[31-(k*4+j)] = pSims[j][i*8+k]; transpose32a( Matrix ); for ( k = 0; k < 32; k++ ) for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 ) pScores[uWord & 0xF]++; } } else { // go through the simulation patterns for ( i = 0; i < nWordsForSim; i++ ) for ( k = 0; k < 32; k++ ) { iMint = 0; for ( b = 0; b < (int)pCut->nFanins; b++ ) if ( pSims[b][i] & (1 << k) ) iMint |= (1 << b); pScores[iMint]++; } } } /**Function************************************************************* Synopsis [Returns the cut-off cost.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausSelectClauses( Clu_Man_t * p ) { int * pCostCount, nClauCount, Cost, CostMax, i, c; assert( Vec_IntSize(p->vClauses) > p->nClausesMax ); // count how many implications have each cost CostMax = p->nSimWords * 32 + 1; pCostCount = ABC_ALLOC( int, CostMax ); memset( pCostCount, 0, sizeof(int) * CostMax ); Vec_IntForEachEntry( p->vCosts, Cost, i ) { if ( Cost == -1 ) continue; assert( Cost < CostMax ); pCostCount[ Cost ]++; } assert( pCostCount[0] == 0 ); // select the bound on the cost (above this bound, implication will be included) nClauCount = 0; for ( c = CostMax - 1; c > 0; c-- ) { assert( pCostCount[c] >= 0 ); nClauCount += pCostCount[c]; if ( nClauCount >= p->nClausesMax ) break; } // collect implications with the given costs nClauCount = 0; Vec_IntForEachEntry( p->vCosts, Cost, i ) { if ( Cost >= c && nClauCount < p->nClausesMax ) { nClauCount++; continue; } Vec_IntWriteEntry( p->vCosts, i, -1 ); } ABC_FREE( pCostCount ); p->nClauses = nClauCount; if ( p->fVerbose ) printf( "Selected %d clauses. Cost range: [%d < %d < %d]\n", nClauCount, 1, c, CostMax ); return c; } /**Function************************************************************* Synopsis [Processes the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausRecordClause( Clu_Man_t * p, Dar_Cut_t * pCut, int iMint, int Cost ) { int i; for ( i = 0; i < (int)pCut->nLeaves; i++ ) Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pLeaves[i]], (iMint&(1<vClauses, Vec_IntSize(p->vLits) ); Vec_IntPush( p->vCosts, Cost ); } /**Function************************************************************* Synopsis [Processes the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausRecordClause2( Clu_Man_t * p, Aig_Cut_t * pCut, int iMint, int Cost ) { int i; for ( i = 0; i < (int)pCut->nFanins; i++ ) Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pFanins[i]], (iMint&(1<vClauses, Vec_IntSize(p->vLits) ); Vec_IntPush( p->vCosts, Cost ); } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausSmlNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj ) { unsigned * pSims; int i; pSims = Fra_ObjSim(pSeq, pObj->Id); for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ ) if ( pSims[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if implications holds.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausSmlNodesAreImp( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) { unsigned * pSimL, * pSimR; int k; pSimL = Fra_ObjSim(pSeq, pObj1->Id); pSimR = Fra_ObjSim(pSeq, pObj2->Id); for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) if ( pSimL[k] & ~pSimR[k] ) // !(Obj1 -> Obj2) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if implications holds.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausSmlNodesAreImpC( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 ) { unsigned * pSimL, * pSimR; int k; pSimL = Fra_ObjSim(pSeq, pObj1->Id); pSimR = Fra_ObjSim(pSeq, pObj2->Id); for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) if ( pSimL[k] & pSimR[k] ) return 0; return 1; } /**Function************************************************************* Synopsis [Processes the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausCollectLatchClauses( Clu_Man_t * p, Fra_Sml_t * pSeq ) { Aig_Obj_t * pObj1, * pObj2; unsigned * pSims1, * pSims2; int CostMax, i, k, nCountConst, nCountImps; nCountConst = nCountImps = 0; CostMax = p->nSimWords * 32; /* // add the property { Aig_Obj_t * pObj; int Lits[1]; pObj = Aig_ManCo( p->pAig, 0 ); Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 1 ); Vec_IntPush( p->vLits, Lits[0] ); Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); Vec_IntPush( p->vCosts, CostMax ); nCountConst++; // printf( "Added the target property to the set of clauses to be inductively checked.\n" ); } */ pSeq->nWordsPref = p->nSimWordsPref; Aig_ManForEachLoSeq( p->pAig, pObj1, i ) { pSims1 = Fra_ObjSim( pSeq, pObj1->Id ); if ( Fra_ClausSmlNodeIsConst( pSeq, pObj1 ) ) { Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); Vec_IntPush( p->vCosts, CostMax ); nCountConst++; continue; } Aig_ManForEachLoSeq( p->pAig, pObj2, k ) { pSims2 = Fra_ObjSim( pSeq, pObj2->Id ); if ( Fra_ClausSmlNodesAreImp( pSeq, pObj1, pObj2 ) ) { Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 0 ) ); Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); Vec_IntPush( p->vCosts, CostMax ); nCountImps++; continue; } if ( Fra_ClausSmlNodesAreImp( pSeq, pObj2, pObj1 ) ) { Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) ); Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 0 ) ); Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); Vec_IntPush( p->vCosts, CostMax ); nCountImps++; continue; } if ( Fra_ClausSmlNodesAreImpC( pSeq, pObj1, pObj2 ) ) { Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) ); Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) ); Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) ); Vec_IntPush( p->vCosts, CostMax ); nCountImps++; continue; } } if ( nCountConst + nCountImps > p->nClausesMax / 2 ) break; } pSeq->nWordsPref = 0; if ( p->fVerbose ) printf( "Collected %d register constants and %d one-hotness implications.\n", nCountConst, nCountImps ); p->nOneHots = nCountConst + nCountImps; p->nOneHotsProven = 0; return 0; } /**Function************************************************************* Synopsis [Processes the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausProcessClauses( Clu_Man_t * p, int fRefs ) { Aig_MmFixed_t * pMemCuts; // Aig_ManCut_t * pManCut; Fra_Sml_t * pComb, * pSeq; Aig_Obj_t * pObj; Dar_Cut_t * pCut; int Scores[16], uScores, i, k, j, nCuts = 0; abctime clk; // simulate the AIG clk = Abc_Clock(); // srand( 0xAABBAABB ); Aig_ManRandom(1); pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 ); if ( p->fTarget && pSeq->fNonConstOut ) { printf( "Property failed after sequential simulation!\n" ); Fra_SmlStop( pSeq ); return 0; } if ( p->fVerbose ) { ABC_PRT( "Sim-seq", Abc_Clock() - clk ); } clk = Abc_Clock(); if ( fRefs ) { Fra_ClausCollectLatchClauses( p, pSeq ); if ( p->fVerbose ) { ABC_PRT( "Lat-cla", Abc_Clock() - clk ); } } // generate cuts for all nodes, assign cost, and find best cuts clk = Abc_Clock(); pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 0, 1 ); // pManCut = Aig_ComputeCuts( p->pAig, 10, 4, 0, 1 ); if ( p->fVerbose ) { ABC_PRT( "Cuts ", Abc_Clock() - clk ); } // collect sequential info for each cut clk = Abc_Clock(); Aig_ManForEachNode( p->pAig, pObj, i ) Dar_ObjForEachCut( pObj, pCut, k ) if ( pCut->nLeaves > 1 ) { pCut->uTruth = Fra_ClausProcessClausesCut( p, pSeq, pCut, Scores ); // uScores = Fra_ClausProcessClausesCut2( p, pSeq, pCut, Scores ); // if ( uScores != pCut->uTruth ) // { // int x = 0; // } } if ( p->fVerbose ) { ABC_PRT( "Infoseq", Abc_Clock() - clk ); } Fra_SmlStop( pSeq ); // perform combinational simulation clk = Abc_Clock(); // srand( 0xAABBAABB ); Aig_ManRandom(1); pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref, 0 ); if ( p->fVerbose ) { ABC_PRT( "Sim-cmb", Abc_Clock() - clk ); } // collect combinational info for each cut clk = Abc_Clock(); Aig_ManForEachNode( p->pAig, pObj, i ) Dar_ObjForEachCut( pObj, pCut, k ) if ( pCut->nLeaves > 1 ) { nCuts++; uScores = Fra_ClausProcessClausesCut( p, pComb, pCut, Scores ); uScores &= ~pCut->uTruth; pCut->uTruth = 0; if ( uScores == 0 ) continue; // write the clauses for ( j = 0; j < (1<nLeaves); j++ ) if ( uScores & (1 << j) ) Fra_ClausRecordClause( p, pCut, j, Scores[j] ); } Fra_SmlStop( pComb ); Aig_MmFixedStop( pMemCuts, 0 ); // Aig_ManCutStop( pManCut ); if ( p->fVerbose ) { ABC_PRT( "Infocmb", Abc_Clock() - clk ); } if ( p->fVerbose ) printf( "Node = %5d. Non-triv cuts = %7d. Clauses = %6d. Clause per cut = %6.2f.\n", Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts ); if ( Vec_IntSize(p->vClauses) > p->nClausesMax ) Fra_ClausSelectClauses( p ); else p->nClauses = Vec_IntSize( p->vClauses ); return 1; } /**Function************************************************************* Synopsis [Processes the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausProcessClauses2( Clu_Man_t * p, int fRefs ) { // Aig_MmFixed_t * pMemCuts; Aig_ManCut_t * pManCut; Fra_Sml_t * pComb, * pSeq; Aig_Obj_t * pObj; Aig_Cut_t * pCut; int i, k, j, nCuts = 0; abctime clk; int ScoresSeq[1<<12], ScoresComb[1<<12]; assert( p->nLutSize < 13 ); // simulate the AIG clk = Abc_Clock(); // srand( 0xAABBAABB ); Aig_ManRandom(1); pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 ); if ( p->fTarget && pSeq->fNonConstOut ) { printf( "Property failed after sequential simulation!\n" ); Fra_SmlStop( pSeq ); return 0; } if ( p->fVerbose ) { //ABC_PRT( "Sim-seq", Abc_Clock() - clk ); } // perform combinational simulation clk = Abc_Clock(); // srand( 0xAABBAABB ); Aig_ManRandom(1); pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref, 0 ); if ( p->fVerbose ) { //ABC_PRT( "Sim-cmb", Abc_Clock() - clk ); } clk = Abc_Clock(); if ( fRefs ) { Fra_ClausCollectLatchClauses( p, pSeq ); if ( p->fVerbose ) { //ABC_PRT( "Lat-cla", Abc_Clock() - clk ); } } // generate cuts for all nodes, assign cost, and find best cuts clk = Abc_Clock(); // pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 0, 1 ); pManCut = Aig_ComputeCuts( p->pAig, p->nCutsMax, p->nLutSize, 0, p->fVerbose ); if ( p->fVerbose ) { //ABC_PRT( "Cuts ", Abc_Clock() - clk ); } // collect combinational info for each cut clk = Abc_Clock(); Aig_ManForEachNode( p->pAig, pObj, i ) { if ( pObj->Level > (unsigned)p->nLevels ) continue; Aig_ObjForEachCut( pManCut, pObj, pCut, k ) if ( pCut->nFanins > 1 ) { nCuts++; Fra_ClausProcessClausesCut3( p, pSeq, pCut, ScoresSeq ); Fra_ClausProcessClausesCut3( p, pComb, pCut, ScoresComb ); // write the clauses for ( j = 0; j < (1<nFanins); j++ ) if ( ScoresComb[j] != 0 && ScoresSeq[j] == 0 ) Fra_ClausRecordClause2( p, pCut, j, ScoresComb[j] ); } } Fra_SmlStop( pSeq ); Fra_SmlStop( pComb ); p->nCuts = nCuts; // Aig_MmFixedStop( pMemCuts, 0 ); Aig_ManCutStop( pManCut ); p->pAig->pManCuts = NULL; if ( p->fVerbose ) { printf( "Node = %5d. Cuts = %7d. Clauses = %6d. Clause/cut = %6.2f.\n", Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts ); ABC_PRT( "Processing sim-info to find candidate clauses (unoptimized)", Abc_Clock() - clk ); } // filter out clauses that are contained in the already proven clauses assert( p->nClauses == 0 ); p->nClauses = Vec_IntSize( p->vClauses ); if ( Vec_IntSize( p->vClausesProven ) > 0 ) { int RetValue, k, Beg; int End = -1; // Suppress "might be used uninitialized" int * pStart; // reset the solver if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); if ( p->pSatMain == NULL ) { printf( "Error: Main solver is unsat.\n" ); return -1; } // add the proven clauses Beg = 0; pStart = Vec_IntArray(p->vLitsProven); Vec_IntForEachEntry( p->vClausesProven, End, i ) { assert( End - Beg <= p->nLutSize ); // add the clause to all timeframes RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); if ( RetValue == 0 ) { printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); return -1; } Beg = End; } assert( End == Vec_IntSize(p->vLitsProven) ); // check the clauses Beg = 0; pStart = Vec_IntArray(p->vLits); Vec_IntForEachEntry( p->vClauses, End, i ) { assert( Vec_IntEntry( p->vCosts, i ) >= 0 ); assert( End - Beg <= p->nLutSize ); // check the clause for ( k = Beg; k < End; k++ ) pStart[k] = lit_neg( pStart[k] ); RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); for ( k = Beg; k < End; k++ ) pStart[k] = lit_neg( pStart[k] ); // the clause holds if ( RetValue == l_False ) { Vec_IntWriteEntry( p->vCosts, i, -1 ); p->nClauses--; } Beg = End; } assert( End == Vec_IntSize(p->vLits) ); if ( p->fVerbose ) printf( "Already proved clauses filtered out %d candidate clauses (out of %d).\n", Vec_IntSize(p->vClauses) - p->nClauses, Vec_IntSize(p->vClauses) ); } p->fFiltering = 0; if ( p->nClauses > p->nClausesMax ) { Fra_ClausSelectClauses( p ); p->fFiltering = 1; } return 1; } /**Function************************************************************* Synopsis [Converts AIG into the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausBmcClauses( Clu_Man_t * p ) { int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f; /* for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) printf( "%d ", p->vLits->pArray[i] ); printf( "\n" ); */ // add the clauses Counter = 0; // skip through the prefix variables if ( p->nPref ) { nLitsTot = p->nPref * 2 * p->pCnf->nVars; for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) p->vLits->pArray[i] += nLitsTot; } // go through the timeframes nLitsTot = 2 * p->pCnf->nVars; pStart = Vec_IntArray(p->vLits); for ( f = 0; f < p->nFrames; f++ ) { Beg = 0; Vec_IntForEachEntry( p->vClauses, End, i ) { if ( Vec_IntEntry( p->vCosts, i ) == -1 ) { Beg = End; continue; } assert( Vec_IntEntry( p->vCosts, i ) > 0 ); assert( End - Beg <= p->nLutSize ); for ( k = Beg; k < End; k++ ) pStart[k] = lit_neg( pStart[k] ); RetValue = sat_solver_solve( p->pSatBmc, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); for ( k = Beg; k < End; k++ ) pStart[k] = lit_neg( pStart[k] ); if ( RetValue != l_False ) { Beg = End; Vec_IntWriteEntry( p->vCosts, i, -1 ); Counter++; continue; } /* // add the clause RetValue = sat_solver_addclause( p->pSatBmc, pStart + Beg, pStart + End ); // assert( RetValue == 1 ); if ( RetValue == 0 ) { printf( "Error: Solver is UNSAT after adding BMC clauses.\n" ); return -1; } */ Beg = End; // simplify the solver if ( p->pSatBmc->qtail != p->pSatBmc->qhead ) { RetValue = sat_solver_simplify(p->pSatBmc); assert( RetValue != 0 ); assert( p->pSatBmc->qtail == p->pSatBmc->qhead ); } } // increment literals for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) p->vLits->pArray[i] += nLitsTot; } // return clauses back to normal nLitsTot = (p->nPref + p->nFrames) * nLitsTot; for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) p->vLits->pArray[i] -= nLitsTot; /* for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) printf( "%d ", p->vLits->pArray[i] ); printf( "\n" ); */ return Counter; } /**Function************************************************************* Synopsis [Cleans simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausSimInfoClean( Clu_Man_t * p ) { assert( p->pCnf->nVars <= Vec_PtrSize(p->vCexes) ); Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 ); p->nCexes = 0; } /**Function************************************************************* Synopsis [Reallocs simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausSimInfoRealloc( Clu_Man_t * p ) { assert( p->nCexes == p->nCexesAlloc ); Vec_PtrReallocSimInfo( p->vCexes ); Vec_PtrCleanSimInfo( p->vCexes, p->nCexesAlloc/32, 2 * p->nCexesAlloc/32 ); p->nCexesAlloc *= 2; } /**Function************************************************************* Synopsis [Records simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausSimInfoRecord( Clu_Man_t * p, int * pModel ) { int i; if ( p->nCexes == p->nCexesAlloc ) Fra_ClausSimInfoRealloc( p ); assert( p->nCexes < p->nCexesAlloc ); for ( i = 0; i < p->pCnf->nVars; i++ ) { if ( pModel[i] == l_True ) { assert( Abc_InfoHasBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes ) == 0 ); Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes ); } } p->nCexes++; } /**Function************************************************************* Synopsis [Uses the simulation info.] Description [Returns 1 if the simulation info disproved the clause.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausSimInfoCheck( Clu_Man_t * p, int * pLits, int nLits ) { unsigned * pSims[16], uWord; int nWords, iVar, i, w; for ( i = 0; i < nLits; i++ ) { iVar = lit_var(pLits[i]) - p->nFrames * p->pCnf->nVars; assert( iVar > 0 && iVar < p->pCnf->nVars ); pSims[i] = (unsigned *)Vec_PtrEntry( p->vCexes, iVar ); } nWords = p->nCexes / 32; for ( w = 0; w < nWords; w++ ) { uWord = ~(unsigned)0; for ( i = 0; i < nLits; i++ ) uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]); if ( uWord ) return 1; } if ( p->nCexes % 32 ) { uWord = ~(unsigned)0; for ( i = 0; i < nLits; i++ ) uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]); if ( uWord & Abc_InfoMask( p->nCexes % 32 ) ) return 1; } return 0; } /**Function************************************************************* Synopsis [Converts AIG into the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ClausInductiveClauses( Clu_Man_t * p ) { // Aig_Obj_t * pObjLi, * pObjLo; int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f, fFlag;//, Lits[2]; p->fFail = 0; // reset the solver if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 ); if ( p->pSatMain == NULL ) { printf( "Error: Main solver is unsat.\n" ); return -1; } Fra_ClausSimInfoClean( p ); /* // check if the property holds if ( Fra_ClausRunSat0( p ) ) printf( "Property holds without strengthening.\n" ); else printf( "Property does not hold without strengthening.\n" ); */ /* // add constant registers Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) if ( Aig_ObjFanin0(pObjLi) == Aig_ManConst1(p->pAig) ) { for ( k = 0; k < p->nFrames; k++ ) { Lits[0] = k * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObjLo->Id], Aig_ObjFaninC0(pObjLi) ); RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 ); if ( RetValue == 0 ) { printf( "Error: Solver is UNSAT after adding constant-register clauses.\n" ); return -1; } } } */ // add the proven clauses nLitsTot = 2 * p->pCnf->nVars; pStart = Vec_IntArray(p->vLitsProven); for ( f = 0; f < p->nFrames; f++ ) { Beg = 0; Vec_IntForEachEntry( p->vClausesProven, End, i ) { assert( End - Beg <= p->nLutSize ); // add the clause to all timeframes RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); if ( RetValue == 0 ) { printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); return -1; } Beg = End; } // increment literals for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ ) p->vLitsProven->pArray[i] += nLitsTot; } // return clauses back to normal nLitsTot = (p->nFrames) * nLitsTot; for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ ) p->vLitsProven->pArray[i] -= nLitsTot; /* // add the proven clauses nLitsTot = 2 * p->pCnf->nVars; pStart = Vec_IntArray(p->vLitsProven); Beg = 0; Vec_IntForEachEntry( p->vClausesProven, End, i ) { assert( End - Beg <= p->nLutSize ); // add the clause to all timeframes RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); if ( RetValue == 0 ) { printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); return -1; } Beg = End; } */ // add the clauses nLitsTot = 2 * p->pCnf->nVars; pStart = Vec_IntArray(p->vLits); for ( f = 0; f < p->nFrames; f++ ) { Beg = 0; Vec_IntForEachEntry( p->vClauses, End, i ) { if ( Vec_IntEntry( p->vCosts, i ) == -1 ) { Beg = End; continue; } assert( Vec_IntEntry( p->vCosts, i ) > 0 ); assert( End - Beg <= p->nLutSize ); // add the clause to all timeframes RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); if ( RetValue == 0 ) { printf( "Error: Solver is UNSAT after adding assumption clauses.\n" ); return -1; } Beg = End; } // increment literals for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) p->vLits->pArray[i] += nLitsTot; } // simplify the solver if ( p->pSatMain->qtail != p->pSatMain->qhead ) { RetValue = sat_solver_simplify(p->pSatMain); assert( RetValue != 0 ); assert( p->pSatMain->qtail == p->pSatMain->qhead ); } // check if the property holds if ( p->fTarget ) { if ( Fra_ClausRunSat0( p ) ) { if ( p->fVerbose ) printf( " Property holds. " ); } else { if ( p->fVerbose ) printf( " Property fails. " ); // return -2; p->fFail = 1; } } /* // add the property for the first K frames for ( i = 0; i < p->nFrames; i++ ) { Aig_Obj_t * pObj; int Lits[2]; // set the output literals pObj = Aig_ManCo(p->pAig, 0); Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 1 ); // add the clause RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 ); // assert( RetValue == 1 ); if ( RetValue == 0 ) { printf( "Error: Solver is UNSAT after adding property for the first K frames.\n" ); return -1; } } */ // simplify the solver if ( p->pSatMain->qtail != p->pSatMain->qhead ) { RetValue = sat_solver_simplify(p->pSatMain); assert( RetValue != 0 ); assert( p->pSatMain->qtail == p->pSatMain->qhead ); } // check the clause in the last timeframe Beg = 0; Counter = 0; Vec_IntForEachEntry( p->vClauses, End, i ) { if ( Vec_IntEntry( p->vCosts, i ) == -1 ) { Beg = End; continue; } assert( Vec_IntEntry( p->vCosts, i ) > 0 ); assert( End - Beg <= p->nLutSize ); if ( Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg) ) { fFlag = 1; // printf( "s-" ); Beg = End; Vec_IntWriteEntry( p->vCosts, i, -1 ); Counter++; continue; } else { fFlag = 0; // printf( "s?" ); } for ( k = Beg; k < End; k++ ) pStart[k] = lit_neg( pStart[k] ); RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); for ( k = Beg; k < End; k++ ) pStart[k] = lit_neg( pStart[k] ); // the problem is not solved if ( RetValue != l_False ) { // printf( "S- " ); // Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model.ptr + p->nFrames * p->pCnf->nVars ); Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model + p->nFrames * p->pCnf->nVars ); // RetValue = Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg); // assert( RetValue ); Beg = End; Vec_IntWriteEntry( p->vCosts, i, -1 ); Counter++; continue; } // printf( "S+ " ); // assert( !fFlag ); /* // add the clause RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End ); // assert( RetValue == 1 ); if ( RetValue == 0 ) { printf( "Error: Solver is UNSAT after adding proved clauses.\n" ); return -1; } */ Beg = End; // simplify the solver if ( p->pSatMain->qtail != p->pSatMain->qhead ) { RetValue = sat_solver_simplify(p->pSatMain); assert( RetValue != 0 ); assert( p->pSatMain->qtail == p->pSatMain->qhead ); } } // return clauses back to normal nLitsTot = p->nFrames * nLitsTot; for ( i = 0; i < Vec_IntSize(p->vLits); i++ ) p->vLits->pArray[i] -= nLitsTot; // if ( fFail ) // return -2; return Counter; } /**Function************************************************************* Synopsis [Converts AIG into the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Clu_Man_t * Fra_ClausAlloc( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fTarget, int fVerbose, int fVeryVerbose ) { Clu_Man_t * p; p = ABC_ALLOC( Clu_Man_t, 1 ); memset( p, 0, sizeof(Clu_Man_t) ); p->pAig = pAig; p->nFrames = nFrames; p->nPref = nPref; p->nClausesMax = nClausesMax; p->nLutSize = nLutSize; p->nLevels = nLevels; p->nCutsMax = nCutsMax; p->nBatches = nBatches; p->fStepUp = fStepUp; p->fTarget = fTarget; p->fVerbose = fVerbose; p->fVeryVerbose = fVeryVerbose; p->nSimWords = 512;//1024;//64; p->nSimFrames = 32;//8;//32; p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames; p->vLits = Vec_IntAlloc( 1<<14 ); p->vClauses = Vec_IntAlloc( 1<<12 ); p->vCosts = Vec_IntAlloc( 1<<12 ); p->vLitsProven = Vec_IntAlloc( 1<<14 ); p->vClausesProven= Vec_IntAlloc( 1<<12 ); p->nCexesAlloc = 1024; p->vCexes = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pAig)+1, p->nCexesAlloc/32 ); Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 ); return p; } /**Function************************************************************* Synopsis [Converts AIG into the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausFree( Clu_Man_t * p ) { if ( p->vCexes ) Vec_PtrFree( p->vCexes ); if ( p->vLits ) Vec_IntFree( p->vLits ); if ( p->vClauses ) Vec_IntFree( p->vClauses ); if ( p->vLitsProven ) Vec_IntFree( p->vLitsProven ); if ( p->vClausesProven ) Vec_IntFree( p->vClausesProven ); if ( p->vCosts ) Vec_IntFree( p->vCosts ); if ( p->pCnf ) Cnf_DataFree( p->pCnf ); if ( p->pSatMain ) sat_solver_delete( p->pSatMain ); if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Converts AIG into the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausAddToStorage( Clu_Man_t * p ) { int * pStart; int Beg, End, Counter, i, k; Beg = 0; Counter = 0; pStart = Vec_IntArray( p->vLits ); Vec_IntForEachEntry( p->vClauses, End, i ) { if ( Vec_IntEntry( p->vCosts, i ) == -1 ) { Beg = End; continue; } assert( Vec_IntEntry( p->vCosts, i ) > 0 ); assert( End - Beg <= p->nLutSize ); for ( k = Beg; k < End; k++ ) Vec_IntPush( p->vLitsProven, pStart[k] ); Vec_IntPush( p->vClausesProven, Vec_IntSize(p->vLitsProven) ); Beg = End; Counter++; if ( i < p->nOneHots ) p->nOneHotsProven++; } if ( p->fVerbose ) printf( "Added to storage %d proved clauses (including %d one-hot clauses)\n", Counter, p->nOneHotsProven ); Vec_IntClear( p->vClauses ); Vec_IntClear( p->vLits ); Vec_IntClear( p->vCosts ); p->nClauses = 0; p->fNothingNew = (int)(Counter == 0); } /**Function************************************************************* Synopsis [Converts AIG into the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausPrintIndClauses( Clu_Man_t * p ) { int Counters[9] = {0}; int * pStart; int Beg, End, i; Beg = 0; pStart = Vec_IntArray( p->vLitsProven ); Vec_IntForEachEntry( p->vClausesProven, End, i ) { if ( End - Beg >= 8 ) Counters[8]++; else Counters[End - Beg]++; //printf( "%d ", End-Beg ); Beg = End; } printf( "SUMMARY: Total proved clauses = %d. ", Vec_IntSize(p->vClausesProven) ); printf( "Clause per lit: " ); for ( i = 0; i < 8; i++ ) if ( Counters[i] ) printf( "%d=%d ", i, Counters[i] ); if ( Counters[8] ) printf( ">7=%d ", Counters[8] ); printf( "\n" ); } /**Function************************************************************* Synopsis [Writes the clauses into an AIGER file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Fra_ClausGetLiteral( Clu_Man_t * p, int * pVar2Id, int Lit ) { Aig_Obj_t * pLiteral; int NodeId = pVar2Id[ lit_var(Lit) ]; assert( NodeId >= 0 ); pLiteral = (Aig_Obj_t *)Aig_ManObj( p->pAig, NodeId )->pData; return Aig_NotCond( pLiteral, lit_sign(Lit) ); } /**Function************************************************************* Synopsis [Writes the clauses into an AIGER file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausWriteIndClauses( Clu_Man_t * p ) { extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); Aig_Man_t * pNew; Aig_Obj_t * pClause, * pLiteral; char * pName; int * pStart, * pVar2Id; int Beg, End, i, k; // create mapping from SAT vars to node IDs pVar2Id = ABC_ALLOC( int, p->pCnf->nVars ); memset( pVar2Id, 0xFF, sizeof(int) * p->pCnf->nVars ); for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) if ( p->pCnf->pVarNums[i] >= 0 ) { assert( p->pCnf->pVarNums[i] < p->pCnf->nVars ); pVar2Id[ p->pCnf->pVarNums[i] ] = i; } // start the manager pNew = Aig_ManDupWithoutPos( p->pAig ); // add the clauses Beg = 0; pStart = Vec_IntArray( p->vLitsProven ); Vec_IntForEachEntry( p->vClausesProven, End, i ) { pClause = Fra_ClausGetLiteral( p, pVar2Id, pStart[Beg] ); for ( k = Beg + 1; k < End; k++ ) { pLiteral = Fra_ClausGetLiteral( p, pVar2Id, pStart[k] ); pClause = Aig_Or( pNew, pClause, pLiteral ); } Aig_ObjCreateCo( pNew, pClause ); Beg = End; } ABC_FREE( pVar2Id ); Aig_ManCleanup( pNew ); pName = Ioa_FileNameGenericAppend( p->pAig->pName, "_care.aig" ); printf( "Care one-hotness clauses will be written into file \"%s\".\n", pName ); Ioa_WriteAiger( pNew, pName, 0, 1 ); Aig_ManStop( pNew ); } /**Function************************************************************* Synopsis [Checks if the clause holds using the given simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausEstimateCoverageOne( Fra_Sml_t * pSim, int * pLits, int nLits, int * pVar2Id, unsigned * pResult ) { unsigned * pSims[16]; int iVar, i, w; for ( i = 0; i < nLits; i++ ) { iVar = lit_var(pLits[i]); pSims[i] = Fra_ObjSim( pSim, pVar2Id[iVar] ); } for ( w = 0; w < pSim->nWordsTotal; w++ ) { pResult[w] = ~(unsigned)0; for ( i = 0; i < nLits; i++ ) pResult[w] &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]); } } /**Function************************************************************* Synopsis [Estimates the coverage of state space by clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClausEstimateCoverage( Clu_Man_t * p ) { int nCombSimWords = (1<<11); Fra_Sml_t * pComb; unsigned * pResultTot, * pResultOne; int nCovered, Beg, End, i, w; int * pStart, * pVar2Id; abctime clk = Abc_Clock(); // simulate the circuit with nCombSimWords * 32 = 64K patterns // srand( 0xAABBAABB ); Aig_ManRandom(1); pComb = Fra_SmlSimulateComb( p->pAig, nCombSimWords, 0 ); // create mapping from SAT vars to node IDs pVar2Id = ABC_ALLOC( int, p->pCnf->nVars ); memset( pVar2Id, 0, sizeof(int) * p->pCnf->nVars ); for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) if ( p->pCnf->pVarNums[i] >= 0 ) { assert( p->pCnf->pVarNums[i] < p->pCnf->nVars ); pVar2Id[ p->pCnf->pVarNums[i] ] = i; } // get storage for one assignment and all assignments assert( Aig_ManCoNum(p->pAig) > 2 ); pResultOne = Fra_ObjSim( pComb, Aig_ManCo(p->pAig, 0)->Id ); pResultTot = Fra_ObjSim( pComb, Aig_ManCo(p->pAig, 1)->Id ); // start the OR of don't-cares for ( w = 0; w < nCombSimWords; w++ ) pResultTot[w] = 0; // check clauses Beg = 0; pStart = Vec_IntArray( p->vLitsProven ); Vec_IntForEachEntry( p->vClausesProven, End, i ) { Fra_ClausEstimateCoverageOne( pComb, pStart + Beg, End-Beg, pVar2Id, pResultOne ); Beg = End; for ( w = 0; w < nCombSimWords; w++ ) pResultTot[w] |= pResultOne[w]; } // count the total number of patterns contained in the don't-care nCovered = 0; for ( w = 0; w < nCombSimWords; w++ ) nCovered += Aig_WordCountOnes( pResultTot[w] ); Fra_SmlStop( pComb ); ABC_FREE( pVar2Id ); // print the result printf( "Care states ratio = %f. ", 1.0 * (nCombSimWords * 32 - nCovered) / (nCombSimWords * 32) ); printf( "(%d out of %d patterns) ", nCombSimWords * 32 - nCovered, nCombSimWords * 32 ); ABC_PRT( "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Converts AIG into the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose ) { Clu_Man_t * p; abctime clk, clkTotal = Abc_Clock(), clkInd; int b, Iter, Counter, nPrefOld; int nClausesBeg = 0; // create the manager p = Fra_ClausAlloc( pAig, nFrames, nPref, nClausesMax, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fTarget, fVerbose, fVeryVerbose ); if ( p->fVerbose ) { printf( "PARAMETERS: Frames = %d. Pref = %d. Clauses max = %d. Cut size = %d.\n", nFrames, nPref, nClausesMax, nLutSize ); printf( "Level max = %d. Cuts max = %d. Batches = %d. Increment cut size = %s.\n", nLevels, nCutsMax, nBatches, fStepUp? "yes":"no" ); //ABC_PRT( "Sim-seq", Abc_Clock() - clk ); } assert( !p->fTarget || Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig) == 1 ); clk = Abc_Clock(); // derive CNF // if ( p->fTarget ) // p->pAig->nRegs++; p->pCnf = Cnf_DeriveSimple( p->pAig, Aig_ManCoNum(p->pAig) ); // if ( p->fTarget ) // p->pAig->nRegs--; if ( fVerbose ) { //ABC_PRT( "CNF ", Abc_Clock() - clk ); } // check BMC clk = Abc_Clock(); p->pSatBmc = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nPref + p->nFrames, 1 ); if ( p->pSatBmc == NULL ) { printf( "Error: BMC solver is unsat.\n" ); Fra_ClausFree( p ); return 1; } if ( p->fTarget && !Fra_ClausRunBmc( p ) ) { printf( "Problem fails the base case after %d frame expansion.\n", p->nPref + p->nFrames ); Fra_ClausFree( p ); return 1; } if ( fVerbose ) { //ABC_PRT( "SAT-bmc", Abc_Clock() - clk ); } // start the SAT solver clk = Abc_Clock(); p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 ); if ( p->pSatMain == NULL ) { printf( "Error: Main solver is unsat.\n" ); Fra_ClausFree( p ); return 1; } for ( b = 0; b < p->nBatches; b++ ) { // if ( fVerbose ) printf( "*** BATCH %d: ", b+1 ); if ( b && p->nLutSize < 12 && (!p->fFiltering || p->fNothingNew || p->fStepUp) ) p->nLutSize++; printf( "Using %d-cuts.\n", p->nLutSize ); // try solving without additional clauses if ( p->fTarget && Fra_ClausRunSat( p ) ) { printf( "Problem is inductive without strengthening.\n" ); Fra_ClausFree( p ); return 1; } if ( fVerbose ) { // ABC_PRT( "SAT-ind", Abc_Clock() - clk ); } // collect the candidate inductive clauses using 4-cuts clk = Abc_Clock(); nPrefOld = p->nPref; p->nPref = 0; p->nSimWordsPref = 0; // Fra_ClausProcessClauses( p, fRefs ); Fra_ClausProcessClauses2( p, fRefs ); p->nPref = nPrefOld; p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames; nClausesBeg = p->nClauses; //ABC_PRT( "Clauses", Abc_Clock() - clk ); // check clauses using BMC if ( fBmc ) { clk = Abc_Clock(); Counter = Fra_ClausBmcClauses( p ); p->nClauses -= Counter; if ( fVerbose ) { printf( "BMC disproved %d clauses. ", Counter ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // prove clauses inductively clkInd = clk = Abc_Clock(); Counter = 1; for ( Iter = 0; Counter > 0; Iter++ ) { if ( fVerbose ) printf( "Iter %3d : Begin = %5d. ", Iter, p->nClauses ); Counter = Fra_ClausInductiveClauses( p ); if ( Counter > 0 ) p->nClauses -= Counter; if ( fVerbose ) { printf( "End = %5d. Exs = %5d. ", p->nClauses, p->nCexes ); // printf( "\n" ); ABC_PRT( "Time", Abc_Clock() - clk ); } clk = Abc_Clock(); } // add proved clauses to storage Fra_ClausAddToStorage( p ); // report the results if ( p->fTarget ) { if ( Counter == -1 ) printf( "Fra_Claus(): Internal error. " ); else if ( p->fFail ) printf( "Property FAILS during refinement. " ); else printf( "Property HOLDS inductively after strengthening. " ); ABC_PRT( "Time ", Abc_Clock() - clkTotal ); if ( !p->fFail ) break; } else { printf( "Finished proving inductive clauses. " ); ABC_PRT( "Time ", Abc_Clock() - clkTotal ); } } // verify the computed interpolant Fra_InvariantVerify( pAig, nFrames, p->vClausesProven, p->vLitsProven ); // printf( "THIS COMMAND IS KNOWN TO HAVE A BUG!\n" ); // if ( !p->fTarget && p->fVerbose ) if ( p->fVerbose ) { Fra_ClausPrintIndClauses( p ); Fra_ClausEstimateCoverage( p ); } if ( !p->fTarget ) { Fra_ClausWriteIndClauses( p ); } /* // print the statistic into a file { FILE * pTable; assert( p->nBatches == 1 ); pTable = fopen( "stats.txt", "a+" ); fprintf( pTable, "%s ", pAig->pName ); fprintf( pTable, "%d ", Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig) ); fprintf( pTable, "%d ", Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig) ); fprintf( pTable, "%d ", Aig_ManRegNum(pAig) ); fprintf( pTable, "%d ", Aig_ManNodeNum(pAig) ); fprintf( pTable, "%d ", p->nCuts ); fprintf( pTable, "%d ", nClausesBeg ); fprintf( pTable, "%d ", p->nClauses ); fprintf( pTable, "%d ", Iter ); fprintf( pTable, "%.2f ", (float)(clkInd-clkTotal)/(float)(CLOCKS_PER_SEC) ); fprintf( pTable, "%.2f ", (float)(Abc_Clock()-clkInd)/(float)(CLOCKS_PER_SEC) ); fprintf( pTable, "%.2f ", (float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC) ); fprintf( pTable, "\n" ); fclose( pTable ); } */ // clean the manager Fra_ClausFree( p ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraCnf.c000066400000000000000000000216771300674244400233110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraCnf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraCnf.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_AddClausesMux( Fra_Man_t * p, Aig_Obj_t * pNode ) { Aig_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; assert( !Aig_IsComplement( pNode ) ); assert( Aig_ObjIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the variable numbers VarF = Fra_ObjSatNum(pNode); VarI = Fra_ObjSatNum(pNodeI); VarT = Fra_ObjSatNum(Aig_Regular(pNodeT)); VarE = Fra_ObjSatNum(Aig_Regular(pNodeE)); // get the complementation flags fCompT = Aig_IsComplement(pNodeT); fCompE = Aig_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 Fra_AddClausesSuper( Fra_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper ) { Aig_Obj_t * pFanin; int * pLits, nLits, RetValue, i; assert( !Aig_IsComplement(pNode) ); assert( Aig_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( Aig_Obj_t *, vSuper, pFanin, i ) { pLits[0] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); pLits[1] = toLitCond(Fra_ObjSatNum(pNode), 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); } // add A & B => C or !A + !B + C Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) pLits[i] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); pLits[nLits-1] = toLitCond(Fra_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 Fra_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) { // if the new node is complemented or a PI, another gate begins if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || (!fFirst && Aig_ObjRefs(pObj) > 1) || (fUseMuxes && Aig_ObjIsMuxType(pObj)) ) { Vec_PtrPushUnique( vSuper, pObj ); return; } // go through the branches Fra_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); Fra_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Fra_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes ) { Vec_Ptr_t * vSuper; assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCi(pObj) ); vSuper = Vec_PtrAlloc( 4 ); Fra_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); return vSuper; } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ObjAddToFrontier( Fra_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) { assert( !Aig_IsComplement(pObj) ); if ( Fra_ObjSatNum(pObj) ) return; assert( Fra_ObjSatNum(pObj) == 0 ); assert( Fra_ObjFaninVec(pObj) == NULL ); if ( Aig_ObjIsConst1(pObj) ) return; Fra_ObjSetSatNum( pObj, p->nSatVars++ ); if ( Aig_ObjIsNode(pObj) ) Vec_PtrPush( vFrontier, pObj ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) { Vec_Ptr_t * vFrontier, * vFanins; Aig_Obj_t * pNode, * pFanin; int i, k, fUseMuxes = 1; assert( pOld || pNew ); // quit if CNF is ready if ( (!pOld || Fra_ObjFaninVec(pOld)) && (!pNew || Fra_ObjFaninVec(pNew)) ) return; // start the frontier vFrontier = Vec_PtrAlloc( 100 ); if ( pOld ) Fra_ObjAddToFrontier( p, pOld, vFrontier ); if ( pNew ) Fra_ObjAddToFrontier( p, pNew, vFrontier ); // explore nodes in the frontier Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i ) { // create the supergate assert( Fra_ObjSatNum(pNode) ); assert( Fra_ObjFaninVec(pNode) == NULL ); if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) { vFanins = Vec_PtrAlloc( 4 ); Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, k ) Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); Fra_AddClausesMux( p, pNode ); } else { vFanins = Fra_CollectSuper( pNode, fUseMuxes ); Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, k ) Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); Fra_AddClausesSuper( p, pNode, vFanins ); } assert( Vec_PtrSize(vFanins) > 1 ); Fra_ObjSetFaninVec( pNode, vFanins ); } Vec_PtrFree( vFrontier ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraCore.c000066400000000000000000000410121300674244400234540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraCore.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* Speculating reduction in the sequential case leads to an interesting situation when a counter-ex may not refine any classes. This happens for non-constant equivalence classes. In such cases the representative of the class (proved by simulation to be non-constant) may be reduced to a constant during the speculative reduction. The fraig-representative of this representative node is a constant node, even though this is a non-constant class. Experiments have shown that this situation happens very often at the beginning of the refinement iteration when there are many spurious candidate equivalence classes (especially if heavy-duty simulatation of BMC was node used at the beginning). As a result, the SAT solver run may return a counter-ex that distinguishes the given representative node from the constant-1 node but this counter-ex does not distinguish the nodes in the non-costant class... This is why there is no check of refinement after a counter-ex in the sequential case. */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reports the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_FraigMiterStatus( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pChild; int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; if ( p->pData ) return 0; Aig_ManForEachPoSeq( p, pObj, i ) { pChild = Aig_ObjChild0(pObj); // check if the output is constant 0 if ( pChild == Aig_ManConst0(p) ) { CountConst0++; continue; } // check if the output is constant 1 if ( pChild == Aig_ManConst1(p) ) { CountNonConst0++; continue; } // check if the output is a primary input if ( Aig_ObjIsCi(Aig_Regular(pChild)) && Aig_ObjCioId(Aig_Regular(pChild)) < p->nTruePis ) { CountNonConst0++; continue; } // check if the output can be not constant 0 if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) { CountNonConst0++; continue; } CountUndecided++; } /* if ( p->pParams->fVerbose ) { printf( "Miter has %d outputs. ", Aig_ManCoNum(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 [Reports the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_FraigMiterAssertedOutput( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pChild; int i; Aig_ManForEachPoSeq( p, pObj, i ) { pChild = Aig_ObjChild0(pObj); // check if the output is constant 0 if ( pChild == Aig_ManConst0(p) ) continue; // check if the output is constant 1 if ( pChild == Aig_ManConst1(p) ) return i; // check if the output can be not constant 0 if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) return i; } return -1; } /**Function************************************************************* Synopsis [Write speculative miter for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fra_FraigNodeSpeculate( Fra_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pObjFraig, Aig_Obj_t * pObjReprFraig ) { static int Counter = 0; char FileName[20]; Aig_Man_t * pTemp; Aig_Obj_t * pNode; int i; // create manager with the logic for these two nodes pTemp = Aig_ManExtractMiter( p->pManFraig, pObjFraig, pObjReprFraig ); // dump the logic into a file sprintf( FileName, "aig\\%03d.blif", ++Counter ); Aig_ManDumpBlif( pTemp, FileName, NULL, NULL ); printf( "Speculation cone with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(pTemp), FileName ); // clean up Aig_ManStop( pTemp ); Aig_ManForEachObj( p->pManFraig, pNode, i ) pNode->pData = p; } /**Function************************************************************* Synopsis [Verifies the generated counter-ex.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_FraigVerifyCounterEx( Fra_Man_t * p, Vec_Int_t * vCex ) { Aig_Obj_t * pObj, ** ppClass; int i, c; assert( Aig_ManCiNum(p->pManAig) == Vec_IntSize(vCex) ); // make sure the input pattern is not used Aig_ManForEachObj( p->pManAig, pObj, i ) assert( !pObj->fMarkB ); // simulate the cex through the AIG Aig_ManConst1(p->pManAig)->fMarkB = 1; Aig_ManForEachCi( p->pManAig, pObj, i ) pObj->fMarkB = Vec_IntEntry(vCex, i); Aig_ManForEachNode( p->pManAig, pObj, i ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); Aig_ManForEachCo( p->pManAig, pObj, i ) pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); // check if the classes hold Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) { if ( pObj->fPhase != pObj->fMarkB ) printf( "The node %d is not constant under cex!\n", pObj->Id ); } Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i ) { for ( c = 1; ppClass[c]; c++ ) if ( (ppClass[0]->fPhase ^ ppClass[c]->fPhase) != (ppClass[0]->fMarkB ^ ppClass[c]->fMarkB) ) printf( "The nodes %d and %d are not equal under cex!\n", ppClass[0]->Id, ppClass[c]->Id ); // for ( c = 0; ppClass[c]; c++ ) // if ( Fra_ObjFraig(ppClass[c],p->pPars->nFramesK) == Aig_ManConst1(p->pManFraig) ) // printf( "A member of non-constant class has a constant repr!\n" ); } // clean the simulation pattern Aig_ManForEachObj( p->pManAig, pObj, i ) pObj->fMarkB = 0; } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fra_FraigNode( Fra_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; int RetValue; assert( !Aig_IsComplement(pObj) ); // get representative of this class pObjRepr = Fra_ClassObjRepr( pObj ); if ( pObjRepr == NULL || // this is a unique node (!p->pPars->fDoSparse && pObjRepr == Aig_ManConst1(p->pManAig)) ) // this is a sparse node return; // get the fraiged node pObjFraig = Fra_ObjFraig( pObj, p->pPars->nFramesK ); // get the fraiged representative pObjReprFraig = Fra_ObjFraig( pObjRepr, p->pPars->nFramesK ); // if the fraiged nodes are the same, return if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) { p->nSatCallsSkipped++; return; } assert( p->pPars->nFramesK || Aig_Regular(pObjFraig) != Aig_ManConst1(p->pManFraig) ); // if they are proved different, the c-ex will be in p->pPatWords RetValue = Fra_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); if ( RetValue == 1 ) // proved equivalent { // if ( p->pPars->fChoicing ) // Aig_ObjCreateRepr( p->pManFraig, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); // the nodes proved equal pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 ); return; } if ( RetValue == -1 ) // failed { if ( p->vTimeouts == NULL ) p->vTimeouts = Vec_PtrAlloc( 100 ); Vec_PtrPush( p->vTimeouts, pObj ); if ( !p->pPars->fSpeculate ) return; assert( 0 ); // speculate p->nSpeculs++; pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 ); Fra_FraigNodeSpeculate( p, pObj, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); return; } // disprove the nodes p->pCla->fRefinement = 1; // if we do not include the node into those disproved, we may end up // merging this node with another representative, for which proof has timed out if ( p->vTimeouts ) Vec_PtrPush( p->vTimeouts, pObj ); // verify that the counter-example satisfies all the constraints // if ( p->vCex ) // Fra_FraigVerifyCounterEx( p, p->vCex ); // simulate the counter-example and return the Fraig node Fra_SmlResimulate( p ); if ( p->pManFraig->pData ) return; if ( !p->pPars->nFramesK && Fra_ClassObjRepr(pObj) == pObjRepr ) printf( "Fra_FraigNode(): Error in class refinement!\n" ); assert( p->pPars->nFramesK || Fra_ClassObjRepr(pObj) != pObjRepr ); } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_FraigSweep( Fra_Man_t * p ) { // Bar_Progress_t * pProgress = NULL; Aig_Obj_t * pObj, * pObjNew; int i, Pos = 0; int nBTracksOld; // fraig latch outputs Aig_ManForEachLoSeq( p->pManAig, pObj, i ) { Fra_FraigNode( p, pObj ); if ( p->pPars->fUseImps ) Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos ); } if ( p->pPars->fLatchCorr ) return; // fraig internal nodes // if ( !p->pPars->fDontShowBar ) // pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pManAig) ); nBTracksOld = p->pPars->nBTLimitNode; Aig_ManForEachNode( p->pManAig, pObj, i ) { // if ( pProgress ) // Bar_ProgressUpdate( pProgress, i, NULL ); // derive and remember the new fraig node pObjNew = Aig_And( p->pManFraig, Fra_ObjChild0Fra(pObj,p->pPars->nFramesK), Fra_ObjChild1Fra(pObj,p->pPars->nFramesK) ); Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjNew ); Aig_Regular(pObjNew)->pData = p; // quit if simulation detected a counter-example for a PO if ( p->pManFraig->pData ) continue; // if ( Aig_SupportSize(p->pManAig,pObj) > 16 ) // continue; // perform fraiging if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax ) p->pPars->nBTLimitNode = 5; Fra_FraigNode( p, pObj ); if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax ) p->pPars->nBTLimitNode = nBTracksOld; // check implications if ( p->pPars->fUseImps ) Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos ); } // if ( pProgress ) // Bar_ProgressStop( pProgress ); // try to prove the outputs of the miter p->nNodesMiter = Aig_ManNodeNum(p->pManFraig); // Fra_MiterStatus( p->pManFraig ); // if ( p->pPars->fProve && p->pManFraig->pData == NULL ) // Fra_MiterProve( p ); // compress implications after processing all of them if ( p->pPars->fUseImps ) Fra_ImpCompactArray( p->pCla->vImps ); } /**Function************************************************************* Synopsis [Performs fraiging of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars ) { Fra_Man_t * p; Aig_Man_t * pManAigNew; abctime clk; if ( Aig_ManNodeNum(pManAig) == 0 ) return Aig_ManDupOrdered(pManAig); clk = Abc_Clock(); p = Fra_ManStart( pManAig, pPars ); p->pManFraig = Fra_ManPrepareComb( p ); p->pSml = Fra_SmlStart( pManAig, 0, 1, pPars->nSimWords ); Fra_SmlSimulate( p, 0 ); // if ( p->pPars->fChoicing ) // Aig_ManReprStart( p->pManFraig, Aig_ManObjNumMax(p->pManAig) ); // collect initial states p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); p->nNodesBeg = Aig_ManNodeNum(pManAig); p->nRegsBeg = Aig_ManRegNum(pManAig); // perform fraig sweep if ( p->pPars->fVerbose ) Fra_ClassesPrint( p->pCla, 1 ); Fra_FraigSweep( p ); // call back the procedure to check implications if ( pManAig->pImpFunc ) pManAig->pImpFunc( p, pManAig->pImpData ); // no need to filter one-hot clauses because they satisfy base case by construction // finalize the fraiged manager Fra_ManFinalizeComb( p ); if ( p->pPars->fChoicing ) { abctime clk2 = Abc_Clock(); Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); pManAigNew = Aig_ManDupRepr( p->pManAig, 1 ); Aig_ManReprStart( pManAigNew, Aig_ManObjNumMax(pManAigNew) ); Aig_ManTransferRepr( pManAigNew, p->pManAig ); Aig_ManMarkValidChoices( pManAigNew ); Aig_ManStop( p->pManFraig ); p->pManFraig = NULL; p->timeTrav += Abc_Clock() - clk2; } else { Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); Aig_ManCleanup( p->pManFraig ); pManAigNew = p->pManFraig; p->pManFraig = NULL; } p->timeTotal = Abc_Clock() - clk; // collect final stats p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); p->nNodesEnd = Aig_ManNodeNum(pManAigNew); p->nRegsEnd = Aig_ManRegNum(pManAigNew); Fra_ManStop( p ); return pManAigNew; } /**Function************************************************************* Synopsis [Performs choicing of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax ) { Fra_Par_t Pars, * pPars = &Pars; Fra_ParamsDefault( pPars ); pPars->nBTLimitNode = nConfMax; pPars->fChoicing = 1; pPars->fDoSparse = 1; pPars->fSpeculate = 0; pPars->fProve = 0; pPars->fVerbose = 0; pPars->fDontShowBar = 1; pPars->nLevelMax = nLevelMax; return Fra_FraigPerform( pManAig, pPars ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve ) { Aig_Man_t * pFraig; Fra_Par_t Pars, * pPars = &Pars; Fra_ParamsDefault( pPars ); pPars->nBTLimitNode = nConfMax; pPars->fChoicing = 0; pPars->fDoSparse = 1; pPars->fSpeculate = 0; pPars->fProve = fProve; pPars->fVerbose = 0; pPars->fDontShowBar = 1; pFraig = Fra_FraigPerform( pManAig, pPars ); return pFraig; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraHot.c000066400000000000000000000365201300674244400233260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraHot.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Computing and using one-hotness conditions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraHot.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Fra_RegToLit( int n, int c ) { return c? -n-1 : n+1; } static inline int Fra_LitReg( int n ) { return (n>0)? n-1 : -n-1; } static inline int Fra_LitSign( int n ) { return (n<0); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_OneHotNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj ) { unsigned * pSims; int i; pSims = Fra_ObjSim(pSeq, pObj->Id); for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ ) if ( pSims[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation infos are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_OneHotNodesAreEqual( Fra_Sml_t * pSeq, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { unsigned * pSims0, * pSims1; int i; pSims0 = Fra_ObjSim(pSeq, pObj0->Id); pSims1 = Fra_ObjSim(pSeq, pObj1->Id); for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ ) if ( pSims0[i] != pSims1[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if implications holds.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_OneHotNodesAreClause( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2, int fCompl1, int fCompl2 ) { unsigned * pSim1, * pSim2; int k; pSim1 = Fra_ObjSim(pSeq, pObj1->Id); pSim2 = Fra_ObjSim(pSeq, pObj2->Id); if ( fCompl1 && fCompl2 ) { for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) if ( pSim1[k] & pSim2[k] ) return 0; } else if ( fCompl1 ) { for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) if ( pSim1[k] & ~pSim2[k] ) return 0; } else if ( fCompl2 ) { for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ ) if ( ~pSim1[k] & pSim2[k] ) return 0; } else assert( 0 ); return 1; } /**Function************************************************************* Synopsis [Computes one-hot implications.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim ) { int fSkipConstEqu = 1; Vec_Int_t * vOneHots; Aig_Obj_t * pObj1, * pObj2; int i, k; int nTruePis = Aig_ManCiNum(pSim->pAig) - Aig_ManRegNum(pSim->pAig); assert( pSim->pAig == p->pManAig ); vOneHots = Vec_IntAlloc( 100 ); Aig_ManForEachLoSeq( pSim->pAig, pObj1, i ) { if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj1) ) continue; assert( i-nTruePis >= 0 ); // Aig_ManForEachLoSeq( pSim->pAig, pObj2, k ) // Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vPis, pObj2, k, Aig_ManCiNum(p)-Aig_ManRegNum(p) ) Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vCis, pObj2, k, i+1 ) { if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj2) ) continue; if ( fSkipConstEqu && Fra_OneHotNodesAreEqual( pSim, pObj1, pObj2 ) ) continue; assert( k-nTruePis >= 0 ); if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 1 ) ) { Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) ); Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) ); continue; } if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 0, 1 ) ) { Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 0) ); Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) ); continue; } if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 0 ) ) { Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) ); Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 0) ); continue; } } } return vOneHots; } /**Function************************************************************* Synopsis [Assumes one-hot implications in the SAT solver.] Description [] SideEffects [] SeeAlso [] **********************************************************************/ void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots ) { Aig_Obj_t * pObj1, * pObj2; int i, Out1, Out2, pLits[2]; int nPiNum = Aig_ManCiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); assert( p->pPars->nFramesK == 1 ); // add to only one frame for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) { Out1 = Vec_IntEntry( vOneHots, i ); Out2 = Vec_IntEntry( vOneHots, i+1 ); if ( Out1 == 0 && Out2 == 0 ) continue; pObj1 = Aig_ManCi( p->pManFraig, nPiNum + Fra_LitReg(Out1) ); pObj2 = Aig_ManCi( p->pManFraig, nPiNum + Fra_LitReg(Out2) ); pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), Fra_LitSign(Out1) ); pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), Fra_LitSign(Out2) ); // add constraint to solver if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) ) { printf( "Fra_OneHotAssume(): Adding clause makes SAT solver unsat.\n" ); sat_solver_delete( p->pSat ); p->pSat = NULL; return; } } } /**Function************************************************************* Synopsis [Checks one-hot implications.] Description [] SideEffects [] SeeAlso [] **********************************************************************/ void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots ) { Aig_Obj_t * pObj1, * pObj2; int RetValue, i, Out1, Out2; int nTruePos = Aig_ManCoNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) { Out1 = Vec_IntEntry( vOneHots, i ); Out2 = Vec_IntEntry( vOneHots, i+1 ); if ( Out1 == 0 && Out2 == 0 ) continue; pObj1 = Aig_ManCo( p->pManFraig, nTruePos + Fra_LitReg(Out1) ); pObj2 = Aig_ManCo( p->pManFraig, nTruePos + Fra_LitReg(Out2) ); RetValue = Fra_NodesAreClause( p, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) ); if ( RetValue != 1 ) { p->pCla->fRefinement = 1; if ( RetValue == 0 ) Fra_SmlResimulate( p ); if ( Vec_IntEntry(vOneHots, i) != 0 ) printf( "Fra_OneHotCheck(): Clause is not refined!\n" ); assert( Vec_IntEntry(vOneHots, i) == 0 ); } } } /**Function************************************************************* Synopsis [Removes those implications that no longer hold.] Description [Returns 1 if refinement has happened.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots ) { Aig_Obj_t * pObj1, * pObj2; int i, Out1, Out2, RetValue = 0; int nPiNum = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); assert( p->pSml->pAig == p->pManAig ); for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) { Out1 = Vec_IntEntry( vOneHots, i ); Out2 = Vec_IntEntry( vOneHots, i+1 ); if ( Out1 == 0 && Out2 == 0 ) continue; // get the corresponding nodes pObj1 = Aig_ManCi( p->pManAig, nPiNum + Fra_LitReg(Out1) ); pObj2 = Aig_ManCi( p->pManAig, nPiNum + Fra_LitReg(Out2) ); // check if implication holds using this simulation info if ( !Fra_OneHotNodesAreClause( p->pSml, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) ) ) { Vec_IntWriteEntry( vOneHots, i, 0 ); Vec_IntWriteEntry( vOneHots, i+1, 0 ); RetValue = 1; } } return RetValue; } /**Function************************************************************* Synopsis [Removes those implications that no longer hold.] Description [Returns 1 if refinement has happened.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots ) { int i, Out1, Out2, Counter = 0; for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) { Out1 = Vec_IntEntry( vOneHots, i ); Out2 = Vec_IntEntry( vOneHots, i+1 ); if ( Out1 == 0 && Out2 == 0 ) continue; Counter++; } return Counter; } /**Function************************************************************* Synopsis [Estimates the coverage of state space by clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots ) { int nSimWords = (1<<14); int nRegs = Aig_ManRegNum(p->pManAig); Vec_Ptr_t * vSimInfo; unsigned * pSim1, * pSim2, * pSimTot; int i, w, Out1, Out2, nCovered, Counter = 0; abctime clk = Abc_Clock(); // generate random sim-info at register outputs vSimInfo = Vec_PtrAllocSimInfo( nRegs + 1, nSimWords ); // srand( 0xAABBAABB ); Aig_ManRandom(1); for ( i = 0; i < nRegs; i++ ) { pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, i ); for ( w = 0; w < nSimWords; w++ ) pSim1[w] = Fra_ObjRandomSim(); } pSimTot = (unsigned *)Vec_PtrEntry( vSimInfo, nRegs ); // collect simulation info memset( pSimTot, 0, sizeof(unsigned) * nSimWords ); for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) { Out1 = Vec_IntEntry( vOneHots, i ); Out2 = Vec_IntEntry( vOneHots, i+1 ); if ( Out1 == 0 && Out2 == 0 ) continue; //printf( "(%c%d,%c%d) ", //Fra_LitSign(Out1)? '-': '+', Fra_LitReg(Out1), //Fra_LitSign(Out2)? '-': '+', Fra_LitReg(Out2) ); Counter++; pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out1) ); pSim2 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out2) ); if ( Fra_LitSign(Out1) && Fra_LitSign(Out2) ) for ( w = 0; w < nSimWords; w++ ) pSimTot[w] |= pSim1[w] & pSim2[w]; else if ( Fra_LitSign(Out1) ) for ( w = 0; w < nSimWords; w++ ) pSimTot[w] |= pSim1[w] & ~pSim2[w]; else if ( Fra_LitSign(Out2) ) for ( w = 0; w < nSimWords; w++ ) pSimTot[w] |= ~pSim1[w] & pSim2[w]; else assert( 0 ); } //printf( "\n" ); // count the total number of patterns contained in the don't-care nCovered = 0; for ( w = 0; w < nSimWords; w++ ) nCovered += Aig_WordCountOnes( pSimTot[w] ); Vec_PtrFree( vSimInfo ); // print the result printf( "Care states ratio = %f. ", 1.0 * (nSimWords * 32 - nCovered) / (nSimWords * 32) ); printf( "(%d out of %d patterns) ", nSimWords * 32 - nCovered, nSimWords * 32 ); ABC_PRT( "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Creates one-hotness EXDC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots ) { Aig_Man_t * pNew; Aig_Obj_t * pObj1, * pObj2, * pObj; int i, Out1, Out2, nTruePis; pNew = Aig_ManStart( Vec_IntSize(vOneHots)/2 ); // for ( i = 0; i < Aig_ManRegNum(p->pManAig); i++ ) // Aig_ObjCreateCi(pNew); Aig_ManForEachCi( p->pManAig, pObj, i ) Aig_ObjCreateCi(pNew); nTruePis = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 ) { Out1 = Vec_IntEntry( vOneHots, i ); Out2 = Vec_IntEntry( vOneHots, i+1 ); if ( Out1 == 0 && Out2 == 0 ) continue; pObj1 = Aig_ManCi( pNew, nTruePis + Fra_LitReg(Out1) ); pObj2 = Aig_ManCi( pNew, nTruePis + Fra_LitReg(Out2) ); pObj1 = Aig_NotCond( pObj1, Fra_LitSign(Out1) ); pObj2 = Aig_NotCond( pObj2, Fra_LitSign(Out2) ); pObj = Aig_Or( pNew, pObj1, pObj2 ); Aig_ObjCreateCo( pNew, pObj ); } Aig_ManCleanup(pNew); // printf( "Created AIG with %d nodes and %d outputs.\n", Aig_ManNodeNum(pNew), Aig_ManCoNum(pNew) ); return pNew; } /**Function************************************************************* Synopsis [Assumes one-hot implications in the SAT solver.] Description [] SideEffects [] SeeAlso [] **********************************************************************/ void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots ) { Vec_Int_t * vGroup; Aig_Obj_t * pObj1, * pObj2; int k, i, j, Out1, Out2, pLits[2]; // // these constrants should be added to different timeframes! // (also note that PIs follow first - then registers) // Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, k ) { Vec_IntForEachEntry( vGroup, Out1, i ) Vec_IntForEachEntryStart( vGroup, Out2, j, i+1 ) { pObj1 = Aig_ManCi( p->pManFraig, Out1 ); pObj2 = Aig_ManCi( p->pManFraig, Out2 ); pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), 1 ); pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), 1 ); // add constraint to solver if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) ) { printf( "Fra_OneHotAddKnownConstraint(): Adding clause makes SAT solver unsat.\n" ); sat_solver_delete( p->pSat ); p->pSat = NULL; return; } } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraImp.c000066400000000000000000000564061300674244400233260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraImp.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Detecting and proving implications.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraImp.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Counts the number of 1s in each siminfo of each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Fra_SmlCountOnesOne( Fra_Sml_t * p, int Node ) { unsigned * pSim; int k, Counter = 0; pSim = Fra_ObjSim( p, Node ); for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) Counter += Aig_WordCountOnes( pSim[k] ); return Counter; } /**Function************************************************************* Synopsis [Counts the number of 1s in each siminfo of each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Fra_SmlCountOnes( Fra_Sml_t * p ) { Aig_Obj_t * pObj; int i, * pnBits; pnBits = ABC_ALLOC( int, Aig_ManObjNumMax(p->pAig) ); memset( pnBits, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) ); Aig_ManForEachObj( p->pAig, pObj, i ) pnBits[i] = Fra_SmlCountOnesOne( p, i ); return pnBits; } /**Function************************************************************* Synopsis [Returns 1 if implications holds.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sml_NodeCheckImp( Fra_Sml_t * p, int Left, int Right ) { unsigned * pSimL, * pSimR; int k; pSimL = Fra_ObjSim( p, Left ); pSimR = Fra_ObjSim( p, Right ); for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) if ( pSimL[k] & ~pSimR[k] ) return 0; return 1; } /**Function************************************************************* Synopsis [Counts the number of 1s in the complement of the implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sml_NodeNotImpWeight( Fra_Sml_t * p, int Left, int Right ) { unsigned * pSimL, * pSimR; int k, Counter = 0; pSimL = Fra_ObjSim( p, Left ); pSimR = Fra_ObjSim( p, Right ); for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) Counter += Aig_WordCountOnes( pSimL[k] & ~pSimR[k] ); return Counter; } /**Function************************************************************* Synopsis [Computes the complement of the implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sml_NodeSaveNotImpPatterns( Fra_Sml_t * p, int Left, int Right, unsigned * pResult ) { unsigned * pSimL, * pSimR; int k; pSimL = Fra_ObjSim( p, Left ); pSimR = Fra_ObjSim( p, Right ); for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) pResult[k] |= pSimL[k] & ~pSimR[k]; } /**Function************************************************************* Synopsis [Returns the array of nodes sorted by the number of 1s.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Fra_SmlSortUsingOnes( Fra_Sml_t * p, int fLatchCorr ) { Aig_Obj_t * pObj; Vec_Ptr_t * vNodes; int i, nNodes, nTotal, nBits, * pnNodes, * pnBits, * pMemory; assert( p->nWordsTotal > 0 ); // count 1s in each node's siminfo pnBits = Fra_SmlCountOnes( p ); // count number of nodes having that many 1s nNodes = 0; nBits = p->nWordsTotal * 32; pnNodes = ABC_ALLOC( int, nBits + 1 ); memset( pnNodes, 0, sizeof(int) * (nBits + 1) ); Aig_ManForEachObj( p->pAig, pObj, i ) { if ( i == 0 ) continue; // skip non-PI and non-internal nodes if ( fLatchCorr ) { if ( !Aig_ObjIsCi(pObj) ) continue; } else { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; } // skip nodes participating in the classes // if ( Fra_ClassObjRepr(pObj) ) // continue; assert( pnBits[i] <= nBits ); // "<" because of normalized info pnNodes[pnBits[i]]++; nNodes++; } // allocate memory for all the nodes pMemory = ABC_ALLOC( int, nNodes + nBits + 1 ); // markup the memory for each node vNodes = Vec_PtrAlloc( nBits + 1 ); Vec_PtrPush( vNodes, pMemory ); for ( i = 1; i <= nBits; i++ ) { pMemory += pnNodes[i-1] + 1; Vec_PtrPush( vNodes, pMemory ); } // add the nodes memset( pnNodes, 0, sizeof(int) * (nBits + 1) ); Aig_ManForEachObj( p->pAig, pObj, i ) { if ( i == 0 ) continue; // skip non-PI and non-internal nodes if ( fLatchCorr ) { if ( !Aig_ObjIsCi(pObj) ) continue; } else { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; } // skip nodes participating in the classes // if ( Fra_ClassObjRepr(pObj) ) // continue; pMemory = (int *)Vec_PtrEntry( vNodes, pnBits[i] ); pMemory[ pnNodes[pnBits[i]]++ ] = i; } // add 0s in the end nTotal = 0; Vec_PtrForEachEntry( int *, vNodes, pMemory, i ) { pMemory[ pnNodes[i]++ ] = 0; nTotal += pnNodes[i]; } assert( nTotal == nNodes + nBits + 1 ); ABC_FREE( pnNodes ); ABC_FREE( pnBits ); return vNodes; } /**Function************************************************************* Synopsis [Returns the array of implications with the highest cost.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Fra_SmlSelectMaxCost( Vec_Int_t * vImps, int * pCosts, int nCostMax, int nImpLimit, int * pCostRange ) { Vec_Int_t * vImpsNew; int * pCostCount, nImpCount, Imp, i, c; assert( Vec_IntSize(vImps) >= nImpLimit ); // count how many implications have each cost pCostCount = ABC_ALLOC( int, nCostMax + 1 ); memset( pCostCount, 0, sizeof(int) * (nCostMax + 1) ); for ( i = 0; i < Vec_IntSize(vImps); i++ ) { assert( pCosts[i] <= nCostMax ); pCostCount[ pCosts[i] ]++; } assert( pCostCount[0] == 0 ); // select the bound on the cost (above this bound, implication will be included) nImpCount = 0; for ( c = nCostMax; c > 0; c-- ) { nImpCount += pCostCount[c]; if ( nImpCount >= nImpLimit ) break; } // printf( "Cost range >= %d.\n", c ); // collect implications with the given costs vImpsNew = Vec_IntAlloc( nImpLimit ); Vec_IntForEachEntry( vImps, Imp, i ) { if ( pCosts[i] < c ) continue; Vec_IntPush( vImpsNew, Imp ); if ( Vec_IntSize( vImpsNew ) == nImpLimit ) break; } ABC_FREE( pCostCount ); if ( pCostRange ) *pCostRange = c; return vImpsNew; } /**Function************************************************************* Synopsis [Compares two implications using their largest ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sml_CompareMaxId( unsigned short * pImp1, unsigned short * pImp2 ) { int Max1 = Abc_MaxInt( pImp1[0], pImp1[1] ); int Max2 = Abc_MaxInt( pImp2[0], pImp2[1] ); if ( Max1 < Max2 ) return -1; if ( Max1 > Max2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Derives implication candidates.] Description [Implication candidates have the property that (1) they hold using sequential simulation information (2) they do not hold using combinational simulation information (3) they have as high expressive power as possible (heuristically) that is, they are easy to disprove combinationally meaning they cover relatively larger sequential subspace.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr ) { int nSimWords = 64; Fra_Sml_t * pSeq, * pComb; Vec_Int_t * vImps, * vTemp; Vec_Ptr_t * vNodes; int * pImpCosts, * pNodesI, * pNodesK; int nImpsTotal = 0, nImpsTried = 0, nImpsNonSeq = 0, nImpsComb = 0, nImpsCollected = 0; int CostMin = ABC_INFINITY, CostMax = 0; int i, k, Imp, CostRange; abctime clk = Abc_Clock(); assert( Aig_ManObjNumMax(p->pManAig) < (1 << 15) ); assert( nImpMaxLimit > 0 && nImpUseLimit > 0 && nImpUseLimit <= nImpMaxLimit ); // normalize both managers pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords, 0 ); pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nSimWords, 1, 1 ); // get the nodes sorted by the number of 1s vNodes = Fra_SmlSortUsingOnes( pSeq, fLatchCorr ); // count the total number of implications for ( k = nSimWords * 32; k > 0; k-- ) for ( i = k - 1; i > 0; i-- ) for ( pNodesI = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) for ( pNodesK = (int *)Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ ) nImpsTotal++; // compute implications and their costs pImpCosts = ABC_ALLOC( int, nImpMaxLimit ); vImps = Vec_IntAlloc( nImpMaxLimit ); for ( k = pSeq->nWordsTotal * 32; k > 0; k-- ) for ( i = k - 1; i > 0; i-- ) { // HERE WE ARE MISSING SOME POTENTIAL IMPLICATIONS (with complement!) for ( pNodesI = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) for ( pNodesK = (int *)Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ ) { nImpsTried++; if ( !Sml_NodeCheckImp(pSeq, *pNodesI, *pNodesK) ) { nImpsNonSeq++; continue; } if ( Sml_NodeCheckImp(pComb, *pNodesI, *pNodesK) ) { nImpsComb++; continue; } nImpsCollected++; Imp = Fra_ImpCreate( *pNodesI, *pNodesK ); pImpCosts[ Vec_IntSize(vImps) ] = Sml_NodeNotImpWeight(pComb, *pNodesI, *pNodesK); CostMin = Abc_MinInt( CostMin, pImpCosts[ Vec_IntSize(vImps) ] ); CostMax = Abc_MaxInt( CostMax, pImpCosts[ Vec_IntSize(vImps) ] ); Vec_IntPush( vImps, Imp ); if ( Vec_IntSize(vImps) == nImpMaxLimit ) goto finish; } } finish: Fra_SmlStop( pComb ); Fra_SmlStop( pSeq ); // select implications with the highest cost CostRange = CostMin; if ( Vec_IntSize(vImps) > nImpUseLimit ) { vImps = Fra_SmlSelectMaxCost( vTemp = vImps, pImpCosts, nSimWords * 32, nImpUseLimit, &CostRange ); Vec_IntFree( vTemp ); } // dealloc ABC_FREE( pImpCosts ); { void * pTemp = Vec_PtrEntry(vNodes, 0); ABC_FREE( pTemp ); } Vec_PtrFree( vNodes ); // reorder implications topologically qsort( (void *)Vec_IntArray(vImps), Vec_IntSize(vImps), sizeof(int), (int (*)(const void *, const void *)) Sml_CompareMaxId ); if ( p->pPars->fVerbose ) { printf( "Implications: All = %d. Try = %d. NonSeq = %d. Comb = %d. Res = %d.\n", nImpsTotal, nImpsTried, nImpsNonSeq, nImpsComb, nImpsCollected ); printf( "Implication weight: Min = %d. Pivot = %d. Max = %d. ", CostMin, CostRange, CostMax ); ABC_PRT( "Time", Abc_Clock() - clk ); } return vImps; } // the following three procedures are called to // - add implications to the SAT solver // - check implications using the SAT solver // - refine implications using after a cex is generated /**Function************************************************************* Synopsis [Add implication clauses to the SAT solver.] Description [Note that implications should be checked in the first frame!] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums ) { sat_solver * pSat = p->pSat; Aig_Obj_t * pLeft, * pRight; Aig_Obj_t * pLeftF, * pRightF; int pLits[2], Imp, Left, Right, i, f, status; int fComplL, fComplR; Vec_IntForEachEntry( vImps, Imp, i ) { // get the corresponding nodes pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); // check if all the nodes are present for ( f = 0; f < p->pPars->nFramesK; f++ ) { // map these info fraig pLeftF = Fra_ObjFraig( pLeft, f ); pRightF = Fra_ObjFraig( pRight, f ); if ( Aig_ObjIsNone(Aig_Regular(pLeftF)) || Aig_ObjIsNone(Aig_Regular(pRightF)) ) { Vec_IntWriteEntry( vImps, i, 0 ); break; } } if ( f < p->pPars->nFramesK ) continue; // add constraints in each timeframe for ( f = 0; f < p->pPars->nFramesK; f++ ) { // map these info fraig pLeftF = Fra_ObjFraig( pLeft, f ); pRightF = Fra_ObjFraig( pRight, f ); // get the corresponding SAT numbers Left = pSatVarNums[ Aig_Regular(pLeftF)->Id ]; Right = pSatVarNums[ Aig_Regular(pRightF)->Id ]; assert( Left > 0 && Left < p->nSatVars ); assert( Right > 0 && Right < p->nSatVars ); // get the complemented attributes fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF); fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF); // get the constraint // L => R L' v R (complement = L & R') pLits[0] = 2 * Left + !fComplL; pLits[1] = 2 * Right + fComplR; // add constraint to solver if ( !sat_solver_addclause( pSat, pLits, pLits + 2 ) ) { sat_solver_delete( pSat ); p->pSat = NULL; return; } } } status = sat_solver_simplify(pSat); if ( status == 0 ) { sat_solver_delete( pSat ); p->pSat = NULL; } // printf( "Total imps = %d. ", Vec_IntSize(vImps) ); Fra_ImpCompactArray( vImps ); // printf( "Valid imps = %d. \n", Vec_IntSize(vImps) ); } /**Function************************************************************* Synopsis [Check implications for the node (if they are present).] Description [Returns the new position in the array.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos ) { Aig_Obj_t * pLeft, * pRight; Aig_Obj_t * pLeftF, * pRightF; int i, Imp, Left, Right, Max, RetValue; int fComplL, fComplR; Vec_IntForEachEntryStart( vImps, Imp, i, Pos ) { if ( Imp == 0 ) continue; Left = Fra_ImpLeft(Imp); Right = Fra_ImpRight(Imp); Max = Abc_MaxInt( Left, Right ); assert( Max >= pNode->Id ); if ( Max > pNode->Id ) return i; // get the corresponding nodes pLeft = Aig_ManObj( p->pManAig, Left ); pRight = Aig_ManObj( p->pManAig, Right ); // get the corresponding FRAIG nodes pLeftF = Fra_ObjFraig( pLeft, p->pPars->nFramesK ); pRightF = Fra_ObjFraig( pRight, p->pPars->nFramesK ); // get the complemented attributes fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF); fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF); // check equality if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) ) { if ( fComplL == fComplR ) // x => x - always true continue; assert( fComplL != fComplR ); // consider 4 possibilities: // NOT(1) => 1 or 0 => 1 - always true // 1 => NOT(1) or 1 => 0 - never true // NOT(x) => x or x - not always true // x => NOT(x) or NOT(x) - not always true if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication continue; // disproved implication p->pCla->fRefinement = 1; Vec_IntWriteEntry( vImps, i, 0 ); continue; } // check the implication // - if true, a clause is added // - if false, a cex is simulated // make sure the implication is refined RetValue = Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR ); if ( RetValue != 1 ) { p->pCla->fRefinement = 1; if ( RetValue == 0 ) Fra_SmlResimulate( p ); if ( Vec_IntEntry(vImps, i) != 0 ) printf( "Fra_ImpCheckForNode(): Implication is not refined!\n" ); assert( Vec_IntEntry(vImps, i) == 0 ); } } return i; } /**Function************************************************************* Synopsis [Removes those implications that no longer hold.] Description [Returns 1 if refinement has happened.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps ) { Aig_Obj_t * pLeft, * pRight; int Imp, i, RetValue = 0; Vec_IntForEachEntry( vImps, Imp, i ) { if ( Imp == 0 ) continue; // get the corresponding nodes pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); // check if implication holds using this simulation info if ( !Sml_NodeCheckImp(p->pSml, pLeft->Id, pRight->Id) ) { Vec_IntWriteEntry( vImps, i, 0 ); RetValue = 1; } } return RetValue; } /**Function************************************************************* Synopsis [Removes empty implications.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ImpCompactArray( Vec_Int_t * vImps ) { int i, k, Imp; k = 0; Vec_IntForEachEntry( vImps, Imp, i ) if ( Imp ) Vec_IntWriteEntry( vImps, k++, Imp ); Vec_IntShrink( vImps, k ); } /**Function************************************************************* Synopsis [Determines the ratio of the state space by computed implications.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p ) { int nSimWords = 64; Fra_Sml_t * pComb; unsigned * pResult; double Ratio = 0.0; int Left, Right, Imp, i; if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) return Ratio; // simulate the AIG manager with combinational patterns pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords, 0 ); // go through the implications and collect where they do not hold pResult = Fra_ObjSim( pComb, 0 ); assert( pResult[0] == 0 ); Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) { Left = Fra_ImpLeft(Imp); Right = Fra_ImpRight(Imp); Sml_NodeSaveNotImpPatterns( pComb, Left, Right, pResult ); } // count the number of ones in this area Ratio = 100.0 * Fra_SmlCountOnesOne( pComb, 0 ) / (32*(pComb->nWordsTotal-pComb->nWordsPref)); Fra_SmlStop( pComb ); return Ratio; } /**Function************************************************************* Synopsis [Returns the number of failed implications.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p ) { int nFrames = 2000; int nSimWords = 8; Fra_Sml_t * pSeq; char * pfFails; int Left, Right, Imp, i, Counter; if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) return 0; // simulate the AIG manager with combinational patterns pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nFrames, nSimWords, 1 ); // go through the implications and check how many of them do not hold pfFails = ABC_ALLOC( char, Vec_IntSize(p->pCla->vImps) ); memset( pfFails, 0, sizeof(char) * Vec_IntSize(p->pCla->vImps) ); Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) { Left = Fra_ImpLeft(Imp); Right = Fra_ImpRight(Imp); pfFails[i] = !Sml_NodeCheckImp( pSeq, Left, Right ); } // count how many has failed Counter = 0; for ( i = 0; i < Vec_IntSize(p->pCla->vImps); i++ ) Counter += pfFails[i]; ABC_FREE( pfFails ); Fra_SmlStop( pSeq ); return Counter; } /**Function************************************************************* Synopsis [Record proven implications in the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew ) { Aig_Obj_t * pLeft, * pRight, * pMiter; int nPosOld, Imp, i; if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) return; // go through the implication nPosOld = Aig_ManCoNum(pNew); Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) { pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); // record the implication: L' + R pMiter = Aig_Or( pNew, Aig_NotCond((Aig_Obj_t *)pLeft->pData, !pLeft->fPhase), Aig_NotCond((Aig_Obj_t *)pRight->pData, pRight->fPhase) ); Aig_ObjCreateCo( pNew, pMiter ); } pNew->nAsserts = Aig_ManCoNum(pNew) - nPosOld; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraInd.c000066400000000000000000000632141300674244400233060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraInd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Inductive prover.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraInd.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" #include "sat/cnf/cnf.h" #include "opt/dar/dar.h" #include "aig/saig/saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs AIG rewriting on the constraint manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_FraigInductionRewrite( Fra_Man_t * p ) { Aig_Man_t * pTemp; Aig_Obj_t * pObj, * pObjPo; int nTruePis, k, i; abctime clk = Abc_Clock(); // perform AIG rewriting on the speculated frames // pTemp = Dar_ManRwsat( pTemp, 1, 0 ); pTemp = Dar_ManRewriteDefault( p->pManFraig ); // printf( "Before = %6d. After = %6d.\n", Aig_ManNodeNum(p->pManFraig), Aig_ManNodeNum(pTemp) ); //Aig_ManDumpBlif( p->pManFraig, "1.blif", NULL, NULL ); //Aig_ManDumpBlif( pTemp, "2.blif", NULL, NULL ); // Fra_FramesWriteCone( pTemp ); // Aig_ManStop( pTemp ); // transfer PI/register pointers assert( p->pManFraig->nRegs == pTemp->nRegs ); assert( p->pManFraig->nAsserts == pTemp->nAsserts ); nTruePis = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), p->pPars->nFramesK, Aig_ManConst1(pTemp) ); Aig_ManForEachPiSeq( p->pManAig, pObj, i ) Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ManCi(pTemp,nTruePis*p->pPars->nFramesK+i) ); k = 0; assert( Aig_ManRegNum(p->pManAig) == Aig_ManCoNum(pTemp) - pTemp->nAsserts ); Aig_ManForEachLoSeq( p->pManAig, pObj, i ) { pObjPo = Aig_ManCo(pTemp, pTemp->nAsserts + k++); Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ObjChild0(pObjPo) ); } // exchange Aig_ManStop( p->pManFraig ); p->pManFraig = pTemp; p->timeRwr += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Performs speculative reduction for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Fra_FramesConstrainNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, int iFrame ) { Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter; // skip nodes without representative if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL ) return; assert( pObjRepr->Id < pObj->Id ); // get the new node pObjNew = Fra_ObjFraig( pObj, iFrame ); // get the new node of the representative pObjReprNew = Fra_ObjFraig( pObjRepr, iFrame ); // if this is the same node, no need to add constraints if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) ) return; // these are different nodes - perform speculative reduction pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); // set the new node Fra_ObjSetFraig( pObj, iFrame, pObjNew2 ); // add the constraint pMiter = Aig_Exor( pManFraig, pObjNew, pObjReprNew ); pMiter = Aig_NotCond( pMiter, !Aig_ObjPhaseReal(pMiter) ); assert( Aig_ObjPhaseReal(pMiter) == 1 ); Aig_ObjCreateCo( pManFraig, pMiter ); } /**Function************************************************************* Synopsis [Prepares the inductive case with speculative reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_FramesWithClasses( Fra_Man_t * p ) { Aig_Man_t * pManFraig; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; int i, k, f; assert( p->pManFraig == NULL ); assert( Aig_ManRegNum(p->pManAig) > 0 ); assert( Aig_ManRegNum(p->pManAig) < Aig_ManCiNum(p->pManAig) ); // start the fraig package pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) * p->nFramesAll ); pManFraig->pName = Abc_UtilStrsav( p->pManAig->pName ); pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec ); pManFraig->nRegs = p->pManAig->nRegs; // create PI nodes for the frames for ( f = 0; f < p->nFramesAll; f++ ) Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), f, Aig_ManConst1(pManFraig) ); for ( f = 0; f < p->nFramesAll; f++ ) Aig_ManForEachPiSeq( p->pManAig, pObj, i ) Fra_ObjSetFraig( pObj, f, Aig_ObjCreateCi(pManFraig) ); // create latches for the first frame Aig_ManForEachLoSeq( p->pManAig, pObj, i ) Fra_ObjSetFraig( pObj, 0, Aig_ObjCreateCi(pManFraig) ); // add timeframes // pManFraig->fAddStrash = 1; for ( f = 0; f < p->nFramesAll - 1; f++ ) { // set the constraints on the latch outputs Aig_ManForEachLoSeq( p->pManAig, pObj, i ) Fra_FramesConstrainNode( pManFraig, pObj, f ); // add internal nodes of this frame Aig_ManForEachNode( p->pManAig, pObj, i ) { pObjNew = Aig_And( pManFraig, Fra_ObjChild0Fra(pObj,f), Fra_ObjChild1Fra(pObj,f) ); Fra_ObjSetFraig( pObj, f, pObjNew ); Fra_FramesConstrainNode( pManFraig, pObj, f ); } // transfer latch input to the latch outputs Aig_ManForEachLiLoSeq( p->pManAig, pObjLi, pObjLo, k ) Fra_ObjSetFraig( pObjLo, f+1, Fra_ObjChild0Fra(pObjLi,f) ); } // pManFraig->fAddStrash = 0; // mark the asserts pManFraig->nAsserts = Aig_ManCoNum(pManFraig); // add the POs for the latch outputs of the last frame Aig_ManForEachLoSeq( p->pManAig, pObj, i ) Aig_ObjCreateCo( pManFraig, Fra_ObjFraig(pObj,p->nFramesAll-1) ); // remove dangling nodes Aig_ManCleanup( pManFraig ); // make sure the satisfying assignment is node assigned assert( pManFraig->pData == NULL ); return pManFraig; } /**Function************************************************************* Synopsis [Prepares the inductive case with speculative reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_FramesAddMore( Aig_Man_t * p, int nFrames ) { Aig_Obj_t * pObj, ** pLatches; int i, k, f, nNodesOld; // set copy pointer of each object to point to itself Aig_ManForEachObj( p, pObj, i ) pObj->pData = pObj; // iterate and add objects nNodesOld = Aig_ManObjNumMax(p); pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p) ); for ( f = 0; f < nFrames; f++ ) { // clean latch inputs and outputs Aig_ManForEachLiSeq( p, pObj, i ) pObj->pData = NULL; Aig_ManForEachLoSeq( p, pObj, i ) pObj->pData = NULL; // save the latch input values k = 0; Aig_ManForEachLiSeq( p, pObj, i ) { if ( Aig_ObjFanin0(pObj)->pData ) pLatches[k++] = Aig_ObjChild0Copy(pObj); else pLatches[k++] = NULL; } // insert them as the latch output values k = 0; Aig_ManForEachLoSeq( p, pObj, i ) pObj->pData = pLatches[k++]; // create the next time frame of nodes Aig_ManForEachNode( p, pObj, i ) { if ( i > nNodesOld ) break; if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData ) pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); else pObj->pData = NULL; } } ABC_FREE( pLatches ); } /**Function************************************************************* Synopsis [Performs partitioned sequential SAT sweepingG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_FraigInductionPart( Aig_Man_t * pAig, Fra_Ssw_t * pPars ) { int fPrintParts = 0; char Buffer[100]; Aig_Man_t * pTemp, * pNew; Vec_Ptr_t * vResult; Vec_Int_t * vPart; int * pMapBack; int i, nCountPis, nCountRegs; int nClasses, nPartSize, fVerbose; abctime clk = Abc_Clock(); // save parameters nPartSize = pPars->nPartSize; pPars->nPartSize = 0; fVerbose = pPars->fVerbose; pPars->fVerbose = 0; // generate partitions if ( pAig->vClockDoms ) { // divide large clock domains into separate partitions vResult = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) { if ( nPartSize && Vec_IntSize(vPart) > nPartSize ) Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize ); else Vec_PtrPush( vResult, Vec_IntDup(vPart) ); } } else vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize ); // vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); // vResult = Aig_ManRegPartitionSmart( pAig, nPartSize ); if ( fPrintParts ) { // print partitions printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) ); Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) { sprintf( Buffer, "part%03d.aig", i ); pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL ); Ioa_WriteAiger( pTemp, Buffer, 0, 0 ); printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) ); Aig_ManStop( pTemp ); } } // perform SSW with partitions Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) { pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack ); // create the projection of 1-hot registers if ( pAig->vOnehots ) pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose ); // run SSW pNew = Fra_FraigInduction( pTemp, pPars ); 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), pPars->nIters, nClasses ); Aig_ManStop( pNew ); Aig_ManStop( pTemp ); ABC_FREE( pMapBack ); } // remap the AIG pNew = Aig_ManDupRepr( pAig, 0 ); Aig_ManSeqCleanup( pNew ); // Aig_ManPrintStats( pAig ); // Aig_ManPrintStats( pNew ); Vec_VecFree( (Vec_Vec_t *)vResult ); pPars->nPartSize = nPartSize; pPars->fVerbose = fVerbose; if ( fVerbose ) { ABC_PRT( "Total time", Abc_Clock() - clk ); } return pNew; } /**Function************************************************************* Synopsis [Performs sequential SAT sweeping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, Fra_Ssw_t * pParams ) { int fUseSimpleCnf = 0; int fUseOldSimulation = 0; // other paramaters affecting performance // - presence of FRAIGing in Abc_NtkDarSeqSweep() // - using distance-1 patterns in Fra_SmlAssignDist1() // - the number of simulation patterns // - the number of BMC frames Fra_Man_t * p; Fra_Par_t Pars, * pPars = &Pars; Aig_Obj_t * pObj; Cnf_Dat_t * pCnf; Aig_Man_t * pManAigNew = NULL; int nNodesBeg, nRegsBeg; int nIter = -1; // Suppress "might be used uninitialized" int i; abctime clk = Abc_Clock(), clk2; abctime TimeToStop = pParams->TimeLimit ? pParams->TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; if ( Aig_ManNodeNum(pManAig) == 0 ) { pParams->nIters = 0; // Ntl_ManFinalize() needs the following to satisfy an assertion Aig_ManReprStart(pManAig,Aig_ManObjNumMax(pManAig)); return Aig_ManDupOrdered(pManAig); } assert( Aig_ManRegNum(pManAig) > 0 ); assert( pParams->nFramesK > 0 ); //Aig_ManShow( pManAig, 0, NULL ); if ( pParams->fWriteImps && pParams->nPartSize > 0 ) { pParams->nPartSize = 0; printf( "Partitioning was disabled to allow implication writing.\n" ); } // perform partitioning if ( (pParams->nPartSize > 0 && pParams->nPartSize < Aig_ManRegNum(pManAig)) || (pManAig->vClockDoms && Vec_VecSize(pManAig->vClockDoms) > 0) ) return Fra_FraigInductionPart( pManAig, pParams ); nNodesBeg = Aig_ManNodeNum(pManAig); nRegsBeg = Aig_ManRegNum(pManAig); // enhance the AIG by adding timeframes // Fra_FramesAddMore( pManAig, 3 ); // get parameters Fra_ParamsDefaultSeq( pPars ); pPars->nFramesP = pParams->nFramesP; pPars->nFramesK = pParams->nFramesK; pPars->nMaxImps = pParams->nMaxImps; pPars->nMaxLevs = pParams->nMaxLevs; pPars->fVerbose = pParams->fVerbose; pPars->fRewrite = pParams->fRewrite; pPars->fLatchCorr = pParams->fLatchCorr; pPars->fUseImps = pParams->fUseImps; pPars->fWriteImps = pParams->fWriteImps; pPars->fUse1Hot = pParams->fUse1Hot; assert( !(pPars->nFramesP > 0 && pPars->fUse1Hot) ); assert( !(pPars->nFramesK > 1 && pPars->fUse1Hot) ); // start the fraig manager for this run p = Fra_ManStart( pManAig, pPars ); p->pPars->nBTLimitNode = 0; // derive and refine e-classes using K initialized frames if ( fUseOldSimulation ) { if ( pPars->nFramesP > 0 ) { pPars->nFramesP = 0; printf( "Fra_FraigInduction(): Prefix cannot be used.\n" ); } p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords ); Fra_SmlSimulate( p, 1 ); } else { // bug: r iscas/blif/s5378.blif ; st; ssw -v // bug: r iscas/blif/s1238.blif ; st; ssw -v // refine the classes with more simulation rounds if ( pPars->fVerbose ) printf( "Simulating %d AIG nodes for %d cycles ... ", Aig_ManNodeNum(pManAig), pPars->nFramesP + 32 ); p->pSml = Fra_SmlSimulateSeq( pManAig, pPars->nFramesP, 32, 1, 1 ); //pPars->nFramesK + 1, 1 ); if ( pPars->fVerbose ) { ABC_PRT( "Time", Abc_Clock() - clk ); } Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, p->pPars->nMaxLevs ); // Fra_ClassesPostprocess( p->pCla ); // compute one-hotness conditions if ( p->pPars->fUse1Hot ) p->vOneHots = Fra_OneHotCompute( p, p->pSml ); // allocate new simulation manager for simulating counter-examples Fra_SmlStop( p->pSml ); p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords ); } // select the most expressive implications if ( pPars->fUseImps ) p->pCla->vImps = Fra_ImpDerive( p, 5000000, pPars->nMaxImps, pPars->fLatchCorr ); if ( pParams->TimeLimit != 0.0 && Abc_Clock() > TimeToStop ) { if ( !pParams->fSilent ) printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" ); goto finish; } // perform BMC (for the min number of frames) Fra_BmcPerform( p, pPars->nFramesP, pPars->nFramesK+1 ); // +1 is needed to prevent non-refinement //Fra_ClassesPrint( p->pCla, 1 ); // if ( p->vCex == NULL ) // p->vCex = Vec_IntAlloc( 1000 ); p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); p->nNodesBeg = nNodesBeg; // Aig_ManNodeNum(pManAig); p->nRegsBeg = nRegsBeg; // Aig_ManRegNum(pManAig); // dump AIG of the timeframes // pManAigNew = Fra_ClassesDeriveAig( p->pCla, pPars->nFramesK ); // Aig_ManDumpBlif( pManAigNew, "frame_aig.blif", NULL, NULL ); // Fra_ManPartitionTest2( pManAigNew ); // Aig_ManStop( pManAigNew ); // iterate the inductive case p->pCla->fRefinement = 1; for ( nIter = 0; p->pCla->fRefinement; nIter++ ) { int nLitsOld = Fra_ClassesCountLits(p->pCla); int nImpsOld = p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0; int nHotsOld = p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0; abctime clk3 = Abc_Clock(); if ( pParams->TimeLimit != 0.0 && Abc_Clock() > TimeToStop ) { if ( !pParams->fSilent ) printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" ); goto finish; } // mark the classes as non-refined p->pCla->fRefinement = 0; // derive non-init K-timeframes while implementing e-classes clk2 = Abc_Clock(); p->pManFraig = Fra_FramesWithClasses( p ); p->timeTrav += Abc_Clock() - clk2; //Aig_ManDumpBlif( p->pManFraig, "testaig.blif", NULL, NULL ); // perform AIG rewriting if ( p->pPars->fRewrite ) Fra_FraigInductionRewrite( p ); // convert the manager to SAT solver (the last nLatches outputs are inputs) if ( fUseSimpleCnf || pPars->fUseImps ) pCnf = Cnf_DeriveSimple( p->pManFraig, Aig_ManRegNum(p->pManFraig) ); else pCnf = Cnf_Derive( p->pManFraig, Aig_ManRegNum(p->pManFraig) ); // Cnf_DataTranformPolarity( pCnf, 0 ); //Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 ); p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); p->nSatVars = pCnf->nVars; assert( p->pSat != NULL ); if ( p->pSat == NULL ) printf( "Fra_FraigInduction(): Computed CNF is not valid.\n" ); if ( pPars->fUseImps ) { Fra_ImpAddToSolver( p, p->pCla->vImps, pCnf->pVarNums ); if ( p->pSat == NULL ) printf( "Fra_FraigInduction(): Adding implicationsn to CNF led to a conflict.\n" ); } // set the pointers to the manager Aig_ManForEachObj( p->pManFraig, pObj, i ) pObj->pData = p; // prepare solver for fraiging the last timeframe Fra_ManClean( p, Aig_ManObjNumMax(p->pManFraig) + Aig_ManNodeNum(p->pManAig) ); // transfer PI/LO variable numbers Aig_ManForEachObj( p->pManFraig, pObj, i ) { if ( pCnf->pVarNums[pObj->Id] == -1 ) continue; Fra_ObjSetSatNum( pObj, pCnf->pVarNums[pObj->Id] ); Fra_ObjSetFaninVec( pObj, (Vec_Ptr_t *)1 ); } Cnf_DataFree( pCnf ); // add one-hotness clauses if ( p->pPars->fUse1Hot ) Fra_OneHotAssume( p, p->vOneHots ); // if ( p->pManAig->vOnehots ) // Fra_OneHotAddKnownConstraint( p, p->pManAig->vOnehots ); // report the intermediate results if ( pPars->fVerbose ) { printf( "%3d : C = %6d. Cl = %6d. L = %6d. LR = %6d. ", nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla), p->pManFraig->nAsserts ); if ( p->pCla->vImps ) printf( "I = %6d. ", Vec_IntSize(p->pCla->vImps) ); if ( p->pPars->fUse1Hot ) printf( "1h = %6d. ", Fra_OneHotCount(p, p->vOneHots) ); printf( "NR = %6d. ", Aig_ManNodeNum(p->pManFraig) ); // printf( "\n" ); } // perform sweeping p->nSatCallsRecent = 0; p->nSatCallsSkipped = 0; clk2 = Abc_Clock(); if ( p->pPars->fUse1Hot ) Fra_OneHotCheck( p, p->vOneHots ); Fra_FraigSweep( p ); if ( pPars->fVerbose ) { ABC_PRT( "T", Abc_Clock() - clk3 ); } // Sat_SolverPrintStats( stdout, p->pSat ); // remove FRAIG and SAT solver Aig_ManStop( p->pManFraig ); p->pManFraig = NULL; // printf( "Vars = %d. Clauses = %d. Learnts = %d.\n", p->pSat->size, p->pSat->clauses.size, p->pSat->learnts.size ); sat_solver_delete( p->pSat ); p->pSat = NULL; memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); // printf( "Recent SAT called = %d. Skipped = %d.\n", p->nSatCallsRecent, p->nSatCallsSkipped ); assert( p->vTimeouts == NULL ); if ( p->vTimeouts ) printf( "Fra_FraigInduction(): SAT solver timed out!\n" ); // check if refinement has happened // p->pCla->fRefinement = (int)(nLitsOld != Fra_ClassesCountLits(p->pCla)); if ( p->pCla->fRefinement && nLitsOld == Fra_ClassesCountLits(p->pCla) && nImpsOld == (p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0) && nHotsOld == (p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0) ) { printf( "Fra_FraigInduction(): Internal error. The result may not verify.\n" ); break; } } /* // verify implications using simulation if ( p->pCla->vImps && Vec_IntSize(p->pCla->vImps) ) { int Temp; abctime clk = Abc_Clock(); if ( Temp = Fra_ImpVerifyUsingSimulation( p ) ) printf( "Implications failing the simulation test = %d (out of %d). ", Temp, Vec_IntSize(p->pCla->vImps) ); else printf( "All %d implications have passed the simulation test. ", Vec_IntSize(p->pCla->vImps) ); ABC_PRT( "Time", Abc_Clock() - clk ); } */ // move the classes into representatives and reduce AIG clk2 = Abc_Clock(); if ( p->pPars->fWriteImps && p->vOneHots && Fra_OneHotCount(p, p->vOneHots) ) { extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); Aig_Man_t * pNew; char * pFileName = Ioa_FileNameGenericAppend( p->pManAig->pName, "_care.aig" ); printf( "Care one-hotness clauses will be written into file \"%s\".\n", pFileName ); pManAigNew = Aig_ManDupOrdered( pManAig ); pNew = Fra_OneHotCreateExdc( p, p->vOneHots ); Ioa_WriteAiger( pNew, pFileName, 0, 1 ); Aig_ManStop( pNew ); } else { // Fra_ClassesPrint( p->pCla, 1 ); Fra_ClassesSelectRepr( p->pCla ); Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); pManAigNew = Aig_ManDupRepr( pManAig, 0 ); } // add implications to the manager // if ( fWriteImps && p->pCla->vImps && Vec_IntSize(p->pCla->vImps) ) // Fra_ImpRecordInManager( p, pManAigNew ); // cleanup the new manager Aig_ManSeqCleanup( pManAigNew ); // remove pointers to the dead nodes // Aig_ManForEachObj( pManAig, pObj, i ) // if ( pObj->pData && Aig_ObjIsNone(pObj->pData) ) // pObj->pData = NULL; // Aig_ManCountMergeRegs( pManAigNew ); p->timeTrav += Abc_Clock() - clk2; p->timeTotal = Abc_Clock() - clk; // get the final stats p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); p->nNodesEnd = Aig_ManNodeNum(pManAigNew); p->nRegsEnd = Aig_ManRegNum(pManAigNew); // free the manager finish: Fra_ManStop( p ); // check the output // if ( Aig_ManCoNum(pManAigNew) - Aig_ManRegNum(pManAigNew) == 1 ) // if ( Aig_ObjChild0( Aig_ManCo(pManAigNew,0) ) == Aig_ManConst0(pManAigNew) ) // printf( "Proved output constant 0.\n" ); pParams->nIters = nIter; return pManAigNew; } /**Function************************************************************* Synopsis [Outputs a set of pairs of equivalent nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_FraigInductionTest( char * pFileName, Fra_Ssw_t * pParams ) { FILE * pFile; char * pFilePairs; Aig_Man_t * pMan, * pNew; Aig_Obj_t * pObj, * pRepr; int * pNum2Id; int i, Counter = 0; pMan = Saig_ManReadBlif( pFileName ); if ( pMan == NULL ) return 0; // perform seq SAT sweeping pNew = Fra_FraigInduction( pMan, pParams ); if ( pNew == NULL ) { Aig_ManStop( pMan ); return 0; } if ( pParams->fVerbose ) { printf( "Original AIG: " ); Aig_ManPrintStats( pMan ); printf( "Reduced AIG: " ); Aig_ManPrintStats( pNew ); } Aig_ManStop( pNew ); pNum2Id = (int *)pMan->pData; // write the output file pFilePairs = Aig_FileNameGenericAppend( pFileName, ".pairs" ); pFile = fopen( pFilePairs, "w" ); Aig_ManForEachObj( pMan, pObj, i ) if ( (pRepr = pMan->pReprs[pObj->Id]) ) { fprintf( pFile, "%d %d %c\n", pNum2Id[pObj->Id], pNum2Id[pRepr->Id], (Aig_ObjPhase(pObj) ^ Aig_ObjPhase(pRepr))? '-' : '+' ); Counter++; } fclose( pFile ); if ( pParams->fVerbose ) { printf( "Result: %d pairs of seq equiv nodes are written into file \"%s\".\n", Counter, pFilePairs ); } Aig_ManStop( pMan ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraIndVer.c000066400000000000000000000122321300674244400237550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraIndVer.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Verification of the inductive invariant.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraIndVer.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" #include "sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Verifies the inductive invariant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_InvariantVerify( Aig_Man_t * pAig, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits ) { Cnf_Dat_t * pCnf; sat_solver * pSat; int * pStart; int RetValue, Beg, End, i, k; int CounterBase = 0, CounterInd = 0; abctime clk = Abc_Clock(); if ( nFrames != 1 ) { printf( "Invariant verification: Can only verify for K = 1\n" ); return 1; } // derive CNF pCnf = Cnf_DeriveSimple( pAig, Aig_ManCoNum(pAig) ); /* // add the property { Aig_Obj_t * pObj; int Lits[1]; pObj = Aig_ManCo( pAig, 0 ); Lits[0] = toLitCond( pCnf->pVarNums[pObj->Id], 1 ); Vec_IntPush( vLits, Lits[0] ); Vec_IntPush( vClauses, Vec_IntSize(vLits) ); printf( "Added the target property to the set of clauses to be inductively checked.\n" ); } */ // derive initialized frames for the base case pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 1 ); // check clauses in the base case Beg = 0; pStart = Vec_IntArray( vLits ); Vec_IntForEachEntry( vClauses, End, i ) { // complement the literals for ( k = Beg; k < End; k++ ) pStart[k] = lit_neg(pStart[k]); RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 ); for ( k = Beg; k < End; k++ ) pStart[k] = lit_neg(pStart[k]); Beg = End; if ( RetValue == l_False ) continue; // printf( "Clause %d failed the base case.\n", i ); CounterBase++; } sat_solver_delete( pSat ); // derive initialized frames for the base case pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames + 1, 0 ); assert( pSat->size == 2 * pCnf->nVars ); // add clauses to the first frame Beg = 0; pStart = Vec_IntArray( vLits ); Vec_IntForEachEntry( vClauses, End, i ) { RetValue = sat_solver_addclause( pSat, pStart + Beg, pStart + End ); Beg = End; if ( RetValue == 0 ) { Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); printf( "Invariant verification: SAT solver is unsat after adding a clause.\n" ); return 0; } } // simplify the solver if ( pSat->qtail != pSat->qhead ) { RetValue = sat_solver_simplify(pSat); assert( RetValue != 0 ); assert( pSat->qtail == pSat->qhead ); } // check clauses in the base case Beg = 0; pStart = Vec_IntArray( vLits ); Vec_IntForEachEntry( vClauses, End, i ) { // complement the literals for ( k = Beg; k < End; k++ ) { pStart[k] += 2 * pCnf->nVars; pStart[k] = lit_neg(pStart[k]); } RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 ); for ( k = Beg; k < End; k++ ) { pStart[k] = lit_neg(pStart[k]); pStart[k] -= 2 * pCnf->nVars; } Beg = End; if ( RetValue == l_False ) continue; // printf( "Clause %d failed the inductive case.\n", i ); CounterInd++; } sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); if ( CounterBase ) printf( "Invariant verification: %d clauses (out of %d) FAILED the base case.\n", CounterBase, Vec_IntSize(vClauses) ); if ( CounterInd ) printf( "Invariant verification: %d clauses (out of %d) FAILED the inductive case.\n", CounterInd, Vec_IntSize(vClauses) ); if ( CounterBase || CounterInd ) return 0; printf( "Invariant verification: %d clauses verified correctly. ", Vec_IntSize(vClauses) ); ABC_PRT( "Time", Abc_Clock() - clk ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraLcr.c000066400000000000000000000551161300674244400233160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraLcorr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Latch correspondence computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraLcorr.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Fra_Lcr_t_ Fra_Lcr_t; struct Fra_Lcr_t_ { // original AIG Aig_Man_t * pAig; // equivalence class representation Fra_Cla_t * pCla; // partitioning information Vec_Ptr_t * vParts; // output partitions int * pInToOutPart; // mapping of PI num into PO partition num int * pInToOutNum; // mapping of PI num into the num of this PO in the partition // AIGs for the partitions Vec_Ptr_t * vFraigs; // other variables int fRefining; // parameters int nFramesP; int fVerbose; // statistics int nIters; int nLitsBeg; int nLitsEnd; int nNodesBeg; int nNodesEnd; int nRegsBeg; int nRegsEnd; // runtime abctime timeSim; abctime timePart; abctime timeTrav; abctime timeFraig; abctime timeUpdate; abctime timeTotal; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the retiming manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Lcr_t * Lcr_ManAlloc( Aig_Man_t * pAig ) { Fra_Lcr_t * p; p = ABC_ALLOC( Fra_Lcr_t, 1 ); memset( p, 0, sizeof(Fra_Lcr_t) ); p->pAig = pAig; p->pInToOutPart = ABC_ALLOC( int, Aig_ManCiNum(pAig) ); memset( p->pInToOutPart, 0, sizeof(int) * Aig_ManCiNum(pAig) ); p->pInToOutNum = ABC_ALLOC( int, Aig_ManCiNum(pAig) ); memset( p->pInToOutNum, 0, sizeof(int) * Aig_ManCiNum(pAig) ); p->vFraigs = Vec_PtrAlloc( 1000 ); return p; } /**Function************************************************************* Synopsis [Prints stats for the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lcr_ManPrint( Fra_Lcr_t * p ) { printf( "Iterations = %d. LitBeg = %d. LitEnd = %d. (%6.2f %%).\n", p->nIters, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/p->nLitsBeg ); printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg, p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/p->nRegsBeg ); ABC_PRT( "AIG simulation ", p->timeSim ); ABC_PRT( "AIG partitioning", p->timePart ); ABC_PRT( "AIG rebuiding ", p->timeTrav ); ABC_PRT( "FRAIGing ", p->timeFraig ); ABC_PRT( "AIG updating ", p->timeUpdate ); ABC_PRT( "TOTAL RUNTIME ", p->timeTotal ); } /**Function************************************************************* Synopsis [Deallocates the retiming manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lcr_ManFree( Fra_Lcr_t * p ) { Aig_Obj_t * pObj; int i; if ( p->fVerbose ) Lcr_ManPrint( p ); Aig_ManForEachCi( p->pAig, pObj, i ) pObj->pNext = NULL; Vec_PtrFree( p->vFraigs ); if ( p->pCla ) Fra_ClassesStop( p->pCla ); if ( p->vParts ) Vec_VecFree( (Vec_Vec_t *)p->vParts ); ABC_FREE( p->pInToOutPart ); ABC_FREE( p->pInToOutNum ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prepare the AIG for class computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig ) { Fra_Man_t * p; Aig_Obj_t * pObj; int i; p = ABC_ALLOC( Fra_Man_t, 1 ); memset( p, 0, sizeof(Fra_Man_t) ); // Aig_ManForEachCi( pAig, pObj, i ) Aig_ManForEachObj( pAig, pObj, i ) pObj->pData = p; return p; } /**Function************************************************************* Synopsis [Prepare the AIG for class computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_LcrAigPrepareTwo( Aig_Man_t * pAig, Fra_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = p; } /**Function************************************************************* Synopsis [Compares two nodes for equivalence after partitioned fraiging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_LcrNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { Fra_Man_t * pTemp = (Fra_Man_t *)pObj0->pData; Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc; Aig_Man_t * pFraig; Aig_Obj_t * pOut0, * pOut1; int nPart0, nPart1; assert( Aig_ObjIsCi(pObj0) ); assert( Aig_ObjIsCi(pObj1) ); // find the partition to which these nodes belong nPart0 = pLcr->pInToOutPart[(long)pObj0->pNext]; nPart1 = pLcr->pInToOutPart[(long)pObj1->pNext]; // if this is the result of refinement of the class created const-1 nodes // the nodes may end up in different partions - we assume them equivalent if ( nPart0 != nPart1 ) { assert( 0 ); return 1; } assert( nPart0 == nPart1 ); pFraig = (Aig_Man_t *)Vec_PtrEntry( pLcr->vFraigs, nPart0 ); // get the fraig outputs pOut0 = Aig_ManCo( pFraig, pLcr->pInToOutNum[(long)pObj0->pNext] ); pOut1 = Aig_ManCo( pFraig, pLcr->pInToOutNum[(long)pObj1->pNext] ); return Aig_ObjFanin0(pOut0) == Aig_ObjFanin0(pOut1); } /**Function************************************************************* Synopsis [Compares the node with a constant after partioned fraiging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_LcrNodeIsConst( Aig_Obj_t * pObj ) { Fra_Man_t * pTemp = (Fra_Man_t *)pObj->pData; Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc; Aig_Man_t * pFraig; Aig_Obj_t * pOut; int nPart; assert( Aig_ObjIsCi(pObj) ); // find the partition to which these nodes belong nPart = pLcr->pInToOutPart[(long)pObj->pNext]; pFraig = (Aig_Man_t *)Vec_PtrEntry( pLcr->vFraigs, nPart ); // get the fraig outputs pOut = Aig_ManCo( pFraig, pLcr->pInToOutNum[(long)pObj->pNext] ); return Aig_ObjFanin0(pOut) == Aig_ManConst1(pFraig); } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Fra_LcrManDup_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; Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsBuf(pObj) ) return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); Fra_LcrManDup_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 [Give the AIG and classes, reduces AIG for partitioning.] Description [Ignores registers that are not in the classes. Places candidate equivalent classes of registers into single outputs (for ease of partitioning). The resulting combinational AIG contains outputs in the same order as equivalence classes of registers, followed by constant-1 registers. Preserves the set of all inputs. Complemented attributes of the outputs do not matter because we need then only for collecting the structural info.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_LcrDeriveAigForPartitioning( Fra_Lcr_t * pLcr ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjPo, * pObjNew, ** ppClass, * pMiter; int i, c, Offset; // remember the numbers of the inputs of the original AIG Aig_ManForEachCi( pLcr->pAig, pObj, i ) { pObj->pData = pLcr; pObj->pNext = (Aig_Obj_t *)(long)i; } // compute the LO/LI offset Offset = Aig_ManCoNum(pLcr->pAig) - Aig_ManCiNum(pLcr->pAig); // create the PIs Aig_ManCleanData( pLcr->pAig ); pNew = Aig_ManStartFrom( pLcr->pAig ); // go over the equivalence classes Vec_PtrForEachEntry( Aig_Obj_t **, pLcr->pCla->vClasses, ppClass, i ) { pMiter = Aig_ManConst0(pNew); for ( c = 0; ppClass[c]; c++ ) { assert( Aig_ObjIsCi(ppClass[c]) ); pObjPo = Aig_ManCo( pLcr->pAig, Offset+(long)ppClass[c]->pNext ); pObjNew = Fra_LcrManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) ); pMiter = Aig_Exor( pNew, pMiter, pObjNew ); } Aig_ObjCreateCo( pNew, pMiter ); } // go over the constant candidates Vec_PtrForEachEntry( Aig_Obj_t *, pLcr->pCla->vClasses1, pObj, i ) { assert( Aig_ObjIsCi(pObj) ); pObjPo = Aig_ManCo( pLcr->pAig, Offset+(long)pObj->pNext ); pMiter = Fra_LcrManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) ); Aig_ObjCreateCo( pNew, pMiter ); } return pNew; } /**Function************************************************************* Synopsis [Remaps partitions into the inputs of original AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_LcrRemapPartitions( Vec_Ptr_t * vParts, Fra_Cla_t * pCla, int * pInToOutPart, int * pInToOutNum ) { Vec_Int_t * vOne, * vOneNew; Aig_Obj_t ** ppClass, * pObjPi; int Out, Offset, i, k, c; // compute the LO/LI offset Offset = Aig_ManCoNum(pCla->pAig) - Aig_ManCiNum(pCla->pAig); Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i ) { vOneNew = Vec_IntAlloc( Vec_IntSize(vOne) ); Vec_IntForEachEntry( vOne, Out, k ) { if ( Out < Vec_PtrSize(pCla->vClasses) ) { ppClass = (Aig_Obj_t **)Vec_PtrEntry( pCla->vClasses, Out ); for ( c = 0; ppClass[c]; c++ ) { pInToOutPart[(long)ppClass[c]->pNext] = i; pInToOutNum[(long)ppClass[c]->pNext] = Vec_IntSize(vOneNew); Vec_IntPush( vOneNew, Offset+(long)ppClass[c]->pNext ); } } else { pObjPi = (Aig_Obj_t *)Vec_PtrEntry( pCla->vClasses1, Out - Vec_PtrSize(pCla->vClasses) ); pInToOutPart[(long)pObjPi->pNext] = i; pInToOutNum[(long)pObjPi->pNext] = Vec_IntSize(vOneNew); Vec_IntPush( vOneNew, Offset+(long)pObjPi->pNext ); } } // replace the class Vec_PtrWriteEntry( vParts, i, vOneNew ); Vec_IntFree( vOne ); } } /**Function************************************************************* Synopsis [Creates AIG of one partition with speculative reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Fra_LcrCreatePart_rec( Fra_Cla_t * pCla, Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return (Aig_Obj_t *)pObj->pData; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsCi(pObj) ) { // Aig_Obj_t * pRepr = Fra_ClassObjRepr(pObj); Aig_Obj_t * pRepr = pCla->pMemRepr[pObj->Id]; if ( pRepr == NULL ) pObj->pData = Aig_ObjCreateCi( pNew ); else { pObj->pData = Fra_LcrCreatePart_rec( pCla, pNew, p, pRepr ); pObj->pData = Aig_NotCond( (Aig_Obj_t *)pObj->pData, pRepr->fPhase ^ pObj->fPhase ); } return (Aig_Obj_t *)pObj->pData; } Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin0(pObj) ); Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin1(pObj) ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); } /**Function************************************************************* Synopsis [Creates AIG of one partition with speculative reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_LcrCreatePart( Fra_Lcr_t * p, Vec_Int_t * vPart ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew; int Out, i; // create new AIG for this partition pNew = Aig_ManStartFrom( p->pAig ); Aig_ManIncrementTravId( p->pAig ); Aig_ObjSetTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) ); Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); Vec_IntForEachEntry( vPart, Out, i ) { pObj = Aig_ManCo( p->pAig, Out ); if ( pObj->fMarkA ) { pObjNew = Fra_LcrCreatePart_rec( p->pCla, pNew, p->pAig, Aig_ObjFanin0(pObj) ); pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); } else pObjNew = Aig_ManConst1( pNew ); Aig_ObjCreateCo( pNew, pObjNew ); } return pNew; } /**Function************************************************************* Synopsis [Marks the nodes belonging to the equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassNodesMark( Fra_Lcr_t * p ) { Aig_Obj_t * pObj, ** ppClass; int i, c, Offset; // compute the LO/LI offset Offset = Aig_ManCoNum(p->pCla->pAig) - Aig_ManCiNum(p->pCla->pAig); // mark the nodes remaining in the classes Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) { pObj = Aig_ManCo( p->pCla->pAig, Offset+(long)pObj->pNext ); pObj->fMarkA = 1; } Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i ) { for ( c = 0; ppClass[c]; c++ ) { pObj = Aig_ManCo( p->pCla->pAig, Offset+(long)ppClass[c]->pNext ); pObj->fMarkA = 1; } } } /**Function************************************************************* Synopsis [Unmarks the nodes belonging to the equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ClassNodesUnmark( Fra_Lcr_t * p ) { Aig_Obj_t * pObj, ** ppClass; int i, c, Offset; // compute the LO/LI offset Offset = Aig_ManCoNum(p->pCla->pAig) - Aig_ManCiNum(p->pCla->pAig); // mark the nodes remaining in the classes Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i ) { pObj = Aig_ManCo( p->pCla->pAig, Offset+(long)pObj->pNext ); pObj->fMarkA = 0; } Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i ) { for ( c = 0; ppClass[c]; c++ ) { pObj = Aig_ManCo( p->pCla->pAig, Offset+(long)ppClass[c]->pNext ); pObj->fMarkA = 0; } } } /**Function************************************************************* Synopsis [Performs choicing of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter, float TimeLimit ) { int nPartSize = 200; int fReprSelect = 0; Fra_Lcr_t * p; Fra_Sml_t * pSml; Fra_Man_t * pTemp; Aig_Man_t * pAigPart, * pAigTemp, * pAigNew = NULL; Vec_Int_t * vPart; int i, nIter; abctime timeSim, clk2, clk3, clk = Abc_Clock(); abctime TimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; if ( Aig_ManNodeNum(pAig) == 0 ) { if ( pnIter ) *pnIter = 0; // Ntl_ManFinalize() requires the following to satisfy an assertion. Aig_ManReprStart(pAig,Aig_ManObjNumMax(pAig)); return Aig_ManDupOrdered(pAig); } assert( Aig_ManRegNum(pAig) > 0 ); // simulate the AIG clk2 = Abc_Clock(); if ( fVerbose ) printf( "Simulating AIG with %d nodes for %d cycles ... ", Aig_ManNodeNum(pAig), nFramesP + 32 ); pSml = Fra_SmlSimulateSeq( pAig, nFramesP, 32, 1, 1 ); if ( fVerbose ) { ABC_PRT( "Time", Abc_Clock() - clk2 ); } timeSim = Abc_Clock() - clk2; // check if simulation discovered non-constant-0 POs if ( fProve && pSml->fNonConstOut ) { pAig->pSeqModel = Fra_SmlGetCounterExample( pSml ); Fra_SmlStop( pSml ); return NULL; } // start the manager p = Lcr_ManAlloc( pAig ); p->nFramesP = nFramesP; p->fVerbose = fVerbose; p->timeSim += timeSim; pTemp = Fra_LcrAigPrepare( pAig ); pTemp->pBmc = (Fra_Bmc_t *)p; pTemp->pSml = pSml; // get preliminary info about equivalence classes pTemp->pCla = p->pCla = Fra_ClassesStart( p->pAig ); Fra_ClassesPrepare( p->pCla, 1, 0 ); p->pCla->pFuncNodeIsConst = Fra_LcrNodeIsConst; p->pCla->pFuncNodesAreEqual = Fra_LcrNodesAreEqual; Fra_SmlStop( pTemp->pSml ); // partition the AIG for latch correspondence computation clk2 = Abc_Clock(); if ( fVerbose ) printf( "Partitioning AIG ... " ); pAigPart = Fra_LcrDeriveAigForPartitioning( p ); p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL ); Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum ); Aig_ManStop( pAigPart ); if ( fVerbose ) { ABC_PRT( "Time", Abc_Clock() - clk2 ); p->timePart += Abc_Clock() - clk2; } // get the initial stats p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); p->nNodesBeg = Aig_ManNodeNum(p->pAig); p->nRegsBeg = Aig_ManRegNum(p->pAig); // perforn interative reduction of the partitions p->fRefining = 1; for ( nIter = 0; p->fRefining; nIter++ ) { p->fRefining = 0; clk3 = Abc_Clock(); // derive AIGs for each partition Fra_ClassNodesMark( p ); Vec_PtrClear( p->vFraigs ); Vec_PtrForEachEntry( Vec_Int_t *, p->vParts, vPart, i ) { if ( TimeLimit != 0.0 && Abc_Clock() > TimeToStop ) { Vec_PtrForEachEntry( Aig_Man_t *, p->vFraigs, pAigPart, i ) Aig_ManStop( pAigPart ); Aig_ManCleanMarkA( pAig ); Aig_ManCleanMarkB( pAig ); printf( "Fra_FraigLatchCorrespondence(): Runtime limit exceeded.\n" ); goto finish; } clk2 = Abc_Clock(); pAigPart = Fra_LcrCreatePart( p, vPart ); p->timeTrav += Abc_Clock() - clk2; clk2 = Abc_Clock(); pAigTemp = Fra_FraigEquivence( pAigPart, nConfMax, 0 ); p->timeFraig += Abc_Clock() - clk2; Vec_PtrPush( p->vFraigs, pAigTemp ); /* { char Name[1000]; sprintf( Name, "part%04d.blif", i ); Aig_ManDumpBlif( pAigPart, Name, NULL, NULL ); } printf( "Finished part %4d (out of %4d). ", i, Vec_PtrSize(p->vParts) ); ABC_PRT( "Time", Abc_Clock() - clk3 ); */ Aig_ManStop( pAigPart ); } Fra_ClassNodesUnmark( p ); // report the intermediate results if ( fVerbose ) { printf( "%3d : Const = %6d. Class = %6d. L = %6d. Part = %3d. ", nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla), Vec_PtrSize(p->vParts) ); ABC_PRT( "T", Abc_Clock() - clk3 ); } // refine the classes Fra_LcrAigPrepareTwo( p->pAig, pTemp ); if ( Fra_ClassesRefine( p->pCla ) ) p->fRefining = 1; if ( Fra_ClassesRefine1( p->pCla, 0, NULL ) ) p->fRefining = 1; // clean the fraigs Vec_PtrForEachEntry( Aig_Man_t *, p->vFraigs, pAigPart, i ) Aig_ManStop( pAigPart ); // repartition if needed if ( 1 ) { clk2 = Abc_Clock(); Vec_VecFree( (Vec_Vec_t *)p->vParts ); pAigPart = Fra_LcrDeriveAigForPartitioning( p ); p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL ); Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum ); Aig_ManStop( pAigPart ); p->timePart += Abc_Clock() - clk2; } } p->nIters = nIter; // move the classes into representatives and reduce AIG clk2 = Abc_Clock(); // Fra_ClassesPrint( p->pCla, 1 ); if ( fReprSelect ) Fra_ClassesSelectRepr( p->pCla ); Fra_ClassesCopyReprs( p->pCla, NULL ); pAigNew = Aig_ManDupRepr( p->pAig, 0 ); Aig_ManSeqCleanup( pAigNew ); // Aig_ManCountMergeRegs( pAigNew ); p->timeUpdate += Abc_Clock() - clk2; p->timeTotal = Abc_Clock() - clk; // get the final stats p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); p->nNodesEnd = Aig_ManNodeNum(pAigNew); p->nRegsEnd = Aig_ManRegNum(pAigNew); finish: ABC_FREE( pTemp ); Lcr_ManFree( p ); if ( pnIter ) *pnIter = nIter; return pAigNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraMan.c000066400000000000000000000263351300674244400233120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Starts the FRAIG manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraMan.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sets the default solving parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ParamsDefault( Fra_Par_t * pPars ) { memset( pPars, 0, sizeof(Fra_Par_t) ); pPars->nSimWords = 32; // the number of words in the simulation info pPars->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached pPars->fPatScores = 0; // enables simulation pattern scoring pPars->MaxScore = 25; // max score after which resimulation is used pPars->fDoSparse = 1; // skips sparse functions // pPars->dActConeRatio = 0.05; // the ratio of cone to be bumped // pPars->dActConeBumpMax = 5.0; // the largest bump of activity pPars->dActConeRatio = 0.3; // the ratio of cone to be bumped pPars->dActConeBumpMax = 10.0; // the largest bump of activity pPars->nBTLimitNode = 100; // conflict limit at a node pPars->nBTLimitMiter = 500000; // conflict limit at an output pPars->nFramesK = 0; // the number of timeframes to unroll pPars->fConeBias = 1; pPars->fRewrite = 0; } /**Function************************************************************* Synopsis [Sets the default solving parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ParamsDefaultSeq( Fra_Par_t * pPars ) { memset( pPars, 0, sizeof(Fra_Par_t) ); pPars->nSimWords = 1; // the number of words in the simulation info pPars->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached pPars->fPatScores = 0; // enables simulation pattern scoring pPars->MaxScore = 25; // max score after which resimulation is used pPars->fDoSparse = 1; // skips sparse functions pPars->dActConeRatio = 0.3; // the ratio of cone to be bumped pPars->dActConeBumpMax = 10.0; // the largest bump of activity pPars->nBTLimitNode = 10000000; // conflict limit at a node pPars->nBTLimitMiter = 500000; // conflict limit at an output pPars->nFramesK = 1; // the number of timeframes to unroll pPars->fConeBias = 0; pPars->fRewrite = 0; pPars->fLatchCorr = 0; } /**Function************************************************************* Synopsis [Starts the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pPars ) { Fra_Man_t * p; Aig_Obj_t * pObj; int i; // allocate the fraiging manager p = ABC_ALLOC( Fra_Man_t, 1 ); memset( p, 0, sizeof(Fra_Man_t) ); p->pPars = pPars; p->pManAig = pManAig; p->nSizeAlloc = Aig_ManObjNumMax( pManAig ); p->nFramesAll = pPars->nFramesK + 1; // allocate storage for sim pattern p->nPatWords = Abc_BitWordNum( (Aig_ManCiNum(pManAig) - Aig_ManRegNum(pManAig)) * p->nFramesAll + Aig_ManRegNum(pManAig) ); p->pPatWords = ABC_ALLOC( unsigned, p->nPatWords ); p->vPiVars = Vec_PtrAlloc( 100 ); // equivalence classes p->pCla = Fra_ClassesStart( pManAig ); // allocate other members p->pMemFraig = ABC_ALLOC( Aig_Obj_t *, p->nSizeAlloc * p->nFramesAll ); memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); // set random number generator // srand( 0xABCABC ); Aig_ManRandom(1); // set the pointer to the manager Aig_ManForEachObj( p->pManAig, pObj, i ) pObj->pData = p; return p; } /**Function************************************************************* Synopsis [Starts the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ManClean( Fra_Man_t * p, int nNodesMax ) { int i; // remove old arrays for ( i = 0; i < p->nMemAlloc; i++ ) if ( p->pMemFanins[i] && p->pMemFanins[i] != (void *)1 ) Vec_PtrFree( p->pMemFanins[i] ); // realloc for the new size if ( p->nMemAlloc < nNodesMax ) { int nMemAllocNew = nNodesMax + 5000; p->pMemFanins = ABC_REALLOC( Vec_Ptr_t *, p->pMemFanins, nMemAllocNew ); p->pMemSatNums = ABC_REALLOC( int, p->pMemSatNums, nMemAllocNew ); p->nMemAlloc = nMemAllocNew; } // prepare for the new run memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc ); memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc ); } /**Function************************************************************* Synopsis [Prepares the new manager to begin fraiging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p ) { Aig_Man_t * pManFraig; Aig_Obj_t * pObj; int i; assert( p->pManFraig == NULL ); // start the fraig package pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) ); pManFraig->pName = Abc_UtilStrsav( p->pManAig->pName ); pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec ); pManFraig->nRegs = p->pManAig->nRegs; pManFraig->nAsserts = p->pManAig->nAsserts; // set the pointers to the available fraig nodes Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), 0, Aig_ManConst1(pManFraig) ); Aig_ManForEachCi( p->pManAig, pObj, i ) Fra_ObjSetFraig( pObj, 0, Aig_ObjCreateCi(pManFraig) ); // set the pointers to the manager Aig_ManForEachObj( pManFraig, pObj, i ) pObj->pData = p; // allocate memory for mapping FRAIG nodes into SAT numbers and fanins p->nMemAlloc = p->nSizeAlloc; p->pMemFanins = ABC_ALLOC( Vec_Ptr_t *, p->nMemAlloc ); memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc ); p->pMemSatNums = ABC_ALLOC( int, p->nMemAlloc ); memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc ); // make sure the satisfying assignment is node assigned assert( pManFraig->pData == NULL ); return pManFraig; } /**Function************************************************************* Synopsis [Finalizes the combinational miter after fraiging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ManFinalizeComb( Fra_Man_t * p ) { Aig_Obj_t * pObj; int i; // add the POs Aig_ManForEachCo( p->pManAig, pObj, i ) Aig_ObjCreateCo( p->pManFraig, Fra_ObjChild0Fra(pObj,0) ); // postprocess Aig_ManCleanMarkB( p->pManFraig ); } /**Function************************************************************* Synopsis [Stops the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ManStop( Fra_Man_t * p ) { if ( p->pPars->fVerbose ) Fra_ManPrint( p ); // save mapping from original nodes into FRAIG nodes if ( p->pManAig ) { if ( p->pManAig->pObjCopies ) ABC_FREE( p->pManAig->pObjCopies ); p->pManAig->pObjCopies = p->pMemFraig; p->pMemFraig = NULL; } Fra_ManClean( p, 0 ); if ( p->vTimeouts ) Vec_PtrFree( p->vTimeouts ); if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); if ( p->pSat ) sat_solver_delete( p->pSat ); if ( p->pCla ) Fra_ClassesStop( p->pCla ); if ( p->pSml ) Fra_SmlStop( p->pSml ); if ( p->vCex ) Vec_IntFree( p->vCex ); if ( p->vOneHots ) Vec_IntFree( p->vOneHots ); ABC_FREE( p->pMemFraig ); ABC_FREE( p->pMemFanins ); ABC_FREE( p->pMemSatNums ); ABC_FREE( p->pPatWords ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints stats for the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ManPrint( Fra_Man_t * p ) { double nMemory = 1.0*Aig_ManObjNumMax(p->pManAig)*(p->pSml->nWordsTotal*sizeof(unsigned)+6*sizeof(void*))/(1<<20); printf( "SimWord = %d. Round = %d. Mem = %0.2f MB. LitBeg = %d. LitEnd = %d. (%6.2f %%).\n", p->pPars->nSimWords, p->pSml->nSimRounds, nMemory, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/(p->nLitsBeg?p->nLitsBeg:1) ); printf( "Proof = %d. Cex = %d. Fail = %d. FailReal = %d. C-lim = %d. ImpRatio = %6.2f %%\n", p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->pPars->nBTLimitNode, Fra_ImpComputeStateSpaceRatio(p) ); printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1), p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) ); if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); if ( p->pPars->fUse1Hot ) Fra_OneHotEstimateCoverage( p, p->vOneHots ); ABC_PRT( "AIG simulation ", p->pSml->timeSim ); ABC_PRT( "AIG traversal ", p->timeTrav ); if ( p->timeRwr ) { ABC_PRT( "AIG rewriting ", p->timeRwr ); } 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 ); } if ( p->nSpeculs ) printf( "Speculations = %d.\n", p->nSpeculs ); fflush( stdout ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraPart.c000066400000000000000000000175401300674244400235030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraPart.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Partitioning for induction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraPart.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim ) { // Bar_Progress_t * pProgress; Vec_Vec_t * vSupps, * vSuppsIn; Vec_Ptr_t * vSuppsNew; Vec_Int_t * vSupNew, * vSup, * vSup2, * vTemp;//, * vSupIn; Vec_Int_t * vOverNew, * vQuantNew; Aig_Obj_t * pObj; int i, k, nCommon, CountOver, CountQuant; int nTotalSupp, nTotalSupp2, Entry, Largest;//, iVar; double Ratio, R; abctime clk; nTotalSupp = 0; nTotalSupp2 = 0; Ratio = 0.0; // compute supports clk = Abc_Clock(); vSupps = (Vec_Vec_t *)Aig_ManSupports( p ); ABC_PRT( "Supports", Abc_Clock() - clk ); // remove last entry Aig_ManForEachCo( p, pObj, i ) { vSup = Vec_VecEntryInt( vSupps, i ); Vec_IntPop( vSup ); // remember support // pObj->pNext = (Aig_Obj_t *)vSup; } // create reverse supports clk = Abc_Clock(); vSuppsIn = Vec_VecStart( Aig_ManCiNum(p) ); Aig_ManForEachCo( p, pObj, i ) { vSup = Vec_VecEntryInt( vSupps, i ); Vec_IntForEachEntry( vSup, Entry, k ) Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i ); } ABC_PRT( "Inverse ", Abc_Clock() - clk ); clk = Abc_Clock(); // compute extended supports Largest = 0; vSuppsNew = Vec_PtrAlloc( Aig_ManCoNum(p) ); vOverNew = Vec_IntAlloc( Aig_ManCoNum(p) ); vQuantNew = Vec_IntAlloc( Aig_ManCoNum(p) ); // pProgress = Bar_ProgressStart( stdout, Aig_ManCoNum(p) ); Aig_ManForEachCo( p, pObj, i ) { // Bar_ProgressUpdate( pProgress, i, NULL ); // get old supports vSup = Vec_VecEntryInt( vSupps, i ); if ( Vec_IntSize(vSup) < 2 ) continue; // compute new supports CountOver = CountQuant = 0; vSupNew = Vec_IntDup( vSup ); // go through the nodes where the first var appears Aig_ManForEachCo( p, pObj, k ) // iVar = Vec_IntEntry( vSup, 0 ); // vSupIn = Vec_VecEntry( vSuppsIn, iVar ); // Vec_IntForEachEntry( vSupIn, Entry, k ) { // pObj = Aig_ManObj( p, Entry ); // get support of this output // vSup2 = (Vec_Int_t *)pObj->pNext; vSup2 = Vec_VecEntryInt( vSupps, k ); // count the number of common vars nCommon = Vec_IntTwoCountCommon(vSup, vSup2); if ( nCommon < 2 ) continue; if ( nCommon > nComLim ) { vSupNew = Vec_IntTwoMerge( vTemp = vSupNew, vSup2 ); Vec_IntFree( vTemp ); CountOver++; } else CountQuant++; } // save the results Vec_PtrPush( vSuppsNew, vSupNew ); Vec_IntPush( vOverNew, CountOver ); Vec_IntPush( vQuantNew, CountQuant ); if ( Largest < Vec_IntSize(vSupNew) ) Largest = Vec_IntSize(vSupNew); nTotalSupp += Vec_IntSize(vSup); nTotalSupp2 += Vec_IntSize(vSupNew); if ( Vec_IntSize(vSup) ) R = Vec_IntSize(vSupNew) / Vec_IntSize(vSup); else R = 0; Ratio += R; if ( R < 5.0 ) continue; printf( "%6d : ", i ); printf( "S = %5d. ", Vec_IntSize(vSup) ); printf( "SNew = %5d. ", Vec_IntSize(vSupNew) ); printf( "R = %7.2f. ", R ); printf( "Over = %5d. ", CountOver ); printf( "Quant = %5d. ", CountQuant ); printf( "\n" ); /* Vec_IntForEachEntry( vSupNew, Entry, k ) printf( "%d ", Entry ); printf( "\n" ); */ } // Bar_ProgressStop( pProgress ); ABC_PRT( "Scanning", Abc_Clock() - clk ); // print cumulative statistics printf( "PIs = %6d. POs = %6d. Lim = %3d. AveS = %3d. SN = %3d. R = %4.2f Max = %5d.\n", Aig_ManCiNum(p), Aig_ManCoNum(p), nComLim, nTotalSupp/Aig_ManCoNum(p), nTotalSupp2/Aig_ManCoNum(p), Ratio/Aig_ManCoNum(p), Largest ); Vec_VecFree( vSupps ); Vec_VecFree( vSuppsIn ); Vec_VecFree( (Vec_Vec_t *)vSuppsNew ); Vec_IntFree( vOverNew ); Vec_IntFree( vQuantNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_ManPartitionTest2( Aig_Man_t * p ) { Vec_Vec_t * vSupps, * vSuppsIn; Vec_Int_t * vSup, * vSup2, * vSup3; Aig_Obj_t * pObj; int Entry, Entry2, Entry3, Counter; int i, k, m, n; abctime clk; char * pSupp; // compute supports clk = Abc_Clock(); vSupps = (Vec_Vec_t *)Aig_ManSupports( p ); ABC_PRT( "Supports", Abc_Clock() - clk ); // remove last entry Aig_ManForEachCo( p, pObj, i ) { vSup = Vec_VecEntryInt( vSupps, i ); Vec_IntPop( vSup ); // remember support // pObj->pNext = (Aig_Obj_t *)vSup; } // create reverse supports clk = Abc_Clock(); vSuppsIn = Vec_VecStart( Aig_ManCiNum(p) ); Aig_ManForEachCo( p, pObj, i ) { if ( i == p->nAsserts ) break; vSup = Vec_VecEntryInt( vSupps, i ); Vec_IntForEachEntry( vSup, Entry, k ) Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i ); } ABC_PRT( "Inverse ", Abc_Clock() - clk ); // create affective supports clk = Abc_Clock(); pSupp = ABC_ALLOC( char, Aig_ManCiNum(p) ); Aig_ManForEachCo( p, pObj, i ) { if ( i % 50 != 0 ) continue; vSup = Vec_VecEntryInt( vSupps, i ); memset( pSupp, 0, sizeof(char) * Aig_ManCiNum(p) ); // go through each input of this output Vec_IntForEachEntry( vSup, Entry, k ) { pSupp[Entry] = 1; vSup2 = Vec_VecEntryInt( vSuppsIn, Entry ); // go though each assert of this input Vec_IntForEachEntry( vSup2, Entry2, m ) { vSup3 = Vec_VecEntryInt( vSupps, Entry2 ); // go through each input of this assert Vec_IntForEachEntry( vSup3, Entry3, n ) { pSupp[Entry3] = 1; } } } // count the entries Counter = 0; for ( m = 0; m < Aig_ManCiNum(p); m++ ) Counter += pSupp[m]; printf( "%d(%d) ", Vec_IntSize(vSup), Counter ); } printf( "\n" ); ABC_PRT( "Extension ", Abc_Clock() - clk ); ABC_FREE( pSupp ); Vec_VecFree( vSupps ); Vec_VecFree( vSuppsIn ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraSat.c000066400000000000000000000427601300674244400233260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraSat.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Runs equivalence test for the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) { int pLits[4], RetValue, RetValue1, nBTLimit; abctime clk;//, clk2 = Abc_Clock(); int status; // make sure the nodes are not complemented assert( !Aig_IsComplement(pNew) ); assert( !Aig_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->pPars->nBTLimitNode; if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) ) { p->nSatFails++; // fail immediately // return -1; if ( nBTLimit <= 10 ) return -1; nBTLimit = (int)pow(nBTLimit, 0.7); } p->nSatCalls++; p->nSatCallsRecent++; // make sure the solver is allocated and has enough variables if ( p->pSat == NULL ) { p->pSat = sat_solver_new(); p->nSatVars = 1; sat_solver_setnvars( p->pSat, 1000 ); // 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 Fra_CnfNodeAddToSolver( p, pOld, pNew ); if ( p->pSat->qtail != p->pSat->qhead ) { status = sat_solver_simplify(p->pSat); assert( status != 0 ); assert( p->pSat->qtail == p->pSat->qhead ); } // prepare variable activity if ( p->pPars->fConeBias ) Fra_SetActivityFactors( p, pOld, pNew ); // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 clk = Abc_Clock(); pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 ); pLits[1] = toLitCond( Fra_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; Fra_SmlSavePattern( p ); p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatFail += Abc_Clock() - clk; // mark the node as the failed node if ( pOld != p->pManFraig->pConst1 ) pOld->fMarkB = 1; pNew->fMarkB = 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( Fra_ObjSatNum(pOld), 1 ); pLits[1] = toLitCond( Fra_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; Fra_SmlSavePattern( p ); p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatFail += Abc_Clock() - clk; // mark the node as the failed node pOld->fMarkB = 1; pNew->fMarkB = 1; p->nSatFailsReal++; return -1; } /* // check BDD proof { int RetVal; ABC_PRT( "Sat", Abc_Clock() - clk2 ); clk2 = Abc_Clock(); RetVal = Fra_NodesAreEquivBdd( 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 the result of test for pObj => pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR ) { int pLits[4], RetValue, RetValue1, nBTLimit; abctime clk;//, clk2 = Abc_Clock(); int status; // make sure the nodes are not complemented assert( !Aig_IsComplement(pNew) ); assert( !Aig_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->pPars->nBTLimitNode; /* if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) ) { 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(); p->nSatVars = 1; sat_solver_setnvars( p->pSat, 1000 ); // 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 Fra_CnfNodeAddToSolver( p, pOld, pNew ); if ( p->pSat->qtail != p->pSat->qhead ) { status = sat_solver_simplify(p->pSat); assert( status != 0 ); assert( p->pSat->qtail == p->pSat->qhead ); } // prepare variable activity if ( p->pPars->fConeBias ) Fra_SetActivityFactors( p, pOld, pNew ); // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 clk = Abc_Clock(); // pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 ); // pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); pLits[0] = toLitCond( Fra_ObjSatNum(pOld), fComplL ); pLits[1] = toLitCond( Fra_ObjSatNum(pNew), !fComplR ); //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; Fra_SmlSavePattern( p ); p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatFail += Abc_Clock() - clk; // mark the node as the failed node if ( pOld != p->pManFraig->pConst1 ) pOld->fMarkB = 1; pNew->fMarkB = 1; p->nSatFailsReal++; return -1; } // return SAT proof p->nSatProof++; return 1; } /**Function************************************************************* Synopsis [Runs the result of test for pObj => pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_NodesAreClause( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR ) { int pLits[4], RetValue, RetValue1, nBTLimit; abctime clk;//, clk2 = Abc_Clock(); int status; // make sure the nodes are not complemented assert( !Aig_IsComplement(pNew) ); assert( !Aig_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->pPars->nBTLimitNode; /* if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) ) { 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(); p->nSatVars = 1; sat_solver_setnvars( p->pSat, 1000 ); // 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 Fra_CnfNodeAddToSolver( p, pOld, pNew ); if ( p->pSat->qtail != p->pSat->qhead ) { status = sat_solver_simplify(p->pSat); assert( status != 0 ); assert( p->pSat->qtail == p->pSat->qhead ); } // prepare variable activity if ( p->pPars->fConeBias ) Fra_SetActivityFactors( p, pOld, pNew ); // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 clk = Abc_Clock(); // pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 ); // pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); pLits[0] = toLitCond( Fra_ObjSatNum(pOld), !fComplL ); pLits[1] = toLitCond( Fra_ObjSatNum(pNew), !fComplR ); //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; Fra_SmlSavePattern( p ); p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatFail += Abc_Clock() - clk; // mark the node as the failed node if ( pOld != p->pManFraig->pConst1 ) pOld->fMarkB = 1; pNew->fMarkB = 1; p->nSatFailsReal++; return -1; } // return SAT proof p->nSatProof++; return 1; } /**Function************************************************************* Synopsis [Runs equivalence test for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew ) { int pLits[2], RetValue1, RetValue; abctime clk; // make sure the nodes are not complemented assert( !Aig_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(); p->nSatVars = 1; sat_solver_setnvars( p->pSat, 1000 ); // 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 Fra_CnfNodeAddToSolver( p, NULL, pNew ); // prepare variable activity if ( p->pPars->fConeBias ) Fra_SetActivityFactors( p, NULL, pNew ); // solve under assumptions clk = Abc_Clock(); pLits[0] = toLitCond( Fra_ObjSatNum(pNew), pNew->fPhase ); RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, (ABC_INT64_T)p->pPars->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 ) Fra_SmlSavePattern( p ); p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatFail += Abc_Clock() - clk; // mark the node as the failed node pNew->fMarkB = 1; p->nSatFailsReal++; return -1; } // return SAT proof p->nSatProof++; return 1; } /**Function************************************************************* Synopsis [Sets variable activities in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SetActivityFactors_rec( Fra_Man_t * p, Aig_Obj_t * pObj, int LevelMin, int LevelMax ) { Vec_Ptr_t * vFanins; Aig_Obj_t * pFanin; int i, Counter = 0; assert( !Aig_IsComplement(pObj) ); assert( Fra_ObjSatNum(pObj) ); // skip visited variables if ( Aig_ObjIsTravIdCurrent(p->pManFraig, pObj) ) return 0; Aig_ObjSetTravIdCurrent(p->pManFraig, pObj); // add the PI to the list if ( pObj->Level <= (unsigned)LevelMin || Aig_ObjIsCi(pObj) ) return 0; // set the factor of this variable // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump if ( p->pSat->factors == NULL ) p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); p->pSat->factors[Fra_ObjSatNum(pObj)] = p->pPars->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); veci_push(&p->pSat->act_vars, Fra_ObjSatNum(pObj)); // explore the fanins vFanins = Fra_ObjFaninVec( pObj ); Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, i ) Counter += Fra_SetActivityFactors_rec( p, Aig_Regular(pFanin), LevelMin, LevelMax ); return 1 + Counter; } /**Function************************************************************* Synopsis [Sets variable activities in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_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 Aig_ManIncrementTravId( p->pManFraig ); // determine the min and max level to visit assert( p->pPars->dActConeRatio > 0 && p->pPars->dActConeRatio < 1 ); LevelMax = Abc_MaxInt( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); LevelMin = (int)(LevelMax * (1.0 - p->pPars->dActConeRatio)); // traverse if ( pOld && !Aig_ObjIsConst1(pOld) ) Fra_SetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); if ( pNew && !Aig_ObjIsConst1(pNew) ) Fra_SetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); //Fra_PrintActivity( p ); p->timeTrav += Abc_Clock() - clk; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraSec.c000066400000000000000000000600321300674244400233010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraSec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [Performs SEC based on seq sweeping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraSec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" #include "aig/ioa/ioa.h" #include "proof/int/int.h" #include "proof/ssw/ssw.h" #include "aig/saig/saig.h" #include "bdd/bbr/bbr.h" #include "proof/pdr/pdr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SecSetDefaultParams( Fra_Sec_t * p ) { memset( p, 0, sizeof(Fra_Sec_t) ); p->fTryComb = 1; // try CEC call as a preprocessing step p->fTryBmc = 1; // try BMC call as a preprocessing step p->nFramesMax = 4; // the max number of frames used for induction p->nBTLimit = 1000; // conflict limit at a node during induction p->nBTLimitGlobal = 5000000; // global conflict limit during induction p->nBTLimitInter = 10000; // conflict limit during interpolation p->nBddVarsMax = 150; // the limit on the number of registers in BDD reachability p->nBddMax = 50000; // the limit on the number of BDD nodes p->nBddIterMax = 1000000; // the limit on the number of BDD iterations p->fPhaseAbstract = 0; // enables phase abstraction p->fRetimeFirst = 1; // enables most-forward retiming at the beginning p->fRetimeRegs = 1; // enables min-register retiming at the beginning p->fFraiging = 1; // enables fraiging at the beginning p->fInduction = 1; // enables the use of induction (signal correspondence) p->fInterpolation = 1; // enables interpolation p->fInterSeparate = 0; // enables interpolation for each outputs separately p->fReachability = 1; // enables BDD based reachability p->fReorderImage = 1; // enables variable reordering during image computation p->fStopOnFirstFail = 1; // enables stopping after first output of a miter has failed to prove p->fUseNewProver = 0; // enables new prover p->fUsePdr = 1; // enables PDR p->nPdrTimeout = 60; // enabled PDR timeout p->fSilent = 0; // disables all output p->fVerbose = 0; // enables verbose reporting of statistics p->fVeryVerbose = 0; // enables very verbose reporting p->TimeLimit = 0; // enables the timeout // internal parameters p->fReportSolution = 0; // enables specialized format for reporting solution } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult ) { Ssw_Pars_t Pars2, * pPars2 = &Pars2; Fra_Ssw_t Pars, * pPars = &Pars; Fra_Sml_t * pSml; Aig_Man_t * pNew, * pTemp; int nFrames, RetValue, nIter; abctime clk, clkTotal = Abc_Clock(); int TimeOut = 0; int fLatchCorr = 0; float TimeLeft = 0.0; pParSec->nSMnumber = -1; // try the miter before solving pNew = Aig_ManDupSimple( p ); RetValue = Fra_FraigMiterStatus( pNew ); if ( RetValue >= 0 ) goto finish; // prepare parameters memset( pPars, 0, sizeof(Fra_Ssw_t) ); pPars->fLatchCorr = fLatchCorr; pPars->fVerbose = pParSec->fVeryVerbose; if ( pParSec->fVerbose ) { printf( "Original miter: Latches = %5d. Nodes = %6d.\n", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); } //Aig_ManDumpBlif( pNew, "after.blif", NULL, NULL ); // perform sequential cleanup clk = Abc_Clock(); if ( pNew->nRegs ) pNew = Aig_ManReduceLaches( pNew, 0 ); if ( pNew->nRegs ) pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 ); if ( pParSec->fVerbose ) { printf( "Sequential cleanup: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } RetValue = Fra_FraigMiterStatus( pNew ); if ( RetValue >= 0 ) goto finish; // perform phase abstraction clk = Abc_Clock(); if ( pParSec->fPhaseAbstract ) { extern Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose ); pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); pNew = Saig_ManPhaseAbstractAuto( pTemp = pNew, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Phase abstraction: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // perform forward retiming if ( pParSec->fRetimeFirst && pNew->nRegs ) { clk = Abc_Clock(); // pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); pNew = Saig_ManRetimeForward( pTemp = pNew, 100, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Forward retiming: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // run latch correspondence clk = Abc_Clock(); if ( pNew->nRegs ) { pNew = Aig_ManDupOrdered( pTemp = pNew ); // pNew = Aig_ManDupDfs( pTemp = pNew ); Aig_ManStop( pTemp ); /* if ( RetValue == -1 && pParSec->TimeLimit ) { TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); if ( TimeLeft == 0.0 ) { if ( !pParSec->fSilent ) printf( "Runtime limit exceeded.\n" ); RetValue = -1; TimeOut = 1; goto finish; } } */ // pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 1000, 1, pParSec->fVeryVerbose, &nIter, TimeLeft ); //Aig_ManDumpBlif( pNew, "ex.blif", NULL, NULL ); Ssw_ManSetDefaultParamsLcorr( pPars2 ); pNew = Ssw_LatchCorrespondence( pTemp = pNew, pPars2 ); nIter = pPars2->nIters; // prepare parameters for scorr Ssw_ManSetDefaultParams( pPars2 ); if ( pTemp->pSeqModel ) { if ( !Saig_ManVerifyCex( pTemp, pTemp->pSeqModel ) ) printf( "Fra_FraigSec(): Counter-example verification has FAILED.\n" ); if ( Saig_ManPiNum(p) != Saig_ManPiNum(pTemp) ) printf( "The counter-example is invalid because of phase abstraction.\n" ); else { ABC_FREE( p->pSeqModel ); p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) ); ABC_FREE( pTemp->pSeqModel ); } } if ( pNew == NULL ) { if ( p->pSeqModel ) { RetValue = 0; if ( !pParSec->fSilent ) { printf( "Networks are NOT EQUIVALENT after simulation. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( pParSec->fReportSolution && !pParSec->fRecursive ) { printf( "SOLUTION: FAIL " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } Aig_ManStop( pTemp ); return RetValue; } pNew = pTemp; RetValue = -1; TimeOut = 1; goto finish; } Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Latch-corr (I=%3d): Latches = %5d. Nodes = %6d. ", nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } /* if ( RetValue == -1 && pParSec->TimeLimit ) { TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); if ( TimeLeft == 0.0 ) { if ( !pParSec->fSilent ) printf( "Runtime limit exceeded.\n" ); RetValue = -1; TimeOut = 1; goto finish; } } */ // perform fraiging if ( pParSec->fFraiging ) { clk = Abc_Clock(); pNew = Fra_FraigEquivence( pTemp = pNew, 100, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Fraiging: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } if ( pNew->nRegs == 0 ) RetValue = Fra_FraigCec( &pNew, 100000, 0 ); RetValue = Fra_FraigMiterStatus( pNew ); if ( RetValue >= 0 ) goto finish; /* if ( RetValue == -1 && pParSec->TimeLimit ) { TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); if ( TimeLeft == 0.0 ) { if ( !pParSec->fSilent ) printf( "Runtime limit exceeded.\n" ); RetValue = -1; TimeOut = 1; goto finish; } } */ // perform min-area retiming if ( pParSec->fRetimeRegs && pNew->nRegs ) { // extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); clk = Abc_Clock(); pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); // pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 ); Aig_ManStop( pTemp ); pNew = Aig_ManDupOrdered( pTemp = pNew ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // perform seq sweeping while increasing the number of frames RetValue = Fra_FraigMiterStatus( pNew ); if ( RetValue == -1 && pParSec->fInduction ) for ( nFrames = 1; nFrames <= pParSec->nFramesMax; nFrames *= 2 ) { /* if ( RetValue == -1 && pParSec->TimeLimit ) { TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); if ( TimeLeft == 0.0 ) { if ( !pParSec->fSilent ) printf( "Runtime limit exceeded.\n" ); RetValue = -1; TimeOut = 1; goto finish; } } */ clk = Abc_Clock(); pPars->nFramesK = nFrames; pPars->TimeLimit = TimeLeft; pPars->fSilent = pParSec->fSilent; // pNew = Fra_FraigInduction( pTemp = pNew, pPars ); pPars2->nFramesK = nFrames; pPars2->nBTLimit = pParSec->nBTLimit; pPars2->nBTLimitGlobal = pParSec->nBTLimitGlobal; // pPars2->nBTLimit = 1000 * nFrames; if ( RetValue == -1 && pPars2->nConflicts > pPars2->nBTLimitGlobal ) { if ( !pParSec->fSilent ) printf( "Global conflict limit (%d) exceeded.\n", pPars2->nBTLimitGlobal ); RetValue = -1; TimeOut = 1; goto finish; } Aig_ManSetRegNum( pNew, pNew->nRegs ); // pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 ); if ( Aig_ManRegNum(pNew) > 0 ) pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 ); else pNew = Aig_ManDupSimpleDfs( pTemp = pNew ); if ( pNew == NULL ) { pNew = pTemp; RetValue = -1; TimeOut = 1; goto finish; } // printf( "Total conflicts = %d.\n", pPars2->nConflicts ); Aig_ManStop( pTemp ); RetValue = Fra_FraigMiterStatus( pNew ); if ( pParSec->fVerbose ) { printf( "K-step (K=%2d,I=%3d): Latches = %5d. Nodes = %6d. ", nFrames, pPars2->nIters, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( RetValue != -1 ) break; // perform retiming // if ( pParSec->fRetimeFirst && pNew->nRegs ) if ( pNew->nRegs ) { // extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); clk = Abc_Clock(); pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); // pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 ); Aig_ManStop( pTemp ); pNew = Aig_ManDupOrdered( pTemp = pNew ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } if ( pNew->nRegs ) pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 ); // perform rewriting clk = Abc_Clock(); pNew = Aig_ManDupOrdered( pTemp = pNew ); Aig_ManStop( pTemp ); // pNew = Dar_ManRewriteDefault( pTemp = pNew ); pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Rewriting: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // perform sequential simulation if ( pNew->nRegs ) { clk = Abc_Clock(); pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000), 1 ); if ( pParSec->fVerbose ) { printf( "Seq simulation : Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( pSml->fNonConstOut ) { pNew->pSeqModel = Fra_SmlGetCounterExample( pSml ); // transfer to the original manager if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) ) printf( "The counter-example is invalid because of phase abstraction.\n" ); else { ABC_FREE( p->pSeqModel ); p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) ); ABC_FREE( pNew->pSeqModel ); } Fra_SmlStop( pSml ); Aig_ManStop( pNew ); RetValue = 0; if ( !pParSec->fSilent ) { printf( "Networks are NOT EQUIVALENT after simulation. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( pParSec->fReportSolution && !pParSec->fRecursive ) { printf( "SOLUTION: FAIL " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } return RetValue; } Fra_SmlStop( pSml ); } } // get the miter status RetValue = Fra_FraigMiterStatus( pNew ); // try interplation clk = Abc_Clock(); Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) ); if ( pParSec->fInterpolation && RetValue == -1 && Aig_ManRegNum(pNew) > 0 ) { Inter_ManParams_t Pars, * pPars = &Pars; int Depth; ABC_FREE( pNew->pSeqModel ); Inter_ManSetDefaultParams( pPars ); // pPars->nBTLimit = 100; pPars->nBTLimit = pParSec->nBTLimitInter; pPars->fVerbose = pParSec->fVeryVerbose; if ( Saig_ManPoNum(pNew) == 1 ) { RetValue = Inter_ManPerformInterpolation( pNew, pPars, &Depth ); } else if ( pParSec->fInterSeparate ) { Abc_Cex_t * pCex = NULL; Aig_Man_t * pTemp, * pAux; Aig_Obj_t * pObjPo; int i, Counter = 0; Saig_ManForEachPo( pNew, pObjPo, i ) { if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pNew) ) continue; if ( pPars->fVerbose ) printf( "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pNew) ); pTemp = Aig_ManDupOneOutput( pNew, i, 1 ); pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 ); Aig_ManStop( pAux ); if ( Saig_ManRegNum(pTemp) > 0 ) { RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &Depth ); if ( pTemp->pSeqModel ) { pCex = p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) ); pCex->iPo = i; Aig_ManStop( pTemp ); break; } // if solved, remove the output if ( RetValue == 1 ) { Aig_ObjPatchFanin0( pNew, pObjPo, Aig_ManConst0(pNew) ); // printf( "Output %3d : Solved ", i ); } else { Counter++; // printf( "Output %3d : Undec ", i ); } } else Counter++; // Aig_ManPrintStats( pTemp ); Aig_ManStop( pTemp ); printf( "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pNew) ); } Aig_ManCleanup( pNew ); if ( pCex == NULL ) { printf( "Interpolation left %d (out of %d) outputs unsolved \n", Counter, Saig_ManPoNum(pNew) ); if ( Counter ) RetValue = -1; } pNew = Aig_ManDupUnsolvedOutputs( pTemp = pNew, 1 ); Aig_ManStop( pTemp ); pNew = Aig_ManScl( pTemp = pNew, 1, 1, 0, -1, -1, 0, 0 ); Aig_ManStop( pTemp ); } else { Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew ); RetValue = Inter_ManPerformInterpolation( pNewOrpos, pPars, &Depth ); if ( pNewOrpos->pSeqModel ) { Abc_Cex_t * pCex; pCex = pNew->pSeqModel = pNewOrpos->pSeqModel; pNewOrpos->pSeqModel = NULL; pCex->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ); } Aig_ManStop( pNewOrpos ); } if ( pParSec->fVerbose ) { if ( RetValue == 1 ) printf( "Property proved using interpolation. " ); else if ( RetValue == 0 ) printf( "Property DISPROVED in frame %d using interpolation. ", Depth ); else if ( RetValue == -1 ) printf( "Property UNDECIDED after interpolation. " ); else assert( 0 ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // try reachability analysis if ( pParSec->fReachability && RetValue == -1 && Aig_ManRegNum(pNew) > 0 && Aig_ManRegNum(pNew) < pParSec->nBddVarsMax ) { Saig_ParBbr_t Pars, * pPars = &Pars; Bbr_ManSetDefaultParams( pPars ); pPars->TimeLimit = 0; pPars->nBddMax = pParSec->nBddMax; pPars->nIterMax = pParSec->nBddIterMax; pPars->fPartition = 1; pPars->fReorder = 1; pPars->fReorderImage = 1; pPars->fVerbose = 0; pPars->fSilent = pParSec->fSilent; pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); RetValue = Aig_ManVerifyUsingBdds( pNew, pPars ); } // try PDR if ( pParSec->fUsePdr && RetValue == -1 && Aig_ManRegNum(pNew) > 0 ) { Pdr_Par_t Pars, * pPars = &Pars; Pdr_ManSetDefaultParams( pPars ); pPars->nTimeOut = pParSec->nPdrTimeout; pPars->fVerbose = pParSec->fVerbose; if ( pParSec->fVerbose ) printf( "Running property directed reachability...\n" ); RetValue = Pdr_ManSolve( pNew, pPars ); if ( pNew->pSeqModel ) pNew->pSeqModel->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ); } finish: // report the miter if ( RetValue == 1 ) { if ( !pParSec->fSilent ) { printf( "Networks are equivalent. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( pParSec->fReportSolution && !pParSec->fRecursive ) { printf( "SOLUTION: PASS " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } } else if ( RetValue == 0 ) { if ( pNew->pSeqModel == NULL ) { int i; // if the CEX is not derives, it is because tricial CEX should be assumed pNew->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pNew), pNew->nTruePis, 1 ); // if the CEX does not work, we need to change PIs to 1 because // the only way it can happen is when a PO is equal to a PI... if ( Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ) == -1 ) for ( i = 0; i < pNew->nTruePis; i++ ) Abc_InfoSetBit( pNew->pSeqModel->pData, i ); } if ( !pParSec->fSilent ) { printf( "Networks are NOT EQUIVALENT. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( pParSec->fReportSolution && !pParSec->fRecursive ) { printf( "SOLUTION: FAIL " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } } else { /////////////////////////////////// // save intermediate result extern void Abc_FrameSetSave1( void * pAig ); Abc_FrameSetSave1( Aig_ManDupSimple(pNew) ); /////////////////////////////////// if ( !pParSec->fSilent ) { printf( "Networks are UNDECIDED. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( pParSec->fReportSolution && !pParSec->fRecursive ) { printf( "SOLUTION: UNDECIDED " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( !TimeOut && !pParSec->fSilent ) { static int Counter = 1; char pFileName[1000]; pParSec->nSMnumber = Counter; sprintf( pFileName, "sm%02d.aig", Counter++ ); Ioa_WriteAiger( pNew, pFileName, 0, 0 ); printf( "The unsolved reduced miter is written into file \"%s\".\n", pFileName ); } } if ( pNew->pSeqModel ) { if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) ) printf( "The counter-example is invalid because of phase abstraction.\n" ); else { ABC_FREE( p->pSeqModel ); p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) ); ABC_FREE( pNew->pSeqModel ); } } if ( ppResult != NULL ) *ppResult = Aig_ManDupSimpleDfs( pNew ); if ( pNew ) Aig_ManStop( pNew ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fraSim.c000066400000000000000000001061101300674244400233150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fraSim.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" #include "aig/saig/saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize ) { Fra_Man_t * p = (Fra_Man_t *)pObj->pData; 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 * pSims; unsigned uHash; int i; // assert( p->pSml->nWordsTotal <= 128 ); uHash = 0; pSims = Fra_ObjSim(p->pSml, pObj->Id); for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) uHash ^= pSims[i] * s_FPrimes[i & 0x7F]; return uHash % nTableSize; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SmlNodeIsConst( Aig_Obj_t * pObj ) { Fra_Man_t * p = (Fra_Man_t *)pObj->pData; unsigned * pSims; int i; pSims = Fra_ObjSim(p->pSml, pObj->Id); for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) if ( pSims[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation infos are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { Fra_Man_t * p = (Fra_Man_t *)pObj0->pData; unsigned * pSims0, * pSims1; int i; pSims0 = Fra_ObjSim(p->pSml, pObj0->Id); pSims1 = Fra_ObjSim(p->pSml, pObj1->Id); for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) if ( pSims0[i] != pSims1[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Counts the number of 1s in the XOR of simulation data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right ) { unsigned * pSimL, * pSimR; int k, Counter = 0; pSimL = Fra_ObjSim( p, Left ); pSimR = Fra_ObjSim( p, Right ); for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] ); return Counter; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SmlNodeIsZero( Fra_Sml_t * p, Aig_Obj_t * pObj ) { unsigned * pSims; int i; pSims = Fra_ObjSim(p, pObj->Id); for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) if ( pSims[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Counts the number of one's in the patten of the output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj ) { unsigned * pSims; int i, Counter = 0; pSims = Fra_ObjSim(p, pObj->Id); for ( i = 0; i < p->nWordsTotal; i++ ) Counter += Aig_WordCountOnes( pSims[i] ); return Counter; } /**Function************************************************************* Synopsis [Generated const 0 pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlSavePattern0( Fra_Man_t * p, int fInit ) { memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); } /**Function************************************************************* Synopsis [[Generated const 1 pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlSavePattern1( Fra_Man_t * p, int fInit ) { Aig_Obj_t * pObj; int i, k, nTruePis; memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); if ( !fInit ) return; // clear the state bits to correspond to all-0 initial state nTruePis = Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); k = 0; Aig_ManForEachLoSeq( p->pManAig, pObj, i ) Abc_InfoXorBit( p->pPatWords, nTruePis * p->nFramesAll + k++ ); } /**Function************************************************************* Synopsis [Copy pattern from the solver into the internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlSavePattern( Fra_Man_t * p ) { Aig_Obj_t * pObj; int i; memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); Aig_ManForEachCi( p->pManFraig, pObj, i ) // if ( p->pSat->model.ptr[Fra_ObjSatNum(pObj)] == l_True ) if ( sat_solver_var_value(p->pSat, Fra_ObjSatNum(pObj)) ) Abc_InfoSetBit( p->pPatWords, i ); if ( p->vCex ) { Vec_IntClear( p->vCex ); for ( i = 0; i < Aig_ManCiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); i++ ) Vec_IntPush( p->vCex, Abc_InfoHasBit( p->pPatWords, i ) ); for ( i = Aig_ManCiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); i < Aig_ManCiNum(p->pManFraig); i++ ) Vec_IntPush( p->vCex, Abc_InfoHasBit( p->pPatWords, i ) ); } /* printf( "Pattern: " ); Aig_ManForEachCi( p->pManFraig, pObj, i ) printf( "%d", Abc_InfoHasBit( p->pPatWords, i ) ); printf( "\n" ); */ } /**Function************************************************************* Synopsis [Creates the counter-example from the successful pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlCheckOutputSavePattern( Fra_Man_t * p, Aig_Obj_t * pObjPo ) { Aig_Obj_t * pFanin, * pObjPi; unsigned * pSims; int i, k, BestPat, * pModel; // find the word of the pattern pFanin = Aig_ObjFanin0(pObjPo); pSims = Fra_ObjSim(p->pSml, pFanin->Id); for ( i = 0; i < p->pSml->nWordsTotal; i++ ) if ( pSims[i] ) break; assert( i < p->pSml->nWordsTotal ); // find the bit of the pattern for ( k = 0; k < 32; k++ ) if ( pSims[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, Aig_ManCiNum(p->pManFraig)+1 ); Aig_ManForEachCi( p->pManAig, pObjPi, i ) { pModel[i] = Abc_InfoHasBit(Fra_ObjSim(p->pSml, pObjPi->Id), BestPat); // printf( "%d", pModel[i] ); } pModel[Aig_ManCiNum(p->pManAig)] = pObjPo->Id; // 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 Fra_SmlCheckOutput( Fra_Man_t * p ) { Aig_Obj_t * pObj; int i; // make sure the reference simulation pattern does not detect the bug pObj = Aig_ManCo( p->pManAig, 0 ); assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) ); Aig_ManForEachCo( p->pManAig, pObj, i ) { if ( !Fra_SmlNodeIsConst( Aig_ObjFanin0(pObj) ) ) { // create the counter-example from this pattern Fra_SmlCheckOutputSavePattern( p, pObj ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Assigns random patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlAssignRandom( Fra_Sml_t * p, Aig_Obj_t * pObj ) { unsigned * pSims; int i; assert( Aig_ObjIsCi(pObj) ); pSims = Fra_ObjSim( p, pObj->Id ); for ( i = 0; i < p->nWordsTotal; i++ ) pSims[i] = Fra_ObjRandomSim(); } /**Function************************************************************* Synopsis [Assigns constant patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ) { unsigned * pSims; int i; assert( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ); pSims = Fra_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = fConst1? ~(unsigned)0 : 0; } /**Function************************************************************* Synopsis [Assings random simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlInitialize( Fra_Sml_t * p, int fInit ) { Aig_Obj_t * pObj; int i; if ( fInit ) { assert( Aig_ManRegNum(p->pAig) > 0 ); assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) ); // assign random info for primary inputs Aig_ManForEachPiSeq( p->pAig, pObj, i ) Fra_SmlAssignRandom( p, pObj ); // assign the initial state for the latches Aig_ManForEachLoSeq( p->pAig, pObj, i ) Fra_SmlAssignConst( p, pObj, 0, 0 ); } else { Aig_ManForEachCi( p->pAig, pObj, i ) Fra_SmlAssignRandom( p, pObj ); } } /**Function************************************************************* Synopsis [Assings distance-1 simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlAssignDist1( Fra_Sml_t * p, unsigned * pPat ) { Aig_Obj_t * pObj; int f, i, k, Limit, nTruePis; assert( p->nFrames > 0 ); if ( p->nFrames == 1 ) { // copy the PI info Aig_ManForEachCi( p->pAig, pObj, i ) Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 ); // flip one bit Limit = Abc_MinInt( Aig_ManCiNum(p->pAig), p->nWordsTotal * 32 - 1 ); for ( i = 0; i < Limit; i++ ) Abc_InfoXorBit( Fra_ObjSim( p, Aig_ManCi(p->pAig,i)->Id ), i+1 ); } else { int fUseDist1 = 0; // copy the PI info for each frame nTruePis = Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig); for ( f = 0; f < p->nFrames; f++ ) Aig_ManForEachPiSeq( p->pAig, pObj, i ) Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * f + i), f ); // copy the latch info k = 0; Aig_ManForEachLoSeq( p->pAig, pObj, i ) Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 ); // assert( p->pManFraig == NULL || nTruePis * p->nFrames + k == Aig_ManCiNum(p->pManFraig) ); // flip one bit of the last frame if ( fUseDist1 ) //&& p->nFrames == 2 ) { Limit = Abc_MinInt( nTruePis, p->nWordsFrame * 32 - 1 ); for ( i = 0; i < Limit; i++ ) Abc_InfoXorBit( Fra_ObjSim( p, Aig_ManCi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 ); } } } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlNodeSimulate( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) { unsigned * pSims, * pSims0, * pSims1; int fCompl, fCompl0, fCompl1, i; assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(pObj) ); assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; pSims1 = Fra_ObjSim(p, Aig_ObjFanin1(pObj)->Id) + p->nWordsFrame * iFrame; // get complemented attributes of the children using their random info fCompl = pObj->fPhase; fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj)); fCompl1 = Aig_ObjPhaseReal(Aig_ObjChild1(pObj)); // simulate if ( fCompl0 && fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (pSims0[i] | pSims1[i]); else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = ~(pSims0[i] | pSims1[i]); } else if ( fCompl0 && !fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (pSims0[i] | ~pSims1[i]); else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (~pSims0[i] & pSims1[i]); } else if ( !fCompl0 && fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (~pSims0[i] | pSims1[i]); else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (pSims0[i] & ~pSims1[i]); } else // if ( !fCompl0 && !fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = ~(pSims0[i] & pSims1[i]); else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (pSims0[i] & pSims1[i]); } } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ) { unsigned * pSims0, * pSims1; int i; assert( !Aig_IsComplement(pObj0) ); assert( !Aig_IsComplement(pObj1) ); assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal ); assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims0 = Fra_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0; pSims1 = Fra_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1; // compare for ( i = 0; i < p->nWordsFrame; i++ ) if ( pSims0[i] != pSims1[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlNodeCopyFanin( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) { unsigned * pSims, * pSims0; int fCompl, fCompl0, i; assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsCo(pObj) ); assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; // get complemented attributes of the children using their random info fCompl = pObj->fPhase; fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj)); // copy information as it is // if ( Aig_ObjFaninC0(pObj) ) if ( fCompl0 ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = ~pSims0[i]; else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = pSims0[i]; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlNodeTransferNext( Fra_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame ) { unsigned * pSims0, * pSims1; int i; assert( !Aig_IsComplement(pOut) ); assert( !Aig_IsComplement(pIn) ); assert( Aig_ObjIsCo(pOut) ); assert( Aig_ObjIsCi(pIn) ); assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims0 = Fra_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame; pSims1 = Fra_ObjSim(p, pIn->Id) + p->nWordsFrame * (iFrame+1); // copy information as it is for ( i = 0; i < p->nWordsFrame; i++ ) pSims1[i] = pSims0[i]; } /**Function************************************************************* Synopsis [Check if any of the POs becomes non-constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_SmlCheckNonConstOutputs( Fra_Sml_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachPoSeq( p->pAig, pObj, i ) if ( !Fra_SmlNodeIsZero(p, pObj) ) return 1; return 0; } /**Function************************************************************* Synopsis [Simulates AIG manager.] Description [Assumes that the PI simulation info is attached.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlSimulateOne( Fra_Sml_t * p ) { Aig_Obj_t * pObj, * pObjLi, * pObjLo; int f, i; abctime clk; clk = Abc_Clock(); for ( f = 0; f < p->nFrames; f++ ) { // simulate the nodes Aig_ManForEachNode( p->pAig, pObj, i ) Fra_SmlNodeSimulate( p, pObj, f ); // copy simulation info into outputs Aig_ManForEachPoSeq( p->pAig, pObj, i ) Fra_SmlNodeCopyFanin( p, pObj, f ); // quit if this is the last timeframe if ( f == p->nFrames - 1 ) break; // copy simulation info into outputs Aig_ManForEachLiSeq( p->pAig, pObj, i ) Fra_SmlNodeCopyFanin( p, pObj, f ); // copy simulation info into the inputs Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) Fra_SmlNodeTransferNext( p, pObjLi, pObjLo, f ); } p->timeSim += Abc_Clock() - clk; p->nSimRounds++; } /**Function************************************************************* Synopsis [Resimulates fraiging manager after finding a counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlResimulate( Fra_Man_t * p ) { int nChanges; abctime clk; Fra_SmlAssignDist1( p->pSml, p->pPatWords ); Fra_SmlSimulateOne( p->pSml ); // if ( p->pPars->fPatScores ) // Fra_CleanPatScores( p ); if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) return; clk = Abc_Clock(); nChanges = Fra_ClassesRefine( p->pCla ); nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); if ( p->pCla->vImps ) nChanges += Fra_ImpRefineUsingCex( p, p->pCla->vImps ); if ( p->vOneHots ) nChanges += Fra_OneHotRefineUsingCex( p, p->vOneHots ); p->timeRef += Abc_Clock() - clk; if ( !p->pPars->nFramesK && nChanges < 1 ) printf( "Error: A counter-example did not refine classes!\n" ); // assert( nChanges >= 1 ); //printf( "Refined classes = %5d. Changes = %4d.\n", Vec_PtrSize(p->vClasses), nChanges ); } /**Function************************************************************* Synopsis [Performs simulation of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlSimulate( Fra_Man_t * p, int fInit ) { int fVerbose = 0; int nChanges, nClasses; abctime clk; assert( !fInit || Aig_ManRegNum(p->pManAig) ); // start the classes Fra_SmlInitialize( p->pSml, fInit ); Fra_SmlSimulateOne( p->pSml ); if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) return; Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, 0 ); // Fra_ClassesPrint( p->pCla, 0 ); if ( fVerbose ) printf( "Starting classes = %5d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); //return; // refine classes by walking 0/1 patterns Fra_SmlSavePattern0( p, fInit ); Fra_SmlAssignDist1( p->pSml, p->pPatWords ); Fra_SmlSimulateOne( p->pSml ); if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) return; clk = Abc_Clock(); nChanges = Fra_ClassesRefine( p->pCla ); nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); p->timeRef += Abc_Clock() - clk; if ( fVerbose ) printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); Fra_SmlSavePattern1( p, fInit ); Fra_SmlAssignDist1( p->pSml, p->pPatWords ); Fra_SmlSimulateOne( p->pSml ); if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) return; clk = Abc_Clock(); nChanges = Fra_ClassesRefine( p->pCla ); nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); p->timeRef += Abc_Clock() - clk; if ( fVerbose ) printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); // refine classes by random simulation do { Fra_SmlInitialize( p->pSml, fInit ); Fra_SmlSimulateOne( p->pSml ); nClasses = Vec_PtrSize(p->pCla->vClasses); if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) return; clk = Abc_Clock(); nChanges = Fra_ClassesRefine( p->pCla ); nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); p->timeRef += Abc_Clock() - clk; if ( fVerbose ) printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); } while ( (double)nChanges / nClasses > p->pPars->dSimSatur ); // if ( p->pPars->fVerbose ) // printf( "Consts = %6d. Classes = %6d. Literals = %6d.\n", // Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); // Fra_ClassesPrint( p->pCla, 0 ); } /**Function************************************************************* Synopsis [Allocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ) { Fra_Sml_t * p; p = (Fra_Sml_t *)ABC_ALLOC( char, sizeof(Fra_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame ); memset( p, 0, sizeof(Fra_Sml_t) + sizeof(unsigned) * (nPref + nFrames) * nWordsFrame ); p->pAig = pAig; p->nPref = nPref; p->nFrames = nPref + nFrames; p->nWordsFrame = nWordsFrame; p->nWordsTotal = (nPref + nFrames) * nWordsFrame; p->nWordsPref = nPref * nWordsFrame; // constant 1 is initialized to 0 because we store values modulus phase (pObj->fPhase) return p; } /**Function************************************************************* Synopsis [Deallocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlStop( Fra_Sml_t * p ) { ABC_FREE( p ); } /**Function************************************************************* Synopsis [Performs simulation of the uninitialized circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords, int fCheckMiter ) { Fra_Sml_t * p; p = Fra_SmlStart( pAig, 0, 1, nWords ); Fra_SmlInitialize( p, 0 ); Fra_SmlSimulateOne( p ); if ( fCheckMiter ) p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p ); return p; } /**Function************************************************************* Synopsis [Reads simulation patterns from file.] Description [Each pattern contains the given number (nInputs) of binary digits. No other symbols (except spaces and line endings) are allowed in the file.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Fra_SmlSimulateReadFile( char * pFileName ) { Vec_Str_t * vRes; FILE * pFile; int c; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" with simulation patterns.\n", pFileName ); return NULL; } vRes = Vec_StrAlloc( 1000 ); while ( (c = fgetc(pFile)) != EOF ) { if ( c == '0' || c == '1' ) Vec_StrPush( vRes, (char)(c - '0') ); else if ( c != ' ' && c != '\r' && c != '\n' && c != '\t' ) { printf( "File \"%s\" contains symbol (%c) other than \'0\' or \'1\'.\n", pFileName, (char)c ); Vec_StrFreeP( &vRes ); break; } } fclose( pFile ); return vRes; } /**Function************************************************************* Synopsis [Assigns simulation patters derived from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlInitializeGiven( Fra_Sml_t * p, Vec_Str_t * vSimInfo ) { Aig_Obj_t * pObj; unsigned * pSims; int i, k, nPats = Vec_StrSize(vSimInfo) / Aig_ManCiNum(p->pAig); int nPatsPadded = p->nWordsTotal * 32; assert( Aig_ManRegNum(p->pAig) == 0 ); assert( Vec_StrSize(vSimInfo) % Aig_ManCiNum(p->pAig) == 0 ); assert( nPats <= nPatsPadded ); Aig_ManForEachCi( p->pAig, pObj, i ) { pSims = Fra_ObjSim( p, pObj->Id ); // clean data for ( k = 0; k < p->nWordsTotal; k++ ) pSims[k] = 0; // load patterns for ( k = 0; k < nPats; k++ ) if ( Vec_StrEntry(vSimInfo, k * Aig_ManCiNum(p->pAig) + i) ) Abc_InfoSetBit( pSims, k ); // pad the remaining bits with the value of the last pattern for ( ; k < nPatsPadded; k++ ) if ( Vec_StrEntry(vSimInfo, (nPats-1) * Aig_ManCiNum(p->pAig) + i) ) Abc_InfoSetBit( pSims, k ); } } /**Function************************************************************* Synopsis [Prints output values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fra_SmlPrintOutputs( Fra_Sml_t * p, int nPatterns ) { Aig_Obj_t * pObj; unsigned * pSims; int i, k; for ( k = 0; k < nPatterns; k++ ) { Aig_ManForEachCo( p->pAig, pObj, i ) { pSims = Fra_ObjSim( p, pObj->Id ); printf( "%d", Abc_InfoHasBit( pSims, k ) ); } printf( "\n" ); ; } } /**Function************************************************************* Synopsis [Assigns simulation patters derived from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Sml_t * Fra_SmlSimulateCombGiven( Aig_Man_t * pAig, char * pFileName, int fCheckMiter, int fVerbose ) { Vec_Str_t * vSimInfo; Fra_Sml_t * p; int nPatterns; assert( Aig_ManRegNum(pAig) == 0 ); // read comb patterns from file vSimInfo = Fra_SmlSimulateReadFile( pFileName ); if ( vSimInfo == NULL ) return NULL; if ( Vec_StrSize(vSimInfo) % Aig_ManCiNum(pAig) != 0 ) { printf( "File \"%s\": The number of binary digits (%d) is not divisible by the number of primary inputs (%d).\n", pFileName, Vec_StrSize(vSimInfo), Aig_ManCiNum(pAig) ); Vec_StrFree( vSimInfo ); return NULL; } p = Fra_SmlStart( pAig, 0, 1, Abc_BitWordNum(Vec_StrSize(vSimInfo) / Aig_ManCiNum(pAig)) ); Fra_SmlInitializeGiven( p, vSimInfo ); nPatterns = Vec_StrSize(vSimInfo) / Aig_ManCiNum(pAig); Vec_StrFree( vSimInfo ); Fra_SmlSimulateOne( p ); if ( fCheckMiter ) p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p ); if ( fVerbose ) Fra_SmlPrintOutputs( p, nPatterns ); return p; } /**Function************************************************************* Synopsis [Performs simulation of the initialized circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords, int fCheckMiter ) { Fra_Sml_t * p; p = Fra_SmlStart( pAig, nPref, nFrames, nWords ); Fra_SmlInitialize( p, 1 ); Fra_SmlSimulateOne( p ); if ( fCheckMiter ) p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p ); return p; } /**Function************************************************************* Synopsis [Creates sequential counter-example from the simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; unsigned * pSims; int iPo, iFrame, iBit, i, k; // make sure the simulation manager has it assert( p->fNonConstOut ); // find the first output that failed iPo = -1; iBit = -1; iFrame = -1; Aig_ManForEachPoSeq( p->pAig, pObj, iPo ) { if ( Fra_SmlNodeIsZero(p, pObj) ) continue; pSims = Fra_ObjSim( p, pObj->Id ); for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) if ( pSims[i] ) { iFrame = i / p->nWordsFrame; iBit = 32 * (i % p->nWordsFrame) + Aig_WordFindFirstBit( pSims[i] ); break; } break; } assert( iPo < Aig_ManCoNum(p->pAig)-Aig_ManRegNum(p->pAig) ); assert( iFrame < p->nFrames ); assert( iBit < 32 * p->nWordsFrame ); // allocate the counter example pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 ); pCex->iPo = iPo; pCex->iFrame = iFrame; // copy the bit data Aig_ManForEachLoSeq( p->pAig, pObj, k ) { pSims = Fra_ObjSim( p, pObj->Id ); if ( Abc_InfoHasBit( pSims, iBit ) ) Abc_InfoSetBit( pCex->pData, k ); } for ( i = 0; i <= iFrame; i++ ) { Aig_ManForEachPiSeq( p->pAig, pObj, k ) { pSims = Fra_ObjSim( p, pObj->Id ); if ( Abc_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k ); } } // verify the counter example if ( !Saig_ManVerifyCex( p->pAig, pCex ) ) { printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); Abc_CexFree( pCex ); pCex = NULL; } return pCex; } /**Function************************************************************* Synopsis [Generates seq counter-example from the combinational one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; int i, nFrames, nTruePis, nTruePos, iPo, iFrame; // get the number of frames assert( Aig_ManRegNum(pAig) > 0 ); assert( Aig_ManRegNum(pFrames) == 0 ); nTruePis = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); nTruePos = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig); nFrames = Aig_ManCiNum(pFrames) / nTruePis; assert( nTruePis * nFrames == Aig_ManCiNum(pFrames) ); assert( nTruePos * nFrames == Aig_ManCoNum(pFrames) ); // find the PO that failed iPo = -1; iFrame = -1; Aig_ManForEachCo( pFrames, pObj, i ) if ( pObj->Id == pModel[Aig_ManCiNum(pFrames)] ) { iPo = i % nTruePos; iFrame = i / nTruePos; break; } assert( iPo >= 0 ); // allocate the counter example pCex = Abc_CexAlloc( Aig_ManRegNum(pAig), nTruePis, iFrame + 1 ); pCex->iPo = iPo; pCex->iFrame = iFrame; // copy the bit data for ( i = 0; i < Aig_ManCiNum(pFrames); i++ ) { if ( pModel[i] ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + i ); if ( pCex->nRegs + i == pCex->nBits - 1 ) break; } // verify the counter example if ( !Saig_ManVerifyCex( pAig, pCex ) ) { printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" ); Abc_CexFree( pCex ); pCex = NULL; } return pCex; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/fra_.c000066400000000000000000000026401300674244400230060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fra_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [New FRAIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 30, 2007.] Revision [$Id: fra_.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fra/module.make000066400000000000000000000007121300674244400240550ustar00rootroot00000000000000SRC += src/proof/fra/fraBmc.c \ src/proof/fra/fraCec.c \ src/proof/fra/fraClass.c \ src/proof/fra/fraClau.c \ src/proof/fra/fraClaus.c \ src/proof/fra/fraCnf.c \ src/proof/fra/fraCore.c \ src/proof/fra/fraHot.c \ src/proof/fra/fraImp.c \ src/proof/fra/fraInd.c \ src/proof/fra/fraIndVer.c \ src/proof/fra/fraLcr.c \ src/proof/fra/fraMan.c \ src/proof/fra/fraPart.c \ src/proof/fra/fraSat.c \ src/proof/fra/fraSec.c \ src/proof/fra/fraSim.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/000077500000000000000000000000001300674244400222515ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraig.h000066400000000000000000000360611300674244400235200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraig.h] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [External declarations of the FRAIG package.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraig.h,v 1.18 2005/07/08 01:01:30 alanmi Exp $] ***********************************************************************/ #ifndef ABC__sat__fraig__fraig_h #define ABC__sat__fraig__fraig_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Fraig_ManStruct_t_ Fraig_Man_t; typedef struct Fraig_NodeStruct_t_ Fraig_Node_t; typedef struct Fraig_NodeVecStruct_t_ Fraig_NodeVec_t; typedef struct Fraig_HashTableStruct_t_ Fraig_HashTable_t; typedef struct Fraig_ParamsStruct_t_ Fraig_Params_t; typedef struct Fraig_PatternsStruct_t_ Fraig_Patterns_t; typedef struct Prove_ParamsStruct_t_ Prove_Params_t; struct Fraig_ParamsStruct_t_ { int nPatsRand; // the number of words of random simulation info int nPatsDyna; // the number of words of dynamic simulation info int nBTLimit; // the max number of backtracks to perform int nSeconds; // the timeout for the final proof int fFuncRed; // performs only one level hashing int fFeedBack; // enables solver feedback int fDist1Pats; // enables distance-1 patterns int fDoSparse; // performs equiv tests for sparse functions int fChoicing; // enables recording structural choices int fTryProve; // tries to solve the final miter int fVerbose; // the verbosiness flag int fVerboseP; // the verbosiness flag (for proof reporting) int fInternal; // is set to 1 for internal fraig calls int nConfLimit; // the limit on the number of conflicts ABC_INT64_T nInspLimit; // the limit on the number of inspections }; 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 }; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // macros working with complemented attributes of the nodes #define Fraig_IsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01))) #define Fraig_Regular(p) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) & ~01)) #define Fraig_Not(p) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ 01)) #define Fraig_NotCond(p,c) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ (c))) // these are currently not used #define Fraig_Ref(p) #define Fraig_Deref(p) #define Fraig_RecursiveDeref(p,c) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== fraigApi.c =============================================================*/ extern Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ); extern Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ); extern Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ); extern Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ); extern Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ); extern Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ); extern int Fraig_ManReadInputNum ( Fraig_Man_t * p ); extern int Fraig_ManReadOutputNum( Fraig_Man_t * p ); extern int Fraig_ManReadNodeNum( Fraig_Man_t * p ); extern Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ); extern Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ); extern Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ); extern char ** Fraig_ManReadInputNames( Fraig_Man_t * p ); extern char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ); extern char * Fraig_ManReadVarsInt( Fraig_Man_t * p ); extern char * Fraig_ManReadSat( Fraig_Man_t * p ); extern int Fraig_ManReadFuncRed( Fraig_Man_t * p ); extern int Fraig_ManReadFeedBack( Fraig_Man_t * p ); extern int Fraig_ManReadDoSparse( Fraig_Man_t * p ); extern int Fraig_ManReadChoicing( Fraig_Man_t * p ); extern int Fraig_ManReadVerbose( Fraig_Man_t * p ); extern int * Fraig_ManReadModel( Fraig_Man_t * p ); extern int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ); extern int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ); extern int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ); extern int Fraig_ManReadSatFails( Fraig_Man_t * p ); extern int Fraig_ManReadConflicts( Fraig_Man_t * p ); extern int Fraig_ManReadInspects( Fraig_Man_t * p ); extern void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ); extern void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ); extern void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ); extern void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ); extern void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ); extern void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ); extern void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ); extern void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ); extern void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ); extern Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ); extern Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ); extern int Fraig_NodeReadNum( Fraig_Node_t * p ); extern Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ); extern Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ); extern Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ); extern Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ); extern int Fraig_NodeReadNumRefs( Fraig_Node_t * p ); extern int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ); extern int Fraig_NodeReadSimInv( Fraig_Node_t * p ); extern int Fraig_NodeReadNumOnes( Fraig_Node_t * p ); extern unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ); extern unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ); extern void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ); extern void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ); extern int Fraig_NodeIsConst( Fraig_Node_t * p ); extern int Fraig_NodeIsVar( Fraig_Node_t * p ); extern int Fraig_NodeIsAnd( Fraig_Node_t * p ); extern int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ); extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); extern Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); extern Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_Node_t * pNodeT, Fraig_Node_t * pNodeE ); extern void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ); /*=== fraigMan.c =============================================================*/ extern void Prove_ParamsSetDefault( Prove_Params_t * pParams ); extern void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ); extern void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ); extern Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ); extern void Fraig_ManFree( Fraig_Man_t * pMan ); extern void Fraig_ManPrintStats( Fraig_Man_t * p ); extern Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p ); extern int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); extern void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes ); /*=== fraigDfs.c =============================================================*/ extern Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ); extern Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ); extern Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ); extern Fraig_NodeVec_t * Fraig_DfsReverse( Fraig_Man_t * pMan ); extern int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ); extern int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); extern int Fraig_CountLevels( Fraig_Man_t * pMan ); /*=== fraigSat.c =============================================================*/ extern int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ); extern int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ); extern void Fraig_ManProveMiter( Fraig_Man_t * p ); extern int Fraig_ManCheckMiter( Fraig_Man_t * p ); extern int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ); /*=== fraigVec.c ===============================================================*/ extern Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ); extern void Fraig_NodeVecFree( Fraig_NodeVec_t * p ); extern Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * p ); extern Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ); extern int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ); extern void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ); extern void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ); extern void Fraig_NodeVecClear( Fraig_NodeVec_t * p ); extern void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); extern int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); extern void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); extern int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); extern void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); extern int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); extern Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ); extern void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); extern void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ); extern Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ); extern void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ); extern void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ); /*=== fraigUtil.c ===============================================================*/ extern void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ); extern int Fraig_ManCheckConsistency( Fraig_Man_t * p ); extern int Fraig_GetMaxLevel( Fraig_Man_t * pMan ); extern void Fraig_ManReportChoices( Fraig_Man_t * pMan ); extern void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ); extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigApi.c000066400000000000000000000326141300674244400241450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigApi.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Access APIs for the FRAIG manager and node.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigApi.c,v 1.2 2005/07/08 01:01:30 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Access functions to read the data members of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ) { return p->vInputs; } Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ) { return p->vOutputs; } Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ) { return p->vNodes; } Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ) { return p->vInputs->pArray; } Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ) { return p->vOutputs->pArray; } Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ) { return p->vNodes->pArray; } int Fraig_ManReadInputNum ( Fraig_Man_t * p ) { return p->vInputs->nSize; } int Fraig_ManReadOutputNum( Fraig_Man_t * p ) { return p->vOutputs->nSize; } int Fraig_ManReadNodeNum( Fraig_Man_t * p ) { return p->vNodes->nSize; } Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ) { return p->pConst1; } Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ) { assert ( i < p->vNodes->nSize ); return p->vNodes->pArray[i]; } char ** Fraig_ManReadInputNames( Fraig_Man_t * p ) { return p->ppInputNames; } char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ) { return p->ppOutputNames; } char * Fraig_ManReadVarsInt( Fraig_Man_t * p ) { return (char *)p->vVarsInt; } char * Fraig_ManReadSat( Fraig_Man_t * p ) { return (char *)p->pSat; } int Fraig_ManReadFuncRed( Fraig_Man_t * p ) { return p->fFuncRed; } int Fraig_ManReadFeedBack( Fraig_Man_t * p ) { return p->fFeedBack; } int Fraig_ManReadDoSparse( Fraig_Man_t * p ) { return p->fDoSparse; } int Fraig_ManReadChoicing( Fraig_Man_t * p ) { return p->fChoicing; } int Fraig_ManReadVerbose( Fraig_Man_t * p ) { return p->fVerbose; } int * Fraig_ManReadModel( Fraig_Man_t * p ) { return p->pModel; } // returns the number of patterns used for random simulation (this number is fixed for the FRAIG run) int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ) { return p->nWordsRand * 32; } // returns the number of dynamic patterns accumulated at runtime (include SAT solver counter-examples and distance-1 patterns derived from them) int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ) { return p->iWordStart * 32; } // returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns) int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ) { return p->iPatsPerm; } // returns the number of times FRAIG package timed out int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFailsReal; } // returns the number of conflicts in the SAT solver int Fraig_ManReadConflicts( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadBackTracks(p->pSat) : 0; } // returns the number of inspections in the SAT solver int Fraig_ManReadInspects( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadInspects(p->pSat) : 0; } /**Function************************************************************* Synopsis [Access functions to set the data members of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ) { p->fFuncRed = fFuncRed; } void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ) { p->fFeedBack = fFeedBack; } void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ) { p->fDoSparse = fDoSparse; } void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ) { p->fChoicing = fChoicing; } void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ) { p->fTryProve = fTryProve; } void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppInputNames = ppNames; } /**Function************************************************************* Synopsis [Access functions to read the data members of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ) { return p->pData0; } Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ) { return p->pData1; } int Fraig_NodeReadNum( Fraig_Node_t * p ) { return p->Num; } Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p1; } Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p2; } Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ) { return p->pNextE; } Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ) { return p->pRepr; } int Fraig_NodeReadNumRefs( Fraig_Node_t * p ) { return p->nRefs; } int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ) { return p->nFanouts; } int Fraig_NodeReadSimInv( Fraig_Node_t * p ) { return p->fInv; } int Fraig_NodeReadNumOnes( Fraig_Node_t * p ) { return p->nOnes; } // returns the pointer to the random simulation patterns (their number is returned by Fraig_ManReadPatternNumRandom) // memory pointed to by this and the following procedure is maintained by the FRAIG package and exists as long as the package runs unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ) { return p->puSimR; } // returns the pointer to the dynamic simulation patterns (their number is returned by Fraig_ManReadPatternNumDynamic or Fraig_ManReadPatternNumDynamicFiltered) // if the number of patterns is not evenly divisible by 32, the patterns beyond the given number contain garbage unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ) { return p->puSimD; } /**Function************************************************************* Synopsis [Access functions to set the data members of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData0 = pData; } void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData1 = pData; } /**Function************************************************************* Synopsis [Checks the type of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsConst( Fraig_Node_t * p ) { return (Fraig_Regular(p))->Num == 0; } int Fraig_NodeIsVar( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi >= 0; } int Fraig_NodeIsAnd( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi < 0 && (Fraig_Regular(p))->Num > 0; } int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ) { assert( !Fraig_IsComplement(p1) ); assert( !Fraig_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } /**Function************************************************************* Synopsis [Returns a new primary input node.] Description [If the node with this number does not exist, create a new PI node with this number.] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ) { int k; if ( i < 0 ) { printf( "Requesting a PI with a negative number\n" ); return NULL; } // create the PIs to fill in the interval if ( i >= p->vInputs->nSize ) for ( k = p->vInputs->nSize; k <= i; k++ ) Fraig_NodeCreatePi( p ); return p->vInputs->pArray[i]; } /**Function************************************************************* Synopsis [Creates a new PO node.] Description [This procedure may take a complemented node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ) { // internal node may be a PO two times Fraig_Regular(pNode)->fNodePo = 1; Fraig_NodeVecPush( p->vOutputs, pNode ); } /**Function************************************************************* Synopsis [Perfoms the AND operation with functional hashing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) { return Fraig_NodeAndCanon( p, p1, p2 ); } /**Function************************************************************* Synopsis [Perfoms the OR operation with functional hashing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) { return Fraig_Not( Fraig_NodeAndCanon( p, Fraig_Not(p1), Fraig_Not(p2) ) ); } /**Function************************************************************* Synopsis [Perfoms the EXOR operation with functional hashing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) { return Fraig_NodeMux( p, p1, Fraig_Not(p2), p2 ); } /**Function************************************************************* Synopsis [Perfoms the MUX operation with functional hashing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pC, Fraig_Node_t * pT, Fraig_Node_t * pE ) { Fraig_Node_t * pAnd1, * pAnd2, * pRes; pAnd1 = Fraig_NodeAndCanon( p, pC, pT ); Fraig_Ref( pAnd1 ); pAnd2 = Fraig_NodeAndCanon( p, Fraig_Not(pC), pE ); Fraig_Ref( pAnd2 ); pRes = Fraig_NodeOr( p, pAnd1, pAnd2 ); Fraig_RecursiveDeref( p, pAnd1 ); Fraig_RecursiveDeref( p, pAnd2 ); Fraig_Deref( pRes ); return pRes; } /**Function************************************************************* Synopsis [Sets the node to be equivalent to the given one.] Description [This procedure is a work-around for the equivalence check. Does not verify the equivalence. Use at the user's risk.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ) { // assert( pMan->fChoicing ); pNodeNew->pNextE = pNodeOld->pNextE; pNodeOld->pNextE = pNodeNew; pNodeNew->pRepr = pNodeOld; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigCanon.c000066400000000000000000000173171300674244400244750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigCanon.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [AND-node creation and elementary AND-operation.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigCanon.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] ***********************************************************************/ #include #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [The internal AND operation for the two FRAIG nodes.] Description [This procedure is the core of the FRAIG package, because it performs the two-step canonicization of FRAIG nodes. The first step involves the lookup in the structural hash table (which hashes two ANDs into a node that has them as fanins, if such a node exists). If the node is not found in the structural hash table, an attempt is made to find a functionally equivalent node in another hash table (which hashes the simulation info into the nodes, which has this simulation info). Some tricks used on the way are described in the comments to the code and in the paper "FRAIGs: Functionally reduced AND-INV graphs".] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ) { Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr; int fUseSatCheck; // int RetValue; // check for trivial cases if ( p1 == p2 ) return p1; if ( p1 == Fraig_Not(p2) ) return Fraig_Not(pMan->pConst1); if ( Fraig_NodeIsConst(p1) ) { if ( p1 == pMan->pConst1 ) return p2; return Fraig_Not(pMan->pConst1); } if ( Fraig_NodeIsConst(p2) ) { if ( p2 == pMan->pConst1 ) return p1; return Fraig_Not(pMan->pConst1); } /* // check for less trivial cases if ( Fraig_IsComplement(p1) ) { if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p1), p2 ) ) { if ( RetValue == -1 ) pMan->nImplies0++; else pMan->nImplies1++; if ( RetValue == -1 ) return p2; } } else { if ( RetValue = Fraig_NodeIsInSupergate( p1, p2 ) ) { if ( RetValue == 1 ) pMan->nSimplifies1++; else pMan->nSimplifies0++; if ( RetValue == 1 ) return p1; return Fraig_Not(pMan->pConst1); } } if ( Fraig_IsComplement(p2) ) { if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p2), p1 ) ) { if ( RetValue == -1 ) pMan->nImplies0++; else pMan->nImplies1++; if ( RetValue == -1 ) return p1; } } else { if ( RetValue = Fraig_NodeIsInSupergate( p2, p1 ) ) { if ( RetValue == 1 ) pMan->nSimplifies1++; else pMan->nSimplifies0++; if ( RetValue == 1 ) return p2; return Fraig_Not(pMan->pConst1); } } */ // perform level-one structural hashing if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found { // if the existent node is part of the cone of unused logic // (that is logic feeding the node which is equivalent to the given node) // return the canonical representative of this node // determine the phase of the given node, with respect to its canonical form pNodeRepr = Fraig_Regular(pNodeNew)->pRepr; if ( pMan->fFuncRed && pNodeRepr ) return Fraig_NotCond( pNodeRepr, Fraig_IsComplement(pNodeNew) ^ Fraig_NodeComparePhase(Fraig_Regular(pNodeNew), pNodeRepr) ); // otherwise, the node is itself a canonical representative, return it return pNodeNew; } // the same node is not found, but the new one is created // if one level hashing is requested (without functionality hashing), return if ( !pMan->fFuncRed ) return pNodeNew; // check if the new node is unique using the simulation info if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) { pMan->nSatZeros++; if ( !pMan->fDoSparse ) // if we do not do sparse functions, skip return pNodeNew; // check the sparse function simulation hash table pNodeOld = Fraig_HashTableLookupF0( pMan, pNodeNew ); if ( pNodeOld == NULL ) // the node is unique (it is added to the table) return pNodeNew; } else { // check the simulation hash table pNodeOld = Fraig_HashTableLookupF( pMan, pNodeNew ); if ( pNodeOld == NULL ) // the node is unique return pNodeNew; } assert( pNodeOld->pRepr == 0 ); // there is another node which looks the same according to simulation // use SAT to resolve the ambiguity fUseSatCheck = (pMan->nInspLimit == 0 || Fraig_ManReadInspects(pMan) < pMan->nInspLimit); if ( fUseSatCheck && Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit, 1000000 ) ) { // set the node to be equivalent with this node // to prevent loops, only set if the old node is not in the TFI of the new node // the loop may happen in the following case: suppose // NodeC = AND(NodeA, NodeB) and at the same time NodeA => NodeB // in this case, NodeA and NodeC are functionally equivalent // however, NodeA is a fanin of node NodeC (this leads to the loop) // add the node to the list of equivalent nodes or dereference it if ( pMan->fChoicing && !Fraig_CheckTfi( pMan, pNodeOld, pNodeNew ) ) { // if the old node is not in the TFI of the new node and choicing // is enabled, add the new node to the list of equivalent ones pNodeNew->pNextE = pNodeOld->pNextE; pNodeOld->pNextE = pNodeNew; } // set the canonical representative of this node pNodeNew->pRepr = pNodeOld; // return the equivalent node return Fraig_NotCond( pNodeOld, Fraig_NodeComparePhase(pNodeOld, pNodeNew) ); } // now we add another member to this simulation class if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) { Fraig_Node_t * pNodeTemp; assert( pMan->fDoSparse ); pNodeTemp = Fraig_HashTableLookupF0( pMan, pNodeNew ); // assert( pNodeTemp == NULL ); // Fraig_HashTableInsertF0( pMan, pNodeNew ); } else { pNodeNew->pNextD = pNodeOld->pNextD; pNodeOld->pNextD = pNodeNew; } // return the new node assert( pNodeNew->pRepr == 0 ); return pNodeNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigChoice.c000066400000000000000000000202571300674244400246260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigTrans.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Adds the additive and distributive choices to the AIG.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - February 1, 2003.] Revision [$Id: fraigTrans.c,v 1.1 2005/02/28 05:34:34 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds choice nodes based on associativity.] Description [Make nLimit big AND gates and add all decompositions to the Fraig.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManAddChoices( Fraig_Man_t * pMan, int fVerbose, int nLimit ) { // ProgressBar * pProgress; char Buffer[100]; abctime clkTotal = Abc_Clock(); int i, nNodesBefore, nNodesAfter, nInputs, nMaxNodes; int /*nMaxLevel,*/ nDistributive; Fraig_Node_t *pNode, *pRepr; Fraig_Node_t *pX, *pA, *pB, *pC, /* *pD,*/ *pN, /* *pQ, *pR,*/ *pT; int fShortCut = 0; nDistributive = 0; // Fraig_ManSetApprox( pMan, 1 ); // NO functional reduction if (fShortCut) Fraig_ManSetFuncRed( pMan, 0 ); // First we mark critical functions i.e. compute those // nodes which lie on the critical path. Note that this // doesn't update the required times on any choice nodes // which are not the representatives /* nMaxLevel = Fraig_GetMaxLevel( pMan ); for ( i = 0; i < pMan->nOutputs; i++ ) { Fraig_SetNodeRequired( pMan, pMan->pOutputs[i], nMaxLevel ); } */ nNodesBefore = Fraig_ManReadNodeNum( pMan ); nInputs = Fraig_ManReadInputNum( pMan ); nMaxNodes = nInputs + nLimit * ( nNodesBefore - nInputs ); printf ("Limit = %d, Before = %d\n", nMaxNodes, nNodesBefore ); if (0) { char buffer[128]; sprintf (buffer, "test" ); // Fraig_MappingShow( pMan, buffer ); } // pProgress = Extra_ProgressBarStart( stdout, nMaxNodes ); Fraig_ManCheckConsistency( pMan ); for ( i = nInputs+1; (i < Fraig_ManReadNodeNum( pMan )) && (nMaxNodes > Fraig_ManReadNodeNum( pMan )); ++i ) { // if ( i == nNodesBefore ) // break; pNode = Fraig_ManReadIthNode( pMan, i ); assert ( pNode ); pRepr = pNode->pRepr ? pNode->pRepr : pNode; //printf ("Slack: %d\n", Fraig_NodeReadSlack( pRepr )); // All the new associative choices we add will have huge slack // since we do not redo timing, and timing doesnt handle choices // well anyway. However every newly added node is a choice of an // existing critical node, so they are considered critical. // if ( (Fraig_NodeReadSlack( pRepr ) > 3) && (i < nNodesBefore) ) // continue; // if ( pNode->pRepr ) // continue; // Try ((ab)c), x = ab -> (a(bc)) and (b(ac)) pX = Fraig_NodeReadOne(pNode); pC = Fraig_NodeReadTwo(pNode); if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX)) { pA = Fraig_NodeReadOne(Fraig_Regular(pX)); pB = Fraig_NodeReadTwo(Fraig_Regular(pX)); // pA = Fraig_NodeGetRepr( pA ); // pB = Fraig_NodeGetRepr( pB ); // pC = Fraig_NodeGetRepr( pC ); if (fShortCut) { pT = Fraig_NodeAnd(pMan, pB, pC); if ( !pT->pRepr ) { pN = Fraig_NodeAnd(pMan, pA, pT); // Fraig_NodeAddChoice( pMan, pNode, pN ); } } else pN = Fraig_NodeAnd(pMan, pA, Fraig_NodeAnd(pMan, pB, pC)); // assert ( Fraig_NodesEqual(pN, pNode) ); if (fShortCut) { pT = Fraig_NodeAnd(pMan, pA, pC); if ( !pT->pRepr ) { pN = Fraig_NodeAnd(pMan, pB, pT); // Fraig_NodeAddChoice( pMan, pNode, pN ); } } else pN = Fraig_NodeAnd(pMan, pB, Fraig_NodeAnd(pMan, pA, pC)); // assert ( Fraig_NodesEqual(pN, pNode) ); } // Try (a(bc)), x = bc -> ((ab)c) and ((ac)b) pA = Fraig_NodeReadOne(pNode); pX = Fraig_NodeReadTwo(pNode); if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX)) { pB = Fraig_NodeReadOne(Fraig_Regular(pX)); pC = Fraig_NodeReadTwo(Fraig_Regular(pX)); // pA = Fraig_NodeGetRepr( pA ); // pB = Fraig_NodeGetRepr( pB ); // pC = Fraig_NodeGetRepr( pC ); if (fShortCut) { pT = Fraig_NodeAnd(pMan, pA, pB); if ( !pT->pRepr ) { pN = Fraig_NodeAnd(pMan, pC, pT); // Fraig_NodeAddChoice( pMan, pNode, pN ); } } else pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pB), pC); // assert ( Fraig_NodesEqual(pN, pNode) ); if (fShortCut) { pT = Fraig_NodeAnd(pMan, pA, pC); if ( !pT->pRepr ) { pN = Fraig_NodeAnd(pMan, pB, pT); // Fraig_NodeAddChoice( pMan, pNode, pN ); } } else pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pC), pB); // assert ( Fraig_NodesEqual(pN, pNode) ); } /* // Try distributive transform pQ = Fraig_NodeReadOne(pNode); pR = Fraig_NodeReadTwo(pNode); if ( (Fraig_IsComplement(pQ) && Fraig_NodeIsAnd(pQ)) && (Fraig_IsComplement(pR) && Fraig_NodeIsAnd(pR)) ) { pA = Fraig_NodeReadOne(Fraig_Regular(pQ)); pB = Fraig_NodeReadTwo(Fraig_Regular(pQ)); pC = Fraig_NodeReadOne(Fraig_Regular(pR)); pD = Fraig_NodeReadTwo(Fraig_Regular(pR)); // Now detect the !(xy + xz) pattern, store // x in pA, y in pB and z in pC and set pD = 0 to indicate // pattern was found assert (pD != 0); if (pA == pC) { pC = pD; pD = 0; } if (pA == pD) { pD = 0; } if (pB == pC) { pB = pA; pA = pC; pC = pD; pD = 0; } if (pB == pD) { pB = pA; pA = pD; pD = 0; } if (pD == 0) { nDistributive++; pN = Fraig_Not(Fraig_NodeAnd(pMan, pA, Fraig_NodeOr(pMan, pB, pC))); if (fShortCut) Fraig_NodeAddChoice( pMan, pNode, pN ); // assert ( Fraig_NodesEqual(pN, pNode) ); } } */ if ( i % 1000 == 0 ) { sprintf( Buffer, "Adding choice %6d...", i - nNodesBefore ); // Extra_ProgressBarUpdate( pProgress, i, Buffer ); } } // Extra_ProgressBarStop( pProgress ); Fraig_ManCheckConsistency( pMan ); nNodesAfter = Fraig_ManReadNodeNum( pMan ); printf ( "Nodes before = %6d. Nodes with associative choices = %6d. Increase = %4.2f %%.\n", nNodesBefore, nNodesAfter, ((float)(nNodesAfter - nNodesBefore)) * 100.0/(nNodesBefore - nInputs) ); printf ( "Distributive = %d\n", nDistributive ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigFanout.c000066400000000000000000000125331300674244400246660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigFanout.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigFanout.c,v 1.5 2005/07/08 01:01:31 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START #ifdef FRAIG_ENABLE_FANOUTS //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Add the fanout to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ) { Fraig_Node_t * pPivot; // pFanins is a fanin of pFanout assert( !Fraig_IsComplement(pFanin) ); assert( !Fraig_IsComplement(pFanout) ); assert( Fraig_Regular(pFanout->p1) == pFanin || Fraig_Regular(pFanout->p2) == pFanin ); pPivot = pFanin->pFanPivot; if ( pPivot == NULL ) { pFanin->pFanPivot = pFanout; return; } if ( Fraig_Regular(pPivot->p1) == pFanin ) { if ( Fraig_Regular(pFanout->p1) == pFanin ) { pFanout->pFanFanin1 = pPivot->pFanFanin1; pPivot->pFanFanin1 = pFanout; } else // if ( Fraig_Regular(pFanout->p2) == pFanin ) { pFanout->pFanFanin2 = pPivot->pFanFanin1; pPivot->pFanFanin1 = pFanout; } } else // if ( Fraig_Regular(pPivot->p2) == pFanin ) { assert( Fraig_Regular(pPivot->p2) == pFanin ); if ( Fraig_Regular(pFanout->p1) == pFanin ) { pFanout->pFanFanin1 = pPivot->pFanFanin2; pPivot->pFanFanin2 = pFanout; } else // if ( Fraig_Regular(pFanout->p2) == pFanin ) { pFanout->pFanFanin2 = pPivot->pFanFanin2; pPivot->pFanFanin2 = pFanout; } } } /**Function************************************************************* Synopsis [Add the fanout to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ) { Fraig_Node_t * pFanout, * pFanout2, ** ppFanList; // start the linked list of fanouts ppFanList = &pFanin->pFanPivot; // go through the fanouts Fraig_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) { // skip the fanout-to-remove if ( pFanout == pFanoutToRemove ) continue; // add useful fanouts to the list *ppFanList = pFanout; ppFanList = Fraig_NodeReadNextFanoutPlace( pFanin, pFanout ); } *ppFanList = NULL; } /**Function************************************************************* Synopsis [Transfers fanout to a different node.] Description [Assumes that the other node currently has no fanouts.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeTransferFanout( Fraig_Node_t * pNodeFrom, Fraig_Node_t * pNodeTo ) { Fraig_Node_t * pFanout; assert( pNodeTo->pFanPivot == NULL ); assert( pNodeTo->pFanFanin1 == NULL ); assert( pNodeTo->pFanFanin2 == NULL ); // go through the fanouts and update their fanins Fraig_NodeForEachFanout( pNodeFrom, pFanout ) { if ( Fraig_Regular(pFanout->p1) == pNodeFrom ) pFanout->p1 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p1) ); else if ( Fraig_Regular(pFanout->p2) == pNodeFrom ) pFanout->p2 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p2) ); } // move the pointers pNodeTo->pFanPivot = pNodeFrom->pFanPivot; pNodeTo->pFanFanin1 = pNodeFrom->pFanFanin1; pNodeTo->pFanFanin2 = pNodeFrom->pFanFanin2; pNodeFrom->pFanPivot = NULL; pNodeFrom->pFanFanin1 = NULL; pNodeFrom->pFanFanin2 = NULL; } /**Function************************************************************* Synopsis [Returns the number of fanouts of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ) { Fraig_Node_t * pFanout; int Counter = 0; Fraig_NodeForEachFanout( pNode, pFanout ) Counter++; return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #endif ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigFeed.c000066400000000000000000000723311300674244400242770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigFeed.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Procedures to support the solver feedback.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigFeed.c,v 1.8 2005/07/08 01:01:31 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ); static int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ); static void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); static void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ); static Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * pMan ); static int Fraig_GetSmallestColumn( int * pHits, int nHits ); static int Fraig_GetHittingPattern( unsigned * pSims, int nWords ); static void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ); static void Fraig_FeedBackCheckTable( Fraig_Man_t * p ); static void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ); static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Initializes the feedback information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_FeedBackInit( Fraig_Man_t * p ) { p->vCones = Fraig_NodeVecAlloc( 500 ); p->vPatsReal = Msat_IntVecAlloc( 1000 ); p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); } /**Function************************************************************* Synopsis [Processes the feedback from teh solver.] Description [Array pModel gives the value of each variable in the SAT solver. Array vVars is the array of integer numbers of variables involves in this conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { int nVarsPi, nWords; int i; abctime clk = Abc_Clock(); // get the number of PI vars in the feedback (also sets the PI values) nVarsPi = Fraig_FeedBackPrepare( p, pModel, vVars ); // set the PI values nWords = Fraig_FeedBackInsert( p, nVarsPi ); assert( p->iWordStart + nWords <= p->nWordsDyna ); // resimulates the words from p->iWordStart to iWordStop for ( i = 1; i < p->vNodes->nSize; i++ ) if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) Fraig_NodeSimulate( p->vNodes->pArray[i], p->iWordStart, p->iWordStart + nWords, 0 ); if ( p->fDoSparse ) Fraig_TableRehashF0( p, 0 ); if ( !p->fChoicing ) Fraig_FeedBackVerify( p, pOld, pNew ); // if there is no room left, compress the patterns if ( p->iWordStart + nWords == p->nWordsDyna ) p->iWordStart = Fraig_FeedBackCompress( p ); else // otherwise, update the starting word p->iWordStart += nWords; p->timeFeed += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Get the number and values of the PI variables.] Description [Returns the number of PI variables involved in this feedback. Fills in the internal presence and value data for the primary inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ) { Fraig_Node_t * pNode; int i, nVars, nVarsPis, * pVars; // clean the presence flag for all PIs for ( i = 0; i < p->vInputs->nSize; i++ ) { pNode = p->vInputs->pArray[i]; pNode->fFeedUse = 0; } // get the variables involved in the feedback nVars = Msat_IntVecReadSize(vVars); pVars = Msat_IntVecReadArray(vVars); // set the values for the present variables nVarsPis = 0; for ( i = 0; i < nVars; i++ ) { pNode = p->vNodes->pArray[ pVars[i] ]; if ( !Fraig_NodeIsVar(pNode) ) continue; // set its value pNode->fFeedUse = 1; pNode->fFeedVal = !MSAT_LITSIGN(pModel[pVars[i]]); nVarsPis++; } return nVarsPis; } /**Function************************************************************* Synopsis [Inserts the new simulation patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ) { Fraig_Node_t * pNode; int nWords, iPatFlip, nPatFlipLimit, i, w; int fUseNoPats = 0; int fUse2Pats = 0; // get the number of words if ( fUse2Pats ) nWords = FRAIG_NUM_WORDS( 2 * nVarsPi + 1 ); else if ( fUseNoPats ) nWords = 1; else nWords = FRAIG_NUM_WORDS( nVarsPi + 1 ); // update the number of words if they do not fit into the simulation info if ( nWords > p->nWordsDyna - p->iWordStart ) nWords = p->nWordsDyna - p->iWordStart; // determine the bound on the flipping bit nPatFlipLimit = nWords * 32 - 2; // mark the real pattern Msat_IntVecPush( p->vPatsReal, p->iWordStart * 32 ); // record the real pattern Fraig_BitStringSetBit( p->pSimsReal, p->iWordStart * 32 ); // set the values at the PIs iPatFlip = 1; for ( i = 0; i < p->vInputs->nSize; i++ ) { pNode = p->vInputs->pArray[i]; for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) if ( !pNode->fFeedUse ) pNode->puSimD[w] = FRAIG_RANDOM_UNSIGNED; else if ( pNode->fFeedVal ) pNode->puSimD[w] = FRAIG_FULL; else // if ( !pNode->fFeedVal ) pNode->puSimD[w] = 0; if ( fUse2Pats ) { // flip two patterns if ( pNode->fFeedUse && 2 * iPatFlip < nPatFlipLimit ) { Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip - 1 ); Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip ); Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip + 1 ); iPatFlip++; } } else if ( fUseNoPats ) { } else { // flip the diagonal if ( pNode->fFeedUse && iPatFlip < nPatFlipLimit ) { Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, iPatFlip ); iPatFlip++; // Extra_PrintBinary( stdout, &pNode->puSimD, 45 ); printf( "\n" ); } } // clean the use mask pNode->fFeedUse = 0; // add the info to the D hash value of the PIs for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) pNode->uHashD ^= pNode->puSimD[w] * s_FraigPrimes[w]; } return nWords; } /**Function************************************************************* Synopsis [Checks that the SAT solver pattern indeed distinquishes the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { int fValue1, fValue2, iPat; iPat = Msat_IntVecReadEntry( p->vPatsReal, Msat_IntVecReadSize(p->vPatsReal)-1 ); fValue1 = (Fraig_BitStringHasBit( pOld->puSimD, iPat )); fValue2 = (Fraig_BitStringHasBit( pNew->puSimD, iPat )); /* Fraig_PrintNode( p, pOld ); printf( "\n" ); Fraig_PrintNode( p, pNew ); printf( "\n" ); */ // assert( fValue1 != fValue2 ); } /**Function************************************************************* Synopsis [Compress the simulation patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_FeedBackCompress( Fraig_Man_t * p ) { unsigned * pSims; unsigned uHash; int i, w, t, nPats, * pPats; int fPerformChecks = (p->nBTLimit == -1); // solve the covering problem if ( fPerformChecks ) { Fraig_FeedBackCheckTable( p ); if ( p->fDoSparse ) Fraig_FeedBackCheckTableF0( p ); } // solve the covering problem Fraig_FeedBackCovering( p, p->vPatsReal ); // get the number of additional patterns nPats = Msat_IntVecReadSize( p->vPatsReal ); pPats = Msat_IntVecReadArray( p->vPatsReal ); // get the new starting word p->iWordStart = FRAIG_NUM_WORDS( p->iPatsPerm + nPats ); // set the simulation info for the PIs for ( i = 0; i < p->vInputs->nSize; i++ ) { // get hold of the simulation info for this PI pSims = p->vInputs->pArray[i]->puSimD; // clean the storage for the new patterns for ( w = p->iWordPerm; w < p->iWordStart; w++ ) p->pSimsTemp[w] = 0; // set the patterns for ( t = 0; t < nPats; t++ ) if ( Fraig_BitStringHasBit( pSims, pPats[t] ) ) { // check if this pattern falls into temporary storage if ( p->iPatsPerm + t < p->iWordPerm * 32 ) Fraig_BitStringSetBit( pSims, p->iPatsPerm + t ); else Fraig_BitStringSetBit( p->pSimsTemp, p->iPatsPerm + t ); } // copy the pattern for ( w = p->iWordPerm; w < p->iWordStart; w++ ) pSims[w] = p->pSimsTemp[w]; // recompute the hashing info uHash = 0; for ( w = 0; w < p->iWordStart; w++ ) uHash ^= pSims[w] * s_FraigPrimes[w]; p->vInputs->pArray[i]->uHashD = uHash; } // update info about the permanently stored patterns p->iWordPerm = p->iWordStart; p->iPatsPerm += nPats; assert( p->iWordPerm == FRAIG_NUM_WORDS( p->iPatsPerm ) ); // resimulate and recompute the hash values for ( i = 1; i < p->vNodes->nSize; i++ ) if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) { p->vNodes->pArray[i]->uHashD = 0; Fraig_NodeSimulate( p->vNodes->pArray[i], 0, p->iWordPerm, 0 ); } // double-check that the nodes are still distinguished if ( fPerformChecks ) Fraig_FeedBackCheckTable( p ); // rehash the values in the F0 table if ( p->fDoSparse ) { Fraig_TableRehashF0( p, 0 ); if ( fPerformChecks ) Fraig_FeedBackCheckTableF0( p ); } // check if we need to resize the simulation info // if less than FRAIG_WORDS_STORE words are left, reallocate simulation info if ( p->iWordPerm + FRAIG_WORDS_STORE > p->nWordsDyna ) Fraig_ReallocateSimulationInfo( p ); // set the real patterns Msat_IntVecClear( p->vPatsReal ); memset( p->pSimsReal, 0, sizeof(unsigned)*p->nWordsDyna ); for ( w = 0; w < p->iWordPerm; w++ ) p->pSimsReal[w] = FRAIG_FULL; if ( p->iPatsPerm % 32 > 0 ) p->pSimsReal[p->iWordPerm-1] = FRAIG_MASK( p->iPatsPerm % 32 ); // printf( "The number of permanent words = %d.\n", p->iWordPerm ); return p->iWordStart; } /**Function************************************************************* Synopsis [Checks the correctness of the functional simulation table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ) { Fraig_NodeVec_t * vColumns; unsigned * pSims; int * pHits, iPat, iCol, i; int nOnesTotal, nSolStarting; int fVeryVerbose = 0; // collect the pairs to be distinguished vColumns = Fraig_FeedBackCoveringStart( p ); // collect the number of 1s in each simulation vector nOnesTotal = 0; pHits = ABC_ALLOC( int, vColumns->nSize ); for ( i = 0; i < vColumns->nSize; i++ ) { pSims = (unsigned *)vColumns->pArray[i]; pHits[i] = Fraig_BitStringCountOnes( pSims, p->iWordStart ); nOnesTotal += pHits[i]; // assert( pHits[i] > 0 ); } // go through the patterns nSolStarting = Msat_IntVecReadSize(vPats); while ( (iCol = Fraig_GetSmallestColumn( pHits, vColumns->nSize )) != -1 ) { // find the pattern, which hits this column iPat = Fraig_GetHittingPattern( (unsigned *)vColumns->pArray[iCol], p->iWordStart ); // cancel the columns covered by this pattern Fraig_CancelCoveredColumns( vColumns, pHits, iPat ); // save the pattern Msat_IntVecPush( vPats, iPat ); } // free the set of columns for ( i = 0; i < vColumns->nSize; i++ ) Fraig_MemFixedEntryRecycle( p->mmSims, (char *)vColumns->pArray[i] ); // print stats related to the covering problem if ( p->fVerbose && fVeryVerbose ) { printf( "%3d\\%3d\\%3d ", p->nWordsRand, p->nWordsDyna, p->iWordPerm ); printf( "Col (pairs) = %5d. ", vColumns->nSize ); printf( "Row (pats) = %5d. ", p->iWordStart * 32 ); printf( "Dns = %6.2f %%. ", vColumns->nSize==0? 0.0 : 100.0 * nOnesTotal / vColumns->nSize / p->iWordStart / 32 ); printf( "Sol = %3d (%3d). ", Msat_IntVecReadSize(vPats), nSolStarting ); printf( "\n" ); } Fraig_NodeVecFree( vColumns ); ABC_FREE( pHits ); } /**Function************************************************************* Synopsis [Checks the correctness of the functional simulation table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p ) { Fraig_NodeVec_t * vColumns; Fraig_HashTable_t * pT = p->pTableF; Fraig_Node_t * pEntF, * pEntD; unsigned * pSims; unsigned * pUnsigned1, * pUnsigned2; int i, k, m, w;//, nOnes; // start the set of columns vColumns = Fraig_NodeVecAlloc( 100 ); // go through the pairs of nodes to be distinguished for ( i = 0; i < pT->nBins; i++ ) Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) { p->vCones->nSize = 0; Fraig_TableBinForEachEntryD( pEntF, pEntD ) Fraig_NodeVecPush( p->vCones, pEntD ); if ( p->vCones->nSize == 1 ) continue; //////////////////////////////// bug fix by alanmi, September 14, 2006 if ( p->vCones->nSize > 20 ) continue; //////////////////////////////// for ( k = 0; k < p->vCones->nSize; k++ ) for ( m = k+1; m < p->vCones->nSize; m++ ) { if ( !Fraig_CompareSimInfoUnderMask( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0, p->pSimsReal ) ) continue; // primary simulation patterns (counter-examples) cannot distinguish this pair // get memory to store the feasible simulation patterns pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); // find the pattern that distinguish this column, exept the primary ones pUnsigned1 = p->vCones->pArray[k]->puSimD; pUnsigned2 = p->vCones->pArray[m]->puSimD; for ( w = 0; w < p->iWordStart; w++ ) pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; // store the pattern Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); // nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); // assert( nOnes > 0 ); } } // if the flag is not set, do not consider sparse nodes in p->pTableF0 if ( !p->fDoSparse ) return vColumns; // recalculate their hash values based on p->pSimsReal pT = p->pTableF0; for ( i = 0; i < pT->nBins; i++ ) Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) { pSims = pEntF->puSimD; pEntF->uHashD = 0; for ( w = 0; w < p->iWordStart; w++ ) pEntF->uHashD ^= (pSims[w] & p->pSimsReal[w]) * s_FraigPrimes[w]; } // rehash the table using these values Fraig_TableRehashF0( p, 1 ); // collect the classes of equivalent node pairs for ( i = 0; i < pT->nBins; i++ ) Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) { p->vCones->nSize = 0; Fraig_TableBinForEachEntryD( pEntF, pEntD ) Fraig_NodeVecPush( p->vCones, pEntD ); if ( p->vCones->nSize == 1 ) continue; // primary simulation patterns (counter-examples) cannot distinguish all these pairs for ( k = 0; k < p->vCones->nSize; k++ ) for ( m = k+1; m < p->vCones->nSize; m++ ) { // get memory to store the feasible simulation patterns pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); // find the patterns that are not distinquished pUnsigned1 = p->vCones->pArray[k]->puSimD; pUnsigned2 = p->vCones->pArray[m]->puSimD; for ( w = 0; w < p->iWordStart; w++ ) pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; // store the pattern Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); // nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); // assert( nOnes > 0 ); } } return vColumns; } /**Function************************************************************* Synopsis [Selects the column, which has the smallest number of hits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_GetSmallestColumn( int * pHits, int nHits ) { int i, iColMin = -1, nHitsMin = 1000000; for ( i = 0; i < nHits; i++ ) { // skip covered columns if ( pHits[i] == 0 ) continue; // take the column if it can only be covered by one pattern if ( pHits[i] == 1 ) return i; // find the column, which requires the smallest number of patterns if ( nHitsMin > pHits[i] ) { nHitsMin = pHits[i]; iColMin = i; } } return iColMin; } /**Function************************************************************* Synopsis [Select the pattern, which hits this column.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_GetHittingPattern( unsigned * pSims, int nWords ) { int i, b; for ( i = 0; i < nWords; i++ ) { if ( pSims[i] == 0 ) continue; for ( b = 0; b < 32; b++ ) if ( pSims[i] & (1 << b) ) return i * 32 + b; } return -1; } /**Function************************************************************* Synopsis [Cancel covered patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ) { unsigned * pSims; int i; for ( i = 0; i < vColumns->nSize; i++ ) { pSims = (unsigned *)vColumns->pArray[i]; if ( Fraig_BitStringHasBit( pSims, iPat ) ) pHits[i] = 0; } } /**Function************************************************************* Synopsis [Checks the correctness of the functional simulation table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_FeedBackCheckTable( Fraig_Man_t * p ) { Fraig_HashTable_t * pT = p->pTableF; Fraig_Node_t * pEntF, * pEntD; int i, k, m, nPairs; nPairs = 0; for ( i = 0; i < pT->nBins; i++ ) Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) { p->vCones->nSize = 0; Fraig_TableBinForEachEntryD( pEntF, pEntD ) Fraig_NodeVecPush( p->vCones, pEntD ); if ( p->vCones->nSize == 1 ) continue; for ( k = 0; k < p->vCones->nSize; k++ ) for ( m = k+1; m < p->vCones->nSize; m++ ) { if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) printf( "Nodes %d and %d have the same D simulation info.\n", p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); nPairs++; } } // printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); } /**Function************************************************************* Synopsis [Checks the correctness of the functional simulation table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ) { Fraig_HashTable_t * pT = p->pTableF0; Fraig_Node_t * pEntF; int i, k, m, nPairs; nPairs = 0; for ( i = 0; i < pT->nBins; i++ ) { p->vCones->nSize = 0; Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) Fraig_NodeVecPush( p->vCones, pEntF ); if ( p->vCones->nSize == 1 ) continue; for ( k = 0; k < p->vCones->nSize; k++ ) for ( m = k+1; m < p->vCones->nSize; m++ ) { if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) printf( "Nodes %d and %d have the same D simulation info.\n", p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); nPairs++; } } // printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); } /**Function************************************************************* Synopsis [Doubles the size of simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ) { Fraig_MemFixed_t * mmSimsNew; // new memory manager for simulation info Fraig_Node_t * pNode; unsigned * pSimsNew; unsigned uSignOld; int i; // allocate a new memory manager p->nWordsDyna *= 2; mmSimsNew = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); // set the new data for the constant node pNode = p->pConst1; pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); pNode->puSimD = pNode->puSimR + p->nWordsRand; memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); // copy the simulation info of the PIs for ( i = 0; i < p->vInputs->nSize; i++ ) { pNode = p->vInputs->pArray[i]; // copy the simulation info pSimsNew = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); memmove( pSimsNew, pNode->puSimR, sizeof(unsigned) * (p->nWordsRand + p->iWordStart) ); // attach the new info pNode->puSimR = pSimsNew; pNode->puSimD = pNode->puSimR + p->nWordsRand; // signatures remain without changes } // replace the manager to free up some memory Fraig_MemFixedStop( p->mmSims, 0 ); p->mmSims = mmSimsNew; // resimulate the internal nodes (this should lead to the same signatures) for ( i = 1; i < p->vNodes->nSize; i++ ) { pNode = p->vNodes->pArray[i]; if ( !Fraig_NodeIsAnd(pNode) ) continue; // allocate memory for the simulation info pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); pNode->puSimD = pNode->puSimR + p->nWordsRand; // derive random simulation info uSignOld = pNode->uHashR; pNode->uHashR = 0; Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); assert( uSignOld == pNode->uHashR ); // derive dynamic simulation info uSignOld = pNode->uHashD; pNode->uHashD = 0; Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); assert( uSignOld == pNode->uHashD ); } // realloc temporary storage p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); } /**Function************************************************************* Synopsis [Generated trivial counter example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ) { int * pModel; pModel = ABC_ALLOC( int, p->vInputs->nSize ); memset( pModel, 0, sizeof(int) * p->vInputs->nSize ); return pModel; } /**Function************************************************************* Synopsis [Saves the counter example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManSimulateBitNode_rec( Fraig_Man_t * p, Fraig_Node_t * pNode ) { int Value0, Value1; if ( Fraig_NodeIsTravIdCurrent( p, pNode ) ) return pNode->fMark3; Fraig_NodeSetTravIdCurrent( p, pNode ); Value0 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p1) ); Value1 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p2) ); Value0 ^= Fraig_IsComplement(pNode->p1); Value1 ^= Fraig_IsComplement(pNode->p2); pNode->fMark3 = Value0 & Value1; return pNode->fMark3; } /**Function************************************************************* Synopsis [Simulates one bit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManSimulateBitNode( Fraig_Man_t * p, Fraig_Node_t * pNode, int * pModel ) { int fCompl, RetValue, i; // set the PI values Fraig_ManIncrementTravId( p ); for ( i = 0; i < p->vInputs->nSize; i++ ) { Fraig_NodeSetTravIdCurrent( p, p->vInputs->pArray[i] ); p->vInputs->pArray[i]->fMark3 = pModel[i]; } // perform the traversal fCompl = Fraig_IsComplement(pNode); RetValue = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode) ); return fCompl ^ RetValue; } /**Function************************************************************* Synopsis [Saves the counter example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ) { int * pModel; int iPattern; int i, fCompl; // the node can be complemented fCompl = Fraig_IsComplement(pNode); // because we compare with constant 0, p->pConst1 should also be complemented fCompl = !fCompl; // derive the model pModel = Fraig_ManAllocCounterExample( p ); iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->nWordsRand, 1 ); if ( iPattern >= 0 ) { for ( i = 0; i < p->vInputs->nSize; i++ ) if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimR, iPattern ) ) pModel[i] = 1; /* printf( "SAT solver's pattern:\n" ); for ( i = 0; i < p->vInputs->nSize; i++ ) printf( "%d", pModel[i] ); printf( "\n" ); */ assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); return pModel; } iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->iWordStart, 0 ); if ( iPattern >= 0 ) { for ( i = 0; i < p->vInputs->nSize; i++ ) if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimD, iPattern ) ) pModel[i] = 1; /* printf( "SAT solver's pattern:\n" ); for ( i = 0; i < p->vInputs->nSize; i++ ) printf( "%d", pModel[i] ); printf( "\n" ); */ assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); return pModel; } ABC_FREE( pModel ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigInt.h000066400000000000000000000625231300674244400241750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigInt.h] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Internal declarations of the FRAIG package.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigInt.h,v 1.15 2005/07/08 01:01:31 alanmi Exp $] ***********************************************************************/ #ifndef ABC__sat__fraig__fraigInt_h #define ABC__sat__fraig__fraigInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/util/abc_global.h" #include "fraig.h" #include "sat/msat/msat.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// /* The AIG node policy: - Each node has its main number (pNode->Num) This is the number of this node in the array of all nodes and its SAT variable number - The PI nodes are stored along with other nodes Additionally, PI nodes have a PI number, by which they are stored in the PI node array - The constant node is has number 0 and is also stored in the array */ //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // enable this macro to support the fanouts #define FRAIG_ENABLE_FANOUTS #define FRAIG_PATTERNS_RANDOM 2048 // should not be less than 128 and more than 32768 (2^15) #define FRAIG_PATTERNS_DYNAMIC 2048 // should not be less than 256 and more than 32768 (2^15) #define FRAIG_MAX_PRIMES 1024 // the maximum number of primes used for hashing // this parameter determines when simulation info is extended // it will be extended when the free storage in the dynamic simulation // info is less or equal to this number of words (FRAIG_WORDS_STORE) // this is done because if the free storage for dynamic simulation info // is not sufficient, computation becomes inefficient #define FRAIG_WORDS_STORE 5 // the bit masks #define FRAIG_MASK(n) ((~((unsigned)0)) >> (32-(n))) #define FRAIG_FULL (~((unsigned)0)) #define FRAIG_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) // generating random unsigned (#define RAND_MAX 0x7fff) //#define FRAIG_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) #define FRAIG_RANDOM_UNSIGNED Aig_ManRandom(0) // macros to get hold of the bits in a bit string #define Fraig_BitStringSetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31))) #define Fraig_BitStringXorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31))) #define Fraig_BitStringHasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0) // macros to get hold of the bits in the support info //#define Fraig_NodeSetVarStr(p,i) (Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] |= (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) //#define Fraig_NodeHasVarStr(p,i) ((Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] & (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) > 0) #define Fraig_NodeSetVarStr(p,i) Fraig_BitStringSetBit(Fraig_Regular(p)->pSuppStr,i) #define Fraig_NodeHasVarStr(p,i) Fraig_BitStringHasBit(Fraig_Regular(p)->pSuppStr,i) // copied from "extra.h" for stand-aloneness #define Fraig_PrintTime(a,t) printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) #define Fraig_HashKey2(a,b,TSIZE) (((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * 12582917) % TSIZE) //#define Fraig_HashKey2(a,b,TSIZE) (( ((unsigned)(a)->Num * 19) ^ ((unsigned)(b)->Num * 1999) ) % TSIZE) //#define Fraig_HashKey2(a,b,TSIZE) ( ((unsigned)((a)->Num + (b)->Num) * ((a)->Num + (b)->Num + 1) / 2) % TSIZE) // the other two hash functions give bad distribution of hash chain lengths (not clear why) //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Fraig_MemFixed_t_ Fraig_MemFixed_t; // the mapping manager struct Fraig_ManStruct_t_ { // the AIG nodes Fraig_NodeVec_t * vInputs; // the array of primary inputs Fraig_NodeVec_t * vNodes; // the array of all nodes, including primary inputs Fraig_NodeVec_t * vOutputs; // the array of primary outputs (some internal nodes) Fraig_Node_t * pConst1; // the pointer to the constant node (vNodes->pArray[0]) // info about the original circuit char ** ppInputNames; // the primary input names char ** ppOutputNames; // the primary output names // various hash-tables Fraig_HashTable_t * pTableS; // hashing by structure Fraig_HashTable_t * pTableF; // hashing by simulation info Fraig_HashTable_t * pTableF0; // hashing by simulation info (sparse functions) // parameters int nWordsRand; // the number of words of random simulation info int nWordsDyna; // the number of words of dynamic simulation info int nBTLimit; // the max number of backtracks to perform int nSeconds; // the runtime limit for the miter proof int fFuncRed; // performs only one level hashing int fFeedBack; // enables solver feedback int fDist1Pats; // enables solver feedback int fDoSparse; // performs equiv tests for sparse functions int fChoicing; // enables recording structural choices int fTryProve; // tries to solve the final miter int fVerbose; // the verbosiness flag int fVerboseP; // the verbosiness flag ABC_INT64_T nInspLimit; // the inspection limit int nTravIds; // the traversal counter int nTravIds2; // the traversal counter // info related to the solver feedback int iWordStart; // the first word to use for simulation int iWordPerm; // the number of words stored permanently int iPatsPerm; // the number of patterns stored permanently Fraig_NodeVec_t * vCones; // the temporary array of internal variables Msat_IntVec_t * vPatsReal; // the array of real pattern numbers unsigned * pSimsReal; // used for simulation patterns unsigned * pSimsDiff; // used for simulation patterns unsigned * pSimsTemp; // used for simulation patterns // the support information int nSuppWords; unsigned ** pSuppS; unsigned ** pSuppF; // the memory managers Fraig_MemFixed_t * mmNodes; // the memory manager for nodes Fraig_MemFixed_t * mmSims; // the memory manager for simulation info // solving the SAT problem Msat_Solver_t * pSat; // the SAT solver Msat_IntVec_t * vProj; // the temporary array of projection vars int nSatNums; // the counter of SAT variables int * pModel; // the assignment, which satisfies the miter // these arrays belong to the solver Msat_IntVec_t * vVarsInt; // the temporary array of variables Msat_ClauseVec_t * vAdjacents; // the temporary storage for connectivity Msat_IntVec_t * vVarsUsed; // the array marking vars appearing in the cone // various statistic variables int nSatCalls; // the number of times equivalence checking was called int nSatProof; // the number of times a proof was found int nSatCounter; // the number of times a counter example was found int nSatFails; // the number of times the SAT solver failed to complete due to resource limit or prediction int nSatFailsReal; // the number of times the SAT solver failed to complete due to resource limit int nSatCallsImp; // the number of times equivalence checking was called int nSatProofImp; // the number of times a proof was found int nSatCounterImp;// the number of times a counter example was found int nSatFailsImp; // the number of times the SAT solver failed to complete int nSatZeros; // the number of times the simulation vector is zero int nSatSupps; // the number of times the support info was useful int nRefErrors; // the number of ref counting errors int nImplies; // the number of implication cases int nSatImpls; // the number of implication SAT calls int nVarsClauses; // the number of variables with clauses int nSimplifies0; int nSimplifies1; int nImplies0; int nImplies1; // runtime statistics abctime timeToAig; // time to transfer to the mapping structure abctime timeSims; // time to compute k-feasible cuts abctime timeTrav; // time to traverse the network abctime timeFeed; // time for solver feedback (recording and resimulating) abctime timeImply; // time to analyze implications abctime timeSat; // time to compute the truth table for each cut abctime timeToNet; // time to transfer back to the network abctime timeTotal; // the total mapping time abctime time1; // time to perform one task abctime time2; // time to perform another task abctime time3; // time to perform another task abctime time4; // time to perform another task }; // the mapping node struct Fraig_NodeStruct_t_ { // various numbers associated with the node int Num; // the unique number (SAT var number) of this node int NumPi; // if the node is a PI, this is its variable number int Level; // the level of the node int nRefs; // the number of references of the node int TravId; // the traversal ID (use to avoid cleaning marks) int TravId2; // the traversal ID (use to avoid cleaning marks) // general information about the node unsigned fInv : 1; // the mark to show that simulation info is complemented unsigned fNodePo : 1; // the mark used for primary outputs unsigned fClauses : 1; // the clauses for this node are loaded unsigned fMark0 : 1; // the mark used for traversals unsigned fMark1 : 1; // the mark used for traversals unsigned fMark2 : 1; // the mark used for traversals unsigned fMark3 : 1; // the mark used for traversals unsigned fFeedUse : 1; // the presence of the variable in the feedback unsigned fFeedVal : 1; // the value of the variable in the feedback unsigned fFailTfo : 1; // the node is in the TFO of the failed SAT run unsigned nFanouts : 2; // the indicator of fanouts (none, one, or many) unsigned nOnes : 20; // the number of 1's in the random sim info // the children of the node Fraig_Node_t * p1; // the first child Fraig_Node_t * p2; // the second child Fraig_NodeVec_t * vFanins; // the fanins of the supergate rooted at this node // Fraig_NodeVec_t * vFanouts; // the fanouts of the supergate rooted at this node // various linked lists Fraig_Node_t * pNextS; // the next node in the structural hash table Fraig_Node_t * pNextF; // the next node in the functional (simulation) hash table Fraig_Node_t * pNextD; // the next node in the list of nodes based on dynamic simulation Fraig_Node_t * pNextE; // the next structural choice (functionally-equivalent node) Fraig_Node_t * pRepr; // the canonical functional representative of the node // simulation data unsigned uHashR; // the hash value for random information unsigned uHashD; // the hash value for dynamic information unsigned * puSimR; // the simulation information (random) unsigned * puSimD; // the simulation information (dynamic) // misc information Fraig_Node_t * pData0; // temporary storage for the corresponding network node Fraig_Node_t * pData1; // temporary storage for the corresponding network node #ifdef FRAIG_ENABLE_FANOUTS // representation of node's fanouts Fraig_Node_t * pFanPivot; // the first fanout of this node Fraig_Node_t * pFanFanin1; // the next fanout of p1 Fraig_Node_t * pFanFanin2; // the next fanout of p2 #endif }; // the vector of nodes struct Fraig_NodeVecStruct_t_ { int nCap; // the number of allocated entries int nSize; // the number of entries in the array Fraig_Node_t ** pArray; // the array of nodes }; // the hash table struct Fraig_HashTableStruct_t_ { Fraig_Node_t ** pBins; // the table bins int nBins; // the size of the table int nEntries; // the total number of entries in the table }; // getting hold of the next fanout of the node #define Fraig_NodeReadNextFanout( pNode, pFanout ) \ ( ( pFanout == NULL )? NULL : \ ((Fraig_Regular((pFanout)->p1) == (pNode))? \ (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) // getting hold of the place where the next fanout will be attached #define Fraig_NodeReadNextFanoutPlace( pNode, pFanout ) \ ( (Fraig_Regular((pFanout)->p1) == (pNode))? \ &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) // iterator through the fanouts of the node #define Fraig_NodeForEachFanout( pNode, pFanout ) \ for ( pFanout = (pNode)->pFanPivot; pFanout; \ pFanout = Fraig_NodeReadNextFanout(pNode, pFanout) ) // safe iterator through the fanouts of the node #define Fraig_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ for ( pFanout = (pNode)->pFanPivot, \ pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout); \ pFanout; \ pFanout = pFanout2, \ pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout) ) // iterators through the entries in the linked lists of nodes // the list of nodes in the structural hash table #define Fraig_TableBinForEachEntryS( pBin, pEnt ) \ for ( pEnt = pBin; \ pEnt; \ pEnt = pEnt->pNextS ) #define Fraig_TableBinForEachEntrySafeS( pBin, pEnt, pEnt2 ) \ for ( pEnt = pBin, \ pEnt2 = pEnt? pEnt->pNextS: NULL; \ pEnt; \ pEnt = pEnt2, \ pEnt2 = pEnt? pEnt->pNextS: NULL ) // the list of nodes in the functional (simulation) hash table #define Fraig_TableBinForEachEntryF( pBin, pEnt ) \ for ( pEnt = pBin; \ pEnt; \ pEnt = pEnt->pNextF ) #define Fraig_TableBinForEachEntrySafeF( pBin, pEnt, pEnt2 ) \ for ( pEnt = pBin, \ pEnt2 = pEnt? pEnt->pNextF: NULL; \ pEnt; \ pEnt = pEnt2, \ pEnt2 = pEnt? pEnt->pNextF: NULL ) // the list of nodes with the same simulation and different functionality #define Fraig_TableBinForEachEntryD( pBin, pEnt ) \ for ( pEnt = pBin; \ pEnt; \ pEnt = pEnt->pNextD ) #define Fraig_TableBinForEachEntrySafeD( pBin, pEnt, pEnt2 ) \ for ( pEnt = pBin, \ pEnt2 = pEnt? pEnt->pNextD: NULL; \ pEnt; \ pEnt = pEnt2, \ pEnt2 = pEnt? pEnt->pNextD: NULL ) // the list of nodes with the same functionality #define Fraig_TableBinForEachEntryE( pBin, pEnt ) \ for ( pEnt = pBin; \ pEnt; \ pEnt = pEnt->pNextE ) #define Fraig_TableBinForEachEntrySafeE( pBin, pEnt, pEnt2 ) \ for ( pEnt = pBin, \ pEnt2 = pEnt? pEnt->pNextE: NULL; \ pEnt; \ pEnt = pEnt2, \ pEnt2 = pEnt? pEnt->pNextE: NULL ) //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// // random number generator imported from another package extern unsigned Aig_ManRandom( int fReset ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /*=== fraigCanon.c =============================================================*/ extern Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ); /*=== fraigFanout.c =============================================================*/ extern void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ); extern void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ); extern int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ); /*=== fraigFeed.c =============================================================*/ extern void Fraig_FeedBackInit( Fraig_Man_t * p ); extern void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); extern void Fraig_FeedBackTest( Fraig_Man_t * p ); extern int Fraig_FeedBackCompress( Fraig_Man_t * p ); extern int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ); extern int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ); /*=== fraigMan.c =============================================================*/ extern void Fraig_ManCreateSolver( Fraig_Man_t * p ); /*=== fraigMem.c =============================================================*/ extern Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ); extern void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ); extern char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ); extern void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ); extern void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ); extern int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ); /*=== fraigNode.c =============================================================*/ extern Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ); extern Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ); extern Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); extern void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ); /*=== fraigPrime.c =============================================================*/ extern int s_FraigPrimes[FRAIG_MAX_PRIMES]; /*=== fraigSat.c ===============================================================*/ extern int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ); /*=== fraigTable.c =============================================================*/ extern Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ); extern void Fraig_HashTableFree( Fraig_HashTable_t * p ); extern int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ); extern Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); extern Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); extern void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); extern int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ); extern int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); extern int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ); extern void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); extern void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ); extern void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ); extern void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ); extern int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ); /*=== fraigUtil.c ===============================================================*/ extern int Fraig_NodeCountPis( Msat_IntVec_t * vVars, int nVarsPi ); extern int Fraig_NodeCountSuppVars( Fraig_Man_t * p, Fraig_Node_t * pNode, int fSuppStr ); extern int Fraig_NodesCompareSupps( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); extern int Fraig_NodeAndSimpleCase_rec( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); extern void Fraig_ManSelectBestChoice( Fraig_Man_t * p ); extern int Fraig_BitStringCountOnes( unsigned * pString, int nWords ); extern void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ); extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); extern int Fraig_NodeIsExor( Fraig_Node_t * pNode ); extern int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ); extern Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ); extern int Fraig_ManCountExors( Fraig_Man_t * pMan ); extern int Fraig_ManCountMuxes( Fraig_Man_t * pMan ); extern int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); extern int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); extern int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ); extern void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ); extern void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); extern int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); extern int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); /*=== fraigVec.c ===============================================================*/ extern void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigMan.c000066400000000000000000000525421300674244400241510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigMan.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Implementation of the FRAIG manager.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigMan.c,v 1.11 2005/07/08 01:01:31 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// abctime timeSelect; abctime timeAssign; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sets the default parameters of the package.] Description [This set of parameters is tuned for equivalence checking.] SideEffects [] SeeAlso [] ***********************************************************************/ void Prove_ParamsSetDefault( Prove_Params_t * pParams ) { // clean the parameter structure memset( pParams, 0, sizeof(Prove_Params_t) ); // general parameters pParams->fUseFraiging = 1; // enables fraiging pParams->fUseRewriting = 1; // enables rewriting pParams->fUseBdds = 0; // enables BDD construction when other methods fail pParams->fVerbose = 0; // prints verbose stats // iterations pParams->nItersMax = 6; // the number of iterations // mitering pParams->nMiteringLimitStart = 5000; // starting mitering limit pParams->nMiteringLimitMulti = 2.0; // multiplicative coefficient to increase the limit in each iteration // rewriting (currently not used) pParams->nRewritingLimitStart = 3; // the number of rewriting iterations pParams->nRewritingLimitMulti = 1.0; // multiplicative coefficient to increase the limit in each iteration // fraiging pParams->nFraigingLimitStart = 2; // starting backtrack(conflict) limit pParams->nFraigingLimitMulti = 8.0; // multiplicative coefficient to increase the limit in each iteration // last-gasp BDD construction pParams->nBddSizeLimit = 1000000; // the number of BDD nodes when construction is aborted pParams->fBddReorder = 1; // enables dynamic BDD variable reordering // last-gasp mitering // pParams->nMiteringLimitLast = 1000000; // final mitering limit pParams->nMiteringLimitLast = 0; // final mitering limit // global SAT solver limits pParams->nTotalBacktrackLimit = 0; // global limit on the number of backtracks pParams->nTotalInspectLimit = 0; // global limit on the number of clause inspects // pParams->nTotalInspectLimit = 100000000; // global limit on the number of clause inspects } /**Function************************************************************* Synopsis [Prints out the current values of CEC engine parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Prove_ParamsPrint( Prove_Params_t * pParams ) { printf( "CEC enging parameters:\n" ); printf( "Fraiging enabled: %s\n", pParams->fUseFraiging? "yes":"no" ); printf( "Rewriting enabled: %s\n", pParams->fUseRewriting? "yes":"no" ); printf( "BDD construction enabled: %s\n", pParams->fUseBdds? "yes":"no" ); printf( "Verbose output enabled: %s\n", pParams->fVerbose? "yes":"no" ); printf( "Solver iterations: %d\n", pParams->nItersMax ); printf( "Starting mitering limit: %d\n", pParams->nMiteringLimitStart ); printf( "Multiplicative coeficient for mitering: %.2f\n", pParams->nMiteringLimitMulti ); printf( "Starting number of rewriting iterations: %d\n", pParams->nRewritingLimitStart ); printf( "Multiplicative coeficient for rewriting: %.2f\n", pParams->nRewritingLimitMulti ); printf( "Starting number of conflicts in fraiging: %.2f\n", pParams->nFraigingLimitMulti ); printf( "Multiplicative coeficient for fraiging: %.2f\n", pParams->nRewritingLimitMulti ); printf( "BDD size limit for bailing out: %d\n", pParams->nBddSizeLimit ); printf( "BDD reordering enabled: %s\n", pParams->fBddReorder? "yes":"no" ); printf( "Last-gasp mitering limit: %d\n", pParams->nMiteringLimitLast ); printf( "Total conflict limit: %d\n", (int)pParams->nTotalBacktrackLimit ); printf( "Total inspection limit: %d\n", (int)pParams->nTotalInspectLimit ); printf( "Parameter dump complete.\n" ); } /**Function************************************************************* Synopsis [Sets the default parameters of the package.] Description [This set of parameters is tuned for equivalence checking.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ) { memset( pParams, 0, sizeof(Fraig_Params_t) ); pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info pParams->nBTLimit = 99; // the max number of backtracks to perform pParams->nSeconds = 20; // the max number of seconds to solve the miter pParams->fFuncRed = 1; // performs only one level hashing pParams->fFeedBack = 1; // enables solver feedback pParams->fDist1Pats = 1; // enables distance-1 patterns pParams->fDoSparse = 0; // performs equiv tests for sparse functions pParams->fChoicing = 0; // enables recording structural choices pParams->fTryProve = 1; // tries to solve the final miter pParams->fVerbose = 0; // the verbosiness flag pParams->fVerboseP = 0; // the verbose flag for reporting the proof pParams->fInternal = 0; // the flag indicates the internal run pParams->nConfLimit = 0; // the limit on the number of conflicts pParams->nInspLimit = 0; // the limit on the number of inspections } /**Function************************************************************* Synopsis [Sets the default parameters of the package.] Description [This set of parameters is tuned for complete FRAIGing.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ) { memset( pParams, 0, sizeof(Fraig_Params_t) ); pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info pParams->nBTLimit = -1; // the max number of backtracks to perform pParams->nSeconds = 20; // the max number of seconds to solve the miter 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 verbose flag for reporting the proof pParams->fInternal = 0; // the flag indicates the internal run pParams->nConfLimit = 0; // the limit on the number of conflicts pParams->nInspLimit = 0; // the limit on the number of inspections } /**Function************************************************************* Synopsis [Creates the new FRAIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) { Fraig_Params_t Params; Fraig_Man_t * p; // set the random seed for simulation // srand( 0xFEEDDEAF ); // srand( 0xDEADCAFE ); Aig_ManRandom( 1 ); // set parameters for equivalence checking if ( pParams == NULL ) Fraig_ParamsSetDefault( pParams = &Params ); // adjust the amount of simulation info if ( pParams->nPatsRand < 128 ) pParams->nPatsRand = 128; if ( pParams->nPatsRand > 32768 ) pParams->nPatsRand = 32768; if ( pParams->nPatsDyna < 128 ) pParams->nPatsDyna = 128; if ( pParams->nPatsDyna > 32768 ) pParams->nPatsDyna = 32768; // if reduction is not performed, allocate minimum simulation info if ( !pParams->fFuncRed ) pParams->nPatsRand = pParams->nPatsDyna = 128; // start the manager p = ABC_ALLOC( Fraig_Man_t, 1 ); memset( p, 0, sizeof(Fraig_Man_t) ); // set the default parameters p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand ); // the number of words of random simulation info p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna ); // the number of patterns for dynamic simulation info p->nBTLimit = pParams->nBTLimit; // -1 means infinite backtrack limit p->nSeconds = pParams->nSeconds; // the timeout for the final miter p->fFuncRed = pParams->fFuncRed; // enables functional reduction (otherwise, only one-level hashing is performed) p->fFeedBack = pParams->fFeedBack; // enables solver feedback (the use of counter-examples in simulation) p->fDist1Pats = pParams->fDist1Pats; // enables solver feedback (the use of counter-examples in simulation) p->fDoSparse = pParams->fDoSparse; // performs equivalence checking for sparse functions (whose sim-info is 0) p->fChoicing = pParams->fChoicing; // disable accumulation of structural choices (keeps only the first choice) p->fTryProve = pParams->fTryProve; // disable accumulation of structural choices (keeps only the first choice) p->fVerbose = pParams->fVerbose; // disable verbose output p->fVerboseP = pParams->fVerboseP; // disable verbose output p->nInspLimit = pParams->nInspLimit; // the limit on the number of inspections // start memory managers p->mmNodes = Fraig_MemFixedStart( sizeof(Fraig_Node_t) ); p->mmSims = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); // allocate node arrays p->vInputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary inputs p->vOutputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary outputs p->vNodes = Fraig_NodeVecAlloc( 1000 ); // the array of internal nodes // start the tables p->pTableS = Fraig_HashTableCreate( 1000 ); // hashing by structure p->pTableF = Fraig_HashTableCreate( 1000 ); // hashing by function p->pTableF0 = Fraig_HashTableCreate( 1000 ); // hashing by function (for sparse functions) // create the constant node p->pConst1 = Fraig_NodeCreateConst( p ); // initialize SAT solver feedback data structures Fraig_FeedBackInit( p ); // initialize other variables p->vProj = Msat_IntVecAlloc( 10 ); p->nTravIds = 1; p->nTravIds2 = 1; return p; } /**Function************************************************************* Synopsis [Deallocates the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManFree( Fraig_Man_t * p ) { int i; if ( p->fVerbose ) { if ( p->fChoicing ) Fraig_ManReportChoices( p ); Fraig_ManPrintStats( p ); // Fraig_TablePrintStatsS( p ); // Fraig_TablePrintStatsF( p ); // Fraig_TablePrintStatsF0( p ); } for ( i = 0; i < p->vNodes->nSize; i++ ) if ( p->vNodes->pArray[i]->vFanins ) { Fraig_NodeVecFree( p->vNodes->pArray[i]->vFanins ); p->vNodes->pArray[i]->vFanins = NULL; } if ( p->vInputs ) Fraig_NodeVecFree( p->vInputs ); if ( p->vNodes ) Fraig_NodeVecFree( p->vNodes ); if ( p->vOutputs ) Fraig_NodeVecFree( p->vOutputs ); if ( p->pTableS ) Fraig_HashTableFree( p->pTableS ); if ( p->pTableF ) Fraig_HashTableFree( p->pTableF ); if ( p->pTableF0 ) Fraig_HashTableFree( p->pTableF0 ); if ( p->pSat ) Msat_SolverFree( p->pSat ); if ( p->vProj ) Msat_IntVecFree( p->vProj ); if ( p->vCones ) Fraig_NodeVecFree( p->vCones ); if ( p->vPatsReal ) Msat_IntVecFree( p->vPatsReal ); if ( p->pModel ) ABC_FREE( p->pModel ); Fraig_MemFixedStop( p->mmNodes, 0 ); Fraig_MemFixedStop( p->mmSims, 0 ); if ( p->pSuppS ) { ABC_FREE( p->pSuppS[0] ); ABC_FREE( p->pSuppS ); } if ( p->pSuppF ) { ABC_FREE( p->pSuppF[0] ); ABC_FREE( p->pSuppF ); } ABC_FREE( p->ppOutputNames ); ABC_FREE( p->ppInputNames ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prepares the SAT solver to run on the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManCreateSolver( Fraig_Man_t * p ) { extern abctime timeSelect; extern abctime timeAssign; assert( p->pSat == NULL ); // allocate data for SAT solving p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 ); p->vVarsInt = Msat_SolverReadConeVars( p->pSat ); p->vAdjacents = Msat_SolverReadAdjacents( p->pSat ); p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat ); timeSelect = 0; timeAssign = 0; } /**Function************************************************************* Synopsis [Deallocates the mapping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManPrintStats( Fraig_Man_t * p ) { double nMemory; nMemory = ((double)(p->vInputs->nSize + p->vNodes->nSize) * (sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20); printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f MB.\n", p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory ); printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatFailsReal, p->nSatZeros ); printf( "Nodes: Final = %d. Total = %d. Mux = %d. (Exor = %d.) ClaVars = %d.\n", Fraig_CountNodes(p,0), p->vNodes->nSize, Fraig_ManCountMuxes(p), Fraig_ManCountExors(p), p->nVarsClauses ); if ( p->pSat ) Msat_SolverPrintStats( p->pSat ); Fraig_PrintTime( "AIG simulation ", p->timeSims ); Fraig_PrintTime( "AIG traversal ", p->timeTrav ); Fraig_PrintTime( "Solver feedback ", p->timeFeed ); Fraig_PrintTime( "SAT solving ", p->timeSat ); Fraig_PrintTime( "Network update ", p->timeToNet ); Fraig_PrintTime( "TOTAL RUNTIME ", p->timeTotal ); if ( p->time1 > 0 ) { Fraig_PrintTime( "time1", p->time1 ); } if ( p->time2 > 0 ) { Fraig_PrintTime( "time2", p->time2 ); } if ( p->time3 > 0 ) { Fraig_PrintTime( "time3", p->time3 ); } if ( p->time4 > 0 ) { Fraig_PrintTime( "time4", p->time4 ); } // ABC_PRT( "Selection ", timeSelect ); // ABC_PRT( "Assignment", timeAssign ); fflush( stdout ); } /**Function************************************************************* Synopsis [Allocates simulation information for all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, int fClean ) { Fraig_NodeVec_t * vInfo; unsigned * pUnsigned; int i; assert( nSize > 0 && nWords > 0 ); vInfo = Fraig_NodeVecAlloc( nSize ); pUnsigned = ABC_ALLOC( unsigned, nSize * nWords ); vInfo->pArray[0] = (Fraig_Node_t *)pUnsigned; if ( fClean ) memset( pUnsigned, 0, sizeof(unsigned) * nSize * nWords ); for ( i = 1; i < nSize; i++ ) vInfo->pArray[i] = (Fraig_Node_t *)(((unsigned *)vInfo->pArray[i-1]) + nWords); vInfo->nSize = nSize; return vInfo; } /**Function************************************************************* Synopsis [Returns simulation info of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p ) { Fraig_NodeVec_t * vInfo; Fraig_Node_t * pNode; unsigned * pUnsigned; int nRandom, nDynamic; int i, k, nWords; nRandom = Fraig_ManReadPatternNumRandom( p ); nDynamic = Fraig_ManReadPatternNumDynamic( p ); nWords = nRandom / 32 + nDynamic / 32; vInfo = Fraig_UtilInfoAlloc( p->vNodes->nSize, nWords, 0 ); for ( i = 0; i < p->vNodes->nSize; i++ ) { pNode = p->vNodes->pArray[i]; assert( i == pNode->Num ); pUnsigned = (unsigned *)vInfo->pArray[i]; for ( k = 0; k < nRandom / 32; k++ ) pUnsigned[k] = pNode->puSimR[k]; for ( k = 0; k < nDynamic / 32; k++ ) pUnsigned[nRandom / 32 + k] = pNode->puSimD[k]; } return vInfo; } /**Function************************************************************* Synopsis [Returns 1 if A v B is always true based on the siminfo.] Description [A v B is always true iff A' * B' is always false.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ) { int fCompl1, fCompl2, i; fCompl1 = 1 ^ Fraig_IsComplement(pNode1) ^ Fraig_Regular(pNode1)->fInv; fCompl2 = 1 ^ Fraig_IsComplement(pNode2) ^ Fraig_Regular(pNode2)->fInv; pNode1 = Fraig_Regular(pNode1); pNode2 = Fraig_Regular(pNode2); assert( pNode1 != pNode2 ); // check the simulation info if ( fCompl1 && fCompl2 ) { for ( i = 0; i < p->nWordsRand; i++ ) if ( ~pNode1->puSimR[i] & ~pNode2->puSimR[i] ) return 0; for ( i = 0; i < p->iWordStart; i++ ) if ( ~pNode1->puSimD[i] & ~pNode2->puSimD[i] ) return 0; return 1; } if ( !fCompl1 && fCompl2 ) { for ( i = 0; i < p->nWordsRand; i++ ) if ( pNode1->puSimR[i] & ~pNode2->puSimR[i] ) return 0; for ( i = 0; i < p->iWordStart; i++ ) if ( pNode1->puSimD[i] & ~pNode2->puSimD[i] ) return 0; return 1; } if ( fCompl1 && !fCompl2 ) { for ( i = 0; i < p->nWordsRand; i++ ) if ( ~pNode1->puSimR[i] & pNode2->puSimR[i] ) return 0; for ( i = 0; i < p->iWordStart; i++ ) if ( ~pNode1->puSimD[i] & pNode2->puSimD[i] ) return 0; return 1; } // if ( fCompl1 && fCompl2 ) { for ( i = 0; i < p->nWordsRand; i++ ) if ( pNode1->puSimR[i] & pNode2->puSimR[i] ) return 0; for ( i = 0; i < p->iWordStart; i++ ) if ( pNode1->puSimD[i] & pNode2->puSimD[i] ) return 0; return 1; } } /**Function************************************************************* Synopsis [Adds clauses to the solver.] Description [This procedure is used to add external clauses to the solver. The clauses are given by sets of nodes. Each node stands for one literal. If the node is complemented, the literal is negated.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes ) { Fraig_Node_t * pNode; int i, fComp, RetValue; if ( p->pSat == NULL ) Fraig_ManCreateSolver( p ); // create four clauses Msat_IntVecClear( p->vProj ); for ( i = 0; i < nNodes; i++ ) { pNode = Fraig_Regular(ppNodes[i]); fComp = Fraig_IsComplement(ppNodes[i]); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); // printf( "%d(%d) ", pNode->Num, fComp ); } // printf( "\n" ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigMem.c000066400000000000000000000166751300674244400241630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigMem.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Fixed-size-entry memory manager for the FRAIG package.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigMem.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Fraig_MemFixed_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 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the internal memory manager.] Description [Can only work with entry size at least 4 byte long.] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ) { Fraig_MemFixed_t * p; p = ABC_ALLOC( Fraig_MemFixed_t, 1 ); memset( p, 0, sizeof(Fraig_MemFixed_t) ); p->nEntrySize = nEntrySize; p->nEntriesAlloc = 0; p->nEntriesUsed = 0; p->pEntriesFree = NULL; if ( nEntrySize * (1 << 10) < (1<<16) ) p->nChunkSize = (1 << 10); else p->nChunkSize = (1<<16) / nEntrySize; 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 [Stops the internal memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_MemFixedStop( Fraig_MemFixed_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 [Extracts one entry from the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_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 [Returns one entry into the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_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 [Frees all associated memory and resets the manager.] Description [Relocates all the memory except the first chunk.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ) { int i; char * pTemp; // 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 [Reports the memory usage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ) { return p->nMemoryAlloc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigNode.c000066400000000000000000000250351300674244400243200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigNode.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Implementation of the FRAIG node.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigNode.c,v 1.3 2005/07/08 01:01:32 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // returns the complemented attribute of the node #define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the constant 1 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ) { Fraig_Node_t * pNode; // create the node pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); memset( pNode, 0, sizeof(Fraig_Node_t) ); // assign the number and add to the array of nodes pNode->Num = p->vNodes->nSize; Fraig_NodeVecPush( p->vNodes, pNode ); pNode->NumPi = -1; // this is not a PI, so its number is -1 pNode->Level = 0; // just like a PI, it has 0 level pNode->nRefs = 1; // it is a persistent node, which comes referenced pNode->fInv = 1; // the simulation info is complemented // create the simulation info pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); pNode->puSimD = pNode->puSimR + p->nWordsRand; memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); // count the number of ones in the simulation vector pNode->nOnes = p->nWordsRand * sizeof(unsigned) * 8; // insert it into the hash table Fraig_HashTableLookupF0( p, pNode ); return pNode; } /**Function************************************************************* Synopsis [Creates a primary input node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ) { Fraig_Node_t * pNode, * pNodeRes; int i; abctime clk; // create the node pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); memset( pNode, 0, sizeof(Fraig_Node_t) ); pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); pNode->puSimD = pNode->puSimR + p->nWordsRand; memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); // assign the number and add to the array of nodes pNode->Num = p->vNodes->nSize; Fraig_NodeVecPush( p->vNodes, pNode ); // assign the PI number and add to the array of primary inputs pNode->NumPi = p->vInputs->nSize; Fraig_NodeVecPush( p->vInputs, pNode ); pNode->Level = 0; // PI has 0 level pNode->nRefs = 1; // it is a persistent node, which comes referenced pNode->fInv = 0; // the simulation info of the PI is not complemented // derive the simulation info for the new node clk = Abc_Clock(); // set the random simulation info for the primary input pNode->uHashR = 0; for ( i = 0; i < p->nWordsRand; i++ ) { // generate the simulation info pNode->puSimR[i] = FRAIG_RANDOM_UNSIGNED; // for reasons that take very long to explain, it makes sense to have (0000000...) // pattern in the set (this helps if we need to return the counter-examples) if ( i == 0 ) pNode->puSimR[i] <<= 1; // compute the hash key pNode->uHashR ^= pNode->puSimR[i] * s_FraigPrimes[i]; } // count the number of ones in the simulation vector pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); // set the systematic simulation info for the primary input pNode->uHashD = 0; for ( i = 0; i < p->iWordStart; i++ ) { // generate the simulation info pNode->puSimD[i] = FRAIG_RANDOM_UNSIGNED; // compute the hash key pNode->uHashD ^= pNode->puSimD[i] * s_FraigPrimes[i]; } p->timeSims += Abc_Clock() - clk; // insert it into the hash table pNodeRes = Fraig_HashTableLookupF( p, pNode ); assert( pNodeRes == NULL ); // add to the runtime of simulation return pNode; } /**Function************************************************************* Synopsis [Creates a new node.] Description [This procedure should be called to create the constant node and the PI nodes first.] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) { Fraig_Node_t * pNode; abctime clk; // create the node pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); memset( pNode, 0, sizeof(Fraig_Node_t) ); // assign the children pNode->p1 = p1; Fraig_Ref(p1); Fraig_Regular(p1)->nRefs++; pNode->p2 = p2; Fraig_Ref(p2); Fraig_Regular(p2)->nRefs++; // assign the number and add to the array of nodes pNode->Num = p->vNodes->nSize; Fraig_NodeVecPush( p->vNodes, pNode ); // assign the PI number pNode->NumPi = -1; // compute the level of this node pNode->Level = 1 + Abc_MaxInt(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level); pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2); pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo; // derive the simulation info clk = Abc_Clock(); // allocate memory for the simulation info pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); pNode->puSimD = pNode->puSimR + p->nWordsRand; // derive random simulation info pNode->uHashR = 0; Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); // derive dynamic simulation info pNode->uHashD = 0; Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); // count the number of ones in the random simulation info pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); if ( pNode->fInv ) pNode->nOnes = p->nWordsRand * 32 - pNode->nOnes; // add to the runtime of simulation p->timeSims += Abc_Clock() - clk; #ifdef FRAIG_ENABLE_FANOUTS // create the fanout info Fraig_NodeAddFaninFanout( Fraig_Regular(p1), pNode ); Fraig_NodeAddFaninFanout( Fraig_Regular(p2), pNode ); #endif return pNode; } /**Function************************************************************* Synopsis [Simulates the node.] Description [Simulates the random or dynamic simulation info through the node. Uses phases of the children to determine their real simulation info. Uses phase of the node to determine the way its simulation info is stored. The resulting info is guaranteed to be 0 for the first pattern.] SideEffects [This procedure modified the hash value of the simulation info.] SeeAlso [] ***********************************************************************/ void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ) { unsigned * pSims, * pSims1, * pSims2; unsigned uHash; int fCompl, fCompl1, fCompl2, i; assert( !Fraig_IsComplement(pNode) ); // get hold of the simulation information pSims = fUseRand? pNode->puSimR : pNode->puSimD; pSims1 = fUseRand? Fraig_Regular(pNode->p1)->puSimR : Fraig_Regular(pNode->p1)->puSimD; pSims2 = fUseRand? Fraig_Regular(pNode->p2)->puSimR : Fraig_Regular(pNode->p2)->puSimD; // get complemented attributes of the children using their random info fCompl = pNode->fInv; fCompl1 = Fraig_NodeIsSimComplement(pNode->p1); fCompl2 = Fraig_NodeIsSimComplement(pNode->p2); // simulate uHash = 0; if ( fCompl1 && fCompl2 ) { if ( fCompl ) for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (pSims1[i] | pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } else for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = ~(pSims1[i] | pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } } else if ( fCompl1 && !fCompl2 ) { if ( fCompl ) for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (pSims1[i] | ~pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } else for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (~pSims1[i] & pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } } else if ( !fCompl1 && fCompl2 ) { if ( fCompl ) for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (~pSims1[i] | pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } else for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (pSims1[i] & ~pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } } else // if ( !fCompl1 && !fCompl2 ) { if ( fCompl ) for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = ~(pSims1[i] & pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } else for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (pSims1[i] & pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } } if ( fUseRand ) pNode->uHashR ^= uHash; else pNode->uHashD ^= uHash; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigPrime.c000066400000000000000000000164051300674244400245100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigPrime.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [The table of the first 1000 primes.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigPrime.c,v 1.4 2005/07/08 01:01:32 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // The 1,024 smallest prime numbers used to compute the hash value // http://www.math.utah.edu/~alfeld/math/primelist.html int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161 }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigSat.c000066400000000000000000001336531300674244400241700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigSat.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Proving functional equivalence using SAT.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigSat.c,v 1.10 2005/07/08 01:01:32 alanmi Exp $] ***********************************************************************/ #include #include "fraigInt.h" #include "sat/msat/msatInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); static void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); static void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); static void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); static void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); static void Fraig_SupergateAddClauses( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ); static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); static void Fraig_SupergateAddClausesMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); //static void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); static void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); static void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); // The lesson learned seems to be that variable should be in reverse topological order // from the output of the miter. The ordering of adjacency lists is very important. // The best way seems to be fanins followed by fanouts. Slight changes to this order // leads to big degradation in quality. static int nMuxes; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks equivalence of two nodes.] Description [Returns 1 iff the nodes are equivalent.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ) { if ( pNode1 == pNode2 ) return 1; if ( pNode1 == Fraig_Not(pNode2) ) return 0; return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit ); } /**Function************************************************************* Synopsis [Tries to prove the final miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManProveMiter( Fraig_Man_t * p ) { Fraig_Node_t * pNode; int i; abctime clk; if ( !p->fTryProve ) return; clk = Abc_Clock(); // consider all outputs of the multi-output miter for ( i = 0; i < p->vOutputs->nSize; i++ ) { pNode = Fraig_Regular(p->vOutputs->pArray[i]); // skip already constant nodes if ( pNode == p->pConst1 ) continue; // skip nodes that are different according to simulation if ( !Fraig_CompareSimInfo( pNode, p->pConst1, p->nWordsRand, 1 ) ) continue; if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1, p->nSeconds ) ) { if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ^ Fraig_NodeComparePhase(p->pConst1, pNode) ) p->vOutputs->pArray[i] = Fraig_Not(p->pConst1); else p->vOutputs->pArray[i] = p->pConst1; } } if ( p->fVerboseP ) { // ABC_PRT( "Final miter proof time", Abc_Clock() - clk ); } } /**Function************************************************************* Synopsis [Returns 1 if the miter is unsat; 0 if sat; -1 if undecided.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManCheckMiter( Fraig_Man_t * p ) { Fraig_Node_t * pNode; int i; ABC_FREE( p->pModel ); for ( i = 0; i < p->vOutputs->nSize; i++ ) { // get the output node (it can be complemented!) pNode = p->vOutputs->pArray[i]; // if the miter is constant 0, the problem is UNSAT if ( pNode == Fraig_Not(p->pConst1) ) continue; // consider the special case when the miter is constant 1 if ( pNode == p->pConst1 ) { // in this case, any counter example will do to distinquish it from constant 0 // here we pick the counter example composed of all zeros p->pModel = Fraig_ManAllocCounterExample( p ); return 0; } // save the counter example p->pModel = Fraig_ManSaveCounterExample( p, pNode ); // if the model is not found, return undecided if ( p->pModel == NULL ) return -1; else return 0; } return 1; } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_MarkTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return 0; pNode->TravId = pMan->nTravIds; // skip the PI node if ( pNode->NumPi >= 0 ) return 1; // check the children return Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p1) ) + Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p2) ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_MarkTfi2_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return 0; // skip the boundary node if ( pNode->TravId == pMan->nTravIds-1 ) { pNode->TravId = pMan->nTravIds; return 1; } pNode->TravId = pMan->nTravIds; // skip the PI node if ( pNode->NumPi >= 0 ) return 1; // check the children return Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p1) ) + Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p2) ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_MarkTfi3_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return 1; // skip the boundary node if ( pNode->TravId == pMan->nTravIds-1 ) { pNode->TravId = pMan->nTravIds; return 1; } pNode->TravId = pMan->nTravIds; // skip the PI node if ( pNode->NumPi >= 0 ) return 0; // check the children return Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p1) ) * Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p2) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_VarsStudy( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { int NumPis, NumCut, fContain; // mark the TFI of pNew p->nTravIds++; NumPis = Fraig_MarkTfi_rec( p, pNew ); printf( "(%d)(%d,%d):", NumPis, pOld->Level, pNew->Level ); // check if the old is in the TFI if ( pOld->TravId == p->nTravIds ) { printf( "* " ); return; } // count the boundary of nodes in pOld p->nTravIds++; NumCut = Fraig_MarkTfi2_rec( p, pOld ); printf( "%d", NumCut ); // check if the new is contained in the old's support p->nTravIds++; fContain = Fraig_MarkTfi3_rec( p, pNew ); printf( "%c ", fContain? '+':'-' ); } /**Function************************************************************* Synopsis [Checks whether two nodes are functinally equivalent.] Description [The flag (fComp) tells whether the nodes to be checked are in the opposite polarity. The second flag (fSkipZeros) tells whether the checking should be performed if the simulation vectors are zeros. Returns 1 if the nodes are equivalent; 0 othewise.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ) { int RetValue, RetValue1, i, fComp; abctime clk; int fVerbose = 0; int fSwitch = 0; // make sure the nodes are not complemented assert( !Fraig_IsComplement(pNew) ); assert( !Fraig_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 if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) { p->nSatFails++; // return 0; // if ( nBTLimit > 10 ) // nBTLimit /= 10; if ( nBTLimit <= 10 ) return 0; nBTLimit = (int)sqrt((double)nBTLimit); // fSwitch = 1; } p->nSatCalls++; // make sure the solver is allocated and has enough variables if ( p->pSat == NULL ) Fraig_ManCreateSolver( p ); // make sure the SAT solver has enough variables for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); /* { Fraig_Node_t * ppNodes[2] = { pOld, pNew }; extern void Fraig_MappingShowNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppRoots, int nRoots, char * pFileName ); Fraig_MappingShowNodes( p, ppNodes, 2, "temp_aig" ); } */ nMuxes = 0; // get the logic cone clk = Abc_Clock(); // Fraig_VarsStudy( p, pOld, pNew ); Fraig_OrderVariables( p, pOld, pNew ); // Fraig_PrepareCones( p, pOld, pNew ); p->timeTrav += Abc_Clock() - clk; // printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/(p->vNodes->nSize - p->vInputs->nSize) ); // ABC_PRT( "Time", Abc_Clock() - clk ); if ( fVerbose ) printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); // prepare variable activity Fraig_SetActivity( p, pOld, pNew ); // get the complemented attribute fComp = Fraig_NodeComparePhase( pOld, pNew ); //Msat_SolverPrintClauses( p->pSat ); //////////////////////////////////////////// // prepare the solver to run incrementally on these variables //clk = Abc_Clock(); Msat_SolverPrepare( p->pSat, p->vVarsInt ); //p->time3 += Abc_Clock() - clk; // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); //Msat_SolverWriteDimacs( p->pSat, "temp_fraig.cnf" ); // run the solver clk = Abc_Clock(); RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == MSAT_FALSE ) { //p->time1 += Abc_Clock() - clk; if ( fVerbose ) { // printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); //ABC_PRT( "time", Abc_Clock() - clk ); } // add the clause Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); // continue solving the other implication } else if ( RetValue1 == MSAT_TRUE ) { //p->time2 += Abc_Clock() - clk; if ( fVerbose ) { // printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); //ABC_PRT( "time", Abc_Clock() - clk ); } // record the counter example Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); // if ( pOld->fFailTfo || pNew->fFailTfo ) // printf( "*" ); // printf( "s(%d)", pNew->Level ); if ( fSwitch ) printf( "s(%d)", pNew->Level ); p->nSatCounter++; return 0; } else // if ( RetValue1 == MSAT_UNKNOWN ) { p->time3 += Abc_Clock() - clk; // if ( pOld->fFailTfo || pNew->fFailTfo ) // printf( "*" ); // printf( "T(%d)", pNew->Level ); // mark the node as the failed node if ( pOld != p->pConst1 ) pOld->fFailTfo = 1; pNew->fFailTfo = 1; // p->nSatFails++; if ( fSwitch ) printf( "T(%d)", pNew->Level ); p->nSatFailsReal++; return 0; } // if the old node was constant 0, we already know the answer if ( pOld == p->pConst1 ) return 1; //////////////////////////////////////////// // prepare the solver to run incrementally //clk = Abc_Clock(); Msat_SolverPrepare( p->pSat, p->vVarsInt ); //p->time3 += Abc_Clock() - clk; // solve under assumptions // A = 0; B = 1 OR A = 0; B = 0 Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); // run the solver clk = Abc_Clock(); RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == MSAT_FALSE ) { //p->time1 += Abc_Clock() - clk; if ( fVerbose ) { // printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); //ABC_PRT( "time", Abc_Clock() - clk ); } // add the clause Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); // continue solving the other implication } else if ( RetValue1 == MSAT_TRUE ) { //p->time2 += Abc_Clock() - clk; if ( fVerbose ) { // printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); //ABC_PRT( "time", Abc_Clock() - clk ); } // record the counter example Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); p->nSatCounter++; // if ( pOld->fFailTfo || pNew->fFailTfo ) // printf( "*" ); // printf( "s(%d)", pNew->Level ); if ( fSwitch ) printf( "s(%d)", pNew->Level ); return 0; } else // if ( RetValue1 == MSAT_UNKNOWN ) { p->time3 += Abc_Clock() - clk; // if ( pOld->fFailTfo || pNew->fFailTfo ) // printf( "*" ); // printf( "T(%d)", pNew->Level ); if ( fSwitch ) printf( "T(%d)", pNew->Level ); // mark the node as the failed node pOld->fFailTfo = 1; pNew->fFailTfo = 1; // p->nSatFails++; p->nSatFailsReal++; return 0; } // return SAT proof p->nSatProof++; // if ( pOld->fFailTfo || pNew->fFailTfo ) // printf( "*" ); // printf( "u(%d)", pNew->Level ); if ( fSwitch ) printf( "u(%d)", pNew->Level ); return 1; } /**Function************************************************************* Synopsis [Checks whether pOld => pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ) { int RetValue, RetValue1, i, fComp; abctime clk; int fVerbose = 0; // make sure the nodes are not complemented assert( !Fraig_IsComplement(pNew) ); assert( !Fraig_IsComplement(pOld) ); assert( pNew != pOld ); p->nSatCallsImp++; // make sure the solver is allocated and has enough variables if ( p->pSat == NULL ) Fraig_ManCreateSolver( p ); // make sure the SAT solver has enough variables for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); // get the logic cone clk = Abc_Clock(); Fraig_OrderVariables( p, pOld, pNew ); // Fraig_PrepareCones( p, pOld, pNew ); p->timeTrav += Abc_Clock() - clk; if ( fVerbose ) printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); // get the complemented attribute fComp = Fraig_NodeComparePhase( pOld, pNew ); //Msat_SolverPrintClauses( p->pSat ); //////////////////////////////////////////// // prepare the solver to run incrementally on these variables //clk = Abc_Clock(); Msat_SolverPrepare( p->pSat, p->vVarsInt ); //p->time3 += Abc_Clock() - clk; // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); // run the solver clk = Abc_Clock(); RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == MSAT_FALSE ) { //p->time1 += Abc_Clock() - clk; if ( fVerbose ) { // printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); //ABC_PRT( "time", Abc_Clock() - clk ); } // add the clause Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); // p->nSatProofImp++; return 1; } else if ( RetValue1 == MSAT_TRUE ) { //p->time2 += Abc_Clock() - clk; if ( fVerbose ) { // printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); //ABC_PRT( "time", Abc_Clock() - clk ); } // record the counter example Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); p->nSatCounterImp++; return 0; } else // if ( RetValue1 == MSAT_UNKNOWN ) { p->time3 += Abc_Clock() - clk; p->nSatFailsImp++; return 0; } } /**Function************************************************************* Synopsis [Prepares the SAT solver to run on the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ) { Fraig_Node_t * pNode1R, * pNode2R; int RetValue, RetValue1, i; abctime clk; int fVerbose = 0; pNode1R = Fraig_Regular(pNode1); pNode2R = Fraig_Regular(pNode2); assert( pNode1R != pNode2R ); // make sure the solver is allocated and has enough variables if ( p->pSat == NULL ) Fraig_ManCreateSolver( p ); // make sure the SAT solver has enough variables for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); // get the logic cone clk = Abc_Clock(); Fraig_OrderVariables( p, pNode1R, pNode2R ); // Fraig_PrepareCones( p, pNode1R, pNode2R ); p->timeTrav += Abc_Clock() - clk; //////////////////////////////////////////// // prepare the solver to run incrementally on these variables //clk = Abc_Clock(); Msat_SolverPrepare( p->pSat, p->vVarsInt ); //p->time3 += Abc_Clock() - clk; // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, !Fraig_IsComplement(pNode1)) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, !Fraig_IsComplement(pNode2)) ); // run the solver clk = Abc_Clock(); RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == MSAT_FALSE ) { //p->time1 += Abc_Clock() - clk; if ( fVerbose ) { // printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); //ABC_PRT( "time", Abc_Clock() - clk ); } // add the clause Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, Fraig_IsComplement(pNode1)) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, Fraig_IsComplement(pNode2)) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); // p->nSatProofImp++; return 1; } else if ( RetValue1 == MSAT_TRUE ) { //p->time2 += Abc_Clock() - clk; if ( fVerbose ) { // printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); //ABC_PRT( "time", Abc_Clock() - clk ); } // record the counter example // Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pNode1R, pNode2R ); p->nSatCounterImp++; return 0; } else // if ( RetValue1 == MSAT_UNKNOWN ) { p->time3 += Abc_Clock() - clk; p->nSatFailsImp++; return 0; } } /**Function************************************************************* Synopsis [Prepares the SAT solver to run on the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { // Msat_IntVec_t * vAdjs; // int * pVars, nVars, i, k; int nVarsAlloc; assert( pOld != pNew ); assert( !Fraig_IsComplement(pOld) ); assert( !Fraig_IsComplement(pNew) ); // clean the variables nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); Msat_IntVecClear( pMan->vVarsInt ); pMan->nTravIds++; Fraig_PrepareCones_rec( pMan, pNew ); Fraig_PrepareCones_rec( pMan, pOld ); /* nVars = Msat_IntVecReadSize( pMan->vVarsInt ); pVars = Msat_IntVecReadArray( pMan->vVarsInt ); for ( i = 0; i < nVars; i++ ) { // process its connections vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); printf( "%d=%d { ", pVars[i], Msat_IntVecReadSize(vAdjs) ); for ( k = 0; k < Msat_IntVecReadSize(vAdjs); k++ ) printf( "%d ", Msat_IntVecReadEntry(vAdjs,k) ); printf( "}\n" ); } i = 0; */ } /**Function************************************************************* Synopsis [Traverses the cone, collects the numbers and adds the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_Node_t * pFanin; Msat_IntVec_t * vAdjs; int fUseMuxes = 1, i; int fItIsTime; // skip if the node is aleady visited assert( !Fraig_IsComplement(pNode) ); if ( pNode->TravId == pMan->nTravIds ) return; pNode->TravId = pMan->nTravIds; // collect the node's number (closer to reverse topological order) Msat_IntVecPush( pMan->vVarsInt, pNode->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 ); if ( !Fraig_NodeIsAnd( pNode ) ) return; // if the node does not have fanins, create them fItIsTime = 0; if ( pNode->vFanins == NULL ) { fItIsTime = 1; // create the fanins of the supergate assert( pNode->fClauses == 0 ); if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) { pNode->vFanins = Fraig_NodeVecAlloc( 4 ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); Fraig_SupergateAddClausesMux( pMan, pNode ); } else { pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); } assert( pNode->vFanins->nSize > 1 ); pNode->fClauses = 1; pMan->nVarsClauses++; // add fanins vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num ); assert( Msat_IntVecReadSize( vAdjs ) == 0 ); for ( i = 0; i < pNode->vFanins->nSize; i++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); Msat_IntVecPush( vAdjs, pFanin->Num ); } } // recursively visit the fanins for ( i = 0; i < pNode->vFanins->nSize; i++ ) Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) ); if ( fItIsTime ) { // recursively visit the fanins for ( i = 0; i < pNode->vFanins->nSize; i++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); Msat_IntVecPush( vAdjs, pNode->Num ); } } } /**Function************************************************************* Synopsis [Collect variables using their proximity from the nodes.] Description [This procedure creates a variable order based on collecting first the nodes that are the closest to the given two target nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { Fraig_Node_t * pNode, * pFanin; int i, k, Number, fUseMuxes = 1; int nVarsAlloc; assert( pOld != pNew ); assert( !Fraig_IsComplement(pOld) ); assert( !Fraig_IsComplement(pNew) ); pMan->nTravIds++; // clean the variables nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); Msat_IntVecClear( pMan->vVarsInt ); // add the first node Msat_IntVecPush( pMan->vVarsInt, pOld->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 ); pOld->TravId = pMan->nTravIds; // add the second node Msat_IntVecPush( pMan->vVarsInt, pNew->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 ); pNew->TravId = pMan->nTravIds; // create the variable order for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) { // get the new node on the frontier Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); pNode = pMan->vNodes->pArray[Number]; if ( !Fraig_NodeIsAnd(pNode) ) continue; // if the node does not have fanins, create them if ( pNode->vFanins == NULL ) { // create the fanins of the supergate assert( pNode->fClauses == 0 ); // detecting a fanout-free cone (experiment only) // Fraig_DetectFanoutFreeCone( pMan, pNode ); if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) { pNode->vFanins = Fraig_NodeVecAlloc( 4 ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); Fraig_SupergateAddClausesMux( pMan, pNode ); // Fraig_DetectFanoutFreeConeMux( pMan, pNode ); nMuxes++; } else { pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); } assert( pNode->vFanins->nSize > 1 ); pNode->fClauses = 1; pMan->nVarsClauses++; pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark() } // explore the implication fanins of pNode for ( k = 0; k < pNode->vFanins->nSize; k++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); if ( pFanin->TravId == pMan->nTravIds ) // already collected continue; // collect and mark Msat_IntVecPush( pMan->vVarsInt, pFanin->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 ); pFanin->TravId = pMan->nTravIds; } } // set up the adjacent variable information // Fraig_SetupAdjacent( pMan, pMan->vVarsInt ); Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt ); } /**Function************************************************************* Synopsis [Set up the adjacent variable information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) { Fraig_Node_t * pNode, * pFanin; Msat_IntVec_t * vAdjs; int * pVars, nVars, i, k; // clean the adjacents for the variables nVars = Msat_IntVecReadSize( vConeVars ); pVars = Msat_IntVecReadArray( vConeVars ); for ( i = 0; i < nVars; i++ ) { // process its connections vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); Msat_IntVecClear( vAdjs ); pNode = pMan->vNodes->pArray[pVars[i]]; if ( !Fraig_NodeIsAnd(pNode) ) continue; // add fanins vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); for ( k = 0; k < pNode->vFanins->nSize; k++ ) // for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); Msat_IntVecPush( vAdjs, pFanin->Num ); // Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); } } // add the fanouts for ( i = 0; i < nVars; i++ ) { pNode = pMan->vNodes->pArray[pVars[i]]; if ( !Fraig_NodeIsAnd(pNode) ) continue; // add the edges for ( k = 0; k < pNode->vFanins->nSize; k++ ) // for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); Msat_IntVecPush( vAdjs, pNode->Num ); // Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); } } } /**Function************************************************************* Synopsis [Set up the adjacent variable information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) { Fraig_Node_t * pNode, * pFanin; Msat_IntVec_t * vAdjs; int * pVars, nVars, i, k; // clean the adjacents for the variables nVars = Msat_IntVecReadSize( vConeVars ); pVars = Msat_IntVecReadArray( vConeVars ); for ( i = 0; i < nVars; i++ ) { pNode = pMan->vNodes->pArray[pVars[i]]; if ( pNode->fMark2 == 0 ) continue; // pNode->fMark2 = 0; // process its connections // vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); // Msat_IntVecClear( vAdjs ); if ( !Fraig_NodeIsAnd(pNode) ) continue; // add fanins vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); for ( k = 0; k < pNode->vFanins->nSize; k++ ) // for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); Msat_IntVecPush( vAdjs, pFanin->Num ); // Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); } } // add the fanouts for ( i = 0; i < nVars; i++ ) { pNode = pMan->vNodes->pArray[pVars[i]]; if ( pNode->fMark2 == 0 ) continue; pNode->fMark2 = 0; if ( !Fraig_NodeIsAnd(pNode) ) continue; // add the edges for ( k = 0; k < pNode->vFanins->nSize; k++ ) // for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); Msat_IntVecPush( vAdjs, pNode->Num ); // Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); } } } /**Function************************************************************* Synopsis [Adds clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_SupergateAddClauses( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ) { int fComp1, RetValue, nVars, Var, Var1, i; assert( Fraig_NodeIsAnd( pNode ) ); nVars = Msat_SolverReadVarNum(p->pSat); Var = pNode->Num; assert( Var < nVars ); for ( i = 0; i < vSuper->nSize; i++ ) { // get the predecessor nodes // get the complemented attributes of the nodes fComp1 = Fraig_IsComplement(vSuper->pArray[i]); // determine the variable numbers Var1 = Fraig_Regular(vSuper->pArray[i])->Num; // check that the variables are in the SAT manager assert( Var1 < nVars ); // suppose the AND-gate is A * B = C // add !A => !C or A + !C // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, fComp1) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 1) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); } // add A & B => C or !A + !B + C // fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); Msat_IntVecClear( p->vProj ); for ( i = 0; i < vSuper->nSize; i++ ) { // get the predecessor nodes // get the complemented attributes of the nodes fComp1 = Fraig_IsComplement(vSuper->pArray[i]); // determine the variable numbers Var1 = Fraig_Regular(vSuper->pArray[i])->Num; // add this variable to the array Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, !fComp1) ); } Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 0) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); } /**Function************************************************************* Synopsis [Adds clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_SupergateAddClausesExor( Fraig_Man_t * p, Fraig_Node_t * pNode ) { Fraig_Node_t * pNode1, * pNode2; int fComp, RetValue; assert( !Fraig_IsComplement( pNode ) ); assert( Fraig_NodeIsExorType( pNode ) ); // get nodes pNode1 = Fraig_Regular(Fraig_Regular(pNode->p1)->p1); pNode2 = Fraig_Regular(Fraig_Regular(pNode->p1)->p2); // get the complemented attribute of the EXOR/NEXOR gate fComp = Fraig_NodeIsExor( pNode ); // 1 if EXOR, 0 if NEXOR // create four clauses Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); } /**Function************************************************************* Synopsis [Adds clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode ) { Fraig_Node_t * pNodeI, * pNodeT, * pNodeE; int RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; assert( !Fraig_IsComplement( pNode ) ); assert( Fraig_NodeIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Fraig_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the variable numbers VarF = pNode->Num; VarI = pNodeI->Num; VarT = Fraig_Regular(pNodeT)->Num; VarE = Fraig_Regular(pNodeE)->Num; // get the complementation flags fCompT = Fraig_IsComplement(pNodeT); fCompE = Fraig_IsComplement(pNodeE); // f = ITE(i, t, e) // i' + t' + f // i' + t + f' // i + e' + f // i + e + f' // create four clauses Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); // two additional clauses // t' & e' -> f' // t & e -> f // t + e + f' // t' + e' + f if ( VarT == VarE ) { // assert( fCompT == !fCompE ); return; } Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); Msat_IntVecClear( p->vProj ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); assert( RetValue ); } /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_DetectFanoutFreeCone_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) { // make the pointer regular pNode = Fraig_Regular(pNode); // if the new node is complemented or a PI, another gate begins if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) ) { Fraig_NodeVecPushUnique( vSuper, pNode ); return; } // go through the branches Fraig_DetectFanoutFreeCone_rec( pNode->p1, vSuper, vInside, 0 ); Fraig_DetectFanoutFreeCone_rec( pNode->p2, vSuper, vInside, 0 ); // add the node Fraig_NodeVecPushUnique( vInside, pNode ); } /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_NodeVec_t * vFanins; Fraig_NodeVec_t * vInside; int nCubes; extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); vFanins = Fraig_NodeVecAlloc( 8 ); vInside = Fraig_NodeVecAlloc( 8 ); Fraig_DetectFanoutFreeCone_rec( pNode, vFanins, vInside, 1 ); assert( vInside->pArray[vInside->nSize-1] == pNode ); nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); printf( "%d(%d)", vFanins->nSize, nCubes ); Fraig_NodeVecFree( vFanins ); Fraig_NodeVecFree( vInside ); } */ /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_DetectFanoutFreeConeMux_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) { // make the pointer regular pNode = Fraig_Regular(pNode); // if the new node is complemented or a PI, another gate begins if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) || !Fraig_NodeIsMuxType(pNode) ) { Fraig_NodeVecPushUnique( vSuper, pNode ); return; } // go through the branches Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p1, vSuper, vInside, 0 ); Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p2, vSuper, vInside, 0 ); Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p1, vSuper, vInside, 0 ); Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p2, vSuper, vInside, 0 ); // add the node Fraig_NodeVecPushUnique( vInside, pNode ); } /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_NodeVec_t * vFanins; Fraig_NodeVec_t * vInside; int nCubes; extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); vFanins = Fraig_NodeVecAlloc( 8 ); vInside = Fraig_NodeVecAlloc( 8 ); Fraig_DetectFanoutFreeConeMux_rec( pNode, vFanins, vInside, 1 ); assert( vInside->pArray[vInside->nSize-1] == pNode ); // nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); nCubes = 0; printf( "%d(%d)", vFanins->nSize, nCubes ); Fraig_NodeVecFree( vFanins ); Fraig_NodeVecFree( vInside ); } /**Function************************************************************* Synopsis [Collect variables using their proximity from the nodes.] Description [This procedure creates a variable order based on collecting first the nodes that are the closest to the given two target nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { Fraig_Node_t * pNode; int i, Number, MaxLevel; float * pFactors = Msat_SolverReadFactors(pMan->pSat); if ( pFactors == NULL ) return; MaxLevel = Abc_MaxInt( pOld->Level, pNew->Level ); // create the variable order for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) { // get the new node on the frontier Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); pNode = pMan->vNodes->pArray[Number]; pFactors[pNode->Num] = (float)pow( 0.97, MaxLevel - pNode->Level ); // if ( pNode->Num % 50 == 0 ) // printf( "(%d) %.2f ", MaxLevel - pNode->Level, pFactors[pNode->Num] ); } // printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigTable.c000066400000000000000000000502601300674244400244600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigTable.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Structural and functional hash tables.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigTable.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Fraig_TableResizeS( Fraig_HashTable_t * p ); static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ) { Fraig_HashTable_t * p; // allocate the table p = ABC_ALLOC( Fraig_HashTable_t, 1 ); memset( p, 0, sizeof(Fraig_HashTable_t) ); // allocate and clean the bins p->nBins = Abc_PrimeCudd(nSize); p->pBins = ABC_ALLOC( Fraig_Node_t *, p->nBins ); memset( p->pBins, 0, sizeof(Fraig_Node_t *) * p->nBins ); return p; } /**Function************************************************************* Synopsis [Deallocates the supergate hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_HashTableFree( Fraig_HashTable_t * p ) { ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Looks up an entry in the structural hash table.] Description [If the entry with the same children does not exists, creates it, inserts it into the table, and returns 0. If the entry with the same children exists, finds it, and return 1. In both cases, the new/old entry is returned in ppNodeRes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ) { Fraig_HashTable_t * p = pMan->pTableS; Fraig_Node_t * pEnt; unsigned Key; // order the arguments if ( Fraig_Regular(p1)->Num > Fraig_Regular(p2)->Num ) pEnt = p1, p1 = p2, p2 = pEnt; Key = Fraig_HashKey2( p1, p2, p->nBins ); Fraig_TableBinForEachEntryS( p->pBins[Key], pEnt ) if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) { *ppNodeRes = pEnt; return 1; } // check if it is a good time for table resizing if ( p->nEntries >= 2 * p->nBins ) { Fraig_TableResizeS( p ); Key = Fraig_HashKey2( p1, p2, p->nBins ); } // create the new node pEnt = Fraig_NodeCreate( pMan, p1, p2 ); // add the node to the corresponding linked list in the table pEnt->pNextS = p->pBins[Key]; p->pBins[Key] = pEnt; *ppNodeRes = pEnt; p->nEntries++; return 0; } /**Function************************************************************* Synopsis [Insert the entry in the functional hash table.] Description [If the entry with the same key exists, return it right away. If the entry with the same key does not exists, inserts it and returns NULL. ] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_HashTable_t * p = pMan->pTableF; Fraig_Node_t * pEnt, * pEntD; unsigned Key; // go through the hash table entries Key = pNode->uHashR % p->nBins; Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) { // if their simulation info differs, skip if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->nWordsRand, 1 ) ) continue; // equivalent up to the complement Fraig_TableBinForEachEntryD( pEnt, pEntD ) { // if their simulation info differs, skip if ( !Fraig_CompareSimInfo( pNode, pEntD, pMan->iWordStart, 0 ) ) continue; // found a simulation-equivalent node return pEntD; } // did not find a simulation equivalent node // add the node to the corresponding linked list pNode->pNextD = pEnt->pNextD; pEnt->pNextD = pNode; // return NULL, because there is no functional equivalence in this case return NULL; } // check if it is a good time for table resizing if ( p->nEntries >= 2 * p->nBins ) { Fraig_TableResizeF( p, 1 ); Key = pNode->uHashR % p->nBins; } // add the node to the corresponding linked list in the table pNode->pNextF = p->pBins[Key]; p->pBins[Key] = pNode; p->nEntries++; // return NULL, because there is no functional equivalence in this case return NULL; } /**Function************************************************************* Synopsis [Insert the entry in the functional hash table.] Description [If the entry with the same key exists, return it right away. If the entry with the same key does not exists, inserts it and returns NULL. ] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_HashTable_t * p = pMan->pTableF0; Fraig_Node_t * pEnt; unsigned Key; // go through the hash table entries Key = pNode->uHashD % p->nBins; Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) { // if their simulation info differs, skip if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->iWordStart, 0 ) ) continue; // found a simulation-equivalent node return pEnt; } // check if it is a good time for table resizing if ( p->nEntries >= 2 * p->nBins ) { Fraig_TableResizeF( p, 0 ); Key = pNode->uHashD % p->nBins; } // add the node to the corresponding linked list in the table pNode->pNextF = p->pBins[Key]; p->pBins[Key] = pNode; p->nEntries++; // return NULL, because there is no functional equivalence in this case return NULL; } /**Function************************************************************* Synopsis [Insert the entry in the functional hash table.] Description [Unconditionally add the node to the corresponding linked list in the table.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_HashTable_t * p = pMan->pTableF0; unsigned Key = pNode->uHashD % p->nBins; pNode->pNextF = p->pBins[Key]; p->pBins[Key] = pNode; p->nEntries++; } /**Function************************************************************* Synopsis [Resizes the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_TableResizeS( Fraig_HashTable_t * p ) { Fraig_Node_t ** pBinsNew; Fraig_Node_t * pEnt, * pEnt2; int nBinsNew, Counter, i; abctime clk; unsigned Key; clk = Abc_Clock(); // get the new table size nBinsNew = Abc_PrimeCudd(2 * p->nBins); // allocate a new array pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < p->nBins; i++ ) Fraig_TableBinForEachEntrySafeS( p->pBins[i], pEnt, pEnt2 ) { Key = Fraig_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); pEnt->pNextS = pBinsNew[Key]; pBinsNew[Key] = pEnt; Counter++; } assert( Counter == p->nEntries ); // printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew ); // ABC_PRT( "Time", Abc_Clock() - clk ); // replace the table and the parameters ABC_FREE( p->pBins ); p->pBins = pBinsNew; p->nBins = nBinsNew; } /**Function************************************************************* Synopsis [Resizes the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ) { Fraig_Node_t ** pBinsNew; Fraig_Node_t * pEnt, * pEnt2; int nBinsNew, Counter, i; abctime clk; unsigned Key; clk = Abc_Clock(); // get the new table size nBinsNew = Abc_PrimeCudd(2 * p->nBins); // allocate a new array pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < p->nBins; i++ ) Fraig_TableBinForEachEntrySafeF( p->pBins[i], pEnt, pEnt2 ) { if ( fUseSimR ) Key = pEnt->uHashR % nBinsNew; else Key = pEnt->uHashD % nBinsNew; pEnt->pNextF = pBinsNew[Key]; pBinsNew[Key] = pEnt; Counter++; } assert( Counter == p->nEntries ); // printf( "Increasing the functional table size from %6d to %6d. ", p->nBins, nBinsNew ); // ABC_PRT( "Time", Abc_Clock() - clk ); // replace the table and the parameters ABC_FREE( p->pBins ); p->pBins = pBinsNew; p->nBins = nBinsNew; } /**Function************************************************************* Synopsis [Compares two pieces of simulation info.] Description [Returns 1 if they are equal.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ) { int i; assert( !Fraig_IsComplement(pNode1) ); assert( !Fraig_IsComplement(pNode2) ); if ( fUseRand ) { // if their signatures differ, skip if ( pNode1->uHashR != pNode2->uHashR ) return 0; // check the simulation info for ( i = 0; i < iWordLast; i++ ) if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) return 0; } else { // if their signatures differ, skip if ( pNode1->uHashD != pNode2->uHashD ) return 0; // check the simulation info for ( i = 0; i < iWordLast; i++ ) if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) return 0; } return 1; } /**Function************************************************************* Synopsis [Find the number of the different pattern.] Description [Returns -1 if there is no such pattern] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ) { int i, v; assert( !Fraig_IsComplement(pNode1) ); assert( !Fraig_IsComplement(pNode2) ); // take into account possible internal complementation fCompl ^= pNode1->fInv; fCompl ^= pNode2->fInv; // find the pattern if ( fCompl ) { if ( fUseRand ) { for ( i = 0; i < iWordLast; i++ ) if ( pNode1->puSimR[i] != ~pNode2->puSimR[i] ) for ( v = 0; v < 32; v++ ) if ( (pNode1->puSimR[i] ^ ~pNode2->puSimR[i]) & (1 << v) ) return i * 32 + v; } else { for ( i = 0; i < iWordLast; i++ ) if ( pNode1->puSimD[i] != ~pNode2->puSimD[i] ) for ( v = 0; v < 32; v++ ) if ( (pNode1->puSimD[i] ^ ~pNode2->puSimD[i]) & (1 << v) ) return i * 32 + v; } } else { if ( fUseRand ) { for ( i = 0; i < iWordLast; i++ ) if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) for ( v = 0; v < 32; v++ ) if ( (pNode1->puSimR[i] ^ pNode2->puSimR[i]) & (1 << v) ) return i * 32 + v; } else { for ( i = 0; i < iWordLast; i++ ) if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) for ( v = 0; v < 32; v++ ) if ( (pNode1->puSimD[i] ^ pNode2->puSimD[i]) & (1 << v) ) return i * 32 + v; } } return -1; } /**Function************************************************************* Synopsis [Compares two pieces of simulation info.] Description [Returns 1 if they are equal.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) { unsigned * pSims1, * pSims2; int i; assert( !Fraig_IsComplement(pNode1) ); assert( !Fraig_IsComplement(pNode2) ); // get hold of simulation info pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; // check the simulation info for ( i = 0; i < iWordLast; i++ ) if ( (pSims1[i] & puMask[i]) != (pSims2[i] & puMask[i]) ) return 0; return 1; } /**Function************************************************************* Synopsis [Compares two pieces of simulation info.] Description [Returns 1 if they are equal.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) { unsigned * pSims1, * pSims2; int i; assert( !Fraig_IsComplement(pNode1) ); assert( !Fraig_IsComplement(pNode2) ); // get hold of simulation info pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; // check the simulation info for ( i = 0; i < iWordLast; i++ ) puMask[i] = ( pSims1[i] ^ pSims2[i] ); } /**Function************************************************************* Synopsis [Prints stats of the structural table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ) { Fraig_HashTable_t * pT = pMan->pTableS; Fraig_Node_t * pNode; int i, Counter; printf( "Structural table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); for ( i = 0; i < pT->nBins; i++ ) { Counter = 0; Fraig_TableBinForEachEntryS( pT->pBins[i], pNode ) Counter++; if ( Counter > 1 ) { printf( "%d ", Counter ); if ( Counter > 50 ) printf( "{%d} ", i ); } } printf( "\n" ); } /**Function************************************************************* Synopsis [Prints stats of the structural table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ) { Fraig_HashTable_t * pT = pMan->pTableF; Fraig_Node_t * pNode; int i, Counter; printf( "Functional table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); for ( i = 0; i < pT->nBins; i++ ) { Counter = 0; Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) Counter++; if ( Counter > 1 ) printf( "{%d} ", Counter ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Prints stats of the structural table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ) { Fraig_HashTable_t * pT = pMan->pTableF0; Fraig_Node_t * pNode; int i, Counter; printf( "Zero-node table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); for ( i = 0; i < pT->nBins; i++ ) { Counter = 0; Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) Counter++; if ( Counter == 0 ) continue; /* printf( "\nBin = %4d : Number of entries = %4d\n", i, Counter ); Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) printf( "Node %5d. Hash = %10d.\n", pNode->Num, pNode->uHashD ); */ } printf( "\n" ); } /**Function************************************************************* Synopsis [Rehashes the table after the simulation info has changed.] Description [Assumes that the hash values have been updated after performing additional simulation. Rehashes the table using the new hash values. Uses pNextF to link the entries in the bins. Uses pNextD to link the entries with identical hash values. Returns 1 if the identical entries have been found. Note that identical hash values may mean that the simulation data is different.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ) { Fraig_HashTable_t * pT = pMan->pTableF0; Fraig_Node_t ** pBinsNew; Fraig_Node_t * pEntF, * pEntF2, * pEnt, * pEntD2, * pEntN; int ReturnValue, Counter, i; unsigned Key; // allocate a new array of bins pBinsNew = ABC_ALLOC( Fraig_Node_t *, pT->nBins ); memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * pT->nBins ); // rehash the entries in the table // go through all the nodes in the F-lists (and possible in D-lists, if used) Counter = 0; ReturnValue = 0; for ( i = 0; i < pT->nBins; i++ ) Fraig_TableBinForEachEntrySafeF( pT->pBins[i], pEntF, pEntF2 ) Fraig_TableBinForEachEntrySafeD( pEntF, pEnt, pEntD2 ) { // decide where to put entry pEnt Key = pEnt->uHashD % pT->nBins; if ( fLinkEquiv ) { // go through the entries in the new bin Fraig_TableBinForEachEntryF( pBinsNew[Key], pEntN ) { // if they have different values skip if ( pEnt->uHashD != pEntN->uHashD ) continue; // they have the same hash value, add pEnt to the D-list pEnt3 pEnt->pNextD = pEntN->pNextD; pEntN->pNextD = pEnt; ReturnValue = 1; Counter++; break; } if ( pEntN != NULL ) // already linked continue; // we did not find equal entry } // link the new entry pEnt->pNextF = pBinsNew[Key]; pBinsNew[Key] = pEnt; pEnt->pNextD = NULL; Counter++; } assert( Counter == pT->nEntries ); // replace the table and the parameters ABC_FREE( pT->pBins ); pT->pBins = pBinsNew; return ReturnValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigUtil.c000066400000000000000000000757271300674244400243650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigUtil.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Various utilities.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigUtil.c,v 1.15 2005/07/08 01:01:34 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" #include ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ); static int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ) { Fraig_NodeVec_t * vNodes; int i; pMan->nTravIds++; vNodes = Fraig_NodeVecAlloc( 100 ); for ( i = 0; i < pMan->vOutputs->nSize; i++ ) Fraig_Dfs_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), vNodes, fEquiv ); return vNodes; } /**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ) { Fraig_NodeVec_t * vNodes; pMan->nTravIds++; vNodes = Fraig_NodeVecAlloc( 100 ); Fraig_Dfs_rec( pMan, Fraig_Regular(pNode), vNodes, fEquiv ); return vNodes; } /**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ) { Fraig_NodeVec_t * vNodes; int i; pMan->nTravIds++; vNodes = Fraig_NodeVecAlloc( 100 ); for ( i = 0; i < nNodes; i++ ) Fraig_Dfs_rec( pMan, Fraig_Regular(ppNodes[i]), vNodes, fEquiv ); return vNodes; } /**Function************************************************************* Synopsis [Recursively computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ) { assert( !Fraig_IsComplement(pNode) ); // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return; pNode->TravId = pMan->nTravIds; // visit the transitive fanin if ( Fraig_NodeIsAnd(pNode) ) { Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p1), vNodes, fEquiv ); Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p2), vNodes, fEquiv ); } if ( fEquiv && pNode->pNextE ) Fraig_Dfs_rec( pMan, pNode->pNextE, vNodes, fEquiv ); // save the node Fraig_NodeVecPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ) { Fraig_NodeVec_t * vNodes; int RetValue; vNodes = Fraig_Dfs( pMan, fEquiv ); RetValue = vNodes->nSize; Fraig_NodeVecFree( vNodes ); return RetValue; } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { assert( !Fraig_IsComplement(pOld) ); assert( !Fraig_IsComplement(pNew) ); pMan->nTravIds++; return Fraig_CheckTfi_rec( pMan, pNew, pOld ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ) { // check the trivial cases if ( pNode == NULL ) return 0; if ( pNode->Num < pOld->Num && !pMan->fChoicing ) return 0; if ( pNode == pOld ) return 1; // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return 0; pNode->TravId = pMan->nTravIds; // check the children if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p1), pOld ) ) return 1; if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p2), pOld ) ) return 1; // check equivalent nodes return Fraig_CheckTfi_rec( pMan, pNode->pNextE, pOld ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_CheckTfi2( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { Fraig_NodeVec_t * vNodes; int RetValue; vNodes = Fraig_DfsOne( pMan, pNew, 1 ); RetValue = (pOld->TravId == pMan->nTravIds); Fraig_NodeVecFree( vNodes ); return RetValue; } /**Function************************************************************* Synopsis [Sets the number of fanouts (none, one, or many).] Description [This procedure collects the nodes reachable from the POs of the AIG and sets the type of fanout counter (none, one, or many) for each node. This procedure is useful to determine fanout-free cones of AND-nodes, which is helpful for rebalancing the AIG (see procedure Fraig_ManRebalance, or something like that).] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ) { Fraig_NodeVec_t * vNodes; Fraig_Node_t * pNodeR; int i; // collect the nodes reachable vNodes = Fraig_Dfs( p, 0 ); // clean the fanouts field for ( i = 0; i < vNodes->nSize; i++ ) { vNodes->pArray[i]->nFanouts = 0; vNodes->pArray[i]->pData0 = NULL; } // mark reachable nodes by setting the two-bit counter pNode->nFans for ( i = 0; i < vNodes->nSize; i++ ) { pNodeR = Fraig_Regular(vNodes->pArray[i]->p1); if ( pNodeR && ++pNodeR->nFanouts == 3 ) pNodeR->nFanouts = 2; pNodeR = Fraig_Regular(vNodes->pArray[i]->p2); if ( pNodeR && ++pNodeR->nFanouts == 3 ) pNodeR->nFanouts = 2; } Fraig_NodeVecFree( vNodes ); } /**Function************************************************************* Synopsis [Creates the constant 1 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_BitStringCountOnes( unsigned * pString, int nWords ) { unsigned char * pSuppBytes = (unsigned char *)pString; int i, nOnes, nBytes = sizeof(unsigned) * nWords; // count the number of ones in the simulation vector for ( i = nOnes = 0; i < nBytes; i++ ) nOnes += bit_count[pSuppBytes[i]]; return nOnes; } /**Function************************************************************* Synopsis [Verify one useful property.] Description [This procedure verifies one useful property. After the FRAIG construction with choice nodes is over, each primary node should have fanins that are primary nodes. The primary nodes is the one that does not have pNode->pRepr set to point to another node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManCheckConsistency( Fraig_Man_t * p ) { Fraig_Node_t * pNode; Fraig_NodeVec_t * pVec; int i; pVec = Fraig_Dfs( p, 0 ); for ( i = 0; i < pVec->nSize; i++ ) { pNode = pVec->pArray[i]; if ( Fraig_NodeIsVar(pNode) ) { if ( pNode->pRepr ) printf( "Primary input %d is a secondary node.\n", pNode->Num ); } else if ( Fraig_NodeIsConst(pNode) ) { if ( pNode->pRepr ) printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); } else { if ( pNode->pRepr ) printf( "Internal node %d is a secondary node.\n", pNode->Num ); if ( Fraig_Regular(pNode->p1)->pRepr ) printf( "Internal node %d has first fanin %d that is a secondary node.\n", pNode->Num, Fraig_Regular(pNode->p1)->Num ); if ( Fraig_Regular(pNode->p2)->pRepr ) printf( "Internal node %d has second fanin %d that is a secondary node.\n", pNode->Num, Fraig_Regular(pNode->p2)->Num ); } } Fraig_NodeVecFree( pVec ); return 1; } /**Function************************************************************* Synopsis [Prints the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_PrintNode( Fraig_Man_t * p, Fraig_Node_t * pNode ) { Fraig_NodeVec_t * vNodes; Fraig_Node_t * pTemp; int fCompl1, fCompl2, i; vNodes = Fraig_DfsOne( p, pNode, 0 ); for ( i = 0; i < vNodes->nSize; i++ ) { pTemp = vNodes->pArray[i]; if ( Fraig_NodeIsVar(pTemp) ) { printf( "%3d : PI ", pTemp->Num ); Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); printf( " " ); Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); printf( " %d\n", pTemp->fInv ); continue; } fCompl1 = Fraig_IsComplement(pTemp->p1); fCompl2 = Fraig_IsComplement(pTemp->p2); printf( "%3d : %c%3d %c%3d ", pTemp->Num, (fCompl1? '-':'+'), Fraig_Regular(pTemp->p1)->Num, (fCompl2? '-':'+'), Fraig_Regular(pTemp->p2)->Num ); Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); printf( " " ); Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); printf( " %d\n", pTemp->fInv ); } Fraig_NodeVecFree( vNodes ); } /**Function************************************************************* Synopsis [Prints the bit string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ) { int Remainder, nWords; int w, i; Remainder = (nBits%(sizeof(unsigned)*8)); nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); for ( w = nWords-1; w >= 0; w-- ) for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) fprintf( pFile, "%c", '0' + (int)((pSign[w] & (1< 0) ); // fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Sets up the mask.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_GetMaxLevel( Fraig_Man_t * pMan ) { int nLevelMax, i; nLevelMax = 0; for ( i = 0; i < pMan->vOutputs->nSize; i++ ) nLevelMax = nLevelMax > Fraig_Regular(pMan->vOutputs->pArray[i])->Level? nLevelMax : Fraig_Regular(pMan->vOutputs->pArray[i])->Level; return nLevelMax; } /**Function************************************************************* Synopsis [Analyses choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_MappingUpdateLevel_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fMaximum ) { Fraig_Node_t * pTemp; int Level1, Level2, LevelE; assert( !Fraig_IsComplement(pNode) ); if ( !Fraig_NodeIsAnd(pNode) ) return pNode->Level; // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return pNode->Level; pNode->TravId = pMan->nTravIds; // compute levels of the children nodes Level1 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p1), fMaximum ); Level2 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p2), fMaximum ); pNode->Level = 1 + Abc_MaxInt( Level1, Level2 ); if ( pNode->pNextE ) { LevelE = Fraig_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); if ( fMaximum ) { if ( pNode->Level < LevelE ) pNode->Level = LevelE; } else { if ( pNode->Level > LevelE ) pNode->Level = LevelE; } // set the level of all equivalent nodes to be the same minimum if ( pNode->pRepr == NULL ) // the primary node for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) pTemp->Level = pNode->Level; } return pNode->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 [] ***********************************************************************/ void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ) { int i; pMan->nTravIds++; for ( i = 0; i < pMan->vOutputs->nSize; i++ ) Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), fMaximum ); } /**Function************************************************************* Synopsis [Reports statistics on choice nodes.] Description [The number of choice nodes is the number of primary nodes, which has pNextE set to a pointer. The number of choices is the number of entries in the equivalent-node lists of the primary nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManReportChoices( Fraig_Man_t * pMan ) { Fraig_Node_t * pNode, * pTemp; int nChoiceNodes, nChoices; int i, LevelMax1, LevelMax2; // report the number of levels LevelMax1 = Fraig_GetMaxLevel( pMan ); Fraig_MappingSetChoiceLevels( pMan, 0 ); LevelMax2 = Fraig_GetMaxLevel( pMan ); // report statistics about choices nChoiceNodes = nChoices = 0; for ( i = 0; i < pMan->vNodes->nSize; i++ ) { pNode = pMan->vNodes->pArray[i]; if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) { // this is a choice node = the primary node that has equivalent nodes nChoiceNodes++; for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) nChoices++; } } printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of EXOR/NEXOR gate.] Description [The node can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsExorType( Fraig_Node_t * pNode ) { Fraig_Node_t * pNode1, * pNode2; // make the node regular (it does not matter for EXOR/NEXOR) pNode = Fraig_Regular(pNode); // if the node or its children are not ANDs or not compl, this cannot be EXOR type if ( !Fraig_NodeIsAnd(pNode) ) return 0; if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) return 0; if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) return 0; // get children pNode1 = Fraig_Regular(pNode->p1); pNode2 = Fraig_Regular(pNode->p2); assert( pNode1->Num < pNode2->Num ); // compare grandchildren return pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2); } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] Description [The node can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ) { Fraig_Node_t * pNode1, * pNode2; // make the node regular (it does not matter for EXOR/NEXOR) pNode = Fraig_Regular(pNode); // if the node or its children are not ANDs or not compl, this cannot be EXOR type if ( !Fraig_NodeIsAnd(pNode) ) return 0; if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) return 0; if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) return 0; // get children pNode1 = Fraig_Regular(pNode->p1); pNode2 = Fraig_Regular(pNode->p2); assert( pNode1->Num < pNode2->Num ); // compare grandchildren // node is an EXOR/NEXOR if ( pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2) ) return 1; // otherwise the node is MUX iff it has a pair of equal grandchildren return pNode1->p1 == Fraig_Not(pNode2->p1) || pNode1->p1 == Fraig_Not(pNode2->p2) || pNode1->p2 == Fraig_Not(pNode2->p1) || pNode1->p2 == Fraig_Not(pNode2->p2); } /**Function************************************************************* Synopsis [Returns 1 if the node is EXOR, 0 if it is NEXOR.] Description [The node should be EXOR type and not complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsExor( Fraig_Node_t * pNode ) { Fraig_Node_t * pNode1; assert( !Fraig_IsComplement(pNode) ); assert( Fraig_NodeIsExorType(pNode) ); assert( Fraig_IsComplement(pNode->p1) ); // get children pNode1 = Fraig_Regular(pNode->p1); return Fraig_IsComplement(pNode1->p1) == Fraig_IsComplement(pNode1->p2); } /**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 [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ) { Fraig_Node_t * pNode1, * pNode2; assert( !Fraig_IsComplement(pNode) ); assert( Fraig_NodeIsMuxType(pNode) ); // get children pNode1 = Fraig_Regular(pNode->p1); pNode2 = Fraig_Regular(pNode->p2); // find the control variable if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) { if ( Fraig_IsComplement(pNode1->p1) ) { // pNode2->p1 is positive phase of C *ppNodeT = Fraig_Not(pNode2->p2); *ppNodeE = Fraig_Not(pNode1->p2); return pNode2->p1; } else { // pNode1->p1 is positive phase of C *ppNodeT = Fraig_Not(pNode1->p2); *ppNodeE = Fraig_Not(pNode2->p2); return pNode1->p1; } } else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) { if ( Fraig_IsComplement(pNode1->p1) ) { // pNode2->p2 is positive phase of C *ppNodeT = Fraig_Not(pNode2->p1); *ppNodeE = Fraig_Not(pNode1->p2); return pNode2->p2; } else { // pNode1->p1 is positive phase of C *ppNodeT = Fraig_Not(pNode1->p2); *ppNodeE = Fraig_Not(pNode2->p1); return pNode1->p1; } } else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) { if ( Fraig_IsComplement(pNode1->p2) ) { // pNode2->p1 is positive phase of C *ppNodeT = Fraig_Not(pNode2->p2); *ppNodeE = Fraig_Not(pNode1->p1); return pNode2->p1; } else { // pNode1->p2 is positive phase of C *ppNodeT = Fraig_Not(pNode1->p1); *ppNodeE = Fraig_Not(pNode2->p2); return pNode1->p2; } } else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) { if ( Fraig_IsComplement(pNode1->p2) ) { // pNode2->p2 is positive phase of C *ppNodeT = Fraig_Not(pNode2->p1); *ppNodeE = Fraig_Not(pNode1->p1); return pNode2->p2; } else { // pNode1->p2 is positive phase of C *ppNodeT = Fraig_Not(pNode1->p1); *ppNodeE = Fraig_Not(pNode2->p1); return pNode1->p2; } } assert( 0 ); // this is not MUX return NULL; } /**Function************************************************************* Synopsis [Counts the number of EXOR type nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManCountExors( Fraig_Man_t * pMan ) { int i, nExors; nExors = 0; for ( i = 0; i < pMan->vNodes->nSize; i++ ) nExors += Fraig_NodeIsExorType( pMan->vNodes->pArray[i] ); return nExors; } /**Function************************************************************* Synopsis [Counts the number of EXOR type nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManCountMuxes( Fraig_Man_t * pMan ) { int i, nMuxes; nMuxes = 0; for ( i = 0; i < pMan->vNodes->nSize; i++ ) nMuxes += Fraig_NodeIsMuxType( pMan->vNodes->pArray[i] ); return nMuxes; } /**Function************************************************************* Synopsis [Returns 1 if siminfo of Node1 is contained in siminfo of Node2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ) { unsigned * pUnsigned1, * pUnsigned2; int i; // compare random siminfo pUnsigned1 = pNode1->puSimR; pUnsigned2 = pNode2->puSimR; for ( i = 0; i < pMan->nWordsRand; i++ ) if ( pUnsigned1[i] & ~pUnsigned2[i] ) return 0; // compare systematic siminfo pUnsigned1 = pNode1->puSimD; pUnsigned2 = pNode2->puSimD; for ( i = 0; i < pMan->iWordStart; i++ ) if ( pUnsigned1[i] & ~pUnsigned2[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Count the number of PI variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ) { int * pVars, nVars, i, Counter; nVars = Msat_IntVecReadSize(vVarNums); pVars = Msat_IntVecReadArray(vVarNums); Counter = 0; for ( i = 0; i < nVars; i++ ) Counter += Fraig_NodeIsVar( p->vNodes->pArray[pVars[i]] ); return Counter; } /**Function************************************************************* Synopsis [Counts the number of EXOR type nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManPrintRefs( Fraig_Man_t * pMan ) { Fraig_NodeVec_t * vPivots; Fraig_Node_t * pNode, * pNode2; int i, k, Counter, nProved; abctime clk; vPivots = Fraig_NodeVecAlloc( 1000 ); for ( i = 0; i < pMan->vNodes->nSize; i++ ) { pNode = pMan->vNodes->pArray[i]; if ( pNode->nOnes == 0 || pNode->nOnes == (unsigned)pMan->nWordsRand * 32 ) continue; if ( pNode->nRefs > 5 ) { Fraig_NodeVecPush( vPivots, pNode ); // printf( "Node %6d : nRefs = %2d Level = %3d.\n", pNode->Num, pNode->nRefs, pNode->Level ); } } printf( "Total nodes = %d. Referenced nodes = %d.\n", pMan->vNodes->nSize, vPivots->nSize ); clk = Abc_Clock(); // count implications Counter = nProved = 0; for ( i = 0; i < vPivots->nSize; i++ ) for ( k = i+1; k < vPivots->nSize; k++ ) { pNode = vPivots->pArray[i]; pNode2 = vPivots->pArray[k]; if ( Fraig_NodeSimsContained( pMan, pNode, pNode2 ) ) { if ( Fraig_NodeIsImplication( pMan, pNode, pNode2, -1 ) ) nProved++; Counter++; } else if ( Fraig_NodeSimsContained( pMan, pNode2, pNode ) ) { if ( Fraig_NodeIsImplication( pMan, pNode2, pNode, -1 ) ) nProved++; Counter++; } } printf( "Number of candidate pairs = %d. Proved = %d.\n", Counter, nProved ); //ABC_PRT( "Time", Abc_Clock() - clk ); return 0; } /**Function************************************************************* Synopsis [Checks if pNew exists among the implication fanins of pOld.] Description [If pNew is an implication fanin of pOld, returns 1. If Fraig_Not(pNew) is an implication fanin of pOld, return -1. Otherwise returns 0.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { int RetValue1, RetValue2; if ( Fraig_Regular(pOld) == Fraig_Regular(pNew) ) return (pOld == pNew)? 1 : -1; if ( Fraig_IsComplement(pOld) || Fraig_NodeIsVar(pOld) ) return 0; RetValue1 = Fraig_NodeIsInSupergate( pOld->p1, pNew ); RetValue2 = Fraig_NodeIsInSupergate( pOld->p2, pNew ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; if ( RetValue1 == 1 || RetValue2 == 1 ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_CollectSupergate_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, int fFirst, int fStopAtMux ) { // if the new node is complemented or a PI, another gate begins // if ( Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || Fraig_NodeIsMuxType(pNode) ) if ( (!fFirst && Fraig_Regular(pNode)->nRefs > 1) || Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || (fStopAtMux && Fraig_NodeIsMuxType(pNode)) ) { Fraig_NodeVecPushUnique( vSuper, pNode ); return; } // go through the branches Fraig_CollectSupergate_rec( pNode->p1, vSuper, 0, fStopAtMux ); Fraig_CollectSupergate_rec( pNode->p2, vSuper, 0, fStopAtMux ); } /**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ) { Fraig_NodeVec_t * vSuper; vSuper = Fraig_NodeVecAlloc( 8 ); Fraig_CollectSupergate_rec( pNode, vSuper, 1, fStopAtMux ); return vSuper; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ) { pMan->nTravIds2++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { pNode->TravId2 = pMan->nTravIds2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { return pNode->TravId2 == pMan->nTravIds2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { return pNode->TravId2 == pMan->nTravIds2 - 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/fraigVec.c000066400000000000000000000331461300674244400241520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [fraigVec.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Vector of FRAIG nodes.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigVec.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates a vector with the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ) { Fraig_NodeVec_t * p; p = ABC_ALLOC( Fraig_NodeVec_t, 1 ); if ( nCap > 0 && nCap < 8 ) nCap = 8; p->nSize = 0; p->nCap = nCap; p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecFree( Fraig_NodeVec_t * p ) { ABC_FREE( p->pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Duplicates the integer array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * pVec ) { Fraig_NodeVec_t * p; p = ABC_ALLOC( Fraig_NodeVec_t, 1 ); p->nSize = pVec->nSize; p->nCap = pVec->nCap; p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL; memcpy( p->pArray, pVec->pArray, sizeof(Fraig_Node_t *) * pVec->nSize ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ) { return p->pArray; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ) { return p->nSize; } /**Function************************************************************* Synopsis [Resizes the vector to the given capacity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = ABC_REALLOC( Fraig_Node_t *, p->pArray, nCapMin ); p->nCap = nCapMin; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ) { assert( p->nSize >= nSizeNew ); p->nSize = nSizeNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecClear( Fraig_NodeVec_t * p ) { p->nSize = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) { if ( p->nSize == p->nCap ) { if ( p->nCap < 16 ) Fraig_NodeVecGrow( p, 16 ); else Fraig_NodeVecGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Entry; } /**Function************************************************************* Synopsis [Add the element while ensuring uniqueness.] Description [Returns 1 if the element was found, and 0 if it was new. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Fraig_NodeVecPush( p, Entry ); return 0; } /**Function************************************************************* Synopsis [Inserts a new node in the order by arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) { Fraig_Node_t * pNode1, * pNode2; int i; Fraig_NodeVecPush( p, pNode ); // find the p of the node for ( i = p->nSize-1; i > 0; i-- ) { pNode1 = p->pArray[i ]; pNode2 = p->pArray[i-1]; if ( pNode1 >= pNode2 ) break; p->pArray[i ] = pNode2; p->pArray[i-1] = pNode1; } } /**Function************************************************************* Synopsis [Add the element while ensuring uniqueness in the order.] Description [Returns 1 if the element was found, and 0 if it was new. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == pNode ) return 1; Fraig_NodeVecPushOrder( p, pNode ); return 0; } /**Function************************************************************* Synopsis [Inserts a new node in the order by arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) { Fraig_Node_t * pNode1, * pNode2; int i; Fraig_NodeVecPush( p, pNode ); // find the p of the node for ( i = p->nSize-1; i > 0; i-- ) { pNode1 = p->pArray[i ]; pNode2 = p->pArray[i-1]; if ( Fraig_Regular(pNode1)->Level <= Fraig_Regular(pNode2)->Level ) break; p->pArray[i ] = pNode2; p->pArray[i-1] = pNode1; } } /**Function************************************************************* Synopsis [Add the element while ensuring uniqueness in the order.] Description [Returns 1 if the element was found, and 0 if it was new. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == pNode ) return 1; Fraig_NodeVecPushOrderByLevel( p, pNode ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ) { return p->pArray[--p->nSize]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) break; assert( i < p->nSize ); for ( i++; i < p->nSize; i++ ) p->pArray[i-1] = p->pArray[i]; p->nSize--; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Entry; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ) { assert( i >= 0 && i < p->nSize ); return p->pArray[i]; } /**Function************************************************************* Synopsis [Comparison procedure for two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecCompareLevelsIncreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) { int Level1 = Fraig_Regular(*pp1)->Level; int Level2 = Fraig_Regular(*pp2)->Level; if ( Level1 < Level2 ) return -1; if ( Level1 > Level2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Comparison procedure for two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecCompareLevelsDecreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) { int Level1 = Fraig_Regular(*pp1)->Level; int Level2 = Fraig_Regular(*pp2)->Level; if ( Level1 > Level2 ) return -1; if ( Level1 < Level2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Comparison procedure for two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecCompareNumbers( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) { int Num1 = Fraig_Regular(*pp1)->Num; int Num2 = Fraig_Regular(*pp2)->Num; if ( Num1 < Num2 ) return -1; if ( Num1 > Num2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Comparison procedure for two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecCompareRefCounts( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) { int nRefs1 = Fraig_Regular(*pp1)->nRefs; int nRefs2 = Fraig_Regular(*pp2)->nRefs; if ( nRefs1 < nRefs2 ) return -1; if ( nRefs1 > nRefs2 ) return 1; nRefs1 = Fraig_Regular(*pp1)->Level; nRefs2 = Fraig_Regular(*pp2)->Level; if ( nRefs1 < nRefs2 ) return -1; if ( nRefs1 > nRefs2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ) { if ( fIncreasing ) qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsIncreasing ); else qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsDecreasing ); } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ) { qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), (int (*)(const void *, const void *)) Fraig_NodeVecCompareNumbers ); } /**Function************************************************************* Synopsis [Sorting the entries by their integer value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ) { qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), (int (*)(const void *, const void *)) Fraig_NodeVecCompareRefCounts ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/fraig/module.make000066400000000000000000000005711300674244400244000ustar00rootroot00000000000000SRC += src/proof/fraig/fraigApi.c \ src/proof/fraig/fraigCanon.c \ src/proof/fraig/fraigFanout.c \ src/proof/fraig/fraigFeed.c \ src/proof/fraig/fraigMan.c \ src/proof/fraig/fraigMem.c \ src/proof/fraig/fraigNode.c \ src/proof/fraig/fraigPrime.c \ src/proof/fraig/fraigSat.c \ src/proof/fraig/fraigTable.c \ src/proof/fraig/fraigUtil.c \ src/proof/fraig/fraigVec.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/000077500000000000000000000000001300674244400217535ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/int.h000066400000000000000000000071071300674244400227230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [int.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: int.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__int__int_h #define ABC__aig__int__int_h /* The interpolation algorithm implemented here was introduced in the paper: K. L. McMillan. Interpolation and SAT-based model checking. CAV’03, pp. 1-13. */ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // simulation manager typedef struct Inter_ManParams_t_ Inter_ManParams_t; struct Inter_ManParams_t_ { int nBTLimit; // limit on the number of conflicts int nFramesMax; // the max number timeframes to unroll int nSecLimit; // time limit in seconds int nFramesK; // the number of timeframes to use in induction int fRewrite; // use additional rewriting to simplify timeframes int fTransLoop; // add transition into the init state under new PI var int fUsePudlak; // use Pudluk interpolation procedure int fUseOther; // use other undisclosed option int fUseMiniSat; // use MiniSat-1.14p instead of internal proof engine int fCheckKstep; // check using K-step induction int fUseBias; // bias decisions to global variables int fUseBackward; // perform backward interpolation int fUseSeparate; // solve each output separately int fUseTwoFrames; // create the OR of two last timeframes int fDropSatOuts; // replace by 1 the solved outputs int fDropInvar; // dump inductive invariant into file int fVerbose; // print verbose statistics int iFrameMax; // the time frame reached char * pFileName; // file name to dump interpolant }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== intCore.c ==========================================================*/ extern void Inter_ManSetDefaultParams( Inter_ManParams_t * p ); extern int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intCheck.c000066400000000000000000000240031300674244400236460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intCheck.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Procedures to perform incremental inductive check.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // checking manager struct Inter_Check_t_ { int nFramesK; // the number of timeframes (K=1 for simple induction) int nVars; // the current number of variables in the solver Aig_Man_t * pFrames; // unrolled timeframes Cnf_Dat_t * pCnf; // CNF of unrolled timeframes sat_solver * pSat; // SAT solver Vec_Int_t * vOrLits; // OR vars in each time frame (total number is the number nFrames) Vec_Int_t * vAndLits; // AND vars in the last timeframe (total number is the number of interpolants) Vec_Int_t * vAssLits; // assumptions (the union of the two) }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create timeframes of the manager for interpolation.] Description [The resulting manager is combinational. The primary inputs corresponding to register outputs are ordered first.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManUnrollFrames( Aig_Man_t * pAig, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; assert( Saig_ManRegNum(pAig) > 0 ); 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) ); // 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; Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObjLo->pData ); } } Aig_ManCleanup( pFrames ); return pFrames; } /**Function************************************************************* Synopsis [This procedure sets default values of interpolation parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK ) { Inter_Check_t * p; // create solver p = ABC_CALLOC( Inter_Check_t, 1 ); p->vOrLits = Vec_IntAlloc( 100 ); p->vAndLits = Vec_IntAlloc( 100 ); p->vAssLits = Vec_IntAlloc( 100 ); // generate the timeframes p->pFrames = Inter_ManUnrollFrames( pTrans, nFramesK ); assert( Aig_ManCiNum(p->pFrames) == nFramesK * Saig_ManPiNum(pTrans) + Saig_ManRegNum(pTrans) ); assert( Aig_ManCoNum(p->pFrames) == nFramesK * Saig_ManRegNum(pTrans) ); // convert to CNF p->pCnf = Cnf_Derive( p->pFrames, Aig_ManCoNum(p->pFrames) ); p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 ); // assign parameters p->nFramesK = nFramesK; p->nVars = p->pCnf->nVars; return p; } /**Function************************************************************* Synopsis [This procedure sets default values of interpolation parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_CheckStop( Inter_Check_t * p ) { if ( p == NULL ) return; Vec_IntFree( p->vOrLits ); Vec_IntFree( p->vAndLits ); Vec_IntFree( p->vAssLits ); Cnf_DataFree( p->pCnf ); Aig_ManStop( p->pFrames ); sat_solver_delete( p->pSat ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates one OR-gate: A + B = C.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_CheckAddOrGate( Inter_Check_t * p, int iVarA, int iVarB, int iVarC ) { int RetValue, pLits[3]; // add A => C or !A + C pLits[0] = toLitCond(iVarA, 1); pLits[1] = toLitCond(iVarC, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); // add B => C or !B + C pLits[0] = toLitCond(iVarB, 1); pLits[1] = toLitCond(iVarC, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); // add !A & !B => !C or A + B + !C pLits[0] = toLitCond(iVarA, 0); pLits[1] = toLitCond(iVarB, 0); pLits[2] = toLitCond(iVarC, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Creates equality: A = B.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_CheckAddEqual( Inter_Check_t * p, int iVarA, int iVarB ) { int RetValue, pLits[3]; // add A => B or !A + B pLits[0] = toLitCond(iVarA, 1); pLits[1] = toLitCond(iVarB, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); // add B => A or !B + A pLits[0] = toLitCond(iVarB, 1); pLits[1] = toLitCond(iVarA, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Perform the checking.] Description [Returns 1 if the check has passed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnfInt, abctime nTimeNewOut ) { Aig_Obj_t * pObj, * pObj2; int i, f, VarA, VarB, RetValue, Entry, status; int nRegs = Aig_ManCiNum(pCnfInt->pMan); assert( Aig_ManCoNum(p->pCnf->pMan) == p->nFramesK * nRegs ); assert( Aig_ManCoNum(pCnfInt->pMan) == 1 ); // set runtime limit if ( nTimeNewOut ) sat_solver_set_runtime_limit( p->pSat, nTimeNewOut ); // add clauses to the SAT solver Cnf_DataLift( pCnfInt, p->nVars ); for ( f = 0; f <= p->nFramesK; f++ ) { // add clauses to the solver for ( i = 0; i < pCnfInt->nClauses; i++ ) { RetValue = sat_solver_addclause( p->pSat, pCnfInt->pClauses[i], pCnfInt->pClauses[i+1] ); assert( RetValue ); } // add equality clauses for the flop variables Aig_ManForEachCi( pCnfInt->pMan, pObj, i ) { pObj2 = f ? Aig_ManCo(p->pFrames, i + (f-1) * nRegs) : Aig_ManCi(p->pFrames, i); Inter_CheckAddEqual( p, pCnfInt->pVarNums[pObj->Id], p->pCnf->pVarNums[pObj2->Id] ); } // add final clauses if ( f < p->nFramesK ) { if ( f == Vec_IntSize(p->vOrLits) ) // find time here { // add literal to this frame VarB = pCnfInt->pVarNums[ Aig_ManCo(pCnfInt->pMan, 0)->Id ]; Vec_IntPush( p->vOrLits, VarB ); } else { // add OR gate for this frame VarA = Vec_IntEntry( p->vOrLits, f ); VarB = pCnfInt->pVarNums[ Aig_ManCo(pCnfInt->pMan, 0)->Id ]; Inter_CheckAddOrGate( p, VarA, VarB, p->nVars + pCnfInt->nVars ); Vec_IntWriteEntry( p->vOrLits, f, p->nVars + pCnfInt->nVars ); // using var ID! } } else { // add AND gate for this frame VarB = pCnfInt->pVarNums[ Aig_ManCo(pCnfInt->pMan, 0)->Id ]; Vec_IntPush( p->vAndLits, VarB ); } // update variable IDs Cnf_DataLift( pCnfInt, pCnfInt->nVars + 1 ); p->nVars += pCnfInt->nVars + 1; } Cnf_DataLift( pCnfInt, -p->nVars ); assert( Vec_IntSize(p->vOrLits) == p->nFramesK ); // collect the assumption literals Vec_IntClear( p->vAssLits ); Vec_IntForEachEntry( p->vOrLits, Entry, i ) Vec_IntPush( p->vAssLits, toLitCond(Entry, 0) ); Vec_IntForEachEntry( p->vAndLits, Entry, i ) Vec_IntPush( p->vAssLits, toLitCond(Entry, 1) ); /* if ( pCnfInt->nLiterals == 3635 ) { int s = 0; } */ // call the SAT solver status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssLits), Vec_IntArray(p->vAssLits) + Vec_IntSize(p->vAssLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); return status == l_False; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intContain.c000066400000000000000000000250571300674244400242360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intContain.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Interpolant containment checking.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intContain.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" #include "proof/fra/fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks constainment of two interpolants.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld ) { Aig_Man_t * pMiter, * pAigTemp; int RetValue; pMiter = Aig_ManCreateMiter( pNew, pOld, 1 ); // pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 ); // Aig_ManStop( pAigTemp ); RetValue = Fra_FraigMiterStatus( pMiter ); if ( RetValue == -1 ) { pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 ); RetValue = Fra_FraigMiterStatus( pAigTemp ); Aig_ManStop( pAigTemp ); // RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0, 0, 0 ); } assert( RetValue != -1 ); Aig_ManStop( pMiter ); return RetValue; } /**Function************************************************************* Synopsis [Checks constainment of two interpolants.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld ) { Aig_Man_t * pMiter, * pAigTemp; int RetValue; pMiter = Aig_ManCreateMiter( pNew, pOld, 0 ); // pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 ); // Aig_ManStop( pAigTemp ); RetValue = Fra_FraigMiterStatus( pMiter ); if ( RetValue == -1 ) { pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 ); RetValue = Fra_FraigMiterStatus( pAigTemp ); Aig_ManStop( pAigTemp ); // RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0, 0, 0 ); } assert( RetValue != -1 ); Aig_ManStop( pMiter ); return RetValue; } /**Function************************************************************* Synopsis [Create timeframes of the manager for interpolation.] Description [The resulting manager is combinational. The primary inputs corresponding to register outputs are ordered first.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManFramesLatches( Aig_Man_t * pAig, int nFrames, Vec_Ptr_t ** pvMapReg ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; assert( Saig_ManRegNum(pAig) > 0 ); pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); // create variables for register outputs *pvMapReg = Vec_PtrAlloc( (nFrames+1) * Saig_ManRegNum(pAig) ); Saig_ManForEachLo( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCi( pFrames ); Vec_PtrPush( *pvMapReg, pObj->pData ); } // 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) ); // 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; Vec_PtrPush( *pvMapReg, pObjLo->pData ); } } return pFrames; } /**Function************************************************************* Synopsis [Duplicates AIG while mapping PIs into the given array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_ManAppendCone( Aig_Man_t * pOld, Aig_Man_t * pNew, Aig_Obj_t ** ppNewPis, int fCompl ) { Aig_Obj_t * pObj; int i; assert( Aig_ManCoNum(pOld) == 1 ); // create the PIs Aig_ManCleanData( pOld ); Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( pOld, pObj, i ) pObj->pData = ppNewPis[i]; // duplicate internal nodes Aig_ManForEachNode( pOld, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add one PO to new pObj = Aig_ManCo( pOld, 0 ); Aig_ObjCreateCo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ); } /**Function************************************************************* Synopsis [Checks constainment of two interpolants inductively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ) { Aig_Man_t * pFrames; Aig_Obj_t ** ppNodes; Vec_Ptr_t * vMapRegs; Cnf_Dat_t * pCnf; sat_solver * pSat; int f, nRegs, status; nRegs = Saig_ManRegNum(pTrans); assert( nRegs > 0 ); // generate the timeframes pFrames = Inter_ManFramesLatches( pTrans, nSteps, &vMapRegs ); assert( Vec_PtrSize(vMapRegs) == (nSteps + 1) * nRegs ); // add main constraints to the timeframes ppNodes = (Aig_Obj_t **)Vec_PtrArray(vMapRegs); if ( !fBackward ) { // forward inductive check: p -> p -> ... -> !p for ( f = 0; f < nSteps; f++ ) Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 ); Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 1 ); } else { // backward inductive check: p -> !p -> ... -> !p Inter_ManAppendCone( pInter, pFrames, ppNodes + 0 * nRegs, 1 ); for ( f = 1; f <= nSteps; f++ ) Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 ); } Vec_PtrFree( vMapRegs ); Aig_ManCleanup( pFrames ); // convert to CNF pCnf = Cnf_Derive( pFrames, 0 ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // Cnf_DataFree( pCnf ); // Aig_ManStop( pFrames ); if ( pSat == NULL ) { Cnf_DataFree( pCnf ); Aig_ManStop( pFrames ); return 1; } // 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 ); // Inter_ManCheckUniqueness( pTrans, pSat, pCnf, nSteps ); Cnf_DataFree( pCnf ); Aig_ManStop( pFrames ); sat_solver_delete( pSat ); return status == l_False; } ABC_NAMESPACE_IMPL_END #include "proof/fra/fra.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Check if cex satisfies uniqueness constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames ) { extern int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ); extern void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ); extern void Fra_SmlSimulateOne( Fra_Sml_t * p ); Fra_Sml_t * pSml; Vec_Int_t * vPis; Aig_Obj_t * pObj, * pObj0; int i, k, v, iBit, * pCounterEx; int Counter; if ( nFrames == 1 ) return 1; // if ( pSat->model.size == 0 ) // possible consequences here!!! assert( 0 ); if ( sat_solver_nvars(pSat) == 0 ) return 1; // assert( Saig_ManPoNum(p) == 1 ); assert( Aig_ManRegNum(p) > 0 ); assert( Aig_ManRegNum(p) < Aig_ManCiNum(p) ); // get the counter-example vPis = Vec_IntAlloc( 100 ); Aig_ManForEachCi( pCnf->pMan, pObj, k ) Vec_IntPush( vPis, pCnf->pVarNums[Aig_ObjId(pObj)] ); assert( Vec_IntSize(vPis) == Aig_ManRegNum(p) + nFrames * Saig_ManPiNum(p) ); pCounterEx = Sat_SolverGetModel( pSat, vPis->pArray, vPis->nSize ); Vec_IntFree( vPis ); // start a new sequential simulator pSml = Fra_SmlStart( p, 0, nFrames, 1 ); // assign simulation info for the registers iBit = 0; Aig_ManForEachLoSeq( p, pObj, i ) Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], 0 ); // assign simulation info for the primary inputs for ( i = 0; i < nFrames; i++ ) Aig_ManForEachPiSeq( p, pObj, k ) Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], i ); assert( iBit == Aig_ManCiNum(pCnf->pMan) ); // run simulation Fra_SmlSimulateOne( pSml ); // check if the given output has failed // RetValue = !Fra_SmlNodeIsZero( pSml, Aig_ManCo(pAig, 0) ); // assert( RetValue ); // check values at the internal nodes Counter = 0; for ( i = 0; i < nFrames; i++ ) for ( k = i+1; k < nFrames; k++ ) { for ( v = 0; v < Aig_ManRegNum(p); v++ ) { pObj0 = Aig_ManLo(p, v); if ( !Fra_SmlNodesCompareInFrame( pSml, pObj0, pObj0, i, k ) ) break; } if ( v == Aig_ManRegNum(p) ) Counter++; } printf( "Uniquness does not hold in %d frames.\n", Counter ); Fra_SmlStop( pSml ); ABC_FREE( pCounterEx ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intCore.c000066400000000000000000000376511300674244400235360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START ////////////////////////////////////////////////////////////////////////` /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default values of interpolation parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_ManSetDefaultParams( Inter_ManParams_t * p ) { memset( p, 0, sizeof(Inter_ManParams_t) ); p->nBTLimit = 0; // limit on the number of conflicts p->nFramesMax = 0; // the max number timeframes to unroll p->nSecLimit = 0; // time limit in seconds p->nFramesK = 1; // the number of timeframes to use in induction p->fRewrite = 0; // use additional rewriting to simplify timeframes p->fTransLoop = 0; // add transition into the init state under new PI var p->fUsePudlak = 0; // use Pudluk interpolation procedure p->fUseOther = 0; // use other undisclosed option p->fUseMiniSat = 0; // use MiniSat-1.14p instead of internal proof engine p->fCheckKstep = 1; // check using K-step induction p->fUseBias = 0; // bias decisions to global variables p->fUseBackward = 0; // perform backward interpolation p->fUseSeparate = 0; // solve each output separately p->fUseTwoFrames = 0; // create OR of two last timeframes p->fDropSatOuts = 0; // replace by 1 the solved outputs p->fVerbose = 0; // print verbose statistics p->iFrameMax =-1; } /**Function************************************************************* Synopsis [Interplates while the number of conflicts is not exceeded.] Description [Returns 1 if proven. 0 if failed. -1 if undecided.] SideEffects [Does not check the property in 0-th frame.] SeeAlso [] ***********************************************************************/ int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame ) { extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ); Inter_Man_t * p; Inter_Check_t * pCheck = NULL; Aig_Man_t * pAigTemp; int s, i, RetValue, Status; abctime clk, clk2, clkTotal = Abc_Clock(), timeTemp = 0; abctime nTimeNewOut = pPars->nSecLimit ? pPars->nSecLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; // enable ORing of the interpolants, if containment check is performed inductively with K > 1 if ( pPars->nFramesK > 1 ) pPars->fTransLoop = 1; // sanity checks assert( Saig_ManRegNum(pAig) > 0 ); assert( Saig_ManPiNum(pAig) > 0 ); assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 ); if ( pPars->fVerbose && Saig_ManConstrNum(pAig) ) printf( "Performing interpolation with %d constraints...\n", Saig_ManConstrNum(pAig) ); if ( Inter_ManCheckInitialState(pAig) ) { *piFrame = -1; printf( "Property trivially fails in the initial state.\n" ); return 0; } /* if ( Inter_ManCheckAllStates(pAig) ) { printf( "Property trivially holds in all states.\n" ); return 1; } */ // create interpolation manager // can perform SAT sweeping and/or rewriting of this AIG... p = Inter_ManCreate( pAig, pPars ); if ( pPars->fTransLoop ) p->pAigTrans = Inter_ManStartOneOutput( pAig, 0 ); else p->pAigTrans = Inter_ManStartDuplicated( pAig ); // derive CNF for the transformed AIG clk = Abc_Clock(); p->pCnfAig = Cnf_Derive( p->pAigTrans, Aig_ManRegNum(p->pAigTrans) ); p->timeCnf += Abc_Clock() - clk; if ( pPars->fVerbose ) { printf( "AIG: PI/PO/Reg = %d/%d/%d. And = %d. Lev = %d. CNF: Var/Cla = %d/%d.\n", Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), Aig_ManAndNum(pAig), Aig_ManLevelNum(pAig), p->pCnfAig->nVars, p->pCnfAig->nClauses ); } // derive interpolant *piFrame = -1; p->nFrames = 1; for ( s = 0; ; s++ ) { Cnf_Dat_t * pCnfInter2; clk2 = Abc_Clock(); // initial state if ( pPars->fUseBackward ) p->pInter = Inter_ManStartOneOutput( pAig, 1 ); else p->pInter = Inter_ManStartInitState( Aig_ManRegNum(pAig) ); assert( Aig_ManCoNum(p->pInter) == 1 ); clk = Abc_Clock(); p->pCnfInter = Cnf_Derive( p->pInter, 0 ); p->timeCnf += Abc_Clock() - clk; // timeframes p->pFrames = Inter_ManFramesInter( pAig, p->nFrames, pPars->fUseBackward, pPars->fUseTwoFrames ); clk = Abc_Clock(); if ( pPars->fRewrite ) { p->pFrames = Dar_ManRwsat( pAigTemp = p->pFrames, 1, 0 ); Aig_ManStop( pAigTemp ); // p->pFrames = Fra_FraigEquivence( pAigTemp = p->pFrames, 100, 0 ); // Aig_ManStop( pAigTemp ); } p->timeRwr += Abc_Clock() - clk; // can also do SAT sweeping on the timeframes... clk = Abc_Clock(); if ( pPars->fUseBackward ) p->pCnfFrames = Cnf_Derive( p->pFrames, Aig_ManCoNum(p->pFrames) ); else // p->pCnfFrames = Cnf_Derive( p->pFrames, 0 ); p->pCnfFrames = Cnf_DeriveSimple( p->pFrames, 0 ); p->timeCnf += Abc_Clock() - clk; // report statistics if ( pPars->fVerbose ) { printf( "Step = %2d. Frames = 1 + %d. And = %5d. Lev = %5d. ", s+1, p->nFrames, Aig_ManNodeNum(p->pFrames), Aig_ManLevelNum(p->pFrames) ); ABC_PRT( "Time", Abc_Clock() - clk2 ); } ////////////////////////////////////////// // start containment checking if ( !(pPars->fTransLoop || pPars->fUseBackward || pPars->nFramesK > 1) ) { pCheck = Inter_CheckStart( p->pAigTrans, pPars->nFramesK ); // try new containment check for the initial state clk = Abc_Clock(); pCnfInter2 = Cnf_Derive( p->pInter, 1 ); p->timeCnf += Abc_Clock() - clk; clk = Abc_Clock(); RetValue = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut ); p->timeEqu += Abc_Clock() - clk; // assert( RetValue == 0 ); Cnf_DataFree( pCnfInter2 ); if ( p->vInters ) Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInter) ); } ////////////////////////////////////////// // iterate the interpolation procedure for ( i = 0; ; i++ ) { if ( pPars->nFramesMax && p->nFrames + i >= pPars->nFramesMax ) { if ( pPars->fVerbose ) printf( "Reached limit (%d) on the number of timeframes.\n", pPars->nFramesMax ); p->timeTotal = Abc_Clock() - clkTotal; Inter_ManStop( p, 0 ); Inter_CheckStop( pCheck ); return -1; } // perform interpolation clk = Abc_Clock(); #ifdef ABC_USE_LIBRARIES if ( pPars->fUseMiniSat ) { assert( !pPars->fUseBackward ); RetValue = Inter_ManPerformOneStepM114p( p, pPars->fUsePudlak, pPars->fUseOther ); } else #endif RetValue = Inter_ManPerformOneStep( p, pPars->fUseBias, pPars->fUseBackward, nTimeNewOut ); if ( pPars->fVerbose ) { printf( " I = %2d. Bmc =%3d. IntAnd =%6d. IntLev =%5d. Conf =%6d. ", i+1, i + 1 + p->nFrames, Aig_ManNodeNum(p->pInter), Aig_ManLevelNum(p->pInter), p->nConfCur ); ABC_PRT( "Time", Abc_Clock() - clk ); } // remember the number of timeframes completed pPars->iFrameMax = i - 1 + p->nFrames; if ( RetValue == 0 ) // found a (spurious?) counter-example { if ( i == 0 ) // real counterexample { if ( pPars->fVerbose ) printf( "Found a real counterexample in frame %d.\n", p->nFrames ); p->timeTotal = Abc_Clock() - clkTotal; *piFrame = p->nFrames; // pAig->pSeqModel = (Abc_Cex_t *)Inter_ManGetCounterExample( pAig, p->nFrames+1, pPars->fVerbose ); { int RetValue; Saig_ParBmc_t ParsBmc, * pParsBmc = &ParsBmc; Saig_ParBmcSetDefaultParams( pParsBmc ); pParsBmc->nConfLimit = 100000000; pParsBmc->nStart = p->nFrames; pParsBmc->fVerbose = pPars->fVerbose; RetValue = Saig_ManBmcScalable( pAig, pParsBmc ); if ( RetValue == 1 ) printf( "Error: The problem should be SAT but it is UNSAT.\n" ); else if ( RetValue == -1 ) printf( "Error: The problem timed out.\n" ); } Inter_ManStop( p, 0 ); Inter_CheckStop( pCheck ); return 0; } // likely spurious counter-example p->nFrames += i; Inter_ManClean( p ); break; } else if ( RetValue == -1 ) { if ( pPars->nSecLimit && Abc_Clock() > nTimeNewOut ) // timed out { if ( pPars->fVerbose ) printf( "Reached timeout (%d seconds).\n", pPars->nSecLimit ); } else { assert( p->nConfCur >= p->nConfLimit ); if ( pPars->fVerbose ) printf( "Reached limit (%d) on the number of conflicts.\n", p->nConfLimit ); } p->timeTotal = Abc_Clock() - clkTotal; Inter_ManStop( p, 0 ); Inter_CheckStop( pCheck ); return -1; } assert( RetValue == 1 ); // found new interpolant // compress the interpolant clk = Abc_Clock(); if ( p->pInterNew ) { // save the timeout value p->pInterNew->Time2Quit = nTimeNewOut; // Ioa_WriteAiger( p->pInterNew, "interpol.aig", 0, 0 ); p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 1, 0 ); // p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 0, 0 ); Aig_ManStop( pAigTemp ); if ( p->pInterNew == NULL ) { printf( "Reached timeout (%d seconds) during rewriting.\n", pPars->nSecLimit ); p->timeTotal = Abc_Clock() - clkTotal; Inter_ManStop( p, 1 ); Inter_CheckStop( pCheck ); return -1; } } p->timeRwr += Abc_Clock() - clk; // check if interpolant is trivial if ( p->pInterNew == NULL || Aig_ObjChild0(Aig_ManCo(p->pInterNew,0)) == Aig_ManConst0(p->pInterNew) ) { // printf( "interpolant is constant 0\n" ); if ( pPars->fVerbose ) printf( "The problem is trivially true for all states.\n" ); p->timeTotal = Abc_Clock() - clkTotal; Inter_ManStop( p, 1 ); Inter_CheckStop( pCheck ); return 1; } // check containment of interpolants clk = Abc_Clock(); if ( pPars->fCheckKstep ) // k-step unique-state induction { if ( Aig_ManCiNum(p->pInterNew) == Aig_ManCiNum(p->pInter) ) { if ( pPars->fTransLoop || pPars->fUseBackward || pPars->nFramesK > 1 ) { clk2 = Abc_Clock(); Status = Inter_ManCheckInductiveContainment( p->pAigTrans, p->pInterNew, Abc_MinInt(i + 1, pPars->nFramesK), pPars->fUseBackward ); timeTemp = Abc_Clock() - clk2; } else { // new containment check clk2 = Abc_Clock(); pCnfInter2 = Cnf_Derive( p->pInterNew, 1 ); p->timeCnf += Abc_Clock() - clk2; timeTemp = Abc_Clock() - clk2; Status = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut ); Cnf_DataFree( pCnfInter2 ); if ( p->vInters ) Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInterNew) ); } } else Status = 0; } else // combinational containment { if ( Aig_ManCiNum(p->pInterNew) == Aig_ManCiNum(p->pInter) ) Status = Inter_ManCheckContainment( p->pInterNew, p->pInter ); else Status = 0; } p->timeEqu += Abc_Clock() - clk - timeTemp; if ( Status ) // contained { if ( pPars->fVerbose ) printf( "Proved containment of interpolants.\n" ); p->timeTotal = Abc_Clock() - clkTotal; Inter_ManStop( p, 1 ); Inter_CheckStop( pCheck ); return 1; } if ( pPars->nSecLimit && Abc_Clock() > nTimeNewOut ) { printf( "Reached timeout (%d seconds).\n", pPars->nSecLimit ); p->timeTotal = Abc_Clock() - clkTotal; Inter_ManStop( p, 1 ); Inter_CheckStop( pCheck ); return -1; } // save interpolant and convert it into CNF if ( pPars->fTransLoop ) { Aig_ManStop( p->pInter ); p->pInter = p->pInterNew; } else { if ( pPars->fUseBackward ) { p->pInter = Aig_ManCreateMiter( pAigTemp = p->pInter, p->pInterNew, 2 ); Aig_ManStop( pAigTemp ); Aig_ManStop( p->pInterNew ); // compress the interpolant clk = Abc_Clock(); p->pInter = Dar_ManRwsat( pAigTemp = p->pInter, 1, 0 ); Aig_ManStop( pAigTemp ); p->timeRwr += Abc_Clock() - clk; } else // forward with the new containment checking (using only the frontier) { Aig_ManStop( p->pInter ); p->pInter = p->pInterNew; } } p->pInterNew = NULL; Cnf_DataFree( p->pCnfInter ); clk = Abc_Clock(); p->pCnfInter = Cnf_Derive( p->pInter, 0 ); p->timeCnf += Abc_Clock() - clk; } // start containment checking Inter_CheckStop( pCheck ); } assert( 0 ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intCtrex.c000066400000000000000000000126331300674244400237240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intCtrex.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Counter-example generation after disproving the property.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intCtrex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" #include "proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Unroll the circuit the given number of timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManFramesBmc( Aig_Man_t * pAig, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; assert( Saig_ManRegNum(pAig) > 0 ); assert( Saig_ManPoNum(pAig) == 1 ); 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_ManConst0( 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) ); if ( f == nFrames - 1 ) break; // transfer to register outputs Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) pObjLi->pData = Aig_ObjChild0Copy(pObjLi); // transfer to register outputs Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) pObjLo->pData = pObjLi->pData; } // create POs for the output of the last frame pObj = Aig_ManCo( pAig, 0 ); Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pFrames ); return pFrames; } /**Function************************************************************* Synopsis [Run the SAT solver on the unrolled instance.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose ) { int nConfLimit = 1000000; Abc_Cex_t * pCtrex = NULL; Aig_Man_t * pFrames; sat_solver * pSat; Cnf_Dat_t * pCnf; int status; abctime clk = Abc_Clock(); Vec_Int_t * vCiIds; // create timeframes assert( Saig_ManPoNum(pAig) == 1 ); pFrames = Inter_ManFramesBmc( pAig, nFrames ); // derive CNF pCnf = Cnf_Derive( pFrames, 0 ); Cnf_DataTranformPolarity( pCnf, 0 ); vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames ); Aig_ManStop( pFrames ); // convert into SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); Cnf_DataFree( pCnf ); if ( pSat == NULL ) { printf( "Counter-example generation in command \"int\" has failed.\n" ); printf( "Use command \"bmc2\" to produce a valid counter-example.\n" ); Vec_IntFree( vCiIds ); return NULL; } // simplify the problem status = sat_solver_simplify(pSat); if ( status == 0 ) { Vec_IntFree( vCiIds ); sat_solver_delete( pSat ); return NULL; } // solve the miter status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); // if the problem is SAT, get the counterexample if ( status == l_True ) { int i, * pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); pCtrex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), nFrames ); pCtrex->iFrame = nFrames - 1; pCtrex->iPo = 0; for ( i = 0; i < Vec_IntSize(vCiIds); i++ ) if ( pModel[i] ) Abc_InfoSetBit( pCtrex->pData, Saig_ManRegNum(pAig) + i ); ABC_FREE( pModel ); } // free the sat_solver sat_solver_delete( pSat ); Vec_IntFree( vCiIds ); // verify counter-example status = Saig_ManVerifyCex( pAig, pCtrex ); if ( status == 0 ) printf( "Inter_ManGetCounterExample(): Counter-example verification has FAILED.\n" ); // report the results if ( fVerbose ) { ABC_PRT( "Total ctrex generation time", Abc_Clock() - clk ); } return pCtrex; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intDup.c000066400000000000000000000127421300674244400233700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intDup.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Specialized AIG duplication procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create trivial AIG manager for the init state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManStartInitState( int nRegs ) { Aig_Man_t * p; Aig_Obj_t * pRes; Aig_Obj_t ** ppInputs; int i; assert( nRegs > 0 ); ppInputs = ABC_ALLOC( Aig_Obj_t *, nRegs ); p = Aig_ManStart( nRegs ); for ( i = 0; i < nRegs; i++ ) ppInputs[i] = Aig_Not( Aig_ObjCreateCi(p) ); pRes = Aig_Multi( p, ppInputs, nRegs, AIG_OBJ_AND ); Aig_ObjCreateCo( p, pRes ); ABC_FREE( ppInputs ); return p; } /**Function************************************************************* Synopsis [Duplicate the AIG w/o POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( Aig_ManRegNum(p) > 0 ); // 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->nTruePis = p->nTruePis; pNew->nTruePos = Saig_ManConstrNum(p); pNew->nRegs = p->nRegs; // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create constraint outputs Saig_ManForEachPo( p, pObj, i ) { if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) continue; Aig_ObjCreateCo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); } // create register inputs with MUXes Saig_ManForEachLi( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicate the AIG w/o POs and transforms to transit into init state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjLi, * pObjLo; Aig_Obj_t * pCtrl = NULL; // Suppress "might be used uninitialized" int i; assert( Aig_ManRegNum(p) > 0 ); // 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 ) { if ( i == Saig_ManPiNum(p) ) pCtrl = Aig_ObjCreateCi( pNew ); pObj->pData = Aig_ObjCreateCi( pNew ); } // set registers pNew->nRegs = fAddFirstPo? 0 : p->nRegs; pNew->nTruePis = fAddFirstPo? Aig_ManCiNum(p) + 1 : p->nTruePis + 1; pNew->nTruePos = fAddFirstPo + Saig_ManConstrNum(p); // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create constraint outputs Saig_ManForEachPo( p, pObj, i ) { if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) continue; Aig_ObjCreateCo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); } // add the PO if ( fAddFirstPo ) { pObj = Aig_ManCo( p, 0 ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } else { // create register inputs with MUXes Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) { pObj = Aig_Mux( pNew, pCtrl, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); // pObj = Aig_Mux( pNew, pCtrl, Aig_ManConst0(pNew), Aig_ObjChild0Copy(pObjLi) ); Aig_ObjCreateCo( pNew, pObj ); } } Aig_ManCleanup( pNew ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intFrames.c000066400000000000000000000101471300674244400240520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intFrames.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Sequential AIG unrolling for interpolation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intFrames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create timeframes of the manager for interpolation.] Description [The resulting manager is combinational. The primary inputs corresponding to register outputs are ordered first. The only POs of the manager is the property output of the last timeframe.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts, int fUseTwoFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; Aig_Obj_t * pLastPo = NULL; int i, f; assert( Saig_ManRegNum(pAig) > 0 ); assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 ); pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); // create variables for register outputs if ( fAddRegOuts ) { Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_ManConst0( pFrames ); } else { 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) ); // add outputs for constraints Saig_ManForEachPo( pAig, pObj, i ) { if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) ) continue; Aig_ObjCreateCo( pFrames, Aig_Not( Aig_ObjChild0Copy(pObj) ) ); } if ( f == nFrames - 1 ) break; // remember the last PO pObj = Aig_ManCo( pAig, 0 ); pLastPo = 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; } // create POs for each register output if ( fAddRegOuts ) { Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); } // create the only PO of the manager else { pObj = Aig_ManCo( pAig, 0 ); // add the last PO if ( pLastPo == NULL || !fUseTwoFrames ) pLastPo = Aig_ObjChild0Copy(pObj); else pLastPo = Aig_Or( pFrames, pLastPo, Aig_ObjChild0Copy(pObj) ); Aig_ObjCreateCo( pFrames, pLastPo ); } Aig_ManCleanup( pFrames ); return pFrames; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intInt.h000066400000000000000000000132651300674244400234000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__int__intInt_h #define ABC__aig__int__intInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/saig/saig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" #include "sat/bsat/satStore.h" #include "int.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // interpolation manager typedef struct Inter_Man_t_ Inter_Man_t; struct Inter_Man_t_ { // AIG manager Aig_Man_t * pAig; // the original AIG manager Aig_Man_t * pAigTrans; // the transformed original AIG manager Cnf_Dat_t * pCnfAig; // CNF for the original manager // interpolant Aig_Man_t * pInter; // the current interpolant Cnf_Dat_t * pCnfInter; // CNF for the current interplant // timeframes Aig_Man_t * pFrames; // the timeframes Cnf_Dat_t * pCnfFrames; // CNF for the timeframes // other data Vec_Int_t * vVarsAB; // the variables participating in // temporary place for the new interpolant Aig_Man_t * pInterNew; Vec_Ptr_t * vInters; // parameters int nFrames; // the number of timeframes int nConfCur; // the current number of conflicts int nConfLimit; // the limit on the number of conflicts int fVerbose; // the verbosiness flag char * pFileName; // runtime abctime timeRwr; abctime timeCnf; abctime timeSat; abctime timeInt; abctime timeEqu; abctime timeOther; abctime timeTotal; }; // containment checking manager typedef struct Inter_Check_t_ Inter_Check_t; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== intCheck.c ============================================================*/ extern Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK ); extern void Inter_CheckStop( Inter_Check_t * p ); extern int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnf, abctime nTimeNewOut ); /*=== intContain.c ============================================================*/ extern int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld ); extern int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld ); extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward ); /*=== intCtrex.c ============================================================*/ extern void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose ); /*=== intDup.c ============================================================*/ extern Aig_Man_t * Inter_ManStartInitState( int nRegs ); extern Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p ); extern Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo ); /*=== intFrames.c ============================================================*/ extern Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts, int fUseTwoFrames ); /*=== intMan.c ============================================================*/ extern Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars ); extern void Inter_ManClean( Inter_Man_t * p ); extern void Inter_ManStop( Inter_Man_t * p, int fProved ); /*=== intM114.c ============================================================*/ extern int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, abctime nTimeNewOut ); /*=== intM114p.c ============================================================*/ #ifdef ABC_USE_LIBRARIES extern int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther ); #endif /*=== intUtil.c ============================================================*/ extern int Inter_ManCheckInitialState( Aig_Man_t * p ); extern int Inter_ManCheckAllStates( Aig_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intInter.c000066400000000000000000000104701300674244400237150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intInter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Experimental procedures to derive and compare interpolants.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManDupExpand( Aig_Man_t * pInter, Aig_Man_t * pOther ) { Aig_Man_t * pInterC; assert( Aig_ManCiNum(pInter) <= Aig_ManCiNum(pOther) ); pInterC = Aig_ManDupSimple( pInter ); Aig_IthVar( pInterC, Aig_ManCiNum(pOther)-1 ); assert( Aig_ManCiNum(pInterC) == Aig_ManCiNum(pOther) ); return pInterC; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_ManVerifyInterpolant1( Inta_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter ) { extern Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ); Aig_Man_t * pLower, * pUpper, * pInterC; int RetValue1, RetValue2; pLower = Inta_ManDeriveClauses( pMan, pCnf, 1 ); pUpper = Inta_ManDeriveClauses( pMan, pCnf, 0 ); Aig_ManFlipFirstPo( pUpper ); pInterC = Inter_ManDupExpand( pInter, pLower ); RetValue1 = Inter_ManCheckContainment( pLower, pInterC ); Aig_ManStop( pInterC ); pInterC = Inter_ManDupExpand( pInter, pUpper ); RetValue2 = Inter_ManCheckContainment( pInterC, pUpper ); Aig_ManStop( pInterC ); if ( RetValue1 && RetValue2 ) printf( "Im is correct.\n" ); if ( !RetValue1 ) printf( "Property A => Im fails.\n" ); if ( !RetValue2 ) printf( "Property Im => !B fails.\n" ); Aig_ManStop( pLower ); Aig_ManStop( pUpper ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_ManVerifyInterpolant2( Intb_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter ) { extern Aig_Man_t * Intb_ManDeriveClauses( Intb_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ); Aig_Man_t * pLower, * pUpper, * pInterC; int RetValue1, RetValue2; pLower = Intb_ManDeriveClauses( pMan, pCnf, 1 ); pUpper = Intb_ManDeriveClauses( pMan, pCnf, 0 ); Aig_ManFlipFirstPo( pUpper ); pInterC = Inter_ManDupExpand( pInter, pLower ); //Aig_ManPrintStats( pLower ); //Aig_ManPrintStats( pUpper ); //Aig_ManPrintStats( pInterC ); //Aig_ManDumpBlif( pInterC, "inter_c.blif", NULL, NULL ); RetValue1 = Inter_ManCheckContainment( pLower, pInterC ); Aig_ManStop( pInterC ); pInterC = Inter_ManDupExpand( pInter, pUpper ); RetValue2 = Inter_ManCheckContainment( pInterC, pUpper ); Aig_ManStop( pInterC ); if ( RetValue1 && RetValue2 ) printf( "Ip is correct.\n" ); if ( !RetValue1 ) printf( "Property A => Ip fails.\n" ); if ( !RetValue2 ) printf( "Property Ip => !B fails.\n" ); Aig_ManStop( pLower ); Aig_ManStop( pUpper ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intM114.c000066400000000000000000000252101300674244400232540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intM114.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Intepolation using ABC's proof generator added to MiniSat-1.14c.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intM114.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the SAT solver for one interpolation run.] Description [pInter is the previous interpolant. pAig is one time frame. pFrames is the unrolled time frames.] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Inter_ManDeriveSatSolver( Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter, Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig, Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames, Vec_Int_t * vVarsAB, int fUseBackward ) { sat_solver * pSat; Aig_Obj_t * pObj, * pObj2; int i, Lits[2]; //Aig_ManDumpBlif( pInter, "out_inter.blif", NULL, NULL ); //Aig_ManDumpBlif( pAig, "out_aig.blif", NULL, NULL ); //Aig_ManDumpBlif( pFrames, "out_frames.blif", NULL, NULL ); // sanity checks assert( Aig_ManRegNum(pInter) == 0 ); assert( Aig_ManRegNum(pAig) > 0 ); assert( Aig_ManRegNum(pFrames) == 0 ); assert( Aig_ManCoNum(pInter) == 1 ); assert( Aig_ManCoNum(pFrames) == fUseBackward? Saig_ManRegNum(pAig) : 1 ); assert( fUseBackward || Aig_ManCiNum(pInter) == Aig_ManRegNum(pAig) ); // assert( (Aig_ManCiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 ); // prepare CNFs Cnf_DataLift( pCnfAig, pCnfFrames->nVars ); Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars ); // start the solver pSat = sat_solver_new(); sat_solver_store_alloc( pSat ); sat_solver_setnvars( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars ); // add clauses of A // interpolant for ( i = 0; i < pCnfInter->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) ) { sat_solver_delete( pSat ); // return clauses to the original state Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); return NULL; } } // connector clauses if ( fUseBackward ) { Saig_ManForEachLi( pAig, pObj2, i ) { if ( Saig_ManRegNum(pAig) == Aig_ManCiNum(pInter) ) pObj = Aig_ManCi( pInter, i ); else { assert( Aig_ManCiNum(pAig) == Aig_ManCiNum(pInter) ); pObj = Aig_ManCi( pInter, Aig_ManCiNum(pAig)-Saig_ManRegNum(pAig) + i ); } Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); } } else { Aig_ManForEachCi( pInter, pObj, i ) { pObj2 = Saig_ManLo( pAig, i ); Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); } } // one timeframe for ( i = 0; i < pCnfAig->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) ) assert( 0 ); } // connector clauses Vec_IntClear( vVarsAB ); if ( fUseBackward ) { Aig_ManForEachCo( pFrames, pObj, i ) { assert( pCnfFrames->pVarNums[pObj->Id] >= 0 ); Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); pObj2 = Saig_ManLo( pAig, i ); Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); } } else { Aig_ManForEachCi( pFrames, pObj, i ) { if ( i == Aig_ManRegNum(pAig) ) break; Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); pObj2 = Saig_ManLi( pAig, i ); Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); } } // add clauses of B sat_solver_store_mark_clauses_a( pSat ); for ( i = 0; i < pCnfFrames->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) ) { pSat->fSolved = 1; break; } } sat_solver_store_mark_roots( pSat ); // return clauses to the original state Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); return pSat; } /**Function************************************************************* Synopsis [Performs one SAT run with interpolation.] Description [Returns 1 if proven. 0 if failed. -1 if undecided.] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, abctime nTimeNewOut ) { sat_solver * pSat; void * pSatCnf = NULL; Inta_Man_t * pManInterA; // Intb_Man_t * pManInterB; int * pGlobalVars; int status, RetValue; int i, Var; abctime clk; // assert( p->pInterNew == NULL ); // derive the SAT solver pSat = Inter_ManDeriveSatSolver( p->pInter, p->pCnfInter, p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, p->vVarsAB, fUseBackward ); if ( pSat == NULL ) { p->pInterNew = NULL; return 1; } // set runtime limit if ( nTimeNewOut ) sat_solver_set_runtime_limit( pSat, nTimeNewOut ); // collect global variables pGlobalVars = ABC_CALLOC( int, sat_solver_nvars(pSat) ); Vec_IntForEachEntry( p->vVarsAB, Var, i ) pGlobalVars[Var] = 1; pSat->pGlobalVars = fUseBias? pGlobalVars : NULL; // solve the problem clk = Abc_Clock(); status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); p->nConfCur = pSat->stats.conflicts; p->timeSat += Abc_Clock() - clk; pSat->pGlobalVars = NULL; ABC_FREE( pGlobalVars ); if ( status == l_False ) { pSatCnf = sat_solver_store_release( pSat ); RetValue = 1; } else if ( status == l_True ) { RetValue = 0; } else { RetValue = -1; } sat_solver_delete( pSat ); if ( pSatCnf == NULL ) return RetValue; // create the resulting manager clk = Abc_Clock(); /* if ( !fUseIp ) { pManInterA = Inta_ManAlloc(); p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 ); Inta_ManFree( pManInterA ); } else { Aig_Man_t * pInterNew2; int RetValue; pManInterA = Inta_ManAlloc(); p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 ); // Inter_ManVerifyInterpolant1( pManInterA, pSatCnf, p->pInterNew ); Inta_ManFree( pManInterA ); pManInterB = Intb_ManAlloc(); pInterNew2 = Intb_ManInterpolate( pManInterB, pSatCnf, p->vVarsAB, 0 ); Inter_ManVerifyInterpolant2( pManInterB, pSatCnf, pInterNew2 ); Intb_ManFree( pManInterB ); // check relationship RetValue = Inter_ManCheckEquivalence( pInterNew2, p->pInterNew ); if ( RetValue ) printf( "Equivalence \"Ip == Im\" holds\n" ); else { // printf( "Equivalence \"Ip == Im\" does not hold\n" ); RetValue = Inter_ManCheckContainment( pInterNew2, p->pInterNew ); if ( RetValue ) printf( "Containment \"Ip -> Im\" holds\n" ); else printf( "Containment \"Ip -> Im\" does not hold\n" ); RetValue = Inter_ManCheckContainment( p->pInterNew, pInterNew2 ); if ( RetValue ) printf( "Containment \"Im -> Ip\" holds\n" ); else printf( "Containment \"Im -> Ip\" does not hold\n" ); } Aig_ManStop( pInterNew2 ); } */ pManInterA = Inta_ManAlloc(); p->pInterNew = (Aig_Man_t *)Inta_ManInterpolate( pManInterA, (Sto_Man_t *)pSatCnf, nTimeNewOut, p->vVarsAB, 0 ); Inta_ManFree( pManInterA ); p->timeInt += Abc_Clock() - clk; Sto_ManFree( (Sto_Man_t *)pSatCnf ); if ( p->pInterNew == NULL ) RetValue = -1; return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intM114p.c000066400000000000000000000352021300674244400234360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intM114p.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Intepolation using interfaced to MiniSat-1.14p.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intM114p.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" #include "sat/psat/m114p.h" #ifdef ABC_USE_LIBRARIES ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the SAT solver for one interpolation run.] Description [pInter is the previous interpolant. pAig is one time frame. pFrames is the unrolled time frames.] SideEffects [] SeeAlso [] ***********************************************************************/ M114p_Solver_t Inter_ManDeriveSatSolverM114p( Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter, Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig, Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames, Vec_Int_t ** pvMapRoots, Vec_Int_t ** pvMapVars ) { M114p_Solver_t pSat; Aig_Obj_t * pObj, * pObj2; int i, Lits[2]; // sanity checks assert( Aig_ManRegNum(pInter) == 0 ); assert( Aig_ManRegNum(pAig) > 0 ); assert( Aig_ManRegNum(pFrames) == 0 ); assert( Aig_ManCoNum(pInter) == 1 ); assert( Aig_ManCoNum(pFrames) == 1 ); assert( Aig_ManCiNum(pInter) == Aig_ManRegNum(pAig) ); // assert( (Aig_ManCiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 ); // prepare CNFs Cnf_DataLift( pCnfAig, pCnfFrames->nVars ); Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars ); *pvMapRoots = Vec_IntAlloc( 10000 ); *pvMapVars = Vec_IntAlloc( 0 ); Vec_IntFill( *pvMapVars, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars, -1 ); for ( i = 0; i < pCnfFrames->nVars; i++ ) Vec_IntWriteEntry( *pvMapVars, i, -2 ); // start the solver pSat = M114p_SolverNew( 1 ); M114p_SolverSetVarNum( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars ); // add clauses of A // interpolant for ( i = 0; i < pCnfInter->nClauses; i++ ) { Vec_IntPush( *pvMapRoots, 0 ); if ( !M114p_SolverAddClause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) ) assert( 0 ); } // connector clauses Aig_ManForEachCi( pInter, pObj, i ) { pObj2 = Saig_ManLo( pAig, i ); Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); Vec_IntPush( *pvMapRoots, 0 ); if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); Vec_IntPush( *pvMapRoots, 0 ); if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) assert( 0 ); } // one timeframe for ( i = 0; i < pCnfAig->nClauses; i++ ) { Vec_IntPush( *pvMapRoots, 0 ); if ( !M114p_SolverAddClause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) ) assert( 0 ); } // connector clauses Aig_ManForEachCi( pFrames, pObj, i ) { if ( i == Aig_ManRegNum(pAig) ) break; // Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] ); Vec_IntWriteEntry( *pvMapVars, pCnfFrames->pVarNums[pObj->Id], i ); pObj2 = Saig_ManLi( pAig, i ); Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 ); Vec_IntPush( *pvMapRoots, 0 ); if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 ); Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 ); Vec_IntPush( *pvMapRoots, 0 ); if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) ) assert( 0 ); } // add clauses of B for ( i = 0; i < pCnfFrames->nClauses; i++ ) { Vec_IntPush( *pvMapRoots, 1 ); if ( !M114p_SolverAddClause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) ) { // assert( 0 ); break; } } // return clauses to the original state Cnf_DataLift( pCnfAig, -pCnfFrames->nVars ); Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars ); return pSat; } /**Function************************************************************* Synopsis [Performs one resolution step.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManResolveM114p( Vec_Int_t * vResolvent, int * pLits, int nLits, int iVar ) { int i, k, iLit = -1, fFound = 0; // find the variable in the clause for ( i = 0; i < vResolvent->nSize; i++ ) if ( lit_var(vResolvent->pArray[i]) == iVar ) { iLit = vResolvent->pArray[i]; vResolvent->pArray[i] = vResolvent->pArray[--vResolvent->nSize]; break; } assert( iLit != -1 ); // add other variables for ( i = 0; i < nLits; i++ ) { if ( lit_var(pLits[i]) == iVar ) { assert( iLit == lit_neg(pLits[i]) ); fFound = 1; continue; } // check if this literal appears for ( k = 0; k < vResolvent->nSize; k++ ) if ( vResolvent->pArray[k] == pLits[i] ) break; if ( k < vResolvent->nSize ) continue; // add this literal Vec_IntPush( vResolvent, pLits[i] ); } assert( fFound ); return 1; } /**Function************************************************************* Synopsis [Computes interpolant using MiniSat-1.14p.] Description [Assumes that the solver returned UNSAT and proof logging was enabled. Array vMapRoots maps number of each root clause into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT solver variable into -1 (var of A), -2 (var of B), and (var of C), where is the var's 0-based number in the ordering of C variables.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManInterpolateM114pPudlak( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars ) { Aig_Man_t * p; Aig_Obj_t * pInter, * pInter2, * pVar; Vec_Ptr_t * vInters; Vec_Int_t * vLiterals, * vClauses, * vResolvent; int * pLitsNext, nLitsNext, nOffset, iLit; int * pLits, * pClauses, * pVars; int nLits, nVars, i, k, v, iVar; assert( M114p_SolverProofIsReady(s) ); vInters = Vec_PtrAlloc( 1000 ); vLiterals = Vec_IntAlloc( 10000 ); vClauses = Vec_IntAlloc( 1000 ); vResolvent = Vec_IntAlloc( 100 ); // create elementary variables p = Aig_ManStart( 10000 ); Vec_IntForEachEntry( vMapVars, iVar, i ) if ( iVar >= 0 ) Aig_IthVar(p, iVar); // process root clauses M114p_SolverForEachRoot( s, &pLits, nLits, i ) { if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B pInter = Aig_ManConst1(p); else // clause of A pInter = Aig_ManConst0(p); Vec_PtrPush( vInters, pInter ); // save the root clause Vec_IntPush( vClauses, Vec_IntSize(vLiterals) ); Vec_IntPush( vLiterals, nLits ); for ( v = 0; v < nLits; v++ ) Vec_IntPush( vLiterals, pLits[v] ); } assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) ); // process learned clauses M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i ) { pInter = Vec_PtrEntry( vInters, pClauses[0] ); // initialize the resolvent nOffset = Vec_IntEntry( vClauses, pClauses[0] ); nLitsNext = Vec_IntEntry( vLiterals, nOffset ); pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1; Vec_IntClear( vResolvent ); for ( v = 0; v < nLitsNext; v++ ) Vec_IntPush( vResolvent, pLitsNext[v] ); for ( k = 0; k < nVars; k++ ) { iVar = Vec_IntEntry( vMapVars, pVars[k] ); pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] ); // resolve it with the next clause nOffset = Vec_IntEntry( vClauses, pClauses[k+1] ); nLitsNext = Vec_IntEntry( vLiterals, nOffset ); pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1; Inter_ManResolveM114p( vResolvent, pLitsNext, nLitsNext, pVars[k] ); if ( iVar == -1 ) // var of A pInter = Aig_Or( p, pInter, pInter2 ); else if ( iVar == -2 ) // var of B pInter = Aig_And( p, pInter, pInter2 ); else // var of C { // check polarity of the pivot variable in the clause for ( v = 0; v < nLitsNext; v++ ) if ( lit_var(pLitsNext[v]) == pVars[k] ) break; assert( v < nLitsNext ); pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLitsNext[v]) ); pInter = Aig_Mux( p, pVar, pInter, pInter2 ); } } Vec_PtrPush( vInters, pInter ); // store the resulting clause Vec_IntPush( vClauses, Vec_IntSize(vLiterals) ); Vec_IntPush( vLiterals, Vec_IntSize(vResolvent) ); Vec_IntForEachEntry( vResolvent, iLit, v ) Vec_IntPush( vLiterals, iLit ); } assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) ); assert( Vec_IntSize(vResolvent) == 0 ); // the empty clause Vec_PtrFree( vInters ); Vec_IntFree( vLiterals ); Vec_IntFree( vClauses ); Vec_IntFree( vResolvent ); Aig_ObjCreateCo( p, pInter ); Aig_ManCleanup( p ); return p; } /**Function************************************************************* Synopsis [Computes interpolant using MiniSat-1.14p.] Description [Assumes that the solver returned UNSAT and proof logging was enabled. Array vMapRoots maps number of each root clause into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT solver variable into -1 (var of A), -2 (var of B), and (var of C), where is the var's 0-based number in the ordering of C variables.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inter_ManpInterpolateM114( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars ) { Aig_Man_t * p; Aig_Obj_t * pInter, * pInter2, * pVar; Vec_Ptr_t * vInters; int * pLits, * pClauses, * pVars; int nLits, nVars, i, k, iVar; int nClauses; nClauses = M114p_SolverProofClauseNum(s); assert( M114p_SolverProofIsReady(s) ); vInters = Vec_PtrAlloc( 1000 ); // process root clauses p = Aig_ManStart( 10000 ); M114p_SolverForEachRoot( s, &pLits, nLits, i ) { if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B pInter = Aig_ManConst1(p); else // clause of A { pInter = Aig_ManConst0(p); for ( k = 0; k < nLits; k++ ) { iVar = Vec_IntEntry( vMapVars, lit_var(pLits[k]) ); if ( iVar < 0 ) // var of A or B continue; // this is a variable of C pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLits[k]) ); pInter = Aig_Or( p, pInter, pVar ); } } Vec_PtrPush( vInters, pInter ); } // assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) ); // process learned clauses M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i ) { pInter = Vec_PtrEntry( vInters, pClauses[0] ); for ( k = 0; k < nVars; k++ ) { iVar = Vec_IntEntry( vMapVars, pVars[k] ); pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] ); if ( iVar == -1 ) // var of A pInter = Aig_Or( p, pInter, pInter2 ); else // var of B or C pInter = Aig_And( p, pInter, pInter2 ); } Vec_PtrPush( vInters, pInter ); } assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) ); Vec_PtrFree( vInters ); Aig_ObjCreateCo( p, pInter ); Aig_ManCleanup( p ); assert( Aig_ManCheck(p) ); return p; } /**Function************************************************************* Synopsis [Performs one SAT run with interpolation.] Description [Returns 1 if proven. 0 if failed. -1 if undecided.] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther ) { M114p_Solver_t pSat; Vec_Int_t * vMapRoots, * vMapVars; clock_t clk; int status, RetValue; assert( p->pInterNew == NULL ); // derive the SAT solver pSat = Inter_ManDeriveSatSolverM114p( p->pInter, p->pCnfInter, p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, &vMapRoots, &vMapVars ); // solve the problem clk = clock(); status = M114p_SolverSolve( pSat, NULL, NULL, 0 ); p->nConfCur = M114p_SolverGetConflictNum( pSat ); p->timeSat += clock() - clk; if ( status == 0 ) { RetValue = 1; // Inter_ManpInterpolateM114Report( pSat, vMapRoots, vMapVars ); clk = clock(); if ( fUsePudlak ) p->pInterNew = Inter_ManInterpolateM114pPudlak( pSat, vMapRoots, vMapVars ); else p->pInterNew = Inter_ManpInterpolateM114( pSat, vMapRoots, vMapVars ); p->timeInt += clock() - clk; } else if ( status == 1 ) { RetValue = 0; } else { RetValue = -1; } M114p_SolverDelete( pSat ); Vec_IntFree( vMapRoots ); Vec_IntFree( vMapVars ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END #endif berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intMan.c000066400000000000000000000112721300674244400233500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Interpolation manager procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" #include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the interpolation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars ) { Inter_Man_t * p; // create interpolation manager p = ABC_ALLOC( Inter_Man_t, 1 ); memset( p, 0, sizeof(Inter_Man_t) ); p->vVarsAB = Vec_IntAlloc( Aig_ManRegNum(pAig) ); p->nConfLimit = pPars->nBTLimit; p->fVerbose = pPars->fVerbose; p->pFileName = pPars->pFileName; p->pAig = pAig; if ( pPars->fDropInvar ) p->vInters = Vec_PtrAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [Cleans the interpolation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_ManClean( Inter_Man_t * p ) { if ( p->vInters ) { Aig_Man_t * pMan; int i; Vec_PtrForEachEntry( Aig_Man_t *, p->vInters, pMan, i ) Aig_ManStop( pMan ); Vec_PtrClear( p->vInters ); } if ( p->pCnfInter ) Cnf_DataFree( p->pCnfInter ); if ( p->pCnfFrames ) Cnf_DataFree( p->pCnfFrames ); if ( p->pInter ) Aig_ManStop( p->pInter ); if ( p->pFrames ) Aig_ManStop( p->pFrames ); } /**Function************************************************************* Synopsis [Writes interpolant into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_ManInterDump( Inter_Man_t * p, int fProved ) { char * pFileName = p->pFileName ? p->pFileName : (char *)"invar.aig"; Aig_Man_t * pMan; pMan = Aig_ManDupArray( p->vInters ); Ioa_WriteAiger( pMan, pFileName, 0, 0 ); Aig_ManStop( pMan ); if ( fProved ) printf( "Inductive invariant is dumped into file \"%s\".\n", pFileName ); else printf( "Interpolants are dumped into file \"%s\".\n", pFileName ); } /**Function************************************************************* Synopsis [Frees the interpolation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inter_ManStop( Inter_Man_t * p, int fProved ) { if ( p->fVerbose ) { p->timeOther = p->timeTotal-p->timeRwr-p->timeCnf-p->timeSat-p->timeInt-p->timeEqu; printf( "Runtime statistics:\n" ); ABC_PRTP( "Rewriting ", p->timeRwr, p->timeTotal ); ABC_PRTP( "CNF mapping", p->timeCnf, p->timeTotal ); ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); ABC_PRTP( "Interpol ", p->timeInt, p->timeTotal ); ABC_PRTP( "Containment", p->timeEqu, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); } if ( p->vInters ) Inter_ManInterDump( p, fProved ); if ( p->pCnfAig ) Cnf_DataFree( p->pCnfAig ); if ( p->pAigTrans ) Aig_ManStop( p->pAigTrans ); if ( p->pInterNew ) Aig_ManStop( p->pInterNew ); Inter_ManClean( p ); Vec_PtrFreeP( &p->vInters ); Vec_IntFreeP( &p->vVarsAB ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/intUtil.c000066400000000000000000000063251300674244400235550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [intUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Various interpolation utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 24, 2008.] Revision [$Id: intUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "intInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if the property fails in the initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManCheckInitialState( Aig_Man_t * p ) { Cnf_Dat_t * pCnf; Aig_Obj_t * pObj; sat_solver * pSat; int i, status; //abctime clk = Abc_Clock(); pCnf = Cnf_Derive( p, Saig_ManRegNum(p) ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 1 ); if ( pSat == NULL ) { Cnf_DataFree( pCnf ); return 0; } status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); //ABC_PRT( "Time", Abc_Clock() - clk ); if ( status == l_True ) { p->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(p), Saig_ManPiNum(p), 1 ); Saig_ManForEachPi( p, pObj, i ) if ( sat_solver_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pObj)] ) ) Abc_InfoSetBit( p->pSeqModel->pData, Aig_ManRegNum(p) + i ); } Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); return status == l_True; } /**Function************************************************************* Synopsis [Returns 1 if the property holds in all states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inter_ManCheckAllStates( Aig_Man_t * p ) { Cnf_Dat_t * pCnf; sat_solver * pSat; int status; abctime clk = Abc_Clock(); pCnf = Cnf_Derive( p, Saig_ManRegNum(p) ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); Cnf_DataFree( pCnf ); if ( pSat == NULL ) return 1; status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); sat_solver_delete( pSat ); ABC_PRT( "Time", Abc_Clock() - clk ); return status == l_False; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int/module.make000066400000000000000000000004301300674244400240740ustar00rootroot00000000000000SRC += src/proof/int/intCheck.c \ src/proof/int/intContain.c \ src/proof/int/intCore.c \ src/proof/int/intCtrex.c \ src/proof/int/intDup.c \ src/proof/int/intFrames.c \ src/proof/int/intInter.c \ src/proof/int/intM114.c \ src/proof/int/intMan.c \ src/proof/int/intUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int2/000077500000000000000000000000001300674244400220355ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int2/int2.h000066400000000000000000000063251300674244400230700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [int2.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 1, 2013.] Revision [$Id: int2.h,v 1.00 2013/12/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__int2__int_h #define ABC__aig__int2__int_h /* The interpolation algorithm implemented here was introduced in the papers: K. L. McMillan. Interpolation and SAT-based model checking. CAV’03, pp. 1-13. C.-Y. Wu et al. A CEX-Guided Interpolant Generation Algorithm for SAT-based Model Checking. DAC'13. */ //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // simulation manager typedef struct Int2_ManPars_t_ Int2_ManPars_t; struct Int2_ManPars_t_ { int nBTLimit; // limit on the number of conflicts int nFramesS; // the starting number timeframes int nFramesMax; // the max number timeframes to unroll int nSecLimit; // time limit in seconds int nFramesK; // the number of timeframes to use in induction int fRewrite; // use additional rewriting to simplify timeframes int fTransLoop; // add transition into the init state under new PI var int fDropInvar; // dump inductive invariant into file int fVerbose; // print verbose statistics int iFrameMax; // the time frame reached char * pFileName; // file name to dump interpolant }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== intCore.c ==========================================================*/ extern void Int2_ManSetDefaultParams( Int2_ManPars_t * p ); extern int Int2_ManPerformInterpolation( Gia_Man_t * p, Int2_ManPars_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int2/int2Bmc.c000066400000000000000000000304151300674244400235020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [int2Bmc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [BMC used inside IMC.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 1, 2013.] Revision [$Id: int2Bmc.c,v 1.00 2013/12/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "int2Int.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Trasnforms AIG to transition into the init state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Int2_ManDupInit( Gia_Man_t * p, int fVerbose ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, iCtrl; assert( Gia_ManRegNum(p) > 0 ); pNew = Gia_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) { if ( i == Gia_ManPiNum(p) ) iCtrl = Gia_ManAppendCi( pNew ); pObj->Value = Gia_ManAppendCi( pNew ); } Gia_ManHashAlloc( 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) ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) Gia_ManAppendCo( pNew, Gia_ManHashMux( pNew, iCtrl, pObjRo->Value, Gia_ObjFanin0Copy(pObjRi) ) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // remove dangling pNew = Gia_ManCleanup( pTemp = pNew ); if ( fVerbose ) printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(pNew) ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Returns 1 if AIG has transition into init state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Int2_ManCheckInit( Gia_Man_t * p ) { sat_solver * pSat; Cnf_Dat_t * pCnf; Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vLits; int i, Lit, RetValue = 0; assert( Gia_ManRegNum(p) > 0 ); pNew = Jf_ManDeriveCnf( p, 0 ); pCnf = (Cnf_Dat_t *)pNew->pData; pNew->pData = NULL; pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat != NULL ) { vLits = Vec_IntAlloc( Gia_ManRegNum(p) ); Gia_ManForEachRi( pNew, pObj, i ) { Lit = pCnf->pVarNums[ Gia_ObjId(pNew, Gia_ObjFanin0(pObj)) ]; Lit = Abc_Var2Lit( Lit, Gia_ObjFaninC0(pObj) ); Vec_IntPush( vLits, Abc_LitNot(Lit) ); } if ( sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ) == l_True ) RetValue = 1; Vec_IntFree( vLits ); sat_solver_delete( pSat ); } Cnf_DataFree( pCnf ); Gia_ManStop( pNew ); return RetValue; } /**Function************************************************************* Synopsis [Creates the BMC instance in the SAT solver.] Description [The PIs are mapped in the natural order. The flop inputs are the last Gia_ManRegNum(p) variables of resulting SAT solver.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Int2_ManFrameInit( Gia_Man_t * p, int nFrames, int fVerbose ) { Gia_Man_t * pFrames, * pTemp; Gia_Obj_t * pObj; int i, f; pFrames = Gia_ManStart( 10000 ); pFrames->pName = Abc_UtilStrsav( p->pName ); pFrames->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; // perform structural hashing Gia_ManHashAlloc( pFrames ); for ( f = 0; f < nFrames; f++ ) { Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pFrames ); Gia_ManForEachRo( p, pObj, i ) pObj->Value = f ? Gia_ObjRoToRi(p, pObj)->Value : 0; 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_ManHashStop( pFrames ); // create flop inputs Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); // remove dangling 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; } sat_solver * Int2_ManSetupBmcSolver( Gia_Man_t * p, int nFrames ) { Gia_Man_t * pFrames, * pTemp; Cnf_Dat_t * pCnf; sat_solver * pSat; // unfold for the given number of timeframes pFrames = Int2_ManFrameInit( p, nFrames, 1 ); assert( Gia_ManRegNum(pFrames) == 0 ); // derive CNF for the timeframes pFrames = Jf_ManDeriveCnf( pTemp = pFrames, 0 ); Gia_ManStop( pTemp ); pCnf = (Cnf_Dat_t *)pFrames->pData; pFrames->pData = NULL; // create SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat != NULL ) { Gia_Obj_t * pObj; int i, nVars = sat_solver_nvars( pSat ); sat_solver_setnvars( pSat, nVars + Gia_ManPoNum(pFrames) ); // add clauses for the POs Gia_ManForEachCo( pFrames, pObj, i ) sat_solver_add_buffer( pSat, nVars + i, pCnf->pVarNums[Gia_ObjId(pFrames, Gia_ObjFanin0(pObj))], Gia_ObjFaninC0(pObj) ); } Cnf_DataFree( pCnf ); Gia_ManStop( pFrames ); return pSat; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Int2_ManCheckFrames( Int2_Man_t * p, int iFrame, int iObj ) { Vec_Int_t * vMapFrame = (Vec_Int_t *)Vec_PtrEntry(p->vMapFrames, iFrame); return Vec_IntEntry(vMapFrame, iObj); } static inline void Int2_ManWriteFrames( Int2_Man_t * p, int iFrame, int iObj, int iRes ) { Vec_Int_t * vMapFrame = (Vec_Int_t *)Vec_PtrEntry(p->vMapFrames, iFrame); assert( Vec_IntEntry(vMapFrame, iObj) == -1 ); Vec_IntWriteEntry( vMapFrame, iObj, iRes ); } void Int2_ManCreateFrames( Int2_Man_t * p, int iFrame, Vec_Int_t * vPrefCos ) { Gia_Obj_t * pObj; int i, Entry, iLit; // create storage room for unfolded IDs for ( i = Vec_PtrSize(p->vMapFrames); i <= iFrame; i++ ) Vec_PtrPush( p->vMapFrames, Vec_IntStartFull( Gia_ManObjNum(p->pGia) ) ); assert( Vec_PtrSize(p->vMapFrames) == iFrame + 1 ); // create constant 0 node if ( f == 0 ) { iLit = 1; Int2_ManWriteFrames( p, iFrame, iObj, 0 ); sat_solver_addclause( p->pGiaPref, &iLit, &iLit + 1 ); } // start the stack Vec_IntClear( p->vStack ); Vec_IntForEachEntry( vPrefCos, Entry, i ) { pObj = Gia_ManCo( p->pGia, Entry ); Vec_IntPush( p->vStack, iFrame ); Vec_IntPush( p->vStack, Gia_ObjId(p->pGia, pObj) ); } // construct unfolded AIG while ( Vec_IntSize(p->vStack) > 0 ) { int iObj = Vec_IntPop(p->vStack); int iFrame = Vec_IntPop(p->vStack); if ( Int2_ManCheckFrames(p, iFrame, iObj) >= 0 ) continue; pObj = Gia_ManObj( p->pGia, iObj ); if ( Gia_ObjIsPi(p->pGia, pObj) ) Int2_ManWriteFrames( p, iFrame, iObj, Gia_ManAppendCi(p->pFrames) ); else if ( iFrame == 0 && Gia_ObjIsRo(p->pGia, iObj) ) Int2_ManWriteFrames( p, iFrame, iObj, 0 ); else if ( Gia_ObjIsRo(p->pGia, iObj) ) { int iObjF = Gia_ObjId( p->pGia, Gia_ObjRoToRi(p->pGia, pObj) ); int iLit = Int2_ManCheckFrames( p, iFrame-1, iObjF ); if ( iLit >= 0 ) Int2_ManWriteFrames( p, iFrame, iObj, iLit ); else { Vec_IntPush( p->vStack, iFrame ); Vec_IntPush( p->vStack, iObj ); Vec_IntPush( p->vStack, iFrame-1 ); Vec_IntPush( p->vStack, iObjF ); } } else if ( Gia_ObjIsCo(pObj) ) { int iObjF = Gia_ObjFaninId0(p->pGia, iObj) ); int iLit = Int2_ManCheckFrames( p, iFrame, iObjF ); if ( iLit >= 0 ) Int2_ManWriteFrames( p, iFrame, iObj, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); else { Vec_IntPush( p->vStack, iFrame ); Vec_IntPush( p->vStack, iObj ); Vec_IntPush( p->vStack, iFrame ); Vec_IntPush( p->vStack, iObjF ); } } else if ( Gia_ObjIsAnd(pObj) ) { int iObjF0 = Gia_ObjFaninId0(p->pGia, iObj) ); int iLit0 = Int2_ManCheckFrames( p, iFrame, iObjF0 ); int iObjF1 = Gia_ObjFaninId1(p->pGia, iObj) ); int iLit1 = Int2_ManCheckFrames( p, iFrame, iObjF1 ); if ( iLit0 >= 0 && iLit1 >= 0 ) { Entry = Gia_ManObjNum(pFrames); iLit = Gia_ManHashAnd(pFrames, iLit0, iLit1); Int2_ManWriteFrames( p, iFrame, iObj, iLit ); if ( Entry < Gia_ManObjNum(pFrames) ) { assert( !Abc_LitIsCompl(iLit) ); sat_solver_add_and( p->pGiaPref, Abc_Lit2Var(iLit), Abc_Lit2Var(iLit0), Abc_Lit2Var(iLit1), Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1), 0 ); } } else { Vec_IntPush( p->vStack, iFrame ); Vec_IntPush( p->vStack, iObj ); if ( iLit0 < 0 ) { Vec_IntPush( p->vStack, iFrame ); Vec_IntPush( p->vStack, iObjF0 ); } if ( iLit1 < 0 ) { Vec_IntPush( p->vStack, iFrame ); Vec_IntPush( p->vStack, iObjF1 ); } } } else assert( 0 ); } } int Int2_ManCheckBmc( Int2_Man_t * p, Vec_Int_t * vCube ) { int status; if ( vCube == NULL ) { Gia_Obj_t * pObj; int i, iLit; Gia_ManForEachPo( p->pGia, pObj, i ) { iLit = Int2_ManCheckFrames( p, 0, Gia_ObjId(p->pGia, pObj) ); if ( iLit == 0 ) continue; if ( iLit == 1 ) return 0; status = sat_solver_solve( p->pSatPref, &iLit, &iLit + 1, 0, 0, 0, 0 ); if ( status == l_False ) continue; if ( status == l_True ) return 0; return -1; } return 1; } status = sat_solver_solve( p->pSatPref, Vec_IntArray(vCube), Vec_IntArray(vCube) + Vec_IntSize(vCube), 0, 0, 0, 0 ); if ( status == l_False ) return 1; if ( status == l_True ) return 0; return -1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int2/int2Core.c000066400000000000000000000263201300674244400236710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [int2Core.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 1, 2013.] Revision [$Id: int2Core.c,v 1.00 2013/12/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "int2Int.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default values of interpolation parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int2_ManSetDefaultParams( Int2_ManPars_t * p ) { memset( p, 0, sizeof(Int2_ManPars_t) ); p->nBTLimit = 0; // limit on the number of conflicts p->nFramesS = 1; // the starting number timeframes p->nFramesMax = 0; // the max number timeframes to unroll p->nSecLimit = 0; // time limit in seconds p->nFramesK = 1; // the number of timeframes to use in induction p->fRewrite = 0; // use additional rewriting to simplify timeframes p->fTransLoop = 0; // add transition into the init state under new PI var p->fDropInvar = 0; // dump inductive invariant into file p->fVerbose = 0; // print verbose statistics p->iFrameMax = -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Int2_ManUnroll( Gia_Man_t * p, int nFrames ) { Gia_Man_t * pFrames, * pTemp; Gia_Obj_t * pObj; int i, f; assert( Gia_ManRegNum(pAig) > 0 ); 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; f < nFrames; f++ ) { 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_ManForEachRi( pAig, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); } Gia_ManForEachRi( pAig, pObj, i ) Gia_ManAppendCo( pFrames, pObj->Value ); Gia_ManHashStop( pFrames ); pFrames = Gia_ManCleanup( pTemp = pFrames ); Gia_ManStop( pTemp ); return pFrames; } sat_solver * Int2_ManPreparePrefix( Gia_Man_t * p, int f, Vec_Int_t ** pvCiMap ) { Gia_Man_t * pPref, * pNew; sat_solver * pSat; // create subset of the timeframe pPref = Int2_ManUnroll( p, f ); // create SAT solver pNew = Jf_ManDeriveCnf( pPref, 0 ); pCnf = (Cnf_Dat_t *)pPref->pData; pPref->pData = NULL; Gia_ManStop( pPref ); // derive the SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // collect indexes of CO variables *pvCiMap = Vec_IntAlloc( 100 ); Gia_ManForEachPo( pNew, pObj, i ) Vec_IntPush( *pvCiMap, pCnf->pVarNums[ Gia_ObjId(pNew, pObj) ] ); // cleanup Cnf_DataFree( pCnf ); Gia_ManStop( pNew ); return pSat; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Int2_ManPrepareSuffix( Gia_Man_t * p, Vec_Int_t * vImageOne, Vec_Int_t * vImagesAll, Vec_Int_t ** pvCoMap, Gia_Man_t ** ppSuff ) { Gia_Man_t * pSuff, * pNew; Gia_Obj_t * pObj; Cnf_Dat_t * pCnf; sat_solver * pSat; Vec_Int_t * vLits; int i, Lit, Limit; // create subset of the timeframe pSuff = Int2_ManProbToGia( p, vImageOne ); assert( Gia_ManPiNum(pSuff) == Gia_ManCiNum(p) ); // create SAT solver pNew = Jf_ManDeriveCnf( pSuff, 0 ); pCnf = (Cnf_Dat_t *)pSuff->pData; pSuff->pData = NULL; Gia_ManStop( pSuff ); // derive the SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // create new constraints vLits = Vec_IntAlloc( 1000 ); Vec_IntForEachEntryStart( vImagesAll, Limit, i, 1 ) { Vec_IntClear( vLits ); for ( k = 0; k < Limit; k++ ) { i++; Lit = Vec_IntEntry( vSop, i + k ); Vec_IntPush( vLits, Abc_LitNot(Lit) ); } if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) // UNSAT { Vec_IntFree( vLits ); Cnf_DataFree( pCnf ); Gia_ManStop( pNew ); *pvCoMap = NULL; return NULL; } } Vec_IntFree( vLits ); // collect indexes of CO variables *pvCoMap = Vec_IntAlloc( 100 ); Gia_ManForEachRo( p, pObj, i ) { pObj = Gia_ManPi( pNew, i + Gia_ManPiNum(p) ); Vec_IntPush( *pvCoMap, pCnf->pVarNums[ Gia_ObjId(pNew, pObj) ] ); } // cleanup Cnf_DataFree( pCnf ); if ( ppSuff ) *ppSuff = pNew; else Gia_ManStop( pNew ); return pSat; } /**Function************************************************************* Synopsis [Returns the cube cover and status.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Int2_ManComputePreimage( Gia_Man_t * pSuff, sat_solver * pSatPref, sat_solver * pSatSuff, Vec_Int_t * vCiMap, Vec_Int_t * vCoMap, Vec_Int_t * vPrio ) { int i, iVar, status; Vec_IntClear( p->vImage ); while ( 1 ) { // run suffix solver status = sat_solver_solve( p->pSatSuff, NULL, NULL, 0, 0, 0, 0 ); if ( status == l_Undef ) return NULL; // timeout if ( status == l_False ) return INT2_COMPUTED; assert( status == l_True ); // collect assignment Vec_IntClear( p->vAssign ); Vec_IntForEachEntry( p->vCiMap, iVar, i ) Vec_IntPush( p->vAssign, sat_solver_var_value(p->pSatSuff, iVar) ); // derive initial cube vCube = Int2_ManRefineCube( p->pSuff, p->vAssign, p->vPrio ); // expend the cube using prefix status = sat_solver_solve( p->pSatPref, Vec_IntArray(vCube), Vec_IntArray(vCube) + Vec_IntSize(vCube), 0, 0, 0, 0 ); if ( status == l_False ) { int k, nCoreLits, * pCoreLits; nCoreLits = sat_solver_final( p->pSatPref, &pCoreLits ); // create cube Vec_IntClear( vCube ); Vec_IntPush( vImage, nCoreLits ); for ( k = 0; k < nCoreLits; k++ ) { Vec_IntPush( vCube, pCoreLits[k] ); Vec_IntPush( vImage, pCoreLits[k] ); } // add cube to the solver if ( !sat_solver_addclause( p->pSatSuff, Vec_IntArray(vCube), Vec_IntArray(vCube) + Vec_IntSize(vCube) ) ) { Vec_IntFree( vCube ); return INT2_COMPUTED; } } Vec_IntFree( vCube ); if ( status == l_Undef ) return INT2_TIME_OUT; if ( status == l_True ) return INT2_FALSE_NEG; assert( status == l_False ); continue; } return p->vImage; } /**Function************************************************************* Synopsis [Interpolates while the number of conflicts is not exceeded.] Description [Returns 1 if proven. 0 if failed. -1 if undecided.] SideEffects [Does not check the property in 0-th frame.] SeeAlso [] ***********************************************************************/ int Int2_ManPerformInterpolation( Gia_Man_t * pInit, Int2_ManPars_t * pPars ) { Int2_Man_t * p; int f, i, RetValue = -1; abctime clk, clkTotal = Abc_Clock(), timeTemp = 0; abctime nTimeToStop = pPars->nSecLimit ? pPars->nSecLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; // sanity checks assert( Gia_ManPiNum(pInit) > 0 ); assert( Gia_ManPoNum(pInit) > 0 ); assert( Gia_ManRegNum(pInit) > 0 ); // create manager p = Int2_ManCreate( pInit, pPars ); // create SAT solver p->pSatPref = sat_solver_new(); sat_solver_setnvars( p->pSatPref, 1000 ); sat_solver_set_runtime_limit( p->pSatPref, nTimeToStop ); // check outputs in the first frame for ( i = 0; i < Gia_ManPoNum(pInit); i++ ) Vec_IntPush( p->vPrefCos, i ); Int2_ManCreateFrames( p, 0, p->vPrefCos ); RetValue = Int2_ManCheckBmc( p, NULL ); if ( RetValue != 1 ) return RetValue; // create original image for ( f = pPars->nFramesS; f < p->nFramesMax; f++ ) { for ( i = 0; i < p->nFramesMax; i++ ) { p->pSatSuff = Int2_ManPrepareSuffix( p, vImageOne. vImagesAll, &vCoMap, &pGiaSuff ); sat_solver_set_runtime_limit( p->pSatSuff, nTimeToStop ); Vec_IntFreeP( &vImageOne ); vImageOne = Int2_ManComputePreimage( pGiaSuff, p->pSatPref, p->pSatSuff, vCiMap, vCoMap ); Vec_IntFree( vCoMap ); Gia_ManStop( pGiaSuff ); if ( nTimeToStop && Abc_Clock() > nTimeToStop ) return -1; if ( vImageOne == NULL ) { if ( i == 0 ) { printf( "Satisfiable in frame %d.\n", f ); Vec_IntFree( vCiMap ); sat_solver_delete( p->pSatPref ); p->pSatPref = NULL; return 0; } f += i; break; } Vec_IntAppend( vImagesAll, vImageOne ); sat_solver_delete( p->pSatSuff ); p->pSatSuff = NULL; } Vec_IntFree( vCiMap ); sat_solver_delete( p->pSatPref ); p->pSatPref = NULL; } Abc_PrintTime( "Time", Abc_Clock() - clk ); p->timeSatPref += Abc_Clock() - clk; Int2_ManStop( p ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int2/int2Int.h000066400000000000000000000137371300674244400235500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [int2Int.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 1, 2013.] Revision [$Id: int2Int.h,v 1.00 2013/12/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__Gia__int2__intInt_h #define ABC__Gia__int2__intInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "sat/bsat/satSolver.h" #include "sat/cnf/cnf.h" #include "int2.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // interpolation manager typedef struct Int2_Man_t_ Int2_Man_t; struct Int2_Man_t_ { // parameters Int2_ManPars_t * pPars; // parameters // GIA managers Gia_Man_t * pGia; // original manager Gia_Man_t * pGiaPref; // prefix manager Gia_Man_t * pGiaSuff; // suffix manager // subset of the manager Vec_Int_t * vSuffCis; // suffix CIs Vec_Int_t * vSuffCos; // suffix COs Vec_Int_t * vPrefCos; // suffix POs Vec_Int_t * vStack; // temporary stack // preimages Vec_Int_t * vImageOne; // latest preimage Vec_Int_t * vImagesAll; // cumulative preimage // variable maps Vec_Ptr_t * vMapFrames; // mapping of GIA IDs into frame IDs Vec_Int_t * vMapPref; // mapping of flop inputs into SAT variables Vec_Int_t * vMapSuff; // mapping of flop outputs into SAT variables // initial minimization Vec_Int_t * vAssign; // assignment of PIs in pGiaSuff Vec_Int_t * vPrio; // priority of PIs in pGiaSuff // SAT solving sat_solver * pSatPref; // prefix solver sat_solver * pSatSuff; // suffix solver // runtime abctime timeSatPref; abctime timeSatSuff; abctime timeOther; abctime timeTotal; }; static inline Int2_Man_t * Int2_ManCreate( Gia_Man_t * pGia, Int2_ManPars_t * pPars ) { Int2_Man_t * p; p = ABC_CALLOC( Int2_Man_t, 1 ); p->pPars = pPars; p->pGia = pGia; p->pGiaPref = Gia_ManStart( 10000 ); // perform structural hashing Gia_ManHashAlloc( pFrames ); // subset of the manager p->vSuffCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vSuffCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); p->vPrefCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); p->vStack = Vec_IntAlloc( 10000 ); // preimages p->vImageOne = Vec_IntAlloc( 1000 ); p->vImagesAll = Vec_IntAlloc( 1000 ); // variable maps p->vMapFrames = Vec_PtrAlloc( 100 ); p->vMapPref = Vec_IntAlloc( Gia_ManRegNum(pGia) ); p->vMapSuff = Vec_IntAlloc( Gia_ManRegNum(pGia) ); // initial minimization p->vAssign = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vPrio = Vec_IntAlloc( Gia_ManCiNum(pGia) ); return p; } static inline void Int2_ManStop( Int2_Man_t * p ) { // GIA managers Gia_ManStopP( &p->pGiaPref ); Gia_ManStopP( &p->pGiaSuff ); // subset of the manager Vec_IntFreeP( &p->vSuffCis ); Vec_IntFreeP( &p->vSuffCos ); Vec_IntFreeP( &p->vPrefCos ); Vec_IntFreeP( &p->vStack ); // preimages Vec_IntFreeP( &p->vImageOne ); Vec_IntFreeP( &p->vImagesAll ); // variable maps Vec_VecFree( (Vec_Vec_t *)p->vMapFrames ); Vec_IntFreeP( &p->vMapPref ); Vec_IntFreeP( &p->vMapSuff ); // initial minimization Vec_IntFreeP( &p->vAssign ); Vec_IntFreeP( &p->vPrio ); // SAT solving if ( p->pSatPref ) sat_solver_delete( p->pSatPref ); if ( p->timeSatSuff ) sat_solver_delete( p->pSatSuff ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== int2Bmc.c =============================================================*/ extern int Int2_ManCheckInit( Gia_Man_t * p ); extern Gia_Man_t * Int2_ManDupInit( Gia_Man_t * p, int fVerbose ); extern sat_solver * Int2_ManSetupBmcSolver( Gia_Man_t * p, int nFrames ); extern void Int2_ManCreateFrames( Int2_Man_t * p, int iFrame, Vec_Int_t * vPrefCos ); extern int Int2_ManCheckBmc( Int2_Man_t * p, Vec_Int_t * vCube ); /*=== int2Refine.c =============================================================*/ extern Vec_Int_t * Int2_ManRefineCube( Gia_Man_t * p, Vec_Int_t * vAssign, Vec_Int_t * vPrio ); /*=== int2Util.c ============================================================*/ extern Gia_Man_t * Int2_ManProbToGia( Gia_Man_t * p, Vec_Int_t * vSop ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int2/int2Refine.c000066400000000000000000000123421300674244400242100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [int2Refine.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 1, 2013.] Revision [$Id: int2Refine.c,v 1.00 2013/12/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "int2Int.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int2_ManJustify_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSelect ) { if ( pObj->fMark1 ) return; pObj->fMark1 = 1; if ( Gia_ObjIsPi(p, pObj) ) return; if ( Gia_ObjIsCo(pObj) ) { Vec_IntPush( vSelect, Gia_ObjCioId(pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); if ( pObj->Value == 1 ) { if ( Gia_ObjFanin0(pObj)->Value < ABC_INFINITY ) Int2_ManJustify_rec( p, Gia_ObjFanin0(pObj), vSelect ); if ( Gia_ObjFanin1(pObj)->Value < ABC_INFINITY ) Int2_ManJustify_rec( p, Gia_ObjFanin1(pObj), vSelect ); return; } if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 ) { if ( Gia_ObjFanin0(pObj)->fMark0 <= Gia_ObjFanin1(pObj)->fMark0 ) // choice { if ( Gia_ObjFanin0(pObj)->Value < ABC_INFINITY ) Int2_ManJustify_rec( p, Gia_ObjFanin0(pObj), vSelect ); } else { if ( Gia_ObjFanin1(pObj)->Value < ABC_INFINITY ) Int2_ManJustify_rec( p, Gia_ObjFanin1(pObj), vSelect ); } } else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 ) { if ( Gia_ObjFanin0(pObj)->Value < ABC_INFINITY ) Int2_ManJustify_rec( p, Gia_ObjFanin0(pObj), vSelect ); } else if ( (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 ) { if ( Gia_ObjFanin1(pObj)->Value < ABC_INFINITY ) Int2_ManJustify_rec( p, Gia_ObjFanin1(pObj), vSelect ); } else assert( 0 ); } /**Function************************************************************* Synopsis [Computes the reduced set of flop variables.] Description [Given is a single-output seq AIG manager and an assignment of its CIs. Returned is a subset of flops that justifies the output.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Int2_ManRefineCube( Gia_Man_t * p, Vec_Int_t * vAssign, Vec_Int_t * vPrio ) { Vec_Int_t * vSubset; Gia_Obj_t * pObj; int i; // set values and prios assert( Gia_ManRegNum(p) > 0 ); assert( Vec_IntSize(vAssign) == Vec_IntSize(vPrio) ); Gia_ManConst0(p)->fMark0 = 0; Gia_ManConst0(p)->fMark1 = 0; Gia_ManConst0(p)->Value = ABC_INFINITY; Gia_ManForEachCi( p, pObj, i ) { pObj->fMark0 = Vec_IntEntry(vAssign, i); pObj->fMark1 = 0; pObj->Value = Vec_IntEntry(vPrio, i); } Gia_ManForEachAnd( p, pObj, i ) { pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); pObj->fMark1 = 0; if ( pObj->fMark0 == 1 ) pObj->Value = Abc_MaxInt( Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 ) pObj->Value = Abc_MinInt( Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); // choice else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else pObj->Value = Gia_ObjFanin1(pObj)->Value; } pObj = Gia_ManPo( p, 0 ); pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)); pObj->fMark1 = 0; pObj->Value = Gia_ObjFanin0(pObj)->Value; assert( pObj->fMark0 == 1 ); assert( pObj->Value < ABC_INFINITY ); // select subset vSubset = Vec_IntAlloc( 100 ); Int2_ManJustify_rec( p, Gia_ObjFanin0(pObj), vSubset ); return vSubset; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int2/int2Util.c000066400000000000000000000113711300674244400237160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [int2Util.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Interpolation engine.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Dec 1, 2013.] Revision [$Id: int2Util.c,v 1.00 2013/12/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "int2Int.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Int2_ManComputeCoPres( Vec_Int_t * vSop, int nRegs ) { Vec_Int_t * vCoPres, * vMap; vCoPres = Vec_IntAlloc( 100 ); if ( vSop == NULL ) Vec_IntPush( vCoPres, 0 ); else { int i, k, Limit; vMap = Vec_IntStart( nRegs ); Vec_IntForEachEntryStart( vSop, Limit, i, 1 ) { for ( k = 0; k < Limit; k++ ) { i++; assert( Vec_IntEntry(vSop, i + k) < 2 * nRegs ); Vec_IntWriteEntry( vMap, Abc_Lit2Var(Vec_IntEntry(vSop, i + k)), 1 ); } } Vec_IntForEachEntry( vMap, Limit, i ) if ( Limit ) Vec_IntPush( vCoPres, i+1 ); Vec_IntFree( vMap ); } return vCoPres; } void Int2_ManCollectInternal_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) ) return; assert( Gia_ObjIsAnd(pObj) ); Int2_ManCollectInternal_rec( p, Gia_ObjFanin0(pObj), vNodes ); Int2_ManCollectInternal_rec( p, Gia_ObjFanin1(pObj), vNodes ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } Vec_Int_t * Int2_ManCollectInternal( Gia_Man_t * p, Vec_Int_t * vCoPres ) { Vec_Int_t * vNodes; Gia_Obj_t * pObj; int i, Entry; Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent(p, Gia_ManConst0(p)); Gia_ManForEachCi( p, pObj, i ) Gia_ObjSetTravIdCurrent(p, pObj); vNodes = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( vCoPres, Entry, i ) Int2_ManCollectInternal_rec( p, Gia_ObjFanin0(Gia_ManCo(p, Entry)), vNodes ); return vNodes; } Gia_Man_t * Int2_ManProbToGia( Gia_Man_t * p, Vec_Int_t * vSop ) { Vec_Int_t * vCoPres, * vNodes; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, k, Entry, Limit; int Lit, Cube, Sop; assert( Gia_ManPoNum(p) == 1 ); // collect COs and ANDs vCoPres = Int2_ManComputeCoPres( vSop, Gia_ManRegNum(p) ); vNodes = Int2_ManCollectInternal( p, vCoPres ); // 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_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManHashAlloc( pNew ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Vec_IntForEachEntry( vCoPres, Entry, i ) { pObj = Gia_ManCo(p, Entry); pObj->Value = Gia_ObjFanin0Copy( pObj ); } // create additional cubes Sop = 0; Vec_IntForEachEntryStart( vSop, Limit, i, 1 ) { Cube = 1; for ( k = 0; k < Limit; k++ ) { i++; Lit = Vec_IntEntry( vSop, i + k ); pObj = Gia_ManRi( p, Abc_Lit2Var(Lit) ); Cube = Gia_ManHashAnd( pNew, Cube, Abc_LitNotCond(pObj->Value, Abc_LitIsCompl(Lit)) ); } Sop = Gia_ManHashOr( pNew, Sop, Cube ); } Gia_ManAppendCo( pNew, Sop ); Gia_ManHashStop( pNew ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/int2/module.make000066400000000000000000000001711300674244400241600ustar00rootroot00000000000000SRC += src/proof/int2/int2Bmc.c \ src/proof/int2/int2Core.c \ src/proof/int2/int2Refine.c \ src/proof/int2/int2Util.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/000077500000000000000000000000001300674244400221205ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/arenaViolation.c000066400000000000000000000417541300674244400252520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [arenaViolation.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [module for addition of arena violator detector induced by stabilizing constraints] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 31, 2012.] ***********************************************************************/ #include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include #include "base/main/mainInt.h" #include "proof/pdr/pdr.h" //#define DISJUNCTIVE_CONSTRAINT_ENABLE_MODE #define BARRIER_MONOTONE_TEST ABC_NAMESPACE_IMPL_START Vec_Ptr_t * createArenaLO( Aig_Man_t *pAigNew, Vec_Ptr_t *vBarriers ) { Vec_Ptr_t *vArenaLO; int barrierCount; Aig_Obj_t *pObj; int i; if( vBarriers == NULL ) return NULL; barrierCount = Vec_PtrSize(vBarriers); if( barrierCount <= 0 ) return NULL; vArenaLO = Vec_PtrAlloc(barrierCount); for( i=0; ipData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(poDriverOld)->pData)); //assert( !Aig_ObjIsCo(poDriverNew) ); return poDriverNew; } Vec_Ptr_t *collectBarrierDisjunctions(Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Vec_Ptr_t *vBarriers) { int barrierCount, i, j, jElem; Vec_Int_t *vIthBarrier; Aig_Obj_t *pObjBarrier, *pObjCurr, *pObjTargetPoOld; Vec_Ptr_t *vNewBarrierSignals; if( vBarriers == NULL ) return NULL; barrierCount = Vec_PtrSize( vBarriers ); if( barrierCount <= 0 ) return NULL; vNewBarrierSignals = Vec_PtrAlloc( barrierCount ); for( i=0; i= 1 ); pObjBarrier = Aig_Not(Aig_ManConst1(pAigNew)); Vec_IntForEachEntry( vIthBarrier, jElem, j ) { pObjTargetPoOld = Aig_ManCo( pAigOld, jElem ); //Aig_ObjPrint( pAigOld, pObjTargetPoOld ); //printf("\n"); pObjCurr = driverToPoNew( pAigOld, pObjTargetPoOld ); pObjBarrier = Aig_Or( pAigNew, pObjCurr, pObjBarrier ); } assert( pObjBarrier ); Vec_PtrPush(vNewBarrierSignals, pObjBarrier); } assert( Vec_PtrSize( vNewBarrierSignals ) == barrierCount ); return vNewBarrierSignals; } Aig_Obj_t *Aig_Xor( Aig_Man_t *pAig, Aig_Obj_t *pObj1, Aig_Obj_t *pObj2 ) { return Aig_Or( pAig, Aig_And( pAig, pObj1, Aig_Not(pObj2) ), Aig_And( pAig, Aig_Not(pObj1), pObj2 ) ); } Aig_Obj_t *createArenaViolation( Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pWindowBegins, Aig_Obj_t *pWithinWindow, Vec_Ptr_t *vMasterBarriers, Vec_Ptr_t *vBarrierLo, Vec_Ptr_t *vBarrierLiDriver, Vec_Ptr_t *vMonotoneDisjunctionNodes ) { Aig_Obj_t *pWindowBeginsLocal = pWindowBegins; Aig_Obj_t *pWithinWindowLocal = pWithinWindow; int i; Aig_Obj_t *pObj, *pObjAnd1, *pObjOr1, *pObjAnd2, *pObjBarrierLo, *pObjBarrierSwitch, *pObjArenaViolation; Vec_Ptr_t *vBarrierSignals; assert( vBarrierLiDriver != NULL ); assert( vMonotoneDisjunctionNodes != NULL ); pObjArenaViolation = Aig_Not(Aig_ManConst1( pAigNew )); vBarrierSignals = collectBarrierDisjunctions(pAigOld, pAigNew, vMasterBarriers); assert( vBarrierSignals != NULL ); assert( Vec_PtrSize( vMonotoneDisjunctionNodes ) == 0 ); Vec_PtrForEachEntry( Aig_Obj_t *, vBarrierSignals, pObj, i ) Vec_PtrPush( vMonotoneDisjunctionNodes, pObj ); assert( Vec_PtrSize( vMonotoneDisjunctionNodes ) == Vec_PtrSize( vMasterBarriers ) ); Vec_PtrForEachEntry( Aig_Obj_t *, vBarrierSignals, pObj, i ) { //pObjNew = driverToPoNew( pAigOld, pObj ); pObjAnd1 = Aig_And(pAigNew, pObj, pWindowBeginsLocal); pObjBarrierLo = (Aig_Obj_t *)Vec_PtrEntry( vBarrierLo, i ); pObjOr1 = Aig_Or(pAigNew, pObjAnd1, pObjBarrierLo); Vec_PtrPush( vBarrierLiDriver, pObjOr1 ); pObjBarrierSwitch = Aig_Xor( pAigNew, pObj, pObjBarrierLo ); pObjAnd2 = Aig_And( pAigNew, pObjBarrierSwitch, pWithinWindowLocal ); pObjArenaViolation = Aig_Or( pAigNew, pObjAnd2, pObjArenaViolation ); } Vec_PtrFree(vBarrierSignals); return pObjArenaViolation; } Aig_Obj_t *createConstrained0LiveConeWithDSC( Aig_Man_t *pNewAig, Vec_Ptr_t *signalList ) { Aig_Obj_t *pConsequent, *pConsequentCopy, *pAntecedent, *p0LiveCone, *pObj; int i, numSigAntecedent; numSigAntecedent = Vec_PtrSize( signalList ) - 1; pAntecedent = Aig_ManConst1( pNewAig ); pConsequent = (Aig_Obj_t *)Vec_PtrEntry( signalList, numSigAntecedent ); pConsequentCopy = Aig_NotCond( (Aig_Obj_t *)(Aig_Regular(pConsequent)->pData), Aig_IsComplement( pConsequent ) ); for(i=0; ipData ); pAntecedent = Aig_And( pNewAig, pAntecedent, Aig_NotCond((Aig_Obj_t *)(Aig_Regular(pObj)->pData), Aig_IsComplement(pObj)) ); } p0LiveCone = Aig_Or( pNewAig, Aig_Not(pAntecedent), pConsequentCopy ); return p0LiveCone; } Vec_Ptr_t *collectCSSignalsWithDSC( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { int i; Aig_Obj_t *pObj, *pConsequent = NULL; Vec_Ptr_t *vNodeArray; vNodeArray = Vec_PtrAlloc(1); Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "csLiveConst_" ) != NULL ) Vec_PtrPush( vNodeArray, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)) ); else if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "csLiveTarget_" ) != NULL ) pConsequent = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } assert( pConsequent ); Vec_PtrPush( vNodeArray, pConsequent ); return vNodeArray; } int collectWindowBeginSignalWithDSC( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { int i; Aig_Obj_t *pObj; Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "windowBegins_" ) != NULL ) { return i; } } return -1; } int collectWithinWindowSignalWithDSC( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { int i; Aig_Obj_t *pObj; Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "withinWindow_" ) != NULL ) return i; } return -1; } int collectPendingSignalWithDSC( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { int i; Aig_Obj_t *pObj; Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "pendingSignal" ) != NULL ) return i; } return -1; } Aig_Obj_t *createAndGateForMonotonicityVerification( Aig_Man_t *pNewAig, Vec_Ptr_t *vDisjunctionSignals, Vec_Ptr_t *vDisjunctionLo, Aig_Obj_t *pendingLo, Aig_Obj_t *pendingSignal ) { Aig_Obj_t *pObjBigAnd, *pObj, *pObjLo, *pObjImply; Aig_Obj_t *pObjPendingAndPendingLo; int i; pObjBigAnd = Aig_ManConst1( pNewAig ); pObjPendingAndPendingLo = Aig_And( pNewAig, pendingLo, pendingSignal ); Vec_PtrForEachEntry( Aig_Obj_t *, vDisjunctionSignals, pObj, i ) { pObjLo = (Aig_Obj_t *)Vec_PtrEntry( vDisjunctionLo, i ); pObjImply = Aig_Or( pNewAig, Aig_Not(Aig_And( pNewAig, pObjPendingAndPendingLo, pObjLo)), pObj ); pObjBigAnd = Aig_And( pNewAig, pObjBigAnd, pObjImply ); } return pObjBigAnd; } Aig_Man_t *createNewAigWith0LivePoWithDSC( Aig_Man_t *pAig, Vec_Ptr_t *signalList, int *index0Live, int windowBeginIndex, int withinWindowIndex, int pendingSignalIndex, Vec_Ptr_t *vBarriers ) { Aig_Man_t *pNewAig; Aig_Obj_t *pObj, *pObjNewPoDriver; int i; int loCopied = 0, loCreated = 0, liCopied = 0, liCreated = 0; Aig_Obj_t *pObjWindowBeginsNew, *pObjWithinWindowNew, *pObjArenaViolation, *pObjTarget, *pObjArenaViolationLiDriver; Aig_Obj_t *pObjNewPoDriverArenaViolated, *pObjArenaViolationLo; Vec_Ptr_t *vBarrierLo, *vBarrierLiDriver, *vBarrierLi; Vec_Ptr_t *vMonotoneNodes; #ifdef BARRIER_MONOTONE_TEST Aig_Obj_t *pObjPendingSignal; Aig_Obj_t *pObjPendingFlopLo; Vec_Ptr_t *vMonotoneBarrierLo; Aig_Obj_t *pObjPendingAndPendingSignal, *pObjMonotoneAnd, *pObjCurrMonotoneLo; #endif //assert( Vec_PtrSize( signalList ) > 1 ); //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_0Live") + 1 ); sprintf(pNewAig->pName, "%s_%s", pAig->pName, "0Live"); pNewAig->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( pAig ); pObj->pData = Aig_ManConst1( pNewAig ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCi( pNewAig ); } //**************************************************************** // Step 4: create register outputs //**************************************************************** Saig_ManForEachLo( pAig, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi( pNewAig ); } //**************************************************************** // Step 4.a: create register outputs for the barrier flops //**************************************************************** vBarrierLo = createArenaLO( pNewAig, vBarriers ); loCreated = Vec_PtrSize(vBarrierLo); //**************************************************************** // Step 4.b: create register output for arenaViolationFlop //**************************************************************** pObjArenaViolationLo = Aig_ObjCreateCi( pNewAig ); loCreated++; #ifdef BARRIER_MONOTONE_TEST //**************************************************************** // Step 4.c: create register output for pendingFlop //**************************************************************** pObjPendingFlopLo = Aig_ObjCreateCi( pNewAig ); loCreated++; //**************************************************************** // Step 4.d: create register outputs for the barrier flops // for asserting monotonicity //**************************************************************** vMonotoneBarrierLo = createMonotoneBarrierLO( pNewAig, vBarriers ); loCreated = loCreated + Vec_PtrSize(vMonotoneBarrierLo); #endif //******************************************************************** // Step 5: create internal nodes //******************************************************************** Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 5.a: create internal nodes corresponding to arenaViolation //******************************************************************** pObjTarget = Aig_ManCo( pAig, windowBeginIndex ); pObjWindowBeginsNew = driverToPoNew( pAig, pObjTarget ); pObjTarget = Aig_ManCo( pAig, withinWindowIndex ); pObjWithinWindowNew = driverToPoNew( pAig, pObjTarget ); vBarrierLiDriver = Vec_PtrAlloc( Vec_PtrSize(vBarriers) ); vMonotoneNodes = Vec_PtrAlloc( Vec_PtrSize(vBarriers) ); pObjArenaViolation = createArenaViolation( pAig, pNewAig, pObjWindowBeginsNew, pObjWithinWindowNew, vBarriers, vBarrierLo, vBarrierLiDriver, vMonotoneNodes ); assert( Vec_PtrSize(vMonotoneNodes) == Vec_PtrSize(vBarriers) ); #ifdef ARENA_VIOLATION_CONSTRAINT #endif pObjArenaViolationLiDriver = Aig_Or( pNewAig, pObjArenaViolation, pObjArenaViolationLo ); #ifdef BARRIER_MONOTONE_TEST //******************************************************************** // Step 5.b: Create internal nodes for monotone testing //******************************************************************** pObjTarget = Aig_ManCo( pAig, pendingSignalIndex ); pObjPendingSignal = driverToPoNew( pAig, pObjTarget ); pObjPendingAndPendingSignal = Aig_And( pNewAig, pObjPendingSignal, pObjPendingFlopLo ); pObjMonotoneAnd = Aig_ManConst1( pNewAig ); Vec_PtrForEachEntry( Aig_Obj_t *, vMonotoneNodes, pObj, i ) { pObjCurrMonotoneLo = (Aig_Obj_t *)Vec_PtrEntry(vMonotoneBarrierLo, i); pObjMonotoneAnd = Aig_And( pNewAig, pObjMonotoneAnd, Aig_Or( pNewAig, Aig_Not(Aig_And(pNewAig, pObjPendingAndPendingSignal, pObjCurrMonotoneLo)), pObj ) ); } #endif //******************************************************************** // Step 6: create primary outputs //******************************************************************** Saig_ManForEachPo( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } pObjNewPoDriver = createConstrained0LiveConeWithDSC( pNewAig, signalList ); pObjNewPoDriverArenaViolated = Aig_Or( pNewAig, pObjNewPoDriver, pObjArenaViolationLo ); #ifdef BARRIER_MONOTONE_TEST pObjNewPoDriverArenaViolated = Aig_And( pNewAig, pObjNewPoDriverArenaViolated, pObjMonotoneAnd ); #endif Aig_ObjCreateCo( pNewAig, pObjNewPoDriverArenaViolated ); *index0Live = i; //******************************************************************** // Step 7: create register inputs //******************************************************************** Saig_ManForEachLi( pAig, pObj, i ) { liCopied++; pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //******************************************************************** // Step 7.a: create register inputs for barrier flops //******************************************************************** assert( Vec_PtrSize(vBarrierLiDriver) == Vec_PtrSize(vBarriers) ); vBarrierLi = createArenaLi( pNewAig, vBarriers, vBarrierLiDriver ); liCreated = Vec_PtrSize( vBarrierLi ); //******************************************************************** // Step 7.b: create register inputs for arenaViolation flop //******************************************************************** Aig_ObjCreateCo( pNewAig, pObjArenaViolationLiDriver ); liCreated++; #ifdef BARRIER_MONOTONE_TEST //**************************************************************** // Step 7.c: create register input for pendingFlop //**************************************************************** Aig_ObjCreateCo( pNewAig, pObjPendingSignal); liCreated++; //******************************************************************** // Step 7.d: create register inputs for the barrier flops // for asserting monotonicity //******************************************************************** Vec_PtrForEachEntry( Aig_Obj_t *, vMonotoneNodes, pObj, i ) { Aig_ObjCreateCo( pNewAig, pObj ); liCreated++; } #endif assert(loCopied + loCreated == liCopied + liCreated); //next step should be changed Aig_ManSetRegNum( pNewAig, loCopied + loCreated ); Aig_ManCleanup( pNewAig ); assert( Aig_ManCheck( pNewAig ) ); Vec_PtrFree(vBarrierLo); Vec_PtrFree(vMonotoneBarrierLo); Vec_PtrFree(vBarrierLiDriver); Vec_PtrFree(vBarrierLi); Vec_PtrFree(vMonotoneNodes); return pNewAig; } Aig_Man_t *generateWorkingAigWithDSC( Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int *pIndex0Live, Vec_Ptr_t *vMasterBarriers ) { Vec_Ptr_t *vSignalVector; Aig_Man_t *pAigNew; int pObjWithinWindow; int pObjWindowBegin; int pObjPendingSignal; vSignalVector = collectCSSignalsWithDSC( pNtk, pAig ); pObjWindowBegin = collectWindowBeginSignalWithDSC( pNtk, pAig ); pObjWithinWindow = collectWithinWindowSignalWithDSC( pNtk, pAig ); pObjPendingSignal = collectPendingSignalWithDSC( pNtk, pAig ); pAigNew = createNewAigWith0LivePoWithDSC( pAig, vSignalVector, pIndex0Live, pObjWindowBegin, pObjWithinWindow, pObjPendingSignal, vMasterBarriers ); Vec_PtrFree(vSignalVector); return pAigNew; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/combination.c000066400000000000000000000323261300674244400245740ustar00rootroot00000000000000#include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include #include "base/main/mainInt.h" #include "proof/pdr/pdr.h" #include ABC_NAMESPACE_IMPL_START long countCombination(long n, long k) { assert( n >= k ); if( n == k ) return 1; if( k == 1 ) return n; return countCombination( n-1, k-1 ) + countCombination( n-1, k ); } void listCombination(int n, int t) { Vec_Int_t *vC; int i, j, combCounter = 0; //Initialization vC = Vec_IntAlloc(t+3); for(i=-1; i0; i--) printf("vC[%d] = %d ", i, Vec_IntEntry(vC, i)); printf("\n"); j = 1; while( Vec_IntEntry( vC, j ) + 1 == Vec_IntEntry( vC, j+1 ) ) { //printf("\nGochon = %d, %d\n", Vec_IntEntry( vC, j ) + 1, Vec_IntEntry( vC, j+1 )); Vec_IntWriteEntry( vC, j, j-1 ); j = j + 1; } if( j > t ) break; Vec_IntWriteEntry( vC, j, Vec_IntEntry( vC, j ) + 1 ); } Vec_IntFree(vC); } int generateCombinatorialStabil( Aig_Man_t *pAigNew, Aig_Man_t *pAigOld, Vec_Int_t *vCandidateMonotoneSignals_, Vec_Ptr_t *vDisj_nCk_, int combN, int combK ) { Aig_Obj_t *pObjMonoCand, *pObj; int targetPoIndex; //Knuth's Data Strcuture int totalCombination_KNUTH = 0; Vec_Int_t *vC_KNUTH; int i_KNUTH, j_KNUTH; //Knuth's Data Structure Initialization vC_KNUTH = Vec_IntAlloc(combK+3); for(i_KNUTH=-1; i_KNUTH0; i_KNUTH--) { targetPoIndex = Vec_IntEntry( vCandidateMonotoneSignals_, Vec_IntEntry(vC_KNUTH, i_KNUTH)); pObj = Aig_ObjChild0Copy(Aig_ManCo( pAigOld, targetPoIndex )); pObjMonoCand = Aig_Or( pAigNew, pObj, pObjMonoCand ); } Vec_PtrPush(vDisj_nCk_, pObjMonoCand ); j_KNUTH = 1; while( Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 == Vec_IntEntry( vC_KNUTH, j_KNUTH+1 ) ) { Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, j_KNUTH-1 ); j_KNUTH = j_KNUTH + 1; } if( j_KNUTH > combK ) break; Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 ); } Vec_IntFree(vC_KNUTH); return totalCombination_KNUTH; } int generateCombinatorialStabilExhaust( Aig_Man_t *pAigNew, Aig_Man_t *pAigOld, Vec_Ptr_t *vDisj_nCk_, int combN, int combK ) { Aig_Obj_t *pObjMonoCand, *pObj; int targetPoIndex; //Knuth's Data Strcuture int totalCombination_KNUTH = 0; Vec_Int_t *vC_KNUTH; int i_KNUTH, j_KNUTH; //Knuth's Data Structure Initialization vC_KNUTH = Vec_IntAlloc(combK+3); for(i_KNUTH=-1; i_KNUTH0; i_KNUTH--) { //targetPoIndex = Vec_IntEntry( vCandidateMonotoneSignals_, Vec_IntEntry(vC_KNUTH, i_KNUTH)); targetPoIndex = Vec_IntEntry(vC_KNUTH, i_KNUTH); pObj = (Aig_Obj_t *)(Aig_ManLo( pAigOld, targetPoIndex )->pData); pObjMonoCand = Aig_Or( pAigNew, pObj, pObjMonoCand ); } Vec_PtrPush(vDisj_nCk_, pObjMonoCand ); j_KNUTH = 1; while( Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 == Vec_IntEntry( vC_KNUTH, j_KNUTH+1 ) ) { Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, j_KNUTH-1 ); j_KNUTH = j_KNUTH + 1; } if( j_KNUTH > combK ) break; Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 ); } Vec_IntFree(vC_KNUTH); return totalCombination_KNUTH; } Aig_Man_t *generateDisjunctiveTester( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int combN, int combK ) { //AIG creation related data structure Aig_Man_t *pNewAig; int piCopied = 0, loCopied = 0, loCreated = 0, liCopied = 0, liCreated = 0, poCopied = 0; //int i, iElem, nRegCount, hintSingalBeginningMarker, hintSingalEndMarker; int i, nRegCount, hintSingalBeginningMarker, hintSingalEndMarker; int combN_internal, combK_internal; //, targetPoIndex; long longI, lCombinationCount; //Aig_Obj_t *pObj, *pObjMonoCand, *pObjLO_nCk, *pObjDisj_nCk; Aig_Obj_t *pObj, *pObjLO_nCk, *pObjDisj_nCk; Vec_Ptr_t *vLO_nCk, *vPODriver_nCk, *vDisj_nCk; Vec_Int_t *vCandidateMonotoneSignals; extern Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk); //Knuth's Data Strcuture //Vec_Int_t *vC_KNUTH; //int i_KNUTH, j_KNUTH, combCounter_KNUTH = 0; //Collecting target HINT signals vCandidateMonotoneSignals = findHintOutputs(pNtk); if( vCandidateMonotoneSignals == NULL ) { printf("\nTraget Signal Set is Empty: Duplicating given AIG\n"); combN_internal = 0; } else { //Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i ) // printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) ); hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 ); hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 ); combN_internal = hintSingalEndMarker - hintSingalBeginningMarker + 1; } //combK_internal = combK; //Knuth's Data Structure Initialization //vC_KNUTH = Vec_IntAlloc(combK_internal+3); //for(i_KNUTH=-1; i_KNUTHpName = (char *)malloc( strlen( pAig->pName ) + strlen("_nCk") + 1 ); sprintf(pNewAig->pName, "%s_%s", pAig->pName, "nCk"); pNewAig->pSpec = NULL; //Standard Mapping of Constant Nodes pObj = Aig_ManConst1( pAig ); pObj->pData = Aig_ManConst1( pNewAig ); //Standard AIG PI duplication Saig_ManForEachPi( pAig, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //Standard AIG LO duplication Saig_ManForEachLo( pAig, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //nCk LO creation lCombinationCount = 0; for(combK_internal=1; combK_internal<=combK; combK_internal++) lCombinationCount += countCombination( combN_internal, combK_internal ); assert( lCombinationCount > 0 ); vLO_nCk = Vec_PtrAlloc(lCombinationCount); for( longI = 0; longI < lCombinationCount; longI++ ) { loCreated++; pObj = Aig_ObjCreateCi(pNewAig); Vec_PtrPush( vLO_nCk, pObj ); } //Standard Node duplication Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //nCk specific logic creation (i.e. nCk number of OR gates) vDisj_nCk = Vec_PtrAlloc(lCombinationCount); //while(1) //{ // //visit combination // //printf("Comb-%3d : ", ++combCounter_KNUTH); // pObjMonoCand = Aig_Not(Aig_ManConst1(pNewAig)); // for( i_KNUTH=combK_internal; i_KNUTH>0; i_KNUTH--) // { // //printf("vC[%d] = %d ", i_KNUTH, Vec_IntEntry(vC_KNUTH, i_KNUTH)); // targetPoIndex = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntEntry(vC_KNUTH, i_KNUTH)); // pObj = Aig_ObjChild0Copy(Aig_ManCo( pAig, targetPoIndex )); // pObjMonoCand = Aig_Or( pNewAig, pObj, pObjMonoCand ); // } // Vec_PtrPush(vDisj_nCk, pObjMonoCand ); // //printf("\n"); // j_KNUTH = 1; // while( Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 == Vec_IntEntry( vC_KNUTH, j_KNUTH+1 ) ) // { // Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, j_KNUTH-1 ); // j_KNUTH = j_KNUTH + 1; // } // if( j_KNUTH > combK_internal ) break; // Vec_IntWriteEntry( vC_KNUTH, j_KNUTH, Vec_IntEntry( vC_KNUTH, j_KNUTH ) + 1 ); //} for( combK_internal=1; combK_internal<=combK; combK_internal++ ) generateCombinatorialStabil( pNewAig, pAig, vCandidateMonotoneSignals, vDisj_nCk, combN_internal, combK_internal ); //creation of implication logic vPODriver_nCk = Vec_PtrAlloc(lCombinationCount); for( longI = 0; longI < lCombinationCount; longI++ ) { pObjLO_nCk = (Aig_Obj_t *)(Vec_PtrEntry( vLO_nCk, longI )); pObjDisj_nCk = (Aig_Obj_t *)(Vec_PtrEntry( vDisj_nCk, longI )); pObj = Aig_Or( pNewAig, Aig_Not(pObjDisj_nCk), pObjLO_nCk); Vec_PtrPush(vPODriver_nCk, pObj); } //Standard PO duplication Saig_ManForEachPo( pAig, pObj, i ) { poCopied++; pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //nCk specific PO creation for( longI = 0; longI < lCombinationCount; longI++ ) { Aig_ObjCreateCo( pNewAig, (Aig_Obj_t *)(Vec_PtrEntry( vPODriver_nCk, longI )) ); } //Standard LI duplication Saig_ManForEachLi( pAig, pObj, i ) { liCopied++; Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //nCk specific LI creation for( longI = 0; longI < lCombinationCount; longI++ ) { liCreated++; Aig_ObjCreateCo( pNewAig, (Aig_Obj_t *)(Vec_PtrEntry( vPODriver_nCk, longI )) ); } //clean-up, book-keeping assert( liCopied + liCreated == loCopied + loCreated ); nRegCount = loCopied + loCreated; Aig_ManSetRegNum( pNewAig, nRegCount ); Aig_ManCleanup( pNewAig ); assert( Aig_ManCheck( pNewAig ) ); //Vec_IntFree(vC_KNUTH); return pNewAig; } Aig_Man_t *generateGeneralDisjunctiveTester( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int combK ) { //AIG creation related data structure Aig_Man_t *pNewAig; int piCopied = 0, loCopied = 0, loCreated = 0, liCopied = 0, liCreated = 0, poCopied = 0; //int i, iElem, nRegCount, hintSingalBeginningMarker, hintSingalEndMarker; int i, nRegCount; int combN_internal, combK_internal; //, targetPoIndex; long longI, lCombinationCount; //Aig_Obj_t *pObj, *pObjMonoCand, *pObjLO_nCk, *pObjDisj_nCk; Aig_Obj_t *pObj, *pObjLO_nCk, *pObjDisj_nCk; Vec_Ptr_t *vLO_nCk, *vPODriver_nCk, *vDisj_nCk; extern Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk); //Knuth's Data Strcuture //Vec_Int_t *vC_KNUTH; //int i_KNUTH, j_KNUTH, combCounter_KNUTH = 0; //Collecting target HINT signals //vCandidateMonotoneSignals = findHintOutputs(pNtk); //if( vCandidateMonotoneSignals == NULL ) //{ // printf("\nTraget Signal Set is Empty: Duplicating given AIG\n"); // combN_internal = 0; //} //else //{ //Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i ) // printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) ); // hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 ); // hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 ); // combN_internal = hintSingalEndMarker - hintSingalBeginningMarker + 1; //} combN_internal = Aig_ManRegNum(pAig); pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_nCk") + 1 ); sprintf(pNewAig->pName, "%s_%s", pAig->pName, "nCk"); pNewAig->pSpec = NULL; //Standard Mapping of Constant Nodes pObj = Aig_ManConst1( pAig ); pObj->pData = Aig_ManConst1( pNewAig ); //Standard AIG PI duplication Saig_ManForEachPi( pAig, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //Standard AIG LO duplication Saig_ManForEachLo( pAig, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //nCk LO creation lCombinationCount = 0; for(combK_internal=1; combK_internal<=combK; combK_internal++) lCombinationCount += countCombination( combN_internal, combK_internal ); assert( lCombinationCount > 0 ); vLO_nCk = Vec_PtrAlloc(lCombinationCount); for( longI = 0; longI < lCombinationCount; longI++ ) { loCreated++; pObj = Aig_ObjCreateCi(pNewAig); Vec_PtrPush( vLO_nCk, pObj ); } //Standard Node duplication Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //nCk specific logic creation (i.e. nCk number of OR gates) vDisj_nCk = Vec_PtrAlloc(lCombinationCount); for( combK_internal=1; combK_internal<=combK; combK_internal++ ) { generateCombinatorialStabilExhaust( pNewAig, pAig, vDisj_nCk, combN_internal, combK_internal ); } //creation of implication logic vPODriver_nCk = Vec_PtrAlloc(lCombinationCount); for( longI = 0; longI < lCombinationCount; longI++ ) { pObjLO_nCk = (Aig_Obj_t *)(Vec_PtrEntry( vLO_nCk, longI )); pObjDisj_nCk = (Aig_Obj_t *)(Vec_PtrEntry( vDisj_nCk, longI )); pObj = Aig_Or( pNewAig, Aig_Not(pObjDisj_nCk), pObjLO_nCk); Vec_PtrPush(vPODriver_nCk, pObj); } //Standard PO duplication Saig_ManForEachPo( pAig, pObj, i ) { poCopied++; pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //nCk specific PO creation for( longI = 0; longI < lCombinationCount; longI++ ) { Aig_ObjCreateCo( pNewAig, (Aig_Obj_t *)(Vec_PtrEntry( vPODriver_nCk, longI )) ); } //Standard LI duplication Saig_ManForEachLi( pAig, pObj, i ) { liCopied++; Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //nCk specific LI creation for( longI = 0; longI < lCombinationCount; longI++ ) { liCreated++; Aig_ObjCreateCo( pNewAig, (Aig_Obj_t *)(Vec_PtrEntry( vPODriver_nCk, longI )) ); } //clean-up, book-keeping assert( liCopied + liCreated == loCopied + loCreated ); nRegCount = loCopied + loCreated; Aig_ManSetRegNum( pNewAig, nRegCount ); Aig_ManCleanup( pNewAig ); assert( Aig_ManCheck( pNewAig ) ); Vec_PtrFree(vLO_nCk); Vec_PtrFree(vPODriver_nCk); Vec_PtrFree(vDisj_nCk); //Vec_IntFree(vC_KNUTH); return pNewAig; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/disjunctiveMonotone.c000066400000000000000000000565321300674244400263450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [disjunctiveMonotone.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [Constraint analysis module for the k-Liveness algorithm invented by Koen Classen, Niklas Sorensson.] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 31, 2012.] ***********************************************************************/ #include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include #include "base/main/mainInt.h" #include "proof/pdr/pdr.h" #include ABC_NAMESPACE_IMPL_START struct aigPoIndices { int attrPendingSignalIndex; int attrHintSingalBeginningMarker; int attrHintSingalEndMarker; int attrSafetyInvarIndex; }; extern struct aigPoIndices *allocAigPoIndices(); extern void deallocAigPoIndices(struct aigPoIndices *toBeDeletedAigPoIndices); extern int collectSafetyInvariantPOIndex(Abc_Ntk_t *pNtk); struct antecedentConsequentVectorsStruct { Vec_Int_t *attrAntecedents; Vec_Int_t *attrConsequentCandidates; }; struct antecedentConsequentVectorsStruct *allocAntecedentConsequentVectorsStruct() { struct antecedentConsequentVectorsStruct *newStructure; newStructure = (struct antecedentConsequentVectorsStruct *)malloc(sizeof (struct antecedentConsequentVectorsStruct)); newStructure->attrAntecedents = NULL; newStructure->attrConsequentCandidates = NULL; assert( newStructure != NULL ); return newStructure; } void deallocAntecedentConsequentVectorsStruct(struct antecedentConsequentVectorsStruct *toBeDeleted) { assert( toBeDeleted != NULL ); if(toBeDeleted->attrAntecedents) Vec_IntFree( toBeDeleted->attrAntecedents ); if(toBeDeleted->attrConsequentCandidates) Vec_IntFree( toBeDeleted->attrConsequentCandidates ); free( toBeDeleted ); } Aig_Man_t *createDisjunctiveMonotoneTester(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct antecedentConsequentVectorsStruct *anteConseVectors, int *startMonotonePropPo) { Aig_Man_t *pNewAig; int iElem, i, nRegCount; int piCopied = 0, liCopied = 0, liCreated = 0, loCopied = 0, loCreated = 0; int poCopied = 0, poCreated = 0; Aig_Obj_t *pObj, *pObjPo, *pObjDriver, *pObjDriverNew, *pObjPendingDriverNew, *pObjPendingAndNextPending; Aig_Obj_t *pPendingFlop, *pObjConseCandFlop, *pObjSafetyInvariantPoDriver; //Vec_Ptr_t *vHintMonotoneLocalDriverNew; Vec_Ptr_t *vConseCandFlopOutput; //Vec_Ptr_t *vHintMonotoneLocalProp; Aig_Obj_t *pObjAnteDisjunction, *pObjConsecDriver, *pObjConsecDriverNew, *pObjCandMonotone, *pObjPrevCandMonotone, *pObjMonotonePropDriver; Vec_Ptr_t *vCandMonotoneProp; Vec_Ptr_t *vCandMonotoneFlopInput; int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex; Vec_Int_t *vAntecedentsLocal = anteConseVectors->attrAntecedents; Vec_Int_t *vConsequentCandidatesLocal = anteConseVectors->attrConsequentCandidates; if( vConsequentCandidatesLocal == NULL ) return NULL; //no candidates for consequent is provided, hence no need to generate a new AIG //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_monotone") + 2 ); sprintf(pNewAig->pName, "%s_%s", pAig->pName, "monotone"); pNewAig->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( pAig ); pObj->pData = Aig_ManConst1( pNewAig ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( pAig, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( pAig, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //**************************************************************** // Step 6: create "D" register output for PENDING flop //**************************************************************** loCreated++; pPendingFlop = Aig_ObjCreateCi( pNewAig ); //**************************************************************** // Step 6.a: create "D" register output for HINT_MONOTONE flop //**************************************************************** vConseCandFlopOutput = Vec_PtrAlloc(Vec_IntSize(vConsequentCandidatesLocal)); Vec_IntForEachEntry( vConsequentCandidatesLocal, iElem, i ) { loCreated++; pObjConseCandFlop = Aig_ObjCreateCi( pNewAig ); Vec_PtrPush( vConseCandFlopOutput, pObjConseCandFlop ); } nRegCount = loCreated + loCopied; //******************************************************************** // Step 7: create internal nodes //******************************************************************** Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 8: mapping appropriate new flop drivers //******************************************************************** if( aigPoIndicesArg->attrSafetyInvarIndex != -1 ) { pObjPo = Aig_ManCo( pAig, aigPoIndicesArg->attrSafetyInvarIndex ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); pObjSafetyInvariantPoDriver = pObjDriverNew; } else pObjSafetyInvariantPoDriver = Aig_ManConst1(pNewAig); pObjPo = Aig_ManCo( pAig, pendingSignalIndexLocal ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjPendingDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); pObjPendingAndNextPending = Aig_And( pNewAig, pObjPendingDriverNew, pPendingFlop ); pObjAnteDisjunction = Aig_Not(Aig_ManConst1( pNewAig )); if( vAntecedentsLocal ) { Vec_IntForEachEntry( vAntecedentsLocal, iElem, i ) { pObjPo = Aig_ManCo( pAig, iElem ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); pObjAnteDisjunction = Aig_Or( pNewAig, pObjDriverNew, pObjAnteDisjunction ); } } vCandMonotoneProp = Vec_PtrAlloc( Vec_IntSize(vConsequentCandidatesLocal) ); vCandMonotoneFlopInput = Vec_PtrAlloc( Vec_IntSize(vConsequentCandidatesLocal) ); Vec_IntForEachEntry( vConsequentCandidatesLocal, iElem, i ) { pObjPo = Aig_ManCo( pAig, iElem ); pObjConsecDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjConsecDriverNew = !Aig_IsComplement(pObjConsecDriver)? (Aig_Obj_t *)(Aig_Regular(pObjConsecDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjConsecDriver)->pData)); pObjCandMonotone = Aig_Or( pNewAig, pObjConsecDriverNew, pObjAnteDisjunction ); pObjPrevCandMonotone = (Aig_Obj_t *)(Vec_PtrEntry( vConseCandFlopOutput, i )); pObjMonotonePropDriver = Aig_Or( pNewAig, Aig_Not( Aig_And( pNewAig, pObjPendingAndNextPending, pObjPrevCandMonotone ) ), pObjCandMonotone ); //Conjunting safety invar pObjMonotonePropDriver = Aig_And( pNewAig, pObjMonotonePropDriver, pObjSafetyInvariantPoDriver ); Vec_PtrPush( vCandMonotoneFlopInput, pObjCandMonotone ); Vec_PtrPush( vCandMonotoneProp, pObjMonotonePropDriver ); } //******************************************************************** // Step 9: create primary outputs //******************************************************************** Saig_ManForEachPo( pAig, pObj, i ) { poCopied++; pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } *startMonotonePropPo = i; Vec_PtrForEachEntry( Aig_Obj_t *, vCandMonotoneProp, pObj, i ) { poCreated++; pObjPo = Aig_ObjCreateCo( pNewAig, pObj ); } //******************************************************************** // Step 9: create latch inputs //******************************************************************** Saig_ManForEachLi( pAig, pObj, i ) { liCopied++; Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //******************************************************************** // Step 9.a: create latch input for PENDING_FLOP //******************************************************************** liCreated++; Aig_ObjCreateCo( pNewAig, pObjPendingDriverNew ); //******************************************************************** // Step 9.b: create latch input for MONOTONE_FLOP //******************************************************************** Vec_PtrForEachEntry( Aig_Obj_t *, vCandMonotoneFlopInput, pObj, i ) { liCreated++; Aig_ObjCreateCo( pNewAig, pObj ); } Aig_ManSetRegNum( pNewAig, nRegCount ); Aig_ManCleanup( pNewAig ); assert( Aig_ManCheck( pNewAig ) ); assert( loCopied + loCreated == liCopied + liCreated ); Vec_PtrFree(vConseCandFlopOutput); Vec_PtrFree(vCandMonotoneProp); Vec_PtrFree(vCandMonotoneFlopInput); return pNewAig; } Vec_Int_t *findNewDisjunctiveMonotone( Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct antecedentConsequentVectorsStruct *anteConseVectors ) { Aig_Man_t *pAigNew; Aig_Obj_t *pObjTargetPo; int poMarker; //int i, RetValue, poSerialNum; int i, poSerialNum; Pdr_Par_t Pars, * pPars = &Pars; //Abc_Cex_t * pCex = NULL; Vec_Int_t *vMonotoneIndex; //char fileName[20]; Abc_Cex_t * cexElem; int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex; pAigNew = createDisjunctiveMonotoneTester(pAig, aigPoIndicesArg, anteConseVectors, &poMarker ); //printf("enter an integer : "); //waitForInteger = getchar(); //putchar(waitForInteger); vMonotoneIndex = Vec_IntAlloc(0); for( i=0; ifVerbose = 0; pPars->fNotVerbose = 1; pPars->fSolveAll = 1; pAigNew->vSeqModelVec = NULL; Pdr_ManSolve( pAigNew, pPars ); if( pAigNew->vSeqModelVec ) { Vec_PtrForEachEntry( Abc_Cex_t *, pAigNew->vSeqModelVec, cexElem, i ) { if( cexElem == NULL && i >= pendingSignalIndexLocal + 1) { poSerialNum = i - (pendingSignalIndexLocal + 1); Vec_IntPush( vMonotoneIndex, Vec_IntEntry( anteConseVectors->attrConsequentCandidates, poSerialNum )); } } } for( i=0; ivSeqModelVec) // Vec_PtrFree(pAigNew->vSeqModelVec); Aig_ManStop(pAigNew); if( Vec_IntSize( vMonotoneIndex ) > 0 ) { return vMonotoneIndex; } else { Vec_IntFree(vMonotoneIndex); return NULL; } } Vec_Int_t *updateAnteConseVectors(struct antecedentConsequentVectorsStruct *anteConse ) { Vec_Int_t *vCandMonotone; int iElem, i; //if( vKnownMonotone == NULL || Vec_IntSize(vKnownMonotone) <= 0 ) // return vHintMonotone; if( anteConse->attrAntecedents == NULL || Vec_IntSize(anteConse->attrAntecedents) <= 0 ) return anteConse->attrConsequentCandidates; vCandMonotone = Vec_IntAlloc(0); Vec_IntForEachEntry( anteConse->attrConsequentCandidates, iElem, i ) { if( Vec_IntFind( anteConse->attrAntecedents, iElem ) == -1 ) Vec_IntPush( vCandMonotone, iElem ); } return vCandMonotone; } Vec_Int_t *vectorDifference(Vec_Int_t *A, Vec_Int_t *B) { Vec_Int_t *C; int iElem, i; C = Vec_IntAlloc(0); Vec_IntForEachEntry( A, iElem, i ) { if( Vec_IntFind( B, iElem ) == -1 ) { Vec_IntPush( C, iElem ); } } return C; } Vec_Int_t *createSingletonIntVector( int iElem ) { Vec_Int_t *myVec = Vec_IntAlloc(1); Vec_IntPush(myVec, iElem); return myVec; } #if 0 Vec_Ptr_t *generateDisjuntiveMonotone_rec() { nextLevelSignals = ; if level is not exhausted for all x \in nextLevelSignals { append x in currAntecendent recond it as a monotone predicate resurse with level - 1 } } #endif #if 0 Vec_Ptr_t *generateDisjuntiveMonotoneLevels(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesInstance, struct antecedentConsequentVectorsStruct *anteConsecInstanceOrig, int level ) { Vec_Int_t *firstLevelMonotone; Vec_Int_t *currVecInt; Vec_Ptr_t *hierarchyList; int iElem, i; assert( level >= 1 ); firstLevelMonotone = findNewDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance ); if( firstLevelMonotone == NULL || Vec_IntSize(firstLevelMonotone) <= 0 ) return NULL; hierarchyList = Vec_PtrAlloc(Vec_IntSize(firstLevelMonotone)); Vec_IntForEachEntry( firstLevelMonotone, iElem, i ) { currVecInt = createSingletonIntVector( iElem ); Vec_PtrPush( hierarchyList, currVecInt ); } if( level > 1 ) { Vec_IntForEachEntry( firstLevelMonotone, iElem, i ) { currVecInt = (Vec_Int_t *)Vec_PtrEntry( hierarchyList, i ); } } return hierarchyList; } #endif int Vec_IntPushUniqueLocal( Vec_Int_t * p, int Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Vec_IntPush( p, Entry ); return 0; } Vec_Ptr_t *findNextLevelDisjunctiveMonotone( Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesInstance, struct antecedentConsequentVectorsStruct *anteConsecInstance, Vec_Ptr_t *previousMonotoneVectors ) { Vec_Ptr_t *newLevelPtrVec; Vec_Int_t *vElem, *vNewDisjunctVector, *newDisjunction; int i, j, iElem; struct antecedentConsequentVectorsStruct *anteConsecInstanceLocal; Vec_Int_t *vUnionPrevMonotoneVector, *vDiffVector; newLevelPtrVec = Vec_PtrAlloc(0); vUnionPrevMonotoneVector = Vec_IntAlloc(0); Vec_PtrForEachEntry(Vec_Int_t *, previousMonotoneVectors, vElem, i) Vec_IntForEachEntry( vElem, iElem, j ) Vec_IntPushUniqueLocal( vUnionPrevMonotoneVector, iElem ); Vec_PtrForEachEntry(Vec_Int_t *, previousMonotoneVectors, vElem, i) { anteConsecInstanceLocal = allocAntecedentConsequentVectorsStruct(); anteConsecInstanceLocal->attrAntecedents = Vec_IntDup(vElem); vDiffVector = vectorDifference( anteConsecInstance->attrConsequentCandidates, vUnionPrevMonotoneVector); anteConsecInstanceLocal->attrConsequentCandidates = vDiffVector; assert( vDiffVector ); //printf("Calling target function %d\n", i); vNewDisjunctVector = findNewDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstanceLocal ); if( vNewDisjunctVector ) { Vec_IntForEachEntry(vNewDisjunctVector, iElem, j) { newDisjunction = Vec_IntDup(vElem); Vec_IntPush( newDisjunction, iElem ); Vec_PtrPush( newLevelPtrVec, newDisjunction ); } Vec_IntFree(vNewDisjunctVector); } deallocAntecedentConsequentVectorsStruct( anteConsecInstanceLocal ); } Vec_IntFree(vUnionPrevMonotoneVector); return newLevelPtrVec; } void printAllIntVectors(Vec_Ptr_t *vDisjunctions, Abc_Ntk_t *pNtk, char *fileName) { Vec_Int_t *vElem; int i, j, iElem; char *name, *hintSubStr; FILE *fp; fp = fopen( fileName, "a" ); Vec_PtrForEachEntry(Vec_Int_t *, vDisjunctions, vElem, i) { fprintf(fp, "( "); Vec_IntForEachEntry( vElem, iElem, j ) { name = Abc_ObjName( Abc_NtkPo(pNtk, iElem)); hintSubStr = strstr( name, "hint"); assert( hintSubStr ); fprintf(fp, "%s", hintSubStr); if( j < Vec_IntSize(vElem) - 1 ) { fprintf(fp, " || "); } else { fprintf(fp, " )\n"); } } } fclose(fp); } void printAllIntVectorsStabil(Vec_Ptr_t *vDisjunctions, Abc_Ntk_t *pNtk, char *fileName) { Vec_Int_t *vElem; int i, j, iElem; char *name, *hintSubStr; FILE *fp; fp = fopen( fileName, "a" ); Vec_PtrForEachEntry(Vec_Int_t *, vDisjunctions, vElem, i) { printf("INT[%d] : ( ", i); fprintf(fp, "( "); Vec_IntForEachEntry( vElem, iElem, j ) { name = Abc_ObjName( Abc_NtkPo(pNtk, iElem)); hintSubStr = strstr( name, "csLevel1Stabil"); assert( hintSubStr ); printf("%s", hintSubStr); fprintf(fp, "%s", hintSubStr); if( j < Vec_IntSize(vElem) - 1 ) { printf(" || "); fprintf(fp, " || "); } else { printf(" )\n"); fprintf(fp, " )\n"); } } //printf(")\n"); } fclose(fp); } void appendVecToMasterVecInt(Vec_Ptr_t *masterVec, Vec_Ptr_t *candVec ) { int i; Vec_Int_t *vCand; Vec_Int_t *vNewIntVec; assert(masterVec != NULL); assert(candVec != NULL); Vec_PtrForEachEntry( Vec_Int_t *, candVec, vCand, i ) { vNewIntVec = Vec_IntDup(vCand); Vec_PtrPush(masterVec, vNewIntVec); } } void deallocateVecOfIntVec( Vec_Ptr_t *vecOfIntVec ) { Vec_Int_t *vInt; int i; if( vecOfIntVec ) { Vec_PtrForEachEntry( Vec_Int_t *, vecOfIntVec, vInt, i ) { Vec_IntFree( vInt ); } Vec_PtrFree(vecOfIntVec); } } Vec_Ptr_t *findDisjunctiveMonotoneSignals( Abc_Ntk_t *pNtk ) { Aig_Man_t *pAig; Vec_Int_t *vCandidateMonotoneSignals; Vec_Int_t *vKnownMonotoneSignals; //Vec_Int_t *vKnownMonotoneSignalsRoundTwo; //Vec_Int_t *vOldConsequentVector; //Vec_Int_t *vRemainingConsecVector; int i; int iElem; int pendingSignalIndex; Abc_Ntk_t *pNtkTemp; int hintSingalBeginningMarker; int hintSingalEndMarker; struct aigPoIndices *aigPoIndicesInstance; //struct monotoneVectorsStruct *monotoneVectorsInstance; struct antecedentConsequentVectorsStruct *anteConsecInstance; //Aig_Obj_t *safetyDriverNew; Vec_Int_t *newIntVec; Vec_Ptr_t *levelOneMonotne, *levelTwoMonotne; //Vec_Ptr_t *levelThreeMonotne; Vec_Ptr_t *vMasterDisjunctions; extern int findPendingSignal(Abc_Ntk_t *pNtk); extern Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk); extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); //system("rm monotone.dat"); /*******************************************/ //Finding the PO index of the pending signal /*******************************************/ pendingSignalIndex = findPendingSignal(pNtk); if( pendingSignalIndex == -1 ) { printf("\nNo Pending Signal Found\n"); return NULL; } //else //printf("Po[%d] = %s\n", pendingSignalIndex, Abc_ObjName( Abc_NtkPo(pNtk, pendingSignalIndex) ) ); /*******************************************/ //Finding the PO indices of all hint signals /*******************************************/ vCandidateMonotoneSignals = findHintOutputs(pNtk); if( vCandidateMonotoneSignals == NULL ) return NULL; else { //Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i ) // printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) ); hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 ); hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 ); } /**********************************************/ //Allocating "struct" with necessary parameters /**********************************************/ aigPoIndicesInstance = allocAigPoIndices(); aigPoIndicesInstance->attrPendingSignalIndex = pendingSignalIndex; aigPoIndicesInstance->attrHintSingalBeginningMarker = hintSingalBeginningMarker; aigPoIndicesInstance->attrHintSingalEndMarker = hintSingalEndMarker; aigPoIndicesInstance->attrSafetyInvarIndex = collectSafetyInvariantPOIndex(pNtk); /****************************************************/ //Allocating "struct" with necessary monotone vectors /****************************************************/ anteConsecInstance = allocAntecedentConsequentVectorsStruct(); anteConsecInstance->attrAntecedents = NULL; anteConsecInstance->attrConsequentCandidates = vCandidateMonotoneSignals; /*******************************************/ //Generate AIG from Ntk /*******************************************/ if( !Abc_NtkIsStrash( pNtk ) ) { pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkTemp = pNtk; } /*******************************************/ //finding LEVEL 1 monotone signals /*******************************************/ //printf("Calling target function outside loop\n"); vKnownMonotoneSignals = findNewDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance ); levelOneMonotne = Vec_PtrAlloc(0); Vec_IntForEachEntry( vKnownMonotoneSignals, iElem, i ) { newIntVec = createSingletonIntVector( iElem ); Vec_PtrPush( levelOneMonotne, newIntVec ); //printf("Monotone Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) ); } //printAllIntVectors( levelOneMonotne, pNtk, "monotone.dat" ); vMasterDisjunctions = Vec_PtrAlloc( Vec_PtrSize( levelOneMonotne )); appendVecToMasterVecInt(vMasterDisjunctions, levelOneMonotne ); /*******************************************/ //finding LEVEL >1 monotone signals /*******************************************/ #if 0 if( vKnownMonotoneSignals ) { Vec_IntForEachEntry( vKnownMonotoneSignals, iElem, i ) { printf("\n**************************************************************\n"); printf("Exploring Second Layer : Reference Po[%d] = %s", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) )); printf("\n**************************************************************\n"); anteConsecInstance->attrAntecedents = createSingletonIntVector( iElem ); vOldConsequentVector = anteConsecInstance->attrConsequentCandidates; vRemainingConsecVector = updateAnteConseVectors(anteConsecInstance); if( anteConsecInstance->attrConsequentCandidates != vRemainingConsecVector ) { anteConsecInstance->attrConsequentCandidates = vRemainingConsecVector; } vKnownMonotoneSignalsRoundTwo = findNewDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance ); Vec_IntForEachEntry( vKnownMonotoneSignalsRoundTwo, iElemTwo, iTwo ) { printf("Monotone Po[%d] = %s, (%d, %d)\n", iElemTwo, Abc_ObjName( Abc_NtkPo(pNtk, iElemTwo) ), iElem, iElemTwo ); } Vec_IntFree(vKnownMonotoneSignalsRoundTwo); Vec_IntFree(anteConsecInstance->attrAntecedents); if(anteConsecInstance->attrConsequentCandidates != vOldConsequentVector) { Vec_IntFree(anteConsecInstance->attrConsequentCandidates); anteConsecInstance->attrConsequentCandidates = vOldConsequentVector; } } } #endif #if 1 levelTwoMonotne = findNextLevelDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance, levelOneMonotne ); //printAllIntVectors( levelTwoMonotne, pNtk, "monotone.dat" ); appendVecToMasterVecInt(vMasterDisjunctions, levelTwoMonotne ); #endif //levelThreeMonotne = findNextLevelDisjunctiveMonotone( pAig, aigPoIndicesInstance, anteConsecInstance, levelTwoMonotne ); //printAllIntVectors( levelThreeMonotne ); //printAllIntVectors( levelTwoMonotne, pNtk, "monotone.dat" ); //appendVecToMasterVecInt(vMasterDisjunctions, levelThreeMonotne ); deallocAigPoIndices(aigPoIndicesInstance); deallocAntecedentConsequentVectorsStruct(anteConsecInstance); //deallocPointersToMonotoneVectors(monotoneVectorsInstance); deallocateVecOfIntVec( levelOneMonotne ); deallocateVecOfIntVec( levelTwoMonotne ); Aig_ManStop(pAig); Vec_IntFree(vKnownMonotoneSignals); return vMasterDisjunctions; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/kLiveConstraints.c000066400000000000000000000121021300674244400255620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kLiveConstraints.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [Constraint analysis module for the k-Liveness algorithm invented by Koen Classen, Niklas Sorensson.] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 31, 2012.] Revision [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include #include "base/main/mainInt.h" #include "proof/pdr/pdr.h" ABC_NAMESPACE_IMPL_START Aig_Obj_t *createConstrained0LiveCone( Aig_Man_t *pNewAig, Vec_Ptr_t *signalList ) { Aig_Obj_t *pConsequent, *pConsequentCopy, *pAntecedent, *p0LiveCone, *pObj; int i, numSigAntecedent; numSigAntecedent = Vec_PtrSize( signalList ) - 1; pAntecedent = Aig_ManConst1( pNewAig ); pConsequent = (Aig_Obj_t *)Vec_PtrEntry( signalList, numSigAntecedent ); pConsequentCopy = Aig_NotCond( (Aig_Obj_t *)(Aig_Regular(pConsequent)->pData), Aig_IsComplement( pConsequent ) ); for(i=0; ipData ); pAntecedent = Aig_And( pNewAig, pAntecedent, Aig_NotCond((Aig_Obj_t *)(Aig_Regular(pObj)->pData), Aig_IsComplement(pObj)) ); } p0LiveCone = Aig_Or( pNewAig, Aig_Not(pAntecedent), pConsequentCopy ); return p0LiveCone; } Vec_Ptr_t *collectCSSignals( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { int i; Aig_Obj_t *pObj, *pConsequent = NULL; Vec_Ptr_t *vNodeArray; vNodeArray = Vec_PtrAlloc(1); Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "csLiveConst_" ) != NULL ) Vec_PtrPush( vNodeArray, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)) ); else if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "csLiveTarget_" ) != NULL ) pConsequent = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } assert( pConsequent ); Vec_PtrPush( vNodeArray, pConsequent ); return vNodeArray; } Aig_Man_t *createNewAigWith0LivePo( Aig_Man_t *pAig, Vec_Ptr_t *signalList, int *index0Live ) { Aig_Man_t *pNewAig; Aig_Obj_t *pObj, *pObjNewPoDriver; int i; //assert( Vec_PtrSize( signalList ) > 1 ); //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_0Live") + 1 ); sprintf(pNewAig->pName, "%s_%s", pAig->pName, "0Live"); pNewAig->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( pAig ); pObj->pData = Aig_ManConst1( pNewAig ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCi( pNewAig ); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCi( pNewAig ); } //******************************************************************** // Step 7: create internal nodes //******************************************************************** Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } Saig_ManForEachPo( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } pObjNewPoDriver = createConstrained0LiveCone( pNewAig, signalList ); Aig_ObjCreateCo( pNewAig, pObjNewPoDriver ); *index0Live = i; Saig_ManForEachLi( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } Aig_ManSetRegNum( pNewAig, Aig_ManRegNum(pAig) ); Aig_ManCleanup( pNewAig ); assert( Aig_ManCheck( pNewAig ) ); return pNewAig; } Vec_Ptr_t *checkMonotoneSignal() { return NULL; } Vec_Ptr_t *gatherMonotoneSignals(Aig_Man_t *pAig) { int i; Aig_Obj_t *pObj; Aig_ManForEachNode( pAig, pObj, i ) { Aig_ObjPrint( pAig, pObj ); printf("\n"); } return NULL; } Aig_Man_t *generateWorkingAig( Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int *pIndex0Live ) { Vec_Ptr_t *vSignalVector; Aig_Man_t *pAigNew; vSignalVector = collectCSSignals( pNtk, pAig ); assert(vSignalVector); pAigNew = createNewAigWith0LivePo( pAig, vSignalVector, pIndex0Live ); Vec_PtrFree(vSignalVector); return pAigNew; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/kliveness.c000066400000000000000000000536361300674244400243040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kliveness.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [Main implementation module of the algorithm k-Liveness ] [invented by Koen Claessen, Niklas Sorensson. Implements] [the code for 'kcs'. 'kcs' pre-processes based on switch] [and then runs the (absorber circuit >> pdr) loop ] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 31, 2012.] ***********************************************************************/ #include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include #include "base/main/mainInt.h" #include "proof/pdr/pdr.h" #include //#define WITHOUT_CONSTRAINTS ABC_NAMESPACE_IMPL_START /***************** Declaration of standard ABC related functions ********************/ 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 Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtk, int Output, int nRange ); extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ); /***********************************************************************************/ /***************** Declaration of kLiveness related functions **********************/ //function defined in kLiveConstraints.c extern Aig_Man_t *generateWorkingAig( Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int *pIndex0Live ); //function defined in arenaViolation.c extern Aig_Man_t *generateWorkingAigWithDSC( Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int *pIndex0Live, Vec_Ptr_t *vMasterBarriers ); //function defined in disjunctiveMonotone.c extern Vec_Ptr_t *findDisjunctiveMonotoneSignals( Abc_Ntk_t *pNtk ); extern Vec_Int_t *createSingletonIntVector( int i ); /***********************************************************************************/ extern Aig_Man_t *generateDisjunctiveTester( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int combN, int combK ); extern Aig_Man_t *generateGeneralDisjunctiveTester( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, int combK ); //Definition of some macros pertaining to modes/switches #define SIMPLE_kCS 0 #define kCS_WITH_SAFETY_INVARIANTS 1 #define kCS_WITH_DISCOVER_MONOTONE_SIGNALS 2 #define kCS_WITH_SAFETY_AND_DCS_INVARIANTS 3 #define kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS 4 //unused function #if 0 Aig_Obj_t *readTargetPinSignal(Aig_Man_t *pAig, Abc_Ntk_t *pNtk) { Aig_Obj_t *pObj; int i; Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "0Liveness_" ) != NULL ) { //return Aig_ObjFanin0(pObj); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } } return NULL; } #endif Aig_Obj_t *readLiveSignal_0( Aig_Man_t *pAig, int liveIndex_0 ) { Aig_Obj_t *pObj; pObj = Aig_ManCo( pAig, liveIndex_0 ); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } Aig_Obj_t *readLiveSignal_k( Aig_Man_t *pAig, int liveIndex_k ) { Aig_Obj_t *pObj; pObj = Aig_ManCo( pAig, liveIndex_k ); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } //unused funtion #if 0 Aig_Obj_t *readTargetPoutSignal(Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int nonFirstIteration) { Aig_Obj_t *pObj; int i; if( nonFirstIteration == 0 ) return NULL; else Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "kLiveness_" ) != NULL ) { //return Aig_ObjFanin0(pObj); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } } return NULL; } #endif //unused function #if 0 void updateNewNetworkNameManager_kCS( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames, Vec_Ptr_t *vPoNames, Vec_Ptr_t *vLiNames ) { Aig_Obj_t *pObj; Abc_Obj_t *pNode; int i, ntkObjId; pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) ); if( vPiNames ) { Saig_ManForEachPi( pAig, pObj, i ) { ntkObjId = Abc_NtkCi( pNtk, i )->Id; Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL ); } } if( vLoNames ) { Saig_ManForEachLo( pAig, pObj, i ) { ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id; Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL ); } } if( vPoNames ) { Saig_ManForEachPo( pAig, pObj, i ) { ntkObjId = Abc_NtkCo( pNtk, i )->Id; Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPoNames, i), NULL ); } } if( vLiNames ) { Saig_ManForEachLi( pAig, pObj, i ) { ntkObjId = Abc_NtkCo( pNtk, Saig_ManPoNum( pAig ) + i )->Id; Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLiNames, i), NULL ); } } // assign latch input names Abc_NtkForEachLatch(pNtk, pNode, i) if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL ) Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL ); } #endif Aig_Man_t *introduceAbsorberLogic( Aig_Man_t *pAig, int *pLiveIndex_0, int *pLiveIndex_k, int nonFirstIteration ) { Aig_Man_t *pNewAig; Aig_Obj_t *pObj, *pObjAbsorberLo, *pPInNewArg, *pPOutNewArg; Aig_Obj_t *pPIn = NULL, *pPOut = NULL, *pPOutCo = NULL; Aig_Obj_t *pFirstAbsorberOr, *pSecondAbsorberOr; int i; int piCopied = 0, loCreated = 0, loCopied = 0, liCreated = 0, liCopied = 0; int nRegCount; assert(*pLiveIndex_0 != -1); if(nonFirstIteration == 0) assert( *pLiveIndex_k == -1 ); else assert( *pLiveIndex_k != -1 ); //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_kCS") + 1 ); sprintf(pNewAig->pName, "%s_%s", pAig->pName, "kCS"); pNewAig->pSpec = NULL; //**************************************************************** // reading the signal pIn, and pOut //**************************************************************** pPIn = readLiveSignal_0( pAig, *pLiveIndex_0 ); if( *pLiveIndex_k == -1 ) pPOut = NULL; else pPOut = readLiveSignal_k( pAig, *pLiveIndex_k ); //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( pAig ); pObj->pData = Aig_ManConst1( pNewAig ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( pAig, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( pAig, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //**************************************************************** // Step 6: create "D" register output for the ABSORBER logic //**************************************************************** loCreated++; pObjAbsorberLo = Aig_ObjCreateCi( pNewAig ); nRegCount = loCreated + loCopied; //******************************************************************** // Step 7: create internal nodes //******************************************************************** Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //**************************************************************** // Step 8: create the two OR gates of the OBSERVER logic //**************************************************************** if( nonFirstIteration == 0 ) { assert(pPIn); pPInNewArg = !Aig_IsComplement(pPIn)? (Aig_Obj_t *)((Aig_Regular(pPIn))->pData) : Aig_Not((Aig_Obj_t *)((Aig_Regular(pPIn))->pData)); pFirstAbsorberOr = Aig_Or( pNewAig, Aig_Not(pPInNewArg), pObjAbsorberLo ); pSecondAbsorberOr = Aig_Or( pNewAig, pPInNewArg, Aig_Not(pObjAbsorberLo) ); } else { assert( pPOut ); pPInNewArg = !Aig_IsComplement(pPIn)? (Aig_Obj_t *)((Aig_Regular(pPIn))->pData) : Aig_Not((Aig_Obj_t *)((Aig_Regular(pPIn))->pData)); pPOutNewArg = !Aig_IsComplement(pPOut)? (Aig_Obj_t *)((Aig_Regular(pPOut))->pData) : Aig_Not((Aig_Obj_t *)((Aig_Regular(pPOut))->pData)); pFirstAbsorberOr = Aig_Or( pNewAig, Aig_Not(pPOutNewArg), pObjAbsorberLo ); pSecondAbsorberOr = Aig_Or( pNewAig, pPInNewArg, Aig_Not(pObjAbsorberLo) ); } //******************************************************************** // Step 9: create primary outputs //******************************************************************** Saig_ManForEachPo( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); if( i == *pLiveIndex_k ) pPOutCo = (Aig_Obj_t *)(pObj->pData); } //create new po if( nonFirstIteration == 0 ) { assert(pPOutCo == NULL); pPOutCo = Aig_ObjCreateCo( pNewAig, pSecondAbsorberOr ); *pLiveIndex_k = i; } else { assert( pPOutCo != NULL ); //pPOutCo = Aig_ObjCreateCo( pNewAig, pSecondAbsorberOr ); //*pLiveIndex_k = Saig_ManPoNum(pAig); Aig_ObjPatchFanin0( pNewAig, pPOutCo, pSecondAbsorberOr ); } Saig_ManForEachLi( pAig, pObj, i ) { liCopied++; Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //create new li liCreated++; Aig_ObjCreateCo( pNewAig, pFirstAbsorberOr ); Aig_ManSetRegNum( pNewAig, nRegCount ); Aig_ManCleanup( pNewAig ); assert( Aig_ManCheck( pNewAig ) ); assert( *pLiveIndex_k != - 1); return pNewAig; } void modifyAigToApplySafetyInvar(Aig_Man_t *pAig, int csTarget, int safetyInvarPO) { Aig_Obj_t *pObjPOSafetyInvar, *pObjSafetyInvar; Aig_Obj_t *pObjPOCSTarget, *pObjCSTarget; Aig_Obj_t *pObjCSTargetNew; pObjPOSafetyInvar = Aig_ManCo( pAig, safetyInvarPO ); pObjSafetyInvar = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPOSafetyInvar), Aig_ObjFaninC0(pObjPOSafetyInvar)); pObjPOCSTarget = Aig_ManCo( pAig, csTarget ); pObjCSTarget = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPOCSTarget), Aig_ObjFaninC0(pObjPOCSTarget)); pObjCSTargetNew = Aig_And( pAig, pObjSafetyInvar, pObjCSTarget ); Aig_ObjPatchFanin0( pAig, pObjPOCSTarget, pObjCSTargetNew ); } int flipConePdr( Aig_Man_t *pAig, int directive, int targetCSPropertyIndex, int safetyInvariantPOIndex, int absorberCount ) { int RetValue, i; Aig_Obj_t *pObjTargetPo; Aig_Man_t *pAigDupl; Pdr_Par_t Pars, * pPars = &Pars; Abc_Cex_t * pCex = NULL; char *fileName; fileName = (char *)malloc(sizeof(char) * 50); sprintf(fileName, "%s_%d.%s", "kLive", absorberCount, "blif" ); if( directive == kCS_WITH_SAFETY_INVARIANTS || directive == kCS_WITH_SAFETY_AND_DCS_INVARIANTS || directive == kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS ) { assert( safetyInvariantPOIndex != -1 ); modifyAigToApplySafetyInvar(pAig, targetCSPropertyIndex, safetyInvariantPOIndex); } pAigDupl = pAig; pAig = Aig_ManDupSimple( pAigDupl ); for( i=0; ifVerbose = 1; pPars->fNotVerbose = 1; pPars->fSolveAll = 1; pAig->vSeqModelVec = NULL; Aig_ManCleanup( pAig ); assert( Aig_ManCheck( pAig ) ); Pdr_ManSolve( pAig, pPars ); if( pAig->vSeqModelVec ) { pCex = (Abc_Cex_t *)Vec_PtrEntry( pAig->vSeqModelVec, targetCSPropertyIndex ); if( pCex == NULL ) { RetValue = 1; } else RetValue = 0; } else { RetValue = -1; exit(0); } free(fileName); for( i=0; i 0 ) return monotoneVector; else return NULL; } void deallocateMasterBarrierDisjunctInt(Vec_Ptr_t *vMasterBarrierDisjunctsArg) { Vec_Int_t *vInt; int i; if(vMasterBarrierDisjunctsArg) { Vec_PtrForEachEntry(Vec_Int_t *, vMasterBarrierDisjunctsArg, vInt, i) { Vec_IntFree(vInt); } Vec_PtrFree(vMasterBarrierDisjunctsArg); } } void deallocateMasterBarrierDisjunctVecPtrVecInt(Vec_Ptr_t *vMasterBarrierDisjunctsArg) { Vec_Int_t *vInt; Vec_Ptr_t *vPtr; int i, j, k, iElem; if(vMasterBarrierDisjunctsArg) { Vec_PtrForEachEntry(Vec_Ptr_t *, vMasterBarrierDisjunctsArg, vPtr, i) { assert(vPtr); Vec_PtrForEachEntry( Vec_Int_t *, vPtr, vInt, j ) { //Vec_IntFree(vInt); Vec_IntForEachEntry( vInt, iElem, k ) printf("%d - ", iElem); //printf("Chung Chang j = %d\n", j); } Vec_PtrFree(vPtr); } Vec_PtrFree(vMasterBarrierDisjunctsArg); } } Vec_Ptr_t *getVecOfVecFairness(FILE *fp) { Vec_Ptr_t *masterVector = Vec_PtrAlloc(0); //Vec_Ptr_t *currSignalVector; char stringBuffer[100]; //int i; while(fgets(stringBuffer, 50, fp)) { if(strstr(stringBuffer, ":")) { } else { } } return masterVector; } int Abc_CommandCS_kLiveness( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkTemp; Aig_Man_t * pAig, *pAigCS, *pAigCSNew; int absorberCount; int absorberLimit = 500; int RetValue; int liveIndex_0 = -1, liveIndex_k = -1; int fVerbose = 1; int directive = -1; int c; int safetyInvariantPO = -1; abctime beginTime, endTime; double time_spent; Vec_Ptr_t *vMasterBarrierDisjuncts = NULL; Aig_Man_t *pWorkingAig; //FILE *fp; pNtk = Abc_FrameReadNtk(pAbc); //fp = fopen("propFile.txt", "r"); //if( fp ) // getVecOfVecFairness(fp); //exit(0); /************************************************* Extraction of Command Line Argument *************************************************/ if( argc == 1 ) { assert( directive == -1 ); directive = SIMPLE_kCS; } else { Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cmCgh" ) ) != EOF ) { switch( c ) { case 'c': directive = kCS_WITH_SAFETY_INVARIANTS; break; case 'm': directive = kCS_WITH_DISCOVER_MONOTONE_SIGNALS; break; case 'C': directive = kCS_WITH_SAFETY_AND_DCS_INVARIANTS; break; case 'g': directive = kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS; break; case 'h': goto usage; break; default: goto usage; } } } /************************************************* Extraction of Command Line Argument Ends *************************************************/ if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkTemp = pNtk; } if( directive == kCS_WITH_SAFETY_INVARIANTS ) { safetyInvariantPO = collectSafetyInvariantPOIndex(pNtkTemp); assert( safetyInvariantPO != -1 ); } if(directive == kCS_WITH_DISCOVER_MONOTONE_SIGNALS) { beginTime = Abc_Clock(); vMasterBarrierDisjuncts = findDisjunctiveMonotoneSignals( pNtk ); endTime = Abc_Clock(); time_spent = (double)(endTime - beginTime)/CLOCKS_PER_SEC; printf("pre-processing time = %f\n",time_spent); return 0; } if(directive == kCS_WITH_SAFETY_AND_DCS_INVARIANTS) { safetyInvariantPO = collectSafetyInvariantPOIndex(pNtkTemp); assert( safetyInvariantPO != -1 ); beginTime = Abc_Clock(); vMasterBarrierDisjuncts = findDisjunctiveMonotoneSignals( pNtk ); endTime = Abc_Clock(); time_spent = (double)(endTime - beginTime)/CLOCKS_PER_SEC; printf("pre-processing time = %f\n",time_spent); assert( vMasterBarrierDisjuncts != NULL ); assert( Vec_PtrSize(vMasterBarrierDisjuncts) > 0 ); } if(directive == kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS) { safetyInvariantPO = collectSafetyInvariantPOIndex(pNtkTemp); assert( safetyInvariantPO != -1 ); beginTime = Abc_Clock(); vMasterBarrierDisjuncts = collectUserGivenDisjunctiveMonotoneSignals( pNtk ); endTime = Abc_Clock(); time_spent = (double)(endTime - beginTime)/CLOCKS_PER_SEC; printf("pre-processing time = %f\n",time_spent); assert( vMasterBarrierDisjuncts != NULL ); assert( Vec_PtrSize(vMasterBarrierDisjuncts) > 0 ); } if(directive == kCS_WITH_SAFETY_AND_DCS_INVARIANTS || directive == kCS_WITH_SAFETY_AND_USER_GIVEN_DCS_INVARIANTS) { assert( vMasterBarrierDisjuncts != NULL ); pWorkingAig = generateWorkingAigWithDSC( pAig, pNtk, &liveIndex_0, vMasterBarrierDisjuncts ); pAigCS = introduceAbsorberLogic(pWorkingAig, &liveIndex_0, &liveIndex_k, 0); } else { pWorkingAig = generateWorkingAig( pAig, pNtk, &liveIndex_0 ); pAigCS = introduceAbsorberLogic(pWorkingAig, &liveIndex_0, &liveIndex_k, 0); } Aig_ManStop(pWorkingAig); for( absorberCount=1; absorberCountpName = Abc_UtilStrsav( pAigCombStabil->pName ); if ( !Abc_NtkCheck( pNtkCombStabil ) ) fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); Abc_FrameSetCurrentNetwork( pAbc, pNtkCombStabil ); Aig_ManStop( pAigCombStabil ); Aig_ManStop( pAig ); return 1; //printf("\ncombCount = %d\n", combCount); //exit(0); /**********************************************************/ usage: fprintf( stdout, "usage: nck [-cmgCh]\n" ); fprintf( stdout, "\tgenerates combinatorial signals for stabilization\n" ); fprintf( stdout, "\t-h : print usage\n"); return 1; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/liveness.c000066400000000000000000002757301300674244400241320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [liveness.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [Main implementation module.] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2009.] Revision [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START #define PROPAGATE_NAMES #define MULTIPLE_LTL_FORMULA #define ALLOW_SAFETY_PROPERTIES #define FULL_BIERE_MODE 0 #define IGNORE_LIVENESS_KEEP_SAFETY_MODE 1 #define IGNORE_SAFETY_KEEP_LIVENESS_MODE 2 #define IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE 3 #define FULL_BIERE_ONE_LOOP_MODE 4 //#define DUPLICATE_CKT_DEBUG extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); //char *strdup(const char *string); //****************************************** //external functions defined in ltl_parser.c //****************************************** typedef struct ltlNode_t ltlNode; extern ltlNode *readLtlFormula( char *formula ); extern void traverseAbstractSyntaxTree( ltlNode *node ); extern ltlNode *parseFormulaCreateAST( char *inputFormula ); extern int isWellFormed( ltlNode *topNode ); extern int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode ); extern void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode ); extern int checkAllBoolHaveAIGPointer( ltlNode *topASTNode ); extern void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap ); extern void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo ); extern Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode ); extern Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode ); extern void traverseAbstractSyntaxTree_postFix( ltlNode *node ); //********************************** //external function declaration ends //********************************** /******************************************************************* LAYOUT OF PI VECTOR: +------------------------------------------------------------------------------------------------------------------------------------+ | TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) | +------------------------------------------------------------------------------------------------------------------------------------+ <------------True PI----------------->|<----------------------------LO---------------------------------------------------------------> LAYOUT OF PO VECTOR: +-----------------------------------------------------------------------------------------------------------+ | SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) | +-----------------------------------------------------------------------------------------------------------+ <--True PO--->|<--------------------------------------LI----------------------------------------------------> ********************************************************************/ static int nodeName_starts_with( Abc_Obj_t *pNode, const char *prefix ) { if( strstr( Abc_ObjName( pNode ), prefix ) == Abc_ObjName( pNode ) ) return 1; else return 0; } void printVecPtrOfString( Vec_Ptr_t *vec ) { int i; for( i=0; i< Vec_PtrSize( vec ); i++ ) { printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) ); } } int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot ) { int i; Aig_Obj_t *pObj; Saig_ManForEachPo( pAig, pObj, i ) { if( pObj == pPivot ) return i; } return -1; } char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot ) { Aig_Obj_t *pObjOld, *pObj; Abc_Obj_t *pNode; int index; assert( Saig_ObjIsPi( pAigNew, pObjPivot ) ); Aig_ManForEachCi( pAigNew, pObj, index ) if( pObj == pObjPivot ) break; assert( index < Aig_ManCiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) ); if( index == Saig_ManPiNum( pAigNew ) - 1 ) return "SAVE_BIERE"; else { pObjOld = Aig_ManCi( pAigOld, index ); pNode = Abc_NtkPi( pNtkOld, index ); assert( pObjOld->pData == pObjPivot ); return Abc_ObjName( pNode ); } } char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair ) { Aig_Obj_t *pObjOld, *pObj; Abc_Obj_t *pNode; int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i; char *dummyStr = (char *)malloc( sizeof(char) * 50 ); assert( Saig_ObjIsLo( pAigNew, pObjPivot ) ); Saig_ManForEachLo( pAigNew, pObj, index ) if( pObj == pObjPivot ) break; if( index < originalLatchNum ) { oldIndex = Saig_ManPiNum( pAigOld ) + index; pObjOld = Aig_ManCi( pAigOld, oldIndex ); pNode = Abc_NtkCi( pNtkOld, oldIndex ); assert( pObjOld->pData == pObjPivot ); return Abc_ObjName( pNode ); } else if( index == originalLatchNum ) return "SAVED_LO"; else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 ) { oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1; pObjOld = Aig_ManCi( pAigOld, oldIndex ); pNode = Abc_NtkCi( pNtkOld, oldIndex ); sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW"); return dummyStr; } else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) ) { oldIndex = index - 2 * originalLatchNum - 1; strMatch = 0; dummyStr[0] = '\0'; Saig_ManForEachPo( pAigOld, pObj, i ) { pNode = Abc_NtkPo( pNtkOld, i ); //if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL ) if( nodeName_starts_with( pNode, "assert_fair" ) ) { if( strMatch == oldIndex ) { sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS"); //return dummyStr; break; } else strMatch++; } } assert( dummyStr[0] != '\0' ); return dummyStr; } else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ) { oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive ); strMatch = 0; dummyStr[0] = '\0'; Saig_ManForEachPo( pAigOld, pObj, i ) { pNode = Abc_NtkPo( pNtkOld, i ); //if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL ) if( nodeName_starts_with( pNode, "assume_fair" ) ) { if( strMatch == oldIndex ) { sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS"); //return dummyStr; break; } else strMatch++; } } assert( dummyStr[0] != '\0' ); return dummyStr; } else return "UNKNOWN"; } Vec_Ptr_t *vecPis, *vecPiNames; Vec_Ptr_t *vecLos, *vecLoNames; int Aig_ManCiCleanupBiere( Aig_Man_t * p ) { int nPisOld = Aig_ManCiNum(p); 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); } int Aig_ManCoCleanupBiere( Aig_Man_t * p ) { int nPosOld = Aig_ManCoNum(p); 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); } Aig_Man_t * LivenessToSafetyTransformation( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) { Aig_Man_t * pNew; int i, nRegCount; Aig_Obj_t * pObjSavePi = NULL; Aig_Obj_t *pObjSavedLo = NULL, *pObjSavedLi = NULL; Aig_Obj_t *pObj, *pMatch; Aig_Obj_t *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL, *pObjSavedLoAndEquality; Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; Aig_Obj_t *pObjSafetyPropertyOutput = NULL; Aig_Obj_t *pObjOriginalSafetyPropertyOutput; Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; char *nodeName; int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0, fairLatch = 0; vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 ); sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s"); pNew->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( p, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecPis, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 4: create the special Pi corresponding to SAVE //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { pObjSavePi = Aig_ObjCreateCi( pNew ); nodeName = "SAVE_BIERE", Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( p, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecLos, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 6: create "saved" register output //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { loCreated++; pObjSavedLo = Aig_ObjCreateCi( pNew ); Vec_PtrPush( vecLos, pObjSavedLo ); nodeName = "SAVED_LO"; Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); } //******************************************************************** // Step 8: create internal nodes //******************************************************************** Aig_ManForEachNode( p, pObj, i ) { pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 8.x : create PO for each safety assertions // NOTE : Here the output is purposely inverted as it will be thrown to // dprove //******************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) { if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) { pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) ); } else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) { pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } collectiveAssertSafety = pObjAndAcc; pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } collectiveAssumeSafety = pObjAndAcc; pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); } else { printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); } } //******************************************************************** // Step 9: create the safety property output gate for the liveness properties // discuss with Sat/Alan for an alternative implementation //******************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); } // create register inputs for the original registers nRegCount = 0; Saig_ManForEachLo( p, pObj, i ) { pMatch = Saig_ObjLoToLi( p, pObj ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); nRegCount++; liCopied++; } // create register input corresponding to the register "saved" if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { #ifndef DUPLICATE_CKT_DEBUG pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); nRegCount++; liCreated++; //Changed on October 13, 2009 //pObjAndAcc = NULL; pObjAndAcc = Aig_ManConst1( pNew ); // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator Saig_ManForEachLo( p, pObj, i ) { pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); pObjXnor = Aig_Not( pObjXor ); pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); } // create the AND gate whose output will be the signal "looped" pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); // create the master AND gate and corresponding AND and OR logic for the liveness properties pObjAndAcc = Aig_ManConst1( pNew ); if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) { printf("Circuit without any liveness property\n"); } else { Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) { liveLatch++; pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); } } pObjLive = pObjAndAcc; pObjAndAcc = Aig_ManConst1( pNew ); if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) printf("Circuit without any fairness property\n"); else { Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) { fairLatch++; pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); } } pObjFair = pObjAndAcc; //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); //Following is the actual Biere translation pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); #endif } Aig_ManSetRegNum( pNew, nRegCount ); Aig_ManCiCleanupBiere( pNew ); Aig_ManCoCleanupBiere( pNew ); Aig_ManCleanup( pNew ); assert( Aig_ManCheck( pNew ) ); if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); } return pNew; } Aig_Man_t * LivenessToSafetyTransformationAbs( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Int_t *vFlops, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) { Aig_Man_t * pNew; int i, nRegCount, iEntry; Aig_Obj_t * pObjSavePi = NULL; Aig_Obj_t *pObjSavedLi = NULL, *pObjSavedLo = NULL; Aig_Obj_t *pObj, *pMatch; Aig_Obj_t *pObjSavedLoAndEquality, *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL; Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; Aig_Obj_t *pObjSafetyPropertyOutput = NULL; Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; char *nodeName; int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0, fairLatch = 0;//, piVecIndex = 0; vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecLos = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 ); sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s"); pNew->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( p, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecPis, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 4: create the special Pi corresponding to SAVE //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { pObjSavePi = Aig_ObjCreateCi( pNew ); nodeName = "SAVE_BIERE", Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( p, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecLos, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 6: create "saved" register output //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { loCreated++; pObjSavedLo = Aig_ObjCreateCi( pNew ); Vec_PtrPush( vecLos, pObjSavedLo ); nodeName = "SAVED_LO"; Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); } //******************************************************************** // Step 8: create internal nodes //******************************************************************** Aig_ManForEachNode( p, pObj, i ) { pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 8.x : create PO for each safety assertions // NOTE : Here the output is purposely inverted as it will be thrown to // dprove //******************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) { if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) { pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) ); } else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) { pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } collectiveAssertSafety = pObjAndAcc; pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } collectiveAssumeSafety = pObjAndAcc; Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); } else { printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); } } //******************************************************************** // Step 9: create the safety property output gate for the liveness properties // discuss with Sat/Alan for an alternative implementation //******************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); } // create register inputs for the original registers nRegCount = 0; Saig_ManForEachLo( p, pObj, i ) { pMatch = Saig_ObjLoToLi( p, pObj ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); nRegCount++; liCopied++; } // create register input corresponding to the register "saved" if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { #ifndef DUPLICATE_CKT_DEBUG pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); nRegCount++; liCreated++; //Changed on October 13, 2009 //pObjAndAcc = NULL; pObjAndAcc = Aig_ManConst1( pNew ); // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator //Saig_ManForEachLo( p, pObj, i ) Saig_ManForEachLo( p, pObj, i ) { printf("Flop[%d] = %s\n", i, Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ); } Vec_IntForEachEntry( vFlops, iEntry, i ) { pObjShadowLo = Aig_ObjCreateCi( pNew ); pObj = Aig_ManLo( p, iEntry ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ) ) + 10 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ), "SHADOW" ); printf("Flop copied [%d] = %s\n", iEntry, nodeName ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); pObjXnor = Aig_Not( pObjXor ); pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); } // create the AND gate whose output will be the signal "looped" pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); // create the master AND gate and corresponding AND and OR logic for the liveness properties pObjAndAcc = Aig_ManConst1( pNew ); if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) { printf("Circuit without any liveness property\n"); } else { Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) { liveLatch++; pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); } } pObjLive = pObjAndAcc; pObjAndAcc = Aig_ManConst1( pNew ); if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) printf("Circuit without any fairness property\n"); else { Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) { fairLatch++; pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); } } pObjFair = pObjAndAcc; //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); //Following is the actual Biere translation pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); #endif } Aig_ManSetRegNum( pNew, nRegCount ); Aig_ManCiCleanupBiere( pNew ); Aig_ManCoCleanupBiere( pNew ); Aig_ManCleanup( pNew ); assert( Aig_ManCheck( pNew ) ); if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + liveLatch + fairLatch ); } return pNew; } Aig_Man_t * LivenessToSafetyTransformationOneStepLoop( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) { Aig_Man_t * pNew; int i, nRegCount; Aig_Obj_t * pObjSavePi = NULL; Aig_Obj_t *pObj, *pMatch; Aig_Obj_t *pObjSavedLoAndEquality; Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; Aig_Obj_t *pObjSafetyPropertyOutput = NULL; Aig_Obj_t *pDriverImage; Aig_Obj_t *pObjCorrespondingLi; Aig_Obj_t *pArgument; Aig_Obj_t *collectiveAssertSafety, *collectiveAssumeSafety; char *nodeName; int piCopied = 0, liCopied = 0, loCopied = 0;//, liCreated = 0, loCreated = 0, piVecIndex = 0; if( Aig_ManRegNum( p ) == 0 ) { printf("The input AIG contains no register, returning the original AIG as it is\n"); return p; } vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( "live2safe" ); pNew->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( p, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecPis, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 4: create the special Pi corresponding to SAVE //**************************************************************** if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) { pObjSavePi = Aig_ObjCreateCi( pNew ); nodeName = "SAVE_BIERE", Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( p, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecLos, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 6: create "saved" register output //**************************************************************** #if 0 loCreated++; pObjSavedLo = Aig_ObjCreateCi( pNew ); Vec_PtrPush( vecLos, pObjSavedLo ); nodeName = "SAVED_LO"; Vec_PtrPush( vecLoNames, nodeName ); #endif //**************************************************************** // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi //**************************************************************** #if 0 pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); #endif //******************************************************************** // Step 8: create internal nodes //******************************************************************** Aig_ManForEachNode( p, pObj, i ) { pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } #if 0 //******************************************************************** // Step 8.x : create PO for each safety assertions //******************************************************************** Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); } #endif if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) { if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) { pObjAndAcc = NULL; Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { //pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); if( pObjAndAcc == NULL ) pObjAndAcc = pArgument; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); } } Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) ); } else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) { pObjAndAcc = NULL; Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { //pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); if( pObjAndAcc == NULL ) pObjAndAcc = pArgument; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); } } collectiveAssertSafety = pObjAndAcc; pObjAndAcc = NULL; Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) { //pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); if( pObjAndAcc == NULL ) pObjAndAcc = pArgument; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); } } collectiveAssumeSafety = pObjAndAcc; Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); } else printf("No safety property is specified, hence no safety gate is created\n"); } //******************************************************************** // Step 9: create the safety property output gate // create the safety property output gate, this will be the sole true PO // of the whole circuit, discuss with Sat/Alan for an alternative implementation //******************************************************************** if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) { pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); } // create register inputs for the original registers nRegCount = 0; Saig_ManForEachLo( p, pObj, i ) { pMatch = Saig_ObjLoToLi( p, pObj ); //Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); nRegCount++; liCopied++; } #if 0 // create register input corresponding to the register "saved" pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); nRegCount++; liCreated++;7 #endif pObjAndAcc = NULL; //**************************************************************************************************** //For detection of loop of length 1 we do not need any shadow register, we only need equality detector //between Lo_j and Li_j and then a cascade of AND gates //**************************************************************************************************** if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) { Saig_ManForEachLo( p, pObj, i ) { pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj ); pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) ); pObjXnor = Aig_Not( pObjXor ); if( pObjAndAcc == NULL ) pObjAndAcc = pObjXnor; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); } } // create the AND gate whose output will be the signal "looped" pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc ); // create the master AND gate and corresponding AND and OR logic for the liveness properties pObjAndAcc = NULL; if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) printf("Circuit without any liveness property\n"); else { Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) { pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); if( pObjAndAcc == NULL ) pObjAndAcc = pDriverImage; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); } } } if( pObjAndAcc != NULL ) pObjLive = pObjAndAcc; else pObjLive = Aig_ManConst1( pNew ); // create the master AND gate and corresponding AND and OR logic for the fairness properties pObjAndAcc = NULL; if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) printf("Circuit without any fairness property\n"); else { Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) { pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); if( pObjAndAcc == NULL ) pObjAndAcc = pDriverImage; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); } } } if( pObjAndAcc != NULL ) pObjFair = pObjAndAcc; else pObjFair = Aig_ManConst1( pNew ); pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); } Aig_ManSetRegNum( pNew, nRegCount ); //printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vPis ), pNew->nRegs ); Aig_ManCiCleanupBiere( pNew ); Aig_ManCoCleanupBiere( pNew ); Aig_ManCleanup( pNew ); assert( Aig_ManCheck( pNew ) ); return pNew; } Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { Abc_Obj_t * pNode; int i, liveCounter = 0; Vec_Ptr_t * vLive; vLive = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pNode, i ) //if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL ) if( nodeName_starts_with( pNode, "assert_fair" ) ) { Vec_PtrPush( vLive, Aig_ManCo( pAig, i ) ); liveCounter++; } printf("Number of liveness property found = %d\n", liveCounter); return vLive; } Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { Abc_Obj_t * pNode; int i, fairCounter = 0; Vec_Ptr_t * vFair; vFair = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pNode, i ) //if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL ) if( nodeName_starts_with( pNode, "assume_fair" ) ) { Vec_PtrPush( vFair, Aig_ManCo( pAig, i ) ); fairCounter++; } printf("Number of fairness property found = %d\n", fairCounter); return vFair; } Vec_Ptr_t * populateSafetyAssertionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { Abc_Obj_t * pNode; int i, assertSafetyCounter = 0; Vec_Ptr_t * vAssertSafety; vAssertSafety = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pNode, i ) //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL ) if( nodeName_starts_with( pNode, "assert_safety" ) || nodeName_starts_with( pNode, "Assert" )) { Vec_PtrPush( vAssertSafety, Aig_ManCo( pAig, i ) ); assertSafetyCounter++; } printf("Number of safety property found = %d\n", assertSafetyCounter); return vAssertSafety; } Vec_Ptr_t * populateSafetyAssumptionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { Abc_Obj_t * pNode; int i, assumeSafetyCounter = 0; Vec_Ptr_t * vAssumeSafety; vAssumeSafety = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pNode, i ) //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL ) if( nodeName_starts_with( pNode, "assume_safety" ) || nodeName_starts_with( pNode, "Assume" )) { Vec_PtrPush( vAssumeSafety, Aig_ManCo( pAig, i ) ); assumeSafetyCounter++; } printf("Number of assume_safety property found = %d\n", assumeSafetyCounter); return vAssumeSafety; } void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames ) { Aig_Obj_t *pObj; Abc_Obj_t *pNode; int i, ntkObjId; pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) ); if( vPiNames ) { Saig_ManForEachPi( pAig, pObj, i ) { ntkObjId = Abc_NtkCi( pNtk, i )->Id; //printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId); Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL ); } } if( vLoNames ) { Saig_ManForEachLo( pAig, pObj, i ) { ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id; //printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId); Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL ); } } Abc_NtkForEachPo(pNtk, pNode, i) { Abc_ObjAssignName(pNode, "assert_safety_", Abc_ObjName(pNode) ); } // assign latch input names Abc_NtkForEachLatch(pNtk, pNode, i) if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL ) Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL ); } int Abc_CommandAbcLivenessToSafety( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; Aig_Man_t * pAig, *pAigNew = NULL; int c; Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; int directive = -1; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); if( argc == 1 ) { assert( directive == -1 ); directive = FULL_BIERE_MODE; } else { Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF ) { switch( c ) { case '1': if( directive == -1 ) directive = FULL_BIERE_ONE_LOOP_MODE; else { assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; else directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; } break; case 's': if( directive == -1 ) directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; else { if( directive != FULL_BIERE_ONE_LOOP_MODE ) goto usage; assert(directive == FULL_BIERE_ONE_LOOP_MODE); directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; } break; case 'l': if( directive == -1 ) directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; else { if( directive != FULL_BIERE_ONE_LOOP_MODE ) goto usage; assert(directive == FULL_BIERE_ONE_LOOP_MODE); directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; } break; case 'h': goto usage; default: goto usage; } } } if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } switch( directive ) { case FULL_BIERE_MODE: //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) //{ // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); // return 1; //} //else //{ pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); break; //} case FULL_BIERE_ONE_LOOP_MODE: //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) //{ // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); // return 1; //} //else //{ pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); break; //} case IGNORE_LIVENESS_KEEP_SAFETY_MODE: //if( Vec_PtrSize(vAssertSafety) == 0 ) //{ // printf("Input circuit has NO safety property, original network is not disturbed\n"); // return 1; //} //else //{ pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); break; //} case IGNORE_SAFETY_KEEP_LIVENESS_MODE: //if( Vec_PtrSize(vLive) == 0 ) //{ // printf("Input circuit has NO liveness property, original network is not disturbed\n"); // return 1; //} //else //{ pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); break; //} case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: //if( Vec_PtrSize(vLive) == 0 ) //{ // printf("Input circuit has NO liveness property, original network is not disturbed\n"); // return 1; //} //else //{ pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); break; //} } #if 0 if( argc == 1 ) { pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n"); } else { Extra_UtilGetoptReset(); c = Extra_UtilGetopt( argc, argv, "1lsh" ); if( c == '1' ) { if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); } else if( c == 'l' ) { if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n"); } else if( c == 's' ) { if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n"); } else if( c == 'h' ) goto usage; else goto usage; } #endif #if 0 Aig_ManPrintStats( pAigNew ); printf("\nDetail statistics*************************************\n"); printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); printf("\n*******************************************************\n"); #endif pNtkNew = Abc_NtkFromAigPhase( pAigNew ); pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames ); Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); #if 0 #ifndef DUPLICATE_CKT_DEBUG Saig_ManForEachPi( pAigNew, pObj, i ) assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); Saig_ManForEachLo( pAigNew, pObj, i ) assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); #endif #endif return 0; usage: fprintf( stdout, "usage: l2s [-1lsh]\n" ); fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); fprintf( stdout, "\t-h : print command usage\n"); return 1; } Vec_Int_t * prepareFlopVector( Aig_Man_t * pAig, int vectorLength ) { Vec_Int_t *vFlops; int i; vFlops = Vec_IntAlloc( vectorLength ); for( i=0; ipName = Abc_UtilStrsav( pAigNew->pName ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames ); Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); #if 0 #ifndef DUPLICATE_CKT_DEBUG Saig_ManForEachPi( pAigNew, pObj, i ) assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); Saig_ManForEachLo( pAigNew, pObj, i ) assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); #endif #endif return 0; usage: fprintf( stdout, "usage: l2s [-1lsh]\n" ); fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); fprintf( stdout, "\t-h : print command usage\n"); return 1; } Aig_Man_t * LivenessToSafetyTransformationWithLTL( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety, int *numLtlProcessed, Vec_Ptr_t *ltlBuffer ) { Aig_Man_t * pNew; int i, ii, iii, nRegCount; Aig_Obj_t * pObjSavePi = NULL; Aig_Obj_t *pObjSavedLo = NULL, *pObjSavedLi = NULL; Aig_Obj_t *pObj, *pMatch; Aig_Obj_t *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL, *pObjSavedLoAndEquality; Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; Aig_Obj_t *pObjLive, *pObjSafetyGate; Aig_Obj_t *pObjSafetyPropertyOutput; Aig_Obj_t *pObjOriginalSafetyPropertyOutput; Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; Aig_Obj_t *pNegatedSafetyConjunction = NULL; Aig_Obj_t *pObjSafetyAndLiveToSafety; char *nodeName, *pFormula; int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0;//, piVecIndex = 0, fairLatch = 0; Vec_Ptr_t *vSignal, *vTopASTNodeArray = NULL; ltlNode *pEnrtyGLOBALLY; ltlNode *topNodeOfAST, *tempTopASTNode; Vec_Vec_t *vAigGFMap; Vec_Ptr_t *vSignalMemory, *vGFFlopMemory, *vPoForLtlProps = NULL; Vec_Ptr_t *vecInputLtlFormulae; vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); //**************************************************************** //step0: Parsing the LTL formula //**************************************************************** //Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pFormula, i ) // printf("\ninput LTL formula [%d] = %s\n", i, pFormula ); #ifdef MULTIPLE_LTL_FORMULA //*************************************************************************** //Reading input LTL formulae from Ntk data-structure and creating //AST for them, Steps involved: // parsing -> AST creation -> well-formedness check -> signal name check //*************************************************************************** //resetting numLtlProcessed *numLtlProcessed = 0; if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { //if( ltlBuffer ) vecInputLtlFormulae = ltlBuffer; //vecInputLtlFormulae = pNtk->vLtlProperties; if( vecInputLtlFormulae ) { vTopASTNodeArray = Vec_PtrAlloc( Vec_PtrSize( vecInputLtlFormulae ) ); printf("\n"); Vec_PtrForEachEntry( char *, vecInputLtlFormulae, pFormula, i ) { tempTopASTNode = parseFormulaCreateAST( pFormula ); //traverseAbstractSyntaxTree_postFix( tempTopASTNode ); if( tempTopASTNode ) { printf("Formula %d: AST is created, ", i+1); if( isWellFormed( tempTopASTNode ) ) printf("Well-formedness check PASSED, "); else { printf("Well-formedness check FAILED!!\n"); printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 ); //do memory management to free the created AST continue; } if( checkSignalNameExistence( pNtk, tempTopASTNode ) ) printf("Signal check PASSED\n"); else { printf("Signal check FAILED!!"); printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 ); //do memory management to free the created AST continue; } Vec_PtrPush( vTopASTNodeArray, tempTopASTNode ); (*numLtlProcessed)++; } else printf("\nNo AST has been created for formula %d, no extra logic will be added\n", i+1 ); } } printf("\n"); if( Vec_PtrSize( vTopASTNodeArray ) == 0 ) { //printf("\nNo AST has been created for any formula; hence the circuit is left untouched\n"); printf("\nCurrently aborting, need to take care when Vec_PtrSize( vTopASTNodeArray ) == 0\n"); exit(0); } } //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l3s") + 1 ); sprintf(pNew->pName, "%s_%s", pNtk->pName, "l3s"); pNew->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( p, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecPis, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 4: create the special Pi corresponding to SAVE //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { pObjSavePi = Aig_ObjCreateCi( pNew ); nodeName = "SAVE_BIERE", Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( p, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecLos, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 6: create "saved" register output //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { loCreated++; pObjSavedLo = Aig_ObjCreateCi( pNew ); Vec_PtrPush( vecLos, pObjSavedLo ); nodeName = "SAVED_LO"; Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi //**************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); } //******************************************************************** // Step 8: create internal nodes //******************************************************************** Aig_ManForEachNode( p, pObj, i ) { pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 8.x : create PO for each safety assertions // NOTE : Here the output is purposely inverted as it will be thrown to // dprove //******************************************************************** assert( pNegatedSafetyConjunction == NULL ); if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE) { if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) { pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } pNegatedSafetyConjunction = Aig_Not(pObjAndAcc); if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) ); } else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) { pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } collectiveAssertSafety = pObjAndAcc; pObjAndAcc = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) { pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); } collectiveAssumeSafety = pObjAndAcc; pNegatedSafetyConjunction = Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ); if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); } else { printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); pNegatedSafetyConjunction = Aig_Not( Aig_ManConst1(pNew) ); if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); } } assert( pNegatedSafetyConjunction != NULL ); //******************************************************************** // Step 9: create the safety property output gate for the liveness properties // discuss with Sat/Alan for an alternative implementation //******************************************************************** if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { vPoForLtlProps = Vec_PtrAlloc( Vec_PtrSize( vTopASTNodeArray ) ); if( Vec_PtrSize( vTopASTNodeArray ) ) { //no effective AST for any input LTL property //must do something graceful } for( i=0; ipData ); Vec_PtrPush( vPoForLtlProps, pObjSafetyPropertyOutput ); } } //************************************************************************************* // Step 10: Placeholder PO's were created for Liveness property outputs in the // last step. FYI, # of new liveness property outputs = # of LTL properties in the circuit // It is time for creation of loop LI's and other stuff // Now creating register inputs for the original flops //************************************************************************************* nRegCount = 0; Saig_ManForEachLo( p, pObj, i ) { pMatch = Saig_ObjLoToLi( p, pObj ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); nRegCount++; liCopied++; } //************************************************************************************* // Step 11: create register input corresponding to the register "saved" //************************************************************************************* if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { #ifndef DUPLICATE_CKT_DEBUG pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); nRegCount++; liCreated++; pObjAndAcc = Aig_ManConst1( pNew ); //************************************************************************************* // Step 11: create the family of shadow registers, then create the cascade of Xnor // and And gates for the comparator //************************************************************************************* Saig_ManForEachLo( p, pObj, i ) { //printf("\nKEMON RENDY = %s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i )) ); //top|route0_target0_queue_with_credit0_queue0 //top|route0_master0_queue2 // if( strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[0]" ) == 0 // || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[1]" ) == 0 || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[2]" ) == 0 ) { pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); pObjXnor = Aig_Not( pObjXor ); pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); } } // create the AND gate whose output will be the signal "looped" pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); // create the master AND gate and corresponding AND and OR logic for the liveness properties //************************************************************************************* // Step 11: logic for LTL properties:- (looped & ~theta) where theta is the input ltl // property // Description of some data-structure: //------------------------------------------------------------------------------------- // Name | Type | Purpose //------------------------------------------------------------------------------------- // vSignalMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties // | | It remembers if OR+Latch for GF node has already been // | | created for a particular signal. // | | // vGFFlopMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties // | | remembers if OR+Latch of a GF node has already been created // | | // vSignal | Vec_Ptr_t * | vector for each AST; contains pointers from GF nodes // | | to AIG signals // | | // vAigGFMap | Vec_Vec_t * | vAigGFMap[ index ] = vector of GF nodes pointing to // | | the same AIG node; "index" is the index of that // | | AIG node in the vector vSignal //************************************************************************************* vSignalMemory = Vec_PtrAlloc(10); vGFFlopMemory = Vec_PtrAlloc(10); Vec_PtrForEachEntry( ltlNode *, vTopASTNodeArray, topNodeOfAST, iii ) { vSignal = Vec_PtrAlloc( 10 ); vAigGFMap = Vec_VecAlloc( 10 ); //************************************************************************************* //Step 11a: for the current AST, find out the leaf level Boolean signal pointers from // the NEW aig. //************************************************************************************* populateBoolWithAigNodePtr( pNtk, p, pNew, topNodeOfAST ); assert( checkAllBoolHaveAIGPointer( topNodeOfAST ) ); //************************************************************************************* //Step 11b: for each GF node, compute the pointer in AIG that it should point to // In particular, if the subtree below GF is some Boolean crown (including the case // of simple negation, create new logic and populate the AIG pointer in GF node // accordingly //************************************************************************************* populateAigPointerUnitGF( pNew, topNodeOfAST, vSignal, vAigGFMap ); //************************************************************************************* //Step 11c: everything below GF are computed. Now, it is time to create logic for individual // GF nodes (i.e. the OR gate and the latch and the Boolean crown of the AST //************************************************************************************* Vec_PtrForEachEntry( Aig_Obj_t *, vSignal, pObj, i ) { //********************************************************* // Step 11c.1: if the OR+Latch of the particular signal is // not already created, create it. It may have already been // created from another property, so check it before creation //********************************************************* if( Vec_PtrFind( vSignalMemory, pObj ) == -1 ) { liveLatch++; pDriverImage = pObj; pObjShadowLo = Aig_ObjCreateCi( pNew ); pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; Vec_PtrPush( vSignalMemory, pObj ); Vec_PtrPush( vGFFlopMemory, pObjShadowLo ); #if 1 #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); //nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); //sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); nodeName = (char *)malloc( 20 ); sprintf( nodeName, "n%d__%s", Aig_ObjId(pObjShadowLo), "GF_flop" ); Vec_PtrPush( vecLoNames, nodeName ); #endif #endif } else pObjShadowLo = (Aig_Obj_t *)Vec_PtrEntry( vGFFlopMemory, Vec_PtrFind( vSignalMemory, pObj ) ); Vec_VecForEachEntryLevel( ltlNode *, vAigGFMap, pEnrtyGLOBALLY, ii, i ) setAIGNodePtrOfGloballyNode( pEnrtyGLOBALLY, pObjShadowLo); //#ifdef PROPAGATE_NAMES // Vec_PtrPush( vecLos, pObjShadowLo ); // nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); // sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); // Vec_PtrPush( vecLoNames, nodeName ); //#endif } //********************************************************* //Step 11c.2: creating the Boolean crown //********************************************************* buildLogicFromLTLNode( pNew, topNodeOfAST ); //********************************************************* //Step 11c.3: creating logic for (looped & ~theta) and patching // it with the proper PO //Note: if ALLOW_SAFETY_PROPERTIES is defined then the final AND //gate is a conjunction of safety & liveness, i.e. SAFETY & (looped => theta) //since ABC convention demands a NOT gate at the end, the property logic //becomes !( SAFETY & (looped => theta) ) = !SAFETY + (looped & !theta) //********************************************************* pObjLive = retriveAIGPointerFromLTLNode( topNodeOfAST ); pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_Not(pObjLive) ); #ifdef ALLOW_SAFETY_PROPERTIES printf("liveness output is conjoined with safety assertions\n"); pObjSafetyAndLiveToSafety = Aig_Or( pNew, pObjSafetyGate, pNegatedSafetyConjunction ); pObjSafetyPropertyOutput = (Aig_Obj_t *)Vec_PtrEntry( vPoForLtlProps, iii ); Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyAndLiveToSafety ); #else pObjSafetyPropertyOutput = Vec_PtrEntry( vPoForLtlProps, iii ); Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); #endif //refreshing vSignal and vAigGFMap arrays Vec_PtrFree( vSignal ); Vec_VecFree( vAigGFMap ); } #endif } #endif Aig_ManSetRegNum( pNew, nRegCount ); Aig_ManCiCleanupBiere( pNew ); Aig_ManCoCleanupBiere( pNew ); Aig_ManCleanup( pNew ); assert( Aig_ManCheck( pNew ) ); if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) { assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); //assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); } return pNew; } int Abc_CommandAbcLivenessToSafetyWithLTL( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; Aig_Man_t * pAig, *pAigNew = NULL; int c; Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; int directive = -1; // char *ltfFormulaString = NULL; int numOfLtlPropOutput;//, LTL_FLAG = 0; Vec_Ptr_t *ltlBuffer; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); if( argc == 1 ) { assert( directive == -1 ); directive = FULL_BIERE_MODE; } else { Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "1slhf" ) ) != EOF ) { switch( c ) { case '1': if( directive == -1 ) directive = FULL_BIERE_ONE_LOOP_MODE; else { assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; else directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; } break; case 's': if( directive == -1 ) directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; else { if( directive != FULL_BIERE_ONE_LOOP_MODE ) goto usage; assert(directive == FULL_BIERE_ONE_LOOP_MODE); directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; } break; case 'l': if( directive == -1 ) directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; else { if( directive != FULL_BIERE_ONE_LOOP_MODE ) goto usage; assert(directive == FULL_BIERE_ONE_LOOP_MODE); directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; } break; case 'f': //assert( argc >= 3 ); //vecLtlFormula = Vec_PtrAlloc( argc - 2 ); //if( argc >= 3 ) //{ // for( t=3; t<=argc; t++ ) // { // printf("argv[%d] = %s\n", t-1, argv[t-1]); // Vec_PtrPush( vecLtlFormula, argv[t-1] ); // } //} //printf("argv[argc] = %s\n", argv[argc-1]); //ltfFormulaString = argv[2]; //LTL_FLAG = 1; printf("\nILLEGAL FLAG: aborting....\n"); exit(0); break; case 'h': goto usage; default: goto usage; } } } if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } if( pAbc->vLTLProperties_global != NULL ) ltlBuffer = pAbc->vLTLProperties_global; else ltlBuffer = NULL; switch( directive ) { case FULL_BIERE_MODE: pAigNew = LivenessToSafetyTransformationWithLTL( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("A new circuit is produced with\n\t%d POs - one for safety and %d for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput+1, numOfLtlPropOutput); break; case FULL_BIERE_ONE_LOOP_MODE: pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); break; case IGNORE_LIVENESS_KEEP_SAFETY_MODE: pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); assert( numOfLtlPropOutput == 0 ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); break; case IGNORE_SAFETY_KEEP_LIVENESS_MODE: pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("A new circuit is produced with\n\t%d PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput); break; case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); break; } #if 0 if( argc == 1 ) { pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n"); } else { Extra_UtilGetoptReset(); c = Extra_UtilGetopt( argc, argv, "1lsh" ); if( c == '1' ) { if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); } else if( c == 'l' ) { if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n"); } else if( c == 's' ) { if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("The input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); } pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); if( Aig_ManRegNum(pAigNew) != 0 ) printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n"); } else if( c == 'h' ) goto usage; else goto usage; } #endif #if 0 Aig_ManPrintStats( pAigNew ); printf("\nDetail statistics*************************************\n"); printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); printf("\n*******************************************************\n"); #endif pNtkNew = Abc_NtkFromAigPhase( pAigNew ); pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames ); Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); #if 0 #ifndef DUPLICATE_CKT_DEBUG Saig_ManForEachPi( pAigNew, pObj, i ) assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); Saig_ManForEachLo( pAigNew, pObj, i ) assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); #endif #endif return 0; usage: fprintf( stdout, "usage: l3s [-1lsh]\n" ); fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); fprintf( stdout, "\t-h : print command usage\n"); return 1; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/liveness_sim.c000066400000000000000000000705201300674244400247700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [liveness_sim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [Main implementation module.] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2009.] Revision [$Id: liveness_sim.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include ABC_NAMESPACE_IMPL_START #define PROPAGATE_NAMES //#define DUPLICATE_CKT_DEBUG extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); //char *strdup(const char *string); /******************************************************************* LAYOUT OF PI VECTOR: +------------------------------------------------------------------------------------------------------------------------------------+ | TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) | +------------------------------------------------------------------------------------------------------------------------------------+ <------------True PI----------------->|<----------------------------LO---------------------------------------------------------------> LAYOUT OF PO VECTOR: +-----------------------------------------------------------------------------------------------------------+ | SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) | +-----------------------------------------------------------------------------------------------------------+ <--True PO--->|<--------------------------------------LI----------------------------------------------------> ********************************************************************/ static void printVecPtrOfString( Vec_Ptr_t *vec ) { int i; for( i=0; i< Vec_PtrSize( vec ); i++ ) { printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) ); } } static int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot ) { int i; Aig_Obj_t *pObj; Saig_ManForEachPo( pAig, pObj, i ) { if( pObj == pPivot ) return i; } return -1; } static char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot ) { Aig_Obj_t *pObjOld, *pObj; Abc_Obj_t *pNode; int index; assert( Saig_ObjIsPi( pAigNew, pObjPivot ) ); Aig_ManForEachCi( pAigNew, pObj, index ) if( pObj == pObjPivot ) break; assert( index < Aig_ManCiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) ); if( index == Saig_ManPiNum( pAigNew ) - 1 ) return "SAVE_BIERE"; else { pObjOld = Aig_ManCi( pAigOld, index ); pNode = Abc_NtkPi( pNtkOld, index ); assert( pObjOld->pData == pObjPivot ); return Abc_ObjName( pNode ); } } static char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair ) { Aig_Obj_t *pObjOld, *pObj; Abc_Obj_t *pNode; int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i; char *dummyStr = (char *)malloc( sizeof(char) * 50 ); assert( Saig_ObjIsLo( pAigNew, pObjPivot ) ); Saig_ManForEachLo( pAigNew, pObj, index ) if( pObj == pObjPivot ) break; if( index < originalLatchNum ) { oldIndex = Saig_ManPiNum( pAigOld ) + index; pObjOld = Aig_ManCi( pAigOld, oldIndex ); pNode = Abc_NtkCi( pNtkOld, oldIndex ); assert( pObjOld->pData == pObjPivot ); return Abc_ObjName( pNode ); } else if( index == originalLatchNum ) return "SAVED_LO"; else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 ) { oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1; pObjOld = Aig_ManCi( pAigOld, oldIndex ); pNode = Abc_NtkCi( pNtkOld, oldIndex ); sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW"); return dummyStr; } else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) ) { oldIndex = index - 2 * originalLatchNum - 1; strMatch = 0; Saig_ManForEachPo( pAigOld, pObj, i ) { pNode = Abc_NtkPo( pNtkOld, i ); if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL ) { if( strMatch == oldIndex ) { sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS"); return dummyStr; } else strMatch++; } } } else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ) { oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive ); strMatch = 0; Saig_ManForEachPo( pAigOld, pObj, i ) { pNode = Abc_NtkPo( pNtkOld, i ); if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL ) { if( strMatch == oldIndex ) { sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS"); return dummyStr; } else strMatch++; } } } else return "UNKNOWN"; return NULL; } extern Vec_Ptr_t *vecPis, *vecPiNames; extern Vec_Ptr_t *vecLos, *vecLoNames; static int Aig_ManCiCleanupBiere( Aig_Man_t * p ) { int nPisOld = Aig_ManCiNum(p); 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); } static int Aig_ManCoCleanupBiere( Aig_Man_t * p ) { int nPosOld = Aig_ManCoNum(p); 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); } static Aig_Man_t * LivenessToSafetyTransformationSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair ) { Aig_Man_t * pNew; int i, nRegCount; Aig_Obj_t * pObjSavePi; Aig_Obj_t *pObjSavedLo, *pObjSavedLi; Aig_Obj_t *pObj, *pMatch; Aig_Obj_t *pObjSaveOrSaved, *pObjSavedLoAndEquality; Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; Aig_Obj_t *pObjSafetyPropertyOutput; Aig_Obj_t *pDriverImage; char *nodeName; int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0, fairLatch = 0; vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); #ifdef DUPLICATE_CKT_DEBUG printf("\nCode is compiled in DEBUG mode, the input-output behavior will be the same as the original circuit\n"); printf("Press any key to continue..."); scanf("%c", &c); #endif //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( "live2safe" ); pNew->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( p, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecPis, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 4: create the special Pi corresponding to SAVE //**************************************************************** #ifndef DUPLICATE_CKT_DEBUG pObjSavePi = Aig_ObjCreateCi( pNew ); nodeName = Abc_UtilStrsav("SAVE_BIERE"), Vec_PtrPush( vecPiNames, nodeName ); #endif //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( p, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecLos, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 6: create "saved" register output //**************************************************************** #ifndef DUPLICATE_CKT_DEBUG loCreated++; pObjSavedLo = Aig_ObjCreateCi( pNew ); Vec_PtrPush( vecLos, pObjSavedLo ); nodeName = Abc_UtilStrsav("SAVED_LO"); Vec_PtrPush( vecLoNames, nodeName ); #endif //**************************************************************** // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi //**************************************************************** #ifndef DUPLICATE_CKT_DEBUG pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); //pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); #endif //******************************************************************** // Step 8: create internal nodes //******************************************************************** Aig_ManForEachNode( p, pObj, i ) { pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 9: create the safety property output gate // create the safety property output gate, this will be the sole true PO // of the whole circuit, discuss with Sat/Alan for an alternative implementation //******************************************************************** #ifndef DUPLICATE_CKT_DEBUG pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); #endif //******************************************************************** // DEBUG: To recreate the same circuit, at least from the input and output // behavior, we need to copy the original PO //******************************************************************** #ifdef DUPLICATE_CKT_DEBUG Saig_ManForEachPo( p, pObj, i ) { Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } #endif // create register inputs for the original registers nRegCount = 0; Saig_ManForEachLo( p, pObj, i ) { pMatch = Saig_ObjLoToLi( p, pObj ); //Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); nRegCount++; liCopied++; } // create register input corresponding to the register "saved" #ifndef DUPLICATE_CKT_DEBUG pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); nRegCount++; liCreated++; pObjAndAcc = NULL; // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator Saig_ManForEachLo( p, pObj, i ) { pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Mux( pNew, pObjSavePi, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); pObjXnor = Aig_Not( pObjXor ); if( pObjAndAcc == NULL ) pObjAndAcc = pObjXnor; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); } } // create the AND gate whose output will be the signal "looped" pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); // create the master AND gate and corresponding AND and OR logic for the liveness properties pObjAndAcc = NULL; if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) printf("\nCircuit without any liveness property\n"); else { Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) { //assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) ); //Aig_ObjPrint( pNew, pObj ); liveLatch++; pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Or( pNew, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo), Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; if( pObjAndAcc == NULL ) pObjAndAcc = pObjShadowLo; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy ); } } } if( pObjAndAcc != NULL ) pObjLive = pObjAndAcc; else pObjLive = Aig_ManConst1( pNew ); // create the master AND gate and corresponding AND and OR logic for the fairness properties pObjAndAcc = NULL; if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) printf("\nCircuit without any fairness property\n"); else { Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) { fairLatch++; //assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) ); pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); pObjShadowLo = Aig_ObjCreateCi( pNew ); #ifdef PROPAGATE_NAMES Vec_PtrPush( vecLos, pObjShadowLo ); nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); Vec_PtrPush( vecLoNames, nodeName ); #endif pObjShadowLiDriver = Aig_Or( pNew, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo), Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); nRegCount++; loCreated++; liCreated++; if( pObjAndAcc == NULL ) pObjAndAcc = pObjShadowLo; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy ); } } } if( pObjAndAcc != NULL ) pObjFair = pObjAndAcc; else pObjFair = Aig_ManConst1( pNew ); //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); #endif Aig_ManSetRegNum( pNew, nRegCount ); Aig_ManCiCleanupBiere( pNew ); Aig_ManCoCleanupBiere( pNew ); Aig_ManCleanup( pNew ); assert( Aig_ManCheck( pNew ) ); #ifndef DUPLICATE_CKT_DEBUG assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); assert( Saig_ManPoNum( pNew ) == 1 ); assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); #endif return pNew; } static Aig_Man_t * LivenessToSafetyTransformationOneStepLoopSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair ) { Aig_Man_t * pNew; int i, nRegCount; Aig_Obj_t * pObjSavePi; Aig_Obj_t *pObj, *pMatch; Aig_Obj_t *pObjSavedLoAndEquality; Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; Aig_Obj_t *pObjSafetyPropertyOutput; Aig_Obj_t *pDriverImage; Aig_Obj_t *pObjCorrespondingLi; char *nodeName; int piCopied = 0, liCopied = 0, loCopied = 0;//, liCreated = 0, loCreated = 0, piVecIndex = 0; vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( "live2safe" ); pNew->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( p, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecPis, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); Vec_PtrPush( vecPiNames, nodeName ); } //**************************************************************** // Step 4: create the special Pi corresponding to SAVE //**************************************************************** pObjSavePi = Aig_ObjCreateCi( pNew ); nodeName = "SAVE_BIERE", Vec_PtrPush( vecPiNames, nodeName ); //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( p, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrPush( vecLos, pObj->pData ); nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); Vec_PtrPush( vecLoNames, nodeName ); } //**************************************************************** // Step 6: create "saved" register output //**************************************************************** #if 0 loCreated++; pObjSavedLo = Aig_ObjCreateCi( pNew ); Vec_PtrPush( vecLos, pObjSavedLo ); nodeName = "SAVED_LO"; Vec_PtrPush( vecLoNames, nodeName ); #endif //**************************************************************** // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi //**************************************************************** #if 0 pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); #endif //******************************************************************** // Step 8: create internal nodes //******************************************************************** Aig_ManForEachNode( p, pObj, i ) { pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 9: create the safety property output gate // create the safety property output gate, this will be the sole true PO // of the whole circuit, discuss with Sat/Alan for an alternative implementation //******************************************************************** pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); // create register inputs for the original registers nRegCount = 0; Saig_ManForEachLo( p, pObj, i ) { pMatch = Saig_ObjLoToLi( p, pObj ); //Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); nRegCount++; liCopied++; } #if 0 // create register input corresponding to the register "saved" pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); nRegCount++; liCreated++; #endif pObjAndAcc = NULL; //**************************************************************************************************** //For detection of loop of length 1 we do not need any shadow register, we only need equality detector //between Lo_j and Li_j and then a cascade of AND gates //**************************************************************************************************** Saig_ManForEachLo( p, pObj, i ) { pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj ); pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) ); pObjXnor = Aig_Not( pObjXor ); if( pObjAndAcc == NULL ) pObjAndAcc = pObjXnor; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); } } // create the AND gate whose output will be the signal "looped" pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc ); // create the master AND gate and corresponding AND and OR logic for the liveness properties pObjAndAcc = NULL; if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) printf("\nCircuit without any liveness property\n"); else { Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) { pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); if( pObjAndAcc == NULL ) pObjAndAcc = pDriverImage; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); } } } if( pObjAndAcc != NULL ) pObjLive = pObjAndAcc; else pObjLive = Aig_ManConst1( pNew ); // create the master AND gate and corresponding AND and OR logic for the fairness properties pObjAndAcc = NULL; if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) printf("\nCircuit without any fairness property\n"); else { Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) { pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); if( pObjAndAcc == NULL ) pObjAndAcc = pDriverImage; else { pObjAndAccDummy = pObjAndAcc; pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); } } } if( pObjAndAcc != NULL ) pObjFair = pObjAndAcc; else pObjFair = Aig_ManConst1( pNew ); pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); Aig_ManSetRegNum( pNew, nRegCount ); printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vCis ), pNew->nRegs ); Aig_ManCiCleanupBiere( pNew ); Aig_ManCoCleanupBiere( pNew ); Aig_ManCleanup( pNew ); assert( Aig_ManCheck( pNew ) ); return pNew; } static Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { Abc_Obj_t * pNode; int i, liveCounter = 0; Vec_Ptr_t * vLive; vLive = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pNode, i ) if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL ) { Vec_PtrPush( vLive, Aig_ManCo( pAig, i ) ); liveCounter++; } printf("\nNumber of liveness property found = %d\n", liveCounter); return vLive; } static Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) { Abc_Obj_t * pNode; int i, fairCounter = 0; Vec_Ptr_t * vFair; vFair = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pNode, i ) if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL ) { Vec_PtrPush( vFair, Aig_ManCo( pAig, i ) ); fairCounter++; } printf("\nNumber of fairness property found = %d\n", fairCounter); return vFair; } static void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames ) { Aig_Obj_t *pObj; int i, ntkObjId; pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) ); Saig_ManForEachPi( pAig, pObj, i ) { ntkObjId = Abc_NtkCi( pNtk, i )->Id; //printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId); Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL ); } Saig_ManForEachLo( pAig, pObj, i ) { ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id; //printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId); Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL ); } } int Abc_CommandAbcLivenessToSafetySim( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; Aig_Man_t * pAig, *pAigNew; int c; Vec_Ptr_t * vLive, * vFair; pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); if ( pNtk == NULL ) { fprintf( pErr, "Empty network.\n" ); return 1; } if( !Abc_NtkIsStrash( pNtk ) ) { printf("\nThe input network was not strashed, strashing....\n"); pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkOld = pNtkTemp; pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkOld = pNtk; vLive = populateLivenessVector( pNtk, pAig ); vFair = populateFairnessVector( pNtk, pAig ); } #if 0 Aig_ManPrintStats( pAig ); printf("\nDetail statistics*************************************\n"); printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAig )); printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAig )); printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAig ) - Saig_ManPiNum( pAig )); printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAig ) - Saig_ManPoNum( pAig )); printf("Numer of registers = %d\n", Saig_ManRegNum( pAig ) ); printf("\n*******************************************************\n"); #endif c = Extra_UtilGetopt( argc, argv, "1" ); if( c == '1' ) pAigNew = LivenessToSafetyTransformationOneStepLoopSim( pNtk, pAig, vLive, vFair ); else pAigNew = LivenessToSafetyTransformationSim( pNtk, pAig, vLive, vFair ); #if 0 Aig_ManPrintStats( pAigNew ); printf("\nDetail statistics*************************************\n"); printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); printf("\n*******************************************************\n"); #endif pNtkNew = Abc_NtkFromAigPhase( pAigNew ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames ); Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); //Saig_ManForEachPi( pAigNew, pObj, i ) // printf("Name of %d-th Pi = %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ); //Saig_ManForEachLo( pAigNew, pObj, i ) // printf("Name of %d-th Lo = %s\n", i, retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ); //printVecPtrOfString( vecPiNames ); //printVecPtrOfString( vecLoNames ); #if 0 #ifndef DUPLICATE_CKT_DEBUG Saig_ManForEachPi( pAigNew, pObj, i ) assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); Saig_ManForEachLo( pAigNew, pObj, i ) assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); #endif #endif return 0; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/ltl_parser.c000066400000000000000000000541021300674244400244350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ltl_parser.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [LTL checker.] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2009.] Revision [$Id: ltl_parser.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "aig/aig/aig.h" #include "base/abc/abc.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START enum ltlToken { AND, OR, NOT, IMPLY, GLOBALLY, EVENTUALLY, NEXT, UNTIL, BOOL }; enum ltlGrammerToken { OPERAND, LTL, BINOP, UOP }; typedef enum ltlToken tokenType; typedef enum ltlGrammerToken ltlGrammerTokenType; struct ltlNode_t { tokenType type; char *name; Aig_Obj_t *pObj; struct ltlNode_t *left; struct ltlNode_t *right; }; typedef struct ltlNode_t ltlNode; ltlNode *generateTypedNode( tokenType new_type ) //void generateTypedNode( ltlNode *new_node, tokenType new_type ) { ltlNode *new_node; new_node = (ltlNode *)malloc( sizeof(ltlNode) ); if( new_node ) { new_node->type = new_type; new_node->pObj = NULL; new_node->name = NULL; new_node->left = NULL; new_node->right = NULL; } return new_node; } Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAig, ltlNode *pLtlNode ); static inline int isNotVarNameSymbol( char c ) { return ( c == ' ' || c == '\t' || c == '\n' || c == ':' || c == '\0' ); } void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk ) { char *pLtlFormula, *tempFormula; int i; if( pAbc->vLTLProperties_global != NULL ) { // printf("Deleting exisitng LTL database from the frame\n"); Vec_PtrFree( pAbc->vLTLProperties_global ); pAbc->vLTLProperties_global = NULL; } pAbc->vLTLProperties_global = Vec_PtrAlloc(Vec_PtrSize(pNtk->vLtlProperties)); Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pLtlFormula, i ) { tempFormula = (char *)malloc( sizeof(char)*(strlen(pLtlFormula)+1) ); sprintf( tempFormula, "%s", pLtlFormula ); Vec_PtrPush( pAbc->vLTLProperties_global, tempFormula ); } } char *getVarName( char *suffixFormula, int startLoc, int *endLocation ) { int i = startLoc, length; char *name; if( isNotVarNameSymbol( suffixFormula[startLoc] ) ) return NULL; while( !isNotVarNameSymbol( suffixFormula[i] ) ) i++; *endLocation = i; length = i - startLoc; name = (char *)malloc( sizeof(char) * (length + 1)); for( i=0; i= (int)strlen( formula ) ) { printf("\nInvalid LTL formula: unexpected end of string..." ); return 1; } return 0; } int isTemporalOperator( char *formula, int index ) { if( !(isUnexpectedEOS( formula, index ) || formula[ index ] == 'G' || formula[ index ] == 'F' || formula[ index ] == 'U' || formula[ index ] == 'X') ) { printf("\nInvalid LTL formula: expecting temporal operator at the position %d....\n", index); return 0; } return 1; } ltlNode *readLtlFormula( char *formula ) { char ch; char *varName; int formulaLength, rememberEnd; int i = startOfSuffixString; ltlNode *curr_node, *temp_node_left, *temp_node_right; char prevChar; formulaLength = strlen( formula ); if( isUnexpectedEOS( formula, startOfSuffixString ) ) { printf("\nFAULTING POINT: formula = %s\nstartOfSuffixString = %d, formula[%d] = %c\n\n", formula, startOfSuffixString, startOfSuffixString - 1, formula[startOfSuffixString-1]); return NULL; } while( i < formulaLength ) { ch = formula[i]; switch(ch){ case ' ': case '\n': case '\r': case '\t': case '\v': case '\f': i++; startOfSuffixString = i; break; case ':': i++; if( !isTemporalOperator( formula, i ) ) return NULL; startOfSuffixString = i; break; case 'G': prevChar = formula[i-1]; if( prevChar == ':' ) //i.e. 'G' is a temporal operator { i++; startOfSuffixString = i; temp_node_left = readLtlFormula( formula ); if( temp_node_left == NULL ) return NULL; else { curr_node = generateTypedNode(GLOBALLY); curr_node->left = temp_node_left; return curr_node; } } else //i.e. 'G' must be starting a variable name { varName = getVarName( formula, i, &rememberEnd ); if( !varName ) { printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); return NULL; } curr_node = generateTypedNode(BOOL); curr_node->name = varName; i = rememberEnd; startOfSuffixString = i; return curr_node; } case 'F': prevChar = formula[i-1]; if( prevChar == ':' ) //i.e. 'F' is a temporal operator { i++; startOfSuffixString = i; temp_node_left = readLtlFormula( formula ); if( temp_node_left == NULL ) return NULL; else { curr_node = generateTypedNode(EVENTUALLY); curr_node->left = temp_node_left; return curr_node; } } else //i.e. 'F' must be starting a variable name { varName = getVarName( formula, i, &rememberEnd ); if( !varName ) { printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); return NULL; } curr_node = generateTypedNode(BOOL); curr_node->name = varName; i = rememberEnd; startOfSuffixString = i; return curr_node; } case 'X': prevChar = formula[i-1]; if( prevChar == ':' ) //i.e. 'X' is a temporal operator { i++; startOfSuffixString = i; temp_node_left = readLtlFormula( formula ); if( temp_node_left == NULL ) return NULL; else { curr_node = generateTypedNode(NEXT); curr_node->left = temp_node_left; return curr_node; } } else //i.e. 'X' must be starting a variable name { varName = getVarName( formula, i, &rememberEnd ); if( !varName ) { printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); return NULL; } curr_node = generateTypedNode(BOOL); curr_node->name = varName; i = rememberEnd; startOfSuffixString = i; return curr_node; } case 'U': prevChar = formula[i-1]; if( prevChar == ':' ) //i.e. 'X' is a temporal operator { i++; startOfSuffixString = i; temp_node_left = readLtlFormula( formula ); if( temp_node_left == NULL ) return NULL; temp_node_right = readLtlFormula( formula ); if( temp_node_right == NULL ) { //need to do memory management: if right subtree is NULL then left //subtree must be freed. return NULL; } curr_node = generateTypedNode(UNTIL); curr_node->left = temp_node_left; curr_node->right = temp_node_right; return curr_node; } else //i.e. 'U' must be starting a variable name { varName = getVarName( formula, i, &rememberEnd ); if( !varName ) { printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); return NULL; } curr_node = generateTypedNode(BOOL); curr_node->name = varName; i = rememberEnd; startOfSuffixString = i; return curr_node; } case '+': i++; startOfSuffixString = i; temp_node_left = readLtlFormula( formula ); if( temp_node_left == NULL ) return NULL; temp_node_right = readLtlFormula( formula ); if( temp_node_right == NULL ) { //need to do memory management: if right subtree is NULL then left //subtree must be freed. return NULL; } curr_node = generateTypedNode(OR); curr_node->left = temp_node_left; curr_node->right = temp_node_right; return curr_node; case '&': i++; startOfSuffixString = i; temp_node_left = readLtlFormula( formula ); if( temp_node_left == NULL ) return NULL; temp_node_right = readLtlFormula( formula ); if( temp_node_right == NULL ) { //need to do memory management: if right subtree is NULL then left //subtree must be freed. return NULL; } curr_node = generateTypedNode(AND); curr_node->left = temp_node_left; curr_node->right = temp_node_right; return curr_node; case '!': i++; startOfSuffixString = i; temp_node_left = readLtlFormula( formula ); if( temp_node_left == NULL ) return NULL; else { curr_node = generateTypedNode(NOT); curr_node->left = temp_node_left; return curr_node; } default: varName = getVarName( formula, i, &rememberEnd ); if( !varName ) { printf("\nInvalid LTL formula: expecting valid variable name token...aborting" ); return NULL; } curr_node = generateTypedNode(BOOL); curr_node->name = varName; i = rememberEnd; startOfSuffixString = i; return curr_node; } } return NULL; } void resetGlobalVar() { startOfSuffixString = 0; } ltlNode *parseFormulaCreateAST( char *inputFormula ) { ltlNode *temp; temp = readLtlFormula( inputFormula ); //if( temp == NULL ) // printf("\nAST creation failed for formula %s", inputFormula ); resetGlobalVar(); return temp; } void traverseAbstractSyntaxTree( ltlNode *node ) { switch(node->type){ case( AND ): printf("& "); assert( node->left != NULL ); assert( node->right != NULL ); traverseAbstractSyntaxTree( node->left ); traverseAbstractSyntaxTree( node->right ); return; case( OR ): printf("+ "); assert( node->left != NULL ); assert( node->right != NULL ); traverseAbstractSyntaxTree( node->left ); traverseAbstractSyntaxTree( node->right ); return; case( NOT ): printf("~ "); assert( node->left != NULL ); traverseAbstractSyntaxTree( node->left ); assert( node->right == NULL ); return; case( GLOBALLY ): printf("G "); assert( node->left != NULL ); traverseAbstractSyntaxTree( node->left ); assert( node->right == NULL ); return; case( EVENTUALLY ): printf("F "); assert( node->left != NULL ); traverseAbstractSyntaxTree( node->left ); assert( node->right == NULL ); return; case( NEXT ): printf("X "); assert( node->left != NULL ); traverseAbstractSyntaxTree( node->left ); assert( node->right == NULL ); return; case( UNTIL ): printf("U "); assert( node->left != NULL ); assert( node->right != NULL ); traverseAbstractSyntaxTree( node->left ); traverseAbstractSyntaxTree( node->right ); return; case( BOOL ): printf("%s ", node->name); assert( node->left == NULL ); assert( node->right == NULL ); return; default: printf("\nUnsupported token type: Exiting execution\n"); exit(0); } } void traverseAbstractSyntaxTree_postFix( ltlNode *node ) { switch(node->type){ case( AND ): printf("( "); assert( node->left != NULL ); assert( node->right != NULL ); traverseAbstractSyntaxTree_postFix( node->left ); printf("& "); traverseAbstractSyntaxTree_postFix( node->right ); printf(") "); return; case( OR ): printf("( "); assert( node->left != NULL ); assert( node->right != NULL ); traverseAbstractSyntaxTree_postFix( node->left ); printf("+ "); traverseAbstractSyntaxTree_postFix( node->right ); printf(") "); return; case( NOT ): printf("~ "); assert( node->left != NULL ); traverseAbstractSyntaxTree_postFix( node->left ); assert( node->right == NULL ); return; case( GLOBALLY ): printf("G "); //printf("( "); assert( node->left != NULL ); traverseAbstractSyntaxTree_postFix( node->left ); assert( node->right == NULL ); //printf(") "); return; case( EVENTUALLY ): printf("F "); //printf("( "); assert( node->left != NULL ); traverseAbstractSyntaxTree_postFix( node->left ); assert( node->right == NULL ); //printf(") "); return; case( NEXT ): printf("X "); assert( node->left != NULL ); traverseAbstractSyntaxTree_postFix( node->left ); assert( node->right == NULL ); return; case( UNTIL ): printf("( "); assert( node->left != NULL ); assert( node->right != NULL ); traverseAbstractSyntaxTree_postFix( node->left ); printf("U "); traverseAbstractSyntaxTree_postFix( node->right ); printf(") "); return; case( BOOL ): printf("%s ", node->name); assert( node->left == NULL ); assert( node->right == NULL ); return; default: printf("\nUnsupported token type: Exiting execution\n"); exit(0); } } void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap ) { ltlNode *nextNode, *nextToNextNode; int serialNumSignal; switch( topASTNode->type ){ case AND: case OR: case IMPLY: populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap ); populateAigPointerUnitGF( pAigNew, topASTNode->right, vSignal, vAigGFMap ); return; case NOT: populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap ); return; case GLOBALLY: nextNode = topASTNode->left; assert( nextNode->type = EVENTUALLY ); nextToNextNode = nextNode->left; if( nextToNextNode->type == BOOL ) { assert( nextToNextNode->pObj ); serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); if( serialNumSignal == -1 ) { Vec_PtrPush( vSignal, nextToNextNode->pObj ); serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); } //Vec_PtrPush( vGLOBALLY, topASTNode ); Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode ); } else { assert( nextToNextNode->pObj == NULL ); buildLogicFromLTLNode_combinationalOnly( pAigNew, nextToNextNode ); serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); if( serialNumSignal == -1 ) { Vec_PtrPush( vSignal, nextToNextNode->pObj ); serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj ); } //Vec_PtrPush( vGLOBALLY, topASTNode ); Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode ); } return; case BOOL: return; default: printf("\nINVALID situation: aborting...\n"); exit(0); } } Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAigNew, ltlNode *pLtlNode ) { Aig_Obj_t *leftAigObj, *rightAigObj; if( pLtlNode->pObj != NULL ) return pLtlNode->pObj; else { assert( pLtlNode->type != BOOL ); switch( pLtlNode->type ){ case AND: assert( pLtlNode->left ); assert( pLtlNode->right ); leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right ); assert( leftAigObj ); assert( rightAigObj ); pLtlNode->pObj = Aig_And( pAigNew, leftAigObj, rightAigObj ); return pLtlNode->pObj; case OR: assert( pLtlNode->left ); assert( pLtlNode->right ); leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right ); assert( leftAigObj ); assert( rightAigObj ); pLtlNode->pObj = Aig_Or( pAigNew, leftAigObj, rightAigObj ); return pLtlNode->pObj; case NOT: assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left ); assert( leftAigObj ); pLtlNode->pObj = Aig_Not( leftAigObj ); return pLtlNode->pObj; case GLOBALLY: case EVENTUALLY: case NEXT: case UNTIL: printf("FORBIDDEN node: ABORTING!!\n"); exit(0); default: printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n"); exit(0); } } } Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode ) { Aig_Obj_t *leftAigObj, *rightAigObj; if( pLtlNode->pObj != NULL ) return pLtlNode->pObj; else { assert( pLtlNode->type != BOOL ); switch( pLtlNode->type ){ case AND: assert( pLtlNode->left ); assert( pLtlNode->right ); leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right ); assert( leftAigObj ); assert( rightAigObj ); pLtlNode->pObj = Aig_And( pAig, leftAigObj, rightAigObj ); return pLtlNode->pObj; case OR: assert( pLtlNode->left ); assert( pLtlNode->right ); leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right ); assert( leftAigObj ); assert( rightAigObj ); pLtlNode->pObj = Aig_Or( pAig, leftAigObj, rightAigObj ); return pLtlNode->pObj; case NOT: assert( pLtlNode->left ); assert( pLtlNode->right == NULL ); leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left ); assert( leftAigObj ); pLtlNode->pObj = Aig_Not( leftAigObj ); return pLtlNode->pObj; case GLOBALLY: case EVENTUALLY: case NEXT: case UNTIL: printf("\nAttempting to create circuit with missing AIG pointer in a TEMPORAL node: ABORTING!!\n"); exit(0); default: printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n"); exit(0); } } } int isNonTemporalSubformula( ltlNode *topNode ) { switch( topNode->type ){ case AND: case OR: case IMPLY: return isNonTemporalSubformula( topNode->left) && isNonTemporalSubformula( topNode->right ) ; case NOT: assert( topNode->right == NULL ); return isNonTemporalSubformula( topNode->left ); case BOOL: return 1; default: return 0; } } int isWellFormed( ltlNode *topNode ) { ltlNode *nextNode; switch( topNode->type ){ case AND: case OR: case IMPLY: return isWellFormed( topNode->left) && isWellFormed( topNode->right ) ; case NOT: assert( topNode->right == NULL ); return isWellFormed( topNode->left ); case BOOL: return 1; case GLOBALLY: nextNode = topNode->left; assert( topNode->right == NULL ); if( nextNode->type != EVENTUALLY ) return 0; else { assert( nextNode->right == NULL ); return isNonTemporalSubformula( nextNode->left ); } default: return 0; } } int checkBooleanConstant( char *targetName ) { if( strcmp( targetName, "true" ) == 0 ) return 1; if( strcmp( targetName, "false" ) == 0 ) return 0; return -1; } int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode ) { char *targetName; Abc_Obj_t * pNode; int i; switch( topASTNode->type ){ case BOOL: targetName = topASTNode->name; //printf("\nTrying to match name %s\n", targetName); if( checkBooleanConstant( targetName ) != -1 ) return 1; Abc_NtkForEachPo( pNtk, pNode, i ) { if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 ) { //printf("\nVariable name \"%s\" MATCHED\n", targetName); return 1; } } printf("\nVariable name \"%s\" not found in the PO name list\n", targetName); return 0; case AND: case OR: case IMPLY: case UNTIL: assert( topASTNode->left != NULL ); assert( topASTNode->right != NULL ); return checkSignalNameExistence( pNtk, topASTNode->left ) && checkSignalNameExistence( pNtk, topASTNode->right ); case NOT: case NEXT: case GLOBALLY: case EVENTUALLY: assert( topASTNode->left != NULL ); assert( topASTNode->right == NULL ); return checkSignalNameExistence( pNtk, topASTNode->left ); default: printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); exit(0); } } void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode ) { char *targetName; Abc_Obj_t * pNode; int i; Aig_Obj_t *pObj, *pDriverImage; switch( topASTNode->type ){ case BOOL: targetName = topASTNode->name; if( checkBooleanConstant( targetName ) == 1 ) { topASTNode->pObj = Aig_ManConst1( pAigNew ); return; } if( checkBooleanConstant( targetName ) == 0 ) { topASTNode->pObj = Aig_Not(topASTNode->pObj = Aig_ManConst1( pAigNew )); return; } Abc_NtkForEachPo( pNtk, pNode, i ) if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 ) { pObj = Aig_ManCo( pAigOld, i ); assert( Aig_ObjIsCo( pObj )); pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); topASTNode->pObj = pDriverImage; return; } assert(0); case AND: case OR: case IMPLY: case UNTIL: assert( topASTNode->left != NULL ); assert( topASTNode->right != NULL ); populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left ); populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->right ); return; case NOT: case NEXT: case GLOBALLY: case EVENTUALLY: assert( topASTNode->left != NULL ); assert( topASTNode->right == NULL ); populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left ); return; default: printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); exit(0); } } int checkAllBoolHaveAIGPointer( ltlNode *topASTNode ) { switch( topASTNode->type ){ case BOOL: if( topASTNode->pObj != NULL ) return 1; else { printf("\nfaulting PODMANDYO topASTNode->name = %s\n", topASTNode->name); return 0; } case AND: case OR: case IMPLY: case UNTIL: assert( topASTNode->left != NULL ); assert( topASTNode->right != NULL ); return checkAllBoolHaveAIGPointer( topASTNode->left ) && checkAllBoolHaveAIGPointer( topASTNode->right ); case NOT: case NEXT: case GLOBALLY: case EVENTUALLY: assert( topASTNode->left != NULL ); assert( topASTNode->right == NULL ); return checkAllBoolHaveAIGPointer( topASTNode->left ); default: printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n"); exit(0); } } void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo ) { astNode->pObj = pObjLo; } Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode ) { return astNode->pObj; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/module.make000066400000000000000000000004551300674244400242500ustar00rootroot00000000000000SRC += src/proof/live/liveness.c \ src/proof/live/liveness_sim.c \ src/proof/live/ltl_parser.c \ src/proof/live/kliveness.c \ src/proof/live/monotone.c \ src/proof/live/disjunctiveMonotone.c \ src/proof/live/arenaViolation.c \ src/proof/live/kLiveConstraints.c \ src/proof/live/combination.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/live/monotone.c000066400000000000000000000423441300674244400241310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [kLiveConstraints.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [Constraint analysis module for the k-Liveness algorithm invented by Koen Classen, Niklas Sorensson.] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 31, 2012.] Revision [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include #include "base/main/mainInt.h" #include "proof/pdr/pdr.h" ABC_NAMESPACE_IMPL_START extern Aig_Man_t *Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); //extern Aig_Man_t *createDisjunctiveMonotoneTester(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg, int *startMonotonePropPo); struct aigPoIndices { int attrPendingSignalIndex; int attrHintSingalBeginningMarker; int attrHintSingalEndMarker; int attrSafetyInvarIndex; }; struct aigPoIndices *allocAigPoIndices() { struct aigPoIndices *newAigPoIndices; newAigPoIndices = (struct aigPoIndices *)malloc(sizeof (struct aigPoIndices)); newAigPoIndices->attrPendingSignalIndex = -1; newAigPoIndices->attrHintSingalBeginningMarker = -1; newAigPoIndices->attrHintSingalEndMarker = -1; newAigPoIndices->attrSafetyInvarIndex = -1; assert( newAigPoIndices != NULL ); return newAigPoIndices; } void deallocAigPoIndices(struct aigPoIndices *toBeDeletedAigPoIndices) { assert(toBeDeletedAigPoIndices != NULL ); free(toBeDeletedAigPoIndices); } struct monotoneVectorsStruct { Vec_Int_t *attrKnownMonotone; Vec_Int_t *attrCandMonotone; Vec_Int_t *attrHintMonotone; }; struct monotoneVectorsStruct *allocPointersToMonotoneVectors() { struct monotoneVectorsStruct *newPointersToMonotoneVectors; newPointersToMonotoneVectors = (struct monotoneVectorsStruct *)malloc(sizeof (struct monotoneVectorsStruct)); newPointersToMonotoneVectors->attrKnownMonotone = NULL; newPointersToMonotoneVectors->attrCandMonotone = NULL; newPointersToMonotoneVectors->attrHintMonotone = NULL; assert( newPointersToMonotoneVectors != NULL ); return newPointersToMonotoneVectors; } void deallocPointersToMonotoneVectors(struct monotoneVectorsStruct *toBeDeleted) { assert( toBeDeleted != NULL ); free( toBeDeleted ); } Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk) { int i, numElementPush = 0; Abc_Obj_t *pNode; Vec_Int_t *vHintPoIntdex; vHintPoIntdex = Vec_IntAlloc(0); Abc_NtkForEachPo( pNtk, pNode, i ) { if( strstr( Abc_ObjName( pNode ), "hint_" ) != NULL ) { Vec_IntPush( vHintPoIntdex, i ); numElementPush++; } } if( numElementPush == 0 ) return NULL; else return vHintPoIntdex; } int findPendingSignal(Abc_Ntk_t *pNtk) { int i, pendingSignalIndex = -1; Abc_Obj_t *pNode; Abc_NtkForEachPo( pNtk, pNode, i ) { if( strstr( Abc_ObjName( pNode ), "pendingSignal" ) != NULL ) { pendingSignalIndex = i; break; } } return pendingSignalIndex; } int checkSanityOfKnownMonotone( Vec_Int_t *vKnownMonotone, Vec_Int_t *vCandMonotone, Vec_Int_t *vHintMonotone ) { int iElem, i; Vec_IntForEachEntry( vKnownMonotone, iElem, i ) printf("%d ", iElem); printf("\n"); Vec_IntForEachEntry( vCandMonotone, iElem, i ) printf("%d ", iElem); printf("\n"); Vec_IntForEachEntry( vHintMonotone, iElem, i ) printf("%d ", iElem); printf("\n"); return 1; } Aig_Man_t *createMonotoneTester(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg, int *startMonotonePropPo) { Aig_Man_t *pNewAig; int iElem, i, nRegCount, oldPoNum, poSerialNum, iElemHint; int piCopied = 0, liCopied = 0, liCreated = 0, loCopied = 0, loCreated = 0; int poCopied = 0, poCreated = 0; Aig_Obj_t *pObj, *pObjPo, *pObjDriver, *pObjDriverNew, *pObjPendingDriverNew, *pObjPendingAndNextPending; Aig_Obj_t *pPendingFlop, *pHintSignalLo, *pHintMonotoneFlop, *pObjTemp1, *pObjTemp2, *pObjKnownMonotoneAnd; Vec_Ptr_t *vHintMonotoneLocalDriverNew; Vec_Ptr_t *vHintMonotoneLocalFlopOutput; Vec_Ptr_t *vHintMonotoneLocalProp; int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex; int hintSingalBeginningMarkerLocal = aigPoIndicesArg->attrHintSingalBeginningMarker; //int hintSingalEndMarkerLocal = aigPoIndicesArg->attrHintSingalEndMarker; Vec_Int_t *vKnownMonotoneLocal = monotoneVectorArg->attrKnownMonotone; Vec_Int_t *vCandMonotoneLocal = monotoneVectorArg->attrCandMonotone; Vec_Int_t *vHintMonotoneLocal = monotoneVectorArg->attrHintMonotone; //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_monotone") + 1 ); sprintf(pNewAig->pName, "%s_%s", pAig->pName, "_monotone"); pNewAig->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( pAig ); pObj->pData = Aig_ManConst1( pNewAig ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( pAig, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( pAig, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //**************************************************************** // Step 6: create "D" register output for PENDING flop //**************************************************************** loCreated++; pPendingFlop = Aig_ObjCreateCi( pNewAig ); //**************************************************************** // Step 6.a: create "D" register output for HINT_MONOTONE flop //**************************************************************** vHintMonotoneLocalFlopOutput = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal)); Vec_IntForEachEntry( vHintMonotoneLocal, iElem, i ) { loCreated++; pHintMonotoneFlop = Aig_ObjCreateCi( pNewAig ); Vec_PtrPush( vHintMonotoneLocalFlopOutput, pHintMonotoneFlop ); } nRegCount = loCreated + loCopied; printf("\nnRegCount = %d\n", nRegCount); //******************************************************************** // Step 7: create internal nodes //******************************************************************** Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 8: mapping appropriate new flop drivers //******************************************************************** pObjPo = Aig_ManCo( pAig, pendingSignalIndexLocal ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjPendingDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); pObjPendingAndNextPending = Aig_And( pNewAig, pObjPendingDriverNew, pPendingFlop ); oldPoNum = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); pObjKnownMonotoneAnd = Aig_ManConst1( pNewAig ); #if 1 if( vKnownMonotoneLocal ) { assert( checkSanityOfKnownMonotone( vKnownMonotoneLocal, vCandMonotoneLocal, vHintMonotoneLocal ) ); Vec_IntForEachEntry( vKnownMonotoneLocal, iElemHint, i ) { iElem = (iElemHint - hintSingalBeginningMarkerLocal) + 1 + pendingSignalIndexLocal; printf("\nProcessing knownMonotone = %d\n", iElem); pObjPo = Aig_ManCo( pAig, iElem ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); pHintSignalLo = (Aig_Obj_t *)Vec_PtrEntry(vHintMonotoneLocalFlopOutput, iElem - oldPoNum); pObjTemp1 = Aig_Or( pNewAig, Aig_And(pNewAig, pObjDriverNew, pHintSignalLo), Aig_And(pNewAig, Aig_Not(pObjDriverNew), Aig_Not(pHintSignalLo)) ); pObjKnownMonotoneAnd = Aig_And( pNewAig, pObjKnownMonotoneAnd, pObjTemp1 ); } pObjPendingAndNextPending = Aig_And( pNewAig, pObjPendingAndNextPending, pObjKnownMonotoneAnd ); } #endif vHintMonotoneLocalDriverNew = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal)); vHintMonotoneLocalProp = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal)); Vec_IntForEachEntry( vHintMonotoneLocal, iElem, i ) { pObjPo = Aig_ManCo( pAig, iElem ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); if( vKnownMonotoneLocal != NULL && Vec_IntFind( vKnownMonotoneLocal, iElem ) != -1 ) { Vec_PtrPush(vHintMonotoneLocalDriverNew, pObjDriverNew); } else { poSerialNum = Vec_IntFind( vHintMonotoneLocal, iElem ); pHintSignalLo = (Aig_Obj_t *)Vec_PtrEntry(vHintMonotoneLocalFlopOutput, poSerialNum ); pObjTemp1 = Aig_And( pNewAig, pObjPendingAndNextPending, pHintSignalLo); pObjTemp2 = Aig_Or( pNewAig, Aig_Not(pObjTemp1), pObjDriverNew ); //pObjTemp2 = Aig_Or( pNewAig, Aig_Not(pObjTemp1), Aig_ManConst1( pNewAig )); //pObjTemp2 = Aig_ManConst1( pNewAig ); Vec_PtrPush(vHintMonotoneLocalDriverNew, pObjDriverNew); Vec_PtrPush(vHintMonotoneLocalProp, pObjTemp2); } } //******************************************************************** // Step 9: create primary outputs //******************************************************************** Saig_ManForEachPo( pAig, pObj, i ) { poCopied++; pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } *startMonotonePropPo = i; Vec_PtrForEachEntry( Aig_Obj_t *, vHintMonotoneLocalProp, pObj, i ) { poCreated++; pObjPo = Aig_ObjCreateCo( pNewAig, pObj ); } //******************************************************************** // Step 9: create latch inputs //******************************************************************** Saig_ManForEachLi( pAig, pObj, i ) { liCopied++; Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //******************************************************************** // Step 9.a: create latch input for PENDING_FLOP //******************************************************************** liCreated++; Aig_ObjCreateCo( pNewAig, pObjPendingDriverNew ); //******************************************************************** // Step 9.b: create latch input for MONOTONE_FLOP //******************************************************************** Vec_PtrForEachEntry( Aig_Obj_t *, vHintMonotoneLocalDriverNew, pObj, i ) { liCreated++; Aig_ObjCreateCo( pNewAig, pObj ); } printf("\npoCopied = %d, poCreated = %d\n", poCopied, poCreated); printf("\nliCreated++ = %d\n", liCreated ); Aig_ManSetRegNum( pNewAig, nRegCount ); Aig_ManCleanup( pNewAig ); assert( Aig_ManCheck( pNewAig ) ); assert( loCopied + loCreated == liCopied + liCreated ); printf("\nSaig_ManPoNum = %d\n", Saig_ManPoNum(pNewAig)); return pNewAig; } Vec_Int_t *findNewMonotone( Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg ) { Aig_Man_t *pAigNew; Aig_Obj_t *pObjTargetPo; int poMarker, oldPoNum; int i, RetValue; Pdr_Par_t Pars, * pPars = &Pars; Abc_Cex_t * pCex = NULL; Vec_Int_t *vMonotoneIndex; int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex; int hintSingalBeginningMarkerLocal = aigPoIndicesArg->attrHintSingalBeginningMarker; //int hintSingalEndMarkerLocal = aigPoIndicesArg->attrHintSingalEndMarker; //Vec_Int_t *vKnownMonotoneLocal = monotoneVectorArg->attrKnownMonotone; //Vec_Int_t *vCandMonotoneLocal = monotoneVectorArg->attrCandMonotone; //Vec_Int_t *vHintMonotoneLocal = monotoneVectorArg->attrHintMonotone; pAigNew = createMonotoneTester(pAig, aigPoIndicesArg, monotoneVectorArg, &poMarker ); oldPoNum = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); vMonotoneIndex = Vec_IntAlloc(0); printf("\nSaig_ManPoNum(pAigNew) = %d, poMarker = %d\n", Saig_ManPoNum(pAigNew), poMarker); for( i=poMarker; ifVerbose = 0; //pPars->iOutput = i; //RetValue = Pdr_ManSolve( pAigNew, pPars, &pCex ); RetValue = Pdr_ManSolve( pAigNew, pPars ); if( RetValue == 1 ) { printf("\ni = %d, RetValue = %d : %s (Frame %d)\n", i - oldPoNum + hintSingalBeginningMarkerLocal, RetValue, "Property Proved", pCex? (pCex)->iFrame : -1 ); Vec_IntPush( vMonotoneIndex, i - (pendingSignalIndexLocal + 1) + hintSingalBeginningMarkerLocal); } Aig_ObjChild0Flip( pObjTargetPo ); } if( Vec_IntSize( vMonotoneIndex ) > 0 ) return vMonotoneIndex; else return NULL; } Vec_Int_t *findRemainingMonotoneCandidates(Vec_Int_t *vKnownMonotone, Vec_Int_t *vHintMonotone) { Vec_Int_t *vCandMonotone; int iElem, i; if( vKnownMonotone == NULL || Vec_IntSize(vKnownMonotone) <= 0 ) return vHintMonotone; vCandMonotone = Vec_IntAlloc(0); Vec_IntForEachEntry( vHintMonotone, iElem, i ) { if( Vec_IntFind( vKnownMonotone, iElem ) == -1 ) Vec_IntPush( vCandMonotone, iElem ); } return vCandMonotone; } Vec_Int_t *findMonotoneSignals( Abc_Ntk_t *pNtk ) { Aig_Man_t *pAig; Vec_Int_t *vCandidateMonotoneSignals; Vec_Int_t *vKnownMonotoneSignals; //Vec_Int_t *vKnownMonotoneSignalsNew; //Vec_Int_t *vRemainingCanMonotone; int i, iElem; int pendingSignalIndex; Abc_Ntk_t *pNtkTemp; int hintSingalBeginningMarker; int hintSingalEndMarker; struct aigPoIndices *aigPoIndicesInstance; struct monotoneVectorsStruct *monotoneVectorsInstance; /*******************************************/ //Finding the PO index of the pending signal /*******************************************/ pendingSignalIndex = findPendingSignal(pNtk); if( pendingSignalIndex == -1 ) { printf("\nNo Pending Signal Found\n"); return NULL; } else printf("Po[%d] = %s\n", pendingSignalIndex, Abc_ObjName( Abc_NtkPo(pNtk, pendingSignalIndex) ) ); /*******************************************/ //Finding the PO indices of all hint signals /*******************************************/ vCandidateMonotoneSignals = findHintOutputs(pNtk); if( vCandidateMonotoneSignals == NULL ) return NULL; else { Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i ) printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) ); hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 ); hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 ); } /**********************************************/ //Allocating "struct" with necessary parameters /**********************************************/ aigPoIndicesInstance = allocAigPoIndices(); aigPoIndicesInstance->attrPendingSignalIndex = pendingSignalIndex; aigPoIndicesInstance->attrHintSingalBeginningMarker = hintSingalBeginningMarker; aigPoIndicesInstance->attrHintSingalEndMarker = hintSingalEndMarker; /****************************************************/ //Allocating "struct" with necessary monotone vectors /****************************************************/ monotoneVectorsInstance = allocPointersToMonotoneVectors(); monotoneVectorsInstance->attrCandMonotone = vCandidateMonotoneSignals; monotoneVectorsInstance->attrHintMonotone = vCandidateMonotoneSignals; /*******************************************/ //Generate AIG from Ntk /*******************************************/ if( !Abc_NtkIsStrash( pNtk ) ) { pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkTemp = pNtk; } /*******************************************/ //finding LEVEL 1 monotone signals /*******************************************/ vKnownMonotoneSignals = findNewMonotone( pAig, aigPoIndicesInstance, monotoneVectorsInstance ); monotoneVectorsInstance->attrKnownMonotone = vKnownMonotoneSignals; /*******************************************/ //finding LEVEL >1 monotone signals /*******************************************/ #if 0 if( vKnownMonotoneSignals ) { printf("\nsize = %d\n", Vec_IntSize(vKnownMonotoneSignals) ); vRemainingCanMonotone = findRemainingMonotoneCandidates(vKnownMonotoneSignals, vCandidateMonotoneSignals); monotoneVectorsInstance->attrCandMonotone = vRemainingCanMonotone; vKnownMonotoneSignalsNew = findNewMonotone( pAig, aigPoIndicesInstance, monotoneVectorsInstance ); } #endif deallocAigPoIndices(aigPoIndicesInstance); deallocPointersToMonotoneVectors(monotoneVectorsInstance); return NULL; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/000077500000000000000000000000001300674244400217465ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/module.make000066400000000000000000000002761300674244400240770ustar00rootroot00000000000000SRC += src/proof/pdr/pdrCnf.c \ src/proof/pdr/pdrCore.c \ src/proof/pdr/pdrInv.c \ src/proof/pdr/pdrMan.c \ src/proof/pdr/pdrSat.c \ src/proof/pdr/pdrTsim.c \ src/proof/pdr/pdrUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdr.c000066400000000000000000000026521300674244400227040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Netlist representation.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdr.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdr.h000066400000000000000000000104761300674244400227140ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdr.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdr.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__sat__pdr__pdr_h #define ABC__sat__pdr__pdr_h ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Pdr_Par_t_ Pdr_Par_t; struct Pdr_Par_t_ { // int iOutput; // zero-based number of primary output to solve int nRecycle; // limit on vars for recycling int nFrameMax; // limit on frame count int nConfLimit; // limit on SAT solver conflicts int nConfGenLimit; // limit on SAT solver conflicts during generalization int nRestLimit; // limit on the number of proof-obligations int nTimeOut; // timeout in seconds int nTimeOutGap; // approximate timeout in seconds since the last change int nTimeOutOne; // approximate timeout in seconds per one output int fTwoRounds; // use two rounds for generalization int fMonoCnf; // monolythic CNF int fDumpInv; // dump inductive invariant int fUseSupp; // use support in the invariant int fShortest; // forces bug traces to be shortest int fShiftStart; // allows clause pushing to start from an intermediate frame int fReuseProofOblig; // reuses proof-obligationgs in the last timeframe int fSkipGeneral; // skips expensive generalization step int fVerbose; // verbose output` int fVeryVerbose; // very verbose output int fNotVerbose; // not printing line by line progress int fSilent; // totally silent execution int fSolveAll; // do not stop when found a SAT output int fStoreCex; // enable storing counter-examples in MO mode int fUseBridge; // use bridge interface int fUsePropOut; // use property output int nFailOuts; // the number of failed outputs int nDropOuts; // the number of timed out outputs int nProveOuts; // the number of proved outputs int iFrame; // explored up to this frame int RunId; // PDR id in this run int(*pFuncStop)(int); // callback to terminate int(*pFuncOnFail)(int,Abc_Cex_t*); // called for a failed output in MO mode abctime timeLastSolved; // the time when the last output was solved Vec_Int_t * vOutMap; // in the multi-output mode, contains status for each PO (0 = sat; 1 = unsat; negative = undecided) }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== pdrCore.c ==========================================================*/ extern void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars ); extern int Pdr_ManSolve( Aig_Man_t * p, Pdr_Par_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrClass.c000066400000000000000000000150061300674244400236670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrClass.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [Equivalence classes of register outputs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrClass.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs duplication with the variable map.] Description [Var map contains -1 if const0 and otherwise.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Pdr_ManRehashWithMap( Aig_Man_t * pAig, Vec_Int_t * vMap ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj; int i, iReg; assert( Vec_IntSize(vMap) == Aig_ManRegNum(pAig) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // create CI mapping Aig_ManCleanData( pAig ); Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames); Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi(pFrames); Saig_ManForEachLo( pAig, pObj, i ) { iReg = Vec_IntEntry(vMap, i); if ( iReg == -1 ) pObj->pData = Aig_ManConst0(pFrames); else pObj->pData = Saig_ManLo(pAig, iReg)->pData; } // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add output nodes Aig_ManForEachCo( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); // finish off Aig_ManCleanup( pFrames ); Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) ); return pFrames; } /**Function************************************************************* Synopsis [Creates mapping of registers.] Description [Var map contains -1 if const0 and otherwise.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Pdr_ManCreateMap( Aig_Man_t * p ) { Aig_Obj_t * pObj; Vec_Int_t * vMap; int * pLit2Id, Lit, i; pLit2Id = ABC_ALLOC( int, Aig_ManObjNumMax(p) * 2 ); for ( i = 0; i < Aig_ManObjNumMax(p) * 2; i++ ) pLit2Id[i] = -1; vMap = Vec_IntAlloc( Aig_ManRegNum(p) ); Saig_ManForEachLi( p, pObj, i ) { if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p) ) { Vec_IntPush( vMap, -1 ); continue; } Lit = 2 * Aig_ObjFaninId0(pObj) + Aig_ObjFaninC0(pObj); if ( pLit2Id[Lit] < 0 ) // the first time pLit2Id[Lit] = i; Vec_IntPush( vMap, pLit2Id[Lit] ); } ABC_FREE( pLit2Id ); return vMap; } /**Function************************************************************* Synopsis [Counts reduced registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManCountMap( Vec_Int_t * vMap ) { int i, Entry, Counter = 0; Vec_IntForEachEntry( vMap, Entry, i ) if ( Entry != i ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Counts reduced registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManPrintMap( Vec_Int_t * vMap ) { Vec_Int_t * vMarks; int f, i, iClass, Entry, Counter = 0; Abc_Print( 1, " Consts: " ); Vec_IntForEachEntry( vMap, Entry, i ) if ( Entry == -1 ) Abc_Print( 1, "%d ", i ); Abc_Print( 1, "\n" ); vMarks = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vMap, iClass, f ) { if ( iClass == -1 ) continue; if ( iClass == f ) continue; // check previous classes if ( Vec_IntFind( vMarks, iClass ) >= 0 ) continue; Vec_IntPush( vMarks, iClass ); // print class Abc_Print( 1, " Class %d : ", iClass ); Vec_IntForEachEntry( vMap, Entry, i ) if ( Entry == iClass ) Abc_Print( 1, "%d ", i ); Abc_Print( 1, "\n" ); } Vec_IntFree( vMarks ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManEquivClasses( Aig_Man_t * pAig ) { Vec_Int_t * vMap; Aig_Man_t * pTemp; int f, nFrames = 100; assert( Saig_ManRegNum(pAig) > 0 ); // start the map vMap = Vec_IntAlloc( 0 ); Vec_IntFill( vMap, Aig_ManRegNum(pAig), -1 ); // iterate and print changes for ( f = 0; f < nFrames; f++ ) { // implement variable map pTemp = Pdr_ManRehashWithMap( pAig, vMap ); // report the result Abc_Print( 1, "F =%4d : Total = %6d. Nodes = %6d. RedRegs = %6d. Prop = %s\n", f+1, Aig_ManNodeNum(pAig), Aig_ManNodeNum(pTemp), Pdr_ManCountMap(vMap), Aig_ObjChild0(Aig_ManCo(pTemp,0)) == Aig_ManConst0(pTemp) ? "proof" : "unknown" ); // recreate the map Pdr_ManPrintMap( vMap ); Vec_IntFree( vMap ); vMap = Pdr_ManCreateMap( pTemp ); Aig_ManStop( pTemp ); if ( Pdr_ManCountMap(vMap) == 0 ) break; } Vec_IntFree( vMap ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrCnf.c000066400000000000000000000356471300674244400233450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrCnf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [CNF computation on demand.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrCnf.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* The CNF (p->pCnf2) is expressed in terms of object IDs. Each node in the CNF is marked if it has clauses (p->pCnf2->pObj2Count[Id] > 0). Each node in the CNF has the first clause (p->pCnf2->pObj2Clause) and the number of clauses (p->pCnf2->pObj2Count). Each node used in a CNF of any timeframe has its SAT var recorded. Each frame has a reserve mapping of SAT variables into ObjIds. */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns SAT variable of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pdr_ObjSatVar1( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) { return p->pCnf1->pVarNums[ Aig_ObjId(pObj) ]; } /**Function************************************************************* Synopsis [Returns SAT variable of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //#define USE_PG #ifdef USE_PG static inline int Pdr_ObjSatVar2FindOrAdd( Pdr_Man_t * p, int k, Aig_Obj_t * pObj ) { Vec_Int_t * vId2Vars = p->pvId2Vars + Aig_ObjId(pObj); assert( p->pCnf2->pObj2Count[Aig_ObjId(pObj)] >= 0 ); if ( Vec_IntSize(vId2Vars) == 0 ) Vec_IntGrow(vId2Vars, 2 * k + 1); if ( Vec_IntGetEntry(vId2Vars, k) == 0 ) { sat_solver * pSat = Pdr_ManSolver(p, k); Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k); int iVarNew = Vec_IntSize( vVar2Ids ); assert( iVarNew > 0 ); Vec_IntPush( vVar2Ids, Aig_ObjId(pObj) ); Vec_IntWriteEntry( vId2Vars, k, iVarNew << 2 ); sat_solver_setnvars( pSat, iVarNew + 1 ); if ( k == 0 && Saig_ObjIsLo(p->pAig, pObj) ) // initialize the register output { int Lit = toLitCond( iVarNew, 1 ); int RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( RetValue == 1 ); (void) RetValue; sat_solver_compress( pSat ); } } return Vec_IntEntry( vId2Vars, k ); } int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj, int Level, int Pol ) { Vec_Int_t * vLits; sat_solver * pSat; Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k); int nVarCount = Vec_IntSize(vVar2Ids); int iVarThis = Pdr_ObjSatVar2FindOrAdd( p, k, pObj ); int * pLit, i, iVar, iClaBeg, iClaEnd, RetValue; int PolPres = (iVarThis & 3); iVarThis >>= 2; if ( Aig_ObjIsCi(pObj) ) return iVarThis; // Pol = 3; // if ( nVarCount != Vec_IntSize(vVar2Ids) || (Pol & ~PolPres) ) if ( (Pol & ~PolPres) ) { *Vec_IntEntryP( p->pvId2Vars + Aig_ObjId(pObj), k ) |= Pol; iClaBeg = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)]; iClaEnd = iClaBeg + p->pCnf2->pObj2Count[Aig_ObjId(pObj)]; assert( iClaBeg < iClaEnd ); /* if ( (Pol & ~PolPres) != 3 ) for ( i = iFirstClause; i < iFirstClause + nClauses; i++ ) { printf( "Clause %5d : ", i ); for ( iVar = 0; iVar < 4; iVar++ ) printf( "%d ", ((unsigned)p->pCnf2->pClaPols[i] >> (2*iVar)) & 3 ); printf( " " ); for ( pLit = p->pCnf2->pClauses[i]; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) printf( "%6d ", *pLit ); printf( "\n" ); } */ pSat = Pdr_ManSolver(p, k); vLits = Vec_WecEntry( p->vVLits, Level ); if ( (Pol & ~PolPres) == 3 ) { assert( nVarCount + 1 == Vec_IntSize(vVar2Ids) ); for ( i = iClaBeg; i < iClaEnd; i++ ) { Vec_IntClear( vLits ); Vec_IntPush( vLits, toLitCond( iVarThis, lit_sign(p->pCnf2->pClauses[i][0]) ) ); for ( pLit = p->pCnf2->pClauses[i]+1; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) { iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)), Level+1, 3 ); Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) ); } RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); assert( RetValue ); (void) RetValue; } } else // if ( (Pol & ~PolPres) == 2 || (Pol & ~PolPres) == 1 ) // write pos/neg polarity { assert( (Pol & ~PolPres) ); for ( i = iClaBeg; i < iClaEnd; i++ ) if ( 2 - !Abc_LitIsCompl(p->pCnf2->pClauses[i][0]) == (Pol & ~PolPres) ) // taking opposite literal { Vec_IntClear( vLits ); Vec_IntPush( vLits, toLitCond( iVarThis, Abc_LitIsCompl(p->pCnf2->pClauses[i][0]) ) ); for ( pLit = p->pCnf2->pClauses[i]+1; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) { iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)), Level+1, ((unsigned)p->pCnf2->pClaPols[i] >> (2*(pLit-p->pCnf2->pClauses[i]-1))) & 3 ); Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) ); } RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); assert( RetValue ); (void) RetValue; } } } return iVarThis; } #else static inline int Pdr_ObjSatVar2FindOrAdd( Pdr_Man_t * p, int k, Aig_Obj_t * pObj, int * pfNewVar ) { Vec_Int_t * vId2Vars = p->pvId2Vars + Aig_ObjId(pObj); assert( p->pCnf2->pObj2Count[Aig_ObjId(pObj)] >= 0 ); if ( Vec_IntSize(vId2Vars) == 0 ) Vec_IntGrow(vId2Vars, 2 * k + 1); if ( Vec_IntGetEntry(vId2Vars, k) == 0 ) { sat_solver * pSat = Pdr_ManSolver(p, k); Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k); int iVarNew = Vec_IntSize( vVar2Ids ); assert( iVarNew > 0 ); Vec_IntPush( vVar2Ids, Aig_ObjId(pObj) ); Vec_IntWriteEntry( vId2Vars, k, iVarNew ); sat_solver_setnvars( pSat, iVarNew + 1 ); if ( k == 0 && Saig_ObjIsLo(p->pAig, pObj) ) // initialize the register output { int Lit = toLitCond( iVarNew, 1 ); int RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( RetValue == 1 ); (void) RetValue; sat_solver_compress( pSat ); } *pfNewVar = 1; } return Vec_IntEntry( vId2Vars, k ); } int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj, int Level, int Pol ) { Vec_Int_t * vLits; sat_solver * pSat; int fNewVar = 0, iVarThis = Pdr_ObjSatVar2FindOrAdd( p, k, pObj, &fNewVar ); int * pLit, i, iVar, iClaBeg, iClaEnd, RetValue; if ( Aig_ObjIsCi(pObj) || !fNewVar ) return iVarThis; iClaBeg = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)]; iClaEnd = iClaBeg + p->pCnf2->pObj2Count[Aig_ObjId(pObj)]; assert( iClaBeg < iClaEnd ); pSat = Pdr_ManSolver(p, k); vLits = Vec_WecEntry( p->vVLits, Level ); for ( i = iClaBeg; i < iClaEnd; i++ ) { Vec_IntClear( vLits ); Vec_IntPush( vLits, toLitCond( iVarThis, lit_sign(p->pCnf2->pClauses[i][0]) ) ); for ( pLit = p->pCnf2->pClauses[i]+1; pLit < p->pCnf2->pClauses[i+1]; pLit++ ) { iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)), Level+1, Pol ); Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) ); } RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) ); assert( RetValue ); (void) RetValue; } return iVarThis; } #endif /**Function************************************************************* Synopsis [Returns SAT variable of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ObjSatVar( Pdr_Man_t * p, int k, int Pol, Aig_Obj_t * pObj ) { if ( p->pPars->fMonoCnf ) return Pdr_ObjSatVar1( p, k, pObj ); else return Pdr_ObjSatVar2( p, k, pObj, 0, Pol ); } /**Function************************************************************* Synopsis [Returns register number for the given SAT variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pdr_ObjRegNum1( Pdr_Man_t * p, int k, int iSatVar ) { int RegId; assert( iSatVar >= 0 ); // consider the case of auxiliary variable if ( iSatVar >= p->pCnf1->nVars ) return -1; // consider the case of register output RegId = Vec_IntEntry( p->vVar2Reg, iSatVar ); assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) ); return RegId; } /**Function************************************************************* Synopsis [Returns register number for the given SAT variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pdr_ObjRegNum2( Pdr_Man_t * p, int k, int iSatVar ) { Aig_Obj_t * pObj; int ObjId; Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, k); assert( iSatVar > 0 && iSatVar < Vec_IntSize(vVar2Ids) ); ObjId = Vec_IntEntry( vVar2Ids, iSatVar ); if ( ObjId == -1 ) // activation variable return -1; pObj = Aig_ManObj( p->pAig, ObjId ); if ( Saig_ObjIsLi( p->pAig, pObj ) ) return Aig_ObjCioId(pObj)-Saig_ManPoNum(p->pAig); assert( 0 ); // should be called for register inputs only return -1; } /**Function************************************************************* Synopsis [Returns register number for the given SAT variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar ) { if ( p->pPars->fMonoCnf ) return Pdr_ObjRegNum1( p, k, iSatVar ); else return Pdr_ObjRegNum2( p, k, iSatVar ); } /**Function************************************************************* Synopsis [Returns the index of unused SAT variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManFreeVar( Pdr_Man_t * p, int k ) { if ( p->pPars->fMonoCnf ) return sat_solver_nvars( Pdr_ManSolver(p, k) ); else { Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry( &p->vVar2Ids, k ); Vec_IntPush( vVar2Ids, -1 ); return Vec_IntSize( vVar2Ids ) - 1; } } /**Function************************************************************* Synopsis [Creates SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline sat_solver * Pdr_ManNewSolver1( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) { Aig_Obj_t * pObj; int i; assert( pSat ); if ( p->pCnf1 == NULL ) { int nRegs = p->pAig->nRegs; p->pAig->nRegs = Aig_ManCoNum(p->pAig); p->pCnf1 = Cnf_DeriveWithMan( p->pCnfMan, p->pAig, Aig_ManCoNum(p->pAig) ); p->pAig->nRegs = nRegs; assert( p->vVar2Reg == NULL ); p->vVar2Reg = Vec_IntStartFull( p->pCnf1->nVars ); Saig_ManForEachLi( p->pAig, pObj, i ) Vec_IntWriteEntry( p->vVar2Reg, Pdr_ObjSatVar(p, k, 3, pObj), i ); } pSat = (sat_solver *)Cnf_DataWriteIntoSolverInt( pSat, p->pCnf1, 1, fInit ); sat_solver_set_runtime_limit( pSat, p->timeToStop ); return pSat; } /**Function************************************************************* Synopsis [Creates SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline sat_solver * Pdr_ManNewSolver2( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) { Vec_Int_t * vVar2Ids; int i, Entry; assert( pSat ); if ( p->pCnf2 == NULL ) { p->pCnf2 = Cnf_DeriveOtherWithMan( p->pCnfMan, p->pAig, 0 ); #ifdef USE_PG p->pCnf2->pClaPols = Cnf_DataDeriveLitPolarities( p->pCnf2 ); #endif p->pvId2Vars = ABC_CALLOC( Vec_Int_t, Aig_ManObjNumMax(p->pAig) ); Vec_PtrGrow( &p->vVar2Ids, 256 ); } // update the variable mapping vVar2Ids = (Vec_Int_t *)Vec_PtrGetEntry( &p->vVar2Ids, k ); if ( vVar2Ids == NULL ) { vVar2Ids = Vec_IntAlloc( 500 ); Vec_PtrWriteEntry( &p->vVar2Ids, k, vVar2Ids ); } Vec_IntForEachEntry( vVar2Ids, Entry, i ) { if ( Entry == -1 ) continue; assert( Vec_IntEntry( p->pvId2Vars + Entry, k ) > 0 ); Vec_IntWriteEntry( p->pvId2Vars + Entry, k, 0 ); } Vec_IntClear( vVar2Ids ); Vec_IntPush( vVar2Ids, -1 ); // start the SAT solver // pSat = sat_solver_new(); sat_solver_setnvars( pSat, 500 ); sat_solver_set_runtime_limit( pSat, p->timeToStop ); return pSat; } /**Function************************************************************* Synopsis [Creates SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ) { assert( pSat != NULL ); if ( p->pPars->fMonoCnf ) return Pdr_ManNewSolver1( pSat, p, k, fInit ); else return Pdr_ManNewSolver2( pSat, p, k, fInit ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrCore.c000066400000000000000000001102301300674244400235050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [Core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrCore.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved ); extern int Gia_ManToBridgeAbort( FILE * pFile, int Size, unsigned char * pBuffer ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if the state could be blocked.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars ) { memset( pPars, 0, sizeof(Pdr_Par_t) ); // pPars->iOutput = -1; // zero-based output number pPars->nRecycle = 300; // limit on vars for recycling pPars->nFrameMax = 10000; // limit on number of timeframes pPars->nTimeOut = 0; // timeout in seconds pPars->nTimeOutGap = 0; // timeout in seconds since the last solved pPars->nConfLimit = 0; // limit on SAT solver conflicts pPars->nConfGenLimit = 0; // limit on SAT solver conflicts during generalization pPars->nRestLimit = 0; // limit on the number of proof-obligations pPars->fTwoRounds = 0; // use two rounds for generalization pPars->fMonoCnf = 0; // monolythic CNF pPars->fDumpInv = 0; // dump inductive invariant pPars->fUseSupp = 1; // using support variables in the invariant pPars->fShortest = 0; // forces bug traces to be shortest pPars->fUsePropOut = 1; // use property output pPars->fVerbose = 0; // verbose output pPars->fVeryVerbose = 0; // very verbose output pPars->fNotVerbose = 0; // not printing line-by-line progress pPars->iFrame = -1; // explored up to this frame pPars->nFailOuts = 0; // the number of disproved outputs pPars->nDropOuts = 0; // the number of timed out outputs pPars->timeLastSolved = 0; // last one solved } /**Function************************************************************* Synopsis [Reduces clause using analyzeFinal.] Description [Assumes that the SAT solver just terminated an UNSAT call.] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Set_t * Pdr_ManReduceClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) { Pdr_Set_t * pCubeMin; Vec_Int_t * vLits; int i, Entry, nCoreLits, * pCoreLits; // get relevant SAT literals nCoreLits = sat_solver_final(Pdr_ManSolver(p, k), &pCoreLits); // translate them into register literals and remove auxiliary vLits = Pdr_ManLitsToCube( p, k, pCoreLits, nCoreLits ); // skip if there is no improvement if ( Vec_IntSize(vLits) == pCube->nLits ) return NULL; assert( Vec_IntSize(vLits) < pCube->nLits ); // if the cube overlaps with init, add any literal Vec_IntForEachEntry( vLits, Entry, i ) if ( lit_sign(Entry) == 0 ) // positive literal break; if ( i == Vec_IntSize(vLits) ) // only negative literals { // add the first positive literal for ( i = 0; i < pCube->nLits; i++ ) if ( lit_sign(pCube->Lits[i]) == 0 ) // positive literal { Vec_IntPush( vLits, pCube->Lits[i] ); break; } assert( i < pCube->nLits ); } // generate a starting cube pCubeMin = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits), Vec_IntSize(vLits) ); assert( !Pdr_SetIsInit(pCubeMin, -1) ); /* // make sure the cube works { int RetValue; RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0, 0 ); assert( RetValue ); } */ return pCubeMin; } /**Function************************************************************* Synopsis [Returns 1 if the state could be blocked.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManPushClauses( Pdr_Man_t * p ) { Pdr_Set_t * pTemp, * pCubeK, * pCubeK1; Vec_Ptr_t * vArrayK, * vArrayK1; int i, j, k, m, RetValue = 0, RetValue2, kMax = Vec_PtrSize(p->vSolvers)-1; int iStartFrame = p->pPars->fShiftStart ? p->iUseFrame : 1; int Counter = 0; abctime clk = Abc_Clock(); assert( p->iUseFrame > 0 ); Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, iStartFrame, kMax ) { Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); vArrayK1 = Vec_VecEntry( p->vClauses, k+1 ); Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) { Counter++; // remove cubes in the same frame that are contained by pCubeK Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 ) { if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp continue; Pdr_SetDeref( pTemp ); Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) ); Vec_PtrPop(vArrayK); m--; } // check if the clause can be moved to the next frame RetValue2 = Pdr_ManCheckCube( p, k, pCubeK, NULL, 0, 0 ); if ( RetValue2 == -1 ) return -1; if ( !RetValue2 ) continue; { Pdr_Set_t * pCubeMin; pCubeMin = Pdr_ManReduceClause( p, k, pCubeK ); if ( pCubeMin != NULL ) { // Abc_Print( 1, "%d ", pCubeK->nLits - pCubeMin->nLits ); Pdr_SetDeref( pCubeK ); pCubeK = pCubeMin; } } // if it can be moved, add it to the next frame Pdr_ManSolverAddClause( p, k+1, pCubeK ); // check if the clause subsumes others Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK1, pCubeK1, i ) { if ( !Pdr_SetContains( pCubeK1, pCubeK ) ) // pCubeK contains pCubeK1 continue; Pdr_SetDeref( pCubeK1 ); Vec_PtrWriteEntry( vArrayK1, i, Vec_PtrEntryLast(vArrayK1) ); Vec_PtrPop(vArrayK1); i--; } // add the last clause Vec_PtrPush( vArrayK1, pCubeK ); Vec_PtrWriteEntry( vArrayK, j, Vec_PtrEntryLast(vArrayK) ); Vec_PtrPop(vArrayK); j--; } if ( Vec_PtrSize(vArrayK) == 0 ) RetValue = 1; } // clean up the last one vArrayK = Vec_VecEntry( p->vClauses, kMax ); Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j ) { // remove cubes in the same frame that are contained by pCubeK Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 ) { if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp continue; /* Abc_Print( 1, "===\n" ); Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL ); Abc_Print( 1, "\n" ); Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL ); Abc_Print( 1, "\n" ); */ Pdr_SetDeref( pTemp ); Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) ); Vec_PtrPop(vArrayK); m--; } } p->tPush += Abc_Clock() - clk; return RetValue; } /**Function************************************************************* Synopsis [Returns 1 if the clause is contained in higher clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet ) { Pdr_Set_t * pThis; Vec_Ptr_t * vArrayK; int i, j, kMax = Vec_PtrSize(p->vSolvers)-1; Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, i, k, kMax+1 ) Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pThis, j ) if ( Pdr_SetContains( pSet, pThis ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Sorts literals by priority.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Pdr_ManSortByPriority( Pdr_Man_t * p, Pdr_Set_t * pCube ) { int * pPrios = Vec_IntArray(p->vPrio); int * pArray = p->pOrder; int temp, i, j, best_i, nSize = pCube->nLits; // initialize variable order for ( i = 0; i < nSize; i++ ) pArray[i] = i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) // if ( pArray[j] < pArray[best_i] ) if ( pPrios[pCube->Lits[pArray[j]]>>1] < pPrios[pCube->Lits[pArray[best_i]]>>1] ) best_i = j; temp = pArray[i]; pArray[i] = pArray[best_i]; pArray[best_i] = temp; } /* for ( i = 0; i < pCube->nLits; i++ ) Abc_Print( 1, "%2d : %5d %5d %5d\n", i, pArray[i], pCube->Lits[pArray[i]]>>1, pPrios[pCube->Lits[pArray[i]]>>1] ); Abc_Print( 1, "\n" ); */ return pArray; } /**Function************************************************************* Synopsis [Returns 1 if the state could be blocked.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManGeneralize( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, Pdr_Set_t ** ppCubeMin ) { Pdr_Set_t * pCubeMin, * pCubeTmp = NULL; int i, j, n, Lit, RetValue; abctime clk = Abc_Clock(); int * pOrder; // if there is no induction, return *ppCubeMin = NULL; RetValue = Pdr_ManCheckCube( p, k, pCube, ppPred, p->pPars->nConfLimit, 0 ); if ( RetValue == -1 ) return -1; if ( RetValue == 0 ) { p->tGeneral += Abc_Clock() - clk; return 0; } // reduce clause using assumptions // pCubeMin = Pdr_SetDup( pCube ); pCubeMin = Pdr_ManReduceClause( p, k, pCube ); if ( pCubeMin == NULL ) pCubeMin = Pdr_SetDup( pCube ); // perform generalization if ( !p->pPars->fSkipGeneral ) { // sort literals by their occurences pOrder = Pdr_ManSortByPriority( p, pCubeMin ); // try removing literals for ( j = 0; j < pCubeMin->nLits; j++ ) { // use ordering // i = j; i = pOrder[j]; // check init state assert( pCubeMin->Lits[i] != -1 ); if ( Pdr_SetIsInit(pCubeMin, i) ) continue; // try removing this literal Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit, 1 ); if ( RetValue == -1 ) { Pdr_SetDeref( pCubeMin ); return -1; } pCubeMin->Lits[i] = Lit; if ( RetValue == 0 ) continue; // remove j-th entry for ( n = j; n < pCubeMin->nLits-1; n++ ) pOrder[n] = pOrder[n+1]; j--; // success - update the cube pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i ); Pdr_SetDeref( pCubeTmp ); assert( pCubeMin->nLits > 0 ); i--; // get the ordering by decreasing priorit pOrder = Pdr_ManSortByPriority( p, pCubeMin ); } if ( p->pPars->fTwoRounds ) for ( j = 0; j < pCubeMin->nLits; j++ ) { // use ordering // i = j; i = pOrder[j]; // check init state assert( pCubeMin->Lits[i] != -1 ); if ( Pdr_SetIsInit(pCubeMin, i) ) continue; // try removing this literal Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit, 0 ); if ( RetValue == -1 ) { Pdr_SetDeref( pCubeMin ); return -1; } pCubeMin->Lits[i] = Lit; if ( RetValue == 0 ) continue; // remove j-th entry for ( n = j; n < pCubeMin->nLits-1; n++ ) pOrder[n] = pOrder[n+1]; j--; // success - update the cube pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i ); Pdr_SetDeref( pCubeTmp ); assert( pCubeMin->nLits > 0 ); i--; // get the ordering by decreasing priorit pOrder = Pdr_ManSortByPriority( p, pCubeMin ); } } assert( ppCubeMin != NULL ); *ppCubeMin = pCubeMin; p->tGeneral += Abc_Clock() - clk; return 1; } /**Function************************************************************* Synopsis [Returns 1 if the state could be blocked.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManBlockCube( Pdr_Man_t * p, Pdr_Set_t * pCube ) { Pdr_Obl_t * pThis; Pdr_Set_t * pPred, * pCubeMin; int i, k, RetValue, Prio = ABC_INFINITY, Counter = 0; int kMax = Vec_PtrSize(p->vSolvers)-1; abctime clk; p->nBlocks++; // create first proof obligation // assert( p->pQueue == NULL ); pThis = Pdr_OblStart( kMax, Prio--, pCube, NULL ); // consume ref Pdr_QueuePush( p, pThis ); // try to solve it recursively while ( !Pdr_QueueIsEmpty(p) ) { Counter++; pThis = Pdr_QueueHead( p ); if ( pThis->iFrame == 0 ) return 0; // SAT if ( pThis->iFrame > kMax ) // finished this level return 1; if ( p->nQueLim && p->nQueCur >= p->nQueLim ) { p->nQueLim = p->nQueLim * 3 / 2; Pdr_QueueStop( p ); return 1; // restart } pThis = Pdr_QueuePop( p ); assert( pThis->iFrame > 0 ); assert( !Pdr_SetIsInit(pThis->pState, -1) ); p->iUseFrame = Abc_MinInt( p->iUseFrame, pThis->iFrame ); clk = Abc_Clock(); if ( Pdr_ManCheckContainment( p, pThis->iFrame, pThis->pState ) ) { p->tContain += Abc_Clock() - clk; Pdr_OblDeref( pThis ); continue; } p->tContain += Abc_Clock() - clk; // check if the cube is already contained RetValue = Pdr_ManCheckCubeCs( p, pThis->iFrame, pThis->pState ); if ( RetValue == -1 ) // resource limit is reached { Pdr_OblDeref( pThis ); return -1; } if ( RetValue ) // cube is blocked by clauses in this frame { Pdr_OblDeref( pThis ); continue; } // check if the cube holds with relative induction pCubeMin = NULL; RetValue = Pdr_ManGeneralize( p, pThis->iFrame-1, pThis->pState, &pPred, &pCubeMin ); if ( RetValue == -1 ) // resource limit is reached { Pdr_OblDeref( pThis ); return -1; } if ( RetValue ) // cube is blocked inductively in this frame { assert( pCubeMin != NULL ); // k is the last frame where pCubeMin holds k = pThis->iFrame; // check other frames assert( pPred == NULL ); for ( k = pThis->iFrame; k < kMax; k++ ) { RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0, 0 ); if ( RetValue == -1 ) { Pdr_OblDeref( pThis ); return -1; } if ( !RetValue ) break; } // add new clause if ( p->pPars->fVeryVerbose ) { Abc_Print( 1, "Adding cube " ); Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL ); Abc_Print( 1, " to frame %d.\n", k ); } // set priority flops for ( i = 0; i < pCubeMin->nLits; i++ ) { assert( pCubeMin->Lits[i] >= 0 ); assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) ); Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 ); } Vec_VecPush( p->vClauses, k, pCubeMin ); // consume ref p->nCubes++; // add clause for ( i = 1; i <= k; i++ ) Pdr_ManSolverAddClause( p, i, pCubeMin ); // schedule proof obligation if ( (k < kMax || p->pPars->fReuseProofOblig) && !p->pPars->fShortest ) { pThis->iFrame = k+1; pThis->prio = Prio--; Pdr_QueuePush( p, pThis ); } else { Pdr_OblDeref( pThis ); } } else { assert( pCubeMin == NULL ); assert( pPred != NULL ); pThis->prio = Prio--; Pdr_QueuePush( p, pThis ); pThis = Pdr_OblStart( pThis->iFrame-1, Prio--, pPred, Pdr_OblRef(pThis) ); Pdr_QueuePush( p, pThis ); } // check termination if ( p->pPars->pFuncStop && p->pPars->pFuncStop(p->pPars->RunId) ) return -1; if ( p->timeToStop && Abc_Clock() > p->timeToStop ) return -1; if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne ) return -1; if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) return -1; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManSolveInt( Pdr_Man_t * p ) { int fPrintClauses = 0; Pdr_Set_t * pCube = NULL; Aig_Obj_t * pObj; Abc_Cex_t * pCexNew; int k, RetValue = -1; int nOutDigits = Abc_Base10Log( Saig_ManPoNum(p->pAig) ); abctime clkStart = Abc_Clock(), clkOne = 0; p->timeToStop = p->pPars->nTimeOut ? p->pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; assert( Vec_PtrSize(p->vSolvers) == 0 ); // in the multi-output mode, mark trivial POs (those fed by const0) as solved if ( p->pPars->fSolveAll ) Saig_ManForEachPo( p->pAig, pObj, k ) if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p->pAig) ) { Vec_IntWriteEntry( p->pPars->vOutMap, k, 1 ); // unsat p->pPars->nProveOuts++; if ( p->pPars->fUseBridge ) Gia_ManToBridgeResult( stdout, 1, NULL, k ); } // create the first timeframe p->pPars->timeLastSolved = Abc_Clock(); Pdr_ManCreateSolver( p, (k = 0) ); while ( 1 ) { p->nFrames = k; assert( k == Vec_PtrSize(p->vSolvers)-1 ); p->iUseFrame = Abc_MaxInt(k, 1); Saig_ManForEachPo( p->pAig, pObj, p->iOutCur ) { // skip disproved outputs if ( p->vCexes && Vec_PtrEntry(p->vCexes, p->iOutCur) ) continue; // skip output whose time has run out if ( p->pTime4Outs && p->pTime4Outs[p->iOutCur] == 0 ) continue; // check if the output is trivially solved if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p->pAig) ) continue; // check if the output is trivially solved if ( Aig_ObjChild0(pObj) == Aig_ManConst1(p->pAig) ) { if ( !p->pPars->fSolveAll ) { pCexNew = Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), k*Saig_ManPoNum(p->pAig)+p->iOutCur ); p->pAig->pSeqModel = pCexNew; return 0; // SAT } pCexNew = (p->pPars->fUseBridge || p->pPars->fStoreCex) ? Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), k*Saig_ManPoNum(p->pAig)+p->iOutCur ) : (Abc_Cex_t *)(ABC_PTRINT_T)1; p->pPars->nFailOuts++; if ( p->pPars->vOutMap ) Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, 0 ); if ( !p->pPars->fNotVerbose ) Abc_Print( 1, "Output %*d was trivially asserted in frame %2d (solved %*d out of %*d outputs).\n", nOutDigits, p->iOutCur, k, nOutDigits, p->pPars->nFailOuts, nOutDigits, Saig_ManPoNum(p->pAig) ); assert( Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL ); if ( p->pPars->fUseBridge ) Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo ); Vec_PtrWriteEntry( p->vCexes, p->iOutCur, pCexNew ); if ( p->pPars->pFuncOnFail && p->pPars->pFuncOnFail(p->iOutCur, p->pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, p->iOutCur) : NULL) ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( !p->pPars->fSilent ) Abc_Print( 1, "Quitting due to callback on fail.\n" ); p->pPars->iFrame = k; return -1; } if ( p->pPars->nFailOuts + p->pPars->nDropOuts == Saig_ManPoNum(p->pAig) ) return p->pPars->nFailOuts ? 0 : -1; // SAT or UNDEC p->pPars->timeLastSolved = Abc_Clock(); continue; } // try to solve this output if ( p->pTime4Outs ) { assert( p->pTime4Outs[p->iOutCur] > 0 ); clkOne = Abc_Clock(); p->timeToStopOne = p->pTime4Outs[p->iOutCur] + Abc_Clock(); } while ( 1 ) { if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( !p->pPars->fSilent ) Abc_Print( 1, "Reached gap timeout (%d seconds).\n", p->pPars->nTimeOutGap ); p->pPars->iFrame = k; return -1; } RetValue = Pdr_ManCheckCube( p, k, NULL, &pCube, p->pPars->nConfLimit, 0 ); if ( RetValue == 1 ) break; if ( RetValue == -1 ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( p->timeToStop && Abc_Clock() > p->timeToStop ) Abc_Print( 1, "Reached timeout (%d seconds).\n", p->pPars->nTimeOut ); else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) Abc_Print( 1, "Reached gap timeout (%d seconds).\n", p->pPars->nTimeOutGap ); else if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne ) { Pdr_QueueClean( p ); pCube = NULL; break; // keep solving } else if ( p->pPars->nConfLimit ) Abc_Print( 1, "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); else if ( p->pPars->fVerbose ) Abc_Print( 1, "Computation cancelled by the callback.\n" ); p->pPars->iFrame = k; return -1; } if ( RetValue == 0 ) { RetValue = Pdr_ManBlockCube( p, pCube ); if ( RetValue == -1 ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( p->timeToStop && Abc_Clock() > p->timeToStop ) Abc_Print( 1, "Reached timeout (%d seconds).\n", p->pPars->nTimeOut ); else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) Abc_Print( 1, "Reached gap timeout (%d seconds).\n", p->pPars->nTimeOutGap ); else if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne ) { Pdr_QueueClean( p ); pCube = NULL; break; // keep solving } else if ( p->pPars->nConfLimit ) Abc_Print( 1, "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); else if ( p->pPars->fVerbose ) Abc_Print( 1, "Computation cancelled by the callback.\n" ); p->pPars->iFrame = k; return -1; } if ( RetValue == 0 ) { if ( fPrintClauses ) { Abc_Print( 1, "*** Clauses after frame %d:\n", k ); Pdr_ManPrintClauses( p, 0 ); } if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, !p->pPars->fSolveAll, Abc_Clock() - clkStart ); p->pPars->iFrame = k; if ( !p->pPars->fSolveAll ) { p->pAig->pSeqModel = Pdr_ManDeriveCex(p); return 0; // SAT } p->pPars->nFailOuts++; pCexNew = (p->pPars->fUseBridge || p->pPars->fStoreCex) ? Pdr_ManDeriveCex(p) : (Abc_Cex_t *)(ABC_PTRINT_T)1; if ( p->pPars->vOutMap ) Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, 0 ); assert( Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL ); if ( p->pPars->fUseBridge ) Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo ); Vec_PtrWriteEntry( p->vCexes, p->iOutCur, pCexNew ); if ( p->pPars->pFuncOnFail && p->pPars->pFuncOnFail(p->iOutCur, p->pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, p->iOutCur) : NULL) ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( !p->pPars->fSilent ) Abc_Print( 1, "Quitting due to callback on fail.\n" ); p->pPars->iFrame = k; return -1; } if ( !p->pPars->fNotVerbose ) Abc_Print( 1, "Output %*d was asserted in frame %2d (%2d) (solved %*d out of %*d outputs).\n", nOutDigits, p->iOutCur, k, k, nOutDigits, p->pPars->nFailOuts, nOutDigits, Saig_ManPoNum(p->pAig) ); if ( p->pPars->nFailOuts == Saig_ManPoNum(p->pAig) ) return 0; // all SAT Pdr_QueueClean( p ); pCube = NULL; break; // keep solving } if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 0, Abc_Clock() - clkStart ); } } if ( p->pTime4Outs ) { abctime timeSince = Abc_Clock() - clkOne; assert( p->pTime4Outs[p->iOutCur] > 0 ); p->pTime4Outs[p->iOutCur] = (p->pTime4Outs[p->iOutCur] > timeSince) ? p->pTime4Outs[p->iOutCur] - timeSince : 0; if ( p->pTime4Outs[p->iOutCur] == 0 && Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL ) // undecided { p->pPars->nDropOuts++; if ( p->pPars->vOutMap ) Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, -1 ); if ( !p->pPars->fNotVerbose ) Abc_Print( 1, "Timing out on output %*d.\n", nOutDigits, p->iOutCur ); } p->timeToStopOne = 0; } } if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); // open a new timeframe p->nQueLim = p->pPars->nRestLimit; assert( pCube == NULL ); Pdr_ManSetPropertyOutput( p, k ); Pdr_ManCreateSolver( p, ++k ); if ( fPrintClauses ) { Abc_Print( 1, "*** Clauses after frame %d:\n", k ); Pdr_ManPrintClauses( p, 0 ); } // push clauses into this timeframe RetValue = Pdr_ManPushClauses( p ); if ( RetValue == -1 ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( !p->pPars->fSilent ) { if ( p->timeToStop && Abc_Clock() > p->timeToStop ) Abc_Print( 1, "Reached timeout (%d seconds).\n", p->pPars->nTimeOut ); else Abc_Print( 1, "Reached conflict limit (%d).\n", p->pPars->nConfLimit ); } p->pPars->iFrame = k; return -1; } if ( RetValue ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( !p->pPars->fSilent ) Pdr_ManReportInvariant( p ); if ( !p->pPars->fSilent ) Pdr_ManVerifyInvariant( p ); p->pPars->iFrame = k; // count the number of UNSAT outputs p->pPars->nProveOuts = Saig_ManPoNum(p->pAig) - p->pPars->nFailOuts - p->pPars->nDropOuts; // convert previously 'unknown' into 'unsat' if ( p->pPars->vOutMap ) for ( k = 0; k < Saig_ManPoNum(p->pAig); k++ ) if ( Vec_IntEntry(p->pPars->vOutMap, k) == -2 ) // unknown { Vec_IntWriteEntry( p->pPars->vOutMap, k, 1 ); // unsat if ( p->pPars->fUseBridge ) Gia_ManToBridgeResult( stdout, 1, NULL, k ); } if ( p->pPars->nProveOuts == Saig_ManPoNum(p->pAig) ) return 1; // UNSAT if ( p->pPars->nFailOuts > 0 ) return 0; // SAT return -1; } if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 0, Abc_Clock() - clkStart ); // check termination if ( p->pPars->pFuncStop && p->pPars->pFuncStop(p->pPars->RunId) ) { p->pPars->iFrame = k; return -1; } if ( p->timeToStop && Abc_Clock() > p->timeToStop ) { if ( fPrintClauses ) { Abc_Print( 1, "*** Clauses after frame %d:\n", k ); Pdr_ManPrintClauses( p, 0 ); } if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( !p->pPars->fSilent ) Abc_Print( 1, "Reached timeout (%d seconds).\n", p->pPars->nTimeOut ); p->pPars->iFrame = k; return -1; } if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC ) { if ( fPrintClauses ) { Abc_Print( 1, "*** Clauses after frame %d:\n", k ); Pdr_ManPrintClauses( p, 0 ); } if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( !p->pPars->fSilent ) Abc_Print( 1, "Reached gap timeout (%d seconds).\n", p->pPars->nTimeOutGap ); p->pPars->iFrame = k; return -1; } if ( p->pPars->nFrameMax && k >= p->pPars->nFrameMax ) { if ( p->pPars->fVerbose ) Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart ); if ( !p->pPars->fSilent ) Abc_Print( 1, "Reached limit on the number of timeframes (%d).\n", p->pPars->nFrameMax ); p->pPars->iFrame = k; return -1; } } assert( 0 ); return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManSolve( Aig_Man_t * pAig, Pdr_Par_t * pPars ) { Pdr_Man_t * p; int k, RetValue; abctime clk = Abc_Clock(); if ( pPars->nTimeOutOne && !pPars->fSolveAll ) pPars->nTimeOutOne = 0; if ( pPars->nTimeOutOne && pPars->nTimeOut == 0 ) pPars->nTimeOut = pPars->nTimeOutOne * Saig_ManPoNum(pAig) / 1000 + (int)((pPars->nTimeOutOne * Saig_ManPoNum(pAig) % 1000) > 0); if ( pPars->fVerbose ) { // Abc_Print( 1, "Running PDR by Niklas Een (aka IC3 by Aaron Bradley) with these parameters:\n" ); Abc_Print( 1, "VarMax = %d. FrameMax = %d. QueMax = %d. TimeMax = %d. ", pPars->nRecycle, pPars->nFrameMax, pPars->nRestLimit, pPars->nTimeOut ); Abc_Print( 1, "MonoCNF = %s. SkipGen = %s. SolveAll = %s.\n", pPars->fMonoCnf ? "yes" : "no", pPars->fSkipGeneral ? "yes" : "no", pPars->fSolveAll ? "yes" : "no" ); } ABC_FREE( pAig->pSeqModel ); p = Pdr_ManStart( pAig, pPars, NULL ); RetValue = Pdr_ManSolveInt( p ); if ( RetValue == 0 ) assert( pAig->pSeqModel != NULL || p->vCexes != NULL ); if ( p->vCexes ) { assert( p->pAig->vSeqModelVec == NULL ); p->pAig->vSeqModelVec = p->vCexes; p->vCexes = NULL; } if ( p->pPars->fDumpInv ) { Abc_FrameSetCnf( Pdr_ManDeriveInfinityClauses( p, RetValue!=1 ) ); Abc_FrameSetStr( Pdr_ManDumpString(p) ); Abc_FrameSetInv( Pdr_ManCountFlopsInv(p) ); Pdr_ManDumpClauses( p, (char *)"inv.pla", RetValue==1 ); } p->tTotal += Abc_Clock() - clk; Pdr_ManStop( p ); pPars->iFrame--; // convert all -2 (unknown) entries into -1 (undec) if ( pPars->vOutMap ) for ( k = 0; k < Saig_ManPoNum(pAig); k++ ) if ( Vec_IntEntry(pPars->vOutMap, k) == -2 ) // unknown Vec_IntWriteEntry( pPars->vOutMap, k, -1 ); // undec if ( pPars->fUseBridge ) Gia_ManToBridgeAbort( stdout, 7, (unsigned char *)"timeout" ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrInt.h000066400000000000000000000241211300674244400233570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrInt.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__sat__pdr__pdrInt_h #define ABC__sat__pdr__pdrInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/saig/saig.h" #include "misc/vec/vecWec.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" #include "pdr.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Pdr_Set_t_ Pdr_Set_t; struct Pdr_Set_t_ { word Sign; // signature int nRefs; // ref counter int nTotal; // total literals int nLits; // num flop literals int Lits[0]; }; typedef struct Pdr_Obl_t_ Pdr_Obl_t; struct Pdr_Obl_t_ { int iFrame; // time frame int prio; // priority int nRefs; // reference counter Pdr_Set_t * pState; // state cube Pdr_Obl_t * pNext; // next one Pdr_Obl_t * pLink; // queue link }; typedef struct Pdr_Man_t_ Pdr_Man_t; struct Pdr_Man_t_ { // input problem Pdr_Par_t * pPars; // parameters Aig_Man_t * pAig; // user's AIG // static CNF representation Cnf_Man_t * pCnfMan; // CNF manager Cnf_Dat_t * pCnf1; // CNF for this AIG Vec_Int_t * vVar2Reg; // mapping of SAT var into registers // dynamic CNF representation Cnf_Dat_t * pCnf2; // CNF for this AIG Vec_Int_t * pvId2Vars; // for each used ObjId, maps frame into SAT var Vec_Ptr_t vVar2Ids; // for each used frame, maps SAT var into ObjId Vec_Wec_t * vVLits; // CNF literals // data representation int iOutCur; // current output Vec_Ptr_t * vCexes; // counter-examples for each output Vec_Ptr_t * vSolvers; // SAT solvers Vec_Vec_t * vClauses; // clauses by timeframe Pdr_Obl_t * pQueue; // proof obligations int * pOrder; // ordering of the lits Vec_Int_t * vActVars; // the counter of activation variables int iUseFrame; // the first used frame // internal use Vec_Int_t * vPrio; // priority flops Vec_Int_t * vLits; // array of literals Vec_Int_t * vCiObjs; // cone leaves Vec_Int_t * vCoObjs; // cone roots Vec_Int_t * vCiVals; // cone leaf values Vec_Int_t * vCoVals; // cone root values Vec_Int_t * vNodes; // cone nodes Vec_Int_t * vUndo; // cone undos Vec_Int_t * vVisits; // intermediate Vec_Int_t * vCi2Rem; // CIs to be removed Vec_Int_t * vRes; // final result Vec_Int_t * vSuppLits; // support literals Pdr_Set_t * pCubeJust; // justification abctime * pTime4Outs;// timeout per output Vec_Ptr_t * vInfCubes; // infinity clauses/cubes // statistics int nBlocks; // the number of times blockState was called int nObligs; // the number of proof obligations derived int nCubes; // the number of cubes derived int nCalls; // the number of SAT calls int nCallsS; // the number of SAT calls (sat) int nCallsU; // the number of SAT calls (unsat) int nStarts; // the number of SAT solver restarts int nFrames; // frames explored int nCasesSS; int nCasesSU; int nCasesUS; int nCasesUU; int nQueCur; int nQueMax; int nQueLim; // runtime abctime timeToStop; abctime timeToStopOne; // time stats abctime tSat; abctime tSatSat; abctime tSatUnsat; abctime tGeneral; abctime tPush; abctime tTsim; abctime tContain; abctime tCnf; abctime tTotal; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline sat_solver * Pdr_ManSolver( Pdr_Man_t * p, int k ) { return (sat_solver *)Vec_PtrEntry(p->vSolvers, k); } static inline abctime Pdr_ManTimeLimit( Pdr_Man_t * p ) { if ( p->timeToStop == 0 ) return p->timeToStopOne; if ( p->timeToStopOne == 0 ) return p->timeToStop; if ( p->timeToStop < p->timeToStopOne ) return p->timeToStop; return p->timeToStopOne; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== pdrCex.c ==========================================================*/ extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ); /*=== pdrCnf.c ==========================================================*/ extern int Pdr_ObjSatVar( Pdr_Man_t * p, int k, int Pol, Aig_Obj_t * pObj ); extern int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar ); extern int Pdr_ManFreeVar( Pdr_Man_t * p, int k ); extern sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit ); /*=== pdrCore.c ==========================================================*/ extern int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet ); /*=== pdrInv.c ==========================================================*/ extern Vec_Int_t * Pdr_ManCountFlopsInv( Pdr_Man_t * p ); extern void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, abctime Time ); extern void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart ); extern void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved ); extern Vec_Str_t * Pdr_ManDumpString( Pdr_Man_t * p ); extern void Pdr_ManReportInvariant( Pdr_Man_t * p ); extern void Pdr_ManVerifyInvariant( Pdr_Man_t * p ); extern Vec_Int_t * Pdr_ManDeriveInfinityClauses( Pdr_Man_t * p, int fReduce ); /*=== pdrMan.c ==========================================================*/ extern Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit ); extern void Pdr_ManStop( Pdr_Man_t * p ); extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ); /*=== pdrSat.c ==========================================================*/ extern sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k ); extern sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k ); extern void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k ); extern Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext ); extern Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray ); extern void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); extern void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues ); extern int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); extern int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit, int fTryConf ); /*=== pdrTsim.c ==========================================================*/ extern Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); /*=== pdrUtil.c ==========================================================*/ extern Pdr_Set_t * Pdr_SetAlloc( int nSize ); extern Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits ); extern Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove ); extern Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits ); extern Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet ); extern Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p ); extern void Pdr_SetDeref( Pdr_Set_t * p ); extern int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew ); extern int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew ); extern int Pdr_SetIsInit( Pdr_Set_t * p, int iRemove ); extern void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts ); extern void Pdr_SetPrintStr( Vec_Str_t * vStr, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts ); extern int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 ); extern Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext ); extern Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p ); extern void Pdr_OblDeref( Pdr_Obl_t * p ); extern int Pdr_QueueIsEmpty( Pdr_Man_t * p ); extern Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p ); extern Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p ); extern void Pdr_QueueClean( Pdr_Man_t * p ); extern void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl ); extern void Pdr_QueuePrint( Pdr_Man_t * p ); extern void Pdr_QueueStop( Pdr_Man_t * p ); extern int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrInv.c000066400000000000000000000453751300674244400233720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrInv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [Invariant computation, printing, verification.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrInv.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" #include "base/abc/abc.h" // for Abc_NtkCollectCioNames() #include "base/main/main.h" // for Abc_FrameReadGlobalFrame() #include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, abctime Time ) { Vec_Ptr_t * vVec; int i, ThisSize, Length, LengthStart; if ( Vec_PtrSize(p->vSolvers) < 2 ) return; if ( Abc_FrameIsBatchMode() && !fClose ) return; // count the total length of the printout Length = 0; Vec_VecForEachLevel( p->vClauses, vVec, i ) Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1); // determine the starting point LengthStart = Abc_MaxInt( 0, Length - 60 ); Abc_Print( 1, "%3d :", Vec_PtrSize(p->vSolvers)-1 ); ThisSize = 5; if ( LengthStart > 0 ) { Abc_Print( 1, " ..." ); ThisSize += 4; } Length = 0; Vec_VecForEachLevel( p->vClauses, vVec, i ) { if ( Length < LengthStart ) { Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1); continue; } Abc_Print( 1, " %d", Vec_PtrSize(vVec) ); Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1); ThisSize += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1); } for ( i = ThisSize; i < 70; i++ ) Abc_Print( 1, " " ); Abc_Print( 1, "%6d", p->nQueMax ); Abc_Print( 1, "%10.2f sec", 1.0*Time/CLOCKS_PER_SEC ); if ( p->pPars->fSolveAll ) Abc_Print( 1, " CEX =%4d", p->pPars->nFailOuts ); if ( p->pPars->nTimeOutOne ) Abc_Print( 1, " T/O =%3d", p->pPars->nDropOuts ); Abc_Print( 1, "%s", fClose ? "\n":"\r" ); if ( fClose ) p->nQueMax = 0; fflush( stdout ); } /**Function************************************************************* Synopsis [Counts how many times each flop appears in the set of cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Pdr_ManCountFlops( Pdr_Man_t * p, Vec_Ptr_t * vCubes ) { Vec_Int_t * vFlopCount; Pdr_Set_t * pCube; int i, n; vFlopCount = Vec_IntStart( Aig_ManRegNum(p->pAig) ); Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { if ( pCube->nRefs == -1 ) continue; for ( n = 0; n < pCube->nLits; n++ ) { assert( pCube->Lits[n] >= 0 && pCube->Lits[n] < 2*Aig_ManRegNum(p->pAig) ); Vec_IntAddToEntry( vFlopCount, pCube->Lits[n] >> 1, 1 ); } } return vFlopCount; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManFindInvariantStart( Pdr_Man_t * p ) { Vec_Ptr_t * vArrayK; int k, kMax = Vec_PtrSize(p->vSolvers)-1; Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax+1 ) if ( Vec_PtrSize(vArrayK) == 0 ) return k; // return -1; // if there is no starting point (as in case of SAT or undecided), return the last frame // Abc_Print( 1, "The last timeframe contains %d clauses.\n", Vec_PtrSize(Vec_VecEntry(p->vClauses, kMax)) ); return kMax; } /**Function************************************************************* Synopsis [Counts the number of variables used in the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Pdr_ManCollectCubes( Pdr_Man_t * p, int kStart ) { Vec_Ptr_t * vResult; Vec_Ptr_t * vArrayK; Pdr_Set_t * pSet; int i, j; vResult = Vec_PtrAlloc( 100 ); Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, kStart ) Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pSet, j ) Vec_PtrPush( vResult, pSet ); return vResult; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Pdr_ManCountFlopsInv( Pdr_Man_t * p ) { int kStart = Pdr_ManFindInvariantStart(p); Vec_Ptr_t *vCubes = Pdr_ManCollectCubes(p, kStart); Vec_Int_t * vInv = Pdr_ManCountFlops( p, vCubes ); Vec_PtrFree(vCubes); return vInv; } /**Function************************************************************* Synopsis [Counts the number of variables used in the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManCountVariables( Pdr_Man_t * p, int kStart ) { Vec_Int_t * vFlopCounts; Vec_Ptr_t * vCubes; int i, Entry, Counter = 0; if ( p->vInfCubes == NULL ) vCubes = Pdr_ManCollectCubes( p, kStart ); else vCubes = Vec_PtrDup( p->vInfCubes ); vFlopCounts = Pdr_ManCountFlops( p, vCubes ); Vec_IntForEachEntry( vFlopCounts, Entry, i ) Counter += (Entry > 0); Vec_IntFreeP( &vFlopCounts ); Vec_PtrFree( vCubes ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart ) { Vec_Ptr_t * vArrayK; Pdr_Set_t * pCube; int i, k, Counter = 0; Vec_VecForEachLevelStart( p->vClauses, vArrayK, k, kStart ) { Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare ); Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, i ) { Abc_Print( 1, "C=%4d. F=%4d ", Counter++, k ); Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL ); Abc_Print( 1, "\n" ); } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_SetPrintOne( Pdr_Set_t * p ) { int i; printf( "Clause: {" ); for ( i = 0; i < p->nLits; i++ ) printf( " %s%d", Abc_LitIsCompl(p->Lits[i])? "!":"", Abc_Lit2Var(p->Lits[i]) ); printf( " }\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Pdr_ManDupAigWithClauses( Aig_Man_t * p, Vec_Ptr_t * vCubes ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew, * pLit; Pdr_Set_t * pCube; int i, n; // 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 outputs for each cube Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { // Pdr_SetPrintOne( pCube ); pObjNew = Aig_ManConst1(pNew); for ( n = 0; n < pCube->nLits; n++ ) { assert( Abc_Lit2Var(pCube->Lits[n]) < Saig_ManRegNum(p) ); pLit = Aig_NotCond( Aig_ManCi(pNew, Saig_ManPiNum(p) + Abc_Lit2Var(pCube->Lits[n])), Abc_LitIsCompl(pCube->Lits[n]) ); pObjNew = Aig_And( pNew, pObjNew, pLit ); } Aig_ObjCreateCo( pNew, pObjNew ); } // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add the POs Saig_ManForEachLi( p, pObj, i ) 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_ManDupSimple(): The check has failed.\n" ); return pNew; } void Pdr_ManDumpAig( Aig_Man_t * p, Vec_Ptr_t * vCubes ) { Aig_Man_t * pNew = Pdr_ManDupAigWithClauses( p, vCubes ); Ioa_WriteAiger( pNew, "aig_with_clauses.aig", 0, 0 ); Aig_ManStop( pNew ); printf( "Dumped modified AIG into file \"aig_with_clauses.aig\".\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved ) { FILE * pFile; Vec_Int_t * vFlopCounts; Vec_Ptr_t * vCubes; Pdr_Set_t * pCube; char ** pNamesCi; int i, kStart, Count = 0; // create file pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { Abc_Print( 1, "Cannot open file \"%s\" for writing invariant.\n", pFileName ); return; } // collect cubes kStart = Pdr_ManFindInvariantStart( p ); if ( fProved ) vCubes = Pdr_ManCollectCubes( p, kStart ); else vCubes = Vec_PtrDup( p->vInfCubes ); Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare ); // Pdr_ManDumpAig( p->pAig, vCubes ); // count cubes Count = 0; Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { if ( pCube->nRefs == -1 ) continue; Count++; } // collect variable appearances vFlopCounts = p->pPars->fUseSupp ? Pdr_ManCountFlops( p, vCubes ) : NULL; // output the header if ( fProved ) fprintf( pFile, "# Inductive invariant for \"%s\"\n", p->pAig->pName ); else fprintf( pFile, "# Clauses of the last timeframe for \"%s\"\n", p->pAig->pName ); fprintf( pFile, "# generated by PDR in ABC on %s\n", Aig_TimeStamp() ); fprintf( pFile, ".i %d\n", p->pPars->fUseSupp ? Pdr_ManCountVariables(p, kStart) : Aig_ManRegNum(p->pAig) ); fprintf( pFile, ".o 1\n" ); fprintf( pFile, ".p %d\n", Count ); // output flop names pNamesCi = Abc_NtkCollectCioNames( Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ), 0 ); if ( pNamesCi ) { fprintf( pFile, ".ilb" ); for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) if ( !p->pPars->fUseSupp || Vec_IntEntry( vFlopCounts, i ) ) fprintf( pFile, " %s", pNamesCi[Saig_ManPiNum(p->pAig) + i] ); fprintf( pFile, "\n" ); ABC_FREE( pNamesCi ); fprintf( pFile, ".ob inv\n" ); } // output cubes Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { if ( pCube->nRefs == -1 ) continue; Pdr_SetPrint( pFile, pCube, Aig_ManRegNum(p->pAig), vFlopCounts ); fprintf( pFile, " 1\n" ); } fprintf( pFile, ".e\n\n" ); fclose( pFile ); Vec_IntFreeP( &vFlopCounts ); Vec_PtrFree( vCubes ); if ( fProved ) Abc_Print( 1, "Inductive invariant was written into file \"%s\".\n", pFileName ); else Abc_Print( 1, "Clauses of the last timeframe were written into file \"%s\".\n", pFileName ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Pdr_ManDumpString( Pdr_Man_t * p ) { Vec_Str_t * vStr; Vec_Int_t * vFlopCounts; Vec_Ptr_t * vCubes; Pdr_Set_t * pCube; int i, kStart; vStr = Vec_StrAlloc( 1000 ); // collect cubes kStart = Pdr_ManFindInvariantStart( p ); if ( p->vInfCubes == NULL ) vCubes = Pdr_ManCollectCubes( p, kStart ); else vCubes = Vec_PtrDup( p->vInfCubes ); Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare ); // collect variable appearances vFlopCounts = p->pPars->fUseSupp ? Pdr_ManCountFlops( p, vCubes ) : NULL; // output cubes Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { if ( pCube->nRefs == -1 ) continue; Pdr_SetPrintStr( vStr, pCube, Aig_ManRegNum(p->pAig), vFlopCounts ); } Vec_IntFreeP( &vFlopCounts ); Vec_PtrFree( vCubes ); Vec_StrPush( vStr, '\0' ); return vStr; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManReportInvariant( Pdr_Man_t * p ) { Vec_Ptr_t * vCubes; int kStart = Pdr_ManFindInvariantStart( p ); vCubes = Pdr_ManCollectCubes( p, kStart ); Abc_Print( 1, "Invariant F[%d] : %d clauses with %d flops (out of %d)\n", kStart, Vec_PtrSize(vCubes), Pdr_ManCountVariables(p, kStart), Aig_ManRegNum(p->pAig) ); Vec_PtrFree( vCubes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManVerifyInvariant( Pdr_Man_t * p ) { sat_solver * pSat; Vec_Int_t * vLits; Vec_Ptr_t * vCubes; Pdr_Set_t * pCube; int i, kStart, kThis, RetValue, Counter = 0; abctime clk = Abc_Clock(); // collect cubes used in the inductive invariant kStart = Pdr_ManFindInvariantStart( p ); vCubes = Pdr_ManCollectCubes( p, kStart ); // create solver with the cubes kThis = Vec_PtrSize(p->vSolvers); pSat = Pdr_ManCreateSolver( p, kThis ); // add the property output // Pdr_ManSetPropertyOutput( p, kThis ); // add the clauses Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { vLits = Pdr_ManCubeToLits( p, kThis, pCube, 1, 0 ); RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); assert( RetValue ); sat_solver_compress( pSat ); } // check each clause Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { vLits = Pdr_ManCubeToLits( p, kThis, pCube, 0, 1 ); RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); if ( RetValue != l_False ) { Abc_Print( 1, "Verification of clause %d failed.\n", i ); Counter++; } } if ( Counter ) Abc_Print( 1, "Verification of %d clauses has failed.\n", Counter ); else { Abc_Print( 1, "Verification of invariant with %d clauses was successful. ", Vec_PtrSize(vCubes) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } // sat_solver_delete( pSat ); Vec_PtrFree( vCubes ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManDeriveMarkNonInductive( Pdr_Man_t * p, Vec_Ptr_t * vCubes ) { sat_solver * pSat; Vec_Int_t * vLits; Pdr_Set_t * pCube; int i, kThis, RetValue, fChanges = 0, Counter = 0; // create solver with the cubes kThis = Vec_PtrSize(p->vSolvers); pSat = Pdr_ManCreateSolver( p, kThis ); // add the clauses Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { if ( pCube->nRefs == -1 ) // skip non-inductive continue; vLits = Pdr_ManCubeToLits( p, kThis, pCube, 1, 0 ); RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); assert( RetValue ); sat_solver_compress( pSat ); } // check each clause Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { if ( pCube->nRefs == -1 ) // skip non-inductive continue; vLits = Pdr_ManCubeToLits( p, kThis, pCube, 0, 1 ); RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); if ( RetValue != l_False ) // mark as non-inductive { pCube->nRefs = -1; fChanges = 1; } else Counter++; } //printf( "Clauses = %d.\n", Counter ); //sat_solver_delete( pSat ); return fChanges; } Vec_Int_t * Pdr_ManDeriveInfinityClauses( Pdr_Man_t * p, int fReduce ) { Vec_Int_t * vResult; Vec_Ptr_t * vCubes; Pdr_Set_t * pCube; int i, v, kStart; // collect cubes used in the inductive invariant kStart = Pdr_ManFindInvariantStart( p ); vCubes = Pdr_ManCollectCubes( p, kStart ); // refine as long as there are changes if ( fReduce ) while ( Pdr_ManDeriveMarkNonInductive(p, vCubes) ); // collect remaining clauses vResult = Vec_IntAlloc( 1000 ); Vec_IntPush( vResult, 0 ); Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i ) { if ( pCube->nRefs == -1 ) // skip non-inductive continue; Vec_IntAddToEntry( vResult, 0, 1 ); Vec_IntPush( vResult, pCube->nLits ); for ( v = 0; v < pCube->nLits; v++ ) Vec_IntPush( vResult, pCube->Lits[v] ); } //Vec_PtrFree( vCubes ); Vec_PtrFreeP( &p->vInfCubes ); p->vInfCubes = vCubes; return vResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrMan.c000066400000000000000000000177001300674244400233400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [Manager procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrMan.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit ) { Pdr_Man_t * p; p = ABC_CALLOC( Pdr_Man_t, 1 ); p->pPars = pPars; p->pAig = pAig; p->vSolvers = Vec_PtrAlloc( 0 ); p->vClauses = Vec_VecAlloc( 0 ); p->pQueue = NULL; p->pOrder = ABC_ALLOC( int, Aig_ManRegNum(pAig) ); p->vActVars = Vec_IntAlloc( 256 ); if ( !p->pPars->fMonoCnf ) p->vVLits = Vec_WecStart( 1+Abc_MaxInt(1, Aig_ManLevels(pAig)) ); // internal use p->vPrio = vPrioInit ? vPrioInit : Vec_IntStart( Aig_ManRegNum(pAig) ); // priority flops p->vLits = Vec_IntAlloc( 100 ); // array of literals p->vCiObjs = Vec_IntAlloc( 100 ); // cone leaves p->vCoObjs = Vec_IntAlloc( 100 ); // cone roots p->vCiVals = Vec_IntAlloc( 100 ); // cone leaf values p->vCoVals = Vec_IntAlloc( 100 ); // cone root values p->vNodes = Vec_IntAlloc( 100 ); // cone nodes p->vUndo = Vec_IntAlloc( 100 ); // cone undos p->vVisits = Vec_IntAlloc( 100 ); // intermediate p->vCi2Rem = Vec_IntAlloc( 100 ); // CIs to be removed p->vRes = Vec_IntAlloc( 100 ); // final result p->vSuppLits= Vec_IntAlloc( 100 ); // support literals p->pCubeJust= Pdr_SetAlloc( Saig_ManRegNum(pAig) ); p->pCnfMan = Cnf_ManStart(); // additional AIG data-members if ( pAig->pFanData == NULL ) Aig_ManFanoutStart( pAig ); if ( pAig->pTerSimData == NULL ) pAig->pTerSimData = ABC_CALLOC( unsigned, 1 + (Aig_ManObjNumMax(pAig) / 16) ); // time spent on each outputs if ( pPars->nTimeOutOne ) { int i; p->pTime4Outs = ABC_ALLOC( abctime, Saig_ManPoNum(pAig) ); for ( i = 0; i < Saig_ManPoNum(pAig); i++ ) p->pTime4Outs[i] = pPars->nTimeOutOne * CLOCKS_PER_SEC / 1000 + 1; } if ( pPars->fSolveAll ) { p->vCexes = Vec_PtrStart( Saig_ManPoNum(p->pAig) ); p->pPars->vOutMap = Vec_IntAlloc( Saig_ManPoNum(pAig) ); Vec_IntFill( p->pPars->vOutMap, Saig_ManPoNum(pAig), -2 ); } return p; } /**Function************************************************************* Synopsis [Frees manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManStop( Pdr_Man_t * p ) { Pdr_Set_t * pCla; sat_solver * pSat; int i, k; Aig_ManCleanMarkAB( p->pAig ); if ( p->pPars->fVerbose ) { Abc_Print( 1, "Block =%5d Oblig =%6d Clause =%6d Call =%6d (sat=%.1f%%) Start =%4d\n", p->nBlocks, p->nObligs, p->nCubes, p->nCalls, 100.0 * p->nCallsS / p->nCalls, p->nStarts ); ABC_PRTP( "SAT solving", p->tSat, p->tTotal ); ABC_PRTP( " unsat ", p->tSatUnsat, p->tTotal ); ABC_PRTP( " sat ", p->tSatSat, p->tTotal ); ABC_PRTP( "Generalize ", p->tGeneral, p->tTotal ); ABC_PRTP( "Push clause", p->tPush, p->tTotal ); ABC_PRTP( "Ternary sim", p->tTsim, p->tTotal ); ABC_PRTP( "Containment", p->tContain, p->tTotal ); ABC_PRTP( "CNF compute", p->tCnf, p->tTotal ); ABC_PRTP( "TOTAL ", p->tTotal, p->tTotal ); fflush( stdout ); } // Abc_Print( 1, "SS =%6d. SU =%6d. US =%6d. UU =%6d.\n", p->nCasesSS, p->nCasesSU, p->nCasesUS, p->nCasesUU ); Vec_PtrForEachEntry( sat_solver *, p->vSolvers, pSat, i ) sat_solver_delete( pSat ); Vec_PtrFree( p->vSolvers ); Vec_VecForEachEntry( Pdr_Set_t *, p->vClauses, pCla, i, k ) Pdr_SetDeref( pCla ); Vec_VecFree( p->vClauses ); Pdr_QueueStop( p ); ABC_FREE( p->pOrder ); Vec_IntFree( p->vActVars ); // static CNF Cnf_DataFree( p->pCnf1 ); Vec_IntFreeP( &p->vVar2Reg ); // dynamic CNF Cnf_DataFree( p->pCnf2 ); if ( p->pvId2Vars ) for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) ABC_FREE( p->pvId2Vars[i].pArray ); ABC_FREE( p->pvId2Vars ); // Vec_VecFreeP( (Vec_Vec_t **)&p->vVar2Ids ); for ( i = 0; i < Vec_PtrSize(&p->vVar2Ids); i++ ) Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, i) ); ABC_FREE( p->vVar2Ids.pArray ); Vec_WecFreeP( &p->vVLits ); // CNF manager Cnf_ManStop( p->pCnfMan ); // internal use Vec_IntFreeP( &p->vPrio ); // priority flops Vec_IntFree( p->vLits ); // array of literals Vec_IntFree( p->vCiObjs ); // cone leaves Vec_IntFree( p->vCoObjs ); // cone roots Vec_IntFree( p->vCiVals ); // cone leaf values Vec_IntFree( p->vCoVals ); // cone root values Vec_IntFree( p->vNodes ); // cone nodes Vec_IntFree( p->vUndo ); // cone undos Vec_IntFree( p->vVisits ); // intermediate Vec_IntFree( p->vCi2Rem ); // CIs to be removed Vec_IntFree( p->vRes ); // final result Vec_IntFree( p->vSuppLits ); // support literals Vec_PtrFreeP( &p->vInfCubes ); ABC_FREE( p->pCubeJust ); ABC_FREE( p->pTime4Outs ); if ( p->vCexes ) Vec_PtrFreeFree( p->vCexes ); // additional AIG data-members if ( p->pAig->pFanData != NULL ) Aig_ManFanoutStop( p->pAig ); if ( p->pAig->pTerSimData != NULL ) ABC_FREE( p->pAig->pTerSimData ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Derives counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p ) { Abc_Cex_t * pCex; Pdr_Obl_t * pObl; int i, f, Lit, nFrames = 0; // count the number of frames for ( pObl = p->pQueue; pObl; pObl = pObl->pNext ) nFrames++; // create the counter-example pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), nFrames ); // pCex->iPo = (p->pPars->iOutput==-1)? 0 : p->pPars->iOutput; pCex->iPo = p->iOutCur; pCex->iFrame = nFrames-1; for ( pObl = p->pQueue, f = 0; pObl; pObl = pObl->pNext, f++ ) for ( i = pObl->pState->nLits; i < pObl->pState->nTotal; i++ ) { Lit = pObl->pState->Lits[i]; if ( lit_sign(Lit) ) continue; assert( lit_var(Lit) < pCex->nPis ); Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + lit_var(Lit) ); } assert( f == nFrames ); if ( !Saig_ManVerifyCex(p->pAig, pCex) ) printf( "CEX for output %d is not valid.\n", p->iOutCur ); return pCex; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrSat.c000066400000000000000000000302471300674244400233550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [SAT solver procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrSat.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates new SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k ) { sat_solver * pSat; Aig_Obj_t * pObj; int i; assert( Vec_PtrSize(p->vSolvers) == k ); assert( Vec_VecSize(p->vClauses) == k ); assert( Vec_IntSize(p->vActVars) == k ); // create new solver pSat = sat_solver_new(); pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) ); Vec_PtrPush( p->vSolvers, pSat ); Vec_VecExpand( p->vClauses, k ); Vec_IntPush( p->vActVars, 0 ); // add property cone Saig_ManForEachPo( p->pAig, pObj, i ) Pdr_ObjSatVar( p, k, 1, pObj ); return pSat; } /**Function************************************************************* Synopsis [Returns old or restarted solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k ) { sat_solver * pSat; Vec_Ptr_t * vArrayK; Pdr_Set_t * pCube; int i, j; pSat = Pdr_ManSolver(p, k); if ( Vec_IntEntry(p->vActVars, k) < p->pPars->nRecycle ) return pSat; assert( k < Vec_PtrSize(p->vSolvers) - 1 ); p->nStarts++; // sat_solver_delete( pSat ); // pSat = sat_solver_new(); sat_solver_restart( pSat ); // create new SAT solver pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) ); // write new SAT solver Vec_PtrWriteEntry( p->vSolvers, k, pSat ); Vec_IntWriteEntry( p->vActVars, k, 0 ); // set the property output Pdr_ManSetPropertyOutput( p, k ); // add the clauses Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, k ) Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, j ) Pdr_ManSolverAddClause( p, k, pCube ); return pSat; } /**Function************************************************************* Synopsis [Converts SAT variables into register IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray ) { int i, RegId; Vec_IntClear( p->vLits ); for ( i = 0; i < nArray; i++ ) { RegId = Pdr_ObjRegNum( p, k, lit_var(pArray[i]) ); if ( RegId == -1 ) continue; assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) ); Vec_IntPush( p->vLits, toLitCond(RegId, !lit_sign(pArray[i])) ); } assert( Vec_IntSize(p->vLits) >= 0 && Vec_IntSize(p->vLits) <= nArray ); return p->vLits; } /**Function************************************************************* Synopsis [Converts the cube in terms of RO numbers into array of CNF literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext ) { Aig_Obj_t * pObj; int i, iVar, iVarMax = 0; abctime clk = Abc_Clock(); Vec_IntClear( p->vLits ); assert( !(fNext && fCompl) ); for ( i = 0; i < pCube->nLits; i++ ) { if ( pCube->Lits[i] == -1 ) continue; if ( fNext ) pObj = Saig_ManLi( p->pAig, lit_var(pCube->Lits[i]) ); else pObj = Saig_ManLo( p->pAig, lit_var(pCube->Lits[i]) ); iVar = Pdr_ObjSatVar( p, k, fNext ? 2 - lit_sign(pCube->Lits[i]) : 3, pObj ); assert( iVar >= 0 ); iVarMax = Abc_MaxInt( iVarMax, iVar ); Vec_IntPush( p->vLits, toLitCond( iVar, fCompl ^ lit_sign(pCube->Lits[i]) ) ); } // sat_solver_setnvars( Pdr_ManSolver(p, k), iVarMax + 1 ); p->tCnf += Abc_Clock() - clk; return p->vLits; } /**Function************************************************************* Synopsis [Sets the property output to 0 (sat) forever.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k ) { sat_solver * pSat; Aig_Obj_t * pObj; int Lit, RetValue, i; if ( !p->pPars->fUsePropOut ) return; pSat = Pdr_ManSolver(p, k); Saig_ManForEachPo( p->pAig, pObj, i ) { // skip solved outputs if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) ) continue; // skip timedout outputs if ( p->pPars->vOutMap && Vec_IntEntry(p->pPars->vOutMap, i) == -1 ) continue; Lit = toLitCond( Pdr_ObjSatVar(p, k, 1, pObj), 1 ); // neg literal RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( RetValue == 1 ); } sat_solver_compress( pSat ); } /**Function************************************************************* Synopsis [Adds one clause in terms of ROs to the k-th SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) { sat_solver * pSat; Vec_Int_t * vLits; int RetValue; pSat = Pdr_ManSolver(p, k); vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 ); RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); assert( RetValue == 1 ); sat_solver_compress( pSat ); } /**Function************************************************************* Synopsis [Collects values of the RO/RI variables in k-th SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues ) { sat_solver * pSat; Aig_Obj_t * pObj; int iVar, i; Vec_IntClear( vValues ); pSat = Pdr_ManSolver(p, k); Aig_ManForEachObjVec( vObjIds, p->pAig, pObj, i ) { iVar = Pdr_ObjSatVar( p, k, 3, pObj ); assert( iVar >= 0 ); Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) ); } } /**Function************************************************************* Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.] Description [Return 1/0 if cube or property are proved to hold/fail in k-th timeframe. Returns the predecessor bad state in ppPred.] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) { sat_solver * pSat; Vec_Int_t * vLits; abctime Limit; int RetValue; pSat = Pdr_ManFetchSolver( p, k ); vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 0 ); Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) ); RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); sat_solver_set_runtime_limit( pSat, Limit ); if ( RetValue == l_Undef ) return -1; return (RetValue == l_False); } /**Function************************************************************* Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.] Description [Return 1/0 if cube or property are proved to hold/fail in k-th timeframe. Returns the predecessor bad state in ppPred.] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit, int fTryConf ) { int fUseLit = 1; int fLitUsed = 0; sat_solver * pSat; Vec_Int_t * vLits; int Lit, RetValue; abctime clk, Limit; p->nCalls++; pSat = Pdr_ManFetchSolver( p, k ); if ( pCube == NULL ) // solve the property { clk = Abc_Clock(); Lit = toLit( Pdr_ObjSatVar(p, k, 2, Aig_ManCo(p->pAig, p->iOutCur)) ); // pos literal (property fails) Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) ); RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, nConfLimit, 0, 0, 0 ); sat_solver_set_runtime_limit( pSat, Limit ); if ( RetValue == l_Undef ) return -1; } else // check relative containment in terms of next states { if ( fUseLit ) { fLitUsed = 1; Vec_IntAddToEntry( p->vActVars, k, 1 ); // add the cube in terms of current state variables vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 ); // add activation literal Lit = toLit( Pdr_ManFreeVar(p, k) ); // add activation literal Vec_IntPush( vLits, Lit ); RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); assert( RetValue == 1 ); sat_solver_compress( pSat ); // create assumptions vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 ); // add activation literal Vec_IntPush( vLits, lit_neg(Lit) ); } else vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 ); // solve clk = Abc_Clock(); Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) ); RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), fTryConf ? p->pPars->nConfGenLimit : nConfLimit, 0, 0, 0 ); sat_solver_set_runtime_limit( pSat, Limit ); if ( RetValue == l_Undef ) { if ( fTryConf && p->pPars->nConfGenLimit ) RetValue = l_True; else return -1; } /* if ( RetValue == l_True ) { int RetValue2 = Pdr_ManCubeJust( p, k, pCube ); if ( RetValue2 ) p->nCasesSS++; else p->nCasesSU++; } else { int RetValue2 = Pdr_ManCubeJust( p, k, pCube ); if ( RetValue2 ) p->nCasesUS++; else p->nCasesUU++; } */ } clk = Abc_Clock() - clk; p->tSat += clk; assert( RetValue != l_Undef ); if ( RetValue == l_False ) { p->tSatUnsat += clk; p->nCallsU++; if ( ppPred ) *ppPred = NULL; RetValue = 1; } else // if ( RetValue == l_True ) { p->tSatSat += clk; p->nCallsS++; if ( ppPred ) *ppPred = Pdr_ManTernarySim( p, k, pCube ); RetValue = 0; } /* // for some reason, it does not work... if ( fLitUsed ) { int RetValue; Lit = lit_neg(Lit); RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( RetValue == 1 ); sat_solver_compress( pSat ); } */ return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrTsim.c000066400000000000000000000374761300674244400235550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrTsim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [Ternary simulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrTsim.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define PDR_ZER 1 #define PDR_ONE 2 #define PDR_UND 3 static inline int Pdr_ManSimInfoNot( int Value ) { if ( Value == PDR_ZER ) return PDR_ONE; if ( Value == PDR_ONE ) return PDR_ZER; return PDR_UND; } static inline int Pdr_ManSimInfoAnd( int Value0, int Value1 ) { if ( Value0 == PDR_ZER || Value1 == PDR_ZER ) return PDR_ZER; if ( Value0 == PDR_ONE && Value1 == PDR_ONE ) return PDR_ONE; return PDR_UND; } static inline int Pdr_ManSimInfoGet( Aig_Man_t * p, Aig_Obj_t * pObj ) { return 3 & (p->pTerSimData[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1)); } static inline void Pdr_ManSimInfoSet( Aig_Man_t * p, Aig_Obj_t * pObj, int Value ) { assert( Value >= PDR_ZER && Value <= PDR_UND ); Value ^= Pdr_ManSimInfoGet( p, pObj ); p->pTerSimData[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Marks the TFI cone and collects CIs and nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManCollectCone_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes ) { assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsCi(pObj) ) { Vec_IntPush( vCiObjs, Aig_ObjId(pObj) ); return; } Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin0(pObj), vCiObjs, vNodes ); if ( Aig_ObjIsCo(pObj) ) return; Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin1(pObj), vCiObjs, vNodes ); Vec_IntPush( vNodes, Aig_ObjId(pObj) ); } /**Function************************************************************* Synopsis [Marks the TFI cone and collects CIs and nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManCollectCone( Aig_Man_t * pAig, Vec_Int_t * vCoObjs, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes ) { Aig_Obj_t * pObj; int i; Vec_IntClear( vCiObjs ); Vec_IntClear( vNodes ); Aig_ManIncrementTravId( pAig ); Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) Pdr_ManCollectCone_rec( pAig, pObj, vCiObjs, vNodes ); } /**Function************************************************************* Synopsis [Performs ternary simulation for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManExtendOneEval( Aig_Man_t * pAig, Aig_Obj_t * pObj ) { int Value0, Value1, Value; Value0 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin0(pObj) ); if ( Aig_ObjFaninC0(pObj) ) Value0 = Pdr_ManSimInfoNot( Value0 ); if ( Aig_ObjIsCo(pObj) ) { Pdr_ManSimInfoSet( pAig, pObj, Value0 ); return Value0; } assert( Aig_ObjIsNode(pObj) ); Value1 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin1(pObj) ); if ( Aig_ObjFaninC1(pObj) ) Value1 = Pdr_ManSimInfoNot( Value1 ); Value = Pdr_ManSimInfoAnd( Value0, Value1 ); Pdr_ManSimInfoSet( pAig, pObj, Value ); return Value; } /**Function************************************************************* Synopsis [Performs ternary simulation for one design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManSimDataInit( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vNodes, Vec_Int_t * vCoObjs, Vec_Int_t * vCoVals, Vec_Int_t * vCi2Rem ) { Aig_Obj_t * pObj; int i; // set the CI values Pdr_ManSimInfoSet( pAig, Aig_ManConst1(pAig), PDR_ONE ); Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) Pdr_ManSimInfoSet( pAig, pObj, (Vec_IntEntry(vCiVals, i)?PDR_ONE:PDR_ZER) ); // set the FOs to remove if ( vCi2Rem != NULL ) Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) Pdr_ManSimInfoSet( pAig, pObj, PDR_UND ); // perform ternary simulation Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) Pdr_ManExtendOneEval( pAig, pObj ); // transfer results to the output Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) Pdr_ManExtendOneEval( pAig, pObj ); // check the results Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i ) if ( Pdr_ManSimInfoGet( pAig, pObj ) != (Vec_IntEntry(vCoVals, i)?PDR_ONE:PDR_ZER) ) return 0; return 1; } /**Function************************************************************* Synopsis [Tries to assign ternary value to one of the CIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManExtendOne( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vUndo, Vec_Int_t * vVis ) { Aig_Obj_t * pFanout; int i, k, iFanout = -1, Value, Value2; assert( Saig_ObjIsLo(pAig, pObj) ); assert( Aig_ObjIsTravIdCurrent(pAig, pObj) ); // save original value Value = Pdr_ManSimInfoGet( pAig, pObj ); assert( Value == PDR_ZER || Value == PDR_ONE ); Vec_IntPush( vUndo, Aig_ObjId(pObj) ); Vec_IntPush( vUndo, Value ); // update original value Pdr_ManSimInfoSet( pAig, pObj, PDR_UND ); // traverse Vec_IntClear( vVis ); Vec_IntPush( vVis, Aig_ObjId(pObj) ); Aig_ManForEachObjVec( vVis, pAig, pObj, i ) { Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, k ) { if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) ) continue; assert( Aig_ObjId(pObj) < Aig_ObjId(pFanout) ); Value = Pdr_ManSimInfoGet( pAig, pFanout ); if ( Value == PDR_UND ) continue; Value2 = Pdr_ManExtendOneEval( pAig, pFanout ); if ( Value2 == Value ) continue; assert( Value2 == PDR_UND ); Vec_IntPush( vUndo, Aig_ObjId(pFanout) ); Vec_IntPush( vUndo, Value ); if ( Aig_ObjIsCo(pFanout) ) return 0; assert( Aig_ObjIsNode(pFanout) ); Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) ); } } return 1; } /**Function************************************************************* Synopsis [Undoes the partial results of ternary simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManExtendUndo( Aig_Man_t * pAig, Vec_Int_t * vUndo ) { Aig_Obj_t * pObj; int i, Value; Aig_ManForEachObjVec( vUndo, pAig, pObj, i ) { Value = Vec_IntEntry(vUndo, ++i); assert( Pdr_ManSimInfoGet(pAig, pObj) == PDR_UND ); Pdr_ManSimInfoSet( pAig, pObj, Value ); } } /**Function************************************************************* Synopsis [Derives the resulting cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManDeriveResult( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem, Vec_Int_t * vRes, Vec_Int_t * vPiLits ) { Aig_Obj_t * pObj; int i, Lit; // mark removed flop outputs Aig_ManIncrementTravId( pAig ); Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) { assert( Saig_ObjIsLo( pAig, pObj ) ); Aig_ObjSetTravIdCurrent(pAig, pObj); } // collect flop outputs that are not marked Vec_IntClear( vRes ); Vec_IntClear( vPiLits ); Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) { if ( Saig_ObjIsPi(pAig, pObj) ) { Lit = toLitCond( Aig_ObjCioId(pObj), (Vec_IntEntry(vCiVals, i) == 0) ); Vec_IntPush( vPiLits, Lit ); continue; } assert( Saig_ObjIsLo(pAig, pObj) ); if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) continue; Lit = toLitCond( Aig_ObjCioId(pObj) - Saig_ManPiNum(pAig), (Vec_IntEntry(vCiVals, i) == 0) ); Vec_IntPush( vRes, Lit ); } if ( Vec_IntSize(vRes) == 0 ) Vec_IntPush(vRes, 0); } /**Function************************************************************* Synopsis [Derives the resulting cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_ManPrintCex( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem ) { Aig_Obj_t * pObj; int i; char * pBuff = ABC_ALLOC( char, Aig_ManCiNum(pAig)+1 ); for ( i = 0; i < Aig_ManCiNum(pAig); i++ ) pBuff[i] = '-'; pBuff[i] = 0; Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i ) pBuff[Aig_ObjCioId(pObj)] = (Vec_IntEntry(vCiVals, i)? '1':'0'); if ( vCi2Rem ) Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i ) pBuff[Aig_ObjCioId(pObj)] = 'x'; Abc_Print( 1, "%s\n", pBuff ); ABC_FREE( pBuff ); } /**Function************************************************************* Synopsis [Shrinks values using ternary simulation.] Description [The cube contains the set of flop index literals which, when converted into a clause and applied to the combinational outputs, led to a satisfiable SAT run in frame k (values stored in the SAT solver). If the cube is NULL, it is assumed that the first property output was asserted and failed. The resulting array is a set of flop index literals that asserts the COs. Priority contains 0 for i-th entry if the i-th FF is desirable to remove.] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) { Pdr_Set_t * pRes; Vec_Int_t * vPrio = p->vPrio; // priority flops (flop indices) Vec_Int_t * vPiLits = p->vLits; // array of literals (0/1 PI values) Vec_Int_t * vCiObjs = p->vCiObjs; // cone leaves (CI obj IDs) Vec_Int_t * vCoObjs = p->vCoObjs; // cone roots (CO obj IDs) Vec_Int_t * vCiVals = p->vCiVals; // cone leaf values (0/1 CI values) Vec_Int_t * vCoVals = p->vCoVals; // cone root values (0/1 CO values) Vec_Int_t * vNodes = p->vNodes; // cone nodes (node obj IDs) Vec_Int_t * vUndo = p->vUndo; // cone undos (node obj IDs) Vec_Int_t * vVisits = p->vVisits; // intermediate (obj IDs) Vec_Int_t * vCi2Rem = p->vCi2Rem; // CIs to be removed (CI obj IDs) Vec_Int_t * vRes = p->vRes; // final result (flop literals) Aig_Obj_t * pObj; int i, Entry, RetValue; abctime clk = Abc_Clock(); // collect CO objects Vec_IntClear( vCoObjs ); if ( pCube == NULL ) // the target is the property output { // Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManCo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) ); Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManCo(p->pAig, p->iOutCur)) ); } else // the target is the cube { for ( i = 0; i < pCube->nLits; i++ ) { if ( pCube->Lits[i] == -1 ) continue; pObj = Saig_ManLi(p->pAig, (pCube->Lits[i] >> 1)); Vec_IntPush( vCoObjs, Aig_ObjId(pObj) ); } } if ( p->pPars->fVeryVerbose ) { Abc_Print( 1, "Trying to justify cube " ); if ( pCube ) Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL ); else Abc_Print( 1, "" ); Abc_Print( 1, " in frame %d.\n", k ); } // collect CI objects Pdr_ManCollectCone( p->pAig, vCoObjs, vCiObjs, vNodes ); // collect values Pdr_ManCollectValues( p, k, vCiObjs, vCiVals ); Pdr_ManCollectValues( p, k, vCoObjs, vCoVals ); // simulate for the first time if ( p->pPars->fVeryVerbose ) Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, NULL ); RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, NULL ); assert( RetValue ); #if 1 // try removing high-priority flops Vec_IntClear( vCi2Rem ); Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i ) { if ( !Saig_ObjIsLo( p->pAig, pObj ) ) continue; Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig); if ( vPrio != NULL && Vec_IntEntry( vPrio, Entry ) != 0 ) continue; Vec_IntClear( vUndo ); if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) ) Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) ); else Pdr_ManExtendUndo( p->pAig, vUndo ); } // try removing low-priority flops Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i ) { if ( !Saig_ObjIsLo( p->pAig, pObj ) ) continue; Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig); if ( vPrio == NULL || Vec_IntEntry( vPrio, Entry ) == 0 ) continue; Vec_IntClear( vUndo ); if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) ) Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) ); else Pdr_ManExtendUndo( p->pAig, vUndo ); } #else // try removing low-priority flops Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i ) { if ( !Saig_ObjIsLo( p->pAig, pObj ) ) continue; Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig); if ( vPrio == NULL || Vec_IntEntry( vPrio, Entry ) == 0 ) continue; Vec_IntClear( vUndo ); if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) ) Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) ); else Pdr_ManExtendUndo( p->pAig, vUndo ); } // try removing high-priority flops Vec_IntClear( vCi2Rem ); Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i ) { if ( !Saig_ObjIsLo( p->pAig, pObj ) ) continue; Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig); if ( vPrio != NULL && Vec_IntEntry( vPrio, Entry ) != 0 ) continue; Vec_IntClear( vUndo ); if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) ) Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) ); else Pdr_ManExtendUndo( p->pAig, vUndo ); } #endif if ( p->pPars->fVeryVerbose ) Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, vCi2Rem ); RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, vCi2Rem ); assert( RetValue ); // derive the set of resulting registers Pdr_ManDeriveResult( p->pAig, vCiObjs, vCiVals, vCi2Rem, vRes, vPiLits ); assert( Vec_IntSize(vRes) > 0 ); p->tTsim += Abc_Clock() - clk; pRes = Pdr_SetCreate( vRes, vPiLits ); assert( k == 0 || !Pdr_SetIsInit(pRes, -1) ); return pRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/pdr/pdrUtil.c000066400000000000000000000474751300674244400235560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [pdrUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Property driven reachability.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 20, 2010.] Revision [$Id: pdrUtil.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "pdrInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Set_t * Pdr_SetAlloc( int nSize ) { Pdr_Set_t * p; assert( nSize >= 0 && nSize < (1<<30) ); p = (Pdr_Set_t *)ABC_CALLOC( char, sizeof(Pdr_Set_t) + nSize * sizeof(int) ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits ) { Pdr_Set_t * p; int i; assert( Vec_IntSize(vLits) + Vec_IntSize(vPiLits) < (1<<30) ); p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (Vec_IntSize(vLits) + Vec_IntSize(vPiLits)) * sizeof(int) ); p->nLits = Vec_IntSize(vLits); p->nTotal = Vec_IntSize(vLits) + Vec_IntSize(vPiLits); p->nRefs = 1; p->Sign = 0; for ( i = 0; i < p->nLits; i++ ) { p->Lits[i] = Vec_IntEntry(vLits, i); p->Sign |= ((word)1 << (p->Lits[i] % 63)); } Vec_IntSelectSort( p->Lits, p->nLits ); // remember PI literals for ( i = p->nLits; i < p->nTotal; i++ ) p->Lits[i] = Vec_IntEntry(vPiLits, i-p->nLits); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove ) { Pdr_Set_t * p; int i, k = 0; assert( iRemove >= 0 && iRemove < pSet->nLits ); p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (pSet->nTotal - 1) * sizeof(int) ); p->nLits = pSet->nLits - 1; p->nTotal = pSet->nTotal - 1; p->nRefs = 1; p->Sign = 0; for ( i = 0; i < pSet->nTotal; i++ ) { if ( i == iRemove ) continue; p->Lits[k++] = pSet->Lits[i]; if ( i >= pSet->nLits ) continue; p->Sign |= ((word)1 << (pSet->Lits[i] % 63)); } assert( k == p->nTotal ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits ) { Pdr_Set_t * p; int i, k = 0; assert( nLits >= 0 && nLits <= pSet->nLits ); p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (nLits + pSet->nTotal - pSet->nLits) * sizeof(int) ); p->nLits = nLits; p->nTotal = nLits + pSet->nTotal - pSet->nLits; p->nRefs = 1; p->Sign = 0; for ( i = 0; i < nLits; i++ ) { assert( pLits[i] >= 0 ); p->Lits[k++] = pLits[i]; p->Sign |= ((word)1 << (pLits[i] % 63)); } Vec_IntSelectSort( p->Lits, p->nLits ); for ( i = pSet->nLits; i < pSet->nTotal; i++ ) p->Lits[k++] = pSet->Lits[i]; assert( k == p->nTotal ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet ) { Pdr_Set_t * p; int i; p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + pSet->nTotal * sizeof(int) ); p->nLits = pSet->nLits; p->nTotal = pSet->nTotal; p->nRefs = 1; p->Sign = pSet->Sign; for ( i = 0; i < pSet->nTotal; i++ ) p->Lits[i] = pSet->Lits[i]; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p ) { p->nRefs++; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_SetDeref( Pdr_Set_t * p ) { if ( --p->nRefs == 0 ) ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts ) { char * pBuff; int i, k, Entry; pBuff = ABC_ALLOC( char, nRegs + 1 ); for ( i = 0; i < nRegs; i++ ) pBuff[i] = '-'; pBuff[i] = 0; for ( i = 0; i < p->nLits; i++ ) { if ( p->Lits[i] == -1 ) continue; pBuff[lit_var(p->Lits[i])] = (lit_sign(p->Lits[i])? '0':'1'); } if ( vFlopCounts ) { // skip some literals k = 0; Vec_IntForEachEntry( vFlopCounts, Entry, i ) if ( Entry ) pBuff[k++] = pBuff[i]; pBuff[k] = 0; } fprintf( pFile, "%s", pBuff ); ABC_FREE( pBuff ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_SetPrintStr( Vec_Str_t * vStr, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts ) { char * pBuff; int i, k = 0, Entry; pBuff = ABC_ALLOC( char, nRegs + 1 ); for ( i = 0; i < nRegs; i++ ) pBuff[i] = '-'; pBuff[i] = 0; for ( i = 0; i < p->nLits; i++ ) { if ( p->Lits[i] == -1 ) continue; pBuff[lit_var(p->Lits[i])] = (lit_sign(p->Lits[i])? '0':'1'); } if ( vFlopCounts ) { // skip some literals Vec_IntForEachEntry( vFlopCounts, Entry, i ) if ( Entry ) pBuff[k++] = pBuff[i]; pBuff[k] = 0; } Vec_StrPushBuffer( vStr, pBuff, k ); Vec_StrPush( vStr, ' ' ); Vec_StrPush( vStr, '0' ); Vec_StrPush( vStr, '\n' ); ABC_FREE( pBuff ); } /**Function************************************************************* Synopsis [Return 1 if pOld set-theoretically contains pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew ) { int * pOldInt, * pNewInt; assert( pOld->nLits > 0 ); assert( pNew->nLits > 0 ); if ( pOld->nLits < pNew->nLits ) return 0; if ( (pOld->Sign & pNew->Sign) != pNew->Sign ) return 0; pOldInt = pOld->Lits + pOld->nLits - 1; pNewInt = pNew->Lits + pNew->nLits - 1; while ( pNew->Lits <= pNewInt ) { if ( pOld->Lits > pOldInt ) return 0; assert( *pNewInt != -1 ); assert( *pOldInt != -1 ); if ( *pNewInt == *pOldInt ) pNewInt--, pOldInt--; else if ( *pNewInt < *pOldInt ) pOldInt--; else return 0; } return 1; } /**Function************************************************************* Synopsis [Return 1 if pOld set-theoretically contains pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew ) { int * pOldInt, * pNewInt; assert( pOld->nLits > 0 ); assert( pNew->nLits > 0 ); pOldInt = pOld->Lits + pOld->nLits - 1; pNewInt = pNew->Lits + pNew->nLits - 1; while ( pNew->Lits <= pNewInt ) { assert( *pOldInt != -1 ); if ( *pNewInt == -1 ) { pNewInt--; continue; } if ( pOld->Lits > pOldInt ) return 0; assert( *pNewInt != -1 ); assert( *pOldInt != -1 ); if ( *pNewInt == *pOldInt ) pNewInt--, pOldInt--; else if ( *pNewInt < *pOldInt ) pOldInt--; else return 0; } return 1; } /**Function************************************************************* Synopsis [Return 1 if the state cube contains init state (000...0).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_SetIsInit( Pdr_Set_t * pCube, int iRemove ) { int i; for ( i = 0; i < pCube->nLits; i++ ) { assert( pCube->Lits[i] != -1 ); if ( i == iRemove ) continue; if ( lit_sign( pCube->Lits[i] ) == 0 ) return 0; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 ) { Pdr_Set_t * p1 = *pp1; Pdr_Set_t * p2 = *pp2; int i; for ( i = 0; i < p1->nLits && i < p2->nLits; i++ ) { if ( p1->Lits[i] > p2->Lits[i] ) return -1; if ( p1->Lits[i] < p2->Lits[i] ) return 1; } if ( i == p1->nLits && i < p2->nLits ) return -1; if ( i < p1->nLits && i == p2->nLits ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext ) { Pdr_Obl_t * p; p = ABC_ALLOC( Pdr_Obl_t, 1 ); p->iFrame = k; p->prio = prio; p->nRefs = 1; p->pState = pState; p->pNext = pNext; p->pLink = NULL; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p ) { p->nRefs++; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_OblDeref( Pdr_Obl_t * p ) { if ( --p->nRefs == 0 ) { if ( p->pNext ) Pdr_OblDeref( p->pNext ); Pdr_SetDeref( p->pState ); ABC_FREE( p ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_QueueIsEmpty( Pdr_Man_t * p ) { return p->pQueue == NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p ) { return p->pQueue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p ) { Pdr_Obl_t * pRes = p->pQueue; if ( p->pQueue == NULL ) return NULL; p->pQueue = p->pQueue->pLink; Pdr_OblDeref( pRes ); p->nQueCur--; return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_QueueClean( Pdr_Man_t * p ) { Pdr_Obl_t * pThis; while ( (pThis = Pdr_QueuePop(p)) ) Pdr_OblDeref( pThis ); pThis = NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl ) { Pdr_Obl_t * pTemp, ** ppPrev; p->nObligs++; p->nQueCur++; p->nQueMax = Abc_MaxInt( p->nQueMax, p->nQueCur ); Pdr_OblRef( pObl ); if ( p->pQueue == NULL ) { p->pQueue = pObl; return; } for ( ppPrev = &p->pQueue, pTemp = p->pQueue; pTemp; ppPrev = &pTemp->pLink, pTemp = pTemp->pLink ) if ( pTemp->iFrame > pObl->iFrame || (pTemp->iFrame == pObl->iFrame && pTemp->prio > pObl->prio) ) break; *ppPrev = pObl; pObl->pLink = pTemp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_QueuePrint( Pdr_Man_t * p ) { Pdr_Obl_t * pObl; for ( pObl = p->pQueue; pObl; pObl = pObl->pLink ) Abc_Print( 1, "Frame = %2d. Prio = %8d.\n", pObl->iFrame, pObl->prio ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pdr_QueueStop( Pdr_Man_t * p ) { Pdr_Obl_t * pObl; while ( !Pdr_QueueIsEmpty(p) ) { pObl = Pdr_QueuePop(p); Pdr_OblDeref( pObl ); } p->pQueue = NULL; p->nQueCur = 0; } #define PDR_VAL0 1 #define PDR_VAL1 2 #define PDR_VALX 3 /**Function************************************************************* Synopsis [Returns value (0 or 1) or X if unassigned.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pdr_ObjSatValue( Aig_Man_t * pAig, Aig_Obj_t * pNode, int fCompl ) { if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) return (pNode->fMarkA ^ fCompl) ? PDR_VAL1 : PDR_VAL0; return PDR_VALX; } /**Function************************************************************* Synopsis [Recursively searched for a satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Pdr_Set_t * pCube, int Heur ) { int Value0, Value1; 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 ( vSuppLits ) // Vec_IntPush( vSuppLits, Abc_Var2Lit( Aig_ObjCioId(pNode), !Value ) ); if ( Saig_ObjIsLo(pAig, pNode) ) { // pCube->Lits[pCube->nLits++] = Abc_Var2Lit( Aig_ObjCioId(pNode) - Saig_ManPiNum(pAig), !Value ); pCube->Lits[pCube->nLits++] = Abc_Var2Lit( Aig_ObjCioId(pNode) - Saig_ManPiNum(pAig), Value ); pCube->Sign |= ((word)1 << (pCube->Lits[pCube->nLits-1] % 63)); } return 1; } assert( Aig_ObjIsNode(pNode) ); // propagation if ( Value ) { if ( !Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), !Aig_ObjFaninC0(pNode), pCube, Heur) ) return 0; return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), !Aig_ObjFaninC1(pNode), pCube, Heur); } // justification Value0 = Pdr_ObjSatValue( pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode) ); if ( Value0 == PDR_VAL0 ) return 1; Value1 = Pdr_ObjSatValue( pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode) ); if ( Value1 == PDR_VAL0 ) return 1; if ( Value0 == PDR_VAL1 && Value1 == PDR_VAL1 ) return 0; if ( Value0 == PDR_VAL1 ) return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur); if ( Value1 == PDR_VAL1 ) return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur); assert( Value0 == PDR_VALX && Value1 == PDR_VALX ); // decision making // if ( rand() % 10 == Heur ) if ( Aig_ObjId(pNode) % 4 == Heur ) return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur); else return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur); } /**Function************************************************************* Synopsis [Returns 1 if SAT assignment is found; 0 otherwise.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube ) { Aig_Obj_t * pNode; int i, v, fCompl; // return 0; for ( i = 0; i < 4; i++ ) { // derive new assignment p->pCubeJust->nLits = 0; p->pCubeJust->Sign = 0; Aig_ManIncrementTravId( p->pAig ); for ( v = 0; v < pCube->nLits; v++ ) { if ( pCube->Lits[v] == -1 ) continue; pNode = Saig_ManLi( p->pAig, lit_var(pCube->Lits[v]) ); fCompl = lit_sign(pCube->Lits[v]) ^ Aig_ObjFaninC0(pNode); if ( !Pdr_NtkFindSatAssign_rec( p->pAig, Aig_ObjFanin0(pNode), !fCompl, p->pCubeJust, i ) ) break; } if ( v < pCube->nLits ) continue; // figure this out!!! if ( p->pCubeJust->nLits == 0 ) continue; // successfully derived new assignment Vec_IntSelectSort( p->pCubeJust->Lits, p->pCubeJust->nLits ); // check assignment against this cube if ( Pdr_SetContainsSimple( p->pCubeJust, pCube ) ) continue; //printf( "\n" ); //Pdr_SetPrint( stdout, pCube, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" ); //Pdr_SetPrint( stdout, p->pCubeJust, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" ); // check assignment against the clauses if ( Pdr_ManCheckContainment( p, k, p->pCubeJust ) ) continue; // find good assignment return 1; } return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/000077500000000000000000000000001300674244400217515ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/module.make000066400000000000000000000002121300674244400240700ustar00rootroot00000000000000SRC += src/proof/ssc/sscClass.c \ src/proof/ssc/sscCore.c \ src/proof/ssc/sscSat.c \ src/proof/ssc/sscSim.c \ src/proof/ssc/sscUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/ssc.h000066400000000000000000000054631300674244400227220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ssc.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sweeping under constraints.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: ssc.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__ssc__ssc_h #define ABC__aig__ssc__ssc_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // choicing parameters typedef struct Ssc_Pars_t_ Ssc_Pars_t; struct Ssc_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 nCallsRecycle; // calls to perform before recycling SAT solver int fAppend; // append constraints to the resulting AIG int fVerbose; // verbose stats int fVerify; // enable internal verification }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== sscCore.c ==========================================================*/ extern void Ssc_ManSetDefaultParams( Ssc_Pars_t * p ); extern Gia_Man_t * Ssc_PerformSweeping( Gia_Man_t * pAig, Gia_Man_t * pCare, Ssc_Pars_t * pPars ); extern Gia_Man_t * Ssc_PerformSweepingConstr( Gia_Man_t * p, Ssc_Pars_t * pPars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/sscClass.c000066400000000000000000000230501300674244400236730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sscClass.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sweeping under constraints.] Synopsis [Equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: sscClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sscInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes hash key of the simuation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ssc_GiaSimHashKey( Gia_Man_t * p, int iObj, int nTableSize ) { static int s_Primes[16] = { 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; word * pSim = Gia_ObjSim( p, iObj ); unsigned uHash = 0; int i, nWords = Gia_ObjSimWords(p); 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 [Returns 1 if sim patterns are equal up to the complement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ssc_GiaSimIsConst0( Gia_Man_t * p, int iObj0 ) { int w, nWords = Gia_ObjSimWords(p); word * pSim = Gia_ObjSim( p, iObj0 ); if ( pSim[0] & 1 ) { for ( w = 0; w < nWords; w++ ) if ( ~pSim[w] ) return 0; } else { for ( w = 0; w < nWords; w++ ) if ( pSim[w] ) return 0; } return 1; } static inline int Ssc_GiaSimAreEqual( Gia_Man_t * p, int iObj0, int iObj1 ) { int w, nWords = Gia_ObjSimWords(p); word * pSim0 = Gia_ObjSim( p, iObj0 ); word * pSim1 = Gia_ObjSim( p, iObj1 ); if ( (pSim0[0] & 1) != (pSim1[0] & 1) ) { for ( w = 0; w < nWords; w++ ) if ( pSim0[w] != ~pSim1[w] ) return 0; } else { for ( w = 0; w < nWords; w++ ) if ( pSim0[w] != pSim1[w] ) return 0; } return 1; } static inline int Ssc_GiaSimAreEqualBit( Gia_Man_t * p, int iObj0, int iObj1 ) { Gia_Obj_t * pObj0 = Gia_ManObj( p, iObj0 ); Gia_Obj_t * pObj1 = Gia_ManObj( p, iObj1 ); return (pObj0->fPhase ^ pObj0->fMark0) == (pObj1->fPhase ^ pObj1->fMark0); } /**Function************************************************************* Synopsis [Refines one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_GiaSimClassCreate( 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 using individual bit-pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_GiaSimClassRefineOneBit( Gia_Man_t * p, int i ) { Gia_Obj_t * pObj; int Ent; assert( Gia_ObjIsHead( p, i ) ); Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Vec_IntPush( p->vClassOld, i ); pObj = Gia_ManObj(p, i); Gia_ClassForEachObj1( p, i, Ent ) { if ( Ssc_GiaSimAreEqualBit( p, i, Ent ) ) Vec_IntPush( p->vClassOld, Ent ); else Vec_IntPush( p->vClassNew, Ent ); } if ( Vec_IntSize( p->vClassNew ) == 0 ) return 0; Ssc_GiaSimClassCreate( p, p->vClassOld ); Ssc_GiaSimClassCreate( p, p->vClassNew ); return 1; } /**Function************************************************************* Synopsis [Refines one class using simulation patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_GiaSimClassRefineOne( Gia_Man_t * p, int i ) { Gia_Obj_t * pObj; int Ent; assert( Gia_ObjIsHead( p, i ) ); Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Vec_IntPush( p->vClassOld, i ); pObj = Gia_ManObj(p, i); Gia_ClassForEachObj1( p, i, Ent ) { if ( Ssc_GiaSimAreEqual( p, i, Ent ) ) Vec_IntPush( p->vClassOld, Ent ); else Vec_IntPush( p->vClassNew, Ent ); } if ( Vec_IntSize( p->vClassNew ) == 0 ) return 0; Ssc_GiaSimClassCreate( p, p->vClassOld ); Ssc_GiaSimClassCreate( p, p->vClassNew ); if ( Vec_IntSize(p->vClassNew) > 1 ) return 1 + Ssc_GiaSimClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); return 1; } void Ssc_GiaSimProcessRefined( Gia_Man_t * p, Vec_Int_t * vRefined ) { int * pTable, nTableSize, i, k, Key; if ( Vec_IntSize(vRefined) == 0 ) return; nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 3 ); pTable = ABC_CALLOC( int, nTableSize ); Vec_IntForEachEntry( vRefined, i, k ) { assert( !Ssc_GiaSimIsConst0( p, i ) ); Key = Ssc_GiaSimHashKey( p, i, nTableSize ); if ( pTable[Key] == 0 ) { assert( Gia_ObjRepr(p, i) == 0 ); assert( Gia_ObjNext(p, i) == 0 ); Gia_ObjSetRepr( p, i, GIA_VOID ); } else { Gia_ObjSetNext( p, pTable[Key], i ); Gia_ObjSetRepr( p, i, Gia_ObjRepr(p, pTable[Key]) ); if ( Gia_ObjRepr(p, i) == GIA_VOID ) Gia_ObjSetRepr( p, i, pTable[Key] ); assert( Gia_ObjRepr(p, i) > 0 ); } pTable[Key] = i; } Vec_IntForEachEntry( vRefined, i, k ) if ( Gia_ObjIsHead( p, i ) ) Ssc_GiaSimClassRefineOne( p, i ); ABC_FREE( pTable ); } /**Function************************************************************* Synopsis [Refines equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_GiaClassesInit( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; assert( p->pReprs == NULL ); p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); p->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) Gia_ObjSetRepr( p, i, Gia_ObjIsCand(pObj) ? 0 : GIA_VOID ); if ( p->vClassOld == NULL ) p->vClassOld = Vec_IntAlloc( 100 ); if ( p->vClassNew == NULL ) p->vClassNew = Vec_IntAlloc( 100 ); } int Ssc_GiaClassesRefine( Gia_Man_t * p ) { Vec_Int_t * vRefinedC; Gia_Obj_t * pObj; int i, Counter = 0; assert( p->pReprs != NULL ); vRefinedC = Vec_IntAlloc( 100 ); Gia_ManForEachCand( p, pObj, i ) if ( Gia_ObjIsTail(p, i) ) Counter += Ssc_GiaSimClassRefineOne( p, Gia_ObjRepr(p, i) ); else if ( Gia_ObjIsConst(p, i) && !Ssc_GiaSimIsConst0(p, i) ) Vec_IntPush( vRefinedC, i ); Ssc_GiaSimProcessRefined( p, vRefinedC ); Counter += Vec_IntSize( vRefinedC ); Vec_IntFree( vRefinedC ); return Counter; } /**Function************************************************************* Synopsis [Check if the pairs have been disproved.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_GiaClassesCheckPairs( Gia_Man_t * p, Vec_Int_t * vDisPairs ) { int i, iRepr, iObj, Result = 1; Vec_IntForEachEntryDouble( vDisPairs, iRepr, iObj, i ) if ( iRepr == Gia_ObjRepr(p, iObj) ) printf( "Pair (%d, %d) are still equivalent.\n", iRepr, iObj ), Result = 0; // if ( Result ) // printf( "Classes are refined correctly.\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/sscCore.c000066400000000000000000000416301300674244400235220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sscCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sweeping under constraints.] Synopsis [The core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: sscCore.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sscInt.h" #include "proof/cec/cec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_ManSetDefaultParams( Ssc_Pars_t * p ) { memset( p, 0, sizeof(Ssc_Pars_t) ); p->nWords = 1; // the number of simulation words p->nBTLimit = 1000; // conflict limit at a node p->nSatVarMax = 5000; // the max number of SAT variables p->nCallsRecycle = 100; // calls to perform before recycling SAT solver p->fVerbose = 0; // verbose stats } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_ManStop( Ssc_Man_t * p ) { Vec_IntFreeP( &p->vFront ); Vec_IntFreeP( &p->vFanins ); Vec_IntFreeP( &p->vPattern ); Vec_IntFreeP( &p->vDisPairs ); Vec_IntFreeP( &p->vPivot ); Vec_IntFreeP( &p->vId2Var ); Vec_IntFreeP( &p->vVar2Id ); if ( p->pSat ) sat_solver_delete( p->pSat ); Gia_ManStopP( &p->pFraig ); ABC_FREE( p ); } Ssc_Man_t * Ssc_ManStart( Gia_Man_t * pAig, Gia_Man_t * pCare, Ssc_Pars_t * pPars ) { Ssc_Man_t * p; p = ABC_CALLOC( Ssc_Man_t, 1 ); p->pPars = pPars; p->pAig = pAig; p->pCare = pCare; p->pFraig = Gia_ManDupDfs( p->pCare ); assert( p->pFraig->pHTable == NULL ); assert( !Gia_ManHasDangling(p->pFraig) ); Gia_ManInvertPos( p->pFraig ); Ssc_ManStartSolver( p ); if ( p->pSat == NULL ) { printf( "Constraints are UNSAT after propagation.\n" ); Ssc_ManStop( p ); return (Ssc_Man_t *)(ABC_PTRINT_T)1; } // p->vPivot = Ssc_GiaFindPivotSim( p->pFraig ); // Vec_IntFreeP( &p->vPivot ); p->vPivot = Ssc_ManFindPivotSat( p ); if ( p->vPivot == (Vec_Int_t *)(ABC_PTRINT_T)1 ) { printf( "Constraints are UNSAT.\n" ); Ssc_ManStop( p ); return (Ssc_Man_t *)(ABC_PTRINT_T)1; } if ( p->vPivot == NULL ) { printf( "Conflict limit is reached while trying to find one SAT assignment.\n" ); Ssc_ManStop( p ); return NULL; } sat_solver_bookmark( p->pSat ); // Vec_IntPrint( p->vPivot ); Gia_ManSetPhasePattern( p->pAig, p->vPivot ); Gia_ManSetPhasePattern( p->pCare, p->vPivot ); if ( Gia_ManCheckCoPhase(p->pCare) ) { printf( "Computed reference pattern violates %d constraints (this is a bug!).\n", Gia_ManCheckCoPhase(p->pCare) ); Ssc_ManStop( p ); return NULL; } // other things p->vDisPairs = Vec_IntAlloc( 100 ); p->vPattern = Vec_IntAlloc( 100 ); p->vFanins = Vec_IntAlloc( 100 ); p->vFront = Vec_IntAlloc( 100 ); Ssc_GiaClassesInit( pAig ); // now it is ready for refinement using simulation return p; } void Ssc_ManPrintStats( Ssc_Man_t * p ) { Abc_Print( 1, "Parameters: SimWords = %d. SatConfs = %d. SatVarMax = %d. CallsRec = %d. Verbose = %d.\n", p->pPars->nWords, p->pPars->nBTLimit, p->pPars->nSatVarMax, p->pPars->nCallsRecycle, p->pPars->fVerbose ); Abc_Print( 1, "SAT calls : Total = %d. Proof = %d. Cex = %d. Undec = %d.\n", p->nSatCalls, p->nSatCallsUnsat, p->nSatCallsSat, p->nSatCallsUndec ); Abc_Print( 1, "SAT solver: Vars = %d. Clauses = %d. Recycles = %d. Sim rounds = %d.\n", sat_solver_nvars(p->pSat), sat_solver_nclauses(p->pSat), p->nRecycles, p->nSimRounds ); p->timeOther = p->timeTotal - p->timeSimInit - p->timeSimSat - p->timeCnfGen - p->timeSatSat - p->timeSatUnsat - p->timeSatUndec; ABC_PRTP( "Initialization ", p->timeSimInit, p->timeTotal ); ABC_PRTP( "SAT simulation ", p->timeSimSat, p->timeTotal ); ABC_PRTP( "CNF generation ", p->timeSimSat, p->timeTotal ); ABC_PRTP( "SAT solving ", p->timeSat-p->timeCnfGen, p->timeTotal ); ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); ABC_PRTP( " undecided ", p->timeSatUndec, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); } /**Function************************************************************* Synopsis [Refine one class by resimulating one pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_GiaSimulatePatternFraig_rec( Ssc_Man_t * p, int iFraigObj ) { Gia_Obj_t * pObj; int Res0, Res1; if ( Ssc_ObjSatVar(p, iFraigObj) ) return sat_solver_var_value( p->pSat, Ssc_ObjSatVar(p, iFraigObj) ); pObj = Gia_ManObj( p->pFraig, iFraigObj ); assert( Gia_ObjIsAnd(pObj) ); Res0 = Ssc_GiaSimulatePatternFraig_rec( p, Gia_ObjFaninId0(pObj, iFraigObj) ); Res1 = Ssc_GiaSimulatePatternFraig_rec( p, Gia_ObjFaninId1(pObj, iFraigObj) ); pObj->fMark0 = (Res0 ^ Gia_ObjFaninC0(pObj)) & (Res1 ^ Gia_ObjFaninC1(pObj)); return pObj->fMark0; } int Ssc_GiaSimulatePattern_rec( Ssc_Man_t * p, Gia_Obj_t * pObj ) { int Res0, Res1; if ( Gia_ObjIsTravIdCurrent(p->pAig, pObj) ) return pObj->fMark0; Gia_ObjSetTravIdCurrent(p->pAig, pObj); if ( ~pObj->Value ) // mapping into FRAIG exists - simulate FRAIG { Res0 = Ssc_GiaSimulatePatternFraig_rec( p, Abc_Lit2Var(pObj->Value) ); pObj->fMark0 = Res0 ^ Abc_LitIsCompl(pObj->Value); } else // mapping into FRAIG does not exist - simulate AIG { Res0 = Ssc_GiaSimulatePattern_rec( p, Gia_ObjFanin0(pObj) ); Res1 = Ssc_GiaSimulatePattern_rec( p, Gia_ObjFanin1(pObj) ); pObj->fMark0 = (Res0 ^ Gia_ObjFaninC0(pObj)) & (Res1 ^ Gia_ObjFaninC1(pObj)); } return pObj->fMark0; } int Ssc_GiaResimulateOneClass( Ssc_Man_t * p, int iRepr, int iObj ) { int Ent, RetValue; assert( iRepr == Gia_ObjRepr(p->pAig, iObj) ); assert( Gia_ObjIsHead( p->pAig, iRepr ) ); // set bit-values at the nodes according to the counter-example Gia_ManIncrementTravId( p->pAig ); Gia_ClassForEachObj( p->pAig, iRepr, Ent ) Ssc_GiaSimulatePattern_rec( p, Gia_ManObj(p->pAig, Ent) ); // refine one class using these bit-values RetValue = Ssc_GiaSimClassRefineOneBit( p->pAig, iRepr ); // check that the candidate equivalence is indeed refined assert( iRepr != Gia_ObjRepr(p->pAig, iObj) ); return RetValue; } /**Function************************************************************* Synopsis [Perform verification of conditional sweeping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_PerformVerification( Gia_Man_t * p0, Gia_Man_t * p1, Gia_Man_t * pC ) { int Status; Cec_ParCec_t ParsCec, * pPars = &ParsCec; // derive the OR of constraint outputs Gia_Man_t * pCond = Gia_ManDupAndOr( pC, Gia_ManPoNum(p0), 1, 0 ); // derive F = F & !OR(c0, c1, c2, ...) Gia_Man_t * p0c = Gia_ManMiter( p0, pCond, 0, 0, 0, 1, 0 ); // derive F = F & !OR(c0, c1, c2, ...) Gia_Man_t * p1c = Gia_ManMiter( p1, pCond, 0, 0, 0, 1, 0 ); // derive dual-output miter Gia_Man_t * pMiter = Gia_ManMiter( p0c, p1c, 0, 1, 0, 0, 0 ); Gia_ManStop( p0c ); Gia_ManStop( p1c ); Gia_ManStop( pCond ); // run equivalence checking Cec_ManCecSetDefaultParams( pPars ); Status = Cec_ManVerify( pMiter, pPars ); Gia_ManStop( pMiter ); // report the results if ( Status == 1 ) printf( "Verification succeeded.\n" ); else if ( Status == 0 ) printf( "Verification failed.\n" ); else if ( Status == -1 ) printf( "Verification undecided.\n" ); else assert( 0 ); return Status; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Ssc_PerformSweepingInt( Gia_Man_t * pAig, Gia_Man_t * pCare, Ssc_Pars_t * pPars ) { Ssc_Man_t * p; Gia_Man_t * pResult, * pTemp; Gia_Obj_t * pObj, * pRepr; abctime clk, clkTotal = Abc_Clock(); int i, fCompl, nRefined, status; clk = Abc_Clock(); assert( Gia_ManRegNum(pCare) == 0 ); assert( Gia_ManCiNum(pAig) == Gia_ManCiNum(pCare) ); assert( Gia_ManIsNormalized(pAig) ); assert( Gia_ManIsNormalized(pCare) ); // reset random numbers Gia_ManRandom( 1 ); // sweeping manager p = Ssc_ManStart( pAig, pCare, pPars ); if ( p == (Ssc_Man_t *)(ABC_PTRINT_T)1 ) // UNSAT return Gia_ManDupZero( pAig ); if ( p == NULL ) // timeout return Gia_ManDup( pAig ); if ( p->pPars->fVerbose ) printf( "Care set produced %d hits out of %d.\n", Ssc_GiaEstimateCare(p->pFraig, 5), 640 ); // perform simulation while ( 1 ) { // simulate care set Ssc_GiaRandomPiPattern( p->pFraig, 5, NULL ); Ssc_GiaSimRound( p->pFraig ); // transfer care patterns to user's AIG if ( !Ssc_GiaTransferPiPattern( pAig, p->pFraig, p->vPivot ) ) break; // simulate the main AIG Ssc_GiaSimRound( pAig ); nRefined = Ssc_GiaClassesRefine( pAig ); if ( pPars->fVerbose ) Gia_ManEquivPrintClasses( pAig, 0, 0 ); if ( nRefined <= Gia_ManCandNum(pAig) / 100 ) break; } p->timeSimInit += Abc_Clock() - clk; // prepare user's AIG Gia_ManFillValue(pAig); Gia_ManConst0(pAig)->Value = 0; Gia_ManForEachCi( pAig, pObj, i ) pObj->Value = Gia_Obj2Lit( p->pFraig, Gia_ManCi(p->pFraig, i) ); // Gia_ManLevelNum(pAig); // prepare swept AIG (should be done after starting SAT solver in Ssc_ManStart) Gia_ManHashStart( p->pFraig ); // perform sweeping Ssc_GiaResetPiPattern( pAig, pPars->nWords ); Ssc_GiaSavePiPattern( pAig, p->vPivot ); Gia_ManForEachCand( pAig, pObj, i ) { if ( pAig->iPatsPi == 64 * pPars->nWords ) { clk = Abc_Clock(); Ssc_GiaSimRound( pAig ); Ssc_GiaClassesRefine( pAig ); if ( pPars->fVerbose ) Gia_ManEquivPrintClasses( pAig, 0, 0 ); Ssc_GiaClassesCheckPairs( pAig, p->vDisPairs ); Vec_IntClear( p->vDisPairs ); // prepare next patterns Ssc_GiaResetPiPattern( pAig, pPars->nWords ); Ssc_GiaSavePiPattern( pAig, p->vPivot ); p->timeSimSat += Abc_Clock() - clk; //printf( "\n" ); } if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( p->pFraig, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( !Gia_ObjHasRepr(pAig, i) ) continue; pRepr = Gia_ObjReprObj(pAig, i); if ( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, pRepr->fPhase ^ pObj->fPhase ) ) { Gia_ObjSetProved( pAig, i ); continue; } assert( Abc_Lit2Var(pRepr->Value) != Abc_Lit2Var(pObj->Value) ); fCompl = pRepr->fPhase ^ pObj->fPhase ^ Abc_LitIsCompl(pRepr->Value) ^ Abc_LitIsCompl(pObj->Value); // perform SAT call clk = Abc_Clock(); p->nSatCalls++; status = Ssc_ManCheckEquivalence( p, Abc_Lit2Var(pRepr->Value), Abc_Lit2Var(pObj->Value), fCompl ); if ( status == l_False ) { p->nSatCallsUnsat++; pObj->Value = Abc_LitNotCond( pRepr->Value, pRepr->fPhase ^ pObj->fPhase ); Gia_ObjSetProved( pAig, i ); } else if ( status == l_True ) { p->nSatCallsSat++; Ssc_GiaSavePiPattern( pAig, p->vPattern ); Vec_IntPush( p->vDisPairs, Gia_ObjRepr(p->pAig, i) ); Vec_IntPush( p->vDisPairs, i ); // printf( "Try %2d and %2d: ", Gia_ObjRepr(p->pAig, i), i ); // Vec_IntPrint( p->vPattern ); if ( Gia_ObjRepr(p->pAig, i) > 0 ) Ssc_GiaResimulateOneClass( p, Gia_ObjRepr(p->pAig, i), i ); } else if ( status == l_Undef ) p->nSatCallsUndec++; else assert( 0 ); p->timeSat += Abc_Clock() - clk; } if ( pAig->iPatsPi > 1 ) { clk = Abc_Clock(); while ( pAig->iPatsPi < 64 * pPars->nWords ) Ssc_GiaSavePiPattern( pAig, p->vPivot ); Ssc_GiaSimRound( pAig ); Ssc_GiaClassesRefine( pAig ); if ( pPars->fVerbose ) Gia_ManEquivPrintClasses( pAig, 0, 0 ); Ssc_GiaClassesCheckPairs( pAig, p->vDisPairs ); Vec_IntClear( p->vDisPairs ); p->timeSimSat += Abc_Clock() - clk; } // Gia_ManEquivPrintClasses( pAig, 1, 0 ); // Gia_ManPrint( pAig ); // generate the resulting AIG pResult = Gia_ManEquivReduce( pAig, 0, 0, 1, 0 ); if ( pResult == NULL ) { printf( "There is no equivalences.\n" ); ABC_FREE( pAig->pReprs ); ABC_FREE( pAig->pNexts ); pResult = Gia_ManDup( pAig ); } pResult = Gia_ManCleanup( pTemp = pResult ); Gia_ManStop( pTemp ); p->timeTotal = Abc_Clock() - clkTotal; if ( pPars->fVerbose ) Ssc_ManPrintStats( p ); Ssc_ManStop( p ); // count the number of representatives if ( pPars->fVerbose ) { Abc_Print( 1, "Reduction in AIG nodes:%8d ->%8d (%6.2f %%). ", Gia_ManAndNum(pAig), Gia_ManAndNum(pResult), 100.0 - 100.0 * Gia_ManAndNum(pResult) / Gia_ManAndNum(pAig) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } return pResult; } Gia_Man_t * Ssc_PerformSweeping( Gia_Man_t * pAig, Gia_Man_t * pCare, Ssc_Pars_t * pPars ) { Gia_Man_t * pResult = Ssc_PerformSweepingInt( pAig, pCare, pPars ); if ( pPars->fVerify ) Ssc_PerformVerification( pAig, pResult, pCare ); return pResult; } Gia_Man_t * Ssc_PerformSweepingConstr( Gia_Man_t * p, Ssc_Pars_t * pPars ) { Gia_Man_t * pAig, * pCare, * pResult; int i; if ( pPars->fVerbose ) Abc_Print( 0, "SAT sweeping AIG with %d constraints.\n", p->nConstrs ); if ( p->nConstrs == 0 ) { pAig = Gia_ManDup( p ); pCare = Gia_ManStart( Gia_ManCiNum(p) + 2 ); pCare->pName = Abc_UtilStrsav( "care" ); for ( i = 0; i < Gia_ManCiNum(p); i++ ) Gia_ManAppendCi( pCare ); Gia_ManAppendCo( pCare, 0 ); } else { Vec_Int_t * vOuts = Vec_IntStartNatural( Gia_ManPoNum(p) ); pAig = Gia_ManDupCones( p, Vec_IntArray(vOuts), Gia_ManPoNum(p) - p->nConstrs, 0 ); pCare = Gia_ManDupCones( p, Vec_IntArray(vOuts) + Gia_ManPoNum(p) - p->nConstrs, p->nConstrs, 0 ); Vec_IntFree( vOuts ); } if ( pPars->fVerbose ) { printf( "User AIG: " ); Gia_ManPrintStats( pAig, NULL ); printf( "Care AIG: " ); Gia_ManPrintStats( pCare, NULL ); } pAig = Gia_ManDupLevelized( pResult = pAig ); Gia_ManStop( pResult ); pResult = Ssc_PerformSweeping( pAig, pCare, pPars ); if ( pPars->fAppend ) { Gia_ManDupAppendShare( pResult, pCare ); pResult->nConstrs = Gia_ManPoNum(pCare); } Gia_ManStop( pAig ); Gia_ManStop( pCare ); return pResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/sscInt.h000066400000000000000000000147341300674244400233760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sscInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Choice computation for tech-mapping.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: sscInt.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__ssc__sscInt_h #define ABC__aig__ssc__sscInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/gia/gia.h" #include "sat/bsat/satSolver.h" #include "ssc.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // choicing manager typedef struct Ssc_Man_t_ Ssc_Man_t; struct Ssc_Man_t_ { // user data Ssc_Pars_t * pPars; // choicing parameters Gia_Man_t * pAig; // subject AIG Gia_Man_t * pCare; // care set AIG // internal data Gia_Man_t * pFraig; // resulting AIG sat_solver * pSat; // recyclable SAT solver Vec_Int_t * vId2Var; // mapping of each node into its SAT var Vec_Int_t * vVar2Id; // mapping of each SAT var into its node Vec_Int_t * vPivot; // one SAT pattern int nSatVarsPivot; // the number of variables for constraints int nSatVars; // the current number of variables // temporary storage Vec_Int_t * vFront; // supergate fanins Vec_Int_t * vFanins; // supergate fanins Vec_Int_t * vPattern; // counter-example Vec_Int_t * vDisPairs; // disproved pairs // SAT calls statistics int nSimRounds; // the number of simulation rounds int nRecycles; // the number of times SAT solver was recycled int nCallsSince; // the number of calls since the last recycle int nSatCalls; // the number of SAT calls int nSatCallsUnsat; // the number of unsat SAT calls int nSatCallsSat; // the number of sat SAT calls int nSatCallsUndec; // the number of undec SAT calls // runtime stats abctime timeSimInit; // simulation and class computation abctime timeSimSat; // simulation of the counter-examples abctime timeCnfGen; // generation of CNF abctime timeSat; // total SAT time abctime timeSatSat; // sat abctime timeSatUnsat; // unsat abctime timeSatUndec; // undecided abctime timeOther; // other runtime abctime timeTotal; // total runtime }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Ssc_ObjSatVar( Ssc_Man_t * p, int iObj ) { return Vec_IntEntry(p->vId2Var, iObj); } static inline void Ssc_ObjSetSatVar( Ssc_Man_t * p, int iObj, int Num ) { Vec_IntWriteEntry(p->vId2Var, iObj, Num); Vec_IntWriteEntry(p->vVar2Id, Num, iObj); } static inline void Ssc_ObjCleanSatVar( Ssc_Man_t * p, int Num ) { Vec_IntWriteEntry(p->vId2Var, Vec_IntEntry(p->vVar2Id, Num), Num); Vec_IntWriteEntry(p->vVar2Id, Num, 0); } static inline int Ssc_ObjFraig( Ssc_Man_t * p, Gia_Obj_t * pObj ) { return pObj->Value; } static inline void Ssc_ObjSetFraig( Gia_Obj_t * pObj, int iNode ) { pObj->Value = iNode; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== sscClass.c =================================================*/ extern void Ssc_GiaClassesInit( Gia_Man_t * p ); extern int Ssc_GiaClassesRefine( Gia_Man_t * p ); extern void Ssc_GiaClassesCheckPairs( Gia_Man_t * p, Vec_Int_t * vDisPairs ); extern int Ssc_GiaSimClassRefineOneBit( Gia_Man_t * p, int i ); /*=== sscCnf.c ===================================================*/ extern void Ssc_CnfNodeAddToSolver( Ssc_Man_t * p, Gia_Obj_t * pObj ); /*=== sscCore.c ==================================================*/ /*=== sscSat.c ===================================================*/ extern void Ssc_ManSatSolverRecycle( Ssc_Man_t * p ); extern void Ssc_ManStartSolver( Ssc_Man_t * p ); extern Vec_Int_t * Ssc_ManFindPivotSat( Ssc_Man_t * p ); extern int Ssc_ManCheckEquivalence( Ssc_Man_t * p, int iRepr, int iObj, int fCompl ); /*=== sscSim.c ===================================================*/ extern void Ssc_GiaResetPiPattern( Gia_Man_t * p, int nWords ); extern void Ssc_GiaRandomPiPattern( Gia_Man_t * p, int nWords, Vec_Int_t * vPivot ); extern int Ssc_GiaTransferPiPattern( Gia_Man_t * pAig, Gia_Man_t * pCare, Vec_Int_t * vPivot ); extern void Ssc_GiaSavePiPattern( Gia_Man_t * p, Vec_Int_t * vPat ); extern void Ssc_GiaSimRound( Gia_Man_t * p ); extern Vec_Int_t * Ssc_GiaFindPivotSim( Gia_Man_t * p ); extern int Ssc_GiaEstimateCare( Gia_Man_t * p, int nWords ); /*=== sscUtil.c ===================================================*/ extern Gia_Man_t * Ssc_GenerateOneHot( int nVars ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/sscSat.c000066400000000000000000000335761300674244400233730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sscSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sweeping under constraints.] Synopsis [SAT procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: sscSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sscInt.h" #include "sat/cnf/cnf.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Ssc_ObjSatLit( Ssc_Man_t * p, int Lit ) { return Abc_Var2Lit( Ssc_ObjSatVar(p, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManAddClausesMux( Ssc_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 = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNode) ); LitI = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNodeI) ); LitT = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNodeT) ); LitE = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,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( Ssc_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 = Ssc_ObjSatLit( p, Gia_Obj2Lit(p->pFraig,pNode) ); Vec_IntForEachEntry( vSuper, Lit, i ) { pLits[0] = Ssc_ObjSatLit( 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 Ssc_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { // stop at complements, PIs, and MUXes if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || Gia_ObjIsMuxType(pObj) ) { Vec_IntPushUnique( vSuper, Gia_Obj2Lit(p, pObj) ); return; } Ssc_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Ssc_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } static void Ssc_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { assert( !Gia_IsComplement(pObj) ); assert( Gia_ObjIsAnd(pObj) ); Vec_IntClear( vSuper ); Ssc_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Ssc_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Ssc_ManCnfAddToFrontier( Ssc_Man_t * p, int Id, Vec_Int_t * vFront ) { Gia_Obj_t * pObj; assert( Id > 0 ); if ( Ssc_ObjSatVar(p, Id) ) return; pObj = Gia_ManObj( p->pFraig, Id ); Ssc_ObjSetSatVar( p, Id, p->nSatVars++ ); sat_solver_setnvars( p->pSat, p->nSatVars + 100 ); if ( Gia_ObjIsAnd(pObj) ) Vec_IntPush( vFront, Id ); } static void Ssc_ManCnfNodeAddToSolver( Ssc_Man_t * p, int NodeId ) { Gia_Obj_t * pNode; int i, k, Id, Lit; abctime clk; assert( NodeId > 0 ); // quit if CNF is ready if ( Ssc_ObjSatVar(p, NodeId) ) return; clk = Abc_Clock(); // start the frontier Vec_IntClear( p->vFront ); Ssc_ManCnfAddToFrontier( p, NodeId, p->vFront ); // explore nodes in the frontier Gia_ManForEachObjVec( p->vFront, p->pFraig, pNode, i ) { // create the supergate assert( Ssc_ObjSatVar(p, Gia_ObjId(p->pFraig, pNode)) ); if ( Gia_ObjIsMuxType(pNode) ) { Vec_IntClear( p->vFanins ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pFraig, Gia_ObjFanin0(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pFraig, Gia_ObjFanin1(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pFraig, Gia_ObjFanin0(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pFraig, Gia_ObjFanin1(pNode) ) ); Vec_IntForEachEntry( p->vFanins, Id, k ) Ssc_ManCnfAddToFrontier( p, Id, p->vFront ); Gia_ManAddClausesMux( p, pNode ); } else { Ssc_ManCollectSuper( p->pFraig, pNode, p->vFanins ); Vec_IntForEachEntry( p->vFanins, Lit, k ) Ssc_ManCnfAddToFrontier( p, Abc_Lit2Var(Lit), p->vFront ); Gia_ManAddClausesSuper( p, pNode, p->vFanins ); } assert( Vec_IntSize(p->vFanins) > 1 ); } p->timeCnfGen += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Starts the SAT solver for constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_ManStartSolver( Ssc_Man_t * p ) { Aig_Man_t * pMan = Gia_ManToAigSimple( p->pFraig ); Cnf_Dat_t * pDat = Cnf_Derive( pMan, 0 ); Gia_Obj_t * pObj; sat_solver * pSat; int i, status; assert( p->pSat == NULL && p->vId2Var == NULL ); assert( Aig_ManObjNumMax(pMan) == Gia_ManObjNum(p->pFraig) ); Aig_ManStop( pMan ); // save variable mapping p->nSatVarsPivot = p->nSatVars = pDat->nVars; p->vId2Var = Vec_IntStart( Gia_ManCandNum(p->pAig) + Gia_ManCandNum(p->pCare) + 10 ); // mapping of each node into its SAT var p->vVar2Id = Vec_IntStart( Gia_ManCandNum(p->pAig) + Gia_ManCandNum(p->pCare) + 10 ); // mapping of each SAT var into its node Ssc_ObjSetSatVar( p, 0, pDat->pVarNums[0] ); Gia_ManForEachCi( p->pFraig, pObj, i ) { int iObj = Gia_ObjId( p->pFraig, pObj ); Ssc_ObjSetSatVar( p, iObj, pDat->pVarNums[iObj] ); } //Cnf_DataWriteIntoFile( pDat, "dump.cnf", 1, NULL, NULL ); // start the SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, pDat->nVars + 1000 ); for ( i = 0; i < pDat->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pDat->pClauses[i], pDat->pClauses[i+1] ) ) { Cnf_DataFree( pDat ); sat_solver_delete( pSat ); return; } } Cnf_DataFree( pDat ); status = sat_solver_simplify( pSat ); if ( status == 0 ) { sat_solver_delete( pSat ); return; } p->pSat = pSat; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_ManCollectSatPattern( Ssc_Man_t * p, Vec_Int_t * vPattern ) { Gia_Obj_t * pObj; int i; Vec_IntClear( vPattern ); Gia_ManForEachCi( p->pFraig, pObj, i ) Vec_IntPush( vPattern, sat_solver_var_value(p->pSat, Ssc_ObjSatVar(p, Gia_ObjId(p->pFraig, pObj))) ); } Vec_Int_t * Ssc_ManFindPivotSat( Ssc_Man_t * p ) { Vec_Int_t * vInit; int status = sat_solver_solve( p->pSat, NULL, NULL, p->pPars->nBTLimit, 0, 0, 0 ); if ( status == l_False ) return (Vec_Int_t *)(ABC_PTRINT_T)1; if ( status == l_Undef ) return NULL; assert( status == l_True ); vInit = Vec_IntAlloc( Gia_ManCiNum(p->pFraig) ); Ssc_ManCollectSatPattern( p, vInit ); return vInit; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_ManCheckEquivalence( Ssc_Man_t * p, int iRepr, int iNode, int fCompl ) { int pLitsSat[2], RetValue; abctime clk; assert( iRepr != iNode ); if ( iRepr > iNode ) return l_Undef; assert( iRepr < iNode ); // if ( p->nTimeOut ) // sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); // create CNF if ( iRepr ) Ssc_ManCnfNodeAddToSolver( p, iRepr ); Ssc_ManCnfNodeAddToSolver( p, iNode ); sat_solver_compress( p->pSat ); // order the literals pLitsSat[0] = Abc_Var2Lit( Ssc_ObjSatVar(p, iRepr), 0 ); pLitsSat[1] = Abc_Var2Lit( Ssc_ObjSatVar(p, iNode), fCompl ^ (int)(iRepr > 0) ); // solve under assumptions // A = 1; B = 0 clk = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, pLitsSat, pLitsSat + 2, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) { pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); // compl pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); // compl RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); assert( RetValue ); p->timeSatUnsat += Abc_Clock() - clk; } else if ( RetValue == l_True ) { Ssc_ManCollectSatPattern( p, p->vPattern ); p->timeSatSat += Abc_Clock() - clk; return l_True; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; return l_Undef; } // if the old node was constant 0, we already know the answer if ( iRepr == 0 ) return l_False; // solve under assumptions // A = 0; B = 1 clk = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, pLitsSat, pLitsSat + 2, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) { pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); assert( RetValue ); p->timeSatUnsat += Abc_Clock() - clk; } else if ( RetValue == l_True ) { Ssc_ManCollectSatPattern( p, p->vPattern ); p->timeSatSat += Abc_Clock() - clk; return l_True; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; return l_Undef; } return l_False; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/sscSim.c000066400000000000000000000267501300674244400233700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sscSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sweeping under constraints.] Synopsis [Simulation procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: sscSim.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sscInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline word Ssc_Random() { return ((word)Gia_ManRandom(0) << 32) | ((word)Gia_ManRandom(0) << 0); } static inline word Ssc_Random1( int Bit ) { return ((word)Gia_ManRandom(0) << 32) | ((word)Gia_ManRandom(0) << 1) | (word)Bit; } static inline word Ssc_Random2() { return ((word)Gia_ManRandom(0) << 32) | ((word)Gia_ManRandom(0) << 2) | (word)2; } static inline void Ssc_SimAnd( word * pSim, word * pSim0, word * pSim1, int nWords, int fComp0, int fComp1 ) { int w; if ( fComp0 && fComp1 ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~(pSim0[w] | pSim1[w]); else if ( fComp0 ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~pSim0[w] & pSim1[w]; else if ( fComp1 ) for ( w = 0; w < nWords; w++ ) pSim[w] = pSim0[w] &~pSim1[w]; else for ( w = 0; w < nWords; w++ ) pSim[w] = pSim0[w] & pSim1[w]; } static inline void Ssc_SimDup( word * pSim, word * pSim0, int nWords, int fComp0 ) { int w; if ( fComp0 ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~pSim0[w]; else for ( w = 0; w < nWords; w++ ) pSim[w] = pSim0[w]; } static inline void Ssc_SimConst( word * pSim, int nWords, int fComp0 ) { int w; if ( fComp0 ) for ( w = 0; w < nWords; w++ ) pSim[w] = ~(word)0; else for ( w = 0; w < nWords; w++ ) pSim[w] = 0; } static inline void Ssc_SimOr( word * pSim, word * pSim0, int nWords, int fComp0 ) { int w; if ( fComp0 ) for ( w = 0; w < nWords; w++ ) pSim[w] |= ~pSim0[w]; else for ( w = 0; w < nWords; w++ ) pSim[w] |= pSim0[w]; } static inline int Ssc_SimFindBitWord( word t ) { int n = 0; if ( t == 0 ) return -1; if ( (t & 0x00000000FFFFFFFF) == 0 ) { n += 32; t >>= 32; } if ( (t & 0x000000000000FFFF) == 0 ) { n += 16; t >>= 16; } if ( (t & 0x00000000000000FF) == 0 ) { n += 8; t >>= 8; } if ( (t & 0x000000000000000F) == 0 ) { n += 4; t >>= 4; } if ( (t & 0x0000000000000003) == 0 ) { n += 2; t >>= 2; } if ( (t & 0x0000000000000001) == 0 ) { n++; } return n; } static inline int Ssc_SimFindBit( word * pSim, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( pSim[w] ) return 64*w + Ssc_SimFindBitWord(pSim[w]); return -1; } static inline int Ssc_SimCountBitsWord( word x ) { x = x - ((x >> 1) & ABC_CONST(0x5555555555555555)); x = (x & ABC_CONST(0x3333333333333333)) + ((x >> 2) & ABC_CONST(0x3333333333333333)); x = (x + (x >> 4)) & ABC_CONST(0x0F0F0F0F0F0F0F0F); x = x + (x >> 8); x = x + (x >> 16); x = x + (x >> 32); return (int)(x & 0xFF); } static inline int Ssc_SimCountBits( word * pSim, int nWords ) { int w, Counter = 0; for ( w = 0; w < nWords; w++ ) Counter += Ssc_SimCountBitsWord(pSim[w]); return Counter; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Vec_WrdDoubleSimInfo( Vec_Wrd_t * p, int nObjs ) { word * pArray = ABC_CALLOC( word, 2 * Vec_WrdSize(p) ); int i, nWords = Vec_WrdSize(p) / nObjs; assert( Vec_WrdSize(p) % nObjs == 0 ); for ( i = 0; i < nObjs; i++ ) memcpy( pArray + 2*i*nWords, p->pArray + i*nWords, sizeof(word) * nWords ); ABC_FREE( p->pArray ); p->pArray = pArray; p->nSize = p->nCap = 2*nWords*nObjs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_GiaResetPiPattern( Gia_Man_t * p, int nWords ) { p->iPatsPi = 0; if ( p->vSimsPi == NULL ) p->vSimsPi = Vec_WrdStart(0); Vec_WrdFill( p->vSimsPi, nWords * Gia_ManCiNum(p), 0 ); assert( nWords == Gia_ObjSimWords( p ) ); } void Ssc_GiaSavePiPattern( Gia_Man_t * p, Vec_Int_t * vPat ) { word * pSimPi; int i; assert( Vec_IntSize(vPat) == Gia_ManCiNum(p) ); if ( p->iPatsPi == 64 * Gia_ObjSimWords(p) ) Vec_WrdDoubleSimInfo( p->vSimsPi, Gia_ManCiNum(p) ); assert( p->iPatsPi < 64 * Gia_ObjSimWords(p) ); pSimPi = Gia_ObjSimPi( p, 0 ); for ( i = 0; i < Gia_ManCiNum(p); i++, pSimPi += Gia_ObjSimWords(p) ) if ( Vec_IntEntry(vPat, i) ) Abc_InfoSetBit( (unsigned *)pSimPi, p->iPatsPi ); p->iPatsPi++; } void Ssc_GiaRandomPiPattern( Gia_Man_t * p, int nWords, Vec_Int_t * vPivot ) { word * pSimPi; int i, w; Ssc_GiaResetPiPattern( p, nWords ); pSimPi = Gia_ObjSimPi( p, 0 ); for ( i = 0; i < Gia_ManPiNum(p); i++, pSimPi += nWords ) { pSimPi[0] = vPivot ? Ssc_Random1(Vec_IntEntry(vPivot, i)) : Ssc_Random2(); for ( w = 1; w < nWords; w++ ) pSimPi[w] = Ssc_Random(); // if ( i < 10 ) // Extra_PrintBinary( stdout, (unsigned *)pSimPi, 64 ), printf( "\n" ); } } void Ssc_GiaPrintPiPatterns( Gia_Man_t * p ) { Gia_Obj_t * pObj; word * pSimAig; int i;//, nWords = Gia_ObjSimWords( p ); Gia_ManForEachCi( p, pObj, i ) { pSimAig = Gia_ObjSimObj( p, pObj ); // Extra_PrintBinary( stdout, pSimAig, 64 * nWords ); } } /**Function************************************************************* Synopsis [Transfer the simulation pattern from pCare to pAig.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_GiaTransferPiPattern( Gia_Man_t * pAig, Gia_Man_t * pCare, Vec_Int_t * vPivot ) { extern word * Ssc_GiaGetCareMask( Gia_Man_t * p ); Gia_Obj_t * pObj; int i, w, nWords = Gia_ObjSimWords( pCare ); word * pCareMask = Ssc_GiaGetCareMask( pCare ); int Count = Ssc_SimCountBits( pCareMask, nWords ); word * pSimPiCare, * pSimPiAig; if ( Count == 0 ) { ABC_FREE( pCareMask ); return 0; } Ssc_GiaResetPiPattern( pAig, nWords ); Gia_ManForEachCi( pCare, pObj, i ) { pSimPiAig = Gia_ObjSimPi( pAig, i ); pSimPiCare = Gia_ObjSimObj( pCare, pObj ); for ( w = 0; w < nWords; w++ ) if ( Vec_IntEntry(vPivot, i) ) pSimPiAig[w] = pSimPiCare[w] | ~pCareMask[w]; else pSimPiAig[w] = pSimPiCare[w] & pCareMask[w]; } ABC_FREE( pCareMask ); return Count; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssc_GiaResetSimInfo( Gia_Man_t * p ) { assert( Vec_WrdSize(p->vSimsPi) % Gia_ManCiNum(p) == 0 ); if ( p->vSims == NULL ) p->vSims = Vec_WrdAlloc(0); Vec_WrdFill( p->vSims, Gia_ObjSimWords(p) * Gia_ManObjNum(p), 0 ); } void Ssc_GiaSimRound( Gia_Man_t * p ) { Gia_Obj_t * pObj; word * pSim, * pSim0, * pSim1; int i, nWords = Gia_ObjSimWords(p); Ssc_GiaResetSimInfo( p ); assert( nWords == Vec_WrdSize(p->vSims) / Gia_ManObjNum(p) ); // constant node Ssc_SimConst( Gia_ObjSim(p, 0), nWords, 0 ); // primary inputs pSim = Gia_ObjSim( p, 1 ); pSim0 = Gia_ObjSimPi( p, 0 ); Gia_ManForEachCi( p, pObj, i ) { assert( pSim == Gia_ObjSimObj( p, pObj ) ); Ssc_SimDup( pSim, pSim0, nWords, 0 ); pSim += nWords; pSim0 += nWords; } // intermediate nodes pSim = Gia_ObjSim( p, 1+Gia_ManCiNum(p) ); Gia_ManForEachAnd( p, pObj, i ) { assert( pSim == Gia_ObjSim( p, i ) ); pSim0 = pSim - pObj->iDiff0 * nWords; pSim1 = pSim - pObj->iDiff1 * nWords; Ssc_SimAnd( pSim, pSim0, pSim1, nWords, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj) ); pSim += nWords; } // primary outputs pSim = Gia_ObjSim( p, Gia_ManObjNum(p) - Gia_ManPoNum(p) ); Gia_ManForEachPo( p, pObj, i ) { assert( pSim == Gia_ObjSimObj( p, pObj ) ); pSim0 = pSim - pObj->iDiff0 * nWords; Ssc_SimDup( pSim, pSim0, nWords, Gia_ObjFaninC0(pObj) ); // Extra_PrintBinary( stdout, pSim, 64 ), printf( "\n" ); pSim += nWords; } } /**Function************************************************************* Synopsis [Returns one SAT assignment of the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word * Ssc_GiaGetCareMask( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, nWords = Gia_ObjSimWords( p ); word * pRes = ABC_FALLOC( word, nWords ); Gia_ManForEachPo( p, pObj, i ) Ssc_SimAnd( pRes, pRes, Gia_ObjSimObj(p, pObj), nWords, 0, 0 ); return pRes; } Vec_Int_t * Ssc_GiaGetOneSim( Gia_Man_t * p ) { Vec_Int_t * vInit; Gia_Obj_t * pObj; int i, iBit, nWords = Gia_ObjSimWords( p ); word * pRes = Ssc_GiaGetCareMask( p ); iBit = Ssc_SimFindBit( pRes, nWords ); ABC_FREE( pRes ); if ( iBit == -1 ) return NULL; vInit = Vec_IntAlloc( 100 ); Gia_ManForEachCi( p, pObj, i ) Vec_IntPush( vInit, Abc_InfoHasBit((unsigned *)Gia_ObjSimObj(p, pObj), iBit) ); return vInit; } Vec_Int_t * Ssc_GiaFindPivotSim( Gia_Man_t * p ) { Vec_Int_t * vInit; Ssc_GiaRandomPiPattern( p, 1, NULL ); Ssc_GiaSimRound( p ); vInit = Ssc_GiaGetOneSim( p ); return vInit; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssc_GiaCountCaresSim( Gia_Man_t * p ) { word * pRes = Ssc_GiaGetCareMask( p ); int nWords = Gia_ObjSimWords( p ); int Count = Ssc_SimCountBits( pRes, nWords ); ABC_FREE( pRes ); return Count; } int Ssc_GiaEstimateCare( Gia_Man_t * p, int nWords ) { Ssc_GiaRandomPiPattern( p, nWords, NULL ); Ssc_GiaSimRound( p ); return Ssc_GiaCountCaresSim( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssc/sscUtil.c000066400000000000000000000121331300674244400235430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sscUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sweeping under constraints.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 29, 2008.] Revision [$Id: sscUtil.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sscInt.h" #include "sat/cnf/cnf.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDropContained( Gia_Man_t * p ) { Gia_Man_t * pNew; Aig_Man_t * pMan = Gia_ManToAigSimple( p ); Cnf_Dat_t * pDat = Cnf_Derive( pMan, Gia_ManPoNum(p) ); Gia_Obj_t * pObj; Vec_Int_t * vLits, * vKeep; sat_solver * pSat; int ConstLit = Abc_Var2Lit(pDat->pVarNums[0], 0); int i, status;//, Count = 0; Aig_ManStop( pMan ); vLits = Vec_IntAlloc( Gia_ManPoNum(p) ); Gia_ManForEachPo( p, pObj, i ) { int iObj = Gia_ObjId( p, pObj ); Vec_IntPush( vLits, Abc_Var2Lit(pDat->pVarNums[iObj], 1) ); } // start the SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, pDat->nVars ); for ( i = 0; i < pDat->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pDat->pClauses[i], pDat->pClauses[i+1] ) ) { Cnf_DataFree( pDat ); sat_solver_delete( pSat ); Vec_IntFree( vLits ); return NULL; } } Cnf_DataFree( pDat ); status = sat_solver_simplify( pSat ); if ( status == 0 ) { sat_solver_delete( pSat ); Vec_IntFree( vLits ); return NULL; } // iterate over POs vKeep = Vec_IntAlloc( Gia_ManPoNum(p) ); Gia_ManForEachPo( p, pObj, i ) { Vec_IntWriteEntry( vLits, i, Abc_LitNot(Vec_IntEntry(vLits,i)) ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 ); Vec_IntWriteEntry( vLits, i, Abc_LitNot(Vec_IntEntry(vLits,i)) ); if ( status == l_False ) Vec_IntWriteEntry( vLits, i, ConstLit ); // const1 SAT var is always true else { assert( status = l_True ); Vec_IntPush( vKeep, i ); } } sat_solver_delete( pSat ); Vec_IntFree( vLits ); if ( Vec_IntSize(vKeep) == Gia_ManPoNum(p) ) { Vec_IntFree( vKeep ); return Gia_ManDup(p); } pNew = Gia_ManDupCones( p, Vec_IntArray(vKeep), Vec_IntSize(vKeep), 0 ); Vec_IntFree( vKeep ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManOptimizeRing( Gia_Man_t * p ) { Ssc_Pars_t Pars, * pPars = &Pars; Gia_Man_t * pTemp, * pAux; int i; assert( p->nConstrs == 0 ); printf( "User AIG: " ); Gia_ManPrintStats( p, NULL ); pTemp = Gia_ManDropContained( p ); printf( "Drop AIG: " ); Gia_ManPrintStats( pTemp, NULL ); // return pTemp; if ( Gia_ManPoNum(pTemp) == 1 ) return pTemp; Ssc_ManSetDefaultParams( pPars ); pPars->fAppend = 1; pPars->fVerbose = 0; pTemp->nConstrs = Gia_ManPoNum(pTemp) - 1; for ( i = 0; i < Gia_ManPoNum(pTemp); i++ ) { // move i-th PO forward Gia_ManSwapPos( pTemp, i ); pTemp = Gia_ManDupDfs( pAux = pTemp ); Gia_ManStop( pAux ); // minimize this PO pTemp = Ssc_PerformSweepingConstr( pAux = pTemp, pPars ); Gia_ManStop( pAux ); pTemp = Gia_ManDupDfs( pAux = pTemp ); Gia_ManStop( pAux ); // move i-th PO back Gia_ManSwapPos( pTemp, i ); pTemp = Gia_ManDupDfs( pAux = pTemp ); Gia_ManStop( pAux ); // report results printf( "AIG%3d : ", i ); Gia_ManPrintStats( pTemp, NULL ); } pTemp->nConstrs = 0; return pTemp; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/000077500000000000000000000000001300674244400217755ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/module.make000066400000000000000000000010521300674244400241170ustar00rootroot00000000000000SRC += src/proof/ssw/sswAig.c \ src/proof/ssw/sswBmc.c \ src/proof/ssw/sswClass.c \ src/proof/ssw/sswCnf.c \ src/proof/ssw/sswConstr.c \ src/proof/ssw/sswCore.c \ src/proof/ssw/sswDyn.c \ src/proof/ssw/sswFilter.c \ src/proof/ssw/sswIslands.c \ src/proof/ssw/sswLcorr.c \ src/proof/ssw/sswMan.c \ src/proof/ssw/sswPart.c \ src/proof/ssw/sswPairs.c \ src/proof/ssw/sswRarity.c \ src/proof/ssw/sswSat.c \ src/proof/ssw/sswSemi.c \ src/proof/ssw/sswSim.c \ src/proof/ssw/sswSimSat.c \ src/proof/ssw/sswSweep.c \ src/proof/ssw/sswUnique.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/ssw.h000066400000000000000000000214411300674244400227640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ssw.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: ssw.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__ssw__ssw_h #define ABC__aig__ssw__ssw_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // choicing parameters typedef struct Ssw_Pars_t_ Ssw_Pars_t; struct Ssw_Pars_t_ { int nPartSize; // size of the partition int nOverSize; // size of the overlap between partitions int nFramesK; // the induction depth int nFramesAddSim; // the number of additional frames to simulate int fConstrs; // treat the last nConstrs POs as seq constraints int fMergeFull; // enables full merge when constraints are used int nMaxLevs; // the max number of levels of nodes to consider int nBTLimit; // conflict limit at a node int nBTLimitGlobal;// conflict limit for multiple runs int nMinDomSize; // min clock domain considered for optimization int nItersStop; // stop after the given number of iterations int fDumpSRInit; // dumps speculative reduction int nResimDelta; // the number of nodes to resimulate int nStepsMax; // (scorr only) the max number of induction steps int TimeLimit; // time out in seconds int fPolarFlip; // uses polarity adjustment int fLatchCorr; // perform register correspondence int fConstCorr; // perform constant correspondence int fOutputCorr; // perform 'PO correspondence' int fSemiFormal; // enable semiformal filtering // int fUniqueness; // enable uniqueness constraints int fDynamic; // enable dynamic addition of constraints int fLocalSim; // enable local simulation simulation int fPartSigCorr; // uses partial signal correspondence int nIsleDist; // extends islands by the given distance int fScorrGia; // new signal correspondence implementation int fUseCSat; // new SAT solver using when fScorrGia is selected int fVerbose; // verbose stats int fFlopVerbose; // verbose printout of redundant flops int fEquivDump; // enables dumping equivalences int fStopWhenGone; // stop when PO output is not a candidate constant // optimized latch correspondence int fLatchCorrOpt; // perform register correspondence (optimized) int nSatVarMax; // max number of SAT vars before recycling SAT solver (optimized latch corr only) int nRecycleCalls; // calls to perform before recycling SAT solver (optimized latch corr only) // optimized signal correspondence int nSatVarMax2; // max number of SAT vars before recycling SAT solver (optimized latch corr only) int nRecycleCalls2;// calls to perform before recycling SAT solver (optimized latch corr only) // internal parameters int nIters; // the number of iterations performed int nConflicts; // the total number of conflicts performed // callback void * pData; void * pFunc; }; typedef struct Ssw_RarPars_t_ Ssw_RarPars_t; struct Ssw_RarPars_t_ { int nFrames; int nWords; int nBinSize; int nRounds; int nRestart; int nRandSeed; int TimeOut; int TimeOutGap; int fSolveAll; int fSetLastState; int fVerbose; int fNotVerbose; int fSilent; int fDropSatOuts; int fMiter; int fUseCex; int fLatchOnly; int fUseFfGrouping; int nSolved; Abc_Cex_t * pCex; int(*pFuncOnFail)(int,Abc_Cex_t*); // called for a failed output in MO mode }; typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== sswBmc.c ==========================================================*/ extern int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame ); /*=== sswConstr.c ==========================================================*/ extern int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ); /*=== sswCore.c ==========================================================*/ extern void Ssw_ManSetDefaultParams( Ssw_Pars_t * p ); extern void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p ); extern Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); extern Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); /*=== sswIslands.c ==========================================================*/ extern int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ); extern int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars ); /*=== sswMiter.c ===================================================*/ /*=== sswPart.c ==========================================================*/ extern Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); /*=== sswPairs.c ===================================================*/ extern int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose ); extern int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ); extern int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars ); extern int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars ); /*=== sswRarity.c ===================================================*/ extern void Ssw_RarSetDefaultParams( Ssw_RarPars_t * p ); extern int Ssw_RarSignalFilter( Aig_Man_t * pAig, Ssw_RarPars_t * pPars ); extern int Ssw_RarSimulate( Aig_Man_t * pAig, Ssw_RarPars_t * pPars ); /*=== sswSim.c ===================================================*/ extern Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords ); extern Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ); extern void Ssw_SmlUnnormalize( Ssw_Sml_t * p ); extern void Ssw_SmlStop( Ssw_Sml_t * p ); extern int Ssw_SmlNumFrames( Ssw_Sml_t * p ); extern int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p ); extern unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj ); extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); extern void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit ); extern int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p ); extern Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswAig.c000066400000000000000000000210111300674244400233710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswAig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [AIG manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswAig.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the SAT manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig ) { Ssw_Frm_t * p; p = ABC_ALLOC( Ssw_Frm_t, 1 ); memset( p, 0, sizeof(Ssw_Frm_t) ); p->pAig = pAig; p->nObjs = Aig_ManObjNumMax( pAig ); p->nFrames = 0; p->pFrames = NULL; p->vAig2Frm = Vec_PtrAlloc( 0 ); Vec_PtrFill( p->vAig2Frm, 2 * p->nObjs, NULL ); return p; } /**Function************************************************************* Synopsis [Starts the SAT manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_FrmStop( Ssw_Frm_t * p ) { if ( p->pFrames ) Aig_ManStop( p->pFrames ); Vec_PtrFree( p->vAig2Frm ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Performs speculative reduction for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Ssw_FramesConstrainNode( Ssw_Man_t * p, Aig_Man_t * pFrames, Aig_Man_t * pAig, Aig_Obj_t * pObj, int iFrame, int fTwoPos ) { Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter; // skip nodes without representative pObjRepr = Aig_ObjRepr(pAig, pObj); if ( pObjRepr == NULL ) return; p->nConstrTotal++; assert( pObjRepr->Id < pObj->Id ); // get the new node pObjNew = Ssw_ObjFrame( p, pObj, iFrame ); // get the new node of the representative pObjReprNew = Ssw_ObjFrame( p, pObjRepr, iFrame ); // if this is the same node, no need to add constraints if ( pObj->fPhase == pObjRepr->fPhase ) { assert( pObjNew != Aig_Not(pObjReprNew) ); if ( pObjNew == pObjReprNew ) return; } else { assert( pObjNew != pObjReprNew ); if ( pObjNew == Aig_Not(pObjReprNew) ) return; } p->nConstrReduced++; // these are different nodes - perform speculative reduction pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); // set the new node Ssw_ObjSetFrame( p, pObj, iFrame, pObjNew2 ); // add the constraint if ( fTwoPos ) { Aig_ObjCreateCo( pFrames, pObjNew2 ); Aig_ObjCreateCo( pFrames, pObjNew ); } else { pMiter = Aig_Exor( pFrames, pObjNew, pObjNew2 ); Aig_ObjCreateCo( pFrames, Aig_NotCond(pMiter, Aig_ObjPhaseReal(pMiter)) ); } } /**Function************************************************************* Synopsis [Prepares the inductive case with speculative reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; int i, f, iLits; assert( p->pFrames == NULL ); assert( Aig_ManRegNum(p->pAig) > 0 ); assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) ); p->nConstrTotal = p->nConstrReduced = 0; // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames ); // create latches for the first frame Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(pFrames) ); // add timeframes iLits = 0; for ( f = 0; f < p->pPars->nFramesK; f++ ) { // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) { pObjNew = Aig_ObjCreateCi(pFrames); pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); } // set the constraints on the latch outputs Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 ); // add internal nodes of this frame Aig_ManForEachNode( p->pAig, pObj, i ) { pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 ); } // transfer to the primary outputs Aig_ManForEachCo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj,f) ); // transfer latch input to the latch outputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) Ssw_ObjSetFrame( p, pObjLo, f+1, Ssw_ObjFrame(p, pObjLi,f) ); } assert( p->vInits == NULL || Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); // add the POs for the latch outputs of the last frame Saig_ManForEachLo( p->pAig, pObj, i ) Aig_ObjCreateCo( pFrames, Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) ); // remove dangling nodes Aig_ManCleanup( pFrames ); // make sure the satisfying assignment is node assigned assert( pFrames->pData == NULL ); //Aig_ManShow( pFrames, 0, NULL ); return pFrames; } /**Function************************************************************* Synopsis [Prepares the inductive case with speculative reduction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjNew; int i; assert( p->pFrames == NULL ); assert( Aig_ManRegNum(p->pAig) > 0 ); assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) ); p->nConstrTotal = p->nConstrReduced = 0; // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames ); pFrames->pName = Abc_UtilStrsav( p->pAig->pName ); // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(pFrames) ); // create latches for the first frame Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(pFrames) ); // set the constraints on the latch outputs Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 ); // add internal nodes of this frame Aig_ManForEachNode( p->pAig, pObj, i ) { pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) ); Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 ); } // add the POs for the latch outputs of the last frame Saig_ManForEachLi( p->pAig, pObj, i ) Aig_ObjCreateCo( pFrames, Ssw_ObjChild0Fra(p, pObj,0) ); // remove dangling nodes Aig_ManCleanup( pFrames ); Aig_ManSetRegNum( pFrames, Aig_ManRegNum(p->pAig) ); // Abc_Print( 1, "SpecRed: Total constraints = %d. Reduced constraints = %d.\n", // p->nConstrTotal, p->nConstrReduced ); return pFrames; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswBmc.c000066400000000000000000000161261300674244400234050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswBmc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Bounded model checker using dynamic unrolling.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswBmc.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Incrementally unroll the timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Ssw_BmcUnroll_rec( Ssw_Frm_t * pFrm, Aig_Obj_t * pObj, int f ) { Aig_Obj_t * pRes, * pRes0, * pRes1; if ( (pRes = Ssw_ObjFrame_(pFrm, pObj, f)) ) return pRes; if ( Aig_ObjIsConst1(pObj) ) pRes = Aig_ManConst1( pFrm->pFrames ); else if ( Saig_ObjIsPi(pFrm->pAig, pObj) ) pRes = Aig_ObjCreateCi( pFrm->pFrames ); else if ( Aig_ObjIsCo(pObj) ) { Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f ); pRes = Ssw_ObjChild0Fra_( pFrm, pObj, f ); } else if ( Saig_ObjIsLo(pFrm->pAig, pObj) ) { if ( f == 0 ) pRes = Aig_ManConst0( pFrm->pFrames ); else pRes = Ssw_BmcUnroll_rec( pFrm, Saig_ObjLoToLi(pFrm->pAig, pObj), f-1 ); } else { assert( Aig_ObjIsNode(pObj) ); Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f ); Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin1(pObj), f ); pRes0 = Ssw_ObjChild0Fra_( pFrm, pObj, f ); pRes1 = Ssw_ObjChild1Fra_( pFrm, pObj, f ); pRes = Aig_And( pFrm->pFrames, pRes0, pRes1 ); } Ssw_ObjSetFrame_( pFrm, pObj, f, pRes ); return pRes; } /**Function************************************************************* Synopsis [Derives counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Ssw_BmcGetCounterExample( Ssw_Frm_t * pFrm, Ssw_Sat_t * pSat, int iPo, int iFrame ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj, * pObjFrames; int f, i, nShift; assert( Saig_ManRegNum(pFrm->pAig) > 0 ); // allocate the counter example pCex = Abc_CexAlloc( Saig_ManRegNum(pFrm->pAig), Saig_ManPiNum(pFrm->pAig), iFrame + 1 ); pCex->iPo = iPo; pCex->iFrame = iFrame; // create data-bits nShift = Saig_ManRegNum(pFrm->pAig); for ( f = 0; f <= iFrame; f++, nShift += Saig_ManPiNum(pFrm->pAig) ) Saig_ManForEachPi( pFrm->pAig, pObj, i ) { pObjFrames = Ssw_ObjFrame_(pFrm, pObj, f); if ( pObjFrames == NULL ) continue; if ( Ssw_CnfGetNodeValue( pSat, pObjFrames ) ) Abc_InfoSetBit( pCex->pData, nShift + i ); } return pCex; } /**Function************************************************************* Synopsis [Performs BMC for the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame ) { Ssw_Frm_t * pFrm; Ssw_Sat_t * pSat; Aig_Obj_t * pObj, * pObjFrame; int status, Lit, i, f, RetValue; abctime clkPart; // start managers assert( Saig_ManRegNum(pAig) > 0 ); Aig_ManSetCioIds( pAig ); pSat = Ssw_SatStart( 0 ); pFrm = Ssw_FrmStart( pAig ); pFrm->pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * 3 ); // report statistics if ( fVerbose ) { Abc_Print( 1, "AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); fflush( stdout ); } // perform dynamic unrolling RetValue = -1; for ( f = 0; f < nFramesMax; f++ ) { clkPart = Abc_Clock(); Saig_ManForEachPo( pAig, pObj, i ) { // unroll the circuit for this output Ssw_BmcUnroll_rec( pFrm, pObj, f ); pObjFrame = Ssw_ObjFrame_( pFrm, pObj, f ); Ssw_CnfNodeAddToSolver( pSat, Aig_Regular(pObjFrame) ); status = sat_solver_simplify(pSat->pSat); assert( status ); // solve Lit = toLitCond( Ssw_ObjSatNum(pSat,pObjFrame), Aig_IsComplement(pObjFrame) ); if ( fVerbose ) { Abc_Print( 1, "Solving output %2d of frame %3d ... \r", i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) ); } status = sat_solver_solve( pSat->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_False ) { /* Lit = lit_neg( Lit ); RetValue = sat_solver_addclause( pSat->pSat, &Lit, &Lit + 1 ); assert( RetValue ); if ( pSat->pSat->qtail != pSat->pSat->qhead ) { RetValue = sat_solver_simplify(pSat->pSat); assert( RetValue ); } */ RetValue = 1; continue; } else if ( status == l_True ) { pAig->pSeqModel = Ssw_BmcGetCounterExample( pFrm, pSat, i, f ); if ( piFrame ) *piFrame = f; RetValue = 0; break; } else { if ( piFrame ) *piFrame = f; RetValue = -1; break; } } if ( fVerbose ) { Abc_Print( 1, "Solved %2d outputs of frame %3d. ", Saig_ManPoNum(pAig), f ); Abc_Print( 1, "Conf =%8.0f. Var =%8d. AIG=%9d. ", (double)pSat->pSat->stats.conflicts, pSat->nSatVars, Aig_ManNodeNum(pFrm->pFrames) ); ABC_PRT( "T", Abc_Clock() - clkPart ); clkPart = Abc_Clock(); fflush( stdout ); } if ( RetValue != 1 ) break; } Ssw_SatStop( pSat ); Ssw_FrmStop( pFrm ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswClass.c000066400000000000000000001063731300674244400237550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswClass.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Representation of candidate equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswClass.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START /* The candidate equivalence classes are stored as a vector of pointers to the array of pointers to the nodes in each class. The first node of the class is its representative node. The representative has the smallest topological order among the class nodes. The nodes inside each class are ordered according to their topological order. The classes are ordered according to the topo order of their representatives. */ // internal representation of candidate equivalence classes struct Ssw_Cla_t_ { // class information Aig_Man_t * pAig; // original AIG manager Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node int * pClassSizes; // sizes of each equivalence class int fConstCorr; // statistics int nClasses; // the total number of non-const classes int nCands1; // the total number of const candidates int nLits; // the number of literals in all classes // memory Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used // temporary data Vec_Ptr_t * vClassOld; // old equivalence class after splitting Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting Vec_Ptr_t * vRefined; // the nodes refined since the last iteration // procedures used for class refinement void * pManData; unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement }; //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline Aig_Obj_t * Ssw_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } static inline void Ssw_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } // iterator through the equivalence classes #define Ssw_ManForEachClass( p, ppClass, i ) \ for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \ if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else // iterator through the nodes in one class #define Ssw_ClassForEachNode( p, pRepr, pNode, i ) \ for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \ if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Ssw_ObjAddClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize ) { assert( p->pId2Class[pRepr->Id] == NULL ); assert( pClass[0] == pRepr ); p->pId2Class[pRepr->Id] = pClass; assert( p->pClassSizes[pRepr->Id] == 0 ); assert( nSize > 1 ); p->pClassSizes[pRepr->Id] = nSize; p->nClasses++; p->nLits += nSize - 1; } /**Function************************************************************* Synopsis [Removes one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t ** Ssw_ObjRemoveClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr ) { Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id]; int nSize; assert( pClass != NULL ); p->pId2Class[pRepr->Id] = NULL; nSize = p->pClassSizes[pRepr->Id]; assert( nSize > 1 ); p->nClasses--; p->nLits -= nSize - 1; p->pClassSizes[pRepr->Id] = 0; return pClass; } /**Function************************************************************* Synopsis [Starts representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig ) { Ssw_Cla_t * p; p = ABC_ALLOC( Ssw_Cla_t, 1 ); memset( p, 0, sizeof(Ssw_Cla_t) ); p->pAig = pAig; p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) ); p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); p->vClassOld = Vec_PtrAlloc( 100 ); p->vClassNew = Vec_PtrAlloc( 100 ); p->vRefined = Vec_PtrAlloc( 1000 ); if ( pAig->pReprs == NULL ) Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); return p; } /**Function************************************************************* Synopsis [Starts representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData, unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement { p->pManData = pManData; p->pFuncNodeHash = pFuncNodeHash; p->pFuncNodeIsConst = pFuncNodeIsConst; p->pFuncNodesAreEqual = pFuncNodesAreEqual; } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ClassesStop( Ssw_Cla_t * p ) { if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); Vec_PtrFree( p->vRefined ); ABC_FREE( p->pId2Class ); ABC_FREE( p->pClassSizes ); ABC_FREE( p->pMemClasses ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p ) { return p->pAig; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p ) { return p->vRefined; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ClassesClearRefined( Ssw_Cla_t * p ) { Vec_PtrClear( p->vRefined ); } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesCand1Num( Ssw_Cla_t * p ) { return p->nCands1; } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesClassNum( Ssw_Cla_t * p ) { return p->nClasses; } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesLitNum( Ssw_Cla_t * p ) { return p->nLits; } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ) { if ( p->pId2Class[pRepr->Id] == NULL ) return NULL; assert( p->pId2Class[pRepr->Id] != NULL ); assert( p->pClassSizes[pRepr->Id] > 1 ); *pnSize = p->pClassSizes[pRepr->Id]; return p->pId2Class[pRepr->Id]; } /**Function************************************************************* Synopsis [Stop representation of equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass ) { int i; Vec_PtrClear( vClass ); if ( p->pId2Class[pRepr->Id] == NULL ) return; assert( p->pClassSizes[pRepr->Id] > 1 ); for ( i = 1; i < p->pClassSizes[pRepr->Id]; i++ ) Vec_PtrPush( vClass, p->pId2Class[pRepr->Id][i] ); } /**Function************************************************************* Synopsis [Checks candidate equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ClassesCheck( Ssw_Cla_t * p ) { Aig_Obj_t * pObj, * pPrev, ** ppClass; int i, k, nLits, nClasses, nCands1; nClasses = nLits = 0; Ssw_ManForEachClass( p, ppClass, k ) { pPrev = NULL; assert( p->pClassSizes[ppClass[0]->Id] >= 2 ); Ssw_ClassForEachNode( p, ppClass[0], pObj, i ) { if ( i == 0 ) assert( Aig_ObjRepr(p->pAig, pObj) == NULL ); else { assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] ); assert( pPrev->Id < pObj->Id ); nLits++; } pPrev = pObj; } nClasses++; } nCands1 = 0; Aig_ManForEachObj( p->pAig, pObj, i ) nCands1 += Ssw_ObjIsConst1Cand( p->pAig, pObj ); assert( p->nLits == nLits ); assert( p->nCands1 == nCands1 ); assert( p->nClasses == nClasses ); } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ClassesPrintOne( Ssw_Cla_t * p, Aig_Obj_t * pRepr ) { Aig_Obj_t * pObj; int i; Abc_Print( 1, "{ " ); Ssw_ClassForEachNode( p, pRepr, pObj, i ) Abc_Print( 1, "%d(%d,%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) ); Abc_Print( 1, "}\n" ); } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose ) { Aig_Obj_t ** ppClass; Aig_Obj_t * pObj; int i; Abc_Print( 1, "Equiv classes: Const1 = %5d. Class = %5d. Lit = %5d.\n", p->nCands1, p->nClasses, p->nCands1+p->nLits ); if ( !fVeryVerbose ) return; Abc_Print( 1, "Constants { " ); Aig_ManForEachObj( p->pAig, pObj, i ) if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) Abc_Print( 1, "%d(%d,%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) ); Abc_Print( 1, "}\n" ); Ssw_ManForEachClass( p, ppClass, i ) { Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] ); Ssw_ClassesPrintOne( p, ppClass[0] ); } Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pRepr, * pTemp; assert( p->pClassSizes[pObj->Id] == 0 ); assert( p->pId2Class[pObj->Id] == NULL ); pRepr = Aig_ObjRepr( p->pAig, pObj ); assert( pRepr != NULL ); // Vec_PtrPush( p->vRefined, pObj ); if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) { assert( p->pClassSizes[pRepr->Id] == 0 ); assert( p->pId2Class[pRepr->Id] == NULL ); Aig_ObjSetRepr( p->pAig, pObj, NULL ); p->nCands1--; return; } // Vec_PtrPush( p->vRefined, pRepr ); Aig_ObjSetRepr( p->pAig, pObj, NULL ); assert( p->pId2Class[pRepr->Id][0] == pRepr ); assert( p->pClassSizes[pRepr->Id] >= 2 ); if ( p->pClassSizes[pRepr->Id] == 2 ) { p->pId2Class[pRepr->Id] = NULL; p->nClasses--; p->pClassSizes[pRepr->Id] = 0; p->nLits--; } else { int i, k = 0; // remove the entry from the class Ssw_ClassForEachNode( p, pRepr, pTemp, i ) if ( pTemp != pObj ) p->pId2Class[pRepr->Id][k++] = pTemp; assert( k + 1 == p->pClassSizes[pRepr->Id] ); // reduce the class p->pClassSizes[pRepr->Id]--; p->nLits--; } } /**Function************************************************************* Synopsis [Takes the set of const1 cands and rehashes them using sim info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr ) { // Aig_Man_t * pAig = p->pAig; Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew; Aig_Obj_t * pObj, * pTemp, * pRepr; int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2; // allocate the hash table hashing simulation info into nodes nTableSize = Abc_PrimeCudd( Vec_PtrSize(vCands)/2 ); ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); // sort through the candidates nEntries = 0; p->nCands1 = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i ) { assert( p->pClassSizes[pObj->Id] == 0 ); Aig_ObjSetRepr( p->pAig, pObj, NULL ); // check if the node belongs to the class of constant 1 if ( p->pFuncNodeIsConst( p->pManData, pObj ) ) { Ssw_ObjSetConst1Cand( p->pAig, pObj ); p->nCands1++; continue; } if ( fConstCorr ) continue; // hash the node by its simulation info iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize; // add the node to the class if ( ppTable[iEntry] == NULL ) { ppTable[iEntry] = pObj; } else { // set the representative of this node pRepr = ppTable[iEntry]; Aig_ObjSetRepr( p->pAig, pObj, pRepr ); // add node to the table if ( Ssw_ObjNext( ppNexts, pRepr ) == NULL ) { // this will be the second entry p->pClassSizes[pRepr->Id]++; nEntries++; } // add the entry to the list Ssw_ObjSetNext( ppNexts, pObj, Ssw_ObjNext( ppNexts, pRepr ) ); Ssw_ObjSetNext( ppNexts, pRepr, pObj ); p->pClassSizes[pRepr->Id]++; nEntries++; } } // copy the entries into storage in the topological order nEntries2 = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i ) { nNodes = p->pClassSizes[pObj->Id]; // skip the nodes that are not representatives of non-trivial classes if ( nNodes == 0 ) continue; assert( nNodes > 1 ); // add the nodes to the class in the topological order ppClassNew = p->pMemClassesFree + nEntries2; ppClassNew[0] = pObj; for ( pTemp = Ssw_ObjNext(ppNexts, pObj), k = 1; pTemp; pTemp = Ssw_ObjNext(ppNexts, pTemp), k++ ) { ppClassNew[nNodes-k] = pTemp; } // add the class of nodes p->pClassSizes[pObj->Id] = 0; Ssw_ObjAddClass( p, pObj, ppClassNew, nNodes ); // increment the number of entries nEntries2 += nNodes; } p->pMemClassesFree += nEntries2; assert( nEntries == nEntries2 ); ABC_FREE( ppTable ); ABC_FREE( ppNexts ); // now it is time to refine the classes return Ssw_ClassesRefine( p, 1 ); } /**Function************************************************************* Synopsis [Creates initial simulation classes.] Description [Assumes that simulation info is assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose ) { // int nFrames = 4; // int nWords = 1; // int nIters = 16; // int nFrames = 32; // int nWords = 4; // int nIters = 0; int nFrames = Abc_MaxInt( nFramesK, 4 ); int nWords = 2; int nIters = 16; Ssw_Cla_t * p; Ssw_Sml_t * pSml; Vec_Ptr_t * vCands; Aig_Obj_t * pObj; int i, k, RetValue; abctime clk; // start the classes p = Ssw_ClassesStart( pAig ); p->fConstCorr = fConstCorr; // perform sequential simulation clk = Abc_Clock(); pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); if ( fVerbose ) { Abc_Print( 1, "Allocated %.2f MB to store simulation information.\n", 1.0*(sizeof(unsigned) * Aig_ManObjNumMax(pAig) * nFrames * nWords)/(1<<20) ); Abc_Print( 1, "Initial simulation of %d frames with %d words. ", nFrames, nWords ); ABC_PRT( "Time", Abc_Clock() - clk ); } // set comparison procedures clk = Abc_Clock(); Ssw_ClassesSetData( p, pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); // collect nodes to be considered as candidates vCands = Vec_PtrAlloc( 1000 ); Aig_ManForEachObj( p->pAig, pObj, i ) { if ( fLatchCorr ) { if ( !Saig_ObjIsLo(p->pAig, pObj) ) continue; } else { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; // skip the node with more that the given number of levels if ( nMaxLevs && (int)pObj->Level > nMaxLevs ) continue; } Vec_PtrPush( vCands, pObj ); } // this change will consider all PO drivers if ( fOutputCorr ) { Vec_PtrClear( vCands ); Aig_ManForEachObj( p->pAig, pObj, i ) pObj->fMarkB = 0; Saig_ManForEachPo( p->pAig, pObj, i ) if ( Aig_ObjIsCand(Aig_ObjFanin0(pObj)) ) Aig_ObjFanin0(pObj)->fMarkB = 1; Aig_ManForEachObj( p->pAig, pObj, i ) if ( pObj->fMarkB ) Vec_PtrPush( vCands, pObj ); Aig_ManForEachObj( p->pAig, pObj, i ) pObj->fMarkB = 0; } // allocate room for classes p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_PtrSize(vCands) ); p->pMemClassesFree = p->pMemClasses; // now it is time to refine the classes Ssw_ClassesPrepareRehash( p, vCands, fConstCorr ); if ( fVerbose ) { Abc_Print( 1, "Collecting candidate equivalence classes. " ); ABC_PRT( "Time", Abc_Clock() - clk ); } clk = Abc_Clock(); // perform iterative refinement using simulation for ( i = 1; i < nIters; i++ ) { // collect const1 candidates Vec_PtrClear( vCands ); Aig_ManForEachObj( p->pAig, pObj, k ) if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) Vec_PtrPush( vCands, pObj ); assert( Vec_PtrSize(vCands) == p->nCands1 ); // perform new round of simulation Ssw_SmlResimulateSeq( pSml ); // check equivalence classes RetValue = Ssw_ClassesPrepareRehash( p, vCands, fConstCorr ); if ( RetValue == 0 ) break; } Ssw_SmlStop( pSml ); Vec_PtrFree( vCands ); if ( fVerbose ) { Abc_Print( 1, "Simulation of %d frames with %d words (%2d rounds). ", nFrames, nWords, i-1 ); ABC_PRT( "Time", Abc_Clock() - clk ); } Ssw_ClassesCheck( p ); // Ssw_ClassesPrint( p, 0 ); return p; } /**Function************************************************************* Synopsis [Creates initial simulation classes.] Description [Assumes that simulation info is assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs ) { Ssw_Cla_t * p; Aig_Obj_t * pObj; int i; // start the classes p = Ssw_ClassesStart( pAig ); // go through the nodes p->nCands1 = 0; Aig_ManForEachObj( pAig, pObj, i ) { if ( fLatchCorr ) { if ( !Saig_ObjIsLo(pAig, pObj) ) continue; } else { if ( !Aig_ObjIsNode(pObj) && !Saig_ObjIsLo(pAig, pObj) ) continue; // skip the node with more that the given number of levels if ( nMaxLevs && (int)pObj->Level > nMaxLevs ) continue; } Ssw_ObjSetConst1Cand( pAig, pObj ); p->nCands1++; } // allocate room for classes p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 ); // Ssw_ClassesPrint( p, 0 ); return p; } /**Function************************************************************* Synopsis [Creates initial simulation classes.] Description [Assumes that simulation info is assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig ) { Ssw_Cla_t * p; Aig_Obj_t * pObj, * pRepr; int * pClassSizes, nEntries, i; // start the classes p = Ssw_ClassesStart( pAig ); // allocate memory for classes p->pMemClasses = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); // count classes p->nCands1 = 0; Aig_ManForEachObj( pAig, pObj, i ) { if ( Ssw_ObjIsConst1Cand(pAig, pObj) ) { p->nCands1++; continue; } if ( (pRepr = Aig_ObjRepr(pAig, pObj)) ) { if ( p->pClassSizes[pRepr->Id]++ == 0 ) p->pClassSizes[pRepr->Id]++; } } // add nodes nEntries = 0; p->nClasses = 0; pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); Aig_ManForEachObj( pAig, pObj, i ) { if ( p->pClassSizes[i] ) { p->pId2Class[i] = p->pMemClasses + nEntries; nEntries += p->pClassSizes[i]; p->pId2Class[i][pClassSizes[i]++] = pObj; p->nClasses++; continue; } if ( Ssw_ObjIsConst1Cand(pAig, pObj) ) continue; if ( (pRepr = Aig_ObjRepr(pAig, pObj)) ) p->pId2Class[pRepr->Id][pClassSizes[pRepr->Id]++] = pObj; } p->pMemClassesFree = p->pMemClasses + nEntries; p->nLits = nEntries - p->nClasses; assert( memcmp(pClassSizes, p->pClassSizes, sizeof(int)*Aig_ManObjNumMax(pAig)) == 0 ); ABC_FREE( pClassSizes ); // Abc_Print( 1, "After converting:\n" ); // Ssw_ClassesPrint( p, 0 ); return p; } /**Function************************************************************* Synopsis [Creates initial simulation classes.] Description [Assumes that simulation info is assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig ) { Ssw_Cla_t * p; Aig_Obj_t * pObj; int i; // start the classes p = Ssw_ClassesStart( pAig ); // go through the nodes p->nCands1 = 0; Saig_ManForEachPo( pAig, pObj, i ) { Ssw_ObjSetConst1Cand( pAig, Aig_ObjFanin0(pObj) ); p->nCands1++; } // allocate room for classes p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 ); // Ssw_ClassesPrint( p, 0 ); return p; } /**Function************************************************************* Synopsis [Creates classes from the temporary representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses ) { Ssw_Cla_t * p; Aig_Obj_t ** ppClassNew; Aig_Obj_t * pObj, * pRepr, * pPrev; int i, k, nTotalObjs, nEntries, Entry; // start the classes p = Ssw_ClassesStart( pAig ); // count the number of entries in the classes nTotalObjs = 0; for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) nTotalObjs += pvClasses[i] ? Vec_IntSize(pvClasses[i]) : 0; // allocate memory for classes p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nTotalObjs ); // create constant-1 class if ( pvClasses[0] ) Vec_IntForEachEntry( pvClasses[0], Entry, i ) { assert( (i == 0) == (Entry == 0) ); if ( i == 0 ) continue; pObj = Aig_ManObj( pAig, Entry ); Ssw_ObjSetConst1Cand( pAig, pObj ); p->nCands1++; } // create classes nEntries = 0; for ( i = 1; i < Aig_ManObjNumMax(pAig); i++ ) { if ( pvClasses[i] == NULL ) continue; // get room for storing the class ppClassNew = p->pMemClasses + nEntries; nEntries += Vec_IntSize( pvClasses[i] ); // store the nodes of the class pPrev = pRepr = Aig_ManObj( pAig, Vec_IntEntry(pvClasses[i],0) ); ppClassNew[0] = pRepr; Vec_IntForEachEntryStart( pvClasses[i], Entry, k, 1 ) { pObj = Aig_ManObj( pAig, Entry ); assert( pPrev->Id < pObj->Id ); pPrev = pObj; ppClassNew[k] = pObj; Aig_ObjSetRepr( pAig, pObj, pRepr ); } // create new class Ssw_ObjAddClass( p, pRepr, ppClassNew, Vec_IntSize(pvClasses[i]) ); } // prepare room for new classes p->pMemClassesFree = p->pMemClasses + nEntries; Ssw_ClassesCheck( p ); // Ssw_ClassesPrint( p, 0 ); return p; } /**Function************************************************************* Synopsis [Creates classes from the temporary representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs ) { Ssw_Cla_t * p; Aig_Obj_t ** ppClassNew; Aig_Obj_t * pObj, * pRepr; int i; // start the classes p = Ssw_ClassesStart( pMiter ); // allocate memory for classes p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_IntSize(vPairs) ); // create classes for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) { pRepr = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i) ); pObj = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i+1) ); assert( Aig_ObjId(pRepr) < Aig_ObjId(pObj) ); Aig_ObjSetRepr( pMiter, pObj, pRepr ); // get room for storing the class ppClassNew = p->pMemClasses + i; ppClassNew[0] = pRepr; ppClassNew[1] = pObj; // create new class Ssw_ObjAddClass( p, pRepr, ppClassNew, 2 ); } // prepare room for new classes p->pMemClassesFree = NULL; Ssw_ClassesCheck( p ); // Ssw_ClassesPrint( p, 0 ); return p; } /**Function************************************************************* Synopsis [Iteratively refines the classes after simulation.] Description [Returns the number of refinements performed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive ) { Aig_Obj_t ** pClassOld, ** pClassNew; Aig_Obj_t * pObj, * pReprNew; int i; // split the class Vec_PtrClear( p->vClassOld ); Vec_PtrClear( p->vClassNew ); Ssw_ClassForEachNode( p, pReprOld, pObj, i ) if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) ) Vec_PtrPush( p->vClassOld, pObj ); else Vec_PtrPush( p->vClassNew, pObj ); // check if splitting happened if ( Vec_PtrSize(p->vClassNew) == 0 ) return 0; // remember that this class is refined // Ssw_ClassForEachNode( p, pReprOld, pObj, i ) // Vec_PtrPush( p->vRefined, pObj ); // get the new representative pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); assert( Vec_PtrSize(p->vClassOld) > 0 ); assert( Vec_PtrSize(p->vClassNew) > 0 ); // create old class pClassOld = Ssw_ObjRemoveClass( p, pReprOld ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i ) { pClassOld[i] = pObj; Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL ); } // create new class pClassNew = pClassOld + i; Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) { pClassNew[i] = pObj; Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); } // put classes back if ( Vec_PtrSize(p->vClassOld) > 1 ) Ssw_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) ); if ( Vec_PtrSize(p->vClassNew) > 1 ) Ssw_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) ); // check if the class should be recursively refined if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 ) return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); return 1; } /**Function************************************************************* Synopsis [Refines the classes after simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive ) { Aig_Obj_t ** ppClass; int i, nRefis = 0; Ssw_ManForEachClass( p, ppClass, i ) nRefis += Ssw_ClassesRefineOneClass( p, ppClass[0], fRecursive ); return nRefis; } /**Function************************************************************* Synopsis [Refines the classes after simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive ) { Aig_Obj_t * pObj; int i, nRefis = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vReprs, pObj, i ) nRefis += Ssw_ClassesRefineOneClass( p, pObj, fRecursive ); return nRefis; } /**Function************************************************************* Synopsis [Refine the group of constant 1 nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ) { Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; int i; if ( Vec_PtrSize(vRoots) == 0 ) return 0; // collect the nodes to be refined Vec_PtrClear( p->vClassNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) Vec_PtrPush( p->vClassNew, pObj ); // check if there is a new class if ( Vec_PtrSize(p->vClassNew) == 0 ) return 0; p->nCands1 -= Vec_PtrSize(p->vClassNew); pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); if ( Vec_PtrSize(p->vClassNew) == 1 ) return 1; // create a new class composed of these nodes ppClassNew = p->pMemClassesFree; p->pMemClassesFree += Vec_PtrSize(p->vClassNew); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) { ppClassNew[i] = pObj; Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); } Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); // refine them recursively if ( fRecursive ) return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); return 1; } /**Function************************************************************* Synopsis [Refine the group of constant 1 nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive ) { Aig_Obj_t * pObj, * pReprNew, ** ppClassNew; int i; // collect the nodes to be refined Vec_PtrClear( p->vClassNew ); for ( i = 0; i < Vec_PtrSize(p->pAig->vObjs); i++ ) if ( p->pAig->pReprs[i] == Aig_ManConst1(p->pAig) ) { pObj = Aig_ManObj( p->pAig, i ); if ( !p->pFuncNodeIsConst( p->pManData, pObj ) ) { Vec_PtrPush( p->vClassNew, pObj ); // Vec_PtrPush( p->vRefined, pObj ); } } // check if there is a new class if ( Vec_PtrSize(p->vClassNew) == 0 ) return 0; if ( p->fConstCorr ) { Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) Aig_ObjSetRepr( p->pAig, pObj, NULL ); return 1; } p->nCands1 -= Vec_PtrSize(p->vClassNew); pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 ); Aig_ObjSetRepr( p->pAig, pReprNew, NULL ); if ( Vec_PtrSize(p->vClassNew) == 1 ) return 1; // create a new class composed of these nodes ppClassNew = p->pMemClassesFree; p->pMemClassesFree += Vec_PtrSize(p->vClassNew); Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i ) { ppClassNew[i] = pObj; Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL ); } Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) ); // refine them recursively if ( fRecursive ) return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswCnf.c000066400000000000000000000325251300674244400234130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswCnf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Computation of CNF.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswCnf.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the SAT manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Sat_t * Ssw_SatStart( int fPolarFlip ) { Ssw_Sat_t * p; int Lit; p = ABC_ALLOC( Ssw_Sat_t, 1 ); memset( p, 0, sizeof(Ssw_Sat_t) ); p->pAig = NULL; p->fPolarFlip = fPolarFlip; p->vSatVars = Vec_IntStart( 10000 ); p->vFanins = Vec_PtrAlloc( 100 ); p->vUsedPis = Vec_PtrAlloc( 100 ); p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, 1000 ); // var 0 is not used // var 1 is reserved for const1 node - add the clause p->nSatVars = 1; Lit = toLit( p->nSatVars ); if ( fPolarFlip ) Lit = lit_neg( Lit ); sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); // Ssw_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ ); Vec_IntWriteEntry( p->vSatVars, 0, p->nSatVars++ ); return p; } /**Function************************************************************* Synopsis [Stop the SAT manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SatStop( Ssw_Sat_t * p ) { // Abc_Print( 1, "Recycling SAT solver with %d vars and %d restarts.\n", // p->pSat->size, p->pSat->stats.starts ); if ( p->pSat ) sat_solver_delete( p->pSat ); Vec_IntFree( p->vSatVars ); Vec_PtrFree( p->vFanins ); Vec_PtrFree( p->vUsedPis ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_AddClausesMux( Ssw_Sat_t * p, Aig_Obj_t * pNode ) { Aig_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; assert( !Aig_IsComplement( pNode ) ); assert( Aig_ObjIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the variable numbers VarF = Ssw_ObjSatNum(p,pNode); VarI = Ssw_ObjSatNum(p,pNodeI); VarT = Ssw_ObjSatNum(p,Aig_Regular(pNodeT)); VarE = Ssw_ObjSatNum(p,Aig_Regular(pNodeE)); // get the complementation flags fCompT = Aig_IsComplement(pNodeT); fCompE = Aig_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); if ( p->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->fPolarFlip ) { if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } 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); if ( p->fPolarFlip ) { if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] ); if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_AddClausesSuper( Ssw_Sat_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper ) { Aig_Obj_t * pFanin; int * pLits, nLits, RetValue, i; assert( !Aig_IsComplement(pNode) ); assert( Aig_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( Aig_Obj_t *, vSuper, pFanin, i ) { pLits[0] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); pLits[1] = toLitCond(Ssw_ObjSatNum(p,pNode), 1); if ( p->fPolarFlip ) { if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); } // add A & B => C or !A + !B + C Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) { pLits[i] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); if ( p->fPolarFlip ) { if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] ); } } pLits[nLits-1] = toLitCond(Ssw_ObjSatNum(p,pNode), 0); if ( p->fPolarFlip ) { if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] ); } RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); assert( RetValue ); ABC_FREE( pLits ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) { // if the new node is complemented or a PI, another gate begins if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || (!fFirst && Aig_ObjRefs(pObj) > 1) || (fUseMuxes && Aig_ObjIsMuxType(pObj)) ) { Vec_PtrPushUnique( vSuper, pObj ); return; } // pObj->fMarkA = 1; // go through the branches Ssw_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); Ssw_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) { assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCi(pObj) ); Vec_PtrClear( vSuper ); Ssw_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ObjAddToFrontier( Ssw_Sat_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) { assert( !Aig_IsComplement(pObj) ); if ( Ssw_ObjSatNum(p,pObj) ) return; assert( Ssw_ObjSatNum(p,pObj) == 0 ); if ( Aig_ObjIsConst1(pObj) ) return; // pObj->fMarkA = 1; // save PIs (used by register correspondence) if ( Aig_ObjIsCi(pObj) ) Vec_PtrPush( p->vUsedPis, pObj ); Ssw_ObjSetSatNum( p, pObj, p->nSatVars++ ); sat_solver_setnvars( p->pSat, 100 * (1 + p->nSatVars / 100) ); if ( Aig_ObjIsNode(pObj) ) Vec_PtrPush( vFrontier, pObj ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj ) { Vec_Ptr_t * vFrontier; Aig_Obj_t * pNode, * pFanin; int i, k, fUseMuxes = 1; // quit if CNF is ready if ( Ssw_ObjSatNum(p,pObj) ) return; // start the frontier vFrontier = Vec_PtrAlloc( 100 ); Ssw_ObjAddToFrontier( p, pObj, vFrontier ); // explore nodes in the frontier Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i ) { // create the supergate assert( Ssw_ObjSatNum(p,pNode) ); if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) { Vec_PtrClear( p->vFanins ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); Ssw_AddClausesMux( p, pNode ); } else { Ssw_CollectSuper( pNode, fUseMuxes, p->vFanins ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k ) Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); Ssw_AddClausesSuper( p, pNode, p->vFanins ); } assert( Vec_PtrSize(p->vFanins) > 1 ); } Vec_PtrFree( vFrontier ); } /**Function************************************************************* Synopsis [Copy pattern from the solver into the internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObj ) { int Value0, Value1, nVarNum; assert( !Aig_IsComplement(pObj) ); nVarNum = Ssw_ObjSatNum( p, pObj ); if ( nVarNum > 0 ) return sat_solver_var_value( p->pSat, nVarNum ); // if ( pObj->fMarkA == 1 ) // return 0; if ( Aig_ObjIsCi(pObj) ) return 0; assert( Aig_ObjIsNode(pObj) ); Value0 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin0(pObj) ); Value0 ^= Aig_ObjFaninC0(pObj); Value1 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin1(pObj) ); Value1 ^= Aig_ObjFaninC1(pObj); return Value0 & Value1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswConstr.c000066400000000000000000000572361300674244400241630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswConstr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [One round of SAT sweeping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" #include "sat/cnf/cnf.h" #include "misc/bar/bar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Constructs initialized timeframes with constraints as POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_FramesWithConstraints( Aig_Man_t * p, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; // assert( Saig_ManConstrNum(p) > 0 ); assert( Aig_ManRegNum(p) > 0 ); assert( Aig_ManRegNum(p) < Aig_ManCiNum(p) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(p) * nFrames ); // create latches for the first frame Saig_ManForEachLo( p, pObj, i ) Aig_ObjSetCopy( pObj, Aig_ManConst0(pFrames) ); // add timeframes for ( f = 0; f < nFrames; f++ ) { // map constants and PIs Aig_ObjSetCopy( Aig_ManConst1(p), Aig_ManConst1(pFrames) ); Saig_ManForEachPi( p, pObj, i ) Aig_ObjSetCopy( pObj, Aig_ObjCreateCi(pFrames) ); // add internal nodes of this frame Aig_ManForEachNode( p, pObj, i ) Aig_ObjSetCopy( pObj, Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ) ); // transfer to the primary output Aig_ManForEachCo( p, pObj, i ) Aig_ObjSetCopy( pObj, Aig_ObjChild0Copy(pObj) ); // create constraint outputs Saig_ManForEachPo( p, pObj, i ) { if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) continue; Aig_ObjCreateCo( pFrames, Aig_Not( Aig_ObjCopy(pObj) ) ); } // transfer latch inputs to the latch outputs Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) Aig_ObjSetCopy( pObjLo, Aig_ObjCopy(pObjLi) ); } // remove dangling nodes Aig_ManCleanup( pFrames ); return pFrames; } /**Function************************************************************* Synopsis [Finds one satisfiable assignment of the timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ) { Aig_Man_t * pFrames; sat_solver * pSat; Cnf_Dat_t * pCnf; Aig_Obj_t * pObj; int i, RetValue; if ( pvInits ) *pvInits = NULL; // assert( p->nConstrs > 0 ); // derive the timeframes pFrames = Ssw_FramesWithConstraints( p, nFrames ); // create CNF pCnf = Cnf_Derive( pFrames, 0 ); // create SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat == NULL ) { Cnf_DataFree( pCnf ); Aig_ManStop( pFrames ); return 1; } // solve RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_True && pvInits ) { *pvInits = Vec_IntAlloc( 1000 ); Aig_ManForEachCi( pFrames, pObj, i ) Vec_IntPush( *pvInits, sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ); // Aig_ManForEachCi( pFrames, pObj, i ) // Abc_Print( 1, "%d", Vec_IntEntry(*pvInits, i) ); // Abc_Print( 1, "\n" ); } sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Aig_ManStop( pFrames ); if ( RetValue == l_False ) return 1; if ( RetValue == l_True ) return 0; return -1; } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSetConstrPhases_( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits ) { Vec_Int_t * vLits; sat_solver * pSat; Cnf_Dat_t * pCnf; Aig_Obj_t * pObj; int i, f, iVar, RetValue, nRegs; if ( pvInits ) *pvInits = NULL; assert( p->nConstrs > 0 ); // create CNF nRegs = p->nRegs; p->nRegs = 0; pCnf = Cnf_Derive( p, Aig_ManCoNum(p) ); p->nRegs = nRegs; // create SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 0 ); assert( pSat->size == nFrames * pCnf->nVars ); // collect constraint literals vLits = Vec_IntAlloc( 100 ); Saig_ManForEachLo( p, pObj, i ) { assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 ); Vec_IntPush( vLits, toLitCond(pCnf->pVarNums[Aig_ObjId(pObj)], 1) ); } for ( f = 0; f < nFrames; f++ ) { Saig_ManForEachPo( p, pObj, i ) { if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) continue; assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 ); iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f; Vec_IntPush( vLits, toLitCond(iVar, 1) ); } } RetValue = sat_solver_solve( pSat, (int *)Vec_IntArray(vLits), (int *)Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_True && pvInits ) { *pvInits = Vec_IntAlloc( 1000 ); for ( f = 0; f < nFrames; f++ ) { Saig_ManForEachPi( p, pObj, i ) { iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f; Vec_IntPush( *pvInits, sat_solver_var_value(pSat, iVar) ); } } } sat_solver_delete( pSat ); Vec_IntFree( vLits ); Cnf_DataFree( pCnf ); if ( RetValue == l_False ) return 1; if ( RetValue == l_True ) return 0; return -1; } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManPrintPolarity( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) Abc_Print( 1, "%d", pObj->fPhase ); Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManRefineByConstrSim( Ssw_Man_t * p ) { Aig_Obj_t * pObj, * pObjLi; int f, i, iLits, RetValue1, RetValue2; int nFrames = Vec_IntSize(p->vInits) / Saig_ManPiNum(p->pAig); assert( Vec_IntSize(p->vInits) % Saig_ManPiNum(p->pAig) == 0 ); // assign register outputs Saig_ManForEachLi( p->pAig, pObj, i ) pObj->fMarkB = 0; // simulate the timeframes iLits = 0; for ( f = 0; f < nFrames; f++ ) { // set the PI simulation information Aig_ManConst1(p->pAig)->fMarkB = 1; Saig_ManForEachPi( p->pAig, pObj, i ) pObj->fMarkB = Vec_IntEntry( p->vInits, iLits++ ); Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) pObj->fMarkB = pObjLi->fMarkB; // simulate internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); // assign the COs Aig_ManForEachCo( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); // check the outputs Saig_ManForEachPo( p->pAig, pObj, i ) { if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) { if ( pObj->fMarkB && Saig_ManConstrNum(p->pAig) ) Abc_Print( 1, "output %d failed in frame %d.\n", i, f ); } else { if ( pObj->fMarkB && Saig_ManConstrNum(p->pAig) ) Abc_Print( 1, "constraint %d failed in frame %d.\n", i, f ); } } // transfer if ( f == 0 ) { // copy markB into phase Aig_ManForEachObj( p->pAig, pObj, i ) pObj->fPhase = pObj->fMarkB; } else { // refine classes RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); } } assert( iLits == Vec_IntSize(p->vInits) ); } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepNodeConstr( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc ) { Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; int RetValue; // get representative of this class pObjRepr = Aig_ObjRepr( p->pAig, pObj ); if ( pObjRepr == NULL ) return 0; // get the fraiged node pObjFraig = Ssw_ObjFrame( p, pObj, f ); // get the fraiged representative pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); // check if constant 0 pattern distinquishes these nodes assert( pObjFraig != NULL && pObjReprFraig != NULL ); assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); // if the fraiged nodes are the same, return if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) return 0; // call equivalence checking if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); else RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); if ( RetValue == 1 ) // proved equivalent { pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); return 0; } if ( RetValue == -1 ) // timed out { Ssw_ClassesRemoveNode( p->ppClasses, pObj ); return 1; } // disproved equivalence Ssw_SmlSavePatternAig( p, f ); Ssw_ManResimulateBit( p, pObj, pObjRepr ); assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) { Abc_Print( 1, "Ssw_ManSweepNodeConstr(): Failed to refine representative.\n" ); } return 1; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Ssw_ManSweepBmcConstr_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) { Aig_Obj_t * pObjNew, * pObjLi; pObjNew = Ssw_ObjFrame( p, pObj, f ); if ( pObjNew ) return pObjNew; assert( !Saig_ObjIsPi(p->pAig, pObj) ); if ( Saig_ObjIsLo(p->pAig, pObj) ) { assert( f > 0 ); pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); } else { assert( Aig_ObjIsNode(pObj) ); Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin1(pObj), f ); pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); } Ssw_ObjSetFrame( p, pObj, f, pObjNew ); assert( pObjNew != NULL ); return pObjNew; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepBmcConstr_old( Ssw_Man_t * p ) { Bar_Progress_t * pProgress = NULL; Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; int i, f, iLits; abctime clk; clk = Abc_Clock(); // start initialized timeframes p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); // build the constraint outputs iLits = 0; for ( f = 0; f < p->pPars->nFramesK; f++ ) { // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) { pObjNew = Aig_ObjCreateCi(p->pFrames); pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); } // build the constraint cones Saig_ManForEachPo( p->pAig, pObj, i ) { if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) continue; pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) ) { assert( Aig_IsComplement(pObjNew) ); continue; } Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) ); } } assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); // sweep internal nodes p->fRefined = 0; if ( p->pPars->fVerbose ) pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); for ( f = 0; f < p->pPars->nFramesK; f++ ) { // sweep internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) { if ( p->pPars->fVerbose ) Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL ); pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 ); } // quit if this is the last timeframe if ( f == p->pPars->nFramesK - 1 ) break; // transfer latch input to the latch outputs Aig_ManForEachCo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); // build logic cones for register outputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { pObjNew = Ssw_ObjFrame( p, pObjLi, f ); Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// } } if ( p->pPars->fVerbose ) Bar_ProgressStop( pProgress ); // cleanup // Ssw_ClassesCheck( p->ppClasses ); p->timeBmc += Abc_Clock() - clk; return p->fRefined; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepBmcConstr( Ssw_Man_t * p ) { Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; int i, f, iLits; abctime clk; clk = Abc_Clock(); // start initialized timeframes p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); // build the constraint outputs iLits = 0; p->fRefined = 0; for ( f = 0; f < p->pPars->nFramesK; f++ ) { // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) { pObjNew = Aig_ObjCreateCi(p->pFrames); pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); } // build the constraint cones Saig_ManForEachPo( p->pAig, pObj, i ) { if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) continue; pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f ); pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) ) { assert( Aig_IsComplement(pObjNew) ); continue; } Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) ); } // sweep flops Saig_ManForEachLo( p->pAig, pObj, i ) p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 ); // sweep internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) { pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 ); } // quit if this is the last timeframe if ( f == p->pPars->nFramesK - 1 ) break; // transfer latch input to the latch outputs Aig_ManForEachCo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); // build logic cones for register outputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { pObjNew = Ssw_ObjFrame( p, pObjLi, f ); Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// } } assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) ); // cleanup // Ssw_ClassesCheck( p->ppClasses ); p->timeBmc += Abc_Clock() - clk; return p->fRefined; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Ssw_FramesWithClasses_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) { Aig_Obj_t * pObjNew, * pObjLi; pObjNew = Ssw_ObjFrame( p, pObj, f ); if ( pObjNew ) return pObjNew; assert( !Saig_ObjIsPi(p->pAig, pObj) ); if ( Saig_ObjIsLo(p->pAig, pObj) ) { assert( f > 0 ); pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); pObjNew = Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); } else { assert( Aig_ObjIsNode(pObj) ); Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f ); Ssw_FramesWithClasses_rec( p, Aig_ObjFanin1(pObj), f ); pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); } Ssw_ObjSetFrame( p, pObj, f, pObjNew ); assert( pObjNew != NULL ); return pObjNew; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepConstr( Ssw_Man_t * p ) { Bar_Progress_t * pProgress = NULL; Aig_Obj_t * pObj, * pObj2, * pObjNew; int nConstrPairs, i, f, iLits; abctime clk; //Ssw_ManPrintPolarity( p->pAig ); // perform speculative reduction clk = Abc_Clock(); // create timeframes p->pFrames = Ssw_FramesWithClasses( p ); // add constants nConstrPairs = Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig); assert( (nConstrPairs & 1) == 0 ); for ( i = 0; i < nConstrPairs; i += 2 ) { pObj = Aig_ManCo( p->pFrames, i ); pObj2 = Aig_ManCo( p->pFrames, i+1 ); Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); } // build logic cones for register inputs for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) { pObj = Aig_ManCo( p->pFrames, nConstrPairs + i ); Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );// } // map constants and PIs of the last frame f = p->pPars->nFramesK; // iLits = 0; iLits = f * Saig_ManPiNum(p->pAig); Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) { pObjNew = Aig_ObjCreateCi(p->pFrames); pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); } assert( Vec_IntSize(p->vInits) == iLits ); p->timeReduce += Abc_Clock() - clk; // add constraints to all timeframes for ( f = 0; f <= p->pPars->nFramesK; f++ ) { Saig_ManForEachPo( p->pAig, pObj, i ) { if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) ) continue; Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f ); // if ( Aig_Regular(Ssw_ObjChild0Fra(p,pObj,f)) == Aig_ManConst1(p->pFrames) ) if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst0(p->pFrames) ) continue; assert( Ssw_ObjChild0Fra(p,pObj,f) != Aig_ManConst1(p->pFrames) ); if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst1(p->pFrames) ) { Abc_Print( 1, "Polarity violation.\n" ); continue; } Ssw_NodesAreConstrained( p, Ssw_ObjChild0Fra(p,pObj,f), Aig_ManConst0(p->pFrames) ); } } f = p->pPars->nFramesK; // clean the solver sat_solver_simplify( p->pMSat->pSat ); // sweep internal nodes p->fRefined = 0; Ssw_ClassesClearRefined( p->ppClasses ); if ( p->pPars->fVerbose ) pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); Aig_ManForEachObj( p->pAig, pObj, i ) { if ( p->pPars->fVerbose ) Bar_ProgressUpdate( pProgress, i, NULL ); if ( Saig_ObjIsLo(p->pAig, pObj) ) p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 ); else if ( Aig_ObjIsNode(pObj) ) { pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 ); } } if ( p->pPars->fVerbose ) Bar_ProgressStop( pProgress ); // cleanup // Ssw_ClassesCheck( p->ppClasses ); return p->fRefined; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswCore.c000066400000000000000000000453761300674244400236050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [The core procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswCore.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManSetDefaultParams( Ssw_Pars_t * p ) { memset( p, 0, sizeof(Ssw_Pars_t) ); p->nPartSize = 0; // size of the partition p->nOverSize = 0; // size of the overlap between partitions p->nFramesK = 1; // the induction depth p->nFramesAddSim = 2; // additional frames to simulate p->fConstrs = 0; // treat the last nConstrs POs as seq constraints p->fMergeFull = 0; // enables full merge when constraints are used p->nBTLimit = 1000; // conflict limit at a node p->nBTLimitGlobal = 5000000; // conflict limit for all runs p->nMinDomSize = 100; // min clock domain considered for optimization p->nItersStop = -1; // stop after the given number of iterations p->nResimDelta = 1000; // the internal of nodes to resimulate p->nStepsMax = -1; // (scorr only) the max number of induction steps p->fPolarFlip = 0; // uses polarity adjustment p->fLatchCorr = 0; // performs register correspondence p->fConstCorr = 0; // performs constant correspondence p->fOutputCorr = 0; // perform 'PO correspondence' p->fSemiFormal = 0; // enable semiformal filtering p->fDynamic = 0; // dynamic partitioning p->fLocalSim = 0; // local simulation p->fVerbose = 0; // verbose stats p->fEquivDump = 0; // enables dumping equivalences // latch correspondence p->fLatchCorrOpt = 0; // performs optimized register correspondence p->nSatVarMax = 1000; // the max number of SAT variables p->nRecycleCalls = 50; // calls to perform before recycling SAT solver // signal correspondence p->nSatVarMax2 = 5000; // the max number of SAT variables p->nRecycleCalls2 = 250; // calls to perform before recycling SAT solver // return values p->nIters = 0; // the number of iterations performed } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p ) { Ssw_ManSetDefaultParams( p ); p->fLatchCorrOpt = 1; p->nBTLimit = 10000; } /**Function************************************************************* Synopsis [Reports improvements for property cones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ReportConeReductions( Ssw_Man_t * p, Aig_Man_t * pAigInit, Aig_Man_t * pAigStop ) { Aig_Man_t * pAig1, * pAig2, * pAux; pAig1 = Aig_ManDupOneOutput( pAigInit, 0, 1 ); pAig1 = Aig_ManScl( pAux = pAig1, 1, 1, 0, -1, -1, 0, 0 ); Aig_ManStop( pAux ); pAig2 = Aig_ManDupOneOutput( pAigStop, 0, 1 ); pAig2 = Aig_ManScl( pAux = pAig2, 1, 1, 0, -1, -1, 0, 0 ); Aig_ManStop( pAux ); p->nNodesBegC = Aig_ManNodeNum(pAig1); p->nNodesEndC = Aig_ManNodeNum(pAig2); p->nRegsBegC = Aig_ManRegNum(pAig1); p->nRegsEndC = Aig_ManRegNum(pAig2); Aig_ManStop( pAig1 ); Aig_ManStop( pAig2 ); } /**Function************************************************************* Synopsis [Reports one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ReportOneOutput( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj == Aig_ManConst1(p) ) Abc_Print( 1, "1" ); else if ( pObj == Aig_ManConst0(p) ) Abc_Print( 1, "0" ); else Abc_Print( 1, "X" ); } /**Function************************************************************* Synopsis [Reports improvements for property cones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ReportOutputs( Aig_Man_t * pAig ) { Aig_Obj_t * pObj; int i; Saig_ManForEachPo( pAig, pObj, i ) { if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) ) Abc_Print( 1, "o" ); else Abc_Print( 1, "c" ); Ssw_ReportOneOutput( pAig, Aig_ObjChild0(pObj) ); } Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [Remove from-equivs that are in the cone of constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManUpdateEquivs( Ssw_Man_t * p, Aig_Man_t * pAig, int fVerbose ) { Vec_Ptr_t * vCones; Aig_Obj_t ** pArray; Aig_Obj_t * pObj; int i, nTotal = 0, nRemoved = 0; // collect the nodes in the cone of constraints pArray = (Aig_Obj_t **)Vec_PtrArray(pAig->vCos); pArray += Saig_ManPoNum(pAig) - Saig_ManConstrNum(pAig); vCones = Aig_ManDfsNodes( pAig, pArray, Saig_ManConstrNum(pAig) ); // remove all the node that are equiv to something and are in the cones Aig_ManForEachObj( pAig, pObj, i ) { if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) continue; if ( pAig->pReprs[i] != NULL ) nTotal++; if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) ) continue; if ( pAig->pReprs[i] ) { if ( p->pPars->fConstrs && !p->pPars->fMergeFull ) { pAig->pReprs[i] = NULL; nRemoved++; } } } // collect statistics p->nConesTotal = Aig_ManCiNum(pAig) + Aig_ManNodeNum(pAig); p->nConesConstr = Vec_PtrSize(vCones); p->nEquivsTotal = nTotal; p->nEquivsConstr = nRemoved; Vec_PtrFree( vCones ); } /**Function************************************************************* Synopsis [Performs computation of signal correspondence with constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p ) { int nSatProof, nSatCallsSat, nRecycles, nSatFailsReal, nUniques; Aig_Man_t * pAigNew; int RetValue, nIter = -1; abctime clk, clkTotal = Abc_Clock(); // get the starting stats p->nLitsBeg = Ssw_ClassesLitNum( p->ppClasses ); p->nNodesBeg = Aig_ManNodeNum(p->pAig); p->nRegsBeg = Aig_ManRegNum(p->pAig); // refine classes using BMC if ( p->pPars->fVerbose ) { Abc_Print( 1, "Before BMC: " ); Ssw_ClassesPrint( p->ppClasses, 0 ); } if ( !p->pPars->fLatchCorr ) { p->pMSat = Ssw_SatStart( 0 ); if ( p->pPars->fConstrs ) Ssw_ManSweepBmcConstr( p ); else Ssw_ManSweepBmc( p ); Ssw_SatStop( p->pMSat ); p->pMSat = NULL; Ssw_ManCleanup( p ); } if ( p->pPars->fVerbose ) { Abc_Print( 1, "After BMC: " ); Ssw_ClassesPrint( p->ppClasses, 0 ); } // apply semi-formal filtering /* if ( p->pPars->fSemiFormal ) { Aig_Man_t * pSRed; Ssw_FilterUsingSemi( p, 0, 2000, p->pPars->fVerbose ); // Ssw_FilterUsingSemi( p, 1, 100000, p->pPars->fVerbose ); pSRed = Ssw_SpeculativeReduction( p ); Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL ); Aig_ManStop( pSRed ); } */ if ( p->pPars->pFunc ) { ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); } if ( p->pPars->nStepsMax == 0 ) { Abc_Print( 1, "Stopped signal correspondence after BMC.\n" ); goto finalize; } // refine classes using induction nSatProof = nSatCallsSat = nRecycles = nSatFailsReal = nUniques = 0; for ( nIter = 0; ; nIter++ ) { if ( p->pPars->nStepsMax == nIter ) { Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", nIter ); goto finalize; } if ( p->pPars->nItersStop >= 0 && p->pPars->nItersStop == nIter ) { Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p ); Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL ); Aig_ManStop( pSRed ); Abc_Print( 1, "Iterative refinement is stopped before iteration %d.\n", nIter ); Abc_Print( 1, "The network is reduced using candidate equivalences.\n" ); Abc_Print( 1, "Speculatively reduced miter is saved in file \"%s\".\n", "srm.blif" ); Abc_Print( 1, "If the miter is SAT, the reduced result is incorrect.\n" ); break; } clk = Abc_Clock(); p->pMSat = Ssw_SatStart( 0 ); if ( p->pPars->fLatchCorrOpt ) { RetValue = Ssw_ManSweepLatch( p ); if ( p->pPars->fVerbose ) { Abc_Print( 1, "%3d : C =%7d. Cl =%7d. Pr =%6d. Cex =%5d. R =%4d. F =%4d. ", nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses), p->nSatProof-nSatProof, p->nSatCallsSat-nSatCallsSat, p->nRecycles-nRecycles, p->nSatFailsReal-nSatFailsReal ); ABC_PRT( "T", Abc_Clock() - clk ); } } else { if ( p->pPars->fConstrs ) RetValue = Ssw_ManSweepConstr( p ); else if ( p->pPars->fDynamic ) RetValue = Ssw_ManSweepDyn( p ); else RetValue = Ssw_ManSweep( p ); p->pPars->nConflicts += p->pMSat->pSat->stats.conflicts; if ( p->pPars->fVerbose ) { Abc_Print( 1, "%3d : C =%7d. Cl =%7d. LR =%6d. NR =%6d. ", nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses), p->nConstrReduced, Aig_ManNodeNum(p->pFrames) ); if ( p->pPars->fDynamic ) { Abc_Print( 1, "Cex =%5d. ", p->nSatCallsSat-nSatCallsSat ); Abc_Print( 1, "R =%4d. ", p->nRecycles-nRecycles ); } Abc_Print( 1, "F =%5d. %s ", p->nSatFailsReal-nSatFailsReal, (Saig_ManPoNum(p->pAig)==1 && Ssw_ObjIsConst1Cand(p->pAig,Aig_ObjFanin0(Aig_ManCo(p->pAig,0))))? "+" : "-" ); ABC_PRT( "T", Abc_Clock() - clk ); } // if ( p->pPars->fDynamic && p->nSatCallsSat-nSatCallsSat < 100 ) // p->pPars->nBTLimit = 10000; if ( p->pPars->fStopWhenGone && Saig_ManPoNum(p->pAig) == 1 && !Ssw_ObjIsConst1Cand(p->pAig,Aig_ObjFanin0(Aig_ManCo(p->pAig,0))) ) { printf( "Iterative refinement is stopped after iteration %d\n", nIter ); printf( "because the property output is no longer a candidate constant.\n" ); // prepare to quite p->nLitsEnd = p->nLitsBeg; p->nNodesEnd = p->nNodesBeg; p->nRegsEnd = p->nRegsBeg; // cleanup Ssw_SatStop( p->pMSat ); p->pMSat = NULL; Ssw_ManCleanup( p ); // cleanup Aig_ManSetPhase( p->pAig ); Aig_ManCleanMarkB( p->pAig ); return Aig_ManDupSimple( p->pAig ); } } nSatProof = p->nSatProof; nSatCallsSat = p->nSatCallsSat; nRecycles = p->nRecycles; nSatFailsReal = p->nSatFailsReal; nUniques = p->nUniques; p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars ); p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls ); Ssw_SatStop( p->pMSat ); p->pMSat = NULL; Ssw_ManCleanup( p ); if ( !RetValue ) break; if ( p->pPars->pFunc ) ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData ); } finalize: p->pPars->nIters = nIter + 1; p->timeTotal = Abc_Clock() - clkTotal; Ssw_ManUpdateEquivs( p, p->pAig, p->pPars->fVerbose ); pAigNew = Aig_ManDupRepr( p->pAig, 0 ); Aig_ManSeqCleanup( pAigNew ); //Ssw_ClassesPrint( p->ppClasses, 1 ); // get the final stats p->nLitsEnd = Ssw_ClassesLitNum( p->ppClasses ); p->nNodesEnd = Aig_ManNodeNum(pAigNew); p->nRegsEnd = Aig_ManRegNum(pAigNew); // cleanup Aig_ManSetPhase( p->pAig ); Aig_ManCleanMarkB( p->pAig ); return pAigNew; } /**Function************************************************************* Synopsis [Performs computation of signal correspondence with constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) { Ssw_Pars_t Pars; Aig_Man_t * pAigNew; Ssw_Man_t * p; assert( Aig_ManRegNum(pAig) > 0 ); // reset random numbers Aig_ManRandom( 1 ); // if parameters are not given, create them if ( pPars == NULL ) Ssw_ManSetDefaultParams( pPars = &Pars ); // consider the case of empty AIG if ( Aig_ManNodeNum(pAig) == 0 ) { pPars->nIters = 0; // Ntl_ManFinalize() needs the following to satisfy an assertion Aig_ManReprStart( pAig,Aig_ManObjNumMax(pAig) ); return Aig_ManDupOrdered(pAig); } // check and update parameters if ( pPars->fLatchCorrOpt ) { pPars->fLatchCorr = 1; pPars->nFramesAddSim = 0; if ( (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) ) return Ssw_SignalCorrespondencePart( pAig, pPars ); } else { assert( pPars->nFramesK > 0 ); // perform partitioning if ( (pPars->nPartSize > 0 && pPars->nPartSize < Aig_ManRegNum(pAig)) || (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) ) return Ssw_SignalCorrespondencePart( pAig, pPars ); } if ( pPars->fScorrGia ) { if ( pPars->fLatchCorrOpt ) { extern Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ); return Cec_LatchCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat ); } else { extern Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat ); return Cec_SignalCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat ); } } // start the induction manager p = Ssw_ManCreate( pAig, pPars ); // compute candidate equivalence classes // p->pPars->nConstrs = 1; if ( p->pPars->fConstrs ) { // create trivial equivalence classes with all nodes being candidates for constant 1 p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchCorr, pPars->nMaxLevs ); Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit ); // derive phase bits to satisfy the constraints if ( Ssw_ManSetConstrPhases( pAig, p->pPars->nFramesK + 1, &p->vInits ) != 0 ) { Abc_Print( 1, "Ssw_SignalCorrespondence(): The init state does not satisfy the constraints!\n" ); p->pPars->fVerbose = 0; Ssw_ManStop( p ); return NULL; } // perform simulation of the first timeframes Ssw_ManRefineByConstrSim( p ); } else { // perform one round of seq simulation and generate candidate equivalence classes p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose ); // p->ppClasses = Ssw_ClassesPrepareTargets( pAig ); if ( pPars->fLatchCorrOpt ) p->pSml = Ssw_SmlStart( pAig, 0, 2, 1 ); else if ( pPars->fDynamic ) p->pSml = Ssw_SmlStart( pAig, 0, p->nFrames + p->pPars->nFramesAddSim, 1 ); else p->pSml = Ssw_SmlStart( pAig, 0, 1 + p->pPars->nFramesAddSim, 1 ); Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); } // allocate storage if ( p->pPars->fLocalSim ) p->pVisited = ABC_CALLOC( int, Ssw_SmlNumFrames( p->pSml ) * Aig_ManObjNumMax(p->pAig) ); // perform refinement of classes pAigNew = Ssw_SignalCorrespondenceRefine( p ); // Ssw_ReportOutputs( pAigNew ); if ( pPars->fConstrs && pPars->fVerbose ) Ssw_ReportConeReductions( p, pAig, pAigNew ); // cleanup Ssw_ManStop( p ); return pAigNew; } /**Function************************************************************* Synopsis [Performs computation of latch correspondence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) { Aig_Man_t * pRes; Ssw_Pars_t Pars; if ( pPars == NULL ) Ssw_ManSetDefaultParamsLcorr( pPars = &Pars ); pRes = Ssw_SignalCorrespondence( pAig, pPars ); // if ( pPars->fConstrs && pPars->fVerbose ) // Ssw_ReportConeReductions( pAig, pRes ); return pRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswDyn.c000066400000000000000000000374141300674244400234410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswDyn.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Dynamic loading of constraints.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswDyn.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" #include "misc/bar/bar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Label PIs nodes of the frames corresponding to PIs of AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManLabelPiNodes( Ssw_Man_t * p ) { Aig_Obj_t * pObj, * pObjFrames; int f, i; Aig_ManConst1( p->pFrames )->fMarkA = 1; Aig_ManConst1( p->pFrames )->fMarkB = 1; for ( f = 0; f < p->nFrames; f++ ) { Saig_ManForEachPi( p->pAig, pObj, i ) { pObjFrames = Ssw_ObjFrame( p, pObj, f ); assert( Aig_ObjIsCi(pObjFrames) ); assert( pObjFrames->fMarkB == 0 ); pObjFrames->fMarkA = 1; pObjFrames->fMarkB = 1; } } } /**Function************************************************************* Synopsis [Collects new POs in p->vNewPos.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManCollectPis_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vNewPis ) { assert( !Aig_IsComplement(pObj) ); if ( pObj->fMarkA ) return; pObj->fMarkA = 1; if ( Aig_ObjIsCi(pObj) ) { Vec_PtrPush( vNewPis, pObj ); return; } assert( Aig_ObjIsNode(pObj) ); Ssw_ManCollectPis_rec( Aig_ObjFanin0(pObj), vNewPis ); Ssw_ManCollectPis_rec( Aig_ObjFanin1(pObj), vNewPis ); } /**Function************************************************************* Synopsis [Collects new POs in p->vNewPos.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManCollectPos_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vNewPos ) { Aig_Obj_t * pFanout; int iFanout = -1, i; assert( !Aig_IsComplement(pObj) ); if ( pObj->fMarkB ) return; pObj->fMarkB = 1; if ( pObj->Id > p->nSRMiterMaxId ) return; if ( Aig_ObjIsCo(pObj) ) { // skip if it is a register input PO if ( Aig_ObjCioId(pObj) >= Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig) ) return; // add the number of this constraint Vec_IntPush( vNewPos, Aig_ObjCioId(pObj)/2 ); return; } // visit the fanouts assert( p->pFrames->pFanData != NULL ); Aig_ObjForEachFanout( p->pFrames, pObj, pFanout, iFanout, i ) Ssw_ManCollectPos_rec( p, pFanout, vNewPos ); } /**Function************************************************************* Synopsis [Loads logic cones and relevant constraints.] Description [Both pRepr and pObj are objects of the AIG. The result is the current SAT solver loaded with the logic cones for pRepr and pObj corresponding to them in the frames, as well as all the relevant constraints.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjFrames, * pReprFrames; Aig_Obj_t * pTemp, * pObj0, * pObj1; int i, iConstr, RetValue; assert( pRepr != pObj ); // get the corresponding frames nodes pReprFrames = Aig_Regular( Ssw_ObjFrame( p, pRepr, p->pPars->nFramesK ) ); pObjFrames = Aig_Regular( Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) ); assert( pReprFrames != pObjFrames ); /* // compute the AIG support Vec_PtrClear( p->vNewLos ); Ssw_ManCollectPis_rec( pRepr, p->vNewLos ); Ssw_ManCollectPis_rec( pObj, p->vNewLos ); // add logic cones for register outputs Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i ) { pObj0 = Aig_Regular( Ssw_ObjFrame( p, pTemp, p->pPars->nFramesK ) ); Ssw_CnfNodeAddToSolver( p->pMSat, pObj0 ); } */ // add cones for the nodes Ssw_CnfNodeAddToSolver( p->pMSat, pReprFrames ); Ssw_CnfNodeAddToSolver( p->pMSat, pObjFrames ); // compute the frames support Vec_PtrClear( p->vNewLos ); Ssw_ManCollectPis_rec( pReprFrames, p->vNewLos ); Ssw_ManCollectPis_rec( pObjFrames, p->vNewLos ); // these nodes include both nodes corresponding to PIs and LOs // (the nodes corresponding to PIs should be labeled with fMarkB!) // collect the related constraint POs Vec_IntClear( p->vNewPos ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i ) Ssw_ManCollectPos_rec( p, pTemp, p->vNewPos ); // check if the corresponding pairs are added Vec_IntForEachEntry( p->vNewPos, iConstr, i ) { pObj0 = Aig_ManCo( p->pFrames, 2*iConstr ); pObj1 = Aig_ManCo( p->pFrames, 2*iConstr+1 ); // if ( pObj0->fMarkB && pObj1->fMarkB ) if ( pObj0->fMarkB || pObj1->fMarkB ) { pObj0->fMarkB = 1; pObj1->fMarkB = 1; Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj0), Aig_ObjChild0(pObj1) ); } } if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) { RetValue = sat_solver_simplify(p->pMSat->pSat); assert( RetValue != 0 ); } } /**Function************************************************************* Synopsis [Tranfers simulation information from FRAIG to AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManSweepTransferDyn( Ssw_Man_t * p ) { Aig_Obj_t * pObj, * pObjFraig; unsigned * pInfo; int i, f, nFrames; // transfer simulation information Aig_ManForEachCi( p->pAig, pObj, i ) { pObjFraig = Ssw_ObjFrame( p, pObj, 0 ); if ( pObjFraig == Aig_ManConst0(p->pFrames) ) { Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 ); continue; } assert( !Aig_IsComplement(pObjFraig) ); assert( Aig_ObjIsCi(pObjFraig) ); pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObjFraig) ); Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 ); } // set random simulation info for the second frame for ( f = 1; f < p->nFrames; f++ ) { Saig_ManForEachPi( p->pAig, pObj, i ) { pObjFraig = Ssw_ObjFrame( p, pObj, f ); assert( !Aig_IsComplement(pObjFraig) ); assert( Aig_ObjIsCi(pObjFraig) ); pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObjFraig) ); Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, f ); } } // create random info nFrames = Ssw_SmlNumFrames( p->pSml ); for ( ; f < nFrames; f++ ) { Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_SmlAssignRandomFrame( p->pSml, pObj, f ); } } /**Function************************************************************* Synopsis [Performs one round of simulation with counter-examples.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepResimulateDyn( Ssw_Man_t * p, int f ) { int RetValue1, RetValue2; abctime clk = Abc_Clock(); // transfer PI simulation information from storage // Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); Ssw_ManSweepTransferDyn( p ); // simulate internal nodes // Ssw_SmlSimulateOneFrame( p->pSml ); Ssw_SmlSimulateOne( p->pSml ); // check equivalence classes RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); // prepare simulation info for the next round Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); p->nPatterns = 0; p->nSimRounds++; p->timeSimSat += Abc_Clock() - clk; return RetValue1 > 0 || RetValue2 > 0; } /**Function************************************************************* Synopsis [Performs one round of simulation with counter-examples.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepResimulateDynLocal( Ssw_Man_t * p, int f ) { Aig_Obj_t * pObj, * pRepr, ** ppClass; int i, k, nSize, RetValue1, RetValue2; abctime clk = Abc_Clock(); p->nSimRounds++; // transfer PI simulation information from storage // Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); Ssw_ManSweepTransferDyn( p ); // determine const1 cands and classes to be simulated Vec_PtrClear( p->vResimConsts ); Vec_PtrClear( p->vResimClasses ); Aig_ManIncrementTravId( p->pAig ); for ( i = p->iNodeStart; i < p->iNodeLast + p->pPars->nResimDelta; i++ ) { if ( i >= Aig_ManObjNumMax( p->pAig ) ) break; pObj = Aig_ManObj( p->pAig, i ); if ( pObj == NULL ) continue; if ( Ssw_ObjIsConst1Cand(p->pAig, pObj) ) { Vec_PtrPush( p->vResimConsts, pObj ); continue; } pRepr = Aig_ObjRepr(p->pAig, pObj); if ( pRepr == NULL ) continue; if ( Aig_ObjIsTravIdCurrent(p->pAig, pRepr) ) continue; Aig_ObjSetTravIdCurrent(p->pAig, pRepr); Vec_PtrPush( p->vResimClasses, pRepr ); } // simulate internal nodes // Ssw_SmlSimulateOneFrame( p->pSml ); // Ssw_SmlSimulateOne( p->pSml ); // resimulate dynamically // Aig_ManIncrementTravId( p->pAig ); // Aig_ObjIsTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) ); p->nVisCounter++; Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimConsts, pObj, i ) Ssw_SmlSimulateOneDyn_rec( p->pSml, pObj, p->nFrames-1, p->pVisited, p->nVisCounter ); // resimulate the cone of influence of the cand classes Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i ) { ppClass = Ssw_ClassesReadClass( p->ppClasses, pRepr, &nSize ); for ( k = 0; k < nSize; k++ ) Ssw_SmlSimulateOneDyn_rec( p->pSml, ppClass[k], p->nFrames-1, p->pVisited, p->nVisCounter ); } // check equivalence classes // RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); // RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); // refine these nodes RetValue1 = Ssw_ClassesRefineConst1Group( p->ppClasses, p->vResimConsts, 1 ); RetValue2 = 0; Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i ) RetValue2 += Ssw_ClassesRefineOneClass( p->ppClasses, pRepr, 1 ); // prepare simulation info for the next round Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); p->nPatterns = 0; p->nSimRounds++; p->timeSimSat += Abc_Clock() - clk; return RetValue1 > 0 || RetValue2 > 0; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepDyn( Ssw_Man_t * p ) { Bar_Progress_t * pProgress = NULL; Aig_Obj_t * pObj, * pObjNew; int i, f; abctime clk; // perform speculative reduction clk = Abc_Clock(); // create timeframes p->pFrames = Ssw_FramesWithClasses( p ); Aig_ManFanoutStart( p->pFrames ); p->nSRMiterMaxId = Aig_ManObjNumMax( p->pFrames ); // map constants and PIs of the last frame f = p->pPars->nFramesK; Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) ); Aig_ManSetCioIds( p->pFrames ); // label nodes corresponding to primary inputs Ssw_ManLabelPiNodes( p ); p->timeReduce += Abc_Clock() - clk; // prepare simulation info assert( p->vSimInfo == NULL ); p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManCiNum(p->pFrames), 1 ); Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); // sweep internal nodes p->fRefined = 0; Ssw_ClassesClearRefined( p->ppClasses ); if ( p->pPars->fVerbose ) pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); p->iNodeStart = 0; Aig_ManForEachObj( p->pAig, pObj, i ) { if ( p->iNodeStart == 0 ) p->iNodeStart = i; if ( p->pPars->fVerbose ) Bar_ProgressUpdate( pProgress, i, NULL ); if ( Saig_ObjIsLo(p->pAig, pObj) ) p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL ); else if ( Aig_ObjIsNode(pObj) ) { pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL ); } // check if it is time to recycle the solver if ( p->pMSat->pSat == NULL || (p->pPars->nSatVarMax2 && p->pMSat->nSatVars > p->pPars->nSatVarMax2 && p->nRecycleCalls > p->pPars->nRecycleCalls2) ) { // resimulate if ( p->nPatterns > 0 ) { p->iNodeLast = i; if ( p->pPars->fLocalSim ) Ssw_ManSweepResimulateDynLocal( p, f ); else Ssw_ManSweepResimulateDyn( p, f ); p->iNodeStart = i+1; } // Abc_Print( 1, "Recycling SAT solver with %d vars and %d calls.\n", // p->pMSat->nSatVars, p->nRecycleCalls ); // Aig_ManCleanMarkAB( p->pAig ); Aig_ManCleanMarkAB( p->pFrames ); // label nodes corresponding to primary inputs Ssw_ManLabelPiNodes( p ); // replace the solver if ( p->pMSat ) { p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars ); p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls ); Ssw_SatStop( p->pMSat ); p->nRecycles++; p->nRecyclesTotal++; p->nRecycleCalls = 0; } p->pMSat = Ssw_SatStart( 0 ); assert( p->nPatterns == 0 ); } // resimulate if ( p->nPatterns == 32 ) { p->iNodeLast = i; if ( p->pPars->fLocalSim ) Ssw_ManSweepResimulateDynLocal( p, f ); else Ssw_ManSweepResimulateDyn( p, f ); p->iNodeStart = i+1; } } // resimulate if ( p->nPatterns > 0 ) { p->iNodeLast = i; if ( p->pPars->fLocalSim ) Ssw_ManSweepResimulateDynLocal( p, f ); else Ssw_ManSweepResimulateDyn( p, f ); } // collect stats if ( p->pPars->fVerbose ) Bar_ProgressStop( pProgress ); // cleanup // Ssw_ClassesCheck( p->ppClasses ); return p->fRefined; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswFilter.c000066400000000000000000000420121300674244400241220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswConstr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [One round of SAT sweeping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManRefineByFilterSim( Ssw_Man_t * p, int nFrames ) { Aig_Obj_t * pObj, * pObjLi; int f, i, RetValue1, RetValue2; assert( nFrames > 0 ); // assign register outputs Saig_ManForEachLi( p->pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); // simulate the timeframes for ( f = 0; f < nFrames; f++ ) { // set the PI simulation information Aig_ManConst1(p->pAig)->fMarkB = 1; Saig_ManForEachPi( p->pAig, pObj, i ) pObj->fMarkB = 0; Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) pObj->fMarkB = pObjLi->fMarkB; // simulate internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); // assign the COs Aig_ManForEachCo( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); // transfer if ( f == 0 ) { // copy markB into phase Aig_ManForEachObj( p->pAig, pObj, i ) pObj->fPhase = pObj->fMarkB; } else { // refine classes RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); } } } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManRollForward( Ssw_Man_t * p, int nFrames ) { Aig_Obj_t * pObj, * pObjLi; int f, i; assert( nFrames > 0 ); // assign register outputs Saig_ManForEachLi( p->pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); // simulate the timeframes for ( f = 0; f < nFrames; f++ ) { // set the PI simulation information Aig_ManConst1(p->pAig)->fMarkB = 1; Saig_ManForEachPi( p->pAig, pObj, i ) pObj->fMarkB = Aig_ManRandom(0) & 1; Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) pObj->fMarkB = pObjLi->fMarkB; // simulate internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); // assign the COs Aig_ManForEachCo( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); } // record the new pattern Saig_ManForEachLi( p->pAig, pObj, i ) if ( pObj->fMarkB ^ Abc_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) ) Abc_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManFindStartingState( Ssw_Man_t * p, Abc_Cex_t * pCex ) { Aig_Obj_t * pObj, * pObjLi; int f, i, iBit; // assign register outputs Saig_ManForEachLi( p->pAig, pObj, i ) pObj->fMarkB = 0; // simulate the timeframes iBit = pCex->nRegs; for ( f = 0; f <= pCex->iFrame; f++ ) { // set the PI simulation information Aig_ManConst1(p->pAig)->fMarkB = 1; Saig_ManForEachPi( p->pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ ); Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) pObj->fMarkB = pObjLi->fMarkB; // simulate internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); // assign the COs Aig_ManForEachCo( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); } assert( iBit == pCex->nBits ); // check that the output failed as expected -- cannot check because it is not an SRM! // pObj = Aig_ManCo( p->pAig, pCex->iPo ); // if ( pObj->fMarkB != 1 ) // Abc_Print( 1, "The counter-example does not refine the output.\n" ); // record the new pattern Saig_ManForEachLo( p->pAig, pObj, i ) if ( pObj->fMarkB ^ Abc_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) ) Abc_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ); } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepNodeFilter( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) { Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; int RetValue; // get representative of this class pObjRepr = Aig_ObjRepr( p->pAig, pObj ); if ( pObjRepr == NULL ) return 0; // get the fraiged node pObjFraig = Ssw_ObjFrame( p, pObj, f ); // get the fraiged representative pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); // check if constant 0 pattern distinquishes these nodes assert( pObjFraig != NULL && pObjReprFraig != NULL ); assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); // if the fraiged nodes are the same, return if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) return 0; // call equivalence checking if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); else RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); if ( RetValue == 1 ) // proved equivalent { pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); return 0; } if ( RetValue == -1 ) // timed out { // Ssw_ClassesRemoveNode( p->ppClasses, pObj ); return 1; } // disproved equivalence Ssw_SmlSavePatternAig( p, f ); Ssw_ManResimulateBit( p, pObj, pObjRepr ); assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) { Abc_Print( 1, "Ssw_ManSweepNodeFilter(): Failed to refine representative.\n" ); } return 0; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Ssw_ManSweepBmcFilter_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) { Aig_Obj_t * pObjNew, * pObjLi; pObjNew = Ssw_ObjFrame( p, pObj, f ); if ( pObjNew ) return pObjNew; assert( !Saig_ObjIsPi(p->pAig, pObj) ); if ( Saig_ObjIsLo(p->pAig, pObj) ) { assert( f > 0 ); pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); pObjNew = Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObjLi), f-1 ); pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) ); } else { assert( Aig_ObjIsNode(pObj) ); Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObj), f ); Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin1(pObj), f ); pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); } Ssw_ObjSetFrame( p, pObj, f, pObjNew ); assert( pObjNew != NULL ); return pObjNew; } /**Function************************************************************* Synopsis [Filter equivalence classes of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepBmcFilter( Ssw_Man_t * p, int TimeLimit ) { Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; int f, f1, i; abctime clkTotal = Abc_Clock(); // start initialized timeframes p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); Saig_ManForEachLo( p->pAig, pObj, i ) { if ( Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ) ) { Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst1(p->pFrames) ); //Abc_Print( 1, "1" ); } else { Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); //Abc_Print( 1, "0" ); } } //Abc_Print( 1, "\n" ); // sweep internal nodes for ( f = 0; f < p->pPars->nFramesK; f++ ) { // realloc mapping of timeframes if ( f == p->nFrames-1 ) { Aig_Obj_t ** pNodeToFrames; pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * 2 * p->nFrames ); for ( f1 = 0; f1 < p->nFrames; f1++ ) { Aig_ManForEachObj( p->pAig, pObj, i ) pNodeToFrames[2*p->nFrames*pObj->Id + f1] = Ssw_ObjFrame( p, pObj, f1 ); } ABC_FREE( p->pNodeToFrames ); p->pNodeToFrames = pNodeToFrames; p->nFrames *= 2; } // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) { pObjNew = Aig_ObjCreateCi(p->pFrames); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); } // sweep internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) { pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); if ( Ssw_ManSweepNodeFilter( p, pObj, f ) ) break; } // printout if ( p->pPars->fVerbose ) { Abc_Print( 1, "Frame %4d : ", f ); Ssw_ClassesPrint( p->ppClasses, 0 ); } if ( i < Vec_PtrSize(p->pAig->vObjs) ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Exceeded the resource limits (%d conflicts). Quitting...\n", p->pPars->nBTLimit ); break; } // quit if this is the last timeframe if ( f == p->pPars->nFramesK - 1 ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Exceeded the time frame limit (%d time frames). Quitting...\n", p->pPars->nFramesK ); break; } // check timeout if ( TimeLimit && ((float)TimeLimit <= (float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)) ) break; // transfer latch input to the latch outputs Aig_ManForEachCo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); // build logic cones for register outputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { pObjNew = Ssw_ObjFrame( p, pObjLi, f ); Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// } } // verify // Ssw_ClassesCheck( p->ppClasses ); return 1; } /**Function************************************************************* Synopsis [Filter equivalence classes of nodes.] Description [Unrolls at most nFramesMax frames. Works with nConfMax conflicts until the first undefined SAT call. Verbose prints the message.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SignalFilter( Aig_Man_t * pAig, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) { Ssw_Pars_t Pars, * pPars = &Pars; Ssw_Man_t * p; int r, TimeLimitPart;//, clkTotal = Abc_Clock(); abctime nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; assert( Aig_ManRegNum(pAig) > 0 ); assert( Aig_ManConstrNum(pAig) == 0 ); // consider the case of empty AIG if ( Aig_ManNodeNum(pAig) == 0 ) return; // reset random numbers Aig_ManRandom( 1 ); // if parameters are not given, create them Ssw_ManSetDefaultParams( pPars = &Pars ); pPars->nFramesK = 3; //nFramesMax; pPars->nBTLimit = nConfMax; pPars->TimeLimit = TimeLimit; pPars->fVerbose = fVerbose; // start the induction manager p = Ssw_ManCreate( pAig, pPars ); pPars->nFramesK = nFramesMax; // create trivial equivalence classes with all nodes being candidates for constant 1 if ( pAig->pReprs == NULL ) p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 ); else p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit ); assert( p->vInits == NULL ); // compute starting state if needed if ( pCex ) Ssw_ManFindStartingState( p, pCex ); // refine classes using BMC for ( r = 0; r < nRounds; r++ ) { if ( p->pPars->fVerbose ) Abc_Print( 1, "Round %3d:\n", r ); // start filtering equivalence classes Ssw_ManRefineByFilterSim( p, p->pPars->nFramesK ); if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) { Abc_Print( 1, "All equivalences are refined away.\n" ); break; } // printout if ( p->pPars->fVerbose ) { Abc_Print( 1, "Initial : " ); Ssw_ClassesPrint( p->ppClasses, 0 ); } p->pMSat = Ssw_SatStart( 0 ); TimeLimitPart = TimeLimit ? (nTimeToStop - Abc_Clock()) / CLOCKS_PER_SEC : 0; if ( TimeLimit2 ) { if ( TimeLimitPart ) TimeLimitPart = Abc_MinInt( TimeLimitPart, TimeLimit2 ); else TimeLimitPart = TimeLimit2; } Ssw_ManSweepBmcFilter( p, TimeLimitPart ); Ssw_SatStop( p->pMSat ); p->pMSat = NULL; Ssw_ManCleanup( p ); // simulate pattern forward Ssw_ManRollForward( p, p->pPars->nFramesK ); // check timeout if ( TimeLimit && Abc_Clock() > nTimeToStop ) { Abc_Print( 1, "Reached timeout (%d seconds).\n", TimeLimit ); break; } } // cleanup Aig_ManSetPhase( p->pAig ); Aig_ManCleanMarkB( p->pAig ); // cleanup pPars->fVerbose = 0; Ssw_ManStop( p ); } /**Function************************************************************* Synopsis [Filter equivalence classes of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SignalFilterGia( Gia_Man_t * p, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) { Aig_Man_t * pAig; pAig = Gia_ManToAigSimple( p ); if ( p->pReprs != NULL ) { Gia_ManReprToAigRepr2( pAig, p ); ABC_FREE( p->pReprs ); ABC_FREE( p->pNexts ); } Ssw_SignalFilter( pAig, nFramesMax, nConfMax, nRounds, TimeLimit, TimeLimit2, pCex, fLatchOnly, fVerbose ); Gia_ManReprFromAigRepr( pAig, p ); Aig_ManStop( pAig ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswInt.h000066400000000000000000000420411300674244400234360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswInt.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__ssw__sswInt_h #define ABC__aig__ssw__sswInt_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/saig/saig.h" #include "sat/bsat/satSolver.h" #include "ssw.h" #include "aig/ioa/ioa.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Ssw_Man_t_ Ssw_Man_t; // signal correspondence manager typedef struct Ssw_Frm_t_ Ssw_Frm_t; // unrolled frames manager typedef struct Ssw_Sat_t_ Ssw_Sat_t; // SAT solver manager typedef struct Ssw_Cla_t_ Ssw_Cla_t; // equivalence classe manager struct Ssw_Man_t_ { // parameters Ssw_Pars_t * pPars; // parameters int nFrames; // for quick lookup // AIGs used in the package Aig_Man_t * pAig; // user-given AIG Aig_Man_t * pFrames; // final AIG Aig_Obj_t ** pNodeToFrames; // mapping of AIG nodes into FRAIG nodes // equivalence classes Ssw_Cla_t * ppClasses; // equivalence classes of nodes int fRefined; // is set to 1 when refinement happens // SAT solving Ssw_Sat_t * pMSatBmc; // SAT manager for base case Ssw_Sat_t * pMSat; // SAT manager for inductive case // SAT solving (latch corr only) Vec_Ptr_t * vSimInfo; // simulation information for the framed PIs int nPatterns; // the number of patterns saved int nSimRounds; // the number of simulation rounds performed int nCallsCount; // the number of calls in this round int nCallsDelta; // the number of calls to skip int nCallsSat; // the number of SAT calls in this round int nCallsUnsat; // the number of UNSAT calls in this round int nRecycleCalls; // the number of calls since last recycling int nRecycles; // the number of time SAT solver was recycled int nRecyclesTotal; // the number of time SAT solver was recycled int nVarsMax; // the maximum variables in the solver int nCallsMax; // the maximum number of SAT calls // uniqueness Vec_Ptr_t * vCommon; // the set of common variables in the logic cones int iOutputLit; // the output literal of the uniqueness constraint Vec_Int_t * vDiffPairs; // is set to 1 if reg pair can be diff int nUniques; // the number of uniqueness constraints used int nUniquesAdded; // useful uniqueness constraints int nUniquesUseful; // useful uniqueness constraints // dynamic constraint addition int nSRMiterMaxId; // max ID after which the last frame begins Vec_Ptr_t * vNewLos; // new time frame LOs of to constrain Vec_Int_t * vNewPos; // new time frame POs of to add constraints int * pVisited; // flags to label visited nodes in each frame int nVisCounter; // the traversal ID // sequential simulation Ssw_Sml_t * pSml; // the simulator int iNodeStart; // the first node considered int iNodeLast; // the last node considered Vec_Ptr_t * vResimConsts; // resimulation constants Vec_Ptr_t * vResimClasses; // resimulation classes Vec_Int_t * vInits; // the init values of primary inputs under constraints // counter example storage int nPatWords; // the number of words in the counter example unsigned * pPatWords; // the counter example // constraints int nConstrTotal; // the number of total constraints int nConstrReduced; // the number of reduced constraints int nStrangers; // the number of strange situations // SAT calls statistics int nSatCalls; // the number of SAT calls int nSatProof; // the number of proofs int nSatFailsReal; // the number of timeouts int nSatCallsUnsat; // the number of unsat SAT calls int nSatCallsSat; // the number of sat SAT calls // node/register/lit statistics int nLitsBeg; int nLitsEnd; int nNodesBeg; int nNodesEnd; int nRegsBeg; int nRegsEnd; // equiv statistis int nConesTotal; int nConesConstr; int nEquivsTotal; int nEquivsConstr; int nNodesBegC; int nNodesEndC; int nRegsBegC; int nRegsEndC; // runtime stats abctime timeBmc; // bounded model checking abctime timeReduce; // speculative reduction abctime timeMarkCones; // marking the cones not to be refined abctime timeSimSat; // simulation of the counter-examples abctime timeSat; // solving SAT abctime timeSatSat; // sat abctime timeSatUnsat; // unsat abctime timeSatUndec; // undecided abctime timeOther; // other runtime abctime timeTotal; // total runtime }; // internal SAT manager struct Ssw_Sat_t_ { Aig_Man_t * pAig; // the AIG manager int fPolarFlip; // flips polarity sat_solver * pSat; // recyclable SAT solver int nSatVars; // the counter of SAT variables Vec_Int_t * vSatVars; // mapping of each node into its SAT var Vec_Ptr_t * vFanins; // fanins of the CNF node Vec_Ptr_t * vUsedPis; // the PIs with SAT variables int nSolverCalls; // the total number of SAT calls }; // internal frames manager struct Ssw_Frm_t_ { Aig_Man_t * pAig; // user-given AIG int nObjs; // offset in terms of AIG nodes int nFrames; // the number of frames in current unrolling Aig_Man_t * pFrames; // unrolled AIG Vec_Ptr_t * vAig2Frm; // mapping of AIG nodes into frame nodes }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Ssw_ObjSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj ) { return Vec_IntGetEntry( p->vSatVars, pObj->Id ); } static inline void Ssw_ObjSetSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj, int Num ) { Vec_IntSetEntry(p->vSatVars, pObj->Id, Num); } static inline int Ssw_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) { return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig); } static inline void Ssw_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj ) { assert( !Ssw_ObjIsConst1Cand( pAig, pObj ) ); Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) ); } static inline Aig_Obj_t * Ssw_ObjFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { return p->pNodeToFrames[p->nFrames*pObj->Id + i]; } static inline void Ssw_ObjSetFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { p->pNodeToFrames[p->nFrames*pObj->Id + i] = pNode; } static inline Aig_Obj_t * Ssw_ObjChild0Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Ssw_ObjChild1Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL; } static inline Aig_Obj_t * Ssw_ObjFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { return (Aig_Obj_t *)Vec_PtrGetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id ); } static inline void Ssw_ObjSetFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { Vec_PtrSetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id, pNode ); } static inline Aig_Obj_t * Ssw_ObjChild0Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Ssw_ObjChild1Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== sswAig.c ===================================================*/ extern Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig ); extern void Ssw_FrmStop( Ssw_Frm_t * p ); extern Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ); extern Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p ); /*=== sswBmc.c ===================================================*/ /*=== sswClass.c =================================================*/ extern Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig ); extern void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData, unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ); extern void Ssw_ClassesStop( Ssw_Cla_t * p ); extern Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p ); extern Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p ); extern void Ssw_ClassesClearRefined( Ssw_Cla_t * p ); extern int Ssw_ClassesCand1Num( Ssw_Cla_t * p ); extern int Ssw_ClassesClassNum( Ssw_Cla_t * p ); extern int Ssw_ClassesLitNum( Ssw_Cla_t * p ); extern Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize ); extern void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass ); extern void Ssw_ClassesCheck( Ssw_Cla_t * p ); extern void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose ); extern void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj ); extern Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose ); extern Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs ); extern Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig ); extern Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig ); extern Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses ); extern Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs ); extern int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive ); extern int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive ); extern int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive ); extern int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive ); extern int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive ); extern int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr ); /*=== sswCnf.c ===================================================*/ extern Ssw_Sat_t * Ssw_SatStart( int fPolarFlip ); extern void Ssw_SatStop( Ssw_Sat_t * p ); extern void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj ); extern int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObjFraig ); /*=== sswConstr.c ===================================================*/ extern int Ssw_ManSweepBmcConstr( Ssw_Man_t * p ); extern int Ssw_ManSweepConstr( Ssw_Man_t * p ); extern void Ssw_ManRefineByConstrSim( Ssw_Man_t * p ); /*=== sswCore.c ===================================================*/ extern Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p ); /*=== sswDyn.c ===================================================*/ extern void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj ); extern int Ssw_ManSweepDyn( Ssw_Man_t * p ); /*=== sswLcorr.c ==========================================================*/ extern int Ssw_ManSweepLatch( Ssw_Man_t * p ); /*=== sswMan.c ===================================================*/ extern Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); extern void Ssw_ManCleanup( Ssw_Man_t * p ); extern void Ssw_ManStop( Ssw_Man_t * p ); /*=== sswSat.c ===================================================*/ extern int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); extern int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); extern int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj ); /*=== sswSemi.c ===================================================*/ extern int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose ); /*=== sswSim.c ===================================================*/ extern unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ); extern int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ); extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); extern int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj ); extern int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); extern void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ); extern Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ); extern void Ssw_SmlClean( Ssw_Sml_t * p ); extern void Ssw_SmlStop( Ssw_Sml_t * p ); extern void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ); extern void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame ); extern void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat ); extern void Ssw_SmlSimulateOne( Ssw_Sml_t * p ); extern void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p ); extern void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter ); extern void Ssw_SmlResimulateSeq( Ssw_Sml_t * p ); /*=== sswSimSat.c ===================================================*/ extern void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ); extern void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f ); /*=== sswSweep.c ===================================================*/ extern int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ); extern void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f ); extern int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs ); extern int Ssw_ManSweepBmc( Ssw_Man_t * p ); extern int Ssw_ManSweep( Ssw_Man_t * p ); /*=== sswUnique.c ===================================================*/ extern void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p ); extern int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose ); extern int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswIslands.c000066400000000000000000000454501300674244400243030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswIslands.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Detection of islands of difference.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswIslands.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates pair of structurally equivalent nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { pObj0->pData = pObj1; pObj1->pData = pObj0; Vec_IntPush( vPairs, pObj0->Id ); Vec_IntPush( vPairs, pObj1->Id ); } /**Function************************************************************* Synopsis [Establishes relationship between nodes using pairing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_MatchingStart( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs ) { Aig_Obj_t * pObj0, * pObj1; int i; // create matching Aig_ManCleanData( p0 ); Aig_ManCleanData( p1 ); for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) { pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) ); pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) ); assert( pObj0->pData == NULL ); assert( pObj1->pData == NULL ); pObj0->pData = pObj1; pObj1->pData = pObj0; } // make sure constants are matched pObj0 = Aig_ManConst1( p0 ); pObj1 = Aig_ManConst1( p1 ); assert( pObj0->pData == pObj1 ); assert( pObj1->pData == pObj0 ); // make sure PIs are matched Saig_ManForEachPi( p0, pObj0, i ) { pObj1 = Aig_ManCi( p1, i ); assert( pObj0->pData == pObj1 ); assert( pObj1->pData == pObj0 ); } // make sure the POs are not matched Aig_ManForEachCo( p0, pObj0, i ) { pObj1 = Aig_ManCo( p1, i ); assert( pObj0->pData == NULL ); assert( pObj1->pData == NULL ); } // check that LIs/LOs are matched in sync Saig_ManForEachLo( p0, pObj0, i ) { if ( pObj0->pData == NULL ) continue; pObj1 = (Aig_Obj_t *)pObj0->pData; if ( !Saig_ObjIsLo(p1, pObj1) ) Abc_Print( 1, "Mismatch between LO pairs.\n" ); } Saig_ManForEachLo( p1, pObj1, i ) { if ( pObj1->pData == NULL ) continue; pObj0 = (Aig_Obj_t *)pObj1->pData; if ( !Saig_ObjIsLo(p0, pObj0) ) Abc_Print( 1, "Mismatch between LO pairs.\n" ); } } /**Function************************************************************* Synopsis [Establishes relationship between nodes using pairing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_MatchingExtendOne( 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 ( pObj->pData != NULL ) continue; if ( Saig_ObjIsLo(p, pObj) ) { pNext = Saig_ObjLoToLi(p, pObj); pNext = Aig_ObjFanin0(pNext); if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) ) { Aig_ObjSetTravIdCurrent(p, pNext); Vec_PtrPush( vNodes, pNext ); } } if ( Aig_ObjIsNode(pObj) ) { pNext = Aig_ObjFanin0(pObj); if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) ) { Aig_ObjSetTravIdCurrent(p, pNext); Vec_PtrPush( vNodes, pNext ); } pNext = Aig_ObjFanin1(pObj); if ( pNext->pData && !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 ( pNext->pData && !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_MatchingCountUnmached( 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 ( pObj->pData != NULL ) continue; Counter++; } return Counter; } /**Function************************************************************* Synopsis [Establishes relationship between nodes using pairing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_MatchingExtend( 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; Aig_ManFanoutStart(p0); Aig_ManFanoutStart(p1); vNodes0 = Vec_PtrAlloc( 1000 ); vNodes1 = Vec_PtrAlloc( 1000 ); if ( fVerbose ) { int nUnmached = Ssw_MatchingCountUnmached(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_MatchingExtendOne( p0, vNodes0 ); Ssw_MatchingExtendOne( p1, vNodes1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k ) { pNext1 = (Aig_Obj_t *)pNext0->pData; if ( pNext1 == NULL ) continue; assert( pNext1->pData == pNext0 ); if ( Saig_ObjIsPi(p0, pNext1) ) continue; pNext0->pData = NULL; pNext1->pData = NULL; } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext0, k ) { pNext1 = (Aig_Obj_t *)pNext0->pData; if ( pNext1 == NULL ) continue; assert( pNext1->pData == pNext0 ); if ( Saig_ObjIsPi(p1, pNext1) ) continue; pNext0->pData = NULL; pNext1->pData = NULL; } if ( fVerbose ) { int nUnmached = Ssw_MatchingCountUnmached(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 ); Aig_ManFanoutStop(p0); Aig_ManFanoutStop(p1); } /**Function************************************************************* Synopsis [Used differences in p0 to complete p1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_MatchingComplete( Aig_Man_t * p0, Aig_Man_t * p1 ) { Vec_Ptr_t * vNewLis; Aig_Obj_t * pObj0, * pObj0Li, * pObj1; int i; // create register outputs in p0 that are absent in p1 vNewLis = Vec_PtrAlloc( 100 ); Saig_ManForEachLiLo( p0, pObj0Li, pObj0, i ) { if ( pObj0->pData != NULL ) continue; pObj1 = Aig_ObjCreateCi( p1 ); pObj0->pData = pObj1; pObj1->pData = pObj0; Vec_PtrPush( vNewLis, pObj0Li ); } // add missing nodes in the topological order Aig_ManForEachNode( p0, pObj0, i ) { if ( pObj0->pData != NULL ) continue; pObj1 = Aig_And( p1, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) ); pObj0->pData = pObj1; pObj1->pData = pObj0; } // create register outputs in p0 that are absent in p1 Vec_PtrForEachEntry( Aig_Obj_t *, vNewLis, pObj0Li, i ) Aig_ObjCreateCo( p1, Aig_ObjChild0Copy(pObj0Li) ); // increment the number of registers Aig_ManSetRegNum( p1, Aig_ManRegNum(p1) + Vec_PtrSize(vNewLis) ); Vec_PtrFree( vNewLis ); } /**Function************************************************************* Synopsis [Derives matching for all pairs.] Description [Modifies both AIGs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ssw_MatchingPairs( Aig_Man_t * p0, Aig_Man_t * p1 ) { Vec_Int_t * vPairsNew; Aig_Obj_t * pObj0, * pObj1; int i; // check correctness assert( Aig_ManCiNum(p0) == Aig_ManCiNum(p1) ); assert( Aig_ManCoNum(p0) == Aig_ManCoNum(p1) ); assert( Aig_ManRegNum(p0) == Aig_ManRegNum(p1) ); assert( Aig_ManObjNum(p0) == Aig_ManObjNum(p1) ); // create complete pairs vPairsNew = Vec_IntAlloc( 2*Aig_ManObjNum(p0) ); Aig_ManForEachObj( p0, pObj0, i ) { if ( Aig_ObjIsCo(pObj0) ) continue; pObj1 = (Aig_Obj_t *)pObj0->pData; Vec_IntPush( vPairsNew, pObj0->Id ); Vec_IntPush( vPairsNew, pObj1->Id ); } return vPairsNew; } /**Function************************************************************* Synopsis [Transfers the result of matching to miter.] Description [The array of pairs should be complete.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ssw_MatchingMiter( Aig_Man_t * pMiter, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairsAll ) { Vec_Int_t * vPairsMiter; Aig_Obj_t * pObj0, * pObj1; int i; // create matching of nodes in the miter vPairsMiter = Vec_IntAlloc( 2*Aig_ManObjNum(p0) ); for ( i = 0; i < Vec_IntSize(vPairsAll); i += 2 ) { pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairsAll, i) ); pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairsAll, i+1) ); assert( pObj0->pData != NULL ); assert( pObj1->pData != NULL ); if ( pObj0->pData == pObj1->pData ) continue; if ( Aig_ObjIsNone((Aig_Obj_t *)pObj0->pData) || Aig_ObjIsNone((Aig_Obj_t *)pObj1->pData) ) continue; // get the miter nodes pObj0 = (Aig_Obj_t *)pObj0->pData; pObj1 = (Aig_Obj_t *)pObj1->pData; assert( !Aig_IsComplement(pObj0) ); assert( !Aig_IsComplement(pObj1) ); assert( Aig_ObjType(pObj0) == Aig_ObjType(pObj1) ); if ( Aig_ObjIsCo(pObj0) ) continue; assert( Aig_ObjIsNode(pObj0) || Saig_ObjIsLo(pMiter, pObj0) ); assert( Aig_ObjIsNode(pObj1) || Saig_ObjIsLo(pMiter, pObj1) ); assert( pObj0->Id < pObj1->Id ); Vec_IntPush( vPairsMiter, pObj0->Id ); Vec_IntPush( vPairsMiter, pObj1->Id ); } return vPairsMiter; } /**Function************************************************************* Synopsis [Solves SEC using structural similarity.] Description [Modifies both p0 and p1 by adding extra logic.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_SecWithSimilaritySweep( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ) { Ssw_Man_t * p; Vec_Int_t * vPairsAll, * vPairsMiter; Aig_Man_t * pMiter, * pAigNew; // derive full matching Ssw_MatchingStart( p0, p1, vPairs ); if ( pPars->nIsleDist ) Ssw_MatchingExtend( p0, p1, pPars->nIsleDist, pPars->fVerbose ); Ssw_MatchingComplete( p0, p1 ); Ssw_MatchingComplete( p1, p0 ); vPairsAll = Ssw_MatchingPairs( p0, p1 ); // create miter and transfer matching pMiter = Saig_ManCreateMiter( p0, p1, 0 ); vPairsMiter = Ssw_MatchingMiter( pMiter, p0, p1, vPairsAll ); Vec_IntFree( vPairsAll ); // start the induction manager p = Ssw_ManCreate( pMiter, pPars ); // create equivalence classes using these IDs if ( p->pPars->fPartSigCorr ) p->ppClasses = Ssw_ClassesPreparePairsSimple( pMiter, vPairsMiter ); else p->ppClasses = Ssw_ClassesPrepare( pMiter, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose ); if ( p->pPars->fDumpSRInit ) { if ( p->pPars->fPartSigCorr ) { Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p ); Aig_ManDumpBlif( pSRed, "srm_part.blif", NULL, NULL ); Aig_ManStop( pSRed ); Abc_Print( 1, "Speculatively reduced miter is saved in file \"%s\".\n", "srm_part.blif" ); } else Abc_Print( 1, "Dumping speculative miter is possible only for partial signal correspondence (switch \"-c\").\n" ); } p->pSml = Ssw_SmlStart( pMiter, 0, 1 + p->pPars->nFramesAddSim, 1 ); Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); // perform refinement of classes pAigNew = Ssw_SignalCorrespondenceRefine( p ); // cleanup Ssw_ManStop( p ); Aig_ManStop( pMiter ); Vec_IntFree( vPairsMiter ); return pAigNew; } /**Function************************************************************* Synopsis [Solves SEC with structural similarity.] Description [The first two arguments are pointers to the AIG managers. The third argument is the array of pairs of IDs of structurally equivalent nodes from the first and second managers, respectively.] SideEffects [The managers will be updated by adding "islands of difference".] SeeAlso [] ***********************************************************************/ int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars ) { Ssw_Pars_t Pars; Aig_Man_t * pAigRes; int RetValue; abctime clk = Abc_Clock(); // derive parameters if not given if ( pPars == NULL ) Ssw_ManSetDefaultParams( pPars = &Pars ); // reduce the AIG with pairs pAigRes = Ssw_SecWithSimilaritySweep( p0, p1, vPairs, pPars ); // report the result of verification RetValue = Ssw_MiterStatus( pAigRes, 1 ); if ( RetValue == 1 ) Abc_Print( 1, "Verification successful. " ); else if ( RetValue == 0 ) Abc_Print( 1, "Verification failed with a counter-example. " ); else Abc_Print( 1, "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0)+Aig_ManRegNum(p1) ); ABC_PRT( "Time", Abc_Clock() - clk ); Aig_ManStop( pAigRes ); return RetValue; } /**Function************************************************************* Synopsis [Dummy procedure to detect structural similarity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_StrSimPerformMatching_hack( Aig_Man_t * p0, Aig_Man_t * p1 ) { Vec_Int_t * vPairs; Aig_Obj_t * pObj; int i; // create array of pairs vPairs = Vec_IntAlloc( 100 ); Aig_ManForEachObj( p0, pObj, i ) { if ( !Aig_ObjIsConst1(pObj) && !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) continue; Vec_IntPush( vPairs, i ); Vec_IntPush( vPairs, i ); } return vPairs; } /**Function************************************************************* Synopsis [Solves SEC with structural similarity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars ) { Vec_Int_t * vPairs; Aig_Man_t * pPart0, * pPart1; int RetValue; if ( pPars->fVerbose ) Abc_Print( 1, "Performing sequential verification using structural similarity.\n" ); // consider the case when a miter is given if ( p1 == NULL ) { if ( pPars->fVerbose ) { Aig_ManPrintStats( p0 ); } // demiter the miter if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) { Abc_Print( 1, "Demitering has failed.\n" ); return -1; } } else { pPart0 = Aig_ManDupSimple( p0 ); pPart1 = Aig_ManDupSimple( p1 ); } if ( pPars->fVerbose ) { // Aig_ManPrintStats( pPart0 ); // Aig_ManPrintStats( pPart1 ); if ( p1 == NULL ) { // Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL ); // Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); // Abc_Print( 1, "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) ); // derive pairs // vPairs = Saig_StrSimPerformMatching_hack( pPart0, pPart1 ); vPairs = Saig_StrSimPerformMatching( pPart0, pPart1, 0, pPars->fVerbose, NULL ); RetValue = Ssw_SecWithSimilarityPairs( pPart0, pPart1, vPairs, pPars ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); Vec_IntFree( vPairs ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswLcorr.c000066400000000000000000000244371300674244400237710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswLcorr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Latch correspondence.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswLcorr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" //#include "bar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Tranfers simulation information from FRAIG to AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManSweepTransfer( Ssw_Man_t * p ) { Aig_Obj_t * pObj, * pObjFraig; unsigned * pInfo; int i; // transfer simulation information Aig_ManForEachCi( p->pAig, pObj, i ) { pObjFraig = Ssw_ObjFrame( p, pObj, 0 ); if ( pObjFraig == Aig_ManConst0(p->pFrames) ) { Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 ); continue; } assert( !Aig_IsComplement(pObjFraig) ); assert( Aig_ObjIsCi(pObjFraig) ); pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObjFraig) ); Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 ); } } /**Function************************************************************* Synopsis [Performs one round of simulation with counter-examples.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepResimulate( Ssw_Man_t * p ) { int RetValue1, RetValue2; abctime clk = Abc_Clock(); // transfer PI simulation information from storage Ssw_ManSweepTransfer( p ); // simulate internal nodes Ssw_SmlSimulateOneFrame( p->pSml ); // check equivalence classes RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); // prepare simulation info for the next round Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); p->nPatterns = 0; p->nSimRounds++; p->timeSimSat += Abc_Clock() - clk; return RetValue1 > 0 || RetValue2 > 0; } /**Function************************************************************* Synopsis [Saves one counter-example into internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlAddPattern( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pCand ) { Aig_Obj_t * pObj; unsigned * pInfo; int i, nVarNum, Value; Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i ) { nVarNum = Ssw_ObjSatNum( p->pMSat, pObj ); assert( nVarNum > 0 ); Value = sat_solver_var_value( p->pMSat->pSat, nVarNum ); if ( Value == 0 ) continue; pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObj) ); Abc_InfoSetBit( pInfo, p->nPatterns ); } } /**Function************************************************************* Synopsis [Builds fraiged logic cone of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManBuildCone_rec( Ssw_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjNew; assert( !Aig_IsComplement(pObj) ); if ( Ssw_ObjFrame( p, pObj, 0 ) ) return; assert( Aig_ObjIsNode(pObj) ); Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObj) ); Ssw_ManBuildCone_rec( p, Aig_ObjFanin1(pObj) ); pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) ); Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); } /**Function************************************************************* Synopsis [Recycles the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManSweepLatchOne( Ssw_Man_t * p, Aig_Obj_t * pObjRepr, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjFraig, * pObjReprFraig, * pObjLi; int RetValue; abctime clk; assert( Aig_ObjIsCi(pObj) ); assert( Aig_ObjIsCi(pObjRepr) || Aig_ObjIsConst1(pObjRepr) ); // check if it makes sense to skip some calls if ( p->nCallsCount > 100 && p->nCallsUnsat < p->nCallsSat ) { if ( ++p->nCallsDelta < 0 ) return; } p->nCallsDelta = 0; clk = Abc_Clock(); // get the fraiged node pObjLi = Saig_ObjLoToLi( p->pAig, pObj ); Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) ); pObjFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 ); // get the fraiged representative if ( Aig_ObjIsCi(pObjRepr) ) { pObjLi = Saig_ObjLoToLi( p->pAig, pObjRepr ); Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) ); pObjReprFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 ); } else pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, 0 ); p->timeReduce += Abc_Clock() - clk; // if the fraiged nodes are the same, return if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) return; p->nRecycleCalls++; p->nCallsCount++; // check equivalence of the two nodes if ( (pObj->fPhase == pObjRepr->fPhase) != (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ) { p->nPatterns++; p->nStrangers++; p->fRefined = 1; } else { RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); if ( RetValue == 1 ) // proved equivalence { p->nCallsUnsat++; return; } if ( RetValue == -1 ) // timed out { Ssw_ClassesRemoveNode( p->ppClasses, pObj ); p->nCallsUnsat++; p->fRefined = 1; return; } else // disproved equivalence { Ssw_SmlAddPattern( p, pObjRepr, pObj ); p->nPatterns++; p->nCallsSat++; p->fRefined = 1; } } } /**Function************************************************************* Synopsis [Performs one iteration of sweeping latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepLatch( Ssw_Man_t * p ) { // Bar_Progress_t * pProgress = NULL; Vec_Ptr_t * vClass; Aig_Obj_t * pObj, * pRepr, * pTemp; int i, k; // start the timeframe p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) ); // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreateCi(p->pFrames) ); // implement equivalence classes Saig_ManForEachLo( p->pAig, pObj, i ) { pRepr = Aig_ObjRepr( p->pAig, pObj ); if ( pRepr == NULL ) { pTemp = Aig_ObjCreateCi(p->pFrames); pTemp->pData = pObj; } else pTemp = Aig_NotCond( Ssw_ObjFrame(p, pRepr, 0), pRepr->fPhase ^ pObj->fPhase ); Ssw_ObjSetFrame( p, pObj, 0, pTemp ); } Aig_ManSetCioIds( p->pFrames ); // prepare simulation info assert( p->vSimInfo == NULL ); p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManCiNum(p->pFrames), 1 ); Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 ); // go through the registers // if ( p->pPars->fVerbose ) // pProgress = Bar_ProgressStart( stdout, Aig_ManRegNum(p->pAig) ); vClass = Vec_PtrAlloc( 100 ); p->fRefined = 0; p->nCallsCount = p->nCallsSat = p->nCallsUnsat = 0; Saig_ManForEachLo( p->pAig, pObj, i ) { // if ( p->pPars->fVerbose ) // Bar_ProgressUpdate( pProgress, i, NULL ); // consider the case of constant candidate if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) Ssw_ManSweepLatchOne( p, Aig_ManConst1(p->pAig), pObj ); else { // consider the case of equivalence class Ssw_ClassesCollectClass( p->ppClasses, pObj, vClass ); if ( Vec_PtrSize(vClass) == 0 ) continue; // try to prove equivalences in this class Vec_PtrForEachEntry( Aig_Obj_t *, vClass, pTemp, k ) if ( Aig_ObjRepr(p->pAig, pTemp) == pObj ) { Ssw_ManSweepLatchOne( p, pObj, pTemp ); if ( p->nPatterns == 32 ) break; } } // resimulate if ( p->nPatterns == 32 ) Ssw_ManSweepResimulate( p ); // attempt recycling the SAT solver if ( p->pPars->nSatVarMax && p->pMSat->nSatVars > p->pPars->nSatVarMax && p->nRecycleCalls > p->pPars->nRecycleCalls ) { p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars ); p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls ); Ssw_SatStop( p->pMSat ); p->pMSat = Ssw_SatStart( 0 ); p->nRecycles++; p->nRecycleCalls = 0; } } // ABC_PRT( "reduce", p->timeReduce ); // Aig_TableProfile( p->pFrames ); // Abc_Print( 1, "And gates = %d\n", Aig_ManNodeNum(p->pFrames) ); // resimulate if ( p->nPatterns > 0 ) Ssw_ManSweepResimulate( p ); // cleanup Vec_PtrFree( vClass ); // if ( p->pPars->fVerbose ) // Bar_ProgressStop( pProgress ); // cleanup // Ssw_ClassesCheck( p->ppClasses ); return p->fRefined; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswMan.c000066400000000000000000000170351300674244400234170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Calls to the SAT solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswMan.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) { Ssw_Man_t * p; // prepare the sequential AIG assert( Saig_ManRegNum(pAig) > 0 ); Aig_ManFanoutStart( pAig ); Aig_ManSetCioIds( pAig ); // create interpolation manager p = ABC_ALLOC( Ssw_Man_t, 1 ); memset( p, 0, sizeof(Ssw_Man_t) ); p->pPars = pPars; p->pAig = pAig; p->nFrames = pPars->nFramesK + 1; p->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * p->nFrames ); p->vCommon = Vec_PtrAlloc( 100 ); p->iOutputLit = -1; // allocate storage for sim pattern p->nPatWords = Abc_BitWordNum( Saig_ManPiNum(pAig) * p->nFrames + Saig_ManRegNum(pAig) ); p->pPatWords = ABC_CALLOC( unsigned, p->nPatWords ); // other p->vNewLos = Vec_PtrAlloc( 100 ); p->vNewPos = Vec_IntAlloc( 100 ); p->vResimConsts = Vec_PtrAlloc( 100 ); p->vResimClasses = Vec_PtrAlloc( 100 ); // p->pPars->fVerbose = 1; return p; } /**Function************************************************************* Synopsis [Prints stats of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManCountEquivs( Ssw_Man_t * p ) { Aig_Obj_t * pObj; int i, nEquivs = 0; Aig_ManForEachObj( p->pAig, pObj, i ) nEquivs += ( Aig_ObjRepr(p->pAig, pObj) != NULL ); return nEquivs; } /**Function************************************************************* Synopsis [Prints stats of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManPrintStats( Ssw_Man_t * p ) { double nMemory = 1.0*Aig_ManObjNumMax(p->pAig)*p->nFrames*(2*sizeof(int)+2*sizeof(void*))/(1<<20); Abc_Print( 1, "Parameters: F = %d. AddF = %d. C-lim = %d. Constr = %d. MaxLev = %d. Mem = %0.2f MB.\n", p->pPars->nFramesK, p->pPars->nFramesAddSim, p->pPars->nBTLimit, Saig_ManConstrNum(p->pAig), p->pPars->nMaxLevs, nMemory ); Abc_Print( 1, "AIG : PI = %d. PO = %d. Latch = %d. Node = %d. Ave SAT vars = %d.\n", Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), Saig_ManRegNum(p->pAig), Aig_ManNodeNum(p->pAig), 0/(p->pPars->nIters+1) ); Abc_Print( 1, "SAT calls : Proof = %d. Cex = %d. Fail = %d. Lits proved = %d.\n", p->nSatProof, p->nSatCallsSat, p->nSatFailsReal, Ssw_ManCountEquivs(p) ); Abc_Print( 1, "SAT solver: Vars max = %d. Calls max = %d. Recycles = %d. Sim rounds = %d.\n", p->nVarsMax, p->nCallsMax, p->nRecyclesTotal, p->nSimRounds ); Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1), p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) ); p->timeOther = p->timeTotal-p->timeBmc-p->timeReduce-p->timeMarkCones-p->timeSimSat-p->timeSat; ABC_PRTP( "BMC ", p->timeBmc, p->timeTotal ); ABC_PRTP( "Spec reduce", p->timeReduce, p->timeTotal ); ABC_PRTP( "Mark cones ", p->timeMarkCones, p->timeTotal ); ABC_PRTP( "Sim SAT ", p->timeSimSat, p->timeTotal ); ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal ); ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); ABC_PRTP( " undecided", p->timeSatUndec, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); // report the reductions if ( p->pAig->nConstrs ) { Abc_Print( 1, "Statistics reflecting the use of constraints:\n" ); Abc_Print( 1, "Total cones = %6d. Constraint cones = %6d. (%6.2f %%)\n", p->nConesTotal, p->nConesConstr, 100.0*p->nConesConstr/p->nConesTotal ); Abc_Print( 1, "Total equivs = %6d. Removed equivs = %6d. (%6.2f %%)\n", p->nEquivsTotal, p->nEquivsConstr, 100.0*p->nEquivsConstr/p->nEquivsTotal ); Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", p->nNodesBegC, p->nNodesEndC, 100.0*(p->nNodesBegC-p->nNodesEndC)/(p->nNodesBegC?p->nNodesBegC:1), p->nRegsBegC, p->nRegsEndC, 100.0*(p->nRegsBegC-p->nRegsEndC)/(p->nRegsBegC?p->nRegsBegC:1) ); } } /**Function************************************************************* Synopsis [Frees the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManCleanup( Ssw_Man_t * p ) { // Aig_ManCleanMarkAB( p->pAig ); assert( p->pMSat == NULL ); if ( p->pFrames ) { Aig_ManCleanMarkAB( p->pFrames ); Aig_ManStop( p->pFrames ); p->pFrames = NULL; memset( p->pNodeToFrames, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) * p->nFrames ); } if ( p->vSimInfo ) { Vec_PtrFree( p->vSimInfo ); p->vSimInfo = NULL; } p->nConstrTotal = 0; p->nConstrReduced = 0; } /**Function************************************************************* Synopsis [Frees the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManStop( Ssw_Man_t * p ) { ABC_FREE( p->pVisited ); if ( p->pPars->fVerbose )//&& p->pPars->nStepsMax == -1 ) Ssw_ManPrintStats( p ); if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses ); if ( p->pSml ) Ssw_SmlStop( p->pSml ); if ( p->vDiffPairs ) Vec_IntFree( p->vDiffPairs ); if ( p->vInits ) Vec_IntFree( p->vInits ); Vec_PtrFree( p->vResimConsts ); Vec_PtrFree( p->vResimClasses ); Vec_PtrFree( p->vNewLos ); Vec_IntFree( p->vNewPos ); Vec_PtrFree( p->vCommon ); ABC_FREE( p->pNodeToFrames ); ABC_FREE( p->pPatWords ); ABC_FREE( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswPairs.c000066400000000000000000000400011300674244400237470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswPairs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Calls to the SAT solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswPairs.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reports the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose ) { Aig_Obj_t * pObj, * pChild; int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; // if ( p->pData ) // return 0; Saig_ManForEachPo( p, pObj, i ) { pChild = Aig_ObjChild0(pObj); // check if the output is constant 0 if ( pChild == Aig_ManConst0(p) ) { CountConst0++; continue; } // check if the output is constant 1 if ( pChild == Aig_ManConst1(p) ) { CountNonConst0++; continue; } // check if the output is a primary input if ( p->nRegs == 0 && Aig_ObjIsCi(Aig_Regular(pChild)) ) { CountNonConst0++; continue; } // check if the output can be not constant 0 if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) { CountNonConst0++; continue; } CountUndecided++; } if ( fVerbose ) { Abc_Print( 1, "Miter has %d outputs. ", Saig_ManPoNum(p) ); Abc_Print( 1, "Const0 = %d. ", CountConst0 ); Abc_Print( 1, "NonConst0 = %d. ", CountNonConst0 ); Abc_Print( 1, "Undecided = %d. ", CountUndecided ); Abc_Print( 1, "\n" ); } if ( CountNonConst0 ) return 0; if ( CountUndecided ) return -1; return 1; } /**Function************************************************************* Synopsis [Transfer equivalent pairs to the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ssw_TransferSignalPairs( Aig_Man_t * pMiter, Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2 ) { Vec_Int_t * vIds; Aig_Obj_t * pObj1, * pObj2; Aig_Obj_t * pObj1m, * pObj2m; int i; vIds = Vec_IntAlloc( 2 * Vec_IntSize(vIds1) ); for ( i = 0; i < Vec_IntSize(vIds1); i++ ) { pObj1 = Aig_ManObj( pAig1, Vec_IntEntry(vIds1, i) ); pObj2 = Aig_ManObj( pAig2, Vec_IntEntry(vIds2, i) ); pObj1m = Aig_Regular((Aig_Obj_t *)pObj1->pData); pObj2m = Aig_Regular((Aig_Obj_t *)pObj2->pData); assert( pObj1m && pObj2m ); if ( pObj1m == pObj2m ) continue; if ( pObj1m->Id < pObj2m->Id ) { Vec_IntPush( vIds, pObj1m->Id ); Vec_IntPush( vIds, pObj2m->Id ); } else { Vec_IntPush( vIds, pObj2m->Id ); Vec_IntPush( vIds, pObj1m->Id ); } } return vIds; } /**Function************************************************************* Synopsis [Transform pairs into class representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t ** Ssw_TransformPairsIntoTempClasses( Vec_Int_t * vPairs, int nObjNumMax ) { Vec_Int_t ** pvClasses; // vector of classes int * pReprs; // mapping nodes into their representatives int Entry, idObj, idRepr, idReprObj, idReprRepr, i; // allocate data-structures pvClasses = ABC_CALLOC( Vec_Int_t *, nObjNumMax ); pReprs = ABC_ALLOC( int, nObjNumMax ); for ( i = 0; i < nObjNumMax; i++ ) pReprs[i] = -1; // consider pairs for ( i = 0; i < Vec_IntSize(vPairs); i += 2 ) { // get both objects idRepr = Vec_IntEntry( vPairs, i ); idObj = Vec_IntEntry( vPairs, i+1 ); assert( idObj > 0 ); assert( (pReprs[idRepr] == -1) || (pvClasses[pReprs[idRepr]] != NULL) ); assert( (pReprs[idObj] == -1) || (pvClasses[pReprs[idObj] ] != NULL) ); // get representatives of both objects idReprRepr = pReprs[idRepr]; idReprObj = pReprs[idObj]; // check different situations if ( idReprRepr == -1 && idReprObj == -1 ) { // they do not have classes // create a class pvClasses[idRepr] = Vec_IntAlloc( 4 ); Vec_IntPush( pvClasses[idRepr], idRepr ); Vec_IntPush( pvClasses[idRepr], idObj ); pReprs[ idRepr ] = idRepr; pReprs[ idObj ] = idRepr; } else if ( idReprRepr >= 0 && idReprObj == -1 ) { // representative has a class // add iObj to the same class Vec_IntPushUniqueOrder( pvClasses[idReprRepr], idObj ); pReprs[ idObj ] = idReprRepr; } else if ( idReprRepr == -1 && idReprObj >= 0 ) { // object has a class assert( idReprObj != idRepr ); if ( idReprObj < idRepr ) { // add idRepr to the same class Vec_IntPushUniqueOrder( pvClasses[idReprObj], idRepr ); pReprs[ idRepr ] = idReprObj; } else // if ( idReprObj > idRepr ) { // make idRepr new representative Vec_IntPushFirst( pvClasses[idReprObj], idRepr ); pvClasses[idRepr] = pvClasses[idReprObj]; pvClasses[idReprObj] = NULL; // set correct representatives of each node Vec_IntForEachEntry( pvClasses[idRepr], Entry, i ) pReprs[ Entry ] = idRepr; } } else // if ( idReprRepr >= 0 && idReprObj >= 0 ) { // both have classes if ( idReprRepr == idReprObj ) { // the classes are the same // nothing to do } else { // the classes are different // find the repr of the new class if ( idReprRepr < idReprObj ) { Vec_IntForEachEntry( pvClasses[idReprObj], Entry, i ) { Vec_IntPushUniqueOrder( pvClasses[idReprRepr], Entry ); pReprs[ Entry ] = idReprRepr; } Vec_IntFree( pvClasses[idReprObj] ); pvClasses[idReprObj] = NULL; } else // if ( idReprRepr > idReprObj ) { Vec_IntForEachEntry( pvClasses[idReprRepr], Entry, i ) { Vec_IntPushUniqueOrder( pvClasses[idReprObj], Entry ); pReprs[ Entry ] = idReprObj; } Vec_IntFree( pvClasses[idReprRepr] ); pvClasses[idReprRepr] = NULL; } } } } ABC_FREE( pReprs ); return pvClasses; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_FreeTempClasses( Vec_Int_t ** pvClasses, int nObjNumMax ) { int i; for ( i = 0; i < nObjNumMax; i++ ) if ( pvClasses[i] ) Vec_IntFree( pvClasses[i] ); ABC_FREE( pvClasses ); } /**Function************************************************************* Synopsis [Performs signal correspondence for the miter of two AIGs with node pairs defined.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_SignalCorrespondenceWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ) { Ssw_Man_t * p; Aig_Man_t * pAigNew, * pMiter; Ssw_Pars_t Pars; Vec_Int_t * vPairs; Vec_Int_t ** pvClasses; assert( Vec_IntSize(vIds1) == Vec_IntSize(vIds2) ); // create sequential miter pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 ); Aig_ManCleanup( pMiter ); // transfer information to the miter vPairs = Ssw_TransferSignalPairs( pMiter, pAig1, pAig2, vIds1, vIds2 ); // create representation of the classes pvClasses = Ssw_TransformPairsIntoTempClasses( vPairs, Aig_ManObjNumMax(pMiter) ); Vec_IntFree( vPairs ); // if parameters are not given, create them if ( pPars == NULL ) Ssw_ManSetDefaultParams( pPars = &Pars ); // start the induction manager p = Ssw_ManCreate( pMiter, pPars ); // create equivalence classes using these IDs p->ppClasses = Ssw_ClassesPreparePairs( pMiter, pvClasses ); p->pSml = Ssw_SmlStart( pMiter, 0, p->nFrames + p->pPars->nFramesAddSim, 1 ); Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); // perform refinement of classes pAigNew = Ssw_SignalCorrespondenceRefine( p ); // cleanup Ssw_FreeTempClasses( pvClasses, Aig_ManObjNumMax(pMiter) ); Ssw_ManStop( p ); Aig_ManStop( pMiter ); return pAigNew; } /**Function************************************************************* Synopsis [Runs inductive SEC for the miter of two AIGs with node pairs defined.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig ) { Aig_Man_t * pAigNew, * pAigRes; Ssw_Pars_t Pars, * pPars = &Pars; Vec_Int_t * vIds1, * vIds2; Aig_Obj_t * pObj, * pRepr; int RetValue, i; abctime clk = Abc_Clock(); Ssw_ManSetDefaultParams( pPars ); pPars->fVerbose = 1; pAigNew = Ssw_SignalCorrespondence( pAig, pPars ); // record pairs of equivalent nodes vIds1 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) ); vIds2 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) ); Aig_ManForEachObj( pAig, pObj, i ) { pRepr = Aig_Regular((Aig_Obj_t *)pObj->pData); if ( pRepr == NULL ) continue; if ( Aig_ManObj(pAigNew, pRepr->Id) == NULL ) continue; /* if ( Aig_ObjIsNode(pObj) ) Abc_Print( 1, "n " ); else if ( Saig_ObjIsPi(pAig, pObj) ) Abc_Print( 1, "pi " ); else if ( Saig_ObjIsLo(pAig, pObj) ) Abc_Print( 1, "lo " ); */ Vec_IntPush( vIds1, Aig_ObjId(pObj) ); Vec_IntPush( vIds2, Aig_ObjId(pRepr) ); } Abc_Print( 1, "Recorded %d pairs (before: %d after: %d).\n", Vec_IntSize(vIds1), Aig_ManObjNumMax(pAig), Aig_ManObjNumMax(pAigNew) ); // try the new AIGs pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig, pAigNew, vIds1, vIds2, pPars ); Vec_IntFree( vIds1 ); Vec_IntFree( vIds2 ); // report the results RetValue = Ssw_MiterStatus( pAigRes, 1 ); if ( RetValue == 1 ) Abc_Print( 1, "Verification successful. " ); else if ( RetValue == 0 ) Abc_Print( 1, "Verification failed with the counter-example. " ); else Abc_Print( 1, "Verification UNDECIDED. Remaining registers %d (total %d). ", Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig) + Aig_ManRegNum(pAigNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); // cleanup Aig_ManStop( pAigNew ); return pAigRes; } /**Function************************************************************* Synopsis [Runs inductive SEC for the miter of two AIGs with node pairs defined.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars ) { Aig_Man_t * pAigRes; int RetValue; abctime clk = Abc_Clock(); assert( vIds1 != NULL && vIds2 != NULL ); // try the new AIGs Abc_Print( 1, "Performing specialized verification with node pairs.\n" ); pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig1, pAig2, vIds1, vIds2, pPars ); // report the results RetValue = Ssw_MiterStatus( pAigRes, 1 ); if ( RetValue == 1 ) Abc_Print( 1, "Verification successful. " ); else if ( RetValue == 0 ) Abc_Print( 1, "Verification failed with a counter-example. " ); else Abc_Print( 1, "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) ); ABC_PRT( "Time", Abc_Clock() - clk ); // cleanup Aig_ManStop( pAigRes ); return RetValue; } /**Function************************************************************* Synopsis [Runs inductive SEC for the miter of two AIGs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars ) { Aig_Man_t * pAigRes, * pMiter; int RetValue; abctime clk = Abc_Clock(); // try the new AIGs Abc_Print( 1, "Performing general verification without node pairs.\n" ); pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 ); Aig_ManCleanup( pMiter ); pAigRes = Ssw_SignalCorrespondence( pMiter, pPars ); Aig_ManStop( pMiter ); // report the results RetValue = Ssw_MiterStatus( pAigRes, 1 ); if ( RetValue == 1 ) Abc_Print( 1, "Verification successful. " ); else if ( RetValue == 0 ) Abc_Print( 1, "Verification failed with a counter-example. " ); else Abc_Print( 1, "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) ); ABC_PRT( "Time", Abc_Clock() - clk ); // cleanup Aig_ManStop( pAigRes ); return RetValue; } /**Function************************************************************* Synopsis [Runs inductive SEC for the miter of two AIGs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars ) { Aig_Man_t * pAigRes; int RetValue; abctime clk = Abc_Clock(); // try the new AIGs // Abc_Print( 1, "Performing general verification without node pairs.\n" ); pAigRes = Ssw_SignalCorrespondence( pMiter, pPars ); // report the results RetValue = Ssw_MiterStatus( pAigRes, 1 ); if ( RetValue == 1 ) Abc_Print( 1, "Verification successful. " ); else if ( RetValue == 0 ) Abc_Print( 1, "Verification failed with a counter-example. " ); else Abc_Print( 1, "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ", Aig_ManRegNum(pAigRes), Aig_ManRegNum(pMiter) ); ABC_PRT( "Time", Abc_Clock() - clk ); // cleanup Aig_ManStop( pAigRes ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswPart.c000066400000000000000000000120231300674244400236020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswPart.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Partitioned signal correspondence.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswPart.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" #include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs partitioned sequential SAT sweeping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) { int fPrintParts = 0; char Buffer[100]; Aig_Man_t * pTemp, * pNew; Vec_Ptr_t * vResult; Vec_Int_t * vPart; int * pMapBack; int i, nCountPis, nCountRegs; int nClasses, nPartSize, fVerbose; abctime clk = Abc_Clock(); if ( pPars->fConstrs ) { Abc_Print( 1, "Cannot use partitioned computation with constraints.\n" ); return NULL; } // save parameters nPartSize = pPars->nPartSize; pPars->nPartSize = 0; fVerbose = pPars->fVerbose; pPars->fVerbose = 0; // generate partitions if ( pAig->vClockDoms ) { // divide large clock domains into separate partitions vResult = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) { if ( nPartSize && Vec_IntSize(vPart) > nPartSize ) Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize ); else Vec_PtrPush( vResult, Vec_IntDup(vPart) ); } } else vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize ); // vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); // vResult = Aig_ManRegPartitionSmart( pAig, nPartSize ); if ( fPrintParts ) { // print partitions Abc_Print( 1, "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) ); Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) { // extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); sprintf( Buffer, "part%03d.aig", i ); pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL ); Ioa_WriteAiger( pTemp, Buffer, 0, 0 ); Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n", i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) ); Aig_ManStop( pTemp ); } } // perform SSW with partitions 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 ); // create the projection of 1-hot registers if ( pAig->vOnehots ) pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose ); // run SSW if (nCountPis>0) { pNew = Ssw_SignalCorrespondence( pTemp, pPars ); nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack ); if ( fVerbose ) Abc_Print( 1, "%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), pPars->nIters, nClasses ); Aig_ManStop( pNew ); } Aig_ManStop( pTemp ); ABC_FREE( pMapBack ); } // remap the AIG pNew = Aig_ManDupRepr( pAig, 0 ); Aig_ManSeqCleanup( pNew ); // Aig_ManPrintStats( pAig ); // Aig_ManPrintStats( pNew ); Vec_VecFree( (Vec_Vec_t *)vResult ); pPars->nPartSize = nPartSize; pPars->fVerbose = fVerbose; if ( fVerbose ) { ABC_PRT( "Total time", Abc_Clock() - clk ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswRarity.c000066400000000000000000001304751300674244400241620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswRarity.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Rarity-driven refinement of equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" #include "aig/gia/giaAig.h" #include "base/main/main.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Ssw_RarMan_t_ Ssw_RarMan_t; struct Ssw_RarMan_t_ { // parameters Ssw_RarPars_t* pPars; int nGroups; // the number of flop groups int nWordsReg; // the number of words in the registers // internal data Aig_Man_t * pAig; // AIG with equivalence classes Ssw_Cla_t * ppClasses; // equivalence classes Vec_Int_t * vInits; // initial state // simulation data word * pObjData; // simulation info for each obj word * pPatData; // pattern data for each reg // candidates to update Vec_Ptr_t * vUpdConst; // constant 1 candidates Vec_Ptr_t * vUpdClass; // class representatives // rarity data int * pRarity; // occur counts for patterns in groups double * pPatCosts; // pattern costs // best patterns Vec_Int_t * vPatBests; // best patterns int iFailPo; // failed primary output int iFailPat; // failed pattern // counter-examples Vec_Ptr_t * vCexes; }; static inline int Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) { assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->pPars->nBinSize ); assert( iPat >= 0 && iPat < (1 << p->pPars->nBinSize) ); return p->pRarity[iBin * (1 << p->pPars->nBinSize) + iPat]; } static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value ) { assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->pPars->nBinSize ); assert( iPat >= 0 && iPat < (1 << p->pPars->nBinSize) ); p->pRarity[iBin * (1 << p->pPars->nBinSize) + iPat] = Value; } static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) { assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->pPars->nBinSize ); assert( iPat >= 0 && iPat < (1 << p->pPars->nBinSize) ); p->pRarity[iBin * (1 << p->pPars->nBinSize) + iPat]++; } static inline int Ssw_RarBitWordNum( int nBits ) { return (nBits>>6) + ((nBits&63) > 0); } static inline word * Ssw_RarObjSim( Ssw_RarMan_t * p, int Id ) { assert( Id < Aig_ManObjNumMax(p->pAig) ); return p->pObjData + p->pPars->nWords * Id; } static inline word * Ssw_RarPatSim( Ssw_RarMan_t * p, int Id ) { assert( Id < 64 * p->pPars->nWords ); return p->pPatData + p->nWordsReg * Id; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_RarSetDefaultParams( Ssw_RarPars_t * p ) { memset( p, 0, sizeof(Ssw_RarPars_t) ); p->nFrames = 20; p->nWords = 50; p->nBinSize = 8; p->nRounds = 0; p->nRestart = 0; p->nRandSeed = 0; p->TimeOut = 0; p->TimeOutGap = 0; p->fSolveAll = 0; p->fDropSatOuts = 0; p->fSetLastState = 0; p->fVerbose = 0; p->fNotVerbose = 0; } /**Function************************************************************* Synopsis [Prepares random number generator.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_RarManPrepareRandom( int nRandSeed ) { int i; Aig_ManRandom( 1 ); for ( i = 0; i < nRandSeed; i++ ) Aig_ManRandom( 0 ); } /**Function************************************************************* Synopsis [Initializes random primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_RarManAssingRandomPis( Ssw_RarMan_t * p ) { word * pSim; Aig_Obj_t * pObj; int w, i; Saig_ManForEachPi( p->pAig, pObj, i ) { pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); for ( w = 0; w < p->pPars->nWords; w++ ) pSim[w] = Aig_ManRandom64(0); // pSim[0] <<= 1; // pSim[0] = (pSim[0] << 2) | 2; pSim[0] = (pSim[0] << 4) | ((i & 1) ? 0xA : 0xC); } } /**Function************************************************************* Synopsis [Derives the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Ssw_RarDeriveCex( Ssw_RarMan_t * p, int iFrame, int iPo, int iPatFinal, int fVerbose ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; Vec_Int_t * vTrace; word * pSim; int i, r, f, iBit, iPatThis; // compute the pattern sequence iPatThis = iPatFinal; vTrace = Vec_IntStartFull( iFrame / p->pPars->nFrames + 1 ); Vec_IntWriteEntry( vTrace, iFrame / p->pPars->nFrames, iPatThis ); for ( r = iFrame / p->pPars->nFrames - 1; r >= 0; r-- ) { iPatThis = Vec_IntEntry( p->vPatBests, r * p->pPars->nWords + iPatThis / 64 ); Vec_IntWriteEntry( vTrace, r, iPatThis ); } // create counter-example pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), iFrame+1 ); pCex->iFrame = iFrame; pCex->iPo = iPo; // insert the bits iBit = Aig_ManRegNum(p->pAig); for ( f = 0; f <= iFrame; f++ ) { Ssw_RarManAssingRandomPis( p ); iPatThis = Vec_IntEntry( vTrace, f / p->pPars->nFrames ); Saig_ManForEachPi( p->pAig, pObj, i ) { pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); if ( Abc_InfoHasBit( (unsigned *)pSim, iPatThis ) ) Abc_InfoSetBit( pCex->pData, iBit ); iBit++; } } Vec_IntFree( vTrace ); assert( iBit == pCex->nBits ); // verify the counter example if ( !Saig_ManVerifyCex( p->pAig, pCex ) ) { Abc_Print( 1, "Ssw_RarDeriveCex(): Counter-example is invalid.\n" ); // Abc_CexFree( pCex ); // pCex = NULL; } else { // Abc_Print( 1, "Counter-example verification is successful.\n" ); } return pCex; } /**Function************************************************************* Synopsis [Transposing 32-bit matrix.] Description [Borrowed from "Hacker's Delight", by Henry Warren.] SideEffects [] SeeAlso [] ***********************************************************************/ void transpose32( unsigned A[32] ) { int j, k; unsigned t, m = 0x0000FFFF; for ( j = 16; j != 0; j = j >> 1, m = m ^ (m << j) ) { for ( k = 0; k < 32; 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 [Transposing 64-bit matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 [Transposing 64-bit matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void transpose64Simple( word A[64], word B[64] ) { int i, k; for ( i = 0; i < 64; i++ ) B[i] = 0; for ( i = 0; i < 64; i++ ) for ( k = 0; k < 64; k++ ) if ( (A[i] >> k) & 1 ) B[k] |= ((word)1 << (63-i)); } /**Function************************************************************* Synopsis [Testing the transposing code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void TransposeTest() { word M[64], N[64]; int i; abctime clk; Aig_ManRandom64( 1 ); // for ( i = 0; i < 64; i++ ) // M[i] = Aig_ManRandom64( 0 ); for ( i = 0; i < 64; i++ ) M[i] = i? (word)0 : ~(word)0; // for ( i = 0; i < 64; i++ ) // Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), Abc_Print( 1, "\n" ); clk = Abc_Clock(); for ( i = 0; i < 100001; i++ ) transpose64Simple( M, N ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); clk = Abc_Clock(); for ( i = 0; i < 100001; i++ ) transpose64( M ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); for ( i = 0; i < 64; i++ ) if ( M[i] != N[i] ) Abc_Print( 1, "Mismatch\n" ); /* Abc_Print( 1, "\n" ); for ( i = 0; i < 64; i++ ) Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), Abc_Print( 1, "\n" ); Abc_Print( 1, "\n" ); for ( i = 0; i < 64; i++ ) Extra_PrintBinary( stdout, (unsigned *)&N[i], 64 ), Abc_Print( 1, "\n" ); */ } /**Function************************************************************* Synopsis [Transposing pObjData[ nRegs x nWords ] -> pPatData[ nWords x nRegs ].] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_RarTranspose( Ssw_RarMan_t * p ) { Aig_Obj_t * pObj; word M[64]; int w, r, i; for ( w = 0; w < p->pPars->nWords; w++ ) for ( r = 0; r < p->nWordsReg; r++ ) { // save input for ( i = 0; i < 64; i++ ) { if ( r*64 + 63-i < Aig_ManRegNum(p->pAig) ) { pObj = Saig_ManLi( p->pAig, r*64 + 63-i ); M[i] = Ssw_RarObjSim( p, Aig_ObjId(pObj) )[w]; } else M[i] = 0; } // transpose transpose64( M ); // save output for ( i = 0; i < 64; i++ ) Ssw_RarPatSim( p, w*64 + 63-i )[r] = M[i]; } /* Saig_ManForEachLi( p->pAig, pObj, i ) { word * pBitData = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); Extra_PrintBinary( stdout, (unsigned *)pBitData, 64*p->pPars->nWords ); Abc_Print( 1, "\n" ); } Abc_Print( 1, "\n" ); for ( i = 0; i < p->pPars->nWords*64; i++ ) { word * pBitData = Ssw_RarPatSim( p, i ); Extra_PrintBinary( stdout, (unsigned *)pBitData, Aig_ManRegNum(p->pAig) ); Abc_Print( 1, "\n" ); } Abc_Print( 1, "\n" ); */ } /**Function************************************************************* Synopsis [Sets random inputs and specialied flop outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_RarManInitialize( Ssw_RarMan_t * p, Vec_Int_t * vInit ) { Aig_Obj_t * pObj, * pObjLi; word * pSim, * pSimLi; int w, i; // constant pObj = Aig_ManConst1( p->pAig ); pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); for ( w = 0; w < p->pPars->nWords; w++ ) pSim[w] = ~(word)0; // primary inputs Ssw_RarManAssingRandomPis( p ); // flop outputs if ( vInit ) { assert( Vec_IntSize(vInit) == Saig_ManRegNum(p->pAig) * p->pPars->nWords ); Saig_ManForEachLo( p->pAig, pObj, i ) { pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); for ( w = 0; w < p->pPars->nWords; w++ ) pSim[w] = Vec_IntEntry(vInit, w * Saig_ManRegNum(p->pAig) + i) ? ~(word)0 : (word)0; } } else { Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i ) { pSimLi = Ssw_RarObjSim( p, Aig_ObjId(pObjLi) ); pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); for ( w = 0; w < p->pPars->nWords; w++ ) pSim[w] = pSimLi[w]; } } } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarManPoIsConst0( void * pMan, Aig_Obj_t * pObj ) { Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); int w; for ( w = 0; w < p->pPars->nWords; w++ ) if ( pSim[w] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarManObjIsConst( void * pMan, Aig_Obj_t * pObj ) { Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); word Flip = pObj->fPhase ? ~(word)0 : 0; int w; for ( w = 0; w < p->pPars->nWords; w++ ) if ( pSim[w] ^ Flip ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation infos are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarManObjsAreEqual( void * pMan, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; word * pSim0 = Ssw_RarObjSim( p, pObj0->Id ); word * pSim1 = Ssw_RarObjSim( p, pObj1->Id ); word Flip = (pObj0->fPhase != pObj1->fPhase) ? ~(word)0 : 0; int w; for ( w = 0; w < p->pPars->nWords; w++ ) if ( pSim0[w] ^ pSim1[w] ^ Flip ) return 0; return 1; } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ssw_RarManObjHashWord( void * pMan, Aig_Obj_t * pObj ) { Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan; 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; int i; uHash = 0; pSims = (unsigned *)Ssw_RarObjSim( p, pObj->Id ); for ( i = 0; i < 2 * p->pPars->nWords; i++ ) uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; return uHash; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarManObjWhichOne( Ssw_RarMan_t * p, Aig_Obj_t * pObj ) { word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); word Flip = 0;//pObj->fPhase ? ~(word)0 : 0; // bug fix! int w, i; for ( w = 0; w < p->pPars->nWords; w++ ) if ( pSim[w] ^ Flip ) { for ( i = 0; i < 64; i++ ) if ( ((pSim[w] ^ Flip) >> i) & 1 ) break; assert( i < 64 ); return w * 64 + i; } return -1; } /**Function************************************************************* Synopsis [Check if any of the POs becomes non-constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarManCheckNonConstOutputs( Ssw_RarMan_t * p, int iFrame, abctime Time ) { Aig_Obj_t * pObj; int i; p->iFailPo = -1; p->iFailPat = -1; Saig_ManForEachPo( p->pAig, pObj, i ) { if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs ) break; if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) ) continue; if ( Ssw_RarManPoIsConst0(p, pObj) ) continue; p->iFailPo = i; p->iFailPat = Ssw_RarManObjWhichOne( p, pObj ); if ( !p->pPars->fSolveAll ) break; // remember the one solved p->pPars->nSolved++; if ( p->vCexes == NULL ) p->vCexes = Vec_PtrStart( Saig_ManPoNum(p->pAig) ); assert( Vec_PtrEntry(p->vCexes, i) == NULL ); Vec_PtrWriteEntry( p->vCexes, i, (void *)(ABC_PTRINT_T)1 ); if ( p->pPars->pFuncOnFail && p->pPars->pFuncOnFail(i, NULL) ) return 2; // quitting due to callback // print final report if ( !p->pPars->fNotVerbose ) { int nOutDigits = Abc_Base10Log( Saig_ManPoNum(p->pAig) ); Abc_Print( 1, "Output %*d was asserted in frame %4d (solved %*d out of %*d outputs). ", nOutDigits, p->iFailPo, iFrame, nOutDigits, p->pPars->nSolved, nOutDigits, Saig_ManPoNum(p->pAig) ); Abc_PrintTime( 1, "Time", Time ); } } if ( p->iFailPo >= 0 ) // found CEX return 1; else return 0; } /**Function************************************************************* Synopsis [Performs one round of simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_RarManSimulate( Ssw_RarMan_t * p, Vec_Int_t * vInit, int fUpdate, int fFirst ) { Aig_Obj_t * pObj, * pRepr; word * pSim, * pSim0, * pSim1; word Flip, Flip0, Flip1; int w, i; // initialize Ssw_RarManInitialize( p, vInit ); Vec_PtrClear( p->vUpdConst ); Vec_PtrClear( p->vUpdClass ); Aig_ManIncrementTravId( p->pAig ); // check comb inputs if ( fUpdate ) Aig_ManForEachCi( p->pAig, pObj, i ) { pRepr = Aig_ObjRepr(p->pAig, pObj); if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) ) continue; if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) ) continue; // save for update if ( pRepr == Aig_ManConst1(p->pAig) ) Vec_PtrPush( p->vUpdConst, pObj ); else { Vec_PtrPush( p->vUpdClass, pRepr ); Aig_ObjSetTravIdCurrent( p->pAig, pRepr ); } } // simulate Aig_ManForEachNode( p->pAig, pObj, i ) { pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) ); pSim1 = Ssw_RarObjSim( p, Aig_ObjFaninId1(pObj) ); Flip0 = Aig_ObjFaninC0(pObj) ? ~(word)0 : 0; Flip1 = Aig_ObjFaninC1(pObj) ? ~(word)0 : 0; for ( w = 0; w < p->pPars->nWords; w++ ) pSim[w] = (Flip0 ^ pSim0[w]) & (Flip1 ^ pSim1[w]); if ( !fUpdate ) continue; // check classes pRepr = Aig_ObjRepr(p->pAig, pObj); if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) ) continue; if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) ) continue; // save for update if ( pRepr == Aig_ManConst1(p->pAig) ) Vec_PtrPush( p->vUpdConst, pObj ); else { Vec_PtrPush( p->vUpdClass, pRepr ); Aig_ObjSetTravIdCurrent( p->pAig, pRepr ); } } // transfer to POs Aig_ManForEachCo( p->pAig, pObj, i ) { pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) ); pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) ); Flip = Aig_ObjFaninC0(pObj) ? ~(word)0 : 0; for ( w = 0; w < p->pPars->nWords; w++ ) pSim[w] = Flip ^ pSim0[w]; } // refine classes if ( fUpdate ) { if ( fFirst ) { Vec_Ptr_t * vCands = Vec_PtrAlloc( 1000 ); Aig_ManForEachObj( p->pAig, pObj, i ) if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) ) Vec_PtrPush( vCands, pObj ); assert( Vec_PtrSize(vCands) == Ssw_ClassesCand1Num(p->ppClasses) ); Ssw_ClassesPrepareRehash( p->ppClasses, vCands, 0 ); Vec_PtrFree( vCands ); } else { Ssw_ClassesRefineConst1Group( p->ppClasses, p->vUpdConst, 1 ); Ssw_ClassesRefineGroup( p->ppClasses, p->vUpdClass, 1 ); } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, Ssw_RarPars_t * pPars ) { Ssw_RarMan_t * p; // if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 ) // return NULL; p = ABC_CALLOC( Ssw_RarMan_t, 1 ); p->pAig = pAig; p->pPars = pPars; p->nGroups = Aig_ManRegNum(pAig) / pPars->nBinSize; p->pRarity = ABC_CALLOC( int, (1 << pPars->nBinSize) * p->nGroups ); p->pPatCosts = ABC_CALLOC( double, p->pPars->nWords * 64 ); p->nWordsReg = Ssw_RarBitWordNum( Aig_ManRegNum(pAig) ); p->pObjData = ABC_ALLOC( word, Aig_ManObjNumMax(pAig) * p->pPars->nWords ); p->pPatData = ABC_ALLOC( word, 64 * p->pPars->nWords * p->nWordsReg ); p->vUpdConst = Vec_PtrAlloc( 100 ); p->vUpdClass = Vec_PtrAlloc( 100 ); p->vPatBests = Vec_IntAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Ssw_RarManStop( Ssw_RarMan_t * p ) { // Vec_PtrFreeP( &p->vCexes ); if ( p->vCexes ) { assert( p->pAig->vSeqModelVec == NULL ); p->pAig->vSeqModelVec = p->vCexes; p->vCexes = NULL; } if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses ); Vec_IntFreeP( &p->vInits ); Vec_IntFreeP( &p->vPatBests ); Vec_PtrFreeP( &p->vUpdConst ); Vec_PtrFreeP( &p->vUpdClass ); ABC_FREE( p->pObjData ); ABC_FREE( p->pPatData ); ABC_FREE( p->pPatCosts ); ABC_FREE( p->pRarity ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Select best patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits ) { // Aig_Obj_t * pObj; unsigned char * pData; unsigned * pPattern; int i, k, Value; // more data from regs to pats Ssw_RarTranspose( p ); // update counters for ( k = 0; k < p->pPars->nWords * 64; k++ ) { pData = (unsigned char *)Ssw_RarPatSim( p, k ); for ( i = 0; i < p->nGroups; i++ ) Ssw_RarAddToBinPat( p, i, pData[i] ); } // for each pattern for ( k = 0; k < p->pPars->nWords * 64; k++ ) { pData = (unsigned char *)Ssw_RarPatSim( p, k ); // find the cost of its values p->pPatCosts[k] = 0.0; for ( i = 0; i < p->nGroups; i++ ) { Value = Ssw_RarGetBinPat( p, i, pData[i] ); assert( Value > 0 ); p->pPatCosts[k] += 1.0/(Value*Value); } // print the result //Abc_Print( 1, "%3d : %9.6f\n", k, p->pPatCosts[k] ); } // choose as many as there are words Vec_IntClear( vInits ); for ( i = 0; i < p->pPars->nWords; i++ ) { // select the best int iPatBest = -1; double iCostBest = -ABC_INFINITY; for ( k = 0; k < p->pPars->nWords * 64; k++ ) if ( iCostBest < p->pPatCosts[k] ) { iCostBest = p->pPatCosts[k]; iPatBest = k; } // remove from costs assert( iPatBest >= 0 ); p->pPatCosts[iPatBest] = -ABC_INFINITY; // set the flops pPattern = (unsigned *)Ssw_RarPatSim( p, iPatBest ); for ( k = 0; k < Aig_ManRegNum(p->pAig); k++ ) Vec_IntPush( vInits, Abc_InfoHasBit(pPattern, k) ); //Abc_Print( 1, "Best pattern %5d\n", iPatBest ); Vec_IntPush( p->vPatBests, iPatBest ); } assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->pPars->nWords ); } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex ) { Vec_Int_t * vInit; Aig_Obj_t * pObj, * pObjLi; int f, i, iBit; // assign register outputs Saig_ManForEachLi( pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit( pCex->pData, i ); // simulate the timeframes iBit = pCex->nRegs; for ( f = 0; f <= pCex->iFrame; f++ ) { // set the PI simulation information Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachPi( pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ ); Saig_ManForEachLiLo( pAig, pObjLi, pObj, i ) pObj->fMarkB = pObjLi->fMarkB; // simulate internal nodes Aig_ManForEachNode( pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); // assign the COs Aig_ManForEachCo( pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); } assert( iBit == pCex->nBits ); // check that the output failed as expected -- cannot check because it is not an SRM! // pObj = Aig_ManCo( pAig, pCex->iPo ); // if ( pObj->fMarkB != 1 ) // Abc_Print( 1, "The counter-example does not refine the output.\n" ); // record the new pattern vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) ); Saig_ManForEachLo( pAig, pObj, i ) { //Abc_Print( 1, "%d", pObj->fMarkB ); Vec_IntPush( vInit, pObj->fMarkB ); } //Abc_Print( 1, "\n" ); Aig_ManCleanMarkB( pAig ); return vInit; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarCheckTrivial( Aig_Man_t * pAig, int fVerbose ) { Aig_Obj_t * pObj; int i; Saig_ManForEachPo( pAig, pObj, i ) { if ( pAig->nConstrs && i >= Saig_ManPoNum(pAig) - pAig->nConstrs ) return 0; if ( pObj->fPhase ) { ABC_FREE( pAig->pSeqModel ); pAig->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), 1 ); pAig->pSeqModel->iPo = i; if ( fVerbose ) Abc_Print( 1, "Output %d is trivally SAT in frame 0. \n", i ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Perform sequential simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarSimulate( Aig_Man_t * pAig, Ssw_RarPars_t * pPars ) { int fTryBmc = 0; int fMiter = 1; Ssw_RarMan_t * p; int r, f = -1; abctime clk, clkTotal = Abc_Clock(); abctime nTimeToStop = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; abctime timeLastSolved = 0; int nNumRestart = 0; int nSavedSeed = pPars->nRandSeed; int RetValue = -1; int iFrameFail = -1; assert( Aig_ManRegNum(pAig) > 0 ); assert( Aig_ManConstrNum(pAig) == 0 ); ABC_FREE( pAig->pSeqModel ); // consider the case of empty AIG // if ( Aig_ManNodeNum(pAig) == 0 ) // return -1; // check trivially SAT miters // if ( fMiter && Ssw_RarCheckTrivial( pAig, fVerbose ) ) // return 0; if ( pPars->fVerbose ) Abc_Print( 1, "Rarity simulation with %d words, %d frames, %d rounds, %d restart, %d seed, and %d sec timeout.\n", pPars->nWords, pPars->nFrames, pPars->nRounds, pPars->nRestart, pPars->nRandSeed, pPars->TimeOut ); // reset random numbers Ssw_RarManPrepareRandom( nSavedSeed ); // create manager p = Ssw_RarManStart( pAig, pPars ); p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * pPars->nWords ); // perform simulation rounds pPars->nSolved = 0; timeLastSolved = Abc_Clock(); for ( r = 0; !pPars->nRounds || (nNumRestart * pPars->nRestart + r < pPars->nRounds); r++ ) { clk = Abc_Clock(); if ( fTryBmc ) { Aig_Man_t * pNewAig = Saig_ManDupWithPhase( pAig, p->vInits ); Saig_BmcPerform( pNewAig, 0, 100, 2000, 3, 0, 0, 1 /*fVerbose*/, 0, &iFrameFail, 0 ); // if ( pNewAig->pSeqModel != NULL ) // Abc_Print( 1, "BMC has found a counter-example in frame %d.\n", iFrameFail ); Aig_ManStop( pNewAig ); } // simulate for ( f = 0; f < pPars->nFrames; f++ ) { Ssw_RarManSimulate( p, f ? NULL : p->vInits, 0, 0 ); if ( fMiter ) { int Status = Ssw_RarManCheckNonConstOutputs(p, r * p->pPars->nFrames + f, Abc_Clock() - clkTotal); if ( Status == 2 ) { Abc_Print( 1, "Quitting due to callback on fail.\n" ); goto finish; } if ( Status == 1 ) // found CEX { RetValue = 0; if ( !pPars->fSolveAll ) { if ( pPars->fVerbose ) Abc_Print( 1, "\n" ); // Abc_Print( 1, "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); Ssw_RarManPrepareRandom( nSavedSeed ); if ( pPars->fVerbose ) Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts.\n", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart ); pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->pPars->nFrames + f, p->iFailPo, p->iFailPat, pPars->fVerbose ); // print final report Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pAig->pSeqModel->iPo, pAig->pName, pAig->pSeqModel->iFrame ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); goto finish; } timeLastSolved = Abc_Clock(); } // else - did not find a counter example } // check timeout if ( pPars->TimeOut && Abc_Clock() > nTimeToStop ) { if ( !pPars->fSilent ) { if ( pPars->fVerbose && !pPars->fSolveAll ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts and solved %d outputs. ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart, pPars->nSolved ); Abc_Print( 1, "Reached timeout (%d sec).\n", pPars->TimeOut ); } goto finish; } if ( pPars->TimeOutGap && timeLastSolved && Abc_Clock() > timeLastSolved + pPars->TimeOutGap * CLOCKS_PER_SEC ) { if ( !pPars->fSilent ) { if ( pPars->fVerbose && !pPars->fSolveAll ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts and solved %d outputs. ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart, pPars->nSolved ); Abc_Print( 1, "Reached gap timeout (%d sec).\n", pPars->TimeOutGap ); } goto finish; } // check if all outputs are solved by now if ( pPars->fSolveAll && p->vCexes && Vec_PtrCountZero(p->vCexes) == 0 ) goto finish; } // get initialization patterns if ( pPars->nRestart && r == pPars->nRestart ) { r = -1; nSavedSeed = (nSavedSeed + 1) % 1000; Ssw_RarManPrepareRandom( nSavedSeed ); Vec_IntFill( p->vInits, Aig_ManRegNum(pAig) * pPars->nWords, 0 ); nNumRestart++; Vec_IntClear( p->vPatBests ); // clean rarity info // memset( p->pRarity, 0, sizeof(int) * (1 << nBinSize) * p->nGroups ); } else Ssw_RarTransferPatterns( p, p->vInits ); // printout if ( pPars->fVerbose ) { if ( pPars->fSolveAll ) { Abc_Print( 1, "Starts =%6d ", nNumRestart ); Abc_Print( 1, "Rounds =%6d ", nNumRestart * pPars->nRestart + ((r==-1)?0:r) ); Abc_Print( 1, "Frames =%6d ", (nNumRestart * pPars->nRestart + r) * pPars->nFrames ); Abc_Print( 1, "CEX =%6d (%6.2f %%) ", pPars->nSolved, 100.0*pPars->nSolved/Saig_ManPoNum(p->pAig) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } else Abc_Print( 1, "." ); } } finish: if ( pPars->fSetLastState && p->vInits ) { assert( Vec_IntSize(p->vInits) % Aig_ManRegNum(pAig) == 0 ); Vec_IntShrink( p->vInits, Aig_ManRegNum(pAig) ); pAig->pData = p->vInits; p->vInits = NULL; } if ( pPars->nSolved ) { /* if ( !pPars->fSilent ) { if ( pPars->fVerbose && !pPars->fSolveAll ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Simulation of %d frames for %d rounds with %d restarts asserted %d (out of %d) POs. ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart, pPars->nSolved, Saig_ManPoNum(p->pAig) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } */ } else if ( r == pPars->nRounds && f == pPars->nFrames ) { if ( !pPars->fSilent ) { if ( pPars->fVerbose ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Simulation of %d frames for %d rounds with %d restarts did not assert POs. ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } } // cleanup Ssw_RarManStop( p ); return RetValue; } /**Function************************************************************* Synopsis [Derive random flop permutation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ssw_RarRandomPermFlop( int nFlops, int nUnused ) { Vec_Int_t * vPerm; int i, k, * pArray; srand( 1 ); printf( "Generating random permutation of %d flops.\n", nFlops ); vPerm = Vec_IntStartNatural( nFlops ); pArray = Vec_IntArray( vPerm ); for ( i = 0; i < nFlops; i++ ) { k = rand() % nFlops; ABC_SWAP( int, pArray[i], pArray[k] ); } printf( "Randomly adding %d unused flops.\n", nUnused ); for ( i = 0; i < nUnused; i++ ) { k = rand() % Vec_IntSize(vPerm); Vec_IntPush( vPerm, -1 ); pArray = Vec_IntArray( vPerm ); ABC_SWAP( int, pArray[Vec_IntSize(vPerm)-1], pArray[k] ); } // Vec_IntPrint(vPerm); return vPerm; } /**Function************************************************************* Synopsis [Perform sequential simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarSimulateGia( Gia_Man_t * p, Ssw_RarPars_t * pPars ) { Aig_Man_t * pAig; int RetValue; if ( pPars->fUseFfGrouping ) { Vec_Int_t * vPerm = Ssw_RarRandomPermFlop( Gia_ManRegNum(p), 10 ); Gia_Man_t * pTemp = Gia_ManDupPermFlopGap( p, vPerm ); Vec_IntFree( vPerm ); pAig = Gia_ManToAigSimple( pTemp ); Gia_ManStop( pTemp ); } else pAig = Gia_ManToAigSimple( p ); RetValue = Ssw_RarSimulate( pAig, pPars ); // save counter-example Abc_CexFree( p->pCexSeq ); p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; Aig_ManStop( pAig ); return RetValue; } /**Function************************************************************* Synopsis [Filter equivalence classes of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarSignalFilter( Aig_Man_t * pAig, Ssw_RarPars_t * pPars ) { Ssw_RarMan_t * p; int r, f = -1, i, k; abctime clkTotal = Abc_Clock(); abctime nTimeToStop = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; int nNumRestart = 0; int nSavedSeed = pPars->nRandSeed; int RetValue = -1; assert( Aig_ManRegNum(pAig) > 0 ); assert( Aig_ManConstrNum(pAig) == 0 ); // consider the case of empty AIG if ( Aig_ManNodeNum(pAig) == 0 ) return -1; // check trivially SAT miters if ( pPars->fMiter && Ssw_RarCheckTrivial( pAig, 1 ) ) return 0; if ( pPars->fVerbose ) Abc_Print( 1, "Rarity equiv filtering with %d words, %d frames, %d rounds, %d seed, and %d sec timeout.\n", pPars->nWords, pPars->nFrames, pPars->nRounds, pPars->nRandSeed, pPars->TimeOut ); // reset random numbers Ssw_RarManPrepareRandom( nSavedSeed ); // create manager p = Ssw_RarManStart( pAig, pPars ); // compute starting state if needed assert( p->vInits == NULL ); if ( pPars->pCex ) { p->vInits = Ssw_RarFindStartingState( pAig, pPars->pCex ); Abc_Print( 1, "Beginning simulation from the state derived using the counter-example.\n" ); } else p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) ); // duplicate the array for ( i = 1; i < pPars->nWords; i++ ) for ( k = 0; k < Aig_ManRegNum(pAig); k++ ) Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) ); assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * pPars->nWords ); // create trivial equivalence classes with all nodes being candidates for constant 1 if ( pAig->pReprs == NULL ) p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchOnly, 0 ); else p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); Ssw_ClassesSetData( p->ppClasses, p, Ssw_RarManObjHashWord, Ssw_RarManObjIsConst, Ssw_RarManObjsAreEqual ); // print the stats if ( pPars->fVerbose ) { Abc_Print( 1, "Initial : " ); Ssw_ClassesPrint( p->ppClasses, 0 ); } // refine classes using BMC for ( r = 0; !pPars->nRounds || (nNumRestart * pPars->nRestart + r < pPars->nRounds); r++ ) { // start filtering equivalence classes if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) { Abc_Print( 1, "All equivalences are refined away.\n" ); break; } // simulate for ( f = 0; f < pPars->nFrames; f++ ) { Ssw_RarManSimulate( p, f ? NULL : p->vInits, 1, !r && !f ); if ( pPars->fMiter && Ssw_RarManCheckNonConstOutputs(p, -1, 0) ) { if ( !pPars->fVerbose ) Abc_Print( 1, "%s", Abc_FrameIsBatchMode() ? "\n" : "\r" ); // Abc_Print( 1, "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * pPars->nFrames, (r+1) * pPars->nFrames ); if ( pPars->fVerbose ) Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts.\n", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart ); Ssw_RarManPrepareRandom( nSavedSeed ); Abc_CexFree( pAig->pSeqModel ); pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->pPars->nFrames + f, p->iFailPo, p->iFailPat, 1 ); // print final report Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", pAig->pSeqModel->iPo, pAig->pName, pAig->pSeqModel->iFrame ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); RetValue = 0; goto finish; } // check timeout if ( pPars->TimeOut && Abc_Clock() > nTimeToStop ) { if ( pPars->fVerbose ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Simulated %d frames for %d rounds with %d restarts. ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart ); Abc_Print( 1, "Reached timeout (%d sec).\n", pPars->TimeOut ); goto finish; } } // get initialization patterns if ( pPars->pCex == NULL && pPars->nRestart && r == pPars->nRestart ) { r = -1; nSavedSeed = (nSavedSeed + 1) % 1000; Ssw_RarManPrepareRandom( nSavedSeed ); Vec_IntFill( p->vInits, Aig_ManRegNum(pAig) * pPars->nWords, 0 ); nNumRestart++; Vec_IntClear( p->vPatBests ); // clean rarity info // memset( p->pRarity, 0, sizeof(int) * (1 << nBinSize) * p->nGroups ); } else Ssw_RarTransferPatterns( p, p->vInits ); // printout if ( pPars->fVerbose ) { Abc_Print( 1, "Round %3d: ", r ); Ssw_ClassesPrint( p->ppClasses, 0 ); } else { Abc_Print( 1, "." ); } } finish: // report if ( r == pPars->nRounds && f == pPars->nFrames ) { if ( !pPars->fVerbose ) Abc_Print( 1, "%s", Abc_FrameIsBatchMode() ? "\n" : "\r" ); Abc_Print( 1, "Simulation of %d frames for %d rounds with %d restarts did not assert POs. ", pPars->nFrames, nNumRestart * pPars->nRestart + r, nNumRestart ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } // cleanup Ssw_RarManStop( p ); return RetValue; } /**Function************************************************************* Synopsis [Filter equivalence classes of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarSignalFilterGia( Gia_Man_t * p, Ssw_RarPars_t * pPars ) { Aig_Man_t * pAig; int RetValue; pAig = Gia_ManToAigSimple( p ); if ( p->pReprs != NULL ) { Gia_ManReprToAigRepr2( pAig, p ); ABC_FREE( p->pReprs ); ABC_FREE( p->pNexts ); } RetValue = Ssw_RarSignalFilter( pAig, pPars ); Gia_ManReprFromAigRepr( pAig, p ); // save counter-example Abc_CexFree( p->pCexSeq ); p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; Aig_ManStop( pAig ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswRarity2.c000066400000000000000000000417231300674244400242410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswRarity.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Rarity-driven refinement of equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Ssw_RarMan_t_ Ssw_RarMan_t; struct Ssw_RarMan_t_ { // parameters int nWords; // the number of words to simulate int nFrames; // the number of frames to simulate int nBinSize; // the number of flops in one group int fVerbose; // the verbosiness flag int nGroups; // the number of flop groups // internal data Aig_Man_t * pAig; // AIG with equivalence classes Ssw_Cla_t * ppClasses; // equivalence classes Ssw_Sml_t * pSml; // simulation manager Vec_Ptr_t * vSimInfo; // simulation info from pSml manager Vec_Int_t * vInits; // initial state // rarity data int * pRarity; // occur counts for patterns in groups int * pGroupValues; // occur counts in each group double * pPatCosts; // pattern costs }; static inline int Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) { assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); return p->pRarity[iBin * (1 << p->nBinSize) + iPat]; } static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value ) { assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); p->pRarity[iBin * (1 << p->nBinSize) + iPat] = Value; } static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat ) { assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize ); assert( iPat >= 0 && iPat < (1 << p->nBinSize) ); p->pRarity[iBin * (1 << p->nBinSize) + iPat]++; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, int nWords, int nFrames, int nBinSize, int fVerbose ) { Ssw_RarMan_t * p; if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 ) return NULL; p = ABC_CALLOC( Ssw_RarMan_t, 1 ); p->pAig = pAig; p->nWords = nWords; p->nFrames = nFrames; p->nBinSize = nBinSize; p->fVerbose = fVerbose; p->nGroups = Aig_ManRegNum(pAig) / nBinSize; p->pRarity = ABC_CALLOC( int, (1 << nBinSize) * p->nGroups ); p->pGroupValues = ABC_CALLOC( int, p->nGroups ); p->pPatCosts = ABC_CALLOC( double, p->nWords * 32 ); p->pSml = Ssw_SmlStart( pAig, 0, nFrames, nWords ); p->vSimInfo = Ssw_SmlSimDataPointers( p->pSml ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Ssw_RarManStop( Ssw_RarMan_t * p ) { if ( p->pSml ) Ssw_SmlStop( p->pSml ); if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses ); Vec_PtrFreeP( &p->vSimInfo ); Vec_IntFreeP( &p->vInits ); ABC_FREE( p->pGroupValues ); ABC_FREE( p->pPatCosts ); ABC_FREE( p->pRarity ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Updates rarity counters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Ssw_RarUpdateCounters( Ssw_RarMan_t * p ) { Aig_Obj_t * pObj; unsigned * pData; int i, k; /* Saig_ManForEachLi( p->pAig, pObj, i ) { pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); Extra_PrintBinary( stdout, pData, 32 ); Abc_Print( 1, "\n" ); } */ for ( k = 0; k < p->nWords * 32; k++ ) { for ( i = 0; i < p->nGroups; i++ ) p->pGroupValues[i] = 0; Saig_ManForEachLi( p->pAig, pObj, i ) { pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); if ( Abc_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups ) p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize)); } for ( i = 0; i < p->nGroups; i++ ) Ssw_RarAddToBinPat( p, i, p->pGroupValues[i] ); } /* for ( i = 0; i < p->nGroups; i++ ) { for ( k = 0; k < (1 << p->nBinSize); k++ ) Abc_Print( 1, "%d ", Ssw_RarGetBinPat(p, i, k) ); Abc_Print( 1, "\n" ); } */ } /**Function************************************************************* Synopsis [Select best patterns.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits ) { Aig_Obj_t * pObj; unsigned * pData; int i, k, Value; // for each pattern for ( k = 0; k < p->nWords * 32; k++ ) { for ( i = 0; i < p->nGroups; i++ ) p->pGroupValues[i] = 0; // compute its group values Saig_ManForEachLi( p->pAig, pObj, i ) { pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); if ( Abc_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups ) p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize)); } // find the cost of its values p->pPatCosts[k] = 0.0; for ( i = 0; i < p->nGroups; i++ ) { Value = Ssw_RarGetBinPat( p, i, p->pGroupValues[i] ); assert( Value > 0 ); p->pPatCosts[k] += 1.0/(Value*Value); } // print the result // Abc_Print( 1, "%3d : %9.6f\n", k, p->pPatCosts[k] ); } // choose as many as there are words Vec_IntClear( vInits ); for ( i = 0; i < p->nWords; i++ ) { // select the best int iPatBest = -1; double iCostBest = -ABC_INFINITY; for ( k = 0; k < p->nWords * 32; k++ ) if ( iCostBest < p->pPatCosts[k] ) { iCostBest = p->pPatCosts[k]; iPatBest = k; } // remove from costs assert( iPatBest >= 0 ); p->pPatCosts[iPatBest] = -ABC_INFINITY; // set the flops Saig_ManForEachLi( p->pAig, pObj, k ) { pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1); Vec_IntPush( vInits, Abc_InfoHasBit(pData, iPatBest) ); } //Abc_Print( 1, "Best pattern %5d\n", iPatBest ); } assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->nWords ); } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex ) { Vec_Int_t * vInit; Aig_Obj_t * pObj, * pObjLi; int f, i, iBit; // assign register outputs Saig_ManForEachLi( pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit( pCex->pData, i ); // simulate the timeframes iBit = pCex->nRegs; for ( f = 0; f <= pCex->iFrame; f++ ) { // set the PI simulation information Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachPi( pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ ); Saig_ManForEachLiLo( pAig, pObjLi, pObj, i ) pObj->fMarkB = pObjLi->fMarkB; // simulate internal nodes Aig_ManForEachNode( pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); // assign the COs Aig_ManForEachCo( pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ); } assert( iBit == pCex->nBits ); // check that the output failed as expected -- cannot check because it is not an SRM! // pObj = Aig_ManCo( pAig, pCex->iPo ); // if ( pObj->fMarkB != 1 ) // Abc_Print( 1, "The counter-example does not refine the output.\n" ); // record the new pattern vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) ); Saig_ManForEachLo( pAig, pObj, i ) Vec_IntPush( vInit, pObj->fMarkB ); return vInit; } /**Function************************************************************* Synopsis [Perform sequential simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarSimulate2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, int fVerbose ) { int fMiter = 1; Ssw_RarMan_t * p; int r; abctime clk, clkTotal = Abc_Clock(); abctime nTimeToStop = TimeOut ? TimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; int RetValue = -1; assert( Aig_ManRegNum(pAig) > 0 ); assert( Aig_ManConstrNum(pAig) == 0 ); // consider the case of empty AIG if ( Aig_ManNodeNum(pAig) == 0 ) return -1; if ( fVerbose ) Abc_Print( 1, "Simulating %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n", nWords, nFrames, nBinSize, nRounds, TimeOut ); // reset random numbers Aig_ManRandom( 1 ); // create manager p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * nWords ); Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); // perform simulation rounds for ( r = 0; r < nRounds; r++ ) { clk = Abc_Clock(); // simulate Ssw_SmlSimulateOne( p->pSml ); if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) ) { if ( fVerbose ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); RetValue = 0; break; } // get initialization patterns Ssw_RarUpdateCounters( p ); Ssw_RarTransferPatterns( p, p->vInits ); Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); // printout if ( fVerbose ) { // Abc_Print( 1, "Round %3d: ", r ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Abc_Print( 1, "." ); } // check timeout if ( TimeOut && Abc_Clock() > nTimeToStop ) { if ( fVerbose ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Reached timeout (%d seconds).\n", TimeOut ); break; } } if ( r == nRounds ) { if ( fVerbose ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } // cleanup Ssw_RarManStop( p ); return RetValue; } /**Function************************************************************* Synopsis [Filter equivalence classes of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarSignalFilter2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) { int fMiter = 0; Ssw_RarMan_t * p; int r, i, k; abctime clkTotal = Abc_Clock(); abctime nTimeToStop = TimeOut ? TimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; int RetValue = -1; assert( Aig_ManRegNum(pAig) > 0 ); assert( Aig_ManConstrNum(pAig) == 0 ); // consider the case of empty AIG if ( Aig_ManNodeNum(pAig) == 0 ) return -1; if ( fVerbose ) Abc_Print( 1, "Filtering equivs with %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n", nWords, nFrames, nBinSize, nRounds, TimeOut ); // reset random numbers Aig_ManRandom( 1 ); // create manager p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose ); // compute starting state if needed assert( p->vInits == NULL ); if ( pCex ) p->vInits = Ssw_RarFindStartingState( pAig, pCex ); else p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) ); // duplicate the array for ( i = 1; i < nWords; i++ ) for ( k = 0; k < Aig_ManRegNum(pAig); k++ ) Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) ); assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * nWords ); // initialize simulation manager Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); // create trivial equivalence classes with all nodes being candidates for constant 1 if ( pAig->pReprs == NULL ) p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 ); else p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig ); Ssw_ClassesSetData( p->ppClasses, p->pSml, NULL, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord ); // print the stats if ( fVerbose ) { Abc_Print( 1, "Initial : " ); Ssw_ClassesPrint( p->ppClasses, 0 ); } // refine classes using BMC for ( r = 0; r < nRounds; r++ ) { // start filtering equivalence classes if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 ) { Abc_Print( 1, "All equivalences are refined away.\n" ); break; } // simulate Ssw_SmlSimulateOne( p->pSml ); if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) ) { if ( fVerbose ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames ); RetValue = 0; break; } // check equivalence classes Ssw_ClassesRefineConst1( p->ppClasses, 1 ); Ssw_ClassesRefine( p->ppClasses, 1 ); // printout if ( fVerbose ) { Abc_Print( 1, "Round %3d: ", r ); Ssw_ClassesPrint( p->ppClasses, 0 ); } // get initialization patterns Ssw_RarUpdateCounters( p ); Ssw_RarTransferPatterns( p, p->vInits ); Ssw_SmlInitializeSpecial( p->pSml, p->vInits ); // check timeout if ( TimeOut && Abc_Clock() > nTimeToStop ) { if ( fVerbose ) Abc_Print( 1, "\n" ); Abc_Print( 1, "Reached timeout (%d seconds).\n", TimeOut ); break; } } if ( r == nRounds ) { Abc_Print( 1, "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } // cleanup Ssw_RarManStop( p ); return -1; } /**Function************************************************************* Synopsis [Filter equivalence classes of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_RarSignalFilterGia2( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose ) { Aig_Man_t * pAig; int RetValue; pAig = Gia_ManToAigSimple( p ); if ( p->pReprs != NULL ) { Gia_ManReprToAigRepr2( pAig, p ); ABC_FREE( p->pReprs ); ABC_FREE( p->pNexts ); } RetValue = Ssw_RarSignalFilter2( pAig, nFrames, nWords, nBinSize, nRounds, TimeOut, pCex, fLatchOnly, fVerbose ); Gia_ManReprFromAigRepr( pAig, p ); Aig_ManStop( pAig ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswSat.c000066400000000000000000000223451300674244400234330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Calls to the SAT solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Runs equivalence test for the two nodes.] Description [Both nodes should be regular and different from each other.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) { int nBTLimit = p->pPars->nBTLimit; int pLits[3], nLits, RetValue, RetValue1; abctime clk;//, status; p->nSatCalls++; p->pMSat->nSolverCalls++; // sanity checks assert( !Aig_IsComplement(pOld) ); assert( !Aig_IsComplement(pNew) ); assert( pOld != pNew ); assert( p->pMSat != NULL ); // if the nodes do not have SAT variables, allocate them Ssw_CnfNodeAddToSolver( p->pMSat, pOld ); Ssw_CnfNodeAddToSolver( p->pMSat, pNew ); // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 nLits = 2; pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 ); pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase == pNew->fPhase ); if ( p->iOutputLit > -1 ) pLits[nLits++] = p->iOutputLit; if ( p->pPars->fPolarFlip ) { if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); } //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) { RetValue = sat_solver_simplify(p->pMSat->pSat); assert( RetValue != 0 ); } clk = Abc_Clock(); RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { p->timeSatUnsat += Abc_Clock() - clk; if ( nLits == 2 ) { pLits[0] = lit_neg( pLits[0] ); pLits[1] = lit_neg( pLits[1] ); RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); assert( RetValue ); /* if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) { RetValue = sat_solver_simplify(p->pMSat->pSat); assert( RetValue != 0 ); } */ } p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->timeSatSat += Abc_Clock() - clk; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatFailsReal++; return -1; } // if the old node was constant 0, we already know the answer if ( pOld == Aig_ManConst1(p->pFrames) ) { p->nSatProof++; return 1; } // solve under assumptions // A = 0; B = 1 OR A = 0; B = 0 nLits = 2; pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 ); pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase ^ pNew->fPhase ); if ( p->iOutputLit > -1 ) pLits[nLits++] = p->iOutputLit; if ( p->pPars->fPolarFlip ) { if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); } if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) { RetValue = sat_solver_simplify(p->pMSat->pSat); assert( RetValue != 0 ); } clk = Abc_Clock(); RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { p->timeSatUnsat += Abc_Clock() - clk; if ( nLits == 2 ) { pLits[0] = lit_neg( pLits[0] ); pLits[1] = lit_neg( pLits[1] ); RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); assert( RetValue ); /* if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead ) { RetValue = sat_solver_simplify(p->pMSat->pSat); assert( RetValue != 0 ); } */ } p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->timeSatSat += Abc_Clock() - clk; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatFailsReal++; return -1; } // return SAT proof p->nSatProof++; return 1; } /**Function************************************************************* Synopsis [Constrains two nodes to be equivalent in the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) { int pLits[2], RetValue, fComplNew; Aig_Obj_t * pTemp; // sanity checks assert( Aig_Regular(pOld) != Aig_Regular(pNew) ); assert( p->pPars->fConstrs || Aig_ObjPhaseReal(pOld) == Aig_ObjPhaseReal(pNew) ); // move constant to the old node if ( Aig_Regular(pNew) == Aig_ManConst1(p->pFrames) ) { assert( Aig_Regular(pOld) != Aig_ManConst1(p->pFrames) ); pTemp = pOld; pOld = pNew; pNew = pTemp; } // move complement to the new node if ( Aig_IsComplement(pOld) ) { pOld = Aig_Regular(pOld); pNew = Aig_Not(pNew); } assert( p->pMSat != NULL ); // if the nodes do not have SAT variables, allocate them Ssw_CnfNodeAddToSolver( p->pMSat, pOld ); Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pNew) ); // transform the new node fComplNew = Aig_IsComplement( pNew ); pNew = Aig_Regular( pNew ); // consider the constant 1 case if ( pOld == Aig_ManConst1(p->pFrames) ) { // add constraint A = 1 ----> A pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew ); if ( p->pPars->fPolarFlip ) { if ( pNew->fPhase ) pLits[0] = lit_neg( pLits[0] ); } RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 1 ); assert( RetValue ); } else { // add constraint A = B ----> (A v !B)(!A v B) // (A v !B) pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 ); pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), !fComplNew ); if ( p->pPars->fPolarFlip ) { if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); } pLits[0] = lit_neg( pLits[0] ); pLits[1] = lit_neg( pLits[1] ); RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); assert( RetValue ); // (!A v B) pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 ); pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew); if ( p->pPars->fPolarFlip ) { if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] ); if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] ); } pLits[0] = lit_neg( pLits[0] ); pLits[1] = lit_neg( pLits[1] ); RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 ); assert( RetValue ); } return 1; } /**Function************************************************************* Synopsis [Constrains one node in the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj ) { int RetValue, Lit; Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pPoObj) ); // add constraint A = 1 ----> A Lit = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_ObjFanin0(pPoObj)), !Aig_ObjFaninC0(pPoObj) ); if ( p->pPars->fPolarFlip ) { if ( Aig_ObjFanin0(pPoObj)->fPhase ) Lit = lit_neg( Lit ); } RetValue = sat_solver_addclause( p->pMSat->pSat, &Lit, &Lit + 1 ); assert( RetValue ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswSemi.c000066400000000000000000000237411300674244400236020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswSemi.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Semiformal for equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswSemi.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Ssw_Sem_t_ Ssw_Sem_t; // BMC manager struct Ssw_Sem_t_ { // parameters int nConfMaxStart; // the starting conflict limit int nConfMax; // the intermediate conflict limit int nFramesSweep; // the number of frames to sweep int fVerbose; // prints output statistics // equivalences considered Ssw_Man_t * pMan; // SAT sweeping manager Vec_Ptr_t * vTargets; // the nodes that are watched // storage for patterns int nPatternsAlloc; // the max number of interesting states int nPatterns; // the number of patterns Vec_Ptr_t * vPatterns; // storage for the interesting states Vec_Int_t * vHistory; // what state and how many steps }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Sem_t * Ssw_SemManStart( Ssw_Man_t * pMan, int nConfMax, int fVerbose ) { Ssw_Sem_t * p; Aig_Obj_t * pObj; int i; // create interpolation manager p = ABC_ALLOC( Ssw_Sem_t, 1 ); memset( p, 0, sizeof(Ssw_Sem_t) ); p->nConfMaxStart = nConfMax; p->nConfMax = nConfMax; p->nFramesSweep = Abc_MaxInt( (1<<21)/Aig_ManNodeNum(pMan->pAig), pMan->nFrames ); p->fVerbose = fVerbose; // equivalences considered p->pMan = pMan; p->vTargets = Vec_PtrAlloc( Saig_ManPoNum(p->pMan->pAig) ); Saig_ManForEachPo( p->pMan->pAig, pObj, i ) Vec_PtrPush( p->vTargets, Aig_ObjFanin0(pObj) ); // storage for patterns p->nPatternsAlloc = 512; p->nPatterns = 1; p->vPatterns = Vec_PtrAllocSimInfo( Aig_ManRegNum(p->pMan->pAig), Abc_BitWordNum(p->nPatternsAlloc) ); Vec_PtrCleanSimInfo( p->vPatterns, 0, Abc_BitWordNum(p->nPatternsAlloc) ); p->vHistory = Vec_IntAlloc( 100 ); Vec_IntPush( p->vHistory, 0 ); // update arrays of the manager assert( 0 ); /* ABC_FREE( p->pMan->pNodeToFrames ); Vec_IntFree( p->pMan->vSatVars ); p->pMan->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pMan->pAig) * p->nFramesSweep ); p->pMan->vSatVars = Vec_IntStart( Aig_ManObjNumMax(p->pMan->pAig) * (p->nFramesSweep+1) ); */ return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SemManStop( Ssw_Sem_t * p ) { Vec_PtrFree( p->vTargets ); Vec_PtrFree( p->vPatterns ); Vec_IntFree( p->vHistory ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SemCheckTargets( Ssw_Sem_t * p ) { Aig_Obj_t * pObj; int i; Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i ) if ( !Ssw_ObjIsConst1Cand(p->pMan->pAig, pObj) ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManFilterBmcSavePattern( Ssw_Sem_t * p ) { unsigned * pInfo; Aig_Obj_t * pObj; int i; if ( p->nPatterns >= p->nPatternsAlloc ) return; Saig_ManForEachLo( p->pMan->pAig, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( p->vPatterns, i ); if ( Abc_InfoHasBit( p->pMan->pPatWords, Saig_ManPiNum(p->pMan->pAig) + i ) ) Abc_InfoSetBit( pInfo, p->nPatterns ); } p->nPatterns++; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManFilterBmc( Ssw_Sem_t * pBmc, int iPat, int fCheckTargets ) { Ssw_Man_t * p = pBmc->pMan; Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; unsigned * pInfo; int i, f, RetValue, fFirst = 0; abctime clk; clk = Abc_Clock(); // start initialized timeframes p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * 3 ); Saig_ManForEachLo( p->pAig, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( pBmc->vPatterns, i ); pObjNew = Aig_NotCond( Aig_ManConst1(p->pFrames), !Abc_InfoHasBit(pInfo, iPat) ); Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); } // sweep internal nodes RetValue = pBmc->nFramesSweep; for ( f = 0; f < pBmc->nFramesSweep; f++ ) { // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) ); // sweep internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) { pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); if ( Ssw_ManSweepNode( p, pObj, f, 1, NULL ) ) { Ssw_ManFilterBmcSavePattern( pBmc ); if ( fFirst == 0 ) { fFirst = 1; pBmc->nConfMax *= 10; } } if ( f > 0 && p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax ) { RetValue = -1; break; } } // quit if this is the last timeframe if ( p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax ) { RetValue += f + 1; break; } if ( fCheckTargets && Ssw_SemCheckTargets( pBmc ) ) break; // transfer latch input to the latch outputs // build logic cones for register outputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { pObjNew = Ssw_ObjChild0Fra(p, pObjLi,f); Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) ); } //Abc_Print( 1, "Frame %2d : Conflicts = %6d. \n", f, p->pSat->stats.conflicts ); } if ( fFirst ) pBmc->nConfMax /= 10; // cleanup Ssw_ClassesCheck( p->ppClasses ); p->timeBmc += Abc_Clock() - clk; return RetValue; } /**Function************************************************************* Synopsis [Returns 1 if one of the targets has failed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose ) { Ssw_Sem_t * p; int RetValue, Frames, Iter; abctime clk = Abc_Clock(); p = Ssw_SemManStart( pMan, nConfMax, fVerbose ); if ( fCheckTargets && Ssw_SemCheckTargets( p ) ) { assert( 0 ); Ssw_SemManStop( p ); return 1; } if ( fVerbose ) { Abc_Print( 1, "AIG : C = %6d. Cl = %6d. Nodes = %6d. ConfMax = %6d. FramesMax = %6d.\n", Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses), Aig_ManNodeNum(p->pMan->pAig), p->nConfMax, p->nFramesSweep ); } RetValue = 0; for ( Iter = 0; Iter < p->nPatterns; Iter++ ) { clk = Abc_Clock(); pMan->pMSat = Ssw_SatStart( 0 ); Frames = Ssw_ManFilterBmc( p, Iter, fCheckTargets ); if ( fVerbose ) { Abc_Print( 1, "%3d : C = %6d. Cl = %6d. NR = %6d. F = %3d. C = %5d. P = %3d. %s ", Iter, Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses), Aig_ManNodeNum(p->pMan->pFrames), Frames, (int)p->pMan->pMSat->pSat->stats.conflicts, p->nPatterns, p->pMan->nSatFailsReal? "f" : " " ); ABC_PRT( "T", Abc_Clock() - clk ); } Ssw_ManCleanup( p->pMan ); if ( fCheckTargets && Ssw_SemCheckTargets( p ) ) { Abc_Print( 1, "Target is hit!!!\n" ); RetValue = 1; } if ( p->nPatterns >= p->nPatternsAlloc ) break; } Ssw_SemManStop( p ); pMan->nStrangers = 0; pMan->nSatCalls = 0; pMan->nSatProof = 0; pMan->nSatFailsReal = 0; pMan->nSatCallsUnsat = 0; pMan->nSatCallsSat = 0; pMan->timeSimSat = 0; pMan->timeSat = 0; pMan->timeSatSat = 0; pMan->timeSatUnsat = 0; pMan->timeSatUndec = 0; return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswSim.c000066400000000000000000001202661300674244400234350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Sequential simulator used by the inductive prover.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswSim.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // simulation manager struct Ssw_Sml_t_ { Aig_Man_t * pAig; // the original AIG manager int nPref; // the number of timeframes in the prefix int nFrames; // the number of timeframes int nWordsFrame; // the number of words in each timeframe int nWordsTotal; // the total number of words at a node int nWordsPref; // the number of word in the prefix int fNonConstOut; // have seen a non-const-0 output during simulation int nSimRounds; // statistics abctime timeSim; // statistics unsigned pData[0]; // simulation data for the nodes }; static inline unsigned * Ssw_ObjSim( Ssw_Sml_t * p, int Id ) { return p->pData + p->nWordsTotal * Id; } static inline unsigned Ssw_ObjRandomSim() { return Aig_ManRandom(0); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, 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; int i; // assert( p->nWordsTotal <= 128 ); uHash = 0; pSims = Ssw_ObjSim(p, pObj->Id); for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; return uHash; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj ) { unsigned * pSims; int i; pSims = Ssw_ObjSim(p, pObj->Id); for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) if ( pSims[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation infos are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { unsigned * pSims0, * pSims1; int i; pSims0 = Ssw_ObjSim(p, pObj0->Id); pSims1 = Ssw_ObjSim(p, pObj1->Id); for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) if ( pSims0[i] != pSims1[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if the node appears to be constant 1 candidate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj ) { return pObj->fPhase == pObj->fMarkB; } /**Function************************************************************* Synopsis [Returns 1 if the nodes appear equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB); } /**Function************************************************************* Synopsis [Counts the number of 1s in the XOR of simulation data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlNodeNotEquWeight( Ssw_Sml_t * p, int Left, int Right ) { unsigned * pSimL, * pSimR; int k, Counter = 0; pSimL = Ssw_ObjSim( p, Left ); pSimR = Ssw_ObjSim( p, Right ); for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] ); return Counter; } /**Function************************************************************* Synopsis [Checks implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ) { unsigned * pSimLi, * pSimLo, * pSimCand; int k; assert( pObjLo->fPhase == 0 ); // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id ); pSimLi = Ssw_ObjSim( p, pObjLi->Id ); pSimLo = Ssw_ObjSim( p, pObjLo->Id ); if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) ) { for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) return 0; } else { for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Counts the number of 1s in the implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ) { unsigned * pSimLi, * pSimLo, * pSimCand; int k, Counter = 0; assert( pObjLo->fPhase == 0 ); // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id ); pSimLi = Ssw_ObjSim( p, pObjLi->Id ); pSimLo = Ssw_ObjSim( p, pObjLo->Id ); if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) ) { for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); } else { for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k])); } return Counter; } /**Function************************************************************* Synopsis [Counts the number of 1s in the implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ) { unsigned * pSimLi, * pSimLo; int k, Counter = 0; assert( pObjLo->fPhase == 0 ); // pObjLi->fPhase may be 1, but the LI simulation data is not complemented! pSimLi = Ssw_ObjSim( p, pObjLi->Id ); pSimLo = Ssw_ObjSim( p, pObjLo->Id ); for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) Counter += Aig_WordCountOnes( ~(pSimLi[k] ^ pSimLo[k]) ); return Counter; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj ) { unsigned * pSims; int i; pSims = Ssw_ObjSim(p, pObj->Id); for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) if ( pSims[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlNodeIsZeroFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f ) { unsigned * pSims = Ssw_ObjSim(p, pObj->Id); return pSims[f] == 0; } /**Function************************************************************* Synopsis [Counts the number of one's in the pattern of the object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ) { unsigned * pSims; int i, Counter = 0; pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id); if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ) { for ( i = 0; i < p->nWordsTotal; i++ ) Counter += Aig_WordCountOnes( ~pSims[i] ); } else { for ( i = 0; i < p->nWordsTotal; i++ ) Counter += Aig_WordCountOnes( pSims[i] ); } return Counter; } /**Function************************************************************* Synopsis [Counts the number of one's in the pattern of the objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ) { Aig_Obj_t * pObj; unsigned * pSims, uWord; int i, k, Counter = 0; if ( Vec_PtrSize(vObjs) == 0 ) return 0; for ( i = 0; i < p->nWordsTotal; i++ ) { uWord = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, k ) { pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id); if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ) uWord |= ~pSims[i]; else uWord |= pSims[i]; } Counter += Aig_WordCountOnes( uWord ); } return Counter; } /**Function************************************************************* Synopsis [Generated const 0 pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlSavePattern0( Ssw_Man_t * p, int fInit ) { memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); } /**Function************************************************************* Synopsis [[Generated const 1 pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlSavePattern1( Ssw_Man_t * p, int fInit ) { Aig_Obj_t * pObj; int i, k, nTruePis; memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); if ( !fInit ) return; // clear the state bits to correspond to all-0 initial state nTruePis = Saig_ManPiNum(p->pAig); k = 0; Saig_ManForEachLo( p->pAig, pObj, i ) Abc_InfoXorBit( p->pPatWords, nTruePis * p->nFrames + k++ ); } /**Function************************************************************* Synopsis [Creates the counter-example from the successful pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Ssw_SmlCheckOutputSavePattern( Ssw_Sml_t * p, Aig_Obj_t * pObjPo ) { Aig_Obj_t * pFanin, * pObjPi; unsigned * pSims; int i, k, BestPat, * pModel; // find the word of the pattern pFanin = Aig_ObjFanin0(pObjPo); pSims = Ssw_ObjSim(p, pFanin->Id); for ( i = 0; i < p->nWordsTotal; i++ ) if ( pSims[i] ) break; assert( i < p->nWordsTotal ); // find the bit of the pattern for ( k = 0; k < 32; k++ ) if ( pSims[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, Aig_ManCiNum(p->pAig)+1 ); Aig_ManForEachCi( p->pAig, pObjPi, i ) { pModel[i] = Abc_InfoHasBit(Ssw_ObjSim(p, pObjPi->Id), BestPat); // Abc_Print( 1, "%d", pModel[i] ); } pModel[Aig_ManCiNum(p->pAig)] = pObjPo->Id; // Abc_Print( 1, "\n" ); return pModel; } /**Function************************************************************* Synopsis [Returns 1 if the one of the output is already non-constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Ssw_SmlCheckOutput( Ssw_Sml_t * p ) { Aig_Obj_t * pObj; int i; // make sure the reference simulation pattern does not detect the bug pObj = Aig_ManCo( p->pAig, 0 ); assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) ); Aig_ManForEachCo( p->pAig, pObj, i ) { if ( !Ssw_SmlObjIsConstWord( p, Aig_ObjFanin0(pObj) ) ) { // create the counter-example from this pattern return Ssw_SmlCheckOutputSavePattern( p, pObj ); } } return NULL; } /**Function************************************************************* Synopsis [Assigns random patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlAssignRandom( Ssw_Sml_t * p, Aig_Obj_t * pObj ) { unsigned * pSims; int i, f; assert( Aig_ObjIsCi(pObj) ); pSims = Ssw_ObjSim( p, pObj->Id ); for ( i = 0; i < p->nWordsTotal; i++ ) pSims[i] = Ssw_ObjRandomSim(); // set the first bit 0 in each frame assert( p->nWordsFrame * p->nFrames == p->nWordsTotal ); for ( f = 0; f < p->nFrames; f++ ) pSims[p->nWordsFrame*f] <<= 1; } /**Function************************************************************* Synopsis [Assigns random patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) { unsigned * pSims; int i; assert( iFrame < p->nFrames ); assert( Aig_ObjIsCi(pObj) ); pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = Ssw_ObjRandomSim(); } /**Function************************************************************* Synopsis [Assigns constant patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ) { unsigned * pSims; int i; assert( iFrame < p->nFrames ); assert( Aig_ObjIsCi(pObj) ); pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = fConst1? ~(unsigned)0 : 0; } /**Function************************************************************* Synopsis [Assigns constant patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlObjAssignConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame, int iWord ) { unsigned * pSims; assert( iFrame < p->nFrames ); assert( iWord < p->nWordsFrame ); assert( Aig_ObjIsCi(pObj) ); pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; pSims[iWord] = fConst1? ~(unsigned)0 : 0; } /**Function************************************************************* Synopsis [Assigns constant patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame ) { unsigned * pSims; assert( iFrame < p->nFrames ); assert( Aig_ObjIsCi(pObj) ); pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; pSims[iWord] = Word; } /**Function************************************************************* Synopsis [Assings distance-1 simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlAssignDist1( Ssw_Sml_t * p, unsigned * pPat ) { Aig_Obj_t * pObj; int f, i, k, Limit, nTruePis; assert( p->nFrames > 0 ); if ( p->nFrames == 1 ) { // copy the PI info Aig_ManForEachCi( p->pAig, pObj, i ) Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 ); // flip one bit Limit = Abc_MinInt( Aig_ManCiNum(p->pAig), p->nWordsTotal * 32 - 1 ); for ( i = 0; i < Limit; i++ ) Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManCi(p->pAig,i)->Id ), i+1 ); } else { int fUseDist1 = 0; // copy the PI info for each frame nTruePis = Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig); for ( f = 0; f < p->nFrames; f++ ) Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * f + i), f ); // copy the latch info k = 0; Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 ); // assert( p->pFrames == NULL || nTruePis * p->nFrames + k == Aig_ManCiNum(p->pFrames) ); // flip one bit of the last frame if ( fUseDist1 ) //&& p->nFrames == 2 ) { Limit = Abc_MinInt( nTruePis, p->nWordsFrame * 32 - 1 ); for ( i = 0; i < Limit; i++ ) Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManCi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 ); } } } /**Function************************************************************* Synopsis [Assings distance-1 simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat ) { Aig_Obj_t * pObj; int f, i, Limit; assert( p->nFrames > 0 ); // copy the pattern into the primary inputs Aig_ManForEachCi( p->pAig, pObj, i ) Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 ); // set distance one PIs for the first frame Limit = Abc_MinInt( Saig_ManPiNum(p->pAig), p->nWordsFrame * 32 - 1 ); for ( i = 0; i < Limit; i++ ) Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManCi(p->pAig, i)->Id ), i+1 ); // create random info for the remaining timeframes for ( f = 1; f < p->nFrames; f++ ) Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_SmlAssignRandomFrame( p, pObj, f ); } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlNodeSimulate( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) { unsigned * pSims, * pSims0, * pSims1; int fCompl, fCompl0, fCompl1, i; assert( iFrame < p->nFrames ); assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(pObj) ); assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; pSims0 = Ssw_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; pSims1 = Ssw_ObjSim(p, Aig_ObjFanin1(pObj)->Id) + p->nWordsFrame * iFrame; // get complemented attributes of the children using their random info fCompl = pObj->fPhase; fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj)); fCompl1 = Aig_ObjPhaseReal(Aig_ObjChild1(pObj)); // simulate if ( fCompl0 && fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (pSims0[i] | pSims1[i]); else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = ~(pSims0[i] | pSims1[i]); } else if ( fCompl0 && !fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (pSims0[i] | ~pSims1[i]); else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (~pSims0[i] & pSims1[i]); } else if ( !fCompl0 && fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (~pSims0[i] | pSims1[i]); else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (pSims0[i] & ~pSims1[i]); } else // if ( !fCompl0 && !fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = ~(pSims0[i] & pSims1[i]); else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = (pSims0[i] & pSims1[i]); } } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlNodesCompareInFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 ) { unsigned * pSims0, * pSims1; int i; assert( iFrame0 < p->nFrames ); assert( iFrame1 < p->nFrames ); assert( !Aig_IsComplement(pObj0) ); assert( !Aig_IsComplement(pObj1) ); assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal ); assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims0 = Ssw_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0; pSims1 = Ssw_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1; // compare for ( i = 0; i < p->nWordsFrame; i++ ) if ( pSims0[i] != pSims1[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlNodeCopyFanin( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) { unsigned * pSims, * pSims0; int fCompl, fCompl0, i; assert( iFrame < p->nFrames ); assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsCo(pObj) ); assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; pSims0 = Ssw_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; // get complemented attributes of the children using their random info fCompl = pObj->fPhase; fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj)); // copy information as it is if ( fCompl0 ) for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = ~pSims0[i]; else for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = pSims0[i]; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlNodeTransferNext( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame ) { unsigned * pSims0, * pSims1; int i; assert( iFrame < p->nFrames ); assert( !Aig_IsComplement(pOut) ); assert( !Aig_IsComplement(pIn) ); assert( Aig_ObjIsCo(pOut) ); assert( Aig_ObjIsCi(pIn) ); assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims0 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame; pSims1 = Ssw_ObjSim(p, pIn->Id) + p->nWordsFrame * (iFrame+1); // copy information as it is for ( i = 0; i < p->nWordsFrame; i++ ) pSims1[i] = pSims0[i]; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlNodeTransferFirst( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn ) { unsigned * pSims0, * pSims1; int i; assert( !Aig_IsComplement(pOut) ); assert( !Aig_IsComplement(pIn) ); assert( Aig_ObjIsCo(pOut) ); assert( Aig_ObjIsCi(pIn) ); assert( p->nWordsFrame < p->nWordsTotal ); // get hold of the simulation information pSims0 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * (p->nFrames-1); pSims1 = Ssw_ObjSim(p, pIn->Id); // copy information as it is for ( i = 0; i < p->nWordsFrame; i++ ) pSims1[i] = pSims0[i]; } /**Function************************************************************* Synopsis [Assings random simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlInitialize( Ssw_Sml_t * p, int fInit ) { Aig_Obj_t * pObj; int i; if ( fInit ) { assert( Aig_ManRegNum(p->pAig) > 0 ); assert( Aig_ManRegNum(p->pAig) <= Aig_ManCiNum(p->pAig) ); // assign random info for primary inputs Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_SmlAssignRandom( p, pObj ); // assign the initial state for the latches Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_SmlObjAssignConst( p, pObj, 0, 0 ); } else { Aig_ManForEachCi( p->pAig, pObj, i ) Ssw_SmlAssignRandom( p, pObj ); } } /**Function************************************************************* Synopsis [Assings random simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit ) { Aig_Obj_t * pObj; int Entry, i, nRegs; nRegs = Aig_ManRegNum(p->pAig); assert( nRegs > 0 ); assert( nRegs <= Aig_ManCiNum(p->pAig) ); assert( Vec_IntSize(vInit) == nRegs * p->nWordsFrame ); // assign random info for primary inputs Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_SmlAssignRandom( p, pObj ); // assign the initial state for the latches Vec_IntForEachEntry( vInit, Entry, i ) Ssw_SmlObjAssignConstWord( p, Saig_ManLo(p->pAig, i % nRegs), Entry, 0, i / nRegs ); } /**Function************************************************************* Synopsis [Assings random simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlReinitialize( Ssw_Sml_t * p ) { Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; assert( Aig_ManRegNum(p->pAig) > 0 ); assert( Aig_ManRegNum(p->pAig) < Aig_ManCiNum(p->pAig) ); // assign random info for primary inputs Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_SmlAssignRandom( p, pObj ); // copy simulation info into the inputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) Ssw_SmlNodeTransferFirst( p, pObjLi, pObjLo ); } /**Function************************************************************* Synopsis [Check if any of the POs becomes non-constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p ) { Aig_Obj_t * pObj; int i; Saig_ManForEachPo( p->pAig, pObj, i ) { if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs ) return 0; if ( !Ssw_SmlNodeIsZero(p, pObj) ) return 1; } return 0; } /**Function************************************************************* Synopsis [Simulates AIG manager.] Description [Assumes that the PI simulation info is attached.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlSimulateOne( Ssw_Sml_t * p ) { Aig_Obj_t * pObj, * pObjLi, * pObjLo; int f, i; abctime clk; clk = Abc_Clock(); for ( f = 0; f < p->nFrames; f++ ) { // simulate the nodes Aig_ManForEachNode( p->pAig, pObj, i ) Ssw_SmlNodeSimulate( p, pObj, f ); // copy simulation info into outputs Saig_ManForEachPo( p->pAig, pObj, i ) Ssw_SmlNodeCopyFanin( p, pObj, f ); // copy simulation info into outputs Saig_ManForEachLi( p->pAig, pObj, i ) Ssw_SmlNodeCopyFanin( p, pObj, f ); // quit if this is the last timeframe if ( f == p->nFrames - 1 ) break; // copy simulation info into the inputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, f ); } p->timeSim += Abc_Clock() - clk; p->nSimRounds++; } /**Function************************************************************* Synopsis [Converts simulation information to be not normallized.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlUnnormalize( Ssw_Sml_t * p ) { Aig_Obj_t * pObj; unsigned * pSims; int i, k; // convert constant 1 pSims = Ssw_ObjSim( p, 0 ); for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = ~pSims[i]; // convert internal nodes Aig_ManForEachNode( p->pAig, pObj, k ) { if ( pObj->fPhase == 0 ) continue; pSims = Ssw_ObjSim( p, pObj->Id ); for ( i = 0; i < p->nWordsFrame; i++ ) pSims[i] = ~pSims[i]; } // PIs/POs are always stored in their natural state } /**Function************************************************************* Synopsis [Simulates AIG manager.] Description [Assumes that the PI simulation info is attached.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter ) { // if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) ) // return; // Aig_ObjSetTravIdCurrent(p->pAig, pObj); if ( pVisited[p->nFrames*pObj->Id+f] == nVisCounter ) return; pVisited[p->nFrames*pObj->Id+f] = nVisCounter; if ( Saig_ObjIsPi( p->pAig, pObj ) || Aig_ObjIsConst1(pObj) ) return; if ( Saig_ObjIsLo( p->pAig, pObj ) ) { if ( f == 0 ) return; Ssw_SmlSimulateOneDyn_rec( p, Saig_ObjLoToLi(p->pAig, pObj), f-1, pVisited, nVisCounter ); Ssw_SmlNodeTransferNext( p, Saig_ObjLoToLi(p->pAig, pObj), pObj, f-1 ); return; } if ( Saig_ObjIsLi( p->pAig, pObj ) ) { Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter ); Ssw_SmlNodeCopyFanin( p, pObj, f ); return; } assert( Aig_ObjIsNode(pObj) ); Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter ); Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin1(pObj), f, pVisited, nVisCounter ); Ssw_SmlNodeSimulate( p, pObj, f ); } /**Function************************************************************* Synopsis [Simulates AIG manager.] Description [Assumes that the PI simulation info is attached.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p ) { Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; abctime clk; clk = Abc_Clock(); // simulate the nodes Aig_ManForEachNode( p->pAig, pObj, i ) Ssw_SmlNodeSimulate( p, pObj, 0 ); // copy simulation info into outputs Saig_ManForEachLi( p->pAig, pObj, i ) Ssw_SmlNodeCopyFanin( p, pObj, 0 ); // copy simulation info into the inputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, 0 ); p->timeSim += Abc_Clock() - clk; p->nSimRounds++; } /**Function************************************************************* Synopsis [Allocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ) { Ssw_Sml_t * p; p = (Ssw_Sml_t *)ABC_ALLOC( char, sizeof(Ssw_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame ); memset( p, 0, sizeof(Ssw_Sml_t) + sizeof(unsigned) * (nPref + nFrames) * nWordsFrame ); p->pAig = pAig; p->nPref = nPref; p->nFrames = nPref + nFrames; p->nWordsFrame = nWordsFrame; p->nWordsTotal = (nPref + nFrames) * nWordsFrame; p->nWordsPref = nPref * nWordsFrame; return p; } /**Function************************************************************* Synopsis [Allocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlClean( Ssw_Sml_t * p ) { memset( p->pData, 0, sizeof(unsigned) * Aig_ManObjNumMax(p->pAig) * p->nWordsTotal ); } /**Function************************************************************* Synopsis [Get simulation data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p ) { Vec_Ptr_t * vSimInfo; Aig_Obj_t * pObj; int i; vSimInfo = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); Aig_ManForEachObj( p->pAig, pObj, i ) Vec_PtrWriteEntry( vSimInfo, i, Ssw_ObjSim(p, i) ); return vSimInfo; } /**Function************************************************************* Synopsis [Deallocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlStop( Ssw_Sml_t * p ) { ABC_FREE( p ); } /**Function************************************************************* Synopsis [Performs simulation of the uninitialized circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords ) { Ssw_Sml_t * p; p = Ssw_SmlStart( pAig, 0, 1, nWords ); Ssw_SmlInitialize( p, 0 ); Ssw_SmlSimulateOne( p ); return p; } /**Function************************************************************* Synopsis [Performs simulation of the initialized circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ) { Ssw_Sml_t * p; p = Ssw_SmlStart( pAig, nPref, nFrames, nWords ); Ssw_SmlInitialize( p, 1 ); Ssw_SmlSimulateOne( p ); p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p ); return p; } /**Function************************************************************* Synopsis [Performs next round of sequential simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlResimulateSeq( Ssw_Sml_t * p ) { Ssw_SmlReinitialize( p ); Ssw_SmlSimulateOne( p ); p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p ); } /**Function************************************************************* Synopsis [Returns the number of frames simulated in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlNumFrames( Ssw_Sml_t * p ) { return p->nFrames; } /**Function************************************************************* Synopsis [Returns the total number of simulation words.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p ) { return p->nWordsTotal; } /**Function************************************************************* Synopsis [Returns the pointer to the simulation info of the node.] Description [The simulation info is normalized unless procedure Ssw_SmlUnnormalize() is called in advance.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Ssw_ObjSim( p, pObj->Id ); } /**Function************************************************************* Synopsis [Creates sequential counter-example from the simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Ssw_SmlGetCounterExample( Ssw_Sml_t * p ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; unsigned * pSims; int iPo, iFrame, iBit, i, k; // make sure the simulation manager has it assert( p->fNonConstOut ); // find the first output that failed iPo = -1; iBit = -1; iFrame = -1; Saig_ManForEachPo( p->pAig, pObj, iPo ) { if ( Ssw_SmlNodeIsZero(p, pObj) ) continue; pSims = Ssw_ObjSim( p, pObj->Id ); for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) if ( pSims[i] ) { iFrame = i / p->nWordsFrame; iBit = 32 * (i % p->nWordsFrame) + Aig_WordFindFirstBit( pSims[i] ); break; } break; } assert( iPo < Aig_ManCoNum(p->pAig)-Aig_ManRegNum(p->pAig) ); assert( iFrame < p->nFrames ); assert( iBit < 32 * p->nWordsFrame ); // allocate the counter example pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 ); pCex->iPo = iPo; pCex->iFrame = iFrame; // copy the bit data Saig_ManForEachLo( p->pAig, pObj, k ) { pSims = Ssw_ObjSim( p, pObj->Id ); if ( Abc_InfoHasBit( pSims, iBit ) ) Abc_InfoSetBit( pCex->pData, k ); } for ( i = 0; i <= iFrame; i++ ) { Saig_ManForEachPi( p->pAig, pObj, k ) { pSims = Ssw_ObjSim( p, pObj->Id ); if ( Abc_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k ); } } // verify the counter example if ( !Saig_ManVerifyCex( p->pAig, pCex ) ) { Abc_Print( 1, "Ssw_SmlGetCounterExample(): Counter-example is invalid.\n" ); Abc_CexFree( pCex ); pCex = NULL; } return pCex; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswSimSat.c000066400000000000000000000076521300674244400241100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswSimSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [Performs resimulation using counter-examples.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswSimSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Handle the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr ) { Aig_Obj_t * pObj; int i, RetValue1, RetValue2; abctime clk = Abc_Clock(); // set the PI simulation information Aig_ManConst1(p->pAig)->fMarkB = 1; Aig_ManForEachCi( p->pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, i ); // simulate internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) ); // if repr is given, perform refinement if ( pRepr ) { // check equivalence classes RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 ); RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 ); // make sure refinement happened if ( Aig_ObjIsConst1(pRepr) ) { assert( RetValue1 ); if ( RetValue1 == 0 ) Abc_Print( 1, "\nSsw_ManResimulateBit() Error: RetValue1 does not hold.\n" ); } else { assert( RetValue2 ); if ( RetValue2 == 0 ) Abc_Print( 1, "\nSsw_ManResimulateBit() Error: RetValue2 does not hold.\n" ); } } p->timeSimSat += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [Handle the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f ) { int RetValue1, RetValue2; abctime clk = Abc_Clock(); // set the PI simulation information Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords ); // simulate internal nodes Ssw_SmlSimulateOne( p->pSml ); // check equivalence classes RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 ); RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 ); // make sure refinement happened if ( Aig_ObjIsConst1(pRepr) ) { assert( RetValue1 ); if ( RetValue1 == 0 ) Abc_Print( 1, "\nSsw_ManResimulateWord() Error: RetValue1 does not hold.\n" ); } else { assert( RetValue2 ); if ( RetValue2 == 0 ) Abc_Print( 1, "\nSsw_ManResimulateWord() Error: RetValue2 does not hold.\n" ); } p->timeSimSat += Abc_Clock() - clk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswSweep.c000066400000000000000000000336121300674244400237660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswSweep.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [One round of SAT sweeping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswSweep.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" #include "misc/bar/bar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Retrives value of the PI in the original AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f ) { int fUseNoBoundary = 0; Aig_Obj_t * pObjFraig; int Value; // assert( Aig_ObjIsCi(pObj) ); pObjFraig = Ssw_ObjFrame( p, pObj, f ); if ( fUseNoBoundary ) { Value = Ssw_CnfGetNodeValue( p->pMSat, Aig_Regular(pObjFraig) ); Value ^= Aig_IsComplement(pObjFraig); } else { int nVarNum = Ssw_ObjSatNum( p->pMSat, Aig_Regular(pObjFraig) ); Value = (!nVarNum)? 0 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pMSat->pSat, nVarNum )); } // Value = (Aig_IsComplement(pObjFraig) ^ ((!nVarNum)? 0 : sat_solver_var_value( p->pSat, nVarNum ))); // Value = (!nVarNum)? Aig_ManRandom(0) & 1 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pSat, nVarNum )); if ( p->pPars->fPolarFlip ) { if ( Aig_Regular(pObjFraig)->fPhase ) Value ^= 1; } return Value; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_CheckConstraints( Ssw_Man_t * p ) { Aig_Obj_t * pObj, * pObj2; int nConstrPairs, i; int Counter = 0; nConstrPairs = Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig); assert( (nConstrPairs & 1) == 0 ); for ( i = 0; i < nConstrPairs; i += 2 ) { pObj = Aig_ManCo( p->pFrames, i ); pObj2 = Aig_ManCo( p->pFrames, i+1 ); if ( Ssw_NodesAreEquiv( p, Aig_ObjFanin0(pObj), Aig_ObjFanin0(pObj2) ) != 1 ) { Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); Counter++; } } Abc_Print( 1, "Total constraints = %d. Added constraints = %d.\n", nConstrPairs/2, Counter ); } /**Function************************************************************* Synopsis [Copy pattern from the solver into the internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlSavePatternAigPhase( Ssw_Man_t * p, int f ) { Aig_Obj_t * pObj; int i; memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); Aig_ManForEachCi( p->pAig, pObj, i ) if ( Aig_ObjPhaseReal( Ssw_ObjFrame(p, pObj, f) ) ) Abc_InfoSetBit( p->pPatWords, i ); } /**Function************************************************************* Synopsis [Copy pattern from the solver into the internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f ) { Aig_Obj_t * pObj; int i; memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); Aig_ManForEachCi( p->pAig, pObj, i ) if ( Ssw_ManGetSatVarValue( p, pObj, f ) ) Abc_InfoSetBit( p->pPatWords, i ); } /**Function************************************************************* Synopsis [Saves one counter-example into internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_SmlAddPatternDyn( Ssw_Man_t * p ) { Aig_Obj_t * pObj; unsigned * pInfo; int i, nVarNum; // iterate through the PIs of the frames Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i ) { assert( Aig_ObjIsCi(pObj) ); nVarNum = Ssw_ObjSatNum( p->pMSat, pObj ); assert( nVarNum > 0 ); if ( sat_solver_var_value( p->pMSat->pSat, nVarNum ) ) { pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObj) ); Abc_InfoSetBit( pInfo, p->nPatterns ); } } } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs ) { Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; int RetValue; abctime clk; // get representative of this class pObjRepr = Aig_ObjRepr( p->pAig, pObj ); if ( pObjRepr == NULL ) return 0; // get the fraiged node pObjFraig = Ssw_ObjFrame( p, pObj, f ); // get the fraiged representative pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f ); // check if constant 0 pattern distinquishes these nodes assert( pObjFraig != NULL && pObjReprFraig != NULL ); assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ); // if the fraiged nodes are the same, return if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) return 0; // add constraints on demand if ( !fBmc && p->pPars->fDynamic ) { clk = Abc_Clock(); Ssw_ManLoadSolver( p, pObjRepr, pObj ); p->nRecycleCalls++; p->timeMarkCones += Abc_Clock() - clk; } // call equivalence checking if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) ) RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); else RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); if ( RetValue == 1 ) // proved equivalent { pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 ); return 0; } if ( vPairs ) { Vec_IntPush( vPairs, pObjRepr->Id ); Vec_IntPush( vPairs, pObj->Id ); } if ( RetValue == -1 ) // timed out { Ssw_ClassesRemoveNode( p->ppClasses, pObj ); return 1; } // disproved the equivalence if ( !fBmc && p->pPars->fDynamic ) { Ssw_SmlAddPatternDyn( p ); p->nPatterns++; return 1; } else Ssw_SmlSavePatternAig( p, f ); if ( !p->pPars->fConstrs ) Ssw_ManResimulateWord( p, pObj, pObjRepr, f ); else Ssw_ManResimulateBit( p, pObj, pObjRepr ); assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr ); if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) { Abc_Print( 1, "Ssw_ManSweepNode(): Failed to refine representative.\n" ); } return 1; } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweepBmc( Ssw_Man_t * p ) { Bar_Progress_t * pProgress = NULL; Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo; int i, f; abctime clk; clk = Abc_Clock(); // start initialized timeframes p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); Saig_ManForEachLo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) ); // sweep internal nodes p->fRefined = 0; if ( p->pPars->fVerbose ) pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK ); for ( f = 0; f < p->pPars->nFramesK; f++ ) { // map constants and PIs Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) ); // sweep flops Saig_ManForEachLo( p->pAig, pObj, i ) p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL ); // sweep internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) { if ( p->pPars->fVerbose ) Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL ); pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL ); } // quit if this is the last timeframe if ( f == p->pPars->nFramesK - 1 ) break; // transfer latch input to the latch outputs Aig_ManForEachCo( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) ); // build logic cones for register outputs Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) { pObjNew = Ssw_ObjFrame( p, pObjLi, f ); Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew ); Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );// } } if ( p->pPars->fVerbose ) Bar_ProgressStop( pProgress ); // cleanup // Ssw_ClassesCheck( p->ppClasses ); p->timeBmc += Abc_Clock() - clk; return p->fRefined; } /**Function************************************************************* Synopsis [Generates AIG with the following nodes put into seq miters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_ManDumpEquivMiter( Aig_Man_t * p, Vec_Int_t * vPairs, int Num ) { FILE * pFile; char pBuffer[16]; Aig_Man_t * pNew; sprintf( pBuffer, "equiv%03d.aig", Num ); pFile = fopen( pBuffer, "w" ); if ( pFile == NULL ) { Abc_Print( 1, "Cannot open file %s for writing.\n", pBuffer ); return; } fclose( pFile ); pNew = Saig_ManCreateEquivMiter( p, vPairs ); Ioa_WriteAiger( pNew, pBuffer, 0, 0 ); Aig_ManStop( pNew ); Abc_Print( 1, "AIG with %4d disproved equivs is dumped into file \"%s\".\n", Vec_IntSize(vPairs)/2, pBuffer ); } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManSweep( Ssw_Man_t * p ) { static int Counter; Bar_Progress_t * pProgress = NULL; Aig_Obj_t * pObj, * pObj2, * pObjNew; int nConstrPairs, i, f; abctime clk; Vec_Int_t * vDisproved; // perform speculative reduction clk = Abc_Clock(); // create timeframes p->pFrames = Ssw_FramesWithClasses( p ); // add constants nConstrPairs = Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig); assert( (nConstrPairs & 1) == 0 ); for ( i = 0; i < nConstrPairs; i += 2 ) { pObj = Aig_ManCo( p->pFrames, i ); pObj2 = Aig_ManCo( p->pFrames, i+1 ); Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) ); } // build logic cones for register inputs for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) { pObj = Aig_ManCo( p->pFrames, nConstrPairs + i ); Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );// } sat_solver_simplify( p->pMSat->pSat ); // map constants and PIs of the last frame f = p->pPars->nFramesK; Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) ); Saig_ManForEachPi( p->pAig, pObj, i ) Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) ); p->timeReduce += Abc_Clock() - clk; // sweep internal nodes p->fRefined = 0; Ssw_ClassesClearRefined( p->ppClasses ); if ( p->pPars->fVerbose ) pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) ); vDisproved = p->pPars->fEquivDump? Vec_IntAlloc(1000) : NULL; Aig_ManForEachObj( p->pAig, pObj, i ) { if ( p->pPars->fVerbose ) Bar_ProgressUpdate( pProgress, i, NULL ); if ( Saig_ObjIsLo(p->pAig, pObj) ) p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved ); else if ( Aig_ObjIsNode(pObj) ) { pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) ); Ssw_ObjSetFrame( p, pObj, f, pObjNew ); p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved ); } } if ( p->pPars->fVerbose ) Bar_ProgressStop( pProgress ); // cleanup // Ssw_ClassesCheck( p->ppClasses ); if ( p->pPars->fEquivDump ) Ssw_ManDumpEquivMiter( p->pAig, vDisproved, Counter++ ); Vec_IntFreeP( &vDisproved ); return p->fRefined; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/proof/ssw/sswUnique.c000066400000000000000000000141661300674244400241540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [sswSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Inductive prover with constraints.] Synopsis [On-demand uniqueness constraints.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 1, 2008.] Revision [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sswInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs computation of signal correspondence with constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p ) { Aig_Obj_t * pObjLo, * pObj0, * pObj1; int i, RetValue, Counter; if ( p->vDiffPairs == NULL ) p->vDiffPairs = Vec_IntAlloc( Saig_ManRegNum(p->pAig) ); Vec_IntClear( p->vDiffPairs ); Saig_ManForEachLo( p->pAig, pObjLo, i ) { pObj0 = Ssw_ObjFrame( p, pObjLo, 0 ); pObj1 = Ssw_ObjFrame( p, pObjLo, 1 ); if ( pObj0 == pObj1 ) Vec_IntPush( p->vDiffPairs, 0 ); else if ( pObj0 == Aig_Not(pObj1) ) Vec_IntPush( p->vDiffPairs, 1 ); // else // Vec_IntPush( p->vDiffPairs, 1 ); else if ( Aig_ObjPhaseReal(pObj0) != Aig_ObjPhaseReal(pObj1) ) Vec_IntPush( p->vDiffPairs, 1 ); else { RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObj0), Aig_Regular(pObj1) ); Vec_IntPush( p->vDiffPairs, RetValue!=1 ); } } assert( Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) ); // count the number of ones Counter = 0; Vec_IntForEachEntry( p->vDiffPairs, RetValue, i ) Counter += RetValue; // Abc_Print( 1, "The number of different register pairs = %d.\n", Counter ); } /**Function************************************************************* Synopsis [Returns 1 if uniqueness constraints can be added.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose ) { Aig_Obj_t * ppObjs[2], * pTemp; int i, k, Value0, Value1, RetValue, fFeasible; assert( p->pPars->nFramesK > 1 ); assert( p->vDiffPairs && Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) ); // compute the first support in terms of LOs ppObjs[0] = pRepr; ppObjs[1] = pObj; Aig_SupportNodes( p->pAig, ppObjs, 2, p->vCommon ); // keep only LOs RetValue = Vec_PtrSize( p->vCommon ); fFeasible = 0; k = 0; Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i ) { assert( Aig_ObjIsCi(pTemp) ); if ( !Saig_ObjIsLo(p->pAig, pTemp) ) continue; assert( Aig_ObjCioId(pTemp) > 0 ); Vec_PtrWriteEntry( p->vCommon, k++, pTemp ); if ( Vec_IntEntry(p->vDiffPairs, Aig_ObjCioId(pTemp) - Saig_ManPiNum(p->pAig)) ) fFeasible = 1; } Vec_PtrShrink( p->vCommon, k ); if ( fVerbose ) Abc_Print( 1, "Node = %5d : Supp = %3d. Regs = %3d. Feasible = %s. ", Aig_ObjId(pObj), RetValue, Vec_PtrSize(p->vCommon), fFeasible? "yes": "no " ); // check the current values RetValue = 1; Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i ) { Value0 = Ssw_ManGetSatVarValue( p, pTemp, 0 ); Value1 = Ssw_ManGetSatVarValue( p, pTemp, 1 ); if ( Value0 != Value1 ) RetValue = 0; if ( fVerbose ) Abc_Print( 1, "%d", Value0 ^ Value1 ); } if ( fVerbose ) Abc_Print( 1, "\n" ); return RetValue && fFeasible; } /**Function************************************************************* Synopsis [Returns the output of the uniqueness constraint.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 ) { Aig_Obj_t * pObj, * pObj1New, * pObj2New, * pMiter, * pTotal; int i, pLits[2]; // int RetValue; assert( Vec_PtrSize(vCommon) > 0 ); // generate the constraint pTotal = Aig_ManConst0(p->pFrames); Vec_PtrForEachEntry( Aig_Obj_t *, vCommon, pObj, i ) { assert( Saig_ObjIsLo(p->pAig, pObj) ); pObj1New = Ssw_ObjFrame( p, pObj, f1 ); pObj2New = Ssw_ObjFrame( p, pObj, f2 ); pMiter = Aig_Exor( p->pFrames, pObj1New, pObj2New ); pTotal = Aig_Or( p->pFrames, pTotal, pMiter ); } if ( Aig_ObjIsConst1(Aig_Regular(pTotal)) ) { // Abc_Print( 1, "Skipped\n" ); return 0; } // create CNF Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pTotal) ); // add output constraint pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_Regular(pTotal)), Aig_IsComplement(pTotal) ); /* RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); assert( RetValue ); // simplify the solver if ( p->pSat->qtail != p->pSat->qhead ) { RetValue = sat_solver_simplify(p->pSat); assert( RetValue != 0 ); } */ assert( p->iOutputLit == -1 ); p->iOutputLit = pLits[0]; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/000077500000000000000000000000001300674244400206235ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/000077500000000000000000000000001300674244400213645ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmc.c000066400000000000000000000026541300674244400223000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmc.h000066400000000000000000000221221300674244400222750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmc.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmc.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC___sat_bmc_BMC_h #define ABC___sat_bmc_BMC_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/saig/saig.h" #include "aig/gia/gia.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // unrolling manager typedef struct Unr_Man_t_ Unr_Man_t; typedef struct Saig_ParBmc_t_ Saig_ParBmc_t; struct Saig_ParBmc_t_ { int nStart; // starting timeframe int nFramesMax; // maximum number of timeframes int nConfLimit; // maximum number of conflicts at a node int nConfLimitJump; // maximum number of conflicts after jumping int nFramesJump; // the number of tiemframes to jump int nTimeOut; // approximate timeout in seconds int nTimeOutGap; // approximate timeout in seconds since the last change int nTimeOutOne; // timeout per output in multi-output solving int nPisAbstract; // the number of PIs to abstract int fSolveAll; // does not stop at the first SAT output int fStoreCex; // enable storing CEXes in the MO mode int fUseBridge; // use bridge interface int fDropSatOuts; // replace sat outputs by constant 0 int nFfToAddMax; // max number of flops to add during CBA int fSkipRand; // skip random decisions int fNoRestarts; // disables periodic restarts int nLearnedStart; // starting learned clause limit int nLearnedDelta; // delta of learned clause limit int nLearnedPerce; // ratio of learned clause limit int fVerbose; // verbose int fNotVerbose; // skip line-by-line print-out char * pLogFileName; // log file name int fSilent; // completely silent int iFrame; // explored up to this frame int nFailOuts; // the number of failed outputs int nDropOuts; // the number of dropped outputs abctime timeLastSolved; // the time when the last output was solved int(*pFuncOnFail)(int,Abc_Cex_t*); // called for a failed output in MO mode }; typedef struct Bmc_AndPar_t_ Bmc_AndPar_t; struct Bmc_AndPar_t_ { int nStart; // starting timeframe int nFramesMax; // maximum number of timeframes int nFramesAdd; // the number of additional frames int nConfLimit; // maximum number of conflicts at a node int nTimeOut; // timeout in seconds int nLutSize; // LUT size for cut computation int fLoadCnf; // dynamic CNF loading int fDumpFrames; // dump unrolled timeframes int fUseSynth; // use synthesis int fUseOldCnf; // use old CNF construction int fVerbose; // verbose int fVeryVerbose; // very verbose int fNotVerbose; // skip line-by-line print-out int iFrame; // explored up to this frame int nFailOuts; // the number of failed outputs int nDropOuts; // the number of dropped outputs }; typedef struct Bmc_BCorePar_t_ Bmc_BCorePar_t; struct Bmc_BCorePar_t_ { int iFrame; // timeframe int iOutput; // property output int nTimeOut; // timeout in seconds char * pFilePivots; // file name with AIG IDs of pivot objects char * pFileProof; // file name to write the resulting proof int fVerbose; // verbose output }; typedef struct Bmc_MulPar_t_ Bmc_MulPar_t; struct Bmc_MulPar_t_ { int TimeOutGlo; int TimeOutLoc; int TimeOutInc; int TimeOutGap; int TimePerOut; int fUseSyn; int fDumpFinal; int fVerbose; int fVeryVerbose; }; typedef struct Bmc_ParFf_t_ Bmc_ParFf_t; struct Bmc_ParFf_t_ { char * pFileName; char * pFormStr; int Algo; int fComplVars; int fStartPats; int nTimeOut; int nIterCheck; int nCardConstr; int fNonStrict; int fBasic; int fFfOnly; int fDump; int fDumpDelay; int fDumpUntest; int fDumpNewFaults; int fVerbose; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== bmcBCore.c ==========================================================*/ extern void Bmc_ManBCorePerform( Gia_Man_t * pGia, Bmc_BCorePar_t * pPars ); /*=== bmcBmc.c ==========================================================*/ extern int Saig_ManBmcSimple( Aig_Man_t * pAig, int nFrames, int nSizeMax, int nBTLimit, int fRewrite, int fVerbose, int * piFrame, int nCofFanLit ); /*=== bmcBmc2.c ==========================================================*/ extern int Saig_BmcPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nNodesMax, int nTimeOut, int nConfMaxOne, int nConfMaxAll, int fVerbose, int fVerbOverwrite, int * piFrames, int fSilent ); /*=== bmcBmc3.c ==========================================================*/ extern void Saig_ParBmcSetDefaultParams( Saig_ParBmc_t * p ); extern int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars ); /*=== bmcBmcAnd.c ==========================================================*/ extern int Gia_ManBmcPerform( Gia_Man_t * p, Bmc_AndPar_t * pPars ); /*=== bmcCexCare.c ==========================================================*/ extern Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ); extern Abc_Cex_t * Bmc_CexCareMinimize( Aig_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose ); extern void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ); /*=== bmcCexCut.c ==========================================================*/ extern Gia_Man_t * Bmc_GiaTargetStates( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fGenAll, int fAllFrames, int fVerbose ); extern Aig_Man_t * Bmc_AigTargetStates( Aig_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fGenAll, int fAllFrames, int fVerbose ); /*=== bmcCexMin.c ==========================================================*/ extern Abc_Cex_t * Saig_ManCexMinPerform( Aig_Man_t * pAig, Abc_Cex_t * pCex ); /*=== bmcCexTool.c ==========================================================*/ extern void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose ); extern int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ); /*=== bmcICheck.c ==========================================================*/ extern void Bmc_PerformICheck( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fEmpty, int fVerbose ); extern Vec_Int_t * Bmc_PerformISearch( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fReverse, int fBackTopo, int fDump, int fVerbose ); /*=== bmcUnroll.c ==========================================================*/ extern Unr_Man_t * Unr_ManUnrollStart( Gia_Man_t * pGia, int fVerbose ); extern Gia_Man_t * Unr_ManUnrollFrame( Unr_Man_t * p, int f ); extern void Unr_ManFree( Unr_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcBCore.c000066400000000000000000000232001300674244400232010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcBCore.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Performs recording of BMC core.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcBCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/bsat/satSolver.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collect pivot variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Bmc_ManBCoreReadPivots( char * pName ) { int Num; Vec_Int_t * vPivots = Vec_IntAlloc( 100 ); FILE * pFile = fopen( pName, "r" ); while ( fscanf( pFile, "%d", &Num ) == 1 ) Vec_IntPush( vPivots, Num ); fclose( pFile ); return vPivots; } Vec_Int_t * Bmc_ManBCoreCollectPivots( Gia_Man_t * p, char * pName, Vec_Int_t * vVarMap ) { Gia_Obj_t * pObj; int i, iVar, iFrame; Vec_Int_t * vPivots = Vec_IntAlloc( 100 ); Vec_Int_t * vVars = Bmc_ManBCoreReadPivots( pName ); Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = 0; Vec_IntForEachEntry( vVars, iVar, i ) if ( iVar > 0 && iVar < Gia_ManObjNum(p) ) Gia_ManObj( p, iVar )->fMark0 = 1; else printf( "Cannot find object with Id %d in the given AIG.\n", iVar ); Vec_IntForEachEntryDouble( vVarMap, iVar, iFrame, i ) if ( Gia_ManObj( p, iVar )->fMark0 ) Vec_IntPush( vPivots, Abc_Lit2Var(i) ); Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = 0; Vec_IntFree( vVars ); return vPivots; } /**Function************************************************************* Synopsis [Collect (Id; Frame) pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Bmc_ManBCoreAssignVar( Gia_Man_t * p, Gia_Obj_t * pObj, int f, Vec_Int_t * vNodes ) { pObj->Value = Abc_Lit2Var(Vec_IntSize(vNodes)); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); Vec_IntPush( vNodes, f ); // printf( "Obj %3d Frame %3d ---> Var %3d ", Gia_ObjId(p, pObj), f, pObj->Value ); // Gia_ObjPrint( p, pObj ); } void Bmc_ManBCoreCollect_rec( Gia_Man_t * p, int Id, int f, Vec_Int_t * vNodes, Vec_Int_t * vRootsNew ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return; Gia_ObjSetTravIdCurrentId(p, Id); pObj = Gia_ManObj( p, Id ); Bmc_ManBCoreAssignVar( p, pObj, f, vNodes ); if ( Gia_ObjIsPi(p, pObj) ) return; if ( Gia_ObjIsRo(p, pObj) ) { Vec_IntPush( vRootsNew, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); return; } assert( Gia_ObjIsAnd(pObj) ); Bmc_ManBCoreCollect_rec( p, Gia_ObjFaninId0p(p, pObj), f, vNodes, vRootsNew ); Bmc_ManBCoreCollect_rec( p, Gia_ObjFaninId1p(p, pObj), f, vNodes, vRootsNew ); } Vec_Int_t * Bmc_ManBCoreCollect( Gia_Man_t * p, int iFrame, int iOut, sat_solver * pSat ) { Gia_Obj_t * pObj; int f, i, iObj, nNodesOld; Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); Vec_Int_t * vRoots = Vec_IntAlloc( 100 ); Vec_Int_t * vRoots2 = Vec_IntAlloc( 100 ); assert( iFrame >= 0 && iOut >= 0 ); // add first variables Vec_IntPush( vNodes, -1 ); Vec_IntPush( vNodes, -1 ); Bmc_ManBCoreAssignVar( p, Gia_ManPo(p, iOut), iFrame, vNodes ); // start with root node Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManPo(p, iOut)) ); // iterate through time frames for ( f = iFrame; f >= 0; f-- ) { Gia_ManIncrementTravId( p ); // add constant node Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Bmc_ManBCoreAssignVar( p, Gia_ManConst0(p), f, vNodes ); sat_solver_add_const( pSat, Gia_ManConst0(p)->Value, 1 ); // collect nodes in this timeframe Vec_IntClear( vRoots2 ); nNodesOld = Vec_IntSize(vNodes); Gia_ManForEachObjVec( vRoots, p, pObj, i ) Bmc_ManBCoreCollect_rec( p, Gia_ObjFaninId0p(p, pObj), f, vNodes, vRoots2 ); if ( f == iFrame ) { // add the final clause pObj = Gia_ManPo(p, iOut); assert( pObj->Value == 1 ); assert( Gia_ObjFanin0(pObj)->Value == 3 ); // sat_solver_add_const( pSat, Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); sat_solver_add_constraint( pSat, Gia_ObjFanin0(pObj)->Value, pObj->Value, Gia_ObjFaninC0(pObj) ); } else { // connect current RIs to previous ROs Gia_ManForEachObjVec( vRoots, p, pObj, i ) sat_solver_add_buffer( pSat, pObj->Value, Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } Gia_ManForEachObjVec( vRoots2, p, pObj, i ) pObj->Value = Gia_ObjRiToRo(p, pObj)->Value; // add nodes of this timeframe Vec_IntForEachEntryStart( vNodes, iObj, i, nNodesOld ) { pObj = Gia_ManObj(p, iObj); i++; if ( Gia_ObjIsCi(pObj) ) continue; assert( Gia_ObjIsAnd(pObj) ); sat_solver_add_and( pSat, pObj->Value, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } // collect constant node ABC_SWAP( Vec_Int_t *, vRoots, vRoots2 ); } // add constraint variables for the init state Gia_ManForEachObjVec( vRoots, p, pObj, i ) { sat_solver_add_constraint( pSat, pObj->Value, Abc_Lit2Var(Vec_IntSize(vNodes)), 1 ); pObj = Gia_ObjRiToRo(p, pObj); Bmc_ManBCoreAssignVar( p, pObj, -1, vNodes ); } Vec_IntFree( vRoots ); Vec_IntFree( vRoots2 ); return vNodes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_ManBCorePerform( Gia_Man_t * p, Bmc_BCorePar_t * pPars ) { clock_t clk = clock(); Intp_Man_t * pManProof; Vec_Int_t * vVarMap, * vCore; sat_solver * pSat; FILE * pFile; void * pSatCnf; int RetValue; // create SAT solver pSat = sat_solver_new(); sat_solver_store_alloc( pSat ); sat_solver_setnvars( pSat, 1000 ); sat_solver_set_runtime_limit( pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); vVarMap = Bmc_ManBCoreCollect( p, pPars->iFrame, pPars->iOutput, pSat ); sat_solver_store_mark_roots( pSat ); // create pivot variables if ( pPars->pFilePivots ) { Vec_Int_t * vPivots = Bmc_ManBCoreCollectPivots(p, pPars->pFilePivots, vVarMap); sat_solver_set_pivot_variables( pSat, Vec_IntArray(vPivots), Vec_IntSize(vPivots) ); Vec_IntReleaseArray( vPivots ); Vec_IntFree( vPivots ); } // solve the problem RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_Undef ) { Vec_IntFree( vVarMap ); sat_solver_delete( pSat ); printf( "Timeout of conflict limit is reached.\n" ); return; } if ( RetValue == l_True ) { Vec_IntFree( vVarMap ); sat_solver_delete( pSat ); printf( "The BMC problem is SAT.\n" ); return; } if ( pPars->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 ); // Sto_ManDumpClauses( (Sto_Man_t *)pSatCnf, "cnf_store.txt" ); // derive the UNSAT core clk = clock(); pManProof = Intp_ManAlloc(); vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, 1, pPars->fVerbose ); Intp_ManFree( pManProof ); if ( pPars->fVerbose ) { printf( "UNSAT core contains %d (out of %d) learned clauses. ", Vec_IntSize(vCore), sat_solver_nconflicts(pSat) ); Abc_PrintTime( 1, "Time", clock() - clk ); } // write the problem Vec_IntSort( vCore, 0 ); pFile = pPars->pFileProof ? fopen( pPars->pFileProof, "wb" ) : stdout; Intp_ManUnsatCorePrintForBmc( pFile, (Sto_Man_t *)pSatCnf, vCore, vVarMap ); if ( pFile != stdout ) fclose( pFile ); // cleanup Sto_ManFree( (Sto_Man_t *)pSatCnf ); Vec_IntFree( vVarMap ); Vec_IntFree( vCore ); sat_solver_delete( pSat ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcBmc.c000066400000000000000000000262371300674244400227250ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcBmc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Simple BMC package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "proof/fra/fra.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create timeframes of the manager for BMC.] Description [The resulting manager is combinational. POs correspond to \ the property outputs in each time-frame.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManFramesBmc( Aig_Man_t * pAig, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; assert( Saig_ManRegNum(pAig) > 0 ); 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_ManConst0( 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 ) Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); if ( f == nFrames - 1 ) break; // 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; } Aig_ManCleanup( pFrames ); return pFrames; } /**Function************************************************************* Synopsis [Returns the number of internal nodes that are not counted yet.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManFramesCount_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( !Aig_ObjIsNode(pObj) ) return 0; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return 0; Aig_ObjSetTravIdCurrent(p, pObj); return 1 + Saig_ManFramesCount_rec( p, Aig_ObjFanin0(pObj) ) + Saig_ManFramesCount_rec( p, Aig_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Create timeframes of the manager for BMC.] Description [The resulting manager is combinational. POs correspond to the property outputs in each time-frame. The unrolling is stopped as soon as the number of nodes in the frames exceeds the given maximum size.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManFramesBmcLimit( Aig_Man_t * pAig, int nFrames, int nSizeMax ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjPo; int i, f, Counter = 0; assert( Saig_ManRegNum(pAig) > 0 ); pFrames = Aig_ManStart( nSizeMax ); Aig_ManIncrementTravId( pFrames ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); // create variables for register outputs Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_ManConst0( pFrames ); // add timeframes Counter = 0; 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 ) { pObjPo = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); Counter += Saig_ManFramesCount_rec( pFrames, Aig_ObjFanin0(pObjPo) ); } if ( Counter >= nSizeMax ) { Aig_ManCleanup( pFrames ); return pFrames; } if ( f == nFrames - 1 ) break; // 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; } Aig_ManCleanup( pFrames ); return pFrames; } ABC_NAMESPACE_IMPL_END #include "misc/util/utilMem.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Performs BMC for the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcSimple( Aig_Man_t * pAig, int nFrames, int nSizeMax, int nConfLimit, int fRewrite, int fVerbose, int * piFrame, int nCofFanLit ) { extern Aig_Man_t * Gia_ManCofactorAig( Aig_Man_t * p, int nFrames, int nCofFanLit ); sat_solver * pSat; Cnf_Dat_t * pCnf; Aig_Man_t * pFrames, * pAigTemp; Aig_Obj_t * pObj; int status, Lit, i, RetValue = -1; abctime clk; // derive the timeframes clk = Abc_Clock(); if ( nCofFanLit ) { pFrames = Gia_ManCofactorAig( pAig, nFrames, nCofFanLit ); if ( pFrames == NULL ) return -1; } else if ( nSizeMax > 0 ) { pFrames = Saig_ManFramesBmcLimit( pAig, nFrames, nSizeMax ); nFrames = Aig_ManCoNum(pFrames) / Saig_ManPoNum(pAig) + ((Aig_ManCoNum(pFrames) % Saig_ManPoNum(pAig)) > 0); } else pFrames = Saig_ManFramesBmc( pAig, nFrames ); if ( piFrame ) *piFrame = nFrames; if ( fVerbose ) { printf( "Running \"bmc\". AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); printf( "Time-frames (%d): PI/PO = %d/%d. Node = %6d. Lev = %5d. ", nFrames, Aig_ManCiNum(pFrames), Aig_ManCoNum(pFrames), Aig_ManNodeNum(pFrames), Aig_ManLevelNum(pFrames) ); ABC_PRT( "Time", Abc_Clock() - clk ); fflush( stdout ); } // rewrite the timeframes if ( fRewrite ) { clk = Abc_Clock(); // pFrames = Dar_ManBalance( pAigTemp = pFrames, 0 ); pFrames = Dar_ManRwsat( pAigTemp = pFrames, 1, 0 ); Aig_ManStop( pAigTemp ); if ( fVerbose ) { printf( "Time-frames after rewriting: Node = %6d. Lev = %5d. ", Aig_ManNodeNum(pFrames), Aig_ManLevelNum(pFrames) ); ABC_PRT( "Time", Abc_Clock() - clk ); fflush( stdout ); } } // create the SAT solver clk = Abc_Clock(); pCnf = Cnf_Derive( pFrames, Aig_ManCoNum(pFrames) ); //if ( s_fInterrupt ) //return -1; pSat = sat_solver_new(); 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] ) ) assert( 0 ); } if ( fVerbose ) { printf( "CNF: Variables = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); ABC_PRT( "Time", Abc_Clock() - clk ); fflush( stdout ); } status = sat_solver_simplify(pSat); if ( status == 0 ) { if ( fVerbose ) { printf( "The BMC problem is trivially UNSAT\n" ); fflush( stdout ); } } else { abctime clkPart = Abc_Clock(); Aig_ManForEachCo( pFrames, pObj, i ) { //if ( s_fInterrupt ) //return -1; Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); if ( fVerbose ) { printf( "Solving output %2d of frame %3d ... \r", i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) ); } clk = Abc_Clock(); status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( fVerbose && (i % Saig_ManPoNum(pAig) == Saig_ManPoNum(pAig) - 1) ) { printf( "Solved %2d outputs of frame %3d. ", Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) ); printf( "Conf =%8.0f. Imp =%11.0f. ", (double)pSat->stats.conflicts, (double)pSat->stats.propagations ); ABC_PRT( "T", Abc_Clock() - clkPart ); clkPart = Abc_Clock(); fflush( stdout ); } if ( status == l_False ) { /* Lit = lit_neg( Lit ); RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( RetValue ); if ( pSat->qtail != pSat->qhead ) { RetValue = sat_solver_simplify(pSat); assert( RetValue ); } */ } else if ( status == l_True ) { Vec_Int_t * vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames ); int * pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); pModel[Aig_ManCiNum(pFrames)] = pObj->Id; pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pFrames, pModel ); ABC_FREE( pModel ); Vec_IntFree( vCiIds ); if ( piFrame ) *piFrame = i / Saig_ManPoNum(pAig); RetValue = 0; break; } else { if ( piFrame ) *piFrame = i / Saig_ManPoNum(pAig); RetValue = -1; break; } } } sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Aig_ManStop( pFrames ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcBmc2.c000066400000000000000000000743431300674244400230100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcBmc2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Simple BMC package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcBmc2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "proof/ssw/ssw.h" #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //#define AIG_VISITED ((Aig_Obj_t *)(ABC_PTRUINT_T)1) typedef struct Saig_Bmc_t_ Saig_Bmc_t; struct Saig_Bmc_t_ { // parameters int nFramesMax; // the max number of timeframes to consider int nNodesMax; // the max number of nodes to add int nConfMaxOne; // the max number of conflicts at a target int nConfMaxAll; // the max number of conflicts for all targets int fVerbose; // enables verbose output // AIG managers Aig_Man_t * pAig; // the user's AIG manager Aig_Man_t * pFrm; // Frames manager Vec_Int_t * vVisited; // nodes visited in Frames // node mapping int nObjs; // the largest number of an AIG object Vec_Ptr_t * vAig2Frm; // mapping of AIG nodees into Frames nodes // SAT solver sat_solver * pSat; // SAT solver int nSatVars; // the number of used SAT variables Vec_Int_t * vObj2Var; // mapping of frames objects in CNF variables int nStitchVars; // subproblems Vec_Ptr_t * vTargets; // targets to be solved in this interval int iFramePrev; // previous frame int iFrameLast; // last frame int iOutputLast; // last output int iFrameFail; // failed frame int iOutputFail; // failed output }; static inline Aig_Obj_t * Saig_BmcObjFrame( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i ) { // return (Aig_Obj_t *)Vec_PtrGetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id ); Aig_Obj_t * pRes; Vec_Int_t * vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vAig2Frm, i ); int iObjLit = Vec_IntEntry( vFrame, Aig_ObjId(pObj) ); if ( iObjLit == -1 ) return NULL; pRes = Aig_ManObj( p->pFrm, Abc_Lit2Var(iObjLit) ); if ( pRes == NULL ) Vec_IntWriteEntry( vFrame, Aig_ObjId(pObj), -1 ); else pRes = Aig_NotCond( pRes, Abc_LitIsCompl(iObjLit) ); return pRes; } static inline void Saig_BmcObjSetFrame( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { // Vec_PtrSetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id, pNode ); Vec_Int_t * vFrame; int iObjLit; if ( i == Vec_PtrSize(p->vAig2Frm) ) Vec_PtrPush( p->vAig2Frm, Vec_IntStartFull(p->nObjs) ); assert( i < Vec_PtrSize(p->vAig2Frm) ); vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vAig2Frm, i ); if ( pNode == NULL ) iObjLit = -1; else iObjLit = Abc_Var2Lit( Aig_ObjId(Aig_Regular(pNode)), Aig_IsComplement(pNode) ); Vec_IntWriteEntry( vFrame, Aig_ObjId(pObj), iObjLit ); } static inline Aig_Obj_t * Saig_BmcObjChild0( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_NotCond(Saig_BmcObjFrame(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)); } static inline Aig_Obj_t * Saig_BmcObjChild1( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_NotCond(Saig_BmcObjFrame(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)); } static inline int Saig_BmcSatNum( Saig_Bmc_t * p, Aig_Obj_t * pObj ) { return Vec_IntGetEntry( p->vObj2Var, pObj->Id ); } static inline void Saig_BmcSetSatNum( Saig_Bmc_t * p, Aig_Obj_t * pObj, int Num ) { Vec_IntSetEntry(p->vObj2Var, pObj->Id, Num); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define ABS_ZER 1 #define ABS_ONE 2 #define ABS_UND 3 static inline int Abs_ManSimInfoNot( int Value ) { if ( Value == ABS_ZER ) return ABS_ONE; if ( Value == ABS_ONE ) return ABS_ZER; return ABS_UND; } static inline int Abs_ManSimInfoAnd( int Value0, int Value1 ) { if ( Value0 == ABS_ZER || Value1 == ABS_ZER ) return ABS_ZER; if ( Value0 == ABS_ONE && Value1 == ABS_ONE ) return ABS_ONE; return ABS_UND; } static inline int Abs_ManSimInfoGet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame ) { unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, iFrame ); return 3 & (pInfo[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1)); } static inline void Abs_ManSimInfoSet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value ) { unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, iFrame ); assert( Value >= ABS_ZER && Value <= ABS_UND ); Value ^= Abs_ManSimInfoGet( vSimInfo, pObj, iFrame ); pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1)); } /**Function************************************************************* Synopsis [Performs ternary simulation for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abs_ManExtendOneEval_rec( Vec_Ptr_t * vSimInfo, Aig_Man_t * p, Aig_Obj_t * pObj, int iFrame ) { int Value0, Value1, Value; Value = Abs_ManSimInfoGet( vSimInfo, pObj, iFrame ); if ( Value ) return Value; if ( Aig_ObjIsCi(pObj) ) { assert( Saig_ObjIsLo(p, pObj) ); Value = Abs_ManExtendOneEval_rec( vSimInfo, p, Saig_ObjLoToLi(p, pObj), iFrame-1 ); Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value ); return Value; } Value0 = Abs_ManExtendOneEval_rec( vSimInfo, p, Aig_ObjFanin0(pObj), iFrame ); if ( Aig_ObjFaninC0(pObj) ) Value0 = Abs_ManSimInfoNot( Value0 ); if ( Aig_ObjIsCo(pObj) ) { Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value0 ); return Value0; } assert( Aig_ObjIsNode(pObj) ); if ( Value0 == ABS_ZER ) Value = ABS_ZER; else { Value1 = Abs_ManExtendOneEval_rec( vSimInfo, p, Aig_ObjFanin1(pObj), iFrame ); if ( Aig_ObjFaninC1(pObj) ) Value1 = Abs_ManSimInfoNot( Value1 ); Value = Abs_ManSimInfoAnd( Value0, Value1 ); } Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value ); assert( Value ); return Value; } /**Function************************************************************* Synopsis [Performs ternary simulation for one design.] Description [The returned array contains the result of ternary simulation for all the frames where the output could be proved 0.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abs_ManTernarySimulate( Aig_Man_t * p, int nFramesMax, int fVerbose ) { Vec_Ptr_t * vSimInfo; Aig_Obj_t * pObj; int i, f, nFramesLimit, nFrameWords; abctime clk = Abc_Clock(); assert( Aig_ManRegNum(p) > 0 ); // the maximum number of frames will be determined to use at most 200Mb of RAM nFramesLimit = 1 + (200000000 * 4)/Aig_ManObjNum(p); nFramesLimit = Abc_MinInt( nFramesLimit, nFramesMax ); nFrameWords = Abc_BitWordNum( 2 * Aig_ManObjNum(p) ); // allocate simulation info vSimInfo = Vec_PtrAlloc( nFramesLimit ); for ( f = 0; f < nFramesLimit; f++ ) { Vec_PtrPush( vSimInfo, ABC_CALLOC(unsigned, nFrameWords) ); if ( f == 0 ) { Saig_ManForEachLo( p, pObj, i ) Abs_ManSimInfoSet( vSimInfo, pObj, 0, ABS_ZER ); } Abs_ManSimInfoSet( vSimInfo, Aig_ManConst1(p), f, ABS_ONE ); Saig_ManForEachPi( p, pObj, i ) Abs_ManSimInfoSet( vSimInfo, pObj, f, ABS_UND ); Saig_ManForEachPo( p, pObj, i ) Abs_ManExtendOneEval_rec( vSimInfo, p, pObj, f ); // check if simulation has derived at least one fail or unknown Saig_ManForEachPo( p, pObj, i ) if ( Abs_ManSimInfoGet(vSimInfo, pObj, f) != ABS_ZER ) { if ( fVerbose ) { printf( "Ternary sim found non-zero output in frame %d. Used %5.2f MB. ", f, 0.25 * (f+1) * Aig_ManObjNum(p) / (1<<20) ); ABC_PRT( "Time", Abc_Clock() - clk ); } return vSimInfo; } } if ( fVerbose ) { printf( "Ternary sim proved all outputs in the first %d frames. Used %5.2f MB. ", nFramesLimit, 0.25 * nFramesLimit * Aig_ManObjNum(p) / (1<<20) ); ABC_PRT( "Time", Abc_Clock() - clk ); } return vSimInfo; } /**Function************************************************************* Synopsis [Free the array of simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abs_ManFreeAray( Vec_Ptr_t * p ) { void * pTemp; int i; Vec_PtrForEachEntry( void *, p, pTemp, i ) ABC_FREE( pTemp ); Vec_PtrFree( p ); } /**Function************************************************************* Synopsis [Create manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Saig_Bmc_t * Saig_BmcManStart( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConfMaxOne, int nConfMaxAll, int fVerbose ) { Saig_Bmc_t * p; Aig_Obj_t * pObj; int i, Lit; // assert( Aig_ManRegNum(pAig) > 0 ); p = (Saig_Bmc_t *)ABC_ALLOC( char, sizeof(Saig_Bmc_t) ); memset( p, 0, sizeof(Saig_Bmc_t) ); // set parameters p->nFramesMax = nFramesMax; p->nNodesMax = nNodesMax; p->nConfMaxOne = nConfMaxOne; p->nConfMaxAll = nConfMaxAll; p->fVerbose = fVerbose; p->pAig = pAig; p->nObjs = Aig_ManObjNumMax(pAig); // create node and variable mappings p->vAig2Frm = Vec_PtrAlloc( 100 ); p->vObj2Var = Vec_IntAlloc( 0 ); Vec_IntFill( p->vObj2Var, p->nObjs, 0 ); // start the AIG manager and map primary inputs p->pFrm = Aig_ManStart( p->nObjs ); Saig_ManForEachLo( pAig, pObj, i ) Saig_BmcObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrm) ); // create SAT solver p->nSatVars = 1; p->pSat = sat_solver_new(); p->pSat->nLearntStart = 10000;//p->pPars->nLearnedStart; p->pSat->nLearntDelta = 5000;//p->pPars->nLearnedDelta; p->pSat->nLearntRatio = 75;//p->pPars->nLearnedPerce; p->pSat->nLearntMax = p->pSat->nLearntStart; sat_solver_setnvars( p->pSat, 2000 ); Lit = toLit( p->nSatVars ); sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); Saig_BmcSetSatNum( p, Aig_ManConst1(p->pFrm), p->nSatVars++ ); // other data structures p->vTargets = Vec_PtrAlloc( 1000 ); p->vVisited = Vec_IntAlloc( 1000 ); p->iOutputFail = -1; p->iFrameFail = -1; return p; } /**Function************************************************************* Synopsis [Delete manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_BmcManStop( Saig_Bmc_t * p ) { Aig_ManStop( p->pFrm ); Vec_VecFree( (Vec_Vec_t *)p->vAig2Frm ); Vec_IntFree( p->vObj2Var ); sat_solver_delete( p->pSat ); Vec_PtrFree( p->vTargets ); Vec_IntFree( p->vVisited ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Explores the possibility of constructing the output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* Aig_Obj_t * Saig_BmcIntervalExplore_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i ) { Aig_Obj_t * pRes, * p0, * p1, * pConst1 = Aig_ManConst1(p->pAig); pRes = Saig_BmcObjFrame( p, pObj, i ); if ( pRes != NULL ) return pRes; if ( Saig_ObjIsPi( p->pAig, pObj ) ) pRes = AIG_VISITED; else if ( Saig_ObjIsLo( p->pAig, pObj ) ) pRes = Saig_BmcIntervalExplore_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1 ); else if ( Aig_ObjIsCo( pObj ) ) { pRes = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin0(pObj), i ); if ( pRes != AIG_VISITED ) pRes = Saig_BmcObjChild0( p, pObj, i ); } else { p0 = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin0(pObj), i ); if ( p0 != AIG_VISITED ) p0 = Saig_BmcObjChild0( p, pObj, i ); p1 = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin1(pObj), i ); if ( p1 != AIG_VISITED ) p1 = Saig_BmcObjChild1( p, pObj, i ); if ( p0 == Aig_Not(p1) ) pRes = Aig_ManConst0(p->pFrm); else if ( Aig_Regular(p0) == pConst1 ) pRes = (p0 == pConst1) ? p1 : Aig_ManConst0(p->pFrm); else if ( Aig_Regular(p1) == pConst1 ) pRes = (p1 == pConst1) ? p0 : Aig_ManConst0(p->pFrm); else pRes = AIG_VISITED; if ( pRes != AIG_VISITED && !Aig_ObjIsConst1(Aig_Regular(pRes)) ) pRes = AIG_VISITED; } Saig_BmcObjSetFrame( p, pObj, i, pRes ); return pRes; } */ /**Function************************************************************* Synopsis [Performs the actual construction of the output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i, Vec_Int_t * vVisited ) { Aig_Obj_t * pRes; pRes = Saig_BmcObjFrame( p, pObj, i ); if ( pRes != NULL ) return pRes; if ( Saig_ObjIsPi( p->pAig, pObj ) ) pRes = Aig_ObjCreateCi(p->pFrm); else if ( Saig_ObjIsLo( p->pAig, pObj ) ) pRes = Saig_BmcIntervalConstruct_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1, vVisited ); else if ( Aig_ObjIsCo( pObj ) ) { Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited ); pRes = Saig_BmcObjChild0( p, pObj, i ); } else { Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited ); if ( Saig_BmcObjChild0(p, pObj, i) == Aig_ManConst0(p->pFrm) ) pRes = Aig_ManConst0(p->pFrm); else { Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin1(pObj), i, vVisited ); pRes = Aig_And( p->pFrm, Saig_BmcObjChild0(p, pObj, i), Saig_BmcObjChild1(p, pObj, i) ); } } assert( pRes != NULL ); Saig_BmcObjSetFrame( p, pObj, i, pRes ); Vec_IntPush( vVisited, Aig_ObjId(pObj) ); Vec_IntPush( vVisited, i ); return pRes; } /**Function************************************************************* Synopsis [Adds new AIG nodes to the frames.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_BmcInterval( Saig_Bmc_t * p ) { Aig_Obj_t * pTarget; int i, iObj, iFrame; int nNodes = Aig_ManObjNum( p->pFrm ); Vec_PtrClear( p->vTargets ); p->iFramePrev = p->iFrameLast; for ( ; p->iFrameLast < p->nFramesMax; p->iFrameLast++, p->iOutputLast = 0 ) { if ( p->iOutputLast == 0 ) { Saig_BmcObjSetFrame( p, Aig_ManConst1(p->pAig), p->iFrameLast, Aig_ManConst1(p->pFrm) ); } for ( ; p->iOutputLast < Saig_ManPoNum(p->pAig); p->iOutputLast++ ) { if ( Aig_ManObjNum(p->pFrm) >= nNodes + p->nNodesMax ) return; // Saig_BmcIntervalExplore_rec( p, Aig_ManCo(p->pAig, p->iOutputLast), p->iFrameLast ); Vec_IntClear( p->vVisited ); pTarget = Saig_BmcIntervalConstruct_rec( p, Aig_ManCo(p->pAig, p->iOutputLast), p->iFrameLast, p->vVisited ); Vec_PtrPush( p->vTargets, pTarget ); Aig_ObjCreateCo( p->pFrm, pTarget ); Aig_ManCleanup( p->pFrm ); // it is not efficient to cleanup the whole manager!!! // check if the node is gone Vec_IntForEachEntryDouble( p->vVisited, iObj, iFrame, i ) Saig_BmcObjFrame( p, Aig_ManObj(p->pAig, iObj), iFrame ); // it is not efficient to remove nodes, which may be used later!!! } } } /**Function************************************************************* Synopsis [Performs the actual construction of the output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_BmcIntervalToAig_rec( Saig_Bmc_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObj ) { if ( pObj->pData ) return (Aig_Obj_t *)pObj->pData; Vec_IntPush( p->vVisited, Aig_ObjId(pObj) ); if ( Saig_BmcSatNum(p, pObj) || Aig_ObjIsCi(pObj) ) { p->nStitchVars += !Aig_ObjIsCi(pObj); return (Aig_Obj_t *)(pObj->pData = Aig_ObjCreateCi(pNew)); } Saig_BmcIntervalToAig_rec( p, pNew, Aig_ObjFanin0(pObj) ); Saig_BmcIntervalToAig_rec( p, pNew, Aig_ObjFanin1(pObj) ); assert( pObj->pData == NULL ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); } /**Function************************************************************* Synopsis [Creates AIG of the newly added nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_BmcIntervalToAig( Saig_Bmc_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew; int i; Aig_ManForEachObj( p->pFrm, pObj, i ) assert( pObj->pData == NULL ); pNew = Aig_ManStart( p->nNodesMax ); Aig_ManConst1(p->pFrm)->pData = Aig_ManConst1(pNew); Vec_IntClear( p->vVisited ); Vec_IntPush( p->vVisited, Aig_ObjId(Aig_ManConst1(p->pFrm)) ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i ) { // assert( !Aig_ObjIsConst1(Aig_Regular(pObj)) ); pObjNew = Saig_BmcIntervalToAig_rec( p, pNew, Aig_Regular(pObj) ); assert( !Aig_IsComplement(pObjNew) ); Aig_ObjCreateCo( pNew, pObjNew ); } return pNew; } /**Function************************************************************* Synopsis [Derives CNF for the newly added nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_BmcLoadCnf( Saig_Bmc_t * p, Cnf_Dat_t * pCnf ) { Aig_Obj_t * pObj, * pObjNew; int i, Lits[2], VarNumOld, VarNumNew; Aig_ManForEachObjVec( p->vVisited, p->pFrm, pObj, i ) { // get the new variable of this node pObjNew = (Aig_Obj_t *)pObj->pData; pObj->pData = NULL; VarNumNew = pCnf->pVarNums[ pObjNew->Id ]; if ( VarNumNew == -1 ) continue; // get the old variable of this node VarNumOld = Saig_BmcSatNum( p, pObj ); if ( VarNumOld == 0 ) { Saig_BmcSetSatNum( p, pObj, VarNumNew ); continue; } // add clauses connecting existing variables Lits[0] = toLitCond( VarNumOld, 0 ); Lits[1] = toLitCond( VarNumNew, 1 ); if ( !sat_solver_addclause( p->pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( VarNumOld, 1 ); Lits[1] = toLitCond( VarNumNew, 0 ); if ( !sat_solver_addclause( p->pSat, Lits, Lits+2 ) ) assert( 0 ); } // add CNF to the SAT solver for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( p->pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) break; if ( i < pCnf->nClauses ) printf( "SAT solver became UNSAT after adding clauses.\n" ); } /**Function************************************************************* Synopsis [Solves targets with the given resource limit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_BmcDeriveFailed( Saig_Bmc_t * p, int iTargetFail ) { int k; p->iOutputFail = p->iOutputLast; p->iFrameFail = p->iFrameLast; for ( k = Vec_PtrSize(p->vTargets); k > iTargetFail; k-- ) { if ( p->iOutputFail == 0 ) { p->iOutputFail = Saig_ManPoNum(p->pAig); p->iFrameFail--; } p->iOutputFail--; } } /**Function************************************************************* Synopsis [Solves targets with the given resource limit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_BmcGenerateCounterExample( Saig_Bmc_t * p ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj, * pObjFrm; int i, f, iVarNum; // start the counter-example pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), p->iFrameFail+1 ); pCex->iFrame = p->iFrameFail; pCex->iPo = p->iOutputFail; // copy the bit data for ( f = 0; f <= p->iFrameFail; f++ ) { Saig_ManForEachPi( p->pAig, pObj, i ) { pObjFrm = Saig_BmcObjFrame( p, pObj, f ); if ( pObjFrm == NULL ) continue; iVarNum = Saig_BmcSatNum( p, pObjFrm ); if ( iVarNum == 0 ) continue; if ( sat_solver_var_value( p->pSat, iVarNum ) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + Saig_ManPiNum(p->pAig) * f + i ); } } // verify the counter example if ( !Saig_ManVerifyCex( p->pAig, pCex ) ) { printf( "Saig_BmcGenerateCounterExample(): Counter-example is invalid.\n" ); Abc_CexFree( pCex ); pCex = NULL; } return pCex; } /**Function************************************************************* Synopsis [Solves targets with the given resource limit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_BmcSolveTargets( Saig_Bmc_t * p, int nStart, int * pnOutsSolved ) { Aig_Obj_t * pObj; int i, k, VarNum, Lit, status, RetValue; assert( Vec_PtrSize(p->vTargets) > 0 ); if ( p->pSat->qtail != p->pSat->qhead ) { RetValue = sat_solver_simplify(p->pSat); assert( RetValue != 0 ); } Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i ) { if ( ((*pnOutsSolved)++ / Saig_ManPoNum(p->pAig)) < nStart ) continue; if ( p->nConfMaxAll && p->pSat->stats.conflicts > p->nConfMaxAll ) return l_Undef; VarNum = Saig_BmcSatNum( p, Aig_Regular(pObj) ); Lit = toLitCond( VarNum, Aig_IsComplement(pObj) ); RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)p->nConfMaxOne, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) // unsat { // add final unit clause Lit = lit_neg( Lit ); status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); assert( status ); // add learned units for ( k = 0; k < veci_size(&p->pSat->unit_lits); k++ ) { Lit = veci_begin(&p->pSat->unit_lits)[k]; status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); assert( status ); } veci_resize(&p->pSat->unit_lits, 0); // propagate units sat_solver_compress( p->pSat ); continue; } if ( RetValue == l_Undef ) // undecided return l_Undef; // generate counter-example Saig_BmcDeriveFailed( p, i ); p->pAig->pSeqModel = Saig_BmcGenerateCounterExample( p ); { // extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, void * pCex ); // Saig_ManExtendCounterExampleTest( p->pAig, 0, p->pAig->pSeqModel ); } return l_True; } return l_False; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_BmcAddTargetsAsPos( Saig_Bmc_t * p ) { Aig_Obj_t * pObj; int i; Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i ) Aig_ObjCreateCo( p->pFrm, pObj ); Aig_ManPrintStats( p->pFrm ); Aig_ManCleanup( p->pFrm ); Aig_ManPrintStats( p->pFrm ); } /**Function************************************************************* Synopsis [Performs BMC with the given parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_BmcPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nNodesMax, int nTimeOut, int nConfMaxOne, int nConfMaxAll, int fVerbose, int fVerbOverwrite, int * piFrames, int fSilent ) { Saig_Bmc_t * p; Aig_Man_t * pNew; Cnf_Dat_t * pCnf; int nOutsSolved = 0; int Iter, RetValue = -1; abctime nTimeToStop = nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; abctime clk = Abc_Clock(), clk2, clkTotal = Abc_Clock(); int Status = -1; /* Vec_Ptr_t * vSimInfo; vSimInfo = Abs_ManTernarySimulate( pAig, nFramesMax, fVerbose ); Abs_ManFreeAray( vSimInfo ); */ if ( fVerbose ) { printf( "Running \"bmc2\". AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n", Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) ); printf( "Params: FramesMax = %d. NodesDelta = %d. ConfMaxOne = %d. ConfMaxAll = %d.\n", nFramesMax, nNodesMax, nConfMaxOne, nConfMaxAll ); } nFramesMax = nFramesMax ? nFramesMax : ABC_INFINITY; p = Saig_BmcManStart( pAig, nFramesMax, nNodesMax, nConfMaxOne, nConfMaxAll, fVerbose ); // set runtime limit if ( nTimeOut ) sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); for ( Iter = 0; ; Iter++ ) { clk2 = Abc_Clock(); // add new logic interval to frames Saig_BmcInterval( p ); // Saig_BmcAddTargetsAsPos( p ); if ( Vec_PtrSize(p->vTargets) == 0 ) break; // convert logic slice into new AIG pNew = Saig_BmcIntervalToAig( p ); //printf( "StitchVars = %d.\n", p->nStitchVars ); // derive CNF for the new AIG pCnf = Cnf_Derive( pNew, Aig_ManCoNum(pNew) ); Cnf_DataLift( pCnf, p->nSatVars ); p->nSatVars += pCnf->nVars; // add this CNF to the solver Saig_BmcLoadCnf( p, pCnf ); Cnf_DataFree( pCnf ); Aig_ManStop( pNew ); // solve the targets RetValue = Saig_BmcSolveTargets( p, nStart, &nOutsSolved ); if ( fVerbose ) { printf( "%4d : F =%5d. O =%4d. And =%8d. Var =%8d. Conf =%7d. ", Iter, p->iFrameLast, p->iOutputLast, Aig_ManNodeNum(p->pFrm), p->nSatVars, (int)p->pSat->stats.conflicts ); printf( "%4.0f MB", 4.0*(p->iFrameLast+1)*p->nObjs/(1<<20) ); printf( "%9.2f sec", (float)(Abc_Clock() - clkTotal)/(float)(CLOCKS_PER_SEC) ); printf( "\n" ); fflush( stdout ); } if ( RetValue != l_False ) break; // check the timeout if ( nTimeOut && Abc_Clock() > nTimeToStop ) { if ( !fSilent ) printf( "Reached timeout (%d seconds).\n", nTimeOut ); if ( piFrames ) *piFrames = p->iFrameLast-1; Saig_BmcManStop( p ); return Status; } } if ( RetValue == l_True ) { assert( p->iFrameFail * Saig_ManPoNum(p->pAig) + p->iOutputFail + 1 == nOutsSolved ); if ( !fSilent ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->iOutputFail, p->pAig->pName, p->iFrameFail ); Status = 0; if ( piFrames ) *piFrames = p->iFrameFail - 1; } else // if ( RetValue == l_False || RetValue == l_Undef ) { if ( !fSilent ) Abc_Print( 1, "No output failed in %d frames. ", Abc_MaxInt(p->iFramePrev-1, 0) ); if ( piFrames ) { if ( p->iOutputLast > 0 ) *piFrames = p->iFramePrev - 2; else *piFrames = p->iFramePrev - 1; } } if ( !fSilent ) { if ( fVerbOverwrite ) { ABC_PRTr( "Time", Abc_Clock() - clk ); } else { ABC_PRT( "Time", Abc_Clock() - clk ); } if ( RetValue != l_True ) { if ( p->iFrameLast >= p->nFramesMax ) printf( "Reached limit on the number of timeframes (%d).\n", p->nFramesMax ); else if ( p->nConfMaxAll && p->pSat->stats.conflicts > p->nConfMaxAll ) printf( "Reached global conflict limit (%d).\n", p->nConfMaxAll ); else if ( nTimeOut && Abc_Clock() > nTimeToStop ) printf( "Reached timeout (%d seconds).\n", nTimeOut ); else printf( "Reached local conflict limit (%d).\n", p->nConfMaxOne ); } } Saig_BmcManStop( p ); fflush( stdout ); return Status; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcBmc3.c000066400000000000000000001671021300674244400230050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcBmc3.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Simple BMC package.] Author [Alan Mishchenko in collaboration with Niklas Een.] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcBmc3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "proof/fra/fra.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "misc/vec/vecHsh.h" #include "misc/vec/vecWec.h" #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Gia_ManBmc_t_ Gia_ManBmc_t; struct Gia_ManBmc_t_ { // input/output data Saig_ParBmc_t * pPars; // parameters Aig_Man_t * pAig; // user AIG Vec_Ptr_t * vCexes; // counter-examples // intermediate data Vec_Int_t * vMapping; // mapping Vec_Int_t * vMapRefs; // mapping references // Vec_Vec_t * vSects; // sections Vec_Int_t * vId2Num; // number of each node Vec_Ptr_t * vTerInfo; // ternary information Vec_Ptr_t * vId2Var; // SAT vars for each object Vec_Wec_t * vVisited; // visited nodes abctime * pTime4Outs; // timeout per output // hash table Vec_Int_t * vData; // storage for cuts Hsh_IntMan_t * vHash; // hash table Vec_Int_t * vId2Lit; // mapping cuts into literals int nHashHit; // hash table hits int nHashMiss; // hash table misses int nBufNum; // the number of simple nodes int nDupNum; // the number of simple nodes int nUniProps; // propagating learned clause values int nLitUsed; // used literals int nLitUseless; // useless literals // SAT solver sat_solver * pSat; // SAT solver int nSatVars; // SAT variables int nObjNums; // SAT objects int nWordNum; // unsigned words for ternary simulation char * pSopSizes, ** pSops; // CNF representation }; extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved ); void Gia_ManReportProgress( FILE * pFile, int prop_no, int depth ) { extern int Gia_ManToBridgeProgress( FILE * pFile, int Size, unsigned char * pBuffer ); char buf[100]; sprintf(buf, "property: safe<%d>\nbug-free-depth: %d\n", prop_no, depth); Gia_ManToBridgeProgress(pFile, strlen(buf), (unsigned char *)buf); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define SAIG_TER_NON 0 #define SAIG_TER_ZER 1 #define SAIG_TER_ONE 2 #define SAIG_TER_UND 3 static inline int Saig_ManBmcSimInfoNot( int Value ) { if ( Value == SAIG_TER_ZER ) return SAIG_TER_ONE; if ( Value == SAIG_TER_ONE ) return SAIG_TER_ZER; return SAIG_TER_UND; } static inline int Saig_ManBmcSimInfoAnd( int Value0, int Value1 ) { if ( Value0 == SAIG_TER_ZER || Value1 == SAIG_TER_ZER ) return SAIG_TER_ZER; if ( Value0 == SAIG_TER_ONE && Value1 == SAIG_TER_ONE ) return SAIG_TER_ONE; return SAIG_TER_UND; } static inline int Saig_ManBmcSimInfoGet( unsigned * pInfo, Aig_Obj_t * pObj ) { return 3 & (pInfo[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1)); } static inline void Saig_ManBmcSimInfoSet( unsigned * pInfo, Aig_Obj_t * pObj, int Value ) { assert( Value >= SAIG_TER_ZER && Value <= SAIG_TER_UND ); Value ^= Saig_ManBmcSimInfoGet( pInfo, pObj ); pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1)); } static inline int Saig_ManBmcSimInfoClear( unsigned * pInfo, Aig_Obj_t * pObj ) { int Value = Saig_ManBmcSimInfoGet( pInfo, pObj ); pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1)); return Value; } /**Function************************************************************* Synopsis [Returns the number of LIs with binary ternary info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcTerSimCount01( Aig_Man_t * p, unsigned * pInfo ) { Aig_Obj_t * pObj; int i, Counter = 0; if ( pInfo == NULL ) return Saig_ManRegNum(p); Saig_ManForEachLi( p, pObj, i ) if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) Counter += (Saig_ManBmcSimInfoGet(pInfo, pObj) != SAIG_TER_UND); return Counter; } /**Function************************************************************* Synopsis [Performs ternary simulation of one frame.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Saig_ManBmcTerSimOne( Aig_Man_t * p, unsigned * pPrev ) { Aig_Obj_t * pObj, * pObjLi; unsigned * pInfo; int i, Val0, Val1; pInfo = ABC_CALLOC( unsigned, Abc_BitWordNum(2 * Aig_ManObjNumMax(p)) ); Saig_ManBmcSimInfoSet( pInfo, Aig_ManConst1(p), SAIG_TER_ONE ); Saig_ManForEachPi( p, pObj, i ) Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_UND ); if ( pPrev == NULL ) { Saig_ManForEachLo( p, pObj, i ) Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_ZER ); } else { Saig_ManForEachLiLo( p, pObjLi, pObj, i ) Saig_ManBmcSimInfoSet( pInfo, pObj, Saig_ManBmcSimInfoGet(pPrev, pObjLi) ); } Aig_ManForEachNode( p, pObj, i ) { Val0 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin0(pObj) ); Val1 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin1(pObj) ); if ( Aig_ObjFaninC0(pObj) ) Val0 = Saig_ManBmcSimInfoNot( Val0 ); if ( Aig_ObjFaninC1(pObj) ) Val1 = Saig_ManBmcSimInfoNot( Val1 ); Saig_ManBmcSimInfoSet( pInfo, pObj, Saig_ManBmcSimInfoAnd(Val0, Val1) ); } Aig_ManForEachCo( p, pObj, i ) { Val0 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin0(pObj) ); if ( Aig_ObjFaninC0(pObj) ) Val0 = Saig_ManBmcSimInfoNot( Val0 ); Saig_ManBmcSimInfoSet( pInfo, pObj, Val0 ); } return pInfo; } /**Function************************************************************* Synopsis [Collects internal nodes and PIs in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManBmcTerSim( Aig_Man_t * p ) { Vec_Ptr_t * vInfos; unsigned * pInfo = NULL; int i, TerPrev = ABC_INFINITY, TerCur, CountIncrease = 0; vInfos = Vec_PtrAlloc( 100 ); for ( i = 0; i < 1000 && CountIncrease < 5 && TerPrev > 0; i++ ) { TerCur = Saig_ManBmcTerSimCount01( p, pInfo ); if ( TerCur >= TerPrev ) CountIncrease++; TerPrev = TerCur; pInfo = Saig_ManBmcTerSimOne( p, pInfo ); Vec_PtrPush( vInfos, pInfo ); } return vInfos; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBmcTerSimTest( Aig_Man_t * p ) { Vec_Ptr_t * vInfos; unsigned * pInfo; int i; vInfos = Saig_ManBmcTerSim( p ); Vec_PtrForEachEntry( unsigned *, vInfos, pInfo, i ) Abc_Print( 1, "%d=%d ", i, Saig_ManBmcTerSimCount01(p, pInfo) ); Abc_Print( 1, "\n" ); Vec_PtrFreeFree( vInfos ); } /**Function************************************************************* Synopsis [Count the number of non-ternary per frame.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcCountNonternary_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vInfos, unsigned * pInfo, int f, int * pCounter ) { int Value = Saig_ManBmcSimInfoClear( pInfo, pObj ); if ( Value == SAIG_TER_NON ) return 0; assert( f >= 0 ); pCounter[f] += (Value == SAIG_TER_UND); if ( Saig_ObjIsPi(p, pObj) || (f == 0 && Saig_ObjIsLo(p, pObj)) || Aig_ObjIsConst1(pObj) ) return 0; if ( Saig_ObjIsLi(p, pObj) ) return Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(pObj), vInfos, pInfo, f, pCounter ); if ( Saig_ObjIsLo(p, pObj) ) return Saig_ManBmcCountNonternary_rec( p, Saig_ObjLoToLi(p, pObj), vInfos, (unsigned *)Vec_PtrEntry(vInfos, f-1), f-1, pCounter ); assert( Aig_ObjIsNode(pObj) ); Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(pObj), vInfos, pInfo, f, pCounter ); Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin1(pObj), vInfos, pInfo, f, pCounter ); return 0; } void Saig_ManBmcCountNonternary( Aig_Man_t * p, Vec_Ptr_t * vInfos, int iFrame ) { int i, * pCounters = ABC_CALLOC( int, iFrame + 1 ); unsigned * pInfo = (unsigned *)Vec_PtrEntry(vInfos, iFrame); assert( Saig_ManBmcSimInfoGet( pInfo, Aig_ManCo(p, 0) ) == SAIG_TER_UND ); Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(Aig_ManCo(p, 0)), vInfos, pInfo, iFrame, pCounters ); for ( i = 0; i <= iFrame; i++ ) Abc_Print( 1, "%d=%d ", i, pCounters[i] ); Abc_Print( 1, "\n" ); ABC_FREE( pCounters ); } /**Function************************************************************* Synopsis [Returns the number of POs with binary ternary info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcTerSimCount01Po( Aig_Man_t * p, unsigned * pInfo ) { Aig_Obj_t * pObj; int i, Counter = 0; Saig_ManForEachPo( p, pObj, i ) Counter += (Saig_ManBmcSimInfoGet(pInfo, pObj) != SAIG_TER_UND); return Counter; } Vec_Ptr_t * Saig_ManBmcTerSimPo( Aig_Man_t * p ) { Vec_Ptr_t * vInfos; unsigned * pInfo = NULL; int i, nPoBin; vInfos = Vec_PtrAlloc( 100 ); for ( i = 0; ; i++ ) { if ( i % 100 == 0 ) Abc_Print( 1, "Frame %5d\n", i ); pInfo = Saig_ManBmcTerSimOne( p, pInfo ); Vec_PtrPush( vInfos, pInfo ); nPoBin = Saig_ManBmcTerSimCount01Po( p, pInfo ); if ( nPoBin < Saig_ManPoNum(p) ) break; } Abc_Print( 1, "Detected terminary PO in frame %d.\n", i ); Saig_ManBmcCountNonternary( p, vInfos, i ); return vInfos; } void Saig_ManBmcTerSimTestPo( Aig_Man_t * p ) { Vec_Ptr_t * vInfos; vInfos = Saig_ManBmcTerSimPo( p ); Vec_PtrFreeFree( vInfos ); } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBmcDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsNode(pObj) ) { Saig_ManBmcDfs_rec( p, Aig_ObjFanin0(pObj), vNodes ); Saig_ManBmcDfs_rec( p, Aig_ObjFanin1(pObj), vNodes ); } Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Collects internal nodes and PIs in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManBmcDfsNodes( Aig_Man_t * p, Vec_Ptr_t * vRoots ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; vNodes = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) Saig_ManBmcDfs_rec( p, Aig_ObjFanin0(pObj), vNodes ); return vNodes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_ManBmcSections( Aig_Man_t * p ) { Vec_Ptr_t * vSects, * vRoots, * vCone; Aig_Obj_t * pObj, * pObjPo; int i; Aig_ManIncrementTravId( p ); Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); // start the roots vRoots = Vec_PtrAlloc( 1000 ); Saig_ManForEachPo( p, pObjPo, i ) { Aig_ObjSetTravIdCurrent( p, pObjPo ); Vec_PtrPush( vRoots, pObjPo ); } // compute the cones vSects = Vec_PtrAlloc( 20 ); while ( Vec_PtrSize(vRoots) > 0 ) { vCone = Saig_ManBmcDfsNodes( p, vRoots ); Vec_PtrPush( vSects, vCone ); // get the next set of roots Vec_PtrClear( vRoots ); Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i ) { if ( !Saig_ObjIsLo(p, pObj) ) continue; pObjPo = Saig_ObjLoToLi( p, pObj ); if ( Aig_ObjIsTravIdCurrent(p, pObjPo) ) continue; Aig_ObjSetTravIdCurrent( p, pObjPo ); Vec_PtrPush( vRoots, pObjPo ); } } Vec_PtrFree( vRoots ); return (Vec_Vec_t *)vSects; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBmcSectionsTest( Aig_Man_t * p ) { Vec_Vec_t * vSects; Vec_Ptr_t * vOne; int i; vSects = Saig_ManBmcSections( p ); Vec_VecForEachLevel( vSects, vOne, i ) Abc_Print( 1, "%d=%d ", i, Vec_PtrSize(vOne) ); Abc_Print( 1, "\n" ); Vec_VecFree( vSects ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBmcSupergate_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_Regular(pObj) ); return; } // go through the branches Saig_ManBmcSupergate_rec( Aig_ObjChild0(pObj), vSuper ); Saig_ManBmcSupergate_rec( Aig_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Collect the topmost supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManBmcSupergate( Aig_Man_t * p, int iPo ) { Vec_Ptr_t * vSuper; Aig_Obj_t * pObj; vSuper = Vec_PtrAlloc( 10 ); pObj = Aig_ManCo( p, iPo ); pObj = Aig_ObjChild0( pObj ); if ( !Aig_IsComplement(pObj) ) { Vec_PtrPush( vSuper, pObj ); return vSuper; } pObj = Aig_Regular( pObj ); if ( !Aig_ObjIsNode(pObj) ) { Vec_PtrPush( vSuper, pObj ); return vSuper; } Saig_ManBmcSupergate_rec( Aig_ObjChild0(pObj), vSuper ); Saig_ManBmcSupergate_rec( Aig_ObjChild1(pObj), vSuper ); return vSuper; } /**Function************************************************************* Synopsis [Returns the number of nodes with ref counter more than 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcCountRefed( Aig_Man_t * p, Vec_Ptr_t * vSuper ) { Aig_Obj_t * pObj; int i, Counter = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) { assert( !Aig_IsComplement(pObj) ); Counter += (Aig_ObjRefs(pObj) > 1); } return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBmcSupergateTest( Aig_Man_t * p ) { Vec_Ptr_t * vSuper; Aig_Obj_t * pObj; int i; Abc_Print( 1, "Supergates: " ); Saig_ManForEachPo( p, pObj, i ) { vSuper = Saig_ManBmcSupergate( p, i ); Abc_Print( 1, "%d=%d(%d) ", i, Vec_PtrSize(vSuper), Saig_ManBmcCountRefed(p, vSuper) ); Vec_PtrFree( vSuper ); } Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBmcWriteBlif( Aig_Man_t * p, Vec_Int_t * vMapping, char * pFileName ) { FILE * pFile; char * pSopSizes, ** pSops; Aig_Obj_t * pObj; char Vals[4]; int i, k, b, iFan, iTruth, * pData; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { Abc_Print( 1, "Cannot open file %s\n", pFileName ); return; } fprintf( pFile, ".model test\n" ); fprintf( pFile, ".inputs" ); Aig_ManForEachCi( p, pObj, i ) fprintf( pFile, " n%d", Aig_ObjId(pObj) ); fprintf( pFile, "\n" ); fprintf( pFile, ".outputs" ); Aig_ManForEachCo( p, pObj, i ) fprintf( pFile, " n%d", Aig_ObjId(pObj) ); fprintf( pFile, "\n" ); fprintf( pFile, ".names" ); fprintf( pFile, " n%d\n", Aig_ObjId(Aig_ManConst1(p)) ); fprintf( pFile, " 1\n" ); Cnf_ReadMsops( &pSopSizes, &pSops ); Aig_ManForEachNode( p, pObj, i ) { if ( Vec_IntEntry(vMapping, i) == 0 ) continue; pData = Vec_IntEntryP( vMapping, Vec_IntEntry(vMapping, i) ); fprintf( pFile, ".names" ); for ( iFan = 0; iFan < 4; iFan++ ) if ( pData[iFan+1] >= 0 ) fprintf( pFile, " n%d", pData[iFan+1] ); else break; fprintf( pFile, " n%d\n", i ); // write SOP iTruth = pData[0] & 0xffff; for ( k = 0; k < pSopSizes[iTruth]; k++ ) { int Lit = pSops[iTruth][k]; for ( b = 3; b >= 0; b-- ) { if ( Lit % 3 == 0 ) Vals[b] = '0'; else if ( Lit % 3 == 1 ) Vals[b] = '1'; else Vals[b] = '-'; Lit = Lit / 3; } for ( b = 0; b < iFan; b++ ) fprintf( pFile, "%c", Vals[b] ); fprintf( pFile, " 1\n" ); } } free( pSopSizes ); free( pSops[1] ); free( pSops ); Aig_ManForEachCo( p, pObj, i ) { fprintf( pFile, ".names" ); fprintf( pFile, " n%d", Aig_ObjId(Aig_ObjFanin0(pObj)) ); fprintf( pFile, " n%d\n", Aig_ObjId(pObj) ); fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) ); } fprintf( pFile, ".end\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBmcMappingTest( Aig_Man_t * p ) { Vec_Int_t * vMapping; vMapping = Cnf_DeriveMappingArray( p ); Saig_ManBmcWriteBlif( p, vMapping, "test.blif" ); Vec_IntFree( vMapping ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManBmcComputeMappingRefs( Aig_Man_t * p, Vec_Int_t * vMap ) { Vec_Int_t * vRefs; Aig_Obj_t * pObj; int i, iFan, * pData; vRefs = Vec_IntStart( Aig_ManObjNumMax(p) ); Aig_ManForEachCo( p, pObj, i ) Vec_IntAddToEntry( vRefs, Aig_ObjFaninId0(pObj), 1 ); Aig_ManForEachNode( p, pObj, i ) { if ( Vec_IntEntry(vMap, i) == 0 ) continue; pData = Vec_IntEntryP( vMap, Vec_IntEntry(vMap, i) ); for ( iFan = 0; iFan < 4; iFan++ ) if ( pData[iFan+1] >= 0 ) Vec_IntAddToEntry( vRefs, pData[iFan+1], 1 ); } return vRefs; } /**Function************************************************************* Synopsis [Create manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManBmc_t * Saig_Bmc3ManStart( Aig_Man_t * pAig, int nTimeOutOne ) { Gia_ManBmc_t * p; Aig_Obj_t * pObj; int i; // assert( Aig_ManRegNum(pAig) > 0 ); p = ABC_CALLOC( Gia_ManBmc_t, 1 ); p->pAig = pAig; // create mapping p->vMapping = Cnf_DeriveMappingArray( pAig ); p->vMapRefs = Saig_ManBmcComputeMappingRefs( pAig, p->vMapping ); // create sections // p->vSects = Saig_ManBmcSections( pAig ); // map object IDs into their numbers and section numbers p->nObjNums = 0; p->vId2Num = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); Vec_IntWriteEntry( p->vId2Num, Aig_ObjId(Aig_ManConst1(pAig)), p->nObjNums++ ); Aig_ManForEachCi( pAig, pObj, i ) Vec_IntWriteEntry( p->vId2Num, Aig_ObjId(pObj), p->nObjNums++ ); Aig_ManForEachNode( pAig, pObj, i ) if ( Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) > 0 ) Vec_IntWriteEntry( p->vId2Num, Aig_ObjId(pObj), p->nObjNums++ ); Aig_ManForEachCo( pAig, pObj, i ) Vec_IntWriteEntry( p->vId2Num, Aig_ObjId(pObj), p->nObjNums++ ); p->vId2Var = Vec_PtrAlloc( 100 ); p->vTerInfo = Vec_PtrAlloc( 100 ); p->vVisited = Vec_WecAlloc( 100 ); // create solver p->nSatVars = 1; p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, 1000 ); Cnf_ReadMsops( &p->pSopSizes, &p->pSops ); // terminary simulation p->nWordNum = Abc_BitWordNum( 2 * Aig_ManObjNumMax(pAig) ); // hash table p->vData = Vec_IntAlloc( 5 * 10000 ); p->vHash = Hsh_IntManStart( p->vData, 5, 10000 ); p->vId2Lit = Vec_IntAlloc( 10000 ); // time spent on each outputs if ( nTimeOutOne ) { p->pTime4Outs = ABC_ALLOC( abctime, Saig_ManPoNum(pAig) ); for ( i = 0; i < Saig_ManPoNum(pAig); i++ ) p->pTime4Outs[i] = nTimeOutOne * CLOCKS_PER_SEC / 1000 + 1; } return p; } /**Function************************************************************* Synopsis [Delete manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_Bmc3ManStop( Gia_ManBmc_t * p ) { if ( p->pPars->fVerbose ) { int nUsedVars = sat_solver_count_usedvars(p->pSat); Abc_Print( 1, "LStart(P) = %d LDelta(Q) = %d LRatio(R) = %d ReduceDB = %d Vars = %d Used = %d (%.2f %%)\n", p->pSat->nLearntStart, p->pSat->nLearntDelta, p->pSat->nLearntRatio, p->pSat->nDBreduces, p->pSat->size, nUsedVars, 100.0*nUsedVars/p->pSat->size ); Abc_Print( 1, "Buffs = %d. Dups = %d. Hash hits = %d. Hash misses = %d. UniProps = %d.\n", p->nBufNum, p->nDupNum, p->nHashHit, p->nHashMiss, p->nUniProps ); } // Aig_ManCleanMarkA( p->pAig ); if ( p->vCexes ) { assert( p->pAig->vSeqModelVec == NULL ); p->pAig->vSeqModelVec = p->vCexes; p->vCexes = NULL; } // Vec_PtrFreeFree( p->vCexes ); Vec_WecFree( p->vVisited ); Vec_IntFree( p->vMapping ); Vec_IntFree( p->vMapRefs ); // Vec_VecFree( p->vSects ); Vec_IntFree( p->vId2Num ); Vec_VecFree( (Vec_Vec_t *)p->vId2Var ); Vec_PtrFreeFree( p->vTerInfo ); sat_solver_delete( p->pSat ); ABC_FREE( p->pTime4Outs ); Vec_IntFree( p->vData ); Hsh_IntManStop( p->vHash ); Vec_IntFree( p->vId2Lit ); ABC_FREE( p->pSopSizes ); ABC_FREE( p->pSops[1] ); ABC_FREE( p->pSops ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Saig_ManBmcMapping( Gia_ManBmc_t * p, Aig_Obj_t * pObj ) { if ( Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) == 0 ) return NULL; return Vec_IntEntryP( p->vMapping, Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Saig_ManBmcLiteral( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame ) { Vec_Int_t * vFrame; int ObjNum; assert( !Aig_ObjIsNode(pObj) || Saig_ManBmcMapping(p, pObj) ); ObjNum = Vec_IntEntry( p->vId2Num, Aig_ObjId(pObj) ); assert( ObjNum >= 0 ); vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vId2Var, iFrame ); assert( vFrame != NULL ); return Vec_IntEntry( vFrame, ObjNum ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Saig_ManBmcSetLiteral( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame, int iLit ) { Vec_Int_t * vFrame; int ObjNum; assert( !Aig_ObjIsNode(pObj) || Saig_ManBmcMapping(p, pObj) ); ObjNum = Vec_IntEntry( p->vId2Num, Aig_ObjId(pObj) ); vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vId2Var, iFrame ); Vec_IntWriteEntry( vFrame, ObjNum, iLit ); /* if ( Vec_IntEntry( p->vMapRefs, Aig_ObjId(pObj) ) > 1 ) p->nLitUsed++; else p->nLitUseless++; */ return iLit; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Saig_ManBmcCof0( int t, int v ) { static int s_Truth[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 }; return 0xffff & ((t & ~s_Truth[v]) | ((t & ~s_Truth[v]) << (1<> (1<= 0 && v <= 3 ); if ( v == 0 ) return ((t & 0xAAAA) >> 1) == (t & 0x5555); if ( v == 1 ) return ((t & 0xCCCC) >> 2) == (t & 0x3333); if ( v == 2 ) return ((t & 0xF0F0) >> 4) == (t & 0x0F0F); if ( v == 3 ) return ((t & 0xFF00) >> 8) == (t & 0x00FF); return -1; } /**Function************************************************************* Synopsis [Derives CNF for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Saig_ManBmcReduceTruth( int uTruth, int Lits[] ) { int v; for ( v = 0; v < 4; v++ ) if ( Lits[v] == 0 ) { uTruth = Saig_ManBmcCof0(uTruth, v); Lits[v] = -1; } else if ( Lits[v] == 1 ) { uTruth = Saig_ManBmcCof1(uTruth, v); Lits[v] = -1; } for ( v = 0; v < 4; v++ ) if ( Lits[v] == -1 ) assert( Saig_ManBmcCofEqual(uTruth, v) ); else if ( Saig_ManBmcCofEqual(uTruth, v) ) Lits[v] = -1; return uTruth; } /**Function************************************************************* Synopsis [Derives CNF for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Saig_ManBmcAddClauses( Gia_ManBmc_t * p, int uTruth, int Lits[], int iLitOut ) { int i, k, b, CutLit, nClaLits, ClaLits[5]; assert( uTruth > 0 && uTruth < 0xffff ); // write positive/negative polarity for ( i = 0; i < 2; i++ ) { if ( i ) uTruth = 0xffff & ~uTruth; // Extra_PrintBinary( stdout, &uTruth, 16 ); Abc_Print( 1, "\n" ); for ( k = 0; k < p->pSopSizes[uTruth]; k++ ) { nClaLits = 0; ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut; CutLit = p->pSops[uTruth][k]; for ( b = 3; b >= 0; b-- ) { if ( CutLit % 3 == 0 ) // value 0 --> write positive literal { assert( Lits[b] > 1 ); ClaLits[nClaLits++] = Lits[b]; } else if ( CutLit % 3 == 1 ) // value 1 --> write negative literal { assert( Lits[b] > 1 ); ClaLits[nClaLits++] = lit_neg(Lits[b]); } CutLit = CutLit / 3; } if ( !sat_solver_addclause( p->pSat, ClaLits, ClaLits+nClaLits ) ) assert( 0 ); } } } /**Function************************************************************* Synopsis [Derives CNF for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcCreateCnf_rec( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame ) { extern unsigned Dar_CutSortVars( unsigned uTruth, int * pVars ); int * pMapping, i, iLit, Lits[5], uTruth; iLit = Saig_ManBmcLiteral( p, pObj, iFrame ); if ( iLit != ~0 ) return iLit; assert( iFrame >= 0 ); if ( Aig_ObjIsCi(pObj) ) { if ( Saig_ObjIsPi(p->pAig, pObj) ) iLit = toLit( p->nSatVars++ ); else iLit = Saig_ManBmcCreateCnf_rec( p, Saig_ObjLoToLi(p->pAig, pObj), iFrame-1 ); return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit ); } if ( Aig_ObjIsCo(pObj) ) { iLit = Saig_ManBmcCreateCnf_rec( p, Aig_ObjFanin0(pObj), iFrame ); if ( Aig_ObjFaninC0(pObj) ) iLit = lit_neg(iLit); return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit ); } assert( Aig_ObjIsNode(pObj) ); pMapping = Saig_ManBmcMapping( p, pObj ); for ( i = 0; i < 4; i++ ) if ( pMapping[i+1] == -1 ) Lits[i] = -1; else Lits[i] = Saig_ManBmcCreateCnf_rec( p, Aig_ManObj(p->pAig, pMapping[i+1]), iFrame ); uTruth = 0xffff & (unsigned)pMapping[0]; // propagate constants uTruth = Saig_ManBmcReduceTruth( uTruth, Lits ); if ( uTruth == 0 || uTruth == 0xffff ) { iLit = (uTruth == 0xffff); return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit ); } // canonicize inputs uTruth = Dar_CutSortVars( uTruth, Lits ); assert( uTruth != 0 && uTruth != 0xffff ); if ( uTruth == 0xAAAA || uTruth == 0x5555 ) { iLit = Abc_LitNotCond( Lits[0], uTruth == 0x5555 ); p->nBufNum++; } else { int iEntry, iRes; int fCompl = (uTruth & 1); Lits[4] = (uTruth & 1) ? 0xffff & ~uTruth : uTruth; iEntry = Vec_IntSize(p->vData) / 5; assert( iEntry * 5 == Vec_IntSize(p->vData) ); for ( i = 0; i < 5; i++ ) Vec_IntPush( p->vData, Lits[i] ); iRes = Hsh_IntManAdd( p->vHash, iEntry ); if ( iRes == iEntry ) { iLit = toLit( p->nSatVars++ ); Saig_ManBmcAddClauses( p, Lits[4], Lits, iLit ); assert( iEntry == Vec_IntSize(p->vId2Lit) ); Vec_IntPush( p->vId2Lit, iLit ); p->nHashMiss++; } else { iLit = Vec_IntEntry( p->vId2Lit, iRes ); Vec_IntShrink( p->vData, Vec_IntSize(p->vData) - 5 ); p->nHashHit++; } iLit = Abc_LitNotCond( iLit, fCompl ); } return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit ); } /**Function************************************************************* Synopsis [Derives CNF for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBmcCreateCnf_iter( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame, Vec_Int_t * vVisit ) { if ( Saig_ManBmcLiteral( p, pObj, iFrame ) != ~0 ) return; if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(p->pAig, pObj); if ( Aig_ObjIsCi(pObj) ) { if ( Saig_ObjIsLo(p->pAig, pObj) ) Vec_IntPush( vVisit, Saig_ObjLoToLi(p->pAig, pObj)->Id ); return; } if ( Aig_ObjIsCo(pObj) ) { Saig_ManBmcCreateCnf_iter( p, Aig_ObjFanin0(pObj), iFrame, vVisit ); return; } else { int * pMapping, i; assert( Aig_ObjIsNode(pObj) ); pMapping = Saig_ManBmcMapping( p, pObj ); for ( i = 0; i < 4; i++ ) if ( pMapping[i+1] != -1 ) Saig_ManBmcCreateCnf_iter( p, Aig_ManObj(p->pAig, pMapping[i+1]), iFrame, vVisit ); } } /**Function************************************************************* Synopsis [Recursively performs terminary simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcRunTerSim_rec( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame ) { unsigned * pInfo = (unsigned *)Vec_PtrEntry( p->vTerInfo, iFrame ); int Val0, Val1, Value = Saig_ManBmcSimInfoGet( pInfo, pObj ); if ( Value != SAIG_TER_NON ) { /* // check the value of this literal in the SAT solver if ( Value == SAIG_TER_UND && Saig_ManBmcMapping(p, pObj) ) { int Lit = Saig_ManBmcLiteral( p, pObj, iFrame ); if ( Lit >= 0 ) { assert( Lit >= 2 ); if ( p->pSat->assigns[Abc_Lit2Var(Lit)] < 2 ) { p->nUniProps++; if ( Abc_LitIsCompl(Lit) ^ (p->pSat->assigns[Abc_Lit2Var(Lit)] == 0) ) Value = SAIG_TER_ONE; else Value = SAIG_TER_ZER; // Value = SAIG_TER_UND; // disable! // use the new value Saig_ManBmcSimInfoSet( pInfo, pObj, Value ); // transfer to the unrolling if ( Value != SAIG_TER_UND ) Saig_ManBmcSetLiteral( p, pObj, iFrame, (int)(Value == SAIG_TER_ONE) ); } } } */ return Value; } if ( Aig_ObjIsCo(pObj) ) { Value = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin0(pObj), iFrame ); if ( Aig_ObjFaninC0(pObj) ) Value = Saig_ManBmcSimInfoNot( Value ); } else if ( Saig_ObjIsLo(p->pAig, pObj) ) { assert( iFrame > 0 ); Value = Saig_ManBmcRunTerSim_rec( p, Saig_ObjLoToLi(p->pAig, pObj), iFrame - 1 ); } else if ( Aig_ObjIsNode(pObj) ) { Val0 = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin0(pObj), iFrame ); Val1 = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin1(pObj), iFrame ); if ( Aig_ObjFaninC0(pObj) ) Val0 = Saig_ManBmcSimInfoNot( Val0 ); if ( Aig_ObjFaninC1(pObj) ) Val1 = Saig_ManBmcSimInfoNot( Val1 ); Value = Saig_ManBmcSimInfoAnd( Val0, Val1 ); } else assert( 0 ); Saig_ManBmcSimInfoSet( pInfo, pObj, Value ); // transfer to the unrolling if ( Saig_ManBmcMapping(p, pObj) && Value != SAIG_TER_UND ) Saig_ManBmcSetLiteral( p, pObj, iFrame, (int)(Value == SAIG_TER_ONE) ); return Value; } /**Function************************************************************* Synopsis [Derives CNF for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcCreateCnf( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame ) { Vec_Int_t * vVisit, * vVisit2; Aig_Obj_t * pTemp; int Lit, f, i; // perform ternary simulation int Value = Saig_ManBmcRunTerSim_rec( p, pObj, iFrame ); if ( Value != SAIG_TER_UND ) return (int)(Value == SAIG_TER_ONE); // construct CNF if value is ternary // Lit = Saig_ManBmcCreateCnf_rec( p, pObj, iFrame ); Vec_WecClear( p->vVisited ); vVisit = Vec_WecPushLevel( p->vVisited ); Vec_IntPush( vVisit, Aig_ObjId(pObj) ); for ( f = iFrame; f >= 0; f-- ) { Aig_ManIncrementTravId( p->pAig ); vVisit2 = Vec_WecPushLevel( p->vVisited ); vVisit = Vec_WecEntry( p->vVisited, Vec_WecSize(p->vVisited)-2 ); Aig_ManForEachObjVec( vVisit, p->pAig, pTemp, i ) Saig_ManBmcCreateCnf_iter( p, pTemp, f, vVisit2 ); if ( Vec_IntSize(vVisit2) == 0 ) break; } Vec_WecForEachLevelReverse( p->vVisited, vVisit, f ) Aig_ManForEachObjVec( vVisit, p->pAig, pTemp, i ) Saig_ManBmcCreateCnf_rec( p, pTemp, iFrame-f ); Lit = Saig_ManBmcLiteral( p, pObj, iFrame ); // extend the SAT solver if ( p->nSatVars > sat_solver_nvars(p->pSat) ) sat_solver_setnvars( p->pSat, p->nSatVars ); return Lit; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeCompareRefsIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) { int Diff = Aig_ObjRefs(*pp1) - Aig_ObjRefs(*pp2); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; Diff = Aig_ObjId(*pp1) - Aig_ObjId(*pp2); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ParBmcSetDefaultParams( Saig_ParBmc_t * p ) { memset( p, 0, sizeof(Saig_ParBmc_t) ); p->nStart = 0; // maximum number of timeframes p->nFramesMax = 0; // maximum number of timeframes p->nConfLimit = 0; // maximum number of conflicts at a node p->nConfLimitJump = 0; // maximum number of conflicts after jumping p->nFramesJump = 0; // the number of tiemframes to jump p->nTimeOut = 0; // approximate timeout in seconds p->nTimeOutGap = 0; // time since the last CEX found p->nPisAbstract = 0; // the number of PIs to abstract p->fSolveAll = 0; // stops on the first SAT instance p->fDropSatOuts = 0; // replace sat outputs by constant 0 p->nLearnedStart = 10000; // starting learned clause limit p->nLearnedDelta = 2000; // delta of learned clause limit p->nLearnedPerce = 80; // ratio of learned clause limit p->fVerbose = 0; // verbose p->fNotVerbose = 0; // skip line-by-line print-out p->iFrame = -1; // explored up to this frame p->nFailOuts = 0; // the number of failed outputs p->nDropOuts = 0; // the number of timed out outputs p->timeLastSolved = 0; // time when the last one was solved } /**Function************************************************************* Synopsis [Returns time to stop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ abctime Saig_ManBmcTimeToStop( Saig_ParBmc_t * pPars, abctime nTimeToStopNG ) { abctime nTimeToStopGap = pPars->nTimeOutGap ? pPars->nTimeOutGap * CLOCKS_PER_SEC + Abc_Clock(): 0; abctime nTimeToStop = 0; if ( nTimeToStopNG && nTimeToStopGap ) nTimeToStop = nTimeToStopNG < nTimeToStopGap ? nTimeToStopNG : nTimeToStopGap; else if ( nTimeToStopNG ) nTimeToStop = nTimeToStopNG; else if ( nTimeToStopGap ) nTimeToStop = nTimeToStopGap; return nTimeToStop; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_ManGenerateCex( Gia_ManBmc_t * p, int f, int i ) { Aig_Obj_t * pObjPi; Abc_Cex_t * pCex = Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), f*Saig_ManPoNum(p->pAig)+i ); int j, k, iBit = Saig_ManRegNum(p->pAig); for ( j = 0; j <= f; j++, iBit += Saig_ManPiNum(p->pAig) ) Saig_ManForEachPi( p->pAig, pObjPi, k ) { int iLit = Saig_ManBmcLiteral( p, pObjPi, j ); if ( iLit != ~0 && sat_solver_var_value(p->pSat, lit_var(iLit)) ) Abc_InfoSetBit( pCex->pData, iBit + k ); } return pCex; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManCallSolver( Gia_ManBmc_t * p, int Lit ) { if ( Lit == 0 ) return l_False; if ( Lit == 1 ) return l_True; return sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)p->pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); } /**Function************************************************************* Synopsis [Bounded model checking engine.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars ) { Gia_ManBmc_t * p; Aig_Obj_t * pObj; Abc_Cex_t * pCexNew, * pCexNew0; FILE * pLogFile = NULL; unsigned * pInfo; int RetValue = -1, fFirst = 1, nJumpFrame = 0, fUnfinished = 0; int nOutDigits = Abc_Base10Log( Saig_ManPoNum(pAig) ); int i, f, k, Lit, status; abctime clk, clk2, clkSatRun, clkOther = 0, clkTotal = Abc_Clock(); abctime nTimeUnsat = 0, nTimeSat = 0, nTimeUndec = 0, clkOne = 0; abctime nTimeToStopNG, nTimeToStop; if ( pPars->pLogFileName ) pLogFile = fopen( pPars->pLogFileName, "wb" ); if ( pPars->nTimeOutOne && pPars->nTimeOut == 0 ) pPars->nTimeOut = pPars->nTimeOutOne * Saig_ManPoNum(pAig) / 1000 + 1; if ( pPars->nTimeOutOne && !pPars->fSolveAll ) pPars->nTimeOutOne = 0; nTimeToStopNG = pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0; nTimeToStop = Saig_ManBmcTimeToStop( pPars, nTimeToStopNG ); // create BMC manager p = Saig_Bmc3ManStart( pAig, pPars->nTimeOutOne ); p->pPars = pPars; p->pSat->nLearntStart = p->pPars->nLearnedStart; p->pSat->nLearntDelta = p->pPars->nLearnedDelta; p->pSat->nLearntRatio = p->pPars->nLearnedPerce; p->pSat->nLearntMax = p->pSat->nLearntStart; p->pSat->fNoRestarts = p->pPars->fNoRestarts; if ( pPars->fSolveAll && p->vCexes == NULL ) p->vCexes = Vec_PtrStart( Saig_ManPoNum(pAig) ); if ( pPars->fVerbose ) { Abc_Print( 1, "Running \"bmc3\". PI/PO/Reg = %d/%d/%d. And =%7d. Lev =%6d. ObjNums =%6d.\n",// Sect =%3d.\n", Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig), Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig), p->nObjNums );//, Vec_VecSize(p->vSects) ); Abc_Print( 1, "Params: FramesMax = %d. Start = %d. ConfLimit = %d. TimeOut = %d. SolveAll = %d.\n", pPars->nFramesMax, pPars->nStart, pPars->nConfLimit, pPars->nTimeOut, pPars->fSolveAll ); } pPars->nFramesMax = pPars->nFramesMax ? pPars->nFramesMax : ABC_INFINITY; // set runtime limit if ( nTimeToStop ) sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); // perform frames Aig_ManRandom( 1 ); pPars->timeLastSolved = Abc_Clock(); for ( f = 0; f < pPars->nFramesMax; f++ ) { // stop BMC after exploring all reachable states if ( !pPars->nFramesJump && Aig_ManRegNum(pAig) < 30 && f == (1 << Aig_ManRegNum(pAig)) ) { Abc_Print( 1, "Stopping BMC because all 2^%d reachable states are visited.\n", Aig_ManRegNum(pAig) ); if ( p->pPars->fUseBridge ) Saig_ManForEachPo( pAig, pObj, i ) if ( !(p->vCexes && Vec_PtrEntry(p->vCexes, i)) && !(p->pTime4Outs && p->pTime4Outs[i] == 0) ) // not SAT and not timed out Gia_ManToBridgeResult( stdout, 1, NULL, i ); RetValue = pPars->nFailOuts ? 0 : 1; goto finish; } // stop BMC if all targets are solved if ( pPars->fSolveAll && pPars->nFailOuts + pPars->nDropOuts >= Saig_ManPoNum(pAig) ) { Abc_Print( 1, "Stopping BMC because all targets are disproved or timed out.\n" ); RetValue = pPars->nFailOuts ? 0 : 1; goto finish; } // consider the next timeframe if ( (RetValue == -1 || pPars->fSolveAll) && pPars->nStart == 0 && !nJumpFrame ) pPars->iFrame = f-1; // map nodes of this section Vec_PtrPush( p->vId2Var, Vec_IntStartFull(p->nObjNums) ); Vec_PtrPush( p->vTerInfo, (pInfo = ABC_CALLOC(unsigned, p->nWordNum)) ); /* // cannot remove mapping of frame values for any timeframes // because with constant propagation they may be needed arbitrarily far if ( f > 2*Vec_VecSize(p->vSects) ) { int iFrameOld = f - 2*Vec_VecSize( p->vSects ); void * pMemory = Vec_IntReleaseArray( Vec_PtrEntry(p->vId2Var, iFrameOld) ); ABC_FREE( pMemory ); } */ // prepare some nodes Saig_ManBmcSetLiteral( p, Aig_ManConst1(pAig), f, 1 ); Saig_ManBmcSimInfoSet( pInfo, Aig_ManConst1(pAig), SAIG_TER_ONE ); Saig_ManForEachPi( pAig, pObj, i ) Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_UND ); if ( f == 0 ) { Saig_ManForEachLo( p->pAig, pObj, i ) { Saig_ManBmcSetLiteral( p, pObj, 0, 0 ); Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_ZER ); } } if ( (pPars->nStart && f < pPars->nStart) || (nJumpFrame && f < nJumpFrame) ) continue; // create CNF upfront if ( pPars->fSolveAll ) { Saig_ManForEachPo( pAig, pObj, i ) { if ( i >= Saig_ManPoNum(pAig) ) break; // check for timeout if ( pPars->nTimeOutGap && pPars->timeLastSolved && Abc_Clock() > pPars->timeLastSolved + pPars->nTimeOutGap * CLOCKS_PER_SEC ) { Abc_Print( 1, "Reached gap timeout (%d seconds).\n", pPars->nTimeOutGap ); goto finish; } if ( nTimeToStop && Abc_Clock() > nTimeToStop ) { if ( !pPars->fSilent ) Abc_Print( 1, "Reached timeout (%d seconds).\n", pPars->nTimeOut ); goto finish; } // skip solved outputs if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) ) continue; // skip output whose time has run out if ( p->pTime4Outs && p->pTime4Outs[i] == 0 ) continue; // add constraints for this output clk2 = Abc_Clock(); Saig_ManBmcCreateCnf( p, pObj, f ); clkOther += Abc_Clock() - clk2; } } // solve SAT clk = Abc_Clock(); Saig_ManForEachPo( pAig, pObj, i ) { if ( i >= Saig_ManPoNum(pAig) ) break; // check for timeout if ( pPars->nTimeOutGap && pPars->timeLastSolved && Abc_Clock() > pPars->timeLastSolved + pPars->nTimeOutGap * CLOCKS_PER_SEC ) { Abc_Print( 1, "Reached gap timeout (%d seconds).\n", pPars->nTimeOutGap ); goto finish; } if ( nTimeToStop && Abc_Clock() > nTimeToStop ) { if ( !pPars->fSilent ) Abc_Print( 1, "Reached timeout (%d seconds).\n", pPars->nTimeOut ); goto finish; } // skip solved outputs if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) ) continue; // skip output whose time has run out if ( p->pTime4Outs && p->pTime4Outs[i] == 0 ) continue; // add constraints for this output clk2 = Abc_Clock(); Lit = Saig_ManBmcCreateCnf( p, pObj, f ); clkOther += Abc_Clock() - clk2; // solve this output fUnfinished = 0; sat_solver_compress( p->pSat ); if ( p->pTime4Outs ) { assert( p->pTime4Outs[i] > 0 ); clkOne = Abc_Clock(); sat_solver_set_runtime_limit( p->pSat, p->pTime4Outs[i] + Abc_Clock() ); } clk2 = Abc_Clock(); status = Saig_ManCallSolver( p, Lit ); clkSatRun = Abc_Clock() - clk2; if ( pLogFile ) fprintf( pLogFile, "Frame %5d Output %5d Time(ms) %8d %8d\n", f, i, Lit < 2 ? 0 : (int)(clkSatRun * 1000 / CLOCKS_PER_SEC), Lit < 2 ? 0 : Abc_MaxInt(0, Abc_MinInt(pPars->nTimeOutOne, pPars->nTimeOutOne - (int)((p->pTime4Outs[i] - clkSatRun) * 1000 / CLOCKS_PER_SEC))) ); if ( p->pTime4Outs ) { abctime timeSince = Abc_Clock() - clkOne; assert( p->pTime4Outs[i] > 0 ); p->pTime4Outs[i] = (p->pTime4Outs[i] > timeSince) ? p->pTime4Outs[i] - timeSince : 0; if ( p->pTime4Outs[i] == 0 && status != l_True ) pPars->nDropOuts++; } if ( status == l_False ) { nTimeUnsat += clkSatRun; if ( Lit != 0 ) { // add final unit clause Lit = lit_neg( Lit ); status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); assert( status ); // add learned units for ( k = 0; k < veci_size(&p->pSat->unit_lits); k++ ) { Lit = veci_begin(&p->pSat->unit_lits)[k]; status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); assert( status ); } veci_resize(&p->pSat->unit_lits, 0); // propagate units sat_solver_compress( p->pSat ); } if ( p->pPars->fUseBridge ) Gia_ManReportProgress( stdout, i, f ); } else if ( status == l_True ) { nTimeSat += clkSatRun; RetValue = 0; fFirst = 0; if ( !pPars->fSolveAll ) { if ( pPars->fVerbose ) { Abc_Print( 1, "%4d %s : ", f, fUnfinished ? "-" : "+" ); Abc_Print( 1, "Var =%8.0f. ", (double)p->nSatVars ); Abc_Print( 1, "Cla =%9.0f. ", (double)p->pSat->stats.clauses ); Abc_Print( 1, "Conf =%7.0f. ", (double)p->pSat->stats.conflicts ); // Abc_Print( 1, "Imp =%10.0f. ", (double)p->pSat->stats.propagations ); Abc_Print( 1, "Uni =%7.0f. ",(double)sat_solver_count_assigned(p->pSat) ); // ABC_PRT( "Time", Abc_Clock() - clk ); Abc_Print( 1, "%4.0f MB", 4.25*(f+1)*p->nObjNums /(1<<20) ); Abc_Print( 1, "%4.0f MB", 1.0*sat_solver_memory(p->pSat)/(1<<20) ); Abc_Print( 1, "%9.2f sec ", (float)(Abc_Clock() - clkTotal)/(float)(CLOCKS_PER_SEC) ); // Abc_Print( 1, "\n" ); // ABC_PRMn( "Id2Var", (f+1)*p->nObjNums*4 ); // ABC_PRMn( "SAT", 42 * p->pSat->size + 16 * (int)p->pSat->stats.clauses + 4 * (int)p->pSat->stats.clauses_literals ); // Abc_Print( 1, "S =%6d. ", p->nBufNum ); // Abc_Print( 1, "D =%6d. ", p->nDupNum ); Abc_Print( 1, "\n" ); fflush( stdout ); } ABC_FREE( pAig->pSeqModel ); pAig->pSeqModel = Saig_ManGenerateCex( p, f, i ); goto finish; } pPars->nFailOuts++; if ( !pPars->fNotVerbose ) Abc_Print( 1, "Output %*d was asserted in frame %2d (solved %*d out of %*d outputs).\n", nOutDigits, i, f, nOutDigits, pPars->nFailOuts, nOutDigits, Saig_ManPoNum(pAig) ); if ( p->vCexes == NULL ) p->vCexes = Vec_PtrStart( Saig_ManPoNum(pAig) ); pCexNew = (p->pPars->fUseBridge || pPars->fStoreCex) ? Saig_ManGenerateCex( p, f, i ) : (Abc_Cex_t *)(ABC_PTRINT_T)1; pCexNew0 = NULL; if ( p->pPars->fUseBridge ) { Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo ); //Abc_CexFree( pCexNew ); pCexNew0 = pCexNew; pCexNew = (Abc_Cex_t *)(ABC_PTRINT_T)1; } Vec_PtrWriteEntry( p->vCexes, i, Abc_CexDup(pCexNew, Saig_ManRegNum(pAig)) ); if ( pPars->pFuncOnFail && pPars->pFuncOnFail(i, pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, i) : NULL) ) { Abc_CexFreeP( &pCexNew0 ); Abc_Print( 1, "Quitting due to callback on fail.\n" ); goto finish; } // reset the timeout pPars->timeLastSolved = Abc_Clock(); nTimeToStop = Saig_ManBmcTimeToStop( pPars, nTimeToStopNG ); if ( nTimeToStop ) sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); // check if other outputs failed under the same counter-example Saig_ManForEachPo( pAig, pObj, k ) { if ( k >= Saig_ManPoNum(pAig) ) break; // skip solved outputs if ( p->vCexes && Vec_PtrEntry(p->vCexes, k) ) continue; // check if this output is solved Lit = Saig_ManBmcCreateCnf( p, pObj, f ); if ( sat_solver_var_value(p->pSat, lit_var(Lit)) == Abc_LitIsCompl(Lit) ) continue; // write entry pPars->nFailOuts++; if ( !pPars->fNotVerbose ) Abc_Print( 1, "Output %*d was asserted in frame %2d (solved %*d out of %*d outputs).\n", nOutDigits, k, f, nOutDigits, pPars->nFailOuts, nOutDigits, Saig_ManPoNum(pAig) ); // report to the bridge if ( p->pPars->fUseBridge ) { // set the output number pCexNew0->iPo = k; Gia_ManToBridgeResult( stdout, 0, pCexNew0, pCexNew0->iPo ); } // remember solved output Vec_PtrWriteEntry( p->vCexes, k, Abc_CexDup(pCexNew, Saig_ManRegNum(pAig)) ); } Abc_CexFreeP( &pCexNew0 ); Abc_CexFree( pCexNew ); } else { nTimeUndec += clkSatRun; assert( status == l_Undef ); if ( pPars->nFramesJump ) { pPars->nConfLimit = pPars->nConfLimitJump; nJumpFrame = f + pPars->nFramesJump; fUnfinished = 1; break; } if ( p->pTime4Outs == NULL ) goto finish; } } if ( pPars->fVerbose ) { if ( fFirst == 1 && f > 0 && p->pSat->stats.conflicts > 1 ) { fFirst = 0; // Abc_Print( 1, "Outputs of frames up to %d are trivially UNSAT.\n", f ); } Abc_Print( 1, "%4d %s : ", f, fUnfinished ? "-" : "+" ); Abc_Print( 1, "Var =%8.0f. ", (double)p->nSatVars ); // Abc_Print( 1, "Used =%8.0f. ", (double)sat_solver_count_usedvars(p->pSat) ); Abc_Print( 1, "Cla =%9.0f. ", (double)p->pSat->stats.clauses ); Abc_Print( 1, "Conf =%7.0f. ",(double)p->pSat->stats.conflicts ); // Abc_Print( 1, "Imp =%10.0f. ", (double)p->pSat->stats.propagations ); Abc_Print( 1, "Uni =%7.0f. ",(double)sat_solver_count_assigned(p->pSat) ); if ( pPars->fSolveAll ) Abc_Print( 1, "CEX =%5d. ", pPars->nFailOuts ); if ( pPars->nTimeOutOne ) Abc_Print( 1, "T/O =%4d. ", pPars->nDropOuts ); // ABC_PRT( "Time", Abc_Clock() - clk ); // Abc_Print( 1, "%4.0f MB", 4.0*Vec_IntSize(p->vVisited) /(1<<20) ); Abc_Print( 1, "%4.0f MB", 4.0*(f+1)*p->nObjNums /(1<<20) ); Abc_Print( 1, "%4.0f MB", 1.0*sat_solver_memory(p->pSat)/(1<<20) ); // Abc_Print( 1, " %6d %6d ", p->nLitUsed, p->nLitUseless ); Abc_Print( 1, "%9.2f sec ", 1.0*(Abc_Clock() - clkTotal)/CLOCKS_PER_SEC ); // Abc_Print( 1, "\n" ); // ABC_PRMn( "Id2Var", (f+1)*p->nObjNums*4 ); // ABC_PRMn( "SAT", 42 * p->pSat->size + 16 * (int)p->pSat->stats.clauses + 4 * (int)p->pSat->stats.clauses_literals ); // Abc_Print( 1, "Simples = %6d. ", p->nBufNum ); // Abc_Print( 1, "Dups = %6d. ", p->nDupNum ); Abc_Print( 1, "\n" ); fflush( stdout ); } } // consider the next timeframe if ( nJumpFrame && pPars->nStart == 0 ) pPars->iFrame = nJumpFrame - pPars->nFramesJump; else if ( RetValue == -1 && pPars->nStart == 0 ) pPars->iFrame = f-1; //ABC_PRT( "CNF generation runtime", clkOther ); finish: if ( pPars->fVerbose ) { Abc_Print( 1, "Runtime: " ); Abc_Print( 1, "CNF = %.1f sec (%.1f %%) ", 1.0*clkOther/CLOCKS_PER_SEC, 100.0*clkOther/(Abc_Clock() - clkTotal) ); Abc_Print( 1, "UNSAT = %.1f sec (%.1f %%) ", 1.0*nTimeUnsat/CLOCKS_PER_SEC, 100.0*nTimeUnsat/(Abc_Clock() - clkTotal) ); Abc_Print( 1, "SAT = %.1f sec (%.1f %%) ", 1.0*nTimeSat/CLOCKS_PER_SEC, 100.0*nTimeSat/(Abc_Clock() - clkTotal) ); Abc_Print( 1, "UNDEC = %.1f sec (%.1f %%)", 1.0*nTimeUndec/CLOCKS_PER_SEC, 100.0*nTimeUndec/(Abc_Clock() - clkTotal) ); Abc_Print( 1, "\n" ); } Saig_Bmc3ManStop( p ); fflush( stdout ); if ( pLogFile ) fclose( pLogFile ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcBmcAnd.c000066400000000000000000001171401300674244400233420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcBmcAnd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Memory-efficient BMC engine] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcBmcAnd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "aig/gia/giaAig.h" #include "sat/bsat/satStore.h" #include "sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Bmc_Mna_t_ Bmc_Mna_t; struct Bmc_Mna_t_ { Gia_Man_t * pFrames; // time frames Cnf_Dat_t * pCnf; // CNF derived for the timeframes Vec_Int_t * vPiMap; // maps unrolled GIA PIs into user GIA PIs Vec_Int_t * vId2Var; // maps GIA IDs into SAT vars Vec_Int_t * vInputs; // inputs of the cone Vec_Int_t * vOutputs; // outputs of the cone Vec_Int_t * vNodes; // internal nodes of the cone sat_solver * pSat; // SAT solver int nSatVars; // the counter of SAT variables abctime clkStart; // starting time }; 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)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs ternary simulation of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Bmc_MnaTernary( Gia_Man_t * p, int nFrames, int nFramesAdd, int fVerbose, int * iFirst ) { Vec_Ptr_t * vStates; unsigned * pState; int nStateWords = Abc_BitWordNum( 2*Gia_ManCoNum(p) ); Gia_Obj_t * pObj, * pObjRo; int f, i, Count[4]; abctime clk = Abc_Clock(); Gia_ManConst0(p)->Value = GIA_ZER; Gia_ManForEachPi( p, pObj, i ) pObj->Value = GIA_UND; Gia_ManForEachRi( p, pObj, i ) pObj->Value = GIA_ZER; *iFirst = -1; vStates = Vec_PtrAlloc( 100 ); for ( f = 0; ; f++ ) { // if frames are given, break at frames if ( nFrames && f == nFrames ) break; // if frames are not given, break after nFramesAdd from the first x-valued if ( !nFrames && *iFirst >= 0 && f == *iFirst + nFramesAdd ) break; // aassign CI values Gia_ManForEachRiRo( p, pObj, pObjRo, i ) pObjRo->Value = pObj->Value; Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_XsimAndCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj), Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); // compute and save CO values pState = ABC_ALLOC( unsigned, nStateWords ); Gia_ManForEachCo( p, pObj, i ) { pObj->Value = Gia_XsimNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); Gia_ManTerSimInfoSet( pState, i, pObj->Value ); if ( *iFirst == -1 && i < Gia_ManPoNum(p) && pObj->Value == GIA_UND ) *iFirst = f; } Vec_PtrPush( vStates, pState ); // print statistics if ( !fVerbose ) continue; Count[0] = Count[1] = Count[2] = Count[3] = 0; Gia_ManForEachRi( p, pObj, i ) Count[pObj->Value]++; printf( "%5d : 0 =%7d 1 =%7d x =%7d all =%7d out = %s\n", f, Count[GIA_ZER], Count[GIA_ONE], Count[GIA_UND], Gia_ManRegNum(p), Gia_ManPo(p, 0)->Value == GIA_UND ? "x" : "0" ); } // assert( Vec_PtrSize(vStates) == nFrames ); if ( fVerbose ) printf( "Finished %d frames. First x-valued PO is in frame %d. ", nFrames, *iFirst ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return vStates; } /**Function************************************************************* Synopsis [Collect AIG nodes for the group of POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_MnaCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes, unsigned * pState ) { if ( pObj->fPhase ) return; pObj->fPhase = 1; if ( Gia_ObjIsAnd(pObj) ) { Bmc_MnaCollect_rec( p, Gia_ObjFanin0(pObj), vNodes, pState ); Bmc_MnaCollect_rec( p, Gia_ObjFanin1(pObj), vNodes, pState ); pObj->Value = Gia_XsimAndCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj), Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); } else if ( Gia_ObjIsRo(p, pObj) ) pObj->Value = pState ? Gia_ManTerSimInfoGet( pState, Gia_ObjCioId(Gia_ObjRoToRi(p, pObj)) ) : GIA_ZER; else if ( Gia_ObjIsPi(p, pObj) ) pObj->Value = GIA_UND; else assert( 0 ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } void Bmc_MnaCollect( Gia_Man_t * p, Vec_Int_t * vCos, Vec_Int_t * vNodes, unsigned * pState ) { Gia_Obj_t * pObj; int i; Vec_IntClear( vNodes ); Gia_ManConst0(p)->fPhase = 1; Gia_ManConst0(p)->Value = GIA_ZER; Gia_ManForEachObjVec( vCos, p, pObj, i ) { assert( Gia_ObjIsCo(pObj) ); Bmc_MnaCollect_rec( p, Gia_ObjFanin0(pObj), vNodes, pState ); pObj->Value = Gia_XsimNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); assert( pObj->Value == GIA_UND ); } } /**Function************************************************************* Synopsis [Select related logic cones for the COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_MnaSelect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves ) { if ( !pObj->fPhase ) return; pObj->fPhase = 0; assert( pObj->Value == GIA_UND ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjFanin0(pObj)->Value == GIA_UND ) Bmc_MnaSelect_rec( p, Gia_ObjFanin0(pObj), vLeaves ); else assert( Gia_ObjFanin0(pObj)->Value + Gia_ObjFaninC0(pObj) == GIA_ONE ); if ( Gia_ObjFanin1(pObj)->Value == GIA_UND ) Bmc_MnaSelect_rec( p, Gia_ObjFanin1(pObj), vLeaves ); else assert( Gia_ObjFanin1(pObj)->Value + Gia_ObjFaninC1(pObj) == GIA_ONE ); } else if ( Gia_ObjIsRo(p, pObj) ) Vec_IntPush( vLeaves, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); } void Bmc_MnaSelect( Gia_Man_t * p, Vec_Int_t * vCos, Vec_Int_t * vNodes, Vec_Int_t * vLeaves ) { Gia_Obj_t * pObj; int i; Vec_IntClear( vLeaves ); Gia_ManForEachObjVec( vCos, p, pObj, i ) Bmc_MnaSelect_rec( p, Gia_ObjFanin0(pObj), vLeaves ); Gia_ManConst0(p)->fPhase = 0; Gia_ManForEachObjVec( vNodes, p, pObj, i ) pObj->fPhase = 0; } /**Function************************************************************* Synopsis [Build AIG for the selected cones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_MnaBuild_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Man_t * pNew, Vec_Int_t * vMap, Vec_Int_t * vPiMap ) { if ( !pObj->fPhase ) return; pObj->fPhase = 0; assert( pObj->Value == GIA_UND ); if ( Gia_ObjIsAnd(pObj) ) { int iLit0 = 1, iLit1 = 1; if ( Gia_ObjFanin0(pObj)->Value == GIA_UND ) Bmc_MnaBuild_rec( p, Gia_ObjFanin0(pObj), pNew, vMap, vPiMap ); if ( Gia_ObjFanin1(pObj)->Value == GIA_UND ) Bmc_MnaBuild_rec( p, Gia_ObjFanin1(pObj), pNew, vMap, vPiMap ); if ( Gia_ObjFanin0(pObj)->Value == GIA_UND ) iLit0 = Abc_LitNotCond( Vec_IntEntry(vMap, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj) ); if ( Gia_ObjFanin1(pObj)->Value == GIA_UND ) iLit1 = Abc_LitNotCond( Vec_IntEntry(vMap, Gia_ObjFaninId1p(p, pObj)), Gia_ObjFaninC1(pObj) ); Vec_IntWriteEntry( vMap, Gia_ObjId(p, pObj), Gia_ManHashAnd(pNew, iLit0, iLit1) ); } else if ( Gia_ObjIsRo(p, pObj) ) assert( Vec_IntEntry(vMap, Gia_ObjId(p, pObj)) != -1 ); else if ( Gia_ObjIsPi(p, pObj) ) { Vec_IntPush( vPiMap, Gia_ObjCioId(pObj) ); Vec_IntWriteEntry( vMap, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); } else assert( 0 ); } void Bmc_MnaBuild( Gia_Man_t * p, Vec_Int_t * vCos, Vec_Int_t * vNodes, Gia_Man_t * pNew, Vec_Int_t * vMap, Vec_Int_t * vPiMap ) { Gia_Obj_t * pObj; int i, iLit; Gia_ManForEachObjVec( vCos, p, pObj, i ) { assert( Gia_ObjIsCo(pObj) ); Bmc_MnaBuild_rec( p, Gia_ObjFanin0(pObj), pNew, vMap, vPiMap ); iLit = Abc_LitNotCond( Vec_IntEntry(vMap, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj) ); Vec_IntWriteEntry( vMap, Gia_ObjId(p, pObj), iLit ); } Gia_ManConst0(p)->fPhase = 0; Gia_ManForEachObjVec( vNodes, p, pObj, i ) pObj->fPhase = 0; } /**Function************************************************************* Synopsis [Compute the first non-trivial timeframe.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManBmcUnroll( Gia_Man_t * pGia, int nFramesMax, int nFramesAdd, int fVerbose, Vec_Int_t ** pvPiMap ) { Gia_Obj_t * pObj; Gia_Man_t * pNew, * pTemp; Vec_Ptr_t * vStates, * vBegins; Vec_Int_t * vRoots, * vCone, * vLeaves, * vMap; unsigned * pStateF, * pStateP; int f, i, iFirst; Gia_ManCleanPhase( pGia ); vCone = Vec_IntAlloc( 1000 ); vLeaves = Vec_IntAlloc( 1000 ); // perform ternary simulation vStates = Bmc_MnaTernary( pGia, nFramesMax, nFramesAdd, fVerbose, &iFirst ); // go backward *pvPiMap = Vec_IntAlloc( 1000 ); vBegins = Vec_PtrStart( Vec_PtrSize(vStates) ); for ( f = Vec_PtrSize(vStates) - 1; f >= 0; f-- ) { // get ternary states pStateF = (unsigned *)Vec_PtrEntry(vStates, f); pStateP = f ? (unsigned *)Vec_PtrEntry(vStates, f-1) : 0; // collect roots of this frame vRoots = Vec_IntAlloc( 100 ); Gia_ManForEachPo( pGia, pObj, i ) if ( Gia_ManTerSimInfoGet( pStateF, Gia_ObjCioId(pObj) ) == GIA_UND ) Vec_IntPush( vRoots, Gia_ObjId(pGia, pObj) ); // add leaves from the previous frame Vec_IntAppend( vRoots, vLeaves ); Vec_PtrWriteEntry( vBegins, f, vRoots ); // find the cone Bmc_MnaCollect( pGia, vRoots, vCone, pStateP ); // computes vCone Bmc_MnaSelect( pGia, vRoots, vCone, vLeaves ); // computes vLeaves if ( fVerbose ) printf( "Frame %4d : Roots = %6d Leaves = %6d Cone = %6d\n", f, Vec_IntSize(vRoots), Vec_IntSize(vLeaves), Vec_IntSize(vCone) ); if ( Vec_IntSize(vLeaves) == 0 ) break; // it is possible that some of the POs are still ternary... } assert( f >= 0 ); // go forward vMap = Vec_IntStartFull( Gia_ManObjNum(pGia) ); pNew = Gia_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( pGia->pName ); Gia_ManHashStart( pNew ); for ( f = 0; f < Vec_PtrSize(vStates); f++ ) { vRoots = (Vec_Int_t *)Vec_PtrEntry( vBegins, f ); if ( vRoots == NULL ) { Gia_ManForEachPo( pGia, pObj, i ) Gia_ManAppendCo( pNew, 0 ); continue; } // get ternary states pStateF = (unsigned *)Vec_PtrEntry(vStates, f); pStateP = f ? (unsigned *)Vec_PtrEntry(vStates, f-1) : 0; // clean POs Gia_ManForEachPo( pGia, pObj, i ) Vec_IntWriteEntry( vMap, Gia_ObjId(pGia, pObj), 0 ); // find the cone Vec_IntPush( *pvPiMap, -f-1 ); Bmc_MnaCollect( pGia, vRoots, vCone, pStateP ); // computes vCone Bmc_MnaBuild( pGia, vRoots, vCone, pNew, vMap, *pvPiMap ); // computes pNew if ( fVerbose ) printf( "Frame %4d : Roots = %6d Leaves = %6d Cone = %6d\n", f, Vec_IntSize(vRoots), Vec_IntSize(vLeaves), Vec_IntSize(vCone) ); // create POs Gia_ManForEachPo( pGia, pObj, i ) Gia_ManAppendCo( pNew, Vec_IntEntry(vMap, Gia_ObjId(pGia, pObj)) ); // set a new map Gia_ManForEachObjVec( vRoots, pGia, pObj, i ) if ( Gia_ObjIsRi(pGia, pObj) ) Vec_IntWriteEntry( vMap, Gia_ObjId(pGia, Gia_ObjRiToRo(pGia, pObj)), Vec_IntEntry(vMap, Gia_ObjId(pGia, pObj)) ); // else if ( Gia_ObjIsPo(pGia, pObj) ) // Gia_ManAppendCo( pNew, Vec_IntEntry(vMap, Gia_ObjId(pGia, pObj)) ); // else assert( 0 ); } Gia_ManHashStop( pNew ); Vec_VecFree( (Vec_Vec_t *)vBegins ); Vec_PtrFreeFree( vStates ); Vec_IntFree( vLeaves ); Vec_IntFree( vCone ); Vec_IntFree( vMap ); // cleanup // Gia_ManPrintStats( pNew, NULL ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); // Gia_ManPrintStats( pNew, NULL ); return pNew; } /**Function************************************************************* Synopsis [BMC manager manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bmc_Mna_t * Bmc_MnaAlloc() { Bmc_Mna_t * p; p = ABC_CALLOC( Bmc_Mna_t, 1 ); p->vId2Var = Vec_IntAlloc( 0 ); p->vInputs = Vec_IntAlloc( 1000 ); p->vOutputs = Vec_IntAlloc( 1000 ); p->vNodes = Vec_IntAlloc( 10000 ); p->pSat = sat_solver_new(); p->nSatVars = 1; p->clkStart = Abc_Clock(); sat_solver_setnvars( p->pSat, 1000 ); return p; } void Bmc_MnaFree( Bmc_Mna_t * p ) { Cnf_DataFree( p->pCnf ); Vec_IntFreeP( &p->vPiMap ); Vec_IntFreeP( &p->vId2Var ); Vec_IntFreeP( &p->vInputs ); Vec_IntFreeP( &p->vOutputs ); Vec_IntFreeP( &p->vNodes ); sat_solver_delete( p->pSat ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Derives GIA for the given cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManBmcDupCone( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vNodes, Vec_Int_t * vOuts ) { Gia_Man_t * pNew; Vec_Int_t * vTempIn, * vTempNode; Gia_Obj_t * pObj; int i; // save values vTempIn = Vec_IntAlloc( Vec_IntSize(vIns) ); Gia_ManForEachObjVec( vIns, p, pObj, i ) Vec_IntPush( vTempIn, pObj->Value ); // save values vTempNode = Vec_IntAlloc( Vec_IntSize(vNodes) ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) Vec_IntPush( vTempNode, pObj->Value ); // derive new GIA pNew = Gia_ManDupFromVecs( p, vIns, vNodes, vOuts, 0 ); // reset values Gia_ManForEachObjVec( vIns, p, pObj, i ) pObj->Value = Vec_IntEntry( vTempIn, i ); // reset values Gia_ManForEachObjVec( vNodes, p, pObj, i ) pObj->Value = Vec_IntEntry( vTempNode, i ); // reset values Gia_ManForEachObjVec( vOuts, p, pObj, i ) pObj->Value = 0; Vec_IntFree( vTempIn ); Vec_IntFree( vTempNode ); return pNew; } /**Function************************************************************* Synopsis [Derives GIA for the given cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBmcAssignVarIds( Bmc_Mna_t * p, Vec_Int_t * vIns, Vec_Int_t * vUsed, Vec_Int_t * vOuts ) { int i, iObj, VarC0 = p->nSatVars++; Vec_IntForEachEntry( vIns, iObj, i ) if ( Vec_IntEntry( p->vId2Var, iObj ) == 0 ) Vec_IntWriteEntry( p->vId2Var, iObj, p->nSatVars++ ); Vec_IntForEachEntryReverse( vUsed, iObj, i ) { assert( Vec_IntEntry( p->vId2Var, iObj ) == 0 ); Vec_IntWriteEntry( p->vId2Var, iObj, p->nSatVars++ ); } Vec_IntForEachEntry( vOuts, iObj, i ) { assert( Vec_IntEntry( p->vId2Var, iObj ) == 0 ); Vec_IntWriteEntry( p->vId2Var, iObj, p->nSatVars++ ); } // extend the SAT solver if ( p->nSatVars > sat_solver_nvars(p->pSat) ) sat_solver_setnvars( p->pSat, p->nSatVars ); return VarC0; } /**Function************************************************************* Synopsis [Derives CNF for the given cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManBmcAddCnf( Bmc_Mna_t * p, Gia_Man_t * pGia, Vec_Int_t * vIns, Vec_Int_t * vNodes, Vec_Int_t * vOuts ) { Gia_Man_t * pNew = Gia_ManBmcDupCone( pGia, vIns, vNodes, vOuts ); Aig_Man_t * pAig = Gia_ManToAigSimple( pNew ); Cnf_Dat_t * pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Vec_Int_t * vUsed, * vMap; Gia_Obj_t * pObj; int i, iObj, VarC0; // collect used variables vUsed = Vec_IntAlloc( pCnf->nVars - Vec_IntSize(vIns) - Vec_IntSize(vOuts) ); Gia_ManForEachAnd( pNew, pObj, i ) if ( pCnf->pVarNums[i] >= 0 ) Vec_IntPush( vUsed, Vec_IntEntry(vNodes, i - Vec_IntSize(vIns) - 1) ); // assign variable IDs VarC0 = Gia_ManBmcAssignVarIds( p, vIns, vUsed, vOuts ); Vec_IntFree( vUsed ); // create variable map from CNF vars into SAT vars vMap = Vec_IntStartFull( pCnf->nVars ); assert( pCnf->pVarNums[0] > 0 ); Vec_IntWriteEntry( vMap, pCnf->pVarNums[0], VarC0 ); Gia_ManForEachObj1( pNew, pObj, i ) { if ( pCnf->pVarNums[i] < 0 ) continue; assert( pCnf->pVarNums[i] >= 0 && pCnf->pVarNums[i] < pCnf->nVars ); if ( Gia_ObjIsCi(pObj) ) iObj = Vec_IntEntry( vIns, i - 1 ); else if ( Gia_ObjIsAnd(pObj) ) iObj = Vec_IntEntry( vNodes, i - Vec_IntSize(vIns) - 1 ); else if ( Gia_ObjIsCo(pObj) ) iObj = Vec_IntEntry( vOuts, i - Vec_IntSize(vIns) - Vec_IntSize(vNodes) - 1 ); else assert( 0 ); assert( Vec_IntEntry(p->vId2Var, iObj) > 0 ); Vec_IntWriteEntry( vMap, pCnf->pVarNums[i], Vec_IntEntry(p->vId2Var, iObj) ); } //Vec_IntPrint( vMap ); // remap CNF for ( i = 0; i < pCnf->nLiterals; i++ ) { assert( pCnf->pClauses[0][i] > 1 && pCnf->pClauses[0][i] < 2 * pCnf->nVars ); pCnf->pClauses[0][i] = Abc_Lit2LitV( Vec_IntArray(vMap), pCnf->pClauses[0][i] ); } Vec_IntFree( vMap ); // add clauses for ( i = 0; i < pCnf->nClauses; i++ ) { /* int v; for ( v = 0; v < pCnf->pClauses[i+1] - pCnf->pClauses[i]; v++ ) printf( "%d ", pCnf->pClauses[i][v] ); printf( "\n" ); */ if ( !sat_solver_addclause( p->pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) break; } if ( i < pCnf->nClauses ) printf( "SAT solver became UNSAT after adding clauses.\n" ); Aig_ManStop( pAig ); Cnf_DataFree( pCnf ); Gia_ManStop( pNew ); } /**Function************************************************************* Synopsis [Collects new nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManBmcAddCone_rec( Bmc_Mna_t * p, Gia_Obj_t * pObj ) { int iObj; if ( pObj->fMark0 ) return; pObj->fMark0 = 1; iObj = Gia_ObjId( p->pFrames, pObj ); if ( Gia_ObjIsAnd(pObj) && Vec_IntEntry(p->vId2Var, iObj) == 0 ) { Gia_ManBmcAddCone_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManBmcAddCone_rec( p, Gia_ObjFanin1(pObj) ); Vec_IntPush( p->vNodes, iObj ); } else Vec_IntPush( p->vInputs, iObj ); } void Gia_ManBmcAddCone( Bmc_Mna_t * p, int iStart, int iStop ) { Gia_Obj_t * pObj; int i; Vec_IntClear( p->vNodes ); Vec_IntClear( p->vInputs ); Vec_IntClear( p->vOutputs ); Vec_IntFillExtra( p->vId2Var, Gia_ManObjNum(p->pFrames), 0 ); for ( i = iStart; i < iStop; i++ ) { pObj = Gia_ManPo(p->pFrames, i); if ( Gia_ObjChild0(pObj) == Gia_ManConst0(p->pFrames) ) continue; Gia_ManBmcAddCone_rec( p, Gia_ObjFanin0(pObj) ); Vec_IntPush( p->vOutputs, Gia_ObjId(p->pFrames, pObj) ); } // clean attributes and create new variables Gia_ManForEachObjVec( p->vNodes, p->pFrames, pObj, i ) pObj->fMark0 = 0; Gia_ManForEachObjVec( p->vInputs, p->pFrames, pObj, i ) pObj->fMark0 = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBmcCheckOutputs( Gia_Man_t * pFrames, int iStart, int iStop ) { int i; for ( i = iStart; i < iStop; i++ ) if ( Gia_ObjChild0(Gia_ManPo(pFrames, i)) != Gia_ManConst0(pFrames) ) return 0; return 1; } int Gia_ManBmcFindFirst( Gia_Man_t * pFrames ) { Gia_Obj_t * pObj; int i; Gia_ManForEachPo( pFrames, pObj, i ) if ( Gia_ObjChild0(pObj) != Gia_ManConst0(pFrames) ) return i; return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBmcPerform_Unr( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) { Unr_Man_t * pUnroll; Bmc_Mna_t * p; int nFramesMax = pPars->nFramesMax ? pPars->nFramesMax : ABC_INFINITY; int f, i=0, Lit, status, RetValue = -2; p = Bmc_MnaAlloc(); pUnroll = Unr_ManUnrollStart( pGia, pPars->fVeryVerbose ); for ( f = 0; f < nFramesMax; f++ ) { p->pFrames = Unr_ManUnrollFrame( pUnroll, f ); if ( !Gia_ManBmcCheckOutputs( p->pFrames, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ) ) { // create another slice Gia_ManBmcAddCone( p, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ); // create CNF in the SAT solver Gia_ManBmcAddCnf( p, p->pFrames, p->vInputs, p->vNodes, p->vOutputs ); // try solving the outputs for ( i = f * Gia_ManPoNum(pGia); i < (f+1) * Gia_ManPoNum(pGia); i++ ) { Gia_Obj_t * pObj = Gia_ManPo(p->pFrames, i); if ( Gia_ObjChild0(pObj) == Gia_ManConst0(p->pFrames) ) continue; Lit = Abc_Var2Lit( Vec_IntEntry(p->vId2Var, Gia_ObjId(p->pFrames, pObj)), 0 ); status = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_False ) // unsat continue; if ( status == l_True ) // sat RetValue = 0; if ( status == l_Undef ) // undecided RetValue = -1; break; } } // report statistics if ( pPars->fVerbose ) { printf( "%4d : PI =%9d. AIG =%9d. Var =%8d. In =%6d. And =%9d. Cla =%9d. Conf =%9d. Mem =%7.1f MB ", f, Gia_ManPiNum(p->pFrames), Gia_ManAndNum(p->pFrames), p->nSatVars-1, Vec_IntSize(p->vInputs), Vec_IntSize(p->vNodes), sat_solver_nclauses(p->pSat), sat_solver_nconflicts(p->pSat), Gia_ManMemory(p->pFrames)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } if ( RetValue != -2 ) { if ( RetValue == -1 ) printf( "SAT solver reached conflict/runtime limit in frame %d.\n", f ); else { printf( "Output %d of miter \"%s\" was asserted in frame %d. ", i - f * Gia_ManPoNum(pGia), Gia_ManName(pGia), f ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } break; } } if ( RetValue == -2 ) RetValue = -1; // dump unfolded frames if ( pPars->fDumpFrames ) { p->pFrames = Gia_ManCleanup( p->pFrames ); Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 ); printf( "Dumped unfolded frames into file \"frames.aig\".\n" ); Gia_ManStop( p->pFrames ); } // cleanup Unr_ManFree( pUnroll ); Bmc_MnaFree( p ); return RetValue; } /**Function************************************************************* Synopsis [Generate counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gia_ManBmcCexGen( Bmc_Mna_t * pMan, Gia_Man_t * p, int iOut ) { Abc_Cex_t * pCex; int i, iObjId, iSatVar, iOrigPi; int iFramePi = 0, iFrame = -1; pCex = Abc_CexAlloc( Gia_ManRegNum(p), Gia_ManPiNum(p), iOut / Gia_ManPoNum(p) + 1 ); pCex->iFrame = iOut / Gia_ManPoNum(p); pCex->iPo = iOut % Gia_ManPoNum(p); // fill in the input values Vec_IntForEachEntry( pMan->vPiMap, iOrigPi, i ) { if ( iOrigPi < 0 ) { iFrame = -iOrigPi-1; continue; } // iOrigPi in iFrame of pGia has PI index iFramePi in pMan->pFrames, iObjId = Gia_ObjId( pMan->pFrames, Gia_ManPi(pMan->pFrames, iFramePi) ); iSatVar = Vec_IntEntry( pMan->vId2Var, iObjId ); if ( sat_solver_var_value(pMan->pSat, iSatVar) ) Abc_InfoSetBit( pCex->pData, Gia_ManRegNum(p) + Gia_ManPiNum(p) * iFrame + iOrigPi ); iFramePi++; } assert( iFramePi == Gia_ManPiNum(pMan->pFrames) ); return pCex; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBmcPerform_old_cnf( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) { Bmc_Mna_t * p; int nFramesMax, f, i=0, Lit, status, RetValue = -2; abctime clk = Abc_Clock(); p = Bmc_MnaAlloc(); p->pFrames = Gia_ManBmcUnroll( pGia, pPars->nFramesMax, pPars->nFramesAdd, pPars->fVeryVerbose, &p->vPiMap ); nFramesMax = Gia_ManPoNum(p->pFrames) / Gia_ManPoNum(pGia); if ( pPars->fVerbose ) { printf( "Unfolding for %d frames with first non-trivial PO %d. ", nFramesMax, Gia_ManBmcFindFirst(p->pFrames) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } if ( pPars->fUseSynth ) { Gia_Man_t * pTemp = p->pFrames; p->pFrames = Gia_ManAigSyn2( pTemp, 1, 0, 0, 0, 0, pPars->fVerbose, 0 ); Gia_ManStop( pTemp ); } else if ( pPars->fVerbose ) Gia_ManPrintStats( p->pFrames, NULL ); if ( pPars->fDumpFrames ) { Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 ); printf( "Dumped unfolded frames into file \"frames.aig\".\n" ); } for ( f = 0; f < nFramesMax; f++ ) { if ( !Gia_ManBmcCheckOutputs( p->pFrames, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ) ) { // create another slice Gia_ManBmcAddCone( p, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ); // create CNF in the SAT solver Gia_ManBmcAddCnf( p, p->pFrames, p->vInputs, p->vNodes, p->vOutputs ); // try solving the outputs for ( i = f * Gia_ManPoNum(pGia); i < (f+1) * Gia_ManPoNum(pGia); i++ ) { Gia_Obj_t * pObj = Gia_ManPo(p->pFrames, i); if ( Gia_ObjChild0(pObj) == Gia_ManConst0(p->pFrames) ) continue; Lit = Abc_Var2Lit( Vec_IntEntry(p->vId2Var, Gia_ObjId(p->pFrames, pObj)), 0 ); status = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_False ) // unsat continue; if ( status == l_True ) // sat RetValue = 0; if ( status == l_Undef ) // undecided RetValue = -1; break; } // report statistics if ( pPars->fVerbose ) { printf( "%4d : PI =%9d. AIG =%9d. Var =%8d. In =%6d. And =%9d. Cla =%9d. Conf =%9d. Mem =%7.1f MB ", f, Gia_ManPiNum(p->pFrames), Gia_ManAndNum(p->pFrames), p->nSatVars-1, Vec_IntSize(p->vInputs), Vec_IntSize(p->vNodes), sat_solver_nclauses(p->pSat), sat_solver_nconflicts(p->pSat), Gia_ManMemory(p->pFrames)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } } if ( RetValue != -2 ) { if ( RetValue == -1 ) printf( "SAT solver reached conflict/runtime limit in frame %d.\n", f ); else { ABC_FREE( pGia->pCexSeq ); pGia->pCexSeq = Gia_ManBmcCexGen( p, pGia, i ); printf( "Output %d of miter \"%s\" was asserted in frame %d. ", i - f * Gia_ManPoNum(pGia), Gia_ManName(pGia), f ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } break; } pPars->iFrame = f; } if ( RetValue == -2 ) RetValue = -1; // cleanup Gia_ManStop( p->pFrames ); Bmc_MnaFree( p ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManBmcAddCnfNew_rec( Bmc_Mna_t * p, Gia_Obj_t * pObj ) { int iObj = Gia_ObjId( p->pFrames, pObj ); if ( Vec_IntEntry(p->vId2Var, iObj) > 0 ) return; Vec_IntWriteEntry(p->vId2Var, iObj, 1); if ( Gia_ObjIsAnd(pObj) && p->pCnf->pObj2Count[iObj] == -1 ) { Gia_ManBmcAddCnfNew_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManBmcAddCnfNew_rec( p, Gia_ObjFanin1(pObj) ); return; } Vec_IntWriteEntry(p->vId2Var, iObj, p->nSatVars++); if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsPo(p->pFrames, pObj) ) { int i, nClas, iCla; Gia_ManBmcAddCnfNew_rec( p, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsAnd(pObj) ) Gia_ManBmcAddCnfNew_rec( p, Gia_ObjFanin1(pObj) ); // extend the SAT solver if ( p->nSatVars > sat_solver_nvars(p->pSat) ) sat_solver_setnvars( p->pSat, p->nSatVars ); // add clauses nClas = p->pCnf->pObj2Count[iObj]; iCla = p->pCnf->pObj2Clause[iObj]; for ( i = 0; i < nClas; i++ ) { int nLits, pLits[10]; int * pClauseThis = p->pCnf->pClauses[iCla+i]; int * pClauseNext = p->pCnf->pClauses[iCla+i+1]; for ( nLits = 0; pClauseThis + nLits < pClauseNext; nLits++ ) { if ( pClauseThis[nLits] < 2 ) printf( "\n\n\nError in CNF generation: Constant literal!\n\n\n" ); assert( pClauseThis[nLits] > 1 && pClauseThis[nLits] < 2*Gia_ManObjNum(p->pFrames) ); pLits[nLits] = Abc_Lit2LitV( Vec_IntArray(p->vId2Var), pClauseThis[nLits] ); } assert( nLits <= 9 ); if ( !sat_solver_addclause( p->pSat, pLits, pLits + nLits ) ) break; } if ( i < nClas ) printf( "SAT solver became UNSAT after adding clauses.\n" ); } else assert( Gia_ObjIsCi(pObj) ); } void Gia_ManBmcAddCnfNew( Bmc_Mna_t * p, int iStart, int iStop ) { Gia_Obj_t * pObj; int i; for ( i = iStart; i < iStop; i++ ) { pObj = Gia_ManPo(p->pFrames, i); if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p->pFrames) ) continue; Gia_ManBmcAddCnfNew_rec( p, pObj ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cnf_Dat_t * Cnf_DeriveGia( Gia_Man_t * p ) { Aig_Man_t * pAig = Gia_ManToAigSimple( p ); Cnf_Dat_t * pCnf = Cnf_DeriveOther( pAig, 1 ); Aig_ManStop( pAig ); return pCnf; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBmcPerformInt( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) { Bmc_Mna_t * p; Gia_Man_t * pTemp; int nFramesMax, f, i=0, Lit = 1, status, RetValue = -2; abctime clk = Abc_Clock(); p = Bmc_MnaAlloc(); sat_solver_set_runtime_limit( p->pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); p->pFrames = Gia_ManBmcUnroll( pGia, pPars->nFramesMax, pPars->nFramesAdd, pPars->fVeryVerbose, &p->vPiMap ); nFramesMax = Gia_ManPoNum(p->pFrames) / Gia_ManPoNum(pGia); if ( pPars->fVerbose ) { printf( "Unfolding for %d frames with first non-trivial PO %d. ", nFramesMax, Gia_ManBmcFindFirst(p->pFrames) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } if ( pPars->fUseSynth ) { p->pFrames = Gia_ManAigSyn2( pTemp = p->pFrames, 1, 0, 0, 0, 0, pPars->fVerbose, 0 ); Gia_ManStop( pTemp ); } else if ( pPars->fVerbose ) Gia_ManPrintStats( p->pFrames, NULL ); if ( pPars->fDumpFrames ) { Gia_AigerWrite( p->pFrames, "frames.aig", 0, 0 ); printf( "Dumped unfolded frames into file \"frames.aig\".\n" ); } if ( pPars->fUseOldCnf ) p->pCnf = Cnf_DeriveGia( p->pFrames ); else { // p->pFrames = Jf_ManDeriveCnf( pTemp = p->pFrames, 1 ); Gia_ManStop( pTemp ); // p->pCnf = (Cnf_Dat_t *)p->pFrames->pData; p->pFrames->pData = NULL; extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); p->pCnf = Mf_ManGenerateCnf( p->pFrames, pPars->nLutSize, 1, 0, pPars->fVerbose ); } Vec_IntFillExtra( p->vId2Var, Gia_ManObjNum(p->pFrames), 0 ); // create clauses for constant node // sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); for ( f = 0; f < nFramesMax; f++ ) { if ( !Gia_ManBmcCheckOutputs( p->pFrames, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ) ) { // create another slice Gia_ManBmcAddCnfNew( p, f * Gia_ManPoNum(pGia), (f+1) * Gia_ManPoNum(pGia) ); // try solving the outputs for ( i = f * Gia_ManPoNum(pGia); i < (f+1) * Gia_ManPoNum(pGia); i++ ) { Gia_Obj_t * pObj = Gia_ManPo(p->pFrames, i); if ( Gia_ObjChild0(pObj) == Gia_ManConst0(p->pFrames) ) continue; if ( Gia_ObjChild0(pObj) == Gia_ManConst1(p->pFrames) ) { printf( "Output %d is trivially SAT.\n", i ); continue; } Lit = Abc_Var2Lit( Vec_IntEntry(p->vId2Var, Gia_ObjId(p->pFrames, pObj)), 0 ); status = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_False ) // unsat continue; if ( status == l_True ) // sat RetValue = 0; if ( status == l_Undef ) // undecided RetValue = -1; break; } // report statistics if ( pPars->fVerbose ) { printf( "%4d : PI =%9d. AIG =%9d. Var =%8d. In =%6d. And =%9d. Cla =%9d. Conf =%9d. Mem =%7.1f MB ", f, Gia_ManPiNum(p->pFrames), Gia_ManAndNum(p->pFrames), p->nSatVars-1, Vec_IntSize(p->vInputs), Vec_IntSize(p->vNodes), sat_solver_nclauses(p->pSat), sat_solver_nconflicts(p->pSat), Gia_ManMemory(p->pFrames)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } } if ( RetValue != -2 ) { if ( RetValue == -1 ) printf( "SAT solver reached conflict/runtime limit in frame %d.\n", f ); else { ABC_FREE( pGia->pCexSeq ); pGia->pCexSeq = Gia_ManBmcCexGen( p, pGia, i ); printf( "Output %d of miter \"%s\" was asserted in frame %d. ", i - f * Gia_ManPoNum(pGia), Gia_ManName(pGia), f ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } break; } pPars->iFrame = f; } if ( RetValue == -2 ) RetValue = -1; // cleanup Gia_ManStop( p->pFrames ); Bmc_MnaFree( p ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBmcPerform( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) { abctime TimeToStop = pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0; if ( pPars->nFramesAdd == 0 ) return Gia_ManBmcPerformInt( pGia, pPars ); // iterate over the engine until we read the global timeout assert( pPars->nTimeOut >= 0 ); while ( 1 ) { if ( TimeToStop && TimeToStop < Abc_Clock() ) return -1; if ( Gia_ManBmcPerformInt( pGia, pPars ) == 0 ) return 0; // set the new runtime limit if ( pPars->nTimeOut ) { pPars->nTimeOut = Abc_MinInt( pPars->nTimeOut-1, (int)((TimeToStop - Abc_Clock()) / CLOCKS_PER_SEC) ); if ( pPars->nTimeOut <= 0 ) return -1; } else return -1; // set the new frames limit pPars->nFramesAdd *= 2; } return -1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcBmci.c000066400000000000000000000275631300674244400231010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcBmci.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcBmci.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p ) { Cnf_Dat_t * pCnf; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); pAig->nRegs = 0; pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Aig_ManStop( pAig ); return pCnf; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cnf_DataLiftGia( Cnf_Dat_t * p, Gia_Man_t * pGia, int nVarsPlus ) { Gia_Obj_t * pObj; int v; Gia_ManForEachObj( pGia, pObj, v ) if ( p->pVarNums[Gia_ObjId(pGia, pObj)] >= 0 ) p->pVarNums[Gia_ObjId(pGia, pObj)] += nVarsPlus; for ( v = 0; v < p->nLiterals; v++ ) p->pClauses[0][v] += 2*nVarsPlus; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_BmciUnfold( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vFFLits, int fPiReuse ) { Gia_Obj_t * pObj; int i; assert( Gia_ManRegNum(p) == Vec_IntSize(vFFLits) ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachRo( p, pObj, i ) pObj->Value = Vec_IntEntry(vFFLits, i); Gia_ManForEachPi( p, pObj, i ) pObj->Value = fPiReuse ? Gia_ObjToLit(pNew, Gia_ManPi(pNew, Gia_ManPiNum(pNew)-Gia_ManPiNum(p)+i)) : Gia_ManAppendCi(pNew); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachRi( p, pObj, i ) Vec_IntWriteEntry( vFFLits, i, Gia_ObjFanin0Copy(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_BmciPart_rec( Gia_Man_t * pNew, Vec_Int_t * vSatMap, int iIdNew, Gia_Man_t * pPart, Vec_Int_t * vPartMap, Vec_Int_t * vCopies ) { Gia_Obj_t * pObj = Gia_ManObj( pNew, iIdNew ); int iLitPart0, iLitPart1, iRes; if ( Vec_IntEntry(vCopies, iIdNew) ) return Vec_IntEntry(vCopies, iIdNew); if ( Vec_IntEntry(vSatMap, iIdNew) >= 0 || Gia_ObjIsCi(pObj) ) { Vec_IntPush( vPartMap, iIdNew ); iRes = Gia_ManAppendCi(pPart); Vec_IntWriteEntry( vCopies, iIdNew, iRes ); return iRes; } assert( Gia_ObjIsAnd(pObj) ); iLitPart0 = Bmc_BmciPart_rec( pNew, vSatMap, Gia_ObjFaninId0(pObj, iIdNew), pPart, vPartMap, vCopies ); iLitPart1 = Bmc_BmciPart_rec( pNew, vSatMap, Gia_ObjFaninId1(pObj, iIdNew), pPart, vPartMap, vCopies ); iLitPart0 = Abc_LitNotCond( iLitPart0, Gia_ObjFaninC0(pObj) ); iLitPart1 = Abc_LitNotCond( iLitPart1, Gia_ObjFaninC1(pObj) ); Vec_IntPush( vPartMap, iIdNew ); iRes = Gia_ManAppendAnd( pPart, iLitPart0, iLitPart1 ); Vec_IntWriteEntry( vCopies, iIdNew, iRes ); return iRes; } Gia_Man_t * Bmc_BmciPart( Gia_Man_t * pNew, Vec_Int_t * vSatMap, Vec_Int_t * vMiters, Vec_Int_t * vPartMap, Vec_Int_t * vCopies ) { Gia_Man_t * pPart; int i, iLit, iLitPart; Vec_IntFill( vCopies, Gia_ManObjNum(pNew), 0 ); Vec_IntFillExtra( vSatMap, Gia_ManObjNum(pNew), -1 ); pPart = Gia_ManStart( 1000 ); pPart->pName = Abc_UtilStrsav( pNew->pName ); Vec_IntClear( vPartMap ); Vec_IntPush( vPartMap, 0 ); Vec_IntForEachEntry( vMiters, iLit, i ) { if ( iLit == -1 ) continue; assert( iLit >= 2 ); iLitPart = Bmc_BmciPart_rec( pNew, vSatMap, Abc_Lit2Var(iLit), pPart, vPartMap, vCopies ); Gia_ManAppendCo( pPart, Abc_LitNotCond(iLitPart, Abc_LitIsCompl(iLit)) ); Vec_IntPush( vPartMap, -1 ); } assert( Gia_ManPoNum(pPart) > 0 ); assert( Vec_IntSize(vPartMap) == Gia_ManObjNum(pPart) ); return pPart; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_BmciPerform( Gia_Man_t * p, Vec_Int_t * vInit0, Vec_Int_t * vInit1, int nFrames, int nWords, int nTimeOut, int fVerbose ) { int nSatVars = 1; Vec_Int_t * vLits0, * vLits1, * vMiters, * vSatMap, * vPartMap, * vCopies; Gia_Man_t * pNew, * pPart; Gia_Obj_t * pObj; Cnf_Dat_t * pCnf; sat_solver * pSat; int iVar0, iVar1, iLit, iLit0, iLit1; int i, f, status, nChanges, nMiters, RetValue = 1; assert( Vec_IntSize(vInit0) == Gia_ManRegNum(p) ); assert( Vec_IntSize(vInit1) == Gia_ManRegNum(p) ); // start the SAT solver pSat = sat_solver_new(); sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); pNew = Gia_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; vLits0 = Vec_IntAlloc( Gia_ManRegNum(p) ); Vec_IntForEachEntry( vInit0, iLit, i ) Vec_IntPush( vLits0, iLit < 2 ? iLit : Gia_ManAppendCi(pNew) ); vLits1 = Vec_IntAlloc( Gia_ManRegNum(p) ); Vec_IntForEachEntry( vInit1, iLit, i ) Vec_IntPush( vLits1, iLit < 2 ? iLit : Gia_ManAppendCi(pNew) ); vMiters = Vec_IntAlloc( 1000 ); vSatMap = Vec_IntAlloc( 1000 ); vPartMap = Vec_IntAlloc( 1000 ); vCopies = Vec_IntAlloc( 1000 ); for ( f = 0; f < nFrames; f++ ) { abctime clk = Abc_Clock(); Bmc_BmciUnfold( pNew, p, vLits0, 0 ); Bmc_BmciUnfold( pNew, p, vLits1, 1 ); assert( Vec_IntSize(vLits0) == Vec_IntSize(vLits1) ); nMiters = 0; Vec_IntClear( vMiters ); Vec_IntForEachEntryTwo( vLits0, vLits1, iLit0, iLit1, i ) if ( (iLit0 >= 2 || iLit1 >= 2) && iLit0 != iLit1 ) Vec_IntPush( vMiters, Gia_ManHashXor(pNew, iLit0, iLit1) ), nMiters++; else Vec_IntPush( vMiters, -1 ); assert( Vec_IntSize(vMiters) == Gia_ManRegNum(p) ); if ( Vec_IntSum(vMiters) + Vec_IntSize(vLits1) == 0 ) { if ( fVerbose ) printf( "Reached a fixed point after %d frames. \n", f+1 ); break; } // create new part pPart = Bmc_BmciPart( pNew, vSatMap, vMiters, vPartMap, vCopies ); pCnf = Cnf_DeriveGiaRemapped( pPart ); Cnf_DataLiftGia( pCnf, pPart, nSatVars ); nSatVars += pCnf->nVars; sat_solver_setnvars( pSat, nSatVars ); for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) assert( 0 ); // stitch the clauses Gia_ManForEachPi( pPart, pObj, i ) { iVar0 = pCnf->pVarNums[Gia_ObjId(pPart, pObj)]; iVar1 = Vec_IntEntry( vSatMap, Vec_IntEntry(vPartMap, Gia_ObjId(pPart, pObj)) ); if ( iVar1 == -1 ) continue; sat_solver_add_buffer( pSat, iVar0, iVar1, 0 ); } // transfer variables Gia_ManForEachCand( pPart, pObj, i ) if ( pCnf->pVarNums[i] >= 0 ) { assert( Gia_ObjIsCi(pObj) || Vec_IntEntry( vSatMap, Vec_IntEntry(vPartMap, i) ) == -1 ); Vec_IntWriteEntry( vSatMap, Vec_IntEntry(vPartMap, i), pCnf->pVarNums[i] ); } Cnf_DataFree( pCnf ); Gia_ManStop( pPart ); // perform runs nChanges = 0; Vec_IntForEachEntry( vMiters, iLit, i ) { if ( iLit == -1 ) continue; assert( Vec_IntEntry(vSatMap, Abc_Lit2Var(iLit)) > 0 ); iLit = Abc_Lit2LitV( Vec_IntArray(vSatMap), iLit ); status = sat_solver_solve( pSat, &iLit, &iLit + 1, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_True ) { nChanges++; continue; } if ( status == l_Undef ) { printf( "Timeout reached after %d seconds. \n", nTimeOut ); RetValue = 0; goto cleanup; } assert( status == l_False ); iLit0 = Vec_IntEntry( vLits0, i ); iLit1 = Vec_IntEntry( vLits1, i ); assert( (iLit0 >= 2 || iLit1 >= 2) && iLit0 != iLit1 ); if ( iLit1 >= 2 ) Vec_IntWriteEntry( vLits1, i, iLit0 ); else Vec_IntWriteEntry( vLits0, i, iLit1 ); iLit0 = Vec_IntEntry( vLits0, i ); iLit1 = Vec_IntEntry( vLits1, i ); assert( iLit0 == iLit1 ); } if ( fVerbose ) { printf( "Frame %4d : ", f+1 ); printf( "Vars =%7d ", nSatVars ); printf( "Clause =%10d ", sat_solver_nclauses(pSat) ); printf( "Conflict =%10d ", sat_solver_nconflicts(pSat) ); printf( "AIG =%7d ", Gia_ManAndNum(pNew) ); printf( "Miters =%5d ", nMiters ); printf( "SAT =%5d ", nChanges ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } if ( nChanges == 0 ) { printf( "Reached a fixed point after %d frames. \n", f+1 ); break; } } cleanup: sat_solver_delete( pSat ); Gia_ManStopP( &pNew ); Vec_IntFree( vLits0 ); Vec_IntFree( vLits1 ); Vec_IntFree( vMiters ); Vec_IntFree( vSatMap ); Vec_IntFree( vPartMap ); Vec_IntFree( vCopies ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBmciTest( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose ) { Vec_Int_t * vInit0 = Vec_IntStart( Gia_ManRegNum(p) ); Bmc_BmciPerform( p, vInit, vInit0, nFrames, nWords, nTimeOut, fVerbose ); Vec_IntFree( vInit0 ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcCexCare.c000066400000000000000000000275751300674244400235440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcCexCare.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Computing care set of the counter-example.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcCexCare.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Takes CEX and its care-set. Returns care-set of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ) { Abc_Cex_t * pNew; Gia_Obj_t * pObj; int i, k; assert( pCex->nPis == pCexCare->nPis ); assert( pCex->nRegs == pCexCare->nRegs ); assert( pCex->nBits == pCexCare->nBits ); // start the counter-example pNew = Abc_CexAlloc( pCex->nRegs, Gia_ManObjNum(p), pCex->iFrame + 1 ); pNew->iFrame = pCex->iFrame; pNew->iPo = pCex->iPo; // initialize terminary simulation Gia_ObjTerSimSet0( Gia_ManConst0(p) ); Gia_ManForEachRi( p, pObj, k ) Gia_ObjTerSimSet0( pObj ); for ( i = 0; i <= pCex->iFrame; i++ ) { Gia_ManForEachPi( p, pObj, k ) { if ( !Abc_InfoHasBit( pCexCare->pData, pCexCare->nRegs + i * pCexCare->nPis + k ) ) Gia_ObjTerSimSetX( pObj ); else if ( Abc_InfoHasBit( pCex->pData, pCex->nRegs + i * pCex->nPis + k ) ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); } Gia_ManForEachRo( p, pObj, k ) Gia_ObjTerSimRo( p, pObj ); Gia_ManForEachAnd( p, pObj, k ) Gia_ObjTerSimAnd( pObj ); Gia_ManForEachCo( p, pObj, k ) Gia_ObjTerSimCo( pObj ); // add cares to the exdended counter-example Gia_ManForEachObj( p, pObj, k ) if ( !Gia_ObjTerSimGetX(pObj) ) Abc_InfoSetBit( pNew->pData, pNew->nRegs + pNew->nPis * i + k ); } pObj = Gia_ManPo( p, pCex->iPo ); assert( Gia_ObjTerSimGet1(pObj) ); return pNew; } /**Function************************************************************* Synopsis [Backward propagation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_CexCarePropagateFwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGrow ) { Gia_Obj_t * pObj; int Prio, Prio0, Prio1; int i, Phase0, Phase1; if ( (fGrow & 2) ) { Gia_ManForEachPi( p, pObj, i ) pObj->Value = Abc_Var2Lit( f * pCex->nPis + (pCex->nPis-1-i) + 1, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) ); } else { Gia_ManForEachPi( p, pObj, i ) pObj->Value = Abc_Var2Lit( f * pCex->nPis + i + 1, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) ); } Gia_ManForEachAnd( p, pObj, i ) { Prio0 = Abc_Lit2Var(Gia_ObjFanin0(pObj)->Value); Prio1 = Abc_Lit2Var(Gia_ObjFanin1(pObj)->Value); Phase0 = Abc_LitIsCompl(Gia_ObjFanin0(pObj)->Value) ^ Gia_ObjFaninC0(pObj); Phase1 = Abc_LitIsCompl(Gia_ObjFanin1(pObj)->Value) ^ Gia_ObjFaninC1(pObj); if ( Phase0 && Phase1 ) Prio = (fGrow & 1) ? Abc_MinInt(Prio0, Prio1) : Abc_MaxInt(Prio0, Prio1); else if ( Phase0 && !Phase1 ) Prio = Prio1; else if ( !Phase0 && Phase1 ) Prio = Prio0; else // if ( !Phase0 && !Phase1 ) Prio = (fGrow & 1) ? Abc_MaxInt(Prio0, Prio1) : Abc_MinInt(Prio0, Prio1); pObj->Value = Abc_Var2Lit( Prio, Phase0 & Phase1 ); } Gia_ManForEachCo( p, pObj, i ) pObj->Value = Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } void Bmc_CexCarePropagateFwd( Gia_Man_t * p, Abc_Cex_t * pCex, int fGrow, Vec_Int_t * vPrios ) { Gia_Obj_t * pObj, * pObjRo, * pObjRi; int f, i; Gia_ManConst0( p )->Value = 0; Gia_ManForEachRi( p, pObj, i ) pObj->Value = 0; Vec_IntClear( vPrios ); for ( f = 0; f <= pCex->iFrame; f++ ) { Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) Vec_IntPush( vPrios, (pObjRo->Value = pObjRi->Value) ); Bmc_CexCarePropagateFwdOne( p, pCex, f, fGrow ); } } /**Function************************************************************* Synopsis [Forward propagation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_CexCarePropagateBwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, Abc_Cex_t * pCexMin ) { Gia_Obj_t * pObj; int i, Phase0, Phase1; Gia_ManForEachCand( p, pObj, i ) pObj->fPhase = 0; Gia_ManForEachCo( p, pObj, i ) if ( pObj->fPhase ) Gia_ObjFanin0(pObj)->fPhase = 1; Gia_ManForEachAndReverse( p, pObj, i ) { if ( !pObj->fPhase ) continue; Phase0 = Abc_LitIsCompl(Gia_ObjFanin0(pObj)->Value) ^ Gia_ObjFaninC0(pObj); Phase1 = Abc_LitIsCompl(Gia_ObjFanin1(pObj)->Value) ^ Gia_ObjFaninC1(pObj); if ( Phase0 && Phase1 ) { Gia_ObjFanin0(pObj)->fPhase = 1; Gia_ObjFanin1(pObj)->fPhase = 1; } else if ( Phase0 && !Phase1 ) Gia_ObjFanin1(pObj)->fPhase = 1; else if ( !Phase0 && Phase1 ) Gia_ObjFanin0(pObj)->fPhase = 1; else // if ( !Phase0 && !Phase1 ) { if ( Abc_Lit2Var(Gia_ObjFanin0(pObj)->Value) <= Abc_Lit2Var(Gia_ObjFanin1(pObj)->Value) ) Gia_ObjFanin0(pObj)->fPhase = 1; else Gia_ObjFanin1(pObj)->fPhase = 1; } } Gia_ManForEachPi( p, pObj, i ) if ( pObj->fPhase ) Abc_InfoSetBit( pCexMin->pData, pCexMin->nRegs + pCexMin->nPis * f + i ); } Abc_Cex_t * Bmc_CexCarePropagateBwd( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vPrios, int fGrow ) { Abc_Cex_t * pCexMin; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int f, i; pCexMin = Abc_CexAlloc( pCex->nRegs, pCex->nPis, pCex->iFrame + 1 ); pCexMin->iPo = pCex->iPo; pCexMin->iFrame = pCex->iFrame; Gia_ManForEachCo( p, pObj, i ) pObj->fPhase = 0; for ( f = pCex->iFrame; f >= 0; f-- ) { Gia_ManPo(p, pCex->iPo)->fPhase = (int)(f == pCex->iFrame); Gia_ManForEachRo( p, pObj, i ) pObj->Value = Vec_IntEntry( vPrios, f * pCex->nRegs + i ); Bmc_CexCarePropagateFwdOne( p, pCex, f, fGrow ); Bmc_CexCarePropagateBwdOne( p, pCex, f, pCexMin ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) pObjRi->fPhase = pObjRo->fPhase; } return pCexMin; } /**Function************************************************************* Synopsis [Computes the care set of the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose ) { int nTryCexes = 4; // belongs to range [1;4] Abc_Cex_t * pCexBest, * pCexMin[4] = {NULL}; int k, nOnesBest, nOnesCur; Vec_Int_t * vPrios; if ( pCex->nPis != Gia_ManPiNum(p) ) { printf( "Given CEX does to have same number of inputs as the AIG.\n" ); return NULL; } if ( pCex->nRegs != Gia_ManRegNum(p) ) { printf( "Given CEX does to have same number of flops as the AIG.\n" ); return NULL; } if ( !(pCex->iPo >= 0 && pCex->iPo < Gia_ManPoNum(p)) ) { printf( "Given CEX has PO whose index is out of range for the AIG.\n" ); return NULL; } assert( pCex->nPis == Gia_ManPiNum(p) ); assert( pCex->nRegs == Gia_ManRegNum(p) ); assert( pCex->iPo >= 0 && pCex->iPo < Gia_ManPoNum(p) ); if ( fVerbose ) { printf( "Original : " ); Bmc_CexPrint( pCex, Gia_ManPiNum(p), 0 ); } vPrios = Vec_IntAlloc( pCex->nRegs * (pCex->iFrame + 1) ); for ( k = 0; k < nTryCexes; k++ ) { Bmc_CexCarePropagateFwd(p, pCex, k, vPrios ); assert( Vec_IntSize(vPrios) == pCex->nRegs * (pCex->iFrame + 1) ); if ( !Abc_LitIsCompl(Gia_ManPo(p, pCex->iPo)->Value) ) { printf( "Counter-example is invalid.\n" ); Vec_IntFree( vPrios ); return NULL; } pCexMin[k] = Bmc_CexCarePropagateBwd( p, pCex, vPrios, k ); if ( fVerbose ) { if ( (k & 1) ) printf( "Decrease : " ); else printf( "Increase : " ); Bmc_CexPrint( pCexMin[k], Gia_ManPiNum(p), 0 ); } } Vec_IntFree( vPrios ); // select the best one pCexBest = pCexMin[0]; nOnesBest = Abc_CexCountOnes(pCexMin[0]); for ( k = 1; k < nTryCexes; k++ ) { nOnesCur = Abc_CexCountOnes(pCexMin[k]); if ( nOnesBest > nOnesCur ) { nOnesBest = nOnesCur; pCexBest = pCexMin[k]; } } for ( k = 0; k < nTryCexes; k++ ) if ( pCexBest != pCexMin[k] ) Abc_CexFreeP( &pCexMin[k] ); // verify and return if ( fVerbose ) { printf( "Final : " ); Bmc_CexPrint( pCexBest, Gia_ManPiNum(p), 0 ); } if ( !Bmc_CexVerify( p, pCex, pCexBest ) ) printf( "Counter-example verification has failed.\n" ); else if ( fCheck ) printf( "Counter-example verification succeeded.\n" ); return pCexBest; } Abc_Cex_t * Bmc_CexCareMinimize( Aig_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose ) { Gia_Man_t * pGia = Gia_ManFromAigSimple( p ); Abc_Cex_t * pCexMin = Bmc_CexCareMinimizeAig( pGia, pCex, fCheck, fVerbose ); Gia_ManStop( pGia ); return pCexMin; } /**Function************************************************************* Synopsis [Verifies the care set of the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ) { Gia_Man_t * pGia = Gia_ManFromAigSimple( p ); if ( fVerbose ) { printf( "Original : " ); Bmc_CexPrint( pCex, Gia_ManPiNum(pGia), 0 ); printf( "Minimized: " ); Bmc_CexPrint( pCexMin, Gia_ManPiNum(pGia), 0 ); } if ( !Bmc_CexVerify( pGia, pCex, pCexMin ) ) printf( "Counter-example verification has failed.\n" ); else printf( "Counter-example verification succeeded.\n" ); Gia_ManStop( pGia ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcCexCut.c000066400000000000000000000506741300674244400234210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcCexCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Derives characterization of bad states.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcCexCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Generate justifying assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_GiaGenerateJust_rec( Gia_Man_t * p, int iFrame, int iObj, Vec_Bit_t * vValues, Vec_Bit_t * vJustis ) { Gia_Obj_t * pObj; int Shift = Gia_ManObjNum(p) * iFrame; if ( iFrame < 0 ) return 0; assert( iFrame >= 0 ); if ( Vec_BitEntry( vJustis, Shift + iObj ) ) return 0; Vec_BitWriteEntry( vJustis, Shift + iObj, 1 ); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCo(pObj) ) return Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId0(pObj, iObj), vValues, vJustis ); if ( Gia_ObjIsCi(pObj) ) return Bmc_GiaGenerateJust_rec( p, iFrame-1, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)), vValues, vJustis ); assert( Gia_ObjIsAnd(pObj) ); if ( Vec_BitEntry( vValues, Shift + iObj ) ) { Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId0(pObj, iObj), vValues, vJustis ); Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId1(pObj, iObj), vValues, vJustis ); } else if ( Vec_BitEntry( vValues, Shift + Gia_ObjFaninId0(pObj, iObj) ) == Gia_ObjFaninC0(pObj) ) Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId0(pObj, iObj), vValues, vJustis ); else if ( Vec_BitEntry( vValues, Shift + Gia_ObjFaninId1(pObj, iObj) ) == Gia_ObjFaninC1(pObj) ) Bmc_GiaGenerateJust_rec( p, iFrame, Gia_ObjFaninId1(pObj, iObj), vValues, vJustis ); else assert( 0 ); return 0; } void Bmc_GiaGenerateJustNonRec( Gia_Man_t * p, int iFrame, Vec_Bit_t * vValues, Vec_Bit_t * vJustis ) { Gia_Obj_t * pObj; int i, k, Shift = Gia_ManObjNum(p) * iFrame; for ( i = iFrame; i >= 0; i--, Shift -= Gia_ManObjNum(p) ) { Gia_ManForEachObjReverse( p, pObj, k ) { if ( k == 0 || Gia_ObjIsPi(p, pObj) ) continue; if ( !Vec_BitEntry( vJustis, Shift + k ) ) continue; if ( Gia_ObjIsAnd(pObj) ) { if ( Vec_BitEntry( vValues, Shift + k ) ) { Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId0(pObj, k), 1 ); Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId1(pObj, k), 1 ); } else if ( Vec_BitEntry( vValues, Shift + Gia_ObjFaninId0(pObj, k) ) == Gia_ObjFaninC0(pObj) ) Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId0(pObj, k), 1 ); else if ( Vec_BitEntry( vValues, Shift + Gia_ObjFaninId1(pObj, k) ) == Gia_ObjFaninC1(pObj) ) Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId1(pObj, k), 1 ); else assert( 0 ); } else if ( Gia_ObjIsCo(pObj) ) Vec_BitWriteEntry( vJustis, Shift + Gia_ObjFaninId0(pObj, k), 1 ); else if ( Gia_ObjIsCi(pObj) && i ) Vec_BitWriteEntry( vJustis, Shift - Gia_ManObjNum(p) + Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)), 1 ); } } } void Bmc_GiaGenerateJust( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Bit_t ** pvValues, Vec_Bit_t ** pvJustis ) { Vec_Bit_t * vValues = Vec_BitStart( Gia_ManObjNum(p) * (pCex->iFrame + 1) ); Vec_Bit_t * vJustis = Vec_BitStart( Gia_ManObjNum(p) * (pCex->iFrame + 1) ); Gia_Obj_t * pObj; int i, k, iBit = 0, fCompl0, fCompl1, fJusti0, fJusti1, Shift; Gia_ManCleanMark0(p); Gia_ManCleanMark1(p); Gia_ManForEachRi( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); for ( Shift = i = 0; i <= pCex->iFrame; i++, Shift += Gia_ManObjNum(p) ) { Gia_ManForEachObj( p, pObj, k ) { if ( Gia_ObjIsAnd(pObj) ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); fJusti0 = Gia_ObjFanin0(pObj)->fMark1; fJusti1 = Gia_ObjFanin1(pObj)->fMark1; pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->fMark1 = fJusti0 & fJusti1; else if ( !fCompl0 && !fCompl1 ) pObj->fMark1 = fJusti0 | fJusti1; else if ( !fCompl0 ) pObj->fMark1 = fJusti0; else if ( !fCompl1 ) pObj->fMark1 = fJusti1; else assert( 0 ); } else if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjIsPi(p, pObj) ) { pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); pObj->fMark1 = 1; } else { pObj->fMark0 = Gia_ObjRoToRi(p, pObj)->fMark0; pObj->fMark1 = Gia_ObjRoToRi(p, pObj)->fMark1; } } else if ( Gia_ObjIsCo(pObj) ) { pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; } else if ( Gia_ObjIsConst0(pObj) ) pObj->fMark1 = 1; else assert( 0 ); if ( pObj->fMark0 ) Vec_BitWriteEntry( vValues, Shift + k, 1 ); if ( pObj->fMark1 ) Vec_BitWriteEntry( vJustis, Shift + k, 1 ); } } assert( iBit == pCex->nBits ); Gia_ManCleanMark0(p); Gia_ManCleanMark1(p); // perform backward traversal to mark just nodes pObj = Gia_ManPo( p, pCex->iPo ); assert( Vec_BitEntry(vJustis, Gia_ManObjNum(p) * pCex->iFrame + Gia_ObjId(p, pObj)) == 0 ); // Bmc_GiaGenerateJust_rec( p, pCex->iFrame, Gia_ObjId(p, pObj), vValues, vJustis ); Vec_BitWriteEntry(vJustis, Gia_ManObjNum(p) * pCex->iFrame + Gia_ObjId(p, pObj), 1); Bmc_GiaGenerateJustNonRec( p, pCex->iFrame, vValues, vJustis ); assert( Vec_BitEntry(vJustis, Gia_ManObjNum(p) * pCex->iFrame + Gia_ObjId(p, pObj)) == 1 ); // return the result *pvValues = vValues; *pvJustis = vJustis; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_GiaGenerateGiaOne( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Bit_t ** pvInits, int iFrBeg, int iFrEnd ) { Vec_Bit_t * vValues; Vec_Bit_t * vJustis; Gia_Man_t * pNew; Gia_Obj_t * pObj; int k, Cube = 1, Counter = 0; Bmc_GiaGenerateJust( p, pCex, &vValues, &vJustis ); // collect flop values in frame iFrBeg *pvInits = Vec_BitStart( Gia_ManRegNum(p) ); Gia_ManForEachRo( p, pObj, k ) if ( Vec_BitEntry(vValues, Gia_ManObjNum(p) * iFrBeg + Gia_ObjId(p, pObj)) ) Vec_BitWriteEntry( *pvInits, k, 1 ); // create GIA with justified values in iFrEnd pNew = Gia_ManStart( 2 * Gia_ManRegNum(p) + 2 ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManForEachRo( p, pObj, k ) { int Literal = Gia_ManAppendCi(pNew); if ( !Vec_BitEntry(vJustis, Gia_ManObjNum(p) * iFrEnd + Gia_ObjId(p, pObj)) ) continue; if ( Vec_BitEntry(vValues, Gia_ManObjNum(p) * iFrEnd + Gia_ObjId(p, pObj)) ) Cube = Gia_ManAppendAnd( pNew, Cube, Literal ); else Cube = Gia_ManAppendAnd( pNew, Cube, Abc_LitNot(Literal) ); Counter++; } // printf( "Only %d flops (out of %d) belong to the care set.\n", Counter, Gia_ManRegNum(p) ); Gia_ManAppendCo( pNew, Cube ); Vec_BitFree( vValues ); Vec_BitFree( vJustis ); return pNew; } /**Function************************************************************* Synopsis [Generates all frames from G to the last one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_GiaGenerateGiaAllFrames( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Bit_t ** pvInits, int iFrBeg, int iFrEnd ) { Vec_Bit_t * vInitEnd; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int f, i, k, iBitOld, iBit = 0, fCompl0, fCompl1; // skip trough the first iFrEnd frames Gia_ManCleanMark0(p); Gia_ManForEachRo( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); *pvInits = Vec_BitStart( Gia_ManRegNum(p) ); for ( i = 0; i < iFrEnd; i++ ) { // remember values in frame iFrBeg if ( i == iFrBeg ) Gia_ManForEachRo( p, pObjRo, k ) if ( pObjRo->fMark0 ) Vec_BitWriteEntry( *pvInits, k, 1 ); // simulate other values Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); 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; } assert( i == iFrEnd ); vInitEnd = Vec_BitStart( Gia_ManRegNum(p) ); Gia_ManForEachRo( p, pObjRo, k ) if ( pObjRo->fMark0 ) Vec_BitWriteEntry( vInitEnd, k, 1 ); // create new AIG manager pNew = Gia_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManForEachRo( p, pObjRo, k ) Gia_ManAppendCi(pNew); Gia_ManHashStart( pNew ); Gia_ManConst0(p)->Value = 1; Gia_ManForEachPi( p, pObj, k ) pObj->Value = 1; iBitOld = iBit; for ( f = iFrEnd; f <= pCex->iFrame; f++ ) { // set up correct init state Gia_ManForEachRo( p, pObjRo, k ) pObjRo->fMark0 = Vec_BitEntry( vInitEnd, k ); // simulate it for a few frames iBit = iBitOld; for ( i = iFrEnd; i < f; i++ ) { Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); 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; } // start creating values Gia_ManForEachRo( p, pObjRo, k ) pObjRo->Value = Abc_LitNotCond( Gia_Obj2Lit(pNew, Gia_ManPi(pNew, k)), !pObjRo->fMark0 ); for ( i = f; i <= pCex->iFrame; i++ ) { Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); Gia_ManForEachAnd( p, pObj, k ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 && !fCompl1 ) pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else if ( !fCompl1 ) pObj->Value = Gia_ObjFanin1(pObj)->Value; else assert( 0 ); assert( pObj->Value > 0 ); } Gia_ManForEachCo( p, pObj, k ) { pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); pObj->Value = Gia_ObjFanin0(pObj)->Value; assert( pObj->Value > 0 ); } if ( i == pCex->iFrame ) break; Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) { pObjRo->fMark0 = pObjRi->fMark0; pObjRo->Value = pObjRi->Value; } } assert( iBit == pCex->nBits ); // create PO Gia_ManAppendCo( pNew, Gia_ManPo(p, pCex->iPo)->Value ); } Gia_ManHashStop( pNew ); Vec_BitFree( vInitEnd ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Generates one frame.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_GiaGenerateGiaAllOne( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Bit_t ** pvInits, int iFrBeg, int iFrEnd ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int i, k, iBit = 0, fCompl0, fCompl1; // skip trough the first iFrEnd frames Gia_ManCleanMark0(p); Gia_ManForEachRo( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); *pvInits = Vec_BitStart( Gia_ManRegNum(p) ); for ( i = 0; i < iFrEnd; i++ ) { // remember values in frame iFrBeg if ( i == iFrBeg ) Gia_ManForEachRo( p, pObjRo, k ) if ( pObjRo->fMark0 ) Vec_BitWriteEntry( *pvInits, k, 1 ); // simulate other values Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); 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; } assert( i == iFrEnd ); // create new AIG manager pNew = Gia_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 1; Gia_ManForEachPi( p, pObj, k ) pObj->Value = 1; Gia_ManForEachRo( p, pObjRo, k ) pObjRo->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), !pObjRo->fMark0 ); Gia_ManHashStart( pNew ); for ( i = iFrEnd; i <= pCex->iFrame; i++ ) { Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); Gia_ManForEachAnd( p, pObj, k ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 && !fCompl1 ) pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else if ( !fCompl1 ) pObj->Value = Gia_ObjFanin1(pObj)->Value; else assert( 0 ); assert( pObj->Value > 0 ); } Gia_ManForEachCo( p, pObj, k ) { pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); pObj->Value = Gia_ObjFanin0(pObj)->Value; assert( pObj->Value > 0 ); } if ( i == pCex->iFrame ) break; Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) { pObjRo->fMark0 = pObjRi->fMark0; pObjRo->Value = pObjRi->Value; } } Gia_ManHashStop( pNew ); assert( iBit == pCex->nBits ); // create PO Gia_ManAppendCo( pNew, Gia_ManPo(p, pCex->iPo)->Value ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Generate GIA for target bad states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_GiaTargetStates( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fUseOne, int fAllFrames, int fVerbose ) { Gia_Man_t * pNew, * pTemp; Vec_Bit_t * vInitNew; if ( iFrBeg < 0 ) { printf( "Starting frame is less than 0.\n" ); return NULL; } if ( iFrEnd < 0 ) { printf( "Stopping frame is less than 0.\n" ); return NULL; } if ( iFrBeg > pCex->iFrame ) { printf( "Starting frame is more than the last frame of CEX (%d).\n", pCex->iFrame ); return NULL; } if ( iFrEnd > pCex->iFrame ) { printf( "Stopping frame is more than the last frame of CEX (%d).\n", pCex->iFrame ); return NULL; } if ( iFrBeg > iFrEnd ) { printf( "Starting frame (%d) should be less than stopping frame (%d).\n", iFrBeg, iFrEnd ); return NULL; } assert( iFrBeg >= 0 && iFrBeg <= pCex->iFrame ); assert( iFrEnd >= 0 && iFrEnd <= pCex->iFrame ); assert( iFrBeg < iFrEnd ); if ( fUseOne ) pNew = Bmc_GiaGenerateGiaOne( p, pCex, &vInitNew, iFrBeg, iFrEnd ); else if ( fAllFrames ) pNew = Bmc_GiaGenerateGiaAllFrames( p, pCex, &vInitNew, iFrBeg, iFrEnd ); else pNew = Bmc_GiaGenerateGiaAllOne( p, pCex, &vInitNew, iFrBeg, iFrEnd ); if ( !fCombOnly ) { // create new GIA pNew = Gia_ManDupWithNewPo( p, pTemp = pNew ); Gia_ManStop( pTemp ); // create new initial state pNew = Gia_ManDupFlip( pTemp = pNew, Vec_BitArray(vInitNew) ); Gia_ManStop( pTemp ); } Vec_BitFree( vInitNew ); return pNew; } /**Function************************************************************* Synopsis [Generate AIG for target bad states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Bmc_AigTargetStates( Aig_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fUseOne, int fAllFrames, int fVerbose ) { Aig_Man_t * pAig; Gia_Man_t * pGia, * pRes; pGia = Gia_ManFromAigSimple( p ); if ( !Gia_ManVerifyCex( pGia, pCex, 0 ) ) { Abc_Print( 1, "Current CEX does not fail AIG \"%s\".\n", p->pName ); Gia_ManStop( pGia ); return NULL; } pRes = Bmc_GiaTargetStates( pGia, pCex, iFrBeg, iFrEnd, fCombOnly, fUseOne, fAllFrames, fVerbose ); Gia_ManStop( pGia ); pAig = Gia_ManToAigSimple( pRes ); Gia_ManStop( pRes ); return pAig; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcCexDepth.c000066400000000000000000000324111300674244400237170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcCexDepth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [CEX depth minimization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcCexDepth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Abc_Cex_t * Bmc_CexInnerStates( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t ** ppCexImpl, int fVerbose ); extern Abc_Cex_t * Bmc_CexCareBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexImpl, Abc_Cex_t * pCexEss, int fFindAll, int fVerbose ); extern int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs targe enlargement of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_CexTargetEnlarge( Gia_Man_t * p, int nFrames ) { Gia_Man_t * pNew, * pOne; Gia_Obj_t * pObj, * pObjRo; 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; for ( k = 0; k < nFrames; k++ ) Gia_ManForEachPi( p, pObj, i ) Gia_ManAppendCi( pNew ); Gia_ManForEachRo( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); for ( k = 0; k < nFrames; k++ ) { Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManCiLit( pNew, (nFrames - 1 - k) * Gia_ManPiNum(p) + i ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); Gia_ManForEachRiRo( p, pObj, pObjRo, i ) pObjRo->Value = pObj->Value; } pObj = Gia_ManPo( p, 0 ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pOne = pNew ); Gia_ManStop( pOne ); return pNew; } /**Function************************************************************* Synopsis [Create target with quantified inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_CexTarget( Gia_Man_t * p, int nFrames ) { Gia_Man_t * pNew, * pTemp; int i, Limit = nFrames * Gia_ManPiNum(p); pNew = Bmc_CexTargetEnlarge( p, nFrames ); for ( i = 0; i < Limit; i++ ) { printf( "%3d : ", i ); if ( i % Gia_ManPiNum(p) == 0 ) Gia_ManPrintStats( pNew, NULL ); pNew = Gia_ManDupExist( pTemp = pNew, i ); Gia_ManStop( pTemp ); } Gia_ManPrintStats( pNew, NULL ); pNew = Gia_ManDupLastPis( pTemp = pNew, Gia_ManRegNum(p) ); Gia_ManStop( pTemp ); Gia_ManPrintStats( pNew, NULL ); pTemp = Gia_ManDupAppendCones( p, &pNew, 1, 1 ); Gia_ManStop( pNew ); Gia_AigerWrite( pTemp, "miter3.aig", 0, 0 ); return pTemp; } /**Function************************************************************* Synopsis [Computes CE-induced network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_CexBuildNetwork2( Gia_Man_t * p, Abc_Cex_t * pCex, int fStart ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int fCompl0, fCompl1; int i, k, iBit; assert( pCex->nRegs == 0 ); assert( pCex->nPis == Gia_ManCiNum(p) ); assert( fStart <= pCex->iFrame ); // start the manager pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( "unate" ); // set const0 Gia_ManConst0(p)->fMark0 = 0; // value Gia_ManConst0(p)->fMark1 = 1; // care Gia_ManConst0(p)->Value = ~0; // set init state Gia_ManForEachRi( p, pObj, k ) { pObj->fMark0 = Abc_InfoHasBit( pCex->pData, pCex->nRegs + fStart * Gia_ManCiNum(p) + Gia_ManPiNum(p) + k ); pObj->fMark1 = 0; pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), !pObj->fMark0 ); } Gia_ManHashAlloc( pNew ); iBit = pCex->nRegs + fStart * Gia_ManCiNum(p); for ( i = fStart; i <= pCex->iFrame; i++ ) { // primary inputs Gia_ManForEachPi( p, pObj, k ) { pObj->fMark0 = Abc_InfoHasBit( pCex->pData, iBit++ ); pObj->fMark1 = 1; pObj->Value = ~0; } iBit += Gia_ManRegNum(p); // transfer Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) { pObjRo->fMark0 = pObjRi->fMark0; pObjRo->fMark1 = pObjRi->fMark1; pObjRo->Value = pObjRi->Value; } // internal nodes Gia_ManForEachAnd( p, pObj, k ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 && !fCompl1 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; else if ( !fCompl1 ) pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1; else assert( 0 ); pObj->Value = ~0; if ( pObj->fMark1 ) continue; if ( pObj->fMark0 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 && !fCompl1 ) pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else if ( !fCompl1 ) pObj->Value = Gia_ObjFanin1(pObj)->Value; else assert( 0 ); assert( pObj->Value > 0 ); } // combinational outputs Gia_ManForEachCo( p, pObj, k ) { pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; pObj->Value = Gia_ObjFanin0(pObj)->Value; } } Gia_ManHashStop( pNew ); assert( iBit == pCex->nBits ); // create primary output pObj = Gia_ManPo(p, pCex->iPo); assert( pObj->fMark0 == 1 ); assert( pObj->fMark1 == 0 ); assert( pObj->Value > 0 ); Gia_ManAppendCo( pNew, pObj->Value ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Bmc_CexBuildNetwork2_( Gia_Man_t * p, Abc_Cex_t * pCex, int fStart ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int fCompl0, fCompl1; int i, k, iBit; assert( pCex->nRegs == 0 ); assert( pCex->nPis == Gia_ManCiNum(p) ); assert( fStart <= pCex->iFrame ); // start the manager pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( "unate" ); // set const0 Gia_ManConst0(p)->fMark0 = 0; // value Gia_ManConst0(p)->Value = 1; // set init state Gia_ManForEachRi( p, pObj, k ) { pObj->fMark0 = Abc_InfoHasBit( pCex->pData, pCex->nRegs + fStart * Gia_ManCiNum(p) + Gia_ManPiNum(p) + k ); pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), !pObj->fMark0 ); } Gia_ManHashAlloc( pNew ); iBit = pCex->nRegs + fStart * Gia_ManCiNum(p); for ( i = fStart; i <= pCex->iFrame; i++ ) { // primary inputs Gia_ManForEachPi( p, pObj, k ) { pObj->fMark0 = Abc_InfoHasBit( pCex->pData, iBit++ ); pObj->Value = 1; } iBit += Gia_ManRegNum(p); // transfer Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) { pObjRo->fMark0 = pObjRi->fMark0; pObjRo->Value = pObjRi->Value; } // internal nodes Gia_ManForEachAnd( p, pObj, k ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 && !fCompl1 ) pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else if ( !fCompl1 ) pObj->Value = Gia_ObjFanin1(pObj)->Value; else assert( 0 ); } // combinational outputs Gia_ManForEachCo( p, pObj, k ) { pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); pObj->Value = Gia_ObjFanin0(pObj)->Value; } } Gia_ManHashStop( pNew ); assert( iBit == pCex->nBits ); // create primary output pObj = Gia_ManPo(p, pCex->iPo); assert( pObj->fMark0 == 1 ); assert( pObj->Value > 0 ); Gia_ManAppendCo( pNew, pObj->Value ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Bmc_CexBuildNetwork2Test( Gia_Man_t * p, Abc_Cex_t * pCex, int nFramesMax ) { Gia_Man_t * pNew, * pTemp; Vec_Ptr_t * vCones; abctime clk = Abc_Clock(); int i; nFramesMax = Abc_MinInt( nFramesMax, pCex->iFrame ); printf( "Processing CEX in frame %d (max frames %d).\n", pCex->iFrame, nFramesMax ); vCones = Vec_PtrAlloc( nFramesMax ); for ( i = pCex->iFrame; i > pCex->iFrame - nFramesMax; i-- ) { printf( "Frame %5d : ", i ); pNew = Bmc_CexBuildNetwork2_( p, pCex, i ); Gia_ManPrintStats( pNew, NULL ); Vec_PtrPush( vCones, pNew ); } pNew = Gia_ManDupAppendCones( p, (Gia_Man_t **)Vec_PtrArray(vCones), Vec_PtrSize(vCones), 1 ); Gia_AigerWrite( pNew, "miter2.aig", 0, 0 ); //Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk ); Vec_PtrForEachEntry( Gia_Man_t *, vCones, pTemp, i ) Gia_ManStop( pTemp ); Vec_PtrFree( vCones ); printf( "GIA with additional properties is written into \"miter2.aig\".\n" ); // printf( "CE-induced network is written into file \"unate.aig\".\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // Gia_ManStop( pNew ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_CexDepthTest( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames, int fVerbose ) { Gia_Man_t * pNew; abctime clk = Abc_Clock(); Abc_Cex_t * pCexImpl = NULL; Abc_Cex_t * pCexStates = Bmc_CexInnerStates( p, pCex, &pCexImpl, fVerbose ); Abc_Cex_t * pCexCare = Bmc_CexCareBits( p, pCexStates, pCexImpl, NULL, 1, fVerbose ); // Abc_Cex_t * pCexEss, * pCexMin; if ( !Bmc_CexVerify( p, pCex, pCexCare ) ) printf( "Counter-example care-set verification has failed.\n" ); // pCexEss = Bmc_CexEssentialBits( p, pCexStates, pCexCare, fVerbose ); // pCexMin = Bmc_CexCareBits( p, pCexStates, pCexImpl, pCexEss, 0, fVerbose ); // if ( !Bmc_CexVerify( p, pCex, pCexMin ) ) // printf( "Counter-example min-set verification has failed.\n" ); // Bmc_CexDumpStats( p, pCex, pCexCare, pCexEss, pCexMin, Abc_Clock() - clk ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); pNew = Bmc_CexBuildNetwork2Test( p, pCexStates, nFrames ); // Bmc_CexPerformUnrollingTest( p, pCex ); Abc_CexFreeP( &pCexStates ); Abc_CexFreeP( &pCexImpl ); Abc_CexFreeP( &pCexCare ); // Abc_CexFreeP( &pCexEss ); // Abc_CexFreeP( &pCexMin ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcCexMin1.c000066400000000000000000000467411300674244400234720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcCexMin1.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [CEX minimization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcCexMin1.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig/ioa/ioa.h" #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the roots to begin traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCexMinGetCos( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Int_t * vLeaves, Vec_Int_t * vRoots ) { Aig_Obj_t * pObj; int i; Vec_IntClear( vRoots ); if ( vLeaves == NULL ) { pObj = Aig_ManCo( pAig, pCex->iPo ); Vec_IntPush( vRoots, Aig_ObjId(pObj) ); return; } Aig_ManForEachObjVec( vLeaves, pAig, pObj, i ) if ( Saig_ObjIsLo(pAig, pObj) ) Vec_IntPush( vRoots, Aig_ObjId( Saig_ObjLoToLi(pAig, pObj) ) ); } /**Function************************************************************* Synopsis [Collects CI of the given timeframe.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCexMinCollectFrameTerms_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vFrameCisOne ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsCo(pObj) ) Saig_ManCexMinCollectFrameTerms_rec( pAig, Aig_ObjFanin0(pObj), vFrameCisOne ); else if ( Aig_ObjIsNode(pObj) ) { Saig_ManCexMinCollectFrameTerms_rec( pAig, Aig_ObjFanin0(pObj), vFrameCisOne ); Saig_ManCexMinCollectFrameTerms_rec( pAig, Aig_ObjFanin1(pObj), vFrameCisOne ); } else if ( Aig_ObjIsCi(pObj) ) Vec_IntPush( vFrameCisOne, Aig_ObjId(pObj) ); } /**Function************************************************************* Synopsis [Collects CIs of all timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_ManCexMinCollectFrameTerms( Aig_Man_t * pAig, Abc_Cex_t * pCex ) { Vec_Vec_t * vFrameCis; Vec_Int_t * vRoots, * vLeaves; Aig_Obj_t * pObj; int i, f; // create terminals vRoots = Vec_IntAlloc( 1000 ); vFrameCis = Vec_VecStart( pCex->iFrame+1 ); for ( f = pCex->iFrame; f >= 0; f-- ) { // create roots vLeaves = (f == pCex->iFrame) ? NULL : Vec_VecEntryInt(vFrameCis, f+1); Saig_ManCexMinGetCos( pAig, pCex, vLeaves, vRoots ); // collect nodes starting from the roots Aig_ManIncrementTravId( pAig ); Aig_ManForEachObjVec( vRoots, pAig, pObj, i ) Saig_ManCexMinCollectFrameTerms_rec( pAig, pObj, Vec_VecEntryInt(vFrameCis, f) ); } Vec_IntFree( vRoots ); return vFrameCis; } /**Function************************************************************* Synopsis [Recursively sets phase and priority.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCexMinDerivePhasePriority_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsCo(pObj) ) { Saig_ManCexMinDerivePhasePriority_rec( pAig, Aig_ObjFanin0(pObj) ); assert( Aig_ObjFanin0(pObj)->iData >= 0 ); pObj->iData = Aig_ObjFanin0(pObj)->iData ^ Aig_ObjFaninC0(pObj); } else if ( Aig_ObjIsNode(pObj) ) { int fPhase0, fPhase1, iPrio0, iPrio1; Saig_ManCexMinDerivePhasePriority_rec( pAig, Aig_ObjFanin0(pObj) ); Saig_ManCexMinDerivePhasePriority_rec( pAig, Aig_ObjFanin1(pObj) ); assert( Aig_ObjFanin0(pObj)->iData >= 0 ); assert( Aig_ObjFanin1(pObj)->iData >= 0 ); fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); iPrio0 = Abc_Lit2Var( Aig_ObjFanin0(pObj)->iData ); iPrio1 = Abc_Lit2Var( Aig_ObjFanin1(pObj)->iData ); if ( fPhase0 && fPhase1 ) // both are one pObj->iData = Abc_Var2Lit( Abc_MinInt(iPrio0, iPrio1), 1 ); else if ( !fPhase0 && fPhase1 ) pObj->iData = Abc_Var2Lit( iPrio0, 0 ); else if ( fPhase0 && !fPhase1 ) pObj->iData = Abc_Var2Lit( iPrio1, 0 ); else // both are zero pObj->iData = Abc_Var2Lit( Abc_MaxInt(iPrio0, iPrio1), 0 ); } } /**Function************************************************************* Synopsis [Verify phase.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCexMinVerifyPhase( Aig_Man_t * pAig, Abc_Cex_t * pCex, int f ) { Aig_Obj_t * pObj; int i; Aig_ManConst1(pAig)->fPhase = 1; Saig_ManForEachPi( pAig, pObj, i ) pObj->fPhase = Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + i); if ( f == 0 ) { Saig_ManForEachLo( pAig, pObj, i ) pObj->fPhase = 0; } else { Saig_ManForEachLo( pAig, pObj, i ) pObj->fPhase = Saig_ObjLoToLi(pAig, pObj)->fPhase; } Aig_ManForEachNode( pAig, pObj, i ) pObj->fPhase = (Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase) & (Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase); Aig_ManForEachCo( pAig, pObj, i ) pObj->fPhase = (Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase); } /**Function************************************************************* Synopsis [Collects phase and priority of all timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCexMinDerivePhasePriority( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Vec_t * vFrameCis, Vec_Vec_t * vFramePPs, int f, Vec_Int_t * vRoots ) { Vec_Int_t * vFramePPsOne, * vFrameCisOne, * vLeaves; Aig_Obj_t * pObj; int i; // set PP for the CIs vFrameCisOne = Vec_VecEntryInt( vFrameCis, f ); vFramePPsOne = Vec_VecEntryInt( vFramePPs, f ); Aig_ManForEachObjVec( vFrameCisOne, pAig, pObj, i ) { pObj->iData = Vec_IntEntry( vFramePPsOne, i ); assert( pObj->iData >= 0 ); } // if ( f == 0 ) // Saig_ManCexMinVerifyPhase( pAig, pCex, f ); // create roots vLeaves = (f == pCex->iFrame) ? NULL : Vec_VecEntryInt(vFrameCis, f+1); Saig_ManCexMinGetCos( pAig, pCex, vLeaves, vRoots ); // derive for the nodes starting from the roots Aig_ManIncrementTravId( pAig ); Aig_ManForEachObjVec( vRoots, pAig, pObj, i ) { Saig_ManCexMinDerivePhasePriority_rec( pAig, pObj ); // if ( f == 0 ) // assert( (pObj->iData & 1) == pObj->fPhase ); } } /**Function************************************************************* Synopsis [Collects phase and priority of all timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_ManCexMinCollectPhasePriority_( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Vec_t * vFrameCis ) { Vec_Vec_t * vFramePPs; Vec_Int_t * vRoots, * vFramePPsOne, * vFrameCisOne; Aig_Obj_t * pObj; int i, f, nPrioOffset; // initialize phase and priority Aig_ManForEachObj( pAig, pObj, i ) pObj->iData = -1; // set the constant node to higher priority than the flops vFramePPs = Vec_VecStart( pCex->iFrame+1 ); nPrioOffset = (pCex->iFrame + 1) * pCex->nPis; Aig_ManConst1(pAig)->iData = Abc_Var2Lit( nPrioOffset + pCex->nRegs, 1 ); vRoots = Vec_IntAlloc( 1000 ); for ( f = 0; f <= pCex->iFrame; f++ ) { int nPiCount = 0; // fill in PP for the CIs vFrameCisOne = Vec_VecEntryInt( vFrameCis, f ); vFramePPsOne = Vec_VecEntryInt( vFramePPs, f ); assert( Vec_IntSize(vFramePPsOne) == 0 ); Aig_ManForEachObjVec( vFrameCisOne, pAig, pObj, i ) { assert( Aig_ObjIsCi(pObj) ); if ( Saig_ObjIsPi(pAig, pObj) ) Vec_IntPush( vFramePPsOne, Abc_Var2Lit( (f+1) * pCex->nPis - nPiCount++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj)) ) ); else if ( f == 0 ) Vec_IntPush( vFramePPsOne, Abc_Var2Lit( nPrioOffset + Saig_ObjRegId(pAig, pObj), 0 ) ); else Vec_IntPush( vFramePPsOne, Saig_ObjLoToLi(pAig, pObj)->iData ); } // compute the PP info Saig_ManCexMinDerivePhasePriority( pAig, pCex, vFrameCis, vFramePPs, f, vRoots ); } Vec_IntFree( vRoots ); // check the output pObj = Aig_ManCo( pAig, pCex->iPo ); assert( Abc_LitIsCompl(pObj->iData) ); return vFramePPs; } /**Function************************************************************* Synopsis [Collects phase and priority of all timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_ManCexMinCollectPhasePriority( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Vec_t * vFrameCis ) { Vec_Vec_t * vFramePPs; Vec_Int_t * vRoots, * vFramePPsOne, * vFrameCisOne; Aig_Obj_t * pObj; int i, f, nPrioOffset; // initialize phase and priority Aig_ManForEachObj( pAig, pObj, i ) pObj->iData = -1; // set the constant node to higher priority than the flops vFramePPs = Vec_VecStart( pCex->iFrame+1 ); nPrioOffset = pCex->nRegs; Aig_ManConst1(pAig)->iData = Abc_Var2Lit( nPrioOffset + (pCex->iFrame + 1) * pCex->nPis, 1 ); vRoots = Vec_IntAlloc( 1000 ); for ( f = 0; f <= pCex->iFrame; f++ ) { int nPiCount = 0; // fill in PP for the CIs vFrameCisOne = Vec_VecEntryInt( vFrameCis, f ); vFramePPsOne = Vec_VecEntryInt( vFramePPs, f ); assert( Vec_IntSize(vFramePPsOne) == 0 ); Aig_ManForEachObjVec( vFrameCisOne, pAig, pObj, i ) { assert( Aig_ObjIsCi(pObj) ); if ( Saig_ObjIsPi(pAig, pObj) ) Vec_IntPush( vFramePPsOne, Abc_Var2Lit( nPrioOffset + (f+1) * pCex->nPis - 1 - nPiCount++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj)) ) ); else if ( f == 0 ) Vec_IntPush( vFramePPsOne, Abc_Var2Lit( Saig_ObjRegId(pAig, pObj), 0 ) ); else Vec_IntPush( vFramePPsOne, Saig_ObjLoToLi(pAig, pObj)->iData ); } // compute the PP info Saig_ManCexMinDerivePhasePriority( pAig, pCex, vFrameCis, vFramePPs, f, vRoots ); } Vec_IntFree( vRoots ); // check the output pObj = Aig_ManCo( pAig, pCex->iPo ); assert( Abc_LitIsCompl(pObj->iData) ); return vFramePPs; } /**Function************************************************************* Synopsis [Returns reasons for the property to fail.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCexMinCollectReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vReason, int fPiReason ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsCi(pObj) ) { if ( fPiReason && Saig_ObjIsPi(p, pObj) ) Vec_IntPush( vReason, Abc_Var2Lit( Aig_ObjCioId(pObj), !Abc_LitIsCompl(pObj->iData) ) ); else if ( !fPiReason && Saig_ObjIsLo(p, pObj) ) Vec_IntPush( vReason, Abc_Var2Lit( Saig_ObjRegId(p, pObj), !Abc_LitIsCompl(pObj->iData) ) ); return; } if ( Aig_ObjIsCo(pObj) ) { Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason ); return; } if ( Aig_ObjIsConst1(pObj) ) return; assert( Aig_ObjIsNode(pObj) ); if ( Abc_LitIsCompl(pObj->iData) ) // value 1 { int fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); int fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); assert( fPhase0 && fPhase1 ); Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason ); Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin1(pObj), vReason, fPiReason ); } else { int fPhase0 = Abc_LitIsCompl( Aig_ObjFanin0(pObj)->iData ) ^ Aig_ObjFaninC0(pObj); int fPhase1 = Abc_LitIsCompl( Aig_ObjFanin1(pObj)->iData ) ^ Aig_ObjFaninC1(pObj); assert( !fPhase0 || !fPhase1 ); if ( !fPhase0 && fPhase1 ) Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason ); else if ( fPhase0 && !fPhase1 ) Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin1(pObj), vReason, fPiReason ); else { int iPrio0 = Abc_Lit2Var( Aig_ObjFanin0(pObj)->iData ); int iPrio1 = Abc_Lit2Var( Aig_ObjFanin1(pObj)->iData ); if ( iPrio0 >= iPrio1 ) Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin0(pObj), vReason, fPiReason ); else Saig_ManCexMinCollectReason_rec( p, Aig_ObjFanin1(pObj), vReason, fPiReason ); } } } /**Function************************************************************* Synopsis [Collects phase and priority of all timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_ManCexMinCollectReason( Aig_Man_t * pAig, Abc_Cex_t * pCex, Vec_Vec_t * vFrameCis, Vec_Vec_t * vFramePPs, int fPiReason ) { Vec_Vec_t * vFrameReas; Vec_Int_t * vRoots, * vLeaves; Aig_Obj_t * pObj; int i, f; // select reason for the property to fail vFrameReas = Vec_VecStart( pCex->iFrame+1 ); vRoots = Vec_IntAlloc( 1000 ); for ( f = pCex->iFrame; f >= 0; f-- ) { // set phase and polarity Saig_ManCexMinDerivePhasePriority( pAig, pCex, vFrameCis, vFramePPs, f, vRoots ); // create roots vLeaves = (f == pCex->iFrame) ? NULL : Vec_VecEntryInt(vFrameCis, f+1); Saig_ManCexMinGetCos( pAig, pCex, vLeaves, vRoots ); // collect nodes starting from the roots Aig_ManIncrementTravId( pAig ); Aig_ManForEachObjVec( vRoots, pAig, pObj, i ) Saig_ManCexMinCollectReason_rec( pAig, pObj, Vec_VecEntryInt(vFrameReas, f), fPiReason ); //printf( "%d(%d) ", Vec_VecLevelSize(vFrameCis, f), Vec_VecLevelSize(vFrameReas, f) ); } //printf( "\n" ); Vec_IntFree( vRoots ); return vFrameReas; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_ManCexMinComputeReason( Aig_Man_t * pAig, Abc_Cex_t * pCex, int fPiReason ) { Vec_Vec_t * vFrameCis, * vFramePPs, * vFrameReas; // sanity checks assert( pCex->nPis == Saig_ManPiNum(pAig) ); assert( pCex->nRegs == Saig_ManRegNum(pAig) ); assert( pCex->iPo >= 0 && pCex->iPo < Saig_ManPoNum(pAig) ); // derive frame terms vFrameCis = Saig_ManCexMinCollectFrameTerms( pAig, pCex ); // derive phase and priority vFramePPs = Saig_ManCexMinCollectPhasePriority( pAig, pCex, vFrameCis ); // derive reasons for property failure vFrameReas = Saig_ManCexMinCollectReason( pAig, pCex, vFrameCis, vFramePPs, fPiReason ); Vec_VecFree( vFramePPs ); Vec_VecFree( vFrameCis ); return vFrameReas; } /**Function************************************************************* Synopsis [Duplicate with literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManCexMinDupWithCubes( Aig_Man_t * pAig, Vec_Vec_t * vReg2Value ) { Vec_Int_t * vLevel; Aig_Man_t * pAigNew; Aig_Obj_t * pObj, * pMiter; int i, k, Lit; assert( pAig->nConstrs == 0 ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) + Vec_VecSizeSize(vReg2Value) + Vec_VecSize(vReg2Value) ); 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) ); // create POs for cubes Vec_VecForEachLevelInt( vReg2Value, vLevel, i ) { if ( i == 0 ) continue; pMiter = Aig_ManConst1( pAigNew ); Vec_IntForEachEntry( vLevel, Lit, k ) { assert( Lit >= 0 && Lit < 2 * Aig_ManRegNum(pAig) ); pObj = Saig_ManLi( pAig, Abc_Lit2Var(Lit) ); pMiter = Aig_And( pAigNew, pMiter, Aig_NotCond(Aig_ObjChild0Copy(pObj), Abc_LitIsCompl(Lit)) ); } Aig_ObjCreateCo( pAigNew, pMiter ); } // transfer to register outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // finalize Aig_ManCleanup( pAigNew ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); return pAigNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_ManCexMinPerform( Aig_Man_t * pAig, Abc_Cex_t * pCex ) { int fReasonPi = 0; Abc_Cex_t * pCexMin = NULL; Aig_Man_t * pManNew = NULL; Vec_Vec_t * vFrameReas; vFrameReas = Saig_ManCexMinComputeReason( pAig, pCex, fReasonPi ); printf( "Reason size = %d. Ave = %d.\n", Vec_VecSizeSize(vFrameReas), Vec_VecSizeSize(vFrameReas)/(pCex->iFrame + 1) ); // try reducing the frames if ( !fReasonPi ) { char * pFileName = "aigcube.aig"; pManNew = Saig_ManCexMinDupWithCubes( pAig, vFrameReas ); Ioa_WriteAiger( pManNew, pFileName, 0, 0 ); Aig_ManStop( pManNew ); printf( "Intermediate AIG is written into file \"%s\".\n", pFileName ); } // find reduced counter-example Vec_VecFree( vFrameReas ); return pCexMin; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcCexMin2.c000066400000000000000000000326261300674244400234700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcCexMin2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [CEX minimization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcCexMin2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig/gia/gia.h" #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Abc_InfoGet2Bits( Vec_Int_t * vData, int nWords, int iFrame, int iObj ) { unsigned * pInfo = (unsigned *)Vec_IntEntryP( vData, nWords * iFrame ); return 3 & (pInfo[iObj >> 4] >> ((iObj & 15) << 1)); } static inline void Abc_InfoSet2Bits( Vec_Int_t * vData, int nWords, int iFrame, int iObj, int Value ) { unsigned * pInfo = (unsigned *)Vec_IntEntryP( vData, nWords * iFrame ); Value ^= (3 & (pInfo[iObj >> 4] >> ((iObj & 15) << 1))); pInfo[iObj >> 4] ^= (Value << ((iObj & 15) << 1)); } static inline void Abc_InfoAdd2Bits( Vec_Int_t * vData, int nWords, int iFrame, int iObj, int Value ) { unsigned * pInfo = (unsigned *)Vec_IntEntryP( vData, nWords * iFrame ); pInfo[iObj >> 4] |= (Value << ((iObj & 15) << 1)); } static inline int Gia_ManGetTwo( Gia_Man_t * p, int iFrame, Gia_Obj_t * pObj ) { return Abc_InfoGet2Bits( p->vTruths, p->nTtWords, iFrame, Gia_ObjId(p, pObj) ); } static inline void Gia_ManSetTwo( Gia_Man_t * p, int iFrame, Gia_Obj_t * pObj, int Value ) { Abc_InfoSet2Bits( p->vTruths, p->nTtWords, iFrame, Gia_ObjId(p, pObj), Value ); } static inline void Gia_ManAddTwo( Gia_Man_t * p, int iFrame, Gia_Obj_t * pObj, int Value ) { Abc_InfoAdd2Bits( p->vTruths, p->nTtWords, iFrame, Gia_ObjId(p, pObj), Value ); } /* For CEX minimization, all terminals (const0, PI, RO in frame0) have equal priority. For abstraction refinement, all terminals, except PPis, have higher priority. */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Annotates the unrolling with CEX value/priority.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAnnotateUnrolling( Gia_Man_t * p, Abc_Cex_t * pCex, int fJustMax ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, f, k, Value, Value0, Value1, iBit; // start storage for internal info assert( p->vTruths == NULL ); p->nTtWords = Abc_BitWordNum( 2 * Gia_ManObjNum(p) ); p->vTruths = Vec_IntStart( (pCex->iFrame + 1) * p->nTtWords ); // assign values to all objects (const0 and RO in frame0 are assigned 0) Gia_ManCleanMark0(p); for ( f = 0, iBit = pCex->nRegs; f <= pCex->iFrame; f++ ) { Gia_ManForEachPi( p, pObj, k ) if ( (pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++)) ) Gia_ManAddTwo( p, f, pObj, 1 ); Gia_ManForEachAnd( p, pObj, k ) if ( (pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj))) ) Gia_ManAddTwo( p, f, pObj, 1 ); Gia_ManForEachCo( p, pObj, k ) if ( (pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) ) Gia_ManAddTwo( p, f, pObj, 1 ); if ( f == pCex->iFrame ) break; Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) if ( (pObjRo->fMark0 = pObjRi->fMark0) ) Gia_ManAddTwo( p, f+1, pObjRo, 1 ); } assert( iBit == pCex->nBits ); // check the output value RetValue = Gia_ManPo(p, pCex->iPo)->fMark0; if ( RetValue != 1 ) printf( "Counter-example is invalid.\n" ); // assign justification to nodes Gia_ManCleanMark0(p); pObj = Gia_ManPo(p, pCex->iPo); pObj->fMark0 = 1; Gia_ManAddTwo( p, pCex->iFrame, pObj, 2 ); for ( f = pCex->iFrame; f >= 0; f-- ) { // transfer to CO drivers Gia_ManForEachCo( p, pObj, k ) if ( (Gia_ObjFanin0(pObj)->fMark0 = pObj->fMark0) ) { pObj->fMark0 = 0; Gia_ManAddTwo( p, f, Gia_ObjFanin0(pObj), 2 ); } // compute justification Gia_ManForEachAndReverse( p, pObj, k ) { if ( !pObj->fMark0 ) continue; pObj->fMark0 = 0; Value = (1 & Gia_ManGetTwo(p, f, pObj)); Value0 = (1 & Gia_ManGetTwo(p, f, Gia_ObjFanin0(pObj))) ^ Gia_ObjFaninC0(pObj); Value1 = (1 & Gia_ManGetTwo(p, f, Gia_ObjFanin1(pObj))) ^ Gia_ObjFaninC1(pObj); if ( Value0 == Value1 ) { assert( Value == (Value0 & Value1) ); if ( fJustMax || Value == 1 ) { Gia_ObjFanin0(pObj)->fMark0 = Gia_ObjFanin1(pObj)->fMark0 = 1; Gia_ManAddTwo( p, f, Gia_ObjFanin0(pObj), 2 ); Gia_ManAddTwo( p, f, Gia_ObjFanin1(pObj), 2 ); } else { Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ManAddTwo( p, f, Gia_ObjFanin0(pObj), 2 ); } } else if ( Value0 == 0 ) { assert( Value == 0 ); Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ManAddTwo( p, f, Gia_ObjFanin0(pObj), 2 ); } else if ( Value1 == 0 ) { assert( Value == 0 ); Gia_ObjFanin1(pObj)->fMark0 = 1; Gia_ManAddTwo( p, f, Gia_ObjFanin1(pObj), 2 ); } else assert( 0 ); } if ( f == 0 ) break; // transfer to RIs Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = 0; Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) if ( (pObjRi->fMark0 = pObjRo->fMark0) ) { pObjRo->fMark0 = 0; Gia_ManAddTwo( p, f-1, pObjRi, 2 ); } } Gia_ManCleanMark0(p); return RetValue; } /**Function************************************************************* Synopsis [Computing AIG characterizing all justifying assignments.] Description [Used in CEX minimization.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCreateUnate( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrame, int nRealPis, int fUseAllObjects ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int f, k, Value; assert( iFrame >= 0 && iFrame <= pCex->iFrame ); pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( "unate" ); Gia_ManCleanValue( p ); // set flop outputs if ( nRealPis < 0 ) // CEX min { Gia_ManForEachRo( p, pObj, k ) { if ( fUseAllObjects ) { int Value = Gia_ManAppendCi(pNew); if ( (Gia_ManGetTwo(p, iFrame, pObj) >> 1) ) // in the path pObj->Value = Value; } else if ( (Gia_ManGetTwo(p, iFrame, pObj) >> 1) ) // in the path pObj->Value = Gia_ManAppendCi(pNew); } } else { Gia_ManForEachRo( p, pObj, k ) pObj->Value = (Gia_ManGetTwo(p, iFrame, pObj) >> 1); } Gia_ManHashAlloc( pNew ); for ( f = iFrame; f <= pCex->iFrame; f++ ) { /* printf( " F%03d ", f ); Gia_ManForEachRo( p, pObj, k ) printf( "%d", pObj->Value > 0 ); printf( "\n" ); */ // set const0 to const1 if present pObj = Gia_ManConst0(p); pObj->Value = (Gia_ManGetTwo(p, f, pObj) >> 1); // set primary inputs if ( nRealPis < 0 ) // CEX min { Gia_ManForEachPi( p, pObj, k ) pObj->Value = (Gia_ManGetTwo(p, f, pObj) >> 1); } else { Gia_ManForEachPi( p, pObj, k ) { pObj->Value = (Gia_ManGetTwo(p, f, pObj) >> 1); if ( k >= nRealPis ) { if ( fUseAllObjects ) { int Value = Gia_ManAppendCi(pNew); if ( (Gia_ManGetTwo(p, f, pObj) >> 1) ) // in the path pObj->Value = Value; } else if ( (Gia_ManGetTwo(p, f, pObj) >> 1) ) // in the path pObj->Value = Gia_ManAppendCi(pNew); } } } // traverse internal nodes Gia_ManForEachAnd( p, pObj, k ) { pObj->Value = 0; Value = Gia_ManGetTwo(p, f, pObj); if ( !(Value >> 1) ) // not in the path continue; if ( Gia_ObjFanin0(pObj)->Value && Gia_ObjFanin1(pObj)->Value ) { if ( 1 & Gia_ManGetTwo(p, f, pObj) ) // value 1 { if ( Gia_ObjFanin0(pObj)->Value > 1 && Gia_ObjFanin1(pObj)->Value > 1 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( Gia_ObjFanin0(pObj)->Value > 1 ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else if ( Gia_ObjFanin1(pObj)->Value > 1 ) pObj->Value = Gia_ObjFanin1(pObj)->Value; else pObj->Value = 1; } else // value 0 { if ( Gia_ObjFanin0(pObj)->Value > 1 && Gia_ObjFanin1(pObj)->Value > 1 ) pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( Gia_ObjFanin0(pObj)->Value > 1 ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else if ( Gia_ObjFanin1(pObj)->Value > 1 ) pObj->Value = Gia_ObjFanin1(pObj)->Value; else pObj->Value = 1; } } else if ( Gia_ObjFanin0(pObj)->Value ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else if ( Gia_ObjFanin1(pObj)->Value ) pObj->Value = Gia_ObjFanin1(pObj)->Value; else assert( 0 ); } Gia_ManForEachCo( p, pObj, k ) pObj->Value = Gia_ObjFanin0(pObj)->Value; if ( f == pCex->iFrame ) break; Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) pObjRo->Value = pObjRi->Value; } Gia_ManHashStop( pNew ); // create primary output pObj = Gia_ManPo(p, pCex->iPo); assert( (Gia_ManGetTwo(p, pCex->iFrame, pObj) >> 1) ); assert( pObj->Value ); Gia_ManAppendCo( pNew, pObj->Value ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gia_ManCexMin( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrameStart, int nRealPis, int fJustMax, int fUseAll, int fVerbose ) { Gia_Man_t * pNew; int f, RetValue; // check CEX assert( pCex->nPis == Gia_ManPiNum(p) ); // assert( pCex->nRegs == Gia_ManRegNum(p) ); assert( pCex->iPo < Gia_ManPoNum(p) ); // check frames assert( iFrameStart >= 0 && iFrameStart <= pCex->iFrame ); // check primary inputs assert( nRealPis < Gia_ManPiNum(p) ); // prepare RetValue = Gia_ManAnnotateUnrolling( p, pCex, fJustMax ); if ( nRealPis >= 0 ) // refinement { pNew = Gia_ManCreateUnate( p, pCex, iFrameStart, nRealPis, fUseAll ); printf( "%3d : ", iFrameStart ); Gia_ManPrintStats( pNew, NULL ); if ( fVerbose ) Gia_AigerWrite( pNew, "temp.aig", 0, 0 ); Gia_ManStop( pNew ); } else // CEX min { for ( f = pCex->iFrame; f >= iFrameStart; f-- ) { pNew = Gia_ManCreateUnate( p, pCex, f, -1, fUseAll ); printf( "%3d : ", f ); Gia_ManPrintStats( pNew, NULL ); if ( fVerbose ) Gia_AigerWrite( pNew, "temp.aig", 0, 0 ); Gia_ManStop( pNew ); } } Vec_IntFreeP( &p->vTruths ); p->nTtWords = 0; return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcCexTools.c000066400000000000000000000712021300674244400237540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcCexTools.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [CEX analysis and optimization toolbox.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcCexTools.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline word Bmc_CexBitMask( int iBit ) { assert( iBit < 64 ); return ~(((word)1) << iBit); } static inline void Bmc_CexCopySim( Vec_Wrd_t * vSims, int iObjTo, int iObjFrom ) { Vec_WrdWriteEntry( vSims, iObjTo, iObjFrom ); } static inline void Bmc_CexAndSim( Vec_Wrd_t * vSims, int iObjTo, int i, int j ) { Vec_WrdWriteEntry( vSims, iObjTo, Vec_WrdEntry(vSims, i) & Vec_WrdEntry(vSims, j) ); } static inline void Bmc_CexOrSim( Vec_Wrd_t * vSims, int iObjTo, int i, int j ) { Vec_WrdWriteEntry( vSims, iObjTo, Vec_WrdEntry(vSims, i) | Vec_WrdEntry(vSims, j) ); } static inline int Bmc_CexSim( Vec_Wrd_t * vSims, int iObj, int i ) { return (Vec_WrdEntry(vSims, iObj) >> i) & 1; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CexBitCount( Abc_Cex_t * p, int nInputs ) { int k, Counter = 0, Counter2 = 0; if ( p == NULL ) { printf( "The counter example is NULL.\n" ); return -1; } for ( k = 0; k < p->nBits; k++ ) { Counter += Abc_InfoHasBit(p->pData, k); if ( (k - p->nRegs) % p->nPis < nInputs ) Counter2 += Abc_InfoHasBit(p->pData, k); } return Counter2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_CexDumpStats( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare, Abc_Cex_t * pCexEss, Abc_Cex_t * pCexMin, abctime clk ) { int nInputs = Gia_ManPiNum(p); int nBitsTotal = (pCex->iFrame + 1) * nInputs; int nBitsCare = Bmc_CexBitCount(pCexCare, nInputs); int nBitsDC = nBitsTotal - nBitsCare; int nBitsEss = Bmc_CexBitCount(pCexEss, nInputs); int nBitsOpt = nBitsCare - nBitsEss; int nBitsMin = Bmc_CexBitCount(pCexMin, nInputs); FILE * pTable = fopen( "cex/stats.txt", "a+" ); fprintf( pTable, "%s ", p->pName ); fprintf( pTable, "%d ", nInputs ); fprintf( pTable, "%d ", Gia_ManRegNum(p) ); fprintf( pTable, "%d ", pCex->iFrame + 1 ); fprintf( pTable, "%d ", nBitsTotal ); fprintf( pTable, "%.2f ", 100.0 * nBitsDC / nBitsTotal ); fprintf( pTable, "%.2f ", 100.0 * nBitsOpt / nBitsTotal ); fprintf( pTable, "%.2f ", 100.0 * nBitsEss / nBitsTotal ); fprintf( pTable, "%.2f ", 100.0 * nBitsMin / nBitsTotal ); fprintf( pTable, "%.2f ", 1.0*clk/(CLOCKS_PER_SEC) ); fprintf( pTable, "\n" ); fclose( pTable ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_CexDumpAogStats( Gia_Man_t * p, abctime clk ) { FILE * pTable = fopen( "cex/aig_stats.txt", "a+" ); fprintf( pTable, "%s ", p->pName ); fprintf( pTable, "%d ", Gia_ManPiNum(p) ); fprintf( pTable, "%d ", Gia_ManAndNum(p) ); fprintf( pTable, "%d ", Gia_ManLevelNum(p) ); fprintf( pTable, "%.2f ", 1.0*clk/(CLOCKS_PER_SEC) ); fprintf( pTable, "\n" ); fclose( pTable ); } /**Function************************************************************* Synopsis [Performs initialized unrolling till the last frame.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_CexPerformUnrolling( Gia_Man_t * p, Abc_Cex_t * pCex ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int i, k; assert( Gia_ManRegNum(p) > 0 ); pNew = Gia_ManStart( (pCex->iFrame + 1) * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachRi( p, pObj, k ) pObj->Value = 0; Gia_ManHashAlloc( pNew ); for ( i = 0; i <= pCex->iFrame; i++ ) { Gia_ManForEachPi( p, pObj, k ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) pObjRo->Value = pObjRi->Value; Gia_ManForEachAnd( p, pObj, k ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, k ) pObj->Value = Gia_ObjFanin0Copy(pObj); } Gia_ManHashStop( pNew ); pObj = Gia_ManPo(p, pCex->iPo); Gia_ManAppendCo( pNew, pObj->Value ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } void Bmc_CexPerformUnrollingTest( Gia_Man_t * p, Abc_Cex_t * pCex ) { Gia_Man_t * pNew; abctime clk = Abc_Clock(); pNew = Bmc_CexPerformUnrolling( p, pCex ); Gia_ManPrintStats( pNew, NULL ); Gia_AigerWrite( pNew, "unroll.aig", 0, 0 ); //Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk ); Gia_ManStop( pNew ); printf( "CE-induced network is written into file \"unroll.aig\".\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Computes CE-induced network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_CexBuildNetwork( Gia_Man_t * p, Abc_Cex_t * pCex ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int fCompl0, fCompl1; int i, k, iBit = pCex->nRegs; // start the manager pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( "unate" ); // set const0 Gia_ManConst0(p)->fMark0 = 0; Gia_ManConst0(p)->fMark1 = 1; Gia_ManConst0(p)->Value = ~0; // set init state Gia_ManForEachRi( p, pObj, k ) { pObj->fMark0 = 0; pObj->fMark1 = 1; pObj->Value = ~0; } Gia_ManHashAlloc( pNew ); for ( i = 0; i <= pCex->iFrame; i++ ) { // primary inputs Gia_ManForEachPi( p, pObj, k ) { pObj->fMark0 = Abc_InfoHasBit( pCex->pData, iBit++ ); pObj->fMark1 = 0; pObj->Value = Gia_ManAppendCi(pNew); } // transfer Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) { pObjRo->fMark0 = pObjRi->fMark0; pObjRo->fMark1 = pObjRi->fMark1; pObjRo->Value = pObjRi->Value; } // internal nodes Gia_ManForEachAnd( p, pObj, k ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 && !fCompl1 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; else if ( !fCompl1 ) pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1; else assert( 0 ); pObj->Value = ~0; if ( pObj->fMark1 ) continue; if ( pObj->fMark0 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 && !fCompl1 ) pObj->Value = Gia_ManHashOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); else if ( !fCompl0 ) pObj->Value = Gia_ObjFanin0(pObj)->Value; else if ( !fCompl1 ) pObj->Value = Gia_ObjFanin1(pObj)->Value; else assert( 0 ); assert( pObj->Value > 0 ); } // combinational outputs Gia_ManForEachCo( p, pObj, k ) { pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; pObj->Value = Gia_ObjFanin0(pObj)->Value; } } Gia_ManHashStop( pNew ); assert( iBit == pCex->nBits ); // create primary output pObj = Gia_ManPo(p, pCex->iPo); assert( pObj->fMark0 == 1 ); assert( pObj->fMark1 == 0 ); assert( pObj->Value > 0 ); Gia_ManAppendCo( pNew, pObj->Value ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } void Bmc_CexBuildNetworkTest( Gia_Man_t * p, Abc_Cex_t * pCex ) { Gia_Man_t * pNew; abctime clk = Abc_Clock(); pNew = Bmc_CexBuildNetwork( p, pCex ); Gia_ManPrintStats( pNew, NULL ); Gia_AigerWrite( pNew, "unate.aig", 0, 0 ); //Bmc_CexDumpAogStats( pNew, Abc_Clock() - clk ); Gia_ManStop( pNew ); printf( "CE-induced network is written into file \"unate.aig\".\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Prints one counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose ) { int i, k, Count, iBit = pCex->nRegs; Abc_CexPrintStatsInputs( pCex, nInputs ); if ( !fVerbose ) return; for ( i = 0; i <= pCex->iFrame; i++ ) { Count = 0; printf( "%3d : ", i ); for ( k = 0; k < nInputs; k++ ) { Count += Abc_InfoHasBit(pCex->pData, iBit); printf( "%d", Abc_InfoHasBit(pCex->pData, iBit++) ); } printf( " %3d ", Count ); Count = 0; for ( ; k < pCex->nPis; k++ ) { Count += Abc_InfoHasBit(pCex->pData, iBit); printf( "%d", Abc_InfoHasBit(pCex->pData, iBit++) ); } printf( " %3d\n", Count ); } assert( iBit == pCex->nBits ); } /**Function************************************************************* Synopsis [Verifies the care set of the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ) { Gia_Obj_t * pObj; int i, k; // assert( pCex->nRegs > 0 ); // assert( pCexCare->nRegs == 0 ); Gia_ObjTerSimSet0( Gia_ManConst0(p) ); Gia_ManForEachRi( p, pObj, k ) Gia_ObjTerSimSet0( pObj ); for ( i = 0; i <= pCex->iFrame; i++ ) { Gia_ManForEachPi( p, pObj, k ) { if ( !Abc_InfoHasBit( pCexCare->pData, pCexCare->nRegs + i * pCexCare->nPis + k ) ) Gia_ObjTerSimSetX( pObj ); else if ( Abc_InfoHasBit( pCex->pData, pCex->nRegs + i * pCex->nPis + k ) ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSet0( pObj ); } Gia_ManForEachRo( p, pObj, k ) Gia_ObjTerSimRo( p, pObj ); Gia_ManForEachAnd( p, pObj, k ) Gia_ObjTerSimAnd( pObj ); Gia_ManForEachCo( p, pObj, k ) Gia_ObjTerSimCo( pObj ); } pObj = Gia_ManPo( p, pCex->iPo ); return Gia_ObjTerSimGet1(pObj); } /**Function************************************************************* Synopsis [Computes internal states of the CEX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Bmc_CexInnerStates( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t ** ppCexImpl, int fVerbose ) { Abc_Cex_t * pNew, * pNew2; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int fCompl0, fCompl1; 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; // start the counter-example pNew2 = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCex->iFrame + 1 ); pNew2->iFrame = pCex->iFrame; pNew2->iPo = pCex->iPo; // set initial state Gia_ManCleanMark01(p); // set const0 Gia_ManConst0(p)->fMark0 = 0; Gia_ManConst0(p)->fMark1 = 1; // set init state Gia_ManForEachRi( p, pObjRi, k ) { pObjRi->fMark0 = 0; pObjRi->fMark1 = 1; } 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; pObjRo->fMark1 = pObjRi->fMark1; } Gia_ManForEachCi( p, pObj, k ) { if ( pObj->fMark0 ) Abc_InfoSetBit( pNew->pData, pNew->nPis * i + k ); if ( pObj->fMark1 ) Abc_InfoSetBit( pNew2->pData, pNew2->nPis * i + k ); } Gia_ManForEachAnd( p, pObj, k ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 && !fCompl1 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; else if ( !fCompl1 ) pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1; else assert( 0 ); } Gia_ManForEachCo( p, pObj, k ) { pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; } /* // print input/state/output printf( "%3d : ", i ); Gia_ManForEachPi( p, pObj, k ) printf( "%d", pObj->fMark0 ); printf( " " ); Gia_ManForEachRo( p, pObj, k ) printf( "%d", pObj->fMark0 ); printf( " " ); Gia_ManForEachPo( p, pObj, k ) printf( "%d", pObj->fMark0 ); printf( "\n" ); */ } assert( iBit == pCex->nBits ); assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 ); printf( "Inner states: " ); Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose ); printf( "Implications: " ); Bmc_CexPrint( pNew2, Gia_ManPiNum(p), fVerbose ); if ( ppCexImpl ) *ppCexImpl = pNew2; else Abc_CexFree( pNew2 ); return pNew; } /**Function************************************************************* Synopsis [Computes care bits of the CEX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_CexCareBits_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { int fCompl0, fCompl1; if ( Gia_ObjIsConst0(pObj) ) return; if ( pObj->fMark1 ) return; pObj->fMark1 = 1; if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); if ( pObj->fMark0 ) { assert( fCompl0 == 1 && fCompl1 == 1 ); Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) ); Bmc_CexCareBits_rec( p, Gia_ObjFanin1(pObj) ); } else { assert( fCompl0 == 0 || fCompl1 == 0 ); if ( fCompl0 == 0 ) Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) ); if ( fCompl1 == 0 ) Bmc_CexCareBits_rec( p, Gia_ObjFanin1(pObj) ); } } void Bmc_CexCareBits2_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { int fCompl0, fCompl1; if ( Gia_ObjIsConst0(pObj) ) return; if ( pObj->fMark1 ) return; pObj->fMark1 = 1; if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); if ( pObj->fMark0 ) { assert( fCompl0 == 1 && fCompl1 == 1 ); Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) ); Bmc_CexCareBits2_rec( p, Gia_ObjFanin1(pObj) ); } else { assert( fCompl0 == 0 || fCompl1 == 0 ); if ( fCompl0 == 0 ) Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) ); /**/ else /**/ if ( fCompl1 == 0 ) Bmc_CexCareBits2_rec( p, Gia_ObjFanin1(pObj) ); } } Abc_Cex_t * Bmc_CexCareBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexImpl, Abc_Cex_t * pCexEss, int fFindAll, int fVerbose ) { Abc_Cex_t * pNew; Gia_Obj_t * pObj; int fCompl0, fCompl1; int i, k, iBit; assert( pCexState->nRegs == 0 ); // start the counter-example pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 ); pNew->iFrame = pCexState->iFrame; pNew->iPo = pCexState->iPo; // set initial state Gia_ManCleanMark01(p); // set const0 Gia_ManConst0(p)->fMark0 = 0; Gia_ManConst0(p)->fMark1 = 1; for ( i = pCexState->iFrame; i >= 0; i-- ) { // set correct values iBit = pCexState->nPis * i; Gia_ManForEachCi( p, pObj, k ) { pObj->fMark0 = Abc_InfoHasBit(pCexState->pData, iBit+k); pObj->fMark1 = 0; if ( pCexImpl ) pObj->fMark1 |= Abc_InfoHasBit(pCexImpl->pData, iBit+k); if ( pCexEss ) pObj->fMark1 |= Abc_InfoHasBit(pCexEss->pData, iBit+k); } Gia_ManForEachAnd( p, pObj, k ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 && !fCompl1 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; else if ( !fCompl1 ) pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1; else assert( 0 ); } Gia_ManForEachCo( p, pObj, k ) pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); // move values from COs to CIs if ( i == pCexState->iFrame ) { assert( Gia_ManPo(p, pCexState->iPo)->fMark0 == 1 ); if ( fFindAll ) Bmc_CexCareBits_rec( p, Gia_ObjFanin0(Gia_ManPo(p, pCexState->iPo)) ); else Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(Gia_ManPo(p, pCexState->iPo)) ); } else { Gia_ManForEachRi( p, pObj, k ) if ( Abc_InfoHasBit(pNew->pData, pNew->nPis * (i+1) + Gia_ManPiNum(p) + k) ) { if ( fFindAll ) Bmc_CexCareBits_rec( p, Gia_ObjFanin0(pObj) ); else Bmc_CexCareBits2_rec( p, Gia_ObjFanin0(pObj) ); } } // save the results Gia_ManForEachCi( p, pObj, k ) if ( pObj->fMark1 ) { pObj->fMark1 = 0; if ( pCexImpl == NULL || !Abc_InfoHasBit(pCexImpl->pData, pNew->nPis * i + k) ) Abc_InfoSetBit(pNew->pData, pNew->nPis * i + k); } } if ( pCexEss ) printf( "Minimized: " ); else printf( "Care bits: " ); Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose ); return pNew; } /**Function************************************************************* Synopsis [Simulates one bit to check whether it is essential.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Bmc_CexEssentialBitOne( Gia_Man_t * p, Abc_Cex_t * pCexState, int iBit, Abc_Cex_t * pCexPrev, int * pfEqual ) { Abc_Cex_t * pNew; Gia_Obj_t * pObj; int i, k, fCompl0, fCompl1; assert( pCexState->nRegs == 0 ); assert( iBit < pCexState->nBits ); if ( pfEqual ) *pfEqual = 0; // start the counter-example pNew = Abc_CexAllocFull( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 ); pNew->iFrame = pCexState->iFrame; pNew->iPo = pCexState->iPo; // clean bit Abc_InfoXorBit( pNew->pData, iBit ); // simulate the remaining frames Gia_ManConst0(p)->fMark0 = 0; Gia_ManConst0(p)->fMark1 = 1; for ( i = iBit / pCexState->nPis; i <= pCexState->iFrame; i++ ) { Gia_ManForEachCi( p, pObj, k ) { pObj->fMark0 = Abc_InfoHasBit( pCexState->pData, i * pCexState->nPis + k ); pObj->fMark1 = Abc_InfoHasBit( pNew->pData, i * pCexState->nPis + k ); } Gia_ManForEachAnd( p, pObj, k ) { fCompl0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); fCompl1 = Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj); pObj->fMark0 = fCompl0 & fCompl1; if ( pObj->fMark0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 & Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 && !fCompl1 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1 | Gia_ObjFanin1(pObj)->fMark1; else if ( !fCompl0 ) pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; else if ( !fCompl1 ) pObj->fMark1 = Gia_ObjFanin1(pObj)->fMark1; else assert( 0 ); } Gia_ManForEachCo( p, pObj, k ) { pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); pObj->fMark1 = Gia_ObjFanin0(pObj)->fMark1; } if ( i < pCexState->iFrame ) { int fChanges = 0; int fEqual = (pCexPrev != NULL); int iBitShift = (i + 1) * pCexState->nPis + Gia_ManPiNum(p); Gia_ManForEachRi( p, pObj, k ) { if ( fEqual && pCexPrev && (int)pObj->fMark1 != Abc_InfoHasBit(pCexPrev->pData, iBitShift + k) ) fEqual = 0; if ( !pObj->fMark1 ) { fChanges = 1; Abc_InfoXorBit( pNew->pData, iBitShift + k ); } } if ( !fChanges || fEqual ) { if ( pfEqual ) *pfEqual = fEqual; Abc_CexFree( pNew ); return NULL; } } /* if ( i == 20 ) { printf( "Frame %d : ", i ); Gia_ManForEachRi( p, pObj, k ) printf( "%d", pObj->fMark1 ); printf( "\n" ); } */ } return pNew; } void Bmc_CexEssentialBitTest( Gia_Man_t * p, Abc_Cex_t * pCexState ) { Abc_Cex_t * pNew; int b; for ( b = 0; b < pCexState->nBits; b++ ) { if ( b % 100 ) continue; pNew = Bmc_CexEssentialBitOne( p, pCexState, b, NULL, NULL ); Bmc_CexPrint( pNew, Gia_ManPiNum(p), 0 ); if ( Gia_ManPo(p, pCexState->iPo)->fMark1 ) printf( "Not essential\n" ); else printf( "Essential\n" ); Abc_CexFree( pNew ); } } /**Function************************************************************* Synopsis [Computes essential bits of the CEX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Bmc_CexEssentialBits( Gia_Man_t * p, Abc_Cex_t * pCexState, Abc_Cex_t * pCexCare, int fVerbose ) { Abc_Cex_t * pNew, * pTemp, * pPrev = NULL; int b, fEqual = 0, fPrevStatus = 0; // abctime clk = Abc_Clock(); assert( pCexState->nBits == pCexCare->nBits ); // start the counter-example pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCexState->iFrame + 1 ); pNew->iFrame = pCexState->iFrame; pNew->iPo = pCexState->iPo; // iterate through care-bits for ( b = 0; b < pCexState->nBits; b++ ) { // skip don't-care bits if ( !Abc_InfoHasBit(pCexCare->pData, b) ) continue; // skip state bits if ( b % pCexCare->nPis >= Gia_ManPiNum(p) ) { Abc_InfoSetBit( pNew->pData, b ); continue; } // check if this is an essential bit pTemp = Bmc_CexEssentialBitOne( p, pCexState, b, pPrev, &fEqual ); // pTemp = Bmc_CexEssentialBitOne( p, pCexState, b, NULL, &fEqual ); if ( pTemp == NULL ) { if ( fEqual && fPrevStatus ) Abc_InfoSetBit( pNew->pData, b ); continue; } // Bmc_CexPrint( pTemp, Gia_ManPiNum(p), fVerbose ); Abc_CexFree( pPrev ); pPrev = pTemp; // record essential bit fPrevStatus = !Gia_ManPo(p, pCexState->iPo)->fMark1; if ( !Gia_ManPo(p, pCexState->iPo)->fMark1 ) Abc_InfoSetBit( pNew->pData, b ); } Abc_CexFreeP( &pPrev ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); printf( "Essentials: " ); Bmc_CexPrint( pNew, Gia_ManPiNum(p), fVerbose ); return pNew; } /**Function************************************************************* Synopsis [Computes essential bits of the CEX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_CexTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ) { abctime clk = Abc_Clock(); Abc_Cex_t * pCexImpl = NULL; Abc_Cex_t * pCexStates = Bmc_CexInnerStates( p, pCex, &pCexImpl, fVerbose ); Abc_Cex_t * pCexCare = Bmc_CexCareBits( p, pCexStates, pCexImpl, NULL, 1, fVerbose ); Abc_Cex_t * pCexEss, * pCexMin; if ( !Bmc_CexVerify( p, pCex, pCexCare ) ) printf( "Counter-example care-set verification has failed.\n" ); pCexEss = Bmc_CexEssentialBits( p, pCexStates, pCexCare, fVerbose ); pCexMin = Bmc_CexCareBits( p, pCexStates, pCexImpl, pCexEss, 0, fVerbose ); if ( !Bmc_CexVerify( p, pCex, pCexMin ) ) printf( "Counter-example min-set verification has failed.\n" ); // Bmc_CexDumpStats( p, pCex, pCexCare, pCexEss, pCexMin, Abc_Clock() - clk ); Abc_CexFreeP( &pCexStates ); Abc_CexFreeP( &pCexImpl ); Abc_CexFreeP( &pCexCare ); Abc_CexFreeP( &pCexEss ); Abc_CexFreeP( &pCexMin ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // Bmc_CexBuildNetworkTest( p, pCex ); // Bmc_CexPerformUnrollingTest( p, pCex ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcChain.c000066400000000000000000000330641300674244400232420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcChain.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Implementation of chain BMC.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcChain.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "aig/gia/giaAig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the first failure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Bmc_ChainFailOneOutput( Gia_Man_t * p, int nFrameMax, int nConfMax, int fVerbose, int fVeryVerbose ) { int RetValue; Abc_Cex_t * pCex = NULL; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); Saig_ParBmc_t Pars, * pPars = &Pars; Saig_ParBmcSetDefaultParams( pPars ); pPars->nFramesMax = nFrameMax; pPars->nConfLimit = nConfMax; pPars->fVerbose = fVeryVerbose; RetValue = Saig_ManBmcScalable( pAig, pPars ); if ( RetValue == 0 ) // SAT { pCex = pAig->pSeqModel, pAig->pSeqModel = NULL; if ( fVeryVerbose ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.\n", pCex->iPo, p->pName, pCex->iFrame ); } else if ( fVeryVerbose ) Abc_Print( 1, "No output asserted in %d frames. Resource limit reached.\n", pPars->iFrame+2 ); Aig_ManStop( pAig ); return pCex; } /**Function************************************************************* Synopsis [Move GIA into the failing state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupWithInit( 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_ObjIsAnd(pObj) ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) { pObj->Value = Gia_ManAppendCi( pNew ); pObj->Value = Abc_LitNotCond( pObj->Value, pObj->fMark0 ); } else if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ObjFanin0Copy(pObj); pObj->Value = Abc_LitNotCond( pObj->Value, pObj->fMark0 ); pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); } } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } Gia_Man_t * Gia_ManVerifyCexAndMove( Gia_Man_t * pGia, Abc_Cex_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; Gia_ManCleanMark0(pGia); Gia_ManForEachRo( pGia, pObj, i ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Gia_ManForEachPi( pGia, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); Gia_ManForEachAnd( pGia, pObj, k ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachCo( pGia, pObj, k ) pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); if ( i == p->iFrame ) break; Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, k ) pObjRo->fMark0 = pObjRi->fMark0; } assert( iBit == p->nBits ); RetValue = Gia_ManPo(pGia, p->iPo)->fMark0; assert( RetValue ); // set PI/PO values to zero and transfer RO values to RI Gia_ManForEachPi( pGia, pObj, k ) pObj->fMark0 = 0; Gia_ManForEachPo( pGia, pObj, k ) pObj->fMark0 = 0; Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, k ) pObjRi->fMark0 = pObjRo->fMark0; // duplicate assuming CI/CO marks are set correctly pNew = Gia_ManDupWithInit( pGia ); Gia_ManCleanMark0(pGia); return pNew; } /**Function************************************************************* Synopsis [Find what outputs fail in this state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupPosAndPropagateInit( 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_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_ObjIsPi(p, pObj) ) pObj->Value = Gia_ManAppendCi( pNew ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = 0; else if ( Gia_ObjIsPo(p, pObj) ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManHashStop( pNew ); assert( Gia_ManPiNum(p) == Gia_ManPiNum(pNew) ); assert( Gia_ManPoNum(p) == Gia_ManPoNum(pNew) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } sat_solver * Gia_ManDeriveSatSolver( Gia_Man_t * p, Vec_Int_t * vSatIds ) { // extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); sat_solver * pSat; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); // Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); Cnf_Dat_t * pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); // save SAT vars for the primary inputs if ( vSatIds ) { Aig_Obj_t * pObj; int i; Vec_IntClear( vSatIds ); Aig_ManForEachCi( pAig, pObj, i ) Vec_IntPush( vSatIds, pCnf->pVarNums[ Aig_ObjId(pObj) ] ); assert( Vec_IntSize(vSatIds) == Gia_ManPiNum(p) ); } Aig_ManStop( pAig ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); Cnf_DataFree( pCnf ); assert( p->nRegs == 0 ); return pSat; } Vec_Int_t * Bmc_ChainFindFailedOutputs( Gia_Man_t * p, Vec_Ptr_t * vCexes ) { Vec_Int_t * vOutputs; Vec_Int_t * vSatIds; Gia_Man_t * pInit; Gia_Obj_t * pObj; sat_solver * pSat; int i, j, Lit, status = 0; // derive output logic cones pInit = Gia_ManDupPosAndPropagateInit( p ); // derive SAT solver and test vSatIds = Vec_IntAlloc( Gia_ManPiNum(p) ); pSat = Gia_ManDeriveSatSolver( pInit, vSatIds ); vOutputs = Vec_IntAlloc( 100 ); Gia_ManForEachPo( pInit, pObj, i ) { if ( Gia_ObjFaninLit0p(pInit, pObj) == 0 ) continue; Lit = Abc_Var2Lit( i+1, 0 ); status = sat_solver_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 ); if ( status == l_True ) { // save the index of solved output Vec_IntPush( vOutputs, i ); // create CEX for this output if ( vCexes ) { Abc_Cex_t * pCex = Abc_CexAlloc( Gia_ManRegNum(p), Gia_ManPiNum(p), 1 ); pCex->iFrame = 0; pCex->iPo = i; for ( j = 0; j < Gia_ManPiNum(p); j++ ) if ( sat_solver_var_value( pSat, Vec_IntEntry(vSatIds, j) ) ) Abc_InfoSetBit( pCex->pData, Gia_ManRegNum(p) + j ); Vec_PtrPush( vCexes, pCex ); } } } Gia_ManStop( pInit ); sat_solver_delete( pSat ); Vec_IntFree( vSatIds ); return vOutputs; } /**Function************************************************************* Synopsis [Cleanup AIG by removing COs replacing failed out by const0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ObjMakePoConst0( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); pObj->iDiff0 = Gia_ObjId( p, pObj ); pObj->fCompl0 = 0; } int Gia_ManCountNonConst0( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Count = 0; Gia_ManForEachPo( p, pObj, i ) Count += (Gia_ObjFaninLit0p(p, pObj) != 0); return Count; } Gia_Man_t * Bmc_ChainCleanup( Gia_Man_t * p, Vec_Int_t * vOutputs ) { int i, iOut; Vec_IntForEachEntry( vOutputs, iOut, i ) { Gia_Obj_t * pObj = Gia_ManPo( p, iOut ); assert( Gia_ObjFaninLit0p(p, pObj) != 0 ); Gia_ObjMakePoConst0( p, pObj ); assert( Gia_ObjFaninLit0p(p, pObj) == 0 ); } return Gia_ManCleanup( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_ChainTest( Gia_Man_t * p, int nFrameMax, int nConfMax, int fVerbose, int fVeryVerbose, Vec_Ptr_t ** pvCexes ) { int Iter, IterMax = 10000; Gia_Man_t * pTemp, * pNew = Gia_ManDup(p); Abc_Cex_t * pCex = NULL; Vec_Int_t * vOutputs; abctime clk2, clk = Abc_Clock(); abctime clkBmc = 0; abctime clkMov = 0; abctime clkSat = 0; abctime clkCln = 0; abctime clkSwp = 0; int DepthTotal = 0; if ( pvCexes ) *pvCexes = Vec_PtrAlloc( 1000 ); for ( Iter = 0; Iter < IterMax; Iter++ ) { if ( Gia_ManPoNum(pNew) == 0 ) { if ( fVerbose ) printf( "Finished all POs.\n" ); break; } // run BMC till the first failure clk2 = Abc_Clock(); pCex = Bmc_ChainFailOneOutput( pNew, nFrameMax, nConfMax, fVerbose, fVeryVerbose ); clkBmc += Abc_Clock() - clk2; if ( pCex == NULL ) { if ( fVerbose ) printf( "BMC could not detect a failed output in %d frames with %d conflicts.\n", nFrameMax, nConfMax ); break; } assert( !Iter || pCex->iFrame > 0 ); // move the AIG to the failure state clk2 = Abc_Clock(); pNew = Gia_ManVerifyCexAndMove( pTemp = pNew, pCex ); Gia_ManStop( pTemp ); DepthTotal += pCex->iFrame; clkMov += Abc_Clock() - clk2; // find outputs that fail in this state clk2 = Abc_Clock(); vOutputs = Bmc_ChainFindFailedOutputs( pNew, pvCexes ? *pvCexes : NULL ); assert( Vec_IntFind(vOutputs, pCex->iPo) >= 0 ); // save the counter-example if ( pvCexes ) Vec_PtrPush( *pvCexes, pCex ); else Abc_CexFree( pCex ); clkSat += Abc_Clock() - clk2; // remove them from the AIG clk2 = Abc_Clock(); pNew = Bmc_ChainCleanup( pTemp = pNew, vOutputs ); Gia_ManStop( pTemp ); clkCln += Abc_Clock() - clk2; // perform sequential cleanup clk2 = Abc_Clock(); // pNew = Gia_ManSeqStructSweep( pTemp = pNew, 0, 1, 0 ); // Gia_ManStop( pTemp ); clkSwp += Abc_Clock() - clk2; // printout if ( fVerbose ) { int nNonConst = Gia_ManCountNonConst0(pNew); printf( "Iter %4d : ", Iter+1 ); printf( "Depth =%5d ", DepthTotal ); printf( "FailPo =%5d ", Vec_IntSize(vOutputs) ); printf( "UndecPo =%5d ", nNonConst ); printf( "(%6.2f %%) ", 100.0 * nNonConst / Gia_ManPoNum(pNew) ); printf( "AIG =%8d ", Gia_ManAndNum(pNew) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } Vec_IntFree( vOutputs ); } printf( "Completed a CEX chain with %d segments, %d frames, and %d failed POs (out of %d). ", Iter, DepthTotal, Gia_ManPoNum(pNew) - Gia_ManCountNonConst0(pNew), Gia_ManPoNum(pNew) ); if ( fVerbose ) { Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Abc_PrintTimeP( 1, "BMC ", clkBmc, Abc_Clock() - clk ); Abc_PrintTimeP( 1, "Init ", clkMov, Abc_Clock() - clk ); Abc_PrintTimeP( 1, "SAT ", clkSat, Abc_Clock() - clk ); Abc_PrintTimeP( 1, "Clean", clkCln, Abc_Clock() - clk ); // Abc_PrintTimeP( 1, "Sweep", clkSwp, Abc_Clock() - clk ); } Gia_ManStop( pNew ); if ( pvCexes ) printf( "Total number of CEXes collected = %d.\n", Vec_PtrSize(*pvCexes) ); return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcClp.c000066400000000000000000001615401300674244400227370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcClp.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [INT-FX: Interpolation-based logic sharing extraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcClp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "misc/vec/vecWec.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [For a given random pattern, compute output change.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_ComputeSimDiff( Gia_Man_t * p, Vec_Int_t * vPat, Vec_Int_t * vPat2 ) { Gia_Obj_t * pObj; int i, Id; word Sim, Sim0, Sim1; Gia_ManForEachCiId( p, Id, i ) { Sim = Vec_IntEntry(vPat, i) ? ~(word)0 : 0; Sim ^= (word)1 << (i + 1); Vec_WrdWriteEntry( p->vSims, Id, Sim ); } Gia_ManForEachAnd( p, pObj, i ) { Sim0 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId0(pObj, i) ); Sim1 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId1(pObj, i) ); Sim0 = Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0; Sim1 = Gia_ObjFaninC1(pObj) ? ~Sim1 : Sim1; Vec_WrdWriteEntry( p->vSims, i, Sim0 & Sim1 ); } Gia_ManForEachCo( p, pObj, i ) { Id = Gia_ObjId( p, pObj ); Sim0 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId0(pObj, Id) ); Sim0 = Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0; Vec_WrdWriteEntry( p->vSims, Id, Sim0 ); } pObj = Gia_ManCo( p, 0 ); Sim = Vec_WrdEntry( p->vSims, Gia_ObjId(p, pObj) ); Vec_IntClear( vPat2 ); for ( i = 1; i <= Gia_ManCiNum(p); i++ ) Vec_IntPush( vPat2, (int)((Sim & 1) ^ ((Sim >> i) & 1)) ); return (int)(Sim & 1); } void Bmc_ComputeSimTest( Gia_Man_t * p ) { int i, v, w, Res, Bit, Bit2, nPats = 256; int Count[2][64][64] = {{{0}}}; int PatCount[64][2][2] = {{{0}}}; int DiffCount[64] = {0}; Vec_Int_t * vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); Vec_Int_t * vPat2 = Vec_IntAlloc( Gia_ManCiNum(p) ); Vec_WrdFreeP( &p->vSims ); p->vSims = Vec_WrdStart( Gia_ManObjNum(p) ); printf( "Number of patterns = %d.\n", nPats ); for ( i = 0; i < nPats; i++ ) { Vec_IntClear( vPat ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) Vec_IntPush( vPat, rand() & 1 ); // Vec_IntForEachEntry( vPat, Bit, v ) // printf( "%d", Bit ); // printf( " " ); Res = Bmc_ComputeSimDiff( p, vPat, vPat2 ); // printf( "%d ", Res ); // Vec_IntForEachEntry( vPat2, Bit, v ) // printf( "%d", Bit ); // printf( "\n" ); Vec_IntForEachEntry( vPat, Bit, v ) PatCount[v][Res][Bit]++; Vec_IntForEachEntry( vPat2, Bit, v ) { if ( Bit ) DiffCount[v]++; Vec_IntForEachEntryStart( vPat2, Bit2, w, v + 1 ) if ( Bit && Bit2 ) Count[Res][v][w]++; } } Vec_IntFree( vPat ); Vec_IntFree( vPat2 ); Vec_WrdFreeP( &p->vSims ); printf( "\n" ); printf( " " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3c ", 'a'+v ); printf( "\n" ); printf( "Off0 " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", PatCount[v][0][0] ); printf( "\n" ); printf( "Off1 " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", PatCount[v][0][1] ); printf( "\n" ); printf( "On0 " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", PatCount[v][1][0] ); printf( "\n" ); printf( "On1 " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", PatCount[v][1][1] ); printf( "\n" ); printf( "\n" ); printf( "Diff " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", DiffCount[v] ); printf( "\n" ); printf( "\n" ); for ( i = 0; i < 2; i++ ) { printf( " " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3c ", 'a'+v ); printf( "\n" ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) { printf( " %c ", 'a'+v ); for ( w = 0; w < Gia_ManCiNum(p); w++ ) { if ( Count[i][v][w] ) printf( "%3d ", Count[i][v][w] ); else printf( " . " ); } printf( "\n" ); } printf( "\n" ); } } static abctime clkCheck1 = 0; static abctime clkCheck2 = 0; static abctime clkCheckS = 0; static abctime clkCheckU = 0; // iterator thought the cubes #define Bmc_SopForEachCube( pSop, nVars, pCube ) for ( pCube = (pSop); *pCube; pCube += (nVars) + 3 ) /**Function************************************************************* Synopsis [Perform approximate irredundant step on the cover.] Description [Iterate through the cubes in the reverse order and check if each cube is contained in the previously seen cubes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CollapseIrredundant( Vec_Str_t * vSop, int nCubes, int nVars ) { int nBTLimit = 0; sat_solver * pSat; int i, k, status, iLit, nRemoved = 0; Vec_Int_t * vLits = Vec_IntAlloc(nVars); // collect cubes char * pCube, * pSop = Vec_StrArray(vSop); Vec_Ptr_t * vCubes = Vec_PtrAlloc(nCubes); assert( Vec_StrSize(vSop) == nCubes * (nVars + 3) + 1 ); Bmc_SopForEachCube( pSop, nVars, pCube ) Vec_PtrPush( vCubes, pCube ); // create SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, nVars ); // iterate through cubes in the reverse order Vec_PtrForEachEntryReverse( char *, vCubes, pCube, i ) { // collect literals Vec_IntClear( vLits ); for ( k = 0; k < nVars; k++ ) if ( pCube[k] != '-' ) Vec_IntPush( vLits, Abc_Var2Lit(k, pCube[k] == '1') ); // check if this cube intersects with the complement of other cubes in the solver // if it does not intersect, then it is redundant and can be skipped // if it does, then it should be added status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) // timeout break; if ( status == l_False ) // unsat { Vec_PtrWriteEntry( vCubes, i, NULL ); nRemoved++; continue; } assert( status == l_True ); // make a clause out of the cube by complementing its literals Vec_IntForEachEntry( vLits, iLit, k ) Vec_IntWriteEntry( vLits, k, Abc_LitNot(iLit) ); // add it to the solver status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); assert( status == 1 ); } //printf( "Approximate irrendundant reduced %d cubes (out of %d).\n", nRemoved, nCubes ); // cleanup cover if ( i == -1 && nRemoved > 0 ) // finished without timeout and removed some cubes { int j = 0; Vec_PtrForEachEntry( char *, vCubes, pCube, i ) if ( pCube != NULL ) for ( k = 0; k < nVars + 3; k++ ) Vec_StrWriteEntry( vSop, j++, pCube[k] ); Vec_StrWriteEntry( vSop, j++, '\0' ); Vec_StrShrink( vSop, j ); } sat_solver_delete( pSat ); Vec_PtrFree( vCubes ); Vec_IntFree( vLits ); return i == -1 ? 1 : 0; } /**Function************************************************************* Synopsis [Perform full irredundant step on the cover.] Description [Iterate through the cubes in the direct order and check if each cube is contained in all other cubes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CollapseIrredundantFull( Vec_Str_t * vSop, int nCubes, int nVars ) { int nBTLimit = 0; sat_solver * pSat; int i, k, status, nRemoved = 0; Vec_Int_t * vLits = Vec_IntAlloc(nVars+nCubes); // collect cubes char * pCube, * pSop = Vec_StrArray(vSop); Vec_Ptr_t * vCubes = Vec_PtrAlloc(nCubes); assert( Vec_StrSize(vSop) == nCubes * (nVars + 3) + 1 ); Bmc_SopForEachCube( pSop, nVars, pCube ) Vec_PtrPush( vCubes, pCube ); // create SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, nVars + nCubes ); // add cubes Vec_PtrForEachEntry( char *, vCubes, pCube, i ) { // collect literals Vec_IntFill( vLits, 1, Abc_Var2Lit(nVars + i, 1) ); // neg literal for ( k = 0; k < nVars; k++ ) if ( pCube[k] != '-' ) Vec_IntPush( vLits, Abc_Var2Lit(k, pCube[k] == '0') ); // add it to the solver status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); assert( status == 1 ); } // iterate through cubes in the direct order Vec_PtrForEachEntry( char *, vCubes, pCube, i ) { // collect literals Vec_IntClear( vLits ); for ( k = 0; k < nCubes; k++ ) if ( k != i && Vec_PtrEntry(vCubes, k) ) // skip this cube and already removed cubes Vec_IntPush( vLits, Abc_Var2Lit(nVars + k, 0) ); // pos literal // collect cube for ( k = 0; k < nVars; k++ ) if ( pCube[k] != '-' ) Vec_IntPush( vLits, Abc_Var2Lit(k, pCube[k] == '1') ); // check if this cube intersects with the complement of other cubes in the solver // if it does not intersect, then it is redundant and can be skipped status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) // timeout break; if ( status == l_False ) // unsat { Vec_PtrWriteEntry( vCubes, i, NULL ); nRemoved++; continue; } assert( status == l_True ); } //printf( "Approximate irrendundant reduced %d cubes (out of %d).\n", nRemoved, nCubes ); // cleanup cover if ( i == Vec_PtrSize(vCubes) && nRemoved > 0 ) // finished without timeout and removed some cubes { int j = 0; Vec_PtrForEachEntry( char *, vCubes, pCube, i ) if ( pCube != NULL ) for ( k = 0; k < nVars + 3; k++ ) Vec_StrWriteEntry( vSop, j++, pCube[k] ); Vec_StrWriteEntry( vSop, j++, '\0' ); Vec_StrShrink( vSop, j ); } sat_solver_delete( pSat ); Vec_PtrFree( vCubes ); Vec_IntFree( vLits ); return i == -1 ? 1 : 0; } /**Function************************************************************* Synopsis [Performs one round of removing literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CollapseExpandRound( sat_solver * pSat, sat_solver * pSatOn, Vec_Int_t * vLits, Vec_Int_t * vNums, Vec_Int_t * vTemp, int nBTLimit, int fCanon, int fOnOffSetLit ) { int fProfile = 0; int k, n, iLit, status; abctime clk; // try removing one literal at a time for ( k = Vec_IntSize(vLits) - 1; k >= 0; k-- ) { int Save = Vec_IntEntry( vLits, k ); if ( Save == -1 ) continue; // check if this literal when expanded overlaps with the on-set if ( pSatOn ) { assert( fOnOffSetLit == -1 ); // it is ok to skip the first round if the literal is positive if ( fCanon && !Abc_LitIsCompl(Save) ) continue; // put into new array Vec_IntClear( vTemp ); Vec_IntForEachEntry( vLits, iLit, n ) if ( iLit != -1 ) Vec_IntPush( vTemp, Abc_LitNotCond(iLit, k==n) ); // check against onset if ( fProfile ) clk = Abc_Clock(); status = sat_solver_solve( pSatOn, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( fProfile ) clkCheck1 += Abc_Clock() - clk; if ( status == l_Undef ) return -1; //printf( "%d", status == l_True ); if ( status == l_False ) { if ( fProfile ) clkCheckU += Abc_Clock() - clk; continue; } if ( fProfile ) clkCheckS += Abc_Clock() - clk; // otherwise keep trying to remove it } Vec_IntWriteEntry( vLits, k, -1 ); // put into new array Vec_IntClear( vTemp ); if ( fOnOffSetLit >= 0 ) Vec_IntPush( vTemp, fOnOffSetLit ); Vec_IntForEachEntry( vLits, iLit, n ) if ( iLit != -1 ) Vec_IntPush( vTemp, iLit ); // check against offset if ( fProfile ) clk = Abc_Clock(); status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( fProfile ) clkCheck2 += Abc_Clock() - clk; // if ( fOnOffSetLit >= 0 ) // Vec_IntPop( vTemp ); if ( status == l_Undef ) return -1; if ( status == l_True ) { Vec_IntWriteEntry( vLits, k, Save ); if ( fProfile ) clkCheckS += Abc_Clock() - clk; } else if ( fProfile ) clkCheckU += Abc_Clock() - clk; } // if ( pSatOn ) // printf( "\n" ); return 0; } /**Function************************************************************* Synopsis [Expends minterm into a cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CollapseExpand( sat_solver * pSat, sat_solver * pSatOn, Vec_Int_t * vLits, Vec_Int_t * vNums, Vec_Int_t * vTemp, int nBTLimit, int fCanon, int fOnOffSetLit ) { // perform one quick reduction if it is non-canonical if ( !fCanon ) { int i, k, iLit, status, nFinal, * pFinal; // check against offset if ( fOnOffSetLit >= 0 ) Vec_IntPush( vLits, fOnOffSetLit ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), nBTLimit, 0, 0, 0 ); if ( fOnOffSetLit >= 0 ) Vec_IntPop( vLits ); if ( status == l_Undef ) return -1; assert( status == l_False ); // get subset of literals nFinal = sat_solver_final( pSat, &pFinal ); // mark unused literals Vec_IntForEachEntry( vLits, iLit, i ) { for ( k = 0; k < nFinal; k++ ) if ( iLit == Abc_LitNot(pFinal[k]) ) break; if ( k == nFinal ) Vec_IntWriteEntry( vLits, i, -1 ); } if ( Bmc_CollapseExpandRound( pSat, NULL, vLits, vNums, vTemp, nBTLimit, fCanon, fOnOffSetLit ) == -1 ) return -1; } else { if ( Bmc_CollapseExpandRound( pSat, pSatOn, vLits, vNums, vTemp, nBTLimit, fCanon, -1 ) == -1 ) return -1; if ( Bmc_CollapseExpandRound( pSat, NULL, vLits, vNums, vTemp, nBTLimit, fCanon, -1 ) == -1 ) return -1; } { // put into new array int i, iLit; Vec_IntClear( vNums ); Vec_IntForEachEntry( vLits, iLit, i ) if ( iLit != -1 ) Vec_IntPush( vNums, i ); } return 0; } int Bmc_CollapseExpand2( sat_solver * pSat, sat_solver * pSatOn, Vec_Int_t * vLits, Vec_Int_t * vNums, Vec_Int_t * vTemp, int nBTLimit, int fCanon, int fOnOffSetLit ) { // perform one quick reduction if it is non-canonical if ( !fCanon ) { int i, k, iLit, j, iNum, status, nFinal, * pFinal; // check against offset if ( fOnOffSetLit >= 0 ) Vec_IntPush( vLits, fOnOffSetLit ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), nBTLimit, 0, 0, 0 ); if ( fOnOffSetLit >= 0 ) Vec_IntPop( vLits ); if ( status == l_Undef ) return -1; assert( status == l_False ); // get subset of literals nFinal = sat_solver_final( pSat, &pFinal ); Vec_IntClear( vNums ); Vec_IntClear( vTemp ); if ( fOnOffSetLit >= 0 ) { //Vec_IntPush( vNums, -1 ); Vec_IntPush( vTemp, fOnOffSetLit ); } Vec_IntForEachEntry( vLits, iLit, i ) { for ( k = 0; k < nFinal; k++ ) if ( iLit == Abc_LitNot(pFinal[k]) ) break; if ( k == nFinal ) continue; Vec_IntPush( vNums, i ); Vec_IntPush( vTemp, iLit ); } // check against offset status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) return -1; assert( status == l_False ); // get subset of literals nFinal = sat_solver_final( pSat, &pFinal ); j = 0; Vec_IntForEachEntry( vTemp, iLit, i ) { if ( iLit == fOnOffSetLit ) continue; for ( k = 0; k < nFinal; k++ ) if ( iLit == Abc_LitNot(pFinal[k]) ) break; if ( k == nFinal ) continue; Vec_IntWriteEntry( vNums, j++, Vec_IntEntry(vNums, i) ); } Vec_IntShrink( vNums, j ); // try removing each literal for ( i = 0; i < Vec_IntSize(vNums); i++ ) { Vec_IntClear( vTemp ); if ( fOnOffSetLit >= 0 ) Vec_IntPush( vTemp, fOnOffSetLit ); Vec_IntForEachEntry( vNums, iNum, k ) if ( k != i ) Vec_IntPush( vTemp, Vec_IntEntry(vLits, iNum) ); // check against offset status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) return -1; if ( status == l_True ) continue; // remove literal Vec_IntDrop( vNums, i ); i--; } } else { if ( Bmc_CollapseExpandRound( pSat, pSatOn, vLits, vNums, vTemp, nBTLimit, fCanon, -1 ) == -1 ) return -1; if ( Bmc_CollapseExpandRound( pSat, NULL, vLits, vNums, vTemp, nBTLimit, fCanon, -1 ) == -1 ) return -1; } /* { // put into new array int i, iLit; Vec_IntClear( vNums ); Vec_IntForEachEntry( vLits, iLit, i ) if ( iLit != -1 ) Vec_IntPush( vNums, i ); //printf( "%d(%d) ", Vec_IntSize(vNums), Vec_IntSize(vLits) ); } */ return 0; } /**Function************************************************************* Synopsis [Returns SAT solver in the 'sat' state with the given assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_ComputeCanonical2( sat_solver * pSat, Vec_Int_t * vLits, Vec_Int_t * vTemp, int nBTLimit ) { int i, k, iLit, status = l_Undef; for ( i = 0; i < Vec_IntSize(vLits); i++ ) { // copy the first i+1 literals Vec_IntClear( vTemp ); Vec_IntForEachEntryStop( vLits, iLit, k, i+1 ) Vec_IntPush( vTemp, iLit ); // check if it satisfies the on-set status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) return l_Undef; if ( status == l_True ) continue; // if it is UNSAT, try the opposite literal iLit = Vec_IntEntry( vLits, i ); // if literal is positive, there is no way to flip it if ( !Abc_LitIsCompl(iLit) ) return l_False; Vec_IntWriteEntry( vLits, i, Abc_LitNot(iLit) ); Vec_IntForEachEntryStart( vLits, iLit, k, i+1 ) Vec_IntWriteEntry( vLits, k, Abc_LitNot(Abc_LitRegular(iLit)) ); // recheck i--; } assert( status == l_True ); return status; } int Bmc_ComputeCanonical( sat_solver * pSat, Vec_Int_t * vLits, Vec_Int_t * vTemp, int nBTLimit ) { sat_solver_set_resource_limits( pSat, nBTLimit, 0, 0, 0 ); return sat_solver_solve_lexsat( pSat, Vec_IntArray(vLits), Vec_IntSize(vLits) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOneInt2( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose, int fCompl ) { int fPrintMinterm = 0; int nVars = Gia_ManCiNum(p); Vec_Int_t * vVars = Vec_IntAlloc( nVars ); Vec_Int_t * vLits = Vec_IntAlloc( nVars ); Vec_Int_t * vLitsC= Vec_IntAlloc( nVars ); Vec_Int_t * vNums = Vec_IntAlloc( nVars ); Vec_Int_t * vCube = Vec_IntAlloc( nVars ); Vec_Str_t * vSop = Vec_StrAlloc( 100 ); int iOut = 0, iLit, iVar, status, n, Count, Start; // create SAT solver Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); sat_solver * pSat[3] = { (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0), (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0), fCanon ? (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0) : NULL }; // collect CI variables int iCiVarBeg = pCnf->nVars - nVars;// - 1; if ( fReverse ) for ( n = nVars - 1; n >= 0; n-- ) Vec_IntPush( vVars, iCiVarBeg + n ); else for ( n = 0; n < nVars; n++ ) Vec_IntPush( vVars, iCiVarBeg + n ); // start with all negative literals Vec_IntForEachEntry( vVars, iVar, n ) Vec_IntPush( vLitsC, Abc_Var2Lit(iVar, 1) ); // check that on-set/off-set is sat for ( n = 0; n < 2 + fCanon; n++ ) { iLit = Abc_Var2Lit( iOut + 1, n&1 ); // n=0 => F=1 n=1 => F=0 status = sat_solver_addclause( pSat[n], &iLit, &iLit + 1 ); if ( status == 0 ) { Vec_StrPrintStr( vSop, ((n&1) ^ fCompl) ? " 1\n" : " 0\n" ); Vec_StrPush( vSop, '\0' ); goto cleanup; // const0/1 } status = sat_solver_solve( pSat[n], NULL, NULL, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) { Vec_StrFreeP( &vSop ); goto cleanup; // timeout } if ( status == l_False ) { Vec_StrPrintStr( vSop, ((n&1) ^ fCompl) ? " 1\n" : " 0\n" ); Vec_StrPush( vSop, '\0' ); goto cleanup; // const0/1 } } Vec_StrPush( vSop, '\0' ); // prepare on-set for solving // if ( fCanon ) // sat_solver_prepare_enum( pSat[0], Vec_IntArray(vVars), Vec_IntSize(vVars) ); Count = 0; while ( 1 ) { // get the assignment if ( fCanon ) status = Bmc_ComputeCanonical( pSat[0], vLitsC, vCube, nBTLimit ); else { sat_solver_clean_polarity( pSat[0], Vec_IntArray(vVars), Vec_IntSize(vVars) ); status = sat_solver_solve( pSat[0], NULL, NULL, 0, 0, 0, 0 ); } if ( status == l_Undef ) { Vec_StrFreeP( &vSop ); goto cleanup; // timeout } if ( status == l_False ) break; // check number of cubes if ( nCubeLim > 0 && Count == nCubeLim ) { //printf( "The number of cubes exceeded the limit (%d).\n", nCubeLim ); Vec_StrFreeP( &vSop ); goto cleanup; // cube out } // collect values Vec_IntClear( vLits ); Vec_IntClear( vLitsC ); Vec_IntForEachEntry( vVars, iVar, n ) { iLit = Abc_Var2Lit(iVar, !sat_solver_var_value(pSat[0], iVar)); Vec_IntPush( vLits, iLit ); Vec_IntPush( vLitsC, iLit ); } // print minterm if ( fPrintMinterm ) { printf( "Mint: " ); Vec_IntForEachEntry( vLits, iLit, n ) printf( "%d", !Abc_LitIsCompl(iLit) ); printf( "\n" ); } // expand the values status = Bmc_CollapseExpand( pSat[1], fCanon ? pSat[2] : pSat[0], vLits, vNums, vCube, nBTLimit, fCanon, -1 ); if ( status < 0 ) { Vec_StrFreeP( &vSop ); goto cleanup; // timeout } // collect cube Vec_StrPop( vSop ); Start = Vec_StrSize( vSop ); Vec_StrFillExtra( vSop, Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop, Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop, Start + nVars + 1, (char)(fCompl ? '0' : '1') ); Vec_StrWriteEntry( vSop, Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop, Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntForEachEntry( vNums, iVar, n ) { iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop, Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop, Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } //if ( fVerbose ) // printf( "Cube %4d: %s", Count, Vec_StrArray(vSop) + Start ); Count++; // add cube status = sat_solver_addclause( pSat[0], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) break; // add cube if ( fCanon ) status = sat_solver_addclause( pSat[2], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); assert( status == 1 ); } //printf( "Finished enumerating %d assignments.\n", Count ); cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vLitsC ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); sat_solver_delete( pSat[0] ); sat_solver_delete( pSat[1] ); if ( fCanon ) sat_solver_delete( pSat[2] ); Cnf_DataFree( pCnf ); // quickly reduce contained cubes if ( vSop != NULL ) Bmc_CollapseIrredundant( vSop, Vec_StrSize(vSop)/(nVars +3), nVars ); return vSop; } Vec_Str_t * Bmc_CollapseOneOld2( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { Vec_Str_t * vSopOn, * vSopOff; int nCubesOn = ABC_INFINITY; int nCubesOff = ABC_INFINITY; vSopOn = Bmc_CollapseOneInt2( p, nCubeLim, nBTLimit, fCanon, fReverse, fVerbose, 0 ); if ( vSopOn ) nCubesOn = Vec_StrCountEntry(vSopOn,'\n'); Gia_ObjFlipFaninC0( Gia_ManPo(p, 0) ); vSopOff = Bmc_CollapseOneInt2( p, Abc_MinInt(nCubeLim, nCubesOn), nBTLimit, fCanon, fReverse, fVerbose, 1 ); Gia_ObjFlipFaninC0( Gia_ManPo(p, 0) ); if ( vSopOff ) nCubesOff = Vec_StrCountEntry(vSopOff,'\n'); if ( vSopOn == NULL ) return vSopOff; if ( vSopOff == NULL ) return vSopOn; if ( nCubesOn <= nCubesOff ) { Vec_StrFree( vSopOff ); return vSopOn; } else { Vec_StrFree( vSopOn ); return vSopOff; } } /**Function************************************************************* Synopsis [This code computes on-set and off-set simultaneously.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOneOld( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { int fVeryVerbose = fVerbose; int nVars = Gia_ManCiNum(p); Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); sat_solver * pSat[2] = { (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0), (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0) }; sat_solver * pSatClean[2] = { (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0), (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0) }; Vec_Str_t * vSop[2] = { Vec_StrAlloc(1000), Vec_StrAlloc(1000) }, * vRes = NULL; Vec_Int_t * vLitsC[2] = { Vec_IntAlloc(nVars), Vec_IntAlloc(nVars) }; Vec_Int_t * vVars = Vec_IntAlloc( nVars ); Vec_Int_t * vLits = Vec_IntAlloc( nVars ); Vec_Int_t * vNums = Vec_IntAlloc( nVars ); Vec_Int_t * vCube = Vec_IntAlloc( nVars ); int n, v, iVar, iLit, iCiVarBeg, iCube = 0, Start, status; abctime clk = 0, Time[2][2] = {{0}}; int fComplete[2] = {0}; // collect CI variables iCiVarBeg = pCnf->nVars - nVars;// - 1; if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); // check that on-set/off-set is sat for ( n = 0; n < 2; n++ ) { iLit = Abc_Var2Lit( 1, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat[n], &iLit, &iLit + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { Vec_StrClear( vSop[0] ); Vec_StrPrintStr( vSop[0], n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop[0], '\0' ); fComplete[0] = 1; goto cleanup; // const0/1 } // start with all negative literals Vec_IntForEachEntry( vVars, iVar, v ) Vec_IntPush( vLitsC[n], Abc_Var2Lit(iVar, 1) ); // add literals to the solver status = sat_solver_addclause( pSat[n], &iLit, &iLit + 1 ); assert( status ); status = sat_solver_addclause( pSatClean[n], &iLit, &iLit + 1 ); assert( status ); // start cover Vec_StrPush( vSop[n], '\0' ); } // compute cube pairs for ( iCube = 0; nCubeLim == 0 || iCube < nCubeLim; iCube++ ) { for ( n = 0; n < 2; n++ ) { if ( fVeryVerbose ) clk = Abc_Clock(); // get the assignment if ( fCanon ) status = Bmc_ComputeCanonical( pSat[n], vLitsC[n], vCube, nBTLimit ); else { sat_solver_clean_polarity( pSat[n], Vec_IntArray(vVars), Vec_IntSize(vVars) ); status = sat_solver_solve( pSat[n], NULL, NULL, 0, 0, 0, 0 ); } if ( fVeryVerbose ) Time[n][0] += Abc_Clock() - clk; if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { fComplete[n] = 1; break; } // collect values Vec_IntClear( vLits ); Vec_IntClear( vLitsC[n] ); Vec_IntForEachEntry( vVars, iVar, v ) { iLit = Abc_Var2Lit(iVar, !sat_solver_var_value(pSat[n], iVar)); Vec_IntPush( vLits, iLit ); Vec_IntPush( vLitsC[n], iLit ); } // expand the values if ( fVeryVerbose ) clk = Abc_Clock(); status = Bmc_CollapseExpand( pSatClean[!n], pSat[n], vLits, vNums, vCube, nBTLimit, fCanon, -1 ); if ( fVeryVerbose ) Time[n][1] += Abc_Clock() - clk; if ( status < 0 ) goto cleanup; // timeout // collect cube Vec_StrPop( vSop[n] ); Start = Vec_StrSize( vSop[n] ); Vec_StrFillExtra( vSop[n], Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 1, (char)(n ? '0' : '1') ); Vec_StrWriteEntry( vSop[n], Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntForEachEntry( vNums, iVar, v ) { iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop[n], Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop[n], Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } // add cube status = sat_solver_addclause( pSat[n], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) { fComplete[n] = 1; break; } assert( status == 1 ); } if ( fComplete[0] || fComplete[1] ) break; } cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vLitsC[0] ); Vec_IntFree( vLitsC[1] ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); Cnf_DataFree( pCnf ); sat_solver_delete( pSat[0] ); sat_solver_delete( pSat[1] ); sat_solver_delete( pSatClean[0] ); sat_solver_delete( pSatClean[1] ); assert( !fComplete[0] || !fComplete[1] ); if ( fComplete[0] || fComplete[1] ) // one of the cover is computed { vRes = vSop[fComplete[1]]; vSop[fComplete[1]] = NULL; if ( iCube > 1 ) // Bmc_CollapseIrredundant( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); Bmc_CollapseIrredundantFull( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); } if ( fVeryVerbose ) { int fProfile = 0; printf( "Processed output with %d supp vars. ", nVars ); if ( vRes == NULL ) printf( "The resulting SOP exceeded %d cubes.\n", nCubeLim ); else printf( "The best cover contains %d cubes.\n", Vec_StrSize(vRes)/(nVars +3) ); Abc_PrintTime( 1, "Onset minterm", Time[0][0] ); Abc_PrintTime( 1, "Onset expand ", Time[0][1] ); Abc_PrintTime( 1, "Offset minterm", Time[1][0] ); Abc_PrintTime( 1, "Offset expand ", Time[1][1] ); if ( fProfile ) { Abc_PrintTime( 1, "Expand check1 ", clkCheck1 ); clkCheck1 = 0; Abc_PrintTime( 1, "Expand check2 ", clkCheck2 ); clkCheck2 = 0; Abc_PrintTime( 1, "Expand sat ", clkCheckS ); clkCheckS = 0; Abc_PrintTime( 1, "Expand unsat ", clkCheckU ); clkCheckU = 0; } } Vec_StrFreeP( &vSop[0] ); Vec_StrFreeP( &vSop[1] ); return vRes; } /**Function************************************************************* Synopsis [This code computes on-set and off-set simultaneously.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOne_int3( sat_solver * pSat0, sat_solver * pSat1, sat_solver * pSat2, sat_solver * pSat3, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { int fVeryVerbose = fVerbose; sat_solver * pSat[2] = { pSat0, pSat1 }; sat_solver * pSatClean[2] = { pSat2, pSat3 }; Vec_Str_t * vSop[2] = { Vec_StrAlloc(1000), Vec_StrAlloc(1000) }, * vRes = NULL; Vec_Int_t * vLitsC[2] = { Vec_IntAlloc(nVars), Vec_IntAlloc(nVars) }; Vec_Int_t * vVars = Vec_IntAlloc( nVars ); Vec_Int_t * vLits = Vec_IntAlloc( nVars ); Vec_Int_t * vNums = Vec_IntAlloc( nVars ); Vec_Int_t * vCube = Vec_IntAlloc( nVars ); int n, v, iVar, iLit, iCiVarBeg, iCube = 0, Start, status; abctime clk = 0, Time[2][2] = {{0}}; int fComplete[2] = {0}; // collect CI variables // iCiVarBeg = pCnf->nVars - nVars;// - 1; iCiVarBeg = sat_solver_nvars(pSat0) - nVars; if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); // check that on-set/off-set is sat for ( n = 0; n < 2; n++ ) { iLit = Abc_Var2Lit( 1, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat[n], &iLit, &iLit + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { Vec_StrClear( vSop[0] ); Vec_StrPrintStr( vSop[0], n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop[0], '\0' ); fComplete[0] = 1; goto cleanup; // const0/1 } // start with all negative literals Vec_IntForEachEntry( vVars, iVar, v ) Vec_IntPush( vLitsC[n], Abc_Var2Lit(iVar, 1) ); // add literals to the solver status = sat_solver_addclause( pSat[n], &iLit, &iLit + 1 ); assert( status ); status = sat_solver_addclause( pSatClean[n], &iLit, &iLit + 1 ); assert( status ); // start cover Vec_StrPush( vSop[n], '\0' ); } // compute cube pairs for ( iCube = 0; nCubeLim == 0 || iCube < nCubeLim; iCube++ ) { for ( n = 0; n < 2; n++ ) { if ( fVeryVerbose ) clk = Abc_Clock(); // get the assignment if ( fCanon ) status = Bmc_ComputeCanonical( pSat[n], vLitsC[n], vCube, nBTLimit ); else { sat_solver_clean_polarity( pSat[n], Vec_IntArray(vVars), Vec_IntSize(vVars) ); status = sat_solver_solve( pSat[n], NULL, NULL, 0, 0, 0, 0 ); } if ( fVeryVerbose ) Time[n][0] += Abc_Clock() - clk; if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { fComplete[n] = 1; break; } // collect values Vec_IntClear( vLits ); Vec_IntClear( vLitsC[n] ); Vec_IntForEachEntry( vVars, iVar, v ) { iLit = Abc_Var2Lit(iVar, !sat_solver_var_value(pSat[n], iVar)); Vec_IntPush( vLits, iLit ); Vec_IntPush( vLitsC[n], iLit ); } // expand the values if ( fVeryVerbose ) clk = Abc_Clock(); status = Bmc_CollapseExpand( pSatClean[!n], pSat[n], vLits, vNums, vCube, nBTLimit, fCanon, -1 ); if ( fVeryVerbose ) Time[n][1] += Abc_Clock() - clk; if ( status < 0 ) goto cleanup; // timeout // collect cube Vec_StrPop( vSop[n] ); Start = Vec_StrSize( vSop[n] ); Vec_StrFillExtra( vSop[n], Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 1, (char)(n ? '0' : '1') ); Vec_StrWriteEntry( vSop[n], Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntForEachEntry( vNums, iVar, v ) { iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop[n], Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop[n], Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } // add cube status = sat_solver_addclause( pSat[n], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) { fComplete[n] = 1; break; } assert( status == 1 ); } if ( fComplete[0] || fComplete[1] ) break; } cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vLitsC[0] ); Vec_IntFree( vLitsC[1] ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); assert( !fComplete[0] || !fComplete[1] ); if ( fComplete[0] || fComplete[1] ) // one of the cover is computed { vRes = vSop[fComplete[1]]; vSop[fComplete[1]] = NULL; if ( iCube > 1 ) // Bmc_CollapseIrredundant( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); Bmc_CollapseIrredundantFull( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); } if ( fVeryVerbose ) { int fProfile = 0; printf( "Processed output with %d supp vars. ", nVars ); if ( vRes == NULL ) printf( "The resulting SOP exceeded %d cubes.\n", nCubeLim ); else printf( "The best cover contains %d cubes.\n", Vec_StrSize(vRes)/(nVars +3) ); Abc_PrintTime( 1, "Onset minterm", Time[0][0] ); Abc_PrintTime( 1, "Onset expand ", Time[0][1] ); Abc_PrintTime( 1, "Offset minterm", Time[1][0] ); Abc_PrintTime( 1, "Offset expand ", Time[1][1] ); if ( fProfile ) { Abc_PrintTime( 1, "Expand check1 ", clkCheck1 ); clkCheck1 = 0; Abc_PrintTime( 1, "Expand check2 ", clkCheck2 ); clkCheck2 = 0; Abc_PrintTime( 1, "Expand sat ", clkCheckS ); clkCheckS = 0; Abc_PrintTime( 1, "Expand unsat ", clkCheckU ); clkCheckU = 0; } } Vec_StrFreeP( &vSop[0] ); Vec_StrFreeP( &vSop[1] ); return vRes; } Vec_Str_t * Bmc_CollapseOne3( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); sat_solver * pSat0 = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); sat_solver * pSat1 = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); sat_solver * pSat2 = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); sat_solver * pSat3 = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); Vec_Str_t * vSop = Bmc_CollapseOne_int3( pSat0, pSat1, pSat2, pSat3, Gia_ManCiNum(p), nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); sat_solver_delete( pSat0 ); sat_solver_delete( pSat1 ); sat_solver_delete( pSat2 ); sat_solver_delete( pSat3 ); Cnf_DataFree( pCnf ); return vSop; } /**Function************************************************************* Synopsis [This code computes on-set and off-set simultaneously.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOne_int2( sat_solver * pSat1, sat_solver * pSat2, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { int fVeryVerbose = fVerbose; sat_solver * pSat[2] = { pSat1, pSat2 }; Vec_Str_t * vSop[2] = { Vec_StrAlloc(1000), Vec_StrAlloc(1000) }, * vRes = NULL; Vec_Int_t * vVars = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vLits = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vNums = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vCube = Vec_IntAlloc( nVars+1 ); int n, v, iVar, pLits[2], iCube = 0, Start, status; abctime clk = 0, Time[2][2] = {{0}}; int fComplete[2] = {0}; // variables int iOutVar = 2; int iOOVars[2] = {0, 1}; // int iOutVar = 1; // int iOOVars[2] = {sat_solver_nvars(pSat) - 5, sat_solver_nvars(pSat) - 5 + 1}; // collect CI variables (0 = onset enable, 1 = offset enable, 2 = output) int iCiVarBeg = 3; // int iCiVarBeg = sat_solver_nvars(pSat) - 5 - nVars; if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); // check that on-set/off-set is sat for ( n = 0; n < 2; n++ ) { pLits[0] = Abc_Var2Lit( iOutVar, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat[n], pLits, pLits + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { Vec_StrClear( vSop[0] ); Vec_StrPrintStr( vSop[0], n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop[0], '\0' ); fComplete[0] = 1; goto cleanup; // const0/1 } // add literals to the solver status = sat_solver_addclause( pSat[n], pLits, pLits + 1 ); assert( status ); // start cover Vec_StrPush( vSop[n], '\0' ); } // compute cube pairs for ( iCube = 0; nCubeLim == 0 || iCube < nCubeLim; iCube++ ) { for ( n = 0; n < 2; n++ ) { if ( fVeryVerbose ) clk = Abc_Clock(); // get the assignment sat_solver_clean_polarity( pSat[n], Vec_IntArray(vVars), Vec_IntSize(vVars) ); pLits[0] = Abc_Var2Lit( iOOVars[n], 1 ); // enable clauses // pLits[1] = Abc_Var2Lit( iOutVar, n ); // set output // status = sat_solver_solve( pSat, pLits, pLits + 2, 0, 0, 0, 0 ); status = sat_solver_solve( pSat[n], pLits, pLits + 1, 0, 0, 0, 0 ); if ( fVeryVerbose ) Time[n][0] += Abc_Clock() - clk; if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { fComplete[n] = 1; break; } // collect values Vec_IntClear( vLits ); Vec_IntForEachEntry( vVars, iVar, v ) Vec_IntPush( vLits, Abc_Var2Lit(iVar, !sat_solver_var_value(pSat[n], iVar)) ); // expand the values if ( fVeryVerbose ) clk = Abc_Clock(); // status = Bmc_CollapseExpand( pSat, NULL, vLits, vNums, vCube, nBTLimit, fCanon, Abc_Var2Lit(iOutVar, !n) ); status = Bmc_CollapseExpand( pSat[!n], NULL, vLits, vNums, vCube, nBTLimit, fCanon, -1 ); if ( fVeryVerbose ) Time[n][1] += Abc_Clock() - clk; if ( status < 0 ) goto cleanup; // timeout // collect cube Vec_StrPop( vSop[n] ); Start = Vec_StrSize( vSop[n] ); Vec_StrFillExtra( vSop[n], Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 1, (char)(n ? '0' : '1') ); Vec_StrWriteEntry( vSop[n], Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntPush( vCube, Abc_Var2Lit( iOOVars[n], 0 ) ); Vec_IntForEachEntry( vNums, iVar, v ) { int iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop[n], Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop[n], Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } // add cube // status = sat_solver_addclause( pSat, Vec_IntArray(vCube), Vec_IntLimit(vCube) ); status = sat_solver_addclause( pSat[n], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) { fComplete[n] = 1; break; } assert( status == 1 ); } if ( fComplete[0] || fComplete[1] ) break; } cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); assert( !fComplete[0] || !fComplete[1] ); if ( fComplete[0] || fComplete[1] ) // one of the cover is computed { vRes = vSop[fComplete[1]]; vSop[fComplete[1]] = NULL; if ( iCube > 1 ) // Bmc_CollapseIrredundant( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); Bmc_CollapseIrredundantFull( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); } if ( fVeryVerbose ) { int fProfile = 0; printf( "Processed output with %d supp vars. ", nVars ); if ( vRes == NULL ) printf( "The resulting SOP exceeded %d cubes.\n", nCubeLim ); else printf( "The best cover contains %d cubes.\n", Vec_StrSize(vRes)/(nVars +3) ); Abc_PrintTime( 1, "Onset minterm", Time[0][0] ); Abc_PrintTime( 1, "Onset expand ", Time[0][1] ); Abc_PrintTime( 1, "Offset minterm", Time[1][0] ); Abc_PrintTime( 1, "Offset expand ", Time[1][1] ); if ( fProfile ) { Abc_PrintTime( 1, "Expand check1 ", clkCheck1 ); clkCheck1 = 0; Abc_PrintTime( 1, "Expand check2 ", clkCheck2 ); clkCheck2 = 0; Abc_PrintTime( 1, "Expand sat ", clkCheckS ); clkCheckS = 0; Abc_PrintTime( 1, "Expand unsat ", clkCheckU ); clkCheckU = 0; } } Vec_StrFreeP( &vSop[0] ); Vec_StrFreeP( &vSop[1] ); return vRes; } /**Function************************************************************* Synopsis [This code computes on-set and off-set simultaneously.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOne_int( sat_solver * pSat, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { int fVeryVerbose = fVerbose; Vec_Str_t * vSop[2] = { Vec_StrAlloc(1000), Vec_StrAlloc(1000) }, * vRes = NULL; Vec_Int_t * vVars = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vLits = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vNums = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vCube = Vec_IntAlloc( nVars+1 ); int n, v, iVar, pLits[2], iCube = 0, Start, status; abctime clk = 0, Time[2][2] = {{0}}; int fComplete[2] = {0}; // variables int iOutVar = 2; int iOOVars[2] = {0, 1}; // int iOutVar = 1; // int iOOVars[2] = {sat_solver_nvars(pSat) - 5, sat_solver_nvars(pSat) - 5 + 1}; // collect CI variables (0 = onset enable, 1 = offset enable, 2 = output) int iCiVarBeg = 3; // int iCiVarBeg = sat_solver_nvars(pSat) - 5 - nVars; if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); // check that on-set/off-set is sat for ( n = 0; n < 2; n++ ) { pLits[0] = Abc_Var2Lit( iOutVar, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat, pLits, pLits + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { Vec_StrClear( vSop[0] ); Vec_StrPrintStr( vSop[0], n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop[0], '\0' ); fComplete[0] = 1; goto cleanup; // const0/1 } // start cover Vec_StrPush( vSop[n], '\0' ); } // compute cube pairs for ( iCube = 0; nCubeLim == 0 || iCube < nCubeLim; iCube++ ) { for ( n = 0; n < 2; n++ ) { if ( fVeryVerbose ) clk = Abc_Clock(); // get the assignment sat_solver_clean_polarity( pSat, Vec_IntArray(vVars), Vec_IntSize(vVars) ); pLits[0] = Abc_Var2Lit( iOutVar, n ); // set output pLits[1] = Abc_Var2Lit( iOOVars[n], 1 ); // enable clauses status = sat_solver_solve( pSat, pLits, pLits + 2, 0, 0, 0, 0 ); if ( fVeryVerbose ) Time[n][0] += Abc_Clock() - clk; if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { fComplete[n] = 1; break; } // collect values Vec_IntClear( vLits ); Vec_IntForEachEntry( vVars, iVar, v ) Vec_IntPush( vLits, Abc_Var2Lit(iVar, !sat_solver_var_value(pSat, iVar)) ); // expand the values if ( fVeryVerbose ) clk = Abc_Clock(); status = Bmc_CollapseExpand( pSat, NULL, vLits, vNums, vCube, nBTLimit, fCanon, Abc_Var2Lit(iOutVar, !n) ); if ( fVeryVerbose ) Time[n][1] += Abc_Clock() - clk; if ( status < 0 ) goto cleanup; // timeout // collect cube Vec_StrPop( vSop[n] ); Start = Vec_StrSize( vSop[n] ); Vec_StrFillExtra( vSop[n], Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 1, (char)(n ? '0' : '1') ); Vec_StrWriteEntry( vSop[n], Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntPush( vCube, Abc_Var2Lit( iOOVars[n], 0 ) ); Vec_IntForEachEntry( vNums, iVar, v ) { int iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop[n], Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop[n], Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } // add cube status = sat_solver_addclause( pSat, Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) { fComplete[n] = 1; break; } assert( status == 1 ); } if ( fComplete[0] || fComplete[1] ) break; } cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); assert( !fComplete[0] || !fComplete[1] ); if ( fComplete[0] || fComplete[1] ) // one of the cover is computed { vRes = vSop[fComplete[1]]; vSop[fComplete[1]] = NULL; if ( iCube > 1 ) // Bmc_CollapseIrredundant( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); Bmc_CollapseIrredundantFull( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); } if ( fVeryVerbose ) { int fProfile = 0; printf( "Processed output with %d supp vars. ", nVars ); if ( vRes == NULL ) printf( "The resulting SOP exceeded %d cubes.\n", nCubeLim ); else printf( "The best cover contains %d cubes.\n", Vec_StrSize(vRes)/(nVars +3) ); Abc_PrintTime( 1, "Onset minterm", Time[0][0] ); Abc_PrintTime( 1, "Onset expand ", Time[0][1] ); Abc_PrintTime( 1, "Offset minterm", Time[1][0] ); Abc_PrintTime( 1, "Offset expand ", Time[1][1] ); if ( fProfile ) { Abc_PrintTime( 1, "Expand check1 ", clkCheck1 ); clkCheck1 = 0; Abc_PrintTime( 1, "Expand check2 ", clkCheck2 ); clkCheck2 = 0; Abc_PrintTime( 1, "Expand sat ", clkCheckS ); clkCheckS = 0; Abc_PrintTime( 1, "Expand unsat ", clkCheckU ); clkCheckU = 0; } } Vec_StrFreeP( &vSop[0] ); Vec_StrFreeP( &vSop[1] ); return vRes; } Vec_Str_t * Bmc_CollapseOne( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); Vec_Str_t * vSop = Bmc_CollapseOne_int( pSat, Gia_ManCiNum(p), nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); return vSop; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcEco.c000066400000000000000000000247731300674244400227350ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcEco.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcEco.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes miter for ECO with given root node and fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Bmc_EcoMiter( Gia_Man_t * pGold, Gia_Man_t * pOld, Vec_Int_t * vFans ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pRoot = Gia_ObjFanin0( Gia_ManPo(pOld, Gia_ManPoNum(pOld)-1) ); // fanin of the last PO Gia_Obj_t * pObj; int i, NewPi, Miter; assert( Gia_ManCiNum(pGold) == Gia_ManCiNum(pOld) ); assert( Gia_ManCoNum(pGold) == Gia_ManCoNum(pOld) - 1 ); assert( Gia_ObjIsAnd(pRoot) ); // create the miter pNew = Gia_ManStart( 3 * Gia_ManObjNum(pGold) ); pNew->pName = Abc_UtilStrsav( pGold->pName ); Gia_ManHashAlloc( pNew ); // copy gold Gia_ManConst0(pGold)->Value = 0; Gia_ManForEachCi( pGold, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); NewPi = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( pGold, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( pGold, pObj, i ) pObj->Value = Gia_ObjFanin0Copy( pObj ); // create onset Gia_ManConst0(pOld)->Value = 0; Gia_ManForEachCi( pOld, pObj, i ) pObj->Value = Gia_ManCi(pGold, i)->Value; Gia_ManForEachAnd( pOld, pObj, i ) if ( pObj == pRoot ) pObj->Value = NewPi; else pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( pOld, pObj, i ) pObj->Value = Gia_ObjFanin0Copy( pObj ); Gia_ManForEachCo( pGold, pObj, i ) Gia_ManAppendCo( pNew, Gia_ManHashXor(pNew, pObj->Value, Gia_ManCo(pOld, i)->Value) ); // create offset Gia_ManForEachAnd( pOld, pObj, i ) if ( pObj == pRoot ) pObj->Value = Abc_LitNot(NewPi); else pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( pOld, pObj, i ) pObj->Value = Gia_ObjFanin0Copy( pObj ); Miter = 0; Gia_ManForEachCo( pGold, pObj, i ) Miter = Gia_ManHashOr( pNew, Miter, Gia_ManHashXor(pNew, pObj->Value, Gia_ManCo(pOld, i)->Value) ); Gia_ManAppendCo( pNew, Miter ); // add outputs for the nodes Gia_ManForEachObjVec( vFans, pOld, pObj, i ) Gia_ManAppendCo( pNew, pObj->Value ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); assert( Gia_ManPiNum(pNew) == Gia_ManCiNum(pGold) + 1 ); assert( Gia_ManPoNum(pNew) == Gia_ManCoNum(pGold) + 1 + Vec_IntSize(vFans) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p ) { Cnf_Dat_t * pCnf; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); pAig->nRegs = 0; pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Aig_ManStop( pAig ); return pCnf; } /**Function************************************************************* Synopsis [Solve the enumeration problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_EcoSolve( sat_solver * pSat, int Root, Vec_Int_t * vVars ) { int nBTLimit = 1000000; Vec_Int_t * vLits = Vec_IntAlloc( Vec_IntSize(vVars) ); int status, i, Div, iVar, nFinal, * pFinal, nIter = 0, RetValue = 0; int pLits[2], nVars = sat_solver_nvars( pSat ); sat_solver_setnvars( pSat, nVars + 1 ); pLits[0] = Abc_Var2Lit( Root, 0 ); // F = 1 pLits[1] = Abc_Var2Lit( nVars, 0 ); // iNewLit while ( 1 ) { // find onset minterm status = sat_solver_solve( pSat, pLits, pLits + 2, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) { RetValue = -1; break; } if ( status == l_False ) { RetValue = 1; break; } assert( status == l_True ); // collect divisor literals Vec_IntClear( vLits ); Vec_IntPush( vLits, Abc_LitNot(pLits[0]) ); // F = 0 Vec_IntForEachEntry( vVars, Div, i ) Vec_IntPush( vLits, sat_solver_var_literal(pSat, Div) ); // check against offset status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) { RetValue = -1; break; } if ( status == l_True ) break; assert( status == l_False ); // compute cube and add clause nFinal = sat_solver_final( pSat, &pFinal ); Vec_IntClear( vLits ); Vec_IntPush( vLits, Abc_LitNot(pLits[1]) ); // NOT(iNewLit) printf( "Cube %d : ", nIter ); for ( i = 0; i < nFinal; i++ ) { if ( pFinal[i] == pLits[0] ) continue; Vec_IntPush( vLits, pFinal[i] ); iVar = Vec_IntFind( vVars, Abc_Lit2Var(pFinal[i]) ); assert( iVar >= 0 ); printf( "%s%d ", Abc_LitIsCompl(pFinal[i]) ? "+":"-", iVar ); } printf( "\n" ); status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); assert( status ); nIter++; } // assert( status == l_True ); Vec_IntFree( vLits ); return RetValue; } /**Function************************************************************* Synopsis [Compute the patch function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_EcoPatch( Gia_Man_t * p, int nIns, int nOuts ) { int i, Lit, RetValue, Root; Gia_Obj_t * pObj; Vec_Int_t * vVars; // generate CNF and solver Cnf_Dat_t * pCnf = Cnf_DeriveGiaRemapped( p ); sat_solver * pSat = sat_solver_new(); sat_solver_setnvars( pSat, pCnf->nVars ); // add timeframe clauses for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) assert( 0 ); // add equality constraints assert( Gia_ManPoNum(p) == nOuts + 1 + nIns ); Gia_ManForEachPo( p, pObj, i ) { if ( i == nOuts ) break; Lit = Abc_Var2Lit( pCnf->pVarNums[Gia_ObjId(p, pObj)], 1 ); // neg lit RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( RetValue ); } // add inequality constraint pObj = Gia_ManPo( p, nOuts ); Lit = Abc_Var2Lit( pCnf->pVarNums[Gia_ObjId(p, pObj)], 0 ); // pos lit RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( RetValue ); // simplify the SAT solver RetValue = sat_solver_simplify( pSat ); assert( RetValue ); // collect input variables vVars = Vec_IntAlloc( nIns ); Gia_ManForEachPo( p, pObj, i ) if ( i >= nOuts + 1 ) Vec_IntPush( vVars, pCnf->pVarNums[Gia_ObjId(p, pObj)] ); assert( Vec_IntSize(vVars) == nIns ); // derive the root variable pObj = Gia_ManPi( p, Gia_ManPiNum(p) - 1 ); Root = pCnf->pVarNums[Gia_ObjId(p, pObj)]; // solve the problem RetValue = Bmc_EcoSolve( pSat, Root, vVars ); Vec_IntFree( vVars ); return RetValue; } /**Function************************************************************* Synopsis [Tests the ECO miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_EcoMiterTest() { char * pFileGold = "eco_gold.aig"; char * pFileOld = "eco_old.aig"; Vec_Int_t * vFans; FILE * pFile; Gia_Man_t * pMiter; Gia_Obj_t * pObj; Gia_Man_t * pGold; Gia_Man_t * pOld; int i, RetValue; // check that the files exist pFile = fopen( pFileGold, "r" ); if ( pFile == NULL ) { printf( "File \"%s\" does not exist.\n", pFileGold ); return; } fclose( pFile ); pFile = fopen( pFileOld, "r" ); if ( pFile == NULL ) { printf( "File \"%s\" does not exist.\n", pFileOld ); return; } fclose( pFile ); // read files pGold = Gia_AigerRead( pFileGold, 0, 0, 0 ); pOld = Gia_AigerRead( pFileOld, 0, 0, 0 ); // create ECO miter vFans = Vec_IntAlloc( Gia_ManCiNum(pOld) ); Gia_ManForEachCi( pOld, pObj, i ) Vec_IntPush( vFans, Gia_ObjId(pOld, pObj) ); pMiter = Bmc_EcoMiter( pGold, pOld, vFans ); Vec_IntFree( vFans ); Gia_AigerWrite( pMiter, "eco_miter.aig", 0, 0 ); // find the patch RetValue = Bmc_EcoPatch( pMiter, Gia_ManCiNum(pGold), Gia_ManCoNum(pGold) ); if ( RetValue == 1 ) printf( "Patch is computed.\n" ); if ( RetValue == 0 ) printf( "Cannot be patched.\n" ); if ( RetValue == -1 ) printf( "Resource limit exceeded.\n" ); Gia_ManStop( pMiter ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcExpand.c000066400000000000000000000135171300674244400234400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcExpand.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Expanding cubes against the offset.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcExpand.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // iterator thought the cubes #define Bmc_SopForEachCube( pSop, nVars, pCube ) for ( pCube = (pSop); *pCube; pCube += (nVars) + 3 ) extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Expands cubes against the offset given as an AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjExpandCubesTry( Vec_Str_t * vSop, sat_solver * pSat, Vec_Int_t * vVars ) { extern int Bmc_CollapseExpandRound( sat_solver * pSat, sat_solver * pSatOn, Vec_Int_t * vLits, Vec_Int_t * vNums, Vec_Int_t * vTemp, int nBTLimit, int fCanon, int fOnOffSetLit ); char * pCube, * pSop = Vec_StrArray(vSop); int nCubes = Abc_SopGetCubeNum(pSop); int nVars = Abc_SopGetVarNum(pSop); Vec_Int_t * vLits = Vec_IntAlloc( nVars ); Vec_Int_t * vTemp = Vec_IntAlloc( nVars ); assert( nVars == Vec_IntSize(vVars) ); assert( Vec_StrSize(vSop) == nCubes * (nVars + 3) + 1 ); Bmc_SopForEachCube( pSop, nVars, pCube ) { int k, Entry; // collect literals and clean cube Vec_IntFill( vLits, nVars, -1 ); for ( k = 0; k < nVars; k++ ) { if ( pCube[k] == '-' ) continue; Vec_IntWriteEntry( vLits, k, Abc_Var2Lit(Vec_IntEntry(vVars, k), pCube[k] == '0') ); pCube[k] = '-'; } // expand cube Bmc_CollapseExpandRound( pSat, NULL, vLits, NULL, vTemp, 0, 0, -1 ); // insert literals Vec_IntForEachEntry( vLits, Entry, k ) if ( Entry != -1 ) pCube[k] = '1' - Abc_LitIsCompl(Entry); } Vec_IntFree( vLits ); Vec_IntFree( vTemp ); return nCubes; } int Abc_ObjExpandCubes( Vec_Str_t * vSop, Gia_Man_t * p, int nVars ) { extern int Bmc_CollapseIrredundantFull( Vec_Str_t * vSop, int nCubes, int nVars ); int fReverse = 0; Vec_Int_t * vVars = Vec_IntAlloc( nVars ); Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); int v, n, iLit, status, nCubesNew, iCiVarBeg = sat_solver_nvars(pSat) - nVars; // check that on-set/off-set is sat int iOutVar = 1; for ( n = 0; n < 2; n++ ) { iLit = Abc_Var2Lit( iOutVar, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat, &iLit, &iLit + 1, 0, 0, 0, 0 ); if ( status == l_False ) { Vec_StrClear( vSop ); Vec_StrPrintStr( vSop, n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop, '\0' ); return 1; } } // add literals to the solver iLit = Abc_Var2Lit( iOutVar, 1 ); status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status ); // collect variables if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); nCubesNew = Abc_ObjExpandCubesTry( vSop, pSat, vVars ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Vec_IntFree( vVars ); if ( nCubesNew > 1 ) Bmc_CollapseIrredundantFull( vSop, nCubesNew, nVars ); return 0; } void Abc_NtkExpandCubes( Abc_Ntk_t * pNtk, Gia_Man_t * pGia, int fVerbose ) { Gia_Man_t * pNew; Abc_Obj_t * pObj; int i; Vec_Str_t * vSop = Vec_StrAlloc( 1000 ); assert( Abc_NtkIsSopLogic(pNtk) ); assert( Abc_NtkCiNum(pNtk) == Gia_ManCiNum(pGia) ); assert( Abc_NtkCoNum(pNtk) == Gia_ManCoNum(pGia) ); Abc_NtkForEachCo( pNtk, pObj, i ) { pObj = Abc_ObjFanin0(pObj); if ( !Abc_ObjIsNode(pObj) || Abc_ObjFaninNum(pObj) == 0 ) continue; assert( Abc_ObjFaninNum(pObj) == Gia_ManCiNum(pGia) ); Vec_StrClear( vSop ); Vec_StrAppend( vSop, (char *)pObj->pData ); Vec_StrPush( vSop, '\0' ); pNew = Gia_ManDupCones( pGia, &i, 1, 0 ); assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(pGia) ); if ( Abc_ObjExpandCubes( vSop, pNew, Abc_ObjFaninNum(pObj) ) ) Vec_IntClear( &pObj->vFanins ); Gia_ManStop( pNew ); pObj->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, Vec_StrArray(vSop) ); } Vec_StrFree( vSop ); Abc_NtkSortSops( pNtk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcFault.c000066400000000000000000001672641300674244400233050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcFault.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Checking for functional faults.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcFault.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define FFTEST_MAX_VARS 2 #define FFTEST_MAX_PARS 8 //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ParFfSetDefault( Bmc_ParFf_t * p ) { memset( p, 0, sizeof(Bmc_ParFf_t) ); p->pFileName = NULL; p->Algo = 0; p->fStartPats = 0; p->nTimeOut = 0; p->nIterCheck = 0; p->fBasic = 0; p->fFfOnly = 0; p->fDump = 0; p->fDumpUntest = 0; p->fVerbose = 0; } /**Function************************************************************* Synopsis [Adds a general cardinality constraint in terms of vVars.] Description [Strict is "exactly K out of N". Non-strict is "less or equal than K out of N".] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cnf_AddSorder( sat_solver * p, int * pVars, int i, int k, int * pnVars ) { int iVar1 = (*pnVars)++; int iVar2 = (*pnVars)++; sat_solver_add_and( p, iVar1, pVars[i], pVars[k], 1, 1, 1 ); sat_solver_add_and( p, iVar2, pVars[i], pVars[k], 0, 0, 0 ); pVars[i] = iVar1; pVars[k] = iVar2; } static inline void Cnf_AddCardinConstrMerge( sat_solver * p, int * pVars, int lo, int hi, int r, int * pnVars ) { int i, step = r * 2; if ( step < hi - lo ) { Cnf_AddCardinConstrMerge( p, pVars, lo, hi-r, step, pnVars ); Cnf_AddCardinConstrMerge( p, pVars, lo+r, hi, step, pnVars ); for ( i = lo+r; i < hi-r; i += step ) Cnf_AddSorder( p, pVars, i, i+r, pnVars ); } } static inline void Cnf_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++ ) Cnf_AddSorder( p, pVars, i, i + (hi - lo + 1) / 2, pnVars ); Cnf_AddCardinConstrRange( p, pVars, lo, mid, pnVars ); Cnf_AddCardinConstrRange( p, pVars, mid+1, hi, pnVars ); Cnf_AddCardinConstrMerge( p, pVars, lo, hi, 1, pnVars ); } } void Cnf_AddCardinConstrPairWise( sat_solver * p, Vec_Int_t * vVars, int K, int fStrict ) { int nVars = sat_solver_nvars(p); int nSizeOld = Vec_IntSize(vVars); int i, iVar, nSize, Lit, nVarsOld; assert( nSizeOld >= 2 ); // check that vars are ok Vec_IntForEachEntry( vVars, iVar, i ) assert( iVar >= 0 && iVar < nVars ); // make the size a degree of two for ( nSize = 1; nSize < nSizeOld; nSize *= 2 ); // extend sat_solver_setnvars( p, nVars + 1 + nSize * nSize / 2 ); if ( nSize != nSizeOld ) { // fill in with const0 Vec_IntFillExtra( vVars, nSize, nVars ); // add const0 variable Lit = Abc_Var2Lit( nVars++, 1 ); if ( !sat_solver_addclause( p, &Lit, &Lit+1 ) ) assert( 0 ); } // construct recursively nVarsOld = nVars; Cnf_AddCardinConstrRange( p, Vec_IntArray(vVars), 0, nSize - 1, &nVars ); // add final constraint assert( K > 0 && K < nSizeOld ); Lit = Abc_Var2Lit( Vec_IntEntry(vVars, K), 1 ); if ( !sat_solver_addclause( p, &Lit, &Lit+1 ) ) assert( 0 ); if ( fStrict ) { Lit = Abc_Var2Lit( Vec_IntEntry(vVars, K-1), 0 ); if ( !sat_solver_addclause( p, &Lit, &Lit+1 ) ) assert( 0 ); } // return to the old size Vec_IntShrink( vVars, 0 ); // make it unusable //printf( "The %d input sorting network contains %d sorters.\n", nSize, (nVars - nVarsOld)/2 ); } /**Function************************************************************* Synopsis [Adds a general cardinality constraint in terms of vVars.] Description [Strict is "exactly K out of N". Non-strict is "less or equal than K out of N".] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cnf_AddCardinVar( int Level, int Base, Vec_Int_t * vVars, int k ) { return Level ? Base + k : Vec_IntEntry( vVars, k ); } void Cnf_AddCardinConstrGeneral( sat_solver * p, Vec_Int_t * vVars, int K, int fStrict ) { int i, k, iCur, iNext, iVar, Lit; int nVars = sat_solver_nvars(p); int nBits = Vec_IntSize(vVars); Vec_IntForEachEntry( vVars, iVar, i ) assert( iVar >= 0 && iVar < nVars ); sat_solver_setnvars( p, nVars + nBits * nBits ); for ( i = 0; i < nBits; i++ ) { iCur = nVars + nBits * (i-1); iNext = nVars + nBits * i; if ( i & 1 ) sat_solver_add_buffer( p, iNext, Cnf_AddCardinVar(i, iCur, vVars, 0), 0 ); for ( k = i & 1; k + 1 < nBits; k += 2 ) { sat_solver_add_and( p, iNext+k , Cnf_AddCardinVar(i, iCur, vVars, k), Cnf_AddCardinVar(i, iCur, vVars, k+1), 1, 1, 1 ); sat_solver_add_and( p, iNext+k+1, Cnf_AddCardinVar(i, iCur, vVars, k), Cnf_AddCardinVar(i, iCur, vVars, k+1), 0, 0, 0 ); } if ( k == nBits - 1 ) sat_solver_add_buffer( p, iNext + nBits-1, Cnf_AddCardinVar(i, iCur, vVars, nBits-1), 0 ); } // add final constraint assert( K > 0 && K < nBits ); Lit = Abc_Var2Lit( nVars + nBits * (nBits - 1) + K, 1 ); if ( !sat_solver_addclause( p, &Lit, &Lit+1 ) ) assert( 0 ); if ( fStrict ) { Lit = Abc_Var2Lit( nVars + nBits * (nBits - 1) + K - 1, 0 ); if ( !sat_solver_addclause( p, &Lit, &Lit+1 ) ) assert( 0 ); } } /**Function************************************************************* Synopsis [Add constraint that no more than 1 variable is 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cnf_AddCardinConstr( sat_solver * p, Vec_Int_t * vVars ) { int i, k, pLits[2], iVar, nVars = sat_solver_nvars(p); Vec_IntForEachEntry( vVars, iVar, i ) assert( iVar >= 0 && iVar < nVars ); iVar = nVars; sat_solver_setnvars( p, nVars + Vec_IntSize(vVars) - 1 ); while ( Vec_IntSize(vVars) > 1 ) { for ( k = i = 0; i < Vec_IntSize(vVars)/2; i++ ) { pLits[0] = Abc_Var2Lit( Vec_IntEntry(vVars, 2*i), 1 ); pLits[1] = Abc_Var2Lit( Vec_IntEntry(vVars, 2*i+1), 1 ); sat_solver_addclause( p, pLits, pLits + 2 ); sat_solver_add_and( p, iVar, Vec_IntEntry(vVars, 2*i), Vec_IntEntry(vVars, 2*i+1), 1, 1, 1 ); Vec_IntWriteEntry( vVars, k++, iVar++ ); } if ( Vec_IntSize(vVars) & 1 ) Vec_IntWriteEntry( vVars, k++, Vec_IntEntryLast(vVars) ); Vec_IntShrink( vVars, k ); } return iVar; } void Cnf_AddCardinConstrTest() { int i, status, Count = 1, nVars = 8; Vec_Int_t * vVars = Vec_IntStartNatural( nVars ); sat_solver * pSat = sat_solver_new(); sat_solver_setnvars( pSat, nVars ); //Cnf_AddCardinConstr( pSat, vVars ); Cnf_AddCardinConstrPairWise( pSat, vVars, 2, 1 ); while ( 1 ) { status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); if ( status != l_True ) break; Vec_IntClear( vVars ); printf( "%3d : ", Count++ ); for ( i = 0; i < nVars; i++ ) { Vec_IntPush( vVars, 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(vVars), Vec_IntArray(vVars) + Vec_IntSize(vVars) ); if ( status == 0 ) break; } sat_solver_delete( pSat ); Vec_IntFree( vVars ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p ) { Cnf_Dat_t * pCnf; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); pAig->nRegs = 0; pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Aig_ManStop( pAig ); return pCnf; // return Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cnf_DataLiftGia( Cnf_Dat_t * p, Gia_Man_t * pGia, int nVarsPlus ) { Gia_Obj_t * pObj; int v; Gia_ManForEachObj( pGia, pObj, v ) if ( p->pVarNums[Gia_ObjId(pGia, pObj)] >= 0 ) p->pVarNums[Gia_ObjId(pGia, pObj)] += nVarsPlus; for ( v = 0; v < p->nLiterals; v++ ) p->pClauses[0][v] += 2*nVarsPlus; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFaultUnfold( Gia_Man_t * p, int fUseMuxes, int fFfOnly ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iCtrl, iThis; pNew = Gia_ManStart( (2 + 3 * fUseMuxes) * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; // add first timeframe Gia_ManForEachRo( p, pObj, i ) pObj->Value = Gia_ManAppendCi( 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) ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); // add second timeframe Gia_ManForEachRo( p, pObj, i ) pObj->Value = Gia_ObjRoToRi(p, pObj)->Value; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); if ( fFfOnly ) { 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) ); Gia_ManForEachRi( p, pObj, i ) { iCtrl = Gia_ManAppendCi(pNew); iThis = Gia_ObjFanin0Copy(pObj); if ( fUseMuxes ) pObj->Value = Gia_ManHashMux( pNew, iCtrl, pObj->Value, iThis ); else pObj->Value = iThis; pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); } } else { Gia_ManForEachAnd( p, pObj, i ) { iCtrl = Gia_ManAppendCi(pNew); iThis = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( fUseMuxes ) pObj->Value = Gia_ManHashMux( pNew, iCtrl, pObj->Value, iThis ); else pObj->Value = iThis; } 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) == Gia_ManRegNum(p) + 2 * Gia_ManPiNum(p) + (fFfOnly ? Gia_ManRegNum(p) : Gia_ManAndNum(p)) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManStuckAtUnfold( Gia_Man_t * p, Vec_Int_t * vMap ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iFuncVars = 0; pNew = Gia_ManStart( 3 * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); 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) ); if ( Vec_IntEntry(vMap, iFuncVars++) ) pObj->Value = Gia_ManHashAnd( pNew, Abc_LitNot(Gia_ManAppendCi(pNew)), pObj->Value ); else Gia_ManAppendCi(pNew); if ( Vec_IntEntry(vMap, iFuncVars++) ) pObj->Value = Gia_ManHashOr( pNew, Gia_ManAppendCi(pNew), pObj->Value ); else Gia_ManAppendCi(pNew); } assert( iFuncVars == Vec_IntSize(vMap) ); 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) == Gia_ManCiNum(p) + 2 * Gia_ManAndNum(p) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFlipUnfold( Gia_Man_t * p, Vec_Int_t * vMap ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iFuncVars = 0; pNew = Gia_ManStart( 4 * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); 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) ); if ( Vec_IntEntry(vMap, iFuncVars++) ) pObj->Value = Gia_ManHashXor( pNew, Gia_ManAppendCi(pNew), pObj->Value ); else Gia_ManAppendCi(pNew); } assert( iFuncVars == Vec_IntSize(vMap) ); 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) == Gia_ManCiNum(p) + Gia_ManAndNum(p) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFOFUnfold( Gia_Man_t * p, Vec_Int_t * vMap ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iCtrl0, iCtrl1, iCtrl2, iCtrl3, iMuxA, iMuxB, iFuncVars = 0; pNew = Gia_ManStart( 9 * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( p, pObj, i ) { if ( Vec_IntEntry(vMap, iFuncVars++) ) iCtrl0 = Gia_ManAppendCi(pNew); else iCtrl0 = 0, Gia_ManAppendCi(pNew); if ( Vec_IntEntry(vMap, iFuncVars++) ) iCtrl1 = Gia_ManAppendCi(pNew); else iCtrl1 = 0, Gia_ManAppendCi(pNew); if ( Vec_IntEntry(vMap, iFuncVars++) ) iCtrl2 = Gia_ManAppendCi(pNew); else iCtrl2 = 0, Gia_ManAppendCi(pNew); if ( Vec_IntEntry(vMap, iFuncVars++) ) iCtrl3 = Gia_ManAppendCi(pNew); else iCtrl3 = 0, Gia_ManAppendCi(pNew); if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) iCtrl0 = Abc_LitNot(iCtrl0); else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) iCtrl1 = Abc_LitNot(iCtrl1); else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) iCtrl2 = Abc_LitNot(iCtrl2); else //if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) iCtrl3 = Abc_LitNot(iCtrl3); iMuxA = Gia_ManHashMux( pNew, Gia_ObjFanin0(pObj)->Value, iCtrl1, iCtrl0 ); iMuxB = Gia_ManHashMux( pNew, Gia_ObjFanin0(pObj)->Value, iCtrl3, iCtrl2 ); pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin1(pObj)->Value, iMuxB, iMuxA ); } assert( iFuncVars == Vec_IntSize(vMap) ); 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) == Gia_ManCiNum(p) + 4 * Gia_ManAndNum(p) ); return pNew; } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_FormStrCount( char * pStr, int * pnVars, int * pnPars ) { int i, Counter = 0; if ( pStr[0] != '(' ) { printf( "The first symbol should be the opening parenthesis \"(\".\n" ); return 1; } if ( pStr[strlen(pStr)-1] != ')' ) { printf( "The last symbol should be the closing parenthesis \")\".\n" ); return 1; } for ( i = 0; pStr[i]; i++ ) if ( pStr[i] == '(' ) Counter++; else if ( pStr[i] == ')' ) Counter--; if ( Counter != 0 ) { printf( "The number of opening and closing parentheses is not equal.\n" ); return 1; } *pnVars = 0; *pnPars = 0; for ( i = 0; pStr[i]; i++ ) { if ( pStr[i] >= 'a' && pStr[i] <= 'b' ) *pnVars = Abc_MaxInt( *pnVars, pStr[i] - 'a' + 1 ); else if ( pStr[i] >= 'p' && pStr[i] <= 's' ) *pnPars = Abc_MaxInt( *pnPars, pStr[i] - 'p' + 1 ); else if ( pStr[i] == '(' || pStr[i] == ')' ) {} else if ( pStr[i] == '&' || pStr[i] == '|' || pStr[i] == '^' ) {} else if ( pStr[i] == '?' || pStr[i] == ':' ) {} else if ( pStr[i] == '~' ) { if ( pStr[i+1] < 'a' || pStr[i+1] > 'z' ) { printf( "Expecting alphabetic symbol (instead of \"%c\") after negation (~)\n", pStr[i+1] ); return 1; } } else { printf( "Unknown symbol (%c) in the formula (%s)\n", pStr[i], pStr ); return 1; } } if ( *pnVars != FFTEST_MAX_VARS ) { printf( "The number of input variables (%d) should be 2\n", *pnVars ); return 1; } if ( *pnPars < 1 && *pnPars > FFTEST_MAX_PARS ) { printf( "The number of parameters should be between 1 and %d\n", *pnPars ); return 1; } return 0; } void Gia_FormStrTransform( char * pStr, char * pForm ) { int i, k; for ( k = i = 0; pForm[i]; i++ ) { if ( pForm[i] == '~' ) { i++; assert( pForm[i] >= 'a' && pForm[i] <= 'z' ); pStr[k++] = 'A' + pForm[i] - 'a'; } else pStr[k++] = pForm[i]; } pStr[k] = 0; } /**Function************************************************************* Synopsis [Implements fault model formula using functional/parameter vars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Gia_ManFormulaEndToken( char * pForm ) { int Counter = 0; char * pThis; for ( pThis = pForm; *pThis; pThis++ ) { assert( *pThis != '~' ); if ( *pThis == '(' ) Counter++; else if ( *pThis == ')' ) Counter--; if ( Counter == 0 ) return pThis + 1; } assert( 0 ); return NULL; } int Gia_ManRealizeFormula_rec( Gia_Man_t * p, int * pVars, int * pPars, char * pBeg, char * pEnd, int nPars ) { int iFans[3], Oper = -1; char * pEndNew; if ( pBeg + 1 == pEnd ) { if ( pBeg[0] >= 'a' && pBeg[0] <= 'b' ) return pVars[pBeg[0] - 'a']; if ( pBeg[0] >= 'A' && pBeg[0] <= 'B' ) return Abc_LitNot( pVars[pBeg[0] - 'A'] ); if ( pBeg[0] >= 'p' && pBeg[0] <= 'w' ) // pqrstuvw return pPars[pBeg[0] - 'p']; if ( pBeg[0] >= 'P' && pBeg[0] <= 'W' ) return Abc_LitNot( pPars[pBeg[0] - 'P'] ); assert( 0 ); return -1; } if ( pBeg[0] == '(' ) { pEndNew = Gia_ManFormulaEndToken( pBeg ); if ( pEndNew == pEnd ) { assert( pBeg[0] == '(' ); assert( pBeg[pEnd-pBeg-1] == ')' ); return Gia_ManRealizeFormula_rec( p, pVars, pPars, pBeg + 1, pEnd - 1, nPars ); } } // get first part pEndNew = Gia_ManFormulaEndToken( pBeg ); iFans[0] = Gia_ManRealizeFormula_rec( p, pVars, pPars, pBeg, pEndNew, nPars ); Oper = pEndNew[0]; // get second part pBeg = pEndNew + 1; pEndNew = Gia_ManFormulaEndToken( pBeg ); iFans[1] = Gia_ManRealizeFormula_rec( p, pVars, pPars, pBeg, pEndNew, nPars ); // derive the formula if ( Oper == '&' ) return Gia_ManHashAnd( p, iFans[0], iFans[1] ); if ( Oper == '|' ) return Gia_ManHashOr( p, iFans[0], iFans[1] ); if ( Oper == '^' ) return Gia_ManHashXor( p, iFans[0], iFans[1] ); // get third part assert( Oper == '?' ); assert( pEndNew[0] == ':' ); pBeg = pEndNew + 1; pEndNew = Gia_ManFormulaEndToken( pBeg ); iFans[2] = Gia_ManRealizeFormula_rec( p, pVars, pPars, pBeg, pEndNew, nPars ); return Gia_ManHashMux( p, iFans[0], iFans[1], iFans[2] ); } int Gia_ManRealizeFormula( Gia_Man_t * p, int * pVars, int * pPars, char * pStr, int nPars ) { return Gia_ManRealizeFormula_rec( p, pVars, pPars, pStr, pStr + strlen(pStr), nPars ); } Gia_Man_t * Gia_ManFormulaUnfold( Gia_Man_t * p, char * pForm, int fFfOnly ) { char pStr[100]; int Count = 0; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, k, iCtrl[FFTEST_MAX_PARS], iFans[FFTEST_MAX_VARS]; int nVars, nPars; assert( strlen(pForm) < 100 ); Gia_FormStrCount( pForm, &nVars, &nPars ); assert( nVars == 2 ); Gia_FormStrTransform( pStr, pForm ); pNew = Gia_ManStart( 5 * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); if ( fFfOnly ) { Gia_ManCleanMark0( p ); Gia_ManForEachRi( p, pObj, i ) Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ManForEachAnd( p, pObj, i ) { if ( pObj->fMark0 ) { for ( k = 0; k < nPars; k++ ) iCtrl[k] = Gia_ManAppendCi(pNew); iFans[0] = Gia_ObjFanin0Copy(pObj); iFans[1] = Gia_ObjFanin1Copy(pObj); pObj->Value = Gia_ManRealizeFormula( pNew, iFans, iCtrl, pStr, nPars ); Count++; } else pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_ManForEachRi( p, pObj, i ) Gia_ObjFanin0(pObj)->fMark0 = 0; } else { Gia_ManForEachAnd( p, pObj, i ) { for ( k = 0; k < nPars; k++ ) iCtrl[k] = Gia_ManAppendCi(pNew); iFans[0] = Gia_ObjFanin0Copy(pObj); iFans[1] = Gia_ObjFanin1Copy(pObj); pObj->Value = Gia_ManRealizeFormula( pNew, iFans, iCtrl, pStr, nPars ); } } 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) == Gia_ManCiNum(p) + nPars * (fFfOnly ? Count : Gia_ManAndNum(p)) ); // if ( fUseFaults ) // Gia_AigerWrite( pNew, "newfault.aig", 0, 0 ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFaultCofactor( Gia_Man_t * p, Vec_Int_t * vValues ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; 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 ) { pObj->Value = Gia_ManAppendCi( pNew ); if ( i < Vec_IntSize(vValues) ) pObj->Value = Vec_IntEntry( vValues, i ); } 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) == Gia_ManPiNum(p) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDumpTests( Vec_Int_t * vTests, int nIter, char * pFileName ) { FILE * pFile = fopen( pFileName, "wb" ); int i, k, v, nVars = Vec_IntSize(vTests) / nIter; assert( Vec_IntSize(vTests) % nIter == 0 ); for ( v = i = 0; i < nIter; i++, fprintf(pFile, "\n") ) for ( k = 0; k < nVars; k++ ) fprintf( pFile, "%d", Vec_IntEntry(vTests, v++) ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDumpTestsSimulate( 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); // collect flop input values Vec_IntClear( vValues ); Gia_ManForEachRi( p, pObj, k ) Vec_IntPush( vValues, pObj->fMark0 ); assert( Vec_IntSize(vValues) == Gia_ManRegNum(p) ); } void Gia_ManDumpTestsDelay( Vec_Int_t * vTests, int nIter, char * pFileName, Gia_Man_t * p ) { FILE * pFile = fopen( pFileName, "wb" ); Vec_Int_t * vValues = Vec_IntAlloc( Gia_ManCiNum(p) ); int i, v, nVars = Vec_IntSize(vTests) / nIter; assert( Vec_IntSize(vTests) % nIter == 0 ); assert( nVars == 2 * Gia_ManPiNum(p) + Gia_ManRegNum(p) ); for ( i = 0; i < nIter; i++ ) { // collect PIs followed by flops Vec_IntClear( vValues ); for ( v = Gia_ManRegNum(p); v < Gia_ManCiNum(p); v++ ) { fprintf( pFile, "%d", Vec_IntEntry(vTests, i * nVars + v) ); Vec_IntPush( vValues, Vec_IntEntry(vTests, i * nVars + v) ); } for ( v = 0; v < Gia_ManRegNum(p); v++ ) { fprintf( pFile, "%d", Vec_IntEntry(vTests, i * nVars + v) ); Vec_IntPush( vValues, Vec_IntEntry(vTests, i * nVars + v) ); } fprintf( pFile, "\n" ); // derive next-state values Gia_ManDumpTestsSimulate( p, vValues ); // collect PIs followed by flops for ( v = Gia_ManCiNum(p); v < nVars; v++ ) fprintf( pFile, "%d", Vec_IntEntry(vTests, i * nVars + v) ); for ( v = 0; v < Vec_IntSize(vValues); v++ ) fprintf( pFile, "%d", Vec_IntEntry(vValues, v) ); fprintf( pFile, "\n" ); } Gia_ManCleanMark0(p); fclose( pFile ); Vec_IntFree( vValues ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintResults( Gia_Man_t * p, sat_solver * pSat, int nIter, abctime clk ) { FILE * pTable = fopen( "fault_stats.txt", "a+" ); fprintf( pTable, "%s ", Gia_ManName(p) ); fprintf( pTable, "%d ", Gia_ManPiNum(p) ); fprintf( pTable, "%d ", Gia_ManPoNum(p) ); fprintf( pTable, "%d ", Gia_ManRegNum(p) ); fprintf( pTable, "%d ", Gia_ManAndNum(p) ); fprintf( pTable, "%d ", sat_solver_nvars(pSat) ); fprintf( pTable, "%d ", sat_solver_nclauses(pSat) ); fprintf( pTable, "%d ", sat_solver_nconflicts(pSat) ); fprintf( pTable, "%d ", nIter ); fprintf( pTable, "%.2f", 1.0*clk/CLOCKS_PER_SEC ); fprintf( pTable, "\n" ); fclose( pTable ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFaultAddOne( Gia_Man_t * pM, Cnf_Dat_t * pCnf, sat_solver * pSat, Vec_Int_t * vLits, int nFuncVars, int fAddOr, Gia_Man_t * pGiaCnf ) { Gia_Man_t * pC;//, * pTemp; Cnf_Dat_t * pCnf2; Gia_Obj_t * pObj; int i, Lit; // derive the cofactor pC = Gia_ManFaultCofactor( pM, vLits ); // derive new CNF pCnf2 = Cnf_DeriveGiaRemapped( pC ); Cnf_DataLiftGia( pCnf2, pC, sat_solver_nvars(pSat) ); // add timeframe clauses for ( i = 0; i < pCnf2->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf2->pClauses[i], pCnf2->pClauses[i+1] ) ) { Cnf_DataFree( pCnf2 ); Gia_ManStop( pC ); return 0; } // add constraint clauses if ( fAddOr ) { // add one OR gate to assert difference of at least one output of the miter Vec_Int_t * vOrGate = Vec_IntAlloc( Gia_ManPoNum(pC) ); Gia_ManForEachPo( pC, pObj, i ) { Lit = Abc_Var2Lit( pCnf2->pVarNums[Gia_ObjId(pC, pObj)], 0 ); Vec_IntPush( vOrGate, Lit ); } if ( !sat_solver_addclause( pSat, Vec_IntArray(vOrGate), Vec_IntArray(vOrGate) + Vec_IntSize(vOrGate) ) ) assert( 0 ); Vec_IntFree( vOrGate ); } else { // add negative literals to assert equality of all outputs of the miter Gia_ManForEachPo( pC, pObj, i ) { Lit = Abc_Var2Lit( pCnf2->pVarNums[Gia_ObjId(pC, pObj)], 1 ); if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) ) { Cnf_DataFree( pCnf2 ); Gia_ManStop( pC ); return 0; } } } // add connection clauses if ( pGiaCnf ) { Gia_ManForEachPi( pGiaCnf, pObj, i ) if ( i >= nFuncVars ) sat_solver_add_buffer( pSat, pCnf->pVarNums[Gia_ObjId(pGiaCnf, pObj)], pCnf2->pVarNums[Gia_ObjId(pC, Gia_ManPi(pC, i))], 0 ); } Cnf_DataFree( pCnf2 ); Gia_ManStop( pC ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDumpUntests( Gia_Man_t * pM, Cnf_Dat_t * pCnf, sat_solver * pSat, int nFuncVars, char * pFileName, int fVerbose ) { FILE * pFile = fopen( pFileName, "wb" ); Vec_Int_t * vLits; Gia_Obj_t * pObj; int nItersMax = 10000; int i, nIters, status, Value, Count = 0; vLits = Vec_IntAlloc( Gia_ManPiNum(pM) - nFuncVars ); for ( nIters = 0; nIters < nItersMax; nIters++ ) { status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) printf( "Timeout reached after dumping %d untestable faults.\n", nIters ); if ( status == l_Undef ) break; if ( status == l_False ) break; // collect literals Vec_IntClear( vLits ); Gia_ManForEachPi( pM, pObj, i ) if ( i >= nFuncVars ) Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], sat_solver_var_value(pSat, pCnf->pVarNums[Gia_ObjId(pM, pObj)])) ); // dump the fault Vec_IntForEachEntry( vLits, Value, i ) if ( Abc_LitIsCompl(Value) ) break; if ( i < Vec_IntSize(vLits) ) { if ( fVerbose ) { printf( "Untestable fault %4d : ", ++Count ); Vec_IntForEachEntry( vLits, Value, i ) if ( Abc_LitIsCompl(Value) ) printf( "%d ", i ); printf( "\n" ); } Vec_IntForEachEntry( vLits, Value, i ) if ( Abc_LitIsCompl(Value) ) fprintf( pFile, "%d ", i ); fprintf( pFile, "\n" ); } // add this clause if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) break; } Vec_IntFree( vLits ); fclose( pFile ); return nIters; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManGetTestPatterns( char * pFileName ) { FILE * pFile = fopen( pFileName, "rb" ); Vec_Int_t * vTests; int c; if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return NULL; } vTests = Vec_IntAlloc( 10000 ); while ( (c = fgetc(pFile)) != EOF ) { if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) continue; if ( c != '0' && c != '1' ) { printf( "Wring symbol (%c) in the input file.\n", c ); Vec_IntFreeP( &vTests ); break; } Vec_IntPush( vTests, c - '0' ); } fclose( pFile ); return vTests; } /**Function************************************************************* Synopsis [Derive the second AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDeriveDup( Gia_Man_t * p, int nPisNew ) { int i; Gia_Man_t * pNew = Gia_ManDup(p); for ( i = 0; i < nPisNew; i++ ) Gia_ManAppendCi( pNew ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFaultAnalyze( sat_solver * pSat, Vec_Int_t * vPars, Vec_Int_t * vMap, Vec_Int_t * vLits, int Iter ) { int nConfLimit = 100; int status, i, v, iVar, Lit; int nUnsats = 0, nRuns = 0; abctime clk = Abc_Clock(); assert( Vec_IntSize(vPars) == Vec_IntSize(vMap) ); // check presence of each variable Vec_IntClear( vLits ); Vec_IntAppend( vLits, vMap ); for ( v = 0; v < Vec_IntSize(vPars); v++ ) { if ( !Vec_IntEntry(vLits, v) ) continue; assert( Vec_IntEntry(vLits, v) == 1 ); nRuns++; Lit = Abc_Var2Lit( Vec_IntEntry(vPars, v), 0 ); status = sat_solver_solve( pSat, &Lit, &Lit+1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) continue; if ( status == l_False ) { nUnsats++; assert( Vec_IntEntry(vMap, v) == 1 ); Vec_IntWriteEntry( vMap, v, 0 ); Lit = Abc_LitNot(Lit); //status = sat_solver_addclause( pSat, &Lit, &Lit+1 ); //assert( status ); continue; } Vec_IntForEachEntry( vPars, iVar, i ) if ( Vec_IntEntry(vLits, i) && sat_solver_var_value(pSat, iVar) ) Vec_IntWriteEntry( vLits, i, 0 ); assert( Vec_IntEntry(vLits, v) == 0 ); } printf( "Iteration %3d has determined %5d (out of %5d) parameters after %6d SAT calls. ", Iter, Vec_IntSize(vMap) - Vec_IntCountPositive(vMap), Vec_IntSize(vPars), nRuns ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return nUnsats; } /**Function************************************************************* Synopsis [Dump faults detected by the new test, which are not detected by previous tests.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFaultDumpNewFaults( Gia_Man_t * pM, int nFuncVars, Vec_Int_t * vTests, Vec_Int_t * vTestNew, Bmc_ParFf_t * pPars ) { char * pFileName = "newfaults.txt"; abctime clk; Gia_Man_t * pC; Cnf_Dat_t * pCnf2; sat_solver * pSat; Vec_Int_t * vLits; int i, Iter, IterMax, nNewFaults; // derive the cofactor pC = Gia_ManFaultCofactor( pM, vTestNew ); // derive new CNF pCnf2 = Cnf_DeriveGiaRemapped( pC ); // create SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, 1 ); sat_solver_set_runtime_limit( pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); // create the first cofactor Gia_ManFaultAddOne( pM, NULL, pSat, vTestNew, nFuncVars, 1, NULL ); // add other test patterns assert( Vec_IntSize(vTests) % nFuncVars == 0 ); IterMax = Vec_IntSize(vTests) / nFuncVars; vLits = Vec_IntAlloc( nFuncVars ); for ( Iter = 0; Iter < IterMax; Iter++ ) { // get pattern Vec_IntClear( vLits ); for ( i = 0; i < nFuncVars; i++ ) Vec_IntPush( vLits, Vec_IntEntry(vTests, Iter*nFuncVars + i) ); // the resulting problem cannot be UNSAT, because the new test is guaranteed // to detect something that the given test set does not detect if ( !Gia_ManFaultAddOne( pM, pCnf2, pSat, vLits, nFuncVars, 0, pC ) ) assert( 0 ); } Vec_IntFree( vLits ); // dump the new faults clk = Abc_Clock(); nNewFaults = Gia_ManDumpUntests( pC, pCnf2, pSat, nFuncVars, pFileName, pPars->fVerbose ); printf( "Dumped %d new multiple faults into file \"%s\". ", nNewFaults, pFileName ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // cleanup sat_solver_delete( pSat ); Cnf_DataFree( pCnf2 ); Gia_ManStop( pC ); return 1; } /**Function************************************************************* Synopsis [Generate miter, CNF and solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFaultPrepare( Gia_Man_t * p, Gia_Man_t * pG, Bmc_ParFf_t * pPars, int nFuncVars, Vec_Int_t * vMap, Vec_Int_t * vTests, Vec_Int_t * vLits, Gia_Man_t ** ppMiter, Cnf_Dat_t ** ppCnf, sat_solver ** ppSat, int fWarmUp ) { Gia_Man_t * p0 = NULL, * p1 = NULL, * pM; Gia_Obj_t * pObj; Cnf_Dat_t * pCnf; sat_solver * pSat; int i, Iter, status; abctime clkSat = 0; if ( Vec_IntSize(vTests) && (Vec_IntSize(vTests) % nFuncVars != 0) ) { printf( "The number of symbols in the input patterns (%d) does not divide evenly on the number of test variables (%d).\n", Vec_IntSize(vTests), nFuncVars ); Vec_IntFree( vTests ); return 0; } // select algorithm if ( pPars->Algo == 0 ) p1 = Gia_ManFormulaUnfold( p, pPars->pFormStr, pPars->fFfOnly ); else if ( pPars->Algo == 1 ) { assert( Gia_ManRegNum(p) > 0 ); p0 = Gia_ManFaultUnfold( pG, 0, pPars->fFfOnly ); p1 = Gia_ManFaultUnfold( p, 1, pPars->fFfOnly ); } else if ( pPars->Algo == 2 ) p1 = Gia_ManStuckAtUnfold( p, vMap ); else if ( pPars->Algo == 3 ) p1 = Gia_ManFlipUnfold( p, vMap ); else if ( pPars->Algo == 4 ) p1 = Gia_ManFOFUnfold( p, vMap ); if ( pPars->Algo != 1 ) p0 = Gia_ManDeriveDup( pG, Gia_ManCiNum(p1) - Gia_ManCiNum(pG) ); // Gia_AigerWrite( p1, "newfault.aig", 0, 0 ); // printf( "Dumped circuit with fault parameters into file \"newfault.aig\".\n" ); // create miter pM = Gia_ManMiter( p0, p1, 0, 0, 0, 0, 0 ); pCnf = Cnf_DeriveGiaRemapped( pM ); Gia_ManStop( p0 ); Gia_ManStop( p1 ); // start the SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, pCnf->nVars ); sat_solver_set_runtime_limit( pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); // add timeframe clauses for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) assert( 0 ); // add one large OR clause Vec_IntClear( vLits ); Gia_ManForEachCo( pM, pObj, i ) Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], 0) ); sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); // save return data *ppMiter = pM; *ppCnf = pCnf; *ppSat = pSat; // add cardinality constraint if ( pPars->fBasic ) { Vec_IntClear( vLits ); Gia_ManForEachPi( pM, pObj, i ) if ( i >= nFuncVars ) Vec_IntPush( vLits, pCnf->pVarNums[Gia_ObjId(pM, pObj)] ); Cnf_AddCardinConstr( pSat, vLits ); } else if ( pPars->nCardConstr ) { Vec_IntClear( vLits ); Gia_ManForEachPi( pM, pObj, i ) if ( i >= nFuncVars ) Vec_IntPush( vLits, pCnf->pVarNums[Gia_ObjId(pM, pObj)] ); Cnf_AddCardinConstrGeneral( pSat, vLits, pPars->nCardConstr, !pPars->fNonStrict ); } // add available test-patterns if ( Vec_IntSize(vTests) > 0 ) { int nTests = Vec_IntSize(vTests) / nFuncVars; assert( Vec_IntSize(vTests) % nFuncVars == 0 ); if ( pPars->pFileName ) printf( "Reading %d pre-computed test patterns from file \"%s\".\n", Vec_IntSize(vTests) / nFuncVars, pPars->pFileName ); else printf( "Reading %d pre-computed test patterns from previous rounds.\n", Vec_IntSize(vTests) / nFuncVars ); for ( Iter = 0; Iter < nTests; Iter++ ) { if ( fWarmUp ) { abctime clk = Abc_Clock(); status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); clkSat += Abc_Clock() - clk; if ( status == l_Undef ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "Timeout reached after %d seconds and adding %d tests.\n", pPars->nTimeOut, Iter ); Vec_IntShrink( vTests, Iter * nFuncVars ); return 0; } if ( status == l_False ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "The problem is UNSAT after adding %d tests.\n", Iter ); Vec_IntShrink( vTests, Iter * nFuncVars ); return 0; } } // get pattern Vec_IntClear( vLits ); for ( i = 0; i < nFuncVars; i++ ) Vec_IntPush( vLits, Vec_IntEntry(vTests, Iter*nFuncVars + i) ); if ( !Gia_ManFaultAddOne( pM, pCnf, pSat, vLits, nFuncVars, 0, pM ) ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "The problem is UNSAT after adding %d tests.\n", Iter ); Vec_IntShrink( vTests, Iter * nFuncVars ); return 0; } if ( pPars->fVerbose ) { printf( "Iter%6d : ", Iter ); printf( "Var =%10d ", sat_solver_nvars(pSat) ); printf( "Clause =%10d ", sat_solver_nclauses(pSat) ); printf( "Conflict =%10d ", sat_solver_nconflicts(pSat) ); //Abc_PrintTime( 1, "Time", clkSat ); ABC_PRTr( "Solver time", clkSat ); } } } else if ( pPars->fStartPats ) { for ( Iter = 0; Iter < 2; Iter++ ) { status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "Timeout reached after %d seconds and %d iterations.\n", pPars->nTimeOut, Iter ); Vec_IntShrink( vTests, Iter * nFuncVars ); return 0; } if ( status == l_False ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "The problem is UNSAT after %d iterations.\n", Iter ); Vec_IntShrink( vTests, Iter * nFuncVars ); return 0; } // initialize simple pattern Vec_IntFill( vLits, nFuncVars, Iter ); Vec_IntAppend( vTests, vLits ); if ( !Gia_ManFaultAddOne( pM, pCnf, pSat, vLits, nFuncVars, 0, pM ) ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "The problem is UNSAT after adding %d tests.\n", Iter ); Vec_IntShrink( vTests, Iter * nFuncVars ); return 0; } } } printf( "Using miter with: AIG nodes = %6d. CNF variables = %6d. CNF clauses = %8d.\n", Gia_ManAndNum(pM), pCnf->nVars, pCnf->nClauses ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFaultTest( Gia_Man_t * p, Gia_Man_t * pG, Bmc_ParFf_t * pPars ) { int nIterMax = 1000000, nVars, nPars; int i, Iter, Iter2, status, nFuncVars = -1; abctime clk, clkSat = 0, clkTotal = Abc_Clock(); Vec_Int_t * vLits, * vMap = NULL, * vTests, * vPars = NULL; Gia_Man_t * pM; Gia_Obj_t * pObj; Cnf_Dat_t * pCnf; sat_solver * pSat = NULL; if ( pPars->Algo == 0 && Gia_FormStrCount( pPars->pFormStr, &nVars, &nPars ) ) return; // select algorithm if ( pPars->Algo == 0 ) printf( "FFTEST is computing test patterns for fault model \"%s\"...\n", pPars->pFormStr ); else if ( pPars->Algo == 1 ) printf( "FFTEST is computing test patterns for %sdelay faults...\n", pPars->fBasic ? "single " : "" ); else if ( pPars->Algo == 2 ) printf( "FFTEST is computing test patterns for %sstuck-at faults...\n", pPars->fBasic ? "single " : "" ); else if ( pPars->Algo == 3 ) printf( "FFTEST is computing test patterns for %scomplement faults...\n", pPars->fBasic ? "single " : "" ); else if ( pPars->Algo == 4 ) printf( "FFTEST is computing test patterns for %sfunctionally observable faults...\n", pPars->fBasic ? "single " : "" ); else { printf( "Unrecognized algorithm (%d).\n", pPars->Algo ); return; } // select algorithm if ( pPars->Algo == 0 ) nFuncVars = Gia_ManCiNum(p); else if ( pPars->Algo == 1 ) nFuncVars = Gia_ManRegNum(p) + 2 * Gia_ManPiNum(p); else if ( pPars->Algo == 2 ) nFuncVars = Gia_ManCiNum(p); else if ( pPars->Algo == 3 ) nFuncVars = Gia_ManCiNum(p); else if ( pPars->Algo == 4 ) nFuncVars = Gia_ManCiNum(p); // collect test patterns from file if ( pPars->pFileName ) vTests = Gia_ManGetTestPatterns( pPars->pFileName ); else vTests = Vec_IntAlloc( 10000 ); if ( vTests == NULL ) return; // select algorithm vMap = Vec_IntAlloc( 0 ); if ( pPars->Algo == 2 ) Vec_IntFill( vMap, 2 * Gia_ManAndNum(p), 1 ); else if ( pPars->Algo == 3 ) Vec_IntFill( vMap, Gia_ManAndNum(p), 1 ); else if ( pPars->Algo == 4 ) Vec_IntFill( vMap, 4 * Gia_ManAndNum(p), 1 ); // prepare SAT solver vLits = Vec_IntAlloc( Gia_ManCoNum(p) ); // add user-speicified test-vectors (if given) and create missing ones (if needed) if ( Gia_ManFaultPrepare(p, pG, pPars, nFuncVars, vMap, vTests, vLits, &pM, &pCnf, &pSat, 1) ) for ( Iter = pPars->fStartPats ? 2 : Vec_IntSize(vTests) / nFuncVars; Iter < nIterMax; Iter++ ) { // collect parameter variables if ( pPars->nIterCheck && vPars == NULL ) { vPars = Vec_IntAlloc( Gia_ManPiNum(pM) - nFuncVars ); Gia_ManForEachPi( pM, pObj, i ) if ( i >= nFuncVars ) Vec_IntPush( vPars, pCnf->pVarNums[Gia_ObjId(pM, pObj)] ); assert( Vec_IntSize(vPars) == Gia_ManPiNum(pM) - nFuncVars ); } // derive unit parameter variables if ( Iter && pPars->nIterCheck && (Iter % pPars->nIterCheck) == 0 ) { Gia_ManFaultAnalyze( pSat, vPars, vMap, vLits, Iter ); // cleanup Gia_ManStop( pM ); Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); // recompute if ( !Gia_ManFaultPrepare(p, pG, pPars, nFuncVars, vMap, vTests, vLits, &pM, &pCnf, &pSat, 0) ) { printf( "This should never happen.\n" ); return; } Vec_IntFreeP( &vPars ); } // solve clk = Abc_Clock(); status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); clkSat += Abc_Clock() - clk; if ( pPars->fVerbose ) { printf( "Iter%6d : ", Iter ); printf( "Var =%10d ", sat_solver_nvars(pSat) ); printf( "Clause =%10d ", sat_solver_nclauses(pSat) ); printf( "Conflict =%10d ", sat_solver_nconflicts(pSat) ); //Abc_PrintTime( 1, "Time", clkSat ); ABC_PRTr( "Solver time", clkSat ); } if ( status == l_Undef ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "Timeout reached after %d seconds and %d iterations.\n", pPars->nTimeOut, Iter ); goto finish; } if ( status == l_False ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "The problem is UNSAT after %d iterations. ", Iter ); break; } assert( status == l_True ); // collect SAT assignment Vec_IntClear( vLits ); Gia_ManForEachPi( pM, pObj, i ) if ( i < nFuncVars ) Vec_IntPush( vLits, sat_solver_var_value(pSat, pCnf->pVarNums[Gia_ObjId(pM, pObj)]) ); // if the user selected to generate new faults detected by this test (vLits) // and not detected by the given test set (vTests), we compute the new faults here and quit if ( pPars->fDumpNewFaults ) { if ( Vec_IntSize(vTests) == 0 ) printf( "The input test patterns are not given.\n" ); else Gia_ManFaultDumpNewFaults( pM, nFuncVars, vTests, vLits, pPars ); goto finish_all; } Vec_IntAppend( vTests, vLits ); // add constraint if ( !Gia_ManFaultAddOne( pM, pCnf, pSat, vLits, nFuncVars, 0, pM ) ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "The problem is UNSAT after adding %d tests.\n", Iter ); break; } } else Iter = Vec_IntSize(vTests) / nFuncVars; finish: // print results // if ( status == l_False ) // Gia_ManPrintResults( p, pSat, Iter, Abc_Clock() - clkTotal ); // cleanup Abc_PrintTime( 1, "Testing runtime", Abc_Clock() - clkTotal ); // dump the test suite if ( pPars->fDump ) { char * pFileName = "tests.txt"; if ( pPars->fDumpDelay && pPars->Algo == 1 ) { Gia_ManDumpTestsDelay( vTests, Iter, pFileName, p ); printf( "Dumping %d pairs of test patterns (total %d pattern) into file \"%s\".\n", Vec_IntSize(vTests) / nFuncVars, 2*Vec_IntSize(vTests) / nFuncVars, pFileName ); } else { Gia_ManDumpTests( vTests, Iter, pFileName ); printf( "Dumping %d test patterns into file \"%s\".\n", Vec_IntSize(vTests) / nFuncVars, pFileName ); } } // compute untestable faults if ( Iter && (p != pG || pPars->fDumpUntest) ) { abctime clkTotal = Abc_Clock(); // restart the SAT solver sat_solver_delete( pSat ); pSat = sat_solver_new(); sat_solver_setnvars( pSat, pCnf->nVars ); sat_solver_set_runtime_limit( pSat, pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); // add timeframe clauses for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) assert( 0 ); // add constraint to rule out no fault // if ( p == pG ) { Vec_IntClear( vLits ); Gia_ManForEachPi( pM, pObj, i ) if ( i >= nFuncVars ) Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], 0) ); sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); } // add cardinality constraint if ( pPars->fBasic ) { Vec_IntClear( vLits ); Gia_ManForEachPi( pM, pObj, i ) if ( i >= nFuncVars ) Vec_IntPush( vLits, pCnf->pVarNums[Gia_ObjId(pM, pObj)] ); Cnf_AddCardinConstr( pSat, vLits ); } // add output clauses Gia_ManForEachCo( pM, pObj, i ) { int Lit = Abc_Var2Lit( pCnf->pVarNums[Gia_ObjId(pM, pObj)], 1 ); sat_solver_addclause( pSat, &Lit, &Lit + 1 ); } // simplify the SAT solver status = sat_solver_simplify( pSat ); assert( status ); // add test patterns assert( Vec_IntSize(vTests) == Iter * nFuncVars ); for ( Iter2 = 0; ; Iter2++ ) { abctime clk = Abc_Clock(); status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); clkSat += Abc_Clock() - clk; if ( pPars->fVerbose ) { printf( "Iter%6d : ", Iter2 ); printf( "Var =%10d ", sat_solver_nvars(pSat) ); printf( "Clause =%10d ", sat_solver_nclauses(pSat) ); printf( "Conflict =%10d ", sat_solver_nconflicts(pSat) ); //Abc_PrintTime( 1, "Time", clkSat ); ABC_PRTr( "Solver time", clkSat ); } if ( status == l_Undef ) { if ( pPars->fVerbose ) printf( "\n" ); printf( "Timeout reached after %d seconds and %d iterations.\n", pPars->nTimeOut, Iter2 ); goto finish; } if ( Iter2 == Iter ) break; assert( status == l_True ); // get pattern Vec_IntClear( vLits ); for ( i = 0; i < nFuncVars; i++ ) Vec_IntPush( vLits, Vec_IntEntry(vTests, Iter2*nFuncVars + i) ); if ( !Gia_ManFaultAddOne( pM, pCnf, pSat, vLits, nFuncVars, 0, pM ) ) { printf( "The problem is UNSAT after adding %d tests.\n", Iter2 ); goto finish; } } assert( Iter2 == Iter ); if ( pPars->fVerbose ) printf( "\n" ); if ( p == pG ) { if ( status == l_True ) printf( "There are untestable faults. " ); else if ( status == l_False ) printf( "There is no untestable faults. " ); else assert( 0 ); Abc_PrintTime( 1, "Fault computation runtime", Abc_Clock() - clkTotal ); } else { if ( status == l_True ) printf( "The circuit is rectifiable. " ); else if ( status == l_False ) printf( "The circuit is not rectifiable (or equivalent to the golden one). " ); else assert( 0 ); Abc_PrintTime( 1, "Rectification runtime", Abc_Clock() - clkTotal ); } // dump untestable faults if ( pPars->fDumpUntest && status == l_True ) { abctime clk = Abc_Clock(); char * pFileName = "untest.txt"; int nUntests = Gia_ManDumpUntests( pM, pCnf, pSat, nFuncVars, pFileName, pPars->fVerbose ); if ( p == pG ) printf( "Dumped %d untestable multiple faults into file \"%s\". ", nUntests, pFileName ); else printf( "Dumped %d ways of rectifying the circuit into file \"%s\". ", nUntests, pFileName ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } } finish_all: sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Gia_ManStop( pM ); Vec_IntFree( vTests ); Vec_IntFree( vMap ); Vec_IntFree( vLits ); Vec_IntFreeP( &vPars ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcFx.c000066400000000000000000000647261300674244400226060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcFx.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [INT-FX: Interpolation-based logic sharing extraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcFx.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "misc/vec/vecWec.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create hash table to hash divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define TAB_UNUSED 0x7FFF typedef struct Tab_Obj_t_ Tab_Obj_t; // 16 bytes struct Tab_Obj_t_ { int Table; int Next; unsigned Cost : 17; unsigned LitA : 15; unsigned LitB : 15; unsigned LitC : 15; unsigned Func : 2; }; typedef struct Tab_Tab_t_ Tab_Tab_t; // 16 bytes struct Tab_Tab_t_ { int SizeMask; int nBins; Tab_Obj_t * pBins; }; static inline Tab_Tab_t * Tab_TabAlloc( int LogSize ) { Tab_Tab_t * p = ABC_CALLOC( Tab_Tab_t, 1 ); assert( LogSize >= 4 && LogSize <= 31 ); p->SizeMask = (1 << LogSize) - 1; p->pBins = ABC_CALLOC( Tab_Obj_t, p->SizeMask + 1 ); p->nBins = 1; return p; } static inline void Tab_TabFree( Tab_Tab_t * p ) { ABC_FREE( p->pBins ); ABC_FREE( p ); } static inline Vec_Int_t * Tab_TabFindBest( Tab_Tab_t * p, int nDivs ) { char * pNames[5] = {"const1", "and", "xor", "mux", "none"}; int * pOrder, i; Vec_Int_t * vDivs = Vec_IntAlloc( 100 ); Vec_Int_t * vCosts = Vec_IntAlloc( p->nBins ); Tab_Obj_t * pEnt, * pLimit = p->pBins + p->nBins; for ( pEnt = p->pBins; pEnt < pLimit; pEnt++ ) Vec_IntPush( vCosts, -(int)pEnt->Cost ); pOrder = Abc_MergeSortCost( Vec_IntArray(vCosts), Vec_IntSize(vCosts) ); for ( i = 0; i < Vec_IntSize(vCosts); i++ ) { pEnt = p->pBins + pOrder[i]; if ( i == nDivs || pEnt->Cost == 1 ) break; printf( "Lit0 = %5d. Lit1 = %5d. Lit2 = %5d. Func = %s. Cost = %3d.\n", pEnt->LitA, pEnt->LitB, pEnt->LitC, pNames[pEnt->Func], pEnt->Cost ); Vec_IntPushTwo( vDivs, pEnt->Func, pEnt->LitA ); Vec_IntPushTwo( vDivs, pEnt->LitB, pEnt->LitC ); } Vec_IntFree( vCosts ); ABC_FREE( pOrder ); return vDivs; } static inline int Tab_Hash( int LitA, int LitB, int LitC, int Func, int Mask ) { return (LitA * 50331653 + LitB * 100663319 + LitC * 201326611 + Func * 402653189) & Mask; } static inline void Tab_TabRehash( Tab_Tab_t * p ) { Tab_Obj_t * pEnt, * pLimit, * pBin; assert( p->nBins == p->SizeMask + 1 ); // realloc memory p->pBins = ABC_REALLOC( Tab_Obj_t, p->pBins, 2 * (p->SizeMask + 1) ); memset( p->pBins + p->SizeMask + 1, 0, sizeof(Tab_Obj_t) * (p->SizeMask + 1) ); // clean entries pLimit = p->pBins + p->SizeMask + 1; for ( pEnt = p->pBins; pEnt < pLimit; pEnt++ ) pEnt->Table = pEnt->Next = 0; // rehash entries p->SizeMask = 2 * p->SizeMask + 1; for ( pEnt = p->pBins + 1; pEnt < pLimit; pEnt++ ) { pBin = p->pBins + Tab_Hash( pEnt->LitA, pEnt->LitB, pEnt->LitC, pEnt->Func, p->SizeMask ); pEnt->Next = pBin->Table; pBin->Table = pEnt - p->pBins; assert( !pEnt->Next || pEnt->Next != pBin->Table ); } } static inline Tab_Obj_t * Tab_TabEntry( Tab_Tab_t * p, int i ) { return i ? p->pBins + i : NULL; } static inline int Tab_TabHashAdd( Tab_Tab_t * p, int * pLits, int Func, int Cost ) { if ( p->nBins == p->SizeMask + 1 ) Tab_TabRehash( p ); assert( p->nBins < p->SizeMask + 1 ); { Tab_Obj_t * pEnt, * pBin = p->pBins + Tab_Hash(pLits[0], pLits[1], pLits[2], Func, p->SizeMask); for ( pEnt = Tab_TabEntry(p, pBin->Table); pEnt; pEnt = Tab_TabEntry(p, pEnt->Next) ) if ( (int)pEnt->LitA == pLits[0] && (int)pEnt->LitB == pLits[1] && (int)pEnt->LitC == pLits[2] && (int)pEnt->Func == Func ) { pEnt->Cost += Cost; return 1; } pEnt = p->pBins + p->nBins; pEnt->LitA = pLits[0]; pEnt->LitB = pLits[1]; pEnt->LitC = pLits[2]; pEnt->Func = Func; pEnt->Cost = Cost; pEnt->Next = pBin->Table; pBin->Table = p->nBins++; assert( !pEnt->Next || pEnt->Next != pBin->Table ); return 0; } } /**Function************************************************************* Synopsis [Input is four literals. Output is type, polarity and fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // name types typedef enum { DIV_CST = 0, // 0: constant 1 DIV_AND, // 1: and (ordered fanins) DIV_XOR, // 2: xor (ordered fanins) DIV_MUX, // 3: mux (c, d1, d0) DIV_NONE // 4: not used } Div_Type_t; static inline Div_Type_t Bmc_FxDivOr( int LitA, int LitB, int * pLits, int * pPhase ) { assert( LitA != LitB ); if ( Abc_Lit2Var(LitA) == Abc_Lit2Var(LitB) ) return DIV_CST; if ( LitA > LitB ) ABC_SWAP( int, LitA, LitB ); pLits[0] = Abc_LitNot(LitA); pLits[1] = Abc_LitNot(LitB); *pPhase = 1; return DIV_AND; } static inline Div_Type_t Bmc_FxDivXor( int LitA, int LitB, int * pLits, int * pPhase ) { assert( LitA != LitB ); *pPhase ^= Abc_LitIsCompl(LitA); *pPhase ^= Abc_LitIsCompl(LitB); pLits[0] = Abc_LitRegular(LitA); pLits[1] = Abc_LitRegular(LitB); return DIV_XOR; } static inline Div_Type_t Bmc_FxDivMux( int LitC, int LitCn, int LitT, int LitE, int * pLits, int * pPhase ) { assert( LitC != LitCn ); assert( Abc_Lit2Var(LitC) == Abc_Lit2Var(LitCn) ); assert( Abc_Lit2Var(LitC) != Abc_Lit2Var(LitT) ); assert( Abc_Lit2Var(LitC) != Abc_Lit2Var(LitE) ); assert( Abc_Lit2Var(LitC) != Abc_Lit2Var(LitE) ); if ( Abc_LitIsCompl(LitC) ) { LitC = Abc_LitRegular(LitC); ABC_SWAP( int, LitT, LitE ); } if ( Abc_LitIsCompl(LitT) ) { *pPhase ^= 1; LitT = Abc_LitNot(LitT); LitE = Abc_LitNot(LitE); } pLits[0] = LitC; pLits[1] = LitT; pLits[2] = LitE; return DIV_MUX; } static inline Div_Type_t Div_FindType( int LitA[2], int LitB[2], int * pLits, int * pPhase ) { *pPhase = 0; pLits[0] = pLits[1] = pLits[2] = TAB_UNUSED; if ( LitA[0] == -1 && LitA[1] == -1 ) return DIV_CST; if ( LitB[0] == -1 && LitB[1] == -1 ) return DIV_CST; assert( LitA[0] >= 0 && LitB[0] >= 0 ); assert( LitA[0] != LitB[0] ); if ( LitA[1] == -1 && LitB[1] == -1 ) return Bmc_FxDivOr( LitA[0], LitB[0], pLits, pPhase ); assert( LitA[1] != LitB[1] ); if ( LitA[1] == -1 || LitB[1] == -1 ) { if ( LitA[1] == -1 ) { ABC_SWAP( int, LitA[0], LitB[0] ); ABC_SWAP( int, LitA[1], LitB[1] ); } assert( LitA[0] >= 0 && LitA[1] >= 0 ); assert( LitB[0] >= 0 && LitB[1] == -1 ); if ( Abc_Lit2Var(LitB[0]) == Abc_Lit2Var(LitA[0]) ) return Bmc_FxDivOr( LitB[0], LitA[1], pLits, pPhase ); if ( Abc_Lit2Var(LitB[0]) == Abc_Lit2Var(LitA[1]) ) return Bmc_FxDivOr( LitB[0], LitA[0], pLits, pPhase ); return DIV_NONE; } if ( Abc_Lit2Var(LitA[0]) == Abc_Lit2Var(LitB[0]) && Abc_Lit2Var(LitA[1]) == Abc_Lit2Var(LitB[1]) ) return Bmc_FxDivXor( LitA[0], LitB[1], pLits, pPhase ); if ( Abc_Lit2Var(LitA[0]) == Abc_Lit2Var(LitB[0]) ) return Bmc_FxDivMux( LitA[0], LitB[0], LitA[1], LitB[1], pLits, pPhase ); if ( Abc_Lit2Var(LitA[0]) == Abc_Lit2Var(LitB[1]) ) return Bmc_FxDivMux( LitA[0], LitB[1], LitA[1], LitB[0], pLits, pPhase ); if ( Abc_Lit2Var(LitA[1]) == Abc_Lit2Var(LitB[0]) ) return Bmc_FxDivMux( LitA[1], LitB[0], LitA[0], LitB[1], pLits, pPhase ); if ( Abc_Lit2Var(LitA[1]) == Abc_Lit2Var(LitB[1]) ) return Bmc_FxDivMux( LitA[1], LitB[1], LitA[0], LitB[0], pLits, pPhase ); return DIV_NONE; } /**Function************************************************************* Synopsis [Returns the number of shared variables, or -1 if failed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Div_AddLit( int Lit, int pLits[2] ) { if ( pLits[0] == -1 ) pLits[0] = Lit; else if ( pLits[1] == -1 ) pLits[1] = Lit; else return 1; return 0; } int Div_FindDiv( Vec_Int_t * vA, Vec_Int_t * vB, int pLitsA[2], int pLitsB[2] ) { int Counter = 0; int * pBegA = vA->pArray, * pEndA = vA->pArray + vA->nSize; int * pBegB = vB->pArray, * pEndB = vB->pArray + vB->nSize; pLitsA[0] = pLitsA[1] = pLitsB[0] = pLitsB[1] = -1; while ( pBegA < pEndA && pBegB < pEndB ) { if ( *pBegA == *pBegB ) pBegA++, pBegB++, Counter++; else if ( *pBegA < *pBegB ) { if ( Div_AddLit( *pBegA++, pLitsA ) ) return -1; } else { if ( Div_AddLit( *pBegB++, pLitsB ) ) return -1; } } while ( pBegA < pEndA ) if ( Div_AddLit( *pBegA++, pLitsA ) ) return -1; while ( pBegB < pEndB ) if ( Div_AddLit( *pBegB++, pLitsB ) ) return -1; return Counter; } void Div_CubePrintOne( Vec_Int_t * vCube, Vec_Str_t * vStr, int nVars ) { int i, Lit; Vec_StrFill( vStr, nVars, '-' ); Vec_IntForEachEntry( vCube, Lit, i ) Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit) ? '0' : '1') ); printf( "%s\n", Vec_StrArray(vStr) ); } void Div_CubePrint( Vec_Wec_t * p, int nVars ) { Vec_Int_t * vCube; int i; Vec_Str_t * vStr = Vec_StrStart( nVars + 1 ); Vec_WecForEachLevel( p, vCube, i ) Div_CubePrintOne( vCube, vStr, nVars ); Vec_StrFree( vStr ); } Vec_Int_t * Div_CubePairs( Vec_Wec_t * p, int nVars, int nDivs ) { int fVerbose = 0; char * pNames[5] = {"const1", "and", "xor", "mux", "none"}; Vec_Int_t * vCube1, * vCube2, * vDivs; int i1, i2, i, k, pLitsA[2], pLitsB[2], pLits[4], Type, Phase, nBase, Count = 0; Vec_Str_t * vStr = Vec_StrStart( nVars + 1 ); Tab_Tab_t * pTab = Tab_TabAlloc( 5 ); Vec_WecForEachLevel( p, vCube1, i ) { // add lit pairs pLits[2] = TAB_UNUSED; Vec_IntForEachEntry( vCube1, pLits[0], i1 ) Vec_IntForEachEntryStart( vCube1, pLits[1], i2, i1+1 ) { Tab_TabHashAdd( pTab, pLits, DIV_AND, 1 ); } Vec_WecForEachLevelStart( p, vCube2, k, i+1 ) { nBase = Div_FindDiv( vCube1, vCube2, pLitsA, pLitsB ); if ( nBase == -1 ) continue; Type = Div_FindType(pLitsA, pLitsB, pLits, &Phase); if ( Type >= DIV_AND && Type <= DIV_MUX ) Tab_TabHashAdd( pTab, pLits, Type, nBase ); if ( fVerbose ) { printf( "Pair %d:\n", Count++ ); Div_CubePrintOne( vCube1, vStr, nVars ); Div_CubePrintOne( vCube2, vStr, nVars ); printf( "Result = %d ", nBase ); assert( nBase > 0 ); printf( "Type = %s ", pNames[Type] ); printf( "LitA = %d ", pLits[0] ); printf( "LitB = %d ", pLits[1] ); printf( "LitC = %d ", pLits[2] ); printf( "Phase = %d ", Phase ); printf( "\n" ); } } } // print the table printf( "Divisors = %d.\n", pTab->nBins ); vDivs = Tab_TabFindBest( pTab, nDivs ); // cleanup Vec_StrFree( vStr ); Tab_TabFree( pTab ); return vDivs; } /**Function************************************************************* Synopsis [Solve the enumeration problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_FxSolve( sat_solver * pSat, int iOut, int iAuxVar, Vec_Int_t * vVars, int fDumpPla, int fVerbose, int * pCounter, Vec_Wec_t * vCubes ) { int nBTLimit = 1000000; int fUseOrder = 1; Vec_Int_t * vLevel = NULL; Vec_Int_t * vLits = Vec_IntAlloc( Vec_IntSize(vVars) ); Vec_Int_t * vLits2 = Vec_IntAlloc( Vec_IntSize(vVars) ); Vec_Str_t * vCube = Vec_StrStart( Vec_IntSize(vVars)+1 ); int status, i, k, n, Lit, Lit2, iVar, nFinal, * pFinal, pLits[2], nIter = 0, RetValue = 0; int Before, After, Total = 0, nLits = 0; pLits[0] = Abc_Var2Lit( iOut + 1, 0 ); // F = 1 pLits[1] = Abc_Var2Lit( iAuxVar, 0 ); // iNewLit if ( vCubes ) Vec_WecClear( vCubes ); if ( fDumpPla ) printf( ".i %d\n", Vec_IntSize(vVars) ); if ( fDumpPla ) printf( ".o %d\n", 1 ); while ( 1 ) { // find onset minterm status = sat_solver_solve( pSat, pLits, pLits + 2, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) { RetValue = -1; break; } if ( status == l_False ) { RetValue = 1; break; } assert( status == l_True ); // collect divisor literals Vec_IntClear( vLits ); Vec_IntPush( vLits, Abc_LitNot(pLits[0]) ); // F = 0 // Vec_IntForEachEntryReverse( vVars, iVar, i ) Vec_IntForEachEntry( vVars, iVar, i ) Vec_IntPush( vLits, sat_solver_var_literal(pSat, iVar) ); if ( fUseOrder ) { ////////////////////////////////////////////////////////////// // save these literals Vec_IntClear( vLits2 ); Vec_IntAppend( vLits2, vLits ); Before = Vec_IntSize(vLits2); // try removing literals from the cube Vec_IntForEachEntry( vLits2, Lit2, k ) { if ( Lit2 == Abc_LitNot(pLits[0]) ) continue; Vec_IntClear( vLits ); Vec_IntForEachEntry( vLits2, Lit, n ) if ( Lit != -1 && Lit != Lit2 ) Vec_IntPush( vLits, Lit ); // call sat status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) assert( 0 ); if ( status == l_True ) // SAT continue; // Lit2 can be removed Vec_IntWriteEntry( vLits2, k, -1 ); } // make one final run Vec_IntClear( vLits ); Vec_IntForEachEntry( vLits2, Lit2, k ) if ( Lit2 != -1 ) Vec_IntPush( vLits, Lit2 ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nBTLimit, 0, 0, 0 ); assert( status == l_False ); // get subset of literals nFinal = sat_solver_final( pSat, &pFinal ); ////////////////////////////////////////////////////////////// } else { /////////////////////////////////////////////////////////////// // check against offset status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) { RetValue = -1; break; } if ( status == l_True ) break; assert( status == l_False ); // get subset of literals nFinal = sat_solver_final( pSat, &pFinal ); Before = nFinal; //printf( "Before %d. ", nFinal ); /* // save these literals Vec_IntClear( vLits ); for ( i = 0; i < nFinal; i++ ) Vec_IntPush( vLits, Abc_LitNot(pFinal[i]) ); Vec_IntReverseOrder( vLits ); // make one final run status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nBTLimit, 0, 0, 0 ); assert( status == l_False ); nFinal = sat_solver_final( pSat, &pFinal ); */ // save these literals Vec_IntClear( vLits2 ); for ( i = 0; i < nFinal; i++ ) Vec_IntPush( vLits2, Abc_LitNot(pFinal[i]) ); Vec_IntSort( vLits2, 1 ); // try removing literals from the cube Vec_IntForEachEntry( vLits2, Lit2, k ) { if ( Lit2 == Abc_LitNot(pLits[0]) ) continue; Vec_IntClear( vLits ); Vec_IntForEachEntry( vLits2, Lit, n ) if ( Lit != -1 && Lit != Lit2 ) Vec_IntPush( vLits, Lit ); // call sat status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) assert( 0 ); if ( status == l_True ) // SAT continue; // Lit2 can be removed Vec_IntWriteEntry( vLits2, k, -1 ); } // make one final run Vec_IntClear( vLits ); Vec_IntForEachEntry( vLits2, Lit2, k ) if ( Lit2 != -1 ) Vec_IntPush( vLits, Lit2 ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nBTLimit, 0, 0, 0 ); assert( status == l_False ); // put them back nFinal = 0; Vec_IntForEachEntry( vLits2, Lit2, k ) if ( Lit2 != -1 ) pFinal[nFinal++] = Abc_LitNot(Lit2); ///////////////////////////////////////////////////////// } //printf( "After %d. \n", nFinal ); After = nFinal; Total += Before - After; // get subset of literals //nFinal = sat_solver_final( pSat, &pFinal ); // compute cube and add clause Vec_IntClear( vLits ); Vec_IntPush( vLits, Abc_LitNot(pLits[1]) ); // NOT(iNewLit) if ( fDumpPla ) Vec_StrFill( vCube, Vec_IntSize(vVars), '-' ); if ( vCubes ) vLevel = Vec_WecPushLevel( vCubes ); for ( i = 0; i < nFinal; i++ ) { if ( pFinal[i] == pLits[0] ) continue; Vec_IntPush( vLits, pFinal[i] ); iVar = Vec_IntFind( vVars, Abc_Lit2Var(pFinal[i]) ); assert( iVar >= 0 && iVar < Vec_IntSize(vVars) ); //printf( "%s%d ", Abc_LitIsCompl(pFinal[i]) ? "+":"-", iVar ); if ( fDumpPla ) Vec_StrWriteEntry( vCube, iVar, (char)(!Abc_LitIsCompl(pFinal[i]) ? '0' : '1') ); if ( vLevel ) Vec_IntPush( vLevel, Abc_Var2Lit(iVar, !Abc_LitIsCompl(pFinal[i])) ); } if ( vCubes ) Vec_IntSort( vLevel, 0 ); if ( fDumpPla ) printf( "%s 1\n", Vec_StrArray(vCube) ); status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); assert( status ); nLits += Vec_IntSize(vLevel); nIter++; } if ( fDumpPla ) printf( ".e\n" ); if ( fDumpPla ) printf( ".p %d\n\n", nIter ); if ( fVerbose ) printf( "Cubes = %d. Reduced = %d. Lits = %d\n", nIter, Total, nLits ); if ( pCounter ) *pCounter = nIter; // assert( status == l_True ); Vec_IntFree( vLits ); Vec_IntFree( vLits2 ); Vec_StrFree( vCube ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_FxCompute( Gia_Man_t * p ) { // create dual-output circuit with on-set/off-set extern Gia_Man_t * Gia_ManDupOnsetOffset( Gia_Man_t * p ); Gia_Man_t * p2 = Gia_ManDupOnsetOffset( p ); // create SAT solver Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p2, 8, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // compute parameters int nOuts = Gia_ManCoNum(p); int nCiVars = Gia_ManCiNum(p), iCiVarBeg = pCnf->nVars - nCiVars;// - 1; int o, i, n, RetValue, nCounter, iAuxVarStart = sat_solver_nvars( pSat ); int nCubes[2][2] = {{0}}; // create variables Vec_Int_t * vVars = Vec_IntAlloc( nCiVars ); for ( n = 0; n < nCiVars; n++ ) Vec_IntPush( vVars, iCiVarBeg + n ); sat_solver_setnvars( pSat, iAuxVarStart + 4*nOuts ); // iterate through outputs for ( o = 0; o < nOuts; o++ ) for ( i = 0; i < 2; i++ ) for ( n = 0; n < 2; n++ ) // 0=onset, 1=offset // for ( n = 1; n >= 0; n-- ) // 0=onset, 1=offset { printf( "Out %3d %sset ", o, n ? "off" : " on" ); RetValue = Bmc_FxSolve( pSat, Abc_Var2Lit(o, n), iAuxVarStart + 2*i*nOuts + Abc_Var2Lit(o, n), vVars, 0, 0, &nCounter, NULL ); if ( RetValue == 0 ) printf( "Mismatch\n" ); if ( RetValue == -1 ) printf( "Timeout\n" ); nCubes[i][n] += nCounter; } // cleanup Vec_IntFree( vVars ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Gia_ManStop( p2 ); printf( "Onset = %5d. Offset = %5d. Onset = %5d. Offset = %5d.\n", nCubes[0][0], nCubes[0][1], nCubes[1][0], nCubes[1][1] ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_FxAddClauses( sat_solver * pSat, Vec_Int_t * vDivs, int iCiVarBeg, int iVarStart ) { int i, Func, pLits[3], nDivs = Vec_IntSize(vDivs)/4; assert( Vec_IntSize(vDivs) % 4 == 0 ); // create new var for each divisor for ( i = 0; i < nDivs; i++ ) { Func = Vec_IntEntry(vDivs, 4*i+0); pLits[0] = Vec_IntEntry(vDivs, 4*i+1); pLits[1] = Vec_IntEntry(vDivs, 4*i+2); pLits[2] = Vec_IntEntry(vDivs, 4*i+3); //printf( "Adding clause with vars %d %d -> %d\n", iCiVarBeg + Abc_Lit2Var(pLits[0]), iCiVarBeg + Abc_Lit2Var(pLits[1]), iVarStart + nDivs - 1 - i ); if ( Func == DIV_AND ) sat_solver_add_and( pSat, iVarStart + nDivs - 1 - i, iCiVarBeg + Abc_Lit2Var(pLits[0]), iCiVarBeg + Abc_Lit2Var(pLits[1]), Abc_LitIsCompl(pLits[0]), Abc_LitIsCompl(pLits[1]), 0 ); else if ( Func == DIV_XOR ) sat_solver_add_xor( pSat, iVarStart + nDivs - 1 - i, iCiVarBeg + Abc_Lit2Var(pLits[0]), iCiVarBeg + Abc_Lit2Var(pLits[1]), 0 ); else if ( Func == DIV_MUX ) sat_solver_add_mux( pSat, iVarStart + nDivs - 1 - i, iCiVarBeg + Abc_Lit2Var(pLits[0]), iCiVarBeg + Abc_Lit2Var(pLits[1]), iCiVarBeg + Abc_Lit2Var(pLits[2]), Abc_LitIsCompl(pLits[0]), Abc_LitIsCompl(pLits[1]), Abc_LitIsCompl(pLits[2]), 0 ); else assert( 0 ); } } int Bmc_FxComputeOne( Gia_Man_t * p, int nIterMax, int nDiv2Add ) { int Extra = 1000; // create SAT solver Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // compute parameters int nCiVars = Gia_ManCiNum(p); // PI count int iCiVarBeg = pCnf->nVars - nCiVars;//- 1; // first PI var int iCiVarCur = iCiVarBeg + nCiVars; // current unused PI var int n, Iter, RetValue; // create variables int iAuxVarStart = sat_solver_nvars(pSat) + Extra; // the aux var sat_solver_setnvars( pSat, iAuxVarStart + 1 + nIterMax ); for ( Iter = 0; Iter < nIterMax; Iter++ ) { Vec_Wec_t * vCubes = Vec_WecAlloc( 1000 ); // collect variables Vec_Int_t * vVar2Sat = Vec_IntAlloc( iCiVarCur-iCiVarBeg ), * vDivs; // for ( n = iCiVarCur - 1; n >= iCiVarBeg; n-- ) for ( n = iCiVarBeg; n < iCiVarCur; n++ ) Vec_IntPush( vVar2Sat, n ); // iterate through outputs printf( "\nIteration %d (Aux = %d)\n", Iter, iAuxVarStart + Iter ); RetValue = Bmc_FxSolve( pSat, 0, iAuxVarStart + Iter, vVar2Sat, 1, 1, NULL, vCubes ); if ( RetValue == 0 ) printf( "Mismatch\n" ); if ( RetValue == -1 ) printf( "Timeout\n" ); // print cubes //Div_CubePrint( vCubes, nCiVars ); vDivs = Div_CubePairs( vCubes, nCiVars, nDiv2Add ); Vec_WecFree( vCubes ); // add clauses and update variables Bmc_FxAddClauses( pSat, vDivs, iCiVarBeg, iCiVarCur ); iCiVarCur += Vec_IntSize(vDivs)/4; Vec_IntFree( vDivs ); // cleanup assert( Vec_IntSize(vVar2Sat) <= nCiVars + Extra ); Vec_IntFree( vVar2Sat ); } // cleanup sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcGen.c000066400000000000000000000137351300674244400227340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcGen.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Generating satisfying assignments.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcGen.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Gia_ManMoObj( Gia_Man_t * p, int iObj ) { return Vec_WrdEntryP( p->vSims, iObj * p->iPatsPi ); } static inline void Gia_ManMoSetCi( Gia_Man_t * p, int iObj ) { int w; word * pSims = Gia_ManMoObj( p, iObj ); for ( w = 0; w < p->iPatsPi; w++ ) pSims[w] = Gia_ManRandomW( 0 ); } static inline void Gia_ManMoSimAnd( Gia_Man_t * p, int iObj ) { int w; Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); word * pSims = Gia_ManMoObj( p, iObj ); word * pSims0 = Gia_ManMoObj( p, Gia_ObjFaninId0(pObj, iObj) ); word * pSims1 = Gia_ManMoObj( p, Gia_ObjFaninId1(pObj, iObj) ); if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) for ( w = 0; w < p->iPatsPi; w++ ) pSims[w] = ~(pSims0[w] | pSims1[w]); else for ( w = 0; w < p->iPatsPi; w++ ) pSims[w] = ~pSims0[w] & pSims1[w]; } else { if ( Gia_ObjFaninC1(pObj) ) for ( w = 0; w < p->iPatsPi; w++ ) pSims[w] = pSims0[w] & ~pSims1[w]; else for ( w = 0; w < p->iPatsPi; w++ ) pSims[w] = pSims0[w] & pSims1[w]; } } static inline void Gia_ManMoSetCo( Gia_Man_t * p, int iObj ) { int w; Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); word * pSims = Gia_ManMoObj( p, iObj ); word * pSims0 = Gia_ManMoObj( p, Gia_ObjFaninId0(pObj, iObj) ); if ( Gia_ObjFaninC0(pObj) ) { for ( w = 0; w < p->iPatsPi; w++ ) pSims[w] = ~pSims0[w]; } else { for ( w = 0; w < p->iPatsPi; w++ ) pSims[w] = pSims0[w]; } } void Gia_ManMoFindSimulate( Gia_Man_t * p, int nWords ) { int i, iObj; Gia_ManRandomW( 1 ); p->iPatsPi = nWords; if ( p->vSims ) Vec_WrdFill( p->vSims, nWords * Gia_ManObjNum(p), 0 ); else p->vSims = Vec_WrdStart( nWords * Gia_ManObjNum(p) ); Gia_ManForEachCiId( p, iObj, i ) Gia_ManMoSetCi( p, iObj ); Gia_ManForEachAndId( p, iObj ) Gia_ManMoSimAnd( p, iObj ); Gia_ManForEachCoId( p, iObj, i ) Gia_ManMoSetCo( p, iObj ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManTestSatEnum( Gia_Man_t * p ) { abctime clk = Abc_Clock(), clk2, clkTotal = 0; Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); int i, v, status, iLit, nWords = 1, iOutVar = 1, Count = 0; Vec_Int_t * vVars = Vec_IntAlloc( 1000 ); word * pSimInfo; // add literals to the solver iLit = Abc_Var2Lit( iOutVar, 0 ); status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status ); // simulate the AIG Gia_ManMoFindSimulate( p, nWords ); // print outputs pSimInfo = Gia_ManMoObj( p, Gia_ObjId(p, Gia_ManCo(p, 0)) ); for ( i = 0; i < 64*nWords; i++ ) printf( "%d", Abc_InfoHasBit( (unsigned *)pSimInfo, i ) ); printf( "\n" ); // iterate through the assignments for ( i = 0; i < 64*nWords; i++ ) { Vec_IntClear( vVars ); for ( v = 0; v < Gia_ManObjNum(p); v++ ) { if ( pCnf->pVarNums[v] == -1 ) continue; pSimInfo = Gia_ManMoObj( p, v ); if ( !Abc_InfoHasBit( (unsigned *)pSimInfo, i ) ) continue; Vec_IntPush( vVars, pCnf->pVarNums[v] ); } //sat_solver_act_var_clear( pSat ); //sat_solver_set_polarity( pSat, Vec_IntArray(vVars), Vec_IntSize(vVars) ); clk2 = Abc_Clock(); status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); clkTotal += Abc_Clock() - clk2; printf( "%c", status == l_True ? '+' : '-' ); if ( status == l_True ) Count++; } printf( "\n" ); printf( "Finished generating %d assignments. ", Count ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Abc_PrintTime( 1, "SAT solver time", clkTotal ); Vec_WrdFreeP( &p->vSims ); Vec_IntFree( vVars ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcICheck.c000066400000000000000000000456751300674244400233610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcICheck.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Performs specialized check.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcICheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p ) { Cnf_Dat_t * pCnf; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); pAig->nRegs = 0; pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Aig_ManStop( pAig ); return pCnf; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cnf_DataLiftGia( Cnf_Dat_t * p, Gia_Man_t * pGia, int nVarsPlus ) { Gia_Obj_t * pObj; int v; Gia_ManForEachObj( pGia, pObj, v ) if ( p->pVarNums[Gia_ObjId(pGia, pObj)] >= 0 ) p->pVarNums[Gia_ObjId(pGia, pObj)] += nVarsPlus; for ( v = 0; v < p->nLiterals; v++ ) p->pClauses[0][v] += 2*nVarsPlus; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Bmc_DeriveSolver( Gia_Man_t * p, Gia_Man_t * pMiter, Cnf_Dat_t * pCnf, int nFramesMax, int nTimeOut, int fVerbose ) { sat_solver * pSat; Vec_Int_t * vLits; Gia_Obj_t * pObj, * pObj0, * pObj1; int i, k, iVar0, iVar1, iVarOut; int VarShift = 0; // start the SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, Gia_ManRegNum(p) + Gia_ManCoNum(p) + pCnf->nVars * (nFramesMax + 1) ); sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); // add one large OR clause vLits = Vec_IntAlloc( Gia_ManCoNum(p) ); Gia_ManForEachCo( p, pObj, i ) Vec_IntPush( vLits, Abc_Var2Lit(Gia_ManRegNum(p) + i, 0) ); sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); // load the last timeframe Cnf_DataLiftGia( pCnf, pMiter, Gia_ManRegNum(p) + Gia_ManCoNum(p) ); VarShift += Gia_ManRegNum(p) + Gia_ManCoNum(p); // add XOR clauses Gia_ManForEachPo( p, pObj, i ) { pObj0 = Gia_ManPo( pMiter, 2*i+0 ); pObj1 = Gia_ManPo( pMiter, 2*i+1 ); iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj0)]; iVar1 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj1)]; iVarOut = Gia_ManRegNum(p) + i; sat_solver_add_xor( pSat, iVar0, iVar1, iVarOut, 0 ); } Gia_ManForEachRi( p, pObj, i ) { pObj0 = Gia_ManRi( pMiter, i ); pObj1 = Gia_ManRi( pMiter, i + Gia_ManRegNum(p) ); iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj0)]; iVar1 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj1)]; iVarOut = Gia_ManRegNum(p) + Gia_ManPoNum(p) + i; sat_solver_add_xor_and( pSat, iVarOut, iVar0, iVar1, i ); } // add timeframe clauses for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) assert( 0 ); // add other timeframes for ( k = 0; k < nFramesMax; k++ ) { // collect variables of the RO nodes Vec_IntClear( vLits ); Gia_ManForEachRo( pMiter, pObj, i ) Vec_IntPush( vLits, pCnf->pVarNums[Gia_ObjId(pMiter, pObj)] ); // lift CNF again Cnf_DataLiftGia( pCnf, pMiter, pCnf->nVars ); VarShift += pCnf->nVars; // stitch the clauses Gia_ManForEachRi( pMiter, pObj, i ) { iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj)]; iVar1 = Vec_IntEntry( vLits, i ); if ( iVar1 == -1 ) continue; sat_solver_add_buffer( pSat, iVar0, iVar1, 0 ); } // add equality clauses for the COs Gia_ManForEachPo( p, pObj, i ) { pObj0 = Gia_ManPo( pMiter, 2*i+0 ); pObj1 = Gia_ManPo( pMiter, 2*i+1 ); iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj0)]; iVar1 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj1)]; sat_solver_add_buffer( pSat, iVar0, iVar1, 0 ); } Gia_ManForEachRi( p, pObj, i ) { pObj0 = Gia_ManRi( pMiter, i ); pObj1 = Gia_ManRi( pMiter, i + Gia_ManRegNum(p) ); iVar0 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj0)]; iVar1 = pCnf->pVarNums[Gia_ObjId(pMiter, pObj1)]; sat_solver_add_buffer_enable( pSat, iVar0, iVar1, i, 0 ); } // add timeframe clauses for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) assert( 0 ); } // sat_solver_compress( pSat ); Cnf_DataLiftGia( pCnf, pMiter, -VarShift ); Vec_IntFree( vLits ); return pSat; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_PerformICheck( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fEmpty, int fVerbose ) { int fUseOldCnf = 0; Gia_Man_t * pMiter, * pTemp; Cnf_Dat_t * pCnf; sat_solver * pSat; Vec_Int_t * vLits, * vUsed; int i, status, Lit; int nLitsUsed, nLits, * pLits; abctime clkStart = Abc_Clock(); assert( nFramesMax > 0 ); assert( Gia_ManRegNum(p) > 0 ); if ( fVerbose ) printf( "Solving M-inductiveness for design %s with %d AND nodes and %d flip-flops:\n", Gia_ManName(p), Gia_ManAndNum(p), Gia_ManRegNum(p) ); // create miter pTemp = Gia_ManDup( p ); pMiter = Gia_ManMiter( p, pTemp, 0, 1, 1, 0, 0 ); Gia_ManStop( pTemp ); assert( Gia_ManPoNum(pMiter) == 2 * Gia_ManPoNum(p) ); assert( Gia_ManRegNum(pMiter) == 2 * Gia_ManRegNum(p) ); // derive CNF if ( fUseOldCnf ) pCnf = Cnf_DeriveGiaRemapped( pMiter ); else { pMiter = Jf_ManDeriveCnf( pTemp = pMiter, 0 ); Gia_ManStop( pTemp ); pCnf = (Cnf_Dat_t *)pMiter->pData; pMiter->pData = NULL; } // collect positive literals vLits = Vec_IntAlloc( Gia_ManCoNum(p) ); for ( i = 0; i < Gia_ManRegNum(p); i++ ) Vec_IntPush( vLits, Abc_Var2Lit(i, fEmpty) ); // iteratively compute a minimal M-inductive set of next-state functions nLitsUsed = fEmpty ? 0 : Vec_IntSize(vLits); vUsed = Vec_IntAlloc( Vec_IntSize(vLits) ); while ( 1 ) { int fChanges = 0; // derive SAT solver pSat = Bmc_DeriveSolver( p, pMiter, pCnf, nFramesMax, nTimeOut, fVerbose ); // sat_solver_bookmark( pSat ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) { printf( "Timeout reached after %d seconds.\n", nTimeOut ); break; } if ( status == l_True ) { printf( "The problem is satisfiable (the current set is not M-inductive).\n" ); break; } assert( status == l_False ); // call analize_final nLits = sat_solver_final( pSat, &pLits ); // mark used literals Vec_IntFill( vUsed, Vec_IntSize(vLits), 0 ); for ( i = 0; i < nLits; i++ ) Vec_IntWriteEntry( vUsed, Abc_Lit2Var(pLits[i]), 1 ); // check if there are any positive unused Vec_IntForEachEntry( vLits, Lit, i ) { assert( i == Abc_Lit2Var(Lit) ); if ( Abc_LitIsCompl(Lit) ) continue; if ( Vec_IntEntry(vUsed, i) ) continue; // positive literal became unused Vec_IntWriteEntry( vLits, i, Abc_LitNot(Lit) ); nLitsUsed--; fChanges = 1; } // report the results if ( fVerbose ) printf( "M =%4d : AIG =%8d. SAT vars =%8d. SAT conf =%8d. S =%6d. (%6.2f %%) ", nFramesMax, (nFramesMax+1) * Gia_ManAndNum(pMiter), Gia_ManRegNum(p) + Gia_ManCoNum(p) + sat_solver_nvars(pSat), sat_solver_nconflicts(pSat), nLitsUsed, 100.0 * nLitsUsed / Gia_ManRegNum(p) ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); // count the number of negative literals sat_solver_delete( pSat ); if ( !fChanges || fEmpty ) break; // break; // sat_solver_rollback( pSat ); } Cnf_DataFree( pCnf ); Gia_ManStop( pMiter ); Vec_IntFree( vLits ); Vec_IntFree( vUsed ); } /**Function************************************************************* Synopsis [Collect flops starting from the POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_PerformFindFlopOrder_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRegs ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjIsRo(p, pObj) ) Vec_IntPush( vRegs, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Bmc_PerformFindFlopOrder_rec( p, Gia_ObjFanin0(pObj), vRegs ); Bmc_PerformFindFlopOrder_rec( p, Gia_ObjFanin1(pObj), vRegs ); } void Bmc_PerformFindFlopOrder( Gia_Man_t * p, Vec_Int_t * vRegs ) { Gia_Obj_t * pObj; int i, iReg, k = 0; // start with POs Vec_IntClear( vRegs ); Gia_ManForEachPo( p, pObj, i ) Vec_IntPush( vRegs, Gia_ObjId(p, pObj) ); // add flop outputs in the B Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachObjVec( vRegs, p, pObj, i ) { assert( Gia_ObjIsPo(p, pObj) || Gia_ObjIsRo(p, pObj) ); if ( Gia_ObjIsRo(p, pObj) ) pObj = Gia_ObjRoToRi( p, pObj ); Bmc_PerformFindFlopOrder_rec( p, Gia_ObjFanin0(pObj), vRegs ); } // add dangling flops Gia_ManForEachRo( p, pObj, i ) if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) Vec_IntPush( vRegs, Gia_ObjId(p, pObj) ); // remove POs; keep flop outputs only; remap ObjId into CiId assert( Vec_IntSize(vRegs) == Gia_ManCoNum(p) ); Gia_ManForEachObjVec( vRegs, p, pObj, i ) { if ( i < Gia_ManPoNum(p) ) continue; iReg = Gia_ObjCioId(pObj) - Gia_ManPiNum(p); assert( iReg >= 0 && iReg < Gia_ManRegNum(p) ); Vec_IntWriteEntry( vRegs, k++, iReg ); } Vec_IntShrink( vRegs, k ); assert( Vec_IntSize(vRegs) == Gia_ManRegNum(p) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_PerformISearchOne( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fReverse, int fBackTopo, int fVerbose, Vec_Int_t * vLits ) { int fUseOldCnf = 0; Gia_Man_t * pMiter, * pTemp; Cnf_Dat_t * pCnf; sat_solver * pSat; Vec_Int_t * vRegs = NULL; // Vec_Int_t * vLits; int i, Iter, status; int nLitsUsed, RetValue = 0; abctime clkStart = Abc_Clock(); assert( nFramesMax > 0 ); assert( Gia_ManRegNum(p) > 0 ); // create miter pTemp = Gia_ManDup( p ); pMiter = Gia_ManMiter( p, pTemp, 0, 1, 1, 0, 0 ); Gia_ManStop( pTemp ); assert( Gia_ManPoNum(pMiter) == 2 * Gia_ManPoNum(p) ); assert( Gia_ManRegNum(pMiter) == 2 * Gia_ManRegNum(p) ); // derive CNF if ( fUseOldCnf ) pCnf = Cnf_DeriveGiaRemapped( pMiter ); else { extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); //pMiter = Jf_ManDeriveCnf( pTemp = pMiter, 0 ); //Gia_ManStop( pTemp ); //pCnf = (Cnf_Dat_t *)pMiter->pData; pMiter->pData = NULL; pCnf = Mf_ManGenerateCnf( pMiter, 8, 0, 0, 0 ); } /* // collect positive literals vLits = Vec_IntAlloc( Gia_ManCoNum(p) ); for ( i = 0; i < Gia_ManRegNum(p); i++ ) Vec_IntPush( vLits, Abc_Var2Lit(i, 0) ); */ // derive SAT solver pSat = Bmc_DeriveSolver( p, pMiter, pCnf, nFramesMax, nTimeOut, fVerbose ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_True ) { printf( "I = %4d : ", nFramesMax ); printf( "Problem is satisfiable.\n" ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Gia_ManStop( pMiter ); return 1; } if ( status == l_Undef ) { printf( "ICheck: Timeout reached after %d seconds. \n", nTimeOut ); RetValue = 1; goto cleanup; } assert( status == l_False ); // count the number of positive literals nLitsUsed = 0; for ( i = 0; i < Gia_ManRegNum(p); i++ ) if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) ) nLitsUsed++; // try removing variables vRegs = Vec_IntStartNatural( Gia_ManRegNum(p) ); if ( fBackTopo ) Bmc_PerformFindFlopOrder( p, vRegs ); if ( fReverse ) Vec_IntReverseOrder( vRegs ); // for ( Iter = 0; Iter < Gia_ManRegNum(p); Iter++ ) Vec_IntForEachEntry( vRegs, i, Iter ) { // i = fReverse ? Gia_ManRegNum(p) - 1 - Iter : Iter; if ( Abc_LitIsCompl(Vec_IntEntry(vLits, i)) ) continue; Vec_IntWriteEntry( vLits, i, Abc_LitNot(Vec_IntEntry(vLits, i)) ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_Undef ) { printf( "ICheck: Timeout reached after %d seconds. \n", nTimeOut ); RetValue = 1; goto cleanup; } if ( status == l_True ) Vec_IntWriteEntry( vLits, i, Abc_LitNot(Vec_IntEntry(vLits, i)) ); else if ( status == l_False ) nLitsUsed--; else assert( 0 ); // report the results //printf( "Round %d: ", o ); if ( fVerbose ) { printf( "I = %4d : AIG =%8d. SAT vars =%8d. SAT conf =%8d. S =%6d. (%6.2f %%) ", i, (nFramesMax+1) * Gia_ManAndNum(pMiter), Gia_ManRegNum(p) + Gia_ManCoNum(p) + sat_solver_nvars(pSat), sat_solver_nconflicts(pSat), nLitsUsed, 100.0 * nLitsUsed / Gia_ManRegNum(p) ); ABC_PRTr( "Time", Abc_Clock() - clkStart ); fflush( stdout ); } } // report the results //printf( "Round %d: ", o ); if ( fVerbose ) { printf( "M = %4d : AIG =%8d. SAT vars =%8d. SAT conf =%8d. S =%6d. (%6.2f %%) ", nFramesMax, (nFramesMax+1) * Gia_ManAndNum(pMiter), Gia_ManRegNum(p) + Gia_ManCoNum(p) + sat_solver_nvars(pSat), sat_solver_nconflicts(pSat), nLitsUsed, 100.0 * nLitsUsed / Gia_ManRegNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); fflush( stdout ); } cleanup: // cleanup sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Gia_ManStop( pMiter ); Vec_IntFree( vRegs ); // Vec_IntFree( vLits ); return RetValue; } Vec_Int_t * Bmc_PerformISearch( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fReverse, int fBackTopo, int fDump, int fVerbose ) { Vec_Int_t * vLits, * vFlops; int i, f; if ( fVerbose ) printf( "Solving M-inductiveness for design %s with %d AND nodes and %d flip-flops with %s %s flop order:\n", Gia_ManName(p), Gia_ManAndNum(p), Gia_ManRegNum(p), fReverse ? "reverse":"direct", fBackTopo ? "backward":"natural" ); fflush( stdout ); // collect positive literals vLits = Vec_IntAlloc( Gia_ManCoNum(p) ); for ( i = 0; i < Gia_ManRegNum(p); i++ ) Vec_IntPush( vLits, Abc_Var2Lit(i, 0) ); for ( f = 1; f <= nFramesMax; f++ ) if ( Bmc_PerformISearchOne( p, f, nTimeOut, fReverse, fBackTopo, fVerbose, vLits ) ) { Vec_IntFree( vLits ); return NULL; } // dump the numbers of the flops if ( fDump ) { int nLitsUsed = 0; for ( i = 0; i < Gia_ManRegNum(p); i++ ) if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) ) nLitsUsed++; printf( "The set contains %d (out of %d) next-state functions with 0-based numbers:\n", nLitsUsed, Gia_ManRegNum(p) ); for ( i = 0; i < Gia_ManRegNum(p); i++ ) if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) ) printf( "%d ", i ); printf( "\n" ); } // save flop indexes vFlops = Vec_IntAlloc( Gia_ManRegNum(p) ); for ( i = 0; i < Gia_ManRegNum(p); i++ ) if ( !Abc_LitIsCompl(Vec_IntEntry(vLits, i)) ) Vec_IntPush( vFlops, 1 ); else Vec_IntPush( vFlops, 0 ); Vec_IntFree( vLits ); return vFlops; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcInse.c000066400000000000000000000275401300674244400231200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcInse.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcInse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline void Gia_ParTestAlloc( Gia_Man_t * p, int nWords ) { assert( !p->pData ); p->pData = (unsigned *)ABC_ALLOC(word, 2*nWords*Gia_ManObjNum(p)); p->iData = nWords; } static inline void Gia_ParTestFree( Gia_Man_t * p ) { ABC_FREE( p->pData ); p->iData = 0; } static inline word * Gia_ParTestObj( Gia_Man_t * p, int Id ) { return (word *)p->pData + Id*(p->iData << 1); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManInseInit( Gia_Man_t * p, Vec_Int_t * vInit ) { Gia_Obj_t * pObj; word * pData1, * pData0; int i, k; Gia_ManForEachRi( p, pObj, k ) { pData0 = Gia_ParTestObj( p, Gia_ObjId(p, pObj) ); pData1 = pData0 + p->iData; if ( Vec_IntEntry(vInit, k) == 0 ) // 0 for ( i = 0; i < p->iData; i++ ) pData0[i] = ~(word)0, pData1[i] = 0; else if ( Vec_IntEntry(vInit, k) == 1 ) // 1 for ( i = 0; i < p->iData; i++ ) pData0[i] = 0, pData1[i] = ~(word)0; else // if ( Vec_IntEntry(vInit, k) > 1 ) // X for ( i = 0; i < p->iData; i++ ) pData0[i] = pData1[i] = 0; } } void Gia_ManInseSimulateObj( Gia_Man_t * p, int Id ) { Gia_Obj_t * pObj = Gia_ManObj( p, Id ); word * pData0, * pDataA0, * pDataB0; word * pData1, * pDataA1, * pDataB1; int i; if ( Gia_ObjIsAnd(pObj) ) { pData0 = Gia_ParTestObj( p, Id ); pData1 = pData0 + p->iData; if ( Gia_ObjFaninC0(pObj) ) { pDataA1 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) ); pDataA0 = pDataA1 + p->iData; if ( Gia_ObjFaninC1(pObj) ) { pDataB1 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) ); pDataB0 = pDataB1 + p->iData; } else { pDataB0 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) ); pDataB1 = pDataB0 + p->iData; } } else { pDataA0 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) ); pDataA1 = pDataA0 + p->iData; if ( Gia_ObjFaninC1(pObj) ) { pDataB1 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) ); pDataB0 = pDataB1 + p->iData; } else { pDataB0 = Gia_ParTestObj( p, Gia_ObjFaninId1(pObj, Id) ); pDataB1 = pDataB0 + p->iData; } } for ( i = 0; i < p->iData; i++ ) pData0[i] = pDataA0[i] | pDataB0[i], pData1[i] = pDataA1[i] & pDataB1[i]; } else if ( Gia_ObjIsCo(pObj) ) { pData0 = Gia_ParTestObj( p, Id ); pData1 = pData0 + p->iData; if ( Gia_ObjFaninC0(pObj) ) { pDataA1 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) ); pDataA0 = pDataA1 + p->iData; } else { pDataA0 = Gia_ParTestObj( p, Gia_ObjFaninId0(pObj, Id) ); pDataA1 = pDataA0 + p->iData; } for ( i = 0; i < p->iData; i++ ) pData0[i] = pDataA0[i], pData1[i] = pDataA1[i]; } else if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjIsPi(p, pObj) ) { pData0 = Gia_ParTestObj( p, Id ); pData1 = pData0 + p->iData; for ( i = 0; i < p->iData; i++ ) pData0[i] = Gia_ManRandomW(0), pData1[i] = ~pData0[i]; } else { int Id2 = Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)); pData0 = Gia_ParTestObj( p, Id ); pData1 = pData0 + p->iData; pDataA0 = Gia_ParTestObj( p, Id2 ); pDataA1 = pDataA0 + p->iData; for ( i = 0; i < p->iData; i++ ) pData0[i] = pDataA0[i], pData1[i] = pDataA1[i]; } } else if ( Gia_ObjIsConst0(pObj) ) { pData0 = Gia_ParTestObj( p, Id ); pData1 = pData0 + p->iData; for ( i = 0; i < p->iData; i++ ) pData0[i] = ~(word)0, pData1[i] = 0; } else assert( 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManInseHighestScore( Gia_Man_t * p, int * pCost ) { Gia_Obj_t * pObj; word * pData0, * pData1; int * pCounts, CountBest; int i, k, b, nPats, iPat; nPats = 64 * p->iData; pCounts = ABC_CALLOC( int, nPats ); Gia_ManForEachRi( p, pObj, k ) { pData0 = Gia_ParTestObj( p, Gia_ObjId(p, pObj) ); pData1 = pData0 + p->iData; for ( i = 0; i < p->iData; i++ ) for ( b = 0; b < 64; b++ ) pCounts[64*i+b] += (((pData0[i] >> b) & 1) || ((pData1[i] >> b) & 1)); // binary } iPat = 0; CountBest = pCounts[0]; for ( k = 1; k < nPats; k++ ) if ( CountBest < pCounts[k] ) CountBest = pCounts[k], iPat = k; *pCost = Gia_ManRegNum(p) - CountBest; // ternary ABC_FREE( pCounts ); return iPat; } void Gia_ManInseFindStarting( Gia_Man_t * p, int iPat, Vec_Int_t * vInit, Vec_Int_t * vInputs ) { Gia_Obj_t * pObj; word * pData0, * pData1; int i, k; Vec_IntClear( vInit ); Gia_ManForEachRi( p, pObj, k ) { pData0 = Gia_ParTestObj( p, Gia_ObjId(p, pObj) ); pData1 = pData0 + p->iData; for ( i = 0; i < p->iData; i++ ) assert( (pData0[i] & pData1[i]) == 0 ); if ( Abc_InfoHasBit( (unsigned *)pData0, iPat ) ) Vec_IntPush( vInit, 0 ); else if ( Abc_InfoHasBit( (unsigned *)pData1, iPat ) ) Vec_IntPush( vInit, 1 ); else Vec_IntPush( vInit, 2 ); } Gia_ManForEachPi( p, pObj, k ) { pData0 = Gia_ParTestObj( p, Gia_ObjId(p, pObj) ); pData1 = pData0 + p->iData; for ( i = 0; i < p->iData; i++ ) assert( (pData0[i] & pData1[i]) == 0 ); if ( Abc_InfoHasBit( (unsigned *)pData0, iPat ) ) Vec_IntPush( vInputs, 0 ); else if ( Abc_InfoHasBit( (unsigned *)pData1, iPat ) ) Vec_IntPush( vInputs, 1 ); else Vec_IntPush( vInputs, 2 ); } } Vec_Int_t * Gia_ManInseSimulate( Gia_Man_t * p, Vec_Int_t * vInit0, Vec_Int_t * vInputs, Vec_Int_t * vInit ) { Vec_Int_t * vRes; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int nFrames = Vec_IntSize(vInputs) / Gia_ManPiNum(p); int i, f, iBit = 0; assert( Vec_IntSize(vInputs) % Gia_ManPiNum(p) == 0 ); assert( Vec_IntSize(vInit0) == Gia_ManRegNum(p) ); assert( Vec_IntSize(vInit) == Gia_ManRegNum(p) ); Gia_ManConst0(p)->fMark0 = 0; Gia_ManForEachRi( p, pObj, i ) pObj->fMark0 = Vec_IntEntry(vInit0, i); for ( f = 0; f < nFrames; f++ ) { Gia_ManForEachPi( p, pObj, i ) pObj->fMark0 = Vec_IntEntry(vInputs, iBit++); Gia_ManForEachAnd( p, pObj, i ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachRi( p, pObj, i ) pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) pObjRo->fMark0 = pObjRi->fMark0; } assert( iBit == Vec_IntSize(vInputs) ); vRes = Vec_IntAlloc( Gia_ManRegNum(p) ); Gia_ManForEachRo( p, pObj, i ) assert( Vec_IntEntry(vInit, i) == 2 || Vec_IntEntry(vInit, i) == (int)pObj->fMark0 ); Gia_ManForEachRo( p, pObj, i ) Vec_IntPush( vRes, pObj->fMark0 | (Vec_IntEntry(vInit, i) != 2 ? 4 : 0) ); Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = 0; return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManInsePerform( Gia_Man_t * p, Vec_Int_t * vInit0, int nFrames, int nWords, int fVerbose ) { Vec_Int_t * vRes, * vInit, * vInputs; Gia_Obj_t * pObj; int i, f, iPat, Cost, Cost0; abctime clk, clkTotal = Abc_Clock(); Gia_ManRandomW( 1 ); if ( fVerbose ) printf( "Running with %d frames, %d words, and %sgiven init state.\n", nFrames, nWords, vInit0 ? "":"no " ); vInit = Vec_IntAlloc(0); Vec_IntFill( vInit, Gia_ManRegNum(p), 2 ); vInputs = Vec_IntStart( Gia_ManPiNum(p) * nFrames ); Gia_ParTestAlloc( p, nWords ); Gia_ManInseInit( p, vInit ); Cost0 = 0; Vec_IntForEachEntry( vInit, iPat, i ) Cost0 += ((iPat >> 1) & 1); if ( fVerbose ) printf( "Frame =%6d : Values =%6d (out of %6d)\n", 0, Cost0, Cost0 ); for ( f = 0; f < nFrames; f++ ) { clk = Abc_Clock(); Gia_ManForEachObj( p, pObj, i ) Gia_ManInseSimulateObj( p, i ); iPat = Gia_ManInseHighestScore( p, &Cost ); Gia_ManInseFindStarting( p, iPat, vInit, vInputs ); Gia_ManInseInit( p, vInit ); if ( fVerbose ) printf( "Frame =%6d : Values =%6d (out of %6d) ", f+1, Cost, Cost0 ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } Gia_ParTestFree( p ); vRes = Gia_ManInseSimulate( p, vInit0, vInputs, vInit ); Vec_IntFreeP( &vInit ); Vec_IntFreeP( &vInputs ); printf( "After %d frames, found a sequence to produce %d x-values (out of %d). ", f, Cost, Gia_ManRegNum(p) ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManInseTest( Gia_Man_t * p, Vec_Int_t * vInit0, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose ) { Vec_Int_t * vRes, * vInit; vInit = Vec_IntAlloc(0); Vec_IntFill( vInit, Gia_ManRegNum(p), 0 ); vRes = Gia_ManInsePerform( p, vInit, nFrames, nWords, fVerbose ); if ( vInit != vInit0 ) Vec_IntFree( vInit ); return vRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcLoad.c000066400000000000000000000153301300674244400230730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcLoad.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Experiments with CNF loading.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcLoad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Bmc_Load_t_ Bmc_Load_t; struct Bmc_Load_t_ { Bmc_AndPar_t * pPars; // parameters Gia_Man_t * pGia; // unrolled AIG sat_solver * pSat; // SAT solvers Vec_Int_t * vSat2Id; // maps SAT var into its node // Vec_Int_t * vCut; // cut in terms of GIA IDs // Vec_Int_t * vCnf; // CNF for the cut int nCallBacks1; int nCallBacks2; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Load CNF for the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_LoadGetSatVar( Bmc_Load_t * p, int Id ) { Gia_Obj_t * pObj = Gia_ManObj( p->pGia, Id ); if ( pObj->Value == 0 ) { pObj->Value = Vec_IntSize( p->vSat2Id ); Vec_IntPush( p->vSat2Id, Id ); sat_solver_setnvars( p->pSat, Vec_IntSize(p->vSat2Id) ); } return pObj->Value; } int Bmc_LoadAddCnf( void * pMan, int iLit ) { Bmc_Load_t * p = (Bmc_Load_t *)pMan; int Lits[3], iVar = Abc_Lit2Var(iLit); Gia_Obj_t * pObj = Gia_ManObj( p->pGia, Vec_IntEntry(p->vSat2Id, iVar) ); p->nCallBacks1++; if ( Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj) ) return 0; assert( Gia_ObjIsAnd(pObj) ); if ( (Abc_LitIsCompl(iLit) ? pObj->fMark1 : pObj->fMark0) ) return 0; Lits[0] = Abc_LitNot(iLit); if ( Abc_LitIsCompl(iLit) ) { Lits[1] = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId0p(p->pGia, pObj)), !Gia_ObjFaninC0(pObj) ); Lits[2] = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId1p(p->pGia, pObj)), !Gia_ObjFaninC1(pObj) ); sat_solver_clause_new( p->pSat, Lits, Lits + 3, 0 ); pObj->fMark1 = 1; } else { Lits[1] = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId0p(p->pGia, pObj)), Gia_ObjFaninC0(pObj) ); sat_solver_clause_new( p->pSat, Lits, Lits + 2, 0 ); Lits[1] = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId1p(p->pGia, pObj)), Gia_ObjFaninC1(pObj) ); sat_solver_clause_new( p->pSat, Lits, Lits + 2, 0 ); pObj->fMark0 = 1; } p->nCallBacks2++; return 1; } int Bmc_LoadAddCnf_rec( Bmc_Load_t * p, int Id ) { int iVar = Bmc_LoadGetSatVar( p, Id ); Gia_Obj_t * pObj = Gia_ManObj( p->pGia, Id ); if ( Gia_ObjIsAnd(pObj) && !(pObj->fMark0 && pObj->fMark1) ) { Bmc_LoadAddCnf( p, Abc_Var2Lit(iVar, 0) ); Bmc_LoadAddCnf( p, Abc_Var2Lit(iVar, 1) ); Bmc_LoadAddCnf_rec( p, Gia_ObjFaninId0(pObj, Id) ); Bmc_LoadAddCnf_rec( p, Gia_ObjFaninId1(pObj, Id) ); } return iVar; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bmc_Load_t * Bmc_LoadStart( Gia_Man_t * pGia ) { Bmc_Load_t * p; int Lit; Gia_ManSetPhase( pGia ); Gia_ManCleanValue( pGia ); Gia_ManCreateRefs( pGia ); p = ABC_CALLOC( Bmc_Load_t, 1 ); p->pGia = pGia; p->pSat = sat_solver_new(); p->vSat2Id = Vec_IntAlloc( 1000 ); Vec_IntPush( p->vSat2Id, 0 ); // create constant node Lit = Abc_Var2Lit( Bmc_LoadGetSatVar(p, 0), 1 ); sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); return p; } void Bmc_LoadStop( Bmc_Load_t * p ) { Vec_IntFree( p->vSat2Id ); sat_solver_delete( p->pSat ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bmc_LoadTest( Gia_Man_t * pGia, int fLoadCnf, int fVerbose ) { int nConfLimit = 0; Bmc_Load_t * p; Gia_Obj_t * pObj; int i, status, Lit; abctime clk = Abc_Clock(); // create the loading manager p = Bmc_LoadStart( pGia ); // add callback for CNF loading if ( fLoadCnf ) { p->pSat->pCnfMan = p; p->pSat->pCnfFunc = Bmc_LoadAddCnf; } // solve SAT problem for each PO Gia_ManForEachPo( pGia, pObj, i ) { if ( fLoadCnf ) Lit = Abc_Var2Lit( Bmc_LoadGetSatVar(p, Gia_ObjFaninId0p(pGia, pObj)), Gia_ObjFaninC0(pObj) ); else Lit = Abc_Var2Lit( Bmc_LoadAddCnf_rec(p, Gia_ObjFaninId0p(pGia, pObj)), Gia_ObjFaninC0(pObj) ); if ( fVerbose ) { printf( "Frame%4d : ", i ); printf( "Vars = %6d ", Vec_IntSize(p->vSat2Id) ); printf( "Clas = %6d ", sat_solver_nclauses(p->pSat) ); } status = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( fVerbose ) { printf( "Conf = %6d ", sat_solver_nconflicts(p->pSat) ); if ( status == l_False ) printf( "UNSAT " ); else if ( status == l_True ) printf( "SAT " ); else // if ( status == l_Undec ) printf( "UNDEC " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } } printf( "Callbacks = %d. Loadings = %d.\n", p->nCallBacks1, p->nCallBacks2 ); Bmc_LoadStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcMaxi.c000066400000000000000000000233421300674244400231140ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcMaxi.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcMaxi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p ) { Cnf_Dat_t * pCnf; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); pAig->nRegs = 0; pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Aig_ManStop( pAig ); return pCnf; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManMaxiUnfold( Gia_Man_t * p, int nFrames, int fUseVars, Vec_Int_t * vInit ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, f; pNew = Gia_ManStart( fUseVars * 2 * Gia_ManRegNum(p) + nFrames * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; // control/data variables Gia_ManForEachRo( p, pObj, i ) Gia_ManAppendCi( pNew ); Gia_ManForEachRo( p, pObj, i ) Gia_ManAppendCi( pNew ); // build timeframes assert( !vInit || Vec_IntSize(vInit) == Gia_ManRegNum(p) ); Gia_ManForEachRo( p, pObj, i ) { int Value = Vec_IntEntry( vInit, i ); int iCtrl = Gia_ManCiLit( pNew, i ); int iData = Gia_ManCiLit( pNew, Gia_ManRegNum(p)+i ); // decide based on Value if ( Value == 0 ) pObj->Value = fUseVars ? Gia_ManHashAnd(pNew, iCtrl, iData) : 0; else if ( Value == 1 ) pObj->Value = fUseVars ? Gia_ManHashOr(pNew, Abc_LitNot(iCtrl), iData) : 1; else if ( Value == 2 ) pObj->Value = Gia_ManHashAnd(pNew, iCtrl, iData); else if ( Value == 3 ) pObj->Value = Gia_ManHashOr(pNew, Abc_LitNot(iCtrl), iData); else if ( Value == 4 ) pObj->Value = 0; else if ( Value == 5 ) pObj->Value = 1; else assert( 0 ); } for ( f = 0; f < nFrames; f++ ) { 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) ); Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); Gia_ManForEachRo( p, pObj, i ) pObj->Value = Gia_ObjRoToRi(p, pObj)->Value; } Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); assert( Gia_ManPiNum(pNew) == 2 * Gia_ManRegNum(p) + nFrames * Gia_ManPiNum(p) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManMaxiPerform( Gia_Man_t * p, Vec_Int_t * vInit, int nFrames, int nTimeOut, int fVerbose ) { int nIterMax = 1000000; int i, iLit, Iter, status; int nLits, * pLits; abctime clkTotal = Abc_Clock(); abctime clkSat = 0; Vec_Int_t * vLits, * vMap; sat_solver * pSat; Gia_Obj_t * pObj; Gia_Man_t * p0 = Gia_ManMaxiUnfold( p, nFrames, 0, vInit ); Gia_Man_t * p1 = Gia_ManMaxiUnfold( p, nFrames, 1, vInit ); Gia_Man_t * pM = Gia_ManMiter( p0, p1, 0, 0, 0, 0, 0 ); Cnf_Dat_t * pCnf = Cnf_DeriveGiaRemapped( pM ); Gia_ManStop( p0 ); Gia_ManStop( p1 ); assert( Gia_ManRegNum(p) > 0 ); if ( fVerbose ) printf( "Running with %d frames and %sgiven init state.\n", nFrames, vInit ? "":"no " ); pSat = sat_solver_new(); sat_solver_setnvars( pSat, pCnf->nVars ); sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) assert( 0 ); // add one large OR clause vLits = Vec_IntAlloc( Gia_ManCoNum(p) ); Gia_ManForEachCo( pM, pObj, i ) Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], 0) ); sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); // create assumptions Vec_IntClear( vLits ); Gia_ManForEachPi( pM, pObj, i ) if ( i == Gia_ManRegNum(p) ) break; else if ( Vec_IntEntry(vInit, i) == 0 || Vec_IntEntry(vInit, i) == 1 ) Vec_IntPush( vLits, Abc_Var2Lit(pCnf->pVarNums[Gia_ObjId(pM, pObj)], 1) ); if ( fVerbose ) { printf( "Iter%6d : ", 0 ); printf( "Var =%10d ", sat_solver_nvars(pSat) ); printf( "Clause =%10d ", sat_solver_nclauses(pSat) ); printf( "Conflict =%10d ", sat_solver_nconflicts(pSat) ); printf( "Subset =%6d ", Vec_IntSize(vLits) ); Abc_PrintTime( 1, "Time", clkSat ); // ABC_PRTr( "Solver time", clkSat ); } for ( Iter = 0; Iter < nIterMax; Iter++ ) { abctime clk = Abc_Clock(); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); clkSat += Abc_Clock() - clk; if ( status == l_Undef ) { // if ( fVerbose ) // printf( "\n" ); printf( "Timeout reached after %d seconds and %d iterations. ", nTimeOut, Iter ); break; } if ( status == l_True ) { // if ( fVerbose ) // printf( "\n" ); printf( "The problem is SAT after %d iterations. ", Iter ); break; } assert( status == l_False ); nLits = sat_solver_final( pSat, &pLits ); if ( fVerbose ) { printf( "Iter%6d : ", Iter+1 ); printf( "Var =%10d ", sat_solver_nvars(pSat) ); printf( "Clause =%10d ", sat_solver_nclauses(pSat) ); printf( "Conflict =%10d ", sat_solver_nconflicts(pSat) ); printf( "Subset =%6d ", nLits ); Abc_PrintTime( 1, "Time", clkSat ); // ABC_PRTr( "Solver time", clkSat ); } if ( Vec_IntSize(vLits) == nLits ) { // if ( fVerbose ) // printf( "\n" ); printf( "Reached fixed point with %d entries after %d iterations. ", Vec_IntSize(vLits), Iter+1 ); break; } // collect used literals Vec_IntClear( vLits ); for ( i = 0; i < nLits; i++ ) Vec_IntPush( vLits, Abc_LitNot(pLits[i]) ); } // create map vMap = Vec_IntStart( pCnf->nVars ); Vec_IntForEachEntry( vLits, iLit, i ) Vec_IntWriteEntry( vMap, Abc_Lit2Var(iLit), 1 ); // create output Vec_IntFree( vLits ); vLits = Vec_IntDup(vInit); Gia_ManForEachPi( pM, pObj, i ) if ( i == Gia_ManRegNum(p) ) break; else if ( Vec_IntEntry(vLits, i) == 4 || Vec_IntEntry(vLits, i) == 5 ) Vec_IntWriteEntry( vLits, i, Vec_IntEntry(vLits, i) ); else if ( (Vec_IntEntry(vLits, i) == 0 || Vec_IntEntry(vLits, i) == 1) && !Vec_IntEntry(vMap, pCnf->pVarNums[Gia_ObjId(pM, pObj)]) ) Vec_IntWriteEntry( vLits, i, Vec_IntEntry(vLits, i) | 2 ); Vec_IntFree( vMap ); // cleanup sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Gia_ManStop( pM ); Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); return vLits; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManMaxiTest( Gia_Man_t * p, Vec_Int_t * vInit0, int nFrames, int nWords, int nTimeOut, int fSim, int fVerbose ) { Vec_Int_t * vRes, * vInit; vInit = vInit0 ? vInit0 : Vec_IntStart( Gia_ManRegNum(p) ); vRes = Gia_ManMaxiPerform( p, vInit, nFrames, nTimeOut, fVerbose ); if ( vInit != vInit0 ) Vec_IntFree( vInit ); return vRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcMulti.c000066400000000000000000000245651300674244400233200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcMulti.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Proving multi-output properties.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "proof/ssw/ssw.h" #include "misc/extra/extra.h" #include "aig/gia/giaAig.h" #include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Divides outputs into solved and unsolved.] Description [Return array of unsolved outputs to extract into a new AIG. Updates the resulting CEXes (vCexesOut) and current output map (vOutMap).] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManProcessOutputs( Vec_Ptr_t * vCexesIn, Vec_Ptr_t * vCexesOut, Vec_Int_t * vOutMap ) { Abc_Cex_t * pCex; Vec_Int_t * vLeftOver; int i, iOut; assert( Vec_PtrSize(vCexesIn) == Vec_IntSize(vOutMap) ); vLeftOver = Vec_IntAlloc( Vec_PtrSize(vCexesIn) ); Vec_IntForEachEntry( vOutMap, iOut, i ) { assert( Vec_PtrEntry(vCexesOut, iOut) == NULL ); pCex = (Abc_Cex_t *)Vec_PtrEntry( vCexesIn, i ); if ( pCex ) // found a CEX for output iOut { Vec_PtrWriteEntry( vCexesIn, i, NULL ); Vec_PtrWriteEntry( vCexesOut, iOut, pCex ); } else // still unsolved { Vec_IntWriteEntry( vOutMap, Vec_IntSize(vLeftOver), iOut ); Vec_IntPush( vLeftOver, i ); } } Vec_IntShrink( vOutMap, Vec_IntSize(vLeftOver) ); return vLeftOver; } /**Function************************************************************* Synopsis [Counts the number of constant 0 POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCountConst0PosGia( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManForEachPo( p, pObj, i ) Counter += (Gia_ObjFaninLit0p(p, pObj) == 0); return Counter; } int Gia_ManCountConst0Pos( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; Saig_ManForEachPo( p, pObj, i ) Counter += (Aig_ObjChild0(pObj) == Aig_ManConst0(p)); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMultiReport( Aig_Man_t * p, char * pStr, int nTotalPo, int nTotalSize, abctime clkStart ) { printf( "%3s : ", pStr ); printf( "PI =%6d ", Saig_ManPiNum(p) ); printf( "PO =%6d ", Saig_ManPoNum(p) ); printf( "FF =%7d ", Saig_ManRegNum(p) ); printf( "ND =%7d ", Aig_ManNodeNum(p) ); printf( "Solved =%7d (%5.1f %%) ", nTotalPo-Saig_ManPoNum(p), 100.0*(nTotalPo-Saig_ManPoNum(p))/Abc_MaxInt(1, nTotalPo) ); printf( "Size =%7d (%5.1f %%) ", Aig_ManObjNum(p), 100.0*Aig_ManObjNum(p)/Abc_MaxInt(1, nTotalSize) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Gia_ManMultiProveSyn( Aig_Man_t * p, int fVerbose, int fVeryVerbose ) { Aig_Man_t * pAig; Gia_Man_t * pGia, * pTemp; pGia = Gia_ManFromAig( p ); pGia = Gia_ManAigSyn2( pTemp = pGia, 1, 0, 0, 0, 0, 0, 0 ); Gia_ManStop( pTemp ); pAig = Gia_ManToAig( pGia, 0 ); Gia_ManStop( pGia ); return pAig; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_ManMultiProveAig( Aig_Man_t * p, Bmc_MulPar_t * pPars ) { Ssw_RarPars_t ParsSim, * pParsSim = &ParsSim; Saig_ParBmc_t ParsBmc, * pParsBmc = &ParsBmc; Vec_Int_t * vOutMap, * vLeftOver; Vec_Ptr_t * vCexes; Aig_Man_t * pTemp; abctime clkStart = Abc_Clock(); abctime nTimeToStop = pPars->TimeOutGlo ? Abc_Clock() + pPars->TimeOutGlo * CLOCKS_PER_SEC : 0; int nTotalPo = Saig_ManPoNum(p); int nTotalSize = Aig_ManObjNum(p); int TimeOutLoc = pPars->TimeOutLoc; int i, RetValue = -1; if ( pPars->fVerbose ) printf( "MultiProve parameters: Global timeout = %d sec. Local timeout = %d sec. Time increase = %d %%.\n", pPars->TimeOutGlo, pPars->TimeOutLoc, pPars->TimeOutInc ); if ( pPars->fVerbose ) printf( "Gap timout = %d sec. Per-output timeout = %d msec. Use synthesis = %d. Dump final = %d. Verbose = %d.\n", pPars->TimeOutGap, pPars->TimePerOut, pPars->fUseSyn, pPars->fDumpFinal, pPars->fVerbose ); // create output map vOutMap = Vec_IntStartNatural( Saig_ManPoNum(p) ); // maps current outputs into their original IDs vCexes = Vec_PtrStart( Saig_ManPoNum(p) ); // maps solved outputs into their CEXes (or markers) for ( i = 0; i < 1000; i++ ) { int nSolved = Vec_PtrCountZero(vCexes); // perform SIM3 Ssw_RarSetDefaultParams( pParsSim ); pParsSim->fSolveAll = 1; pParsSim->fNotVerbose = 1; pParsSim->fSilent = !pPars->fVeryVerbose; pParsSim->TimeOut = TimeOutLoc; pParsSim->nRandSeed = (i * 17) % 500; pParsSim->nWords = 5; RetValue *= Ssw_RarSimulate( p, pParsSim ); // sort outputs if ( p->vSeqModelVec ) { vLeftOver = Gia_ManProcessOutputs( p->vSeqModelVec, vCexes, vOutMap ); if ( Vec_IntSize(vLeftOver) == 0 ) break; // remove solved p = Saig_ManDupCones( pTemp = p, Vec_IntArray(vLeftOver), Vec_IntSize(vLeftOver) ); Vec_IntFree( vLeftOver ); Aig_ManStop( pTemp ); } if ( pPars->fVerbose ) Gia_ManMultiReport( p, "SIM", nTotalPo, nTotalSize, clkStart ); // check timeout if ( nTimeToStop && Abc_Clock() + TimeOutLoc * CLOCKS_PER_SEC > nTimeToStop ) { printf( "Global timeout (%d sec) is reached.\n", pPars->TimeOutGlo ); break; } // perform BMC Saig_ParBmcSetDefaultParams( pParsBmc ); pParsBmc->fSolveAll = 1; pParsBmc->fNotVerbose = 1; pParsBmc->fSilent = !pPars->fVeryVerbose; pParsBmc->nTimeOut = TimeOutLoc; pParsBmc->nTimeOutOne = pPars->TimePerOut; RetValue *= Saig_ManBmcScalable( p, pParsBmc ); if ( pPars->fVeryVerbose ) Abc_Print( 1, "Some outputs are SAT (%d out of %d) after %d frames.\n", Saig_ManPoNum(p) - Vec_PtrCountZero(p->vSeqModelVec), Saig_ManPoNum(p), pParsBmc->iFrame ); // sort outputs if ( p->vSeqModelVec ) { vLeftOver = Gia_ManProcessOutputs( p->vSeqModelVec, vCexes, vOutMap ); if ( Vec_IntSize(vLeftOver) == 0 ) break; // remove solved p = Saig_ManDupCones( pTemp = p, Vec_IntArray(vLeftOver), Vec_IntSize(vLeftOver) ); Vec_IntFree( vLeftOver ); Aig_ManStop( pTemp ); } if ( pPars->fVerbose ) Gia_ManMultiReport( p, "BMC", nTotalPo, nTotalSize, clkStart ); // check timeout if ( nTimeToStop && Abc_Clock() + TimeOutLoc * CLOCKS_PER_SEC > nTimeToStop ) { printf( "Global timeout (%d sec) is reached.\n", pPars->TimeOutGlo ); break; } // check gap timeout if ( pPars->TimeOutGap && pPars->TimeOutGap <= TimeOutLoc && nSolved == Vec_PtrCountZero(vCexes) ) { printf( "Gap timeout (%d sec) is reached.\n", pPars->TimeOutGap ); break; } // synthesize if ( pPars->fUseSyn ) { p = Gia_ManMultiProveSyn( pTemp = p, pPars->fVerbose, pPars->fVeryVerbose ); Aig_ManStop( pTemp ); if ( pPars->fVerbose ) Gia_ManMultiReport( p, "SYN", nTotalPo, nTotalSize, clkStart ); } // increase timeout TimeOutLoc += TimeOutLoc * pPars->TimeOutInc / 100; } Vec_IntFree( vOutMap ); if ( pPars->fVerbose ) printf( "The number of POs proved UNSAT by synthesis = %d.\n", Gia_ManCountConst0Pos(p) ); if ( pPars->fDumpFinal ) { char * pFileName = Extra_FileNameGenericAppend( p->pName, "_out.aig" ); Ioa_WriteAiger( p, pFileName, 0, 0 ); printf( "Final AIG was dumped into file \"%s\".\n", pFileName ); } Aig_ManStop( p ); return vCexes; } int Gia_ManMultiProve( Gia_Man_t * p, Bmc_MulPar_t * pPars ) { Aig_Man_t * pAig; if ( p->vSeqModelVec ) Vec_PtrFreeFree( p->vSeqModelVec ), p->vSeqModelVec = NULL; pAig = Gia_ManToAig( p, 0 ); p->vSeqModelVec = Gia_ManMultiProveAig( pAig, pPars ); // deletes pAig assert( Vec_PtrSize(p->vSeqModelVec) == Gia_ManPoNum(p) ); return Vec_PtrCountZero(p->vSeqModelVec) == Vec_PtrSize(p->vSeqModelVec) ? -1 : 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/bmcUnroll.c000066400000000000000000000445421300674244400234760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [bmcUnroll.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [Unrolling manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define UNR_DIFF_NULL 0x7FFF typedef struct Unr_Obj_t_ Unr_Obj_t; // 24 bytes + (RankMax-1) * 4 bytes struct Unr_Obj_t_ { unsigned hFan0; // address of the fanin unsigned hFan1; // address of the fanin unsigned fCompl0 : 1; // complemented bit unsigned fCompl1 : 1; // complemented bit unsigned uRDiff0 : 15; // rank diff of the fanin unsigned uRDiff1 : 15; // rank diff of the fanin unsigned fItIsPi : 1; // remember attributes unsigned fItIsPo : 1; // remember attributes unsigned RankMax : 15; // max rank diff between node and its fanout unsigned RankCur : 15; // cur rank of the node unsigned OrigId; // original object ID unsigned Res[1]; // RankMax entries }; struct Unr_Man_t_ { // input data Gia_Man_t * pGia; // the user's AIG manager Gia_Man_t * pFrames; // unrolled manager int nObjs; // the number of objects // intermediate data Vec_Int_t * vOrder; // ordering of GIA objects Vec_Int_t * vOrderLim; // beginning of each time frame Vec_Int_t * vTents; // tents of GIA objects Vec_Int_t * vRanks; // ranks of GIA objects // unrolling data int * pObjs; // storage for unroling objects int * pEnd; // end of storage Vec_Int_t * vObjLim; // handle of the first object in each frame Vec_Int_t * vCiMap; // mapping of GIA CIs into unrolling objects Vec_Int_t * vCoMap; // mapping of GIA POs into unrolling objects Vec_Int_t * vPiLits; // storage for PI literals }; static inline Unr_Obj_t * Unr_ManObj( Unr_Man_t * p, int h ) { assert( h >= 0 && h < p->pEnd - p->pObjs ); return (Unr_Obj_t *)(p->pObjs + h); } static inline int Unr_ObjSizeInt( int Rank ) { return 0xFFFFFFFE & (sizeof(Unr_Obj_t) / sizeof(int) + Rank); } static inline int Unr_ObjSize( Unr_Obj_t * pObj ) { return Unr_ObjSizeInt(pObj->RankMax); } static inline int Unr_ManFanin0Value( Unr_Man_t * p, Unr_Obj_t * pObj ) { Unr_Obj_t * pFanin = Unr_ManObj( p, pObj->hFan0 ); int Index = (pFanin->RankCur + pFanin->RankMax - pObj->uRDiff0) % pFanin->RankMax; assert( pFanin->RankCur < pFanin->RankMax ); assert( pObj->uRDiff0 < pFanin->RankMax ); return Abc_LitNotCond( pFanin->Res[Index], pObj->fCompl0 ); } static inline int Unr_ManFanin1Value( Unr_Man_t * p, Unr_Obj_t * pObj ) { Unr_Obj_t * pFanin = Unr_ManObj( p, pObj->hFan1 ); int Index = (pFanin->RankCur + pFanin->RankMax - pObj->uRDiff1) % pFanin->RankMax; assert( pFanin->RankCur < pFanin->RankMax ); assert( pObj->uRDiff1 < pFanin->RankMax ); return Abc_LitNotCond( pFanin->Res[Index], pObj->fCompl1 ); } static inline int Unr_ManObjReadValue( Unr_Obj_t * pObj ) { assert( pObj->RankCur >= 0 && pObj->RankCur < pObj->RankMax ); return pObj->Res[ pObj->RankCur ]; } static inline void Unr_ManObjSetValue( Unr_Obj_t * pObj, int Value ) { assert( Value >= 0 ); pObj->RankCur = (UNR_DIFF_NULL & (pObj->RankCur + 1)) % pObj->RankMax; pObj->Res[ pObj->RankCur ] = Value; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntWriteMaxEntry( Vec_Int_t * p, int i, int Entry ) { assert( i >= 0 && i < p->nSize ); p->pArray[i] = Abc_MaxInt( p->pArray[i], Entry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Unr_ManProfileRanks( Vec_Int_t * vRanks ) { int RankMax = Vec_IntFindMax( vRanks ); Vec_Int_t * vCounts = Vec_IntStart( RankMax+1 ); int i, Rank, Count, nExtras = 0; Vec_IntForEachEntry( vRanks, Rank, i ) Vec_IntAddToEntry( vCounts, Rank, 1 ); Vec_IntForEachEntry( vCounts, Count, i ) { if ( Count == 0 ) continue; printf( "%2d : %8d (%6.2f %%)\n", i, Count, 100.0 * Count / Vec_IntSize(vRanks) ); nExtras += Count * i; } printf( "Extra space = %d (%6.2f %%) ", nExtras, 100.0 * nExtras / Vec_IntSize(vRanks) ); Vec_IntFree( vCounts ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Unr_ManSetup_rec( Unr_Man_t * p, int iObj, int iTent, Vec_Int_t * vRoots ) { Gia_Obj_t * pObj; int iFanin; if ( Vec_IntEntry(p->vTents, iObj) >= 0 ) return; Vec_IntWriteEntry(p->vTents, iObj, iTent); pObj = Gia_ManObj( p->pGia, iObj ); if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ) { Unr_ManSetup_rec( p, (iFanin = Gia_ObjFaninId0(pObj, iObj)), iTent, vRoots ); Vec_IntWriteMaxEntry( p->vRanks, iFanin, Abc_MaxInt(0, iTent - Vec_IntEntry(p->vTents, iFanin) - 1) ); } if ( Gia_ObjIsAnd(pObj) ) { Unr_ManSetup_rec( p, (iFanin = Gia_ObjFaninId1(pObj, iObj)), iTent, vRoots ); Vec_IntWriteMaxEntry( p->vRanks, iFanin, Abc_MaxInt(0, iTent - Vec_IntEntry(p->vTents, iFanin) - 1) ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { Vec_IntPush( vRoots, (iFanin = Gia_ObjId(p->pGia, Gia_ObjRoToRi(p->pGia, pObj))) ); Vec_IntWriteMaxEntry( p->vRanks, iFanin, 0 ); } Vec_IntPush( p->vOrder, iObj ); } void Unr_ManSetup( Unr_Man_t * p, int fVerbose ) { Vec_Int_t * vRoots, * vRoots2, * vMap; Unr_Obj_t * pUnrObj; Gia_Obj_t * pObj; int i, k, t, iObj, nInts, * pInts; abctime clk = Abc_Clock(); // create zero rank assert( Vec_IntSize(p->vOrder) == 0 ); Vec_IntPush( p->vOrder, 0 ); Vec_IntPush( p->vOrderLim, Vec_IntSize(p->vOrder) ); Vec_IntWriteEntry( p->vTents, 0, 0 ); Vec_IntWriteEntry( p->vRanks, 0, 0 ); // start from the POs vRoots = Vec_IntAlloc( 100 ); vRoots2 = Vec_IntAlloc( 100 ); Gia_ManForEachPo( p->pGia, pObj, i ) Unr_ManSetup_rec( p, Gia_ObjId(p->pGia, pObj), 0, vRoots ); // collect tents while ( Vec_IntSize(vRoots) > 0 ) { Vec_IntPush( p->vOrderLim, Vec_IntSize(p->vOrder) ); Vec_IntClear( vRoots2 ); Vec_IntForEachEntry( vRoots, iObj, i ) Unr_ManSetup_rec( p, iObj, Vec_IntSize(p->vOrderLim)-1, vRoots2 ); ABC_SWAP( Vec_Int_t *, vRoots, vRoots2 ); } Vec_IntPush( p->vOrderLim, Vec_IntSize(p->vOrder) ); Vec_IntFree( vRoots ); Vec_IntFree( vRoots2 ); // allocate memory nInts = 0; Vec_IntForEachEntry( p->vOrder, iObj, i ) nInts += Unr_ObjSizeInt( Vec_IntEntry(p->vRanks, iObj) + 1 ); p->pObjs = pInts = ABC_CALLOC( int, nInts ); p->pEnd = p->pObjs + nInts; // create const0 node pUnrObj = Unr_ManObj( p, pInts - p->pObjs ); pUnrObj->RankMax = Vec_IntEntry(p->vRanks, 0) + 1; pUnrObj->uRDiff0 = pUnrObj->uRDiff1 = UNR_DIFF_NULL; pUnrObj->Res[0] = 0; // const0 // map the objects vMap = Vec_IntStartFull( p->nObjs ); Vec_IntWriteEntry( vMap, 0, pInts - p->pObjs ); pInts += Unr_ObjSize(pUnrObj); // mark up the entries assert( Vec_IntSize(p->vObjLim) == 0 ); for ( t = Vec_IntSize(p->vOrderLim) - 2; t >= 0; t-- ) { int Beg = Vec_IntEntry(p->vOrderLim, t); int End = Vec_IntEntry(p->vOrderLim, t+1); Vec_IntPush( p->vObjLim, pInts - p->pObjs ); Vec_IntForEachEntryStartStop( p->vOrder, iObj, i, Beg, End ) { pObj = Gia_ManObj( p->pGia, iObj ); pUnrObj = Unr_ManObj( p, pInts - p->pObjs ); pUnrObj->uRDiff0 = pUnrObj->uRDiff1 = UNR_DIFF_NULL; if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ) pUnrObj->uRDiff0 = Abc_MaxInt(0, Vec_IntEntry(p->vTents, iObj) - Vec_IntEntry(p->vTents, Gia_ObjFaninId0(pObj, iObj)) - 1); if ( Gia_ObjIsAnd(pObj) ) pUnrObj->uRDiff1 = Abc_MaxInt(0, Vec_IntEntry(p->vTents, iObj) - Vec_IntEntry(p->vTents, Gia_ObjFaninId1(pObj, iObj)) - 1); else if ( Gia_ObjIsRo(p->pGia, pObj) ) pUnrObj->uRDiff0 = 0; pUnrObj->RankMax = Vec_IntEntry(p->vRanks, iObj) + 1; pUnrObj->RankCur = UNR_DIFF_NULL; pUnrObj->OrigId = iObj; for ( k = 0; k < (int)pUnrObj->RankMax; k++ ) pUnrObj->Res[k] = -1; assert( ((pInts - p->pObjs) & 1) == 0 ); // align for 64-bits Vec_IntWriteEntry( vMap, iObj, pInts - p->pObjs ); pInts += Unr_ObjSize( pUnrObj ); } } assert( pInts - p->pObjs == nInts ); // label the objects Gia_ManForEachObj( p->pGia, pObj, i ) { if ( Vec_IntEntry(vMap, i) == -1 ) continue; pUnrObj = Unr_ManObj( p, Vec_IntEntry(vMap, i) ); if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ) { pUnrObj->hFan0 = Vec_IntEntry( vMap, Gia_ObjFaninId0(pObj, i) ); pUnrObj->fCompl0 = Gia_ObjFaninC0(pObj); pUnrObj->fItIsPo = Gia_ObjIsPo(p->pGia, pObj); } if ( Gia_ObjIsAnd(pObj) ) { pUnrObj->hFan1 = Vec_IntEntry( vMap, Gia_ObjFaninId1(pObj, i) ); pUnrObj->fCompl1 = Gia_ObjFaninC1(pObj); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) { pUnrObj->hFan0 = Vec_IntEntry( vMap, Gia_ObjId(p->pGia, Gia_ObjRoToRi(p->pGia, pObj)) ); pUnrObj->fCompl0 = 0; } else if ( Gia_ObjIsPi(p->pGia, pObj) ) { pUnrObj->hFan0 = Gia_ObjCioId(pObj); // remember CIO id pUnrObj->hFan1 = Vec_IntEntry(p->vTents, i); // remember tent pUnrObj->fItIsPi = 1; } } // store CI/PO objects; Gia_ManForEachCi( p->pGia, pObj, i ) Vec_IntPush( p->vCiMap, Vec_IntEntry(vMap, Gia_ObjId(p->pGia, pObj)) ); Gia_ManForEachCo( p->pGia, pObj, i ) Vec_IntPush( p->vCoMap, Vec_IntEntry(vMap, Gia_ObjId(p->pGia, pObj)) ); Vec_IntFreeP( &vMap ); // print stats if ( fVerbose ) { Unr_ManProfileRanks( p->vRanks ); printf( "Memory usage = %6.2f MB ", 4.0 * nInts / (1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } Vec_IntFreeP( &p->vOrder ); Vec_IntFreeP( &p->vOrderLim ); Vec_IntFreeP( &p->vRanks ); Vec_IntFreeP( &p->vTents ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Unr_Man_t * Unr_ManAlloc( Gia_Man_t * pGia ) { Unr_Man_t * p; p = ABC_CALLOC( Unr_Man_t, 1 ); p->pGia = pGia; p->nObjs = Gia_ManObjNum(pGia); p->vOrder = Vec_IntAlloc( p->nObjs ); p->vOrderLim = Vec_IntAlloc( 100 ); p->vTents = Vec_IntStartFull( p->nObjs ); p->vRanks = Vec_IntStart( p->nObjs ); p->vObjLim = Vec_IntAlloc( 100 ); p->vCiMap = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vCoMap = Vec_IntAlloc( Gia_ManCoNum(pGia) ); p->vPiLits = Vec_IntAlloc( 10000 ); p->pFrames = Gia_ManStart( 10000 ); p->pFrames->pName = Abc_UtilStrsav( pGia->pName ); Gia_ManHashStart( p->pFrames ); return p; } void Unr_ManFree( Unr_Man_t * p ) { Gia_ManStop( p->pFrames ); // intermediate data Vec_IntFreeP( &p->vOrder ); Vec_IntFreeP( &p->vOrderLim ); Vec_IntFreeP( &p->vTents ); Vec_IntFreeP( &p->vRanks ); // unrolling data Vec_IntFreeP( &p->vObjLim ); Vec_IntFreeP( &p->vCiMap ); Vec_IntFreeP( &p->vCoMap ); Vec_IntFreeP( &p->vPiLits ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Perform smart unrolling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Unr_Man_t * Unr_ManUnrollStart( Gia_Man_t * pGia, int fVerbose ) { int i, iHandle; Unr_Man_t * p; p = Unr_ManAlloc( pGia ); Unr_ManSetup( p, fVerbose ); for ( i = 0; i < Gia_ManRegNum(p->pGia); i++ ) if ( (iHandle = Vec_IntEntry(p->vCoMap, Gia_ManPoNum(p->pGia) + i)) != -1 ) Unr_ManObjSetValue( Unr_ManObj(p, iHandle), 0 ); return p; } Gia_Man_t * Unr_ManUnrollFrame( Unr_Man_t * p, int f ) { int i, iLit, iLit0, iLit1, hStart; for ( i = 0; i < Gia_ManPiNum(p->pGia); i++ ) Vec_IntPush( p->vPiLits, Gia_ManAppendCi(p->pFrames) ); hStart = Vec_IntEntry( p->vObjLim, Abc_MaxInt(0, Vec_IntSize(p->vObjLim)-1-f) ); while ( p->pObjs + hStart < p->pEnd ) { Unr_Obj_t * pUnrObj = Unr_ManObj( p, hStart ); if ( pUnrObj->uRDiff0 != UNR_DIFF_NULL && pUnrObj->uRDiff1 != UNR_DIFF_NULL ) // AND node { iLit0 = Unr_ManFanin0Value( p, pUnrObj ); iLit1 = Unr_ManFanin1Value( p, pUnrObj ); iLit = Gia_ManHashAnd( p->pFrames, iLit0, iLit1 ); Unr_ManObjSetValue( pUnrObj, iLit ); } else if ( pUnrObj->uRDiff0 != UNR_DIFF_NULL && pUnrObj->uRDiff1 == UNR_DIFF_NULL ) // PO/RI/RO { iLit = Unr_ManFanin0Value( p, pUnrObj ); Unr_ManObjSetValue( pUnrObj, iLit ); if ( pUnrObj->fItIsPo ) Gia_ManAppendCo( p->pFrames, iLit ); } else // PI (pUnrObj->hFan0 is CioId; pUnrObj->hFan1 is tent) { assert( pUnrObj->fItIsPi && f >= (int)pUnrObj->hFan1 ); iLit = Vec_IntEntry( p->vPiLits, Gia_ManPiNum(p->pGia) * (f - pUnrObj->hFan1) + pUnrObj->hFan0 ); Unr_ManObjSetValue( pUnrObj, iLit ); } hStart += Unr_ObjSize( pUnrObj ); } assert( p->pObjs + hStart == p->pEnd ); assert( Gia_ManPoNum(p->pFrames) == (f + 1) * Gia_ManPoNum(p->pGia) ); return p->pFrames; } Gia_Man_t * Unr_ManUnroll( Gia_Man_t * pGia, int nFrames ) { Unr_Man_t * p; Gia_Man_t * pFrames; int f; p = Unr_ManUnrollStart( pGia, 1 ); for ( f = 0; f < nFrames; f++ ) Unr_ManUnrollFrame( p, f ); pFrames = Gia_ManCleanup( p->pFrames ); Unr_ManFree( p ); return pFrames; } /**Function************************************************************* Synopsis [Perform naive unrolling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Unr_ManUnrollSimple( Gia_Man_t * pGia, int nFrames ) { Gia_Man_t * pFrames; Gia_Obj_t * pObj, * pObjRi; int f, i; pFrames = Gia_ManStart( 10000 ); pFrames->pName = Abc_UtilStrsav( pGia->pName ); Gia_ManHashAlloc( pFrames ); Gia_ManConst0(pGia)->Value = 0; Gia_ManForEachRi( pGia, pObj, i ) pObj->Value = 0; for ( f = 0; f < nFrames; f++ ) { Gia_ManForEachPi( pGia, pObj, i ) pObj->Value = Gia_ManAppendCi(pFrames); Gia_ManForEachRiRo( pGia, pObjRi, pObj, i ) pObj->Value = pObjRi->Value; Gia_ManForEachAnd( pGia, pObj, i ) pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( pGia, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); Gia_ManForEachPo( pGia, pObj, i ) Gia_ManAppendCo( pFrames, pObj->Value ); } Gia_ManHashStop( pFrames ); Gia_ManSetRegNum( pFrames, 0 ); pFrames = Gia_ManCleanup( pGia = pFrames ); Gia_ManStop( pGia ); return pFrames; } /**Function************************************************************* Synopsis [Perform evaluation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Unr_ManTest( Gia_Man_t * pGia, int nFrames ) { Gia_Man_t * pFrames0, * pFrames1; abctime clk = Abc_Clock(); pFrames0 = Unr_ManUnroll( pGia, nFrames ); Abc_PrintTime( 1, "Unroll ", Abc_Clock() - clk ); clk = Abc_Clock(); pFrames1 = Unr_ManUnrollSimple( pGia, nFrames ); Abc_PrintTime( 1, "UnrollS", Abc_Clock() - clk ); Gia_ManPrintStats( pFrames0, NULL ); Gia_ManPrintStats( pFrames1, NULL ); Gia_AigerWrite( pFrames0, "frames0.aig", 0, 0 ); Gia_AigerWrite( pFrames1, "frames1.aig", 0, 0 ); Gia_ManStop( pFrames0 ); Gia_ManStop( pFrames1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bmc/module.make000066400000000000000000000012161300674244400235100ustar00rootroot00000000000000SRC += src/sat/bmc/bmcBCore.c \ src/sat/bmc/bmcBmc.c \ src/sat/bmc/bmcBmc2.c \ src/sat/bmc/bmcBmc3.c \ src/sat/bmc/bmcBmcAnd.c \ src/sat/bmc/bmcBmci.c \ src/sat/bmc/bmcCexCare.c \ src/sat/bmc/bmcCexCut.c \ src/sat/bmc/bmcCexDepth.c \ src/sat/bmc/bmcCexMin1.c \ src/sat/bmc/bmcCexMin2.c \ src/sat/bmc/bmcCexTools.c \ src/sat/bmc/bmcChain.c \ src/sat/bmc/bmcClp.c \ src/sat/bmc/bmcEco.c \ src/sat/bmc/bmcExpand.c \ src/sat/bmc/bmcFault.c \ src/sat/bmc/bmcFx.c \ src/sat/bmc/bmcGen.c \ src/sat/bmc/bmcICheck.c \ src/sat/bmc/bmcInse.c \ src/sat/bmc/bmcLoad.c \ src/sat/bmc/bmcMaxi.c \ src/sat/bmc/bmcMulti.c \ src/sat/bmc/bmcUnroll.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/000077500000000000000000000000001300674244400215545ustar00rootroot00000000000000berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/license000066400000000000000000000021061300674244400231200ustar00rootroot00000000000000MiniSat -- Copyright (c) 2005, Niklas Sorensson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/module.make000066400000000000000000000005521300674244400237020ustar00rootroot00000000000000SRC += src/sat/bsat/satMem.c \ src/sat/bsat/satInter.c \ src/sat/bsat/satInterA.c \ src/sat/bsat/satInterB.c \ src/sat/bsat/satInterP.c \ src/sat/bsat/satProof.c \ src/sat/bsat/satSolver.c \ src/sat/bsat/satSolver2.c \ src/sat/bsat/satSolver2i.c \ src/sat/bsat/satStore.c \ src/sat/bsat/satTrace.c \ src/sat/bsat/satTruth.c \ src/sat/bsat/satUtil.c berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satChecker.c000066400000000000000000000130451300674244400237770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satChecker.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sat_solver.] Synopsis [Resolution proof checker.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: satChecker.c,v 1.4 2005/09/16 22:55:03 casem Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sat_PrintClause( Vec_Vec_t * vClauses, int Clause ) { Vec_Int_t * vClause; int i, Entry; printf( "Clause %d: {", Clause ); vClause = Vec_VecEntry( vClauses, Clause ); Vec_IntForEachEntry( vClause, Entry, i ) printf( " %d", Entry ); printf( " }\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sat_ProofResolve( Vec_Vec_t * vClauses, int Result, int Clause1, int Clause2 ) { Vec_Int_t * vResult = Vec_VecEntry( vClauses, Result ); Vec_Int_t * vClause1 = Vec_VecEntry( vClauses, Clause1 ); Vec_Int_t * vClause2 = Vec_VecEntry( vClauses, Clause2 ); int Entry1, Entry2, ResVar; int i, j, Counter = 0; Vec_IntForEachEntry( vClause1, Entry1, i ) Vec_IntForEachEntry( vClause2, Entry2, j ) if ( Entry1 == -Entry2 ) { ResVar = Entry1; Counter++; } if ( Counter != 1 ) { printf( "Error: Clause %d = Resolve(%d, %d): The number of pivot vars is %d.\n", Result, Clause1, Clause2, Counter ); Sat_PrintClause( vClauses, Clause1 ); Sat_PrintClause( vClauses, Clause2 ); return 0; } // create new clause assert( Vec_IntSize(vResult) == 0 ); Vec_IntForEachEntry( vClause1, Entry1, i ) if ( Entry1 != ResVar && Entry1 != -ResVar ) Vec_IntPushUnique( vResult, Entry1 ); assert( Vec_IntSize(vResult) + 1 == Vec_IntSize(vClause1) ); Vec_IntForEachEntry( vClause2, Entry2, i ) if ( Entry2 != ResVar && Entry2 != -ResVar ) Vec_IntPushUnique( vResult, Entry2 ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sat_ProofChecker( char * pFileName ) { FILE * pFile; Vec_Vec_t * vClauses; int c, i, Num, RetValue, Counter, Counter2, Clause1, Clause2; int RetValue; // open the file pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) return; // count the number of clauses Counter = Counter2 = 0; while ( (c = fgetc(pFile)) != EOF ) { Counter += (c == '\n'); Counter2 += (c == '*'); } vClauses = Vec_VecStart( Counter+1 ); printf( "The proof contains %d roots and %d resolution steps.\n", Counter-Counter2, Counter2 ); // read the clauses rewind( pFile ); for ( i = 1 ; ; i++ ) { RetValue = RetValue = fscanf( pFile, "%d", &Num ); if ( RetValue != 1 ) break; assert( Num == i ); while ( (c = fgetc( pFile )) == ' ' ); if ( c == '*' ) { RetValue = fscanf( pFile, "%d %d", &Clause1, &Clause2 ); assert( RetValue == 2 ); RetValue = fscanf( pFile, "%d", &Num ); assert( RetValue == 1 ); assert( Num == 0 ); if ( !Sat_ProofResolve( vClauses, i, Clause1, Clause2 ) ) { printf( "Error detected in the resolution proof.\n" ); Vec_VecFree( vClauses ); fclose( pFile ); return; } } else { ungetc( c, pFile ); while ( 1 ) { RetValue = fscanf( pFile, "%d", &Num ); assert( RetValue == 1 ); if ( Num == 0 ) break; Vec_VecPush( vClauses, i, (void *)Num ); } RetValue = fscanf( pFile, "%d", &Num ); assert( RetValue == 1 ); assert( Num == 0 ); } } assert( i-1 == Counter ); if ( Vec_IntSize( Vec_VecEntry(vClauses, Counter) ) != 0 ) printf( "The last clause is not empty.\n" ); else printf( "The empty clause is derived.\n" ); Vec_VecFree( vClauses ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satClause.h000066400000000000000000000447411300674244400236630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satMem.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT solver.] Synopsis [Memory management.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2004.] Revision [$Id: satMem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__sat__bsat__satMem_h #define ABC__sat__bsat__satMem_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //#define LEARNT_MAX_START_DEFAULT 0 #define LEARNT_MAX_START_DEFAULT 10000 #define LEARNT_MAX_INCRE_DEFAULT 1000 #define LEARNT_MAX_RATIO_DEFAULT 50 //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //================================================================================================= // Clause datatype + minor functions: typedef struct clause_t clause; struct clause_t { unsigned lrn : 1; unsigned mark : 1; unsigned partA : 1; unsigned lbd : 8; unsigned size : 21; lit lits[0]; }; // learned clauses have "hidden" literal (c->lits[c->size]) to store clause ID // data-structure for logging entries // memory is allocated in 2^nPageSize word-sized pages // the first 'word' of each page are stores the word limit // although clause memory pieces are aligned to 64-bit words // the integer clause handles are in terms of 32-bit unsigneds // allowing for the first bit to be used for labeling 2-lit clauses typedef struct Sat_Mem_t_ Sat_Mem_t; struct Sat_Mem_t_ { int nEntries[2]; // entry count int BookMarkH[2]; // bookmarks for handles int BookMarkE[2]; // bookmarks for entries int iPage[2]; // current memory page int nPageSize; // page log size in terms of ints unsigned uPageMask; // page mask unsigned uLearnedMask; // learned mask int nPagesAlloc; // page count allocated int ** pPages; // page pointers }; static inline int Sat_MemLimit( int * p ) { return p[0]; } static inline int Sat_MemIncLimit( int * p, int nInts ) { return p[0] += nInts; } static inline void Sat_MemWriteLimit( int * p, int nInts ) { p[0] = nInts; } static inline int Sat_MemHandPage( Sat_Mem_t * p, cla h ) { return h >> p->nPageSize; } static inline int Sat_MemHandShift( Sat_Mem_t * p, cla h ) { return h & p->uPageMask; } static inline int Sat_MemIntSize( int size, int lrn ) { return (size + 2 + lrn) & ~01; } static inline int Sat_MemClauseSize( clause * p ) { return Sat_MemIntSize(p->size, p->lrn); } static inline int Sat_MemClauseSize2( clause * p ) { return Sat_MemIntSize(p->size, 1); } //static inline clause * Sat_MemClause( Sat_Mem_t * p, int i, int k ) { assert(i <= p->iPage[i&1] && k <= Sat_MemLimit(p->pPages[i])); return (clause *)(p->pPages[i] + k ); } static inline clause * Sat_MemClause( Sat_Mem_t * p, int i, int k ) { assert( k ); return (clause *)(p->pPages[i] + k); } //static inline clause * Sat_MemClauseHand( Sat_Mem_t * p, cla h ) { assert(Sat_MemHandPage(p, h) <= p->iPage[(h & p->uLearnedMask) > 0]); assert(Sat_MemHandShift(p, h) >= 2 && Sat_MemHandShift(p, h) < (int)p->uLearnedMask); return Sat_MemClause( p, Sat_MemHandPage(p, h), Sat_MemHandShift(p, h) ); } static inline clause * Sat_MemClauseHand( Sat_Mem_t * p, cla h ) { return h ? Sat_MemClause( p, Sat_MemHandPage(p, h), Sat_MemHandShift(p, h) ) : NULL; } static inline int Sat_MemEntryNum( Sat_Mem_t * p, int lrn ) { return p->nEntries[lrn]; } static inline cla Sat_MemHand( Sat_Mem_t * p, int i, int k ) { return (i << p->nPageSize) | k; } static inline cla Sat_MemHandCurrent( Sat_Mem_t * p, int lrn ) { return (p->iPage[lrn] << p->nPageSize) | Sat_MemLimit( p->pPages[p->iPage[lrn]] ); } static inline int Sat_MemClauseUsed( Sat_Mem_t * p, cla h ) { return h < p->BookMarkH[(h & p->uLearnedMask) > 0]; } static inline double Sat_MemMemoryHand( Sat_Mem_t * p, cla h ) { return 1.0 * ((Sat_MemHandPage(p, h) + 2)/2 * (1 << (p->nPageSize+2)) + Sat_MemHandShift(p, h) * 4); } static inline double Sat_MemMemoryUsed( Sat_Mem_t * p, int lrn ) { return Sat_MemMemoryHand( p, Sat_MemHandCurrent(p, lrn) ); } static inline double Sat_MemMemoryAllUsed( Sat_Mem_t * p ) { return Sat_MemMemoryUsed( p, 0 ) + Sat_MemMemoryUsed( p, 1 ); } static inline double Sat_MemMemoryAll( Sat_Mem_t * p ) { return 1.0 * (p->iPage[0] + p->iPage[1] + 2) * (1 << (p->nPageSize+2)); } // p is memory storage // c is clause pointer // i is page number // k is page offset // print problem clauses NOT in proof mode #define Sat_MemForEachClause( p, c, i, k ) \ for ( i = 0; i <= p->iPage[0]; i += 2 ) \ for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize(c) ) if ( i == 0 && k == 2 ) {} else // print problem clauses in proof mode #define Sat_MemForEachClause2( p, c, i, k ) \ for ( i = 0; i <= p->iPage[0]; i += 2 ) \ for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize2(c) ) if ( i == 0 && k == 2 ) {} else #define Sat_MemForEachLearned( p, c, i, k ) \ for ( i = 1; i <= p->iPage[1]; i += 2 ) \ for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize(c) ) //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int clause_from_lit( lit l ) { return l + l + 1; } static inline int clause_is_lit( cla h ) { return (h & 1); } static inline lit clause_read_lit( cla h ) { return (lit)(h >> 1); } static inline int clause_learnt_h( Sat_Mem_t * p, cla h ) { return (h & p->uLearnedMask) > 0; } static inline int clause_learnt( clause * c ) { return c->lrn; } static inline int clause_id( clause * c ) { return c->lits[c->size]; } static inline void clause_set_id( clause * c, int id ) { c->lits[c->size] = id; } static inline int clause_size( clause * c ) { return c->size; } static inline lit * clause_begin( clause * c ) { return c->lits; } static inline lit * clause_end( clause * c ) { return c->lits + c->size; } static inline void clause_print( clause * c ) { int i; printf( "{ " ); for ( i = 0; i < clause_size(c); i++ ) printf( "%d ", (clause_begin(c)[i] & 1)? -(clause_begin(c)[i] >> 1) : clause_begin(c)[i] >> 1 ); printf( "}\n" ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocating vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sat_MemCountL( Sat_Mem_t * p ) { clause * c; int i, k, Count = 0; Sat_MemForEachLearned( p, c, i, k ) Count++; return Count; } /**Function************************************************************* Synopsis [Allocating vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sat_MemAlloc_( Sat_Mem_t * p, int nPageSize ) { assert( nPageSize > 8 && nPageSize < 32 ); memset( p, 0, sizeof(Sat_Mem_t) ); p->nPageSize = nPageSize; p->uLearnedMask = (unsigned)(1 << nPageSize); p->uPageMask = (unsigned)((1 << nPageSize) - 1); p->nPagesAlloc = 256; p->pPages = ABC_CALLOC( int *, p->nPagesAlloc ); p->pPages[0] = ABC_ALLOC( int, (1 << p->nPageSize) ); p->pPages[1] = ABC_ALLOC( int, (1 << p->nPageSize) ); p->iPage[0] = 0; p->iPage[1] = 1; Sat_MemWriteLimit( p->pPages[0], 2 ); Sat_MemWriteLimit( p->pPages[1], 2 ); } static inline Sat_Mem_t * Sat_MemAlloc( int nPageSize ) { Sat_Mem_t * p; p = ABC_CALLOC( Sat_Mem_t, 1 ); Sat_MemAlloc_( p, nPageSize ); return p; } /**Function************************************************************* Synopsis [Resetting vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sat_MemRestart( Sat_Mem_t * p ) { p->nEntries[0] = 0; p->nEntries[1] = 0; p->iPage[0] = 0; p->iPage[1] = 1; Sat_MemWriteLimit( p->pPages[0], 2 ); Sat_MemWriteLimit( p->pPages[1], 2 ); } /**Function************************************************************* Synopsis [Sets the bookmark.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sat_MemBookMark( Sat_Mem_t * p ) { p->BookMarkE[0] = p->nEntries[0]; p->BookMarkE[1] = p->nEntries[1]; p->BookMarkH[0] = Sat_MemHandCurrent( p, 0 ); p->BookMarkH[1] = Sat_MemHandCurrent( p, 1 ); } static inline void Sat_MemRollBack( Sat_Mem_t * p ) { p->nEntries[0] = p->BookMarkE[0]; p->nEntries[1] = p->BookMarkE[1]; p->iPage[0] = Sat_MemHandPage( p, p->BookMarkH[0] ); p->iPage[1] = Sat_MemHandPage( p, p->BookMarkH[1] ); Sat_MemWriteLimit( p->pPages[p->iPage[0]], Sat_MemHandShift( p, p->BookMarkH[0] ) ); Sat_MemWriteLimit( p->pPages[p->iPage[1]], Sat_MemHandShift( p, p->BookMarkH[1] ) ); } /**Function************************************************************* Synopsis [Freeing vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sat_MemFree_( Sat_Mem_t * p ) { int i; for ( i = 0; i < p->nPagesAlloc; i++ ) ABC_FREE( p->pPages[i] ); ABC_FREE( p->pPages ); } static inline void Sat_MemFree( Sat_Mem_t * p ) { Sat_MemFree_( p ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates new clause.] Description [The resulting clause is fully initialized.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sat_MemAppend( Sat_Mem_t * p, int * pArray, int nSize, int lrn, int fPlus1 ) { clause * c; int * pPage = p->pPages[p->iPage[lrn]]; int nInts = Sat_MemIntSize( nSize, lrn | fPlus1 ); assert( nInts + 3 < (1 << p->nPageSize) ); // need two extra at the begining of the page and one extra in the end if ( Sat_MemLimit(pPage) + nInts + 2 >= (1 << p->nPageSize) ) { p->iPage[lrn] += 2; if ( p->iPage[lrn] >= p->nPagesAlloc ) { p->pPages = ABC_REALLOC( int *, p->pPages, p->nPagesAlloc * 2 ); memset( p->pPages + p->nPagesAlloc, 0, sizeof(int *) * p->nPagesAlloc ); p->nPagesAlloc *= 2; } if ( p->pPages[p->iPage[lrn]] == NULL ) p->pPages[p->iPage[lrn]] = ABC_ALLOC( int, (1 << p->nPageSize) ); pPage = p->pPages[p->iPage[lrn]]; Sat_MemWriteLimit( pPage, 2 ); } pPage[Sat_MemLimit(pPage)] = 0; c = (clause *)(pPage + Sat_MemLimit(pPage)); c->size = nSize; c->lrn = lrn; if ( pArray ) memcpy( c->lits, pArray, sizeof(int) * nSize ); if ( lrn | fPlus1 ) c->lits[c->size] = p->nEntries[lrn]; p->nEntries[lrn]++; Sat_MemIncLimit( pPage, nInts ); return Sat_MemHandCurrent(p, lrn) - nInts; } /**Function************************************************************* Synopsis [Shrinking vector size.] Description [] SideEffects [This procedure does not update the number of entries.] SeeAlso [] ***********************************************************************/ static inline void Sat_MemShrink( Sat_Mem_t * p, int h, int lrn ) { assert( clause_learnt_h(p, h) == lrn ); assert( h && h <= Sat_MemHandCurrent(p, lrn) ); p->iPage[lrn] = Sat_MemHandPage(p, h); Sat_MemWriteLimit( p->pPages[p->iPage[lrn]], Sat_MemHandShift(p, h) ); } /**Function************************************************************* Synopsis [Compacts learned clauses by removing marked entries.] Description [Returns the number of remaining entries.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sat_MemCompactLearned( Sat_Mem_t * p, int fDoMove ) { clause * c, * cPivot = NULL; int i, k, iNew = 1, kNew = 2, nInts, fStartLooking, Counter = 0; int hLimit = Sat_MemHandCurrent(p, 1); if ( hLimit == Sat_MemHand(p, 1, 2) ) return 0; if ( fDoMove && p->BookMarkH[1] ) { // move the pivot assert( p->BookMarkH[1] >= Sat_MemHand(p, 1, 2) && p->BookMarkH[1] <= hLimit ); // get the pivot and remember it may be pointed offlimit cPivot = Sat_MemClauseHand( p, p->BookMarkH[1] ); if ( p->BookMarkH[1] < hLimit && !cPivot->mark ) { p->BookMarkH[1] = cPivot->lits[cPivot->size]; cPivot = NULL; } // else find the next used clause after cPivot } // iterate through the learned clauses fStartLooking = 0; Sat_MemForEachLearned( p, c, i, k ) { assert( c->lrn ); // skip marked entry if ( c->mark ) { // if pivot is a marked clause, start looking for the next non-marked one if ( cPivot && cPivot == c ) { fStartLooking = 1; cPivot = NULL; } continue; } // if we started looking before, we found it! if ( fStartLooking ) { fStartLooking = 0; p->BookMarkH[1] = c->lits[c->size]; } // compute entry size nInts = Sat_MemClauseSize(c); assert( !(nInts & 1) ); // check if we need to scroll to the next page if ( kNew + nInts >= (1 << p->nPageSize) ) { // set the limit of the current page if ( fDoMove ) Sat_MemWriteLimit( p->pPages[iNew], kNew ); // move writing position to the new page iNew += 2; kNew = 2; } if ( fDoMove ) { // make sure the result is the same as previous dry run assert( c->lits[c->size] == Sat_MemHand(p, iNew, kNew) ); // only copy the clause if it has changed if ( i != iNew || k != kNew ) { memmove( p->pPages[iNew] + kNew, c, sizeof(int) * nInts ); // c = Sat_MemClause( p, iNew, kNew ); // assersions do not hold during dry run c = (clause *)(p->pPages[iNew] + kNew); assert( nInts == Sat_MemClauseSize(c) ); } // set the new ID value c->lits[c->size] = Counter; } else // remember the address of the clause in the new location c->lits[c->size] = Sat_MemHand(p, iNew, kNew); // update writing position kNew += nInts; assert( iNew <= i && kNew < (1 << p->nPageSize) ); // update counter Counter++; } if ( fDoMove ) { // update the counter p->nEntries[1] = Counter; // update the page count p->iPage[1] = iNew; // set the limit of the last page Sat_MemWriteLimit( p->pPages[iNew], kNew ); // check if the pivot need to be updated if ( p->BookMarkH[1] ) { if ( cPivot ) { p->BookMarkH[1] = Sat_MemHandCurrent(p, 1); p->BookMarkE[1] = p->nEntries[1]; } else p->BookMarkE[1] = clause_id(Sat_MemClauseHand( p, p->BookMarkH[1] )); } } return Counter; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satInter.c000066400000000000000000001042501300674244400235130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satInter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sat_solver.] Synopsis [Interpolation package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $] ***********************************************************************/ #include #include #include #include #include "satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // variable assignments static const lit LIT_UNDEF = 0xffffffff; // interpolation manager struct Int_Man_t_ { // clauses of the problems Sto_Man_t * pCnf; // the set of CNF clauses for A and B int pGloVars[16]; // global variables int nGloVars; // the number of global variables // various parameters int fVerbose; // verbosiness flag int fProofVerif; // verifies the proof int fProofWrite; // writes the proof file int nVarsAlloc; // the allocated size of var arrays int nClosAlloc; // the allocated size of clause arrays // internal BCP int nRootSize; // the number of root level assignments int nTrailSize; // the number of assignments made lit * pTrail; // chronological order of assignments (size nVars) lit * pAssigns; // assignments by variable (size nVars) char * pSeens; // temporary mark (size nVars) Sto_Cls_t ** pReasons; // reasons for each assignment (size nVars) Sto_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) // interpolation data int nVarsAB; // the number of global variables int * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] unsigned * pInters; // storage for interpolants as truth tables (size nClauses) int nIntersAlloc; // the allocated size of truth table array int nWords; // the number of words in the truth table // proof recording int Counter; // counter of resolved clauses int * pProofNums; // the proof numbers for each clause (size nClauses) FILE * pFile; // the file for proof recording // internal verification lit * pResLits; // the literals of the resolvent int nResLits; // the number of literals of the resolvent int nResLitsAlloc;// the number of literals of the resolvent // runtime stats abctime timeBcp; // the runtime for BCP abctime timeTrace; // the runtime of trace construction abctime timeTotal; // the total runtime of interpolation }; // procedure to get hold of the clauses' truth table static inline unsigned * Int_ManTruthRead( Int_Man_t * p, Sto_Cls_t * pCls ) { return p->pInters + pCls->Id * p->nWords; } static inline void Int_ManTruthClear( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = 0; } static inline void Int_ManTruthFill( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~0; } static inline void Int_ManTruthCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; } static inline void Int_ManTruthAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; } static inline void Int_ManTruthOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; } static inline void Int_ManTruthOrNot( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= ~q[i]; } // reading/writing the proof for a clause static inline int Int_ManProofGet( Int_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } static inline void Int_ManProofSet( Int_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Int_Man_t * Int_ManAlloc() { Int_Man_t * p; // allocate the manager p = (Int_Man_t *)ABC_ALLOC( char, sizeof(Int_Man_t) ); memset( p, 0, sizeof(Int_Man_t) ); // verification p->nResLitsAlloc = (1<<16); p->pResLits = ABC_ALLOC( lit, p->nResLitsAlloc ); // parameters p->fProofWrite = 0; p->fProofVerif = 1; return p; } /**Function************************************************************* Synopsis [Allocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Int_ManSetGlobalVars( Int_Man_t * p, int nGloVars ) { p->nGloVars = nGloVars; return p->pGloVars; } /**Function************************************************************* Synopsis [Count common variables in the clauses of A and B.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Int_ManGlobalVars( Int_Man_t * p ) { Sto_Cls_t * pClause; int Var, nVarsAB, v; // mark the variable encountered in the clauses of A Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( !pClause->fA ) break; for ( v = 0; v < (int)pClause->nLits; v++ ) p->pVarTypes[lit_var(pClause->pLits[v])] = 1; } if ( p->nGloVars ) { for ( v = 0; v < p->nGloVars; v++ ) p->pVarTypes[ p->pGloVars[v] ] = - v - 1; return p->nGloVars; } // check variables that appear in clauses of B nVarsAB = 0; Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( pClause->fA ) continue; for ( v = 0; v < (int)pClause->nLits; v++ ) { Var = lit_var(pClause->pLits[v]); if ( p->pVarTypes[Var] == 1 ) // var of A { // change it into a global variable nVarsAB++; p->pVarTypes[Var] = -1; } } } // order global variables nVarsAB = 0; for ( v = 0; v < p->pCnf->nVars; v++ ) if ( p->pVarTypes[v] == -1 ) p->pVarTypes[v] -= nVarsAB++; //printf( "There are %d global variables.\n", nVarsAB ); return nVarsAB; } /**Function************************************************************* Synopsis [Resize proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int_ManResize( Int_Man_t * p ) { // check if resizing is needed if ( p->nVarsAlloc < p->pCnf->nVars ) { // find the new size if ( p->nVarsAlloc == 0 ) p->nVarsAlloc = 1; while ( p->nVarsAlloc < p->pCnf->nVars ) p->nVarsAlloc *= 2; // resize the arrays p->pTrail = ABC_REALLOC(lit, p->pTrail, p->nVarsAlloc ); p->pAssigns = ABC_REALLOC(lit, p->pAssigns, p->nVarsAlloc ); p->pSeens = ABC_REALLOC(char, p->pSeens, p->nVarsAlloc ); p->pVarTypes = ABC_REALLOC(int, p->pVarTypes, p->nVarsAlloc ); p->pReasons = ABC_REALLOC(Sto_Cls_t *, p->pReasons, p->nVarsAlloc ); p->pWatches = ABC_REALLOC(Sto_Cls_t *, p->pWatches, p->nVarsAlloc*2 ); } // clean the free space memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars ); memset( p->pSeens , 0, sizeof(char) * p->pCnf->nVars ); memset( p->pVarTypes, 0, sizeof(int) * p->pCnf->nVars ); memset( p->pReasons , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars ); memset( p->pWatches , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 ); // compute the number of common variables p->nVarsAB = Int_ManGlobalVars( p ); // compute the number of words in the truth table p->nWords = (p->nVarsAB <= 5 ? 1 : (1 << (p->nVarsAB - 5))); // check if resizing of clauses is needed if ( p->nClosAlloc < p->pCnf->nClauses ) { // find the new size if ( p->nClosAlloc == 0 ) p->nClosAlloc = 1; while ( p->nClosAlloc < p->pCnf->nClauses ) p->nClosAlloc *= 2; // resize the arrays p->pProofNums = ABC_REALLOC(int, p->pProofNums, p->nClosAlloc ); } memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses ); // check if resizing of truth tables is needed if ( p->nIntersAlloc < p->nWords * p->pCnf->nClauses ) { p->nIntersAlloc = p->nWords * p->pCnf->nClauses; p->pInters = ABC_REALLOC(unsigned, p->pInters, p->nIntersAlloc ); } // memset( p->pInters, 0, sizeof(unsigned) * p->nWords * p->pCnf->nClauses ); } /**Function************************************************************* Synopsis [Deallocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int_ManFree( Int_Man_t * p ) { /* printf( "Runtime stats:\n" ); ABC_PRT( "BCP ", p->timeBcp ); ABC_PRT( "Trace ", p->timeTrace ); ABC_PRT( "TOTAL ", p->timeTotal ); */ ABC_FREE( p->pInters ); ABC_FREE( p->pProofNums ); ABC_FREE( p->pTrail ); ABC_FREE( p->pAssigns ); ABC_FREE( p->pSeens ); ABC_FREE( p->pVarTypes ); ABC_FREE( p->pReasons ); ABC_FREE( p->pWatches ); ABC_FREE( p->pResLits ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int_ManPrintClause( Int_Man_t * p, Sto_Cls_t * pClause ) { int i; printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Int_ManProofGet(p, pClause) ); for ( i = 0; i < (int)pClause->nLits; i++ ) printf( " %d", pClause->pLits[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints the resolvent.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int_ManPrintResolvent( lit * pResLits, int nResLits ) { int i; printf( "Resolvent: {" ); for ( i = 0; i < nResLits; i++ ) printf( " %d", pResLits[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Records the proof.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_PrintBinary__( FILE * pFile, unsigned Sign[], int nBits ) { int Remainder, nWords; int w, i; Remainder = (nBits%(sizeof(unsigned)*8)); nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); for ( w = nWords-1; w >= 0; w-- ) for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1< 0) ); } /**Function************************************************************* Synopsis [Prints the interpolant for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int_ManPrintInterOne( Int_Man_t * p, Sto_Cls_t * pClause ) { printf( "Clause %2d : ", pClause->Id ); Extra_PrintBinary__( stdout, Int_ManTruthRead(p, pClause), (1 << p->nVarsAB) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Adds one clause to the watcher list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Int_ManWatchClause( Int_Man_t * p, Sto_Cls_t * pClause, lit Lit ) { assert( lit_check(Lit, p->pCnf->nVars) ); 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; } /**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Int_ManEnqueue( Int_Man_t * p, lit Lit, Sto_Cls_t * pReason ) { int Var = lit_var(Lit); if ( p->pAssigns[Var] != LIT_UNDEF ) return p->pAssigns[Var] == Lit; p->pAssigns[Var] = Lit; p->pReasons[Var] = pReason; p->pTrail[p->nTrailSize++] = Lit; //printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); return 1; } /**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Int_ManCancelUntil( Int_Man_t * p, int Level ) { lit Lit; int i, Var; for ( i = p->nTrailSize - 1; i >= Level; i-- ) { Lit = p->pTrail[i]; Var = lit_var( Lit ); p->pReasons[Var] = NULL; p->pAssigns[Var] = LIT_UNDEF; //printf( "cancelling var %d\n", Var ); } p->nTrailSize = Level; } /**Function************************************************************* Synopsis [Propagate one assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Sto_Cls_t * Int_ManPropagateOne( Int_Man_t * p, lit Lit ) { Sto_Cls_t ** ppPrev, * pCur, * pTemp; lit LitF = lit_neg(Lit); int i; // iterate through the literals ppPrev = p->pWatches + Lit; for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) { // 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; pTemp = pCur->pNext0; pCur->pNext0 = pCur->pNext1; pCur->pNext1 = pTemp; } assert( pCur->pLits[1] == LitF ); // if the first literal is true, the clause is satisfied if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) { ppPrev = &pCur->pNext1; 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 ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(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 *ppPrev = pCur->pNext1; // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) Int_ManWatchClause( p, pCur, pCur->pLits[1] ); break; } if ( i < (int)pCur->nLits ) // found new watch continue; // clause is unit - enqueue new implication if ( Int_ManEnqueue(p, pCur->pLits[0], pCur) ) { ppPrev = &pCur->pNext1; continue; } // conflict detected - return the conflict clause return pCur; } return NULL; } /**Function************************************************************* Synopsis [Propagate the current assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sto_Cls_t * Int_ManPropagate( Int_Man_t * p, int Start ) { Sto_Cls_t * pClause; int i; abctime clk = Abc_Clock(); for ( i = Start; i < p->nTrailSize; i++ ) { pClause = Int_ManPropagateOne( p, p->pTrail[i] ); if ( pClause ) { p->timeBcp += Abc_Clock() - clk; return pClause; } } p->timeBcp += Abc_Clock() - clk; return NULL; } /**Function************************************************************* Synopsis [Writes one root clause into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int_ManProofWriteOne( Int_Man_t * p, Sto_Cls_t * pClause ) { Int_ManProofSet( p, pClause, ++p->Counter ); if ( p->fProofWrite ) { int v; fprintf( p->pFile, "%d", Int_ManProofGet(p, pClause) ); for ( v = 0; v < (int)pClause->nLits; v++ ) fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) ); fprintf( p->pFile, " 0 0\n" ); } } /**Function************************************************************* Synopsis [Traces the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Int_ManProofTraceOne( Int_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal ) { Sto_Cls_t * pReason; int i, v, Var, PrevId; int fPrint = 0; abctime clk = Abc_Clock(); // collect resolvent literals if ( p->fProofVerif ) { assert( (int)pConflict->nLits <= p->nResLitsAlloc ); memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); p->nResLits = pConflict->nLits; } // mark all the variables in the conflict as seen for ( v = 0; v < (int)pConflict->nLits; v++ ) p->pSeens[lit_var(pConflict->pLits[v])] = 1; // start the anticedents // pFinal->pAntis = Vec_PtrAlloc( 32 ); // Vec_PtrPush( pFinal->pAntis, pConflict ); if ( p->pCnf->nClausesA ) Int_ManTruthCopy( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pConflict), p->nWords ); // follow the trail backwards PrevId = Int_ManProofGet(p, pConflict); for ( i = p->nTrailSize - 1; i >= 0; i-- ) { // skip literals that are not involved Var = lit_var(p->pTrail[i]); if ( !p->pSeens[Var] ) continue; p->pSeens[Var] = 0; // skip literals of the resulting clause pReason = p->pReasons[Var]; if ( pReason == NULL ) continue; assert( p->pTrail[i] == pReason->pLits[0] ); // add the variables to seen for ( v = 1; v < (int)pReason->nLits; v++ ) p->pSeens[lit_var(pReason->pLits[v])] = 1; // record the reason clause assert( Int_ManProofGet(p, pReason) > 0 ); p->Counter++; if ( p->fProofWrite ) fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Int_ManProofGet(p, pReason) ); PrevId = p->Counter; if ( p->pCnf->nClausesA ) { if ( p->pVarTypes[Var] == 1 ) // var of A Int_ManTruthOr( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pReason), p->nWords ); else Int_ManTruthAnd( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pReason), p->nWords ); } // resolve the temporary resolvent with the reason clause if ( p->fProofVerif ) { int v1, v2; if ( fPrint ) Int_ManPrintResolvent( p->pResLits, p->nResLits ); // check that the var is present in the resolvent for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == Var ) break; if ( v1 == p->nResLits ) printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); // remove this variable from the resolvent assert( lit_var(p->pResLits[v1]) == Var ); p->nResLits--; for ( ; v1 < p->nResLits; v1++ ) p->pResLits[v1] = p->pResLits[v1+1]; // add variables of the reason clause for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) { for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) break; // if it is a new variable, add it to the resolvent if ( v1 == p->nResLits ) { if ( p->nResLits == p->nResLitsAlloc ) printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n", pFinal->Id ); p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; continue; } // if the variable is the same, the literal should be the same too if ( p->pResLits[v1] == pReason->pLits[v2] ) continue; // the literal is different printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); } } // Vec_PtrPush( pFinal->pAntis, pReason ); } // unmark all seen variables // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // p->pSeens[lit_var(p->pTrail[i])] = 0; // check that the literals are unmarked // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); // use the resulting clause to check the correctness of resolution if ( p->fProofVerif ) { int v1, v2; if ( fPrint ) Int_ManPrintResolvent( p->pResLits, p->nResLits ); for ( v1 = 0; v1 < p->nResLits; v1++ ) { for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) if ( pFinal->pLits[v2] == p->pResLits[v1] ) break; if ( v2 < (int)pFinal->nLits ) continue; break; } if ( v1 < p->nResLits ) { printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); Int_ManPrintClause( p, pConflict ); Int_ManPrintResolvent( p->pResLits, p->nResLits ); Int_ManPrintClause( p, pFinal ); } // if there are literals in the clause that are not in the resolvent // it means that the derived resolvent is stronger than the clause // we can replace the clause with the resolvent by removing these literals if ( p->nResLits != (int)pFinal->nLits ) { for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ ) { for ( v2 = 0; v2 < p->nResLits; v2++ ) if ( pFinal->pLits[v1] == p->pResLits[v2] ) break; if ( v2 < p->nResLits ) continue; // remove literal v1 from the final clause pFinal->nLits--; for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ ) pFinal->pLits[v2] = pFinal->pLits[v2+1]; v1--; } assert( p->nResLits == (int)pFinal->nLits ); } } p->timeTrace += Abc_Clock() - clk; // return the proof pointer if ( p->pCnf->nClausesA ) { // Int_ManPrintInterOne( p, pFinal ); } Int_ManProofSet( p, pFinal, p->Counter ); // make sure the same proof ID is not asssigned to two consecutive clauses assert( p->pProofNums[pFinal->Id-1] != p->Counter ); return p->Counter; } /**Function************************************************************* Synopsis [Records the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Int_ManProofRecordOne( Int_Man_t * p, Sto_Cls_t * pClause ) { Sto_Cls_t * pConflict; int i; // empty clause never ends up there assert( pClause->nLits > 0 ); if ( pClause->nLits == 0 ) printf( "Error: Empty clause is attempted.\n" ); // add assumptions to the trail assert( !pClause->fRoot ); assert( p->nTrailSize == p->nRootSize ); // if any of the clause literals are already assumed // it means that the clause is redundant and can be skipped for ( i = 0; i < (int)pClause->nLits; i++ ) if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] ) return 1; for ( i = 0; i < (int)pClause->nLits; i++ ) if ( !Int_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) { assert( 0 ); // impossible return 0; } // propagate the assumptions pConflict = Int_ManPropagate( p, p->nRootSize ); if ( pConflict == NULL ) { assert( 0 ); // cannot prove return 0; } // skip the clause if it is weaker or the same as the conflict clause if ( pClause->nLits >= pConflict->nLits ) { // check if every literal of conflict clause can be found in the given clause int j; for ( i = 0; i < (int)pConflict->nLits; i++ ) { for ( j = 0; j < (int)pClause->nLits; j++ ) if ( pConflict->pLits[i] == pClause->pLits[j] ) break; if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found break; } if ( i == (int)pConflict->nLits ) // all lits are found { // undo to the root level Int_ManCancelUntil( p, p->nRootSize ); return 1; } } // construct the proof Int_ManProofTraceOne( p, pConflict, pClause ); // undo to the root level Int_ManCancelUntil( p, p->nRootSize ); // add large clauses to the watched lists if ( pClause->nLits > 1 ) { Int_ManWatchClause( p, pClause, pClause->pLits[0] ); Int_ManWatchClause( p, pClause, pClause->pLits[1] ); return 1; } assert( pClause->nLits == 1 ); // if the clause proved is unit, add it and propagate if ( !Int_ManEnqueue( p, pClause->pLits[0], pClause ) ) { assert( 0 ); // impossible return 0; } // propagate the assumption pConflict = Int_ManPropagate( p, p->nRootSize ); if ( pConflict ) { // construct the proof Int_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); return 0; } // update the root level p->nRootSize = p->nTrailSize; return 1; } /**Function************************************************************* Synopsis [Propagate the root clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Int_ManProcessRoots( Int_Man_t * p ) { Sto_Cls_t * pClause; int Counter; // make sure the root clauses are preceeding the learnt clauses Counter = 0; Sto_ManForEachClause( p->pCnf, pClause ) { assert( (int)pClause->fA == (Counter < (int)p->pCnf->nClausesA) ); assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots) ); Counter++; } assert( p->pCnf->nClauses == Counter ); // make sure the last clause if empty assert( p->pCnf->pTail->nLits == 0 ); // go through the root unit clauses p->nTrailSize = 0; Sto_ManForEachClauseRoot( p->pCnf, pClause ) { // create watcher lists for the root clauses if ( pClause->nLits > 1 ) { Int_ManWatchClause( p, pClause, pClause->pLits[0] ); Int_ManWatchClause( p, pClause, pClause->pLits[1] ); } // empty clause and large clauses if ( pClause->nLits != 1 ) continue; // unit clause assert( lit_check(pClause->pLits[0], p->pCnf->nVars) ); if ( !Int_ManEnqueue( p, pClause->pLits[0], pClause ) ) { // detected root level conflict // printf( "Error in Int_ManProcessRoots(): Detected a root-level conflict too early!\n" ); // assert( 0 ); // detected root level conflict Int_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found root level conflict!\n" ); return 0; } } // propagate the root unit clauses pClause = Int_ManPropagate( p, 0 ); if ( pClause ) { // detected root level conflict Int_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found root level conflict!\n" ); return 0; } // set the root level p->nRootSize = p->nTrailSize; return 1; } /**Function************************************************************* Synopsis [Records the proof.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Int_ManPrepareInter( Int_Man_t * p ) { // elementary truth tables unsigned uTruths[8][8] = { { 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 } }; Sto_Cls_t * pClause; int Var, VarAB, v; assert( p->nVarsAB <= 8 ); // set interpolants for root clauses Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( !pClause->fA ) // clause of B { Int_ManTruthFill( Int_ManTruthRead(p, pClause), p->nWords ); // Int_ManPrintInterOne( p, pClause ); continue; } // clause of A Int_ManTruthClear( Int_ManTruthRead(p, pClause), p->nWords ); for ( v = 0; v < (int)pClause->nLits; v++ ) { Var = lit_var(pClause->pLits[v]); if ( p->pVarTypes[Var] < 0 ) // global var { VarAB = -p->pVarTypes[Var]-1; assert( VarAB >= 0 && VarAB < p->nVarsAB ); if ( lit_sign(pClause->pLits[v]) ) // negative var Int_ManTruthOrNot( Int_ManTruthRead(p, pClause), uTruths[VarAB], p->nWords ); else Int_ManTruthOr( Int_ManTruthRead(p, pClause), uTruths[VarAB], p->nWords ); } } // Int_ManPrintInterOne( p, pClause ); } } /**Function************************************************************* Synopsis [Computes interpolant for the given CNF.] Description [Returns the number of common variable found and interpolant. Returns 0, if something did not work.] SideEffects [] SeeAlso [] ***********************************************************************/ int Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult ) { Sto_Cls_t * pClause; int RetValue = 1; abctime clkTotal = Abc_Clock(); // check that the CNF makes sense assert( pCnf->nVars > 0 && pCnf->nClauses > 0 ); p->pCnf = pCnf; p->fVerbose = fVerbose; *ppResult = NULL; // adjust the manager Int_ManResize( p ); // prepare the interpolant computation Int_ManPrepareInter( p ); // construct proof for each clause // start the proof if ( p->fProofWrite ) { p->pFile = fopen( "proof.cnf_", "w" ); p->Counter = 0; } // write the root clauses Sto_ManForEachClauseRoot( p->pCnf, pClause ) Int_ManProofWriteOne( p, pClause ); // propagate root level assignments if ( Int_ManProcessRoots( p ) ) { // if there is no conflict, consider learned clauses Sto_ManForEachClause( p->pCnf, pClause ) { if ( pClause->fRoot ) continue; if ( !Int_ManProofRecordOne( p, pClause ) ) { RetValue = 0; break; } } } // stop the proof if ( p->fProofWrite ) { fclose( p->pFile ); p->pFile = NULL; } if ( fVerbose ) { printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f MB\n", p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter, 1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), 1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) ); p->timeTotal += Abc_Clock() - clkTotal; } *ppResult = Int_ManTruthRead( p, p->pCnf->pTail ); return p->nVarsAB; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satInterA.c000066400000000000000000001045501300674244400236170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satInter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sat_solver.] Synopsis [Interpolation package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $] ***********************************************************************/ #include #include #include #include #include "satStore.h" #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // variable assignments static const lit LIT_UNDEF = 0xffffffff; // interpolation manager struct Inta_Man_t_ { // clauses of the problems Sto_Man_t * pCnf; // the set of CNF clauses for A and B Vec_Int_t * vVarsAB; // the array of global variables // various parameters int fVerbose; // verbosiness flag int fProofVerif; // verifies the proof int fProofWrite; // writes the proof file int nVarsAlloc; // the allocated size of var arrays int nClosAlloc; // the allocated size of clause arrays // internal BCP int nRootSize; // the number of root level assignments int nTrailSize; // the number of assignments made lit * pTrail; // chronological order of assignments (size nVars) lit * pAssigns; // assignments by variable (size nVars) char * pSeens; // temporary mark (size nVars) Sto_Cls_t ** pReasons; // reasons for each assignment (size nVars) Sto_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) // interpolation data Aig_Man_t * pAig; // the AIG manager for recording the interpolant int * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] Aig_Obj_t ** pInters; // storage for interpolants as truth tables (size nClauses) int nIntersAlloc; // the allocated size of truth table array // proof recording int Counter; // counter of resolved clauses int * pProofNums; // the proof numbers for each clause (size nClauses) FILE * pFile; // the file for proof recording // internal verification Vec_Int_t * vResLits; // runtime stats abctime timeBcp; // the runtime for BCP abctime timeTrace; // the runtime of trace construction abctime timeTotal; // the total runtime of interpolation }; // procedure to get hold of the clauses' truth table static inline Aig_Obj_t ** Inta_ManAigRead( Inta_Man_t * pMan, Sto_Cls_t * pCls ) { return pMan->pInters + pCls->Id; } static inline void Inta_ManAigClear( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst0(pMan->pAig); } static inline void Inta_ManAigFill( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst1(pMan->pAig); } static inline void Inta_ManAigCopy( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = *q; } static inline void Inta_ManAigAnd( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_And(pMan->pAig, *p, *q); } static inline void Inta_ManAigOr( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, *q); } static inline void Inta_ManAigOrNot( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(*q)); } static inline void Inta_ManAigOrVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_IthVar(pMan->pAig, v)); } static inline void Inta_ManAigOrNotVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(Aig_IthVar(pMan->pAig, v))); } // reading/writing the proof for a clause static inline int Inta_ManProofGet( Inta_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } static inline void Inta_ManProofSet( Inta_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Inta_Man_t * Inta_ManAlloc() { Inta_Man_t * p; // allocate the manager p = (Inta_Man_t *)ABC_ALLOC( char, sizeof(Inta_Man_t) ); memset( p, 0, sizeof(Inta_Man_t) ); // verification p->vResLits = Vec_IntAlloc( 1000 ); // parameters p->fProofWrite = 0; p->fProofVerif = 1; return p; } /**Function************************************************************* Synopsis [Count common variables in the clauses of A and B.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inta_ManGlobalVars( Inta_Man_t * p ) { Sto_Cls_t * pClause; int LargeNum = -100000000; int Var, nVarsAB, v; // mark the variable encountered in the clauses of A Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( !pClause->fA ) break; for ( v = 0; v < (int)pClause->nLits; v++ ) p->pVarTypes[lit_var(pClause->pLits[v])] = 1; } // check variables that appear in clauses of B nVarsAB = 0; Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( pClause->fA ) continue; for ( v = 0; v < (int)pClause->nLits; v++ ) { Var = lit_var(pClause->pLits[v]); if ( p->pVarTypes[Var] == 1 ) // var of A { // change it into a global variable nVarsAB++; p->pVarTypes[Var] = LargeNum; } } } assert( nVarsAB <= Vec_IntSize(p->vVarsAB) ); // order global variables nVarsAB = 0; Vec_IntForEachEntry( p->vVarsAB, Var, v ) p->pVarTypes[Var] = -(1+nVarsAB++); // check that there is no extra global variables for ( v = 0; v < p->pCnf->nVars; v++ ) assert( p->pVarTypes[v] != LargeNum ); return nVarsAB; } /**Function************************************************************* Synopsis [Resize proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inta_ManResize( Inta_Man_t * p ) { p->Counter = 0; // check if resizing is needed if ( p->nVarsAlloc < p->pCnf->nVars ) { // find the new size if ( p->nVarsAlloc == 0 ) p->nVarsAlloc = 1; while ( p->nVarsAlloc < p->pCnf->nVars ) p->nVarsAlloc *= 2; // resize the arrays p->pTrail = ABC_REALLOC(lit, p->pTrail, p->nVarsAlloc ); p->pAssigns = ABC_REALLOC(lit, p->pAssigns, p->nVarsAlloc ); p->pSeens = ABC_REALLOC(char, p->pSeens, p->nVarsAlloc ); p->pVarTypes = ABC_REALLOC(int, p->pVarTypes, p->nVarsAlloc ); p->pReasons = ABC_REALLOC(Sto_Cls_t *, p->pReasons, p->nVarsAlloc ); p->pWatches = ABC_REALLOC(Sto_Cls_t *, p->pWatches, p->nVarsAlloc*2 ); } // clean the free space memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars ); memset( p->pSeens , 0, sizeof(char) * p->pCnf->nVars ); memset( p->pVarTypes, 0, sizeof(int) * p->pCnf->nVars ); memset( p->pReasons , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars ); memset( p->pWatches , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 ); // compute the number of common variables Inta_ManGlobalVars( p ); // check if resizing of clauses is needed if ( p->nClosAlloc < p->pCnf->nClauses ) { // find the new size if ( p->nClosAlloc == 0 ) p->nClosAlloc = 1; while ( p->nClosAlloc < p->pCnf->nClauses ) p->nClosAlloc *= 2; // resize the arrays p->pProofNums = ABC_REALLOC( int, p->pProofNums, p->nClosAlloc ); } memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses ); // check if resizing of truth tables is needed if ( p->nIntersAlloc < p->pCnf->nClauses ) { p->nIntersAlloc = p->pCnf->nClauses; p->pInters = ABC_REALLOC( Aig_Obj_t *, p->pInters, p->nIntersAlloc ); } memset( p->pInters, 0, sizeof(Aig_Obj_t *) * p->pCnf->nClauses ); } /**Function************************************************************* Synopsis [Deallocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inta_ManFree( Inta_Man_t * p ) { /* printf( "Runtime stats:\n" ); ABC_PRT( "BCP ", p->timeBcp ); ABC_PRT( "Trace ", p->timeTrace ); ABC_PRT( "TOTAL ", p->timeTotal ); */ ABC_FREE( p->pInters ); ABC_FREE( p->pProofNums ); ABC_FREE( p->pTrail ); ABC_FREE( p->pAssigns ); ABC_FREE( p->pSeens ); ABC_FREE( p->pVarTypes ); ABC_FREE( p->pReasons ); ABC_FREE( p->pWatches ); Vec_IntFree( p->vResLits ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inta_ManPrintClause( Inta_Man_t * p, Sto_Cls_t * pClause ) { int i; printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Inta_ManProofGet(p, pClause) ); for ( i = 0; i < (int)pClause->nLits; i++ ) printf( " %d", pClause->pLits[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints the resolvent.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inta_ManPrintResolvent( Vec_Int_t * vResLits ) { int i, Entry; printf( "Resolvent: {" ); Vec_IntForEachEntry( vResLits, Entry, i ) printf( " %d", Entry ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints the interpolant for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inta_ManPrintInterOne( Inta_Man_t * p, Sto_Cls_t * pClause ) { printf( "Clause %2d : ", pClause->Id ); // Extra_PrintBinary___( stdout, Inta_ManAigRead(p, pClause), (1 << p->nVarsAB) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Adds one clause to the watcher list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Inta_ManWatchClause( Inta_Man_t * p, Sto_Cls_t * pClause, lit Lit ) { assert( lit_check(Lit, p->pCnf->nVars) ); 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; } /**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Inta_ManEnqueue( Inta_Man_t * p, lit Lit, Sto_Cls_t * pReason ) { int Var = lit_var(Lit); if ( p->pAssigns[Var] != LIT_UNDEF ) return p->pAssigns[Var] == Lit; p->pAssigns[Var] = Lit; p->pReasons[Var] = pReason; p->pTrail[p->nTrailSize++] = Lit; //printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); return 1; } /**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Inta_ManCancelUntil( Inta_Man_t * p, int Level ) { lit Lit; int i, Var; for ( i = p->nTrailSize - 1; i >= Level; i-- ) { Lit = p->pTrail[i]; Var = lit_var( Lit ); p->pReasons[Var] = NULL; p->pAssigns[Var] = LIT_UNDEF; //printf( "cancelling var %d\n", Var ); } p->nTrailSize = Level; } /**Function************************************************************* Synopsis [Propagate one assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Sto_Cls_t * Inta_ManPropagateOne( Inta_Man_t * p, lit Lit ) { Sto_Cls_t ** ppPrev, * pCur, * pTemp; lit LitF = lit_neg(Lit); int i; // iterate through the literals ppPrev = p->pWatches + Lit; for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) { // 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; pTemp = pCur->pNext0; pCur->pNext0 = pCur->pNext1; pCur->pNext1 = pTemp; } assert( pCur->pLits[1] == LitF ); // if the first literal is true, the clause is satisfied if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) { ppPrev = &pCur->pNext1; 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 ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(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 *ppPrev = pCur->pNext1; // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) Inta_ManWatchClause( p, pCur, pCur->pLits[1] ); break; } if ( i < (int)pCur->nLits ) // found new watch continue; // clause is unit - enqueue new implication if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) ) { ppPrev = &pCur->pNext1; continue; } // conflict detected - return the conflict clause return pCur; } return NULL; } /**Function************************************************************* Synopsis [Propagate the current assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sto_Cls_t * Inta_ManPropagate( Inta_Man_t * p, int Start ) { Sto_Cls_t * pClause; int i; abctime clk = Abc_Clock(); for ( i = Start; i < p->nTrailSize; i++ ) { pClause = Inta_ManPropagateOne( p, p->pTrail[i] ); if ( pClause ) { p->timeBcp += Abc_Clock() - clk; return pClause; } } p->timeBcp += Abc_Clock() - clk; return NULL; } /**Function************************************************************* Synopsis [Writes one root clause into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inta_ManProofWriteOne( Inta_Man_t * p, Sto_Cls_t * pClause ) { Inta_ManProofSet( p, pClause, ++p->Counter ); if ( p->fProofWrite ) { int v; fprintf( p->pFile, "%d", Inta_ManProofGet(p, pClause) ); for ( v = 0; v < (int)pClause->nLits; v++ ) fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) ); fprintf( p->pFile, " 0 0\n" ); } } /**Function************************************************************* Synopsis [Traces the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal ) { Sto_Cls_t * pReason; int i, v, Var, PrevId; int fPrint = 0; abctime clk = Abc_Clock(); // collect resolvent literals if ( p->fProofVerif ) { Vec_IntClear( p->vResLits ); for ( i = 0; i < (int)pConflict->nLits; i++ ) Vec_IntPush( p->vResLits, pConflict->pLits[i] ); } // mark all the variables in the conflict as seen for ( v = 0; v < (int)pConflict->nLits; v++ ) p->pSeens[lit_var(pConflict->pLits[v])] = 1; // start the anticedents // pFinal->pAntis = Vec_PtrAlloc( 32 ); // Vec_PtrPush( pFinal->pAntis, pConflict ); if ( p->pCnf->nClausesA ) Inta_ManAigCopy( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pConflict) ); // follow the trail backwards PrevId = Inta_ManProofGet(p, pConflict); for ( i = p->nTrailSize - 1; i >= 0; i-- ) { // skip literals that are not involved Var = lit_var(p->pTrail[i]); if ( !p->pSeens[Var] ) continue; p->pSeens[Var] = 0; // skip literals of the resulting clause pReason = p->pReasons[Var]; if ( pReason == NULL ) continue; assert( p->pTrail[i] == pReason->pLits[0] ); // add the variables to seen for ( v = 1; v < (int)pReason->nLits; v++ ) p->pSeens[lit_var(pReason->pLits[v])] = 1; // record the reason clause assert( Inta_ManProofGet(p, pReason) > 0 ); p->Counter++; if ( p->fProofWrite ) fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Inta_ManProofGet(p, pReason) ); PrevId = p->Counter; if ( p->pCnf->nClausesA ) { if ( p->pVarTypes[Var] == 1 ) // var of A Inta_ManAigOr( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); else Inta_ManAigAnd( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); } // resolve the temporary resolvent with the reason clause if ( p->fProofVerif ) { int v1, v2, Entry = -1; if ( fPrint ) Inta_ManPrintResolvent( p->vResLits ); // check that the var is present in the resolvent Vec_IntForEachEntry( p->vResLits, Entry, v1 ) if ( lit_var(Entry) == Var ) break; if ( v1 == Vec_IntSize(p->vResLits) ) printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); if ( Entry != lit_neg(pReason->pLits[0]) ) printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); // remove variable v1 from the resolvent assert( lit_var(Entry) == Var ); Vec_IntRemove( p->vResLits, Entry ); // add variables of the reason clause for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) { Vec_IntForEachEntry( p->vResLits, Entry, v1 ) if ( lit_var(Entry) == lit_var(pReason->pLits[v2]) ) break; // if it is a new variable, add it to the resolvent if ( v1 == Vec_IntSize(p->vResLits) ) { Vec_IntPush( p->vResLits, pReason->pLits[v2] ); continue; } // if the variable is the same, the literal should be the same too if ( Entry == pReason->pLits[v2] ) continue; // the literal is different printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); } } // Vec_PtrPush( pFinal->pAntis, pReason ); } // unmark all seen variables // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // p->pSeens[lit_var(p->pTrail[i])] = 0; // check that the literals are unmarked // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); // use the resulting clause to check the correctness of resolution if ( p->fProofVerif ) { int v1, v2, Entry = -1; if ( fPrint ) Inta_ManPrintResolvent( p->vResLits ); Vec_IntForEachEntry( p->vResLits, Entry, v1 ) { for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) if ( pFinal->pLits[v2] == Entry ) break; if ( v2 < (int)pFinal->nLits ) continue; break; } if ( v1 < Vec_IntSize(p->vResLits) ) { printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); Inta_ManPrintClause( p, pConflict ); Inta_ManPrintResolvent( p->vResLits ); Inta_ManPrintClause( p, pFinal ); } // if there are literals in the clause that are not in the resolvent // it means that the derived resolvent is stronger than the clause // we can replace the clause with the resolvent by removing these literals if ( Vec_IntSize(p->vResLits) != (int)pFinal->nLits ) { for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ ) { Vec_IntForEachEntry( p->vResLits, Entry, v2 ) if ( pFinal->pLits[v1] == Entry ) break; if ( v2 < Vec_IntSize(p->vResLits) ) continue; // remove literal v1 from the final clause pFinal->nLits--; for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ ) pFinal->pLits[v2] = pFinal->pLits[v2+1]; v1--; } assert( Vec_IntSize(p->vResLits) == (int)pFinal->nLits ); } } p->timeTrace += Abc_Clock() - clk; // return the proof pointer if ( p->pCnf->nClausesA ) { // Inta_ManPrintInterOne( p, pFinal ); } Inta_ManProofSet( p, pFinal, p->Counter ); // make sure the same proof ID is not asssigned to two consecutive clauses assert( p->pProofNums[pFinal->Id-1] != p->Counter ); // if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] ) // p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id]; return p->Counter; } /**Function************************************************************* Synopsis [Records the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inta_ManProofRecordOne( Inta_Man_t * p, Sto_Cls_t * pClause ) { Sto_Cls_t * pConflict; int i; // empty clause never ends up there assert( pClause->nLits > 0 ); if ( pClause->nLits == 0 ) printf( "Error: Empty clause is attempted.\n" ); assert( !pClause->fRoot ); assert( p->nTrailSize == p->nRootSize ); // if any of the clause literals are already assumed // it means that the clause is redundant and can be skipped for ( i = 0; i < (int)pClause->nLits; i++ ) if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] ) return 1; // add assumptions to the trail for ( i = 0; i < (int)pClause->nLits; i++ ) if ( !Inta_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) { assert( 0 ); // impossible return 0; } // propagate the assumptions pConflict = Inta_ManPropagate( p, p->nRootSize ); if ( pConflict == NULL ) { assert( 0 ); // cannot prove return 0; } // skip the clause if it is weaker or the same as the conflict clause if ( pClause->nLits >= pConflict->nLits ) { // check if every literal of conflict clause can be found in the given clause int j; for ( i = 0; i < (int)pConflict->nLits; i++ ) { for ( j = 0; j < (int)pClause->nLits; j++ ) if ( pConflict->pLits[i] == pClause->pLits[j] ) break; if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found break; } if ( i == (int)pConflict->nLits ) // all lits are found { // undo to the root level Inta_ManCancelUntil( p, p->nRootSize ); return 1; } } // construct the proof Inta_ManProofTraceOne( p, pConflict, pClause ); // undo to the root level Inta_ManCancelUntil( p, p->nRootSize ); // add large clauses to the watched lists if ( pClause->nLits > 1 ) { Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); Inta_ManWatchClause( p, pClause, pClause->pLits[1] ); return 1; } assert( pClause->nLits == 1 ); // if the clause proved is unit, add it and propagate if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) { assert( 0 ); // impossible return 0; } // propagate the assumption pConflict = Inta_ManPropagate( p, p->nRootSize ); if ( pConflict ) { // construct the proof Inta_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty ); // if ( p->fVerbose ) // printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); return 0; } // update the root level p->nRootSize = p->nTrailSize; return 1; } /**Function************************************************************* Synopsis [Propagate the root clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Inta_ManProcessRoots( Inta_Man_t * p ) { Sto_Cls_t * pClause; int Counter; // make sure the root clauses are preceeding the learnt clauses Counter = 0; Sto_ManForEachClause( p->pCnf, pClause ) { assert( (int)pClause->fA == (Counter < (int)p->pCnf->nClausesA) ); assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots) ); Counter++; } assert( p->pCnf->nClauses == Counter ); // make sure the last clause if empty assert( p->pCnf->pTail->nLits == 0 ); // go through the root unit clauses p->nTrailSize = 0; Sto_ManForEachClauseRoot( p->pCnf, pClause ) { // create watcher lists for the root clauses if ( pClause->nLits > 1 ) { Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); Inta_ManWatchClause( p, pClause, pClause->pLits[1] ); } // empty clause and large clauses if ( pClause->nLits != 1 ) continue; // unit clause assert( lit_check(pClause->pLits[0], p->pCnf->nVars) ); if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) { // detected root level conflict // printf( "Error in Inta_ManProcessRoots(): Detected a root-level conflict too early!\n" ); // assert( 0 ); // detected root level conflict Inta_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found root level conflict!\n" ); return 0; } } // propagate the root unit clauses pClause = Inta_ManPropagate( p, 0 ); if ( pClause ) { // detected root level conflict Inta_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found root level conflict!\n" ); return 0; } // set the root level p->nRootSize = p->nTrailSize; return 1; } /**Function************************************************************* Synopsis [Records the proof.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Inta_ManPrepareInter( Inta_Man_t * p ) { Sto_Cls_t * pClause; int Var, VarAB, v; // set interpolants for root clauses Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( !pClause->fA ) // clause of B { Inta_ManAigFill( p, Inta_ManAigRead(p, pClause) ); // Inta_ManPrintInterOne( p, pClause ); continue; } // clause of A Inta_ManAigClear( p, Inta_ManAigRead(p, pClause) ); for ( v = 0; v < (int)pClause->nLits; v++ ) { Var = lit_var(pClause->pLits[v]); if ( p->pVarTypes[Var] < 0 ) // global var { VarAB = -p->pVarTypes[Var]-1; assert( VarAB >= 0 && VarAB < Vec_IntSize(p->vVarsAB) ); if ( lit_sign(pClause->pLits[v]) ) // negative var Inta_ManAigOrNotVar( p, Inta_ManAigRead(p, pClause), VarAB ); else Inta_ManAigOrVar( p, Inta_ManAigRead(p, pClause), VarAB ); } } // Inta_ManPrintInterOne( p, pClause ); } } /**Function************************************************************* Synopsis [Computes interpolant for the given CNF.] Description [Takes the interpolation manager, the CNF deriving by the SAT solver, which includes ClausesA, ClausesB, and learned clauses. Additional arguments are the vector of variables common to AB and the verbosiness flag. Returns the AIG manager with a single output, containing the interpolant.] SideEffects [] SeeAlso [] ***********************************************************************/ void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, abctime TimeToStop, void * vVarsAB, int fVerbose ) { Aig_Man_t * pRes; Aig_Obj_t * pObj; Sto_Cls_t * pClause; int RetValue = 1; abctime clkTotal = Abc_Clock(); if ( TimeToStop && Abc_Clock() > TimeToStop ) return NULL; // check that the CNF makes sense assert( pCnf->nVars > 0 && pCnf->nClauses > 0 ); p->pCnf = pCnf; p->fVerbose = fVerbose; p->vVarsAB = (Vec_Int_t *)vVarsAB; p->pAig = pRes = Aig_ManStart( 10000 ); Aig_IthVar( p->pAig, Vec_IntSize(p->vVarsAB) - 1 ); // adjust the manager Inta_ManResize( p ); // prepare the interpolant computation Inta_ManPrepareInter( p ); // construct proof for each clause // start the proof if ( p->fProofWrite ) { p->pFile = fopen( "proof.cnf_", "w" ); p->Counter = 0; } // write the root clauses Sto_ManForEachClauseRoot( p->pCnf, pClause ) { Inta_ManProofWriteOne( p, pClause ); if ( TimeToStop && Abc_Clock() > TimeToStop ) { Aig_ManStop( pRes ); p->pAig = NULL; return NULL; } } // propagate root level assignments if ( Inta_ManProcessRoots( p ) ) { // if there is no conflict, consider learned clauses Sto_ManForEachClause( p->pCnf, pClause ) { if ( pClause->fRoot ) continue; if ( !Inta_ManProofRecordOne( p, pClause ) ) { RetValue = 0; break; } if ( TimeToStop && Abc_Clock() > TimeToStop ) { Aig_ManStop( pRes ); p->pAig = NULL; return NULL; } } } // stop the proof if ( p->fProofWrite ) { fclose( p->pFile ); // Sat_ProofChecker( "proof.cnf_" ); p->pFile = NULL; } if ( fVerbose ) { // ABC_PRT( "Interpo", Abc_Clock() - clkTotal ); printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f MB\n", p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter, 1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), 1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) ); p->timeTotal += Abc_Clock() - clkTotal; } pObj = *Inta_ManAigRead( p, p->pCnf->pTail ); Aig_ObjCreateCo( pRes, pObj ); Aig_ManCleanup( pRes ); p->pAig = NULL; return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ) { Aig_Man_t * p; Aig_Obj_t * pMiter, * pSum, * pLit; Sto_Cls_t * pClause; int Var, VarAB, v; p = Aig_ManStart( 10000 ); pMiter = Aig_ManConst1(p); Sto_ManForEachClauseRoot( pCnf, pClause ) { if ( fClausesA ^ pClause->fA ) // clause of B continue; // clause of A pSum = Aig_ManConst0(p); for ( v = 0; v < (int)pClause->nLits; v++ ) { Var = lit_var(pClause->pLits[v]); if ( pMan->pVarTypes[Var] < 0 ) // global var { VarAB = -pMan->pVarTypes[Var]-1; assert( VarAB >= 0 && VarAB < Vec_IntSize(pMan->vVarsAB) ); pLit = Aig_NotCond( Aig_IthVar(p, VarAB), lit_sign(pClause->pLits[v]) ); } else pLit = Aig_NotCond( Aig_IthVar(p, Vec_IntSize(pMan->vVarsAB)+1+Var), lit_sign(pClause->pLits[v]) ); pSum = Aig_Or( p, pSum, pLit ); } pMiter = Aig_And( p, pMiter, pSum ); } Aig_ObjCreateCo( p, pMiter ); return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satInterB.c000066400000000000000000001076751300674244400236330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satInter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sat_solver.] Synopsis [Interpolation package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $] ***********************************************************************/ #include #include #include #include #include "satStore.h" #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // variable assignments static const lit LIT_UNDEF = 0xffffffff; // interpolation manager struct Intb_Man_t_ { // clauses of the problems Sto_Man_t * pCnf; // the set of CNF clauses for A and B Vec_Int_t * vVarsAB; // the array of global variables // various parameters int fVerbose; // verbosiness flag int fProofVerif; // verifies the proof int fProofWrite; // writes the proof file int nVarsAlloc; // the allocated size of var arrays int nClosAlloc; // the allocated size of clause arrays // internal BCP int nRootSize; // the number of root level assignments int nTrailSize; // the number of assignments made lit * pTrail; // chronological order of assignments (size nVars) lit * pAssigns; // assignments by variable (size nVars) char * pSeens; // temporary mark (size nVars) Sto_Cls_t ** pReasons; // reasons for each assignment (size nVars) Sto_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) // interpolation data Aig_Man_t * pAig; // the AIG manager for recording the interpolant int * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] Aig_Obj_t ** pInters; // storage for interpolants as truth tables (size nClauses) int nIntersAlloc; // the allocated size of truth table array // proof recording int Counter; // counter of resolved clauses int * pProofNums; // the proof numbers for each clause (size nClauses) FILE * pFile; // the file for proof recording // internal verification lit * pResLits; // the literals of the resolvent int nResLits; // the number of literals of the resolvent int nResLitsAlloc;// the number of literals of the resolvent // runtime stats abctime timeBcp; // the runtime for BCP abctime timeTrace; // the runtime of trace construction abctime timeTotal; // the total runtime of interpolation }; // procedure to get hold of the clauses' truth table static inline Aig_Obj_t ** Intb_ManAigRead( Intb_Man_t * pMan, Sto_Cls_t * pCls ) { return pMan->pInters + pCls->Id; } static inline void Intb_ManAigClear( Intb_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst0(pMan->pAig); } static inline void Intb_ManAigFill( Intb_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst1(pMan->pAig); } static inline void Intb_ManAigCopy( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = *q; } static inline void Intb_ManAigAnd( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_And(pMan->pAig, *p, *q); } static inline void Intb_ManAigOr( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, *q); } static inline void Intb_ManAigOrNot( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(*q)); } static inline void Intb_ManAigOrVar( Intb_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_IthVar(pMan->pAig, v)); } static inline void Intb_ManAigOrNotVar( Intb_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(Aig_IthVar(pMan->pAig, v))); } static inline void Intb_ManAigMux0( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q, int v){ *p = Aig_Mux(pMan->pAig, Aig_IthVar(pMan->pAig, v), *q, *p); } static inline void Intb_ManAigMux1( Intb_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q, int v){ *p = Aig_Mux(pMan->pAig, Aig_IthVar(pMan->pAig, v), *p, *q); } // reading/writing the proof for a clause static inline int Intb_ManProofGet( Intb_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } static inline void Intb_ManProofSet( Intb_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Intb_Man_t * Intb_ManAlloc() { Intb_Man_t * p; // allocate the manager p = (Intb_Man_t *)ABC_ALLOC( char, sizeof(Intb_Man_t) ); memset( p, 0, sizeof(Intb_Man_t) ); // verification p->nResLitsAlloc = (1<<16); p->pResLits = ABC_ALLOC( lit, p->nResLitsAlloc ); // parameters p->fProofWrite = 0; p->fProofVerif = 1; return p; } /**Function************************************************************* Synopsis [Count common variables in the clauses of A and B.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Intb_ManGlobalVars( Intb_Man_t * p ) { Sto_Cls_t * pClause; int LargeNum = -100000000; int Var, nVarsAB, v; // mark the variable encountered in the clauses of A Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( !pClause->fA ) break; for ( v = 0; v < (int)pClause->nLits; v++ ) p->pVarTypes[lit_var(pClause->pLits[v])] = 1; } // check variables that appear in clauses of B nVarsAB = 0; Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( pClause->fA ) continue; for ( v = 0; v < (int)pClause->nLits; v++ ) { Var = lit_var(pClause->pLits[v]); if ( p->pVarTypes[Var] == 1 ) // var of A { // change it into a global variable nVarsAB++; p->pVarTypes[Var] = LargeNum; } } } assert( nVarsAB <= Vec_IntSize(p->vVarsAB) ); // order global variables nVarsAB = 0; Vec_IntForEachEntry( p->vVarsAB, Var, v ) p->pVarTypes[Var] = -(1+nVarsAB++); // check that there is no extra global variables for ( v = 0; v < p->pCnf->nVars; v++ ) assert( p->pVarTypes[v] != LargeNum ); return nVarsAB; } /**Function************************************************************* Synopsis [Resize proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intb_ManResize( Intb_Man_t * p ) { p->Counter = 0; // check if resizing is needed if ( p->nVarsAlloc < p->pCnf->nVars ) { // find the new size if ( p->nVarsAlloc == 0 ) p->nVarsAlloc = 1; while ( p->nVarsAlloc < p->pCnf->nVars ) p->nVarsAlloc *= 2; // resize the arrays p->pTrail = ABC_REALLOC(lit, p->pTrail, p->nVarsAlloc ); p->pAssigns = ABC_REALLOC(lit, p->pAssigns, p->nVarsAlloc ); p->pSeens = ABC_REALLOC(char, p->pSeens, p->nVarsAlloc ); p->pVarTypes = ABC_REALLOC(int, p->pVarTypes, p->nVarsAlloc ); p->pReasons = ABC_REALLOC(Sto_Cls_t *, p->pReasons, p->nVarsAlloc ); p->pWatches = ABC_REALLOC(Sto_Cls_t *, p->pWatches, p->nVarsAlloc*2 ); } // clean the free space memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars ); memset( p->pSeens , 0, sizeof(char) * p->pCnf->nVars ); memset( p->pVarTypes, 0, sizeof(int) * p->pCnf->nVars ); memset( p->pReasons , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars ); memset( p->pWatches , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 ); // compute the number of common variables Intb_ManGlobalVars( p ); // check if resizing of clauses is needed if ( p->nClosAlloc < p->pCnf->nClauses ) { // find the new size if ( p->nClosAlloc == 0 ) p->nClosAlloc = 1; while ( p->nClosAlloc < p->pCnf->nClauses ) p->nClosAlloc *= 2; // resize the arrays p->pProofNums = ABC_REALLOC( int, p->pProofNums, p->nClosAlloc ); } memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses ); // check if resizing of truth tables is needed if ( p->nIntersAlloc < p->pCnf->nClauses ) { p->nIntersAlloc = p->pCnf->nClauses; p->pInters = ABC_REALLOC( Aig_Obj_t *, p->pInters, p->nIntersAlloc ); } memset( p->pInters, 0, sizeof(Aig_Obj_t *) * p->pCnf->nClauses ); } /**Function************************************************************* Synopsis [Deallocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intb_ManFree( Intb_Man_t * p ) { /* printf( "Runtime stats:\n" ); ABC_PRT( "BCP ", p->timeBcp ); ABC_PRT( "Trace ", p->timeTrace ); ABC_PRT( "TOTAL ", p->timeTotal ); */ ABC_FREE( p->pInters ); ABC_FREE( p->pProofNums ); ABC_FREE( p->pTrail ); ABC_FREE( p->pAssigns ); ABC_FREE( p->pSeens ); ABC_FREE( p->pVarTypes ); ABC_FREE( p->pReasons ); ABC_FREE( p->pWatches ); ABC_FREE( p->pResLits ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intb_ManPrintClause( Intb_Man_t * p, Sto_Cls_t * pClause ) { int i; printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Intb_ManProofGet(p, pClause) ); for ( i = 0; i < (int)pClause->nLits; i++ ) printf( " %d", pClause->pLits[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints the resolvent.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intb_ManPrintResolvent( lit * pResLits, int nResLits ) { int i; printf( "Resolvent: {" ); for ( i = 0; i < nResLits; i++ ) printf( " %d", pResLits[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints the interpolant for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intb_ManPrintInterOne( Intb_Man_t * p, Sto_Cls_t * pClause ) { printf( "Clause %2d : ", pClause->Id ); // Extra_PrintBinary___( stdout, Intb_ManAigRead(p, pClause), (1 << p->nVarsAB) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Adds one clause to the watcher list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Intb_ManWatchClause( Intb_Man_t * p, Sto_Cls_t * pClause, lit Lit ) { assert( lit_check(Lit, p->pCnf->nVars) ); 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; } /**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Intb_ManEnqueue( Intb_Man_t * p, lit Lit, Sto_Cls_t * pReason ) { int Var = lit_var(Lit); if ( p->pAssigns[Var] != LIT_UNDEF ) return p->pAssigns[Var] == Lit; p->pAssigns[Var] = Lit; p->pReasons[Var] = pReason; p->pTrail[p->nTrailSize++] = Lit; //printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); return 1; } /**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Intb_ManCancelUntil( Intb_Man_t * p, int Level ) { lit Lit; int i, Var; for ( i = p->nTrailSize - 1; i >= Level; i-- ) { Lit = p->pTrail[i]; Var = lit_var( Lit ); p->pReasons[Var] = NULL; p->pAssigns[Var] = LIT_UNDEF; //printf( "cancelling var %d\n", Var ); } p->nTrailSize = Level; } /**Function************************************************************* Synopsis [Propagate one assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Sto_Cls_t * Intb_ManPropagateOne( Intb_Man_t * p, lit Lit ) { Sto_Cls_t ** ppPrev, * pCur, * pTemp; lit LitF = lit_neg(Lit); int i; // iterate through the literals ppPrev = p->pWatches + Lit; for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) { // 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; pTemp = pCur->pNext0; pCur->pNext0 = pCur->pNext1; pCur->pNext1 = pTemp; } assert( pCur->pLits[1] == LitF ); // if the first literal is true, the clause is satisfied if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) { ppPrev = &pCur->pNext1; 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 ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(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 *ppPrev = pCur->pNext1; // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) Intb_ManWatchClause( p, pCur, pCur->pLits[1] ); break; } if ( i < (int)pCur->nLits ) // found new watch continue; // clause is unit - enqueue new implication if ( Intb_ManEnqueue(p, pCur->pLits[0], pCur) ) { ppPrev = &pCur->pNext1; continue; } // conflict detected - return the conflict clause return pCur; } return NULL; } /**Function************************************************************* Synopsis [Propagate the current assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sto_Cls_t * Intb_ManPropagate( Intb_Man_t * p, int Start ) { Sto_Cls_t * pClause; int i; abctime clk = Abc_Clock(); for ( i = Start; i < p->nTrailSize; i++ ) { pClause = Intb_ManPropagateOne( p, p->pTrail[i] ); if ( pClause ) { p->timeBcp += Abc_Clock() - clk; return pClause; } } p->timeBcp += Abc_Clock() - clk; return NULL; } /**Function************************************************************* Synopsis [Writes one root clause into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intb_ManProofWriteOne( Intb_Man_t * p, Sto_Cls_t * pClause ) { Intb_ManProofSet( p, pClause, ++p->Counter ); if ( p->fProofWrite ) { int v; fprintf( p->pFile, "%d", Intb_ManProofGet(p, pClause) ); for ( v = 0; v < (int)pClause->nLits; v++ ) fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) ); fprintf( p->pFile, " 0 0\n" ); } } /**Function************************************************************* Synopsis [Traces the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Intb_ManGetGlobalVar( Intb_Man_t * p, int Var ) { int VarAB; if ( p->pVarTypes[Var] >= 0 ) // global var return -1; VarAB = -p->pVarTypes[Var]-1; assert( VarAB >= 0 && VarAB < Vec_IntSize(p->vVarsAB) ); return VarAB; } /**Function************************************************************* Synopsis [Traces the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Intb_ManProofTraceOne( Intb_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal ) { Sto_Cls_t * pReason; int i, v, Var, PrevId; int fPrint = 0; abctime clk = Abc_Clock(); // collect resolvent literals if ( p->fProofVerif ) { assert( (int)pConflict->nLits <= p->nResLitsAlloc ); memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); p->nResLits = pConflict->nLits; } // mark all the variables in the conflict as seen for ( v = 0; v < (int)pConflict->nLits; v++ ) p->pSeens[lit_var(pConflict->pLits[v])] = 1; // start the anticedents // pFinal->pAntis = Vec_PtrAlloc( 32 ); // Vec_PtrPush( pFinal->pAntis, pConflict ); if ( p->pCnf->nClausesA ) Intb_ManAigCopy( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pConflict) ); // follow the trail backwards PrevId = Intb_ManProofGet(p, pConflict); for ( i = p->nTrailSize - 1; i >= 0; i-- ) { // skip literals that are not involved Var = lit_var(p->pTrail[i]); if ( !p->pSeens[Var] ) continue; p->pSeens[Var] = 0; // skip literals of the resulting clause pReason = p->pReasons[Var]; if ( pReason == NULL ) continue; assert( p->pTrail[i] == pReason->pLits[0] ); // add the variables to seen for ( v = 1; v < (int)pReason->nLits; v++ ) p->pSeens[lit_var(pReason->pLits[v])] = 1; // record the reason clause assert( Intb_ManProofGet(p, pReason) > 0 ); p->Counter++; if ( p->fProofWrite ) fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Intb_ManProofGet(p, pReason) ); PrevId = p->Counter; if ( p->pCnf->nClausesA ) { if ( p->pVarTypes[Var] == 1 )// || rand() % 10 == 0 ) // var of A Intb_ManAigOr( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pReason) ); else if ( p->pVarTypes[Var] == 0 ) // var of B Intb_ManAigAnd( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pReason) ); else { int VarAB = Intb_ManGetGlobalVar(p, Var); // check that the var is present in the reason for ( v = 0; v < (int)pReason->nLits; v++ ) if ( lit_var(pReason->pLits[v]) == Var ) break; assert( v < (int)pReason->nLits ); if ( lit_sign(pReason->pLits[v]) ) // negative polarity Intb_ManAigMux0( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pReason), VarAB ); else Intb_ManAigMux1( p, Intb_ManAigRead(p, pFinal), Intb_ManAigRead(p, pReason), VarAB ); } } // resolve the temporary resolvent with the reason clause if ( p->fProofVerif ) { int v1, v2; if ( fPrint ) Intb_ManPrintResolvent( p->pResLits, p->nResLits ); // check that the var is present in the resolvent for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == Var ) break; if ( v1 == p->nResLits ) printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); // remove this variable from the resolvent assert( lit_var(p->pResLits[v1]) == Var ); p->nResLits--; for ( ; v1 < p->nResLits; v1++ ) p->pResLits[v1] = p->pResLits[v1+1]; // add variables of the reason clause for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) { for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) break; // if it is a new variable, add it to the resolvent if ( v1 == p->nResLits ) { if ( p->nResLits == p->nResLitsAlloc ) printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n", pFinal->Id ); p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; continue; } // if the variable is the same, the literal should be the same too if ( p->pResLits[v1] == pReason->pLits[v2] ) continue; // the literal is different printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); } } // Vec_PtrPush( pFinal->pAntis, pReason ); } // unmark all seen variables // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // p->pSeens[lit_var(p->pTrail[i])] = 0; // check that the literals are unmarked // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); // use the resulting clause to check the correctness of resolution if ( p->fProofVerif ) { int v1, v2; if ( fPrint ) Intb_ManPrintResolvent( p->pResLits, p->nResLits ); for ( v1 = 0; v1 < p->nResLits; v1++ ) { for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) if ( pFinal->pLits[v2] == p->pResLits[v1] ) break; if ( v2 < (int)pFinal->nLits ) continue; break; } if ( v1 < p->nResLits ) { printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); Intb_ManPrintClause( p, pConflict ); Intb_ManPrintResolvent( p->pResLits, p->nResLits ); Intb_ManPrintClause( p, pFinal ); } // if there are literals in the clause that are not in the resolvent // it means that the derived resolvent is stronger than the clause // we can replace the clause with the resolvent by removing these literals if ( p->nResLits != (int)pFinal->nLits ) { for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ ) { for ( v2 = 0; v2 < p->nResLits; v2++ ) if ( pFinal->pLits[v1] == p->pResLits[v2] ) break; if ( v2 < p->nResLits ) continue; // remove literal v1 from the final clause pFinal->nLits--; for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ ) pFinal->pLits[v2] = pFinal->pLits[v2+1]; v1--; } assert( p->nResLits == (int)pFinal->nLits ); } } p->timeTrace += Abc_Clock() - clk; // return the proof pointer if ( p->pCnf->nClausesA ) { // Intb_ManPrintInterOne( p, pFinal ); } Intb_ManProofSet( p, pFinal, p->Counter ); // make sure the same proof ID is not asssigned to two consecutive clauses assert( p->pProofNums[pFinal->Id-1] != p->Counter ); // if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] ) // p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id]; return p->Counter; } /**Function************************************************************* Synopsis [Records the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Intb_ManProofRecordOne( Intb_Man_t * p, Sto_Cls_t * pClause ) { Sto_Cls_t * pConflict; int i; // empty clause never ends up there assert( pClause->nLits > 0 ); if ( pClause->nLits == 0 ) printf( "Error: Empty clause is attempted.\n" ); assert( !pClause->fRoot ); assert( p->nTrailSize == p->nRootSize ); // if any of the clause literals are already assumed // it means that the clause is redundant and can be skipped for ( i = 0; i < (int)pClause->nLits; i++ ) if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] ) return 1; // add assumptions to the trail for ( i = 0; i < (int)pClause->nLits; i++ ) if ( !Intb_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) { assert( 0 ); // impossible return 0; } // propagate the assumptions pConflict = Intb_ManPropagate( p, p->nRootSize ); if ( pConflict == NULL ) { assert( 0 ); // cannot prove return 0; } // skip the clause if it is weaker or the same as the conflict clause if ( pClause->nLits >= pConflict->nLits ) { // check if every literal of conflict clause can be found in the given clause int j; for ( i = 0; i < (int)pConflict->nLits; i++ ) { for ( j = 0; j < (int)pClause->nLits; j++ ) if ( pConflict->pLits[i] == pClause->pLits[j] ) break; if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found break; } if ( i == (int)pConflict->nLits ) // all lits are found { // undo to the root level Intb_ManCancelUntil( p, p->nRootSize ); return 1; } } // construct the proof Intb_ManProofTraceOne( p, pConflict, pClause ); // undo to the root level Intb_ManCancelUntil( p, p->nRootSize ); // add large clauses to the watched lists if ( pClause->nLits > 1 ) { Intb_ManWatchClause( p, pClause, pClause->pLits[0] ); Intb_ManWatchClause( p, pClause, pClause->pLits[1] ); return 1; } assert( pClause->nLits == 1 ); // if the clause proved is unit, add it and propagate if ( !Intb_ManEnqueue( p, pClause->pLits[0], pClause ) ) { assert( 0 ); // impossible return 0; } // propagate the assumption pConflict = Intb_ManPropagate( p, p->nRootSize ); if ( pConflict ) { // construct the proof Intb_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty ); // if ( p->fVerbose ) // printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); return 0; } // update the root level p->nRootSize = p->nTrailSize; return 1; } /**Function************************************************************* Synopsis [Propagate the root clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Intb_ManProcessRoots( Intb_Man_t * p ) { Sto_Cls_t * pClause; int Counter; // make sure the root clauses are preceeding the learnt clauses Counter = 0; Sto_ManForEachClause( p->pCnf, pClause ) { assert( (int)pClause->fA == (Counter < (int)p->pCnf->nClausesA) ); assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots) ); Counter++; } assert( p->pCnf->nClauses == Counter ); // make sure the last clause if empty assert( p->pCnf->pTail->nLits == 0 ); // go through the root unit clauses p->nTrailSize = 0; Sto_ManForEachClauseRoot( p->pCnf, pClause ) { // create watcher lists for the root clauses if ( pClause->nLits > 1 ) { Intb_ManWatchClause( p, pClause, pClause->pLits[0] ); Intb_ManWatchClause( p, pClause, pClause->pLits[1] ); } // empty clause and large clauses if ( pClause->nLits != 1 ) continue; // unit clause assert( lit_check(pClause->pLits[0], p->pCnf->nVars) ); if ( !Intb_ManEnqueue( p, pClause->pLits[0], pClause ) ) { // detected root level conflict // printf( "Error in Intb_ManProcessRoots(): Detected a root-level conflict too early!\n" ); // assert( 0 ); // detected root level conflict Intb_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found root level conflict!\n" ); return 0; } } // propagate the root unit clauses pClause = Intb_ManPropagate( p, 0 ); if ( pClause ) { // detected root level conflict Intb_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found root level conflict!\n" ); return 0; } // set the root level p->nRootSize = p->nTrailSize; return 1; } /**Function************************************************************* Synopsis [Records the proof.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intb_ManPrepareInter( Intb_Man_t * p ) { Sto_Cls_t * pClause; int Var, VarAB, v; // set interpolants for root clauses Sto_ManForEachClauseRoot( p->pCnf, pClause ) { if ( !pClause->fA ) // clause of B { Intb_ManAigFill( p, Intb_ManAigRead(p, pClause) ); // Intb_ManPrintInterOne( p, pClause ); continue; } // clause of A Intb_ManAigClear( p, Intb_ManAigRead(p, pClause) ); for ( v = 0; v < (int)pClause->nLits; v++ ) { Var = lit_var(pClause->pLits[v]); if ( p->pVarTypes[Var] < 0 ) // global var { VarAB = -p->pVarTypes[Var]-1; assert( VarAB >= 0 && VarAB < Vec_IntSize(p->vVarsAB) ); if ( lit_sign(pClause->pLits[v]) ) // negative var Intb_ManAigOrNotVar( p, Intb_ManAigRead(p, pClause), VarAB ); else Intb_ManAigOrVar( p, Intb_ManAigRead(p, pClause), VarAB ); } } // Intb_ManPrintInterOne( p, pClause ); } } /**Function************************************************************* Synopsis [Computes interpolant for the given CNF.] Description [Takes the interpolation manager, the CNF deriving by the SAT solver, which includes ClausesA, ClausesB, and learned clauses. Additional arguments are the vector of variables common to AB and the verbosiness flag. Returns the AIG manager with a single output, containing the interpolant.] SideEffects [] SeeAlso [] ***********************************************************************/ void * Intb_ManInterpolate( Intb_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose ) { Aig_Man_t * pRes; Aig_Obj_t * pObj; Sto_Cls_t * pClause; int RetValue = 1; abctime clkTotal = Abc_Clock(); // check that the CNF makes sense assert( pCnf->nVars > 0 && pCnf->nClauses > 0 ); p->pCnf = pCnf; p->fVerbose = fVerbose; p->vVarsAB = (Vec_Int_t *)vVarsAB; p->pAig = pRes = Aig_ManStart( 10000 ); Aig_IthVar( p->pAig, Vec_IntSize(p->vVarsAB) - 1 ); // adjust the manager Intb_ManResize( p ); // prepare the interpolant computation Intb_ManPrepareInter( p ); // construct proof for each clause // start the proof if ( p->fProofWrite ) { p->pFile = fopen( "proof.cnf_", "w" ); p->Counter = 0; } // write the root clauses Sto_ManForEachClauseRoot( p->pCnf, pClause ) Intb_ManProofWriteOne( p, pClause ); // propagate root level assignments if ( Intb_ManProcessRoots( p ) ) { // if there is no conflict, consider learned clauses Sto_ManForEachClause( p->pCnf, pClause ) { if ( pClause->fRoot ) continue; if ( !Intb_ManProofRecordOne( p, pClause ) ) { RetValue = 0; break; } } } // stop the proof if ( p->fProofWrite ) { fclose( p->pFile ); // Sat_ProofChecker( "proof.cnf_" ); p->pFile = NULL; } if ( fVerbose ) { // ABC_PRT( "Interpo", Abc_Clock() - clkTotal ); printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f MB\n", p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter, 1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), 1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) ); p->timeTotal += Abc_Clock() - clkTotal; } pObj = *Intb_ManAigRead( p, p->pCnf->pTail ); Aig_ObjCreateCo( pRes, pObj ); Aig_ManCleanup( pRes ); p->pAig = NULL; return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Intb_ManDeriveClauses( Intb_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ) { Aig_Man_t * p; Aig_Obj_t * pMiter, * pSum, * pLit; Sto_Cls_t * pClause; int Var, VarAB, v; p = Aig_ManStart( 10000 ); pMiter = Aig_ManConst1(p); Sto_ManForEachClauseRoot( pCnf, pClause ) { if ( fClausesA ^ pClause->fA ) // clause of B continue; // clause of A pSum = Aig_ManConst0(p); for ( v = 0; v < (int)pClause->nLits; v++ ) { Var = lit_var(pClause->pLits[v]); if ( pMan->pVarTypes[Var] < 0 ) // global var { VarAB = -pMan->pVarTypes[Var]-1; assert( VarAB >= 0 && VarAB < Vec_IntSize(pMan->vVarsAB) ); pLit = Aig_NotCond( Aig_IthVar(p, VarAB), lit_sign(pClause->pLits[v]) ); } else pLit = Aig_NotCond( Aig_IthVar(p, Vec_IntSize(pMan->vVarsAB)+1+Var), lit_sign(pClause->pLits[v]) ); pSum = Aig_Or( p, pSum, pLit ); } pMiter = Aig_And( p, pMiter, pSum ); } Aig_ObjCreateCo( p, pMiter ); return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satInterP.c000066400000000000000000001057201300674244400236360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satInter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT sat_solver.] Synopsis [Interpolation package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $] ***********************************************************************/ #include #include #include #include #include "satStore.h" #include "misc/vec/vec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // variable assignments static const lit LIT_UNDEF = 0xffffffff; // interpolation manager struct Intp_Man_t_ { // clauses of the problems Sto_Man_t * pCnf; // the set of CNF clauses for A and B // various parameters int fVerbose; // verbosiness flag int fProofVerif; // verifies the proof int fProofWrite; // writes the proof file int nVarsAlloc; // the allocated size of var arrays int nClosAlloc; // the allocated size of clause arrays // internal BCP int nRootSize; // the number of root level assignments int nTrailSize; // the number of assignments made lit * pTrail; // chronological order of assignments (size nVars) lit * pAssigns; // assignments by variable (size nVars) char * pSeens; // temporary mark (size nVars) Sto_Cls_t ** pReasons; // reasons for each assignment (size nVars) Sto_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) // proof data // Vec_Int_t * vAnties; // anticedents for all clauses // Vec_Int_t * vBreaks; // beginnings of anticedents for each clause Vec_Ptr_t * vAntClas; // anticedant clauses int nAntStart; // starting antecedant clause // proof recording int Counter; // counter of resolved clauses int * pProofNums; // the proof numbers for each clause (size nClauses) FILE * pFile; // the file for proof recording // internal verification lit * pResLits; // the literals of the resolvent int nResLits; // the number of literals of the resolvent int nResLitsAlloc;// the number of literals of the resolvent // runtime stats abctime timeBcp; // the runtime for BCP abctime timeTrace; // the runtime of trace construction abctime timeTotal; // the total runtime of interpolation }; // reading/writing the proof for a clause static inline int Intp_ManProofGet( Intp_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } static inline void Intp_ManProofSet( Intp_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Intp_Man_t * Intp_ManAlloc() { Intp_Man_t * p; // allocate the manager p = (Intp_Man_t *)ABC_ALLOC( char, sizeof(Intp_Man_t) ); memset( p, 0, sizeof(Intp_Man_t) ); // verification p->nResLitsAlloc = (1<<16); p->pResLits = ABC_ALLOC( lit, p->nResLitsAlloc ); // proof recording // p->vAnties = Vec_IntAlloc( 1000 ); // p->vBreaks = Vec_IntAlloc( 1000 ); p->vAntClas = Vec_PtrAlloc( 1000 ); p->nAntStart = 0; // parameters p->fProofWrite = 0; p->fProofVerif = 1; return p; } /**Function************************************************************* Synopsis [Resize proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManResize( Intp_Man_t * p ) { // check if resizing is needed if ( p->nVarsAlloc < p->pCnf->nVars ) { // find the new size if ( p->nVarsAlloc == 0 ) p->nVarsAlloc = 1; while ( p->nVarsAlloc < p->pCnf->nVars ) p->nVarsAlloc *= 2; // resize the arrays p->pTrail = ABC_REALLOC(lit, p->pTrail, p->nVarsAlloc ); p->pAssigns = ABC_REALLOC(lit, p->pAssigns, p->nVarsAlloc ); p->pSeens = ABC_REALLOC(char, p->pSeens, p->nVarsAlloc ); // p->pVarTypes = ABC_REALLOC(int, p->pVarTypes, p->nVarsAlloc ); p->pReasons = ABC_REALLOC(Sto_Cls_t *, p->pReasons, p->nVarsAlloc ); p->pWatches = ABC_REALLOC(Sto_Cls_t *, p->pWatches, p->nVarsAlloc*2 ); } // clean the free space memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars ); memset( p->pSeens , 0, sizeof(char) * p->pCnf->nVars ); // memset( p->pVarTypes, 0, sizeof(int) * p->pCnf->nVars ); memset( p->pReasons , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars ); memset( p->pWatches , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 ); // check if resizing of clauses is needed if ( p->nClosAlloc < p->pCnf->nClauses ) { // find the new size if ( p->nClosAlloc == 0 ) p->nClosAlloc = 1; while ( p->nClosAlloc < p->pCnf->nClauses ) p->nClosAlloc *= 2; // resize the arrays p->pProofNums = ABC_REALLOC( int, p->pProofNums, p->nClosAlloc ); } memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses ); } /**Function************************************************************* Synopsis [Deallocate proof manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManFree( Intp_Man_t * p ) { /* printf( "Runtime stats:\n" ); ABC_PRT( "BCP ", p->timeBcp ); ABC_PRT( "Trace ", p->timeTrace ); ABC_PRT( "TOTAL ", p->timeTotal ); */ // Vec_IntFree( p->vAnties ); // Vec_IntFree( p->vBreaks ); Vec_VecFree( (Vec_Vec_t *)p->vAntClas ); // ABC_FREE( p->pInters ); ABC_FREE( p->pProofNums ); ABC_FREE( p->pTrail ); ABC_FREE( p->pAssigns ); ABC_FREE( p->pSeens ); // ABC_FREE( p->pVarTypes ); ABC_FREE( p->pReasons ); ABC_FREE( p->pWatches ); ABC_FREE( p->pResLits ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManPrintClause( Intp_Man_t * p, Sto_Cls_t * pClause ) { int i; printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Intp_ManProofGet(p, pClause) ); for ( i = 0; i < (int)pClause->nLits; i++ ) printf( " %d", pClause->pLits[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints the resolvent.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManPrintResolvent( lit * pResLits, int nResLits ) { int i; printf( "Resolvent: {" ); for ( i = 0; i < nResLits; i++ ) printf( " %d", pResLits[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints the interpolant for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManPrintInterOne( Intp_Man_t * p, Sto_Cls_t * pClause ) { printf( "Clause %2d : ", pClause->Id ); // Extra_PrintBinary___( stdout, Intp_ManAigRead(p, pClause), (1 << p->nVarsAB) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Adds one clause to the watcher list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Intp_ManWatchClause( Intp_Man_t * p, Sto_Cls_t * pClause, lit Lit ) { assert( lit_check(Lit, p->pCnf->nVars) ); 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; } /**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Intp_ManEnqueue( Intp_Man_t * p, lit Lit, Sto_Cls_t * pReason ) { int Var = lit_var(Lit); if ( p->pAssigns[Var] != LIT_UNDEF ) return p->pAssigns[Var] == Lit; p->pAssigns[Var] = Lit; p->pReasons[Var] = pReason; p->pTrail[p->nTrailSize++] = Lit; //printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); return 1; } /**Function************************************************************* Synopsis [Records implication.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Intp_ManCancelUntil( Intp_Man_t * p, int Level ) { lit Lit; int i, Var; for ( i = p->nTrailSize - 1; i >= Level; i-- ) { Lit = p->pTrail[i]; Var = lit_var( Lit ); p->pReasons[Var] = NULL; p->pAssigns[Var] = LIT_UNDEF; //printf( "cancelling var %d\n", Var ); } p->nTrailSize = Level; } /**Function************************************************************* Synopsis [Propagate one assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Sto_Cls_t * Intp_ManPropagateOne( Intp_Man_t * p, lit Lit ) { Sto_Cls_t ** ppPrev, * pCur, * pTemp; lit LitF = lit_neg(Lit); int i; // iterate through the literals ppPrev = p->pWatches + Lit; for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) { // 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; pTemp = pCur->pNext0; pCur->pNext0 = pCur->pNext1; pCur->pNext1 = pTemp; } assert( pCur->pLits[1] == LitF ); // if the first literal is true, the clause is satisfied if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) { ppPrev = &pCur->pNext1; 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 ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(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 *ppPrev = pCur->pNext1; // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) Intp_ManWatchClause( p, pCur, pCur->pLits[1] ); break; } if ( i < (int)pCur->nLits ) // found new watch continue; // clause is unit - enqueue new implication if ( Intp_ManEnqueue(p, pCur->pLits[0], pCur) ) { ppPrev = &pCur->pNext1; continue; } // conflict detected - return the conflict clause return pCur; } return NULL; } /**Function************************************************************* Synopsis [Propagate the current assignments.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sto_Cls_t * Intp_ManPropagate( Intp_Man_t * p, int Start ) { Sto_Cls_t * pClause; int i; abctime clk = Abc_Clock(); for ( i = Start; i < p->nTrailSize; i++ ) { pClause = Intp_ManPropagateOne( p, p->pTrail[i] ); if ( pClause ) { p->timeBcp += Abc_Clock() - clk; return pClause; } } p->timeBcp += Abc_Clock() - clk; return NULL; } /**Function************************************************************* Synopsis [Writes one root clause into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManProofWriteOne( Intp_Man_t * p, Sto_Cls_t * pClause ) { Intp_ManProofSet( p, pClause, ++p->Counter ); if ( p->fProofWrite ) { int v; fprintf( p->pFile, "%d", Intp_ManProofGet(p, pClause) ); for ( v = 0; v < (int)pClause->nLits; v++ ) fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) ); fprintf( p->pFile, " 0 0\n" ); } } /**Function************************************************************* Synopsis [Traces the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Intp_ManProofTraceOne( Intp_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal ) { Sto_Cls_t * pReason; int i, v, Var, PrevId; int fPrint = 0; abctime clk = Abc_Clock(); // collect resolvent literals if ( p->fProofVerif ) { assert( (int)pConflict->nLits <= p->nResLitsAlloc ); memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); p->nResLits = pConflict->nLits; } // mark all the variables in the conflict as seen for ( v = 0; v < (int)pConflict->nLits; v++ ) p->pSeens[lit_var(pConflict->pLits[v])] = 1; // start the anticedents // pFinal->pAntis = Vec_PtrAlloc( 32 ); // Vec_PtrPush( pFinal->pAntis, pConflict ); // assert( pFinal->Id == Vec_IntSize(p->vBreaks) ); // Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) ); // Vec_IntPush( p->vAnties, pConflict->Id ); { Vec_Int_t * vAnts = Vec_IntAlloc( 16 ); assert( Vec_PtrSize(p->vAntClas) == pFinal->Id - p->nAntStart ); Vec_IntPush( vAnts, pConflict->Id ); Vec_PtrPush( p->vAntClas, vAnts ); } // if ( p->pCnf->nClausesA ) // Intp_ManAigCopy( p, Intp_ManAigRead(p, pFinal), Intp_ManAigRead(p, pConflict) ); // follow the trail backwards PrevId = Intp_ManProofGet(p, pConflict); for ( i = p->nTrailSize - 1; i >= 0; i-- ) { // skip literals that are not involved Var = lit_var(p->pTrail[i]); if ( !p->pSeens[Var] ) continue; p->pSeens[Var] = 0; // skip literals of the resulting clause pReason = p->pReasons[Var]; if ( pReason == NULL ) continue; assert( p->pTrail[i] == pReason->pLits[0] ); // add the variables to seen for ( v = 1; v < (int)pReason->nLits; v++ ) p->pSeens[lit_var(pReason->pLits[v])] = 1; // record the reason clause assert( Intp_ManProofGet(p, pReason) > 0 ); p->Counter++; if ( p->fProofWrite ) fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Intp_ManProofGet(p, pReason) ); PrevId = p->Counter; // if ( p->pCnf->nClausesA ) // { // if ( p->pVarTypes[Var] == 1 ) // var of A // Intp_ManAigOr( p, Intp_ManAigRead(p, pFinal), Intp_ManAigRead(p, pReason) ); // else // Intp_ManAigAnd( p, Intp_ManAigRead(p, pFinal), Intp_ManAigRead(p, pReason) ); // } // resolve the temporary resolvent with the reason clause if ( p->fProofVerif ) { int v1, v2; if ( fPrint ) Intp_ManPrintResolvent( p->pResLits, p->nResLits ); // check that the var is present in the resolvent for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == Var ) break; if ( v1 == p->nResLits ) printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); // remove this variable from the resolvent assert( lit_var(p->pResLits[v1]) == Var ); p->nResLits--; for ( ; v1 < p->nResLits; v1++ ) p->pResLits[v1] = p->pResLits[v1+1]; // add variables of the reason clause for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) { for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) break; // if it is a new variable, add it to the resolvent if ( v1 == p->nResLits ) { if ( p->nResLits == p->nResLitsAlloc ) printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n", pFinal->Id ); p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; continue; } // if the variable is the same, the literal should be the same too if ( p->pResLits[v1] == pReason->pLits[v2] ) continue; // the literal is different printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); } } // Vec_PtrPush( pFinal->pAntis, pReason ); // Vec_IntPush( p->vAnties, pReason->Id ); Vec_IntPush( (Vec_Int_t *)Vec_PtrEntryLast(p->vAntClas), pReason->Id ); } // unmark all seen variables // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // p->pSeens[lit_var(p->pTrail[i])] = 0; // check that the literals are unmarked // for ( i = p->nTrailSize - 1; i >= 0; i-- ) // assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); // use the resulting clause to check the correctness of resolution if ( p->fProofVerif ) { int v1, v2; if ( fPrint ) Intp_ManPrintResolvent( p->pResLits, p->nResLits ); for ( v1 = 0; v1 < p->nResLits; v1++ ) { for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) if ( pFinal->pLits[v2] == p->pResLits[v1] ) break; if ( v2 < (int)pFinal->nLits ) continue; break; } if ( v1 < p->nResLits ) { printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); Intp_ManPrintClause( p, pConflict ); Intp_ManPrintResolvent( p->pResLits, p->nResLits ); Intp_ManPrintClause( p, pFinal ); } // if there are literals in the clause that are not in the resolvent // it means that the derived resolvent is stronger than the clause // we can replace the clause with the resolvent by removing these literals if ( p->nResLits != (int)pFinal->nLits ) { for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ ) { for ( v2 = 0; v2 < p->nResLits; v2++ ) if ( pFinal->pLits[v1] == p->pResLits[v2] ) break; if ( v2 < p->nResLits ) continue; // remove literal v1 from the final clause pFinal->nLits--; for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ ) pFinal->pLits[v2] = pFinal->pLits[v2+1]; v1--; } assert( p->nResLits == (int)pFinal->nLits ); } } p->timeTrace += Abc_Clock() - clk; // return the proof pointer // if ( p->pCnf->nClausesA ) // { // Intp_ManPrintInterOne( p, pFinal ); // } Intp_ManProofSet( p, pFinal, p->Counter ); // make sure the same proof ID is not asssigned to two consecutive clauses assert( p->pProofNums[pFinal->Id-1] != p->Counter ); // if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] ) // p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id]; return p->Counter; } /**Function************************************************************* Synopsis [Records the proof for one clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Intp_ManProofRecordOne( Intp_Man_t * p, Sto_Cls_t * pClause ) { Sto_Cls_t * pConflict; int i; // empty clause never ends up there assert( pClause->nLits > 0 ); if ( pClause->nLits == 0 ) printf( "Error: Empty clause is attempted.\n" ); assert( !pClause->fRoot ); assert( p->nTrailSize == p->nRootSize ); // if any of the clause literals are already assumed // it means that the clause is redundant and can be skipped for ( i = 0; i < (int)pClause->nLits; i++ ) if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] ) { // Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) ); Vec_PtrPush( p->vAntClas, Vec_IntAlloc(0) ); return 1; } // add assumptions to the trail for ( i = 0; i < (int)pClause->nLits; i++ ) if ( !Intp_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) { assert( 0 ); // impossible return 0; } // propagate the assumptions pConflict = Intp_ManPropagate( p, p->nRootSize ); if ( pConflict == NULL ) { assert( 0 ); // cannot prove return 0; } // skip the clause if it is weaker or the same as the conflict clause if ( pClause->nLits >= pConflict->nLits ) { // check if every literal of conflict clause can be found in the given clause int j; for ( i = 0; i < (int)pConflict->nLits; i++ ) { for ( j = 0; j < (int)pClause->nLits; j++ ) if ( pConflict->pLits[i] == pClause->pLits[j] ) break; if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found break; } if ( i == (int)pConflict->nLits ) // all lits are found { // undo to the root level Intp_ManCancelUntil( p, p->nRootSize ); // Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) ); Vec_PtrPush( p->vAntClas, Vec_IntAlloc(0) ); return 1; } } // construct the proof Intp_ManProofTraceOne( p, pConflict, pClause ); // undo to the root level Intp_ManCancelUntil( p, p->nRootSize ); // add large clauses to the watched lists if ( pClause->nLits > 1 ) { Intp_ManWatchClause( p, pClause, pClause->pLits[0] ); Intp_ManWatchClause( p, pClause, pClause->pLits[1] ); return 1; } assert( pClause->nLits == 1 ); // if the clause proved is unit, add it and propagate if ( !Intp_ManEnqueue( p, pClause->pLits[0], pClause ) ) { assert( 0 ); // impossible return 0; } // propagate the assumption pConflict = Intp_ManPropagate( p, p->nRootSize ); if ( pConflict ) { // insert place-holders till the empty clause while ( Vec_PtrSize(p->vAntClas) < p->pCnf->pEmpty->Id - p->nAntStart ) Vec_PtrPush( p->vAntClas, Vec_IntAlloc(0) ); // construct the proof for the empty clause Intp_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty ); // if ( p->fVerbose ) // printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); return 0; } // update the root level p->nRootSize = p->nTrailSize; return 1; } /**Function************************************************************* Synopsis [Propagate the root clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Intp_ManProcessRoots( Intp_Man_t * p ) { Sto_Cls_t * pClause; int Counter; // make sure the root clauses are preceeding the learnt clauses Counter = 0; Sto_ManForEachClause( p->pCnf, pClause ) { assert( (int)pClause->fA == (Counter < (int)p->pCnf->nClausesA) ); assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots) ); Counter++; } assert( p->pCnf->nClauses == Counter ); // make sure the last clause if empty assert( p->pCnf->pTail->nLits == 0 ); // go through the root unit clauses p->nTrailSize = 0; Sto_ManForEachClauseRoot( p->pCnf, pClause ) { // create watcher lists for the root clauses if ( pClause->nLits > 1 ) { Intp_ManWatchClause( p, pClause, pClause->pLits[0] ); Intp_ManWatchClause( p, pClause, pClause->pLits[1] ); } // empty clause and large clauses if ( pClause->nLits != 1 ) continue; // unit clause assert( lit_check(pClause->pLits[0], p->pCnf->nVars) ); if ( !Intp_ManEnqueue( p, pClause->pLits[0], pClause ) ) { // detected root level conflict // printf( "Error in Intp_ManProcessRoots(): Detected a root-level conflict too early!\n" ); // assert( 0 ); // detected root level conflict Intp_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found root level conflict!\n" ); return 0; } } // propagate the root unit clauses pClause = Intp_ManPropagate( p, 0 ); if ( pClause ) { // detected root level conflict Intp_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); if ( p->fVerbose ) printf( "Found root level conflict!\n" ); return 0; } // set the root level p->nRootSize = p->nTrailSize; return 1; } /**Function************************************************************* Synopsis [Verifies the UNSAT core.] Description [Takes the interpolation manager, the CNF derived by the SAT solver, which includes the root clauses and the learned clauses. Returns the array of integers representing the number of root clauses that are in the UNSAT core.] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManUnsatCoreVerify( Sto_Man_t * pCnf, Vec_Int_t * vCore ) { int fVerbose = 0; int nConfMax = 1000000; sat_solver * pSat; Sto_Cls_t * pClause; Vec_Ptr_t * vClauses; int i, iClause, RetValue; abctime clk = Abc_Clock(); // collect the clauses vClauses = Vec_PtrAlloc( 1000 ); Sto_ManForEachClauseRoot( pCnf, pClause ) { assert( Vec_PtrSize(vClauses) == pClause->Id ); Vec_PtrPush( vClauses, pClause ); } // create new SAT solver pSat = sat_solver_new(); // sat_solver_setnvars( pSat, nSatVars ); Vec_IntForEachEntry( vCore, iClause, i ) { pClause = (Sto_Cls_t *)Vec_PtrEntry( vClauses, iClause ); if ( !sat_solver_addclause( pSat, pClause->pLits, pClause->pLits+pClause->nLits ) ) { printf( "The core verification problem is trivially UNSAT.\n" ); break; } } Vec_PtrFree( vClauses ); // 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 ); sat_solver_delete( pSat ); if ( fVerbose ) { if ( RetValue == l_Undef ) printf( "Conflict limit is reached. " ); else if ( RetValue == l_True ) printf( "UNSAT core verification FAILED. " ); else printf( "UNSAT core verification succeeded. " ); ABC_PRT( "Time", Abc_Clock() - clk ); } else { if ( RetValue == l_True ) printf( "UNSAT core verification FAILED. \n" ); } } /**Function************************************************************* Synopsis [Recursively computes the UNSAT core.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManUnsatCore_rec( Vec_Ptr_t * vAntClas, int iThis, Vec_Int_t * vCore, int nRoots, Vec_Str_t * vVisited, int fLearned ) { // int i, iStop, iStart; Vec_Int_t * vAnt; int i, Entry; // skip visited clauses if ( Vec_StrEntry( vVisited, iThis ) ) return; Vec_StrWriteEntry( vVisited, iThis, 1 ); // add a root clause to the core if ( iThis < nRoots ) { if ( !fLearned ) Vec_IntPush( vCore, iThis ); return; } // iterate through the clauses // iStart = Vec_IntEntry( vBreaks, iThis ); // iStop = Vec_IntEntry( vBreaks, iThis+1 ); // assert( iStop != -1 ); // for ( i = iStart; i < iStop; i++ ) vAnt = (Vec_Int_t *)Vec_PtrEntry( vAntClas, iThis - nRoots ); Vec_IntForEachEntry( vAnt, Entry, i ) // Intp_ManUnsatCore_rec( vAntClas, Vec_IntEntry(vAnties, i), vCore, nRoots, vVisited ); Intp_ManUnsatCore_rec( vAntClas, Entry, vCore, nRoots, vVisited, fLearned ); // collect learned clause if ( fLearned ) Vec_IntPush( vCore, iThis ); } /**Function************************************************************* Synopsis [Computes UNSAT core of the satisfiablity problem.] Description [Takes the interpolation manager, the CNF derived by the SAT solver, which includes the root clauses and the learned clauses. Returns the array of integers representing the number of root clauses that are in the UNSAT core.] SideEffects [] SeeAlso [] ***********************************************************************/ void * Intp_ManUnsatCore( Intp_Man_t * p, Sto_Man_t * pCnf, int fLearned, int fVerbose ) { Vec_Int_t * vCore; Vec_Str_t * vVisited; Sto_Cls_t * pClause; int RetValue = 1; abctime clkTotal = Abc_Clock(); // check that the CNF makes sense assert( pCnf->nVars > 0 && pCnf->nClauses > 0 ); p->pCnf = pCnf; p->fVerbose = fVerbose; // adjust the manager Intp_ManResize( p ); // construct proof for each clause // start the proof if ( p->fProofWrite ) { p->pFile = fopen( "proof.cnf_", "w" ); p->Counter = 0; } // write the root clauses // Vec_IntClear( p->vAnties ); // Vec_IntFill( p->vBreaks, p->pCnf->nRoots, 0 ); Vec_PtrClear( p->vAntClas ); p->nAntStart = p->pCnf->nRoots; Sto_ManForEachClauseRoot( p->pCnf, pClause ) Intp_ManProofWriteOne( p, pClause ); // propagate root level assignments if ( Intp_ManProcessRoots( p ) ) { // if there is no conflict, consider learned clauses Sto_ManForEachClause( p->pCnf, pClause ) { if ( pClause->fRoot ) continue; if ( !Intp_ManProofRecordOne( p, pClause ) ) { RetValue = 0; break; } } } // add the last breaker // assert( p->pCnf->pEmpty->Id == Vec_IntSize(p->vBreaks) - 1 ); // Vec_IntPush( p->vBreaks, Vec_IntSize(p->vAnties) ); assert( p->pCnf->pEmpty->Id - p->nAntStart == Vec_PtrSize(p->vAntClas) - 1 ); Vec_PtrPush( p->vAntClas, Vec_IntAlloc(0) ); // stop the proof if ( p->fProofWrite ) { fclose( p->pFile ); // Sat_ProofChecker( "proof.cnf_" ); p->pFile = NULL; } if ( fVerbose ) { // ABC_PRT( "Core", Abc_Clock() - clkTotal ); printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f MB\n", p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter, 1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), 1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) ); p->timeTotal += Abc_Clock() - clkTotal; } // derive the UNSAT core vCore = Vec_IntAlloc( 1000 ); vVisited = Vec_StrStart( p->pCnf->pEmpty->Id+1 ); Intp_ManUnsatCore_rec( p->vAntClas, p->pCnf->pEmpty->Id, vCore, p->pCnf->nRoots, vVisited, fLearned ); Vec_StrFree( vVisited ); if ( fVerbose ) printf( "Root clauses = %d. Learned clauses = %d. UNSAT core size = %d.\n", p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, Vec_IntSize(vCore) ); // Intp_ManUnsatCoreVerify( p->pCnf, vCore ); return vCore; } /**Function************************************************************* Synopsis [Prints learned clauses in terms of original problem varibles.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Intp_ManUnsatCorePrintForBmc( FILE * pFile, Sto_Man_t * pCnf, void * vCore0, void * vVarMap0 ) { Vec_Int_t * vCore = (Vec_Int_t *)vCore0; Vec_Int_t * vVarMap = (Vec_Int_t *)vVarMap0; Vec_Ptr_t * vClaMap; Sto_Cls_t * pClause; int v, i, iClause, fCompl, iObj, iFrame; // create map of clause vClaMap = Vec_PtrAlloc( pCnf->nClauses ); Sto_ManForEachClause( pCnf, pClause ) Vec_PtrPush( vClaMap, pClause ); // print clauses fprintf( pFile, "UNSAT contains %d learned clauses:\n", Vec_IntSize(vCore) ); Vec_IntForEachEntry( vCore, iClause, i ) { pClause = (Sto_Cls_t *)Vec_PtrEntry(vClaMap, iClause); fprintf( pFile, "%6d : %6d : ", i, iClause - pCnf->nRoots ); for ( v = 0; v < (int)pClause->nLits; v++ ) { fCompl = Abc_LitIsCompl(pClause->pLits[v]); iObj = Vec_IntEntry(vVarMap, 2*Abc_Lit2Var(pClause->pLits[v])); iFrame = Vec_IntEntry(vVarMap, 2*Abc_Lit2Var(pClause->pLits[v])+1); fprintf( pFile, "%s%d(%d) ", fCompl ? "!":"", iObj, iFrame ); } if ( pClause->nLits == 0 ) fprintf( pFile, "Empty" ); fprintf( pFile, "\n" ); } Vec_PtrFree( vClaMap ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satMem.c000066400000000000000000000404151300674244400231520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satMem.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT solver.] Synopsis [Memory management.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2004.] Revision [$Id: satMem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "satMem.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Sat_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 Sat_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 Sat_MmStep_t_ { int nMems; // the number of fixed memory managers employed Sat_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc int nMapSize; // the size of the memory array Sat_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 [] ***********************************************************************/ Sat_MmFixed_t * Sat_MmFixedStart( int nEntrySize ) { Sat_MmFixed_t * p; p = ABC_ALLOC( Sat_MmFixed_t, 1 ); memset( p, 0, sizeof(Sat_MmFixed_t) ); p->nEntrySize = nEntrySize; p->nEntriesAlloc = 0; p->nEntriesUsed = 0; p->pEntriesFree = NULL; if ( nEntrySize * (1 << 10) < (1<<16) ) p->nChunkSize = (1 << 10); else p->nChunkSize = (1<<16) / nEntrySize; 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 Sat_MmFixedStop( Sat_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 * Sat_MmFixedEntryFetch( Sat_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 Sat_MmFixedEntryRecycle( Sat_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 Sat_MmFixedRestart( Sat_MmFixed_t * p ) { int i; char * pTemp; if ( p->nChunks == 0 ) return; assert( p->nChunks > 0 ); // 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 Sat_MmFixedReadMemUsage( Sat_MmFixed_t * p ) { return p->nMemoryAlloc; } /**Function************************************************************* Synopsis [Allocates entries of flexible size.] Description [Can only work with entry size at least 4 byte long.] SideEffects [] SeeAlso [] ***********************************************************************/ Sat_MmFlex_t * Sat_MmFlexStart() { Sat_MmFlex_t * p; p = ABC_ALLOC( Sat_MmFlex_t, 1 ); memset( p, 0, sizeof(Sat_MmFlex_t) ); p->nEntriesUsed = 0; p->pCurrent = NULL; p->pEnd = NULL; p->nChunkSize = (1 << 16); 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 Sat_MmFlexStop( Sat_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 * Sat_MmFlexEntryFetch( Sat_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 [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sat_MmFlexReadMemUsage( Sat_MmFlex_t * p ) { return p->nMemoryAlloc; } /**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 [] ***********************************************************************/ Sat_MmStep_t * Sat_MmStepStart( int nSteps ) { Sat_MmStep_t * p; int i, k; p = ABC_ALLOC( Sat_MmStep_t, 1 ); p->nMems = nSteps; // start the fixed memory managers p->pMems = ABC_ALLOC( Sat_MmFixed_t *, p->nMems ); for ( i = 0; i < p->nMems; i++ ) p->pMems[i] = Sat_MmFixedStart( (8<nMapSize = (4<nMems); p->pMap = ABC_ALLOC( Sat_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 Sat_MmStepStop( Sat_MmStep_t * p, int fVerbose ) { int i; if ( p->nChunksAlloc ) { for ( i = 0; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); ABC_FREE( p->pChunks ); } for ( i = 0; i < p->nMems; i++ ) Sat_MmFixedStop( p->pMems[i], fVerbose ); ABC_FREE( p->pMems ); ABC_FREE( p->pMap ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stops the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sat_MmStepRestart( Sat_MmStep_t * p ) { int i; if ( p->nChunksAlloc ) { for ( i = 0; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); p->nChunks = 0; } for ( i = 0; i < p->nMems; i++ ) Sat_MmFixedRestart( p->pMems[i] ); } /**Function************************************************************* Synopsis [Creates the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Sat_MmStepEntryFetch( Sat_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 Sat_MmFixedEntryFetch( p->pMap[nBytes] ); } /**Function************************************************************* Synopsis [Recycles the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sat_MmStepEntryRecycle( Sat_MmStep_t * p, char * pEntry, int nBytes ) { if ( nBytes == 0 ) return; if ( nBytes > p->nMapSize ) { // ABC_FREE( pEntry ); return; } Sat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sat_MmStepReadMemUsage( Sat_MmStep_t * p ) { int i, nMemTotal = 0; for ( i = 0; i < p->nMems; i++ ) nMemTotal += p->pMems[i]->nMemoryAlloc; return nMemTotal; } ABC_NAMESPACE_IMPL_END berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satMem.h000066400000000000000000000070561300674244400231630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satMem.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT solver.] Synopsis [Memory management.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - January 1, 2004.] Revision [$Id: satMem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__sat__bsat__satMem_h #define ABC__sat__bsat__satMem_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/util/abc_global.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Sat_MmFixed_t_ Sat_MmFixed_t; typedef struct Sat_MmFlex_t_ Sat_MmFlex_t; typedef struct Sat_MmStep_t_ Sat_MmStep_t; //////////////////////////////////////////////////////////////////////// /// GLOBAL VARIABLES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // fixed-size-block memory manager extern Sat_MmFixed_t * Sat_MmFixedStart( int nEntrySize ); extern void Sat_MmFixedStop( Sat_MmFixed_t * p, int fVerbose ); extern char * Sat_MmFixedEntryFetch( Sat_MmFixed_t * p ); extern void Sat_MmFixedEntryRecycle( Sat_MmFixed_t * p, char * pEntry ); extern void Sat_MmFixedRestart( Sat_MmFixed_t * p ); extern int Sat_MmFixedReadMemUsage( Sat_MmFixed_t * p ); // flexible-size-block memory manager extern Sat_MmFlex_t * Sat_MmFlexStart(); extern void Sat_MmFlexStop( Sat_MmFlex_t * p, int fVerbose ); extern char * Sat_MmFlexEntryFetch( Sat_MmFlex_t * p, int nBytes ); extern int Sat_MmFlexReadMemUsage( Sat_MmFlex_t * p ); // hierarchical memory manager extern Sat_MmStep_t * Sat_MmStepStart( int nSteps ); extern void Sat_MmStepStop( Sat_MmStep_t * p, int fVerbose ); extern void Sat_MmStepRestart( Sat_MmStep_t * p ); extern char * Sat_MmStepEntryFetch( Sat_MmStep_t * p, int nBytes ); extern void Sat_MmStepEntryRecycle( Sat_MmStep_t * p, char * pEntry, int nBytes ); extern int Sat_MmStepReadMemUsage( Sat_MmStep_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// berkeley-abc-1.01+20161002hgeb6eca6+dfsg/src/sat/bsat/satProof.c000066400000000000000000000764561300674244400235370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [satProof.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT solver.] Synopsis [Proof manipulation procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: satProof.c,v 1.4 2005/09/16 22:55:03 casem Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "misc/vec/vecSet.h" #include "aig/aig/aig.h" #include "satTruth.h" ABC_NAMESPACE_IMPL_START /* Proof is represented as a vector of records. A resolution record is represented by a handle (an offset in this vector). A resolution record entry is